Index: azure_iot_hub_riscv/trunk/.gitignore
===================================================================
--- azure_iot_hub_riscv/trunk/.gitignore	(revision 453)
+++ azure_iot_hub_riscv/trunk/.gitignore	(revision 453)
@@ -0,0 +1,52 @@
+# Prerequisites
+*.d
+
+# Object files
+*.o
+*.ko
+*.obj
+*.elf
+
+# Linker output
+*.ilk
+*.map
+*.exp
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Libraries
+*.lib
+*.a
+*.la
+*.lo
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+*.i*86
+*.x86_64
+*.hex
+
+# Debug files
+*.dSYM/
+*.su
+*.idb
+*.pdb
+
+# Kernel Module Compile Results
+*.mod*
+*.cmd
+.tmp_versions/
+modules.order
+Module.symvers
+Mkfile.old
+dkms.conf
Index: azure_iot_hub_riscv/trunk/Makefile
===================================================================
--- azure_iot_hub_riscv/trunk/Makefile	(revision 453)
+++ azure_iot_hub_riscv/trunk/Makefile	(revision 453)
@@ -0,0 +1,50 @@
+
+MAKE = make
+
+LIBKERNEL = asp_baseplatform/OBJ/K210_GCC/libkernel/libkernel.a
+LIBWOLFSSL = wolfssl-4.4.0/Debug/libwolfssl.a
+LIBZLIB = zlib-1.2.11/Debug/libzlib.a
+LIBAZURE_IOT_SDK = azure_iot_sdk/Debug/libazure_iot_sdk.a
+ASP_ELF = app_iothub_client/Debug/asp.elf
+
+$(LIBKERNEL):
+	$(MAKE) -j 1 -C asp_baseplatform/OBJ/K210_GCC/DEMO all
+
+$(LIBWOLFSSL):
+	$(MAKE) -j -C wolfssl-4.4.0 all
+
+$(LIBZLIB):
+	$(MAKE) -j -C zlib-1.2.11 all
+
+$(LIBAZURE_IOT_SDK):
+	$(MAKE) -j -C azure_iot_sdk all
+
+$(ASP_ELF): $(LIBKERNEL) $(LIBWOLFSSL) $(LIBZLIB) $(LIBAZURE_IOT_SDK)
+	$(MAKE) -j 1 -C app_iothub_client/Debug all
+
+.PHONY: refresh
+refresh: 
+	rm -f $(LIBKERNEL)
+	rm -f $(LIBWOLFSSL)
+	rm -f $(LIBZLIB)
+	rm -f $(LIBAZURE_IOT_SDK)
+	rm -f $(ASP_ELF)
+
+.PHONY: all
+all: refresh $(ASP_ELF)
+
+.PHONY: clean
+clean:
+	$(MAKE) -j -C asp_baseplatform/OBJ/K210_GCC/DEMO clean
+	$(MAKE) -j -C wolfssl-4.4.0 clean
+	$(MAKE) -j -C zlib-1.2.11 clean
+	$(MAKE) -j -C azure_iot_sdk clean
+	$(MAKE) -j -C app_iothub_client/Debug clean
+
+.PHONY: realclean
+realclean:
+	$(MAKE) -j -C asp_baseplatform/OBJ/K210_GCC/DEMO realclean
+	$(MAKE) -j -C wolfssl-4.4.0 clean
+	$(MAKE) -j -C zlib-1.2.11 clean
+	$(MAKE) -j -C azure_iot_sdk clean
+	$(MAKE) -j -C app_iothub_client/Debug realclean
Index: azure_iot_hub_riscv/trunk/app_iothub_client/.vscode/c_cpp_properties.json
===================================================================
--- azure_iot_hub_riscv/trunk/app_iothub_client/.vscode/c_cpp_properties.json	(revision 453)
+++ azure_iot_hub_riscv/trunk/app_iothub_client/.vscode/c_cpp_properties.json	(revision 453)
@@ -0,0 +1,44 @@
+{
+    "configurations": [
+        {
+            "name": "Sipeed Maix bit",
+            "includePath": [
+                "${workspaceFolder}/../asp_baseplatform",
+                "${workspaceFolder}/../asp_baseplatform/arch",
+                "${workspaceFolder}/../asp_baseplatform/arch/riscv_gcc",
+                "${workspaceFolder}/../asp_baseplatform/arch/gcc",
+                "${workspaceFolder}/../asp_baseplatform/files",
+                "${workspaceFolder}/../asp_baseplatform/files/ff",
+                "${workspaceFolder}/../asp_baseplatform/include",
+                "${workspaceFolder}/../asp_baseplatform/target/k210_gcc",
+                "${workspaceFolder}/../asp_baseplatform/pdic/k210",
+                "${workspaceFolder}/../asp_baseplatform/monitor",
+                "${workspaceFolder}/../wolfssl-4.4.0",
+                "${workspaceFolder}/../wolfssl-4.4.0/wolfssl",
+                "${workspaceFolder}/../wolfssl-4.4.0/wolfssl/wolfcrypt",
+                "${workspaceFolder}/../zlib-1.2.11/src",
+                "${workspaceFolder}/../azure_iot_sdk/c-utility/adapters",
+                "${workspaceFolder}/../azure_iot_sdk/c-utility/inc",
+                "${workspaceFolder}/../azure_iot_sdk/c-utility/pal/toppers",
+                "${workspaceFolder}/../azure_iot_sdk/certs",
+                "${workspaceFolder}/../azure_iot_sdk/deps",
+                "${workspaceFolder}/../azure_iot_sdk/deps/parson",
+                "${workspaceFolder}/../azure_iot_sdk/deps/azure-macro-utils-c/inc",
+                "${workspaceFolder}/../azure_iot_sdk/deps/umock-c/inc",
+                "${workspaceFolder}/../azure_iot_sdk/serializer/inc",
+                "${workspaceFolder}/../azure_iot_sdk/iothub_client/inc",
+                "${workspaceFolder}/../azure_iot_sdk/provisioning_client/inc",
+                "${workspaceFolder}/src",
+                "${workspaceFolder}/Debug"
+            ],
+            "defines": [
+            ],
+            "windowsSdkVersion": "10.0.17763.0",
+            "compilerPath": "C:\\xpack-riscv-none-embed-gcc-8.3.0-1.2\\bin\\riscv-none-embed-gcc.exe",
+            "cStandard": "c11",
+            "cppStandard": "c++17",
+            "intelliSenseMode": "gcc-x64"
+        }
+    ],
+    "version": 4
+}
Index: azure_iot_hub_riscv/trunk/app_iothub_client/.vscode/settings.json
===================================================================
--- azure_iot_hub_riscv/trunk/app_iothub_client/.vscode/settings.json	(revision 453)
+++ azure_iot_hub_riscv/trunk/app_iothub_client/.vscode/settings.json	(revision 453)
@@ -0,0 +1,17 @@
+// Place your settings in this file to overwrite default and user settings.
+{
+    "terminal.integrated.setLocaleVariables": true,
+    "terminal.integrated.shell.windows": "C:\\msys64\\usr\\bin\\bash.exe",
+    "terminal.integrated.shellArgs.windows": [
+        "--login",
+        "-i"
+    ],
+    "terminal.integrated.env.windows": {
+        "PATH": "C:\\xpack-riscv-none-embed-gcc-8.3.0-1.2\\bin",
+        "CHERE_INVOKING": "1",
+        "MSYS2_PATH_TYPE": "inherit",
+        "MSYSTEM": "MINGW64"
+    },
+    "C_Cpp.intelliSenseEngine": "Tag Parser",
+    "C_Cpp.default.intelliSenseMode": "gcc-x64"
+}
Index: azure_iot_hub_riscv/trunk/app_iothub_client/.vscode/tasks.json
===================================================================
--- azure_iot_hub_riscv/trunk/app_iothub_client/.vscode/tasks.json	(revision 453)
+++ azure_iot_hub_riscv/trunk/app_iothub_client/.vscode/tasks.json	(revision 453)
@@ -0,0 +1,161 @@
+{
+    "version": "2.0.0",
+    "name": "make",
+    "type": "shell",
+    "problemMatcher": {
+        "owner": "cpp",
+        "fileLocation": [
+            "relative",
+            "${workspaceFolder}/Debug"
+        ],
+        "pattern": {
+            "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error|fatal error):\\s+(.*)$",
+            "file": 1,
+            "line": 2,
+            "column": 3,
+            "severity": 4,
+            "message": 5
+        }
+    },
+    "tasks": [
+        {
+            "label": "build all",
+            "args": [
+                "-j",
+                "1",
+                "-C",
+                "..",
+                "all"
+            ],
+            "linux": {
+                "command": "make"
+            },
+            "osx": {
+                "command": "make"
+            },
+            "windows": {
+                "command": "make.exe"
+            },
+            "group": {
+                "kind": "build",
+                "isDefault": true
+            }
+        },
+        {
+            "label": "clean all",
+            "args": [
+                "-C",
+                "..",
+                "clean"
+            ],
+            "linux": {
+                "command": "make"
+            },
+            "osx": {
+                "command": "make"
+            },
+            "windows": {
+                "command": "make.exe"
+            },
+            "group": "build"
+        },
+        {
+            "label": "realclean all",
+            "args": [
+                "-C",
+                "..",
+                "realclean"
+            ],
+            "linux": {
+                "command": "make"
+            },
+            "osx": {
+                "command": "make"
+            },
+            "windows": {
+                "command": "make.exe"
+            },
+            "group": "build"
+        },
+        {
+            "label": "build app_iothub_client",
+            "args": [
+                "-j",
+                "1",
+                "all"
+            ],
+            "linux": {
+                "command": "make"
+            },
+            "osx": {
+                "command": "make"
+            },
+            "windows": {
+                "command": "make.exe"
+            },
+            "group": "build"
+        },
+        {
+            "label": "cfg app_iothub_client",
+            "args": [
+                "-j",
+                "1",
+                "kernel_cfg.h"
+            ],
+            "linux": {
+                "command": "make"
+            },
+            "osx": {
+                "command": "make"
+            },
+            "windows": {
+                "command": "make.exe"
+            },
+            "group": "build"
+        },
+        {
+            "label": "clean app_iothub_client",
+            "args": [
+                "clean"
+            ],
+            "linux": {
+                "command": "make"
+            },
+            "osx": {
+                "command": "make"
+            },
+            "windows": {
+                "command": "make.exe"
+            },
+            "group": "build"
+        },
+        {
+            "label": "realclean app_iothub_client",
+            "args": [
+                "realclean"
+            ],
+            "linux": {
+                "command": "make"
+            },
+            "osx": {
+                "command": "make"
+            },
+            "windows": {
+                "command": "make.exe"
+            },
+            "group": "build"
+        },
+        {
+            "label": "write app_iothub_client",
+            "command": "/C/Python38/python.exe",
+                "args": [
+                "../tools/kflash/kflash.py",
+                "-p",
+                "COM12",
+                "-b",
+                "1500000",
+                "Debug/app_iothub_client.bin"
+            ]
+        }
+    ]
+}
Index: azure_iot_hub_riscv/trunk/app_iothub_client/Debug/Makefile
===================================================================
--- azure_iot_hub_riscv/trunk/app_iothub_client/Debug/Makefile	(revision 453)
+++ azure_iot_hub_riscv/trunk/app_iothub_client/Debug/Makefile	(revision 453)
@@ -0,0 +1,635 @@
+#
+#  TOPPERS/ASP Kernel
+#      Toyohashi Open Platform for Embedded Real-Time Systems/
+#      Advanced Standard Profile Kernel
+# 
+#  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                              Toyohashi Univ. of Technology, JAPAN
+#  Copyright (C) 2006-2019 by Embedded and Real-Time Systems Laboratory
+#              Graduate School of Information Science, Nagoya Univ., JAPAN
+# 
+#  ä¸è¨èä½æ¨©è
+ã¯ï¼ä»¥ä¸ã®(1)ï½(4)ã®æ¡ä»¶ãæºããå ´åã«éãï¼æ¬ã½ããã¦ã§
+#  ã¢ï¼æ¬ã½ããã¦ã§ã¢ãæ¹å¤ãããã®ãå«ãï¼ä»¥ä¸åãï¼ãä½¿ç¨ã»è¤è£½ã»æ¹
+#  å¤ã»åé
+å¸ï¼ä»¥ä¸ï¼å©ç¨ã¨å¼ã¶ï¼ãããã¨ãç¡åã§è¨±è«¾ããï¼
+#   (1) æ¬ã½ããã¦ã§ã¢ãã½ã¼ã¹ã³ã¼ãã®å½¢ã§å©ç¨ããå ´åã«ã¯ï¼ä¸è¨ã®èä½
+#       æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãï¼ãã®ã¾ã¾ã®å½¢ã§ã½ã¼
+#       ã¹ã³ã¼ãä¸­ã«å«ã¾ãã¦ãããã¨ï¼
+#   (2) æ¬ã½ããã¦ã§ã¢ãï¼ã©ã¤ãã©ãªå½¢å¼ãªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#       ç¨ã§ããå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨
+#       è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®èä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨
+#       ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#   (3) æ¬ã½ããã¦ã§ã¢ãï¼æ©å¨ã«çµã¿è¾¼ããªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããªãå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼æ¬¡ã®ããããã®æ¡ä»¶ãæºããã
+#      ã¨ï¼
+#     (a) åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®è
+#         ä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#     (b) åé
+å¸ã®å½¢æ
+ãï¼å¥ã«å®ããæ¹æ³ã«ãã£ã¦ï¼TOPPERSãã­ã¸ã§ã¯ãã«
+#        å ±åãããã¨ï¼
+#   (4) æ¬ã½ããã¦ã§ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæ
+#      å®³ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ããå
+è²¬ãããã¨ï¼
+#      ã¾ãï¼æ¬ã½ããã¦ã§ã¢ã®ã¦ã¼ã¶ã¾ãã¯ã¨ã³ãã¦ã¼ã¶ããã®ãããªãç
+#      ç±ã«åºã¥ãè«æ±ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ãã
+#      å
+è²¬ãããã¨ï¼
+# 
+#  æ¬ã½ããã¦ã§ã¢ã¯ï¼ç¡ä¿è¨¼ã§æä¾ããã¦ãããã®ã§ããï¼ä¸è¨èä½æ¨©è
+ã
+#  ãã³TOPPERSãã­ã¸ã§ã¯ãã¯ï¼æ¬ã½ããã¦ã§ã¢ã«é¢ãã¦ï¼ç¹å®ã®ä½¿ç¨ç®ç
+#  ã«å¯¾ããé©åæ§ãå«ãã¦ï¼ãããªãä¿è¨¼ãè¡ããªãï¼ã¾ãï¼æ¬ã½ããã¦ã§
+#  ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæå®³ã«é¢ãã¦ãï¼ã
+#  ã®è²¬ä»»ãè² ããªãï¼
+# 
+#  $Id$
+# 
+
+#
+#  ã¿ã¼ã²ããã®æå®ï¼Makefile.targetã§ä¸æ¸ããããã®ãé²ãããï¼
+#
+all:
+
+#
+#  ã¿ã¼ã²ããç¥ç§°ã®å®ç¾©
+#
+TARGET = k210_gcc
+
+#
+#  ãã­ã°ã©ãã³ã°è¨èªã®å®ç¾©
+#
+SRCLANG = c
+ifeq ($(SRCLANG),c)
+	LIBS = -lc -lm
+endif
+ifeq ($(SRCLANG),c++)
+	USE_CXX = true
+	CXXLIBS = -lstdc++ -lc -lm
+	CXXRTS = cxxrt.o newlibrt.o
+endif
+
+#
+#  ã½ã¼ã¹ãã¡ã¤ã«ã®ãã£ã¬ã¯ããªã®å®ç¾©
+#
+SRCDIR = ../../asp_baseplatform
+
+#
+#  ãªãã¸ã§ã¯ããã¡ã¤ã«åã®æ¡å¼µå­ã®è¨­å®
+#
+OBJEXT = elf
+
+#
+#  å®è¡ç°å¢ã®å®ç¾©ï¼ã¿ã¼ã²ããä¾å­ã«ä¸æ¸ããããå ´åãããï¼
+#
+DBGENV := ROM
+
+#
+#  ã«ã¼ãã«ã©ã¤ãã©ãªï¼libkernel.aï¼ã®ãã£ã¬ã¯ããªå
+#  ï¼ã«ã¼ãã«ã©ã¤ãã©ãªãmakeå¯¾è±¡ã«ããæã¯ï¼ç©ºã«å®ç¾©ããï¼
+#
+KERNEL_LIB = 
+
+#
+#  ã«ã¼ãã«ãé¢æ°åä½ã§ã³ã³ãã¤ã«ãããã©ããã®å®ç¾©
+#
+KERNEL_FUNCOBJS = 
+
+#
+#  ãã¬ã¼ã¹ã­ã°ãåå¾ãããã©ããã®å®ç¾©
+#
+ENABLE_TRACE = 
+
+#
+#  éçºãã¼ã«ï¼ã³ã³ãã¤ã©ç­ï¼ã®ãã£ã¬ã¯ããªã®å®ç¾©
+#
+DEVTOOLDIR = 
+
+#
+#  ã¦ã¼ãã£ãªãã£ãã­ã°ã©ã ã®åç§°
+#
+PERL = /usr/bin/perl
+CFG = $(SRCDIR)/cfg/cfg/cfg
+
+#
+#  ãªãã¸ã§ã¯ããã¡ã¤ã«åã®å®ç¾©
+#
+OBJNAME = app_iothub_client
+ifdef OBJEXT
+	OBJFILE = $(OBJNAME).$(OBJEXT)
+	CFG1_OUT = cfg1_out.$(OBJEXT)
+else
+	OBJFILE = $(OBJNAME)
+	CFG1_OUT = cfg1_out
+endif
+
+#
+#  ä¸­éãªãã¸ã§ã¯ããã¡ã¤ã«ã¨ä¾å­é¢ä¿ãã¡ã¤ã«ãç½®ããã£ã¬ã¯ããªã®å®ç¾©
+#
+OBJDIR = obj
+DEPDIR = obj
+
+#
+#  ã¿ã¼ã²ããä¾å­é¨ã®ãã£ã¬ã¯ããªã®å®ç¾©
+#
+TARGETDIR = $(SRCDIR)/target/$(TARGET)
+
+#
+#  ã¿ã¼ã²ããä¾å­ã®å®ç¾©ã®ã¤ã³ã¯ã«ã¼ã
+#
+include $(TARGETDIR)/Makefile.target
+
+#
+#  å
+±éã³ã³ãã¤ã«ãªãã·ã§ã³ã®å®ç¾©
+#
+COPTS := $(COPTS) -g -std=gnu11 -ffunction-sections -fdata-sections
+ifndef OMIT_WARNING_ALL
+  COPTS := $(COPTS) -Wall
+endif
+ifndef OMIT_OPTIMIZATION
+  COPTS := $(COPTS) -O2
+endif
+COPTS := $(COPTS) -Wno-unused-variable -Wno-unused-function
+#CDEFS := $(CDEFS) -DLWIP_DEBUG
+CDEFS := $(CDEFS) -DMONITOR_PORTID=1 -DUSE_CUPCOMMAND -DNOT_USE_TBP_MKTIME_GMTIME -DSPI_WAIT_TIME=100 -DSDEV_SENSE_ONETIME -DMAX_FONT_IMAGE=24
+CDEFS := $(CDEFS) -DUSE_WOLFSSL=1 -DHSM_TYPE_SYMM_KEY -DUSE_PROV_MODULE -Dget_time=azure_get_time
+INCLUDES := -I. -I$(SRCDIR)/include -I$(SRCDIR)/arch -I$(SRCDIR) $(INCLUDES)
+LDFLAGS := $(LDFLAGS) -Wl,--wrap=exit
+CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) 
+LIBS := $(LIBS) $(CXXLIBS) \
+	$(SRCDIR)/../zlib-1.2.11/Debug/libzlib.a \
+	$(SRCDIR)/../wolfssl-4.4.0/Debug/libwolfssl.a \
+	$(SRCDIR)/../azure_iot_sdk/Debug/libazure_iot_sdk.a
+CFLAGS = $(COPTS) $(CDEFS) $(INCLUDES)
+
+#
+#  ã¢ããªã±ã¼ã·ã§ã³ãã­ã°ã©ã ã«é¢ããå®ç¾©
+#
+APPLNAME = app_iothub_client
+APPLDIR := $(APPLDIR) ../src ../kendryte
+APPL_CFG = main.cfg
+
+APPL_DIR := $(APPLDIR) $(SRCDIR)/library
+APPL_ASMOBJS :=
+ifdef USE_CXX
+	APPL_CXXOBJS := $(APPL_CXXOBJS) main.o
+	APPL_COBJS := $(APPL_COBJS) client.o code.o envcmd.o command.o esp_at_socket.o kpu_main.o region_layer.o kpu.o
+else
+	APPL_COBJS := $(APPL_COBJS) main.o client.o code.o envcmd.o command.o esp_at_socket.o kpu_main.o region_layer.o kpu.o
+endif
+APPL_COBJS := $(APPL_COBJS) log_output.o vasyslog.o t_perror.o strerror.o stub.o yolo.o
+APPL_CFLAGS := $(APPL_CFLAGS) -D___src_yolo_kmodel=model_data -D___src_yolo_kmodel_len=model_size
+APPL_LIBS =
+ifdef APPLDIR
+	INCLUDES := $(INCLUDES) $(foreach dir,$(APPLDIR),-I$(dir))
+endif
+INCLUDES += -I$(SRCDIR)/../azure_iot_sdk/certs
+INCLUDES += -I$(SRCDIR)/../azure_iot_sdk/c-utility/inc
+INCLUDES += -I$(SRCDIR)/../azure_iot_sdk/c-utility/pal/toppers
+INCLUDES += -I$(SRCDIR)/../azure_iot_sdk/iothub_client/inc
+INCLUDES += -I$(SRCDIR)/../azure_iot_sdk/iothub_client/inc/internal
+INCLUDES += -I$(SRCDIR)/../azure_iot_sdk/provisioning_client/adapters
+INCLUDES += -I$(SRCDIR)/../azure_iot_sdk/provisioning_client/inc
+INCLUDES += -I$(SRCDIR)/../azure_iot_sdk/provisioning_client/inc/azure_prov_client/internal
+INCLUDES += -I$(SRCDIR)/../azure_iot_sdk/deps/parson
+INCLUDES += -I$(SRCDIR)/../azure_iot_sdk/deps/azure-macro-utils-c/inc
+INCLUDES += -I$(SRCDIR)/../azure_iot_sdk/deps/umock-c/inc
+INCLUDES += -I$(SRCDIR)/../azure_iot_sdk/serializer/inc
+INCLUDES += -I$(SRCDIR)/../azure_iot_sdk/uhttp/inc
+INCLUDES += -I$(SRCDIR)/../azure_iot_sdk/umqtt/inc
+INCLUDES += -I$(SRCDIR)/../wolfssl-4.4.0/wolfssl
+INCLUDES += -I$(SRCDIR)/../wolfssl-4.4.0/wolfssl/wolfcrypt
+INCLUDES += -I$(SRCDIR)/../wolfssl-4.4.0
+INCLUDES += -I$(SRCDIR)/../zlib-1.2.11/src
+
+#
+#  ããã«ã¦ã§ã¢ã® Makefile ã®ã¤ã³ã¯ã«ã¼ã
+#
+include $(SRCDIR)/monitor/Makefile.config
+include $(SRCDIR)/files/ff/Makefile.config
+include $(SRCDIR)/files/Makefile.config
+include $(SRCDIR)/ui/snfont_disp/Makefile.config
+
+#
+#  GDIC Makefile ã®ã¤ã³ã¯ã«ã¼ã
+#
+include $(SRCDIR)/gdic/sipeed_st7789/Makefile.config
+include $(SRCDIR)/gdic/sipeed_ov2640/Makefile.config
+include $(SRCDIR)/gdic/spi_driver/Makefile.config
+
+#
+#  ã·ã¹ãã ãµã¼ãã¹ã«é¢ããå®ç¾©
+#
+SYSSVC_DIR := $(SYSSVC_DIR) $(SRCDIR)/syssvc $(SRCDIR)/library $(SRCDIR)/pdic/k210
+SYSSVC_ASMOBJS := $(SYSSVC_ASMOBJS)
+SYSSVC_COBJS := $(SYSSVC_COBJS) banner.o syslog.o serial.o logtask.o \
+				 device.o spi.o spi_reg.o dvp.o clock.o malloc.o riscv64.o \
+				 $(CXXRTS)
+SYSSVC_CFLAGS := $(SYSSVC_CFLAGS)
+SYSSVC_LIBS := $(SYSSVC_LIBS)
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/pdic/k210
+
+#
+#  ãã¬ã¼ã¹ã­ã°è¨é²ã®ãµã³ãã«ã³ã¼ãã«é¢ããå®ç¾©
+#
+ifdef ENABLE_TRACE
+	COPTS := $(COPTS) -DTOPPERS_ENABLE_TRACE
+	SYSSVC_DIR := $(SYSSVC_DIR) $(SRCDIR)/arch/tracelog
+endif
+
+#
+#  ã¿ã¼ã²ãããã¡ã¤ã«
+#
+.PHONY: all
+#all: $(DEPDIR) check
+all: $(DEPDIR) check $(OBJNAME).bin
+#all: $(DEPDIR) check $(OBJNAME).srec
+
+##### ä»¥ä¸ã¯ç·¨éããªããã¨ #####
+
+#
+#  ã³ã³ãã£ã®ã¥ã¬ã¼ã¿ã«é¢ããå®ç¾©
+#
+CFG_TABS := --api-table $(SRCDIR)/kernel/kernel_api.csv \
+			--cfg1-def-table $(SRCDIR)/kernel/kernel_def.csv $(CFG_TABS)
+
+CFG_ASMOBJS := $(CFG_ASMOBJS)
+CFG_COBJS := kernel_cfg.o $(CFG_COBJS)
+CFG_OBJS := $(CFG_ASMOBJS) $(CFG_COBJS)
+CFG2_OUT_SRCS := kernel_cfg.h kernel_cfg.c $(CFG2_OUT_SRCS)
+
+#
+#  ã«ã¼ãã«ã«é¢ããå®ç¾©
+#
+#  KERNEL_ASMOBJS: ã«ã¼ãã«ã©ã¤ãã©ãªã«å«ããï¼ã½ã¼ã¹ãã¢ã»ã³ããªè¨èªã®
+#				   ãªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#  KERNEL_COBJS: ã«ã¼ãã«ã®ã©ã¤ãã©ãªã«å«ããï¼ã½ã¼ã¹ãCè¨èªã§ï¼ã½ã¼ã¹
+#				 ãã¡ã¤ã«ã¨1å¯¾1ã«å¯¾å¿ãããªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#  KERNEL_LCSRCS: ã«ã¼ãã«ã®ã©ã¤ãã©ãªã«å«ããCè¨èªã®ã½ã¼ã¹ãã¡ã¤ã«ã§ï¼
+#				  1ã¤ã®ã½ã¼ã¹ãã¡ã¤ã«ããè¤æ°ã®ãªãã¸ã§ã¯ããã¡ã¤ã«ãç
+#				  æãããã®ï¼
+#  KERNEL_LCOBJS: ä¸ã®ã½ã¼ã¹ãã¡ã¤ã«ããçæããããªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#  KERNEL_AUX_COBJS: ã­ã¼ãã¢ã¸ã¥ã¼ã«ã«å«ããªããï¼ã«ã¼ãã«ã®ã½ã¼ã¹ãã¡
+#					 ã¤ã«ã¨åããªãã·ã§ã³ãé©ç¨ãã¦ã³ã³ãã¤ã«ãã¹ãï¼ã½ã¼
+#					 ã¹ãCè¨èªã®ãªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#
+KERNEL_DIR := $(KERNEL_DIR) $(SRCDIR)/kernel
+KERNEL_ASMOBJS := $(KERNEL_ASMOBJS)
+KERNEL_COBJS := $(KERNEL_COBJS)
+KERNEL_CFLAGS := $(KERNEL_CFLAGS) -I$(SRCDIR)/kernel
+ifdef OMIT_MAKEOFFSET
+  OFFSET_H =
+else
+  OFFSET_H = offset.h
+ifndef OFFSET_TF
+  KERNEL_AUX_COBJS := $(KERNEL_AUX_COBJS) makeoffset.o
+endif
+endif
+
+#
+#  ç°å¢ã«ä¾å­ããã³ã³ãã¤ã«ãªãã·ã§ã³ã®å®ç¾©
+#
+ifdef DBGENV
+  CDEFS := $(CDEFS) -D$(DBGENV)
+endif
+
+#
+#  ã«ã¼ãã«ã®ãã¡ã¤ã«æ§æã®å®ç¾©
+#
+include $(SRCDIR)/kernel/Makefile.kernel
+ifdef KERNEL_FUNCOBJS
+	KERNEL_LCSRCS := $(KERNEL_FCSRCS)
+	KERNEL_LCOBJS := $(foreach file,$(KERNEL_FCSRCS),$($(file:.c=)))
+else
+	KERNEL_CFLAGS := -DALLFUNC $(KERNEL_CFLAGS)
+	KERNEL_COBJS := $(KERNEL_COBJS) \
+					$(foreach file,$(KERNEL_FCSRCS),$(file:.c=.o))
+endif
+
+#
+#  ã½ã¼ã¹ãã¡ã¤ã«ã®ãããã£ã¬ã¯ããªã«é¢ããå®ç¾©
+#
+vpath %.c $(KERNEL_DIR) $(SYSSVC_DIR) $(APPL_DIR)
+vpath %.cpp $(KERNEL_DIR) $(SYSSVC_DIR) $(APPL_DIR)
+vpath %.S $(KERNEL_DIR) $(SYSSVC_DIR) $(APPL_DIR)
+vpath %.cfg $(APPL_DIR)
+
+#
+#  ä¸­éãªãã¸ã§ã¯ããã¡ã¤ã«ãç½®ããã£ã¬ã¯ããªã®å¦ç
+#
+APPL_ASMOBJS   := $(addprefix $(OBJDIR)/, $(APPL_ASMOBJS))
+APPL_CXXOBJS   := $(addprefix $(OBJDIR)/, $(APPL_CXXOBJS))
+APPL_COBJS     := $(addprefix $(OBJDIR)/, $(APPL_COBJS))
+SYSSVC_ASMOBJS := $(addprefix $(OBJDIR)/, $(SYSSVC_ASMOBJS))
+SYSSVC_COBJS   := $(addprefix $(OBJDIR)/, $(SYSSVC_COBJS))
+KERNEL_ASMOBJS := $(addprefix $(OBJDIR)/, $(KERNEL_ASMOBJS))
+KERNEL_COBJS   := $(addprefix $(OBJDIR)/, $(KERNEL_COBJS))
+KERNEL_LCOBJS  := $(addprefix $(OBJDIR)/, $(KERNEL_LCOBJS))
+CFG_ASMOBJS    := $(addprefix $(OBJDIR)/, $(CFG_ASMOBJS))
+CFG_COBJS      := $(addprefix $(OBJDIR)/, $(CFG_COBJS))
+
+#
+#  ã³ã³ãã¤ã«ã®ããã®å¤æ°ã®å®ç¾©
+#
+APPL_OBJS = $(APPL_ASMOBJS) $(APPL_COBJS) $(APPL_CXXOBJS)
+SYSSVC_OBJS = $(SYSSVC_ASMOBJS) $(SYSSVC_COBJS)
+KERNEL_LIB_OBJS = $(KERNEL_ASMOBJS) $(KERNEL_COBJS) $(KERNEL_LCOBJS)
+CFG_OBJS = $(CFG_ASMOBJS) $(CFG_COBJS)
+ALL_OBJS = $(START_OBJS) $(APPL_OBJS) $(SYSSVC_OBJS) $(CFG_OBJS) \
+											$(END_OBJS) $(HIDDEN_OBJS)
+ALL_LIBS = -lkernel $(LIBS)
+ifdef KERNEL_LIB
+	LIBS_DEP = $(KERNEL_LIB)/libkernel.a $(filter %.a,$(LIBS))
+	OBJ_LDFLAGS := $(OBJ_LDFLAGS) -L$(KERNEL_LIB)
+	REALCLEAN_FILES := libkernel.a $(REALCLEAN_FILES)
+else
+	LIBS_DEP = libkernel.a $(filter %.a,$(LIBS))
+	OBJ_LDFLAGS := $(OBJ_LDFLAGS) -L.
+endif
+
+ifdef TEXT_START_ADDRESS
+	LDFLAGS := $(LDFLAGS) -Wl,-Ttext,$(TEXT_START_ADDRESS)
+endif
+ifdef DATA_START_ADDRESS
+	LDFLAGS := $(LDFLAGS) -Wl,-Tdata,$(DATA_START_ADDRESS)
+endif
+ifdef LDSCRIPT
+	LDFLAGS := $(LDFLAGS) -T $(LDSCRIPT)
+endif
+
+#
+#  ã«ã¼ãã«ã®ã³ã³ãã£ã®ã¥ã¬ã¼ã·ã§ã³ãã¡ã¤ã«ã®çæ
+#
+cfg1_out.c: cfg1_out.timestamp ;
+cfg1_out.timestamp: $(APPL_CFG)
+	$(CFG) --pass 1 $(CFG_KERNEL) $(INCLUDES) $(CFG_TABS) $<
+	touch -r cfg1_out.c cfg1_out.timestamp
+
+$(CFG1_OUT): $(START_OBJS) $(OBJDIR)/cfg1_out.o $(END_OBJS) $(HIDDEN_OBJS)
+	$(LINK) $(CFLAGS) $(LDFLAGS) $(CFG1_OUT_LDFLAGS) -o $(CFG1_OUT) \
+						$(START_OBJS) $(OBJDIR)/cfg1_out.o $(LIBS) $(END_OBJS)
+
+cfg1_out.syms: $(CFG1_OUT)
+	$(NM) -n $(CFG1_OUT) > cfg1_out.syms
+
+cfg1_out.srec: $(CFG1_OUT)
+	$(OBJCOPY) -O srec -S $(CFG1_OUT) cfg1_out.srec
+
+$(CFG2_OUT_SRCS): kernel_cfg.timestamp ;
+kernel_cfg.timestamp: $(APPL_CFG) cfg1_out.syms cfg1_out.srec
+	$(CFG) --pass 2 $(CFG_KERNEL) $(INCLUDES) \
+				-T $(TARGETDIR)/target.tf $(CFG_TABS) $<
+	touch -r kernel_cfg.c kernel_cfg.timestamp
+
+#
+#  ãªãã»ãããã¡ã¤ã«ï¼offset.hï¼ã®çæè¦å
+#
+$(OFFSET_H): offset.timestamp ;
+ifdef OFFSET_TF
+offset.timestamp: $(APPL_CFG) kernel_cfg.timestamp
+	$(CFG) --pass 3 --kernel asp $(INCLUDES) \
+				--rom-image cfg1_out.srec --symbol-table cfg1_out.syms \
+				-T $(OFFSET_TF) $(CFG_TABS) $<
+	touch -r $(OFFSET_H) offset.timestamp
+else
+offset.timestamp: makeoffset.s $(SRCDIR)/utils/genoffset
+	$(PERL) $(SRCDIR)/utils/genoffset makeoffset.s > offset.h
+	touch -r $(OFFSET_H) offset.timestamp
+endif
+
+#
+#  ã«ã¼ãã«ã©ã¤ãã©ãªãã¡ã¤ã«ã®çæ
+#
+libkernel.a: $(OFFSET_H) $(KERNEL_LIB_OBJS)
+	rm -f libkernel.a
+	$(AR) -rcs libkernel.a $(KERNEL_LIB_OBJS)
+	$(RANLIB) libkernel.a
+
+#
+#  ä¸¦åmakeã®ããã®ä¾å­é¢ä¿ã®å®ç¾©
+#
+$(APPL_OBJS) $(SYSSVC_OBJS): | kernel_cfg.timestamp
+$(APPL_ASMOBJS) $(SYSSVC_ASMOBJS) $(KERNEL_ASMOBJS) $(CFG_ASMOBJS): \
+														| offset.timestamp
+
+#
+#  ç¹å¥ãªä¾å­é¢ä¿ã®å®ç¾©
+#
+$(OBJDIR)/banner.o: $(filter-out $(OBJDIR)/banner.o,$(ALL_OBJS)) \
+																$(LIBS_DEP)
+
+#
+#  å
+¨ä½ã®ãªã³ã¯
+#
+$(OBJFILE): $(ALL_OBJS) $(LIBS_DEP)
+	$(LINK) $(CFLAGS) $(LDFLAGS) $(OBJ_LDFLAGS) -o $(OBJFILE) \
+			-Wl,-Map=$(OBJNAME).map,--cref -Wl,--gc-sections -Wl,-estart,--gc-keep-exported=_kernel_istk \
+			$(START_OBJS) $(APPL_OBJS) $(SYSSVC_OBJS) $(CFG_OBJS) \
+			-Wl,--start-group $(ALL_LIBS) -Wl,--end-group $(END_OBJS)
+
+#
+#  ä¾å­é¢ä¿ãã©ã«ãã®ä½æ
+#
+$(DEPDIR):
+	mkdir $@
+
+#
+#  ã·ã³ãã«ãã¡ã¤ã«ã®çæ
+#
+$(OBJNAME).syms: $(OBJFILE)
+	$(NM) -n $(OBJFILE) > $(OBJNAME).syms
+
+#
+#  ãã¤ããªãã¡ã¤ã«ã®çæ
+#
+$(OBJNAME).bin: $(OBJFILE)
+	$(OBJCOPY) -O binary -S $(OBJFILE) $(OBJNAME).bin
+	$(OBJDUMP) -h $(OBJFILE)
+	$(SIZE) $(OBJFILE)
+
+#
+#  Sã¬ã³ã¼ããã¡ã¤ã«ã®çæ
+#
+$(OBJNAME).srec: $(OBJFILE)
+	$(OBJCOPY) -O srec -S $(OBJFILE) $(OBJNAME).srec
+
+#
+#  ã¨ã©ã¼ãã§ãã¯å¦ç
+#
+.PHONY: check
+check: check.timestamp ;
+check.timestamp: $(APPL_CFG) $(OBJNAME).syms $(OBJNAME).srec
+#	$(CFG) --pass 3 --kernel asp $(INCLUDES) \
+#				--rom-image cfg1_out.srec --symbol-table cfg1_out.syms \
+#				-T $(OFFSET_TF) $(CFG_TABS) $<
+	touch -r $(OFFSET_H) check.timestamp
+	@echo "configuration check passed"
+
+#
+#  ã³ã³ãã¤ã«çµæã®æ¶å»
+#
+.PHONY: clean
+clean:
+	rm -f \#* *~ $(OBJDIR)/*.o $(DEPDIR)/*.d $(CLEAN_FILES)
+	rm -f $(OBJFILE) $(OBJNAME).syms $(OBJNAME).srec $(OBJNAME).bin
+	rm -f kernel_cfg.timestamp $(CFG2_OUT_SRCS)
+	rm -f offset.timestamp $(OFFSET_H)
+	rm -f cfg1_out.syms cfg1_out.srec $(CFG1_OUT)
+	rm -f cfg1_out.timestamp cfg1_out.c
+ifndef KERNEL_LIB
+	rm -f libkernel.a
+endif
+	rm -f makeoffset.s offset.h
+
+.PHONY: cleankernel
+cleankernel:
+	rm -f makeoffset.s $(OFFSET_H) $(KERNEL_LIB_OBJS)
+	rm -f $(KERNEL_LIB_OBJS:$(OBJDIR)/%.o=$(DEPDIR)/%.d)
+
+
+.PHONY: realclean
+realclean: clean
+	rm -f $(REALCLEAN_FILES)
+
+#
+#  ã³ã³ãã£ã®ã¥ã¬ã¼ã¿ãçæãããã¡ã¤ã«ã®ã³ã³ãã¤ã«ã«ã¼ã«ã®å®ç¾©
+#
+#  ã³ã³ãã£ã®ã¥ã¬ã¼ã¿ãçæãããã¡ã¤ã«ã¯ï¼å
+±éã®ã³ã³ãã¤ã«ãªãã·ã§ã³
+#  ã®ã¿ãä»ãã¦ã³ã³ãã¤ã«ããï¼
+#
+ALL_CFG_COBJS = $(CFG_COBJS) $(OBJDIR)/cfg1_out.o
+ALL_CFG_ASMOBJS = $(CFG_ASMOBJS)
+
+$(ALL_CFG_COBJS): $(OBJDIR)/%.o: %.c
+	$(CC) -c -o $@ -MD -MP -MF $(DEPDIR)/$*.d $(CFLAGS) $(CFG_CFLAGS) $<
+
+$(ALL_CFG_COBJS:$(OBJDIR)/%.o=%.s): %.s: %.c
+	$(CC) -S -o $@ $(CFLAGS) $(CFG_CFLAGS) $<
+
+$(ALL_CFG_ASMOBJS): $(OBJDIR)/%.o: %.S
+	$(CC) -c -o $@ -MD -MP -MF $(DEPDIR)/$*.d $(CFLAGS) $(CFG_CFLAGS) $<
+
+#
+#  ä¾å­é¢ä¿ãã¡ã¤ã«ã®ã¤ã³ã¯ã«ã¼ã
+#
+-include $(DEPDIR)/*.d
+
+#
+#  éçºãã¼ã«ã®ã³ãã³ãåã®å®ç¾©
+#
+ifeq ($(TOOL),gcc)
+	#
+	#  GNUéçºç°å¢ç¨
+	#
+	ifdef GCC_TARGET
+		GCC_TARGET_PREFIX = $(GCC_TARGET)-
+	else
+		GCC_TARGET_PREFIX =
+	endif
+	CC := $(GCC_TARGET_PREFIX)gcc
+	CXX := $(GCC_TARGET_PREFIX)g++
+	AS := $(GCC_TARGET_PREFIX)as
+	LD := $(GCC_TARGET_PREFIX)ld
+	AR := $(GCC_TARGET_PREFIX)ar
+	NM := $(GCC_TARGET_PREFIX)nm
+	RANLIB := $(GCC_TARGET_PREFIX)ranlib
+	OBJCOPY := $(GCC_TARGET_PREFIX)objcopy
+	OBJDUMP := $(GCC_TARGET_PREFIX)objdump
+	SIZE := $(GCC_TARGET_PREFIX)size
+endif
+
+ifdef DEVTOOLDIR
+	CC := $(DEVTOOLDIR)/$(CC)
+	CXX := $(DEVTOOLDIR)/$(CXX)
+	AS := $(DEVTOOLDIR)/$(AS)
+	LD := $(DEVTOOLDIR)/$(LD)
+	AR := $(DEVTOOLDIR)/$(AR)
+	NM := $(DEVTOOLDIR)/$(NM)
+	RANLIB := $(DEVTOOLDIR)/$(RANLIB)
+	OBJCOPY := $(DEVTOOLDIR)/$(OBJCOPY)
+	OBJDUMP := $(DEVTOOLDIR)/$(OBJDUMP)
+endif
+
+ifdef USE_CXX
+	LINK = $(CXX)
+else
+	LINK = $(CC)
+endif
+
+#
+#  ã³ã³ãã¤ã«ã«ã¼ã«ã®å®ç¾©
+#
+$(KERNEL_COBJS): $(OBJDIR)/%.o: %.c
+	$(CC) -c -o $@ -MD -MP -MF $(DEPDIR)/$*.d $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_COBJS:$(OBJDIR)/%.o=%.s): %.s: %.c
+	$(CC) -S -o $@ $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_LCOBJS): $(OBJDIR)/%.o:
+	$(CC) -c -o $@ -DTOPPERS_$(*F) -MD -MP -MF $(DEPDIR)/$*.d \
+									$(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_LCOBJS:$(OBJDIR)/%.o=%.s): %.s:
+	$(CC) -S -o $@ -DTOPPERS_$(*F) $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_ASMOBJS): $(OBJDIR)/%.o: %.S
+	$(CC) -c -o $@ -MD -MP -MF $(DEPDIR)/$*.d $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(SYSSVC_COBJS): $(OBJDIR)/%.o: %.c
+	$(CC) -c -o $@ -MD -MP -MF $(DEPDIR)/$*.d $(CFLAGS) $(SYSSVC_CFLAGS) $<
+
+$(SYSSVC_COBJS:$(OBJDIR)/%.o=%.s): %.s: %.c
+	$(CC) -S -o $@ $(CFLAGS) $(SYSSVC_CFLAGS) $<
+
+$(SYSSVC_ASMOBJS): $(OBJDIR)/%.o: %.S
+	$(CC) -c -o $@ -MD -MP -MF $(DEPDIR)/$*.d $(CFLAGS) $(SYSSVC_CFLAGS) $<
+
+$(APPL_COBJS): $(OBJDIR)/%.o: %.c
+	$(CC) -c -o $@ -MD -MP -MF $(DEPDIR)/$*.d $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_COBJS:$(OBJDIR)/%.o=%.s): %.s: %.c
+	$(CC) -S -o $@ $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_CXXOBJS): $(OBJDIR)/%.o: %.cpp
+	$(CXX) -c -o $@ -MD -MP -MF $(DEPDIR)/$*.d $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_CXXOBJS:$(OBJDIR)/%.o=%.s): %.s: %.cpp
+	$(CXX) -S -o $@ $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_ASMOBJS): $(OBJDIR)/%.o: %.S
+	$(CC) -c -o $@ -MD -MP -MF $(DEPDIR)/$*.d $(CFLAGS) $(APPL_CFLAGS) $<
+
+#
+#  ããã©ã«ãã³ã³ãã¤ã«ã«ã¼ã«ãä¸æ¸ã
+#
+$(OBJDIR)/%.o: %.c
+	@echo "*** Default compile rules should not be used."
+	$(CC) -c -o $@ -MD -MP -MF $(DEPDIR)/$*.d $(CFLAGS) $<
+
+%.s: %.c
+	@echo "*** Default compile rules should not be used."
+	$(CC) -S -o $@ $(CFLAGS) $<
+
+$(OBJDIR)/%.o: %.cpp
+	@echo "*** Default compile rules should not be used."
+	$(CXX) -c -o $@ -MD -MP -MF $(DEPDIR)/$*.d $(CFLAGS) $<
+
+%.s: %.cpp
+	@echo "*** Default compile rules should not be used."
+	$(CXX) -S -o $@ $(CFLAGS) $<
+
+$(OBJDIR)/%.o: %.S
+	@echo "*** Default compile rules should not be used."
+	$(CC) -c -o $@ -MD -MP -MF $(DEPDIR)/$*.d $(CFLAGS) $<
Index: azure_iot_hub_riscv/trunk/app_iothub_client/Makefile
===================================================================
--- azure_iot_hub_riscv/trunk/app_iothub_client/Makefile	(revision 453)
+++ azure_iot_hub_riscv/trunk/app_iothub_client/Makefile	(revision 453)
@@ -0,0 +1,17 @@
+
+MAKE = make
+
+.PHONY: all
+all:
+	$(MAKE) -j -C Debug all
+
+kernel_cfg.h:
+	$(MAKE) -j 1 -C Debug kernel_cfg.h
+
+.PHONY: clean
+clean:
+	$(MAKE) -j -C Debug clean
+
+.PHONY: realclean
+realclean:
+	$(MAKE) -j -C Debug realclean
Index: azure_iot_hub_riscv/trunk/app_iothub_client/kendryte/atomic.h
===================================================================
--- azure_iot_hub_riscv/trunk/app_iothub_client/kendryte/atomic.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/app_iothub_client/kendryte/atomic.h	(revision 453)
@@ -0,0 +1,236 @@
+
+/* Copyright 2018 Canaan Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _BSP_ATOMIC_H
+#define _BSP_ATOMIC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SPINLOCK_INIT \
+    {                 \
+        0             \
+    }
+
+#define CORELOCK_INIT          \
+    {                          \
+        .lock = SPINLOCK_INIT, \
+        .count = 0,            \
+        .core = -1             \
+    }
+
+/* Defination of memory barrier macro */
+#define mb()                          \
+    {                                 \
+        asm volatile("fence" ::       \
+                         : "memory"); \
+    }
+
+#define atomic_set(ptr, val) (*(volatile typeof(*(ptr)) *)(ptr) = val)
+#define atomic_read(ptr) (*(volatile typeof(*(ptr)) *)(ptr))
+
+#ifndef __riscv_atomic
+#error "atomic extension is required."
+#endif
+#define atomic_add(ptr, inc) __sync_fetch_and_add(ptr, inc)
+#define atomic_or(ptr, inc) __sync_fetch_and_or(ptr, inc)
+#define atomic_swap(ptr, swp) __sync_lock_test_and_set(ptr, swp)
+#define atomic_cas(ptr, cmp, swp) __sync_val_compare_and_swap(ptr, cmp, swp)
+
+typedef struct _spinlock
+{
+    int lock;
+} spinlock_t;
+
+typedef struct _semaphore
+{
+    spinlock_t lock;
+    int count;
+    int waiting;
+} semaphore_t;
+
+typedef struct _corelock
+{
+    spinlock_t lock;
+    int count;
+    int core;
+} corelock_t;
+
+static inline int spinlock_trylock(spinlock_t *lock)
+{
+    int res = atomic_swap(&lock->lock, -1);
+    /* Use memory barrier to keep coherency */
+    mb();
+    return res;
+}
+
+static inline void spinlock_lock(spinlock_t *lock)
+{
+    while(spinlock_trylock(lock))
+        ;
+}
+
+static inline void spinlock_unlock(spinlock_t *lock)
+{
+    /* Use memory barrier to keep coherency */
+    mb();
+    atomic_set(&lock->lock, 0);
+    asm volatile("nop");
+}
+
+static inline void semaphore_signal(semaphore_t *semaphore, int i)
+{
+    spinlock_lock(&(semaphore->lock));
+    semaphore->count += i;
+    spinlock_unlock(&(semaphore->lock));
+}
+
+static inline void semaphore_wait(semaphore_t *semaphore, int i)
+{
+    atomic_add(&(semaphore->waiting), 1);
+    while(1)
+    {
+        spinlock_lock(&(semaphore->lock));
+        if(semaphore->count >= i)
+        {
+            semaphore->count -= i;
+            atomic_add(&(semaphore->waiting), -1);
+            spinlock_unlock(&(semaphore->lock));
+            break;
+        }
+        spinlock_unlock(&(semaphore->lock));
+    }
+}
+
+static inline int semaphore_count(semaphore_t *semaphore)
+{
+    int res = 0;
+
+    spinlock_lock(&(semaphore->lock));
+    res = semaphore->count;
+    spinlock_unlock(&(semaphore->lock));
+    return res;
+}
+
+static inline int semaphore_waiting(semaphore_t *semaphore)
+{
+    return atomic_read(&(semaphore->waiting));
+}
+
+static inline int corelock_trylock(corelock_t *lock)
+{
+    int res = 0;
+    unsigned long core;
+
+    asm volatile("csrr %0, mhartid;"
+                 : "=r"(core));
+    if(spinlock_trylock(&lock->lock))
+    {
+        return -1;
+    }
+
+    if(lock->count == 0)
+    {
+        /* First time get lock */
+        lock->count++;
+        lock->core = core;
+        res = 0;
+    } else if(lock->core == core)
+    {
+        /* Same core get lock */
+        lock->count++;
+        res = 0;
+    } else
+    {
+        /* Different core get lock */
+        res = -1;
+    }
+    spinlock_unlock(&lock->lock);
+
+    return res;
+}
+
+static inline void corelock_lock(corelock_t *lock)
+{
+    unsigned long core;
+
+    asm volatile("csrr %0, mhartid;"
+                 : "=r"(core));
+    spinlock_lock(&lock->lock);
+
+    if(lock->count == 0)
+    {
+        /* First time get lock */
+        lock->count++;
+        lock->core = core;
+    } else if(lock->core == core)
+    {
+        /* Same core get lock */
+        lock->count++;
+    } else
+    {
+        /* Different core get lock */
+        spinlock_unlock(&lock->lock);
+
+        do
+        {
+            while(atomic_read(&lock->count))
+                ;
+        } while(corelock_trylock(lock));
+        return;
+    }
+    spinlock_unlock(&lock->lock);
+}
+
+static inline void corelock_unlock(corelock_t *lock)
+{
+    unsigned long core;
+
+    asm volatile("csrr %0, mhartid;"
+                 : "=r"(core));
+    spinlock_lock(&lock->lock);
+
+    if(lock->core == core)
+    {
+        /* Same core release lock */
+        lock->count--;
+        if(lock->count <= 0)
+        {
+            lock->core = -1;
+            lock->count = 0;
+        }
+    } else
+    {
+        /* Different core release lock */
+        spinlock_unlock(&lock->lock);
+
+        register unsigned long a7 asm("a7") = 93;
+        register unsigned long a0 asm("a0") = 0;
+        register unsigned long a1 asm("a1") = 0;
+        register unsigned long a2 asm("a2") = 0;
+
+        asm volatile("scall"
+                     : "+r"(a0)
+                     : "r"(a1), "r"(a2), "r"(a7));
+    }
+    spinlock_unlock(&lock->lock);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _BSP_ATOMIC_H */
Index: azure_iot_hub_riscv/trunk/app_iothub_client/kendryte/incbin.h
===================================================================
--- azure_iot_hub_riscv/trunk/app_iothub_client/kendryte/incbin.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/app_iothub_client/kendryte/incbin.h	(revision 453)
@@ -0,0 +1,314 @@
+/**
+ * @file incbin.h
+ * @author Dale Weiler
+ * @brief Utility for including binary files
+ *
+ * Facilities for including binary files into the current translation unit and
+ * making use from them externally in other translation units.
+ */
+#ifndef INCBIN_HDR
+#define INCBIN_HDR
+#include <limits.h>
+
+# define INCBIN_ALIGNMENT_INDEX 7
+
+/* Lookup table of (1 << n) where `n' is `INCBIN_ALIGNMENT_INDEX' */
+#define INCBIN_ALIGN_SHIFT_0 1
+#define INCBIN_ALIGN_SHIFT_1 2
+#define INCBIN_ALIGN_SHIFT_2 4
+#define INCBIN_ALIGN_SHIFT_3 8
+#define INCBIN_ALIGN_SHIFT_4 16
+#define INCBIN_ALIGN_SHIFT_5 32
+#define INCBIN_ALIGN_SHIFT_6 64
+#define INCBIN_ALIGN_SHIFT_7 128
+
+/* Actual alignment value */
+#define INCBIN_ALIGNMENT \
+    INCBIN_CONCATENATE( \
+        INCBIN_CONCATENATE(INCBIN_ALIGN_SHIFT, _), \
+        INCBIN_ALIGNMENT_INDEX)
+
+/* Stringize */
+#define INCBIN_STR(X) \
+    #X
+#define INCBIN_STRINGIZE(X) \
+    INCBIN_STR(X)
+/* Concatenate */
+#define INCBIN_CAT(X, Y) \
+    X ## Y
+#define INCBIN_CONCATENATE(X, Y) \
+    INCBIN_CAT(X, Y)
+/* Deferred macro expansion */
+#define INCBIN_EVAL(X) \
+    X
+#define INCBIN_INVOKE(N, ...) \
+    INCBIN_EVAL(N(__VA_ARGS__))
+
+/* Green Hills uses a different directive for including binary data */
+#if defined(__ghs__)
+#  define INCBIN_MACRO "\tINCBIN"
+#else
+#  define INCBIN_MACRO ".incbin"
+#endif
+
+#ifndef _MSC_VER
+#  define INCBIN_ALIGN \
+    __attribute__((aligned(INCBIN_ALIGNMENT)))
+#else
+#  define INCBIN_ALIGN __declspec(align(INCBIN_ALIGNMENT))
+#endif
+
+#if defined(__arm__) || /* GNU C and RealView */ \
+    defined(__arm) || /* Diab */ \
+    defined(_ARM) /* ImageCraft */
+#  define INCBIN_ARM
+#endif
+
+#ifdef __GNUC__
+/* Utilize .balign where supported */
+#  define INCBIN_ALIGN_HOST ".balign " INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"
+#  define INCBIN_ALIGN_BYTE ".balign 1\n"
+#elif defined(INCBIN_ARM)
+/*
+ * On arm assemblers, the alignment value is calculated as (1 << n) where `n' is
+ * the shift count. This is the value passed to `.align'
+ */
+#  define INCBIN_ALIGN_HOST ".align" INCBIN_STRINGIZE(INCBIN_ALIGNMENT_INDEX) "\n"
+#  define INCBIN_ALIGN_BYTE ".align 0\n"
+#else
+/* We assume other inline assembler's treat `.align' as `.balign' */
+#  define INCBIN_ALIGN_HOST ".align" INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"
+#  define INCBIN_ALIGN_BYTE ".align 1\n"
+#endif
+
+/* INCBIN_CONST is used by incbin.c generated files */
+#if defined(__cplusplus)
+#  define INCBIN_EXTERNAL extern "C"
+#  define INCBIN_CONST    extern const
+#else
+#  define INCBIN_EXTERNAL extern
+#  define INCBIN_CONST    const
+#endif
+
+#if defined(__APPLE__)
+/* The directives are different for Apple branded compilers */
+#  define INCBIN_SECTION         ".data\n"
+#  define INCBIN_GLOBAL(NAME)    ".globl " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
+#  define INCBIN_INT             ".long "
+#  define INCBIN_MANGLE          "_"
+#  define INCBIN_BYTE            ".byte "
+#  define INCBIN_TYPE(...)
+#else
+#  define INCBIN_SECTION         ".section .data\n"
+#  define INCBIN_GLOBAL(NAME)    ".global " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
+#  define INCBIN_INT             ".int "
+#  if defined(__USER_LABEL_PREFIX__)
+#    define INCBIN_MANGLE        INCBIN_STRINGIZE(__USER_LABEL_PREFIX__)
+#  else
+#    define INCBIN_MANGLE        ""
+#  endif
+#  if defined(INCBIN_ARM)
+/* On arm assemblers, `@' is used as a line comment token */
+#    define INCBIN_TYPE(NAME)    ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", %object\n"
+#  elif defined(__MINGW32__) || defined(__MINGW64__)
+/* Mingw doesn't support this directive either */
+#    define INCBIN_TYPE(NAME)
+#  else
+/* It's safe to use `@' on other architectures */
+#    define INCBIN_TYPE(NAME)    ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", @object\n"
+#  endif
+#  define INCBIN_BYTE            ".byte "
+#endif
+
+/* List of style types used for symbol names */
+#define INCBIN_STYLE_CAMEL 0
+#define INCBIN_STYLE_SNAKE 1
+
+/**
+ * @brief Specify the prefix to use for symbol names.
+ *
+ * By default this is `g', producing symbols of the form:
+ * @code
+ * #include "incbin.h"
+ * INCBIN(Foo, "foo.txt");
+ *
+ * // Now you have the following symbols:
+ * // const unsigned char gFooData[];
+ * // const unsigned char gFooEnd;
+ * // const unsigned int gFooSize;
+ * @endcode
+ *
+ * If however you specify a prefix before including: e.g:
+ * @code
+ * #define INCBIN_PREFIX incbin
+ * #include "incbin.h"
+ * INCBIN(Foo, "foo.txt");
+ *
+ * // Now you have the following symbols instead:
+ * // const unsigned char incbinFooData[];
+ * // const unsigned char incbinFooEnd;
+ * // const unsigned int incbinFooSize;
+ * @endcode
+ */
+#if !defined(INCBIN_PREFIX)
+#  define INCBIN_PREFIX g
+#endif
+
+/**
+ * @brief Specify the style used for symbol names.
+ *
+ * Possible options are
+ * - INCBIN_STYLE_CAMEL "CamelCase"
+ * - INCBIN_STYLE_SNAKE "snake_case"
+ *
+ * Default option is *INCBIN_STYLE_CAMEL* producing symbols of the form:
+ * @code
+ * #include "incbin.h"
+ * INCBIN(Foo, "foo.txt");
+ *
+ * // Now you have the following symbols:
+ * // const unsigned char <prefix>FooData[];
+ * // const unsigned char <prefix>FooEnd;
+ * // const unsigned int <prefix>FooSize;
+ * @endcode
+ *
+ * If however you specify a style before including: e.g:
+ * @code
+ * #define INCBIN_STYLE INCBIN_STYLE_SNAKE
+ * #include "incbin.h"
+ * INCBIN(foo, "foo.txt");
+ *
+ * // Now you have the following symbols:
+ * // const unsigned char <prefix>foo_data[];
+ * // const unsigned char <prefix>foo_end;
+ * // const unsigned int <prefix>foo_size;
+ * @endcode
+ */
+#if !defined(INCBIN_STYLE)
+#  define INCBIN_STYLE INCBIN_STYLE_CAMEL
+#endif
+
+/* Style lookup tables */
+#define INCBIN_STYLE_0_DATA Data
+#define INCBIN_STYLE_0_END End
+#define INCBIN_STYLE_0_SIZE Size
+#define INCBIN_STYLE_1_DATA _data
+#define INCBIN_STYLE_1_END _end
+#define INCBIN_STYLE_1_SIZE _size
+
+/* Style lookup: returning identifier */
+#define INCBIN_STYLE_IDENT(TYPE) \
+    INCBIN_CONCATENATE( \
+        INCBIN_STYLE_, \
+        INCBIN_CONCATENATE( \
+            INCBIN_EVAL(INCBIN_STYLE), \
+            INCBIN_CONCATENATE(_, TYPE)))
+
+/* Style lookup: returning string literal */
+#define INCBIN_STYLE_STRING(TYPE) \
+    INCBIN_STRINGIZE( \
+        INCBIN_STYLE_IDENT(TYPE)) \
+
+/* Generate the global labels by indirectly invoking the macro with our style
+ * type and concatenating the name against them. */
+#define INCBIN_GLOBAL_LABELS(NAME, TYPE) \
+    INCBIN_INVOKE( \
+        INCBIN_GLOBAL, \
+        INCBIN_CONCATENATE( \
+            NAME, \
+            INCBIN_INVOKE( \
+                INCBIN_STYLE_IDENT, \
+                TYPE))) \
+    INCBIN_INVOKE( \
+        INCBIN_TYPE, \
+        INCBIN_CONCATENATE( \
+            NAME, \
+            INCBIN_INVOKE( \
+                INCBIN_STYLE_IDENT, \
+                TYPE)))
+
+/**
+ * @brief Externally reference binary data included in another translation unit.
+ *
+ * Produces three external symbols that reference the binary data included in
+ * another translation unit.
+ *
+ * The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
+ * "Data", as well as "End" and "Size" after. An example is provided below.
+ *
+ * @param NAME The name given for the binary data
+ *
+ * @code
+ * INCBIN_EXTERN(Foo);
+ *
+ * // Now you have the following symbols:
+ * // extern const unsigned char <prefix>FooData[];
+ * // extern const unsigned char <prefix>FooEnd;
+ * // extern const unsigned int <prefix>FooSize;
+ * @endcode
+ */
+#define INCBIN_EXTERN(NAME) \
+    INCBIN_EXTERNAL INCBIN_ALIGN unsigned char \
+        INCBIN_CONCATENATE( \
+            INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
+            INCBIN_STYLE_IDENT(DATA))[]; \
+    INCBIN_EXTERNAL INCBIN_ALIGN unsigned char * \
+    INCBIN_CONCATENATE( \
+        INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
+        INCBIN_STYLE_IDENT(END)); \
+    INCBIN_EXTERNAL unsigned int \
+        INCBIN_CONCATENATE( \
+            INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
+            INCBIN_STYLE_IDENT(SIZE))
+
+/**
+ * @brief Include a binary file into the current translation unit.
+ *
+ * Includes a binary file into the current translation unit, producing three symbols
+ * for objects that encode the data and size respectively.
+ *
+ * The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
+ * "Data", as well as "End" and "Size" after. An example is provided below.
+ *
+ * @param NAME The name to associate with this binary data (as an identifier.)
+ * @param FILENAME The file to include (as a string literal.)
+ *
+ * @code
+ * INCBIN(Icon, "icon.png");
+ *
+ * // Now you have the following symbols:
+ * // const unsigned char <prefix>IconData[];
+ * // const unsigned char <prefix>IconEnd;
+ * // const unsigned int <prefix>IconSize;
+ * @endcode
+ *
+ * @warning This must be used in global scope
+ * @warning The identifiers may be different if INCBIN_STYLE is not default
+ *
+ * To externally reference the data included by this in another translation unit
+ * please @see INCBIN_EXTERN.
+ */
+#ifdef _MSC_VER
+#define INCBIN(NAME, FILENAME) \
+    INCBIN_EXTERN(NAME)
+#else
+#define INCBIN(NAME, FILENAME) \
+    __asm__(INCBIN_SECTION \
+            INCBIN_GLOBAL_LABELS(NAME, DATA) \
+            INCBIN_ALIGN_HOST \
+            INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) ":\n" \
+            INCBIN_MACRO " \"" FILENAME "\"\n" \
+            INCBIN_GLOBAL_LABELS(NAME, END) \
+            INCBIN_ALIGN_BYTE \
+            INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) ":\n" \
+                INCBIN_BYTE "1\n" \
+            INCBIN_GLOBAL_LABELS(NAME, SIZE) \
+            INCBIN_ALIGN_HOST \
+            INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(SIZE) ":\n" \
+                INCBIN_INT INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) " - " \
+                           INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) "\n" \
+    ); \
+    INCBIN_EXTERN(NAME)
+
+#endif
+#endif
Index: azure_iot_hub_riscv/trunk/app_iothub_client/kendryte/kpu.c
===================================================================
--- azure_iot_hub_riscv/trunk/app_iothub_client/kendryte/kpu.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/app_iothub_client/kendryte/kpu.c	(revision 453)
@@ -0,0 +1,1872 @@
+#include <assert.h>
+#include <float.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <kernel_impl.h>
+#include <target_syssvc.h>
+#include "kendryte-k210.h"
+#include "device.h"
+#include "atomic.h"
+#include "kpu.h"
+#include "utils.h"
+#include "kpu_main.h"
+
+#define sil_orw_mem(a, b) sil_wrw_mem((a), sil_rew_mem(a) | (b))
+
+void sysctl_enable_irq(void)
+{
+    set_csr(mie, MIP_MEIP);
+    set_csr(mstatus, MSTATUS_MIE);
+}
+
+void sysctl_disable_irq(void)
+{
+    clear_csr(mie, MIP_MEIP);
+    clear_csr(mstatus, MSTATUS_MIE);
+}
+
+uint64_t sysctl_get_time_us(void)
+{
+    uint64_t v_cycle = read_cycle();
+    return v_cycle * 1000000 / SYSCTRL_CLOCK_FREQ_IN0;
+}
+
+static int is_memory(uintptr_t address)
+{
+    enum
+    {
+        mem_len = 6 * 1024 * 1024,
+        mem_no_cache_len = 8 * 1024 * 1024,
+    };
+    return ((address >= 0x80000000) && (address < 0x80000000 + mem_len)) || ((address >= 0x40000000) && (address < 0x40000000 + mem_no_cache_len)) || (address == 0x50450040);
+}
+
+uint32_t is_memory_cache(uintptr_t address)
+{
+    #define MEM_CACHE_LEN (6 * 1024 * 1024)
+
+    return ((address >= 0x80000000) && (address < 0x80000000 + MEM_CACHE_LEN));
+}
+
+int plic_irq_enable(INTNO irq_number)
+{
+    if (irq_number != INTNO_AI)
+        return -1;
+    ena_int(irq_number);
+    return 0;
+}
+
+int plic_set_priority(INTNO irq_number, uint32_t priority)
+{
+    if (irq_number != INTNO_AI)
+        return -1;
+    set_ipriority(irq_number, priority);
+    return 0;
+}
+
+plic_irq_callback_t ai_done_callback;
+void *ai_done_ctx;
+
+void plic_irq_register(INTNO irq, plic_irq_callback_t callback, void *ctx)
+{
+    ER ret;
+    if (irq != INTNO_AI)
+        return;
+
+    ret = loc_cpu();
+
+    ai_done_callback = callback;
+    ai_done_ctx = ctx;
+
+    if (ret == E_OK)
+        unl_cpu();
+}
+
+void ai_done_isr(intptr_t exinf)
+{
+    sysctl_disable_irq();
+    if (ai_done_callback != NULL){
+        ai_done_callback(ai_done_ctx);
+    }
+    sysctl_enable_irq();
+}
+
+plic_irq_callback_t ai_dma_done_callback;
+void *ai_dma_done_ctx;
+
+void kpu_dmac_irq_register(dmac_channel_number_t channel_num,
+    plic_irq_callback_t dmac_callback, void *ctx, uint32_t priority)
+{
+    ER ret;
+    if (channel_num != AI_DMA_CH)
+        return;
+
+    set_ipriority(INTNO_DMAAI, priority);
+
+    ret = loc_cpu();
+
+    ai_dma_done_callback = dmac_callback;
+    ai_dma_done_ctx = ctx;
+
+    if (ret == E_OK)
+        unl_cpu();
+}
+
+void ai_dma_done_isr(DMA_Handle_t *dma)
+{
+    sysctl_disable_irq();
+    if (ai_dma_done_callback != NULL) {
+        ai_dma_done_callback(ai_dma_done_ctx);
+    }
+    sysctl_enable_irq();
+}
+
+void dmac_set_irq(dmac_channel_number_t channel_num,
+    plic_irq_callback_t dmac_callback, void *ctx, uint32_t priority)
+{
+    ER ret;
+    if (channel_num != AI_DMA_CH)
+        return;
+
+    set_ipriority(INTNO_DMAAI, priority);
+
+    ret = loc_cpu();
+
+    ai_dma_done_callback = dmac_callback;
+    ai_dma_done_ctx = ctx;
+
+    if (ret == E_OK)
+        unl_cpu();
+}
+
+DMA_Handle_t g_ai_hdma;
+
+void dmac_set_single_mode(dmac_channel_number_t channel_num,
+    const void *src, void *dest, uint8_t src_inc,
+    uint8_t dest_inc,
+    uint8_t dmac_burst_size,
+    uint8_t dmac_trans_width,
+    size_t block_size)
+{
+    if (channel_num != AI_DMA_CH)
+        return;
+
+    DMA_Handle_t *hdma = &g_ai_hdma;
+    int mem_type_src = is_memory((uintptr_t)src), mem_type_dest = is_memory((uintptr_t)dest);
+    uint8_t flow_control;
+    if(mem_type_src == 0 && mem_type_dest == 0)
+        flow_control = DMA_PERIPH_TO_PERIPH;
+    else if(mem_type_src == 1 && mem_type_dest == 0)
+        flow_control = DMA_MEMORY_TO_PERIPH;
+    else if(mem_type_src == 0 && mem_type_dest == 1)
+        flow_control = DMA_PERIPH_TO_MEMORY;
+    else
+        flow_control = DMA_MEMORY_TO_MEMORY;
+
+    hdma->Init.Direction    = flow_control;	/* DMA転送方向 */
+    hdma->Init.SrcHandShake = (mem_type_src ? DMAC_HS_SOFTWARE : DMAC_HS_HARDWARE);	/* ソースハンドシェイク */
+    hdma->Init.DrcHandShake = (mem_type_dest ? DMAC_HS_SOFTWARE : DMAC_HS_HARDWARE);	/* デスティネーションハンドシェイク */
+    hdma->Init.SrcInc       = src_inc;	/* ソースインクリメント設定 */
+    hdma->Init.DstInc       = dest_inc;	/* デスティネーションインクリメント設定 */
+    hdma->Init.SrcTransWidth = dmac_trans_width;	/* ソース転送幅 */
+    hdma->Init.DstTransWidth = dmac_trans_width;	/* デスティネーション転送幅 */
+    hdma->Init.SrcBurstSize = dmac_burst_size;	/* ソースバーストサイズ */
+    hdma->Init.DstBurstSize = dmac_burst_size;	/* デスティネーションバーストサイズ */
+    dma_reset(hdma);
+
+    dma_start(hdma, (uintptr_t)src, (uintptr_t)dest, block_size);
+}
+
+#define LAYER_BURST_SIZE 12
+
+#define KPU_DEBUG 0
+#define USE_CACHED_AI_RAM 0
+
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+#define max(a, b) (((a) > (b)) ? (a) : (b))
+#define ALIGN_UP(x, align) ((x + (align - 1)) & (~(align - 1)))
+
+static int ai_step(void *userdata);
+static int kpu_kmodel_done(kpu_model_context_t *ctx);
+
+volatile kpu_config_t *const kpu = (volatile kpu_config_t *)AI_BASE_ADDR;
+static volatile uint32_t kpu_status;
+
+typedef struct kpu_context
+{
+    kpu_task_t kpu_task;
+    uint32_t kpu_status;
+} kpu_context_t;
+
+volatile kpu_context_t g_kpu_context;
+
+static int kpu_run_all_done(void *_task)
+{
+    atomic_swap(&g_kpu_context.kpu_status, 0);
+    kpu_task_t *task = (kpu_task_t *)_task;
+    task->callback(task);
+    return 0;
+}
+
+int kpu_continue(void *_task)
+{
+    kpu_task_t *task = (kpu_task_t *)_task;
+    int layer_burst_size = 1;
+
+    kpu->interrupt_clear.data = (kpu_config_interrupt_t){
+        .calc_done_int = 1,
+        .layer_cfg_almost_empty_int = 1,
+        .layer_cfg_almost_full_int = 1};
+
+    if(task->remain_layers_length == 0)
+    {
+        return 0;
+    }
+    if(task->remain_layers_length <= layer_burst_size)
+    {
+        for(uint32_t i = 0; i < task->remain_layers_length; i++)
+        {
+            kpu->layer_argument_fifo = task->remain_layers[i].interrupt_enabe.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].image_addr.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].image_channel_num.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].image_size.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].kernel_pool_type_cfg.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].kernel_load_cfg.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].kernel_offset.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].kernel_calc_type_cfg.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].write_back_cfg.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].conv_value.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].conv_value2.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].dma_parameter.reg;
+        }
+        task->remain_layers_length = 0;
+    } else
+    {
+        for(uint32_t i = 0; i < layer_burst_size; i++)
+        {
+            kpu->layer_argument_fifo = task->remain_layers[i].interrupt_enabe.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].image_addr.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].image_channel_num.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].image_size.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].kernel_pool_type_cfg.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].kernel_load_cfg.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].kernel_offset.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].kernel_calc_type_cfg.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].write_back_cfg.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].conv_value.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].conv_value2.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].dma_parameter.reg;
+        }
+        task->remain_layers += layer_burst_size;
+        task->remain_layers_length -= layer_burst_size;
+    }
+    return 0;
+}
+
+static int kpu_run_dma_output(uint32_t dma_ch, void *dst, uint32_t length, plic_irq_callback_t cb, void *_task)
+{
+    select_dma_channel(dma_ch, DMA_SELECT_AI_RX_REQ);
+    kpu_dmac_irq_register(dma_ch, kpu_run_all_done, _task, 1);
+    dmac_set_single_mode(dma_ch, (void *)(&kpu->fifo_data_out), (void *)(dst), DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
+                        DMAC_MSIZE_8, DMAC_TRANS_WIDTH_64, (length + 7) / 8);
+    return 0;
+}
+
+static int kpu_run_dma_input_done_push_layers(void *_task)
+{
+    kpu_task_t *task = (kpu_task_t *)_task;
+    kpu->interrupt_clear.reg = 7;
+    dma_end(&g_ai_hdma);
+    kpu->fifo_threshold.data = (kpu_config_fifo_threshold_t){
+        .fifo_full_threshold = 10, .fifo_empty_threshold = 1};
+    kpu->eight_bit_mode.data = (kpu_config_eight_bit_mode_t){
+        .eight_bit_mode = task->eight_bit_mode};
+
+    kpu_layer_argument_t *last_layer = &task->layers[task->layers_length - 1];
+
+    kpu_run_dma_output(task->dma_ch, task->dst, last_layer->dma_parameter.data.dma_total_byte + 1, kpu_run_all_done, task);
+
+    kpu->interrupt_mask.data = (kpu_config_interrupt_t){
+        .calc_done_int = 0,
+        .layer_cfg_almost_empty_int = 0,
+        .layer_cfg_almost_full_int = 1};
+    kpu_continue(task);
+    return 0;
+}
+
+static void kpu_run_dma_input(uint32_t dma_ch, const void *src, plic_irq_callback_t cb, void *_task)
+{
+    kpu_task_t *task = _task;
+    kpu_layer_argument_t *first_layer = &task->layers[0];
+    uint64_t input_size = first_layer->kernel_calc_type_cfg.data.channel_switch_addr * 64 * (first_layer->image_channel_num.data.i_ch_num + 1);
+    kpu_dmac_irq_register(dma_ch, cb, _task, 1);
+    dmac_set_single_mode(dma_ch, (void *)src, (void *)(AI_IO_BASE_ADDR), DMAC_ADDR_INCREMENT, DMAC_ADDR_INCREMENT,
+                        DMAC_MSIZE_16, DMAC_TRANS_WIDTH_64, input_size / 8);
+}
+
+int kpu_run(kpu_task_t *v_task, dmac_channel_number_t dma_ch, const void *src, void *dest, plic_irq_callback_t callback)
+{
+    if(atomic_cas(&g_kpu_context.kpu_status, 0, 1))
+        return -1;
+
+    memcpy((void *)&g_kpu_context.kpu_task, v_task, sizeof(kpu_task_t));
+    kpu_task_t *task = (kpu_task_t *)&g_kpu_context.kpu_task;
+
+    kpu_layer_argument_t *last_layer = &task->layers[task->layers_length - 1];
+
+    uint64_t output_size = last_layer->dma_parameter.data.dma_total_byte + 1;
+
+    last_layer->dma_parameter.data.send_data_out = 1;
+    last_layer->interrupt_enabe.data.int_en = 1;
+
+    task->dma_ch = dma_ch;
+    task->dst = dest;
+    task->dst_length = output_size;
+    task->callback = callback;
+    task->remain_layers_length = task->layers_length;
+    task->remain_layers = task->layers;
+
+    plic_set_priority(INTNO_AI, 1);
+    plic_irq_register(INTNO_AI, kpu_continue, task);
+    plic_irq_enable(INTNO_AI);
+
+    kpu_run_dma_input(dma_ch, src, kpu_run_dma_input_done_push_layers, task);
+
+    return 0;
+}
+
+uint8_t *kpu_get_output_buf(kpu_task_t *task)
+{
+    kpu_layer_argument_t *last_layer = &task->layers[task->layers_length - 1];
+    size_t output_size = ((last_layer->dma_parameter.data.dma_total_byte + 1) + 7) / 8 * 8;
+    return malloc(output_size);
+}
+
+void kpu_release_output_buf(uint8_t *output_buf)
+{
+    if(output_buf != NULL)
+        free(output_buf);
+}
+
+static int kpu_done(void *ctx)
+{
+    atomic_swap(&kpu_status, 0);
+    kpu_task_t *task = (kpu_task_t *)ctx;
+    task->callback(task->ctx);
+    return 0;
+}
+
+static int kpu_config_input(void *ctx)
+{
+    kpu_task_t *task = (kpu_task_t *)ctx;
+    kpu->interrupt_clear.reg = 7;
+    if(task->remain_layers_length <= LAYER_BURST_SIZE)
+    {
+        for(uint32_t i = 0; i < task->remain_layers_length; i++)
+        {
+            kpu->layer_argument_fifo = task->remain_layers[i].interrupt_enabe.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].image_addr.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].image_channel_num.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].image_size.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].kernel_pool_type_cfg.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].kernel_load_cfg.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].kernel_offset.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].kernel_calc_type_cfg.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].write_back_cfg.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].conv_value.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].conv_value2.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].dma_parameter.reg;
+        }
+        task->remain_layers_length = 0;
+        kpu->interrupt_mask.reg = 7;
+    } else
+    {
+        for(uint32_t i = 0; i < LAYER_BURST_SIZE; i++)
+        {
+            kpu->layer_argument_fifo = task->remain_layers[i].interrupt_enabe.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].image_addr.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].image_channel_num.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].image_size.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].kernel_pool_type_cfg.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].kernel_load_cfg.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].kernel_offset.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].kernel_calc_type_cfg.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].write_back_cfg.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].conv_value.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].conv_value2.reg;
+            kpu->layer_argument_fifo = task->remain_layers[i].dma_parameter.reg;
+        }
+        task->remain_layers += LAYER_BURST_SIZE;
+        task->remain_layers_length -= LAYER_BURST_SIZE;
+    }
+    return 0;
+}
+
+static void kpu_data_output(kpu_task_t *task)
+{
+    select_dma_channel(task->dma_ch, DMA_SELECT_AI_RX_REQ);
+    kpu_dmac_irq_register(task->dma_ch, kpu_done, task, 1);
+    dmac_set_single_mode(task->dma_ch, (void *)(&kpu->fifo_data_out), (void *)(task->dst), DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
+                        DMAC_MSIZE_8, DMAC_TRANS_WIDTH_64, task->dst_length);
+}
+
+static int kpu_data_ready(void *ctx)
+{
+    kpu_task_t *task = (kpu_task_t *)ctx;
+
+    dma_end(&g_ai_hdma);
+    kpu_data_output(task);
+
+    kpu->eight_bit_mode.reg = task->eight_bit_mode;
+    kpu->interrupt_mask.reg = 7;
+    kpu->interrupt_clear.reg = 7;
+    kpu->fifo_threshold.data = (kpu_config_fifo_threshold_t){
+        .fifo_full_threshold = 12, .fifo_empty_threshold = 1};
+
+    plic_set_priority(INTNO_AI, 2);
+    plic_irq_register(INTNO_AI, kpu_config_input, task);
+    plic_irq_enable(INTNO_AI);
+    kpu_config_input(task);
+    kpu->interrupt_mask.data = (kpu_config_interrupt_t){
+        .calc_done_int = 1,
+        .layer_cfg_almost_empty_int = 0,
+        .layer_cfg_almost_full_int = 1};
+    return 0;
+}
+
+static void kpu_data_input(kpu_task_t *task)
+{
+    if(task->src == NULL)
+    {
+        kpu_data_ready(task);
+        return;
+    }
+    kpu_dmac_irq_register(task->dma_ch, kpu_data_ready, task, 1);
+    kpu_layer_argument_t *layer = &task->layers[0];
+    dmac_set_single_mode(task->dma_ch, (void *)(uintptr_t)task->src, (void *)(uintptr_t)(AI_IO_BASE_ADDR + layer->image_addr.data.image_src_addr * 64), DMAC_ADDR_INCREMENT, DMAC_ADDR_INCREMENT,
+                        DMAC_MSIZE_16, DMAC_TRANS_WIDTH_64, task->src_length);
+}
+
+int kpu_single_task_init(kpu_task_t *task)
+{
+    /*
+    *  AIクロック有効化
+    */
+    sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_PERI), SYSCTL_CLK_EN_PERI_AI_CLK_EN);
+
+    kpu_layer_argument_t *first_layer = &task->layers[0];
+    kpu_layer_argument_t *last_layer = &task->layers[task->layers_length - 1];
+
+    last_layer->dma_parameter.data.send_data_out = 1;
+    last_layer->interrupt_enabe.data.int_en = 1;
+    task->src_length = first_layer->kernel_calc_type_cfg.data.channel_switch_addr * 64 * (first_layer->image_channel_num.data.i_ch_num + 1) / 8;
+    task->dst_length = ((last_layer->dma_parameter.data.dma_total_byte + 1) + 7) / 8;
+    task->dst = (uint64_t *)malloc(task->dst_length * 8);
+    if(task->dst == NULL)
+        return 1;
+    memset(task->dst, 0, task->dst_length * 8);
+    return 0;
+}
+
+int kpu_single_task_deinit(kpu_task_t *task)
+{
+    free(task->dst);
+    return 0;
+}
+
+int kpu_model_load_from_buffer(kpu_task_t *task, uint8_t *buffer, kpu_model_layer_metadata_t **meta)
+{
+    uintptr_t base_addr = (uintptr_t)buffer;
+    kpu_model_header_t *header = (kpu_model_header_t *)buffer;
+    kpu_model_layer_metadata_t *layer_meta = (kpu_model_layer_metadata_t *)(base_addr + sizeof(kpu_model_header_t));
+    kpu_layer_argument_t *layers = (kpu_layer_argument_t *)(base_addr + header->layers_argument_start);
+
+    if(header->version != 1)
+        return -1;
+    uint32_t layers_length = header->layers_length;
+    task->layers_length = layers_length;
+    task->eight_bit_mode = header->flags & 1;
+    task->layers = layers;
+    task->output_scale = layer_meta[layers_length - 1].output_scale;
+    task->output_bias = layer_meta[layers_length - 1].output_bias;
+    size_t i;
+    for(i = 0; i < layers_length; i++)
+    {
+        layers[i].kernel_load_cfg.data.para_start_addr = (uint64_t)(base_addr + layer_meta[i].weigths_offset);
+        layers[i].kernel_pool_type_cfg.data.bwsx_base_addr = (uint64_t)(base_addr + layer_meta[i].bn_offset);
+        layers[i].kernel_calc_type_cfg.data.active_addr = (uint64_t)(base_addr + layer_meta[i].act_offset);
+    }
+
+    if(meta)
+        *meta = layer_meta;
+    return 0;
+}
+
+int kpu_start(kpu_task_t *task)
+{
+    if(atomic_cas(&kpu_status, 0, 1))
+        return -1;
+
+    task->remain_layers_length = task->layers_length;
+    task->remain_layers = task->layers;
+    kpu_data_input(task);
+    return 0;
+}
+
+static void kpu_send_layer(const kpu_layer_argument_t *layer)
+{
+    kpu->layer_argument_fifo = layer->interrupt_enabe.reg;
+    kpu->layer_argument_fifo = layer->image_addr.reg;
+    kpu->layer_argument_fifo = layer->image_channel_num.reg;
+    kpu->layer_argument_fifo = layer->image_size.reg;
+    kpu->layer_argument_fifo = layer->kernel_pool_type_cfg.reg;
+    kpu->layer_argument_fifo = layer->kernel_load_cfg.reg;
+    kpu->layer_argument_fifo = layer->kernel_offset.reg;
+    kpu->layer_argument_fifo = layer->kernel_calc_type_cfg.reg;
+    kpu->layer_argument_fifo = layer->write_back_cfg.reg;
+    kpu->layer_argument_fifo = layer->conv_value.reg;
+    kpu->layer_argument_fifo = layer->conv_value2.reg;
+    kpu->layer_argument_fifo = layer->dma_parameter.reg;
+}
+
+void kpu_init(int eight_bit_mode, plic_irq_callback_t callback, void *userdata)
+{
+    kpu->interrupt_clear.reg = 7;
+    kpu->fifo_threshold.data = (kpu_config_fifo_threshold_t){
+        .fifo_full_threshold = 10, .fifo_empty_threshold = 1};
+    kpu->eight_bit_mode.data = (kpu_config_eight_bit_mode_t){
+        .eight_bit_mode = eight_bit_mode};
+    kpu->interrupt_mask.data = (kpu_config_interrupt_t){
+        .calc_done_int = 1,
+        .layer_cfg_almost_empty_int = 0,
+        .layer_cfg_almost_full_int = 1};
+
+    plic_set_priority(INTNO_AI, 1);
+    plic_irq_register(INTNO_AI, callback, userdata);
+    plic_irq_enable(INTNO_AI);
+}
+
+void kpu_input_dma(const kpu_layer_argument_t *layer, const uint8_t *src, dmac_channel_number_t dma_ch, plic_irq_callback_t callback, void *userdata)
+{
+    uint64_t input_size = layer->kernel_calc_type_cfg.data.channel_switch_addr * 64 * (layer->image_channel_num.data.i_ch_num + 1);
+    dmac_set_irq(dma_ch, callback, userdata, 1);
+    dmac_set_single_mode(dma_ch, (void *)src, (void *)(uintptr_t)(AI_IO_BASE_ADDR + layer->image_addr.data.image_src_addr * 64), DMAC_ADDR_INCREMENT, DMAC_ADDR_INCREMENT,
+                        DMAC_MSIZE_16, DMAC_TRANS_WIDTH_64, input_size / 8);
+}
+
+static void kpu_conv2d_core(kpu_layer_argument_t *layer)
+{
+    kpu_send_layer(layer);
+}
+
+void kpu_conv2d(kpu_layer_argument_t *layer)
+{
+    kpu->interrupt_clear.data = (kpu_config_interrupt_t){
+        .calc_done_int = 1,
+        .layer_cfg_almost_empty_int = 1,
+        .layer_cfg_almost_full_int = 1};
+    kpu->interrupt_mask.data = (kpu_config_interrupt_t){
+        .calc_done_int = 1,
+        .layer_cfg_almost_empty_int = 0,
+        .layer_cfg_almost_full_int = 1};
+    kpu_conv2d_core(layer);
+}
+
+void kpu_conv2d_output(kpu_layer_argument_t *layer, dmac_channel_number_t dma_ch, uint8_t *dest, plic_irq_callback_t callback, void *userdata)
+{
+    kpu->interrupt_clear.data = (kpu_config_interrupt_t){
+        .calc_done_int = 1,
+        .layer_cfg_almost_empty_int = 1,
+        .layer_cfg_almost_full_int = 1};
+    kpu->interrupt_mask.data = (kpu_config_interrupt_t){
+        .calc_done_int = 1,
+        .layer_cfg_almost_empty_int = 1,
+        .layer_cfg_almost_full_int = 1};
+    layer->dma_parameter.data.send_data_out = 1;
+    select_dma_channel(dma_ch, DMA_SELECT_AI_RX_REQ);
+    dmac_set_irq(dma_ch, callback, userdata, 1);
+    dmac_set_single_mode(dma_ch, (void *)(&kpu->fifo_data_out), dest, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
+                        DMAC_MSIZE_8, DMAC_TRANS_WIDTH_64, (layer->dma_parameter.data.dma_total_byte + 8) / 8);
+    kpu_conv2d_core(layer);
+}
+
+void kpu_conv2d_output_full_add(kpu_layer_argument_t *layer, dmac_channel_number_t dma_ch, uint64_t *dest, plic_irq_callback_t callback, void *userdata)
+{
+    uint32_t channels = layer->image_channel_num.data.o_ch_num + 1;
+    layer->interrupt_enabe.data.full_add = 1;
+
+    kpu->interrupt_clear.data = (kpu_config_interrupt_t){
+        .calc_done_int = 1,
+        .layer_cfg_almost_empty_int = 1,
+        .layer_cfg_almost_full_int = 1};
+    kpu->interrupt_mask.data = (kpu_config_interrupt_t){
+        .calc_done_int = 1,
+        .layer_cfg_almost_empty_int = 1,
+        .layer_cfg_almost_full_int = 1};
+    layer->dma_parameter.data.send_data_out = 1;
+    select_dma_channel(dma_ch, DMA_SELECT_AI_RX_REQ);
+    dmac_set_irq(dma_ch, callback, userdata, 1);
+    dmac_set_single_mode(dma_ch, (void *)(&kpu->fifo_data_out), dest, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
+                        DMAC_MSIZE_8, DMAC_TRANS_WIDTH_64, channels);
+    kpu_conv2d_core(layer);
+}
+
+void kpu_add(const uint8_t *src1, const quantize_param_t *src1_param, const uint8_t *src2, const quantize_param_t *src2_param, size_t count, uint8_t *dest, const quantize_param_t *dest_param)
+{
+    quantize_param_t q1 = *src1_param, q2 = *src2_param, q3 = *dest_param;
+
+    size_t i;
+    for(i = 0; i < count; i++)
+    {
+        int value = ((*src1++ * q1.scale + q1.bias + *src2++ * q2.scale + q2.bias) - q3.bias) / q3.scale;
+        if(value < 0)
+            value = 0;
+        if(value > 0xFF)
+            value = 0xFF;
+        *dest++ = value;
+    }
+}
+
+void kpu_global_average_pool(const uint8_t *src, const quantize_param_t *src_param, int kernel_size, int channels, uint8_t *dest, const quantize_param_t *dest_param)
+{
+    quantize_param_t q1 = *src_param, q2 = *dest_param;
+    size_t oc, y, x;
+
+    if(((uintptr_t)dest) >= AI_IO_BASE_ADDR && ((uintptr_t)dest) < AI_IO_BASE_ADDR + 2 * 1024 * 1024)
+    {
+        uint32_t row_padding = 16;
+        uint32_t row_group = 4;
+        uint32_t row_length = 1;
+        uint32_t height = 4;
+
+        for(oc = 0; oc < channels; oc++)
+        {
+            uint8_t *channel_origin = dest + oc / row_group * row_length * height * 64 + oc % row_group * row_padding;
+            for(y = 0; y < 1; y++)
+            {
+                uint8_t *y_origin = channel_origin + y * row_length * 64;
+                for(x = 0; x < 1; x++)
+                {
+                    int64_t sum = 0;
+                    size_t i;
+                    for(i = 0; i < kernel_size; i++)
+                        sum += *src++;
+
+                    int value = ((sum * q1.scale + q1.bias) / kernel_size - q2.bias) / q2.scale;
+                    if(value < 0)
+                        value = 0;
+                    if(value > 0xFF)
+                        value = 0xFF;
+                    y_origin[x] = value;
+                }
+            }
+        }
+    } else
+    {
+        for(oc = 0; oc < channels; oc++)
+        {
+            int64_t sum = 0;
+            size_t i;
+            for(i = 0; i < kernel_size; i++)
+                sum += *src++;
+
+            int value = ((sum * q1.scale + q1.bias) / kernel_size - q2.bias) / q2.scale;
+            if(value < 0)
+                value = 0;
+            if(value > 0xFF)
+                value = 0xFF;
+            dest[oc] = value;
+        }
+    }
+}
+
+void kpu_global_average_pool_float(const uint8_t *src, const quantize_param_t *src_param, int kernel_size, int channels, float *dest)
+{
+    quantize_param_t q = *src_param;
+    size_t oc;
+
+    for(oc = 0; oc < channels; oc++)
+    {
+        int64_t sum = 0;
+        size_t i;
+        for(i = 0; i < kernel_size; i++)
+            sum += *src++;
+
+        float value = (sum * q.scale + q.bias) / kernel_size;
+        dest[oc] = value;
+    }
+}
+
+void kpu_matmul_end(const uint8_t *src, int channels, float *dest, const quantize_param_t *dest_param)
+{
+    quantize_param_t q1 = *dest_param;
+    size_t i = 0;
+    for(i = 0; i < channels; i++)
+        *dest++ = src[i * 16] * q1.scale + q1.bias;
+}
+
+void kpu_fully_connected(const float *src, const float *weights, const float *biases, float *dest, int input_channels, int output_channels)
+{
+    int ic, oc;
+    for(oc = 0; oc < output_channels; oc++)
+    {
+        const float *c_weights = weights + oc * input_channels;
+
+        float sum = 0.0f;
+        for(ic = 0; ic < input_channels; ic++)
+            sum += src[ic] * c_weights[ic];
+        dest[oc] = sum + biases[oc];
+    }
+}
+
+void kpu_dequantize(const uint8_t *src, const quantize_param_t *src_param, size_t count, float *dest)
+{
+    quantize_param_t q1 = *src_param;
+    size_t i = 0;
+    for(i = 0; i < count; i++)
+        *dest++ = src[i] * q1.scale + q1.bias;
+}
+
+void kpu_input_with_padding(kpu_layer_argument_t *layer, const uint8_t *src, int width, int height, int channels)
+{
+    uint8_t *dest = (uint8_t *)(uintptr_t)(AI_IO_BASE_ADDR + layer->image_addr.data.image_src_addr * 64);
+    size_t oc, y, x;
+
+    uint32_t row_padding;
+    uint32_t row_group;
+    uint32_t row_length;
+
+    if(width <= 16)
+    {
+        row_padding = 16;
+        row_group = 4;
+        row_length = 1;
+    } else if(width <= 32)
+    {
+        row_padding = 32;
+        row_group = 2;
+        row_length = 1;
+    } else
+    {
+        row_padding = 64;
+        row_group = 1;
+        row_length = (width + 63) / 64;
+    }
+
+    for(oc = 0; oc < channels; oc++)
+    {
+        uint8_t *channel_origin = dest + oc / row_group * row_length * height * 64 + oc % row_group * row_padding;
+        for(y = 0; y < height; y++)
+        {
+            uint8_t *y_origin = channel_origin + y * row_length * 64;
+            for(x = 0; x < width; x++)
+                y_origin[x] = *src++;
+        }
+    }
+}
+#if USE_CACHED_AI_RAM
+static void kpu_flush_cache(uint32_t addr, size_t lines)
+{
+    size_t line;
+    for(line = 0; line < lines; line++)
+    {
+        const uint64_t *src = (const uint64_t *)(AI_RAM_BASE_ADDR + (addr + line) * 64);
+        uint64_t *dest = (uint64_t *)(AI_IO_BASE_ADDR + (addr + line) * 64);
+        size_t i;
+        for(i = 0; i < 8; i++)
+            dest[i] = src[i];
+    }
+}
+#endif
+static int64_t kpu_carry_shift(int64_t value, uint32_t shift)
+{
+    if(shift > 0)
+    {
+        value >>= shift - 1;
+        if(value & 0x1)
+        {
+            if(value < 0)
+                value = (value >> 1) - 1;
+            else
+                value = (value >> 1) + 1;
+        } else
+        {
+            value >>= 1;
+        }
+    }
+
+    return value;
+}
+static void kpu_upload_core(size_t width, size_t height, size_t channels, const uint8_t *src, uint32_t kpu_addr)
+{
+    uint8_t *dest = (uint8_t *)(uintptr_t)(AI_IO_BASE_ADDR + kpu_addr * 64);
+    size_t oc, y, x;
+    uint32_t row_padding;
+    uint32_t row_group;
+    uint32_t row_length;
+    if(width <= 16)
+    {
+        row_padding = 16;
+        row_group = 4;
+        row_length = 1;
+    } else if(width <= 32)
+    {
+        row_padding = 32;
+        row_group = 2;
+        row_length = 1;
+    } else
+    {
+        row_padding = 64;
+        row_group = 1;
+        row_length = (width + 63) / 64;
+    }
+
+    if((uintptr_t)src % 8 == 0 && width % 8 == 0)
+    {
+#define UPLOAD_BEGIN()                                                                                             \
+    for(oc = 0; oc < channels; oc++)                                                                               \
+    {                                                                                                              \
+        uint8_t *channel_origin = dest + oc / row_group * row_length * height * 64 + oc % row_group * row_padding; \
+        for(y = 0; y < height; y++)                                                                                \
+        {                                                                                                          \
+            uint64_t *y_origin = (uint64_t *)(channel_origin + y * row_length * 64);
+
+#define UPLOAD_END() \
+    }                \
+    }
+
+        width /= 8;
+        const uint64_t *u64_src = (const uint64_t *)src;
+        if(width == 1)
+        {
+            UPLOAD_BEGIN()
+            y_origin[0] = *u64_src++;
+            UPLOAD_END()
+        } else if(width == 2)
+        {
+            UPLOAD_BEGIN()
+            {
+                y_origin[0] = *u64_src++;
+                y_origin[1] = *u64_src++;
+            }
+            UPLOAD_END()
+        } else if(width == 4)
+        {
+            UPLOAD_BEGIN()
+            {
+                y_origin[0] = *u64_src++;
+                y_origin[1] = *u64_src++;
+                y_origin[2] = *u64_src++;
+                y_origin[3] = *u64_src++;
+            }
+            UPLOAD_END()
+        } else
+        {
+            UPLOAD_BEGIN()
+            for(x = 0; x < width; x++)
+                y_origin[x] = *u64_src++;
+            UPLOAD_END()
+        }
+    } else
+    {
+        for(oc = 0; oc < channels; oc++)
+        {
+            uint8_t *channel_origin = dest + oc / row_group * row_length * height * 64 + oc % row_group * row_padding;
+            for(y = 0; y < height; y++)
+            {
+                uint8_t *y_origin = channel_origin + y * row_length * 64;
+                for(x = 0; x < width; x++)
+                    y_origin[x] = *src++;
+            }
+        }
+    }
+}
+static void kpu_kmodel_input_with_padding(const kpu_layer_argument_t *layer, const uint8_t *src)
+{
+    size_t width = layer->image_size.data.i_row_wid + 1;
+    size_t height = layer->image_size.data.i_col_high + 1;
+    size_t channels = layer->image_channel_num.data.i_ch_num + 1;
+
+    kpu_upload_core(width, height, channels, src, layer->image_addr.data.image_src_addr);
+}
+
+static void kpu_kmodel_input_float(const float *src, float *dest, size_t count)
+{
+    memcpy(dest, src, count * sizeof(float));
+}
+
+static void kpu_float_activation(float *data, size_t count, kpu_model_activation_t act)
+{
+    size_t i;
+
+    if(act == KLA_RELU)
+    {
+        for(i = 0; i < count; i++)
+            data[i] = max(data[i], 0);
+    } else if(act == KLA_RELU6)
+    {
+        for(i = 0; i < count; i++)
+            data[i] = min(max(data[i], 0), 6);
+    }
+}
+
+static void kpu_kmodel_add(const kpu_model_add_layer_argument_t *arg, kpu_model_context_t *ctx)
+{
+    const float *src_a = (const float *)(ctx->main_buffer + arg->main_mem_in_a_address);
+    const float *src_b = (const float *)(ctx->main_buffer + arg->main_mem_in_b_address);
+    float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address);
+    size_t i, count = arg->count;
+
+    for(i = 0; i < count; i++)
+        dest[i] = src_a[i] + src_b[i];
+}
+
+static void kpu_quantized_add(const kpu_model_quant_add_layer_argument_t *arg, kpu_model_context_t *ctx)
+{
+    const uint8_t *src_a = (const uint8_t *)(ctx->main_buffer + arg->main_mem_in_a_address);
+    const uint8_t *src_b = (const uint8_t *)(ctx->main_buffer + arg->main_mem_in_b_address);
+    size_t count = ALIGN_UP(arg->count, 8) / 8;
+    int64_t off_a = arg->in_a_offset, mul_a = arg->in_a_mul, sh_a = arg->in_a_shift;
+    int64_t off_b = arg->in_b_offset, mul_b = arg->in_b_mul, sh_b = arg->in_b_shift;
+    int64_t off_o = arg->out_offset, mul_o = arg->out_mul, sh_o = arg->out_shift;
+
+    uint8_t *dest = (uint8_t *)(ctx->main_buffer + arg->main_mem_out_address);
+    size_t i;
+
+    if(sh_a == sh_b)
+    {
+#define QADD_UNROLL_1(x)     \
+    int64_t a##x = *src_a++; \
+    int64_t b##x = *src_b++;
+
+#define QADD_UNROLL_2(x) \
+    a##x += off_a;       \
+    b##x += off_b;
+
+#define QADD_UNROLL_3(x) \
+    a##x *= mul_a;       \
+    b##x *= mul_b;
+
+#define QADD_UNROLL_4(x) \
+    int64_t v##x = a##x + b##x;
+
+#define QADD_UNROLL_5(x) \
+    v##x >>= sh_a;
+
+#define QADD_UNROLL_6(x) \
+    v##x *= mul_o;
+
+#define QADD_UNROLL_7(x) \
+    v##x = kpu_carry_shift(v##x, sh_o);
+
+#define QADD_UNROLL_8(x) \
+    v##x += off_o;
+
+#define QADD_UNROLL_9(x) \
+    v##x = min(0xFF, max(0, v##x));
+
+#define QADD_UNROLL_10(x) \
+    *dest++ = v##x;
+
+#define QADD_UNROLL_S(x)                       \
+    QADD_UNROLL_##x(0)                         \
+        QADD_UNROLL_##x(1)                     \
+            QADD_UNROLL_##x(2)                 \
+                QADD_UNROLL_##x(3)             \
+                    QADD_UNROLL_##x(4)         \
+                        QADD_UNROLL_##x(5)     \
+                            QADD_UNROLL_##x(6) \
+                                QADD_UNROLL_##x(7)
+
+        for(i = 0; i < count; i++)
+        {
+            QADD_UNROLL_S(1);
+            QADD_UNROLL_S(2);
+            QADD_UNROLL_S(3);
+            QADD_UNROLL_S(4);
+            QADD_UNROLL_S(5);
+            QADD_UNROLL_S(6);
+            QADD_UNROLL_S(7);
+            QADD_UNROLL_S(8);
+            QADD_UNROLL_S(9);
+            QADD_UNROLL_S(10);
+        }
+    } else
+    {
+#undef QADD_UNROLL_1
+#define QADD_UNROLL_1(x)     \
+    int64_t a##x = *src_a++; \
+    int64_t b##x = *src_b++;
+
+#undef QADD_UNROLL_2
+#define QADD_UNROLL_2(x) \
+    a##x += off_a;       \
+    b##x += off_b;
+
+#undef QADD_UNROLL_3
+#define QADD_UNROLL_3(x) \
+    a##x *= mul_a;       \
+    b##x *= mul_b;
+
+#undef QADD_UNROLL_4
+#define QADD_UNROLL_4(x) \
+    a##x >>= sh_a;       \
+    b##x >>= sh_b;
+
+#undef QADD_UNROLL_5
+#define QADD_UNROLL_5(x) \
+    int64_t v##x = a##x + b##x;
+
+#undef QADD_UNROLL_6
+#define QADD_UNROLL_6(x) \
+    v##x *= mul_o;
+
+#undef QADD_UNROLL_7
+#define QADD_UNROLL_7(x) \
+    v##x = kpu_carry_shift(v##x, sh_o);
+
+#undef QADD_UNROLL_8
+#define QADD_UNROLL_8(x) \
+    v##x += off_o;
+
+#undef QADD_UNROLL_9
+#define QADD_UNROLL_9(x) \
+    v##x = min(0xFF, max(0, v##x));
+
+#undef QADD_UNROLL_10
+#define QADD_UNROLL_10(x) \
+    *dest++ = v##x;
+
+#undef QADD_UNROLL_S
+#define QADD_UNROLL_S(x)                       \
+    QADD_UNROLL_##x(0)                         \
+        QADD_UNROLL_##x(1)                     \
+            QADD_UNROLL_##x(2)                 \
+                QADD_UNROLL_##x(3)             \
+                    QADD_UNROLL_##x(4)         \
+                        QADD_UNROLL_##x(5)     \
+                            QADD_UNROLL_##x(6) \
+                                QADD_UNROLL_##x(7)
+
+        for(i = 0; i < count; i++)
+        {
+            QADD_UNROLL_S(1);
+            QADD_UNROLL_S(2);
+            QADD_UNROLL_S(3);
+            QADD_UNROLL_S(4);
+            QADD_UNROLL_S(5);
+            QADD_UNROLL_S(6);
+            QADD_UNROLL_S(7);
+            QADD_UNROLL_S(8);
+            QADD_UNROLL_S(9);
+            QADD_UNROLL_S(10);
+        }
+    }
+}
+
+static void kpu_global_average_pool2d(const kpu_model_gap2d_layer_argument_t *arg, kpu_model_context_t *ctx)
+{
+    const float *src = (const float *)(ctx->main_buffer + arg->main_mem_in_address);
+    float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address);
+    size_t oc, channels = arg->channels, kernel_size = arg->kernel_size;
+
+    for(oc = 0; oc < channels; oc++)
+    {
+        float sum = 0.f;
+        size_t i;
+        for(i = 0; i < kernel_size; i++)
+            sum += *src++;
+
+        dest[oc] = sum / kernel_size;
+    }
+}
+
+static void kpu_quantized_max_pool2d(const kpu_model_quant_max_pool2d_layer_argument_t *arg, kpu_model_context_t *ctx)
+{
+    const uint8_t *src = (const uint8_t *)(ctx->main_buffer + arg->main_mem_in_address);
+    uint8_t *dest = (uint8_t *)(ctx->main_buffer + arg->main_mem_out_address);
+    kpu_model_shape_t in_shape = arg->in_shape, out_shape = arg->out_shape;
+    uint32_t kernel_width = arg->kernel_width, kernel_height = arg->kernel_height;
+    uint32_t stride_width = arg->stride_width, stride_height = arg->stride_height;
+    uint32_t padding_width = arg->padding_width, padding_height = arg->padding_height;
+
+    uint32_t out_y, out_x, oc;
+
+    for(oc = 0; oc < out_shape.channels; oc++)
+    {
+        const uint8_t *channel_src = src + in_shape.width * in_shape.height * oc;
+        for(out_y = 0; out_y < out_shape.height; out_y++)
+        {
+            for(out_x = 0; out_x < out_shape.width; out_x++)
+            {
+                int32_t in_x_origin = (int32_t)(out_x * stride_width) - padding_width;
+                int32_t in_y_origin = (int32_t)(out_y * stride_height) - padding_height;
+                int32_t kernel_x_start = max(0, -in_x_origin);
+                int32_t kernel_x_end = min(kernel_width, in_shape.width - in_x_origin);
+                int32_t kernel_y_start = max(0, -in_y_origin);
+                int32_t kernel_y_end = min(kernel_height, in_shape.height - in_y_origin);
+                uint8_t value = 0;
+
+                int32_t kernel_y, kernel_x;
+                for(kernel_y = kernel_y_start; kernel_y < kernel_y_end; kernel_y++)
+                {
+                    for(kernel_x = kernel_x_start; kernel_x < kernel_x_end; kernel_x++)
+                    {
+                        int32_t in_x = in_x_origin + kernel_x;
+                        int32_t in_y = in_y_origin + kernel_y;
+                        value = max(value, channel_src[in_y * in_shape.width + in_x]);
+                    }
+                }
+
+                *dest++ = value;
+            }
+        }
+    }
+}
+
+static void kpu_average_pool2d(const kpu_model_ave_pool2d_layer_argument_t *arg, kpu_model_context_t *ctx)
+{
+    const float *src = (const float *)(ctx->main_buffer + arg->main_mem_in_address);
+    float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address);
+    kpu_model_shape_t in_shape = arg->in_shape, out_shape = arg->out_shape;
+    uint32_t kernel_width = arg->kernel_width, kernel_height = arg->kernel_height;
+    uint32_t stride_width = arg->stride_width, stride_height = arg->stride_height;
+    uint32_t padding_width = arg->padding_width, padding_height = arg->padding_height;
+
+    uint32_t out_y, out_x, oc;
+
+    for(oc = 0; oc < out_shape.channels; oc++)
+    {
+        const float *channel_src = src + in_shape.width * in_shape.height * oc;
+        for(out_y = 0; out_y < out_shape.height; out_y++)
+        {
+            for(out_x = 0; out_x < out_shape.width; out_x++)
+            {
+                int32_t in_x_origin = (int32_t)(out_x * stride_width) - padding_width;
+                int32_t in_y_origin = (int32_t)(out_y * stride_height) - padding_height;
+                int32_t kernel_x_start = max(0, -in_x_origin);
+                int32_t kernel_x_end = min(kernel_width, in_shape.width - in_x_origin);
+                int32_t kernel_y_start = max(0, -in_y_origin);
+                int32_t kernel_y_end = min(kernel_height, in_shape.height - in_y_origin);
+                float value = 0;
+                float kernel_count = 0;
+
+                int32_t kernel_y, kernel_x;
+                for(kernel_y = kernel_y_start; kernel_y < kernel_y_end; kernel_y++)
+                {
+                    for(kernel_x = kernel_x_start; kernel_x < kernel_x_end; kernel_x++)
+                    {
+                        int32_t in_x = in_x_origin + kernel_x;
+                        int32_t in_y = in_y_origin + kernel_y;
+                        value += channel_src[in_y * in_shape.width + in_x];
+                        kernel_count++;
+                    }
+                }
+
+                *dest++ = value / kernel_count;
+            }
+        }
+    }
+}
+
+static void kpu_quantize(const kpu_model_quantize_layer_argument_t *arg, kpu_model_context_t *ctx)
+{
+    size_t count = arg->count;
+    const float *src = (const float *)(ctx->main_buffer + arg->main_mem_in_address);
+
+    kpu_model_quant_param_t q = arg->quant_param;
+
+    float scale = 1.f / q.scale;
+
+    uint8_t *dest = (uint8_t *)(ctx->main_buffer + arg->mem_out_address);
+    size_t i;
+    for(i = 0; i < count; i++)
+    {
+        int value = roundf((*src++ - q.bias) * scale);
+        if(value < 0)
+            value = 0;
+        if(value > 0xFF)
+            value = 0xFF;
+        *dest++ = (uint8_t)value;
+    }
+}
+
+static void kpu_kmodel_dequantize(const kpu_model_dequantize_layer_argument_t *arg, kpu_model_context_t *ctx)
+{
+    const uint8_t *src = (const uint8_t *)(ctx->main_buffer + arg->main_mem_in_address);
+    float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address);
+    size_t oc, count = arg->count;
+    kpu_model_quant_param_t q = arg->quant_param;
+
+    for(oc = 0; oc < count; oc++)
+        dest[oc] = *src++ * q.scale + q.bias;
+}
+
+static void kpu_kmodel_channelwise_dequantize(const kpu_model_channelwise_dequant_argument_t *arg, kpu_model_context_t *ctx)
+{
+    const uint8_t *src = (const uint8_t *)(ctx->main_buffer + arg->main_mem_in_address);
+    float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address);
+    size_t oc, i, channels = arg->channels, count = arg->channel_size;
+
+    for(oc = 0; oc < channels; oc++)
+    {
+        const kpu_model_quant_param_t q = arg->quant_params[oc];
+
+        for(i = 0; i < count; i++)
+            *dest++ = *src++ * q.scale + q.bias;
+    }
+}
+
+static void kpu_requantize(const kpu_model_requantize_layer_argument_t *arg, kpu_model_context_t *ctx)
+{
+    const uint8_t *src = (const uint8_t *)(ctx->main_buffer + arg->main_mem_in_address);
+    uint8_t *dest = (uint8_t *)(ctx->main_buffer + arg->main_mem_out_address);
+    size_t oc, count = arg->count;
+    const uint8_t *table = arg->table;
+
+    if(false && count % 8 == 0)
+    {
+        for(oc = 0; oc < count;)
+        {
+            dest[oc++] = table[*src++];
+            dest[oc++] = table[*src++];
+            dest[oc++] = table[*src++];
+            dest[oc++] = table[*src++];
+            dest[oc++] = table[*src++];
+            dest[oc++] = table[*src++];
+            dest[oc++] = table[*src++];
+            dest[oc++] = table[*src++];
+        }
+    } else
+    {
+        for(oc = 0; oc < count; oc++)
+            dest[oc] = table[src[oc]];
+    }
+}
+
+static void kpu_l2_normalization(const kpu_model_l2_norm_layer_argument_t *arg, kpu_model_context_t *ctx)
+{
+    const float *src = (const float *)(ctx->main_buffer + arg->main_mem_in_address);
+    float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address);
+    size_t oc, channels = arg->channels;
+
+    float sum = 0.f;
+    const float epsilon = 1e-10f;
+    for(oc = 0; oc < channels; oc++)
+        sum += src[oc] * src[oc];
+    if(sum < epsilon)
+        sum = epsilon;
+    sum = 1.f / sqrtf(sum);
+    for(oc = 0; oc < channels; oc++)
+        dest[oc] = src[oc] * sum;
+}
+
+static void kpu_softmax(const kpu_model_softmax_layer_argument_t *arg, kpu_model_context_t *ctx)
+{
+    const float *src = (const float *)(ctx->main_buffer + arg->main_mem_in_address);
+    float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address);
+    size_t oc, channels = arg->channels;
+
+    float max = FLT_MIN;
+    for(oc = 0; oc < channels; oc++)
+        max = fmaxf(max, src[oc]);
+
+    float sum = 0.f;
+    for(oc = 0; oc < channels; oc++)
+    {
+        float value = expf(src[oc] - max);
+        sum += value;
+        dest[oc] = value;
+    }
+
+    for(oc = 0; oc < channels; oc++)
+        dest[oc] /= sum;
+}
+
+static void kpu_concat(const kpu_model_concat_layer_argument_t *arg, kpu_model_context_t *ctx)
+{
+    uint8_t *dest = (uint8_t *)(ctx->main_buffer + arg->main_mem_out_address);
+    uint32_t count = arg->input_count, i;
+
+    for(i = 0; i < count; i++)
+    {
+        kpu_model_memory_range_t input = arg->inputs_mem[i];
+        const uint8_t *src = (const uint8_t *)(ctx->main_buffer + input.start);
+        memcpy(dest, src, input.size);
+        dest += input.size;
+    }
+}
+
+static void kpu_kmodel_fully_connected(const kpu_model_fully_connected_layer_argument_t *arg, kpu_model_context_t *ctx)
+{
+    const float *src = (const float *)(ctx->main_buffer + arg->main_mem_in_address);
+    float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address);
+    uint32_t in_channels = arg->in_channels, out_channels = arg->out_channels, ic, oc;
+    float *weights = (float *)malloc(in_channels * out_channels * sizeof(float));
+    float *bias = (float *)malloc(out_channels * sizeof(float));
+    memcpy(weights, arg->weights, out_channels * in_channels * sizeof(float));
+    memcpy(bias, arg->weights + in_channels * out_channels, out_channels * sizeof(float));
+
+    if(in_channels % 8 == 0)
+    {
+#define FC_UNROLL_1(x)     \
+    float i##x = *c_src++; \
+    float w##x = *c_weights++;
+
+#define FC_UNROLL_2(x) \
+    sum += i##x * w##x;
+
+#define FC_UNROLL_S(x)                       \
+    FC_UNROLL_##x(0)                         \
+        FC_UNROLL_##x(1)                     \
+            FC_UNROLL_##x(2)                 \
+                FC_UNROLL_##x(3)             \
+                    FC_UNROLL_##x(4)         \
+                        FC_UNROLL_##x(5)     \
+                            FC_UNROLL_##x(6) \
+                                FC_UNROLL_##x(7)
+
+        for(oc = 0; oc < out_channels; oc++)
+        {
+            const float *c_src = src;
+            const float *c_weights = weights + oc * in_channels;
+
+            float sum = 0.0f;
+            for(ic = 0; ic < in_channels / 8; ic++)
+            {
+                FC_UNROLL_S(1);
+                FC_UNROLL_S(2);
+            }
+
+            dest[oc] = sum + bias[oc];
+        }
+    } else
+    {
+        for(oc = 0; oc < out_channels; oc++)
+        {
+            const float *c_weights = weights + oc * in_channels;
+
+            float sum = 0.0f;
+            for(ic = 0; ic < in_channels; ic++)
+                sum += src[ic] * c_weights[ic];
+            dest[oc] = sum + bias[oc];
+        }
+    }
+    free(weights);
+    free(bias);
+    kpu_float_activation(dest, out_channels, arg->act);
+}
+
+static void kpu_tf_flatten(const kpu_model_tf_flatten_layer_argument_t *arg, kpu_model_context_t *ctx)
+{
+    const float *src = (const float *)(ctx->main_buffer + arg->main_mem_in_address);
+    float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address);
+    kpu_model_shape_t in_shape = arg->shape;
+    uint32_t oc, oy, ox;
+
+    for(oy = 0; oy < in_shape.height; oy++)
+        for(ox = 0; ox < in_shape.width; ox++)
+            for(oc = 0; oc < in_shape.channels; oc++)
+                *dest++ = src[(oc * in_shape.height + oy) * in_shape.width + ox];
+}
+
+static void kpu_resize_nearest_neighbor(const kpu_model_resize_nearest_neighbor_layer_argument_t *arg, kpu_model_context_t *ctx)
+{
+    const float *src = (const float *)(ctx->main_buffer + arg->main_mem_in_address);
+    float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address);
+    kpu_model_shape_t in_shape = arg->in_shape;
+    uint32_t out_width = arg->out_width, out_height = arg->out_height;
+    uint32_t oc, oy, ox;
+
+    float height_scale = (float)in_shape.height / out_height;
+    float width_scale = (float)in_shape.width / out_width;
+
+    for(oc = 0; oc < in_shape.channels; oc++)
+    {
+        const float *channel_src = src + in_shape.width * in_shape.height * oc;
+        for(oy = 0; oy < out_height; oy++)
+        {
+            uint32_t in_y = (uint32_t)min(floorf(oy * height_scale), in_shape.height - 1);
+            const float *y_origin = channel_src + in_y * in_shape.width;
+            for(ox = 0; ox < out_width; ox++)
+            {
+                uint32_t in_x = (uint32_t)min(floorf(ox * width_scale), in_shape.width - 1);
+                *dest++ = y_origin[in_x];
+            }
+        }
+    }
+}
+
+static void kpu_quant_resize_nearest_neighbor(const kpu_model_quant_resize_nearest_neighbor_layer_argument_t *arg, kpu_model_context_t *ctx)
+{
+    const uint8_t *src = (const uint8_t *)(ctx->main_buffer + arg->main_mem_in_address);
+    uint8_t *dest = (uint8_t *)(ctx->main_buffer + arg->main_mem_out_address);
+    kpu_model_shape_t in_shape = arg->in_shape;
+    uint32_t out_width = arg->out_width, out_height = arg->out_height;
+    uint32_t oc, oy, ox;
+
+    float height_scale = (float)in_shape.height / out_height;
+    float width_scale = (float)in_shape.width / out_width;
+
+    for(oc = 0; oc < in_shape.channels; oc++)
+    {
+        const uint8_t *channel_src = src + in_shape.width * in_shape.height * oc;
+        for(oy = 0; oy < out_height; oy++)
+        {
+            uint32_t in_y = (uint32_t)min(floorf(oy * height_scale), in_shape.height - 1);
+            const uint8_t *y_origin = channel_src + in_y * in_shape.width;
+            for(ox = 0; ox < out_width; ox++)
+            {
+                uint32_t in_x = (uint32_t)min(floorf(ox * width_scale), in_shape.width - 1);
+                *dest++ = y_origin[in_x];
+            }
+        }
+    }
+}
+
+static void kpu_logistic(const kpu_model_logistic_layer_argument_t *arg, kpu_model_context_t *ctx)
+{
+    const float *src = (const float *)(ctx->main_buffer + arg->main_mem_in_address);
+    float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address);
+    size_t oc, channels = arg->channels;
+
+    for(oc = 0; oc < channels; oc++)
+        dest[oc] = 1.f / (1.f + expf(-src[oc]));
+}
+
+static void kpu_conv(const kpu_model_conv_layer_argument_t *arg, kpu_model_context_t *ctx)
+{
+    volatile kpu_layer_argument_t layer = *(const volatile kpu_layer_argument_t *)(ctx->model_buffer + arg->layer_offset);
+    layer.kernel_load_cfg.data.para_start_addr = (uintptr_t)(ctx->model_buffer + arg->weights_offset) - IOMEM;
+    layer.kernel_pool_type_cfg.data.bwsx_base_addr = (uintptr_t)(ctx->model_buffer + arg->bn_offset) - IOMEM;
+    layer.kernel_calc_type_cfg.data.active_addr = (uintptr_t)(ctx->model_buffer + arg->act_offset) - IOMEM;
+
+    if(arg->flags & KLF_MAIN_MEM_OUT)
+    {
+        dmac_channel_number_t dma_ch = ctx->dma_ch;
+        uint8_t *dest = ctx->main_buffer + arg->main_mem_out_address;
+        kpu->interrupt_clear.data = (kpu_config_interrupt_t){
+            .calc_done_int = 1,
+            .layer_cfg_almost_empty_int = 1,
+            .layer_cfg_almost_full_int = 1};
+        kpu->interrupt_mask.data = (kpu_config_interrupt_t){
+            .calc_done_int = 1,
+            .layer_cfg_almost_empty_int = 1,
+            .layer_cfg_almost_full_int = 1};
+        layer.dma_parameter.data.send_data_out = 1;
+        select_dma_channel(dma_ch, DMA_SELECT_AI_RX_REQ);
+        if(ctx->current_layer < ctx->layers_length)
+            dmac_set_irq(dma_ch, ai_step, ctx, 1);
+        else
+            dmac_set_irq(dma_ch, (plic_irq_callback_t)kpu_kmodel_done, ctx, 1);
+        dmac_set_single_mode(dma_ch, (void *)(&kpu->fifo_data_out), dest, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
+                            DMAC_MSIZE_8, DMAC_TRANS_WIDTH_64, (layer.dma_parameter.data.dma_total_byte + 8) / 8);
+    } else
+    {
+        kpu->interrupt_clear.data = (kpu_config_interrupt_t){
+            .calc_done_int = 1,
+            .layer_cfg_almost_empty_int = 1,
+            .layer_cfg_almost_full_int = 1};
+
+        kpu->interrupt_mask.data = (kpu_config_interrupt_t){
+            .calc_done_int = 0,
+            .layer_cfg_almost_empty_int = 1,
+            .layer_cfg_almost_full_int = 1};
+        layer.interrupt_enabe.data.int_en = 1;
+    }
+
+    kpu_send_layer((const kpu_layer_argument_t *)&layer);
+}
+
+static void kpu_add_padding(const kpu_model_add_padding_layer_argument_t *arg, kpu_model_context_t *ctx)
+{
+    const uint8_t *src = (const uint8_t *)(ctx->main_buffer + arg->main_mem_in_address);
+#if USE_CACHED_AI_RAM
+    uint8_t *dest = (uint8_t *)(uintptr_t)(AI_RAM_BASE_ADDR + arg->kpu_mem_out_address * 64);
+#else
+    uint8_t *dest = (uint8_t *)(uintptr_t)(AI_IO_BASE_ADDR + arg->kpu_mem_out_address * 64);
+#endif
+
+    uint32_t row_padding = 16;
+    uint32_t row_group = 4;
+    uint32_t row_length = 1;
+    uint32_t height = 4;
+    uint32_t oc, x, y, channels = arg->channels;
+
+    for(oc = 0; oc < channels; oc++)
+    {
+        uint8_t *channel_origin = dest + oc / row_group * row_length * height * 64 + oc % row_group * row_padding;
+        for(y = 0; y < 1; y++)
+        {
+            uint8_t *y_origin = channel_origin + y * row_length * 64;
+            for(x = 0; x < 1; x++)
+                y_origin[x] = *src++;
+        }
+    }
+
+#if USE_CACHED_AI_RAM
+    uint32_t lines = row_length * height * channels / row_group;
+    kpu_flush_cache(arg->kpu_mem_out_address, lines);
+#endif
+}
+
+static void kpu_remove_padding(const kpu_model_remove_padding_layer_argument_t *arg, kpu_model_context_t *ctx)
+{
+    const uint8_t *src = (const uint8_t *)(ctx->main_buffer + arg->main_mem_in_address);
+    uint8_t *dest = (uint8_t *)(ctx->main_buffer + arg->main_mem_out_address);
+    uint32_t oc, channels = arg->channels;
+
+    for(oc = 0; oc < channels; oc++)
+        *dest++ = src[oc * 16];
+}
+
+static void kpu_upload(const kpu_model_upload_layer_argument_t *arg, kpu_model_context_t *ctx)
+{
+    size_t width = arg->width;
+    size_t height = arg->height;
+    size_t channels = arg->channels;
+
+    kpu_upload_core(width, height, channels, ctx->main_buffer + arg->main_mem_in_address, arg->kpu_mem_out_address);
+}
+
+int kpu_load_kmodel(kpu_model_context_t *ctx, const uint8_t *buffer)
+{
+#if FIX_CACHE
+    configASSERT(is_memory_cache((uintptr_t)buffer));
+#endif
+    uintptr_t base_addr = (uintptr_t)buffer;
+    const kpu_kmodel_header_t *header = (const kpu_kmodel_header_t *)buffer;
+
+    if (header->version == 3 && header->arch == 0)
+    {
+        ctx->is_nncase = 0;
+        ctx->model_buffer = buffer;
+        ctx->output_count = header->output_count;
+        ctx->outputs = (const kpu_model_output_t *)(base_addr + sizeof(kpu_kmodel_header_t));
+        ctx->layer_headers = (const kpu_model_layer_header_t *)((uintptr_t)ctx->outputs + sizeof(kpu_model_output_t) * ctx->output_count);
+        ctx->layers_length = header->layers_length;
+        ctx->body_start = (const uint8_t *)((uintptr_t)ctx->layer_headers + sizeof(kpu_model_layer_header_t) * header->layers_length);
+        ctx->main_buffer = (uint8_t *)malloc(header->main_mem_usage);
+        if (!ctx->main_buffer)
+            return -1;
+        uint32_t body_size = 0;
+        for (int i=0; i<ctx->layers_length; i++)
+        {
+            const kpu_model_layer_header_t *cnt_layer_header = ctx->layer_headers + i;
+            body_size += cnt_layer_header->body_size;
+        }
+        uint8_t *body_start_iomem = (uint8_t *)((uintptr_t)ctx->body_start - IOMEM);
+        const uint8_t *body_start_cache = ctx->body_start;
+        memcpy(body_start_iomem, body_start_cache, body_size);
+        for (int i=0; i<body_size; i++)
+        {
+            configASSERT(body_start_iomem[i] == body_start_cache[i]);
+        }
+        
+    } else
+    {
+        return -1;
+    }
+
+    return 0;
+}
+
+int kpu_get_output(kpu_model_context_t *ctx, uint32_t index, uint8_t **data, size_t *size)
+{
+    if(ctx->is_nncase)
+        return -1;
+
+    if(index >= ctx->output_count)
+        return -1;
+
+    const kpu_model_output_t *output = ctx->outputs + index;
+    *data = ctx->main_buffer + output->address;
+    *size = output->size;
+    return 0;
+}
+
+void kpu_model_free(kpu_model_context_t *ctx)
+{
+    if(ctx->is_nncase)
+        return;
+
+    free(ctx->main_buffer);
+    ctx->main_buffer = NULL;
+}
+
+#if KPU_DEBUG
+static uint64_t last_time;
+static uint64_t total_time;
+static uint64_t kpu_time;
+static uint32_t last_layer_type;
+
+static const char *str_layer_type(uint32_t type)
+{
+    switch(type)
+    {
+        case KL_ADD:
+            return "Add";
+        case KL_QUANTIZED_ADD:
+            return "QuantAdd";
+        case KL_GLOBAL_AVERAGE_POOL2D:
+            return "GAP";
+        case KL_QUANTIZED_MAX_POOL2D:
+            return "QuantMaxPool2d";
+        case KL_AVERAGE_POOL2D:
+            return "AveragePool2d";
+        case KL_QUANTIZE:
+            return "Quantize";
+        case KL_DEQUANTIZE:
+            return "Dequantize";
+        case KL_REQUANTIZE:
+            return "Requantize";
+        case KL_L2_NORMALIZATION:
+            return "L2Norm";
+        case KL_SOFTMAX:
+            return "Softmax";
+        case KL_CONCAT:
+            return "Concat";
+        case KL_QUANTIZED_CONCAT:
+            return "QuantConcat";
+        case KL_FULLY_CONNECTED:
+            return "FullyConnected";
+        case KL_TENSORFLOW_FLATTEN:
+            return "TFFlatten";
+        case KL_RESIZE_NEAREST_NEIGHBOR:
+            return "ResizeNearestNeighbor";
+        case KL_QUANTIZED_RESIZE_NEAREST_NEIGHBOR:
+            return "QuantResizeNearestNeighbor";
+        case KL_CHANNELWISE_DEQUANTIZE:
+            return "ChannelwiseDequantize";
+        case KL_LOGISTIC:
+            return "Logistic";
+        case KL_K210_CONV:
+            return "K210Conv";
+        case KL_K210_ADD_PADDING:
+            return "K210AddPad";
+        case KL_K210_REMOVE_PADDING:
+            return "K210RemovePad";
+        case KL_K210_UPLOAD:
+            return "K210Upload";
+        default:
+            return "Unknown";
+    }
+}
+#endif
+
+static int kpu_kmodel_done(kpu_model_context_t *ctx)
+{
+    kpu->interrupt_clear.data = (kpu_config_interrupt_t){
+        .calc_done_int = 1,
+        .layer_cfg_almost_empty_int = 1,
+        .layer_cfg_almost_full_int = 1};
+    kpu->interrupt_mask.data = (kpu_config_interrupt_t){
+        .calc_done_int = 1,
+        .layer_cfg_almost_empty_int = 1,
+        .layer_cfg_almost_full_int = 1};
+#if KPU_DEBUG
+    uint32_t cnt_layer_id = ctx->current_layer - 1;
+    uint64_t time = sysctl_get_time_us();
+    if(last_time != 0)
+    {
+        uint64_t layer_time = time - last_time;
+        syslog(LOG_NOTICE, "layer %d [%s]: %f ms", cnt_layer_id, str_layer_type(last_layer_type), layer_time / 1000.0);
+        total_time += layer_time;
+        if(last_layer_type == KL_K210_CONV)
+            kpu_time += layer_time;
+    }
+
+    syslog(LOG_NOTICE, "KPU: %f ms", kpu_time / 1000.0);
+    syslog(LOG_NOTICE, "CPU: %f ms", (total_time - kpu_time) / 1000.0);
+    syslog(LOG_NOTICE, "Model: %f ms", total_time / 1000.0);
+#endif
+    ctx->done_callback(ctx->userdata);
+    return 0;
+}
+
+static int ai_step(void *userdata)
+{
+    kpu_model_context_t *ctx = (kpu_model_context_t *)userdata;
+
+    uint32_t cnt_layer_id = ctx->current_layer;
+    const uint8_t *layer_body = ctx->current_body;
+    const kpu_model_layer_header_t *cnt_layer_header = ctx->layer_headers + cnt_layer_id;
+    if (cnt_layer_id >= ctx->layers_length) {
+        //syslog(LOG_NOTICE, "overrun");
+        kpu_kmodel_done(ctx);
+        return -1;
+    }
+
+    ctx->current_layer++;
+    ctx->current_body += cnt_layer_header->body_size;
+
+#if KPU_DEBUG
+    uint64_t time = sysctl_get_time_us();
+    if(last_time != 0)
+    {
+        uint64_t layer_time = time - last_time;
+        syslog(LOG_NOTICE, "layer %d/%d [%s]: %d.%03d ms", cnt_layer_id, ctx->layers_length, str_layer_type(last_layer_type), layer_time / 1000, layer_time % 1000);
+        total_time += layer_time;
+        if(last_layer_type == KL_K210_CONV)
+            kpu_time += layer_time;
+    }
+
+    last_layer_type = cnt_layer_header->type;
+    last_time = sysctl_get_time_us();
+#endif
+
+    switch(cnt_layer_header->type)
+    {
+        case KL_ADD:
+            kpu_kmodel_add((const kpu_model_add_layer_argument_t *)layer_body, ctx);
+            break;
+        case KL_QUANTIZED_ADD:
+            kpu_quantized_add((const kpu_model_quant_add_layer_argument_t *)layer_body, ctx);
+            break;
+        case KL_GLOBAL_AVERAGE_POOL2D:
+            kpu_global_average_pool2d((const kpu_model_gap2d_layer_argument_t *)layer_body, ctx);
+            break;
+        case KL_QUANTIZED_MAX_POOL2D:
+            kpu_quantized_max_pool2d((const kpu_model_quant_max_pool2d_layer_argument_t *)layer_body, ctx);
+            break;
+        case KL_AVERAGE_POOL2D:
+            kpu_average_pool2d((const kpu_model_ave_pool2d_layer_argument_t *)layer_body, ctx);
+            break;
+        case KL_QUANTIZE:
+            kpu_quantize((const kpu_model_quantize_layer_argument_t *)layer_body, ctx);
+            break;
+        case KL_DEQUANTIZE:
+            kpu_kmodel_dequantize((const kpu_model_dequantize_layer_argument_t *)layer_body, ctx);
+            break;
+        case KL_REQUANTIZE:
+            kpu_requantize((const kpu_model_requantize_layer_argument_t *)layer_body, ctx);
+            break;
+        case KL_L2_NORMALIZATION:
+            kpu_l2_normalization((const kpu_model_l2_norm_layer_argument_t *)layer_body, ctx);
+            break;
+        case KL_SOFTMAX:
+            kpu_softmax((const kpu_model_softmax_layer_argument_t *)layer_body, ctx);
+            break;
+        case KL_CONCAT:
+        case KL_QUANTIZED_CONCAT:
+            kpu_concat((const kpu_model_concat_layer_argument_t *)layer_body, ctx);
+            break;
+        case KL_FULLY_CONNECTED:
+            kpu_kmodel_fully_connected((const kpu_model_fully_connected_layer_argument_t *)layer_body, ctx);
+            break;
+        case KL_TENSORFLOW_FLATTEN:
+            kpu_tf_flatten((const kpu_model_tf_flatten_layer_argument_t *)layer_body, ctx);
+            break;
+        case KL_RESIZE_NEAREST_NEIGHBOR:
+            kpu_resize_nearest_neighbor((const kpu_model_resize_nearest_neighbor_layer_argument_t *)layer_body, ctx);
+            break;
+        case KL_QUANTIZED_RESIZE_NEAREST_NEIGHBOR:
+            kpu_quant_resize_nearest_neighbor((const kpu_model_quant_resize_nearest_neighbor_layer_argument_t *)layer_body, ctx);
+            break;
+        case KL_CHANNELWISE_DEQUANTIZE:
+            kpu_kmodel_channelwise_dequantize((const kpu_model_channelwise_dequant_argument_t *)layer_body, ctx);
+            break;
+        case KL_LOGISTIC:
+            kpu_logistic((const kpu_model_logistic_layer_argument_t *)layer_body, ctx);
+            break;
+        case KL_K210_CONV:
+            kpu_conv((const kpu_model_conv_layer_argument_t *)layer_body, ctx);
+            return 0;
+        case KL_K210_ADD_PADDING:
+            kpu_add_padding((const kpu_model_add_padding_layer_argument_t *)layer_body, ctx);
+            break;
+        case KL_K210_REMOVE_PADDING:
+            kpu_remove_padding((const kpu_model_remove_padding_layer_argument_t *)layer_body, ctx);
+            break;
+        case KL_K210_UPLOAD:
+            kpu_upload((const kpu_model_upload_layer_argument_t *)layer_body, ctx);
+            break;
+        default:
+            assert(!"Layer is not supported.");
+            kpu_kmodel_done(ctx);
+            return -1;
+    }
+
+    if (ctx->current_layer < ctx->layers_length)
+        ai_step(userdata);
+    else
+        kpu_kmodel_done(ctx);
+    return 0;
+}
+
+static void ai_step_not_isr(void *userdata)
+{
+    sysctl_disable_irq();
+    ai_step(userdata);
+    sysctl_enable_irq();
+}
+
+int kpu_run_kmodel(kpu_model_context_t *ctx, const uint8_t *src, dmac_channel_number_t dma_ch, kpu_done_callback_t done_callback, void *userdata)
+{
+    if(ctx->is_nncase)
+        return -1;
+
+    ctx->dma_ch = dma_ch;
+    ctx->done_callback = done_callback;
+    ctx->userdata = userdata;
+    ctx->current_layer = 0;
+    ctx->current_body = ctx->body_start;
+#if KPU_DEBUG
+    last_time = 0;
+    total_time = 0;
+    kpu_time = 0;
+#endif
+
+    kpu_kmodel_header_t *header = (kpu_kmodel_header_t *)ctx->model_buffer;
+    kpu->interrupt_clear.reg = 7;
+    kpu->fifo_threshold.data = (kpu_config_fifo_threshold_t){
+        .fifo_full_threshold = 10, .fifo_empty_threshold = 1};
+    kpu->eight_bit_mode.data = (kpu_config_eight_bit_mode_t){
+        .eight_bit_mode = header->flags & 1};
+    kpu->interrupt_mask.data = (kpu_config_interrupt_t){
+        .calc_done_int = 1,
+        .layer_cfg_almost_empty_int = 0,
+        .layer_cfg_almost_full_int = 1};
+
+    plic_set_priority(INTNO_AI, 1);
+    plic_irq_register(INTNO_AI, ai_step, ctx);
+    plic_irq_enable(INTNO_AI);
+
+    const kpu_model_layer_header_t *first_layer_header = ctx->layer_headers;
+
+    switch(first_layer_header->type)
+    {
+        case KL_K210_CONV:
+        {
+            const kpu_model_conv_layer_argument_t *first_layer = (const kpu_model_conv_layer_argument_t *)ctx->body_start;
+            kpu_layer_argument_t layer_arg = *(volatile kpu_layer_argument_t *)(ctx->model_buffer + first_layer->layer_offset);
+
+            if((layer_arg.image_size.data.i_row_wid + 1) % 64 != 0)
+            {
+                kpu_kmodel_input_with_padding(&layer_arg, src);
+                ai_step_not_isr(ctx);
+            } else
+            {
+                kpu_input_dma(&layer_arg, src, ctx->dma_ch, ai_step, ctx);
+            }
+        }
+        break;
+        case KL_FULLY_CONNECTED:
+        {
+            const kpu_model_fully_connected_layer_argument_t *first_layer = (const kpu_model_fully_connected_layer_argument_t *)ctx->body_start;
+            kpu_kmodel_input_float((const float *)src, (float *)(ctx->main_buffer + first_layer->main_mem_in_address), first_layer->in_channels);
+            ai_step_not_isr(ctx);
+        }
+        break;
+        default:
+            return -1;
+    }
+
+    return 0;
+}
Index: azure_iot_hub_riscv/trunk/app_iothub_client/kendryte/kpu.h
===================================================================
--- azure_iot_hub_riscv/trunk/app_iothub_client/kendryte/kpu.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/app_iothub_client/kendryte/kpu.h	(revision 453)
@@ -0,0 +1,973 @@
+/* Copyright 2018 Canaan Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _KPU_H
+#define _KPU_H
+
+#include <kendryte-k210.h>
+#include <stdint.h>
+#include "device.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define kpu_matmul_begin kpu_conv2d_output
+#define IOMEM 0x40000000
+
+typedef int (*plic_irq_callback_t)(void *ctx);
+
+typedef struct
+{
+    union
+    {
+        uint64_t reg;
+        struct
+        {
+            uint64_t int_en : 1;
+            uint64_t ram_flag : 1;
+            uint64_t full_add : 1;
+            uint64_t depth_wise_layer : 1;
+            uint64_t reserved : 60;
+        } data;
+    } interrupt_enabe;
+
+    union
+    {
+        uint64_t reg;
+        struct
+        {
+            uint64_t image_src_addr : 15;
+            uint64_t reserved0 : 17;
+            uint64_t image_dst_addr : 15;
+            uint64_t reserved1 : 17;
+        } data;
+    } image_addr;
+
+    union
+    {
+        uint64_t reg;
+        struct
+        {
+            uint64_t i_ch_num : 10;
+            uint64_t reserved0 : 22;
+            uint64_t o_ch_num : 10;
+            uint64_t reserved1 : 6;
+            uint64_t o_ch_num_coef : 10;
+            uint64_t reserved2 : 6;
+        } data;
+    } image_channel_num;
+
+    union
+    {
+        uint64_t reg;
+        struct
+        {
+            uint64_t i_row_wid : 10;
+            uint64_t i_col_high : 9;
+            uint64_t reserved0 : 13;
+            uint64_t o_row_wid : 10;
+            uint64_t o_col_high : 9;
+            uint64_t reserved1 : 13;
+        } data;
+    } image_size;
+
+    union
+    {
+        uint64_t reg;
+        struct
+        {
+            uint64_t kernel_type : 3;
+            uint64_t pad_type : 1;
+            uint64_t pool_type : 4;
+            uint64_t first_stride : 1;
+            uint64_t bypass_conv : 1;
+            uint64_t load_para : 1;
+            uint64_t reserved0 : 5;
+            uint64_t dma_burst_size : 8;
+            uint64_t pad_value : 8;
+            uint64_t bwsx_base_addr : 32;
+        } data;
+    } kernel_pool_type_cfg;
+
+    union
+    {
+        uint64_t reg;
+        struct
+        {
+            uint64_t load_coor : 1;
+            uint64_t load_time : 6;
+            uint64_t reserved0 : 8;
+            uint64_t para_size : 17;
+            uint64_t para_start_addr : 32;
+        } data;
+    } kernel_load_cfg;
+
+    union
+    {
+        uint64_t reg;
+        struct
+        {
+            uint64_t coef_column_offset : 4;
+            uint64_t coef_row_offset : 12;
+            uint64_t reserved0 : 48;
+        } data;
+    } kernel_offset;
+
+    union
+    {
+        uint64_t reg;
+        struct
+        {
+            uint64_t channel_switch_addr : 15;
+            uint64_t reserved : 1;
+            uint64_t row_switch_addr : 4;
+            uint64_t coef_size : 8;
+            uint64_t coef_group : 3;
+            uint64_t load_act : 1;
+            uint64_t active_addr : 32;
+        } data;
+    } kernel_calc_type_cfg;
+
+    union
+    {
+        uint64_t reg;
+        struct
+        {
+            uint64_t wb_channel_switch_addr : 15;
+            uint64_t reserved0 : 1;
+            uint64_t wb_row_switch_addr : 4;
+            uint64_t wb_group : 3;
+            uint64_t reserved1 : 41;
+        } data;
+    } write_back_cfg;
+
+    union
+    {
+        uint64_t reg;
+        struct
+        {
+            uint64_t shr_w : 4;
+            uint64_t shr_x : 4;
+            uint64_t arg_w : 24;
+            uint64_t arg_x : 24;
+            uint64_t reserved0 : 8;
+        } data;
+    } conv_value;
+
+    union
+    {
+        uint64_t reg;
+        struct
+        {
+            uint64_t arg_add : 40;
+            uint64_t reserved : 24;
+        } data;
+    } conv_value2;
+
+    union
+    {
+        uint64_t reg;
+        struct
+        {
+            uint64_t send_data_out : 1;
+            uint64_t reserved : 15;
+            uint64_t channel_byte_num : 16;
+            uint64_t dma_total_byte : 32;
+        } data;
+    } dma_parameter;
+} kpu_layer_argument_t;
+
+typedef struct
+{
+    union
+    {
+        uint64_t reg;
+        struct
+        {
+            uint64_t shift_number : 8;
+            uint64_t y_mul : 16;
+            uint64_t x_start : 36;
+        } data;
+    } activate_para[16];
+
+    union
+    {
+        uint64_t reg;
+        struct
+        {
+            uint8_t result_bias[8];
+        } data;
+    } activate_para_bias0;
+
+    union
+    {
+        uint64_t reg;
+        struct
+        {
+            uint8_t result_bias[8];
+        } data;
+    } activate_para_bias1;
+} kpu_activate_table_t;
+
+typedef struct
+{
+    union
+    {
+        uint64_t reg;
+        struct
+        {
+            uint64_t norm_mul : 24;
+            uint64_t norm_add : 32;
+            uint64_t norm_shift : 4;
+        } data;
+    } batchnorm;
+} kpu_batchnorm_argument_t;
+
+typedef struct
+{
+    union
+    {
+        uint64_t reg;
+        struct
+        {
+            uint16_t weight[9];
+        } data;
+    } weights;
+} kpu_weights_kernel_16_3x3_t;
+
+typedef struct
+{
+    uint64_t calc_done_int : 1;
+    uint64_t layer_cfg_almost_empty_int : 1;
+    uint64_t layer_cfg_almost_full_int : 1;
+    uint64_t reserved : 61;
+} kpu_config_interrupt_t;
+
+typedef struct
+{
+    uint64_t fifo_full_threshold : 4;
+    uint64_t fifo_empty_threshold : 4;
+    uint64_t reserved : 56;
+} kpu_config_fifo_threshold_t;
+
+typedef struct
+{
+    uint64_t dma_fifo_flush_n : 1;
+    uint64_t gs_fifo_flush_n : 1;
+    uint64_t cfg_fifo_flush_n : 1;
+    uint64_t cmd_fifo_flush_n : 1;
+    uint64_t resp_fifo_flush_n : 1;
+    uint64_t reserved : 59;
+} kpu_config_fifo_ctrl_t;
+
+typedef struct
+{
+    uint64_t eight_bit_mode : 1;
+    uint64_t reserved : 63;
+} kpu_config_eight_bit_mode_t;
+
+typedef struct
+{
+    volatile uint64_t layer_argument_fifo;
+
+    volatile union
+    {
+        uint64_t reg;
+        kpu_config_interrupt_t data;
+    } interrupt_status;
+
+    volatile union
+    {
+        uint64_t reg;
+        kpu_config_interrupt_t data;
+    } interrupt_raw;
+
+    volatile union
+    {
+        uint64_t reg;
+        kpu_config_interrupt_t data;
+    } interrupt_mask;
+
+    volatile union
+    {
+        uint64_t reg;
+        kpu_config_interrupt_t data;
+    } interrupt_clear;
+
+    volatile union
+    {
+        uint64_t reg;
+        kpu_config_fifo_threshold_t data;
+    } fifo_threshold;
+
+    volatile uint64_t fifo_data_out;
+
+    volatile union
+    {
+        uint64_t reg;
+        kpu_config_fifo_ctrl_t data;
+    } fifo_ctrl;
+
+    volatile union
+    {
+        uint64_t reg;
+        kpu_config_eight_bit_mode_t data;
+    } eight_bit_mode;
+} kpu_config_t;
+
+#define dmac_channel_number_t int
+
+typedef struct
+{
+    kpu_layer_argument_t *layers;
+    kpu_layer_argument_t *remain_layers;
+    plic_irq_callback_t callback;
+    void *ctx;
+    uint64_t *src;
+    uint64_t *dst;
+    uint32_t src_length;
+    uint32_t dst_length;
+    uint32_t layers_length;
+    uint32_t remain_layers_length;
+    dmac_channel_number_t dma_ch;
+    uint32_t eight_bit_mode;
+    float output_scale;
+    float output_bias;
+    float input_scale;
+    float input_bias;
+} kpu_task_t;
+
+typedef struct
+{
+    uint32_t version;
+    uint32_t flags;
+    uint32_t arch;
+    uint32_t layers_length;
+    uint32_t max_start_address;
+    uint32_t main_mem_usage;
+    uint32_t output_count;
+} kpu_kmodel_header_t;
+
+typedef struct
+{
+    uint32_t version;
+    uint32_t flags;
+    uint32_t layers_length;
+    uint32_t max_start_address;
+    uint32_t layers_argument_start;
+} kpu_model_header_t;
+
+typedef struct
+{
+    uint32_t address;
+    uint32_t size;
+} kpu_model_output_t;
+
+typedef enum
+{
+    KL_INVALID = 0,
+    KL_ADD,
+    KL_QUANTIZED_ADD,
+    KL_GLOBAL_MAX_POOL2D,
+    KL_QUANTIZED_GLOBAL_MAX_POOL2D,
+    KL_GLOBAL_AVERAGE_POOL2D,
+    KL_QUANTIZED_GLOBAL_AVERAGE_POOL2D,
+    KL_MAX_POOL2D,
+    KL_QUANTIZED_MAX_POOL2D,
+    KL_AVERAGE_POOL2D,
+    KL_QUANTIZED_AVERAGE_POOL2D,
+    KL_QUANTIZE,
+    KL_DEQUANTIZE,
+    KL_REQUANTIZE,
+    KL_L2_NORMALIZATION,
+    KL_SOFTMAX,
+    KL_CONCAT,
+    KL_QUANTIZED_CONCAT,
+    KL_FULLY_CONNECTED,
+    KL_QUANTIZED_FULLY_CONNECTED,
+    KL_TENSORFLOW_FLATTEN,
+    KL_QUANTIZED_TENSORFLOW_FLATTEN,
+    KL_RESIZE_NEAREST_NEIGHBOR,
+    KL_QUANTIZED_RESIZE_NEAREST_NEIGHBOR,
+    KL_CHANNELWISE_DEQUANTIZE,
+    KL_LOGISTIC,
+    KL_K210_CONV = 10240,
+    KL_K210_ADD_PADDING,
+    KL_K210_REMOVE_PADDING,
+    KL_K210_UPLOAD
+} kpu_model_layer_type_t;
+
+typedef struct
+{
+    uint32_t type;
+    uint32_t body_size;
+} kpu_model_layer_header_t;
+
+typedef enum
+{
+    KLF_NONE = 0,
+    KLF_MAIN_MEM_OUT = 1
+} kpu_model_layer_flags_t;
+
+typedef enum
+{
+    KLP_SAME = 0,
+    KLP_VALID = 1
+} kpu_model_padding_t;
+
+typedef enum
+{
+    KLA_LINEAR = 0,
+    KLA_RELU = 1,
+    KLA_RELU6 = 2
+} kpu_model_activation_t;
+
+typedef struct
+{
+    float scale;
+    float bias;
+} kpu_model_quant_param_t;
+
+typedef struct
+{
+    uint32_t width;
+    uint32_t height;
+    uint32_t channels;
+} kpu_model_shape_t;
+
+typedef struct
+{
+    uint32_t start;
+    uint32_t size;
+} kpu_model_memory_range_t;
+
+typedef struct
+{
+    uint32_t flags;
+    uint32_t main_mem_out_address;
+    uint32_t layer_offset;
+    uint32_t weights_offset;
+    uint32_t bn_offset;
+    uint32_t act_offset;
+} kpu_model_conv_layer_argument_t;
+
+typedef struct
+{
+    uint32_t flags;
+    uint32_t main_mem_in_a_address;
+    uint32_t main_mem_in_b_address;
+    uint32_t main_mem_out_address;
+    uint32_t count;
+} kpu_model_add_layer_argument_t;
+
+typedef struct
+{
+    uint32_t flags;
+    uint32_t main_mem_in_a_address;
+    uint32_t main_mem_in_b_address;
+    uint32_t main_mem_out_address;
+    uint32_t count;
+    int32_t in_a_offset;
+    int32_t in_a_mul;
+    int32_t in_a_shift;
+    int32_t in_b_offset;
+    int32_t in_b_mul;
+    int32_t in_b_shift;
+    int32_t out_offset;
+    int32_t out_mul;
+    int32_t out_shift;
+} kpu_model_quant_add_layer_argument_t;
+
+typedef struct
+{
+    uint32_t flags;
+    uint32_t main_mem_in_address;
+    uint32_t main_mem_out_address;
+    uint32_t kernel_size;
+    uint32_t channels;
+} kpu_model_gap2d_layer_argument_t;
+
+typedef struct
+{
+    uint32_t flags;
+    uint32_t main_mem_in_address;
+    uint32_t main_mem_out_address;
+    kpu_model_shape_t in_shape;
+    kpu_model_shape_t out_shape;
+    uint32_t kernel_width;
+    uint32_t kernel_height;
+    uint32_t stride_width;
+    uint32_t stride_height;
+    uint32_t padding_width;
+    uint32_t padding_height;
+} kpu_model_quant_max_pool2d_layer_argument_t;
+
+typedef struct
+{
+    uint32_t flags;
+    uint32_t main_mem_in_address;
+    uint32_t main_mem_out_address;
+    kpu_model_shape_t in_shape;
+    kpu_model_shape_t out_shape;
+    uint32_t kernel_width;
+    uint32_t kernel_height;
+    uint32_t stride_width;
+    uint32_t stride_height;
+    uint32_t padding_width;
+    uint32_t padding_height;
+    kpu_model_activation_t act;
+} kpu_model_ave_pool2d_layer_argument_t;
+
+typedef struct
+{
+    uint32_t flags;
+    uint32_t main_mem_in_address;
+    uint32_t mem_out_address;
+    uint32_t count;
+    kpu_model_quant_param_t quant_param;
+} kpu_model_quantize_layer_argument_t;
+
+typedef struct
+{
+    uint32_t flags;
+    uint32_t main_mem_in_address;
+    uint32_t main_mem_out_address;
+    uint32_t count;
+    kpu_model_quant_param_t quant_param;
+} kpu_model_dequantize_layer_argument_t;
+
+typedef struct
+{
+    uint32_t flags;
+    uint32_t main_mem_in_address;
+    uint32_t main_mem_out_address;
+    uint32_t count;
+    uint8_t table[256];
+} kpu_model_requantize_layer_argument_t;
+
+typedef struct
+{
+    uint32_t flags;
+    uint32_t main_mem_in_address;
+    uint32_t kpu_mem_out_address;
+    uint32_t channels;
+} kpu_model_add_padding_layer_argument_t;
+
+typedef struct
+{
+    uint32_t flags;
+    uint32_t main_mem_in_address;
+    uint32_t main_mem_out_address;
+    uint32_t channels;
+} kpu_model_remove_padding_layer_argument_t;
+
+typedef struct
+{
+    uint32_t flags;
+    uint32_t main_mem_in_address;
+    uint32_t kpu_mem_out_address;
+    uint32_t width;
+    uint32_t height;
+    uint32_t channels;
+} kpu_model_upload_layer_argument_t;
+
+typedef struct
+{
+    uint32_t flags;
+    uint32_t main_mem_in_address;
+    uint32_t main_mem_out_address;
+    uint32_t channels;
+} kpu_model_l2_norm_layer_argument_t;
+
+typedef struct
+{
+    uint32_t flags;
+    uint32_t main_mem_in_address;
+    uint32_t main_mem_out_address;
+    uint32_t channels;
+} kpu_model_softmax_layer_argument_t;
+
+typedef struct
+{
+    uint32_t flags;
+    uint32_t main_mem_out_address;
+    uint32_t input_count;
+    kpu_model_memory_range_t inputs_mem[0];
+} kpu_model_concat_layer_argument_t;
+
+typedef struct
+{
+    uint32_t flags;
+    uint32_t main_mem_in_address;
+    uint32_t main_mem_out_address;
+    uint32_t in_channels;
+    uint32_t out_channels;
+    kpu_model_activation_t act;
+    float weights[0];
+} kpu_model_fully_connected_layer_argument_t;
+
+typedef struct
+{
+    uint32_t flags;
+    uint32_t main_mem_in_address;
+    uint32_t main_mem_out_address;
+    kpu_model_shape_t shape;
+} kpu_model_tf_flatten_layer_argument_t;
+
+typedef struct
+{
+    uint32_t flags;
+    uint32_t main_mem_in_address;
+    uint32_t main_mem_out_address;
+    kpu_model_shape_t in_shape;
+    uint32_t out_width;
+    uint32_t out_height;
+    uint32_t align_corners;
+} kpu_model_resize_nearest_neighbor_layer_argument_t;
+
+typedef struct
+{
+    uint32_t flags;
+    uint32_t main_mem_in_address;
+    uint32_t main_mem_out_address;
+    kpu_model_shape_t in_shape;
+    uint32_t out_width;
+    uint32_t out_height;
+    uint32_t align_corners;
+} kpu_model_quant_resize_nearest_neighbor_layer_argument_t;
+
+typedef struct
+{
+    uint32_t flags;
+    uint32_t main_mem_in_address;
+    uint32_t main_mem_out_address;
+    uint32_t channels;
+    uint32_t channel_size;
+    kpu_model_quant_param_t quant_params[0];
+} kpu_model_channelwise_dequant_argument_t;
+
+typedef struct
+{
+    uint32_t flags;
+    uint32_t main_mem_in_address;
+    uint32_t main_mem_out_address;
+    uint32_t channels;
+} kpu_model_logistic_layer_argument_t;
+
+typedef void (*kpu_done_callback_t)(void *userdata);
+
+typedef struct
+{
+    int is_nncase;
+
+    union
+    {
+        struct
+        {
+            const uint8_t *model_buffer;
+            uint8_t *main_buffer;
+            uint32_t output_count;
+            const kpu_model_output_t *outputs;
+            const kpu_model_layer_header_t *layer_headers;
+            const uint8_t *body_start;
+            uint32_t layers_length;
+            volatile uint32_t current_layer;
+            const uint8_t *volatile current_body;
+            dmac_channel_number_t dma_ch;
+            kpu_done_callback_t done_callback;
+            void *userdata;
+        };
+
+        struct
+        {
+            void* nncase_ctx;
+        };
+    };
+} kpu_model_context_t;
+
+typedef struct
+{
+    uint32_t weigths_offset;
+    uint32_t bn_offset;
+    uint32_t act_offset;
+    float input_scale;
+    float input_bias;
+    float output_scale;
+    float output_bias;
+} kpu_model_layer_metadata_t;
+
+typedef struct _quantize_param
+{
+    float scale;
+    float bias;
+} quantize_param_t;
+
+extern volatile kpu_config_t *const kpu;
+
+/**
+ * @brief       Modle complier init kpu handler
+ *
+ * @param[in]   task            Kpu handler
+ *
+ * @return      Kpu handler
+ */
+extern kpu_task_t *kpu_task_init(kpu_task_t *task);
+
+/**
+ * @brief       Kpu run for AI
+ *
+ * @param[in]   task                Kpu handler
+ * @param[in]   dma_ch              DMA for kpu
+ * @param[in]   src                 The picture data
+ * @param[in]   dest                The result of kpu
+ * @param[in]   callback            The callback of kpu
+ *
+ * @return      result
+ *     - 0      Success
+ *     - Other  Fail.Kpu is busy.
+ */
+int kpu_run(kpu_task_t *task, dmac_channel_number_t dma_ch, const void *src, void *dest, plic_irq_callback_t callback);
+
+/**
+ * @brief       Get kpu result buf
+ *
+ * @param[in]   task                Kpu handler
+ *
+ * @return      Kpu result buf
+ */
+uint8_t *kpu_get_output_buf(kpu_task_t *task);
+
+/**
+ * @brief       Release kpu output buf
+ *
+ * @param[in]   output_buf                Kpu output buf
+ *
+ */
+void kpu_release_output_buf(uint8_t *output_buf);
+
+/**
+ * @brief       Kpu run for AI
+ *
+ * @param[in]   task                Kpu handler
+*
+* @return      result
+*     - 0      Success
+*     - Other  Fail.Kpu is busy.
+*/
+int kpu_start(kpu_task_t *task);
+
+/**
+ * @brief      Initialize kpu handler
+ *
+ * @param[in]   task            Kpu handler
+ *
+ * @return      result
+ *     - 0      Success
+ *     - Other  Fail.
+ */
+int kpu_single_task_init(kpu_task_t *task);
+
+/**
+ * @brief      Uninitialize kpu handler
+ *
+ * @param[in]   task            Kpu handler
+ *
+ * @return      result
+ *     - 0      Success
+ *     - Other  Fail.
+ */
+int kpu_single_task_deinit(kpu_task_t *task);
+
+/**
+ * @brief      Load kmodel and init kpu task
+ *
+ * @param[in]   task            Kpu handler
+ * @param[in]   buffer          Kmodel
+ * @param[in]   meta            Test data
+ *
+ * @return      result
+ *     - 0      Success
+ *     - Other  Fail.
+ */
+int kpu_model_load_from_buffer(kpu_task_t *task, uint8_t *buffer, kpu_model_layer_metadata_t **meta);
+
+/**
+ * @brief       Kpu initialize
+ *
+ * @param[in]   eight_bit_mode            0:16bit mode  1:8bit mode
+ * @param[in]   callback                  Callback of kpu
+ * @param[in]   userdata                  Data of callback
+ *
+ */
+void kpu_init(int eight_bit_mode, plic_irq_callback_t callback, void *userdata);
+
+/**
+ * @brief       Kpu input data by dma
+ *
+ * @param[in]   layer                   Kpu task layer
+ * @param[in]   src                     Image data
+ * @param[in]   dma_ch                  Dmac channel
+ * @param[in]   callback                Dmac complete callback
+ * @param[in]   userdata                Data of callback
+ *
+ */
+void kpu_input_dma(const kpu_layer_argument_t *layer, const uint8_t *src, dmac_channel_number_t dma_ch, plic_irq_callback_t callback, void *userdata);
+
+/**
+ * @brief       Kpu input data by cpu
+ *
+ * @param[in]   layer                   Kpu task layer
+ * @param[in]   src                     Image data
+ * @param[in]   width                   Image width
+ * @param[in]   height                  Image heigth
+ * @param[in]   channels                Color channel, RGB is 3
+ *
+ */
+void kpu_input_with_padding(kpu_layer_argument_t *layer, const uint8_t *src, int width, int height, int channels);
+
+/**
+ * @brief       Kpu run only one layer
+ *
+ * @param[in]   layer                   Kpu task layer
+ *
+ */
+void kpu_conv2d(kpu_layer_argument_t *layer);
+
+/**
+ * @brief       Kpu run only one layer then get the result by dma
+ *
+ * @param[in]   layer                   Kpu task layer
+ * @param[in]   dma_ch                  Dmac channel
+ * @param[in]   dest                    Result
+ * @param[in]   callback                Dmac complete callback
+ * @param[in]   userdata                Data of callback
+ *
+ */
+void kpu_conv2d_output(kpu_layer_argument_t *layer, dmac_channel_number_t dma_ch, uint8_t *dest, plic_irq_callback_t callback, void *userdata);
+
+/**
+ * @brief       Kpu pooling
+ *
+ * @param[in]   src                        Source
+ * @param[in]   src_param                  Source param
+ * @param[in]   kernel_size                Kernel size, 7*7 is 49
+ * @param[in]   channels                   Channels
+ * @param[in]   dest                       Dest
+ * @param[in]   dest_param                 Dest param
+ *
+ */
+void kpu_global_average_pool(const uint8_t *src, const quantize_param_t *src_param, int kernel_size, int channels, uint8_t *dest, const quantize_param_t *dest_param);
+
+/**
+ * @brief       Kpu pooling
+ *
+ * @param[in]   src                        Source
+ * @param[in]   src_param                  Source param
+ * @param[in]   kernel_size                Kernel size, 7*7 is 49
+ * @param[in]   channels                   Channels
+ * @param[in]   dest                       Dest
+ *
+ */
+void kpu_global_average_pool_float(const uint8_t *src, const quantize_param_t *src_param, int kernel_size, int channels, float *dest);
+
+/**
+ * @brief       Kpu fullly connected by cpu
+ *
+ * @param[in]   src                                 Source
+ * @param[in]   weights                             Weight
+ * @param[in]   biases                              Biases
+ * @param[in]   dest                                Dest
+ * @param[in]   input_channels                      Input channels
+ * @param[in]   output_channels                     Output channels
+ *
+ */
+void kpu_fully_connected(const float *src, const float *weights, const float *biases, float *dest, int input_channels, int output_channels);
+
+/**
+ * @brief       Kpu matrix multiplication
+ *
+ * @param[in]   src                                 Source
+ * @param[in]   channels                            Channels
+ * @param[in]   dest                                Dest
+ * @param[in]   dest_param                          Dest param
+ *
+ */
+void kpu_matmul_end(const uint8_t *src, int channels, float *dest, const quantize_param_t *dest_param);
+
+/**
+ * @brief       Kpu dequantize
+ *
+ * @param[in]   src                                 Source
+ * @param[in]   src_param                           Source param
+ * @param[in]   count                               Dequantize count
+ * @param[in]   dest                                Dest
+ *
+ */
+void kpu_dequantize(const uint8_t *src, const quantize_param_t *src_param, size_t count, float *dest);
+
+/**
+ * @brief       Kpu load kmodel
+ *
+ * @param[in]   ctx                                 Kmodel object
+ * @param[in]   buffer                              Kmodel buffer
+ *
+ * @return      result
+ *     - 0      Success
+ *     - Other  Fail.
+ */
+int kpu_load_kmodel(kpu_model_context_t *ctx, const uint8_t *buffer);
+
+/**
+ * @brief       Kpu free kmodel buffer
+ *
+ * @param[in]   ctx                                 kmodel object
+ *
+ */
+void kpu_model_free(kpu_model_context_t *ctx);
+
+/**
+ * @brief       Kpu load kmodel
+ *
+ * @param[in]   ctx                                 Kmodel object
+ * @param[in]   index                               Output index
+ * @param[in]   data                                Output data
+ * @param[in]   size                                Output data size
+ *
+ * @return      result
+ *     - 0      Success
+ *     - Other  Fail.
+ */
+int kpu_get_output(kpu_model_context_t *ctx, uint32_t index, uint8_t **data, size_t *size);
+
+/**
+ * @brief       Kpu run kmodel
+ *
+ * @param[in]   ctx                                 Kmodel object
+ * @param[in]   src                                 Source data
+ * @param[in]   dma_ch                              Dma channel
+ * @param[in]   done_callback                       Kpu complete callback
+ * @param[in]   userdata                            Data of callback
+ *
+ * @return      result
+ *     - 0      Success
+ *     - Other  Fail.
+ */
+int kpu_run_kmodel(kpu_model_context_t *ctx, const uint8_t *src, dmac_channel_number_t dma_ch, kpu_done_callback_t done_callback, void *userdata);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: azure_iot_hub_riscv/trunk/app_iothub_client/kendryte/region_layer.c
===================================================================
--- azure_iot_hub_riscv/trunk/app_iothub_client/kendryte/region_layer.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/app_iothub_client/kendryte/region_layer.c	(revision 453)
@@ -0,0 +1,405 @@
+#include <stdlib.h>
+#include <math.h>
+#include <stdio.h>
+#include "region_layer.h"
+
+typedef struct
+{
+    float x;
+    float y;
+    float w;
+    float h;
+} box_t;
+
+typedef struct
+{
+    int index;
+    int class;
+    float **probs;
+} sortable_box_t;
+
+
+int region_layer_init(region_layer_t *rl, int width, int height, int channels, int origin_width, int origin_height)
+{
+    int flag = 0;
+
+    rl->coords = 4;
+    rl->image_width = 320;
+    rl->image_height = 240;
+
+    rl->classes = channels / 5 - 5;
+    rl->net_width = origin_width;
+    rl->net_height = origin_height;
+    rl->layer_width = width;
+    rl->layer_height = height;
+    rl->boxes_number = (rl->layer_width * rl->layer_height * rl->anchor_number); 
+    rl->output_number = (rl->boxes_number * (rl->classes + rl->coords + 1));
+
+    rl->output = malloc(rl->output_number * sizeof(float));
+    if (rl->output == NULL)
+    {
+        flag = -1;
+        goto malloc_error;
+    }
+    rl->boxes = malloc(rl->boxes_number * sizeof(box_t));
+    if (rl->boxes == NULL)
+    {
+        flag = -2;
+        goto malloc_error;
+    }
+    rl->probs_buf = malloc(rl->boxes_number * (rl->classes + 1) * sizeof(float));
+    if (rl->probs_buf == NULL)
+    {
+        flag = -3;
+        goto malloc_error;
+    }
+    rl->probs = malloc(rl->boxes_number * sizeof(float *));
+    if (rl->probs == NULL)
+    {
+        flag = -4;
+        goto malloc_error;
+    }
+    for (uint32_t i = 0; i < rl->boxes_number; i++)
+        rl->probs[i] = &(rl->probs_buf[i * (rl->classes + 1)]);
+    return 0;
+malloc_error:
+    free(rl->output);
+    free(rl->boxes);
+    free(rl->probs_buf);
+    free(rl->probs);
+    return flag;
+}
+
+void region_layer_deinit(region_layer_t *rl)
+{
+    free(rl->output);
+    free(rl->boxes);
+    free(rl->probs_buf);
+    free(rl->probs);
+}
+
+static inline float sigmoid(float x)
+{
+    return 1.f / (1.f + expf(-x));
+}
+
+static void activate_array(region_layer_t *rl, int index, int n)
+{
+    float *output = &rl->output[index];
+    float *input = &rl->input[index];
+
+    for (int i = 0; i < n; ++i)
+        output[i] = sigmoid(input[i]);
+}
+
+static int entry_index(region_layer_t *rl, int location, int entry)
+{
+    int wh = rl->layer_width * rl->layer_height;
+    int n   = location / wh;
+    int loc = location % wh;
+
+    return n * wh * (rl->coords + rl->classes + 1) + entry * wh + loc;
+}
+
+static void softmax(region_layer_t *rl, float *input, int n, int stride, float *output)
+{
+    int i;
+    float diff;
+    float e;
+    float sum = 0;
+    float largest_i = input[0];
+
+    for (i = 0; i < n; ++i)
+    {
+        if (input[i * stride] > largest_i)
+            largest_i = input[i * stride];
+    }
+
+    for (i = 0; i < n; ++i) {
+        diff = input[i * stride] - largest_i;
+        e = expf(diff);
+        sum += e;
+        output[i * stride] = e;
+    }
+    for (i = 0; i < n; ++i)
+        output[i * stride] /= sum;
+}
+
+static void softmax_cpu(region_layer_t *rl, float *input, int n, int batch, int batch_offset, int groups, int stride, float *output)
+{
+    int g, b;
+
+    for (b = 0; b < batch; ++b) {
+        for (g = 0; g < groups; ++g)
+            softmax(rl, input + b * batch_offset + g, n, stride, output + b * batch_offset + g);
+    }
+}
+
+static void forward_region_layer(region_layer_t *rl)
+{
+    int index;
+
+    for (index = 0; index < rl->output_number; index++)
+        rl->output[index] = rl->input[index];
+
+    for (int n = 0; n < rl->anchor_number; ++n)
+    {
+        index = entry_index(rl, n * rl->layer_width * rl->layer_height, 0);
+        activate_array(rl, index, 2 * rl->layer_width * rl->layer_height);
+        index = entry_index(rl, n * rl->layer_width * rl->layer_height, 4);
+        activate_array(rl, index, rl->layer_width * rl->layer_height);
+    }
+
+    index = entry_index(rl, 0, rl->coords + 1);
+    softmax_cpu(rl, rl->input + index, rl->classes, rl->anchor_number,
+            rl->output_number / rl->anchor_number, rl->layer_width * rl->layer_height,
+            rl->layer_width * rl->layer_height, rl->output + index);
+}
+
+static void correct_region_boxes(region_layer_t *rl, box_t *boxes)
+{
+    uint32_t net_width = rl->net_width;
+    uint32_t net_height = rl->net_height;
+    uint32_t image_width = rl->image_width;
+    uint32_t image_height = rl->image_height;
+    uint32_t boxes_number = rl->boxes_number;
+    int new_w = 0;
+    int new_h = 0;
+
+    if (((float)net_width / image_width) <
+        ((float)net_height / image_height)) {
+        new_w = net_width;
+        new_h = (image_height * net_width) / image_width;
+    } else {
+        new_h = net_height;
+        new_w = (image_width * net_height) / image_height;
+    }
+    for (int i = 0; i < boxes_number; ++i) {
+        box_t b = boxes[i];
+
+        b.x = (b.x - (net_width - new_w) / 2. / net_width) /
+              ((float)new_w / net_width);
+        b.y = (b.y - (net_height - new_h) / 2. / net_height) /
+              ((float)new_h / net_height);
+        b.w *= (float)net_width / new_w;
+        b.h *= (float)net_height / new_h;
+        boxes[i] = b;
+    }
+}
+
+static box_t get_region_box(float *x, float *biases, int n, int index, int i, int j, int w, int h, int stride)
+{
+    volatile box_t b;
+
+    b.x = (i + x[index + 0 * stride]) / w;
+    b.y = (j + x[index + 1 * stride]) / h;
+    b.w = expf(x[index + 2 * stride]) * biases[2 * n] / w;
+    b.h = expf(x[index + 3 * stride]) * biases[2 * n + 1] / h;
+    return b;
+}
+
+static void get_region_boxes(region_layer_t *rl, float *predictions, float **probs, box_t *boxes)
+{
+    uint32_t layer_width = rl->layer_width;
+    uint32_t layer_height = rl->layer_height;
+    uint32_t anchor_number = rl->anchor_number;
+    uint32_t classes = rl->classes;
+    uint32_t coords = rl->coords;
+    float threshold = rl->threshold;
+
+    for (int i = 0; i < layer_width * layer_height; ++i)
+    {
+        int row = i / layer_width;
+        int col = i % layer_width;
+
+        for (int n = 0; n < anchor_number; ++n)
+        {
+            int index = n * layer_width * layer_height + i;
+
+            for (int j = 0; j < classes; ++j)
+                probs[index][j] = 0;
+            int obj_index = entry_index(rl, n * layer_width * layer_height + i, coords);
+            int box_index = entry_index(rl, n * layer_width * layer_height + i, 0);
+            float scale  = predictions[obj_index];
+
+            boxes[index] = get_region_box(predictions, rl->anchor, n, box_index, col, row,
+                layer_width, layer_height, layer_width * layer_height);
+
+            float max = 0;
+
+            for (int j = 0; j < classes; ++j)
+            {
+                int class_index = entry_index(rl, n * layer_width * layer_height + i, coords + 1 + j);
+                float prob = scale * predictions[class_index];
+
+                probs[index][j] = (prob > threshold) ? prob : 0;
+                if (prob > max)
+                    max = prob;
+            }
+            probs[index][classes] = max;
+        }
+    }
+    correct_region_boxes(rl, boxes);
+}
+
+static int nms_comparator(void *pa, void *pb)
+{
+    sortable_box_t a = *(sortable_box_t *)pa;
+    sortable_box_t b = *(sortable_box_t *)pb;
+    float diff = a.probs[a.index][b.class] - b.probs[b.index][b.class];
+
+    if (diff < 0)
+        return 1;
+    else if (diff > 0)
+        return -1;
+    return 0;
+}
+
+static float overlap(float x1, float w1, float x2, float w2)
+{
+    float l1 = x1 - w1/2;
+    float l2 = x2 - w2/2;
+    float left = l1 > l2 ? l1 : l2;
+    float r1 = x1 + w1/2;
+    float r2 = x2 + w2/2;
+    float right = r1 < r2 ? r1 : r2;
+
+    return right - left;
+}
+
+static float box_intersection(box_t a, box_t b)
+{
+    float w = overlap(a.x, a.w, b.x, b.w);
+    float h = overlap(a.y, a.h, b.y, b.h);
+
+    if (w < 0 || h < 0)
+        return 0;
+    return w * h;
+}
+
+static float box_union(box_t a, box_t b)
+{
+    float i = box_intersection(a, b);
+    float u = a.w * a.h + b.w * b.h - i;
+
+    return u;
+}
+
+static float box_iou(box_t a, box_t b)
+{
+    return box_intersection(a, b) / box_union(a, b);
+}
+
+static void do_nms_sort(region_layer_t *rl, box_t *boxes, float **probs)
+{
+    uint32_t boxes_number = rl->boxes_number;
+    uint32_t classes = rl->classes;
+    float nms_value = rl->nms_value;
+    int i, j, k;
+    sortable_box_t s[boxes_number];
+
+    for (i = 0; i < boxes_number; ++i)
+    {
+        s[i].index = i;
+        s[i].class = 0;
+        s[i].probs = probs;
+    }
+
+    for (k = 0; k < classes; ++k)
+    {
+        for (i = 0; i < boxes_number; ++i)
+            s[i].class = k;
+        qsort(s, boxes_number, sizeof(sortable_box_t), nms_comparator);
+        for (i = 0; i < boxes_number; ++i)
+        {
+            if (probs[s[i].index][k] == 0)
+                continue;
+            box_t a = boxes[s[i].index];
+
+            for (j = i + 1; j < boxes_number; ++j)
+            {
+                box_t b = boxes[s[j].index];
+
+                if (box_iou(a, b) > nms_value)
+                    probs[s[j].index][k] = 0;
+            }
+        }
+    }
+}
+
+static int max_index(float *a, int n)
+{
+    int i, max_i = 0;
+    float max = a[0];
+
+    for (i = 1; i < n; ++i)
+    {
+        if (a[i] > max)
+        {
+            max   = a[i];
+            max_i = i;
+        }
+    }
+    return max_i;
+}
+
+static void region_layer_output(region_layer_t *rl, obj_info_t *obj_info)
+{
+    uint32_t obj_number = 0;
+    uint32_t image_width = rl->image_width;
+    uint32_t image_height = rl->image_height;
+    uint32_t boxes_number = rl->boxes_number;
+    float threshold = rl->threshold;
+    box_t *boxes = (box_t *)rl->boxes;
+    
+    for (int i = 0; i < rl->boxes_number; ++i)
+    {
+        int class  = max_index(rl->probs[i], rl->classes);
+        float prob = rl->probs[i][class];
+
+        if (prob > threshold)
+        {
+            box_t *b = boxes + i;
+            obj_info->obj[obj_number].x1 = b->x * image_width - (b->w * image_width / 2);
+            obj_info->obj[obj_number].y1 = b->y * image_height - (b->h * image_height / 2);
+            obj_info->obj[obj_number].x2 = b->x * image_width + (b->w * image_width / 2);
+            obj_info->obj[obj_number].y2 = b->y * image_height + (b->h * image_height / 2);
+            obj_info->obj[obj_number].class_id = class;
+            obj_info->obj[obj_number].prob = prob;
+            obj_number++;
+        }
+    }
+    obj_info->obj_number = obj_number;
+}
+
+void region_layer_run(region_layer_t *rl, obj_info_t *obj_info)
+{
+    forward_region_layer(rl);
+    get_region_boxes(rl, rl->output, rl->probs, rl->boxes);
+    do_nms_sort(rl, rl->boxes, rl->probs);
+    // region_layer_output(rl, obj_info);
+}
+
+void region_layer_draw_boxes(region_layer_t *rl, callback_draw_box callback)
+{
+    uint32_t image_width = rl->image_width;
+    uint32_t image_height = rl->image_height;
+    float threshold = rl->threshold;
+    box_t *boxes = (box_t *)rl->boxes;
+
+    for (int i = 0; i < rl->boxes_number; ++i)
+    {
+        int class  = max_index(rl->probs[i], rl->classes);
+        float prob = rl->probs[i][class];
+
+        if (prob > threshold)
+        {
+            box_t *b = boxes + i;
+            uint32_t x1 = b->x * image_width - (b->w * image_width / 2);
+            uint32_t y1 = b->y * image_height - (b->h * image_height / 2);
+            uint32_t x2 = b->x * image_width + (b->w * image_width / 2);
+            uint32_t y2 = b->y * image_height + (b->h * image_height / 2);
+            callback(x1, y1, x2, y2, class, prob);
+        }
+    }
+}
Index: azure_iot_hub_riscv/trunk/app_iothub_client/kendryte/region_layer.h
===================================================================
--- azure_iot_hub_riscv/trunk/app_iothub_client/kendryte/region_layer.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/app_iothub_client/kendryte/region_layer.h	(revision 453)
@@ -0,0 +1,51 @@
+#ifndef _REGION_LAYER
+#define _REGION_LAYER
+
+#include <stdint.h>
+#include "kpu.h"
+
+typedef struct
+{
+    uint32_t obj_number;
+    struct
+    {
+        uint32_t x1;
+        uint32_t y1;
+        uint32_t x2;
+        uint32_t y2;
+        uint32_t class_id;
+        float prob;
+    } obj[10];
+} obj_info_t;
+
+typedef struct
+{
+    float threshold;
+    float nms_value;
+    uint32_t coords;
+    uint32_t anchor_number;
+    float *anchor;
+    uint32_t image_width;
+    uint32_t image_height;
+    uint32_t classes;
+    uint32_t net_width;
+    uint32_t net_height;
+    uint32_t layer_width;
+    uint32_t layer_height;
+    uint32_t boxes_number;
+    uint32_t output_number;
+    void *boxes;
+    float *input;
+    float *output;
+    float *probs_buf;
+    float **probs;
+} region_layer_t;
+
+typedef void (*callback_draw_box)(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2, uint32_t class, float prob);
+
+int region_layer_init(region_layer_t *rl, int width, int height, int channels, int origin_width, int origin_height);
+void region_layer_deinit(region_layer_t *rl);
+void region_layer_run(region_layer_t *rl, obj_info_t *obj_info);
+void region_layer_draw_boxes(region_layer_t *rl, callback_draw_box callback);
+
+#endif // _REGION_LAYER
Index: azure_iot_hub_riscv/trunk/app_iothub_client/kendryte/utils.h
===================================================================
--- azure_iot_hub_riscv/trunk/app_iothub_client/kendryte/utils.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/app_iothub_client/kendryte/utils.h	(revision 453)
@@ -0,0 +1,349 @@
+/* Copyright 2018 Canaan Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _DRIVER_UTILS_H
+#define _DRIVER_UTILS_H
+
+#ifdef __cplusplus
+#include <cstdbool>
+#include <cstddef>
+#include <cstdint>
+#else /* __cplusplus */
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define KENDRYTE_MIN(a, b) ((a) > (b) ? (b) : (a))
+#define KENDRYTE_MAX(a, b) ((a) > (b) ? (a) : (b))
+
+#define FIX_CACHE 1
+
+#ifdef __ASSEMBLY__
+#define KENDRYTE_CAST(type, ptr) ptr
+#else /* __ASSEMBLY__ */
+/**
+ * @brief       Cast the pointer to specified pointer type.
+ *
+ * @param[in]   type        The pointer type to cast to
+ * @param[in]   ptr         The pointer to apply the type cast to
+ */
+#define KENDRYTE_CAST(type, ptr) ((type)(ptr))
+#endif /* __ASSEMBLY__ */
+
+/**
+ * @addtogroup      UTIL_RW_FUNC Memory Read/Write Utilities
+ *
+ * This section implements read and write functionality for various
+ * memory untis. The memory unit terms used for these functions are
+ * consistent with those used in the ARM Architecture Reference Manual
+ * ARMv7-A and ARMv7-R edition manual. The terms used for units of memory are:
+ *
+ *  Unit of Memory | Abbreviation | Size in Bits
+ * :---------------|:-------------|:------------:
+ *  Byte           | byte         |       8
+ *  Half Word      | hword        |      16
+ *  Word           | word         |      32
+ *  Double Word    | dword        |      64
+ *
+ */
+
+/**
+ * @brief       Write the 8 bit byte to the destination address in device memory.
+ *
+ * @param[in]   dest        Write destination pointer address
+ * @param[in]   src         8 bit data byte to write to memory
+ */
+#define kendryte_write_byte(dest, src) \
+    (*KENDRYTE_CAST(volatile uint8_t *, (dest)) = (src))
+
+/**
+ * @brief       Read and return the 8 bit byte from the source address in device memory.
+ *
+ * @param[in]   src     Read source pointer address
+ *
+ * @return      8 bit data byte value
+ */
+#define kendryte_read_byte(src) (*KENDRYTE_CAST(volatile uint8_t *, (src)))
+
+/**
+ * @brief       Write the 16 bit half word to the destination address in device memory.
+ *
+ * @param[in]   dest        Write destination pointer address
+ * @param[in]   src         16 bit data half word to write to memory
+ */
+#define kendryte_write_hword(dest, src) \
+    (*KENDRYTE_CAST(volatile uint16_t *, (dest)) = (src))
+
+/**
+ * @brief       Read and return the 16 bit half word from the source address in device
+ *
+ * @param[in]   src     Read source pointer address
+ *
+ * @return      16 bit data half word value
+ */
+#define kendryte_read_hword(src) (*KENDRYTE_CAST(volatile uint16_t *, (src)))
+
+/**
+ * @brief       Write the 32 bit word to the destination address in device memory.
+ *
+ * @param[in]   dest        Write destination pointer address
+ * @param[in]   src         32 bit data word to write to memory
+ */
+#define kendryte_write_word(dest, src) \
+    (*KENDRYTE_CAST(volatile uint32_t *, (dest)) = (src))
+
+/**
+ * @brief       Read and return the 32 bit word from the source address in device memory.
+ *
+ * @param[in]   src     Read source pointer address
+ *
+ * @return      32 bit data half word value
+ */
+#define kendryte_read_word(src) (*KENDRYTE_CAST(volatile uint32_t *, (src)))
+
+/**
+ * @brief       Write the 64 bit double word to the destination address in device memory.
+ *
+ * @param[in]   dest        Write destination pointer address
+ * @param[in]   src         64 bit data word to write to memory
+ */
+#define kendryte_write_dword(dest, src) \
+    (*KENDRYTE_CAST(volatile uint64_t *, (dest)) = (src))
+
+/**
+ * @brief       Read and return the 64 bit double word from the source address in device
+ *
+ * @param[in]   src     Read source pointer address
+ *
+ * @return      64 bit data half word value
+ */
+#define kendryte_read_dword(src) (*KENDRYTE_CAST(volatile uint64_t *, (src)))
+
+/**
+ * @brief       Set selected bits in the 8 bit byte at the destination address in device
+ *
+ * @param[in]   dest        Destination pointer address
+ * @param[in]   bits        Bits to set in destination byte
+ */
+#define kendryte_setbits_byte(dest, bits) \
+    (kendryte_write_byte(dest, kendryte_read_byte(dest) | (bits)))
+
+/**
+ * @brief       Clear selected bits in the 8 bit byte at the destination address in device
+ *
+ * @param[in]   dest        Destination pointer address
+ * @param[in]   bits        Bits to clear in destination byte
+ */
+#define kendryte_clrbits_byte(dest, bits) \
+    (kendryte_write_byte(dest, kendryte_read_byte(dest) & ~(bits)))
+
+/**
+ * @brief       Change or toggle selected bits in the 8 bit byte at the destination address
+ *
+ * @param[in]   dest        Destination pointer address
+ * @param[in]   bits        Bits to change in destination byte
+ */
+#define kendryte_xorbits_byte(dest, bits) \
+    (kendryte_write_byte(dest, kendryte_read_byte(dest) ^ (bits)))
+
+/**
+ * @brief       Replace selected bits in the 8 bit byte at the destination address in device
+ *
+ * @param[in]   dest        Destination pointer address
+ * @param[in]   msk         Bits to replace in destination byte
+ * @param[in]   src         Source bits to write to cleared bits in destination byte
+ */
+#define kendryte_replbits_byte(dest, msk, src) \
+    (kendryte_write_byte(dest, (kendryte_read_byte(dest) & ~(msk)) | ((src) & (msk))))
+
+/**
+ * @brief       Set selected bits in the 16 bit halfword at the destination address in
+ *
+ * @param[in]   dest        Destination pointer address
+ * @param[in]   bits        Bits to set in destination halfword
+ */
+#define kendryte_setbits_hword(dest, bits) \
+    (kendryte_write_hword(dest, kendryte_read_hword(dest) | (bits)))
+
+/**
+ * @brief       Clear selected bits in the 16 bit halfword at the destination address in
+ *
+ * @param[in]   dest        Destination pointer address
+ * @param[in]   bits        Bits to clear in destination halfword
+ */
+#define kendryte_clrbits_hword(dest, bits) \
+    (kendryte_write_hword(dest, kendryte_read_hword(dest) & ~(bits)))
+
+/**
+ * @brief       Change or toggle selected bits in the 16 bit halfword at the destination
+ *
+ * @param[in]   dest        Destination pointer address
+ * @param[in]   bits        Bits to change in destination halfword
+ */
+#define kendryte_xorbits_hword(dest, bits) \
+    (kendryte_write_hword(dest, kendryte_read_hword(dest) ^ (bits)))
+
+/**
+ * @brief       Replace selected bits in the 16 bit halfword at the destination address in
+ *
+ * @param[in]   dest        Destination pointer address
+ * @param[in]   msk         Bits to replace in destination byte
+ * @param[in]   src         Source bits to write to cleared bits in destination halfword
+ */
+#define kendryte_replbits_hword(dest, msk, src) \
+    (kendryte_write_hword(dest, (kendryte_read_hword(dest) & ~(msk)) | ((src) & (msk))))
+
+/**
+ * @brief       Set selected bits in the 32 bit word at the destination address in device
+ *
+ * @param[in]   dest        Destination pointer address
+ * @param[in]   bits        Bits to set in destination word
+ */
+#define kendryte_setbits_word(dest, bits) \
+    (kendryte_write_word(dest, kendryte_read_word(dest) | (bits)))
+
+/**
+ * @brief       Clear selected bits in the 32 bit word at the destination address in device
+ *
+ * @param[in]   dest        Destination pointer address
+ * @param[in]   bits        Bits to clear in destination word
+ */
+#define kendryte_clrbits_word(dest, bits) \
+    (kendryte_write_word(dest, kendryte_read_word(dest) & ~(bits)))
+
+/**
+ * @brief       Change or toggle selected bits in the 32 bit word at the destination address
+ *
+ * @param[in]   dest        Destination pointer address
+ * @param[in]   bits        Bits to change in destination word
+ */
+#define kendryte_xorbits_word(dest, bits) \
+    (kendryte_write_word(dest, kendryte_read_word(dest) ^ (bits)))
+
+/**
+ * @brief       Replace selected bits in the 32 bit word at the destination address in
+ *
+ * @param[in]   dest        Destination pointer address
+ * @param[in]   msk         Bits to replace in destination word
+ * @param[in]   src         Source bits to write to cleared bits in destination word
+ */
+#define kendryte_replbits_word(dest, msk, src) \
+    (kendryte_write_word(dest, (kendryte_read_word(dest) & ~(msk)) | ((src) & (msk))))
+
+/**
+ * @brief      Set selected bits in the 64 bit doubleword at the destination address in
+ *
+ * @param[in]   dest     Destination pointer address
+ * @param[in]   bits     Bits to set in destination doubleword
+ */
+#define kendryte_setbits_dword(dest, bits) \
+    (kendryte_write_dword(dest, kendryte_read_dword(dest) | (bits)))
+
+/**
+ * @brief       Clear selected bits in the 64 bit doubleword at the destination address in
+ *
+ * @param[in]   dest        Destination pointer address
+ * @param[in]   bits        Bits to clear in destination doubleword
+ */
+#define kendryte_clrbits_dword(dest, bits) \
+    (kendryte_write_dword(dest, kendryte_read_dword(dest) & ~(bits)))
+
+/**
+ * @brief       Change or toggle selected bits in the 64 bit doubleword at the destination
+ *
+ * @param[in]   dest        Destination pointer address
+ * @param[in]   bits        Bits to change in destination doubleword
+ */
+#define kendryte_xorbits_dword(dest, bits) \
+    (kendryte_write_dword(dest, kendryte_read_dword(dest) ^ (bits)))
+
+/**
+ * @brief       Replace selected bits in the 64 bit doubleword at the destination address in
+ *
+ * @param[in]   dest        Destination pointer address
+ * @param[in]   msk         its to replace in destination doubleword
+ * @param[in]   src         Source bits to write to cleared bits in destination word
+ */
+#define kendryte_replbits_dword(dest, msk, src) \
+    (kendryte_write_dword(dest, (kendryte_read_dword(dest) & ~(msk)) | ((src) & (msk))))
+
+#define configASSERT(x)                                   \
+    if((x) == 0)                                          \
+    {                                                     \
+        printf("(%s:%d) %s\r\n", __FILE__, __LINE__, #x); \
+        for(;;)                                           \
+            ;                                             \
+    }
+
+/**
+ * @brief       Set value by mask
+ *
+ * @param[in]   bits        The one be set
+ * @param[in]   mask        mask value
+ * @param[in]   value       The value to set
+ */
+void set_bit(volatile uint32_t *bits, uint32_t mask, uint32_t value);
+
+/**
+ * @brief       Set value by mask
+ *
+ * @param[in]   bits        The one be set
+ * @param[in]   mask        Mask value
+ * @param[in]   offset      Mask's offset
+ * @param[in]   value       The value to set
+ */
+void set_bit_offset(volatile uint32_t *bits, uint32_t mask, size_t offset, uint32_t value);
+
+/**
+ * @brief       Set bit for gpio, only set one bit
+ *
+ * @param[in]   bits        The one be set
+ * @param[in]   idx         Offset value
+ * @param[in]   value       The value to set
+ */
+void set_gpio_bit(volatile uint32_t *bits, size_t idx, uint32_t value);
+
+/**
+ * @brief      Get bits value of mask
+ *
+ * @param[in]   bits        The source data
+ * @param[in]   mask        Mask value
+ * @param[in]   offset      Mask's offset
+ *
+ * @return      The bits value of mask
+ */
+uint32_t get_bit(volatile uint32_t *bits, uint32_t mask, size_t offset);
+
+/**
+ * @brief       Get a bit value by offset
+ *
+ * @param[in]   bits        The source data
+ * @param[in]   offset      Bit's offset
+ *
+ *
+ * @return      The bit value
+ */
+uint32_t get_gpio_bit(volatile uint32_t *bits, size_t offset);
+
+uint32_t is_memory_cache(uintptr_t address);
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* _DRIVER_COMMON_H */
Index: azure_iot_hub_riscv/trunk/app_iothub_client/kendryte/yolo.c
===================================================================
--- azure_iot_hub_riscv/trunk/app_iothub_client/kendryte/yolo.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/app_iothub_client/kendryte/yolo.c	(revision 453)
@@ -0,0 +1,7 @@
+#define INCBIN_STYLE INCBIN_STYLE_SNAKE
+#define INCBIN_PREFIX
+#include "incbin.h"
+
+#define CLASS_NUMBER 20
+
+INCBIN(model, "yolo.kmodel");
Index: azure_iot_hub_riscv/trunk/app_iothub_client/src/client.c
===================================================================
--- azure_iot_hub_riscv/trunk/app_iothub_client/src/client.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/app_iothub_client/src/client.c	(revision 453)
@@ -0,0 +1,563 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/* This sample uses the _LL APIs of iothub_client for example purposes.
+That does not mean that HTTP only works with the _LL APIs.
+Simply changing the using the convenience layer (functions not having _LL)
+and removing calls to _DoWork will yield the same results. */
+
+#include "azure_c_shared_utility/threadapi.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/platform.h"
+#include "azure_c_shared_utility/shared_util_options.h"
+#include "iothub_client_ll.h"
+#include "iothub_message.h"
+#include "iothubtransporthttp.h"
+#include "iothubtransportmqtt.h"
+#include "iothubtransportmqtt_websockets.h"
+#include "iothub_client_options.h"
+#include "serializer.h"
+#include "serializer_devicetwin.h"
+#include "client.h"
+
+#ifdef _MSC_VER
+extern int sprintf_s(char* dst, size_t dstSizeInBytes, const char* format, ...);
+#endif // _MSC_VER
+
+#define SET_TRUSTED_CERT_IN_SAMPLES
+
+#ifdef SET_TRUSTED_CERT_IN_SAMPLES
+#include "certs.h"
+#endif // SET_TRUSTED_CERT_IN_SAMPLES
+
+/*String containing Hostname, Device Id & Device Key in the format:                         */
+/*  "HostName=<host_name>;DeviceId=<device_id>;SharedAccessKey=<device_key>"                */
+/*  "HostName=<host_name>;DeviceId=<device_id>;SharedAccessSignature=<device_sas_token>"    */
+char* connectionString = NULL;
+
+bool g_use_proxy;
+HTTP_PROXY_OPTIONS g_proxy_options;
+int ledOn;
+
+static int callbackCounter;
+static bool g_continueRunning;
+static bool g_twinReport;
+static char propText[1024];
+#define MESSAGE_COUNT       5
+#define DOWORK_LOOP_NUM     3
+
+typedef struct EVENT_INSTANCE_TAG
+{
+	IOTHUB_MESSAGE_HANDLE messageHandle;
+	size_t messageTrackingId;  // For tracking the messages within the user callback.
+} EVENT_INSTANCE;
+
+static IOTHUBMESSAGE_DISPOSITION_RESULT ReceiveMessageCallback(IOTHUB_MESSAGE_HANDLE message, void* userContextCallback)
+{
+	int* counter = (int*)userContextCallback;
+	const char* buffer;
+	size_t size;
+	MAP_HANDLE mapProperties;
+	const char* messageId;
+	const char* correlationId;
+	const char* contentType;
+	const char* contentEncoding;
+
+	// Message properties
+	if ((messageId = IoTHubMessage_GetMessageId(message)) == NULL)
+	{
+		messageId = "<null>";
+	}
+
+	if ((correlationId = IoTHubMessage_GetCorrelationId(message)) == NULL)
+	{
+		correlationId = "<null>";
+	}
+
+	if ((contentType = IoTHubMessage_GetContentTypeSystemProperty(message)) == NULL)
+	{
+		contentType = "<null>";
+	}
+
+	if ((contentEncoding = IoTHubMessage_GetContentEncodingSystemProperty(message)) == NULL)
+	{
+		contentEncoding = "<null>";
+	}
+
+	// Message content
+	if (IoTHubMessage_GetByteArray(message, (const unsigned char**)&buffer, &size) != IOTHUB_MESSAGE_OK)
+	{
+		printf("unable to retrieve the message data\r\n");
+	}
+	else
+	{
+		(void)printf("Received Message [%d]\r\n Message ID: %s\r\n Correlation ID: %s\r\n Content-Type: %s\r\n Content-Encoding: %s\r\n Data: <<<%.*s>>> & Size=%d\r\n",
+			*counter, messageId, correlationId, contentType, contentEncoding, (int)size, buffer, (int)size);
+		// If we receive the work 'quit' then we stop running
+		if (size == (strlen("quit") * sizeof(char)) && memcmp(buffer, "quit", size) == 0)
+		{
+			g_continueRunning = false;
+		}
+	}
+
+	// Retrieve properties from the message
+	mapProperties = IoTHubMessage_Properties(message);
+	if (mapProperties != NULL)
+	{
+		const char*const* keys;
+		const char*const* values;
+		size_t propertyCount = 0;
+		if (Map_GetInternals(mapProperties, &keys, &values, &propertyCount) == MAP_OK)
+		{
+			if (propertyCount > 0)
+			{
+				size_t index;
+
+				printf(" Message Properties:\r\n");
+				for (index = 0; index < propertyCount; index++)
+				{
+					(void)printf("\tKey: %s Value: %s\r\n", keys[index], values[index]);
+				}
+				(void)printf("\r\n");
+			}
+		}
+	}
+
+	/* Some device specific action code goes here... */
+	(*counter)++;
+	return IOTHUBMESSAGE_ACCEPTED;
+}
+
+// Define the Model
+BEGIN_NAMESPACE(WeatherStation);
+
+DECLARE_MODEL(ContosoAnemometer,
+WITH_DATA(double, windSpeed),
+WITH_DATA(double, temperature),
+WITH_DATA(double, humidity),
+WITH_METHOD(quit),
+WITH_METHOD(turnLedOn),
+WITH_METHOD(turnLedOff)
+);
+
+DECLARE_STRUCT(ThresholdD,
+	double, value
+);
+
+DECLARE_STRUCT(ThresholdR,
+	double, value,
+	ascii_char_ptr, status
+);
+
+DECLARE_DEVICETWIN_MODEL(AnemometerState,
+WITH_REPORTED_PROPERTY(ThresholdR, threshold)
+);
+
+DECLARE_DEVICETWIN_MODEL(AnemometerSettings,
+WITH_DESIRED_PROPERTY(ThresholdD, threshold, onDesiredThreshold)
+);
+
+END_NAMESPACE(WeatherStation);
+
+void anemometerReportedStateCallback(int status_code, void* userContextCallback)
+{
+	AnemometerState *anemometer = (AnemometerState *)userContextCallback;
+
+	printf("received states \033[43m%d\033[49m, reported threshold = %.1f\n", status_code, anemometer->threshold.value);
+}
+
+void onDesiredThreshold(void* argument)
+{
+	// Note: The argument is NOT a pointer to threshold, but instead a pointer to the MODEL
+	//       that contains threshold as one of its arguments.  In this case, it
+	//       is AnemometerSettings*.
+
+	AnemometerSettings *anemometer = (AnemometerSettings *)argument;
+	printf("received a new desired.threshold = \033[42m%.1f\033[49m\n", anemometer->threshold.value);
+
+	g_twinReport = true;
+}
+
+METHODRETURN_HANDLE quit(ContosoAnemometer* device)
+{
+	(void)device;
+	(void)printf("quit with Method.\r\n");
+
+	g_continueRunning = false;
+
+	METHODRETURN_HANDLE result = MethodReturn_Create(0, "{\"Message\":\"quit with Method\"}");
+	return result;
+}
+
+METHODRETURN_HANDLE turnLedOn(ContosoAnemometer* device)
+{
+	(void)device;
+	(void)printf("\033[41mTurning LED on with Method.\033[49m\r\n");
+
+	ledOn = 1;
+
+	METHODRETURN_HANDLE result = MethodReturn_Create(1, "{\"Message\":\"Turning fan on with Method\"}");
+	return result;
+}
+
+METHODRETURN_HANDLE turnLedOff(ContosoAnemometer* device)
+{
+	(void)device;
+	(void)printf("\033[44mTurning LED off with Method.\033[49m\r\n");
+
+	ledOn = 0;
+
+	METHODRETURN_HANDLE result = MethodReturn_Create(0, "{\"Message\":\"Turning fan off with Method\"}");
+	return result;
+}
+
+static int ReceiveDeviceMethodCallback(const char* method_name, const unsigned char* payload, size_t size, unsigned char** response, size_t* resp_size, void* userContextCallback)
+{
+	int result;
+
+	/*this is step  3: receive the method and push that payload into serializer (from below)*/
+	char* payloadZeroTerminated = (char*)malloc(size + 1);
+	if (payloadZeroTerminated == 0)
+	{
+		printf("failed to malloc\r\n");
+		*resp_size = 0;
+		*response = NULL;
+		result = -1;
+	}
+	else
+	{
+		(void)memcpy(payloadZeroTerminated, payload, size);
+		payloadZeroTerminated[size] = '\0';
+
+		/*execute method - userContextCallback is of type deviceModel*/
+		METHODRETURN_HANDLE methodResult = EXECUTE_METHOD(userContextCallback, method_name, payloadZeroTerminated);
+		free(payloadZeroTerminated);
+
+		if (methodResult == NULL)
+		{
+			printf("failed to EXECUTE_METHOD\r\n");
+			*resp_size = 0;
+			*response = NULL;
+			result = -1;
+		}
+		else
+		{
+			/* get the serializer answer and push it in the networking stack*/
+			const METHODRETURN_DATA* data = MethodReturn_GetReturn(methodResult);
+			if (data == NULL)
+			{
+				printf("failed to MethodReturn_GetReturn\r\n");
+				*resp_size = 0;
+				*response = NULL;
+				result = -1;
+			}
+			else
+			{
+				result = data->statusCode;
+				if (data->jsonValue == NULL)
+				{
+					char* resp = "{}";
+					*resp_size = strlen(resp);
+					*response = (unsigned char*)malloc(*resp_size);
+					(void)memcpy(*response, resp, *resp_size);
+				}
+				else
+				{
+					*resp_size = strlen(data->jsonValue);
+					*response = (unsigned char*)malloc(*resp_size);
+					(void)memcpy(*response, data->jsonValue, *resp_size);
+				}
+			}
+			MethodReturn_Destroy(methodResult);
+		}
+	}
+	return result;
+}
+
+static void SendConfirmationCallback(IOTHUB_CLIENT_CONFIRMATION_RESULT result, void* userContextCallback)
+{
+	EVENT_INSTANCE* eventInstance = (EVENT_INSTANCE*)userContextCallback;
+
+	(void)printf("Confirmation[%d] received for message tracking id = %u with result = %s\r\n", callbackCounter, eventInstance->messageTrackingId, MU_ENUM_TO_STRING(IOTHUB_CLIENT_CONFIRMATION_RESULT, result));
+
+	/* Some device specific action code goes here... */
+	callbackCounter++;
+	IoTHubMessage_Destroy(eventInstance->messageHandle);
+}
+
+void iothub_client_run(int proto)
+{
+	IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle;
+
+	EVENT_INSTANCE messages[MESSAGE_COUNT];
+	int msg_id = 0;
+	double avgWindSpeed = 10.0;
+	double minTemperature = 20.0;
+	double minHumidity = 60.0;
+	int receiveContext = 0;
+
+	g_continueRunning = true;
+
+	srand((unsigned int)time(NULL));
+
+	callbackCounter = 0;
+
+	if (platform_init() != 0)
+	{
+		(void)printf("Failed to initialize the platform.\r\n");
+	}
+	else {
+		if (serializer_init(NULL) != SERIALIZER_OK)
+		{
+			(void)printf("Failed in serializer_init.");
+		}
+		else if (SERIALIZER_REGISTER_NAMESPACE(WeatherStation) == NULL)
+		{
+			LogError("unable to SERIALIZER_REGISTER_NAMESPACE");
+		}
+		else
+		{
+			IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol;
+			switch (proto) {
+			case 0:
+				(void)printf("Starting the IoTHub client sample HTTP...\r\n");
+				protocol = HTTP_Protocol;
+				break;
+			case 1:
+				(void)printf("Starting the IoTHub client sample MQTT...\r\n");
+				protocol = MQTT_Protocol;
+				break;
+			case 2:
+				(void)printf("Starting the IoTHub client sample MQTT over WebSocket...\r\n");
+				protocol = MQTT_WebSocket_Protocol;
+				break;
+			default:
+				platform_deinit();
+				return;
+			}
+
+			if ((iotHubClientHandle = IoTHubClient_LL_CreateFromConnectionString(connectionString, protocol)) == NULL)
+			{
+				(void)printf("ERROR: iotHubClientHandle is NULL!\r\n");
+			}
+			else
+			{
+				if (g_use_proxy)
+				{
+					if (IoTHubClient_LL_SetOption(iotHubClientHandle, OPTION_HTTP_PROXY, &g_proxy_options) != IOTHUB_CLIENT_OK)
+					{
+						printf("failure to set option \"HTTP Proxy\"\r\n");
+					}
+				}
+#if 0
+				long curl_verbose = 1;
+				if (IoTHubClient_LL_SetOption(iotHubClientHandle, OPTION_CURL_VERBOSE, &curl_verbose) != IOTHUB_CLIENT_OK)
+				{
+					printf("failure to set option \"CURL Verbose\"\r\n");
+				}
+
+				unsigned int timeout = 241000;
+				// Because it can poll "after 9 seconds" polls will happen effectively // at ~10 seconds.
+				// Note that for scalabilty, the default value of minimumPollingTime
+				// is 25 minutes. For more information, see:
+				// https://azure.microsoft.com/documentation/articles/iot-hub-devguide/#messaging
+				unsigned int minimumPollingTime = 9;
+				if (IoTHubClient_LL_SetOption(iotHubClientHandle, "timeout", &timeout) != IOTHUB_CLIENT_OK)
+				{
+					printf("failure to set option \"timeout\"\r\n");
+				}
+
+				if (IoTHubClient_LL_SetOption(iotHubClientHandle, "MinimumPollingTime", &minimumPollingTime) != IOTHUB_CLIENT_OK)
+				{
+					printf("failure to set option \"MinimumPollingTime\"\r\n");
+				}
+
+				bool traceOn = 1;
+				if (IoTHubClient_LL_SetOption(iotHubClientHandle, OPTION_LOG_TRACE, &traceOn) != IOTHUB_CLIENT_OK)
+				{
+					printf("failure to set option \"log trace on\"\r\n");
+				}
+#endif
+#ifdef SET_TRUSTED_CERT_IN_SAMPLES
+				// For mbed add the certificate information
+				if (IoTHubClient_LL_SetOption(iotHubClientHandle, OPTION_TRUSTED_CERT, certificates) != IOTHUB_CLIENT_OK)
+				{
+					printf("failure to set option \"TrustedCerts\"\r\n");
+				}
+#endif // SET_TRUSTED_CERT_IN_SAMPLES
+				AnemometerState *anemometerState = IoTHubDeviceTwin_LL_CreateAnemometerState(iotHubClientHandle);
+				if (anemometerState == NULL)
+				{
+					printf("Failure in IoTHubDeviceTwin_LL_CreateAnemometerState");
+				}
+				else
+				{
+					(void)printf("IoTHubDeviceTwin_LL_CreateAnemometerState...successful.\r\n");
+				}
+				AnemometerSettings *anemometerSettings = IoTHubDeviceTwin_LL_CreateAnemometerSettings(iotHubClientHandle);
+				if (anemometerSettings == NULL)
+				{
+					printf("Failure in IoTHubDeviceTwin_LL_CreateAnemometerSettings");
+				}
+				else
+				{
+					(void)printf("IoTHubDeviceTwin_LL_CreateAnemometerSettings...successful.\r\n");
+				}
+				ContosoAnemometer* myWeather = CREATE_MODEL_INSTANCE(WeatherStation, ContosoAnemometer);
+				if (myWeather == NULL)
+				{
+					(void)printf("Failed on CREATE_MODEL_INSTANCE\r\n");
+				}
+				else if (IoTHubClient_LL_SetDeviceMethodCallback(iotHubClientHandle, ReceiveDeviceMethodCallback, myWeather) != IOTHUB_CLIENT_OK)
+				{
+					(void)printf("ERROR: IoTHubClient_LL_SetDeviceMethodCallback..........FAILED!\r\n");
+				}
+				else
+				{
+					(void)printf("IoTHubClient_LL_SetDeviceMethodCallback...successful.\r\n");
+				}
+				/* Setting Message call back, so we can receive Commands. */
+				if (IoTHubClient_LL_SetMessageCallback(iotHubClientHandle, ReceiveMessageCallback, &receiveContext) != IOTHUB_CLIENT_OK)
+				{
+					(void)printf("ERROR: IoTHubClient_LL_SetMessageCallback..........FAILED!\r\n");
+				}
+				else
+				{
+					(void)printf("IoTHubClient_LL_SetMessageCallback...successful.\r\n");
+				}
+
+				/* Now that we are ready to receive commands, let's send some messages */
+				int iterator = 4000;
+				do
+				{
+					if (iterator >= 5000)
+					{
+						iterator = 0;
+						int msgPos = msg_id % MESSAGE_COUNT;
+						unsigned char *msgText;
+						size_t msgSize;
+						myWeather->windSpeed = avgWindSpeed + (rand() % 4 + 2);
+						myWeather->temperature = minTemperature + (rand() % 10);
+						myWeather->humidity = minHumidity + (rand() % 20);
+						if (SERIALIZE(&msgText, &msgSize, myWeather->windSpeed, myWeather->temperature, myWeather->humidity) != CODEFIRST_OK)
+						{
+							(void)printf("Failed to serialize\r\n");
+						}
+						else if ((messages[msgPos].messageHandle = IoTHubMessage_CreateFromByteArray((const unsigned char*)msgText, msgSize)) == NULL)
+						{
+							(void)printf("ERROR: iotHubMessageHandle is NULL!\r\n");
+							free(msgText);
+						}
+						else
+						{
+							MAP_HANDLE propMap;
+
+							messages[msgPos].messageTrackingId = msg_id;
+
+							propMap = IoTHubMessage_Properties(messages[msgPos].messageHandle);
+							(void)sprintf_s(propText, sizeof(propText), myWeather->temperature > anemometerSettings->threshold.value ? "true" : "false");
+							if (Map_AddOrUpdate(propMap, "temperatureAlert", propText) != MAP_OK)
+							{
+								(void)printf("ERROR: Map_AddOrUpdate Failed!\r\n");
+							}
+
+							if (proto == 0) {
+								(void)IoTHubMessage_SetContentTypeSystemProperty(messages[msgPos].messageHandle, "application/json");
+								(void)IoTHubMessage_SetContentEncodingSystemProperty(messages[msgPos].messageHandle, "utf-8");
+							}
+
+							if (IoTHubClient_LL_SendEventAsync(iotHubClientHandle, messages[msgPos].messageHandle, SendConfirmationCallback, &messages[msgPos]) != IOTHUB_CLIENT_OK)
+							{
+								(void)printf("ERROR: IoTHubClient_LL_SendEventAsync..........FAILED!\r\n");
+							}
+							else
+							{
+								(void)printf("IoTHubClient_LL_SendEventAsync accepted message [%d] for transmission to IoT Hub.\r\n", msg_id);
+							}
+
+							free(msgText);
+							msg_id++;
+						}
+					}
+					else if (g_twinReport) {
+						g_twinReport = false;
+						anemometerState->threshold.value = anemometerSettings->threshold.value;
+						anemometerState->threshold.status = "success";
+						IoTHubDeviceTwin_LL_SendReportedStateAnemometerState(anemometerState, anemometerReportedStateCallback, anemometerState);
+					}
+					iterator++;
+
+					IoTHubClient_LL_DoWork(iotHubClientHandle);
+					ThreadAPI_Sleep(1);
+
+				} while (g_continueRunning);
+
+				(void)printf("iothub_client_run has gotten quit message, call DoWork %d more time to complete final sending...\r\n", DOWORK_LOOP_NUM);
+				for (size_t index = 0; index < DOWORK_LOOP_NUM; index++)
+				{
+					IoTHubClient_LL_DoWork(iotHubClientHandle);
+					ThreadAPI_Sleep(1);
+				}
+
+				if (anemometerSettings != NULL)
+					IoTHubDeviceTwin_LL_DestroyAnemometerSettings(anemometerSettings);
+				if (anemometerState != NULL)
+					IoTHubDeviceTwin_LL_DestroyAnemometerState(anemometerState);
+				if (myWeather != NULL)
+					DESTROY_MODEL_INSTANCE(myWeather);
+				IoTHubClient_LL_Destroy(iotHubClientHandle);
+			}
+			serializer_deinit();
+		}
+		platform_deinit();
+	}
+}
+
+void iothub_client_init()
+{
+#if 0
+	char *set_cs_argv[2] = {
+		"set_cs",
+		"[device connection string]"
+	};
+	set_cs_main(2, set_cs_argv);
+
+	char *set_proxy_argv[2] = {
+		"set_proxy",
+		"example.com:8080"
+	};
+	set_proxy_main(2, set_proxy_argv);
+#endif
+}
+
+int iothub_client_main(int argc, char **argv)
+{
+	if (connectionString == NULL) {
+		printf("Not set connection string, use 'device csgen' or 'device setcs'.\n");
+		return 0;
+	}
+
+	if (argc < 2) {
+		iothub_client_run(1);
+		return 0;
+	}
+
+	if (strcmp(argv[1], "http") == 0) {
+		iothub_client_run(0);
+		return 0;
+	}
+	else if (strcmp(argv[1], "mqtt") == 0) {
+		iothub_client_run(1);
+		return 0;
+	}
+	else if (strcmp(argv[1], "mqttows") == 0) {
+		iothub_client_run(2);
+		return 0;
+	}
+
+	printf("%s [http|mqtt|mqttows] \n", argv[0]);
+	return 0;
+}
Index: azure_iot_hub_riscv/trunk/app_iothub_client/src/client.h
===================================================================
--- azure_iot_hub_riscv/trunk/app_iothub_client/src/client.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/app_iothub_client/src/client.h	(revision 453)
@@ -0,0 +1,19 @@
+#ifndef CLIENT_H
+#define CLIENT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void iothub_client_init(void);
+int iothub_client_main(int argc, char **argv);
+int set_cs_main(int argc, char **argv);
+int set_proxy_main(int argc, char **argv);
+int clear_proxy_main(int argc, char **argv);
+int dps_csgen_main(int argc, char **argv);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CLIENT_H */
Index: azure_iot_hub_riscv/trunk/app_iothub_client/src/code.c
===================================================================
--- azure_iot_hub_riscv/trunk/app_iothub_client/src/code.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/app_iothub_client/src/code.c	(revision 453)
@@ -0,0 +1,260 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+
+// hint on compile; copy the source code here and paste onto ->
+// azure-iot-sdk-c/provisioning_client/samples/prov_dev_client_ll_sample/prov_dev_client_ll_sample.c
+// compile the whole SDK with provisioning enabled
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "iothub.h"
+#include "iothub_message.h"
+#include "iothub_client_version.h"
+#include "azure_c_shared_utility/threadapi.h"
+#include "azure_c_shared_utility/tickcounter.h"
+#include "azure_c_shared_utility/shared_util_options.h"
+#include "azure_c_shared_utility/http_proxy_io.h"
+
+#include "iothub_device_client_ll.h"
+#include "iothub_client_options.h"
+#include "azure_prov_client/prov_device_ll_client.h"
+#include "azure_prov_client/prov_security_factory.h"
+
+#include "iothubtransporthttp.h"
+#include "azure_prov_client/prov_transport_http_client.h"
+#include "iothubtransportmqtt.h"
+#include "azure_prov_client/prov_transport_mqtt_client.h"
+#include "iothubtransportmqtt_websockets.h"
+#include "azure_prov_client/prov_transport_mqtt_ws_client.h"
+#include "client.h"
+
+#define SET_TRUSTED_CERT_IN_SAMPLES
+
+#ifdef SET_TRUSTED_CERT_IN_SAMPLES
+#include "certs.h"
+#endif // SET_TRUSTED_CERT_IN_SAMPLES
+
+extern char* connectionString;
+
+MU_DEFINE_ENUM_STRINGS(PROV_DEVICE_RESULT, PROV_DEVICE_RESULT_VALUE);
+MU_DEFINE_ENUM_STRINGS(PROV_DEVICE_REG_STATUS, PROV_DEVICE_REG_STATUS_VALUES);
+
+static const char *global_prov_uri = "global.azure-devices-provisioning.net";
+static char *g_access_key = NULL;
+
+extern bool g_use_proxy;
+extern HTTP_PROXY_OPTIONS g_proxy_options;
+
+#define MESSAGES_TO_SEND            2
+#define TIME_BETWEEN_MESSAGES       2
+
+typedef struct CLIENT_SAMPLE_INFO_TAG
+{
+	unsigned int sleep_time;
+	char *iothub_uri;
+	char *access_key_name;
+	char *device_key;
+	char *device_id;
+	int registration_complete;
+} CLIENT_SAMPLE_INFO;
+
+typedef struct IOTHUB_CLIENT_SAMPLE_INFO_TAG
+{
+	int connected;
+	int stop_running;
+} IOTHUB_CLIENT_SAMPLE_INFO;
+
+static IOTHUBMESSAGE_DISPOSITION_RESULT receive_msg_callback(IOTHUB_MESSAGE_HANDLE message, void *user_context)
+{
+	(void)message;
+	IOTHUB_CLIENT_SAMPLE_INFO *iothub_info = (IOTHUB_CLIENT_SAMPLE_INFO *)user_context;
+	(void)printf("Stop message recieved from IoTHub\r\n");
+	iothub_info->stop_running = 1;
+	return IOTHUBMESSAGE_ACCEPTED;
+}
+
+static void registation_status_callback(PROV_DEVICE_REG_STATUS reg_status, void *user_context)
+{
+	(void)user_context;
+	(void)printf(".");
+}
+
+static void iothub_connection_status(IOTHUB_CLIENT_CONNECTION_STATUS result, IOTHUB_CLIENT_CONNECTION_STATUS_REASON reason, void *user_context)
+{
+	(void)reason;
+	if (user_context == NULL)
+	{
+		printf("iothub_connection_status user_context is NULL\r\n");
+	}
+	else
+	{
+		IOTHUB_CLIENT_SAMPLE_INFO *iothub_info = (IOTHUB_CLIENT_SAMPLE_INFO *)user_context;
+		if (result == IOTHUB_CLIENT_CONNECTION_AUTHENTICATED)
+		{
+			iothub_info->connected = 1;
+		}
+		else
+		{
+			iothub_info->connected = 0;
+			iothub_info->stop_running = 1;
+		}
+	}
+}
+
+static void register_device_callback(PROV_DEVICE_RESULT register_result, const char *iothub_uri, const char *device_id, void *user_context)
+{
+	if (user_context == NULL)
+	{
+		printf("user_context is NULL\r\n");
+	}
+	else
+	{
+		CLIENT_SAMPLE_INFO *user_ctx = (CLIENT_SAMPLE_INFO *)user_context;
+		if (register_result == PROV_DEVICE_RESULT_OK)
+		{
+			(void)printf("\nRegistration Information received from service: %s!\r\n", iothub_uri);
+			(void)mallocAndStrcpy_s(&user_ctx->iothub_uri, iothub_uri);
+			(void)mallocAndStrcpy_s(&user_ctx->device_id, device_id);
+			user_ctx->registration_complete = 1;
+
+			size_t len = snprintf(NULL, 0,
+				"HostName=%s;DeviceId=%s;SharedAccessKey=%s",
+				iothub_uri,
+				device_id,
+				g_access_key);
+			char *conn_str = (char *)malloc(len + 1);
+			if (conn_str == NULL) {
+				printf("OOM while creating connection string\n");
+				exit(1);
+			}
+
+			snprintf(conn_str, len + 1,
+				"HostName=%s;DeviceId=%s;SharedAccessKey=%s",
+				iothub_uri,
+				device_id,
+				g_access_key);
+			conn_str[len] = 0;
+			free(connectionString);
+			connectionString = conn_str;
+			printf("Connection String:\n%s\n", connectionString);
+		}
+		else
+		{
+			(void)printf("Failure encountered on registration %s\r\n", MU_ENUM_TO_STRING(PROV_DEVICE_RESULT, register_result));
+			user_ctx->registration_complete = 2;
+		}
+	}
+}
+
+int dps_csgen_main(int argc, char *argv[])
+{
+	if (argc < 5) {
+		printf("usage:\ndps_csgen [http|mqtt|mqttows] <scope_id> <device_id> <primary_key (groupSAS)>\n");
+		return 0;
+	}
+
+	IOTHUB_CLIENT_TRANSPORT_PROVIDER iothub_transport;
+	PROV_DEVICE_TRANSPORT_PROVIDER_FUNCTION prov_device_protocol;
+
+	if (strcmp(argv[1], "http") == 0) {
+		iothub_transport = HTTP_Protocol;
+		prov_device_protocol = Prov_Device_HTTP_Protocol;
+	}
+	else if (strcmp(argv[1], "mqtt") == 0) {
+		iothub_transport = MQTT_Protocol;
+		prov_device_protocol = Prov_Device_MQTT_Protocol;
+	}
+	else if (strcmp(argv[1], "mqttows") == 0) {
+		iothub_transport = MQTT_WebSocket_Protocol;
+		prov_device_protocol = Prov_Device_MQTT_WS_Protocol;
+	}
+	else {
+		iothub_transport = MQTT_Protocol;
+		prov_device_protocol = Prov_Device_MQTT_Protocol;
+	}
+
+	const char *scope_id = argv[2];
+	const char *reg_id = argv[3];
+	g_access_key = argv[4];
+	prov_dev_set_symmetric_key_info(reg_id, g_access_key);
+
+	bool traceOn = false;
+
+	(void)IoTHub_Init();
+	(void)prov_dev_security_init(SECURE_DEVICE_TYPE_SYMMETRIC_KEY);
+	HTTP_PROXY_OPTIONS http_proxy;
+	CLIENT_SAMPLE_INFO user_ctx;
+
+	memset(&http_proxy, 0, sizeof(HTTP_PROXY_OPTIONS));
+	memset(&user_ctx, 0, sizeof(CLIENT_SAMPLE_INFO));
+
+	user_ctx.registration_complete = 0;
+	user_ctx.sleep_time = 10;
+
+	PROV_DEVICE_LL_HANDLE handle;
+	if ((handle = Prov_Device_LL_Create(global_prov_uri, scope_id, prov_device_protocol)) == NULL)
+	{
+		(void)printf("failed calling Prov_Device_LL_Create\r\n");
+	}
+	else
+	{
+		if (g_use_proxy)
+		{
+			Prov_Device_LL_SetOption(handle, OPTION_HTTP_PROXY, &g_proxy_options);
+		}
+
+#ifdef SET_TRUSTED_CERT_IN_SAMPLES
+	// For mbed add the certificate information
+		if (Prov_Device_LL_SetOption(handle, OPTION_TRUSTED_CERT, certificates) != PROV_DEVICE_RESULT_OK)
+		{
+			printf("failure to set option \"TrustedCerts\"\r\n");
+		}
+#endif // SET_TRUSTED_CERT_IN_SAMPLES
+
+		Prov_Device_LL_SetOption(handle, PROV_OPTION_LOG_TRACE, &traceOn);
+		if (Prov_Device_LL_Register_Device(handle, register_device_callback, &user_ctx, registation_status_callback, &user_ctx) != PROV_DEVICE_RESULT_OK)
+		{
+			(void)printf("failed calling Prov_Device_LL_Register_Device\r\n");
+		}
+		else
+		{
+			do
+			{
+				Prov_Device_LL_DoWork(handle);
+				ThreadAPI_Sleep(user_ctx.sleep_time);
+			} while (user_ctx.registration_complete == 0);
+		}
+		Prov_Device_LL_Destroy(handle);
+	}
+
+	if (user_ctx.registration_complete != 1)
+	{
+		(void)printf("error: registration failed!\r\n");
+	}
+	else
+	{
+		IOTHUB_DEVICE_CLIENT_LL_HANDLE device_ll_handle;
+
+		if ((device_ll_handle = IoTHubDeviceClient_LL_CreateFromDeviceAuth(user_ctx.iothub_uri, user_ctx.device_id, iothub_transport)) == NULL)
+		{
+			(void)printf("failed create IoTHub client from connection string %s!\r\n", user_ctx.iothub_uri);
+		}
+		else
+		{
+			IOTHUB_CLIENT_SAMPLE_INFO iothub_info;
+			iothub_info.stop_running = 0;
+			iothub_info.connected = 0;
+
+			(void)IoTHubDeviceClient_LL_SetConnectionStatusCallback(device_ll_handle, iothub_connection_status, &iothub_info);
+			IoTHubDeviceClient_LL_Destroy(device_ll_handle);
+		}
+	}
+	free(user_ctx.iothub_uri);
+	free(user_ctx.device_id);
+	prov_dev_security_deinit();
+
+	IoTHub_Deinit();
+	return 0;
+}
Index: azure_iot_hub_riscv/trunk/app_iothub_client/src/command.c
===================================================================
--- azure_iot_hub_riscv/trunk/app_iothub_client/src/command.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/app_iothub_client/src/command.c	(revision 453)
@@ -0,0 +1,151 @@
+#include <kernel.h>
+#include <t_syslog.h>
+#include <stdio.h>
+#include <t_stdlib.h>
+#include <stdlib.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#include "kernel_cfg.h"
+#include "monitor.h"
+#include "device.h"
+
+/*
+ *  デバイスコマンド番号
+ */
+static int_t led_func(int argc, char **argv);
+#ifdef USE_PINGSEND
+static int_t png_func(int argc, char **argv);
+#endif
+extern int iothub_client_main(int argc, char **argv);
+extern int dps_csgen_main(int argc, char *argv[]);
+extern int set_cs_main(int argc, char **argv);
+extern int set_proxy_main(int argc, char **argv);
+extern int clear_proxy_main(int argc, char **argv);
+extern int set_wifi_main(int argc, char **argv);
+
+/*
+ *  デバイスコマンドテーブル
+ */
+static const COMMAND_INFO device_command_info[] = {
+	{"LED",		led_func},
+#ifdef USE_PINGSEND
+	{"PING",    png_func},
+#endif
+	{"IOT",		iothub_client_main},
+	{"CSGEN",	dps_csgen_main},
+	{"SETCS",	set_cs_main},
+	{"PROXY",	set_proxy_main},
+	{"CPRX",	clear_proxy_main},
+	{"WIFI",	set_wifi_main},
+};
+
+#define NUM_DEVICE_CMD   (sizeof(device_command_info)/sizeof(COMMAND_INFO))
+
+static const char device_name[] = "DEVICE";
+static const char device_help[] =
+"  Device  LED (no) (on-1,off-0)  led   control\n"
+#ifdef USE_PINGSEND
+"          PING addr              send  ping   \n"
+#endif
+"          IOT                    connect azure\n"
+"          CSGEN               provision device\n"
+"          SETCS          set connection string\n"
+"          PROXY                  set proxy    \n"
+"          CPRX                   clear proxy  \n"
+"          WIFI                   set ssid pwd \n";
+
+#define LED_PIN       3		/* D13 */
+static const uint16_t led_pattern[1] = {
+	LED_PIN
+};
+
+static COMMAND_LINK device_command_link = {
+	NULL,
+	NUM_DEVICE_CMD,
+	device_name,
+	NULL,
+	device_help,
+	&device_command_info[0]
+};
+
+static int a2i(char *str)
+{
+	int num = 0;
+
+	while(*str >= '0' && *str <= '9'){
+		num = num * 10 + *str++ - '0';
+	}
+	return num;
+}
+
+/*
+ *  DEVICEコマンド設定関数
+ */
+void device_info_init(intptr_t exinf)
+{
+	setup_command(&device_command_link);
+}
+
+/*
+ *  ダイレクトデジタルピン出力
+ */
+void
+digitalWrite(uint8_t Pin, int dwVal){
+    int8_t gpio_pin = gpio_get_gpiohno(Pin, false);
+
+    if( gpio_pin >= 0){
+        gpio_set_pin(TADR_GPIOHS_BASE, (uint8_t)gpio_pin, dwVal);
+    }
+}
+
+/*
+ *  LED設定コマンド関数
+ */
+static int_t led_func(int argc, char **argv)
+{
+	int_t    arg1=0, arg2;
+
+	if(argc < 3)
+		return -1;
+	arg1 = a2i(argv[1]);
+	arg2 = a2i(argv[2]);
+	if(arg1 >= 1 && arg1 <= 4){
+		if(arg2 != 0)
+			digitalWrite(led_pattern[arg1-1], 1);
+		else
+			digitalWrite(led_pattern[arg1-1], 0);
+	}
+	return 0;
+}
+
+
+#ifdef USE_PINGSEND
+/*
+ *  PING送信マンド関数
+ */
+static int_t png_func(int argc, char **argv)
+{
+	const char *addr;
+	uint32_t paddr = 0;
+	int      a, i;
+
+	if(argc < 2)
+		return -1;
+	addr = argv[1];
+	for(i = a = 0 ; i < 4 ; addr++){
+		if(*addr <= '9' && *addr >= '0'){
+			a *= 10;
+			a += *addr - '0';
+		}
+		else{
+			paddr |= a << (i * 8);
+			a = 0;
+			i++;
+		}
+		if(*addr == 0)
+			break;
+	}
+	set_pingaddr(paddr);
+	return 0;
+}
+#endif
Index: azure_iot_hub_riscv/trunk/app_iothub_client/src/envcmd.c
===================================================================
--- azure_iot_hub_riscv/trunk/app_iothub_client/src/envcmd.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/app_iothub_client/src/envcmd.c	(revision 453)
@@ -0,0 +1,308 @@
+/*
+*  TOPPERS/ASP Kernel
+*      Toyohashi Open Platform for Embedded Real-Time Systems/
+*      Advanced Standard Profile Kernel
+* 
+*  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+*                              Toyohashi Univ. of Technology, JAPAN
+*  Copyright (C) 2004-2012 by Embedded and Real-Time Systems Laboratory
+*              Graduate School of Information Science, Nagoya Univ., JAPAN
+* 
+*  ãLì ÒÍCÈºÌ(1)`(4)Ìðð½·êÉÀèC{\tgEF
+*  Ai{\tgEFAðüÏµ½àÌðÜÞDÈº¯¶jðgpE¡»Eü
+*  ÏEÄzziÈºCpÆÄÔj·é±Æð³Åø·éD
+*  (1) {\tgEFAð\[XR[hÌ`Åp·éêÉÍCãLÌì
+*       \¦C±Ìpð¨æÑºLÌ³ÛØKèªC»ÌÜÜÌ`Å\[
+*      XR[hÉÜÜêÄ¢é±ÆD
+*  (2) {\tgEFAðCCu`®ÈÇC¼Ì\tgEFAJ­Ég
+*      pÅ«é`ÅÄzz·éêÉÍCÄzzÉº¤hL
+gip
+*      Ò}j
+AÈÇjÉCãLÌì \¦C±Ìpð¨æÑºL
+*      Ì³ÛØKèðfÚ·é±ÆD
+*  (3) {\tgEFAðC@íÉgÝÞÈÇC¼Ì\tgEFAJ­Ég
+*      pÅ«È¢`ÅÄzz·éêÉÍCÌ¢¸ê©Ìðð½·±
+*      ÆD
+*    (a) ÄzzÉº¤hL
+gipÒ}j
+AÈÇjÉCãLÌ
+*        ì \¦C±Ìpð¨æÑºLÌ³ÛØKèðfÚ·é±ÆD
+*    (b) ÄzzÌ`ÔðCÊÉèßéû@ÉæÁÄCTOPPERSvWFNgÉ
+*        ñ·é±ÆD
+*  (4) {\tgEFAÌpÉæè¼ÚIÜ½ÍÔÚIÉ¶¶é¢©Èé¹
+*      Q©çàCãLì Ò¨æÑTOPPERSvWFNgðÆÓ·é±ÆD
+*      Ü½C{\tgEFAÌ[UÜ½ÍGh[U©çÌ¢©Èé
+*      RÉîÃ­¿©çàCãLì Ò¨æÑTOPPERSvWFNgð
+*      ÆÓ·é±ÆD
+* 
+*  {\tgEFAÍC³ÛØÅñ³êÄ¢éàÌÅ éDãLì Ò¨
+*  æÑTOPPERSvWFNgÍC{\tgEFAÉÖµÄCÁèÌgpÚI
+*  ÉÎ·éK«àÜßÄC¢©ÈéÛØàsíÈ¢DÜ½C{\tgEF
+*  AÌpÉæè¼ÚIÜ½ÍÔÚIÉ¶¶½¢©Èé¹QÉÖµÄàC»
+*  ÌÓCðíÈ¢D
+* 
+*  $Id$
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include "azure_c_shared_utility/shared_util_options.h"
+
+extern char* connectionString;
+
+extern bool g_use_proxy;
+extern HTTP_PROXY_OPTIONS g_proxy_options;
+
+enum proxy_parse_state_t {
+	proxy_parse_state_schema,
+	proxy_parse_state_colonslash,
+	proxy_parse_state_colonslashslash,
+	proxy_parse_state_username,
+	proxy_parse_state_password,
+	proxy_parse_state_address,
+	proxy_parse_state_port,
+	proxy_parse_state_error,
+};
+
+int set_proxy(const char *proxy, bool silent)
+{
+	const char *schema = NULL, *address = NULL, *port = NULL, *username = NULL, *password = NULL;
+	int schema_len = 0, address_len = 0, port_len = 0, username_len = 0, password_len = 0;
+
+	enum proxy_parse_state_t state = proxy_parse_state_schema;
+
+	const char *pos = proxy;
+	schema = pos;
+	for (char c = *pos; c != '\0'; pos++, c = *pos) {
+		switch (state) {
+		case proxy_parse_state_schema:
+			if (c == ':') {
+				schema_len = (int)pos - (int)schema;
+				username = pos + 3;
+				state = proxy_parse_state_colonslash;
+			}
+			break;
+		case proxy_parse_state_colonslash:
+			if (c == '/') {
+				state = proxy_parse_state_colonslashslash;
+			}
+			else {
+				username = schema;
+				username_len = schema_len;
+				schema = NULL;
+				schema_len = 0;
+				password = pos;
+				state = proxy_parse_state_password;
+				goto case_proxy_parse_state_password;
+			}
+			break;
+		case proxy_parse_state_colonslashslash:
+			if (c == '/') {
+				state = proxy_parse_state_username;
+			}
+			else {
+				state = proxy_parse_state_error;
+			}
+			break;
+		case proxy_parse_state_username:
+			if (c == ':') {
+				username_len = (int)pos - (int)username;
+				password = pos + 1;
+				state = proxy_parse_state_password;
+			}
+			else if (c == '@') {
+				username_len = (int)pos - (int)username;
+				address = pos + 1;
+				state = proxy_parse_state_address;
+			}
+			break;
+		case proxy_parse_state_password:
+		case_proxy_parse_state_password:
+			if (c == '@') {
+				password_len = (int)pos - (int)password;
+				address = pos + 1;
+				state = proxy_parse_state_address;
+			}
+			break;
+		case proxy_parse_state_address:
+			if (c == ':') {
+				address_len = (int)pos - (int)address;
+				port = pos + 1;
+				state = proxy_parse_state_port;
+			}
+			break;
+		case proxy_parse_state_port:
+			if ((c < '0') && (c > '9')) {
+				state = proxy_parse_state_error;
+			}
+			break;
+		}
+
+		if (state == proxy_parse_state_error)
+			break;
+	}
+
+	switch (state)
+	{
+	case proxy_parse_state_schema:
+	case proxy_parse_state_colonslash:
+	case proxy_parse_state_colonslashslash:
+		goto error;
+	case proxy_parse_state_username:
+		username_len = (int)pos - (int)username;
+		address = username;
+		address_len = username_len;
+		username = NULL;
+		username_len = 0;
+		break;
+	case proxy_parse_state_password:
+		password_len = (int)pos - (int)password;
+		address = username;
+		address_len = username_len;
+		username = NULL;
+		username_len = 0;
+		port = password;
+		port_len = password_len;
+		password = NULL;
+		password_len = 0;
+		break;
+	case proxy_parse_state_address:
+		address_len = (int)pos - (int)address;
+		break;
+	case proxy_parse_state_port:
+		port_len = (int)pos - (int)port;
+		break;
+	case proxy_parse_state_error:
+	default:
+		goto error;
+	}
+
+	if (schema_len > 0) {
+		if (strncmp(schema, "http", schema_len) != 0)
+			goto error;
+	}
+
+	if (address_len == 0)
+		goto error;
+
+	char *buf = malloc(address_len + port_len + username_len + password_len + 4);
+	if (buf == NULL) {
+		if (!silent)
+			printf("Memory error.\n");
+		return -1;
+	}
+
+	free((char *)g_proxy_options.host_address);
+
+	memcpy(buf, address, address_len);
+	buf[address_len] = '\0';
+	g_proxy_options.host_address = buf;
+
+	buf = buf + address_len + 1;
+	memcpy(buf, port, port_len);
+	buf[port_len] = '\0';
+	g_proxy_options.port = port_len == 0 ? 8080 : atoi(buf);
+
+	buf = buf + port_len + 1;
+	memcpy(buf, username, username_len);
+	buf[username_len] = '\0';
+	g_proxy_options.username = (username_len == 0) && (password_len == 0) ? NULL : buf;
+
+	buf = buf + username_len + 1;
+	memcpy(buf, password, password_len);
+	buf[password_len] = '\0';
+	g_proxy_options.password = (username_len == 0) && (password_len == 0) ? NULL : buf;
+
+	return 0;
+error:
+	if (!silent)
+		printf("proxy string parse error. 'http://[<user>:<password>@]<address>:<port>'\n");
+	return -1;
+}
+
+
+int set_cs_main(int argc, char **argv)
+{
+	if (argc < 2) {
+		printf("usage:\n%s <connection string>\n", argv[0]);
+		return 0;
+	}
+
+	int len = strlen(argv[1]);
+	if (len < 70) {
+		printf("String containing Hostname, Device Id & Device Key in the format:\n");
+		printf("  HostName=<host_name>;DeviceId=<device_id>;SharedAccessKey=<device_key>\n");
+		printf("  HostName=<host_name>;DeviceId=<device_id>;SharedAccessSignature=<device_sas_token>\n");
+		return 0;
+	}
+
+	char *conn_str = (char *)malloc(len + 1);
+	if (conn_str == NULL) {
+		printf("OOM while creating connection string\n");
+		return 1;
+	}
+
+	memcpy(conn_str, argv[1], len);
+	conn_str[len] = 0;
+	free(connectionString);
+	connectionString = conn_str;
+	printf("Connection String:\n%s\n", connectionString);
+
+	return 0;
+}
+
+int set_proxy_main(int argc, char **argv)
+{
+	int result;
+
+	if (argc < 2) {
+		if (g_proxy_options.username != NULL) {
+			printf("HTTP_PROXY=http://%s:%s@%s:%d\n",
+				g_proxy_options.username,
+				g_proxy_options.password,
+				g_proxy_options.host_address,
+				g_proxy_options.port);
+		}
+		else if (g_proxy_options.host_address != NULL) {
+			printf("HTTP_PROXY=http://%s:%d\n",
+				g_proxy_options.host_address,
+				g_proxy_options.port);
+		}
+		else {
+			printf("HTTP_PROXY=\n");
+		}
+		return 0;
+	}
+
+	if ((result = set_proxy(argv[1], false)) == 0) {
+		g_use_proxy = true;
+	}
+	else {
+		g_use_proxy = false;
+	}
+
+	return 0;
+}
+int clear_proxy_main(int argc, char **argv)
+{
+	free((char *)g_proxy_options.host_address);
+	g_proxy_options.host_address = NULL;
+	g_proxy_options.port = 0;
+	g_proxy_options.username = NULL;
+	g_proxy_options.password = NULL;
+
+	g_use_proxy = false;
+	return 0;
+}
+
+int set_wifi_main(int argc, char **argv)
+{
+	if (argc < 3) {
+		return 0;
+	}
+
+	set_ssid_pwd(argv[1], argv[2]);
+
+	prepare_esp_at();
+}
Index: azure_iot_hub_riscv/trunk/app_iothub_client/src/esp_at_socket.c
===================================================================
--- azure_iot_hub_riscv/trunk/app_iothub_client/src/esp_at_socket.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/app_iothub_client/src/esp_at_socket.c	(revision 453)
@@ -0,0 +1,1713 @@
+/*
+*  TOPPERS/ASP Kernel
+*      Toyohashi Open Platform for Embedded Real-Time Systems/
+*      Advanced Standard Profile Kernel
+* 
+*  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+*                              Toyohashi Univ. of Technology, JAPAN
+*  Copyright (C) 2004-2012 by Embedded and Real-Time Systems Laboratory
+*              Graduate School of Information Science, Nagoya Univ., JAPAN
+* 
+*  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+*  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+*  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+*  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+*      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+*      スコード中に含まれていること．
+*  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+*      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+*      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+*      の無保証規定を掲載すること．
+*  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+*      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+*      と．
+*    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+*        作権表示，この利用条件および下記の無保証規定を掲載すること．
+*    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+*        報告すること．
+*  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+*      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+*      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+*      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+*      免責すること．
+* 
+*  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+*  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+*  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+*  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+*  の責任を負わない．
+* 
+*  $Id$
+*/
+#include <stddef.h>
+#include <stdbool.h>
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <target_syssvc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <time.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#include "kernel_cfg.h"
+#include "device.h"
+#include "monitor.h"
+#include "main.h"
+#include "esp_at_socket.h"
+#include "azure_c_shared_utility/esp_at_socket.h"
+#include "azure_c_shared_utility/optimize_size.h"
+
+//#define AT_DEBUG
+time_t MINIMUM_YEAR;
+
+typedef enum at_param_type_t {
+	at_param_number,
+	at_param_string,
+	at_param_symbol,
+} at_param_type_t;
+
+typedef enum at_parse_state_t {
+	at_none,
+	at_informtion,
+	at_response,
+	at_link_id,
+	at_parameter,
+	at_number,
+	at_string_str,
+	at_string_esc,
+	at_string_edq,
+	at_symbol,
+	at_line_text,
+	at_cr,
+	at_crlf,
+	at_receive_data,
+} at_parse_state_t;
+
+typedef struct esp_serial_state_t esp_serial_state_t;
+typedef bool (*set_parameter_t)(esp_serial_state_t *esp_state, int pos, at_param_type_t type, intptr_t value);
+typedef at_parse_state_t (*exec_response_t)(esp_serial_state_t *esp_state, int pos);
+
+typedef struct at_response_table_t {
+	const char *name;
+	set_parameter_t next_parameter;
+	exec_response_t exec_response;
+} at_response_table_t;
+
+typedef enum at_response_kind_t {
+	at_response_kind_no_set,
+	at_response_kind_ok,
+	at_response_kind_send_ok,
+	at_response_kind_busy,
+	at_response_kind_ready,
+	at_response_kind_progress,
+	at_response_kind_connect,
+	at_response_kind_closed,
+	at_response_kind_error,
+	at_response_kind_fail,
+	at_response_kind_already_connect,
+	at_response_kind_received,
+} at_response_kind_t;
+
+typedef enum at_symbol_kind_t {
+	at_symbol_kind_unknown,
+	at_symbol_kind_apip,
+	at_symbol_kind_apmac,
+	at_symbol_kind_staip,
+	at_symbol_kind_stamac,
+	at_symbol_kind_gateway,
+	at_symbol_kind_netmask,
+} at_symbol_kind_t;
+
+typedef enum at_connection_mode_t {
+	at_single_connection_mode,
+	at_multiple_connections_mode
+} at_connection_mode_t;
+
+typedef enum at_encryption_method_t {
+	at_encryption_method_unknown,
+	at_encryption_method_open,
+	at_encryption_method_wep,
+	at_encryption_method_wpa_psk,
+	at_encryption_method_wpa2_psk,
+	at_encryption_method_wpa_wpa2_psk,
+	at_encryption_method_wpa2_enterprise,
+} at_encryption_method_t;
+
+typedef struct esp_ap_status_t {
+	at_encryption_method_t encryption_method;
+	char ssid[36];
+	int rssi;
+	struct ether_addr mac;
+	int channel;
+	int freq_offset;
+	int freq_calibration;
+} esp_ap_status_t;
+
+typedef struct esp_ap_config_t {
+	char ssid[36];
+	char pwd[64];
+	int channel;
+	at_encryption_method_t encryption_method;
+	int max_connection;
+	int ssid_hidden;
+} esp_ap_config_t;
+
+typedef enum at_wifi_mode_t {
+	at_wifi_mode_unknown,
+	at_wifi_mode_station,
+	at_wifi_mode_soft_ap,
+	at_wifi_mode_soft_ap_station,
+}at_wifi_mode_t;
+
+typedef enum at_wifi_state_t {
+	at_wifi_state_disconnected,
+	at_wifi_state_connected,
+	at_wifi_state_got_ip,
+	at_wifi_state_busy,
+}at_wifi_state_t;
+
+typedef struct esp_socket_state_t {
+	at_wifi_mode_t wifi_mode;
+	at_wifi_state_t wifi_state;
+	at_connection_mode_t connection_mode;
+	struct ether_addr ap_mac;
+	struct in_addr ap_ip;
+	struct in_addr ap_gateway;
+	struct in_addr ap_netmask;
+	struct ether_addr sta_mac;
+	struct in_addr sta_ip;
+	struct in_addr sta_gateway;
+	struct in_addr sta_netmask;
+	char ssid[36];
+	struct ether_addr baseid;
+	int channel;
+	int rssi;
+	at_symbol_kind_t symbol_kind;
+	int ap_status_count;
+	esp_ap_status_t ap_status[10];
+	esp_ap_config_t config;
+	int link_id;
+	int length;
+	struct in_addr remote_ip;
+	in_port_t remote_port;
+	int received;
+	int lost;
+	time_t date_time;
+} esp_socket_state_t;
+
+typedef enum esp_state_t {
+	esp_state_echo_off,
+	esp_state_reset,
+	esp_state_set_station_mode,
+	esp_state_auto_connect_to_ap_off,
+	esp_state_set_multiple_connections_mode,
+	esp_state_show_remote_ip_and_port,
+	esp_state_connect_ap,
+	esp_state_update_time,
+	esp_state_get_time,
+	esp_state_done
+} esp_state_t;
+
+typedef struct esp_serial_state_t {
+	esp_state_t esp_state;
+	char *ssid;
+	char *pwd;
+	ID dtqid;
+	at_parse_state_t parse_state;
+	char string[64];
+	int string_pos;
+	int number;
+	const at_response_table_t *response;
+	at_response_kind_t response_kind;
+	int param_pos;
+	esp_socket_state_t params;
+	esp_socket_state_t current_state;
+} esp_serial_state_t;
+
+typedef enum connection_state_t {
+	connection_state_disconnected,
+	connection_state_connecting,
+	connection_state_connected,
+	connection_state_disconnecting,
+} connection_state_t;
+
+typedef struct at_connection_t {
+	int link_id;
+	bool used;
+	connection_state_t state;
+	const char *ssl;
+	bool blocking;
+	unsigned int timeout;
+	esp_serial_state_t *esp_state;
+	uint8_t *rx_buff;
+	uint32_t rx_pos_w;
+	uint32_t rx_pos_r;
+} at_connection_t;
+
+esp_serial_state_t esp_serial_state;
+extern const at_response_table_t response_table[];
+extern const int response_table_count;
+ER esp_serial_clear(esp_serial_state_t *esp_state, TMO tmo);
+ER esp_serial_read(esp_serial_state_t *esp_state, at_response_kind_t *res_kind, TMO tmo);
+ER esp_serial_write(esp_serial_state_t *esp_state, const char *text, at_response_kind_t *res_kind, TMO tmo);
+int connection_read_data(at_connection_t *connection, void *data, int len);
+
+at_connection_t connections[5] = {
+	{ 0, false },
+	{ 1, false },
+	{ 2, false },
+	{ 3, false },
+	{ 4, false },
+};
+
+at_connection_t *new_connection()
+{
+	for (int i = 0; i < sizeof(connections) / sizeof(connections[0]); i++) {
+		at_connection_t *connection = &connections[i];
+		if (connection->used)
+			continue;
+
+		memset(&connection->used, 0, sizeof(*connection) - offsetof(at_connection_t, used));
+		connection->rx_buff = calloc(1, AT_CONNECTION_RX_BUFF_SIZE);
+		if (connection->rx_buff == NULL)
+			return NULL;
+
+		connection->used = true;
+		return connection;
+	}
+
+	return NULL;
+}
+
+void delete_connection(at_connection_t *connection)
+{
+#ifdef AT_DEBUG
+	printf("delete_connection %d\n", connection->link_id);
+#endif
+	free(connection->rx_buff);
+	connection->used = false;
+}
+
+at_connection_t *get_connection(int link_id)
+{
+	for (int i = 0; i < sizeof(connections) / sizeof(connections[0]); i++) {
+		if (connections[i].link_id == link_id) {
+			return &connections[i];
+		}
+	}
+
+	return NULL;
+}
+
+void init_esp_at()
+{
+	struct tm tm = {
+        0,  /* tm_sec */
+        0,  /* tm_min */
+        0,  /* tm_hour */
+        1,  /* tm_mday */
+        0,  /* tm_mon */
+        2020 - 1900,  /* tm_year */
+	};
+	MINIMUM_YEAR = mktime(&tm);
+
+	esp_serial_state.current_state.wifi_mode = at_wifi_mode_station;
+	esp_serial_state.dtqid = DTQ_ESP_AT;
+}
+
+const at_response_table_t *get_response(const char *name)
+{
+	const at_response_table_t *result;
+
+	result = response_table;
+	for (int i = 0; i < response_table_count; i++, result++) {
+		if (strcmp(result->name, name) == 0)
+			return result;
+	}
+
+	return NULL;
+}
+
+at_symbol_kind_t get_symbol(const char *name)
+{
+	if (strcmp("APIP", name) == 0)
+		return at_symbol_kind_apip;
+	if (strcmp("APMAC", name) == 0)
+		return at_symbol_kind_apmac;
+	if (strcmp("STAIP", name) == 0)
+		return at_symbol_kind_staip;
+	if (strcmp("STAMAC", name) == 0)
+		return at_symbol_kind_stamac;
+	if (strcmp("gateway", name) == 0)
+		return at_symbol_kind_gateway;
+	if (strcmp("netmask", name) == 0)
+		return at_symbol_kind_netmask;
+	return at_symbol_kind_unknown;
+}
+
+bool append_char(esp_serial_state_t *esp_state, int c)
+{
+	if (esp_state->string_pos >= sizeof(esp_state->string)) {
+		esp_state->string[0] = '\0';
+		return false;
+	}
+
+	esp_state->string[esp_state->string_pos++] = c;
+
+	return true;
+}
+
+bool proc_atc_res(esp_serial_state_t *esp_state, int c)
+{
+	switch (esp_state->parse_state) {
+	case at_none:
+		if (c == '+') {
+			esp_state->string_pos = 0;
+			esp_state->string[esp_state->string_pos++] = c;
+			esp_state->parse_state = at_informtion;
+			return false;
+		}
+		else if (isalpha(c) || c == '>') {
+			esp_state->string_pos = 0;
+			esp_state->string[esp_state->string_pos++] = c;
+			esp_state->parse_state = at_response;
+			if (c == '>') {
+				append_char(esp_state, '\0');
+				esp_state->response = get_response(esp_state->string);
+				if (esp_state->response != NULL) {
+#ifdef AT_DEBUG
+					printf("\033[35m%s\033[0m\r\n", esp_state->response->name);
+#endif
+					esp_state->parse_state = esp_state->response->exec_response(esp_state, esp_state->param_pos);
+					esp_state->response = NULL;
+					return true;
+				}
+			}
+			return false;
+		}
+		else if (isdigit(c)) {
+			esp_state->number = c - '0';
+			esp_state->parse_state = at_link_id;
+			return false;
+		}
+		else if (c == '\r') {
+			esp_state->parse_state = at_crlf;
+			return false;
+		}
+		return false;
+	case at_informtion:
+		if ((c == ':') || (c == ',')) {
+			append_char(esp_state, '\0');
+			esp_state->response = get_response(esp_state->string);
+			if (esp_state->response != NULL) {
+				esp_state->param_pos = 0;
+				memset(&esp_state->params, 0, sizeof(esp_state->params));
+				esp_state->parse_state = at_parameter;
+				return false;
+			}
+		}
+		else if (isalpha(c) || isdigit(c) || c == ' ') {
+			append_char(esp_state, c);
+			esp_state->parse_state = at_informtion;
+			return false;
+		}
+		break;
+	case at_response:
+		if ((c == '\r') || (c == '.')) {
+			append_char(esp_state, '\0');
+			esp_state->response = get_response(esp_state->string);
+			if (esp_state->response != NULL) {
+				esp_state->param_pos = 0;
+				memset(&esp_state->params, 0, sizeof(esp_state->params));
+				esp_state->parse_state = at_crlf;
+				return false;
+			}
+		}
+		else if (isalpha(c) || isdigit(c) || c == ' ') {
+			append_char(esp_state, c);
+			esp_state->parse_state = at_response;
+			return false;
+		}
+		break;
+	case at_link_id:
+		if (isdigit(c)) {
+			esp_state->parse_state = at_link_id;
+			esp_state->number *= 10;
+			esp_state->number += c - '0';
+			return false;
+		}
+		else if (c == ',') {
+			esp_state->param_pos = 0;
+			memset(&esp_state->params, 0, sizeof(esp_state->params));
+			esp_state->params.link_id = esp_state->number;
+			esp_state->string_pos = 0;
+			esp_state->parse_state = at_response;
+			return false;
+		}
+		break;
+	case at_parameter:
+		if (isdigit(c)) {
+			esp_state->parse_state = at_number;
+			esp_state->number = c - '0';
+			return false;
+		}
+		else if (c == '"') {
+			esp_state->string_pos = 0;
+			esp_state->string[esp_state->string_pos] = '\0';
+			esp_state->parse_state = at_string_str;
+			return false;
+		}
+		else if (isalpha(c)) {
+			esp_state->string_pos = 0;
+			esp_state->string[esp_state->string_pos++] = c;
+			esp_state->parse_state = at_line_text;
+			return false;
+		}
+		break;
+	case at_number:
+		if (isdigit(c)) {
+			esp_state->parse_state = at_number;
+			esp_state->number *= 10;
+			esp_state->number += c - '0';
+			return false;
+		}
+		else if (c == ',') {
+			esp_state->param_pos++;
+			if (esp_state->response->next_parameter(esp_state, esp_state->param_pos, at_param_number, esp_state->number)) {
+				esp_state->parse_state = at_parameter;
+				return false;
+			}
+		}
+		else if (c == ':') {
+			esp_state->param_pos++;
+			if (esp_state->response->next_parameter(esp_state, esp_state->param_pos, at_param_number, esp_state->number)) {
+#ifdef AT_DEBUG
+				printf("\033[35m%s\033[0m\r\n", esp_state->response->name);
+#endif
+				esp_state->parse_state = esp_state->response->exec_response(esp_state, esp_state->param_pos);
+				esp_state->string_pos = 0;
+				esp_state->response = NULL;
+				return true;
+			}
+		}
+		else if (c == '\r') {
+			esp_state->param_pos++;
+			if (esp_state->response->next_parameter(esp_state, esp_state->param_pos, at_param_number, esp_state->number)) {
+				esp_state->parse_state = at_crlf;
+				return false;
+			}
+		}
+		break;
+	case at_string_str:
+		if (c == '"') {
+			esp_state->parse_state = at_string_edq;
+			return false;
+		}
+		else if (c == '\\') {
+			esp_state->parse_state = at_string_esc;
+			return false;
+		}
+		else {
+			append_char(esp_state, c);
+			esp_state->parse_state = at_string_str;
+			return false;
+		}
+		break;
+	case at_string_esc:
+		append_char(esp_state, c);
+		esp_state->parse_state = at_string_str;
+		return false;
+	case at_string_edq:
+		if (c == ',') {
+			append_char(esp_state, '\0');
+			esp_state->param_pos++;
+			if (esp_state->response->next_parameter(esp_state, esp_state->param_pos, at_param_string, (intptr_t)esp_state->string)) {
+				esp_state->parse_state = at_parameter;
+				return false;
+			}
+		}
+		else if (c == '\r') {
+			append_char(esp_state, '\0');
+			esp_state->param_pos++;
+			if (esp_state->response->next_parameter(esp_state, esp_state->param_pos, at_param_string, (intptr_t)esp_state->string)) {
+				esp_state->parse_state = at_crlf;
+				return false;
+			}
+		}
+		break;
+	case at_symbol:
+		if (c == ',' || c == ':') {
+			append_char(esp_state, '\0');
+			esp_state->param_pos++;
+			if (esp_state->response->next_parameter(esp_state, esp_state->param_pos, at_param_symbol, (intptr_t)get_symbol(esp_state->string))) {
+				esp_state->parse_state = at_parameter;
+				return false;
+			}
+		}
+		else if (c == '\r') {
+			append_char(esp_state, '\0');
+			esp_state->param_pos++;
+			if (esp_state->response->next_parameter(esp_state, esp_state->param_pos, at_param_symbol, (intptr_t)get_symbol(esp_state->string))) {
+				esp_state->parse_state = at_crlf;
+				return false;
+			}
+		}
+		else if (isalpha(c) || isdigit(c) || c == ' ') {
+			append_char(esp_state, c);
+			esp_state->parse_state = at_symbol;
+			return false;
+		}
+		break;
+	case at_line_text:
+		if (c == '\r') {
+			append_char(esp_state, '\0');
+			esp_state->param_pos++;
+			if (esp_state->response->next_parameter(esp_state, esp_state->param_pos, at_param_symbol, (intptr_t)esp_state->string)) {
+				esp_state->parse_state = at_crlf;
+				return false;
+			}
+		}
+		else if (isprint(c)) {
+			append_char(esp_state, c);
+			esp_state->parse_state = at_line_text;
+			return false;
+		}
+		break;
+	case at_cr:
+		if (c == '\r') {
+			esp_state->parse_state = at_crlf;
+			return false;
+		}
+		break;
+	case at_crlf:
+		if (c == '\n') {
+			if (esp_state->response != NULL) {
+#ifdef AT_DEBUG
+				printf("\033[35m%s\033[0m\r\n", esp_state->response->name);
+#endif
+				esp_state->parse_state = esp_state->response->exec_response(esp_state, esp_state->param_pos);
+			}
+			else {
+				esp_state->parse_state = at_none;
+			}
+			esp_state->string_pos = 0;
+			esp_state->response = NULL;
+			return true;
+		}
+		else if (c == '\r' || (c == '.')) {
+			esp_state->parse_state = at_crlf;
+			return false;
+		}
+		break;
+	case at_receive_data: {
+		esp_state->current_state.received++;
+		at_connection_t *connection = get_connection(esp_state->current_state.link_id);
+		if (connection != NULL) {
+			int pos = connection->rx_pos_w + 1;
+			if (pos >= AT_CONNECTION_RX_BUFF_SIZE)
+				pos = 0;
+			if (pos != connection->rx_pos_r) {
+				connection->rx_buff[connection->rx_pos_w] = c;
+				connection->rx_pos_w = pos;
+			}
+			else {
+				esp_state->current_state.lost++;
+			}
+		}
+		else {
+			esp_state->current_state.lost++;
+		}
+		if (esp_state->current_state.received >= esp_state->current_state.length) {
+#ifdef AT_DEBUG
+			printf("\033[35mrecv:%d, lost:%d\033[0m\r\n", esp_state->current_state.received, esp_state->current_state.lost);
+#endif
+			esp_state->parse_state = at_none;
+			esp_state->response_kind = at_response_kind_received;
+			return true;
+		}
+		return false;
+	}
+	}
+#ifdef AT_DEBUG
+	if (esp_state->parse_state != at_none)
+		printf("\033[35mparse error. state:%d\033[0m\r\n", esp_state->parse_state);
+#endif
+	esp_state->parse_state = at_none;
+	esp_state->response = NULL;
+	return false;
+}
+
+ER esp_serial_clear(esp_serial_state_t *esp_state, TMO tmo)
+{
+	return ini_dtq(esp_state->dtqid);
+}
+
+ER esp_serial_read(esp_serial_state_t *esp_state, at_response_kind_t *res_kind, TMO tmo)
+{
+	ER ret;
+	intptr_t data = 0;
+	ret = trcv_dtq(esp_state->dtqid, (intptr_t *)&data, tmo);
+	if ((ret != E_OK) && (ret != E_TMOUT)) {
+		printf("trcv_dtq error %s", itron_strerror(ret));
+	}
+	*res_kind = (at_response_kind_t)data;
+	return ret;
+}
+
+ER esp_serial_write(esp_serial_state_t *esp_state, const char *text, at_response_kind_t *res_kind, TMO tmo)
+{
+	ER ret;
+
+	ret = esp_serial_clear(esp_state, 100);
+	if ((ret != E_OK) && (ret != E_TMOUT)) {
+		printf("esp_serial_clear error %s", itron_strerror(ret));
+		return ret;
+	}
+
+#ifdef AT_DEBUG
+	printf("\033[32m%s\033[0m", text);
+#endif
+	ret = serial_wri_dat(AT_PORTID, text, (uint_t)strlen(text));
+	if (ret < 0) {
+		printf("serial_wri_dat error %s", itron_strerror(ret));
+		return ret;
+	}
+
+	return esp_serial_read(esp_state, res_kind, tmo);
+}
+
+int connection_read_data(at_connection_t *connection, void *data, int len)
+{
+	esp_serial_state_t *esp_state = connection->esp_state;
+	int ret = 0;
+
+	for (unsigned char *pos = (unsigned char *)data, *end = &pos[len]; pos < end; pos++) {
+		if (connection->rx_pos_w == connection->rx_pos_r) {
+			return ret;
+		}
+
+		*pos = connection->rx_buff[connection->rx_pos_r];
+		connection->rx_pos_r++;
+		if (connection->rx_pos_r >= AT_CONNECTION_RX_BUFF_SIZE)
+			connection->rx_pos_r = 0;
+
+		ret++;
+	}
+
+	return ret;
+}
+
+static bool at_cipmux_set_param(esp_serial_state_t *esp_state, int pos, at_param_type_t type, intptr_t value)
+{
+	esp_socket_state_t *params = &esp_state->params;
+
+	switch (pos) {
+	case 1:
+		switch (value) {
+		case 0:
+			params->connection_mode = at_single_connection_mode;
+			return true;
+		case 1:
+			params->connection_mode = at_multiple_connections_mode;
+			return true;
+		}
+		break;
+	}
+
+	return false;
+}
+
+static at_parse_state_t at_cipmux_exec(esp_serial_state_t *esp_state, int pos)
+{
+	if (pos >= 1)
+		esp_state->current_state.connection_mode = esp_state->params.connection_mode;
+
+	return at_none;
+}
+
+static bool at_cifsr_set_param(esp_serial_state_t *esp_state, int pos, at_param_type_t type, intptr_t value)
+{
+	esp_socket_state_t *params = &esp_state->params;
+
+	switch (pos) {
+	case 1:
+		params->symbol_kind = (at_symbol_kind_t)value;
+		return true;
+	case 2:
+		switch (params->symbol_kind)
+		{
+		case at_symbol_kind_apip:
+			if (inet_aton((const char *)value, &params->ap_ip)) {
+				return true;
+			}
+			break;
+		case at_symbol_kind_apmac:
+			if (ether_aton_r((const char *)value, &params->ap_mac)) {
+				return true;
+			}
+			break;
+		case at_symbol_kind_staip:
+			if (inet_aton((const char *)value, &params->sta_ip)) {
+				return true;
+			}
+			break;
+		case at_symbol_kind_stamac:
+			if (ether_aton_r((const char *)value, &params->sta_mac)) {
+				return true;
+			}
+			break;
+		}
+		break;
+	}
+
+	return false;
+}
+
+static at_parse_state_t at_cifsr_exec(esp_serial_state_t *esp_state, int pos)
+{
+	if (pos < 2)
+		return at_none;
+
+	switch (esp_state->params.symbol_kind)
+	{
+	case at_symbol_kind_apip:
+		esp_state->current_state.ap_ip = esp_state->params.ap_ip;
+		break;
+	case at_symbol_kind_apmac:
+		esp_state->current_state.ap_mac = esp_state->params.ap_mac;
+		break;
+	case at_symbol_kind_staip:
+		esp_state->current_state.sta_ip = esp_state->params.sta_ip;
+		break;
+	case at_symbol_kind_stamac:
+		esp_state->current_state.sta_mac = esp_state->params.sta_mac;
+		break;
+	}
+
+	return at_none;
+}
+
+static bool at_cipap_set_param(esp_serial_state_t *esp_state, int pos, at_param_type_t type, intptr_t value)
+{
+	esp_socket_state_t *params = &esp_state->params;
+
+	switch (pos) {
+	case 1:
+		params->symbol_kind = (at_symbol_kind_t)value;
+		return true;
+	case 2:
+		switch (params->symbol_kind)
+		{
+		case at_symbol_kind_gateway:
+			if (inet_aton((const char *)value, &params->ap_gateway)) {
+				return true;
+			}
+			break;
+		case at_symbol_kind_netmask:
+			if (inet_aton((const char *)value, &params->ap_netmask)) {
+				return true;
+			}
+			break;
+		}
+		break;
+	}
+
+	return false;
+}
+
+static at_parse_state_t at_cipap_exec(esp_serial_state_t *esp_state, int pos)
+{
+	if (pos < 2)
+		return at_none;
+
+	switch (esp_state->params.symbol_kind)
+	{
+	case at_symbol_kind_gateway:
+		esp_state->current_state.ap_gateway = esp_state->params.ap_gateway;
+		break;
+	case at_symbol_kind_netmask:
+		esp_state->current_state.ap_netmask = esp_state->params.ap_netmask;
+		break;
+	}
+
+	return at_none;
+}
+
+static bool at_cipsntptime_set_param(esp_serial_state_t *esp_state, int pos, at_param_type_t type, intptr_t value)
+{
+	esp_socket_state_t *params = &esp_state->params;
+	struct tm date_time = { 0 };
+
+	switch (pos) {
+	case 1:
+		if (strptime((const char *)value, "%a %b %d %T %Y", &date_time) != NULL) {
+			printf("%04d/%02d/%02d %02d:%02d:%02d\r\n",
+				date_time.tm_year+1900, date_time.tm_mon+1, date_time.tm_mday,
+				date_time.tm_hour, date_time.tm_min, date_time.tm_sec);
+			params->date_time = mktime(&date_time);
+			return true;
+		}
+		break;
+	}
+
+	return false;
+}
+
+static at_parse_state_t at_cipsntptime_exec(esp_serial_state_t *esp_state, int pos)
+{
+	esp_socket_state_t *params = &esp_state->params;
+	struct tm current_time_val = { 0 };
+	time_t current_time = params->date_time;
+
+	if (current_time <= MINIMUM_YEAR)
+		return at_none;
+
+	esp_state->current_state.date_time = current_time;
+	gmtime_r(&current_time, &current_time_val);
+	rtc_set_time((struct tm2 *)&current_time_val);
+
+	current_time = time(NULL);
+	printf("%s\r\n", ctime(&current_time));
+
+	return at_none;
+}
+
+static bool at_cipsta_set_param(esp_serial_state_t *esp_state, int pos, at_param_type_t type, intptr_t value)
+{
+	esp_socket_state_t *params = &esp_state->params;
+
+	switch (pos) {
+	case 1:
+		params->symbol_kind = (at_symbol_kind_t)value;
+		return true;
+	case 2:
+		switch (params->symbol_kind)
+		{
+		case at_symbol_kind_gateway:
+			if (inet_aton((const char *)value, &params->sta_gateway)) {
+				return true;
+			}
+			break;
+		case at_symbol_kind_netmask:
+			if (inet_aton((const char *)value, &params->sta_netmask)) {
+				return true;
+			}
+			break;
+		}
+		break;
+	}
+
+	return false;
+}
+
+static at_parse_state_t at_cipsta_exec(esp_serial_state_t *esp_state, int pos)
+{
+	if (pos < 2)
+		return at_none;
+
+	switch (esp_state->params.symbol_kind)
+	{
+	case at_symbol_kind_gateway:
+		esp_state->current_state.sta_gateway = esp_state->params.sta_gateway;
+		break;
+	case at_symbol_kind_netmask:
+		esp_state->current_state.sta_netmask = esp_state->params.sta_netmask;
+		break;
+	}
+
+	return at_none;
+}
+
+static bool at_cwjap_set_param(esp_serial_state_t *esp_state, int pos, at_param_type_t type, intptr_t value)
+{
+	esp_socket_state_t *params = &esp_state->params;
+
+	switch (pos) {
+	case 1:
+		if (type == at_param_string) {
+			strcpy(params->ssid, (const char *)value);
+			return true;
+		}
+		break;
+	case 2:
+		if (ether_aton_r((const char *)value, &params->baseid)) {
+			return true;
+		}
+		break;
+	case 3:
+		params->channel = (int)value;
+		return true;
+	case 4:
+		params->rssi = (int)value;
+		return true;
+		break;
+	}
+
+	return false;
+}
+
+static at_parse_state_t at_cwjap_exec(esp_serial_state_t *esp_state, int pos)
+{
+	if (pos >= 1)
+		strcpy(esp_state->current_state.ssid, esp_state->params.ssid);
+
+	if (pos >= 2)
+		esp_state->current_state.baseid = esp_state->params.baseid;
+
+	if (pos >= 3)
+		esp_state->current_state.channel = esp_state->params.channel;
+
+	if (pos >= 4)
+		esp_state->current_state.rssi = esp_state->params.rssi;
+
+	return at_none;
+}
+
+static bool at_cwlap_set_param(esp_serial_state_t *esp_state, int pos, at_param_type_t type, intptr_t value)
+{
+	if (esp_state->params.ap_status_count >= sizeof(esp_state->params.ap_status) / sizeof(esp_state->params.ap_status[0]))
+		return false;
+
+	esp_ap_status_t *ap_status = &esp_state->params.ap_status[esp_state->params.ap_status_count];
+
+	switch (pos) {
+	case 1:
+		switch (value) {
+		case 0:
+			ap_status->encryption_method = at_encryption_method_open;
+			return true;
+		case 1:
+			ap_status->encryption_method = at_encryption_method_wep;
+			return true;
+		case 2:
+			ap_status->encryption_method = at_encryption_method_wpa_psk;
+			return true;
+		case 3:
+			ap_status->encryption_method = at_encryption_method_wpa2_psk;
+			return true;
+		case 4:
+			ap_status->encryption_method = at_encryption_method_wpa_wpa2_psk;
+			return true;
+		case 5:
+			ap_status->encryption_method = at_encryption_method_wpa2_enterprise;
+			return true;
+		}
+		break;
+	case 2:
+		strcpy(ap_status->ssid, (const char *)value);
+		return true;
+	case 3:
+		ap_status->rssi = (int)value;
+		return true;
+		break;
+	case 4:
+		if (ether_aton_r((const char *)value, &ap_status->mac)) {
+			return true;
+		}
+		break;
+	case 5:
+		ap_status->channel = (int)value;
+		return true;
+	case 6:
+		ap_status->freq_offset = (int)value;
+		return true;
+	case 7:
+		ap_status->freq_calibration = (int)value;
+		return true;
+	}
+
+	return false;
+}
+
+static at_parse_state_t at_cwlap_exec(esp_serial_state_t *esp_state, int pos)
+{
+	esp_state->params.ap_status_count++;
+
+	return at_none;
+}
+
+static bool at_cwmode_set_param(esp_serial_state_t *esp_state, int pos, at_param_type_t type, intptr_t value)
+{
+	esp_socket_state_t *params = &esp_state->params;
+
+	switch (pos) {
+	case 1:
+		switch (value) {
+		case 1:
+			params->wifi_mode = at_wifi_mode_unknown;
+			return true;
+		case 2:
+			params->wifi_mode = at_wifi_mode_station;
+			return true;
+		case 3:
+			params->wifi_mode = at_wifi_mode_soft_ap;
+			return true;
+		case 4:
+			params->wifi_mode = at_wifi_mode_soft_ap_station;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static at_parse_state_t at_cwmode_exec(esp_serial_state_t *esp_state, int pos)
+{
+	if (pos >= 1)
+		esp_state->current_state.wifi_mode = esp_state->params.wifi_mode;
+
+	return at_none;
+}
+
+static bool at_cwsap_set_param(esp_serial_state_t *esp_state, int pos, at_param_type_t type, intptr_t value)
+{
+	esp_ap_config_t *ap_config = &esp_state->params.config;
+
+	switch (pos) {
+	case 1:
+		strcpy(ap_config->ssid, (const char *)value);
+		return true;
+	case 2:
+		strcpy(ap_config->pwd, (const char *)value);
+		return true;
+	case 3:
+		ap_config->channel = (int)value;
+		return true;
+	case 4:
+		switch (value) {
+		case 0:
+			ap_config->encryption_method = at_encryption_method_open;
+			return true;
+		case 1:
+			ap_config->encryption_method = at_encryption_method_wep;
+			return true;
+		case 2:
+			ap_config->encryption_method = at_encryption_method_wpa_psk;
+			return true;
+		case 3:
+			ap_config->encryption_method = at_encryption_method_wpa2_psk;
+			return true;
+		case 4:
+			ap_config->encryption_method = at_encryption_method_wpa_wpa2_psk;
+			return true;
+		case 5:
+			ap_config->encryption_method = at_encryption_method_wpa2_enterprise;
+			return true;
+		}
+		break;
+	case 5:
+		ap_config->max_connection = (int)value;
+		break;
+	case 6:
+		switch (value) {
+		case 0:
+			ap_config->ssid_hidden = 0;
+			return true;
+		case 1:
+			ap_config->ssid_hidden = 1;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static at_parse_state_t at_cwsap_exec(esp_serial_state_t *esp_state, int pos)
+{
+	return at_none;
+}
+
+static bool at_ipd_set_param(esp_serial_state_t *esp_state, int pos, at_param_type_t type, intptr_t value)
+{
+	esp_socket_state_t *params = &esp_state->params;
+
+	switch (pos) {
+	case 1:
+		if ((value >= 0) && (value <= 4)) {
+			params->link_id = (int)value;
+			return true;
+		}
+		break;
+	case 2:
+		if ((value >= 1) && (value <= AT_CONNECTION_RX_BUFF_SIZE)) {
+			params->length = (int)value;
+			return true;
+		}
+		break;
+	case 3:
+		if (inet_aton((const char *)value, &params->remote_ip)) {
+			return true;
+		}
+		break;
+	case 4:
+		if (value >= 0 && value < 65536) {
+			params->remote_port = (in_port_t)value;
+			return true;
+		}
+		break;
+	}
+
+	return false;
+}
+
+static at_parse_state_t at_ipd_exec(esp_serial_state_t *esp_state, int pos)
+{
+	if (pos >= 1)
+		esp_state->current_state.link_id = esp_state->params.link_id;
+	if (pos >= 2)
+		esp_state->current_state.length = esp_state->params.length;
+	if (pos >= 3)
+		esp_state->current_state.remote_ip = esp_state->params.remote_ip;
+	if (pos >= 4)
+		esp_state->current_state.remote_port = esp_state->params.remote_port;
+
+	esp_state->current_state.received = 0;
+	esp_state->current_state.lost = 0;
+	esp_state->response_kind = at_response_kind_no_set;
+
+	return at_receive_data;
+}
+
+static bool at_already_connect_set_param(esp_serial_state_t *esp_state, int pos, at_param_type_t type, intptr_t value)
+{
+	// 引数なし
+	return false;
+}
+
+static at_parse_state_t at_already_connect_exec(esp_serial_state_t *esp_state, int pos)
+{
+	at_connection_t *connection = get_connection(esp_state->params.link_id);
+	if (connection != NULL) {
+		connection->state = connection_state_connected;
+	}
+
+	esp_state->response_kind = at_response_kind_already_connect;
+
+	return at_none;
+}
+
+static bool at_error_set_param(esp_serial_state_t *esp_state, int pos, at_param_type_t type, intptr_t value)
+{
+	// 引数なし
+	return false;
+}
+
+static at_parse_state_t at_error_exec(esp_serial_state_t *esp_state, int pos)
+{
+	esp_state->response_kind = at_response_kind_error;
+
+	return at_none;
+}
+
+static bool at_fail_set_param(esp_serial_state_t *esp_state, int pos, at_param_type_t type, intptr_t value)
+{
+	// 引数なし
+	return false;
+}
+
+static at_parse_state_t at_fail_exec(esp_serial_state_t *esp_state, int pos)
+{
+	esp_state->response_kind = at_response_kind_fail;
+
+	return at_none;
+}
+
+static bool at_ok_set_param(esp_serial_state_t *esp_state, int pos, at_param_type_t type, intptr_t value)
+{
+	// 引数なし
+	return false;
+}
+
+static at_parse_state_t at_ok_exec(esp_serial_state_t *esp_state, int pos)
+{
+	esp_state->response_kind = at_response_kind_ok;
+
+	return at_none;
+}
+
+static bool at_send_ok_set_param(esp_serial_state_t *esp_state, int pos, at_param_type_t type, intptr_t value)
+{
+	// 引数なし
+	return false;
+}
+
+static at_parse_state_t at_send_ok_exec(esp_serial_state_t *esp_state, int pos)
+{
+	esp_state->response_kind = at_response_kind_send_ok;
+
+	return at_none;
+}
+
+static bool at_wifi_connected_set_param(esp_serial_state_t *esp_state, int pos, at_param_type_t type, intptr_t value)
+{
+	// 引数なし
+	return false;
+}
+
+static at_parse_state_t at_wifi_connected_exec(esp_serial_state_t *esp_state, int pos)
+{
+	esp_state->current_state.wifi_state = at_wifi_state_connected;
+
+	return at_none;
+}
+
+static bool at_wifi_disconnect_set_param(esp_serial_state_t *esp_state, int pos, at_param_type_t type, intptr_t value)
+{
+	// 引数なし
+	return false;
+}
+
+static at_parse_state_t at_wifi_disconnect_exec(esp_serial_state_t *esp_state, int pos)
+{
+	esp_state->current_state.wifi_state = at_wifi_state_disconnected;
+
+	return at_none;
+}
+
+static bool at_wifi_got_ip_set_param(esp_serial_state_t *esp_state, int pos, at_param_type_t type, intptr_t value)
+{
+	// 引数なし
+	return false;
+}
+
+static at_parse_state_t at_wifi_got_ip_exec(esp_serial_state_t *esp_state, int pos)
+{
+	esp_state->current_state.wifi_state = at_wifi_state_got_ip;
+
+	return at_none;
+}
+
+static bool at_busy_set_param(esp_serial_state_t *esp_state, int pos, at_param_type_t type, intptr_t value)
+{
+	// 引数なし
+	return false;
+}
+
+static at_parse_state_t at_busy_exec(esp_serial_state_t *esp_state, int pos)
+{
+	esp_state->response_kind = at_response_kind_busy;
+	esp_state->current_state.wifi_state = at_wifi_state_busy;
+
+	return at_none;
+}
+
+static bool at_ready_set_param(esp_serial_state_t *esp_state, int pos, at_param_type_t type, intptr_t value)
+{
+	// 引数なし
+	return false;
+}
+
+static at_parse_state_t at_ready_exec(esp_serial_state_t *esp_state, int pos)
+{
+	esp_state->response_kind = at_response_kind_ready;
+	esp_state->current_state.wifi_state = at_wifi_state_disconnected;
+
+	return at_none;
+}
+
+static bool at_progress_set_param(esp_serial_state_t *esp_state, int pos, at_param_type_t type, intptr_t value)
+{
+	// 引数なし
+	return false;
+}
+
+static at_parse_state_t at_progress_exec(esp_serial_state_t *esp_state, int pos)
+{
+	esp_state->response_kind = at_response_kind_progress;
+
+	return at_none;
+}
+
+static bool at_connect_set_param(esp_serial_state_t *esp_state, int pos, at_param_type_t type, intptr_t value)
+{
+	// 引数なし
+	return false;
+}
+
+static at_parse_state_t at_connect_exec(esp_serial_state_t *esp_state, int pos)
+{
+	at_connection_t *connection = get_connection(esp_state->params.link_id);
+	if (connection != NULL) {
+		connection->state = connection_state_connected;
+	}
+
+	esp_state->response_kind = at_response_kind_connect;
+
+	return at_none;
+}
+
+static bool at_closed_set_param(esp_serial_state_t *esp_state, int pos, at_param_type_t type, intptr_t value)
+{
+	// 引数なし
+	return false;
+}
+
+static at_parse_state_t at_closed_exec(esp_serial_state_t *esp_state, int pos)
+{
+	at_connection_t *connection = get_connection(esp_state->params.link_id);
+	if (connection != NULL) {
+		connection->state = connection_state_disconnected;
+	}
+
+	esp_state->response_kind = at_response_kind_closed;
+
+	return at_none;
+}
+
+const at_response_table_t response_table[] = {
+	{ "+CIPMUX", at_cipmux_set_param, at_cipmux_exec },
+	{ "+CIFSR", at_cifsr_set_param, at_cifsr_exec },
+	{ "+CIPAP", at_cipap_set_param, at_cipap_exec },
+	{ "+CIPSNTPTIME", at_cipsntptime_set_param, at_cipsntptime_exec },
+	{ "+CIPSTA", at_cipsta_set_param, at_cipsta_exec },
+	{ "+CWJAP", at_cwjap_set_param, at_cwjap_exec },
+	{ "+CWLAP", at_cwlap_set_param, at_cwlap_exec },
+	{ "+CWMODE", at_cwmode_set_param, at_cwmode_exec },
+	{ "+CWSAP", at_cwsap_set_param, at_cwsap_exec },
+	{ "+IPD", at_ipd_set_param, at_ipd_exec },
+	{ "ALREADY CONNECT", at_already_connect_set_param, at_already_connect_exec },
+	{ "ERROR", at_error_set_param, at_error_exec },
+	{ "FAIL", at_fail_set_param, at_fail_exec },
+	{ "OK", at_ok_set_param, at_ok_exec },
+	{ "SEND OK", at_send_ok_set_param, at_send_ok_exec },
+	{ "WIFI CONNECTED", at_wifi_connected_set_param, at_wifi_connected_exec },
+	{ "WIFI DISCONNECT", at_wifi_disconnect_set_param, at_wifi_disconnect_exec },
+	{ "WIFI GOT IP", at_wifi_got_ip_set_param, at_wifi_got_ip_exec },
+	{ "busy p", at_busy_set_param, at_busy_exec },
+	{ "ready", at_ready_set_param, at_ready_exec },
+	{ ">", at_progress_set_param, at_progress_exec },
+	{ "CONNECT", at_connect_set_param, at_connect_exec},
+	{ "CLOSED", at_closed_set_param, at_closed_exec},
+};
+const int response_table_count = sizeof(response_table) / sizeof(response_table[0]);
+
+int esp_at_rx_handler(void *data, int len)
+{
+	esp_serial_state_t *esp_state = &esp_serial_state;
+	uint8_t *c = (uint8_t *)data;
+	ER ret;
+
+	for (uint8_t *end = &c[len]; c < end; c++) {
+		if (proc_atc_res(esp_state, *c)) {
+			if (esp_state->response_kind != at_response_kind_no_set) {
+				ret = tsnd_dtq(esp_state->dtqid, (intptr_t)esp_state->response_kind, 20);
+				if (ret != E_OK) {
+					printf("snd_dtq error %s\n", itron_strerror(ret));
+				}
+				esp_state->response_kind = at_response_kind_no_set;
+			}
+		}
+	}
+
+	return (int)((intptr_t)c - (intptr_t)data);
+}
+
+void set_ssid_pwd(const char *ssid, const char *pwd)
+{
+	esp_serial_state_t *esp_state = &esp_serial_state;
+
+	free(esp_state->ssid);
+	esp_state->ssid = strdup(ssid);
+	free(esp_state->pwd);
+	esp_state->pwd = strdup(pwd);
+}
+
+bool prepare_esp_at()
+{
+	esp_serial_state_t *esp_state = &esp_serial_state;
+	ER ret;
+	char temp[64];
+	int tmo = 0;
+	at_response_kind_t res_kind = at_response_kind_no_set;
+
+	if (esp_state->current_state.wifi_state != at_wifi_state_got_ip)
+		esp_state->esp_state = esp_state_echo_off;
+
+retry:
+	ret = esp_serial_clear(esp_state, 100);
+	if ((ret != E_OK) && (ret != E_TMOUT))
+		return false;
+
+	switch (esp_state->esp_state) {
+	case esp_state_reset:
+		ret = esp_serial_write(esp_state, "AT+RST\r\n", &res_kind, 10000);
+		if ((ret != E_OK) || (res_kind != at_response_kind_ok)) {
+			printf("reset error %s %d\n", itron_strerror(ret), res_kind);
+			return false;
+		}
+
+		ret = esp_serial_read(esp_state, &res_kind, 10000);
+		if ((ret != E_OK) || (res_kind != at_response_kind_ready)) {
+			printf("ready error %s %d\n", itron_strerror(ret), res_kind);
+			return false;
+		}
+		esp_state->esp_state = esp_state_echo_off;
+	case esp_state_echo_off:
+		ret = esp_serial_write(esp_state, "ATE0\r\n", &res_kind, 10000);
+		if ((ret != E_OK) || (res_kind != at_response_kind_ok)) {
+			printf("echo off error %s %d\n", itron_strerror(ret), res_kind);
+			break;
+		}
+		esp_state->esp_state = esp_state_set_station_mode;
+	case esp_state_set_station_mode:
+		ret = esp_serial_write(esp_state, "AT+CWMODE=1\r\n", &res_kind, 10000);
+		if ((ret != E_OK) || (res_kind != at_response_kind_ok)) {
+			printf("set station mode error %s %d\n", itron_strerror(ret), res_kind);
+			break;
+		}
+		esp_state->esp_state = esp_state_auto_connect_to_ap_off;
+	case esp_state_auto_connect_to_ap_off:
+		ret = esp_serial_write(esp_state, "AT+CWAUTOCONN=0\r\n", &res_kind, 10000);
+		if ((ret != E_OK) || (res_kind != at_response_kind_ok)) {
+			printf("auto connect off error %s %d\n", itron_strerror(ret), res_kind);
+			break;
+		}
+		esp_state->esp_state = esp_state_set_multiple_connections_mode;
+	case esp_state_set_multiple_connections_mode:
+		ret = esp_serial_write(esp_state, "AT+CIPMUX=1\r\n", &res_kind, 10000);
+		if ((ret != E_OK) || (res_kind != at_response_kind_ok)) {
+			printf("set multiple connections mode error %s %d\n", itron_strerror(ret), res_kind);
+			break;
+		}
+		esp_state->esp_state = esp_state_show_remote_ip_and_port;
+	case esp_state_show_remote_ip_and_port:
+		ret = esp_serial_write(esp_state, "AT+CIPDINFO=1\r\n", &res_kind, 10000);
+		if ((ret != E_OK) || (res_kind != at_response_kind_ok)) {
+			printf("show remote ip/port error %s %d\n", itron_strerror(ret), res_kind);
+			break;
+		}
+		esp_state->esp_state = esp_state_connect_ap;
+	case esp_state_connect_ap:
+		if ((esp_state->ssid == NULL) || (esp_state->pwd == NULL)) {
+			printf("ssid psw error %s %d\n", itron_strerror(ret), res_kind);
+			break;
+		}
+
+		sprintf(temp, "AT+CWJAP=\"%s\",\"%s\"\r\n", esp_state->ssid, esp_state->pwd);
+		ret = esp_serial_write(esp_state, temp, &res_kind, 20000);
+		if ((ret != E_OK) || (res_kind != at_response_kind_ok)) {
+			printf("connect wifi error %s %d\n", itron_strerror(ret), res_kind);
+			break;
+		}
+		esp_state->esp_state = esp_state_update_time;
+	case esp_state_update_time:
+		sprintf(temp, "AT+CIPSNTPCFG=%d,%d,\"%s\"\r\n", 1, 9, "ntp.nict.jp");
+		ret = esp_serial_write(esp_state, temp, &res_kind, 10000);
+		if ((ret != E_OK) || (res_kind != at_response_kind_ok)) {
+			printf("ntp config error %s %d\n", itron_strerror(ret), res_kind);
+			break;
+		}
+		esp_state->esp_state = esp_state_get_time;
+	case esp_state_get_time:
+		ret = esp_serial_write(esp_state, "AT+CIPSNTPTIME?\r\n", &res_kind, 10000);
+		if ((ret != E_OK) || (res_kind != at_response_kind_ok)) {
+			printf("get time error %s %d\n", itron_strerror(ret), res_kind);
+			break;
+		}
+		if (esp_state->current_state.date_time <= MINIMUM_YEAR) {
+			tmo++;
+			if (tmo < 10) {
+				printf("retry to get time %s\n", ctime(NULL));
+				dly_tsk(1000);
+				esp_state->esp_state = esp_state_get_time;
+				goto retry;
+			}
+		}
+		esp_state->esp_state = esp_state_done;
+	case esp_state_done: {
+		time_t ntp = esp_state->current_state.date_time;
+		time_t local = time(NULL);
+		if ((local > ntp) && ((local - ntp) > 60 * 60)) {
+			esp_state->esp_state = esp_state_get_time;
+			goto retry;
+		}
+		return true;
+	}
+	default:
+		esp_state->esp_state = esp_state_echo_off;
+		goto retry;
+	}
+
+	if (res_kind == at_response_kind_busy){
+		esp_state->esp_state = esp_state_reset;
+		goto retry;
+	}
+
+	printf("prepare error %s %d\n", itron_strerror(ret), res_kind);
+	esp_state->esp_state = esp_state_echo_off;
+	return false;
+}
+
+ESP_AT_SOCKET_HANDLE esp_at_socket_create(bool ssl)
+{
+	at_connection_t *connection = new_connection();
+	if (connection == NULL)
+		return NULL;
+
+	connection->ssl = ssl ? "SSL" : "TCP";
+	connection->esp_state = &esp_serial_state;
+
+	return (ESP_AT_SOCKET_HANDLE)connection;
+}
+
+void esp_at_socket_set_blocking(ESP_AT_SOCKET_HANDLE espAtSocketHandle, bool blocking, unsigned int timeout)
+{
+	at_connection_t *connection = (at_connection_t *)espAtSocketHandle;
+
+	connection->blocking = blocking;
+	connection->timeout = timeout;
+
+#ifdef AT_DEBUG
+	printf("\033[35mblocking:%s timeout:%d\033[0m\n", blocking ? "true" : "false", timeout);
+#endif
+}
+
+void esp_at_socket_destroy(ESP_AT_SOCKET_HANDLE espAtSocketHandle)
+{
+	at_connection_t *connection = (at_connection_t *)espAtSocketHandle;
+
+	delete_connection(connection);
+}
+
+int esp_at_socket_connect(ESP_AT_SOCKET_HANDLE espAtSocketHandle, const char *host, const int port)
+{
+	at_connection_t *connection = (at_connection_t *)espAtSocketHandle;
+	at_response_kind_t res_kind;
+
+	if (connection->state == connection_state_connected) {
+		printf("esp_at_socket_connect state error %d\n", connection->state);
+		return 0;
+	}
+
+	if (!prepare_esp_at()) {
+		printf("prepare_esp_at error\n");
+		return -MU_FAILURE;
+	}
+
+	connection->state = connection_state_connecting;
+
+	ER ret;
+	char temp[64];
+	sprintf(temp, "AT+CIPSTART=%d,\"%s\",\"%s\",%d\r\n", connection->link_id, connection->ssl, host, port);
+	ret = esp_serial_write(connection->esp_state, temp, &res_kind, 10000);
+	if ((ret != E_OK) || (res_kind != at_response_kind_connect)) {
+		printf("connect error connect %s %d\n", itron_strerror(ret), res_kind);
+		return -MU_FAILURE;
+	}
+	ret = esp_serial_read(connection->esp_state, &res_kind, 10000);
+	if ((ret != E_OK) || (res_kind != at_response_kind_ok)) {
+		printf("connect error done %s %d\n", itron_strerror(ret), res_kind);
+		return -MU_FAILURE;
+	}
+#ifdef AT_DEBUG
+	printf("\033[35mconnected !\033[0m\n");
+#endif
+	return 0;
+}
+
+bool esp_at_socket_is_connected(ESP_AT_SOCKET_HANDLE espAtSocketHandle)
+{
+	at_connection_t *connection = (at_connection_t *)espAtSocketHandle;
+
+	return connection->state == connection_state_connected;
+}
+
+void esp_at_socket_close(ESP_AT_SOCKET_HANDLE espAtSocketHandle)
+{
+	at_connection_t *connection = (at_connection_t *)espAtSocketHandle;
+	at_response_kind_t res_kind;
+
+	if (connection->state == connection_state_disconnected) {
+		printf("esp_at_socket_close state error %d\n", connection->state);
+		return;
+	}
+
+	connection->state = connection_state_disconnecting;
+
+	ER ret;
+	char temp[64];
+	sprintf(temp, "AT+CIPCLOSE=%d\r\n", connection->link_id);
+	ret = esp_serial_write(connection->esp_state, temp, &res_kind, 10000);
+	if (ret == E_OK) {
+		if (res_kind == at_response_kind_closed) {
+			ret = esp_serial_read(connection->esp_state, &res_kind, 10000);
+		}
+		if ((ret == E_OK) && (res_kind == at_response_kind_ok)) {
+			return;
+		}
+	}
+
+	printf("close error %s %d\n", itron_strerror(ret), res_kind);
+}
+
+int esp_at_socket_send(ESP_AT_SOCKET_HANDLE espAtSocketHandle, const char *data, int length)
+{
+	at_connection_t *connection = (at_connection_t *)espAtSocketHandle;
+	at_response_kind_t res_kind;
+
+	if (connection->state != connection_state_connected) {
+		printf("esp_at_socket_send state error %d\n", connection->state);
+		return -MU_FAILURE;
+	}
+
+	ER ret;
+	char temp[64];
+	sprintf(temp, "AT+CIPSEND=%d,%d\r\n", connection->link_id, length);
+	ret = esp_serial_write(connection->esp_state, temp, &res_kind, 10000);
+	if ((ret != E_OK) || (res_kind != at_response_kind_ok)) {
+		printf("send error command %s %d\n", itron_strerror(ret), res_kind);
+		return -MU_FAILURE;
+	}
+	do {
+		ret = esp_serial_read(connection->esp_state, &res_kind, 10000);
+		if ((ret != E_OK) || ((res_kind != at_response_kind_ok)
+			&& (res_kind != at_response_kind_progress))) {
+			printf("send error progress %s %d\n", itron_strerror(ret), res_kind);
+			return -MU_FAILURE;
+		}
+	} while(res_kind == at_response_kind_ok);
+	ret = serial_wri_dat(AT_PORTID, data, length);
+	if (ret < 0) {
+		printf("send error write data %s\n", itron_strerror(ret));
+		return -MU_FAILURE;
+	}
+	do {
+		ret = esp_serial_read(connection->esp_state, &res_kind, 60000);
+		if (ret != E_OK) {
+			printf("send error done %s\n", itron_strerror(ret));
+			break;
+		}
+		if (res_kind == at_response_kind_send_ok)
+			return length;
+	} while ((res_kind == at_response_kind_no_set)
+		|| (res_kind == at_response_kind_ok));
+
+	printf("send error done kind=%d\n", res_kind);
+
+	return -MU_FAILURE;
+}
+
+int esp_at_socket_receive(ESP_AT_SOCKET_HANDLE espAtSocketHandle, char *data, int length)
+{
+	at_connection_t *connection = (at_connection_t *)espAtSocketHandle;
+
+	if (connection->state != connection_state_connected) {
+		printf("esp_at_socket_receive state error %d\n", connection->state);
+		return -MU_FAILURE;
+	}
+
+	int ret;
+	ret = connection_read_data(connection, data, length);
+	if (ret < 0) {
+		printf("receive error %s\n", itron_strerror(ret));
+		return -MU_FAILURE;
+	}
+#ifdef AT_DEBUG
+	if (ret > 0)
+		printf("\033[35mreceived %d\033[0m\n", ret);
+#endif
+	return ret;
+}
Index: azure_iot_hub_riscv/trunk/app_iothub_client/src/esp_at_socket.h
===================================================================
--- azure_iot_hub_riscv/trunk/app_iothub_client/src/esp_at_socket.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/app_iothub_client/src/esp_at_socket.h	(revision 453)
@@ -0,0 +1,69 @@
+/*
+*  TOPPERS/ASP Kernel
+*      Toyohashi Open Platform for Embedded Real-Time Systems/
+*      Advanced Standard Profile Kernel
+* 
+*  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+*                              Toyohashi Univ. of Technology, JAPAN
+*  Copyright (C) 2004-2012 by Embedded and Real-Time Systems Laboratory
+*              Graduate School of Information Science, Nagoya Univ., JAPAN
+* 
+*  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+*  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+*  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+*  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+*      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+*      スコード中に含まれていること．
+*  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+*      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+*      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+*      の無保証規定を掲載すること．
+*  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+*      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+*      と．
+*    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+*        作権表示，この利用条件および下記の無保証規定を掲載すること．
+*    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+*        報告すること．
+*  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+*      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+*      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+*      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+*      免責すること．
+* 
+*  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+*  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+*  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+*  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+*  の責任を負わない．
+* 
+*  $Id$
+*/
+
+#ifndef _ESP_AT_SOCKET_H_
+#define _ESP_AT_SOCKET_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#define ETH_ALEN	6
+struct ether_addr {
+	uint8_t ether_addr_octet[ETH_ALEN];
+};
+
+typedef uint16_t in_port_t;
+typedef uint32_t in_addr_t;
+
+struct in_addr {
+	in_addr_t s_addr;
+};
+
+struct ether_addr *ether_aton_r(const char *x, struct ether_addr *p_a);
+int inet_aton(const char *s0, struct in_addr *dest);
+
+void init_esp_at();
+
+/*ESPのバッファサイズ*/
+#define AT_CONNECTION_RX_BUFF_SIZE 4096
+
+#endif /* _ESP_AT_SOCKET_H_ */
Index: azure_iot_hub_riscv/trunk/app_iothub_client/src/kpu_main.c
===================================================================
--- azure_iot_hub_riscv/trunk/app_iothub_client/src/kpu_main.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/app_iothub_client/src/kpu_main.c	(revision 453)
@@ -0,0 +1,569 @@
+/*
+*  TOPPERS/ASP Kernel
+*      Toyohashi Open Platform for Embedded Real-Time Systems/
+*      Advanced Standard Profile Kernel
+* 
+*  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+*                              Toyohashi Univ. of Technology, JAPAN
+*  Copyright (C) 2004-2012 by Embedded and Real-Time Systems Laboratory
+*              Graduate School of Information Science, Nagoya Univ., JAPAN
+* 
+*  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+*  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+*  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+*  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+*      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+*      スコード中に含まれていること．
+*  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+*      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+*      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+*      の無保証規定を掲載すること．
+*  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+*      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+*      と．
+*    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+*        作権表示，この利用条件および下記の無保証規定を掲載すること．
+*    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+*        報告すること．
+*  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+*      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+*      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+*      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+*      免責すること．
+* 
+*  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+*  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+*  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+*  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+*  の責任を負わない．
+* 
+*  $Id$
+*/
+
+#include <kernel.h>
+#include <stdlib.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <target_syssvc.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#include "device.h"
+#include "pinmode.h"
+#include "sipeed_st7789.h"
+#include "sipeed_ov2640.h"
+#include "storagedevice.h"
+#ifdef SDEV_SENSE_ONETIME
+#include "spi_driver.h"
+#include "sddiskio.h"
+#else
+#include "rom_file.h"
+#endif
+#include "kernel_cfg.h"
+#include "kpu_main.h"
+#include "kpu.h"
+#include "region_layer.h"
+
+extern void ai_dma_done_isr(DMA_Handle_t *dma);
+
+/*
+*  サービスコールのエラーのログ出力
+*/
+Inline void
+svc_perror(const char *file, int_t line, const char *expr, ER ercd)
+{
+	if (ercd < 0) {
+		t_perror(LOG_ERROR, file, line, expr, ercd);
+	}
+}
+
+#define	SVC_PERROR(expr)	svc_perror(__FILE__, __LINE__, #expr, (expr))
+
+#define SWAP_32(x) ((x >> 24) | (x >> 8 & 0xff00) | (x << 8 & 0xff0000) | (x << 24))
+
+#ifndef SPI1DMATX_SEM
+#define SPI1DMATX_SEM   0
+#endif
+
+#define CLASS_NUMBER 20
+
+LCD_Handler_t  LcdHandle;
+LCD_DrawProp_t DrawProp;
+DVP_Handle_t   DvpHandle;
+OV2640_t       CameraHandle;
+
+uint8_t  sTxBuffer[16];
+
+static uint8_t time_string[12];
+
+static void
+set_value(uint8_t *buf, int value)
+{
+	buf[1] = (value % 10) + '0';
+	buf[0] = (value / 10) + '0';
+}
+
+static void
+set_time(uint8_t *buf, struct tm2 *tm)
+{
+	buf[8] = 0;
+	set_value(&buf[6], tm->tm_sec);
+	buf[5] = ':';
+	set_value(&buf[3], tm->tm_min);
+	buf[2] = ':';
+	set_value(&buf[0], tm->tm_hour);
+}
+
+/*
+*  ダイレクトデジタルピン設定
+*/
+void
+pinMode(uint8_t Pin, uint8_t dwMode){ 
+	int gpionum = gpio_get_gpiohno(Pin, false);
+	GPIO_Init_t init = {0};
+
+	syslog_2(LOG_NOTICE, "## pinMode Pin(%d) gpionum(%d) ##", Pin, gpionum);
+	if(gpionum >= 0){
+		uint8_t function = FUNC_GPIOHS0 + gpionum;
+		fpioa_set_function(Pin, function);
+		switch(dwMode){
+		case INPUT:
+			init.mode = GPIO_MODE_INPUT;
+			init.pull = GPIO_NOPULL;
+			break;
+		case INPUT_PULLDOWN:
+			init.mode = GPIO_MODE_INPUT;
+			init.pull = GPIO_PULLDOWN;
+			break;
+		case INPUT_PULLUP:
+			init.mode = GPIO_MODE_INPUT;
+			init.pull = GPIO_PULLUP;
+			break;
+		case OUTPUT:
+		default:
+			init.mode = GPIO_MODE_OUTPUT;
+			init.pull = GPIO_PULLDOWN;
+			break;
+		}
+		gpio_setup(TADR_GPIOHS_BASE, &init, (uint8_t)gpionum);
+	}
+	return ;
+}
+
+void digitalWrite(uint8_t Pin, int dwVal);
+
+#if (CLASS_NUMBER > 1)
+typedef struct
+{
+	char *str;
+	uint16_t color;
+	uint16_t height;
+	uint16_t width;
+} class_lable_t;
+
+class_lable_t class_lable[CLASS_NUMBER] =
+{
+	{"aeroplane", ST7789_GREEN},
+	{"bicycle", ST7789_GREEN},
+	{"bird", ST7789_GREEN},
+	{"boat", ST7789_GREEN},
+	{"bottle", 0xF81F},
+	{"bus", ST7789_GREEN},
+	{"car", ST7789_GREEN},
+	{"cat", ST7789_GREEN},
+	{"chair", 0xFD20},
+	{"cow", ST7789_GREEN},
+	{"diningtable", ST7789_GREEN},
+	{"dog", ST7789_GREEN},
+	{"horse", ST7789_GREEN},
+	{"motorbike", ST7789_GREEN},
+	{"person", 0xF800},
+	{"pottedplant", ST7789_GREEN},
+	{"sheep", ST7789_GREEN},
+	{"sofa", ST7789_GREEN},
+	{"train", ST7789_GREEN},
+	{"tvmonitor", 0xF9B6}
+};
+
+static uint32_t lable_string_draw_ram[115 * 16 * 8 / 2];
+#endif
+extern uint8_t model_data[];
+kpu_model_context_t g_task;
+static region_layer_t detect_rl;
+
+volatile uint8_t g_ai_done_flag;
+
+void ai_done(void *ctx)
+{
+	g_ai_done_flag = 2;
+}
+
+#define ANCHOR_NUM 5
+float g_anchor[ANCHOR_NUM * 2] = {1.08, 1.19, 3.42, 4.41, 6.63, 11.38, 9.42, 5.11, 16.62, 10.52};
+
+static void drawboxes(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2, uint32_t class, float prob)
+{
+	if (x1 >= 320)
+		x1 = 319;
+	if (x2 >= 320)
+		x2 = 319;
+	if (y1 >= 240)
+		y1 = 239;
+	if (y2 >= 240)
+		y2 = 239;
+
+#if (CLASS_NUMBER > 1)
+	DrawProp.TextColor = class_lable[class].color;
+	lcd_drawRect(&DrawProp, x1, y1, x2-x1, y2-y1);
+	DrawProp.TextColor = ST7789_WHITE;
+	DrawProp.BackColor = class_lable[class].color;
+	DrawProp.pFont = &Font12;
+	lcd_DisplayStringAt(&DrawProp, x1 + 1, y1 + 1, class_lable[class].str, LEFT_MODE);
+#else
+	lcd_drawRect(&DrawProp, x1, y1, x2, y2, 2, ST7789_RED);
+#endif
+}
+
+/*
+*  メインタスク
+*/
+void kpu_task(intptr_t exinf)
+{
+	SPI_Init_t Init;
+	SPI_Handle_t    *hspi;
+	LCD_Handler_t   *hlcd;
+	OV2640_t        *hcmr;
+	DVP_Handle_t    *hdvp;
+	uint16_t        *lcd_buffer;
+	ER_UINT	ercd;
+	uint32_t i, count;
+	struct tm2 time;
+	unsigned long atmp;
+#ifdef SDEV_SENSE_ONETIME
+	StorageDevice_t *psdev;
+	SDCARD_Handler_t *hsd = NULL;
+#else
+	uint32_t esize, fsize, headlen;
+	uint8_t  *addr;
+#endif
+
+	SVC_PERROR(syslog_msk_log(LOG_UPTO(LOG_INFO), LOG_UPTO(LOG_EMERG)));
+	syslog(LOG_NOTICE, "Sample program starts (exinf = %d).", (int_t) exinf);
+
+	pinMode(LED_PIN, OUTPUT);
+
+	select_spi0_dvp_mode(1);
+
+#ifdef SDEV_SENSE_ONETIME
+	pinMode(SPI_SS_PIN, OUTPUT);
+	digitalWrite(SPI_SS_PIN, HIGH);
+#else	/* USE ROMFILE */
+	rom_file_init();
+	esize = 1*1024*1024;
+	addr  = (uint8_t *)romfont;
+	while(esize > 4){
+		fsize = (addr[0] << 24) | (addr[1] << 16) | (addr[2] << 8) | addr[3];
+		if((fsize & 3) != 0 || fsize < 16 || fsize > esize)
+			break;
+		for(i = 0 ; i < 28 ; i++){
+			if(addr[i+4] == 0)
+				break;
+		}
+		if(i >= 28)
+			break;
+		if(i < 12)
+			headlen = 16;
+		else
+			headlen = 32;
+		if(create_rom_file((const char *)(addr+4), (uintptr_t)(addr+headlen), fsize-headlen) < 0)
+			break;
+		addr += fsize;
+		esize -= fsize;
+	}
+#endif
+
+	hcmr = &CameraHandle;
+	hcmr->frameSize = FRAMESIZE_QVGA;
+	hcmr->pixFormat = PIXFORMAT_RGB565;
+	ov2640_getResolition(hcmr, FRAMESIZE_QVGA);
+	hcmr->_resetPoliraty  = ACTIVE_HIGH;
+	hcmr->_pwdnPoliraty   = ACTIVE_HIGH;
+	hcmr->_slaveAddr      = 0x00;
+	hcmr->_dataBuffer     = NULL;
+	hcmr->_aiBuffer       = NULL;
+
+	// just support RGB565 and YUV442 on k210
+
+	// Initialize the camera bus, 8bit reg
+	hdvp = &DvpHandle;
+	hcmr->hdvp = hdvp;
+	hdvp->Init.Freq         = 24000000;
+	hdvp->Init.Width        = hcmr->_width;
+	hdvp->Init.Height       = hcmr->_height;
+	hdvp->Init.Format       = DVP_FORMAT_RGB;
+	hdvp->Init.BurstMode    = DVP_BURST_ENABLE;
+	hdvp->Init.AutoMode     = DVP_AUTOMODE_DISABLE;
+	hdvp->Init.GMMlen       = 4;
+
+	hdvp->Init.num_sccb_reg = 8;
+	hdvp->Init.CMosPClkPin  = 47;
+	hdvp->Init.CMosXClkPin  = 46;
+	hdvp->Init.CMosHRefPin  = 45;
+	hdvp->Init.CMosPwDnPin  = 44;
+	hdvp->Init.CMosVSyncPin = 43;
+	hdvp->Init.CMosRstPin   = 42;
+	hdvp->Init.SccbSClkPin  = 41;
+	hdvp->Init.SccbSdaPin   = 40;
+	hdvp->Init.IntNo        = INTNO_DVP;
+	syslog_1(LOG_NOTICE, "## DvpHandle[%08x] ##", &DvpHandle);
+
+	syslog_3(LOG_NOTICE, "## hcmr->_width(%d) hcmr->_height(%d) size[%08x] ##", hcmr->_width, hcmr->_height, (hcmr->_width * hcmr->_height * 2));
+	atmp = (unsigned long)malloc(hcmr->_width * hcmr->_height * 2 + 64); //RGB565
+	hcmr->_dataBuffer = (uint32_t *)((atmp + 63) & ~63);
+	if(hcmr->_dataBuffer == NULL){
+		hcmr->_width = 0;
+		hcmr->_height = 0;
+		syslog_0(LOG_ERROR, "Can't allocate _dataBuffer !");
+		slp_tsk();
+	}
+	atmp = (unsigned long)malloc(hcmr->_width * hcmr->_height * 3 + 128);   //RGB888
+	hcmr->_aiBuffer = (uint32_t *)((atmp + 127) & ~127);
+	if(hcmr->_aiBuffer == NULL){
+		hcmr->_width = 0;
+		hcmr->_height = 0;
+		free(hcmr->_dataBuffer);
+		hcmr->_dataBuffer = NULL;
+		syslog_0(LOG_ERROR, "Can't allocate _aiBuffer !");
+		slp_tsk();
+	}
+	syslog_2(LOG_NOTICE, "## hcmr->_dataBuffer[%08x] hcmr->_aiBuffer[%08x] ##", hcmr->_dataBuffer, hcmr->_aiBuffer);
+	atmp = (unsigned long)hcmr->_aiBuffer - IOMEM;
+	hdvp->Init.RedAddr    = (uint32_t)atmp;
+	atmp = (unsigned long)hcmr->_aiBuffer + hcmr->_width * hcmr->_height - IOMEM;
+	hdvp->Init.GreenAddr  = (uint32_t)atmp;
+	atmp = (unsigned long)hcmr->_aiBuffer + hcmr->_width * hcmr->_height * 2 - IOMEM;
+	hdvp->Init.BlueAddr   = (uint32_t)atmp;
+	atmp = (unsigned long)hcmr->_dataBuffer - IOMEM;
+	hdvp->Init.RGBAddr    = (uint32_t)atmp;
+	dvp_init(hdvp);
+
+	if(ov2640_sensor_ov_detect(hcmr) == E_OK){
+		syslog_0(LOG_NOTICE, "find ov sensor !");
+	}
+	else if(ov2640_sensro_gc_detect(hcmr) == E_OK){
+		syslog_0(LOG_NOTICE, "find gc3028 !");
+	}
+	if(ov2640_reset(hcmr) != E_OK){
+		syslog_0(LOG_ERROR, "ov2640 reset error !");
+		slp_tsk();
+	}
+	if(ov2640_set_pixformat(hcmr) != E_OK){
+		syslog_0(LOG_ERROR, "set pixformat error !");
+		slp_tsk();
+	}
+	if(ov2640_set_framesize(hcmr) != E_OK){
+		syslog_0(LOG_ERROR, "set frame size error !");
+		slp_tsk();
+	}
+	if(ov2640_setInvert(hcmr, false) != E_OK){
+		syslog_0(LOG_ERROR, "set invert error !");
+		slp_tsk();
+	}
+	syslog_1(LOG_NOTICE, "OV2640 id(%d)", ov2640_id(hcmr));
+
+	Init.WorkMode     = SPI_WORK_MODE_0;
+	Init.FrameFormat  = SPI_FF_OCTAL;
+	Init.DataSize     = 8;
+	Init.Prescaler    = 15000000;
+	Init.SignBit      = 0;
+	Init.InstLength   = 8;
+	Init.AddrLength   = 0;
+	Init.WaitCycles   = 0;
+	Init.IATransMode  = SPI_AITM_AS_FRAME_FORMAT;
+	Init.SclkPin      = SIPEED_ST7789_SCLK_PIN;
+	Init.MosiPin      = -1;
+	Init.MisoPin      = -1;
+	Init.SsPin        = SIPEED_ST7789_SS_PIN;
+	Init.SsNo         = SIPEED_ST7789_SS;
+	Init.TxDMAChannel = SIPEED_DMA_CH;
+	Init.RxDMAChannel = -1;
+	Init.semid        = SPI1TRN_SEM;
+	Init.semlock      = SPI1LOCK_SEM;
+	Init.semdmaid     = SPI1DMATX_SEM;
+	hspi = spi_init(SPI_PORTID, &Init);
+	if(hspi == NULL){
+		syslog_0(LOG_ERROR, "SPI INIT ERROR");
+		slp_tsk();
+	}
+
+	hlcd = &LcdHandle;
+	hlcd->hspi    = hspi;
+//	hlcd->spi_lock= SPI1LOCK_SEM;
+	hlcd->dir     = DIR_YX_LRUD;
+	hlcd->dcx_pin = SIPEED_ST7789_DCX_PIN;
+	hlcd->rst_pin = SIPEED_ST7789_RST_PIN;
+	hlcd->cs_sel  = SIPEED_ST7789_SS;
+	hlcd->rst_no  = SIPEED_ST7789_RST_GPIONUM;
+	hlcd->dcx_no  = SIPEED_ST7789_DCX_GPIONUM;
+	DrawProp.hlcd = hlcd;
+	lcd_init(hlcd);
+	syslog_2(LOG_NOTICE, "width(%d) height(%d)", hlcd->_width, hlcd->_height);
+	count = hcmr->_width * hcmr->_height;
+	lcd_buffer = (uint16_t *)malloc(count * 2);
+	if(lcd_buffer == NULL){
+		syslog_0(LOG_ERROR, "no lcd buffer !");
+		slp_tsk();
+	}
+	DrawProp.BackColor = ST7789_WHITE;
+	DrawProp.TextColor = ST7789_BLACK;
+	lcd_fillScreen(&DrawProp);
+
+#ifdef SDEV_SENSE_ONETIME
+	Init.WorkMode     = SPI_WORK_MODE_0;
+	Init.FrameFormat  = SPI_FF_STANDARD;
+	Init.DataSize     = 8;
+	Init.Prescaler    = 5000000;
+	Init.SignBit      = 0;
+	Init.InstLength   = 0;
+	Init.AddrLength   = 0;
+	Init.WaitCycles   = 0;
+	Init.IATransMode  = SPI_AITM_STANDARD;
+	Init.SclkPin      = SPI_SCK_PIN;
+	Init.MosiPin      = SPI_MOSI_PIN;
+	Init.MisoPin      = SPI_MISO_PIN;
+	Init.SsPin        = -1;
+	Init.SsNo         = -1;
+	Init.TxDMAChannel = -1;
+	Init.RxDMAChannel = SPI_DMA1_CH;
+	Init.semid        = SPI2TRN_SEM;
+	Init.semlock      = SPI2LOCK_SEM;
+	Init.semdmaid     = SPI2DMATX_SEM;
+	hspi = spi_init(SPICARD_PORTID, &Init);
+	if(hspi == NULL){
+		syslog_0(LOG_ERROR, "SPI-CARD INIT ERROR");
+		slp_tsk();
+	}
+	sdcard_setspi2(SPISDCARD_PORTID, hspi, SPI_SS_PIN);
+
+	/*
+	*  SD-CARD SPI通信設定
+	*/
+	for(i = 0 ; i < 10 ; i++)
+		sTxBuffer[i] = 0xff;
+	if((ercd = spi_core_transmit(hspi, -1, (uint8_t*)sTxBuffer, 10)) != E_OK){
+		/* Transfer error in transmission process */
+		syslog_1(LOG_NOTICE, "## call Error_Handler(2)(%d) ##", ercd);
+	}
+#if SPI_WAIT_TIME == 0
+	if((ercd = spi_wait(hspi, 100)) != E_OK){
+		syslog_0(LOG_NOTICE, "## call Error_Handler(3) ##");
+	}
+#endif
+	dly_tsk(100);
+	SDMSence_task(0);
+	psdev = SDMGetStorageDevice(SDCARD_DEVNO);
+	hsd = (SDCARD_Handler_t *)psdev->_sdev_local[1];
+	if(hsd == NULL)
+		syslog_0(LOG_ERROR, "SD-CARD INITAIL ERROR !");
+#endif
+	extern DMA_Handle_t g_ai_hdma;
+	g_ai_hdma.chnum = AI_DMA_CH;
+	g_ai_hdma.xfercallback = ai_dma_done_isr;
+	g_ai_hdma.errorcallback     = NULL;
+	g_ai_hdma.Init.Request      = DMA_SELECT_AI_RX_REQ;	/* DMA選択 */
+	g_ai_hdma.Init.Direction    = DMA_PERIPH_TO_MEMORY;	/* DMA転送方向 */
+	g_ai_hdma.Init.SrcMultBlock = DMAC_MULTBLOCK_CONT;	/* ソースマルチブロックタイプ */
+	g_ai_hdma.Init.DrcMultBlock = DMAC_MULTBLOCK_CONT;	/* デスティネーションマルチブロックタイプ */
+	g_ai_hdma.Init.SrcHandShake = DMAC_HS_HARDWARE;	/* ソースハンドシェイク */
+	g_ai_hdma.Init.DrcHandShake = DMAC_HS_SOFTWARE;	/* デスティネーションハンドシェイク */
+	g_ai_hdma.Init.SrcHwhsPol   = DMAC_HWHS_POLARITY_LOW;	/* ソースハードウェアハンドシェイク極性 */
+	g_ai_hdma.Init.DrcHwhsPol   = DMAC_HWHS_POLARITY_LOW;	/* デスティネーションハードウェアハンドシェイク極性 */
+	g_ai_hdma.Init.Priority     = 4;	/* 優先度 */
+	g_ai_hdma.Init.SrcMaster    = DMAC_MASTER1;	/* ソースマスター設定 */
+	g_ai_hdma.Init.DstMaster    = DMAC_MASTER2;	/* デスティネーションマスター設定 */
+	g_ai_hdma.Init.SrcInc       = DMAC_ADDR_NOCHANGE;	/* ソースインクリメント設定 */
+	g_ai_hdma.Init.DstInc       = DMAC_ADDR_INCREMENT;	/* デスティネーションインクリメント設定 */
+	g_ai_hdma.Init.SrcTransWidth = DMAC_TRANS_WIDTH_32;	/* ソース転送幅 */
+	g_ai_hdma.Init.DstTransWidth = DMAC_TRANS_WIDTH_32;	/* デスティネーション転送幅 */
+	g_ai_hdma.Init.SrcBurstSize = DMAC_MSIZE_4;	/* ソースバーストサイズ */
+	g_ai_hdma.Init.DstBurstSize = DMAC_MSIZE_4;	/* デスティネーションバーストサイズ */
+	g_ai_hdma.Init.IocBlkTrans  = 0;	/* IOCブロック転送 */
+	g_ai_hdma.localdata         = (void *)&g_task;
+	if ((ercd = dma_init(&g_ai_hdma)) != E_OK) {
+		syslog_0(LOG_ERROR, "AI-DMA INITAIL ERROR !");
+	}
+
+	if (kpu_load_kmodel(&g_task, model_data) != 0) {
+		syslog_0(LOG_ERROR, "kmodel init error");
+		slp_tsk();
+	}
+
+	detect_rl.anchor_number = ANCHOR_NUM;
+	detect_rl.anchor = g_anchor;
+	detect_rl.threshold = 0.7;
+	detect_rl.nms_value = 0.3;
+	region_layer_init(&detect_rl, 10, 7, 125, 320, 240);
+
+	bool_t camok = true;
+	if((ercd = ov2640_activate(hcmr, true)) != E_OK){
+		syslog_2(LOG_NOTICE, "ov2640 activate error result(%d) id(%d) ##", ercd, ov2640_id(hcmr));
+		camok = false;
+	}
+
+	int tmo = 0;
+	g_ai_done_flag = 0;
+	while (camok) {
+		if (g_ai_done_flag == 0) {
+			ercd = ov2640_snapshot(hcmr);
+			if (ercd != E_OK) {
+				camok = false;
+				continue;
+			}
+			g_ai_done_flag = 1;
+
+			/* start to calculate */
+			atmp = (unsigned long)hcmr->_aiBuffer - IOMEM;
+			kpu_run_kmodel(&g_task, (const uint8_t *)atmp, AI_DMA_CH, ai_done, NULL);
+
+			uint32_t *p = (uint32_t *)hcmr->_dataBuffer;
+			uint32_t *q = (uint32_t *)lcd_buffer;
+			uint32_t *e = (uint32_t *)&lcd_buffer[count];
+			for (; q < e ; p++, q++){
+				*q = SWAP_32(*p);
+			}
+		}
+
+		if (g_ai_done_flag == 1) {
+			tmo++;
+			if (tmo >= 10) {
+				tmo = 0;
+				g_ai_done_flag = 0;
+			}
+			else {
+				dly_tsk(1);
+			}
+			continue;
+		}
+		else if (g_ai_done_flag == 2) {
+			g_ai_done_flag = 0;
+			float *output;
+			size_t output_size;
+			kpu_get_output(&g_task, 0, &output, &output_size);
+			detect_rl.input = output;
+
+			/* start region layer */
+			region_layer_run(&detect_rl, NULL);
+		}
+
+		lcd_drawPicture(hlcd, 0, 0, hcmr->_width, hcmr->_height, lcd_buffer);
+
+		/* draw boxs */
+		region_layer_draw_boxes(&detect_rl, drawboxes);
+	}
+	ov2640_activate(hcmr, false);
+
+	syslog_0(LOG_NOTICE, "## STOP ##");
+	slp_tsk();
+	syslog(LOG_NOTICE, "Sample program ends.");
+	SVC_PERROR(ext_ker());
+	assert(0);
+}
Index: azure_iot_hub_riscv/trunk/app_iothub_client/src/kpu_main.h
===================================================================
--- azure_iot_hub_riscv/trunk/app_iothub_client/src/kpu_main.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/app_iothub_client/src/kpu_main.h	(revision 453)
@@ -0,0 +1,149 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ *
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ *
+ *  $Id$
+ */
+
+/*
+ *		サンプルプログラム(1)のヘッダファイル
+ */
+
+/*
+ *  ターゲット依存の定義
+ */
+#include "target_test.h"
+#include "glcd_disp.h"
+
+/*
+ *  各タスクの優先度の定義
+ */
+
+#define KPU_PRIORITY	5		/* メインタスクの優先度 */
+								/* HIGH_PRIORITYより高くすること */
+
+/*
+ *  ターゲットに依存する可能性のある定数の定義
+ */
+
+#ifndef TASK_PORTID
+#define	TASK_PORTID		1			/* 文字入力するシリアルポートID */
+#endif /* TASK_PORTID */
+
+#ifndef KPU_STACK_SIZE
+#define	KPU_STACK_SIZE		8192		/* タスクのスタックサイズ */
+#endif /* KPU_STACK_SIZE */
+
+
+#define SIPEED_ST7789_RST_PIN    37
+#define SIPEED_ST7789_DCX_PIN    38
+#define SIPEED_ST7789_SS_PIN     36
+#define SIPEED_ST7789_SCLK_PIN   39
+
+// default peripheral
+#define SIPEED_ST7789_RST_GPIONUM  6
+#define SIPEED_ST7789_DCX_GPIONUM  7
+#define SIPEED_ST7789_SS           3
+
+#define SPISDCARD_PORTID    0
+
+#define SPI_SCK_PIN   27
+#define SPI_MISO_PIN  26
+#define SPI_MOSI_PIN  28
+#define SPI_SS_PIN    29
+#define LED_PIN       3		/* D13 */
+
+#define SPI_PORTID    SPI1_PORTID
+#define INHNO_SPI     IRQ_VECTOR_SPI0	/* 割込みハンドラ番号 */
+#define INTNO_SPI     IRQ_VECTOR_SPI0	/* 割込み番号 */
+#define INTPRI_SPI    -5		/* 割込み優先度 */
+#define INTATR_SPI    0			/* 割込み属性 */
+
+#define SIPEED_DMA_CH DMA_CHANNEL3
+#define INHNO_DMATX   IRQ_VECTOR_DMA3	/* 割込みハンドラ番号 */
+#define INTNO_DMATX   IRQ_VECTOR_DMA3	/* 割込み番号 */
+#define INTPRI_DMATX  -4		/* 割込み優先度 */
+#define INTATR_DMATX  0			/* 割込み属性 */
+
+#define SPICARD_PORTID SPI2_PORTID
+#define INHNO_SPIC    IRQ_VECTOR_SPI1	/* 割込みハンドラ番号 */
+#define INTNO_SPIC    IRQ_VECTOR_SPI1	/* 割込み番号 */
+#define INTPRI_SPIC   -5		/* 割込み優先度 */
+#define INTATR_SPIC   0			/* 割込み属性 */
+
+#define SPI_DMA1_CH   DMA_CHANNEL2
+#define INHNO_DMARX   IRQ_VECTOR_DMA2	/* 割込みハンドラ番号 */
+#define INTNO_DMARX   IRQ_VECTOR_DMA2	/* 割込み番号 */
+#define INTPRI_DMARX  -4		/* 割込み優先度 */
+#define INTATR_DMARX  0			/* 割込み属性 */
+
+#define INHNO_AI      IRQ_VECTOR_AI	/* 割込みハンドラ番号 */
+#define INTNO_AI      IRQ_VECTOR_AI	/* 割込み番号 */
+#define INTPRI_AI     -4		/* 割込み優先度 */
+#define INTATR_AI     0			/* 割込み属性 */
+
+#define AI_DMA_CH     DMA_CHANNEL5
+#define INHNO_DMAAI   IRQ_VECTOR_DMA5	/* 割込みハンドラ番号 */
+#define INTNO_DMAAI   IRQ_VECTOR_DMA5	/* 割込み番号 */
+#define INTPRI_DMAAI  -4		/* 割込み優先度 */
+#define INTATR_DMAAI  0			/* 割込み属性 */
+
+#define HIGH 0x1
+#define LOW  0x0
+
+#define INPUT           0x0
+#define OUTPUT          0x3
+#define INPUT_PULLUP    0x2
+#define INPUT_PULLDOWN  0X1
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  ヒープ領域の設定
+ */
+extern intptr_t heap_param[2];
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+
+extern void kpu_task(intptr_t exinf);
+extern void heap_init(intptr_t exinf);
+extern void ai_done_isr(intptr_t exinf);
+
+#endif /* TOPPERS_MACRO_ONLY */
Index: azure_iot_hub_riscv/trunk/app_iothub_client/src/main.c
===================================================================
--- azure_iot_hub_riscv/trunk/app_iothub_client/src/main.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/app_iothub_client/src/main.c	(revision 453)
@@ -0,0 +1,364 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2012 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *  ESP-WROOM-02テストの本体
+ *  シールド上のプッシュスイッチがESP-WROOM-02の
+ *  リセットスイッチです．リセット後、ATコマンドを使って、
+ *  ESP-WROOM-02と通信ができます。
+ *  例えば、AT+GMRは、AT GMR(return)でESP-WROOM-02に送信され
+ *  ESP-WROOM-02からの受信データはコンソールに表示されます．
+ */
+
+#include <stddef.h>
+#include <stdbool.h>
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <target_syssvc.h>
+#include <stdio.h>
+#include <string.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#include "kernel_cfg.h"
+#include "device.h"
+#include "monitor.h"
+#include "main.h"
+#include "esp_at_socket.h"
+
+/*
+ *  サービスコールのエラーのログ出力
+ */
+Inline void
+svc_perror(const char *file, int_t line, const char *expr, ER ercd)
+{
+	if (ercd < 0) {
+		t_perror(LOG_ERROR, file, line, expr, ercd);
+	}
+}
+
+#define	SVC_PERROR(expr)	svc_perror(__FILE__, __LINE__, #expr, (expr))
+
+/*static*/ uint32_t heap_area[256*1024] __attribute((section(".heap")));
+
+intptr_t heap_param[2] = {
+	(intptr_t)heap_area,
+	sizeof(heap_area)
+};
+
+static char    aTxBuffer[TX_BUF_SIZE];
+static uint8_t aRxBuffer[RX_BUF_SIZE];
+
+int     rx_mode = MODE_DEFAULT;
+queue_t rx_queue;
+
+/*
+ *  デバイスコマンド番号
+ */
+#define BASE_CMD_LEN     4
+
+static int_t mode_func(int argc, char **argv);
+static int_t count_func(int argc, char **argv);
+static int_t at_func(int argc, char **argv);
+
+/*
+ *  デバイスコマンドテーブル
+ */
+static const COMMAND_INFO at_command_info[] = {
+	{"MODE",	mode_func},
+	{"TCNT",	count_func},
+	{"",		at_func}
+};
+
+#define NUM_DEVICE_CMD   (sizeof(at_command_info)/sizeof(COMMAND_INFO))
+
+static const char at_name[] = "AT";
+static const char at_help[] =
+"  AT      MODE (no) echo mode\n"
+"          TCNT      recived count\n"
+"          any command\n";
+
+static COMMAND_LINK at_command_link = {
+	NULL,
+	NUM_DEVICE_CMD,
+	at_name,
+	NULL,
+	at_help,
+	&at_command_info[0]
+};
+
+static int a2i(char *str)
+{
+	int num = 0;
+
+	while(*str >= '0' && *str <= '9'){
+		num = num * 10 + *str++ - '0';
+	}
+	return num;
+}
+
+/*
+ *  ATコマンド設定関数
+ */
+void at_info_init(intptr_t exinf)
+{
+	setup_command(&at_command_link);
+}
+
+/*
+ *  ECHOモード設定関数
+ */
+static int_t mode_func(int argc, char **argv)
+{
+	int mode = rx_mode;
+
+	if(argc >= 2){
+		mode = a2i(argv[1]);
+		if(mode < 0 || mode > MODE_ECHO_HEX)
+			mode = MODE_DEFAULT;
+		rx_mode = mode;
+	}
+	printf("AT ECHO MODE(%d)\n", mode);
+	return mode;
+}
+
+/*
+ *  受信カウントコマンド取得関数
+ */
+static int_t count_func(int argc, char **argv)
+{
+	printf("AT RECIVED COUNT(%d)(%d)\n", rx_queue.size, rx_queue.clen);
+	return rx_queue.clen;
+}
+
+
+/*
+ *  AT設定コマンド関数
+ */
+static int_t at_func(int argc, char **argv)
+{
+	int  i, arg_count = BASE_CMD_LEN;
+	char *p = aTxBuffer;
+	char *s, c;
+	ER_UINT result;
+	int  caps = 1;
+
+	for(i = 0 ; i < argc ; i++){
+		arg_count++;
+		arg_count += strlen(argv[i]);
+	}
+	*p++ = 'A';
+	*p++ = 'T';
+	if(arg_count > BASE_CMD_LEN){
+		for(i = 0 ; i < argc ; i++){
+			s = argv[i];
+			*p++ = '+';
+			while(*s != 0){
+				c = *s++;
+				if(c == '"')
+					caps ^= 1;
+				if(caps && c >= 'a' && c <= 'z')
+					c -= 0x20;
+				*p++ = c;
+			}
+		}
+	}
+	*p++ = '\r';
+	*p++ = '\n';
+	*p++ = 0;
+	result = serial_wri_dat(AT_PORTID, (const char *)aTxBuffer, arg_count);
+	if(result < 0){
+		syslog_1(LOG_ERROR, "AT command send error(%d) !", result);
+	}
+	printf("%d:%s", arg_count, aTxBuffer);
+	return arg_count;
+}
+
+int wolfSSL_Debugging_ON(void);
+int esp_at_rx_handler(void *data, int len);
+
+/*
+ *  メインタスク
+ */
+void main_task(intptr_t exinf)
+{
+	T_SERIAL_RPOR k_rpor;
+	queue_t *rxque;
+	ER_UINT	ercd;
+	int i, j, len;
+	int dlen = 0;
+	uint8_t ch;
+
+	//wolfSSL_Debugging_ON();
+	init_esp_at();
+
+	SVC_PERROR(syslog_msk_log(LOG_UPTO(LOG_INFO), LOG_UPTO(LOG_EMERG)));
+	syslog(LOG_NOTICE, "Sample program starts (exinf = %d).", (int_t) exinf);
+
+	/*
+	 *  シリアルポートの初期化
+	 *
+	 *  システムログタスクと同じシリアルポートを使う場合など，シリアル
+	 *  ポートがオープン済みの場合にはここでE_OBJエラーになるが，支障は
+	 *  ない．
+	 */
+	ercd = serial_opn_por(TASK_PORTID);
+	if (ercd < 0 && MERCD(ercd) != E_OBJ) {
+		syslog(LOG_ERROR, "%s (%d) reported by `serial_opn_por'.",
+									itron_strerror(ercd), SERCD(ercd));
+	}
+	SVC_PERROR(serial_ctl_por(TASK_PORTID,
+							(IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV)));
+
+	/*
+	 * キューバッファの初期化
+	 */
+	rxque = &rx_queue;
+	rxque->size = RX_BUF_SIZE;
+	rxque->clen  = 0;
+	rxque->head = 0;
+	rxque->tail = 0;
+	rxque->pbuffer = aRxBuffer;
+
+	/*
+	 *  ESP-WROOM02用シリアルポートの初期化
+	 */
+	ercd = serial_opn_por(AT_PORTID);
+	if (ercd < 0 && MERCD(ercd) != E_OBJ) {
+		syslog(LOG_ERROR, "%s (%d) reported by `serial_opn_por'.(AT)",
+									itron_strerror(ercd), SERCD(ercd));
+		slp_tsk();
+	}
+	SVC_PERROR(serial_ctl_por(AT_PORTID, 0));
+	while(dlen < 500000){
+		serial_ref_por(AT_PORTID, &k_rpor);
+		len = k_rpor.reacnt;
+		if((rxque->size - rxque->clen) < len)
+			len = rxque->size - rxque->clen;
+		if(len > 0){
+			if(rxque->head >= rxque->tail){
+				if((rxque->size - rxque->head) < len)
+					i = rxque->size - rxque->head;
+				else
+					i = len;
+				j = serial_rea_dat(AT_PORTID, (char *)&rxque->pbuffer[rxque->head], i);
+				rxque->head += j;
+				if(rxque->head >= rxque->size)
+					rxque->head -= rxque->size;
+				rxque->clen += j;
+				len -= j;
+			}
+			if(len > 0){
+				j = serial_rea_dat(AT_PORTID, (char *)&rxque->pbuffer[rxque->head], len);
+				rxque->head += j;
+				if(rxque->head >= rxque->size)
+					rxque->head -= rxque->size;
+				rxque->clen += j;
+				len -= j;
+			}
+		}
+		while(rxque->clen > 0 && rx_mode != MODE_NOECHO){
+			if(rx_mode == MODE_ECHO_CHAR){
+				ch = rxque->pbuffer[rxque->tail];
+				if(ch >= 0x7f)
+					ch = '.';
+				else if(ch < 0x20 && ch != '\r' && ch != '\n')
+					ch = '.';
+				putchar(ch);
+			}
+			else
+				printf("%02x ", rxque->pbuffer[rxque->tail]);
+			rxque->clen--;
+			rxque->tail++;
+			if(rxque->tail >= rxque->size)
+				rxque->tail -= rxque->size;
+			dlen++;
+			if((dlen % 32) == 0 && rx_mode == MODE_ECHO_HEX){
+				printf("\n");
+				dly_tsk(50);
+			}
+		}
+		if (rxque->clen > 0) {
+			len = rxque->clen;
+			if (rxque->tail >= rxque->head) {
+				if ((rxque->size - rxque->tail) < len)
+					i = rxque->size - rxque->tail;
+				else
+					i = len;
+				j = esp_at_rx_handler((char *)&rxque->pbuffer[rxque->tail], i);
+				rxque->tail += j;
+				if (rxque->tail >= rxque->size)
+					rxque->tail -= rxque->size;
+				rxque->clen -= j;
+				len -= j;
+			}
+			if (len > 0) {
+				j = esp_at_rx_handler((char *)&rxque->pbuffer[rxque->tail], len);
+				rxque->tail += j;
+				if (rxque->tail >= rxque->size)
+					rxque->tail -= rxque->size;
+				rxque->clen -= j;
+				len -= j;
+			}
+		}
+		else {
+			dly_tsk(20);
+		}
+	}
+	syslog_0(LOG_NOTICE, "## STOP ##");
+	slp_tsk();
+
+	syslog(LOG_NOTICE, "Sample program ends.");
+//	SVC_PERROR(ext_ker());
+}
+
+int EmbedReceive(struct WOLFSSL *ssl, char *buf, int sz, void *_ctx)
+{
+	syslog(LOG_NOTICE, "EmbedReceive");
+	return 0;
+}
+
+int EmbedSend(struct WOLFSSL* ssl, char* buf, int sz, void* _ctx)
+{
+	syslog(LOG_NOTICE, "EmbedSend");
+	return 0;
+}
Index: azure_iot_hub_riscv/trunk/app_iothub_client/src/main.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/app_iothub_client/src/main.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/app_iothub_client/src/main.cfg	(revision 453)
@@ -0,0 +1,56 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *  K210 LEDデモプログラムのシステムコンフィギュレーションファイル
+ */
+INCLUDE("target_timer.cfg");
+INCLUDE("syssvc/syslog.cfg");
+INCLUDE("syssvc/banner.cfg");
+INCLUDE("syssvc/serial.cfg");
+INCLUDE("syssvc/logtask.cfg");
+INCLUDE("pdic/k210/device.cfg");
+INCLUDE("pdic/k210/dvp.cfg");
+INCLUDE("files/storagedevice.cfg");
+INCLUDE("files/ff/fatfs.cfg");
+INCLUDE("monitor/monitor.cfg");
+
+#include "itron.h"
+#include "device.h"
+#include "kpu_main.h"
+#include "main.h"
+
+ATT_INI({ TA_NULL, 0, rtc_init });
+ATT_INI({ TA_NULL, 0, rtc_info_init });
+ATT_INI({ TA_NULL, heap_param, heap_init });
+ATT_INI({ TA_NULL, 0, device_info_init });
+ATT_INI({ TA_NULL, 0, at_info_init });
+
+CRE_DTQ(DTQ_ESP_AT, { TA_NULL, NUM_ESP_AT, NULL });
+
+CRE_SEM(SPI1TRN_SEM,   { TA_TPRI, 0, 1 });
+CRE_SEM(SPI1DMATX_SEM, { TA_TPRI, 0, 1 });
+CRE_SEM(SPI1LOCK_SEM,  { TA_TPRI, 1, 1 });
+
+CRE_SEM(SPI2TRN_SEM,   { TA_TPRI, 0, 1 });
+CRE_SEM(SPI2DMATX_SEM, { TA_TPRI, 0, 1 });
+CRE_SEM(SPI2LOCK_SEM,  { TA_TPRI, 1, 1 });
+
+CRE_TSK(MAIN_TASK, { TA_ACT, 0, main_task, MAIN_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(KPU_TASK, { TA_ACT, 0, kpu_task, KPU_PRIORITY, KPU_STACK_SIZE, NULL });
+
+ATT_ISR({TA_NULL, SPI_PORTID, INTNO_SPI, spi_isr, 1 });
+CFG_INT(INTNO_SPI, { TA_ENAINT | INTATR_SPI, INTPRI_SPI });
+ATT_ISR({TA_NULL, SIPEED_DMA_CH, INTNO_DMATX, channel_dmac_isr, 1 });
+CFG_INT(INTNO_DMATX, { TA_ENAINT | INTATR_DMATX, INTPRI_DMATX });
+
+ATT_ISR({TA_NULL, SPICARD_PORTID, INTNO_SPIC, spi_isr, 1 });
+CFG_INT(INTNO_SPIC, { TA_ENAINT | INTATR_SPIC, INTPRI_SPIC });
+ATT_ISR({TA_NULL, SPI_DMA1_CH, INTNO_DMARX, channel_dmac_isr, 1 });
+CFG_INT(INTNO_DMARX, { TA_ENAINT | INTATR_DMARX, INTPRI_DMARX });
+
+ATT_ISR({TA_NULL, 0, INTNO_AI, ai_done_isr, 1 });
+CFG_INT(INTNO_AI, { TA_ENAINT | INTATR_AI, INTPRI_AI });
+ATT_ISR({TA_NULL, AI_DMA_CH, INTNO_DMAAI, channel_dmac_isr, 1 });
+CFG_INT(INTNO_DMAAI, { TA_ENAINT | INTATR_DMAAI, INTPRI_DMAAI });
Index: azure_iot_hub_riscv/trunk/app_iothub_client/src/main.h
===================================================================
--- azure_iot_hub_riscv/trunk/app_iothub_client/src/main.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/app_iothub_client/src/main.h	(revision 453)
@@ -0,0 +1,110 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ *
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ *
+ *  $Id$
+ */
+
+/*
+ *	ESP-WROOM-02テストのヘッダファイル
+ */
+
+/*
+ *  ターゲット依存の定義
+ */
+#include "target_test.h"
+
+/*
+ *  各タスクの優先度の定義
+ */
+
+#define MAIN_PRIORITY	8		/* メインタスクの優先度 */
+								/* HIGH_PRIORITYより高くすること */
+
+/*
+ *  ターゲットに依存する可能性のある定数の定義
+ */
+
+#ifndef TASK_PORTID
+#define	TASK_PORTID		1			/* 文字入力するシリアルポートID */
+#endif /* TASK_PORTID */
+#define AT_PORTID       2
+
+#ifndef STACK_SIZE
+#define	STACK_SIZE		2048		/* タスクのスタックサイズ */
+#endif /* STACK_SIZE */
+
+/*
+ *  シリアル設定情報
+ */
+#define TX_BUF_SIZE     256
+#define RX_BUF_SIZE     1024
+
+#define MODE_NOECHO     0
+#define MODE_ECHO_CHAR  1
+#define MODE_ECHO_HEX   2
+#define MODE_DEFAULT    MODE_NOECHO
+
+#define NUM_ESP_AT      4
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  ヒープ領域の設定
+ */
+extern intptr_t heap_param[2];
+
+typedef struct queue_s {
+	uint16_t size;
+	int16_t  clen;
+	uint16_t head;
+	uint16_t tail;
+	uint8_t  *pbuffer;
+} queue_t;
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+extern void	main_task(intptr_t exinf);
+
+extern void heap_init(intptr_t exinf);
+extern void device_info_init(intptr_t exinf);
+extern void at_info_init(intptr_t exinf);
+
+
+#endif /* TOPPERS_MACRO_ONLY */
Index: azure_iot_hub_riscv/trunk/app_iothub_client/src/stub.c
===================================================================
--- azure_iot_hub_riscv/trunk/app_iothub_client/src/stub.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/app_iothub_client/src/stub.c	(revision 453)
@@ -0,0 +1,96 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include "main.h"
+#include "kernel_cfg.h"
+#include "esp_at_socket.h"
+
+void __wrap_exit(int status)
+{
+	ext_ker();
+}
+
+int _kill(int pid, int sig)
+{
+	return 0;
+}
+
+int _getpid(int n)
+{
+	return 1;
+}
+
+int custom_rand_generate_seed(uint8_t *output, uint32_t sz)
+{
+	SYSTIM now;
+	int32_t i;
+
+	get_tim(&now);
+	srand(now);
+
+	for (i = 0; i < sz; i++)
+		output[i] = rand();
+
+	return 0;
+}
+
+// musl-libc
+
+int inet_aton(const char *s0, struct in_addr *dest)
+{
+	const char *s = s0;
+	unsigned char *d = (unsigned char *)dest;
+	unsigned long a[4] = { 0 };
+	char *z;
+	int i;
+
+	for (i = 0; i < 4; i++) {
+		a[i] = strtoul(s, &z, 0);
+		if (z == s || (*z && *z != '.') || !isdigit(*s))
+			return 0;
+		if (!*z) break;
+		s = z + 1;
+	}
+	if (i == 4) return 0;
+	switch (i) {
+	case 0:
+		a[1] = a[0] & 0xffffff;
+		a[0] >>= 24;
+	case 1:
+		a[2] = a[1] & 0xffff;
+		a[1] >>= 16;
+	case 2:
+		a[3] = a[2] & 0xff;
+		a[2] >>= 8;
+	}
+	for (i = 0; i < 4; i++) {
+		if (a[i] > 255) return 0;
+		d[i] = a[i];
+	}
+	return 1;
+}
+
+struct ether_addr *ether_aton_r(const char *x, struct ether_addr *p_a)
+{
+	struct ether_addr a;
+	char *y;
+	for (int ii = 0; ii < 6; ii++) {
+		unsigned long int n;
+		if (ii != 0) {
+			if (x[0] != ':') return 0; /* bad format */
+			else x++;
+		}
+		n = strtoul(x, &y, 16);
+		x = y;
+		if (n > 0xFF) return 0; /* bad byte */
+		a.ether_addr_octet[ii] = n;
+	}
+	if (x[0] != 0) return 0; /* bad format */
+	*p_a = a;
+	return p_a;
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/.vscode/c_cpp_properties.json
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/.vscode/c_cpp_properties.json	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/.vscode/c_cpp_properties.json	(revision 453)
@@ -0,0 +1,26 @@
+{
+    "configurations": [
+        {
+            "name": "Sipeed Maix bit",
+            "includePath": [
+                "${workspaceFolder}/../asp_baseplatform",
+                "${workspaceFolder}/../asp_baseplatform/arch/riscv_gcc",
+                "${workspaceFolder}/../asp_baseplatform/arch/gcc",
+                "${workspaceFolder}/../asp_baseplatform/include",
+                "${workspaceFolder}/../asp_baseplatform/target/k210_gcc",
+                "${workspaceFolder}/../asp_baseplatform/sample"
+            ],
+            "defines": [
+                "USE_ARM_FPU",
+                "TOPPERS_EXECUTE_ON_ROM",
+                "TARGET_KERNEL_ASP"
+            ],
+            "windowsSdkVersion": "10.0.17763.0",
+            "compilerPath": "C:\\xpack-riscv-none-embed-gcc-8.3.0-1.2\\bin\\riscv-none-embed-gcc.exe",
+            "cStandard": "c11",
+            "cppStandard": "c++17",
+            "intelliSenseMode": "gcc-x64"
+        }
+    ],
+    "version": 4
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/.vscode/settings.json
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/.vscode/settings.json	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/.vscode/settings.json	(revision 453)
@@ -0,0 +1,17 @@
+// Place your settings in this file to overwrite default and user settings.
+{
+    "terminal.integrated.setLocaleVariables": true,
+    "terminal.integrated.shell.windows": "C:\\msys64\\usr\\bin\\bash.exe",
+    "terminal.integrated.shellArgs.windows": [
+        "--login",
+        "-i"
+    ],
+    "terminal.integrated.env.windows": {
+        "PATH": "C:\\xpack-riscv-none-embed-gcc-8.3.0-1.2\\bin",
+        "CHERE_INVOKING": "1",
+        "MSYS2_PATH_TYPE": "inherit",
+        "MSYSTEM": "MINGW64"
+    },
+    "C_Cpp.intelliSenseEngine": "Tag Parser",
+    "C_Cpp.default.intelliSenseMode": "gcc-x64"
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/.vscode/tasks.json
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/.vscode/tasks.json	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/.vscode/tasks.json	(revision 453)
@@ -0,0 +1,84 @@
+{
+    // See https://go.microsoft.com/fwlink/?LinkId=733558
+    // for the documentation about the tasks.json format
+    "version": "2.0.0",
+    "name": "make",
+    "type": "shell",
+    "problemMatcher": {
+        "owner": "cpp",
+        "fileLocation": [
+            "relative",
+            "${workspaceFolder}/Debug"
+        ],
+        "pattern": {
+            "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error|fatal error):\\s+(.*)$",
+            "file": 1,
+            "line": 2,
+            "column": 3,
+            "severity": 4,
+            "message": 5
+        }
+    },
+    "tasks": [
+        {
+            "label": "build asp_baseplatform",
+            "args": [
+                "all"
+            ],
+            "linux": {
+                "command": "make"
+            },
+            "osx": {
+                "command": "make"
+            },
+            "windows": {
+                "command": "make.exe"
+            },
+            "group": "build"
+        },
+        {
+            "label": "clean asp_baseplatform",
+            "args": [
+                "clean"
+            ],
+            "linux": {
+                "command": "make"
+            },
+            "osx": {
+                "command": "make"
+            },
+            "windows": {
+                "command": "make.exe"
+            },
+            "group": "build"
+        },
+        {
+            "label": "realclean asp_baseplatform",
+            "args": [
+                "realclean"
+            ],
+            "linux": {
+                "command": "make"
+            },
+            "osx": {
+                "command": "make"
+            },
+            "windows": {
+                "command": "make.exe"
+            },
+            "group": "build"
+        },
+        {
+            "label": "write asp_baseplatform",
+            "command": "/C/Python38/python.exe",
+            "args": [
+                "../tools/kflash/kflash.py",
+                "-p",
+                "COM12",
+                "-b",
+                "1500000",
+                "OBJ/K210_GCC/DEMO/asp.bin"
+            ]
+        }
+    ]
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/MANIFEST
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/MANIFEST	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/MANIFEST	(revision 453)
@@ -0,0 +1,112 @@
+PACKAGE asp
+VERSION 1.9.3
+
+configure
+MANIFEST
+README.txt
+
+doc/asp_spec.txt
+doc/configurator.txt
+doc/design.txt
+doc/extension.txt
+doc/porting.txt
+doc/user.txt
+doc/version.txt
+
+include/histogram.h
+include/itron.h
+include/kernel.h
+include/log_output.h
+include/queue.h
+include/sil.h
+include/t_stddef.h
+include/t_stdlib.h
+include/t_syslog.h
+include/test_lib.h
+
+kernel/Makefile.kernel
+kernel/alarm.c
+kernel/alarm.h
+kernel/allfunc.h
+kernel/check.h
+kernel/cyclic.c
+kernel/cyclic.h
+kernel/dataqueue.c
+kernel/dataqueue.h
+kernel/eventflag.c
+kernel/eventflag.h
+kernel/exception.c
+kernel/exception.h
+kernel/genoffset.tf
+kernel/interrupt.c
+kernel/interrupt.h
+kernel/kernel.tf
+kernel/kernel_api.csv
+kernel/kernel_check.tf
+kernel/kernel_def.csv
+kernel/kernel_impl.h
+kernel/kernel_int.h
+kernel/kernel_rename.def
+kernel/kernel_rename.h
+kernel/kernel_unrename.h
+kernel/mailbox.c
+kernel/mailbox.h
+kernel/mempfix.c
+kernel/mempfix.h
+kernel/pridataq.c
+kernel/pridataq.h
+kernel/semaphore.c
+kernel/semaphore.h
+kernel/startup.c
+kernel/sys_manage.c
+kernel/task.c
+kernel/task.h
+kernel/task_except.c
+kernel/task_manage.c
+kernel/task_refer.c
+kernel/task_sync.c
+kernel/time_event.c
+kernel/time_event.h
+kernel/time_manage.c
+kernel/wait.c
+kernel/wait.h
+
+library/histogram.c
+library/log_output.c
+library/strerror.c
+library/t_perror.c
+library/test_lib.c
+library/vasyslog.c
+
+sample/Makefile
+sample/sample1.c
+sample/sample1.cfg
+sample/sample1.h
+
+syssvc/banner.c
+syssvc/banner.cfg
+syssvc/banner.h
+syssvc/logtask.c
+syssvc/logtask.cfg
+syssvc/logtask.h
+syssvc/serial.c
+syssvc/serial.cfg
+syssvc/serial.h
+syssvc/syslog.c
+syssvc/syslog.cfg
+syssvc/syslog.h
+
+utils/applyrename
+utils/genoffset
+utils/genrename
+utils/gentest
+utils/makedep
+utils/makerelease
+
+INCLUDE target/dve68k_gcc/MANIFEST
+INCLUDE arch/m68k_gcc/MANIFEST
+INCLUDE arch/gcc/MANIFEST
+INCLUDE arch/logtrace/MANIFEST
+INCLUDE pdic/upd72001/MANIFEST
+INCLUDE test/MANIFEST
+INCLUDE extension/MANIFEST
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/Makefile
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/Makefile	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/Makefile	(revision 453)
@@ -0,0 +1,14 @@
+
+MAKE = make
+
+.PHONY: all
+all:
+	$(MAKE) -j 1 -C OBJ/K210_GCC/DEMO all
+
+.PHONY: clean
+clean:
+	$(MAKE) -j 1 -C OBJ/K210_GCC/DEMO clean
+
+.PHONY: realclean
+realclean:
+	$(MAKE) -j 1 -C OBJ/K210_GCC/DEMO realclean
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/DEMO/Makefile
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/DEMO/Makefile	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/DEMO/Makefile	(revision 453)
@@ -0,0 +1,612 @@
+#
+#  TOPPERS/ASP Kernel
+#      Toyohashi Open Platform for Embedded Real-Time Systems/
+#      Advanced Standard Profile Kernel
+# 
+#  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                              Toyohashi Univ. of Technology, JAPAN
+#  Copyright (C) 2006-2014 by Embedded and Real-Time Systems Laboratory
+#              Graduate School of Information Science, Nagoya Univ., JAPAN
+# 
+#  ä¸è¨èä½æ¨©è
+ã¯ï¼ä»¥ä¸ã®(1)ï½(4)ã®æ¡ä»¶ãæºããå ´åã«éãï¼æ¬ã½ããã¦ã§
+#  ã¢ï¼æ¬ã½ããã¦ã§ã¢ãæ¹å¤ãããã®ãå«ãï¼ä»¥ä¸åãï¼ãä½¿ç¨ã»è¤è£½ã»æ¹
+#  å¤ã»åé
+å¸ï¼ä»¥ä¸ï¼å©ç¨ã¨å¼ã¶ï¼ãããã¨ãç¡åã§è¨±è«¾ããï¼
+#  (1) æ¬ã½ããã¦ã§ã¢ãã½ã¼ã¹ã³ã¼ãã®å½¢ã§å©ç¨ããå ´åã«ã¯ï¼ä¸è¨ã®èä½
+#      æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãï¼ãã®ã¾ã¾ã®å½¢ã§ã½ã¼
+#      ã¹ã³ã¼ãä¸­ã«å«ã¾ãã¦ãããã¨ï¼
+#  (2) æ¬ã½ããã¦ã§ã¢ãï¼ã©ã¤ãã©ãªå½¢å¼ãªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨
+#      è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®èä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨
+#      ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#  (3) æ¬ã½ããã¦ã§ã¢ãï¼æ©å¨ã«çµã¿è¾¼ããªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããªãå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼æ¬¡ã®ããããã®æ¡ä»¶ãæºããã
+#      ã¨ï¼
+#    (a) åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®è
+#        ä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#    (b) åé
+å¸ã®å½¢æ
+ãï¼å¥ã«å®ããæ¹æ³ã«ãã£ã¦ï¼TOPPERSãã­ã¸ã§ã¯ãã«
+#        å ±åãããã¨ï¼
+#  (4) æ¬ã½ããã¦ã§ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæ
+#      å®³ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ããå
+è²¬ãããã¨ï¼
+#      ã¾ãï¼æ¬ã½ããã¦ã§ã¢ã®ã¦ã¼ã¶ã¾ãã¯ã¨ã³ãã¦ã¼ã¶ããã®ãããªãç
+#      ç±ã«åºã¥ãè«æ±ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ãã
+#      å
+è²¬ãããã¨ï¼
+# 
+#  æ¬ã½ããã¦ã§ã¢ã¯ï¼ç¡ä¿è¨¼ã§æä¾ããã¦ãããã®ã§ããï¼ä¸è¨èä½æ¨©è
+ã
+#  ãã³TOPPERSãã­ã¸ã§ã¯ãã¯ï¼æ¬ã½ããã¦ã§ã¢ã«é¢ãã¦ï¼ç¹å®ã®ä½¿ç¨ç®ç
+#  ã«å¯¾ããé©åæ§ãå«ãã¦ï¼ãããªãä¿è¨¼ãè¡ããªãï¼ã¾ãï¼æ¬ã½ããã¦ã§
+#  ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæå®³ã«é¢ãã¦ãï¼ã
+#  ã®è²¬ä»»ãè² ããªãï¼
+# 
+#  $Id$
+# 
+
+#
+#  ã¿ã¼ã²ããã®æå®ï¼Makefile.targetã§ä¸æ¸ããããã®ãé²ãããï¼
+#
+all:
+
+#
+#  ã¿ã¼ã²ããç¥ç§°ã®å®ç¾©
+#
+TARGET = k210_gcc
+
+#
+#  ãã­ã°ã©ãã³ã°è¨èªã®å®ç¾©
+#
+SRCLANG = c
+ifeq ($(SRCLANG),c)
+  LIBS = -lc 
+endif
+ifeq ($(SRCLANG),c++)
+  USE_CXX = true
+  CXXLIBS = -lstdc++ -lm -lc
+  CXXRTS = cxxrt.o newlibrt.o
+endif
+
+#
+#  ã½ã¼ã¹ãã¡ã¤ã«ã®ãã£ã¬ã¯ããªã®å®ç¾©
+#
+SRCDIR = ../../..
+
+#
+#  ãªãã¸ã§ã¯ããã¡ã¤ã«åã®æ¡å¼µå­ã®è¨­å®
+#
+OBJEXT = exe
+
+#
+#  å®è¡ç°å¢ã®å®ç¾©ï¼ã¿ã¼ã²ããä¾å­ã«ä¸æ¸ããããå ´åãããï¼
+#
+DBGENV := ROM
+
+#
+#  ã«ã¼ãã«ã©ã¤ãã©ãªï¼libkernel.aï¼ã®ãã£ã¬ã¯ããªå
+#  ï¼ã«ã¼ãã«ã©ã¤ãã©ãªãmakeå¯¾è±¡ã«ããæã¯ï¼ç©ºã«å®ç¾©ããï¼
+#
+KERNEL_LIB = ../libkernel
+
+#
+#  ã«ã¼ãã«ãé¢æ°åä½ã§ã³ã³ãã¤ã«ãããã©ããã®å®ç¾©
+#
+KERNEL_FUNCOBJS = 
+
+#
+#  ãã¬ã¼ã¹ã­ã°ãåå¾ãããã©ããã®å®ç¾©
+#
+ENABLE_TRACE = 
+
+#
+#  ã¦ã¼ãã£ãªãã£ãã­ã°ã©ã ã®åç§°
+#
+PERL = /usr/bin/perl
+CFG = $(SRCDIR)/cfg/cfg/cfg
+
+#
+#  ãªãã¸ã§ã¯ããã¡ã¤ã«åã®å®ç¾©
+#
+OBJNAME = asp
+ifdef OBJEXT
+  OBJFILE = $(OBJNAME).$(OBJEXT)
+  CFG1_OUT = cfg1_out.$(OBJEXT)
+else
+  OBJFILE = $(OBJNAME)
+  CFG1_OUT = cfg1_out
+endif
+
+#
+#  ã¿ã¼ã²ããä¾å­é¨ã®ãã£ã¬ã¯ããªã®å®ç¾©
+#
+TARGETDIR = $(SRCDIR)/target/$(TARGET)
+
+#
+#  ã¿ã¼ã²ããä¾å­ã®å®ç¾©ã®ã¤ã³ã¯ã«ã¼ã
+#
+include $(TARGETDIR)/Makefile.target
+
+#
+#  ã³ã³ãã£ã®ã¥ã¬ã¼ã¿é¢ä¿ã®å¤æ°ã®å®ç¾©
+#
+CFG_TABS := --api-table $(SRCDIR)/kernel/kernel_api.csv \
+			--cfg1-def-table $(SRCDIR)/kernel/kernel_def.csv $(CFG_TABS)
+
+CFG_ASMOBJS := $(CFG_ASMOBJS)
+CFG_COBJS := kernel_cfg.o $(CFG_COBJS)
+CFG_OBJS := $(CFG_ASMOBJS) $(CFG_COBJS)
+CFG2_OUT_SRCS := kernel_cfg.h kernel_cfg.c $(CFG2_OUT_SRCS)
+
+#
+#  å
+±éã³ã³ãã¤ã«ãªãã·ã§ã³ã®å®ç¾©
+#
+COPTS := $(COPTS) -g -ffunction-sections -fdata-sections
+ifndef OMIT_WARNING_ALL
+  COPTS := $(COPTS) -Wall
+endif
+ifndef OMIT_OPTIMIZATION
+  COPTS := $(COPTS) -O2
+endif
+CDEFS := $(CDEFS) -DSPI_WAIT_TIME=100 -DSDEV_SENSE_ONETIME -DMAX_FONT_IMAGE=24
+INCLUDES := -I. -I$(SRCDIR)/include -I$(SRCDIR)/arch -I$(SRCDIR) $(INCLUDES)
+LDFLAGS := $(LDFLAGS) 
+CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) 
+LIBS := $(LIBS) $(CXXLIBS)
+CFLAGS = $(COPTS) $(CDEFS) $(INCLUDES)
+
+#
+#  ã¢ããªã±ã¼ã·ã§ã³ãã­ã°ã©ã ã«é¢ããå®ç¾©
+#
+APPLNAME = demo
+APPLDIR = 
+APPL_CFG = $(APPLNAME).cfg
+
+APPL_DIR = $(APPLDIR) $(SRCDIR)/library
+APPL_ASMOBJS =
+ifdef USE_CXX
+  APPL_CXXOBJS = $(APPLNAME).o 
+  APPL_COBJS =
+else
+  APPL_COBJS = $(APPLNAME).o 
+endif
+APPL_COBJS := $(APPL_COBJS) log_output.o vasyslog.o t_perror.o strerror.o
+APPL_CFLAGS =
+APPL_LIBS =
+ifdef APPLDIR
+  INCLUDES := $(INCLUDES) $(foreach dir,$(APPLDIR),-I$(dir))
+endif
+
+#
+#  ããã«ã¦ã§ã¢ã® Makefile ã®ã¤ã³ã¯ã«ã¼ã
+#
+include $(SRCDIR)/monitor/Makefile.config
+include $(SRCDIR)/files/ff/Makefile.config
+include $(SRCDIR)/files/Makefile.config
+include $(SRCDIR)/ui/snfont_disp/Makefile.config
+
+#
+#  GDIC Makefile ã®ã¤ã³ã¯ã«ã¼ã
+#
+include $(SRCDIR)/gdic/sipeed_st7789/Makefile.config
+include $(SRCDIR)/gdic/sipeed_ov2640/Makefile.config
+include $(SRCDIR)/gdic/spi_driver/Makefile.config
+
+#
+#  ã·ã¹ãã ãµã¼ãã¹ã«é¢ããå®ç¾©
+#
+SYSSVC_DIR := $(SYSSVC_DIR) $(SRCDIR)/syssvc $(SRCDIR)/library $(SRCDIR)/pdic/k210
+SYSSVC_ASMOBJS := $(SYSSVC_ASMOBJS)
+SYSSVC_COBJS := $(SYSSVC_COBJS) banner.o syslog.o serial.o logtask.o \
+			device.o spi.o spi_reg.o dvp.o clock.o malloc.o tlsf.o riscv64.o \
+				 $(CXXRTS)
+SYSSVC_CFLAGS := $(SYSSVC_CFLAGS)
+SYSSVC_LIBS := $(SYSSVC_LIBS)
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/pdic/k210
+#LDFLAGS := $(LDFLAGS) \
+#	-Wl,--wrap=_malloc_r \
+#	-Wl,--wrap=_calloc_r \
+#	-Wl,--wrap=_free_r \
+#	-Wl,--wrap=_realloc_r
+
+#
+#  ã«ã¼ãã«ã«é¢ããå®ç¾©
+#
+#  KERNEL_ASMOBJS: ã«ã¼ãã«ã©ã¤ãã©ãªã«å«ããï¼ã½ã¼ã¹ãã¢ã»ã³ããªè¨èªã®
+#				   ãªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#  KERNEL_COBJS: ã«ã¼ãã«ã®ã©ã¤ãã©ãªã«å«ããï¼ã½ã¼ã¹ãCè¨èªã§ï¼ã½ã¼ã¹
+#				 ãã¡ã¤ã«ã¨1å¯¾1ã«å¯¾å¿ãããªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#  KERNEL_LCSRCS: ã«ã¼ãã«ã®ã©ã¤ãã©ãªã«å«ããCè¨èªã®ã½ã¼ã¹ãã¡ã¤ã«ã§ï¼
+#				  1ã¤ã®ã½ã¼ã¹ãã¡ã¤ã«ããè¤æ°ã®ãªãã¸ã§ã¯ããã¡ã¤ã«ãç
+#				  æãããã®ï¼
+#  KERNEL_LCOBJS: ä¸ã®ã½ã¼ã¹ãã¡ã¤ã«ããçæããããªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#  KERNEL_AUX_COBJS: ã­ã¼ãã¢ã¸ã¥ã¼ã«ã«å«ããªããï¼ã«ã¼ãã«ã®ã½ã¼ã¹ãã¡
+#					 ã¤ã«ã¨åããªãã·ã§ã³ãé©ç¨ãã¦ã³ã³ãã¤ã«ãã¹ãï¼ã½ã¼
+#					 ã¹ãCè¨èªã®ãªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#
+KERNEL_DIR := $(KERNEL_DIR) $(SRCDIR)/kernel
+KERNEL_ASMOBJS := $(KERNEL_ASMOBJS)
+KERNEL_COBJS := $(KERNEL_COBJS)
+KERNEL_CFLAGS := $(KERNEL_CFLAGS) -I$(SRCDIR)/kernel
+ifdef OMIT_MAKEOFFSET
+  OFFSET_H =
+else
+  OFFSET_H = offset.h
+ifndef OFFSET_TF
+  KERNEL_AUX_COBJS := $(KERNEL_AUX_COBJS) makeoffset.o
+endif
+endif
+
+#
+#  ã¿ã¼ã²ãããã¡ã¤ã«ï¼è¤æ°ãåæã«é¸æãã¦ã¯ãªããªãï¼
+#
+#all: $(OBJFILE)
+all: $(OBJNAME).bin
+#all: $(OBJNAME).srec
+
+##### ä»¥ä¸ã¯ç·¨éããªããã¨ #####
+
+#
+#  ç°å¢ã«ä¾å­ããã³ã³ãã¤ã«ãªãã·ã§ã³ã®å®ç¾©
+#
+ifdef DBGENV
+  CDEFS := $(CDEFS) -D$(DBGENV)
+endif
+
+#
+#  ã«ã¼ãã«ã®ãã¡ã¤ã«æ§æã®å®ç¾©
+#
+include $(SRCDIR)/kernel/Makefile.kernel
+ifdef KERNEL_FUNCOBJS
+  KERNEL_LCSRCS := $(KERNEL_FCSRCS)
+  KERNEL_LCOBJS := $(foreach file,$(KERNEL_FCSRCS),$($(file:.c=)))
+else
+  KERNEL_CFLAGS := -DALLFUNC $(KERNEL_CFLAGS)
+  KERNEL_COBJS := $(KERNEL_COBJS) \
+					$(foreach file,$(KERNEL_FCSRCS),$(file:.c=.o))
+endif
+
+#
+#  ã½ã¼ã¹ãã¡ã¤ã«ã®ãããã£ã¬ã¯ããªã«é¢ããå®ç¾©
+#
+vpath %.c $(KERNEL_DIR) $(SYSSVC_DIR) $(APPL_DIR)
+vpath %.S $(KERNEL_DIR) $(SYSSVC_DIR) $(APPL_DIR)
+vpath %.cfg $(APPL_DIR)
+
+#
+#  ã³ã³ãã¤ã«ã®ããã®å¤æ°ã®å®ç¾©
+#
+KERNEL_LIB_OBJS = $(KERNEL_ASMOBJS) $(KERNEL_COBJS) $(KERNEL_LCOBJS)
+SYSSVC_OBJS = $(SYSSVC_ASMOBJS) $(SYSSVC_COBJS)
+APPL_OBJS = $(APPL_ASMOBJS) $(APPL_COBJS) $(APPL_CXXOBJS)
+ALL_OBJS = $(START_OBJS) $(APPL_OBJS) $(SYSSVC_OBJS) $(CFG_OBJS) \
+											$(END_OBJS) $(HIDDEN_OBJS)
+ifdef KERNEL_LIB
+  ALL_LIBS = $(APPL_LIBS) $(SYSSVC_LIBS) -lkernel $(LIBS)
+  LIBS_DEP = $(filter %.a,$(ALL_LIBS)) $(KERNEL_LIB)/libkernel.a
+  LDFLAGS := $(LDFLAGS) -L$(KERNEL_LIB)
+  REALCLEAN_FILES := libkernel.a $(REALCLEAN_FILES)
+else
+  ALL_LIBS = $(APPL_LIBS) $(SYSSVC_LIBS) libkernel.a $(LIBS)
+  LIBS_DEP = $(filter %.a,$(ALL_LIBS))
+endif
+
+ifdef TEXT_START_ADDRESS
+  LDFLAGS := $(LDFLAGS) -Wl,-Ttext,$(TEXT_START_ADDRESS)
+  CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) -Wl,-Ttext,$(TEXT_START_ADDRESS)
+endif
+ifdef DATA_START_ADDRESS
+  LDFLAGS := $(LDFLAGS) -Wl,-Tdata,$(DATA_START_ADDRESS)
+  CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) -Wl,-Tdata,$(DATA_START_ADDRESS)
+endif
+ifdef LDSCRIPT
+  LDFLAGS := $(LDFLAGS) -T $(LDSCRIPT)
+  CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) -T $(LDSCRIPT)
+endif
+
+#
+#  ãªãã»ãããã¡ã¤ã«ï¼offset.hï¼ã®çæè¦å
+#
+ifdef OFFSET_TF
+offset.h: $(APPL_CFG) kernel_cfg.timestamp
+	$(CFG) --pass 3 --kernel asp $(INCLUDES) \
+				--rom-image cfg1_out.srec --symbol-table cfg1_out.syms \
+				-T $(OFFSET_TF) $(CFG_TABS) $<
+else
+offset.h: makeoffset.s $(SRCDIR)/utils/genoffset
+	$(PERL) $(SRCDIR)/utils/genoffset makeoffset.s > offset.h
+endif
+
+#
+#  ã«ã¼ãã«ã®ã³ã³ãã£ã®ã¥ã¬ã¼ã·ã§ã³ãã¡ã¤ã«ã®çæ
+#
+cfg1_out.c: $(APPL_CFG)
+	$(CFG) --pass 1 --kernel asp $(INCLUDES) $(CFG_TABS) $<
+
+$(CFG2_OUT_SRCS): kernel_cfg.timestamp
+kernel_cfg.timestamp: $(APPL_CFG) \
+						$(START_OBJS) cfg1_out.o $(END_OBJS) $(HIDDEN_OBJS)
+	$(LINK) $(CFLAGS) $(CFG1_OUT_LDFLAGS) -o $(CFG1_OUT) \
+						$(START_OBJS) cfg1_out.o $(END_OBJS)
+	$(NM) -n $(CFG1_OUT) > cfg1_out.syms
+	$(OBJCOPY) -O srec -S $(CFG1_OUT) cfg1_out.srec
+	$(CFG) --pass 2 --kernel asp $(INCLUDES) \
+				-T $(TARGETDIR)/target.tf $(CFG_TABS) $<
+	touch -r kernel_cfg.c kernel_cfg.timestamp
+
+#
+#  ã«ã¼ãã«ã©ã¤ãã©ãªãã¡ã¤ã«ã®çæ
+#
+$(KERNEL_LIB)/libkernel.a: $(OFFSET_H) $(KERNEL_LIB_OBJS)
+	rm -f libkernel.a
+	$(AR) -rcs $(KERNEL_LIB)/libkernel.a $(KERNEL_LIB_OBJS)
+	$(RANLIB) $(KERNEL_LIB)/libkernel.a
+
+#
+#  ç¹å¥ãªä¾å­é¢ä¿ã®å®ç¾©
+#
+banner.o: kernel_cfg.timestamp $(filter-out banner.o,$(ALL_OBJS)) $(LIBS_DEP)
+
+#
+#  å
+¨ä½ã®ãªã³ã¯
+#
+$(OBJFILE): $(APPL_CFG) kernel_cfg.timestamp $(ALL_OBJS) $(LIBS_DEP)
+	$(LINK) $(CFLAGS) $(LDFLAGS) -o $(OBJFILE) $(START_OBJS) \
+			-Wl,-Map=$(OBJNAME).map,--cref -Wl,--gc-sections -Wl,-estart,--gc-keep-exported=_kernel_istk \
+			$(APPL_OBJS) $(SYSSVC_OBJS) $(CFG_OBJS) \
+			-Wl,--start-group $(ALL_LIBS) -Wl,--end-group $(END_OBJS)
+	$(NM) -n $(OBJFILE) > $(OBJNAME).syms
+	$(OBJCOPY) -O srec -S $(OBJFILE) $(OBJNAME).srec
+	$(CFG) --pass 3 --kernel asp $(INCLUDES) \
+				--rom-image $(OBJNAME).srec --symbol-table $(OBJNAME).syms \
+				-T $(TARGETDIR)/target_check.tf $(CFG_TABS) $<
+
+#
+#  ãã¤ããªãã¡ã¤ã«ã®çæ
+#
+$(OBJNAME).bin: $(OBJFILE)
+	$(OBJCOPY) -O binary -S $(OBJFILE) $(OBJNAME).bin
+
+#
+#  Sã¬ã³ã¼ããã¡ã¤ã«ã®çæ
+#
+$(OBJNAME).srec: $(OBJFILE)
+	$(OBJCOPY) -O srec -S $(OBJFILE) $(OBJNAME).srec
+
+#
+#  ã³ã³ãã¤ã«çµæã®æ¶å»
+#
+.PHONY: clean
+clean:
+	rm -f \#* *~ *.o $(CLEAN_FILES)
+	rm -f $(OBJFILE) $(OBJNAME).syms $(OBJNAME).srec $(OBJNAME).bin
+	rm -f kernel_cfg.timestamp $(CFG2_OUT_SRCS)
+	rm -f cfg1_out.c $(CFG1_OUT) cfg1_out.syms cfg1_out.srec
+ifndef KERNEL_LIB
+	rm -f libkernel.a
+endif
+	rm -f makeoffset.s offset.h
+
+.PHONY: cleankernel
+cleankernel:
+	rm -rf $(KERNEL_LIB_OBJS)
+	rm -f makeoffset.s offset.h
+
+.PHONY: cleandep
+cleandep:
+	if ! [ -f Makefile.depend ]; then \
+		rm -f kernel_cfg.timestamp $(CFG2_OUT_SRCS); \
+		rm -f cfg1_out.c cfg1_out.o $(CFG1_OUT) cfg1_out.syms cfg1_out.srec; \
+		rm -f makeoffset.s offset.h; \
+	fi
+	rm -f Makefile.depend
+
+.PHONY: realclean
+realclean: cleandep clean
+	rm -f $(REALCLEAN_FILES)
+
+#
+#  ã³ã³ãã£ã®ã¥ã¬ã¼ã¿ãçæãããã¡ã¤ã«ã®ã³ã³ãã¤ã«ã«ã¼ã«ã¨ä¾å­é¢ä¿ä½æ
+#  ã«ã¼ã«ã®å®ç¾©
+#
+#  ã³ã³ãã£ã®ã¥ã¬ã¼ã¿ãçæãããã¡ã¤ã«ã¯ï¼ã¢ããªã±ã¼ã·ã§ã³ãã­ã°ã©ã ç¨ï¼
+#  ã·ã¹ãã ãµã¼ãã¹ç¨ï¼ã«ã¼ãã«ç¨ã®ãã¹ã¦ã®ãªãã·ã§ã³ãä»ãã¦ã³ã³ãã¤ã«
+#  ããï¼
+#
+ALL_CFG_COBJS = $(CFG_COBJS) cfg1_out.o
+ALL_CFG_ASMOBJS = $(CFG_ASMOBJS)
+CFG_CFLAGS = $(APPL_CFLAGS) $(SYSSVC_CFLAGS) $(KERNEL_CFLAGS)
+
+$(ALL_CFG_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(CFG_CFLAGS) $<
+
+$(ALL_CFG_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(CFG_CFLAGS) $<
+
+$(ALL_CFG_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(CFG_CFLAGS)" $< >> Makefile.depend
+
+$(ALL_CFG_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(CFG_CFLAGS) $<
+
+$(ALL_CFG_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(CFG_CFLAGS)" $< >> Makefile.depend
+
+#
+#  ç¹æ®ãªä¾å­é¢ä¿ä½æã«ã¼ã«ã®å®ç¾©
+#
+cfg1_out.depend: $(APPL_CFG)
+	@$(CFG) -M cfg1_out.c $(INCLUDES) $< >> Makefile.depend
+
+makeoffset.d: makeoffset.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-T "makeoffset.s" -O "$(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+#
+#  ä¾å­é¢ä¿ãã¡ã¤ã«ã®çæ
+#
+.PHONY: gendepend
+gendepend:
+	@echo "Generating Makefile.depend."
+
+.PHONY: depend
+ifdef KERNEL_LIB
+depend: cleandep kernel_cfg.timestamp gendepend \
+		cfg1_out.depend cfg1_out.d \
+		$(ALL_OBJS:.o=.d)
+else
+depend: cleandep $(OFFSET_H) kernel_cfg.timestamp gendepend \
+		cfg1_out.depend cfg1_out.d \
+		$(KERNEL_AUX_COBJS:.o=.d) $(KERNEL_ASMOBJS:.o=.d) \
+		$(KERNEL_COBJS:.o=.d) $(KERNEL_LCSRCS:.c=.d) $(ALL_OBJS:.o=.d)
+endif
+
+#
+#  ä¾å­é¢ä¿ãã¡ã¤ã«ãã¤ã³ã¯ã«ã¼ã
+#
+-include Makefile.depend
+
+#
+#  éçºãã¼ã«ã®ã³ãã³ãåã®å®ç¾©
+#
+ifeq ($(TOOL),gcc)
+  #
+  #  GNUéçºç°å¢ç¨
+  #
+  ifdef GCC_TARGET
+    GCC_TARGET_PREFIX = $(GCC_TARGET)-
+  else
+    GCC_TARGET_PREFIX =
+  endif
+  CC = $(GCC_TARGET_PREFIX)gcc
+  CXX = $(GCC_TARGET_PREFIX)g++
+  AS = $(GCC_TARGET_PREFIX)as
+  LD = $(GCC_TARGET_PREFIX)ld
+  AR = $(GCC_TARGET_PREFIX)ar
+  NM = $(GCC_TARGET_PREFIX)nm
+  RANLIB = $(GCC_TARGET_PREFIX)ranlib
+  OBJCOPY = $(GCC_TARGET_PREFIX)objcopy
+  OBJDUMP = $(GCC_TARGET_PREFIX)objdump
+endif
+
+ifdef USE_CXX
+  LINK = $(CXX)
+else
+  LINK = $(CC)
+endif
+
+#
+#  ã³ã³ãã¤ã«ã«ã¼ã«ã®å®ç¾©
+#
+KERNEL_ALL_COBJS = $(KERNEL_COBJS) $(KERNEL_AUX_COBJS)
+
+$(KERNEL_ALL_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_ALL_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_LCOBJS): %.o:
+	$(CC) -DTOPPERS_$(*F) -o $@ -c $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_LCOBJS:.o=.s): %.s:
+	$(CC) -DTOPPERS_$(*F) -o $@ -S $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(SYSSVC_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(SYSSVC_CFLAGS) $<
+
+$(SYSSVC_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(SYSSVC_CFLAGS) $<
+
+$(SYSSVC_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(SYSSVC_CFLAGS) $<
+
+$(APPL_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_CXXOBJS): %.o: %.cpp
+	$(CXX) -c $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_CXXOBJS:.o=.s): %.s: %.cpp
+	$(CXX) -S $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(APPL_CFLAGS) $<
+
+#
+#  ä¾å­é¢ä¿ä½æã«ã¼ã«ã®å®ç¾©
+#
+$(KERNEL_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+$(KERNEL_LCSRCS:.c=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) -T "$($*)" \
+		-O "-DALLFUNC $(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+$(KERNEL_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+$(SYSSVC_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(SYSSVC_CFLAGS)" $< >> Makefile.depend
+
+$(SYSSVC_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(SYSSVC_CFLAGS)" $< >> Makefile.depend
+
+$(APPL_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(APPL_CFLAGS)" $< >> Makefile.depend
+
+$(APPL_CXXOBJS:.o=.d): %.d: %.cpp
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CXX) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(APPL_CFLAGS)" $< >> Makefile.depend
+
+$(APPL_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(APPL_CFLAGS)" $< >> Makefile.depend
+
+#
+#  ããã©ã«ãã³ã³ãã¤ã«ã«ã¼ã«ãä¸æ¸ã
+#
+%.o: %.c
+	@echo "*** Default compile rules should not be used."
+	$(CC) -c $(CFLAGS) $<
+
+%.s: %.c
+	@echo "*** Default compile rules should not be used."
+	$(CC) -S $(CFLAGS) $<
+
+%.o: %.cpp
+	@echo "*** Default compile rules should not be used."
+	$(CXX) -c $(CFLAGS) $<
+
+%.s: %.cpp
+	@echo "*** Default compile rules should not be used."
+	$(CXX) -S $(CFLAGS) $<
+
+%.o: %.S
+	@echo "*** Default compile rules should not be used."
+	$(CC) -c $(CFLAGS) $<
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/DEMO/demo.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/DEMO/demo.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/DEMO/demo.c	(revision 453)
@@ -0,0 +1,606 @@
+/*
+*  TOPPERS/ASP Kernel
+*      Toyohashi Open Platform for Embedded Real-Time Systems/
+*      Advanced Standard Profile Kernel
+* 
+*  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+*                              Toyohashi Univ. of Technology, JAPAN
+*  Copyright (C) 2004-2012 by Embedded and Real-Time Systems Laboratory
+*              Graduate School of Information Science, Nagoya Univ., JAPAN
+* 
+*  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+*  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+*  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+*  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+*      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+*      スコード中に含まれていること．
+*  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+*      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+*      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+*      の無保証規定を掲載すること．
+*  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+*      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+*      と．
+*    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+*        作権表示，この利用条件および下記の無保証規定を掲載すること．
+*    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+*        報告すること．
+*  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+*      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+*      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+*      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+*      免責すること．
+* 
+*  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+*  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+*  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+*  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+*  の責任を負わない．
+* 
+*  $Id$
+*/
+
+/* 
+*  K210 LEDデモプログラム
+*  このデモプログラムは、デフォルトでSDEV_SENSE_ONETIMEコンパイルが
+*  有効となっておりSDカード中に東雲漢字フォントが書き込まれて
+*  いることを前提としています。
+*  TOPPERS BASE PLATFORM(CV)中のui/snfont_dispディレクトリ中の
+*  以下のフォントをSDカードに書き込んで起動してください。
+*    shinonome_font12.fnt
+*    shinonome_font16.fnt
+*  プログラム中に漢字フォントをROMファイルして取り込んで漢字の表示も
+*  可能です。この場合、SDEV_SENSE_ONETIMEコンパイルスイッチを無効にし
+*  USE_ROMFONTコンパイルスイッチを有効にして、Makefile中に
+*  gdic/rom_file/Makefile.configを取り込んでビルドしてください。
+*/
+
+#include <kernel.h>
+#include <stdlib.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <target_syssvc.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#include "device.h"
+#include "pinmode.h"
+#include "sipeed_st7789.h"
+#include "sipeed_ov2640.h"
+#include "storagedevice.h"
+#ifdef SDEV_SENSE_ONETIME
+#include "spi_driver.h"
+#include "sddiskio.h"
+#else
+#include "rom_file.h"
+#endif
+#include "kernel_cfg.h"
+#include "demo.h"
+#include "topamelogo.h"
+
+#define IOMEM 0x40000000
+
+/*
+*  サービスコールのエラーのログ出力
+*/
+Inline void
+svc_perror(const char *file, int_t line, const char *expr, ER ercd)
+{
+	if (ercd < 0) {
+		t_perror(LOG_ERROR, file, line, expr, ercd);
+	}
+}
+
+#define	SVC_PERROR(expr)	svc_perror(__FILE__, __LINE__, #expr, (expr))
+
+#define SWAP_32(x) ((x >> 24) | (x >> 8 & 0xff00) | (x << 8 & 0xff0000) | (x << 24))
+
+#ifndef SPI1DMATX_SEM
+#define SPI1DMATX_SEM   0
+#endif
+
+#if !defined(NOT_USEFILFONT)
+static const char string1[] = {
+	'T', 'O', 'P', 'P', 'E', 'R', 'S',0xE3,0x83,0x97,0xE3,0x83,0xAD,0xE3,0x82,0xB8,
+	0xE3,0x82,0xA7,0xE3,0x82,0xAF,0xE3,0x83,0x88,0
+};
+static const char string2[] = {
+	0xE6,0x95,0x99,0xE8,0x82,0xB2,0xE3,0x83,0xAF,0xE3,0x83,0xBC,0xE3,0x82,0xAD,
+	0xE3,0x83,0xB3,0xE3,0x82,0xB0,0xE3,0x83,0xAB,0xE3,0x83,0xBC,0xE3,0x83,0x97,0
+};
+#else
+static const char string1[] = "TOPPERS PROJECT";
+static const char string2[] = "Educational Working Group.";
+#endif
+
+static uint32_t heap_area[256*1024];
+
+intptr_t heap_param[2] = {
+	(intptr_t)heap_area,
+	sizeof(heap_area)
+};
+
+/*
+*  使用する変数の定義
+*/
+static const Point testPolygon[7] = {
+	{0, 0},
+	{319, 239},
+	{160, 0},
+	{160, 239},
+	{319, 0},
+	{0, 239},
+	{0, 0}
+};
+
+LCD_Handler_t  LcdHandle;
+LCD_DrawProp_t DrawProp;
+DVP_Handle_t   DvpHandle;
+OV2640_t       CameraHandle;
+
+uint8_t  sTxBuffer[16];
+
+static uint8_t time_string[12];
+
+static void
+set_value(uint8_t *buf, int value)
+{
+	buf[1] = (value % 10) + '0';
+	buf[0] = (value / 10) + '0';
+}
+
+static void
+set_time(uint8_t *buf, struct tm2 *tm)
+{
+	buf[8] = 0;
+	set_value(&buf[6], tm->tm_sec);
+	buf[5] = ':';
+	set_value(&buf[3], tm->tm_min);
+	buf[2] = ':';
+	set_value(&buf[0], tm->tm_hour);
+}
+
+
+/*
+*  ダイレクトデジタルピン設定
+*/
+void
+pinMode(uint8_t Pin, uint8_t dwMode){ 
+	int gpionum = gpio_get_gpiohno(Pin, false);
+	GPIO_Init_t init = {0};
+
+	syslog_2(LOG_NOTICE, "## pinMode Pin(%d) gpionum(%d) ##", Pin, gpionum);
+	if(gpionum >= 0){
+		uint8_t function = FUNC_GPIOHS0 + gpionum;
+		fpioa_set_function(Pin, function);
+		switch(dwMode){
+		case INPUT:
+			init.mode = GPIO_MODE_INPUT;
+			init.pull = GPIO_NOPULL;
+			break;
+		case INPUT_PULLDOWN:
+			init.mode = GPIO_MODE_INPUT;
+			init.pull = GPIO_PULLDOWN;
+			break;
+		case INPUT_PULLUP:
+			init.mode = GPIO_MODE_INPUT;
+			init.pull = GPIO_PULLUP;
+			break;
+		case OUTPUT:
+		default:
+			init.mode = GPIO_MODE_OUTPUT;
+			init.pull = GPIO_PULLDOWN;
+			break;
+		}
+		gpio_setup(TADR_GPIOHS_BASE, &init, (uint8_t)gpionum);
+	}
+	return ;
+}
+
+/*
+*  ダイレクトデジタルピン出力
+*/
+void
+digitalWrite(uint8_t Pin, int dwVal){
+	int8_t gpio_pin = gpio_get_gpiohno(Pin, false);
+
+	if( gpio_pin >= 0){
+		gpio_set_pin(TADR_GPIOHS_BASE, (uint8_t)gpio_pin, dwVal);
+	}
+}
+
+/*
+*  周期ハンドラ
+*/
+void cyclic_handler(intptr_t exinf)
+{
+	static bool_t b = 0;
+	b ^= 1;
+
+	digitalWrite(LED_PIN, b);
+}
+
+/*
+*  グラフィック表示テスト
+*/
+void
+grapics_test(LCD_Handler_t *hlcd)
+{
+	uint16_t x, y;
+	int      i;
+
+	DrawProp.BackColor = ST7789_BLACK;
+	lcd_fillScreen(&DrawProp);
+	dly_tsk(1000);
+	lcd_drawPixel(hlcd, hlcd->_width/2, hlcd->_height/2, ST7789_GREEN);
+	dly_tsk(1000);
+
+	lcd_fillScreen(&DrawProp);
+	for(y=0; y < hlcd->_height; y+=5) {
+		lcd_drawFastHLine(hlcd, 0, y, hlcd->_width, ST7789_RED);
+	}
+	for (x=0; x < hlcd->_width; x+=5) {
+		lcd_drawFastVLine(hlcd, x, 0, hlcd->_height, ST7789_BLUE);
+	}
+	dly_tsk(1000);
+
+	lcd_fillScreen(&DrawProp);
+	DrawProp.TextColor = ST7789_GREEN;
+	lcd_drawPolygon(&DrawProp, (Point *)testPolygon, sizeof(testPolygon)/sizeof(Point));
+	dly_tsk(1000);
+
+	lcd_fillScreen(&DrawProp);
+	DrawProp.TextColor = ST7789_GREEN;
+	for (y=0; y < hlcd->_height; y+=6) {
+		lcd_drawRect(&DrawProp, hlcd->_width/2 -y/2, hlcd->_height/2 -y/2 , y, y);
+	}
+	for(i = 0 ; i < 3 ; i++){
+		lcd_invertDisplay(hlcd, true);
+		dly_tsk(500);
+		lcd_invertDisplay(hlcd, false);
+		dly_tsk(500);
+	}
+	lcd_fillScreen(&DrawProp);
+	lcd_drawBitmap(hlcd, 33, 48, (uint8_t *)topamelogo);
+	dly_tsk(1000);
+}
+
+/*
+*  メインタスク
+*/
+void main_task(intptr_t exinf)
+{
+	SPI_Init_t Init;
+	SPI_Handle_t    *hspi;
+	LCD_Handler_t   *hlcd;
+	OV2640_t        *hcmr;
+	DVP_Handle_t    *hdvp;
+	uint16_t        *lcd_buffer;
+	ER_UINT	ercd;
+	uint32_t i, count;
+	struct tm2 time;
+	unsigned long atmp;
+#ifdef SDEV_SENSE_ONETIME
+	StorageDevice_t *psdev;
+	SDCARD_Handler_t *hsd = NULL;
+#else
+	uint32_t esize, fsize, headlen;
+	uint8_t  *addr;
+#endif
+
+	SVC_PERROR(syslog_msk_log(LOG_UPTO(LOG_INFO), LOG_UPTO(LOG_EMERG)));
+	syslog(LOG_NOTICE, "Sample program starts (exinf = %d).", (int_t) exinf);
+
+	/*
+	*  シリアルポートの初期化
+	*
+	*  システムログタスクと同じシリアルポートを使う場合など，シリアル
+	*  ポートがオープン済みの場合にはここでE_OBJエラーになるが，支障は
+	*  ない．
+	*/
+	ercd = serial_opn_por(TASK_PORTID);
+	if (ercd < 0 && MERCD(ercd) != E_OBJ) {
+		syslog(LOG_ERROR, "%s (%d) reported by `serial_opn_por'.",
+									itron_strerror(ercd), SERCD(ercd));
+	}
+	SVC_PERROR(serial_ctl_por(TASK_PORTID,
+							(IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV)));
+
+	pinMode(LED_PIN, OUTPUT);
+	SVC_PERROR(sta_cyc(CYCHDR1));
+
+	select_spi0_dvp_mode(1);
+
+#ifdef SDEV_SENSE_ONETIME
+	pinMode(SPI_SS_PIN, OUTPUT);
+	digitalWrite(SPI_SS_PIN, HIGH);
+#else	/* USE ROMFILE */
+	rom_file_init();
+	esize = 1*1024*1024;
+	addr  = (uint8_t *)romfont;
+	while(esize > 4){
+		fsize = (addr[0] << 24) | (addr[1] << 16) | (addr[2] << 8) | addr[3];
+		if((fsize & 3) != 0 || fsize < 16 || fsize > esize)
+			break;
+		for(i = 0 ; i < 28 ; i++){
+			if(addr[i+4] == 0)
+				break;
+		}
+		if(i >= 28)
+			break;
+		if(i < 12)
+			headlen = 16;
+		else
+			headlen = 32;
+		if(create_rom_file((const char *)(addr+4), (uintptr_t)(addr+headlen), fsize-headlen) < 0)
+			break;
+		addr += fsize;
+		esize -= fsize;
+	}
+#endif
+
+	hcmr = &CameraHandle;
+	hcmr->frameSize = FRAMESIZE_QVGA;
+	hcmr->pixFormat = PIXFORMAT_RGB565;
+	ov2640_getResolition(hcmr, FRAMESIZE_QVGA);
+	hcmr->_resetPoliraty  = ACTIVE_HIGH;
+	hcmr->_pwdnPoliraty   = ACTIVE_HIGH;
+	hcmr->_slaveAddr      = 0x00;
+	hcmr->_dataBuffer     = NULL;
+	hcmr->_aiBuffer       = NULL;
+
+	// just support RGB565 and YUV442 on k210
+
+	// Initialize the camera bus, 8bit reg
+	hdvp = &DvpHandle;
+	hcmr->hdvp = hdvp;
+	hdvp->Init.Freq         = 24000000;
+	hdvp->Init.Width        = hcmr->_width;
+	hdvp->Init.Height       = hcmr->_height;
+	hdvp->Init.Format       = DVP_FORMAT_RGB;
+	hdvp->Init.BurstMode    = DVP_BURST_ENABLE;
+	hdvp->Init.AutoMode     = DVP_AUTOMODE_DISABLE;
+	hdvp->Init.GMMlen       = 4;
+
+	hdvp->Init.num_sccb_reg = 8;
+	hdvp->Init.CMosPClkPin  = 47;
+	hdvp->Init.CMosXClkPin  = 46;
+	hdvp->Init.CMosHRefPin  = 45;
+	hdvp->Init.CMosPwDnPin  = 44;
+	hdvp->Init.CMosVSyncPin = 43;
+	hdvp->Init.CMosRstPin   = 42;
+	hdvp->Init.SccbSClkPin  = 41;
+	hdvp->Init.SccbSdaPin   = 40;
+	hdvp->Init.IntNo        = INTNO_DVP;
+	syslog_1(LOG_NOTICE, "## DvpHandle[%08x] ##", &DvpHandle);
+
+	syslog_3(LOG_NOTICE, "## hcmr->_width(%d) hcmr->_height(%d) size[%08x] ##", hcmr->_width, hcmr->_height, (hcmr->_width * hcmr->_height * 2));
+	atmp = (unsigned long)malloc(hcmr->_width * hcmr->_height * 2 + 64); //RGB565
+	hcmr->_dataBuffer = (uint32_t *)((atmp + 63) & ~63);
+	if(hcmr->_dataBuffer == NULL){
+		hcmr->_width = 0;
+		hcmr->_height = 0;
+		syslog_0(LOG_ERROR, "Can't allocate _dataBuffer !");
+		slp_tsk();
+	}
+	atmp = (unsigned long)malloc(hcmr->_width * hcmr->_height * 3 + 128);   //RGB888
+	hcmr->_aiBuffer = (uint32_t *)((atmp + 127) & ~127);
+	if(hcmr->_aiBuffer == NULL){
+		hcmr->_width = 0;
+		hcmr->_height = 0;
+		free(hcmr->_dataBuffer);
+		hcmr->_dataBuffer = NULL;
+		syslog_0(LOG_ERROR, "Can't allocate _aiBuffer !");
+		slp_tsk();
+	}
+	syslog_2(LOG_NOTICE, "## hcmr->_dataBuffer[%08x] hcmr->_aiBuffer[%08x] ##", hcmr->_dataBuffer, hcmr->_aiBuffer);
+	atmp = (unsigned long)hcmr->_aiBuffer - IOMEM;
+	hdvp->Init.RedAddr    = (uint32_t)atmp;
+	atmp = (unsigned long)hcmr->_aiBuffer + hcmr->_width * hcmr->_height - IOMEM;
+	hdvp->Init.GreenAddr  = (uint32_t)atmp;
+	atmp = (unsigned long)hcmr->_aiBuffer + hcmr->_width * hcmr->_height * 2 - IOMEM;
+	hdvp->Init.BlueAddr   = (uint32_t)atmp;
+	atmp = (unsigned long)hcmr->_dataBuffer - IOMEM;
+	hdvp->Init.RGBAddr    = (uint32_t)atmp;
+	dvp_init(hdvp);
+
+	if(ov2640_sensor_ov_detect(hcmr) == E_OK){
+		syslog_0(LOG_NOTICE, "find ov sensor !");
+	}
+	else if(ov2640_sensro_gc_detect(hcmr) == E_OK){
+		syslog_0(LOG_NOTICE, "find gc3028 !");
+	}
+	if(ov2640_reset(hcmr) != E_OK){
+		syslog_0(LOG_ERROR, "ov2640 reset error !");
+		slp_tsk();
+	}
+	if(ov2640_set_pixformat(hcmr) != E_OK){
+		syslog_0(LOG_ERROR, "set pixformat error !");
+		slp_tsk();
+	}
+	if(ov2640_set_framesize(hcmr) != E_OK){
+		syslog_0(LOG_ERROR, "set frame size error !");
+		slp_tsk();
+	}
+	if(ov2640_setInvert(hcmr, false) != E_OK){
+		syslog_0(LOG_ERROR, "set invert error !");
+		slp_tsk();
+	}
+	syslog_1(LOG_NOTICE, "OV2640 id(%d)", ov2640_id(hcmr));
+
+	Init.WorkMode     = SPI_WORK_MODE_0;
+	Init.FrameFormat  = SPI_FF_OCTAL;
+	Init.DataSize     = 8;
+	Init.Prescaler    = 15000000;
+	Init.SignBit      = 0;
+	Init.InstLength   = 8;
+	Init.AddrLength   = 0;
+	Init.WaitCycles   = 0;
+	Init.IATransMode  = SPI_AITM_AS_FRAME_FORMAT;
+	Init.SclkPin      = SIPEED_ST7789_SCLK_PIN;
+	Init.MosiPin      = -1;
+	Init.MisoPin      = -1;
+	Init.SsPin        = SIPEED_ST7789_SS_PIN;
+	Init.SsNo         = SIPEED_ST7789_SS;
+	Init.TxDMAChannel = SIPEED_DMA_CH;
+	Init.RxDMAChannel = -1;
+	Init.semid        = SPI1TRN_SEM;
+	Init.semlock      = SPI1LOCK_SEM;
+	Init.semdmaid     = SPI1DMATX_SEM;
+	hspi = spi_init(SPI_PORTID, &Init);
+	if(hspi == NULL){
+		syslog_0(LOG_ERROR, "SPI INIT ERROR");
+		slp_tsk();
+	}
+
+	hlcd = &LcdHandle;
+	hlcd->hspi    = hspi;
+//	hlcd->spi_lock= SPI1LOCK_SEM;
+	hlcd->dir     = DIR_YX_LRUD;
+	hlcd->dcx_pin = SIPEED_ST7789_DCX_PIN;
+	hlcd->rst_pin = SIPEED_ST7789_RST_PIN;
+	hlcd->cs_sel  = SIPEED_ST7789_SS;
+	hlcd->rst_no  = SIPEED_ST7789_RST_GPIONUM;
+	hlcd->dcx_no  = SIPEED_ST7789_DCX_GPIONUM;
+	DrawProp.hlcd = hlcd;
+	lcd_init(hlcd);
+	syslog_2(LOG_NOTICE, "width(%d) height(%d)", hlcd->_width, hlcd->_height);
+	count = hcmr->_width * hcmr->_height;
+	lcd_buffer = (uint16_t *)malloc(count * 2);
+	if(lcd_buffer == NULL){
+		syslog_0(LOG_ERROR, "no lcd buffer !");
+		slp_tsk();
+	}
+	DrawProp.BackColor = ST7789_WHITE;
+	DrawProp.TextColor = ST7789_BLACK;
+	lcd_fillScreen(&DrawProp);
+
+#ifdef SDEV_SENSE_ONETIME
+	Init.WorkMode     = SPI_WORK_MODE_0;
+	Init.FrameFormat  = SPI_FF_STANDARD;
+	Init.DataSize     = 8;
+	Init.Prescaler    = 5000000;
+	Init.SignBit      = 0;
+	Init.InstLength   = 0;
+	Init.AddrLength   = 0;
+	Init.WaitCycles   = 0;
+	Init.IATransMode  = SPI_AITM_STANDARD;
+	Init.SclkPin      = SPI_SCK_PIN;
+	Init.MosiPin      = SPI_MOSI_PIN;
+	Init.MisoPin      = SPI_MISO_PIN;
+	Init.SsPin        = -1;
+	Init.SsNo         = -1;
+	Init.TxDMAChannel = -1;
+	Init.RxDMAChannel = SPI_DMA1_CH;
+	Init.semid        = SPI2TRN_SEM;
+	Init.semlock      = SPI2LOCK_SEM;
+	Init.semdmaid     = SPI2DMATX_SEM;
+	hspi = spi_init(SPICARD_PORTID, &Init);
+	if(hspi == NULL){
+		syslog_0(LOG_ERROR, "SPI-CARD INIT ERROR");
+		slp_tsk();
+	}
+	sdcard_setspi2(SPISDCARD_PORTID, hspi, SPI_SS_PIN);
+
+	/*
+	*  SD-CARD SPI通信設定
+	*/
+	for(i = 0 ; i < 10 ; i++)
+		sTxBuffer[i] = 0xff;
+	if((ercd = spi_core_transmit(hspi, -1, (uint8_t*)sTxBuffer, 10)) != E_OK){
+		/* Transfer error in transmission process */
+		syslog_1(LOG_NOTICE, "## call Error_Handler(2)(%d) ##", ercd);
+	}
+#if SPI_WAIT_TIME == 0
+	if((ercd = spi_wait(hspi, 100)) != E_OK){
+		syslog_0(LOG_NOTICE, "## call Error_Handler(3) ##");
+	}
+#endif
+	dly_tsk(100);
+	SDMSence_task(0);
+	psdev = SDMGetStorageDevice(SDCARD_DEVNO);
+	hsd = (SDCARD_Handler_t *)psdev->_sdev_local[1];
+	if(hsd == NULL)
+		syslog_0(LOG_ERROR, "SD-CARD INITAIL ERROR !");
+#endif
+
+	for(;;){
+		DrawProp.BackColor = ST7789_WHITE;
+		DrawProp.TextColor = ST7789_BLACK;
+		lcd_fillScreen(&DrawProp);
+		lcd_fillRect(hlcd, 0, 0, hlcd->_width, (hlcd->_height/3)*2-20, ST7789_BLUE);
+		DrawProp.TextColor = ST7789_WHITE;
+		DrawProp.BackColor = ST7789_BLUE;
+		DrawProp.pFont = &Font16;
+		lcd_DisplayStringAt(&DrawProp, 0, 16, (uint8_t *)string1, CENTER_MODE);
+		lcd_DisplayStringAt(&DrawProp, 0, 40, (uint8_t *)string2, CENTER_MODE);
+		lcd_DisplayStringAt(&DrawProp, 0, 64, (uint8_t *)"TOPPERS BASE PLATFORM(RV)", CENTER_MODE);
+
+		DrawProp.TextColor = ST7789_GREEN;
+		lcd_DisplayStringAt(&DrawProp, 0, 88, (uint8_t *)"TOPPERS/ASP Kernel", CENTER_MODE);
+		DrawProp.TextColor = ST7789_RED;
+		lcd_DisplayStringAt(&DrawProp, 0, 112, (uint8_t *)"RISC-V/64 K210", CENTER_MODE);
+		lcd_drawBitmap(hlcd, hlcd->_width/2-30, (hlcd->_height/3)*2, (uint8_t *)topamelogo);
+		dly_tsk(5000);
+
+		DrawProp.BackColor = ST7789_BLACK;
+		DrawProp.TextColor = ST7789_WHITE;
+		grapics_test(hlcd);
+
+		DrawProp.TextColor = ST7789_BLACK;
+		DrawProp.BackColor = ST7789_WHITE;
+		lcd_fillScreen(&DrawProp);
+		lcd_fillRect(hlcd, 0, 0, hlcd->_width, hlcd->_height/3, ST7789_BLUE);
+		DrawProp.TextColor = ST7789_WHITE;
+		DrawProp.BackColor = ST7789_BLUE;
+		DrawProp.pFont = &Font16;
+		lcd_DisplayStringAt(&DrawProp, 0, 16, (uint8_t *)"TOPPERS BASE PLATFORM TEST", CENTER_MODE);
+
+		DrawProp.TextColor = ST7789_BLACK;
+		DrawProp.BackColor = ST7789_WHITE;
+		DrawProp.pFont = &Font8;
+		lcd_DisplayStringAt(&DrawProp, 0, 100, (uint8_t *)"Helle World !", CENTER_MODE);
+		DrawProp.pFont = &Font12;
+		lcd_DisplayStringAt(&DrawProp, 0, 120, (uint8_t *)"Helle World !", CENTER_MODE);
+		DrawProp.pFont = &Font16;
+		lcd_DisplayStringAt(&DrawProp, 0, 140, (uint8_t *)"Helle World !", CENTER_MODE);
+
+		DrawProp.TextColor = ST7789_RED;
+		for(i = 20 ; i < 80 ; i++){
+			lcd_DrawCircle(&DrawProp, hlcd->_width/2, hlcd->_height/2+30, i);
+			if(i == 25)
+				i += 10;
+		}
+		for(i = 0 ; i < 30 ; i++){
+			rtc_get_time(&time);
+			set_time(time_string, &time);
+			lcd_DisplayStringAt(&DrawProp, 0, 160, time_string, CENTER_MODE);
+			dly_tsk(1000);
+		}
+
+		if((ercd = ov2640_activate(hcmr, true)) != E_OK){
+			syslog_2(LOG_NOTICE, "ov2640 activate error result(%d) id(%d) ##", ercd, ov2640_id(hcmr));
+			continue;
+		}
+
+		for(i = 0 ; i < 2000 ; i++){
+			if((i % 100) == 0)
+				syslog_1(LOG_NOTICE, "camera count(%d)", i);
+			ercd = ov2640_snapshot(hcmr);
+			if(ercd == E_OK){
+				uint32_t *p = (uint32_t *)hcmr->_dataBuffer;
+				uint32_t *q = (uint32_t *)lcd_buffer;
+				uint32_t *e = (uint32_t *)&lcd_buffer[count];
+				for (; q < e ; p++, q++){
+					*q = SWAP_32(*p);
+				}
+				lcd_drawPicture(hlcd, 0, 0, hcmr->_width, hcmr->_height, lcd_buffer);
+			}
+		}
+		ov2640_activate(hcmr, false);
+	}
+	syslog_0(LOG_NOTICE, "## STOP ##");
+	slp_tsk();
+	syslog(LOG_NOTICE, "Sample program ends.");
+	SVC_PERROR(ext_ker());
+	assert(0);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/DEMO/demo.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/DEMO/demo.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/DEMO/demo.cfg	(revision 453)
@@ -0,0 +1,46 @@
+/*
+ *  $Id$
+ */
+
+/*
+ *  K210 LEDデモプログラムのシステムコンフィギュレーションファイル
+ */
+INCLUDE("target_timer.cfg");
+INCLUDE("syssvc/syslog.cfg");
+INCLUDE("syssvc/banner.cfg");
+INCLUDE("syssvc/serial.cfg");
+INCLUDE("syssvc/logtask.cfg");
+INCLUDE("pdic/k210/device.cfg");
+INCLUDE("pdic/k210/dvp.cfg");
+INCLUDE("files/storagedevice.cfg");
+INCLUDE("files/ff/fatfs.cfg");
+INCLUDE("monitor/monitor.cfg");
+
+#include "device.h"
+#include "demo.h"
+
+ATT_INI({ TA_NULL, 0, rtc_init });
+ATT_INI({ TA_NULL, 0, rtc_info_init });
+ATT_INI({ TA_NULL, heap_param, heap_init });
+
+CRE_SEM(SPI1TRN_SEM,   { TA_TPRI, 0, 1 });
+CRE_SEM(SPI1DMATX_SEM, { TA_TPRI, 0, 1 });
+CRE_SEM(SPI1LOCK_SEM,  { TA_TPRI, 1, 1 });
+
+CRE_SEM(SPI2TRN_SEM,   { TA_TPRI, 0, 1 });
+CRE_SEM(SPI2DMATX_SEM, { TA_TPRI, 0, 1 });
+CRE_SEM(SPI2LOCK_SEM,  { TA_TPRI, 1, 1 });
+
+CRE_TSK(MAIN_TASK, { TA_ACT, 0, main_task, MAIN_PRIORITY, STACK_SIZE, NULL });
+CRE_CYC(CYCHDR1, { TA_NULL, 0, cyclic_handler, 500, 0 });
+
+ATT_ISR({TA_NULL, SPI_PORTID, INTNO_SPI, spi_isr, 1 });
+CFG_INT(INTNO_SPI, { TA_ENAINT | INTATR_SPI, INTPRI_SPI });
+ATT_ISR({TA_NULL, SIPEED_DMA_CH, INTNO_DMATX, channel_dmac_isr, 1 });
+CFG_INT(INTNO_DMATX, { TA_ENAINT | INTATR_DMATX, INTPRI_DMATX });
+
+ATT_ISR({TA_NULL, SPICARD_PORTID, INTNO_SPIC, spi_isr, 1 });
+CFG_INT(INTNO_SPIC, { TA_ENAINT | INTATR_SPIC, INTPRI_SPIC });
+ATT_ISR({TA_NULL, SPI_DMA1_CH, INTNO_DMARX, channel_dmac_isr, 1 });
+CFG_INT(INTNO_DMARX, { TA_ENAINT | INTATR_DMARX, INTPRI_DMARX });
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/DEMO/demo.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/DEMO/demo.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/DEMO/demo.h	(revision 453)
@@ -0,0 +1,138 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ *
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ *
+ *  $Id$
+ */
+
+/*
+ *		サンプルプログラム(1)のヘッダファイル
+ */
+
+/*
+ *  ターゲット依存の定義
+ */
+#include "target_test.h"
+#include "glcd_disp.h"
+
+/*
+ *  各タスクの優先度の定義
+ */
+
+#define MAIN_PRIORITY	5		/* メインタスクの優先度 */
+								/* HIGH_PRIORITYより高くすること */
+
+/*
+ *  ターゲットに依存する可能性のある定数の定義
+ */
+
+#ifndef TASK_PORTID
+#define	TASK_PORTID		1			/* 文字入力するシリアルポートID */
+#endif /* TASK_PORTID */
+
+#ifndef STACK_SIZE
+#define	STACK_SIZE		8192		/* タスクのスタックサイズ */
+#endif /* STACK_SIZE */
+
+
+#define SIPEED_ST7789_RST_PIN    37
+#define SIPEED_ST7789_DCX_PIN    38
+#define SIPEED_ST7789_SS_PIN     36
+#define SIPEED_ST7789_SCLK_PIN   39
+
+// default peripheral
+#define SIPEED_ST7789_RST_GPIONUM  6
+#define SIPEED_ST7789_DCX_GPIONUM  7
+#define SIPEED_ST7789_SS           3
+
+#define SPISDCARD_PORTID    0
+
+#define SPI_SCK_PIN   27
+#define SPI_MISO_PIN  26
+#define SPI_MOSI_PIN  28
+#define SPI_SS_PIN    29
+#define LED_PIN       3		/* D13 */
+
+#define SPI_PORTID    SPI1_PORTID
+#define INHNO_SPI     IRQ_VECTOR_SPI0	/* 割込みハンドラ番号 */
+#define INTNO_SPI     IRQ_VECTOR_SPI0	/* 割込み番号 */
+#define INTPRI_SPI    -5		/* 割込み優先度 */
+#define INTATR_SPI    0			/* 割込み属性 */
+
+#define SIPEED_DMA_CH DMA_CHANNEL3
+#define INHNO_DMATX   IRQ_VECTOR_DMA3	/* 割込みハンドラ番号 */
+#define INTNO_DMATX   IRQ_VECTOR_DMA3	/* 割込み番号 */
+#define INTPRI_DMATX  -4		/* 割込み優先度 */
+#define INTATR_DMATX  0			/* 割込み属性 */
+
+#define SPICARD_PORTID SPI2_PORTID
+#define INHNO_SPIC    IRQ_VECTOR_SPI1	/* 割込みハンドラ番号 */
+#define INTNO_SPIC    IRQ_VECTOR_SPI1	/* 割込み番号 */
+#define INTPRI_SPIC   -5		/* 割込み優先度 */
+#define INTATR_SPIC   0			/* 割込み属性 */
+
+#define SPI_DMA1_CH   DMA_CHANNEL2
+#define INHNO_DMARX   IRQ_VECTOR_DMA2	/* 割込みハンドラ番号 */
+#define INTNO_DMARX   IRQ_VECTOR_DMA2	/* 割込み番号 */
+#define INTPRI_DMARX  -4		/* 割込み優先度 */
+#define INTATR_DMARX  0			/* 割込み属性 */
+
+#define HIGH 0x1
+#define LOW  0x0
+
+#define INPUT           0x0
+#define OUTPUT          0x3
+#define INPUT_PULLUP    0x2
+#define INPUT_PULLDOWN  0X1
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  ヒープ領域の設定
+ */
+extern intptr_t heap_param[2];
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+
+extern void	main_task(intptr_t exinf);
+extern void heap_init(intptr_t exinf);
+extern void	cyclic_handler(intptr_t exinf);
+
+#endif /* TOPPERS_MACRO_ONLY */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/DEMO/topamelogo.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/DEMO/topamelogo.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/DEMO/topamelogo.h	(revision 453)
@@ -0,0 +1,798 @@
+const unsigned char topamelogo[12726] = {
+	 0x42, 0x4d, 0xd6, 0x23, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 
+	 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x42, 0x00,  0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfd,  0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff, 
+	 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff,  0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 
+	 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff,  0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 
+	 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff,  0xff, 0xf9, 0xf7, 0xfb, 0xff, 0xff, 0xff, 0xe3, 
+	 0xe1, 0xe5, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff,  0xef, 0xef, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xfd, 
+	 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff,  0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 
+	 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xfd, 0xfd,  0xff, 0xfd, 0xfd, 0xff, 0xfd, 0xfb, 0xff, 0xfd, 
+	 0xfb, 0xff, 0xfd, 0xfd, 0xff, 0xfd, 0xfd, 0xff,  0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 
+	 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff,  0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 
+	 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd,  0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff, 
+	 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff,  0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 
+	 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff,  0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 
+	 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xfd, 0xfd,  0xff, 0xfd, 0xfb, 0xff, 0xf1, 0xf1, 0xf5, 0x4f, 
+	 0x4d, 0x51, 0xc5, 0xc3, 0xc7, 0xf9, 0xf7, 0xfb,  0xff, 0xff, 0xff, 0xfb, 0xfb, 0xff, 0xff, 0xfd, 
+	 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff,  0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 
+	 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xfd, 0xfd,  0xff, 0xfd, 0xfd, 0xff, 0xfd, 0xfb, 0xff, 0xfd, 
+	 0xfb, 0xff, 0xfd, 0xfd, 0xff, 0xfd, 0xfd, 0xff,  0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 
+	 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff,  0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 
+	 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 
+	 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5,  0xf9, 0xff, 0xfd, 0xff, 0xbb, 0xbb, 0xbd, 0x61, 
+	 0x61, 0x63, 0xc9, 0x93, 0x9d, 0xff, 0xe1, 0xeb,  0xe9, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff, 0xf9, 
+	 0xff, 0xff, 0xfb, 0xff, 0xff, 0xf9, 0xff, 0xff,  0xef, 0xf5, 0xff, 0xfb, 0xff, 0xff, 0xfb, 0xff, 
+	 0xf3, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xf9,  0xfd, 0xff, 0xfd, 0xff, 0xf7, 0xed, 0xf1, 0xff, 
+	 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xfd,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 
+	 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd,  0xff, 0xff, 0xfd, 0xff, 0x17, 0x17, 0x19, 0x29, 
+	 0x29, 0x2b, 0x35, 0x00, 0x09, 0xff, 0xf7, 0xff,  0xe9, 0xff, 0xff, 0xdb, 0xf5, 0xf3, 0xff, 0xfb, 
+	 0xff, 0xff, 0xed, 0xf3, 0xff, 0xfb, 0xff, 0xff,  0xfb, 0xff, 0xff, 0xf7, 0xfd, 0xff, 0xf9, 0xff, 
+	 0xeb, 0xf9, 0xf9, 0xf3, 0xff, 0xff, 0xff, 0xf5,  0xf9, 0xff, 0xfd, 0xff, 0xc3, 0xb9, 0xbd, 0xed, 
+	 0xe3, 0xe7, 0xfd, 0xf7, 0xfb, 0xfb, 0xf7, 0xf9,  0xf5, 0xf5, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 
+	 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfb,  0xff, 0xc5, 0xb1, 0xb7, 0x5b, 0x5b, 0x5f, 0x3b, 
+	 0x3b, 0x3f, 0x55, 0x65, 0x65, 0xd5, 0xe5, 0xe7,  0xf1, 0xff, 0xff, 0xed, 0xff, 0xff, 0xff, 0xfd, 
+	 0xff, 0xff, 0xfd, 0xff, 0xeb, 0xff, 0xff, 0xe7,  0xfb, 0xfb, 0xff, 0xfd, 0xff, 0xf7, 0xf1, 0xf7, 
+	 0xfd, 0xff, 0xff, 0xef, 0xf1, 0xf5, 0xff, 0xfd,  0xff, 0x59, 0x4f, 0x53, 0x3f, 0x37, 0x3b, 0xff, 
+	 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xfd,  0xff, 0xff, 0xff, 0xef, 0xef, 0xf1, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 
+	 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 
+	 0xfd, 0xfd, 0xff, 0xfd, 0xfd, 0xff, 0xff, 0xef,  0xf5, 0x45, 0x31, 0x37, 0x39, 0x39, 0x3d, 0x35, 
+	 0x35, 0x39, 0x31, 0x41, 0x43, 0x06, 0x15, 0x17,  0xdf, 0xef, 0xf1, 0xed, 0xfd, 0xff, 0xf9, 0xf1, 
+	 0xf5, 0xff, 0xfd, 0xff, 0xe9, 0xfd, 0xfd, 0xe3,  0xf7, 0xf7, 0xf1, 0xeb, 0xef, 0xff, 0xfd, 0xff, 
+	 0xf3, 0xf7, 0xf9, 0xf3, 0xf7, 0xf9, 0x4d, 0x41,  0x45, 0x61, 0x55, 0x59, 0x69, 0x5f, 0x63, 0xfd, 
+	 0xf3, 0xf7, 0xf9, 0xf3, 0xf7, 0xff, 0xfd, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xff, 
+	 0xfd, 0xfd, 0xff, 0xfd, 0xfd, 0xff, 0xff, 0xf9,  0xff, 0x5f, 0x43, 0x51, 0x6f, 0x2f, 0x41, 0x6f, 
+	 0x2f, 0x41, 0x3d, 0x43, 0x4b, 0x49, 0x4f, 0x57,  0xbb, 0xb7, 0xbf, 0xff, 0xfb, 0xff, 0xf7, 0xfd, 
+	 0xff, 0xf9, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff,  0xfb, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xdf, 0xed, 
+	 0xe1, 0xdf, 0xe7, 0x4b, 0x49, 0x51, 0x53, 0x49,  0x4d, 0x3f, 0x35, 0x39, 0x6d, 0x65, 0x69, 0xff, 
+	 0xfd, 0xff, 0xfb, 0xf7, 0xf9, 0xfd, 0xf7, 0xfb,  0xff, 0xff, 0xff, 0xfd, 0xfd, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xff, 
+	 0xfd, 0xfd, 0xff, 0xfb, 0xfb, 0xfd, 0xff, 0xe9,  0xf5, 0x4d, 0x31, 0x3d, 0x79, 0x39, 0x4d, 0x77, 
+	 0x37, 0x49, 0x19, 0x1f, 0x27, 0x3d, 0x43, 0x49,  0x2b, 0x27, 0x2f, 0xff, 0xfd, 0xff, 0xf7, 0xfd, 
+	 0xff, 0xe9, 0xef, 0xf7, 0xf5, 0xe7, 0xf1, 0xfd,  0xef, 0xf9, 0xff, 0xf7, 0xff, 0x97, 0x6b, 0x7b, 
+	 0x4d, 0x4b, 0x53, 0x47, 0x45, 0x4d, 0x4b, 0x3f,  0x43, 0x4f, 0x45, 0x49, 0x9f, 0x95, 0x99, 0xff, 
+	 0xf5, 0xf9, 0xff, 0xfd, 0xff, 0xff, 0xfb, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfb, 0xff, 
+	 0xfd, 0xfb, 0xfd, 0xfd, 0xfb, 0xfd, 0xc7, 0xad,  0xbb, 0x57, 0x3d, 0x4b, 0x49, 0x27, 0x37, 0x5f, 
+	 0x3d, 0x4d, 0x2f, 0x35, 0x3f, 0x47, 0x4d, 0x57,  0x71, 0x4d, 0x5d, 0x63, 0x3f, 0x4f, 0xf7, 0xfb, 
+	 0xff, 0xfb, 0xfd, 0xff, 0xff, 0xf9, 0xff, 0xe1,  0xc1, 0xd1, 0x0b, 0x11, 0x19, 0x4d, 0x53, 0x5d, 
+	 0x3f, 0x43, 0x4b, 0x39, 0x3d, 0x45, 0x37, 0x2d,  0x31, 0x53, 0x47, 0x4b, 0xd3, 0xc9, 0xcd, 0xfd, 
+	 0xf3, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfb, 0xff, 
+	 0xfd, 0xfb, 0xfd, 0xfd, 0xf9, 0xfd, 0xa3, 0x89,  0x97, 0x53, 0x3b, 0x49, 0x63, 0x43, 0x51, 0x3f, 
+	 0x1d, 0x2d, 0xd7, 0xdd, 0xe7, 0x00, 0x04, 0x0b,  0x59, 0x35, 0x45, 0x73, 0x4f, 0x5f, 0x97, 0x99, 
+	 0xa3, 0xf1, 0xf5, 0xff, 0x75, 0x57, 0x65, 0x7f,  0x5f, 0x6f, 0x49, 0x51, 0x59, 0x4d, 0x55, 0x5d, 
+	 0xb7, 0xbb, 0xc5, 0x43, 0x45, 0x4f, 0x45, 0x39,  0x3d, 0x4f, 0x43, 0x47, 0xff, 0xfb, 0xff, 0xff, 
+	 0xfd, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xef, 0xf1,  0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfd, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff,  0xfb, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xf9, 0xfd, 
+	 0xff, 0xfd, 0xff, 0xfb, 0xf9, 0xfb, 0x79, 0x69,  0x75, 0x5b, 0x4b, 0x57, 0x00, 0x59, 0x51, 0x71, 
+	 0xe1, 0xd9, 0xa7, 0xe7, 0xe7, 0x00, 0x09, 0x07,  0x6d, 0x37, 0x4b, 0x63, 0x2f, 0x41, 0x4f, 0x41, 
+	 0x4d, 0x35, 0x27, 0x33, 0x3b, 0x55, 0x5b, 0x31,  0x4b, 0x51, 0x00, 0x4b, 0x3d, 0x61, 0xf9, 0xeb, 
+	 0xaf, 0xbb, 0xc3, 0x3d, 0x47, 0x4f, 0x49, 0x3f,  0x43, 0x27, 0x1d, 0x21, 0xff, 0xfd, 0xff, 0xff, 
+	 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xf9, 0xf9, 0xfb, 0xfd, 0xfd, 
+	 0xff, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xf5,  0xf1, 0xf5, 0xf9, 0xf7, 0xf9, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xf5, 0xf3, 0xf5, 0x75, 0x65,  0x73, 0x45, 0x35, 0x41, 0x00, 0x39, 0x31, 0x7f, 
+	 0xed, 0xe5, 0x95, 0xd7, 0xd5, 0x00, 0x0f, 0x0d,  0x5d, 0x27, 0x3b, 0x61, 0x2d, 0x3f, 0x43, 0x35, 
+	 0x41, 0x4b, 0x3d, 0x49, 0x15, 0x2f, 0x35, 0x31,  0x4b, 0x51, 0x6f, 0xff, 0xf9, 0x4f, 0xe7, 0xd9, 
+	 0xbf, 0xcb, 0xd3, 0x3d, 0x47, 0x4f, 0x55, 0x4b,  0x4f, 0xb3, 0xa7, 0xab, 0xf3, 0xe9, 0xed, 0xff, 
+	 0xf9, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xf9, 0xfb,  0xef, 0xef, 0xf1, 0xff, 0xff, 0xff, 0xfd, 0xfd, 
+	 0xff, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf7, 
+	 0xf9, 0xfb, 0xf9, 0xfb, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xfd, 0xf9, 0xfb, 0xff, 0xff, 0xff, 
+	 0xfd, 0xf9, 0xfb, 0xff, 0xfb, 0xff, 0x77, 0x65,  0x71, 0x63, 0x51, 0x5b, 0x53, 0xd1, 0xc5, 0x81, 
+	 0xff, 0xf3, 0xc5, 0xdf, 0xe1, 0x09, 0x23, 0x27,  0x65, 0x41, 0x4f, 0x67, 0x43, 0x51, 0x33, 0x1b, 
+	 0x27, 0x69, 0x51, 0x5d, 0x53, 0x55, 0x5d, 0x19,  0x1d, 0x25, 0x61, 0xf5, 0xe5, 0x4d, 0xe1, 0xd1, 
+	 0xab, 0xb3, 0xb9, 0x4b, 0x53, 0x59, 0x37, 0x2d,  0x31, 0xff, 0xfb, 0xff, 0xff, 0xf9, 0xfd, 0xff, 
+	 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xfb, 0xfb, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xfd, 
+	 0xff, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 
+	 0xff, 0xfd, 0xf9, 0xfd, 0xf5, 0xf1, 0xf3, 0xff,  0xf9, 0xfd, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 
+	 0xfb, 0xf7, 0xf9, 0xff, 0xff, 0xff, 0x7d, 0x6b,  0x77, 0x73, 0x61, 0x6d, 0x7b, 0xf9, 0xed, 0x00, 
+	 0x61, 0x55, 0x9b, 0xb3, 0xb7, 0x95, 0xaf, 0xb1,  0xf5, 0xcf, 0xdd, 0xff, 0xdf, 0xed, 0xff, 0xf9, 
+	 0xff, 0xfb, 0xe1, 0xed, 0xbd, 0xc1, 0xc7, 0x91,  0x95, 0x9d, 0x00, 0x75, 0x65, 0x75, 0xff, 0xf9, 
+	 0x79, 0x81, 0x87, 0x31, 0x39, 0x41, 0x5f, 0x53,  0x57, 0xf5, 0xe9, 0xed, 0xff, 0xfd, 0xff, 0xff, 
+	 0xfd, 0xff, 0xf7, 0xf3, 0xf5, 0xfb, 0xf5, 0xf9,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 
+	 0xff, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xf9, 0xf5, 
+	 0xf9, 0xff, 0xff, 0xff, 0xfd, 0xf9, 0xfb, 0xff,  0xfd, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf1, 0xf5, 
+	 0xfb, 0xf3, 0xf7, 0xff, 0xf9, 0xfd, 0xaf, 0x8d,  0x95, 0x39, 0x17, 0x21, 0xbd, 0xe7, 0xe3, 0xd3, 
+	 0xfd, 0xf9, 0xff, 0xe3, 0xed, 0xff, 0xf7, 0xff,  0xfb, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xfb, 
+	 0xff, 0xff, 0xf3, 0xf9, 0xff, 0xf1, 0xfb, 0xff,  0xf9, 0xff, 0xdd, 0xff, 0xfd, 0x8f, 0xb1, 0xaf, 
+	 0x2d, 0x25, 0x29, 0x4b, 0x43, 0x47, 0xfb, 0xef,  0xf3, 0xf7, 0xeb, 0xef, 0xfb, 0xf1, 0xf5, 0xff, 
+	 0xf7, 0xfb, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xef, 0xef, 0xf1, 0xfd, 0xfd, 
+	 0xff, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xfb, 0xf7, 
+	 0xfb, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xf1,  0xeb, 0xef, 0xff, 0xfd, 0xff, 0xff, 0xfb, 0xfd, 
+	 0xff, 0xff, 0xff, 0xfb, 0xf5, 0xf7, 0x3d, 0x1b,  0x25, 0x85, 0x63, 0x6d, 0xc9, 0xf3, 0xef, 0xdd, 
+	 0xff, 0xff, 0xff, 0xf1, 0xfb, 0xff, 0xf9, 0xff,  0xf3, 0xf9, 0xfb, 0xef, 0xf3, 0xf7, 0xff, 0xfb, 
+	 0xff, 0xff, 0xfb, 0xff, 0xff, 0xf1, 0xfb, 0xff,  0xf5, 0xff, 0xcb, 0xed, 0xeb, 0xe1, 0xff, 0xff, 
+	 0x89, 0x7f, 0x83, 0x1d, 0x13, 0x19, 0xfd, 0xf1,  0xf5, 0xff, 0xfd, 0xff, 0xff, 0xf5, 0xf9, 0xff, 
+	 0xfd, 0xff, 0xfb, 0xf5, 0xf9, 0xfb, 0xf5, 0xf9,  0xff, 0xff, 0xff, 0xfd, 0xfd, 0xff, 0xfd, 0xfd, 
+	 0xff, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xff,  0xff, 0xfd, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 
+	 0xff, 0xe1, 0xdd, 0xe1, 0xff, 0xff, 0xff, 0xc3,  0xbd, 0xc1, 0x79, 0x71, 0x75, 0x63, 0x5d, 0x5f, 
+	 0x9b, 0x95, 0x97, 0xb1, 0xa9, 0xad, 0x73, 0x41,  0x4b, 0xe7, 0xb3, 0xbd, 0xdd, 0xf9, 0xf5, 0xe1, 
+	 0xfb, 0xf9, 0xff, 0xf9, 0xfd, 0xff, 0xf5, 0xf9,  0xdd, 0xff, 0xff, 0xdb, 0xff, 0xff, 0xff, 0xf9, 
+	 0xfd, 0xf9, 0xef, 0xf3, 0xfb, 0xff, 0xff, 0xf1,  0xf7, 0xf7, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfd, 
+	 0xbf, 0xa3, 0xa9, 0x65, 0x49, 0x51, 0xe3, 0xd7,  0xdb, 0xf5, 0xe9, 0xed, 0xbf, 0xb5, 0xb9, 0xd3, 
+	 0xc9, 0xcd, 0xf3, 0xed, 0xf1, 0xff, 0xff, 0xff,  0xf1, 0xf1, 0xf3, 0xfd, 0xfd, 0xff, 0xfd, 0xfd, 
+	 0xff, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xff,  0xff, 0xfb, 0xff, 0xff, 0xfb, 0xff, 0xc1, 0xbf, 
+	 0xc1, 0x11, 0x0d, 0x11, 0x5b, 0x55, 0x59, 0x53,  0x4f, 0x51, 0x51, 0x49, 0x4d, 0x57, 0x51, 0x53, 
+	 0x57, 0x4f, 0x53, 0x2d, 0x27, 0x29, 0x6f, 0x3d,  0x47, 0xef, 0xbb, 0xc5, 0xdd, 0xf9, 0xf5, 0xe7, 
+	 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff,  0xd5, 0xff, 0xf9, 0xdd, 0xff, 0xff, 0xff, 0xfd, 
+	 0xff, 0xff, 0xfd, 0xff, 0xf7, 0xfd, 0xff, 0xf5,  0xfb, 0xfd, 0xfb, 0xfb, 0xfd, 0xeb, 0xeb, 0xed, 
+	 0xd9, 0xbd, 0xc3, 0x61, 0x45, 0x4d, 0x73, 0x69,  0x6d, 0x61, 0x55, 0x59, 0x5b, 0x51, 0x55, 0x55, 
+	 0x4b, 0x4f, 0x53, 0x4f, 0x51, 0x45, 0x41, 0x43,  0x6d, 0x6d, 0x6f, 0xf9, 0xf9, 0xfb, 0xfd, 0xfd, 
+	 0xff, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff,  0xfb, 0xef, 0xfd, 0xf7, 0xfb, 0xfd, 0xfb, 0xff, 
+	 0xff, 0xff, 0xf3, 0xe3, 0xf3, 0xff, 0xf5, 0xff,  0xdb, 0xc7, 0xe3, 0x23, 0x0f, 0x29, 0x57, 0x4b, 
+	 0x63, 0x4f, 0x43, 0x5b, 0x47, 0x43, 0x4f, 0x3f,  0x3b, 0x49, 0x97, 0x8f, 0xa1, 0xa5, 0x9d, 0xaf, 
+	 0xa7, 0x95, 0xb7, 0x1f, 0x0d, 0x2f, 0x47, 0x39,  0x49, 0xcf, 0xc1, 0xd3, 0xe7, 0xff, 0xf1, 0xef, 
+	 0xff, 0xf7, 0xe3, 0xfb, 0xef, 0xef, 0xff, 0xfb,  0xff, 0xed, 0xff, 0xff, 0xf5, 0xff, 0xff, 0xeb, 
+	 0xff, 0xff, 0xf5, 0xff, 0xef, 0xff, 0xfb, 0xe7,  0xff, 0xf3, 0xef, 0xff, 0xf7, 0xe3, 0xfb, 0xeb, 
+	 0xdb, 0xcd, 0xdf, 0x45, 0x39, 0x49, 0x77, 0x6b,  0x85, 0x9f, 0x93, 0xad, 0xbb, 0xb3, 0xc5, 0x7d, 
+	 0x77, 0x87, 0x45, 0x3d, 0x51, 0x3f, 0x35, 0x49,  0x4b, 0x37, 0x53, 0x57, 0x43, 0x61, 0x5d, 0x43, 
+	 0x5d, 0xf7, 0xdd, 0xf7, 0xfd, 0xed, 0xf5, 0xfd,  0xed, 0xf5, 0xf7, 0xf9, 0xf7, 0xfd, 0xff, 0xfd, 
+	 0xe7, 0xf7, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff,  0xfd, 0xf3, 0xff, 0xfb, 0xf1, 0xf3, 0xf1, 0xfd, 
+	 0xff, 0xfd, 0xff, 0xf7, 0xff, 0x5f, 0x4f, 0x5f,  0x41, 0x2b, 0x47, 0x4b, 0x37, 0x51, 0x3b, 0x2f, 
+	 0x47, 0x3f, 0x33, 0x4b, 0xa9, 0xa5, 0xb1, 0xef,  0xeb, 0xf9, 0xff, 0xfb, 0xff, 0xfd, 0xf5, 0xff, 
+	 0xff, 0xed, 0xff, 0x51, 0x3f, 0x5f, 0x49, 0x3b,  0x4b, 0xcb, 0xbd, 0xcd, 0xe5, 0xfd, 0xed, 0xd7, 
+	 0xf1, 0xe1, 0xef, 0xff, 0xfb, 0xef, 0xff, 0xfb,  0xff, 0xef, 0xff, 0xff, 0xf5, 0xff, 0xff, 0xf5, 
+	 0xff, 0xff, 0xf3, 0xff, 0xef, 0xff, 0xfb, 0xe9,  0xff, 0xf5, 0xd9, 0xf3, 0xe3, 0xef, 0xff, 0xf7, 
+	 0xc1, 0xb3, 0xc5, 0x55, 0x47, 0x57, 0x9f, 0x91,  0xad, 0xff, 0xf7, 0xff, 0xf5, 0xef, 0xff, 0xfd, 
+	 0xf7, 0xff, 0xe1, 0xd9, 0xeb, 0x3b, 0x31, 0x45,  0x51, 0x3d, 0x5b, 0x41, 0x2d, 0x49, 0x4f, 0x33, 
+	 0x4f, 0x47, 0x2d, 0x47, 0x87, 0x77, 0x7f, 0xff,  0xfb, 0xff, 0xef, 0xef, 0xed, 0xf5, 0xf7, 0xf5, 
+	 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xed, 0xed, 0xf1, 0xff, 0xfb, 0xff, 0xff, 
+	 0xf5, 0xff, 0x4f, 0x33, 0x45, 0x65, 0x49, 0x5b,  0x51, 0x35, 0x47, 0x47, 0x2b, 0x3d, 0x55, 0x45, 
+	 0x51, 0xa7, 0x99, 0xa3, 0xf5, 0xf1, 0xf1, 0xff,  0xfb, 0xfb, 0xf5, 0xef, 0xf3, 0xf9, 0xf3, 0xf7, 
+	 0xff, 0xf3, 0xfd, 0x99, 0x8d, 0x97, 0x77, 0x43,  0x65, 0xb3, 0x7f, 0xa1, 0xff, 0xfd, 0xff, 0xff, 
+	 0xfd, 0xff, 0xfd, 0xff, 0xf9, 0xf3, 0xf7, 0xef,  0xff, 0xff, 0xfb, 0xff, 0xfd, 0xf9, 0xff, 0xf9, 
+	 0xf5, 0xff, 0xf5, 0xf1, 0xfd, 0xff, 0xf9, 0xff,  0xff, 0xfb, 0xff, 0xfd, 0xff, 0xed, 0xe3, 0xe7, 
+	 0xe9, 0xb5, 0xd7, 0x75, 0x43, 0x65, 0xd1, 0xc9,  0xd1, 0xf3, 0xe9, 0xf1, 0xff, 0xfb, 0xfd, 0xfb, 
+	 0xf7, 0xf9, 0xf7, 0xed, 0xf5, 0xfb, 0xf1, 0xf9,  0x51, 0x3b, 0x4b, 0x49, 0x33, 0x43, 0x55, 0x35, 
+	 0x47, 0x55, 0x35, 0x47, 0x57, 0x3d, 0x47, 0x7f,  0x63, 0x6f, 0xff, 0xf3, 0xf9, 0xfd, 0xef, 0xf5, 
+	 0xed, 0xed, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xf3,  0xf7, 0xf5, 0xf5, 0xf9, 0xff, 0xef, 0xf9, 0x59, 
+	 0x49, 0x53, 0x55, 0x39, 0x4b, 0x4f, 0x33, 0x45,  0x51, 0x35, 0x47, 0x51, 0x35, 0x47, 0x85, 0x75, 
+	 0x81, 0xff, 0xf3, 0xfd, 0xff, 0xff, 0xff, 0xf5,  0xf1, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xfd, 0xf1, 0xfb, 0xe9, 0xdd, 0xe7, 0x71, 0x3f,  0x61, 0x79, 0x47, 0x69, 0xf1, 0xe7, 0xeb, 0xff, 
+	 0xfd, 0xff, 0xf1, 0xf7, 0xed, 0xf3, 0xf9, 0xef,  0xff, 0xff, 0xfb, 0xff, 0xfb, 0xf7, 0xff, 0xff, 
+	 0xfb, 0xff, 0xf9, 0xf5, 0xfd, 0xff, 0xf9, 0xfd,  0xff, 0xf9, 0xfd, 0xf3, 0xf7, 0xff, 0xfd, 0xff, 
+	 0xa3, 0x6f, 0x93, 0x67, 0x35, 0x57, 0xfb, 0xf1,  0xf9, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xfb, 0xfd, 0xff, 0xf9, 0xff, 0xff, 0xfd, 0xff,  0xdb, 0xc3, 0xd3, 0x55, 0x3f, 0x4f, 0x51, 0x31, 
+	 0x43, 0x4f, 0x2f, 0x41, 0x59, 0x3d, 0x49, 0x65,  0x49, 0x55, 0x8f, 0x81, 0x87, 0xff, 0xfd, 0xff, 
+	 0xf3, 0xf3, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9,  0xff, 0xff, 0xfb, 0xff, 0x81, 0x63, 0x77, 0x63, 
+	 0x45, 0x59, 0x5d, 0x37, 0x47, 0x4b, 0x27, 0x37,  0x55, 0x35, 0x39, 0x5f, 0x3f, 0x45, 0xf7, 0xe7, 
+	 0xe7, 0xff, 0xfd, 0xfd, 0xfb, 0xf7, 0xf9, 0xfd,  0xf7, 0xfb, 0xfb, 0xfb, 0xfd, 0xfd, 0xfd, 0xff, 
+	 0xfb, 0xf9, 0xf9, 0xfb, 0xf9, 0xf9, 0x35, 0x0b,  0x19, 0x63, 0x39, 0x47, 0xd5, 0xc5, 0xd5, 0xff, 
+	 0xf9, 0xff, 0xf5, 0xfb, 0xff, 0xf9, 0xff, 0xff,  0xf9, 0xfd, 0xf7, 0xff, 0xff, 0xfb, 0xfd, 0xff, 
+	 0xf9, 0xff, 0xff, 0xfb, 0xf5, 0xfb, 0xff, 0xf1,  0xf7, 0xfd, 0xff, 0xf7, 0xff, 0xf3, 0xe3, 0xf3, 
+	 0x65, 0x3b, 0x49, 0x49, 0x1d, 0x2b, 0xf9, 0xf9,  0xf9, 0xe7, 0xe7, 0xe7, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xf5, 0xf9, 0xfd, 0xf3, 0xf7,  0xff, 0xfb, 0xfb, 0x9d, 0x87, 0x87, 0x51, 0x2d, 
+	 0x33, 0x53, 0x2f, 0x35, 0x5f, 0x35, 0x45, 0x65,  0x3b, 0x4b, 0x61, 0x43, 0x55, 0xd9, 0xbb, 0xcf, 
+	 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9,  0xff, 0xeb, 0xdb, 0xe7, 0x61, 0x43, 0x57, 0x57, 
+	 0x39, 0x4d, 0x4f, 0x29, 0x39, 0x5f, 0x39, 0x49,  0x61, 0x41, 0x47, 0x89, 0x69, 0x6d, 0xff, 0xf5, 
+	 0xf5, 0xff, 0xf5, 0xf5, 0xff, 0xfd, 0xff, 0xff,  0xff, 0xff, 0xfb, 0xfb, 0xfd, 0xf9, 0xf9, 0xfb, 
+	 0xfb, 0xf9, 0xf9, 0xf5, 0xf3, 0xf3, 0x87, 0x5d,  0x6b, 0x59, 0x2d, 0x3b, 0x87, 0x77, 0x89, 0xf3, 
+	 0xe3, 0xf5, 0xf5, 0xfb, 0xff, 0xf9, 0xff, 0xff,  0xfb, 0xff, 0xf7, 0xff, 0xff, 0xfb, 0xf9, 0xfd, 
+	 0xf7, 0xff, 0xff, 0xfb, 0xf7, 0xfd, 0xff, 0xf7,  0xfd, 0xff, 0xfd, 0xed, 0xff, 0x71, 0x61, 0x73, 
+	 0x63, 0x39, 0x47, 0xaf, 0x85, 0x91, 0xff, 0xff,  0xff, 0xf9, 0xf9, 0xf9, 0xeb, 0xe9, 0xed, 0xfd, 
+	 0xfd, 0xff, 0xf9, 0xef, 0xf3, 0xff, 0xfd, 0xff,  0xff, 0xfd, 0xff, 0xcf, 0xb9, 0xbb, 0x6b, 0x47, 
+	 0x4d, 0x51, 0x2d, 0x33, 0x61, 0x39, 0x47, 0x51,  0x27, 0x37, 0x4d, 0x2f, 0x41, 0x67, 0x49, 0x5d, 
+	 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5,  0xff, 0x6b, 0x59, 0x63, 0x5b, 0x3d, 0x51, 0x45, 
+	 0x27, 0x3b, 0x47, 0x23, 0x31, 0x5d, 0x39, 0x47,  0x4d, 0x33, 0x2f, 0xab, 0x91, 0x8d, 0xff, 0xf3, 
+	 0xf7, 0xff, 0xfd, 0xff, 0xfb, 0xf7, 0xff, 0xeb,  0xe7, 0xff, 0xf3, 0xf5, 0xff, 0xf3, 0xf5, 0xff, 
+	 0xed, 0xf5, 0xff, 0xf1, 0xf9, 0xff, 0xe1, 0xe3,  0xff, 0x4d, 0x4d, 0x6d, 0x21, 0x21, 0x6d, 0x75, 
+	 0x75, 0xc3, 0x75, 0x79, 0xd7, 0x73, 0x77, 0xd5,  0x65, 0x6f, 0xbd, 0x47, 0x51, 0x9f, 0x5d, 0x65, 
+	 0xb5, 0x4b, 0x55, 0xa3, 0x6f, 0x73, 0xd1, 0x7d,  0x81, 0xdf, 0x5b, 0x5d, 0xa9, 0x37, 0x37, 0x83, 
+	 0x41, 0x41, 0x61, 0xf1, 0xf3, 0xff, 0xdd, 0xe5,  0xff, 0xf1, 0xf9, 0xff, 0xf3, 0xf5, 0xff, 0xe7, 
+	 0xe9, 0xff, 0xff, 0xf7, 0xff, 0xf5, 0xef, 0xff,  0xff, 0xfb, 0xfd, 0xb5, 0xa3, 0xa5, 0x4b, 0x2d, 
+	 0x2b, 0x5b, 0x3d, 0x3b, 0x53, 0x29, 0x3b, 0x63,  0x39, 0x4d, 0x4b, 0x2d, 0x41, 0x61, 0x41, 0x57, 
+	 0xb7, 0xa9, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xe9,  0xf5, 0x31, 0x1f, 0x29, 0x55, 0x37, 0x4b, 0x49, 
+	 0x29, 0x3f, 0x69, 0x45, 0x53, 0x51, 0x2d, 0x3b,  0x47, 0x2b, 0x29, 0x9b, 0x7f, 0x7d, 0xff, 0xf5, 
+	 0xf9, 0xf7, 0xeb, 0xef, 0xf3, 0xef, 0xff, 0xf7,  0xf3, 0xff, 0xf3, 0xf5, 0xff, 0xad, 0xad, 0xd5, 
+	 0x53, 0x5b, 0x75, 0x27, 0x2d, 0x49, 0x4b, 0x4b,  0x6b, 0x5b, 0x5b, 0x7b, 0x63, 0x63, 0xaf, 0x7d, 
+	 0x7d, 0xcb, 0x6d, 0x71, 0xcf, 0x55, 0x5b, 0xb7,  0x5b, 0x65, 0xb3, 0x65, 0x6d, 0xbd, 0x55, 0x5f, 
+	 0xad, 0x5f, 0x69, 0xb7, 0x71, 0x75, 0xd3, 0x61,  0x65, 0xc3, 0x79, 0x79, 0xc7, 0x53, 0x53, 0x9f, 
+	 0x5b, 0x5b, 0x7b, 0x43, 0x43, 0x63, 0x29, 0x2f,  0x4f, 0x69, 0x71, 0x8f, 0x6d, 0x6f, 0x97, 0xd9, 
+	 0xdb, 0xff, 0xf1, 0xeb, 0xff, 0xf1, 0xe9, 0xff,  0xe5, 0xd5, 0xd7, 0x63, 0x51, 0x55, 0x55, 0x35, 
+	 0x35, 0x59, 0x39, 0x39, 0x61, 0x37, 0x49, 0x4f,  0x25, 0x37, 0x59, 0x39, 0x4f, 0x4d, 0x2d, 0x43, 
+	 0x37, 0x29, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xf5,  0xf5, 0x5d, 0x57, 0x57, 0x51, 0x3b, 0x4d, 0x49, 
+	 0x35, 0x45, 0x45, 0x2b, 0x35, 0x57, 0x3d, 0x47,  0x53, 0x47, 0x3d, 0x5b, 0x4f, 0x45, 0xd9, 0xd5, 
+	 0xe9, 0xaf, 0xab, 0xbf, 0x2f, 0x27, 0x7b, 0x85,  0x7f, 0xd3, 0x77, 0x75, 0xdd, 0x4b, 0x4b, 0xb3, 
+	 0x5d, 0x69, 0xb9, 0x5d, 0x69, 0xb9, 0x4f, 0x59,  0xd5, 0x37, 0x43, 0xbf, 0x41, 0x3b, 0xdf, 0x47, 
+	 0x41, 0xe5, 0x41, 0x3b, 0xe9, 0x3b, 0x35, 0xe3,  0x3f, 0x47, 0xdb, 0x39, 0x41, 0xd7, 0x3b, 0x43, 
+	 0xd7, 0x35, 0x3d, 0xd3, 0x4d, 0x47, 0xf5, 0x31,  0x2b, 0xd9, 0x4b, 0x45, 0xe9, 0x45, 0x3f, 0xe3, 
+	 0x41, 0x4d, 0xc9, 0x43, 0x4d, 0xc9, 0x5d, 0x65,  0xc1, 0x5f, 0x69, 0xc5, 0x33, 0x33, 0x99, 0x87, 
+	 0x87, 0xed, 0xbd, 0xb9, 0xff, 0x65, 0x63, 0xab,  0x45, 0x3d, 0x4d, 0x55, 0x4d, 0x5d, 0x5f, 0x49, 
+	 0x47, 0x4f, 0x39, 0x37, 0x49, 0x29, 0x3d, 0x53,  0x33, 0x47, 0x4f, 0x39, 0x4b, 0x43, 0x2d, 0x41, 
+	 0x51, 0x4f, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xc1,  0xc1, 0x53, 0x4d, 0x4d, 0x4d, 0x37, 0x49, 0x45, 
+	 0x31, 0x41, 0x71, 0x55, 0x61, 0x41, 0x25, 0x31,  0x3f, 0x33, 0x29, 0x83, 0x77, 0x6d, 0xf1, 0xed, 
+	 0xff, 0xf9, 0xf5, 0xff, 0x9f, 0x99, 0xed, 0x51,  0x49, 0x9d, 0x5d, 0x5b, 0xc5, 0x51, 0x51, 0xb9, 
+	 0x51, 0x5d, 0xad, 0x4d, 0x59, 0xa9, 0x43, 0x4f,  0xcb, 0x3f, 0x49, 0xc5, 0x57, 0x51, 0xf5, 0x3f, 
+	 0x39, 0xdd, 0x31, 0x2d, 0xd9, 0x45, 0x3f, 0xed,  0x31, 0x3b, 0xcf, 0x45, 0x4d, 0xe3, 0x3d, 0x45, 
+	 0xdb, 0x3d, 0x45, 0xd9, 0x3f, 0x39, 0xe7, 0x49,  0x43, 0xf1, 0x47, 0x3f, 0xe3, 0x43, 0x3d, 0xe1, 
+	 0x45, 0x4f, 0xcb, 0x3b, 0x47, 0xc3, 0x47, 0x51,  0xad, 0x49, 0x53, 0xad, 0x57, 0x57, 0xbd, 0x69, 
+	 0x69, 0xcf, 0x4b, 0x45, 0x8f, 0x89, 0x85, 0xcd,  0xfd, 0xf5, 0xff, 0xf3, 0xed, 0xfd, 0xaf, 0x9b, 
+	 0x97, 0x81, 0x6b, 0x69, 0x57, 0x35, 0x4b, 0x61,  0x41, 0x55, 0x41, 0x2b, 0x3d, 0x53, 0x3d, 0x51, 
+	 0x59, 0x57, 0x51, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff,  0xfb, 0x57, 0x5d, 0x55, 0x31, 0x23, 0x35, 0x55, 
+	 0x47, 0x59, 0xc7, 0xb5, 0xbb, 0xff, 0xf7, 0xff,  0xff, 0xff, 0xf7, 0xff, 0xff, 0xf3, 0xe7, 0xe7, 
+	 0xff, 0x3d, 0x3d, 0x61, 0x63, 0x59, 0xd9, 0x59,  0x51, 0xd1, 0x49, 0x43, 0xe3, 0x4f, 0x4b, 0xe9, 
+	 0x41, 0x4d, 0xcd, 0x35, 0x41, 0xc1, 0x37, 0x33,  0xdf, 0x3f, 0x3b, 0xe5, 0x47, 0x3f, 0xdf, 0x3d, 
+	 0x35, 0xd5, 0x29, 0x41, 0xbb, 0x45, 0x5b, 0xd5,  0x49, 0x8b, 0xd9, 0x00, 0x1f, 0x6f, 0x00, 0x41, 
+	 0x8f, 0x3b, 0x7d, 0xcb, 0x3f, 0x53, 0xcd, 0x2b,  0x41, 0xbb, 0x47, 0x3f, 0xdf, 0x39, 0x31, 0xd1, 
+	 0x3b, 0x35, 0xe1, 0x45, 0x41, 0xed, 0x47, 0x4f,  0xdd, 0x35, 0x3f, 0xcd, 0x3b, 0x37, 0xd3, 0x37, 
+	 0x33, 0xcf, 0x67, 0x61, 0xd3, 0x5d, 0x57, 0xc9,  0x51, 0x4d, 0x69, 0xf3, 0xef, 0xff, 0xff, 0xff, 
+	 0xfd, 0xff, 0xf3, 0xf1, 0xfd, 0xe1, 0xfb, 0xc1,  0xa7, 0xbf, 0x59, 0x4b, 0x5f, 0x59, 0x49, 0x5f, 
+	 0x4f, 0x5d, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe5, 0xeb,  0xe5, 0xd5, 0xdb, 0xd5, 0xe7, 0xd9, 0xeb, 0xff, 
+	 0xf9, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xed, 0xf3,  0xfd, 0xf9, 0xeb, 0xf1, 0xed, 0xe1, 0x21, 0x21, 
+	 0x45, 0x6f, 0x6f, 0x93, 0x5b, 0x53, 0xd1, 0x51,  0x49, 0xc9, 0x3f, 0x3b, 0xd9, 0x3b, 0x37, 0xd5, 
+	 0x43, 0x4f, 0xcf, 0x49, 0x55, 0xd5, 0x47, 0x41,  0xed, 0x49, 0x43, 0xef, 0x3b, 0x33, 0xd3, 0x53, 
+	 0x4b, 0xeb, 0x45, 0x59, 0xd3, 0x23, 0x3b, 0xb5,  0x65, 0xa7, 0xf7, 0x9b, 0xdd, 0xff, 0x89, 0xcb, 
+	 0xff, 0x61, 0xa3, 0xf3, 0x43, 0x59, 0xd3, 0x4d,  0x61, 0xdb, 0x43, 0x3b, 0xdb, 0x53, 0x4b, 0xeb, 
+	 0x43, 0x3f, 0xe9, 0x41, 0x3b, 0xe7, 0x3b, 0x43,  0xd3, 0x3f, 0x47, 0xd7, 0x49, 0x43, 0xe1, 0x4b, 
+	 0x47, 0xe5, 0x4f, 0x4b, 0xbb, 0x55, 0x4f, 0xbf,  0x41, 0x3d, 0x59, 0x29, 0x25, 0x41, 0xed, 0xdf, 
+	 0xdd, 0xff, 0xf3, 0xf1, 0xff, 0xf5, 0xff, 0xff,  0xf1, 0xff, 0xff, 0xf9, 0xff, 0xef, 0xdf, 0xf3, 
+	 0xcb, 0xd7, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xfd,  0xf9, 0xfb, 0xff, 0xff, 0xfb, 0xed, 0xff, 0xf5, 
+	 0xe7, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xfb, 0xff,  0xff, 0xfd, 0xeb, 0x21, 0x1d, 0x0b, 0x37, 0x33, 
+	 0x5d, 0x51, 0x4d, 0x77, 0x4d, 0x3f, 0xd7, 0x57,  0x49, 0xdf, 0x35, 0x29, 0xe3, 0x57, 0x49, 0xff, 
+	 0x35, 0x3d, 0xd3, 0x3d, 0x45, 0xd9, 0x41, 0x39,  0xd5, 0x49, 0x3f, 0xdd, 0x49, 0x5b, 0xc3, 0x4b, 
+	 0x5d, 0xc5, 0x00, 0x4d, 0x6f, 0x91, 0xf1, 0xff,  0x4f, 0xf9, 0xf5, 0x35, 0xdf, 0xdb, 0x3f, 0xeb, 
+	 0xe7, 0x3b, 0xe7, 0xe3, 0x85, 0xe5, 0xff, 0x00,  0x55, 0x77, 0x5f, 0x71, 0xd9, 0x2f, 0x43, 0xa9, 
+	 0x49, 0x3f, 0xdd, 0x47, 0x3d, 0xdb, 0x45, 0x47,  0xed, 0x2d, 0x31, 0xd7, 0x4b, 0x3f, 0xf7, 0x3d, 
+	 0x33, 0xeb, 0x4b, 0x41, 0xc5, 0x61, 0x55, 0xd9,  0x31, 0x2d, 0x4b, 0x3b, 0x35, 0x55, 0x2d, 0x21, 
+	 0x1b, 0xfb, 0xef, 0xe9, 0xff, 0xf5, 0xff, 0xff,  0xe9, 0xff, 0xf5, 0xe7, 0xff, 0xff, 0xf7, 0xff, 
+	 0xef, 0xff, 0xe9, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff,  0xff, 0xef, 0xf5, 0xf3, 0xff, 0xf3, 0xff, 0xff, 
+	 0xf7, 0xff, 0xff, 0xf3, 0xfb, 0xff, 0xef, 0xf7,  0x2d, 0x29, 0x19, 0x4f, 0x4b, 0x39, 0x29, 0x27, 
+	 0x4f, 0x53, 0x4f, 0x79, 0x41, 0x33, 0xc9, 0x43,  0x35, 0xcb, 0x41, 0x35, 0xf1, 0x43, 0x37, 0xf3, 
+	 0x3d, 0x45, 0xd9, 0x3b, 0x43, 0xd7, 0x47, 0x3d,  0xdb, 0x4b, 0x41, 0xdf, 0x63, 0x75, 0xdd, 0x3f, 
+	 0x53, 0xb9, 0x49, 0xa7, 0xcb, 0x65, 0xc3, 0xe7,  0x31, 0xdb, 0xd7, 0x3d, 0xe7, 0xe3, 0x49, 0xf3, 
+	 0xef, 0x37, 0xe3, 0xdf, 0x69, 0xc7, 0xeb, 0x1d,  0x7b, 0x9f, 0x11, 0x25, 0x8d, 0x5f, 0x71, 0xd9, 
+	 0x5b, 0x4f, 0xed, 0x4b, 0x41, 0xdf, 0x31, 0x35,  0xdb, 0x4f, 0x51, 0xf7, 0x35, 0x2b, 0xe3, 0x41, 
+	 0x35, 0xed, 0x4f, 0x45, 0xc9, 0x43, 0x37, 0xbb,  0x47, 0x41, 0x61, 0x37, 0x31, 0x51, 0x5b, 0x4f, 
+	 0x49, 0x1f, 0x13, 0x0d, 0xff, 0xed, 0xff, 0xff,  0xeb, 0xff, 0xfb, 0xed, 0xff, 0xff, 0xf7, 0xff, 
+	 0xf3, 0xff, 0xed, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xf7,  0xf9, 0xfb, 0xff, 0xff, 0xff, 0xed, 0xff, 0xff, 
+	 0xed, 0xff, 0xff, 0xf9, 0xff, 0x57, 0x41, 0x4b,  0x55, 0x4d, 0x39, 0x4f, 0x47, 0x33, 0x39, 0x33, 
+	 0x5b, 0x3d, 0x37, 0x5f, 0x59, 0x45, 0xe1, 0x49,  0x35, 0xd3, 0x51, 0x3f, 0xff, 0x4b, 0x3b, 0xfb, 
+	 0x25, 0x29, 0xbf, 0x49, 0x4d, 0xe1, 0x3d, 0x35,  0xd5, 0x49, 0x41, 0xe1, 0x2b, 0x59, 0xb3, 0x9f, 
+	 0xcd, 0xff, 0x51, 0xe9, 0xff, 0x49, 0xe1, 0xfd,  0x00, 0xed, 0xf7, 0x0b, 0xff, 0xff, 0x00, 0xef, 
+	 0xf9, 0x00, 0xf1, 0xfb, 0x57, 0xef, 0xff, 0x5f,  0xf7, 0xff, 0x55, 0x81, 0xdd, 0x43, 0x6f, 0xcb, 
+	 0x25, 0x1d, 0xbd, 0x53, 0x4b, 0xeb, 0x37, 0x37,  0xdf, 0x39, 0x39, 0xe3, 0x47, 0x37, 0xf3, 0x49, 
+	 0x39, 0xf7, 0x65, 0x53, 0xdb, 0x5d, 0x4d, 0xd3,  0x2b, 0x23, 0x3f, 0x39, 0x31, 0x4d, 0x39, 0x2b, 
+	 0x23, 0x5d, 0x4d, 0x45, 0x5d, 0x3d, 0x5d, 0xff,  0xeb, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xf3, 0xff, 
+	 0xe1, 0xeb, 0xd9, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xfd,  0xff, 0xfd, 0xff, 0xff, 0xff, 0xed, 0xff, 0xff, 
+	 0xf5, 0xff, 0xef, 0xd9, 0xe3, 0x4f, 0x39, 0x43,  0x47, 0x3f, 0x2b, 0x49, 0x41, 0x2d, 0x2f, 0x29, 
+	 0x51, 0x3b, 0x35, 0x5d, 0x45, 0x33, 0xcf, 0x5f,  0x4b, 0xe7, 0x3d, 0x2d, 0xed, 0x3d, 0x2d, 0xed, 
+	 0x4d, 0x51, 0xe7, 0x3b, 0x41, 0xd5, 0x4d, 0x45,  0xe5, 0x43, 0x3d, 0xdd, 0x2f, 0x5d, 0xb7, 0x21, 
+	 0x51, 0xab, 0x45, 0xdd, 0xf9, 0x4b, 0xe3, 0xff,  0x09, 0xff, 0xff, 0x00, 0xed, 0xf7, 0x04, 0xf9, 
+	 0xff, 0x00, 0xf1, 0xfb, 0x43, 0xdb, 0xf7, 0x29,  0xc1, 0xdd, 0x27, 0x55, 0xaf, 0x39, 0x65, 0xc1, 
+	 0x4f, 0x47, 0xe7, 0x3d, 0x35, 0xd5, 0x41, 0x41,  0xe9, 0x3d, 0x3d, 0xe5, 0x45, 0x35, 0xf3, 0x3d, 
+	 0x2d, 0xeb, 0x4b, 0x39, 0xc1, 0x57, 0x45, 0xcd,  0x3f, 0x37, 0x51, 0x39, 0x31, 0x4b, 0x53, 0x45, 
+	 0x3d, 0x4b, 0x3b, 0x33, 0x51, 0x31, 0x51, 0xf7,  0xd7, 0xf9, 0xff, 0xed, 0xff, 0xff, 0xed, 0xff, 
+	 0xfb, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xf9,  0xff, 0xef, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 
+	 0xfb, 0xff, 0x85, 0x5d, 0x73, 0x63, 0x39, 0x4f,  0x61, 0x31, 0x4d, 0x5b, 0x2b, 0x47, 0x4f, 0x33, 
+	 0x55, 0x3f, 0x23, 0x45, 0x5f, 0x59, 0x85, 0x6d,  0x65, 0x93, 0x65, 0x65, 0x9d, 0x81, 0x81, 0xb9, 
+	 0x6f, 0x6b, 0xab, 0x7d, 0x79, 0xbb, 0x4d, 0x61,  0xc1, 0x4d, 0x5f, 0xc1, 0x57, 0x3f, 0xe9, 0x51, 
+	 0x39, 0xe3, 0x2b, 0x5b, 0xbf, 0x91, 0xc3, 0xff,  0x3d, 0xdb, 0xff, 0x43, 0xe1, 0xff, 0x4b, 0xe7, 
+	 0xff, 0x41, 0xdd, 0xff, 0x6d, 0x9d, 0xfd, 0x21,  0x53, 0xb1, 0x55, 0x3b, 0xdd, 0x53, 0x39, 0xdd, 
+	 0x59, 0x69, 0xc1, 0x5b, 0x6b, 0xc3, 0x63, 0x65,  0x99, 0x5d, 0x5d, 0x91, 0x77, 0x79, 0xa9, 0x79, 
+	 0x7b, 0xab, 0x6d, 0x67, 0x91, 0x49, 0x43, 0x6d,  0x51, 0x35, 0x59, 0x49, 0x2d, 0x51, 0x61, 0x31, 
+	 0x4f, 0x5b, 0x2b, 0x49, 0x67, 0x3d, 0x53, 0x73,  0x49, 0x5f, 0xff, 0xfb, 0xff, 0xff, 0xfb, 0xff, 
+	 0xe1, 0xf5, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff,  0xff, 0xe7, 0xf7, 0xff, 0xfb, 0xef, 0xfd, 0xf7, 
+	 0xe9, 0xf7, 0x5d, 0x33, 0x49, 0x4b, 0x23, 0x37,  0x5d, 0x2d, 0x49, 0x63, 0x33, 0x4f, 0x47, 0x2b, 
+	 0x4d, 0x4d, 0x31, 0x53, 0x55, 0x4d, 0x7b, 0x7d,  0x77, 0xa5, 0x1f, 0x1d, 0x55, 0xdb, 0xd9, 0xff, 
+	 0xd9, 0xd5, 0xff, 0xb7, 0xb3, 0xf5, 0x00, 0x06,  0x65, 0x57, 0x6b, 0xcb, 0x51, 0x39, 0xe5, 0x61, 
+	 0x47, 0xf3, 0x25, 0x57, 0xb9, 0x43, 0x73, 0xd7,  0x06, 0xa3, 0xcf, 0x39, 0xd7, 0xff, 0x41, 0xdd, 
+	 0xff, 0x00, 0x6d, 0x95, 0x45, 0x75, 0xd5, 0x39,  0x69, 0xc9, 0x53, 0x39, 0xdb, 0x6b, 0x4f, 0xf3, 
+	 0x09, 0x1b, 0x71, 0x7b, 0x8b, 0xe3, 0xed, 0xef,  0xff, 0xeb, 0xed, 0xff, 0xd1, 0xd3, 0xff, 0x02, 
+	 0x02, 0x31, 0x6b, 0x67, 0x8f, 0x45, 0x3f, 0x69,  0x45, 0x29, 0x4d, 0x3f, 0x23, 0x47, 0x55, 0x25, 
+	 0x43, 0x61, 0x31, 0x4f, 0x5b, 0x31, 0x47, 0x4b,  0x23, 0x37, 0xf7, 0xeb, 0xf5, 0xff, 0xf9, 0xff, 
+	 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xf9,  0xf9, 0xe9, 0xf7, 0xf7, 0xff, 0xfd, 0xff, 0xcb, 
+	 0xbd, 0xc3, 0x71, 0x4d, 0x5b, 0x57, 0x33, 0x41,  0x59, 0x31, 0x45, 0x51, 0x29, 0x3b, 0x3d, 0x25, 
+	 0x3d, 0x59, 0x41, 0x59, 0x1f, 0x17, 0x31, 0xd7,  0xcf, 0xe9, 0xfd, 0xf7, 0xff, 0xed, 0xe7, 0xff, 
+	 0xff, 0xf3, 0xff, 0xff, 0xf3, 0xff, 0xf7, 0xf9,  0xff, 0x4d, 0x4f, 0x69, 0x6f, 0x63, 0xd1, 0x59, 
+	 0x4d, 0xbb, 0x31, 0x3d, 0xb9, 0x3f, 0x4b, 0xc7,  0x45, 0x6f, 0xd7, 0x15, 0x43, 0xa9, 0x1f, 0x4b, 
+	 0xaf, 0x4f, 0x79, 0xdd, 0x3d, 0x49, 0xbd, 0x3f,  0x4b, 0xbf, 0x53, 0x45, 0xa7, 0x3f, 0x31, 0x93, 
+	 0xeb, 0xeb, 0xf7, 0xf3, 0xf3, 0xff, 0xfd, 0xf1,  0xff, 0xf5, 0xe9, 0xff, 0xf1, 0xed, 0xff, 0xe7, 
+	 0xe3, 0xfd, 0x9f, 0x99, 0xaf, 0x4f, 0x47, 0x5f,  0x41, 0x2b, 0x41, 0x53, 0x3b, 0x51, 0x53, 0x2b, 
+	 0x3f, 0x5b, 0x33, 0x45, 0x53, 0x2f, 0x3d, 0x55,  0x31, 0x3f, 0xf7, 0xe9, 0xef, 0xff, 0xf3, 0xf9, 
+	 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed, 0xfb,  0xfb, 0xf3, 0xff, 0xff, 0xff, 0xfd, 0xff, 0x41, 
+	 0x35, 0x3b, 0x65, 0x41, 0x4f, 0x53, 0x2f, 0x3d,  0x5b, 0x33, 0x47, 0x55, 0x2d, 0x3f, 0x55, 0x3d, 
+	 0x55, 0x55, 0x3d, 0x55, 0xd3, 0xcb, 0xe5, 0xff,  0xf7, 0xff, 0xe9, 0xe3, 0xff, 0xf7, 0xf1, 0xff, 
+	 0xdf, 0xd1, 0xf7, 0xeb, 0xdd, 0xff, 0xe3, 0xe5,  0xff, 0xf1, 0xf3, 0xff, 0x00, 0x00, 0x57, 0x6d, 
+	 0x61, 0xcf, 0x37, 0x43, 0xbf, 0x47, 0x53, 0xcf,  0x2f, 0x5b, 0xc1, 0x2d, 0x59, 0xbf, 0x37, 0x61, 
+	 0xc5, 0x21, 0x4d, 0xb1, 0x43, 0x4f, 0xc3, 0x47,  0x51, 0xc5, 0x7f, 0x73, 0xd5, 0x79, 0x6d, 0xcf, 
+	 0xf7, 0xf7, 0xff, 0xf9, 0xf9, 0xff, 0xe5, 0xd9,  0xf9, 0xf3, 0xe7, 0xff, 0xfd, 0xf7, 0xff, 0xf5, 
+	 0xef, 0xff, 0xfb, 0xf3, 0xff, 0x97, 0x91, 0xa7,  0x61, 0x49, 0x5f, 0x3d, 0x25, 0x3b, 0x5b, 0x33, 
+	 0x45, 0x59, 0x31, 0x43, 0x57, 0x33, 0x41, 0x67,  0x43, 0x51, 0xb7, 0xab, 0xb1, 0xff, 0xf5, 0xfb, 
+	 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff,  0xf9, 0xf7, 0xff, 0xf7, 0xff, 0xf9, 0xf7, 0x0f, 
+	 0x04, 0x02, 0x4f, 0x2f, 0x37, 0x4f, 0x2d, 0x35,  0x5b, 0x37, 0x45, 0x55, 0x33, 0x41, 0x4d, 0x3b, 
+	 0x45, 0x71, 0x5f, 0x69, 0xff, 0xfd, 0xff, 0xff,  0xf9, 0xff, 0xf7, 0xe3, 0xe3, 0x87, 0x71, 0x73, 
+	 0x99, 0x7b, 0x79, 0x73, 0x53, 0x53, 0xb1, 0x8b,  0x73, 0xff, 0xf9, 0xdf, 0x93, 0x93, 0xcd, 0x75, 
+	 0x75, 0xaf, 0x3d, 0x39, 0xd9, 0x3d, 0x39, 0xd9,  0x4d, 0x2d, 0xd9, 0x59, 0x39, 0xe7, 0x53, 0x35, 
+	 0xdf, 0x67, 0x47, 0xf1, 0x41, 0x3d, 0xd3, 0x41,  0x3f, 0xd3, 0x4b, 0x4b, 0x75, 0xe1, 0xe3, 0xff, 
+	 0xef, 0xcb, 0x9f, 0x9d, 0x7b, 0x4f, 0x7f, 0x5d,  0x63, 0x7f, 0x5d, 0x63, 0xa7, 0x91, 0x93, 0xf7, 
+	 0xe1, 0xe3, 0xff, 0xfd, 0xff, 0xff, 0xf3, 0xf7,  0x27, 0x17, 0x1b, 0x4b, 0x39, 0x3f, 0x55, 0x35, 
+	 0x3d, 0x59, 0x39, 0x41, 0x57, 0x37, 0x3f, 0x4f,  0x2f, 0x37, 0x39, 0x2d, 0x31, 0xff, 0xfd, 0xff, 
+	 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff,  0xf9, 0xe9, 0xf5, 0xeb, 0xff, 0xff, 0xfd, 0x5d, 
+	 0x51, 0x4f, 0x55, 0x35, 0x3d, 0x5b, 0x3b, 0x43,  0x59, 0x35, 0x43, 0x4d, 0x29, 0x37, 0x61, 0x4f, 
+	 0x59, 0xff, 0xfb, 0xff, 0xf1, 0xe3, 0xe9, 0xf5,  0xe7, 0xed, 0xff, 0xf3, 0xf5, 0xf5, 0xe1, 0xe1, 
+	 0x7d, 0x5f, 0x5d, 0x79, 0x5b, 0x59, 0x7d, 0x59,  0x41, 0xbb, 0x97, 0x7f, 0xd7, 0xd7, 0xff, 0x6b, 
+	 0x6b, 0xa5, 0x4f, 0x49, 0xe9, 0x4d, 0x47, 0xe9,  0x67, 0x47, 0xf5, 0x55, 0x37, 0xe3, 0x59, 0x3b, 
+	 0xe5, 0x53, 0x35, 0xdd, 0x45, 0x41, 0xd7, 0x4d,  0x49, 0xdd, 0x23, 0x23, 0x4d, 0xdd, 0xdf, 0xff, 
+	 0x9d, 0x79, 0x4d, 0x8b, 0x69, 0x3d, 0x7b, 0x59,  0x5f, 0x9b, 0x79, 0x7f, 0xff, 0xef, 0xf3, 0xff, 
+	 0xe9, 0xed, 0xfb, 0xef, 0xf3, 0xff, 0xf5, 0xf9,  0x9f, 0x8d, 0x91, 0x5f, 0x4d, 0x53, 0x59, 0x39, 
+	 0x41, 0x51, 0x2f, 0x37, 0x55, 0x33, 0x3b, 0x53,  0x31, 0x39, 0x0b, 0x00, 0x02, 0xff, 0xfd, 0xff, 
+	 0xf5, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff,  0xfb, 0xeb, 0xf1, 0xe9, 0xff, 0xfd, 0xfd, 0x73, 
+	 0x65, 0x65, 0x45, 0x23, 0x31, 0x53, 0x31, 0x3f,  0x53, 0x31, 0x43, 0x4f, 0x2d, 0x3f, 0x4d, 0x37, 
+	 0x43, 0xff, 0xfb, 0xff, 0xff, 0xfd, 0xfd, 0xff,  0xf9, 0xf9, 0xff, 0xf3, 0xe3, 0xff, 0xe9, 0xd9, 
+	 0xa7, 0x75, 0x5f, 0x99, 0x67, 0x51, 0xa5, 0x5f,  0x59, 0x97, 0x51, 0x4b, 0xd3, 0xcf, 0xfd, 0x63, 
+	 0x5f, 0x8d, 0x2f, 0x35, 0xdd, 0x2b, 0x31, 0xd9,  0x49, 0x41, 0xf1, 0x3b, 0x33, 0xe3, 0x4f, 0x49, 
+	 0xf3, 0x3f, 0x39, 0xe3, 0x41, 0x47, 0xe3, 0x4b,  0x4f, 0xeb, 0x47, 0x45, 0x5f, 0xa7, 0xa5, 0xbf, 
+	 0x9f, 0x5b, 0x3f, 0x95, 0x51, 0x33, 0x99, 0x61,  0x5b, 0xe5, 0xad, 0xa5, 0xff, 0xf7, 0xed, 0xf3, 
+	 0xcf, 0xc7, 0xff, 0xff, 0xfb, 0xff, 0xfb, 0xf7,  0xf3, 0xe1, 0xe1, 0x69, 0x57, 0x57, 0x57, 0x39, 
+	 0x41, 0x49, 0x29, 0x33, 0x53, 0x33, 0x41, 0x61,  0x3f, 0x4d, 0x37, 0x25, 0x31, 0xff, 0xfb, 0xff, 
+	 0xf5, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xf9,  0xf1, 0xf9, 0xff, 0xf7, 0xff, 0xfd, 0xfd, 0x5f, 
+	 0x51, 0x51, 0x53, 0x31, 0x3f, 0x59, 0x39, 0x47,  0x55, 0x33, 0x45, 0x53, 0x31, 0x43, 0x5d, 0x47, 
+	 0x53, 0xff, 0xf3, 0xfd, 0xff, 0xf3, 0xf1, 0xdd,  0xc9, 0xc9, 0xa1, 0x7f, 0x71, 0xa7, 0x85, 0x77, 
+	 0x93, 0x61, 0x4b, 0x89, 0x57, 0x41, 0x99, 0x53,  0x4d, 0x9f, 0x59, 0x53, 0xcd, 0xc7, 0xf7, 0x5b, 
+	 0x55, 0x85, 0x33, 0x39, 0xe1, 0x49, 0x4d, 0xf5,  0x3b, 0x33, 0xe3, 0x49, 0x41, 0xf1, 0x37, 0x31, 
+	 0xd9, 0x4b, 0x45, 0xef, 0x3d, 0x43, 0xdf, 0x3d,  0x43, 0xdf, 0x31, 0x2f, 0x49, 0x61, 0x5f, 0x79, 
+	 0xa5, 0x61, 0x45, 0xa9, 0x65, 0x47, 0x91, 0x59,  0x53, 0x8f, 0x57, 0x51, 0xab, 0x89, 0x7f, 0xa7, 
+	 0x85, 0x7b, 0xfb, 0xe9, 0xe3, 0xff, 0xf5, 0xef,  0xe1, 0xcd, 0xcf, 0x5f, 0x4d, 0x4f, 0x4b, 0x2b, 
+	 0x35, 0x55, 0x35, 0x3f, 0x59, 0x39, 0x47, 0x4b,  0x2b, 0x39, 0x51, 0x3f, 0x4b, 0xff, 0xfb, 0xff, 
+	 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff,  0xff, 0xf7, 0xfb, 0xf9, 0xff, 0xf1, 0xfd, 0x67, 
+	 0x55, 0x61, 0x4f, 0x2b, 0x41, 0x51, 0x2d, 0x43,  0x61, 0x3d, 0x55, 0x4d, 0x29, 0x41, 0x51, 0x39, 
+	 0x49, 0xa1, 0x87, 0x97, 0xff, 0xfb, 0xff, 0xe1,  0xc5, 0xc9, 0x7f, 0x51, 0x49, 0x8b, 0x5d, 0x55, 
+	 0xa1, 0x63, 0x53, 0x99, 0x5b, 0x4b, 0x8d, 0x4f,  0x63, 0x8d, 0x4f, 0x63, 0xd1, 0xb9, 0xdb, 0x75, 
+	 0x5b, 0x7d, 0x5d, 0x53, 0xc5, 0x53, 0x49, 0xbb,  0x3d, 0x4b, 0xab, 0x4d, 0x5b, 0xbd, 0x43, 0x51, 
+	 0xaf, 0x4f, 0x5d, 0xbb, 0x55, 0x4d, 0xb5, 0x51,  0x49, 0xb1, 0x65, 0x4d, 0x5f, 0x71, 0x59, 0x6b, 
+	 0x93, 0x55, 0x55, 0x95, 0x57, 0x57, 0x9f, 0x5d,  0x59, 0x8f, 0x4d, 0x47, 0x89, 0x5b, 0x57, 0x93, 
+	 0x65, 0x61, 0xff, 0xe5, 0xe7, 0xff, 0xf3, 0xf5,  0x3f, 0x27, 0x31, 0x51, 0x3b, 0x45, 0x51, 0x2f, 
+	 0x41, 0x59, 0x37, 0x49, 0x53, 0x31, 0x45, 0x51,  0x2f, 0x43, 0x4d, 0x39, 0x4d, 0xff, 0xf5, 0xff, 
+	 0xf9, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xfd,  0xfd, 0xf9, 0xfd, 0xfd, 0xff, 0xf7, 0xff, 0x75, 
+	 0x63, 0x6d, 0x53, 0x2f, 0x45, 0x4f, 0x2b, 0x41,  0x4d, 0x29, 0x41, 0x51, 0x2d, 0x45, 0x5b, 0x43, 
+	 0x53, 0x51, 0x37, 0x47, 0xff, 0xef, 0xf3, 0xff,  0xe7, 0xeb, 0x99, 0x6d, 0x65, 0x81, 0x53, 0x4b, 
+	 0x93, 0x55, 0x45, 0x9f, 0x61, 0x51, 0x8d, 0x4f,  0x63, 0x8b, 0x4d, 0x61, 0x8d, 0x75, 0x97, 0x55, 
+	 0x3b, 0x5d, 0x33, 0x29, 0x9b, 0x31, 0x27, 0x99,  0x27, 0x35, 0x95, 0x2d, 0x3b, 0x9d, 0x2d, 0x3b, 
+	 0x99, 0x2b, 0x39, 0x97, 0x2f, 0x27, 0x8f, 0x31,  0x29, 0x91, 0x5f, 0x47, 0x59, 0x73, 0x5b, 0x6d, 
+	 0x99, 0x5b, 0x5b, 0x91, 0x53, 0x53, 0x91, 0x4f,  0x49, 0xa3, 0x61, 0x5b, 0x91, 0x63, 0x5f, 0x9b, 
+	 0x6d, 0x69, 0xff, 0xe5, 0xe7, 0xc9, 0xad, 0xaf,  0x65, 0x4f, 0x59, 0x51, 0x39, 0x43, 0x57, 0x35, 
+	 0x47, 0x4f, 0x2d, 0x3f, 0x55, 0x33, 0x47, 0x57,  0x33, 0x49, 0x53, 0x3f, 0x53, 0xff, 0xf7, 0xff, 
+	 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff,  0xff, 0xf7, 0xfd, 0xff, 0xff, 0xf9, 0xff, 0x55, 
+	 0x45, 0x53, 0x57, 0x31, 0x47, 0x51, 0x2b, 0x41,  0x51, 0x2b, 0x43, 0x55, 0x2f, 0x47, 0x3b, 0x1b, 
+	 0x31, 0x61, 0x43, 0x57, 0x61, 0x43, 0x51, 0xff,  0xf3, 0xff, 0xa7, 0x79, 0x7f, 0x77, 0x49, 0x4f, 
+	 0x9f, 0x5f, 0x63, 0x93, 0x53, 0x57, 0x79, 0x57,  0x65, 0x77, 0x55, 0x63, 0x69, 0x3b, 0x49, 0x5d, 
+	 0x2f, 0x3d, 0x53, 0x23, 0x47, 0x55, 0x25, 0x49,  0x4f, 0x39, 0x4d, 0x49, 0x35, 0x47, 0x4f, 0x3b, 
+	 0x4b, 0x47, 0x33, 0x43, 0x57, 0x27, 0x45, 0x55,  0x25, 0x43, 0x75, 0x45, 0x4b, 0x87, 0x57, 0x5d, 
+	 0x85, 0x63, 0x67, 0x7d, 0x59, 0x5d, 0xad, 0x6f,  0x71, 0x81, 0x41, 0x45, 0x8d, 0x5f, 0x65, 0xf1, 
+	 0xc3, 0xc9, 0xf7, 0xd9, 0xe3, 0x61, 0x45, 0x4f,  0x49, 0x2b, 0x3f, 0x4f, 0x31, 0x45, 0x55, 0x2f, 
+	 0x47, 0x53, 0x2d, 0x45, 0x55, 0x2d, 0x47, 0x55,  0x2f, 0x49, 0x31, 0x1f, 0x31, 0xff, 0xf7, 0xff, 
+	 0xf3, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff,  0xff, 0xf1, 0xf7, 0xff, 0xff, 0xf9, 0xff, 0x25, 
+	 0x13, 0x23, 0x55, 0x2f, 0x45, 0x51, 0x2b, 0x41,  0x63, 0x3d, 0x55, 0x4d, 0x27, 0x3f, 0x65, 0x45, 
+	 0x5b, 0x41, 0x23, 0x37, 0x6b, 0x4d, 0x59, 0x3d,  0x1f, 0x2b, 0xff, 0xdb, 0xdf, 0x95, 0x67, 0x6d, 
+	 0x95, 0x55, 0x59, 0x9f, 0x5f, 0x63, 0x75, 0x55,  0x63, 0x71, 0x51, 0x5f, 0x5b, 0x2d, 0x3b, 0x65, 
+	 0x37, 0x45, 0x59, 0x29, 0x4d, 0x57, 0x27, 0x4b,  0x4b, 0x35, 0x49, 0x43, 0x2f, 0x41, 0x45, 0x31, 
+	 0x41, 0x43, 0x2f, 0x41, 0x61, 0x31, 0x4f, 0x55,  0x25, 0x43, 0x6f, 0x3f, 0x45, 0x73, 0x43, 0x49, 
+	 0x7d, 0x59, 0x5d, 0x7d, 0x5b, 0x5f, 0x89, 0x49,  0x4d, 0x9f, 0x5f, 0x63, 0xb3, 0x85, 0x8b, 0xed, 
+	 0xbf, 0xc3, 0x33, 0x15, 0x21, 0x55, 0x39, 0x43,  0x4f, 0x31, 0x45, 0x4f, 0x31, 0x45, 0x4f, 0x29, 
+	 0x41, 0x5f, 0x39, 0x51, 0x55, 0x2d, 0x47, 0x53,  0x2b, 0x45, 0x19, 0x07, 0x19, 0xff, 0xf3, 0xff, 
+	 0xef, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xfd,  0xff, 0xe7, 0xf3, 0xfb, 0xff, 0xfb, 0xff, 0x3d, 
+	 0x31, 0x3d, 0x57, 0x33, 0x43, 0x51, 0x2d, 0x3d,  0x65, 0x3b, 0x4d, 0x53, 0x29, 0x39, 0x3d, 0x1f, 
+	 0x2d, 0x59, 0x3b, 0x49, 0x43, 0x29, 0x37, 0x6d,  0x51, 0x5f, 0x49, 0x23, 0x37, 0x57, 0x31, 0x45, 
+	 0x77, 0x41, 0x57, 0x83, 0x4d, 0x63, 0x61, 0x49,  0x4b, 0x55, 0x3d, 0x3f, 0x69, 0x35, 0x45, 0x67, 
+	 0x33, 0x43, 0x6d, 0x39, 0x39, 0x67, 0x33, 0x31,  0x5b, 0x2f, 0x3d, 0x5d, 0x31, 0x3f, 0x5b, 0x2d, 
+	 0x3b, 0x5d, 0x2f, 0x3d, 0x75, 0x3d, 0x3d, 0x65,  0x2d, 0x2d, 0x69, 0x33, 0x43, 0x63, 0x2d, 0x3d, 
+	 0x63, 0x45, 0x49, 0x65, 0x47, 0x4b, 0x91, 0x61,  0x69, 0x49, 0x17, 0x1f, 0x6d, 0x4b, 0x55, 0x6d, 
+	 0x4b, 0x55, 0x49, 0x2d, 0x3d, 0x49, 0x2d, 0x3f,  0x61, 0x41, 0x55, 0x49, 0x29, 0x3d, 0x5d, 0x31, 
+	 0x47, 0x5f, 0x33, 0x49, 0x5b, 0x35, 0x49, 0x5d,  0x37, 0x4b, 0x57, 0x4d, 0x55, 0xff, 0xf9, 0xff, 
+	 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xfb,  0xff, 0xed, 0xf9, 0xff, 0xff, 0xfb, 0xff, 0xa9, 
+	 0x9d, 0xa9, 0x65, 0x3f, 0x4f, 0x57, 0x33, 0x43,  0x53, 0x29, 0x3b, 0x5f, 0x35, 0x47, 0x57, 0x39, 
+	 0x47, 0x5d, 0x3d, 0x4d, 0x53, 0x37, 0x45, 0x47,  0x2d, 0x3b, 0x5d, 0x37, 0x4b, 0x5b, 0x35, 0x49, 
+	 0x6b, 0x37, 0x4b, 0x6f, 0x39, 0x4f, 0x53, 0x3b,  0x3d, 0x45, 0x2d, 0x2f, 0x6d, 0x3b, 0x49, 0x5d, 
+	 0x2b, 0x39, 0x6b, 0x37, 0x35, 0x63, 0x2f, 0x2f,  0x57, 0x2b, 0x39, 0x61, 0x35, 0x43, 0x61, 0x33, 
+	 0x41, 0x5d, 0x2f, 0x3d, 0x6b, 0x33, 0x33, 0x67,  0x2f, 0x2f, 0x67, 0x31, 0x41, 0x65, 0x2d, 0x3d, 
+	 0x55, 0x37, 0x3b, 0x51, 0x35, 0x37, 0x5d, 0x2b,  0x33, 0x69, 0x37, 0x3f, 0x4f, 0x2d, 0x37, 0x5b, 
+	 0x37, 0x41, 0x53, 0x37, 0x47, 0x51, 0x35, 0x45,  0x4d, 0x2b, 0x41, 0x55, 0x33, 0x49, 0x63, 0x37, 
+	 0x4d, 0x49, 0x1d, 0x35, 0x59, 0x33, 0x47, 0x67,  0x41, 0x53, 0xcd, 0xc1, 0xc9, 0xff, 0xfb, 0xff, 
+	 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff,  0xff, 0xef, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xf5, 
+	 0xed, 0xf3, 0x6b, 0x49, 0x4f, 0x5b, 0x39, 0x3f,  0x55, 0x2b, 0x33, 0x65, 0x3b, 0x43, 0x55, 0x37, 
+	 0x3f, 0x47, 0x29, 0x2f, 0x4b, 0x33, 0x41, 0x4b,  0x33, 0x41, 0x49, 0x2b, 0x41, 0x53, 0x35, 0x4b, 
+	 0x55, 0x29, 0x49, 0x57, 0x2b, 0x49, 0x5b, 0x37,  0x39, 0x55, 0x2f, 0x33, 0x5d, 0x31, 0x51, 0x53, 
+	 0x27, 0x47, 0x4f, 0x35, 0x3d, 0x4b, 0x31, 0x39,  0x45, 0x25, 0x57, 0x4b, 0x29, 0x5d, 0x4d, 0x29, 
+	 0x5f, 0x4b, 0x27, 0x5d, 0x4d, 0x2d, 0x39, 0x53,  0x33, 0x3f, 0x5b, 0x27, 0x4f, 0x61, 0x2d, 0x55, 
+	 0x5f, 0x31, 0x3d, 0x5d, 0x2f, 0x3b, 0x63, 0x3f,  0x47, 0x6d, 0x47, 0x51, 0x45, 0x2b, 0x35, 0x39, 
+	 0x1f, 0x29, 0x59, 0x41, 0x51, 0x47, 0x2f, 0x3f,  0x51, 0x2d, 0x41, 0x57, 0x35, 0x49, 0x5d, 0x2f, 
+	 0x43, 0x53, 0x25, 0x39, 0x53, 0x31, 0x3b, 0x67,  0x43, 0x4d, 0xff, 0xfd, 0xf9, 0xff, 0xfd, 0xfb, 
+	 0xf1, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff,  0xff, 0xe9, 0xfb, 0xfd, 0xfd, 0xf5, 0xfb, 0xfb, 
+	 0xf3, 0xf7, 0x63, 0x41, 0x47, 0x55, 0x33, 0x39,  0x5f, 0x35, 0x3d, 0x59, 0x2f, 0x35, 0x4f, 0x31, 
+	 0x37, 0x5f, 0x41, 0x47, 0x3f, 0x27, 0x35, 0x57,  0x3d, 0x4b, 0x4d, 0x2f, 0x45, 0x4b, 0x2d, 0x43, 
+	 0x61, 0x35, 0x53, 0x57, 0x2b, 0x49, 0x5b, 0x37,  0x39, 0x5f, 0x3b, 0x3d, 0x55, 0x29, 0x49, 0x5b, 
+	 0x2f, 0x4d, 0x51, 0x37, 0x3d, 0x4f, 0x35, 0x3d,  0x49, 0x29, 0x5b, 0x43, 0x21, 0x55, 0x49, 0x25, 
+	 0x59, 0x4d, 0x29, 0x5f, 0x4f, 0x2f, 0x3b, 0x59,  0x39, 0x45, 0x55, 0x21, 0x49, 0x5f, 0x2b, 0x53, 
+	 0x5d, 0x2f, 0x3b, 0x65, 0x37, 0x43, 0x51, 0x2b,  0x35, 0x49, 0x23, 0x2d, 0x5b, 0x3f, 0x4b, 0x55, 
+	 0x3b, 0x45, 0x4f, 0x35, 0x45, 0x47, 0x2d, 0x3d,  0x4d, 0x29, 0x3d, 0x55, 0x31, 0x45, 0x53, 0x25, 
+	 0x39, 0x75, 0x47, 0x5b, 0x51, 0x2f, 0x39, 0x63,  0x41, 0x4b, 0xf7, 0xf1, 0xef, 0xff, 0xff, 0xfd, 
+	 0xf1, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb,  0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xc7, 0xc1, 0xc5, 0x49, 0x43, 0x47,  0x4f, 0x3f, 0x49, 0x3d, 0x2d, 0x37, 0x53, 0x33, 
+	 0x43, 0x4d, 0x2f, 0x3d, 0x53, 0x2b, 0x3f, 0x5b,  0x33, 0x45, 0x5d, 0x35, 0x49, 0x5b, 0x31, 0x47, 
+	 0x53, 0x31, 0x45, 0x53, 0x2f, 0x45, 0x55, 0x31,  0x43, 0x55, 0x31, 0x43, 0x55, 0x31, 0x43, 0x55, 
+	 0x31, 0x43, 0x55, 0x31, 0x43, 0x55, 0x31, 0x43,  0x55, 0x31, 0x43, 0x55, 0x31, 0x43, 0x55, 0x31, 
+	 0x43, 0x55, 0x31, 0x43, 0x55, 0x31, 0x43, 0x55,  0x31, 0x43, 0x55, 0x31, 0x43, 0x55, 0x31, 0x43, 
+	 0x55, 0x31, 0x43, 0x55, 0x31, 0x43, 0x4d, 0x29,  0x3f, 0x5b, 0x39, 0x4d, 0x5f, 0x35, 0x4b, 0x4f, 
+	 0x27, 0x3b, 0x5f, 0x31, 0x45, 0x55, 0x27, 0x3b,  0x61, 0x35, 0x45, 0x59, 0x2d, 0x3d, 0x55, 0x31, 
+	 0x3f, 0x59, 0x35, 0x41, 0x51, 0x43, 0x49, 0xcb,  0xbd, 0xc3, 0xf3, 0xf9, 0xf9, 0xf5, 0xfb, 0xfd, 
+	 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd,  0xff, 0xff, 0xf5, 0xf9, 0xff, 0xff, 0xff, 0xfb, 
+	 0xf3, 0xf7, 0xfd, 0xf7, 0xfb, 0x43, 0x3d, 0x41,  0x45, 0x35, 0x3f, 0x4d, 0x3f, 0x47, 0x5b, 0x3d, 
+	 0x4b, 0x5d, 0x3d, 0x4d, 0x4d, 0x25, 0x39, 0x49,  0x21, 0x35, 0x59, 0x2f, 0x45, 0x53, 0x29, 0x3f, 
+	 0x49, 0x27, 0x3b, 0x57, 0x33, 0x49, 0x55, 0x31,  0x43, 0x55, 0x31, 0x43, 0x55, 0x31, 0x43, 0x55, 
+	 0x31, 0x43, 0x55, 0x31, 0x43, 0x55, 0x31, 0x43,  0x55, 0x31, 0x43, 0x55, 0x31, 0x43, 0x55, 0x31, 
+	 0x43, 0x55, 0x31, 0x43, 0x55, 0x31, 0x43, 0x55,  0x31, 0x43, 0x55, 0x31, 0x43, 0x55, 0x31, 0x43, 
+	 0x55, 0x31, 0x43, 0x55, 0x31, 0x43, 0x4f, 0x2b,  0x41, 0x53, 0x31, 0x45, 0x51, 0x29, 0x3d, 0x61, 
+	 0x37, 0x4d, 0x5f, 0x31, 0x45, 0x57, 0x29, 0x3d,  0x59, 0x2d, 0x3d, 0x65, 0x39, 0x49, 0x57, 0x33, 
+	 0x3f, 0x5b, 0x37, 0x45, 0x45, 0x37, 0x3d, 0xff,  0xf5, 0xfb, 0xfb, 0xff, 0xff, 0xfb, 0xff, 0xff, 
+	 0xd9, 0xed, 0xeb, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9,  0xfd, 0xff, 0xfd, 0xff, 0xe9, 0xe7, 0xe9, 0xff, 
+	 0xff, 0xff, 0xf7, 0xf5, 0xf9, 0xd7, 0xd3, 0xd7,  0x5d, 0x51, 0x59, 0x43, 0x37, 0x3f, 0x35, 0x15, 
+	 0x25, 0x5d, 0x3d, 0x4d, 0x5d, 0x35, 0x47, 0x5d,  0x35, 0x49, 0x59, 0x2f, 0x45, 0x53, 0x2b, 0x3f, 
+	 0x61, 0x3f, 0x53, 0x4f, 0x2d, 0x41, 0x55, 0x2f,  0x43, 0x55, 0x2f, 0x43, 0x55, 0x2f, 0x43, 0x55, 
+	 0x2f, 0x43, 0x55, 0x2f, 0x43, 0x55, 0x2f, 0x43,  0x55, 0x2f, 0x43, 0x55, 0x2f, 0x43, 0x55, 0x2f, 
+	 0x43, 0x55, 0x2f, 0x43, 0x55, 0x2f, 0x43, 0x55,  0x2f, 0x43, 0x55, 0x2f, 0x43, 0x55, 0x2f, 0x43, 
+	 0x55, 0x2f, 0x43, 0x55, 0x2f, 0x43, 0x5b, 0x35,  0x49, 0x51, 0x2b, 0x3f, 0x5b, 0x31, 0x47, 0x49, 
+	 0x1f, 0x35, 0x5b, 0x33, 0x45, 0x5f, 0x37, 0x4b,  0x5f, 0x3b, 0x4b, 0x4b, 0x27, 0x37, 0x4b, 0x31, 
+	 0x3d, 0x7b, 0x61, 0x6b, 0xb7, 0xab, 0xb1, 0xff,  0xfb, 0xff, 0xeb, 0xef, 0xf1, 0xf9, 0xfd, 0xfd, 
+	 0xed, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9,  0xfd, 0xff, 0xf7, 0xfb, 0xff, 0xff, 0xff, 0xff, 
+	 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff,  0x4d, 0x41, 0x49, 0x4d, 0x41, 0x49, 0x77, 0x57, 
+	 0x67, 0x3b, 0x1b, 0x2b, 0x5f, 0x37, 0x49, 0x59,  0x31, 0x45, 0x55, 0x2b, 0x41, 0x63, 0x39, 0x4f, 
+	 0x3f, 0x1b, 0x2f, 0x59, 0x35, 0x49, 0x55, 0x2f,  0x43, 0x55, 0x2f, 0x43, 0x55, 0x2f, 0x43, 0x55, 
+	 0x2f, 0x43, 0x55, 0x2f, 0x43, 0x55, 0x2f, 0x43,  0x55, 0x2f, 0x43, 0x55, 0x2f, 0x43, 0x55, 0x2f, 
+	 0x43, 0x55, 0x2f, 0x43, 0x55, 0x2f, 0x43, 0x55,  0x2f, 0x43, 0x55, 0x2f, 0x43, 0x55, 0x2f, 0x43, 
+	 0x55, 0x2f, 0x43, 0x55, 0x2f, 0x43, 0x59, 0x33,  0x47, 0x53, 0x2d, 0x41, 0x55, 0x2d, 0x41, 0x6f, 
+	 0x47, 0x5b, 0x47, 0x1f, 0x33, 0x53, 0x2b, 0x3d,  0x59, 0x35, 0x45, 0x5d, 0x39, 0x49, 0x53, 0x39, 
+	 0x45, 0x41, 0x27, 0x31, 0xff, 0xf3, 0xf9, 0xff,  0xfd, 0xff, 0xf9, 0xfd, 0xff, 0xfd, 0xff, 0xff, 
+	 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xfd, 0xf9, 0xfb, 0xf5, 0xf5, 0xf7, 0xfb, 
+	 0xfb, 0xfd, 0xef, 0xef, 0xf3, 0xf3, 0xf3, 0xf7,  0xff, 0xfd, 0xff, 0x31, 0x27, 0x2f, 0x55, 0x39, 
+	 0x45, 0x45, 0x29, 0x37, 0x5d, 0x35, 0x45, 0x61,  0x3b, 0x4b, 0x49, 0x23, 0x37, 0x4f, 0x29, 0x3d, 
+	 0x5b, 0x39, 0x4b, 0x4f, 0x2d, 0x3f, 0x57, 0x2f,  0x45, 0x57, 0x2f, 0x45, 0x57, 0x2f, 0x45, 0x57, 
+	 0x2f, 0x45, 0x57, 0x2f, 0x45, 0x57, 0x2f, 0x45,  0x57, 0x2f, 0x45, 0x57, 0x2f, 0x45, 0x57, 0x2f, 
+	 0x45, 0x57, 0x2f, 0x45, 0x57, 0x2f, 0x45, 0x57,  0x2f, 0x45, 0x57, 0x2f, 0x45, 0x57, 0x2f, 0x45, 
+	 0x57, 0x2f, 0x45, 0x57, 0x2f, 0x45, 0x57, 0x2d,  0x41, 0x57, 0x2d, 0x41, 0x61, 0x3b, 0x4f, 0x49, 
+	 0x23, 0x37, 0x4f, 0x2f, 0x3f, 0x63, 0x43, 0x53,  0x43, 0x2d, 0x39, 0x47, 0x31, 0x3d, 0x2d, 0x21, 
+	 0x29, 0xf7, 0xeb, 0xf3, 0xff, 0xf9, 0xfd, 0xf7,  0xf1, 0xf7, 0xff, 0xff, 0xff, 0xed, 0xed, 0xef, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xf3,  0xf5, 0xff, 0xff, 0xff, 0xf9, 0xf9, 0xfb, 0xff, 
+	 0xff, 0xff, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff,  0xfb, 0xf1, 0xf9, 0xf7, 0xeb, 0xf3, 0x37, 0x1b, 
+	 0x29, 0x65, 0x49, 0x55, 0x51, 0x2b, 0x3b, 0x4f,  0x29, 0x39, 0x69, 0x43, 0x57, 0x59, 0x33, 0x47, 
+	 0x4f, 0x2d, 0x3f, 0x59, 0x37, 0x49, 0x57, 0x2f,  0x45, 0x57, 0x2f, 0x45, 0x57, 0x2f, 0x45, 0x57, 
+	 0x2f, 0x45, 0x57, 0x2f, 0x45, 0x57, 0x2f, 0x45,  0x57, 0x2f, 0x45, 0x57, 0x2f, 0x45, 0x57, 0x2f, 
+	 0x45, 0x57, 0x2f, 0x45, 0x57, 0x2f, 0x45, 0x57,  0x2f, 0x45, 0x57, 0x2f, 0x45, 0x57, 0x2f, 0x45, 
+	 0x57, 0x2f, 0x45, 0x57, 0x2f, 0x45, 0x5d, 0x33,  0x45, 0x59, 0x2f, 0x41, 0x4b, 0x25, 0x39, 0x59, 
+	 0x33, 0x45, 0x47, 0x27, 0x37, 0x4f, 0x2f, 0x3f,  0x57, 0x41, 0x4d, 0x4b, 0x35, 0x41, 0xef, 0xe3, 
+	 0xeb, 0xff, 0xfd, 0xff, 0xf9, 0xf3, 0xf9, 0xff,  0xfd, 0xff, 0xf7, 0xf7, 0xf9, 0xfd, 0xfd, 0xff, 
+	 0xf5, 0xf7, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xf7, 0xfb, 0xfd, 0xef, 
+	 0xf3, 0xf5, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff,  0xff, 0xfb, 0xff, 0xfd, 0xf7, 0xff, 0xff, 0xed, 
+	 0xf7, 0x2b, 0x13, 0x1d, 0x59, 0x35, 0x43, 0x63,  0x3f, 0x4d, 0x3f, 0x1b, 0x2b, 0x69, 0x45, 0x55, 
+	 0x45, 0x29, 0x37, 0x4b, 0x2f, 0x3d, 0x55, 0x2f,  0x45, 0x55, 0x2f, 0x45, 0x55, 0x2f, 0x45, 0x55, 
+	 0x2f, 0x45, 0x55, 0x2f, 0x45, 0x55, 0x2f, 0x45,  0x55, 0x2f, 0x45, 0x55, 0x2f, 0x45, 0x55, 0x2f, 
+	 0x45, 0x55, 0x2f, 0x45, 0x55, 0x2f, 0x45, 0x55,  0x2f, 0x45, 0x55, 0x2f, 0x45, 0x55, 0x2f, 0x45, 
+	 0x55, 0x2f, 0x45, 0x55, 0x2f, 0x45, 0x51, 0x29,  0x39, 0x59, 0x31, 0x41, 0x57, 0x37, 0x47, 0x59, 
+	 0x3b, 0x49, 0x45, 0x31, 0x3d, 0x61, 0x4f, 0x59,  0x04, 0x00, 0x06, 0xf5, 0xef, 0xf7, 0xe5, 0xe5, 
+	 0xeb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb,  0xfb, 0xff, 0xff, 0xf9, 0xfd, 0xff, 0xf9, 0xff, 
+	 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xf5, 0xf5, 0xf7, 0xed, 0xf1, 0xf3, 0xfd, 
+	 0xff, 0xff, 0xf7, 0xfb, 0xfd, 0xef, 0xf1, 0xf5,  0xff, 0xfd, 0xff, 0xf5, 0xef, 0xf5, 0xff, 0xef, 
+	 0xf9, 0xbf, 0xa7, 0xb1, 0x6d, 0x49, 0x57, 0x4f,  0x2b, 0x39, 0x59, 0x35, 0x45, 0x55, 0x31, 0x41, 
+	 0x4d, 0x31, 0x3f, 0x53, 0x37, 0x45, 0x55, 0x2f,  0x45, 0x55, 0x2f, 0x45, 0x55, 0x2f, 0x45, 0x55, 
+	 0x2f, 0x45, 0x55, 0x2f, 0x45, 0x55, 0x2f, 0x45,  0x55, 0x2f, 0x45, 0x55, 0x2f, 0x45, 0x55, 0x2f, 
+	 0x45, 0x55, 0x2f, 0x45, 0x55, 0x2f, 0x45, 0x55,  0x2f, 0x45, 0x55, 0x2f, 0x45, 0x55, 0x2f, 0x45, 
+	 0x55, 0x2f, 0x45, 0x55, 0x2f, 0x45, 0x5d, 0x35,  0x45, 0x51, 0x2b, 0x3b, 0x51, 0x31, 0x41, 0x57, 
+	 0x39, 0x47, 0x55, 0x41, 0x4d, 0x37, 0x25, 0x2f,  0xff, 0xfd, 0xff, 0xed, 0xe7, 0xed, 0xf3, 0xf3, 
+	 0xf9, 0xff, 0xff, 0xff, 0xf1, 0xf1, 0xf5, 0xff,  0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfb, 0xff, 
+	 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfb,  0xff, 0xfb, 0xfb, 0xff, 0xf9, 0xfb, 0xff, 0xf9, 
+	 0xfb, 0xff, 0xf7, 0xfd, 0xff, 0xf7, 0xfd, 0xff,  0xfd, 0xfb, 0xff, 0xfb, 0xf9, 0xfd, 0xf3, 0xdf, 
+	 0xe9, 0x55, 0x41, 0x4b, 0x51, 0x37, 0x41, 0x53,  0x39, 0x43, 0x49, 0x2f, 0x39, 0x4b, 0x31, 0x3b, 
+	 0x4f, 0x39, 0x43, 0x4b, 0x35, 0x3f, 0x51, 0x31,  0x43, 0x51, 0x31, 0x43, 0x51, 0x31, 0x43, 0x51, 
+	 0x31, 0x43, 0x51, 0x31, 0x45, 0x51, 0x31, 0x45,  0x51, 0x31, 0x45, 0x51, 0x31, 0x45, 0x4f, 0x2f, 
+	 0x43, 0x4d, 0x2d, 0x41, 0x4d, 0x2d, 0x41, 0x51,  0x31, 0x43, 0x53, 0x33, 0x47, 0x55, 0x35, 0x47, 
+	 0x51, 0x31, 0x43, 0x4d, 0x2d, 0x41, 0x4f, 0x31,  0x3d, 0x5d, 0x3f, 0x4b, 0x61, 0x4d, 0x57, 0x13, 
+	 0x00, 0x07, 0xb3, 0xa9, 0xb1, 0xf9, 0xef, 0xf7,  0xe9, 0xeb, 0xf1, 0xfb, 0xfd, 0xff, 0xfb, 0xff, 
+	 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 
+	 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xfd, 
+	 0xff, 0xff, 0xfb, 0xff, 0xff, 0xfb, 0xff, 0xff,  0xff, 0xfd, 0xff, 0xff, 0xfb, 0xff, 0x61, 0x4d, 
+	 0x57, 0x5d, 0x49, 0x53, 0x53, 0x39, 0x43, 0x49,  0x2d, 0x39, 0x55, 0x3b, 0x47, 0x5f, 0x45, 0x4f, 
+	 0x41, 0x2b, 0x35, 0x69, 0x53, 0x5d, 0x65, 0x45,  0x57, 0x5d, 0x3d, 0x51, 0x55, 0x35, 0x47, 0x4f, 
+	 0x2f, 0x43, 0x51, 0x31, 0x43, 0x51, 0x31, 0x43,  0x4f, 0x2f, 0x43, 0x4d, 0x2d, 0x3f, 0x4b, 0x2b, 
+	 0x3f, 0x53, 0x33, 0x45, 0x57, 0x37, 0x49, 0x51,  0x31, 0x45, 0x49, 0x29, 0x3b, 0x49, 0x29, 0x3b, 
+	 0x55, 0x35, 0x49, 0x63, 0x43, 0x55, 0x69, 0x4d,  0x57, 0x27, 0x09, 0x15, 0xbf, 0xa9, 0xb3, 0xff, 
+	 0xfb, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xf9, 0xff,  0xfd, 0xff, 0xff, 0xed, 0xef, 0xf5, 0xfb, 0xff, 
+	 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 
+	 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd,  0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xfb, 0xff, 0xff, 0xfb, 0xff, 0xff,  0xff, 0xff, 0xff, 0xfd, 0xfd, 0xff, 0x3b, 0x2d, 
+	 0x33, 0x55, 0x47, 0x4d, 0x47, 0x33, 0x39, 0x47,  0x33, 0x39, 0x5f, 0x4f, 0x55, 0x53, 0x41, 0x49, 
+	 0xc9, 0xbf, 0xc3, 0xdf, 0xd5, 0xdb, 0x5f, 0x4d,  0x59, 0x55, 0x41, 0x4f, 0x49, 0x37, 0x43, 0x47, 
+	 0x35, 0x41, 0x4d, 0x3b, 0x47, 0x55, 0x43, 0x4f,  0x59, 0x45, 0x53, 0x57, 0x45, 0x51, 0x4d, 0x3b, 
+	 0x47, 0x57, 0x45, 0x51, 0x5d, 0x4b, 0x57, 0x59,  0x45, 0x53, 0x4f, 0x3d, 0x49, 0x51, 0x3d, 0x4b, 
+	 0x5f, 0x4d, 0x59, 0x6f, 0x5b, 0x69, 0xff, 0xf3,  0xf9, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff, 
+	 0xf5, 0xf9, 0xf9, 0xf5, 0xf9, 0xfd, 0xfb, 0xff,  0xef, 0xf1, 0xf5, 0xfd, 0xff, 0xff, 0xfb, 0xff, 
+	 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd,  0xff, 0xff, 0xfd, 0xff, 0xfd, 0xfd, 0xff, 0xfd, 
+	 0xfd, 0xff, 0xfb, 0xff, 0xff, 0xf9, 0xff, 0xff,  0xfd, 0xfd, 0xff, 0xfb, 0xfb, 0xff, 0x77, 0x69, 
+	 0x6f, 0x4d, 0x3f, 0x45, 0x3f, 0x2b, 0x31, 0x49,  0x35, 0x3d, 0xc5, 0xb5, 0xbb, 0xf1, 0xe1, 0xe7, 
+	 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfb,  0xff, 0xff, 0xfb, 0xff, 0xff, 0xf7, 0xff, 0xff, 
+	 0xed, 0xf9, 0xe7, 0xd5, 0xe3, 0xc5, 0xb3, 0xc1,  0x9f, 0x8d, 0x9b, 0x87, 0x73, 0x81, 0x9f, 0x8d, 
+	 0x99, 0xa9, 0x97, 0xa5, 0xbb, 0xa9, 0xb7, 0xd1,  0xbf, 0xcb, 0xe7, 0xd5, 0xe1, 0xf9, 0xe7, 0xf5, 
+	 0xff, 0xf5, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xf7,  0xfd, 0xff, 0xf9, 0xff, 0xff, 0xf5, 0xf9, 0xff, 
+	 0xfd, 0xff, 0xfd, 0xfb, 0xff, 0xff, 0xff, 0xff,  0xfd, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xfb, 0xff, 
+	 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd,  0xff, 0xff, 0xfb, 0xff, 0xfd, 0xfb, 0xff, 0xfd, 
+	 0xfd, 0xff, 0xfb, 0xff, 0xff, 0xfb, 0xff, 0xff,  0xfd, 0xfb, 0xff, 0xfb, 0xf9, 0xfd, 0xdf, 0xd5, 
+	 0xd9, 0x6d, 0x63, 0x67, 0x41, 0x35, 0x39, 0xeb,  0xdd, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xfb, 
+	 0xfb, 0xfb, 0xfd, 0xf5, 0xf5, 0xf7, 0xff, 0xfb,  0xff, 0xff, 0xf9, 0xfd, 0xfb, 0xf5, 0xf9, 0xf7, 
+	 0xf1, 0xf5, 0xf7, 0xf1, 0xf7, 0xfd, 0xf7, 0xfd,  0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xfd, 0xf7, 
+	 0xfd, 0xfd, 0xf7, 0xfd, 0xff, 0xf9, 0xff, 0xff,  0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 
+	 0xff, 0xfd, 0xff, 0xff, 0xfb, 0xff, 0xf9, 0xf9,  0xfb, 0xff, 0xff, 0xff, 0xf7, 0xf7, 0xf9, 0xfd, 
+	 0xfd, 0xff, 0xff, 0xff, 0xff, 0xef, 0xef, 0xf1,  0xef, 0xef, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd,  0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff, 
+	 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff,  0xff, 0xfd, 0xff, 0xfd, 0xfb, 0xff, 0xff, 0xfd, 
+	 0xff, 0x2b, 0x21, 0x25, 0x4f, 0x43, 0x47, 0xff,  0xf3, 0xf7, 0xf9, 0xf1, 0xf5, 0xff, 0xff, 0xff, 
+	 0xf7, 0xf7, 0xf9, 0xfd, 0xfd, 0xff, 0xfb, 0xf5,  0xf9, 0xff, 0xfb, 0xff, 0xff, 0xfd, 0xff, 0xff, 
+	 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfb, 0xff,  0xfd, 0xf7, 0xfd, 0xfd, 0xf7, 0xfb, 0xff, 0xfd, 
+	 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff,  0xfd, 0xff, 0xfd, 0xf7, 0xfd, 0xf9, 0xf3, 0xf9, 
+	 0xf9, 0xf3, 0xf7, 0xf9, 0xf3, 0xf9, 0xf9, 0xf9,  0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 
+	 0xfd, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd,  0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff, 
+	 0xfd, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff,  0xff, 0xff, 0xff, 0xfd, 0xfd, 0xff, 0xf7, 0xf1, 
+	 0xf3, 0xd5, 0xcf, 0xd1, 0xdd, 0xd3, 0xd7, 0xf9,  0xef, 0xf3, 0xff, 0xff, 0xff, 0xfd, 0xf9, 0xfd, 
+	 0xfb, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xf9, 0xfb,  0xfd, 0xfb, 0xfb, 0xfd, 0xfb, 0xfb, 0xfd, 0xf9, 
+	 0xfb, 0xfd, 0xf9, 0xfb, 0xfd, 0xfb, 0xfd, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 
+	 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xfb, 0xfd, 0xff, 0xfb, 0xfd, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff,  0xff, 0xe7, 0xf1, 0xf1, 0xf1, 0xf7, 0xf9, 0xf7, 
+	 0xfd, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xff,  0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 
+	 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd,  0xff, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff, 
+	 0xfd, 0xff, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xff,  0xfd, 0xfd, 0xff, 0xfb, 0xfb, 0xff, 0xff, 0xfb, 
+	 0xff, 0xf1, 0xeb, 0xed, 0xf7, 0xed, 0xf1, 0xff,  0xfd, 0xff, 0xf5, 0xf3, 0xf5, 0xff, 0xfb, 0xff, 
+	 0xf5, 0xfb, 0xfd, 0xfb, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xfd, 0xff, 0xff, 0xfb, 0xfb, 0xfd, 0xfb, 0xfd, 
+	 0xff, 0xfb, 0xfb, 0xfd, 0xfb, 0xfb, 0xfd, 0xfb,  0xfd, 0xff, 0xfd, 0xfd, 0xff, 0xfd, 0xff, 0xff, 
+	 0xfb, 0xfd, 0xff, 0xfb, 0xfb, 0xfd, 0xf7, 0xff,  0xff, 0xf3, 0xfd, 0xfd, 0xfb, 0xff, 0xff, 0xfb, 
+	 0xff, 0xff, 0xf9, 0xf9, 0xfb, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 
+	 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+};
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/I2C/Makefile
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/I2C/Makefile	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/I2C/Makefile	(revision 453)
@@ -0,0 +1,599 @@
+#
+#  TOPPERS/ASP Kernel
+#      Toyohashi Open Platform for Embedded Real-Time Systems/
+#      Advanced Standard Profile Kernel
+# 
+#  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                              Toyohashi Univ. of Technology, JAPAN
+#  Copyright (C) 2006-2014 by Embedded and Real-Time Systems Laboratory
+#              Graduate School of Information Science, Nagoya Univ., JAPAN
+# 
+#  ä¸è¨èä½æ¨©è
+ã¯ï¼ä»¥ä¸ã®(1)ï½(4)ã®æ¡ä»¶ãæºããå ´åã«éãï¼æ¬ã½ããã¦ã§
+#  ã¢ï¼æ¬ã½ããã¦ã§ã¢ãæ¹å¤ãããã®ãå«ãï¼ä»¥ä¸åãï¼ãä½¿ç¨ã»è¤è£½ã»æ¹
+#  å¤ã»åé
+å¸ï¼ä»¥ä¸ï¼å©ç¨ã¨å¼ã¶ï¼ãããã¨ãç¡åã§è¨±è«¾ããï¼
+#  (1) æ¬ã½ããã¦ã§ã¢ãã½ã¼ã¹ã³ã¼ãã®å½¢ã§å©ç¨ããå ´åã«ã¯ï¼ä¸è¨ã®èä½
+#      æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãï¼ãã®ã¾ã¾ã®å½¢ã§ã½ã¼
+#      ã¹ã³ã¼ãä¸­ã«å«ã¾ãã¦ãããã¨ï¼
+#  (2) æ¬ã½ããã¦ã§ã¢ãï¼ã©ã¤ãã©ãªå½¢å¼ãªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨
+#      è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®èä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨
+#      ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#  (3) æ¬ã½ããã¦ã§ã¢ãï¼æ©å¨ã«çµã¿è¾¼ããªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããªãå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼æ¬¡ã®ããããã®æ¡ä»¶ãæºããã
+#      ã¨ï¼
+#    (a) åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®è
+#        ä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#    (b) åé
+å¸ã®å½¢æ
+ãï¼å¥ã«å®ããæ¹æ³ã«ãã£ã¦ï¼TOPPERSãã­ã¸ã§ã¯ãã«
+#        å ±åãããã¨ï¼
+#  (4) æ¬ã½ããã¦ã§ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæ
+#      å®³ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ããå
+è²¬ãããã¨ï¼
+#      ã¾ãï¼æ¬ã½ããã¦ã§ã¢ã®ã¦ã¼ã¶ã¾ãã¯ã¨ã³ãã¦ã¼ã¶ããã®ãããªãç
+#      ç±ã«åºã¥ãè«æ±ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ãã
+#      å
+è²¬ãããã¨ï¼
+# 
+#  æ¬ã½ããã¦ã§ã¢ã¯ï¼ç¡ä¿è¨¼ã§æä¾ããã¦ãããã®ã§ããï¼ä¸è¨èä½æ¨©è
+ã
+#  ãã³TOPPERSãã­ã¸ã§ã¯ãã¯ï¼æ¬ã½ããã¦ã§ã¢ã«é¢ãã¦ï¼ç¹å®ã®ä½¿ç¨ç®ç
+#  ã«å¯¾ããé©åæ§ãå«ãã¦ï¼ãããªãä¿è¨¼ãè¡ããªãï¼ã¾ãï¼æ¬ã½ããã¦ã§
+#  ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæå®³ã«é¢ãã¦ãï¼ã
+#  ã®è²¬ä»»ãè² ããªãï¼
+# 
+#  $Id$
+# 
+
+#
+#  ã¿ã¼ã²ããã®æå®ï¼Makefile.targetã§ä¸æ¸ããããã®ãé²ãããï¼
+#
+all:
+
+#
+#  ã¿ã¼ã²ããç¥ç§°ã®å®ç¾©
+#
+TARGET = k210_gcc
+
+#
+#  ãã­ã°ã©ãã³ã°è¨èªã®å®ç¾©
+#
+SRCLANG = c
+ifeq ($(SRCLANG),c)
+  LIBS = -lc -lm
+endif
+ifeq ($(SRCLANG),c++)
+  USE_CXX = true
+  CXXLIBS = -lstdc++ -lm -lc
+  CXXRTS = cxxrt.o newlibrt.o
+endif
+
+#
+#  ã½ã¼ã¹ãã¡ã¤ã«ã®ãã£ã¬ã¯ããªã®å®ç¾©
+#
+SRCDIR = ../../..
+
+#
+#  ãªãã¸ã§ã¯ããã¡ã¤ã«åã®æ¡å¼µå­ã®è¨­å®
+#
+OBJEXT = exe
+
+#
+#  å®è¡ç°å¢ã®å®ç¾©ï¼ã¿ã¼ã²ããä¾å­ã«ä¸æ¸ããããå ´åãããï¼
+#
+DBGENV := 
+
+#
+#  ã«ã¼ãã«ã©ã¤ãã©ãªï¼libkernel.aï¼ã®ãã£ã¬ã¯ããªå
+#  ï¼ã«ã¼ãã«ã©ã¤ãã©ãªãmakeå¯¾è±¡ã«ããæã¯ï¼ç©ºã«å®ç¾©ããï¼
+#
+KERNEL_LIB = ../libkernel
+
+#
+#  ã«ã¼ãã«ãé¢æ°åä½ã§ã³ã³ãã¤ã«ãããã©ããã®å®ç¾©
+#
+KERNEL_FUNCOBJS = 
+
+#
+#  ãã¬ã¼ã¹ã­ã°ãåå¾ãããã©ããã®å®ç¾©
+#
+ENABLE_TRACE = 
+
+#
+#  ã¦ã¼ãã£ãªãã£ãã­ã°ã©ã ã®åç§°
+#
+PERL = /usr/bin/perl
+CFG = $(SRCDIR)/cfg/cfg/cfg
+
+#
+#  ãªãã¸ã§ã¯ããã¡ã¤ã«åã®å®ç¾©
+#
+OBJNAME = asp
+ifdef OBJEXT
+  OBJFILE = $(OBJNAME).$(OBJEXT)
+  CFG1_OUT = cfg1_out.$(OBJEXT)
+else
+  OBJFILE = $(OBJNAME)
+  CFG1_OUT = cfg1_out
+endif
+
+#
+#  ã¿ã¼ã²ããä¾å­é¨ã®ãã£ã¬ã¯ããªã®å®ç¾©
+#
+TARGETDIR = $(SRCDIR)/target/$(TARGET)
+
+#
+#  ã¿ã¼ã²ããä¾å­ã®å®ç¾©ã®ã¤ã³ã¯ã«ã¼ã
+#
+include $(TARGETDIR)/Makefile.target
+
+#
+#  ã³ã³ãã£ã®ã¥ã¬ã¼ã¿é¢ä¿ã®å¤æ°ã®å®ç¾©
+#
+CFG_TABS := --api-table $(SRCDIR)/kernel/kernel_api.csv \
+			--cfg1-def-table $(SRCDIR)/kernel/kernel_def.csv $(CFG_TABS)
+
+CFG_ASMOBJS := $(CFG_ASMOBJS)
+CFG_COBJS := kernel_cfg.o $(CFG_COBJS)
+CFG_OBJS := $(CFG_ASMOBJS) $(CFG_COBJS)
+CFG2_OUT_SRCS := kernel_cfg.h kernel_cfg.c $(CFG2_OUT_SRCS)
+
+#
+#  å
+±éã³ã³ãã¤ã«ãªãã·ã§ã³ã®å®ç¾©
+#
+COPTS := $(COPTS) -g 
+ifndef OMIT_WARNING_ALL
+  COPTS := $(COPTS) -Wall
+endif
+ifndef OMIT_OPTIMIZATION
+  COPTS := $(COPTS) -O2
+endif
+CDEFS := $(CDEFS) 
+INCLUDES := -I. -I$(SRCDIR)/include -I$(SRCDIR)/arch -I$(SRCDIR) $(INCLUDES)
+LDFLAGS := $(LDFLAGS) 
+CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) 
+LIBS := $(LIBS) $(CXXLIBS)
+CFLAGS = $(COPTS) $(CDEFS) $(INCLUDES)
+
+#
+#  ã¢ããªã±ã¼ã·ã§ã³ãã­ã°ã©ã ã«é¢ããå®ç¾©
+#
+APPLNAME = i2ctest
+APPLDIR = 
+APPL_CFG = $(APPLNAME).cfg
+
+APPL_DIR = $(APPLDIR) $(SRCDIR)/library
+APPL_ASMOBJS =
+ifdef USE_CXX
+  APPL_CXXOBJS = $(APPLNAME).o 
+  APPL_COBJS =
+else
+  APPL_COBJS = $(APPLNAME).o 
+endif
+APPL_COBJS := $(APPL_COBJS) log_output.o vasyslog.o t_perror.o strerror.o
+APPL_CFLAGS =
+APPL_LIBS =
+ifdef APPLDIR
+  INCLUDES := $(INCLUDES) $(foreach dir,$(APPLDIR),-I$(dir))
+endif
+
+#  ããã«ã¦ã§ã¢ã® Makefile ã®ã¤ã³ã¯ã«ã¼ã
+#
+include $(SRCDIR)/monitor/Makefile.config
+
+#
+#  GDIC Makefile ã®ã¤ã³ã¯ã«ã¼ã
+#
+include $(SRCDIR)/gdic/aqm0802_st7032/Makefile.config
+
+#
+#  ã·ã¹ãã ãµã¼ãã¹ã«é¢ããå®ç¾©
+#
+SYSSVC_DIR := $(SYSSVC_DIR) $(SRCDIR)/syssvc $(SRCDIR)/library $(SRCDIR)/pdic/k210
+SYSSVC_ASMOBJS := $(SYSSVC_ASMOBJS)
+SYSSVC_COBJS := $(SYSSVC_COBJS) banner.o syslog.o serial.o logtask.o riscv64.o \
+				 device.o i2c.o clock.o pinmode.o $(CXXRTS)
+SYSSVC_CFLAGS := $(SYSSVC_CFLAGS)
+SYSSVC_LIBS := $(SYSSVC_LIBS)
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/pdic/k210
+
+#
+#  ã«ã¼ãã«ã«é¢ããå®ç¾©
+#
+#  KERNEL_ASMOBJS: ã«ã¼ãã«ã©ã¤ãã©ãªã«å«ããï¼ã½ã¼ã¹ãã¢ã»ã³ããªè¨èªã®
+#				   ãªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#  KERNEL_COBJS: ã«ã¼ãã«ã®ã©ã¤ãã©ãªã«å«ããï¼ã½ã¼ã¹ãCè¨èªã§ï¼ã½ã¼ã¹
+#				 ãã¡ã¤ã«ã¨1å¯¾1ã«å¯¾å¿ãããªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#  KERNEL_LCSRCS: ã«ã¼ãã«ã®ã©ã¤ãã©ãªã«å«ããCè¨èªã®ã½ã¼ã¹ãã¡ã¤ã«ã§ï¼
+#				  1ã¤ã®ã½ã¼ã¹ãã¡ã¤ã«ããè¤æ°ã®ãªãã¸ã§ã¯ããã¡ã¤ã«ãç
+#				  æãããã®ï¼
+#  KERNEL_LCOBJS: ä¸ã®ã½ã¼ã¹ãã¡ã¤ã«ããçæããããªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#  KERNEL_AUX_COBJS: ã­ã¼ãã¢ã¸ã¥ã¼ã«ã«å«ããªããï¼ã«ã¼ãã«ã®ã½ã¼ã¹ãã¡
+#					 ã¤ã«ã¨åããªãã·ã§ã³ãé©ç¨ãã¦ã³ã³ãã¤ã«ãã¹ãï¼ã½ã¼
+#					 ã¹ãCè¨èªã®ãªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#
+KERNEL_DIR := $(KERNEL_DIR) $(SRCDIR)/kernel
+KERNEL_ASMOBJS := $(KERNEL_ASMOBJS)
+KERNEL_COBJS := $(KERNEL_COBJS)
+KERNEL_CFLAGS := $(KERNEL_CFLAGS) -I$(SRCDIR)/kernel
+ifdef OMIT_MAKEOFFSET
+  OFFSET_H =
+else
+  OFFSET_H = offset.h
+ifndef OFFSET_TF
+  KERNEL_AUX_COBJS := $(KERNEL_AUX_COBJS) makeoffset.o
+endif
+endif
+
+#
+#  ã¿ã¼ã²ãããã¡ã¤ã«ï¼è¤æ°ãåæã«é¸æãã¦ã¯ãªããªãï¼
+#
+all: $(OBJFILE)
+#all: $(OBJNAME).bin
+#all: $(OBJNAME).srec
+
+##### ä»¥ä¸ã¯ç·¨éããªããã¨ #####
+
+#
+#  ç°å¢ã«ä¾å­ããã³ã³ãã¤ã«ãªãã·ã§ã³ã®å®ç¾©
+#
+ifdef DBGENV
+  CDEFS := $(CDEFS) -D$(DBGENV)
+endif
+
+#
+#  ã«ã¼ãã«ã®ãã¡ã¤ã«æ§æã®å®ç¾©
+#
+include $(SRCDIR)/kernel/Makefile.kernel
+ifdef KERNEL_FUNCOBJS
+  KERNEL_LCSRCS := $(KERNEL_FCSRCS)
+  KERNEL_LCOBJS := $(foreach file,$(KERNEL_FCSRCS),$($(file:.c=)))
+else
+  KERNEL_CFLAGS := -DALLFUNC $(KERNEL_CFLAGS)
+  KERNEL_COBJS := $(KERNEL_COBJS) \
+					$(foreach file,$(KERNEL_FCSRCS),$(file:.c=.o))
+endif
+
+#
+#  ã½ã¼ã¹ãã¡ã¤ã«ã®ãããã£ã¬ã¯ããªã«é¢ããå®ç¾©
+#
+vpath %.c $(KERNEL_DIR) $(SYSSVC_DIR) $(APPL_DIR)
+vpath %.S $(KERNEL_DIR) $(SYSSVC_DIR) $(APPL_DIR)
+vpath %.cfg $(APPL_DIR)
+
+#
+#  ã³ã³ãã¤ã«ã®ããã®å¤æ°ã®å®ç¾©
+#
+KERNEL_LIB_OBJS = $(KERNEL_ASMOBJS) $(KERNEL_COBJS) $(KERNEL_LCOBJS)
+SYSSVC_OBJS = $(SYSSVC_ASMOBJS) $(SYSSVC_COBJS)
+APPL_OBJS = $(APPL_ASMOBJS) $(APPL_COBJS) $(APPL_CXXOBJS)
+ALL_OBJS = $(START_OBJS) $(APPL_OBJS) $(SYSSVC_OBJS) $(CFG_OBJS) \
+											$(END_OBJS) $(HIDDEN_OBJS)
+ifdef KERNEL_LIB
+  ALL_LIBS = $(APPL_LIBS) $(SYSSVC_LIBS) -lkernel $(LIBS)
+  LIBS_DEP = $(filter %.a,$(ALL_LIBS)) $(KERNEL_LIB)/libkernel.a
+  LDFLAGS := $(LDFLAGS) -L$(KERNEL_LIB)
+  REALCLEAN_FILES := libkernel.a $(REALCLEAN_FILES)
+else
+  ALL_LIBS = $(APPL_LIBS) $(SYSSVC_LIBS) libkernel.a $(LIBS)
+  LIBS_DEP = $(filter %.a,$(ALL_LIBS))
+endif
+
+ifdef TEXT_START_ADDRESS
+  LDFLAGS := $(LDFLAGS) -Wl,-Ttext,$(TEXT_START_ADDRESS)
+  CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) -Wl,-Ttext,$(TEXT_START_ADDRESS)
+endif
+ifdef DATA_START_ADDRESS
+  LDFLAGS := $(LDFLAGS) -Wl,-Tdata,$(DATA_START_ADDRESS)
+  CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) -Wl,-Tdata,$(DATA_START_ADDRESS)
+endif
+ifdef LDSCRIPT
+  LDFLAGS := $(LDFLAGS) -Wl,-T,$(LDSCRIPT)
+  CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) -Wl,-T,$(LDSCRIPT)
+endif
+
+#
+#  ãªãã»ãããã¡ã¤ã«ï¼offset.hï¼ã®çæè¦å
+#
+ifdef OFFSET_TF
+offset.h: $(APPL_CFG) kernel_cfg.timestamp
+	$(CFG) --pass 3 --kernel asp $(INCLUDES) \
+				--rom-image cfg1_out.srec --symbol-table cfg1_out.syms \
+				-T $(OFFSET_TF) $(CFG_TABS) $<
+else
+offset.h: makeoffset.s $(SRCDIR)/utils/genoffset
+	$(PERL) $(SRCDIR)/utils/genoffset makeoffset.s > offset.h
+endif
+
+#
+#  ã«ã¼ãã«ã®ã³ã³ãã£ã®ã¥ã¬ã¼ã·ã§ã³ãã¡ã¤ã«ã®çæ
+#
+cfg1_out.c: $(APPL_CFG)
+	$(CFG) --pass 1 --kernel asp $(INCLUDES) $(CFG_TABS) $<
+
+$(CFG2_OUT_SRCS): kernel_cfg.timestamp
+kernel_cfg.timestamp: $(APPL_CFG) \
+						$(START_OBJS) cfg1_out.o $(END_OBJS) $(HIDDEN_OBJS)
+	$(LINK) $(CFLAGS) $(CFG1_OUT_LDFLAGS) -o $(CFG1_OUT) \
+						$(START_OBJS) cfg1_out.o $(END_OBJS)
+	$(NM) -n $(CFG1_OUT) > cfg1_out.syms
+	$(OBJCOPY) -O srec -S $(CFG1_OUT) cfg1_out.srec
+	$(CFG) --pass 2 --kernel asp $(INCLUDES) \
+				-T $(TARGETDIR)/target.tf $(CFG_TABS) $<
+	touch -r kernel_cfg.c kernel_cfg.timestamp
+
+#
+#  ã«ã¼ãã«ã©ã¤ãã©ãªãã¡ã¤ã«ã®çæ
+#
+libkernel.a: $(OFFSET_H) $(KERNEL_LIB_OBJS)
+	rm -f libkernel.a
+	$(AR) -rcs libkernel.a $(KERNEL_LIB_OBJS)
+	$(RANLIB) libkernel.a
+
+#
+#  ç¹å¥ãªä¾å­é¢ä¿ã®å®ç¾©
+#
+banner.o: kernel_cfg.timestamp $(filter-out banner.o,$(ALL_OBJS)) $(LIBS_DEP)
+
+#
+#  å
+¨ä½ã®ãªã³ã¯
+#
+$(OBJFILE): $(APPL_CFG) kernel_cfg.timestamp $(ALL_OBJS) $(LIBS_DEP)
+	$(LINK) $(CFLAGS) $(LDFLAGS) -o $(OBJFILE) $(START_OBJS) \
+			$(APPL_OBJS) $(SYSSVC_OBJS) $(CFG_OBJS) $(ALL_LIBS) $(END_OBJS)
+	$(NM) -n $(OBJFILE) > $(OBJNAME).syms
+	$(OBJCOPY) -O srec -S $(OBJFILE) $(OBJNAME).srec
+	$(OBJCOPY) -O binary -S $(OBJFILE) $(OBJNAME).bin
+	$(CFG) --pass 3 --kernel asp $(INCLUDES) \
+				--rom-image $(OBJNAME).srec --symbol-table $(OBJNAME).syms \
+				-T $(TARGETDIR)/target_check.tf $(CFG_TABS) $<
+
+#
+#  ãã¤ããªãã¡ã¤ã«ã®çæ
+#
+$(OBJNAME).bin: $(OBJFILE)
+	$(OBJCOPY) -O binary -S $(OBJFILE) $(OBJNAME).bin
+
+#
+#  Sã¬ã³ã¼ããã¡ã¤ã«ã®çæ
+#
+$(OBJNAME).srec: $(OBJFILE)
+	$(OBJCOPY) -O srec -S $(OBJFILE) $(OBJNAME).srec
+
+#
+#  ã³ã³ãã¤ã«çµæã®æ¶å»
+#
+.PHONY: clean
+clean:
+	rm -f \#* *~ *.o $(CLEAN_FILES)
+	rm -f $(OBJFILE) $(OBJNAME).syms $(OBJNAME).srec $(OBJNAME).bin
+	rm -f kernel_cfg.timestamp $(CFG2_OUT_SRCS)
+	rm -f cfg1_out.c $(CFG1_OUT) cfg1_out.syms cfg1_out.srec
+ifndef KERNEL_LIB
+	rm -f libkernel.a
+endif
+	rm -f makeoffset.s offset.h
+
+.PHONY: cleankernel
+cleankernel:
+	rm -rf $(KERNEL_LIB_OBJS)
+	rm -f makeoffset.s offset.h
+
+.PHONY: cleandep
+cleandep:
+	if ! [ -f Makefile.depend ]; then \
+		rm -f kernel_cfg.timestamp $(CFG2_OUT_SRCS); \
+		rm -f cfg1_out.c cfg1_out.o $(CFG1_OUT) cfg1_out.syms cfg1_out.srec; \
+		rm -f makeoffset.s offset.h; \
+	fi
+	rm -f Makefile.depend
+
+.PHONY: realclean
+realclean: cleandep clean
+	rm -f $(REALCLEAN_FILES)
+
+#
+#  ã³ã³ãã£ã®ã¥ã¬ã¼ã¿ãçæãããã¡ã¤ã«ã®ã³ã³ãã¤ã«ã«ã¼ã«ã¨ä¾å­é¢ä¿ä½æ
+#  ã«ã¼ã«ã®å®ç¾©
+#
+#  ã³ã³ãã£ã®ã¥ã¬ã¼ã¿ãçæãããã¡ã¤ã«ã¯ï¼ã¢ããªã±ã¼ã·ã§ã³ãã­ã°ã©ã ç¨ï¼
+#  ã·ã¹ãã ãµã¼ãã¹ç¨ï¼ã«ã¼ãã«ç¨ã®ãã¹ã¦ã®ãªãã·ã§ã³ãä»ãã¦ã³ã³ãã¤ã«
+#  ããï¼
+#
+ALL_CFG_COBJS = $(CFG_COBJS) cfg1_out.o
+ALL_CFG_ASMOBJS = $(CFG_ASMOBJS)
+CFG_CFLAGS = $(APPL_CFLAGS) $(SYSSVC_CFLAGS) $(KERNEL_CFLAGS)
+
+$(ALL_CFG_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(CFG_CFLAGS) $<
+
+$(ALL_CFG_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(CFG_CFLAGS) $<
+
+$(ALL_CFG_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(CFG_CFLAGS)" $< >> Makefile.depend
+
+$(ALL_CFG_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(CFG_CFLAGS) $<
+
+$(ALL_CFG_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(CFG_CFLAGS)" $< >> Makefile.depend
+
+#
+#  ç¹æ®ãªä¾å­é¢ä¿ä½æã«ã¼ã«ã®å®ç¾©
+#
+cfg1_out.depend: $(APPL_CFG)
+	@$(CFG) -M cfg1_out.c $(INCLUDES) $< >> Makefile.depend
+
+makeoffset.d: makeoffset.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-T "makeoffset.s" -O "$(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+#
+#  ä¾å­é¢ä¿ãã¡ã¤ã«ã®çæ
+#
+.PHONY: gendepend
+gendepend:
+	@echo "Generating Makefile.depend."
+
+.PHONY: depend
+ifdef KERNEL_LIB
+depend: cleandep kernel_cfg.timestamp gendepend \
+		cfg1_out.depend cfg1_out.d \
+		$(ALL_OBJS:.o=.d)
+else
+depend: cleandep $(OFFSET_H) kernel_cfg.timestamp gendepend \
+		cfg1_out.depend cfg1_out.d \
+		$(KERNEL_AUX_COBJS:.o=.d) $(KERNEL_ASMOBJS:.o=.d) \
+		$(KERNEL_COBJS:.o=.d) $(KERNEL_LCSRCS:.c=.d) $(ALL_OBJS:.o=.d)
+endif
+
+#
+#  ä¾å­é¢ä¿ãã¡ã¤ã«ãã¤ã³ã¯ã«ã¼ã
+#
+-include Makefile.depend
+
+#
+#  éçºãã¼ã«ã®ã³ãã³ãåã®å®ç¾©
+#
+ifeq ($(TOOL),gcc)
+  #
+  #  GNUéçºç°å¢ç¨
+  #
+  ifdef GCC_TARGET
+    GCC_TARGET_PREFIX = $(GCC_TARGET)-
+  else
+    GCC_TARGET_PREFIX =
+  endif
+  CC = $(GCC_TARGET_PREFIX)gcc
+  CXX = $(GCC_TARGET_PREFIX)g++
+  AS = $(GCC_TARGET_PREFIX)as
+  LD = $(GCC_TARGET_PREFIX)ld
+  AR = $(GCC_TARGET_PREFIX)ar
+  NM = $(GCC_TARGET_PREFIX)nm
+  RANLIB = $(GCC_TARGET_PREFIX)ranlib
+  OBJCOPY = $(GCC_TARGET_PREFIX)objcopy
+  OBJDUMP = $(GCC_TARGET_PREFIX)objdump
+endif
+
+ifdef USE_CXX
+  LINK = $(CXX)
+else
+  LINK = $(CC)
+endif
+
+#
+#  ã³ã³ãã¤ã«ã«ã¼ã«ã®å®ç¾©
+#
+KERNEL_ALL_COBJS = $(KERNEL_COBJS) $(KERNEL_AUX_COBJS)
+
+$(KERNEL_ALL_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_ALL_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_LCOBJS): %.o:
+	$(CC) -DTOPPERS_$(*F) -o $@ -c $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_LCOBJS:.o=.s): %.s:
+	$(CC) -DTOPPERS_$(*F) -o $@ -S $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(SYSSVC_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(SYSSVC_CFLAGS) $<
+
+$(SYSSVC_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(SYSSVC_CFLAGS) $<
+
+$(SYSSVC_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(SYSSVC_CFLAGS) $<
+
+$(APPL_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_CXXOBJS): %.o: %.cpp
+	$(CXX) -c $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_CXXOBJS:.o=.s): %.s: %.cpp
+	$(CXX) -S $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(APPL_CFLAGS) $<
+
+#
+#  ä¾å­é¢ä¿ä½æã«ã¼ã«ã®å®ç¾©
+#
+$(KERNEL_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+$(KERNEL_LCSRCS:.c=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) -T "$($*)" \
+		-O "-DALLFUNC $(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+$(KERNEL_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+$(SYSSVC_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(SYSSVC_CFLAGS)" $< >> Makefile.depend
+
+$(SYSSVC_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(SYSSVC_CFLAGS)" $< >> Makefile.depend
+
+$(APPL_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(APPL_CFLAGS)" $< >> Makefile.depend
+
+$(APPL_CXXOBJS:.o=.d): %.d: %.cpp
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CXX) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(APPL_CFLAGS)" $< >> Makefile.depend
+
+$(APPL_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(APPL_CFLAGS)" $< >> Makefile.depend
+
+#
+#  ããã©ã«ãã³ã³ãã¤ã«ã«ã¼ã«ãä¸æ¸ã
+#
+%.o: %.c
+	@echo "*** Default compile rules should not be used."
+	$(CC) -c $(CFLAGS) $<
+
+%.s: %.c
+	@echo "*** Default compile rules should not be used."
+	$(CC) -S $(CFLAGS) $<
+
+%.o: %.cpp
+	@echo "*** Default compile rules should not be used."
+	$(CXX) -c $(CFLAGS) $<
+
+%.s: %.cpp
+	@echo "*** Default compile rules should not be used."
+	$(CXX) -S $(CFLAGS) $<
+
+%.o: %.S
+	@echo "*** Default compile rules should not be used."
+	$(CC) -c $(CFLAGS) $<
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/I2C/i2ctest.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/I2C/i2ctest.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/I2C/i2ctest.c	(revision 453)
@@ -0,0 +1,273 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2012 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2017 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *  I2Cテストの本体
+ *  本テストはmaxi bitにブレッドボードにI2Cシールドを接続してテスト
+ *  maxidunoでは電気的な問題で通信エラーとなる.
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <sil.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#include "kernel_cfg.h"
+#include <target_syssvc.h>
+#include <string.h>
+#include "device.h"
+#include "pinmode.h"
+#include "i2ctest.h"
+
+/*
+ *  サービスコールのエラーのログ出力
+ */
+Inline void
+svc_perror(const char *file, int_t line, const char *expr, ER ercd)
+{
+	if (ercd < 0) {
+		t_perror(LOG_ERROR, file, line, expr, ercd);
+	}
+}
+
+#define	SVC_PERROR(expr)	svc_perror(__FILE__, __LINE__, #expr, (expr))
+
+
+#define RXBUFFERSIZE       12
+
+/*
+ *  スレーブアドレス定義
+ */
+#define LCD_ADDR           (0x3E<<1)
+#define EEPROM_ADDR        (0x50<<1)
+#define ADT7410_ADDR       (0x48<<1)
+
+#define ADT7410_TEMP_H	0x00
+#define ADT7410_TEMP_L	0x01
+#define ADT7410_STATUS	0x02
+
+#define LCD_locate(h, x, y) aqm0802_set_command((h), (0x80 + ((y) << 6) + (x)))
+#define LCD_puts(h, b)      aqm0802_set_data((h), (b), strlen((const char *)(b)))
+
+
+/* Buffer used for reception */
+uint8_t aRxBuffer[RXBUFFERSIZE];
+
+uint8_t lcd_buf[2][12];
+
+/*
+ *  I2C SEND CALLBACK FUNCTION
+ */
+static void
+I2C_TxCpltCallback(I2C_Handle_t *hi2c)
+{
+	syslog_1(LOG_DEBUG, "## I2C_TxCpltCallback(%08x) ##", hi2c);
+}
+
+/*
+ *  I2C RECEIVE CALLBACK
+ */
+static void
+I2C_RxCpltCallback(I2C_Handle_t *hi2c)
+{
+	syslog_1(LOG_DEBUG, "## I2C_RxCpltCallback(%08x) ##", hi2c);
+}
+
+/*
+ *  I2C ERROR CALLBACK
+ */
+static void
+I2C_ErrorCallback(I2C_Handle_t *hi2c)
+{
+	syslog_1(LOG_ERROR, "## I2C_ErrorCallback(%08x) ##", hi2c);
+}
+
+static void
+set_value(uint8_t *buf, int value)
+{
+    buf[1] = (value % 10) + '0';
+    buf[0] = (value / 10) + '0';
+}
+
+static void
+set_time(uint8_t *buf, long time)
+{
+    int wk = time/1000;
+    set_value(&buf[6], wk % 60);
+    wk = wk / 60;
+    buf[5] = ':';
+    set_value(&buf[3], wk % 60);
+    wk = wk / 60;
+    buf[2] = ':';
+    set_value(&buf[0], wk);
+}
+
+/*
+ *  メインタスク
+ */
+void main_task(intptr_t exinf)
+{
+	I2C_Init_t i2c_initd;
+	I2C_Handle_t *hi2c;
+	CLCD_Handler_t  CLcdHandle;
+	ER_UINT	ercd;
+	SYSTIM  tim;
+	uint16_t temp;
+	uint32_t count = 0;
+
+	SVC_PERROR(syslog_msk_log(LOG_UPTO(LOG_INFO), LOG_UPTO(LOG_EMERG)));
+	syslog(LOG_NOTICE, "Sample program starts (exinf = %d).", (int_t) exinf);
+
+	/*
+	 *  シリアルポートの初期化
+	 *
+	 *  システムログタスクと同じシリアルポートを使う場合など，シリアル
+	 *  ポートがオープン済みの場合にはここでE_OBJエラーになるが，支障は
+	 *  ない．
+	 */
+	ercd = serial_opn_por(TASK_PORTID);
+	if (ercd < 0 && MERCD(ercd) != E_OBJ) {
+		syslog(LOG_ERROR, "%s (%d) reported by `serial_opn_por'.",
+									itron_strerror(ercd), SERCD(ercd));
+	}
+	SVC_PERROR(serial_ctl_por(TASK_PORTID,
+							(IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV)));
+
+	syslog_1(LOG_NOTICE, "I2C SEND/RECV START(%d)", I2C_PORTID);
+
+	i2c_initd.ClockSpeed      = 100000;
+	i2c_initd.OwnAddress1     = 0;
+	i2c_initd.AddressingMode  = I2C_ADDRESSINGMODE_7BIT;
+	i2c_initd.SclPin          = getGpioPin(15);
+	i2c_initd.SdaPin          = getGpioPin(14);
+	i2c_initd.semid           = I2CTRS_SEM;
+	i2c_initd.semlock         = I2CLOC_SEM;
+	syslog_2(LOG_NOTICE, "I2C SDAPIN(%d) SCLPIN(%d)", i2c_initd.SdaPin, i2c_initd.SclPin);
+
+	if((hi2c = i2c_init(I2C_PORTID, &i2c_initd)) == NULL){
+		/* Initialization Error */
+		syslog_0(LOG_ERROR, "## I2C ERROR(1) ##");
+	}
+	syslog_1(LOG_NOTICE, "LCD INITAILIZE(%d) !", I2C_PORTID);
+
+	hi2c->writecallback = I2C_TxCpltCallback;
+	hi2c->readcallback  = I2C_RxCpltCallback;
+	hi2c->errorcallback = I2C_ErrorCallback;
+
+	memset(&lcd_buf[0][0], ' ', 8);
+	memset(&lcd_buf[1][0], ' ', 8);
+
+	CLcdHandle.hi2c  = hi2c;
+	CLcdHandle.saddr = LCD_ADDR;
+	if((ercd = aqm0802_init(&CLcdHandle)) != E_OK){
+		syslog_2(LOG_ERROR, "## LCD INIT ERROR(%d)[%08x] ##", ercd, hi2c->ErrorCode);
+		goto stop_task;
+	}
+
+	get_tim(&tim);
+	set_time(&lcd_buf[0][0], tim);
+	LCD_locate(&CLcdHandle, 0, 0);
+	LCD_puts(&CLcdHandle, &lcd_buf[0][0]);
+
+	dly_tsk(200);
+#ifdef EEPROM_ADDR
+	syslog_1(LOG_NOTICE, "READ EEPROM [%08x] !", aRxBuffer);
+	dly_tsk(200);
+	if(i2c_memread(hi2c, (uint16_t)EEPROM_ADDR, 0, I2C_MEMADD_SIZE_16BIT, (uint8_t*)aRxBuffer, RXBUFFERSIZE)!= E_OK){
+	    /* I2C RECEIVE ERROR */
+		syslog_1(LOG_ERROR, "## I2C ERROR(12)[%08x] ##", hi2c->ErrorCode);
+		goto stop_task;
+	}
+#endif
+
+	syslog_0(LOG_NOTICE, "TEMP SENSER !");
+	do{
+		/* STATUS READ */
+		if(i2c_memread(hi2c, (uint16_t)ADT7410_ADDR, ADT7410_STATUS, I2C_MEMADD_SIZE_8BIT, (uint8_t*)aRxBuffer, 1)!= E_OK){
+			/* I2C RECEIVE ERROR */
+			syslog_1(LOG_ERROR, "## I2C ERROR(13)[%08x] ##", hi2c->ErrorCode);
+			goto stop_task;
+		}
+		temp = aRxBuffer[0];
+		syslog_1(LOG_NOTICE, "## temp[%02x] ##", temp);
+	}while((temp & 0x80) != 0);
+
+#if 1
+	while(count < 1000){
+		if(i2c_memread(hi2c, (uint16_t)ADT7410_ADDR, ADT7410_TEMP_H, I2C_MEMADD_SIZE_8BIT, (uint8_t*)aRxBuffer, 1)!= E_OK){
+			/* I2C RECEIVE ERROR */
+			syslog_1(LOG_ERROR, "## I2C ERROR(14)[%08x] ##", hi2c->ErrorCode);
+			goto stop_task;
+		}
+		temp = aRxBuffer[0] << 8;
+		if(i2c_memread(hi2c, (uint16_t)ADT7410_ADDR, ADT7410_TEMP_L, I2C_MEMADD_SIZE_8BIT, (uint8_t*)aRxBuffer, 1)!= E_OK){
+			/* I2C RECEIVE ERROR */
+			syslog_1(LOG_ERROR, "## I2C ERROR(15)[%08x] ##", hi2c->ErrorCode);
+			goto stop_task;
+		}
+		temp += aRxBuffer[0];
+		temp /= 13;
+
+		get_tim(&tim);
+		set_time(&lcd_buf[0][0], tim);
+		LCD_locate(&CLcdHandle, 0, 0);
+		LCD_puts(&CLcdHandle, &lcd_buf[0][0]);
+		set_value(&lcd_buf[1][0], temp/10);
+		lcd_buf[1][2] = '.';
+		lcd_buf[1][3] = (temp % 10) + '0';
+		LCD_locate(&CLcdHandle, 0, 1);
+		LCD_puts(&CLcdHandle, &lcd_buf[1][0]);
+		if((count % 10) == 0)
+			syslog_2(LOG_NOTICE, "count(%d) temp(%d)", count, temp);
+		dly_tsk(1000);
+		count++;
+	}
+#endif
+
+stop_task:
+	syslog_0(LOG_NOTICE, "## STOP ##");
+	slp_tsk();
+	syslog(LOG_NOTICE, "Sample program ends.");
+//	SVC_PERROR(ext_ker());
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/I2C/i2ctest.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/I2C/i2ctest.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/I2C/i2ctest.cfg	(revision 453)
@@ -0,0 +1,29 @@
+/*
+ *  $Id$
+ */
+
+/*
+ *  SPIテストのコンフィギュレーションファイル
+ */
+INCLUDE("target_timer.cfg");
+INCLUDE("syssvc/syslog.cfg");
+INCLUDE("syssvc/banner.cfg");
+INCLUDE("syssvc/serial.cfg");
+INCLUDE("syssvc/logtask.cfg");
+INCLUDE("monitor/monitor.cfg");
+INCLUDE("pdic/k210/device.cfg");
+
+#include "device.h"
+#include "i2ctest.h"
+
+ATT_INI({ TA_NULL, 0, rtc_init });
+ATT_INI({ TA_NULL, 0, rtc_info_init });
+
+CRE_SEM(I2CTRS_SEM, { TA_TPRI, 0, 1 });
+CRE_SEM(I2CLOC_SEM, { TA_TPRI, 1, 1 });
+
+CRE_TSK(MAIN_TASK, { TA_NULL, 0, main_task, MAIN_PRIORITY, STACK_SIZE, NULL });
+
+ATT_ISR({TA_NULL, I2C_PORTID, INTNO_I2CEV, i2c_isr, 1 });
+CFG_INT(INTNO_I2CEV, { TA_ENAINT | INTATR_I2CEV, INTPRI_I2CEV });
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/I2C/i2ctest.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/I2C/i2ctest.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/I2C/i2ctest.h	(revision 453)
@@ -0,0 +1,102 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ *
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ *
+ *  $Id$
+ */
+
+/*
+ *	I2Cテストのヘッダファイル
+ */
+
+/*
+ *  ターゲット依存の定義
+ */
+#include "target_test.h"
+#include "i2c.h"
+#include "aqm0802_st7032.h"
+
+/*
+ *  各タスクの優先度の定義
+ */
+
+#define MAIN_PRIORITY	5		/* メインタスクの優先度 */
+								/* HIGH_PRIORITYより高くすること */
+
+#define HIGH_PRIORITY	9		/* 並行実行されるタスクの優先度 */
+#define MID_PRIORITY	10
+#define LOW_PRIORITY	11
+
+/*
+ *  ターゲットに依存する可能性のある定数の定義
+ */
+
+#ifndef TASK_PORTID
+#define	TASK_PORTID		1			/* 文字入力するシリアルポートID */
+#endif /* TASK_PORTID */
+
+#ifndef STACK_SIZE
+#define	STACK_SIZE		4096		/* タスクのスタックサイズ */
+#endif /* STACK_SIZE */
+
+#ifndef PORTID
+#define PORTID        1				/* arduino D15/D14 */
+#endif
+
+#if PORTID == 1
+#define I2C_PORTID    I2C1_PORTID
+#define INHNO_I2CEV   IRQ_VECTOR_I2C0	/* 割込みハンドラ番号 */
+#define INTNO_I2CEV   IRQ_VECTOR_I2C0	/* 割込み番号 */
+#define INTPRI_I2CEV  -5			/* 割込み優先度 */
+#define INTATR_I2CEV  0				/* 割込み属性 */
+#else
+#define I2C_PORTID    I2C2_PORTID
+#define INHNO_I2CEV   IRQ_VECTOR_I2C1	/* 割込みハンドラ番号 */
+#define INTNO_I2CEV   IRQ_VECTOR_I2C1	/* 割込み番号 */
+#define INTPRI_I2CEV  -5			/* 割込み優先度 */
+#define INTATR_I2CEV  0				/* 割込み属性 */
+#endif
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+extern void	main_task(intptr_t exinf);
+
+#endif /* TOPPERS_MACRO_ONLY */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/MON/Makefile
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/MON/Makefile	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/MON/Makefile	(revision 453)
@@ -0,0 +1,593 @@
+#
+#  TOPPERS/ASP Kernel
+#      Toyohashi Open Platform for Embedded Real-Time Systems/
+#      Advanced Standard Profile Kernel
+# 
+#  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                              Toyohashi Univ. of Technology, JAPAN
+#  Copyright (C) 2006-2014 by Embedded and Real-Time Systems Laboratory
+#              Graduate School of Information Science, Nagoya Univ., JAPAN
+# 
+#  ä¸è¨èä½æ¨©è
+ã¯ï¼ä»¥ä¸ã®(1)ï½(4)ã®æ¡ä»¶ãæºããå ´åã«éãï¼æ¬ã½ããã¦ã§
+#  ã¢ï¼æ¬ã½ããã¦ã§ã¢ãæ¹å¤ãããã®ãå«ãï¼ä»¥ä¸åãï¼ãä½¿ç¨ã»è¤è£½ã»æ¹
+#  å¤ã»åé
+å¸ï¼ä»¥ä¸ï¼å©ç¨ã¨å¼ã¶ï¼ãããã¨ãç¡åã§è¨±è«¾ããï¼
+#  (1) æ¬ã½ããã¦ã§ã¢ãã½ã¼ã¹ã³ã¼ãã®å½¢ã§å©ç¨ããå ´åã«ã¯ï¼ä¸è¨ã®èä½
+#      æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãï¼ãã®ã¾ã¾ã®å½¢ã§ã½ã¼
+#      ã¹ã³ã¼ãä¸­ã«å«ã¾ãã¦ãããã¨ï¼
+#  (2) æ¬ã½ããã¦ã§ã¢ãï¼ã©ã¤ãã©ãªå½¢å¼ãªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨
+#      è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®èä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨
+#      ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#  (3) æ¬ã½ããã¦ã§ã¢ãï¼æ©å¨ã«çµã¿è¾¼ããªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããªãå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼æ¬¡ã®ããããã®æ¡ä»¶ãæºããã
+#      ã¨ï¼
+#    (a) åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®è
+#        ä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#    (b) åé
+å¸ã®å½¢æ
+ãï¼å¥ã«å®ããæ¹æ³ã«ãã£ã¦ï¼TOPPERSãã­ã¸ã§ã¯ãã«
+#        å ±åãããã¨ï¼
+#  (4) æ¬ã½ããã¦ã§ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæ
+#      å®³ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ããå
+è²¬ãããã¨ï¼
+#      ã¾ãï¼æ¬ã½ããã¦ã§ã¢ã®ã¦ã¼ã¶ã¾ãã¯ã¨ã³ãã¦ã¼ã¶ããã®ãããªãç
+#      ç±ã«åºã¥ãè«æ±ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ãã
+#      å
+è²¬ãããã¨ï¼
+# 
+#  æ¬ã½ããã¦ã§ã¢ã¯ï¼ç¡ä¿è¨¼ã§æä¾ããã¦ãããã®ã§ããï¼ä¸è¨èä½æ¨©è
+ã
+#  ãã³TOPPERSãã­ã¸ã§ã¯ãã¯ï¼æ¬ã½ããã¦ã§ã¢ã«é¢ãã¦ï¼ç¹å®ã®ä½¿ç¨ç®ç
+#  ã«å¯¾ããé©åæ§ãå«ãã¦ï¼ãããªãä¿è¨¼ãè¡ããªãï¼ã¾ãï¼æ¬ã½ããã¦ã§
+#  ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæå®³ã«é¢ãã¦ãï¼ã
+#  ã®è²¬ä»»ãè² ããªãï¼
+# 
+#  $Id$
+# 
+
+#
+#  ã¿ã¼ã²ããã®æå®ï¼Makefile.targetã§ä¸æ¸ããããã®ãé²ãããï¼
+#
+all:
+
+#
+#  ã¿ã¼ã²ããç¥ç§°ã®å®ç¾©
+#
+TARGET = k210_gcc
+
+#
+#  ãã­ã°ã©ãã³ã°è¨èªã®å®ç¾©
+#
+SRCLANG = c
+ifeq ($(SRCLANG),c)
+  LIBS = -lc -lm
+endif
+ifeq ($(SRCLANG),c++)
+  USE_CXX = true
+  CXXLIBS = -lstdc++ -lm -lc
+  CXXRTS = cxxrt.o newlibrt.o
+endif
+
+#
+#  ã½ã¼ã¹ãã¡ã¤ã«ã®ãã£ã¬ã¯ããªã®å®ç¾©
+#
+SRCDIR = ../../..
+
+#
+#  ãªãã¸ã§ã¯ããã¡ã¤ã«åã®æ¡å¼µå­ã®è¨­å®
+#
+OBJEXT = exe
+
+#
+#  å®è¡ç°å¢ã®å®ç¾©ï¼ã¿ã¼ã²ããä¾å­ã«ä¸æ¸ããããå ´åãããï¼
+#
+DBGENV := 
+
+#
+#  ã«ã¼ãã«ã©ã¤ãã©ãªï¼libkernel.aï¼ã®ãã£ã¬ã¯ããªå
+#  ï¼ã«ã¼ãã«ã©ã¤ãã©ãªãmakeå¯¾è±¡ã«ããæã¯ï¼ç©ºã«å®ç¾©ããï¼
+#
+KERNEL_LIB = ../libkernel
+
+#
+#  ã«ã¼ãã«ãé¢æ°åä½ã§ã³ã³ãã¤ã«ãããã©ããã®å®ç¾©
+#
+KERNEL_FUNCOBJS = 
+
+#
+#  ãã¬ã¼ã¹ã­ã°ãåå¾ãããã©ããã®å®ç¾©
+#
+ENABLE_TRACE = 
+
+#
+#  ã¦ã¼ãã£ãªãã£ãã­ã°ã©ã ã®åç§°
+#
+PERL = /usr/bin/perl
+CFG = $(SRCDIR)/cfg/cfg/cfg
+
+#
+#  ãªãã¸ã§ã¯ããã¡ã¤ã«åã®å®ç¾©
+#
+OBJNAME = asp
+ifdef OBJEXT
+  OBJFILE = $(OBJNAME).$(OBJEXT)
+  CFG1_OUT = cfg1_out.$(OBJEXT)
+else
+  OBJFILE = $(OBJNAME)
+  CFG1_OUT = cfg1_out
+endif
+
+#
+#  ã¿ã¼ã²ããä¾å­é¨ã®ãã£ã¬ã¯ããªã®å®ç¾©
+#
+TARGETDIR = $(SRCDIR)/target/$(TARGET)
+
+#
+#  ã¿ã¼ã²ããä¾å­ã®å®ç¾©ã®ã¤ã³ã¯ã«ã¼ã
+#
+include $(TARGETDIR)/Makefile.target
+
+#
+#  ã³ã³ãã£ã®ã¥ã¬ã¼ã¿é¢ä¿ã®å¤æ°ã®å®ç¾©
+#
+CFG_TABS := --api-table $(SRCDIR)/kernel/kernel_api.csv \
+			--cfg1-def-table $(SRCDIR)/kernel/kernel_def.csv $(CFG_TABS)
+
+CFG_ASMOBJS := $(CFG_ASMOBJS)
+CFG_COBJS := kernel_cfg.o $(CFG_COBJS)
+CFG_OBJS := $(CFG_ASMOBJS) $(CFG_COBJS)
+CFG2_OUT_SRCS := kernel_cfg.h kernel_cfg.c $(CFG2_OUT_SRCS)
+
+#
+#  å
+±éã³ã³ãã¤ã«ãªãã·ã§ã³ã®å®ç¾©
+#
+COPTS := $(COPTS) -g 
+ifndef OMIT_WARNING_ALL
+  COPTS := $(COPTS) -Wall
+endif
+ifndef OMIT_OPTIMIZATION
+  COPTS := $(COPTS) -O2
+endif
+CDEFS := $(CDEFS) 
+INCLUDES := -I. -I$(SRCDIR)/include -I$(SRCDIR)/arch -I$(SRCDIR) $(INCLUDES)
+LDFLAGS := $(LDFLAGS) 
+CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) 
+LIBS := $(LIBS) $(CXXLIBS)
+CFLAGS = $(COPTS) $(CDEFS) $(INCLUDES)
+
+#
+#  ã¢ããªã±ã¼ã·ã§ã³ãã­ã°ã©ã ã«é¢ããå®ç¾©
+#
+APPLNAME = sample1
+APPLDIR = 
+APPL_CFG = $(APPLNAME).cfg
+
+APPL_DIR = $(APPLDIR) $(SRCDIR)/library
+APPL_ASMOBJS =
+ifdef USE_CXX
+  APPL_CXXOBJS = $(APPLNAME).o 
+  APPL_COBJS =
+else
+  APPL_COBJS = $(APPLNAME).o 
+endif
+APPL_COBJS := $(APPL_COBJS) log_output.o vasyslog.o t_perror.o strerror.o
+APPL_CFLAGS =
+APPL_LIBS =
+ifdef APPLDIR
+  INCLUDES := $(INCLUDES) $(foreach dir,$(APPLDIR),-I$(dir))
+endif
+
+#  ããã«ã¦ã§ã¢ã® Makefile ã®ã¤ã³ã¯ã«ã¼ã
+#
+include $(SRCDIR)/monitor/Makefile.config
+
+#
+#  ã·ã¹ãã ãµã¼ãã¹ã«é¢ããå®ç¾©
+#
+SYSSVC_DIR := $(SYSSVC_DIR) $(SRCDIR)/syssvc $(SRCDIR)/library $(SRCDIR)/pdic/k210
+SYSSVC_ASMOBJS := $(SYSSVC_ASMOBJS)
+SYSSVC_COBJS := $(SYSSVC_COBJS) banner.o syslog.o serial.o logtask.o riscv64.o \
+				 device.o clock.o $(CXXRTS)
+SYSSVC_CFLAGS := $(SYSSVC_CFLAGS)
+SYSSVC_LIBS := $(SYSSVC_LIBS)
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/pdic/k210
+
+#
+#  ã«ã¼ãã«ã«é¢ããå®ç¾©
+#
+#  KERNEL_ASMOBJS: ã«ã¼ãã«ã©ã¤ãã©ãªã«å«ããï¼ã½ã¼ã¹ãã¢ã»ã³ããªè¨èªã®
+#				   ãªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#  KERNEL_COBJS: ã«ã¼ãã«ã®ã©ã¤ãã©ãªã«å«ããï¼ã½ã¼ã¹ãCè¨èªã§ï¼ã½ã¼ã¹
+#				 ãã¡ã¤ã«ã¨1å¯¾1ã«å¯¾å¿ãããªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#  KERNEL_LCSRCS: ã«ã¼ãã«ã®ã©ã¤ãã©ãªã«å«ããCè¨èªã®ã½ã¼ã¹ãã¡ã¤ã«ã§ï¼
+#				  1ã¤ã®ã½ã¼ã¹ãã¡ã¤ã«ããè¤æ°ã®ãªãã¸ã§ã¯ããã¡ã¤ã«ãç
+#				  æãããã®ï¼
+#  KERNEL_LCOBJS: ä¸ã®ã½ã¼ã¹ãã¡ã¤ã«ããçæããããªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#  KERNEL_AUX_COBJS: ã­ã¼ãã¢ã¸ã¥ã¼ã«ã«å«ããªããï¼ã«ã¼ãã«ã®ã½ã¼ã¹ãã¡
+#					 ã¤ã«ã¨åããªãã·ã§ã³ãé©ç¨ãã¦ã³ã³ãã¤ã«ãã¹ãï¼ã½ã¼
+#					 ã¹ãCè¨èªã®ãªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#
+KERNEL_DIR := $(KERNEL_DIR) $(SRCDIR)/kernel
+KERNEL_ASMOBJS := $(KERNEL_ASMOBJS)
+KERNEL_COBJS := $(KERNEL_COBJS)
+KERNEL_CFLAGS := $(KERNEL_CFLAGS) -I$(SRCDIR)/kernel
+ifdef OMIT_MAKEOFFSET
+  OFFSET_H =
+else
+  OFFSET_H = offset.h
+ifndef OFFSET_TF
+  KERNEL_AUX_COBJS := $(KERNEL_AUX_COBJS) makeoffset.o
+endif
+endif
+
+#
+#  ã¿ã¼ã²ãããã¡ã¤ã«ï¼è¤æ°ãåæã«é¸æãã¦ã¯ãªããªãï¼
+#
+#all: $(OBJFILE)
+all: $(OBJNAME).bin
+#all: $(OBJNAME).srec
+
+##### ä»¥ä¸ã¯ç·¨éããªããã¨ #####
+
+#
+#  ç°å¢ã«ä¾å­ããã³ã³ãã¤ã«ãªãã·ã§ã³ã®å®ç¾©
+#
+ifdef DBGENV
+  CDEFS := $(CDEFS) -D$(DBGENV)
+endif
+
+#
+#  ã«ã¼ãã«ã®ãã¡ã¤ã«æ§æã®å®ç¾©
+#
+include $(SRCDIR)/kernel/Makefile.kernel
+ifdef KERNEL_FUNCOBJS
+  KERNEL_LCSRCS := $(KERNEL_FCSRCS)
+  KERNEL_LCOBJS := $(foreach file,$(KERNEL_FCSRCS),$($(file:.c=)))
+else
+  KERNEL_CFLAGS := -DALLFUNC $(KERNEL_CFLAGS)
+  KERNEL_COBJS := $(KERNEL_COBJS) \
+					$(foreach file,$(KERNEL_FCSRCS),$(file:.c=.o))
+endif
+
+#
+#  ã½ã¼ã¹ãã¡ã¤ã«ã®ãããã£ã¬ã¯ããªã«é¢ããå®ç¾©
+#
+vpath %.c $(KERNEL_DIR) $(SYSSVC_DIR) $(APPL_DIR)
+vpath %.S $(KERNEL_DIR) $(SYSSVC_DIR) $(APPL_DIR)
+vpath %.cfg $(APPL_DIR)
+
+#
+#  ã³ã³ãã¤ã«ã®ããã®å¤æ°ã®å®ç¾©
+#
+KERNEL_LIB_OBJS = $(KERNEL_ASMOBJS) $(KERNEL_COBJS) $(KERNEL_LCOBJS)
+SYSSVC_OBJS = $(SYSSVC_ASMOBJS) $(SYSSVC_COBJS)
+APPL_OBJS = $(APPL_ASMOBJS) $(APPL_COBJS) $(APPL_CXXOBJS)
+ALL_OBJS = $(START_OBJS) $(APPL_OBJS) $(SYSSVC_OBJS) $(CFG_OBJS) \
+											$(END_OBJS) $(HIDDEN_OBJS)
+ifdef KERNEL_LIB
+  ALL_LIBS = $(APPL_LIBS) $(SYSSVC_LIBS) -lkernel $(LIBS)
+  LIBS_DEP = $(filter %.a,$(ALL_LIBS)) $(KERNEL_LIB)/libkernel.a
+  LDFLAGS := $(LDFLAGS) -L$(KERNEL_LIB)
+  REALCLEAN_FILES := libkernel.a $(REALCLEAN_FILES)
+else
+  ALL_LIBS = $(APPL_LIBS) $(SYSSVC_LIBS) libkernel.a $(LIBS)
+  LIBS_DEP = $(filter %.a,$(ALL_LIBS))
+endif
+
+ifdef TEXT_START_ADDRESS
+  LDFLAGS := $(LDFLAGS) -Wl,-Ttext,$(TEXT_START_ADDRESS)
+  CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) -Wl,-Ttext,$(TEXT_START_ADDRESS)
+endif
+ifdef DATA_START_ADDRESS
+  LDFLAGS := $(LDFLAGS) -Wl,-Tdata,$(DATA_START_ADDRESS)
+  CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) -Wl,-Tdata,$(DATA_START_ADDRESS)
+endif
+ifdef LDSCRIPT
+  LDFLAGS := $(LDFLAGS) -Wl,-T,$(LDSCRIPT)
+  CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) -Wl,-T,$(LDSCRIPT)
+endif
+
+#
+#  ãªãã»ãããã¡ã¤ã«ï¼offset.hï¼ã®çæè¦å
+#
+ifdef OFFSET_TF
+offset.h: $(APPL_CFG) kernel_cfg.timestamp
+	$(CFG) --pass 3 --kernel asp $(INCLUDES) \
+				--rom-image cfg1_out.srec --symbol-table cfg1_out.syms \
+				-T $(OFFSET_TF) $(CFG_TABS) $<
+else
+offset.h: makeoffset.s $(SRCDIR)/utils/genoffset
+	$(PERL) $(SRCDIR)/utils/genoffset makeoffset.s > offset.h
+endif
+
+#
+#  ã«ã¼ãã«ã®ã³ã³ãã£ã®ã¥ã¬ã¼ã·ã§ã³ãã¡ã¤ã«ã®çæ
+#
+cfg1_out.c: $(APPL_CFG)
+	$(CFG) --pass 1 --kernel asp $(INCLUDES) $(CFG_TABS) $<
+
+$(CFG2_OUT_SRCS): kernel_cfg.timestamp
+kernel_cfg.timestamp: $(APPL_CFG) \
+						$(START_OBJS) cfg1_out.o $(END_OBJS) $(HIDDEN_OBJS)
+	$(LINK) $(CFLAGS) $(CFG1_OUT_LDFLAGS) -o $(CFG1_OUT) \
+						$(START_OBJS) cfg1_out.o $(END_OBJS)
+	$(NM) -n $(CFG1_OUT) > cfg1_out.syms
+	$(OBJCOPY) -O srec -S $(CFG1_OUT) cfg1_out.srec
+	$(CFG) --pass 2 --kernel asp $(INCLUDES) \
+				-T $(TARGETDIR)/target.tf $(CFG_TABS) $<
+	touch -r kernel_cfg.c kernel_cfg.timestamp
+
+#
+#  ã«ã¼ãã«ã©ã¤ãã©ãªãã¡ã¤ã«ã®çæ
+#
+$(KERNEL_LIB)/libkernel.a: $(OFFSET_H) $(KERNEL_LIB_OBJS)
+	rm -f libkernel.a
+	$(AR) -rcs $(KERNEL_LIB)/libkernel.a $(KERNEL_LIB_OBJS)
+	$(RANLIB) $(KERNEL_LIB)/libkernel.a
+
+#
+#  ç¹å¥ãªä¾å­é¢ä¿ã®å®ç¾©
+#
+banner.o: kernel_cfg.timestamp $(filter-out banner.o,$(ALL_OBJS)) $(LIBS_DEP)
+
+#
+#  å
+¨ä½ã®ãªã³ã¯
+#
+$(OBJFILE): $(APPL_CFG) kernel_cfg.timestamp $(ALL_OBJS) $(LIBS_DEP)
+	$(LINK) $(CFLAGS) $(LDFLAGS) -o $(OBJFILE) $(START_OBJS) \
+			$(APPL_OBJS) $(SYSSVC_OBJS) $(CFG_OBJS) $(ALL_LIBS) $(END_OBJS)
+	$(NM) -n $(OBJFILE) > $(OBJNAME).syms
+	$(OBJCOPY) -O srec -S $(OBJFILE) $(OBJNAME).srec
+	$(CFG) --pass 3 --kernel asp $(INCLUDES) \
+				--rom-image $(OBJNAME).srec --symbol-table $(OBJNAME).syms \
+				-T $(TARGETDIR)/target_check.tf $(CFG_TABS) $<
+
+#
+#  ãã¤ããªãã¡ã¤ã«ã®çæ
+#
+$(OBJNAME).bin: $(OBJFILE)
+	$(OBJCOPY) -O binary -S $(OBJFILE) $(OBJNAME).bin
+
+#
+#  Sã¬ã³ã¼ããã¡ã¤ã«ã®çæ
+#
+$(OBJNAME).srec: $(OBJFILE)
+	$(OBJCOPY) -O srec -S $(OBJFILE) $(OBJNAME).srec
+
+#
+#  ã³ã³ãã¤ã«çµæã®æ¶å»
+#
+.PHONY: clean
+clean:
+	rm -f \#* *~ *.o $(CLEAN_FILES)
+	rm -f $(OBJFILE) $(OBJNAME).syms $(OBJNAME).srec $(OBJNAME).bin
+	rm -f kernel_cfg.timestamp $(CFG2_OUT_SRCS)
+	rm -f cfg1_out.c $(CFG1_OUT) cfg1_out.syms cfg1_out.srec
+ifndef KERNEL_LIB
+	rm -f libkernel.a
+endif
+	rm -f makeoffset.s offset.h
+
+.PHONY: cleankernel
+cleankernel:
+	rm -rf $(KERNEL_LIB_OBJS)
+	rm -f makeoffset.s offset.h
+
+.PHONY: cleandep
+cleandep:
+	if ! [ -f Makefile.depend ]; then \
+		rm -f kernel_cfg.timestamp $(CFG2_OUT_SRCS); \
+		rm -f cfg1_out.c cfg1_out.o $(CFG1_OUT) cfg1_out.syms cfg1_out.srec; \
+		rm -f makeoffset.s offset.h; \
+	fi
+	rm -f Makefile.depend
+
+.PHONY: realclean
+realclean: cleandep clean
+	rm -f $(REALCLEAN_FILES)
+
+#
+#  ã³ã³ãã£ã®ã¥ã¬ã¼ã¿ãçæãããã¡ã¤ã«ã®ã³ã³ãã¤ã«ã«ã¼ã«ã¨ä¾å­é¢ä¿ä½æ
+#  ã«ã¼ã«ã®å®ç¾©
+#
+#  ã³ã³ãã£ã®ã¥ã¬ã¼ã¿ãçæãããã¡ã¤ã«ã¯ï¼ã¢ããªã±ã¼ã·ã§ã³ãã­ã°ã©ã ç¨ï¼
+#  ã·ã¹ãã ãµã¼ãã¹ç¨ï¼ã«ã¼ãã«ç¨ã®ãã¹ã¦ã®ãªãã·ã§ã³ãä»ãã¦ã³ã³ãã¤ã«
+#  ããï¼
+#
+ALL_CFG_COBJS = $(CFG_COBJS) cfg1_out.o
+ALL_CFG_ASMOBJS = $(CFG_ASMOBJS)
+CFG_CFLAGS = $(APPL_CFLAGS) $(SYSSVC_CFLAGS) $(KERNEL_CFLAGS)
+
+$(ALL_CFG_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(CFG_CFLAGS) $<
+
+$(ALL_CFG_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(CFG_CFLAGS) $<
+
+$(ALL_CFG_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(CFG_CFLAGS)" $< >> Makefile.depend
+
+$(ALL_CFG_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(CFG_CFLAGS) $<
+
+$(ALL_CFG_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(CFG_CFLAGS)" $< >> Makefile.depend
+
+#
+#  ç¹æ®ãªä¾å­é¢ä¿ä½æã«ã¼ã«ã®å®ç¾©
+#
+cfg1_out.depend: $(APPL_CFG)
+	@$(CFG) -M cfg1_out.c $(INCLUDES) $< >> Makefile.depend
+
+makeoffset.d: makeoffset.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-T "makeoffset.s" -O "$(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+#
+#  ä¾å­é¢ä¿ãã¡ã¤ã«ã®çæ
+#
+.PHONY: gendepend
+gendepend:
+	@echo "Generating Makefile.depend."
+
+.PHONY: depend
+ifdef KERNEL_LIB
+depend: cleandep kernel_cfg.timestamp gendepend \
+		cfg1_out.depend cfg1_out.d \
+		$(ALL_OBJS:.o=.d)
+else
+depend: cleandep $(OFFSET_H) kernel_cfg.timestamp gendepend \
+		cfg1_out.depend cfg1_out.d \
+		$(KERNEL_AUX_COBJS:.o=.d) $(KERNEL_ASMOBJS:.o=.d) \
+		$(KERNEL_COBJS:.o=.d) $(KERNEL_LCSRCS:.c=.d) $(ALL_OBJS:.o=.d)
+endif
+
+#
+#  ä¾å­é¢ä¿ãã¡ã¤ã«ãã¤ã³ã¯ã«ã¼ã
+#
+-include Makefile.depend
+
+#
+#  éçºãã¼ã«ã®ã³ãã³ãåã®å®ç¾©
+#
+ifeq ($(TOOL),gcc)
+  #
+  #  GNUéçºç°å¢ç¨
+  #
+  ifdef GCC_TARGET
+    GCC_TARGET_PREFIX = $(GCC_TARGET)-
+  else
+    GCC_TARGET_PREFIX =
+  endif
+  CC = $(GCC_TARGET_PREFIX)gcc
+  CXX = $(GCC_TARGET_PREFIX)g++
+  AS = $(GCC_TARGET_PREFIX)as
+  LD = $(GCC_TARGET_PREFIX)ld
+  AR = $(GCC_TARGET_PREFIX)ar
+  NM = $(GCC_TARGET_PREFIX)nm
+  RANLIB = $(GCC_TARGET_PREFIX)ranlib
+  OBJCOPY = $(GCC_TARGET_PREFIX)objcopy
+  OBJDUMP = $(GCC_TARGET_PREFIX)objdump
+endif
+
+ifdef USE_CXX
+  LINK = $(CXX)
+else
+  LINK = $(CC)
+endif
+
+#
+#  ã³ã³ãã¤ã«ã«ã¼ã«ã®å®ç¾©
+#
+KERNEL_ALL_COBJS = $(KERNEL_COBJS) $(KERNEL_AUX_COBJS)
+
+$(KERNEL_ALL_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_ALL_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_LCOBJS): %.o:
+	$(CC) -DTOPPERS_$(*F) -o $@ -c $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_LCOBJS:.o=.s): %.s:
+	$(CC) -DTOPPERS_$(*F) -o $@ -S $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(SYSSVC_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(SYSSVC_CFLAGS) $<
+
+$(SYSSVC_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(SYSSVC_CFLAGS) $<
+
+$(SYSSVC_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(SYSSVC_CFLAGS) $<
+
+$(APPL_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_CXXOBJS): %.o: %.cpp
+	$(CXX) -c $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_CXXOBJS:.o=.s): %.s: %.cpp
+	$(CXX) -S $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(APPL_CFLAGS) $<
+
+#
+#  ä¾å­é¢ä¿ä½æã«ã¼ã«ã®å®ç¾©
+#
+$(KERNEL_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+$(KERNEL_LCSRCS:.c=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) -T "$($*)" \
+		-O "-DALLFUNC $(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+$(KERNEL_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+$(SYSSVC_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(SYSSVC_CFLAGS)" $< >> Makefile.depend
+
+$(SYSSVC_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(SYSSVC_CFLAGS)" $< >> Makefile.depend
+
+$(APPL_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(APPL_CFLAGS)" $< >> Makefile.depend
+
+$(APPL_CXXOBJS:.o=.d): %.d: %.cpp
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CXX) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(APPL_CFLAGS)" $< >> Makefile.depend
+
+$(APPL_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(APPL_CFLAGS)" $< >> Makefile.depend
+
+#
+#  ããã©ã«ãã³ã³ãã¤ã«ã«ã¼ã«ãä¸æ¸ã
+#
+%.o: %.c
+	@echo "*** Default compile rules should not be used."
+	$(CC) -c $(CFLAGS) $<
+
+%.s: %.c
+	@echo "*** Default compile rules should not be used."
+	$(CC) -S $(CFLAGS) $<
+
+%.o: %.cpp
+	@echo "*** Default compile rules should not be used."
+	$(CXX) -c $(CFLAGS) $<
+
+%.s: %.cpp
+	@echo "*** Default compile rules should not be used."
+	$(CXX) -S $(CFLAGS) $<
+
+%.o: %.S
+	@echo "*** Default compile rules should not be used."
+	$(CC) -c $(CFLAGS) $<
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/MON/sample1.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/MON/sample1.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/MON/sample1.c	(revision 453)
@@ -0,0 +1,541 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2012 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *  サンプルプログラム(1)の本体
+ *
+ *  ASPカーネルの基本的な動作を確認するためのサンプルプログラム．
+ *
+ *  プログラムの概要:
+ *
+ *  ユーザインタフェースを受け持つメインタスク（タスクID: MAIN_TASK，優
+ *  先度: MAIN_PRIORITY）と，3つの並行実行されるタスク（タスクID:
+ *  TASK1～TASK3，初期優先度: MID_PRIORITY）で構成される．また，起動周
+ *  期が2秒の周期ハンドラ（周期ハンドラID: CYCHDR1）を用いる．
+ *
+ *  並行実行されるタスクは，task_loop回空ループを実行する度に，タスクが
+ *  実行中であることをあらわすメッセージを表示する．空ループを実行する
+ *  のは，空ループなしでメッセージを出力すると，多量のメッセージが出力
+ *  され，プログラムの動作が確認しずらくなるためである．また，低速なシ
+ *  リアルポートを用いてメッセージを出力する場合に，すべてのメッセージ
+ *  が出力できるように，メッセージの量を制限するという理由もある．
+ *
+ *  周期ハンドラは，三つの優先度（HIGH_PRIORITY，MID_PRIORITY，
+ *  LOW_PRIORITY）のレディキューを回転させる．プログラムの起動直後は，
+ *  周期ハンドラは停止状態になっている．
+ *
+ *  メインタスクは，シリアルI/Oポートからの文字入力を行い（文字入力を
+ *  待っている間は，並行実行されるタスクが実行されている），入力された
+ *  文字に対応した処理を実行する．入力された文字と処理の関係は次の通り．
+ *  Control-Cまたは'Q'が入力されると，プログラムを終了する．
+ *
+ *  '1' : 対象タスクをTASK1に切り換える（初期設定）．
+ *  '2' : 対象タスクをTASK2に切り換える．
+ *  '3' : 対象タスクをTASK3に切り換える．
+ *  'a' : 対象タスクをact_tskにより起動する．
+ *  'A' : 対象タスクに対する起動要求をcan_actによりキャンセルする．
+ *  'e' : 対象タスクにext_tskを呼び出させ，終了させる．
+ *  't' : 対象タスクをter_tskにより強制終了する．
+ *  '>' : 対象タスクの優先度をHIGH_PRIORITYにする．
+ *  '=' : 対象タスクの優先度をMID_PRIORITYにする．
+ *  '<' : 対象タスクの優先度をLOW_PRIORITYにする．
+ *  'G' : 対象タスクの優先度をget_priで読み出す．
+ *  's' : 対象タスクにslp_tskを呼び出させ，起床待ちにさせる．
+ *  'S' : 対象タスクにtslp_tsk(10秒)を呼び出させ，起床待ちにさせる．
+ *  'w' : 対象タスクをwup_tskにより起床する．
+ *  'W' : 対象タスクに対する起床要求をcan_wupによりキャンセルする．
+ *  'l' : 対象タスクをrel_waiにより強制的に待ち解除にする．
+ *  'u' : 対象タスクをsus_tskにより強制待ち状態にする．
+ *  'm' : 対象タスクの強制待ち状態をrsm_tskにより解除する．
+ *  'd' : 対象タスクにdly_tsk(10秒)を呼び出させ，時間経過待ちにさせる．
+ *  'x' : 対象タスクに例外パターン0x0001の例外処理を要求する．
+ *  'X' : 対象タスクに例外パターン0x0002の例外処理を要求する．
+ *  'y' : 対象タスクにdis_texを呼び出させ，タスク例外を禁止する．
+ *  'Y' : 対象タスクにena_texを呼び出させ，タスク例外を許可する．
+ *  'r' : 3つの優先度（HIGH_PRIORITY，MID_PRIORITY，LOW_PRIORITY）のレ
+ *        ディキューを回転させる．
+ *  'c' : 周期ハンドラを動作開始させる．
+ *  'C' : 周期ハンドラを動作停止させる．
+ *  'b' : アラームハンドラを5秒後に起動するよう動作開始させる．
+ *  'B' : アラームハンドラを動作停止させる．
+ *  'z' : 対象タスクにCPU例外を発生させる（タスクを終了させる）．
+ *  'Z' : 対象タスクにCPUロック状態でCPU例外を発生させる（プログラムを
+ *        終了する）．
+ *  'V' : get_utmで性能評価用システム時刻を2回読む．
+ *  'v' : 発行したシステムコールを表示する（デフォルト）．
+ *  'q' : 発行したシステムコールを表示しない．
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#include "kernel_cfg.h"
+#include "sample1.h"
+
+/*
+ *  サービスコールのエラーのログ出力
+ */
+Inline void
+svc_perror(const char *file, int_t line, const char *expr, ER ercd)
+{
+	if (ercd < 0) {
+		t_perror(LOG_ERROR, file, line, expr, ercd);
+	}
+}
+
+#define	SVC_PERROR(expr)	svc_perror(__FILE__, __LINE__, #expr, (expr))
+
+/*
+ *  並行実行されるタスクへのメッセージ領域
+ */
+char	message[3];
+
+/*
+ *  ループ回数
+ */
+ulong_t	task_loop;		/* タスク内でのループ回数 */
+ulong_t	tex_loop;		/* 例外処理ルーチン内でのループ回数 */
+
+/*
+ *  並行実行されるタスク
+ */
+void task(intptr_t exinf)
+{
+	volatile ulong_t	i;
+	int_t		n = 0;
+	int_t		tskno = (int_t) exinf;
+	const char	*graph[] = { "|", "  +", "    *" };
+	char		c;
+
+	SVC_PERROR(ena_tex());
+	while (true) {
+		syslog(LOG_NOTICE, "task%d is running (%03d).   %s",
+										tskno, ++n, graph[tskno-1]);
+		for (i = 0; i < task_loop; i++);
+		c = message[tskno-1];
+		message[tskno-1] = 0;
+		switch (c) {
+		case 'e':
+			syslog(LOG_INFO, "#%d#ext_tsk()", tskno);
+			SVC_PERROR(ext_tsk());
+			assert(0);
+		case 's':
+			syslog(LOG_INFO, "#%d#slp_tsk()", tskno);
+			SVC_PERROR(slp_tsk());
+			break;
+		case 'S':
+			syslog(LOG_INFO, "#%d#tslp_tsk(10000)", tskno);
+			SVC_PERROR(tslp_tsk(10000));
+			break;
+		case 'd':
+			syslog(LOG_INFO, "#%d#dly_tsk(10000)", tskno);
+			SVC_PERROR(dly_tsk(10000));
+			break;
+		case 'y':
+			syslog(LOG_INFO, "#%d#dis_tex()", tskno);
+			SVC_PERROR(dis_tex());
+			break;
+		case 'Y':
+			syslog(LOG_INFO, "#%d#ena_tex()", tskno);
+			SVC_PERROR(ena_tex());
+			break;
+#ifdef CPUEXC1
+		case 'z':
+			syslog(LOG_NOTICE, "#%d#raise CPU exception", tskno);
+			RAISE_CPU_EXCEPTION;
+			break;
+		case 'Z':
+			SVC_PERROR(loc_cpu());
+			syslog(LOG_NOTICE, "#%d#raise CPU exception", tskno);
+			RAISE_CPU_EXCEPTION;
+			SVC_PERROR(unl_cpu());
+			break;
+#endif /* CPUEXC1 */
+		default:
+			break;
+		}
+	}
+}
+
+/*
+ *  並行して実行されるタスク用のタスク例外処理ルーチン
+ */
+void tex_routine(TEXPTN texptn, intptr_t exinf)
+{
+	volatile ulong_t	i;
+	int_t	tskno = (int_t) exinf;
+
+	syslog(LOG_NOTICE, "task%d receives exception 0x%04x.", tskno, texptn);
+	for (i = 0; i < tex_loop; i++);
+
+	if ((texptn & 0x8000U) != 0U) {
+		syslog(LOG_INFO, "#%d#ext_tsk()", tskno);
+		SVC_PERROR(ext_tsk());
+		assert(0);
+	}
+}
+
+/*
+ *  CPU例外ハンドラ
+ */
+#ifdef CPUEXC1
+
+void
+cpuexc_handler(void *p_excinf)
+{
+	ID		tskid;
+
+	syslog(LOG_NOTICE, "CPU exception handler (p_excinf = %08p).", p_excinf);
+	if (sns_ctx() != true) {
+		syslog(LOG_WARNING,
+					"sns_ctx() is not true in CPU exception handler.");
+	}
+	if (sns_dpn() != true) {
+		syslog(LOG_WARNING,
+					"sns_dpn() is not true in CPU exception handler.");
+	}
+	syslog(LOG_INFO, "sns_loc = %d sns_dsp = %d sns_tex = %d",
+									sns_loc(), sns_dsp(), sns_tex());
+	syslog(LOG_INFO, "xsns_dpn = %d xsns_xpn = %d",
+									xsns_dpn(p_excinf), xsns_xpn(p_excinf));
+
+	if (xsns_xpn(p_excinf)) {
+		syslog(LOG_NOTICE, "Sample program ends with exception.");
+		SVC_PERROR(ext_ker());
+		assert(0);
+	}
+
+	SVC_PERROR(iget_tid(&tskid));
+	SVC_PERROR(iras_tex(tskid, 0x8000U));
+}
+
+#endif /* CPUEXC1 */
+
+/*
+ *  周期ハンドラ
+ *
+ *  HIGH_PRIORITY，MID_PRIORITY，LOW_PRIORITY の各優先度のレディキュー
+ *  を回転させる．
+ */
+void cyclic_handler(intptr_t exinf)
+{
+	SVC_PERROR(irot_rdq(HIGH_PRIORITY));
+	SVC_PERROR(irot_rdq(MID_PRIORITY));
+	SVC_PERROR(irot_rdq(LOW_PRIORITY));
+}
+
+/*
+ *  アラームハンドラ
+ *
+ *  HIGH_PRIORITY，MID_PRIORITY，LOW_PRIORITY の各優先度のレディキュー
+ *  を回転させる．
+ */
+void alarm_handler(intptr_t exinf)
+{
+	SVC_PERROR(irot_rdq(HIGH_PRIORITY));
+	SVC_PERROR(irot_rdq(MID_PRIORITY));
+	SVC_PERROR(irot_rdq(LOW_PRIORITY));
+}
+
+/*
+ *  メインタスク
+ */
+void main_task(intptr_t exinf)
+{
+	char	c;
+	ID		tskid = TASK1;
+	int_t	tskno = 1;
+	ER_UINT	ercd;
+	PRI		tskpri;
+#ifndef TASK_LOOP
+	volatile ulong_t	i;
+	SYSTIM	stime1, stime2;
+#endif /* TASK_LOOP */
+#ifdef TOPPERS_SUPPORT_GET_UTM
+	SYSUTM	utime1, utime2;
+#endif /* TOPPERS_SUPPORT_GET_UTM */
+
+	SVC_PERROR(syslog_msk_log(LOG_UPTO(LOG_INFO), LOG_UPTO(LOG_EMERG)));
+	syslog(LOG_NOTICE, "Sample program starts (exinf = %d).", (int_t) exinf);
+
+	/*
+	 *  シリアルポートの初期化
+	 *
+	 *  システムログタスクと同じシリアルポートを使う場合など，シリアル
+	 *  ポートがオープン済みの場合にはここでE_OBJエラーになるが，支障は
+	 *  ない．
+	 */
+	ercd = serial_opn_por(TASK_PORTID);
+	if (ercd < 0 && MERCD(ercd) != E_OBJ) {
+		syslog(LOG_ERROR, "%s (%d) reported by `serial_opn_por'.",
+									itron_strerror(ercd), SERCD(ercd));
+	}
+	SVC_PERROR(serial_ctl_por(TASK_PORTID,
+							(IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV)));
+
+	/*
+ 	 *  ループ回数の設定
+	 *
+	 *  並行実行されるタスク内での空ループの回数（task_loop）は，空ルー
+	 *  プの実行時間が約0.4秒になるように設定する．この設定のために，
+	 *  LOOP_REF回の空ループの実行時間を，その前後でget_timを呼ぶことで
+	 *  測定し，その測定結果から空ループの実行時間が0.4秒になるループ回
+	 *  数を求め，task_loopに設定する．
+	 *
+	 *  LOOP_REFは，デフォルトでは1,000,000に設定しているが，想定したよ
+	 *  り遅いプロセッサでは，サンプルプログラムの実行開始に時間がかか
+	 *  りすぎるという問題を生じる．逆に想定したより速いプロセッサでは，
+	 *  LOOP_REF回の空ループの実行時間が短くなり，task_loopに設定する値
+	 *  の誤差が大きくなるという問題がある．
+	 *
+	 *  そこで，そのようなターゲットでは，target_test.hで，LOOP_REFを適
+	 *  切な値に定義するのが望ましい．
+	 *
+	 *  また，task_loopの値を固定したい場合には，その値をTASK_LOOPにマ
+	 *  クロ定義する．TASK_LOOPがマクロ定義されている場合，上記の測定を
+	 *  行わずに，TASK_LOOPに定義された値を空ループの回数とする．
+	 *
+	 * ターゲットによっては，空ループの実行時間の1回目の測定で，本来よ
+	 * りも長めになるものがある．このようなターゲットでは，MEASURE_TWICE
+	 * をマクロ定義することで，1回目の測定結果を捨てて，2回目の測定結果
+	 * を使う．
+	 *
+	 *  タスク例外処理ルーチン内での空ループの回数（tex_loop）は，
+	 *  task_loopの4分の1の値（空ループの実行時間が0.1秒になるループ回
+	 *  数）に設定する．
+	 */
+#ifdef TASK_LOOP
+	task_loop = TASK_LOOP;
+#else /* TASK_LOOP */
+
+#ifdef MEASURE_TWICE
+	task_loop = LOOP_REF;
+	SVC_PERROR(get_tim(&stime1));
+	for (i = 0; i < task_loop; i++);
+	SVC_PERROR(get_tim(&stime2));
+#endif /* MEASURE_TWICE */
+
+	task_loop = LOOP_REF;
+	SVC_PERROR(get_tim(&stime1));
+	for (i = 0; i < task_loop; i++);
+	SVC_PERROR(get_tim(&stime2));
+	task_loop = LOOP_REF * 400UL / (stime2 - stime1);
+
+#endif /* TASK_LOOP */
+	tex_loop = task_loop / 4;
+
+	/*
+ 	 *  タスクの起動
+	 */
+	SVC_PERROR(act_tsk(TASK1));
+	SVC_PERROR(act_tsk(TASK2));
+	SVC_PERROR(act_tsk(TASK3));
+
+	/*
+ 	 *  メインループ
+	 */
+	do {
+#ifndef USE_CUPCOMMAND
+		SVC_PERROR(serial_rea_dat(TASK_PORTID, &c, 1));
+#else
+		do{
+			c = get_cup_command();
+			dly_tsk(10);
+		}while(c == 0);
+#endif
+		switch (c) {
+		case 'e':
+		case 's':
+		case 'S':
+		case 'd':
+		case 'y':
+		case 'Y':
+		case 'z':
+		case 'Z':
+			message[tskno-1] = c;
+			break;
+		case '1':
+			tskno = 1;
+			tskid = TASK1;
+			break;
+		case '2':
+			tskno = 2;
+			tskid = TASK2;
+			break;
+		case '3':
+			tskno = 3;
+			tskid = TASK3;
+			break;
+		case 'a':
+			syslog(LOG_INFO, "#act_tsk(%d)", tskno);
+			SVC_PERROR(act_tsk(tskid));
+			break;
+		case 'A':
+			syslog(LOG_INFO, "#can_act(%d)", tskno);
+			SVC_PERROR(ercd = can_act(tskid));
+			if (ercd >= 0) {
+				syslog(LOG_NOTICE, "can_act(%d) returns %d", tskno, ercd);
+			}
+			break;
+		case 't':
+			syslog(LOG_INFO, "#ter_tsk(%d)", tskno);
+			SVC_PERROR(ter_tsk(tskid));
+			break;
+		case '>':
+			syslog(LOG_INFO, "#chg_pri(%d, HIGH_PRIORITY)", tskno);
+			SVC_PERROR(chg_pri(tskid, HIGH_PRIORITY));
+			break;
+		case '=':
+			syslog(LOG_INFO, "#chg_pri(%d, MID_PRIORITY)", tskno);
+			SVC_PERROR(chg_pri(tskid, MID_PRIORITY));
+			break;
+		case '<':
+			syslog(LOG_INFO, "#chg_pri(%d, LOW_PRIORITY)", tskno);
+			SVC_PERROR(chg_pri(tskid, LOW_PRIORITY));
+			break;
+		case 'G':
+			syslog(LOG_INFO, "#get_pri(%d, &tskpri)", tskno);
+			SVC_PERROR(ercd = get_pri(tskid, &tskpri));
+			if (ercd >= 0) {
+				syslog(LOG_NOTICE, "priority of task %d is %d", tskno, tskpri);
+			}
+			break;
+		case 'w':
+			syslog(LOG_INFO, "#wup_tsk(%d)", tskno);
+			SVC_PERROR(wup_tsk(tskid));
+			break;
+		case 'W':
+			syslog(LOG_INFO, "#can_wup(%d)", tskno);
+			SVC_PERROR(ercd = can_wup(tskid));
+			if (ercd >= 0) {
+				syslog(LOG_NOTICE, "can_wup(%d) returns %d", tskno, ercd);
+			}
+			break;
+		case 'l':
+			syslog(LOG_INFO, "#rel_wai(%d)", tskno);
+			SVC_PERROR(rel_wai(tskid));
+			break;
+		case 'u':
+			syslog(LOG_INFO, "#sus_tsk(%d)", tskno);
+			SVC_PERROR(sus_tsk(tskid));
+			break;
+		case 'm':
+			syslog(LOG_INFO, "#rsm_tsk(%d)", tskno);
+			SVC_PERROR(rsm_tsk(tskid));
+			break;
+		case 'x':
+			syslog(LOG_INFO, "#ras_tex(%d, 0x0001U)", tskno);
+			SVC_PERROR(ras_tex(tskid, 0x0001U));
+			break;
+		case 'X':
+			syslog(LOG_INFO, "#ras_tex(%d, 0x0002U)", tskno);
+			SVC_PERROR(ras_tex(tskid, 0x0002U));
+			break;
+		case 'r':
+			syslog(LOG_INFO, "#rot_rdq(three priorities)");
+			SVC_PERROR(rot_rdq(HIGH_PRIORITY));
+			SVC_PERROR(rot_rdq(MID_PRIORITY));
+			SVC_PERROR(rot_rdq(LOW_PRIORITY));
+			break;
+		case 'c':
+			syslog(LOG_INFO, "#sta_cyc(1)");
+			SVC_PERROR(sta_cyc(CYCHDR1));
+			break;
+		case 'C':
+			syslog(LOG_INFO, "#stp_cyc(1)");
+			SVC_PERROR(stp_cyc(CYCHDR1));
+			break;
+		case 'b':
+			syslog(LOG_INFO, "#sta_alm(1, 5000)");
+			SVC_PERROR(sta_alm(ALMHDR1, 5000));
+			break;
+		case 'B':
+			syslog(LOG_INFO, "#stp_alm(1)");
+			SVC_PERROR(stp_alm(ALMHDR1));
+			break;
+
+		case 'V':
+#ifdef TOPPERS_SUPPORT_GET_UTM
+			SVC_PERROR(get_utm(&utime1));
+			SVC_PERROR(get_utm(&utime2));
+			syslog(LOG_NOTICE, "utime1 = %ld, utime2 = %ld",
+										(ulong_t) utime1, (ulong_t) utime2);
+#else /* TOPPERS_SUPPORT_GET_UTM */
+			syslog(LOG_NOTICE, "get_utm is not supported.");
+#endif /* TOPPERS_SUPPORT_GET_UTM */
+			break;
+
+		case 'v':
+			SVC_PERROR(syslog_msk_log(LOG_UPTO(LOG_INFO),
+										LOG_UPTO(LOG_EMERG)));
+			break;
+		case 'q':
+			SVC_PERROR(syslog_msk_log(LOG_UPTO(LOG_NOTICE),
+										LOG_UPTO(LOG_EMERG)));
+			break;
+
+#ifdef BIT_KERNEL
+		case ' ':
+			SVC_PERROR(loc_cpu());
+			{
+				extern ER	bit_kernel(void);
+
+				SVC_PERROR(ercd = bit_kernel());
+				if (ercd >= 0) {
+					syslog(LOG_NOTICE, "bit_kernel passed.");
+				}
+			}
+			SVC_PERROR(unl_cpu());
+			break;
+#endif /* BIT_KERNEL */
+
+		default:
+			break;
+		}
+	} while (c != '\003' && c != 'Q');
+
+	syslog(LOG_NOTICE, "Sample program ends.");
+	SVC_PERROR(ext_ker());
+	assert(0);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/MON/sample1.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/MON/sample1.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/MON/sample1.cfg	(revision 453)
@@ -0,0 +1,32 @@
+/*
+ *  $Id$
+ */
+
+/*
+ *  サンプルプログラム(1)のシステムコンフィギュレーションファイル
+ */
+INCLUDE("target_timer.cfg");
+INCLUDE("syssvc/syslog.cfg");
+INCLUDE("syssvc/banner.cfg");
+INCLUDE("syssvc/serial.cfg");
+INCLUDE("syssvc/logtask.cfg");
+INCLUDE("pdic/k210/device.cfg");
+INCLUDE("monitor/monitor.cfg");
+
+#include "sample1.h"
+
+ATT_INI({ TA_NULL, 0, rtc_init });
+ATT_INI({ TA_NULL, 0, rtc_info_init });
+
+CRE_TSK(TASK1, { TA_NULL, 1, task, MID_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK2, { TA_NULL, 2, task, MID_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK3, { TA_NULL, 3, task, MID_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(MAIN_TASK, { TA_NULL, 0, main_task, MAIN_PRIORITY, STACK_SIZE, NULL });
+DEF_TEX(TASK1, { TA_NULL, tex_routine });
+DEF_TEX(TASK2, { TA_NULL, tex_routine });
+DEF_TEX(TASK3, { TA_NULL, tex_routine });
+CRE_CYC(CYCHDR1, { TA_NULL, 0, cyclic_handler, 2000, 0 });
+CRE_ALM(ALMHDR1, { TA_NULL, 0, alarm_handler });
+#ifdef CPUEXC1
+DEF_EXC(CPUEXC1, { TA_NULL, cpuexc_handler });
+#endif /* CPUEXC1 */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/MON/sample1.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/MON/sample1.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/MON/sample1.h	(revision 453)
@@ -0,0 +1,94 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ *
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ *
+ *  $Id$
+ */
+
+/*
+ *		サンプルプログラム(1)のヘッダファイル
+ */
+
+/*
+ *  ターゲット依存の定義
+ */
+#include "target_test.h"
+
+/*
+ *  各タスクの優先度の定義
+ */
+
+#define MAIN_PRIORITY	5		/* メインタスクの優先度 */
+								/* HIGH_PRIORITYより高くすること */
+
+#define HIGH_PRIORITY	9		/* 並行実行されるタスクの優先度 */
+#define MID_PRIORITY	10
+#define LOW_PRIORITY	11
+
+/*
+ *  ターゲットに依存する可能性のある定数の定義
+ */
+
+#ifndef TASK_PORTID
+#define	TASK_PORTID		1			/* 文字入力するシリアルポートID */
+#endif /* TASK_PORTID */
+
+#ifndef STACK_SIZE
+#define	STACK_SIZE		4096		/* タスクのスタックサイズ */
+#endif /* STACK_SIZE */
+
+#ifndef LOOP_REF
+#define LOOP_REF		ULONG_C(1000000)	/* 速度計測用のループ回数 */
+#endif /* LOOP_REF */
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+#ifndef TOPPERS_MACRO_ONLY
+
+extern void	task(intptr_t exinf);
+extern void	main_task(intptr_t exinf);
+extern void	tex_routine(TEXPTN texptn, intptr_t exinf);
+#ifdef CPUEXC1
+extern void	cpuexc_handler(void *p_excinf);
+#endif /* CPUEXC1 */
+extern void	cyclic_handler(intptr_t exinf);
+extern void	alarm_handler(intptr_t exinf);
+extern int8_t get_cup_command(void);
+
+#endif /* TOPPERS_MACRO_ONLY */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/SDCARD/Makefile
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/SDCARD/Makefile	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/SDCARD/Makefile	(revision 453)
@@ -0,0 +1,602 @@
+#
+#  TOPPERS/ASP Kernel
+#      Toyohashi Open Platform for Embedded Real-Time Systems/
+#      Advanced Standard Profile Kernel
+# 
+#  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                              Toyohashi Univ. of Technology, JAPAN
+#  Copyright (C) 2006-2014 by Embedded and Real-Time Systems Laboratory
+#              Graduate School of Information Science, Nagoya Univ., JAPAN
+# 
+#  ä¸è¨èä½æ¨©è
+ã¯ï¼ä»¥ä¸ã®(1)ï½(4)ã®æ¡ä»¶ãæºããå ´åã«éãï¼æ¬ã½ããã¦ã§
+#  ã¢ï¼æ¬ã½ããã¦ã§ã¢ãæ¹å¤ãããã®ãå«ãï¼ä»¥ä¸åãï¼ãä½¿ç¨ã»è¤è£½ã»æ¹
+#  å¤ã»åé
+å¸ï¼ä»¥ä¸ï¼å©ç¨ã¨å¼ã¶ï¼ãããã¨ãç¡åã§è¨±è«¾ããï¼
+#  (1) æ¬ã½ããã¦ã§ã¢ãã½ã¼ã¹ã³ã¼ãã®å½¢ã§å©ç¨ããå ´åã«ã¯ï¼ä¸è¨ã®èä½
+#      æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãï¼ãã®ã¾ã¾ã®å½¢ã§ã½ã¼
+#      ã¹ã³ã¼ãä¸­ã«å«ã¾ãã¦ãããã¨ï¼
+#  (2) æ¬ã½ããã¦ã§ã¢ãï¼ã©ã¤ãã©ãªå½¢å¼ãªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨
+#      è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®èä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨
+#      ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#  (3) æ¬ã½ããã¦ã§ã¢ãï¼æ©å¨ã«çµã¿è¾¼ããªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããªãå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼æ¬¡ã®ããããã®æ¡ä»¶ãæºããã
+#      ã¨ï¼
+#    (a) åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®è
+#        ä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#    (b) åé
+å¸ã®å½¢æ
+ãï¼å¥ã«å®ããæ¹æ³ã«ãã£ã¦ï¼TOPPERSãã­ã¸ã§ã¯ãã«
+#        å ±åãããã¨ï¼
+#  (4) æ¬ã½ããã¦ã§ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæ
+#      å®³ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ããå
+è²¬ãããã¨ï¼
+#      ã¾ãï¼æ¬ã½ããã¦ã§ã¢ã®ã¦ã¼ã¶ã¾ãã¯ã¨ã³ãã¦ã¼ã¶ããã®ãããªãç
+#      ç±ã«åºã¥ãè«æ±ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ãã
+#      å
+è²¬ãããã¨ï¼
+# 
+#  æ¬ã½ããã¦ã§ã¢ã¯ï¼ç¡ä¿è¨¼ã§æä¾ããã¦ãããã®ã§ããï¼ä¸è¨èä½æ¨©è
+ã
+#  ãã³TOPPERSãã­ã¸ã§ã¯ãã¯ï¼æ¬ã½ããã¦ã§ã¢ã«é¢ãã¦ï¼ç¹å®ã®ä½¿ç¨ç®ç
+#  ã«å¯¾ããé©åæ§ãå«ãã¦ï¼ãããªãä¿è¨¼ãè¡ããªãï¼ã¾ãï¼æ¬ã½ããã¦ã§
+#  ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæå®³ã«é¢ãã¦ãï¼ã
+#  ã®è²¬ä»»ãè² ããªãï¼
+# 
+#  $Id$
+# 
+
+#
+#  ã¿ã¼ã²ããã®æå®ï¼Makefile.targetã§ä¸æ¸ããããã®ãé²ãããï¼
+#
+all:
+
+#
+#  ã¿ã¼ã²ããç¥ç§°ã®å®ç¾©
+#
+TARGET = k210_gcc
+
+#
+#  ãã­ã°ã©ãã³ã°è¨èªã®å®ç¾©
+#
+SRCLANG = c
+ifeq ($(SRCLANG),c)
+  LIBS = -lc -lm
+endif
+ifeq ($(SRCLANG),c++)
+  USE_CXX = true
+  CXXLIBS = -lstdc++ -lm -lc
+  CXXRTS = cxxrt.o newlibrt.o
+endif
+
+#
+#  ã½ã¼ã¹ãã¡ã¤ã«ã®ãã£ã¬ã¯ããªã®å®ç¾©
+#
+SRCDIR = ../../..
+
+#
+#  ãªãã¸ã§ã¯ããã¡ã¤ã«åã®æ¡å¼µå­ã®è¨­å®
+#
+OBJEXT = exe
+
+#
+#  å®è¡ç°å¢ã®å®ç¾©ï¼ã¿ã¼ã²ããä¾å­ã«ä¸æ¸ããããå ´åãããï¼
+#
+DBGENV := 
+
+#
+#  ã«ã¼ãã«ã©ã¤ãã©ãªï¼libkernel.aï¼ã®ãã£ã¬ã¯ããªå
+#  ï¼ã«ã¼ãã«ã©ã¤ãã©ãªãmakeå¯¾è±¡ã«ããæã¯ï¼ç©ºã«å®ç¾©ããï¼
+#
+KERNEL_LIB = ../libkernel
+
+#
+#  ã«ã¼ãã«ãé¢æ°åä½ã§ã³ã³ãã¤ã«ãããã©ããã®å®ç¾©
+#
+KERNEL_FUNCOBJS = 
+
+#
+#  ãã¬ã¼ã¹ã­ã°ãåå¾ãããã©ããã®å®ç¾©
+#
+ENABLE_TRACE = 
+
+#
+#  ã¦ã¼ãã£ãªãã£ãã­ã°ã©ã ã®åç§°
+#
+PERL = /usr/bin/perl
+CFG = $(SRCDIR)/cfg/cfg/cfg
+
+#
+#  ãªãã¸ã§ã¯ããã¡ã¤ã«åã®å®ç¾©
+#
+OBJNAME = asp
+ifdef OBJEXT
+  OBJFILE = $(OBJNAME).$(OBJEXT)
+  CFG1_OUT = cfg1_out.$(OBJEXT)
+else
+  OBJFILE = $(OBJNAME)
+  CFG1_OUT = cfg1_out
+endif
+
+#
+#  ã¿ã¼ã²ããä¾å­é¨ã®ãã£ã¬ã¯ããªã®å®ç¾©
+#
+TARGETDIR = $(SRCDIR)/target/$(TARGET)
+
+#
+#  ã¿ã¼ã²ããä¾å­ã®å®ç¾©ã®ã¤ã³ã¯ã«ã¼ã
+#
+include $(TARGETDIR)/Makefile.target
+
+#
+#  ã³ã³ãã£ã®ã¥ã¬ã¼ã¿é¢ä¿ã®å¤æ°ã®å®ç¾©
+#
+CFG_TABS := --api-table $(SRCDIR)/kernel/kernel_api.csv \
+			--cfg1-def-table $(SRCDIR)/kernel/kernel_def.csv $(CFG_TABS)
+
+CFG_ASMOBJS := $(CFG_ASMOBJS)
+CFG_COBJS := kernel_cfg.o $(CFG_COBJS)
+CFG_OBJS := $(CFG_ASMOBJS) $(CFG_COBJS)
+CFG2_OUT_SRCS := kernel_cfg.h kernel_cfg.c $(CFG2_OUT_SRCS)
+
+#
+#  å
+±éã³ã³ãã¤ã«ãªãã·ã§ã³ã®å®ç¾©
+#
+COPTS := $(COPTS) -g 
+ifndef OMIT_WARNING_ALL
+  COPTS := $(COPTS) -Wall
+endif
+ifndef OMIT_OPTIMIZATION
+  COPTS := $(COPTS) -O2
+endif
+CDEFS := $(CDEFS) -DSDEV_SENSE_ONETIME
+INCLUDES := -I. -I$(SRCDIR)/include -I$(SRCDIR)/arch -I$(SRCDIR) $(INCLUDES)
+LDFLAGS := $(LDFLAGS) 
+CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) 
+LIBS := $(LIBS) $(CXXLIBS)
+CFLAGS = $(COPTS) $(CDEFS) $(INCLUDES)
+
+#
+#  ã¢ããªã±ã¼ã·ã§ã³ãã­ã°ã©ã ã«é¢ããå®ç¾©
+#
+APPLNAME = sdtest
+APPLDIR = 
+APPL_CFG = $(APPLNAME).cfg
+
+APPL_DIR = $(APPLDIR) $(SRCDIR)/library
+APPL_ASMOBJS =
+ifdef USE_CXX
+  APPL_CXXOBJS = $(APPLNAME).o 
+  APPL_COBJS =
+else
+  APPL_COBJS = $(APPLNAME).o 
+endif
+APPL_COBJS := $(APPL_COBJS) log_output.o vasyslog.o t_perror.o strerror.o
+APPL_CFLAGS =
+APPL_LIBS =
+ifdef APPLDIR
+  INCLUDES := $(INCLUDES) $(foreach dir,$(APPLDIR),-I$(dir))
+endif
+
+#
+#  ããã«ã¦ã§ã¢ã® Makefile ã®ã¤ã³ã¯ã«ã¼ã
+#
+include $(SRCDIR)/monitor/Makefile.config
+include $(SRCDIR)/files/ff/Makefile.config
+include $(SRCDIR)/files/Makefile.config
+
+#
+#  GDIC Makefile ã®ã¤ã³ã¯ã«ã¼ã
+#
+include $(SRCDIR)/gdic/spi_driver/Makefile.config
+
+#
+#  ã·ã¹ãã ãµã¼ãã¹ã«é¢ããå®ç¾©
+#
+SYSSVC_DIR := $(SYSSVC_DIR) $(SRCDIR)/syssvc $(SRCDIR)/library $(SRCDIR)/pdic/k210
+SYSSVC_ASMOBJS := $(SYSSVC_ASMOBJS)
+SYSSVC_COBJS := $(SYSSVC_COBJS) banner.o syslog.o serial.o logtask.o riscv64.o \
+				 device.o spi.o spi_reg.o clock.o malloc.o tlsf.o $(CXXRTS)
+SYSSVC_CFLAGS := $(SYSSVC_CFLAGS)
+SYSSVC_LIBS := $(SYSSVC_LIBS)
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/pdic/k210
+
+#
+#  ã«ã¼ãã«ã«é¢ããå®ç¾©
+#
+#  KERNEL_ASMOBJS: ã«ã¼ãã«ã©ã¤ãã©ãªã«å«ããï¼ã½ã¼ã¹ãã¢ã»ã³ããªè¨èªã®
+#				   ãªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#  KERNEL_COBJS: ã«ã¼ãã«ã®ã©ã¤ãã©ãªã«å«ããï¼ã½ã¼ã¹ãCè¨èªã§ï¼ã½ã¼ã¹
+#				 ãã¡ã¤ã«ã¨1å¯¾1ã«å¯¾å¿ãããªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#  KERNEL_LCSRCS: ã«ã¼ãã«ã®ã©ã¤ãã©ãªã«å«ããCè¨èªã®ã½ã¼ã¹ãã¡ã¤ã«ã§ï¼
+#				  1ã¤ã®ã½ã¼ã¹ãã¡ã¤ã«ããè¤æ°ã®ãªãã¸ã§ã¯ããã¡ã¤ã«ãç
+#				  æãããã®ï¼
+#  KERNEL_LCOBJS: ä¸ã®ã½ã¼ã¹ãã¡ã¤ã«ããçæããããªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#  KERNEL_AUX_COBJS: ã­ã¼ãã¢ã¸ã¥ã¼ã«ã«å«ããªããï¼ã«ã¼ãã«ã®ã½ã¼ã¹ãã¡
+#					 ã¤ã«ã¨åããªãã·ã§ã³ãé©ç¨ãã¦ã³ã³ãã¤ã«ãã¹ãï¼ã½ã¼
+#					 ã¹ãCè¨èªã®ãªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#
+KERNEL_DIR := $(KERNEL_DIR) $(SRCDIR)/kernel
+KERNEL_ASMOBJS := $(KERNEL_ASMOBJS)
+KERNEL_COBJS := $(KERNEL_COBJS)
+KERNEL_CFLAGS := $(KERNEL_CFLAGS) -I$(SRCDIR)/kernel
+ifdef OMIT_MAKEOFFSET
+  OFFSET_H =
+else
+  OFFSET_H = offset.h
+ifndef OFFSET_TF
+  KERNEL_AUX_COBJS := $(KERNEL_AUX_COBJS) makeoffset.o
+endif
+endif
+
+#
+#  ã¿ã¼ã²ãããã¡ã¤ã«ï¼è¤æ°ãåæã«é¸æãã¦ã¯ãªããªãï¼
+#
+all: $(OBJFILE)
+#all: $(OBJNAME).bin
+#all: $(OBJNAME).srec
+
+##### ä»¥ä¸ã¯ç·¨éããªããã¨ #####
+
+#
+#  ç°å¢ã«ä¾å­ããã³ã³ãã¤ã«ãªãã·ã§ã³ã®å®ç¾©
+#
+ifdef DBGENV
+  CDEFS := $(CDEFS) -D$(DBGENV)
+endif
+
+#
+#  ã«ã¼ãã«ã®ãã¡ã¤ã«æ§æã®å®ç¾©
+#
+include $(SRCDIR)/kernel/Makefile.kernel
+ifdef KERNEL_FUNCOBJS
+  KERNEL_LCSRCS := $(KERNEL_FCSRCS)
+  KERNEL_LCOBJS := $(foreach file,$(KERNEL_FCSRCS),$($(file:.c=)))
+else
+  KERNEL_CFLAGS := -DALLFUNC $(KERNEL_CFLAGS)
+  KERNEL_COBJS := $(KERNEL_COBJS) \
+					$(foreach file,$(KERNEL_FCSRCS),$(file:.c=.o))
+endif
+
+#
+#  ã½ã¼ã¹ãã¡ã¤ã«ã®ãããã£ã¬ã¯ããªã«é¢ããå®ç¾©
+#
+vpath %.c $(KERNEL_DIR) $(SYSSVC_DIR) $(APPL_DIR)
+vpath %.S $(KERNEL_DIR) $(SYSSVC_DIR) $(APPL_DIR)
+vpath %.cfg $(APPL_DIR)
+
+#
+#  ã³ã³ãã¤ã«ã®ããã®å¤æ°ã®å®ç¾©
+#
+KERNEL_LIB_OBJS = $(KERNEL_ASMOBJS) $(KERNEL_COBJS) $(KERNEL_LCOBJS)
+SYSSVC_OBJS = $(SYSSVC_ASMOBJS) $(SYSSVC_COBJS)
+APPL_OBJS = $(APPL_ASMOBJS) $(APPL_COBJS) $(APPL_CXXOBJS)
+ALL_OBJS = $(START_OBJS) $(APPL_OBJS) $(SYSSVC_OBJS) $(CFG_OBJS) \
+											$(END_OBJS) $(HIDDEN_OBJS)
+ifdef KERNEL_LIB
+  ALL_LIBS = $(APPL_LIBS) $(SYSSVC_LIBS) -lkernel $(LIBS)
+  LIBS_DEP = $(filter %.a,$(ALL_LIBS)) $(KERNEL_LIB)/libkernel.a
+  LDFLAGS := $(LDFLAGS) -L$(KERNEL_LIB)
+  REALCLEAN_FILES := libkernel.a $(REALCLEAN_FILES)
+else
+  ALL_LIBS = $(APPL_LIBS) $(SYSSVC_LIBS) libkernel.a $(LIBS)
+  LIBS_DEP = $(filter %.a,$(ALL_LIBS))
+endif
+
+ifdef TEXT_START_ADDRESS
+  LDFLAGS := $(LDFLAGS) -Wl,-Ttext,$(TEXT_START_ADDRESS)
+  CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) -Wl,-Ttext,$(TEXT_START_ADDRESS)
+endif
+ifdef DATA_START_ADDRESS
+  LDFLAGS := $(LDFLAGS) -Wl,-Tdata,$(DATA_START_ADDRESS)
+  CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) -Wl,-Tdata,$(DATA_START_ADDRESS)
+endif
+ifdef LDSCRIPT
+  LDFLAGS := $(LDFLAGS) -Wl,-T,$(LDSCRIPT)
+  CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) -Wl,-T,$(LDSCRIPT)
+endif
+
+#
+#  ãªãã»ãããã¡ã¤ã«ï¼offset.hï¼ã®çæè¦å
+#
+ifdef OFFSET_TF
+offset.h: $(APPL_CFG) kernel_cfg.timestamp
+	$(CFG) --pass 3 --kernel asp $(INCLUDES) \
+				--rom-image cfg1_out.srec --symbol-table cfg1_out.syms \
+				-T $(OFFSET_TF) $(CFG_TABS) $<
+else
+offset.h: makeoffset.s $(SRCDIR)/utils/genoffset
+	$(PERL) $(SRCDIR)/utils/genoffset makeoffset.s > offset.h
+endif
+
+#
+#  ã«ã¼ãã«ã®ã³ã³ãã£ã®ã¥ã¬ã¼ã·ã§ã³ãã¡ã¤ã«ã®çæ
+#
+cfg1_out.c: $(APPL_CFG)
+	$(CFG) --pass 1 --kernel asp $(INCLUDES) $(CFG_TABS) $<
+
+$(CFG2_OUT_SRCS): kernel_cfg.timestamp
+kernel_cfg.timestamp: $(APPL_CFG) \
+						$(START_OBJS) cfg1_out.o $(END_OBJS) $(HIDDEN_OBJS)
+	$(LINK) $(CFLAGS) $(CFG1_OUT_LDFLAGS) -o $(CFG1_OUT) \
+						$(START_OBJS) cfg1_out.o $(END_OBJS)
+	$(NM) -n $(CFG1_OUT) > cfg1_out.syms
+	$(OBJCOPY) -O srec -S $(CFG1_OUT) cfg1_out.srec
+	$(CFG) --pass 2 --kernel asp $(INCLUDES) \
+				-T $(TARGETDIR)/target.tf $(CFG_TABS) $<
+	touch -r kernel_cfg.c kernel_cfg.timestamp
+
+#
+#  ã«ã¼ãã«ã©ã¤ãã©ãªãã¡ã¤ã«ã®çæ
+#
+libkernel.a: $(OFFSET_H) $(KERNEL_LIB_OBJS)
+	rm -f libkernel.a
+	$(AR) -rcs libkernel.a $(KERNEL_LIB_OBJS)
+	$(RANLIB) libkernel.a
+
+#
+#  ç¹å¥ãªä¾å­é¢ä¿ã®å®ç¾©
+#
+banner.o: kernel_cfg.timestamp $(filter-out banner.o,$(ALL_OBJS)) $(LIBS_DEP)
+
+#
+#  å
+¨ä½ã®ãªã³ã¯
+#
+$(OBJFILE): $(APPL_CFG) kernel_cfg.timestamp $(ALL_OBJS) $(LIBS_DEP)
+	$(LINK) $(CFLAGS) $(LDFLAGS) -o $(OBJFILE) $(START_OBJS) \
+			$(APPL_OBJS) $(SYSSVC_OBJS) $(CFG_OBJS) $(ALL_LIBS) $(END_OBJS)
+	$(NM) -n $(OBJFILE) > $(OBJNAME).syms
+	$(OBJCOPY) -O srec -S $(OBJFILE) $(OBJNAME).srec
+	$(OBJCOPY) -O binary -S $(OBJFILE) $(OBJNAME).bin
+	$(CFG) --pass 3 --kernel asp $(INCLUDES) \
+				--rom-image $(OBJNAME).srec --symbol-table $(OBJNAME).syms \
+				-T $(TARGETDIR)/target_check.tf $(CFG_TABS) $<
+
+#
+#  ãã¤ããªãã¡ã¤ã«ã®çæ
+#
+$(OBJNAME).bin: $(OBJFILE)
+	$(OBJCOPY) -O binary -S $(OBJFILE) $(OBJNAME).bin
+
+#
+#  Sã¬ã³ã¼ããã¡ã¤ã«ã®çæ
+#
+$(OBJNAME).srec: $(OBJFILE)
+	$(OBJCOPY) -O srec -S $(OBJFILE) $(OBJNAME).srec
+
+#
+#  ã³ã³ãã¤ã«çµæã®æ¶å»
+#
+.PHONY: clean
+clean:
+	rm -f \#* *~ *.o $(CLEAN_FILES)
+	rm -f $(OBJFILE) $(OBJNAME).syms $(OBJNAME).srec $(OBJNAME).bin
+	rm -f kernel_cfg.timestamp $(CFG2_OUT_SRCS)
+	rm -f cfg1_out.c $(CFG1_OUT) cfg1_out.syms cfg1_out.srec
+ifndef KERNEL_LIB
+	rm -f libkernel.a
+endif
+	rm -f makeoffset.s offset.h
+
+.PHONY: cleankernel
+cleankernel:
+	rm -rf $(KERNEL_LIB_OBJS)
+	rm -f makeoffset.s offset.h
+
+.PHONY: cleandep
+cleandep:
+	if ! [ -f Makefile.depend ]; then \
+		rm -f kernel_cfg.timestamp $(CFG2_OUT_SRCS); \
+		rm -f cfg1_out.c cfg1_out.o $(CFG1_OUT) cfg1_out.syms cfg1_out.srec; \
+		rm -f makeoffset.s offset.h; \
+	fi
+	rm -f Makefile.depend
+
+.PHONY: realclean
+realclean: cleandep clean
+	rm -f $(REALCLEAN_FILES)
+
+#
+#  ã³ã³ãã£ã®ã¥ã¬ã¼ã¿ãçæãããã¡ã¤ã«ã®ã³ã³ãã¤ã«ã«ã¼ã«ã¨ä¾å­é¢ä¿ä½æ
+#  ã«ã¼ã«ã®å®ç¾©
+#
+#  ã³ã³ãã£ã®ã¥ã¬ã¼ã¿ãçæãããã¡ã¤ã«ã¯ï¼ã¢ããªã±ã¼ã·ã§ã³ãã­ã°ã©ã ç¨ï¼
+#  ã·ã¹ãã ãµã¼ãã¹ç¨ï¼ã«ã¼ãã«ç¨ã®ãã¹ã¦ã®ãªãã·ã§ã³ãä»ãã¦ã³ã³ãã¤ã«
+#  ããï¼
+#
+ALL_CFG_COBJS = $(CFG_COBJS) cfg1_out.o
+ALL_CFG_ASMOBJS = $(CFG_ASMOBJS)
+CFG_CFLAGS = $(APPL_CFLAGS) $(SYSSVC_CFLAGS) $(KERNEL_CFLAGS)
+
+$(ALL_CFG_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(CFG_CFLAGS) $<
+
+$(ALL_CFG_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(CFG_CFLAGS) $<
+
+$(ALL_CFG_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(CFG_CFLAGS)" $< >> Makefile.depend
+
+$(ALL_CFG_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(CFG_CFLAGS) $<
+
+$(ALL_CFG_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(CFG_CFLAGS)" $< >> Makefile.depend
+
+#
+#  ç¹æ®ãªä¾å­é¢ä¿ä½æã«ã¼ã«ã®å®ç¾©
+#
+cfg1_out.depend: $(APPL_CFG)
+	@$(CFG) -M cfg1_out.c $(INCLUDES) $< >> Makefile.depend
+
+makeoffset.d: makeoffset.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-T "makeoffset.s" -O "$(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+#
+#  ä¾å­é¢ä¿ãã¡ã¤ã«ã®çæ
+#
+.PHONY: gendepend
+gendepend:
+	@echo "Generating Makefile.depend."
+
+.PHONY: depend
+ifdef KERNEL_LIB
+depend: cleandep kernel_cfg.timestamp gendepend \
+		cfg1_out.depend cfg1_out.d \
+		$(ALL_OBJS:.o=.d)
+else
+depend: cleandep $(OFFSET_H) kernel_cfg.timestamp gendepend \
+		cfg1_out.depend cfg1_out.d \
+		$(KERNEL_AUX_COBJS:.o=.d) $(KERNEL_ASMOBJS:.o=.d) \
+		$(KERNEL_COBJS:.o=.d) $(KERNEL_LCSRCS:.c=.d) $(ALL_OBJS:.o=.d)
+endif
+
+#
+#  ä¾å­é¢ä¿ãã¡ã¤ã«ãã¤ã³ã¯ã«ã¼ã
+#
+-include Makefile.depend
+
+#
+#  éçºãã¼ã«ã®ã³ãã³ãåã®å®ç¾©
+#
+ifeq ($(TOOL),gcc)
+  #
+  #  GNUéçºç°å¢ç¨
+  #
+  ifdef GCC_TARGET
+    GCC_TARGET_PREFIX = $(GCC_TARGET)-
+  else
+    GCC_TARGET_PREFIX =
+  endif
+  CC = $(GCC_TARGET_PREFIX)gcc
+  CXX = $(GCC_TARGET_PREFIX)g++
+  AS = $(GCC_TARGET_PREFIX)as
+  LD = $(GCC_TARGET_PREFIX)ld
+  AR = $(GCC_TARGET_PREFIX)ar
+  NM = $(GCC_TARGET_PREFIX)nm
+  RANLIB = $(GCC_TARGET_PREFIX)ranlib
+  OBJCOPY = $(GCC_TARGET_PREFIX)objcopy
+  OBJDUMP = $(GCC_TARGET_PREFIX)objdump
+endif
+
+ifdef USE_CXX
+  LINK = $(CXX)
+else
+  LINK = $(CC)
+endif
+
+#
+#  ã³ã³ãã¤ã«ã«ã¼ã«ã®å®ç¾©
+#
+KERNEL_ALL_COBJS = $(KERNEL_COBJS) $(KERNEL_AUX_COBJS)
+
+$(KERNEL_ALL_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_ALL_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_LCOBJS): %.o:
+	$(CC) -DTOPPERS_$(*F) -o $@ -c $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_LCOBJS:.o=.s): %.s:
+	$(CC) -DTOPPERS_$(*F) -o $@ -S $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(SYSSVC_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(SYSSVC_CFLAGS) $<
+
+$(SYSSVC_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(SYSSVC_CFLAGS) $<
+
+$(SYSSVC_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(SYSSVC_CFLAGS) $<
+
+$(APPL_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_CXXOBJS): %.o: %.cpp
+	$(CXX) -c $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_CXXOBJS:.o=.s): %.s: %.cpp
+	$(CXX) -S $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(APPL_CFLAGS) $<
+
+#
+#  ä¾å­é¢ä¿ä½æã«ã¼ã«ã®å®ç¾©
+#
+$(KERNEL_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+$(KERNEL_LCSRCS:.c=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) -T "$($*)" \
+		-O "-DALLFUNC $(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+$(KERNEL_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+$(SYSSVC_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(SYSSVC_CFLAGS)" $< >> Makefile.depend
+
+$(SYSSVC_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(SYSSVC_CFLAGS)" $< >> Makefile.depend
+
+$(APPL_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(APPL_CFLAGS)" $< >> Makefile.depend
+
+$(APPL_CXXOBJS:.o=.d): %.d: %.cpp
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CXX) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(APPL_CFLAGS)" $< >> Makefile.depend
+
+$(APPL_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(APPL_CFLAGS)" $< >> Makefile.depend
+
+#
+#  ããã©ã«ãã³ã³ãã¤ã«ã«ã¼ã«ãä¸æ¸ã
+#
+%.o: %.c
+	@echo "*** Default compile rules should not be used."
+	$(CC) -c $(CFLAGS) $<
+
+%.s: %.c
+	@echo "*** Default compile rules should not be used."
+	$(CC) -S $(CFLAGS) $<
+
+%.o: %.cpp
+	@echo "*** Default compile rules should not be used."
+	$(CXX) -c $(CFLAGS) $<
+
+%.s: %.cpp
+	@echo "*** Default compile rules should not be used."
+	$(CXX) -S $(CFLAGS) $<
+
+%.o: %.S
+	@echo "*** Default compile rules should not be used."
+	$(CC) -c $(CFLAGS) $<
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/SDCARD/sdtest.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/SDCARD/sdtest.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/SDCARD/sdtest.c	(revision 453)
@@ -0,0 +1,319 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2012 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *  SD-CARDテストの本体
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <target_syssvc.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#include "kernel_cfg.h"
+#include "device.h"
+#include "spi.h"
+#include "spi_driver.h"
+#ifdef SDEV_SENSE_ONETIME
+#include "storagedevice.h"
+#include "sddiskio.h"
+#endif
+#include "sdtest.h"
+
+/*
+ *  サービスコールのエラーのログ出力
+ */
+Inline void
+svc_perror(const char *file, int_t line, const char *expr, ER ercd)
+{
+	if (ercd < 0) {
+		t_perror(LOG_ERROR, file, line, expr, ercd);
+	}
+}
+
+#define	SVC_PERROR(expr)	svc_perror(__FILE__, __LINE__, #expr, (expr))
+
+
+static uint32_t heap_area[16*1024];
+
+intptr_t heap_param[2] = {
+	(intptr_t)heap_area,
+	(4*16*1024)
+};
+
+uint8_t  sdbuffer[512];
+
+/*
+ *  SW1割込み
+ */
+void sw_int(int arg)
+{
+	syslog_1(LOG_NOTICE, "## sw_int(%d) ##", arg);
+}
+
+void
+pinMode(uint8_t Pin, uint8_t dwMode){ 
+    int gpionum = gpio_get_gpiohno(Pin, false);
+	GPIO_Init_t init = {0};
+
+	syslog_2(LOG_NOTICE, "## pinMode Pin(%d) gpionum(%d) ##", Pin, gpionum);
+    if(gpionum >= 0){
+        uint8_t function = FUNC_GPIOHS0 + gpionum;
+        fpioa_set_function(Pin, function);
+		switch(dwMode){
+		case INPUT:
+			init.mode = GPIO_MODE_INPUT;
+			init.pull = GPIO_NOPULL;
+			break;
+		case INPUT_PULLDOWN:
+			init.mode = GPIO_MODE_INPUT;
+			init.pull = GPIO_PULLDOWN;
+			break;
+		case INPUT_PULLUP:
+			init.mode = GPIO_MODE_INPUT;
+			init.pull = GPIO_PULLUP;
+			break;
+		case OUTPUT:
+		default:
+			init.mode = GPIO_MODE_OUTPUT;
+			init.pull = GPIO_PULLDOWN;
+			break;
+		}
+        gpio_setup(TADR_GPIOHS_BASE, &init, (uint8_t)gpionum);
+    }
+    return ;
+}
+
+void
+digitalWrite(uint8_t Pin, int dwVal){
+    int8_t gpio_pin = gpio_get_gpiohno(Pin, false);
+
+    if( gpio_pin >= 0){
+        gpio_set_pin(TADR_GPIOHS_BASE, (uint8_t)gpio_pin, dwVal);
+    }
+}
+
+
+/*
+ *  メインタスク
+ */
+void main_task(intptr_t exinf)
+{
+#ifdef SDEV_SENSE_ONETIME
+	StorageDevice_t *psdev;
+#endif
+	SPI_Init_t Init;
+	SPI_Handle_t *hspi;
+	SDCARD_Handler_t *hsd = NULL;
+#ifndef SDEV_SENSE_ONETIME
+	SDCARD_CardInfo_t CardInfo;
+#endif
+	ER_UINT	ercd;
+	int i;
+
+	SVC_PERROR(syslog_msk_log(LOG_UPTO(LOG_INFO), LOG_UPTO(LOG_EMERG)));
+	syslog(LOG_NOTICE, "Sample program starts (exinf = %d).", (int_t) exinf);
+
+	/*
+	 *  シリアルポートの初期化
+	 *
+	 *  システムログタスクと同じシリアルポートを使う場合など，シリアル
+	 *  ポートがオープン済みの場合にはここでE_OBJエラーになるが，支障は
+	 *  ない．
+	 */
+	ercd = serial_opn_por(TASK_PORTID);
+	if (ercd < 0 && MERCD(ercd) != E_OBJ) {
+		syslog(LOG_ERROR, "%s (%d) reported by `serial_opn_por'.",
+									itron_strerror(ercd), SERCD(ercd));
+	}
+	SVC_PERROR(serial_ctl_por(TASK_PORTID,
+							(IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV)));
+
+	dly_tsk(100);
+	syslog_0(LOG_NOTICE, "SPI SEND/RECV START");
+	pinMode(SPI_SS_PIN, OUTPUT);
+	digitalWrite(SPI_SS_PIN, HIGH);
+#if 1	/* ROI DEBUG */
+	dly_tsk(100);
+#endif	/* ROI DEBUG */
+
+	/*##-1- Configure the SPI peripheral #######################################*/
+	/* Set the SPI parameters */
+	Init.WorkMode     = SPI_WORK_MODE_0;
+	Init.FrameFormat  = SPI_FF_STANDARD;
+	Init.DataSize     = 8;
+	Init.Prescaler    = 5000000;
+	Init.SignBit      = 0;
+	Init.InstLength   = 0;
+	Init.AddrLength   = 0;
+	Init.WaitCycles   = 0;
+	Init.IATransMode  = SPI_AITM_STANDARD;
+	Init.SclkPin      = SPI_SCK_PIN;
+	Init.MosiPin      = SPI_MOSI_PIN;
+	Init.MisoPin      = SPI_MISO_PIN;
+	Init.SsPin        = -1;
+	Init.SsNo         = -1;
+#ifdef USE_TXDMA*/
+	Init.TxDMAChannel = SPI_DMA2_CH;
+#else
+	Init.TxDMAChannel = -1;
+#endif
+	Init.RxDMAChannel = SPI_DMA1_CH;
+	Init.semid        = SPITRN_SEM;
+	Init.semlock      = SPILOCK_SEM;
+	Init.semdmaid     = SPIDMATX_SEM;
+	hspi = spi_init(SPI_PORTID, &Init);
+	if(hspi == NULL){
+		syslog_0(LOG_ERROR, "SPI INIT ERROR");
+		slp_tsk();
+	}
+	sdcard_setspi2(SPISDCARD_PORTID, hspi, SPI_SS_PIN);
+
+	/*
+	 *  SD-CARD SPI通信設定
+	 */
+	for(i = 0 ; i < 10 ; i++)
+		sdbuffer[i] = 0xff;
+	if((ercd = spi_transmit(hspi, (uint8_t*)sdbuffer, 10)) != E_OK){
+		/* Transfer error in transmission process */
+		syslog_1(LOG_NOTICE, "## call Error_Handler(2)(%d) ##", ercd);
+	}
+#if SPI_WAIT_TIME == 0
+	if((ercd = spi_wait(hspi, 100)) != E_OK){
+		syslog_0(LOG_NOTICE, "## call Error_Handler(3) ##");
+	}
+#endif
+	dly_tsk(100);
+
+#ifndef SDEV_SENSE_ONETIME
+	if(sdcard_init(SPISDCARD_PORTID)){
+		hsd = sdcard_open(SPISDCARD_PORTID);
+		syslog_1(LOG_NOTICE, "## card(%d) ##", hsd->cardtype);
+		SVC_PERROR(sdcard_checkCID(hsd));
+		SVC_PERROR(sdcard_sendCSD(hsd));
+		SVC_PERROR(sdcard_getcardinfo(hsd, &CardInfo));
+		SVC_PERROR(sdcard_configuration(hsd));
+	}
+#else
+	SDMSence_task(0);
+	psdev = SDMGetStorageDevice(SDCARD_DEVNO);
+	hsd = (SDCARD_Handler_t *)psdev->_sdev_local[1];
+#endif
+	if(hsd == NULL){
+		syslog_0(LOG_NOTICE, "SD-CARD INITIAL ERROR !");
+		slp_tsk();
+	}
+#ifndef SDEV_SENSE_ONETIME
+	if(hsd != NULL && hsd->hspi != NULL){
+		unsigned char *p;
+		int j, bpb;
+		int SecPerCls, Rsv, NumFat, Fsize, RootDirC, RootSec;
+		for(i = 0 ; i < 1 ; i++){
+			ercd = sdcard_blockread(hsd, sdbuffer, i*512, 512, 1);
+			syslog_3(LOG_NOTICE, "## ercd(%d) i(%d) sdbuffer[%08x] ##", ercd, i, sdbuffer);
+			dly_tsk(300);
+			p = (unsigned char *)sdbuffer;
+			if(i == 0){
+				if(p[0x36] == 'F' && p[0x37] == 'A' && p[0x38] == 'T')
+					bpb = 0;
+				else{
+					bpb = p[0x1c6];
+					bpb |= p[0x1c7]<<8;
+					bpb |= p[0x1c8]<<16;
+					bpb |= p[0x1c9]<<24;
+				}
+			}
+			printf("\nsec(%d) ", i);
+			for(j = 0 ; j < 512 ; j++){
+				if((j % 16) == 0)
+					printf("\n%03x ", j);
+				printf("%02x ", p[j]);
+			}
+			printf("\n");
+		}
+		syslog_1(LOG_NOTICE, "## bpb(%08x) ##", bpb);
+		if(bpb != 0){
+			ercd = sdcard_blockread(hsd, sdbuffer, bpb*512, 512, 1);
+			syslog_3(LOG_NOTICE, "## ercd(%d) i(%d) sdbuffer[%08x] ##", ercd, bpb, sdbuffer);
+			dly_tsk(300);
+			printf("\nsec(%d) ", bpb);
+			for(j = 0 ; j < 512 ; j++){
+				if((j % 16) == 0)
+					printf("\n%03x ", j);
+				printf("%02x ", p[j]);
+			}
+			printf("\n");
+		}
+		p = (unsigned char *)sdbuffer;
+		SecPerCls = p[13];
+		Rsv = p[14] + (p[15] << 8);
+		NumFat = p[16];
+		RootDirC = p[17] + (p[18]<<8);
+		Fsize = p[22] + (p[23] << 8);
+		syslog_4(LOG_NOTICE, "## SecPerCls(%d) Rsv(%d) NumFat(%d) RootDirC(%d) ##", SecPerCls, Rsv, NumFat, RootDirC);
+		RootSec = bpb + Rsv + (NumFat * Fsize);
+		syslog_2(LOG_NOTICE, "## Fsize(%d) RootSec(%d) ##", Fsize, RootSec);
+
+		for(i = 0 ; i < 2 ; i++){
+			ercd = sdcard_blockread(hsd, sdbuffer, (i+RootSec)*512, 512, 1);
+			syslog_3(LOG_NOTICE, "## ercd(%d) i(%d) sdbuffer[%08x] ##", ercd, (i+RootSec), sdbuffer);
+			dly_tsk(300);
+			p = (unsigned char *)sdbuffer;
+			printf("\nsec(%d) ", (i+RootSec));
+			for(j = 0 ; j < 512 ; j++){
+				if((j % 16) == 0)
+					printf("\n%03x ", j);
+				printf("%02x ", p[j]);
+			}
+			printf("\n");
+		}
+	}
+#endif
+	(void)(hsd);
+
+	syslog(LOG_NOTICE, "Sample program ends.");
+	slp_tsk();
+//	SVC_PERROR(ext_ker());
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/SDCARD/sdtest.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/SDCARD/sdtest.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/SDCARD/sdtest.cfg	(revision 453)
@@ -0,0 +1,41 @@
+/*
+ *  $Id$
+ */
+
+/*
+ *  SD-CARDテストのコンフィギュレーションファイル
+ */
+INCLUDE("target_timer.cfg");
+INCLUDE("syssvc/syslog.cfg");
+INCLUDE("syssvc/banner.cfg");
+INCLUDE("syssvc/serial.cfg");
+INCLUDE("syssvc/logtask.cfg");
+INCLUDE("syssvc/tlsf.cfg");
+INCLUDE("pdic/k210/device.cfg");
+INCLUDE("files/storagedevice.cfg");
+INCLUDE("files/ff/fatfs.cfg");
+INCLUDE("monitor/monitor.cfg");
+
+#include "device.h"
+#include "spi.h"
+#include "sdtest.h"
+
+ATT_INI({ TA_NULL, 0, rtc_init });
+ATT_INI({ TA_NULL, 0, rtc_info_init });
+ATT_INI({ TA_NULL, heap_param, heap_init });
+
+CRE_SEM(SPITRN_SEM,   { TA_TPRI, 0, 1 });
+CRE_SEM(SPILOCK_SEM,  { TA_TPRI, 1, 1 });
+CRE_SEM(SPIDMATX_SEM, { TA_TPRI, 0, 1 });
+
+CRE_TSK(MAIN_TASK, { TA_ACT, 0, main_task, MAIN_PRIORITY, STACK_SIZE, NULL });
+
+ATT_ISR({TA_NULL, SPI_PORTID, INTNO_SPI, spi_isr, 1 });
+CFG_INT(INTNO_SPI, { TA_ENAINT | INTATR_SPI, INTPRI_SPI });
+
+ATT_ISR({TA_NULL, SPI_DMA1_CH, INTNO_DMARX, channel_dmac_isr, 1 });
+CFG_INT(INTNO_DMARX, { TA_ENAINT | INTATR_DMARX, INTPRI_DMARX });
+
+ATT_ISR({TA_NULL, SPI_DMA2_CH, INTNO_DMATX, channel_dmac_isr, 1 });
+CFG_INT(INTNO_DMATX, { TA_ENAINT | INTATR_DMATX, INTPRI_DMATX });
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/SDCARD/sdtest.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/SDCARD/sdtest.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/SDCARD/sdtest.h	(revision 453)
@@ -0,0 +1,119 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ *
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ *
+ *  $Id$
+ */
+
+/*
+ *	SD-CARDテストのヘッダファイル
+ */
+
+/*
+ *  ターゲット依存の定義
+ */
+#include "target_test.h"
+
+/*
+ *  各タスクの優先度の定義
+ */
+
+#define MAIN_PRIORITY	5		/* メインタスクの優先度 */
+
+
+/*
+ *  ターゲットに依存する可能性のある定数の定義
+ */
+
+#ifndef TASK_PORTID
+#define	TASK_PORTID		1			/* 文字入力するシリアルポートID */
+#endif /* TASK_PORTID */
+
+#ifndef STACK_SIZE
+#define	STACK_SIZE		4096		/* タスクのスタックサイズ */
+#endif /* STACK_SIZE */
+
+#define SPISDCARD_PORTID    0
+
+#define SPI_SCK_PIN   27
+#define SPI_MISO_PIN  26
+#define SPI_MOSI_PIN  28
+#define SPI_SS_PIN    29
+
+#define SPI_PORTID    SPI2_PORTID
+#define INHNO_SPI     IRQ_VECTOR_SPI1	/* 割込みハンドラ番号 */
+#define INTNO_SPI     IRQ_VECTOR_SPI1	/* 割込み番号 */
+#define INTPRI_SPI    -5		/* 割込み優先度 */
+#define INTATR_SPI    0			/* 割込み属性 */
+
+#define SPI_DMA1_CH   DMA_CHANNEL2
+#define INHNO_DMARX   IRQ_VECTOR_DMA2	/* 割込みハンドラ番号 */
+#define INTNO_DMARX   IRQ_VECTOR_DMA2	/* 割込み番号 */
+#define INTPRI_DMARX  -4		/* 割込み優先度 */
+#define INTATR_DMARX  0			/* 割込み属性 */
+
+#define SPI_DMA2_CH   DMA_CHANNEL3
+#define INHNO_DMATX   IRQ_VECTOR_DMA3	/* 割込みハンドラ番号 */
+#define INTNO_DMATX   IRQ_VECTOR_DMA3	/* 割込み番号 */
+#define INTPRI_DMATX  -4		/* 割込み優先度 */
+#define INTATR_DMATX  0			/* 割込み属性 */
+
+#define HIGH 0x1
+#define LOW  0x0
+
+#define INPUT           0x0
+#define OUTPUT          0x3
+#define INPUT_PULLUP    0x2
+#define INPUT_PULLDOWN  0X1
+
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  ヒープ領域の設定
+ */
+extern intptr_t heap_param[2];
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+
+extern void	main_task(intptr_t exinf);
+extern void heap_init(intptr_t exinf);
+
+#endif /* TOPPERS_MACRO_ONLY */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/TEST/Makefile
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/TEST/Makefile	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/TEST/Makefile	(revision 453)
@@ -0,0 +1,594 @@
+#
+#  TOPPERS/ASP Kernel
+#      Toyohashi Open Platform for Embedded Real-Time Systems/
+#      Advanced Standard Profile Kernel
+# 
+#  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                              Toyohashi Univ. of Technology, JAPAN
+#  Copyright (C) 2006-2014 by Embedded and Real-Time Systems Laboratory
+#              Graduate School of Information Science, Nagoya Univ., JAPAN
+# 
+#  ä¸è¨èä½æ¨©è
+ã¯ï¼ä»¥ä¸ã®(1)ï½(4)ã®æ¡ä»¶ãæºããå ´åã«éãï¼æ¬ã½ããã¦ã§
+#  ã¢ï¼æ¬ã½ããã¦ã§ã¢ãæ¹å¤ãããã®ãå«ãï¼ä»¥ä¸åãï¼ãä½¿ç¨ã»è¤è£½ã»æ¹
+#  å¤ã»åé
+å¸ï¼ä»¥ä¸ï¼å©ç¨ã¨å¼ã¶ï¼ãããã¨ãç¡åã§è¨±è«¾ããï¼
+#  (1) æ¬ã½ããã¦ã§ã¢ãã½ã¼ã¹ã³ã¼ãã®å½¢ã§å©ç¨ããå ´åã«ã¯ï¼ä¸è¨ã®èä½
+#      æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãï¼ãã®ã¾ã¾ã®å½¢ã§ã½ã¼
+#      ã¹ã³ã¼ãä¸­ã«å«ã¾ãã¦ãããã¨ï¼
+#  (2) æ¬ã½ããã¦ã§ã¢ãï¼ã©ã¤ãã©ãªå½¢å¼ãªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨
+#      è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®èä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨
+#      ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#  (3) æ¬ã½ããã¦ã§ã¢ãï¼æ©å¨ã«çµã¿è¾¼ããªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããªãå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼æ¬¡ã®ããããã®æ¡ä»¶ãæºããã
+#      ã¨ï¼
+#    (a) åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®è
+#        ä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#    (b) åé
+å¸ã®å½¢æ
+ãï¼å¥ã«å®ããæ¹æ³ã«ãã£ã¦ï¼TOPPERSãã­ã¸ã§ã¯ãã«
+#        å ±åãããã¨ï¼
+#  (4) æ¬ã½ããã¦ã§ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæ
+#      å®³ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ããå
+è²¬ãããã¨ï¼
+#      ã¾ãï¼æ¬ã½ããã¦ã§ã¢ã®ã¦ã¼ã¶ã¾ãã¯ã¨ã³ãã¦ã¼ã¶ããã®ãããªãç
+#      ç±ã«åºã¥ãè«æ±ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ãã
+#      å
+è²¬ãããã¨ï¼
+# 
+#  æ¬ã½ããã¦ã§ã¢ã¯ï¼ç¡ä¿è¨¼ã§æä¾ããã¦ãããã®ã§ããï¼ä¸è¨èä½æ¨©è
+ã
+#  ãã³TOPPERSãã­ã¸ã§ã¯ãã¯ï¼æ¬ã½ããã¦ã§ã¢ã«é¢ãã¦ï¼ç¹å®ã®ä½¿ç¨ç®ç
+#  ã«å¯¾ããé©åæ§ãå«ãã¦ï¼ãããªãä¿è¨¼ãè¡ããªãï¼ã¾ãï¼æ¬ã½ããã¦ã§
+#  ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæå®³ã«é¢ãã¦ãï¼ã
+#  ã®è²¬ä»»ãè² ããªãï¼
+# 
+#  $Id$
+# 
+
+#
+#  ã¿ã¼ã²ããã®æå®ï¼Makefile.targetã§ä¸æ¸ããããã®ãé²ãããï¼
+#
+all:
+
+#
+#  ã¿ã¼ã²ããç¥ç§°ã®å®ç¾©
+#
+TARGET = k210_gcc
+
+#
+#  ãã­ã°ã©ãã³ã°è¨èªã®å®ç¾©
+#
+SRCLANG = c
+ifeq ($(SRCLANG),c)
+  LIBS = -lc -lm
+endif
+ifeq ($(SRCLANG),c++)
+  USE_CXX = true
+  CXXLIBS = -lstdc++ -lm -lc
+  CXXRTS = cxxrt.o newlibrt.o
+endif
+
+#
+#  ã½ã¼ã¹ãã¡ã¤ã«ã®ãã£ã¬ã¯ããªã®å®ç¾©
+#
+SRCDIR = ../../..
+
+#
+#  ãªãã¸ã§ã¯ããã¡ã¤ã«åã®æ¡å¼µå­ã®è¨­å®
+#
+OBJEXT = exe
+
+#
+#  å®è¡ç°å¢ã®å®ç¾©ï¼ã¿ã¼ã²ããä¾å­ã«ä¸æ¸ããããå ´åãããï¼
+#
+DBGENV := 
+
+#
+#  ã«ã¼ãã«ã©ã¤ãã©ãªï¼libkernel.aï¼ã®ãã£ã¬ã¯ããªå
+#  ï¼ã«ã¼ãã«ã©ã¤ãã©ãªãmakeå¯¾è±¡ã«ããæã¯ï¼ç©ºã«å®ç¾©ããï¼
+#
+KERNEL_LIB = ../libkernel
+
+#
+#  ã«ã¼ãã«ãé¢æ°åä½ã§ã³ã³ãã¤ã«ãããã©ããã®å®ç¾©
+#
+KERNEL_FUNCOBJS = 
+
+#
+#  ãã¬ã¼ã¹ã­ã°ãåå¾ãããã©ããã®å®ç¾©
+#
+ENABLE_TRACE = 
+
+#
+#  ã¦ã¼ãã£ãªãã£ãã­ã°ã©ã ã®åç§°
+#
+PERL = /usr/bin/perl
+CFG = $(SRCDIR)/cfg/cfg/cfg
+
+#
+#  ãªãã¸ã§ã¯ããã¡ã¤ã«åã®å®ç¾©
+#
+OBJNAME = asp
+ifdef OBJEXT
+  OBJFILE = $(OBJNAME).$(OBJEXT)
+  CFG1_OUT = cfg1_out.$(OBJEXT)
+else
+  OBJFILE = $(OBJNAME)
+  CFG1_OUT = cfg1_out
+endif
+
+#
+#  ã¿ã¼ã²ããä¾å­é¨ã®ãã£ã¬ã¯ããªã®å®ç¾©
+#
+TARGETDIR = $(SRCDIR)/target/$(TARGET)
+
+#
+#  ã¿ã¼ã²ããä¾å­ã®å®ç¾©ã®ã¤ã³ã¯ã«ã¼ã
+#
+include $(TARGETDIR)/Makefile.target
+
+#
+#  ã³ã³ãã£ã®ã¥ã¬ã¼ã¿é¢ä¿ã®å¤æ°ã®å®ç¾©
+#
+CFG_TABS := --api-table $(SRCDIR)/kernel/kernel_api.csv \
+			--cfg1-def-table $(SRCDIR)/kernel/kernel_def.csv $(CFG_TABS)
+
+CFG_ASMOBJS := $(CFG_ASMOBJS)
+CFG_COBJS := kernel_cfg.o $(CFG_COBJS)
+CFG_OBJS := $(CFG_ASMOBJS) $(CFG_COBJS)
+CFG2_OUT_SRCS := kernel_cfg.h kernel_cfg.c $(CFG2_OUT_SRCS)
+
+#
+#  å
+±éã³ã³ãã¤ã«ãªãã·ã§ã³ã®å®ç¾©
+#
+COPTS := $(COPTS) -g 
+ifndef OMIT_WARNING_ALL
+  COPTS := $(COPTS) -Wall
+endif
+ifndef OMIT_OPTIMIZATION
+  COPTS := $(COPTS) -O2
+endif
+CDEFS := $(CDEFS) 
+INCLUDES := -I. -I$(SRCDIR)/include -I$(SRCDIR)/arch -I$(SRCDIR) $(INCLUDES)
+LDFLAGS := $(LDFLAGS) 
+CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) 
+LIBS := $(LIBS) $(CXXLIBS)
+CFLAGS = $(COPTS) $(CDEFS) $(INCLUDES)
+
+#
+#  ã¢ããªã±ã¼ã·ã§ã³ãã­ã°ã©ã ã«é¢ããå®ç¾©
+#
+APPLNAME = test
+APPLDIR = 
+APPL_CFG = $(APPLNAME).cfg
+
+APPL_DIR = $(APPLDIR) $(SRCDIR)/library
+APPL_ASMOBJS =
+ifdef USE_CXX
+  APPL_CXXOBJS = $(APPLNAME).o 
+  APPL_COBJS =
+else
+  APPL_COBJS = $(APPLNAME).o 
+endif
+APPL_COBJS := $(APPL_COBJS) log_output.o vasyslog.o t_perror.o strerror.o
+APPL_CFLAGS =
+APPL_LIBS =
+ifdef APPLDIR
+  INCLUDES := $(INCLUDES) $(foreach dir,$(APPLDIR),-I$(dir))
+endif
+
+#  ããã«ã¦ã§ã¢ã® Makefile ã®ã¤ã³ã¯ã«ã¼ã
+#
+include $(SRCDIR)/monitor/Makefile.config
+
+#
+#  ã·ã¹ãã ãµã¼ãã¹ã«é¢ããå®ç¾©
+#
+SYSSVC_DIR := $(SYSSVC_DIR) $(SRCDIR)/syssvc $(SRCDIR)/library $(SRCDIR)/pdic/k210
+SYSSVC_ASMOBJS := $(SYSSVC_ASMOBJS)
+SYSSVC_COBJS := $(SYSSVC_COBJS) banner.o syslog.o serial.o logtask.o riscv64.o \
+				 device.o clock.o pinmode.o $(CXXRTS)
+SYSSVC_CFLAGS := $(SYSSVC_CFLAGS)
+SYSSVC_LIBS := $(SYSSVC_LIBS)
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/pdic/k210
+
+#
+#  ã«ã¼ãã«ã«é¢ããå®ç¾©
+#
+#  KERNEL_ASMOBJS: ã«ã¼ãã«ã©ã¤ãã©ãªã«å«ããï¼ã½ã¼ã¹ãã¢ã»ã³ããªè¨èªã®
+#				   ãªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#  KERNEL_COBJS: ã«ã¼ãã«ã®ã©ã¤ãã©ãªã«å«ããï¼ã½ã¼ã¹ãCè¨èªã§ï¼ã½ã¼ã¹
+#				 ãã¡ã¤ã«ã¨1å¯¾1ã«å¯¾å¿ãããªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#  KERNEL_LCSRCS: ã«ã¼ãã«ã®ã©ã¤ãã©ãªã«å«ããCè¨èªã®ã½ã¼ã¹ãã¡ã¤ã«ã§ï¼
+#				  1ã¤ã®ã½ã¼ã¹ãã¡ã¤ã«ããè¤æ°ã®ãªãã¸ã§ã¯ããã¡ã¤ã«ãç
+#				  æãããã®ï¼
+#  KERNEL_LCOBJS: ä¸ã®ã½ã¼ã¹ãã¡ã¤ã«ããçæããããªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#  KERNEL_AUX_COBJS: ã­ã¼ãã¢ã¸ã¥ã¼ã«ã«å«ããªããï¼ã«ã¼ãã«ã®ã½ã¼ã¹ãã¡
+#					 ã¤ã«ã¨åããªãã·ã§ã³ãé©ç¨ãã¦ã³ã³ãã¤ã«ãã¹ãï¼ã½ã¼
+#					 ã¹ãCè¨èªã®ãªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#
+KERNEL_DIR := $(KERNEL_DIR) $(SRCDIR)/kernel
+KERNEL_ASMOBJS := $(KERNEL_ASMOBJS)
+KERNEL_COBJS := $(KERNEL_COBJS)
+KERNEL_CFLAGS := $(KERNEL_CFLAGS) -I$(SRCDIR)/kernel
+ifdef OMIT_MAKEOFFSET
+  OFFSET_H =
+else
+  OFFSET_H = offset.h
+ifndef OFFSET_TF
+  KERNEL_AUX_COBJS := $(KERNEL_AUX_COBJS) makeoffset.o
+endif
+endif
+
+#
+#  ã¿ã¼ã²ãããã¡ã¤ã«ï¼è¤æ°ãåæã«é¸æãã¦ã¯ãªããªãï¼
+#
+all: $(OBJFILE)
+#all: $(OBJNAME).bin
+#all: $(OBJNAME).srec
+
+##### ä»¥ä¸ã¯ç·¨éããªããã¨ #####
+
+#
+#  ç°å¢ã«ä¾å­ããã³ã³ãã¤ã«ãªãã·ã§ã³ã®å®ç¾©
+#
+ifdef DBGENV
+  CDEFS := $(CDEFS) -D$(DBGENV)
+endif
+
+#
+#  ã«ã¼ãã«ã®ãã¡ã¤ã«æ§æã®å®ç¾©
+#
+include $(SRCDIR)/kernel/Makefile.kernel
+ifdef KERNEL_FUNCOBJS
+  KERNEL_LCSRCS := $(KERNEL_FCSRCS)
+  KERNEL_LCOBJS := $(foreach file,$(KERNEL_FCSRCS),$($(file:.c=)))
+else
+  KERNEL_CFLAGS := -DALLFUNC $(KERNEL_CFLAGS)
+  KERNEL_COBJS := $(KERNEL_COBJS) \
+					$(foreach file,$(KERNEL_FCSRCS),$(file:.c=.o))
+endif
+
+#
+#  ã½ã¼ã¹ãã¡ã¤ã«ã®ãããã£ã¬ã¯ããªã«é¢ããå®ç¾©
+#
+vpath %.c $(KERNEL_DIR) $(SYSSVC_DIR) $(APPL_DIR)
+vpath %.S $(KERNEL_DIR) $(SYSSVC_DIR) $(APPL_DIR)
+vpath %.cfg $(APPL_DIR)
+
+#
+#  ã³ã³ãã¤ã«ã®ããã®å¤æ°ã®å®ç¾©
+#
+KERNEL_LIB_OBJS = $(KERNEL_ASMOBJS) $(KERNEL_COBJS) $(KERNEL_LCOBJS)
+SYSSVC_OBJS = $(SYSSVC_ASMOBJS) $(SYSSVC_COBJS)
+APPL_OBJS = $(APPL_ASMOBJS) $(APPL_COBJS) $(APPL_CXXOBJS)
+ALL_OBJS = $(START_OBJS) $(APPL_OBJS) $(SYSSVC_OBJS) $(CFG_OBJS) \
+											$(END_OBJS) $(HIDDEN_OBJS)
+ifdef KERNEL_LIB
+  ALL_LIBS = $(APPL_LIBS) $(SYSSVC_LIBS) -lkernel $(LIBS)
+  LIBS_DEP = $(filter %.a,$(ALL_LIBS)) $(KERNEL_LIB)/libkernel.a
+  LDFLAGS := $(LDFLAGS) -L$(KERNEL_LIB)
+  REALCLEAN_FILES := libkernel.a $(REALCLEAN_FILES)
+else
+  ALL_LIBS = $(APPL_LIBS) $(SYSSVC_LIBS) libkernel.a $(LIBS)
+  LIBS_DEP = $(filter %.a,$(ALL_LIBS))
+endif
+
+ifdef TEXT_START_ADDRESS
+  LDFLAGS := $(LDFLAGS) -Wl,-Ttext,$(TEXT_START_ADDRESS)
+  CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) -Wl,-Ttext,$(TEXT_START_ADDRESS)
+endif
+ifdef DATA_START_ADDRESS
+  LDFLAGS := $(LDFLAGS) -Wl,-Tdata,$(DATA_START_ADDRESS)
+  CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) -Wl,-Tdata,$(DATA_START_ADDRESS)
+endif
+ifdef LDSCRIPT
+  LDFLAGS := $(LDFLAGS) -Wl,-T,$(LDSCRIPT)
+  CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) -Wl,-T,$(LDSCRIPT)
+endif
+
+#
+#  ãªãã»ãããã¡ã¤ã«ï¼offset.hï¼ã®çæè¦å
+#
+ifdef OFFSET_TF
+offset.h: $(APPL_CFG) kernel_cfg.timestamp
+	$(CFG) --pass 3 --kernel asp $(INCLUDES) \
+				--rom-image cfg1_out.srec --symbol-table cfg1_out.syms \
+				-T $(OFFSET_TF) $(CFG_TABS) $<
+else
+offset.h: makeoffset.s $(SRCDIR)/utils/genoffset
+	$(PERL) $(SRCDIR)/utils/genoffset makeoffset.s > offset.h
+endif
+
+#
+#  ã«ã¼ãã«ã®ã³ã³ãã£ã®ã¥ã¬ã¼ã·ã§ã³ãã¡ã¤ã«ã®çæ
+#
+cfg1_out.c: $(APPL_CFG)
+	$(CFG) --pass 1 --kernel asp $(INCLUDES) $(CFG_TABS) $<
+
+$(CFG2_OUT_SRCS): kernel_cfg.timestamp
+kernel_cfg.timestamp: $(APPL_CFG) \
+						$(START_OBJS) cfg1_out.o $(END_OBJS) $(HIDDEN_OBJS)
+	$(LINK) $(CFLAGS) $(CFG1_OUT_LDFLAGS) -o $(CFG1_OUT) \
+						$(START_OBJS) cfg1_out.o $(END_OBJS)
+	$(NM) -n $(CFG1_OUT) > cfg1_out.syms
+	$(OBJCOPY) -O srec -S $(CFG1_OUT) cfg1_out.srec
+	$(CFG) --pass 2 --kernel asp $(INCLUDES) \
+				-T $(TARGETDIR)/target.tf $(CFG_TABS) $<
+	touch -r kernel_cfg.c kernel_cfg.timestamp
+
+#
+#  ã«ã¼ãã«ã©ã¤ãã©ãªãã¡ã¤ã«ã®çæ
+#
+libkernel.a: $(OFFSET_H) $(KERNEL_LIB_OBJS)
+	rm -f libkernel.a
+	$(AR) -rcs libkernel.a $(KERNEL_LIB_OBJS)
+	$(RANLIB) libkernel.a
+
+#
+#  ç¹å¥ãªä¾å­é¢ä¿ã®å®ç¾©
+#
+banner.o: kernel_cfg.timestamp $(filter-out banner.o,$(ALL_OBJS)) $(LIBS_DEP)
+
+#
+#  å
+¨ä½ã®ãªã³ã¯
+#
+$(OBJFILE): $(APPL_CFG) kernel_cfg.timestamp $(ALL_OBJS) $(LIBS_DEP)
+	$(LINK) $(CFLAGS) $(LDFLAGS) -o $(OBJFILE) $(START_OBJS) \
+			$(APPL_OBJS) $(SYSSVC_OBJS) $(CFG_OBJS) $(ALL_LIBS) $(END_OBJS)
+	$(NM) -n $(OBJFILE) > $(OBJNAME).syms
+	$(OBJCOPY) -O srec -S $(OBJFILE) $(OBJNAME).srec
+	$(OBJCOPY) -O binary -S $(OBJFILE) $(OBJNAME).bin
+	$(CFG) --pass 3 --kernel asp $(INCLUDES) \
+				--rom-image $(OBJNAME).srec --symbol-table $(OBJNAME).syms \
+				-T $(TARGETDIR)/target_check.tf $(CFG_TABS) $<
+
+#
+#  ãã¤ããªãã¡ã¤ã«ã®çæ
+#
+$(OBJNAME).bin: $(OBJFILE)
+	$(OBJCOPY) -O binary -S $(OBJFILE) $(OBJNAME).bin
+
+#
+#  Sã¬ã³ã¼ããã¡ã¤ã«ã®çæ
+#
+$(OBJNAME).srec: $(OBJFILE)
+	$(OBJCOPY) -O srec -S $(OBJFILE) $(OBJNAME).srec
+
+#
+#  ã³ã³ãã¤ã«çµæã®æ¶å»
+#
+.PHONY: clean
+clean:
+	rm -f \#* *~ *.o $(CLEAN_FILES)
+	rm -f $(OBJFILE) $(OBJNAME).syms $(OBJNAME).srec $(OBJNAME).bin
+	rm -f kernel_cfg.timestamp $(CFG2_OUT_SRCS)
+	rm -f cfg1_out.c $(CFG1_OUT) cfg1_out.syms cfg1_out.srec
+ifndef KERNEL_LIB
+	rm -f libkernel.a
+endif
+	rm -f makeoffset.s offset.h
+
+.PHONY: cleankernel
+cleankernel:
+	rm -rf $(KERNEL_LIB_OBJS)
+	rm -f makeoffset.s offset.h
+
+.PHONY: cleandep
+cleandep:
+	if ! [ -f Makefile.depend ]; then \
+		rm -f kernel_cfg.timestamp $(CFG2_OUT_SRCS); \
+		rm -f cfg1_out.c cfg1_out.o $(CFG1_OUT) cfg1_out.syms cfg1_out.srec; \
+		rm -f makeoffset.s offset.h; \
+	fi
+	rm -f Makefile.depend
+
+.PHONY: realclean
+realclean: cleandep clean
+	rm -f $(REALCLEAN_FILES)
+
+#
+#  ã³ã³ãã£ã®ã¥ã¬ã¼ã¿ãçæãããã¡ã¤ã«ã®ã³ã³ãã¤ã«ã«ã¼ã«ã¨ä¾å­é¢ä¿ä½æ
+#  ã«ã¼ã«ã®å®ç¾©
+#
+#  ã³ã³ãã£ã®ã¥ã¬ã¼ã¿ãçæãããã¡ã¤ã«ã¯ï¼ã¢ããªã±ã¼ã·ã§ã³ãã­ã°ã©ã ç¨ï¼
+#  ã·ã¹ãã ãµã¼ãã¹ç¨ï¼ã«ã¼ãã«ç¨ã®ãã¹ã¦ã®ãªãã·ã§ã³ãä»ãã¦ã³ã³ãã¤ã«
+#  ããï¼
+#
+ALL_CFG_COBJS = $(CFG_COBJS) cfg1_out.o
+ALL_CFG_ASMOBJS = $(CFG_ASMOBJS)
+CFG_CFLAGS = $(APPL_CFLAGS) $(SYSSVC_CFLAGS) $(KERNEL_CFLAGS)
+
+$(ALL_CFG_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(CFG_CFLAGS) $<
+
+$(ALL_CFG_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(CFG_CFLAGS) $<
+
+$(ALL_CFG_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(CFG_CFLAGS)" $< >> Makefile.depend
+
+$(ALL_CFG_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(CFG_CFLAGS) $<
+
+$(ALL_CFG_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(CFG_CFLAGS)" $< >> Makefile.depend
+
+#
+#  ç¹æ®ãªä¾å­é¢ä¿ä½æã«ã¼ã«ã®å®ç¾©
+#
+cfg1_out.depend: $(APPL_CFG)
+	@$(CFG) -M cfg1_out.c $(INCLUDES) $< >> Makefile.depend
+
+makeoffset.d: makeoffset.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-T "makeoffset.s" -O "$(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+#
+#  ä¾å­é¢ä¿ãã¡ã¤ã«ã®çæ
+#
+.PHONY: gendepend
+gendepend:
+	@echo "Generating Makefile.depend."
+
+.PHONY: depend
+ifdef KERNEL_LIB
+depend: cleandep kernel_cfg.timestamp gendepend \
+		cfg1_out.depend cfg1_out.d \
+		$(ALL_OBJS:.o=.d)
+else
+depend: cleandep $(OFFSET_H) kernel_cfg.timestamp gendepend \
+		cfg1_out.depend cfg1_out.d \
+		$(KERNEL_AUX_COBJS:.o=.d) $(KERNEL_ASMOBJS:.o=.d) \
+		$(KERNEL_COBJS:.o=.d) $(KERNEL_LCSRCS:.c=.d) $(ALL_OBJS:.o=.d)
+endif
+
+#
+#  ä¾å­é¢ä¿ãã¡ã¤ã«ãã¤ã³ã¯ã«ã¼ã
+#
+-include Makefile.depend
+
+#
+#  éçºãã¼ã«ã®ã³ãã³ãåã®å®ç¾©
+#
+ifeq ($(TOOL),gcc)
+  #
+  #  GNUéçºç°å¢ç¨
+  #
+  ifdef GCC_TARGET
+    GCC_TARGET_PREFIX = $(GCC_TARGET)-
+  else
+    GCC_TARGET_PREFIX =
+  endif
+  CC = $(GCC_TARGET_PREFIX)gcc
+  CXX = $(GCC_TARGET_PREFIX)g++
+  AS = $(GCC_TARGET_PREFIX)as
+  LD = $(GCC_TARGET_PREFIX)ld
+  AR = $(GCC_TARGET_PREFIX)ar
+  NM = $(GCC_TARGET_PREFIX)nm
+  RANLIB = $(GCC_TARGET_PREFIX)ranlib
+  OBJCOPY = $(GCC_TARGET_PREFIX)objcopy
+  OBJDUMP = $(GCC_TARGET_PREFIX)objdump
+endif
+
+ifdef USE_CXX
+  LINK = $(CXX)
+else
+  LINK = $(CC)
+endif
+
+#
+#  ã³ã³ãã¤ã«ã«ã¼ã«ã®å®ç¾©
+#
+KERNEL_ALL_COBJS = $(KERNEL_COBJS) $(KERNEL_AUX_COBJS)
+
+$(KERNEL_ALL_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_ALL_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_LCOBJS): %.o:
+	$(CC) -DTOPPERS_$(*F) -o $@ -c $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_LCOBJS:.o=.s): %.s:
+	$(CC) -DTOPPERS_$(*F) -o $@ -S $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(SYSSVC_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(SYSSVC_CFLAGS) $<
+
+$(SYSSVC_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(SYSSVC_CFLAGS) $<
+
+$(SYSSVC_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(SYSSVC_CFLAGS) $<
+
+$(APPL_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_CXXOBJS): %.o: %.cpp
+	$(CXX) -c $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_CXXOBJS:.o=.s): %.s: %.cpp
+	$(CXX) -S $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(APPL_CFLAGS) $<
+
+#
+#  ä¾å­é¢ä¿ä½æã«ã¼ã«ã®å®ç¾©
+#
+$(KERNEL_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+$(KERNEL_LCSRCS:.c=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) -T "$($*)" \
+		-O "-DALLFUNC $(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+$(KERNEL_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+$(SYSSVC_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(SYSSVC_CFLAGS)" $< >> Makefile.depend
+
+$(SYSSVC_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(SYSSVC_CFLAGS)" $< >> Makefile.depend
+
+$(APPL_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(APPL_CFLAGS)" $< >> Makefile.depend
+
+$(APPL_CXXOBJS:.o=.d): %.d: %.cpp
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CXX) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(APPL_CFLAGS)" $< >> Makefile.depend
+
+$(APPL_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(APPL_CFLAGS)" $< >> Makefile.depend
+
+#
+#  ããã©ã«ãã³ã³ãã¤ã«ã«ã¼ã«ãä¸æ¸ã
+#
+%.o: %.c
+	@echo "*** Default compile rules should not be used."
+	$(CC) -c $(CFLAGS) $<
+
+%.s: %.c
+	@echo "*** Default compile rules should not be used."
+	$(CC) -S $(CFLAGS) $<
+
+%.o: %.cpp
+	@echo "*** Default compile rules should not be used."
+	$(CXX) -c $(CFLAGS) $<
+
+%.s: %.cpp
+	@echo "*** Default compile rules should not be used."
+	$(CXX) -S $(CFLAGS) $<
+
+%.o: %.S
+	@echo "*** Default compile rules should not be used."
+	$(CC) -c $(CFLAGS) $<
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/TEST/test.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/TEST/test.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/TEST/test.c	(revision 453)
@@ -0,0 +1,179 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2012 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *  D13にUSER-SWを設定した場合、設定により割込みを起動する
+ *  WDTに割込みモードのWDT設定を行う
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#include "target_syssvc.h"
+#include "kernel_cfg.h"
+#include "device.h"
+#include "pinmode.h"
+#include "test.h"
+
+/*
+ *  サービスコールのエラーのログ出力
+ */
+Inline void
+svc_perror(const char *file, int_t line, const char *expr, ER ercd)
+{
+	if (ercd < 0) {
+		t_perror(LOG_ERROR, file, line, expr, ercd);
+	}
+}
+
+#define	SVC_PERROR(expr)	svc_perror(__FILE__, __LINE__, #expr, (expr))
+
+#define SW_PIN   13
+
+
+static void
+pinModex(uint8_t dwPin, uint8_t dwMode){ 
+    int gpionumx = gpio_get_gpiohno(getGpioPin(dwPin), true);
+	GPIO_Init_t init = {0};
+	int gpionum;
+
+	gpionum = gpionumx;
+	syslog_4(LOG_NOTICE, "## dwPin(%d) MD_PIN_MAP(%d) gpionum(%d) gpionumx(%d)  ##", dwPin, getGpioPin(dwPin), gpionum, gpionumx);
+    if(gpionum >= 0){
+        uint8_t function = FUNC_GPIOHS0 + gpionum;
+        fpioa_set_function(getGpioPin(dwPin), function);
+		switch(dwMode){
+		case INPUT:
+			init.mode = GPIO_MODE_INPUT;
+//			init.mode = GPIO_MODE_IT_RISING;
+			init.pull = GPIO_NOPULL;
+			break;
+		case INPUT_PULLDOWN:
+			init.mode = GPIO_MODE_INPUT;
+			init.pull = GPIO_PULLDOWN;
+			break;
+		case INPUT_PULLUP:
+			init.mode = GPIO_MODE_INPUT;
+			init.pull = GPIO_PULLUP;
+			break;
+		case OUTPUT:
+		default:
+			init.mode = GPIO_MODE_OUTPUT;
+			init.pull = GPIO_PULLDOWN;
+			break;
+		}
+        gpio_setup(TADR_GPIOHS_BASE, &init, (uint8_t)gpionum);
+    }
+    return ;
+}
+
+/*
+ *  WDT割込みコールバック
+ */
+static void
+wdt_int_handler(WDT_Handle_t *hwdt)
+{
+	syslog_1(LOG_NOTICE, "wdt_int_handler[%x] !", hwdt);
+}
+
+/*
+ *  USER-SW割込みハンドラ
+ */
+void
+sw_int_handler(void)
+{
+	uint32_t ipr = sil_rew_mem((uint32_t *)(TADR_GPIOHS_BASE+TOFF_GPIOHS_RISE_IP));
+	uint32_t ipf = sil_rew_mem((uint32_t *)(TADR_GPIOHS_BASE+TOFF_GPIOHS_FALL_IP));
+	syslog_2(LOG_EMERG, "## sw_int_handler r[%08x] f(%08x] ##", ipr, ipf);
+	sil_wrw_mem((uint32_t *)(TADR_GPIOHS_BASE+TOFF_GPIOHS_RISE_IP), ipr);
+}
+
+/*
+ *  メインタスク
+ */
+void
+main_task(intptr_t exinf)
+{
+	WDT_Handle_t *hwdt;
+	ER_UINT	ercd;
+	int     i;
+	uint32_t cnt;
+
+	SVC_PERROR(syslog_msk_log(LOG_UPTO(LOG_INFO), LOG_UPTO(LOG_EMERG)));
+	syslog(LOG_NOTICE, "Sample program starts (exinf = %d).", (int_t) exinf);
+
+	/*
+	 *  シリアルポートの初期化
+	 *
+	 *  システムログタスクと同じシリアルポートを使う場合など，シリアル
+	 *  ポートがオープン済みの場合にはここでE_OBJエラーになるが，支障は
+	 *  ない．
+	 */
+	ercd = serial_opn_por(TASK_PORTID);
+	if (ercd < 0 && MERCD(ercd) != E_OBJ) {
+		syslog(LOG_ERROR, "%s (%d) reported by `serial_opn_por'.",
+									itron_strerror(ercd), SERCD(ercd));
+	}
+	SVC_PERROR(serial_ctl_por(TASK_PORTID,
+							(IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV)));
+
+	pinModex(SW_PIN, INPUT);
+	hwdt = wdt_init(WDOG1_PORTID);
+	hwdt->callback = wdt_int_handler;
+	cnt = wdt_start(hwdt, WDT_MODE_INTERRUPT, 10000);
+	syslog_1(LOG_NOTICE, "## cnt(%d) ##", cnt);
+	for(i = 0 ; i < 500000 ; i++){
+		syslog_1(LOG_NOTICE, "## sw(%d) ##", digitalRead(SW_PIN));
+		dly_tsk(1000);
+		if(i == 15){
+			wdt_deinit(hwdt);
+			syslog_0(LOG_NOTICE, "WDT STOP");
+		}
+	}
+	slp_tsk();
+
+	syslog(LOG_NOTICE, "Sample program ends.");
+	SVC_PERROR(ext_ker());
+	assert(0);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/TEST/test.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/TEST/test.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/TEST/test.cfg	(revision 453)
@@ -0,0 +1,24 @@
+/*
+ *  $Id$
+ */
+
+/*
+ *  サンプルプログラム(1)のシステムコンフィギュレーションファイル
+ */
+INCLUDE("target_timer.cfg");
+INCLUDE("syssvc/syslog.cfg");
+INCLUDE("syssvc/banner.cfg");
+INCLUDE("syssvc/serial.cfg");
+INCLUDE("syssvc/logtask.cfg");
+INCLUDE("pdic/k210/device.cfg");
+INCLUDE("monitor/monitor.cfg");
+
+#include "test.h"
+
+ATT_INI({ TA_NULL, 0, rtc_init });
+ATT_INI({ TA_NULL, 0, rtc_info_init });
+
+CRE_TSK(MAIN_TASK, { TA_NULL, 0, main_task, MAIN_PRIORITY, STACK_SIZE, NULL });
+
+DEF_INH(IRQ_VECTOR_GPIOHS0, { TA_NULL, sw_int_handler });
+CFG_INT(IRQ_VECTOR_GPIOHS0, { TA_ENAINT | 0, -3 });
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/TEST/test.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/TEST/test.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/OBJ/K210_GCC/TEST/test.h	(revision 453)
@@ -0,0 +1,80 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ *
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ *
+ *  $Id$
+ */
+
+/*
+ *		サンプルプログラム(1)のヘッダファイル
+ */
+
+/*
+ *  ターゲット依存の定義
+ */
+#include "target_test.h"
+
+/*
+ *  各タスクの優先度の定義
+ */
+
+#define MAIN_PRIORITY	5		/* メインタスクの優先度 */
+								/* HIGH_PRIORITYより高くすること */
+
+/*
+ *  ターゲットに依存する可能性のある定数の定義
+ */
+
+#ifndef TASK_PORTID
+#define	TASK_PORTID		1			/* 文字入力するシリアルポートID */
+#endif /* TASK_PORTID */
+
+#ifndef STACK_SIZE
+#define	STACK_SIZE		4096		/* タスクのスタックサイズ */
+#endif /* STACK_SIZE */
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+#ifndef TOPPERS_MACRO_ONLY
+
+extern void	main_task(intptr_t exinf);
+extern int8_t get_cup_command(void);
+extern void sw_int_handler(void);
+
+#endif /* TOPPERS_MACRO_ONLY */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/README.txt
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/README.txt	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/README.txt	(revision 453)
@@ -0,0 +1,47 @@
+
+	TOPPERS/ASP Kernel（Release 1.9.3）
+		Toyohashi Open Platform for Embedded Real-Time Systems/
+		Advanced Standard Profile Kernel
+
+TOPPERS/ASPカーネル（以下，ASPカーネル）は，TOPPERS新世代カーネルの基盤
+となるものとして，TOPPERSプロジェクトにおいて開発したリアルタイムカーネ
+ルです．μITRON4.0仕様のスタンダードプロファイル準拠のリアルタイムカー
+ネルであるTOPPERS/JSPカーネルを拡張・改良する形で開発しました．
+
+【最初に読むべきドキュメント】
+
+ASPカーネルのユーザーズマニュアルが，doc/user.txtにあります．ASPカーネ
+ルを使用する場合には，まずはこのドキュメントからお読み下さい．
+
+【ファイルの閲覧にあたって】
+
+ASPカーネルのドキュメント（プレーンテキストファイル）およびソースファイ
+ルを読む際には，TABを4に設定してください．
+
+【利用条件】
+
+ASPカーネルの利用条件は，各ファイルの先頭に表示されているTOPPERSライセ
+ンスです．TOPPERSライセンスに関するFAQが，以下のページにあります．
+
+	http://www.toppers.jp/faq/faq_ct12.html
+
+【質問・バグレポート・意見等の送付先】
+
+ASPカーネルをより良いものにするためのご意見等を歓迎します．ASPカーネル
+に関する質問やバグレポート，ご意見等は，TOPPERSプロジェクトの会員は
+TOPPERS開発者メーリングリスト（dev@toppers.jp）宛またはASPカーネルのバ
+グトラッキングシステム（Trac）に，その他の方はTOPPERSユーザーズメーリン
+グリスト（users@toppers.jp）宛にお願いします．
+
+TOPPERSユーザーズメーリングリストへの登録方法については，以下のページに
+説明があります．
+
+	http://www.toppers.jp/community.html
+
+【ポーティングにあたって】
+
+ASPカーネルを，TOPPERSプロジェクトからオープンソースにすることを前提に，
+未サポートのターゲットにポーティングされる場合には，あらかじめご相談く
+ださると幸いです．
+
+以上
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/README_RISC_V.txt
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/README_RISC_V.txt	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/README_RISC_V.txt	(revision 453)
@@ -0,0 +1,18 @@
+
+RISC-V HI-FIVE1/K210アーキテクチャ・GCC依存部パッケージ（担当：TOPPERSプロジェクト教育WG）
+
+パッケージ：
+asp_arch_riscv_gcc-1.9.3.tar.gz
+
+ディレクトリ：
+arch/gcc
+arch/riscv_gcc
+target/hifive1_gcc
+
+対応する非依存部のパッケージ：
+1.9.*
+
+リリース日：
+2019/10/11
+
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/gcc/MANIFEST
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/gcc/MANIFEST	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/gcc/MANIFEST	(revision 453)
@@ -0,0 +1,4 @@
+PACKAGE asp
+
+MANIFEST
+tool_stddef.h
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/gcc/tool_stddef.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/gcc/tool_stddef.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/gcc/tool_stddef.h	(revision 453)
@@ -0,0 +1,211 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		t_stddef.hの開発環境依存部（GCC用）
+ */
+
+#ifndef TOPPERS_TOOL_STDDEF_H
+#define TOPPERS_TOOL_STDDEF_H
+
+/*
+ *  コンパイラの拡張機能のためのマクロ定義
+ */
+#ifndef __cplusplus					/* C++にはinline がある */
+#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
+									/* C99にはinline がある */
+#define inline	__inline__			/* インライン関数 */
+#endif /* !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L */
+#endif /* __cplusplus */
+
+#define Inline	static __inline__	/* インライン関数 */
+
+#ifndef __cplusplus					/* C++にはasmがある */
+#define asm		__asm__				/* インラインアセンブラ */
+#endif /* __cplusplus */
+
+#define Asm		__asm__ volatile	/* インラインアセンブラ（最適化抑止）*/
+
+#define NoReturn	__attribute__((__noreturn__))
+									/* リターンしない関数 */
+
+/*
+ *  開発環境の標準インクルードファイルの利用
+ *
+ *  NULLの定義をstddef.hから，INT_MAX，INT_MIN，UINT_MAX，LONG_MAX，
+ *  LONG_MIN，ULONG_MAX，CHAR_BITの定義をlimits.hから取り込む．
+ *
+ *  C++/EC++では，標準仕様上はこれらのインクルードファイルが用意されて
+ *  いるとは限らないので注意が必要である（ほとんどの開発環境で用意され
+ *  ている）．
+ */
+#ifndef TOPPERS_MACRO_ONLY
+#include <stddef.h>
+#include <limits.h>
+#endif /* TOPPERS_MACRO_ONLY */
+
+/*
+ *  stdint.hの代用となる定義
+ *
+ *  開発環境にstdint.hが用意されておらず，各整数型のサイズがあるパター
+ *  ンに当てはまる場合に，stdint.hの代用となる定義を与える．
+ *
+ *  TOPPERS_STDINT_TYPE1: char/short/int/long longのビット長がそれぞれ
+ *                        8/16/32/64ビットで，ポインタのビット長がlong
+ *                        のビット長と一致する場合
+ */
+#ifdef TOPPERS_STDINT_TYPE1
+
+/*
+ *  コンパイラ依存のデータ型の定義
+ */
+#ifndef TOPPERS_MACRO_ONLY
+
+typedef signed char			int8_t;		/* 符号付き8ビット整数 */
+typedef unsigned char		uint8_t;	/* 符号無し8ビット整数 */
+
+typedef signed short		int16_t;	/* 符号付き16ビット整数 */
+typedef unsigned short		uint16_t;	/* 符号無し16ビット整数 */
+
+typedef signed int			int32_t;	/* 符号付き32ビット整数 */
+typedef unsigned int		uint32_t;	/* 符号無し32ビット整数 */
+
+#if ___int64_t_defined
+typedef __int64_t	int64_t;			/* 符号付き64ビット整数 */
+typedef __uint64_t	uint64_t;			/* 符号無し64ビット整数 */
+#else
+typedef signed long long	int64_t;	/* 符号付き64ビット整数 */
+typedef unsigned long long	uint64_t;	/* 符号無し64ビット整数 */
+#endif
+
+typedef int8_t				int_least8_t;	/* 8ビット以上の符号付き整数 */
+typedef uint8_t				uint_least8_t;	/* 8ビット以上の符号無し整数 */
+
+typedef __intptr_t			intptr_t;	/* ポインタを格納できる符号付き整数 */
+typedef __uintptr_t			uintptr_t;	/* ポインタを格納できる符号無し整数 */
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+/*
+ *  コンパイラ依存のデータ型の整数定数を作るマクロ
+ */
+#ifndef INT8_C
+#define INT8_C(val)			(val)
+#endif /* INT8_C */
+
+#ifndef UINT8_C
+#define UINT8_C(val)		(val ## U)
+#endif /* UINT8_C */
+
+#ifndef INT16_C
+#define INT16_C(val)		(val)
+#endif /* INT16_C */
+
+#ifndef UINT16_C
+#define UINT16_C(val)		(val ## U)
+#endif /* UINT16_C */
+
+#ifndef INT32_C
+#define INT32_C(val)		(val)
+#endif /* INT32_C */
+
+#ifndef UINT32_C
+#define UINT32_C(val)		(val ## U)
+#endif /* UINT32_C */
+
+#ifndef INT64_C
+#define INT64_C(val)		(val ## LL)
+#endif /* INT64_C */
+
+#ifndef UINT64_C
+#define UINT64_C(val)		(val ## ULL)
+#endif /* UINT64_C */
+
+/*
+ *  コンパイラ依存のデータ型に格納できる最大値と最小値の定義
+ */
+#define INT8_MAX			SCHAR_MAX
+#define INT8_MIN			SCHAR_MIN
+#define UINT8_MAX			UCHAR_MAX
+
+#define INT16_MAX			SHRT_MAX
+#define INT16_MIN			SHRT_MIN
+#define UINT16_MAX			USHRT_MAX
+
+#define INT32_MAX			INT_MAX
+#define INT32_MIN			INT_MIN
+#define UINT32_MAX			UINT_MAX
+
+#define INT64_MAX			LLONG_MAX
+#define INT64_MIN			LLONG_MIN
+#define UINT64_MAX			ULLONG_MAX
+
+#define INT_LEAST8_MAX		INT8_MAX
+#define INT_LEAST8_MIN		INT8_MIN
+#define UINT_LEAST8_MAX		INT8_MAX
+
+#else
+#ifndef TOPPERS_MACRO_ONLY
+#include <stdint.h>
+#endif /* TOPPERS_MACRO_ONLY */
+#endif /* TOPPERS_STDINT_TYPE1 */
+
+/*
+ *  浮動小数点型に関する定義
+ *
+ *  TOPPERS_STDFLOAT_TYPE1: floatがIEEE754準拠の単精度浮動小数点数，
+ *							doubleが倍精度浮動小数点数の場合
+ */
+#ifdef TOPPERS_STDFLOAT_TYPE1
+#ifndef TOPPERS_MACRO_ONLY
+
+typedef float		float32_t;			/* IEEE754準拠の単精度浮動小数点数 */
+typedef double		double64_t;			/* IEEE754準拠の倍精度浮動小数点数 */
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+#define FLOAT32_MIN		1.17549435e-38F
+#define FLOAT32_MAX		3.40282347e+38F
+#define DOUBLE64_MIN	2.2250738585072014e-308
+#define DOUBLE64_MAX	1.7976931348623157e+308
+
+#endif /* TOPPERS_STDFLOAT_TYPE1 */
+#endif /* TOPPERS_TOOL_STDDEF_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/logtrace/MANIFEST
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/logtrace/MANIFEST	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/logtrace/MANIFEST	(revision 453)
@@ -0,0 +1,6 @@
+PACKAGE asp
+
+MANIFEST
+trace_config.c
+trace_config.h
+trace_dump.c
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/logtrace/trace_config.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/logtrace/trace_config.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/logtrace/trace_config.c	(revision 453)
@@ -0,0 +1,249 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		トレースログ機能
+ */
+
+#include "kernel_impl.h"
+#include "task.h"
+#include "time_event.h"
+#include <sil.h>
+
+/*
+ *  トレースログバッファとそれにアクセスするためのポインタ
+ */
+SYSLOG	trace_buffer[TCNT_TRACE_BUFFER];	/* トレースログバッファ */
+uint_t	trace_count;				/* トレースログバッファ中のログの数 */
+uint_t	trace_head;					/* 先頭のトレースログの格納位置 */
+uint_t	trace_tail;					/* 次のトレースログの格納位置 */
+MODE	trace_mode;					/* トレースモード */
+
+/*
+ *  トレースログ機能の初期化
+ */
+void
+trace_initialize(intptr_t exinf)
+{
+	MODE	mode = ((MODE) exinf);
+
+	trace_count = 0U;
+	trace_head = 0U;
+	trace_tail = 0U;
+	trace_mode = mode;
+}     
+
+/*
+ *  トレースログの開始
+ */
+ER
+trace_sta_log(MODE mode)
+{
+	if ((mode & TRACE_CLEAR) != 0U) {
+		trace_count = 0U;
+		trace_head = 0U;
+		trace_tail = 0U;
+	}
+	trace_mode = mode;
+	return(E_OK);
+}     
+
+/* 
+ *  トレースログの書込み
+ */
+ER
+trace_wri_log(TRACE *p_trace)
+{
+	SIL_PRE_LOC;
+
+	if (trace_mode != TRACE_STOP) {
+		SIL_LOC_INT();
+
+		/*
+		 *  トレース時刻の設定
+		 *
+		 *  LOG_WRI_LOG_ENTERから呼ばれた場合にp_trace->logtimを書き換
+		 *  えてしまうのは気持ちが悪いが，wri_logの方で上書きするため問
+		 *  題はない．
+		 */
+		p_trace->logtim = TRACE_GET_TIM();
+
+		/*
+		 *  トレースバッファに記録
+		 */
+		trace_buffer[trace_tail] = *p_trace;
+		trace_tail++;
+		if (trace_tail >= TCNT_TRACE_BUFFER) {
+			trace_tail = 0U;
+		}
+		if (trace_count < TCNT_TRACE_BUFFER) {
+			trace_count++;
+			if (trace_count >= TCNT_TRACE_BUFFER
+						&& (trace_mode & TRACE_AUTOSTOP) != 0U) {
+				trace_mode = TRACE_STOP;
+			}
+		}
+		else {
+			trace_head = trace_tail;
+		}
+
+		SIL_UNL_INT();
+	}
+	return(E_OK);
+}
+
+/*
+ *  トレースログの読出し
+ */
+ER
+trace_rea_log(TRACE *p_trace)
+{
+	ER_UINT	ercd;
+	SIL_PRE_LOC;
+
+	SIL_LOC_INT();
+
+	/*
+	 *  トレースログバッファからの取出し
+	 */
+	if (trace_count > 0U) {
+		*p_trace = trace_buffer[trace_head];
+		trace_count--;
+		trace_head++;
+		if (trace_head >= TCNT_TRACE_BUFFER) {
+			trace_head = 0U;
+		}
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_OBJ;
+	}
+
+	SIL_UNL_INT();
+	return(ercd);
+}
+
+/*
+ *  トレースログを出力するためのライブラリ関数
+ */
+
+void
+trace_write_0(uint_t type)
+{
+	TRACE	trace;
+
+	trace.logtype = type;
+	(void) trace_wri_log(&trace);
+}
+
+void
+trace_write_1(uint_t type, intptr_t arg1)
+{
+	TRACE	trace;
+
+	trace.logtype = type;
+	trace.loginfo[0] = arg1;
+	(void) trace_wri_log(&trace);
+}
+
+void
+trace_write_2(uint_t type, intptr_t arg1, intptr_t arg2)
+{
+	TRACE	trace;
+
+	trace.logtype = type;
+	trace.loginfo[0] = arg1;
+	trace.loginfo[1] = arg2;
+	(void) trace_wri_log(&trace);
+}
+
+void
+trace_write_3(uint_t type, intptr_t arg1, intptr_t arg2, intptr_t arg3)
+{
+	TRACE	trace;
+
+	trace.logtype = type;
+	trace.loginfo[0] = arg1;
+	trace.loginfo[1] = arg2;
+	trace.loginfo[2] = arg3;
+	(void) trace_wri_log(&trace);
+}
+
+/*
+ *  アセンブリ言語で記述されるコードからトレースログを出力するための関
+ *  数
+ */
+
+void
+log_dsp_enter(TCB *p_tcb)
+{
+	trace_1(LOG_TYPE_DSP|LOG_ENTER, p_tcb);
+}
+
+void
+log_dsp_leave(TCB *p_tcb)
+{
+	trace_1(LOG_TYPE_DSP|LOG_LEAVE, p_tcb);
+}
+
+void
+log_inh_enter(INHNO inhno)
+{
+	trace_1(LOG_TYPE_INH|LOG_ENTER, inhno);
+}
+
+void
+log_inh_leave(INHNO inhno)
+{
+	trace_1(LOG_TYPE_INH|LOG_LEAVE, inhno);
+}
+
+void
+log_exc_enter(EXCNO excno)
+{
+	trace_1(LOG_TYPE_EXC|LOG_ENTER, excno);
+}
+
+void
+log_exc_leave(EXCNO excno)
+{
+	trace_1(LOG_TYPE_EXC|LOG_LEAVE, excno);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/logtrace/trace_config.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/logtrace/trace_config.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/logtrace/trace_config.h	(revision 453)
@@ -0,0 +1,181 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2012 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		トレースログに関する設定
+ *
+ *  このインクルードファイルは，target_config.hおよびtarget_syssvc.hの
+ *  みからインクルードされる．また，トレースログ機能の初期化や記録の開
+ *  始／停止，トレースログのダンプを行うプログラムからインクルードする
+ *  ことを想定している．
+ */
+
+#ifndef TOPPERS_TRACE_CONFIG_H
+#define TOPPERS_TRACE_CONFIG_H
+
+/*
+ *  トレースログバッファのサイズ
+ */
+#ifndef TCNT_TRACE_BUFFER
+#define TCNT_TRACE_BUFFER	1024
+#endif /* TCNT_TRACE_BUFFER */
+
+/*
+ *  トレース時刻の取得方法
+ */
+#ifndef TRACE_GET_TIM
+#define TRACE_GET_TIM()		(current_time)
+#endif /* TRACE_GET_TIM */
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  トレースログのデータ構造
+ *
+ *  システムログ機能のログ情報のデータ構造と同じものを用いる．
+ */
+#include <t_syslog.h>
+typedef	SYSLOG	TRACE;
+
+/*
+ *  トレースログバッファとそれにアクセスするためのポインタ
+ */
+extern TRACE	trace_buffer[];		/* トレースログバッファ */
+extern uint_t	trace_count;		/* トレースログバッファ中のログの数 */
+extern uint_t	trace_head;			/* 先頭のトレースログの格納位置 */
+extern uint_t	trace_tail;			/* 次のトレースログの格納位置 */
+extern uint_t	trace_lost;			/* 失われたトレースの数 */
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+/*
+ *  トレースモードの定義
+ */
+#define TRACE_STOP			UINT_C(0x00)	/* トレース停止 */
+#define TRACE_RINGBUF		UINT_C(0x01)	/* リングバッファモード */
+#define TRACE_AUTOSTOP		UINT_C(0x02)	/* 自動停止モード */
+#define TRACE_CLEAR			UINT_C(0x04)	/* トレースログのクリア */
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  トレースログ機能の初期化
+ *
+ *  トレースログ機能を初期化する．初期化ルーチンとして登録することを想
+ *  定している．引数により次の動作を行う．
+ *
+ *  TRACE_STOP：初期化のみでトレースは開始しない．
+ *  TRACE_RINGBUF：リングバッファモードでトレースを開始．
+ *  TRACE_AUTOSTOP：自動停止モードでトレースを開始．
+ */
+extern void	trace_initialize(intptr_t exinf);
+
+/*
+ *  トレースログの開始
+ *
+ *  トレースログの記録を開始／停止する．引数により次の動作を行う．
+ *
+ *  TRACE_STOP：トレースを停止．
+ *  TRACE_RINGBUF：リングバッファモードでトレースを開始．
+ *  TRACE_AUTOSTOP：自動停止モードでトレースを開始．
+ *  TRACE_CLEAR：トレースログをクリア．
+ */
+extern ER	trace_sta_log(MODE mode);
+
+/*
+ *  トレースログの書込み
+ */
+extern ER	trace_wri_log(TRACE *p_trace);
+
+/*
+ *  トレースログの読出し
+ */
+extern ER	trace_rea_log(TRACE *p_trace);
+
+/* 
+ *  トレースログのダンプ（trace_dump.c）
+ *
+ *  トレースログをダンプする．終了処理ルーチンとして登録することも想定
+ *  している．引数として，ダンプ先となる文字出力関数へのポインタを渡す．
+ *  ターゲット依存の低レベル文字出力を利用する場合には，target_putcを渡
+ *  す．
+ */
+extern void	trace_dump(intptr_t exinf);
+
+/*
+ *  トレースログを出力するためのライブラリ関数
+ */
+extern void	trace_write_0(uint_t type);
+extern void	trace_write_1(uint_t type, intptr_t arg1);
+extern void	trace_write_2(uint_t type, intptr_t arg1, intptr_t arg2);
+extern void	trace_write_3(uint_t type, intptr_t arg1, intptr_t arg2,
+														intptr_t arg3);
+
+/*
+ *  トレースログを出力するためのマクロ
+ */
+
+#define trace_0(type) \
+				trace_write_0(type)
+
+#define trace_1(type, arg1) \
+				trace_write_1(type, (intptr_t)(arg1))
+
+#define trace_2(type, arg1, arg2) \
+				trace_write_2(type, (intptr_t)(arg1), (intptr_t)(arg2))
+
+#define trace_3(type, arg1, arg2, arg3) \
+				trace_write_3(type, (intptr_t)(arg1), (intptr_t)(arg2), \
+						(intptr_t)(arg3))
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+/*
+ *  トレースログ方法の設定
+ */
+#define LOG_TSKSTAT(p_tcb)		trace_2(LOG_TYPE_TSKSTAT, p_tcb, p_tcb->tstat)
+
+#define LOG_DSP_LEAVE(p_tcb)	trace_1(LOG_TYPE_DSP|LOG_LEAVE, p_tcb)
+
+#define LOG_SYSLOG_WRI_LOG_ENTER(prio, p_syslog) \
+								trace_wri_log((TRACE *) p_syslog)
+
+#endif /* TOPPERS_TRACE_CONFIG_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/logtrace/trace_dump.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/logtrace/trace_dump.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/logtrace/trace_dump.c	(revision 453)
@@ -0,0 +1,154 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2007-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		トレースログのダンプ
+ */
+
+#include "kernel_impl.h"
+#include "task.h"
+#include <log_output.h>
+
+/* 
+ *  カーネル情報の取出し
+ */
+static intptr_t
+get_tskid(intptr_t info)
+{
+	TCB		*p_tcb;
+	ID		tskid;
+
+	p_tcb = (TCB *) info;
+	if (p_tcb == NULL) {
+		tskid = 0;
+	}
+	else {
+		tskid = TSKID(p_tcb);
+	}
+	return((intptr_t) tskid);
+}
+
+static intptr_t
+get_tskstat(intptr_t info)
+{
+	uint_t		tstat;
+	const char	*tstatstr;
+
+	tstat = (uint_t) info;
+	switch (tstat & (TS_RUNNABLE|TS_WAITING|TS_SUSPENDED)) {
+	case TS_DORMANT:
+		tstatstr = "DORMANT";
+		break;
+	case TS_RUNNABLE:
+		tstatstr = "RUNNABLE";
+		break;
+	case TS_WAITING:
+		tstatstr = "WAITING";
+		break;
+	case TS_SUSPENDED:
+		tstatstr = "SUSPENDED";
+		break;
+	case TS_WAITING|TS_SUSPENDED:
+		tstatstr = "WAITING-SUSPENDED";
+		break;
+	default:
+		tstatstr = "unknown state";
+		break;
+	}
+	return((intptr_t) tstatstr);
+}
+
+/* 
+ *  トレースログの表示
+ */
+static void
+trace_print(TRACE *p_trace, void (*putc)(char))
+{
+	intptr_t	traceinfo[TMAX_LOGINFO + 1];
+	const char	*tracemsg;
+	int_t		i;
+
+	traceinfo[0] = (intptr_t)(p_trace->logtim);
+	syslog_printf("[%d] ", traceinfo, putc);
+
+	switch (p_trace->logtype) {
+	case LOG_TYPE_TSKSTAT:
+		traceinfo[0] = get_tskid(p_trace->loginfo[0]);
+		traceinfo[1] = get_tskstat(p_trace->loginfo[1]);
+		tracemsg = "task %d becomes %s.";
+		break;
+	case LOG_TYPE_DSP|LOG_LEAVE:
+		traceinfo[0] = get_tskid(p_trace->loginfo[0]);
+		tracemsg = "dispatch to task %d.";
+		break;
+	case LOG_TYPE_COMMENT:
+		for (i = 1; i < TMAX_LOGINFO; i++) {
+			traceinfo[i-1] = p_trace->loginfo[i];
+		}
+		tracemsg = (const char *)(p_trace->loginfo[0]);
+		break;
+	case LOG_TYPE_ASSERT:
+		traceinfo[0] = p_trace->loginfo[0];
+		traceinfo[1] = p_trace->loginfo[1];
+		traceinfo[2] = p_trace->loginfo[2];
+		tracemsg = "%s:%u: Assertion `%s' failed.";
+		break;
+	default:
+		traceinfo[0] = p_trace->logtype;
+		tracemsg = "unknown trace log type: %d.";
+		break;
+	}
+	syslog_printf(tracemsg, traceinfo, putc);
+	(*putc)('\n');
+}
+
+/* 
+ *  トレースログのダンプ
+ */
+void
+trace_dump(intptr_t exinf)
+{
+	TRACE	trace;
+	void	(*putc)(char);
+
+	putc = (void (*)(char)) exinf;
+	while (trace_rea_log(&trace) >= 0) {
+		trace_print(&trace, putc);
+	}
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/MANIFEST
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/MANIFEST	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/MANIFEST	(revision 453)
@@ -0,0 +1,25 @@
+PACKAGE asp
+
+MANIFEST
+encoding.h
+Makefile.prc
+makeoffset.c
+prc_cfg1_out.h
+prc_config.c
+prc_config.h
+prc_def.csv
+prc_kernel.h
+prc_offset.tf
+prc_rename.def
+prc_rename.h
+prc_sil.h
+prc_stddef.h
+prc_support.S
+prc_test.h
+prc_timer.c
+prc_timer.cfg
+prc_timer.h
+prc_unrename.h
+riscv32elf.ld
+riscv64elf.ld
+start.S
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/Makefile.prc
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/Makefile.prc	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/Makefile.prc	(revision 453)
@@ -0,0 +1,32 @@
+#
+#		Makefileのプロセッサ依存部（RISC-V用）
+#
+
+#
+#  プロセッサ依存部ディレクトリ名の定義
+#
+PRCDIR = $(SRCDIR)/arch/$(PRC)_$(TOOL)
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(PRCDIR)
+COPTS := $(COPTS)
+LDFLAGS := $(LDFLAGS) -nostdlib -nostartfiles
+
+#
+#  カーネルに関する定義
+#
+KERNEL_DIR := $(KERNEL_DIR) $(PRCDIR)
+KERNEL_ASMOBJS := $(KERNEL_ASMOBJS) prc_support.o
+KERNEL_COBJS := $(KERNEL_COBJS) prc_config.o prc_timer.o
+
+#
+#  コンフィギュレータ関係の変数の定義
+#
+CFG_TABS := $(CFG_TABS) --cfg1-def-table $(PRCDIR)/prc_def.csv
+
+#
+#  オフセットファイル生成のための定義
+#
+OFFSET_TF = $(PRCDIR)/prc_offset.tf
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/encoding.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/encoding.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/encoding.h	(revision 453)
@@ -0,0 +1,1383 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *   Copyright 2016 SiFive, Inc.
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ */
+/* Copyright 2018 Canaan Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RISCV_CSR_ENCODING_H
+#define RISCV_CSR_ENCODING_H
+
+#define MSTATUS_UIE         0x00000001
+#define MSTATUS_SIE         0x00000002
+#define MSTATUS_HIE         0x00000004
+#define MSTATUS_MIE         0x00000008
+#define MSTATUS_UPIE        0x00000010
+#define MSTATUS_SPIE        0x00000020
+#define MSTATUS_HPIE        0x00000040
+#define MSTATUS_MPIE        0x00000080
+#define MSTATUS_SPP         0x00000100
+#define MSTATUS_HPP         0x00000600
+#define MSTATUS_MPP         0x00001800
+#define MSTATUS_FS          0x00006000
+#define MSTATUS_XS          0x00018000
+#define MSTATUS_MPRV        0x00020000
+#define MSTATUS_PUM         0x00040000
+#define MSTATUS_MXR         0x00080000
+#define MSTATUS_VM          0x1F000000
+#define MSTATUS32_SD        0x80000000
+#define MSTATUS64_SD        0x8000000000000000
+
+#define SSTATUS_UIE         0x00000001
+#define SSTATUS_SIE         0x00000002
+#define SSTATUS_UPIE        0x00000010
+#define SSTATUS_SPIE        0x00000020
+#define SSTATUS_SPP         0x00000100
+#define SSTATUS_FS          0x00006000
+#define SSTATUS_XS          0x00018000
+#define SSTATUS_PUM         0x00040000
+#define SSTATUS32_SD        0x80000000
+#define SSTATUS64_SD        0x8000000000000000
+
+#define DCSR_XDEBUGVER      (3<<30)
+#define DCSR_NDRESET        (1<<29)
+#define DCSR_FULLRESET      (1<<28)
+#define DCSR_EBREAKM        (1<<15)
+#define DCSR_EBREAKH        (1<<14)
+#define DCSR_EBREAKS        (1<<13)
+#define DCSR_EBREAKU        (1<<12)
+#define DCSR_STOPCYCLE      (1<<10)
+#define DCSR_STOPTIME       (1<<9)
+#define DCSR_CAUSE          (7<<6)
+#define DCSR_DEBUGINT       (1<<5)
+#define DCSR_HALT           (1<<3)
+#define DCSR_STEP           (1<<2)
+#define DCSR_PRV            (3<<0)
+
+#define DCSR_CAUSE_NONE     0
+#define DCSR_CAUSE_SWBP     1
+#define DCSR_CAUSE_HWBP     2
+#define DCSR_CAUSE_DEBUGINT 3
+#define DCSR_CAUSE_STEP     4
+#define DCSR_CAUSE_HALT     5
+
+#define MCONTROL_TYPE(xlen)    (0xfULL<<((xlen)-4))
+#define MCONTROL_DMODE(xlen)   (1ULL<<((xlen)-5))
+#define MCONTROL_MASKMAX(xlen) (0x3fULL<<((xlen)-11))
+
+#define MCONTROL_SELECT     (1<<19)
+#define MCONTROL_TIMING     (1<<18)
+#define MCONTROL_ACTION     (0x3f<<12)
+#define MCONTROL_CHAIN      (1<<11)
+#define MCONTROL_MATCH      (0xf<<7)
+#define MCONTROL_M          (1<<6)
+#define MCONTROL_H          (1<<5)
+#define MCONTROL_S          (1<<4)
+#define MCONTROL_U          (1<<3)
+#define MCONTROL_EXECUTE    (1<<2)
+#define MCONTROL_STORE      (1<<1)
+#define MCONTROL_LOAD       (1<<0)
+
+#define MCONTROL_TYPE_NONE      0
+#define MCONTROL_TYPE_MATCH     2
+
+#define MCONTROL_ACTION_DEBUG_EXCEPTION   0
+#define MCONTROL_ACTION_DEBUG_MODE        1
+#define MCONTROL_ACTION_TRACE_START       2
+#define MCONTROL_ACTION_TRACE_STOP        3
+#define MCONTROL_ACTION_TRACE_EMIT        4
+
+#define MCONTROL_MATCH_EQUAL     0
+#define MCONTROL_MATCH_NAPOT     1
+#define MCONTROL_MATCH_GE        2
+#define MCONTROL_MATCH_LT        3
+#define MCONTROL_MATCH_MASK_LOW  4
+#define MCONTROL_MATCH_MASK_HIGH 5
+
+#define MIP_SSIP            (1 << IRQ_S_SOFT)
+#define MIP_HSIP            (1 << IRQ_H_SOFT)
+#define MIP_MSIP            (1 << IRQ_M_SOFT)
+#define MIP_STIP            (1 << IRQ_S_TIMER)
+#define MIP_HTIP            (1 << IRQ_H_TIMER)
+#define MIP_MTIP            (1 << IRQ_M_TIMER)
+#define MIP_SEIP            (1 << IRQ_S_EXT)
+#define MIP_HEIP            (1 << IRQ_H_EXT)
+#define MIP_MEIP            (1 << IRQ_M_EXT)
+
+#define SIP_SSIP MIP_SSIP
+#define SIP_STIP MIP_STIP
+
+#define PRV_U 0
+#define PRV_S 1
+#define PRV_H 2
+#define PRV_M 3
+
+#define VM_MBARE 0
+#define VM_MBB   1
+#define VM_MBBID 2
+#define VM_SV32  8
+#define VM_SV39  9
+#define VM_SV48  10
+
+#define IRQ_S_SOFT   1
+#define IRQ_H_SOFT   2
+#define IRQ_M_SOFT   3
+#define IRQ_S_TIMER  5
+#define IRQ_H_TIMER  6
+#define IRQ_M_TIMER  7
+#define IRQ_S_EXT    9
+#define IRQ_H_EXT    10
+#define IRQ_M_EXT    11
+#define IRQ_COP      12
+#define IRQ_HOST     13
+
+#define DEFAULT_RSTVEC     0x00001000
+#define DEFAULT_NMIVEC     0x00001004
+#define DEFAULT_MTVEC      0x00001010
+#define CONFIG_STRING_ADDR 0x0000100C
+#define EXT_IO_BASE        0x40000000
+#define DRAM_BASE          0x80000000
+
+/* page table entry (PTE) fields */
+#define PTE_V     0x001U /* Valid */
+#define PTE_R     0x002U /* Read */
+#define PTE_W     0x004U /* Write */
+#define PTE_X     0x008U /* Execute */
+#define PTE_U     0x010U /* User */
+#define PTE_G     0x020U /* Global */
+#define PTE_A     0x040U /* Accessed */
+#define PTE_D     0x080U /* Dirty */
+#define PTE_SOFT  0x300U /* Reserved for Software */
+
+#define PTE_PPN_SHIFT 10
+
+#define PTE_TABLE(PTE) (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V)
+
+#if defined(__riscv)
+
+#if defined(__riscv64)
+# define MSTATUS_SD MSTATUS64_SD
+# define SSTATUS_SD SSTATUS64_SD
+# define RISCV_PGLEVEL_BITS 9
+#else
+# define MSTATUS_SD MSTATUS32_SD
+# define SSTATUS_SD SSTATUS32_SD
+# define RISCV_PGLEVEL_BITS 10
+#endif
+#define RISCV_PGSHIFT 12
+#define RISCV_PGSIZE (1 << RISCV_PGSHIFT)
+
+#ifndef TOPPERS_MACRO_ONLY
+
+#if defined(__GNUC__)
+
+#define read_csr(reg) ({ unsigned long __tmp; \
+  asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \
+  __tmp; })
+
+#define write_csr(reg, val) ({ \
+  if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \
+    asm volatile ("csrw " #reg ", %0" :: "i"(val)); \
+  else \
+    asm volatile ("csrw " #reg ", %0" :: "r"(val)); })
+
+#define swap_csr(reg, val) ({ unsigned long __tmp; \
+  if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \
+    asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "i"(val)); \
+  else \
+    asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "r"(val)); \
+  __tmp; })
+
+#define set_csr(reg, bit) ({ unsigned long __tmp; \
+  if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \
+    asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \
+  else \
+    asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \
+  __tmp; })
+
+#define clear_csr(reg, bit) ({ unsigned long __tmp; \
+  if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \
+    asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \
+  else \
+    asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \
+  __tmp; })
+
+#define read_time()         read_csr(mtime)
+#define read_cycle()        read_csr(mcycle)
+#define current_coreid()       read_csr(mhartid)
+
+#endif	/* __GNUC__ */
+
+#endif	/* TOPPERS_MACRO_ONLY */
+
+#endif
+
+#endif
+/* Automatically generated by parse-opcodes */
+#ifndef RISCV_ENCODING_H
+#define RISCV_ENCODING_H
+#define MATCH_BEQ 0x63
+#define MASK_BEQ  0x707f
+#define MATCH_BNE 0x1063
+#define MASK_BNE  0x707f
+#define MATCH_BLT 0x4063
+#define MASK_BLT  0x707f
+#define MATCH_BGE 0x5063
+#define MASK_BGE  0x707f
+#define MATCH_BLTU 0x6063
+#define MASK_BLTU  0x707f
+#define MATCH_BGEU 0x7063
+#define MASK_BGEU  0x707f
+#define MATCH_JALR 0x67
+#define MASK_JALR  0x707f
+#define MATCH_JAL 0x6f
+#define MASK_JAL  0x7f
+#define MATCH_LUI 0x37
+#define MASK_LUI  0x7f
+#define MATCH_AUIPC 0x17
+#define MASK_AUIPC  0x7f
+#define MATCH_ADDI 0x13
+#define MASK_ADDI  0x707f
+#define MATCH_SLLI 0x1013
+#define MASK_SLLI  0xfc00707f
+#define MATCH_SLTI 0x2013
+#define MASK_SLTI  0x707f
+#define MATCH_SLTIU 0x3013
+#define MASK_SLTIU  0x707f
+#define MATCH_XORI 0x4013
+#define MASK_XORI  0x707f
+#define MATCH_SRLI 0x5013
+#define MASK_SRLI  0xfc00707f
+#define MATCH_SRAI 0x40005013
+#define MASK_SRAI  0xfc00707f
+#define MATCH_ORI 0x6013
+#define MASK_ORI  0x707f
+#define MATCH_ANDI 0x7013
+#define MASK_ANDI  0x707f
+#define MATCH_ADD 0x33
+#define MASK_ADD  0xfe00707f
+#define MATCH_SUB 0x40000033
+#define MASK_SUB  0xfe00707f
+#define MATCH_SLL 0x1033
+#define MASK_SLL  0xfe00707f
+#define MATCH_SLT 0x2033
+#define MASK_SLT  0xfe00707f
+#define MATCH_SLTU 0x3033
+#define MASK_SLTU  0xfe00707f
+#define MATCH_XOR 0x4033
+#define MASK_XOR  0xfe00707f
+#define MATCH_SRL 0x5033
+#define MASK_SRL  0xfe00707f
+#define MATCH_SRA 0x40005033
+#define MASK_SRA  0xfe00707f
+#define MATCH_OR 0x6033
+#define MASK_OR  0xfe00707f
+#define MATCH_AND 0x7033
+#define MASK_AND  0xfe00707f
+#define MATCH_ADDIW 0x1b
+#define MASK_ADDIW  0x707f
+#define MATCH_SLLIW 0x101b
+#define MASK_SLLIW  0xfe00707f
+#define MATCH_SRLIW 0x501b
+#define MASK_SRLIW  0xfe00707f
+#define MATCH_SRAIW 0x4000501b
+#define MASK_SRAIW  0xfe00707f
+#define MATCH_ADDW 0x3b
+#define MASK_ADDW  0xfe00707f
+#define MATCH_SUBW 0x4000003b
+#define MASK_SUBW  0xfe00707f
+#define MATCH_SLLW 0x103b
+#define MASK_SLLW  0xfe00707f
+#define MATCH_SRLW 0x503b
+#define MASK_SRLW  0xfe00707f
+#define MATCH_SRAW 0x4000503b
+#define MASK_SRAW  0xfe00707f
+#define MATCH_LB 0x3
+#define MASK_LB  0x707f
+#define MATCH_LH 0x1003
+#define MASK_LH  0x707f
+#define MATCH_LW 0x2003
+#define MASK_LW  0x707f
+#define MATCH_LD 0x3003
+#define MASK_LD  0x707f
+#define MATCH_LBU 0x4003
+#define MASK_LBU  0x707f
+#define MATCH_LHU 0x5003
+#define MASK_LHU  0x707f
+#define MATCH_LWU 0x6003
+#define MASK_LWU  0x707f
+#define MATCH_SB 0x23
+#define MASK_SB  0x707f
+#define MATCH_SH 0x1023
+#define MASK_SH  0x707f
+#define MATCH_SW 0x2023
+#define MASK_SW  0x707f
+#define MATCH_SD 0x3023
+#define MASK_SD  0x707f
+#define MATCH_FENCE 0xf
+#define MASK_FENCE  0x707f
+#define MATCH_FENCE_I 0x100f
+#define MASK_FENCE_I  0x707f
+#define MATCH_MUL 0x2000033
+#define MASK_MUL  0xfe00707f
+#define MATCH_MULH 0x2001033
+#define MASK_MULH  0xfe00707f
+#define MATCH_MULHSU 0x2002033
+#define MASK_MULHSU  0xfe00707f
+#define MATCH_MULHU 0x2003033
+#define MASK_MULHU  0xfe00707f
+#define MATCH_DIV 0x2004033
+#define MASK_DIV  0xfe00707f
+#define MATCH_DIVU 0x2005033
+#define MASK_DIVU  0xfe00707f
+#define MATCH_REM 0x2006033
+#define MASK_REM  0xfe00707f
+#define MATCH_REMU 0x2007033
+#define MASK_REMU  0xfe00707f
+#define MATCH_MULW 0x200003b
+#define MASK_MULW  0xfe00707f
+#define MATCH_DIVW 0x200403b
+#define MASK_DIVW  0xfe00707f
+#define MATCH_DIVUW 0x200503b
+#define MASK_DIVUW  0xfe00707f
+#define MATCH_REMW 0x200603b
+#define MASK_REMW  0xfe00707f
+#define MATCH_REMUW 0x200703b
+#define MASK_REMUW  0xfe00707f
+#define MATCH_AMOADD_W 0x202f
+#define MASK_AMOADD_W  0xf800707f
+#define MATCH_AMOXOR_W 0x2000202f
+#define MASK_AMOXOR_W  0xf800707f
+#define MATCH_AMOOR_W 0x4000202f
+#define MASK_AMOOR_W  0xf800707f
+#define MATCH_AMOAND_W 0x6000202f
+#define MASK_AMOAND_W  0xf800707f
+#define MATCH_AMOMIN_W 0x8000202f
+#define MASK_AMOMIN_W  0xf800707f
+#define MATCH_AMOMAX_W 0xa000202f
+#define MASK_AMOMAX_W  0xf800707f
+#define MATCH_AMOMINU_W 0xc000202f
+#define MASK_AMOMINU_W  0xf800707f
+#define MATCH_AMOMAXU_W 0xe000202f
+#define MASK_AMOMAXU_W  0xf800707f
+#define MATCH_AMOSWAP_W 0x800202f
+#define MASK_AMOSWAP_W  0xf800707f
+#define MATCH_LR_W 0x1000202f
+#define MASK_LR_W  0xf9f0707f
+#define MATCH_SC_W 0x1800202f
+#define MASK_SC_W  0xf800707f
+#define MATCH_AMOADD_D 0x302f
+#define MASK_AMOADD_D  0xf800707f
+#define MATCH_AMOXOR_D 0x2000302f
+#define MASK_AMOXOR_D  0xf800707f
+#define MATCH_AMOOR_D 0x4000302f
+#define MASK_AMOOR_D  0xf800707f
+#define MATCH_AMOAND_D 0x6000302f
+#define MASK_AMOAND_D  0xf800707f
+#define MATCH_AMOMIN_D 0x8000302f
+#define MASK_AMOMIN_D  0xf800707f
+#define MATCH_AMOMAX_D 0xa000302f
+#define MASK_AMOMAX_D  0xf800707f
+#define MATCH_AMOMINU_D 0xc000302f
+#define MASK_AMOMINU_D  0xf800707f
+#define MATCH_AMOMAXU_D 0xe000302f
+#define MASK_AMOMAXU_D  0xf800707f
+#define MATCH_AMOSWAP_D 0x800302f
+#define MASK_AMOSWAP_D  0xf800707f
+#define MATCH_LR_D 0x1000302f
+#define MASK_LR_D  0xf9f0707f
+#define MATCH_SC_D 0x1800302f
+#define MASK_SC_D  0xf800707f
+#define MATCH_ECALL 0x73
+#define MASK_ECALL  0xffffffff
+#define MATCH_EBREAK 0x100073
+#define MASK_EBREAK  0xffffffff
+#define MATCH_URET 0x200073
+#define MASK_URET  0xffffffff
+#define MATCH_SRET 0x10200073
+#define MASK_SRET  0xffffffff
+#define MATCH_HRET 0x20200073
+#define MASK_HRET  0xffffffff
+#define MATCH_MRET 0x30200073
+#define MASK_MRET  0xffffffff
+#define MATCH_DRET 0x7b200073
+#define MASK_DRET  0xffffffff
+#define MATCH_SFENCE_VM 0x10400073
+#define MASK_SFENCE_VM  0xfff07fff
+#define MATCH_WFI 0x10500073
+#define MASK_WFI  0xffffffff
+#define MATCH_CSRRW 0x1073
+#define MASK_CSRRW  0x707f
+#define MATCH_CSRRS 0x2073
+#define MASK_CSRRS  0x707f
+#define MATCH_CSRRC 0x3073
+#define MASK_CSRRC  0x707f
+#define MATCH_CSRRWI 0x5073
+#define MASK_CSRRWI  0x707f
+#define MATCH_CSRRSI 0x6073
+#define MASK_CSRRSI  0x707f
+#define MATCH_CSRRCI 0x7073
+#define MASK_CSRRCI  0x707f
+#define MATCH_FADD_S 0x53
+#define MASK_FADD_S  0xfe00007f
+#define MATCH_FSUB_S 0x8000053
+#define MASK_FSUB_S  0xfe00007f
+#define MATCH_FMUL_S 0x10000053
+#define MASK_FMUL_S  0xfe00007f
+#define MATCH_FDIV_S 0x18000053
+#define MASK_FDIV_S  0xfe00007f
+#define MATCH_FSGNJ_S 0x20000053
+#define MASK_FSGNJ_S  0xfe00707f
+#define MATCH_FSGNJN_S 0x20001053
+#define MASK_FSGNJN_S  0xfe00707f
+#define MATCH_FSGNJX_S 0x20002053
+#define MASK_FSGNJX_S  0xfe00707f
+#define MATCH_FMIN_S 0x28000053
+#define MASK_FMIN_S  0xfe00707f
+#define MATCH_FMAX_S 0x28001053
+#define MASK_FMAX_S  0xfe00707f
+#define MATCH_FSQRT_S 0x58000053
+#define MASK_FSQRT_S  0xfff0007f
+#define MATCH_FADD_D 0x2000053
+#define MASK_FADD_D  0xfe00007f
+#define MATCH_FSUB_D 0xa000053
+#define MASK_FSUB_D  0xfe00007f
+#define MATCH_FMUL_D 0x12000053
+#define MASK_FMUL_D  0xfe00007f
+#define MATCH_FDIV_D 0x1a000053
+#define MASK_FDIV_D  0xfe00007f
+#define MATCH_FSGNJ_D 0x22000053
+#define MASK_FSGNJ_D  0xfe00707f
+#define MATCH_FSGNJN_D 0x22001053
+#define MASK_FSGNJN_D  0xfe00707f
+#define MATCH_FSGNJX_D 0x22002053
+#define MASK_FSGNJX_D  0xfe00707f
+#define MATCH_FMIN_D 0x2a000053
+#define MASK_FMIN_D  0xfe00707f
+#define MATCH_FMAX_D 0x2a001053
+#define MASK_FMAX_D  0xfe00707f
+#define MATCH_FCVT_S_D 0x40100053
+#define MASK_FCVT_S_D  0xfff0007f
+#define MATCH_FCVT_D_S 0x42000053
+#define MASK_FCVT_D_S  0xfff0007f
+#define MATCH_FSQRT_D 0x5a000053
+#define MASK_FSQRT_D  0xfff0007f
+#define MATCH_FLE_S 0xa0000053
+#define MASK_FLE_S  0xfe00707f
+#define MATCH_FLT_S 0xa0001053
+#define MASK_FLT_S  0xfe00707f
+#define MATCH_FEQ_S 0xa0002053
+#define MASK_FEQ_S  0xfe00707f
+#define MATCH_FLE_D 0xa2000053
+#define MASK_FLE_D  0xfe00707f
+#define MATCH_FLT_D 0xa2001053
+#define MASK_FLT_D  0xfe00707f
+#define MATCH_FEQ_D 0xa2002053
+#define MASK_FEQ_D  0xfe00707f
+#define MATCH_FCVT_W_S 0xc0000053
+#define MASK_FCVT_W_S  0xfff0007f
+#define MATCH_FCVT_WU_S 0xc0100053
+#define MASK_FCVT_WU_S  0xfff0007f
+#define MATCH_FCVT_L_S 0xc0200053
+#define MASK_FCVT_L_S  0xfff0007f
+#define MATCH_FCVT_LU_S 0xc0300053
+#define MASK_FCVT_LU_S  0xfff0007f
+#define MATCH_FMV_X_S 0xe0000053
+#define MASK_FMV_X_S  0xfff0707f
+#define MATCH_FCLASS_S 0xe0001053
+#define MASK_FCLASS_S  0xfff0707f
+#define MATCH_FCVT_W_D 0xc2000053
+#define MASK_FCVT_W_D  0xfff0007f
+#define MATCH_FCVT_WU_D 0xc2100053
+#define MASK_FCVT_WU_D  0xfff0007f
+#define MATCH_FCVT_L_D 0xc2200053
+#define MASK_FCVT_L_D  0xfff0007f
+#define MATCH_FCVT_LU_D 0xc2300053
+#define MASK_FCVT_LU_D  0xfff0007f
+#define MATCH_FMV_X_D 0xe2000053
+#define MASK_FMV_X_D  0xfff0707f
+#define MATCH_FCLASS_D 0xe2001053
+#define MASK_FCLASS_D  0xfff0707f
+#define MATCH_FCVT_S_W 0xd0000053
+#define MASK_FCVT_S_W  0xfff0007f
+#define MATCH_FCVT_S_WU 0xd0100053
+#define MASK_FCVT_S_WU  0xfff0007f
+#define MATCH_FCVT_S_L 0xd0200053
+#define MASK_FCVT_S_L  0xfff0007f
+#define MATCH_FCVT_S_LU 0xd0300053
+#define MASK_FCVT_S_LU  0xfff0007f
+#define MATCH_FMV_S_X 0xf0000053
+#define MASK_FMV_S_X  0xfff0707f
+#define MATCH_FCVT_D_W 0xd2000053
+#define MASK_FCVT_D_W  0xfff0007f
+#define MATCH_FCVT_D_WU 0xd2100053
+#define MASK_FCVT_D_WU  0xfff0007f
+#define MATCH_FCVT_D_L 0xd2200053
+#define MASK_FCVT_D_L  0xfff0007f
+#define MATCH_FCVT_D_LU 0xd2300053
+#define MASK_FCVT_D_LU  0xfff0007f
+#define MATCH_FMV_D_X 0xf2000053
+#define MASK_FMV_D_X  0xfff0707f
+#define MATCH_FLW 0x2007
+#define MASK_FLW  0x707f
+#define MATCH_FLD 0x3007
+#define MASK_FLD  0x707f
+#define MATCH_FSW 0x2027
+#define MASK_FSW  0x707f
+#define MATCH_FSD 0x3027
+#define MASK_FSD  0x707f
+#define MATCH_FMADD_S 0x43
+#define MASK_FMADD_S  0x600007f
+#define MATCH_FMSUB_S 0x47
+#define MASK_FMSUB_S  0x600007f
+#define MATCH_FNMSUB_S 0x4b
+#define MASK_FNMSUB_S  0x600007f
+#define MATCH_FNMADD_S 0x4f
+#define MASK_FNMADD_S  0x600007f
+#define MATCH_FMADD_D 0x2000043
+#define MASK_FMADD_D  0x600007f
+#define MATCH_FMSUB_D 0x2000047
+#define MASK_FMSUB_D  0x600007f
+#define MATCH_FNMSUB_D 0x200004b
+#define MASK_FNMSUB_D  0x600007f
+#define MATCH_FNMADD_D 0x200004f
+#define MASK_FNMADD_D  0x600007f
+#define MATCH_C_NOP 0x1
+#define MASK_C_NOP  0xffff
+#define MATCH_C_ADDI16SP 0x6101
+#define MASK_C_ADDI16SP  0xef83
+#define MATCH_C_JR 0x8002
+#define MASK_C_JR  0xf07f
+#define MATCH_C_JALR 0x9002
+#define MASK_C_JALR  0xf07f
+#define MATCH_C_EBREAK 0x9002
+#define MASK_C_EBREAK  0xffff
+#define MATCH_C_LD 0x6000
+#define MASK_C_LD  0xe003
+#define MATCH_C_SD 0xe000
+#define MASK_C_SD  0xe003
+#define MATCH_C_ADDIW 0x2001
+#define MASK_C_ADDIW  0xe003
+#define MATCH_C_LDSP 0x6002
+#define MASK_C_LDSP  0xe003
+#define MATCH_C_SDSP 0xe002
+#define MASK_C_SDSP  0xe003
+#define MATCH_C_ADDI4SPN 0x0
+#define MASK_C_ADDI4SPN  0xe003
+#define MATCH_C_FLD 0x2000
+#define MASK_C_FLD  0xe003
+#define MATCH_C_LW 0x4000
+#define MASK_C_LW  0xe003
+#define MATCH_C_FLW 0x6000
+#define MASK_C_FLW  0xe003
+#define MATCH_C_FSD 0xa000
+#define MASK_C_FSD  0xe003
+#define MATCH_C_SW 0xc000
+#define MASK_C_SW  0xe003
+#define MATCH_C_FSW 0xe000
+#define MASK_C_FSW  0xe003
+#define MATCH_C_ADDI 0x1
+#define MASK_C_ADDI  0xe003
+#define MATCH_C_JAL 0x2001
+#define MASK_C_JAL  0xe003
+#define MATCH_C_LI 0x4001
+#define MASK_C_LI  0xe003
+#define MATCH_C_LUI 0x6001
+#define MASK_C_LUI  0xe003
+#define MATCH_C_SRLI 0x8001
+#define MASK_C_SRLI  0xec03
+#define MATCH_C_SRAI 0x8401
+#define MASK_C_SRAI  0xec03
+#define MATCH_C_ANDI 0x8801
+#define MASK_C_ANDI  0xec03
+#define MATCH_C_SUB 0x8c01
+#define MASK_C_SUB  0xfc63
+#define MATCH_C_XOR 0x8c21
+#define MASK_C_XOR  0xfc63
+#define MATCH_C_OR 0x8c41
+#define MASK_C_OR  0xfc63
+#define MATCH_C_AND 0x8c61
+#define MASK_C_AND  0xfc63
+#define MATCH_C_SUBW 0x9c01
+#define MASK_C_SUBW  0xfc63
+#define MATCH_C_ADDW 0x9c21
+#define MASK_C_ADDW  0xfc63
+#define MATCH_C_J 0xa001
+#define MASK_C_J  0xe003
+#define MATCH_C_BEQZ 0xc001
+#define MASK_C_BEQZ  0xe003
+#define MATCH_C_BNEZ 0xe001
+#define MASK_C_BNEZ  0xe003
+#define MATCH_C_SLLI 0x2
+#define MASK_C_SLLI  0xe003
+#define MATCH_C_FLDSP 0x2002
+#define MASK_C_FLDSP  0xe003
+#define MATCH_C_LWSP 0x4002
+#define MASK_C_LWSP  0xe003
+#define MATCH_C_FLWSP 0x6002
+#define MASK_C_FLWSP  0xe003
+#define MATCH_C_MV 0x8002
+#define MASK_C_MV  0xf003
+#define MATCH_C_ADD 0x9002
+#define MASK_C_ADD  0xf003
+#define MATCH_C_FSDSP 0xa002
+#define MASK_C_FSDSP  0xe003
+#define MATCH_C_SWSP 0xc002
+#define MASK_C_SWSP  0xe003
+#define MATCH_C_FSWSP 0xe002
+#define MASK_C_FSWSP  0xe003
+#define MATCH_CUSTOM0 0xb
+#define MASK_CUSTOM0  0x707f
+#define MATCH_CUSTOM0_RS1 0x200b
+#define MASK_CUSTOM0_RS1  0x707f
+#define MATCH_CUSTOM0_RS1_RS2 0x300b
+#define MASK_CUSTOM0_RS1_RS2  0x707f
+#define MATCH_CUSTOM0_RD 0x400b
+#define MASK_CUSTOM0_RD  0x707f
+#define MATCH_CUSTOM0_RD_RS1 0x600b
+#define MASK_CUSTOM0_RD_RS1  0x707f
+#define MATCH_CUSTOM0_RD_RS1_RS2 0x700b
+#define MASK_CUSTOM0_RD_RS1_RS2  0x707f
+#define MATCH_CUSTOM1 0x2b
+#define MASK_CUSTOM1  0x707f
+#define MATCH_CUSTOM1_RS1 0x202b
+#define MASK_CUSTOM1_RS1  0x707f
+#define MATCH_CUSTOM1_RS1_RS2 0x302b
+#define MASK_CUSTOM1_RS1_RS2  0x707f
+#define MATCH_CUSTOM1_RD 0x402b
+#define MASK_CUSTOM1_RD  0x707f
+#define MATCH_CUSTOM1_RD_RS1 0x602b
+#define MASK_CUSTOM1_RD_RS1  0x707f
+#define MATCH_CUSTOM1_RD_RS1_RS2 0x702b
+#define MASK_CUSTOM1_RD_RS1_RS2  0x707f
+#define MATCH_CUSTOM2 0x5b
+#define MASK_CUSTOM2  0x707f
+#define MATCH_CUSTOM2_RS1 0x205b
+#define MASK_CUSTOM2_RS1  0x707f
+#define MATCH_CUSTOM2_RS1_RS2 0x305b
+#define MASK_CUSTOM2_RS1_RS2  0x707f
+#define MATCH_CUSTOM2_RD 0x405b
+#define MASK_CUSTOM2_RD  0x707f
+#define MATCH_CUSTOM2_RD_RS1 0x605b
+#define MASK_CUSTOM2_RD_RS1  0x707f
+#define MATCH_CUSTOM2_RD_RS1_RS2 0x705b
+#define MASK_CUSTOM2_RD_RS1_RS2  0x707f
+#define MATCH_CUSTOM3 0x7b
+#define MASK_CUSTOM3  0x707f
+#define MATCH_CUSTOM3_RS1 0x207b
+#define MASK_CUSTOM3_RS1  0x707f
+#define MATCH_CUSTOM3_RS1_RS2 0x307b
+#define MASK_CUSTOM3_RS1_RS2  0x707f
+#define MATCH_CUSTOM3_RD 0x407b
+#define MASK_CUSTOM3_RD  0x707f
+#define MATCH_CUSTOM3_RD_RS1 0x607b
+#define MASK_CUSTOM3_RD_RS1  0x707f
+#define MATCH_CUSTOM3_RD_RS1_RS2 0x707b
+#define MASK_CUSTOM3_RD_RS1_RS2  0x707f
+#define CSR_FFLAGS 0x1
+#define CSR_FRM 0x2
+#define CSR_FCSR 0x3
+#define CSR_CYCLE 0xc00
+#define CSR_TIME 0xc01
+#define CSR_INSTRET 0xc02
+#define CSR_HPMCOUNTER3 0xc03
+#define CSR_HPMCOUNTER4 0xc04
+#define CSR_HPMCOUNTER5 0xc05
+#define CSR_HPMCOUNTER6 0xc06
+#define CSR_HPMCOUNTER7 0xc07
+#define CSR_HPMCOUNTER8 0xc08
+#define CSR_HPMCOUNTER9 0xc09
+#define CSR_HPMCOUNTER10 0xc0a
+#define CSR_HPMCOUNTER11 0xc0b
+#define CSR_HPMCOUNTER12 0xc0c
+#define CSR_HPMCOUNTER13 0xc0d
+#define CSR_HPMCOUNTER14 0xc0e
+#define CSR_HPMCOUNTER15 0xc0f
+#define CSR_HPMCOUNTER16 0xc10
+#define CSR_HPMCOUNTER17 0xc11
+#define CSR_HPMCOUNTER18 0xc12
+#define CSR_HPMCOUNTER19 0xc13
+#define CSR_HPMCOUNTER20 0xc14
+#define CSR_HPMCOUNTER21 0xc15
+#define CSR_HPMCOUNTER22 0xc16
+#define CSR_HPMCOUNTER23 0xc17
+#define CSR_HPMCOUNTER24 0xc18
+#define CSR_HPMCOUNTER25 0xc19
+#define CSR_HPMCOUNTER26 0xc1a
+#define CSR_HPMCOUNTER27 0xc1b
+#define CSR_HPMCOUNTER28 0xc1c
+#define CSR_HPMCOUNTER29 0xc1d
+#define CSR_HPMCOUNTER30 0xc1e
+#define CSR_HPMCOUNTER31 0xc1f
+#define CSR_SSTATUS 0x100
+#define CSR_SIE 0x104
+#define CSR_STVEC 0x105
+#define CSR_SSCRATCH 0x140
+#define CSR_SEPC 0x141
+#define CSR_SCAUSE 0x142
+#define CSR_SBADADDR 0x143
+#define CSR_SIP 0x144
+#define CSR_SPTBR 0x180
+#define CSR_MSTATUS 0x300
+#define CSR_MISA 0x301
+#define CSR_MEDELEG 0x302
+#define CSR_MIDELEG 0x303
+#define CSR_MIE 0x304
+#define CSR_MTVEC 0x305
+#define CSR_MSCRATCH 0x340
+#define CSR_MEPC 0x341
+#define CSR_MCAUSE 0x342
+#define CSR_MBADADDR 0x343
+#define CSR_MIP 0x344
+#define CSR_TSELECT 0x7a0
+#define CSR_TDATA1 0x7a1
+#define CSR_TDATA2 0x7a2
+#define CSR_TDATA3 0x7a3
+#define CSR_DCSR 0x7b0
+#define CSR_DPC 0x7b1
+#define CSR_DSCRATCH 0x7b2
+#define CSR_MCYCLE 0xb00
+#define CSR_MINSTRET 0xb02
+#define CSR_MHPMCOUNTER3 0xb03
+#define CSR_MHPMCOUNTER4 0xb04
+#define CSR_MHPMCOUNTER5 0xb05
+#define CSR_MHPMCOUNTER6 0xb06
+#define CSR_MHPMCOUNTER7 0xb07
+#define CSR_MHPMCOUNTER8 0xb08
+#define CSR_MHPMCOUNTER9 0xb09
+#define CSR_MHPMCOUNTER10 0xb0a
+#define CSR_MHPMCOUNTER11 0xb0b
+#define CSR_MHPMCOUNTER12 0xb0c
+#define CSR_MHPMCOUNTER13 0xb0d
+#define CSR_MHPMCOUNTER14 0xb0e
+#define CSR_MHPMCOUNTER15 0xb0f
+#define CSR_MHPMCOUNTER16 0xb10
+#define CSR_MHPMCOUNTER17 0xb11
+#define CSR_MHPMCOUNTER18 0xb12
+#define CSR_MHPMCOUNTER19 0xb13
+#define CSR_MHPMCOUNTER20 0xb14
+#define CSR_MHPMCOUNTER21 0xb15
+#define CSR_MHPMCOUNTER22 0xb16
+#define CSR_MHPMCOUNTER23 0xb17
+#define CSR_MHPMCOUNTER24 0xb18
+#define CSR_MHPMCOUNTER25 0xb19
+#define CSR_MHPMCOUNTER26 0xb1a
+#define CSR_MHPMCOUNTER27 0xb1b
+#define CSR_MHPMCOUNTER28 0xb1c
+#define CSR_MHPMCOUNTER29 0xb1d
+#define CSR_MHPMCOUNTER30 0xb1e
+#define CSR_MHPMCOUNTER31 0xb1f
+#define CSR_MUCOUNTEREN 0x320
+#define CSR_MSCOUNTEREN 0x321
+#define CSR_MHPMEVENT3 0x323
+#define CSR_MHPMEVENT4 0x324
+#define CSR_MHPMEVENT5 0x325
+#define CSR_MHPMEVENT6 0x326
+#define CSR_MHPMEVENT7 0x327
+#define CSR_MHPMEVENT8 0x328
+#define CSR_MHPMEVENT9 0x329
+#define CSR_MHPMEVENT10 0x32a
+#define CSR_MHPMEVENT11 0x32b
+#define CSR_MHPMEVENT12 0x32c
+#define CSR_MHPMEVENT13 0x32d
+#define CSR_MHPMEVENT14 0x32e
+#define CSR_MHPMEVENT15 0x32f
+#define CSR_MHPMEVENT16 0x330
+#define CSR_MHPMEVENT17 0x331
+#define CSR_MHPMEVENT18 0x332
+#define CSR_MHPMEVENT19 0x333
+#define CSR_MHPMEVENT20 0x334
+#define CSR_MHPMEVENT21 0x335
+#define CSR_MHPMEVENT22 0x336
+#define CSR_MHPMEVENT23 0x337
+#define CSR_MHPMEVENT24 0x338
+#define CSR_MHPMEVENT25 0x339
+#define CSR_MHPMEVENT26 0x33a
+#define CSR_MHPMEVENT27 0x33b
+#define CSR_MHPMEVENT28 0x33c
+#define CSR_MHPMEVENT29 0x33d
+#define CSR_MHPMEVENT30 0x33e
+#define CSR_MHPMEVENT31 0x33f
+#define CSR_MVENDORID 0xf11
+#define CSR_MARCHID 0xf12
+#define CSR_MIMPID 0xf13
+#define CSR_MHARTID 0xf14
+#define CSR_CYCLEH 0xc80
+#define CSR_TIMEH 0xc81
+#define CSR_INSTRETH 0xc82
+#define CSR_HPMCOUNTER3H 0xc83
+#define CSR_HPMCOUNTER4H 0xc84
+#define CSR_HPMCOUNTER5H 0xc85
+#define CSR_HPMCOUNTER6H 0xc86
+#define CSR_HPMCOUNTER7H 0xc87
+#define CSR_HPMCOUNTER8H 0xc88
+#define CSR_HPMCOUNTER9H 0xc89
+#define CSR_HPMCOUNTER10H 0xc8a
+#define CSR_HPMCOUNTER11H 0xc8b
+#define CSR_HPMCOUNTER12H 0xc8c
+#define CSR_HPMCOUNTER13H 0xc8d
+#define CSR_HPMCOUNTER14H 0xc8e
+#define CSR_HPMCOUNTER15H 0xc8f
+#define CSR_HPMCOUNTER16H 0xc90
+#define CSR_HPMCOUNTER17H 0xc91
+#define CSR_HPMCOUNTER18H 0xc92
+#define CSR_HPMCOUNTER19H 0xc93
+#define CSR_HPMCOUNTER20H 0xc94
+#define CSR_HPMCOUNTER21H 0xc95
+#define CSR_HPMCOUNTER22H 0xc96
+#define CSR_HPMCOUNTER23H 0xc97
+#define CSR_HPMCOUNTER24H 0xc98
+#define CSR_HPMCOUNTER25H 0xc99
+#define CSR_HPMCOUNTER26H 0xc9a
+#define CSR_HPMCOUNTER27H 0xc9b
+#define CSR_HPMCOUNTER28H 0xc9c
+#define CSR_HPMCOUNTER29H 0xc9d
+#define CSR_HPMCOUNTER30H 0xc9e
+#define CSR_HPMCOUNTER31H 0xc9f
+#define CSR_MCYCLEH 0xb80
+#define CSR_MINSTRETH 0xb82
+#define CSR_MHPMCOUNTER3H 0xb83
+#define CSR_MHPMCOUNTER4H 0xb84
+#define CSR_MHPMCOUNTER5H 0xb85
+#define CSR_MHPMCOUNTER6H 0xb86
+#define CSR_MHPMCOUNTER7H 0xb87
+#define CSR_MHPMCOUNTER8H 0xb88
+#define CSR_MHPMCOUNTER9H 0xb89
+#define CSR_MHPMCOUNTER10H 0xb8a
+#define CSR_MHPMCOUNTER11H 0xb8b
+#define CSR_MHPMCOUNTER12H 0xb8c
+#define CSR_MHPMCOUNTER13H 0xb8d
+#define CSR_MHPMCOUNTER14H 0xb8e
+#define CSR_MHPMCOUNTER15H 0xb8f
+#define CSR_MHPMCOUNTER16H 0xb90
+#define CSR_MHPMCOUNTER17H 0xb91
+#define CSR_MHPMCOUNTER18H 0xb92
+#define CSR_MHPMCOUNTER19H 0xb93
+#define CSR_MHPMCOUNTER20H 0xb94
+#define CSR_MHPMCOUNTER21H 0xb95
+#define CSR_MHPMCOUNTER22H 0xb96
+#define CSR_MHPMCOUNTER23H 0xb97
+#define CSR_MHPMCOUNTER24H 0xb98
+#define CSR_MHPMCOUNTER25H 0xb99
+#define CSR_MHPMCOUNTER26H 0xb9a
+#define CSR_MHPMCOUNTER27H 0xb9b
+#define CSR_MHPMCOUNTER28H 0xb9c
+#define CSR_MHPMCOUNTER29H 0xb9d
+#define CSR_MHPMCOUNTER30H 0xb9e
+#define CSR_MHPMCOUNTER31H 0xb9f
+#define CAUSE_MISALIGNED_FETCH 0x0
+#define CAUSE_FAULT_FETCH 0x1
+#define CAUSE_ILLEGAL_INSTRUCTION 0x2
+#define CAUSE_BREAKPOINT 0x3
+#define CAUSE_MISALIGNED_LOAD 0x4
+#define CAUSE_FAULT_LOAD 0x5
+#define CAUSE_MISALIGNED_STORE 0x6
+#define CAUSE_FAULT_STORE 0x7
+#define CAUSE_USER_ECALL 0x8
+#define CAUSE_SUPERVISOR_ECALL 0x9
+#define CAUSE_HYPERVISOR_ECALL 0xa
+#define CAUSE_MACHINE_ECALL 0xb
+#endif
+#if defined(DECLARE_INSN)
+DECLARE_INSN(beq, MATCH_BEQ, MASK_BEQ)
+DECLARE_INSN(bne, MATCH_BNE, MASK_BNE)
+DECLARE_INSN(blt, MATCH_BLT, MASK_BLT)
+DECLARE_INSN(bge, MATCH_BGE, MASK_BGE)
+DECLARE_INSN(bltu, MATCH_BLTU, MASK_BLTU)
+DECLARE_INSN(bgeu, MATCH_BGEU, MASK_BGEU)
+DECLARE_INSN(jalr, MATCH_JALR, MASK_JALR)
+DECLARE_INSN(jal, MATCH_JAL, MASK_JAL)
+DECLARE_INSN(lui, MATCH_LUI, MASK_LUI)
+DECLARE_INSN(auipc, MATCH_AUIPC, MASK_AUIPC)
+DECLARE_INSN(addi, MATCH_ADDI, MASK_ADDI)
+DECLARE_INSN(slli, MATCH_SLLI, MASK_SLLI)
+DECLARE_INSN(slti, MATCH_SLTI, MASK_SLTI)
+DECLARE_INSN(sltiu, MATCH_SLTIU, MASK_SLTIU)
+DECLARE_INSN(xori, MATCH_XORI, MASK_XORI)
+DECLARE_INSN(srli, MATCH_SRLI, MASK_SRLI)
+DECLARE_INSN(srai, MATCH_SRAI, MASK_SRAI)
+DECLARE_INSN(ori, MATCH_ORI, MASK_ORI)
+DECLARE_INSN(andi, MATCH_ANDI, MASK_ANDI)
+DECLARE_INSN(add, MATCH_ADD, MASK_ADD)
+DECLARE_INSN(sub, MATCH_SUB, MASK_SUB)
+DECLARE_INSN(sll, MATCH_SLL, MASK_SLL)
+DECLARE_INSN(slt, MATCH_SLT, MASK_SLT)
+DECLARE_INSN(sltu, MATCH_SLTU, MASK_SLTU)
+DECLARE_INSN(xor, MATCH_XOR, MASK_XOR)
+DECLARE_INSN(srl, MATCH_SRL, MASK_SRL)
+DECLARE_INSN(sra, MATCH_SRA, MASK_SRA)
+DECLARE_INSN(or, MATCH_OR, MASK_OR)
+DECLARE_INSN(and, MATCH_AND, MASK_AND)
+DECLARE_INSN(addiw, MATCH_ADDIW, MASK_ADDIW)
+DECLARE_INSN(slliw, MATCH_SLLIW, MASK_SLLIW)
+DECLARE_INSN(srliw, MATCH_SRLIW, MASK_SRLIW)
+DECLARE_INSN(sraiw, MATCH_SRAIW, MASK_SRAIW)
+DECLARE_INSN(addw, MATCH_ADDW, MASK_ADDW)
+DECLARE_INSN(subw, MATCH_SUBW, MASK_SUBW)
+DECLARE_INSN(sllw, MATCH_SLLW, MASK_SLLW)
+DECLARE_INSN(srlw, MATCH_SRLW, MASK_SRLW)
+DECLARE_INSN(sraw, MATCH_SRAW, MASK_SRAW)
+DECLARE_INSN(lb, MATCH_LB, MASK_LB)
+DECLARE_INSN(lh, MATCH_LH, MASK_LH)
+DECLARE_INSN(lw, MATCH_LW, MASK_LW)
+DECLARE_INSN(ld, MATCH_LD, MASK_LD)
+DECLARE_INSN(lbu, MATCH_LBU, MASK_LBU)
+DECLARE_INSN(lhu, MATCH_LHU, MASK_LHU)
+DECLARE_INSN(lwu, MATCH_LWU, MASK_LWU)
+DECLARE_INSN(sb, MATCH_SB, MASK_SB)
+DECLARE_INSN(sh, MATCH_SH, MASK_SH)
+DECLARE_INSN(sw, MATCH_SW, MASK_SW)
+DECLARE_INSN(sd, MATCH_SD, MASK_SD)
+DECLARE_INSN(fence, MATCH_FENCE, MASK_FENCE)
+DECLARE_INSN(fence_i, MATCH_FENCE_I, MASK_FENCE_I)
+DECLARE_INSN(mul, MATCH_MUL, MASK_MUL)
+DECLARE_INSN(mulh, MATCH_MULH, MASK_MULH)
+DECLARE_INSN(mulhsu, MATCH_MULHSU, MASK_MULHSU)
+DECLARE_INSN(mulhu, MATCH_MULHU, MASK_MULHU)
+DECLARE_INSN(div, MATCH_DIV, MASK_DIV)
+DECLARE_INSN(divu, MATCH_DIVU, MASK_DIVU)
+DECLARE_INSN(rem, MATCH_REM, MASK_REM)
+DECLARE_INSN(remu, MATCH_REMU, MASK_REMU)
+DECLARE_INSN(mulw, MATCH_MULW, MASK_MULW)
+DECLARE_INSN(divw, MATCH_DIVW, MASK_DIVW)
+DECLARE_INSN(divuw, MATCH_DIVUW, MASK_DIVUW)
+DECLARE_INSN(remw, MATCH_REMW, MASK_REMW)
+DECLARE_INSN(remuw, MATCH_REMUW, MASK_REMUW)
+DECLARE_INSN(amoadd_w, MATCH_AMOADD_W, MASK_AMOADD_W)
+DECLARE_INSN(amoxor_w, MATCH_AMOXOR_W, MASK_AMOXOR_W)
+DECLARE_INSN(amoor_w, MATCH_AMOOR_W, MASK_AMOOR_W)
+DECLARE_INSN(amoand_w, MATCH_AMOAND_W, MASK_AMOAND_W)
+DECLARE_INSN(amomin_w, MATCH_AMOMIN_W, MASK_AMOMIN_W)
+DECLARE_INSN(amomax_w, MATCH_AMOMAX_W, MASK_AMOMAX_W)
+DECLARE_INSN(amominu_w, MATCH_AMOMINU_W, MASK_AMOMINU_W)
+DECLARE_INSN(amomaxu_w, MATCH_AMOMAXU_W, MASK_AMOMAXU_W)
+DECLARE_INSN(amoswap_w, MATCH_AMOSWAP_W, MASK_AMOSWAP_W)
+DECLARE_INSN(lr_w, MATCH_LR_W, MASK_LR_W)
+DECLARE_INSN(sc_w, MATCH_SC_W, MASK_SC_W)
+DECLARE_INSN(amoadd_d, MATCH_AMOADD_D, MASK_AMOADD_D)
+DECLARE_INSN(amoxor_d, MATCH_AMOXOR_D, MASK_AMOXOR_D)
+DECLARE_INSN(amoor_d, MATCH_AMOOR_D, MASK_AMOOR_D)
+DECLARE_INSN(amoand_d, MATCH_AMOAND_D, MASK_AMOAND_D)
+DECLARE_INSN(amomin_d, MATCH_AMOMIN_D, MASK_AMOMIN_D)
+DECLARE_INSN(amomax_d, MATCH_AMOMAX_D, MASK_AMOMAX_D)
+DECLARE_INSN(amominu_d, MATCH_AMOMINU_D, MASK_AMOMINU_D)
+DECLARE_INSN(amomaxu_d, MATCH_AMOMAXU_D, MASK_AMOMAXU_D)
+DECLARE_INSN(amoswap_d, MATCH_AMOSWAP_D, MASK_AMOSWAP_D)
+DECLARE_INSN(lr_d, MATCH_LR_D, MASK_LR_D)
+DECLARE_INSN(sc_d, MATCH_SC_D, MASK_SC_D)
+DECLARE_INSN(ecall, MATCH_ECALL, MASK_ECALL)
+DECLARE_INSN(ebreak, MATCH_EBREAK, MASK_EBREAK)
+DECLARE_INSN(uret, MATCH_URET, MASK_URET)
+DECLARE_INSN(sret, MATCH_SRET, MASK_SRET)
+DECLARE_INSN(hret, MATCH_HRET, MASK_HRET)
+DECLARE_INSN(mret, MATCH_MRET, MASK_MRET)
+DECLARE_INSN(dret, MATCH_DRET, MASK_DRET)
+DECLARE_INSN(sfence_vm, MATCH_SFENCE_VM, MASK_SFENCE_VM)
+DECLARE_INSN(wfi, MATCH_WFI, MASK_WFI)
+DECLARE_INSN(csrrw, MATCH_CSRRW, MASK_CSRRW)
+DECLARE_INSN(csrrs, MATCH_CSRRS, MASK_CSRRS)
+DECLARE_INSN(csrrc, MATCH_CSRRC, MASK_CSRRC)
+DECLARE_INSN(csrrwi, MATCH_CSRRWI, MASK_CSRRWI)
+DECLARE_INSN(csrrsi, MATCH_CSRRSI, MASK_CSRRSI)
+DECLARE_INSN(csrrci, MATCH_CSRRCI, MASK_CSRRCI)
+DECLARE_INSN(fadd_s, MATCH_FADD_S, MASK_FADD_S)
+DECLARE_INSN(fsub_s, MATCH_FSUB_S, MASK_FSUB_S)
+DECLARE_INSN(fmul_s, MATCH_FMUL_S, MASK_FMUL_S)
+DECLARE_INSN(fdiv_s, MATCH_FDIV_S, MASK_FDIV_S)
+DECLARE_INSN(fsgnj_s, MATCH_FSGNJ_S, MASK_FSGNJ_S)
+DECLARE_INSN(fsgnjn_s, MATCH_FSGNJN_S, MASK_FSGNJN_S)
+DECLARE_INSN(fsgnjx_s, MATCH_FSGNJX_S, MASK_FSGNJX_S)
+DECLARE_INSN(fmin_s, MATCH_FMIN_S, MASK_FMIN_S)
+DECLARE_INSN(fmax_s, MATCH_FMAX_S, MASK_FMAX_S)
+DECLARE_INSN(fsqrt_s, MATCH_FSQRT_S, MASK_FSQRT_S)
+DECLARE_INSN(fadd_d, MATCH_FADD_D, MASK_FADD_D)
+DECLARE_INSN(fsub_d, MATCH_FSUB_D, MASK_FSUB_D)
+DECLARE_INSN(fmul_d, MATCH_FMUL_D, MASK_FMUL_D)
+DECLARE_INSN(fdiv_d, MATCH_FDIV_D, MASK_FDIV_D)
+DECLARE_INSN(fsgnj_d, MATCH_FSGNJ_D, MASK_FSGNJ_D)
+DECLARE_INSN(fsgnjn_d, MATCH_FSGNJN_D, MASK_FSGNJN_D)
+DECLARE_INSN(fsgnjx_d, MATCH_FSGNJX_D, MASK_FSGNJX_D)
+DECLARE_INSN(fmin_d, MATCH_FMIN_D, MASK_FMIN_D)
+DECLARE_INSN(fmax_d, MATCH_FMAX_D, MASK_FMAX_D)
+DECLARE_INSN(fcvt_s_d, MATCH_FCVT_S_D, MASK_FCVT_S_D)
+DECLARE_INSN(fcvt_d_s, MATCH_FCVT_D_S, MASK_FCVT_D_S)
+DECLARE_INSN(fsqrt_d, MATCH_FSQRT_D, MASK_FSQRT_D)
+DECLARE_INSN(fle_s, MATCH_FLE_S, MASK_FLE_S)
+DECLARE_INSN(flt_s, MATCH_FLT_S, MASK_FLT_S)
+DECLARE_INSN(feq_s, MATCH_FEQ_S, MASK_FEQ_S)
+DECLARE_INSN(fle_d, MATCH_FLE_D, MASK_FLE_D)
+DECLARE_INSN(flt_d, MATCH_FLT_D, MASK_FLT_D)
+DECLARE_INSN(feq_d, MATCH_FEQ_D, MASK_FEQ_D)
+DECLARE_INSN(fcvt_w_s, MATCH_FCVT_W_S, MASK_FCVT_W_S)
+DECLARE_INSN(fcvt_wu_s, MATCH_FCVT_WU_S, MASK_FCVT_WU_S)
+DECLARE_INSN(fcvt_l_s, MATCH_FCVT_L_S, MASK_FCVT_L_S)
+DECLARE_INSN(fcvt_lu_s, MATCH_FCVT_LU_S, MASK_FCVT_LU_S)
+DECLARE_INSN(fmv_x_s, MATCH_FMV_X_S, MASK_FMV_X_S)
+DECLARE_INSN(fclass_s, MATCH_FCLASS_S, MASK_FCLASS_S)
+DECLARE_INSN(fcvt_w_d, MATCH_FCVT_W_D, MASK_FCVT_W_D)
+DECLARE_INSN(fcvt_wu_d, MATCH_FCVT_WU_D, MASK_FCVT_WU_D)
+DECLARE_INSN(fcvt_l_d, MATCH_FCVT_L_D, MASK_FCVT_L_D)
+DECLARE_INSN(fcvt_lu_d, MATCH_FCVT_LU_D, MASK_FCVT_LU_D)
+DECLARE_INSN(fmv_x_d, MATCH_FMV_X_D, MASK_FMV_X_D)
+DECLARE_INSN(fclass_d, MATCH_FCLASS_D, MASK_FCLASS_D)
+DECLARE_INSN(fcvt_s_w, MATCH_FCVT_S_W, MASK_FCVT_S_W)
+DECLARE_INSN(fcvt_s_wu, MATCH_FCVT_S_WU, MASK_FCVT_S_WU)
+DECLARE_INSN(fcvt_s_l, MATCH_FCVT_S_L, MASK_FCVT_S_L)
+DECLARE_INSN(fcvt_s_lu, MATCH_FCVT_S_LU, MASK_FCVT_S_LU)
+DECLARE_INSN(fmv_s_x, MATCH_FMV_S_X, MASK_FMV_S_X)
+DECLARE_INSN(fcvt_d_w, MATCH_FCVT_D_W, MASK_FCVT_D_W)
+DECLARE_INSN(fcvt_d_wu, MATCH_FCVT_D_WU, MASK_FCVT_D_WU)
+DECLARE_INSN(fcvt_d_l, MATCH_FCVT_D_L, MASK_FCVT_D_L)
+DECLARE_INSN(fcvt_d_lu, MATCH_FCVT_D_LU, MASK_FCVT_D_LU)
+DECLARE_INSN(fmv_d_x, MATCH_FMV_D_X, MASK_FMV_D_X)
+DECLARE_INSN(flw, MATCH_FLW, MASK_FLW)
+DECLARE_INSN(fld, MATCH_FLD, MASK_FLD)
+DECLARE_INSN(fsw, MATCH_FSW, MASK_FSW)
+DECLARE_INSN(fsd, MATCH_FSD, MASK_FSD)
+DECLARE_INSN(fmadd_s, MATCH_FMADD_S, MASK_FMADD_S)
+DECLARE_INSN(fmsub_s, MATCH_FMSUB_S, MASK_FMSUB_S)
+DECLARE_INSN(fnmsub_s, MATCH_FNMSUB_S, MASK_FNMSUB_S)
+DECLARE_INSN(fnmadd_s, MATCH_FNMADD_S, MASK_FNMADD_S)
+DECLARE_INSN(fmadd_d, MATCH_FMADD_D, MASK_FMADD_D)
+DECLARE_INSN(fmsub_d, MATCH_FMSUB_D, MASK_FMSUB_D)
+DECLARE_INSN(fnmsub_d, MATCH_FNMSUB_D, MASK_FNMSUB_D)
+DECLARE_INSN(fnmadd_d, MATCH_FNMADD_D, MASK_FNMADD_D)
+DECLARE_INSN(c_nop, MATCH_C_NOP, MASK_C_NOP)
+DECLARE_INSN(c_addi16sp, MATCH_C_ADDI16SP, MASK_C_ADDI16SP)
+DECLARE_INSN(c_jr, MATCH_C_JR, MASK_C_JR)
+DECLARE_INSN(c_jalr, MATCH_C_JALR, MASK_C_JALR)
+DECLARE_INSN(c_ebreak, MATCH_C_EBREAK, MASK_C_EBREAK)
+DECLARE_INSN(c_ld, MATCH_C_LD, MASK_C_LD)
+DECLARE_INSN(c_sd, MATCH_C_SD, MASK_C_SD)
+DECLARE_INSN(c_addiw, MATCH_C_ADDIW, MASK_C_ADDIW)
+DECLARE_INSN(c_ldsp, MATCH_C_LDSP, MASK_C_LDSP)
+DECLARE_INSN(c_sdsp, MATCH_C_SDSP, MASK_C_SDSP)
+DECLARE_INSN(c_addi4spn, MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN)
+DECLARE_INSN(c_fld, MATCH_C_FLD, MASK_C_FLD)
+DECLARE_INSN(c_lw, MATCH_C_LW, MASK_C_LW)
+DECLARE_INSN(c_flw, MATCH_C_FLW, MASK_C_FLW)
+DECLARE_INSN(c_fsd, MATCH_C_FSD, MASK_C_FSD)
+DECLARE_INSN(c_sw, MATCH_C_SW, MASK_C_SW)
+DECLARE_INSN(c_fsw, MATCH_C_FSW, MASK_C_FSW)
+DECLARE_INSN(c_addi, MATCH_C_ADDI, MASK_C_ADDI)
+DECLARE_INSN(c_jal, MATCH_C_JAL, MASK_C_JAL)
+DECLARE_INSN(c_li, MATCH_C_LI, MASK_C_LI)
+DECLARE_INSN(c_lui, MATCH_C_LUI, MASK_C_LUI)
+DECLARE_INSN(c_srli, MATCH_C_SRLI, MASK_C_SRLI)
+DECLARE_INSN(c_srai, MATCH_C_SRAI, MASK_C_SRAI)
+DECLARE_INSN(c_andi, MATCH_C_ANDI, MASK_C_ANDI)
+DECLARE_INSN(c_sub, MATCH_C_SUB, MASK_C_SUB)
+DECLARE_INSN(c_xor, MATCH_C_XOR, MASK_C_XOR)
+DECLARE_INSN(c_or, MATCH_C_OR, MASK_C_OR)
+DECLARE_INSN(c_and, MATCH_C_AND, MASK_C_AND)
+DECLARE_INSN(c_subw, MATCH_C_SUBW, MASK_C_SUBW)
+DECLARE_INSN(c_addw, MATCH_C_ADDW, MASK_C_ADDW)
+DECLARE_INSN(c_j, MATCH_C_J, MASK_C_J)
+DECLARE_INSN(c_beqz, MATCH_C_BEQZ, MASK_C_BEQZ)
+DECLARE_INSN(c_bnez, MATCH_C_BNEZ, MASK_C_BNEZ)
+DECLARE_INSN(c_slli, MATCH_C_SLLI, MASK_C_SLLI)
+DECLARE_INSN(c_fldsp, MATCH_C_FLDSP, MASK_C_FLDSP)
+DECLARE_INSN(c_lwsp, MATCH_C_LWSP, MASK_C_LWSP)
+DECLARE_INSN(c_flwsp, MATCH_C_FLWSP, MASK_C_FLWSP)
+DECLARE_INSN(c_mv, MATCH_C_MV, MASK_C_MV)
+DECLARE_INSN(c_add, MATCH_C_ADD, MASK_C_ADD)
+DECLARE_INSN(c_fsdsp, MATCH_C_FSDSP, MASK_C_FSDSP)
+DECLARE_INSN(c_swsp, MATCH_C_SWSP, MASK_C_SWSP)
+DECLARE_INSN(c_fswsp, MATCH_C_FSWSP, MASK_C_FSWSP)
+DECLARE_INSN(custom0, MATCH_CUSTOM0, MASK_CUSTOM0)
+DECLARE_INSN(custom0_rs1, MATCH_CUSTOM0_RS1, MASK_CUSTOM0_RS1)
+DECLARE_INSN(custom0_rs1_rs2, MATCH_CUSTOM0_RS1_RS2, MASK_CUSTOM0_RS1_RS2)
+DECLARE_INSN(custom0_rd, MATCH_CUSTOM0_RD, MASK_CUSTOM0_RD)
+DECLARE_INSN(custom0_rd_rs1, MATCH_CUSTOM0_RD_RS1, MASK_CUSTOM0_RD_RS1)
+DECLARE_INSN(custom0_rd_rs1_rs2, MATCH_CUSTOM0_RD_RS1_RS2, MASK_CUSTOM0_RD_RS1_RS2)
+DECLARE_INSN(custom1, MATCH_CUSTOM1, MASK_CUSTOM1)
+DECLARE_INSN(custom1_rs1, MATCH_CUSTOM1_RS1, MASK_CUSTOM1_RS1)
+DECLARE_INSN(custom1_rs1_rs2, MATCH_CUSTOM1_RS1_RS2, MASK_CUSTOM1_RS1_RS2)
+DECLARE_INSN(custom1_rd, MATCH_CUSTOM1_RD, MASK_CUSTOM1_RD)
+DECLARE_INSN(custom1_rd_rs1, MATCH_CUSTOM1_RD_RS1, MASK_CUSTOM1_RD_RS1)
+DECLARE_INSN(custom1_rd_rs1_rs2, MATCH_CUSTOM1_RD_RS1_RS2, MASK_CUSTOM1_RD_RS1_RS2)
+DECLARE_INSN(custom2, MATCH_CUSTOM2, MASK_CUSTOM2)
+DECLARE_INSN(custom2_rs1, MATCH_CUSTOM2_RS1, MASK_CUSTOM2_RS1)
+DECLARE_INSN(custom2_rs1_rs2, MATCH_CUSTOM2_RS1_RS2, MASK_CUSTOM2_RS1_RS2)
+DECLARE_INSN(custom2_rd, MATCH_CUSTOM2_RD, MASK_CUSTOM2_RD)
+DECLARE_INSN(custom2_rd_rs1, MATCH_CUSTOM2_RD_RS1, MASK_CUSTOM2_RD_RS1)
+DECLARE_INSN(custom2_rd_rs1_rs2, MATCH_CUSTOM2_RD_RS1_RS2, MASK_CUSTOM2_RD_RS1_RS2)
+DECLARE_INSN(custom3, MATCH_CUSTOM3, MASK_CUSTOM3)
+DECLARE_INSN(custom3_rs1, MATCH_CUSTOM3_RS1, MASK_CUSTOM3_RS1)
+DECLARE_INSN(custom3_rs1_rs2, MATCH_CUSTOM3_RS1_RS2, MASK_CUSTOM3_RS1_RS2)
+DECLARE_INSN(custom3_rd, MATCH_CUSTOM3_RD, MASK_CUSTOM3_RD)
+DECLARE_INSN(custom3_rd_rs1, MATCH_CUSTOM3_RD_RS1, MASK_CUSTOM3_RD_RS1)
+DECLARE_INSN(custom3_rd_rs1_rs2, MATCH_CUSTOM3_RD_RS1_RS2, MASK_CUSTOM3_RD_RS1_RS2)
+#endif
+#if defined(DECLARE_CSR)
+DECLARE_CSR(fflags, CSR_FFLAGS)
+DECLARE_CSR(frm, CSR_FRM)
+DECLARE_CSR(fcsr, CSR_FCSR)
+DECLARE_CSR(cycle, CSR_CYCLE)
+DECLARE_CSR(time, CSR_TIME)
+DECLARE_CSR(instret, CSR_INSTRET)
+DECLARE_CSR(hpmcounter3, CSR_HPMCOUNTER3)
+DECLARE_CSR(hpmcounter4, CSR_HPMCOUNTER4)
+DECLARE_CSR(hpmcounter5, CSR_HPMCOUNTER5)
+DECLARE_CSR(hpmcounter6, CSR_HPMCOUNTER6)
+DECLARE_CSR(hpmcounter7, CSR_HPMCOUNTER7)
+DECLARE_CSR(hpmcounter8, CSR_HPMCOUNTER8)
+DECLARE_CSR(hpmcounter9, CSR_HPMCOUNTER9)
+DECLARE_CSR(hpmcounter10, CSR_HPMCOUNTER10)
+DECLARE_CSR(hpmcounter11, CSR_HPMCOUNTER11)
+DECLARE_CSR(hpmcounter12, CSR_HPMCOUNTER12)
+DECLARE_CSR(hpmcounter13, CSR_HPMCOUNTER13)
+DECLARE_CSR(hpmcounter14, CSR_HPMCOUNTER14)
+DECLARE_CSR(hpmcounter15, CSR_HPMCOUNTER15)
+DECLARE_CSR(hpmcounter16, CSR_HPMCOUNTER16)
+DECLARE_CSR(hpmcounter17, CSR_HPMCOUNTER17)
+DECLARE_CSR(hpmcounter18, CSR_HPMCOUNTER18)
+DECLARE_CSR(hpmcounter19, CSR_HPMCOUNTER19)
+DECLARE_CSR(hpmcounter20, CSR_HPMCOUNTER20)
+DECLARE_CSR(hpmcounter21, CSR_HPMCOUNTER21)
+DECLARE_CSR(hpmcounter22, CSR_HPMCOUNTER22)
+DECLARE_CSR(hpmcounter23, CSR_HPMCOUNTER23)
+DECLARE_CSR(hpmcounter24, CSR_HPMCOUNTER24)
+DECLARE_CSR(hpmcounter25, CSR_HPMCOUNTER25)
+DECLARE_CSR(hpmcounter26, CSR_HPMCOUNTER26)
+DECLARE_CSR(hpmcounter27, CSR_HPMCOUNTER27)
+DECLARE_CSR(hpmcounter28, CSR_HPMCOUNTER28)
+DECLARE_CSR(hpmcounter29, CSR_HPMCOUNTER29)
+DECLARE_CSR(hpmcounter30, CSR_HPMCOUNTER30)
+DECLARE_CSR(hpmcounter31, CSR_HPMCOUNTER31)
+DECLARE_CSR(sstatus, CSR_SSTATUS)
+DECLARE_CSR(sie, CSR_SIE)
+DECLARE_CSR(stvec, CSR_STVEC)
+DECLARE_CSR(sscratch, CSR_SSCRATCH)
+DECLARE_CSR(sepc, CSR_SEPC)
+DECLARE_CSR(scause, CSR_SCAUSE)
+DECLARE_CSR(sbadaddr, CSR_SBADADDR)
+DECLARE_CSR(sip, CSR_SIP)
+DECLARE_CSR(sptbr, CSR_SPTBR)
+DECLARE_CSR(mstatus, CSR_MSTATUS)
+DECLARE_CSR(misa, CSR_MISA)
+DECLARE_CSR(medeleg, CSR_MEDELEG)
+DECLARE_CSR(mideleg, CSR_MIDELEG)
+DECLARE_CSR(mie, CSR_MIE)
+DECLARE_CSR(mtvec, CSR_MTVEC)
+DECLARE_CSR(mscratch, CSR_MSCRATCH)
+DECLARE_CSR(mepc, CSR_MEPC)
+DECLARE_CSR(mcause, CSR_MCAUSE)
+DECLARE_CSR(mbadaddr, CSR_MBADADDR)
+DECLARE_CSR(mip, CSR_MIP)
+DECLARE_CSR(tselect, CSR_TSELECT)
+DECLARE_CSR(tdata1, CSR_TDATA1)
+DECLARE_CSR(tdata2, CSR_TDATA2)
+DECLARE_CSR(tdata3, CSR_TDATA3)
+DECLARE_CSR(dcsr, CSR_DCSR)
+DECLARE_CSR(dpc, CSR_DPC)
+DECLARE_CSR(dscratch, CSR_DSCRATCH)
+DECLARE_CSR(mcycle, CSR_MCYCLE)
+DECLARE_CSR(minstret, CSR_MINSTRET)
+DECLARE_CSR(mhpmcounter3, CSR_MHPMCOUNTER3)
+DECLARE_CSR(mhpmcounter4, CSR_MHPMCOUNTER4)
+DECLARE_CSR(mhpmcounter5, CSR_MHPMCOUNTER5)
+DECLARE_CSR(mhpmcounter6, CSR_MHPMCOUNTER6)
+DECLARE_CSR(mhpmcounter7, CSR_MHPMCOUNTER7)
+DECLARE_CSR(mhpmcounter8, CSR_MHPMCOUNTER8)
+DECLARE_CSR(mhpmcounter9, CSR_MHPMCOUNTER9)
+DECLARE_CSR(mhpmcounter10, CSR_MHPMCOUNTER10)
+DECLARE_CSR(mhpmcounter11, CSR_MHPMCOUNTER11)
+DECLARE_CSR(mhpmcounter12, CSR_MHPMCOUNTER12)
+DECLARE_CSR(mhpmcounter13, CSR_MHPMCOUNTER13)
+DECLARE_CSR(mhpmcounter14, CSR_MHPMCOUNTER14)
+DECLARE_CSR(mhpmcounter15, CSR_MHPMCOUNTER15)
+DECLARE_CSR(mhpmcounter16, CSR_MHPMCOUNTER16)
+DECLARE_CSR(mhpmcounter17, CSR_MHPMCOUNTER17)
+DECLARE_CSR(mhpmcounter18, CSR_MHPMCOUNTER18)
+DECLARE_CSR(mhpmcounter19, CSR_MHPMCOUNTER19)
+DECLARE_CSR(mhpmcounter20, CSR_MHPMCOUNTER20)
+DECLARE_CSR(mhpmcounter21, CSR_MHPMCOUNTER21)
+DECLARE_CSR(mhpmcounter22, CSR_MHPMCOUNTER22)
+DECLARE_CSR(mhpmcounter23, CSR_MHPMCOUNTER23)
+DECLARE_CSR(mhpmcounter24, CSR_MHPMCOUNTER24)
+DECLARE_CSR(mhpmcounter25, CSR_MHPMCOUNTER25)
+DECLARE_CSR(mhpmcounter26, CSR_MHPMCOUNTER26)
+DECLARE_CSR(mhpmcounter27, CSR_MHPMCOUNTER27)
+DECLARE_CSR(mhpmcounter28, CSR_MHPMCOUNTER28)
+DECLARE_CSR(mhpmcounter29, CSR_MHPMCOUNTER29)
+DECLARE_CSR(mhpmcounter30, CSR_MHPMCOUNTER30)
+DECLARE_CSR(mhpmcounter31, CSR_MHPMCOUNTER31)
+DECLARE_CSR(mucounteren, CSR_MUCOUNTEREN)
+DECLARE_CSR(mscounteren, CSR_MSCOUNTEREN)
+DECLARE_CSR(mhpmevent3, CSR_MHPMEVENT3)
+DECLARE_CSR(mhpmevent4, CSR_MHPMEVENT4)
+DECLARE_CSR(mhpmevent5, CSR_MHPMEVENT5)
+DECLARE_CSR(mhpmevent6, CSR_MHPMEVENT6)
+DECLARE_CSR(mhpmevent7, CSR_MHPMEVENT7)
+DECLARE_CSR(mhpmevent8, CSR_MHPMEVENT8)
+DECLARE_CSR(mhpmevent9, CSR_MHPMEVENT9)
+DECLARE_CSR(mhpmevent10, CSR_MHPMEVENT10)
+DECLARE_CSR(mhpmevent11, CSR_MHPMEVENT11)
+DECLARE_CSR(mhpmevent12, CSR_MHPMEVENT12)
+DECLARE_CSR(mhpmevent13, CSR_MHPMEVENT13)
+DECLARE_CSR(mhpmevent14, CSR_MHPMEVENT14)
+DECLARE_CSR(mhpmevent15, CSR_MHPMEVENT15)
+DECLARE_CSR(mhpmevent16, CSR_MHPMEVENT16)
+DECLARE_CSR(mhpmevent17, CSR_MHPMEVENT17)
+DECLARE_CSR(mhpmevent18, CSR_MHPMEVENT18)
+DECLARE_CSR(mhpmevent19, CSR_MHPMEVENT19)
+DECLARE_CSR(mhpmevent20, CSR_MHPMEVENT20)
+DECLARE_CSR(mhpmevent21, CSR_MHPMEVENT21)
+DECLARE_CSR(mhpmevent22, CSR_MHPMEVENT22)
+DECLARE_CSR(mhpmevent23, CSR_MHPMEVENT23)
+DECLARE_CSR(mhpmevent24, CSR_MHPMEVENT24)
+DECLARE_CSR(mhpmevent25, CSR_MHPMEVENT25)
+DECLARE_CSR(mhpmevent26, CSR_MHPMEVENT26)
+DECLARE_CSR(mhpmevent27, CSR_MHPMEVENT27)
+DECLARE_CSR(mhpmevent28, CSR_MHPMEVENT28)
+DECLARE_CSR(mhpmevent29, CSR_MHPMEVENT29)
+DECLARE_CSR(mhpmevent30, CSR_MHPMEVENT30)
+DECLARE_CSR(mhpmevent31, CSR_MHPMEVENT31)
+DECLARE_CSR(mvendorid, CSR_MVENDORID)
+DECLARE_CSR(marchid, CSR_MARCHID)
+DECLARE_CSR(mimpid, CSR_MIMPID)
+DECLARE_CSR(mhartid, CSR_MHARTID)
+DECLARE_CSR(cycleh, CSR_CYCLEH)
+DECLARE_CSR(timeh, CSR_TIMEH)
+DECLARE_CSR(instreth, CSR_INSTRETH)
+DECLARE_CSR(hpmcounter3h, CSR_HPMCOUNTER3H)
+DECLARE_CSR(hpmcounter4h, CSR_HPMCOUNTER4H)
+DECLARE_CSR(hpmcounter5h, CSR_HPMCOUNTER5H)
+DECLARE_CSR(hpmcounter6h, CSR_HPMCOUNTER6H)
+DECLARE_CSR(hpmcounter7h, CSR_HPMCOUNTER7H)
+DECLARE_CSR(hpmcounter8h, CSR_HPMCOUNTER8H)
+DECLARE_CSR(hpmcounter9h, CSR_HPMCOUNTER9H)
+DECLARE_CSR(hpmcounter10h, CSR_HPMCOUNTER10H)
+DECLARE_CSR(hpmcounter11h, CSR_HPMCOUNTER11H)
+DECLARE_CSR(hpmcounter12h, CSR_HPMCOUNTER12H)
+DECLARE_CSR(hpmcounter13h, CSR_HPMCOUNTER13H)
+DECLARE_CSR(hpmcounter14h, CSR_HPMCOUNTER14H)
+DECLARE_CSR(hpmcounter15h, CSR_HPMCOUNTER15H)
+DECLARE_CSR(hpmcounter16h, CSR_HPMCOUNTER16H)
+DECLARE_CSR(hpmcounter17h, CSR_HPMCOUNTER17H)
+DECLARE_CSR(hpmcounter18h, CSR_HPMCOUNTER18H)
+DECLARE_CSR(hpmcounter19h, CSR_HPMCOUNTER19H)
+DECLARE_CSR(hpmcounter20h, CSR_HPMCOUNTER20H)
+DECLARE_CSR(hpmcounter21h, CSR_HPMCOUNTER21H)
+DECLARE_CSR(hpmcounter22h, CSR_HPMCOUNTER22H)
+DECLARE_CSR(hpmcounter23h, CSR_HPMCOUNTER23H)
+DECLARE_CSR(hpmcounter24h, CSR_HPMCOUNTER24H)
+DECLARE_CSR(hpmcounter25h, CSR_HPMCOUNTER25H)
+DECLARE_CSR(hpmcounter26h, CSR_HPMCOUNTER26H)
+DECLARE_CSR(hpmcounter27h, CSR_HPMCOUNTER27H)
+DECLARE_CSR(hpmcounter28h, CSR_HPMCOUNTER28H)
+DECLARE_CSR(hpmcounter29h, CSR_HPMCOUNTER29H)
+DECLARE_CSR(hpmcounter30h, CSR_HPMCOUNTER30H)
+DECLARE_CSR(hpmcounter31h, CSR_HPMCOUNTER31H)
+DECLARE_CSR(mcycleh, CSR_MCYCLEH)
+DECLARE_CSR(minstreth, CSR_MINSTRETH)
+DECLARE_CSR(mhpmcounter3h, CSR_MHPMCOUNTER3H)
+DECLARE_CSR(mhpmcounter4h, CSR_MHPMCOUNTER4H)
+DECLARE_CSR(mhpmcounter5h, CSR_MHPMCOUNTER5H)
+DECLARE_CSR(mhpmcounter6h, CSR_MHPMCOUNTER6H)
+DECLARE_CSR(mhpmcounter7h, CSR_MHPMCOUNTER7H)
+DECLARE_CSR(mhpmcounter8h, CSR_MHPMCOUNTER8H)
+DECLARE_CSR(mhpmcounter9h, CSR_MHPMCOUNTER9H)
+DECLARE_CSR(mhpmcounter10h, CSR_MHPMCOUNTER10H)
+DECLARE_CSR(mhpmcounter11h, CSR_MHPMCOUNTER11H)
+DECLARE_CSR(mhpmcounter12h, CSR_MHPMCOUNTER12H)
+DECLARE_CSR(mhpmcounter13h, CSR_MHPMCOUNTER13H)
+DECLARE_CSR(mhpmcounter14h, CSR_MHPMCOUNTER14H)
+DECLARE_CSR(mhpmcounter15h, CSR_MHPMCOUNTER15H)
+DECLARE_CSR(mhpmcounter16h, CSR_MHPMCOUNTER16H)
+DECLARE_CSR(mhpmcounter17h, CSR_MHPMCOUNTER17H)
+DECLARE_CSR(mhpmcounter18h, CSR_MHPMCOUNTER18H)
+DECLARE_CSR(mhpmcounter19h, CSR_MHPMCOUNTER19H)
+DECLARE_CSR(mhpmcounter20h, CSR_MHPMCOUNTER20H)
+DECLARE_CSR(mhpmcounter21h, CSR_MHPMCOUNTER21H)
+DECLARE_CSR(mhpmcounter22h, CSR_MHPMCOUNTER22H)
+DECLARE_CSR(mhpmcounter23h, CSR_MHPMCOUNTER23H)
+DECLARE_CSR(mhpmcounter24h, CSR_MHPMCOUNTER24H)
+DECLARE_CSR(mhpmcounter25h, CSR_MHPMCOUNTER25H)
+DECLARE_CSR(mhpmcounter26h, CSR_MHPMCOUNTER26H)
+DECLARE_CSR(mhpmcounter27h, CSR_MHPMCOUNTER27H)
+DECLARE_CSR(mhpmcounter28h, CSR_MHPMCOUNTER28H)
+DECLARE_CSR(mhpmcounter29h, CSR_MHPMCOUNTER29H)
+DECLARE_CSR(mhpmcounter30h, CSR_MHPMCOUNTER30H)
+DECLARE_CSR(mhpmcounter31h, CSR_MHPMCOUNTER31H)
+#endif
+#if defined(DECLARE_CAUSE)
+DECLARE_CAUSE("misaligned fetch", CAUSE_MISALIGNED_FETCH)
+DECLARE_CAUSE("fault fetch", CAUSE_FAULT_FETCH)
+DECLARE_CAUSE("illegal instruction", CAUSE_ILLEGAL_INSTRUCTION)
+DECLARE_CAUSE("breakpoint", CAUSE_BREAKPOINT)
+DECLARE_CAUSE("misaligned load", CAUSE_MISALIGNED_LOAD)
+DECLARE_CAUSE("fault load", CAUSE_FAULT_LOAD)
+DECLARE_CAUSE("misaligned store", CAUSE_MISALIGNED_STORE)
+DECLARE_CAUSE("fault store", CAUSE_FAULT_STORE)
+DECLARE_CAUSE("user_ecall", CAUSE_USER_ECALL)
+DECLARE_CAUSE("supervisor_ecall", CAUSE_SUPERVISOR_ECALL)
+DECLARE_CAUSE("hypervisor_ecall", CAUSE_HYPERVISOR_ECALL)
+DECLARE_CAUSE("machine_ecall", CAUSE_MACHINE_ECALL)
+#endif
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/makeoffset.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/makeoffset.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/makeoffset.c	(revision 453)
@@ -0,0 +1,106 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2012 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+#include "kernel_impl.h"
+#include "task.h"
+#include "sil.h"
+
+#define OFFSET_DEF(TYPE, FIELD)							\
+	Asm("OFFSET_DEF " #TYPE "_" #FIELD " = %0"			\
+	  : /* no output */									\
+	  : "g"(offsetof(TYPE, FIELD)))
+
+#define OFFSET_DEF2(TYPE, FIELD, FIELDNAME)				\
+	Asm("OFFSET_DEF " #TYPE "_" #FIELDNAME " = %0"		\
+	  : /* no output */									\
+	  : "g"(offsetof(TYPE, FIELD)))
+
+void
+makeoffset(void)
+{
+	OFFSET_DEF(TCB, p_tinib);
+	OFFSET_DEF(TCB, texptn);
+	OFFSET_DEF2(TCB, tskctxb.sp, sp);
+	OFFSET_DEF2(TCB, tskctxb.pc, pc);
+
+	OFFSET_DEF(TINIB, exinf);
+	OFFSET_DEF(TINIB, task);
+}
+
+void
+sil_endian(void)
+{
+#ifdef SIL_ENDIAN_BIG			/* ビッグエンディアンプロセッサ */
+	Asm("SIL_ENDIAN = BIG");
+#else /* SIL_ENDIAN_BIG */
+#ifdef SIL_ENDIAN_LITTLE		/* リトルエンディアンプロセッサ */
+	Asm("SIL_ENDIAN = LITTLE");
+#endif /* SIL_ENDIAN_LITTLE */
+#endif /* SIL_ENDIAN_BIG */
+}
+
+uint32_t	BIT_REF_4 = 0x12345678;
+uint16_t	BIT_REF_2 = 0x1234;
+uint8_t		BIT_REF_1 = 0x12;
+
+TCB	BIT_BB_TCB_enatex = {
+	{ NULL, NULL },			/* task_queue */
+	NULL,					/* p_tinib */
+	0U,						/* tstat */
+#ifdef TOPPERS_SUPPORT_MUTEX
+	0U,						/* bpriority */
+#endif /* TOPPERS_SUPPORT_MUTEX */
+	0U,						/* priority */
+	false,					/* acqeue */
+	false,					/* wupque */
+	true,					/* enatex */
+	0U,						/* texptn */
+	NULL,					/* p_winifo */
+#ifdef TOPPERS_SUPPORT_MUTEX
+	{ NULL, NULL },			/* mutex_queue */
+#endif /* TOPPERS_SUPPORT_MUTEX */
+#ifdef TOPPERS_SUPPORT_OVRHDR
+	0U,						/* leftotm */
+#endif /* TOPPERS_SUPPORT_OVRHDR */
+	{ NULL, NULL }			/* tskctxb */
+};
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_cfg1_out.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_cfg1_out.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_cfg1_out.h	(revision 453)
@@ -0,0 +1,48 @@
+/*
+ *		cfg1_out.cのリンクに必要なスタブの定義
+ */
+
+void sta_ker(void)
+{
+}
+
+void hardware_init_hook(void)
+{
+}
+
+void software_init_hook(void)
+{
+}
+
+const SIZE		_kernel_istksz = 0;
+
+STK_T *const	_kernel_istk = NULL;
+
+/*
+ *  オフセットファイルを生成するための定義
+ */
+const uint8_t	MAGIC_1 = 0x12;
+const uint16_t	MAGIC_2 = 0x1234;
+const uint32_t	MAGIC_4 = 0x12345678;
+
+const TCB	TCB_enatex = {
+	{ NULL, NULL },			/* task_queue */
+	NULL,					/* p_tinib */
+	0U,						/* tstat */
+#ifdef TOPPERS_SUPPORT_MUTEX
+	0U,						/* bpriority */
+#endif /* TOPPERS_SUPPORT_MUTEX */
+	0U,						/* priority */
+	false,					/* acqeue */
+	false,					/* wupque */
+	true,					/* enatex */
+	0U,						/* texptn */
+	NULL,					/* p_winifo */
+#ifdef TOPPERS_SUPPORT_MUTEX
+	{ NULL, NULL },			/* mutex_queue */
+#endif /* TOPPERS_SUPPORT_MUTEX */
+#ifdef TOPPERS_SUPPORT_OVRHDR
+	0U,						/* leftotm */
+#endif /* TOPPERS_SUPPORT_OVRHDR */
+	{ NULL, NULL }			/* tskctxb */
+};
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_config.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_config.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_config.c	(revision 453)
@@ -0,0 +1,240 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2009 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		プロセッサ依存モジュール（RISC-V用）
+ */
+
+#include "kernel_impl.h"
+#include "check.h"
+#include "task.h"
+
+/*
+ *  CPUロックフラグ実現のための変数
+ */
+volatile bool_t			lock_flag;	/* CPUロックフラグの値を保持する変数 */
+volatile uint16_t		inest_lvl;	/* 割込みネストを保存する変数 */
+volatile unsigned long	kernel_mie;	/* デフォルトのMIE値を保存する変数 */
+static unsigned long	saved_trap;	/* MACHINE TRAPデータの保存変数 */
+
+/*
+ *  MACHINE割込みハンドラ領域のテーブル
+ */
+volatile EXCVE m_interrupt_handlers[TMAX_MACHNE_INTNO];
+
+
+#ifndef OMIT_DEFAULT_INT_HANDLER
+/*
+ *  未登録の割込みが発生した場合に呼び出される
+ */
+static void
+default_int_handler(unsigned long mcause, void *p_excinf)
+{
+	unsigned long mstatus = *(((uintptr_t*)p_excinf) + P_EXCINF_OFFSET_MSTATUS);
+	uintptr_t     pc      = *(((uintptr_t*)p_excinf) + P_EXCINF_OFFSET_PC);
+	unsigned long excno   = mcause & MCAUSE_CAUSE;
+
+	if((long)mcause < 0)
+		excno += TMAX_MACHNE_INTNO / 2;
+
+	switch (excno) {
+	case EXC_INSTRUCTION_ADDRESS_MISALIGNED:
+		syslog(LOG_EMERG, "\nUnregistered instruction address misaligned occurs.");
+		break;
+	case EXC_INSTRUCTION_ADDRESS_FAULT:
+		syslog(LOG_EMERG, "\nUnregistered instruction address fault occurs.");
+		break;
+	case EXC_ILLEGAL_INSTRUCTION:
+		syslog(LOG_EMERG, "\nUnregistered illegal instruction occurs.");
+		break;
+	case EXC_BREAKPOINT:
+		syslog(LOG_EMERG, "\nUnregistered breakpoint occurs.");
+		break;
+	case EXC_LOAD_ADDRESS_MISALIGNED:
+		syslog(LOG_EMERG, "\nUnregistered load address misaligned occurs.");
+		break;
+	case EXC_LOAD_ADDRESS_FAULT:
+		syslog(LOG_EMERG, "\nUnregistered load address fault occurs.");
+		break;
+	case EXC_STORE_AMO_ADDRESS_MISALIGNED:
+		syslog(LOG_EMERG, "\nUnregistered store AMO address misaligned occurs.");
+		break;
+	case EXC_STORE_AMO_ACCESS_FAUT:
+		syslog(LOG_EMERG, "\nUnregistered store AMO access faut occurs.");
+		break;
+	case EXC_ENVIRONMENT_CALL_FROM_MMODE:
+		syslog(LOG_EMERG, "\nUnregistered environment call from MMODE occurs.");
+		break;
+	default:
+		syslog(LOG_EMERG, "\nUnregistered Interrupt occurs.");
+		break;
+	}
+
+	syslog(LOG_EMERG, "Excno = 0x%02X, PC = 0x%X, mstatus = 0x%X, p_excinf = 0x%X",
+		   excno, pc, mstatus, p_excinf);
+
+	target_exit();
+}
+#endif /* OMIT_DEFAULT_INT_HANDLER */
+
+/*
+ *  プロセッサ依存の初期化
+ */
+void
+prc_initialize(void)
+{
+	extern void	software_init_hook(void);
+	void (*volatile fp)(void) = software_init_hook;
+	int  i;
+
+	/*
+	 *  software_init_hookへのポインタを，一旦volatile指定のあるfpに代
+	 *  入してから使うのは，0との比較が最適化で削除されないようにするた
+	 *  めである．
+	 */
+	if (fp != 0) {
+		(*fp)();
+	}
+
+	/*
+	 *  CPUロックフラグ実現のための変数の初期化
+	 */
+	lock_flag  = true;
+	kernel_mie = KERNEL_MIE;
+	clear_csr(mie, KERNEL_MIE);
+	set_csr(mie, MIP_MSIP);
+	inest_lvl  = 0;
+
+	/*
+	 *  例外ベクタテーブルの初期化
+	 */
+#ifndef OMIT_DEFAULT_INT_HANDLER
+	for(i = 0 ; i < TMAX_MACHNE_INTNO ; i++){
+		m_interrupt_handlers[i].exc_handler = (FP)default_int_handler;
+	}
+#endif
+	saved_trap = read_csr(mtvec);
+	write_csr(mtvec, &trap_entry);
+	ena_intm();
+
+	/*
+	 *  FPU拡張の初期化
+	 */
+	if(read_csr(misa) & (1 << ('F' - 'A'))){
+		set_csr(mstatus, MSTATUS_FS);	/* FPU設定、但し割込みはサポートしない */
+		write_csr(fcsr, 0);				/* ラウンディングモード設定 */
+	}
+
+	(void)(i);
+}
+
+/*
+ *  プロセッサ依存の終了処理
+ */
+void
+prc_terminate(void)
+{
+	extern void	software_term_hook(void);
+	void (*volatile fp)(void) = software_term_hook;
+
+	/*
+	 *  software_term_hookへのポインタを，一旦volatile指定のあるfpに代
+	 *  入してから使うのは，0との比較が最適化で削除されないようにするた
+	 *  めである．
+	 */
+	if (fp != 0) {
+		(*fp)();
+	}
+
+	write_csr(mtvec, saved_trap);
+}
+
+/*
+ *  C言語レベル MACHINE割込みハンドラ
+ */
+uint32_t
+handle_trap(unsigned long mcause, void *p_excinf)
+{
+	uint32_t intno = mcause & MCAUSE_CAUSE;
+	void     (*func)(unsigned long, void *);
+
+	if(inest_lvl++ == 0)
+		write_csr(mtvec, &trap_nest);
+	if((long)mcause < 0)
+		intno += TMAX_MACHNE_INTNO / 2;
+	if(intno < TMAX_MACHNE_INTNO){
+		func = (void(*)(unsigned long, void *))m_interrupt_handlers[intno].exc_handler;
+		if(func != NULL)
+			func(mcause, p_excinf);
+	}
+	else{
+		syslog_1(LOG_EMERG, "Irrigal machine Exception mcause = %08X", (int)intno);
+	}
+	if(--inest_lvl == 0)
+		write_csr(mtvec, &trap_entry);
+	return inest_lvl;
+}
+
+/*
+ *  CPU例外の発生状況のログ出力
+ *
+ *  CPU例外ハンドラの中から，CPU例外情報ポインタ（p_excinf）を引数とし
+ *  て呼び出すことで，CPU例外の発生状況をシステムログに出力する．
+ */
+#ifdef SUPPORT_XLOG_SYS
+
+void
+xlog_sys(void *p_excinf)
+{
+	unsigned long *excsp = (unsigned long *) p_excinf;
+
+	syslog_0(LOG_ERROR, "CPU Exception Information:");
+	syslog_4(LOG_ERROR, "mstatus = %08x PC = %x mcause = %x STACK = %x",
+				*((excsp + P_EXCINF_OFFSET_MSTATUS)), 
+				*((excsp + P_EXCINF_OFFSET_PC)),
+				*((excsp + P_EXCINF_OFFSET_MCAUSE)),
+				((unsigned long)excsp + 19 * 4));
+	syslog_1(LOG_ERROR, "p_excinf = %x", (unsigned long)excsp);
+}
+
+#endif /* SUPPORT_XLOG_SYS */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_config.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_config.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_config.h	(revision 453)
@@ -0,0 +1,474 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		プロセッサ依存モジュール（RISC-V用）
+ *
+ *  このインクルードファイルは，target_config.h（または，そこからインク
+ *  ルードされるファイル）のみからインクルードされる．他のファイルから
+ *  直接インクルードしてはならない．
+ */
+
+#ifndef TOPPERS_PRC_CONFIG_H
+#define TOPPERS_PRC_CONFIG_H
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  プロセッサの特殊命令のインライン関数定義
+ */
+#include "encoding.h"
+
+/*
+ *  MCAUSE REGISTER定義
+ */
+#define MCAUSE_CAUSE        0x7FFFFFFF
+
+/*
+ *  使用するシリアルポートID
+ */
+#ifndef SIO_PORTID
+#define SIO_PORTID		(1)
+#endif /* SIO_PORTID */
+
+/*
+ *  MACHINEの最大割込み数を定義
+ */
+#define TMAX_MACHNE_INTNO	32
+
+/*
+ *  タスクコンテキストブロックの定義
+ */
+typedef struct task_context_block {
+	void	*sp;		/* スタックポインタ */
+	FP		pc;			/* プログラムカウンタ */
+} TSKCTXB;
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+/*
+ *  割込み優先度マスク操作ライブラリ
+ *
+ *  RISCV/32では，PLICの割込みスレッシュホールドで割込みレベルを管理する．
+ */
+
+/*
+ *  割込み優先度マスクの外部表現と内部表現の変換
+ */
+#define EXT_IPM(iipm)	(-CAST(PRI, (iipm)))		/* 外部表現に変換 */
+#define INT_IPM(ipm)	CAST(uint16_t, -(ipm))		/* 内部表現に変換 */
+
+/*
+ *  カーネル割込み設定定義
+ */
+#define KERNEL_MIE		(MIP_MTIP | MIP_MEIP)
+
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  CPUロックフラグ実現のための変数
+ *
+ *  これらの変数は，CPUロック状態の時のみ書き換えてよいものとする．
+ */
+extern volatile bool_t			lock_flag;	/* CPUロックフラグの値を保持する変数 */
+extern volatile uint16_t		inest_lvl;	/* 割込みネストを保存する変数 */
+extern volatile unsigned long	kernel_mie;	/* デフォルトのMIE値を保存する変数 */
+
+/*
+ *  TOPPERS標準割込み処理モデルの実現
+ *
+ *  割込み優先度マスクとしては，mie（MACHINE割込みイネーブルレジスタ）を
+ *  用いる．全割込みを禁止する機能として，mstatusのMIEやPLICの割込みスレ
+ *  ッドが，カーネル管理外の割込みをサポートするため，これらはCPUロック
+ *  のために用いない．
+ *  PLICの割込みスレッドでは、MITの割込みロックができないことも、
+ *  この選択とした理由である．
+ *
+ *  CPUロック状態を管理すための変数(lock_flag)を用意する．
+ *  システムスタックのネスト管理の変数(inest_lvl)を用意する．
+ *  外部割込みの制御はPLICを用いるが、この制御はPRCでは管理せず
+ *  ターゲットレベルで管理を行う．
+ */
+
+/*
+ *  コンテキストの参照
+ *
+ *  RISCVでは，割込みネストレベルでコンテキストを判定する．
+ */
+Inline bool_t
+sense_context(void)
+{
+	return inest_lvl != 0;
+}
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+/*
+ *  例外フレームのオフセット
+ */
+#define P_EXCINF_OFFSET_MSTATUS     0x00
+#define P_EXCINF_OFFSET_PC          0x01
+#define P_EXCINF_OFFSET_MCAUSE		0x02
+#define P_EXCONF_OFFSET_MIE         0x03
+#define P_EXCONF_OFFSET_SP          0x04
+
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  MACHINE割込みの禁止
+ *
+ *  割込み制御で使用するため作成．
+ */
+Inline void
+dis_intm(void)
+{
+	clear_csr(mstatus, MSTATUS_MIE);
+}
+
+/*
+ *  MACHINE割込みの許可
+ *
+ *  割込み制御で使用するため作成．
+ */
+Inline void
+ena_intm(void)
+{
+	set_csr(mstatus, MSTATUS_MIE);
+}
+
+/*
+ *  CPUロック状態への移行
+ *
+ *  mie（MACHINE割込みイネーブルレジスタ）を，カーネル管理割込み設
+ *  定をマスクすることでCPUロック状態を設定する．
+ *  また，lock_flagをtrueにする．
+ *
+ *  この関数は，CPUロック状態（lock_flagがtrueの状態）で呼ばれることは
+ *  ないものと想定している．
+ */
+Inline void
+x_lock_cpu(void)
+{
+	clear_csr(mie, KERNEL_MIE);
+	lock_flag = true;
+}
+
+#define t_lock_cpu()	x_lock_cpu()
+#define i_lock_cpu()	x_lock_cpu()
+
+/*
+ *  CPUロック状態の解除
+ *
+ *  lock_flagをfalseにし，mie（MACHINE割込みイネーブルレジスタ）中の，
+ *  イネーブル設定を行う．
+ *
+ *  この関数は，CPUロック状態（lock_flagがtrueの状態）でのみ呼ばれるも
+ *  のと想定している．
+ */
+Inline void
+x_unlock_cpu(void)
+{
+	lock_flag = false;
+	set_csr(mie, kernel_mie);
+}
+
+#define t_unlock_cpu()	x_unlock_cpu()
+#define i_unlock_cpu()	x_unlock_cpu()
+
+/*
+ *  CPUロック状態の参照
+ */
+Inline bool_t
+x_sense_lock(void)
+{
+	return(lock_flag);
+}
+
+#define t_sense_lock()	x_sense_lock()
+#define i_sense_lock()	x_sense_lock()
+
+/*
+ *  chg_ipmで有効な割込み優先度の範囲の判定
+ */
+#define VALID_INTPRI_CHGIPM(intpri) \
+				(TMIN_INTPRI <= (intpri) && (intpri) <= TMAX_INTPRI)
+
+/*
+ * （モデル上の）割込み優先度マスクの設定
+ *
+ *  CPUロックフラグがクリアされている時は，ハードウェアの割込み優先度マ
+ *  スクを設定する．(mitは想定していない)
+ */
+Inline void
+x_set_ipm(PRI intpri)
+{
+	set_ithreshold(INT_IPM(intpri));
+}
+
+#define t_set_ipm(intpri)	x_set_ipm(intpri)
+#define i_set_ipm(intpri)	x_set_ipm(intpri)
+
+/*
+ * （モデル上の）割込み優先度マスクの参照
+ *
+ *  CPUロックフラグがクリアされている時はハードウェアの割込み優先度マ
+ *  スクを参照する．
+ */
+Inline PRI
+x_get_ipm(void)
+{
+	return(EXT_IPM(current_ithreshold()));
+}
+
+#define t_get_ipm()		x_get_ipm()
+#define i_get_ipm()		x_get_ipm()
+
+/*
+ *  最高優先順位タスクへのディスパッチ（prc_support.S）
+ *
+ *  dispatchは，タスクコンテキストから呼び出されたサービスコール処理か
+ *  ら呼び出すべきもので，タスクコンテキスト・CPUロック状態・ディスパッ
+ *  チ許可状態・（モデル上の）割込み優先度マスク全解除状態で呼び出さな
+ *  ければならない．
+ */
+extern void	dispatch(void);
+
+/*
+ *  ディスパッチャの動作開始（prc_support.S）
+ *
+ *  start_dispatchは，カーネル起動時に呼び出すべきもので，すべての割込
+ *  みを禁止した状態（割込みロック状態と同等の状態）で呼び出さなければ
+ *  ならない．
+ */
+extern void	start_dispatch(void) NoReturn;
+
+/*
+ *  現在のコンテキストを捨ててディスパッチ（prc_support.S）
+ *
+ *  exit_and_dispatchは，ext_tskから呼び出すべきもので，タスクコンテキ
+ *  スト・CPUロック状態・ディスパッチ許可状態・（モデル上の）割込み優先
+ *  度マスク全解除状態で呼び出さなければならない．
+ */
+extern void	exit_and_dispatch(void) NoReturn;
+
+/*
+ *  カーネルの終了処理の呼出し（prc_support.S）
+ *
+ *  call_exit_kernelは，カーネルの終了時に呼び出すべきもので，非タスク
+ *  コンテキストに切り換えて，カーネルの終了処理（exit_kernel）を呼び出
+ *  す．
+ */
+extern void call_exit_kernel(void) NoReturn;
+
+/*
+ *  MACHINE割込みトラップ関数 （prc_support.S）
+ *
+ *  trap_entryは最初のMACHINE割込みを処理する関数．
+ */
+extern void trap_entry(void);
+
+/*
+ *  MACHINE割込みネストトラップ関数 （prc_support.S）
+ *
+ *  trap_entryはネスト時のMACHINE割込みを処理する関数．
+ */
+extern void trap_nest(void);
+
+
+/*
+ *  タスクコンテキストの初期化
+ *
+ *  タスクが休止状態から実行できる状態に移行する時に呼ばれる．この時点
+ *  でスタック領域を使ってはならない．
+ *
+ *  activate_contextを，インライン関数ではなくマクロ定義としているのは，
+ *  この時点ではTCBが定義されていないためである．
+ */
+extern void	start_r(void);
+
+#define activate_context(p_tcb)											\
+{																		\
+	(p_tcb)->tskctxb.sp = (void *)((char *)((p_tcb)->p_tinib->stk)		\
+										+ (p_tcb)->p_tinib->stksz);		\
+	(p_tcb)->tskctxb.pc = (void *) start_r;								\
+}
+
+/*
+ *  calltexは使用しない
+ */
+#define OMIT_CALLTEX
+
+/*
+ *  例外ベクタテーブルの構造の定義
+ */
+typedef struct exc_vector_entry {
+	FP		exc_handler;		/* 例外ハンドラの起動番地 */
+} EXCVE;
+
+/*
+ *  MACHINE割込みハンドラ領域のテーブル
+ */
+extern volatile EXCVE m_interrupt_handlers[TMAX_MACHNE_INTNO];
+
+/*
+ *  CPU例外ハンドラの設定
+ *
+ *  ベクトル番号excnoのCPU例外ハンドラの出入口処理の番地をexc_entryに設
+ *  定する．
+ */
+Inline void
+x_define_exc(EXCNO excno, FP exc_entry)
+{
+	m_interrupt_handlers[excno].exc_handler = exc_entry;
+}
+
+/*
+ *  MACHINE割込みハンドラの設定
+ */
+Inline void
+x_machine_inh(INHNO inhno, FP int_entry)
+{
+	m_interrupt_handlers[inhno+16].exc_handler = int_entry;
+}
+
+/*
+ *  CPU例外ハンドラの出入口処理の生成
+ *
+ *  CPU例外ハンドラの番地をA1に，CPU例外ハンドラ番号をD1に入れて，
+ *  exchdr_entryに分岐する．割込みハンドラの出入口処理と同様に，CPU例外
+ *  ハンドラ毎にCPU例外ハンドラを呼び出す処理を展開する方法もあるが，展
+ *  開する処理内容が複雑であるため，採用していない．
+ */
+
+/*
+ *  CPU例外ハンドラの出入口処理のラベルを作るマクロ
+ */
+#define EXC_ENTRY(excno, exchdr)	_kernel_##exchdr##_##excno
+
+/*
+ *  CPU例外ハンドラの出入口処理
+ */
+#if defined(__riscv64)
+#define EXCHDR_ENTRY(excno, excno_num, exchdr) \
+extern void _kernel_##exchdr##_##excno(void *sp); \
+asm(".text							\n" \
+"_kernel_" #exchdr "_" #excno ":	\n" \
+"	addi sp, sp, -32				\n"	 /* 保存領域を確保 */ \
+"	sd ra, 24(sp)					\n"	 /* return addressをセーブ */ \
+"	csrsi mstatus, 8				\n"	 /* 割込みを許可(MSTATUS_MIE) */ \
+"	mv a0, a1						\n"  /* stack pointerをa0に */ \
+"	jal " #exchdr "					\n"	 /* exchdrに分岐 */ \
+"	ld ra, 24(sp)					\n"	 /* return addressをリストア */ \
+"	csrci mstatus, 8				\n"	 /* 割込みを禁止(MSTATUS_MIE) */ \
+"	addi sp, sp, 32					\n"	 /* 保存領域を開放 */ \
+"	ret								\n");/* リターン */
+#else
+#define EXCHDR_ENTRY(excno, excno_num, exchdr) \
+extern void _kernel_##exchdr##_##excno(void *sp); \
+asm(".text							\n" \
+"_kernel_" #exchdr "_" #excno ":	\n" \
+"	addi sp, sp, -16				\n"	 /* 保存領域を確保 */ \
+"	sw ra, 12(sp)					\n"	 /* return addressをセーブ */ \
+"	csrsi mstatus, 8				\n"	 /* 割込みを許可(MSTATUS_MIE) */ \
+"	mv a0, a1						\n"  /* stack pointerをa0に */ \
+"	jal " #exchdr "					\n"	 /* exchdrに分岐 */ \
+"	lw ra, 12(sp)					\n"	 /* return addressをリストア */ \
+"	csrci mstatus, 8				\n"	 /* 割込みを禁止(MSTATUS_MIE) */ \
+"	addi sp, sp, 16					\n"	 /* 保存領域を開放 */ \
+"	ret								\n");/* リターン */
+#endif
+
+/*
+ *  CPU例外の発生した時のコンテキストの参照
+ *
+ *  CPU例外の発生した時のコンテキストが，タスクコンテキストの時にfalse，
+ *  そうでない時にtrueを返す．
+ */
+Inline bool_t
+exc_sense_context(void *p_excinf)
+{
+	return inest_lvl > 1;
+}
+
+/*
+ *  CPU例外の発生した時のコンテキストと割込みのマスク状態の参照
+ *
+ *  CPU例外の発生した時のシステム状態が，カーネル実行中でなく，タスクコ
+ *  ンテキストであり，全割込みロック状態でなく，CPUロック状態でなく，割
+ *  込み優先度マスク全解除状態である時にtrue，そうでない時にfalseを返す
+ *  （CPU例外がカーネル管理外の割込み処理中で発生した場合にもfalseを返
+ *  す）．
+ *
+ *  CPU例外の発生した時のmie（MACHINE割込みイネーブルレジスタ）が初期設
+ *  定でないで，カーネル実行中でないこと，全割込みロック状態でないこと
+ *  ，CPUロック状態でないこと，割込み優先度マスク全解除状態であることの
+ *  4つの条件をチェックすることができる（CPU例外が発生した時のlock_flag
+ *  を参照する必要はない）．
+ */
+Inline bool_t
+exc_sense_intmask(void *p_excinf)
+{
+	return(!exc_sense_context(p_excinf)
+					&& ((read_csr(mie) & KERNEL_MIE) != 0));
+}
+
+
+/*
+ *  プロセッサ依存の初期化
+ */
+extern void	prc_initialize(void);
+
+/*
+ *  プロセッサ依存の終了時処理
+ */
+extern void	prc_terminate(void);
+
+/*
+ *  C言語レベル MACHINE割込みハンドラ
+ */
+extern uint32_t handle_trap(unsigned long mcause, void *p_excinf);
+
+#endif /* TOPPERS_MACRO_ONLY */
+#endif /* TOPPERS_PRC_CONFIG_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_def.csv
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_def.csv	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_def.csv	(revision 453)
@@ -0,0 +1,6 @@
+TMAX_INTNO,TMAX_INTNO
+sizeof_TCB,sizeof(TCB)
+offsetof_TCB_p_tinib,"offsetof(TCB,p_tinib)"
+offsetof_TCB_texptn,"offsetof(TCB,texptn)"
+offsetof_TCB_sp,"offsetof(TCB,tskctxb.sp)"
+offsetof_TCB_pc,"offsetof(TCB,tskctxb.pc)"
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_kernel.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_kernel.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_kernel.h	(revision 453)
@@ -0,0 +1,69 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2007 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		kernel.hのプロセッサ依存部（RISC-V用）
+ *
+ *  このインクルードファイルは，target_kernel.h（または，そこからインク
+ *  ルードされるファイル）のみからインクルードされる．他のファイルから
+ *  直接インクルードしてはならない．
+ */
+
+#ifndef TOPPERS_PRC_KERNEL_H
+#define TOPPERS_PRC_KERNEL_H
+
+/*
+ *  サポートする機能の定義
+ */
+#define TOPPERS_TARGET_SUPPORT_DIS_INT      /* dis_intをサポートする */
+#define TOPPERS_TARGET_SUPPORT_ENA_INT      /* ena_intをサポートする */
+
+/*
+ *  カーネル管理の割込み優先度の範囲
+ */
+#ifndef TMIN_INTPRI
+#define TMIN_INTPRI		(-7)		/* 割込み優先度の最小値（最高値）*/
+#endif /* TMIN_INTPRI */
+#define TMAX_INTPRI		(-1)		/* 割込み優先度の最大値（最低値） */
+
+#endif /* TOPPERS_PRC_KERNEL_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_offset.tf
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_offset.tf	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_offset.tf	(revision 453)
@@ -0,0 +1,24 @@
+$ 
+$ 		オフセットファイル生成用テンプレートファイル（RISC-V用）
+$ 
+
+$ 
+$  標準テンプレートファイルのインクルード
+$ 
+$INCLUDE "kernel/genoffset.tf"$
+
+$ 
+$  オフセット値のマクロ定義の生成
+$ 
+$DEFINE("TCB_p_tinib", offsetof_TCB_p_tinib)$
+$DEFINE("TCB_texptn", offsetof_TCB_texptn)$
+$DEFINE("TCB_sp", offsetof_TCB_sp)$
+$DEFINE("TCB_pc", offsetof_TCB_pc)$
+
+$DEFINE("TINIB_exinf", offsetof_TINIB_exinf)$
+$DEFINE("TINIB_task", offsetof_TINIB_task)$
+
+$ 
+$  ビットオフセット値等のマクロ定義の生成
+$ 
+$DEFINE_BIT("TCB_enatex", sizeof_TCB, "B")$
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_rename.def
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_rename.def	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_rename.def	(revision 453)
@@ -0,0 +1,16 @@
+# prc_config.c
+prc_initialize
+prc_terminate
+handle_trap
+m_interrupt_handlers
+lock_flag
+inest_lvl
+
+# prc_support.S
+dispatch
+start_dispatch
+exit_and_dispatch
+call_exit_kernel
+start_r
+trap_entry
+trap_nest
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_rename.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_rename.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_rename.h	(revision 453)
@@ -0,0 +1,53 @@
+/* This file is generated from prc_rename.def by genrename. */
+
+#ifndef TOPPERS_PRC_RENAME_H
+#define TOPPERS_PRC_RENAME_H
+
+/*
+ *  prc_config.c
+ */
+#define prc_initialize				_kernel_prc_initialize
+#define prc_terminate				_kernel_prc_terminate
+#define handle_trap					_kernel_handle_trap
+#define m_interrupt_handlers		_kernel_m_interrupt_handlers
+#define lock_flag					_kernel_lock_flag
+#define inest_lvl					_kernel_inest_lvl
+
+/*
+ *  prc_support.S
+ */
+#define dispatch					_kernel_dispatch
+#define start_dispatch				_kernel_start_dispatch
+#define exit_and_dispatch			_kernel_exit_and_dispatch
+#define call_exit_kernel			_kernel_call_exit_kernel
+#define start_r						_kernel_start_r
+#define trap_entry					_kernel_trap_entry
+#define trap_nest					_kernel_trap_nest
+
+#ifdef TOPPERS_LABEL_ASM
+
+/*
+ *  prc_config.c
+ */
+#define _prc_initialize				__kernel_prc_initialize
+#define _prc_terminate				__kernel_prc_terminate
+#define _handle_trap				__kernel_handle_trap
+#define _m_interrupt_handlers		__kernel_m_interrupt_handlers
+#define _lock_flag					__kernel_lock_flag
+#define _inest_lvl					__kernel_inest_lvl
+
+/*
+ *  prc_support.S
+ */
+#define _dispatch					__kernel_dispatch
+#define _start_dispatch				__kernel_start_dispatch
+#define _exit_and_dispatch			__kernel_exit_and_dispatch
+#define _call_exit_kernel			__kernel_call_exit_kernel
+#define _start_r					__kernel_start_r
+#define _trap_entry					__kernel_trap_entry
+#define _trap_nest					__kernel_trap_nest
+
+#endif /* TOPPERS_LABEL_ASM */
+
+
+#endif /* TOPPERS_PRC_RENAME_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_sil.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_sil.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_sil.h	(revision 453)
@@ -0,0 +1,94 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2008 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		sil.hのプロセッサ依存部（RISC-V用）
+ */
+
+#ifndef TOPPERS_PRC_SIL_H
+#define TOPPERS_PRC_SIL_H
+
+#ifndef TOPPERS_MACRO_ONLY
+
+#include "encoding.h"
+
+/*
+ *  NMIを除くすべての割込みの禁止
+ */
+Inline unsigned long
+TOPPERS_disint(void)
+{
+	unsigned long TOPPERS_sr = read_csr(mie);;
+
+	clear_csr(mie, (MIP_MEIP | MIP_MTIP));
+	return(TOPPERS_sr);
+}
+
+/*
+ *  割込み優先度マスク（内部表現）の現在値の設定
+ */
+Inline void
+TOPPERS_enaint(unsigned long TOPPERS_mie)
+{
+	write_csr(mie, TOPPERS_mie);
+}
+
+/*
+ *  全割込みロック状態の制御
+ */
+#define SIL_PRE_LOC		unsigned long TOPPERS_mie
+#define SIL_LOC_INT()	((void)(TOPPERS_mie = TOPPERS_disint()))
+#define SIL_UNL_INT()	(TOPPERS_enaint(TOPPERS_mie))
+
+/*
+ *  微少時間待ち
+ */
+extern void sil_dly_nse(ulong_t dlytim);
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+/*
+ *  プロセッサのエンディアン
+ */
+#define SIL_ENDIAN_LITTLE				/* ビッグエンディアン */
+
+#endif /* TOPPERS_PRC_SIL_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_stddef.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_stddef.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_stddef.h	(revision 453)
@@ -0,0 +1,59 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2007 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		t_stddef.hのプロセッサ依存部（RISC-V用）
+ *
+ *  このインクルードファイルは，target_stddef.h（または，そこからインク
+ *  ルードされるファイル）のみからインクルードされる．他のファイルから
+ *  直接インクルードしてはならない．
+ */
+
+#ifndef TOPPERS_PRC_STDDEF_H
+#define TOPPERS_PRC_STDDEF_H
+
+/*
+ *  ターゲットを識別するためのマクロの定義
+ */
+#define TOPPERS_RISCV			/* プロセッサ略称 */
+
+#endif /* TOPPERS_PRC_STDDEF_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_support.S
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_support.S	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_support.S	(revision 453)
@@ -0,0 +1,753 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		プロセッサ依存モジュール アセンブリ言語部（RISC-V用）
+ */
+
+#define	TOPPERS_MACRO_ONLY
+#include "encoding.h"
+#define UINT_C(val)			(val)		/* uint_t型の定数を作るマクロ */
+#define ULONG_C(val)		(val)		/* ulong_t型の定数を作るマクロ */
+#define CAST(type, val)		(val)		/* 型キャストを行うマクロ */
+#include "kernel_impl.h"
+#include "offset.h"
+
+#if defined(__riscv64)
+#define LREG                ld
+#define SREG                sd
+#define LFREG               fld
+#define SFREG               fsd
+#define REGSIZE             8
+#else
+#define LREG                lw
+#define SREG                sw
+#define LFREG               flw
+#define SFREG               fsw
+#define REGSIZE             4
+#endif
+
+#if defined(USE_FPU) && !defined(__riscv_float_abi_soft)
+#define SAVEREG1            27
+#define SAVEREG2            42
+#define SAVEREG3            26
+#else
+#define SAVEREG1            15
+#define SAVEREG2            22
+#define SAVEREG3            14
+#endif
+
+/*
+ *  タスクディスパッチャ
+ */
+	.text
+	.globl dispatch
+dispatch:
+	/*
+	 *  このルーチンは，タスクコンテキスト・CPUロック状態・ディスパッチ
+	 *  許可状態・（モデル上の）割込み優先度マスク全解除状態で呼び出さ
+	 *  れる．
+	 */
+	addi sp, sp, -SAVEREG1*REGSIZE	/* レジスタ保存領域を確保 */
+	SREG ra, 0*REGSIZE(sp)			/* returnアドレスを保存 */
+	SREG gp, 1*REGSIZE(sp)			/* call先セーブのレジスタを保存 */
+	SREG tp, 2*REGSIZE(sp)
+	SREG s0, 3*REGSIZE(sp)
+	SREG s1, 4*REGSIZE(sp)
+	SREG s2, 5*REGSIZE(sp)
+	SREG s3, 6*REGSIZE(sp)
+	SREG s4, 7*REGSIZE(sp)
+	SREG s5, 8*REGSIZE(sp)
+	SREG s6, 9*REGSIZE(sp)
+	SREG s7, 10*REGSIZE(sp)
+	SREG s8, 11*REGSIZE(sp)
+	SREG s9, 12*REGSIZE(sp)
+	SREG s10, 13*REGSIZE(sp)
+	SREG s11, 14*REGSIZE(sp)
+#if SAVEREG1 == 27
+	SFREG fs0, 15*REGSIZE(sp)
+	SFREG fs1, 16*REGSIZE(sp)
+	SFREG fs2, 17*REGSIZE(sp)
+	SFREG fs3, 18*REGSIZE(sp)
+	SFREG fs4, 19*REGSIZE(sp)
+	SFREG fs5, 20*REGSIZE(sp)
+	SFREG fs6, 21*REGSIZE(sp)
+	SFREG fs7, 22*REGSIZE(sp)
+	SFREG fs8, 23*REGSIZE(sp)
+	SFREG fs9, 24*REGSIZE(sp)
+	SFREG fs10, 25*REGSIZE(sp)
+	SFREG fs11, 26*REGSIZE(sp)
+#endif
+	la a1, p_runtsk					/* p_runtskをA0に */
+	LREG a0, 0(a1)
+	SREG sp, TCB_sp(a0)				/* タスクスタックを保存 */
+	la a1, dispatch_r
+	SREG a1, TCB_pc(a0)				/* 実行再開番地を保存 */
+	j dispatcher
+
+	.globl dispatch_r
+dispatch_r:
+	LREG ra, 0*REGSIZE(sp)			/* returnアドレスを復帰 */
+	LREG gp, 1*REGSIZE(sp)			/* call先セーブのレジスタを復帰 */
+	LREG tp, 2*REGSIZE(sp)
+	LREG s0, 3*REGSIZE(sp)
+	LREG s1, 4*REGSIZE(sp)
+	LREG s2, 5*REGSIZE(sp)
+	LREG s3, 6*REGSIZE(sp)
+	LREG s4, 7*REGSIZE(sp)
+	LREG s5, 8*REGSIZE(sp)
+	LREG s6, 9*REGSIZE(sp)
+	LREG s7, 10*REGSIZE(sp)
+	LREG s8, 11*REGSIZE(sp)
+	LREG s9, 12*REGSIZE(sp)
+	LREG s10, 13*REGSIZE(sp)
+	LREG s11, 14*REGSIZE(sp)
+#if SAVEREG1 == 27
+	LFREG fs0, 15*REGSIZE(sp)
+	LFREG fs1, 16*REGSIZE(sp)
+	LFREG fs2, 17*REGSIZE(sp)
+	LFREG fs3, 18*REGSIZE(sp)
+	LFREG fs4, 19*REGSIZE(sp)
+	LFREG fs5, 20*REGSIZE(sp)
+	LFREG fs6, 21*REGSIZE(sp)
+	LFREG fs7, 22*REGSIZE(sp)
+	LFREG fs8, 23*REGSIZE(sp)
+	LFREG fs9, 24*REGSIZE(sp)
+	LFREG fs10, 25*REGSIZE(sp)
+	LFREG fs11, 26*REGSIZE(sp)
+#endif
+	addi sp, sp, SAVEREG1*REGSIZE	/* レジスタ保存領域を解放 */
+	li a2, TCB_enatex_bit			/* enatexがfalseならリターン */
+	lbu a1, TCB_enatex(a0)
+	sra a1, a1, a2
+	andi a1, a1, 1
+	beqz a1, dispatch_r_1
+	LREG a1, TCB_texptn(a0)			/* texptnが0ならリターン */
+	beqz a1, dispatch_r_1
+	la a2, ipmflg					/* ipmflgがtrueであれば            */
+	lw a1, 0(a2)
+	bnez a1, call_texrtn			/* タスク例外処理ルーチンの呼出し */
+dispatch_r_1:
+	ret
+
+/*
+ *  ディスパッチャの動作開始（prc_support.S）
+ */
+	.globl start_dispatch
+start_dispatch:
+	/*
+	 *  このルーチンは，カーネル起動時に，すべての割込みを禁止した状態
+	 * （割込みロック状態と同等）で呼び出される．また，割込みモード（非
+	 *  タスクコンテキストと同等）で呼び出されることを想定している．
+	 *
+	 *  prc_initializeで，lock_flagをtrueに，mieはinit_mieに
+	 *  カーネル管理外の割込みを許可済みで，CPUロック状態・（モデル上の）
+	 *  割込み優先度マスク全解除状態になっている．
+	 *  (カーネル管理外の割込みを許可しておかないとmtipがうまく起動しない)
+	 *  また，initialize_taskでdisdspをfalseに初期化しているため，ディ
+	 *  スパッチ許可状態になっている．
+	 */
+	la a0, _kernel_istk				/* STACKをカーネルISTKに */
+	LREG sp, 0(a0)
+	la a0, _kernel_istksz
+	LREG a1, 0(a0)
+	add sp, sp, a1
+	j dispatcher_0
+
+/*
+ *  現在のコンテキストを捨ててディスパッチ
+ */
+	.globl exit_and_dispatch
+exit_and_dispatch:
+	/* ディスパッチャ本体（dispatcher）へ */
+
+/*
+ *  ディスパッチャ本体
+ */
+dispatcher:
+	/*
+	 *  このルーチンは，タスクコンテキスト・CPUロック状態・ディスパッチ
+	 *  許可状態・（モデル上の）割込み優先度マスク全解除状態で呼び出さ
+	 *  れる．
+	 *
+	 *  すなわち，マスタモード・lock_flagがtrue・disdspがfalse・dspflg
+	 *  がtrue・saved_iipmがIIPM_ENAALLとなっている．実行再開番地へもこ
+	 *  の状態のまま分岐する．
+	 */
+#ifdef LOG_DSP_ENTER
+	la a2, p_runtsk					/* p_runtskをパラメータに */
+	LREG a0, 0(a2)
+	jal log_dsp_enter
+#endif /* LOG_DSP_ENTER */
+dispatcher_0:
+	la a1, p_schedtsk				/* p_schedtskをp_runtskに */
+	LREG a0, 0(a1)
+	la a2, p_runtsk
+	SREG a0, 0(a2)
+	beqz a0, dispatcher_1			/* p_runtskがNULLならdispatcher_1へ */
+	LREG sp, TCB_sp(a0)				/* タスクスタックを復帰 */
+#ifdef LOG_DSP_LEAVE
+	jal log_dsp_leave
+	la a2, p_runtsk					/* p_runtskを復帰 */
+	LREG a0, 0(a2)
+#endif /* LOG_DSP_LEAVE */
+	LREG a1, TCB_pc(a0)				/* 実行再開番地へ分岐 */
+	jr a1
+dispatcher_1:
+	/*
+	 *  CPUロック状態を解除する準備をする．
+	 */
+	csrr a5, mie					/* mieをa5に保存 */
+	la a3, lock_flag				/* CPUロック解除状態に */
+	sw zero, 0(a3)
+dispatcher_2:
+	/*
+	 *  割込みを許可し，割込みモードに切り換えて，割込みを待つ．
+	 *
+	 *  ここで割込みモードに切り換えるのは，ここで発生する割込み処理に
+	 *  どのスタックを使うかという問題の解決と，割込みハンドラ内でのタ
+	 *  スクディスパッチの防止という2つの意味がある．
+	 *
+	 *  プロセッサを割込み待ちに移行させる処理と，割込み許可とは，不可
+	 *  分に行なう必要がある（M68040ではstop命令で両方行なうので問題な
+	 *  い）．これを不可分に行なわない場合，割込みを許可した直後に割込
+	 *  みが入り，その中でタスクが実行可能状態になると，実行すべきタス
+	 *  クがあるにもかかわらずプロセッサが割込み待ちになってしまう．
+	 *
+	 *  割込み待ちの間は，p_runtskをNULL（＝0）に設定しなければならな
+	 *  い．このように設定しないと，割込みハンドラからiget_tidを呼び出
+	 *  した際の動作が仕様に合致しなくなる．
+	 */
+	la a1, kernel_mie				/* 割込み待ち */
+	LREG a2, 0(a1)
+	csrs mie, a2
+	wfi
+	csrw mie, a5					/* 元の状態に戻す */
+	la a2, reqflg					/* reqflgがfalseならdispatcher_2へ */
+	lw a1, 0(a2)
+	beqz a1, dispatcher_2
+	sw zero, 0(a2)					/* reqflgをfalseに */
+
+	/*
+	 *  CPUロック状態に戻す．割込み待ちの間に実行した割込みハンドラによ
+	 *  り，saved_iipmが書き換えられる可能性があるため，元の値に戻す必
+	 *  要がある．dispatcherが実行される時は，saved_iipmがIIPM_ENAALL
+	 *  となっているため，ここではsaved_iipmをIIPM_ENAALL（＝0）に戻せ
+	 *  ばよい．
+	 */
+	la a3, lock_flag				/* CPUロック状態に */
+	li a1, true
+	sw a1, 0(a3)
+	j dispatcher_0
+
+/*
+ *  カーネルの終了処理の呼出し
+ *
+ *  RISCVでは，モード切換えによりスタックも切り換わらないため，明示的な
+ *  スタック切換えを行う．最初から割込みモードであった場合も，同じ処理
+ *  でよい．
+ */
+	.globl call_exit_kernel
+call_exit_kernel:
+	la a0, _kernel_istk				/* STACKをカーネルISTKに */
+	LREG sp, 0(a0)
+	la a0, _kernel_istksz
+	LREG a1, 0(a0)
+	add sp, sp, a1
+	j exit_kernel					/* カーネルの終了処理を呼ぶ */
+
+/*
+ *  タスク開始時処理
+ */
+	.text
+	.globl start_r
+start_r:
+	la a1, lock_flag				/* CPUロック解除状態に */
+	sw zero, 0(a1)
+	la ra, ext_tsk					/* ext_tskを戻り番地に設定 */
+	li a2, KERNEL_MIE
+	csrrs a2, mie, a2				/* 割込み許可   */
+	LREG a1, TCB_p_tinib(a0)		/* p_runtsk->p_tinibをa1に */
+	LREG a0, TINIB_exinf(a1)		/* exinfを引数レジスタa0に  */
+	LREG a2, TINIB_task(a1)			/* タスクの起動番地をa2に */
+	jr a2
+
+
+/*
+ *  MACHINE割込み出口処理
+ *
+ *  第一レベルのMACHIE割込みを行う．スタックするレジスタはネスト割込みとほぼ
+ *  同じ，ユーザースタック上に，t3-t6までのレジスタはユーザースタックに
+ *  保存する．(ネスト割込みではシステムスタックに保存)そのため、
+ *  4*RGSIZEバイト分、割込みのためにユーザースタックを消費する．
+ *  例外/割込みが発生すると，システムスタック上に以下の情報とスクラッチ
+ *  レジスタを保存する．
+ *
+ *   ------------
+ *  | mstatus    |
+ *   ------------
+ *  | mpc        |
+ *   ------------
+ *  | mcause     |
+ *   ------------
+ *  | mip        |
+ *   ------------
+ *  | sp(x2)     |
+ *   ------------
+ *  | reserved   |
+ *   ------------
+ *  | a0(x10)    |
+ *   ------------
+ *  | a1(x11)    |
+ *   ------------
+ *  | ra(x1)     |
+ *   ------------
+ *  | a2(x12)    |
+ *   ------------
+ */
+	.text
+	.align 4
+	.global trap_entry
+trap_entry:
+	addi sp, sp, -SAVEREG2*REGSIZE	/* ユーザースタックにワークレジスタの保存領域を作成 */
+	SREG t3, 18*REGSIZE(sp)			/* t3-t6をワークレジスタとして使用する */
+	SREG t4, 19*REGSIZE(sp)
+	SREG t5, 20*REGSIZE(sp)
+	SREG t6, 21*REGSIZE(sp)
+	la t4, _kernel_istk				/* STACKをカーネルISTKに */
+	LREG t5, 0(t4)
+	la t4, _kernel_istksz
+	LREG t6, 0(t4)
+	mv t4, sp						/* ユーザースタックをt4にコピー */
+	add sp, t5, t6					/* システムスタックを設定 */
+
+	addi sp, sp, -SAVEREG2*REGSIZE	/* システムスタック保存領域を作成 */
+	SREG a0, 6*REGSIZE(sp)			/* スクラッチレジスタを保存 */
+	SREG a1, 7*REGSIZE(sp)
+	SREG a2, 8*REGSIZE(sp)
+	SREG ra, 9*REGSIZE(sp)
+	SREG a3, 10*REGSIZE(sp)
+	SREG a4, 11*REGSIZE(sp)
+	SREG a5, 12*REGSIZE(sp)
+	SREG a6, 13*REGSIZE(sp)
+	SREG a7, 14*REGSIZE(sp)
+	SREG t0, 15*REGSIZE(sp)
+	SREG t1, 16*REGSIZE(sp)
+	SREG t2, 17*REGSIZE(sp)
+#if SAVEREG2 == 42
+	SFREG ft0, 22*REGSIZE(sp)
+	SFREG ft1, 23*REGSIZE(sp)
+	SFREG ft2, 24*REGSIZE(sp)
+	SFREG ft3, 25*REGSIZE(sp)
+	SFREG ft4, 26*REGSIZE(sp)
+	SFREG ft5, 27*REGSIZE(sp)
+	SFREG ft6, 28*REGSIZE(sp)
+	SFREG ft7, 29*REGSIZE(sp)
+	SFREG fa0, 30*REGSIZE(sp)
+	SFREG fa1, 31*REGSIZE(sp)
+	SFREG fa2, 32*REGSIZE(sp)
+	SFREG fa3, 33*REGSIZE(sp)
+	SFREG fa4, 34*REGSIZE(sp)
+	SFREG fa5, 35*REGSIZE(sp)
+	SFREG fa6, 36*REGSIZE(sp)
+	SFREG fa7, 37*REGSIZE(sp)
+	SFREG ft8, 38*REGSIZE(sp)
+	SFREG ft9, 39*REGSIZE(sp)
+	SFREG ft10, 40*REGSIZE(sp)
+	SFREG ft11, 41*REGSIZE(sp)
+#endif
+
+	csrr a0, mcause					/* mcauseを2に保存 */
+	SREG a0, 2*REGSIZE(sp)
+	csrr t5, mepc					/* mpcを1に保存 */
+	SREG t5, 1*REGSIZE(sp)
+	csrr t6, mstatus				/* mstatusを0に保存 */
+	SREG t6, 0*REGSIZE(sp)
+	csrr t3, mie					/* mieを3に保存 */
+	SREG t3, 3*REGSIZE(sp)
+	SREG t4, 4*REGSIZE(sp)			/* ユーザースタックを4に保存 */
+	li a2, KERNEL_MIE
+	csrc mie, a2					/* カーネル内割込み禁止   */
+	li a3, (MSTATUS_MPP | MSTATUS_MIE)
+	csrs mstatus, a3				/* カーネル外割込み許可 */
+	mv a1, sp						/* スタックをa1に設定 */
+	call handle_trap				/* MACHINEハンドラを呼び出す */
+
+	LREG a0, 6*REGSIZE(sp)			/* スクラッチレジスタを復帰 */
+	LREG a1, 7*REGSIZE(sp)
+	LREG a2, 8*REGSIZE(sp)
+	LREG ra, 9*REGSIZE(sp)
+	LREG a3, 10*REGSIZE(sp)
+	LREG a4, 11*REGSIZE(sp)
+	LREG a5, 12*REGSIZE(sp)
+	LREG a6, 13*REGSIZE(sp)
+	LREG a7, 14*REGSIZE(sp)
+	LREG t0, 15*REGSIZE(sp)
+	LREG t1, 16*REGSIZE(sp)
+	LREG t2, 17*REGSIZE(sp)
+#if SAVEREG2 == 42
+	LFREG ft0, 22*REGSIZE(sp)
+	LFREG ft1, 23*REGSIZE(sp)
+	LFREG ft2, 24*REGSIZE(sp)
+	LFREG ft3, 25*REGSIZE(sp)
+	LFREG ft4, 26*REGSIZE(sp)
+	LFREG ft5, 27*REGSIZE(sp)
+	LFREG ft6, 28*REGSIZE(sp)
+	LFREG ft7, 29*REGSIZE(sp)
+	LFREG fa0, 30*REGSIZE(sp)
+	LFREG fa1, 31*REGSIZE(sp)
+	LFREG fa2, 32*REGSIZE(sp)
+	LFREG fa3, 33*REGSIZE(sp)
+	LFREG fa4, 34*REGSIZE(sp)
+	LFREG fa5, 35*REGSIZE(sp)
+	LFREG fa6, 36*REGSIZE(sp)
+	LFREG fa7, 37*REGSIZE(sp)
+	LFREG ft8, 38*REGSIZE(sp)
+	LFREG ft9, 39*REGSIZE(sp)
+	LFREG ft10, 40*REGSIZE(sp)
+	LFREG ft11, 41*REGSIZE(sp)
+#endif
+
+	la t5, reqflg					/* reqflgがtrueであればtrap_entery_2へ */
+	lw t6, 0(t5)
+	bnez t6, trap_entry_2
+	la t5, lock_flag				/* CPUロック解除の準備 */
+	sw zero, 0(t5)
+	LREG t5, 1*REGSIZE(sp)			/* mepcの取り出し */
+	LREG t6, 0*REGSIZE(sp)			/* mstatusの取り出し */
+	LREG t4, 3*REGSIZE(sp)			/* mieの取り出し */
+	csrw mepc, t5					/* mepcを復帰 */
+	csrw mstatus, t6				/* mstatusを復帰 */
+	csrw mie, t4					/* mieを復帰 */
+	LREG sp, 4*REGSIZE(sp)			/* ユーザースタックを復帰 */
+
+	LREG t3, 18*REGSIZE(sp)			/* ワーク用スクラッチレジスタを復帰 */
+	LREG t4, 19*REGSIZE(sp)
+	LREG t5, 20*REGSIZE(sp)
+	LREG t6, 21*REGSIZE(sp)
+	addi sp, sp, SAVEREG2*REGSIZE	/* スタックを開放 */
+	mret
+
+trap_entry_2:
+	LREG t5, 1*REGSIZE(sp)			/* mepcの取り出し */
+	LREG t4, 2*REGSIZE(sp)			/* mcauseの取り出し */
+	LREG t3, 3*REGSIZE(sp)			/* mieの取り出し */
+	LREG t6, 0*REGSIZE(sp)			/* mstatusの取り出し */
+	LREG sp, 4*REGSIZE(sp)			/* ユーザースタックを復帰 */
+
+	SREG t6, 0*REGSIZE(sp)			/* mstatusの保存 */
+	SREG t3, 3*REGSIZE(sp)			/* mieの保存 */
+	SREG t4, 2*REGSIZE(sp)			/* mcauseの保存 */
+	SREG t5, 1*REGSIZE(sp)			/* mepcの保存 */
+	SREG a0, 6*REGSIZE(sp)			/* スクラッチレジスタを保存 */
+	SREG a1, 7*REGSIZE(sp)
+	SREG a2, 8*REGSIZE(sp)
+	SREG ra, 9*REGSIZE(sp)
+	SREG a3, 10*REGSIZE(sp)
+	SREG a4, 11*REGSIZE(sp)
+	SREG a5, 12*REGSIZE(sp)
+	SREG a6, 13*REGSIZE(sp)
+	SREG a7, 14*REGSIZE(sp)
+	SREG t0, 15*REGSIZE(sp)
+	SREG t1, 16*REGSIZE(sp)
+	SREG t2, 17*REGSIZE(sp)
+#if SAVEREG2 == 42
+	SFREG ft0, 22*REGSIZE(sp)
+	SFREG ft1, 23*REGSIZE(sp)
+	SFREG ft2, 24*REGSIZE(sp)
+	SFREG ft3, 25*REGSIZE(sp)
+	SFREG ft4, 26*REGSIZE(sp)
+	SFREG ft5, 27*REGSIZE(sp)
+	SFREG ft6, 28*REGSIZE(sp)
+	SFREG ft7, 29*REGSIZE(sp)
+	SFREG fa0, 30*REGSIZE(sp)
+	SFREG fa1, 31*REGSIZE(sp)
+	SFREG fa2, 32*REGSIZE(sp)
+	SFREG fa3, 33*REGSIZE(sp)
+	SFREG fa4, 34*REGSIZE(sp)
+	SFREG fa5, 35*REGSIZE(sp)
+	SFREG fa6, 36*REGSIZE(sp)
+	SFREG fa7, 37*REGSIZE(sp)
+	SFREG ft8, 38*REGSIZE(sp)
+	SFREG ft9, 39*REGSIZE(sp)
+	SFREG ft10, 40*REGSIZE(sp)
+	SFREG ft11, 41*REGSIZE(sp)
+#endif
+
+	la a0, reqflg					/* reqflgをfalseに */
+	sw zero, 0(a0)
+	la a1, lock_flag				/* loc_flagをtrueに */
+	li a2, true
+	sw a2, 0(a1)
+
+	la a1, p_runtsk					/* p_runtskをa0に */
+	LREG a0, 0(a1)
+	la a2, dspflg					/* dspflgがfalseならret_int_1へ */
+	lw a3, 0(a2)
+	beqz a3, ret_int_1
+	la a2, p_schedtsk				/* p_runtskとp_schedtskが同じなら */
+	LREG a3, 0(a2)
+	beq a0, a3, ret_int_1			/* ret_int_1へ */
+
+	addi sp, sp, -SAVEREG3*REGSIZE	/* call先セーブのレジスタを保存 */
+	SREG gp, 0*REGSIZE(sp)
+	SREG tp, 1*REGSIZE(sp)
+	SREG s0, 2*REGSIZE(sp)
+	SREG s1, 3*REGSIZE(sp)
+	SREG s2, 4*REGSIZE(sp)
+	SREG s3, 5*REGSIZE(sp)
+	SREG s4, 6*REGSIZE(sp)
+	SREG s5, 7*REGSIZE(sp)
+	SREG s6, 8*REGSIZE(sp)
+	SREG s7, 9*REGSIZE(sp)
+	SREG s8, 10*REGSIZE(sp)
+	SREG s9, 11*REGSIZE(sp)
+	SREG s10, 12*REGSIZE(sp)
+	SREG s11, 13*REGSIZE(sp)
+#if SAVEREG3 == 26
+	SFREG fs0, 14*REGSIZE(sp)
+	SFREG fs1, 15*REGSIZE(sp)
+	SFREG fs2, 16*REGSIZE(sp)
+	SFREG fs3, 17*REGSIZE(sp)
+	SFREG fs4, 18*REGSIZE(sp)
+	SFREG fs5, 19*REGSIZE(sp)
+	SFREG fs6, 20*REGSIZE(sp)
+	SFREG fs7, 21*REGSIZE(sp)
+	SFREG fs8, 22*REGSIZE(sp)
+	SFREG fs9, 23*REGSIZE(sp)
+	SFREG fs10, 24*REGSIZE(sp)
+	SFREG fs11, 25*REGSIZE(sp)
+#endif
+	SREG sp, TCB_sp(a0)				/* タスクスタックを保存 */
+	la a1, ret_int_r				/* 実行再開番地を保存 */
+	SREG a1, TCB_pc(a0)
+	j dispatcher
+
+ret_int_r:
+	LREG gp, 0*REGSIZE(sp)			/* call先セーブのレジスタを復帰 */
+	LREG tp, 1*REGSIZE(sp)
+	LREG s0, 2*REGSIZE(sp)
+	LREG s1, 3*REGSIZE(sp)
+	LREG s2, 4*REGSIZE(sp)
+	LREG s3, 5*REGSIZE(sp)
+	LREG s4, 6*REGSIZE(sp)
+	LREG s5, 7*REGSIZE(sp)
+	LREG s6, 8*REGSIZE(sp)
+	LREG s7, 9*REGSIZE(sp)
+	LREG s8, 10*REGSIZE(sp)
+	LREG s9, 11*REGSIZE(sp)
+	LREG s10, 12*REGSIZE(sp)
+	LREG s11, 13*REGSIZE(sp)
+#if SAVEREG3 == 26
+	LFREG fs0, 14*REGSIZE(sp)
+	LFREG fs1, 15*REGSIZE(sp)
+	LFREG fs2, 16*REGSIZE(sp)
+	LFREG fs3, 17*REGSIZE(sp)
+	LFREG fs4, 18*REGSIZE(sp)
+	LFREG fs5, 19*REGSIZE(sp)
+	LFREG fs6, 20*REGSIZE(sp)
+	LFREG fs7, 21*REGSIZE(sp)
+	LFREG fs8, 22*REGSIZE(sp)
+	LFREG fs9, 23*REGSIZE(sp)
+	LFREG fs10, 24*REGSIZE(sp)
+	LFREG fs11, 25*REGSIZE(sp)
+#endif
+	addi sp, sp, SAVEREG3*REGSIZE
+ret_int_1:
+	/*
+	 *  enatexがtrueで，texptnが0でなく，ipmflgがtrueであれば，タスク
+	 *  例外処理ルーチンを呼び出す．
+	 */
+	li a2, TCB_enatex_bit			/* enatexがfalseならret_int_2へ */
+	lbu a1, TCB_enatex(a0)
+	sra a1, a1, a2
+	andi a1, a1, 1
+	beqz a1, ret_int_2
+	lw a1, TCB_texptn(a0)			/* texptnが0ならばret_int_2へ */
+	beqz a1, ret_int_2
+	la a2, ipmflg					/* ipmflgがfalseならret_int_2へ */
+	lw a1, 0(a2)
+	beqz a1, ret_int_2
+	jal call_texrtn
+ret_int_2:
+	/*
+	 *  割込み処理からのリターンにより，CPUロック解除状態に移行するよ
+	 *  う準備する．割込み優先度マスクは，MRET命令により元の値に戻るた
+	 *  め，lock_flagをfalseにしておけばよい．
+	 */
+	la a0, lock_flag				/* CPUロック解除の準備 */
+	sw zero, 0(a0)
+
+ret_int_3:
+	LREG a1, 3*REGSIZE(sp)			/* mieの取り出し */
+	LREG a2, 1*REGSIZE(sp)			/* mpcの取り出し */
+	LREG a3, 0*REGSIZE(sp)			/* mstatusの取り出し */
+	csrw mepc, a2					/* mpcの復帰 */
+	csrw mstatus, a3				/* mstatusの復帰 */
+	csrw mie, a1					/* mieの復帰 */
+
+	LREG a0, 6*REGSIZE(sp)			/* スクラッチレジスタの復帰 */
+	LREG a1, 7*REGSIZE(sp)
+	LREG a2, 8*REGSIZE(sp)
+	LREG ra, 9*REGSIZE(sp)
+	LREG a3, 10*REGSIZE(sp)
+	LREG a4, 11*REGSIZE(sp)
+	LREG a5, 12*REGSIZE(sp)
+	LREG a6, 13*REGSIZE(sp)
+	LREG a7, 14*REGSIZE(sp)
+	LREG t0, 15*REGSIZE(sp)
+	LREG t1, 16*REGSIZE(sp)
+	LREG t2, 17*REGSIZE(sp)
+	LREG t3, 18*REGSIZE(sp)
+	LREG t4, 19*REGSIZE(sp)
+	LREG t5, 20*REGSIZE(sp)
+	LREG t6, 21*REGSIZE(sp)
+#if SAVEREG2 == 42
+	LFREG ft0, 22*REGSIZE(sp)
+	LFREG ft1, 23*REGSIZE(sp)
+	LFREG ft2, 24*REGSIZE(sp)
+	LFREG ft3, 25*REGSIZE(sp)
+	LFREG ft4, 26*REGSIZE(sp)
+	LFREG ft5, 27*REGSIZE(sp)
+	LFREG ft6, 28*REGSIZE(sp)
+	LFREG ft7, 29*REGSIZE(sp)
+	LFREG fa0, 30*REGSIZE(sp)
+	LFREG fa1, 31*REGSIZE(sp)
+	LFREG fa2, 32*REGSIZE(sp)
+	LFREG fa3, 33*REGSIZE(sp)
+	LFREG fa4, 34*REGSIZE(sp)
+	LFREG fa5, 35*REGSIZE(sp)
+	LFREG fa6, 36*REGSIZE(sp)
+	LFREG fa7, 37*REGSIZE(sp)
+	LFREG ft8, 38*REGSIZE(sp)
+	LFREG ft9, 39*REGSIZE(sp)
+	LFREG ft10, 40*REGSIZE(sp)
+	LFREG ft11, 41*REGSIZE(sp)
+#endif
+	addi sp, sp, SAVEREG2*REGSIZE
+	mret
+
+/*
+ *  MACHINEネスト割込み出入口処理
+ *
+ *  trap_nestは，ネストしたMACHINE割込みの出入口処理を行う．
+ *  mtvecの設定は呼び出したhandle_trapで行う．
+ *  handle_trapからのリターンはネスト状態に限定されるため
+ *  この出入り口では、スタックの変更も行わない．
+ */
+	.text
+	.align 4
+	.global trap_nest
+trap_nest:
+	addi sp, sp, -SAVEREG2*REGSIZE	/* システムスタック保存領域を作成 */
+	SREG a0, 6*REGSIZE(sp)			/* スクラッチレジスタを保存 */
+	SREG a1, 7*REGSIZE(sp)
+	SREG a2, 8*REGSIZE(sp)
+	SREG ra, 9*REGSIZE(sp)
+	SREG a3, 10*REGSIZE(sp)
+	SREG a4, 11*REGSIZE(sp)
+	SREG a5, 12*REGSIZE(sp)
+	SREG a6, 13*REGSIZE(sp)
+	SREG a7, 14*REGSIZE(sp)
+	SREG t0, 15*REGSIZE(sp)
+	SREG t1, 16*REGSIZE(sp)
+	SREG t2, 17*REGSIZE(sp)
+	SREG t3, 18*REGSIZE(sp)
+	SREG t4, 19*REGSIZE(sp)
+	SREG t5, 20*REGSIZE(sp)
+	SREG t6, 21*REGSIZE(sp)
+#if SAVEREG2 == 42
+	SFREG ft0, 22*REGSIZE(sp)
+	SFREG ft1, 23*REGSIZE(sp)
+	SFREG ft2, 24*REGSIZE(sp)
+	SFREG ft3, 25*REGSIZE(sp)
+	SFREG ft4, 26*REGSIZE(sp)
+	SFREG ft5, 27*REGSIZE(sp)
+	SFREG ft6, 28*REGSIZE(sp)
+	SFREG ft7, 29*REGSIZE(sp)
+	SFREG fa0, 30*REGSIZE(sp)
+	SFREG fa1, 31*REGSIZE(sp)
+	SFREG fa2, 32*REGSIZE(sp)
+	SFREG fa3, 33*REGSIZE(sp)
+	SFREG fa4, 34*REGSIZE(sp)
+	SFREG fa5, 35*REGSIZE(sp)
+	SFREG fa6, 36*REGSIZE(sp)
+	SFREG fa7, 37*REGSIZE(sp)
+	SFREG ft8, 38*REGSIZE(sp)
+	SFREG ft9, 39*REGSIZE(sp)
+	SFREG ft10, 40*REGSIZE(sp)
+	SFREG ft11, 41*REGSIZE(sp)
+#endif
+
+	csrr a3, mstatus			    /* mstatusを0に保存 */
+	SREG a3, 0*REGSIZE(sp)
+	csrr a1, mie					/* mieを3に保存 */
+	SREG a1, 3*REGSIZE(sp)
+	addi a2, sp, 22*REGSIZE			/* システムスタックを4に保存 */
+	SREG a2, 4*REGSIZE(sp)
+	csrr a0, mcause					/* mcauseをa0に取り出し */
+	SREG a0, 2*REGSIZE(sp)			/* mcauseを2に保存 */
+	csrr a3, mepc					/* mpcを1に保存 */
+	SREG a3, 1*REGSIZE(sp)
+	li a2, KERNEL_MIE
+	csrc mie, a2					/* カーネル内割込み禁止   */
+	li a3, (MSTATUS_MPP | MSTATUS_MIE)
+	csrs mstatus, a3				/* カーネル外割込み許可 */
+	mv a1, sp						/* スタックをa1に設定 */
+	la ra, ret_int_3				/* リターンアドレスをセット */
+	j handle_trap					/* MACHINEハンドラを呼び出す */
+
+/*
+ *  微少時間待ち（本来はSILのターゲット依存部）
+ */
+	.globl sil_dly_nse
+	.align 4
+sil_dly_nse:
+	addi  a0, a0, (-SIL_DLY_TIM1)	/* a0からSIL_DLY_TIM1を引く */
+	blez  a0, _sil_dly_nse_2		/* 結果が0以下ならリターン */
+_sil_dly_nse_1:
+	addi  a0, a0, (-SIL_DLY_TIM2)	/* a0からSIL_DLY_TIM2を引く */
+	bgtz  a0, _sil_dly_nse_1		/* 結果が0より大きければループ */
+_sil_dly_nse_2:
+	ret
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_test.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_test.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_test.h	(revision 453)
@@ -0,0 +1,52 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2006,2007 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		テストプログラムのターゲット依存定義（RISC-V用）
+ */
+
+#ifndef TOPPERS_PRC_TEST_H
+#define TOPPERS_PRC_TEST_H
+
+#define CPUEXC1					3		/* ゼロ除算例外(BREAKPOINT) */
+#define RAISE_CPU_EXCEPTION		syslog(LOG_NOTICE, "zerodiv = %d", 10 / 0)
+
+#endif /* TOPPERS_PRC_TEST_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_timer.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_timer.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_timer.c	(revision 453)
@@ -0,0 +1,128 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2005,2006 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		タイマドライバ（RISC-V用）
+ */
+
+#include "kernel_impl.h"
+#include "time_event.h"
+#include <sil.h>
+#include "target_timer.h"
+
+
+static int32_t  molecule;
+
+/*
+ *  最初の割込みのタイマー値は不定のため
+ *  割込み発生時のタイマー値をベースにマッチ時間を設定する．
+ */
+static void
+pre_timer_handler(void)
+{
+	CLOCK mtimecmp = target_current_timer_value() + TO_CLOCK(TIC_NUME, TIC_DENO);
+
+	target_set_target_timer_value(mtimecmp);
+	x_machine_inh(IRQ_M_TIMER, (FP)prc_timer_handler);
+}
+
+/*
+ *  タイマの起動処理
+ */
+void
+prc_timer_initialize(intptr_t exinf)
+{
+	CLOCK	mtimecmp;
+
+	/*
+	 *  タイマ周期を設定し，タイマの動作を開始する．
+	 */
+	mtimecmp = target_current_timer_value() + TO_CLOCK(TIC_NUME, TIC_DENO);
+	target_set_target_timer_value(mtimecmp);
+	molecule = REMAINDER(TIC_NUME, TIC_DENO);
+
+	/*
+	 *  タイマ割込み要求をクリアする．
+	 */
+	x_machine_inh(IRQ_M_TIMER, (FP)pre_timer_handler);
+}
+
+/*
+ *  タイマの停止処理
+ */
+void
+prc_timer_terminate(intptr_t exinf)
+{
+	/*
+	 *  タイマの動作を停止する．
+	 */
+	clear_csr(mie, MIP_MTIP);
+}
+
+/*
+ *  タイマ割込みハンドラ
+ */
+void
+prc_timer_handler(void)
+{
+	uint8_t  threshold = (uint8_t)current_ithreshold();
+	CLOCK	mtimecmp;
+	int32_t	difference;
+
+	kernel_mie &= ~MIP_MTIP;
+	mtimecmp = target_get_target_timer_value();
+	do{
+		mtimecmp += TO_CLOCK(TIC_NUME, TIC_DENO);
+		if(molecule >= DENOMINATOR(TIC_NUME, TIC_DENO)){
+			mtimecmp++;
+			molecule -= DENOMINATOR(TIC_NUME, TIC_DENO);
+		}
+		molecule += REMAINDER(TIC_NUME, TIC_DENO);
+		difference = mtimecmp - target_current_timer_value();
+	}while(difference <= 0);
+	target_set_target_timer_value(mtimecmp);
+	set_ithreshold((uint32_t)INT_IPM(INTPRI_TIMER));
+	set_csr(mie, kernel_mie);
+	signal_time();					/* タイムティックの供給 */
+	clear_csr(mie, KERNEL_MIE);
+	set_ithreshold((uint32_t)threshold);
+	kernel_mie |= MIP_MTIP;
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_timer.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_timer.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_timer.cfg	(revision 453)
@@ -0,0 +1,11 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *		タイマドライバのコンフィギュレーションファイル
+ */
+
+#include "prc_timer.h"
+ATT_INI({ TA_NULL, 0, prc_timer_initialize });
+ATT_TER({ TA_NULL, 0, prc_timer_terminate });
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_timer.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_timer.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_timer.h	(revision 453)
@@ -0,0 +1,104 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2008 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		タイマドライバ（RISC-V用）
+ */
+
+#ifndef TOPPERS_PRC_TIMER_H
+#define TOPPERS_PRC_TIMER_H
+
+#include "target_syssvc.h"
+
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  タイマ値の内部表現の型
+ */
+typedef uint64_t	CLOCK;
+
+/*
+ *  タイマ値の内部表現とミリ秒・μ秒単位との変換
+ */
+#define DENOMINATOR(nume, deno) (1000 * (nume) / (deno))
+#define REMAINDER(nume, deno)   (((CLINT_FREQ * (nume)) / (deno)) % DENOMINATOR((nume), (deno)))
+#define TIMER_CLOCK				(CLINT_FREQ)
+#define TO_CLOCK(nume, deno)	((CLOCK)((TIMER_CLOCK * (nume) / (deno)) / 1000u))
+#define TO_USEC(clock)			(((SYSUTM) clock) * 1000U / TIMER_CLOCK)
+
+/*
+ *  設定できる最大のタイマ周期（単位は内部表現）
+ */
+#define MAX_CLOCK		((CLOCK) 0xffffffffffffffffU)
+
+/*
+ *  タイマの起動処理
+ *
+ *  タイマを初期化し，周期的なタイマ割込み要求を発生させる．
+ */
+extern void	prc_timer_initialize(intptr_t exinf);
+
+/*
+ *  タイマの停止処理
+ *
+ *  タイマの動作を停止させる．
+ */
+extern void	prc_timer_terminate(intptr_t exinf);
+
+/*
+ *  タイマ割込み要求のチェック
+ */
+Inline bool_t
+prc_timer_probe_int(void)
+{
+	return (read_csr(mip) & MIP_MTIP) != 0;
+}
+
+/*
+ *  タイマ割込みハンドラ
+ */
+extern void	prc_timer_handler(void);
+
+#endif /* TOPPERS_MACRO_ONLY */
+#endif /* TOPPERS_PRC_TIMER_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_unrename.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_unrename.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_unrename.h	(revision 453)
@@ -0,0 +1,56 @@
+/* This file is generated from prc_rename.def by genrename. */
+
+/* This file is included only when prc_rename.h has been included. */
+#ifdef TOPPERS_PRC_RENAME_H
+#undef TOPPERS_PRC_RENAME_H
+
+/*
+ *  prc_config.c
+ */
+#undef prc_initialize
+#undef prc_terminate
+#undef handle_trap
+#undef m_interrupt_handlers
+#undef lock_flag
+#undef inest_lvl
+#undef kernel_mie
+
+/*
+ *  prc_support.S
+ */
+#undef dispatch
+#undef start_dispatch
+#undef exit_and_dispatch
+#undef call_exit_kernel
+#undef start_r
+#undef trap_entry
+#undef trap_nest
+
+#ifdef TOPPERS_LABEL_ASM
+
+/*
+ *  prc_config.c
+ */
+#undef _prc_initialize
+#undef _prc_terminate
+#undef _handle_trap
+#undef _m_interrupt_handlers
+#undef _lock_flag
+#undef _inest_lvl
+#undef _kernel_mie
+
+/*
+ *  prc_support.S
+ */
+#undef _dispatch
+#undef _start_dispatch
+#undef _exit_and_dispatch
+#undef _call_exit_kernel
+#undef _start_r
+#undef _trap_entry
+#undef _trap_nest
+
+#endif /* TOPPERS_LABEL_ASM */
+
+
+#endif /* TOPPERS_PRC_RENAME_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/riscv32elf.ld
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/riscv32elf.ld	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/riscv32elf.ld	(revision 453)
@@ -0,0 +1,110 @@
+/*
+ *  @(#) $Id$
+ */
+
+MEMORY
+{
+  /*
+   * Memory with CPU cache.
+   *6M CPU SRAM
+   */
+  ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = (6 * 1024 * 1024)
+  /*
+   * Memory without CPU cache
+   * 6M CPU SRAM
+  */
+  ram_nocache (wxa!ri) : ORIGIN = 0x40000000, LENGTH = (6 * 1024 * 1024)
+}
+
+OUTPUT_ARCH(riscv)
+
+PROVIDE(hardware_init_hook = 0);
+PROVIDE(software_init_hook = 0);
+PROVIDE(software_term_hook = 0);
+PROVIDE(__idata_start = 0);
+PROVIDE(__idata_end = 0);
+STARTUP(start.o)
+
+SECTIONS
+{
+    __stack_size = DEFINED(__stack_size) ? __stack_size : 2K;
+
+    .init :
+    {
+        KEEP (*(.init))
+    }>ram
+    .text :
+    {
+        __text = . ;
+        *(.text .stub .text.* .gnu.linkonce.t.*)
+
+    }>ram
+    .fini :
+    {
+        KEEP (*(.fini))
+    }>ram
+    _etext = . ;
+    PROVIDE (etext = .) ;
+    .rodata :
+    {
+        *(.rodata .rodata.* .gnu.linkonce.r.*)
+    }>ram
+    . = ALIGN(4) ;
+    .data : 
+    {
+        __data_start = . ;
+        /* Writable data segment (.data segment) */
+        *(.data .data.*)
+        *(.sdata .sdata.* .sdata2 .sdata2.*)
+        . = ALIGN(8);
+        PROVIDE( __global_pointer$ = ABSOLUTE(.) + 0x800);
+    }>ram
+    .eh_frame : { KEEP (*(.eh_frame)) }>ram
+    .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) }>ram
+    .ctors :
+    {
+        KEEP (*crtbegin.o(.ctors))
+        KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
+        KEEP (*(SORT(.ctors.*)))
+        KEEP (*(.ctors))
+    }>ram
+    .dtors :
+    {
+        KEEP (*crtbegin.o(.dtors))
+        KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
+        KEEP (*(SORT(.dtors.*)))
+        KEEP (*(.dtors))
+    }>ram
+    _edata  = . ;
+    PROVIDE (edata = .) ;
+    . = ALIGN(4) ;
+    __bss_start = . ;
+    _bss = .;
+    .bss :
+    {
+        *(.bss .bss.*)
+        *(.sbss .sbss.* .sbss2 .sbss2.*)
+        *(COMMON)
+    }>ram
+    _end = . ;
+    __bss_end = . ;
+    _ebss = . ;
+    .stack (NOLOAD) :
+    {
+    	*(.stack)
+    }>ram
+    .heap (NOLOAD) :
+    {
+        PROVIDE (_heap_start = .) ;
+        *(.heap)
+    }>ram
+    PROVIDE (_heap_end = .) ;
+    PROVIDE (end = .) ;
+    .comment        0 : { *(.comment) }
+    .debug          0 : { *(.debug) }
+    .line           0 : { *(.line) }
+    .debug_srcinfo  0 : { *(.debug_srcinfo) }
+    .debug_sfnames  0 : { *(.debug_sfnames) }
+    .debug_aranges  0 : { *(.debug_aranges) }
+    .debug_pubnames 0 : { *(.debug_pubnames) }
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/riscv64elf.ld
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/riscv64elf.ld	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/riscv64elf.ld	(revision 453)
@@ -0,0 +1,110 @@
+/*
+ *  @(#) $Id$
+ */
+
+MEMORY
+{
+  /*
+   * Memory with CPU cache.
+   *6M CPU SRAM
+   */
+  ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = (6 * 1024 * 1024)
+  /*
+   * Memory without CPU cache
+   * 6M CPU SRAM
+  */
+  ram_nocache (wxa!ri) : ORIGIN = 0x40000000, LENGTH = (6 * 1024 * 1024)
+}
+
+OUTPUT_ARCH(riscv)
+
+PROVIDE(hardware_init_hook = 0);
+PROVIDE(software_init_hook = 0);
+PROVIDE(software_term_hook = 0);
+PROVIDE(__idata_start = 0);
+PROVIDE(__idata_end = 0);
+STARTUP(start.o)
+
+SECTIONS
+{
+    __stack_size = DEFINED(__stack_size) ? __stack_size : 8K;
+
+    .init :
+    {
+        KEEP (*(.init))
+    }>ram
+    .text :
+    {
+        __text = . ;
+        *(.text .stub .text.* .gnu.linkonce.t.*)
+
+    }>ram
+    .fini :
+    {
+        KEEP (*(.fini))
+    }>ram
+    _etext = . ;
+    PROVIDE (etext = .) ;
+    .rodata :
+    {
+        *(.rodata .rodata.* .gnu.linkonce.r.*)
+    }>ram
+    . = ALIGN(8);
+    .data : 
+    {
+        __data_start = . ;
+        /* Writable data segment (.data segment) */
+        *(.data .data.*)
+        *(.sdata .sdata.* .sdata2 .sdata2.*)
+        . = ALIGN(8);
+        PROVIDE( __global_pointer$ = ABSOLUTE(.) + 0x800);
+    }>ram
+    .eh_frame : { KEEP (*(.eh_frame)) }>ram
+    .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) }>ram
+    .ctors :
+    {
+        KEEP (*crtbegin.o(.ctors))
+        KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
+        KEEP (*(SORT(.ctors.*)))
+        KEEP (*(.ctors))
+    }>ram
+    .dtors :
+    {
+        KEEP (*crtbegin.o(.dtors))
+        KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
+        KEEP (*(SORT(.dtors.*)))
+        KEEP (*(.dtors))
+    }>ram
+    _edata  = . ;
+    PROVIDE (edata = .) ;
+    . = ALIGN(8) ;
+    __bss_start = . ;
+    _bss = .;
+    .bss :
+    {
+        *(.bss .bss.*)
+        *(.sbss .sbss.* .sbss2 .sbss2.*)
+        *(COMMON)
+    }>ram
+    _end = . ;
+    __bss_end = . ;
+    _ebss = . ;
+    .stack (NOLOAD) :
+    {
+    	*(.stack)
+    }>ram
+    .heap (NOLOAD) :
+    {
+        PROVIDE (_heap_start = .) ;
+        *(.heap)
+    }>ram
+    PROVIDE (_heap_end = .) ;
+    PROVIDE (end = .) ;
+    .comment        0 : { *(.comment) }
+    .debug          0 : { *(.debug) }
+    .line           0 : { *(.line) }
+    .debug_srcinfo  0 : { *(.debug_srcinfo) }
+    .debug_sfnames  0 : { *(.debug_sfnames) }
+    .debug_aranges  0 : { *(.debug_aranges) }
+    .debug_pubnames 0 : { *(.debug_pubnames) }
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/start.S
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/start.S	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/start.S	(revision 453)
@@ -0,0 +1,128 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005,2006 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2018-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *  カーネル対応のスタートアップモジュール（RISC-V用）
+ */
+
+#define TOPPERS_MACRO_ONLY
+#include "encoding.h"
+
+#if defined(__riscv64)
+#define LREG                ld
+#else
+#define LREG                lw
+#endif
+
+	.text
+	.globl start
+start:
+	.cfi_startproc
+	.cfi_undefined ra
+    .option push
+    .option norelax
+    la gp, __global_pointer$
+    .option pop
+
+    csrw mideleg, 0
+    csrw medeleg, 0
+    csrw mie, 0
+    csrw mip, 0
+    csrr a0, mhartid
+	la a1, _kernel_istksz
+    LREG a2, 0(a1)
+    sll sp, a2, a0
+	la a1, _kernel_istk
+	LREG a2, 0(a1)
+    add sp, sp, a2
+	bnez a0, start_5
+
+	/*
+	 *  bssセクションのクリア
+	 */
+start_1:
+	la a0, __bss_start
+	la a1, _end
+	bgeu a0, a1, start_3
+start_2:
+	sw zero, (a0)
+	addi a0, a0, 4
+	bltu a0, a1, start_2
+
+	/*
+	 *  dataセクションの初期化（ROM化対応）
+	 *
+	 *  __idata_startから__idata_endまでを，__data_start以降にコピーす
+	 *  る．
+	 */
+start_3:
+	la a0, __idata_start
+	la a1, __data_start
+	la a2, __idata_end
+	bgeu a0, a2, start_5
+
+start_4:
+	lw t0, (a0)
+	sw t0, (a1)
+	addi a0, a0, 4
+	addi a1, a1, 4
+	bltu a0, a2, start_4
+
+start_5:
+#ifndef __riscv_float_abi_soft
+	/* Enable FPU */
+	li t0, MSTATUS_FS
+	csrs mstatus, t0
+	csrr t1, mstatus
+	and t1, t1, t0
+	beqz t1, start_6
+	fssr x0
+
+start_6:
+#endif
+
+	/*
+	 *  カーネルを起動する．
+	 */
+	j   sta_ker
+	.cfi_endproc
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/cfg/MANIFEST
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/cfg/MANIFEST	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/cfg/MANIFEST	(revision 453)
@@ -0,0 +1,8 @@
+MANIFEST
+cfg.rb
+pass1.rb
+pass2.rb
+GenFile.rb
+SRecord.rb
+
+doc/cfg_user.txt
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/configure
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/configure	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/configure	(revision 453)
@@ -0,0 +1,295 @@
+#! /usr/bin/perl
+#
+#  TOPPERS Software
+#      Toyohashi Open Platform for Embedded Real-Time Systems
+# 
+#  Copyright (C) 2001-2003 by Embedded and Real-Time Systems Laboratory
+#                              Toyohashi Univ. of Technology, JAPAN
+#  Copyright (C) 2006-2012 by Embedded and Real-Time Systems Laboratory
+#              Graduate School of Information Science, Nagoya Univ., JAPAN
+# 
+#  ä¸è¨èä½æ¨©è
+ã¯ï¼ä»¥ä¸ã®(1)ï½(4)ã®æ¡ä»¶ãæºããå ´åã«éãï¼æ¬ã½ããã¦ã§
+#  ã¢ï¼æ¬ã½ããã¦ã§ã¢ãæ¹å¤ãããã®ãå«ãï¼ä»¥ä¸åãï¼ãä½¿ç¨ã»è¤è£½ã»æ¹
+#  å¤ã»åé
+å¸ï¼ä»¥ä¸ï¼å©ç¨ã¨å¼ã¶ï¼ãããã¨ãç¡åã§è¨±è«¾ããï¼
+#  (1) æ¬ã½ããã¦ã§ã¢ãã½ã¼ã¹ã³ã¼ãã®å½¢ã§å©ç¨ããå ´åã«ã¯ï¼ä¸è¨ã®èä½
+#      æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãï¼ãã®ã¾ã¾ã®å½¢ã§ã½ã¼
+#      ã¹ã³ã¼ãä¸­ã«å«ã¾ãã¦ãããã¨ï¼
+#  (2) æ¬ã½ããã¦ã§ã¢ãï¼ã©ã¤ãã©ãªå½¢å¼ãªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨
+#      è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®èä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨
+#      ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#  (3) æ¬ã½ããã¦ã§ã¢ãï¼æ©å¨ã«çµã¿è¾¼ããªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããªãå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼æ¬¡ã®ããããã®æ¡ä»¶ãæºããã
+#      ã¨ï¼
+#    (a) åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®è
+#        ä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#    (b) åé
+å¸ã®å½¢æ
+ãï¼å¥ã«å®ããæ¹æ³ã«ãã£ã¦ï¼TOPPERSãã­ã¸ã§ã¯ãã«
+#        å ±åãããã¨ï¼
+#  (4) æ¬ã½ããã¦ã§ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæ
+#      å®³ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ããå
+è²¬ãããã¨ï¼
+#      ã¾ãï¼æ¬ã½ããã¦ã§ã¢ã®ã¦ã¼ã¶ã¾ãã¯ã¨ã³ãã¦ã¼ã¶ããã®ãããªãç
+#      ç±ã«åºã¥ãè«æ±ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ãã
+#      å
+è²¬ãããã¨ï¼
+# 
+#  æ¬ã½ããã¦ã§ã¢ã¯ï¼ç¡ä¿è¨¼ã§æä¾ããã¦ãããã®ã§ããï¼ä¸è¨èä½æ¨©è
+ã
+#  ãã³TOPPERSãã­ã¸ã§ã¯ãã¯ï¼æ¬ã½ããã¦ã§ã¢ã«é¢ãã¦ï¼ç¹å®ã®ä½¿ç¨ç®ç
+#  ã«å¯¾ããé©åæ§ãå«ãã¦ï¼ãããªãä¿è¨¼ãè¡ããªãï¼ã¾ãï¼æ¬ã½ããã¦ã§
+#  ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæå®³ã«é¢ãã¦ãï¼ã
+#  ã®è²¬ä»»ãè² ããªãï¼
+# 
+#  @(#) $Id$
+# 
+
+use Getopt::Std;
+
+#  ãªãã·ã§ã³ã®å®ç¾©
+#
+#  -T <target>			ã¿ã¼ã²ããåï¼å¿
+é ï¼
+#  -A <applname>		ã¢ããªã±ã¼ã·ã§ã³ãã­ã°ã©ã åï¼ããã©ã«ãã¯sample1ï¼
+#  -a <appldir>			ã¢ããªã±ã¼ã·ã§ã³ã®ãã£ã¬ã¯ããªå
+#  -U <applobjs>		ä»ã®ã¢ããªã±ã¼ã·ã§ã³ãã­ã°ã©ã ãã¡ã¤ã«
+#						ï¼.oãã¡ã¤ã«åã§æå®ï¼è¤æ°æå®å¯ï¼
+#  -S <syssvcobjs>		ã·ã¹ãã ãµã¼ãã¹ã®ãã­ã°ã©ã ãã¡ã¤ã«
+#						ï¼.oãã¡ã¤ã«åã§æå®ï¼è¤æ°æå®å¯ï¼
+#  -L <kernel_lib>		ã«ã¼ãã«ã©ã¤ãã©ãªï¼libkernel.aï¼ã®ãã£ã¬ã¯ããªå
+#						ï¼çç¥ããå ´åï¼ã«ã¼ãã«ã©ã¤ãã©ãªãmakeããï¼
+#  -f					ã«ã¼ãã«ãé¢æ°åä½ã§ã³ã³ãã¤ã«ãããã©ããã®æå®
+#  -D <srcdir>			ã«ã¼ãã«ç­ã®ã½ã¼ã¹ã®ç½®ããã¦ãããã£ã¬ã¯ããª
+#  -l <srclang>			ãã­ã°ã©ãã³ã°è¨èªï¼ç¾æç¹ã§ã¯cã¨c++ã®ã¿ãµãã¼ãï¼
+#  -t <templatedir>		ãã³ãã¬ã¼ããã£ã¬ã¯ããªã®æå®ï¼ããã©ã«ãã¯sampleï¼
+#  -m <makefile>		ãã³ãã¬ã¼ãMakefileåã®æå®ï¼ããã©ã«ãã¯Makefileï¼
+#  -d <dbgenv>			å®è¡ç°å¢ã®åç§°
+#  -r					ãã¬ã¼ã¹ã­ã°è¨é²ã®ãµã³ãã«ã³ã¼ããä½¿ç¨ãããã©ãã
+#						ã®æå®
+#  -p <perl>			perlã®ãã¹åï¼æç¤ºçã«æå®ããå ´åï¼
+#  -g <cfg>				ã³ã³ãã£ã®ã¥ã¬ã¼ã¿ï¼cfgï¼ã®ãã¹å
+#  -P <num>				ãã­ã»ããµæ°ï¼ãã«ããã­ã»ããµå¯¾å¿ã«ã¼ãã«ã®å ´åï¼
+#  -o <options>			å
+±éã³ã³ãã¤ã«ãªãã·ã§ã³ï¼COPTSã«è¿½å ï¼
+#  -O <options>			å
+±éã·ã³ãã«å®ç¾©ãªãã·ã§ã³ï¼CDEFSã«è¿½å ï¼
+#  -k <options>			å
+±éãªã³ã«ãªãã·ã§ã³ï¼LDFLAGSç­ã«è¿½å ï¼
+
+#  ä½¿ç¨ä¾(1)
+#
+#  % ../configure -T dve68k_gcc -D GDB_STUB -A perf1 -a ../test -U histogram.o
+#
+#  ä½¿ç¨ä¾(2)
+#
+#  % ../configure -T macosx_gcc -L .
+#	ã¢ããªã±ã¼ã·ã§ã³ãã­ã°ã©ã ã¯ sample1 ã«ãªãï¼
+
+#
+#  ãªãã·ã§ã³ã®å¦ç
+#
+getopt("TAaUSLDltmdpgPoOk");
+
+#
+#  å¤æ°ã®åæå
+#
+
+$target = $opt_T;
+$applname = $opt_A ? $opt_A : "sample1";
+$appldir = $opt_a ? $opt_a : "";
+$applobjs = $opt_U ? $opt_U : "";
+$syssvcobjs = $opt_S ? $opt_S : "";
+$kernel_lib = $opt_L ? $opt_L : "";
+$kernel_funcobjs = $opt_f ? "true" : "";
+$srclang = $opt_l ? $opt_l : "c";
+$makefile = $opt_m ? $opt_m : "Makefile";
+$dbgenv = $opt_d ? "TOPPERS_".$opt_d : "";
+$enable_trace = $opt_r ? "true" : "";
+$prc_num = $opt_P ? $opt_P : "";
+$copts = $opt_o ? $opt_o : "";
+$cdefs = $opt_O ? $opt_O : "";
+$ldflags = $opt_k ? $opt_k : "";
+
+#
+#  ãªãã¸ã§ã¯ããã¡ã¤ã«åã®æ¡å¼µå­ãè¿ã
+#
+sub get_objext {
+	if ($^O eq 'cygwin') {
+		return("exe");
+	}
+	elsif ($^O eq 'msys') {
+		return("exe");
+	}
+	else {
+		return("");
+	}
+}
+
+#
+#  ãã­ã°ã©ã ã®å ´æãæ¤ç´¢ãã
+#
+sub get_path {
+	my($progname, @pathlist) = @_;
+	my($path);
+
+	foreach $path (@pathlist) {
+		if (-x $path."/".$progname) {
+			return($path."/".$progname);
+		}
+	}
+	return("");
+}
+
+#
+#  ãã¡ã¤ã«ãå¤æãã
+#
+sub convert {
+	my($infile, $outfile) = @_;
+	my($line);
+
+	print STDERR "configure: Generating $outfile from $infile.\n";
+	if (-f $outfile) {
+		print STDERR "configure: $outfile exists.",
+						"  Save as $outfile.bak.\n";
+		rename($outfile, $outfile.".bak");
+	}
+	unless (open(INFILE, $infile)) {
+		print STDERR "configure: can't open $infile\n";
+		exit(1);
+	}
+	unless (open(OUTFILE, "> ".$outfile)) {
+		print STDERR "configure: can't open $outfile\n";
+		exit(1);
+	}
+
+	while ($line = <INFILE>) {
+		chop $line;
+		while ($line =~ /^(.*)\@\(([A-Za-z_]+)\)(.*)$/) {
+			$line = $1.$vartable{$2}.$3;
+		}
+		print OUTFILE $line,"\n";
+	}
+
+	close(INFILE);
+	close(OUTFILE);
+}
+
+#
+#  ãµã³ãã«ãè¦ã¤ãã¦ãã¡ã¤ã«ãçæãã
+#
+sub generate {
+	my($file, $mandatory) = @_;
+	my($path);
+
+	$path = $templatedir."/".$file.".".$target;
+	if (-f $path) {
+		convert($path, $file);
+		return;
+	}	
+
+	$path = $templatedir."/".$file;
+	if ($mandatory || -f $path) {
+		convert($path, $file);
+	}	
+}
+
+#
+#  ã½ã¼ã¹ãã£ã¬ã¯ããªåãåãåºã
+#
+$pwd = `pwd`; chop $pwd;
+if ($opt_D) {
+	$srcabsdir = $srcdir = $opt_D;
+}
+elsif ($0 =~ /(.*)\/configure/) {
+	$srcdir = $1;
+	if ($srcdir =~ /^\//) {
+		$srcabsdir = $srcdir;
+	}
+	else {
+		$srcabsdir = $pwd."/".$srcdir;
+	}
+}
+else {
+	$srcabsdir = $srcdir = $pwd;
+}
+
+$perl = $opt_p ? $opt_p : get_path("perl", ("/usr/local/bin", "/usr/bin"));
+$cfg = $opt_g ? $opt_g : "\$(SRCDIR)/cfg/cfg/cfg";
+$cfgfile = $opt_g ? $opt_g : $srcdir."/cfg/cfg/cfg";
+$templatedir = $opt_t ? $opt_t : $srcdir."/sample";
+
+#
+#  -Tãªãã·ã§ã³ã®ç¢ºèª
+#
+unless ($opt_T) {
+	print STDERR "configure: -T option is mandatory\n";
+	print STDERR "Installed targets are:\n";
+	foreach $targetname (<$srcdir/target/[a-zA-Z0-9]*>) {
+		$targetname =~ s|$srcdir/target/||;
+		print STDERR "\t$targetname\n";
+	}
+	exit(1);
+}
+
+#
+#  å¤æ°ãã¼ãã«ã®ä½æ
+#
+%vartable = ();
+$vartable{"TARGET"} = $target;
+$vartable{"APPLNAME"} = $applname;
+$vartable{"APPLDIR"} = $appldir;
+$vartable{"APPLOBJS"} = $applobjs;
+$vartable{"SYSSVCOBJS"} = $syssvcobjs;
+$vartable{"KERNEL_LIB"} = $kernel_lib;
+$vartable{"KERNEL_FUNCOBJS"} = $kernel_funcobjs;
+$vartable{"SRCDIR"} = $srcdir;
+$vartable{"SRCABSDIR"} = $srcabsdir;
+$vartable{"SRCLANG"} = $srclang;
+$vartable{"DBGENV"} = $dbgenv;
+$vartable{"ENABLE_TRACE"} = $enable_trace;
+$vartable{"PERL"} = $perl;
+$vartable{"CFG"} = $cfg;
+$objext = get_objext();
+$vartable{"OBJEXT"} = $objext;
+$vartable{"PRC_NUM"} = $prc_num;
+$vartable{"COPTS"} = $copts;
+$vartable{"CDEFS"} = $cdefs;
+$vartable{"LDFLAGS"} = $ldflags;
+
+#
+#  ã¿ã¼ã²ãããã£ã¬ã¯ããªã®ãã§ãã¯
+#
+
+if (! -d $srcdir."/target/".$target) {
+	print STDERR "configure: $srcdir/target/$target not exist\n";
+	exit(1);
+}
+
+#
+#  Makefile ã¨ã¢ããªã±ã¼ã·ã§ã³ãã¡ã¤ã«ã®çæ
+#
+
+generate($makefile, 1);
+generate($applname.".c", 0);
+generate($applname.".cpp", 0);
+generate($applname.".h", 0);
+generate($applname.".cfg", 0);
+
+#
+#  cfg ãã§ãã¦ãããã®ãã§ãã¯
+#
+
+if (!(-x ($objext eq "" ? $cfgfile : $cfgfile.".".$objext))) {
+	print STDERR "Executable file of the configurator (cfg) is not found.\n";
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/files/Makefile.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/files/Makefile.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/files/Makefile.config	(revision 453)
@@ -0,0 +1,60 @@
+#
+#   TOPPERS/JSP Kernel
+#       Toyohashi Open Platform for Embedded Real-Time Systems/
+#       Just Standard Profile Kernel
+#
+#   Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                               Toyohashi Univ. of Technology, JAPAN
+#   Copyright (C) 2003-2004 by Ryosuke Takeuchi
+#                Platform Development Center RICOH COMPANY,LTD. JAPAN
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+
+#
+#  Makefile のプロセッサ依存 (storagedevice用)
+#
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/files
+CDEFS := $(CDEFS) -D_STORAGEDEVICEMANAGER_
+LDFLAGS := $(LDFLAGS) \
+	-Wl,--wrap=fseek \
+	-Wl,--wrap=fopen \
+	-Wl,--wrap=fclose
+
+#
+#  ファイルシステムに関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR) $(SRCDIR)/files
+SYSSVC_COBJS := $(SYSSVC_COBJS) storagedevice.o stdio.o stdfile.o diskutils.o
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/files/diskutils.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/files/diskutils.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/files/diskutils.c	(revision 453)
@@ -0,0 +1,278 @@
+/*
+ *  TOPPERS/JSP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Just Standard Profile Kernel
+ * 
+ *  Copyright (C) 2010-2015 by GJ Designing Center RICOH COMPANY,LTD. JAPAN
+ *  Copyright (C) 2015-2016 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+ *  によって公表されている GNU General Public License の Version 2 に記
+ *  述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+ *  を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+ *  含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+ *  接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "storagedevice.h"
+#include "monitor.h"
+
+#define NUM_VOLUME_CMD      5
+
+static int_t volume_format(int argc, char **argv);
+static int_t volume_dir(int argc, char **argv);
+static int_t volume_mkdir(int argc, char **argv);
+static int_t volume_rmdir(int argc, char **argv);
+static int_t volume_delete(int argc, char **argv);
+
+/*
+ *  VOLUMEコマンドテーブル
+ */
+static const COMMAND_INFO volume_command_info[] = {
+	{"FORMAT",		volume_format },	/* ボリュームフォーマット */
+	{"DIR",			volume_dir    },	/* ディレクトリ表示 */
+	{"MKDIR",		volume_mkdir  },	/* ディレクトリ作成 */
+	{"RMDIR",		volume_rmdir  },	/* ディレクトリ削除 */
+	{"ERASE",		volume_delete }		/* ファイル削除 */
+};
+
+static const char volume_name[] = "VOLUME";
+static const char volume_help[] =
+"  Volume  FORMAT   [drive]\n"
+"          DIR      [path] \n"
+"          MKDIR    [path] \n"
+"          RMDIR    [path] \n"
+"          ERASE    [path] \n";
+
+static COMMAND_LINK volume_command_link = {
+	NULL,
+	NUM_VOLUME_CMD,
+	volume_name,
+	NULL,
+	volume_help,
+	&volume_command_info[0]
+};
+
+static struct dirent2 finfo;
+
+/*
+ *  RTCコマンド設定関数
+ */
+void volume_info_init(intptr_t exinf)
+{
+	setup_command(&volume_command_link);
+}
+
+/*
+ *  ストレージボリュームフォーマット
+ */
+static int_t
+volume_format(int argc, char **argv)
+{
+	printf("not support !\n");
+	return 0;
+}
+
+/*
+ *  ストレージボリュームディレクトリ
+ */
+static int_t
+volume_dir(int argc, char **argv)
+{
+	StorageDevice_t *psdev;
+	struct statfs2  status;
+	char   *path, *spath, name[16];
+	int    devno, no, count;
+	void   *dir;
+
+	name[0] = 0;
+	if(argc > 1)
+		spath = path = argv[1];
+	else
+		spath = path = &name[1];
+	devno = SDMGetDeviceNo((const char **)&path);
+	psdev = SDMGetStorageDevice(devno);
+	if(psdev == 0){
+		printf("\nno device !\n");
+		return -1;
+	}
+	if(psdev->pdevff == 0 || psdev->pdevff->_sdevff_opendir == 0){
+		printf("\nno function !\n");
+		return -1;
+	}
+	if((psdev->_sdev_attribute & SDEV_EMPLOY) == 0){
+		printf("\nno media !\n");
+		return -1;
+	}
+	count = 0;
+	dir = psdev->pdevff->_sdevff_opendir(spath);
+	if(dir != NULL){
+		if(*spath == 0){
+			name[0] = devno + '0';
+			name[1] = ':';
+			name[2] = '/';
+			name[3] = 0;
+			spath = name;
+		}
+		printf("\nDirectory [%s]\n", spath);
+		while(psdev->pdevff->_sdevff_readdir(dir, &finfo) != 0 && finfo.d_name[0] != 0){
+			count++;
+			printf("%3d %s ", count, finfo.d_name);
+			no = strlen(finfo.d_name);
+			while(no < 24){
+				putchar(' ');
+				no++;
+			}
+			printf("%04d/%02d/%02d ", (finfo.d_date>>9)+1980, (finfo.d_date>>5) & 15, finfo.d_date & 31);
+			printf("%02d:%02d:%02d ", finfo.d_time>>11, (finfo.d_time>>5) & 63, (finfo.d_time & 31)*2);
+			if(finfo.d_type & AM_HID)
+				name[0] = '*';
+			else
+				name[0] = ' ';
+			if(finfo.d_type & AM_SYS)
+				name[1] = 'S';
+			else
+				name[1] = ' ';
+			name[2] = 'R';
+			if(finfo.d_type & AM_RDO)
+				name[3] = ' ';
+			else
+				name[3] = 'W';
+			name[4] = 0;
+			if(finfo.d_type & AM_DIR)
+				printf("<DIR>  \n");
+			else if(finfo.d_type & AM_VOL)
+				printf("<VOL>  \n");
+			else
+				printf("[%s]  %8d\n", name, (int)finfo.d_fsize);
+		}
+		printf("     %d file(s)\n", count);
+		psdev->pdevff->_sdevff_closedir(dir);
+		if(psdev->pdevff->_sdevff_statfs != 0
+			 && psdev->pdevff->_sdevff_statfs(spath, &status) == 0){
+			printf("     %d free blocks %d bytes in a block\n", (int)status.f_bfree, (int)status.f_bsize);
+		}
+	}
+	else{
+		printf("Disk Error !\n");
+	}
+	return 0;
+}
+
+/*
+ *  ストレージボリュームMKDIR
+ */
+static int_t
+volume_mkdir(int argc, char **argv)
+{
+	StorageDevice_t *psdev;
+	char   *path, *spath;
+	int    devno;
+
+	if(argc > 1){
+		spath = path = argv[1];
+		devno = SDMGetDeviceNo((const char **)&path);
+		psdev = SDMGetStorageDevice(devno);
+		if(psdev == 0){
+			printf("\nno device !\n");
+			return -1;
+		}
+		if(psdev->pdevff == 0 || psdev->pdevff->_sdevff_mkdir == 0){
+			printf("\nno function !\n");
+			return -1;
+		}
+		printf(" mkdir[%s]\n", path);
+		if(psdev->pdevff->_sdevff_mkdir(spath) >= 0)
+			printf("   Ok\n");
+		else
+			printf("   Error\n");
+	}
+	return 0;
+}
+
+/*
+ *  ストレージボリュームRMDIR
+ */
+static int_t
+volume_rmdir(int argc, char **argv)
+{
+	StorageDevice_t *psdev;
+	char   *path, *spath;
+	int    devno;
+
+	if(argc > 1){
+		spath = path = argv[1];
+		devno = SDMGetDeviceNo((const char **)&path);
+		psdev = SDMGetStorageDevice(devno);
+		if(psdev == 0){
+			printf("\nno device !\n");
+			return -1;
+		}
+		if(psdev->pdevff == 0 || psdev->pdevff->_sdevff_rmdir == 0){
+			printf("\nno function !\n");
+			return -1;
+		}
+		printf(" rmdir[%s]\n", path);
+		if(psdev->pdevff->_sdevff_rmdir(spath) >= 0)
+			printf("   Ok\n");
+		else
+			printf("   Error\n");
+	}
+	return 0;
+}
+
+/*
+ *  ストレージボリュームファイル削除
+ */
+static int_t
+volume_delete(int argc, char **argv)
+{
+	StorageDevice_t *psdev;
+	char   *path, *spath;
+	int    devno;
+
+	if(argc > 1){
+		spath = path = argv[1];
+		devno = SDMGetDeviceNo((const char **)&path);
+		psdev = SDMGetStorageDevice(devno);
+		if(psdev == 0){
+			printf("\nno device !\n");
+			return -1;
+		}
+		if(psdev->pdevff == 0 || psdev->pdevff->_sdevff_unlink == 0){
+			printf("\nno function !\n");
+			return -1;
+		}
+		printf(" unlink[%s]\n", path);
+		if(psdev->pdevff->_sdevff_unlink(spath) >= 0)
+			printf("   Ok\n");
+		else
+			printf("   Error\n");
+	}
+	return 0;
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/files/fcntl.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/files/fcntl.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/files/fcntl.h	(revision 453)
@@ -0,0 +1,229 @@
+/*	$NetBSD: fcntl.h,v 1.10.2.1 1998/01/29 10:38:31 mellon Exp $	*/
+
+/*-
+ * Copyright (c) 1983, 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)fcntl.h	8.3 (Berkeley) 1/21/94
+ */
+
+/*
+ * このプログラムはNetBSD用ヘッダーに
+ * ＲＯＭファイル専用ファイルストレージ専用機能を追加したインクルードファイルである。
+ *
+ * $Modifier:  roi takeuchi
+ * $Date:    2019/12/03
+ * $Version: 1.0.0.1
+ *
+ */
+#ifndef _SYS_FCNTL_H_
+#define	_SYS_FCNTL_H_
+
+/*
+ * This file includes the definitions for open and fcntl
+ * described by POSIX for <fcntl.h>; it also includes
+ * related kernel definitions.
+ */
+#ifndef NOTUSE_TYPES_H	/* types.hは呼ばない */
+#include <sys/types.h>
+#elif defined(__SHC__)	/* SHCの場合off_tは未定義 */
+typedef long long off_t;
+#endif
+
+/*
+ * File status flags: these are used by open(2), fcntl(2).
+ * They are also used (indirectly) in the kernel file structure f_flags,
+ * which is a superset of the open/fcntl flags.  Open flags and f_flags
+ * are inter-convertible using OFLAGS(fflags) and FFLAGS(oflags).
+ * Open/fcntl flags begin with O_; kernel-internal flags begin with F.
+ */
+/* open-only flags */
+#define	O_RDONLY	0x0000		/* open for reading only */
+#define	O_WRONLY	0x0001		/* open for writing only */
+#define	O_RDWR		0x0002		/* open for reading and writing */
+#define	O_ACCMODE	0x0003		/* mask for above modes */
+
+/*
+ * Kernel encoding of open mode; separate read and write bits that are
+ * independently testable: 1 greater than the above.
+ *
+ * XXX
+ * FREAD and FWRITE are excluded from the #ifdef _KERNEL so that TIOCFLUSH,
+ * which was documented to use FREAD/FWRITE, continues to work.
+ */
+#ifndef _POSIX_SOURCE
+#define	FREAD		0x0001
+#define	FWRITE		0x0002
+#endif
+#define	O_NONBLOCK	0x0004		/* no delay */
+#define	O_APPEND	0x0008		/* set append mode */
+#ifndef _POSIX_SOURCE
+#define	O_SHLOCK	0x0010		/* open with shared file lock */
+#define	O_EXLOCK	0x0020		/* open with exclusive file lock */
+#define	O_ASYNC		0x0040		/* signal pgrp when data ready */
+#endif
+#if !defined(_POSIX_SOURCE) || defined(_XOPEN_SOURCE)
+#define	O_SYNC		0x0080		/* synchronous writes */
+#endif
+#define	O_CREAT		0x0200		/* create if nonexistant */
+#define	O_TRUNC		0x0400		/* truncate to zero length */
+#define	O_EXCL		0x0800		/* error if already exists */
+
+/* defined by POSIX 1003.1; BSD default, but required to be distinct */
+#define	O_NOCTTY	0x8000		/* don't assign controlling terminal */
+
+/*
+ * The O_* flags used to have only F* names, which were used in the kernel
+ * and by fcntl.  We retain the F* names for the kernel f_flags field
+ * and for backward compatibility for fcntl.
+ */
+#ifndef _POSIX_SOURCE
+#define	FAPPEND		O_APPEND	/* kernel/compat */
+#define	FASYNC		O_ASYNC		/* kernel/compat */
+#define	FFSYNC		O_SYNC		/* kernel */
+#ifndef _XOPEN_SOURCE
+#define	O_FSYNC		O_SYNC		/* compat */
+#endif
+#define	FNONBLOCK	O_NONBLOCK	/* kernel */
+#define	FNDELAY		O_NONBLOCK	/* compat */
+#define	O_NDELAY	O_NONBLOCK	/* compat */
+#endif
+
+/*
+ * Constants used for fcntl(2)
+ */
+
+/* command values */
+#define	F_DUPFD		0		/* duplicate file descriptor */
+#define	F_GETFD		1		/* get file descriptor flags */
+#define	F_SETFD		2		/* set file descriptor flags */
+#define	F_GETFL		3		/* get file status flags */
+#define	F_SETFL		4		/* set file status flags */
+#ifndef _POSIX_SOURCE
+#define	F_GETOWN	5		/* get SIGIO/SIGURG proc/pgrp */
+#define F_SETOWN	6		/* set SIGIO/SIGURG proc/pgrp */
+#endif
+#define	F_GETLK		7		/* get record locking information */
+#define	F_SETLK		8		/* set record locking information */
+#define	F_SETLKW	9		/* F_SETLK; wait if blocked */
+
+/* file descriptor flags (F_GETFD, F_SETFD) */
+#define	FD_CLOEXEC	1		/* close-on-exec flag */
+
+/* record locking flags (F_GETLK, F_SETLK, F_SETLKW) */
+#define	F_RDLCK		1		/* shared or read lock */
+#define	F_UNLCK		2		/* unlock */
+#define	F_WRLCK		3		/* exclusive or write lock */
+
+#ifndef _POSIX_SOURCE
+/* lock operations for flock(2) */
+#define	LOCK_SH		0x01		/* shared file lock */
+#define	LOCK_EX		0x02		/* exclusive file lock */
+#define	LOCK_NB		0x04		/* don't block when locking */
+#define	LOCK_UN		0x08		/* unlock file */
+#endif
+
+/* fseek parameters */
+#ifndef SEEK_SET
+#define	SEEK_SET	0	/* set file offset to offset */
+#endif
+#ifndef SEEK_CUR
+#define	SEEK_CUR	1	/* set file offset to current plus offset */
+#endif
+#ifndef SEEK_END
+#define	SEEK_END	2	/* set file offset to EOF plus offset */
+#endif
+
+/* struct stat defintion */
+#ifndef	_SYS_STAT_H
+struct stat {
+	unsigned int    st_dev;		/* inode's device */
+	unsigned int    st_ino;		/* inode's number */
+	unsigned int    st_mode;	/* inode protection mode */
+	unsigned int    t_nlink;	/* number of hard links */
+	unsigned int    st_uid;		/* user ID of the file's owner */
+	unsigned int    st_gid;		/* group ID of the file's group */
+	unsigned int    st_rdev;	/* device type */
+	int             st_atime;	/* time of last access */
+	long            st_atimensec;	/* nsec of last access */
+	int             st_mtime;	/* time of last data modification */
+	long            st_mtimensec;	/* nsec of last data modification */
+	int             st_ctime;	/* time of last file status change */
+	long            st_ctimensec;	/* nsec of last file status change */
+	off_t           st_size;	/* file size, in bytes */
+	off_t           st_blocks;	/* blocks allocated for file */
+	unsigned int    st_blksize;	/* optimal blocksize for I/O */
+	unsigned int    st_flags;	/* user defined flags for file */
+	unsigned int    st_gen;		/* file generation number */
+	off_t           st_qspare[2];
+};
+#define _STAT_H_
+#endif	/* _SYS_STAT_H */
+
+/*
+ * Protections are chosen from these bits, or-ed together
+ */
+#define	PROT_NONE	0x00	/* no permissions */
+#define	PROT_READ	0x01	/* pages can be read */
+#define	PROT_WRITE	0x02	/* pages can be written */
+#define	PROT_EXEC	0x04	/* pages can be executed */
+
+/*
+ * Flags contain sharing type and options.
+ * Sharing types; choose one.
+ */
+#define	MAP_SHARED	0x0001	/* share changes */
+#define	MAP_PRIVATE	0x0002	/* changes are private */
+#define	MAP_COPY	0x0004	/* "copy" region at mmap time */
+
+struct StdFileIndex {
+	void            *sdmdev;
+	int             sdmfd;
+};
+
+extern int   open(const char *pathname, int flags);
+extern int   close(int fd);
+extern int   fstat(int fd, struct stat *buf);
+extern off_t lseek(int fd, off_t offset, int whence);
+extern long  read(int fd, void *buf, long count);
+extern long  write(int fd, const void *buf, long count);
+extern void  *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
+extern int   munmap(void *start, size_t length);
+
+
+#endif /* !_SYS_FCNTL_H_ */
+
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/00readme.txt
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/00readme.txt	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/00readme.txt	(revision 453)
@@ -0,0 +1,96 @@
+FatFs/Tiny-FatFs Module Source Files R0.07a                 (C)ChaN, 2009
+
+
+FILES
+
+  ff.h       Common include file for FatFs and application module.
+  ff.c       FatFs module.
+  diskio.h   Common include file for FatFs and disk I/O module.
+  diskio.c   Skeleton of low level disk I/O module.
+  integer.h  Alternative type definitions for integer variables.
+  option     Optional external functions.
+
+  Low level disk I/O module is not included in this archive because the FatFs
+  module is only a generic file system layer and not depend on any specific
+  storage device. You have to provide a low level disk I/O module that written
+  to control your storage device.
+
+
+
+AGREEMENTS
+
+ FatFs module is an open source software to implement FAT file system to
+ small embedded systems. This is a free software and is opened for education,
+ research and commercial developments under license policy of following trems.
+
+  Copyright (C) 2009, ChaN, all right reserved.
+
+ * The FatFs module is a free software and there is NO WARRANTY.
+ * No restriction on use. You can use, modify and redistribute it for
+   personal, non-profit or commercial use UNDER YOUR RESPONSIBILITY.
+ * Redistributions of source code must retain the above copyright notice.
+
+
+
+REVISION HISTORY
+
+  Feb 26, 2006  R0.00  Prototype
+
+  Apr 29, 2006  R0.01  First release.
+
+  Jun 01, 2006  R0.02  Added FAT12.
+                       Removed unbuffered mode.
+                       Fixed a problem on small (<32M) patition.
+
+  Jun 10, 2006  R0.02a Added a configuration option _FS_MINIMUM.
+
+  Sep 22, 2006  R0.03  Added f_rename.
+                       Changed option _FS_MINIMUM to _FS_MINIMIZE.
+
+  Dec 11, 2006  R0.03a Improved cluster scan algolithm to write files fast.
+                       Fixed f_mkdir creates incorrect directory on FAT32.
+
+  Feb 04, 2007  R0.04  Supported multiple drive system. (FatFs)
+                       Changed some APIs for multiple drive system.
+                       Added f_mkfs. (FatFs)
+                       Added _USE_FAT32 option. (Tiny-FatFs)
+
+  Apr 01, 2007  R0.04a Supported multiple partitions on a plysical drive. (FatFs)
+                       Fixed an endian sensitive code in f_mkfs. (FatFs)
+                       Added a capability of extending the file size to f_lseek.
+                       Added minimization level 3.
+                       Fixed a problem that can collapse a sector when recreate an
+                       existing file in any sub-directory at non FAT32 cfg. (Tiny-FatFs)
+
+  May 05, 2007  R0.04b Added _USE_NTFLAG option.
+                       Added FSInfo support.
+                       Fixed some problems corresponds to FAT32. (Tiny-FatFs)
+                       Fixed DBCS name can result FR_INVALID_NAME.
+                       Fixed short seek (0 < ofs <= csize) collapses the file object.
+
+  Aug 25, 2007  R0.05  Changed arguments of f_read, f_write.
+                       Changed arguments of f_mkfs. (FatFs)
+                       Fixed f_mkfs on FAT32 creates incorrect FSInfo. (FatFs)
+                       Fixed f_mkdir on FAT32 creates incorrect directory. (FatFs)
+
+  Feb 03, 2008  R0.05a Added f_truncate().
+                       Added f_utime().
+                       Fixed off by one error at FAT sub-type determination.
+                       Fixed btr in f_read() can be mistruncated.
+                       Fixed cached sector is not flushed when create and close without write.
+
+  Apr 01, 2008  R0.06  Added f_forward(). (Tiny-FatFs)
+                       Added string functions: fputc(), fputs(), fprintf() and fgets().
+                       Improved performance of f_lseek() on move to the same or following cluster.
+
+  Apr 01, 2009, R0.07  Merged Tiny-FatFs as a buffer configuration option.
+                       Added long file name support.
+                       Added multiple code page support.
+                       Added re-entrancy for multitask operation.
+                       Added auto cluster size selection to f_mkfs().
+                       Added rewind option to f_readdir().
+                       Changed result code of critical errors.
+                       Renamed string functions to avoid name collision.
+
+  Apr 14, 2009, R0.07a Separated out OS dependent code on reentrant cfg.
+                       Added multiple sector size support.
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/Makefile.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/Makefile.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/Makefile.config	(revision 453)
@@ -0,0 +1,55 @@
+#
+#   TOPPERS/JSP Kernel
+#       Toyohashi Open Platform for Embedded Real-Time Systems/
+#       Just Standard Profile Kernel
+#
+#   Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                               Toyohashi Univ. of Technology, JAPAN
+#   Copyright (C) 2003-2004 by Ryosuke Takeuchi
+#                Platform Development Center RICOH COMPANY,LTD. JAPAN
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+ 
+#
+#  Makefile のプロセッサ依存 (fatfs用)
+#
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/files/ff
+
+#
+#  ファイルシステムに関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR) $(SRCDIR)/files/ff $(SRCDIR)/files/ff/option
+SYSSVC_COBJS := $(SYSSVC_COBJS) ff.o syncobj.o cc932.o diskio.o sddiskio.o fffcntl.o
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/Makefile2.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/Makefile2.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/Makefile2.config	(revision 453)
@@ -0,0 +1,55 @@
+#
+#   TOPPERS/JSP Kernel
+#       Toyohashi Open Platform for Embedded Real-Time Systems/
+#       Just Standard Profile Kernel
+#
+#   Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                               Toyohashi Univ. of Technology, JAPAN
+#   Copyright (C) 2003-2004 by Ryosuke Takeuchi
+#                Platform Development Center RICOH COMPANY,LTD. JAPAN
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+ 
+#
+#  Makefile のプロセッサ依存 (fatfs用)
+#
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/files/ff
+
+#
+#  ファイルシステムに関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR) $(SRCDIR)/files/ff $(SRCDIR)/files/ff/option
+SYSSVC_COBJS := $(SYSSVC_COBJS) ff.o syncobj.o cc932.o diskio.o fffcntl.o
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/diskio.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/diskio.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/diskio.c	(revision 453)
@@ -0,0 +1,157 @@
+/*
+ *  FatFs for TOPPERS
+ *      FAT File system/
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2005- by Industrial Technology Institute,
+ *                          Miyagi Prefectural Government, JAPAN
+ *  Copyright (C) 2007-2010 by 
+ *                     GJ Business Division RICOH COMPANY,LTD. JAPAN
+ *  Copyright (C) 2015-2017 by TOPPERS PROJECT Educational Group.
+ * 
+ *  上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+ *  によって公表されている GNU General Public License の Version 2 に記
+ *  述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+ *  を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+ *  含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+ *  接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *  FatFsが規定している下位レイヤI/F
+ *  　本来は複数ドライブに対応すべきだが、このターゲットボードでは
+ *  　ドライブは１つのみサポートしている。
+ */
+
+#include "kernel_impl.h"
+#include <string.h>	/*  memcpy()  */
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include "storagedevice.h"
+#include "diskio.h"
+
+#define RETRY_COUNT    8
+
+/*
+ *  ディスク・ドライブの初期化
+ *　　引数
+ *　　　 BYTE Drive	物理ドライブ番号
+ */
+DSTATUS
+disk_initialize(BYTE Drive)
+{
+	StorageDevice_t *psdev = SDMGetStorageDevice(Drive);
+
+	if(psdev == NULL || psdev->pdevf == NULL || psdev->pdevf->_sdevf_diskinit == NULL)
+		return STA_NODISK;
+	return psdev->pdevf->_sdevf_diskinit(psdev);
+}
+
+
+/*
+ *  ディスク・ドライブの状態取得
+ *　　引数
+ *　　　 BYTE Drive	物理ドライブ番号
+ */
+DSTATUS
+disk_status(BYTE Drive)
+{
+	StorageDevice_t *psdev = SDMGetStorageDevice(Drive);
+
+	if(psdev == NULL || psdev->pdevf == NULL || psdev->pdevf->_sdevf_diskstatus == NULL)
+		return STA_NODISK;
+	return psdev->pdevf->_sdevf_diskstatus(psdev);
+}
+
+
+/*
+ *  ディスクからの読み込み
+ *　　引数
+ *　　　 BYTE Drive　　　　　物理ドライブ番号
+ *　　　 BYTE* Buffer        読み出しバッファへのポインタ
+ *　　　 DWORD SectorNumber  読み出し開始セクタ番号
+ *　　　 BYTE SectorCount    読み出しセクタ数
+ */
+DRESULT
+disk_read(BYTE Drive, BYTE* Buffer, DWORD SectorNumber, BYTE SectorCount)
+{
+	StorageDevice_t *psdev = SDMGetStorageDevice(Drive);
+
+	if(psdev == NULL || psdev->pdevf == NULL || psdev->pdevf->_sdevf_diskread == NULL)
+		return RES_ERROR;
+	return psdev->pdevf->_sdevf_diskread(psdev, Buffer, SectorNumber, SectorCount);
+}
+
+/*
+ *  ディスクへの書き込み
+ *　　引数
+ *　　　 BYTE Drive　　　　　物理ドライブ番号
+ *　　　 BYTE* Buffer        書き込むデータへのポインタ
+ *　　　 DWORD SectorNumber  書き込み開始セクタ番号
+ *　　　 BYTE SectorCount    書き込みセクタ数
+ */
+DRESULT
+disk_write(BYTE Drive, const BYTE* Buffer, DWORD SectorNumber, BYTE SectorCount)
+{
+	StorageDevice_t *psdev = SDMGetStorageDevice(Drive);
+
+	if(psdev == NULL || psdev->pdevf == NULL || psdev->pdevf->_sdevf_diskwrite == NULL)
+		return RES_ERROR;
+	return psdev->pdevf->_sdevf_diskwrite(psdev, Buffer, SectorNumber, SectorCount);
+}
+
+DRESULT
+disk_ioctl(BYTE Drive, BYTE Func, void* Buffer)
+{
+	StorageDevice_t *psdev = SDMGetStorageDevice(Drive);
+
+	if(psdev == NULL || psdev->pdevf == NULL || psdev->pdevf->_sdevf_diskioctl == NULL)
+		return RES_ERROR;
+	return psdev->pdevf->_sdevf_diskioctl(psdev, Func, Buffer);
+}
+
+/*
+ *  日付・時刻の取得
+ *  　　ToDo：未実装
+ */
+DWORD
+get_fattime(void)
+{
+	SYSTIM systim;
+	DWORD  fdate = ((2017-1980)<<25)+(1<<21)+(1<<16);
+	DWORD  ftime;
+
+	if(SDeviceHead._get_datetime != 0)
+		return (DWORD)SDeviceHead._get_datetime();
+	else{
+		get_tim(&systim);
+		systim = (systim+1000L) /2000L;
+		ftime  = systim % 30;
+		ftime += ((systim/30) % 60)<<5;
+		ftime += ((systim/(60*30))<<11);
+		return (fdate+ftime);
+	}
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/diskio.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/diskio.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/diskio.h	(revision 453)
@@ -0,0 +1,70 @@
+/*-----------------------------------------------------------------------
+/  Low level disk interface modlue include file  R0.07   (C)ChaN, 2009
+/-----------------------------------------------------------------------*/
+
+#ifndef _DISKIO
+
+#define _READONLY	0	/* 1: Read-only mode */
+#define _USE_IOCTL	1
+
+#include "integer.h"
+
+
+/* Status of Disk Functions */
+typedef BYTE	DSTATUS;
+
+/* Results of Disk Functions */
+typedef enum {
+	RES_OK = 0,		/* 0: Successful */
+	RES_ERROR,		/* 1: R/W Error */
+	RES_WRPRT,		/* 2: Write Protected */
+	RES_NOTRDY,		/* 3: Not Ready */
+	RES_PARERR		/* 4: Invalid Parameter */
+} DRESULT;
+
+
+/*---------------------------------------*/
+/* Prototypes for disk control functions */
+
+BOOL assign_drives (int argc, char *argv[]);
+DSTATUS disk_initialize (BYTE);
+DSTATUS disk_status (BYTE);
+DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);
+#if	_READONLY == 0
+DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);
+#endif
+DRESULT disk_ioctl (BYTE, BYTE, void*);
+
+
+
+/* Disk Status Bits (DSTATUS) */
+
+#define STA_NOINIT		0x01	/* Drive not initialized */
+#define STA_NODISK		0x02	/* No medium in the drive */
+#define STA_PROTECT		0x04	/* Write protected */
+
+
+/* Command code for disk_ioctrl() */
+
+/* Generic command */
+#define CTRL_SYNC			0	/* Mandatory for write functions */
+#define GET_SECTOR_COUNT	1	/* Mandatory for only f_mkfs() */
+#define GET_SECTOR_SIZE		2
+#define GET_BLOCK_SIZE		3	/* Mandatory for only f_mkfs() */
+#define CTRL_POWER			4
+#define CTRL_LOCK			5
+#define CTRL_EJECT			6
+/* MMC/SDC command */
+#define MMC_GET_TYPE		10
+#define MMC_GET_CSD			11
+#define MMC_GET_CID			12
+#define MMC_GET_OCR			13
+#define MMC_GET_SDSTAT		14
+/* ATA/CF command */
+#define ATA_GET_REV			20
+#define ATA_GET_MODEL		21
+#define ATA_GET_SN			22
+
+
+#define _DISKIO
+#endif
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/fatfs.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/fatfs.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/fatfs.cfg	(revision 453)
@@ -0,0 +1,18 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *  FATFSのコンフィギュレーションファイル
+ */
+
+#include "ff.h"
+#include "sddiskio.h"
+
+ATT_INI({TA_NULL, 0, sd_init});
+
+CRE_SEM(SEMID_FATFS1,{ TA_TPRI, 1, 1 });
+CRE_SEM(SEMID_FATFS2,{ TA_TPRI, 1, 1 });
+CRE_SEM(SEMID_FATFS3,{ TA_TPRI, 1, 1 });
+CRE_SEM(SEMID_FATFS4,{ TA_TPRI, 1, 1 });
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/ff.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/ff.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/ff.c	(revision 453)
@@ -0,0 +1,2945 @@
+/*----------------------------------------------------------------------------/
+/  FatFs - FAT file system module  R0.07a                    (C)ChaN, 2009
+/-----------------------------------------------------------------------------/
+/ FatFs module is an open source software to implement FAT file system to
+/ small embedded systems. This is a free software and is opened for education,
+/ research and commercial developments under license policy of following trems.
+/
+/  Copyright (C) 2009, ChaN, all right reserved.
+/
+/ * The FatFs module is a free software and there is NO WARRANTY.
+/ * No restriction on use. You can use, modify and redistribute it for
+/   personal, non-profit or commercial use UNDER YOUR RESPONSIBILITY.
+/ * Redistributions of source code must retain the above copyright notice.
+//-----------------------------------------------------------------------------/
+/ Feb 26,'06 R0.00  Prototype.
+/
+/ Apr 29,'06 R0.01  First stable version.
+/
+/ Jun 01,'06 R0.02  Added FAT12 support.
+/                   Removed unbuffered mode.
+/                   Fixed a problem on small (<32M) patition.
+/ Jun 10,'06 R0.02a Added a configuration option (_FS_MINIMUM).
+/
+/ Sep 22,'06 R0.03  Added f_rename().
+/                   Changed option _FS_MINIMUM to _FS_MINIMIZE.
+/ Dec 11,'06 R0.03a Improved cluster scan algolithm to write files fast.
+/                   Fixed f_mkdir() creates incorrect directory on FAT32.
+/
+/ Feb 04,'07 R0.04  Supported multiple drive system.
+/                   Changed some interfaces for multiple drive system.
+/                   Changed f_mountdrv() to f_mount().
+/                   Added f_mkfs().
+/ Apr 01,'07 R0.04a Supported multiple partitions on a plysical drive.
+/                   Added a capability of extending file size to f_lseek().
+/                   Added minimization level 3.
+/                   Fixed an endian sensitive code in f_mkfs().
+/ May 05,'07 R0.04b Added a configuration option _USE_NTFLAG.
+/                   Added FSInfo support.
+/                   Fixed DBCS name can result FR_INVALID_NAME.
+/                   Fixed short seek (<= csize) collapses the file object.
+/
+/ Aug 25,'07 R0.05  Changed arguments of f_read(), f_write() and f_mkfs().
+/                   Fixed f_mkfs() on FAT32 creates incorrect FSInfo.
+/                   Fixed f_mkdir() on FAT32 creates incorrect directory.
+/ Feb 03,'08 R0.05a Added f_truncate() and f_utime().
+/                   Fixed off by one error at FAT sub-type determination.
+/                   Fixed btr in f_read() can be mistruncated.
+/                   Fixed cached sector is not flushed when create and close
+/                   without write.
+/
+/ Apr 01,'08 R0.06  Added fputc(), fputs(), fprintf() and fgets().
+/                   Improved performance of f_lseek() on moving to the same
+/                   or following cluster.
+/
+/ Apr 01,'09 R0.07  Merged Tiny-FatFs as a buffer configuration option.
+/                   Added long file name support.
+/                   Added multiple code page support.
+/                   Added re-entrancy for multitask operation.
+/                   Added auto cluster size selection to f_mkfs().
+/                   Added rewind option to f_readdir().
+/                   Changed result code of critical errors.
+/                   Renamed string functions to avoid name collision.
+/ Apr 14,'09 R0.07a Separated out OS dependent code on reentrant cfg.
+/                   Added multiple sector size support.
+/---------------------------------------------------------------------------*/
+
+#include "ff.h"			/* FatFs configurations and declarations */
+#include "diskio.h"		/* Declarations of low level disk I/O functions */
+
+
+/*--------------------------------------------------------------------------
+
+   Module Private Definitions
+
+---------------------------------------------------------------------------*/
+
+#if _FS_REENTRANT
+#if _USE_LFN == 1
+#error Static LFN work area must not be used in re-entrant configuration.
+#endif
+#define	ENTER_FF(fs)		{ if (!lock_fs(fs)) return FR_TIMEOUT; }
+#define	LEAVE_FF(fs, res)	{ unlock_fs(fs, res); return res; }
+
+#else
+#define	ENTER_FF(fs)
+#define LEAVE_FF(fs, res)	return res
+
+#endif
+
+#define	ABORT(fs, res)		{ fp->flag |= FA__ERROR; LEAVE_FF(fs, res); }
+
+#ifndef NULL
+#define	NULL	0
+#endif
+
+
+/*--------------------------------------------------------------------------
+
+   Private Work Area
+
+---------------------------------------------------------------------------*/
+
+static
+FATFS *FatFs[_DRIVES];	/* Pointer to the file system objects (logical drives) */
+static
+WORD Fsid;				/* File system mount ID */
+
+
+#if _USE_LFN == 1	/* LFN with static LFN working buffer */
+static
+WORD LfnBuf[_MAX_LFN + 1];
+#define	NAMEBUF(sp,lp)	BYTE sp[12]; WCHAR *lp = LfnBuf
+#define INITBUF(dj,sp,lp)	dj.fn = sp; dj.lfn = lp
+
+#elif _USE_LFN > 1	/* LFN with dynamic LFN working buffer */
+#define	NAMEBUF(sp,lp)	BYTE sp[12]; WCHAR lbuf[_MAX_LFN + 1], *lp = lbuf
+#define INITBUF(dj,sp,lp)	dj.fn = sp; dj.lfn = lp
+#if 1	/* ROI MODIFIED */
+#define INITBUF2(dj,sp)		dj.fn = sp
+#endif	/* ROI MODIFIED */
+
+#else				/* No LFN */
+#define	NAMEBUF(sp,lp)	BYTE sp[12]
+#define INITBUF(dj,sp,lp)	dj.fn = sp
+
+#endif
+
+
+
+
+/*--------------------------------------------------------------------------
+
+   Private Functions
+
+---------------------------------------------------------------------------*/
+
+
+/*-----------------------------------------------------------------------*/
+/* String functions                                                      */
+/*-----------------------------------------------------------------------*/
+
+/* Copy memory to memory */
+static
+void mem_cpy (void* dst, const void* src, int cnt) {
+	char *d = (char*)dst;
+	const char *s = (const char *)src;
+	while (cnt--) *d++ = *s++;
+}
+
+/* Fill memory */
+static
+void mem_set (void* dst, int val, int cnt) {
+	char *d = (char*)dst;
+	while (cnt--) *d++ = (char)val;
+}
+
+/* Compare memory to memory */
+static
+int mem_cmp (const void* dst, const void* src, int cnt) {
+	const char *d = (const char *)dst, *s = (const char *)src;
+	int r = 0;
+	while (cnt-- && (r = *d++ - *s++) == 0) ;
+	return r;
+}
+
+/* Check if chr is contained in the string */
+static
+int chk_chr (const char* str, int chr) {
+	while (*str && *str != chr) str++;
+	return *str;
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Request/Release grant to access the volume                            */
+/*-----------------------------------------------------------------------*/
+#if _FS_REENTRANT
+
+static
+BOOL lock_fs (
+	FATFS *fs		/* File system object */
+)
+{
+	return ff_req_grant(fs->sobj);
+}
+
+
+static
+void unlock_fs (
+	FATFS *fs,		/* File system object */
+	FRESULT res		/* Result code to be returned */
+)
+{
+	if (res != FR_NOT_ENABLED &&
+		res != FR_INVALID_DRIVE &&
+		res != FR_INVALID_OBJECT &&
+		res != FR_TIMEOUT) {
+		ff_rel_grant(fs->sobj);
+	}
+}
+#endif
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Change window offset                                                  */
+/*-----------------------------------------------------------------------*/
+
+static
+FRESULT move_window (
+	FATFS *fs,		/* File system object */
+	DWORD sector	/* Sector number to make apperance in the fs->win[] */
+)					/* Move to zero only writes back dirty window */
+{
+	DWORD wsect;
+
+
+	wsect = fs->winsect;
+	if (wsect != sector) {	/* Changed current window */
+#if !_FS_READONLY
+		if (fs->wflag) {	/* Write back dirty window if needed */
+			if (disk_write(fs->drive, fs->win, wsect, 1) != RES_OK)
+				return FR_DISK_ERR;
+			fs->wflag = 0;
+			if (wsect < (fs->fatbase + fs->sects_fat)) {	/* In FAT area */
+				BYTE nf;
+				for (nf = fs->n_fats; nf >= 2; nf--) {	/* Refrect the change to FAT copy */
+					wsect += fs->sects_fat;
+					disk_write(fs->drive, fs->win, wsect, 1);
+				}
+			}
+		}
+#endif
+		if (sector) {
+			if (disk_read(fs->drive, fs->win, sector, 1) != RES_OK)
+				return FR_DISK_ERR;
+			fs->winsect = sector;
+		}
+	}
+
+	return FR_OK;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Clean-up cached data                                                  */
+/*-----------------------------------------------------------------------*/
+#if !_FS_READONLY
+static
+FRESULT sync (	/* FR_OK: successful, FR_DISK_ERR: failed */
+	FATFS *fs	/* File system object */
+)
+{
+	FRESULT res;
+
+
+	res = move_window(fs, 0);
+	if (res == FR_OK) {
+		/* Update FSInfo sector if needed */
+		if (fs->fs_type == FS_FAT32 && fs->fsi_flag) {
+			fs->winsect = 0;
+			mem_set(fs->win, 0, 512);
+			ST_WORD(fs->win+BS_55AA, 0xAA55);
+			ST_DWORD(fs->win+FSI_LeadSig, 0x41615252);
+			ST_DWORD(fs->win+FSI_StrucSig, 0x61417272);
+			ST_DWORD(fs->win+FSI_Free_Count, fs->free_clust);
+			ST_DWORD(fs->win+FSI_Nxt_Free, fs->last_clust);
+			disk_write(fs->drive, fs->win, fs->fsi_sector, 1);
+			fs->fsi_flag = 0;
+		}
+		/* Make sure that no pending write process in the physical drive */
+		if (disk_ioctl(fs->drive, CTRL_SYNC, (void*)NULL) != RES_OK)
+			res = FR_DISK_ERR;
+	}
+
+	return res;
+}
+#endif
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Get a cluster status                                                  */
+/*-----------------------------------------------------------------------*/
+
+static
+DWORD get_cluster (	/* 0xFFFFFFFF:Disk error, 1:Interal error, Else:Cluster status */
+	FATFS *fs,		/* File system object */
+	DWORD clst		/* Cluster# to get the link information */
+)
+{
+	WORD wc, bc;
+	DWORD fsect;
+
+
+	if (clst < 2 || clst >= fs->max_clust)	/* Check cluster address range */
+		return 1;
+
+	fsect = fs->fatbase;
+	switch (fs->fs_type) {
+	case FS_FAT12 :
+		bc = (WORD)clst * 3 / 2;
+		if (move_window(fs, fsect + (bc / SS(fs)))) break;
+		wc = fs->win[bc & (SS(fs) - 1)]; bc++;
+		if (move_window(fs, fsect + (bc / SS(fs)))) break;
+		wc |= (WORD)fs->win[bc & (SS(fs) - 1)] << 8;
+		return (clst & 1) ? (wc >> 4) : (wc & 0xFFF);
+
+	case FS_FAT16 :
+		if (move_window(fs, fsect + (clst / (SS(fs) / 2)))) break;
+		return LD_WORD(&fs->win[((WORD)clst * 2) & (SS(fs) - 1)]);
+
+	case FS_FAT32 :
+		if (move_window(fs, fsect + (clst / (SS(fs) / 4)))) break;
+		return LD_DWORD(&fs->win[((WORD)clst * 4) & (SS(fs) - 1)]) & 0x0FFFFFFF;
+	}
+
+	return 0xFFFFFFFF;	/* An error occured at the disk I/O layer */
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Change a cluster status                                               */
+/*-----------------------------------------------------------------------*/
+#if !_FS_READONLY
+static
+FRESULT put_cluster (
+	FATFS *fs,		/* File system object */
+	DWORD clst,		/* Cluster# to be changed (must be 2 to fs->max_clust-1) */
+	DWORD val		/* New value to mark the cluster */
+)
+{
+	WORD bc;
+	BYTE *p;
+	DWORD fsect;
+	FRESULT res;
+
+
+	if (clst < 2 || clst >= fs->max_clust) {	/* Check cluster address range */
+		res = FR_INT_ERR;
+
+	} else {
+		fsect = fs->fatbase;
+		switch (fs->fs_type) {
+		case FS_FAT12 :
+			bc = (WORD)clst * 3 / 2;
+			res = move_window(fs, fsect + (bc / SS(fs)));
+			if (res != FR_OK) break;
+			p = &fs->win[bc & (SS(fs) - 1)];
+			*p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val;
+			bc++;
+			fs->wflag = 1;
+			res = move_window(fs, fsect + (bc / SS(fs)));
+			if (res != FR_OK) break;
+			p = &fs->win[bc & (SS(fs) - 1)];
+			*p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F));
+			break;
+
+		case FS_FAT16 :
+			res = move_window(fs, fsect + (clst / (SS(fs) / 2)));
+			if (res != FR_OK) break;
+			ST_WORD(&fs->win[((WORD)clst * 2) & (SS(fs) - 1)], (WORD)val);
+			break;
+
+		case FS_FAT32 :
+			res = move_window(fs, fsect + (clst / (SS(fs) / 4)));
+			if (res != FR_OK) break;
+			ST_DWORD(&fs->win[((WORD)clst * 4) & (SS(fs) - 1)], val);
+			break;
+
+		default :
+			res = FR_INT_ERR;
+		}
+		fs->wflag = 1;
+	}
+
+	return res;
+}
+#endif /* !_FS_READONLY */
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Remove a cluster chain                                                */
+/*-----------------------------------------------------------------------*/
+#if !_FS_READONLY
+static
+FRESULT remove_chain (
+	FATFS *fs,			/* File system object */
+	DWORD clst			/* Cluster# to remove chain from */
+)
+{
+	FRESULT res;
+	DWORD nxt;
+
+
+	if (clst < 2 || clst >= fs->max_clust) {	/* Check cluster address range */
+		res = FR_INT_ERR;
+
+	} else {
+		res = FR_OK;
+		while (clst < fs->max_clust) {			/* Not a last link? */
+			nxt = get_cluster(fs, clst);		/* Get cluster status */
+			if (nxt == 0) break;				/* Empty cluster? */
+			if (nxt == 1) { res = FR_INT_ERR; break; }	/* Internal error? */
+			if (nxt == 0xFFFFFFFF) { res = FR_DISK_ERR; break; }	/* Disk error? */
+			res = put_cluster(fs, clst, 0);		/* Mark the cluster "empty" */
+			if (res != FR_OK) break;
+			if (fs->free_clust != 0xFFFFFFFF) {	/* Update FSInfo */
+				fs->free_clust++;
+				fs->fsi_flag = 1;
+			}
+			clst = nxt;	/* Next cluster */
+		}
+	}
+
+	return res;
+}
+#endif
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Stretch or create a cluster chain                                     */
+/*-----------------------------------------------------------------------*/
+#if !_FS_READONLY
+static
+DWORD create_chain (	/* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */
+	FATFS *fs,			/* File system object */
+	DWORD clst			/* Cluster# to stretch. 0 means create a new chain. */
+)
+{
+	DWORD cs, ncl, scl, mcl;
+
+
+	mcl = fs->max_clust;
+	if (clst == 0) {		/* Create new chain */
+		scl = fs->last_clust;			/* Get suggested start point */
+		if (scl == 0 || scl >= mcl) scl = 1;
+	}
+	else {					/* Stretch existing chain */
+		cs = get_cluster(fs, clst);		/* Check the cluster status */
+		if (cs < 2) return 1;			/* It is an invalid cluster */
+		if (cs < mcl) return cs;		/* It is already followed by next cluster */
+		scl = clst;
+	}
+
+	ncl = scl;				/* Start cluster */
+	for (;;) {
+		ncl++;							/* Next cluster */
+		if (ncl >= mcl) {				/* Wrap around */
+			ncl = 2;
+			if (ncl > scl) return 0;	/* No free custer */
+		}
+		cs = get_cluster(fs, ncl);		/* Get the cluster status */
+		if (cs == 0) break;				/* Found a free cluster */
+		if (cs == 0xFFFFFFFF || cs == 1)/* An error occured */
+			return cs;
+		if (ncl == scl) return 0;		/* No free custer */
+	}
+
+	if (put_cluster(fs, ncl, 0x0FFFFFFF))	/* Mark the new cluster "in use" */
+		return 0xFFFFFFFF;
+	if (clst != 0) {						/* Link it to previous one if needed */
+		if (put_cluster(fs, clst, ncl))
+			return 0xFFFFFFFF;
+	}
+
+	fs->last_clust = ncl;				/* Update FSINFO */
+	if (fs->free_clust != 0xFFFFFFFF) {
+		fs->free_clust--;
+		fs->fsi_flag = 1;
+	}
+
+	return ncl;		/* Return new cluster number */
+}
+#endif /* !_FS_READONLY */
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Get sector# from cluster#                                             */
+/*-----------------------------------------------------------------------*/
+
+static
+DWORD clust2sect (	/* !=0: sector number, 0: failed - invalid cluster# */
+	FATFS *fs,		/* File system object */
+	DWORD clst		/* Cluster# to be converted */
+)
+{
+	clst -= 2;
+	if (clst >= (fs->max_clust - 2)) return 0;		/* Invalid cluster# */
+	return clst * fs->csize + fs->database;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Seek directory index                                                  */
+/*-----------------------------------------------------------------------*/
+
+static
+FRESULT dir_seek (
+	DIR *dj,		/* Pointer to directory object */
+	WORD idx		/* Directory index number */
+)
+{
+	DWORD clst;
+	WORD ic;
+
+
+	dj->index = idx;
+	clst = dj->sclust;
+	if (clst == 1 || clst >= dj->fs->max_clust)	/* Check start cluster range */
+		return FR_INT_ERR;
+
+	if (clst == 0) {	/* Static table */
+		if (idx >= dj->fs->n_rootdir)		/* Index is out of range */
+			return FR_INT_ERR;
+		dj->sect = dj->fs->dirbase + idx / (SS(dj->fs) / 32);
+	}
+	else {				/* Dynamic table */
+		ic = SS(dj->fs) / 32 * dj->fs->csize;	/* Indexes per cluster */
+		while (idx >= ic) {	/* Follow cluster chain */
+			clst = get_cluster(dj->fs, clst);			/* Get next cluster */
+			if (clst == 0xFFFFFFFF) return FR_DISK_ERR;	/* Disk error */
+			if (clst < 2 || clst >= dj->fs->max_clust)	/* Reached to end of table or int error */
+				return FR_INT_ERR;
+			idx -= ic;
+		}
+		dj->clust = clst;
+		dj->sect = clust2sect(dj->fs, clst) + idx / (SS(dj->fs) / 32);
+	}
+	dj->dir = dj->fs->win + (idx % (SS(dj->fs) / 32)) * 32;
+
+	return FR_OK;	/* Seek succeeded */
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Move directory index next                                             */
+/*-----------------------------------------------------------------------*/
+
+static
+FRESULT dir_next (	/* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT and could not streach */
+	DIR *dj,		/* Pointer to directory object */
+	BOOL streach	/* FALSE: Do not streach table, TRUE: Streach table if needed */
+)
+{
+	DWORD clst;
+	WORD i;
+
+
+	i = dj->index + 1;
+	if (!i || !dj->sect)	/* Report EOT when index has reached 65535 */
+		return FR_NO_FILE;
+
+	if (!(i % (SS(dj->fs) / 32))) {	/* Sector changed? */
+		dj->sect++;					/* Next sector */
+
+		if (dj->sclust == 0) {	/* Static table */
+			if (i >= dj->fs->n_rootdir)	/* Report EOT when end of table */
+				return FR_NO_FILE;
+		}
+		else {					/* Dynamic table */
+			if (((i / (SS(dj->fs) / 32)) & (dj->fs->csize - 1)) == 0) {	/* Cluster changed? */
+				clst = get_cluster(dj->fs, dj->clust);			/* Get next cluster */
+				if (clst <= 1) return FR_INT_ERR;
+				if (clst == 0xFFFFFFFF) return FR_DISK_ERR;
+				if (clst >= dj->fs->max_clust) {				/* When it reached end of dinamic table */
+#if !_FS_READONLY
+					BYTE c;
+					if (!streach) return FR_NO_FILE;			/* When do not streach, report EOT */
+					clst = create_chain(dj->fs, dj->clust);		/* Streach cluster chain */
+					if (clst == 0) return FR_DENIED;			/* No free cluster */
+					if (clst == 1) return FR_INT_ERR;
+					if (clst == 0xFFFFFFFF) return FR_DISK_ERR;
+					/* Clean-up streached table */
+					if (move_window(dj->fs, 0)) return FR_DISK_ERR;	/* Flush active window */
+					mem_set(dj->fs->win, 0, SS(dj->fs));			/* Clear window buffer */
+					dj->fs->winsect = clust2sect(dj->fs, clst);	/* Cluster start sector */
+					for (c = 0; c < dj->fs->csize; c++) {		/* Fill the new cluster with 0 */
+						dj->fs->wflag = 1;
+						if (move_window(dj->fs, 0)) return FR_DISK_ERR;
+						dj->fs->winsect++;
+					}
+					dj->fs->winsect -= c;						/* Rewind window address */
+#else
+					return FR_NO_FILE;			/* Report EOT */
+#endif
+				}
+				dj->clust = clst;				/* Initialize data for new cluster */
+				dj->sect = clust2sect(dj->fs, clst);
+			}
+		}
+	}
+
+	dj->index = i;
+	dj->dir = dj->fs->win + (i % (SS(dj->fs) / 32)) * 32;
+
+	return FR_OK;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Test/Pick/Fit an LFN segment from/to directory entry                  */
+/*-----------------------------------------------------------------------*/
+#if _USE_LFN
+static
+const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30};	/* Offset of LFN chars in the directory entry */
+
+
+static
+BOOL test_lfn (			/* TRUE:Matched, FALSE:Not matched */
+	WCHAR *lfnbuf,		/* Pointer to the LFN to be compared */
+	BYTE *dir			/* Pointer to the directory entry containing a part of LFN */
+)
+{
+	int i, s;
+	WCHAR wc1, wc2;
+
+
+	i = ((dir[LDIR_Ord] & 0xBF) - 1) * 13;	/* Offset in the LFN buffer */
+	s = 0;
+	do {
+		if (i >= _MAX_LFN) return FALSE;	/* Out of buffer range? */
+		wc1 = LD_WORD(dir+LfnOfs[s]);		/* Get both characters to compare */
+		wc2 = lfnbuf[i++];
+		if (IsLower(wc1)) wc1 -= 0x20;		/* Compare it (ignore case) */
+		if (IsLower(wc2)) wc2 -= 0x20;
+		if (wc1 != wc2) return FALSE;
+	} while (++s < 13 && wc1);				/* Repeat until last char or a NUL char is processed */
+
+	return TRUE;							/* The LFN entry matched */
+}
+
+
+
+static
+BOOL pick_lfn (			/* TRUE:Succeeded, FALSE:Buffer overflow */
+	WCHAR *lfnbuf,		/* Pointer to the Unicode-LFN buffer */
+	BYTE *dir			/* Pointer to the directory entry */
+)
+{
+	int i, s;
+	WCHAR wchr;
+
+
+	i = ((dir[LDIR_Ord] & 0xBF) - 1) * 13;	/* Offset in the LFN buffer */
+	s = 0;
+	do {
+		wchr = LD_WORD(dir+LfnOfs[s]);		/* Get an LFN char */
+		if (!wchr) break;					/* End of LFN? */
+		if (i >= _MAX_LFN) return FALSE;	/* Buffer overflow */
+		lfnbuf[i++] = wchr;					/* Store it */
+	} while (++s < 13);						/* Repeat until last char is copied */
+	if (dir[LDIR_Ord] & 0x40) lfnbuf[i] = 0;	/* Put terminator if last LFN entry */
+
+	return TRUE;
+}
+
+
+#if !_FS_READONLY
+static
+void fit_lfn (
+	const WCHAR *lfnbuf,	/* Pointer to the LFN buffer */
+	BYTE *dir,				/* Pointer to the directory entry */
+	BYTE ord,				/* LFN order (1-20) */
+	BYTE sum				/* SFN sum */
+)
+{
+	int i, s;
+	WCHAR wchr;
+
+
+	dir[LDIR_Chksum] = sum;			/* Set check sum */
+	dir[LDIR_Attr] = AM_LFN;		/* Set attribute. LFN entry */
+	dir[LDIR_Type] = 0;
+	ST_WORD(dir+LDIR_FstClusLO, 0);
+
+	i = (ord - 1) * 13;				/* Offset in the LFN buffer */
+	s = wchr = 0;
+	do {
+		if (wchr != 0xFFFF) wchr = lfnbuf[i++];	/* Get an effective char */
+		ST_WORD(dir+LfnOfs[s], wchr);	/* Put it */
+		if (!wchr) wchr = 0xFFFF;	/* Padding chars following last char */
+	} while (++s < 13);
+	if (wchr == 0xFFFF || !lfnbuf[i]) ord |= 0x40;/* Bottom LFN part is the start of LFN sequence */
+	dir[LDIR_Ord] = ord;			/* Set the LFN order */
+}
+
+#endif
+#endif
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Create numbered name                                                  */
+/*-----------------------------------------------------------------------*/
+#if _USE_LFN
+void gen_numname (
+	BYTE *dst,			/* Pointer to genartated SFN */
+	const BYTE *src,	/* Pointer to source SFN to be modified */
+	const WCHAR *lfn,	/* Pointer to LFN */
+	WORD num			/* Sequense number */
+)
+{
+	char ns[8];
+	int i, j;
+
+
+	mem_cpy(dst, src, 11);
+
+	if (num > 5) {	/* On many collisions, generate a hash number instead of sequencial number */
+		do num = (num >> 1) + (num << 15) + (WORD)*lfn++; while (*lfn);
+	}
+
+	/* itoa */
+	i = 7;
+	do {
+		ns[i--] = (num % 10) + '0';
+		num /= 10;
+	} while (num);
+	ns[i] = '~';
+
+	/* Append the number */
+	for (j = 0; j < i && dst[j] != ' '; j++) {
+		if (IsDBCS1(dst[j])) {
+			if (j == i - 1) break;
+			j++;
+		}
+	}
+	do {
+		dst[j++] = (i < 8) ? ns[i++] : ' ';
+	} while (j < 8);
+}
+#endif
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Calculate sum of an SFN                                               */
+/*-----------------------------------------------------------------------*/
+#if _USE_LFN
+static
+BYTE sum_sfn (
+	const BYTE *dir		/* Ptr to directory entry */
+)
+{
+	BYTE sum = 0;
+	int n = 11;
+
+	do sum = (sum >> 1) + (sum << 7) + *dir++; while (--n);
+	return sum;
+}
+#endif
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Find an object in the directory                                       */
+/*-----------------------------------------------------------------------*/
+
+static
+FRESULT dir_find (
+	DIR *dj			/* Pointer to the directory object linked to the file name */
+)
+{
+	FRESULT res;
+	BYTE a, c, lfen, ord, sum, *dir;
+
+
+	res = dir_seek(dj, 0);			/* Rewind directory object */
+	if (res != FR_OK) return res;
+
+	ord = sum = 0xFF; lfen = *(dj->fn+11) & 1;
+	do {
+		res = move_window(dj->fs, dj->sect);
+		if (res != FR_OK) break;
+		dir = dj->dir;					/* Ptr to the directory entry of current index */
+		c = dir[DIR_Name];
+		if (c == 0) { res = FR_NO_FILE; break; }	/* Reached to end of table */
+		a = dir[DIR_Attr] & AM_MASK;
+#if _USE_LFN	/* LFN configuration */
+		if (c == 0xE5 || c == '.' || ((a & AM_VOL) && a != AM_LFN)) {	/* An entry without valid data */
+			ord = 0xFF;
+		} else {
+			if (a == AM_LFN) {			/* An LFN entry is found */
+				if (dj->lfn) {
+					if (c & 0x40) {		/* Is it start of LFN sequence? */
+						sum = dir[LDIR_Chksum];
+						c &= 0xBF; ord = c;		/* LFN start order */
+						dj->lfn_idx = dj->index;
+					}
+					/* Check LFN validity. Compare LFN if it is out of 8.3 format */
+					ord = (c == ord && sum == dir[LDIR_Chksum] && (!lfen || test_lfn(dj->lfn, dir))) ? ord - 1 : 0xFF;
+				}
+			} else {					/* An SFN entry is found */
+				if (ord || sum != sum_sfn(dir)) {	/* Did not LFN match? */
+					dj->lfn_idx = 0xFFFF;
+					ord = 0xFF;
+				}
+				if (lfen) {				/* Match LFN if it is out of 8.3 format */
+					if (ord == 0) break;
+				} else {				/* Match SFN if LFN is in 8.3 format */
+					if (!mem_cmp(dir, dj->fn, 11)) break;
+				}
+			}
+		}
+#else	/* Non LFN configuration */
+		if (c != 0xE5 && c != '.' && !(a & AM_VOL) && !mem_cmp(dir, dj->fn, 11)) /* Is it a valid entry? */
+			break;
+#endif
+		res = dir_next(dj, FALSE);				/* Next entry */
+	} while (res == FR_OK);
+
+	return res;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Read an object from the directory                                     */
+/*-----------------------------------------------------------------------*/
+#if _FS_MINIMIZE <= 2
+static
+FRESULT dir_read (
+	DIR *dj			/* Pointer to the directory object to store read object name */
+)
+{
+	FRESULT res;
+	BYTE a, c, ord, sum, *dir;
+
+
+	ord = sum = 0xFF;
+	res = FR_NO_FILE;
+	while (dj->sect) {
+		res = move_window(dj->fs, dj->sect);
+		if (res != FR_OK) break;
+		dir = dj->dir;					/* Ptr to the directory entry of current index */
+		c = dir[DIR_Name];
+		if (c == 0) { res = FR_NO_FILE; break; }	/* Reached to end of table */
+		a = dir[DIR_Attr] & AM_MASK;
+#if _USE_LFN	/* LFN configuration */
+		if (c == 0xE5 || c == '.' || ((a & AM_VOL) && a != AM_LFN)) {	/* An entry without valid data */
+			ord = 0xFF;
+		} else {
+			if (a == AM_LFN) {			/* An LFN entry is found */
+				if (c & 0x40) {			/* Is it start of LFN sequence? */
+					sum = dir[LDIR_Chksum];
+					c &= 0xBF; ord = c;
+					dj->lfn_idx = dj->index;
+				}
+				/* Check LFN validity and capture it */
+				ord = (c == ord && sum == dir[LDIR_Chksum] && pick_lfn(dj->lfn, dir)) ? ord - 1 : 0xFF;
+			} else {					/* An SFN entry is found */
+				if (ord || sum != sum_sfn(dir))	/* Is there a valid LFN entry? */
+					dj->lfn_idx = 0xFFFF;		/* No LFN. */
+				break;
+			}
+		}
+#else	/* Non LFN configuration */
+		if (c != 0xE5 && c != '.' && !(a & AM_VOL))	/* Is it a valid entry? */
+			break;
+#endif
+		res = dir_next(dj, FALSE);				/* Next entry */
+		if (res != FR_OK) break;
+	}
+
+	if (res != FR_OK) dj->sect = 0;
+
+	return res;
+}
+#endif
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Register an object to the directory                                   */
+/*-----------------------------------------------------------------------*/
+#if !_FS_READONLY
+static
+FRESULT dir_register (	/* FR_OK:Successful, FR_DENIED:No free entry or too many SFN collision, FR_DISK_ERR:Disk error */
+	DIR *dj				/* Target directory with object name to be created */
+)
+{
+	FRESULT res;
+	BYTE c, *dir;
+
+#if _USE_LFN	/* LFN configuration */
+	WORD n, ne, is;
+	BYTE sn[12], *fn, sum;
+	WCHAR *lfn;
+
+	fn = dj->fn; lfn = dj->lfn;
+	mem_cpy(sn, fn, 12);
+	if (sn[11] & 1) {		/* When LFN is out of 8.3 format, generate a numbered name */
+		fn[11] = 0; dj->lfn = NULL;			/* Find only SFN */
+		for (n = 1; n < 100; n++) {
+			gen_numname(fn, sn, lfn, n);	/* Generate a numbered name */
+			res = dir_find(dj);				/* Check if the name collides with existing SFN */
+			if (res != FR_OK) break;
+		}
+		if (n == 100) return FR_DENIED;		/* Abort if too many collisions */
+		if (res != FR_NO_FILE) return res;	/* Abort if the result is other than 'not collided' */
+		fn[11] = sn[11]; dj->lfn = lfn;
+	}
+	if (sn[11] & 2) {		/* When eliminate LFN, reserve only an SFN entry. */
+		ne = 1;
+	} else {				/* Otherwise reserve an SFN + LFN entries. */
+		for (ne = 0; lfn[ne]; ne++) ;
+		ne = (ne + 25) / 13;
+	}
+
+	/* Reserve contiguous entries */
+	res = dir_seek(dj, 0);
+	if (res != FR_OK) return res;
+	n = is = 0;
+	do {
+		res = move_window(dj->fs, dj->sect);
+		if (res != FR_OK) break;
+		c = *dj->dir;	/* Check the entry status */
+		if (c == 0xE5 || c == 0) {	/* Is it a blank entry? */
+			if (n == 0) is = dj->index;	/* First index of the contigulus entry */
+			if (++n == ne) break;	/* A contiguous entry that requiered count is found */
+		} else {
+			n = 0;					/* Not a blank entry. Restart to search */
+		}
+		res = dir_next(dj, TRUE);	/* Next entry with table streach */
+	} while (res == FR_OK);
+
+	if (res == FR_OK && ne > 1) {	/* Initialize LFN entry if needed */
+		res = dir_seek(dj, is);
+		if (res == FR_OK) {
+			sum = sum_sfn(dj->fn);	/* Sum of the SFN tied to the LFN */
+			ne--;
+			do {					/* Store LFN entries in bottom first */
+				res = move_window(dj->fs, dj->sect);
+				if (res != FR_OK) break;
+				fit_lfn(dj->lfn, dj->dir, (BYTE)ne, sum);
+				dj->fs->wflag = 1;
+				res = dir_next(dj, FALSE);	/* Next entry */
+			} while (res == FR_OK && --ne);
+		}
+	}
+
+#else	/* Non LFN configuration */
+	res = dir_seek(dj, 0);
+	if (res == FR_OK) {
+		do {	/* Find a blank entry for the SFN */
+			res = move_window(dj->fs, dj->sect);
+			if (res != FR_OK) break;
+			c = *dj->dir;
+			if (c == 0xE5 || c == 0) break;	/* Is it a blank entry? */
+			res = dir_next(dj, TRUE);		/* Next entry with table streach */
+		} while (res == FR_OK);
+	}
+#endif
+
+	if (res == FR_OK) {		/* Initialize the SFN entry */
+		res = move_window(dj->fs, dj->sect);
+		if (res == FR_OK) {
+			dir = dj->dir;
+			mem_set(dir, 0, 32);			/* Clean the entry */
+			mem_cpy(dir, dj->fn, 11);	/* Put SFN */
+			dir[DIR_NTres] = *(dj->fn+11) & 0x18;	/* Put NT flag */
+			dj->fs->wflag = 1;
+		}
+	}
+
+	return res;
+}
+#endif /* !_FS_READONLY */
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Remove an object from the directory                                   */
+/*-----------------------------------------------------------------------*/
+#if !_FS_READONLY && !_FS_MINIMIZE
+static
+FRESULT dir_remove (	/* FR_OK: Successful, FR_DISK_ERR: A disk error */
+	DIR *dj				/* Directory object pointing the entry to be removed */
+)
+{
+	FRESULT res;
+
+#if _USE_LFN	/* LFN configuration */
+	WORD i;
+
+	i = dj->index;	/* SFN index */
+	res = dir_seek(dj, (WORD)((dj->lfn_idx == 0xFFFF) ? i : dj->lfn_idx));	/* Goto the SFN or top of the LFN entries */
+	if (res == FR_OK) {
+		do {
+			res = move_window(dj->fs, dj->sect);
+			if (res != FR_OK) break;
+			*dj->dir = 0xE5;				/* Mark the entry "deleted" */
+			dj->fs->wflag = 1;
+			if (dj->index >= i) break;		/* When SFN is deleted, all entries of the object is deleted. */
+			res = dir_next(dj, FALSE);		/* Next entry */
+		} while (res == FR_OK);
+		if (res == FR_NO_FILE) res = FR_INT_ERR;
+	}
+
+#else			/* Non LFN configuration */
+	res = dir_seek(dj, dj->index);
+	if (res == FR_OK) {
+		res = move_window(dj->fs, dj->sect);
+		if (res == FR_OK) {
+			*dj->dir = 0xE5;				/* Mark the entry "deleted" */
+			dj->fs->wflag = 1;
+		}
+	}
+#endif
+
+	return res;
+}
+#endif /* !_FS_READONLY */
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Pick a segment and create the object name in directory form           */
+/*-----------------------------------------------------------------------*/
+
+static
+FRESULT create_name (
+	DIR *dj,			/* Pointer to the directory object */
+	const char **path	/* Pointer to pointer to the segment in the path string */
+)
+{
+#if _USE_LFN
+	BYTE c, b, cf, *sfn;
+	WCHAR w, *lfn;
+	int i, ni, si, di;
+	const char *p;
+
+	/* Create LFN in Unicode */
+	si = di = 0;
+	p = *path;
+	lfn = dj->lfn;
+	for (;;) {
+		w = (BYTE)p[si++];				/* Get a character */
+		if (w < ' ' || w == '/' || w == '\\') break;	/* Break on end of segment */
+		if (IsDBCS1(w)) {				/* If it is DBC 1st byte */
+			c = p[si++];				/* Get 2nd byte */
+			if (!IsDBCS2(c))			/* Reject invalid DBC */
+				return FR_INVALID_NAME;
+			w = (w << 8) + c;
+		} else {
+			if (chk_chr("\"*:<>\?|\x7F", w))	/* Reject unallowable chars for LFN */
+				return FR_INVALID_NAME;
+		}
+		w = ff_convert(w, 1);			/* Convert OEM to Unicode, store it */
+		if (!w || di >= _MAX_LFN)		/* Reject invalid code or too long name */
+			return FR_INVALID_NAME;
+		lfn[di++] = w;
+	}
+	*path = &p[si];						/* Rerurn pointer to the next segment */
+	cf = (w < ' ') ? 4 : 0;				/* Set last segment flag if end of path */
+
+	while (di) {						/* Strip trailing spaces and dots */
+		w = lfn[di - 1];
+		if (w != ' ' && w != '.') break;
+		di--;
+	}
+	if (!di) return FR_INVALID_NAME;	/* Reject null string */
+
+	lfn[di] = 0;						/* LFN is created */
+
+	/* Create SFN in directory form */
+	sfn = dj->fn;
+	mem_set(sfn, ' ', 11);
+	for (si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++) ;	/* Strip leading spaces and dots */
+	if (si) cf |= 1;
+	while (di && lfn[di - 1] != '.') di--;	/* Find extension (di<=si: no extension) */
+
+	b = i = 0; ni = 8;
+	for (;;) {
+		w = lfn[si++];					/* Get an LFN char */
+		if (w == 0) break;				/* Break when enf of the LFN */
+		if (w == ' ' || (w == '.' && si != di)) {	/* Remove spaces and dots */
+			cf |= 1; continue;
+		}
+		if (i >= ni || si == di) {		/* Here is extension or end of SFN */
+			if (ni == 11) {				/* Extension is longer than 3 bytes */
+				cf |= 1; break;
+			}
+			if (si != di) cf |= 1;		/* File name is longer than 8 bytes */
+			if (si > di) break;			/* No extension */
+			si = di; i = 8; ni = 11;	/* Enter extension section */
+			b <<= 2; continue;
+		}
+		w = ff_convert(w, 0);			/* Unicode -> OEM code */
+		if (w >= 0x80) cf |= 0x20;		/* If there is any extended char, force create an LFN */
+		if (w >= 0x100) {				/* Double byte char */
+			if (i >= ni - 1) {
+				cf |= 1; i = ni; continue;
+			}
+			sfn[i++] = (BYTE)(w >> 8);
+		} else {						/* Single byte char */
+			if (chk_chr("+,;[=]", w)) {	/* Replace unallowable chars for SFN */
+				w = '_'; cf |= 1;
+			} else {
+				if (IsUpper(w)) {		/* Large capital */
+					b |= 2;
+				} else {
+					if (IsLower(w)) {	/* Small capital */
+						b |= 1; w -= 0x20;
+					}
+				}
+			}
+		}
+		sfn[i++] = (BYTE)w;
+	}
+	if (sfn[0] == 0xE5) sfn[0] = 0x05;	/* When first char collides with 0xE5, replace it with 0x05 */
+
+	if (ni == 8) b <<= 2;
+	if ((cf & 0x21) == 0) {	/* When LFN is in 8.3 format without extended char, NT flags are created */
+		if ((b & 0x03) == 0x01) cf |= 0x10;	/* NT flag (Extension has only small capital) */
+		if ((b & 0x0C) == 0x04) cf |= 0x08;	/* NT flag (Filename has only small capital) */
+		if ((b & 0x0C) != 0x0C && (b & 0x03) != 0x03) cf |= 2;	/* Eliminate LFN when non composite capitals */
+	}
+
+	sfn[11] = cf;		/* SFN is created */
+
+#else
+	BYTE c, d, b, *sfn;
+	int ni, si, i;
+	const char *p;
+
+	/* Create file name in directory form */
+	sfn = dj->fn;
+	mem_set(sfn, ' ', 11);
+	si = i = b = 0; ni = 8;
+	p = *path;
+	for (;;) {
+		c = p[si++];
+		if (c < ' ' || c == '/' || c == '\\') break;	/* Break on end of segment */
+		if (c == '.' || i >= ni) {
+			if (ni != 8 || c != '.') return FR_INVALID_NAME;
+			i = 8; ni = 11;
+			b <<= 2; continue;
+		}
+		if (c >= 0x80) b |= 3;			/* If there is any extended char, eliminate NT flag */
+		if (IsDBCS1(c)) {				/* If it is DBC 1st byte */
+			d = p[si++];				/* Get 2nd byte */
+			if (!IsDBCS2(d) || i >= ni - 1)	/* Reject invalid DBC */
+				return FR_INVALID_NAME;
+			sfn[i++] = c;
+			sfn[i++] = d;
+		} else {
+			if (chk_chr(" +,;[=]\"*:<>\?|\x7F", c))	/* Reject unallowable chrs for SFN */
+				return FR_INVALID_NAME;
+			if (IsUpper(c)) {
+				b |= 2;
+			} else {
+				if (IsLower(c)) {
+					b |= 1; c -= 0x20;
+				}
+			}
+			sfn[i++] = c;
+		}
+	}
+	*path = &p[si];						/* Rerurn pointer to the next segment */
+	c = (c < ' ') ? 4 : 0;				/* Set last segment flag if end of path */
+
+	if (!i) return FR_INVALID_NAME;		/* Reject null string */
+	if (sfn[0] == 0xE5) sfn[0] = 0x05;	/* When first char collides with 0xE5, replace it with 0x05 */
+
+	if (ni == 8) b <<= 2;
+	if ((b & 0x03) == 0x01) c |= 0x10;	/* NT flag (Extension has only small capital) */
+	if ((b & 0x0C) == 0x04) c |= 0x08;	/* NT flag (Filename has only small capital) */
+
+	sfn[11] = c;		/* Store NT flag, File name is created */
+#endif
+
+	return FR_OK;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Get file information from directory entry                             */
+/*-----------------------------------------------------------------------*/
+#if _FS_MINIMIZE <= 1
+static
+void get_fileinfo (		/* No return code */
+	DIR *dj,			/* Pointer to the directory object */
+	FILINFO *fno	 	/* Pointer to store the file information */
+)
+{
+	int i;
+	BYTE c, nt, *dir;
+	char *p;
+
+
+	p = fno->fname;
+	if (dj->sect) {
+		dir = dj->dir;
+		nt = dir[DIR_NTres];		/* NT flag */
+		for (i = 0; i < 8; i++) {	/* Copy file name body */
+			c = dir[i];
+			if (c == ' ') break;
+			if (c == 0x05) c = 0xE5;
+			if ((nt & 0x08) && IsUpper(c)) c += 0x20;
+			*p++ = c;
+		}
+		if (dir[8] != ' ') {		/* Copy file name extension */
+			*p++ = '.';
+			for (i = 8; i < 11; i++) {
+				c = dir[i];
+				if (c == ' ') break;
+				if ((nt & 0x10) && IsUpper(c)) c += 0x20;
+				*p++ = c;
+			}
+		}
+		fno->fattrib = dir[DIR_Attr];				/* Attribute */
+		fno->fsize = LD_DWORD(dir+DIR_FileSize);	/* Size */
+		fno->fdate = LD_WORD(dir+DIR_WrtDate);		/* Date */
+		fno->ftime = LD_WORD(dir+DIR_WrtTime);		/* Time */
+	}
+	*p = 0;
+
+#if _USE_LFN
+	p = fno->lfname;
+	if (p) {
+		WCHAR wchr, *lfn;
+
+		i = 0;
+		if (dj->sect && dj->lfn_idx != 0xFFFF) {/* Get LFN if available */
+			lfn = dj->lfn;
+			while ((wchr = *lfn++) != 0) {		/* Get an LFN char */
+				wchr = ff_convert(wchr, 0);		/* Unicode -> OEM code */
+				if (!wchr) { i = 0; break; }	/* Conversion error, no LFN */
+				if (_DF1S && wchr >= 0x100)		/* Put 1st byte if it is a DBC */
+					p[i++] = (char)(wchr >> 8);
+				p[i++] = (char)wchr;
+				if (i >= fno->lfsize) { i = 0; break; }	/* Buffer overrun, no LFN */
+			}
+		}
+		p[i] = 0;	/* Terminator */
+	}
+#endif
+}
+#endif /* _FS_MINIMIZE <= 1 */
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Follow a file path                                                    */
+/*-----------------------------------------------------------------------*/
+
+static
+FRESULT follow_path (	/* FR_OK(0): successful, !=0: error code */
+	DIR *dj,			/* Directory object to return last directory and found object */
+	const char *path	/* Full-path string to find a file or directory */
+)
+{
+	FRESULT res;
+	BYTE *dir, last;
+
+
+	if (*path == '/' || *path == '\\' ) path++;	/* Strip heading separator */
+
+	dj->sclust =						/* Set start directory (root dir) */
+		(dj->fs->fs_type == FS_FAT32) ? dj->fs->dirbase : 0;
+
+	if ((BYTE)*path < ' ') {			/* Null path means the root directory */
+		res = dir_seek(dj, 0);
+		dj->dir = NULL;
+
+	} else {							/* Follow path */
+		for (;;) {
+			res = create_name(dj, &path);	/* Get a segment */
+			if (res != FR_OK) break;
+			res = dir_find(dj);				/* Find it */
+			last = *(dj->fn+11) & 4;
+			if (res != FR_OK) {				/* Could not find the object */
+				if (res == FR_NO_FILE && !last)
+					res = FR_NO_PATH;
+				break;
+			}
+			if (last) break;				/* Last segment match. Function completed. */
+			dir = dj->dir;					/* There is next segment. Follow the sub directory */
+			if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */
+				res = FR_NO_PATH; break;
+			}
+			dj->sclust = ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | LD_WORD(dir+DIR_FstClusLO);
+		}
+	}
+
+	return res;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Load boot record and check if it is an FAT boot record                */
+/*-----------------------------------------------------------------------*/
+
+static
+BYTE check_fs (	/* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record, 3:Error */
+	FATFS *fs,	/* File system object */
+	DWORD sect	/* Sector# (lba) to check if it is an FAT boot record or not */
+)
+{
+	if (disk_read(fs->drive, fs->win, sect, 1) != RES_OK)	/* Load boot record */
+		return 3;
+	if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55)				/* Check record signature (always placed at offset 510 even if the sector size is >512) */
+		return 2;
+
+	if (!mem_cmp(&fs->win[BS_FilSysType], "FAT", 3))		/* Check FAT signature */
+		return 0;
+	if (!mem_cmp(&fs->win[BS_FilSysType32], "FAT32", 5) && !(fs->win[BPB_ExtFlags] & 0x80))
+		return 0;
+
+	return 1;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Make sure that the file system is valid                               */
+/*-----------------------------------------------------------------------*/
+
+static
+FRESULT auto_mount (	/* FR_OK(0): successful, !=0: any error occured */
+	const char **path,	/* Pointer to pointer to the path name (drive number) */
+	FATFS **rfs,		/* Pointer to pointer to the found file system object */
+	BYTE chk_wp			/* !=0: Check media write protection for write access */
+)
+{
+	FRESULT res;
+	BYTE vol, fmt, *tbl;
+	DSTATUS stat;
+	DWORD bsect, fsize, tsect, mclst;
+	const char *p = *path;
+	FATFS *fs;
+
+
+	/* Get logical drive number from the path name */
+	vol = p[0] - '0';			/* Is there a drive number? */
+	if (vol <= 9 && p[1] == ':') {
+		p += 2;					/* Found a drive number, get and strip it */
+		*path = p;				/* Return pointer to the path name */
+	} else {
+		vol = 0;				/* No drive number is given, use drive number 0 as default */
+	}
+
+	/* Check if the logical drive number is valid or not */
+	if (vol >= _DRIVES) return FR_INVALID_DRIVE;	/* Is the drive number valid? */
+	*rfs = fs = FatFs[vol];					/* Returen pointer to the corresponding file system object */
+	if (!fs) return FR_NOT_ENABLED;			/* Is the file system object registered? */
+
+	ENTER_FF(fs);				/* Lock file system */
+
+	if (fs->fs_type) {						/* If the logical drive has been mounted */
+		stat = disk_status(fs->drive);
+		if (!(stat & STA_NOINIT)) {			/* and physical drive is kept initialized (has not been changed), */
+#if !_FS_READONLY
+			if (chk_wp && (stat & STA_PROTECT))	/* Check write protection if needed */
+				return FR_WRITE_PROTECTED;
+#endif
+			return FR_OK;					/* The file system object is valid */
+		}
+	}
+
+	/* The logical drive must be re-mounted. Following code attempts to mount the volume */
+
+	fs->fs_type = 0;					/* Clear the file system object */
+	fs->drive = LD2PD(vol);				/* Bind the logical drive and a physical drive */
+	stat = disk_initialize(fs->drive);	/* Initialize low level disk I/O layer */
+	if (stat & STA_NOINIT)				/* Check if the drive is ready */
+		return FR_NOT_READY;
+#if _MAX_SS != 512						/* Get disk sector size if needed */
+	if (disk_ioctl(fs->drive, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS)
+		return FR_NO_FILESYSTEM;
+#endif
+#if !_FS_READONLY
+	if (chk_wp && (stat & STA_PROTECT))	/* Check write protection if needed */
+		return FR_WRITE_PROTECTED;
+#endif
+	/* Search FAT partition on the drive */
+	fmt = check_fs(fs, bsect = 0);		/* Check sector 0 as an SFD format */
+	if (fmt == 1) {						/* Not an FAT boot record, it may be patitioned */
+		/* Check a partition listed in top of the partition table */
+		tbl = &fs->win[MBR_Table + LD2PT(vol) * 16];	/* Partition table */
+		if (tbl[4]) {									/* Is the partition existing? */
+			bsect = LD_DWORD(&tbl[8]);					/* Partition offset in LBA */
+			fmt = check_fs(fs, bsect);					/* Check the partition */
+		}
+	}
+	if (fmt == 3) return FR_DISK_ERR;
+	if (fmt || LD_WORD(fs->win+BPB_BytsPerSec) != SS(fs))	/* No valid FAT patition is found */
+		return FR_NO_FILESYSTEM;
+
+	/* Initialize the file system object */
+	fsize = LD_WORD(fs->win+BPB_FATSz16);				/* Number of sectors per FAT */
+	if (!fsize) fsize = LD_DWORD(fs->win+BPB_FATSz32);
+	fs->sects_fat = fsize;
+	fs->n_fats = fs->win[BPB_NumFATs];					/* Number of FAT copies */
+	fsize *= fs->n_fats;								/* (Number of sectors in FAT area) */
+	fs->fatbase = bsect + LD_WORD(fs->win+BPB_RsvdSecCnt); /* FAT start sector (lba) */
+	fs->csize = fs->win[BPB_SecPerClus];				/* Number of sectors per cluster */
+	fs->n_rootdir = LD_WORD(fs->win+BPB_RootEntCnt);	/* Nmuber of root directory entries */
+	tsect = LD_WORD(fs->win+BPB_TotSec16);				/* Number of sectors on the file system */
+	if (!tsect) tsect = LD_DWORD(fs->win+BPB_TotSec32);
+	fs->max_clust = mclst = (tsect						/* Last cluster# + 1 */
+		- LD_WORD(fs->win+BPB_RsvdSecCnt) - fsize - fs->n_rootdir / (SS(fs)/32)
+		) / fs->csize + 2;
+
+	fmt = FS_FAT12;										/* Determine the FAT sub type */
+	if (mclst >= 0xFF7) fmt = FS_FAT16;				/* Number of clusters >= 0xFF5 */
+	if (mclst >= 0xFFF7) fmt = FS_FAT32;			/* Number of clusters >= 0xFFF5 */
+
+	if (fmt == FS_FAT32)
+		fs->dirbase = LD_DWORD(fs->win+BPB_RootClus);	/* Root directory start cluster */
+	else
+		fs->dirbase = fs->fatbase + fsize;				/* Root directory start sector (lba) */
+	fs->database = fs->fatbase + fsize + fs->n_rootdir / (SS(fs)/32);	/* Data start sector (lba) */
+
+#if !_FS_READONLY
+	/* Initialize allocation information */
+	fs->free_clust = 0xFFFFFFFF;
+	fs->wflag = 0;
+	/* Get fsinfo if needed */
+	if (fmt == FS_FAT32) {
+		fs->fsi_sector = bsect + LD_WORD(fs->win+BPB_FSInfo);
+		fs->fsi_flag = 0;
+		if (disk_read(fs->drive, fs->win, fs->fsi_sector, 1) == RES_OK &&
+			LD_WORD(fs->win+BS_55AA) == 0xAA55 &&
+			LD_DWORD(fs->win+FSI_LeadSig) == 0x41615252 &&
+			LD_DWORD(fs->win+FSI_StrucSig) == 0x61417272) {
+			fs->last_clust = LD_DWORD(fs->win+FSI_Nxt_Free);
+			fs->free_clust = LD_DWORD(fs->win+FSI_Free_Count);
+		}
+	}
+#endif
+	fs->winsect = 0;
+	fs->fs_type = fmt;			/* FAT syb-type */
+	fs->id = ++Fsid;			/* File system mount ID */
+	res = FR_OK;
+
+	return res;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Check if the file/dir object is valid or not                          */
+/*-----------------------------------------------------------------------*/
+
+static
+FRESULT validate (	/* FR_OK(0): The object is valid, !=0: Invalid */
+	FATFS *fs,		/* Pointer to the file system object */
+	WORD id			/* Member id of the target object to be checked */
+)
+{
+	if (!fs || !fs->fs_type || fs->id != id)
+		return FR_INVALID_OBJECT;
+
+	ENTER_FF(fs);		/* Lock file system */
+
+	if (disk_status(fs->drive) & STA_NOINIT)
+		return FR_NOT_READY;
+
+	return FR_OK;
+}
+
+
+
+
+/*--------------------------------------------------------------------------
+
+   Public Functions
+
+--------------------------------------------------------------------------*/
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Mount/Unmount a Locical Drive                                         */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_mount (
+	BYTE vol,		/* Logical drive number to be mounted/unmounted */
+	FATFS *fs		/* Pointer to new file system object (NULL for unmount)*/
+)
+{
+	FATFS *rfs;
+
+
+	if (vol >= _DRIVES)				/* Check if the drive number is valid */
+		return FR_INVALID_DRIVE;
+	rfs = FatFs[vol];				/* Get current state */
+
+	if (rfs) {
+#if _FS_REENTRANT					/* Discard sync object of the current volume */
+		if (!ff_del_syncobj(fs->sobj)) return FR_INT_ERR;
+#endif
+		rfs->fs_type = 0;			/* Clear old fs object */
+	}
+
+	if (fs) {
+		fs->fs_type = 0;			/* Clear new fs object */
+#if _FS_REENTRANT					/* Create sync object for the new volume */
+		if (!ff_cre_syncobj(vol, &fs->sobj)) return FR_INT_ERR;
+#endif
+	}
+	FatFs[vol] = fs;				/* Register new fs object */
+
+	return FR_OK;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Open or Create a File                                                 */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_open (
+	FIL *fp,			/* Pointer to the blank file object */
+	const char *path,	/* Pointer to the file name */
+	BYTE mode			/* Access mode and file open mode flags */
+)
+{
+	FRESULT res;
+	DIR dj;
+	NAMEBUF(sfn, lfn);
+	BYTE *dir;
+
+
+	fp->fs = NULL;		/* Clear file object */
+#if !_FS_READONLY
+	mode &= (FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW);
+	res = auto_mount(&path, &dj.fs, (BYTE)(mode & (FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)));
+#else
+	mode &= FA_READ;
+	res = auto_mount(&path, &dj.fs, 0);
+#endif
+	if (res != FR_OK) LEAVE_FF(dj.fs, res);
+	INITBUF(dj, sfn, lfn);
+	res = follow_path(&dj, path);	/* Follow the file path */
+
+#if !_FS_READONLY
+	/* Create or Open a file */
+	if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) {
+		DWORD ps, cl;
+
+		if (res != FR_OK) {		/* No file, create new */
+			if (res == FR_NO_FILE)
+				res = dir_register(&dj);
+			if (res != FR_OK) LEAVE_FF(dj.fs, res);
+			mode |= FA_CREATE_ALWAYS;
+			dir = dj.dir;
+		}
+		else {					/* Any object is already existing */
+			if (mode & FA_CREATE_NEW)			/* Cannot create new */
+				LEAVE_FF(dj.fs, FR_EXIST);
+			dir = dj.dir;
+			if (!dir || (dir[DIR_Attr] & (AM_RDO | AM_DIR)))	/* Cannot overwrite it (R/O or DIR) */
+				LEAVE_FF(dj.fs, FR_DENIED);
+			if (mode & FA_CREATE_ALWAYS) {		/* Resize it to zero if needed */
+				cl = ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | LD_WORD(dir+DIR_FstClusLO);	/* Get start cluster */
+				ST_WORD(dir+DIR_FstClusHI, 0);	/* cluster = 0 */
+				ST_WORD(dir+DIR_FstClusLO, 0);
+				ST_DWORD(dir+DIR_FileSize, 0);	/* size = 0 */
+				dj.fs->wflag = 1;
+				ps = dj.fs->winsect;			/* Remove the cluster chain */
+				if (cl) {
+					res = remove_chain(dj.fs, cl);
+					if (res) LEAVE_FF(dj.fs, res);
+					dj.fs->last_clust = cl - 1;	/* Reuse the cluster hole */
+				}
+				res = move_window(dj.fs, ps);
+				if (res != FR_OK) LEAVE_FF(dj.fs, res);
+			}
+		}
+		if (mode & FA_CREATE_ALWAYS) {
+			dir[DIR_Attr] = 0;					/* Reset attribute */
+			ps = get_fattime();
+			ST_DWORD(dir+DIR_CrtTime, ps);		/* Created time */
+			dj.fs->wflag = 1;
+			mode |= FA__WRITTEN;				/* Set file changed flag */
+		}
+	}
+	/* Open an existing file */
+	else {
+#endif /* !_FS_READONLY */
+		if (res != FR_OK) LEAVE_FF(dj.fs, res);	/* Follow failed */
+		dir = dj.dir;
+		if (!dir || (dir[DIR_Attr] & AM_DIR))	/* It is a directory */
+			LEAVE_FF(dj.fs, FR_NO_FILE);
+#if !_FS_READONLY
+		if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */
+			LEAVE_FF(dj.fs, FR_DENIED);
+	}
+	fp->dir_sect = dj.fs->winsect;		/* Pointer to the directory entry */
+	fp->dir_ptr = dj.dir;
+#endif
+	fp->flag = mode;					/* File access mode */
+	fp->org_clust =						/* File start cluster */
+		((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | LD_WORD(dir+DIR_FstClusLO);
+	fp->fsize = LD_DWORD(dir+DIR_FileSize);	/* File size */
+	fp->fptr = 0; fp->csect = 255;		/* File pointer */
+	fp->dsect = 0;
+	fp->fs = dj.fs; fp->id = dj.fs->id;	/* Owner file system object of the file */
+
+	LEAVE_FF(dj.fs, FR_OK);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Read File                                                             */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_read (
+	FIL *fp, 		/* Pointer to the file object */
+	void *buff,		/* Pointer to data buffer */
+	UINT btr,		/* Number of bytes to read */
+	UINT *br		/* Pointer to number of bytes read */
+)
+{
+	FRESULT res;
+	DWORD clst, sect, remain;
+	UINT rcnt, cc;
+	BYTE *rbuff = buff;
+
+
+	*br = 0;
+
+	res = validate(fp->fs, fp->id);					/* Check validity of the object */
+	if (res != FR_OK) LEAVE_FF(fp->fs, res);
+	if (fp->flag & FA__ERROR)						/* Check abort flag */
+		LEAVE_FF(fp->fs, FR_INT_ERR);
+	if (!(fp->flag & FA_READ)) 						/* Check access mode */
+		LEAVE_FF(fp->fs, FR_DENIED);
+	remain = fp->fsize - fp->fptr;
+	if (btr > remain) btr = (UINT)remain;			/* Truncate btr by remaining bytes */
+
+	for ( ;  btr;									/* Repeat until all data transferred */
+		rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) {
+		if ((fp->fptr % SS(fp->fs)) == 0) {			/* On the sector boundary? */
+			if (fp->csect >= fp->fs->csize) {		/* On the cluster boundary? */
+				clst = (fp->fptr == 0) ?			/* On the top of the file? */
+					fp->org_clust : get_cluster(fp->fs, fp->curr_clust);
+				if (clst <= 1) ABORT(fp->fs, FR_INT_ERR);
+				if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
+				fp->curr_clust = clst;				/* Update current cluster */
+				fp->csect = 0;						/* Reset sector offset in the cluster */
+			}
+			sect = clust2sect(fp->fs, fp->curr_clust);	/* Get current sector */
+			if (!sect) ABORT(fp->fs, FR_INT_ERR);
+			sect += fp->csect;
+			cc = btr / SS(fp->fs);					/* When remaining bytes >= sector size, */
+			if (cc) {								/* Read maximum contiguous sectors directly */
+				if (fp->csect + cc > fp->fs->csize)	/* Clip at cluster boundary */
+					cc = fp->fs->csize - fp->csect;
+				if (disk_read(fp->fs->drive, rbuff, sect, (BYTE)cc) != RES_OK)
+					ABORT(fp->fs, FR_DISK_ERR);
+				fp->csect += (BYTE)cc;				/* Next sector address in the cluster */
+				rcnt = SS(fp->fs) * cc;				/* Number of bytes transferred */
+				continue;
+			}
+#if !_FS_TINY
+#if !_FS_READONLY
+			if (fp->flag & FA__DIRTY) {			/* Write sector I/O buffer if needed */
+				if (disk_write(fp->fs->drive, fp->buf, fp->dsect, 1) != RES_OK)
+					ABORT(fp->fs, FR_DISK_ERR);
+				fp->flag &= (BYTE)~FA__DIRTY;
+			}
+#endif
+			if (fp->dsect != sect) {			/* Fill sector buffer with file data */
+				if (disk_read(fp->fs->drive, fp->buf, sect, 1) != RES_OK)
+					ABORT(fp->fs, FR_DISK_ERR);
+			}
+#endif
+			fp->dsect = sect;
+			fp->csect++;							/* Next sector address in the cluster */
+		}
+		rcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs));	/* Get partial sector data from sector buffer */
+		if (rcnt > btr) rcnt = btr;
+#if _FS_TINY
+		if (move_window(fp->fs, fp->dsect))			/* Move sector window */
+			ABORT(fp->fs, FR_DISK_ERR);
+		mem_cpy(rbuff, &fp->fs->win[fp->fptr % SS(fp->fs)], rcnt);	/* Pick partial sector */
+#else
+		mem_cpy(rbuff, &fp->buf[fp->fptr % SS(fp->fs)], rcnt);	/* Pick partial sector */
+#endif
+	}
+
+
+	LEAVE_FF(fp->fs, FR_OK);
+}
+
+
+
+
+#if !_FS_READONLY
+/*-----------------------------------------------------------------------*/
+/* Write File                                                            */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_write (
+	FIL *fp,			/* Pointer to the file object */
+	const void *buff,	/* Pointer to the data to be written */
+	UINT btw,			/* Number of bytes to write */
+	UINT *bw			/* Pointer to number of bytes written */
+)
+{
+	FRESULT res;
+	DWORD clst, sect;
+	UINT wcnt, cc;
+	const BYTE *wbuff = buff;
+
+
+	*bw = 0;
+
+	res = validate(fp->fs, fp->id);					/* Check validity of the object */
+	if (res != FR_OK) LEAVE_FF(fp->fs, res);
+	if (fp->flag & FA__ERROR)						/* Check abort flag */
+		LEAVE_FF(fp->fs, FR_INT_ERR);
+	if (!(fp->flag & FA_WRITE))						/* Check access mode */
+		LEAVE_FF(fp->fs, FR_DENIED);
+	if (fp->fsize + btw < fp->fsize) btw = 0;		/* File size cannot reach 4GB */
+
+	for ( ;  btw;									/* Repeat until all data transferred */
+		wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) {
+		if ((fp->fptr % SS(fp->fs)) == 0) {			/* On the sector boundary? */
+			if (fp->csect >= fp->fs->csize) {		/* On the cluster boundary? */
+				if (fp->fptr == 0) {				/* On the top of the file? */
+					clst = fp->org_clust;			/* Follow from the origin */
+					if (clst == 0)					/* When there is no cluster chain, */
+						fp->org_clust = clst = create_chain(fp->fs, 0);	/* Create a new cluster chain */
+				} else {							/* Middle or end of the file */
+					clst = create_chain(fp->fs, fp->curr_clust);			/* Follow or streach cluster chain */
+				}
+				if (clst == 0) break;				/* Could not allocate a new cluster (disk full) */
+				if (clst == 1) ABORT(fp->fs, FR_INT_ERR);
+				if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
+				fp->curr_clust = clst;				/* Update current cluster */
+				fp->csect = 0;						/* Reset sector address in the cluster */
+			}
+#if _FS_TINY
+			if (fp->fs->winsect == fp->dsect && move_window(fp->fs, 0))	/* Write back data buffer prior to following direct transfer */
+				ABORT(fp->fs, FR_DISK_ERR);
+#else
+			if (fp->flag & FA__DIRTY) {		/* Write back data buffer prior to following direct transfer */
+				if (disk_write(fp->fs->drive, fp->buf, fp->dsect, 1) != RES_OK)
+					ABORT(fp->fs, FR_DISK_ERR);
+				fp->flag &= (BYTE)~FA__DIRTY;
+			}
+#endif
+			sect = clust2sect(fp->fs, fp->curr_clust);	/* Get current sector */
+			if (!sect) ABORT(fp->fs, FR_INT_ERR);
+			sect += fp->csect;
+			cc = btw / SS(fp->fs);					/* When remaining bytes >= sector size, */
+			if (cc) {								/* Write maximum contiguous sectors directly */
+				if (fp->csect + cc > fp->fs->csize)	/* Clip at cluster boundary */
+					cc = fp->fs->csize - fp->csect;
+				if (disk_write(fp->fs->drive, wbuff, sect, (BYTE)cc) != RES_OK)
+					ABORT(fp->fs, FR_DISK_ERR);
+				fp->csect += (BYTE)cc;				/* Next sector address in the cluster */
+				wcnt = SS(fp->fs) * cc;				/* Number of bytes transferred */
+				continue;
+			}
+#if _FS_TINY
+			if (fp->fptr >= fp->fsize) {			/* Avoid silly buffer filling at growing edge */
+				if (move_window(fp->fs, 0)) ABORT(fp->fs, FR_DISK_ERR);
+				fp->fs->winsect = sect;
+			}
+#else
+			if (fp->dsect != sect) {				/* Fill sector buffer with file data */
+				if (fp->fptr < fp->fsize &&
+					disk_read(fp->fs->drive, fp->buf, sect, 1) != RES_OK)
+						ABORT(fp->fs, FR_DISK_ERR);
+			}
+#endif
+			fp->dsect = sect;
+			fp->csect++;							/* Next sector address in the cluster */
+		}
+		wcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs));	/* Put partial sector into file I/O buffer */
+		if (wcnt > btw) wcnt = btw;
+#if _FS_TINY
+		if (move_window(fp->fs, fp->dsect))			/* Move sector window */
+			ABORT(fp->fs, FR_DISK_ERR);
+		mem_cpy(&fp->fs->win[fp->fptr % SS(fp->fs)], wbuff, wcnt);	/* Fit partial sector */
+		fp->fs->wflag = 1;
+#else
+		mem_cpy(&fp->buf[fp->fptr % SS(fp->fs)], wbuff, wcnt);	/* Fit partial sector */
+		fp->flag |= FA__DIRTY;
+#endif
+	}
+
+	if (fp->fptr > fp->fsize) fp->fsize = fp->fptr;	/* Update file size if needed */
+	fp->flag |= FA__WRITTEN;						/* Set file changed flag */
+
+	LEAVE_FF(fp->fs, FR_OK);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Synchronize the File Object                                           */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_sync (
+	FIL *fp		/* Pointer to the file object */
+)
+{
+	FRESULT res;
+	DWORD tim;
+	BYTE *dir;
+
+
+	res = validate(fp->fs, fp->id);		/* Check validity of the object */
+	if (res == FR_OK) {
+		if (fp->flag & FA__WRITTEN) {	/* Has the file been written? */
+#if !_FS_TINY	/* Write-back dirty buffer */
+			if (fp->flag & FA__DIRTY) {
+				if (disk_write(fp->fs->drive, fp->buf, fp->dsect, 1) != RES_OK)
+					LEAVE_FF(fp->fs, FR_DISK_ERR);
+				fp->flag &= (BYTE)~FA__DIRTY;
+			}
+#endif
+			/* Update the directory entry */
+			res = move_window(fp->fs, fp->dir_sect);
+			if (res == FR_OK) {
+				dir = fp->dir_ptr;
+				dir[DIR_Attr] |= AM_ARC;					/* Set archive bit */
+				ST_DWORD(dir+DIR_FileSize, fp->fsize);		/* Update file size */
+				ST_WORD(dir+DIR_FstClusLO, fp->org_clust);	/* Update start cluster */
+				ST_WORD(dir+DIR_FstClusHI, fp->org_clust >> 16);
+				tim = get_fattime();					/* Updated time */
+				ST_DWORD(dir+DIR_WrtTime, tim);
+				fp->flag &= (BYTE)~FA__WRITTEN;
+				fp->fs->wflag = 1;
+				res = sync(fp->fs);
+			}
+		}
+	}
+
+	LEAVE_FF(fp->fs, res);
+}
+
+#endif /* !_FS_READONLY */
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Close File                                                            */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_close (
+	FIL *fp		/* Pointer to the file object to be closed */
+)
+{
+	FRESULT res;
+
+
+#if _FS_READONLY
+	res = validate(fp->fs, fp->id);
+	if (res == FR_OK) fp->fs = NULL;
+	LEAVE_FF(fp->fs, res);
+#else
+	res = f_sync(fp);
+	if (res == FR_OK) fp->fs = NULL;
+	return res;
+#endif
+}
+
+
+
+
+#if _FS_MINIMIZE <= 2
+/*-----------------------------------------------------------------------*/
+/* Seek File R/W Pointer                                                 */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_lseek (
+	FIL *fp,		/* Pointer to the file object */
+	DWORD ofs		/* File pointer from top of file */
+)
+{
+	FRESULT res;
+	DWORD clst, bcs, nsect, ifptr;
+
+
+	res = validate(fp->fs, fp->id);		/* Check validity of the object */
+	if (res != FR_OK) LEAVE_FF(fp->fs, res);
+	if (fp->flag & FA__ERROR)			/* Check abort flag */
+		LEAVE_FF(fp->fs, FR_INT_ERR);
+	if (ofs > fp->fsize					/* In read-only mode, clip offset with the file size */
+#if !_FS_READONLY
+		 && !(fp->flag & FA_WRITE)
+#endif
+		) ofs = fp->fsize;
+
+	ifptr = fp->fptr;
+	fp->fptr = 0; fp->csect = 255;
+	nsect = 0;
+	if (ofs > 0) {
+		bcs = (DWORD)fp->fs->csize * SS(fp->fs);	/* Cluster size (byte) */
+		if (ifptr > 0 &&
+			(ofs - 1) / bcs >= (ifptr - 1) / bcs) {	/* When seek to same or following cluster, */
+			fp->fptr = (ifptr - 1) & ~(bcs - 1);	/* start from the current cluster */
+			ofs -= fp->fptr;
+			clst = fp->curr_clust;
+		} else {									/* When seek to back cluster, */
+			clst = fp->org_clust;					/* start from the first cluster */
+#if !_FS_READONLY
+			if (clst == 0) {						/* If no cluster chain, create a new chain */
+				clst = create_chain(fp->fs, 0);
+				if (clst == 1) ABORT(fp->fs, FR_INT_ERR);
+				if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
+				fp->org_clust = clst;
+			}
+#endif
+			fp->curr_clust = clst;
+		}
+		if (clst != 0) {
+			while (ofs > bcs) {						/* Cluster following loop */
+#if !_FS_READONLY
+				if (fp->flag & FA_WRITE) {			/* Check if in write mode or not */
+					clst = create_chain(fp->fs, clst);	/* Force streached if in write mode */
+					if (clst == 0) {				/* When disk gets full, clip file size */
+						ofs = bcs; break;
+					}
+				} else
+#endif
+					clst = get_cluster(fp->fs, clst);	/* Follow cluster chain if not in write mode */
+				if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
+				if (clst <= 1 || clst >= fp->fs->max_clust) ABORT(fp->fs, FR_INT_ERR);
+				fp->curr_clust = clst;
+				fp->fptr += bcs;
+				ofs -= bcs;
+			}
+			fp->fptr += ofs;
+			fp->csect = (BYTE)(ofs / SS(fp->fs));	/* Sector offset in the cluster */
+			if (ofs % SS(fp->fs)) {
+				nsect = clust2sect(fp->fs, clst);	/* Current sector */
+				if (!nsect) ABORT(fp->fs, FR_INT_ERR);
+				nsect += fp->csect;
+				fp->csect++;
+			}
+		}
+	}
+	if (nsect && nsect != fp->dsect && fp->fptr % SS(fp->fs)) {
+#if !_FS_TINY
+#if !_FS_READONLY
+		if (fp->flag & FA__DIRTY) {			/* Write-back dirty buffer if needed */
+			if (disk_write(fp->fs->drive, fp->buf, fp->dsect, 1) != RES_OK)
+				ABORT(fp->fs, FR_DISK_ERR);
+			fp->flag &= (BYTE)~FA__DIRTY;
+		}
+#endif
+		if (disk_read(fp->fs->drive, fp->buf, nsect, 1) != RES_OK)
+			ABORT(fp->fs, FR_DISK_ERR);
+#endif
+		fp->dsect = nsect;
+	}
+#if !_FS_READONLY
+	if (fp->fptr > fp->fsize) {			/* Set changed flag if the file size is extended */
+		fp->fsize = fp->fptr;
+		fp->flag |= FA__WRITTEN;
+	}
+#endif
+
+	LEAVE_FF(fp->fs, res);
+}
+
+
+
+
+#if _FS_MINIMIZE <= 1
+/*-----------------------------------------------------------------------*/
+/* Create a Directroy Object                                             */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_opendir (
+	DIR *dj,			/* Pointer to directory object to create */
+	const char *path	/* Pointer to the directory path */
+)
+{
+	FRESULT res;
+	NAMEBUF(sfn, lfn);
+	BYTE *dir;
+
+
+	res = auto_mount(&path, &dj->fs, 0);
+	if (res == FR_OK) {
+		INITBUF((*dj), sfn, lfn);
+		res = follow_path(dj, path);			/* Follow the path to the directory */
+		if (res == FR_OK) {						/* Follow completed */
+			dir = dj->dir;
+			if (dir) {							/* It is not the root dir */
+				if (dir[DIR_Attr] & AM_DIR) {	/* The object is a directory */
+					dj->sclust = ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | LD_WORD(dir+DIR_FstClusLO);
+				} else {						/* The object is not a directory */
+					res = FR_NO_PATH;
+				}
+			} else {							/* It is the root dir */
+				dj->sclust = (dj->fs->fs_type == FS_FAT32) ? dj->fs->dirbase : 0;
+			}
+			if (res == FR_OK) res = dir_seek(dj, 0);
+			dj->id = dj->fs->id;
+		} else {
+			if (res == FR_NO_FILE) res = FR_NO_PATH;
+		}
+	}
+
+	LEAVE_FF(dj->fs, res);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Read Directory Entry in Sequense                                      */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_readdir (
+	DIR *dj,			/* Pointer to the open directory object */
+	FILINFO *fno		/* Pointer to file information to return */
+)
+{
+	FRESULT res;
+	NAMEBUF(sfn, lfn);
+
+
+	res = validate(dj->fs, dj->id);			/* Check validity of the object */
+	if (res == FR_OK) {
+#if 0	/* ROI DEBUG */
+		INITBUF((*dj), sfn, lfn);
+#else	/* ROI DEBUG */
+		INITBUF2((*dj), sfn);
+#endif	/* ROI DEBUG */
+		if (!fno) {
+			res = dir_seek(dj, 0);
+		} else {
+			res = dir_read(dj);
+			if (res == FR_NO_FILE) {
+				dj->sect = 0;
+				res = FR_OK;
+			}
+			if (res == FR_OK) {				/* A valid entry is found */
+				get_fileinfo(dj, fno);		/* Get the object information */
+				res = dir_next(dj, FALSE);	/* Increment index for next */
+				if (res == FR_NO_FILE) {
+					dj->sect = 0;
+					res = FR_OK;
+				}
+			}
+		}
+	}
+
+	LEAVE_FF(dj->fs, res);
+}
+
+
+
+#if _FS_MINIMIZE == 0
+/*-----------------------------------------------------------------------*/
+/* Get File Status                                                       */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_stat (
+	const char *path,	/* Pointer to the file path */
+	FILINFO *fno		/* Pointer to file information to return */
+)
+{
+	FRESULT res;
+	DIR dj;
+	NAMEBUF(sfn, lfn);
+
+
+	res = auto_mount(&path, &dj.fs, 0);
+	if (res == FR_OK) {
+		INITBUF(dj, sfn, lfn);
+		res = follow_path(&dj, path);	/* Follow the file path */
+		if (res == FR_OK) {				/* Follwo completed */
+			if (dj.dir)	/* Found an object */
+				get_fileinfo(&dj, fno);
+			else		/* It is root dir */
+				res = FR_INVALID_NAME;
+		}
+	}
+
+	LEAVE_FF(dj.fs, res);
+}
+
+
+
+#if !_FS_READONLY
+/*-----------------------------------------------------------------------*/
+/* Truncate File                                                         */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_truncate (
+	FIL *fp		/* Pointer to the file object */
+)
+{
+	FRESULT res;
+	DWORD ncl;
+
+
+	res = validate(fp->fs, fp->id);		/* Check validity of the object */
+	if (res != FR_OK) LEAVE_FF(fp->fs, res);
+	if (fp->flag & FA__ERROR)			/* Check abort flag */
+		LEAVE_FF(fp->fs, FR_INT_ERR);
+	if (!(fp->flag & FA_WRITE))			/* Check access mode */
+		LEAVE_FF(fp->fs, FR_DENIED);
+
+	if (fp->fsize > fp->fptr) {
+		fp->fsize = fp->fptr;	/* Set file size to current R/W point */
+		fp->flag |= FA__WRITTEN;
+		if (fp->fptr == 0) {	/* When set file size to zero, remove entire cluster chain */
+			res = remove_chain(fp->fs, fp->org_clust);
+			fp->org_clust = 0;
+		} else {				/* When truncate a part of the file, remove remaining clusters */
+			ncl = get_cluster(fp->fs, fp->curr_clust);
+			res = FR_OK;
+			if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR;
+			if (ncl == 1) res = FR_INT_ERR;
+			if (res == FR_OK && ncl < fp->fs->max_clust) {
+				res = put_cluster(fp->fs, fp->curr_clust, 0x0FFFFFFF);
+				if (res == FR_OK) res = remove_chain(fp->fs, ncl);
+			}
+		}
+	}
+	if (res != FR_OK) fp->flag |= FA__ERROR;
+
+	LEAVE_FF(fp->fs, res);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Get Number of Free Clusters                                           */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_getfree (
+	const char *path,	/* Pointer to the logical drive number (root dir) */
+	DWORD *nclst,		/* Pointer to the variable to return number of free clusters */
+	FATFS **fatfs		/* Pointer to pointer to corresponding file system object to return */
+)
+{
+	FRESULT res;
+	DWORD n, clst, sect;
+	BYTE fat, f, *p;
+
+
+	/* Get drive number */
+	res = auto_mount(&path, fatfs, 0);
+	if (res != FR_OK) LEAVE_FF(*fatfs, res);
+
+	/* If number of free cluster is valid, return it without cluster scan. */
+	if ((*fatfs)->free_clust <= (*fatfs)->max_clust - 2) {
+		*nclst = (*fatfs)->free_clust;
+		LEAVE_FF(*fatfs, FR_OK);
+	}
+
+	/* Get number of free clusters */
+	fat = (*fatfs)->fs_type;
+	n = 0;
+	if (fat == FS_FAT12) {
+		clst = 2;
+		do {
+			if ((WORD)get_cluster(*fatfs, clst) == 0) n++;
+		} while (++clst < (*fatfs)->max_clust);
+	} else {
+		clst = (*fatfs)->max_clust;
+		sect = (*fatfs)->fatbase;
+		f = 0; p = 0;
+		do {
+			if (!f) {
+				res = move_window(*fatfs, sect++);
+				if (res != FR_OK)
+					LEAVE_FF(*fatfs, res);
+				p = (*fatfs)->win;
+			}
+			if (fat == FS_FAT16) {
+				if (LD_WORD(p) == 0) n++;
+				p += 2; f += 1;
+			} else {
+				if (LD_DWORD(p) == 0) n++;
+				p += 4; f += 2;
+			}
+		} while (--clst);
+	}
+	(*fatfs)->free_clust = n;
+	if (fat == FS_FAT32) (*fatfs)->fsi_flag = 1;
+	*nclst = n;
+
+	LEAVE_FF(*fatfs, FR_OK);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Delete a File or Directory                                            */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_unlink (
+	const char *path		/* Pointer to the file or directory path */
+)
+{
+	FRESULT res;
+	DIR dj, sdj;
+	NAMEBUF(sfn, lfn);
+	BYTE *dir;
+	DWORD dclst;
+
+
+	res = auto_mount(&path, &dj.fs, 1);
+	if (res != FR_OK) LEAVE_FF(dj.fs, res);
+
+	INITBUF(dj, sfn, lfn);
+	res = follow_path(&dj, path);			/* Follow the file path */
+	if (res != FR_OK) LEAVE_FF(dj.fs, res); /* Follow failed */
+
+	dir = dj.dir;
+	if (!dir)								/* Is it the root directory? */
+		LEAVE_FF(dj.fs, FR_INVALID_NAME);
+	if (dir[DIR_Attr] & AM_RDO)				/* Is it a R/O object? */
+		LEAVE_FF(dj.fs, FR_DENIED);
+	dclst = ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | LD_WORD(dir+DIR_FstClusLO);
+
+	if (dir[DIR_Attr] & AM_DIR) {			/* It is a sub-directory */
+		if (dclst < 2) LEAVE_FF(dj.fs, FR_INT_ERR);
+		mem_cpy(&sdj, &dj, sizeof(DIR));		/* Check if the sub-dir is empty or not */
+		sdj.sclust = dclst;
+		res = dir_seek(&sdj, 0);
+		if (res != FR_OK) LEAVE_FF(dj.fs, res);
+		res = dir_read(&sdj);
+		if (res == FR_OK) res = FR_DENIED;	/* Not empty sub-dir */
+		if (res != FR_NO_FILE) LEAVE_FF(dj.fs, res);
+	}
+
+	res = dir_remove(&dj);					/* Remove directory entry */
+	if (res == FR_OK) {
+		if (dclst)
+			res = remove_chain(dj.fs, dclst);	/* Remove the cluster chain */
+		if (res == FR_OK) res = sync(dj.fs);
+	}
+
+	LEAVE_FF(dj.fs, FR_OK);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Create a Directory                                                    */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_mkdir (
+	const char *path		/* Pointer to the directory path */
+)
+{
+	FRESULT res;
+	DIR dj;
+	NAMEBUF(sfn, lfn);
+	BYTE *dir, n;
+	DWORD dsect, dclst, pclst, tim;
+
+
+	res = auto_mount(&path, &dj.fs, 1);
+	if (res != FR_OK) LEAVE_FF(dj.fs, res);
+
+	INITBUF(dj, sfn, lfn);
+	res = follow_path(&dj, path);			/* Follow the file path */
+	if (res == FR_OK) res = FR_EXIST;		/* Any file or directory is already existing */
+	if (res != FR_NO_FILE)					/* Any error occured */
+		LEAVE_FF(dj.fs, res);
+
+	dclst = create_chain(dj.fs, 0);			/* Allocate a new cluster for new directory table */
+	res = FR_OK;
+	if (dclst == 0) res = FR_DENIED;
+	if (dclst == 1) res = FR_INT_ERR;
+	if (dclst == 0xFFFFFFFF) res = FR_DISK_ERR;
+	if (res == FR_OK)
+		res = move_window(dj.fs, 0);
+	if (res != FR_OK) LEAVE_FF(dj.fs, res);
+	dsect = clust2sect(dj.fs, dclst);
+
+	dir = dj.fs->win;						/* Initialize the new directory table */
+	mem_set(dir, 0, SS(dj.fs));
+	mem_set(dir+DIR_Name, ' ', 8+3);		/* Create "." entry */
+	dir[DIR_Name] = '.';
+	dir[DIR_Attr] = AM_DIR;
+	tim = get_fattime();
+	ST_DWORD(dir+DIR_WrtTime, tim);
+	ST_WORD(dir+DIR_FstClusLO, dclst);
+	ST_WORD(dir+DIR_FstClusHI, dclst >> 16);
+	mem_cpy(dir+32, dir, 32); 			/* Create ".." entry */
+	dir[33] = '.';
+	pclst = dj.sclust;
+	if (dj.fs->fs_type == FS_FAT32 && pclst == dj.fs->dirbase)
+		pclst = 0;
+	ST_WORD(dir+32+DIR_FstClusLO, pclst);
+	ST_WORD(dir+32+DIR_FstClusHI, pclst >> 16);
+	for (n = 0; n < dj.fs->csize; n++) {	/* Write dot entries and clear left sectors */
+		dj.fs->winsect = dsect++;
+		dj.fs->wflag = 1;
+		res = move_window(dj.fs, 0);
+		if (res) LEAVE_FF(dj.fs, res);
+		mem_set(dir, 0, SS(dj.fs));
+	}
+
+	res = dir_register(&dj);
+	if (res != FR_OK) {
+		remove_chain(dj.fs, dclst);
+	} else {
+		dir = dj.dir;
+		dir[DIR_Attr] = AM_DIR;					/* Attribute */
+		ST_DWORD(dir+DIR_WrtTime, tim);			/* Crated time */
+		ST_WORD(dir+DIR_FstClusLO, dclst);		/* Table start cluster */
+		ST_WORD(dir+DIR_FstClusHI, dclst >> 16);
+		dj.fs->wflag = 1;
+		res = sync(dj.fs);
+	}
+
+	LEAVE_FF(dj.fs, res);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Change File Attribute                                                 */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_chmod (
+	const char *path,	/* Pointer to the file path */
+	BYTE value,			/* Attribute bits */
+	BYTE mask			/* Attribute mask to change */
+)
+{
+	FRESULT res;
+	DIR dj;
+	NAMEBUF(sfn, lfn);
+	BYTE *dir;
+
+
+	res = auto_mount(&path, &dj.fs, 1);
+	if (res == FR_OK) {
+		INITBUF(dj, sfn, lfn);
+		res = follow_path(&dj, path);		/* Follow the file path */
+		if (res == FR_OK) {
+			dir = dj.dir;
+			if (!dir) {						/* Is it a root directory? */
+				res = FR_INVALID_NAME;
+			} else {						/* File or sub directory */
+				mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC;	/* Valid attribute mask */
+				dir[DIR_Attr] = (value & mask) | (dir[DIR_Attr] & (BYTE)~mask);	/* Apply attribute change */
+				dj.fs->wflag = 1;
+				res = sync(dj.fs);
+			}
+		}
+	}
+
+	LEAVE_FF(dj.fs, res);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Change Timestamp                                                      */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_utime (
+	const char *path,	/* Pointer to the file/directory name */
+	const FILINFO *fno	/* Pointer to the timestamp to be set */
+)
+{
+	FRESULT res;
+	DIR dj;
+	NAMEBUF(sfn, lfn);
+	BYTE *dir;
+
+
+	res = auto_mount(&path, &dj.fs, 1);
+	if (res == FR_OK) {
+		INITBUF(dj, sfn, lfn);
+		res = follow_path(&dj, path);	/* Follow the file path */
+		if (res == FR_OK) {
+			dir = dj.dir;
+			if (!dir) {				/* Root directory */
+				res = FR_INVALID_NAME;
+			} else {				/* File or sub-directory */
+				ST_WORD(dir+DIR_WrtTime, fno->ftime);
+				ST_WORD(dir+DIR_WrtDate, fno->fdate);
+				dj.fs->wflag = 1;
+				res = sync(dj.fs);
+			}
+		}
+	}
+
+	LEAVE_FF(dj.fs, res);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Rename File/Directory                                                 */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_rename (
+	const char *path_old,	/* Pointer to the old name */
+	const char *path_new	/* Pointer to the new name */
+)
+{
+	FRESULT res;
+	DIR dj_old, dj_new;
+	NAMEBUF(sfn, lfn);
+	BYTE buf[21], *dir;
+	DWORD dw;
+
+
+	INITBUF(dj_old, sfn, lfn);
+	res = auto_mount(&path_old, &dj_old.fs, 1);
+	if (res == FR_OK) {
+		dj_new.fs = dj_old.fs;
+		res = follow_path(&dj_old, path_old);	/* Check old object */
+	}
+	if (res != FR_OK) LEAVE_FF(dj_old.fs, res);	/* The old object is not found */
+
+	if (!dj_old.dir) LEAVE_FF(dj_old.fs, FR_NO_FILE);	/* Is root dir? */
+	mem_cpy(buf, dj_old.dir+DIR_Attr, 21);		/* Save the object information */
+
+	mem_cpy(&dj_new, &dj_old, sizeof(DIR));
+	res = follow_path(&dj_new, path_new);		/* Check new object */
+	if (res == FR_OK) res = FR_EXIST;			/* The new object name is already existing */
+	if (res == FR_NO_FILE) { 					/* Is it a valid path and no name collision? */
+		res = dir_register(&dj_new);			/* Register the new object */
+		if (res == FR_OK) {
+			dir = dj_new.dir;					/* Copy object information into new entry */
+			mem_cpy(dir+13, buf+2, 19);
+			dir[DIR_Attr] = buf[0];
+			dj_old.fs->wflag = 1;
+			if (dir[DIR_Attr] & AM_DIR) {		/* Update .. entry in the directory if needed */
+				dw = clust2sect(dj_new.fs, (DWORD)LD_WORD(dir+DIR_FstClusHI) | LD_WORD(dir+DIR_FstClusLO));
+				if (!dw) {
+					res = FR_INT_ERR;
+				} else {
+					res = move_window(dj_new.fs, dw);
+					dir = dj_new.fs->win+32;
+					if (res == FR_OK && dir[1] == '.') {
+						dw = (dj_new.fs->fs_type == FS_FAT32 && dj_new.sclust == dj_new.fs->dirbase) ? 0 : dj_new.sclust;
+						ST_WORD(dir+DIR_FstClusLO, dw);
+						ST_WORD(dir+DIR_FstClusHI, dw >> 16);
+						dj_new.fs->wflag = 1;
+					}
+				}
+			}
+			if (res == FR_OK) {
+				res = dir_remove(&dj_old);			/* Remove old entry */
+				if (res == FR_OK)
+					res = sync(dj_old.fs);
+			}
+		}
+	}
+
+	LEAVE_FF(dj_old.fs, res);
+}
+
+#endif /* !_FS_READONLY */
+#endif /* _FS_MINIMIZE == 0 */
+#endif /* _FS_MINIMIZE <= 1 */
+#endif /* _FS_MINIMIZE <= 2 */
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Forward data to the stream directly (Available on only _FS_TINY cfg)  */
+/*-----------------------------------------------------------------------*/
+#if _USE_FORWARD && _FS_TINY
+
+FRESULT f_forward (
+	FIL *fp, 						/* Pointer to the file object */
+	UINT (*func)(const BYTE*,UINT),	/* Pointer to the streaming function */
+	UINT btr,						/* Number of bytes to forward */
+	UINT *bf						/* Pointer to number of bytes forwarded */
+)
+{
+	FRESULT res;
+	DWORD remain, clst, sect;
+	UINT rcnt;
+
+
+	*bf = 0;
+
+	res = validate(fp->fs, fp->id);					/* Check validity of the object */
+	if (res != FR_OK) LEAVE_FF(fp->fs, res);
+	if (fp->flag & FA__ERROR)						/* Check error flag */
+		LEAVE_FF(fp->fs, FR_INT_ERR);
+	if (!(fp->flag & FA_READ))						/* Check access mode */
+		LEAVE_FF(fp->fs, FR_DENIED);
+
+	remain = fp->fsize - fp->fptr;
+	if (btr > remain) btr = (UINT)remain;			/* Truncate btr by remaining bytes */
+
+	for ( ;  btr && (*func)(NULL, 0);				/* Repeat until all data transferred or stream becomes busy */
+		fp->fptr += rcnt, *bf += rcnt, btr -= rcnt) {
+		if ((fp->fptr % SS(fp->fs)) == 0) {			/* On the sector boundary? */
+			if (fp->csect >= fp->fs->csize) {		/* On the cluster boundary? */
+				clst = (fp->fptr == 0) ?			/* On the top of the file? */
+					fp->org_clust : get_cluster(fp->fs, fp->curr_clust);
+				if (clst <= 1) ABORT(fp->fs, FR_INT_ERR);
+				if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
+				fp->curr_clust = clst;				/* Update current cluster */
+				fp->csect = 0;						/* Reset sector address in the cluster */
+			}
+			fp->csect++;							/* Next sector address in the cluster */
+		}
+		sect = clust2sect(fp->fs, fp->curr_clust);	/* Get current data sector */
+		if (!sect) ABORT(fp->fs, FR_INT_ERR);
+		sect += fp->csect - 1;
+		if (move_window(fp->fs, sect))				/* Move sector window */
+			ABORT(fp->fs, FR_DISK_ERR);
+		fp->dsect = sect;
+		rcnt = SS(fp->fs) - (WORD)(fp->fptr % SS(fp->fs));	/* Forward data from sector window */
+		if (rcnt > btr) rcnt = btr;
+		rcnt = (*func)(&fp->fs->win[(WORD)fp->fptr % SS(fp->fs)], rcnt);
+		if (!rcnt) ABORT(fp->fs, FR_INT_ERR);
+	}
+
+	LEAVE_FF(fp->fs, FR_OK);
+}
+#endif /* _USE_FORWARD */
+
+
+
+#if _USE_MKFS && !_FS_READONLY
+/*-----------------------------------------------------------------------*/
+/* Create File System on the Drive                                       */
+/*-----------------------------------------------------------------------*/
+#define N_ROOTDIR	512			/* Multiple of 32 and <= 2048 */
+#define N_FATS		1			/* 1 or 2 */
+#define MAX_SECTOR	131072000UL	/* Maximum partition size */
+#ifndef MIN_SECTOR	/* ROI DEBUG */
+#define MIN_SECTOR	2000UL		/* Minimum partition size */
+#endif				/* ROI DEBUG */
+
+
+FRESULT f_mkfs (
+	BYTE drv,			/* Logical drive number */
+	BYTE partition,		/* Partitioning rule 0:FDISK, 1:SFD */
+	WORD allocsize		/* Allocation unit size [bytes] */
+)
+{
+	static const DWORD sstbl[] = { 2048000, 1024000, 512000, 256000, 128000, 64000, 32000, 16000, 8000, 4000,   0 };
+	static const WORD cstbl[] =  {   32768,   16384,   8192,   4096,   2048, 16384,  8192,  4096, 2048, 1024, 512 };
+	BYTE fmt, m, *tbl;
+	DWORD b_part, b_fat, b_dir, b_data;		/* Area offset (LBA) */
+	DWORD n_part, n_rsv, n_fat, n_dir;		/* Area size */
+	DWORD n_clst, n;
+	WORD as;
+	FATFS *fs;
+	DSTATUS stat;
+
+
+	/* Check validity of the parameters */
+	if (drv >= _DRIVES) return FR_INVALID_DRIVE;
+	if (partition >= 2) return FR_MKFS_ABORTED;
+
+	/* Check mounted drive and clear work area */
+	fs = FatFs[drv];
+	if (!fs) return FR_NOT_ENABLED;
+	fs->fs_type = 0;
+	drv = LD2PD(drv);
+
+	/* Get disk statics */
+	stat = disk_initialize(drv);
+	if (stat & STA_NOINIT) return FR_NOT_READY;
+	if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
+	if (disk_ioctl(drv, GET_SECTOR_COUNT, &n_part) != RES_OK || n_part < MIN_SECTOR)
+		return FR_MKFS_ABORTED;
+	if (n_part > MAX_SECTOR) n_part = MAX_SECTOR;
+	b_part = (!partition) ? 63 : 0;		/* Boot sector */
+	n_part -= b_part;
+#if _MAX_SS == 512
+	if (!allocsize) {					/* Auto selection of cluster size */
+		for (n = 0; n_part < sstbl[n]; n++) ;
+		allocsize = cstbl[n];
+	}
+#endif
+	for (as = 512; as <= 32768U && as != allocsize; as <<= 1);
+	if (as != allocsize) return FR_MKFS_ABORTED;
+#if _MAX_SS != 512						/* Check disk sector size */
+	if (disk_ioctl(drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK
+		|| SS(fs) > _MAX_SS
+		|| SS(fs) > allocsize)
+		return FR_MKFS_ABORTED;
+#endif
+	allocsize /= SS(fs);		/* Number of sectors per cluster */
+
+	/* Pre-compute number of clusters and FAT type */
+	n_clst = n_part / allocsize;
+	fmt = FS_FAT12;
+	if (n_clst >= 0xFF5) fmt = FS_FAT16;
+	if (n_clst >= 0xFFF5) fmt = FS_FAT32;
+
+	/* Determine offset and size of FAT structure */
+	switch (fmt) {
+	case FS_FAT12:
+		n_fat = ((n_clst * 3 + 1) / 2 + 3 + SS(fs) - 1) / SS(fs);
+		n_rsv = 1 + partition;
+		n_dir = N_ROOTDIR * 32 / SS(fs);
+		break;
+	case FS_FAT16:
+		n_fat = ((n_clst * 2) + 4 + SS(fs) - 1) / SS(fs);
+		n_rsv = 1 + partition;
+		n_dir = N_ROOTDIR * 32 / SS(fs);
+		break;
+	default:
+		n_fat = ((n_clst * 4) + 8 + SS(fs) - 1) / SS(fs);
+		n_rsv = 33 - partition;
+		n_dir = 0;
+	}
+	b_fat = b_part + n_rsv;			/* FATs start sector */
+	b_dir = b_fat + n_fat * N_FATS;	/* Directory start sector */
+	b_data = b_dir + n_dir;			/* Data start sector */
+
+	/* Align data start sector to erase block boundary (for flash memory media) */
+	if (disk_ioctl(drv, GET_BLOCK_SIZE, &n) != RES_OK) return FR_MKFS_ABORTED;
+	n = (b_data + n - 1) & ~(n - 1);
+	n_fat += (n - b_data) / N_FATS;
+	/* b_dir and b_data are no longer used below */
+
+	/* Determine number of cluster and final check of validity of the FAT type */
+	n_clst = (n_part - n_rsv - n_fat * N_FATS - n_dir) / allocsize;
+	if (   (fmt == FS_FAT16 && n_clst < 0xFF5)
+		|| (fmt == FS_FAT32 && n_clst < 0xFFF5))
+		return FR_MKFS_ABORTED;
+
+	/* Create partition table if needed */
+	if (!partition) {
+		DWORD n_disk = b_part + n_part;
+
+		tbl = fs->win+MBR_Table;
+		ST_DWORD(tbl, 0x00010180);		/* Partition start in CHS */
+		if (n_disk < 63UL * 255 * 1024) {	/* Partition end in CHS */
+			n_disk = n_disk / 63 / 255;
+			tbl[7] = (BYTE)n_disk;
+			tbl[6] = (BYTE)((n_disk >> 2) | 63);
+		} else {
+			ST_WORD(&tbl[6], 0xFFFF);
+		}
+		tbl[5] = 254;
+		if (fmt != FS_FAT32)			/* System ID */
+			tbl[4] = (n_part < 0x10000) ? 0x04 : 0x06;
+		else
+			tbl[4] = 0x0c;
+		ST_DWORD(tbl+8, 63);			/* Partition start in LBA */
+		ST_DWORD(tbl+12, n_part);		/* Partition size in LBA */
+		ST_WORD(tbl+64, 0xAA55);		/* Signature */
+		if (disk_write(drv, fs->win, 0, 1) != RES_OK)
+			return FR_DISK_ERR;
+	}
+
+	/* Create boot record */
+	tbl = fs->win;								/* Clear buffer */
+	mem_set(tbl, 0, SS(fs));
+	ST_DWORD(tbl+BS_jmpBoot, 0x90FEEB);			/* Boot code (jmp $, nop) */
+	ST_WORD(tbl+BPB_BytsPerSec, SS(fs));		/* Sector size */
+	tbl[BPB_SecPerClus] = (BYTE)allocsize;		/* Sectors per cluster */
+	ST_WORD(tbl+BPB_RsvdSecCnt, n_rsv);			/* Reserved sectors */
+	tbl[BPB_NumFATs] = N_FATS;					/* Number of FATs */
+	ST_WORD(tbl+BPB_RootEntCnt, SS(fs) / 32 * n_dir); /* Number of rootdir entries */
+	if (n_part < 0x10000) {						/* Number of total sectors */
+		ST_WORD(tbl+BPB_TotSec16, n_part);
+	} else {
+		ST_DWORD(tbl+BPB_TotSec32, n_part);
+	}
+	tbl[BPB_Media] = 0xF8;						/* Media descripter */
+	ST_WORD(tbl+BPB_SecPerTrk, 63);				/* Number of sectors per track */
+	ST_WORD(tbl+BPB_NumHeads, 255);				/* Number of heads */
+	ST_DWORD(tbl+BPB_HiddSec, b_part);			/* Hidden sectors */
+	n = get_fattime();							/* Use current time as a VSN */
+	if (fmt != FS_FAT32) {
+		ST_DWORD(tbl+BS_VolID, n);				/* Volume serial number */
+		ST_WORD(tbl+BPB_FATSz16, n_fat);		/* Number of secters per FAT */
+		tbl[BS_DrvNum] = 0x80;					/* Drive number */
+		tbl[BS_BootSig] = 0x29;					/* Extended boot signature */
+		mem_cpy(tbl+BS_VolLab, "NO NAME    FAT     ", 19);	/* Volume lavel, FAT signature */
+	} else {
+		ST_DWORD(tbl+BS_VolID32, n);			/* Volume serial number */
+		ST_DWORD(tbl+BPB_FATSz32, n_fat);		/* Number of secters per FAT */
+		ST_DWORD(tbl+BPB_RootClus, 2);			/* Root directory cluster (2) */
+		ST_WORD(tbl+BPB_FSInfo, 1);				/* FSInfo record offset (bs+1) */
+		ST_WORD(tbl+BPB_BkBootSec, 6);			/* Backup boot record offset (bs+6) */
+		tbl[BS_DrvNum32] = 0x80;				/* Drive number */
+		tbl[BS_BootSig32] = 0x29;				/* Extended boot signature */
+		mem_cpy(tbl+BS_VolLab32, "NO NAME    FAT32   ", 19);	/* Volume lavel, FAT signature */
+	}
+	ST_WORD(tbl+BS_55AA, 0xAA55);				/* Signature */
+	if (disk_write(drv, tbl, b_part+0, 1) != RES_OK)
+		return FR_DISK_ERR;
+	if (fmt == FS_FAT32)
+		disk_write(drv, tbl, b_part+6, 1);
+
+	/* Initialize FAT area */
+	for (m = 0; m < N_FATS; m++) {
+		mem_set(tbl, 0, SS(fs));		/* 1st sector of the FAT  */
+		if (fmt != FS_FAT32) {
+			n = (fmt == FS_FAT12) ? 0x00FFFFF8 : 0xFFFFFFF8;
+			ST_DWORD(tbl, n);				/* Reserve cluster #0-1 (FAT12/16) */
+		} else {
+			ST_DWORD(tbl+0, 0xFFFFFFF8);	/* Reserve cluster #0-1 (FAT32) */
+			ST_DWORD(tbl+4, 0xFFFFFFFF);
+			ST_DWORD(tbl+8, 0x0FFFFFFF);	/* Reserve cluster #2 for root dir */
+		}
+		if (disk_write(drv, tbl, b_fat++, 1) != RES_OK)
+			return FR_DISK_ERR;
+		mem_set(tbl, 0, SS(fs));		/* Following FAT entries are filled by zero */
+		for (n = 1; n < n_fat; n++) {
+			if (disk_write(drv, tbl, b_fat++, 1) != RES_OK)
+				return FR_DISK_ERR;
+		}
+	}
+
+	/* Initialize Root directory */
+	m = (BYTE)((fmt == FS_FAT32) ? allocsize : n_dir);
+	do {
+		if (disk_write(drv, tbl, b_fat++, 1) != RES_OK)
+			return FR_DISK_ERR;
+	} while (--m);
+
+	/* Create FSInfo record if needed */
+	if (fmt == FS_FAT32) {
+		ST_WORD(tbl+BS_55AA, 0xAA55);
+		ST_DWORD(tbl+FSI_LeadSig, 0x41615252);
+		ST_DWORD(tbl+FSI_StrucSig, 0x61417272);
+		ST_DWORD(tbl+FSI_Free_Count, n_clst - 1);
+		ST_DWORD(tbl+FSI_Nxt_Free, 0xFFFFFFFF);
+		disk_write(drv, tbl, b_part+1, 1);
+		disk_write(drv, tbl, b_part+7, 1);
+	}
+
+	return (disk_ioctl(drv, CTRL_SYNC, (void*)NULL) == RES_OK) ? FR_OK : FR_DISK_ERR;
+}
+
+#endif /* _USE_MKFS && !_FS_READONLY */
+
+
+
+
+#if _USE_STRFUNC
+/*-----------------------------------------------------------------------*/
+/* Get a string from the file                                            */
+/*-----------------------------------------------------------------------*/
+char* f_gets (
+	char* buff,	/* Pointer to the string buffer to read */
+	int len,	/* Size of string buffer */
+	FIL* fil	/* Pointer to the file object */
+)
+{
+	int i = 0;
+	char *p = buff;
+	UINT rc;
+
+
+	while (i < len - 1) {			/* Read bytes until buffer gets filled */
+		f_read(fil, p, 1, &rc);
+		if (rc != 1) break;			/* Break when no data to read */
+#if _USE_STRFUNC >= 2
+		if (*p == '\r') continue;	/* Strip '\r' */
+#endif
+		i++;
+		if (*p++ == '\n') break;	/* Break when reached end of line */
+	}
+	*p = 0;
+	return i ? buff : NULL;			/* When no data read (eof or error), return with error. */
+}
+
+
+
+#if !_FS_READONLY
+#include <stdarg.h>
+/*-----------------------------------------------------------------------*/
+/* Put a character to the file                                           */
+/*-----------------------------------------------------------------------*/
+int f_putc (
+	int chr,	/* A character to be output */
+	FIL* fil	/* Ponter to the file object */
+)
+{
+	UINT bw;
+	char c;
+
+
+#if _USE_STRFUNC >= 2
+	if (chr == '\n') f_putc ('\r', fil);	/* LF -> CRLF conversion */
+#endif
+	if (!fil) {	/* Special value may be used to switch the destination to any other device */
+	/*	put_console(chr);	*/
+		return chr;
+	}
+	c = (char)chr;
+	f_write(fil, &c, 1, &bw);	/* Write a byte to the file */
+	return bw ? chr : EOF;		/* Return the result */
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Put a string to the file                                              */
+/*-----------------------------------------------------------------------*/
+int f_puts (
+	const char* str,	/* Pointer to the string to be output */
+	FIL* fil			/* Pointer to the file object */
+)
+{
+	int n;
+
+
+	for (n = 0; *str; str++, n++) {
+		if (f_putc(*str, fil) == EOF) return EOF;
+	}
+	return n;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Put a formatted string to the file                                    */
+/*-----------------------------------------------------------------------*/
+int f_printf (
+	FIL* fil,			/* Pointer to the file object */
+	const char* str,	/* Pointer to the format string */
+	...					/* Optional arguments... */
+)
+{
+	va_list arp;
+	UCHAR c, f, r;
+	ULONG val;
+	char s[16];
+	int i, w, res, cc;
+
+
+	va_start(arp, str);
+
+	for (cc = res = 0; cc != EOF; res += cc) {
+		c = *str++;
+		if (c == 0) break;			/* End of string */
+		if (c != '%') {				/* Non escape cahracter */
+			cc = f_putc(c, fil);
+			if (cc != EOF) cc = 1;
+			continue;
+		}
+		w = f = 0;
+		c = *str++;
+		if (c == '0') {				/* Flag: '0' padding */
+			f = 1; c = *str++;
+		}
+		while (c >= '0' && c <= '9') {	/* Precision */
+			w = w * 10 + (c - '0');
+			c = *str++;
+		}
+		if (c == 'l') {				/* Prefix: Size is long int */
+			f |= 2; c = *str++;
+		}
+		if (c == 's') {				/* Type is string */
+			cc = f_puts(va_arg(arp, char*), fil);
+			continue;
+		}
+		if (c == 'c') {				/* Type is character */
+			cc = f_putc(va_arg(arp, int), fil);
+			if (cc != EOF) cc = 1;
+			continue;
+		}
+		r = 0;
+		if (c == 'd') r = 10;		/* Type is signed decimal */
+		if (c == 'u') r = 10;		/* Type is unsigned decimal */
+		if (c == 'X') r = 16;		/* Type is unsigned hexdecimal */
+		if (r == 0) break;			/* Unknown type */
+		if (f & 2) {				/* Get the value */
+			val = (ULONG)va_arg(arp, long);
+		} else {
+			val = (c == 'd') ? (ULONG)(long)va_arg(arp, int) : (ULONG)va_arg(arp, unsigned int);
+		}
+		/* Put numeral string */
+		if (c == 'd') {
+			if (val & 0x80000000) {
+				val = 0 - val;
+				f |= 4;
+			}
+		}
+		i = sizeof(s) - 1; s[i] = 0;
+		do {
+			c = (UCHAR)(val % r + '0');
+			if (c > '9') c += 7;
+			s[--i] = c;
+			val /= r;
+		} while (i && val);
+		if (i && (f & 4)) s[--i] = '-';
+		w = sizeof(s) - 1 - w;
+		while (i && i > w) s[--i] = (f & 1) ? '0' : ' ';
+		cc = f_puts(&s[i], fil);
+	}
+
+	va_end(arp);
+	return (cc == EOF) ? cc : res;
+}
+
+#endif /* !_FS_READONLY */
+#endif /* _USE_STRFUNC */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/ff.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/ff.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/ff.h	(revision 453)
@@ -0,0 +1,553 @@
+/*---------------------------------------------------------------------------/
+/  FatFs - FAT file system module include file  R0.07a       (C)ChaN, 2009
+/----------------------------------------------------------------------------/
+/ FatFs module is an open source software to implement FAT file system to
+/ small embedded systems. This is a free software and is opened for education,
+/ research and commercial developments under license policy of following trems.
+/
+/  Copyright (C) 2009, ChaN, all right reserved.
+/
+/ * The FatFs module is a free software and there is NO WARRANTY.
+/ * No restriction on use. You can use, modify and redistribute it for
+/   personal, non-profit or commercial use UNDER YOUR RESPONSIBILITY.
+/ * Redistributions of source code must retain the above copyright notice.
+/----------------------------------------------------------------------------*/
+
+#include "integer.h"
+
+/*---------------------------------------------------------------------------/
+/ FatFs Configuration Options
+/
+/ CAUTION! Do not forget to make clean the project after any changes to
+/ the configuration options.
+/
+/----------------------------------------------------------------------------*/
+#ifndef _FATFS
+#define _FATFS
+
+#define _WORD_ACCESS	0
+/* The _WORD_ACCESS option defines which access method is used to the word
+/  data in the FAT structure.
+/
+/   0: Byte-by-byte access. Always compatible with all platforms.
+/   1: Word access. Do not choose this unless following condition is met.
+/
+/  When the byte order on the memory is big-endian or address miss-aligned
+/  word access results incorrect behavior, the _WORD_ACCESS must be set to 0.
+/  If it is not the case, the value can also be set to 1 to improve the
+/  performance and code efficiency. */
+
+
+#define _FS_READONLY	0
+/* Setting _FS_READONLY to 1 defines read only configuration. This removes
+/  writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename,
+/  f_truncate and useless f_getfree. */
+
+
+#define _FS_MINIMIZE	0
+/* The _FS_MINIMIZE option defines minimization level to remove some functions.
+/
+/   0: Full function.
+/   1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename
+/      are removed.
+/   2: f_opendir and f_readdir are removed in addition to level 1.
+/   3: f_lseek is removed in addition to level 2. */
+
+
+#define	_FS_TINY	0
+/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system
+/  object instead of the sector buffer in the individual file object for file
+/  data transfer. This reduces memory consumption 512 bytes each file object. */
+
+
+#define	_USE_STRFUNC	0
+/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
+
+
+#define	_USE_MKFS	1
+/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */
+
+
+#define	_USE_FORWARD	0
+/* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */
+
+
+#ifndef _DRIVES
+#define _DRIVES		1
+#endif
+/* Number of volumes (logical drives) to be used. */
+
+
+#define	_MAX_SS	512
+/* Maximum sector size to be handled. (512/1024/2048/4096) */
+/* 512 for memroy card and hard disk, 1024 for floppy disk, 2048 for MO disk */
+
+
+#define	_MULTI_PARTITION	0
+/* When _MULTI_PARTITION is set to 0, each volume is bound to the same physical
+/ drive number and can mount only first primaly partition. When it is set to 1,
+/ each volume is tied to the partitions listed in Drives[]. */
+
+
+#define _CODE_PAGE	932
+/* The _CODE_PAGE specifies the OEM code page to be used on the target system.
+/  When it is non LFN configuration, there is no difference between SBCS code
+/  pages. When LFN is enabled, the code page must always be set correctly.
+/   437 - U.S.
+/   720 - Arabic
+/   737 - Greek
+/   775 - Baltic
+/   850 - Multilingual Latin 1
+/   852 - Latin 2
+/   855 - Cyrillic
+/   857 - Turkish
+/   858 - Multilingual Latin 1 + Euro
+/   862 - Hebrew
+/   866 - Russian
+/   874 - Thai
+/   932 - Japanese Shift-JIS       (DBCS)
+/   936 - Simplified Chinese GBK   (DBCS)
+/   949 - Korean                   (DBCS)
+/   950 - Traditional Chinese Big5 (DBCS)
+/   1258 - Vietnam
+*/
+
+
+#define	_USE_LFN	2
+#define	_MAX_LFN	255		/* Maximum LFN length to handle (max:255) */
+/* The _USE_LFN option switches the LFN support.
+/
+/   0: Disable LFN.
+/   1: Enable LFN with static working buffer on the bss. NOT REENTRANT.
+/   2: Enable LFN with dynamic working buffer on the caller's STACK.
+/
+/  The working buffer occupies (_MAX_LFN + 1) * 2 bytes. When enable LFN,
+/  a Unicode - OEM code conversion function ff_convert() must be added to
+/  the project. */
+
+
+#define _FS_REENTRANT	1
+#define _TIMEOUT		1000	/* Timeout period in unit of time ticks */
+#define	_SYNC_t			int		/* Type of sync object used on the OS. */
+								/* e.g. HANDLE, OS_EVENT*, ID and etc.. */
+/* To make the FatFs module re-entrant, set _FS_REENTRANT to 1 and add user
+/  provided synchronization handlers, ff_req_grant, ff_rel_grant,
+/  ff_del_syncobj and ff_cre_syncobj function to the project. */
+
+
+
+
+/* End of configuration options. Do not change followings without care.     */
+/*--------------------------------------------------------------------------*/
+
+
+
+/* Definitions corresponds to multiple sector size */
+
+#if _MAX_SS == 512
+#define	SS(fs)	512
+#else
+#if _MAX_SS == 1024 || _MAX_SS == 2048 || _MAX_SS == 4096
+#define	SS(fs)	((fs)->s_size)
+#else
+#error Sector size must be 512, 1024, 2048 or 4096.
+#endif
+#endif
+
+
+
+/* File system object structure */
+
+typedef struct _FATFS {
+	BYTE	fs_type;	/* FAT sub type */
+	BYTE	drive;		/* Physical drive number */
+	BYTE	csize;		/* Number of sectors per cluster */
+	BYTE	n_fats;		/* Number of FAT copies */
+	BYTE	wflag;		/* win[] dirty flag (1:must be written back) */
+	BYTE	pad1;
+	WORD	id;			/* File system mount ID */
+	WORD	n_rootdir;	/* Number of root directory entries (0 on FAT32) */
+#if _FS_REENTRANT
+	_SYNC_t	sobj;		/* Identifier of sync object */
+#endif
+#if _MAX_SS != 512U
+	WORD	s_size;		/* Sector size */
+#endif
+#if !_FS_READONLY
+	BYTE	fsi_flag;	/* fsinfo dirty flag (1:must be written back) */
+	BYTE	pad2;
+	DWORD	last_clust;	/* Last allocated cluster */
+	DWORD	free_clust;	/* Number of free clusters */
+	DWORD	fsi_sector;	/* fsinfo sector */
+#endif
+	DWORD	sects_fat;	/* Sectors per fat */
+	DWORD	max_clust;	/* Maximum cluster# + 1. Number of clusters is max_clust - 2 */
+	DWORD	fatbase;	/* FAT start sector */
+	DWORD	dirbase;	/* Root directory start sector (Cluster# on FAT32) */
+	DWORD	database;	/* Data start sector */
+	DWORD	winsect;	/* Current sector appearing in the win[] */
+#if 1	/* ROI DEBUG */
+	DWORD   dummy[2];	/* cache aline */
+#endif	/* ROI DEBUG */
+	BYTE	win[_MAX_SS];/* Disk access window for Directory/FAT */
+} FATFS;
+
+
+
+/* Directory object structure */
+
+typedef struct _DIR {
+	WORD	id;			/* Owner file system mount ID */
+	WORD	index;		/* Current index number */
+	FATFS*	fs;			/* Pointer to the owner file system object */
+	DWORD	sclust;		/* Table start cluster (0:Static table) */
+	DWORD	clust;		/* Current cluster */
+	DWORD	sect;		/* Current sector */
+	BYTE*	dir;		/* Pointer to the current SFN entry in the win[] */
+	BYTE*	fn;			/* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
+#if _USE_LFN
+	WCHAR*	lfn;		/* Pointer to the LFN working buffer */
+	WORD	lfn_idx;	/* Last matched LFN index (0xFFFF:No LFN) */
+#endif
+} DIR;
+
+
+
+/* File object structure */
+
+typedef struct _FIL {
+	FATFS*	fs;			/* Pointer to the owner file system object */
+	WORD	id;			/* Owner file system mount ID */
+	BYTE	flag;		/* File status flags */
+	BYTE	csect;		/* Sector address in the cluster */
+	DWORD	fptr;		/* File R/W pointer */
+	DWORD	fsize;		/* File size */
+	DWORD	org_clust;	/* File start cluster */
+	DWORD	curr_clust;	/* Current cluster */
+	DWORD	dsect;		/* Current data sector */
+#if !_FS_READONLY
+	DWORD	dir_sect;	/* Sector containing the directory entry */
+	BYTE*	dir_ptr;	/* Ponter to the directory entry in the window */
+#endif
+#if !_FS_TINY
+	BYTE	buf[_MAX_SS];/* File R/W buffer */
+#endif
+} FIL;
+
+
+
+/* File status structure */
+
+typedef struct _FILINFO {
+	DWORD fsize;		/* File size */
+	WORD fdate;			/* Last modified date */
+	WORD ftime;			/* Last modified time */
+	BYTE fattrib;		/* Attribute */
+	char fname[13];		/* Short file name (8.3 format) */
+#if _USE_LFN
+	char *lfname;		/* Pointer to the LFN buffer */
+	int lfsize;			/* Size of LFN buffer [bytes] */
+#endif
+} FILINFO;
+
+
+
+/* DBCS code ranges */
+
+#if _CODE_PAGE == 932	/* CP932 (Japanese Shift-JIS) */
+#define _DF1S	0x81	/* DBC 1st byte range 1 start */
+#define _DF1E	0x9F	/* DBC 1st byte range 1 end */
+#define _DF2S	0xE0	/* DBC 1st byte range 2 start */
+#define _DF2E	0xFC	/* DBC 1st byte range 2 end */
+#define _DS1S	0x40	/* DBC 2nd byte range 1 start */
+#define _DS1E	0x7E	/* DBC 2nd byte range 1 end */
+#define _DS2S	0x80	/* DBC 2nd byte range 2 start */
+#define _DS2E	0xFC	/* DBC 2nd byte range 2 end */
+
+#elif _CODE_PAGE == 936	/* CP936 (Simplified Chinese GBK) */
+#define _DF1S	0x81
+#define _DF1E	0xFE
+#define _DS1S	0x40
+#define _DS1E	0x7E
+#define _DS2S	0x80
+#define _DS2E	0xFE
+
+#elif _CODE_PAGE == 949	/* CP949 (Korean) */
+#define _DF1S	0x81
+#define _DF1E	0xFE
+#define _DS1S	0x41
+#define _DS1E	0x5A
+#define _DS2S	0x61
+#define _DS2E	0x7A
+#define _DS3S	0x81
+#define _DS3E	0xFE
+
+#elif _CODE_PAGE == 950	/* CP950 (Traditional Chinese Big5) */
+#define _DF1S	0x81
+#define _DF1E	0xFE
+#define _DS1S	0x40
+#define _DS1E	0x7E
+#define _DS2S	0xA1
+#define _DS2E	0xFE
+
+#else					/* SBCS code pages */
+#define _DF1S	0
+
+#endif
+
+
+
+/* Character code support macros */
+
+#define IsUpper(c)	(((c)>='A')&&((c)<='Z'))
+#define IsLower(c)	(((c)>='a')&&((c)<='z'))
+#define IsDigit(c)	(((c)>='0')&&((c)<='9'))
+
+#if _DF1S	/* DBCS configuration */
+
+#if _DF2S	/* Two 1st byte areas */
+#define IsDBCS1(c)	(((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E))
+#else		/* One 1st byte area */
+#define IsDBCS1(c)	((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E)
+#endif
+
+#if _DS3S	/* Three 2nd byte areas */
+#define IsDBCS2(c)	(((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E))
+#else		/* Two 2nd byte areas */
+#define IsDBCS2(c)	(((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E))
+#endif
+
+#else		/* SBCS configuration */
+
+#define IsDBCS1(c)	0
+#define IsDBCS2(c)	0
+
+#endif /* _DF1S */
+
+
+
+/* Definitions corresponds to multi partition */
+
+#if _MULTI_PARTITION		/* Multiple partition configuration */
+
+typedef struct _PARTITION {
+	BYTE pd;	/* Physical drive# */
+	BYTE pt;	/* Partition # (0-3) */
+} PARTITION;
+
+extern
+const PARTITION Drives[];			/* Logical drive# to physical location conversion table */
+#define LD2PD(drv) (Drives[drv].pd)	/* Get physical drive# */
+#define LD2PT(drv) (Drives[drv].pt)	/* Get partition# */
+
+#else						/* Single partition configuration */
+
+#define LD2PD(drv) (drv)	/* Physical drive# is equal to the logical drive# */
+#define LD2PT(drv) 0		/* Always mounts the 1st partition */
+
+#endif
+
+
+
+/* File function return code (FRESULT) */
+
+typedef enum {
+	FR_OK = 0,			/* 0 */
+	FR_DISK_ERR,		/* 1 */
+	FR_INT_ERR,			/* 2 */
+	FR_NOT_READY,		/* 3 */
+	FR_NO_FILE,			/* 4 */
+	FR_NO_PATH,			/* 5 */
+	FR_INVALID_NAME,	/* 6 */
+	FR_DENIED,			/* 7 */
+	FR_EXIST,			/* 8 */
+	FR_INVALID_OBJECT,	/* 9 */
+	FR_WRITE_PROTECTED,	/* 10 */
+	FR_INVALID_DRIVE,	/* 11 */
+	FR_NOT_ENABLED,		/* 12 */
+	FR_NO_FILESYSTEM,	/* 13 */
+	FR_MKFS_ABORTED,	/* 14 */
+	FR_TIMEOUT			/* 15 */
+} FRESULT;
+
+
+
+/*--------------------------------------------------------------*/
+/* FatFs module application interface                           */
+
+FRESULT f_mount (BYTE, FATFS*);						/* Mount/Unmount a logical drive */
+FRESULT f_open (FIL*, const char*, BYTE);			/* Open or create a file */
+FRESULT f_read (FIL*, void*, UINT, UINT*);			/* Read data from a file */
+FRESULT f_write (FIL*, const void*, UINT, UINT*);	/* Write data to a file */
+FRESULT f_lseek (FIL*, DWORD);						/* Move file pointer of a file object */
+FRESULT f_close (FIL*);								/* Close an open file object */
+FRESULT f_opendir (DIR*, const char*);				/* Open an existing directory */
+FRESULT f_readdir (DIR*, FILINFO*);					/* Read a directory item */
+FRESULT f_stat (const char*, FILINFO*);				/* Get file status */
+FRESULT f_getfree (const char*, DWORD*, FATFS**);	/* Get number of free clusters on the drive */
+FRESULT f_truncate (FIL*);							/* Truncate file */
+FRESULT f_sync (FIL*);								/* Flush cached data of a writing file */
+FRESULT f_unlink (const char*);						/* Delete an existing file or directory */
+FRESULT	f_mkdir (const char*);						/* Create a new directory */
+FRESULT f_chmod (const char*, BYTE, BYTE);			/* Change attriburte of the file/dir */
+FRESULT f_utime (const char*, const FILINFO*);		/* Change timestamp of the file/dir */
+FRESULT f_rename (const char*, const char*);		/* Rename/Move a file or directory */
+FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*);	/* Forward data to the stream */
+FRESULT f_mkfs (BYTE, BYTE, WORD);					/* Create a file system on the drive */
+
+#if _USE_STRFUNC
+int f_putc (int, FIL*);								/* Put a character to the file */
+int f_puts (const char*, FIL*);						/* Put a string to the file */
+int f_printf (FIL*, const char*, ...);				/* Put a formatted string to the file */
+char* f_gets (char*, int, FIL*);					/* Get a string from the file */
+#define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0)
+#define f_error(fp) (((fp)->flag & FA__ERROR) ? 1 : 0)
+#ifndef EOF
+#define EOF -1
+#endif
+#endif
+
+
+
+/*--------------------------------------------------------------*/
+/* User defined functions                                       */
+
+/* Real time clock */
+#if !_FS_READONLY
+DWORD get_fattime (void);	/* 31-25: Year(0-127 org.1980), 24-21: Month(1-12), 20-16: Day(1-31) */
+							/* 15-11: Hour(0-23), 10-5: Minute(0-59), 4-0: Second(0-29 *2) */
+#endif
+
+/* Unicode - OEM code conversion */
+#if _USE_LFN
+WCHAR ff_convert (WCHAR, UINT);
+#endif
+
+/* Sync functions */
+#if _FS_REENTRANT
+BOOL ff_cre_syncobj(BYTE, _SYNC_t*);
+BOOL ff_del_syncobj(_SYNC_t);
+BOOL ff_req_grant(_SYNC_t);
+void ff_rel_grant(_SYNC_t);
+#endif
+
+
+
+/*--------------------------------------------------------------*/
+/* Flags and offset address                                     */
+
+
+/* File access control and file status flags (FIL.flag) */
+
+#define	FA_READ				0x01
+#define	FA_OPEN_EXISTING	0x00
+#if _FS_READONLY == 0
+#define	FA_WRITE			0x02
+#define	FA_CREATE_NEW		0x04
+#define	FA_CREATE_ALWAYS	0x08
+#define	FA_OPEN_ALWAYS		0x10
+#define FA__WRITTEN			0x20
+#define FA__DIRTY			0x40
+#endif
+#define FA__ERROR			0x80
+
+
+/* FAT sub type (FATFS.fs_type) */
+
+#define FS_FAT12	1
+#define FS_FAT16	2
+#define FS_FAT32	3
+
+
+/* File attribute bits for directory entry */
+
+#define	AM_RDO	0x01	/* Read only */
+#define	AM_HID	0x02	/* Hidden */
+#define	AM_SYS	0x04	/* System */
+#define	AM_VOL	0x08	/* Volume label */
+#define AM_LFN	0x0F	/* LFN entry */
+#define AM_DIR	0x10	/* Directory */
+#define AM_ARC	0x20	/* Archive */
+#define AM_MASK	0x3F	/* Mask of defined bits */
+
+
+/* FatFs refers the members in the FAT structures with byte offset instead
+/ of structure member because there are incompatibility of the packing option
+/ between various compilers. */
+
+#define BS_jmpBoot			0
+#define BS_OEMName			3
+#define BPB_BytsPerSec		11
+#define BPB_SecPerClus		13
+#define BPB_RsvdSecCnt		14
+#define BPB_NumFATs			16
+#define BPB_RootEntCnt		17
+#define BPB_TotSec16		19
+#define BPB_Media			21
+#define BPB_FATSz16			22
+#define BPB_SecPerTrk		24
+#define BPB_NumHeads		26
+#define BPB_HiddSec			28
+#define BPB_TotSec32		32
+#define BS_55AA				510
+
+#define BS_DrvNum			36
+#define BS_BootSig			38
+#define BS_VolID			39
+#define BS_VolLab			43
+#define BS_FilSysType		54
+
+#define BPB_FATSz32			36
+#define BPB_ExtFlags		40
+#define BPB_FSVer			42
+#define BPB_RootClus		44
+#define BPB_FSInfo			48
+#define BPB_BkBootSec		50
+#define BS_DrvNum32			64
+#define BS_BootSig32		66
+#define BS_VolID32			67
+#define BS_VolLab32			71
+#define BS_FilSysType32		82
+
+#define	FSI_LeadSig			0
+#define	FSI_StrucSig		484
+#define	FSI_Free_Count		488
+#define	FSI_Nxt_Free		492
+
+#define MBR_Table			446
+
+#define	DIR_Name			0
+#define	DIR_Attr			11
+#define	DIR_NTres			12
+#define	DIR_CrtTime			14
+#define	DIR_CrtDate			16
+#define	DIR_FstClusHI		20
+#define	DIR_WrtTime			22
+#define	DIR_WrtDate			24
+#define	DIR_FstClusLO		26
+#define	DIR_FileSize		28
+#define	LDIR_Ord			0
+#define	LDIR_Attr			11
+#define	LDIR_Type			12
+#define	LDIR_Chksum			13
+#define	LDIR_FstClusLO		26
+
+
+
+/*--------------------------------*/
+/* Multi-byte word access macros  */
+
+#if _WORD_ACCESS == 1	/* Enable word access to the FAT structure */
+#define	LD_WORD(ptr)		(WORD)(*(WORD*)(BYTE*)(ptr))
+#define	LD_DWORD(ptr)		(DWORD)(*(DWORD*)(BYTE*)(ptr))
+#define	ST_WORD(ptr,val)	*(WORD*)(BYTE*)(ptr)=(WORD)(val)
+#define	ST_DWORD(ptr,val)	*(DWORD*)(BYTE*)(ptr)=(DWORD)(val)
+#else					/* Use byte-by-byte access to the FAT structure */
+#define	LD_WORD(ptr)		(WORD)(((WORD)*(BYTE*)((ptr)+1)<<8)|(WORD)*(BYTE*)(ptr))
+#define	LD_DWORD(ptr)		(DWORD)(((DWORD)*(BYTE*)((ptr)+3)<<24)|((DWORD)*(BYTE*)((ptr)+2)<<16)|((WORD)*(BYTE*)((ptr)+1)<<8)|*(BYTE*)(ptr))
+#define	ST_WORD(ptr,val)	*(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8)
+#define	ST_DWORD(ptr,val)	*(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8); *(BYTE*)((ptr)+2)=(BYTE)((DWORD)(val)>>16); *(BYTE*)((ptr)+3)=(BYTE)((DWORD)(val)>>24)
+#endif
+
+
+#endif /* _FATFS */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/fffcntl.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/fffcntl.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/fffcntl.c	(revision 453)
@@ -0,0 +1,492 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2012 by GT Development Center RICOH COMPANY,LTD. JAPAN
+ * 
+ *  上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+ *  によって公表されている GNU General Public License の Version 2 に記
+ *  述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+ *  を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+ *  含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+ *  接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ * FatFS用POSIX変換用関数
+ * 1. ff_opendir               FatFSファイルのオープンディレクトリ
+ * 2. ff_closedir              FatFSファイルのクローズディレクトリ
+ * 3. ff_readdir               FatFSファイルのディレクトリエントリ読み出し
+ * 4. ff_mkdir                 FatFSファイルのディレクトリ作成
+ * 5. ff_unlink                FatFSファイルのディレクトリまたはファイル削除
+ * 6. ff_rename                FatFSファイルのリネーム
+ * 7. ff_chmod                 FatFSファイルのチェンジモード
+ * 8. ff_stat                  FatFSファイルのダイレクトステートの取り出し
+ * 9. ff_statfs                FatFSファイルのシステムステータスの取り出し
+ * 10.ff_open                  FatFSファイルのオープン
+ * 11.ff_close                 FatFSファイルのクローズ
+ * 12.ff_fstat                 FatFSファイルのステートの取り出し
+ * 13.ff_fseek                 FatFSファイルのシーク
+ * 14.ff_read                  FatFSファイルからのデータ読み出し
+ * 15.ff_write                 FatFSファイルへのデータ書き込み
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "storagedevice.h"
+#include "ff.h"
+
+#ifndef NUM_DIRNEST
+#define NUM_DIRNEST 4
+#endif
+#ifndef NUM_FIL
+#define NUM_FIL     16
+#endif
+
+#define	S_IRUSR	0000400	/* read permission, owner */
+#define	S_IWUSR	0000200	/* write permission, owner */
+#define	S_IXUSR 0000100/* execute/search permission, owner */
+#define	S_IRGRP	0000040	/* read permission, group */
+#define	S_IWGRP	0000020	/* write permission, grougroup */
+#define	S_IXGRP 0000010/* execute/search permission, group */
+#define	S_IROTH	0000004	/* read permission, other */
+#define	S_IWOTH	0000002	/* write permission, other */
+#define	S_IXOTH 0000001/* execute/search permission, other */
+
+#define	FF_EINVAL 22	/* Invalid argument */
+
+static void *ff_opendir(const char *pathname);
+static int ff_closedir(void *dir);
+static int ff_readdir(void *dir, void *pdirent);
+static int ff_mkdir(const char *pathname);
+static int ff_unlink(const char *pathname);
+static int ff_rename(const char *oname, const char *nname);
+static int ff_chmod(const char *name, int mode);
+static int ff_stat(const char *name, struct stat *buf);
+static int ff_statfs(const char *name, void *status);
+static int ff_open(int devno, const char *pathname, int flags);
+static int ff_close(int fd);
+static int ff_fstat(int fd, struct stat *buf);
+static off_t ff_lseek(int fd, off_t offset, int whence, int *res);
+static long ff_read(int fd, void *buf, long count, int *res);
+static long ff_write(int fd, const void *buf, long count, int *res);
+
+
+const StorageDeviceFileFunc_t fatfsSDeviceFileFunc = {
+	ff_opendir,
+	ff_closedir,
+	ff_readdir,
+	ff_mkdir,
+	ff_unlink,
+	ff_unlink,
+	ff_rename,
+	ff_chmod,
+	ff_stat,
+	ff_statfs,
+	ff_open,
+	ff_close,
+	ff_fstat,
+	ff_lseek,
+	ff_read,
+	ff_write,
+	0
+};
+
+typedef struct DIRPACK {
+	DIR      dir;
+	FILINFO  finfo;
+} DIRP;
+
+static FIL   FileObj[NUM_FIL];
+static DIRP  dirobj[NUM_DIRNEST];
+static UH    long_file_name[128];
+static int   opendircount = 0;
+static char  sddevname[256];
+static int   ff_errno;
+
+/*
+ *  FatFsファイルディレクトリオープン
+ */
+static void *ff_opendir(const char *pathname)
+{
+	DIRP *dirp;
+	FRESULT result;
+
+	if(opendircount >= NUM_DIRNEST)
+		return NULL;
+	dirp = &dirobj[opendircount++];
+	if((result = f_opendir(&dirp->dir, pathname)) != FR_OK){
+		ff_errno = result;
+		opendircount--;
+		return NULL;
+	}
+	else
+		return dirp;
+}
+
+/*
+ *  FatFsファイルディレクトリクローズ
+ */
+static int ff_closedir(void *dir)
+{
+	if(opendircount > 0)
+		opendircount--;
+	return 0;
+}
+
+/*
+ *  FatFsファイルディレクトリ読み込み
+ */
+static int ff_readdir(void *dir, void *pdirent)
+{
+	struct dirent2 *pd = pdirent;
+	DIRP   *dirp = dir;
+	FRESULT result;
+
+#if _USE_LFN != 0
+	dirp->dir.lfn = long_file_name;
+#endif
+	if((result = f_readdir(&dirp->dir, &dirp->finfo)) != FR_OK){
+		ff_errno = result;
+		return 0;
+	}
+	if(dirp->dir.sect == 0)
+		return 0;
+	pd->d_fsize = dirp->finfo.fsize;
+	pd->d_date  = dirp->finfo.fdate;
+	pd->d_time  = dirp->finfo.ftime;
+	pd->d_type  = dirp->finfo.fattrib;
+#if _USE_LFN != 0
+	if(dirp->dir.lfn_idx != 0xffff){
+		UH *pw, data;
+		UB *p, *pe;
+		pw = dirp->dir.lfn;
+		p  = pd->d_name;
+		pe = p+254;
+		while(*pw != 0 && p < pe){
+			data = ff_convert(*pw, 0);
+			if(data <= 0x80)
+				*p++ = (UB)data;
+			else{
+				*p++ = data >> 8;
+				*p++ = (UB)data;
+			}
+			pw++;
+		}
+		*p = 0;
+	}
+	else
+#endif
+	{
+		int     i;
+		for(i = 0 ; i < (8+1+3) && dirp->finfo.fname[i] != 0 ; i++)
+			pd->d_name[i] = dirp->finfo.fname[i];
+		pd->d_name[i] = 0;
+	}
+	return 1;
+}
+
+/*
+ *  FatFsディレクトリ作成
+ */
+static int ff_mkdir(const char *pathname)
+{
+	int result = f_mkdir(pathname);
+	if(result == FR_OK)
+		return 0;
+	else{
+		ff_errno = result;
+		return -1;
+	}
+}
+
+/*
+ *  FatFsディレクトリ/ファイル削除
+ */
+static int ff_unlink(const char *pathname)
+{
+	int result = f_unlink(pathname);
+	if(result == FR_OK)
+		return 0;
+	else{
+		ff_errno = result;
+		return -1;
+	}
+}
+
+/*
+ *  FatFsリネーム
+ */
+static int ff_rename(const char *oname, const char *nname)
+{
+	int result = f_rename(oname, nname);
+	if(result == FR_OK)
+		return 0;
+	else{
+		ff_errno = result;
+		return -1;
+	}
+}
+
+/*
+ *  FatFsモード変更
+ */
+static int ff_chmod(const char *name, int mode)
+{
+	FRESULT result;
+	BYTE value = 0;
+	BYTE mask  = AM_RDO;
+
+	if((mode & (S_IWUSR|S_IWGRP|S_IWOTH)) == 0){
+		value |= AM_RDO;
+	}
+	result = f_chmod(name, value, mask);
+	if(result == FR_OK)
+		return 0;
+	else{
+		ff_errno = result;
+		return -1;
+	}
+}
+
+/*
+ *  FatFs直接ファイルステート取得
+ */
+static int ff_stat(const char *name, struct stat *buf)
+{
+	FILINFO finfo;
+	FRESULT result;
+
+	memset(buf, 0, sizeof(struct stat));
+	finfo.lfname = NULL;
+	result = f_stat(name, &finfo);
+	if(result == FR_OK){
+		buf->st_mode = S_IRUSR|S_IRGRP|S_IROTH;
+		if((finfo.fattrib & AM_RDO) == 0)
+			buf->st_mode |= S_IWUSR|S_IWGRP|S_IWOTH;
+		buf->st_blksize = 512;
+		buf->st_blocks  = (finfo.fsize+buf->st_blksize-1)/buf->st_blksize;
+		buf->st_size = finfo.fsize;
+		return 0;
+	}
+	else{
+		ff_errno = result;
+		return -1;
+	}
+}
+
+/*
+ *  FatFsシステムステータスの取り出し
+ */
+static int ff_statfs(const char *name, void *status)
+{
+	struct statfs2 *p = status;
+	FATFS   *fatfs;
+	DWORD   nclust;
+	FRESULT result;
+
+	result = f_getfree(name, &nclust, &fatfs);
+	if(result == FR_OK){
+		memset(p, 0, sizeof(struct statfs2));
+		p->f_bsize  = fatfs->csize * _MAX_SS;
+		p->f_blocks = fatfs->max_clust-1;
+		p->f_bfree  = nclust;
+		return 0;
+	}
+	else{
+		ff_errno = result;
+		return -1;
+	}
+}
+
+/*
+ *  FatFsファイルオープン
+ */
+static int ff_open(int devno, const char *pathname, int flags)
+{
+	int result, i;
+	unsigned char mode;
+
+	if(devno < 0 || devno >= MAXIMUM_DEVNO){
+		ff_errno = FF_EINVAL;
+		return -1;
+	}
+	sddevname[0] = devno + '0';
+	sddevname[1] = ':';
+	strcpy(&sddevname[2], pathname);
+	mode = (flags+1) & 3;
+	if(flags & O_CREAT)
+		mode |= FA_OPEN_ALWAYS;
+	if(flags & O_EXCL)
+		mode |= FA_CREATE_NEW;
+	result = -1;
+	for(i = 0 ; i < NUM_FIL ; i++){
+		if(FileObj[i].fs == 0){
+			result = f_open(&FileObj[i], sddevname, mode);
+			if(result == 0)
+				return (i);
+			else
+				FileObj[i].fs = 0;
+			break;
+		}
+	}
+	ff_errno = result;
+	return -1;
+}
+
+/*
+ *  FatFsファイルクローズ
+ */
+static int ff_close(int fd)
+{
+	FRESULT result;
+
+	if(fd >= NUM_FIL){
+		ff_errno = FF_EINVAL;
+		return -1;
+	}
+	result = f_close(&FileObj[fd]);
+	if(result == FR_OK)
+		return 0;
+	else{
+		ff_errno = result;
+		return -1;
+	}
+}
+
+/*
+ *  FatFsファイルステート取得
+ */
+static int ff_fstat(int fd, struct stat *buf)
+{
+	if(fd >= NUM_FIL){
+		ff_errno = FF_EINVAL;
+		return -1;
+	}
+	memset(buf, 0, sizeof(struct stat));
+	buf->st_size = FileObj[fd].fsize;
+#ifdef _EXT_RTOS
+	buf->st_mtime = (FileObj[fd.fdate<<16)
+                   | FileObj[fd].ftime;
+#endif
+	buf->st_atime = buf->st_ctime
+                  = buf->st_mtime;
+	buf->st_mode = S_IRUSR|S_IRGRP|S_IROTH;
+	if((FileObj[fd].flag & FA_WRITE) != 0)
+		buf->st_mode |= S_IWUSR|S_IWGRP|S_IWOTH;
+	return 0;
+}
+
+/*
+ *  FatFsファイルシーク
+ */
+static off_t ff_lseek(int fd, off_t offset, int whence, int *res)
+{
+	off_t off = 0;
+	FRESULT result;
+
+	*res = -1;
+	if(fd >= NUM_FIL){
+		ff_errno = FF_EINVAL;
+		return -1;
+	}
+	switch (whence) {
+	case SEEK_SET:
+		off = offset;
+		break;
+	case SEEK_CUR:
+		off = FileObj[fd].fptr + offset;
+		break;
+	case SEEK_END:
+		off = FileObj[fd].fsize + offset;
+		break;
+	default:
+		ff_errno =  FF_EINVAL;
+		return -1;
+	}
+	result = f_lseek(&FileObj[fd], off);
+	if(result != FR_OK){
+		ff_errno = result;
+		off = -1;
+	}
+	else
+		*res = 0;
+	return off;
+}
+
+/*
+ *  FatFsファイル読みだし
+ */
+static long ff_read(int fd, void *buf, long count, int *res)
+{
+	long n;
+	FRESULT result;
+
+	*res = -1;
+	if(fd >= NUM_FIL){
+		ff_errno = FF_EINVAL;
+		return 0;
+	}
+	result =  f_read(&FileObj[fd], buf, count, (unsigned int *)&n);
+	if(result != FR_OK){
+		ff_errno = result;
+		n = 0;
+	}
+	else
+		*res = 0;
+	return n;
+}
+
+/*
+ *  FatFsファイル書き込み
+ */
+static long ff_write(int fd, const void *buf, long count, int *res)
+{
+	long n = 0;
+	FRESULT result;
+
+	*res = -1;
+	if(fd >= NUM_FIL){
+		ff_errno = FF_EINVAL;
+		return 0;
+	}
+	result = f_write(&FileObj[fd], buf, count, (unsigned int *)&n);
+	if(result != FR_OK){
+		ff_errno = result;
+		n = 0;
+	}
+	else
+		*res = 0;
+	return n;
+}
+
+/* This function is called each time errno is evaluated. */
+int *__errno(void)
+{
+	return (int *)&ff_errno;
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/integer.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/integer.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/integer.h	(revision 453)
@@ -0,0 +1,42 @@
+/*-------------------------------------------*/
+/* Integer type definitions for FatFs module */
+/*-------------------------------------------*/
+
+#ifndef _INTEGER
+
+#if 0
+#include <windows.h>
+#else
+#include <itron.h>
+
+#if 0	/* ROI DEBUG */
+/* These types must be 16-bit, 32-bit or larger integer */
+typedef int				INT;
+typedef unsigned int	UINT;
+#endif	/* ROI DEBUG */
+
+/* These types must be 8-bit integer */
+typedef signed char		CHAR;
+typedef unsigned char	UCHAR;
+typedef unsigned char	BYTE;
+
+/* These types must be 16-bit integer */
+typedef short			SHORT;
+typedef unsigned short	USHORT;
+typedef unsigned short	WORD;
+typedef unsigned short	WCHAR;
+
+/* These types must be 32-bit integer */
+typedef long			LONG;
+typedef unsigned long	ULONG;
+typedef unsigned long	DWORD;
+
+#if 0	/* ROI DEBUG */
+/* Boolean type */
+typedef enum { FALSE = 0, TRUE } BOOL;
+#endif	/* ROI DEBUG */
+
+#endif
+
+#define _INTEGER
+#endif
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/option/cc932.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/option/cc932.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/option/cc932.c	(revision 453)
@@ -0,0 +1,3784 @@
+/*------------------------------------------------------------------------*/
+/* Unicode - OEM code bidirectional converter  (C)ChaN, 2009              */
+/*                                                                        */
+/* CP932 (Japanese Shift-JIS)                                             */
+/*------------------------------------------------------------------------*/
+
+#include "../ff.h"
+
+#define _TINY_TABLE	0
+
+#if _USE_LFN && _CODE_PAGE == 932
+
+
+static
+const WCHAR uni2sjis[] = {
+/*  Unicode - Sjis, Unicode - Sjis, Unicode - Sjis, Unicode - Sjis, */
+	0x00A7, 0x8198, 0x00A8, 0x814E, 0x00B0, 0x818B, 0x00B1, 0x817D,
+	0x00B4, 0x814C, 0x00B6, 0x81F7, 0x00D7, 0x817E, 0x00F7, 0x8180,
+	0x0391, 0x839F, 0x0392, 0x83A0, 0x0393, 0x83A1, 0x0394, 0x83A2,
+	0x0395, 0x83A3, 0x0396, 0x83A4, 0x0397, 0x83A5, 0x0398, 0x83A6,
+	0x0399, 0x83A7, 0x039A, 0x83A8, 0x039B, 0x83A9, 0x039C, 0x83AA,
+	0x039D, 0x83AB, 0x039E, 0x83AC, 0x039F, 0x83AD, 0x03A0, 0x83AE,
+	0x03A1, 0x83AF, 0x03A3, 0x83B0, 0x03A4, 0x83B1, 0x03A5, 0x83B2,
+	0x03A6, 0x83B3, 0x03A7, 0x83B4, 0x03A8, 0x83B5, 0x03A9, 0x83B6,
+	0x03B1, 0x83BF, 0x03B2, 0x83C0, 0x03B3, 0x83C1, 0x03B4, 0x83C2,
+	0x03B5, 0x83C3, 0x03B6, 0x83C4, 0x03B7, 0x83C5, 0x03B8, 0x83C6,
+	0x03B9, 0x83C7, 0x03BA, 0x83C8, 0x03BB, 0x83C9, 0x03BC, 0x83CA,
+	0x03BD, 0x83CB, 0x03BE, 0x83CC, 0x03BF, 0x83CD, 0x03C0, 0x83CE,
+	0x03C1, 0x83CF, 0x03C3, 0x83D0, 0x03C4, 0x83D1, 0x03C5, 0x83D2,
+	0x03C6, 0x83D3, 0x03C7, 0x83D4, 0x03C8, 0x83D5, 0x03C9, 0x83D6,
+	0x0401, 0x8446, 0x0410, 0x8440, 0x0411, 0x8441, 0x0412, 0x8442,
+	0x0413, 0x8443, 0x0414, 0x8444, 0x0415, 0x8445, 0x0416, 0x8447,
+	0x0417, 0x8448, 0x0418, 0x8449, 0x0419, 0x844A, 0x041A, 0x844B,
+	0x041B, 0x844C, 0x041C, 0x844D, 0x041D, 0x844E, 0x041E, 0x844F,
+	0x041F, 0x8450, 0x0420, 0x8451, 0x0421, 0x8452, 0x0422, 0x8453,
+	0x0423, 0x8454, 0x0424, 0x8455, 0x0425, 0x8456, 0x0426, 0x8457,
+	0x0427, 0x8458, 0x0428, 0x8459, 0x0429, 0x845A, 0x042A, 0x845B,
+	0x042B, 0x845C, 0x042C, 0x845D, 0x042D, 0x845E, 0x042E, 0x845F,
+	0x042F, 0x8460, 0x0430, 0x8470, 0x0431, 0x8471, 0x0432, 0x8472,
+	0x0433, 0x8473, 0x0434, 0x8474, 0x0435, 0x8475, 0x0436, 0x8477,
+	0x0437, 0x8478, 0x0438, 0x8479, 0x0439, 0x847A, 0x043A, 0x847B,
+	0x043B, 0x847C, 0x043C, 0x847D, 0x043D, 0x847E, 0x043E, 0x8480,
+	0x043F, 0x8481, 0x0440, 0x8482, 0x0441, 0x8483, 0x0442, 0x8484,
+	0x0443, 0x8485, 0x0444, 0x8486, 0x0445, 0x8487, 0x0446, 0x8488,
+	0x0447, 0x8489, 0x0448, 0x848A, 0x0449, 0x848B, 0x044A, 0x848C,
+	0x044B, 0x848D, 0x044C, 0x848E, 0x044D, 0x848F, 0x044E, 0x8490,
+	0x044F, 0x8491, 0x0451, 0x8476, 0x2010, 0x815D, 0x2015, 0x815C,
+	0x2018, 0x8165, 0x2019, 0x8166, 0x201C, 0x8167, 0x201D, 0x8168,
+	0x2020, 0x81F5, 0x2021, 0x81F6, 0x2025, 0x8164, 0x2026, 0x8163,
+	0x2030, 0x81F1, 0x2032, 0x818C, 0x2033, 0x818D, 0x203B, 0x81A6,
+	0x2103, 0x818E, 0x2116, 0x8782, 0x2121, 0x8784, 0x212B, 0x81F0,
+	0x2160, 0x8754, 0x2161, 0x8755, 0x2162, 0x8756, 0x2163, 0x8757,
+	0x2164, 0x8758, 0x2165, 0x8759, 0x2166, 0x875A, 0x2167, 0x875B,
+	0x2168, 0x875C, 0x2169, 0x875D, 0x2170, 0xFA40, 0x2171, 0xFA41,
+	0x2172, 0xFA42, 0x2173, 0xFA43, 0x2174, 0xFA44, 0x2175, 0xFA45,
+	0x2176, 0xFA46, 0x2177, 0xFA47, 0x2178, 0xFA48, 0x2179, 0xFA49,
+	0x2190, 0x81A9, 0x2191, 0x81AA, 0x2192, 0x81A8, 0x2193, 0x81AB,
+	0x21D2, 0x81CB, 0x21D4, 0x81CC, 0x2200, 0x81CD, 0x2202, 0x81DD,
+	0x2203, 0x81CE, 0x2207, 0x81DE, 0x2208, 0x81B8, 0x220B, 0x81B9,
+	0x2211, 0x8794, 0x221A, 0x81E3, 0x221D, 0x81E5, 0x221E, 0x8187,
+	0x221F, 0x8798, 0x2220, 0x81DA, 0x2225, 0x8161, 0x2227, 0x81C8,
+	0x2228, 0x81C9, 0x2229, 0x81BF, 0x222A, 0x81BE, 0x222B, 0x81E7,
+	0x222C, 0x81E8, 0x222E, 0x8793, 0x2234, 0x8188, 0x2235, 0x81E6,
+	0x223D, 0x81E4, 0x2252, 0x81E0, 0x2260, 0x8182, 0x2261, 0x81DF,
+	0x2266, 0x8185, 0x2267, 0x8186, 0x226A, 0x81E1, 0x226B, 0x81E2,
+	0x2282, 0x81BC, 0x2283, 0x81BD, 0x2286, 0x81BA, 0x2287, 0x81BB,
+	0x22A5, 0x81DB, 0x22BF, 0x8799, 0x2312, 0x81DC, 0x2460, 0x8740,
+	0x2461, 0x8741, 0x2462, 0x8742, 0x2463, 0x8743, 0x2464, 0x8744,
+	0x2465, 0x8745, 0x2466, 0x8746, 0x2467, 0x8747, 0x2468, 0x8748,
+	0x2469, 0x8749, 0x246A, 0x874A, 0x246B, 0x874B, 0x246C, 0x874C,
+	0x246D, 0x874D, 0x246E, 0x874E, 0x246F, 0x874F, 0x2470, 0x8750,
+	0x2471, 0x8751, 0x2472, 0x8752, 0x2473, 0x8753, 0x2500, 0x849F,
+	0x2501, 0x84AA, 0x2502, 0x84A0, 0x2503, 0x84AB, 0x250C, 0x84A1,
+	0x250F, 0x84AC, 0x2510, 0x84A2, 0x2513, 0x84AD, 0x2514, 0x84A4,
+	0x2517, 0x84AF, 0x2518, 0x84A3, 0x251B, 0x84AE, 0x251C, 0x84A5,
+	0x251D, 0x84BA, 0x2520, 0x84B5, 0x2523, 0x84B0, 0x2524, 0x84A7,
+	0x2525, 0x84BC, 0x2528, 0x84B7, 0x252B, 0x84B2, 0x252C, 0x84A6,
+	0x252F, 0x84B6, 0x2530, 0x84BB, 0x2533, 0x84B1, 0x2534, 0x84A8,
+	0x2537, 0x84B8, 0x2538, 0x84BD, 0x253B, 0x84B3, 0x253C, 0x84A9,
+	0x253F, 0x84B9, 0x2542, 0x84BE, 0x254B, 0x84B4, 0x25A0, 0x81A1,
+	0x25A1, 0x81A0, 0x25B2, 0x81A3, 0x25B3, 0x81A2, 0x25BC, 0x81A5,
+	0x25BD, 0x81A4, 0x25C6, 0x819F, 0x25C7, 0x819E, 0x25CB, 0x819B,
+	0x25CE, 0x819D, 0x25CF, 0x819C, 0x25EF, 0x81FC, 0x2605, 0x819A,
+	0x2606, 0x8199, 0x2640, 0x818A, 0x2642, 0x8189, 0x266A, 0x81F4,
+	0x266D, 0x81F3, 0x266F, 0x81F2, 0x3000, 0x8140, 0x3001, 0x8141,
+	0x3002, 0x8142, 0x3003, 0x8156, 0x3005, 0x8158, 0x3006, 0x8159,
+	0x3007, 0x815A, 0x3008, 0x8171, 0x3009, 0x8172, 0x300A, 0x8173,
+	0x300B, 0x8174, 0x300C, 0x8175, 0x300D, 0x8176, 0x300E, 0x8177,
+	0x300F, 0x8178, 0x3010, 0x8179, 0x3011, 0x817A, 0x3012, 0x81A7,
+	0x3013, 0x81AC, 0x3014, 0x816B, 0x3015, 0x816C, 0x301D, 0x8780,
+	0x301F, 0x8781, 0x3041, 0x829F, 0x3042, 0x82A0, 0x3043, 0x82A1,
+	0x3044, 0x82A2, 0x3045, 0x82A3, 0x3046, 0x82A4, 0x3047, 0x82A5,
+	0x3048, 0x82A6, 0x3049, 0x82A7, 0x304A, 0x82A8, 0x304B, 0x82A9,
+	0x304C, 0x82AA, 0x304D, 0x82AB, 0x304E, 0x82AC, 0x304F, 0x82AD,
+	0x3050, 0x82AE, 0x3051, 0x82AF, 0x3052, 0x82B0, 0x3053, 0x82B1,
+	0x3054, 0x82B2, 0x3055, 0x82B3, 0x3056, 0x82B4, 0x3057, 0x82B5,
+	0x3058, 0x82B6, 0x3059, 0x82B7, 0x305A, 0x82B8, 0x305B, 0x82B9,
+	0x305C, 0x82BA, 0x305D, 0x82BB, 0x305E, 0x82BC, 0x305F, 0x82BD,
+	0x3060, 0x82BE, 0x3061, 0x82BF, 0x3062, 0x82C0, 0x3063, 0x82C1,
+	0x3064, 0x82C2, 0x3065, 0x82C3, 0x3066, 0x82C4, 0x3067, 0x82C5,
+	0x3068, 0x82C6, 0x3069, 0x82C7, 0x306A, 0x82C8, 0x306B, 0x82C9,
+	0x306C, 0x82CA, 0x306D, 0x82CB, 0x306E, 0x82CC, 0x306F, 0x82CD,
+	0x3070, 0x82CE, 0x3071, 0x82CF, 0x3072, 0x82D0, 0x3073, 0x82D1,
+	0x3074, 0x82D2, 0x3075, 0x82D3, 0x3076, 0x82D4, 0x3077, 0x82D5,
+	0x3078, 0x82D6, 0x3079, 0x82D7, 0x307A, 0x82D8, 0x307B, 0x82D9,
+	0x307C, 0x82DA, 0x307D, 0x82DB, 0x307E, 0x82DC, 0x307F, 0x82DD,
+	0x3080, 0x82DE, 0x3081, 0x82DF, 0x3082, 0x82E0, 0x3083, 0x82E1,
+	0x3084, 0x82E2, 0x3085, 0x82E3, 0x3086, 0x82E4, 0x3087, 0x82E5,
+	0x3088, 0x82E6, 0x3089, 0x82E7, 0x308A, 0x82E8, 0x308B, 0x82E9,
+	0x308C, 0x82EA, 0x308D, 0x82EB, 0x308E, 0x82EC, 0x308F, 0x82ED,
+	0x3090, 0x82EE, 0x3091, 0x82EF, 0x3092, 0x82F0, 0x3093, 0x82F1,
+	0x3094, 0x8394, 0x309B, 0x814A, 0x309C, 0x814B, 0x309D, 0x8154,
+	0x309E, 0x8155, 0x30A1, 0x8340, 0x30A2, 0x8341, 0x30A3, 0x8342,
+	0x30A4, 0x8343, 0x30A5, 0x8344, 0x30A6, 0x8345, 0x30A7, 0x8346,
+	0x30A8, 0x8347, 0x30A9, 0x8348, 0x30AA, 0x8349, 0x30AB, 0x834A,
+	0x30AC, 0x834B, 0x30AD, 0x834C, 0x30AE, 0x834D, 0x30AF, 0x834E,
+	0x30B0, 0x834F, 0x30B1, 0x8350, 0x30B2, 0x8351, 0x30B3, 0x8352,
+	0x30B4, 0x8353, 0x30B5, 0x8354, 0x30B6, 0x8355, 0x30B7, 0x8356,
+	0x30B8, 0x8357, 0x30B9, 0x8358, 0x30BA, 0x8359, 0x30BB, 0x835A,
+	0x30BC, 0x835B, 0x30BD, 0x835C, 0x30BE, 0x835D, 0x30BF, 0x835E,
+	0x30C0, 0x835F, 0x30C1, 0x8360, 0x30C2, 0x8361, 0x30C3, 0x8362,
+	0x30C4, 0x8363, 0x30C5, 0x8364, 0x30C6, 0x8365, 0x30C7, 0x8366,
+	0x30C8, 0x8367, 0x30C9, 0x8368, 0x30CA, 0x8369, 0x30CB, 0x836A,
+	0x30CC, 0x836B, 0x30CD, 0x836C, 0x30CE, 0x836D, 0x30CF, 0x836E,
+	0x30D0, 0x836F, 0x30D1, 0x8370, 0x30D2, 0x8371, 0x30D3, 0x8372,
+	0x30D4, 0x8373, 0x30D5, 0x8374, 0x30D6, 0x8375, 0x30D7, 0x8376,
+	0x30D8, 0x8377, 0x30D9, 0x8378, 0x30DA, 0x8379, 0x30DB, 0x837A,
+	0x30DC, 0x837B, 0x30DD, 0x837C, 0x30DE, 0x837D, 0x30DF, 0x837E,
+	0x30E0, 0x8380, 0x30E1, 0x8381, 0x30E2, 0x8382, 0x30E3, 0x8383,
+	0x30E4, 0x8384, 0x30E5, 0x8385, 0x30E6, 0x8386, 0x30E7, 0x8387,
+	0x30E8, 0x8388, 0x30E9, 0x8389, 0x30EA, 0x838A, 0x30EB, 0x838B,
+	0x30EC, 0x838C, 0x30ED, 0x838D, 0x30EE, 0x838E, 0x30EF, 0x838F,
+	0x30F0, 0x8390, 0x30F1, 0x8391, 0x30F2, 0x8392, 0x30F3, 0x8393,
+	0x30F4, 0x8394, 0x30F5, 0x8395, 0x30F6, 0x8396, 0x30FB, 0x8145,
+	0x30FC, 0x815B, 0x30FD, 0x8152, 0x30FE, 0x8153, 0x3231, 0x878A,
+	0x3232, 0x878B, 0x3239, 0x878C, 0x32A4, 0x8785, 0x32A5, 0x8786,
+	0x32A6, 0x8787, 0x32A7, 0x8788, 0x32A8, 0x8789, 0x3303, 0x8765,
+	0x330D, 0x8769, 0x3314, 0x8760, 0x3318, 0x8763, 0x3322, 0x8761,
+	0x3323, 0x876B, 0x3326, 0x876A, 0x3327, 0x8764, 0x332B, 0x876C,
+	0x3336, 0x8766, 0x333B, 0x876E, 0x3349, 0x875F, 0x334A, 0x876D,
+	0x334D, 0x8762, 0x3351, 0x8767, 0x3357, 0x8768, 0x337B, 0x877E,
+	0x337C, 0x878F, 0x337D, 0x878E, 0x337E, 0x878D, 0x338E, 0x8772,
+	0x338F, 0x8773, 0x339C, 0x876F, 0x339D, 0x8770, 0x339E, 0x8771,
+	0x33A1, 0x8775, 0x33C4, 0x8774, 0x33CD, 0x8783, 0x4E00, 0x88EA,
+	0x4E01, 0x929A, 0x4E03, 0x8EB5, 0x4E07, 0x969C, 0x4E08, 0x8FE4,
+	0x4E09, 0x8E4F, 0x4E0A, 0x8FE3, 0x4E0B, 0x89BA, 0x4E0D, 0x9573,
+	0x4E0E, 0x975E, 0x4E10, 0x98A0, 0x4E11, 0x894E, 0x4E14, 0x8A8E,
+	0x4E15, 0x98A1, 0x4E16, 0x90A2, 0x4E17, 0x99C0, 0x4E18, 0x8B75,
+	0x4E19, 0x95B8, 0x4E1E, 0x8FE5, 0x4E21, 0x97BC, 0x4E26, 0x95C0,
+	0x4E28, 0xFA68, 0x4E2A, 0x98A2, 0x4E2D, 0x9286, 0x4E31, 0x98A3,
+	0x4E32, 0x8BF8, 0x4E36, 0x98A4, 0x4E38, 0x8ADB, 0x4E39, 0x924F,
+	0x4E3B, 0x8EE5, 0x4E3C, 0x98A5, 0x4E3F, 0x98A6, 0x4E42, 0x98A7,
+	0x4E43, 0x9454, 0x4E45, 0x8B76, 0x4E4B, 0x9456, 0x4E4D, 0x93E1,
+	0x4E4E, 0x8CC1, 0x4E4F, 0x9652, 0x4E55, 0xE568, 0x4E56, 0x98A8,
+	0x4E57, 0x8FE6, 0x4E58, 0x98A9, 0x4E59, 0x89B3, 0x4E5D, 0x8BE3,
+	0x4E5E, 0x8CEE, 0x4E5F, 0x96E7, 0x4E62, 0x9BA4, 0x4E71, 0x9790,
+	0x4E73, 0x93FB, 0x4E7E, 0x8AA3, 0x4E80, 0x8B54, 0x4E82, 0x98AA,
+	0x4E85, 0x98AB, 0x4E86, 0x97B9, 0x4E88, 0x975C, 0x4E89, 0x9188,
+	0x4E8A, 0x98AD, 0x4E8B, 0x8E96, 0x4E8C, 0x93F1, 0x4E8E, 0x98B0,
+	0x4E91, 0x895D, 0x4E92, 0x8CDD, 0x4E94, 0x8CDC, 0x4E95, 0x88E4,
+	0x4E98, 0x986A, 0x4E99, 0x9869, 0x4E9B, 0x8DB1, 0x4E9C, 0x889F,
+	0x4E9E, 0x98B1, 0x4E9F, 0x98B2, 0x4EA0, 0x98B3, 0x4EA1, 0x9653,
+	0x4EA2, 0x98B4, 0x4EA4, 0x8CF0, 0x4EA5, 0x88E5, 0x4EA6, 0x9692,
+	0x4EA8, 0x8B9C, 0x4EAB, 0x8B9D, 0x4EAC, 0x8B9E, 0x4EAD, 0x92E0,
+	0x4EAE, 0x97BA, 0x4EB0, 0x98B5, 0x4EB3, 0x98B6, 0x4EB6, 0x98B7,
+	0x4EBA, 0x906C, 0x4EC0, 0x8F59, 0x4EC1, 0x906D, 0x4EC2, 0x98BC,
+	0x4EC4, 0x98BA, 0x4EC6, 0x98BB, 0x4EC7, 0x8B77, 0x4ECA, 0x8DA1,
+	0x4ECB, 0x89EE, 0x4ECD, 0x98B9, 0x4ECE, 0x98B8, 0x4ECF, 0x95A7,
+	0x4ED4, 0x8E65, 0x4ED5, 0x8E64, 0x4ED6, 0x91BC, 0x4ED7, 0x98BD,
+	0x4ED8, 0x9574, 0x4ED9, 0x90E5, 0x4EDD, 0x8157, 0x4EDE, 0x98BE,
+	0x4EDF, 0x98C0, 0x4EE1, 0xFA69, 0x4EE3, 0x91E3, 0x4EE4, 0x97DF,
+	0x4EE5, 0x88C8, 0x4EED, 0x98BF, 0x4EEE, 0x89BC, 0x4EF0, 0x8BC2,
+	0x4EF2, 0x9287, 0x4EF6, 0x8C8F, 0x4EF7, 0x98C1, 0x4EFB, 0x9443,
+	0x4EFC, 0xFA6A, 0x4F00, 0xFA6B, 0x4F01, 0x8AE9, 0x4F03, 0xFA6C,
+	0x4F09, 0x98C2, 0x4F0A, 0x88C9, 0x4F0D, 0x8CDE, 0x4F0E, 0x8AEA,
+	0x4F0F, 0x959A, 0x4F10, 0x94B0, 0x4F11, 0x8B78, 0x4F1A, 0x89EF,
+	0x4F1C, 0x98E5, 0x4F1D, 0x9360, 0x4F2F, 0x948C, 0x4F30, 0x98C4,
+	0x4F34, 0x94BA, 0x4F36, 0x97E0, 0x4F38, 0x904C, 0x4F39, 0xFA6D,
+	0x4F3A, 0x8E66, 0x4F3C, 0x8E97, 0x4F3D, 0x89BE, 0x4F43, 0x92CF,
+	0x4F46, 0x9241, 0x4F47, 0x98C8, 0x4F4D, 0x88CA, 0x4F4E, 0x92E1,
+	0x4F4F, 0x8F5A, 0x4F50, 0x8DB2, 0x4F51, 0x9743, 0x4F53, 0x91CC,
+	0x4F55, 0x89BD, 0x4F56, 0xFA6E, 0x4F57, 0x98C7, 0x4F59, 0x975D,
+	0x4F5A, 0x98C3, 0x4F5B, 0x98C5, 0x4F5C, 0x8DEC, 0x4F5D, 0x98C6,
+	0x4F5E, 0x9B43, 0x4F69, 0x98CE, 0x4F6F, 0x98D1, 0x4F70, 0x98CF,
+	0x4F73, 0x89C0, 0x4F75, 0x95B9, 0x4F76, 0x98C9, 0x4F7B, 0x98CD,
+	0x4F7C, 0x8CF1, 0x4F7F, 0x8E67, 0x4F83, 0x8AA4, 0x4F86, 0x98D2,
+	0x4F88, 0x98CA, 0x4F8A, 0xFA70, 0x4F8B, 0x97E1, 0x4F8D, 0x8E98,
+	0x4F8F, 0x98CB, 0x4F91, 0x98D0, 0x4F92, 0xFA6F, 0x4F94, 0xFA72,
+	0x4F96, 0x98D3, 0x4F98, 0x98CC, 0x4F9A, 0xFA71, 0x4F9B, 0x8B9F,
+	0x4F9D, 0x88CB, 0x4FA0, 0x8BA0, 0x4FA1, 0x89BF, 0x4FAB, 0x9B44,
+	0x4FAD, 0x9699, 0x4FAE, 0x958E, 0x4FAF, 0x8CF2, 0x4FB5, 0x904E,
+	0x4FB6, 0x97B5, 0x4FBF, 0x95D6, 0x4FC2, 0x8C57, 0x4FC3, 0x91A3,
+	0x4FC4, 0x89E2, 0x4FC9, 0xFA61, 0x4FCA, 0x8F72, 0x4FCD, 0xFA73,
+	0x4FCE, 0x98D7, 0x4FD0, 0x98DC, 0x4FD1, 0x98DA, 0x4FD4, 0x98D5,
+	0x4FD7, 0x91AD, 0x4FD8, 0x98D8, 0x4FDA, 0x98DB, 0x4FDB, 0x98D9,
+	0x4FDD, 0x95DB, 0x4FDF, 0x98D6, 0x4FE1, 0x904D, 0x4FE3, 0x9693,
+	0x4FE4, 0x98DD, 0x4FE5, 0x98DE, 0x4FEE, 0x8F43, 0x4FEF, 0x98EB,
+	0x4FF3, 0x946F, 0x4FF5, 0x9555, 0x4FF6, 0x98E6, 0x4FF8, 0x95EE,
+	0x4FFA, 0x89B4, 0x4FFE, 0x98EA, 0x4FFF, 0xFA76, 0x5005, 0x98E4,
+	0x5006, 0x98ED, 0x5009, 0x9171, 0x500B, 0x8CC2, 0x500D, 0x947B,
+	0x500F, 0xE0C5, 0x5011, 0x98EC, 0x5012, 0x937C, 0x5014, 0x98E1,
+	0x5016, 0x8CF4, 0x5019, 0x8CF3, 0x501A, 0x98DF, 0x501E, 0xFA77,
+	0x501F, 0x8ED8, 0x5021, 0x98E7, 0x5022, 0xFA75, 0x5023, 0x95ED,
+	0x5024, 0x926C, 0x5025, 0x98E3, 0x5026, 0x8C91, 0x5028, 0x98E0,
+	0x5029, 0x98E8, 0x502A, 0x98E2, 0x502B, 0x97CF, 0x502C, 0x98E9,
+	0x502D, 0x9860, 0x5036, 0x8BE4, 0x5039, 0x8C90, 0x5040, 0xFA74,
+	0x5042, 0xFA7A, 0x5043, 0x98EE, 0x5046, 0xFA78, 0x5047, 0x98EF,
+	0x5048, 0x98F3, 0x5049, 0x88CC, 0x504F, 0x95CE, 0x5050, 0x98F2,
+	0x5055, 0x98F1, 0x5056, 0x98F5, 0x505A, 0x98F4, 0x505C, 0x92E2,
+	0x5065, 0x8C92, 0x506C, 0x98F6, 0x5070, 0xFA79, 0x5072, 0x8EC3,
+	0x5074, 0x91A4, 0x5075, 0x92E3, 0x5076, 0x8BF4, 0x5078, 0x98F7,
+	0x507D, 0x8B55, 0x5080, 0x98F8, 0x5085, 0x98FA, 0x508D, 0x9654,
+	0x5091, 0x8C86, 0x5094, 0xFA7B, 0x5098, 0x8E50, 0x5099, 0x94F5,
+	0x509A, 0x98F9, 0x50AC, 0x8DC3, 0x50AD, 0x9762, 0x50B2, 0x98FC,
+	0x50B3, 0x9942, 0x50B4, 0x98FB, 0x50B5, 0x8DC2, 0x50B7, 0x8F9D,
+	0x50BE, 0x8C58, 0x50C2, 0x9943, 0x50C5, 0x8BCD, 0x50C9, 0x9940,
+	0x50CA, 0x9941, 0x50CD, 0x93AD, 0x50CF, 0x919C, 0x50D1, 0x8BA1,
+	0x50D5, 0x966C, 0x50D6, 0x9944, 0x50D8, 0xFA7D, 0x50DA, 0x97BB,
+	0x50DE, 0x9945, 0x50E3, 0x9948, 0x50E5, 0x9946, 0x50E7, 0x916D,
+	0x50ED, 0x9947, 0x50EE, 0x9949, 0x50F4, 0xFA7C, 0x50F5, 0x994B,
+	0x50F9, 0x994A, 0x50FB, 0x95C6, 0x5100, 0x8B56, 0x5101, 0x994D,
+	0x5102, 0x994E, 0x5104, 0x89AD, 0x5109, 0x994C, 0x5112, 0x8EF2,
+	0x5114, 0x9951, 0x5115, 0x9950, 0x5116, 0x994F, 0x5118, 0x98D4,
+	0x511A, 0x9952, 0x511F, 0x8F9E, 0x5121, 0x9953, 0x512A, 0x9744,
+	0x5132, 0x96D7, 0x5137, 0x9955, 0x513A, 0x9954, 0x513B, 0x9957,
+	0x513C, 0x9956, 0x513F, 0x9958, 0x5140, 0x9959, 0x5141, 0x88F2,
+	0x5143, 0x8CB3, 0x5144, 0x8C5A, 0x5145, 0x8F5B, 0x5146, 0x929B,
+	0x5147, 0x8BA2, 0x5148, 0x90E6, 0x5149, 0x8CF5, 0x514A, 0xFA7E,
+	0x514B, 0x8D8E, 0x514C, 0x995B, 0x514D, 0x96C6, 0x514E, 0x9365,
+	0x5150, 0x8E99, 0x5152, 0x995A, 0x5154, 0x995C, 0x515A, 0x937D,
+	0x515C, 0x8A95, 0x5162, 0x995D, 0x5164, 0xFA80, 0x5165, 0x93FC,
+	0x5168, 0x9153, 0x5169, 0x995F, 0x516A, 0x9960, 0x516B, 0x94AA,
+	0x516C, 0x8CF6, 0x516D, 0x985A, 0x516E, 0x9961, 0x5171, 0x8BA4,
+	0x5175, 0x95BA, 0x5176, 0x91B4, 0x5177, 0x8BEF, 0x5178, 0x9354,
+	0x517C, 0x8C93, 0x5180, 0x9962, 0x5182, 0x9963, 0x5185, 0x93E0,
+	0x5186, 0x897E, 0x5189, 0x9966, 0x518A, 0x8DFB, 0x518C, 0x9965,
+	0x518D, 0x8DC4, 0x518F, 0x9967, 0x5190, 0xE3EC, 0x5191, 0x9968,
+	0x5192, 0x9660, 0x5193, 0x9969, 0x5195, 0x996A, 0x5196, 0x996B,
+	0x5197, 0x8FE7, 0x5199, 0x8ECA, 0x519D, 0xFA81, 0x51A0, 0x8AA5,
+	0x51A2, 0x996E, 0x51A4, 0x996C, 0x51A5, 0x96BB, 0x51A6, 0x996D,
+	0x51A8, 0x9579, 0x51A9, 0x996F, 0x51AA, 0x9970, 0x51AB, 0x9971,
+	0x51AC, 0x937E, 0x51B0, 0x9975, 0x51B1, 0x9973, 0x51B2, 0x9974,
+	0x51B3, 0x9972, 0x51B4, 0x8DE1, 0x51B5, 0x9976, 0x51B6, 0x96E8,
+	0x51B7, 0x97E2, 0x51BD, 0x9977, 0x51BE, 0xFA82, 0x51C4, 0x90A6,
+	0x51C5, 0x9978, 0x51C6, 0x8F79, 0x51C9, 0x9979, 0x51CB, 0x929C,
+	0x51CC, 0x97BD, 0x51CD, 0x9380, 0x51D6, 0x99C3, 0x51DB, 0x997A,
+	0x51DC, 0xEAA3, 0x51DD, 0x8BC3, 0x51E0, 0x997B, 0x51E1, 0x967D,
+	0x51E6, 0x8F88, 0x51E7, 0x91FA, 0x51E9, 0x997D, 0x51EA, 0x93E2,
+	0x51EC, 0xFA83, 0x51ED, 0x997E, 0x51F0, 0x9980, 0x51F1, 0x8A4D,
+	0x51F5, 0x9981, 0x51F6, 0x8BA5, 0x51F8, 0x93CA, 0x51F9, 0x899A,
+	0x51FA, 0x8F6F, 0x51FD, 0x949F, 0x51FE, 0x9982, 0x5200, 0x9381,
+	0x5203, 0x906E, 0x5204, 0x9983, 0x5206, 0x95AA, 0x5207, 0x90D8,
+	0x5208, 0x8AA0, 0x520A, 0x8AA7, 0x520B, 0x9984, 0x520E, 0x9986,
+	0x5211, 0x8C59, 0x5214, 0x9985, 0x5215, 0xFA84, 0x5217, 0x97F1,
+	0x521D, 0x8F89, 0x5224, 0x94BB, 0x5225, 0x95CA, 0x5227, 0x9987,
+	0x5229, 0x9798, 0x522A, 0x9988, 0x522E, 0x9989, 0x5230, 0x939E,
+	0x5233, 0x998A, 0x5236, 0x90A7, 0x5237, 0x8DFC, 0x5238, 0x8C94,
+	0x5239, 0x998B, 0x523A, 0x8E68, 0x523B, 0x8D8F, 0x5243, 0x92E4,
+	0x5244, 0x998D, 0x5247, 0x91A5, 0x524A, 0x8DED, 0x524B, 0x998E,
+	0x524C, 0x998F, 0x524D, 0x914F, 0x524F, 0x998C, 0x5254, 0x9991,
+	0x5256, 0x9655, 0x525B, 0x8D84, 0x525E, 0x9990, 0x5263, 0x8C95,
+	0x5264, 0x8DDC, 0x5265, 0x948D, 0x5269, 0x9994, 0x526A, 0x9992,
+	0x526F, 0x959B, 0x5270, 0x8FE8, 0x5271, 0x999B, 0x5272, 0x8A84,
+	0x5273, 0x9995, 0x5274, 0x9993, 0x5275, 0x916E, 0x527D, 0x9997,
+	0x527F, 0x9996, 0x5283, 0x8A63, 0x5287, 0x8C80, 0x5288, 0x999C,
+	0x5289, 0x97AB, 0x528D, 0x9998, 0x5291, 0x999D, 0x5292, 0x999A,
+	0x5294, 0x9999, 0x529B, 0x97CD, 0x529C, 0xFA85, 0x529F, 0x8CF7,
+	0x52A0, 0x89C1, 0x52A3, 0x97F2, 0x52A6, 0xFA86, 0x52A9, 0x8F95,
+	0x52AA, 0x9377, 0x52AB, 0x8D85, 0x52AC, 0x99A0, 0x52AD, 0x99A1,
+	0x52AF, 0xFB77, 0x52B1, 0x97E3, 0x52B4, 0x984A, 0x52B5, 0x99A3,
+	0x52B9, 0x8CF8, 0x52BC, 0x99A2, 0x52BE, 0x8A4E, 0x52C0, 0xFA87,
+	0x52C1, 0x99A4, 0x52C3, 0x9675, 0x52C5, 0x92BA, 0x52C7, 0x9745,
+	0x52C9, 0x95D7, 0x52CD, 0x99A5, 0x52D2, 0xE8D3, 0x52D5, 0x93AE,
+	0x52D7, 0x99A6, 0x52D8, 0x8AA8, 0x52D9, 0x96B1, 0x52DB, 0xFA88,
+	0x52DD, 0x8F9F, 0x52DE, 0x99A7, 0x52DF, 0x95E5, 0x52E0, 0x99AB,
+	0x52E2, 0x90A8, 0x52E3, 0x99A8, 0x52E4, 0x8BCE, 0x52E6, 0x99A9,
+	0x52E7, 0x8AA9, 0x52F2, 0x8C4D, 0x52F3, 0x99AC, 0x52F5, 0x99AD,
+	0x52F8, 0x99AE, 0x52F9, 0x99AF, 0x52FA, 0x8ED9, 0x52FE, 0x8CF9,
+	0x52FF, 0x96DC, 0x5300, 0xFA89, 0x5301, 0x96E6, 0x5302, 0x93F5,
+	0x5305, 0x95EF, 0x5306, 0x99B0, 0x5307, 0xFA8A, 0x5308, 0x99B1,
+	0x530D, 0x99B3, 0x530F, 0x99B5, 0x5310, 0x99B4, 0x5315, 0x99B6,
+	0x5316, 0x89BB, 0x5317, 0x966B, 0x5319, 0x8DFA, 0x531A, 0x99B7,
+	0x531D, 0x9178, 0x5320, 0x8FA0, 0x5321, 0x8BA7, 0x5323, 0x99B8,
+	0x5324, 0xFA8B, 0x532A, 0x94D9, 0x532F, 0x99B9, 0x5331, 0x99BA,
+	0x5333, 0x99BB, 0x5338, 0x99BC, 0x5339, 0x9543, 0x533A, 0x8BE6,
+	0x533B, 0x88E3, 0x533F, 0x93BD, 0x5340, 0x99BD, 0x5341, 0x8F5C,
+	0x5343, 0x90E7, 0x5345, 0x99BF, 0x5346, 0x99BE, 0x5347, 0x8FA1,
+	0x5348, 0x8CDF, 0x5349, 0x99C1, 0x534A, 0x94BC, 0x534D, 0x99C2,
+	0x5351, 0x94DA, 0x5352, 0x91B2, 0x5353, 0x91EC, 0x5354, 0x8BA6,
+	0x5357, 0x93EC, 0x5358, 0x9250, 0x535A, 0x948E, 0x535C, 0x966D,
+	0x535E, 0x99C4, 0x5360, 0x90E8, 0x5366, 0x8C54, 0x5369, 0x99C5,
+	0x536E, 0x99C6, 0x536F, 0x894B, 0x5370, 0x88F3, 0x5371, 0x8AEB,
+	0x5372, 0xFA8C, 0x5373, 0x91A6, 0x5374, 0x8B70, 0x5375, 0x9791,
+	0x5377, 0x99C9, 0x5378, 0x89B5, 0x537B, 0x99C8, 0x537F, 0x8BA8,
+	0x5382, 0x99CA, 0x5384, 0x96EF, 0x5393, 0xFA8D, 0x5396, 0x99CB,
+	0x5398, 0x97D0, 0x539A, 0x8CFA, 0x539F, 0x8CB4, 0x53A0, 0x99CC,
+	0x53A5, 0x99CE, 0x53A6, 0x99CD, 0x53A8, 0x907E, 0x53A9, 0x8958,
+	0x53AD, 0x897D, 0x53AE, 0x99CF, 0x53B0, 0x99D0, 0x53B2, 0xFA8E,
+	0x53B3, 0x8CB5, 0x53B6, 0x99D1, 0x53BB, 0x8B8E, 0x53C2, 0x8E51,
+	0x53C3, 0x99D2, 0x53C8, 0x9694, 0x53C9, 0x8DB3, 0x53CA, 0x8B79,
+	0x53CB, 0x9746, 0x53CC, 0x916F, 0x53CD, 0x94BD, 0x53CE, 0x8EFB,
+	0x53D4, 0x8F66, 0x53D6, 0x8EE6, 0x53D7, 0x8EF3, 0x53D9, 0x8F96,
+	0x53DB, 0x94BE, 0x53DD, 0xFA8F, 0x53DF, 0x99D5, 0x53E1, 0x8962,
+	0x53E2, 0x9170, 0x53E3, 0x8CFB, 0x53E4, 0x8CC3, 0x53E5, 0x8BE5,
+	0x53E8, 0x99D9, 0x53E9, 0x9240, 0x53EA, 0x91FC, 0x53EB, 0x8BA9,
+	0x53EC, 0x8FA2, 0x53ED, 0x99DA, 0x53EE, 0x99D8, 0x53EF, 0x89C2,
+	0x53F0, 0x91E4, 0x53F1, 0x8EB6, 0x53F2, 0x8E6A, 0x53F3, 0x8945,
+	0x53F6, 0x8A90, 0x53F7, 0x8D86, 0x53F8, 0x8E69, 0x53FA, 0x99DB,
+	0x5401, 0x99DC, 0x5403, 0x8B68, 0x5404, 0x8A65, 0x5408, 0x8D87,
+	0x5409, 0x8B67, 0x540A, 0x92DD, 0x540B, 0x8944, 0x540C, 0x93AF,
+	0x540D, 0x96BC, 0x540E, 0x8D40, 0x540F, 0x9799, 0x5410, 0x9366,
+	0x5411, 0x8CFC, 0x541B, 0x8C4E, 0x541D, 0x99E5, 0x541F, 0x8BE1,
+	0x5420, 0x9669, 0x5426, 0x94DB, 0x5429, 0x99E4, 0x542B, 0x8ADC,
+	0x542C, 0x99DF, 0x542D, 0x99E0, 0x542E, 0x99E2, 0x5436, 0x99E3,
+	0x5438, 0x8B7A, 0x5439, 0x9081, 0x543B, 0x95AB, 0x543C, 0x99E1,
+	0x543D, 0x99DD, 0x543E, 0x8CE1, 0x5440, 0x99DE, 0x5442, 0x9843,
+	0x5446, 0x95F0, 0x5448, 0x92E6, 0x5449, 0x8CE0, 0x544A, 0x8D90,
+	0x544E, 0x99E6, 0x5451, 0x93DB, 0x545F, 0x99EA, 0x5468, 0x8EFC,
+	0x546A, 0x8EF4, 0x5470, 0x99ED, 0x5471, 0x99EB, 0x5473, 0x96A1,
+	0x5475, 0x99E8, 0x5476, 0x99F1, 0x5477, 0x99EC, 0x547B, 0x99EF,
+	0x547C, 0x8CC4, 0x547D, 0x96BD, 0x5480, 0x99F0, 0x5484, 0x99F2,
+	0x5486, 0x99F4, 0x548A, 0xFA92, 0x548B, 0x8DEE, 0x548C, 0x9861,
+	0x548E, 0x99E9, 0x548F, 0x99E7, 0x5490, 0x99F3, 0x5492, 0x99EE,
+	0x549C, 0xFA91, 0x54A2, 0x99F6, 0x54A4, 0x9A42, 0x54A5, 0x99F8,
+	0x54A8, 0x99FC, 0x54A9, 0xFA93, 0x54AB, 0x9A40, 0x54AC, 0x99F9,
+	0x54AF, 0x9A5D, 0x54B2, 0x8DE7, 0x54B3, 0x8A50, 0x54B8, 0x99F7,
+	0x54BC, 0x9A44, 0x54BD, 0x88F4, 0x54BE, 0x9A43, 0x54C0, 0x88A3,
+	0x54C1, 0x9569, 0x54C2, 0x9A41, 0x54C4, 0x99FA, 0x54C7, 0x99F5,
+	0x54C8, 0x99FB, 0x54C9, 0x8DC6, 0x54D8, 0x9A45, 0x54E1, 0x88F5,
+	0x54E2, 0x9A4E, 0x54E5, 0x9A46, 0x54E6, 0x9A47, 0x54E8, 0x8FA3,
+	0x54E9, 0x9689, 0x54ED, 0x9A4C, 0x54EE, 0x9A4B, 0x54F2, 0x934E,
+	0x54FA, 0x9A4D, 0x54FD, 0x9A4A, 0x54FF, 0xFA94, 0x5504, 0x8953,
+	0x5506, 0x8DB4, 0x5507, 0x904F, 0x550F, 0x9A48, 0x5510, 0x9382,
+	0x5514, 0x9A49, 0x5516, 0x88A0, 0x552E, 0x9A53, 0x552F, 0x9742,
+	0x5531, 0x8FA5, 0x5533, 0x9A59, 0x5538, 0x9A58, 0x5539, 0x9A4F,
+	0x553E, 0x91C1, 0x5540, 0x9A50, 0x5544, 0x91ED, 0x5545, 0x9A55,
+	0x5546, 0x8FA4, 0x554C, 0x9A52, 0x554F, 0x96E2, 0x5553, 0x8C5B,
+	0x5556, 0x9A56, 0x5557, 0x9A57, 0x555C, 0x9A54, 0x555D, 0x9A5A,
+	0x5563, 0x9A51, 0x557B, 0x9A60, 0x557C, 0x9A65, 0x557E, 0x9A61,
+	0x5580, 0x9A5C, 0x5583, 0x9A66, 0x5584, 0x9150, 0x5586, 0xFA95,
+	0x5587, 0x9A68, 0x5589, 0x8D41, 0x558A, 0x9A5E, 0x558B, 0x929D,
+	0x5598, 0x9A62, 0x5599, 0x9A5B, 0x559A, 0x8AAB, 0x559C, 0x8AEC,
+	0x559D, 0x8A85, 0x559E, 0x9A63, 0x559F, 0x9A5F, 0x55A7, 0x8C96,
+	0x55A8, 0x9A69, 0x55A9, 0x9A67, 0x55AA, 0x9172, 0x55AB, 0x8B69,
+	0x55AC, 0x8BAA, 0x55AE, 0x9A64, 0x55B0, 0x8BF2, 0x55B6, 0x8963,
+	0x55C4, 0x9A6D, 0x55C5, 0x9A6B, 0x55C7, 0x9AA5, 0x55D4, 0x9A70,
+	0x55DA, 0x9A6A, 0x55DC, 0x9A6E, 0x55DF, 0x9A6C, 0x55E3, 0x8E6B,
+	0x55E4, 0x9A6F, 0x55F7, 0x9A72, 0x55F9, 0x9A77, 0x55FD, 0x9A75,
+	0x55FE, 0x9A74, 0x5606, 0x9251, 0x5609, 0x89C3, 0x5614, 0x9A71,
+	0x5616, 0x9A73, 0x5617, 0x8FA6, 0x5618, 0x8952, 0x561B, 0x9A76,
+	0x5629, 0x89DC, 0x562F, 0x9A82, 0x5631, 0x8FFA, 0x5632, 0x9A7D,
+	0x5634, 0x9A7B, 0x5636, 0x9A7C, 0x5638, 0x9A7E, 0x5642, 0x895C,
+	0x564C, 0x9158, 0x564E, 0x9A78, 0x5650, 0x9A79, 0x565B, 0x8A9A,
+	0x5664, 0x9A81, 0x5668, 0x8AED, 0x566A, 0x9A84, 0x566B, 0x9A80,
+	0x566C, 0x9A83, 0x5674, 0x95AC, 0x5678, 0x93D3, 0x567A, 0x94B6,
+	0x5680, 0x9A86, 0x5686, 0x9A85, 0x5687, 0x8A64, 0x568A, 0x9A87,
+	0x568F, 0x9A8A, 0x5694, 0x9A89, 0x56A0, 0x9A88, 0x56A2, 0x9458,
+	0x56A5, 0x9A8B, 0x56AE, 0x9A8C, 0x56B4, 0x9A8E, 0x56B6, 0x9A8D,
+	0x56BC, 0x9A90, 0x56C0, 0x9A93, 0x56C1, 0x9A91, 0x56C2, 0x9A8F,
+	0x56C3, 0x9A92, 0x56C8, 0x9A94, 0x56CE, 0x9A95, 0x56D1, 0x9A96,
+	0x56D3, 0x9A97, 0x56D7, 0x9A98, 0x56D8, 0x9964, 0x56DA, 0x8EFA,
+	0x56DB, 0x8E6C, 0x56DE, 0x89F1, 0x56E0, 0x88F6, 0x56E3, 0x9263,
+	0x56EE, 0x9A99, 0x56F0, 0x8DA2, 0x56F2, 0x88CD, 0x56F3, 0x907D,
+	0x56F9, 0x9A9A, 0x56FA, 0x8CC5, 0x56FD, 0x8D91, 0x56FF, 0x9A9C,
+	0x5700, 0x9A9B, 0x5703, 0x95DE, 0x5704, 0x9A9D, 0x5708, 0x9A9F,
+	0x5709, 0x9A9E, 0x570B, 0x9AA0, 0x570D, 0x9AA1, 0x570F, 0x8C97,
+	0x5712, 0x8980, 0x5713, 0x9AA2, 0x5716, 0x9AA4, 0x5718, 0x9AA3,
+	0x571C, 0x9AA6, 0x571F, 0x9379, 0x5726, 0x9AA7, 0x5727, 0x88B3,
+	0x5728, 0x8DDD, 0x572D, 0x8C5C, 0x5730, 0x926E, 0x5737, 0x9AA8,
+	0x5738, 0x9AA9, 0x573B, 0x9AAB, 0x5740, 0x9AAC, 0x5742, 0x8DE2,
+	0x5747, 0x8BCF, 0x574A, 0x9656, 0x574E, 0x9AAA, 0x574F, 0x9AAD,
+	0x5750, 0x8DBF, 0x5751, 0x8D42, 0x5759, 0xFA96, 0x5761, 0x9AB1,
+	0x5764, 0x8DA3, 0x5765, 0xFA97, 0x5766, 0x9252, 0x5769, 0x9AAE,
+	0x576A, 0x92D8, 0x577F, 0x9AB2, 0x5782, 0x9082, 0x5788, 0x9AB0,
+	0x5789, 0x9AB3, 0x578B, 0x8C5E, 0x5793, 0x9AB4, 0x57A0, 0x9AB5,
+	0x57A2, 0x8D43, 0x57A3, 0x8A5F, 0x57A4, 0x9AB7, 0x57AA, 0x9AB8,
+	0x57AC, 0xFA98, 0x57B0, 0x9AB9, 0x57B3, 0x9AB6, 0x57C0, 0x9AAF,
+	0x57C3, 0x9ABA, 0x57C6, 0x9ABB, 0x57C7, 0xFA9A, 0x57C8, 0xFA99,
+	0x57CB, 0x9684, 0x57CE, 0x8FE9, 0x57D2, 0x9ABD, 0x57D3, 0x9ABE,
+	0x57D4, 0x9ABC, 0x57D6, 0x9AC0, 0x57DC, 0x9457, 0x57DF, 0x88E6,
+	0x57E0, 0x9575, 0x57E3, 0x9AC1, 0x57F4, 0x8FFB, 0x57F7, 0x8EB7,
+	0x57F9, 0x947C, 0x57FA, 0x8AEE, 0x57FC, 0x8DE9, 0x5800, 0x9678,
+	0x5802, 0x93B0, 0x5805, 0x8C98, 0x5806, 0x91CD, 0x580A, 0x9ABF,
+	0x580B, 0x9AC2, 0x5815, 0x91C2, 0x5819, 0x9AC3, 0x581D, 0x9AC4,
+	0x5821, 0x9AC6, 0x5824, 0x92E7, 0x582A, 0x8AAC, 0x582F, 0xEA9F,
+	0x5830, 0x8981, 0x5831, 0x95F1, 0x5834, 0x8FEA, 0x5835, 0x9367,
+	0x583A, 0x8DE4, 0x583D, 0x9ACC, 0x5840, 0x95BB, 0x5841, 0x97DB,
+	0x584A, 0x89F2, 0x584B, 0x9AC8, 0x5851, 0x9159, 0x5852, 0x9ACB,
+	0x5854, 0x9383, 0x5857, 0x9368, 0x5858, 0x9384, 0x5859, 0x94B7,
+	0x585A, 0x92CB, 0x585E, 0x8DC7, 0x5862, 0x9AC7, 0x5869, 0x8996,
+	0x586B, 0x9355, 0x5870, 0x9AC9, 0x5872, 0x9AC5, 0x5875, 0x906F,
+	0x5879, 0x9ACD, 0x587E, 0x8F6D, 0x5883, 0x8BAB, 0x5885, 0x9ACE,
+	0x5893, 0x95E6, 0x5897, 0x919D, 0x589C, 0x92C4, 0x589E, 0xFA9D,
+	0x589F, 0x9AD0, 0x58A8, 0x966E, 0x58AB, 0x9AD1, 0x58AE, 0x9AD6,
+	0x58B2, 0xFA9E, 0x58B3, 0x95AD, 0x58B8, 0x9AD5, 0x58B9, 0x9ACF,
+	0x58BA, 0x9AD2, 0x58BB, 0x9AD4, 0x58BE, 0x8DA4, 0x58C1, 0x95C7,
+	0x58C5, 0x9AD7, 0x58C7, 0x9264, 0x58CA, 0x89F3, 0x58CC, 0x8FEB,
+	0x58D1, 0x9AD9, 0x58D3, 0x9AD8, 0x58D5, 0x8D88, 0x58D7, 0x9ADA,
+	0x58D8, 0x9ADC, 0x58D9, 0x9ADB, 0x58DC, 0x9ADE, 0x58DE, 0x9AD3,
+	0x58DF, 0x9AE0, 0x58E4, 0x9ADF, 0x58E5, 0x9ADD, 0x58EB, 0x8E6D,
+	0x58EC, 0x9070, 0x58EE, 0x9173, 0x58EF, 0x9AE1, 0x58F0, 0x90BA,
+	0x58F1, 0x88EB, 0x58F2, 0x9484, 0x58F7, 0x92D9, 0x58F9, 0x9AE3,
+	0x58FA, 0x9AE2, 0x58FB, 0x9AE4, 0x58FC, 0x9AE5, 0x58FD, 0x9AE6,
+	0x5902, 0x9AE7, 0x5909, 0x95CF, 0x590A, 0x9AE8, 0x590B, 0xFA9F,
+	0x590F, 0x89C4, 0x5910, 0x9AE9, 0x5915, 0x975B, 0x5916, 0x8A4F,
+	0x5918, 0x99C7, 0x5919, 0x8F67, 0x591A, 0x91BD, 0x591B, 0x9AEA,
+	0x591C, 0x96E9, 0x5922, 0x96B2, 0x5925, 0x9AEC, 0x5927, 0x91E5,
+	0x5929, 0x9356, 0x592A, 0x91BE, 0x592B, 0x9576, 0x592C, 0x9AED,
+	0x592D, 0x9AEE, 0x592E, 0x899B, 0x5931, 0x8EB8, 0x5932, 0x9AEF,
+	0x5937, 0x88CE, 0x5938, 0x9AF0, 0x593E, 0x9AF1, 0x5944, 0x8982,
+	0x5947, 0x8AEF, 0x5948, 0x93DE, 0x5949, 0x95F2, 0x594E, 0x9AF5,
+	0x594F, 0x9174, 0x5950, 0x9AF4, 0x5951, 0x8C5F, 0x5953, 0xFAA0,
+	0x5954, 0x967A, 0x5955, 0x9AF3, 0x5957, 0x9385, 0x5958, 0x9AF7,
+	0x595A, 0x9AF6, 0x595B, 0xFAA1, 0x595D, 0xFAA2, 0x5960, 0x9AF9,
+	0x5962, 0x9AF8, 0x5963, 0xFAA3, 0x5965, 0x899C, 0x5967, 0x9AFA,
+	0x5968, 0x8FA7, 0x5969, 0x9AFC, 0x596A, 0x9244, 0x596C, 0x9AFB,
+	0x596E, 0x95B1, 0x5973, 0x8F97, 0x5974, 0x937A, 0x5978, 0x9B40,
+	0x597D, 0x8D44, 0x5981, 0x9B41, 0x5982, 0x9440, 0x5983, 0x94DC,
+	0x5984, 0x96CF, 0x598A, 0x9444, 0x598D, 0x9B4A, 0x5993, 0x8B57,
+	0x5996, 0x9764, 0x5999, 0x96AD, 0x599B, 0x9BAA, 0x599D, 0x9B42,
+	0x59A3, 0x9B45, 0x59A4, 0xFAA4, 0x59A5, 0x91C3, 0x59A8, 0x9657,
+	0x59AC, 0x9369, 0x59B2, 0x9B46, 0x59B9, 0x9685, 0x59BA, 0xFAA5,
+	0x59BB, 0x8DC8, 0x59BE, 0x8FA8, 0x59C6, 0x9B47, 0x59C9, 0x8E6F,
+	0x59CB, 0x8E6E, 0x59D0, 0x88B7, 0x59D1, 0x8CC6, 0x59D3, 0x90A9,
+	0x59D4, 0x88CF, 0x59D9, 0x9B4B, 0x59DA, 0x9B4C, 0x59DC, 0x9B49,
+	0x59E5, 0x8957, 0x59E6, 0x8AAD, 0x59E8, 0x9B48, 0x59EA, 0x96C3,
+	0x59EB, 0x9550, 0x59F6, 0x88A6, 0x59FB, 0x88F7, 0x59FF, 0x8E70,
+	0x5A01, 0x88D0, 0x5A03, 0x88A1, 0x5A09, 0x9B51, 0x5A11, 0x9B4F,
+	0x5A18, 0x96BA, 0x5A1A, 0x9B52, 0x5A1C, 0x9B50, 0x5A1F, 0x9B4E,
+	0x5A20, 0x9050, 0x5A25, 0x9B4D, 0x5A29, 0x95D8, 0x5A2F, 0x8CE2,
+	0x5A35, 0x9B56, 0x5A36, 0x9B57, 0x5A3C, 0x8FA9, 0x5A40, 0x9B53,
+	0x5A41, 0x984B, 0x5A46, 0x946B, 0x5A49, 0x9B55, 0x5A5A, 0x8DA5,
+	0x5A62, 0x9B58, 0x5A66, 0x9577, 0x5A6A, 0x9B59, 0x5A6C, 0x9B54,
+	0x5A7F, 0x96B9, 0x5A92, 0x947D, 0x5A9A, 0x9B5A, 0x5A9B, 0x9551,
+	0x5ABC, 0x9B5B, 0x5ABD, 0x9B5F, 0x5ABE, 0x9B5C, 0x5AC1, 0x89C5,
+	0x5AC2, 0x9B5E, 0x5AC9, 0x8EB9, 0x5ACB, 0x9B5D, 0x5ACC, 0x8C99,
+	0x5AD0, 0x9B6B, 0x5AD6, 0x9B64, 0x5AD7, 0x9B61, 0x5AE1, 0x9284,
+	0x5AE3, 0x9B60, 0x5AE6, 0x9B62, 0x5AE9, 0x9B63, 0x5AFA, 0x9B65,
+	0x5AFB, 0x9B66, 0x5B09, 0x8AF0, 0x5B0B, 0x9B68, 0x5B0C, 0x9B67,
+	0x5B16, 0x9B69, 0x5B22, 0x8FEC, 0x5B2A, 0x9B6C, 0x5B2C, 0x92DA,
+	0x5B30, 0x8964, 0x5B32, 0x9B6A, 0x5B36, 0x9B6D, 0x5B3E, 0x9B6E,
+	0x5B40, 0x9B71, 0x5B43, 0x9B6F, 0x5B45, 0x9B70, 0x5B50, 0x8E71,
+	0x5B51, 0x9B72, 0x5B54, 0x8D45, 0x5B55, 0x9B73, 0x5B56, 0xFAA6,
+	0x5B57, 0x8E9A, 0x5B58, 0x91B6, 0x5B5A, 0x9B74, 0x5B5B, 0x9B75,
+	0x5B5C, 0x8E79, 0x5B5D, 0x8D46, 0x5B5F, 0x96D0, 0x5B63, 0x8B47,
+	0x5B64, 0x8CC7, 0x5B65, 0x9B76, 0x5B66, 0x8A77, 0x5B69, 0x9B77,
+	0x5B6B, 0x91B7, 0x5B70, 0x9B78, 0x5B71, 0x9BA1, 0x5B73, 0x9B79,
+	0x5B75, 0x9B7A, 0x5B78, 0x9B7B, 0x5B7A, 0x9B7D, 0x5B80, 0x9B7E,
+	0x5B83, 0x9B80, 0x5B85, 0x91EE, 0x5B87, 0x8946, 0x5B88, 0x8EE7,
+	0x5B89, 0x88C0, 0x5B8B, 0x9176, 0x5B8C, 0x8AAE, 0x5B8D, 0x8EB3,
+	0x5B8F, 0x8D47, 0x5B95, 0x9386, 0x5B97, 0x8F40, 0x5B98, 0x8AAF,
+	0x5B99, 0x9288, 0x5B9A, 0x92E8, 0x5B9B, 0x88B6, 0x5B9C, 0x8B58,
+	0x5B9D, 0x95F3, 0x5B9F, 0x8EC0, 0x5BA2, 0x8B71, 0x5BA3, 0x90E9,
+	0x5BA4, 0x8EBA, 0x5BA5, 0x9747, 0x5BA6, 0x9B81, 0x5BAE, 0x8B7B,
+	0x5BB0, 0x8DC9, 0x5BB3, 0x8A51, 0x5BB4, 0x8983, 0x5BB5, 0x8FAA,
+	0x5BB6, 0x89C6, 0x5BB8, 0x9B82, 0x5BB9, 0x9765, 0x5BBF, 0x8F68,
+	0x5BC0, 0xFAA7, 0x5BC2, 0x8EE2, 0x5BC3, 0x9B83, 0x5BC4, 0x8AF1,
+	0x5BC5, 0x93D0, 0x5BC6, 0x96A7, 0x5BC7, 0x9B84, 0x5BC9, 0x9B85,
+	0x5BCC, 0x9578, 0x5BD0, 0x9B87, 0x5BD2, 0x8AA6, 0x5BD3, 0x8BF5,
+	0x5BD4, 0x9B86, 0x5BD8, 0xFAA9, 0x5BDB, 0x8AB0, 0x5BDD, 0x9051,
+	0x5BDE, 0x9B8B, 0x5BDF, 0x8E40, 0x5BE1, 0x89C7, 0x5BE2, 0x9B8A,
+	0x5BE4, 0x9B88, 0x5BE5, 0x9B8C, 0x5BE6, 0x9B89, 0x5BE7, 0x944A,
+	0x5BE8, 0x9ECB, 0x5BE9, 0x9052, 0x5BEB, 0x9B8D, 0x5BEC, 0xFAAA,
+	0x5BEE, 0x97BE, 0x5BF0, 0x9B8E, 0x5BF3, 0x9B90, 0x5BF5, 0x929E,
+	0x5BF6, 0x9B8F, 0x5BF8, 0x90A1, 0x5BFA, 0x8E9B, 0x5BFE, 0x91CE,
+	0x5BFF, 0x8EF5, 0x5C01, 0x9595, 0x5C02, 0x90EA, 0x5C04, 0x8ECB,
+	0x5C05, 0x9B91, 0x5C06, 0x8FAB, 0x5C07, 0x9B92, 0x5C08, 0x9B93,
+	0x5C09, 0x88D1, 0x5C0A, 0x91B8, 0x5C0B, 0x9071, 0x5C0D, 0x9B94,
+	0x5C0E, 0x93B1, 0x5C0F, 0x8FAC, 0x5C11, 0x8FAD, 0x5C13, 0x9B95,
+	0x5C16, 0x90EB, 0x5C1A, 0x8FAE, 0x5C1E, 0xFAAB, 0x5C20, 0x9B96,
+	0x5C22, 0x9B97, 0x5C24, 0x96DE, 0x5C28, 0x9B98, 0x5C2D, 0x8BC4,
+	0x5C31, 0x8F41, 0x5C38, 0x9B99, 0x5C39, 0x9B9A, 0x5C3A, 0x8EDA,
+	0x5C3B, 0x904B, 0x5C3C, 0x93F2, 0x5C3D, 0x9073, 0x5C3E, 0x94F6,
+	0x5C3F, 0x9441, 0x5C40, 0x8BC7, 0x5C41, 0x9B9B, 0x5C45, 0x8B8F,
+	0x5C46, 0x9B9C, 0x5C48, 0x8BFC, 0x5C4A, 0x93CD, 0x5C4B, 0x89AE,
+	0x5C4D, 0x8E72, 0x5C4E, 0x9B9D, 0x5C4F, 0x9BA0, 0x5C50, 0x9B9F,
+	0x5C51, 0x8BFB, 0x5C53, 0x9B9E, 0x5C55, 0x9357, 0x5C5E, 0x91AE,
+	0x5C60, 0x936A, 0x5C61, 0x8EC6, 0x5C64, 0x9177, 0x5C65, 0x979A,
+	0x5C6C, 0x9BA2, 0x5C6E, 0x9BA3, 0x5C6F, 0x93D4, 0x5C71, 0x8E52,
+	0x5C76, 0x9BA5, 0x5C79, 0x9BA6, 0x5C8C, 0x9BA7, 0x5C90, 0x8AF2,
+	0x5C91, 0x9BA8, 0x5C94, 0x9BA9, 0x5CA1, 0x89AA, 0x5CA6, 0xFAAC,
+	0x5CA8, 0x915A, 0x5CA9, 0x8AE2, 0x5CAB, 0x9BAB, 0x5CAC, 0x96A6,
+	0x5CB1, 0x91D0, 0x5CB3, 0x8A78, 0x5CB6, 0x9BAD, 0x5CB7, 0x9BAF,
+	0x5CB8, 0x8ADD, 0x5CBA, 0xFAAD, 0x5CBB, 0x9BAC, 0x5CBC, 0x9BAE,
+	0x5CBE, 0x9BB1, 0x5CC5, 0x9BB0, 0x5CC7, 0x9BB2, 0x5CD9, 0x9BB3,
+	0x5CE0, 0x93BB, 0x5CE1, 0x8BAC, 0x5CE8, 0x89E3, 0x5CE9, 0x9BB4,
+	0x5CEA, 0x9BB9, 0x5CED, 0x9BB7, 0x5CEF, 0x95F5, 0x5CF0, 0x95F4,
+	0x5CF5, 0xFAAE, 0x5CF6, 0x9387, 0x5CFA, 0x9BB6, 0x5CFB, 0x8F73,
+	0x5CFD, 0x9BB5, 0x5D07, 0x9092, 0x5D0B, 0x9BBA, 0x5D0E, 0x8DE8,
+	0x5D11, 0x9BC0, 0x5D14, 0x9BC1, 0x5D15, 0x9BBB, 0x5D16, 0x8A52,
+	0x5D17, 0x9BBC, 0x5D18, 0x9BC5, 0x5D19, 0x9BC4, 0x5D1A, 0x9BC3,
+	0x5D1B, 0x9BBF, 0x5D1F, 0x9BBE, 0x5D22, 0x9BC2, 0x5D27, 0xFAAF,
+	0x5D29, 0x95F6, 0x5D42, 0xFAB2, 0x5D4B, 0x9BC9, 0x5D4C, 0x9BC6,
+	0x5D4E, 0x9BC8, 0x5D50, 0x9792, 0x5D52, 0x9BC7, 0x5D53, 0xFAB0,
+	0x5D5C, 0x9BBD, 0x5D69, 0x9093, 0x5D6C, 0x9BCA, 0x5D6D, 0xFAB3,
+	0x5D6F, 0x8DB5, 0x5D73, 0x9BCB, 0x5D76, 0x9BCC, 0x5D82, 0x9BCF,
+	0x5D84, 0x9BCE, 0x5D87, 0x9BCD, 0x5D8B, 0x9388, 0x5D8C, 0x9BB8,
+	0x5D90, 0x9BD5, 0x5D9D, 0x9BD1, 0x5DA2, 0x9BD0, 0x5DAC, 0x9BD2,
+	0x5DAE, 0x9BD3, 0x5DB7, 0x9BD6, 0x5DB8, 0xFAB4, 0x5DB9, 0xFAB5,
+	0x5DBA, 0x97E4, 0x5DBC, 0x9BD7, 0x5DBD, 0x9BD4, 0x5DC9, 0x9BD8,
+	0x5DCC, 0x8ADE, 0x5DCD, 0x9BD9, 0x5DD0, 0xFAB6, 0x5DD2, 0x9BDB,
+	0x5DD3, 0x9BDA, 0x5DD6, 0x9BDC, 0x5DDB, 0x9BDD, 0x5DDD, 0x90EC,
+	0x5DDE, 0x8F42, 0x5DE1, 0x8F84, 0x5DE3, 0x9183, 0x5DE5, 0x8D48,
+	0x5DE6, 0x8DB6, 0x5DE7, 0x8D49, 0x5DE8, 0x8B90, 0x5DEB, 0x9BDE,
+	0x5DEE, 0x8DB7, 0x5DF1, 0x8CC8, 0x5DF2, 0x9BDF, 0x5DF3, 0x96A4,
+	0x5DF4, 0x9462, 0x5DF5, 0x9BE0, 0x5DF7, 0x8D4A, 0x5DFB, 0x8AAA,
+	0x5DFD, 0x9246, 0x5DFE, 0x8BD0, 0x5E02, 0x8E73, 0x5E03, 0x957A,
+	0x5E06, 0x94BF, 0x5E0B, 0x9BE1, 0x5E0C, 0x8AF3, 0x5E11, 0x9BE4,
+	0x5E16, 0x929F, 0x5E19, 0x9BE3, 0x5E1A, 0x9BE2, 0x5E1B, 0x9BE5,
+	0x5E1D, 0x92E9, 0x5E25, 0x9083, 0x5E2B, 0x8E74, 0x5E2D, 0x90C8,
+	0x5E2F, 0x91D1, 0x5E30, 0x8B41, 0x5E33, 0x92A0, 0x5E36, 0x9BE6,
+	0x5E37, 0x9BE7, 0x5E38, 0x8FED, 0x5E3D, 0x9658, 0x5E40, 0x9BEA,
+	0x5E43, 0x9BE9, 0x5E44, 0x9BE8, 0x5E45, 0x959D, 0x5E47, 0x9BF1,
+	0x5E4C, 0x9679, 0x5E4E, 0x9BEB, 0x5E54, 0x9BED, 0x5E55, 0x968B,
+	0x5E57, 0x9BEC, 0x5E5F, 0x9BEE, 0x5E61, 0x94A6, 0x5E62, 0x9BEF,
+	0x5E63, 0x95BC, 0x5E64, 0x9BF0, 0x5E72, 0x8AB1, 0x5E73, 0x95BD,
+	0x5E74, 0x944E, 0x5E75, 0x9BF2, 0x5E76, 0x9BF3, 0x5E78, 0x8D4B,
+	0x5E79, 0x8AB2, 0x5E7A, 0x9BF4, 0x5E7B, 0x8CB6, 0x5E7C, 0x9763,
+	0x5E7D, 0x9748, 0x5E7E, 0x8AF4, 0x5E7F, 0x9BF6, 0x5E81, 0x92A1,
+	0x5E83, 0x8D4C, 0x5E84, 0x8FAF, 0x5E87, 0x94DD, 0x5E8A, 0x8FB0,
+	0x5E8F, 0x8F98, 0x5E95, 0x92EA, 0x5E96, 0x95F7, 0x5E97, 0x9358,
+	0x5E9A, 0x8D4D, 0x5E9C, 0x957B, 0x5EA0, 0x9BF7, 0x5EA6, 0x9378,
+	0x5EA7, 0x8DC0, 0x5EAB, 0x8CC9, 0x5EAD, 0x92EB, 0x5EB5, 0x88C1,
+	0x5EB6, 0x8F8E, 0x5EB7, 0x8D4E, 0x5EB8, 0x9766, 0x5EC1, 0x9BF8,
+	0x5EC2, 0x9BF9, 0x5EC3, 0x9470, 0x5EC8, 0x9BFA, 0x5EC9, 0x97F5,
+	0x5ECA, 0x984C, 0x5ECF, 0x9BFC, 0x5ED0, 0x9BFB, 0x5ED3, 0x8A66,
+	0x5ED6, 0x9C40, 0x5EDA, 0x9C43, 0x5EDB, 0x9C44, 0x5EDD, 0x9C42,
+	0x5EDF, 0x955F, 0x5EE0, 0x8FB1, 0x5EE1, 0x9C46, 0x5EE2, 0x9C45,
+	0x5EE3, 0x9C41, 0x5EE8, 0x9C47, 0x5EE9, 0x9C48, 0x5EEC, 0x9C49,
+	0x5EF0, 0x9C4C, 0x5EF1, 0x9C4A, 0x5EF3, 0x9C4B, 0x5EF4, 0x9C4D,
+	0x5EF6, 0x8984, 0x5EF7, 0x92EC, 0x5EF8, 0x9C4E, 0x5EFA, 0x8C9A,
+	0x5EFB, 0x89F4, 0x5EFC, 0x9455, 0x5EFE, 0x9C4F, 0x5EFF, 0x93F9,
+	0x5F01, 0x95D9, 0x5F03, 0x9C50, 0x5F04, 0x984D, 0x5F09, 0x9C51,
+	0x5F0A, 0x95BE, 0x5F0B, 0x9C54, 0x5F0C, 0x989F, 0x5F0D, 0x98AF,
+	0x5F0F, 0x8EAE, 0x5F10, 0x93F3, 0x5F11, 0x9C55, 0x5F13, 0x8B7C,
+	0x5F14, 0x92A2, 0x5F15, 0x88F8, 0x5F16, 0x9C56, 0x5F17, 0x95A4,
+	0x5F18, 0x8D4F, 0x5F1B, 0x926F, 0x5F1F, 0x92ED, 0x5F21, 0xFAB7,
+	0x5F25, 0x96ED, 0x5F26, 0x8CB7, 0x5F27, 0x8CCA, 0x5F29, 0x9C57,
+	0x5F2D, 0x9C58, 0x5F2F, 0x9C5E, 0x5F31, 0x8EE3, 0x5F34, 0xFAB8,
+	0x5F35, 0x92A3, 0x5F37, 0x8BAD, 0x5F38, 0x9C59, 0x5F3C, 0x954A,
+	0x5F3E, 0x9265, 0x5F41, 0x9C5A, 0x5F45, 0xFA67, 0x5F48, 0x9C5B,
+	0x5F4A, 0x8BAE, 0x5F4C, 0x9C5C, 0x5F4E, 0x9C5D, 0x5F51, 0x9C5F,
+	0x5F53, 0x9396, 0x5F56, 0x9C60, 0x5F57, 0x9C61, 0x5F59, 0x9C62,
+	0x5F5C, 0x9C53, 0x5F5D, 0x9C52, 0x5F61, 0x9C63, 0x5F62, 0x8C60,
+	0x5F66, 0x9546, 0x5F67, 0xFAB9, 0x5F69, 0x8DCA, 0x5F6A, 0x9556,
+	0x5F6B, 0x92A4, 0x5F6C, 0x956A, 0x5F6D, 0x9C64, 0x5F70, 0x8FB2,
+	0x5F71, 0x8965, 0x5F73, 0x9C65, 0x5F77, 0x9C66, 0x5F79, 0x96F0,
+	0x5F7C, 0x94DE, 0x5F7F, 0x9C69, 0x5F80, 0x899D, 0x5F81, 0x90AA,
+	0x5F82, 0x9C68, 0x5F83, 0x9C67, 0x5F84, 0x8C61, 0x5F85, 0x91D2,
+	0x5F87, 0x9C6D, 0x5F88, 0x9C6B, 0x5F8A, 0x9C6A, 0x5F8B, 0x97A5,
+	0x5F8C, 0x8CE3, 0x5F90, 0x8F99, 0x5F91, 0x9C6C, 0x5F92, 0x936B,
+	0x5F93, 0x8F5D, 0x5F97, 0x93BE, 0x5F98, 0x9C70, 0x5F99, 0x9C6F,
+	0x5F9E, 0x9C6E, 0x5FA0, 0x9C71, 0x5FA1, 0x8CE4, 0x5FA8, 0x9C72,
+	0x5FA9, 0x959C, 0x5FAA, 0x8F7A, 0x5FAD, 0x9C73, 0x5FAE, 0x94F7,
+	0x5FB3, 0x93BF, 0x5FB4, 0x92A5, 0x5FB7, 0xFABA, 0x5FB9, 0x934F,
+	0x5FBC, 0x9C74, 0x5FBD, 0x8B4A, 0x5FC3, 0x9053, 0x5FC5, 0x954B,
+	0x5FCC, 0x8AF5, 0x5FCD, 0x9445, 0x5FD6, 0x9C75, 0x5FD7, 0x8E75,
+	0x5FD8, 0x9659, 0x5FD9, 0x965A, 0x5FDC, 0x899E, 0x5FDD, 0x9C7A,
+	0x5FDE, 0xFABB, 0x5FE0, 0x9289, 0x5FE4, 0x9C77, 0x5FEB, 0x89F5,
+	0x5FF0, 0x9CAB, 0x5FF1, 0x9C79, 0x5FF5, 0x944F, 0x5FF8, 0x9C78,
+	0x5FFB, 0x9C76, 0x5FFD, 0x8D9A, 0x5FFF, 0x9C7C, 0x600E, 0x9C83,
+	0x600F, 0x9C89, 0x6010, 0x9C81, 0x6012, 0x937B, 0x6015, 0x9C86,
+	0x6016, 0x957C, 0x6019, 0x9C80, 0x601B, 0x9C85, 0x601C, 0x97E5,
+	0x601D, 0x8E76, 0x6020, 0x91D3, 0x6021, 0x9C7D, 0x6025, 0x8B7D,
+	0x6026, 0x9C88, 0x6027, 0x90AB, 0x6028, 0x8985, 0x6029, 0x9C82,
+	0x602A, 0x89F6, 0x602B, 0x9C87, 0x602F, 0x8BAF, 0x6031, 0x9C84,
+	0x603A, 0x9C8A, 0x6041, 0x9C8C, 0x6042, 0x9C96, 0x6043, 0x9C94,
+	0x6046, 0x9C91, 0x604A, 0x9C90, 0x604B, 0x97F6, 0x604D, 0x9C92,
+	0x6050, 0x8BB0, 0x6052, 0x8D50, 0x6055, 0x8F9A, 0x6059, 0x9C99,
+	0x605A, 0x9C8B, 0x605D, 0xFABC, 0x605F, 0x9C8F, 0x6060, 0x9C7E,
+	0x6062, 0x89F8, 0x6063, 0x9C93, 0x6064, 0x9C95, 0x6065, 0x9270,
+	0x6068, 0x8DA6, 0x6069, 0x89B6, 0x606A, 0x9C8D, 0x606B, 0x9C98,
+	0x606C, 0x9C97, 0x606D, 0x8BB1, 0x606F, 0x91A7, 0x6070, 0x8A86,
+	0x6075, 0x8C62, 0x6077, 0x9C8E, 0x6081, 0x9C9A, 0x6083, 0x9C9D,
+	0x6084, 0x9C9F, 0x6085, 0xFABD, 0x6089, 0x8EBB, 0x608A, 0xFABE,
+	0x608B, 0x9CA5, 0x608C, 0x92EE, 0x608D, 0x9C9B, 0x6092, 0x9CA3,
+	0x6094, 0x89F7, 0x6096, 0x9CA1, 0x6097, 0x9CA2, 0x609A, 0x9C9E,
+	0x609B, 0x9CA0, 0x609F, 0x8CE5, 0x60A0, 0x9749, 0x60A3, 0x8AB3,
+	0x60A6, 0x8978, 0x60A7, 0x9CA4, 0x60A9, 0x9459, 0x60AA, 0x88AB,
+	0x60B2, 0x94DF, 0x60B3, 0x9C7B, 0x60B4, 0x9CAA, 0x60B5, 0x9CAE,
+	0x60B6, 0x96E3, 0x60B8, 0x9CA7, 0x60BC, 0x9389, 0x60BD, 0x9CAC,
+	0x60C5, 0x8FEE, 0x60C6, 0x9CAD, 0x60C7, 0x93D5, 0x60D1, 0x9866,
+	0x60D3, 0x9CA9, 0x60D5, 0xFAC0, 0x60D8, 0x9CAF, 0x60DA, 0x8D9B,
+	0x60DC, 0x90C9, 0x60DE, 0xFABF, 0x60DF, 0x88D2, 0x60E0, 0x9CA8,
+	0x60E1, 0x9CA6, 0x60E3, 0x9179, 0x60E7, 0x9C9C, 0x60E8, 0x8E53,
+	0x60F0, 0x91C4, 0x60F1, 0x9CBB, 0x60F2, 0xFAC2, 0x60F3, 0x917A,
+	0x60F4, 0x9CB6, 0x60F6, 0x9CB3, 0x60F7, 0x9CB4, 0x60F9, 0x8EE4,
+	0x60FA, 0x9CB7, 0x60FB, 0x9CBA, 0x6100, 0x9CB5, 0x6101, 0x8F44,
+	0x6103, 0x9CB8, 0x6106, 0x9CB2, 0x6108, 0x96FA, 0x6109, 0x96F9,
+	0x610D, 0x9CBC, 0x610E, 0x9CBD, 0x610F, 0x88D3, 0x6111, 0xFAC3,
+	0x6115, 0x9CB1, 0x611A, 0x8BF0, 0x611B, 0x88A4, 0x611F, 0x8AB4,
+	0x6120, 0xFAC1, 0x6121, 0x9CB9, 0x6127, 0x9CC1, 0x6128, 0x9CC0,
+	0x612C, 0x9CC5, 0x6130, 0xFAC5, 0x6134, 0x9CC6, 0x6137, 0xFAC4,
+	0x613C, 0x9CC4, 0x613D, 0x9CC7, 0x613E, 0x9CBF, 0x613F, 0x9CC3,
+	0x6142, 0x9CC8, 0x6144, 0x9CC9, 0x6147, 0x9CBE, 0x6148, 0x8E9C,
+	0x614A, 0x9CC2, 0x614B, 0x91D4, 0x614C, 0x8D51, 0x614D, 0x9CB0,
+	0x614E, 0x9054, 0x6153, 0x9CD6, 0x6155, 0x95E7, 0x6158, 0x9CCC,
+	0x6159, 0x9CCD, 0x615A, 0x9CCE, 0x615D, 0x9CD5, 0x615F, 0x9CD4,
+	0x6162, 0x969D, 0x6163, 0x8AB5, 0x6165, 0x9CD2, 0x6167, 0x8C64,
+	0x6168, 0x8A53, 0x616B, 0x9CCF, 0x616E, 0x97B6, 0x616F, 0x9CD1,
+	0x6170, 0x88D4, 0x6171, 0x9CD3, 0x6173, 0x9CCA, 0x6174, 0x9CD0,
+	0x6175, 0x9CD7, 0x6176, 0x8C63, 0x6177, 0x9CCB, 0x617E, 0x977C,
+	0x6182, 0x974A, 0x6187, 0x9CDA, 0x618A, 0x9CDE, 0x618E, 0x919E,
+	0x6190, 0x97F7, 0x6191, 0x9CDF, 0x6194, 0x9CDC, 0x6196, 0x9CD9,
+	0x6198, 0xFAC6, 0x6199, 0x9CD8, 0x619A, 0x9CDD, 0x61A4, 0x95AE,
+	0x61A7, 0x93B2, 0x61A9, 0x8C65, 0x61AB, 0x9CE0, 0x61AC, 0x9CDB,
+	0x61AE, 0x9CE1, 0x61B2, 0x8C9B, 0x61B6, 0x89AF, 0x61BA, 0x9CE9,
+	0x61BE, 0x8AB6, 0x61C3, 0x9CE7, 0x61C6, 0x9CE8, 0x61C7, 0x8DA7,
+	0x61C8, 0x9CE6, 0x61C9, 0x9CE4, 0x61CA, 0x9CE3, 0x61CB, 0x9CEA,
+	0x61CC, 0x9CE2, 0x61CD, 0x9CEC, 0x61D0, 0x89F9, 0x61E3, 0x9CEE,
+	0x61E6, 0x9CED, 0x61F2, 0x92A6, 0x61F4, 0x9CF1, 0x61F6, 0x9CEF,
+	0x61F7, 0x9CE5, 0x61F8, 0x8C9C, 0x61FA, 0x9CF0, 0x61FC, 0x9CF4,
+	0x61FD, 0x9CF3, 0x61FE, 0x9CF5, 0x61FF, 0x9CF2, 0x6200, 0x9CF6,
+	0x6208, 0x9CF7, 0x6209, 0x9CF8, 0x620A, 0x95E8, 0x620C, 0x9CFA,
+	0x620D, 0x9CF9, 0x620E, 0x8F5E, 0x6210, 0x90AC, 0x6211, 0x89E4,
+	0x6212, 0x89FA, 0x6213, 0xFAC7, 0x6214, 0x9CFB, 0x6216, 0x88BD,
+	0x621A, 0x90CA, 0x621B, 0x9CFC, 0x621D, 0xE6C1, 0x621E, 0x9D40,
+	0x621F, 0x8C81, 0x6221, 0x9D41, 0x6226, 0x90ED, 0x622A, 0x9D42,
+	0x622E, 0x9D43, 0x622F, 0x8B59, 0x6230, 0x9D44, 0x6232, 0x9D45,
+	0x6233, 0x9D46, 0x6234, 0x91D5, 0x6238, 0x8CCB, 0x623B, 0x96DF,
+	0x623F, 0x965B, 0x6240, 0x8F8A, 0x6241, 0x9D47, 0x6247, 0x90EE,
+	0x6248, 0xE7BB, 0x6249, 0x94E0, 0x624B, 0x8EE8, 0x624D, 0x8DCB,
+	0x624E, 0x9D48, 0x6253, 0x91C5, 0x6255, 0x95A5, 0x6258, 0x91EF,
+	0x625B, 0x9D4B, 0x625E, 0x9D49, 0x6260, 0x9D4C, 0x6263, 0x9D4A,
+	0x6268, 0x9D4D, 0x626E, 0x95AF, 0x6271, 0x88B5, 0x6276, 0x957D,
+	0x6279, 0x94E1, 0x627C, 0x9D4E, 0x627E, 0x9D51, 0x627F, 0x8FB3,
+	0x6280, 0x8B5A, 0x6282, 0x9D4F, 0x6283, 0x9D56, 0x6284, 0x8FB4,
+	0x6289, 0x9D50, 0x628A, 0x9463, 0x6291, 0x977D, 0x6292, 0x9D52,
+	0x6293, 0x9D53, 0x6294, 0x9D57, 0x6295, 0x938A, 0x6296, 0x9D54,
+	0x6297, 0x8D52, 0x6298, 0x90DC, 0x629B, 0x9D65, 0x629C, 0x94B2,
+	0x629E, 0x91F0, 0x62A6, 0xFAC8, 0x62AB, 0x94E2, 0x62AC, 0x9DAB,
+	0x62B1, 0x95F8, 0x62B5, 0x92EF, 0x62B9, 0x9695, 0x62BB, 0x9D5A,
+	0x62BC, 0x899F, 0x62BD, 0x928A, 0x62C2, 0x9D63, 0x62C5, 0x9253,
+	0x62C6, 0x9D5D, 0x62C7, 0x9D64, 0x62C8, 0x9D5F, 0x62C9, 0x9D66,
+	0x62CA, 0x9D62, 0x62CC, 0x9D61, 0x62CD, 0x948F, 0x62CF, 0x9D5B,
+	0x62D0, 0x89FB, 0x62D1, 0x9D59, 0x62D2, 0x8B91, 0x62D3, 0x91F1,
+	0x62D4, 0x9D55, 0x62D7, 0x9D58, 0x62D8, 0x8D53, 0x62D9, 0x90D9,
+	0x62DB, 0x8FB5, 0x62DC, 0x9D60, 0x62DD, 0x9471, 0x62E0, 0x8B92,
+	0x62E1, 0x8A67, 0x62EC, 0x8A87, 0x62ED, 0x9040, 0x62EE, 0x9D68,
+	0x62EF, 0x9D6D, 0x62F1, 0x9D69, 0x62F3, 0x8C9D, 0x62F5, 0x9D6E,
+	0x62F6, 0x8E41, 0x62F7, 0x8D89, 0x62FE, 0x8F45, 0x62FF, 0x9D5C,
+	0x6301, 0x8E9D, 0x6302, 0x9D6B, 0x6307, 0x8E77, 0x6308, 0x9D6C,
+	0x6309, 0x88C2, 0x630C, 0x9D67, 0x6311, 0x92A7, 0x6319, 0x8B93,
+	0x631F, 0x8BB2, 0x6327, 0x9D6A, 0x6328, 0x88A5, 0x632B, 0x8DC1,
+	0x632F, 0x9055, 0x633A, 0x92F0, 0x633D, 0x94D2, 0x633E, 0x9D70,
+	0x633F, 0x917D, 0x6349, 0x91A8, 0x634C, 0x8E4A, 0x634D, 0x9D71,
+	0x634F, 0x9D73, 0x6350, 0x9D6F, 0x6355, 0x95DF, 0x6357, 0x92BB,
+	0x635C, 0x917B, 0x6367, 0x95F9, 0x6368, 0x8ECC, 0x6369, 0x9D80,
+	0x636B, 0x9D7E, 0x636E, 0x9098, 0x6372, 0x8C9E, 0x6376, 0x9D78,
+	0x6377, 0x8FB7, 0x637A, 0x93E6, 0x637B, 0x9450, 0x6380, 0x9D76,
+	0x6383, 0x917C, 0x6388, 0x8EF6, 0x6389, 0x9D7B, 0x638C, 0x8FB6,
+	0x638E, 0x9D75, 0x638F, 0x9D7A, 0x6392, 0x9472, 0x6396, 0x9D74,
+	0x6398, 0x8C40, 0x639B, 0x8A7C, 0x639F, 0x9D7C, 0x63A0, 0x97A9,
+	0x63A1, 0x8DCC, 0x63A2, 0x9254, 0x63A3, 0x9D79, 0x63A5, 0x90DA,
+	0x63A7, 0x8D54, 0x63A8, 0x9084, 0x63A9, 0x8986, 0x63AA, 0x915B,
+	0x63AB, 0x9D77, 0x63AC, 0x8B64, 0x63B2, 0x8C66, 0x63B4, 0x92CD,
+	0x63B5, 0x9D7D, 0x63BB, 0x917E, 0x63BE, 0x9D81, 0x63C0, 0x9D83,
+	0x63C3, 0x91B5, 0x63C4, 0x9D89, 0x63C6, 0x9D84, 0x63C9, 0x9D86,
+	0x63CF, 0x9560, 0x63D0, 0x92F1, 0x63D2, 0x9D87, 0x63D6, 0x974B,
+	0x63DA, 0x9767, 0x63DB, 0x8AB7, 0x63E1, 0x88AC, 0x63E3, 0x9D85,
+	0x63E9, 0x9D82, 0x63EE, 0x8AF6, 0x63F4, 0x8987, 0x63F5, 0xFAC9,
+	0x63F6, 0x9D88, 0x63FA, 0x9768, 0x6406, 0x9D8C, 0x640D, 0x91B9,
+	0x640F, 0x9D93, 0x6413, 0x9D8D, 0x6416, 0x9D8A, 0x6417, 0x9D91,
+	0x641C, 0x9D72, 0x6426, 0x9D8E, 0x6428, 0x9D92, 0x642C, 0x94C0,
+	0x642D, 0x938B, 0x6434, 0x9D8B, 0x6436, 0x9D8F, 0x643A, 0x8C67,
+	0x643E, 0x8DEF, 0x6442, 0x90DB, 0x644E, 0x9D97, 0x6458, 0x9345,
+	0x6460, 0xFACA, 0x6467, 0x9D94, 0x6469, 0x9680, 0x646F, 0x9D95,
+	0x6476, 0x9D96, 0x6478, 0x96CC, 0x647A, 0x90A0, 0x6483, 0x8C82,
+	0x6488, 0x9D9D, 0x6492, 0x8E54, 0x6493, 0x9D9A, 0x6495, 0x9D99,
+	0x649A, 0x9451, 0x649D, 0xFACB, 0x649E, 0x93B3, 0x64A4, 0x9350,
+	0x64A5, 0x9D9B, 0x64A9, 0x9D9C, 0x64AB, 0x958F, 0x64AD, 0x9464,
+	0x64AE, 0x8E42, 0x64B0, 0x90EF, 0x64B2, 0x966F, 0x64B9, 0x8A68,
+	0x64BB, 0x9DA3, 0x64BC, 0x9D9E, 0x64C1, 0x9769, 0x64C2, 0x9DA5,
+	0x64C5, 0x9DA1, 0x64C7, 0x9DA2, 0x64CD, 0x9180, 0x64CE, 0xFACC,
+	0x64D2, 0x9DA0, 0x64D4, 0x9D5E, 0x64D8, 0x9DA4, 0x64DA, 0x9D9F,
+	0x64E0, 0x9DA9, 0x64E1, 0x9DAA, 0x64E2, 0x9346, 0x64E3, 0x9DAC,
+	0x64E6, 0x8E43, 0x64E7, 0x9DA7, 0x64EC, 0x8B5B, 0x64EF, 0x9DAD,
+	0x64F1, 0x9DA6, 0x64F2, 0x9DB1, 0x64F4, 0x9DB0, 0x64F6, 0x9DAF,
+	0x64FA, 0x9DB2, 0x64FD, 0x9DB4, 0x64FE, 0x8FEF, 0x6500, 0x9DB3,
+	0x6505, 0x9DB7, 0x6518, 0x9DB5, 0x651C, 0x9DB6, 0x651D, 0x9D90,
+	0x6523, 0x9DB9, 0x6524, 0x9DB8, 0x652A, 0x9D98, 0x652B, 0x9DBA,
+	0x652C, 0x9DAE, 0x652F, 0x8E78, 0x6534, 0x9DBB, 0x6535, 0x9DBC,
+	0x6536, 0x9DBE, 0x6537, 0x9DBD, 0x6538, 0x9DBF, 0x6539, 0x89FC,
+	0x653B, 0x8D55, 0x653E, 0x95FA, 0x653F, 0x90AD, 0x6545, 0x8CCC,
+	0x6548, 0x9DC1, 0x654D, 0x9DC4, 0x654E, 0xFACD, 0x654F, 0x9571,
+	0x6551, 0x8B7E, 0x6555, 0x9DC3, 0x6556, 0x9DC2, 0x6557, 0x9473,
+	0x6558, 0x9DC5, 0x6559, 0x8BB3, 0x655D, 0x9DC7, 0x655E, 0x9DC6,
+	0x6562, 0x8AB8, 0x6563, 0x8E55, 0x6566, 0x93D6, 0x656C, 0x8C68,
+	0x6570, 0x9094, 0x6572, 0x9DC8, 0x6574, 0x90AE, 0x6575, 0x9347,
+	0x6577, 0x957E, 0x6578, 0x9DC9, 0x6582, 0x9DCA, 0x6583, 0x9DCB,
+	0x6587, 0x95B6, 0x6588, 0x9B7C, 0x6589, 0x90C4, 0x658C, 0x956B,
+	0x658E, 0x8DD6, 0x6590, 0x94E3, 0x6591, 0x94C1, 0x6597, 0x936C,
+	0x6599, 0x97BF, 0x659B, 0x9DCD, 0x659C, 0x8ECE, 0x659F, 0x9DCE,
+	0x65A1, 0x88B4, 0x65A4, 0x8BD2, 0x65A5, 0x90CB, 0x65A7, 0x9580,
+	0x65AB, 0x9DCF, 0x65AC, 0x8E61, 0x65AD, 0x9266, 0x65AF, 0x8E7A,
+	0x65B0, 0x9056, 0x65B7, 0x9DD0, 0x65B9, 0x95FB, 0x65BC, 0x8997,
+	0x65BD, 0x8E7B, 0x65C1, 0x9DD3, 0x65C3, 0x9DD1, 0x65C4, 0x9DD4,
+	0x65C5, 0x97B7, 0x65C6, 0x9DD2, 0x65CB, 0x90F9, 0x65CC, 0x9DD5,
+	0x65CF, 0x91B0, 0x65D2, 0x9DD6, 0x65D7, 0x8AF8, 0x65D9, 0x9DD8,
+	0x65DB, 0x9DD7, 0x65E0, 0x9DD9, 0x65E1, 0x9DDA, 0x65E2, 0x8AF9,
+	0x65E5, 0x93FA, 0x65E6, 0x9255, 0x65E7, 0x8B8C, 0x65E8, 0x8E7C,
+	0x65E9, 0x9181, 0x65EC, 0x8F7B, 0x65ED, 0x88AE, 0x65F1, 0x9DDB,
+	0x65FA, 0x89A0, 0x65FB, 0x9DDF, 0x6600, 0xFACE, 0x6602, 0x8D56,
+	0x6603, 0x9DDE, 0x6606, 0x8DA9, 0x6607, 0x8FB8, 0x6609, 0xFAD1,
+	0x660A, 0x9DDD, 0x660C, 0x8FB9, 0x660E, 0x96BE, 0x660F, 0x8DA8,
+	0x6613, 0x88D5, 0x6614, 0x90CC, 0x6615, 0xFACF, 0x661C, 0x9DE4,
+	0x661E, 0xFAD3, 0x661F, 0x90AF, 0x6620, 0x8966, 0x6624, 0xFAD4,
+	0x6625, 0x8F74, 0x6627, 0x9686, 0x6628, 0x8DF0, 0x662D, 0x8FBA,
+	0x662E, 0xFAD2, 0x662F, 0x90A5, 0x6631, 0xFA63, 0x6634, 0x9DE3,
+	0x6635, 0x9DE1, 0x6636, 0x9DE2, 0x663B, 0xFAD0, 0x663C, 0x928B,
+	0x663F, 0x9E45, 0x6641, 0x9DE8, 0x6642, 0x8E9E, 0x6643, 0x8D57,
+	0x6644, 0x9DE6, 0x6649, 0x9DE7, 0x664B, 0x9057, 0x664F, 0x9DE5,
+	0x6652, 0x8E4E, 0x6657, 0xFAD6, 0x6659, 0xFAD7, 0x665D, 0x9DEA,
+	0x665E, 0x9DE9, 0x665F, 0x9DEE, 0x6662, 0x9DEF, 0x6664, 0x9DEB,
+	0x6665, 0xFAD5, 0x6666, 0x8A41, 0x6667, 0x9DEC, 0x6668, 0x9DED,
+	0x6669, 0x94D3, 0x666E, 0x9581, 0x666F, 0x8C69, 0x6670, 0x9DF0,
+	0x6673, 0xFAD9, 0x6674, 0x90B0, 0x6676, 0x8FBB, 0x667A, 0x9271,
+	0x6681, 0x8BC5, 0x6683, 0x9DF1, 0x6684, 0x9DF5, 0x6687, 0x89C9,
+	0x6688, 0x9DF2, 0x6689, 0x9DF4, 0x668E, 0x9DF3, 0x6691, 0x8F8B,
+	0x6696, 0x9267, 0x6697, 0x88C3, 0x6698, 0x9DF6, 0x6699, 0xFADA,
+	0x669D, 0x9DF7, 0x66A0, 0xFADB, 0x66A2, 0x92A8, 0x66A6, 0x97EF,
+	0x66AB, 0x8E62, 0x66AE, 0x95E9, 0x66B2, 0xFADC, 0x66B4, 0x965C,
+	0x66B8, 0x9E41, 0x66B9, 0x9DF9, 0x66BC, 0x9DFC, 0x66BE, 0x9DFB,
+	0x66BF, 0xFADD, 0x66C1, 0x9DF8, 0x66C4, 0x9E40, 0x66C7, 0x93DC,
+	0x66C9, 0x9DFA, 0x66D6, 0x9E42, 0x66D9, 0x8F8C, 0x66DA, 0x9E43,
+	0x66DC, 0x976A, 0x66DD, 0x9498, 0x66E0, 0x9E44, 0x66E6, 0x9E46,
+	0x66E9, 0x9E47, 0x66F0, 0x9E48, 0x66F2, 0x8BC8, 0x66F3, 0x8967,
+	0x66F4, 0x8D58, 0x66F5, 0x9E49, 0x66F7, 0x9E4A, 0x66F8, 0x8F91,
+	0x66F9, 0x9182, 0x66FA, 0xFADE, 0x66FB, 0xFA66, 0x66FC, 0x99D6,
+	0x66FD, 0x915D, 0x66FE, 0x915C, 0x66FF, 0x91D6, 0x6700, 0x8DC5,
+	0x6703, 0x98F0, 0x6708, 0x8C8E, 0x6709, 0x974C, 0x670B, 0x95FC,
+	0x670D, 0x959E, 0x670E, 0xFADF, 0x670F, 0x9E4B, 0x6714, 0x8DF1,
+	0x6715, 0x92BD, 0x6716, 0x9E4C, 0x6717, 0x984E, 0x671B, 0x965D,
+	0x671D, 0x92A9, 0x671E, 0x9E4D, 0x671F, 0x8AFA, 0x6726, 0x9E4E,
+	0x6727, 0x9E4F, 0x6728, 0x96D8, 0x672A, 0x96A2, 0x672B, 0x9696,
+	0x672C, 0x967B, 0x672D, 0x8E44, 0x672E, 0x9E51, 0x6731, 0x8EE9,
+	0x6734, 0x9670, 0x6736, 0x9E53, 0x6737, 0x9E56, 0x6738, 0x9E55,
+	0x673A, 0x8AF7, 0x673D, 0x8B80, 0x673F, 0x9E52, 0x6741, 0x9E54,
+	0x6746, 0x9E57, 0x6749, 0x9099, 0x674E, 0x979B, 0x674F, 0x88C7,
+	0x6750, 0x8DDE, 0x6751, 0x91BA, 0x6753, 0x8EDB, 0x6756, 0x8FF1,
+	0x6759, 0x9E5A, 0x675C, 0x936D, 0x675E, 0x9E58, 0x675F, 0x91A9,
+	0x6760, 0x9E59, 0x6761, 0x8FF0, 0x6762, 0x96DB, 0x6763, 0x9E5B,
+	0x6764, 0x9E5C, 0x6765, 0x9788, 0x6766, 0xFAE1, 0x676A, 0x9E61,
+	0x676D, 0x8D59, 0x676F, 0x9474, 0x6770, 0x9E5E, 0x6771, 0x938C,
+	0x6772, 0x9DDC, 0x6773, 0x9DE0, 0x6775, 0x8B6E, 0x6777, 0x9466,
+	0x677C, 0x9E60, 0x677E, 0x8FBC, 0x677F, 0x94C2, 0x6785, 0x9E66,
+	0x6787, 0x94F8, 0x6789, 0x9E5D, 0x678B, 0x9E63, 0x678C, 0x9E62,
+	0x6790, 0x90CD, 0x6795, 0x968D, 0x6797, 0x97D1, 0x679A, 0x9687,
+	0x679C, 0x89CA, 0x679D, 0x8E7D, 0x67A0, 0x9867, 0x67A1, 0x9E65,
+	0x67A2, 0x9095, 0x67A6, 0x9E64, 0x67A9, 0x9E5F, 0x67AF, 0x8CCD,
+	0x67B3, 0x9E6B, 0x67B4, 0x9E69, 0x67B6, 0x89CB, 0x67B7, 0x9E67,
+	0x67B8, 0x9E6D, 0x67B9, 0x9E73, 0x67BB, 0xFAE2, 0x67C0, 0xFAE4,
+	0x67C1, 0x91C6, 0x67C4, 0x95BF, 0x67C6, 0x9E75, 0x67CA, 0x9541,
+	0x67CE, 0x9E74, 0x67CF, 0x9490, 0x67D0, 0x965E, 0x67D1, 0x8AB9,
+	0x67D3, 0x90F5, 0x67D4, 0x8F5F, 0x67D8, 0x92D1, 0x67DA, 0x974D,
+	0x67DD, 0x9E70, 0x67DE, 0x9E6F, 0x67E2, 0x9E71, 0x67E4, 0x9E6E,
+	0x67E7, 0x9E76, 0x67E9, 0x9E6C, 0x67EC, 0x9E6A, 0x67EE, 0x9E72,
+	0x67EF, 0x9E68, 0x67F1, 0x928C, 0x67F3, 0x96F6, 0x67F4, 0x8EC4,
+	0x67F5, 0x8DF2, 0x67FB, 0x8DB8, 0x67FE, 0x968F, 0x67FF, 0x8A60,
+	0x6801, 0xFAE5, 0x6802, 0x92CC, 0x6803, 0x93C8, 0x6804, 0x8968,
+	0x6813, 0x90F0, 0x6816, 0x90B2, 0x6817, 0x8C49, 0x681E, 0x9E78,
+	0x6821, 0x8D5A, 0x6822, 0x8A9C, 0x6829, 0x9E7A, 0x682A, 0x8A94,
+	0x682B, 0x9E81, 0x6832, 0x9E7D, 0x6834, 0x90F1, 0x6838, 0x8A6A,
+	0x6839, 0x8DAA, 0x683C, 0x8A69, 0x683D, 0x8DCD, 0x6840, 0x9E7B,
+	0x6841, 0x8C85, 0x6842, 0x8C6A, 0x6843, 0x938D, 0x6844, 0xFAE6,
+	0x6846, 0x9E79, 0x6848, 0x88C4, 0x684D, 0x9E7C, 0x684E, 0x9E7E,
+	0x6850, 0x8BCB, 0x6851, 0x8C4B, 0x6852, 0xFAE3, 0x6853, 0x8ABA,
+	0x6854, 0x8B6A, 0x6859, 0x9E82, 0x685C, 0x8DF7, 0x685D, 0x9691,
+	0x685F, 0x8E56, 0x6863, 0x9E83, 0x6867, 0x954F, 0x6874, 0x9E8F,
+	0x6876, 0x89B1, 0x6877, 0x9E84, 0x687E, 0x9E95, 0x687F, 0x9E85,
+	0x6881, 0x97C0, 0x6883, 0x9E8C, 0x6885, 0x947E, 0x688D, 0x9E94,
+	0x688F, 0x9E87, 0x6893, 0x88B2, 0x6894, 0x9E89, 0x6897, 0x8D5B,
+	0x689B, 0x9E8B, 0x689D, 0x9E8A, 0x689F, 0x9E86, 0x68A0, 0x9E91,
+	0x68A2, 0x8FBD, 0x68A6, 0x9AEB, 0x68A7, 0x8CE6, 0x68A8, 0x979C,
+	0x68AD, 0x9E88, 0x68AF, 0x92F2, 0x68B0, 0x8A42, 0x68B1, 0x8DAB,
+	0x68B3, 0x9E80, 0x68B5, 0x9E90, 0x68B6, 0x8A81, 0x68B9, 0x9E8E,
+	0x68BA, 0x9E92, 0x68BC, 0x938E, 0x68C4, 0x8AFC, 0x68C6, 0x9EB0,
+	0x68C8, 0xFA64, 0x68C9, 0x96C7, 0x68CA, 0x9E97, 0x68CB, 0x8AFB,
+	0x68CD, 0x9E9E, 0x68CF, 0xFAE7, 0x68D2, 0x965F, 0x68D4, 0x9E9F,
+	0x68D5, 0x9EA1, 0x68D7, 0x9EA5, 0x68D8, 0x9E99, 0x68DA, 0x9249,
+	0x68DF, 0x938F, 0x68E0, 0x9EA9, 0x68E1, 0x9E9C, 0x68E3, 0x9EA6,
+	0x68E7, 0x9EA0, 0x68EE, 0x9058, 0x68EF, 0x9EAA, 0x68F2, 0x90B1,
+	0x68F9, 0x9EA8, 0x68FA, 0x8ABB, 0x6900, 0x986F, 0x6901, 0x9E96,
+	0x6904, 0x9EA4, 0x6905, 0x88D6, 0x6908, 0x9E98, 0x690B, 0x96B8,
+	0x690C, 0x9E9D, 0x690D, 0x9041, 0x690E, 0x92C5, 0x690F, 0x9E93,
+	0x6912, 0x9EA3, 0x6919, 0x909A, 0x691A, 0x9EAD, 0x691B, 0x8A91,
+	0x691C, 0x8C9F, 0x6921, 0x9EAF, 0x6922, 0x9E9A, 0x6923, 0x9EAE,
+	0x6925, 0x9EA7, 0x6926, 0x9E9B, 0x6928, 0x9EAB, 0x692A, 0x9EAC,
+	0x6930, 0x9EBD, 0x6934, 0x93CC, 0x6936, 0x9EA2, 0x6939, 0x9EB9,
+	0x693D, 0x9EBB, 0x693F, 0x92D6, 0x694A, 0x976B, 0x6953, 0x9596,
+	0x6954, 0x9EB6, 0x6955, 0x91C8, 0x6959, 0x9EBC, 0x695A, 0x915E,
+	0x695C, 0x9EB3, 0x695D, 0x9EC0, 0x695E, 0x9EBF, 0x6960, 0x93ED,
+	0x6961, 0x9EBE, 0x6962, 0x93E8, 0x6968, 0xFAE9, 0x696A, 0x9EC2,
+	0x696B, 0x9EB5, 0x696D, 0x8BC6, 0x696E, 0x9EB8, 0x696F, 0x8F7C,
+	0x6973, 0x9480, 0x6974, 0x9EBA, 0x6975, 0x8BC9, 0x6977, 0x9EB2,
+	0x6978, 0x9EB4, 0x6979, 0x9EB1, 0x697C, 0x984F, 0x697D, 0x8A79,
+	0x697E, 0x9EB7, 0x6981, 0x9EC1, 0x6982, 0x8A54, 0x698A, 0x8DE5,
+	0x698E, 0x897C, 0x6991, 0x9ED2, 0x6994, 0x9850, 0x6995, 0x9ED5,
+	0x6998, 0xFAEB, 0x699B, 0x9059, 0x699C, 0x9ED4, 0x69A0, 0x9ED3,
+	0x69A7, 0x9ED0, 0x69AE, 0x9EC4, 0x69B1, 0x9EE1, 0x69B2, 0x9EC3,
+	0x69B4, 0x9ED6, 0x69BB, 0x9ECE, 0x69BE, 0x9EC9, 0x69BF, 0x9EC6,
+	0x69C1, 0x9EC7, 0x69C3, 0x9ECF, 0x69C7, 0xEAA0, 0x69CA, 0x9ECC,
+	0x69CB, 0x8D5C, 0x69CC, 0x92C6, 0x69CD, 0x9184, 0x69CE, 0x9ECA,
+	0x69D0, 0x9EC5, 0x69D3, 0x9EC8, 0x69D8, 0x976C, 0x69D9, 0x968A,
+	0x69DD, 0x9ECD, 0x69DE, 0x9ED7, 0x69E2, 0xFAEC, 0x69E7, 0x9EDF,
+	0x69E8, 0x9ED8, 0x69EB, 0x9EE5, 0x69ED, 0x9EE3, 0x69F2, 0x9EDE,
+	0x69F9, 0x9EDD, 0x69FB, 0x92CE, 0x69FD, 0x9185, 0x69FF, 0x9EDB,
+	0x6A02, 0x9ED9, 0x6A05, 0x9EE0, 0x6A0A, 0x9EE6, 0x6A0B, 0x94F3,
+	0x6A0C, 0x9EEC, 0x6A12, 0x9EE7, 0x6A13, 0x9EEA, 0x6A14, 0x9EE4,
+	0x6A17, 0x9294, 0x6A19, 0x9557, 0x6A1B, 0x9EDA, 0x6A1E, 0x9EE2,
+	0x6A1F, 0x8FBE, 0x6A21, 0x96CD, 0x6A22, 0x9EF6, 0x6A23, 0x9EE9,
+	0x6A29, 0x8CA0, 0x6A2A, 0x89A1, 0x6A2B, 0x8A7E, 0x6A2E, 0x9ED1,
+	0x6A30, 0xFAED, 0x6A35, 0x8FBF, 0x6A36, 0x9EEE, 0x6A38, 0x9EF5,
+	0x6A39, 0x8EF7, 0x6A3A, 0x8A92, 0x6A3D, 0x924D, 0x6A44, 0x9EEB,
+	0x6A46, 0xFAEF, 0x6A47, 0x9EF0, 0x6A48, 0x9EF4, 0x6A4B, 0x8BB4,
+	0x6A58, 0x8B6B, 0x6A59, 0x9EF2, 0x6A5F, 0x8B40, 0x6A61, 0x93C9,
+	0x6A62, 0x9EF1, 0x6A66, 0x9EF3, 0x6A6B, 0xFAEE, 0x6A72, 0x9EED,
+	0x6A73, 0xFAF0, 0x6A78, 0x9EEF, 0x6A7E, 0xFAF1, 0x6A7F, 0x8A80,
+	0x6A80, 0x9268, 0x6A84, 0x9EFA, 0x6A8D, 0x9EF8, 0x6A8E, 0x8CE7,
+	0x6A90, 0x9EF7, 0x6A97, 0x9F40, 0x6A9C, 0x9E77, 0x6AA0, 0x9EF9,
+	0x6AA2, 0x9EFB, 0x6AA3, 0x9EFC, 0x6AAA, 0x9F4B, 0x6AAC, 0x9F47,
+	0x6AAE, 0x9E8D, 0x6AB3, 0x9F46, 0x6AB8, 0x9F45, 0x6ABB, 0x9F42,
+	0x6AC1, 0x9EE8, 0x6AC2, 0x9F44, 0x6AC3, 0x9F43, 0x6AD1, 0x9F49,
+	0x6AD3, 0x9845, 0x6ADA, 0x9F4C, 0x6ADB, 0x8BF9, 0x6ADE, 0x9F48,
+	0x6ADF, 0x9F4A, 0x6AE2, 0xFAF2, 0x6AE4, 0xFAF3, 0x6AE8, 0x94A5,
+	0x6AEA, 0x9F4D, 0x6AFA, 0x9F51, 0x6AFB, 0x9F4E, 0x6B04, 0x9793,
+	0x6B05, 0x9F4F, 0x6B0A, 0x9EDC, 0x6B12, 0x9F52, 0x6B16, 0x9F53,
+	0x6B1D, 0x8954, 0x6B1F, 0x9F55, 0x6B20, 0x8C87, 0x6B21, 0x8E9F,
+	0x6B23, 0x8BD3, 0x6B27, 0x89A2, 0x6B32, 0x977E, 0x6B37, 0x9F57,
+	0x6B38, 0x9F56, 0x6B39, 0x9F59, 0x6B3A, 0x8B5C, 0x6B3D, 0x8BD4,
+	0x6B3E, 0x8ABC, 0x6B43, 0x9F5C, 0x6B47, 0x9F5B, 0x6B49, 0x9F5D,
+	0x6B4C, 0x89CC, 0x6B4E, 0x9256, 0x6B50, 0x9F5E, 0x6B53, 0x8ABD,
+	0x6B54, 0x9F60, 0x6B59, 0x9F5F, 0x6B5B, 0x9F61, 0x6B5F, 0x9F62,
+	0x6B61, 0x9F63, 0x6B62, 0x8E7E, 0x6B63, 0x90B3, 0x6B64, 0x8D9F,
+	0x6B66, 0x9590, 0x6B69, 0x95E0, 0x6B6A, 0x9863, 0x6B6F, 0x8E95,
+	0x6B73, 0x8DCE, 0x6B74, 0x97F0, 0x6B78, 0x9F64, 0x6B79, 0x9F65,
+	0x6B7B, 0x8E80, 0x6B7F, 0x9F66, 0x6B80, 0x9F67, 0x6B83, 0x9F69,
+	0x6B84, 0x9F68, 0x6B86, 0x9677, 0x6B89, 0x8F7D, 0x6B8A, 0x8EEA,
+	0x6B8B, 0x8E63, 0x6B8D, 0x9F6A, 0x6B95, 0x9F6C, 0x6B96, 0x9042,
+	0x6B98, 0x9F6B, 0x6B9E, 0x9F6D, 0x6BA4, 0x9F6E, 0x6BAA, 0x9F6F,
+	0x6BAB, 0x9F70, 0x6BAF, 0x9F71, 0x6BB1, 0x9F73, 0x6BB2, 0x9F72,
+	0x6BB3, 0x9F74, 0x6BB4, 0x89A3, 0x6BB5, 0x9269, 0x6BB7, 0x9F75,
+	0x6BBA, 0x8E45, 0x6BBB, 0x8A6B, 0x6BBC, 0x9F76, 0x6BBF, 0x9361,
+	0x6BC0, 0x9ACA, 0x6BC5, 0x8B42, 0x6BC6, 0x9F77, 0x6BCB, 0x9F78,
+	0x6BCD, 0x95EA, 0x6BCE, 0x9688, 0x6BD2, 0x93C5, 0x6BD3, 0x9F79,
+	0x6BD4, 0x94E4, 0x6BD6, 0xFAF4, 0x6BD8, 0x94F9, 0x6BDB, 0x96D1,
+	0x6BDF, 0x9F7A, 0x6BEB, 0x9F7C, 0x6BEC, 0x9F7B, 0x6BEF, 0x9F7E,
+	0x6BF3, 0x9F7D, 0x6C08, 0x9F81, 0x6C0F, 0x8E81, 0x6C11, 0x96AF,
+	0x6C13, 0x9F82, 0x6C14, 0x9F83, 0x6C17, 0x8B43, 0x6C1B, 0x9F84,
+	0x6C23, 0x9F86, 0x6C24, 0x9F85, 0x6C34, 0x9085, 0x6C37, 0x9558,
+	0x6C38, 0x8969, 0x6C3E, 0x94C3, 0x6C3F, 0xFAF5, 0x6C40, 0x92F3,
+	0x6C41, 0x8F60, 0x6C42, 0x8B81, 0x6C4E, 0x94C4, 0x6C50, 0x8EAC,
+	0x6C55, 0x9F88, 0x6C57, 0x8ABE, 0x6C5A, 0x8998, 0x6C5C, 0xFAF6,
+	0x6C5D, 0x93F0, 0x6C5E, 0x9F87, 0x6C5F, 0x8D5D, 0x6C60, 0x9272,
+	0x6C62, 0x9F89, 0x6C68, 0x9F91, 0x6C6A, 0x9F8A, 0x6C6F, 0xFAF8,
+	0x6C70, 0x91BF, 0x6C72, 0x8B82, 0x6C73, 0x9F92, 0x6C7A, 0x8C88,
+	0x6C7D, 0x8B44, 0x6C7E, 0x9F90, 0x6C81, 0x9F8E, 0x6C82, 0x9F8B,
+	0x6C83, 0x9780, 0x6C86, 0xFAF7, 0x6C88, 0x92BE, 0x6C8C, 0x93D7,
+	0x6C8D, 0x9F8C, 0x6C90, 0x9F94, 0x6C92, 0x9F93, 0x6C93, 0x8C42,
+	0x6C96, 0x89AB, 0x6C99, 0x8DB9, 0x6C9A, 0x9F8D, 0x6C9B, 0x9F8F,
+	0x6CA1, 0x9676, 0x6CA2, 0x91F2, 0x6CAB, 0x9697, 0x6CAE, 0x9F9C,
+	0x6CB1, 0x9F9D, 0x6CB3, 0x89CD, 0x6CB8, 0x95A6, 0x6CB9, 0x96FB,
+	0x6CBA, 0x9F9F, 0x6CBB, 0x8EA1, 0x6CBC, 0x8FC0, 0x6CBD, 0x9F98,
+	0x6CBE, 0x9F9E, 0x6CBF, 0x8988, 0x6CC1, 0x8BB5, 0x6CC4, 0x9F95,
+	0x6CC5, 0x9F9A, 0x6CC9, 0x90F2, 0x6CCA, 0x9491, 0x6CCC, 0x94E5,
+	0x6CD3, 0x9F97, 0x6CD5, 0x9640, 0x6CD7, 0x9F99, 0x6CD9, 0x9FA2,
+	0x6CDA, 0xFAF9, 0x6CDB, 0x9FA0, 0x6CDD, 0x9F9B, 0x6CE1, 0x9641,
+	0x6CE2, 0x9467, 0x6CE3, 0x8B83, 0x6CE5, 0x9344, 0x6CE8, 0x928D,
+	0x6CEA, 0x9FA3, 0x6CEF, 0x9FA1, 0x6CF0, 0x91D7, 0x6CF1, 0x9F96,
+	0x6CF3, 0x896A, 0x6D04, 0xFAFA, 0x6D0B, 0x976D, 0x6D0C, 0x9FAE,
+	0x6D12, 0x9FAD, 0x6D17, 0x90F4, 0x6D19, 0x9FAA, 0x6D1B, 0x978C,
+	0x6D1E, 0x93B4, 0x6D1F, 0x9FA4, 0x6D25, 0x92C3, 0x6D29, 0x896B,
+	0x6D2A, 0x8D5E, 0x6D2B, 0x9FA7, 0x6D32, 0x8F46, 0x6D33, 0x9FAC,
+	0x6D35, 0x9FAB, 0x6D36, 0x9FA6, 0x6D38, 0x9FA9, 0x6D3B, 0x8A88,
+	0x6D3D, 0x9FA8, 0x6D3E, 0x9468, 0x6D41, 0x97AC, 0x6D44, 0x8FF2,
+	0x6D45, 0x90F3, 0x6D59, 0x9FB4, 0x6D5A, 0x9FB2, 0x6D5C, 0x956C,
+	0x6D63, 0x9FAF, 0x6D64, 0x9FB1, 0x6D66, 0x8959, 0x6D69, 0x8D5F,
+	0x6D6A, 0x9851, 0x6D6C, 0x8A5C, 0x6D6E, 0x9582, 0x6D6F, 0xFAFC,
+	0x6D74, 0x9781, 0x6D77, 0x8A43, 0x6D78, 0x905A, 0x6D79, 0x9FB3,
+	0x6D85, 0x9FB8, 0x6D87, 0xFAFB, 0x6D88, 0x8FC1, 0x6D8C, 0x974F,
+	0x6D8E, 0x9FB5, 0x6D93, 0x9FB0, 0x6D95, 0x9FB6, 0x6D96, 0xFB40,
+	0x6D99, 0x97DC, 0x6D9B, 0x9393, 0x6D9C, 0x93C0, 0x6DAC, 0xFB41,
+	0x6DAF, 0x8A55, 0x6DB2, 0x8974, 0x6DB5, 0x9FBC, 0x6DB8, 0x9FBF,
+	0x6DBC, 0x97C1, 0x6DC0, 0x9784, 0x6DC5, 0x9FC6, 0x6DC6, 0x9FC0,
+	0x6DC7, 0x9FBD, 0x6DCB, 0x97D2, 0x6DCC, 0x9FC3, 0x6DCF, 0xFB42,
+	0x6DD1, 0x8F69, 0x6DD2, 0x9FC5, 0x6DD5, 0x9FCA, 0x6DD8, 0x9391,
+	0x6DD9, 0x9FC8, 0x6DDE, 0x9FC2, 0x6DE1, 0x9257, 0x6DE4, 0x9FC9,
+	0x6DE6, 0x9FBE, 0x6DE8, 0x9FC4, 0x6DEA, 0x9FCB, 0x6DEB, 0x88FA,
+	0x6DEC, 0x9FC1, 0x6DEE, 0x9FCC, 0x6DF1, 0x905B, 0x6DF2, 0xFB44,
+	0x6DF3, 0x8F7E, 0x6DF5, 0x95A3, 0x6DF7, 0x8DAC, 0x6DF8, 0xFB43,
+	0x6DF9, 0x9FB9, 0x6DFA, 0x9FC7, 0x6DFB, 0x9359, 0x6DFC, 0xFB45,
+	0x6E05, 0x90B4, 0x6E07, 0x8A89, 0x6E08, 0x8DCF, 0x6E09, 0x8FC2,
+	0x6E0A, 0x9FBB, 0x6E0B, 0x8F61, 0x6E13, 0x8C6B, 0x6E15, 0x9FBA,
+	0x6E19, 0x9FD0, 0x6E1A, 0x8F8D, 0x6E1B, 0x8CB8, 0x6E1D, 0x9FDF,
+	0x6E1F, 0x9FD9, 0x6E20, 0x8B94, 0x6E21, 0x936E, 0x6E23, 0x9FD4,
+	0x6E24, 0x9FDD, 0x6E25, 0x88AD, 0x6E26, 0x8951, 0x6E27, 0xFB48,
+	0x6E29, 0x89B7, 0x6E2B, 0x9FD6, 0x6E2C, 0x91AA, 0x6E2D, 0x9FCD,
+	0x6E2E, 0x9FCF, 0x6E2F, 0x8D60, 0x6E38, 0x9FE0, 0x6E39, 0xFB46,
+	0x6E3A, 0x9FDB, 0x6E3C, 0xFB49, 0x6E3E, 0x9FD3, 0x6E43, 0x9FDA,
+	0x6E4A, 0x96A9, 0x6E4D, 0x9FD8, 0x6E4E, 0x9FDC, 0x6E56, 0x8CCE,
+	0x6E58, 0x8FC3, 0x6E5B, 0x9258, 0x6E5C, 0xFB47, 0x6E5F, 0x9FD2,
+	0x6E67, 0x974E, 0x6E6B, 0x9FD5, 0x6E6E, 0x9FCE, 0x6E6F, 0x9392,
+	0x6E72, 0x9FD1, 0x6E76, 0x9FD7, 0x6E7E, 0x9870, 0x6E7F, 0x8EBC,
+	0x6E80, 0x969E, 0x6E82, 0x9FE1, 0x6E8C, 0x94AC, 0x6E8F, 0x9FED,
+	0x6E90, 0x8CB9, 0x6E96, 0x8F80, 0x6E98, 0x9FE3, 0x6E9C, 0x97AD,
+	0x6E9D, 0x8D61, 0x6E9F, 0x9FF0, 0x6EA2, 0x88EC, 0x6EA5, 0x9FEE,
+	0x6EAA, 0x9FE2, 0x6EAF, 0x9FE8, 0x6EB2, 0x9FEA, 0x6EB6, 0x976E,
+	0x6EB7, 0x9FE5, 0x6EBA, 0x934D, 0x6EBD, 0x9FE7, 0x6EBF, 0xFB4A,
+	0x6EC2, 0x9FEF, 0x6EC4, 0x9FE9, 0x6EC5, 0x96C5, 0x6EC9, 0x9FE4,
+	0x6ECB, 0x8EA0, 0x6ECC, 0x9FFC, 0x6ED1, 0x8A8A, 0x6ED3, 0x9FE6,
+	0x6ED4, 0x9FEB, 0x6ED5, 0x9FEC, 0x6EDD, 0x91EA, 0x6EDE, 0x91D8,
+	0x6EEC, 0x9FF4, 0x6EEF, 0x9FFA, 0x6EF2, 0x9FF8, 0x6EF4, 0x9348,
+	0x6EF7, 0xE042, 0x6EF8, 0x9FF5, 0x6EFE, 0x9FF6, 0x6EFF, 0x9FDE,
+	0x6F01, 0x8B99, 0x6F02, 0x9559, 0x6F06, 0x8EBD, 0x6F09, 0x8D97,
+	0x6F0F, 0x9852, 0x6F11, 0x9FF2, 0x6F13, 0xE041, 0x6F14, 0x8989,
+	0x6F15, 0x9186, 0x6F20, 0x9499, 0x6F22, 0x8ABF, 0x6F23, 0x97F8,
+	0x6F2B, 0x969F, 0x6F2C, 0x92D0, 0x6F31, 0x9FF9, 0x6F32, 0x9FFB,
+	0x6F38, 0x9151, 0x6F3E, 0xE040, 0x6F3F, 0x9FF7, 0x6F41, 0x9FF1,
+	0x6F45, 0x8AC1, 0x6F54, 0x8C89, 0x6F58, 0xE04E, 0x6F5B, 0xE049,
+	0x6F5C, 0x90F6, 0x6F5F, 0x8A83, 0x6F64, 0x8F81, 0x6F66, 0xE052,
+	0x6F6D, 0xE04B, 0x6F6E, 0x92AA, 0x6F6F, 0xE048, 0x6F70, 0x92D7,
+	0x6F74, 0xE06B, 0x6F78, 0xE045, 0x6F7A, 0xE044, 0x6F7C, 0xE04D,
+	0x6F80, 0xE047, 0x6F81, 0xE046, 0x6F82, 0xE04C, 0x6F84, 0x909F,
+	0x6F86, 0xE043, 0x6F88, 0xFB4B, 0x6F8E, 0xE04F, 0x6F91, 0xE050,
+	0x6F97, 0x8AC0, 0x6FA1, 0xE055, 0x6FA3, 0xE054, 0x6FA4, 0xE056,
+	0x6FAA, 0xE059, 0x6FB1, 0x9362, 0x6FB3, 0xE053, 0x6FB5, 0xFB4C,
+	0x6FB9, 0xE057, 0x6FC0, 0x8C83, 0x6FC1, 0x91F7, 0x6FC2, 0xE051,
+	0x6FC3, 0x945A, 0x6FC6, 0xE058, 0x6FD4, 0xE05D, 0x6FD5, 0xE05B,
+	0x6FD8, 0xE05E, 0x6FDB, 0xE061, 0x6FDF, 0xE05A, 0x6FE0, 0x8D8A,
+	0x6FE1, 0x9447, 0x6FE4, 0x9FB7, 0x6FEB, 0x9794, 0x6FEC, 0xE05C,
+	0x6FEE, 0xE060, 0x6FEF, 0x91F3, 0x6FF1, 0xE05F, 0x6FF3, 0xE04A,
+	0x6FF5, 0xFB4D, 0x6FF6, 0xE889, 0x6FFA, 0xE064, 0x6FFE, 0xE068,
+	0x7001, 0xE066, 0x7005, 0xFB4E, 0x7007, 0xFB4F, 0x7009, 0xE062,
+	0x700B, 0xE063, 0x700F, 0xE067, 0x7011, 0xE065, 0x7015, 0x956D,
+	0x7018, 0xE06D, 0x701A, 0xE06A, 0x701B, 0xE069, 0x701D, 0xE06C,
+	0x701E, 0x93D2, 0x701F, 0xE06E, 0x7026, 0x9295, 0x7027, 0x91EB,
+	0x7028, 0xFB50, 0x702C, 0x90A3, 0x7030, 0xE06F, 0x7032, 0xE071,
+	0x703E, 0xE070, 0x704C, 0x9FF3, 0x7051, 0xE072, 0x7058, 0x93E5,
+	0x7063, 0xE073, 0x706B, 0x89CE, 0x706F, 0x9394, 0x7070, 0x8A44,
+	0x7078, 0x8B84, 0x707C, 0x8EDC, 0x707D, 0x8DD0, 0x7085, 0xFB51,
+	0x7089, 0x9846, 0x708A, 0x9086, 0x708E, 0x898A, 0x7092, 0xE075,
+	0x7099, 0xE074, 0x70AB, 0xFB52, 0x70AC, 0xE078, 0x70AD, 0x9259,
+	0x70AE, 0xE07B, 0x70AF, 0xE076, 0x70B3, 0xE07A, 0x70B8, 0xE079,
+	0x70B9, 0x935F, 0x70BA, 0x88D7, 0x70BB, 0xFA62, 0x70C8, 0x97F3,
+	0x70CB, 0xE07D, 0x70CF, 0x8947, 0x70D9, 0xE080, 0x70DD, 0xE07E,
+	0x70DF, 0xE07C, 0x70F1, 0xE077, 0x70F9, 0x9642, 0x70FD, 0xE082,
+	0x7104, 0xFB54, 0x7109, 0xE081, 0x710F, 0xFB53, 0x7114, 0x898B,
+	0x7119, 0xE084, 0x711A, 0x95B0, 0x711C, 0xE083, 0x7121, 0x96B3,
+	0x7126, 0x8FC5, 0x7136, 0x9152, 0x713C, 0x8FC4, 0x7146, 0xFB56,
+	0x7147, 0xFB57, 0x7149, 0x97F9, 0x714C, 0xE08A, 0x714E, 0x90F7,
+	0x7155, 0xE086, 0x7156, 0xE08B, 0x7159, 0x898C, 0x715C, 0xFB55,
+	0x7162, 0xE089, 0x7164, 0x9481, 0x7165, 0xE085, 0x7166, 0xE088,
+	0x7167, 0x8FC6, 0x7169, 0x94CF, 0x716C, 0xE08C, 0x716E, 0x8ECF,
+	0x717D, 0x90F8, 0x7184, 0xE08F, 0x7188, 0xE087, 0x718A, 0x8C46,
+	0x718F, 0xE08D, 0x7194, 0x976F, 0x7195, 0xE090, 0x7199, 0xEAA4,
+	0x719F, 0x8F6E, 0x71A8, 0xE091, 0x71AC, 0xE092, 0x71B1, 0x944D,
+	0x71B9, 0xE094, 0x71BE, 0xE095, 0x71C1, 0xFB59, 0x71C3, 0x9452,
+	0x71C8, 0x9395, 0x71C9, 0xE097, 0x71CE, 0xE099, 0x71D0, 0x97D3,
+	0x71D2, 0xE096, 0x71D4, 0xE098, 0x71D5, 0x898D, 0x71D7, 0xE093,
+	0x71DF, 0x9A7A, 0x71E0, 0xE09A, 0x71E5, 0x9187, 0x71E6, 0x8E57,
+	0x71E7, 0xE09C, 0x71EC, 0xE09B, 0x71ED, 0x9043, 0x71EE, 0x99D7,
+	0x71F5, 0xE09D, 0x71F9, 0xE09F, 0x71FB, 0xE08E, 0x71FC, 0xE09E,
+	0x71FE, 0xFB5A, 0x71FF, 0xE0A0, 0x7206, 0x949A, 0x720D, 0xE0A1,
+	0x7210, 0xE0A2, 0x721B, 0xE0A3, 0x7228, 0xE0A4, 0x722A, 0x92DC,
+	0x722C, 0xE0A6, 0x722D, 0xE0A5, 0x7230, 0xE0A7, 0x7232, 0xE0A8,
+	0x7235, 0x8EDD, 0x7236, 0x9583, 0x723A, 0x96EA, 0x723B, 0xE0A9,
+	0x723C, 0xE0AA, 0x723D, 0x9175, 0x723E, 0x8EA2, 0x723F, 0xE0AB,
+	0x7240, 0xE0AC, 0x7246, 0xE0AD, 0x7247, 0x95D0, 0x7248, 0x94C5,
+	0x724B, 0xE0AE, 0x724C, 0x9476, 0x7252, 0x92AB, 0x7258, 0xE0AF,
+	0x7259, 0x89E5, 0x725B, 0x8B8D, 0x725D, 0x96C4, 0x725F, 0x96B4,
+	0x7261, 0x89B2, 0x7262, 0x9853, 0x7267, 0x9671, 0x7269, 0x95A8,
+	0x7272, 0x90B5, 0x7274, 0xE0B0, 0x7279, 0x93C1, 0x727D, 0x8CA1,
+	0x727E, 0xE0B1, 0x7280, 0x8DD2, 0x7281, 0xE0B3, 0x7282, 0xE0B2,
+	0x7287, 0xE0B4, 0x7292, 0xE0B5, 0x7296, 0xE0B6, 0x72A0, 0x8B5D,
+	0x72A2, 0xE0B7, 0x72A7, 0xE0B8, 0x72AC, 0x8CA2, 0x72AF, 0x94C6,
+	0x72B1, 0xFB5B, 0x72B2, 0xE0BA, 0x72B6, 0x8FF3, 0x72B9, 0xE0B9,
+	0x72BE, 0xFB5C, 0x72C2, 0x8BB6, 0x72C3, 0xE0BB, 0x72C4, 0xE0BD,
+	0x72C6, 0xE0BC, 0x72CE, 0xE0BE, 0x72D0, 0x8CCF, 0x72D2, 0xE0BF,
+	0x72D7, 0x8BE7, 0x72D9, 0x915F, 0x72DB, 0x8D9D, 0x72E0, 0xE0C1,
+	0x72E1, 0xE0C2, 0x72E2, 0xE0C0, 0x72E9, 0x8EEB, 0x72EC, 0x93C6,
+	0x72ED, 0x8BB7, 0x72F7, 0xE0C4, 0x72F8, 0x924B, 0x72F9, 0xE0C3,
+	0x72FC, 0x9854, 0x72FD, 0x9482, 0x730A, 0xE0C7, 0x7316, 0xE0C9,
+	0x7317, 0xE0C6, 0x731B, 0x96D2, 0x731C, 0xE0C8, 0x731D, 0xE0CA,
+	0x731F, 0x97C2, 0x7324, 0xFB5D, 0x7325, 0xE0CE, 0x7329, 0xE0CD,
+	0x732A, 0x9296, 0x732B, 0x944C, 0x732E, 0x8CA3, 0x732F, 0xE0CC,
+	0x7334, 0xE0CB, 0x7336, 0x9750, 0x7337, 0x9751, 0x733E, 0xE0CF,
+	0x733F, 0x898E, 0x7344, 0x8D96, 0x7345, 0x8E82, 0x734E, 0xE0D0,
+	0x734F, 0xE0D1, 0x7357, 0xE0D3, 0x7363, 0x8F62, 0x7368, 0xE0D5,
+	0x736A, 0xE0D4, 0x7370, 0xE0D6, 0x7372, 0x8A6C, 0x7375, 0xE0D8,
+	0x7377, 0xFB5F, 0x7378, 0xE0D7, 0x737A, 0xE0DA, 0x737B, 0xE0D9,
+	0x7384, 0x8CBA, 0x7387, 0x97A6, 0x7389, 0x8BCA, 0x738B, 0x89A4,
+	0x7396, 0x8BE8, 0x73A9, 0x8ADF, 0x73B2, 0x97E6, 0x73B3, 0xE0DC,
+	0x73BB, 0xE0DE, 0x73BD, 0xFB60, 0x73C0, 0xE0DF, 0x73C2, 0x89CF,
+	0x73C8, 0xE0DB, 0x73C9, 0xFB61, 0x73CA, 0x8E58, 0x73CD, 0x92BF,
+	0x73CE, 0xE0DD, 0x73D2, 0xFB64, 0x73D6, 0xFB62, 0x73DE, 0xE0E2,
+	0x73E0, 0x8EEC, 0x73E3, 0xFB63, 0x73E5, 0xE0E0, 0x73EA, 0x8C5D,
+	0x73ED, 0x94C7, 0x73EE, 0xE0E1, 0x73F1, 0xE0FC, 0x73F5, 0xFB66,
+	0x73F8, 0xE0E7, 0x73FE, 0x8CBB, 0x7403, 0x8B85, 0x7405, 0xE0E4,
+	0x7406, 0x979D, 0x7407, 0xFB65, 0x7409, 0x97AE, 0x7422, 0x91F4,
+	0x7425, 0xE0E6, 0x7426, 0xFB67, 0x7429, 0xFB69, 0x742A, 0xFB68,
+	0x742E, 0xFB6A, 0x7432, 0xE0E8, 0x7433, 0x97D4, 0x7434, 0x8BD5,
+	0x7435, 0x94FA, 0x7436, 0x9469, 0x743A, 0xE0E9, 0x743F, 0xE0EB,
+	0x7441, 0xE0EE, 0x7455, 0xE0EA, 0x7459, 0xE0ED, 0x745A, 0x8CE8,
+	0x745B, 0x896C, 0x745C, 0xE0EF, 0x745E, 0x9090, 0x745F, 0xE0EC,
+	0x7460, 0x97DA, 0x7462, 0xFB6B, 0x7463, 0xE0F2, 0x7464, 0xEAA2,
+	0x7469, 0xE0F0, 0x746A, 0xE0F3, 0x746F, 0xE0E5, 0x7470, 0xE0F1,
+	0x7473, 0x8DBA, 0x7476, 0xE0F4, 0x747E, 0xE0F5, 0x7483, 0x979E,
+	0x7489, 0xFB6C, 0x748B, 0xE0F6, 0x749E, 0xE0F7, 0x749F, 0xFB6D,
+	0x74A2, 0xE0E3, 0x74A7, 0xE0F8, 0x74B0, 0x8AC2, 0x74BD, 0x8EA3,
+	0x74CA, 0xE0F9, 0x74CF, 0xE0FA, 0x74D4, 0xE0FB, 0x74DC, 0x895A,
+	0x74E0, 0xE140, 0x74E2, 0x955A, 0x74E3, 0xE141, 0x74E6, 0x8AA2,
+	0x74E7, 0xE142, 0x74E9, 0xE143, 0x74EE, 0xE144, 0x74F0, 0xE146,
+	0x74F1, 0xE147, 0x74F2, 0xE145, 0x74F6, 0x9572, 0x74F7, 0xE149,
+	0x74F8, 0xE148, 0x7501, 0xFB6E, 0x7503, 0xE14B, 0x7504, 0xE14A,
+	0x7505, 0xE14C, 0x750C, 0xE14D, 0x750D, 0xE14F, 0x750E, 0xE14E,
+	0x7511, 0x8D99, 0x7513, 0xE151, 0x7515, 0xE150, 0x7518, 0x8AC3,
+	0x751A, 0x9072, 0x751C, 0x935B, 0x751E, 0xE152, 0x751F, 0x90B6,
+	0x7523, 0x8E59, 0x7525, 0x8999, 0x7526, 0xE153, 0x7528, 0x9770,
+	0x752B, 0x95E1, 0x752C, 0xE154, 0x752F, 0xFAA8, 0x7530, 0x9363,
+	0x7531, 0x9752, 0x7532, 0x8D62, 0x7533, 0x905C, 0x7537, 0x926A,
+	0x7538, 0x99B2, 0x753A, 0x92AC, 0x753B, 0x89E6, 0x753C, 0xE155,
+	0x7544, 0xE156, 0x7546, 0xE15B, 0x7549, 0xE159, 0x754A, 0xE158,
+	0x754B, 0x9DC0, 0x754C, 0x8A45, 0x754D, 0xE157, 0x754F, 0x88D8,
+	0x7551, 0x94A8, 0x7554, 0x94C8, 0x7559, 0x97AF, 0x755A, 0xE15C,
+	0x755B, 0xE15A, 0x755C, 0x927B, 0x755D, 0x90A4, 0x7560, 0x94A9,
+	0x7562, 0x954C, 0x7564, 0xE15E, 0x7565, 0x97AA, 0x7566, 0x8C6C,
+	0x7567, 0xE15F, 0x7569, 0xE15D, 0x756A, 0x94D4, 0x756B, 0xE160,
+	0x756D, 0xE161, 0x756F, 0xFB6F, 0x7570, 0x88D9, 0x7573, 0x8FF4,
+	0x7574, 0xE166, 0x7576, 0xE163, 0x7577, 0x93EB, 0x7578, 0xE162,
+	0x757F, 0x8B45, 0x7582, 0xE169, 0x7586, 0xE164, 0x7587, 0xE165,
+	0x7589, 0xE168, 0x758A, 0xE167, 0x758B, 0x9544, 0x758E, 0x9161,
+	0x758F, 0x9160, 0x7591, 0x8B5E, 0x7594, 0xE16A, 0x759A, 0xE16B,
+	0x759D, 0xE16C, 0x75A3, 0xE16E, 0x75A5, 0xE16D, 0x75AB, 0x8975,
+	0x75B1, 0xE176, 0x75B2, 0x94E6, 0x75B3, 0xE170, 0x75B5, 0xE172,
+	0x75B8, 0xE174, 0x75B9, 0x905D, 0x75BC, 0xE175, 0x75BD, 0xE173,
+	0x75BE, 0x8EBE, 0x75C2, 0xE16F, 0x75C3, 0xE171, 0x75C5, 0x9561,
+	0x75C7, 0x8FC7, 0x75CA, 0xE178, 0x75CD, 0xE177, 0x75D2, 0xE179,
+	0x75D4, 0x8EA4, 0x75D5, 0x8DAD, 0x75D8, 0x9397, 0x75D9, 0xE17A,
+	0x75DB, 0x92C9, 0x75DE, 0xE17C, 0x75E2, 0x979F, 0x75E3, 0xE17B,
+	0x75E9, 0x9189, 0x75F0, 0xE182, 0x75F2, 0xE184, 0x75F3, 0xE185,
+	0x75F4, 0x9273, 0x75FA, 0xE183, 0x75FC, 0xE180, 0x75FE, 0xE17D,
+	0x75FF, 0xE17E, 0x7601, 0xE181, 0x7609, 0xE188, 0x760B, 0xE186,
+	0x760D, 0xE187, 0x761F, 0xE189, 0x7620, 0xE18B, 0x7621, 0xE18C,
+	0x7622, 0xE18D, 0x7624, 0xE18E, 0x7627, 0xE18A, 0x7630, 0xE190,
+	0x7634, 0xE18F, 0x763B, 0xE191, 0x7642, 0x97C3, 0x7646, 0xE194,
+	0x7647, 0xE192, 0x7648, 0xE193, 0x764C, 0x8AE0, 0x7652, 0x96FC,
+	0x7656, 0x95C8, 0x7658, 0xE196, 0x765C, 0xE195, 0x7661, 0xE197,
+	0x7662, 0xE198, 0x7667, 0xE19C, 0x7668, 0xE199, 0x7669, 0xE19A,
+	0x766A, 0xE19B, 0x766C, 0xE19D, 0x7670, 0xE19E, 0x7672, 0xE19F,
+	0x7676, 0xE1A0, 0x7678, 0xE1A1, 0x767A, 0x94AD, 0x767B, 0x936F,
+	0x767C, 0xE1A2, 0x767D, 0x9492, 0x767E, 0x9553, 0x7680, 0xE1A3,
+	0x7682, 0xFB70, 0x7683, 0xE1A4, 0x7684, 0x9349, 0x7686, 0x8A46,
+	0x7687, 0x8D63, 0x7688, 0xE1A5, 0x768B, 0xE1A6, 0x768E, 0xE1A7,
+	0x7690, 0x8E48, 0x7693, 0xE1A9, 0x7696, 0xE1A8, 0x7699, 0xE1AA,
+	0x769A, 0xE1AB, 0x769B, 0xFB73, 0x769C, 0xFB71, 0x769E, 0xFB72,
+	0x76A6, 0xFB74, 0x76AE, 0x94E7, 0x76B0, 0xE1AC, 0x76B4, 0xE1AD,
+	0x76B7, 0xEA89, 0x76B8, 0xE1AE, 0x76B9, 0xE1AF, 0x76BA, 0xE1B0,
+	0x76BF, 0x8E4D, 0x76C2, 0xE1B1, 0x76C3, 0x9475, 0x76C6, 0x967E,
+	0x76C8, 0x896D, 0x76CA, 0x8976, 0x76CD, 0xE1B2, 0x76D2, 0xE1B4,
+	0x76D6, 0xE1B3, 0x76D7, 0x9390, 0x76DB, 0x90B7, 0x76DC, 0x9F58,
+	0x76DE, 0xE1B5, 0x76DF, 0x96BF, 0x76E1, 0xE1B6, 0x76E3, 0x8AC4,
+	0x76E4, 0x94D5, 0x76E5, 0xE1B7, 0x76E7, 0xE1B8, 0x76EA, 0xE1B9,
+	0x76EE, 0x96DA, 0x76F2, 0x96D3, 0x76F4, 0x92BC, 0x76F8, 0x918A,
+	0x76FB, 0xE1BB, 0x76FE, 0x8F82, 0x7701, 0x8FC8, 0x7704, 0xE1BE,
+	0x7707, 0xE1BD, 0x7708, 0xE1BC, 0x7709, 0x94FB, 0x770B, 0x8AC5,
+	0x770C, 0x8CA7, 0x771B, 0xE1C4, 0x771E, 0xE1C1, 0x771F, 0x905E,
+	0x7720, 0x96B0, 0x7724, 0xE1C0, 0x7725, 0xE1C2, 0x7726, 0xE1C3,
+	0x7729, 0xE1BF, 0x7737, 0xE1C5, 0x7738, 0xE1C6, 0x773A, 0x92AD,
+	0x773C, 0x8AE1, 0x7740, 0x9285, 0x7746, 0xFB76, 0x7747, 0xE1C7,
+	0x775A, 0xE1C8, 0x775B, 0xE1CB, 0x7761, 0x9087, 0x7763, 0x93C2,
+	0x7765, 0xE1CC, 0x7766, 0x9672, 0x7768, 0xE1C9, 0x776B, 0xE1CA,
+	0x7779, 0xE1CF, 0x777E, 0xE1CE, 0x777F, 0xE1CD, 0x778B, 0xE1D1,
+	0x778E, 0xE1D0, 0x7791, 0xE1D2, 0x779E, 0xE1D4, 0x77A0, 0xE1D3,
+	0x77A5, 0x95CB, 0x77AC, 0x8F75, 0x77AD, 0x97C4, 0x77B0, 0xE1D5,
+	0x77B3, 0x93B5, 0x77B6, 0xE1D6, 0x77B9, 0xE1D7, 0x77BB, 0xE1DB,
+	0x77BC, 0xE1D9, 0x77BD, 0xE1DA, 0x77BF, 0xE1D8, 0x77C7, 0xE1DC,
+	0x77CD, 0xE1DD, 0x77D7, 0xE1DE, 0x77DA, 0xE1DF, 0x77DB, 0x96B5,
+	0x77DC, 0xE1E0, 0x77E2, 0x96EE, 0x77E3, 0xE1E1, 0x77E5, 0x926D,
+	0x77E7, 0x948A, 0x77E9, 0x8BE9, 0x77ED, 0x925A, 0x77EE, 0xE1E2,
+	0x77EF, 0x8BB8, 0x77F3, 0x90CE, 0x77FC, 0xE1E3, 0x7802, 0x8DBB,
+	0x780C, 0xE1E4, 0x7812, 0xE1E5, 0x7814, 0x8CA4, 0x7815, 0x8DD3,
+	0x7820, 0xE1E7, 0x7821, 0xFB78, 0x7825, 0x9375, 0x7826, 0x8DD4,
+	0x7827, 0x8B6D, 0x7832, 0x9643, 0x7834, 0x946A, 0x783A, 0x9376,
+	0x783F, 0x8D7B, 0x7845, 0xE1E9, 0x784E, 0xFB79, 0x785D, 0x8FC9,
+	0x7864, 0xFB7A, 0x786B, 0x97B0, 0x786C, 0x8D64, 0x786F, 0x8CA5,
+	0x7872, 0x94A1, 0x7874, 0xE1EB, 0x787A, 0xFB7B, 0x787C, 0xE1ED,
+	0x7881, 0x8CE9, 0x7886, 0xE1EC, 0x7887, 0x92F4, 0x788C, 0xE1EF,
+	0x788D, 0x8A56, 0x788E, 0xE1EA, 0x7891, 0x94E8, 0x7893, 0x894F,
+	0x7895, 0x8DEA, 0x7897, 0x9871, 0x789A, 0xE1EE, 0x78A3, 0xE1F0,
+	0x78A7, 0x95C9, 0x78A9, 0x90D7, 0x78AA, 0xE1F2, 0x78AF, 0xE1F3,
+	0x78B5, 0xE1F1, 0x78BA, 0x8A6D, 0x78BC, 0xE1F9, 0x78BE, 0xE1F8,
+	0x78C1, 0x8EA5, 0x78C5, 0xE1FA, 0x78C6, 0xE1F5, 0x78CA, 0xE1FB,
+	0x78CB, 0xE1F6, 0x78D0, 0x94D6, 0x78D1, 0xE1F4, 0x78D4, 0xE1F7,
+	0x78DA, 0xE241, 0x78E7, 0xE240, 0x78E8, 0x9681, 0x78EC, 0xE1FC,
+	0x78EF, 0x88E9, 0x78F4, 0xE243, 0x78FD, 0xE242, 0x7901, 0x8FCA,
+	0x7907, 0xE244, 0x790E, 0x9162, 0x7911, 0xE246, 0x7912, 0xE245,
+	0x7919, 0xE247, 0x7926, 0xE1E6, 0x792A, 0xE1E8, 0x792B, 0xE249,
+	0x792C, 0xE248, 0x7930, 0xFB7C, 0x793A, 0x8EA6, 0x793C, 0x97E7,
+	0x793E, 0x8ED0, 0x7940, 0xE24A, 0x7941, 0x8C56, 0x7947, 0x8B5F,
+	0x7948, 0x8B46, 0x7949, 0x8E83, 0x7950, 0x9753, 0x7953, 0xE250,
+	0x7955, 0xE24F, 0x7956, 0x9163, 0x7957, 0xE24C, 0x795A, 0xE24E,
+	0x795D, 0x8F6A, 0x795E, 0x905F, 0x795F, 0xE24D, 0x7960, 0xE24B,
+	0x7962, 0x9449, 0x7965, 0x8FCB, 0x7968, 0x955B, 0x796D, 0x8DD5,
+	0x7977, 0x9398, 0x797A, 0xE251, 0x797F, 0xE252, 0x7980, 0xE268,
+	0x7981, 0x8BD6, 0x7984, 0x985C, 0x7985, 0x9154, 0x798A, 0xE253,
+	0x798D, 0x89D0, 0x798E, 0x92F5, 0x798F, 0x959F, 0x7994, 0xFB81,
+	0x799B, 0xFB83, 0x799D, 0xE254, 0x79A6, 0x8B9A, 0x79A7, 0xE255,
+	0x79AA, 0xE257, 0x79AE, 0xE258, 0x79B0, 0x9448, 0x79B3, 0xE259,
+	0x79B9, 0xE25A, 0x79BA, 0xE25B, 0x79BD, 0x8BD7, 0x79BE, 0x89D1,
+	0x79BF, 0x93C3, 0x79C0, 0x8F47, 0x79C1, 0x8E84, 0x79C9, 0xE25C,
+	0x79CB, 0x8F48, 0x79D1, 0x89C8, 0x79D2, 0x9562, 0x79D5, 0xE25D,
+	0x79D8, 0x94E9, 0x79DF, 0x9164, 0x79E1, 0xE260, 0x79E3, 0xE261,
+	0x79E4, 0x9489, 0x79E6, 0x9060, 0x79E7, 0xE25E, 0x79E9, 0x9281,
+	0x79EC, 0xE25F, 0x79F0, 0x8FCC, 0x79FB, 0x88DA, 0x7A00, 0x8B48,
+	0x7A08, 0xE262, 0x7A0B, 0x92F6, 0x7A0D, 0xE263, 0x7A0E, 0x90C5,
+	0x7A14, 0x96AB, 0x7A17, 0x9542, 0x7A18, 0xE264, 0x7A19, 0xE265,
+	0x7A1A, 0x9274, 0x7A1C, 0x97C5, 0x7A1F, 0xE267, 0x7A20, 0xE266,
+	0x7A2E, 0x8EED, 0x7A31, 0xE269, 0x7A32, 0x88EE, 0x7A37, 0xE26C,
+	0x7A3B, 0xE26A, 0x7A3C, 0x89D2, 0x7A3D, 0x8C6D, 0x7A3E, 0xE26B,
+	0x7A3F, 0x8D65, 0x7A40, 0x8D92, 0x7A42, 0x95E4, 0x7A43, 0xE26D,
+	0x7A46, 0x9673, 0x7A49, 0xE26F, 0x7A4D, 0x90CF, 0x7A4E, 0x896E,
+	0x7A4F, 0x89B8, 0x7A50, 0x88AA, 0x7A57, 0xE26E, 0x7A61, 0xE270,
+	0x7A62, 0xE271, 0x7A63, 0x8FF5, 0x7A69, 0xE272, 0x7A6B, 0x8A6E,
+	0x7A70, 0xE274, 0x7A74, 0x8C8A, 0x7A76, 0x8B86, 0x7A79, 0xE275,
+	0x7A7A, 0x8BF3, 0x7A7D, 0xE276, 0x7A7F, 0x90FA, 0x7A81, 0x93CB,
+	0x7A83, 0x90DE, 0x7A84, 0x8DF3, 0x7A88, 0xE277, 0x7A92, 0x9282,
+	0x7A93, 0x918B, 0x7A95, 0xE279, 0x7A96, 0xE27B, 0x7A97, 0xE278,
+	0x7A98, 0xE27A, 0x7A9F, 0x8C41, 0x7AA9, 0xE27C, 0x7AAA, 0x8C45,
+	0x7AAE, 0x8B87, 0x7AAF, 0x9771, 0x7AB0, 0xE27E, 0x7AB6, 0xE280,
+	0x7ABA, 0x894D, 0x7ABF, 0xE283, 0x7AC3, 0x8A96, 0x7AC4, 0xE282,
+	0x7AC5, 0xE281, 0x7AC7, 0xE285, 0x7AC8, 0xE27D, 0x7ACA, 0xE286,
+	0x7ACB, 0x97A7, 0x7ACD, 0xE287, 0x7ACF, 0xE288, 0x7AD1, 0xFB84,
+	0x7AD2, 0x9AF2, 0x7AD3, 0xE28A, 0x7AD5, 0xE289, 0x7AD9, 0xE28B,
+	0x7ADA, 0xE28C, 0x7ADC, 0x97B3, 0x7ADD, 0xE28D, 0x7ADF, 0xE8ED,
+	0x7AE0, 0x8FCD, 0x7AE1, 0xE28E, 0x7AE2, 0xE28F, 0x7AE3, 0x8F76,
+	0x7AE5, 0x93B6, 0x7AE6, 0xE290, 0x7AE7, 0xFB85, 0x7AEA, 0x9247,
+	0x7AEB, 0xFB87, 0x7AED, 0xE291, 0x7AEF, 0x925B, 0x7AF0, 0xE292,
+	0x7AF6, 0x8BA3, 0x7AF8, 0x995E, 0x7AF9, 0x927C, 0x7AFA, 0x8EB1,
+	0x7AFF, 0x8AC6, 0x7B02, 0xE293, 0x7B04, 0xE2A0, 0x7B06, 0xE296,
+	0x7B08, 0x8B88, 0x7B0A, 0xE295, 0x7B0B, 0xE2A2, 0x7B0F, 0xE294,
+	0x7B11, 0x8FCE, 0x7B18, 0xE298, 0x7B19, 0xE299, 0x7B1B, 0x934A,
+	0x7B1E, 0xE29A, 0x7B20, 0x8A7D, 0x7B25, 0x9079, 0x7B26, 0x9584,
+	0x7B28, 0xE29C, 0x7B2C, 0x91E6, 0x7B33, 0xE297, 0x7B35, 0xE29B,
+	0x7B36, 0xE29D, 0x7B39, 0x8DF9, 0x7B45, 0xE2A4, 0x7B46, 0x954D,
+	0x7B48, 0x94A4, 0x7B49, 0x9399, 0x7B4B, 0x8BD8, 0x7B4C, 0xE2A3,
+	0x7B4D, 0xE2A1, 0x7B4F, 0x94B3, 0x7B50, 0xE29E, 0x7B51, 0x927D,
+	0x7B52, 0x939B, 0x7B54, 0x939A, 0x7B56, 0x8DF4, 0x7B5D, 0xE2B6,
+	0x7B65, 0xE2A6, 0x7B67, 0xE2A8, 0x7B6C, 0xE2AB, 0x7B6E, 0xE2AC,
+	0x7B70, 0xE2A9, 0x7B71, 0xE2AA, 0x7B74, 0xE2A7, 0x7B75, 0xE2A5,
+	0x7B7A, 0xE29F, 0x7B86, 0x95CD, 0x7B87, 0x89D3, 0x7B8B, 0xE2B3,
+	0x7B8D, 0xE2B0, 0x7B8F, 0xE2B5, 0x7B92, 0xE2B4, 0x7B94, 0x9493,
+	0x7B95, 0x96A5, 0x7B97, 0x8E5A, 0x7B98, 0xE2AE, 0x7B99, 0xE2B7,
+	0x7B9A, 0xE2B2, 0x7B9C, 0xE2B1, 0x7B9D, 0xE2AD, 0x7B9E, 0xFB88,
+	0x7B9F, 0xE2AF, 0x7BA1, 0x8AC7, 0x7BAA, 0x925C, 0x7BAD, 0x90FB,
+	0x7BB1, 0x94A0, 0x7BB4, 0xE2BC, 0x7BB8, 0x94A2, 0x7BC0, 0x90DF,
+	0x7BC1, 0xE2B9, 0x7BC4, 0x94CD, 0x7BC6, 0xE2BD, 0x7BC7, 0x95D1,
+	0x7BC9, 0x927A, 0x7BCB, 0xE2B8, 0x7BCC, 0xE2BA, 0x7BCF, 0xE2BB,
+	0x7BDD, 0xE2BE, 0x7BE0, 0x8EC2, 0x7BE4, 0x93C4, 0x7BE5, 0xE2C3,
+	0x7BE6, 0xE2C2, 0x7BE9, 0xE2BF, 0x7BED, 0x9855, 0x7BF3, 0xE2C8,
+	0x7BF6, 0xE2CC, 0x7BF7, 0xE2C9, 0x7C00, 0xE2C5, 0x7C07, 0xE2C6,
+	0x7C0D, 0xE2CB, 0x7C11, 0xE2C0, 0x7C12, 0x99D3, 0x7C13, 0xE2C7,
+	0x7C14, 0xE2C1, 0x7C17, 0xE2CA, 0x7C1F, 0xE2D0, 0x7C21, 0x8AC8,
+	0x7C23, 0xE2CD, 0x7C27, 0xE2CE, 0x7C2A, 0xE2CF, 0x7C2B, 0xE2D2,
+	0x7C37, 0xE2D1, 0x7C38, 0x94F4, 0x7C3D, 0xE2D3, 0x7C3E, 0x97FA,
+	0x7C3F, 0x95EB, 0x7C40, 0xE2D8, 0x7C43, 0xE2D5, 0x7C4C, 0xE2D4,
+	0x7C4D, 0x90D0, 0x7C4F, 0xE2D7, 0x7C50, 0xE2D9, 0x7C54, 0xE2D6,
+	0x7C56, 0xE2DD, 0x7C58, 0xE2DA, 0x7C5F, 0xE2DB, 0x7C60, 0xE2C4,
+	0x7C64, 0xE2DC, 0x7C65, 0xE2DE, 0x7C6C, 0xE2DF, 0x7C73, 0x95C4,
+	0x7C75, 0xE2E0, 0x7C7E, 0x96E0, 0x7C81, 0x8BCC, 0x7C82, 0x8C48,
+	0x7C83, 0xE2E1, 0x7C89, 0x95B2, 0x7C8B, 0x9088, 0x7C8D, 0x96AE,
+	0x7C90, 0xE2E2, 0x7C92, 0x97B1, 0x7C95, 0x9494, 0x7C97, 0x9165,
+	0x7C98, 0x9453, 0x7C9B, 0x8F6C, 0x7C9F, 0x88BE, 0x7CA1, 0xE2E7,
+	0x7CA2, 0xE2E5, 0x7CA4, 0xE2E3, 0x7CA5, 0x8A9F, 0x7CA7, 0x8FCF,
+	0x7CA8, 0xE2E8, 0x7CAB, 0xE2E6, 0x7CAD, 0xE2E4, 0x7CAE, 0xE2EC,
+	0x7CB1, 0xE2EB, 0x7CB2, 0xE2EA, 0x7CB3, 0xE2E9, 0x7CB9, 0xE2ED,
+	0x7CBD, 0xE2EE, 0x7CBE, 0x90B8, 0x7CC0, 0xE2EF, 0x7CC2, 0xE2F1,
+	0x7CC5, 0xE2F0, 0x7CCA, 0x8CD0, 0x7CCE, 0x9157, 0x7CD2, 0xE2F3,
+	0x7CD6, 0x939C, 0x7CD8, 0xE2F2, 0x7CDC, 0xE2F4, 0x7CDE, 0x95B3,
+	0x7CDF, 0x918C, 0x7CE0, 0x8D66, 0x7CE2, 0xE2F5, 0x7CE7, 0x97C6,
+	0x7CEF, 0xE2F7, 0x7CF2, 0xE2F8, 0x7CF4, 0xE2F9, 0x7CF6, 0xE2FA,
+	0x7CF8, 0x8E85, 0x7CFA, 0xE2FB, 0x7CFB, 0x8C6E, 0x7CFE, 0x8B8A,
+	0x7D00, 0x8B49, 0x7D02, 0xE340, 0x7D04, 0x96F1, 0x7D05, 0x8D67,
+	0x7D06, 0xE2FC, 0x7D0A, 0xE343, 0x7D0B, 0x96E4, 0x7D0D, 0x945B,
+	0x7D10, 0x9552, 0x7D14, 0x8F83, 0x7D15, 0xE342, 0x7D17, 0x8ED1,
+	0x7D18, 0x8D68, 0x7D19, 0x8E86, 0x7D1A, 0x8B89, 0x7D1B, 0x95B4,
+	0x7D1C, 0xE341, 0x7D20, 0x9166, 0x7D21, 0x9661, 0x7D22, 0x8DF5,
+	0x7D2B, 0x8E87, 0x7D2C, 0x92DB, 0x7D2E, 0xE346, 0x7D2F, 0x97DD,
+	0x7D30, 0x8DD7, 0x7D32, 0xE347, 0x7D33, 0x9061, 0x7D35, 0xE349,
+	0x7D39, 0x8FD0, 0x7D3A, 0x8DAE, 0x7D3F, 0xE348, 0x7D42, 0x8F49,
+	0x7D43, 0x8CBC, 0x7D44, 0x9167, 0x7D45, 0xE344, 0x7D46, 0xE34A,
+	0x7D48, 0xFB8A, 0x7D4B, 0xE345, 0x7D4C, 0x8C6F, 0x7D4E, 0xE34D,
+	0x7D4F, 0xE351, 0x7D50, 0x8C8B, 0x7D56, 0xE34C, 0x7D5B, 0xE355,
+	0x7D5C, 0xFB8B, 0x7D5E, 0x8D69, 0x7D61, 0x978D, 0x7D62, 0x88BA,
+	0x7D63, 0xE352, 0x7D66, 0x8B8B, 0x7D68, 0xE34F, 0x7D6E, 0xE350,
+	0x7D71, 0x939D, 0x7D72, 0xE34E, 0x7D73, 0xE34B, 0x7D75, 0x8A47,
+	0x7D76, 0x90E2, 0x7D79, 0x8CA6, 0x7D7D, 0xE357, 0x7D89, 0xE354,
+	0x7D8F, 0xE356, 0x7D93, 0xE353, 0x7D99, 0x8C70, 0x7D9A, 0x91B1,
+	0x7D9B, 0xE358, 0x7D9C, 0x918E, 0x7D9F, 0xE365, 0x7DA0, 0xFB8D,
+	0x7DA2, 0xE361, 0x7DA3, 0xE35B, 0x7DAB, 0xE35F, 0x7DAC, 0x8EF8,
+	0x7DAD, 0x88DB, 0x7DAE, 0xE35A, 0x7DAF, 0xE362, 0x7DB0, 0xE366,
+	0x7DB1, 0x8D6A, 0x7DB2, 0x96D4, 0x7DB4, 0x92D4, 0x7DB5, 0xE35C,
+	0x7DB7, 0xFB8C, 0x7DB8, 0xE364, 0x7DBA, 0xE359, 0x7DBB, 0x925D,
+	0x7DBD, 0xE35E, 0x7DBE, 0x88BB, 0x7DBF, 0x96C8, 0x7DC7, 0xE35D,
+	0x7DCA, 0x8BD9, 0x7DCB, 0x94EA, 0x7DCF, 0x918D, 0x7DD1, 0x97CE,
+	0x7DD2, 0x8F8F, 0x7DD5, 0xE38E, 0x7DD6, 0xFB8E, 0x7DD8, 0xE367,
+	0x7DDA, 0x90FC, 0x7DDC, 0xE363, 0x7DDD, 0xE368, 0x7DDE, 0xE36A,
+	0x7DE0, 0x92F7, 0x7DE1, 0xE36D, 0x7DE4, 0xE369, 0x7DE8, 0x95D2,
+	0x7DE9, 0x8AC9, 0x7DEC, 0x96C9, 0x7DEF, 0x88DC, 0x7DF2, 0xE36C,
+	0x7DF4, 0x97FB, 0x7DFB, 0xE36B, 0x7E01, 0x898F, 0x7E04, 0x93EA,
+	0x7E05, 0xE36E, 0x7E09, 0xE375, 0x7E0A, 0xE36F, 0x7E0B, 0xE376,
+	0x7E12, 0xE372, 0x7E1B, 0x949B, 0x7E1E, 0x8EC8, 0x7E1F, 0xE374,
+	0x7E21, 0xE371, 0x7E22, 0xE377, 0x7E23, 0xE370, 0x7E26, 0x8F63,
+	0x7E2B, 0x9644, 0x7E2E, 0x8F6B, 0x7E31, 0xE373, 0x7E32, 0xE380,
+	0x7E35, 0xE37B, 0x7E37, 0xE37E, 0x7E39, 0xE37C, 0x7E3A, 0xE381,
+	0x7E3B, 0xE37A, 0x7E3D, 0xE360, 0x7E3E, 0x90D1, 0x7E41, 0x94C9,
+	0x7E43, 0xE37D, 0x7E46, 0xE378, 0x7E4A, 0x9140, 0x7E4B, 0x8C71,
+	0x7E4D, 0x8F4A, 0x7E52, 0xFB8F, 0x7E54, 0x9044, 0x7E55, 0x9155,
+	0x7E56, 0xE384, 0x7E59, 0xE386, 0x7E5A, 0xE387, 0x7E5D, 0xE383,
+	0x7E5E, 0xE385, 0x7E66, 0xE379, 0x7E67, 0xE382, 0x7E69, 0xE38A,
+	0x7E6A, 0xE389, 0x7E6D, 0x969A, 0x7E70, 0x8C4A, 0x7E79, 0xE388,
+	0x7E7B, 0xE38C, 0x7E7C, 0xE38B, 0x7E7D, 0xE38F, 0x7E7F, 0xE391,
+	0x7E82, 0x8E5B, 0x7E83, 0xE38D, 0x7E88, 0xE392, 0x7E89, 0xE393,
+	0x7E8A, 0xFA5C, 0x7E8C, 0xE394, 0x7E8E, 0xE39A, 0x7E8F, 0x935A,
+	0x7E90, 0xE396, 0x7E92, 0xE395, 0x7E93, 0xE397, 0x7E94, 0xE398,
+	0x7E96, 0xE399, 0x7E9B, 0xE39B, 0x7E9C, 0xE39C, 0x7F36, 0x8ACA,
+	0x7F38, 0xE39D, 0x7F3A, 0xE39E, 0x7F45, 0xE39F, 0x7F47, 0xFB90,
+	0x7F4C, 0xE3A0, 0x7F4D, 0xE3A1, 0x7F4E, 0xE3A2, 0x7F50, 0xE3A3,
+	0x7F51, 0xE3A4, 0x7F54, 0xE3A6, 0x7F55, 0xE3A5, 0x7F58, 0xE3A7,
+	0x7F5F, 0xE3A8, 0x7F60, 0xE3A9, 0x7F67, 0xE3AC, 0x7F68, 0xE3AA,
+	0x7F69, 0xE3AB, 0x7F6A, 0x8DDF, 0x7F6B, 0x8C72, 0x7F6E, 0x9275,
+	0x7F70, 0x94B1, 0x7F72, 0x8F90, 0x7F75, 0x946C, 0x7F77, 0x94EB,
+	0x7F78, 0xE3AD, 0x7F79, 0x9CEB, 0x7F82, 0xE3AE, 0x7F83, 0xE3B0,
+	0x7F85, 0x9785, 0x7F86, 0xE3AF, 0x7F87, 0xE3B2, 0x7F88, 0xE3B1,
+	0x7F8A, 0x9772, 0x7F8C, 0xE3B3, 0x7F8E, 0x94FC, 0x7F94, 0xE3B4,
+	0x7F9A, 0xE3B7, 0x7F9D, 0xE3B6, 0x7F9E, 0xE3B5, 0x7FA1, 0xFB91,
+	0x7FA3, 0xE3B8, 0x7FA4, 0x8C51, 0x7FA8, 0x9141, 0x7FA9, 0x8B60,
+	0x7FAE, 0xE3BC, 0x7FAF, 0xE3B9, 0x7FB2, 0xE3BA, 0x7FB6, 0xE3BD,
+	0x7FB8, 0xE3BE, 0x7FB9, 0xE3BB, 0x7FBD, 0x8948, 0x7FC1, 0x89A5,
+	0x7FC5, 0xE3C0, 0x7FC6, 0xE3C1, 0x7FCA, 0xE3C2, 0x7FCC, 0x9782,
+	0x7FD2, 0x8F4B, 0x7FD4, 0xE3C4, 0x7FD5, 0xE3C3, 0x7FE0, 0x9089,
+	0x7FE1, 0xE3C5, 0x7FE6, 0xE3C6, 0x7FE9, 0xE3C7, 0x7FEB, 0x8AE3,
+	0x7FF0, 0x8ACB, 0x7FF3, 0xE3C8, 0x7FF9, 0xE3C9, 0x7FFB, 0x967C,
+	0x7FFC, 0x9783, 0x8000, 0x9773, 0x8001, 0x9856, 0x8003, 0x8D6C,
+	0x8004, 0xE3CC, 0x8005, 0x8ED2, 0x8006, 0xE3CB, 0x800B, 0xE3CD,
+	0x800C, 0x8EA7, 0x8010, 0x91CF, 0x8012, 0xE3CE, 0x8015, 0x8D6B,
+	0x8017, 0x96D5, 0x8018, 0xE3CF, 0x8019, 0xE3D0, 0x801C, 0xE3D1,
+	0x8021, 0xE3D2, 0x8028, 0xE3D3, 0x8033, 0x8EA8, 0x8036, 0x96EB,
+	0x803B, 0xE3D5, 0x803D, 0x925E, 0x803F, 0xE3D4, 0x8046, 0xE3D7,
+	0x804A, 0xE3D6, 0x8052, 0xE3D8, 0x8056, 0x90B9, 0x8058, 0xE3D9,
+	0x805A, 0xE3DA, 0x805E, 0x95B7, 0x805F, 0xE3DB, 0x8061, 0x918F,
+	0x8062, 0xE3DC, 0x8068, 0xE3DD, 0x806F, 0x97FC, 0x8070, 0xE3E0,
+	0x8072, 0xE3DF, 0x8073, 0xE3DE, 0x8074, 0x92AE, 0x8076, 0xE3E1,
+	0x8077, 0x9045, 0x8079, 0xE3E2, 0x807D, 0xE3E3, 0x807E, 0x9857,
+	0x807F, 0xE3E4, 0x8084, 0xE3E5, 0x8085, 0xE3E7, 0x8086, 0xE3E6,
+	0x8087, 0x94A3, 0x8089, 0x93F7, 0x808B, 0x985D, 0x808C, 0x94A7,
+	0x8093, 0xE3E9, 0x8096, 0x8FD1, 0x8098, 0x9549, 0x809A, 0xE3EA,
+	0x809B, 0xE3E8, 0x809D, 0x8ACC, 0x80A1, 0x8CD2, 0x80A2, 0x8E88,
+	0x80A5, 0x94EC, 0x80A9, 0x8CA8, 0x80AA, 0x9662, 0x80AC, 0xE3ED,
+	0x80AD, 0xE3EB, 0x80AF, 0x8D6D, 0x80B1, 0x8D6E, 0x80B2, 0x88E7,
+	0x80B4, 0x8DE6, 0x80BA, 0x9478, 0x80C3, 0x88DD, 0x80C4, 0xE3F2,
+	0x80C6, 0x925F, 0x80CC, 0x9477, 0x80CE, 0x91D9, 0x80D6, 0xE3F4,
+	0x80D9, 0xE3F0, 0x80DA, 0xE3F3, 0x80DB, 0xE3EE, 0x80DD, 0xE3F1,
+	0x80DE, 0x9645, 0x80E1, 0x8CD3, 0x80E4, 0x88FB, 0x80E5, 0xE3EF,
+	0x80EF, 0xE3F6, 0x80F1, 0xE3F7, 0x80F4, 0x93B7, 0x80F8, 0x8BB9,
+	0x80FC, 0xE445, 0x80FD, 0x945C, 0x8102, 0x8E89, 0x8105, 0x8BBA,
+	0x8106, 0x90C6, 0x8107, 0x9865, 0x8108, 0x96AC, 0x8109, 0xE3F5,
+	0x810A, 0x90D2, 0x811A, 0x8B72, 0x811B, 0xE3F8, 0x8123, 0xE3FA,
+	0x8129, 0xE3F9, 0x812F, 0xE3FB, 0x8131, 0x9245, 0x8133, 0x945D,
+	0x8139, 0x92AF, 0x813E, 0xE442, 0x8146, 0xE441, 0x814B, 0xE3FC,
+	0x814E, 0x9074, 0x8150, 0x9585, 0x8151, 0xE444, 0x8153, 0xE443,
+	0x8154, 0x8D6F, 0x8155, 0x9872, 0x815F, 0xE454, 0x8165, 0xE448,
+	0x8166, 0xE449, 0x816B, 0x8EEE, 0x816E, 0xE447, 0x8170, 0x8D98,
+	0x8171, 0xE446, 0x8174, 0xE44A, 0x8178, 0x92B0, 0x8179, 0x95A0,
+	0x817A, 0x9142, 0x817F, 0x91DA, 0x8180, 0xE44E, 0x8182, 0xE44F,
+	0x8183, 0xE44B, 0x8188, 0xE44C, 0x818A, 0xE44D, 0x818F, 0x8D70,
+	0x8193, 0xE455, 0x8195, 0xE451, 0x819A, 0x9586, 0x819C, 0x968C,
+	0x819D, 0x9547, 0x81A0, 0xE450, 0x81A3, 0xE453, 0x81A4, 0xE452,
+	0x81A8, 0x9663, 0x81A9, 0xE456, 0x81B0, 0xE457, 0x81B3, 0x9156,
+	0x81B5, 0xE458, 0x81B8, 0xE45A, 0x81BA, 0xE45E, 0x81BD, 0xE45B,
+	0x81BE, 0xE459, 0x81BF, 0x945E, 0x81C0, 0xE45C, 0x81C2, 0xE45D,
+	0x81C6, 0x89B0, 0x81C8, 0xE464, 0x81C9, 0xE45F, 0x81CD, 0xE460,
+	0x81D1, 0xE461, 0x81D3, 0x919F, 0x81D8, 0xE463, 0x81D9, 0xE462,
+	0x81DA, 0xE465, 0x81DF, 0xE466, 0x81E0, 0xE467, 0x81E3, 0x9062,
+	0x81E5, 0x89E7, 0x81E7, 0xE468, 0x81E8, 0x97D5, 0x81EA, 0x8EA9,
+	0x81ED, 0x8F4C, 0x81F3, 0x8E8A, 0x81F4, 0x9276, 0x81FA, 0xE469,
+	0x81FB, 0xE46A, 0x81FC, 0x8950, 0x81FE, 0xE46B, 0x8201, 0xE46C,
+	0x8202, 0xE46D, 0x8205, 0xE46E, 0x8207, 0xE46F, 0x8208, 0x8BBB,
+	0x8209, 0x9DA8, 0x820A, 0xE470, 0x820C, 0x90E3, 0x820D, 0xE471,
+	0x820E, 0x8EC9, 0x8210, 0xE472, 0x8212, 0x98AE, 0x8216, 0xE473,
+	0x8217, 0x95DC, 0x8218, 0x8ADA, 0x821B, 0x9143, 0x821C, 0x8F77,
+	0x821E, 0x9591, 0x821F, 0x8F4D, 0x8229, 0xE474, 0x822A, 0x8D71,
+	0x822B, 0xE475, 0x822C, 0x94CA, 0x822E, 0xE484, 0x8233, 0xE477,
+	0x8235, 0x91C7, 0x8236, 0x9495, 0x8237, 0x8CBD, 0x8238, 0xE476,
+	0x8239, 0x9144, 0x8240, 0xE478, 0x8247, 0x92F8, 0x8258, 0xE47A,
+	0x8259, 0xE479, 0x825A, 0xE47C, 0x825D, 0xE47B, 0x825F, 0xE47D,
+	0x8262, 0xE480, 0x8264, 0xE47E, 0x8266, 0x8ACD, 0x8268, 0xE481,
+	0x826A, 0xE482, 0x826B, 0xE483, 0x826E, 0x8DAF, 0x826F, 0x97C7,
+	0x8271, 0xE485, 0x8272, 0x9046, 0x8276, 0x8990, 0x8277, 0xE486,
+	0x8278, 0xE487, 0x827E, 0xE488, 0x828B, 0x88F0, 0x828D, 0xE489,
+	0x8292, 0xE48A, 0x8299, 0x9587, 0x829D, 0x8EC5, 0x829F, 0xE48C,
+	0x82A5, 0x8A48, 0x82A6, 0x88B0, 0x82AB, 0xE48B, 0x82AC, 0xE48E,
+	0x82AD, 0x946D, 0x82AF, 0x9063, 0x82B1, 0x89D4, 0x82B3, 0x9646,
+	0x82B8, 0x8C7C, 0x82B9, 0x8BDA, 0x82BB, 0xE48D, 0x82BD, 0x89E8,
+	0x82C5, 0x8AA1, 0x82D1, 0x8991, 0x82D2, 0xE492, 0x82D3, 0x97E8,
+	0x82D4, 0x91DB, 0x82D7, 0x9563, 0x82D9, 0xE49E, 0x82DB, 0x89D5,
+	0x82DC, 0xE49C, 0x82DE, 0xE49A, 0x82DF, 0xE491, 0x82E1, 0xE48F,
+	0x82E3, 0xE490, 0x82E5, 0x8EE1, 0x82E6, 0x8BEA, 0x82E7, 0x9297,
+	0x82EB, 0x93CF, 0x82F1, 0x8970, 0x82F3, 0xE494, 0x82F4, 0xE493,
+	0x82F9, 0xE499, 0x82FA, 0xE495, 0x82FB, 0xE498, 0x8301, 0xFB93,
+	0x8302, 0x96CE, 0x8303, 0xE497, 0x8304, 0x89D6, 0x8305, 0x8A9D,
+	0x8306, 0xE49B, 0x8309, 0xE49D, 0x830E, 0x8C73, 0x8316, 0xE4A1,
+	0x8317, 0xE4AA, 0x8318, 0xE4AB, 0x831C, 0x88A9, 0x8323, 0xE4B2,
+	0x8328, 0x88EF, 0x832B, 0xE4A9, 0x832F, 0xE4A8, 0x8331, 0xE4A3,
+	0x8332, 0xE4A2, 0x8334, 0xE4A0, 0x8335, 0xE49F, 0x8336, 0x9283,
+	0x8338, 0x91F9, 0x8339, 0xE4A5, 0x8340, 0xE4A4, 0x8345, 0xE4A7,
+	0x8349, 0x9190, 0x834A, 0x8C74, 0x834F, 0x8960, 0x8350, 0xE4A6,
+	0x8352, 0x8D72, 0x8358, 0x9191, 0x8362, 0xFB94, 0x8373, 0xE4B8,
+	0x8375, 0xE4B9, 0x8377, 0x89D7, 0x837B, 0x89AC, 0x837C, 0xE4B6,
+	0x837F, 0xFB95, 0x8385, 0xE4AC, 0x8387, 0xE4B4, 0x8389, 0xE4BB,
+	0x838A, 0xE4B5, 0x838E, 0xE4B3, 0x8393, 0xE496, 0x8396, 0xE4B1,
+	0x839A, 0xE4AD, 0x839E, 0x8ACE, 0x839F, 0xE4AF, 0x83A0, 0xE4BA,
+	0x83A2, 0xE4B0, 0x83A8, 0xE4BC, 0x83AA, 0xE4AE, 0x83AB, 0x949C,
+	0x83B1, 0x9789, 0x83B5, 0xE4B7, 0x83BD, 0xE4CD, 0x83C1, 0xE4C5,
+	0x83C5, 0x909B, 0x83C7, 0xFB96, 0x83CA, 0x8B65, 0x83CC, 0x8BDB,
+	0x83CE, 0xE4C0, 0x83D3, 0x89D9, 0x83D6, 0x8FD2, 0x83D8, 0xE4C3,
+	0x83DC, 0x8DD8, 0x83DF, 0x9370, 0x83E0, 0xE4C8, 0x83E9, 0x95EC,
+	0x83EB, 0xE4BF, 0x83EF, 0x89D8, 0x83F0, 0x8CD4, 0x83F1, 0x9548,
+	0x83F2, 0xE4C9, 0x83F4, 0xE4BD, 0x83F6, 0xFB97, 0x83F7, 0xE4C6,
+	0x83FB, 0xE4D0, 0x83FD, 0xE4C1, 0x8403, 0xE4C2, 0x8404, 0x93B8,
+	0x8407, 0xE4C7, 0x840B, 0xE4C4, 0x840C, 0x9647, 0x840D, 0xE4CA,
+	0x840E, 0x88DE, 0x8413, 0xE4BE, 0x8420, 0xE4CC, 0x8422, 0xE4CB,
+	0x8429, 0x948B, 0x842A, 0xE4D2, 0x842C, 0xE4DD, 0x8431, 0x8A9E,
+	0x8435, 0xE4E0, 0x8438, 0xE4CE, 0x843C, 0xE4D3, 0x843D, 0x978E,
+	0x8446, 0xE4DC, 0x8448, 0xFB98, 0x8449, 0x9774, 0x844E, 0x97A8,
+	0x8457, 0x9298, 0x845B, 0x8A8B, 0x8461, 0x9592, 0x8462, 0xE4E2,
+	0x8463, 0x939F, 0x8466, 0x88AF, 0x8469, 0xE4DB, 0x846B, 0xE4D7,
+	0x846C, 0x9192, 0x846D, 0xE4D1, 0x846E, 0xE4D9, 0x846F, 0xE4DE,
+	0x8471, 0x944B, 0x8475, 0x88A8, 0x8477, 0xE4D6, 0x8479, 0xE4DF,
+	0x847A, 0x9598, 0x8482, 0xE4DA, 0x8484, 0xE4D5, 0x848B, 0x8FD3,
+	0x8490, 0x8F4E, 0x8494, 0x8EAA, 0x8499, 0x96D6, 0x849C, 0x9566,
+	0x849F, 0xE4E5, 0x84A1, 0xE4EE, 0x84AD, 0xE4D8, 0x84B2, 0x8A97,
+	0x84B4, 0xFB99, 0x84B8, 0x8FF6, 0x84B9, 0xE4E3, 0x84BB, 0xE4E8,
+	0x84BC, 0x9193, 0x84BF, 0xE4E4, 0x84C1, 0xE4EB, 0x84C4, 0x927E,
+	0x84C6, 0xE4EC, 0x84C9, 0x9775, 0x84CA, 0xE4E1, 0x84CB, 0x8A57,
+	0x84CD, 0xE4E7, 0x84D0, 0xE4EA, 0x84D1, 0x96AA, 0x84D6, 0xE4ED,
+	0x84D9, 0xE4E6, 0x84DA, 0xE4E9, 0x84DC, 0xFA60, 0x84EC, 0x9648,
+	0x84EE, 0x9840, 0x84F4, 0xE4F1, 0x84FC, 0xE4F8, 0x84FF, 0xE4F0,
+	0x8500, 0x8EC1, 0x8506, 0xE4CF, 0x8511, 0x95CC, 0x8513, 0x96A0,
+	0x8514, 0xE4F7, 0x8515, 0xE4F6, 0x8517, 0xE4F2, 0x8518, 0xE4F3,
+	0x851A, 0x8955, 0x851F, 0xE4F5, 0x8521, 0xE4EF, 0x8526, 0x92D3,
+	0x852C, 0xE4F4, 0x852D, 0x88FC, 0x8535, 0x91A0, 0x853D, 0x95C1,
+	0x8540, 0xE4F9, 0x8541, 0xE540, 0x8543, 0x94D7, 0x8548, 0xE4FC,
+	0x8549, 0x8FD4, 0x854A, 0x8EC7, 0x854B, 0xE542, 0x854E, 0x8BBC,
+	0x8553, 0xFB9A, 0x8555, 0xE543, 0x8557, 0x9599, 0x8558, 0xE4FB,
+	0x8559, 0xFB9B, 0x855A, 0xE4D4, 0x8563, 0xE4FA, 0x8568, 0x986E,
+	0x8569, 0x93A0, 0x856A, 0x9593, 0x856B, 0xFB9C, 0x856D, 0xE54A,
+	0x8577, 0xE550, 0x857E, 0xE551, 0x8580, 0xE544, 0x8584, 0x9496,
+	0x8587, 0xE54E, 0x8588, 0xE546, 0x858A, 0xE548, 0x8590, 0xE552,
+	0x8591, 0xE547, 0x8594, 0xE54B, 0x8597, 0x8992, 0x8599, 0x93E3,
+	0x859B, 0xE54C, 0x859C, 0xE54F, 0x85A4, 0xE545, 0x85A6, 0x9145,
+	0x85A8, 0xE549, 0x85A9, 0x8E46, 0x85AA, 0x9064, 0x85AB, 0x8C4F,
+	0x85AC, 0x96F2, 0x85AE, 0x96F7, 0x85AF, 0x8F92, 0x85B0, 0xFB9E,
+	0x85B9, 0xE556, 0x85BA, 0xE554, 0x85C1, 0x986D, 0x85C9, 0xE553,
+	0x85CD, 0x9795, 0x85CF, 0xE555, 0x85D0, 0xE557, 0x85D5, 0xE558,
+	0x85DC, 0xE55B, 0x85DD, 0xE559, 0x85E4, 0x93A1, 0x85E5, 0xE55A,
+	0x85E9, 0x94CB, 0x85EA, 0xE54D, 0x85F7, 0x8F93, 0x85F9, 0xE55C,
+	0x85FA, 0xE561, 0x85FB, 0x9194, 0x85FE, 0xE560, 0x8602, 0xE541,
+	0x8606, 0xE562, 0x8607, 0x9168, 0x860A, 0xE55D, 0x860B, 0xE55F,
+	0x8613, 0xE55E, 0x8616, 0x9F50, 0x8617, 0x9F41, 0x861A, 0xE564,
+	0x8622, 0xE563, 0x862D, 0x9796, 0x862F, 0xE1BA, 0x8630, 0xE565,
+	0x863F, 0xE566, 0x864D, 0xE567, 0x864E, 0x8CD5, 0x8650, 0x8B73,
+	0x8654, 0xE569, 0x8655, 0x997C, 0x865A, 0x8B95, 0x865C, 0x97B8,
+	0x865E, 0x8BF1, 0x865F, 0xE56A, 0x8667, 0xE56B, 0x866B, 0x928E,
+	0x8671, 0xE56C, 0x8679, 0x93F8, 0x867B, 0x88B8, 0x868A, 0x89E1,
+	0x868B, 0xE571, 0x868C, 0xE572, 0x8693, 0xE56D, 0x8695, 0x8E5C,
+	0x86A3, 0xE56E, 0x86A4, 0x9461, 0x86A9, 0xE56F, 0x86AA, 0xE570,
+	0x86AB, 0xE57A, 0x86AF, 0xE574, 0x86B0, 0xE577, 0x86B6, 0xE573,
+	0x86C4, 0xE575, 0x86C6, 0xE576, 0x86C7, 0x8ED6, 0x86C9, 0xE578,
+	0x86CB, 0x9260, 0x86CD, 0x8C75, 0x86CE, 0x8A61, 0x86D4, 0xE57B,
+	0x86D9, 0x8A5E, 0x86DB, 0xE581, 0x86DE, 0xE57C, 0x86DF, 0xE580,
+	0x86E4, 0x94B8, 0x86E9, 0xE57D, 0x86EC, 0xE57E, 0x86ED, 0x9567,
+	0x86EE, 0x94D8, 0x86EF, 0xE582, 0x86F8, 0x91FB, 0x86F9, 0xE58C,
+	0x86FB, 0xE588, 0x86FE, 0x89E9, 0x8700, 0xE586, 0x8702, 0x9649,
+	0x8703, 0xE587, 0x8706, 0xE584, 0x8708, 0xE585, 0x8709, 0xE58A,
+	0x870A, 0xE58D, 0x870D, 0xE58B, 0x8711, 0xE589, 0x8712, 0xE583,
+	0x8718, 0x9277, 0x871A, 0xE594, 0x871C, 0x96A8, 0x8725, 0xE592,
+	0x8729, 0xE593, 0x8734, 0xE58E, 0x8737, 0xE590, 0x873B, 0xE591,
+	0x873F, 0xE58F, 0x8749, 0x90E4, 0x874B, 0x9858, 0x874C, 0xE598,
+	0x874E, 0xE599, 0x8753, 0xE59F, 0x8755, 0x9049, 0x8757, 0xE59B,
+	0x8759, 0xE59E, 0x875F, 0xE596, 0x8760, 0xE595, 0x8763, 0xE5A0,
+	0x8766, 0x89DA, 0x8768, 0xE59C, 0x876A, 0xE5A1, 0x876E, 0xE59D,
+	0x8774, 0xE59A, 0x8776, 0x92B1, 0x8778, 0xE597, 0x877F, 0x9488,
+	0x8782, 0xE5A5, 0x878D, 0x975A, 0x879F, 0xE5A4, 0x87A2, 0xE5A3,
+	0x87AB, 0xE5AC, 0x87AF, 0xE5A6, 0x87B3, 0xE5AE, 0x87BA, 0x9786,
+	0x87BB, 0xE5B1, 0x87BD, 0xE5A8, 0x87C0, 0xE5A9, 0x87C4, 0xE5AD,
+	0x87C6, 0xE5B0, 0x87C7, 0xE5AF, 0x87CB, 0xE5A7, 0x87D0, 0xE5AA,
+	0x87D2, 0xE5BB, 0x87E0, 0xE5B4, 0x87EF, 0xE5B2, 0x87F2, 0xE5B3,
+	0x87F6, 0xE5B8, 0x87F7, 0xE5B9, 0x87F9, 0x8A49, 0x87FB, 0x8B61,
+	0x87FE, 0xE5B7, 0x8805, 0xE5A2, 0x8807, 0xFBA1, 0x880D, 0xE5B6,
+	0x880E, 0xE5BA, 0x880F, 0xE5B5, 0x8811, 0xE5BC, 0x8815, 0xE5BE,
+	0x8816, 0xE5BD, 0x8821, 0xE5C0, 0x8822, 0xE5BF, 0x8823, 0xE579,
+	0x8827, 0xE5C4, 0x8831, 0xE5C1, 0x8836, 0xE5C2, 0x8839, 0xE5C3,
+	0x883B, 0xE5C5, 0x8840, 0x8C8C, 0x8842, 0xE5C7, 0x8844, 0xE5C6,
+	0x8846, 0x8F4F, 0x884C, 0x8D73, 0x884D, 0x9FA5, 0x8852, 0xE5C8,
+	0x8853, 0x8F70, 0x8857, 0x8A58, 0x8859, 0xE5C9, 0x885B, 0x8971,
+	0x885D, 0x8FD5, 0x885E, 0xE5CA, 0x8861, 0x8D74, 0x8862, 0xE5CB,
+	0x8863, 0x88DF, 0x8868, 0x955C, 0x886B, 0xE5CC, 0x8870, 0x908A,
+	0x8872, 0xE5D3, 0x8875, 0xE5D0, 0x8877, 0x928F, 0x887D, 0xE5D1,
+	0x887E, 0xE5CE, 0x887F, 0x8BDC, 0x8881, 0xE5CD, 0x8882, 0xE5D4,
+	0x8888, 0x8C55, 0x888B, 0x91DC, 0x888D, 0xE5DA, 0x8892, 0xE5D6,
+	0x8896, 0x91B3, 0x8897, 0xE5D5, 0x8899, 0xE5D8, 0x889E, 0xE5CF,
+	0x88A2, 0xE5D9, 0x88A4, 0xE5DB, 0x88AB, 0x94ED, 0x88AE, 0xE5D7,
+	0x88B0, 0xE5DC, 0x88B1, 0xE5DE, 0x88B4, 0x8CD1, 0x88B5, 0xE5D2,
+	0x88B7, 0x88BF, 0x88BF, 0xE5DD, 0x88C1, 0x8DD9, 0x88C2, 0x97F4,
+	0x88C3, 0xE5DF, 0x88C4, 0xE5E0, 0x88C5, 0x9195, 0x88CF, 0x97A0,
+	0x88D4, 0xE5E1, 0x88D5, 0x9754, 0x88D8, 0xE5E2, 0x88D9, 0xE5E3,
+	0x88DC, 0x95E2, 0x88DD, 0xE5E4, 0x88DF, 0x8DBE, 0x88E1, 0x97A1,
+	0x88E8, 0xE5E9, 0x88F2, 0xE5EA, 0x88F3, 0x8FD6, 0x88F4, 0xE5E8,
+	0x88F5, 0xFBA2, 0x88F8, 0x9787, 0x88F9, 0xE5E5, 0x88FC, 0xE5E7,
+	0x88FD, 0x90BB, 0x88FE, 0x909E, 0x8902, 0xE5E6, 0x8904, 0xE5EB,
+	0x8907, 0x95A1, 0x890A, 0xE5ED, 0x890C, 0xE5EC, 0x8910, 0x8A8C,
+	0x8912, 0x964A, 0x8913, 0xE5EE, 0x891C, 0xFA5D, 0x891D, 0xE5FA,
+	0x891E, 0xE5F0, 0x8925, 0xE5F1, 0x892A, 0xE5F2, 0x892B, 0xE5F3,
+	0x8936, 0xE5F7, 0x8938, 0xE5F8, 0x893B, 0xE5F6, 0x8941, 0xE5F4,
+	0x8943, 0xE5EF, 0x8944, 0xE5F5, 0x894C, 0xE5F9, 0x894D, 0xE8B5,
+	0x8956, 0x89A6, 0x895E, 0xE5FC, 0x895F, 0x8BDD, 0x8960, 0xE5FB,
+	0x8964, 0xE641, 0x8966, 0xE640, 0x896A, 0xE643, 0x896D, 0xE642,
+	0x896F, 0xE644, 0x8972, 0x8F50, 0x8974, 0xE645, 0x8977, 0xE646,
+	0x897E, 0xE647, 0x897F, 0x90BC, 0x8981, 0x9776, 0x8983, 0xE648,
+	0x8986, 0x95A2, 0x8987, 0x9465, 0x8988, 0xE649, 0x898A, 0xE64A,
+	0x898B, 0x8CA9, 0x898F, 0x8B4B, 0x8993, 0xE64B, 0x8996, 0x8E8B,
+	0x8997, 0x9460, 0x8998, 0xE64C, 0x899A, 0x8A6F, 0x89A1, 0xE64D,
+	0x89A6, 0xE64F, 0x89A7, 0x9797, 0x89A9, 0xE64E, 0x89AA, 0x9065,
+	0x89AC, 0xE650, 0x89AF, 0xE651, 0x89B2, 0xE652, 0x89B3, 0x8ACF,
+	0x89BA, 0xE653, 0x89BD, 0xE654, 0x89BF, 0xE655, 0x89C0, 0xE656,
+	0x89D2, 0x8A70, 0x89DA, 0xE657, 0x89DC, 0xE658, 0x89DD, 0xE659,
+	0x89E3, 0x89F0, 0x89E6, 0x9047, 0x89E7, 0xE65A, 0x89F4, 0xE65B,
+	0x89F8, 0xE65C, 0x8A00, 0x8CBE, 0x8A02, 0x92F9, 0x8A03, 0xE65D,
+	0x8A08, 0x8C76, 0x8A0A, 0x9075, 0x8A0C, 0xE660, 0x8A0E, 0x93A2,
+	0x8A10, 0xE65F, 0x8A12, 0xFBA3, 0x8A13, 0x8C50, 0x8A16, 0xE65E,
+	0x8A17, 0x91F5, 0x8A18, 0x8B4C, 0x8A1B, 0xE661, 0x8A1D, 0xE662,
+	0x8A1F, 0x8FD7, 0x8A23, 0x8C8D, 0x8A25, 0xE663, 0x8A2A, 0x964B,
+	0x8A2D, 0x90DD, 0x8A31, 0x8B96, 0x8A33, 0x96F3, 0x8A34, 0x9169,
+	0x8A36, 0xE664, 0x8A37, 0xFBA4, 0x8A3A, 0x9066, 0x8A3B, 0x9290,
+	0x8A3C, 0x8FD8, 0x8A41, 0xE665, 0x8A46, 0xE668, 0x8A48, 0xE669,
+	0x8A50, 0x8DBC, 0x8A51, 0x91C0, 0x8A52, 0xE667, 0x8A54, 0x8FD9,
+	0x8A55, 0x955D, 0x8A5B, 0xE666, 0x8A5E, 0x8E8C, 0x8A60, 0x8972,
+	0x8A62, 0xE66D, 0x8A63, 0x8C77, 0x8A66, 0x8E8E, 0x8A69, 0x8E8D,
+	0x8A6B, 0x986C, 0x8A6C, 0xE66C, 0x8A6D, 0xE66B, 0x8A6E, 0x9146,
+	0x8A70, 0x8B6C, 0x8A71, 0x9862, 0x8A72, 0x8A59, 0x8A73, 0x8FDA,
+	0x8A79, 0xFBA5, 0x8A7C, 0xE66A, 0x8A82, 0xE66F, 0x8A84, 0xE670,
+	0x8A85, 0xE66E, 0x8A87, 0x8CD6, 0x8A89, 0x975F, 0x8A8C, 0x8E8F,
+	0x8A8D, 0x9446, 0x8A91, 0xE673, 0x8A93, 0x90BE, 0x8A95, 0x9261,
+	0x8A98, 0x9755, 0x8A9A, 0xE676, 0x8A9E, 0x8CEA, 0x8AA0, 0x90BD,
+	0x8AA1, 0xE672, 0x8AA3, 0xE677, 0x8AA4, 0x8CEB, 0x8AA5, 0xE674,
+	0x8AA6, 0xE675, 0x8AA7, 0xFBA6, 0x8AA8, 0xE671, 0x8AAC, 0x90E0,
+	0x8AAD, 0x93C7, 0x8AB0, 0x924E, 0x8AB2, 0x89DB, 0x8AB9, 0x94EE,
+	0x8ABC, 0x8B62, 0x8ABE, 0xFBA7, 0x8ABF, 0x92B2, 0x8AC2, 0xE67A,
+	0x8AC4, 0xE678, 0x8AC7, 0x926B, 0x8ACB, 0x90BF, 0x8ACC, 0x8AD0,
+	0x8ACD, 0xE679, 0x8ACF, 0x907A, 0x8AD2, 0x97C8, 0x8AD6, 0x985F,
+	0x8ADA, 0xE67B, 0x8ADB, 0xE687, 0x8ADC, 0x92B3, 0x8ADE, 0xE686,
+	0x8ADF, 0xFBA8, 0x8AE0, 0xE683, 0x8AE1, 0xE68B, 0x8AE2, 0xE684,
+	0x8AE4, 0xE680, 0x8AE6, 0x92FA, 0x8AE7, 0xE67E, 0x8AEB, 0xE67C,
+	0x8AED, 0x9740, 0x8AEE, 0x8E90, 0x8AF1, 0xE681, 0x8AF3, 0xE67D,
+	0x8AF6, 0xFBAA, 0x8AF7, 0xE685, 0x8AF8, 0x8F94, 0x8AFA, 0x8CBF,
+	0x8AFE, 0x91F8, 0x8B00, 0x9664, 0x8B01, 0x8979, 0x8B02, 0x88E0,
+	0x8B04, 0x93A3, 0x8B07, 0xE689, 0x8B0C, 0xE688, 0x8B0E, 0x93E4,
+	0x8B10, 0xE68D, 0x8B14, 0xE682, 0x8B16, 0xE68C, 0x8B17, 0xE68E,
+	0x8B19, 0x8CAA, 0x8B1A, 0xE68A, 0x8B1B, 0x8D75, 0x8B1D, 0x8ED3,
+	0x8B20, 0xE68F, 0x8B21, 0x9777, 0x8B26, 0xE692, 0x8B28, 0xE695,
+	0x8B2B, 0xE693, 0x8B2C, 0x9554, 0x8B33, 0xE690, 0x8B39, 0x8BDE,
+	0x8B3E, 0xE694, 0x8B41, 0xE696, 0x8B49, 0xE69A, 0x8B4C, 0xE697,
+	0x8B4E, 0xE699, 0x8B4F, 0xE698, 0x8B53, 0xFBAB, 0x8B56, 0xE69B,
+	0x8B58, 0x8EAF, 0x8B5A, 0xE69D, 0x8B5B, 0xE69C, 0x8B5C, 0x9588,
+	0x8B5F, 0xE69F, 0x8B66, 0x8C78, 0x8B6B, 0xE69E, 0x8B6C, 0xE6A0,
+	0x8B6F, 0xE6A1, 0x8B70, 0x8B63, 0x8B71, 0xE3BF, 0x8B72, 0x8FF7,
+	0x8B74, 0xE6A2, 0x8B77, 0x8CEC, 0x8B7D, 0xE6A3, 0x8B7F, 0xFBAC,
+	0x8B80, 0xE6A4, 0x8B83, 0x8E5D, 0x8B8A, 0x9DCC, 0x8B8C, 0xE6A5,
+	0x8B8E, 0xE6A6, 0x8B90, 0x8F51, 0x8B92, 0xE6A7, 0x8B93, 0xE6A8,
+	0x8B96, 0xE6A9, 0x8B99, 0xE6AA, 0x8B9A, 0xE6AB, 0x8C37, 0x924A,
+	0x8C3A, 0xE6AC, 0x8C3F, 0xE6AE, 0x8C41, 0xE6AD, 0x8C46, 0x93A4,
+	0x8C48, 0xE6AF, 0x8C4A, 0x964C, 0x8C4C, 0xE6B0, 0x8C4E, 0xE6B1,
+	0x8C50, 0xE6B2, 0x8C55, 0xE6B3, 0x8C5A, 0x93D8, 0x8C61, 0x8FDB,
+	0x8C62, 0xE6B4, 0x8C6A, 0x8D8B, 0x8C6B, 0x98AC, 0x8C6C, 0xE6B5,
+	0x8C78, 0xE6B6, 0x8C79, 0x955E, 0x8C7A, 0xE6B7, 0x8C7C, 0xE6BF,
+	0x8C82, 0xE6B8, 0x8C85, 0xE6BA, 0x8C89, 0xE6B9, 0x8C8A, 0xE6BB,
+	0x8C8C, 0x9665, 0x8C8D, 0xE6BC, 0x8C8E, 0xE6BD, 0x8C94, 0xE6BE,
+	0x8C98, 0xE6C0, 0x8C9D, 0x8A4C, 0x8C9E, 0x92E5, 0x8CA0, 0x9589,
+	0x8CA1, 0x8DE0, 0x8CA2, 0x8D76, 0x8CA7, 0x956E, 0x8CA8, 0x89DD,
+	0x8CA9, 0x94CC, 0x8CAA, 0xE6C3, 0x8CAB, 0x8AD1, 0x8CAC, 0x90D3,
+	0x8CAD, 0xE6C2, 0x8CAE, 0xE6C7, 0x8CAF, 0x9299, 0x8CB0, 0x96E1,
+	0x8CB2, 0xE6C5, 0x8CB3, 0xE6C6, 0x8CB4, 0x8B4D, 0x8CB6, 0xE6C8,
+	0x8CB7, 0x9483, 0x8CB8, 0x91DD, 0x8CBB, 0x94EF, 0x8CBC, 0x935C,
+	0x8CBD, 0xE6C4, 0x8CBF, 0x9666, 0x8CC0, 0x89EA, 0x8CC1, 0xE6CA,
+	0x8CC2, 0x9847, 0x8CC3, 0x92C0, 0x8CC4, 0x9864, 0x8CC7, 0x8E91,
+	0x8CC8, 0xE6C9, 0x8CCA, 0x91AF, 0x8CCD, 0xE6DA, 0x8CCE, 0x9147,
+	0x8CD1, 0x93F6, 0x8CD3, 0x956F, 0x8CDA, 0xE6CD, 0x8CDB, 0x8E5E,
+	0x8CDC, 0x8E92, 0x8CDE, 0x8FDC, 0x8CE0, 0x9485, 0x8CE2, 0x8CAB,
+	0x8CE3, 0xE6CC, 0x8CE4, 0xE6CB, 0x8CE6, 0x958A, 0x8CEA, 0x8EBF,
+	0x8CED, 0x9371, 0x8CF0, 0xFBAD, 0x8CF4, 0xFBAE, 0x8CFA, 0xE6CF,
+	0x8CFB, 0xE6D0, 0x8CFC, 0x8D77, 0x8CFD, 0xE6CE, 0x8D04, 0xE6D1,
+	0x8D05, 0xE6D2, 0x8D07, 0xE6D4, 0x8D08, 0x91A1, 0x8D0A, 0xE6D3,
+	0x8D0B, 0x8AE4, 0x8D0D, 0xE6D6, 0x8D0F, 0xE6D5, 0x8D10, 0xE6D7,
+	0x8D12, 0xFBAF, 0x8D13, 0xE6D9, 0x8D14, 0xE6DB, 0x8D16, 0xE6DC,
+	0x8D64, 0x90D4, 0x8D66, 0x8ECD, 0x8D67, 0xE6DD, 0x8D6B, 0x8A71,
+	0x8D6D, 0xE6DE, 0x8D70, 0x9196, 0x8D71, 0xE6DF, 0x8D73, 0xE6E0,
+	0x8D74, 0x958B, 0x8D76, 0xFBB0, 0x8D77, 0x8B4E, 0x8D81, 0xE6E1,
+	0x8D85, 0x92B4, 0x8D8A, 0x897A, 0x8D99, 0xE6E2, 0x8DA3, 0x8EEF,
+	0x8DA8, 0x9096, 0x8DB3, 0x91AB, 0x8DBA, 0xE6E5, 0x8DBE, 0xE6E4,
+	0x8DC2, 0xE6E3, 0x8DCB, 0xE6EB, 0x8DCC, 0xE6E9, 0x8DCF, 0xE6E6,
+	0x8DD6, 0xE6E8, 0x8DDA, 0xE6E7, 0x8DDB, 0xE6EA, 0x8DDD, 0x8B97,
+	0x8DDF, 0xE6EE, 0x8DE1, 0x90D5, 0x8DE3, 0xE6EF, 0x8DE8, 0x8CD7,
+	0x8DEA, 0xE6EC, 0x8DEB, 0xE6ED, 0x8DEF, 0x9848, 0x8DF3, 0x92B5,
+	0x8DF5, 0x9148, 0x8DFC, 0xE6F0, 0x8DFF, 0xE6F3, 0x8E08, 0xE6F1,
+	0x8E09, 0xE6F2, 0x8E0A, 0x9778, 0x8E0F, 0x93A5, 0x8E10, 0xE6F6,
+	0x8E1D, 0xE6F4, 0x8E1E, 0xE6F5, 0x8E1F, 0xE6F7, 0x8E2A, 0xE748,
+	0x8E30, 0xE6FA, 0x8E34, 0xE6FB, 0x8E35, 0xE6F9, 0x8E42, 0xE6F8,
+	0x8E44, 0x92FB, 0x8E47, 0xE740, 0x8E48, 0xE744, 0x8E49, 0xE741,
+	0x8E4A, 0xE6FC, 0x8E4C, 0xE742, 0x8E50, 0xE743, 0x8E55, 0xE74A,
+	0x8E59, 0xE745, 0x8E5F, 0x90D6, 0x8E60, 0xE747, 0x8E63, 0xE749,
+	0x8E64, 0xE746, 0x8E72, 0xE74C, 0x8E74, 0x8F52, 0x8E76, 0xE74B,
+	0x8E7C, 0xE74D, 0x8E81, 0xE74E, 0x8E84, 0xE751, 0x8E85, 0xE750,
+	0x8E87, 0xE74F, 0x8E8A, 0xE753, 0x8E8B, 0xE752, 0x8E8D, 0x96F4,
+	0x8E91, 0xE755, 0x8E93, 0xE754, 0x8E94, 0xE756, 0x8E99, 0xE757,
+	0x8EA1, 0xE759, 0x8EAA, 0xE758, 0x8EAB, 0x9067, 0x8EAC, 0xE75A,
+	0x8EAF, 0x8BEB, 0x8EB0, 0xE75B, 0x8EB1, 0xE75D, 0x8EBE, 0xE75E,
+	0x8EC5, 0xE75F, 0x8EC6, 0xE75C, 0x8EC8, 0xE760, 0x8ECA, 0x8ED4,
+	0x8ECB, 0xE761, 0x8ECC, 0x8B4F, 0x8ECD, 0x8C52, 0x8ECF, 0xFBB2,
+	0x8ED2, 0x8CAC, 0x8EDB, 0xE762, 0x8EDF, 0x93EE, 0x8EE2, 0x935D,
+	0x8EE3, 0xE763, 0x8EEB, 0xE766, 0x8EF8, 0x8EB2, 0x8EFB, 0xE765,
+	0x8EFC, 0xE764, 0x8EFD, 0x8C79, 0x8EFE, 0xE767, 0x8F03, 0x8A72,
+	0x8F05, 0xE769, 0x8F09, 0x8DDA, 0x8F0A, 0xE768, 0x8F0C, 0xE771,
+	0x8F12, 0xE76B, 0x8F13, 0xE76D, 0x8F14, 0x95E3, 0x8F15, 0xE76A,
+	0x8F19, 0xE76C, 0x8F1B, 0xE770, 0x8F1C, 0xE76E, 0x8F1D, 0x8B50,
+	0x8F1F, 0xE76F, 0x8F26, 0xE772, 0x8F29, 0x9479, 0x8F2A, 0x97D6,
+	0x8F2F, 0x8F53, 0x8F33, 0xE773, 0x8F38, 0x9741, 0x8F39, 0xE775,
+	0x8F3B, 0xE774, 0x8F3E, 0xE778, 0x8F3F, 0x9760, 0x8F42, 0xE777,
+	0x8F44, 0x8A8D, 0x8F45, 0xE776, 0x8F46, 0xE77B, 0x8F49, 0xE77A,
+	0x8F4C, 0xE779, 0x8F4D, 0x9351, 0x8F4E, 0xE77C, 0x8F57, 0xE77D,
+	0x8F5C, 0xE77E, 0x8F5F, 0x8D8C, 0x8F61, 0x8C44, 0x8F62, 0xE780,
+	0x8F63, 0xE781, 0x8F64, 0xE782, 0x8F9B, 0x9068, 0x8F9C, 0xE783,
+	0x8F9E, 0x8EAB, 0x8F9F, 0xE784, 0x8FA3, 0xE785, 0x8FA7, 0x999F,
+	0x8FA8, 0x999E, 0x8FAD, 0xE786, 0x8FAE, 0xE390, 0x8FAF, 0xE787,
+	0x8FB0, 0x9243, 0x8FB1, 0x904A, 0x8FB2, 0x945F, 0x8FB7, 0xE788,
+	0x8FBA, 0x95D3, 0x8FBB, 0x92D2, 0x8FBC, 0x8D9E, 0x8FBF, 0x9248,
+	0x8FC2, 0x8949, 0x8FC4, 0x9698, 0x8FC5, 0x9076, 0x8FCE, 0x8C7D,
+	0x8FD1, 0x8BDF, 0x8FD4, 0x95D4, 0x8FDA, 0xE789, 0x8FE2, 0xE78B,
+	0x8FE5, 0xE78A, 0x8FE6, 0x89DE, 0x8FE9, 0x93F4, 0x8FEA, 0xE78C,
+	0x8FEB, 0x9497, 0x8FED, 0x9352, 0x8FEF, 0xE78D, 0x8FF0, 0x8F71,
+	0x8FF4, 0xE78F, 0x8FF7, 0x96C0, 0x8FF8, 0xE79E, 0x8FF9, 0xE791,
+	0x8FFA, 0xE792, 0x8FFD, 0x92C7, 0x9000, 0x91DE, 0x9001, 0x9197,
+	0x9003, 0x93A6, 0x9005, 0xE790, 0x9006, 0x8B74, 0x900B, 0xE799,
+	0x900D, 0xE796, 0x900E, 0xE7A3, 0x900F, 0x93A7, 0x9010, 0x9280,
+	0x9011, 0xE793, 0x9013, 0x92FC, 0x9014, 0x9372, 0x9015, 0xE794,
+	0x9016, 0xE798, 0x9017, 0x9080, 0x9019, 0x9487, 0x901A, 0x92CA,
+	0x901D, 0x90C0, 0x901E, 0xE797, 0x901F, 0x91AC, 0x9020, 0x91A2,
+	0x9021, 0xE795, 0x9022, 0x88A7, 0x9023, 0x9841, 0x9027, 0xE79A,
+	0x902E, 0x91DF, 0x9031, 0x8F54, 0x9032, 0x9069, 0x9035, 0xE79C,
+	0x9036, 0xE79B, 0x9038, 0x88ED, 0x9039, 0xE79D, 0x903C, 0x954E,
+	0x903E, 0xE7A5, 0x9041, 0x93D9, 0x9042, 0x908B, 0x9045, 0x9278,
+	0x9047, 0x8BF6, 0x9049, 0xE7A4, 0x904A, 0x9756, 0x904B, 0x895E,
+	0x904D, 0x95D5, 0x904E, 0x89DF, 0x904F, 0xE79F, 0x9050, 0xE7A0,
+	0x9051, 0xE7A1, 0x9052, 0xE7A2, 0x9053, 0x93B9, 0x9054, 0x9242,
+	0x9055, 0x88E1, 0x9056, 0xE7A6, 0x9058, 0xE7A7, 0x9059, 0xEAA1,
+	0x905C, 0x91BB, 0x905E, 0xE7A8, 0x9060, 0x8993, 0x9061, 0x916B,
+	0x9063, 0x8CAD, 0x9065, 0x9779, 0x9067, 0xFBB5, 0x9068, 0xE7A9,
+	0x9069, 0x934B, 0x906D, 0x9198, 0x906E, 0x8ED5, 0x906F, 0xE7AA,
+	0x9072, 0xE7AD, 0x9075, 0x8F85, 0x9076, 0xE7AB, 0x9077, 0x914A,
+	0x9078, 0x9149, 0x907A, 0x88E2, 0x907C, 0x97C9, 0x907D, 0xE7AF,
+	0x907F, 0x94F0, 0x9080, 0xE7B1, 0x9081, 0xE7B0, 0x9082, 0xE7AE,
+	0x9083, 0xE284, 0x9084, 0x8AD2, 0x9087, 0xE78E, 0x9089, 0xE7B3,
+	0x908A, 0xE7B2, 0x908F, 0xE7B4, 0x9091, 0x9757, 0x90A3, 0x93DF,
+	0x90A6, 0x964D, 0x90A8, 0xE7B5, 0x90AA, 0x8ED7, 0x90AF, 0xE7B6,
+	0x90B1, 0xE7B7, 0x90B5, 0xE7B8, 0x90B8, 0x9340, 0x90C1, 0x88E8,
+	0x90CA, 0x8D78, 0x90CE, 0x9859, 0x90DB, 0xE7BC, 0x90DE, 0xFBB6,
+	0x90E1, 0x8C53, 0x90E2, 0xE7B9, 0x90E4, 0xE7BA, 0x90E8, 0x9594,
+	0x90ED, 0x8A73, 0x90F5, 0x9758, 0x90F7, 0x8BBD, 0x90FD, 0x9373,
+	0x9102, 0xE7BD, 0x9112, 0xE7BE, 0x9115, 0xFBB8, 0x9119, 0xE7BF,
+	0x9127, 0xFBB9, 0x912D, 0x9341, 0x9130, 0xE7C1, 0x9132, 0xE7C0,
+	0x9149, 0x93D1, 0x914A, 0xE7C2, 0x914B, 0x8F55, 0x914C, 0x8EDE,
+	0x914D, 0x947A, 0x914E, 0x9291, 0x9152, 0x8EF0, 0x9154, 0x908C,
+	0x9156, 0xE7C3, 0x9158, 0xE7C4, 0x9162, 0x907C, 0x9163, 0xE7C5,
+	0x9165, 0xE7C6, 0x9169, 0xE7C7, 0x916A, 0x978F, 0x916C, 0x8F56,
+	0x9172, 0xE7C9, 0x9173, 0xE7C8, 0x9175, 0x8D79, 0x9177, 0x8D93,
+	0x9178, 0x8E5F, 0x9182, 0xE7CC, 0x9187, 0x8F86, 0x9189, 0xE7CB,
+	0x918B, 0xE7CA, 0x918D, 0x91E7, 0x9190, 0x8CED, 0x9192, 0x90C1,
+	0x9197, 0x94AE, 0x919C, 0x8F58, 0x91A2, 0xE7CD, 0x91A4, 0x8FDD,
+	0x91AA, 0xE7D0, 0x91AB, 0xE7CE, 0x91AF, 0xE7CF, 0x91B4, 0xE7D2,
+	0x91B5, 0xE7D1, 0x91B8, 0x8FF8, 0x91BA, 0xE7D3, 0x91C0, 0xE7D4,
+	0x91C1, 0xE7D5, 0x91C6, 0x94CE, 0x91C7, 0x8DD1, 0x91C8, 0x8EDF,
+	0x91C9, 0xE7D6, 0x91CB, 0xE7D7, 0x91CC, 0x97A2, 0x91CD, 0x8F64,
+	0x91CE, 0x96EC, 0x91CF, 0x97CA, 0x91D0, 0xE7D8, 0x91D1, 0x8BE0,
+	0x91D6, 0xE7D9, 0x91D7, 0xFBBB, 0x91D8, 0x9342, 0x91DA, 0xFBBA,
+	0x91DB, 0xE7DC, 0x91DC, 0x8A98, 0x91DD, 0x906A, 0x91DE, 0xFBBC,
+	0x91DF, 0xE7DA, 0x91E1, 0xE7DB, 0x91E3, 0x92DE, 0x91E4, 0xFBBF,
+	0x91E5, 0xFBC0, 0x91E6, 0x9674, 0x91E7, 0x8BFA, 0x91ED, 0xFBBD,
+	0x91EE, 0xFBBE, 0x91F5, 0xE7DE, 0x91F6, 0xE7DF, 0x91FC, 0xE7DD,
+	0x91FF, 0xE7E1, 0x9206, 0xFBC1, 0x920A, 0xFBC3, 0x920D, 0x93DD,
+	0x920E, 0x8A62, 0x9210, 0xFBC2, 0x9211, 0xE7E5, 0x9214, 0xE7E2,
+	0x9215, 0xE7E4, 0x921E, 0xE7E0, 0x9229, 0xE86E, 0x922C, 0xE7E3,
+	0x9234, 0x97E9, 0x9237, 0x8CD8, 0x9239, 0xFBCA, 0x923A, 0xFBC4,
+	0x923C, 0xFBC6, 0x923F, 0xE7ED, 0x9240, 0xFBC5, 0x9244, 0x9353,
+	0x9245, 0xE7E8, 0x9248, 0xE7EB, 0x9249, 0xE7E9, 0x924B, 0xE7EE,
+	0x924E, 0xFBC7, 0x9250, 0xE7EF, 0x9251, 0xFBC9, 0x9257, 0xE7E7,
+	0x9259, 0xFBC8, 0x925A, 0xE7F4, 0x925B, 0x8994, 0x925E, 0xE7E6,
+	0x9262, 0x94AB, 0x9264, 0xE7EA, 0x9266, 0x8FDE, 0x9267, 0xFBCB,
+	0x9271, 0x8D7A, 0x9277, 0xFBCD, 0x9278, 0xFBCE, 0x927E, 0x9667,
+	0x9280, 0x8BE2, 0x9283, 0x8F65, 0x9285, 0x93BA, 0x9288, 0xFA5F,
+	0x9291, 0x914C, 0x9293, 0xE7F2, 0x9295, 0xE7EC, 0x9296, 0xE7F1,
+	0x9298, 0x96C1, 0x929A, 0x92B6, 0x929B, 0xE7F3, 0x929C, 0xE7F0,
+	0x92A7, 0xFBCC, 0x92AD, 0x914B, 0x92B7, 0xE7F7, 0x92B9, 0xE7F6,
+	0x92CF, 0xE7F5, 0x92D0, 0xFBD2, 0x92D2, 0x964E, 0x92D3, 0xFBD6,
+	0x92D5, 0xFBD4, 0x92D7, 0xFBD0, 0x92D9, 0xFBD1, 0x92E0, 0xFBD5,
+	0x92E4, 0x8F9B, 0x92E7, 0xFBCF, 0x92E9, 0xE7F8, 0x92EA, 0x95DD,
+	0x92ED, 0x8973, 0x92F2, 0x9565, 0x92F3, 0x9292, 0x92F8, 0x8B98,
+	0x92F9, 0xFA65, 0x92FA, 0xE7FA, 0x92FB, 0xFBD9, 0x92FC, 0x8D7C,
+	0x92FF, 0xFBDC, 0x9302, 0xFBDE, 0x9306, 0x8E4B, 0x930F, 0xE7F9,
+	0x9310, 0x908D, 0x9318, 0x908E, 0x9319, 0xE840, 0x931A, 0xE842,
+	0x931D, 0xFBDD, 0x931E, 0xFBDB, 0x9320, 0x8FF9, 0x9321, 0xFBD8,
+	0x9322, 0xE841, 0x9323, 0xE843, 0x9325, 0xFBD7, 0x9326, 0x8BD1,
+	0x9328, 0x9564, 0x932B, 0x8EE0, 0x932C, 0x9842, 0x932E, 0xE7FC,
+	0x932F, 0x8DF6, 0x9332, 0x985E, 0x9335, 0xE845, 0x933A, 0xE844,
+	0x933B, 0xE846, 0x9344, 0xE7FB, 0x9348, 0xFA5E, 0x934B, 0x93E7,
+	0x934D, 0x9374, 0x9354, 0x92D5, 0x9356, 0xE84B, 0x9357, 0xFBE0,
+	0x935B, 0x9262, 0x935C, 0xE847, 0x9360, 0xE848, 0x936C, 0x8C4C,
+	0x936E, 0xE84A, 0x9370, 0xFBDF, 0x9375, 0x8CAE, 0x937C, 0xE849,
+	0x937E, 0x8FDF, 0x938C, 0x8A99, 0x9394, 0xE84F, 0x9396, 0x8DBD,
+	0x9397, 0x9199, 0x939A, 0x92C8, 0x93A4, 0xFBE1, 0x93A7, 0x8A5A,
+	0x93AC, 0xE84D, 0x93AD, 0xE84E, 0x93AE, 0x92C1, 0x93B0, 0xE84C,
+	0x93B9, 0xE850, 0x93C3, 0xE856, 0x93C6, 0xFBE2, 0x93C8, 0xE859,
+	0x93D0, 0xE858, 0x93D1, 0x934C, 0x93D6, 0xE851, 0x93D7, 0xE852,
+	0x93D8, 0xE855, 0x93DD, 0xE857, 0x93DE, 0xFBE3, 0x93E1, 0x8BBE,
+	0x93E4, 0xE85A, 0x93E5, 0xE854, 0x93E8, 0xE853, 0x93F8, 0xFBE4,
+	0x9403, 0xE85E, 0x9407, 0xE85F, 0x9410, 0xE860, 0x9413, 0xE85D,
+	0x9414, 0xE85C, 0x9418, 0x8FE0, 0x9419, 0x93A8, 0x941A, 0xE85B,
+	0x9421, 0xE864, 0x942B, 0xE862, 0x9431, 0xFBE5, 0x9435, 0xE863,
+	0x9436, 0xE861, 0x9438, 0x91F6, 0x943A, 0xE865, 0x9441, 0xE866,
+	0x9444, 0xE868, 0x9445, 0xFBE6, 0x9448, 0xFBE7, 0x9451, 0x8AD3,
+	0x9452, 0xE867, 0x9453, 0x96F8, 0x945A, 0xE873, 0x945B, 0xE869,
+	0x945E, 0xE86C, 0x9460, 0xE86A, 0x9462, 0xE86B, 0x946A, 0xE86D,
+	0x9470, 0xE86F, 0x9475, 0xE870, 0x9477, 0xE871, 0x947C, 0xE874,
+	0x947D, 0xE872, 0x947E, 0xE875, 0x947F, 0xE877, 0x9481, 0xE876,
+	0x9577, 0x92B7, 0x9580, 0x96E5, 0x9582, 0xE878, 0x9583, 0x914D,
+	0x9587, 0xE879, 0x9589, 0x95C2, 0x958A, 0xE87A, 0x958B, 0x8A4A,
+	0x958F, 0x895B, 0x9591, 0x8AD5, 0x9592, 0xFBE8, 0x9593, 0x8AD4,
+	0x9594, 0xE87B, 0x9596, 0xE87C, 0x9598, 0xE87D, 0x9599, 0xE87E,
+	0x95A0, 0xE880, 0x95A2, 0x8AD6, 0x95A3, 0x8A74, 0x95A4, 0x8D7D,
+	0x95A5, 0x94B4, 0x95A7, 0xE882, 0x95A8, 0xE881, 0x95AD, 0xE883,
+	0x95B2, 0x897B, 0x95B9, 0xE886, 0x95BB, 0xE885, 0x95BC, 0xE884,
+	0x95BE, 0xE887, 0x95C3, 0xE88A, 0x95C7, 0x88C5, 0x95CA, 0xE888,
+	0x95CC, 0xE88C, 0x95CD, 0xE88B, 0x95D4, 0xE88E, 0x95D5, 0xE88D,
+	0x95D6, 0xE88F, 0x95D8, 0x93AC, 0x95DC, 0xE890, 0x95E1, 0xE891,
+	0x95E2, 0xE893, 0x95E5, 0xE892, 0x961C, 0x958C, 0x9621, 0xE894,
+	0x9628, 0xE895, 0x962A, 0x8DE3, 0x962E, 0xE896, 0x962F, 0xE897,
+	0x9632, 0x9668, 0x963B, 0x916A, 0x963F, 0x88A2, 0x9640, 0x91C9,
+	0x9642, 0xE898, 0x9644, 0x958D, 0x964B, 0xE89B, 0x964C, 0xE899,
+	0x964D, 0x8D7E, 0x964F, 0xE89A, 0x9650, 0x8CC0, 0x965B, 0x95C3,
+	0x965C, 0xE89D, 0x965D, 0xE89F, 0x965E, 0xE89E, 0x965F, 0xE8A0,
+	0x9662, 0x8940, 0x9663, 0x9077, 0x9664, 0x8F9C, 0x9665, 0x8AD7,
+	0x9666, 0xE8A1, 0x966A, 0x9486, 0x966C, 0xE8A3, 0x9670, 0x8941,
+	0x9672, 0xE8A2, 0x9673, 0x92C2, 0x9675, 0x97CB, 0x9676, 0x93A9,
+	0x9677, 0xE89C, 0x9678, 0x97A4, 0x967A, 0x8CAF, 0x967D, 0x977A,
+	0x9685, 0x8BF7, 0x9686, 0x97B2, 0x9688, 0x8C47, 0x968A, 0x91E0,
+	0x968B, 0xE440, 0x968D, 0xE8A4, 0x968E, 0x8A4B, 0x968F, 0x908F,
+	0x9694, 0x8A75, 0x9695, 0xE8A6, 0x9697, 0xE8A7, 0x9698, 0xE8A5,
+	0x9699, 0x8C84, 0x969B, 0x8DDB, 0x969C, 0x8FE1, 0x969D, 0xFBEB,
+	0x96A0, 0x8942, 0x96A3, 0x97D7, 0x96A7, 0xE8A9, 0x96A8, 0xE7AC,
+	0x96AA, 0xE8A8, 0x96AF, 0xFBEC, 0x96B0, 0xE8AC, 0x96B1, 0xE8AA,
+	0x96B2, 0xE8AB, 0x96B4, 0xE8AD, 0x96B6, 0xE8AE, 0x96B7, 0x97EA,
+	0x96B8, 0xE8AF, 0x96B9, 0xE8B0, 0x96BB, 0x90C7, 0x96BC, 0x94B9,
+	0x96C0, 0x909D, 0x96C1, 0x8AE5, 0x96C4, 0x9759, 0x96C5, 0x89EB,
+	0x96C6, 0x8F57, 0x96C7, 0x8CD9, 0x96C9, 0xE8B3, 0x96CB, 0xE8B2,
+	0x96CC, 0x8E93, 0x96CD, 0xE8B4, 0x96CE, 0xE8B1, 0x96D1, 0x8E47,
+	0x96D5, 0xE8B8, 0x96D6, 0xE5AB, 0x96D9, 0x99D4, 0x96DB, 0x9097,
+	0x96DC, 0xE8B6, 0x96E2, 0x97A3, 0x96E3, 0x93EF, 0x96E8, 0x894A,
+	0x96EA, 0x90E1, 0x96EB, 0x8EB4, 0x96F0, 0x95B5, 0x96F2, 0x895F,
+	0x96F6, 0x97EB, 0x96F7, 0x978B, 0x96F9, 0xE8B9, 0x96FB, 0x9364,
+	0x9700, 0x8EF9, 0x9704, 0xE8BA, 0x9706, 0xE8BB, 0x9707, 0x906B,
+	0x9708, 0xE8BC, 0x970A, 0x97EC, 0x970D, 0xE8B7, 0x970E, 0xE8BE,
+	0x970F, 0xE8C0, 0x9711, 0xE8BF, 0x9713, 0xE8BD, 0x9716, 0xE8C1,
+	0x9719, 0xE8C2, 0x971C, 0x919A, 0x971E, 0x89E0, 0x9724, 0xE8C3,
+	0x9727, 0x96B6, 0x972A, 0xE8C4, 0x9730, 0xE8C5, 0x9732, 0x9849,
+	0x9733, 0xFBED, 0x9738, 0x9E50, 0x9739, 0xE8C6, 0x973B, 0xFBEE,
+	0x973D, 0xE8C7, 0x973E, 0xE8C8, 0x9742, 0xE8CC, 0x9743, 0xFBEF,
+	0x9744, 0xE8C9, 0x9746, 0xE8CA, 0x9748, 0xE8CB, 0x9749, 0xE8CD,
+	0x974D, 0xFBF0, 0x974F, 0xFBF1, 0x9751, 0xFBF2, 0x9752, 0x90C2,
+	0x9755, 0xFBF3, 0x9756, 0x96F5, 0x9759, 0x90C3, 0x975C, 0xE8CE,
+	0x975E, 0x94F1, 0x9760, 0xE8CF, 0x9761, 0xEA72, 0x9762, 0x96CA,
+	0x9764, 0xE8D0, 0x9766, 0xE8D1, 0x9768, 0xE8D2, 0x9769, 0x8A76,
+	0x976B, 0xE8D4, 0x976D, 0x9078, 0x9771, 0xE8D5, 0x9774, 0x8C43,
+	0x9779, 0xE8D6, 0x977A, 0xE8DA, 0x977C, 0xE8D8, 0x9781, 0xE8D9,
+	0x9784, 0x8A93, 0x9785, 0xE8D7, 0x9786, 0xE8DB, 0x978B, 0xE8DC,
+	0x978D, 0x88C6, 0x978F, 0xE8DD, 0x9790, 0xE8DE, 0x9798, 0x8FE2,
+	0x979C, 0xE8DF, 0x97A0, 0x8B66, 0x97A3, 0xE8E2, 0x97A6, 0xE8E1,
+	0x97A8, 0xE8E0, 0x97AB, 0xE691, 0x97AD, 0x95DA, 0x97B3, 0xE8E3,
+	0x97B4, 0xE8E4, 0x97C3, 0xE8E5, 0x97C6, 0xE8E6, 0x97C8, 0xE8E7,
+	0x97CB, 0xE8E8, 0x97D3, 0x8AD8, 0x97DC, 0xE8E9, 0x97ED, 0xE8EA,
+	0x97EE, 0x9442, 0x97F2, 0xE8EC, 0x97F3, 0x89B9, 0x97F5, 0xE8EF,
+	0x97F6, 0xE8EE, 0x97FB, 0x8943, 0x97FF, 0x8BBF, 0x9801, 0x95C5,
+	0x9802, 0x92B8, 0x9803, 0x8DA0, 0x9805, 0x8D80, 0x9806, 0x8F87,
+	0x9808, 0x907B, 0x980C, 0xE8F1, 0x980F, 0xE8F0, 0x9810, 0x9761,
+	0x9811, 0x8AE6, 0x9812, 0x94D0, 0x9813, 0x93DA, 0x9817, 0x909C,
+	0x9818, 0x97CC, 0x981A, 0x8C7A, 0x9821, 0xE8F4, 0x9824, 0xE8F3,
+	0x982C, 0x966A, 0x982D, 0x93AA, 0x9834, 0x896F, 0x9837, 0xE8F5,
+	0x9838, 0xE8F2, 0x983B, 0x9570, 0x983C, 0x978A, 0x983D, 0xE8F6,
+	0x9846, 0xE8F7, 0x984B, 0xE8F9, 0x984C, 0x91E8, 0x984D, 0x8A7A,
+	0x984E, 0x8A7B, 0x984F, 0xE8F8, 0x9854, 0x8AE7, 0x9855, 0x8CB0,
+	0x9857, 0xFBF4, 0x9858, 0x8AE8, 0x985B, 0x935E, 0x985E, 0x97DE,
+	0x9865, 0xFBF5, 0x9867, 0x8CDA, 0x986B, 0xE8FA, 0x986F, 0xE8FB,
+	0x9870, 0xE8FC, 0x9871, 0xE940, 0x9873, 0xE942, 0x9874, 0xE941,
+	0x98A8, 0x9597, 0x98AA, 0xE943, 0x98AF, 0xE944, 0x98B1, 0xE945,
+	0x98B6, 0xE946, 0x98C3, 0xE948, 0x98C4, 0xE947, 0x98C6, 0xE949,
+	0x98DB, 0x94F2, 0x98DC, 0xE3CA, 0x98DF, 0x9048, 0x98E2, 0x8B51,
+	0x98E9, 0xE94A, 0x98EB, 0xE94B, 0x98ED, 0x99AA, 0x98EE, 0x9F5A,
+	0x98EF, 0x94D1, 0x98F2, 0x88F9, 0x98F4, 0x88B9, 0x98FC, 0x8E94,
+	0x98FD, 0x964F, 0x98FE, 0x8FFC, 0x9903, 0xE94C, 0x9905, 0x96DD,
+	0x9909, 0xE94D, 0x990A, 0x977B, 0x990C, 0x8961, 0x9910, 0x8E60,
+	0x9912, 0xE94E, 0x9913, 0x89EC, 0x9914, 0xE94F, 0x9918, 0xE950,
+	0x991D, 0xE952, 0x991E, 0xE953, 0x9920, 0xE955, 0x9921, 0xE951,
+	0x9924, 0xE954, 0x9927, 0xFBF8, 0x9928, 0x8AD9, 0x992C, 0xE956,
+	0x992E, 0xE957, 0x993D, 0xE958, 0x993E, 0xE959, 0x9942, 0xE95A,
+	0x9945, 0xE95C, 0x9949, 0xE95B, 0x994B, 0xE95E, 0x994C, 0xE961,
+	0x9950, 0xE95D, 0x9951, 0xE95F, 0x9952, 0xE960, 0x9955, 0xE962,
+	0x9957, 0x8BC0, 0x9996, 0x8EF1, 0x9997, 0xE963, 0x9998, 0xE964,
+	0x9999, 0x8D81, 0x999E, 0xFBFA, 0x99A5, 0xE965, 0x99A8, 0x8A5D,
+	0x99AC, 0x946E, 0x99AD, 0xE966, 0x99AE, 0xE967, 0x99B3, 0x9279,
+	0x99B4, 0x93E9, 0x99BC, 0xE968, 0x99C1, 0x949D, 0x99C4, 0x91CA,
+	0x99C5, 0x8977, 0x99C6, 0x8BEC, 0x99C8, 0x8BED, 0x99D0, 0x9293,
+	0x99D1, 0xE96D, 0x99D2, 0x8BEE, 0x99D5, 0x89ED, 0x99D8, 0xE96C,
+	0x99DB, 0xE96A, 0x99DD, 0xE96B, 0x99DF, 0xE969, 0x99E2, 0xE977,
+	0x99ED, 0xE96E, 0x99EE, 0xE96F, 0x99F1, 0xE970, 0x99F2, 0xE971,
+	0x99F8, 0xE973, 0x99FB, 0xE972, 0x99FF, 0x8F78, 0x9A01, 0xE974,
+	0x9A05, 0xE976, 0x9A0E, 0x8B52, 0x9A0F, 0xE975, 0x9A12, 0x919B,
+	0x9A13, 0x8CB1, 0x9A19, 0xE978, 0x9A28, 0x91CB, 0x9A2B, 0xE979,
+	0x9A30, 0x93AB, 0x9A37, 0xE97A, 0x9A3E, 0xE980, 0x9A40, 0xE97D,
+	0x9A42, 0xE97C, 0x9A43, 0xE97E, 0x9A45, 0xE97B, 0x9A4D, 0xE982,
+	0x9A4E, 0xFBFB, 0x9A55, 0xE981, 0x9A57, 0xE984, 0x9A5A, 0x8BC1,
+	0x9A5B, 0xE983, 0x9A5F, 0xE985, 0x9A62, 0xE986, 0x9A64, 0xE988,
+	0x9A65, 0xE987, 0x9A69, 0xE989, 0x9A6A, 0xE98B, 0x9A6B, 0xE98A,
+	0x9AA8, 0x8D9C, 0x9AAD, 0xE98C, 0x9AB0, 0xE98D, 0x9AB8, 0x8A5B,
+	0x9ABC, 0xE98E, 0x9AC0, 0xE98F, 0x9AC4, 0x9091, 0x9ACF, 0xE990,
+	0x9AD1, 0xE991, 0x9AD3, 0xE992, 0x9AD4, 0xE993, 0x9AD8, 0x8D82,
+	0x9AD9, 0xFBFC, 0x9ADC, 0xFC40, 0x9ADE, 0xE994, 0x9ADF, 0xE995,
+	0x9AE2, 0xE996, 0x9AE3, 0xE997, 0x9AE6, 0xE998, 0x9AEA, 0x94AF,
+	0x9AEB, 0xE99A, 0x9AED, 0x9545, 0x9AEE, 0xE99B, 0x9AEF, 0xE999,
+	0x9AF1, 0xE99D, 0x9AF4, 0xE99C, 0x9AF7, 0xE99E, 0x9AFB, 0xE99F,
+	0x9B06, 0xE9A0, 0x9B18, 0xE9A1, 0x9B1A, 0xE9A2, 0x9B1F, 0xE9A3,
+	0x9B22, 0xE9A4, 0x9B23, 0xE9A5, 0x9B25, 0xE9A6, 0x9B27, 0xE9A7,
+	0x9B28, 0xE9A8, 0x9B29, 0xE9A9, 0x9B2A, 0xE9AA, 0x9B2E, 0xE9AB,
+	0x9B2F, 0xE9AC, 0x9B31, 0x9F54, 0x9B32, 0xE9AD, 0x9B3B, 0xE2F6,
+	0x9B3C, 0x8B53, 0x9B41, 0x8A40, 0x9B42, 0x8DB0, 0x9B43, 0xE9AF,
+	0x9B44, 0xE9AE, 0x9B45, 0x96A3, 0x9B4D, 0xE9B1, 0x9B4E, 0xE9B2,
+	0x9B4F, 0xE9B0, 0x9B51, 0xE9B3, 0x9B54, 0x9682, 0x9B58, 0xE9B4,
+	0x9B5A, 0x8B9B, 0x9B6F, 0x9844, 0x9B72, 0xFC42, 0x9B74, 0xE9B5,
+	0x9B75, 0xFC41, 0x9B83, 0xE9B7, 0x9B8E, 0x88BC, 0x9B8F, 0xFC43,
+	0x9B91, 0xE9B8, 0x9B92, 0x95A9, 0x9B93, 0xE9B6, 0x9B96, 0xE9B9,
+	0x9B97, 0xE9BA, 0x9B9F, 0xE9BB, 0x9BA0, 0xE9BC, 0x9BA8, 0xE9BD,
+	0x9BAA, 0x968E, 0x9BAB, 0x8E4C, 0x9BAD, 0x8DF8, 0x9BAE, 0x914E,
+	0x9BB1, 0xFC44, 0x9BB4, 0xE9BE, 0x9BB9, 0xE9C1, 0x9BBB, 0xFC45,
+	0x9BC0, 0xE9BF, 0x9BC6, 0xE9C2, 0x9BC9, 0x8CEF, 0x9BCA, 0xE9C0,
+	0x9BCF, 0xE9C3, 0x9BD1, 0xE9C4, 0x9BD2, 0xE9C5, 0x9BD4, 0xE9C9,
+	0x9BD6, 0x8E49, 0x9BDB, 0x91E2, 0x9BE1, 0xE9CA, 0x9BE2, 0xE9C7,
+	0x9BE3, 0xE9C6, 0x9BE4, 0xE9C8, 0x9BE8, 0x8C7E, 0x9BF0, 0xE9CE,
+	0x9BF1, 0xE9CD, 0x9BF2, 0xE9CC, 0x9BF5, 0x88B1, 0x9C00, 0xFC46,
+	0x9C04, 0xE9D8, 0x9C06, 0xE9D4, 0x9C08, 0xE9D5, 0x9C09, 0xE9D1,
+	0x9C0A, 0xE9D7, 0x9C0C, 0xE9D3, 0x9C0D, 0x8A82, 0x9C10, 0x986B,
+	0x9C12, 0xE9D6, 0x9C13, 0xE9D2, 0x9C14, 0xE9D0, 0x9C15, 0xE9CF,
+	0x9C1B, 0xE9DA, 0x9C21, 0xE9DD, 0x9C24, 0xE9DC, 0x9C25, 0xE9DB,
+	0x9C2D, 0x9568, 0x9C2E, 0xE9D9, 0x9C2F, 0x88F1, 0x9C30, 0xE9DE,
+	0x9C32, 0xE9E0, 0x9C39, 0x8A8F, 0x9C3A, 0xE9CB, 0x9C3B, 0x8956,
+	0x9C3E, 0xE9E2, 0x9C46, 0xE9E1, 0x9C47, 0xE9DF, 0x9C48, 0x924C,
+	0x9C52, 0x9690, 0x9C57, 0x97D8, 0x9C5A, 0xE9E3, 0x9C60, 0xE9E4,
+	0x9C67, 0xE9E5, 0x9C76, 0xE9E6, 0x9C78, 0xE9E7, 0x9CE5, 0x92B9,
+	0x9CE7, 0xE9E8, 0x9CE9, 0x94B5, 0x9CEB, 0xE9ED, 0x9CEC, 0xE9E9,
+	0x9CF0, 0xE9EA, 0x9CF3, 0x9650, 0x9CF4, 0x96C2, 0x9CF6, 0x93CE,
+	0x9D03, 0xE9EE, 0x9D06, 0xE9EF, 0x9D07, 0x93BC, 0x9D08, 0xE9EC,
+	0x9D09, 0xE9EB, 0x9D0E, 0x89A8, 0x9D12, 0xE9F7, 0x9D15, 0xE9F6,
+	0x9D1B, 0x8995, 0x9D1F, 0xE9F4, 0x9D23, 0xE9F3, 0x9D26, 0xE9F1,
+	0x9D28, 0x8A9B, 0x9D2A, 0xE9F0, 0x9D2B, 0x8EB0, 0x9D2C, 0x89A7,
+	0x9D3B, 0x8D83, 0x9D3E, 0xE9FA, 0x9D3F, 0xE9F9, 0x9D41, 0xE9F8,
+	0x9D44, 0xE9F5, 0x9D46, 0xE9FB, 0x9D48, 0xE9FC, 0x9D50, 0xEA44,
+	0x9D51, 0xEA43, 0x9D59, 0xEA45, 0x9D5C, 0x894C, 0x9D5D, 0xEA40,
+	0x9D5E, 0xEA41, 0x9D60, 0x8D94, 0x9D61, 0x96B7, 0x9D64, 0xEA42,
+	0x9D6B, 0xFC48, 0x9D6C, 0x9651, 0x9D6F, 0xEA4A, 0x9D70, 0xFC47,
+	0x9D72, 0xEA46, 0x9D7A, 0xEA4B, 0x9D87, 0xEA48, 0x9D89, 0xEA47,
+	0x9D8F, 0x8C7B, 0x9D9A, 0xEA4C, 0x9DA4, 0xEA4D, 0x9DA9, 0xEA4E,
+	0x9DAB, 0xEA49, 0x9DAF, 0xE9F2, 0x9DB2, 0xEA4F, 0x9DB4, 0x92DF,
+	0x9DB8, 0xEA53, 0x9DBA, 0xEA54, 0x9DBB, 0xEA52, 0x9DC1, 0xEA51,
+	0x9DC2, 0xEA57, 0x9DC4, 0xEA50, 0x9DC6, 0xEA55, 0x9DCF, 0xEA56,
+	0x9DD3, 0xEA59, 0x9DD9, 0xEA58, 0x9DE6, 0xEA5B, 0x9DED, 0xEA5C,
+	0x9DEF, 0xEA5D, 0x9DF2, 0x9868, 0x9DF8, 0xEA5A, 0x9DF9, 0x91E9,
+	0x9DFA, 0x8DEB, 0x9DFD, 0xEA5E, 0x9E19, 0xFC4A, 0x9E1A, 0xEA5F,
+	0x9E1B, 0xEA60, 0x9E1E, 0xEA61, 0x9E75, 0xEA62, 0x9E78, 0x8CB2,
+	0x9E79, 0xEA63, 0x9E7D, 0xEA64, 0x9E7F, 0x8EAD, 0x9E81, 0xEA65,
+	0x9E88, 0xEA66, 0x9E8B, 0xEA67, 0x9E8C, 0xEA68, 0x9E91, 0xEA6B,
+	0x9E92, 0xEA69, 0x9E93, 0x985B, 0x9E95, 0xEA6A, 0x9E97, 0x97ED,
+	0x9E9D, 0xEA6C, 0x9E9F, 0x97D9, 0x9EA5, 0xEA6D, 0x9EA6, 0x949E,
+	0x9EA9, 0xEA6E, 0x9EAA, 0xEA70, 0x9EAD, 0xEA71, 0x9EB8, 0xEA6F,
+	0x9EB9, 0x8D8D, 0x9EBA, 0x96CB, 0x9EBB, 0x9683, 0x9EBC, 0x9BF5,
+	0x9EBE, 0x9F80, 0x9EBF, 0x969B, 0x9EC4, 0x89A9, 0x9ECC, 0xEA73,
+	0x9ECD, 0x8B6F, 0x9ECE, 0xEA74, 0x9ECF, 0xEA75, 0x9ED0, 0xEA76,
+	0x9ED1, 0xFC4B, 0x9ED2, 0x8D95, 0x9ED4, 0xEA77, 0x9ED8, 0xE0D2,
+	0x9ED9, 0x96D9, 0x9EDB, 0x91E1, 0x9EDC, 0xEA78, 0x9EDD, 0xEA7A,
+	0x9EDE, 0xEA79, 0x9EE0, 0xEA7B, 0x9EE5, 0xEA7C, 0x9EE8, 0xEA7D,
+	0x9EEF, 0xEA7E, 0x9EF4, 0xEA80, 0x9EF6, 0xEA81, 0x9EF7, 0xEA82,
+	0x9EF9, 0xEA83, 0x9EFB, 0xEA84, 0x9EFC, 0xEA85, 0x9EFD, 0xEA86,
+	0x9F07, 0xEA87, 0x9F08, 0xEA88, 0x9F0E, 0x9343, 0x9F13, 0x8CDB,
+	0x9F15, 0xEA8A, 0x9F20, 0x916C, 0x9F21, 0xEA8B, 0x9F2C, 0xEA8C,
+	0x9F3B, 0x9540, 0x9F3E, 0xEA8D, 0x9F4A, 0xEA8E, 0x9F4B, 0xE256,
+	0x9F4E, 0xE6D8, 0x9F4F, 0xE8EB, 0x9F52, 0xEA8F, 0x9F54, 0xEA90,
+	0x9F5F, 0xEA92, 0x9F60, 0xEA93, 0x9F61, 0xEA94, 0x9F62, 0x97EE,
+	0x9F63, 0xEA91, 0x9F66, 0xEA95, 0x9F67, 0xEA96, 0x9F6A, 0xEA98,
+	0x9F6C, 0xEA97, 0x9F72, 0xEA9A, 0x9F76, 0xEA9B, 0x9F77, 0xEA99,
+	0x9F8D, 0x97B4, 0x9F95, 0xEA9C, 0x9F9C, 0xEA9D, 0x9F9D, 0xE273,
+	0x9FA0, 0xEA9E, 0xF929, 0xFAE0, 0xF9DC, 0xFBE9, 0xFA0E, 0xFA90,
+	0xFA0F, 0xFA9B, 0xFA10, 0xFA9C, 0xFA11, 0xFAB1, 0xFA12, 0xFAD8,
+	0xFA13, 0xFAE8, 0xFA14, 0xFAEA, 0xFA15, 0xFB58, 0xFA16, 0xFB5E,
+	0xFA17, 0xFB75, 0xFA18, 0xFB7D, 0xFA19, 0xFB7E, 0xFA1A, 0xFB80,
+	0xFA1B, 0xFB82, 0xFA1C, 0xFB86, 0xFA1D, 0xFB89, 0xFA1E, 0xFB92,
+	0xFA1F, 0xFB9D, 0xFA20, 0xFB9F, 0xFA21, 0xFBA0, 0xFA22, 0xFBA9,
+	0xFA23, 0xFBB1, 0xFA24, 0xFBB3, 0xFA25, 0xFBB4, 0xFA26, 0xFBB7,
+	0xFA27, 0xFBD3, 0xFA28, 0xFBDA, 0xFA29, 0xFBEA, 0xFA2A, 0xFBF6,
+	0xFA2B, 0xFBF7, 0xFA2C, 0xFBF9, 0xFA2D, 0xFC49, 0xFF01, 0x8149,
+	0xFF02, 0xFA57, 0xFF03, 0x8194, 0xFF04, 0x8190, 0xFF05, 0x8193,
+	0xFF06, 0x8195, 0xFF07, 0xFA56, 0xFF08, 0x8169, 0xFF09, 0x816A,
+	0xFF0A, 0x8196, 0xFF0B, 0x817B, 0xFF0C, 0x8143, 0xFF0D, 0x817C,
+	0xFF0E, 0x8144, 0xFF0F, 0x815E, 0xFF10, 0x824F, 0xFF11, 0x8250,
+	0xFF12, 0x8251, 0xFF13, 0x8252, 0xFF14, 0x8253, 0xFF15, 0x8254,
+	0xFF16, 0x8255, 0xFF17, 0x8256, 0xFF18, 0x8257, 0xFF19, 0x8258,
+	0xFF1A, 0x8146, 0xFF1B, 0x8147, 0xFF1C, 0x8183, 0xFF1D, 0x8181,
+	0xFF1E, 0x8184, 0xFF1F, 0x8148, 0xFF20, 0x8197, 0xFF21, 0x8260,
+	0xFF22, 0x8261, 0xFF23, 0x8262, 0xFF24, 0x8263, 0xFF25, 0x8264,
+	0xFF26, 0x8265, 0xFF27, 0x8266, 0xFF28, 0x8267, 0xFF29, 0x8268,
+	0xFF2A, 0x8269, 0xFF2B, 0x826A, 0xFF2C, 0x826B, 0xFF2D, 0x826C,
+	0xFF2E, 0x826D, 0xFF2F, 0x826E, 0xFF30, 0x826F, 0xFF31, 0x8270,
+	0xFF32, 0x8271, 0xFF33, 0x8272, 0xFF34, 0x8273, 0xFF35, 0x8274,
+	0xFF36, 0x8275, 0xFF37, 0x8276, 0xFF38, 0x8277, 0xFF39, 0x8278,
+	0xFF3A, 0x8279, 0xFF3B, 0x816D, 0xFF3C, 0x815F, 0xFF3D, 0x816E,
+	0xFF3E, 0x814F, 0xFF3F, 0x8151, 0xFF40, 0x814D, 0xFF41, 0x8281,
+	0xFF42, 0x8282, 0xFF43, 0x8283, 0xFF44, 0x8284, 0xFF45, 0x8285,
+	0xFF46, 0x8286, 0xFF47, 0x8287, 0xFF48, 0x8288, 0xFF49, 0x8289,
+	0xFF4A, 0x828A, 0xFF4B, 0x828B, 0xFF4C, 0x828C, 0xFF4D, 0x828D,
+	0xFF4E, 0x828E, 0xFF4F, 0x828F, 0xFF50, 0x8290, 0xFF51, 0x8291,
+	0xFF52, 0x8292, 0xFF53, 0x8293, 0xFF54, 0x8294, 0xFF55, 0x8295,
+	0xFF56, 0x8296, 0xFF57, 0x8297, 0xFF58, 0x8298, 0xFF59, 0x8299,
+	0xFF5A, 0x829A, 0xFF5B, 0x816F, 0xFF5C, 0x8162, 0xFF5D, 0x8170,
+	0xFF5E, 0x8160, 0xFF61, 0x00A1, 0xFF62, 0x00A2, 0xFF63, 0x00A3,
+	0xFF64, 0x00A4, 0xFF65, 0x00A5, 0xFF66, 0x00A6, 0xFF67, 0x00A7,
+	0xFF68, 0x00A8, 0xFF69, 0x00A9, 0xFF6A, 0x00AA, 0xFF6B, 0x00AB,
+	0xFF6C, 0x00AC, 0xFF6D, 0x00AD, 0xFF6E, 0x00AE, 0xFF6F, 0x00AF,
+	0xFF70, 0x00B0, 0xFF71, 0x00B1, 0xFF72, 0x00B2, 0xFF73, 0x00B3,
+	0xFF74, 0x00B4, 0xFF75, 0x00B5, 0xFF76, 0x00B6, 0xFF77, 0x00B7,
+	0xFF78, 0x00B8, 0xFF79, 0x00B9, 0xFF7A, 0x00BA, 0xFF7B, 0x00BB,
+	0xFF7C, 0x00BC, 0xFF7D, 0x00BD, 0xFF7E, 0x00BE, 0xFF7F, 0x00BF,
+	0xFF80, 0x00C0, 0xFF81, 0x00C1, 0xFF82, 0x00C2, 0xFF83, 0x00C3,
+	0xFF84, 0x00C4, 0xFF85, 0x00C5, 0xFF86, 0x00C6, 0xFF87, 0x00C7,
+	0xFF88, 0x00C8, 0xFF89, 0x00C9, 0xFF8A, 0x00CA, 0xFF8B, 0x00CB,
+	0xFF8C, 0x00CC, 0xFF8D, 0x00CD, 0xFF8E, 0x00CE, 0xFF8F, 0x00CF,
+	0xFF90, 0x00D0, 0xFF91, 0x00D1, 0xFF92, 0x00D2, 0xFF93, 0x00D3,
+	0xFF94, 0x00D4, 0xFF95, 0x00D5, 0xFF96, 0x00D6, 0xFF97, 0x00D7,
+	0xFF98, 0x00D8, 0xFF99, 0x00D9, 0xFF9A, 0x00DA, 0xFF9B, 0x00DB,
+	0xFF9C, 0x00DC, 0xFF9D, 0x00DD, 0xFF9E, 0x00DE, 0xFF9F, 0x00DF,
+	0xFFE0, 0x8191, 0xFFE1, 0x8192, 0xFFE2, 0x81CA, 0xFFE3, 0x8150,
+	0xFFE4, 0xFA55, 0xFFE5, 0x818F, 0, 0
+};
+
+#if !_TINY_TABLE
+static
+const WCHAR sjis2uni[] = {
+/*	SJIS - Unicode, SJIS - Unicode, SJIS - Unicode, SJIS - Unicode, */
+	0x00A1, 0xFF61, 0x00A2, 0xFF62, 0x00A3, 0xFF63, 0x00A4, 0xFF64,
+	0x00A5, 0xFF65, 0x00A6, 0xFF66, 0x00A7, 0xFF67, 0x00A8, 0xFF68,
+	0x00A9, 0xFF69, 0x00AA, 0xFF6A, 0x00AB, 0xFF6B, 0x00AC, 0xFF6C,
+	0x00AD, 0xFF6D, 0x00AE, 0xFF6E, 0x00AF, 0xFF6F, 0x00B0, 0xFF70,
+	0x00B1, 0xFF71, 0x00B2, 0xFF72, 0x00B3, 0xFF73, 0x00B4, 0xFF74,
+	0x00B5, 0xFF75, 0x00B6, 0xFF76, 0x00B7, 0xFF77, 0x00B8, 0xFF78,
+	0x00B9, 0xFF79, 0x00BA, 0xFF7A, 0x00BB, 0xFF7B, 0x00BC, 0xFF7C,
+	0x00BD, 0xFF7D, 0x00BE, 0xFF7E, 0x00BF, 0xFF7F, 0x00C0, 0xFF80,
+	0x00C1, 0xFF81, 0x00C2, 0xFF82, 0x00C3, 0xFF83, 0x00C4, 0xFF84,
+	0x00C5, 0xFF85, 0x00C6, 0xFF86, 0x00C7, 0xFF87, 0x00C8, 0xFF88,
+	0x00C9, 0xFF89, 0x00CA, 0xFF8A, 0x00CB, 0xFF8B, 0x00CC, 0xFF8C,
+	0x00CD, 0xFF8D, 0x00CE, 0xFF8E, 0x00CF, 0xFF8F, 0x00D0, 0xFF90,
+	0x00D1, 0xFF91, 0x00D2, 0xFF92, 0x00D3, 0xFF93, 0x00D4, 0xFF94,
+	0x00D5, 0xFF95, 0x00D6, 0xFF96, 0x00D7, 0xFF97, 0x00D8, 0xFF98,
+	0x00D9, 0xFF99, 0x00DA, 0xFF9A, 0x00DB, 0xFF9B, 0x00DC, 0xFF9C,
+	0x00DD, 0xFF9D, 0x00DE, 0xFF9E, 0x00DF, 0xFF9F, 0x8140, 0x3000,
+	0x8141, 0x3001, 0x8142, 0x3002, 0x8143, 0xFF0C, 0x8144, 0xFF0E,
+	0x8145, 0x30FB, 0x8146, 0xFF1A, 0x8147, 0xFF1B, 0x8148, 0xFF1F,
+	0x8149, 0xFF01, 0x814A, 0x309B, 0x814B, 0x309C, 0x814C, 0x00B4,
+	0x814D, 0xFF40, 0x814E, 0x00A8, 0x814F, 0xFF3E, 0x8150, 0xFFE3,
+	0x8151, 0xFF3F, 0x8152, 0x30FD, 0x8153, 0x30FE, 0x8154, 0x309D,
+	0x8155, 0x309E, 0x8156, 0x3003, 0x8157, 0x4EDD, 0x8158, 0x3005,
+	0x8159, 0x3006, 0x815A, 0x3007, 0x815B, 0x30FC, 0x815C, 0x2015,
+	0x815D, 0x2010, 0x815E, 0xFF0F, 0x815F, 0xFF3C, 0x8160, 0xFF5E,
+	0x8161, 0x2225, 0x8162, 0xFF5C, 0x8163, 0x2026, 0x8164, 0x2025,
+	0x8165, 0x2018, 0x8166, 0x2019, 0x8167, 0x201C, 0x8168, 0x201D,
+	0x8169, 0xFF08, 0x816A, 0xFF09, 0x816B, 0x3014, 0x816C, 0x3015,
+	0x816D, 0xFF3B, 0x816E, 0xFF3D, 0x816F, 0xFF5B, 0x8170, 0xFF5D,
+	0x8171, 0x3008, 0x8172, 0x3009, 0x8173, 0x300A, 0x8174, 0x300B,
+	0x8175, 0x300C, 0x8176, 0x300D, 0x8177, 0x300E, 0x8178, 0x300F,
+	0x8179, 0x3010, 0x817A, 0x3011, 0x817B, 0xFF0B, 0x817C, 0xFF0D,
+	0x817D, 0x00B1, 0x817E, 0x00D7, 0x8180, 0x00F7, 0x8181, 0xFF1D,
+	0x8182, 0x2260, 0x8183, 0xFF1C, 0x8184, 0xFF1E, 0x8185, 0x2266,
+	0x8186, 0x2267, 0x8187, 0x221E, 0x8188, 0x2234, 0x8189, 0x2642,
+	0x818A, 0x2640, 0x818B, 0x00B0, 0x818C, 0x2032, 0x818D, 0x2033,
+	0x818E, 0x2103, 0x818F, 0xFFE5, 0x8190, 0xFF04, 0x8191, 0xFFE0,
+	0x8192, 0xFFE1, 0x8193, 0xFF05, 0x8194, 0xFF03, 0x8195, 0xFF06,
+	0x8196, 0xFF0A, 0x8197, 0xFF20, 0x8198, 0x00A7, 0x8199, 0x2606,
+	0x819A, 0x2605, 0x819B, 0x25CB, 0x819C, 0x25CF, 0x819D, 0x25CE,
+	0x819E, 0x25C7, 0x819F, 0x25C6, 0x81A0, 0x25A1, 0x81A1, 0x25A0,
+	0x81A2, 0x25B3, 0x81A3, 0x25B2, 0x81A4, 0x25BD, 0x81A5, 0x25BC,
+	0x81A6, 0x203B, 0x81A7, 0x3012, 0x81A8, 0x2192, 0x81A9, 0x2190,
+	0x81AA, 0x2191, 0x81AB, 0x2193, 0x81AC, 0x3013, 0x81B8, 0x2208,
+	0x81B9, 0x220B, 0x81BA, 0x2286, 0x81BB, 0x2287, 0x81BC, 0x2282,
+	0x81BD, 0x2283, 0x81BE, 0x222A, 0x81BF, 0x2229, 0x81C8, 0x2227,
+	0x81C9, 0x2228, 0x81CA, 0xFFE2, 0x81CB, 0x21D2, 0x81CC, 0x21D4,
+	0x81CD, 0x2200, 0x81CE, 0x2203, 0x81DA, 0x2220, 0x81DB, 0x22A5,
+	0x81DC, 0x2312, 0x81DD, 0x2202, 0x81DE, 0x2207, 0x81DF, 0x2261,
+	0x81E0, 0x2252, 0x81E1, 0x226A, 0x81E2, 0x226B, 0x81E3, 0x221A,
+	0x81E4, 0x223D, 0x81E5, 0x221D, 0x81E6, 0x2235, 0x81E7, 0x222B,
+	0x81E8, 0x222C, 0x81F0, 0x212B, 0x81F1, 0x2030, 0x81F2, 0x266F,
+	0x81F3, 0x266D, 0x81F4, 0x266A, 0x81F5, 0x2020, 0x81F6, 0x2021,
+	0x81F7, 0x00B6, 0x81FC, 0x25EF, 0x824F, 0xFF10, 0x8250, 0xFF11,
+	0x8251, 0xFF12, 0x8252, 0xFF13, 0x8253, 0xFF14, 0x8254, 0xFF15,
+	0x8255, 0xFF16, 0x8256, 0xFF17, 0x8257, 0xFF18, 0x8258, 0xFF19,
+	0x8260, 0xFF21, 0x8261, 0xFF22, 0x8262, 0xFF23, 0x8263, 0xFF24,
+	0x8264, 0xFF25, 0x8265, 0xFF26, 0x8266, 0xFF27, 0x8267, 0xFF28,
+	0x8268, 0xFF29, 0x8269, 0xFF2A, 0x826A, 0xFF2B, 0x826B, 0xFF2C,
+	0x826C, 0xFF2D, 0x826D, 0xFF2E, 0x826E, 0xFF2F, 0x826F, 0xFF30,
+	0x8270, 0xFF31, 0x8271, 0xFF32, 0x8272, 0xFF33, 0x8273, 0xFF34,
+	0x8274, 0xFF35, 0x8275, 0xFF36, 0x8276, 0xFF37, 0x8277, 0xFF38,
+	0x8278, 0xFF39, 0x8279, 0xFF3A, 0x8281, 0xFF41, 0x8282, 0xFF42,
+	0x8283, 0xFF43, 0x8284, 0xFF44, 0x8285, 0xFF45, 0x8286, 0xFF46,
+	0x8287, 0xFF47, 0x8288, 0xFF48, 0x8289, 0xFF49, 0x828A, 0xFF4A,
+	0x828B, 0xFF4B, 0x828C, 0xFF4C, 0x828D, 0xFF4D, 0x828E, 0xFF4E,
+	0x828F, 0xFF4F, 0x8290, 0xFF50, 0x8291, 0xFF51, 0x8292, 0xFF52,
+	0x8293, 0xFF53, 0x8294, 0xFF54, 0x8295, 0xFF55, 0x8296, 0xFF56,
+	0x8297, 0xFF57, 0x8298, 0xFF58, 0x8299, 0xFF59, 0x829A, 0xFF5A,
+	0x829F, 0x3041, 0x82A0, 0x3042, 0x82A1, 0x3043, 0x82A2, 0x3044,
+	0x82A3, 0x3045, 0x82A4, 0x3046, 0x82A5, 0x3047, 0x82A6, 0x3048,
+	0x82A7, 0x3049, 0x82A8, 0x304A, 0x82A9, 0x304B, 0x82AA, 0x304C,
+	0x82AB, 0x304D, 0x82AC, 0x304E, 0x82AD, 0x304F, 0x82AE, 0x3050,
+	0x82AF, 0x3051, 0x82B0, 0x3052, 0x82B1, 0x3053, 0x82B2, 0x3054,
+	0x82B3, 0x3055, 0x82B4, 0x3056, 0x82B5, 0x3057, 0x82B6, 0x3058,
+	0x82B7, 0x3059, 0x82B8, 0x305A, 0x82B9, 0x305B, 0x82BA, 0x305C,
+	0x82BB, 0x305D, 0x82BC, 0x305E, 0x82BD, 0x305F, 0x82BE, 0x3060,
+	0x82BF, 0x3061, 0x82C0, 0x3062, 0x82C1, 0x3063, 0x82C2, 0x3064,
+	0x82C3, 0x3065, 0x82C4, 0x3066, 0x82C5, 0x3067, 0x82C6, 0x3068,
+	0x82C7, 0x3069, 0x82C8, 0x306A, 0x82C9, 0x306B, 0x82CA, 0x306C,
+	0x82CB, 0x306D, 0x82CC, 0x306E, 0x82CD, 0x306F, 0x82CE, 0x3070,
+	0x82CF, 0x3071, 0x82D0, 0x3072, 0x82D1, 0x3073, 0x82D2, 0x3074,
+	0x82D3, 0x3075, 0x82D4, 0x3076, 0x82D5, 0x3077, 0x82D6, 0x3078,
+	0x82D7, 0x3079, 0x82D8, 0x307A, 0x82D9, 0x307B, 0x82DA, 0x307C,
+	0x82DB, 0x307D, 0x82DC, 0x307E, 0x82DD, 0x307F, 0x82DE, 0x3080,
+	0x82DF, 0x3081, 0x82E0, 0x3082, 0x82E1, 0x3083, 0x82E2, 0x3084,
+	0x82E3, 0x3085, 0x82E4, 0x3086, 0x82E5, 0x3087, 0x82E6, 0x3088,
+	0x82E7, 0x3089, 0x82E8, 0x308A, 0x82E9, 0x308B, 0x82EA, 0x308C,
+	0x82EB, 0x308D, 0x82EC, 0x308E, 0x82ED, 0x308F, 0x82EE, 0x3090,
+	0x82EF, 0x3091, 0x82F0, 0x3092, 0x82F1, 0x3093, 0x8340, 0x30A1,
+	0x8341, 0x30A2, 0x8342, 0x30A3, 0x8343, 0x30A4, 0x8344, 0x30A5,
+	0x8345, 0x30A6, 0x8346, 0x30A7, 0x8347, 0x30A8, 0x8348, 0x30A9,
+	0x8349, 0x30AA, 0x834A, 0x30AB, 0x834B, 0x30AC, 0x834C, 0x30AD,
+	0x834D, 0x30AE, 0x834E, 0x30AF, 0x834F, 0x30B0, 0x8350, 0x30B1,
+	0x8351, 0x30B2, 0x8352, 0x30B3, 0x8353, 0x30B4, 0x8354, 0x30B5,
+	0x8355, 0x30B6, 0x8356, 0x30B7, 0x8357, 0x30B8, 0x8358, 0x30B9,
+	0x8359, 0x30BA, 0x835A, 0x30BB, 0x835B, 0x30BC, 0x835C, 0x30BD,
+	0x835D, 0x30BE, 0x835E, 0x30BF, 0x835F, 0x30C0, 0x8360, 0x30C1,
+	0x8361, 0x30C2, 0x8362, 0x30C3, 0x8363, 0x30C4, 0x8364, 0x30C5,
+	0x8365, 0x30C6, 0x8366, 0x30C7, 0x8367, 0x30C8, 0x8368, 0x30C9,
+	0x8369, 0x30CA, 0x836A, 0x30CB, 0x836B, 0x30CC, 0x836C, 0x30CD,
+	0x836D, 0x30CE, 0x836E, 0x30CF, 0x836F, 0x30D0, 0x8370, 0x30D1,
+	0x8371, 0x30D2, 0x8372, 0x30D3, 0x8373, 0x30D4, 0x8374, 0x30D5,
+	0x8375, 0x30D6, 0x8376, 0x30D7, 0x8377, 0x30D8, 0x8378, 0x30D9,
+	0x8379, 0x30DA, 0x837A, 0x30DB, 0x837B, 0x30DC, 0x837C, 0x30DD,
+	0x837D, 0x30DE, 0x837E, 0x30DF, 0x8380, 0x30E0, 0x8381, 0x30E1,
+	0x8382, 0x30E2, 0x8383, 0x30E3, 0x8384, 0x30E4, 0x8385, 0x30E5,
+	0x8386, 0x30E6, 0x8387, 0x30E7, 0x8388, 0x30E8, 0x8389, 0x30E9,
+	0x838A, 0x30EA, 0x838B, 0x30EB, 0x838C, 0x30EC, 0x838D, 0x30ED,
+	0x838E, 0x30EE, 0x838F, 0x30EF, 0x8390, 0x30F0, 0x8391, 0x30F1,
+	0x8392, 0x30F2, 0x8393, 0x30F3, 0x8394, 0x3094, 0x8394, 0x30F4,
+	0x8395, 0x30F5, 0x8396, 0x30F6, 0x839F, 0x0391, 0x83A0, 0x0392,
+	0x83A1, 0x0393, 0x83A2, 0x0394, 0x83A3, 0x0395, 0x83A4, 0x0396,
+	0x83A5, 0x0397, 0x83A6, 0x0398, 0x83A7, 0x0399, 0x83A8, 0x039A,
+	0x83A9, 0x039B, 0x83AA, 0x039C, 0x83AB, 0x039D, 0x83AC, 0x039E,
+	0x83AD, 0x039F, 0x83AE, 0x03A0, 0x83AF, 0x03A1, 0x83B0, 0x03A3,
+	0x83B1, 0x03A4, 0x83B2, 0x03A5, 0x83B3, 0x03A6, 0x83B4, 0x03A7,
+	0x83B5, 0x03A8, 0x83B6, 0x03A9, 0x83BF, 0x03B1, 0x83C0, 0x03B2,
+	0x83C1, 0x03B3, 0x83C2, 0x03B4, 0x83C3, 0x03B5, 0x83C4, 0x03B6,
+	0x83C5, 0x03B7, 0x83C6, 0x03B8, 0x83C7, 0x03B9, 0x83C8, 0x03BA,
+	0x83C9, 0x03BB, 0x83CA, 0x03BC, 0x83CB, 0x03BD, 0x83CC, 0x03BE,
+	0x83CD, 0x03BF, 0x83CE, 0x03C0, 0x83CF, 0x03C1, 0x83D0, 0x03C3,
+	0x83D1, 0x03C4, 0x83D2, 0x03C5, 0x83D3, 0x03C6, 0x83D4, 0x03C7,
+	0x83D5, 0x03C8, 0x83D6, 0x03C9, 0x8440, 0x0410, 0x8441, 0x0411,
+	0x8442, 0x0412, 0x8443, 0x0413, 0x8444, 0x0414, 0x8445, 0x0415,
+	0x8446, 0x0401, 0x8447, 0x0416, 0x8448, 0x0417, 0x8449, 0x0418,
+	0x844A, 0x0419, 0x844B, 0x041A, 0x844C, 0x041B, 0x844D, 0x041C,
+	0x844E, 0x041D, 0x844F, 0x041E, 0x8450, 0x041F, 0x8451, 0x0420,
+	0x8452, 0x0421, 0x8453, 0x0422, 0x8454, 0x0423, 0x8455, 0x0424,
+	0x8456, 0x0425, 0x8457, 0x0426, 0x8458, 0x0427, 0x8459, 0x0428,
+	0x845A, 0x0429, 0x845B, 0x042A, 0x845C, 0x042B, 0x845D, 0x042C,
+	0x845E, 0x042D, 0x845F, 0x042E, 0x8460, 0x042F, 0x8470, 0x0430,
+	0x8471, 0x0431, 0x8472, 0x0432, 0x8473, 0x0433, 0x8474, 0x0434,
+	0x8475, 0x0435, 0x8476, 0x0451, 0x8477, 0x0436, 0x8478, 0x0437,
+	0x8479, 0x0438, 0x847A, 0x0439, 0x847B, 0x043A, 0x847C, 0x043B,
+	0x847D, 0x043C, 0x847E, 0x043D, 0x8480, 0x043E, 0x8481, 0x043F,
+	0x8482, 0x0440, 0x8483, 0x0441, 0x8484, 0x0442, 0x8485, 0x0443,
+	0x8486, 0x0444, 0x8487, 0x0445, 0x8488, 0x0446, 0x8489, 0x0447,
+	0x848A, 0x0448, 0x848B, 0x0449, 0x848C, 0x044A, 0x848D, 0x044B,
+	0x848E, 0x044C, 0x848F, 0x044D, 0x8490, 0x044E, 0x8491, 0x044F,
+	0x849F, 0x2500, 0x84A0, 0x2502, 0x84A1, 0x250C, 0x84A2, 0x2510,
+	0x84A3, 0x2518, 0x84A4, 0x2514, 0x84A5, 0x251C, 0x84A6, 0x252C,
+	0x84A7, 0x2524, 0x84A8, 0x2534, 0x84A9, 0x253C, 0x84AA, 0x2501,
+	0x84AB, 0x2503, 0x84AC, 0x250F, 0x84AD, 0x2513, 0x84AE, 0x251B,
+	0x84AF, 0x2517, 0x84B0, 0x2523, 0x84B1, 0x2533, 0x84B2, 0x252B,
+	0x84B3, 0x253B, 0x84B4, 0x254B, 0x84B5, 0x2520, 0x84B6, 0x252F,
+	0x84B7, 0x2528, 0x84B8, 0x2537, 0x84B9, 0x253F, 0x84BA, 0x251D,
+	0x84BB, 0x2530, 0x84BC, 0x2525, 0x84BD, 0x2538, 0x84BE, 0x2542,
+	0x8740, 0x2460, 0x8741, 0x2461, 0x8742, 0x2462, 0x8743, 0x2463,
+	0x8744, 0x2464, 0x8745, 0x2465, 0x8746, 0x2466, 0x8747, 0x2467,
+	0x8748, 0x2468, 0x8749, 0x2469, 0x874A, 0x246A, 0x874B, 0x246B,
+	0x874C, 0x246C, 0x874D, 0x246D, 0x874E, 0x246E, 0x874F, 0x246F,
+	0x8750, 0x2470, 0x8751, 0x2471, 0x8752, 0x2472, 0x8753, 0x2473,
+	0x8754, 0x2160, 0x8755, 0x2161, 0x8756, 0x2162, 0x8757, 0x2163,
+	0x8758, 0x2164, 0x8759, 0x2165, 0x875A, 0x2166, 0x875B, 0x2167,
+	0x875C, 0x2168, 0x875D, 0x2169, 0x875F, 0x3349, 0x8760, 0x3314,
+	0x8761, 0x3322, 0x8762, 0x334D, 0x8763, 0x3318, 0x8764, 0x3327,
+	0x8765, 0x3303, 0x8766, 0x3336, 0x8767, 0x3351, 0x8768, 0x3357,
+	0x8769, 0x330D, 0x876A, 0x3326, 0x876B, 0x3323, 0x876C, 0x332B,
+	0x876D, 0x334A, 0x876E, 0x333B, 0x876F, 0x339C, 0x8770, 0x339D,
+	0x8771, 0x339E, 0x8772, 0x338E, 0x8773, 0x338F, 0x8774, 0x33C4,
+	0x8775, 0x33A1, 0x877E, 0x337B, 0x8780, 0x301D, 0x8781, 0x301F,
+	0x8782, 0x2116, 0x8783, 0x33CD, 0x8784, 0x2121, 0x8785, 0x32A4,
+	0x8786, 0x32A5, 0x8787, 0x32A6, 0x8788, 0x32A7, 0x8789, 0x32A8,
+	0x878A, 0x3231, 0x878B, 0x3232, 0x878C, 0x3239, 0x878D, 0x337E,
+	0x878E, 0x337D, 0x878F, 0x337C, 0x8793, 0x222E, 0x8794, 0x2211,
+	0x8798, 0x221F, 0x8799, 0x22BF, 0x889F, 0x4E9C, 0x88A0, 0x5516,
+	0x88A1, 0x5A03, 0x88A2, 0x963F, 0x88A3, 0x54C0, 0x88A4, 0x611B,
+	0x88A5, 0x6328, 0x88A6, 0x59F6, 0x88A7, 0x9022, 0x88A8, 0x8475,
+	0x88A9, 0x831C, 0x88AA, 0x7A50, 0x88AB, 0x60AA, 0x88AC, 0x63E1,
+	0x88AD, 0x6E25, 0x88AE, 0x65ED, 0x88AF, 0x8466, 0x88B0, 0x82A6,
+	0x88B1, 0x9BF5, 0x88B2, 0x6893, 0x88B3, 0x5727, 0x88B4, 0x65A1,
+	0x88B5, 0x6271, 0x88B6, 0x5B9B, 0x88B7, 0x59D0, 0x88B8, 0x867B,
+	0x88B9, 0x98F4, 0x88BA, 0x7D62, 0x88BB, 0x7DBE, 0x88BC, 0x9B8E,
+	0x88BD, 0x6216, 0x88BE, 0x7C9F, 0x88BF, 0x88B7, 0x88C0, 0x5B89,
+	0x88C1, 0x5EB5, 0x88C2, 0x6309, 0x88C3, 0x6697, 0x88C4, 0x6848,
+	0x88C5, 0x95C7, 0x88C6, 0x978D, 0x88C7, 0x674F, 0x88C8, 0x4EE5,
+	0x88C9, 0x4F0A, 0x88CA, 0x4F4D, 0x88CB, 0x4F9D, 0x88CC, 0x5049,
+	0x88CD, 0x56F2, 0x88CE, 0x5937, 0x88CF, 0x59D4, 0x88D0, 0x5A01,
+	0x88D1, 0x5C09, 0x88D2, 0x60DF, 0x88D3, 0x610F, 0x88D4, 0x6170,
+	0x88D5, 0x6613, 0x88D6, 0x6905, 0x88D7, 0x70BA, 0x88D8, 0x754F,
+	0x88D9, 0x7570, 0x88DA, 0x79FB, 0x88DB, 0x7DAD, 0x88DC, 0x7DEF,
+	0x88DD, 0x80C3, 0x88DE, 0x840E, 0x88DF, 0x8863, 0x88E0, 0x8B02,
+	0x88E1, 0x9055, 0x88E2, 0x907A, 0x88E3, 0x533B, 0x88E4, 0x4E95,
+	0x88E5, 0x4EA5, 0x88E6, 0x57DF, 0x88E7, 0x80B2, 0x88E8, 0x90C1,
+	0x88E9, 0x78EF, 0x88EA, 0x4E00, 0x88EB, 0x58F1, 0x88EC, 0x6EA2,
+	0x88ED, 0x9038, 0x88EE, 0x7A32, 0x88EF, 0x8328, 0x88F0, 0x828B,
+	0x88F1, 0x9C2F, 0x88F2, 0x5141, 0x88F3, 0x5370, 0x88F4, 0x54BD,
+	0x88F5, 0x54E1, 0x88F6, 0x56E0, 0x88F7, 0x59FB, 0x88F8, 0x5F15,
+	0x88F9, 0x98F2, 0x88FA, 0x6DEB, 0x88FB, 0x80E4, 0x88FC, 0x852D,
+	0x8940, 0x9662, 0x8941, 0x9670, 0x8942, 0x96A0, 0x8943, 0x97FB,
+	0x8944, 0x540B, 0x8945, 0x53F3, 0x8946, 0x5B87, 0x8947, 0x70CF,
+	0x8948, 0x7FBD, 0x8949, 0x8FC2, 0x894A, 0x96E8, 0x894B, 0x536F,
+	0x894C, 0x9D5C, 0x894D, 0x7ABA, 0x894E, 0x4E11, 0x894F, 0x7893,
+	0x8950, 0x81FC, 0x8951, 0x6E26, 0x8952, 0x5618, 0x8953, 0x5504,
+	0x8954, 0x6B1D, 0x8955, 0x851A, 0x8956, 0x9C3B, 0x8957, 0x59E5,
+	0x8958, 0x53A9, 0x8959, 0x6D66, 0x895A, 0x74DC, 0x895B, 0x958F,
+	0x895C, 0x5642, 0x895D, 0x4E91, 0x895E, 0x904B, 0x895F, 0x96F2,
+	0x8960, 0x834F, 0x8961, 0x990C, 0x8962, 0x53E1, 0x8963, 0x55B6,
+	0x8964, 0x5B30, 0x8965, 0x5F71, 0x8966, 0x6620, 0x8967, 0x66F3,
+	0x8968, 0x6804, 0x8969, 0x6C38, 0x896A, 0x6CF3, 0x896B, 0x6D29,
+	0x896C, 0x745B, 0x896D, 0x76C8, 0x896E, 0x7A4E, 0x896F, 0x9834,
+	0x8970, 0x82F1, 0x8971, 0x885B, 0x8972, 0x8A60, 0x8973, 0x92ED,
+	0x8974, 0x6DB2, 0x8975, 0x75AB, 0x8976, 0x76CA, 0x8977, 0x99C5,
+	0x8978, 0x60A6, 0x8979, 0x8B01, 0x897A, 0x8D8A, 0x897B, 0x95B2,
+	0x897C, 0x698E, 0x897D, 0x53AD, 0x897E, 0x5186, 0x8980, 0x5712,
+	0x8981, 0x5830, 0x8982, 0x5944, 0x8983, 0x5BB4, 0x8984, 0x5EF6,
+	0x8985, 0x6028, 0x8986, 0x63A9, 0x8987, 0x63F4, 0x8988, 0x6CBF,
+	0x8989, 0x6F14, 0x898A, 0x708E, 0x898B, 0x7114, 0x898C, 0x7159,
+	0x898D, 0x71D5, 0x898E, 0x733F, 0x898F, 0x7E01, 0x8990, 0x8276,
+	0x8991, 0x82D1, 0x8992, 0x8597, 0x8993, 0x9060, 0x8994, 0x925B,
+	0x8995, 0x9D1B, 0x8996, 0x5869, 0x8997, 0x65BC, 0x8998, 0x6C5A,
+	0x8999, 0x7525, 0x899A, 0x51F9, 0x899B, 0x592E, 0x899C, 0x5965,
+	0x899D, 0x5F80, 0x899E, 0x5FDC, 0x899F, 0x62BC, 0x89A0, 0x65FA,
+	0x89A1, 0x6A2A, 0x89A2, 0x6B27, 0x89A3, 0x6BB4, 0x89A4, 0x738B,
+	0x89A5, 0x7FC1, 0x89A6, 0x8956, 0x89A7, 0x9D2C, 0x89A8, 0x9D0E,
+	0x89A9, 0x9EC4, 0x89AA, 0x5CA1, 0x89AB, 0x6C96, 0x89AC, 0x837B,
+	0x89AD, 0x5104, 0x89AE, 0x5C4B, 0x89AF, 0x61B6, 0x89B0, 0x81C6,
+	0x89B1, 0x6876, 0x89B2, 0x7261, 0x89B3, 0x4E59, 0x89B4, 0x4FFA,
+	0x89B5, 0x5378, 0x89B6, 0x6069, 0x89B7, 0x6E29, 0x89B8, 0x7A4F,
+	0x89B9, 0x97F3, 0x89BA, 0x4E0B, 0x89BB, 0x5316, 0x89BC, 0x4EEE,
+	0x89BD, 0x4F55, 0x89BE, 0x4F3D, 0x89BF, 0x4FA1, 0x89C0, 0x4F73,
+	0x89C1, 0x52A0, 0x89C2, 0x53EF, 0x89C3, 0x5609, 0x89C4, 0x590F,
+	0x89C5, 0x5AC1, 0x89C6, 0x5BB6, 0x89C7, 0x5BE1, 0x89C8, 0x79D1,
+	0x89C9, 0x6687, 0x89CA, 0x679C, 0x89CB, 0x67B6, 0x89CC, 0x6B4C,
+	0x89CD, 0x6CB3, 0x89CE, 0x706B, 0x89CF, 0x73C2, 0x89D0, 0x798D,
+	0x89D1, 0x79BE, 0x89D2, 0x7A3C, 0x89D3, 0x7B87, 0x89D4, 0x82B1,
+	0x89D5, 0x82DB, 0x89D6, 0x8304, 0x89D7, 0x8377, 0x89D8, 0x83EF,
+	0x89D9, 0x83D3, 0x89DA, 0x8766, 0x89DB, 0x8AB2, 0x89DC, 0x5629,
+	0x89DD, 0x8CA8, 0x89DE, 0x8FE6, 0x89DF, 0x904E, 0x89E0, 0x971E,
+	0x89E1, 0x868A, 0x89E2, 0x4FC4, 0x89E3, 0x5CE8, 0x89E4, 0x6211,
+	0x89E5, 0x7259, 0x89E6, 0x753B, 0x89E7, 0x81E5, 0x89E8, 0x82BD,
+	0x89E9, 0x86FE, 0x89EA, 0x8CC0, 0x89EB, 0x96C5, 0x89EC, 0x9913,
+	0x89ED, 0x99D5, 0x89EE, 0x4ECB, 0x89EF, 0x4F1A, 0x89F0, 0x89E3,
+	0x89F1, 0x56DE, 0x89F2, 0x584A, 0x89F3, 0x58CA, 0x89F4, 0x5EFB,
+	0x89F5, 0x5FEB, 0x89F6, 0x602A, 0x89F7, 0x6094, 0x89F8, 0x6062,
+	0x89F9, 0x61D0, 0x89FA, 0x6212, 0x89FB, 0x62D0, 0x89FC, 0x6539,
+	0x8A40, 0x9B41, 0x8A41, 0x6666, 0x8A42, 0x68B0, 0x8A43, 0x6D77,
+	0x8A44, 0x7070, 0x8A45, 0x754C, 0x8A46, 0x7686, 0x8A47, 0x7D75,
+	0x8A48, 0x82A5, 0x8A49, 0x87F9, 0x8A4A, 0x958B, 0x8A4B, 0x968E,
+	0x8A4C, 0x8C9D, 0x8A4D, 0x51F1, 0x8A4E, 0x52BE, 0x8A4F, 0x5916,
+	0x8A50, 0x54B3, 0x8A51, 0x5BB3, 0x8A52, 0x5D16, 0x8A53, 0x6168,
+	0x8A54, 0x6982, 0x8A55, 0x6DAF, 0x8A56, 0x788D, 0x8A57, 0x84CB,
+	0x8A58, 0x8857, 0x8A59, 0x8A72, 0x8A5A, 0x93A7, 0x8A5B, 0x9AB8,
+	0x8A5C, 0x6D6C, 0x8A5D, 0x99A8, 0x8A5E, 0x86D9, 0x8A5F, 0x57A3,
+	0x8A60, 0x67FF, 0x8A61, 0x86CE, 0x8A62, 0x920E, 0x8A63, 0x5283,
+	0x8A64, 0x5687, 0x8A65, 0x5404, 0x8A66, 0x5ED3, 0x8A67, 0x62E1,
+	0x8A68, 0x64B9, 0x8A69, 0x683C, 0x8A6A, 0x6838, 0x8A6B, 0x6BBB,
+	0x8A6C, 0x7372, 0x8A6D, 0x78BA, 0x8A6E, 0x7A6B, 0x8A6F, 0x899A,
+	0x8A70, 0x89D2, 0x8A71, 0x8D6B, 0x8A72, 0x8F03, 0x8A73, 0x90ED,
+	0x8A74, 0x95A3, 0x8A75, 0x9694, 0x8A76, 0x9769, 0x8A77, 0x5B66,
+	0x8A78, 0x5CB3, 0x8A79, 0x697D, 0x8A7A, 0x984D, 0x8A7B, 0x984E,
+	0x8A7C, 0x639B, 0x8A7D, 0x7B20, 0x8A7E, 0x6A2B, 0x8A80, 0x6A7F,
+	0x8A81, 0x68B6, 0x8A82, 0x9C0D, 0x8A83, 0x6F5F, 0x8A84, 0x5272,
+	0x8A85, 0x559D, 0x8A86, 0x6070, 0x8A87, 0x62EC, 0x8A88, 0x6D3B,
+	0x8A89, 0x6E07, 0x8A8A, 0x6ED1, 0x8A8B, 0x845B, 0x8A8C, 0x8910,
+	0x8A8D, 0x8F44, 0x8A8E, 0x4E14, 0x8A8F, 0x9C39, 0x8A90, 0x53F6,
+	0x8A91, 0x691B, 0x8A92, 0x6A3A, 0x8A93, 0x9784, 0x8A94, 0x682A,
+	0x8A95, 0x515C, 0x8A96, 0x7AC3, 0x8A97, 0x84B2, 0x8A98, 0x91DC,
+	0x8A99, 0x938C, 0x8A9A, 0x565B, 0x8A9B, 0x9D28, 0x8A9C, 0x6822,
+	0x8A9D, 0x8305, 0x8A9E, 0x8431, 0x8A9F, 0x7CA5, 0x8AA0, 0x5208,
+	0x8AA1, 0x82C5, 0x8AA2, 0x74E6, 0x8AA3, 0x4E7E, 0x8AA4, 0x4F83,
+	0x8AA5, 0x51A0, 0x8AA6, 0x5BD2, 0x8AA7, 0x520A, 0x8AA8, 0x52D8,
+	0x8AA9, 0x52E7, 0x8AAA, 0x5DFB, 0x8AAB, 0x559A, 0x8AAC, 0x582A,
+	0x8AAD, 0x59E6, 0x8AAE, 0x5B8C, 0x8AAF, 0x5B98, 0x8AB0, 0x5BDB,
+	0x8AB1, 0x5E72, 0x8AB2, 0x5E79, 0x8AB3, 0x60A3, 0x8AB4, 0x611F,
+	0x8AB5, 0x6163, 0x8AB6, 0x61BE, 0x8AB7, 0x63DB, 0x8AB8, 0x6562,
+	0x8AB9, 0x67D1, 0x8ABA, 0x6853, 0x8ABB, 0x68FA, 0x8ABC, 0x6B3E,
+	0x8ABD, 0x6B53, 0x8ABE, 0x6C57, 0x8ABF, 0x6F22, 0x8AC0, 0x6F97,
+	0x8AC1, 0x6F45, 0x8AC2, 0x74B0, 0x8AC3, 0x7518, 0x8AC4, 0x76E3,
+	0x8AC5, 0x770B, 0x8AC6, 0x7AFF, 0x8AC7, 0x7BA1, 0x8AC8, 0x7C21,
+	0x8AC9, 0x7DE9, 0x8ACA, 0x7F36, 0x8ACB, 0x7FF0, 0x8ACC, 0x809D,
+	0x8ACD, 0x8266, 0x8ACE, 0x839E, 0x8ACF, 0x89B3, 0x8AD0, 0x8ACC,
+	0x8AD1, 0x8CAB, 0x8AD2, 0x9084, 0x8AD3, 0x9451, 0x8AD4, 0x9593,
+	0x8AD5, 0x9591, 0x8AD6, 0x95A2, 0x8AD7, 0x9665, 0x8AD8, 0x97D3,
+	0x8AD9, 0x9928, 0x8ADA, 0x8218, 0x8ADB, 0x4E38, 0x8ADC, 0x542B,
+	0x8ADD, 0x5CB8, 0x8ADE, 0x5DCC, 0x8ADF, 0x73A9, 0x8AE0, 0x764C,
+	0x8AE1, 0x773C, 0x8AE2, 0x5CA9, 0x8AE3, 0x7FEB, 0x8AE4, 0x8D0B,
+	0x8AE5, 0x96C1, 0x8AE6, 0x9811, 0x8AE7, 0x9854, 0x8AE8, 0x9858,
+	0x8AE9, 0x4F01, 0x8AEA, 0x4F0E, 0x8AEB, 0x5371, 0x8AEC, 0x559C,
+	0x8AED, 0x5668, 0x8AEE, 0x57FA, 0x8AEF, 0x5947, 0x8AF0, 0x5B09,
+	0x8AF1, 0x5BC4, 0x8AF2, 0x5C90, 0x8AF3, 0x5E0C, 0x8AF4, 0x5E7E,
+	0x8AF5, 0x5FCC, 0x8AF6, 0x63EE, 0x8AF7, 0x673A, 0x8AF8, 0x65D7,
+	0x8AF9, 0x65E2, 0x8AFA, 0x671F, 0x8AFB, 0x68CB, 0x8AFC, 0x68C4,
+	0x8B40, 0x6A5F, 0x8B41, 0x5E30, 0x8B42, 0x6BC5, 0x8B43, 0x6C17,
+	0x8B44, 0x6C7D, 0x8B45, 0x757F, 0x8B46, 0x7948, 0x8B47, 0x5B63,
+	0x8B48, 0x7A00, 0x8B49, 0x7D00, 0x8B4A, 0x5FBD, 0x8B4B, 0x898F,
+	0x8B4C, 0x8A18, 0x8B4D, 0x8CB4, 0x8B4E, 0x8D77, 0x8B4F, 0x8ECC,
+	0x8B50, 0x8F1D, 0x8B51, 0x98E2, 0x8B52, 0x9A0E, 0x8B53, 0x9B3C,
+	0x8B54, 0x4E80, 0x8B55, 0x507D, 0x8B56, 0x5100, 0x8B57, 0x5993,
+	0x8B58, 0x5B9C, 0x8B59, 0x622F, 0x8B5A, 0x6280, 0x8B5B, 0x64EC,
+	0x8B5C, 0x6B3A, 0x8B5D, 0x72A0, 0x8B5E, 0x7591, 0x8B5F, 0x7947,
+	0x8B60, 0x7FA9, 0x8B61, 0x87FB, 0x8B62, 0x8ABC, 0x8B63, 0x8B70,
+	0x8B64, 0x63AC, 0x8B65, 0x83CA, 0x8B66, 0x97A0, 0x8B67, 0x5409,
+	0x8B68, 0x5403, 0x8B69, 0x55AB, 0x8B6A, 0x6854, 0x8B6B, 0x6A58,
+	0x8B6C, 0x8A70, 0x8B6D, 0x7827, 0x8B6E, 0x6775, 0x8B6F, 0x9ECD,
+	0x8B70, 0x5374, 0x8B71, 0x5BA2, 0x8B72, 0x811A, 0x8B73, 0x8650,
+	0x8B74, 0x9006, 0x8B75, 0x4E18, 0x8B76, 0x4E45, 0x8B77, 0x4EC7,
+	0x8B78, 0x4F11, 0x8B79, 0x53CA, 0x8B7A, 0x5438, 0x8B7B, 0x5BAE,
+	0x8B7C, 0x5F13, 0x8B7D, 0x6025, 0x8B7E, 0x6551, 0x8B80, 0x673D,
+	0x8B81, 0x6C42, 0x8B82, 0x6C72, 0x8B83, 0x6CE3, 0x8B84, 0x7078,
+	0x8B85, 0x7403, 0x8B86, 0x7A76, 0x8B87, 0x7AAE, 0x8B88, 0x7B08,
+	0x8B89, 0x7D1A, 0x8B8A, 0x7CFE, 0x8B8B, 0x7D66, 0x8B8C, 0x65E7,
+	0x8B8D, 0x725B, 0x8B8E, 0x53BB, 0x8B8F, 0x5C45, 0x8B90, 0x5DE8,
+	0x8B91, 0x62D2, 0x8B92, 0x62E0, 0x8B93, 0x6319, 0x8B94, 0x6E20,
+	0x8B95, 0x865A, 0x8B96, 0x8A31, 0x8B97, 0x8DDD, 0x8B98, 0x92F8,
+	0x8B99, 0x6F01, 0x8B9A, 0x79A6, 0x8B9B, 0x9B5A, 0x8B9C, 0x4EA8,
+	0x8B9D, 0x4EAB, 0x8B9E, 0x4EAC, 0x8B9F, 0x4F9B, 0x8BA0, 0x4FA0,
+	0x8BA1, 0x50D1, 0x8BA2, 0x5147, 0x8BA3, 0x7AF6, 0x8BA4, 0x5171,
+	0x8BA5, 0x51F6, 0x8BA6, 0x5354, 0x8BA7, 0x5321, 0x8BA8, 0x537F,
+	0x8BA9, 0x53EB, 0x8BAA, 0x55AC, 0x8BAB, 0x5883, 0x8BAC, 0x5CE1,
+	0x8BAD, 0x5F37, 0x8BAE, 0x5F4A, 0x8BAF, 0x602F, 0x8BB0, 0x6050,
+	0x8BB1, 0x606D, 0x8BB2, 0x631F, 0x8BB3, 0x6559, 0x8BB4, 0x6A4B,
+	0x8BB5, 0x6CC1, 0x8BB6, 0x72C2, 0x8BB7, 0x72ED, 0x8BB8, 0x77EF,
+	0x8BB9, 0x80F8, 0x8BBA, 0x8105, 0x8BBB, 0x8208, 0x8BBC, 0x854E,
+	0x8BBD, 0x90F7, 0x8BBE, 0x93E1, 0x8BBF, 0x97FF, 0x8BC0, 0x9957,
+	0x8BC1, 0x9A5A, 0x8BC2, 0x4EF0, 0x8BC3, 0x51DD, 0x8BC4, 0x5C2D,
+	0x8BC5, 0x6681, 0x8BC6, 0x696D, 0x8BC7, 0x5C40, 0x8BC8, 0x66F2,
+	0x8BC9, 0x6975, 0x8BCA, 0x7389, 0x8BCB, 0x6850, 0x8BCC, 0x7C81,
+	0x8BCD, 0x50C5, 0x8BCE, 0x52E4, 0x8BCF, 0x5747, 0x8BD0, 0x5DFE,
+	0x8BD1, 0x9326, 0x8BD2, 0x65A4, 0x8BD3, 0x6B23, 0x8BD4, 0x6B3D,
+	0x8BD5, 0x7434, 0x8BD6, 0x7981, 0x8BD7, 0x79BD, 0x8BD8, 0x7B4B,
+	0x8BD9, 0x7DCA, 0x8BDA, 0x82B9, 0x8BDB, 0x83CC, 0x8BDC, 0x887F,
+	0x8BDD, 0x895F, 0x8BDE, 0x8B39, 0x8BDF, 0x8FD1, 0x8BE0, 0x91D1,
+	0x8BE1, 0x541F, 0x8BE2, 0x9280, 0x8BE3, 0x4E5D, 0x8BE4, 0x5036,
+	0x8BE5, 0x53E5, 0x8BE6, 0x533A, 0x8BE7, 0x72D7, 0x8BE8, 0x7396,
+	0x8BE9, 0x77E9, 0x8BEA, 0x82E6, 0x8BEB, 0x8EAF, 0x8BEC, 0x99C6,
+	0x8BED, 0x99C8, 0x8BEE, 0x99D2, 0x8BEF, 0x5177, 0x8BF0, 0x611A,
+	0x8BF1, 0x865E, 0x8BF2, 0x55B0, 0x8BF3, 0x7A7A, 0x8BF4, 0x5076,
+	0x8BF5, 0x5BD3, 0x8BF6, 0x9047, 0x8BF7, 0x9685, 0x8BF8, 0x4E32,
+	0x8BF9, 0x6ADB, 0x8BFA, 0x91E7, 0x8BFB, 0x5C51, 0x8BFC, 0x5C48,
+	0x8C40, 0x6398, 0x8C41, 0x7A9F, 0x8C42, 0x6C93, 0x8C43, 0x9774,
+	0x8C44, 0x8F61, 0x8C45, 0x7AAA, 0x8C46, 0x718A, 0x8C47, 0x9688,
+	0x8C48, 0x7C82, 0x8C49, 0x6817, 0x8C4A, 0x7E70, 0x8C4B, 0x6851,
+	0x8C4C, 0x936C, 0x8C4D, 0x52F2, 0x8C4E, 0x541B, 0x8C4F, 0x85AB,
+	0x8C50, 0x8A13, 0x8C51, 0x7FA4, 0x8C52, 0x8ECD, 0x8C53, 0x90E1,
+	0x8C54, 0x5366, 0x8C55, 0x8888, 0x8C56, 0x7941, 0x8C57, 0x4FC2,
+	0x8C58, 0x50BE, 0x8C59, 0x5211, 0x8C5A, 0x5144, 0x8C5B, 0x5553,
+	0x8C5C, 0x572D, 0x8C5D, 0x73EA, 0x8C5E, 0x578B, 0x8C5F, 0x5951,
+	0x8C60, 0x5F62, 0x8C61, 0x5F84, 0x8C62, 0x6075, 0x8C63, 0x6176,
+	0x8C64, 0x6167, 0x8C65, 0x61A9, 0x8C66, 0x63B2, 0x8C67, 0x643A,
+	0x8C68, 0x656C, 0x8C69, 0x666F, 0x8C6A, 0x6842, 0x8C6B, 0x6E13,
+	0x8C6C, 0x7566, 0x8C6D, 0x7A3D, 0x8C6E, 0x7CFB, 0x8C6F, 0x7D4C,
+	0x8C70, 0x7D99, 0x8C71, 0x7E4B, 0x8C72, 0x7F6B, 0x8C73, 0x830E,
+	0x8C74, 0x834A, 0x8C75, 0x86CD, 0x8C76, 0x8A08, 0x8C77, 0x8A63,
+	0x8C78, 0x8B66, 0x8C79, 0x8EFD, 0x8C7A, 0x981A, 0x8C7B, 0x9D8F,
+	0x8C7C, 0x82B8, 0x8C7D, 0x8FCE, 0x8C7E, 0x9BE8, 0x8C80, 0x5287,
+	0x8C81, 0x621F, 0x8C82, 0x6483, 0x8C83, 0x6FC0, 0x8C84, 0x9699,
+	0x8C85, 0x6841, 0x8C86, 0x5091, 0x8C87, 0x6B20, 0x8C88, 0x6C7A,
+	0x8C89, 0x6F54, 0x8C8A, 0x7A74, 0x8C8B, 0x7D50, 0x8C8C, 0x8840,
+	0x8C8D, 0x8A23, 0x8C8E, 0x6708, 0x8C8F, 0x4EF6, 0x8C90, 0x5039,
+	0x8C91, 0x5026, 0x8C92, 0x5065, 0x8C93, 0x517C, 0x8C94, 0x5238,
+	0x8C95, 0x5263, 0x8C96, 0x55A7, 0x8C97, 0x570F, 0x8C98, 0x5805,
+	0x8C99, 0x5ACC, 0x8C9A, 0x5EFA, 0x8C9B, 0x61B2, 0x8C9C, 0x61F8,
+	0x8C9D, 0x62F3, 0x8C9E, 0x6372, 0x8C9F, 0x691C, 0x8CA0, 0x6A29,
+	0x8CA1, 0x727D, 0x8CA2, 0x72AC, 0x8CA3, 0x732E, 0x8CA4, 0x7814,
+	0x8CA5, 0x786F, 0x8CA6, 0x7D79, 0x8CA7, 0x770C, 0x8CA8, 0x80A9,
+	0x8CA9, 0x898B, 0x8CAA, 0x8B19, 0x8CAB, 0x8CE2, 0x8CAC, 0x8ED2,
+	0x8CAD, 0x9063, 0x8CAE, 0x9375, 0x8CAF, 0x967A, 0x8CB0, 0x9855,
+	0x8CB1, 0x9A13, 0x8CB2, 0x9E78, 0x8CB3, 0x5143, 0x8CB4, 0x539F,
+	0x8CB5, 0x53B3, 0x8CB6, 0x5E7B, 0x8CB7, 0x5F26, 0x8CB8, 0x6E1B,
+	0x8CB9, 0x6E90, 0x8CBA, 0x7384, 0x8CBB, 0x73FE, 0x8CBC, 0x7D43,
+	0x8CBD, 0x8237, 0x8CBE, 0x8A00, 0x8CBF, 0x8AFA, 0x8CC0, 0x9650,
+	0x8CC1, 0x4E4E, 0x8CC2, 0x500B, 0x8CC3, 0x53E4, 0x8CC4, 0x547C,
+	0x8CC5, 0x56FA, 0x8CC6, 0x59D1, 0x8CC7, 0x5B64, 0x8CC8, 0x5DF1,
+	0x8CC9, 0x5EAB, 0x8CCA, 0x5F27, 0x8CCB, 0x6238, 0x8CCC, 0x6545,
+	0x8CCD, 0x67AF, 0x8CCE, 0x6E56, 0x8CCF, 0x72D0, 0x8CD0, 0x7CCA,
+	0x8CD1, 0x88B4, 0x8CD2, 0x80A1, 0x8CD3, 0x80E1, 0x8CD4, 0x83F0,
+	0x8CD5, 0x864E, 0x8CD6, 0x8A87, 0x8CD7, 0x8DE8, 0x8CD8, 0x9237,
+	0x8CD9, 0x96C7, 0x8CDA, 0x9867, 0x8CDB, 0x9F13, 0x8CDC, 0x4E94,
+	0x8CDD, 0x4E92, 0x8CDE, 0x4F0D, 0x8CDF, 0x5348, 0x8CE0, 0x5449,
+	0x8CE1, 0x543E, 0x8CE2, 0x5A2F, 0x8CE3, 0x5F8C, 0x8CE4, 0x5FA1,
+	0x8CE5, 0x609F, 0x8CE6, 0x68A7, 0x8CE7, 0x6A8E, 0x8CE8, 0x745A,
+	0x8CE9, 0x7881, 0x8CEA, 0x8A9E, 0x8CEB, 0x8AA4, 0x8CEC, 0x8B77,
+	0x8CED, 0x9190, 0x8CEE, 0x4E5E, 0x8CEF, 0x9BC9, 0x8CF0, 0x4EA4,
+	0x8CF1, 0x4F7C, 0x8CF2, 0x4FAF, 0x8CF3, 0x5019, 0x8CF4, 0x5016,
+	0x8CF5, 0x5149, 0x8CF6, 0x516C, 0x8CF7, 0x529F, 0x8CF8, 0x52B9,
+	0x8CF9, 0x52FE, 0x8CFA, 0x539A, 0x8CFB, 0x53E3, 0x8CFC, 0x5411,
+	0x8D40, 0x540E, 0x8D41, 0x5589, 0x8D42, 0x5751, 0x8D43, 0x57A2,
+	0x8D44, 0x597D, 0x8D45, 0x5B54, 0x8D46, 0x5B5D, 0x8D47, 0x5B8F,
+	0x8D48, 0x5DE5, 0x8D49, 0x5DE7, 0x8D4A, 0x5DF7, 0x8D4B, 0x5E78,
+	0x8D4C, 0x5E83, 0x8D4D, 0x5E9A, 0x8D4E, 0x5EB7, 0x8D4F, 0x5F18,
+	0x8D50, 0x6052, 0x8D51, 0x614C, 0x8D52, 0x6297, 0x8D53, 0x62D8,
+	0x8D54, 0x63A7, 0x8D55, 0x653B, 0x8D56, 0x6602, 0x8D57, 0x6643,
+	0x8D58, 0x66F4, 0x8D59, 0x676D, 0x8D5A, 0x6821, 0x8D5B, 0x6897,
+	0x8D5C, 0x69CB, 0x8D5D, 0x6C5F, 0x8D5E, 0x6D2A, 0x8D5F, 0x6D69,
+	0x8D60, 0x6E2F, 0x8D61, 0x6E9D, 0x8D62, 0x7532, 0x8D63, 0x7687,
+	0x8D64, 0x786C, 0x8D65, 0x7A3F, 0x8D66, 0x7CE0, 0x8D67, 0x7D05,
+	0x8D68, 0x7D18, 0x8D69, 0x7D5E, 0x8D6A, 0x7DB1, 0x8D6B, 0x8015,
+	0x8D6C, 0x8003, 0x8D6D, 0x80AF, 0x8D6E, 0x80B1, 0x8D6F, 0x8154,
+	0x8D70, 0x818F, 0x8D71, 0x822A, 0x8D72, 0x8352, 0x8D73, 0x884C,
+	0x8D74, 0x8861, 0x8D75, 0x8B1B, 0x8D76, 0x8CA2, 0x8D77, 0x8CFC,
+	0x8D78, 0x90CA, 0x8D79, 0x9175, 0x8D7A, 0x9271, 0x8D7B, 0x783F,
+	0x8D7C, 0x92FC, 0x8D7D, 0x95A4, 0x8D7E, 0x964D, 0x8D80, 0x9805,
+	0x8D81, 0x9999, 0x8D82, 0x9AD8, 0x8D83, 0x9D3B, 0x8D84, 0x525B,
+	0x8D85, 0x52AB, 0x8D86, 0x53F7, 0x8D87, 0x5408, 0x8D88, 0x58D5,
+	0x8D89, 0x62F7, 0x8D8A, 0x6FE0, 0x8D8B, 0x8C6A, 0x8D8C, 0x8F5F,
+	0x8D8D, 0x9EB9, 0x8D8E, 0x514B, 0x8D8F, 0x523B, 0x8D90, 0x544A,
+	0x8D91, 0x56FD, 0x8D92, 0x7A40, 0x8D93, 0x9177, 0x8D94, 0x9D60,
+	0x8D95, 0x9ED2, 0x8D96, 0x7344, 0x8D97, 0x6F09, 0x8D98, 0x8170,
+	0x8D99, 0x7511, 0x8D9A, 0x5FFD, 0x8D9B, 0x60DA, 0x8D9C, 0x9AA8,
+	0x8D9D, 0x72DB, 0x8D9E, 0x8FBC, 0x8D9F, 0x6B64, 0x8DA0, 0x9803,
+	0x8DA1, 0x4ECA, 0x8DA2, 0x56F0, 0x8DA3, 0x5764, 0x8DA4, 0x58BE,
+	0x8DA5, 0x5A5A, 0x8DA6, 0x6068, 0x8DA7, 0x61C7, 0x8DA8, 0x660F,
+	0x8DA9, 0x6606, 0x8DAA, 0x6839, 0x8DAB, 0x68B1, 0x8DAC, 0x6DF7,
+	0x8DAD, 0x75D5, 0x8DAE, 0x7D3A, 0x8DAF, 0x826E, 0x8DB0, 0x9B42,
+	0x8DB1, 0x4E9B, 0x8DB2, 0x4F50, 0x8DB3, 0x53C9, 0x8DB4, 0x5506,
+	0x8DB5, 0x5D6F, 0x8DB6, 0x5DE6, 0x8DB7, 0x5DEE, 0x8DB8, 0x67FB,
+	0x8DB9, 0x6C99, 0x8DBA, 0x7473, 0x8DBB, 0x7802, 0x8DBC, 0x8A50,
+	0x8DBD, 0x9396, 0x8DBE, 0x88DF, 0x8DBF, 0x5750, 0x8DC0, 0x5EA7,
+	0x8DC1, 0x632B, 0x8DC2, 0x50B5, 0x8DC3, 0x50AC, 0x8DC4, 0x518D,
+	0x8DC5, 0x6700, 0x8DC6, 0x54C9, 0x8DC7, 0x585E, 0x8DC8, 0x59BB,
+	0x8DC9, 0x5BB0, 0x8DCA, 0x5F69, 0x8DCB, 0x624D, 0x8DCC, 0x63A1,
+	0x8DCD, 0x683D, 0x8DCE, 0x6B73, 0x8DCF, 0x6E08, 0x8DD0, 0x707D,
+	0x8DD1, 0x91C7, 0x8DD2, 0x7280, 0x8DD3, 0x7815, 0x8DD4, 0x7826,
+	0x8DD5, 0x796D, 0x8DD6, 0x658E, 0x8DD7, 0x7D30, 0x8DD8, 0x83DC,
+	0x8DD9, 0x88C1, 0x8DDA, 0x8F09, 0x8DDB, 0x969B, 0x8DDC, 0x5264,
+	0x8DDD, 0x5728, 0x8DDE, 0x6750, 0x8DDF, 0x7F6A, 0x8DE0, 0x8CA1,
+	0x8DE1, 0x51B4, 0x8DE2, 0x5742, 0x8DE3, 0x962A, 0x8DE4, 0x583A,
+	0x8DE5, 0x698A, 0x8DE6, 0x80B4, 0x8DE7, 0x54B2, 0x8DE8, 0x5D0E,
+	0x8DE9, 0x57FC, 0x8DEA, 0x7895, 0x8DEB, 0x9DFA, 0x8DEC, 0x4F5C,
+	0x8DED, 0x524A, 0x8DEE, 0x548B, 0x8DEF, 0x643E, 0x8DF0, 0x6628,
+	0x8DF1, 0x6714, 0x8DF2, 0x67F5, 0x8DF3, 0x7A84, 0x8DF4, 0x7B56,
+	0x8DF5, 0x7D22, 0x8DF6, 0x932F, 0x8DF7, 0x685C, 0x8DF8, 0x9BAD,
+	0x8DF9, 0x7B39, 0x8DFA, 0x5319, 0x8DFB, 0x518A, 0x8DFC, 0x5237,
+	0x8E40, 0x5BDF, 0x8E41, 0x62F6, 0x8E42, 0x64AE, 0x8E43, 0x64E6,
+	0x8E44, 0x672D, 0x8E45, 0x6BBA, 0x8E46, 0x85A9, 0x8E47, 0x96D1,
+	0x8E48, 0x7690, 0x8E49, 0x9BD6, 0x8E4A, 0x634C, 0x8E4B, 0x9306,
+	0x8E4C, 0x9BAB, 0x8E4D, 0x76BF, 0x8E4E, 0x6652, 0x8E4F, 0x4E09,
+	0x8E50, 0x5098, 0x8E51, 0x53C2, 0x8E52, 0x5C71, 0x8E53, 0x60E8,
+	0x8E54, 0x6492, 0x8E55, 0x6563, 0x8E56, 0x685F, 0x8E57, 0x71E6,
+	0x8E58, 0x73CA, 0x8E59, 0x7523, 0x8E5A, 0x7B97, 0x8E5B, 0x7E82,
+	0x8E5C, 0x8695, 0x8E5D, 0x8B83, 0x8E5E, 0x8CDB, 0x8E5F, 0x9178,
+	0x8E60, 0x9910, 0x8E61, 0x65AC, 0x8E62, 0x66AB, 0x8E63, 0x6B8B,
+	0x8E64, 0x4ED5, 0x8E65, 0x4ED4, 0x8E66, 0x4F3A, 0x8E67, 0x4F7F,
+	0x8E68, 0x523A, 0x8E69, 0x53F8, 0x8E6A, 0x53F2, 0x8E6B, 0x55E3,
+	0x8E6C, 0x56DB, 0x8E6D, 0x58EB, 0x8E6E, 0x59CB, 0x8E6F, 0x59C9,
+	0x8E70, 0x59FF, 0x8E71, 0x5B50, 0x8E72, 0x5C4D, 0x8E73, 0x5E02,
+	0x8E74, 0x5E2B, 0x8E75, 0x5FD7, 0x8E76, 0x601D, 0x8E77, 0x6307,
+	0x8E78, 0x652F, 0x8E79, 0x5B5C, 0x8E7A, 0x65AF, 0x8E7B, 0x65BD,
+	0x8E7C, 0x65E8, 0x8E7D, 0x679D, 0x8E7E, 0x6B62, 0x8E80, 0x6B7B,
+	0x8E81, 0x6C0F, 0x8E82, 0x7345, 0x8E83, 0x7949, 0x8E84, 0x79C1,
+	0x8E85, 0x7CF8, 0x8E86, 0x7D19, 0x8E87, 0x7D2B, 0x8E88, 0x80A2,
+	0x8E89, 0x8102, 0x8E8A, 0x81F3, 0x8E8B, 0x8996, 0x8E8C, 0x8A5E,
+	0x8E8D, 0x8A69, 0x8E8E, 0x8A66, 0x8E8F, 0x8A8C, 0x8E90, 0x8AEE,
+	0x8E91, 0x8CC7, 0x8E92, 0x8CDC, 0x8E93, 0x96CC, 0x8E94, 0x98FC,
+	0x8E95, 0x6B6F, 0x8E96, 0x4E8B, 0x8E97, 0x4F3C, 0x8E98, 0x4F8D,
+	0x8E99, 0x5150, 0x8E9A, 0x5B57, 0x8E9B, 0x5BFA, 0x8E9C, 0x6148,
+	0x8E9D, 0x6301, 0x8E9E, 0x6642, 0x8E9F, 0x6B21, 0x8EA0, 0x6ECB,
+	0x8EA1, 0x6CBB, 0x8EA2, 0x723E, 0x8EA3, 0x74BD, 0x8EA4, 0x75D4,
+	0x8EA5, 0x78C1, 0x8EA6, 0x793A, 0x8EA7, 0x800C, 0x8EA8, 0x8033,
+	0x8EA9, 0x81EA, 0x8EAA, 0x8494, 0x8EAB, 0x8F9E, 0x8EAC, 0x6C50,
+	0x8EAD, 0x9E7F, 0x8EAE, 0x5F0F, 0x8EAF, 0x8B58, 0x8EB0, 0x9D2B,
+	0x8EB1, 0x7AFA, 0x8EB2, 0x8EF8, 0x8EB3, 0x5B8D, 0x8EB4, 0x96EB,
+	0x8EB5, 0x4E03, 0x8EB6, 0x53F1, 0x8EB7, 0x57F7, 0x8EB8, 0x5931,
+	0x8EB9, 0x5AC9, 0x8EBA, 0x5BA4, 0x8EBB, 0x6089, 0x8EBC, 0x6E7F,
+	0x8EBD, 0x6F06, 0x8EBE, 0x75BE, 0x8EBF, 0x8CEA, 0x8EC0, 0x5B9F,
+	0x8EC1, 0x8500, 0x8EC2, 0x7BE0, 0x8EC3, 0x5072, 0x8EC4, 0x67F4,
+	0x8EC5, 0x829D, 0x8EC6, 0x5C61, 0x8EC7, 0x854A, 0x8EC8, 0x7E1E,
+	0x8EC9, 0x820E, 0x8ECA, 0x5199, 0x8ECB, 0x5C04, 0x8ECC, 0x6368,
+	0x8ECD, 0x8D66, 0x8ECE, 0x659C, 0x8ECF, 0x716E, 0x8ED0, 0x793E,
+	0x8ED1, 0x7D17, 0x8ED2, 0x8005, 0x8ED3, 0x8B1D, 0x8ED4, 0x8ECA,
+	0x8ED5, 0x906E, 0x8ED6, 0x86C7, 0x8ED7, 0x90AA, 0x8ED8, 0x501F,
+	0x8ED9, 0x52FA, 0x8EDA, 0x5C3A, 0x8EDB, 0x6753, 0x8EDC, 0x707C,
+	0x8EDD, 0x7235, 0x8EDE, 0x914C, 0x8EDF, 0x91C8, 0x8EE0, 0x932B,
+	0x8EE1, 0x82E5, 0x8EE2, 0x5BC2, 0x8EE3, 0x5F31, 0x8EE4, 0x60F9,
+	0x8EE5, 0x4E3B, 0x8EE6, 0x53D6, 0x8EE7, 0x5B88, 0x8EE8, 0x624B,
+	0x8EE9, 0x6731, 0x8EEA, 0x6B8A, 0x8EEB, 0x72E9, 0x8EEC, 0x73E0,
+	0x8EED, 0x7A2E, 0x8EEE, 0x816B, 0x8EEF, 0x8DA3, 0x8EF0, 0x9152,
+	0x8EF1, 0x9996, 0x8EF2, 0x5112, 0x8EF3, 0x53D7, 0x8EF4, 0x546A,
+	0x8EF5, 0x5BFF, 0x8EF6, 0x6388, 0x8EF7, 0x6A39, 0x8EF8, 0x7DAC,
+	0x8EF9, 0x9700, 0x8EFA, 0x56DA, 0x8EFB, 0x53CE, 0x8EFC, 0x5468,
+	0x8F40, 0x5B97, 0x8F41, 0x5C31, 0x8F42, 0x5DDE, 0x8F43, 0x4FEE,
+	0x8F44, 0x6101, 0x8F45, 0x62FE, 0x8F46, 0x6D32, 0x8F47, 0x79C0,
+	0x8F48, 0x79CB, 0x8F49, 0x7D42, 0x8F4A, 0x7E4D, 0x8F4B, 0x7FD2,
+	0x8F4C, 0x81ED, 0x8F4D, 0x821F, 0x8F4E, 0x8490, 0x8F4F, 0x8846,
+	0x8F50, 0x8972, 0x8F51, 0x8B90, 0x8F52, 0x8E74, 0x8F53, 0x8F2F,
+	0x8F54, 0x9031, 0x8F55, 0x914B, 0x8F56, 0x916C, 0x8F57, 0x96C6,
+	0x8F58, 0x919C, 0x8F59, 0x4EC0, 0x8F5A, 0x4F4F, 0x8F5B, 0x5145,
+	0x8F5C, 0x5341, 0x8F5D, 0x5F93, 0x8F5E, 0x620E, 0x8F5F, 0x67D4,
+	0x8F60, 0x6C41, 0x8F61, 0x6E0B, 0x8F62, 0x7363, 0x8F63, 0x7E26,
+	0x8F64, 0x91CD, 0x8F65, 0x9283, 0x8F66, 0x53D4, 0x8F67, 0x5919,
+	0x8F68, 0x5BBF, 0x8F69, 0x6DD1, 0x8F6A, 0x795D, 0x8F6B, 0x7E2E,
+	0x8F6C, 0x7C9B, 0x8F6D, 0x587E, 0x8F6E, 0x719F, 0x8F6F, 0x51FA,
+	0x8F70, 0x8853, 0x8F71, 0x8FF0, 0x8F72, 0x4FCA, 0x8F73, 0x5CFB,
+	0x8F74, 0x6625, 0x8F75, 0x77AC, 0x8F76, 0x7AE3, 0x8F77, 0x821C,
+	0x8F78, 0x99FF, 0x8F79, 0x51C6, 0x8F7A, 0x5FAA, 0x8F7B, 0x65EC,
+	0x8F7C, 0x696F, 0x8F7D, 0x6B89, 0x8F7E, 0x6DF3, 0x8F80, 0x6E96,
+	0x8F81, 0x6F64, 0x8F82, 0x76FE, 0x8F83, 0x7D14, 0x8F84, 0x5DE1,
+	0x8F85, 0x9075, 0x8F86, 0x9187, 0x8F87, 0x9806, 0x8F88, 0x51E6,
+	0x8F89, 0x521D, 0x8F8A, 0x6240, 0x8F8B, 0x6691, 0x8F8C, 0x66D9,
+	0x8F8D, 0x6E1A, 0x8F8E, 0x5EB6, 0x8F8F, 0x7DD2, 0x8F90, 0x7F72,
+	0x8F91, 0x66F8, 0x8F92, 0x85AF, 0x8F93, 0x85F7, 0x8F94, 0x8AF8,
+	0x8F95, 0x52A9, 0x8F96, 0x53D9, 0x8F97, 0x5973, 0x8F98, 0x5E8F,
+	0x8F99, 0x5F90, 0x8F9A, 0x6055, 0x8F9B, 0x92E4, 0x8F9C, 0x9664,
+	0x8F9D, 0x50B7, 0x8F9E, 0x511F, 0x8F9F, 0x52DD, 0x8FA0, 0x5320,
+	0x8FA1, 0x5347, 0x8FA2, 0x53EC, 0x8FA3, 0x54E8, 0x8FA4, 0x5546,
+	0x8FA5, 0x5531, 0x8FA6, 0x5617, 0x8FA7, 0x5968, 0x8FA8, 0x59BE,
+	0x8FA9, 0x5A3C, 0x8FAA, 0x5BB5, 0x8FAB, 0x5C06, 0x8FAC, 0x5C0F,
+	0x8FAD, 0x5C11, 0x8FAE, 0x5C1A, 0x8FAF, 0x5E84, 0x8FB0, 0x5E8A,
+	0x8FB1, 0x5EE0, 0x8FB2, 0x5F70, 0x8FB3, 0x627F, 0x8FB4, 0x6284,
+	0x8FB5, 0x62DB, 0x8FB6, 0x638C, 0x8FB7, 0x6377, 0x8FB8, 0x6607,
+	0x8FB9, 0x660C, 0x8FBA, 0x662D, 0x8FBB, 0x6676, 0x8FBC, 0x677E,
+	0x8FBD, 0x68A2, 0x8FBE, 0x6A1F, 0x8FBF, 0x6A35, 0x8FC0, 0x6CBC,
+	0x8FC1, 0x6D88, 0x8FC2, 0x6E09, 0x8FC3, 0x6E58, 0x8FC4, 0x713C,
+	0x8FC5, 0x7126, 0x8FC6, 0x7167, 0x8FC7, 0x75C7, 0x8FC8, 0x7701,
+	0x8FC9, 0x785D, 0x8FCA, 0x7901, 0x8FCB, 0x7965, 0x8FCC, 0x79F0,
+	0x8FCD, 0x7AE0, 0x8FCE, 0x7B11, 0x8FCF, 0x7CA7, 0x8FD0, 0x7D39,
+	0x8FD1, 0x8096, 0x8FD2, 0x83D6, 0x8FD3, 0x848B, 0x8FD4, 0x8549,
+	0x8FD5, 0x885D, 0x8FD6, 0x88F3, 0x8FD7, 0x8A1F, 0x8FD8, 0x8A3C,
+	0x8FD9, 0x8A54, 0x8FDA, 0x8A73, 0x8FDB, 0x8C61, 0x8FDC, 0x8CDE,
+	0x8FDD, 0x91A4, 0x8FDE, 0x9266, 0x8FDF, 0x937E, 0x8FE0, 0x9418,
+	0x8FE1, 0x969C, 0x8FE2, 0x9798, 0x8FE3, 0x4E0A, 0x8FE4, 0x4E08,
+	0x8FE5, 0x4E1E, 0x8FE6, 0x4E57, 0x8FE7, 0x5197, 0x8FE8, 0x5270,
+	0x8FE9, 0x57CE, 0x8FEA, 0x5834, 0x8FEB, 0x58CC, 0x8FEC, 0x5B22,
+	0x8FED, 0x5E38, 0x8FEE, 0x60C5, 0x8FEF, 0x64FE, 0x8FF0, 0x6761,
+	0x8FF1, 0x6756, 0x8FF2, 0x6D44, 0x8FF3, 0x72B6, 0x8FF4, 0x7573,
+	0x8FF5, 0x7A63, 0x8FF6, 0x84B8, 0x8FF7, 0x8B72, 0x8FF8, 0x91B8,
+	0x8FF9, 0x9320, 0x8FFA, 0x5631, 0x8FFB, 0x57F4, 0x8FFC, 0x98FE,
+	0x9040, 0x62ED, 0x9041, 0x690D, 0x9042, 0x6B96, 0x9043, 0x71ED,
+	0x9044, 0x7E54, 0x9045, 0x8077, 0x9046, 0x8272, 0x9047, 0x89E6,
+	0x9048, 0x98DF, 0x9049, 0x8755, 0x904A, 0x8FB1, 0x904B, 0x5C3B,
+	0x904C, 0x4F38, 0x904D, 0x4FE1, 0x904E, 0x4FB5, 0x904F, 0x5507,
+	0x9050, 0x5A20, 0x9051, 0x5BDD, 0x9052, 0x5BE9, 0x9053, 0x5FC3,
+	0x9054, 0x614E, 0x9055, 0x632F, 0x9056, 0x65B0, 0x9057, 0x664B,
+	0x9058, 0x68EE, 0x9059, 0x699B, 0x905A, 0x6D78, 0x905B, 0x6DF1,
+	0x905C, 0x7533, 0x905D, 0x75B9, 0x905E, 0x771F, 0x905F, 0x795E,
+	0x9060, 0x79E6, 0x9061, 0x7D33, 0x9062, 0x81E3, 0x9063, 0x82AF,
+	0x9064, 0x85AA, 0x9065, 0x89AA, 0x9066, 0x8A3A, 0x9067, 0x8EAB,
+	0x9068, 0x8F9B, 0x9069, 0x9032, 0x906A, 0x91DD, 0x906B, 0x9707,
+	0x906C, 0x4EBA, 0x906D, 0x4EC1, 0x906E, 0x5203, 0x906F, 0x5875,
+	0x9070, 0x58EC, 0x9071, 0x5C0B, 0x9072, 0x751A, 0x9073, 0x5C3D,
+	0x9074, 0x814E, 0x9075, 0x8A0A, 0x9076, 0x8FC5, 0x9077, 0x9663,
+	0x9078, 0x976D, 0x9079, 0x7B25, 0x907A, 0x8ACF, 0x907B, 0x9808,
+	0x907C, 0x9162, 0x907D, 0x56F3, 0x907E, 0x53A8, 0x9080, 0x9017,
+	0x9081, 0x5439, 0x9082, 0x5782, 0x9083, 0x5E25, 0x9084, 0x63A8,
+	0x9085, 0x6C34, 0x9086, 0x708A, 0x9087, 0x7761, 0x9088, 0x7C8B,
+	0x9089, 0x7FE0, 0x908A, 0x8870, 0x908B, 0x9042, 0x908C, 0x9154,
+	0x908D, 0x9310, 0x908E, 0x9318, 0x908F, 0x968F, 0x9090, 0x745E,
+	0x9091, 0x9AC4, 0x9092, 0x5D07, 0x9093, 0x5D69, 0x9094, 0x6570,
+	0x9095, 0x67A2, 0x9096, 0x8DA8, 0x9097, 0x96DB, 0x9098, 0x636E,
+	0x9099, 0x6749, 0x909A, 0x6919, 0x909B, 0x83C5, 0x909C, 0x9817,
+	0x909D, 0x96C0, 0x909E, 0x88FE, 0x909F, 0x6F84, 0x90A0, 0x647A,
+	0x90A1, 0x5BF8, 0x90A2, 0x4E16, 0x90A3, 0x702C, 0x90A4, 0x755D,
+	0x90A5, 0x662F, 0x90A6, 0x51C4, 0x90A7, 0x5236, 0x90A8, 0x52E2,
+	0x90A9, 0x59D3, 0x90AA, 0x5F81, 0x90AB, 0x6027, 0x90AC, 0x6210,
+	0x90AD, 0x653F, 0x90AE, 0x6574, 0x90AF, 0x661F, 0x90B0, 0x6674,
+	0x90B1, 0x68F2, 0x90B2, 0x6816, 0x90B3, 0x6B63, 0x90B4, 0x6E05,
+	0x90B5, 0x7272, 0x90B6, 0x751F, 0x90B7, 0x76DB, 0x90B8, 0x7CBE,
+	0x90B9, 0x8056, 0x90BA, 0x58F0, 0x90BB, 0x88FD, 0x90BC, 0x897F,
+	0x90BD, 0x8AA0, 0x90BE, 0x8A93, 0x90BF, 0x8ACB, 0x90C0, 0x901D,
+	0x90C1, 0x9192, 0x90C2, 0x9752, 0x90C3, 0x9759, 0x90C4, 0x6589,
+	0x90C5, 0x7A0E, 0x90C6, 0x8106, 0x90C7, 0x96BB, 0x90C8, 0x5E2D,
+	0x90C9, 0x60DC, 0x90CA, 0x621A, 0x90CB, 0x65A5, 0x90CC, 0x6614,
+	0x90CD, 0x6790, 0x90CE, 0x77F3, 0x90CF, 0x7A4D, 0x90D0, 0x7C4D,
+	0x90D1, 0x7E3E, 0x90D2, 0x810A, 0x90D3, 0x8CAC, 0x90D4, 0x8D64,
+	0x90D5, 0x8DE1, 0x90D6, 0x8E5F, 0x90D7, 0x78A9, 0x90D8, 0x5207,
+	0x90D9, 0x62D9, 0x90DA, 0x63A5, 0x90DB, 0x6442, 0x90DC, 0x6298,
+	0x90DD, 0x8A2D, 0x90DE, 0x7A83, 0x90DF, 0x7BC0, 0x90E0, 0x8AAC,
+	0x90E1, 0x96EA, 0x90E2, 0x7D76, 0x90E3, 0x820C, 0x90E4, 0x8749,
+	0x90E5, 0x4ED9, 0x90E6, 0x5148, 0x90E7, 0x5343, 0x90E8, 0x5360,
+	0x90E9, 0x5BA3, 0x90EA, 0x5C02, 0x90EB, 0x5C16, 0x90EC, 0x5DDD,
+	0x90ED, 0x6226, 0x90EE, 0x6247, 0x90EF, 0x64B0, 0x90F0, 0x6813,
+	0x90F1, 0x6834, 0x90F2, 0x6CC9, 0x90F3, 0x6D45, 0x90F4, 0x6D17,
+	0x90F5, 0x67D3, 0x90F6, 0x6F5C, 0x90F7, 0x714E, 0x90F8, 0x717D,
+	0x90F9, 0x65CB, 0x90FA, 0x7A7F, 0x90FB, 0x7BAD, 0x90FC, 0x7DDA,
+	0x9140, 0x7E4A, 0x9141, 0x7FA8, 0x9142, 0x817A, 0x9143, 0x821B,
+	0x9144, 0x8239, 0x9145, 0x85A6, 0x9146, 0x8A6E, 0x9147, 0x8CCE,
+	0x9148, 0x8DF5, 0x9149, 0x9078, 0x914A, 0x9077, 0x914B, 0x92AD,
+	0x914C, 0x9291, 0x914D, 0x9583, 0x914E, 0x9BAE, 0x914F, 0x524D,
+	0x9150, 0x5584, 0x9151, 0x6F38, 0x9152, 0x7136, 0x9153, 0x5168,
+	0x9154, 0x7985, 0x9155, 0x7E55, 0x9156, 0x81B3, 0x9157, 0x7CCE,
+	0x9158, 0x564C, 0x9159, 0x5851, 0x915A, 0x5CA8, 0x915B, 0x63AA,
+	0x915C, 0x66FE, 0x915D, 0x66FD, 0x915E, 0x695A, 0x915F, 0x72D9,
+	0x9160, 0x758F, 0x9161, 0x758E, 0x9162, 0x790E, 0x9163, 0x7956,
+	0x9164, 0x79DF, 0x9165, 0x7C97, 0x9166, 0x7D20, 0x9167, 0x7D44,
+	0x9168, 0x8607, 0x9169, 0x8A34, 0x916A, 0x963B, 0x916B, 0x9061,
+	0x916C, 0x9F20, 0x916D, 0x50E7, 0x916E, 0x5275, 0x916F, 0x53CC,
+	0x9170, 0x53E2, 0x9171, 0x5009, 0x9172, 0x55AA, 0x9173, 0x58EE,
+	0x9174, 0x594F, 0x9175, 0x723D, 0x9176, 0x5B8B, 0x9177, 0x5C64,
+	0x9178, 0x531D, 0x9179, 0x60E3, 0x917A, 0x60F3, 0x917B, 0x635C,
+	0x917C, 0x6383, 0x917D, 0x633F, 0x917E, 0x63BB, 0x9180, 0x64CD,
+	0x9181, 0x65E9, 0x9182, 0x66F9, 0x9183, 0x5DE3, 0x9184, 0x69CD,
+	0x9185, 0x69FD, 0x9186, 0x6F15, 0x9187, 0x71E5, 0x9188, 0x4E89,
+	0x9189, 0x75E9, 0x918A, 0x76F8, 0x918B, 0x7A93, 0x918C, 0x7CDF,
+	0x918D, 0x7DCF, 0x918E, 0x7D9C, 0x918F, 0x8061, 0x9190, 0x8349,
+	0x9191, 0x8358, 0x9192, 0x846C, 0x9193, 0x84BC, 0x9194, 0x85FB,
+	0x9195, 0x88C5, 0x9196, 0x8D70, 0x9197, 0x9001, 0x9198, 0x906D,
+	0x9199, 0x9397, 0x919A, 0x971C, 0x919B, 0x9A12, 0x919C, 0x50CF,
+	0x919D, 0x5897, 0x919E, 0x618E, 0x919F, 0x81D3, 0x91A0, 0x8535,
+	0x91A1, 0x8D08, 0x91A2, 0x9020, 0x91A3, 0x4FC3, 0x91A4, 0x5074,
+	0x91A5, 0x5247, 0x91A6, 0x5373, 0x91A7, 0x606F, 0x91A8, 0x6349,
+	0x91A9, 0x675F, 0x91AA, 0x6E2C, 0x91AB, 0x8DB3, 0x91AC, 0x901F,
+	0x91AD, 0x4FD7, 0x91AE, 0x5C5E, 0x91AF, 0x8CCA, 0x91B0, 0x65CF,
+	0x91B1, 0x7D9A, 0x91B2, 0x5352, 0x91B3, 0x8896, 0x91B4, 0x5176,
+	0x91B5, 0x63C3, 0x91B6, 0x5B58, 0x91B7, 0x5B6B, 0x91B8, 0x5C0A,
+	0x91B9, 0x640D, 0x91BA, 0x6751, 0x91BB, 0x905C, 0x91BC, 0x4ED6,
+	0x91BD, 0x591A, 0x91BE, 0x592A, 0x91BF, 0x6C70, 0x91C0, 0x8A51,
+	0x91C1, 0x553E, 0x91C2, 0x5815, 0x91C3, 0x59A5, 0x91C4, 0x60F0,
+	0x91C5, 0x6253, 0x91C6, 0x67C1, 0x91C7, 0x8235, 0x91C8, 0x6955,
+	0x91C9, 0x9640, 0x91CA, 0x99C4, 0x91CB, 0x9A28, 0x91CC, 0x4F53,
+	0x91CD, 0x5806, 0x91CE, 0x5BFE, 0x91CF, 0x8010, 0x91D0, 0x5CB1,
+	0x91D1, 0x5E2F, 0x91D2, 0x5F85, 0x91D3, 0x6020, 0x91D4, 0x614B,
+	0x91D5, 0x6234, 0x91D6, 0x66FF, 0x91D7, 0x6CF0, 0x91D8, 0x6EDE,
+	0x91D9, 0x80CE, 0x91DA, 0x817F, 0x91DB, 0x82D4, 0x91DC, 0x888B,
+	0x91DD, 0x8CB8, 0x91DE, 0x9000, 0x91DF, 0x902E, 0x91E0, 0x968A,
+	0x91E1, 0x9EDB, 0x91E2, 0x9BDB, 0x91E3, 0x4EE3, 0x91E4, 0x53F0,
+	0x91E5, 0x5927, 0x91E6, 0x7B2C, 0x91E7, 0x918D, 0x91E8, 0x984C,
+	0x91E9, 0x9DF9, 0x91EA, 0x6EDD, 0x91EB, 0x7027, 0x91EC, 0x5353,
+	0x91ED, 0x5544, 0x91EE, 0x5B85, 0x91EF, 0x6258, 0x91F0, 0x629E,
+	0x91F1, 0x62D3, 0x91F2, 0x6CA2, 0x91F3, 0x6FEF, 0x91F4, 0x7422,
+	0x91F5, 0x8A17, 0x91F6, 0x9438, 0x91F7, 0x6FC1, 0x91F8, 0x8AFE,
+	0x91F9, 0x8338, 0x91FA, 0x51E7, 0x91FB, 0x86F8, 0x91FC, 0x53EA,
+	0x9240, 0x53E9, 0x9241, 0x4F46, 0x9242, 0x9054, 0x9243, 0x8FB0,
+	0x9244, 0x596A, 0x9245, 0x8131, 0x9246, 0x5DFD, 0x9247, 0x7AEA,
+	0x9248, 0x8FBF, 0x9249, 0x68DA, 0x924A, 0x8C37, 0x924B, 0x72F8,
+	0x924C, 0x9C48, 0x924D, 0x6A3D, 0x924E, 0x8AB0, 0x924F, 0x4E39,
+	0x9250, 0x5358, 0x9251, 0x5606, 0x9252, 0x5766, 0x9253, 0x62C5,
+	0x9254, 0x63A2, 0x9255, 0x65E6, 0x9256, 0x6B4E, 0x9257, 0x6DE1,
+	0x9258, 0x6E5B, 0x9259, 0x70AD, 0x925A, 0x77ED, 0x925B, 0x7AEF,
+	0x925C, 0x7BAA, 0x925D, 0x7DBB, 0x925E, 0x803D, 0x925F, 0x80C6,
+	0x9260, 0x86CB, 0x9261, 0x8A95, 0x9262, 0x935B, 0x9263, 0x56E3,
+	0x9264, 0x58C7, 0x9265, 0x5F3E, 0x9266, 0x65AD, 0x9267, 0x6696,
+	0x9268, 0x6A80, 0x9269, 0x6BB5, 0x926A, 0x7537, 0x926B, 0x8AC7,
+	0x926C, 0x5024, 0x926D, 0x77E5, 0x926E, 0x5730, 0x926F, 0x5F1B,
+	0x9270, 0x6065, 0x9271, 0x667A, 0x9272, 0x6C60, 0x9273, 0x75F4,
+	0x9274, 0x7A1A, 0x9275, 0x7F6E, 0x9276, 0x81F4, 0x9277, 0x8718,
+	0x9278, 0x9045, 0x9279, 0x99B3, 0x927A, 0x7BC9, 0x927B, 0x755C,
+	0x927C, 0x7AF9, 0x927D, 0x7B51, 0x927E, 0x84C4, 0x9280, 0x9010,
+	0x9281, 0x79E9, 0x9282, 0x7A92, 0x9283, 0x8336, 0x9284, 0x5AE1,
+	0x9285, 0x7740, 0x9286, 0x4E2D, 0x9287, 0x4EF2, 0x9288, 0x5B99,
+	0x9289, 0x5FE0, 0x928A, 0x62BD, 0x928B, 0x663C, 0x928C, 0x67F1,
+	0x928D, 0x6CE8, 0x928E, 0x866B, 0x928F, 0x8877, 0x9290, 0x8A3B,
+	0x9291, 0x914E, 0x9292, 0x92F3, 0x9293, 0x99D0, 0x9294, 0x6A17,
+	0x9295, 0x7026, 0x9296, 0x732A, 0x9297, 0x82E7, 0x9298, 0x8457,
+	0x9299, 0x8CAF, 0x929A, 0x4E01, 0x929B, 0x5146, 0x929C, 0x51CB,
+	0x929D, 0x558B, 0x929E, 0x5BF5, 0x929F, 0x5E16, 0x92A0, 0x5E33,
+	0x92A1, 0x5E81, 0x92A2, 0x5F14, 0x92A3, 0x5F35, 0x92A4, 0x5F6B,
+	0x92A5, 0x5FB4, 0x92A6, 0x61F2, 0x92A7, 0x6311, 0x92A8, 0x66A2,
+	0x92A9, 0x671D, 0x92AA, 0x6F6E, 0x92AB, 0x7252, 0x92AC, 0x753A,
+	0x92AD, 0x773A, 0x92AE, 0x8074, 0x92AF, 0x8139, 0x92B0, 0x8178,
+	0x92B1, 0x8776, 0x92B2, 0x8ABF, 0x92B3, 0x8ADC, 0x92B4, 0x8D85,
+	0x92B5, 0x8DF3, 0x92B6, 0x929A, 0x92B7, 0x9577, 0x92B8, 0x9802,
+	0x92B9, 0x9CE5, 0x92BA, 0x52C5, 0x92BB, 0x6357, 0x92BC, 0x76F4,
+	0x92BD, 0x6715, 0x92BE, 0x6C88, 0x92BF, 0x73CD, 0x92C0, 0x8CC3,
+	0x92C1, 0x93AE, 0x92C2, 0x9673, 0x92C3, 0x6D25, 0x92C4, 0x589C,
+	0x92C5, 0x690E, 0x92C6, 0x69CC, 0x92C7, 0x8FFD, 0x92C8, 0x939A,
+	0x92C9, 0x75DB, 0x92CA, 0x901A, 0x92CB, 0x585A, 0x92CC, 0x6802,
+	0x92CD, 0x63B4, 0x92CE, 0x69FB, 0x92CF, 0x4F43, 0x92D0, 0x6F2C,
+	0x92D1, 0x67D8, 0x92D2, 0x8FBB, 0x92D3, 0x8526, 0x92D4, 0x7DB4,
+	0x92D5, 0x9354, 0x92D6, 0x693F, 0x92D7, 0x6F70, 0x92D8, 0x576A,
+	0x92D9, 0x58F7, 0x92DA, 0x5B2C, 0x92DB, 0x7D2C, 0x92DC, 0x722A,
+	0x92DD, 0x540A, 0x92DE, 0x91E3, 0x92DF, 0x9DB4, 0x92E0, 0x4EAD,
+	0x92E1, 0x4F4E, 0x92E2, 0x505C, 0x92E3, 0x5075, 0x92E4, 0x5243,
+	0x92E5, 0x8C9E, 0x92E6, 0x5448, 0x92E7, 0x5824, 0x92E8, 0x5B9A,
+	0x92E9, 0x5E1D, 0x92EA, 0x5E95, 0x92EB, 0x5EAD, 0x92EC, 0x5EF7,
+	0x92ED, 0x5F1F, 0x92EE, 0x608C, 0x92EF, 0x62B5, 0x92F0, 0x633A,
+	0x92F1, 0x63D0, 0x92F2, 0x68AF, 0x92F3, 0x6C40, 0x92F4, 0x7887,
+	0x92F5, 0x798E, 0x92F6, 0x7A0B, 0x92F7, 0x7DE0, 0x92F8, 0x8247,
+	0x92F9, 0x8A02, 0x92FA, 0x8AE6, 0x92FB, 0x8E44, 0x92FC, 0x9013,
+	0x9340, 0x90B8, 0x9341, 0x912D, 0x9342, 0x91D8, 0x9343, 0x9F0E,
+	0x9344, 0x6CE5, 0x9345, 0x6458, 0x9346, 0x64E2, 0x9347, 0x6575,
+	0x9348, 0x6EF4, 0x9349, 0x7684, 0x934A, 0x7B1B, 0x934B, 0x9069,
+	0x934C, 0x93D1, 0x934D, 0x6EBA, 0x934E, 0x54F2, 0x934F, 0x5FB9,
+	0x9350, 0x64A4, 0x9351, 0x8F4D, 0x9352, 0x8FED, 0x9353, 0x9244,
+	0x9354, 0x5178, 0x9355, 0x586B, 0x9356, 0x5929, 0x9357, 0x5C55,
+	0x9358, 0x5E97, 0x9359, 0x6DFB, 0x935A, 0x7E8F, 0x935B, 0x751C,
+	0x935C, 0x8CBC, 0x935D, 0x8EE2, 0x935E, 0x985B, 0x935F, 0x70B9,
+	0x9360, 0x4F1D, 0x9361, 0x6BBF, 0x9362, 0x6FB1, 0x9363, 0x7530,
+	0x9364, 0x96FB, 0x9365, 0x514E, 0x9366, 0x5410, 0x9367, 0x5835,
+	0x9368, 0x5857, 0x9369, 0x59AC, 0x936A, 0x5C60, 0x936B, 0x5F92,
+	0x936C, 0x6597, 0x936D, 0x675C, 0x936E, 0x6E21, 0x936F, 0x767B,
+	0x9370, 0x83DF, 0x9371, 0x8CED, 0x9372, 0x9014, 0x9373, 0x90FD,
+	0x9374, 0x934D, 0x9375, 0x7825, 0x9376, 0x783A, 0x9377, 0x52AA,
+	0x9378, 0x5EA6, 0x9379, 0x571F, 0x937A, 0x5974, 0x937B, 0x6012,
+	0x937C, 0x5012, 0x937D, 0x515A, 0x937E, 0x51AC, 0x9380, 0x51CD,
+	0x9381, 0x5200, 0x9382, 0x5510, 0x9383, 0x5854, 0x9384, 0x5858,
+	0x9385, 0x5957, 0x9386, 0x5B95, 0x9387, 0x5CF6, 0x9388, 0x5D8B,
+	0x9389, 0x60BC, 0x938A, 0x6295, 0x938B, 0x642D, 0x938C, 0x6771,
+	0x938D, 0x6843, 0x938E, 0x68BC, 0x938F, 0x68DF, 0x9390, 0x76D7,
+	0x9391, 0x6DD8, 0x9392, 0x6E6F, 0x9393, 0x6D9B, 0x9394, 0x706F,
+	0x9395, 0x71C8, 0x9396, 0x5F53, 0x9397, 0x75D8, 0x9398, 0x7977,
+	0x9399, 0x7B49, 0x939A, 0x7B54, 0x939B, 0x7B52, 0x939C, 0x7CD6,
+	0x939D, 0x7D71, 0x939E, 0x5230, 0x939F, 0x8463, 0x93A0, 0x8569,
+	0x93A1, 0x85E4, 0x93A2, 0x8A0E, 0x93A3, 0x8B04, 0x93A4, 0x8C46,
+	0x93A5, 0x8E0F, 0x93A6, 0x9003, 0x93A7, 0x900F, 0x93A8, 0x9419,
+	0x93A9, 0x9676, 0x93AA, 0x982D, 0x93AB, 0x9A30, 0x93AC, 0x95D8,
+	0x93AD, 0x50CD, 0x93AE, 0x52D5, 0x93AF, 0x540C, 0x93B0, 0x5802,
+	0x93B1, 0x5C0E, 0x93B2, 0x61A7, 0x93B3, 0x649E, 0x93B4, 0x6D1E,
+	0x93B5, 0x77B3, 0x93B6, 0x7AE5, 0x93B7, 0x80F4, 0x93B8, 0x8404,
+	0x93B9, 0x9053, 0x93BA, 0x9285, 0x93BB, 0x5CE0, 0x93BC, 0x9D07,
+	0x93BD, 0x533F, 0x93BE, 0x5F97, 0x93BF, 0x5FB3, 0x93C0, 0x6D9C,
+	0x93C1, 0x7279, 0x93C2, 0x7763, 0x93C3, 0x79BF, 0x93C4, 0x7BE4,
+	0x93C5, 0x6BD2, 0x93C6, 0x72EC, 0x93C7, 0x8AAD, 0x93C8, 0x6803,
+	0x93C9, 0x6A61, 0x93CA, 0x51F8, 0x93CB, 0x7A81, 0x93CC, 0x6934,
+	0x93CD, 0x5C4A, 0x93CE, 0x9CF6, 0x93CF, 0x82EB, 0x93D0, 0x5BC5,
+	0x93D1, 0x9149, 0x93D2, 0x701E, 0x93D3, 0x5678, 0x93D4, 0x5C6F,
+	0x93D5, 0x60C7, 0x93D6, 0x6566, 0x93D7, 0x6C8C, 0x93D8, 0x8C5A,
+	0x93D9, 0x9041, 0x93DA, 0x9813, 0x93DB, 0x5451, 0x93DC, 0x66C7,
+	0x93DD, 0x920D, 0x93DE, 0x5948, 0x93DF, 0x90A3, 0x93E0, 0x5185,
+	0x93E1, 0x4E4D, 0x93E2, 0x51EA, 0x93E3, 0x8599, 0x93E4, 0x8B0E,
+	0x93E5, 0x7058, 0x93E6, 0x637A, 0x93E7, 0x934B, 0x93E8, 0x6962,
+	0x93E9, 0x99B4, 0x93EA, 0x7E04, 0x93EB, 0x7577, 0x93EC, 0x5357,
+	0x93ED, 0x6960, 0x93EE, 0x8EDF, 0x93EF, 0x96E3, 0x93F0, 0x6C5D,
+	0x93F1, 0x4E8C, 0x93F2, 0x5C3C, 0x93F3, 0x5F10, 0x93F4, 0x8FE9,
+	0x93F5, 0x5302, 0x93F6, 0x8CD1, 0x93F7, 0x8089, 0x93F8, 0x8679,
+	0x93F9, 0x5EFF, 0x93FA, 0x65E5, 0x93FB, 0x4E73, 0x93FC, 0x5165,
+	0x9440, 0x5982, 0x9441, 0x5C3F, 0x9442, 0x97EE, 0x9443, 0x4EFB,
+	0x9444, 0x598A, 0x9445, 0x5FCD, 0x9446, 0x8A8D, 0x9447, 0x6FE1,
+	0x9448, 0x79B0, 0x9449, 0x7962, 0x944A, 0x5BE7, 0x944B, 0x8471,
+	0x944C, 0x732B, 0x944D, 0x71B1, 0x944E, 0x5E74, 0x944F, 0x5FF5,
+	0x9450, 0x637B, 0x9451, 0x649A, 0x9452, 0x71C3, 0x9453, 0x7C98,
+	0x9454, 0x4E43, 0x9455, 0x5EFC, 0x9456, 0x4E4B, 0x9457, 0x57DC,
+	0x9458, 0x56A2, 0x9459, 0x60A9, 0x945A, 0x6FC3, 0x945B, 0x7D0D,
+	0x945C, 0x80FD, 0x945D, 0x8133, 0x945E, 0x81BF, 0x945F, 0x8FB2,
+	0x9460, 0x8997, 0x9461, 0x86A4, 0x9462, 0x5DF4, 0x9463, 0x628A,
+	0x9464, 0x64AD, 0x9465, 0x8987, 0x9466, 0x6777, 0x9467, 0x6CE2,
+	0x9468, 0x6D3E, 0x9469, 0x7436, 0x946A, 0x7834, 0x946B, 0x5A46,
+	0x946C, 0x7F75, 0x946D, 0x82AD, 0x946E, 0x99AC, 0x946F, 0x4FF3,
+	0x9470, 0x5EC3, 0x9471, 0x62DD, 0x9472, 0x6392, 0x9473, 0x6557,
+	0x9474, 0x676F, 0x9475, 0x76C3, 0x9476, 0x724C, 0x9477, 0x80CC,
+	0x9478, 0x80BA, 0x9479, 0x8F29, 0x947A, 0x914D, 0x947B, 0x500D,
+	0x947C, 0x57F9, 0x947D, 0x5A92, 0x947E, 0x6885, 0x9480, 0x6973,
+	0x9481, 0x7164, 0x9482, 0x72FD, 0x9483, 0x8CB7, 0x9484, 0x58F2,
+	0x9485, 0x8CE0, 0x9486, 0x966A, 0x9487, 0x9019, 0x9488, 0x877F,
+	0x9489, 0x79E4, 0x948A, 0x77E7, 0x948B, 0x8429, 0x948C, 0x4F2F,
+	0x948D, 0x5265, 0x948E, 0x535A, 0x948F, 0x62CD, 0x9490, 0x67CF,
+	0x9491, 0x6CCA, 0x9492, 0x767D, 0x9493, 0x7B94, 0x9494, 0x7C95,
+	0x9495, 0x8236, 0x9496, 0x8584, 0x9497, 0x8FEB, 0x9498, 0x66DD,
+	0x9499, 0x6F20, 0x949A, 0x7206, 0x949B, 0x7E1B, 0x949C, 0x83AB,
+	0x949D, 0x99C1, 0x949E, 0x9EA6, 0x949F, 0x51FD, 0x94A0, 0x7BB1,
+	0x94A1, 0x7872, 0x94A2, 0x7BB8, 0x94A3, 0x8087, 0x94A4, 0x7B48,
+	0x94A5, 0x6AE8, 0x94A6, 0x5E61, 0x94A7, 0x808C, 0x94A8, 0x7551,
+	0x94A9, 0x7560, 0x94AA, 0x516B, 0x94AB, 0x9262, 0x94AC, 0x6E8C,
+	0x94AD, 0x767A, 0x94AE, 0x9197, 0x94AF, 0x9AEA, 0x94B0, 0x4F10,
+	0x94B1, 0x7F70, 0x94B2, 0x629C, 0x94B3, 0x7B4F, 0x94B4, 0x95A5,
+	0x94B5, 0x9CE9, 0x94B6, 0x567A, 0x94B7, 0x5859, 0x94B8, 0x86E4,
+	0x94B9, 0x96BC, 0x94BA, 0x4F34, 0x94BB, 0x5224, 0x94BC, 0x534A,
+	0x94BD, 0x53CD, 0x94BE, 0x53DB, 0x94BF, 0x5E06, 0x94C0, 0x642C,
+	0x94C1, 0x6591, 0x94C2, 0x677F, 0x94C3, 0x6C3E, 0x94C4, 0x6C4E,
+	0x94C5, 0x7248, 0x94C6, 0x72AF, 0x94C7, 0x73ED, 0x94C8, 0x7554,
+	0x94C9, 0x7E41, 0x94CA, 0x822C, 0x94CB, 0x85E9, 0x94CC, 0x8CA9,
+	0x94CD, 0x7BC4, 0x94CE, 0x91C6, 0x94CF, 0x7169, 0x94D0, 0x9812,
+	0x94D1, 0x98EF, 0x94D2, 0x633D, 0x94D3, 0x6669, 0x94D4, 0x756A,
+	0x94D5, 0x76E4, 0x94D6, 0x78D0, 0x94D7, 0x8543, 0x94D8, 0x86EE,
+	0x94D9, 0x532A, 0x94DA, 0x5351, 0x94DB, 0x5426, 0x94DC, 0x5983,
+	0x94DD, 0x5E87, 0x94DE, 0x5F7C, 0x94DF, 0x60B2, 0x94E0, 0x6249,
+	0x94E1, 0x6279, 0x94E2, 0x62AB, 0x94E3, 0x6590, 0x94E4, 0x6BD4,
+	0x94E5, 0x6CCC, 0x94E6, 0x75B2, 0x94E7, 0x76AE, 0x94E8, 0x7891,
+	0x94E9, 0x79D8, 0x94EA, 0x7DCB, 0x94EB, 0x7F77, 0x94EC, 0x80A5,
+	0x94ED, 0x88AB, 0x94EE, 0x8AB9, 0x94EF, 0x8CBB, 0x94F0, 0x907F,
+	0x94F1, 0x975E, 0x94F2, 0x98DB, 0x94F3, 0x6A0B, 0x94F4, 0x7C38,
+	0x94F5, 0x5099, 0x94F6, 0x5C3E, 0x94F7, 0x5FAE, 0x94F8, 0x6787,
+	0x94F9, 0x6BD8, 0x94FA, 0x7435, 0x94FB, 0x7709, 0x94FC, 0x7F8E,
+	0x9540, 0x9F3B, 0x9541, 0x67CA, 0x9542, 0x7A17, 0x9543, 0x5339,
+	0x9544, 0x758B, 0x9545, 0x9AED, 0x9546, 0x5F66, 0x9547, 0x819D,
+	0x9548, 0x83F1, 0x9549, 0x8098, 0x954A, 0x5F3C, 0x954B, 0x5FC5,
+	0x954C, 0x7562, 0x954D, 0x7B46, 0x954E, 0x903C, 0x954F, 0x6867,
+	0x9550, 0x59EB, 0x9551, 0x5A9B, 0x9552, 0x7D10, 0x9553, 0x767E,
+	0x9554, 0x8B2C, 0x9555, 0x4FF5, 0x9556, 0x5F6A, 0x9557, 0x6A19,
+	0x9558, 0x6C37, 0x9559, 0x6F02, 0x955A, 0x74E2, 0x955B, 0x7968,
+	0x955C, 0x8868, 0x955D, 0x8A55, 0x955E, 0x8C79, 0x955F, 0x5EDF,
+	0x9560, 0x63CF, 0x9561, 0x75C5, 0x9562, 0x79D2, 0x9563, 0x82D7,
+	0x9564, 0x9328, 0x9565, 0x92F2, 0x9566, 0x849C, 0x9567, 0x86ED,
+	0x9568, 0x9C2D, 0x9569, 0x54C1, 0x956A, 0x5F6C, 0x956B, 0x658C,
+	0x956C, 0x6D5C, 0x956D, 0x7015, 0x956E, 0x8CA7, 0x956F, 0x8CD3,
+	0x9570, 0x983B, 0x9571, 0x654F, 0x9572, 0x74F6, 0x9573, 0x4E0D,
+	0x9574, 0x4ED8, 0x9575, 0x57E0, 0x9576, 0x592B, 0x9577, 0x5A66,
+	0x9578, 0x5BCC, 0x9579, 0x51A8, 0x957A, 0x5E03, 0x957B, 0x5E9C,
+	0x957C, 0x6016, 0x957D, 0x6276, 0x957E, 0x6577, 0x9580, 0x65A7,
+	0x9581, 0x666E, 0x9582, 0x6D6E, 0x9583, 0x7236, 0x9584, 0x7B26,
+	0x9585, 0x8150, 0x9586, 0x819A, 0x9587, 0x8299, 0x9588, 0x8B5C,
+	0x9589, 0x8CA0, 0x958A, 0x8CE6, 0x958B, 0x8D74, 0x958C, 0x961C,
+	0x958D, 0x9644, 0x958E, 0x4FAE, 0x958F, 0x64AB, 0x9590, 0x6B66,
+	0x9591, 0x821E, 0x9592, 0x8461, 0x9593, 0x856A, 0x9594, 0x90E8,
+	0x9595, 0x5C01, 0x9596, 0x6953, 0x9597, 0x98A8, 0x9598, 0x847A,
+	0x9599, 0x8557, 0x959A, 0x4F0F, 0x959B, 0x526F, 0x959C, 0x5FA9,
+	0x959D, 0x5E45, 0x959E, 0x670D, 0x959F, 0x798F, 0x95A0, 0x8179,
+	0x95A1, 0x8907, 0x95A2, 0x8986, 0x95A3, 0x6DF5, 0x95A4, 0x5F17,
+	0x95A5, 0x6255, 0x95A6, 0x6CB8, 0x95A7, 0x4ECF, 0x95A8, 0x7269,
+	0x95A9, 0x9B92, 0x95AA, 0x5206, 0x95AB, 0x543B, 0x95AC, 0x5674,
+	0x95AD, 0x58B3, 0x95AE, 0x61A4, 0x95AF, 0x626E, 0x95B0, 0x711A,
+	0x95B1, 0x596E, 0x95B2, 0x7C89, 0x95B3, 0x7CDE, 0x95B4, 0x7D1B,
+	0x95B5, 0x96F0, 0x95B6, 0x6587, 0x95B7, 0x805E, 0x95B8, 0x4E19,
+	0x95B9, 0x4F75, 0x95BA, 0x5175, 0x95BB, 0x5840, 0x95BC, 0x5E63,
+	0x95BD, 0x5E73, 0x95BE, 0x5F0A, 0x95BF, 0x67C4, 0x95C0, 0x4E26,
+	0x95C1, 0x853D, 0x95C2, 0x9589, 0x95C3, 0x965B, 0x95C4, 0x7C73,
+	0x95C5, 0x9801, 0x95C6, 0x50FB, 0x95C7, 0x58C1, 0x95C8, 0x7656,
+	0x95C9, 0x78A7, 0x95CA, 0x5225, 0x95CB, 0x77A5, 0x95CC, 0x8511,
+	0x95CD, 0x7B86, 0x95CE, 0x504F, 0x95CF, 0x5909, 0x95D0, 0x7247,
+	0x95D1, 0x7BC7, 0x95D2, 0x7DE8, 0x95D3, 0x8FBA, 0x95D4, 0x8FD4,
+	0x95D5, 0x904D, 0x95D6, 0x4FBF, 0x95D7, 0x52C9, 0x95D8, 0x5A29,
+	0x95D9, 0x5F01, 0x95DA, 0x97AD, 0x95DB, 0x4FDD, 0x95DC, 0x8217,
+	0x95DD, 0x92EA, 0x95DE, 0x5703, 0x95DF, 0x6355, 0x95E0, 0x6B69,
+	0x95E1, 0x752B, 0x95E2, 0x88DC, 0x95E3, 0x8F14, 0x95E4, 0x7A42,
+	0x95E5, 0x52DF, 0x95E6, 0x5893, 0x95E7, 0x6155, 0x95E8, 0x620A,
+	0x95E9, 0x66AE, 0x95EA, 0x6BCD, 0x95EB, 0x7C3F, 0x95EC, 0x83E9,
+	0x95ED, 0x5023, 0x95EE, 0x4FF8, 0x95EF, 0x5305, 0x95F0, 0x5446,
+	0x95F1, 0x5831, 0x95F2, 0x5949, 0x95F3, 0x5B9D, 0x95F4, 0x5CF0,
+	0x95F5, 0x5CEF, 0x95F6, 0x5D29, 0x95F7, 0x5E96, 0x95F8, 0x62B1,
+	0x95F9, 0x6367, 0x95FA, 0x653E, 0x95FB, 0x65B9, 0x95FC, 0x670B,
+	0x9640, 0x6CD5, 0x9641, 0x6CE1, 0x9642, 0x70F9, 0x9643, 0x7832,
+	0x9644, 0x7E2B, 0x9645, 0x80DE, 0x9646, 0x82B3, 0x9647, 0x840C,
+	0x9648, 0x84EC, 0x9649, 0x8702, 0x964A, 0x8912, 0x964B, 0x8A2A,
+	0x964C, 0x8C4A, 0x964D, 0x90A6, 0x964E, 0x92D2, 0x964F, 0x98FD,
+	0x9650, 0x9CF3, 0x9651, 0x9D6C, 0x9652, 0x4E4F, 0x9653, 0x4EA1,
+	0x9654, 0x508D, 0x9655, 0x5256, 0x9656, 0x574A, 0x9657, 0x59A8,
+	0x9658, 0x5E3D, 0x9659, 0x5FD8, 0x965A, 0x5FD9, 0x965B, 0x623F,
+	0x965C, 0x66B4, 0x965D, 0x671B, 0x965E, 0x67D0, 0x965F, 0x68D2,
+	0x9660, 0x5192, 0x9661, 0x7D21, 0x9662, 0x80AA, 0x9663, 0x81A8,
+	0x9664, 0x8B00, 0x9665, 0x8C8C, 0x9666, 0x8CBF, 0x9667, 0x927E,
+	0x9668, 0x9632, 0x9669, 0x5420, 0x966A, 0x982C, 0x966B, 0x5317,
+	0x966C, 0x50D5, 0x966D, 0x535C, 0x966E, 0x58A8, 0x966F, 0x64B2,
+	0x9670, 0x6734, 0x9671, 0x7267, 0x9672, 0x7766, 0x9673, 0x7A46,
+	0x9674, 0x91E6, 0x9675, 0x52C3, 0x9676, 0x6CA1, 0x9677, 0x6B86,
+	0x9678, 0x5800, 0x9679, 0x5E4C, 0x967A, 0x5954, 0x967B, 0x672C,
+	0x967C, 0x7FFB, 0x967D, 0x51E1, 0x967E, 0x76C6, 0x9680, 0x6469,
+	0x9681, 0x78E8, 0x9682, 0x9B54, 0x9683, 0x9EBB, 0x9684, 0x57CB,
+	0x9685, 0x59B9, 0x9686, 0x6627, 0x9687, 0x679A, 0x9688, 0x6BCE,
+	0x9689, 0x54E9, 0x968A, 0x69D9, 0x968B, 0x5E55, 0x968C, 0x819C,
+	0x968D, 0x6795, 0x968E, 0x9BAA, 0x968F, 0x67FE, 0x9690, 0x9C52,
+	0x9691, 0x685D, 0x9692, 0x4EA6, 0x9693, 0x4FE3, 0x9694, 0x53C8,
+	0x9695, 0x62B9, 0x9696, 0x672B, 0x9697, 0x6CAB, 0x9698, 0x8FC4,
+	0x9699, 0x4FAD, 0x969A, 0x7E6D, 0x969B, 0x9EBF, 0x969C, 0x4E07,
+	0x969D, 0x6162, 0x969E, 0x6E80, 0x969F, 0x6F2B, 0x96A0, 0x8513,
+	0x96A1, 0x5473, 0x96A2, 0x672A, 0x96A3, 0x9B45, 0x96A4, 0x5DF3,
+	0x96A5, 0x7B95, 0x96A6, 0x5CAC, 0x96A7, 0x5BC6, 0x96A8, 0x871C,
+	0x96A9, 0x6E4A, 0x96AA, 0x84D1, 0x96AB, 0x7A14, 0x96AC, 0x8108,
+	0x96AD, 0x5999, 0x96AE, 0x7C8D, 0x96AF, 0x6C11, 0x96B0, 0x7720,
+	0x96B1, 0x52D9, 0x96B2, 0x5922, 0x96B3, 0x7121, 0x96B4, 0x725F,
+	0x96B5, 0x77DB, 0x96B6, 0x9727, 0x96B7, 0x9D61, 0x96B8, 0x690B,
+	0x96B9, 0x5A7F, 0x96BA, 0x5A18, 0x96BB, 0x51A5, 0x96BC, 0x540D,
+	0x96BD, 0x547D, 0x96BE, 0x660E, 0x96BF, 0x76DF, 0x96C0, 0x8FF7,
+	0x96C1, 0x9298, 0x96C2, 0x9CF4, 0x96C3, 0x59EA, 0x96C4, 0x725D,
+	0x96C5, 0x6EC5, 0x96C6, 0x514D, 0x96C7, 0x68C9, 0x96C8, 0x7DBF,
+	0x96C9, 0x7DEC, 0x96CA, 0x9762, 0x96CB, 0x9EBA, 0x96CC, 0x6478,
+	0x96CD, 0x6A21, 0x96CE, 0x8302, 0x96CF, 0x5984, 0x96D0, 0x5B5F,
+	0x96D1, 0x6BDB, 0x96D2, 0x731B, 0x96D3, 0x76F2, 0x96D4, 0x7DB2,
+	0x96D5, 0x8017, 0x96D6, 0x8499, 0x96D7, 0x5132, 0x96D8, 0x6728,
+	0x96D9, 0x9ED9, 0x96DA, 0x76EE, 0x96DB, 0x6762, 0x96DC, 0x52FF,
+	0x96DD, 0x9905, 0x96DE, 0x5C24, 0x96DF, 0x623B, 0x96E0, 0x7C7E,
+	0x96E1, 0x8CB0, 0x96E2, 0x554F, 0x96E3, 0x60B6, 0x96E4, 0x7D0B,
+	0x96E5, 0x9580, 0x96E6, 0x5301, 0x96E7, 0x4E5F, 0x96E8, 0x51B6,
+	0x96E9, 0x591C, 0x96EA, 0x723A, 0x96EB, 0x8036, 0x96EC, 0x91CE,
+	0x96ED, 0x5F25, 0x96EE, 0x77E2, 0x96EF, 0x5384, 0x96F0, 0x5F79,
+	0x96F1, 0x7D04, 0x96F2, 0x85AC, 0x96F3, 0x8A33, 0x96F4, 0x8E8D,
+	0x96F5, 0x9756, 0x96F6, 0x67F3, 0x96F7, 0x85AE, 0x96F8, 0x9453,
+	0x96F9, 0x6109, 0x96FA, 0x6108, 0x96FB, 0x6CB9, 0x96FC, 0x7652,
+	0x9740, 0x8AED, 0x9741, 0x8F38, 0x9742, 0x552F, 0x9743, 0x4F51,
+	0x9744, 0x512A, 0x9745, 0x52C7, 0x9746, 0x53CB, 0x9747, 0x5BA5,
+	0x9748, 0x5E7D, 0x9749, 0x60A0, 0x974A, 0x6182, 0x974B, 0x63D6,
+	0x974C, 0x6709, 0x974D, 0x67DA, 0x974E, 0x6E67, 0x974F, 0x6D8C,
+	0x9750, 0x7336, 0x9751, 0x7337, 0x9752, 0x7531, 0x9753, 0x7950,
+	0x9754, 0x88D5, 0x9755, 0x8A98, 0x9756, 0x904A, 0x9757, 0x9091,
+	0x9758, 0x90F5, 0x9759, 0x96C4, 0x975A, 0x878D, 0x975B, 0x5915,
+	0x975C, 0x4E88, 0x975D, 0x4F59, 0x975E, 0x4E0E, 0x975F, 0x8A89,
+	0x9760, 0x8F3F, 0x9761, 0x9810, 0x9762, 0x50AD, 0x9763, 0x5E7C,
+	0x9764, 0x5996, 0x9765, 0x5BB9, 0x9766, 0x5EB8, 0x9767, 0x63DA,
+	0x9768, 0x63FA, 0x9769, 0x64C1, 0x976A, 0x66DC, 0x976B, 0x694A,
+	0x976C, 0x69D8, 0x976D, 0x6D0B, 0x976E, 0x6EB6, 0x976F, 0x7194,
+	0x9770, 0x7528, 0x9771, 0x7AAF, 0x9772, 0x7F8A, 0x9773, 0x8000,
+	0x9774, 0x8449, 0x9775, 0x84C9, 0x9776, 0x8981, 0x9777, 0x8B21,
+	0x9778, 0x8E0A, 0x9779, 0x9065, 0x977A, 0x967D, 0x977B, 0x990A,
+	0x977C, 0x617E, 0x977D, 0x6291, 0x977E, 0x6B32, 0x9780, 0x6C83,
+	0x9781, 0x6D74, 0x9782, 0x7FCC, 0x9783, 0x7FFC, 0x9784, 0x6DC0,
+	0x9785, 0x7F85, 0x9786, 0x87BA, 0x9787, 0x88F8, 0x9788, 0x6765,
+	0x9789, 0x83B1, 0x978A, 0x983C, 0x978B, 0x96F7, 0x978C, 0x6D1B,
+	0x978D, 0x7D61, 0x978E, 0x843D, 0x978F, 0x916A, 0x9790, 0x4E71,
+	0x9791, 0x5375, 0x9792, 0x5D50, 0x9793, 0x6B04, 0x9794, 0x6FEB,
+	0x9795, 0x85CD, 0x9796, 0x862D, 0x9797, 0x89A7, 0x9798, 0x5229,
+	0x9799, 0x540F, 0x979A, 0x5C65, 0x979B, 0x674E, 0x979C, 0x68A8,
+	0x979D, 0x7406, 0x979E, 0x7483, 0x979F, 0x75E2, 0x97A0, 0x88CF,
+	0x97A1, 0x88E1, 0x97A2, 0x91CC, 0x97A3, 0x96E2, 0x97A4, 0x9678,
+	0x97A5, 0x5F8B, 0x97A6, 0x7387, 0x97A7, 0x7ACB, 0x97A8, 0x844E,
+	0x97A9, 0x63A0, 0x97AA, 0x7565, 0x97AB, 0x5289, 0x97AC, 0x6D41,
+	0x97AD, 0x6E9C, 0x97AE, 0x7409, 0x97AF, 0x7559, 0x97B0, 0x786B,
+	0x97B1, 0x7C92, 0x97B2, 0x9686, 0x97B3, 0x7ADC, 0x97B4, 0x9F8D,
+	0x97B5, 0x4FB6, 0x97B6, 0x616E, 0x97B7, 0x65C5, 0x97B8, 0x865C,
+	0x97B9, 0x4E86, 0x97BA, 0x4EAE, 0x97BB, 0x50DA, 0x97BC, 0x4E21,
+	0x97BD, 0x51CC, 0x97BE, 0x5BEE, 0x97BF, 0x6599, 0x97C0, 0x6881,
+	0x97C1, 0x6DBC, 0x97C2, 0x731F, 0x97C3, 0x7642, 0x97C4, 0x77AD,
+	0x97C5, 0x7A1C, 0x97C6, 0x7CE7, 0x97C7, 0x826F, 0x97C8, 0x8AD2,
+	0x97C9, 0x907C, 0x97CA, 0x91CF, 0x97CB, 0x9675, 0x97CC, 0x9818,
+	0x97CD, 0x529B, 0x97CE, 0x7DD1, 0x97CF, 0x502B, 0x97D0, 0x5398,
+	0x97D1, 0x6797, 0x97D2, 0x6DCB, 0x97D3, 0x71D0, 0x97D4, 0x7433,
+	0x97D5, 0x81E8, 0x97D6, 0x8F2A, 0x97D7, 0x96A3, 0x97D8, 0x9C57,
+	0x97D9, 0x9E9F, 0x97DA, 0x7460, 0x97DB, 0x5841, 0x97DC, 0x6D99,
+	0x97DD, 0x7D2F, 0x97DE, 0x985E, 0x97DF, 0x4EE4, 0x97E0, 0x4F36,
+	0x97E1, 0x4F8B, 0x97E2, 0x51B7, 0x97E3, 0x52B1, 0x97E4, 0x5DBA,
+	0x97E5, 0x601C, 0x97E6, 0x73B2, 0x97E7, 0x793C, 0x97E8, 0x82D3,
+	0x97E9, 0x9234, 0x97EA, 0x96B7, 0x97EB, 0x96F6, 0x97EC, 0x970A,
+	0x97ED, 0x9E97, 0x97EE, 0x9F62, 0x97EF, 0x66A6, 0x97F0, 0x6B74,
+	0x97F1, 0x5217, 0x97F2, 0x52A3, 0x97F3, 0x70C8, 0x97F4, 0x88C2,
+	0x97F5, 0x5EC9, 0x97F6, 0x604B, 0x97F7, 0x6190, 0x97F8, 0x6F23,
+	0x97F9, 0x7149, 0x97FA, 0x7C3E, 0x97FB, 0x7DF4, 0x97FC, 0x806F,
+	0x9840, 0x84EE, 0x9841, 0x9023, 0x9842, 0x932C, 0x9843, 0x5442,
+	0x9844, 0x9B6F, 0x9845, 0x6AD3, 0x9846, 0x7089, 0x9847, 0x8CC2,
+	0x9848, 0x8DEF, 0x9849, 0x9732, 0x984A, 0x52B4, 0x984B, 0x5A41,
+	0x984C, 0x5ECA, 0x984D, 0x5F04, 0x984E, 0x6717, 0x984F, 0x697C,
+	0x9850, 0x6994, 0x9851, 0x6D6A, 0x9852, 0x6F0F, 0x9853, 0x7262,
+	0x9854, 0x72FC, 0x9855, 0x7BED, 0x9856, 0x8001, 0x9857, 0x807E,
+	0x9858, 0x874B, 0x9859, 0x90CE, 0x985A, 0x516D, 0x985B, 0x9E93,
+	0x985C, 0x7984, 0x985D, 0x808B, 0x985E, 0x9332, 0x985F, 0x8AD6,
+	0x9860, 0x502D, 0x9861, 0x548C, 0x9862, 0x8A71, 0x9863, 0x6B6A,
+	0x9864, 0x8CC4, 0x9865, 0x8107, 0x9866, 0x60D1, 0x9867, 0x67A0,
+	0x9868, 0x9DF2, 0x9869, 0x4E99, 0x986A, 0x4E98, 0x986B, 0x9C10,
+	0x986C, 0x8A6B, 0x986D, 0x85C1, 0x986E, 0x8568, 0x986F, 0x6900,
+	0x9870, 0x6E7E, 0x9871, 0x7897, 0x9872, 0x8155, 0x989F, 0x5F0C,
+	0x98A0, 0x4E10, 0x98A1, 0x4E15, 0x98A2, 0x4E2A, 0x98A3, 0x4E31,
+	0x98A4, 0x4E36, 0x98A5, 0x4E3C, 0x98A6, 0x4E3F, 0x98A7, 0x4E42,
+	0x98A8, 0x4E56, 0x98A9, 0x4E58, 0x98AA, 0x4E82, 0x98AB, 0x4E85,
+	0x98AC, 0x8C6B, 0x98AD, 0x4E8A, 0x98AE, 0x8212, 0x98AF, 0x5F0D,
+	0x98B0, 0x4E8E, 0x98B1, 0x4E9E, 0x98B2, 0x4E9F, 0x98B3, 0x4EA0,
+	0x98B4, 0x4EA2, 0x98B5, 0x4EB0, 0x98B6, 0x4EB3, 0x98B7, 0x4EB6,
+	0x98B8, 0x4ECE, 0x98B9, 0x4ECD, 0x98BA, 0x4EC4, 0x98BB, 0x4EC6,
+	0x98BC, 0x4EC2, 0x98BD, 0x4ED7, 0x98BE, 0x4EDE, 0x98BF, 0x4EED,
+	0x98C0, 0x4EDF, 0x98C1, 0x4EF7, 0x98C2, 0x4F09, 0x98C3, 0x4F5A,
+	0x98C4, 0x4F30, 0x98C5, 0x4F5B, 0x98C6, 0x4F5D, 0x98C7, 0x4F57,
+	0x98C8, 0x4F47, 0x98C9, 0x4F76, 0x98CA, 0x4F88, 0x98CB, 0x4F8F,
+	0x98CC, 0x4F98, 0x98CD, 0x4F7B, 0x98CE, 0x4F69, 0x98CF, 0x4F70,
+	0x98D0, 0x4F91, 0x98D1, 0x4F6F, 0x98D2, 0x4F86, 0x98D3, 0x4F96,
+	0x98D4, 0x5118, 0x98D5, 0x4FD4, 0x98D6, 0x4FDF, 0x98D7, 0x4FCE,
+	0x98D8, 0x4FD8, 0x98D9, 0x4FDB, 0x98DA, 0x4FD1, 0x98DB, 0x4FDA,
+	0x98DC, 0x4FD0, 0x98DD, 0x4FE4, 0x98DE, 0x4FE5, 0x98DF, 0x501A,
+	0x98E0, 0x5028, 0x98E1, 0x5014, 0x98E2, 0x502A, 0x98E3, 0x5025,
+	0x98E4, 0x5005, 0x98E5, 0x4F1C, 0x98E6, 0x4FF6, 0x98E7, 0x5021,
+	0x98E8, 0x5029, 0x98E9, 0x502C, 0x98EA, 0x4FFE, 0x98EB, 0x4FEF,
+	0x98EC, 0x5011, 0x98ED, 0x5006, 0x98EE, 0x5043, 0x98EF, 0x5047,
+	0x98F0, 0x6703, 0x98F1, 0x5055, 0x98F2, 0x5050, 0x98F3, 0x5048,
+	0x98F4, 0x505A, 0x98F5, 0x5056, 0x98F6, 0x506C, 0x98F7, 0x5078,
+	0x98F8, 0x5080, 0x98F9, 0x509A, 0x98FA, 0x5085, 0x98FB, 0x50B4,
+	0x98FC, 0x50B2, 0x9940, 0x50C9, 0x9941, 0x50CA, 0x9942, 0x50B3,
+	0x9943, 0x50C2, 0x9944, 0x50D6, 0x9945, 0x50DE, 0x9946, 0x50E5,
+	0x9947, 0x50ED, 0x9948, 0x50E3, 0x9949, 0x50EE, 0x994A, 0x50F9,
+	0x994B, 0x50F5, 0x994C, 0x5109, 0x994D, 0x5101, 0x994E, 0x5102,
+	0x994F, 0x5116, 0x9950, 0x5115, 0x9951, 0x5114, 0x9952, 0x511A,
+	0x9953, 0x5121, 0x9954, 0x513A, 0x9955, 0x5137, 0x9956, 0x513C,
+	0x9957, 0x513B, 0x9958, 0x513F, 0x9959, 0x5140, 0x995A, 0x5152,
+	0x995B, 0x514C, 0x995C, 0x5154, 0x995D, 0x5162, 0x995E, 0x7AF8,
+	0x995F, 0x5169, 0x9960, 0x516A, 0x9961, 0x516E, 0x9962, 0x5180,
+	0x9963, 0x5182, 0x9964, 0x56D8, 0x9965, 0x518C, 0x9966, 0x5189,
+	0x9967, 0x518F, 0x9968, 0x5191, 0x9969, 0x5193, 0x996A, 0x5195,
+	0x996B, 0x5196, 0x996C, 0x51A4, 0x996D, 0x51A6, 0x996E, 0x51A2,
+	0x996F, 0x51A9, 0x9970, 0x51AA, 0x9971, 0x51AB, 0x9972, 0x51B3,
+	0x9973, 0x51B1, 0x9974, 0x51B2, 0x9975, 0x51B0, 0x9976, 0x51B5,
+	0x9977, 0x51BD, 0x9978, 0x51C5, 0x9979, 0x51C9, 0x997A, 0x51DB,
+	0x997B, 0x51E0, 0x997C, 0x8655, 0x997D, 0x51E9, 0x997E, 0x51ED,
+	0x9980, 0x51F0, 0x9981, 0x51F5, 0x9982, 0x51FE, 0x9983, 0x5204,
+	0x9984, 0x520B, 0x9985, 0x5214, 0x9986, 0x520E, 0x9987, 0x5227,
+	0x9988, 0x522A, 0x9989, 0x522E, 0x998A, 0x5233, 0x998B, 0x5239,
+	0x998C, 0x524F, 0x998D, 0x5244, 0x998E, 0x524B, 0x998F, 0x524C,
+	0x9990, 0x525E, 0x9991, 0x5254, 0x9992, 0x526A, 0x9993, 0x5274,
+	0x9994, 0x5269, 0x9995, 0x5273, 0x9996, 0x527F, 0x9997, 0x527D,
+	0x9998, 0x528D, 0x9999, 0x5294, 0x999A, 0x5292, 0x999B, 0x5271,
+	0x999C, 0x5288, 0x999D, 0x5291, 0x999E, 0x8FA8, 0x999F, 0x8FA7,
+	0x99A0, 0x52AC, 0x99A1, 0x52AD, 0x99A2, 0x52BC, 0x99A3, 0x52B5,
+	0x99A4, 0x52C1, 0x99A5, 0x52CD, 0x99A6, 0x52D7, 0x99A7, 0x52DE,
+	0x99A8, 0x52E3, 0x99A9, 0x52E6, 0x99AA, 0x98ED, 0x99AB, 0x52E0,
+	0x99AC, 0x52F3, 0x99AD, 0x52F5, 0x99AE, 0x52F8, 0x99AF, 0x52F9,
+	0x99B0, 0x5306, 0x99B1, 0x5308, 0x99B2, 0x7538, 0x99B3, 0x530D,
+	0x99B4, 0x5310, 0x99B5, 0x530F, 0x99B6, 0x5315, 0x99B7, 0x531A,
+	0x99B8, 0x5323, 0x99B9, 0x532F, 0x99BA, 0x5331, 0x99BB, 0x5333,
+	0x99BC, 0x5338, 0x99BD, 0x5340, 0x99BE, 0x5346, 0x99BF, 0x5345,
+	0x99C0, 0x4E17, 0x99C1, 0x5349, 0x99C2, 0x534D, 0x99C3, 0x51D6,
+	0x99C4, 0x535E, 0x99C5, 0x5369, 0x99C6, 0x536E, 0x99C7, 0x5918,
+	0x99C8, 0x537B, 0x99C9, 0x5377, 0x99CA, 0x5382, 0x99CB, 0x5396,
+	0x99CC, 0x53A0, 0x99CD, 0x53A6, 0x99CE, 0x53A5, 0x99CF, 0x53AE,
+	0x99D0, 0x53B0, 0x99D1, 0x53B6, 0x99D2, 0x53C3, 0x99D3, 0x7C12,
+	0x99D4, 0x96D9, 0x99D5, 0x53DF, 0x99D6, 0x66FC, 0x99D7, 0x71EE,
+	0x99D8, 0x53EE, 0x99D9, 0x53E8, 0x99DA, 0x53ED, 0x99DB, 0x53FA,
+	0x99DC, 0x5401, 0x99DD, 0x543D, 0x99DE, 0x5440, 0x99DF, 0x542C,
+	0x99E0, 0x542D, 0x99E1, 0x543C, 0x99E2, 0x542E, 0x99E3, 0x5436,
+	0x99E4, 0x5429, 0x99E5, 0x541D, 0x99E6, 0x544E, 0x99E7, 0x548F,
+	0x99E8, 0x5475, 0x99E9, 0x548E, 0x99EA, 0x545F, 0x99EB, 0x5471,
+	0x99EC, 0x5477, 0x99ED, 0x5470, 0x99EE, 0x5492, 0x99EF, 0x547B,
+	0x99F0, 0x5480, 0x99F1, 0x5476, 0x99F2, 0x5484, 0x99F3, 0x5490,
+	0x99F4, 0x5486, 0x99F5, 0x54C7, 0x99F6, 0x54A2, 0x99F7, 0x54B8,
+	0x99F8, 0x54A5, 0x99F9, 0x54AC, 0x99FA, 0x54C4, 0x99FB, 0x54C8,
+	0x99FC, 0x54A8, 0x9A40, 0x54AB, 0x9A41, 0x54C2, 0x9A42, 0x54A4,
+	0x9A43, 0x54BE, 0x9A44, 0x54BC, 0x9A45, 0x54D8, 0x9A46, 0x54E5,
+	0x9A47, 0x54E6, 0x9A48, 0x550F, 0x9A49, 0x5514, 0x9A4A, 0x54FD,
+	0x9A4B, 0x54EE, 0x9A4C, 0x54ED, 0x9A4D, 0x54FA, 0x9A4E, 0x54E2,
+	0x9A4F, 0x5539, 0x9A50, 0x5540, 0x9A51, 0x5563, 0x9A52, 0x554C,
+	0x9A53, 0x552E, 0x9A54, 0x555C, 0x9A55, 0x5545, 0x9A56, 0x5556,
+	0x9A57, 0x5557, 0x9A58, 0x5538, 0x9A59, 0x5533, 0x9A5A, 0x555D,
+	0x9A5B, 0x5599, 0x9A5C, 0x5580, 0x9A5D, 0x54AF, 0x9A5E, 0x558A,
+	0x9A5F, 0x559F, 0x9A60, 0x557B, 0x9A61, 0x557E, 0x9A62, 0x5598,
+	0x9A63, 0x559E, 0x9A64, 0x55AE, 0x9A65, 0x557C, 0x9A66, 0x5583,
+	0x9A67, 0x55A9, 0x9A68, 0x5587, 0x9A69, 0x55A8, 0x9A6A, 0x55DA,
+	0x9A6B, 0x55C5, 0x9A6C, 0x55DF, 0x9A6D, 0x55C4, 0x9A6E, 0x55DC,
+	0x9A6F, 0x55E4, 0x9A70, 0x55D4, 0x9A71, 0x5614, 0x9A72, 0x55F7,
+	0x9A73, 0x5616, 0x9A74, 0x55FE, 0x9A75, 0x55FD, 0x9A76, 0x561B,
+	0x9A77, 0x55F9, 0x9A78, 0x564E, 0x9A79, 0x5650, 0x9A7A, 0x71DF,
+	0x9A7B, 0x5634, 0x9A7C, 0x5636, 0x9A7D, 0x5632, 0x9A7E, 0x5638,
+	0x9A80, 0x566B, 0x9A81, 0x5664, 0x9A82, 0x562F, 0x9A83, 0x566C,
+	0x9A84, 0x566A, 0x9A85, 0x5686, 0x9A86, 0x5680, 0x9A87, 0x568A,
+	0x9A88, 0x56A0, 0x9A89, 0x5694, 0x9A8A, 0x568F, 0x9A8B, 0x56A5,
+	0x9A8C, 0x56AE, 0x9A8D, 0x56B6, 0x9A8E, 0x56B4, 0x9A8F, 0x56C2,
+	0x9A90, 0x56BC, 0x9A91, 0x56C1, 0x9A92, 0x56C3, 0x9A93, 0x56C0,
+	0x9A94, 0x56C8, 0x9A95, 0x56CE, 0x9A96, 0x56D1, 0x9A97, 0x56D3,
+	0x9A98, 0x56D7, 0x9A99, 0x56EE, 0x9A9A, 0x56F9, 0x9A9B, 0x5700,
+	0x9A9C, 0x56FF, 0x9A9D, 0x5704, 0x9A9E, 0x5709, 0x9A9F, 0x5708,
+	0x9AA0, 0x570B, 0x9AA1, 0x570D, 0x9AA2, 0x5713, 0x9AA3, 0x5718,
+	0x9AA4, 0x5716, 0x9AA5, 0x55C7, 0x9AA6, 0x571C, 0x9AA7, 0x5726,
+	0x9AA8, 0x5737, 0x9AA9, 0x5738, 0x9AAA, 0x574E, 0x9AAB, 0x573B,
+	0x9AAC, 0x5740, 0x9AAD, 0x574F, 0x9AAE, 0x5769, 0x9AAF, 0x57C0,
+	0x9AB0, 0x5788, 0x9AB1, 0x5761, 0x9AB2, 0x577F, 0x9AB3, 0x5789,
+	0x9AB4, 0x5793, 0x9AB5, 0x57A0, 0x9AB6, 0x57B3, 0x9AB7, 0x57A4,
+	0x9AB8, 0x57AA, 0x9AB9, 0x57B0, 0x9ABA, 0x57C3, 0x9ABB, 0x57C6,
+	0x9ABC, 0x57D4, 0x9ABD, 0x57D2, 0x9ABE, 0x57D3, 0x9ABF, 0x580A,
+	0x9AC0, 0x57D6, 0x9AC1, 0x57E3, 0x9AC2, 0x580B, 0x9AC3, 0x5819,
+	0x9AC4, 0x581D, 0x9AC5, 0x5872, 0x9AC6, 0x5821, 0x9AC7, 0x5862,
+	0x9AC8, 0x584B, 0x9AC9, 0x5870, 0x9ACA, 0x6BC0, 0x9ACB, 0x5852,
+	0x9ACC, 0x583D, 0x9ACD, 0x5879, 0x9ACE, 0x5885, 0x9ACF, 0x58B9,
+	0x9AD0, 0x589F, 0x9AD1, 0x58AB, 0x9AD2, 0x58BA, 0x9AD3, 0x58DE,
+	0x9AD4, 0x58BB, 0x9AD5, 0x58B8, 0x9AD6, 0x58AE, 0x9AD7, 0x58C5,
+	0x9AD8, 0x58D3, 0x9AD9, 0x58D1, 0x9ADA, 0x58D7, 0x9ADB, 0x58D9,
+	0x9ADC, 0x58D8, 0x9ADD, 0x58E5, 0x9ADE, 0x58DC, 0x9ADF, 0x58E4,
+	0x9AE0, 0x58DF, 0x9AE1, 0x58EF, 0x9AE2, 0x58FA, 0x9AE3, 0x58F9,
+	0x9AE4, 0x58FB, 0x9AE5, 0x58FC, 0x9AE6, 0x58FD, 0x9AE7, 0x5902,
+	0x9AE8, 0x590A, 0x9AE9, 0x5910, 0x9AEA, 0x591B, 0x9AEB, 0x68A6,
+	0x9AEC, 0x5925, 0x9AED, 0x592C, 0x9AEE, 0x592D, 0x9AEF, 0x5932,
+	0x9AF0, 0x5938, 0x9AF1, 0x593E, 0x9AF2, 0x7AD2, 0x9AF3, 0x5955,
+	0x9AF4, 0x5950, 0x9AF5, 0x594E, 0x9AF6, 0x595A, 0x9AF7, 0x5958,
+	0x9AF8, 0x5962, 0x9AF9, 0x5960, 0x9AFA, 0x5967, 0x9AFB, 0x596C,
+	0x9AFC, 0x5969, 0x9B40, 0x5978, 0x9B41, 0x5981, 0x9B42, 0x599D,
+	0x9B43, 0x4F5E, 0x9B44, 0x4FAB, 0x9B45, 0x59A3, 0x9B46, 0x59B2,
+	0x9B47, 0x59C6, 0x9B48, 0x59E8, 0x9B49, 0x59DC, 0x9B4A, 0x598D,
+	0x9B4B, 0x59D9, 0x9B4C, 0x59DA, 0x9B4D, 0x5A25, 0x9B4E, 0x5A1F,
+	0x9B4F, 0x5A11, 0x9B50, 0x5A1C, 0x9B51, 0x5A09, 0x9B52, 0x5A1A,
+	0x9B53, 0x5A40, 0x9B54, 0x5A6C, 0x9B55, 0x5A49, 0x9B56, 0x5A35,
+	0x9B57, 0x5A36, 0x9B58, 0x5A62, 0x9B59, 0x5A6A, 0x9B5A, 0x5A9A,
+	0x9B5B, 0x5ABC, 0x9B5C, 0x5ABE, 0x9B5D, 0x5ACB, 0x9B5E, 0x5AC2,
+	0x9B5F, 0x5ABD, 0x9B60, 0x5AE3, 0x9B61, 0x5AD7, 0x9B62, 0x5AE6,
+	0x9B63, 0x5AE9, 0x9B64, 0x5AD6, 0x9B65, 0x5AFA, 0x9B66, 0x5AFB,
+	0x9B67, 0x5B0C, 0x9B68, 0x5B0B, 0x9B69, 0x5B16, 0x9B6A, 0x5B32,
+	0x9B6B, 0x5AD0, 0x9B6C, 0x5B2A, 0x9B6D, 0x5B36, 0x9B6E, 0x5B3E,
+	0x9B6F, 0x5B43, 0x9B70, 0x5B45, 0x9B71, 0x5B40, 0x9B72, 0x5B51,
+	0x9B73, 0x5B55, 0x9B74, 0x5B5A, 0x9B75, 0x5B5B, 0x9B76, 0x5B65,
+	0x9B77, 0x5B69, 0x9B78, 0x5B70, 0x9B79, 0x5B73, 0x9B7A, 0x5B75,
+	0x9B7B, 0x5B78, 0x9B7C, 0x6588, 0x9B7D, 0x5B7A, 0x9B7E, 0x5B80,
+	0x9B80, 0x5B83, 0x9B81, 0x5BA6, 0x9B82, 0x5BB8, 0x9B83, 0x5BC3,
+	0x9B84, 0x5BC7, 0x9B85, 0x5BC9, 0x9B86, 0x5BD4, 0x9B87, 0x5BD0,
+	0x9B88, 0x5BE4, 0x9B89, 0x5BE6, 0x9B8A, 0x5BE2, 0x9B8B, 0x5BDE,
+	0x9B8C, 0x5BE5, 0x9B8D, 0x5BEB, 0x9B8E, 0x5BF0, 0x9B8F, 0x5BF6,
+	0x9B90, 0x5BF3, 0x9B91, 0x5C05, 0x9B92, 0x5C07, 0x9B93, 0x5C08,
+	0x9B94, 0x5C0D, 0x9B95, 0x5C13, 0x9B96, 0x5C20, 0x9B97, 0x5C22,
+	0x9B98, 0x5C28, 0x9B99, 0x5C38, 0x9B9A, 0x5C39, 0x9B9B, 0x5C41,
+	0x9B9C, 0x5C46, 0x9B9D, 0x5C4E, 0x9B9E, 0x5C53, 0x9B9F, 0x5C50,
+	0x9BA0, 0x5C4F, 0x9BA1, 0x5B71, 0x9BA2, 0x5C6C, 0x9BA3, 0x5C6E,
+	0x9BA4, 0x4E62, 0x9BA5, 0x5C76, 0x9BA6, 0x5C79, 0x9BA7, 0x5C8C,
+	0x9BA8, 0x5C91, 0x9BA9, 0x5C94, 0x9BAA, 0x599B, 0x9BAB, 0x5CAB,
+	0x9BAC, 0x5CBB, 0x9BAD, 0x5CB6, 0x9BAE, 0x5CBC, 0x9BAF, 0x5CB7,
+	0x9BB0, 0x5CC5, 0x9BB1, 0x5CBE, 0x9BB2, 0x5CC7, 0x9BB3, 0x5CD9,
+	0x9BB4, 0x5CE9, 0x9BB5, 0x5CFD, 0x9BB6, 0x5CFA, 0x9BB7, 0x5CED,
+	0x9BB8, 0x5D8C, 0x9BB9, 0x5CEA, 0x9BBA, 0x5D0B, 0x9BBB, 0x5D15,
+	0x9BBC, 0x5D17, 0x9BBD, 0x5D5C, 0x9BBE, 0x5D1F, 0x9BBF, 0x5D1B,
+	0x9BC0, 0x5D11, 0x9BC1, 0x5D14, 0x9BC2, 0x5D22, 0x9BC3, 0x5D1A,
+	0x9BC4, 0x5D19, 0x9BC5, 0x5D18, 0x9BC6, 0x5D4C, 0x9BC7, 0x5D52,
+	0x9BC8, 0x5D4E, 0x9BC9, 0x5D4B, 0x9BCA, 0x5D6C, 0x9BCB, 0x5D73,
+	0x9BCC, 0x5D76, 0x9BCD, 0x5D87, 0x9BCE, 0x5D84, 0x9BCF, 0x5D82,
+	0x9BD0, 0x5DA2, 0x9BD1, 0x5D9D, 0x9BD2, 0x5DAC, 0x9BD3, 0x5DAE,
+	0x9BD4, 0x5DBD, 0x9BD5, 0x5D90, 0x9BD6, 0x5DB7, 0x9BD7, 0x5DBC,
+	0x9BD8, 0x5DC9, 0x9BD9, 0x5DCD, 0x9BDA, 0x5DD3, 0x9BDB, 0x5DD2,
+	0x9BDC, 0x5DD6, 0x9BDD, 0x5DDB, 0x9BDE, 0x5DEB, 0x9BDF, 0x5DF2,
+	0x9BE0, 0x5DF5, 0x9BE1, 0x5E0B, 0x9BE2, 0x5E1A, 0x9BE3, 0x5E19,
+	0x9BE4, 0x5E11, 0x9BE5, 0x5E1B, 0x9BE6, 0x5E36, 0x9BE7, 0x5E37,
+	0x9BE8, 0x5E44, 0x9BE9, 0x5E43, 0x9BEA, 0x5E40, 0x9BEB, 0x5E4E,
+	0x9BEC, 0x5E57, 0x9BED, 0x5E54, 0x9BEE, 0x5E5F, 0x9BEF, 0x5E62,
+	0x9BF0, 0x5E64, 0x9BF1, 0x5E47, 0x9BF2, 0x5E75, 0x9BF3, 0x5E76,
+	0x9BF4, 0x5E7A, 0x9BF5, 0x9EBC, 0x9BF6, 0x5E7F, 0x9BF7, 0x5EA0,
+	0x9BF8, 0x5EC1, 0x9BF9, 0x5EC2, 0x9BFA, 0x5EC8, 0x9BFB, 0x5ED0,
+	0x9BFC, 0x5ECF, 0x9C40, 0x5ED6, 0x9C41, 0x5EE3, 0x9C42, 0x5EDD,
+	0x9C43, 0x5EDA, 0x9C44, 0x5EDB, 0x9C45, 0x5EE2, 0x9C46, 0x5EE1,
+	0x9C47, 0x5EE8, 0x9C48, 0x5EE9, 0x9C49, 0x5EEC, 0x9C4A, 0x5EF1,
+	0x9C4B, 0x5EF3, 0x9C4C, 0x5EF0, 0x9C4D, 0x5EF4, 0x9C4E, 0x5EF8,
+	0x9C4F, 0x5EFE, 0x9C50, 0x5F03, 0x9C51, 0x5F09, 0x9C52, 0x5F5D,
+	0x9C53, 0x5F5C, 0x9C54, 0x5F0B, 0x9C55, 0x5F11, 0x9C56, 0x5F16,
+	0x9C57, 0x5F29, 0x9C58, 0x5F2D, 0x9C59, 0x5F38, 0x9C5A, 0x5F41,
+	0x9C5B, 0x5F48, 0x9C5C, 0x5F4C, 0x9C5D, 0x5F4E, 0x9C5E, 0x5F2F,
+	0x9C5F, 0x5F51, 0x9C60, 0x5F56, 0x9C61, 0x5F57, 0x9C62, 0x5F59,
+	0x9C63, 0x5F61, 0x9C64, 0x5F6D, 0x9C65, 0x5F73, 0x9C66, 0x5F77,
+	0x9C67, 0x5F83, 0x9C68, 0x5F82, 0x9C69, 0x5F7F, 0x9C6A, 0x5F8A,
+	0x9C6B, 0x5F88, 0x9C6C, 0x5F91, 0x9C6D, 0x5F87, 0x9C6E, 0x5F9E,
+	0x9C6F, 0x5F99, 0x9C70, 0x5F98, 0x9C71, 0x5FA0, 0x9C72, 0x5FA8,
+	0x9C73, 0x5FAD, 0x9C74, 0x5FBC, 0x9C75, 0x5FD6, 0x9C76, 0x5FFB,
+	0x9C77, 0x5FE4, 0x9C78, 0x5FF8, 0x9C79, 0x5FF1, 0x9C7A, 0x5FDD,
+	0x9C7B, 0x60B3, 0x9C7C, 0x5FFF, 0x9C7D, 0x6021, 0x9C7E, 0x6060,
+	0x9C80, 0x6019, 0x9C81, 0x6010, 0x9C82, 0x6029, 0x9C83, 0x600E,
+	0x9C84, 0x6031, 0x9C85, 0x601B, 0x9C86, 0x6015, 0x9C87, 0x602B,
+	0x9C88, 0x6026, 0x9C89, 0x600F, 0x9C8A, 0x603A, 0x9C8B, 0x605A,
+	0x9C8C, 0x6041, 0x9C8D, 0x606A, 0x9C8E, 0x6077, 0x9C8F, 0x605F,
+	0x9C90, 0x604A, 0x9C91, 0x6046, 0x9C92, 0x604D, 0x9C93, 0x6063,
+	0x9C94, 0x6043, 0x9C95, 0x6064, 0x9C96, 0x6042, 0x9C97, 0x606C,
+	0x9C98, 0x606B, 0x9C99, 0x6059, 0x9C9A, 0x6081, 0x9C9B, 0x608D,
+	0x9C9C, 0x60E7, 0x9C9D, 0x6083, 0x9C9E, 0x609A, 0x9C9F, 0x6084,
+	0x9CA0, 0x609B, 0x9CA1, 0x6096, 0x9CA2, 0x6097, 0x9CA3, 0x6092,
+	0x9CA4, 0x60A7, 0x9CA5, 0x608B, 0x9CA6, 0x60E1, 0x9CA7, 0x60B8,
+	0x9CA8, 0x60E0, 0x9CA9, 0x60D3, 0x9CAA, 0x60B4, 0x9CAB, 0x5FF0,
+	0x9CAC, 0x60BD, 0x9CAD, 0x60C6, 0x9CAE, 0x60B5, 0x9CAF, 0x60D8,
+	0x9CB0, 0x614D, 0x9CB1, 0x6115, 0x9CB2, 0x6106, 0x9CB3, 0x60F6,
+	0x9CB4, 0x60F7, 0x9CB5, 0x6100, 0x9CB6, 0x60F4, 0x9CB7, 0x60FA,
+	0x9CB8, 0x6103, 0x9CB9, 0x6121, 0x9CBA, 0x60FB, 0x9CBB, 0x60F1,
+	0x9CBC, 0x610D, 0x9CBD, 0x610E, 0x9CBE, 0x6147, 0x9CBF, 0x613E,
+	0x9CC0, 0x6128, 0x9CC1, 0x6127, 0x9CC2, 0x614A, 0x9CC3, 0x613F,
+	0x9CC4, 0x613C, 0x9CC5, 0x612C, 0x9CC6, 0x6134, 0x9CC7, 0x613D,
+	0x9CC8, 0x6142, 0x9CC9, 0x6144, 0x9CCA, 0x6173, 0x9CCB, 0x6177,
+	0x9CCC, 0x6158, 0x9CCD, 0x6159, 0x9CCE, 0x615A, 0x9CCF, 0x616B,
+	0x9CD0, 0x6174, 0x9CD1, 0x616F, 0x9CD2, 0x6165, 0x9CD3, 0x6171,
+	0x9CD4, 0x615F, 0x9CD5, 0x615D, 0x9CD6, 0x6153, 0x9CD7, 0x6175,
+	0x9CD8, 0x6199, 0x9CD9, 0x6196, 0x9CDA, 0x6187, 0x9CDB, 0x61AC,
+	0x9CDC, 0x6194, 0x9CDD, 0x619A, 0x9CDE, 0x618A, 0x9CDF, 0x6191,
+	0x9CE0, 0x61AB, 0x9CE1, 0x61AE, 0x9CE2, 0x61CC, 0x9CE3, 0x61CA,
+	0x9CE4, 0x61C9, 0x9CE5, 0x61F7, 0x9CE6, 0x61C8, 0x9CE7, 0x61C3,
+	0x9CE8, 0x61C6, 0x9CE9, 0x61BA, 0x9CEA, 0x61CB, 0x9CEB, 0x7F79,
+	0x9CEC, 0x61CD, 0x9CED, 0x61E6, 0x9CEE, 0x61E3, 0x9CEF, 0x61F6,
+	0x9CF0, 0x61FA, 0x9CF1, 0x61F4, 0x9CF2, 0x61FF, 0x9CF3, 0x61FD,
+	0x9CF4, 0x61FC, 0x9CF5, 0x61FE, 0x9CF6, 0x6200, 0x9CF7, 0x6208,
+	0x9CF8, 0x6209, 0x9CF9, 0x620D, 0x9CFA, 0x620C, 0x9CFB, 0x6214,
+	0x9CFC, 0x621B, 0x9D40, 0x621E, 0x9D41, 0x6221, 0x9D42, 0x622A,
+	0x9D43, 0x622E, 0x9D44, 0x6230, 0x9D45, 0x6232, 0x9D46, 0x6233,
+	0x9D47, 0x6241, 0x9D48, 0x624E, 0x9D49, 0x625E, 0x9D4A, 0x6263,
+	0x9D4B, 0x625B, 0x9D4C, 0x6260, 0x9D4D, 0x6268, 0x9D4E, 0x627C,
+	0x9D4F, 0x6282, 0x9D50, 0x6289, 0x9D51, 0x627E, 0x9D52, 0x6292,
+	0x9D53, 0x6293, 0x9D54, 0x6296, 0x9D55, 0x62D4, 0x9D56, 0x6283,
+	0x9D57, 0x6294, 0x9D58, 0x62D7, 0x9D59, 0x62D1, 0x9D5A, 0x62BB,
+	0x9D5B, 0x62CF, 0x9D5C, 0x62FF, 0x9D5D, 0x62C6, 0x9D5E, 0x64D4,
+	0x9D5F, 0x62C8, 0x9D60, 0x62DC, 0x9D61, 0x62CC, 0x9D62, 0x62CA,
+	0x9D63, 0x62C2, 0x9D64, 0x62C7, 0x9D65, 0x629B, 0x9D66, 0x62C9,
+	0x9D67, 0x630C, 0x9D68, 0x62EE, 0x9D69, 0x62F1, 0x9D6A, 0x6327,
+	0x9D6B, 0x6302, 0x9D6C, 0x6308, 0x9D6D, 0x62EF, 0x9D6E, 0x62F5,
+	0x9D6F, 0x6350, 0x9D70, 0x633E, 0x9D71, 0x634D, 0x9D72, 0x641C,
+	0x9D73, 0x634F, 0x9D74, 0x6396, 0x9D75, 0x638E, 0x9D76, 0x6380,
+	0x9D77, 0x63AB, 0x9D78, 0x6376, 0x9D79, 0x63A3, 0x9D7A, 0x638F,
+	0x9D7B, 0x6389, 0x9D7C, 0x639F, 0x9D7D, 0x63B5, 0x9D7E, 0x636B,
+	0x9D80, 0x6369, 0x9D81, 0x63BE, 0x9D82, 0x63E9, 0x9D83, 0x63C0,
+	0x9D84, 0x63C6, 0x9D85, 0x63E3, 0x9D86, 0x63C9, 0x9D87, 0x63D2,
+	0x9D88, 0x63F6, 0x9D89, 0x63C4, 0x9D8A, 0x6416, 0x9D8B, 0x6434,
+	0x9D8C, 0x6406, 0x9D8D, 0x6413, 0x9D8E, 0x6426, 0x9D8F, 0x6436,
+	0x9D90, 0x651D, 0x9D91, 0x6417, 0x9D92, 0x6428, 0x9D93, 0x640F,
+	0x9D94, 0x6467, 0x9D95, 0x646F, 0x9D96, 0x6476, 0x9D97, 0x644E,
+	0x9D98, 0x652A, 0x9D99, 0x6495, 0x9D9A, 0x6493, 0x9D9B, 0x64A5,
+	0x9D9C, 0x64A9, 0x9D9D, 0x6488, 0x9D9E, 0x64BC, 0x9D9F, 0x64DA,
+	0x9DA0, 0x64D2, 0x9DA1, 0x64C5, 0x9DA2, 0x64C7, 0x9DA3, 0x64BB,
+	0x9DA4, 0x64D8, 0x9DA5, 0x64C2, 0x9DA6, 0x64F1, 0x9DA7, 0x64E7,
+	0x9DA8, 0x8209, 0x9DA9, 0x64E0, 0x9DAA, 0x64E1, 0x9DAB, 0x62AC,
+	0x9DAC, 0x64E3, 0x9DAD, 0x64EF, 0x9DAE, 0x652C, 0x9DAF, 0x64F6,
+	0x9DB0, 0x64F4, 0x9DB1, 0x64F2, 0x9DB2, 0x64FA, 0x9DB3, 0x6500,
+	0x9DB4, 0x64FD, 0x9DB5, 0x6518, 0x9DB6, 0x651C, 0x9DB7, 0x6505,
+	0x9DB8, 0x6524, 0x9DB9, 0x6523, 0x9DBA, 0x652B, 0x9DBB, 0x6534,
+	0x9DBC, 0x6535, 0x9DBD, 0x6537, 0x9DBE, 0x6536, 0x9DBF, 0x6538,
+	0x9DC0, 0x754B, 0x9DC1, 0x6548, 0x9DC2, 0x6556, 0x9DC3, 0x6555,
+	0x9DC4, 0x654D, 0x9DC5, 0x6558, 0x9DC6, 0x655E, 0x9DC7, 0x655D,
+	0x9DC8, 0x6572, 0x9DC9, 0x6578, 0x9DCA, 0x6582, 0x9DCB, 0x6583,
+	0x9DCC, 0x8B8A, 0x9DCD, 0x659B, 0x9DCE, 0x659F, 0x9DCF, 0x65AB,
+	0x9DD0, 0x65B7, 0x9DD1, 0x65C3, 0x9DD2, 0x65C6, 0x9DD3, 0x65C1,
+	0x9DD4, 0x65C4, 0x9DD5, 0x65CC, 0x9DD6, 0x65D2, 0x9DD7, 0x65DB,
+	0x9DD8, 0x65D9, 0x9DD9, 0x65E0, 0x9DDA, 0x65E1, 0x9DDB, 0x65F1,
+	0x9DDC, 0x6772, 0x9DDD, 0x660A, 0x9DDE, 0x6603, 0x9DDF, 0x65FB,
+	0x9DE0, 0x6773, 0x9DE1, 0x6635, 0x9DE2, 0x6636, 0x9DE3, 0x6634,
+	0x9DE4, 0x661C, 0x9DE5, 0x664F, 0x9DE6, 0x6644, 0x9DE7, 0x6649,
+	0x9DE8, 0x6641, 0x9DE9, 0x665E, 0x9DEA, 0x665D, 0x9DEB, 0x6664,
+	0x9DEC, 0x6667, 0x9DED, 0x6668, 0x9DEE, 0x665F, 0x9DEF, 0x6662,
+	0x9DF0, 0x6670, 0x9DF1, 0x6683, 0x9DF2, 0x6688, 0x9DF3, 0x668E,
+	0x9DF4, 0x6689, 0x9DF5, 0x6684, 0x9DF6, 0x6698, 0x9DF7, 0x669D,
+	0x9DF8, 0x66C1, 0x9DF9, 0x66B9, 0x9DFA, 0x66C9, 0x9DFB, 0x66BE,
+	0x9DFC, 0x66BC, 0x9E40, 0x66C4, 0x9E41, 0x66B8, 0x9E42, 0x66D6,
+	0x9E43, 0x66DA, 0x9E44, 0x66E0, 0x9E45, 0x663F, 0x9E46, 0x66E6,
+	0x9E47, 0x66E9, 0x9E48, 0x66F0, 0x9E49, 0x66F5, 0x9E4A, 0x66F7,
+	0x9E4B, 0x670F, 0x9E4C, 0x6716, 0x9E4D, 0x671E, 0x9E4E, 0x6726,
+	0x9E4F, 0x6727, 0x9E50, 0x9738, 0x9E51, 0x672E, 0x9E52, 0x673F,
+	0x9E53, 0x6736, 0x9E54, 0x6741, 0x9E55, 0x6738, 0x9E56, 0x6737,
+	0x9E57, 0x6746, 0x9E58, 0x675E, 0x9E59, 0x6760, 0x9E5A, 0x6759,
+	0x9E5B, 0x6763, 0x9E5C, 0x6764, 0x9E5D, 0x6789, 0x9E5E, 0x6770,
+	0x9E5F, 0x67A9, 0x9E60, 0x677C, 0x9E61, 0x676A, 0x9E62, 0x678C,
+	0x9E63, 0x678B, 0x9E64, 0x67A6, 0x9E65, 0x67A1, 0x9E66, 0x6785,
+	0x9E67, 0x67B7, 0x9E68, 0x67EF, 0x9E69, 0x67B4, 0x9E6A, 0x67EC,
+	0x9E6B, 0x67B3, 0x9E6C, 0x67E9, 0x9E6D, 0x67B8, 0x9E6E, 0x67E4,
+	0x9E6F, 0x67DE, 0x9E70, 0x67DD, 0x9E71, 0x67E2, 0x9E72, 0x67EE,
+	0x9E73, 0x67B9, 0x9E74, 0x67CE, 0x9E75, 0x67C6, 0x9E76, 0x67E7,
+	0x9E77, 0x6A9C, 0x9E78, 0x681E, 0x9E79, 0x6846, 0x9E7A, 0x6829,
+	0x9E7B, 0x6840, 0x9E7C, 0x684D, 0x9E7D, 0x6832, 0x9E7E, 0x684E,
+	0x9E80, 0x68B3, 0x9E81, 0x682B, 0x9E82, 0x6859, 0x9E83, 0x6863,
+	0x9E84, 0x6877, 0x9E85, 0x687F, 0x9E86, 0x689F, 0x9E87, 0x688F,
+	0x9E88, 0x68AD, 0x9E89, 0x6894, 0x9E8A, 0x689D, 0x9E8B, 0x689B,
+	0x9E8C, 0x6883, 0x9E8D, 0x6AAE, 0x9E8E, 0x68B9, 0x9E8F, 0x6874,
+	0x9E90, 0x68B5, 0x9E91, 0x68A0, 0x9E92, 0x68BA, 0x9E93, 0x690F,
+	0x9E94, 0x688D, 0x9E95, 0x687E, 0x9E96, 0x6901, 0x9E97, 0x68CA,
+	0x9E98, 0x6908, 0x9E99, 0x68D8, 0x9E9A, 0x6922, 0x9E9B, 0x6926,
+	0x9E9C, 0x68E1, 0x9E9D, 0x690C, 0x9E9E, 0x68CD, 0x9E9F, 0x68D4,
+	0x9EA0, 0x68E7, 0x9EA1, 0x68D5, 0x9EA2, 0x6936, 0x9EA3, 0x6912,
+	0x9EA4, 0x6904, 0x9EA5, 0x68D7, 0x9EA6, 0x68E3, 0x9EA7, 0x6925,
+	0x9EA8, 0x68F9, 0x9EA9, 0x68E0, 0x9EAA, 0x68EF, 0x9EAB, 0x6928,
+	0x9EAC, 0x692A, 0x9EAD, 0x691A, 0x9EAE, 0x6923, 0x9EAF, 0x6921,
+	0x9EB0, 0x68C6, 0x9EB1, 0x6979, 0x9EB2, 0x6977, 0x9EB3, 0x695C,
+	0x9EB4, 0x6978, 0x9EB5, 0x696B, 0x9EB6, 0x6954, 0x9EB7, 0x697E,
+	0x9EB8, 0x696E, 0x9EB9, 0x6939, 0x9EBA, 0x6974, 0x9EBB, 0x693D,
+	0x9EBC, 0x6959, 0x9EBD, 0x6930, 0x9EBE, 0x6961, 0x9EBF, 0x695E,
+	0x9EC0, 0x695D, 0x9EC1, 0x6981, 0x9EC2, 0x696A, 0x9EC3, 0x69B2,
+	0x9EC4, 0x69AE, 0x9EC5, 0x69D0, 0x9EC6, 0x69BF, 0x9EC7, 0x69C1,
+	0x9EC8, 0x69D3, 0x9EC9, 0x69BE, 0x9ECA, 0x69CE, 0x9ECB, 0x5BE8,
+	0x9ECC, 0x69CA, 0x9ECD, 0x69DD, 0x9ECE, 0x69BB, 0x9ECF, 0x69C3,
+	0x9ED0, 0x69A7, 0x9ED1, 0x6A2E, 0x9ED2, 0x6991, 0x9ED3, 0x69A0,
+	0x9ED4, 0x699C, 0x9ED5, 0x6995, 0x9ED6, 0x69B4, 0x9ED7, 0x69DE,
+	0x9ED8, 0x69E8, 0x9ED9, 0x6A02, 0x9EDA, 0x6A1B, 0x9EDB, 0x69FF,
+	0x9EDC, 0x6B0A, 0x9EDD, 0x69F9, 0x9EDE, 0x69F2, 0x9EDF, 0x69E7,
+	0x9EE0, 0x6A05, 0x9EE1, 0x69B1, 0x9EE2, 0x6A1E, 0x9EE3, 0x69ED,
+	0x9EE4, 0x6A14, 0x9EE5, 0x69EB, 0x9EE6, 0x6A0A, 0x9EE7, 0x6A12,
+	0x9EE8, 0x6AC1, 0x9EE9, 0x6A23, 0x9EEA, 0x6A13, 0x9EEB, 0x6A44,
+	0x9EEC, 0x6A0C, 0x9EED, 0x6A72, 0x9EEE, 0x6A36, 0x9EEF, 0x6A78,
+	0x9EF0, 0x6A47, 0x9EF1, 0x6A62, 0x9EF2, 0x6A59, 0x9EF3, 0x6A66,
+	0x9EF4, 0x6A48, 0x9EF5, 0x6A38, 0x9EF6, 0x6A22, 0x9EF7, 0x6A90,
+	0x9EF8, 0x6A8D, 0x9EF9, 0x6AA0, 0x9EFA, 0x6A84, 0x9EFB, 0x6AA2,
+	0x9EFC, 0x6AA3, 0x9F40, 0x6A97, 0x9F41, 0x8617, 0x9F42, 0x6ABB,
+	0x9F43, 0x6AC3, 0x9F44, 0x6AC2, 0x9F45, 0x6AB8, 0x9F46, 0x6AB3,
+	0x9F47, 0x6AAC, 0x9F48, 0x6ADE, 0x9F49, 0x6AD1, 0x9F4A, 0x6ADF,
+	0x9F4B, 0x6AAA, 0x9F4C, 0x6ADA, 0x9F4D, 0x6AEA, 0x9F4E, 0x6AFB,
+	0x9F4F, 0x6B05, 0x9F50, 0x8616, 0x9F51, 0x6AFA, 0x9F52, 0x6B12,
+	0x9F53, 0x6B16, 0x9F54, 0x9B31, 0x9F55, 0x6B1F, 0x9F56, 0x6B38,
+	0x9F57, 0x6B37, 0x9F58, 0x76DC, 0x9F59, 0x6B39, 0x9F5A, 0x98EE,
+	0x9F5B, 0x6B47, 0x9F5C, 0x6B43, 0x9F5D, 0x6B49, 0x9F5E, 0x6B50,
+	0x9F5F, 0x6B59, 0x9F60, 0x6B54, 0x9F61, 0x6B5B, 0x9F62, 0x6B5F,
+	0x9F63, 0x6B61, 0x9F64, 0x6B78, 0x9F65, 0x6B79, 0x9F66, 0x6B7F,
+	0x9F67, 0x6B80, 0x9F68, 0x6B84, 0x9F69, 0x6B83, 0x9F6A, 0x6B8D,
+	0x9F6B, 0x6B98, 0x9F6C, 0x6B95, 0x9F6D, 0x6B9E, 0x9F6E, 0x6BA4,
+	0x9F6F, 0x6BAA, 0x9F70, 0x6BAB, 0x9F71, 0x6BAF, 0x9F72, 0x6BB2,
+	0x9F73, 0x6BB1, 0x9F74, 0x6BB3, 0x9F75, 0x6BB7, 0x9F76, 0x6BBC,
+	0x9F77, 0x6BC6, 0x9F78, 0x6BCB, 0x9F79, 0x6BD3, 0x9F7A, 0x6BDF,
+	0x9F7B, 0x6BEC, 0x9F7C, 0x6BEB, 0x9F7D, 0x6BF3, 0x9F7E, 0x6BEF,
+	0x9F80, 0x9EBE, 0x9F81, 0x6C08, 0x9F82, 0x6C13, 0x9F83, 0x6C14,
+	0x9F84, 0x6C1B, 0x9F85, 0x6C24, 0x9F86, 0x6C23, 0x9F87, 0x6C5E,
+	0x9F88, 0x6C55, 0x9F89, 0x6C62, 0x9F8A, 0x6C6A, 0x9F8B, 0x6C82,
+	0x9F8C, 0x6C8D, 0x9F8D, 0x6C9A, 0x9F8E, 0x6C81, 0x9F8F, 0x6C9B,
+	0x9F90, 0x6C7E, 0x9F91, 0x6C68, 0x9F92, 0x6C73, 0x9F93, 0x6C92,
+	0x9F94, 0x6C90, 0x9F95, 0x6CC4, 0x9F96, 0x6CF1, 0x9F97, 0x6CD3,
+	0x9F98, 0x6CBD, 0x9F99, 0x6CD7, 0x9F9A, 0x6CC5, 0x9F9B, 0x6CDD,
+	0x9F9C, 0x6CAE, 0x9F9D, 0x6CB1, 0x9F9E, 0x6CBE, 0x9F9F, 0x6CBA,
+	0x9FA0, 0x6CDB, 0x9FA1, 0x6CEF, 0x9FA2, 0x6CD9, 0x9FA3, 0x6CEA,
+	0x9FA4, 0x6D1F, 0x9FA5, 0x884D, 0x9FA6, 0x6D36, 0x9FA7, 0x6D2B,
+	0x9FA8, 0x6D3D, 0x9FA9, 0x6D38, 0x9FAA, 0x6D19, 0x9FAB, 0x6D35,
+	0x9FAC, 0x6D33, 0x9FAD, 0x6D12, 0x9FAE, 0x6D0C, 0x9FAF, 0x6D63,
+	0x9FB0, 0x6D93, 0x9FB1, 0x6D64, 0x9FB2, 0x6D5A, 0x9FB3, 0x6D79,
+	0x9FB4, 0x6D59, 0x9FB5, 0x6D8E, 0x9FB6, 0x6D95, 0x9FB7, 0x6FE4,
+	0x9FB8, 0x6D85, 0x9FB9, 0x6DF9, 0x9FBA, 0x6E15, 0x9FBB, 0x6E0A,
+	0x9FBC, 0x6DB5, 0x9FBD, 0x6DC7, 0x9FBE, 0x6DE6, 0x9FBF, 0x6DB8,
+	0x9FC0, 0x6DC6, 0x9FC1, 0x6DEC, 0x9FC2, 0x6DDE, 0x9FC3, 0x6DCC,
+	0x9FC4, 0x6DE8, 0x9FC5, 0x6DD2, 0x9FC6, 0x6DC5, 0x9FC7, 0x6DFA,
+	0x9FC8, 0x6DD9, 0x9FC9, 0x6DE4, 0x9FCA, 0x6DD5, 0x9FCB, 0x6DEA,
+	0x9FCC, 0x6DEE, 0x9FCD, 0x6E2D, 0x9FCE, 0x6E6E, 0x9FCF, 0x6E2E,
+	0x9FD0, 0x6E19, 0x9FD1, 0x6E72, 0x9FD2, 0x6E5F, 0x9FD3, 0x6E3E,
+	0x9FD4, 0x6E23, 0x9FD5, 0x6E6B, 0x9FD6, 0x6E2B, 0x9FD7, 0x6E76,
+	0x9FD8, 0x6E4D, 0x9FD9, 0x6E1F, 0x9FDA, 0x6E43, 0x9FDB, 0x6E3A,
+	0x9FDC, 0x6E4E, 0x9FDD, 0x6E24, 0x9FDE, 0x6EFF, 0x9FDF, 0x6E1D,
+	0x9FE0, 0x6E38, 0x9FE1, 0x6E82, 0x9FE2, 0x6EAA, 0x9FE3, 0x6E98,
+	0x9FE4, 0x6EC9, 0x9FE5, 0x6EB7, 0x9FE6, 0x6ED3, 0x9FE7, 0x6EBD,
+	0x9FE8, 0x6EAF, 0x9FE9, 0x6EC4, 0x9FEA, 0x6EB2, 0x9FEB, 0x6ED4,
+	0x9FEC, 0x6ED5, 0x9FED, 0x6E8F, 0x9FEE, 0x6EA5, 0x9FEF, 0x6EC2,
+	0x9FF0, 0x6E9F, 0x9FF1, 0x6F41, 0x9FF2, 0x6F11, 0x9FF3, 0x704C,
+	0x9FF4, 0x6EEC, 0x9FF5, 0x6EF8, 0x9FF6, 0x6EFE, 0x9FF7, 0x6F3F,
+	0x9FF8, 0x6EF2, 0x9FF9, 0x6F31, 0x9FFA, 0x6EEF, 0x9FFB, 0x6F32,
+	0x9FFC, 0x6ECC, 0xE040, 0x6F3E, 0xE041, 0x6F13, 0xE042, 0x6EF7,
+	0xE043, 0x6F86, 0xE044, 0x6F7A, 0xE045, 0x6F78, 0xE046, 0x6F81,
+	0xE047, 0x6F80, 0xE048, 0x6F6F, 0xE049, 0x6F5B, 0xE04A, 0x6FF3,
+	0xE04B, 0x6F6D, 0xE04C, 0x6F82, 0xE04D, 0x6F7C, 0xE04E, 0x6F58,
+	0xE04F, 0x6F8E, 0xE050, 0x6F91, 0xE051, 0x6FC2, 0xE052, 0x6F66,
+	0xE053, 0x6FB3, 0xE054, 0x6FA3, 0xE055, 0x6FA1, 0xE056, 0x6FA4,
+	0xE057, 0x6FB9, 0xE058, 0x6FC6, 0xE059, 0x6FAA, 0xE05A, 0x6FDF,
+	0xE05B, 0x6FD5, 0xE05C, 0x6FEC, 0xE05D, 0x6FD4, 0xE05E, 0x6FD8,
+	0xE05F, 0x6FF1, 0xE060, 0x6FEE, 0xE061, 0x6FDB, 0xE062, 0x7009,
+	0xE063, 0x700B, 0xE064, 0x6FFA, 0xE065, 0x7011, 0xE066, 0x7001,
+	0xE067, 0x700F, 0xE068, 0x6FFE, 0xE069, 0x701B, 0xE06A, 0x701A,
+	0xE06B, 0x6F74, 0xE06C, 0x701D, 0xE06D, 0x7018, 0xE06E, 0x701F,
+	0xE06F, 0x7030, 0xE070, 0x703E, 0xE071, 0x7032, 0xE072, 0x7051,
+	0xE073, 0x7063, 0xE074, 0x7099, 0xE075, 0x7092, 0xE076, 0x70AF,
+	0xE077, 0x70F1, 0xE078, 0x70AC, 0xE079, 0x70B8, 0xE07A, 0x70B3,
+	0xE07B, 0x70AE, 0xE07C, 0x70DF, 0xE07D, 0x70CB, 0xE07E, 0x70DD,
+	0xE080, 0x70D9, 0xE081, 0x7109, 0xE082, 0x70FD, 0xE083, 0x711C,
+	0xE084, 0x7119, 0xE085, 0x7165, 0xE086, 0x7155, 0xE087, 0x7188,
+	0xE088, 0x7166, 0xE089, 0x7162, 0xE08A, 0x714C, 0xE08B, 0x7156,
+	0xE08C, 0x716C, 0xE08D, 0x718F, 0xE08E, 0x71FB, 0xE08F, 0x7184,
+	0xE090, 0x7195, 0xE091, 0x71A8, 0xE092, 0x71AC, 0xE093, 0x71D7,
+	0xE094, 0x71B9, 0xE095, 0x71BE, 0xE096, 0x71D2, 0xE097, 0x71C9,
+	0xE098, 0x71D4, 0xE099, 0x71CE, 0xE09A, 0x71E0, 0xE09B, 0x71EC,
+	0xE09C, 0x71E7, 0xE09D, 0x71F5, 0xE09E, 0x71FC, 0xE09F, 0x71F9,
+	0xE0A0, 0x71FF, 0xE0A1, 0x720D, 0xE0A2, 0x7210, 0xE0A3, 0x721B,
+	0xE0A4, 0x7228, 0xE0A5, 0x722D, 0xE0A6, 0x722C, 0xE0A7, 0x7230,
+	0xE0A8, 0x7232, 0xE0A9, 0x723B, 0xE0AA, 0x723C, 0xE0AB, 0x723F,
+	0xE0AC, 0x7240, 0xE0AD, 0x7246, 0xE0AE, 0x724B, 0xE0AF, 0x7258,
+	0xE0B0, 0x7274, 0xE0B1, 0x727E, 0xE0B2, 0x7282, 0xE0B3, 0x7281,
+	0xE0B4, 0x7287, 0xE0B5, 0x7292, 0xE0B6, 0x7296, 0xE0B7, 0x72A2,
+	0xE0B8, 0x72A7, 0xE0B9, 0x72B9, 0xE0BA, 0x72B2, 0xE0BB, 0x72C3,
+	0xE0BC, 0x72C6, 0xE0BD, 0x72C4, 0xE0BE, 0x72CE, 0xE0BF, 0x72D2,
+	0xE0C0, 0x72E2, 0xE0C1, 0x72E0, 0xE0C2, 0x72E1, 0xE0C3, 0x72F9,
+	0xE0C4, 0x72F7, 0xE0C5, 0x500F, 0xE0C6, 0x7317, 0xE0C7, 0x730A,
+	0xE0C8, 0x731C, 0xE0C9, 0x7316, 0xE0CA, 0x731D, 0xE0CB, 0x7334,
+	0xE0CC, 0x732F, 0xE0CD, 0x7329, 0xE0CE, 0x7325, 0xE0CF, 0x733E,
+	0xE0D0, 0x734E, 0xE0D1, 0x734F, 0xE0D2, 0x9ED8, 0xE0D3, 0x7357,
+	0xE0D4, 0x736A, 0xE0D5, 0x7368, 0xE0D6, 0x7370, 0xE0D7, 0x7378,
+	0xE0D8, 0x7375, 0xE0D9, 0x737B, 0xE0DA, 0x737A, 0xE0DB, 0x73C8,
+	0xE0DC, 0x73B3, 0xE0DD, 0x73CE, 0xE0DE, 0x73BB, 0xE0DF, 0x73C0,
+	0xE0E0, 0x73E5, 0xE0E1, 0x73EE, 0xE0E2, 0x73DE, 0xE0E3, 0x74A2,
+	0xE0E4, 0x7405, 0xE0E5, 0x746F, 0xE0E6, 0x7425, 0xE0E7, 0x73F8,
+	0xE0E8, 0x7432, 0xE0E9, 0x743A, 0xE0EA, 0x7455, 0xE0EB, 0x743F,
+	0xE0EC, 0x745F, 0xE0ED, 0x7459, 0xE0EE, 0x7441, 0xE0EF, 0x745C,
+	0xE0F0, 0x7469, 0xE0F1, 0x7470, 0xE0F2, 0x7463, 0xE0F3, 0x746A,
+	0xE0F4, 0x7476, 0xE0F5, 0x747E, 0xE0F6, 0x748B, 0xE0F7, 0x749E,
+	0xE0F8, 0x74A7, 0xE0F9, 0x74CA, 0xE0FA, 0x74CF, 0xE0FB, 0x74D4,
+	0xE0FC, 0x73F1, 0xE140, 0x74E0, 0xE141, 0x74E3, 0xE142, 0x74E7,
+	0xE143, 0x74E9, 0xE144, 0x74EE, 0xE145, 0x74F2, 0xE146, 0x74F0,
+	0xE147, 0x74F1, 0xE148, 0x74F8, 0xE149, 0x74F7, 0xE14A, 0x7504,
+	0xE14B, 0x7503, 0xE14C, 0x7505, 0xE14D, 0x750C, 0xE14E, 0x750E,
+	0xE14F, 0x750D, 0xE150, 0x7515, 0xE151, 0x7513, 0xE152, 0x751E,
+	0xE153, 0x7526, 0xE154, 0x752C, 0xE155, 0x753C, 0xE156, 0x7544,
+	0xE157, 0x754D, 0xE158, 0x754A, 0xE159, 0x7549, 0xE15A, 0x755B,
+	0xE15B, 0x7546, 0xE15C, 0x755A, 0xE15D, 0x7569, 0xE15E, 0x7564,
+	0xE15F, 0x7567, 0xE160, 0x756B, 0xE161, 0x756D, 0xE162, 0x7578,
+	0xE163, 0x7576, 0xE164, 0x7586, 0xE165, 0x7587, 0xE166, 0x7574,
+	0xE167, 0x758A, 0xE168, 0x7589, 0xE169, 0x7582, 0xE16A, 0x7594,
+	0xE16B, 0x759A, 0xE16C, 0x759D, 0xE16D, 0x75A5, 0xE16E, 0x75A3,
+	0xE16F, 0x75C2, 0xE170, 0x75B3, 0xE171, 0x75C3, 0xE172, 0x75B5,
+	0xE173, 0x75BD, 0xE174, 0x75B8, 0xE175, 0x75BC, 0xE176, 0x75B1,
+	0xE177, 0x75CD, 0xE178, 0x75CA, 0xE179, 0x75D2, 0xE17A, 0x75D9,
+	0xE17B, 0x75E3, 0xE17C, 0x75DE, 0xE17D, 0x75FE, 0xE17E, 0x75FF,
+	0xE180, 0x75FC, 0xE181, 0x7601, 0xE182, 0x75F0, 0xE183, 0x75FA,
+	0xE184, 0x75F2, 0xE185, 0x75F3, 0xE186, 0x760B, 0xE187, 0x760D,
+	0xE188, 0x7609, 0xE189, 0x761F, 0xE18A, 0x7627, 0xE18B, 0x7620,
+	0xE18C, 0x7621, 0xE18D, 0x7622, 0xE18E, 0x7624, 0xE18F, 0x7634,
+	0xE190, 0x7630, 0xE191, 0x763B, 0xE192, 0x7647, 0xE193, 0x7648,
+	0xE194, 0x7646, 0xE195, 0x765C, 0xE196, 0x7658, 0xE197, 0x7661,
+	0xE198, 0x7662, 0xE199, 0x7668, 0xE19A, 0x7669, 0xE19B, 0x766A,
+	0xE19C, 0x7667, 0xE19D, 0x766C, 0xE19E, 0x7670, 0xE19F, 0x7672,
+	0xE1A0, 0x7676, 0xE1A1, 0x7678, 0xE1A2, 0x767C, 0xE1A3, 0x7680,
+	0xE1A4, 0x7683, 0xE1A5, 0x7688, 0xE1A6, 0x768B, 0xE1A7, 0x768E,
+	0xE1A8, 0x7696, 0xE1A9, 0x7693, 0xE1AA, 0x7699, 0xE1AB, 0x769A,
+	0xE1AC, 0x76B0, 0xE1AD, 0x76B4, 0xE1AE, 0x76B8, 0xE1AF, 0x76B9,
+	0xE1B0, 0x76BA, 0xE1B1, 0x76C2, 0xE1B2, 0x76CD, 0xE1B3, 0x76D6,
+	0xE1B4, 0x76D2, 0xE1B5, 0x76DE, 0xE1B6, 0x76E1, 0xE1B7, 0x76E5,
+	0xE1B8, 0x76E7, 0xE1B9, 0x76EA, 0xE1BA, 0x862F, 0xE1BB, 0x76FB,
+	0xE1BC, 0x7708, 0xE1BD, 0x7707, 0xE1BE, 0x7704, 0xE1BF, 0x7729,
+	0xE1C0, 0x7724, 0xE1C1, 0x771E, 0xE1C2, 0x7725, 0xE1C3, 0x7726,
+	0xE1C4, 0x771B, 0xE1C5, 0x7737, 0xE1C6, 0x7738, 0xE1C7, 0x7747,
+	0xE1C8, 0x775A, 0xE1C9, 0x7768, 0xE1CA, 0x776B, 0xE1CB, 0x775B,
+	0xE1CC, 0x7765, 0xE1CD, 0x777F, 0xE1CE, 0x777E, 0xE1CF, 0x7779,
+	0xE1D0, 0x778E, 0xE1D1, 0x778B, 0xE1D2, 0x7791, 0xE1D3, 0x77A0,
+	0xE1D4, 0x779E, 0xE1D5, 0x77B0, 0xE1D6, 0x77B6, 0xE1D7, 0x77B9,
+	0xE1D8, 0x77BF, 0xE1D9, 0x77BC, 0xE1DA, 0x77BD, 0xE1DB, 0x77BB,
+	0xE1DC, 0x77C7, 0xE1DD, 0x77CD, 0xE1DE, 0x77D7, 0xE1DF, 0x77DA,
+	0xE1E0, 0x77DC, 0xE1E1, 0x77E3, 0xE1E2, 0x77EE, 0xE1E3, 0x77FC,
+	0xE1E4, 0x780C, 0xE1E5, 0x7812, 0xE1E6, 0x7926, 0xE1E7, 0x7820,
+	0xE1E8, 0x792A, 0xE1E9, 0x7845, 0xE1EA, 0x788E, 0xE1EB, 0x7874,
+	0xE1EC, 0x7886, 0xE1ED, 0x787C, 0xE1EE, 0x789A, 0xE1EF, 0x788C,
+	0xE1F0, 0x78A3, 0xE1F1, 0x78B5, 0xE1F2, 0x78AA, 0xE1F3, 0x78AF,
+	0xE1F4, 0x78D1, 0xE1F5, 0x78C6, 0xE1F6, 0x78CB, 0xE1F7, 0x78D4,
+	0xE1F8, 0x78BE, 0xE1F9, 0x78BC, 0xE1FA, 0x78C5, 0xE1FB, 0x78CA,
+	0xE1FC, 0x78EC, 0xE240, 0x78E7, 0xE241, 0x78DA, 0xE242, 0x78FD,
+	0xE243, 0x78F4, 0xE244, 0x7907, 0xE245, 0x7912, 0xE246, 0x7911,
+	0xE247, 0x7919, 0xE248, 0x792C, 0xE249, 0x792B, 0xE24A, 0x7940,
+	0xE24B, 0x7960, 0xE24C, 0x7957, 0xE24D, 0x795F, 0xE24E, 0x795A,
+	0xE24F, 0x7955, 0xE250, 0x7953, 0xE251, 0x797A, 0xE252, 0x797F,
+	0xE253, 0x798A, 0xE254, 0x799D, 0xE255, 0x79A7, 0xE256, 0x9F4B,
+	0xE257, 0x79AA, 0xE258, 0x79AE, 0xE259, 0x79B3, 0xE25A, 0x79B9,
+	0xE25B, 0x79BA, 0xE25C, 0x79C9, 0xE25D, 0x79D5, 0xE25E, 0x79E7,
+	0xE25F, 0x79EC, 0xE260, 0x79E1, 0xE261, 0x79E3, 0xE262, 0x7A08,
+	0xE263, 0x7A0D, 0xE264, 0x7A18, 0xE265, 0x7A19, 0xE266, 0x7A20,
+	0xE267, 0x7A1F, 0xE268, 0x7980, 0xE269, 0x7A31, 0xE26A, 0x7A3B,
+	0xE26B, 0x7A3E, 0xE26C, 0x7A37, 0xE26D, 0x7A43, 0xE26E, 0x7A57,
+	0xE26F, 0x7A49, 0xE270, 0x7A61, 0xE271, 0x7A62, 0xE272, 0x7A69,
+	0xE273, 0x9F9D, 0xE274, 0x7A70, 0xE275, 0x7A79, 0xE276, 0x7A7D,
+	0xE277, 0x7A88, 0xE278, 0x7A97, 0xE279, 0x7A95, 0xE27A, 0x7A98,
+	0xE27B, 0x7A96, 0xE27C, 0x7AA9, 0xE27D, 0x7AC8, 0xE27E, 0x7AB0,
+	0xE280, 0x7AB6, 0xE281, 0x7AC5, 0xE282, 0x7AC4, 0xE283, 0x7ABF,
+	0xE284, 0x9083, 0xE285, 0x7AC7, 0xE286, 0x7ACA, 0xE287, 0x7ACD,
+	0xE288, 0x7ACF, 0xE289, 0x7AD5, 0xE28A, 0x7AD3, 0xE28B, 0x7AD9,
+	0xE28C, 0x7ADA, 0xE28D, 0x7ADD, 0xE28E, 0x7AE1, 0xE28F, 0x7AE2,
+	0xE290, 0x7AE6, 0xE291, 0x7AED, 0xE292, 0x7AF0, 0xE293, 0x7B02,
+	0xE294, 0x7B0F, 0xE295, 0x7B0A, 0xE296, 0x7B06, 0xE297, 0x7B33,
+	0xE298, 0x7B18, 0xE299, 0x7B19, 0xE29A, 0x7B1E, 0xE29B, 0x7B35,
+	0xE29C, 0x7B28, 0xE29D, 0x7B36, 0xE29E, 0x7B50, 0xE29F, 0x7B7A,
+	0xE2A0, 0x7B04, 0xE2A1, 0x7B4D, 0xE2A2, 0x7B0B, 0xE2A3, 0x7B4C,
+	0xE2A4, 0x7B45, 0xE2A5, 0x7B75, 0xE2A6, 0x7B65, 0xE2A7, 0x7B74,
+	0xE2A8, 0x7B67, 0xE2A9, 0x7B70, 0xE2AA, 0x7B71, 0xE2AB, 0x7B6C,
+	0xE2AC, 0x7B6E, 0xE2AD, 0x7B9D, 0xE2AE, 0x7B98, 0xE2AF, 0x7B9F,
+	0xE2B0, 0x7B8D, 0xE2B1, 0x7B9C, 0xE2B2, 0x7B9A, 0xE2B3, 0x7B8B,
+	0xE2B4, 0x7B92, 0xE2B5, 0x7B8F, 0xE2B6, 0x7B5D, 0xE2B7, 0x7B99,
+	0xE2B8, 0x7BCB, 0xE2B9, 0x7BC1, 0xE2BA, 0x7BCC, 0xE2BB, 0x7BCF,
+	0xE2BC, 0x7BB4, 0xE2BD, 0x7BC6, 0xE2BE, 0x7BDD, 0xE2BF, 0x7BE9,
+	0xE2C0, 0x7C11, 0xE2C1, 0x7C14, 0xE2C2, 0x7BE6, 0xE2C3, 0x7BE5,
+	0xE2C4, 0x7C60, 0xE2C5, 0x7C00, 0xE2C6, 0x7C07, 0xE2C7, 0x7C13,
+	0xE2C8, 0x7BF3, 0xE2C9, 0x7BF7, 0xE2CA, 0x7C17, 0xE2CB, 0x7C0D,
+	0xE2CC, 0x7BF6, 0xE2CD, 0x7C23, 0xE2CE, 0x7C27, 0xE2CF, 0x7C2A,
+	0xE2D0, 0x7C1F, 0xE2D1, 0x7C37, 0xE2D2, 0x7C2B, 0xE2D3, 0x7C3D,
+	0xE2D4, 0x7C4C, 0xE2D5, 0x7C43, 0xE2D6, 0x7C54, 0xE2D7, 0x7C4F,
+	0xE2D8, 0x7C40, 0xE2D9, 0x7C50, 0xE2DA, 0x7C58, 0xE2DB, 0x7C5F,
+	0xE2DC, 0x7C64, 0xE2DD, 0x7C56, 0xE2DE, 0x7C65, 0xE2DF, 0x7C6C,
+	0xE2E0, 0x7C75, 0xE2E1, 0x7C83, 0xE2E2, 0x7C90, 0xE2E3, 0x7CA4,
+	0xE2E4, 0x7CAD, 0xE2E5, 0x7CA2, 0xE2E6, 0x7CAB, 0xE2E7, 0x7CA1,
+	0xE2E8, 0x7CA8, 0xE2E9, 0x7CB3, 0xE2EA, 0x7CB2, 0xE2EB, 0x7CB1,
+	0xE2EC, 0x7CAE, 0xE2ED, 0x7CB9, 0xE2EE, 0x7CBD, 0xE2EF, 0x7CC0,
+	0xE2F0, 0x7CC5, 0xE2F1, 0x7CC2, 0xE2F2, 0x7CD8, 0xE2F3, 0x7CD2,
+	0xE2F4, 0x7CDC, 0xE2F5, 0x7CE2, 0xE2F6, 0x9B3B, 0xE2F7, 0x7CEF,
+	0xE2F8, 0x7CF2, 0xE2F9, 0x7CF4, 0xE2FA, 0x7CF6, 0xE2FB, 0x7CFA,
+	0xE2FC, 0x7D06, 0xE340, 0x7D02, 0xE341, 0x7D1C, 0xE342, 0x7D15,
+	0xE343, 0x7D0A, 0xE344, 0x7D45, 0xE345, 0x7D4B, 0xE346, 0x7D2E,
+	0xE347, 0x7D32, 0xE348, 0x7D3F, 0xE349, 0x7D35, 0xE34A, 0x7D46,
+	0xE34B, 0x7D73, 0xE34C, 0x7D56, 0xE34D, 0x7D4E, 0xE34E, 0x7D72,
+	0xE34F, 0x7D68, 0xE350, 0x7D6E, 0xE351, 0x7D4F, 0xE352, 0x7D63,
+	0xE353, 0x7D93, 0xE354, 0x7D89, 0xE355, 0x7D5B, 0xE356, 0x7D8F,
+	0xE357, 0x7D7D, 0xE358, 0x7D9B, 0xE359, 0x7DBA, 0xE35A, 0x7DAE,
+	0xE35B, 0x7DA3, 0xE35C, 0x7DB5, 0xE35D, 0x7DC7, 0xE35E, 0x7DBD,
+	0xE35F, 0x7DAB, 0xE360, 0x7E3D, 0xE361, 0x7DA2, 0xE362, 0x7DAF,
+	0xE363, 0x7DDC, 0xE364, 0x7DB8, 0xE365, 0x7D9F, 0xE366, 0x7DB0,
+	0xE367, 0x7DD8, 0xE368, 0x7DDD, 0xE369, 0x7DE4, 0xE36A, 0x7DDE,
+	0xE36B, 0x7DFB, 0xE36C, 0x7DF2, 0xE36D, 0x7DE1, 0xE36E, 0x7E05,
+	0xE36F, 0x7E0A, 0xE370, 0x7E23, 0xE371, 0x7E21, 0xE372, 0x7E12,
+	0xE373, 0x7E31, 0xE374, 0x7E1F, 0xE375, 0x7E09, 0xE376, 0x7E0B,
+	0xE377, 0x7E22, 0xE378, 0x7E46, 0xE379, 0x7E66, 0xE37A, 0x7E3B,
+	0xE37B, 0x7E35, 0xE37C, 0x7E39, 0xE37D, 0x7E43, 0xE37E, 0x7E37,
+	0xE380, 0x7E32, 0xE381, 0x7E3A, 0xE382, 0x7E67, 0xE383, 0x7E5D,
+	0xE384, 0x7E56, 0xE385, 0x7E5E, 0xE386, 0x7E59, 0xE387, 0x7E5A,
+	0xE388, 0x7E79, 0xE389, 0x7E6A, 0xE38A, 0x7E69, 0xE38B, 0x7E7C,
+	0xE38C, 0x7E7B, 0xE38D, 0x7E83, 0xE38E, 0x7DD5, 0xE38F, 0x7E7D,
+	0xE390, 0x8FAE, 0xE391, 0x7E7F, 0xE392, 0x7E88, 0xE393, 0x7E89,
+	0xE394, 0x7E8C, 0xE395, 0x7E92, 0xE396, 0x7E90, 0xE397, 0x7E93,
+	0xE398, 0x7E94, 0xE399, 0x7E96, 0xE39A, 0x7E8E, 0xE39B, 0x7E9B,
+	0xE39C, 0x7E9C, 0xE39D, 0x7F38, 0xE39E, 0x7F3A, 0xE39F, 0x7F45,
+	0xE3A0, 0x7F4C, 0xE3A1, 0x7F4D, 0xE3A2, 0x7F4E, 0xE3A3, 0x7F50,
+	0xE3A4, 0x7F51, 0xE3A5, 0x7F55, 0xE3A6, 0x7F54, 0xE3A7, 0x7F58,
+	0xE3A8, 0x7F5F, 0xE3A9, 0x7F60, 0xE3AA, 0x7F68, 0xE3AB, 0x7F69,
+	0xE3AC, 0x7F67, 0xE3AD, 0x7F78, 0xE3AE, 0x7F82, 0xE3AF, 0x7F86,
+	0xE3B0, 0x7F83, 0xE3B1, 0x7F88, 0xE3B2, 0x7F87, 0xE3B3, 0x7F8C,
+	0xE3B4, 0x7F94, 0xE3B5, 0x7F9E, 0xE3B6, 0x7F9D, 0xE3B7, 0x7F9A,
+	0xE3B8, 0x7FA3, 0xE3B9, 0x7FAF, 0xE3BA, 0x7FB2, 0xE3BB, 0x7FB9,
+	0xE3BC, 0x7FAE, 0xE3BD, 0x7FB6, 0xE3BE, 0x7FB8, 0xE3BF, 0x8B71,
+	0xE3C0, 0x7FC5, 0xE3C1, 0x7FC6, 0xE3C2, 0x7FCA, 0xE3C3, 0x7FD5,
+	0xE3C4, 0x7FD4, 0xE3C5, 0x7FE1, 0xE3C6, 0x7FE6, 0xE3C7, 0x7FE9,
+	0xE3C8, 0x7FF3, 0xE3C9, 0x7FF9, 0xE3CA, 0x98DC, 0xE3CB, 0x8006,
+	0xE3CC, 0x8004, 0xE3CD, 0x800B, 0xE3CE, 0x8012, 0xE3CF, 0x8018,
+	0xE3D0, 0x8019, 0xE3D1, 0x801C, 0xE3D2, 0x8021, 0xE3D3, 0x8028,
+	0xE3D4, 0x803F, 0xE3D5, 0x803B, 0xE3D6, 0x804A, 0xE3D7, 0x8046,
+	0xE3D8, 0x8052, 0xE3D9, 0x8058, 0xE3DA, 0x805A, 0xE3DB, 0x805F,
+	0xE3DC, 0x8062, 0xE3DD, 0x8068, 0xE3DE, 0x8073, 0xE3DF, 0x8072,
+	0xE3E0, 0x8070, 0xE3E1, 0x8076, 0xE3E2, 0x8079, 0xE3E3, 0x807D,
+	0xE3E4, 0x807F, 0xE3E5, 0x8084, 0xE3E6, 0x8086, 0xE3E7, 0x8085,
+	0xE3E8, 0x809B, 0xE3E9, 0x8093, 0xE3EA, 0x809A, 0xE3EB, 0x80AD,
+	0xE3EC, 0x5190, 0xE3ED, 0x80AC, 0xE3EE, 0x80DB, 0xE3EF, 0x80E5,
+	0xE3F0, 0x80D9, 0xE3F1, 0x80DD, 0xE3F2, 0x80C4, 0xE3F3, 0x80DA,
+	0xE3F4, 0x80D6, 0xE3F5, 0x8109, 0xE3F6, 0x80EF, 0xE3F7, 0x80F1,
+	0xE3F8, 0x811B, 0xE3F9, 0x8129, 0xE3FA, 0x8123, 0xE3FB, 0x812F,
+	0xE3FC, 0x814B, 0xE440, 0x968B, 0xE441, 0x8146, 0xE442, 0x813E,
+	0xE443, 0x8153, 0xE444, 0x8151, 0xE445, 0x80FC, 0xE446, 0x8171,
+	0xE447, 0x816E, 0xE448, 0x8165, 0xE449, 0x8166, 0xE44A, 0x8174,
+	0xE44B, 0x8183, 0xE44C, 0x8188, 0xE44D, 0x818A, 0xE44E, 0x8180,
+	0xE44F, 0x8182, 0xE450, 0x81A0, 0xE451, 0x8195, 0xE452, 0x81A4,
+	0xE453, 0x81A3, 0xE454, 0x815F, 0xE455, 0x8193, 0xE456, 0x81A9,
+	0xE457, 0x81B0, 0xE458, 0x81B5, 0xE459, 0x81BE, 0xE45A, 0x81B8,
+	0xE45B, 0x81BD, 0xE45C, 0x81C0, 0xE45D, 0x81C2, 0xE45E, 0x81BA,
+	0xE45F, 0x81C9, 0xE460, 0x81CD, 0xE461, 0x81D1, 0xE462, 0x81D9,
+	0xE463, 0x81D8, 0xE464, 0x81C8, 0xE465, 0x81DA, 0xE466, 0x81DF,
+	0xE467, 0x81E0, 0xE468, 0x81E7, 0xE469, 0x81FA, 0xE46A, 0x81FB,
+	0xE46B, 0x81FE, 0xE46C, 0x8201, 0xE46D, 0x8202, 0xE46E, 0x8205,
+	0xE46F, 0x8207, 0xE470, 0x820A, 0xE471, 0x820D, 0xE472, 0x8210,
+	0xE473, 0x8216, 0xE474, 0x8229, 0xE475, 0x822B, 0xE476, 0x8238,
+	0xE477, 0x8233, 0xE478, 0x8240, 0xE479, 0x8259, 0xE47A, 0x8258,
+	0xE47B, 0x825D, 0xE47C, 0x825A, 0xE47D, 0x825F, 0xE47E, 0x8264,
+	0xE480, 0x8262, 0xE481, 0x8268, 0xE482, 0x826A, 0xE483, 0x826B,
+	0xE484, 0x822E, 0xE485, 0x8271, 0xE486, 0x8277, 0xE487, 0x8278,
+	0xE488, 0x827E, 0xE489, 0x828D, 0xE48A, 0x8292, 0xE48B, 0x82AB,
+	0xE48C, 0x829F, 0xE48D, 0x82BB, 0xE48E, 0x82AC, 0xE48F, 0x82E1,
+	0xE490, 0x82E3, 0xE491, 0x82DF, 0xE492, 0x82D2, 0xE493, 0x82F4,
+	0xE494, 0x82F3, 0xE495, 0x82FA, 0xE496, 0x8393, 0xE497, 0x8303,
+	0xE498, 0x82FB, 0xE499, 0x82F9, 0xE49A, 0x82DE, 0xE49B, 0x8306,
+	0xE49C, 0x82DC, 0xE49D, 0x8309, 0xE49E, 0x82D9, 0xE49F, 0x8335,
+	0xE4A0, 0x8334, 0xE4A1, 0x8316, 0xE4A2, 0x8332, 0xE4A3, 0x8331,
+	0xE4A4, 0x8340, 0xE4A5, 0x8339, 0xE4A6, 0x8350, 0xE4A7, 0x8345,
+	0xE4A8, 0x832F, 0xE4A9, 0x832B, 0xE4AA, 0x8317, 0xE4AB, 0x8318,
+	0xE4AC, 0x8385, 0xE4AD, 0x839A, 0xE4AE, 0x83AA, 0xE4AF, 0x839F,
+	0xE4B0, 0x83A2, 0xE4B1, 0x8396, 0xE4B2, 0x8323, 0xE4B3, 0x838E,
+	0xE4B4, 0x8387, 0xE4B5, 0x838A, 0xE4B6, 0x837C, 0xE4B7, 0x83B5,
+	0xE4B8, 0x8373, 0xE4B9, 0x8375, 0xE4BA, 0x83A0, 0xE4BB, 0x8389,
+	0xE4BC, 0x83A8, 0xE4BD, 0x83F4, 0xE4BE, 0x8413, 0xE4BF, 0x83EB,
+	0xE4C0, 0x83CE, 0xE4C1, 0x83FD, 0xE4C2, 0x8403, 0xE4C3, 0x83D8,
+	0xE4C4, 0x840B, 0xE4C5, 0x83C1, 0xE4C6, 0x83F7, 0xE4C7, 0x8407,
+	0xE4C8, 0x83E0, 0xE4C9, 0x83F2, 0xE4CA, 0x840D, 0xE4CB, 0x8422,
+	0xE4CC, 0x8420, 0xE4CD, 0x83BD, 0xE4CE, 0x8438, 0xE4CF, 0x8506,
+	0xE4D0, 0x83FB, 0xE4D1, 0x846D, 0xE4D2, 0x842A, 0xE4D3, 0x843C,
+	0xE4D4, 0x855A, 0xE4D5, 0x8484, 0xE4D6, 0x8477, 0xE4D7, 0x846B,
+	0xE4D8, 0x84AD, 0xE4D9, 0x846E, 0xE4DA, 0x8482, 0xE4DB, 0x8469,
+	0xE4DC, 0x8446, 0xE4DD, 0x842C, 0xE4DE, 0x846F, 0xE4DF, 0x8479,
+	0xE4E0, 0x8435, 0xE4E1, 0x84CA, 0xE4E2, 0x8462, 0xE4E3, 0x84B9,
+	0xE4E4, 0x84BF, 0xE4E5, 0x849F, 0xE4E6, 0x84D9, 0xE4E7, 0x84CD,
+	0xE4E8, 0x84BB, 0xE4E9, 0x84DA, 0xE4EA, 0x84D0, 0xE4EB, 0x84C1,
+	0xE4EC, 0x84C6, 0xE4ED, 0x84D6, 0xE4EE, 0x84A1, 0xE4EF, 0x8521,
+	0xE4F0, 0x84FF, 0xE4F1, 0x84F4, 0xE4F2, 0x8517, 0xE4F3, 0x8518,
+	0xE4F4, 0x852C, 0xE4F5, 0x851F, 0xE4F6, 0x8515, 0xE4F7, 0x8514,
+	0xE4F8, 0x84FC, 0xE4F9, 0x8540, 0xE4FA, 0x8563, 0xE4FB, 0x8558,
+	0xE4FC, 0x8548, 0xE540, 0x8541, 0xE541, 0x8602, 0xE542, 0x854B,
+	0xE543, 0x8555, 0xE544, 0x8580, 0xE545, 0x85A4, 0xE546, 0x8588,
+	0xE547, 0x8591, 0xE548, 0x858A, 0xE549, 0x85A8, 0xE54A, 0x856D,
+	0xE54B, 0x8594, 0xE54C, 0x859B, 0xE54D, 0x85EA, 0xE54E, 0x8587,
+	0xE54F, 0x859C, 0xE550, 0x8577, 0xE551, 0x857E, 0xE552, 0x8590,
+	0xE553, 0x85C9, 0xE554, 0x85BA, 0xE555, 0x85CF, 0xE556, 0x85B9,
+	0xE557, 0x85D0, 0xE558, 0x85D5, 0xE559, 0x85DD, 0xE55A, 0x85E5,
+	0xE55B, 0x85DC, 0xE55C, 0x85F9, 0xE55D, 0x860A, 0xE55E, 0x8613,
+	0xE55F, 0x860B, 0xE560, 0x85FE, 0xE561, 0x85FA, 0xE562, 0x8606,
+	0xE563, 0x8622, 0xE564, 0x861A, 0xE565, 0x8630, 0xE566, 0x863F,
+	0xE567, 0x864D, 0xE568, 0x4E55, 0xE569, 0x8654, 0xE56A, 0x865F,
+	0xE56B, 0x8667, 0xE56C, 0x8671, 0xE56D, 0x8693, 0xE56E, 0x86A3,
+	0xE56F, 0x86A9, 0xE570, 0x86AA, 0xE571, 0x868B, 0xE572, 0x868C,
+	0xE573, 0x86B6, 0xE574, 0x86AF, 0xE575, 0x86C4, 0xE576, 0x86C6,
+	0xE577, 0x86B0, 0xE578, 0x86C9, 0xE579, 0x8823, 0xE57A, 0x86AB,
+	0xE57B, 0x86D4, 0xE57C, 0x86DE, 0xE57D, 0x86E9, 0xE57E, 0x86EC,
+	0xE580, 0x86DF, 0xE581, 0x86DB, 0xE582, 0x86EF, 0xE583, 0x8712,
+	0xE584, 0x8706, 0xE585, 0x8708, 0xE586, 0x8700, 0xE587, 0x8703,
+	0xE588, 0x86FB, 0xE589, 0x8711, 0xE58A, 0x8709, 0xE58B, 0x870D,
+	0xE58C, 0x86F9, 0xE58D, 0x870A, 0xE58E, 0x8734, 0xE58F, 0x873F,
+	0xE590, 0x8737, 0xE591, 0x873B, 0xE592, 0x8725, 0xE593, 0x8729,
+	0xE594, 0x871A, 0xE595, 0x8760, 0xE596, 0x875F, 0xE597, 0x8778,
+	0xE598, 0x874C, 0xE599, 0x874E, 0xE59A, 0x8774, 0xE59B, 0x8757,
+	0xE59C, 0x8768, 0xE59D, 0x876E, 0xE59E, 0x8759, 0xE59F, 0x8753,
+	0xE5A0, 0x8763, 0xE5A1, 0x876A, 0xE5A2, 0x8805, 0xE5A3, 0x87A2,
+	0xE5A4, 0x879F, 0xE5A5, 0x8782, 0xE5A6, 0x87AF, 0xE5A7, 0x87CB,
+	0xE5A8, 0x87BD, 0xE5A9, 0x87C0, 0xE5AA, 0x87D0, 0xE5AB, 0x96D6,
+	0xE5AC, 0x87AB, 0xE5AD, 0x87C4, 0xE5AE, 0x87B3, 0xE5AF, 0x87C7,
+	0xE5B0, 0x87C6, 0xE5B1, 0x87BB, 0xE5B2, 0x87EF, 0xE5B3, 0x87F2,
+	0xE5B4, 0x87E0, 0xE5B5, 0x880F, 0xE5B6, 0x880D, 0xE5B7, 0x87FE,
+	0xE5B8, 0x87F6, 0xE5B9, 0x87F7, 0xE5BA, 0x880E, 0xE5BB, 0x87D2,
+	0xE5BC, 0x8811, 0xE5BD, 0x8816, 0xE5BE, 0x8815, 0xE5BF, 0x8822,
+	0xE5C0, 0x8821, 0xE5C1, 0x8831, 0xE5C2, 0x8836, 0xE5C3, 0x8839,
+	0xE5C4, 0x8827, 0xE5C5, 0x883B, 0xE5C6, 0x8844, 0xE5C7, 0x8842,
+	0xE5C8, 0x8852, 0xE5C9, 0x8859, 0xE5CA, 0x885E, 0xE5CB, 0x8862,
+	0xE5CC, 0x886B, 0xE5CD, 0x8881, 0xE5CE, 0x887E, 0xE5CF, 0x889E,
+	0xE5D0, 0x8875, 0xE5D1, 0x887D, 0xE5D2, 0x88B5, 0xE5D3, 0x8872,
+	0xE5D4, 0x8882, 0xE5D5, 0x8897, 0xE5D6, 0x8892, 0xE5D7, 0x88AE,
+	0xE5D8, 0x8899, 0xE5D9, 0x88A2, 0xE5DA, 0x888D, 0xE5DB, 0x88A4,
+	0xE5DC, 0x88B0, 0xE5DD, 0x88BF, 0xE5DE, 0x88B1, 0xE5DF, 0x88C3,
+	0xE5E0, 0x88C4, 0xE5E1, 0x88D4, 0xE5E2, 0x88D8, 0xE5E3, 0x88D9,
+	0xE5E4, 0x88DD, 0xE5E5, 0x88F9, 0xE5E6, 0x8902, 0xE5E7, 0x88FC,
+	0xE5E8, 0x88F4, 0xE5E9, 0x88E8, 0xE5EA, 0x88F2, 0xE5EB, 0x8904,
+	0xE5EC, 0x890C, 0xE5ED, 0x890A, 0xE5EE, 0x8913, 0xE5EF, 0x8943,
+	0xE5F0, 0x891E, 0xE5F1, 0x8925, 0xE5F2, 0x892A, 0xE5F3, 0x892B,
+	0xE5F4, 0x8941, 0xE5F5, 0x8944, 0xE5F6, 0x893B, 0xE5F7, 0x8936,
+	0xE5F8, 0x8938, 0xE5F9, 0x894C, 0xE5FA, 0x891D, 0xE5FB, 0x8960,
+	0xE5FC, 0x895E, 0xE640, 0x8966, 0xE641, 0x8964, 0xE642, 0x896D,
+	0xE643, 0x896A, 0xE644, 0x896F, 0xE645, 0x8974, 0xE646, 0x8977,
+	0xE647, 0x897E, 0xE648, 0x8983, 0xE649, 0x8988, 0xE64A, 0x898A,
+	0xE64B, 0x8993, 0xE64C, 0x8998, 0xE64D, 0x89A1, 0xE64E, 0x89A9,
+	0xE64F, 0x89A6, 0xE650, 0x89AC, 0xE651, 0x89AF, 0xE652, 0x89B2,
+	0xE653, 0x89BA, 0xE654, 0x89BD, 0xE655, 0x89BF, 0xE656, 0x89C0,
+	0xE657, 0x89DA, 0xE658, 0x89DC, 0xE659, 0x89DD, 0xE65A, 0x89E7,
+	0xE65B, 0x89F4, 0xE65C, 0x89F8, 0xE65D, 0x8A03, 0xE65E, 0x8A16,
+	0xE65F, 0x8A10, 0xE660, 0x8A0C, 0xE661, 0x8A1B, 0xE662, 0x8A1D,
+	0xE663, 0x8A25, 0xE664, 0x8A36, 0xE665, 0x8A41, 0xE666, 0x8A5B,
+	0xE667, 0x8A52, 0xE668, 0x8A46, 0xE669, 0x8A48, 0xE66A, 0x8A7C,
+	0xE66B, 0x8A6D, 0xE66C, 0x8A6C, 0xE66D, 0x8A62, 0xE66E, 0x8A85,
+	0xE66F, 0x8A82, 0xE670, 0x8A84, 0xE671, 0x8AA8, 0xE672, 0x8AA1,
+	0xE673, 0x8A91, 0xE674, 0x8AA5, 0xE675, 0x8AA6, 0xE676, 0x8A9A,
+	0xE677, 0x8AA3, 0xE678, 0x8AC4, 0xE679, 0x8ACD, 0xE67A, 0x8AC2,
+	0xE67B, 0x8ADA, 0xE67C, 0x8AEB, 0xE67D, 0x8AF3, 0xE67E, 0x8AE7,
+	0xE680, 0x8AE4, 0xE681, 0x8AF1, 0xE682, 0x8B14, 0xE683, 0x8AE0,
+	0xE684, 0x8AE2, 0xE685, 0x8AF7, 0xE686, 0x8ADE, 0xE687, 0x8ADB,
+	0xE688, 0x8B0C, 0xE689, 0x8B07, 0xE68A, 0x8B1A, 0xE68B, 0x8AE1,
+	0xE68C, 0x8B16, 0xE68D, 0x8B10, 0xE68E, 0x8B17, 0xE68F, 0x8B20,
+	0xE690, 0x8B33, 0xE691, 0x97AB, 0xE692, 0x8B26, 0xE693, 0x8B2B,
+	0xE694, 0x8B3E, 0xE695, 0x8B28, 0xE696, 0x8B41, 0xE697, 0x8B4C,
+	0xE698, 0x8B4F, 0xE699, 0x8B4E, 0xE69A, 0x8B49, 0xE69B, 0x8B56,
+	0xE69C, 0x8B5B, 0xE69D, 0x8B5A, 0xE69E, 0x8B6B, 0xE69F, 0x8B5F,
+	0xE6A0, 0x8B6C, 0xE6A1, 0x8B6F, 0xE6A2, 0x8B74, 0xE6A3, 0x8B7D,
+	0xE6A4, 0x8B80, 0xE6A5, 0x8B8C, 0xE6A6, 0x8B8E, 0xE6A7, 0x8B92,
+	0xE6A8, 0x8B93, 0xE6A9, 0x8B96, 0xE6AA, 0x8B99, 0xE6AB, 0x8B9A,
+	0xE6AC, 0x8C3A, 0xE6AD, 0x8C41, 0xE6AE, 0x8C3F, 0xE6AF, 0x8C48,
+	0xE6B0, 0x8C4C, 0xE6B1, 0x8C4E, 0xE6B2, 0x8C50, 0xE6B3, 0x8C55,
+	0xE6B4, 0x8C62, 0xE6B5, 0x8C6C, 0xE6B6, 0x8C78, 0xE6B7, 0x8C7A,
+	0xE6B8, 0x8C82, 0xE6B9, 0x8C89, 0xE6BA, 0x8C85, 0xE6BB, 0x8C8A,
+	0xE6BC, 0x8C8D, 0xE6BD, 0x8C8E, 0xE6BE, 0x8C94, 0xE6BF, 0x8C7C,
+	0xE6C0, 0x8C98, 0xE6C1, 0x621D, 0xE6C2, 0x8CAD, 0xE6C3, 0x8CAA,
+	0xE6C4, 0x8CBD, 0xE6C5, 0x8CB2, 0xE6C6, 0x8CB3, 0xE6C7, 0x8CAE,
+	0xE6C8, 0x8CB6, 0xE6C9, 0x8CC8, 0xE6CA, 0x8CC1, 0xE6CB, 0x8CE4,
+	0xE6CC, 0x8CE3, 0xE6CD, 0x8CDA, 0xE6CE, 0x8CFD, 0xE6CF, 0x8CFA,
+	0xE6D0, 0x8CFB, 0xE6D1, 0x8D04, 0xE6D2, 0x8D05, 0xE6D3, 0x8D0A,
+	0xE6D4, 0x8D07, 0xE6D5, 0x8D0F, 0xE6D6, 0x8D0D, 0xE6D7, 0x8D10,
+	0xE6D8, 0x9F4E, 0xE6D9, 0x8D13, 0xE6DA, 0x8CCD, 0xE6DB, 0x8D14,
+	0xE6DC, 0x8D16, 0xE6DD, 0x8D67, 0xE6DE, 0x8D6D, 0xE6DF, 0x8D71,
+	0xE6E0, 0x8D73, 0xE6E1, 0x8D81, 0xE6E2, 0x8D99, 0xE6E3, 0x8DC2,
+	0xE6E4, 0x8DBE, 0xE6E5, 0x8DBA, 0xE6E6, 0x8DCF, 0xE6E7, 0x8DDA,
+	0xE6E8, 0x8DD6, 0xE6E9, 0x8DCC, 0xE6EA, 0x8DDB, 0xE6EB, 0x8DCB,
+	0xE6EC, 0x8DEA, 0xE6ED, 0x8DEB, 0xE6EE, 0x8DDF, 0xE6EF, 0x8DE3,
+	0xE6F0, 0x8DFC, 0xE6F1, 0x8E08, 0xE6F2, 0x8E09, 0xE6F3, 0x8DFF,
+	0xE6F4, 0x8E1D, 0xE6F5, 0x8E1E, 0xE6F6, 0x8E10, 0xE6F7, 0x8E1F,
+	0xE6F8, 0x8E42, 0xE6F9, 0x8E35, 0xE6FA, 0x8E30, 0xE6FB, 0x8E34,
+	0xE6FC, 0x8E4A, 0xE740, 0x8E47, 0xE741, 0x8E49, 0xE742, 0x8E4C,
+	0xE743, 0x8E50, 0xE744, 0x8E48, 0xE745, 0x8E59, 0xE746, 0x8E64,
+	0xE747, 0x8E60, 0xE748, 0x8E2A, 0xE749, 0x8E63, 0xE74A, 0x8E55,
+	0xE74B, 0x8E76, 0xE74C, 0x8E72, 0xE74D, 0x8E7C, 0xE74E, 0x8E81,
+	0xE74F, 0x8E87, 0xE750, 0x8E85, 0xE751, 0x8E84, 0xE752, 0x8E8B,
+	0xE753, 0x8E8A, 0xE754, 0x8E93, 0xE755, 0x8E91, 0xE756, 0x8E94,
+	0xE757, 0x8E99, 0xE758, 0x8EAA, 0xE759, 0x8EA1, 0xE75A, 0x8EAC,
+	0xE75B, 0x8EB0, 0xE75C, 0x8EC6, 0xE75D, 0x8EB1, 0xE75E, 0x8EBE,
+	0xE75F, 0x8EC5, 0xE760, 0x8EC8, 0xE761, 0x8ECB, 0xE762, 0x8EDB,
+	0xE763, 0x8EE3, 0xE764, 0x8EFC, 0xE765, 0x8EFB, 0xE766, 0x8EEB,
+	0xE767, 0x8EFE, 0xE768, 0x8F0A, 0xE769, 0x8F05, 0xE76A, 0x8F15,
+	0xE76B, 0x8F12, 0xE76C, 0x8F19, 0xE76D, 0x8F13, 0xE76E, 0x8F1C,
+	0xE76F, 0x8F1F, 0xE770, 0x8F1B, 0xE771, 0x8F0C, 0xE772, 0x8F26,
+	0xE773, 0x8F33, 0xE774, 0x8F3B, 0xE775, 0x8F39, 0xE776, 0x8F45,
+	0xE777, 0x8F42, 0xE778, 0x8F3E, 0xE779, 0x8F4C, 0xE77A, 0x8F49,
+	0xE77B, 0x8F46, 0xE77C, 0x8F4E, 0xE77D, 0x8F57, 0xE77E, 0x8F5C,
+	0xE780, 0x8F62, 0xE781, 0x8F63, 0xE782, 0x8F64, 0xE783, 0x8F9C,
+	0xE784, 0x8F9F, 0xE785, 0x8FA3, 0xE786, 0x8FAD, 0xE787, 0x8FAF,
+	0xE788, 0x8FB7, 0xE789, 0x8FDA, 0xE78A, 0x8FE5, 0xE78B, 0x8FE2,
+	0xE78C, 0x8FEA, 0xE78D, 0x8FEF, 0xE78E, 0x9087, 0xE78F, 0x8FF4,
+	0xE790, 0x9005, 0xE791, 0x8FF9, 0xE792, 0x8FFA, 0xE793, 0x9011,
+	0xE794, 0x9015, 0xE795, 0x9021, 0xE796, 0x900D, 0xE797, 0x901E,
+	0xE798, 0x9016, 0xE799, 0x900B, 0xE79A, 0x9027, 0xE79B, 0x9036,
+	0xE79C, 0x9035, 0xE79D, 0x9039, 0xE79E, 0x8FF8, 0xE79F, 0x904F,
+	0xE7A0, 0x9050, 0xE7A1, 0x9051, 0xE7A2, 0x9052, 0xE7A3, 0x900E,
+	0xE7A4, 0x9049, 0xE7A5, 0x903E, 0xE7A6, 0x9056, 0xE7A7, 0x9058,
+	0xE7A8, 0x905E, 0xE7A9, 0x9068, 0xE7AA, 0x906F, 0xE7AB, 0x9076,
+	0xE7AC, 0x96A8, 0xE7AD, 0x9072, 0xE7AE, 0x9082, 0xE7AF, 0x907D,
+	0xE7B0, 0x9081, 0xE7B1, 0x9080, 0xE7B2, 0x908A, 0xE7B3, 0x9089,
+	0xE7B4, 0x908F, 0xE7B5, 0x90A8, 0xE7B6, 0x90AF, 0xE7B7, 0x90B1,
+	0xE7B8, 0x90B5, 0xE7B9, 0x90E2, 0xE7BA, 0x90E4, 0xE7BB, 0x6248,
+	0xE7BC, 0x90DB, 0xE7BD, 0x9102, 0xE7BE, 0x9112, 0xE7BF, 0x9119,
+	0xE7C0, 0x9132, 0xE7C1, 0x9130, 0xE7C2, 0x914A, 0xE7C3, 0x9156,
+	0xE7C4, 0x9158, 0xE7C5, 0x9163, 0xE7C6, 0x9165, 0xE7C7, 0x9169,
+	0xE7C8, 0x9173, 0xE7C9, 0x9172, 0xE7CA, 0x918B, 0xE7CB, 0x9189,
+	0xE7CC, 0x9182, 0xE7CD, 0x91A2, 0xE7CE, 0x91AB, 0xE7CF, 0x91AF,
+	0xE7D0, 0x91AA, 0xE7D1, 0x91B5, 0xE7D2, 0x91B4, 0xE7D3, 0x91BA,
+	0xE7D4, 0x91C0, 0xE7D5, 0x91C1, 0xE7D6, 0x91C9, 0xE7D7, 0x91CB,
+	0xE7D8, 0x91D0, 0xE7D9, 0x91D6, 0xE7DA, 0x91DF, 0xE7DB, 0x91E1,
+	0xE7DC, 0x91DB, 0xE7DD, 0x91FC, 0xE7DE, 0x91F5, 0xE7DF, 0x91F6,
+	0xE7E0, 0x921E, 0xE7E1, 0x91FF, 0xE7E2, 0x9214, 0xE7E3, 0x922C,
+	0xE7E4, 0x9215, 0xE7E5, 0x9211, 0xE7E6, 0x925E, 0xE7E7, 0x9257,
+	0xE7E8, 0x9245, 0xE7E9, 0x9249, 0xE7EA, 0x9264, 0xE7EB, 0x9248,
+	0xE7EC, 0x9295, 0xE7ED, 0x923F, 0xE7EE, 0x924B, 0xE7EF, 0x9250,
+	0xE7F0, 0x929C, 0xE7F1, 0x9296, 0xE7F2, 0x9293, 0xE7F3, 0x929B,
+	0xE7F4, 0x925A, 0xE7F5, 0x92CF, 0xE7F6, 0x92B9, 0xE7F7, 0x92B7,
+	0xE7F8, 0x92E9, 0xE7F9, 0x930F, 0xE7FA, 0x92FA, 0xE7FB, 0x9344,
+	0xE7FC, 0x932E, 0xE840, 0x9319, 0xE841, 0x9322, 0xE842, 0x931A,
+	0xE843, 0x9323, 0xE844, 0x933A, 0xE845, 0x9335, 0xE846, 0x933B,
+	0xE847, 0x935C, 0xE848, 0x9360, 0xE849, 0x937C, 0xE84A, 0x936E,
+	0xE84B, 0x9356, 0xE84C, 0x93B0, 0xE84D, 0x93AC, 0xE84E, 0x93AD,
+	0xE84F, 0x9394, 0xE850, 0x93B9, 0xE851, 0x93D6, 0xE852, 0x93D7,
+	0xE853, 0x93E8, 0xE854, 0x93E5, 0xE855, 0x93D8, 0xE856, 0x93C3,
+	0xE857, 0x93DD, 0xE858, 0x93D0, 0xE859, 0x93C8, 0xE85A, 0x93E4,
+	0xE85B, 0x941A, 0xE85C, 0x9414, 0xE85D, 0x9413, 0xE85E, 0x9403,
+	0xE85F, 0x9407, 0xE860, 0x9410, 0xE861, 0x9436, 0xE862, 0x942B,
+	0xE863, 0x9435, 0xE864, 0x9421, 0xE865, 0x943A, 0xE866, 0x9441,
+	0xE867, 0x9452, 0xE868, 0x9444, 0xE869, 0x945B, 0xE86A, 0x9460,
+	0xE86B, 0x9462, 0xE86C, 0x945E, 0xE86D, 0x946A, 0xE86E, 0x9229,
+	0xE86F, 0x9470, 0xE870, 0x9475, 0xE871, 0x9477, 0xE872, 0x947D,
+	0xE873, 0x945A, 0xE874, 0x947C, 0xE875, 0x947E, 0xE876, 0x9481,
+	0xE877, 0x947F, 0xE878, 0x9582, 0xE879, 0x9587, 0xE87A, 0x958A,
+	0xE87B, 0x9594, 0xE87C, 0x9596, 0xE87D, 0x9598, 0xE87E, 0x9599,
+	0xE880, 0x95A0, 0xE881, 0x95A8, 0xE882, 0x95A7, 0xE883, 0x95AD,
+	0xE884, 0x95BC, 0xE885, 0x95BB, 0xE886, 0x95B9, 0xE887, 0x95BE,
+	0xE888, 0x95CA, 0xE889, 0x6FF6, 0xE88A, 0x95C3, 0xE88B, 0x95CD,
+	0xE88C, 0x95CC, 0xE88D, 0x95D5, 0xE88E, 0x95D4, 0xE88F, 0x95D6,
+	0xE890, 0x95DC, 0xE891, 0x95E1, 0xE892, 0x95E5, 0xE893, 0x95E2,
+	0xE894, 0x9621, 0xE895, 0x9628, 0xE896, 0x962E, 0xE897, 0x962F,
+	0xE898, 0x9642, 0xE899, 0x964C, 0xE89A, 0x964F, 0xE89B, 0x964B,
+	0xE89C, 0x9677, 0xE89D, 0x965C, 0xE89E, 0x965E, 0xE89F, 0x965D,
+	0xE8A0, 0x965F, 0xE8A1, 0x9666, 0xE8A2, 0x9672, 0xE8A3, 0x966C,
+	0xE8A4, 0x968D, 0xE8A5, 0x9698, 0xE8A6, 0x9695, 0xE8A7, 0x9697,
+	0xE8A8, 0x96AA, 0xE8A9, 0x96A7, 0xE8AA, 0x96B1, 0xE8AB, 0x96B2,
+	0xE8AC, 0x96B0, 0xE8AD, 0x96B4, 0xE8AE, 0x96B6, 0xE8AF, 0x96B8,
+	0xE8B0, 0x96B9, 0xE8B1, 0x96CE, 0xE8B2, 0x96CB, 0xE8B3, 0x96C9,
+	0xE8B4, 0x96CD, 0xE8B5, 0x894D, 0xE8B6, 0x96DC, 0xE8B7, 0x970D,
+	0xE8B8, 0x96D5, 0xE8B9, 0x96F9, 0xE8BA, 0x9704, 0xE8BB, 0x9706,
+	0xE8BC, 0x9708, 0xE8BD, 0x9713, 0xE8BE, 0x970E, 0xE8BF, 0x9711,
+	0xE8C0, 0x970F, 0xE8C1, 0x9716, 0xE8C2, 0x9719, 0xE8C3, 0x9724,
+	0xE8C4, 0x972A, 0xE8C5, 0x9730, 0xE8C6, 0x9739, 0xE8C7, 0x973D,
+	0xE8C8, 0x973E, 0xE8C9, 0x9744, 0xE8CA, 0x9746, 0xE8CB, 0x9748,
+	0xE8CC, 0x9742, 0xE8CD, 0x9749, 0xE8CE, 0x975C, 0xE8CF, 0x9760,
+	0xE8D0, 0x9764, 0xE8D1, 0x9766, 0xE8D2, 0x9768, 0xE8D3, 0x52D2,
+	0xE8D4, 0x976B, 0xE8D5, 0x9771, 0xE8D6, 0x9779, 0xE8D7, 0x9785,
+	0xE8D8, 0x977C, 0xE8D9, 0x9781, 0xE8DA, 0x977A, 0xE8DB, 0x9786,
+	0xE8DC, 0x978B, 0xE8DD, 0x978F, 0xE8DE, 0x9790, 0xE8DF, 0x979C,
+	0xE8E0, 0x97A8, 0xE8E1, 0x97A6, 0xE8E2, 0x97A3, 0xE8E3, 0x97B3,
+	0xE8E4, 0x97B4, 0xE8E5, 0x97C3, 0xE8E6, 0x97C6, 0xE8E7, 0x97C8,
+	0xE8E8, 0x97CB, 0xE8E9, 0x97DC, 0xE8EA, 0x97ED, 0xE8EB, 0x9F4F,
+	0xE8EC, 0x97F2, 0xE8ED, 0x7ADF, 0xE8EE, 0x97F6, 0xE8EF, 0x97F5,
+	0xE8F0, 0x980F, 0xE8F1, 0x980C, 0xE8F2, 0x9838, 0xE8F3, 0x9824,
+	0xE8F4, 0x9821, 0xE8F5, 0x9837, 0xE8F6, 0x983D, 0xE8F7, 0x9846,
+	0xE8F8, 0x984F, 0xE8F9, 0x984B, 0xE8FA, 0x986B, 0xE8FB, 0x986F,
+	0xE8FC, 0x9870, 0xE940, 0x9871, 0xE941, 0x9874, 0xE942, 0x9873,
+	0xE943, 0x98AA, 0xE944, 0x98AF, 0xE945, 0x98B1, 0xE946, 0x98B6,
+	0xE947, 0x98C4, 0xE948, 0x98C3, 0xE949, 0x98C6, 0xE94A, 0x98E9,
+	0xE94B, 0x98EB, 0xE94C, 0x9903, 0xE94D, 0x9909, 0xE94E, 0x9912,
+	0xE94F, 0x9914, 0xE950, 0x9918, 0xE951, 0x9921, 0xE952, 0x991D,
+	0xE953, 0x991E, 0xE954, 0x9924, 0xE955, 0x9920, 0xE956, 0x992C,
+	0xE957, 0x992E, 0xE958, 0x993D, 0xE959, 0x993E, 0xE95A, 0x9942,
+	0xE95B, 0x9949, 0xE95C, 0x9945, 0xE95D, 0x9950, 0xE95E, 0x994B,
+	0xE95F, 0x9951, 0xE960, 0x9952, 0xE961, 0x994C, 0xE962, 0x9955,
+	0xE963, 0x9997, 0xE964, 0x9998, 0xE965, 0x99A5, 0xE966, 0x99AD,
+	0xE967, 0x99AE, 0xE968, 0x99BC, 0xE969, 0x99DF, 0xE96A, 0x99DB,
+	0xE96B, 0x99DD, 0xE96C, 0x99D8, 0xE96D, 0x99D1, 0xE96E, 0x99ED,
+	0xE96F, 0x99EE, 0xE970, 0x99F1, 0xE971, 0x99F2, 0xE972, 0x99FB,
+	0xE973, 0x99F8, 0xE974, 0x9A01, 0xE975, 0x9A0F, 0xE976, 0x9A05,
+	0xE977, 0x99E2, 0xE978, 0x9A19, 0xE979, 0x9A2B, 0xE97A, 0x9A37,
+	0xE97B, 0x9A45, 0xE97C, 0x9A42, 0xE97D, 0x9A40, 0xE97E, 0x9A43,
+	0xE980, 0x9A3E, 0xE981, 0x9A55, 0xE982, 0x9A4D, 0xE983, 0x9A5B,
+	0xE984, 0x9A57, 0xE985, 0x9A5F, 0xE986, 0x9A62, 0xE987, 0x9A65,
+	0xE988, 0x9A64, 0xE989, 0x9A69, 0xE98A, 0x9A6B, 0xE98B, 0x9A6A,
+	0xE98C, 0x9AAD, 0xE98D, 0x9AB0, 0xE98E, 0x9ABC, 0xE98F, 0x9AC0,
+	0xE990, 0x9ACF, 0xE991, 0x9AD1, 0xE992, 0x9AD3, 0xE993, 0x9AD4,
+	0xE994, 0x9ADE, 0xE995, 0x9ADF, 0xE996, 0x9AE2, 0xE997, 0x9AE3,
+	0xE998, 0x9AE6, 0xE999, 0x9AEF, 0xE99A, 0x9AEB, 0xE99B, 0x9AEE,
+	0xE99C, 0x9AF4, 0xE99D, 0x9AF1, 0xE99E, 0x9AF7, 0xE99F, 0x9AFB,
+	0xE9A0, 0x9B06, 0xE9A1, 0x9B18, 0xE9A2, 0x9B1A, 0xE9A3, 0x9B1F,
+	0xE9A4, 0x9B22, 0xE9A5, 0x9B23, 0xE9A6, 0x9B25, 0xE9A7, 0x9B27,
+	0xE9A8, 0x9B28, 0xE9A9, 0x9B29, 0xE9AA, 0x9B2A, 0xE9AB, 0x9B2E,
+	0xE9AC, 0x9B2F, 0xE9AD, 0x9B32, 0xE9AE, 0x9B44, 0xE9AF, 0x9B43,
+	0xE9B0, 0x9B4F, 0xE9B1, 0x9B4D, 0xE9B2, 0x9B4E, 0xE9B3, 0x9B51,
+	0xE9B4, 0x9B58, 0xE9B5, 0x9B74, 0xE9B6, 0x9B93, 0xE9B7, 0x9B83,
+	0xE9B8, 0x9B91, 0xE9B9, 0x9B96, 0xE9BA, 0x9B97, 0xE9BB, 0x9B9F,
+	0xE9BC, 0x9BA0, 0xE9BD, 0x9BA8, 0xE9BE, 0x9BB4, 0xE9BF, 0x9BC0,
+	0xE9C0, 0x9BCA, 0xE9C1, 0x9BB9, 0xE9C2, 0x9BC6, 0xE9C3, 0x9BCF,
+	0xE9C4, 0x9BD1, 0xE9C5, 0x9BD2, 0xE9C6, 0x9BE3, 0xE9C7, 0x9BE2,
+	0xE9C8, 0x9BE4, 0xE9C9, 0x9BD4, 0xE9CA, 0x9BE1, 0xE9CB, 0x9C3A,
+	0xE9CC, 0x9BF2, 0xE9CD, 0x9BF1, 0xE9CE, 0x9BF0, 0xE9CF, 0x9C15,
+	0xE9D0, 0x9C14, 0xE9D1, 0x9C09, 0xE9D2, 0x9C13, 0xE9D3, 0x9C0C,
+	0xE9D4, 0x9C06, 0xE9D5, 0x9C08, 0xE9D6, 0x9C12, 0xE9D7, 0x9C0A,
+	0xE9D8, 0x9C04, 0xE9D9, 0x9C2E, 0xE9DA, 0x9C1B, 0xE9DB, 0x9C25,
+	0xE9DC, 0x9C24, 0xE9DD, 0x9C21, 0xE9DE, 0x9C30, 0xE9DF, 0x9C47,
+	0xE9E0, 0x9C32, 0xE9E1, 0x9C46, 0xE9E2, 0x9C3E, 0xE9E3, 0x9C5A,
+	0xE9E4, 0x9C60, 0xE9E5, 0x9C67, 0xE9E6, 0x9C76, 0xE9E7, 0x9C78,
+	0xE9E8, 0x9CE7, 0xE9E9, 0x9CEC, 0xE9EA, 0x9CF0, 0xE9EB, 0x9D09,
+	0xE9EC, 0x9D08, 0xE9ED, 0x9CEB, 0xE9EE, 0x9D03, 0xE9EF, 0x9D06,
+	0xE9F0, 0x9D2A, 0xE9F1, 0x9D26, 0xE9F2, 0x9DAF, 0xE9F3, 0x9D23,
+	0xE9F4, 0x9D1F, 0xE9F5, 0x9D44, 0xE9F6, 0x9D15, 0xE9F7, 0x9D12,
+	0xE9F8, 0x9D41, 0xE9F9, 0x9D3F, 0xE9FA, 0x9D3E, 0xE9FB, 0x9D46,
+	0xE9FC, 0x9D48, 0xEA40, 0x9D5D, 0xEA41, 0x9D5E, 0xEA42, 0x9D64,
+	0xEA43, 0x9D51, 0xEA44, 0x9D50, 0xEA45, 0x9D59, 0xEA46, 0x9D72,
+	0xEA47, 0x9D89, 0xEA48, 0x9D87, 0xEA49, 0x9DAB, 0xEA4A, 0x9D6F,
+	0xEA4B, 0x9D7A, 0xEA4C, 0x9D9A, 0xEA4D, 0x9DA4, 0xEA4E, 0x9DA9,
+	0xEA4F, 0x9DB2, 0xEA50, 0x9DC4, 0xEA51, 0x9DC1, 0xEA52, 0x9DBB,
+	0xEA53, 0x9DB8, 0xEA54, 0x9DBA, 0xEA55, 0x9DC6, 0xEA56, 0x9DCF,
+	0xEA57, 0x9DC2, 0xEA58, 0x9DD9, 0xEA59, 0x9DD3, 0xEA5A, 0x9DF8,
+	0xEA5B, 0x9DE6, 0xEA5C, 0x9DED, 0xEA5D, 0x9DEF, 0xEA5E, 0x9DFD,
+	0xEA5F, 0x9E1A, 0xEA60, 0x9E1B, 0xEA61, 0x9E1E, 0xEA62, 0x9E75,
+	0xEA63, 0x9E79, 0xEA64, 0x9E7D, 0xEA65, 0x9E81, 0xEA66, 0x9E88,
+	0xEA67, 0x9E8B, 0xEA68, 0x9E8C, 0xEA69, 0x9E92, 0xEA6A, 0x9E95,
+	0xEA6B, 0x9E91, 0xEA6C, 0x9E9D, 0xEA6D, 0x9EA5, 0xEA6E, 0x9EA9,
+	0xEA6F, 0x9EB8, 0xEA70, 0x9EAA, 0xEA71, 0x9EAD, 0xEA72, 0x9761,
+	0xEA73, 0x9ECC, 0xEA74, 0x9ECE, 0xEA75, 0x9ECF, 0xEA76, 0x9ED0,
+	0xEA77, 0x9ED4, 0xEA78, 0x9EDC, 0xEA79, 0x9EDE, 0xEA7A, 0x9EDD,
+	0xEA7B, 0x9EE0, 0xEA7C, 0x9EE5, 0xEA7D, 0x9EE8, 0xEA7E, 0x9EEF,
+	0xEA80, 0x9EF4, 0xEA81, 0x9EF6, 0xEA82, 0x9EF7, 0xEA83, 0x9EF9,
+	0xEA84, 0x9EFB, 0xEA85, 0x9EFC, 0xEA86, 0x9EFD, 0xEA87, 0x9F07,
+	0xEA88, 0x9F08, 0xEA89, 0x76B7, 0xEA8A, 0x9F15, 0xEA8B, 0x9F21,
+	0xEA8C, 0x9F2C, 0xEA8D, 0x9F3E, 0xEA8E, 0x9F4A, 0xEA8F, 0x9F52,
+	0xEA90, 0x9F54, 0xEA91, 0x9F63, 0xEA92, 0x9F5F, 0xEA93, 0x9F60,
+	0xEA94, 0x9F61, 0xEA95, 0x9F66, 0xEA96, 0x9F67, 0xEA97, 0x9F6C,
+	0xEA98, 0x9F6A, 0xEA99, 0x9F77, 0xEA9A, 0x9F72, 0xEA9B, 0x9F76,
+	0xEA9C, 0x9F95, 0xEA9D, 0x9F9C, 0xEA9E, 0x9FA0, 0xEA9F, 0x582F,
+	0xEAA0, 0x69C7, 0xEAA1, 0x9059, 0xEAA2, 0x7464, 0xEAA3, 0x51DC,
+	0xEAA4, 0x7199, 0xFA40, 0x2170, 0xFA41, 0x2171, 0xFA42, 0x2172,
+	0xFA43, 0x2173, 0xFA44, 0x2174, 0xFA45, 0x2175, 0xFA46, 0x2176,
+	0xFA47, 0x2177, 0xFA48, 0x2178, 0xFA49, 0x2179, 0xFA55, 0xFFE4,
+	0xFA56, 0xFF07, 0xFA57, 0xFF02, 0xFA5C, 0x7E8A, 0xFA5D, 0x891C,
+	0xFA5E, 0x9348, 0xFA5F, 0x9288, 0xFA60, 0x84DC, 0xFA61, 0x4FC9,
+	0xFA62, 0x70BB, 0xFA63, 0x6631, 0xFA64, 0x68C8, 0xFA65, 0x92F9,
+	0xFA66, 0x66FB, 0xFA67, 0x5F45, 0xFA68, 0x4E28, 0xFA69, 0x4EE1,
+	0xFA6A, 0x4EFC, 0xFA6B, 0x4F00, 0xFA6C, 0x4F03, 0xFA6D, 0x4F39,
+	0xFA6E, 0x4F56, 0xFA6F, 0x4F92, 0xFA70, 0x4F8A, 0xFA71, 0x4F9A,
+	0xFA72, 0x4F94, 0xFA73, 0x4FCD, 0xFA74, 0x5040, 0xFA75, 0x5022,
+	0xFA76, 0x4FFF, 0xFA77, 0x501E, 0xFA78, 0x5046, 0xFA79, 0x5070,
+	0xFA7A, 0x5042, 0xFA7B, 0x5094, 0xFA7C, 0x50F4, 0xFA7D, 0x50D8,
+	0xFA7E, 0x514A, 0xFA80, 0x5164, 0xFA81, 0x519D, 0xFA82, 0x51BE,
+	0xFA83, 0x51EC, 0xFA84, 0x5215, 0xFA85, 0x529C, 0xFA86, 0x52A6,
+	0xFA87, 0x52C0, 0xFA88, 0x52DB, 0xFA89, 0x5300, 0xFA8A, 0x5307,
+	0xFA8B, 0x5324, 0xFA8C, 0x5372, 0xFA8D, 0x5393, 0xFA8E, 0x53B2,
+	0xFA8F, 0x53DD, 0xFA90, 0xFA0E, 0xFA91, 0x549C, 0xFA92, 0x548A,
+	0xFA93, 0x54A9, 0xFA94, 0x54FF, 0xFA95, 0x5586, 0xFA96, 0x5759,
+	0xFA97, 0x5765, 0xFA98, 0x57AC, 0xFA99, 0x57C8, 0xFA9A, 0x57C7,
+	0xFA9B, 0xFA0F, 0xFA9C, 0xFA10, 0xFA9D, 0x589E, 0xFA9E, 0x58B2,
+	0xFA9F, 0x590B, 0xFAA0, 0x5953, 0xFAA1, 0x595B, 0xFAA2, 0x595D,
+	0xFAA3, 0x5963, 0xFAA4, 0x59A4, 0xFAA5, 0x59BA, 0xFAA6, 0x5B56,
+	0xFAA7, 0x5BC0, 0xFAA8, 0x752F, 0xFAA9, 0x5BD8, 0xFAAA, 0x5BEC,
+	0xFAAB, 0x5C1E, 0xFAAC, 0x5CA6, 0xFAAD, 0x5CBA, 0xFAAE, 0x5CF5,
+	0xFAAF, 0x5D27, 0xFAB0, 0x5D53, 0xFAB1, 0xFA11, 0xFAB2, 0x5D42,
+	0xFAB3, 0x5D6D, 0xFAB4, 0x5DB8, 0xFAB5, 0x5DB9, 0xFAB6, 0x5DD0,
+	0xFAB7, 0x5F21, 0xFAB8, 0x5F34, 0xFAB9, 0x5F67, 0xFABA, 0x5FB7,
+	0xFABB, 0x5FDE, 0xFABC, 0x605D, 0xFABD, 0x6085, 0xFABE, 0x608A,
+	0xFABF, 0x60DE, 0xFAC0, 0x60D5, 0xFAC1, 0x6120, 0xFAC2, 0x60F2,
+	0xFAC3, 0x6111, 0xFAC4, 0x6137, 0xFAC5, 0x6130, 0xFAC6, 0x6198,
+	0xFAC7, 0x6213, 0xFAC8, 0x62A6, 0xFAC9, 0x63F5, 0xFACA, 0x6460,
+	0xFACB, 0x649D, 0xFACC, 0x64CE, 0xFACD, 0x654E, 0xFACE, 0x6600,
+	0xFACF, 0x6615, 0xFAD0, 0x663B, 0xFAD1, 0x6609, 0xFAD2, 0x662E,
+	0xFAD3, 0x661E, 0xFAD4, 0x6624, 0xFAD5, 0x6665, 0xFAD6, 0x6657,
+	0xFAD7, 0x6659, 0xFAD8, 0xFA12, 0xFAD9, 0x6673, 0xFADA, 0x6699,
+	0xFADB, 0x66A0, 0xFADC, 0x66B2, 0xFADD, 0x66BF, 0xFADE, 0x66FA,
+	0xFADF, 0x670E, 0xFAE0, 0xF929, 0xFAE1, 0x6766, 0xFAE2, 0x67BB,
+	0xFAE3, 0x6852, 0xFAE4, 0x67C0, 0xFAE5, 0x6801, 0xFAE6, 0x6844,
+	0xFAE7, 0x68CF, 0xFAE8, 0xFA13, 0xFAE9, 0x6968, 0xFAEA, 0xFA14,
+	0xFAEB, 0x6998, 0xFAEC, 0x69E2, 0xFAED, 0x6A30, 0xFAEE, 0x6A6B,
+	0xFAEF, 0x6A46, 0xFAF0, 0x6A73, 0xFAF1, 0x6A7E, 0xFAF2, 0x6AE2,
+	0xFAF3, 0x6AE4, 0xFAF4, 0x6BD6, 0xFAF5, 0x6C3F, 0xFAF6, 0x6C5C,
+	0xFAF7, 0x6C86, 0xFAF8, 0x6C6F, 0xFAF9, 0x6CDA, 0xFAFA, 0x6D04,
+	0xFAFB, 0x6D87, 0xFAFC, 0x6D6F, 0xFB40, 0x6D96, 0xFB41, 0x6DAC,
+	0xFB42, 0x6DCF, 0xFB43, 0x6DF8, 0xFB44, 0x6DF2, 0xFB45, 0x6DFC,
+	0xFB46, 0x6E39, 0xFB47, 0x6E5C, 0xFB48, 0x6E27, 0xFB49, 0x6E3C,
+	0xFB4A, 0x6EBF, 0xFB4B, 0x6F88, 0xFB4C, 0x6FB5, 0xFB4D, 0x6FF5,
+	0xFB4E, 0x7005, 0xFB4F, 0x7007, 0xFB50, 0x7028, 0xFB51, 0x7085,
+	0xFB52, 0x70AB, 0xFB53, 0x710F, 0xFB54, 0x7104, 0xFB55, 0x715C,
+	0xFB56, 0x7146, 0xFB57, 0x7147, 0xFB58, 0xFA15, 0xFB59, 0x71C1,
+	0xFB5A, 0x71FE, 0xFB5B, 0x72B1, 0xFB5C, 0x72BE, 0xFB5D, 0x7324,
+	0xFB5E, 0xFA16, 0xFB5F, 0x7377, 0xFB60, 0x73BD, 0xFB61, 0x73C9,
+	0xFB62, 0x73D6, 0xFB63, 0x73E3, 0xFB64, 0x73D2, 0xFB65, 0x7407,
+	0xFB66, 0x73F5, 0xFB67, 0x7426, 0xFB68, 0x742A, 0xFB69, 0x7429,
+	0xFB6A, 0x742E, 0xFB6B, 0x7462, 0xFB6C, 0x7489, 0xFB6D, 0x749F,
+	0xFB6E, 0x7501, 0xFB6F, 0x756F, 0xFB70, 0x7682, 0xFB71, 0x769C,
+	0xFB72, 0x769E, 0xFB73, 0x769B, 0xFB74, 0x76A6, 0xFB75, 0xFA17,
+	0xFB76, 0x7746, 0xFB77, 0x52AF, 0xFB78, 0x7821, 0xFB79, 0x784E,
+	0xFB7A, 0x7864, 0xFB7B, 0x787A, 0xFB7C, 0x7930, 0xFB7D, 0xFA18,
+	0xFB7E, 0xFA19, 0xFB80, 0xFA1A, 0xFB81, 0x7994, 0xFB82, 0xFA1B,
+	0xFB83, 0x799B, 0xFB84, 0x7AD1, 0xFB85, 0x7AE7, 0xFB86, 0xFA1C,
+	0xFB87, 0x7AEB, 0xFB88, 0x7B9E, 0xFB89, 0xFA1D, 0xFB8A, 0x7D48,
+	0xFB8B, 0x7D5C, 0xFB8C, 0x7DB7, 0xFB8D, 0x7DA0, 0xFB8E, 0x7DD6,
+	0xFB8F, 0x7E52, 0xFB90, 0x7F47, 0xFB91, 0x7FA1, 0xFB92, 0xFA1E,
+	0xFB93, 0x8301, 0xFB94, 0x8362, 0xFB95, 0x837F, 0xFB96, 0x83C7,
+	0xFB97, 0x83F6, 0xFB98, 0x8448, 0xFB99, 0x84B4, 0xFB9A, 0x8553,
+	0xFB9B, 0x8559, 0xFB9C, 0x856B, 0xFB9D, 0xFA1F, 0xFB9E, 0x85B0,
+	0xFB9F, 0xFA20, 0xFBA0, 0xFA21, 0xFBA1, 0x8807, 0xFBA2, 0x88F5,
+	0xFBA3, 0x8A12, 0xFBA4, 0x8A37, 0xFBA5, 0x8A79, 0xFBA6, 0x8AA7,
+	0xFBA7, 0x8ABE, 0xFBA8, 0x8ADF, 0xFBA9, 0xFA22, 0xFBAA, 0x8AF6,
+	0xFBAB, 0x8B53, 0xFBAC, 0x8B7F, 0xFBAD, 0x8CF0, 0xFBAE, 0x8CF4,
+	0xFBAF, 0x8D12, 0xFBB0, 0x8D76, 0xFBB1, 0xFA23, 0xFBB2, 0x8ECF,
+	0xFBB3, 0xFA24, 0xFBB4, 0xFA25, 0xFBB5, 0x9067, 0xFBB6, 0x90DE,
+	0xFBB7, 0xFA26, 0xFBB8, 0x9115, 0xFBB9, 0x9127, 0xFBBA, 0x91DA,
+	0xFBBB, 0x91D7, 0xFBBC, 0x91DE, 0xFBBD, 0x91ED, 0xFBBE, 0x91EE,
+	0xFBBF, 0x91E4, 0xFBC0, 0x91E5, 0xFBC1, 0x9206, 0xFBC2, 0x9210,
+	0xFBC3, 0x920A, 0xFBC4, 0x923A, 0xFBC5, 0x9240, 0xFBC6, 0x923C,
+	0xFBC7, 0x924E, 0xFBC8, 0x9259, 0xFBC9, 0x9251, 0xFBCA, 0x9239,
+	0xFBCB, 0x9267, 0xFBCC, 0x92A7, 0xFBCD, 0x9277, 0xFBCE, 0x9278,
+	0xFBCF, 0x92E7, 0xFBD0, 0x92D7, 0xFBD1, 0x92D9, 0xFBD2, 0x92D0,
+	0xFBD3, 0xFA27, 0xFBD4, 0x92D5, 0xFBD5, 0x92E0, 0xFBD6, 0x92D3,
+	0xFBD7, 0x9325, 0xFBD8, 0x9321, 0xFBD9, 0x92FB, 0xFBDA, 0xFA28,
+	0xFBDB, 0x931E, 0xFBDC, 0x92FF, 0xFBDD, 0x931D, 0xFBDE, 0x9302,
+	0xFBDF, 0x9370, 0xFBE0, 0x9357, 0xFBE1, 0x93A4, 0xFBE2, 0x93C6,
+	0xFBE3, 0x93DE, 0xFBE4, 0x93F8, 0xFBE5, 0x9431, 0xFBE6, 0x9445,
+	0xFBE7, 0x9448, 0xFBE8, 0x9592, 0xFBE9, 0xF9DC, 0xFBEA, 0xFA29,
+	0xFBEB, 0x969D, 0xFBEC, 0x96AF, 0xFBED, 0x9733, 0xFBEE, 0x973B,
+	0xFBEF, 0x9743, 0xFBF0, 0x974D, 0xFBF1, 0x974F, 0xFBF2, 0x9751,
+	0xFBF3, 0x9755, 0xFBF4, 0x9857, 0xFBF5, 0x9865, 0xFBF6, 0xFA2A,
+	0xFBF7, 0xFA2B, 0xFBF8, 0x9927, 0xFBF9, 0xFA2C, 0xFBFA, 0x999E,
+	0xFBFB, 0x9A4E, 0xFBFC, 0x9AD9, 0xFC40, 0x9ADC, 0xFC41, 0x9B75,
+	0xFC42, 0x9B72, 0xFC43, 0x9B8F, 0xFC44, 0x9BB1, 0xFC45, 0x9BBB,
+	0xFC46, 0x9C00, 0xFC47, 0x9D70, 0xFC48, 0x9D6B, 0xFC49, 0xFA2D,
+	0xFC4A, 0x9E19, 0xFC4B, 0x9ED1, 0, 0
+};
+#endif
+
+
+
+WCHAR ff_convert (	/* Converted code, 0 means conversion error */
+	WCHAR	src,	/* Character code to be converted */
+	UINT	dir		/* 0: Unicode to OEMCP, 1: OEMCP to Unicode */
+)
+{
+	const WCHAR *p;
+	WCHAR c;
+	int i, n, li, hi;
+
+
+	if (src <= 0x80) {	/* ASCII */
+		c = src;
+	} else {
+#if !_TINY_TABLE
+		if (dir) {		/* OEMCP to unicode */
+			p = sjis2uni;
+			hi = sizeof(sjis2uni) / 4 - 1;
+		} else {		/* Unicode to OEMCP */
+			p = uni2sjis;
+			hi = sizeof(uni2sjis) / 4 - 1;
+		}
+		li = 0;
+		for (n = 16; n; n--) {
+			i = li + (hi - li) / 2;
+			if (src == p[i * 2]) break;
+			if (src > p[i * 2])
+				li = i;
+			else
+				hi = i;
+		}
+		c = n ? p[i * 2 + 1] : 0;
+#else
+		if (dir) {		/* OEMCP to unicode (Incremental search)*/
+			p = &uni2sjis[1];
+			do {
+				c = *p;
+				p += 2;
+			p -= 3;
+			c = *p;
+			} while (c && c != src);
+		} else {		/* Unicode to OEMCP */
+			li = 0; hi = sizeof(uni2sjis) / 4 - 1;
+			for (n = 16; n; n--) {
+				i = li + (hi - li) / 2;
+				if (src == uni2sjis[i * 2]) break;
+				if (src > uni2sjis[i * 2])
+					li = i;
+				else
+					hi = i;
+			}
+			c = n ? uni2sjis[i * 2 + 1] : 0;
+		}
+#endif
+	}
+
+	return c;
+}
+#else
+#error This file is not needed in current configuration.
+
+#endif
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/option/cc936.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/option/cc936.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/option/cc936.c	(revision 453)
@@ -0,0 +1,10960 @@
+/*------------------------------------------------------------------------*/
+/* Unicode - OEM code bidirectional converter  (C)ChaN, 2009              */
+/*                                                                        */
+/* CP936 (Simplified Chinese GBK)                                         */
+/*------------------------------------------------------------------------*/
+
+#include "../ff.h"
+
+
+#if _USE_LFN && _CODE_PAGE == 936
+
+
+static
+const WCHAR uni2oem[] = {
+/*  Unicode - OEM,  Unicode - OEM,  Unicode - OEM,  Unicode - OEM */
+	0x00A4, 0xA1E8, 0x00A7, 0xA1EC, 0x00A8, 0xA1A7, 0x00B0, 0xA1E3,
+	0x00B1, 0xA1C0, 0x00B7, 0xA1A4, 0x00D7, 0xA1C1, 0x00E0, 0xA8A4,
+	0x00E1, 0xA8A2, 0x00E8, 0xA8A8, 0x00E9, 0xA8A6, 0x00EA, 0xA8BA,
+	0x00EC, 0xA8AC, 0x00ED, 0xA8AA, 0x00F2, 0xA8B0, 0x00F3, 0xA8AE,
+	0x00F7, 0xA1C2, 0x00F9, 0xA8B4, 0x00FA, 0xA8B2, 0x00FC, 0xA8B9,
+	0x0101, 0xA8A1, 0x0113, 0xA8A5, 0x011B, 0xA8A7, 0x012B, 0xA8A9,
+	0x0144, 0xA8BD, 0x0148, 0xA8BE, 0x014D, 0xA8AD, 0x016B, 0xA8B1,
+	0x01CE, 0xA8A3, 0x01D0, 0xA8AB, 0x01D2, 0xA8AF, 0x01D4, 0xA8B3,
+	0x01D6, 0xA8B5, 0x01D8, 0xA8B6, 0x01DA, 0xA8B7, 0x01DC, 0xA8B8,
+	0x0251, 0xA8BB, 0x0261, 0xA8C0, 0x02C7, 0xA1A6, 0x02C9, 0xA1A5,
+	0x02CA, 0xA840, 0x02CB, 0xA841, 0x02D9, 0xA842, 0x0391, 0xA6A1,
+	0x0392, 0xA6A2, 0x0393, 0xA6A3, 0x0394, 0xA6A4, 0x0395, 0xA6A5,
+	0x0396, 0xA6A6, 0x0397, 0xA6A7, 0x0398, 0xA6A8, 0x0399, 0xA6A9,
+	0x039A, 0xA6AA, 0x039B, 0xA6AB, 0x039C, 0xA6AC, 0x039D, 0xA6AD,
+	0x039E, 0xA6AE, 0x039F, 0xA6AF, 0x03A0, 0xA6B0, 0x03A1, 0xA6B1,
+	0x03A3, 0xA6B2, 0x03A4, 0xA6B3, 0x03A5, 0xA6B4, 0x03A6, 0xA6B5,
+	0x03A7, 0xA6B6, 0x03A8, 0xA6B7, 0x03A9, 0xA6B8, 0x03B1, 0xA6C1,
+	0x03B2, 0xA6C2, 0x03B3, 0xA6C3, 0x03B4, 0xA6C4, 0x03B5, 0xA6C5,
+	0x03B6, 0xA6C6, 0x03B7, 0xA6C7, 0x03B8, 0xA6C8, 0x03B9, 0xA6C9,
+	0x03BA, 0xA6CA, 0x03BB, 0xA6CB, 0x03BC, 0xA6CC, 0x03BD, 0xA6CD,
+	0x03BE, 0xA6CE, 0x03BF, 0xA6CF, 0x03C0, 0xA6D0, 0x03C1, 0xA6D1,
+	0x03C3, 0xA6D2, 0x03C4, 0xA6D3, 0x03C5, 0xA6D4, 0x03C6, 0xA6D5,
+	0x03C7, 0xA6D6, 0x03C8, 0xA6D7, 0x03C9, 0xA6D8, 0x0401, 0xA7A7,
+	0x0410, 0xA7A1, 0x0411, 0xA7A2, 0x0412, 0xA7A3, 0x0413, 0xA7A4,
+	0x0414, 0xA7A5, 0x0415, 0xA7A6, 0x0416, 0xA7A8, 0x0417, 0xA7A9,
+	0x0418, 0xA7AA, 0x0419, 0xA7AB, 0x041A, 0xA7AC, 0x041B, 0xA7AD,
+	0x041C, 0xA7AE, 0x041D, 0xA7AF, 0x041E, 0xA7B0, 0x041F, 0xA7B1,
+	0x0420, 0xA7B2, 0x0421, 0xA7B3, 0x0422, 0xA7B4, 0x0423, 0xA7B5,
+	0x0424, 0xA7B6, 0x0425, 0xA7B7, 0x0426, 0xA7B8, 0x0427, 0xA7B9,
+	0x0428, 0xA7BA, 0x0429, 0xA7BB, 0x042A, 0xA7BC, 0x042B, 0xA7BD,
+	0x042C, 0xA7BE, 0x042D, 0xA7BF, 0x042E, 0xA7C0, 0x042F, 0xA7C1,
+	0x0430, 0xA7D1, 0x0431, 0xA7D2, 0x0432, 0xA7D3, 0x0433, 0xA7D4,
+	0x0434, 0xA7D5, 0x0435, 0xA7D6, 0x0436, 0xA7D8, 0x0437, 0xA7D9,
+	0x0438, 0xA7DA, 0x0439, 0xA7DB, 0x043A, 0xA7DC, 0x043B, 0xA7DD,
+	0x043C, 0xA7DE, 0x043D, 0xA7DF, 0x043E, 0xA7E0, 0x043F, 0xA7E1,
+	0x0440, 0xA7E2, 0x0441, 0xA7E3, 0x0442, 0xA7E4, 0x0443, 0xA7E5,
+	0x0444, 0xA7E6, 0x0445, 0xA7E7, 0x0446, 0xA7E8, 0x0447, 0xA7E9,
+	0x0448, 0xA7EA, 0x0449, 0xA7EB, 0x044A, 0xA7EC, 0x044B, 0xA7ED,
+	0x044C, 0xA7EE, 0x044D, 0xA7EF, 0x044E, 0xA7F0, 0x044F, 0xA7F1,
+	0x0451, 0xA7D7, 0x2010, 0xA95C, 0x2013, 0xA843, 0x2014, 0xA1AA,
+	0x2015, 0xA844, 0x2016, 0xA1AC, 0x2018, 0xA1AE, 0x2019, 0xA1AF,
+	0x201C, 0xA1B0, 0x201D, 0xA1B1, 0x2025, 0xA845, 0x2026, 0xA1AD,
+	0x2030, 0xA1EB, 0x2032, 0xA1E4, 0x2033, 0xA1E5, 0x2035, 0xA846,
+	0x203B, 0xA1F9, 0x20AC, 0x0080, 0x2103, 0xA1E6, 0x2105, 0xA847,
+	0x2109, 0xA848, 0x2116, 0xA1ED, 0x2121, 0xA959, 0x2160, 0xA2F1,
+	0x2161, 0xA2F2, 0x2162, 0xA2F3, 0x2163, 0xA2F4, 0x2164, 0xA2F5,
+	0x2165, 0xA2F6, 0x2166, 0xA2F7, 0x2167, 0xA2F8, 0x2168, 0xA2F9,
+	0x2169, 0xA2FA, 0x216A, 0xA2FB, 0x216B, 0xA2FC, 0x2170, 0xA2A1,
+	0x2171, 0xA2A2, 0x2172, 0xA2A3, 0x2173, 0xA2A4, 0x2174, 0xA2A5,
+	0x2175, 0xA2A6, 0x2176, 0xA2A7, 0x2177, 0xA2A8, 0x2178, 0xA2A9,
+	0x2179, 0xA2AA, 0x2190, 0xA1FB, 0x2191, 0xA1FC, 0x2192, 0xA1FA,
+	0x2193, 0xA1FD, 0x2196, 0xA849, 0x2197, 0xA84A, 0x2198, 0xA84B,
+	0x2199, 0xA84C, 0x2208, 0xA1CA, 0x220F, 0xA1C7, 0x2211, 0xA1C6,
+	0x2215, 0xA84D, 0x221A, 0xA1CC, 0x221D, 0xA1D8, 0x221E, 0xA1DE,
+	0x221F, 0xA84E, 0x2220, 0xA1CF, 0x2223, 0xA84F, 0x2225, 0xA1CE,
+	0x2227, 0xA1C4, 0x2228, 0xA1C5, 0x2229, 0xA1C9, 0x222A, 0xA1C8,
+	0x222B, 0xA1D2, 0x222E, 0xA1D3, 0x2234, 0xA1E0, 0x2235, 0xA1DF,
+	0x2236, 0xA1C3, 0x2237, 0xA1CB, 0x223D, 0xA1D7, 0x2248, 0xA1D6,
+	0x224C, 0xA1D5, 0x2252, 0xA850, 0x2260, 0xA1D9, 0x2261, 0xA1D4,
+	0x2264, 0xA1DC, 0x2265, 0xA1DD, 0x2266, 0xA851, 0x2267, 0xA852,
+	0x226E, 0xA1DA, 0x226F, 0xA1DB, 0x2295, 0xA892, 0x2299, 0xA1D1,
+	0x22A5, 0xA1CD, 0x22BF, 0xA853, 0x2312, 0xA1D0, 0x2460, 0xA2D9,
+	0x2461, 0xA2DA, 0x2462, 0xA2DB, 0x2463, 0xA2DC, 0x2464, 0xA2DD,
+	0x2465, 0xA2DE, 0x2466, 0xA2DF, 0x2467, 0xA2E0, 0x2468, 0xA2E1,
+	0x2469, 0xA2E2, 0x2474, 0xA2C5, 0x2475, 0xA2C6, 0x2476, 0xA2C7,
+	0x2477, 0xA2C8, 0x2478, 0xA2C9, 0x2479, 0xA2CA, 0x247A, 0xA2CB,
+	0x247B, 0xA2CC, 0x247C, 0xA2CD, 0x247D, 0xA2CE, 0x247E, 0xA2CF,
+	0x247F, 0xA2D0, 0x2480, 0xA2D1, 0x2481, 0xA2D2, 0x2482, 0xA2D3,
+	0x2483, 0xA2D4, 0x2484, 0xA2D5, 0x2485, 0xA2D6, 0x2486, 0xA2D7,
+	0x2487, 0xA2D8, 0x2488, 0xA2B1, 0x2489, 0xA2B2, 0x248A, 0xA2B3,
+	0x248B, 0xA2B4, 0x248C, 0xA2B5, 0x248D, 0xA2B6, 0x248E, 0xA2B7,
+	0x248F, 0xA2B8, 0x2490, 0xA2B9, 0x2491, 0xA2BA, 0x2492, 0xA2BB,
+	0x2493, 0xA2BC, 0x2494, 0xA2BD, 0x2495, 0xA2BE, 0x2496, 0xA2BF,
+	0x2497, 0xA2C0, 0x2498, 0xA2C1, 0x2499, 0xA2C2, 0x249A, 0xA2C3,
+	0x249B, 0xA2C4, 0x2500, 0xA9A4, 0x2501, 0xA9A5, 0x2502, 0xA9A6,
+	0x2503, 0xA9A7, 0x2504, 0xA9A8, 0x2505, 0xA9A9, 0x2506, 0xA9AA,
+	0x2507, 0xA9AB, 0x2508, 0xA9AC, 0x2509, 0xA9AD, 0x250A, 0xA9AE,
+	0x250B, 0xA9AF, 0x250C, 0xA9B0, 0x250D, 0xA9B1, 0x250E, 0xA9B2,
+	0x250F, 0xA9B3, 0x2510, 0xA9B4, 0x2511, 0xA9B5, 0x2512, 0xA9B6,
+	0x2513, 0xA9B7, 0x2514, 0xA9B8, 0x2515, 0xA9B9, 0x2516, 0xA9BA,
+	0x2517, 0xA9BB, 0x2518, 0xA9BC, 0x2519, 0xA9BD, 0x251A, 0xA9BE,
+	0x251B, 0xA9BF, 0x251C, 0xA9C0, 0x251D, 0xA9C1, 0x251E, 0xA9C2,
+	0x251F, 0xA9C3, 0x2520, 0xA9C4, 0x2521, 0xA9C5, 0x2522, 0xA9C6,
+	0x2523, 0xA9C7, 0x2524, 0xA9C8, 0x2525, 0xA9C9, 0x2526, 0xA9CA,
+	0x2527, 0xA9CB, 0x2528, 0xA9CC, 0x2529, 0xA9CD, 0x252A, 0xA9CE,
+	0x252B, 0xA9CF, 0x252C, 0xA9D0, 0x252D, 0xA9D1, 0x252E, 0xA9D2,
+	0x252F, 0xA9D3, 0x2530, 0xA9D4, 0x2531, 0xA9D5, 0x2532, 0xA9D6,
+	0x2533, 0xA9D7, 0x2534, 0xA9D8, 0x2535, 0xA9D9, 0x2536, 0xA9DA,
+	0x2537, 0xA9DB, 0x2538, 0xA9DC, 0x2539, 0xA9DD, 0x253A, 0xA9DE,
+	0x253B, 0xA9DF, 0x253C, 0xA9E0, 0x253D, 0xA9E1, 0x253E, 0xA9E2,
+	0x253F, 0xA9E3, 0x2540, 0xA9E4, 0x2541, 0xA9E5, 0x2542, 0xA9E6,
+	0x2543, 0xA9E7, 0x2544, 0xA9E8, 0x2545, 0xA9E9, 0x2546, 0xA9EA,
+	0x2547, 0xA9EB, 0x2548, 0xA9EC, 0x2549, 0xA9ED, 0x254A, 0xA9EE,
+	0x254B, 0xA9EF, 0x2550, 0xA854, 0x2551, 0xA855, 0x2552, 0xA856,
+	0x2553, 0xA857, 0x2554, 0xA858, 0x2555, 0xA859, 0x2556, 0xA85A,
+	0x2557, 0xA85B, 0x2558, 0xA85C, 0x2559, 0xA85D, 0x255A, 0xA85E,
+	0x255B, 0xA85F, 0x255C, 0xA860, 0x255D, 0xA861, 0x255E, 0xA862,
+	0x255F, 0xA863, 0x2560, 0xA864, 0x2561, 0xA865, 0x2562, 0xA866,
+	0x2563, 0xA867, 0x2564, 0xA868, 0x2565, 0xA869, 0x2566, 0xA86A,
+	0x2567, 0xA86B, 0x2568, 0xA86C, 0x2569, 0xA86D, 0x256A, 0xA86E,
+	0x256B, 0xA86F, 0x256C, 0xA870, 0x256D, 0xA871, 0x256E, 0xA872,
+	0x256F, 0xA873, 0x2570, 0xA874, 0x2571, 0xA875, 0x2572, 0xA876,
+	0x2573, 0xA877, 0x2581, 0xA878, 0x2582, 0xA879, 0x2583, 0xA87A,
+	0x2584, 0xA87B, 0x2585, 0xA87C, 0x2586, 0xA87D, 0x2587, 0xA87E,
+	0x2588, 0xA880, 0x2589, 0xA881, 0x258A, 0xA882, 0x258B, 0xA883,
+	0x258C, 0xA884, 0x258D, 0xA885, 0x258E, 0xA886, 0x258F, 0xA887,
+	0x2593, 0xA888, 0x2594, 0xA889, 0x2595, 0xA88A, 0x25A0, 0xA1F6,
+	0x25A1, 0xA1F5, 0x25B2, 0xA1F8, 0x25B3, 0xA1F7, 0x25BC, 0xA88B,
+	0x25BD, 0xA88C, 0x25C6, 0xA1F4, 0x25C7, 0xA1F3, 0x25CB, 0xA1F0,
+	0x25CE, 0xA1F2, 0x25CF, 0xA1F1, 0x25E2, 0xA88D, 0x25E3, 0xA88E,
+	0x25E4, 0xA88F, 0x25E5, 0xA890, 0x2605, 0xA1EF, 0x2606, 0xA1EE,
+	0x2609, 0xA891, 0x2640, 0xA1E2, 0x2642, 0xA1E1, 0x3000, 0xA1A1,
+	0x3001, 0xA1A2, 0x3002, 0xA1A3, 0x3003, 0xA1A8, 0x3005, 0xA1A9,
+	0x3006, 0xA965, 0x3007, 0xA996, 0x3008, 0xA1B4, 0x3009, 0xA1B5,
+	0x300A, 0xA1B6, 0x300B, 0xA1B7, 0x300C, 0xA1B8, 0x300D, 0xA1B9,
+	0x300E, 0xA1BA, 0x300F, 0xA1BB, 0x3010, 0xA1BE, 0x3011, 0xA1BF,
+	0x3012, 0xA893, 0x3013, 0xA1FE, 0x3014, 0xA1B2, 0x3015, 0xA1B3,
+	0x3016, 0xA1BC, 0x3017, 0xA1BD, 0x301D, 0xA894, 0x301E, 0xA895,
+	0x3021, 0xA940, 0x3022, 0xA941, 0x3023, 0xA942, 0x3024, 0xA943,
+	0x3025, 0xA944, 0x3026, 0xA945, 0x3027, 0xA946, 0x3028, 0xA947,
+	0x3029, 0xA948, 0x3041, 0xA4A1, 0x3042, 0xA4A2, 0x3043, 0xA4A3,
+	0x3044, 0xA4A4, 0x3045, 0xA4A5, 0x3046, 0xA4A6, 0x3047, 0xA4A7,
+	0x3048, 0xA4A8, 0x3049, 0xA4A9, 0x304A, 0xA4AA, 0x304B, 0xA4AB,
+	0x304C, 0xA4AC, 0x304D, 0xA4AD, 0x304E, 0xA4AE, 0x304F, 0xA4AF,
+	0x3050, 0xA4B0, 0x3051, 0xA4B1, 0x3052, 0xA4B2, 0x3053, 0xA4B3,
+	0x3054, 0xA4B4, 0x3055, 0xA4B5, 0x3056, 0xA4B6, 0x3057, 0xA4B7,
+	0x3058, 0xA4B8, 0x3059, 0xA4B9, 0x305A, 0xA4BA, 0x305B, 0xA4BB,
+	0x305C, 0xA4BC, 0x305D, 0xA4BD, 0x305E, 0xA4BE, 0x305F, 0xA4BF,
+	0x3060, 0xA4C0, 0x3061, 0xA4C1, 0x3062, 0xA4C2, 0x3063, 0xA4C3,
+	0x3064, 0xA4C4, 0x3065, 0xA4C5, 0x3066, 0xA4C6, 0x3067, 0xA4C7,
+	0x3068, 0xA4C8, 0x3069, 0xA4C9, 0x306A, 0xA4CA, 0x306B, 0xA4CB,
+	0x306C, 0xA4CC, 0x306D, 0xA4CD, 0x306E, 0xA4CE, 0x306F, 0xA4CF,
+	0x3070, 0xA4D0, 0x3071, 0xA4D1, 0x3072, 0xA4D2, 0x3073, 0xA4D3,
+	0x3074, 0xA4D4, 0x3075, 0xA4D5, 0x3076, 0xA4D6, 0x3077, 0xA4D7,
+	0x3078, 0xA4D8, 0x3079, 0xA4D9, 0x307A, 0xA4DA, 0x307B, 0xA4DB,
+	0x307C, 0xA4DC, 0x307D, 0xA4DD, 0x307E, 0xA4DE, 0x307F, 0xA4DF,
+	0x3080, 0xA4E0, 0x3081, 0xA4E1, 0x3082, 0xA4E2, 0x3083, 0xA4E3,
+	0x3084, 0xA4E4, 0x3085, 0xA4E5, 0x3086, 0xA4E6, 0x3087, 0xA4E7,
+	0x3088, 0xA4E8, 0x3089, 0xA4E9, 0x308A, 0xA4EA, 0x308B, 0xA4EB,
+	0x308C, 0xA4EC, 0x308D, 0xA4ED, 0x308E, 0xA4EE, 0x308F, 0xA4EF,
+	0x3090, 0xA4F0, 0x3091, 0xA4F1, 0x3092, 0xA4F2, 0x3093, 0xA4F3,
+	0x309B, 0xA961, 0x309C, 0xA962, 0x309D, 0xA966, 0x309E, 0xA967,
+	0x30A1, 0xA5A1, 0x30A2, 0xA5A2, 0x30A3, 0xA5A3, 0x30A4, 0xA5A4,
+	0x30A5, 0xA5A5, 0x30A6, 0xA5A6, 0x30A7, 0xA5A7, 0x30A8, 0xA5A8,
+	0x30A9, 0xA5A9, 0x30AA, 0xA5AA, 0x30AB, 0xA5AB, 0x30AC, 0xA5AC,
+	0x30AD, 0xA5AD, 0x30AE, 0xA5AE, 0x30AF, 0xA5AF, 0x30B0, 0xA5B0,
+	0x30B1, 0xA5B1, 0x30B2, 0xA5B2, 0x30B3, 0xA5B3, 0x30B4, 0xA5B4,
+	0x30B5, 0xA5B5, 0x30B6, 0xA5B6, 0x30B7, 0xA5B7, 0x30B8, 0xA5B8,
+	0x30B9, 0xA5B9, 0x30BA, 0xA5BA, 0x30BB, 0xA5BB, 0x30BC, 0xA5BC,
+	0x30BD, 0xA5BD, 0x30BE, 0xA5BE, 0x30BF, 0xA5BF, 0x30C0, 0xA5C0,
+	0x30C1, 0xA5C1, 0x30C2, 0xA5C2, 0x30C3, 0xA5C3, 0x30C4, 0xA5C4,
+	0x30C5, 0xA5C5, 0x30C6, 0xA5C6, 0x30C7, 0xA5C7, 0x30C8, 0xA5C8,
+	0x30C9, 0xA5C9, 0x30CA, 0xA5CA, 0x30CB, 0xA5CB, 0x30CC, 0xA5CC,
+	0x30CD, 0xA5CD, 0x30CE, 0xA5CE, 0x30CF, 0xA5CF, 0x30D0, 0xA5D0,
+	0x30D1, 0xA5D1, 0x30D2, 0xA5D2, 0x30D3, 0xA5D3, 0x30D4, 0xA5D4,
+	0x30D5, 0xA5D5, 0x30D6, 0xA5D6, 0x30D7, 0xA5D7, 0x30D8, 0xA5D8,
+	0x30D9, 0xA5D9, 0x30DA, 0xA5DA, 0x30DB, 0xA5DB, 0x30DC, 0xA5DC,
+	0x30DD, 0xA5DD, 0x30DE, 0xA5DE, 0x30DF, 0xA5DF, 0x30E0, 0xA5E0,
+	0x30E1, 0xA5E1, 0x30E2, 0xA5E2, 0x30E3, 0xA5E3, 0x30E4, 0xA5E4,
+	0x30E5, 0xA5E5, 0x30E6, 0xA5E6, 0x30E7, 0xA5E7, 0x30E8, 0xA5E8,
+	0x30E9, 0xA5E9, 0x30EA, 0xA5EA, 0x30EB, 0xA5EB, 0x30EC, 0xA5EC,
+	0x30ED, 0xA5ED, 0x30EE, 0xA5EE, 0x30EF, 0xA5EF, 0x30F0, 0xA5F0,
+	0x30F1, 0xA5F1, 0x30F2, 0xA5F2, 0x30F3, 0xA5F3, 0x30F4, 0xA5F4,
+	0x30F5, 0xA5F5, 0x30F6, 0xA5F6, 0x30FC, 0xA960, 0x30FD, 0xA963,
+	0x30FE, 0xA964, 0x3105, 0xA8C5, 0x3106, 0xA8C6, 0x3107, 0xA8C7,
+	0x3108, 0xA8C8, 0x3109, 0xA8C9, 0x310A, 0xA8CA, 0x310B, 0xA8CB,
+	0x310C, 0xA8CC, 0x310D, 0xA8CD, 0x310E, 0xA8CE, 0x310F, 0xA8CF,
+	0x3110, 0xA8D0, 0x3111, 0xA8D1, 0x3112, 0xA8D2, 0x3113, 0xA8D3,
+	0x3114, 0xA8D4, 0x3115, 0xA8D5, 0x3116, 0xA8D6, 0x3117, 0xA8D7,
+	0x3118, 0xA8D8, 0x3119, 0xA8D9, 0x311A, 0xA8DA, 0x311B, 0xA8DB,
+	0x311C, 0xA8DC, 0x311D, 0xA8DD, 0x311E, 0xA8DE, 0x311F, 0xA8DF,
+	0x3120, 0xA8E0, 0x3121, 0xA8E1, 0x3122, 0xA8E2, 0x3123, 0xA8E3,
+	0x3124, 0xA8E4, 0x3125, 0xA8E5, 0x3126, 0xA8E6, 0x3127, 0xA8E7,
+	0x3128, 0xA8E8, 0x3129, 0xA8E9, 0x3220, 0xA2E5, 0x3221, 0xA2E6,
+	0x3222, 0xA2E7, 0x3223, 0xA2E8, 0x3224, 0xA2E9, 0x3225, 0xA2EA,
+	0x3226, 0xA2EB, 0x3227, 0xA2EC, 0x3228, 0xA2ED, 0x3229, 0xA2EE,
+	0x3231, 0xA95A, 0x32A3, 0xA949, 0x338E, 0xA94A, 0x338F, 0xA94B,
+	0x339C, 0xA94C, 0x339D, 0xA94D, 0x339E, 0xA94E, 0x33A1, 0xA94F,
+	0x33C4, 0xA950, 0x33CE, 0xA951, 0x33D1, 0xA952, 0x33D2, 0xA953,
+	0x33D5, 0xA954, 0x4E00, 0xD2BB, 0x4E01, 0xB6A1, 0x4E02, 0x8140,
+	0x4E03, 0xC6DF, 0x4E04, 0x8141, 0x4E05, 0x8142, 0x4E06, 0x8143,
+	0x4E07, 0xCDF2, 0x4E08, 0xD5C9, 0x4E09, 0xC8FD, 0x4E0A, 0xC9CF,
+	0x4E0B, 0xCFC2, 0x4E0C, 0xD8A2, 0x4E0D, 0xB2BB, 0x4E0E, 0xD3EB,
+	0x4E0F, 0x8144, 0x4E10, 0xD8A4, 0x4E11, 0xB3F3, 0x4E12, 0x8145,
+	0x4E13, 0xD7A8, 0x4E14, 0xC7D2, 0x4E15, 0xD8A7, 0x4E16, 0xCAC0,
+	0x4E17, 0x8146, 0x4E18, 0xC7F0, 0x4E19, 0xB1FB, 0x4E1A, 0xD2B5,
+	0x4E1B, 0xB4D4, 0x4E1C, 0xB6AB, 0x4E1D, 0xCBBF, 0x4E1E, 0xD8A9,
+	0x4E1F, 0x8147, 0x4E20, 0x8148, 0x4E21, 0x8149, 0x4E22, 0xB6AA,
+	0x4E23, 0x814A, 0x4E24, 0xC1BD, 0x4E25, 0xD1CF, 0x4E26, 0x814B,
+	0x4E27, 0xC9A5, 0x4E28, 0xD8AD, 0x4E29, 0x814C, 0x4E2A, 0xB8F6,
+	0x4E2B, 0xD1BE, 0x4E2C, 0xE3DC, 0x4E2D, 0xD6D0, 0x4E2E, 0x814D,
+	0x4E2F, 0x814E, 0x4E30, 0xB7E1, 0x4E31, 0x814F, 0x4E32, 0xB4AE,
+	0x4E33, 0x8150, 0x4E34, 0xC1D9, 0x4E35, 0x8151, 0x4E36, 0xD8BC,
+	0x4E37, 0x8152, 0x4E38, 0xCDE8, 0x4E39, 0xB5A4, 0x4E3A, 0xCEAA,
+	0x4E3B, 0xD6F7, 0x4E3C, 0x8153, 0x4E3D, 0xC0F6, 0x4E3E, 0xBED9,
+	0x4E3F, 0xD8AF, 0x4E40, 0x8154, 0x4E41, 0x8155, 0x4E42, 0x8156,
+	0x4E43, 0xC4CB, 0x4E44, 0x8157, 0x4E45, 0xBEC3, 0x4E46, 0x8158,
+	0x4E47, 0xD8B1, 0x4E48, 0xC3B4, 0x4E49, 0xD2E5, 0x4E4A, 0x8159,
+	0x4E4B, 0xD6AE, 0x4E4C, 0xCEDA, 0x4E4D, 0xD5A7, 0x4E4E, 0xBAF5,
+	0x4E4F, 0xB7A6, 0x4E50, 0xC0D6, 0x4E51, 0x815A, 0x4E52, 0xC6B9,
+	0x4E53, 0xC5D2, 0x4E54, 0xC7C7, 0x4E55, 0x815B, 0x4E56, 0xB9D4,
+	0x4E57, 0x815C, 0x4E58, 0xB3CB, 0x4E59, 0xD2D2, 0x4E5A, 0x815D,
+	0x4E5B, 0x815E, 0x4E5C, 0xD8BF, 0x4E5D, 0xBEC5, 0x4E5E, 0xC6F2,
+	0x4E5F, 0xD2B2, 0x4E60, 0xCFB0, 0x4E61, 0xCFE7, 0x4E62, 0x815F,
+	0x4E63, 0x8160, 0x4E64, 0x8161, 0x4E65, 0x8162, 0x4E66, 0xCAE9,
+	0x4E67, 0x8163, 0x4E68, 0x8164, 0x4E69, 0xD8C0, 0x4E6A, 0x8165,
+	0x4E6B, 0x8166, 0x4E6C, 0x8167, 0x4E6D, 0x8168, 0x4E6E, 0x8169,
+	0x4E6F, 0x816A, 0x4E70, 0xC2F2, 0x4E71, 0xC2D2, 0x4E72, 0x816B,
+	0x4E73, 0xC8E9, 0x4E74, 0x816C, 0x4E75, 0x816D, 0x4E76, 0x816E,
+	0x4E77, 0x816F, 0x4E78, 0x8170, 0x4E79, 0x8171, 0x4E7A, 0x8172,
+	0x4E7B, 0x8173, 0x4E7C, 0x8174, 0x4E7D, 0x8175, 0x4E7E, 0xC7AC,
+	0x4E7F, 0x8176, 0x4E80, 0x8177, 0x4E81, 0x8178, 0x4E82, 0x8179,
+	0x4E83, 0x817A, 0x4E84, 0x817B, 0x4E85, 0x817C, 0x4E86, 0xC1CB,
+	0x4E87, 0x817D, 0x4E88, 0xD3E8, 0x4E89, 0xD5F9, 0x4E8A, 0x817E,
+	0x4E8B, 0xCAC2, 0x4E8C, 0xB6FE, 0x4E8D, 0xD8A1, 0x4E8E, 0xD3DA,
+	0x4E8F, 0xBFF7, 0x4E90, 0x8180, 0x4E91, 0xD4C6, 0x4E92, 0xBBA5,
+	0x4E93, 0xD8C1, 0x4E94, 0xCEE5, 0x4E95, 0xBEAE, 0x4E96, 0x8181,
+	0x4E97, 0x8182, 0x4E98, 0xD8A8, 0x4E99, 0x8183, 0x4E9A, 0xD1C7,
+	0x4E9B, 0xD0A9, 0x4E9C, 0x8184, 0x4E9D, 0x8185, 0x4E9E, 0x8186,
+	0x4E9F, 0xD8BD, 0x4EA0, 0xD9EF, 0x4EA1, 0xCDF6, 0x4EA2, 0xBFBA,
+	0x4EA3, 0x8187, 0x4EA4, 0xBDBB, 0x4EA5, 0xBAA5, 0x4EA6, 0xD2E0,
+	0x4EA7, 0xB2FA, 0x4EA8, 0xBAE0, 0x4EA9, 0xC4B6, 0x4EAA, 0x8188,
+	0x4EAB, 0xCFED, 0x4EAC, 0xBEA9, 0x4EAD, 0xCDA4, 0x4EAE, 0xC1C1,
+	0x4EAF, 0x8189, 0x4EB0, 0x818A, 0x4EB1, 0x818B, 0x4EB2, 0xC7D7,
+	0x4EB3, 0xD9F1, 0x4EB4, 0x818C, 0x4EB5, 0xD9F4, 0x4EB6, 0x818D,
+	0x4EB7, 0x818E, 0x4EB8, 0x818F, 0x4EB9, 0x8190, 0x4EBA, 0xC8CB,
+	0x4EBB, 0xD8E9, 0x4EBC, 0x8191, 0x4EBD, 0x8192, 0x4EBE, 0x8193,
+	0x4EBF, 0xD2DA, 0x4EC0, 0xCAB2, 0x4EC1, 0xC8CA, 0x4EC2, 0xD8EC,
+	0x4EC3, 0xD8EA, 0x4EC4, 0xD8C6, 0x4EC5, 0xBDF6, 0x4EC6, 0xC6CD,
+	0x4EC7, 0xB3F0, 0x4EC8, 0x8194, 0x4EC9, 0xD8EB, 0x4ECA, 0xBDF1,
+	0x4ECB, 0xBDE9, 0x4ECC, 0x8195, 0x4ECD, 0xC8D4, 0x4ECE, 0xB4D3,
+	0x4ECF, 0x8196, 0x4ED0, 0x8197, 0x4ED1, 0xC2D8, 0x4ED2, 0x8198,
+	0x4ED3, 0xB2D6, 0x4ED4, 0xD7D0, 0x4ED5, 0xCACB, 0x4ED6, 0xCBFB,
+	0x4ED7, 0xD5CC, 0x4ED8, 0xB8B6, 0x4ED9, 0xCFC9, 0x4EDA, 0x8199,
+	0x4EDB, 0x819A, 0x4EDC, 0x819B, 0x4EDD, 0xD9DA, 0x4EDE, 0xD8F0,
+	0x4EDF, 0xC7AA, 0x4EE0, 0x819C, 0x4EE1, 0xD8EE, 0x4EE2, 0x819D,
+	0x4EE3, 0xB4FA, 0x4EE4, 0xC1EE, 0x4EE5, 0xD2D4, 0x4EE6, 0x819E,
+	0x4EE7, 0x819F, 0x4EE8, 0xD8ED, 0x4EE9, 0x81A0, 0x4EEA, 0xD2C7,
+	0x4EEB, 0xD8EF, 0x4EEC, 0xC3C7, 0x4EED, 0x81A1, 0x4EEE, 0x81A2,
+	0x4EEF, 0x81A3, 0x4EF0, 0xD1F6, 0x4EF1, 0x81A4, 0x4EF2, 0xD6D9,
+	0x4EF3, 0xD8F2, 0x4EF4, 0x81A5, 0x4EF5, 0xD8F5, 0x4EF6, 0xBCFE,
+	0x4EF7, 0xBCDB, 0x4EF8, 0x81A6, 0x4EF9, 0x81A7, 0x4EFA, 0x81A8,
+	0x4EFB, 0xC8CE, 0x4EFC, 0x81A9, 0x4EFD, 0xB7DD, 0x4EFE, 0x81AA,
+	0x4EFF, 0xB7C2, 0x4F00, 0x81AB, 0x4F01, 0xC6F3, 0x4F02, 0x81AC,
+	0x4F03, 0x81AD, 0x4F04, 0x81AE, 0x4F05, 0x81AF, 0x4F06, 0x81B0,
+	0x4F07, 0x81B1, 0x4F08, 0x81B2, 0x4F09, 0xD8F8, 0x4F0A, 0xD2C1,
+	0x4F0B, 0x81B3, 0x4F0C, 0x81B4, 0x4F0D, 0xCEE9, 0x4F0E, 0xBCBF,
+	0x4F0F, 0xB7FC, 0x4F10, 0xB7A5, 0x4F11, 0xD0DD, 0x4F12, 0x81B5,
+	0x4F13, 0x81B6, 0x4F14, 0x81B7, 0x4F15, 0x81B8, 0x4F16, 0x81B9,
+	0x4F17, 0xD6DA, 0x4F18, 0xD3C5, 0x4F19, 0xBBEF, 0x4F1A, 0xBBE1,
+	0x4F1B, 0xD8F1, 0x4F1C, 0x81BA, 0x4F1D, 0x81BB, 0x4F1E, 0xC9A1,
+	0x4F1F, 0xCEB0, 0x4F20, 0xB4AB, 0x4F21, 0x81BC, 0x4F22, 0xD8F3,
+	0x4F23, 0x81BD, 0x4F24, 0xC9CB, 0x4F25, 0xD8F6, 0x4F26, 0xC2D7,
+	0x4F27, 0xD8F7, 0x4F28, 0x81BE, 0x4F29, 0x81BF, 0x4F2A, 0xCEB1,
+	0x4F2B, 0xD8F9, 0x4F2C, 0x81C0, 0x4F2D, 0x81C1, 0x4F2E, 0x81C2,
+	0x4F2F, 0xB2AE, 0x4F30, 0xB9C0, 0x4F31, 0x81C3, 0x4F32, 0xD9A3,
+	0x4F33, 0x81C4, 0x4F34, 0xB0E9, 0x4F35, 0x81C5, 0x4F36, 0xC1E6,
+	0x4F37, 0x81C6, 0x4F38, 0xC9EC, 0x4F39, 0x81C7, 0x4F3A, 0xCBC5,
+	0x4F3B, 0x81C8, 0x4F3C, 0xCBC6, 0x4F3D, 0xD9A4, 0x4F3E, 0x81C9,
+	0x4F3F, 0x81CA, 0x4F40, 0x81CB, 0x4F41, 0x81CC, 0x4F42, 0x81CD,
+	0x4F43, 0xB5E8, 0x4F44, 0x81CE, 0x4F45, 0x81CF, 0x4F46, 0xB5AB,
+	0x4F47, 0x81D0, 0x4F48, 0x81D1, 0x4F49, 0x81D2, 0x4F4A, 0x81D3,
+	0x4F4B, 0x81D4, 0x4F4C, 0x81D5, 0x4F4D, 0xCEBB, 0x4F4E, 0xB5CD,
+	0x4F4F, 0xD7A1, 0x4F50, 0xD7F4, 0x4F51, 0xD3D3, 0x4F52, 0x81D6,
+	0x4F53, 0xCCE5, 0x4F54, 0x81D7, 0x4F55, 0xBACE, 0x4F56, 0x81D8,
+	0x4F57, 0xD9A2, 0x4F58, 0xD9DC, 0x4F59, 0xD3E0, 0x4F5A, 0xD8FD,
+	0x4F5B, 0xB7F0, 0x4F5C, 0xD7F7, 0x4F5D, 0xD8FE, 0x4F5E, 0xD8FA,
+	0x4F5F, 0xD9A1, 0x4F60, 0xC4E3, 0x4F61, 0x81D9, 0x4F62, 0x81DA,
+	0x4F63, 0xD3B6, 0x4F64, 0xD8F4, 0x4F65, 0xD9DD, 0x4F66, 0x81DB,
+	0x4F67, 0xD8FB, 0x4F68, 0x81DC, 0x4F69, 0xC5E5, 0x4F6A, 0x81DD,
+	0x4F6B, 0x81DE, 0x4F6C, 0xC0D0, 0x4F6D, 0x81DF, 0x4F6E, 0x81E0,
+	0x4F6F, 0xD1F0, 0x4F70, 0xB0DB, 0x4F71, 0x81E1, 0x4F72, 0x81E2,
+	0x4F73, 0xBCD1, 0x4F74, 0xD9A6, 0x4F75, 0x81E3, 0x4F76, 0xD9A5,
+	0x4F77, 0x81E4, 0x4F78, 0x81E5, 0x4F79, 0x81E6, 0x4F7A, 0x81E7,
+	0x4F7B, 0xD9AC, 0x4F7C, 0xD9AE, 0x4F7D, 0x81E8, 0x4F7E, 0xD9AB,
+	0x4F7F, 0xCAB9, 0x4F80, 0x81E9, 0x4F81, 0x81EA, 0x4F82, 0x81EB,
+	0x4F83, 0xD9A9, 0x4F84, 0xD6B6, 0x4F85, 0x81EC, 0x4F86, 0x81ED,
+	0x4F87, 0x81EE, 0x4F88, 0xB3DE, 0x4F89, 0xD9A8, 0x4F8A, 0x81EF,
+	0x4F8B, 0xC0FD, 0x4F8C, 0x81F0, 0x4F8D, 0xCACC, 0x4F8E, 0x81F1,
+	0x4F8F, 0xD9AA, 0x4F90, 0x81F2, 0x4F91, 0xD9A7, 0x4F92, 0x81F3,
+	0x4F93, 0x81F4, 0x4F94, 0xD9B0, 0x4F95, 0x81F5, 0x4F96, 0x81F6,
+	0x4F97, 0xB6B1, 0x4F98, 0x81F7, 0x4F99, 0x81F8, 0x4F9A, 0x81F9,
+	0x4F9B, 0xB9A9, 0x4F9C, 0x81FA, 0x4F9D, 0xD2C0, 0x4F9E, 0x81FB,
+	0x4F9F, 0x81FC, 0x4FA0, 0xCFC0, 0x4FA1, 0x81FD, 0x4FA2, 0x81FE,
+	0x4FA3, 0xC2C2, 0x4FA4, 0x8240, 0x4FA5, 0xBDC4, 0x4FA6, 0xD5EC,
+	0x4FA7, 0xB2E0, 0x4FA8, 0xC7C8, 0x4FA9, 0xBFEB, 0x4FAA, 0xD9AD,
+	0x4FAB, 0x8241, 0x4FAC, 0xD9AF, 0x4FAD, 0x8242, 0x4FAE, 0xCEEA,
+	0x4FAF, 0xBAEE, 0x4FB0, 0x8243, 0x4FB1, 0x8244, 0x4FB2, 0x8245,
+	0x4FB3, 0x8246, 0x4FB4, 0x8247, 0x4FB5, 0xC7D6, 0x4FB6, 0x8248,
+	0x4FB7, 0x8249, 0x4FB8, 0x824A, 0x4FB9, 0x824B, 0x4FBA, 0x824C,
+	0x4FBB, 0x824D, 0x4FBC, 0x824E, 0x4FBD, 0x824F, 0x4FBE, 0x8250,
+	0x4FBF, 0xB1E3, 0x4FC0, 0x8251, 0x4FC1, 0x8252, 0x4FC2, 0x8253,
+	0x4FC3, 0xB4D9, 0x4FC4, 0xB6ED, 0x4FC5, 0xD9B4, 0x4FC6, 0x8254,
+	0x4FC7, 0x8255, 0x4FC8, 0x8256, 0x4FC9, 0x8257, 0x4FCA, 0xBFA1,
+	0x4FCB, 0x8258, 0x4FCC, 0x8259, 0x4FCD, 0x825A, 0x4FCE, 0xD9DE,
+	0x4FCF, 0xC7CE, 0x4FD0, 0xC0FE, 0x4FD1, 0xD9B8, 0x4FD2, 0x825B,
+	0x4FD3, 0x825C, 0x4FD4, 0x825D, 0x4FD5, 0x825E, 0x4FD6, 0x825F,
+	0x4FD7, 0xCBD7, 0x4FD8, 0xB7FD, 0x4FD9, 0x8260, 0x4FDA, 0xD9B5,
+	0x4FDB, 0x8261, 0x4FDC, 0xD9B7, 0x4FDD, 0xB1A3, 0x4FDE, 0xD3E1,
+	0x4FDF, 0xD9B9, 0x4FE0, 0x8262, 0x4FE1, 0xD0C5, 0x4FE2, 0x8263,
+	0x4FE3, 0xD9B6, 0x4FE4, 0x8264, 0x4FE5, 0x8265, 0x4FE6, 0xD9B1,
+	0x4FE7, 0x8266, 0x4FE8, 0xD9B2, 0x4FE9, 0xC1A9, 0x4FEA, 0xD9B3,
+	0x4FEB, 0x8267, 0x4FEC, 0x8268, 0x4FED, 0xBCF3, 0x4FEE, 0xD0DE,
+	0x4FEF, 0xB8A9, 0x4FF0, 0x8269, 0x4FF1, 0xBEE3, 0x4FF2, 0x826A,
+	0x4FF3, 0xD9BD, 0x4FF4, 0x826B, 0x4FF5, 0x826C, 0x4FF6, 0x826D,
+	0x4FF7, 0x826E, 0x4FF8, 0xD9BA, 0x4FF9, 0x826F, 0x4FFA, 0xB0B3,
+	0x4FFB, 0x8270, 0x4FFC, 0x8271, 0x4FFD, 0x8272, 0x4FFE, 0xD9C2,
+	0x4FFF, 0x8273, 0x5000, 0x8274, 0x5001, 0x8275, 0x5002, 0x8276,
+	0x5003, 0x8277, 0x5004, 0x8278, 0x5005, 0x8279, 0x5006, 0x827A,
+	0x5007, 0x827B, 0x5008, 0x827C, 0x5009, 0x827D, 0x500A, 0x827E,
+	0x500B, 0x8280, 0x500C, 0xD9C4, 0x500D, 0xB1B6, 0x500E, 0x8281,
+	0x500F, 0xD9BF, 0x5010, 0x8282, 0x5011, 0x8283, 0x5012, 0xB5B9,
+	0x5013, 0x8284, 0x5014, 0xBEF3, 0x5015, 0x8285, 0x5016, 0x8286,
+	0x5017, 0x8287, 0x5018, 0xCCC8, 0x5019, 0xBAF2, 0x501A, 0xD2D0,
+	0x501B, 0x8288, 0x501C, 0xD9C3, 0x501D, 0x8289, 0x501E, 0x828A,
+	0x501F, 0xBDE8, 0x5020, 0x828B, 0x5021, 0xB3AB, 0x5022, 0x828C,
+	0x5023, 0x828D, 0x5024, 0x828E, 0x5025, 0xD9C5, 0x5026, 0xBEEB,
+	0x5027, 0x828F, 0x5028, 0xD9C6, 0x5029, 0xD9BB, 0x502A, 0xC4DF,
+	0x502B, 0x8290, 0x502C, 0xD9BE, 0x502D, 0xD9C1, 0x502E, 0xD9C0,
+	0x502F, 0x8291, 0x5030, 0x8292, 0x5031, 0x8293, 0x5032, 0x8294,
+	0x5033, 0x8295, 0x5034, 0x8296, 0x5035, 0x8297, 0x5036, 0x8298,
+	0x5037, 0x8299, 0x5038, 0x829A, 0x5039, 0x829B, 0x503A, 0xD5AE,
+	0x503B, 0x829C, 0x503C, 0xD6B5, 0x503D, 0x829D, 0x503E, 0xC7E3,
+	0x503F, 0x829E, 0x5040, 0x829F, 0x5041, 0x82A0, 0x5042, 0x82A1,
+	0x5043, 0xD9C8, 0x5044, 0x82A2, 0x5045, 0x82A3, 0x5046, 0x82A4,
+	0x5047, 0xBCD9, 0x5048, 0xD9CA, 0x5049, 0x82A5, 0x504A, 0x82A6,
+	0x504B, 0x82A7, 0x504C, 0xD9BC, 0x504D, 0x82A8, 0x504E, 0xD9CB,
+	0x504F, 0xC6AB, 0x5050, 0x82A9, 0x5051, 0x82AA, 0x5052, 0x82AB,
+	0x5053, 0x82AC, 0x5054, 0x82AD, 0x5055, 0xD9C9, 0x5056, 0x82AE,
+	0x5057, 0x82AF, 0x5058, 0x82B0, 0x5059, 0x82B1, 0x505A, 0xD7F6,
+	0x505B, 0x82B2, 0x505C, 0xCDA3, 0x505D, 0x82B3, 0x505E, 0x82B4,
+	0x505F, 0x82B5, 0x5060, 0x82B6, 0x5061, 0x82B7, 0x5062, 0x82B8,
+	0x5063, 0x82B9, 0x5064, 0x82BA, 0x5065, 0xBDA1, 0x5066, 0x82BB,
+	0x5067, 0x82BC, 0x5068, 0x82BD, 0x5069, 0x82BE, 0x506A, 0x82BF,
+	0x506B, 0x82C0, 0x506C, 0xD9CC, 0x506D, 0x82C1, 0x506E, 0x82C2,
+	0x506F, 0x82C3, 0x5070, 0x82C4, 0x5071, 0x82C5, 0x5072, 0x82C6,
+	0x5073, 0x82C7, 0x5074, 0x82C8, 0x5075, 0x82C9, 0x5076, 0xC5BC,
+	0x5077, 0xCDB5, 0x5078, 0x82CA, 0x5079, 0x82CB, 0x507A, 0x82CC,
+	0x507B, 0xD9CD, 0x507C, 0x82CD, 0x507D, 0x82CE, 0x507E, 0xD9C7,
+	0x507F, 0xB3A5, 0x5080, 0xBFFE, 0x5081, 0x82CF, 0x5082, 0x82D0,
+	0x5083, 0x82D1, 0x5084, 0x82D2, 0x5085, 0xB8B5, 0x5086, 0x82D3,
+	0x5087, 0x82D4, 0x5088, 0xC0FC, 0x5089, 0x82D5, 0x508A, 0x82D6,
+	0x508B, 0x82D7, 0x508C, 0x82D8, 0x508D, 0xB0F8, 0x508E, 0x82D9,
+	0x508F, 0x82DA, 0x5090, 0x82DB, 0x5091, 0x82DC, 0x5092, 0x82DD,
+	0x5093, 0x82DE, 0x5094, 0x82DF, 0x5095, 0x82E0, 0x5096, 0x82E1,
+	0x5097, 0x82E2, 0x5098, 0x82E3, 0x5099, 0x82E4, 0x509A, 0x82E5,
+	0x509B, 0x82E6, 0x509C, 0x82E7, 0x509D, 0x82E8, 0x509E, 0x82E9,
+	0x509F, 0x82EA, 0x50A0, 0x82EB, 0x50A1, 0x82EC, 0x50A2, 0x82ED,
+	0x50A3, 0xB4F6, 0x50A4, 0x82EE, 0x50A5, 0xD9CE, 0x50A6, 0x82EF,
+	0x50A7, 0xD9CF, 0x50A8, 0xB4A2, 0x50A9, 0xD9D0, 0x50AA, 0x82F0,
+	0x50AB, 0x82F1, 0x50AC, 0xB4DF, 0x50AD, 0x82F2, 0x50AE, 0x82F3,
+	0x50AF, 0x82F4, 0x50B0, 0x82F5, 0x50B1, 0x82F6, 0x50B2, 0xB0C1,
+	0x50B3, 0x82F7, 0x50B4, 0x82F8, 0x50B5, 0x82F9, 0x50B6, 0x82FA,
+	0x50B7, 0x82FB, 0x50B8, 0x82FC, 0x50B9, 0x82FD, 0x50BA, 0xD9D1,
+	0x50BB, 0xC9B5, 0x50BC, 0x82FE, 0x50BD, 0x8340, 0x50BE, 0x8341,
+	0x50BF, 0x8342, 0x50C0, 0x8343, 0x50C1, 0x8344, 0x50C2, 0x8345,
+	0x50C3, 0x8346, 0x50C4, 0x8347, 0x50C5, 0x8348, 0x50C6, 0x8349,
+	0x50C7, 0x834A, 0x50C8, 0x834B, 0x50C9, 0x834C, 0x50CA, 0x834D,
+	0x50CB, 0x834E, 0x50CC, 0x834F, 0x50CD, 0x8350, 0x50CE, 0x8351,
+	0x50CF, 0xCFF1, 0x50D0, 0x8352, 0x50D1, 0x8353, 0x50D2, 0x8354,
+	0x50D3, 0x8355, 0x50D4, 0x8356, 0x50D5, 0x8357, 0x50D6, 0xD9D2,
+	0x50D7, 0x8358, 0x50D8, 0x8359, 0x50D9, 0x835A, 0x50DA, 0xC1C5,
+	0x50DB, 0x835B, 0x50DC, 0x835C, 0x50DD, 0x835D, 0x50DE, 0x835E,
+	0x50DF, 0x835F, 0x50E0, 0x8360, 0x50E1, 0x8361, 0x50E2, 0x8362,
+	0x50E3, 0x8363, 0x50E4, 0x8364, 0x50E5, 0x8365, 0x50E6, 0xD9D6,
+	0x50E7, 0xC9AE, 0x50E8, 0x8366, 0x50E9, 0x8367, 0x50EA, 0x8368,
+	0x50EB, 0x8369, 0x50EC, 0xD9D5, 0x50ED, 0xD9D4, 0x50EE, 0xD9D7,
+	0x50EF, 0x836A, 0x50F0, 0x836B, 0x50F1, 0x836C, 0x50F2, 0x836D,
+	0x50F3, 0xCBDB, 0x50F4, 0x836E, 0x50F5, 0xBDA9, 0x50F6, 0x836F,
+	0x50F7, 0x8370, 0x50F8, 0x8371, 0x50F9, 0x8372, 0x50FA, 0x8373,
+	0x50FB, 0xC6A7, 0x50FC, 0x8374, 0x50FD, 0x8375, 0x50FE, 0x8376,
+	0x50FF, 0x8377, 0x5100, 0x8378, 0x5101, 0x8379, 0x5102, 0x837A,
+	0x5103, 0x837B, 0x5104, 0x837C, 0x5105, 0x837D, 0x5106, 0xD9D3,
+	0x5107, 0xD9D8, 0x5108, 0x837E, 0x5109, 0x8380, 0x510A, 0x8381,
+	0x510B, 0xD9D9, 0x510C, 0x8382, 0x510D, 0x8383, 0x510E, 0x8384,
+	0x510F, 0x8385, 0x5110, 0x8386, 0x5111, 0x8387, 0x5112, 0xC8E5,
+	0x5113, 0x8388, 0x5114, 0x8389, 0x5115, 0x838A, 0x5116, 0x838B,
+	0x5117, 0x838C, 0x5118, 0x838D, 0x5119, 0x838E, 0x511A, 0x838F,
+	0x511B, 0x8390, 0x511C, 0x8391, 0x511D, 0x8392, 0x511E, 0x8393,
+	0x511F, 0x8394, 0x5120, 0x8395, 0x5121, 0xC0DC, 0x5122, 0x8396,
+	0x5123, 0x8397, 0x5124, 0x8398, 0x5125, 0x8399, 0x5126, 0x839A,
+	0x5127, 0x839B, 0x5128, 0x839C, 0x5129, 0x839D, 0x512A, 0x839E,
+	0x512B, 0x839F, 0x512C, 0x83A0, 0x512D, 0x83A1, 0x512E, 0x83A2,
+	0x512F, 0x83A3, 0x5130, 0x83A4, 0x5131, 0x83A5, 0x5132, 0x83A6,
+	0x5133, 0x83A7, 0x5134, 0x83A8, 0x5135, 0x83A9, 0x5136, 0x83AA,
+	0x5137, 0x83AB, 0x5138, 0x83AC, 0x5139, 0x83AD, 0x513A, 0x83AE,
+	0x513B, 0x83AF, 0x513C, 0x83B0, 0x513D, 0x83B1, 0x513E, 0x83B2,
+	0x513F, 0xB6F9, 0x5140, 0xD8A3, 0x5141, 0xD4CA, 0x5142, 0x83B3,
+	0x5143, 0xD4AA, 0x5144, 0xD0D6, 0x5145, 0xB3E4, 0x5146, 0xD5D7,
+	0x5147, 0x83B4, 0x5148, 0xCFC8, 0x5149, 0xB9E2, 0x514A, 0x83B5,
+	0x514B, 0xBFCB, 0x514C, 0x83B6, 0x514D, 0xC3E2, 0x514E, 0x83B7,
+	0x514F, 0x83B8, 0x5150, 0x83B9, 0x5151, 0xB6D2, 0x5152, 0x83BA,
+	0x5153, 0x83BB, 0x5154, 0xCDC3, 0x5155, 0xD9EE, 0x5156, 0xD9F0,
+	0x5157, 0x83BC, 0x5158, 0x83BD, 0x5159, 0x83BE, 0x515A, 0xB5B3,
+	0x515B, 0x83BF, 0x515C, 0xB6B5, 0x515D, 0x83C0, 0x515E, 0x83C1,
+	0x515F, 0x83C2, 0x5160, 0x83C3, 0x5161, 0x83C4, 0x5162, 0xBEA4,
+	0x5163, 0x83C5, 0x5164, 0x83C6, 0x5165, 0xC8EB, 0x5166, 0x83C7,
+	0x5167, 0x83C8, 0x5168, 0xC8AB, 0x5169, 0x83C9, 0x516A, 0x83CA,
+	0x516B, 0xB0CB, 0x516C, 0xB9AB, 0x516D, 0xC1F9, 0x516E, 0xD9E2,
+	0x516F, 0x83CB, 0x5170, 0xC0BC, 0x5171, 0xB9B2, 0x5172, 0x83CC,
+	0x5173, 0xB9D8, 0x5174, 0xD0CB, 0x5175, 0xB1F8, 0x5176, 0xC6E4,
+	0x5177, 0xBEDF, 0x5178, 0xB5E4, 0x5179, 0xD7C8, 0x517A, 0x83CD,
+	0x517B, 0xD1F8, 0x517C, 0xBCE6, 0x517D, 0xCADE, 0x517E, 0x83CE,
+	0x517F, 0x83CF, 0x5180, 0xBCBD, 0x5181, 0xD9E6, 0x5182, 0xD8E7,
+	0x5183, 0x83D0, 0x5184, 0x83D1, 0x5185, 0xC4DA, 0x5186, 0x83D2,
+	0x5187, 0x83D3, 0x5188, 0xB8D4, 0x5189, 0xC8BD, 0x518A, 0x83D4,
+	0x518B, 0x83D5, 0x518C, 0xB2E1, 0x518D, 0xD4D9, 0x518E, 0x83D6,
+	0x518F, 0x83D7, 0x5190, 0x83D8, 0x5191, 0x83D9, 0x5192, 0xC3B0,
+	0x5193, 0x83DA, 0x5194, 0x83DB, 0x5195, 0xC3E1, 0x5196, 0xDAA2,
+	0x5197, 0xC8DF, 0x5198, 0x83DC, 0x5199, 0xD0B4, 0x519A, 0x83DD,
+	0x519B, 0xBEFC, 0x519C, 0xC5A9, 0x519D, 0x83DE, 0x519E, 0x83DF,
+	0x519F, 0x83E0, 0x51A0, 0xB9DA, 0x51A1, 0x83E1, 0x51A2, 0xDAA3,
+	0x51A3, 0x83E2, 0x51A4, 0xD4A9, 0x51A5, 0xDAA4, 0x51A6, 0x83E3,
+	0x51A7, 0x83E4, 0x51A8, 0x83E5, 0x51A9, 0x83E6, 0x51AA, 0x83E7,
+	0x51AB, 0xD9FB, 0x51AC, 0xB6AC, 0x51AD, 0x83E8, 0x51AE, 0x83E9,
+	0x51AF, 0xB7EB, 0x51B0, 0xB1F9, 0x51B1, 0xD9FC, 0x51B2, 0xB3E5,
+	0x51B3, 0xBEF6, 0x51B4, 0x83EA, 0x51B5, 0xBFF6, 0x51B6, 0xD2B1,
+	0x51B7, 0xC0E4, 0x51B8, 0x83EB, 0x51B9, 0x83EC, 0x51BA, 0x83ED,
+	0x51BB, 0xB6B3, 0x51BC, 0xD9FE, 0x51BD, 0xD9FD, 0x51BE, 0x83EE,
+	0x51BF, 0x83EF, 0x51C0, 0xBEBB, 0x51C1, 0x83F0, 0x51C2, 0x83F1,
+	0x51C3, 0x83F2, 0x51C4, 0xC6E0, 0x51C5, 0x83F3, 0x51C6, 0xD7BC,
+	0x51C7, 0xDAA1, 0x51C8, 0x83F4, 0x51C9, 0xC1B9, 0x51CA, 0x83F5,
+	0x51CB, 0xB5F2, 0x51CC, 0xC1E8, 0x51CD, 0x83F6, 0x51CE, 0x83F7,
+	0x51CF, 0xBCF5, 0x51D0, 0x83F8, 0x51D1, 0xB4D5, 0x51D2, 0x83F9,
+	0x51D3, 0x83FA, 0x51D4, 0x83FB, 0x51D5, 0x83FC, 0x51D6, 0x83FD,
+	0x51D7, 0x83FE, 0x51D8, 0x8440, 0x51D9, 0x8441, 0x51DA, 0x8442,
+	0x51DB, 0xC1DD, 0x51DC, 0x8443, 0x51DD, 0xC4FD, 0x51DE, 0x8444,
+	0x51DF, 0x8445, 0x51E0, 0xBCB8, 0x51E1, 0xB7B2, 0x51E2, 0x8446,
+	0x51E3, 0x8447, 0x51E4, 0xB7EF, 0x51E5, 0x8448, 0x51E6, 0x8449,
+	0x51E7, 0x844A, 0x51E8, 0x844B, 0x51E9, 0x844C, 0x51EA, 0x844D,
+	0x51EB, 0xD9EC, 0x51EC, 0x844E, 0x51ED, 0xC6BE, 0x51EE, 0x844F,
+	0x51EF, 0xBFAD, 0x51F0, 0xBBCB, 0x51F1, 0x8450, 0x51F2, 0x8451,
+	0x51F3, 0xB5CA, 0x51F4, 0x8452, 0x51F5, 0xDBC9, 0x51F6, 0xD0D7,
+	0x51F7, 0x8453, 0x51F8, 0xCDB9, 0x51F9, 0xB0BC, 0x51FA, 0xB3F6,
+	0x51FB, 0xBBF7, 0x51FC, 0xDBCA, 0x51FD, 0xBAAF, 0x51FE, 0x8454,
+	0x51FF, 0xD4E4, 0x5200, 0xB5B6, 0x5201, 0xB5F3, 0x5202, 0xD8D6,
+	0x5203, 0xC8D0, 0x5204, 0x8455, 0x5205, 0x8456, 0x5206, 0xB7D6,
+	0x5207, 0xC7D0, 0x5208, 0xD8D7, 0x5209, 0x8457, 0x520A, 0xBFAF,
+	0x520B, 0x8458, 0x520C, 0x8459, 0x520D, 0xDBBB, 0x520E, 0xD8D8,
+	0x520F, 0x845A, 0x5210, 0x845B, 0x5211, 0xD0CC, 0x5212, 0xBBAE,
+	0x5213, 0x845C, 0x5214, 0x845D, 0x5215, 0x845E, 0x5216, 0xEBBE,
+	0x5217, 0xC1D0, 0x5218, 0xC1F5, 0x5219, 0xD4F2, 0x521A, 0xB8D5,
+	0x521B, 0xB4B4, 0x521C, 0x845F, 0x521D, 0xB3F5, 0x521E, 0x8460,
+	0x521F, 0x8461, 0x5220, 0xC9BE, 0x5221, 0x8462, 0x5222, 0x8463,
+	0x5223, 0x8464, 0x5224, 0xC5D0, 0x5225, 0x8465, 0x5226, 0x8466,
+	0x5227, 0x8467, 0x5228, 0xC5D9, 0x5229, 0xC0FB, 0x522A, 0x8468,
+	0x522B, 0xB1F0, 0x522C, 0x8469, 0x522D, 0xD8D9, 0x522E, 0xB9CE,
+	0x522F, 0x846A, 0x5230, 0xB5BD, 0x5231, 0x846B, 0x5232, 0x846C,
+	0x5233, 0xD8DA, 0x5234, 0x846D, 0x5235, 0x846E, 0x5236, 0xD6C6,
+	0x5237, 0xCBA2, 0x5238, 0xC8AF, 0x5239, 0xC9B2, 0x523A, 0xB4CC,
+	0x523B, 0xBFCC, 0x523C, 0x846F, 0x523D, 0xB9F4, 0x523E, 0x8470,
+	0x523F, 0xD8DB, 0x5240, 0xD8DC, 0x5241, 0xB6E7, 0x5242, 0xBCC1,
+	0x5243, 0xCCEA, 0x5244, 0x8471, 0x5245, 0x8472, 0x5246, 0x8473,
+	0x5247, 0x8474, 0x5248, 0x8475, 0x5249, 0x8476, 0x524A, 0xCFF7,
+	0x524B, 0x8477, 0x524C, 0xD8DD, 0x524D, 0xC7B0, 0x524E, 0x8478,
+	0x524F, 0x8479, 0x5250, 0xB9D0, 0x5251, 0xBDA3, 0x5252, 0x847A,
+	0x5253, 0x847B, 0x5254, 0xCCDE, 0x5255, 0x847C, 0x5256, 0xC6CA,
+	0x5257, 0x847D, 0x5258, 0x847E, 0x5259, 0x8480, 0x525A, 0x8481,
+	0x525B, 0x8482, 0x525C, 0xD8E0, 0x525D, 0x8483, 0x525E, 0xD8DE,
+	0x525F, 0x8484, 0x5260, 0x8485, 0x5261, 0xD8DF, 0x5262, 0x8486,
+	0x5263, 0x8487, 0x5264, 0x8488, 0x5265, 0xB0FE, 0x5266, 0x8489,
+	0x5267, 0xBEE7, 0x5268, 0x848A, 0x5269, 0xCAA3, 0x526A, 0xBCF4,
+	0x526B, 0x848B, 0x526C, 0x848C, 0x526D, 0x848D, 0x526E, 0x848E,
+	0x526F, 0xB8B1, 0x5270, 0x848F, 0x5271, 0x8490, 0x5272, 0xB8EE,
+	0x5273, 0x8491, 0x5274, 0x8492, 0x5275, 0x8493, 0x5276, 0x8494,
+	0x5277, 0x8495, 0x5278, 0x8496, 0x5279, 0x8497, 0x527A, 0x8498,
+	0x527B, 0x8499, 0x527C, 0x849A, 0x527D, 0xD8E2, 0x527E, 0x849B,
+	0x527F, 0xBDCB, 0x5280, 0x849C, 0x5281, 0xD8E4, 0x5282, 0xD8E3,
+	0x5283, 0x849D, 0x5284, 0x849E, 0x5285, 0x849F, 0x5286, 0x84A0,
+	0x5287, 0x84A1, 0x5288, 0xC5FC, 0x5289, 0x84A2, 0x528A, 0x84A3,
+	0x528B, 0x84A4, 0x528C, 0x84A5, 0x528D, 0x84A6, 0x528E, 0x84A7,
+	0x528F, 0x84A8, 0x5290, 0xD8E5, 0x5291, 0x84A9, 0x5292, 0x84AA,
+	0x5293, 0xD8E6, 0x5294, 0x84AB, 0x5295, 0x84AC, 0x5296, 0x84AD,
+	0x5297, 0x84AE, 0x5298, 0x84AF, 0x5299, 0x84B0, 0x529A, 0x84B1,
+	0x529B, 0xC1A6, 0x529C, 0x84B2, 0x529D, 0xC8B0, 0x529E, 0xB0EC,
+	0x529F, 0xB9A6, 0x52A0, 0xBCD3, 0x52A1, 0xCEF1, 0x52A2, 0xDBBD,
+	0x52A3, 0xC1D3, 0x52A4, 0x84B3, 0x52A5, 0x84B4, 0x52A6, 0x84B5,
+	0x52A7, 0x84B6, 0x52A8, 0xB6AF, 0x52A9, 0xD6FA, 0x52AA, 0xC5AC,
+	0x52AB, 0xBDD9, 0x52AC, 0xDBBE, 0x52AD, 0xDBBF, 0x52AE, 0x84B7,
+	0x52AF, 0x84B8, 0x52B0, 0x84B9, 0x52B1, 0xC0F8, 0x52B2, 0xBEA2,
+	0x52B3, 0xC0CD, 0x52B4, 0x84BA, 0x52B5, 0x84BB, 0x52B6, 0x84BC,
+	0x52B7, 0x84BD, 0x52B8, 0x84BE, 0x52B9, 0x84BF, 0x52BA, 0x84C0,
+	0x52BB, 0x84C1, 0x52BC, 0x84C2, 0x52BD, 0x84C3, 0x52BE, 0xDBC0,
+	0x52BF, 0xCAC6, 0x52C0, 0x84C4, 0x52C1, 0x84C5, 0x52C2, 0x84C6,
+	0x52C3, 0xB2AA, 0x52C4, 0x84C7, 0x52C5, 0x84C8, 0x52C6, 0x84C9,
+	0x52C7, 0xD3C2, 0x52C8, 0x84CA, 0x52C9, 0xC3E3, 0x52CA, 0x84CB,
+	0x52CB, 0xD1AB, 0x52CC, 0x84CC, 0x52CD, 0x84CD, 0x52CE, 0x84CE,
+	0x52CF, 0x84CF, 0x52D0, 0xDBC2, 0x52D1, 0x84D0, 0x52D2, 0xC0D5,
+	0x52D3, 0x84D1, 0x52D4, 0x84D2, 0x52D5, 0x84D3, 0x52D6, 0xDBC3,
+	0x52D7, 0x84D4, 0x52D8, 0xBFB1, 0x52D9, 0x84D5, 0x52DA, 0x84D6,
+	0x52DB, 0x84D7, 0x52DC, 0x84D8, 0x52DD, 0x84D9, 0x52DE, 0x84DA,
+	0x52DF, 0xC4BC, 0x52E0, 0x84DB, 0x52E1, 0x84DC, 0x52E2, 0x84DD,
+	0x52E3, 0x84DE, 0x52E4, 0xC7DA, 0x52E5, 0x84DF, 0x52E6, 0x84E0,
+	0x52E7, 0x84E1, 0x52E8, 0x84E2, 0x52E9, 0x84E3, 0x52EA, 0x84E4,
+	0x52EB, 0x84E5, 0x52EC, 0x84E6, 0x52ED, 0x84E7, 0x52EE, 0x84E8,
+	0x52EF, 0x84E9, 0x52F0, 0xDBC4, 0x52F1, 0x84EA, 0x52F2, 0x84EB,
+	0x52F3, 0x84EC, 0x52F4, 0x84ED, 0x52F5, 0x84EE, 0x52F6, 0x84EF,
+	0x52F7, 0x84F0, 0x52F8, 0x84F1, 0x52F9, 0xD9E8, 0x52FA, 0xC9D7,
+	0x52FB, 0x84F2, 0x52FC, 0x84F3, 0x52FD, 0x84F4, 0x52FE, 0xB9B4,
+	0x52FF, 0xCEF0, 0x5300, 0xD4C8, 0x5301, 0x84F5, 0x5302, 0x84F6,
+	0x5303, 0x84F7, 0x5304, 0x84F8, 0x5305, 0xB0FC, 0x5306, 0xB4D2,
+	0x5307, 0x84F9, 0x5308, 0xD0D9, 0x5309, 0x84FA, 0x530A, 0x84FB,
+	0x530B, 0x84FC, 0x530C, 0x84FD, 0x530D, 0xD9E9, 0x530E, 0x84FE,
+	0x530F, 0xDECB, 0x5310, 0xD9EB, 0x5311, 0x8540, 0x5312, 0x8541,
+	0x5313, 0x8542, 0x5314, 0x8543, 0x5315, 0xD8B0, 0x5316, 0xBBAF,
+	0x5317, 0xB1B1, 0x5318, 0x8544, 0x5319, 0xB3D7, 0x531A, 0xD8CE,
+	0x531B, 0x8545, 0x531C, 0x8546, 0x531D, 0xD4D1, 0x531E, 0x8547,
+	0x531F, 0x8548, 0x5320, 0xBDB3, 0x5321, 0xBFEF, 0x5322, 0x8549,
+	0x5323, 0xCFBB, 0x5324, 0x854A, 0x5325, 0x854B, 0x5326, 0xD8D0,
+	0x5327, 0x854C, 0x5328, 0x854D, 0x5329, 0x854E, 0x532A, 0xB7CB,
+	0x532B, 0x854F, 0x532C, 0x8550, 0x532D, 0x8551, 0x532E, 0xD8D1,
+	0x532F, 0x8552, 0x5330, 0x8553, 0x5331, 0x8554, 0x5332, 0x8555,
+	0x5333, 0x8556, 0x5334, 0x8557, 0x5335, 0x8558, 0x5336, 0x8559,
+	0x5337, 0x855A, 0x5338, 0x855B, 0x5339, 0xC6A5, 0x533A, 0xC7F8,
+	0x533B, 0xD2BD, 0x533C, 0x855C, 0x533D, 0x855D, 0x533E, 0xD8D2,
+	0x533F, 0xC4E4, 0x5340, 0x855E, 0x5341, 0xCAAE, 0x5342, 0x855F,
+	0x5343, 0xC7A7, 0x5344, 0x8560, 0x5345, 0xD8A6, 0x5346, 0x8561,
+	0x5347, 0xC9FD, 0x5348, 0xCEE7, 0x5349, 0xBBDC, 0x534A, 0xB0EB,
+	0x534B, 0x8562, 0x534C, 0x8563, 0x534D, 0x8564, 0x534E, 0xBBAA,
+	0x534F, 0xD0AD, 0x5350, 0x8565, 0x5351, 0xB1B0, 0x5352, 0xD7E4,
+	0x5353, 0xD7BF, 0x5354, 0x8566, 0x5355, 0xB5A5, 0x5356, 0xC2F4,
+	0x5357, 0xC4CF, 0x5358, 0x8567, 0x5359, 0x8568, 0x535A, 0xB2A9,
+	0x535B, 0x8569, 0x535C, 0xB2B7, 0x535D, 0x856A, 0x535E, 0xB1E5,
+	0x535F, 0xDFB2, 0x5360, 0xD5BC, 0x5361, 0xBFA8, 0x5362, 0xC2AC,
+	0x5363, 0xD8D5, 0x5364, 0xC2B1, 0x5365, 0x856B, 0x5366, 0xD8D4,
+	0x5367, 0xCED4, 0x5368, 0x856C, 0x5369, 0xDAE0, 0x536A, 0x856D,
+	0x536B, 0xCEC0, 0x536C, 0x856E, 0x536D, 0x856F, 0x536E, 0xD8B4,
+	0x536F, 0xC3AE, 0x5370, 0xD3A1, 0x5371, 0xCEA3, 0x5372, 0x8570,
+	0x5373, 0xBCB4, 0x5374, 0xC8B4, 0x5375, 0xC2D1, 0x5376, 0x8571,
+	0x5377, 0xBEED, 0x5378, 0xD0B6, 0x5379, 0x8572, 0x537A, 0xDAE1,
+	0x537B, 0x8573, 0x537C, 0x8574, 0x537D, 0x8575, 0x537E, 0x8576,
+	0x537F, 0xC7E4, 0x5380, 0x8577, 0x5381, 0x8578, 0x5382, 0xB3A7,
+	0x5383, 0x8579, 0x5384, 0xB6F2, 0x5385, 0xCCFC, 0x5386, 0xC0FA,
+	0x5387, 0x857A, 0x5388, 0x857B, 0x5389, 0xC0F7, 0x538A, 0x857C,
+	0x538B, 0xD1B9, 0x538C, 0xD1E1, 0x538D, 0xD8C7, 0x538E, 0x857D,
+	0x538F, 0x857E, 0x5390, 0x8580, 0x5391, 0x8581, 0x5392, 0x8582,
+	0x5393, 0x8583, 0x5394, 0x8584, 0x5395, 0xB2DE, 0x5396, 0x8585,
+	0x5397, 0x8586, 0x5398, 0xC0E5, 0x5399, 0x8587, 0x539A, 0xBAF1,
+	0x539B, 0x8588, 0x539C, 0x8589, 0x539D, 0xD8C8, 0x539E, 0x858A,
+	0x539F, 0xD4AD, 0x53A0, 0x858B, 0x53A1, 0x858C, 0x53A2, 0xCFE1,
+	0x53A3, 0xD8C9, 0x53A4, 0x858D, 0x53A5, 0xD8CA, 0x53A6, 0xCFC3,
+	0x53A7, 0x858E, 0x53A8, 0xB3F8, 0x53A9, 0xBEC7, 0x53AA, 0x858F,
+	0x53AB, 0x8590, 0x53AC, 0x8591, 0x53AD, 0x8592, 0x53AE, 0xD8CB,
+	0x53AF, 0x8593, 0x53B0, 0x8594, 0x53B1, 0x8595, 0x53B2, 0x8596,
+	0x53B3, 0x8597, 0x53B4, 0x8598, 0x53B5, 0x8599, 0x53B6, 0xDBCC,
+	0x53B7, 0x859A, 0x53B8, 0x859B, 0x53B9, 0x859C, 0x53BA, 0x859D,
+	0x53BB, 0xC8A5, 0x53BC, 0x859E, 0x53BD, 0x859F, 0x53BE, 0x85A0,
+	0x53BF, 0xCFD8, 0x53C0, 0x85A1, 0x53C1, 0xC8FE, 0x53C2, 0xB2CE,
+	0x53C3, 0x85A2, 0x53C4, 0x85A3, 0x53C5, 0x85A4, 0x53C6, 0x85A5,
+	0x53C7, 0x85A6, 0x53C8, 0xD3D6, 0x53C9, 0xB2E6, 0x53CA, 0xBCB0,
+	0x53CB, 0xD3D1, 0x53CC, 0xCBAB, 0x53CD, 0xB7B4, 0x53CE, 0x85A7,
+	0x53CF, 0x85A8, 0x53D0, 0x85A9, 0x53D1, 0xB7A2, 0x53D2, 0x85AA,
+	0x53D3, 0x85AB, 0x53D4, 0xCAE5, 0x53D5, 0x85AC, 0x53D6, 0xC8A1,
+	0x53D7, 0xCADC, 0x53D8, 0xB1E4, 0x53D9, 0xD0F0, 0x53DA, 0x85AD,
+	0x53DB, 0xC5D1, 0x53DC, 0x85AE, 0x53DD, 0x85AF, 0x53DE, 0x85B0,
+	0x53DF, 0xDBC5, 0x53E0, 0xB5FE, 0x53E1, 0x85B1, 0x53E2, 0x85B2,
+	0x53E3, 0xBFDA, 0x53E4, 0xB9C5, 0x53E5, 0xBEE4, 0x53E6, 0xC1ED,
+	0x53E7, 0x85B3, 0x53E8, 0xDFB6, 0x53E9, 0xDFB5, 0x53EA, 0xD6BB,
+	0x53EB, 0xBDD0, 0x53EC, 0xD5D9, 0x53ED, 0xB0C8, 0x53EE, 0xB6A3,
+	0x53EF, 0xBFC9, 0x53F0, 0xCCA8, 0x53F1, 0xDFB3, 0x53F2, 0xCAB7,
+	0x53F3, 0xD3D2, 0x53F4, 0x85B4, 0x53F5, 0xD8CF, 0x53F6, 0xD2B6,
+	0x53F7, 0xBAC5, 0x53F8, 0xCBBE, 0x53F9, 0xCCBE, 0x53FA, 0x85B5,
+	0x53FB, 0xDFB7, 0x53FC, 0xB5F0, 0x53FD, 0xDFB4, 0x53FE, 0x85B6,
+	0x53FF, 0x85B7, 0x5400, 0x85B8, 0x5401, 0xD3F5, 0x5402, 0x85B9,
+	0x5403, 0xB3D4, 0x5404, 0xB8F7, 0x5405, 0x85BA, 0x5406, 0xDFBA,
+	0x5407, 0x85BB, 0x5408, 0xBACF, 0x5409, 0xBCAA, 0x540A, 0xB5F5,
+	0x540B, 0x85BC, 0x540C, 0xCDAC, 0x540D, 0xC3FB, 0x540E, 0xBAF3,
+	0x540F, 0xC0F4, 0x5410, 0xCDC2, 0x5411, 0xCFF2, 0x5412, 0xDFB8,
+	0x5413, 0xCFC5, 0x5414, 0x85BD, 0x5415, 0xC2C0, 0x5416, 0xDFB9,
+	0x5417, 0xC2F0, 0x5418, 0x85BE, 0x5419, 0x85BF, 0x541A, 0x85C0,
+	0x541B, 0xBEFD, 0x541C, 0x85C1, 0x541D, 0xC1DF, 0x541E, 0xCDCC,
+	0x541F, 0xD2F7, 0x5420, 0xB7CD, 0x5421, 0xDFC1, 0x5422, 0x85C2,
+	0x5423, 0xDFC4, 0x5424, 0x85C3, 0x5425, 0x85C4, 0x5426, 0xB7F1,
+	0x5427, 0xB0C9, 0x5428, 0xB6D6, 0x5429, 0xB7D4, 0x542A, 0x85C5,
+	0x542B, 0xBAAC, 0x542C, 0xCCFD, 0x542D, 0xBFD4, 0x542E, 0xCBB1,
+	0x542F, 0xC6F4, 0x5430, 0x85C6, 0x5431, 0xD6A8, 0x5432, 0xDFC5,
+	0x5433, 0x85C7, 0x5434, 0xCEE2, 0x5435, 0xB3B3, 0x5436, 0x85C8,
+	0x5437, 0x85C9, 0x5438, 0xCEFC, 0x5439, 0xB4B5, 0x543A, 0x85CA,
+	0x543B, 0xCEC7, 0x543C, 0xBAF0, 0x543D, 0x85CB, 0x543E, 0xCEE1,
+	0x543F, 0x85CC, 0x5440, 0xD1BD, 0x5441, 0x85CD, 0x5442, 0x85CE,
+	0x5443, 0xDFC0, 0x5444, 0x85CF, 0x5445, 0x85D0, 0x5446, 0xB4F4,
+	0x5447, 0x85D1, 0x5448, 0xB3CA, 0x5449, 0x85D2, 0x544A, 0xB8E6,
+	0x544B, 0xDFBB, 0x544C, 0x85D3, 0x544D, 0x85D4, 0x544E, 0x85D5,
+	0x544F, 0x85D6, 0x5450, 0xC4C5, 0x5451, 0x85D7, 0x5452, 0xDFBC,
+	0x5453, 0xDFBD, 0x5454, 0xDFBE, 0x5455, 0xC5BB, 0x5456, 0xDFBF,
+	0x5457, 0xDFC2, 0x5458, 0xD4B1, 0x5459, 0xDFC3, 0x545A, 0x85D8,
+	0x545B, 0xC7BA, 0x545C, 0xCED8, 0x545D, 0x85D9, 0x545E, 0x85DA,
+	0x545F, 0x85DB, 0x5460, 0x85DC, 0x5461, 0x85DD, 0x5462, 0xC4D8,
+	0x5463, 0x85DE, 0x5464, 0xDFCA, 0x5465, 0x85DF, 0x5466, 0xDFCF,
+	0x5467, 0x85E0, 0x5468, 0xD6DC, 0x5469, 0x85E1, 0x546A, 0x85E2,
+	0x546B, 0x85E3, 0x546C, 0x85E4, 0x546D, 0x85E5, 0x546E, 0x85E6,
+	0x546F, 0x85E7, 0x5470, 0x85E8, 0x5471, 0xDFC9, 0x5472, 0xDFDA,
+	0x5473, 0xCEB6, 0x5474, 0x85E9, 0x5475, 0xBAC7, 0x5476, 0xDFCE,
+	0x5477, 0xDFC8, 0x5478, 0xC5DE, 0x5479, 0x85EA, 0x547A, 0x85EB,
+	0x547B, 0xC9EB, 0x547C, 0xBAF4, 0x547D, 0xC3FC, 0x547E, 0x85EC,
+	0x547F, 0x85ED, 0x5480, 0xBED7, 0x5481, 0x85EE, 0x5482, 0xDFC6,
+	0x5483, 0x85EF, 0x5484, 0xDFCD, 0x5485, 0x85F0, 0x5486, 0xC5D8,
+	0x5487, 0x85F1, 0x5488, 0x85F2, 0x5489, 0x85F3, 0x548A, 0x85F4,
+	0x548B, 0xD5A6, 0x548C, 0xBACD, 0x548D, 0x85F5, 0x548E, 0xBECC,
+	0x548F, 0xD3BD, 0x5490, 0xB8C0, 0x5491, 0x85F6, 0x5492, 0xD6E4,
+	0x5493, 0x85F7, 0x5494, 0xDFC7, 0x5495, 0xB9BE, 0x5496, 0xBFA7,
+	0x5497, 0x85F8, 0x5498, 0x85F9, 0x5499, 0xC1FC, 0x549A, 0xDFCB,
+	0x549B, 0xDFCC, 0x549C, 0x85FA, 0x549D, 0xDFD0, 0x549E, 0x85FB,
+	0x549F, 0x85FC, 0x54A0, 0x85FD, 0x54A1, 0x85FE, 0x54A2, 0x8640,
+	0x54A3, 0xDFDB, 0x54A4, 0xDFE5, 0x54A5, 0x8641, 0x54A6, 0xDFD7,
+	0x54A7, 0xDFD6, 0x54A8, 0xD7C9, 0x54A9, 0xDFE3, 0x54AA, 0xDFE4,
+	0x54AB, 0xE5EB, 0x54AC, 0xD2A7, 0x54AD, 0xDFD2, 0x54AE, 0x8642,
+	0x54AF, 0xBFA9, 0x54B0, 0x8643, 0x54B1, 0xD4DB, 0x54B2, 0x8644,
+	0x54B3, 0xBFC8, 0x54B4, 0xDFD4, 0x54B5, 0x8645, 0x54B6, 0x8646,
+	0x54B7, 0x8647, 0x54B8, 0xCFCC, 0x54B9, 0x8648, 0x54BA, 0x8649,
+	0x54BB, 0xDFDD, 0x54BC, 0x864A, 0x54BD, 0xD1CA, 0x54BE, 0x864B,
+	0x54BF, 0xDFDE, 0x54C0, 0xB0A7, 0x54C1, 0xC6B7, 0x54C2, 0xDFD3,
+	0x54C3, 0x864C, 0x54C4, 0xBAE5, 0x54C5, 0x864D, 0x54C6, 0xB6DF,
+	0x54C7, 0xCDDB, 0x54C8, 0xB9FE, 0x54C9, 0xD4D5, 0x54CA, 0x864E,
+	0x54CB, 0x864F, 0x54CC, 0xDFDF, 0x54CD, 0xCFEC, 0x54CE, 0xB0A5,
+	0x54CF, 0xDFE7, 0x54D0, 0xDFD1, 0x54D1, 0xD1C6, 0x54D2, 0xDFD5,
+	0x54D3, 0xDFD8, 0x54D4, 0xDFD9, 0x54D5, 0xDFDC, 0x54D6, 0x8650,
+	0x54D7, 0xBBA9, 0x54D8, 0x8651, 0x54D9, 0xDFE0, 0x54DA, 0xDFE1,
+	0x54DB, 0x8652, 0x54DC, 0xDFE2, 0x54DD, 0xDFE6, 0x54DE, 0xDFE8,
+	0x54DF, 0xD3B4, 0x54E0, 0x8653, 0x54E1, 0x8654, 0x54E2, 0x8655,
+	0x54E3, 0x8656, 0x54E4, 0x8657, 0x54E5, 0xB8E7, 0x54E6, 0xC5B6,
+	0x54E7, 0xDFEA, 0x54E8, 0xC9DA, 0x54E9, 0xC1A8, 0x54EA, 0xC4C4,
+	0x54EB, 0x8658, 0x54EC, 0x8659, 0x54ED, 0xBFDE, 0x54EE, 0xCFF8,
+	0x54EF, 0x865A, 0x54F0, 0x865B, 0x54F1, 0x865C, 0x54F2, 0xD5DC,
+	0x54F3, 0xDFEE, 0x54F4, 0x865D, 0x54F5, 0x865E, 0x54F6, 0x865F,
+	0x54F7, 0x8660, 0x54F8, 0x8661, 0x54F9, 0x8662, 0x54FA, 0xB2B8,
+	0x54FB, 0x8663, 0x54FC, 0xBADF, 0x54FD, 0xDFEC, 0x54FE, 0x8664,
+	0x54FF, 0xDBC1, 0x5500, 0x8665, 0x5501, 0xD1E4, 0x5502, 0x8666,
+	0x5503, 0x8667, 0x5504, 0x8668, 0x5505, 0x8669, 0x5506, 0xCBF4,
+	0x5507, 0xB4BD, 0x5508, 0x866A, 0x5509, 0xB0A6, 0x550A, 0x866B,
+	0x550B, 0x866C, 0x550C, 0x866D, 0x550D, 0x866E, 0x550E, 0x866F,
+	0x550F, 0xDFF1, 0x5510, 0xCCC6, 0x5511, 0xDFF2, 0x5512, 0x8670,
+	0x5513, 0x8671, 0x5514, 0xDFED, 0x5515, 0x8672, 0x5516, 0x8673,
+	0x5517, 0x8674, 0x5518, 0x8675, 0x5519, 0x8676, 0x551A, 0x8677,
+	0x551B, 0xDFE9, 0x551C, 0x8678, 0x551D, 0x8679, 0x551E, 0x867A,
+	0x551F, 0x867B, 0x5520, 0xDFEB, 0x5521, 0x867C, 0x5522, 0xDFEF,
+	0x5523, 0xDFF0, 0x5524, 0xBBBD, 0x5525, 0x867D, 0x5526, 0x867E,
+	0x5527, 0xDFF3, 0x5528, 0x8680, 0x5529, 0x8681, 0x552A, 0xDFF4,
+	0x552B, 0x8682, 0x552C, 0xBBA3, 0x552D, 0x8683, 0x552E, 0xCADB,
+	0x552F, 0xCEA8, 0x5530, 0xE0A7, 0x5531, 0xB3AA, 0x5532, 0x8684,
+	0x5533, 0xE0A6, 0x5534, 0x8685, 0x5535, 0x8686, 0x5536, 0x8687,
+	0x5537, 0xE0A1, 0x5538, 0x8688, 0x5539, 0x8689, 0x553A, 0x868A,
+	0x553B, 0x868B, 0x553C, 0xDFFE, 0x553D, 0x868C, 0x553E, 0xCDD9,
+	0x553F, 0xDFFC, 0x5540, 0x868D, 0x5541, 0xDFFA, 0x5542, 0x868E,
+	0x5543, 0xBFD0, 0x5544, 0xD7C4, 0x5545, 0x868F, 0x5546, 0xC9CC,
+	0x5547, 0x8690, 0x5548, 0x8691, 0x5549, 0xDFF8, 0x554A, 0xB0A1,
+	0x554B, 0x8692, 0x554C, 0x8693, 0x554D, 0x8694, 0x554E, 0x8695,
+	0x554F, 0x8696, 0x5550, 0xDFFD, 0x5551, 0x8697, 0x5552, 0x8698,
+	0x5553, 0x8699, 0x5554, 0x869A, 0x5555, 0xDFFB, 0x5556, 0xE0A2,
+	0x5557, 0x869B, 0x5558, 0x869C, 0x5559, 0x869D, 0x555A, 0x869E,
+	0x555B, 0x869F, 0x555C, 0xE0A8, 0x555D, 0x86A0, 0x555E, 0x86A1,
+	0x555F, 0x86A2, 0x5560, 0x86A3, 0x5561, 0xB7C8, 0x5562, 0x86A4,
+	0x5563, 0x86A5, 0x5564, 0xC6A1, 0x5565, 0xC9B6, 0x5566, 0xC0B2,
+	0x5567, 0xDFF5, 0x5568, 0x86A6, 0x5569, 0x86A7, 0x556A, 0xC5BE,
+	0x556B, 0x86A8, 0x556C, 0xD8C4, 0x556D, 0xDFF9, 0x556E, 0xC4F6,
+	0x556F, 0x86A9, 0x5570, 0x86AA, 0x5571, 0x86AB, 0x5572, 0x86AC,
+	0x5573, 0x86AD, 0x5574, 0x86AE, 0x5575, 0xE0A3, 0x5576, 0xE0A4,
+	0x5577, 0xE0A5, 0x5578, 0xD0A5, 0x5579, 0x86AF, 0x557A, 0x86B0,
+	0x557B, 0xE0B4, 0x557C, 0xCCE4, 0x557D, 0x86B1, 0x557E, 0xE0B1,
+	0x557F, 0x86B2, 0x5580, 0xBFA6, 0x5581, 0xE0AF, 0x5582, 0xCEB9,
+	0x5583, 0xE0AB, 0x5584, 0xC9C6, 0x5585, 0x86B3, 0x5586, 0x86B4,
+	0x5587, 0xC0AE, 0x5588, 0xE0AE, 0x5589, 0xBAED, 0x558A, 0xBAB0,
+	0x558B, 0xE0A9, 0x558C, 0x86B5, 0x558D, 0x86B6, 0x558E, 0x86B7,
+	0x558F, 0xDFF6, 0x5590, 0x86B8, 0x5591, 0xE0B3, 0x5592, 0x86B9,
+	0x5593, 0x86BA, 0x5594, 0xE0B8, 0x5595, 0x86BB, 0x5596, 0x86BC,
+	0x5597, 0x86BD, 0x5598, 0xB4AD, 0x5599, 0xE0B9, 0x559A, 0x86BE,
+	0x559B, 0x86BF, 0x559C, 0xCFB2, 0x559D, 0xBAC8, 0x559E, 0x86C0,
+	0x559F, 0xE0B0, 0x55A0, 0x86C1, 0x55A1, 0x86C2, 0x55A2, 0x86C3,
+	0x55A3, 0x86C4, 0x55A4, 0x86C5, 0x55A5, 0x86C6, 0x55A6, 0x86C7,
+	0x55A7, 0xD0FA, 0x55A8, 0x86C8, 0x55A9, 0x86C9, 0x55AA, 0x86CA,
+	0x55AB, 0x86CB, 0x55AC, 0x86CC, 0x55AD, 0x86CD, 0x55AE, 0x86CE,
+	0x55AF, 0x86CF, 0x55B0, 0x86D0, 0x55B1, 0xE0AC, 0x55B2, 0x86D1,
+	0x55B3, 0xD4FB, 0x55B4, 0x86D2, 0x55B5, 0xDFF7, 0x55B6, 0x86D3,
+	0x55B7, 0xC5E7, 0x55B8, 0x86D4, 0x55B9, 0xE0AD, 0x55BA, 0x86D5,
+	0x55BB, 0xD3F7, 0x55BC, 0x86D6, 0x55BD, 0xE0B6, 0x55BE, 0xE0B7,
+	0x55BF, 0x86D7, 0x55C0, 0x86D8, 0x55C1, 0x86D9, 0x55C2, 0x86DA,
+	0x55C3, 0x86DB, 0x55C4, 0xE0C4, 0x55C5, 0xD0E1, 0x55C6, 0x86DC,
+	0x55C7, 0x86DD, 0x55C8, 0x86DE, 0x55C9, 0xE0BC, 0x55CA, 0x86DF,
+	0x55CB, 0x86E0, 0x55CC, 0xE0C9, 0x55CD, 0xE0CA, 0x55CE, 0x86E1,
+	0x55CF, 0x86E2, 0x55D0, 0x86E3, 0x55D1, 0xE0BE, 0x55D2, 0xE0AA,
+	0x55D3, 0xC9A4, 0x55D4, 0xE0C1, 0x55D5, 0x86E4, 0x55D6, 0xE0B2,
+	0x55D7, 0x86E5, 0x55D8, 0x86E6, 0x55D9, 0x86E7, 0x55DA, 0x86E8,
+	0x55DB, 0x86E9, 0x55DC, 0xCAC8, 0x55DD, 0xE0C3, 0x55DE, 0x86EA,
+	0x55DF, 0xE0B5, 0x55E0, 0x86EB, 0x55E1, 0xCECB, 0x55E2, 0x86EC,
+	0x55E3, 0xCBC3, 0x55E4, 0xE0CD, 0x55E5, 0xE0C6, 0x55E6, 0xE0C2,
+	0x55E7, 0x86ED, 0x55E8, 0xE0CB, 0x55E9, 0x86EE, 0x55EA, 0xE0BA,
+	0x55EB, 0xE0BF, 0x55EC, 0xE0C0, 0x55ED, 0x86EF, 0x55EE, 0x86F0,
+	0x55EF, 0xE0C5, 0x55F0, 0x86F1, 0x55F1, 0x86F2, 0x55F2, 0xE0C7,
+	0x55F3, 0xE0C8, 0x55F4, 0x86F3, 0x55F5, 0xE0CC, 0x55F6, 0x86F4,
+	0x55F7, 0xE0BB, 0x55F8, 0x86F5, 0x55F9, 0x86F6, 0x55FA, 0x86F7,
+	0x55FB, 0x86F8, 0x55FC, 0x86F9, 0x55FD, 0xCBD4, 0x55FE, 0xE0D5,
+	0x55FF, 0x86FA, 0x5600, 0xE0D6, 0x5601, 0xE0D2, 0x5602, 0x86FB,
+	0x5603, 0x86FC, 0x5604, 0x86FD, 0x5605, 0x86FE, 0x5606, 0x8740,
+	0x5607, 0x8741, 0x5608, 0xE0D0, 0x5609, 0xBCCE, 0x560A, 0x8742,
+	0x560B, 0x8743, 0x560C, 0xE0D1, 0x560D, 0x8744, 0x560E, 0xB8C2,
+	0x560F, 0xD8C5, 0x5610, 0x8745, 0x5611, 0x8746, 0x5612, 0x8747,
+	0x5613, 0x8748, 0x5614, 0x8749, 0x5615, 0x874A, 0x5616, 0x874B,
+	0x5617, 0x874C, 0x5618, 0xD0EA, 0x5619, 0x874D, 0x561A, 0x874E,
+	0x561B, 0xC2EF, 0x561C, 0x874F, 0x561D, 0x8750, 0x561E, 0xE0CF,
+	0x561F, 0xE0BD, 0x5620, 0x8751, 0x5621, 0x8752, 0x5622, 0x8753,
+	0x5623, 0xE0D4, 0x5624, 0xE0D3, 0x5625, 0x8754, 0x5626, 0x8755,
+	0x5627, 0xE0D7, 0x5628, 0x8756, 0x5629, 0x8757, 0x562A, 0x8758,
+	0x562B, 0x8759, 0x562C, 0xE0DC, 0x562D, 0xE0D8, 0x562E, 0x875A,
+	0x562F, 0x875B, 0x5630, 0x875C, 0x5631, 0xD6F6, 0x5632, 0xB3B0,
+	0x5633, 0x875D, 0x5634, 0xD7EC, 0x5635, 0x875E, 0x5636, 0xCBBB,
+	0x5637, 0x875F, 0x5638, 0x8760, 0x5639, 0xE0DA, 0x563A, 0x8761,
+	0x563B, 0xCEFB, 0x563C, 0x8762, 0x563D, 0x8763, 0x563E, 0x8764,
+	0x563F, 0xBAD9, 0x5640, 0x8765, 0x5641, 0x8766, 0x5642, 0x8767,
+	0x5643, 0x8768, 0x5644, 0x8769, 0x5645, 0x876A, 0x5646, 0x876B,
+	0x5647, 0x876C, 0x5648, 0x876D, 0x5649, 0x876E, 0x564A, 0x876F,
+	0x564B, 0x8770, 0x564C, 0xE0E1, 0x564D, 0xE0DD, 0x564E, 0xD2AD,
+	0x564F, 0x8771, 0x5650, 0x8772, 0x5651, 0x8773, 0x5652, 0x8774,
+	0x5653, 0x8775, 0x5654, 0xE0E2, 0x5655, 0x8776, 0x5656, 0x8777,
+	0x5657, 0xE0DB, 0x5658, 0xE0D9, 0x5659, 0xE0DF, 0x565A, 0x8778,
+	0x565B, 0x8779, 0x565C, 0xE0E0, 0x565D, 0x877A, 0x565E, 0x877B,
+	0x565F, 0x877C, 0x5660, 0x877D, 0x5661, 0x877E, 0x5662, 0xE0DE,
+	0x5663, 0x8780, 0x5664, 0xE0E4, 0x5665, 0x8781, 0x5666, 0x8782,
+	0x5667, 0x8783, 0x5668, 0xC6F7, 0x5669, 0xD8AC, 0x566A, 0xD4EB,
+	0x566B, 0xE0E6, 0x566C, 0xCAC9, 0x566D, 0x8784, 0x566E, 0x8785,
+	0x566F, 0x8786, 0x5670, 0x8787, 0x5671, 0xE0E5, 0x5672, 0x8788,
+	0x5673, 0x8789, 0x5674, 0x878A, 0x5675, 0x878B, 0x5676, 0xB8C1,
+	0x5677, 0x878C, 0x5678, 0x878D, 0x5679, 0x878E, 0x567A, 0x878F,
+	0x567B, 0xE0E7, 0x567C, 0xE0E8, 0x567D, 0x8790, 0x567E, 0x8791,
+	0x567F, 0x8792, 0x5680, 0x8793, 0x5681, 0x8794, 0x5682, 0x8795,
+	0x5683, 0x8796, 0x5684, 0x8797, 0x5685, 0xE0E9, 0x5686, 0xE0E3,
+	0x5687, 0x8798, 0x5688, 0x8799, 0x5689, 0x879A, 0x568A, 0x879B,
+	0x568B, 0x879C, 0x568C, 0x879D, 0x568D, 0x879E, 0x568E, 0xBABF,
+	0x568F, 0xCCE7, 0x5690, 0x879F, 0x5691, 0x87A0, 0x5692, 0x87A1,
+	0x5693, 0xE0EA, 0x5694, 0x87A2, 0x5695, 0x87A3, 0x5696, 0x87A4,
+	0x5697, 0x87A5, 0x5698, 0x87A6, 0x5699, 0x87A7, 0x569A, 0x87A8,
+	0x569B, 0x87A9, 0x569C, 0x87AA, 0x569D, 0x87AB, 0x569E, 0x87AC,
+	0x569F, 0x87AD, 0x56A0, 0x87AE, 0x56A1, 0x87AF, 0x56A2, 0x87B0,
+	0x56A3, 0xCFF9, 0x56A4, 0x87B1, 0x56A5, 0x87B2, 0x56A6, 0x87B3,
+	0x56A7, 0x87B4, 0x56A8, 0x87B5, 0x56A9, 0x87B6, 0x56AA, 0x87B7,
+	0x56AB, 0x87B8, 0x56AC, 0x87B9, 0x56AD, 0x87BA, 0x56AE, 0x87BB,
+	0x56AF, 0xE0EB, 0x56B0, 0x87BC, 0x56B1, 0x87BD, 0x56B2, 0x87BE,
+	0x56B3, 0x87BF, 0x56B4, 0x87C0, 0x56B5, 0x87C1, 0x56B6, 0x87C2,
+	0x56B7, 0xC8C2, 0x56B8, 0x87C3, 0x56B9, 0x87C4, 0x56BA, 0x87C5,
+	0x56BB, 0x87C6, 0x56BC, 0xBDC0, 0x56BD, 0x87C7, 0x56BE, 0x87C8,
+	0x56BF, 0x87C9, 0x56C0, 0x87CA, 0x56C1, 0x87CB, 0x56C2, 0x87CC,
+	0x56C3, 0x87CD, 0x56C4, 0x87CE, 0x56C5, 0x87CF, 0x56C6, 0x87D0,
+	0x56C7, 0x87D1, 0x56C8, 0x87D2, 0x56C9, 0x87D3, 0x56CA, 0xC4D2,
+	0x56CB, 0x87D4, 0x56CC, 0x87D5, 0x56CD, 0x87D6, 0x56CE, 0x87D7,
+	0x56CF, 0x87D8, 0x56D0, 0x87D9, 0x56D1, 0x87DA, 0x56D2, 0x87DB,
+	0x56D3, 0x87DC, 0x56D4, 0xE0EC, 0x56D5, 0x87DD, 0x56D6, 0x87DE,
+	0x56D7, 0xE0ED, 0x56D8, 0x87DF, 0x56D9, 0x87E0, 0x56DA, 0xC7F4,
+	0x56DB, 0xCBC4, 0x56DC, 0x87E1, 0x56DD, 0xE0EE, 0x56DE, 0xBBD8,
+	0x56DF, 0xD8B6, 0x56E0, 0xD2F2, 0x56E1, 0xE0EF, 0x56E2, 0xCDC5,
+	0x56E3, 0x87E2, 0x56E4, 0xB6DA, 0x56E5, 0x87E3, 0x56E6, 0x87E4,
+	0x56E7, 0x87E5, 0x56E8, 0x87E6, 0x56E9, 0x87E7, 0x56EA, 0x87E8,
+	0x56EB, 0xE0F1, 0x56EC, 0x87E9, 0x56ED, 0xD4B0, 0x56EE, 0x87EA,
+	0x56EF, 0x87EB, 0x56F0, 0xC0A7, 0x56F1, 0xB4D1, 0x56F2, 0x87EC,
+	0x56F3, 0x87ED, 0x56F4, 0xCEA7, 0x56F5, 0xE0F0, 0x56F6, 0x87EE,
+	0x56F7, 0x87EF, 0x56F8, 0x87F0, 0x56F9, 0xE0F2, 0x56FA, 0xB9CC,
+	0x56FB, 0x87F1, 0x56FC, 0x87F2, 0x56FD, 0xB9FA, 0x56FE, 0xCDBC,
+	0x56FF, 0xE0F3, 0x5700, 0x87F3, 0x5701, 0x87F4, 0x5702, 0x87F5,
+	0x5703, 0xC6D4, 0x5704, 0xE0F4, 0x5705, 0x87F6, 0x5706, 0xD4B2,
+	0x5707, 0x87F7, 0x5708, 0xC8A6, 0x5709, 0xE0F6, 0x570A, 0xE0F5,
+	0x570B, 0x87F8, 0x570C, 0x87F9, 0x570D, 0x87FA, 0x570E, 0x87FB,
+	0x570F, 0x87FC, 0x5710, 0x87FD, 0x5711, 0x87FE, 0x5712, 0x8840,
+	0x5713, 0x8841, 0x5714, 0x8842, 0x5715, 0x8843, 0x5716, 0x8844,
+	0x5717, 0x8845, 0x5718, 0x8846, 0x5719, 0x8847, 0x571A, 0x8848,
+	0x571B, 0x8849, 0x571C, 0xE0F7, 0x571D, 0x884A, 0x571E, 0x884B,
+	0x571F, 0xCDC1, 0x5720, 0x884C, 0x5721, 0x884D, 0x5722, 0x884E,
+	0x5723, 0xCAA5, 0x5724, 0x884F, 0x5725, 0x8850, 0x5726, 0x8851,
+	0x5727, 0x8852, 0x5728, 0xD4DA, 0x5729, 0xDBD7, 0x572A, 0xDBD9,
+	0x572B, 0x8853, 0x572C, 0xDBD8, 0x572D, 0xB9E7, 0x572E, 0xDBDC,
+	0x572F, 0xDBDD, 0x5730, 0xB5D8, 0x5731, 0x8854, 0x5732, 0x8855,
+	0x5733, 0xDBDA, 0x5734, 0x8856, 0x5735, 0x8857, 0x5736, 0x8858,
+	0x5737, 0x8859, 0x5738, 0x885A, 0x5739, 0xDBDB, 0x573A, 0xB3A1,
+	0x573B, 0xDBDF, 0x573C, 0x885B, 0x573D, 0x885C, 0x573E, 0xBBF8,
+	0x573F, 0x885D, 0x5740, 0xD6B7, 0x5741, 0x885E, 0x5742, 0xDBE0,
+	0x5743, 0x885F, 0x5744, 0x8860, 0x5745, 0x8861, 0x5746, 0x8862,
+	0x5747, 0xBEF9, 0x5748, 0x8863, 0x5749, 0x8864, 0x574A, 0xB7BB,
+	0x574B, 0x8865, 0x574C, 0xDBD0, 0x574D, 0xCCAE, 0x574E, 0xBFB2,
+	0x574F, 0xBBB5, 0x5750, 0xD7F8, 0x5751, 0xBFD3, 0x5752, 0x8866,
+	0x5753, 0x8867, 0x5754, 0x8868, 0x5755, 0x8869, 0x5756, 0x886A,
+	0x5757, 0xBFE9, 0x5758, 0x886B, 0x5759, 0x886C, 0x575A, 0xBCE1,
+	0x575B, 0xCCB3, 0x575C, 0xDBDE, 0x575D, 0xB0D3, 0x575E, 0xCEEB,
+	0x575F, 0xB7D8, 0x5760, 0xD7B9, 0x5761, 0xC6C2, 0x5762, 0x886D,
+	0x5763, 0x886E, 0x5764, 0xC0A4, 0x5765, 0x886F, 0x5766, 0xCCB9,
+	0x5767, 0x8870, 0x5768, 0xDBE7, 0x5769, 0xDBE1, 0x576A, 0xC6BA,
+	0x576B, 0xDBE3, 0x576C, 0x8871, 0x576D, 0xDBE8, 0x576E, 0x8872,
+	0x576F, 0xC5F7, 0x5770, 0x8873, 0x5771, 0x8874, 0x5772, 0x8875,
+	0x5773, 0xDBEA, 0x5774, 0x8876, 0x5775, 0x8877, 0x5776, 0xDBE9,
+	0x5777, 0xBFC0, 0x5778, 0x8878, 0x5779, 0x8879, 0x577A, 0x887A,
+	0x577B, 0xDBE6, 0x577C, 0xDBE5, 0x577D, 0x887B, 0x577E, 0x887C,
+	0x577F, 0x887D, 0x5780, 0x887E, 0x5781, 0x8880, 0x5782, 0xB4B9,
+	0x5783, 0xC0AC, 0x5784, 0xC2A2, 0x5785, 0xDBE2, 0x5786, 0xDBE4,
+	0x5787, 0x8881, 0x5788, 0x8882, 0x5789, 0x8883, 0x578A, 0x8884,
+	0x578B, 0xD0CD, 0x578C, 0xDBED, 0x578D, 0x8885, 0x578E, 0x8886,
+	0x578F, 0x8887, 0x5790, 0x8888, 0x5791, 0x8889, 0x5792, 0xC0DD,
+	0x5793, 0xDBF2, 0x5794, 0x888A, 0x5795, 0x888B, 0x5796, 0x888C,
+	0x5797, 0x888D, 0x5798, 0x888E, 0x5799, 0x888F, 0x579A, 0x8890,
+	0x579B, 0xB6E2, 0x579C, 0x8891, 0x579D, 0x8892, 0x579E, 0x8893,
+	0x579F, 0x8894, 0x57A0, 0xDBF3, 0x57A1, 0xDBD2, 0x57A2, 0xB9B8,
+	0x57A3, 0xD4AB, 0x57A4, 0xDBEC, 0x57A5, 0x8895, 0x57A6, 0xBFD1,
+	0x57A7, 0xDBF0, 0x57A8, 0x8896, 0x57A9, 0xDBD1, 0x57AA, 0x8897,
+	0x57AB, 0xB5E6, 0x57AC, 0x8898, 0x57AD, 0xDBEB, 0x57AE, 0xBFE5,
+	0x57AF, 0x8899, 0x57B0, 0x889A, 0x57B1, 0x889B, 0x57B2, 0xDBEE,
+	0x57B3, 0x889C, 0x57B4, 0xDBF1, 0x57B5, 0x889D, 0x57B6, 0x889E,
+	0x57B7, 0x889F, 0x57B8, 0xDBF9, 0x57B9, 0x88A0, 0x57BA, 0x88A1,
+	0x57BB, 0x88A2, 0x57BC, 0x88A3, 0x57BD, 0x88A4, 0x57BE, 0x88A5,
+	0x57BF, 0x88A6, 0x57C0, 0x88A7, 0x57C1, 0x88A8, 0x57C2, 0xB9A1,
+	0x57C3, 0xB0A3, 0x57C4, 0x88A9, 0x57C5, 0x88AA, 0x57C6, 0x88AB,
+	0x57C7, 0x88AC, 0x57C8, 0x88AD, 0x57C9, 0x88AE, 0x57CA, 0x88AF,
+	0x57CB, 0xC2F1, 0x57CC, 0x88B0, 0x57CD, 0x88B1, 0x57CE, 0xB3C7,
+	0x57CF, 0xDBEF, 0x57D0, 0x88B2, 0x57D1, 0x88B3, 0x57D2, 0xDBF8,
+	0x57D3, 0x88B4, 0x57D4, 0xC6D2, 0x57D5, 0xDBF4, 0x57D6, 0x88B5,
+	0x57D7, 0x88B6, 0x57D8, 0xDBF5, 0x57D9, 0xDBF7, 0x57DA, 0xDBF6,
+	0x57DB, 0x88B7, 0x57DC, 0x88B8, 0x57DD, 0xDBFE, 0x57DE, 0x88B9,
+	0x57DF, 0xD3F2, 0x57E0, 0xB2BA, 0x57E1, 0x88BA, 0x57E2, 0x88BB,
+	0x57E3, 0x88BC, 0x57E4, 0xDBFD, 0x57E5, 0x88BD, 0x57E6, 0x88BE,
+	0x57E7, 0x88BF, 0x57E8, 0x88C0, 0x57E9, 0x88C1, 0x57EA, 0x88C2,
+	0x57EB, 0x88C3, 0x57EC, 0x88C4, 0x57ED, 0xDCA4, 0x57EE, 0x88C5,
+	0x57EF, 0xDBFB, 0x57F0, 0x88C6, 0x57F1, 0x88C7, 0x57F2, 0x88C8,
+	0x57F3, 0x88C9, 0x57F4, 0xDBFA, 0x57F5, 0x88CA, 0x57F6, 0x88CB,
+	0x57F7, 0x88CC, 0x57F8, 0xDBFC, 0x57F9, 0xC5E0, 0x57FA, 0xBBF9,
+	0x57FB, 0x88CD, 0x57FC, 0x88CE, 0x57FD, 0xDCA3, 0x57FE, 0x88CF,
+	0x57FF, 0x88D0, 0x5800, 0xDCA5, 0x5801, 0x88D1, 0x5802, 0xCCC3,
+	0x5803, 0x88D2, 0x5804, 0x88D3, 0x5805, 0x88D4, 0x5806, 0xB6D1,
+	0x5807, 0xDDC0, 0x5808, 0x88D5, 0x5809, 0x88D6, 0x580A, 0x88D7,
+	0x580B, 0xDCA1, 0x580C, 0x88D8, 0x580D, 0xDCA2, 0x580E, 0x88D9,
+	0x580F, 0x88DA, 0x5810, 0x88DB, 0x5811, 0xC7B5, 0x5812, 0x88DC,
+	0x5813, 0x88DD, 0x5814, 0x88DE, 0x5815, 0xB6E9, 0x5816, 0x88DF,
+	0x5817, 0x88E0, 0x5818, 0x88E1, 0x5819, 0xDCA7, 0x581A, 0x88E2,
+	0x581B, 0x88E3, 0x581C, 0x88E4, 0x581D, 0x88E5, 0x581E, 0xDCA6,
+	0x581F, 0x88E6, 0x5820, 0xDCA9, 0x5821, 0xB1A4, 0x5822, 0x88E7,
+	0x5823, 0x88E8, 0x5824, 0xB5CC, 0x5825, 0x88E9, 0x5826, 0x88EA,
+	0x5827, 0x88EB, 0x5828, 0x88EC, 0x5829, 0x88ED, 0x582A, 0xBFB0,
+	0x582B, 0x88EE, 0x582C, 0x88EF, 0x582D, 0x88F0, 0x582E, 0x88F1,
+	0x582F, 0x88F2, 0x5830, 0xD1DF, 0x5831, 0x88F3, 0x5832, 0x88F4,
+	0x5833, 0x88F5, 0x5834, 0x88F6, 0x5835, 0xB6C2, 0x5836, 0x88F7,
+	0x5837, 0x88F8, 0x5838, 0x88F9, 0x5839, 0x88FA, 0x583A, 0x88FB,
+	0x583B, 0x88FC, 0x583C, 0x88FD, 0x583D, 0x88FE, 0x583E, 0x8940,
+	0x583F, 0x8941, 0x5840, 0x8942, 0x5841, 0x8943, 0x5842, 0x8944,
+	0x5843, 0x8945, 0x5844, 0xDCA8, 0x5845, 0x8946, 0x5846, 0x8947,
+	0x5847, 0x8948, 0x5848, 0x8949, 0x5849, 0x894A, 0x584A, 0x894B,
+	0x584B, 0x894C, 0x584C, 0xCBFA, 0x584D, 0xEBF3, 0x584E, 0x894D,
+	0x584F, 0x894E, 0x5850, 0x894F, 0x5851, 0xCBDC, 0x5852, 0x8950,
+	0x5853, 0x8951, 0x5854, 0xCBFE, 0x5855, 0x8952, 0x5856, 0x8953,
+	0x5857, 0x8954, 0x5858, 0xCCC1, 0x5859, 0x8955, 0x585A, 0x8956,
+	0x585B, 0x8957, 0x585C, 0x8958, 0x585D, 0x8959, 0x585E, 0xC8FB,
+	0x585F, 0x895A, 0x5860, 0x895B, 0x5861, 0x895C, 0x5862, 0x895D,
+	0x5863, 0x895E, 0x5864, 0x895F, 0x5865, 0xDCAA, 0x5866, 0x8960,
+	0x5867, 0x8961, 0x5868, 0x8962, 0x5869, 0x8963, 0x586A, 0x8964,
+	0x586B, 0xCCEE, 0x586C, 0xDCAB, 0x586D, 0x8965, 0x586E, 0x8966,
+	0x586F, 0x8967, 0x5870, 0x8968, 0x5871, 0x8969, 0x5872, 0x896A,
+	0x5873, 0x896B, 0x5874, 0x896C, 0x5875, 0x896D, 0x5876, 0x896E,
+	0x5877, 0x896F, 0x5878, 0x8970, 0x5879, 0x8971, 0x587A, 0x8972,
+	0x587B, 0x8973, 0x587C, 0x8974, 0x587D, 0x8975, 0x587E, 0xDBD3,
+	0x587F, 0x8976, 0x5880, 0xDCAF, 0x5881, 0xDCAC, 0x5882, 0x8977,
+	0x5883, 0xBEB3, 0x5884, 0x8978, 0x5885, 0xCAFB, 0x5886, 0x8979,
+	0x5887, 0x897A, 0x5888, 0x897B, 0x5889, 0xDCAD, 0x588A, 0x897C,
+	0x588B, 0x897D, 0x588C, 0x897E, 0x588D, 0x8980, 0x588E, 0x8981,
+	0x588F, 0x8982, 0x5890, 0x8983, 0x5891, 0x8984, 0x5892, 0xC9CA,
+	0x5893, 0xC4B9, 0x5894, 0x8985, 0x5895, 0x8986, 0x5896, 0x8987,
+	0x5897, 0x8988, 0x5898, 0x8989, 0x5899, 0xC7BD, 0x589A, 0xDCAE,
+	0x589B, 0x898A, 0x589C, 0x898B, 0x589D, 0x898C, 0x589E, 0xD4F6,
+	0x589F, 0xD0E6, 0x58A0, 0x898D, 0x58A1, 0x898E, 0x58A2, 0x898F,
+	0x58A3, 0x8990, 0x58A4, 0x8991, 0x58A5, 0x8992, 0x58A6, 0x8993,
+	0x58A7, 0x8994, 0x58A8, 0xC4AB, 0x58A9, 0xB6D5, 0x58AA, 0x8995,
+	0x58AB, 0x8996, 0x58AC, 0x8997, 0x58AD, 0x8998, 0x58AE, 0x8999,
+	0x58AF, 0x899A, 0x58B0, 0x899B, 0x58B1, 0x899C, 0x58B2, 0x899D,
+	0x58B3, 0x899E, 0x58B4, 0x899F, 0x58B5, 0x89A0, 0x58B6, 0x89A1,
+	0x58B7, 0x89A2, 0x58B8, 0x89A3, 0x58B9, 0x89A4, 0x58BA, 0x89A5,
+	0x58BB, 0x89A6, 0x58BC, 0xDBD4, 0x58BD, 0x89A7, 0x58BE, 0x89A8,
+	0x58BF, 0x89A9, 0x58C0, 0x89AA, 0x58C1, 0xB1DA, 0x58C2, 0x89AB,
+	0x58C3, 0x89AC, 0x58C4, 0x89AD, 0x58C5, 0xDBD5, 0x58C6, 0x89AE,
+	0x58C7, 0x89AF, 0x58C8, 0x89B0, 0x58C9, 0x89B1, 0x58CA, 0x89B2,
+	0x58CB, 0x89B3, 0x58CC, 0x89B4, 0x58CD, 0x89B5, 0x58CE, 0x89B6,
+	0x58CF, 0x89B7, 0x58D0, 0x89B8, 0x58D1, 0xDBD6, 0x58D2, 0x89B9,
+	0x58D3, 0x89BA, 0x58D4, 0x89BB, 0x58D5, 0xBABE, 0x58D6, 0x89BC,
+	0x58D7, 0x89BD, 0x58D8, 0x89BE, 0x58D9, 0x89BF, 0x58DA, 0x89C0,
+	0x58DB, 0x89C1, 0x58DC, 0x89C2, 0x58DD, 0x89C3, 0x58DE, 0x89C4,
+	0x58DF, 0x89C5, 0x58E0, 0x89C6, 0x58E1, 0x89C7, 0x58E2, 0x89C8,
+	0x58E3, 0x89C9, 0x58E4, 0xC8C0, 0x58E5, 0x89CA, 0x58E6, 0x89CB,
+	0x58E7, 0x89CC, 0x58E8, 0x89CD, 0x58E9, 0x89CE, 0x58EA, 0x89CF,
+	0x58EB, 0xCABF, 0x58EC, 0xC8C9, 0x58ED, 0x89D0, 0x58EE, 0xD7B3,
+	0x58EF, 0x89D1, 0x58F0, 0xC9F9, 0x58F1, 0x89D2, 0x58F2, 0x89D3,
+	0x58F3, 0xBFC7, 0x58F4, 0x89D4, 0x58F5, 0x89D5, 0x58F6, 0xBAF8,
+	0x58F7, 0x89D6, 0x58F8, 0x89D7, 0x58F9, 0xD2BC, 0x58FA, 0x89D8,
+	0x58FB, 0x89D9, 0x58FC, 0x89DA, 0x58FD, 0x89DB, 0x58FE, 0x89DC,
+	0x58FF, 0x89DD, 0x5900, 0x89DE, 0x5901, 0x89DF, 0x5902, 0xE2BA,
+	0x5903, 0x89E0, 0x5904, 0xB4A6, 0x5905, 0x89E1, 0x5906, 0x89E2,
+	0x5907, 0xB1B8, 0x5908, 0x89E3, 0x5909, 0x89E4, 0x590A, 0x89E5,
+	0x590B, 0x89E6, 0x590C, 0x89E7, 0x590D, 0xB8B4, 0x590E, 0x89E8,
+	0x590F, 0xCFC4, 0x5910, 0x89E9, 0x5911, 0x89EA, 0x5912, 0x89EB,
+	0x5913, 0x89EC, 0x5914, 0xD9E7, 0x5915, 0xCFA6, 0x5916, 0xCDE2,
+	0x5917, 0x89ED, 0x5918, 0x89EE, 0x5919, 0xD9ED, 0x591A, 0xB6E0,
+	0x591B, 0x89EF, 0x591C, 0xD2B9, 0x591D, 0x89F0, 0x591E, 0x89F1,
+	0x591F, 0xB9BB, 0x5920, 0x89F2, 0x5921, 0x89F3, 0x5922, 0x89F4,
+	0x5923, 0x89F5, 0x5924, 0xE2B9, 0x5925, 0xE2B7, 0x5926, 0x89F6,
+	0x5927, 0xB4F3, 0x5928, 0x89F7, 0x5929, 0xCCEC, 0x592A, 0xCCAB,
+	0x592B, 0xB7F2, 0x592C, 0x89F8, 0x592D, 0xD8B2, 0x592E, 0xD1EB,
+	0x592F, 0xBABB, 0x5930, 0x89F9, 0x5931, 0xCAA7, 0x5932, 0x89FA,
+	0x5933, 0x89FB, 0x5934, 0xCDB7, 0x5935, 0x89FC, 0x5936, 0x89FD,
+	0x5937, 0xD2C4, 0x5938, 0xBFE4, 0x5939, 0xBCD0, 0x593A, 0xB6E1,
+	0x593B, 0x89FE, 0x593C, 0xDEC5, 0x593D, 0x8A40, 0x593E, 0x8A41,
+	0x593F, 0x8A42, 0x5940, 0x8A43, 0x5941, 0xDEC6, 0x5942, 0xDBBC,
+	0x5943, 0x8A44, 0x5944, 0xD1D9, 0x5945, 0x8A45, 0x5946, 0x8A46,
+	0x5947, 0xC6E6, 0x5948, 0xC4CE, 0x5949, 0xB7EE, 0x594A, 0x8A47,
+	0x594B, 0xB7DC, 0x594C, 0x8A48, 0x594D, 0x8A49, 0x594E, 0xBFFC,
+	0x594F, 0xD7E0, 0x5950, 0x8A4A, 0x5951, 0xC6F5, 0x5952, 0x8A4B,
+	0x5953, 0x8A4C, 0x5954, 0xB1BC, 0x5955, 0xDEC8, 0x5956, 0xBDB1,
+	0x5957, 0xCCD7, 0x5958, 0xDECA, 0x5959, 0x8A4D, 0x595A, 0xDEC9,
+	0x595B, 0x8A4E, 0x595C, 0x8A4F, 0x595D, 0x8A50, 0x595E, 0x8A51,
+	0x595F, 0x8A52, 0x5960, 0xB5EC, 0x5961, 0x8A53, 0x5962, 0xC9DD,
+	0x5963, 0x8A54, 0x5964, 0x8A55, 0x5965, 0xB0C2, 0x5966, 0x8A56,
+	0x5967, 0x8A57, 0x5968, 0x8A58, 0x5969, 0x8A59, 0x596A, 0x8A5A,
+	0x596B, 0x8A5B, 0x596C, 0x8A5C, 0x596D, 0x8A5D, 0x596E, 0x8A5E,
+	0x596F, 0x8A5F, 0x5970, 0x8A60, 0x5971, 0x8A61, 0x5972, 0x8A62,
+	0x5973, 0xC5AE, 0x5974, 0xC5AB, 0x5975, 0x8A63, 0x5976, 0xC4CC,
+	0x5977, 0x8A64, 0x5978, 0xBCE9, 0x5979, 0xCBFD, 0x597A, 0x8A65,
+	0x597B, 0x8A66, 0x597C, 0x8A67, 0x597D, 0xBAC3, 0x597E, 0x8A68,
+	0x597F, 0x8A69, 0x5980, 0x8A6A, 0x5981, 0xE5F9, 0x5982, 0xC8E7,
+	0x5983, 0xE5FA, 0x5984, 0xCDFD, 0x5985, 0x8A6B, 0x5986, 0xD7B1,
+	0x5987, 0xB8BE, 0x5988, 0xC2E8, 0x5989, 0x8A6C, 0x598A, 0xC8D1,
+	0x598B, 0x8A6D, 0x598C, 0x8A6E, 0x598D, 0xE5FB, 0x598E, 0x8A6F,
+	0x598F, 0x8A70, 0x5990, 0x8A71, 0x5991, 0x8A72, 0x5992, 0xB6CA,
+	0x5993, 0xBCCB, 0x5994, 0x8A73, 0x5995, 0x8A74, 0x5996, 0xD1FD,
+	0x5997, 0xE6A1, 0x5998, 0x8A75, 0x5999, 0xC3EE, 0x599A, 0x8A76,
+	0x599B, 0x8A77, 0x599C, 0x8A78, 0x599D, 0x8A79, 0x599E, 0xE6A4,
+	0x599F, 0x8A7A, 0x59A0, 0x8A7B, 0x59A1, 0x8A7C, 0x59A2, 0x8A7D,
+	0x59A3, 0xE5FE, 0x59A4, 0xE6A5, 0x59A5, 0xCDD7, 0x59A6, 0x8A7E,
+	0x59A7, 0x8A80, 0x59A8, 0xB7C1, 0x59A9, 0xE5FC, 0x59AA, 0xE5FD,
+	0x59AB, 0xE6A3, 0x59AC, 0x8A81, 0x59AD, 0x8A82, 0x59AE, 0xC4DD,
+	0x59AF, 0xE6A8, 0x59B0, 0x8A83, 0x59B1, 0x8A84, 0x59B2, 0xE6A7,
+	0x59B3, 0x8A85, 0x59B4, 0x8A86, 0x59B5, 0x8A87, 0x59B6, 0x8A88,
+	0x59B7, 0x8A89, 0x59B8, 0x8A8A, 0x59B9, 0xC3C3, 0x59BA, 0x8A8B,
+	0x59BB, 0xC6DE, 0x59BC, 0x8A8C, 0x59BD, 0x8A8D, 0x59BE, 0xE6AA,
+	0x59BF, 0x8A8E, 0x59C0, 0x8A8F, 0x59C1, 0x8A90, 0x59C2, 0x8A91,
+	0x59C3, 0x8A92, 0x59C4, 0x8A93, 0x59C5, 0x8A94, 0x59C6, 0xC4B7,
+	0x59C7, 0x8A95, 0x59C8, 0x8A96, 0x59C9, 0x8A97, 0x59CA, 0xE6A2,
+	0x59CB, 0xCABC, 0x59CC, 0x8A98, 0x59CD, 0x8A99, 0x59CE, 0x8A9A,
+	0x59CF, 0x8A9B, 0x59D0, 0xBDE3, 0x59D1, 0xB9C3, 0x59D2, 0xE6A6,
+	0x59D3, 0xD0D5, 0x59D4, 0xCEAF, 0x59D5, 0x8A9C, 0x59D6, 0x8A9D,
+	0x59D7, 0xE6A9, 0x59D8, 0xE6B0, 0x59D9, 0x8A9E, 0x59DA, 0xD2A6,
+	0x59DB, 0x8A9F, 0x59DC, 0xBDAA, 0x59DD, 0xE6AD, 0x59DE, 0x8AA0,
+	0x59DF, 0x8AA1, 0x59E0, 0x8AA2, 0x59E1, 0x8AA3, 0x59E2, 0x8AA4,
+	0x59E3, 0xE6AF, 0x59E4, 0x8AA5, 0x59E5, 0xC0D1, 0x59E6, 0x8AA6,
+	0x59E7, 0x8AA7, 0x59E8, 0xD2CC, 0x59E9, 0x8AA8, 0x59EA, 0x8AA9,
+	0x59EB, 0x8AAA, 0x59EC, 0xBCA7, 0x59ED, 0x8AAB, 0x59EE, 0x8AAC,
+	0x59EF, 0x8AAD, 0x59F0, 0x8AAE, 0x59F1, 0x8AAF, 0x59F2, 0x8AB0,
+	0x59F3, 0x8AB1, 0x59F4, 0x8AB2, 0x59F5, 0x8AB3, 0x59F6, 0x8AB4,
+	0x59F7, 0x8AB5, 0x59F8, 0x8AB6, 0x59F9, 0xE6B1, 0x59FA, 0x8AB7,
+	0x59FB, 0xD2F6, 0x59FC, 0x8AB8, 0x59FD, 0x8AB9, 0x59FE, 0x8ABA,
+	0x59FF, 0xD7CB, 0x5A00, 0x8ABB, 0x5A01, 0xCDFE, 0x5A02, 0x8ABC,
+	0x5A03, 0xCDDE, 0x5A04, 0xC2A6, 0x5A05, 0xE6AB, 0x5A06, 0xE6AC,
+	0x5A07, 0xBDBF, 0x5A08, 0xE6AE, 0x5A09, 0xE6B3, 0x5A0A, 0x8ABD,
+	0x5A0B, 0x8ABE, 0x5A0C, 0xE6B2, 0x5A0D, 0x8ABF, 0x5A0E, 0x8AC0,
+	0x5A0F, 0x8AC1, 0x5A10, 0x8AC2, 0x5A11, 0xE6B6, 0x5A12, 0x8AC3,
+	0x5A13, 0xE6B8, 0x5A14, 0x8AC4, 0x5A15, 0x8AC5, 0x5A16, 0x8AC6,
+	0x5A17, 0x8AC7, 0x5A18, 0xC4EF, 0x5A19, 0x8AC8, 0x5A1A, 0x8AC9,
+	0x5A1B, 0x8ACA, 0x5A1C, 0xC4C8, 0x5A1D, 0x8ACB, 0x5A1E, 0x8ACC,
+	0x5A1F, 0xBEEA, 0x5A20, 0xC9EF, 0x5A21, 0x8ACD, 0x5A22, 0x8ACE,
+	0x5A23, 0xE6B7, 0x5A24, 0x8ACF, 0x5A25, 0xB6F0, 0x5A26, 0x8AD0,
+	0x5A27, 0x8AD1, 0x5A28, 0x8AD2, 0x5A29, 0xC3E4, 0x5A2A, 0x8AD3,
+	0x5A2B, 0x8AD4, 0x5A2C, 0x8AD5, 0x5A2D, 0x8AD6, 0x5A2E, 0x8AD7,
+	0x5A2F, 0x8AD8, 0x5A30, 0x8AD9, 0x5A31, 0xD3E9, 0x5A32, 0xE6B4,
+	0x5A33, 0x8ADA, 0x5A34, 0xE6B5, 0x5A35, 0x8ADB, 0x5A36, 0xC8A2,
+	0x5A37, 0x8ADC, 0x5A38, 0x8ADD, 0x5A39, 0x8ADE, 0x5A3A, 0x8ADF,
+	0x5A3B, 0x8AE0, 0x5A3C, 0xE6BD, 0x5A3D, 0x8AE1, 0x5A3E, 0x8AE2,
+	0x5A3F, 0x8AE3, 0x5A40, 0xE6B9, 0x5A41, 0x8AE4, 0x5A42, 0x8AE5,
+	0x5A43, 0x8AE6, 0x5A44, 0x8AE7, 0x5A45, 0x8AE8, 0x5A46, 0xC6C5,
+	0x5A47, 0x8AE9, 0x5A48, 0x8AEA, 0x5A49, 0xCDF1, 0x5A4A, 0xE6BB,
+	0x5A4B, 0x8AEB, 0x5A4C, 0x8AEC, 0x5A4D, 0x8AED, 0x5A4E, 0x8AEE,
+	0x5A4F, 0x8AEF, 0x5A50, 0x8AF0, 0x5A51, 0x8AF1, 0x5A52, 0x8AF2,
+	0x5A53, 0x8AF3, 0x5A54, 0x8AF4, 0x5A55, 0xE6BC, 0x5A56, 0x8AF5,
+	0x5A57, 0x8AF6, 0x5A58, 0x8AF7, 0x5A59, 0x8AF8, 0x5A5A, 0xBBE9,
+	0x5A5B, 0x8AF9, 0x5A5C, 0x8AFA, 0x5A5D, 0x8AFB, 0x5A5E, 0x8AFC,
+	0x5A5F, 0x8AFD, 0x5A60, 0x8AFE, 0x5A61, 0x8B40, 0x5A62, 0xE6BE,
+	0x5A63, 0x8B41, 0x5A64, 0x8B42, 0x5A65, 0x8B43, 0x5A66, 0x8B44,
+	0x5A67, 0xE6BA, 0x5A68, 0x8B45, 0x5A69, 0x8B46, 0x5A6A, 0xC0B7,
+	0x5A6B, 0x8B47, 0x5A6C, 0x8B48, 0x5A6D, 0x8B49, 0x5A6E, 0x8B4A,
+	0x5A6F, 0x8B4B, 0x5A70, 0x8B4C, 0x5A71, 0x8B4D, 0x5A72, 0x8B4E,
+	0x5A73, 0x8B4F, 0x5A74, 0xD3A4, 0x5A75, 0xE6BF, 0x5A76, 0xC9F4,
+	0x5A77, 0xE6C3, 0x5A78, 0x8B50, 0x5A79, 0x8B51, 0x5A7A, 0xE6C4,
+	0x5A7B, 0x8B52, 0x5A7C, 0x8B53, 0x5A7D, 0x8B54, 0x5A7E, 0x8B55,
+	0x5A7F, 0xD0F6, 0x5A80, 0x8B56, 0x5A81, 0x8B57, 0x5A82, 0x8B58,
+	0x5A83, 0x8B59, 0x5A84, 0x8B5A, 0x5A85, 0x8B5B, 0x5A86, 0x8B5C,
+	0x5A87, 0x8B5D, 0x5A88, 0x8B5E, 0x5A89, 0x8B5F, 0x5A8A, 0x8B60,
+	0x5A8B, 0x8B61, 0x5A8C, 0x8B62, 0x5A8D, 0x8B63, 0x5A8E, 0x8B64,
+	0x5A8F, 0x8B65, 0x5A90, 0x8B66, 0x5A91, 0x8B67, 0x5A92, 0xC3BD,
+	0x5A93, 0x8B68, 0x5A94, 0x8B69, 0x5A95, 0x8B6A, 0x5A96, 0x8B6B,
+	0x5A97, 0x8B6C, 0x5A98, 0x8B6D, 0x5A99, 0x8B6E, 0x5A9A, 0xC3C4,
+	0x5A9B, 0xE6C2, 0x5A9C, 0x8B6F, 0x5A9D, 0x8B70, 0x5A9E, 0x8B71,
+	0x5A9F, 0x8B72, 0x5AA0, 0x8B73, 0x5AA1, 0x8B74, 0x5AA2, 0x8B75,
+	0x5AA3, 0x8B76, 0x5AA4, 0x8B77, 0x5AA5, 0x8B78, 0x5AA6, 0x8B79,
+	0x5AA7, 0x8B7A, 0x5AA8, 0x8B7B, 0x5AA9, 0x8B7C, 0x5AAA, 0xE6C1,
+	0x5AAB, 0x8B7D, 0x5AAC, 0x8B7E, 0x5AAD, 0x8B80, 0x5AAE, 0x8B81,
+	0x5AAF, 0x8B82, 0x5AB0, 0x8B83, 0x5AB1, 0x8B84, 0x5AB2, 0xE6C7,
+	0x5AB3, 0xCFB1, 0x5AB4, 0x8B85, 0x5AB5, 0xEBF4, 0x5AB6, 0x8B86,
+	0x5AB7, 0x8B87, 0x5AB8, 0xE6CA, 0x5AB9, 0x8B88, 0x5ABA, 0x8B89,
+	0x5ABB, 0x8B8A, 0x5ABC, 0x8B8B, 0x5ABD, 0x8B8C, 0x5ABE, 0xE6C5,
+	0x5ABF, 0x8B8D, 0x5AC0, 0x8B8E, 0x5AC1, 0xBCDE, 0x5AC2, 0xC9A9,
+	0x5AC3, 0x8B8F, 0x5AC4, 0x8B90, 0x5AC5, 0x8B91, 0x5AC6, 0x8B92,
+	0x5AC7, 0x8B93, 0x5AC8, 0x8B94, 0x5AC9, 0xBCB5, 0x5ACA, 0x8B95,
+	0x5ACB, 0x8B96, 0x5ACC, 0xCFD3, 0x5ACD, 0x8B97, 0x5ACE, 0x8B98,
+	0x5ACF, 0x8B99, 0x5AD0, 0x8B9A, 0x5AD1, 0x8B9B, 0x5AD2, 0xE6C8,
+	0x5AD3, 0x8B9C, 0x5AD4, 0xE6C9, 0x5AD5, 0x8B9D, 0x5AD6, 0xE6CE,
+	0x5AD7, 0x8B9E, 0x5AD8, 0xE6D0, 0x5AD9, 0x8B9F, 0x5ADA, 0x8BA0,
+	0x5ADB, 0x8BA1, 0x5ADC, 0xE6D1, 0x5ADD, 0x8BA2, 0x5ADE, 0x8BA3,
+	0x5ADF, 0x8BA4, 0x5AE0, 0xE6CB, 0x5AE1, 0xB5D5, 0x5AE2, 0x8BA5,
+	0x5AE3, 0xE6CC, 0x5AE4, 0x8BA6, 0x5AE5, 0x8BA7, 0x5AE6, 0xE6CF,
+	0x5AE7, 0x8BA8, 0x5AE8, 0x8BA9, 0x5AE9, 0xC4DB, 0x5AEA, 0x8BAA,
+	0x5AEB, 0xE6C6, 0x5AEC, 0x8BAB, 0x5AED, 0x8BAC, 0x5AEE, 0x8BAD,
+	0x5AEF, 0x8BAE, 0x5AF0, 0x8BAF, 0x5AF1, 0xE6CD, 0x5AF2, 0x8BB0,
+	0x5AF3, 0x8BB1, 0x5AF4, 0x8BB2, 0x5AF5, 0x8BB3, 0x5AF6, 0x8BB4,
+	0x5AF7, 0x8BB5, 0x5AF8, 0x8BB6, 0x5AF9, 0x8BB7, 0x5AFA, 0x8BB8,
+	0x5AFB, 0x8BB9, 0x5AFC, 0x8BBA, 0x5AFD, 0x8BBB, 0x5AFE, 0x8BBC,
+	0x5AFF, 0x8BBD, 0x5B00, 0x8BBE, 0x5B01, 0x8BBF, 0x5B02, 0x8BC0,
+	0x5B03, 0x8BC1, 0x5B04, 0x8BC2, 0x5B05, 0x8BC3, 0x5B06, 0x8BC4,
+	0x5B07, 0x8BC5, 0x5B08, 0x8BC6, 0x5B09, 0xE6D2, 0x5B0A, 0x8BC7,
+	0x5B0B, 0x8BC8, 0x5B0C, 0x8BC9, 0x5B0D, 0x8BCA, 0x5B0E, 0x8BCB,
+	0x5B0F, 0x8BCC, 0x5B10, 0x8BCD, 0x5B11, 0x8BCE, 0x5B12, 0x8BCF,
+	0x5B13, 0x8BD0, 0x5B14, 0x8BD1, 0x5B15, 0x8BD2, 0x5B16, 0xE6D4,
+	0x5B17, 0xE6D3, 0x5B18, 0x8BD3, 0x5B19, 0x8BD4, 0x5B1A, 0x8BD5,
+	0x5B1B, 0x8BD6, 0x5B1C, 0x8BD7, 0x5B1D, 0x8BD8, 0x5B1E, 0x8BD9,
+	0x5B1F, 0x8BDA, 0x5B20, 0x8BDB, 0x5B21, 0x8BDC, 0x5B22, 0x8BDD,
+	0x5B23, 0x8BDE, 0x5B24, 0x8BDF, 0x5B25, 0x8BE0, 0x5B26, 0x8BE1,
+	0x5B27, 0x8BE2, 0x5B28, 0x8BE3, 0x5B29, 0x8BE4, 0x5B2A, 0x8BE5,
+	0x5B2B, 0x8BE6, 0x5B2C, 0x8BE7, 0x5B2D, 0x8BE8, 0x5B2E, 0x8BE9,
+	0x5B2F, 0x8BEA, 0x5B30, 0x8BEB, 0x5B31, 0x8BEC, 0x5B32, 0xE6D5,
+	0x5B33, 0x8BED, 0x5B34, 0xD9F8, 0x5B35, 0x8BEE, 0x5B36, 0x8BEF,
+	0x5B37, 0xE6D6, 0x5B38, 0x8BF0, 0x5B39, 0x8BF1, 0x5B3A, 0x8BF2,
+	0x5B3B, 0x8BF3, 0x5B3C, 0x8BF4, 0x5B3D, 0x8BF5, 0x5B3E, 0x8BF6,
+	0x5B3F, 0x8BF7, 0x5B40, 0xE6D7, 0x5B41, 0x8BF8, 0x5B42, 0x8BF9,
+	0x5B43, 0x8BFA, 0x5B44, 0x8BFB, 0x5B45, 0x8BFC, 0x5B46, 0x8BFD,
+	0x5B47, 0x8BFE, 0x5B48, 0x8C40, 0x5B49, 0x8C41, 0x5B4A, 0x8C42,
+	0x5B4B, 0x8C43, 0x5B4C, 0x8C44, 0x5B4D, 0x8C45, 0x5B4E, 0x8C46,
+	0x5B4F, 0x8C47, 0x5B50, 0xD7D3, 0x5B51, 0xE6DD, 0x5B52, 0x8C48,
+	0x5B53, 0xE6DE, 0x5B54, 0xBFD7, 0x5B55, 0xD4D0, 0x5B56, 0x8C49,
+	0x5B57, 0xD7D6, 0x5B58, 0xB4E6, 0x5B59, 0xCBEF, 0x5B5A, 0xE6DA,
+	0x5B5B, 0xD8C3, 0x5B5C, 0xD7CE, 0x5B5D, 0xD0A2, 0x5B5E, 0x8C4A,
+	0x5B5F, 0xC3CF, 0x5B60, 0x8C4B, 0x5B61, 0x8C4C, 0x5B62, 0xE6DF,
+	0x5B63, 0xBCBE, 0x5B64, 0xB9C2, 0x5B65, 0xE6DB, 0x5B66, 0xD1A7,
+	0x5B67, 0x8C4D, 0x5B68, 0x8C4E, 0x5B69, 0xBAA2, 0x5B6A, 0xC2CF,
+	0x5B6B, 0x8C4F, 0x5B6C, 0xD8AB, 0x5B6D, 0x8C50, 0x5B6E, 0x8C51,
+	0x5B6F, 0x8C52, 0x5B70, 0xCAEB, 0x5B71, 0xE5EE, 0x5B72, 0x8C53,
+	0x5B73, 0xE6DC, 0x5B74, 0x8C54, 0x5B75, 0xB7F5, 0x5B76, 0x8C55,
+	0x5B77, 0x8C56, 0x5B78, 0x8C57, 0x5B79, 0x8C58, 0x5B7A, 0xC8E6,
+	0x5B7B, 0x8C59, 0x5B7C, 0x8C5A, 0x5B7D, 0xC4F5, 0x5B7E, 0x8C5B,
+	0x5B7F, 0x8C5C, 0x5B80, 0xE5B2, 0x5B81, 0xC4FE, 0x5B82, 0x8C5D,
+	0x5B83, 0xCBFC, 0x5B84, 0xE5B3, 0x5B85, 0xD5AC, 0x5B86, 0x8C5E,
+	0x5B87, 0xD3EE, 0x5B88, 0xCAD8, 0x5B89, 0xB0B2, 0x5B8A, 0x8C5F,
+	0x5B8B, 0xCBCE, 0x5B8C, 0xCDEA, 0x5B8D, 0x8C60, 0x5B8E, 0x8C61,
+	0x5B8F, 0xBAEA, 0x5B90, 0x8C62, 0x5B91, 0x8C63, 0x5B92, 0x8C64,
+	0x5B93, 0xE5B5, 0x5B94, 0x8C65, 0x5B95, 0xE5B4, 0x5B96, 0x8C66,
+	0x5B97, 0xD7DA, 0x5B98, 0xB9D9, 0x5B99, 0xD6E6, 0x5B9A, 0xB6A8,
+	0x5B9B, 0xCDF0, 0x5B9C, 0xD2CB, 0x5B9D, 0xB1A6, 0x5B9E, 0xCAB5,
+	0x5B9F, 0x8C67, 0x5BA0, 0xB3E8, 0x5BA1, 0xC9F3, 0x5BA2, 0xBFCD,
+	0x5BA3, 0xD0FB, 0x5BA4, 0xCAD2, 0x5BA5, 0xE5B6, 0x5BA6, 0xBBC2,
+	0x5BA7, 0x8C68, 0x5BA8, 0x8C69, 0x5BA9, 0x8C6A, 0x5BAA, 0xCFDC,
+	0x5BAB, 0xB9AC, 0x5BAC, 0x8C6B, 0x5BAD, 0x8C6C, 0x5BAE, 0x8C6D,
+	0x5BAF, 0x8C6E, 0x5BB0, 0xD4D7, 0x5BB1, 0x8C6F, 0x5BB2, 0x8C70,
+	0x5BB3, 0xBAA6, 0x5BB4, 0xD1E7, 0x5BB5, 0xCFFC, 0x5BB6, 0xBCD2,
+	0x5BB7, 0x8C71, 0x5BB8, 0xE5B7, 0x5BB9, 0xC8DD, 0x5BBA, 0x8C72,
+	0x5BBB, 0x8C73, 0x5BBC, 0x8C74, 0x5BBD, 0xBFED, 0x5BBE, 0xB1F6,
+	0x5BBF, 0xCBDE, 0x5BC0, 0x8C75, 0x5BC1, 0x8C76, 0x5BC2, 0xBCC5,
+	0x5BC3, 0x8C77, 0x5BC4, 0xBCC4, 0x5BC5, 0xD2FA, 0x5BC6, 0xC3DC,
+	0x5BC7, 0xBFDC, 0x5BC8, 0x8C78, 0x5BC9, 0x8C79, 0x5BCA, 0x8C7A,
+	0x5BCB, 0x8C7B, 0x5BCC, 0xB8BB, 0x5BCD, 0x8C7C, 0x5BCE, 0x8C7D,
+	0x5BCF, 0x8C7E, 0x5BD0, 0xC3C2, 0x5BD1, 0x8C80, 0x5BD2, 0xBAAE,
+	0x5BD3, 0xD4A2, 0x5BD4, 0x8C81, 0x5BD5, 0x8C82, 0x5BD6, 0x8C83,
+	0x5BD7, 0x8C84, 0x5BD8, 0x8C85, 0x5BD9, 0x8C86, 0x5BDA, 0x8C87,
+	0x5BDB, 0x8C88, 0x5BDC, 0x8C89, 0x5BDD, 0xC7DE, 0x5BDE, 0xC4AF,
+	0x5BDF, 0xB2EC, 0x5BE0, 0x8C8A, 0x5BE1, 0xB9D1, 0x5BE2, 0x8C8B,
+	0x5BE3, 0x8C8C, 0x5BE4, 0xE5BB, 0x5BE5, 0xC1C8, 0x5BE6, 0x8C8D,
+	0x5BE7, 0x8C8E, 0x5BE8, 0xD5AF, 0x5BE9, 0x8C8F, 0x5BEA, 0x8C90,
+	0x5BEB, 0x8C91, 0x5BEC, 0x8C92, 0x5BED, 0x8C93, 0x5BEE, 0xE5BC,
+	0x5BEF, 0x8C94, 0x5BF0, 0xE5BE, 0x5BF1, 0x8C95, 0x5BF2, 0x8C96,
+	0x5BF3, 0x8C97, 0x5BF4, 0x8C98, 0x5BF5, 0x8C99, 0x5BF6, 0x8C9A,
+	0x5BF7, 0x8C9B, 0x5BF8, 0xB4E7, 0x5BF9, 0xB6D4, 0x5BFA, 0xCBC2,
+	0x5BFB, 0xD1B0, 0x5BFC, 0xB5BC, 0x5BFD, 0x8C9C, 0x5BFE, 0x8C9D,
+	0x5BFF, 0xCAD9, 0x5C00, 0x8C9E, 0x5C01, 0xB7E2, 0x5C02, 0x8C9F,
+	0x5C03, 0x8CA0, 0x5C04, 0xC9E4, 0x5C05, 0x8CA1, 0x5C06, 0xBDAB,
+	0x5C07, 0x8CA2, 0x5C08, 0x8CA3, 0x5C09, 0xCEBE, 0x5C0A, 0xD7F0,
+	0x5C0B, 0x8CA4, 0x5C0C, 0x8CA5, 0x5C0D, 0x8CA6, 0x5C0E, 0x8CA7,
+	0x5C0F, 0xD0A1, 0x5C10, 0x8CA8, 0x5C11, 0xC9D9, 0x5C12, 0x8CA9,
+	0x5C13, 0x8CAA, 0x5C14, 0xB6FB, 0x5C15, 0xE6D8, 0x5C16, 0xBCE2,
+	0x5C17, 0x8CAB, 0x5C18, 0xB3BE, 0x5C19, 0x8CAC, 0x5C1A, 0xC9D0,
+	0x5C1B, 0x8CAD, 0x5C1C, 0xE6D9, 0x5C1D, 0xB3A2, 0x5C1E, 0x8CAE,
+	0x5C1F, 0x8CAF, 0x5C20, 0x8CB0, 0x5C21, 0x8CB1, 0x5C22, 0xDECC,
+	0x5C23, 0x8CB2, 0x5C24, 0xD3C8, 0x5C25, 0xDECD, 0x5C26, 0x8CB3,
+	0x5C27, 0xD2A2, 0x5C28, 0x8CB4, 0x5C29, 0x8CB5, 0x5C2A, 0x8CB6,
+	0x5C2B, 0x8CB7, 0x5C2C, 0xDECE, 0x5C2D, 0x8CB8, 0x5C2E, 0x8CB9,
+	0x5C2F, 0x8CBA, 0x5C30, 0x8CBB, 0x5C31, 0xBECD, 0x5C32, 0x8CBC,
+	0x5C33, 0x8CBD, 0x5C34, 0xDECF, 0x5C35, 0x8CBE, 0x5C36, 0x8CBF,
+	0x5C37, 0x8CC0, 0x5C38, 0xCAAC, 0x5C39, 0xD2FC, 0x5C3A, 0xB3DF,
+	0x5C3B, 0xE5EA, 0x5C3C, 0xC4E1, 0x5C3D, 0xBEA1, 0x5C3E, 0xCEB2,
+	0x5C3F, 0xC4F2, 0x5C40, 0xBED6, 0x5C41, 0xC6A8, 0x5C42, 0xB2E3,
+	0x5C43, 0x8CC1, 0x5C44, 0x8CC2, 0x5C45, 0xBED3, 0x5C46, 0x8CC3,
+	0x5C47, 0x8CC4, 0x5C48, 0xC7FC, 0x5C49, 0xCCEB, 0x5C4A, 0xBDEC,
+	0x5C4B, 0xCEDD, 0x5C4C, 0x8CC5, 0x5C4D, 0x8CC6, 0x5C4E, 0xCABA,
+	0x5C4F, 0xC6C1, 0x5C50, 0xE5EC, 0x5C51, 0xD0BC, 0x5C52, 0x8CC7,
+	0x5C53, 0x8CC8, 0x5C54, 0x8CC9, 0x5C55, 0xD5B9, 0x5C56, 0x8CCA,
+	0x5C57, 0x8CCB, 0x5C58, 0x8CCC, 0x5C59, 0xE5ED, 0x5C5A, 0x8CCD,
+	0x5C5B, 0x8CCE, 0x5C5C, 0x8CCF, 0x5C5D, 0x8CD0, 0x5C5E, 0xCAF4,
+	0x5C5F, 0x8CD1, 0x5C60, 0xCDC0, 0x5C61, 0xC2C5, 0x5C62, 0x8CD2,
+	0x5C63, 0xE5EF, 0x5C64, 0x8CD3, 0x5C65, 0xC2C4, 0x5C66, 0xE5F0,
+	0x5C67, 0x8CD4, 0x5C68, 0x8CD5, 0x5C69, 0x8CD6, 0x5C6A, 0x8CD7,
+	0x5C6B, 0x8CD8, 0x5C6C, 0x8CD9, 0x5C6D, 0x8CDA, 0x5C6E, 0xE5F8,
+	0x5C6F, 0xCDCD, 0x5C70, 0x8CDB, 0x5C71, 0xC9BD, 0x5C72, 0x8CDC,
+	0x5C73, 0x8CDD, 0x5C74, 0x8CDE, 0x5C75, 0x8CDF, 0x5C76, 0x8CE0,
+	0x5C77, 0x8CE1, 0x5C78, 0x8CE2, 0x5C79, 0xD2D9, 0x5C7A, 0xE1A8,
+	0x5C7B, 0x8CE3, 0x5C7C, 0x8CE4, 0x5C7D, 0x8CE5, 0x5C7E, 0x8CE6,
+	0x5C7F, 0xD3EC, 0x5C80, 0x8CE7, 0x5C81, 0xCBEA, 0x5C82, 0xC6F1,
+	0x5C83, 0x8CE8, 0x5C84, 0x8CE9, 0x5C85, 0x8CEA, 0x5C86, 0x8CEB,
+	0x5C87, 0x8CEC, 0x5C88, 0xE1AC, 0x5C89, 0x8CED, 0x5C8A, 0x8CEE,
+	0x5C8B, 0x8CEF, 0x5C8C, 0xE1A7, 0x5C8D, 0xE1A9, 0x5C8E, 0x8CF0,
+	0x5C8F, 0x8CF1, 0x5C90, 0xE1AA, 0x5C91, 0xE1AF, 0x5C92, 0x8CF2,
+	0x5C93, 0x8CF3, 0x5C94, 0xB2ED, 0x5C95, 0x8CF4, 0x5C96, 0xE1AB,
+	0x5C97, 0xB8DA, 0x5C98, 0xE1AD, 0x5C99, 0xE1AE, 0x5C9A, 0xE1B0,
+	0x5C9B, 0xB5BA, 0x5C9C, 0xE1B1, 0x5C9D, 0x8CF5, 0x5C9E, 0x8CF6,
+	0x5C9F, 0x8CF7, 0x5CA0, 0x8CF8, 0x5CA1, 0x8CF9, 0x5CA2, 0xE1B3,
+	0x5CA3, 0xE1B8, 0x5CA4, 0x8CFA, 0x5CA5, 0x8CFB, 0x5CA6, 0x8CFC,
+	0x5CA7, 0x8CFD, 0x5CA8, 0x8CFE, 0x5CA9, 0xD1D2, 0x5CAA, 0x8D40,
+	0x5CAB, 0xE1B6, 0x5CAC, 0xE1B5, 0x5CAD, 0xC1EB, 0x5CAE, 0x8D41,
+	0x5CAF, 0x8D42, 0x5CB0, 0x8D43, 0x5CB1, 0xE1B7, 0x5CB2, 0x8D44,
+	0x5CB3, 0xD4C0, 0x5CB4, 0x8D45, 0x5CB5, 0xE1B2, 0x5CB6, 0x8D46,
+	0x5CB7, 0xE1BA, 0x5CB8, 0xB0B6, 0x5CB9, 0x8D47, 0x5CBA, 0x8D48,
+	0x5CBB, 0x8D49, 0x5CBC, 0x8D4A, 0x5CBD, 0xE1B4, 0x5CBE, 0x8D4B,
+	0x5CBF, 0xBFF9, 0x5CC0, 0x8D4C, 0x5CC1, 0xE1B9, 0x5CC2, 0x8D4D,
+	0x5CC3, 0x8D4E, 0x5CC4, 0xE1BB, 0x5CC5, 0x8D4F, 0x5CC6, 0x8D50,
+	0x5CC7, 0x8D51, 0x5CC8, 0x8D52, 0x5CC9, 0x8D53, 0x5CCA, 0x8D54,
+	0x5CCB, 0xE1BE, 0x5CCC, 0x8D55, 0x5CCD, 0x8D56, 0x5CCE, 0x8D57,
+	0x5CCF, 0x8D58, 0x5CD0, 0x8D59, 0x5CD1, 0x8D5A, 0x5CD2, 0xE1BC,
+	0x5CD3, 0x8D5B, 0x5CD4, 0x8D5C, 0x5CD5, 0x8D5D, 0x5CD6, 0x8D5E,
+	0x5CD7, 0x8D5F, 0x5CD8, 0x8D60, 0x5CD9, 0xD6C5, 0x5CDA, 0x8D61,
+	0x5CDB, 0x8D62, 0x5CDC, 0x8D63, 0x5CDD, 0x8D64, 0x5CDE, 0x8D65,
+	0x5CDF, 0x8D66, 0x5CE0, 0x8D67, 0x5CE1, 0xCFBF, 0x5CE2, 0x8D68,
+	0x5CE3, 0x8D69, 0x5CE4, 0xE1BD, 0x5CE5, 0xE1BF, 0x5CE6, 0xC2CD,
+	0x5CE7, 0x8D6A, 0x5CE8, 0xB6EB, 0x5CE9, 0x8D6B, 0x5CEA, 0xD3F8,
+	0x5CEB, 0x8D6C, 0x5CEC, 0x8D6D, 0x5CED, 0xC7CD, 0x5CEE, 0x8D6E,
+	0x5CEF, 0x8D6F, 0x5CF0, 0xB7E5, 0x5CF1, 0x8D70, 0x5CF2, 0x8D71,
+	0x5CF3, 0x8D72, 0x5CF4, 0x8D73, 0x5CF5, 0x8D74, 0x5CF6, 0x8D75,
+	0x5CF7, 0x8D76, 0x5CF8, 0x8D77, 0x5CF9, 0x8D78, 0x5CFA, 0x8D79,
+	0x5CFB, 0xBEFE, 0x5CFC, 0x8D7A, 0x5CFD, 0x8D7B, 0x5CFE, 0x8D7C,
+	0x5CFF, 0x8D7D, 0x5D00, 0x8D7E, 0x5D01, 0x8D80, 0x5D02, 0xE1C0,
+	0x5D03, 0xE1C1, 0x5D04, 0x8D81, 0x5D05, 0x8D82, 0x5D06, 0xE1C7,
+	0x5D07, 0xB3E7, 0x5D08, 0x8D83, 0x5D09, 0x8D84, 0x5D0A, 0x8D85,
+	0x5D0B, 0x8D86, 0x5D0C, 0x8D87, 0x5D0D, 0x8D88, 0x5D0E, 0xC6E9,
+	0x5D0F, 0x8D89, 0x5D10, 0x8D8A, 0x5D11, 0x8D8B, 0x5D12, 0x8D8C,
+	0x5D13, 0x8D8D, 0x5D14, 0xB4DE, 0x5D15, 0x8D8E, 0x5D16, 0xD1C2,
+	0x5D17, 0x8D8F, 0x5D18, 0x8D90, 0x5D19, 0x8D91, 0x5D1A, 0x8D92,
+	0x5D1B, 0xE1C8, 0x5D1C, 0x8D93, 0x5D1D, 0x8D94, 0x5D1E, 0xE1C6,
+	0x5D1F, 0x8D95, 0x5D20, 0x8D96, 0x5D21, 0x8D97, 0x5D22, 0x8D98,
+	0x5D23, 0x8D99, 0x5D24, 0xE1C5, 0x5D25, 0x8D9A, 0x5D26, 0xE1C3,
+	0x5D27, 0xE1C2, 0x5D28, 0x8D9B, 0x5D29, 0xB1C0, 0x5D2A, 0x8D9C,
+	0x5D2B, 0x8D9D, 0x5D2C, 0x8D9E, 0x5D2D, 0xD5B8, 0x5D2E, 0xE1C4,
+	0x5D2F, 0x8D9F, 0x5D30, 0x8DA0, 0x5D31, 0x8DA1, 0x5D32, 0x8DA2,
+	0x5D33, 0x8DA3, 0x5D34, 0xE1CB, 0x5D35, 0x8DA4, 0x5D36, 0x8DA5,
+	0x5D37, 0x8DA6, 0x5D38, 0x8DA7, 0x5D39, 0x8DA8, 0x5D3A, 0x8DA9,
+	0x5D3B, 0x8DAA, 0x5D3C, 0x8DAB, 0x5D3D, 0xE1CC, 0x5D3E, 0xE1CA,
+	0x5D3F, 0x8DAC, 0x5D40, 0x8DAD, 0x5D41, 0x8DAE, 0x5D42, 0x8DAF,
+	0x5D43, 0x8DB0, 0x5D44, 0x8DB1, 0x5D45, 0x8DB2, 0x5D46, 0x8DB3,
+	0x5D47, 0xEFFA, 0x5D48, 0x8DB4, 0x5D49, 0x8DB5, 0x5D4A, 0xE1D3,
+	0x5D4B, 0xE1D2, 0x5D4C, 0xC7B6, 0x5D4D, 0x8DB6, 0x5D4E, 0x8DB7,
+	0x5D4F, 0x8DB8, 0x5D50, 0x8DB9, 0x5D51, 0x8DBA, 0x5D52, 0x8DBB,
+	0x5D53, 0x8DBC, 0x5D54, 0x8DBD, 0x5D55, 0x8DBE, 0x5D56, 0x8DBF,
+	0x5D57, 0x8DC0, 0x5D58, 0xE1C9, 0x5D59, 0x8DC1, 0x5D5A, 0x8DC2,
+	0x5D5B, 0xE1CE, 0x5D5C, 0x8DC3, 0x5D5D, 0xE1D0, 0x5D5E, 0x8DC4,
+	0x5D5F, 0x8DC5, 0x5D60, 0x8DC6, 0x5D61, 0x8DC7, 0x5D62, 0x8DC8,
+	0x5D63, 0x8DC9, 0x5D64, 0x8DCA, 0x5D65, 0x8DCB, 0x5D66, 0x8DCC,
+	0x5D67, 0x8DCD, 0x5D68, 0x8DCE, 0x5D69, 0xE1D4, 0x5D6A, 0x8DCF,
+	0x5D6B, 0xE1D1, 0x5D6C, 0xE1CD, 0x5D6D, 0x8DD0, 0x5D6E, 0x8DD1,
+	0x5D6F, 0xE1CF, 0x5D70, 0x8DD2, 0x5D71, 0x8DD3, 0x5D72, 0x8DD4,
+	0x5D73, 0x8DD5, 0x5D74, 0xE1D5, 0x5D75, 0x8DD6, 0x5D76, 0x8DD7,
+	0x5D77, 0x8DD8, 0x5D78, 0x8DD9, 0x5D79, 0x8DDA, 0x5D7A, 0x8DDB,
+	0x5D7B, 0x8DDC, 0x5D7C, 0x8DDD, 0x5D7D, 0x8DDE, 0x5D7E, 0x8DDF,
+	0x5D7F, 0x8DE0, 0x5D80, 0x8DE1, 0x5D81, 0x8DE2, 0x5D82, 0xE1D6,
+	0x5D83, 0x8DE3, 0x5D84, 0x8DE4, 0x5D85, 0x8DE5, 0x5D86, 0x8DE6,
+	0x5D87, 0x8DE7, 0x5D88, 0x8DE8, 0x5D89, 0x8DE9, 0x5D8A, 0x8DEA,
+	0x5D8B, 0x8DEB, 0x5D8C, 0x8DEC, 0x5D8D, 0x8DED, 0x5D8E, 0x8DEE,
+	0x5D8F, 0x8DEF, 0x5D90, 0x8DF0, 0x5D91, 0x8DF1, 0x5D92, 0x8DF2,
+	0x5D93, 0x8DF3, 0x5D94, 0x8DF4, 0x5D95, 0x8DF5, 0x5D96, 0x8DF6,
+	0x5D97, 0x8DF7, 0x5D98, 0x8DF8, 0x5D99, 0xE1D7, 0x5D9A, 0x8DF9,
+	0x5D9B, 0x8DFA, 0x5D9C, 0x8DFB, 0x5D9D, 0xE1D8, 0x5D9E, 0x8DFC,
+	0x5D9F, 0x8DFD, 0x5DA0, 0x8DFE, 0x5DA1, 0x8E40, 0x5DA2, 0x8E41,
+	0x5DA3, 0x8E42, 0x5DA4, 0x8E43, 0x5DA5, 0x8E44, 0x5DA6, 0x8E45,
+	0x5DA7, 0x8E46, 0x5DA8, 0x8E47, 0x5DA9, 0x8E48, 0x5DAA, 0x8E49,
+	0x5DAB, 0x8E4A, 0x5DAC, 0x8E4B, 0x5DAD, 0x8E4C, 0x5DAE, 0x8E4D,
+	0x5DAF, 0x8E4E, 0x5DB0, 0x8E4F, 0x5DB1, 0x8E50, 0x5DB2, 0x8E51,
+	0x5DB3, 0x8E52, 0x5DB4, 0x8E53, 0x5DB5, 0x8E54, 0x5DB6, 0x8E55,
+	0x5DB7, 0xE1DA, 0x5DB8, 0x8E56, 0x5DB9, 0x8E57, 0x5DBA, 0x8E58,
+	0x5DBB, 0x8E59, 0x5DBC, 0x8E5A, 0x5DBD, 0x8E5B, 0x5DBE, 0x8E5C,
+	0x5DBF, 0x8E5D, 0x5DC0, 0x8E5E, 0x5DC1, 0x8E5F, 0x5DC2, 0x8E60,
+	0x5DC3, 0x8E61, 0x5DC4, 0x8E62, 0x5DC5, 0xE1DB, 0x5DC6, 0x8E63,
+	0x5DC7, 0x8E64, 0x5DC8, 0x8E65, 0x5DC9, 0x8E66, 0x5DCA, 0x8E67,
+	0x5DCB, 0x8E68, 0x5DCC, 0x8E69, 0x5DCD, 0xCEA1, 0x5DCE, 0x8E6A,
+	0x5DCF, 0x8E6B, 0x5DD0, 0x8E6C, 0x5DD1, 0x8E6D, 0x5DD2, 0x8E6E,
+	0x5DD3, 0x8E6F, 0x5DD4, 0x8E70, 0x5DD5, 0x8E71, 0x5DD6, 0x8E72,
+	0x5DD7, 0x8E73, 0x5DD8, 0x8E74, 0x5DD9, 0x8E75, 0x5DDA, 0x8E76,
+	0x5DDB, 0xE7DD, 0x5DDC, 0x8E77, 0x5DDD, 0xB4A8, 0x5DDE, 0xD6DD,
+	0x5DDF, 0x8E78, 0x5DE0, 0x8E79, 0x5DE1, 0xD1B2, 0x5DE2, 0xB3B2,
+	0x5DE3, 0x8E7A, 0x5DE4, 0x8E7B, 0x5DE5, 0xB9A4, 0x5DE6, 0xD7F3,
+	0x5DE7, 0xC7C9, 0x5DE8, 0xBEDE, 0x5DE9, 0xB9AE, 0x5DEA, 0x8E7C,
+	0x5DEB, 0xCED7, 0x5DEC, 0x8E7D, 0x5DED, 0x8E7E, 0x5DEE, 0xB2EE,
+	0x5DEF, 0xDBCF, 0x5DF0, 0x8E80, 0x5DF1, 0xBCBA, 0x5DF2, 0xD2D1,
+	0x5DF3, 0xCBC8, 0x5DF4, 0xB0CD, 0x5DF5, 0x8E81, 0x5DF6, 0x8E82,
+	0x5DF7, 0xCFEF, 0x5DF8, 0x8E83, 0x5DF9, 0x8E84, 0x5DFA, 0x8E85,
+	0x5DFB, 0x8E86, 0x5DFC, 0x8E87, 0x5DFD, 0xD9E3, 0x5DFE, 0xBDED,
+	0x5DFF, 0x8E88, 0x5E00, 0x8E89, 0x5E01, 0xB1D2, 0x5E02, 0xCAD0,
+	0x5E03, 0xB2BC, 0x5E04, 0x8E8A, 0x5E05, 0xCBA7, 0x5E06, 0xB7AB,
+	0x5E07, 0x8E8B, 0x5E08, 0xCAA6, 0x5E09, 0x8E8C, 0x5E0A, 0x8E8D,
+	0x5E0B, 0x8E8E, 0x5E0C, 0xCFA3, 0x5E0D, 0x8E8F, 0x5E0E, 0x8E90,
+	0x5E0F, 0xE0F8, 0x5E10, 0xD5CA, 0x5E11, 0xE0FB, 0x5E12, 0x8E91,
+	0x5E13, 0x8E92, 0x5E14, 0xE0FA, 0x5E15, 0xC5C1, 0x5E16, 0xCCFB,
+	0x5E17, 0x8E93, 0x5E18, 0xC1B1, 0x5E19, 0xE0F9, 0x5E1A, 0xD6E3,
+	0x5E1B, 0xB2AF, 0x5E1C, 0xD6C4, 0x5E1D, 0xB5DB, 0x5E1E, 0x8E94,
+	0x5E1F, 0x8E95, 0x5E20, 0x8E96, 0x5E21, 0x8E97, 0x5E22, 0x8E98,
+	0x5E23, 0x8E99, 0x5E24, 0x8E9A, 0x5E25, 0x8E9B, 0x5E26, 0xB4F8,
+	0x5E27, 0xD6A1, 0x5E28, 0x8E9C, 0x5E29, 0x8E9D, 0x5E2A, 0x8E9E,
+	0x5E2B, 0x8E9F, 0x5E2C, 0x8EA0, 0x5E2D, 0xCFAF, 0x5E2E, 0xB0EF,
+	0x5E2F, 0x8EA1, 0x5E30, 0x8EA2, 0x5E31, 0xE0FC, 0x5E32, 0x8EA3,
+	0x5E33, 0x8EA4, 0x5E34, 0x8EA5, 0x5E35, 0x8EA6, 0x5E36, 0x8EA7,
+	0x5E37, 0xE1A1, 0x5E38, 0xB3A3, 0x5E39, 0x8EA8, 0x5E3A, 0x8EA9,
+	0x5E3B, 0xE0FD, 0x5E3C, 0xE0FE, 0x5E3D, 0xC3B1, 0x5E3E, 0x8EAA,
+	0x5E3F, 0x8EAB, 0x5E40, 0x8EAC, 0x5E41, 0x8EAD, 0x5E42, 0xC3DD,
+	0x5E43, 0x8EAE, 0x5E44, 0xE1A2, 0x5E45, 0xB7F9, 0x5E46, 0x8EAF,
+	0x5E47, 0x8EB0, 0x5E48, 0x8EB1, 0x5E49, 0x8EB2, 0x5E4A, 0x8EB3,
+	0x5E4B, 0x8EB4, 0x5E4C, 0xBBCF, 0x5E4D, 0x8EB5, 0x5E4E, 0x8EB6,
+	0x5E4F, 0x8EB7, 0x5E50, 0x8EB8, 0x5E51, 0x8EB9, 0x5E52, 0x8EBA,
+	0x5E53, 0x8EBB, 0x5E54, 0xE1A3, 0x5E55, 0xC4BB, 0x5E56, 0x8EBC,
+	0x5E57, 0x8EBD, 0x5E58, 0x8EBE, 0x5E59, 0x8EBF, 0x5E5A, 0x8EC0,
+	0x5E5B, 0xE1A4, 0x5E5C, 0x8EC1, 0x5E5D, 0x8EC2, 0x5E5E, 0xE1A5,
+	0x5E5F, 0x8EC3, 0x5E60, 0x8EC4, 0x5E61, 0xE1A6, 0x5E62, 0xB4B1,
+	0x5E63, 0x8EC5, 0x5E64, 0x8EC6, 0x5E65, 0x8EC7, 0x5E66, 0x8EC8,
+	0x5E67, 0x8EC9, 0x5E68, 0x8ECA, 0x5E69, 0x8ECB, 0x5E6A, 0x8ECC,
+	0x5E6B, 0x8ECD, 0x5E6C, 0x8ECE, 0x5E6D, 0x8ECF, 0x5E6E, 0x8ED0,
+	0x5E6F, 0x8ED1, 0x5E70, 0x8ED2, 0x5E71, 0x8ED3, 0x5E72, 0xB8C9,
+	0x5E73, 0xC6BD, 0x5E74, 0xC4EA, 0x5E75, 0x8ED4, 0x5E76, 0xB2A2,
+	0x5E77, 0x8ED5, 0x5E78, 0xD0D2, 0x5E79, 0x8ED6, 0x5E7A, 0xE7DB,
+	0x5E7B, 0xBBC3, 0x5E7C, 0xD3D7, 0x5E7D, 0xD3C4, 0x5E7E, 0x8ED7,
+	0x5E7F, 0xB9E3, 0x5E80, 0xE2CF, 0x5E81, 0x8ED8, 0x5E82, 0x8ED9,
+	0x5E83, 0x8EDA, 0x5E84, 0xD7AF, 0x5E85, 0x8EDB, 0x5E86, 0xC7EC,
+	0x5E87, 0xB1D3, 0x5E88, 0x8EDC, 0x5E89, 0x8EDD, 0x5E8A, 0xB4B2,
+	0x5E8B, 0xE2D1, 0x5E8C, 0x8EDE, 0x5E8D, 0x8EDF, 0x5E8E, 0x8EE0,
+	0x5E8F, 0xD0F2, 0x5E90, 0xC2AE, 0x5E91, 0xE2D0, 0x5E92, 0x8EE1,
+	0x5E93, 0xBFE2, 0x5E94, 0xD3A6, 0x5E95, 0xB5D7, 0x5E96, 0xE2D2,
+	0x5E97, 0xB5EA, 0x5E98, 0x8EE2, 0x5E99, 0xC3ED, 0x5E9A, 0xB8FD,
+	0x5E9B, 0x8EE3, 0x5E9C, 0xB8AE, 0x5E9D, 0x8EE4, 0x5E9E, 0xC5D3,
+	0x5E9F, 0xB7CF, 0x5EA0, 0xE2D4, 0x5EA1, 0x8EE5, 0x5EA2, 0x8EE6,
+	0x5EA3, 0x8EE7, 0x5EA4, 0x8EE8, 0x5EA5, 0xE2D3, 0x5EA6, 0xB6C8,
+	0x5EA7, 0xD7F9, 0x5EA8, 0x8EE9, 0x5EA9, 0x8EEA, 0x5EAA, 0x8EEB,
+	0x5EAB, 0x8EEC, 0x5EAC, 0x8EED, 0x5EAD, 0xCDA5, 0x5EAE, 0x8EEE,
+	0x5EAF, 0x8EEF, 0x5EB0, 0x8EF0, 0x5EB1, 0x8EF1, 0x5EB2, 0x8EF2,
+	0x5EB3, 0xE2D8, 0x5EB4, 0x8EF3, 0x5EB5, 0xE2D6, 0x5EB6, 0xCAFC,
+	0x5EB7, 0xBFB5, 0x5EB8, 0xD3B9, 0x5EB9, 0xE2D5, 0x5EBA, 0x8EF4,
+	0x5EBB, 0x8EF5, 0x5EBC, 0x8EF6, 0x5EBD, 0x8EF7, 0x5EBE, 0xE2D7,
+	0x5EBF, 0x8EF8, 0x5EC0, 0x8EF9, 0x5EC1, 0x8EFA, 0x5EC2, 0x8EFB,
+	0x5EC3, 0x8EFC, 0x5EC4, 0x8EFD, 0x5EC5, 0x8EFE, 0x5EC6, 0x8F40,
+	0x5EC7, 0x8F41, 0x5EC8, 0x8F42, 0x5EC9, 0xC1AE, 0x5ECA, 0xC0C8,
+	0x5ECB, 0x8F43, 0x5ECC, 0x8F44, 0x5ECD, 0x8F45, 0x5ECE, 0x8F46,
+	0x5ECF, 0x8F47, 0x5ED0, 0x8F48, 0x5ED1, 0xE2DB, 0x5ED2, 0xE2DA,
+	0x5ED3, 0xC0AA, 0x5ED4, 0x8F49, 0x5ED5, 0x8F4A, 0x5ED6, 0xC1CE,
+	0x5ED7, 0x8F4B, 0x5ED8, 0x8F4C, 0x5ED9, 0x8F4D, 0x5EDA, 0x8F4E,
+	0x5EDB, 0xE2DC, 0x5EDC, 0x8F4F, 0x5EDD, 0x8F50, 0x5EDE, 0x8F51,
+	0x5EDF, 0x8F52, 0x5EE0, 0x8F53, 0x5EE1, 0x8F54, 0x5EE2, 0x8F55,
+	0x5EE3, 0x8F56, 0x5EE4, 0x8F57, 0x5EE5, 0x8F58, 0x5EE6, 0x8F59,
+	0x5EE7, 0x8F5A, 0x5EE8, 0xE2DD, 0x5EE9, 0x8F5B, 0x5EEA, 0xE2DE,
+	0x5EEB, 0x8F5C, 0x5EEC, 0x8F5D, 0x5EED, 0x8F5E, 0x5EEE, 0x8F5F,
+	0x5EEF, 0x8F60, 0x5EF0, 0x8F61, 0x5EF1, 0x8F62, 0x5EF2, 0x8F63,
+	0x5EF3, 0x8F64, 0x5EF4, 0xDBC8, 0x5EF5, 0x8F65, 0x5EF6, 0xD1D3,
+	0x5EF7, 0xCDA2, 0x5EF8, 0x8F66, 0x5EF9, 0x8F67, 0x5EFA, 0xBDA8,
+	0x5EFB, 0x8F68, 0x5EFC, 0x8F69, 0x5EFD, 0x8F6A, 0x5EFE, 0xDEC3,
+	0x5EFF, 0xD8A5, 0x5F00, 0xBFAA, 0x5F01, 0xDBCD, 0x5F02, 0xD2EC,
+	0x5F03, 0xC6FA, 0x5F04, 0xC5AA, 0x5F05, 0x8F6B, 0x5F06, 0x8F6C,
+	0x5F07, 0x8F6D, 0x5F08, 0xDEC4, 0x5F09, 0x8F6E, 0x5F0A, 0xB1D7,
+	0x5F0B, 0xDFAE, 0x5F0C, 0x8F6F, 0x5F0D, 0x8F70, 0x5F0E, 0x8F71,
+	0x5F0F, 0xCABD, 0x5F10, 0x8F72, 0x5F11, 0xDFB1, 0x5F12, 0x8F73,
+	0x5F13, 0xB9AD, 0x5F14, 0x8F74, 0x5F15, 0xD2FD, 0x5F16, 0x8F75,
+	0x5F17, 0xB8A5, 0x5F18, 0xBAEB, 0x5F19, 0x8F76, 0x5F1A, 0x8F77,
+	0x5F1B, 0xB3DA, 0x5F1C, 0x8F78, 0x5F1D, 0x8F79, 0x5F1E, 0x8F7A,
+	0x5F1F, 0xB5DC, 0x5F20, 0xD5C5, 0x5F21, 0x8F7B, 0x5F22, 0x8F7C,
+	0x5F23, 0x8F7D, 0x5F24, 0x8F7E, 0x5F25, 0xC3D6, 0x5F26, 0xCFD2,
+	0x5F27, 0xBBA1, 0x5F28, 0x8F80, 0x5F29, 0xE5F3, 0x5F2A, 0xE5F2,
+	0x5F2B, 0x8F81, 0x5F2C, 0x8F82, 0x5F2D, 0xE5F4, 0x5F2E, 0x8F83,
+	0x5F2F, 0xCDE4, 0x5F30, 0x8F84, 0x5F31, 0xC8F5, 0x5F32, 0x8F85,
+	0x5F33, 0x8F86, 0x5F34, 0x8F87, 0x5F35, 0x8F88, 0x5F36, 0x8F89,
+	0x5F37, 0x8F8A, 0x5F38, 0x8F8B, 0x5F39, 0xB5AF, 0x5F3A, 0xC7BF,
+	0x5F3B, 0x8F8C, 0x5F3C, 0xE5F6, 0x5F3D, 0x8F8D, 0x5F3E, 0x8F8E,
+	0x5F3F, 0x8F8F, 0x5F40, 0xECB0, 0x5F41, 0x8F90, 0x5F42, 0x8F91,
+	0x5F43, 0x8F92, 0x5F44, 0x8F93, 0x5F45, 0x8F94, 0x5F46, 0x8F95,
+	0x5F47, 0x8F96, 0x5F48, 0x8F97, 0x5F49, 0x8F98, 0x5F4A, 0x8F99,
+	0x5F4B, 0x8F9A, 0x5F4C, 0x8F9B, 0x5F4D, 0x8F9C, 0x5F4E, 0x8F9D,
+	0x5F4F, 0x8F9E, 0x5F50, 0xE5E6, 0x5F51, 0x8F9F, 0x5F52, 0xB9E9,
+	0x5F53, 0xB5B1, 0x5F54, 0x8FA0, 0x5F55, 0xC2BC, 0x5F56, 0xE5E8,
+	0x5F57, 0xE5E7, 0x5F58, 0xE5E9, 0x5F59, 0x8FA1, 0x5F5A, 0x8FA2,
+	0x5F5B, 0x8FA3, 0x5F5C, 0x8FA4, 0x5F5D, 0xD2CD, 0x5F5E, 0x8FA5,
+	0x5F5F, 0x8FA6, 0x5F60, 0x8FA7, 0x5F61, 0xE1EA, 0x5F62, 0xD0CE,
+	0x5F63, 0x8FA8, 0x5F64, 0xCDAE, 0x5F65, 0x8FA9, 0x5F66, 0xD1E5,
+	0x5F67, 0x8FAA, 0x5F68, 0x8FAB, 0x5F69, 0xB2CA, 0x5F6A, 0xB1EB,
+	0x5F6B, 0x8FAC, 0x5F6C, 0xB1F2, 0x5F6D, 0xC5ED, 0x5F6E, 0x8FAD,
+	0x5F6F, 0x8FAE, 0x5F70, 0xD5C3, 0x5F71, 0xD3B0, 0x5F72, 0x8FAF,
+	0x5F73, 0xE1DC, 0x5F74, 0x8FB0, 0x5F75, 0x8FB1, 0x5F76, 0x8FB2,
+	0x5F77, 0xE1DD, 0x5F78, 0x8FB3, 0x5F79, 0xD2DB, 0x5F7A, 0x8FB4,
+	0x5F7B, 0xB3B9, 0x5F7C, 0xB1CB, 0x5F7D, 0x8FB5, 0x5F7E, 0x8FB6,
+	0x5F7F, 0x8FB7, 0x5F80, 0xCDF9, 0x5F81, 0xD5F7, 0x5F82, 0xE1DE,
+	0x5F83, 0x8FB8, 0x5F84, 0xBEB6, 0x5F85, 0xB4FD, 0x5F86, 0x8FB9,
+	0x5F87, 0xE1DF, 0x5F88, 0xBADC, 0x5F89, 0xE1E0, 0x5F8A, 0xBBB2,
+	0x5F8B, 0xC2C9, 0x5F8C, 0xE1E1, 0x5F8D, 0x8FBA, 0x5F8E, 0x8FBB,
+	0x5F8F, 0x8FBC, 0x5F90, 0xD0EC, 0x5F91, 0x8FBD, 0x5F92, 0xCDBD,
+	0x5F93, 0x8FBE, 0x5F94, 0x8FBF, 0x5F95, 0xE1E2, 0x5F96, 0x8FC0,
+	0x5F97, 0xB5C3, 0x5F98, 0xC5C7, 0x5F99, 0xE1E3, 0x5F9A, 0x8FC1,
+	0x5F9B, 0x8FC2, 0x5F9C, 0xE1E4, 0x5F9D, 0x8FC3, 0x5F9E, 0x8FC4,
+	0x5F9F, 0x8FC5, 0x5FA0, 0x8FC6, 0x5FA1, 0xD3F9, 0x5FA2, 0x8FC7,
+	0x5FA3, 0x8FC8, 0x5FA4, 0x8FC9, 0x5FA5, 0x8FCA, 0x5FA6, 0x8FCB,
+	0x5FA7, 0x8FCC, 0x5FA8, 0xE1E5, 0x5FA9, 0x8FCD, 0x5FAA, 0xD1AD,
+	0x5FAB, 0x8FCE, 0x5FAC, 0x8FCF, 0x5FAD, 0xE1E6, 0x5FAE, 0xCEA2,
+	0x5FAF, 0x8FD0, 0x5FB0, 0x8FD1, 0x5FB1, 0x8FD2, 0x5FB2, 0x8FD3,
+	0x5FB3, 0x8FD4, 0x5FB4, 0x8FD5, 0x5FB5, 0xE1E7, 0x5FB6, 0x8FD6,
+	0x5FB7, 0xB5C2, 0x5FB8, 0x8FD7, 0x5FB9, 0x8FD8, 0x5FBA, 0x8FD9,
+	0x5FBB, 0x8FDA, 0x5FBC, 0xE1E8, 0x5FBD, 0xBBD5, 0x5FBE, 0x8FDB,
+	0x5FBF, 0x8FDC, 0x5FC0, 0x8FDD, 0x5FC1, 0x8FDE, 0x5FC2, 0x8FDF,
+	0x5FC3, 0xD0C4, 0x5FC4, 0xE2E0, 0x5FC5, 0xB1D8, 0x5FC6, 0xD2E4,
+	0x5FC7, 0x8FE0, 0x5FC8, 0x8FE1, 0x5FC9, 0xE2E1, 0x5FCA, 0x8FE2,
+	0x5FCB, 0x8FE3, 0x5FCC, 0xBCC9, 0x5FCD, 0xC8CC, 0x5FCE, 0x8FE4,
+	0x5FCF, 0xE2E3, 0x5FD0, 0xECFE, 0x5FD1, 0xECFD, 0x5FD2, 0xDFAF,
+	0x5FD3, 0x8FE5, 0x5FD4, 0x8FE6, 0x5FD5, 0x8FE7, 0x5FD6, 0xE2E2,
+	0x5FD7, 0xD6BE, 0x5FD8, 0xCDFC, 0x5FD9, 0xC3A6, 0x5FDA, 0x8FE8,
+	0x5FDB, 0x8FE9, 0x5FDC, 0x8FEA, 0x5FDD, 0xE3C3, 0x5FDE, 0x8FEB,
+	0x5FDF, 0x8FEC, 0x5FE0, 0xD6D2, 0x5FE1, 0xE2E7, 0x5FE2, 0x8FED,
+	0x5FE3, 0x8FEE, 0x5FE4, 0xE2E8, 0x5FE5, 0x8FEF, 0x5FE6, 0x8FF0,
+	0x5FE7, 0xD3C7, 0x5FE8, 0x8FF1, 0x5FE9, 0x8FF2, 0x5FEA, 0xE2EC,
+	0x5FEB, 0xBFEC, 0x5FEC, 0x8FF3, 0x5FED, 0xE2ED, 0x5FEE, 0xE2E5,
+	0x5FEF, 0x8FF4, 0x5FF0, 0x8FF5, 0x5FF1, 0xB3C0, 0x5FF2, 0x8FF6,
+	0x5FF3, 0x8FF7, 0x5FF4, 0x8FF8, 0x5FF5, 0xC4EE, 0x5FF6, 0x8FF9,
+	0x5FF7, 0x8FFA, 0x5FF8, 0xE2EE, 0x5FF9, 0x8FFB, 0x5FFA, 0x8FFC,
+	0x5FFB, 0xD0C3, 0x5FFC, 0x8FFD, 0x5FFD, 0xBAF6, 0x5FFE, 0xE2E9,
+	0x5FFF, 0xB7DE, 0x6000, 0xBBB3, 0x6001, 0xCCAC, 0x6002, 0xCBCB,
+	0x6003, 0xE2E4, 0x6004, 0xE2E6, 0x6005, 0xE2EA, 0x6006, 0xE2EB,
+	0x6007, 0x8FFE, 0x6008, 0x9040, 0x6009, 0x9041, 0x600A, 0xE2F7,
+	0x600B, 0x9042, 0x600C, 0x9043, 0x600D, 0xE2F4, 0x600E, 0xD4F5,
+	0x600F, 0xE2F3, 0x6010, 0x9044, 0x6011, 0x9045, 0x6012, 0xC5AD,
+	0x6013, 0x9046, 0x6014, 0xD5FA, 0x6015, 0xC5C2, 0x6016, 0xB2C0,
+	0x6017, 0x9047, 0x6018, 0x9048, 0x6019, 0xE2EF, 0x601A, 0x9049,
+	0x601B, 0xE2F2, 0x601C, 0xC1AF, 0x601D, 0xCBBC, 0x601E, 0x904A,
+	0x601F, 0x904B, 0x6020, 0xB5A1, 0x6021, 0xE2F9, 0x6022, 0x904C,
+	0x6023, 0x904D, 0x6024, 0x904E, 0x6025, 0xBCB1, 0x6026, 0xE2F1,
+	0x6027, 0xD0D4, 0x6028, 0xD4B9, 0x6029, 0xE2F5, 0x602A, 0xB9D6,
+	0x602B, 0xE2F6, 0x602C, 0x904F, 0x602D, 0x9050, 0x602E, 0x9051,
+	0x602F, 0xC7D3, 0x6030, 0x9052, 0x6031, 0x9053, 0x6032, 0x9054,
+	0x6033, 0x9055, 0x6034, 0x9056, 0x6035, 0xE2F0, 0x6036, 0x9057,
+	0x6037, 0x9058, 0x6038, 0x9059, 0x6039, 0x905A, 0x603A, 0x905B,
+	0x603B, 0xD7DC, 0x603C, 0xEDA1, 0x603D, 0x905C, 0x603E, 0x905D,
+	0x603F, 0xE2F8, 0x6040, 0x905E, 0x6041, 0xEDA5, 0x6042, 0xE2FE,
+	0x6043, 0xCAD1, 0x6044, 0x905F, 0x6045, 0x9060, 0x6046, 0x9061,
+	0x6047, 0x9062, 0x6048, 0x9063, 0x6049, 0x9064, 0x604A, 0x9065,
+	0x604B, 0xC1B5, 0x604C, 0x9066, 0x604D, 0xBBD0, 0x604E, 0x9067,
+	0x604F, 0x9068, 0x6050, 0xBFD6, 0x6051, 0x9069, 0x6052, 0xBAE3,
+	0x6053, 0x906A, 0x6054, 0x906B, 0x6055, 0xCBA1, 0x6056, 0x906C,
+	0x6057, 0x906D, 0x6058, 0x906E, 0x6059, 0xEDA6, 0x605A, 0xEDA3,
+	0x605B, 0x906F, 0x605C, 0x9070, 0x605D, 0xEDA2, 0x605E, 0x9071,
+	0x605F, 0x9072, 0x6060, 0x9073, 0x6061, 0x9074, 0x6062, 0xBBD6,
+	0x6063, 0xEDA7, 0x6064, 0xD0F4, 0x6065, 0x9075, 0x6066, 0x9076,
+	0x6067, 0xEDA4, 0x6068, 0xBADE, 0x6069, 0xB6F7, 0x606A, 0xE3A1,
+	0x606B, 0xB6B2, 0x606C, 0xCCF1, 0x606D, 0xB9A7, 0x606E, 0x9077,
+	0x606F, 0xCFA2, 0x6070, 0xC7A1, 0x6071, 0x9078, 0x6072, 0x9079,
+	0x6073, 0xBFD2, 0x6074, 0x907A, 0x6075, 0x907B, 0x6076, 0xB6F1,
+	0x6077, 0x907C, 0x6078, 0xE2FA, 0x6079, 0xE2FB, 0x607A, 0xE2FD,
+	0x607B, 0xE2FC, 0x607C, 0xC4D5, 0x607D, 0xE3A2, 0x607E, 0x907D,
+	0x607F, 0xD3C1, 0x6080, 0x907E, 0x6081, 0x9080, 0x6082, 0x9081,
+	0x6083, 0xE3A7, 0x6084, 0xC7C4, 0x6085, 0x9082, 0x6086, 0x9083,
+	0x6087, 0x9084, 0x6088, 0x9085, 0x6089, 0xCFA4, 0x608A, 0x9086,
+	0x608B, 0x9087, 0x608C, 0xE3A9, 0x608D, 0xBAB7, 0x608E, 0x9088,
+	0x608F, 0x9089, 0x6090, 0x908A, 0x6091, 0x908B, 0x6092, 0xE3A8,
+	0x6093, 0x908C, 0x6094, 0xBBDA, 0x6095, 0x908D, 0x6096, 0xE3A3,
+	0x6097, 0x908E, 0x6098, 0x908F, 0x6099, 0x9090, 0x609A, 0xE3A4,
+	0x609B, 0xE3AA, 0x609C, 0x9091, 0x609D, 0xE3A6, 0x609E, 0x9092,
+	0x609F, 0xCEF2, 0x60A0, 0xD3C6, 0x60A1, 0x9093, 0x60A2, 0x9094,
+	0x60A3, 0xBBBC, 0x60A4, 0x9095, 0x60A5, 0x9096, 0x60A6, 0xD4C3,
+	0x60A7, 0x9097, 0x60A8, 0xC4FA, 0x60A9, 0x9098, 0x60AA, 0x9099,
+	0x60AB, 0xEDA8, 0x60AC, 0xD0FC, 0x60AD, 0xE3A5, 0x60AE, 0x909A,
+	0x60AF, 0xC3F5, 0x60B0, 0x909B, 0x60B1, 0xE3AD, 0x60B2, 0xB1AF,
+	0x60B3, 0x909C, 0x60B4, 0xE3B2, 0x60B5, 0x909D, 0x60B6, 0x909E,
+	0x60B7, 0x909F, 0x60B8, 0xBCC2, 0x60B9, 0x90A0, 0x60BA, 0x90A1,
+	0x60BB, 0xE3AC, 0x60BC, 0xB5BF, 0x60BD, 0x90A2, 0x60BE, 0x90A3,
+	0x60BF, 0x90A4, 0x60C0, 0x90A5, 0x60C1, 0x90A6, 0x60C2, 0x90A7,
+	0x60C3, 0x90A8, 0x60C4, 0x90A9, 0x60C5, 0xC7E9, 0x60C6, 0xE3B0,
+	0x60C7, 0x90AA, 0x60C8, 0x90AB, 0x60C9, 0x90AC, 0x60CA, 0xBEAA,
+	0x60CB, 0xCDEF, 0x60CC, 0x90AD, 0x60CD, 0x90AE, 0x60CE, 0x90AF,
+	0x60CF, 0x90B0, 0x60D0, 0x90B1, 0x60D1, 0xBBF3, 0x60D2, 0x90B2,
+	0x60D3, 0x90B3, 0x60D4, 0x90B4, 0x60D5, 0xCCE8, 0x60D6, 0x90B5,
+	0x60D7, 0x90B6, 0x60D8, 0xE3AF, 0x60D9, 0x90B7, 0x60DA, 0xE3B1,
+	0x60DB, 0x90B8, 0x60DC, 0xCFA7, 0x60DD, 0xE3AE, 0x60DE, 0x90B9,
+	0x60DF, 0xCEA9, 0x60E0, 0xBBDD, 0x60E1, 0x90BA, 0x60E2, 0x90BB,
+	0x60E3, 0x90BC, 0x60E4, 0x90BD, 0x60E5, 0x90BE, 0x60E6, 0xB5EB,
+	0x60E7, 0xBEE5, 0x60E8, 0xB2D2, 0x60E9, 0xB3CD, 0x60EA, 0x90BF,
+	0x60EB, 0xB1B9, 0x60EC, 0xE3AB, 0x60ED, 0xB2D1, 0x60EE, 0xB5AC,
+	0x60EF, 0xB9DF, 0x60F0, 0xB6E8, 0x60F1, 0x90C0, 0x60F2, 0x90C1,
+	0x60F3, 0xCFEB, 0x60F4, 0xE3B7, 0x60F5, 0x90C2, 0x60F6, 0xBBCC,
+	0x60F7, 0x90C3, 0x60F8, 0x90C4, 0x60F9, 0xC8C7, 0x60FA, 0xD0CA,
+	0x60FB, 0x90C5, 0x60FC, 0x90C6, 0x60FD, 0x90C7, 0x60FE, 0x90C8,
+	0x60FF, 0x90C9, 0x6100, 0xE3B8, 0x6101, 0xB3EE, 0x6102, 0x90CA,
+	0x6103, 0x90CB, 0x6104, 0x90CC, 0x6105, 0x90CD, 0x6106, 0xEDA9,
+	0x6107, 0x90CE, 0x6108, 0xD3FA, 0x6109, 0xD3E4, 0x610A, 0x90CF,
+	0x610B, 0x90D0, 0x610C, 0x90D1, 0x610D, 0xEDAA, 0x610E, 0xE3B9,
+	0x610F, 0xD2E2, 0x6110, 0x90D2, 0x6111, 0x90D3, 0x6112, 0x90D4,
+	0x6113, 0x90D5, 0x6114, 0x90D6, 0x6115, 0xE3B5, 0x6116, 0x90D7,
+	0x6117, 0x90D8, 0x6118, 0x90D9, 0x6119, 0x90DA, 0x611A, 0xD3DE,
+	0x611B, 0x90DB, 0x611C, 0x90DC, 0x611D, 0x90DD, 0x611E, 0x90DE,
+	0x611F, 0xB8D0, 0x6120, 0xE3B3, 0x6121, 0x90DF, 0x6122, 0x90E0,
+	0x6123, 0xE3B6, 0x6124, 0xB7DF, 0x6125, 0x90E1, 0x6126, 0xE3B4,
+	0x6127, 0xC0A2, 0x6128, 0x90E2, 0x6129, 0x90E3, 0x612A, 0x90E4,
+	0x612B, 0xE3BA, 0x612C, 0x90E5, 0x612D, 0x90E6, 0x612E, 0x90E7,
+	0x612F, 0x90E8, 0x6130, 0x90E9, 0x6131, 0x90EA, 0x6132, 0x90EB,
+	0x6133, 0x90EC, 0x6134, 0x90ED, 0x6135, 0x90EE, 0x6136, 0x90EF,
+	0x6137, 0x90F0, 0x6138, 0x90F1, 0x6139, 0x90F2, 0x613A, 0x90F3,
+	0x613B, 0x90F4, 0x613C, 0x90F5, 0x613D, 0x90F6, 0x613E, 0x90F7,
+	0x613F, 0xD4B8, 0x6140, 0x90F8, 0x6141, 0x90F9, 0x6142, 0x90FA,
+	0x6143, 0x90FB, 0x6144, 0x90FC, 0x6145, 0x90FD, 0x6146, 0x90FE,
+	0x6147, 0x9140, 0x6148, 0xB4C8, 0x6149, 0x9141, 0x614A, 0xE3BB,
+	0x614B, 0x9142, 0x614C, 0xBBC5, 0x614D, 0x9143, 0x614E, 0xC9F7,
+	0x614F, 0x9144, 0x6150, 0x9145, 0x6151, 0xC9E5, 0x6152, 0x9146,
+	0x6153, 0x9147, 0x6154, 0x9148, 0x6155, 0xC4BD, 0x6156, 0x9149,
+	0x6157, 0x914A, 0x6158, 0x914B, 0x6159, 0x914C, 0x615A, 0x914D,
+	0x615B, 0x914E, 0x615C, 0x914F, 0x615D, 0xEDAB, 0x615E, 0x9150,
+	0x615F, 0x9151, 0x6160, 0x9152, 0x6161, 0x9153, 0x6162, 0xC2FD,
+	0x6163, 0x9154, 0x6164, 0x9155, 0x6165, 0x9156, 0x6166, 0x9157,
+	0x6167, 0xBBDB, 0x6168, 0xBFAE, 0x6169, 0x9158, 0x616A, 0x9159,
+	0x616B, 0x915A, 0x616C, 0x915B, 0x616D, 0x915C, 0x616E, 0x915D,
+	0x616F, 0x915E, 0x6170, 0xCEBF, 0x6171, 0x915F, 0x6172, 0x9160,
+	0x6173, 0x9161, 0x6174, 0x9162, 0x6175, 0xE3BC, 0x6176, 0x9163,
+	0x6177, 0xBFB6, 0x6178, 0x9164, 0x6179, 0x9165, 0x617A, 0x9166,
+	0x617B, 0x9167, 0x617C, 0x9168, 0x617D, 0x9169, 0x617E, 0x916A,
+	0x617F, 0x916B, 0x6180, 0x916C, 0x6181, 0x916D, 0x6182, 0x916E,
+	0x6183, 0x916F, 0x6184, 0x9170, 0x6185, 0x9171, 0x6186, 0x9172,
+	0x6187, 0x9173, 0x6188, 0x9174, 0x6189, 0x9175, 0x618A, 0x9176,
+	0x618B, 0xB1EF, 0x618C, 0x9177, 0x618D, 0x9178, 0x618E, 0xD4F7,
+	0x618F, 0x9179, 0x6190, 0x917A, 0x6191, 0x917B, 0x6192, 0x917C,
+	0x6193, 0x917D, 0x6194, 0xE3BE, 0x6195, 0x917E, 0x6196, 0x9180,
+	0x6197, 0x9181, 0x6198, 0x9182, 0x6199, 0x9183, 0x619A, 0x9184,
+	0x619B, 0x9185, 0x619C, 0x9186, 0x619D, 0xEDAD, 0x619E, 0x9187,
+	0x619F, 0x9188, 0x61A0, 0x9189, 0x61A1, 0x918A, 0x61A2, 0x918B,
+	0x61A3, 0x918C, 0x61A4, 0x918D, 0x61A5, 0x918E, 0x61A6, 0x918F,
+	0x61A7, 0xE3BF, 0x61A8, 0xBAA9, 0x61A9, 0xEDAC, 0x61AA, 0x9190,
+	0x61AB, 0x9191, 0x61AC, 0xE3BD, 0x61AD, 0x9192, 0x61AE, 0x9193,
+	0x61AF, 0x9194, 0x61B0, 0x9195, 0x61B1, 0x9196, 0x61B2, 0x9197,
+	0x61B3, 0x9198, 0x61B4, 0x9199, 0x61B5, 0x919A, 0x61B6, 0x919B,
+	0x61B7, 0xE3C0, 0x61B8, 0x919C, 0x61B9, 0x919D, 0x61BA, 0x919E,
+	0x61BB, 0x919F, 0x61BC, 0x91A0, 0x61BD, 0x91A1, 0x61BE, 0xBAB6,
+	0x61BF, 0x91A2, 0x61C0, 0x91A3, 0x61C1, 0x91A4, 0x61C2, 0xB6AE,
+	0x61C3, 0x91A5, 0x61C4, 0x91A6, 0x61C5, 0x91A7, 0x61C6, 0x91A8,
+	0x61C7, 0x91A9, 0x61C8, 0xD0B8, 0x61C9, 0x91AA, 0x61CA, 0xB0C3,
+	0x61CB, 0xEDAE, 0x61CC, 0x91AB, 0x61CD, 0x91AC, 0x61CE, 0x91AD,
+	0x61CF, 0x91AE, 0x61D0, 0x91AF, 0x61D1, 0xEDAF, 0x61D2, 0xC0C1,
+	0x61D3, 0x91B0, 0x61D4, 0xE3C1, 0x61D5, 0x91B1, 0x61D6, 0x91B2,
+	0x61D7, 0x91B3, 0x61D8, 0x91B4, 0x61D9, 0x91B5, 0x61DA, 0x91B6,
+	0x61DB, 0x91B7, 0x61DC, 0x91B8, 0x61DD, 0x91B9, 0x61DE, 0x91BA,
+	0x61DF, 0x91BB, 0x61E0, 0x91BC, 0x61E1, 0x91BD, 0x61E2, 0x91BE,
+	0x61E3, 0x91BF, 0x61E4, 0x91C0, 0x61E5, 0x91C1, 0x61E6, 0xC5B3,
+	0x61E7, 0x91C2, 0x61E8, 0x91C3, 0x61E9, 0x91C4, 0x61EA, 0x91C5,
+	0x61EB, 0x91C6, 0x61EC, 0x91C7, 0x61ED, 0x91C8, 0x61EE, 0x91C9,
+	0x61EF, 0x91CA, 0x61F0, 0x91CB, 0x61F1, 0x91CC, 0x61F2, 0x91CD,
+	0x61F3, 0x91CE, 0x61F4, 0x91CF, 0x61F5, 0xE3C2, 0x61F6, 0x91D0,
+	0x61F7, 0x91D1, 0x61F8, 0x91D2, 0x61F9, 0x91D3, 0x61FA, 0x91D4,
+	0x61FB, 0x91D5, 0x61FC, 0x91D6, 0x61FD, 0x91D7, 0x61FE, 0x91D8,
+	0x61FF, 0xDCB2, 0x6200, 0x91D9, 0x6201, 0x91DA, 0x6202, 0x91DB,
+	0x6203, 0x91DC, 0x6204, 0x91DD, 0x6205, 0x91DE, 0x6206, 0xEDB0,
+	0x6207, 0x91DF, 0x6208, 0xB8EA, 0x6209, 0x91E0, 0x620A, 0xCEEC,
+	0x620B, 0xEAA7, 0x620C, 0xD0E7, 0x620D, 0xCAF9, 0x620E, 0xC8D6,
+	0x620F, 0xCFB7, 0x6210, 0xB3C9, 0x6211, 0xCED2, 0x6212, 0xBDE4,
+	0x6213, 0x91E1, 0x6214, 0x91E2, 0x6215, 0xE3DE, 0x6216, 0xBBF2,
+	0x6217, 0xEAA8, 0x6218, 0xD5BD, 0x6219, 0x91E3, 0x621A, 0xC6DD,
+	0x621B, 0xEAA9, 0x621C, 0x91E4, 0x621D, 0x91E5, 0x621E, 0x91E6,
+	0x621F, 0xEAAA, 0x6220, 0x91E7, 0x6221, 0xEAAC, 0x6222, 0xEAAB,
+	0x6223, 0x91E8, 0x6224, 0xEAAE, 0x6225, 0xEAAD, 0x6226, 0x91E9,
+	0x6227, 0x91EA, 0x6228, 0x91EB, 0x6229, 0x91EC, 0x622A, 0xBDD8,
+	0x622B, 0x91ED, 0x622C, 0xEAAF, 0x622D, 0x91EE, 0x622E, 0xC2BE,
+	0x622F, 0x91EF, 0x6230, 0x91F0, 0x6231, 0x91F1, 0x6232, 0x91F2,
+	0x6233, 0xB4C1, 0x6234, 0xB4F7, 0x6235, 0x91F3, 0x6236, 0x91F4,
+	0x6237, 0xBBA7, 0x6238, 0x91F5, 0x6239, 0x91F6, 0x623A, 0x91F7,
+	0x623B, 0x91F8, 0x623C, 0x91F9, 0x623D, 0xECE6, 0x623E, 0xECE5,
+	0x623F, 0xB7BF, 0x6240, 0xCBF9, 0x6241, 0xB1E2, 0x6242, 0x91FA,
+	0x6243, 0xECE7, 0x6244, 0x91FB, 0x6245, 0x91FC, 0x6246, 0x91FD,
+	0x6247, 0xC9C8, 0x6248, 0xECE8, 0x6249, 0xECE9, 0x624A, 0x91FE,
+	0x624B, 0xCAD6, 0x624C, 0xDED0, 0x624D, 0xB2C5, 0x624E, 0xD4FA,
+	0x624F, 0x9240, 0x6250, 0x9241, 0x6251, 0xC6CB, 0x6252, 0xB0C7,
+	0x6253, 0xB4F2, 0x6254, 0xC8D3, 0x6255, 0x9242, 0x6256, 0x9243,
+	0x6257, 0x9244, 0x6258, 0xCDD0, 0x6259, 0x9245, 0x625A, 0x9246,
+	0x625B, 0xBFB8, 0x625C, 0x9247, 0x625D, 0x9248, 0x625E, 0x9249,
+	0x625F, 0x924A, 0x6260, 0x924B, 0x6261, 0x924C, 0x6262, 0x924D,
+	0x6263, 0xBFDB, 0x6264, 0x924E, 0x6265, 0x924F, 0x6266, 0xC7A4,
+	0x6267, 0xD6B4, 0x6268, 0x9250, 0x6269, 0xC0A9, 0x626A, 0xDED1,
+	0x626B, 0xC9A8, 0x626C, 0xD1EF, 0x626D, 0xC5A4, 0x626E, 0xB0E7,
+	0x626F, 0xB3B6, 0x6270, 0xC8C5, 0x6271, 0x9251, 0x6272, 0x9252,
+	0x6273, 0xB0E2, 0x6274, 0x9253, 0x6275, 0x9254, 0x6276, 0xB7F6,
+	0x6277, 0x9255, 0x6278, 0x9256, 0x6279, 0xC5FA, 0x627A, 0x9257,
+	0x627B, 0x9258, 0x627C, 0xB6F3, 0x627D, 0x9259, 0x627E, 0xD5D2,
+	0x627F, 0xB3D0, 0x6280, 0xBCBC, 0x6281, 0x925A, 0x6282, 0x925B,
+	0x6283, 0x925C, 0x6284, 0xB3AD, 0x6285, 0x925D, 0x6286, 0x925E,
+	0x6287, 0x925F, 0x6288, 0x9260, 0x6289, 0xBEF1, 0x628A, 0xB0D1,
+	0x628B, 0x9261, 0x628C, 0x9262, 0x628D, 0x9263, 0x628E, 0x9264,
+	0x628F, 0x9265, 0x6290, 0x9266, 0x6291, 0xD2D6, 0x6292, 0xCAE3,
+	0x6293, 0xD7A5, 0x6294, 0x9267, 0x6295, 0xCDB6, 0x6296, 0xB6B6,
+	0x6297, 0xBFB9, 0x6298, 0xD5DB, 0x6299, 0x9268, 0x629A, 0xB8A7,
+	0x629B, 0xC5D7, 0x629C, 0x9269, 0x629D, 0x926A, 0x629E, 0x926B,
+	0x629F, 0xDED2, 0x62A0, 0xBFD9, 0x62A1, 0xC2D5, 0x62A2, 0xC7C0,
+	0x62A3, 0x926C, 0x62A4, 0xBBA4, 0x62A5, 0xB1A8, 0x62A6, 0x926D,
+	0x62A7, 0x926E, 0x62A8, 0xC5EA, 0x62A9, 0x926F, 0x62AA, 0x9270,
+	0x62AB, 0xC5FB, 0x62AC, 0xCCA7, 0x62AD, 0x9271, 0x62AE, 0x9272,
+	0x62AF, 0x9273, 0x62B0, 0x9274, 0x62B1, 0xB1A7, 0x62B2, 0x9275,
+	0x62B3, 0x9276, 0x62B4, 0x9277, 0x62B5, 0xB5D6, 0x62B6, 0x9278,
+	0x62B7, 0x9279, 0x62B8, 0x927A, 0x62B9, 0xC4A8, 0x62BA, 0x927B,
+	0x62BB, 0xDED3, 0x62BC, 0xD1BA, 0x62BD, 0xB3E9, 0x62BE, 0x927C,
+	0x62BF, 0xC3F2, 0x62C0, 0x927D, 0x62C1, 0x927E, 0x62C2, 0xB7F7,
+	0x62C3, 0x9280, 0x62C4, 0xD6F4, 0x62C5, 0xB5A3, 0x62C6, 0xB2F0,
+	0x62C7, 0xC4B4, 0x62C8, 0xC4E9, 0x62C9, 0xC0AD, 0x62CA, 0xDED4,
+	0x62CB, 0x9281, 0x62CC, 0xB0E8, 0x62CD, 0xC5C4, 0x62CE, 0xC1E0,
+	0x62CF, 0x9282, 0x62D0, 0xB9D5, 0x62D1, 0x9283, 0x62D2, 0xBEDC,
+	0x62D3, 0xCDD8, 0x62D4, 0xB0CE, 0x62D5, 0x9284, 0x62D6, 0xCDCF,
+	0x62D7, 0xDED6, 0x62D8, 0xBED0, 0x62D9, 0xD7BE, 0x62DA, 0xDED5,
+	0x62DB, 0xD5D0, 0x62DC, 0xB0DD, 0x62DD, 0x9285, 0x62DE, 0x9286,
+	0x62DF, 0xC4E2, 0x62E0, 0x9287, 0x62E1, 0x9288, 0x62E2, 0xC2A3,
+	0x62E3, 0xBCF0, 0x62E4, 0x9289, 0x62E5, 0xD3B5, 0x62E6, 0xC0B9,
+	0x62E7, 0xC5A1, 0x62E8, 0xB2A6, 0x62E9, 0xD4F1, 0x62EA, 0x928A,
+	0x62EB, 0x928B, 0x62EC, 0xC0A8, 0x62ED, 0xCAC3, 0x62EE, 0xDED7,
+	0x62EF, 0xD5FC, 0x62F0, 0x928C, 0x62F1, 0xB9B0, 0x62F2, 0x928D,
+	0x62F3, 0xC8AD, 0x62F4, 0xCBA9, 0x62F5, 0x928E, 0x62F6, 0xDED9,
+	0x62F7, 0xBFBD, 0x62F8, 0x928F, 0x62F9, 0x9290, 0x62FA, 0x9291,
+	0x62FB, 0x9292, 0x62FC, 0xC6B4, 0x62FD, 0xD7A7, 0x62FE, 0xCAB0,
+	0x62FF, 0xC4C3, 0x6300, 0x9293, 0x6301, 0xB3D6, 0x6302, 0xB9D2,
+	0x6303, 0x9294, 0x6304, 0x9295, 0x6305, 0x9296, 0x6306, 0x9297,
+	0x6307, 0xD6B8, 0x6308, 0xEAFC, 0x6309, 0xB0B4, 0x630A, 0x9298,
+	0x630B, 0x9299, 0x630C, 0x929A, 0x630D, 0x929B, 0x630E, 0xBFE6,
+	0x630F, 0x929C, 0x6310, 0x929D, 0x6311, 0xCCF4, 0x6312, 0x929E,
+	0x6313, 0x929F, 0x6314, 0x92A0, 0x6315, 0x92A1, 0x6316, 0xCDDA,
+	0x6317, 0x92A2, 0x6318, 0x92A3, 0x6319, 0x92A4, 0x631A, 0xD6BF,
+	0x631B, 0xC2CE, 0x631C, 0x92A5, 0x631D, 0xCECE, 0x631E, 0xCCA2,
+	0x631F, 0xD0AE, 0x6320, 0xC4D3, 0x6321, 0xB5B2, 0x6322, 0xDED8,
+	0x6323, 0xD5F5, 0x6324, 0xBCB7, 0x6325, 0xBBD3, 0x6326, 0x92A6,
+	0x6327, 0x92A7, 0x6328, 0xB0A4, 0x6329, 0x92A8, 0x632A, 0xC5B2,
+	0x632B, 0xB4EC, 0x632C, 0x92A9, 0x632D, 0x92AA, 0x632E, 0x92AB,
+	0x632F, 0xD5F1, 0x6330, 0x92AC, 0x6331, 0x92AD, 0x6332, 0xEAFD,
+	0x6333, 0x92AE, 0x6334, 0x92AF, 0x6335, 0x92B0, 0x6336, 0x92B1,
+	0x6337, 0x92B2, 0x6338, 0x92B3, 0x6339, 0xDEDA, 0x633A, 0xCDA6,
+	0x633B, 0x92B4, 0x633C, 0x92B5, 0x633D, 0xCDEC, 0x633E, 0x92B6,
+	0x633F, 0x92B7, 0x6340, 0x92B8, 0x6341, 0x92B9, 0x6342, 0xCEE6,
+	0x6343, 0xDEDC, 0x6344, 0x92BA, 0x6345, 0xCDB1, 0x6346, 0xC0A6,
+	0x6347, 0x92BB, 0x6348, 0x92BC, 0x6349, 0xD7BD, 0x634A, 0x92BD,
+	0x634B, 0xDEDB, 0x634C, 0xB0C6, 0x634D, 0xBAB4, 0x634E, 0xC9D3,
+	0x634F, 0xC4F3, 0x6350, 0xBEE8, 0x6351, 0x92BE, 0x6352, 0x92BF,
+	0x6353, 0x92C0, 0x6354, 0x92C1, 0x6355, 0xB2B6, 0x6356, 0x92C2,
+	0x6357, 0x92C3, 0x6358, 0x92C4, 0x6359, 0x92C5, 0x635A, 0x92C6,
+	0x635B, 0x92C7, 0x635C, 0x92C8, 0x635D, 0x92C9, 0x635E, 0xC0CC,
+	0x635F, 0xCBF0, 0x6360, 0x92CA, 0x6361, 0xBCF1, 0x6362, 0xBBBB,
+	0x6363, 0xB5B7, 0x6364, 0x92CB, 0x6365, 0x92CC, 0x6366, 0x92CD,
+	0x6367, 0xC5F5, 0x6368, 0x92CE, 0x6369, 0xDEE6, 0x636A, 0x92CF,
+	0x636B, 0x92D0, 0x636C, 0x92D1, 0x636D, 0xDEE3, 0x636E, 0xBEDD,
+	0x636F, 0x92D2, 0x6370, 0x92D3, 0x6371, 0xDEDF, 0x6372, 0x92D4,
+	0x6373, 0x92D5, 0x6374, 0x92D6, 0x6375, 0x92D7, 0x6376, 0xB4B7,
+	0x6377, 0xBDDD, 0x6378, 0x92D8, 0x6379, 0x92D9, 0x637A, 0xDEE0,
+	0x637B, 0xC4ED, 0x637C, 0x92DA, 0x637D, 0x92DB, 0x637E, 0x92DC,
+	0x637F, 0x92DD, 0x6380, 0xCFC6, 0x6381, 0x92DE, 0x6382, 0xB5E0,
+	0x6383, 0x92DF, 0x6384, 0x92E0, 0x6385, 0x92E1, 0x6386, 0x92E2,
+	0x6387, 0xB6DE, 0x6388, 0xCADA, 0x6389, 0xB5F4, 0x638A, 0xDEE5,
+	0x638B, 0x92E3, 0x638C, 0xD5C6, 0x638D, 0x92E4, 0x638E, 0xDEE1,
+	0x638F, 0xCCCD, 0x6390, 0xC6FE, 0x6391, 0x92E5, 0x6392, 0xC5C5,
+	0x6393, 0x92E6, 0x6394, 0x92E7, 0x6395, 0x92E8, 0x6396, 0xD2B4,
+	0x6397, 0x92E9, 0x6398, 0xBEF2, 0x6399, 0x92EA, 0x639A, 0x92EB,
+	0x639B, 0x92EC, 0x639C, 0x92ED, 0x639D, 0x92EE, 0x639E, 0x92EF,
+	0x639F, 0x92F0, 0x63A0, 0xC2D3, 0x63A1, 0x92F1, 0x63A2, 0xCCBD,
+	0x63A3, 0xB3B8, 0x63A4, 0x92F2, 0x63A5, 0xBDD3, 0x63A6, 0x92F3,
+	0x63A7, 0xBFD8, 0x63A8, 0xCDC6, 0x63A9, 0xD1DA, 0x63AA, 0xB4EB,
+	0x63AB, 0x92F4, 0x63AC, 0xDEE4, 0x63AD, 0xDEDD, 0x63AE, 0xDEE7,
+	0x63AF, 0x92F5, 0x63B0, 0xEAFE, 0x63B1, 0x92F6, 0x63B2, 0x92F7,
+	0x63B3, 0xC2B0, 0x63B4, 0xDEE2, 0x63B5, 0x92F8, 0x63B6, 0x92F9,
+	0x63B7, 0xD6C0, 0x63B8, 0xB5A7, 0x63B9, 0x92FA, 0x63BA, 0xB2F4,
+	0x63BB, 0x92FB, 0x63BC, 0xDEE8, 0x63BD, 0x92FC, 0x63BE, 0xDEF2,
+	0x63BF, 0x92FD, 0x63C0, 0x92FE, 0x63C1, 0x9340, 0x63C2, 0x9341,
+	0x63C3, 0x9342, 0x63C4, 0xDEED, 0x63C5, 0x9343, 0x63C6, 0xDEF1,
+	0x63C7, 0x9344, 0x63C8, 0x9345, 0x63C9, 0xC8E0, 0x63CA, 0x9346,
+	0x63CB, 0x9347, 0x63CC, 0x9348, 0x63CD, 0xD7E1, 0x63CE, 0xDEEF,
+	0x63CF, 0xC3E8, 0x63D0, 0xCCE1, 0x63D1, 0x9349, 0x63D2, 0xB2E5,
+	0x63D3, 0x934A, 0x63D4, 0x934B, 0x63D5, 0x934C, 0x63D6, 0xD2BE,
+	0x63D7, 0x934D, 0x63D8, 0x934E, 0x63D9, 0x934F, 0x63DA, 0x9350,
+	0x63DB, 0x9351, 0x63DC, 0x9352, 0x63DD, 0x9353, 0x63DE, 0xDEEE,
+	0x63DF, 0x9354, 0x63E0, 0xDEEB, 0x63E1, 0xCED5, 0x63E2, 0x9355,
+	0x63E3, 0xB4A7, 0x63E4, 0x9356, 0x63E5, 0x9357, 0x63E6, 0x9358,
+	0x63E7, 0x9359, 0x63E8, 0x935A, 0x63E9, 0xBFAB, 0x63EA, 0xBEBE,
+	0x63EB, 0x935B, 0x63EC, 0x935C, 0x63ED, 0xBDD2, 0x63EE, 0x935D,
+	0x63EF, 0x935E, 0x63F0, 0x935F, 0x63F1, 0x9360, 0x63F2, 0xDEE9,
+	0x63F3, 0x9361, 0x63F4, 0xD4AE, 0x63F5, 0x9362, 0x63F6, 0xDEDE,
+	0x63F7, 0x9363, 0x63F8, 0xDEEA, 0x63F9, 0x9364, 0x63FA, 0x9365,
+	0x63FB, 0x9366, 0x63FC, 0x9367, 0x63FD, 0xC0BF, 0x63FE, 0x9368,
+	0x63FF, 0xDEEC, 0x6400, 0xB2F3, 0x6401, 0xB8E9, 0x6402, 0xC2A7,
+	0x6403, 0x9369, 0x6404, 0x936A, 0x6405, 0xBDC1, 0x6406, 0x936B,
+	0x6407, 0x936C, 0x6408, 0x936D, 0x6409, 0x936E, 0x640A, 0x936F,
+	0x640B, 0xDEF5, 0x640C, 0xDEF8, 0x640D, 0x9370, 0x640E, 0x9371,
+	0x640F, 0xB2AB, 0x6410, 0xB4A4, 0x6411, 0x9372, 0x6412, 0x9373,
+	0x6413, 0xB4EA, 0x6414, 0xC9A6, 0x6415, 0x9374, 0x6416, 0x9375,
+	0x6417, 0x9376, 0x6418, 0x9377, 0x6419, 0x9378, 0x641A, 0x9379,
+	0x641B, 0xDEF6, 0x641C, 0xCBD1, 0x641D, 0x937A, 0x641E, 0xB8E3,
+	0x641F, 0x937B, 0x6420, 0xDEF7, 0x6421, 0xDEFA, 0x6422, 0x937C,
+	0x6423, 0x937D, 0x6424, 0x937E, 0x6425, 0x9380, 0x6426, 0xDEF9,
+	0x6427, 0x9381, 0x6428, 0x9382, 0x6429, 0x9383, 0x642A, 0xCCC2,
+	0x642B, 0x9384, 0x642C, 0xB0E1, 0x642D, 0xB4EE, 0x642E, 0x9385,
+	0x642F, 0x9386, 0x6430, 0x9387, 0x6431, 0x9388, 0x6432, 0x9389,
+	0x6433, 0x938A, 0x6434, 0xE5BA, 0x6435, 0x938B, 0x6436, 0x938C,
+	0x6437, 0x938D, 0x6438, 0x938E, 0x6439, 0x938F, 0x643A, 0xD0AF,
+	0x643B, 0x9390, 0x643C, 0x9391, 0x643D, 0xB2EB, 0x643E, 0x9392,
+	0x643F, 0xEBA1, 0x6440, 0x9393, 0x6441, 0xDEF4, 0x6442, 0x9394,
+	0x6443, 0x9395, 0x6444, 0xC9E3, 0x6445, 0xDEF3, 0x6446, 0xB0DA,
+	0x6447, 0xD2A1, 0x6448, 0xB1F7, 0x6449, 0x9396, 0x644A, 0xCCAF,
+	0x644B, 0x9397, 0x644C, 0x9398, 0x644D, 0x9399, 0x644E, 0x939A,
+	0x644F, 0x939B, 0x6450, 0x939C, 0x6451, 0x939D, 0x6452, 0xDEF0,
+	0x6453, 0x939E, 0x6454, 0xCBA4, 0x6455, 0x939F, 0x6456, 0x93A0,
+	0x6457, 0x93A1, 0x6458, 0xD5AA, 0x6459, 0x93A2, 0x645A, 0x93A3,
+	0x645B, 0x93A4, 0x645C, 0x93A5, 0x645D, 0x93A6, 0x645E, 0xDEFB,
+	0x645F, 0x93A7, 0x6460, 0x93A8, 0x6461, 0x93A9, 0x6462, 0x93AA,
+	0x6463, 0x93AB, 0x6464, 0x93AC, 0x6465, 0x93AD, 0x6466, 0x93AE,
+	0x6467, 0xB4DD, 0x6468, 0x93AF, 0x6469, 0xC4A6, 0x646A, 0x93B0,
+	0x646B, 0x93B1, 0x646C, 0x93B2, 0x646D, 0xDEFD, 0x646E, 0x93B3,
+	0x646F, 0x93B4, 0x6470, 0x93B5, 0x6471, 0x93B6, 0x6472, 0x93B7,
+	0x6473, 0x93B8, 0x6474, 0x93B9, 0x6475, 0x93BA, 0x6476, 0x93BB,
+	0x6477, 0x93BC, 0x6478, 0xC3FE, 0x6479, 0xC4A1, 0x647A, 0xDFA1,
+	0x647B, 0x93BD, 0x647C, 0x93BE, 0x647D, 0x93BF, 0x647E, 0x93C0,
+	0x647F, 0x93C1, 0x6480, 0x93C2, 0x6481, 0x93C3, 0x6482, 0xC1CC,
+	0x6483, 0x93C4, 0x6484, 0xDEFC, 0x6485, 0xBEEF, 0x6486, 0x93C5,
+	0x6487, 0xC6B2, 0x6488, 0x93C6, 0x6489, 0x93C7, 0x648A, 0x93C8,
+	0x648B, 0x93C9, 0x648C, 0x93CA, 0x648D, 0x93CB, 0x648E, 0x93CC,
+	0x648F, 0x93CD, 0x6490, 0x93CE, 0x6491, 0xB3C5, 0x6492, 0xC8F6,
+	0x6493, 0x93CF, 0x6494, 0x93D0, 0x6495, 0xCBBA, 0x6496, 0xDEFE,
+	0x6497, 0x93D1, 0x6498, 0x93D2, 0x6499, 0xDFA4, 0x649A, 0x93D3,
+	0x649B, 0x93D4, 0x649C, 0x93D5, 0x649D, 0x93D6, 0x649E, 0xD7B2,
+	0x649F, 0x93D7, 0x64A0, 0x93D8, 0x64A1, 0x93D9, 0x64A2, 0x93DA,
+	0x64A3, 0x93DB, 0x64A4, 0xB3B7, 0x64A5, 0x93DC, 0x64A6, 0x93DD,
+	0x64A7, 0x93DE, 0x64A8, 0x93DF, 0x64A9, 0xC1C3, 0x64AA, 0x93E0,
+	0x64AB, 0x93E1, 0x64AC, 0xC7CB, 0x64AD, 0xB2A5, 0x64AE, 0xB4E9,
+	0x64AF, 0x93E2, 0x64B0, 0xD7AB, 0x64B1, 0x93E3, 0x64B2, 0x93E4,
+	0x64B3, 0x93E5, 0x64B4, 0x93E6, 0x64B5, 0xC4EC, 0x64B6, 0x93E7,
+	0x64B7, 0xDFA2, 0x64B8, 0xDFA3, 0x64B9, 0x93E8, 0x64BA, 0xDFA5,
+	0x64BB, 0x93E9, 0x64BC, 0xBAB3, 0x64BD, 0x93EA, 0x64BE, 0x93EB,
+	0x64BF, 0x93EC, 0x64C0, 0xDFA6, 0x64C1, 0x93ED, 0x64C2, 0xC0DE,
+	0x64C3, 0x93EE, 0x64C4, 0x93EF, 0x64C5, 0xC9C3, 0x64C6, 0x93F0,
+	0x64C7, 0x93F1, 0x64C8, 0x93F2, 0x64C9, 0x93F3, 0x64CA, 0x93F4,
+	0x64CB, 0x93F5, 0x64CC, 0x93F6, 0x64CD, 0xB2D9, 0x64CE, 0xC7E6,
+	0x64CF, 0x93F7, 0x64D0, 0xDFA7, 0x64D1, 0x93F8, 0x64D2, 0xC7DC,
+	0x64D3, 0x93F9, 0x64D4, 0x93FA, 0x64D5, 0x93FB, 0x64D6, 0x93FC,
+	0x64D7, 0xDFA8, 0x64D8, 0xEBA2, 0x64D9, 0x93FD, 0x64DA, 0x93FE,
+	0x64DB, 0x9440, 0x64DC, 0x9441, 0x64DD, 0x9442, 0x64DE, 0xCBD3,
+	0x64DF, 0x9443, 0x64E0, 0x9444, 0x64E1, 0x9445, 0x64E2, 0xDFAA,
+	0x64E3, 0x9446, 0x64E4, 0xDFA9, 0x64E5, 0x9447, 0x64E6, 0xB2C1,
+	0x64E7, 0x9448, 0x64E8, 0x9449, 0x64E9, 0x944A, 0x64EA, 0x944B,
+	0x64EB, 0x944C, 0x64EC, 0x944D, 0x64ED, 0x944E, 0x64EE, 0x944F,
+	0x64EF, 0x9450, 0x64F0, 0x9451, 0x64F1, 0x9452, 0x64F2, 0x9453,
+	0x64F3, 0x9454, 0x64F4, 0x9455, 0x64F5, 0x9456, 0x64F6, 0x9457,
+	0x64F7, 0x9458, 0x64F8, 0x9459, 0x64F9, 0x945A, 0x64FA, 0x945B,
+	0x64FB, 0x945C, 0x64FC, 0x945D, 0x64FD, 0x945E, 0x64FE, 0x945F,
+	0x64FF, 0x9460, 0x6500, 0xC5CA, 0x6501, 0x9461, 0x6502, 0x9462,
+	0x6503, 0x9463, 0x6504, 0x9464, 0x6505, 0x9465, 0x6506, 0x9466,
+	0x6507, 0x9467, 0x6508, 0x9468, 0x6509, 0xDFAB, 0x650A, 0x9469,
+	0x650B, 0x946A, 0x650C, 0x946B, 0x650D, 0x946C, 0x650E, 0x946D,
+	0x650F, 0x946E, 0x6510, 0x946F, 0x6511, 0x9470, 0x6512, 0xD4DC,
+	0x6513, 0x9471, 0x6514, 0x9472, 0x6515, 0x9473, 0x6516, 0x9474,
+	0x6517, 0x9475, 0x6518, 0xC8C1, 0x6519, 0x9476, 0x651A, 0x9477,
+	0x651B, 0x9478, 0x651C, 0x9479, 0x651D, 0x947A, 0x651E, 0x947B,
+	0x651F, 0x947C, 0x6520, 0x947D, 0x6521, 0x947E, 0x6522, 0x9480,
+	0x6523, 0x9481, 0x6524, 0x9482, 0x6525, 0xDFAC, 0x6526, 0x9483,
+	0x6527, 0x9484, 0x6528, 0x9485, 0x6529, 0x9486, 0x652A, 0x9487,
+	0x652B, 0xBEF0, 0x652C, 0x9488, 0x652D, 0x9489, 0x652E, 0xDFAD,
+	0x652F, 0xD6A7, 0x6530, 0x948A, 0x6531, 0x948B, 0x6532, 0x948C,
+	0x6533, 0x948D, 0x6534, 0xEAB7, 0x6535, 0xEBB6, 0x6536, 0xCAD5,
+	0x6537, 0x948E, 0x6538, 0xD8FC, 0x6539, 0xB8C4, 0x653A, 0x948F,
+	0x653B, 0xB9A5, 0x653C, 0x9490, 0x653D, 0x9491, 0x653E, 0xB7C5,
+	0x653F, 0xD5FE, 0x6540, 0x9492, 0x6541, 0x9493, 0x6542, 0x9494,
+	0x6543, 0x9495, 0x6544, 0x9496, 0x6545, 0xB9CA, 0x6546, 0x9497,
+	0x6547, 0x9498, 0x6548, 0xD0A7, 0x6549, 0xF4CD, 0x654A, 0x9499,
+	0x654B, 0x949A, 0x654C, 0xB5D0, 0x654D, 0x949B, 0x654E, 0x949C,
+	0x654F, 0xC3F4, 0x6550, 0x949D, 0x6551, 0xBEC8, 0x6552, 0x949E,
+	0x6553, 0x949F, 0x6554, 0x94A0, 0x6555, 0xEBB7, 0x6556, 0xB0BD,
+	0x6557, 0x94A1, 0x6558, 0x94A2, 0x6559, 0xBDCC, 0x655A, 0x94A3,
+	0x655B, 0xC1B2, 0x655C, 0x94A4, 0x655D, 0xB1D6, 0x655E, 0xB3A8,
+	0x655F, 0x94A5, 0x6560, 0x94A6, 0x6561, 0x94A7, 0x6562, 0xB8D2,
+	0x6563, 0xC9A2, 0x6564, 0x94A8, 0x6565, 0x94A9, 0x6566, 0xB6D8,
+	0x6567, 0x94AA, 0x6568, 0x94AB, 0x6569, 0x94AC, 0x656A, 0x94AD,
+	0x656B, 0xEBB8, 0x656C, 0xBEB4, 0x656D, 0x94AE, 0x656E, 0x94AF,
+	0x656F, 0x94B0, 0x6570, 0xCAFD, 0x6571, 0x94B1, 0x6572, 0xC7C3,
+	0x6573, 0x94B2, 0x6574, 0xD5FB, 0x6575, 0x94B3, 0x6576, 0x94B4,
+	0x6577, 0xB7F3, 0x6578, 0x94B5, 0x6579, 0x94B6, 0x657A, 0x94B7,
+	0x657B, 0x94B8, 0x657C, 0x94B9, 0x657D, 0x94BA, 0x657E, 0x94BB,
+	0x657F, 0x94BC, 0x6580, 0x94BD, 0x6581, 0x94BE, 0x6582, 0x94BF,
+	0x6583, 0x94C0, 0x6584, 0x94C1, 0x6585, 0x94C2, 0x6586, 0x94C3,
+	0x6587, 0xCEC4, 0x6588, 0x94C4, 0x6589, 0x94C5, 0x658A, 0x94C6,
+	0x658B, 0xD5AB, 0x658C, 0xB1F3, 0x658D, 0x94C7, 0x658E, 0x94C8,
+	0x658F, 0x94C9, 0x6590, 0xECB3, 0x6591, 0xB0DF, 0x6592, 0x94CA,
+	0x6593, 0xECB5, 0x6594, 0x94CB, 0x6595, 0x94CC, 0x6596, 0x94CD,
+	0x6597, 0xB6B7, 0x6598, 0x94CE, 0x6599, 0xC1CF, 0x659A, 0x94CF,
+	0x659B, 0xF5FA, 0x659C, 0xD0B1, 0x659D, 0x94D0, 0x659E, 0x94D1,
+	0x659F, 0xD5E5, 0x65A0, 0x94D2, 0x65A1, 0xCED3, 0x65A2, 0x94D3,
+	0x65A3, 0x94D4, 0x65A4, 0xBDEF, 0x65A5, 0xB3E2, 0x65A6, 0x94D5,
+	0x65A7, 0xB8AB, 0x65A8, 0x94D6, 0x65A9, 0xD5B6, 0x65AA, 0x94D7,
+	0x65AB, 0xEDBD, 0x65AC, 0x94D8, 0x65AD, 0xB6CF, 0x65AE, 0x94D9,
+	0x65AF, 0xCBB9, 0x65B0, 0xD0C2, 0x65B1, 0x94DA, 0x65B2, 0x94DB,
+	0x65B3, 0x94DC, 0x65B4, 0x94DD, 0x65B5, 0x94DE, 0x65B6, 0x94DF,
+	0x65B7, 0x94E0, 0x65B8, 0x94E1, 0x65B9, 0xB7BD, 0x65BA, 0x94E2,
+	0x65BB, 0x94E3, 0x65BC, 0xECB6, 0x65BD, 0xCAA9, 0x65BE, 0x94E4,
+	0x65BF, 0x94E5, 0x65C0, 0x94E6, 0x65C1, 0xC5D4, 0x65C2, 0x94E7,
+	0x65C3, 0xECB9, 0x65C4, 0xECB8, 0x65C5, 0xC2C3, 0x65C6, 0xECB7,
+	0x65C7, 0x94E8, 0x65C8, 0x94E9, 0x65C9, 0x94EA, 0x65CA, 0x94EB,
+	0x65CB, 0xD0FD, 0x65CC, 0xECBA, 0x65CD, 0x94EC, 0x65CE, 0xECBB,
+	0x65CF, 0xD7E5, 0x65D0, 0x94ED, 0x65D1, 0x94EE, 0x65D2, 0xECBC,
+	0x65D3, 0x94EF, 0x65D4, 0x94F0, 0x65D5, 0x94F1, 0x65D6, 0xECBD,
+	0x65D7, 0xC6EC, 0x65D8, 0x94F2, 0x65D9, 0x94F3, 0x65DA, 0x94F4,
+	0x65DB, 0x94F5, 0x65DC, 0x94F6, 0x65DD, 0x94F7, 0x65DE, 0x94F8,
+	0x65DF, 0x94F9, 0x65E0, 0xCEDE, 0x65E1, 0x94FA, 0x65E2, 0xBCC8,
+	0x65E3, 0x94FB, 0x65E4, 0x94FC, 0x65E5, 0xC8D5, 0x65E6, 0xB5A9,
+	0x65E7, 0xBEC9, 0x65E8, 0xD6BC, 0x65E9, 0xD4E7, 0x65EA, 0x94FD,
+	0x65EB, 0x94FE, 0x65EC, 0xD1AE, 0x65ED, 0xD0F1, 0x65EE, 0xEAB8,
+	0x65EF, 0xEAB9, 0x65F0, 0xEABA, 0x65F1, 0xBAB5, 0x65F2, 0x9540,
+	0x65F3, 0x9541, 0x65F4, 0x9542, 0x65F5, 0x9543, 0x65F6, 0xCAB1,
+	0x65F7, 0xBFF5, 0x65F8, 0x9544, 0x65F9, 0x9545, 0x65FA, 0xCDFA,
+	0x65FB, 0x9546, 0x65FC, 0x9547, 0x65FD, 0x9548, 0x65FE, 0x9549,
+	0x65FF, 0x954A, 0x6600, 0xEAC0, 0x6601, 0x954B, 0x6602, 0xB0BA,
+	0x6603, 0xEABE, 0x6604, 0x954C, 0x6605, 0x954D, 0x6606, 0xC0A5,
+	0x6607, 0x954E, 0x6608, 0x954F, 0x6609, 0x9550, 0x660A, 0xEABB,
+	0x660B, 0x9551, 0x660C, 0xB2FD, 0x660D, 0x9552, 0x660E, 0xC3F7,
+	0x660F, 0xBBE8, 0x6610, 0x9553, 0x6611, 0x9554, 0x6612, 0x9555,
+	0x6613, 0xD2D7, 0x6614, 0xCEF4, 0x6615, 0xEABF, 0x6616, 0x9556,
+	0x6617, 0x9557, 0x6618, 0x9558, 0x6619, 0xEABC, 0x661A, 0x9559,
+	0x661B, 0x955A, 0x661C, 0x955B, 0x661D, 0xEAC3, 0x661E, 0x955C,
+	0x661F, 0xD0C7, 0x6620, 0xD3B3, 0x6621, 0x955D, 0x6622, 0x955E,
+	0x6623, 0x955F, 0x6624, 0x9560, 0x6625, 0xB4BA, 0x6626, 0x9561,
+	0x6627, 0xC3C1, 0x6628, 0xD7F2, 0x6629, 0x9562, 0x662A, 0x9563,
+	0x662B, 0x9564, 0x662C, 0x9565, 0x662D, 0xD5D1, 0x662E, 0x9566,
+	0x662F, 0xCAC7, 0x6630, 0x9567, 0x6631, 0xEAC5, 0x6632, 0x9568,
+	0x6633, 0x9569, 0x6634, 0xEAC4, 0x6635, 0xEAC7, 0x6636, 0xEAC6,
+	0x6637, 0x956A, 0x6638, 0x956B, 0x6639, 0x956C, 0x663A, 0x956D,
+	0x663B, 0x956E, 0x663C, 0xD6E7, 0x663D, 0x956F, 0x663E, 0xCFD4,
+	0x663F, 0x9570, 0x6640, 0x9571, 0x6641, 0xEACB, 0x6642, 0x9572,
+	0x6643, 0xBBCE, 0x6644, 0x9573, 0x6645, 0x9574, 0x6646, 0x9575,
+	0x6647, 0x9576, 0x6648, 0x9577, 0x6649, 0x9578, 0x664A, 0x9579,
+	0x664B, 0xBDFA, 0x664C, 0xC9CE, 0x664D, 0x957A, 0x664E, 0x957B,
+	0x664F, 0xEACC, 0x6650, 0x957C, 0x6651, 0x957D, 0x6652, 0xC9B9,
+	0x6653, 0xCFFE, 0x6654, 0xEACA, 0x6655, 0xD4CE, 0x6656, 0xEACD,
+	0x6657, 0xEACF, 0x6658, 0x957E, 0x6659, 0x9580, 0x665A, 0xCDED,
+	0x665B, 0x9581, 0x665C, 0x9582, 0x665D, 0x9583, 0x665E, 0x9584,
+	0x665F, 0xEAC9, 0x6660, 0x9585, 0x6661, 0xEACE, 0x6662, 0x9586,
+	0x6663, 0x9587, 0x6664, 0xCEEE, 0x6665, 0x9588, 0x6666, 0xBBDE,
+	0x6667, 0x9589, 0x6668, 0xB3BF, 0x6669, 0x958A, 0x666A, 0x958B,
+	0x666B, 0x958C, 0x666C, 0x958D, 0x666D, 0x958E, 0x666E, 0xC6D5,
+	0x666F, 0xBEB0, 0x6670, 0xCEFA, 0x6671, 0x958F, 0x6672, 0x9590,
+	0x6673, 0x9591, 0x6674, 0xC7E7, 0x6675, 0x9592, 0x6676, 0xBEA7,
+	0x6677, 0xEAD0, 0x6678, 0x9593, 0x6679, 0x9594, 0x667A, 0xD6C7,
+	0x667B, 0x9595, 0x667C, 0x9596, 0x667D, 0x9597, 0x667E, 0xC1C0,
+	0x667F, 0x9598, 0x6680, 0x9599, 0x6681, 0x959A, 0x6682, 0xD4DD,
+	0x6683, 0x959B, 0x6684, 0xEAD1, 0x6685, 0x959C, 0x6686, 0x959D,
+	0x6687, 0xCFBE, 0x6688, 0x959E, 0x6689, 0x959F, 0x668A, 0x95A0,
+	0x668B, 0x95A1, 0x668C, 0xEAD2, 0x668D, 0x95A2, 0x668E, 0x95A3,
+	0x668F, 0x95A4, 0x6690, 0x95A5, 0x6691, 0xCAEE, 0x6692, 0x95A6,
+	0x6693, 0x95A7, 0x6694, 0x95A8, 0x6695, 0x95A9, 0x6696, 0xC5AF,
+	0x6697, 0xB0B5, 0x6698, 0x95AA, 0x6699, 0x95AB, 0x669A, 0x95AC,
+	0x669B, 0x95AD, 0x669C, 0x95AE, 0x669D, 0xEAD4, 0x669E, 0x95AF,
+	0x669F, 0x95B0, 0x66A0, 0x95B1, 0x66A1, 0x95B2, 0x66A2, 0x95B3,
+	0x66A3, 0x95B4, 0x66A4, 0x95B5, 0x66A5, 0x95B6, 0x66A6, 0x95B7,
+	0x66A7, 0xEAD3, 0x66A8, 0xF4DF, 0x66A9, 0x95B8, 0x66AA, 0x95B9,
+	0x66AB, 0x95BA, 0x66AC, 0x95BB, 0x66AD, 0x95BC, 0x66AE, 0xC4BA,
+	0x66AF, 0x95BD, 0x66B0, 0x95BE, 0x66B1, 0x95BF, 0x66B2, 0x95C0,
+	0x66B3, 0x95C1, 0x66B4, 0xB1A9, 0x66B5, 0x95C2, 0x66B6, 0x95C3,
+	0x66B7, 0x95C4, 0x66B8, 0x95C5, 0x66B9, 0xE5DF, 0x66BA, 0x95C6,
+	0x66BB, 0x95C7, 0x66BC, 0x95C8, 0x66BD, 0x95C9, 0x66BE, 0xEAD5,
+	0x66BF, 0x95CA, 0x66C0, 0x95CB, 0x66C1, 0x95CC, 0x66C2, 0x95CD,
+	0x66C3, 0x95CE, 0x66C4, 0x95CF, 0x66C5, 0x95D0, 0x66C6, 0x95D1,
+	0x66C7, 0x95D2, 0x66C8, 0x95D3, 0x66C9, 0x95D4, 0x66CA, 0x95D5,
+	0x66CB, 0x95D6, 0x66CC, 0x95D7, 0x66CD, 0x95D8, 0x66CE, 0x95D9,
+	0x66CF, 0x95DA, 0x66D0, 0x95DB, 0x66D1, 0x95DC, 0x66D2, 0x95DD,
+	0x66D3, 0x95DE, 0x66D4, 0x95DF, 0x66D5, 0x95E0, 0x66D6, 0x95E1,
+	0x66D7, 0x95E2, 0x66D8, 0x95E3, 0x66D9, 0xCAEF, 0x66DA, 0x95E4,
+	0x66DB, 0xEAD6, 0x66DC, 0xEAD7, 0x66DD, 0xC6D8, 0x66DE, 0x95E5,
+	0x66DF, 0x95E6, 0x66E0, 0x95E7, 0x66E1, 0x95E8, 0x66E2, 0x95E9,
+	0x66E3, 0x95EA, 0x66E4, 0x95EB, 0x66E5, 0x95EC, 0x66E6, 0xEAD8,
+	0x66E7, 0x95ED, 0x66E8, 0x95EE, 0x66E9, 0xEAD9, 0x66EA, 0x95EF,
+	0x66EB, 0x95F0, 0x66EC, 0x95F1, 0x66ED, 0x95F2, 0x66EE, 0x95F3,
+	0x66EF, 0x95F4, 0x66F0, 0xD4BB, 0x66F1, 0x95F5, 0x66F2, 0xC7FA,
+	0x66F3, 0xD2B7, 0x66F4, 0xB8FC, 0x66F5, 0x95F6, 0x66F6, 0x95F7,
+	0x66F7, 0xEAC2, 0x66F8, 0x95F8, 0x66F9, 0xB2DC, 0x66FA, 0x95F9,
+	0x66FB, 0x95FA, 0x66FC, 0xC2FC, 0x66FD, 0x95FB, 0x66FE, 0xD4F8,
+	0x66FF, 0xCCE6, 0x6700, 0xD7EE, 0x6701, 0x95FC, 0x6702, 0x95FD,
+	0x6703, 0x95FE, 0x6704, 0x9640, 0x6705, 0x9641, 0x6706, 0x9642,
+	0x6707, 0x9643, 0x6708, 0xD4C2, 0x6709, 0xD3D0, 0x670A, 0xEBC3,
+	0x670B, 0xC5F3, 0x670C, 0x9644, 0x670D, 0xB7FE, 0x670E, 0x9645,
+	0x670F, 0x9646, 0x6710, 0xEBD4, 0x6711, 0x9647, 0x6712, 0x9648,
+	0x6713, 0x9649, 0x6714, 0xCBB7, 0x6715, 0xEBDE, 0x6716, 0x964A,
+	0x6717, 0xC0CA, 0x6718, 0x964B, 0x6719, 0x964C, 0x671A, 0x964D,
+	0x671B, 0xCDFB, 0x671C, 0x964E, 0x671D, 0xB3AF, 0x671E, 0x964F,
+	0x671F, 0xC6DA, 0x6720, 0x9650, 0x6721, 0x9651, 0x6722, 0x9652,
+	0x6723, 0x9653, 0x6724, 0x9654, 0x6725, 0x9655, 0x6726, 0xEBFC,
+	0x6727, 0x9656, 0x6728, 0xC4BE, 0x6729, 0x9657, 0x672A, 0xCEB4,
+	0x672B, 0xC4A9, 0x672C, 0xB1BE, 0x672D, 0xD4FD, 0x672E, 0x9658,
+	0x672F, 0xCAF5, 0x6730, 0x9659, 0x6731, 0xD6EC, 0x6732, 0x965A,
+	0x6733, 0x965B, 0x6734, 0xC6D3, 0x6735, 0xB6E4, 0x6736, 0x965C,
+	0x6737, 0x965D, 0x6738, 0x965E, 0x6739, 0x965F, 0x673A, 0xBBFA,
+	0x673B, 0x9660, 0x673C, 0x9661, 0x673D, 0xD0E0, 0x673E, 0x9662,
+	0x673F, 0x9663, 0x6740, 0xC9B1, 0x6741, 0x9664, 0x6742, 0xD4D3,
+	0x6743, 0xC8A8, 0x6744, 0x9665, 0x6745, 0x9666, 0x6746, 0xB8CB,
+	0x6747, 0x9667, 0x6748, 0xE8BE, 0x6749, 0xC9BC, 0x674A, 0x9668,
+	0x674B, 0x9669, 0x674C, 0xE8BB, 0x674D, 0x966A, 0x674E, 0xC0EE,
+	0x674F, 0xD0D3, 0x6750, 0xB2C4, 0x6751, 0xB4E5, 0x6752, 0x966B,
+	0x6753, 0xE8BC, 0x6754, 0x966C, 0x6755, 0x966D, 0x6756, 0xD5C8,
+	0x6757, 0x966E, 0x6758, 0x966F, 0x6759, 0x9670, 0x675A, 0x9671,
+	0x675B, 0x9672, 0x675C, 0xB6C5, 0x675D, 0x9673, 0x675E, 0xE8BD,
+	0x675F, 0xCAF8, 0x6760, 0xB8DC, 0x6761, 0xCCF5, 0x6762, 0x9674,
+	0x6763, 0x9675, 0x6764, 0x9676, 0x6765, 0xC0B4, 0x6766, 0x9677,
+	0x6767, 0x9678, 0x6768, 0xD1EE, 0x6769, 0xE8BF, 0x676A, 0xE8C2,
+	0x676B, 0x9679, 0x676C, 0x967A, 0x676D, 0xBABC, 0x676E, 0x967B,
+	0x676F, 0xB1AD, 0x6770, 0xBDDC, 0x6771, 0x967C, 0x6772, 0xEABD,
+	0x6773, 0xE8C3, 0x6774, 0x967D, 0x6775, 0xE8C6, 0x6776, 0x967E,
+	0x6777, 0xE8CB, 0x6778, 0x9680, 0x6779, 0x9681, 0x677A, 0x9682,
+	0x677B, 0x9683, 0x677C, 0xE8CC, 0x677D, 0x9684, 0x677E, 0xCBC9,
+	0x677F, 0xB0E5, 0x6780, 0x9685, 0x6781, 0xBCAB, 0x6782, 0x9686,
+	0x6783, 0x9687, 0x6784, 0xB9B9, 0x6785, 0x9688, 0x6786, 0x9689,
+	0x6787, 0xE8C1, 0x6788, 0x968A, 0x6789, 0xCDF7, 0x678A, 0x968B,
+	0x678B, 0xE8CA, 0x678C, 0x968C, 0x678D, 0x968D, 0x678E, 0x968E,
+	0x678F, 0x968F, 0x6790, 0xCEF6, 0x6791, 0x9690, 0x6792, 0x9691,
+	0x6793, 0x9692, 0x6794, 0x9693, 0x6795, 0xD5ED, 0x6796, 0x9694,
+	0x6797, 0xC1D6, 0x6798, 0xE8C4, 0x6799, 0x9695, 0x679A, 0xC3B6,
+	0x679B, 0x9696, 0x679C, 0xB9FB, 0x679D, 0xD6A6, 0x679E, 0xE8C8,
+	0x679F, 0x9697, 0x67A0, 0x9698, 0x67A1, 0x9699, 0x67A2, 0xCAE0,
+	0x67A3, 0xD4E6, 0x67A4, 0x969A, 0x67A5, 0xE8C0, 0x67A6, 0x969B,
+	0x67A7, 0xE8C5, 0x67A8, 0xE8C7, 0x67A9, 0x969C, 0x67AA, 0xC7B9,
+	0x67AB, 0xB7E3, 0x67AC, 0x969D, 0x67AD, 0xE8C9, 0x67AE, 0x969E,
+	0x67AF, 0xBFDD, 0x67B0, 0xE8D2, 0x67B1, 0x969F, 0x67B2, 0x96A0,
+	0x67B3, 0xE8D7, 0x67B4, 0x96A1, 0x67B5, 0xE8D5, 0x67B6, 0xBCDC,
+	0x67B7, 0xBCCF, 0x67B8, 0xE8DB, 0x67B9, 0x96A2, 0x67BA, 0x96A3,
+	0x67BB, 0x96A4, 0x67BC, 0x96A5, 0x67BD, 0x96A6, 0x67BE, 0x96A7,
+	0x67BF, 0x96A8, 0x67C0, 0x96A9, 0x67C1, 0xE8DE, 0x67C2, 0x96AA,
+	0x67C3, 0xE8DA, 0x67C4, 0xB1FA, 0x67C5, 0x96AB, 0x67C6, 0x96AC,
+	0x67C7, 0x96AD, 0x67C8, 0x96AE, 0x67C9, 0x96AF, 0x67CA, 0x96B0,
+	0x67CB, 0x96B1, 0x67CC, 0x96B2, 0x67CD, 0x96B3, 0x67CE, 0x96B4,
+	0x67CF, 0xB0D8, 0x67D0, 0xC4B3, 0x67D1, 0xB8CC, 0x67D2, 0xC6E2,
+	0x67D3, 0xC8BE, 0x67D4, 0xC8E1, 0x67D5, 0x96B5, 0x67D6, 0x96B6,
+	0x67D7, 0x96B7, 0x67D8, 0xE8CF, 0x67D9, 0xE8D4, 0x67DA, 0xE8D6,
+	0x67DB, 0x96B8, 0x67DC, 0xB9F1, 0x67DD, 0xE8D8, 0x67DE, 0xD7F5,
+	0x67DF, 0x96B9, 0x67E0, 0xC4FB, 0x67E1, 0x96BA, 0x67E2, 0xE8DC,
+	0x67E3, 0x96BB, 0x67E4, 0x96BC, 0x67E5, 0xB2E9, 0x67E6, 0x96BD,
+	0x67E7, 0x96BE, 0x67E8, 0x96BF, 0x67E9, 0xE8D1, 0x67EA, 0x96C0,
+	0x67EB, 0x96C1, 0x67EC, 0xBCED, 0x67ED, 0x96C2, 0x67EE, 0x96C3,
+	0x67EF, 0xBFC2, 0x67F0, 0xE8CD, 0x67F1, 0xD6F9, 0x67F2, 0x96C4,
+	0x67F3, 0xC1F8, 0x67F4, 0xB2F1, 0x67F5, 0x96C5, 0x67F6, 0x96C6,
+	0x67F7, 0x96C7, 0x67F8, 0x96C8, 0x67F9, 0x96C9, 0x67FA, 0x96CA,
+	0x67FB, 0x96CB, 0x67FC, 0x96CC, 0x67FD, 0xE8DF, 0x67FE, 0x96CD,
+	0x67FF, 0xCAC1, 0x6800, 0xE8D9, 0x6801, 0x96CE, 0x6802, 0x96CF,
+	0x6803, 0x96D0, 0x6804, 0x96D1, 0x6805, 0xD5A4, 0x6806, 0x96D2,
+	0x6807, 0xB1EA, 0x6808, 0xD5BB, 0x6809, 0xE8CE, 0x680A, 0xE8D0,
+	0x680B, 0xB6B0, 0x680C, 0xE8D3, 0x680D, 0x96D3, 0x680E, 0xE8DD,
+	0x680F, 0xC0B8, 0x6810, 0x96D4, 0x6811, 0xCAF7, 0x6812, 0x96D5,
+	0x6813, 0xCBA8, 0x6814, 0x96D6, 0x6815, 0x96D7, 0x6816, 0xC6DC,
+	0x6817, 0xC0F5, 0x6818, 0x96D8, 0x6819, 0x96D9, 0x681A, 0x96DA,
+	0x681B, 0x96DB, 0x681C, 0x96DC, 0x681D, 0xE8E9, 0x681E, 0x96DD,
+	0x681F, 0x96DE, 0x6820, 0x96DF, 0x6821, 0xD0A3, 0x6822, 0x96E0,
+	0x6823, 0x96E1, 0x6824, 0x96E2, 0x6825, 0x96E3, 0x6826, 0x96E4,
+	0x6827, 0x96E5, 0x6828, 0x96E6, 0x6829, 0xE8F2, 0x682A, 0xD6EA,
+	0x682B, 0x96E7, 0x682C, 0x96E8, 0x682D, 0x96E9, 0x682E, 0x96EA,
+	0x682F, 0x96EB, 0x6830, 0x96EC, 0x6831, 0x96ED, 0x6832, 0xE8E0,
+	0x6833, 0xE8E1, 0x6834, 0x96EE, 0x6835, 0x96EF, 0x6836, 0x96F0,
+	0x6837, 0xD1F9, 0x6838, 0xBACB, 0x6839, 0xB8F9, 0x683A, 0x96F1,
+	0x683B, 0x96F2, 0x683C, 0xB8F1, 0x683D, 0xD4D4, 0x683E, 0xE8EF,
+	0x683F, 0x96F3, 0x6840, 0xE8EE, 0x6841, 0xE8EC, 0x6842, 0xB9F0,
+	0x6843, 0xCCD2, 0x6844, 0xE8E6, 0x6845, 0xCEA6, 0x6846, 0xBFF2,
+	0x6847, 0x96F4, 0x6848, 0xB0B8, 0x6849, 0xE8F1, 0x684A, 0xE8F0,
+	0x684B, 0x96F5, 0x684C, 0xD7C0, 0x684D, 0x96F6, 0x684E, 0xE8E4,
+	0x684F, 0x96F7, 0x6850, 0xCDA9, 0x6851, 0xC9A3, 0x6852, 0x96F8,
+	0x6853, 0xBBB8, 0x6854, 0xBDDB, 0x6855, 0xE8EA, 0x6856, 0x96F9,
+	0x6857, 0x96FA, 0x6858, 0x96FB, 0x6859, 0x96FC, 0x685A, 0x96FD,
+	0x685B, 0x96FE, 0x685C, 0x9740, 0x685D, 0x9741, 0x685E, 0x9742,
+	0x685F, 0x9743, 0x6860, 0xE8E2, 0x6861, 0xE8E3, 0x6862, 0xE8E5,
+	0x6863, 0xB5B5, 0x6864, 0xE8E7, 0x6865, 0xC7C5, 0x6866, 0xE8EB,
+	0x6867, 0xE8ED, 0x6868, 0xBDB0, 0x6869, 0xD7AE, 0x686A, 0x9744,
+	0x686B, 0xE8F8, 0x686C, 0x9745, 0x686D, 0x9746, 0x686E, 0x9747,
+	0x686F, 0x9748, 0x6870, 0x9749, 0x6871, 0x974A, 0x6872, 0x974B,
+	0x6873, 0x974C, 0x6874, 0xE8F5, 0x6875, 0x974D, 0x6876, 0xCDB0,
+	0x6877, 0xE8F6, 0x6878, 0x974E, 0x6879, 0x974F, 0x687A, 0x9750,
+	0x687B, 0x9751, 0x687C, 0x9752, 0x687D, 0x9753, 0x687E, 0x9754,
+	0x687F, 0x9755, 0x6880, 0x9756, 0x6881, 0xC1BA, 0x6882, 0x9757,
+	0x6883, 0xE8E8, 0x6884, 0x9758, 0x6885, 0xC3B7, 0x6886, 0xB0F0,
+	0x6887, 0x9759, 0x6888, 0x975A, 0x6889, 0x975B, 0x688A, 0x975C,
+	0x688B, 0x975D, 0x688C, 0x975E, 0x688D, 0x975F, 0x688E, 0x9760,
+	0x688F, 0xE8F4, 0x6890, 0x9761, 0x6891, 0x9762, 0x6892, 0x9763,
+	0x6893, 0xE8F7, 0x6894, 0x9764, 0x6895, 0x9765, 0x6896, 0x9766,
+	0x6897, 0xB9A3, 0x6898, 0x9767, 0x6899, 0x9768, 0x689A, 0x9769,
+	0x689B, 0x976A, 0x689C, 0x976B, 0x689D, 0x976C, 0x689E, 0x976D,
+	0x689F, 0x976E, 0x68A0, 0x976F, 0x68A1, 0x9770, 0x68A2, 0xC9D2,
+	0x68A3, 0x9771, 0x68A4, 0x9772, 0x68A5, 0x9773, 0x68A6, 0xC3CE,
+	0x68A7, 0xCEE0, 0x68A8, 0xC0E6, 0x68A9, 0x9774, 0x68AA, 0x9775,
+	0x68AB, 0x9776, 0x68AC, 0x9777, 0x68AD, 0xCBF3, 0x68AE, 0x9778,
+	0x68AF, 0xCCDD, 0x68B0, 0xD0B5, 0x68B1, 0x9779, 0x68B2, 0x977A,
+	0x68B3, 0xCAE1, 0x68B4, 0x977B, 0x68B5, 0xE8F3, 0x68B6, 0x977C,
+	0x68B7, 0x977D, 0x68B8, 0x977E, 0x68B9, 0x9780, 0x68BA, 0x9781,
+	0x68BB, 0x9782, 0x68BC, 0x9783, 0x68BD, 0x9784, 0x68BE, 0x9785,
+	0x68BF, 0x9786, 0x68C0, 0xBCEC, 0x68C1, 0x9787, 0x68C2, 0xE8F9,
+	0x68C3, 0x9788, 0x68C4, 0x9789, 0x68C5, 0x978A, 0x68C6, 0x978B,
+	0x68C7, 0x978C, 0x68C8, 0x978D, 0x68C9, 0xC3DE, 0x68CA, 0x978E,
+	0x68CB, 0xC6E5, 0x68CC, 0x978F, 0x68CD, 0xB9F7, 0x68CE, 0x9790,
+	0x68CF, 0x9791, 0x68D0, 0x9792, 0x68D1, 0x9793, 0x68D2, 0xB0F4,
+	0x68D3, 0x9794, 0x68D4, 0x9795, 0x68D5, 0xD7D8, 0x68D6, 0x9796,
+	0x68D7, 0x9797, 0x68D8, 0xBCAC, 0x68D9, 0x9798, 0x68DA, 0xC5EF,
+	0x68DB, 0x9799, 0x68DC, 0x979A, 0x68DD, 0x979B, 0x68DE, 0x979C,
+	0x68DF, 0x979D, 0x68E0, 0xCCC4, 0x68E1, 0x979E, 0x68E2, 0x979F,
+	0x68E3, 0xE9A6, 0x68E4, 0x97A0, 0x68E5, 0x97A1, 0x68E6, 0x97A2,
+	0x68E7, 0x97A3, 0x68E8, 0x97A4, 0x68E9, 0x97A5, 0x68EA, 0x97A6,
+	0x68EB, 0x97A7, 0x68EC, 0x97A8, 0x68ED, 0x97A9, 0x68EE, 0xC9AD,
+	0x68EF, 0x97AA, 0x68F0, 0xE9A2, 0x68F1, 0xC0E2, 0x68F2, 0x97AB,
+	0x68F3, 0x97AC, 0x68F4, 0x97AD, 0x68F5, 0xBFC3, 0x68F6, 0x97AE,
+	0x68F7, 0x97AF, 0x68F8, 0x97B0, 0x68F9, 0xE8FE, 0x68FA, 0xB9D7,
+	0x68FB, 0x97B1, 0x68FC, 0xE8FB, 0x68FD, 0x97B2, 0x68FE, 0x97B3,
+	0x68FF, 0x97B4, 0x6900, 0x97B5, 0x6901, 0xE9A4, 0x6902, 0x97B6,
+	0x6903, 0x97B7, 0x6904, 0x97B8, 0x6905, 0xD2CE, 0x6906, 0x97B9,
+	0x6907, 0x97BA, 0x6908, 0x97BB, 0x6909, 0x97BC, 0x690A, 0x97BD,
+	0x690B, 0xE9A3, 0x690C, 0x97BE, 0x690D, 0xD6B2, 0x690E, 0xD7B5,
+	0x690F, 0x97BF, 0x6910, 0xE9A7, 0x6911, 0x97C0, 0x6912, 0xBDB7,
+	0x6913, 0x97C1, 0x6914, 0x97C2, 0x6915, 0x97C3, 0x6916, 0x97C4,
+	0x6917, 0x97C5, 0x6918, 0x97C6, 0x6919, 0x97C7, 0x691A, 0x97C8,
+	0x691B, 0x97C9, 0x691C, 0x97CA, 0x691D, 0x97CB, 0x691E, 0x97CC,
+	0x691F, 0xE8FC, 0x6920, 0xE8FD, 0x6921, 0x97CD, 0x6922, 0x97CE,
+	0x6923, 0x97CF, 0x6924, 0xE9A1, 0x6925, 0x97D0, 0x6926, 0x97D1,
+	0x6927, 0x97D2, 0x6928, 0x97D3, 0x6929, 0x97D4, 0x692A, 0x97D5,
+	0x692B, 0x97D6, 0x692C, 0x97D7, 0x692D, 0xCDD6, 0x692E, 0x97D8,
+	0x692F, 0x97D9, 0x6930, 0xD2AC, 0x6931, 0x97DA, 0x6932, 0x97DB,
+	0x6933, 0x97DC, 0x6934, 0xE9B2, 0x6935, 0x97DD, 0x6936, 0x97DE,
+	0x6937, 0x97DF, 0x6938, 0x97E0, 0x6939, 0xE9A9, 0x693A, 0x97E1,
+	0x693B, 0x97E2, 0x693C, 0x97E3, 0x693D, 0xB4AA, 0x693E, 0x97E4,
+	0x693F, 0xB4BB, 0x6940, 0x97E5, 0x6941, 0x97E6, 0x6942, 0xE9AB,
+	0x6943, 0x97E7, 0x6944, 0x97E8, 0x6945, 0x97E9, 0x6946, 0x97EA,
+	0x6947, 0x97EB, 0x6948, 0x97EC, 0x6949, 0x97ED, 0x694A, 0x97EE,
+	0x694B, 0x97EF, 0x694C, 0x97F0, 0x694D, 0x97F1, 0x694E, 0x97F2,
+	0x694F, 0x97F3, 0x6950, 0x97F4, 0x6951, 0x97F5, 0x6952, 0x97F6,
+	0x6953, 0x97F7, 0x6954, 0xD0A8, 0x6955, 0x97F8, 0x6956, 0x97F9,
+	0x6957, 0xE9A5, 0x6958, 0x97FA, 0x6959, 0x97FB, 0x695A, 0xB3FE,
+	0x695B, 0x97FC, 0x695C, 0x97FD, 0x695D, 0xE9AC, 0x695E, 0xC0E3,
+	0x695F, 0x97FE, 0x6960, 0xE9AA, 0x6961, 0x9840, 0x6962, 0x9841,
+	0x6963, 0xE9B9, 0x6964, 0x9842, 0x6965, 0x9843, 0x6966, 0xE9B8,
+	0x6967, 0x9844, 0x6968, 0x9845, 0x6969, 0x9846, 0x696A, 0x9847,
+	0x696B, 0xE9AE, 0x696C, 0x9848, 0x696D, 0x9849, 0x696E, 0xE8FA,
+	0x696F, 0x984A, 0x6970, 0x984B, 0x6971, 0xE9A8, 0x6972, 0x984C,
+	0x6973, 0x984D, 0x6974, 0x984E, 0x6975, 0x984F, 0x6976, 0x9850,
+	0x6977, 0xBFAC, 0x6978, 0xE9B1, 0x6979, 0xE9BA, 0x697A, 0x9851,
+	0x697B, 0x9852, 0x697C, 0xC2A5, 0x697D, 0x9853, 0x697E, 0x9854,
+	0x697F, 0x9855, 0x6980, 0xE9AF, 0x6981, 0x9856, 0x6982, 0xB8C5,
+	0x6983, 0x9857, 0x6984, 0xE9AD, 0x6985, 0x9858, 0x6986, 0xD3DC,
+	0x6987, 0xE9B4, 0x6988, 0xE9B5, 0x6989, 0xE9B7, 0x698A, 0x9859,
+	0x698B, 0x985A, 0x698C, 0x985B, 0x698D, 0xE9C7, 0x698E, 0x985C,
+	0x698F, 0x985D, 0x6990, 0x985E, 0x6991, 0x985F, 0x6992, 0x9860,
+	0x6993, 0x9861, 0x6994, 0xC0C6, 0x6995, 0xE9C5, 0x6996, 0x9862,
+	0x6997, 0x9863, 0x6998, 0xE9B0, 0x6999, 0x9864, 0x699A, 0x9865,
+	0x699B, 0xE9BB, 0x699C, 0xB0F1, 0x699D, 0x9866, 0x699E, 0x9867,
+	0x699F, 0x9868, 0x69A0, 0x9869, 0x69A1, 0x986A, 0x69A2, 0x986B,
+	0x69A3, 0x986C, 0x69A4, 0x986D, 0x69A5, 0x986E, 0x69A6, 0x986F,
+	0x69A7, 0xE9BC, 0x69A8, 0xD5A5, 0x69A9, 0x9870, 0x69AA, 0x9871,
+	0x69AB, 0xE9BE, 0x69AC, 0x9872, 0x69AD, 0xE9BF, 0x69AE, 0x9873,
+	0x69AF, 0x9874, 0x69B0, 0x9875, 0x69B1, 0xE9C1, 0x69B2, 0x9876,
+	0x69B3, 0x9877, 0x69B4, 0xC1F1, 0x69B5, 0x9878, 0x69B6, 0x9879,
+	0x69B7, 0xC8B6, 0x69B8, 0x987A, 0x69B9, 0x987B, 0x69BA, 0x987C,
+	0x69BB, 0xE9BD, 0x69BC, 0x987D, 0x69BD, 0x987E, 0x69BE, 0x9880,
+	0x69BF, 0x9881, 0x69C0, 0x9882, 0x69C1, 0xE9C2, 0x69C2, 0x9883,
+	0x69C3, 0x9884, 0x69C4, 0x9885, 0x69C5, 0x9886, 0x69C6, 0x9887,
+	0x69C7, 0x9888, 0x69C8, 0x9889, 0x69C9, 0x988A, 0x69CA, 0xE9C3,
+	0x69CB, 0x988B, 0x69CC, 0xE9B3, 0x69CD, 0x988C, 0x69CE, 0xE9B6,
+	0x69CF, 0x988D, 0x69D0, 0xBBB1, 0x69D1, 0x988E, 0x69D2, 0x988F,
+	0x69D3, 0x9890, 0x69D4, 0xE9C0, 0x69D5, 0x9891, 0x69D6, 0x9892,
+	0x69D7, 0x9893, 0x69D8, 0x9894, 0x69D9, 0x9895, 0x69DA, 0x9896,
+	0x69DB, 0xBCF7, 0x69DC, 0x9897, 0x69DD, 0x9898, 0x69DE, 0x9899,
+	0x69DF, 0xE9C4, 0x69E0, 0xE9C6, 0x69E1, 0x989A, 0x69E2, 0x989B,
+	0x69E3, 0x989C, 0x69E4, 0x989D, 0x69E5, 0x989E, 0x69E6, 0x989F,
+	0x69E7, 0x98A0, 0x69E8, 0x98A1, 0x69E9, 0x98A2, 0x69EA, 0x98A3,
+	0x69EB, 0x98A4, 0x69EC, 0x98A5, 0x69ED, 0xE9CA, 0x69EE, 0x98A6,
+	0x69EF, 0x98A7, 0x69F0, 0x98A8, 0x69F1, 0x98A9, 0x69F2, 0xE9CE,
+	0x69F3, 0x98AA, 0x69F4, 0x98AB, 0x69F5, 0x98AC, 0x69F6, 0x98AD,
+	0x69F7, 0x98AE, 0x69F8, 0x98AF, 0x69F9, 0x98B0, 0x69FA, 0x98B1,
+	0x69FB, 0x98B2, 0x69FC, 0x98B3, 0x69FD, 0xB2DB, 0x69FE, 0x98B4,
+	0x69FF, 0xE9C8, 0x6A00, 0x98B5, 0x6A01, 0x98B6, 0x6A02, 0x98B7,
+	0x6A03, 0x98B8, 0x6A04, 0x98B9, 0x6A05, 0x98BA, 0x6A06, 0x98BB,
+	0x6A07, 0x98BC, 0x6A08, 0x98BD, 0x6A09, 0x98BE, 0x6A0A, 0xB7AE,
+	0x6A0B, 0x98BF, 0x6A0C, 0x98C0, 0x6A0D, 0x98C1, 0x6A0E, 0x98C2,
+	0x6A0F, 0x98C3, 0x6A10, 0x98C4, 0x6A11, 0x98C5, 0x6A12, 0x98C6,
+	0x6A13, 0x98C7, 0x6A14, 0x98C8, 0x6A15, 0x98C9, 0x6A16, 0x98CA,
+	0x6A17, 0xE9CB, 0x6A18, 0xE9CC, 0x6A19, 0x98CB, 0x6A1A, 0x98CC,
+	0x6A1B, 0x98CD, 0x6A1C, 0x98CE, 0x6A1D, 0x98CF, 0x6A1E, 0x98D0,
+	0x6A1F, 0xD5C1, 0x6A20, 0x98D1, 0x6A21, 0xC4A3, 0x6A22, 0x98D2,
+	0x6A23, 0x98D3, 0x6A24, 0x98D4, 0x6A25, 0x98D5, 0x6A26, 0x98D6,
+	0x6A27, 0x98D7, 0x6A28, 0xE9D8, 0x6A29, 0x98D8, 0x6A2A, 0xBAE1,
+	0x6A2B, 0x98D9, 0x6A2C, 0x98DA, 0x6A2D, 0x98DB, 0x6A2E, 0x98DC,
+	0x6A2F, 0xE9C9, 0x6A30, 0x98DD, 0x6A31, 0xD3A3, 0x6A32, 0x98DE,
+	0x6A33, 0x98DF, 0x6A34, 0x98E0, 0x6A35, 0xE9D4, 0x6A36, 0x98E1,
+	0x6A37, 0x98E2, 0x6A38, 0x98E3, 0x6A39, 0x98E4, 0x6A3A, 0x98E5,
+	0x6A3B, 0x98E6, 0x6A3C, 0x98E7, 0x6A3D, 0xE9D7, 0x6A3E, 0xE9D0,
+	0x6A3F, 0x98E8, 0x6A40, 0x98E9, 0x6A41, 0x98EA, 0x6A42, 0x98EB,
+	0x6A43, 0x98EC, 0x6A44, 0xE9CF, 0x6A45, 0x98ED, 0x6A46, 0x98EE,
+	0x6A47, 0xC7C1, 0x6A48, 0x98EF, 0x6A49, 0x98F0, 0x6A4A, 0x98F1,
+	0x6A4B, 0x98F2, 0x6A4C, 0x98F3, 0x6A4D, 0x98F4, 0x6A4E, 0x98F5,
+	0x6A4F, 0x98F6, 0x6A50, 0xE9D2, 0x6A51, 0x98F7, 0x6A52, 0x98F8,
+	0x6A53, 0x98F9, 0x6A54, 0x98FA, 0x6A55, 0x98FB, 0x6A56, 0x98FC,
+	0x6A57, 0x98FD, 0x6A58, 0xE9D9, 0x6A59, 0xB3C8, 0x6A5A, 0x98FE,
+	0x6A5B, 0xE9D3, 0x6A5C, 0x9940, 0x6A5D, 0x9941, 0x6A5E, 0x9942,
+	0x6A5F, 0x9943, 0x6A60, 0x9944, 0x6A61, 0xCFF0, 0x6A62, 0x9945,
+	0x6A63, 0x9946, 0x6A64, 0x9947, 0x6A65, 0xE9CD, 0x6A66, 0x9948,
+	0x6A67, 0x9949, 0x6A68, 0x994A, 0x6A69, 0x994B, 0x6A6A, 0x994C,
+	0x6A6B, 0x994D, 0x6A6C, 0x994E, 0x6A6D, 0x994F, 0x6A6E, 0x9950,
+	0x6A6F, 0x9951, 0x6A70, 0x9952, 0x6A71, 0xB3F7, 0x6A72, 0x9953,
+	0x6A73, 0x9954, 0x6A74, 0x9955, 0x6A75, 0x9956, 0x6A76, 0x9957,
+	0x6A77, 0x9958, 0x6A78, 0x9959, 0x6A79, 0xE9D6, 0x6A7A, 0x995A,
+	0x6A7B, 0x995B, 0x6A7C, 0xE9DA, 0x6A7D, 0x995C, 0x6A7E, 0x995D,
+	0x6A7F, 0x995E, 0x6A80, 0xCCB4, 0x6A81, 0x995F, 0x6A82, 0x9960,
+	0x6A83, 0x9961, 0x6A84, 0xCFAD, 0x6A85, 0x9962, 0x6A86, 0x9963,
+	0x6A87, 0x9964, 0x6A88, 0x9965, 0x6A89, 0x9966, 0x6A8A, 0x9967,
+	0x6A8B, 0x9968, 0x6A8C, 0x9969, 0x6A8D, 0x996A, 0x6A8E, 0xE9D5,
+	0x6A8F, 0x996B, 0x6A90, 0xE9DC, 0x6A91, 0xE9DB, 0x6A92, 0x996C,
+	0x6A93, 0x996D, 0x6A94, 0x996E, 0x6A95, 0x996F, 0x6A96, 0x9970,
+	0x6A97, 0xE9DE, 0x6A98, 0x9971, 0x6A99, 0x9972, 0x6A9A, 0x9973,
+	0x6A9B, 0x9974, 0x6A9C, 0x9975, 0x6A9D, 0x9976, 0x6A9E, 0x9977,
+	0x6A9F, 0x9978, 0x6AA0, 0xE9D1, 0x6AA1, 0x9979, 0x6AA2, 0x997A,
+	0x6AA3, 0x997B, 0x6AA4, 0x997C, 0x6AA5, 0x997D, 0x6AA6, 0x997E,
+	0x6AA7, 0x9980, 0x6AA8, 0x9981, 0x6AA9, 0xE9DD, 0x6AAA, 0x9982,
+	0x6AAB, 0xE9DF, 0x6AAC, 0xC3CA, 0x6AAD, 0x9983, 0x6AAE, 0x9984,
+	0x6AAF, 0x9985, 0x6AB0, 0x9986, 0x6AB1, 0x9987, 0x6AB2, 0x9988,
+	0x6AB3, 0x9989, 0x6AB4, 0x998A, 0x6AB5, 0x998B, 0x6AB6, 0x998C,
+	0x6AB7, 0x998D, 0x6AB8, 0x998E, 0x6AB9, 0x998F, 0x6ABA, 0x9990,
+	0x6ABB, 0x9991, 0x6ABC, 0x9992, 0x6ABD, 0x9993, 0x6ABE, 0x9994,
+	0x6ABF, 0x9995, 0x6AC0, 0x9996, 0x6AC1, 0x9997, 0x6AC2, 0x9998,
+	0x6AC3, 0x9999, 0x6AC4, 0x999A, 0x6AC5, 0x999B, 0x6AC6, 0x999C,
+	0x6AC7, 0x999D, 0x6AC8, 0x999E, 0x6AC9, 0x999F, 0x6ACA, 0x99A0,
+	0x6ACB, 0x99A1, 0x6ACC, 0x99A2, 0x6ACD, 0x99A3, 0x6ACE, 0x99A4,
+	0x6ACF, 0x99A5, 0x6AD0, 0x99A6, 0x6AD1, 0x99A7, 0x6AD2, 0x99A8,
+	0x6AD3, 0x99A9, 0x6AD4, 0x99AA, 0x6AD5, 0x99AB, 0x6AD6, 0x99AC,
+	0x6AD7, 0x99AD, 0x6AD8, 0x99AE, 0x6AD9, 0x99AF, 0x6ADA, 0x99B0,
+	0x6ADB, 0x99B1, 0x6ADC, 0x99B2, 0x6ADD, 0x99B3, 0x6ADE, 0x99B4,
+	0x6ADF, 0x99B5, 0x6AE0, 0x99B6, 0x6AE1, 0x99B7, 0x6AE2, 0x99B8,
+	0x6AE3, 0x99B9, 0x6AE4, 0x99BA, 0x6AE5, 0x99BB, 0x6AE6, 0x99BC,
+	0x6AE7, 0x99BD, 0x6AE8, 0x99BE, 0x6AE9, 0x99BF, 0x6AEA, 0x99C0,
+	0x6AEB, 0x99C1, 0x6AEC, 0x99C2, 0x6AED, 0x99C3, 0x6AEE, 0x99C4,
+	0x6AEF, 0x99C5, 0x6AF0, 0x99C6, 0x6AF1, 0x99C7, 0x6AF2, 0x99C8,
+	0x6AF3, 0x99C9, 0x6AF4, 0x99CA, 0x6AF5, 0x99CB, 0x6AF6, 0x99CC,
+	0x6AF7, 0x99CD, 0x6AF8, 0x99CE, 0x6AF9, 0x99CF, 0x6AFA, 0x99D0,
+	0x6AFB, 0x99D1, 0x6AFC, 0x99D2, 0x6AFD, 0x99D3, 0x6AFE, 0x99D4,
+	0x6AFF, 0x99D5, 0x6B00, 0x99D6, 0x6B01, 0x99D7, 0x6B02, 0x99D8,
+	0x6B03, 0x99D9, 0x6B04, 0x99DA, 0x6B05, 0x99DB, 0x6B06, 0x99DC,
+	0x6B07, 0x99DD, 0x6B08, 0x99DE, 0x6B09, 0x99DF, 0x6B0A, 0x99E0,
+	0x6B0B, 0x99E1, 0x6B0C, 0x99E2, 0x6B0D, 0x99E3, 0x6B0E, 0x99E4,
+	0x6B0F, 0x99E5, 0x6B10, 0x99E6, 0x6B11, 0x99E7, 0x6B12, 0x99E8,
+	0x6B13, 0x99E9, 0x6B14, 0x99EA, 0x6B15, 0x99EB, 0x6B16, 0x99EC,
+	0x6B17, 0x99ED, 0x6B18, 0x99EE, 0x6B19, 0x99EF, 0x6B1A, 0x99F0,
+	0x6B1B, 0x99F1, 0x6B1C, 0x99F2, 0x6B1D, 0x99F3, 0x6B1E, 0x99F4,
+	0x6B1F, 0x99F5, 0x6B20, 0xC7B7, 0x6B21, 0xB4CE, 0x6B22, 0xBBB6,
+	0x6B23, 0xD0C0, 0x6B24, 0xECA3, 0x6B25, 0x99F6, 0x6B26, 0x99F7,
+	0x6B27, 0xC5B7, 0x6B28, 0x99F8, 0x6B29, 0x99F9, 0x6B2A, 0x99FA,
+	0x6B2B, 0x99FB, 0x6B2C, 0x99FC, 0x6B2D, 0x99FD, 0x6B2E, 0x99FE,
+	0x6B2F, 0x9A40, 0x6B30, 0x9A41, 0x6B31, 0x9A42, 0x6B32, 0xD3FB,
+	0x6B33, 0x9A43, 0x6B34, 0x9A44, 0x6B35, 0x9A45, 0x6B36, 0x9A46,
+	0x6B37, 0xECA4, 0x6B38, 0x9A47, 0x6B39, 0xECA5, 0x6B3A, 0xC6DB,
+	0x6B3B, 0x9A48, 0x6B3C, 0x9A49, 0x6B3D, 0x9A4A, 0x6B3E, 0xBFEE,
+	0x6B3F, 0x9A4B, 0x6B40, 0x9A4C, 0x6B41, 0x9A4D, 0x6B42, 0x9A4E,
+	0x6B43, 0xECA6, 0x6B44, 0x9A4F, 0x6B45, 0x9A50, 0x6B46, 0xECA7,
+	0x6B47, 0xD0AA, 0x6B48, 0x9A51, 0x6B49, 0xC7B8, 0x6B4A, 0x9A52,
+	0x6B4B, 0x9A53, 0x6B4C, 0xB8E8, 0x6B4D, 0x9A54, 0x6B4E, 0x9A55,
+	0x6B4F, 0x9A56, 0x6B50, 0x9A57, 0x6B51, 0x9A58, 0x6B52, 0x9A59,
+	0x6B53, 0x9A5A, 0x6B54, 0x9A5B, 0x6B55, 0x9A5C, 0x6B56, 0x9A5D,
+	0x6B57, 0x9A5E, 0x6B58, 0x9A5F, 0x6B59, 0xECA8, 0x6B5A, 0x9A60,
+	0x6B5B, 0x9A61, 0x6B5C, 0x9A62, 0x6B5D, 0x9A63, 0x6B5E, 0x9A64,
+	0x6B5F, 0x9A65, 0x6B60, 0x9A66, 0x6B61, 0x9A67, 0x6B62, 0xD6B9,
+	0x6B63, 0xD5FD, 0x6B64, 0xB4CB, 0x6B65, 0xB2BD, 0x6B66, 0xCEE4,
+	0x6B67, 0xC6E7, 0x6B68, 0x9A68, 0x6B69, 0x9A69, 0x6B6A, 0xCDE1,
+	0x6B6B, 0x9A6A, 0x6B6C, 0x9A6B, 0x6B6D, 0x9A6C, 0x6B6E, 0x9A6D,
+	0x6B6F, 0x9A6E, 0x6B70, 0x9A6F, 0x6B71, 0x9A70, 0x6B72, 0x9A71,
+	0x6B73, 0x9A72, 0x6B74, 0x9A73, 0x6B75, 0x9A74, 0x6B76, 0x9A75,
+	0x6B77, 0x9A76, 0x6B78, 0x9A77, 0x6B79, 0xB4F5, 0x6B7A, 0x9A78,
+	0x6B7B, 0xCBC0, 0x6B7C, 0xBCDF, 0x6B7D, 0x9A79, 0x6B7E, 0x9A7A,
+	0x6B7F, 0x9A7B, 0x6B80, 0x9A7C, 0x6B81, 0xE9E2, 0x6B82, 0xE9E3,
+	0x6B83, 0xD1EA, 0x6B84, 0xE9E5, 0x6B85, 0x9A7D, 0x6B86, 0xB4F9,
+	0x6B87, 0xE9E4, 0x6B88, 0x9A7E, 0x6B89, 0xD1B3, 0x6B8A, 0xCAE2,
+	0x6B8B, 0xB2D0, 0x6B8C, 0x9A80, 0x6B8D, 0xE9E8, 0x6B8E, 0x9A81,
+	0x6B8F, 0x9A82, 0x6B90, 0x9A83, 0x6B91, 0x9A84, 0x6B92, 0xE9E6,
+	0x6B93, 0xE9E7, 0x6B94, 0x9A85, 0x6B95, 0x9A86, 0x6B96, 0xD6B3,
+	0x6B97, 0x9A87, 0x6B98, 0x9A88, 0x6B99, 0x9A89, 0x6B9A, 0xE9E9,
+	0x6B9B, 0xE9EA, 0x6B9C, 0x9A8A, 0x6B9D, 0x9A8B, 0x6B9E, 0x9A8C,
+	0x6B9F, 0x9A8D, 0x6BA0, 0x9A8E, 0x6BA1, 0xE9EB, 0x6BA2, 0x9A8F,
+	0x6BA3, 0x9A90, 0x6BA4, 0x9A91, 0x6BA5, 0x9A92, 0x6BA6, 0x9A93,
+	0x6BA7, 0x9A94, 0x6BA8, 0x9A95, 0x6BA9, 0x9A96, 0x6BAA, 0xE9EC,
+	0x6BAB, 0x9A97, 0x6BAC, 0x9A98, 0x6BAD, 0x9A99, 0x6BAE, 0x9A9A,
+	0x6BAF, 0x9A9B, 0x6BB0, 0x9A9C, 0x6BB1, 0x9A9D, 0x6BB2, 0x9A9E,
+	0x6BB3, 0xECAF, 0x6BB4, 0xC5B9, 0x6BB5, 0xB6CE, 0x6BB6, 0x9A9F,
+	0x6BB7, 0xD2F3, 0x6BB8, 0x9AA0, 0x6BB9, 0x9AA1, 0x6BBA, 0x9AA2,
+	0x6BBB, 0x9AA3, 0x6BBC, 0x9AA4, 0x6BBD, 0x9AA5, 0x6BBE, 0x9AA6,
+	0x6BBF, 0xB5EE, 0x6BC0, 0x9AA7, 0x6BC1, 0xBBD9, 0x6BC2, 0xECB1,
+	0x6BC3, 0x9AA8, 0x6BC4, 0x9AA9, 0x6BC5, 0xD2E3, 0x6BC6, 0x9AAA,
+	0x6BC7, 0x9AAB, 0x6BC8, 0x9AAC, 0x6BC9, 0x9AAD, 0x6BCA, 0x9AAE,
+	0x6BCB, 0xCEE3, 0x6BCC, 0x9AAF, 0x6BCD, 0xC4B8, 0x6BCE, 0x9AB0,
+	0x6BCF, 0xC3BF, 0x6BD0, 0x9AB1, 0x6BD1, 0x9AB2, 0x6BD2, 0xB6BE,
+	0x6BD3, 0xD8B9, 0x6BD4, 0xB1C8, 0x6BD5, 0xB1CF, 0x6BD6, 0xB1D1,
+	0x6BD7, 0xC5FE, 0x6BD8, 0x9AB3, 0x6BD9, 0xB1D0, 0x6BDA, 0x9AB4,
+	0x6BDB, 0xC3AB, 0x6BDC, 0x9AB5, 0x6BDD, 0x9AB6, 0x6BDE, 0x9AB7,
+	0x6BDF, 0x9AB8, 0x6BE0, 0x9AB9, 0x6BE1, 0xD5B1, 0x6BE2, 0x9ABA,
+	0x6BE3, 0x9ABB, 0x6BE4, 0x9ABC, 0x6BE5, 0x9ABD, 0x6BE6, 0x9ABE,
+	0x6BE7, 0x9ABF, 0x6BE8, 0x9AC0, 0x6BE9, 0x9AC1, 0x6BEA, 0xEBA4,
+	0x6BEB, 0xBAC1, 0x6BEC, 0x9AC2, 0x6BED, 0x9AC3, 0x6BEE, 0x9AC4,
+	0x6BEF, 0xCCBA, 0x6BF0, 0x9AC5, 0x6BF1, 0x9AC6, 0x6BF2, 0x9AC7,
+	0x6BF3, 0xEBA5, 0x6BF4, 0x9AC8, 0x6BF5, 0xEBA7, 0x6BF6, 0x9AC9,
+	0x6BF7, 0x9ACA, 0x6BF8, 0x9ACB, 0x6BF9, 0xEBA8, 0x6BFA, 0x9ACC,
+	0x6BFB, 0x9ACD, 0x6BFC, 0x9ACE, 0x6BFD, 0xEBA6, 0x6BFE, 0x9ACF,
+	0x6BFF, 0x9AD0, 0x6C00, 0x9AD1, 0x6C01, 0x9AD2, 0x6C02, 0x9AD3,
+	0x6C03, 0x9AD4, 0x6C04, 0x9AD5, 0x6C05, 0xEBA9, 0x6C06, 0xEBAB,
+	0x6C07, 0xEBAA, 0x6C08, 0x9AD6, 0x6C09, 0x9AD7, 0x6C0A, 0x9AD8,
+	0x6C0B, 0x9AD9, 0x6C0C, 0x9ADA, 0x6C0D, 0xEBAC, 0x6C0E, 0x9ADB,
+	0x6C0F, 0xCACF, 0x6C10, 0xD8B5, 0x6C11, 0xC3F1, 0x6C12, 0x9ADC,
+	0x6C13, 0xC3A5, 0x6C14, 0xC6F8, 0x6C15, 0xEBAD, 0x6C16, 0xC4CA,
+	0x6C17, 0x9ADD, 0x6C18, 0xEBAE, 0x6C19, 0xEBAF, 0x6C1A, 0xEBB0,
+	0x6C1B, 0xB7D5, 0x6C1C, 0x9ADE, 0x6C1D, 0x9ADF, 0x6C1E, 0x9AE0,
+	0x6C1F, 0xB7FA, 0x6C20, 0x9AE1, 0x6C21, 0xEBB1, 0x6C22, 0xC7E2,
+	0x6C23, 0x9AE2, 0x6C24, 0xEBB3, 0x6C25, 0x9AE3, 0x6C26, 0xBAA4,
+	0x6C27, 0xD1F5, 0x6C28, 0xB0B1, 0x6C29, 0xEBB2, 0x6C2A, 0xEBB4,
+	0x6C2B, 0x9AE4, 0x6C2C, 0x9AE5, 0x6C2D, 0x9AE6, 0x6C2E, 0xB5AA,
+	0x6C2F, 0xC2C8, 0x6C30, 0xC7E8, 0x6C31, 0x9AE7, 0x6C32, 0xEBB5,
+	0x6C33, 0x9AE8, 0x6C34, 0xCBAE, 0x6C35, 0xE3DF, 0x6C36, 0x9AE9,
+	0x6C37, 0x9AEA, 0x6C38, 0xD3C0, 0x6C39, 0x9AEB, 0x6C3A, 0x9AEC,
+	0x6C3B, 0x9AED, 0x6C3C, 0x9AEE, 0x6C3D, 0xD9DB, 0x6C3E, 0x9AEF,
+	0x6C3F, 0x9AF0, 0x6C40, 0xCDA1, 0x6C41, 0xD6AD, 0x6C42, 0xC7F3,
+	0x6C43, 0x9AF1, 0x6C44, 0x9AF2, 0x6C45, 0x9AF3, 0x6C46, 0xD9E0,
+	0x6C47, 0xBBE3, 0x6C48, 0x9AF4, 0x6C49, 0xBABA, 0x6C4A, 0xE3E2,
+	0x6C4B, 0x9AF5, 0x6C4C, 0x9AF6, 0x6C4D, 0x9AF7, 0x6C4E, 0x9AF8,
+	0x6C4F, 0x9AF9, 0x6C50, 0xCFAB, 0x6C51, 0x9AFA, 0x6C52, 0x9AFB,
+	0x6C53, 0x9AFC, 0x6C54, 0xE3E0, 0x6C55, 0xC9C7, 0x6C56, 0x9AFD,
+	0x6C57, 0xBAB9, 0x6C58, 0x9AFE, 0x6C59, 0x9B40, 0x6C5A, 0x9B41,
+	0x6C5B, 0xD1B4, 0x6C5C, 0xE3E1, 0x6C5D, 0xC8EA, 0x6C5E, 0xB9AF,
+	0x6C5F, 0xBDAD, 0x6C60, 0xB3D8, 0x6C61, 0xCEDB, 0x6C62, 0x9B42,
+	0x6C63, 0x9B43, 0x6C64, 0xCCC0, 0x6C65, 0x9B44, 0x6C66, 0x9B45,
+	0x6C67, 0x9B46, 0x6C68, 0xE3E8, 0x6C69, 0xE3E9, 0x6C6A, 0xCDF4,
+	0x6C6B, 0x9B47, 0x6C6C, 0x9B48, 0x6C6D, 0x9B49, 0x6C6E, 0x9B4A,
+	0x6C6F, 0x9B4B, 0x6C70, 0xCCAD, 0x6C71, 0x9B4C, 0x6C72, 0xBCB3,
+	0x6C73, 0x9B4D, 0x6C74, 0xE3EA, 0x6C75, 0x9B4E, 0x6C76, 0xE3EB,
+	0x6C77, 0x9B4F, 0x6C78, 0x9B50, 0x6C79, 0xD0DA, 0x6C7A, 0x9B51,
+	0x6C7B, 0x9B52, 0x6C7C, 0x9B53, 0x6C7D, 0xC6FB, 0x6C7E, 0xB7DA,
+	0x6C7F, 0x9B54, 0x6C80, 0x9B55, 0x6C81, 0xC7DF, 0x6C82, 0xD2CA,
+	0x6C83, 0xCED6, 0x6C84, 0x9B56, 0x6C85, 0xE3E4, 0x6C86, 0xE3EC,
+	0x6C87, 0x9B57, 0x6C88, 0xC9F2, 0x6C89, 0xB3C1, 0x6C8A, 0x9B58,
+	0x6C8B, 0x9B59, 0x6C8C, 0xE3E7, 0x6C8D, 0x9B5A, 0x6C8E, 0x9B5B,
+	0x6C8F, 0xC6E3, 0x6C90, 0xE3E5, 0x6C91, 0x9B5C, 0x6C92, 0x9B5D,
+	0x6C93, 0xEDB3, 0x6C94, 0xE3E6, 0x6C95, 0x9B5E, 0x6C96, 0x9B5F,
+	0x6C97, 0x9B60, 0x6C98, 0x9B61, 0x6C99, 0xC9B3, 0x6C9A, 0x9B62,
+	0x6C9B, 0xC5E6, 0x6C9C, 0x9B63, 0x6C9D, 0x9B64, 0x6C9E, 0x9B65,
+	0x6C9F, 0xB9B5, 0x6CA0, 0x9B66, 0x6CA1, 0xC3BB, 0x6CA2, 0x9B67,
+	0x6CA3, 0xE3E3, 0x6CA4, 0xC5BD, 0x6CA5, 0xC1A4, 0x6CA6, 0xC2D9,
+	0x6CA7, 0xB2D7, 0x6CA8, 0x9B68, 0x6CA9, 0xE3ED, 0x6CAA, 0xBBA6,
+	0x6CAB, 0xC4AD, 0x6CAC, 0x9B69, 0x6CAD, 0xE3F0, 0x6CAE, 0xBEDA,
+	0x6CAF, 0x9B6A, 0x6CB0, 0x9B6B, 0x6CB1, 0xE3FB, 0x6CB2, 0xE3F5,
+	0x6CB3, 0xBAD3, 0x6CB4, 0x9B6C, 0x6CB5, 0x9B6D, 0x6CB6, 0x9B6E,
+	0x6CB7, 0x9B6F, 0x6CB8, 0xB7D0, 0x6CB9, 0xD3CD, 0x6CBA, 0x9B70,
+	0x6CBB, 0xD6CE, 0x6CBC, 0xD5D3, 0x6CBD, 0xB9C1, 0x6CBE, 0xD5B4,
+	0x6CBF, 0xD1D8, 0x6CC0, 0x9B71, 0x6CC1, 0x9B72, 0x6CC2, 0x9B73,
+	0x6CC3, 0x9B74, 0x6CC4, 0xD0B9, 0x6CC5, 0xC7F6, 0x6CC6, 0x9B75,
+	0x6CC7, 0x9B76, 0x6CC8, 0x9B77, 0x6CC9, 0xC8AA, 0x6CCA, 0xB2B4,
+	0x6CCB, 0x9B78, 0x6CCC, 0xC3DA, 0x6CCD, 0x9B79, 0x6CCE, 0x9B7A,
+	0x6CCF, 0x9B7B, 0x6CD0, 0xE3EE, 0x6CD1, 0x9B7C, 0x6CD2, 0x9B7D,
+	0x6CD3, 0xE3FC, 0x6CD4, 0xE3EF, 0x6CD5, 0xB7A8, 0x6CD6, 0xE3F7,
+	0x6CD7, 0xE3F4, 0x6CD8, 0x9B7E, 0x6CD9, 0x9B80, 0x6CDA, 0x9B81,
+	0x6CDB, 0xB7BA, 0x6CDC, 0x9B82, 0x6CDD, 0x9B83, 0x6CDE, 0xC5A2,
+	0x6CDF, 0x9B84, 0x6CE0, 0xE3F6, 0x6CE1, 0xC5DD, 0x6CE2, 0xB2A8,
+	0x6CE3, 0xC6FC, 0x6CE4, 0x9B85, 0x6CE5, 0xC4E0, 0x6CE6, 0x9B86,
+	0x6CE7, 0x9B87, 0x6CE8, 0xD7A2, 0x6CE9, 0x9B88, 0x6CEA, 0xC0E1,
+	0x6CEB, 0xE3F9, 0x6CEC, 0x9B89, 0x6CED, 0x9B8A, 0x6CEE, 0xE3FA,
+	0x6CEF, 0xE3FD, 0x6CF0, 0xCCA9, 0x6CF1, 0xE3F3, 0x6CF2, 0x9B8B,
+	0x6CF3, 0xD3BE, 0x6CF4, 0x9B8C, 0x6CF5, 0xB1C3, 0x6CF6, 0xEDB4,
+	0x6CF7, 0xE3F1, 0x6CF8, 0xE3F2, 0x6CF9, 0x9B8D, 0x6CFA, 0xE3F8,
+	0x6CFB, 0xD0BA, 0x6CFC, 0xC6C3, 0x6CFD, 0xD4F3, 0x6CFE, 0xE3FE,
+	0x6CFF, 0x9B8E, 0x6D00, 0x9B8F, 0x6D01, 0xBDE0, 0x6D02, 0x9B90,
+	0x6D03, 0x9B91, 0x6D04, 0xE4A7, 0x6D05, 0x9B92, 0x6D06, 0x9B93,
+	0x6D07, 0xE4A6, 0x6D08, 0x9B94, 0x6D09, 0x9B95, 0x6D0A, 0x9B96,
+	0x6D0B, 0xD1F3, 0x6D0C, 0xE4A3, 0x6D0D, 0x9B97, 0x6D0E, 0xE4A9,
+	0x6D0F, 0x9B98, 0x6D10, 0x9B99, 0x6D11, 0x9B9A, 0x6D12, 0xC8F7,
+	0x6D13, 0x9B9B, 0x6D14, 0x9B9C, 0x6D15, 0x9B9D, 0x6D16, 0x9B9E,
+	0x6D17, 0xCFB4, 0x6D18, 0x9B9F, 0x6D19, 0xE4A8, 0x6D1A, 0xE4AE,
+	0x6D1B, 0xC2E5, 0x6D1C, 0x9BA0, 0x6D1D, 0x9BA1, 0x6D1E, 0xB6B4,
+	0x6D1F, 0x9BA2, 0x6D20, 0x9BA3, 0x6D21, 0x9BA4, 0x6D22, 0x9BA5,
+	0x6D23, 0x9BA6, 0x6D24, 0x9BA7, 0x6D25, 0xBDF2, 0x6D26, 0x9BA8,
+	0x6D27, 0xE4A2, 0x6D28, 0x9BA9, 0x6D29, 0x9BAA, 0x6D2A, 0xBAE9,
+	0x6D2B, 0xE4AA, 0x6D2C, 0x9BAB, 0x6D2D, 0x9BAC, 0x6D2E, 0xE4AC,
+	0x6D2F, 0x9BAD, 0x6D30, 0x9BAE, 0x6D31, 0xB6FD, 0x6D32, 0xD6DE,
+	0x6D33, 0xE4B2, 0x6D34, 0x9BAF, 0x6D35, 0xE4AD, 0x6D36, 0x9BB0,
+	0x6D37, 0x9BB1, 0x6D38, 0x9BB2, 0x6D39, 0xE4A1, 0x6D3A, 0x9BB3,
+	0x6D3B, 0xBBEE, 0x6D3C, 0xCDDD, 0x6D3D, 0xC7A2, 0x6D3E, 0xC5C9,
+	0x6D3F, 0x9BB4, 0x6D40, 0x9BB5, 0x6D41, 0xC1F7, 0x6D42, 0x9BB6,
+	0x6D43, 0xE4A4, 0x6D44, 0x9BB7, 0x6D45, 0xC7B3, 0x6D46, 0xBDAC,
+	0x6D47, 0xBDBD, 0x6D48, 0xE4A5, 0x6D49, 0x9BB8, 0x6D4A, 0xD7C7,
+	0x6D4B, 0xB2E2, 0x6D4C, 0x9BB9, 0x6D4D, 0xE4AB, 0x6D4E, 0xBCC3,
+	0x6D4F, 0xE4AF, 0x6D50, 0x9BBA, 0x6D51, 0xBBEB, 0x6D52, 0xE4B0,
+	0x6D53, 0xC5A8, 0x6D54, 0xE4B1, 0x6D55, 0x9BBB, 0x6D56, 0x9BBC,
+	0x6D57, 0x9BBD, 0x6D58, 0x9BBE, 0x6D59, 0xD5E3, 0x6D5A, 0xBFA3,
+	0x6D5B, 0x9BBF, 0x6D5C, 0xE4BA, 0x6D5D, 0x9BC0, 0x6D5E, 0xE4B7,
+	0x6D5F, 0x9BC1, 0x6D60, 0xE4BB, 0x6D61, 0x9BC2, 0x6D62, 0x9BC3,
+	0x6D63, 0xE4BD, 0x6D64, 0x9BC4, 0x6D65, 0x9BC5, 0x6D66, 0xC6D6,
+	0x6D67, 0x9BC6, 0x6D68, 0x9BC7, 0x6D69, 0xBAC6, 0x6D6A, 0xC0CB,
+	0x6D6B, 0x9BC8, 0x6D6C, 0x9BC9, 0x6D6D, 0x9BCA, 0x6D6E, 0xB8A1,
+	0x6D6F, 0xE4B4, 0x6D70, 0x9BCB, 0x6D71, 0x9BCC, 0x6D72, 0x9BCD,
+	0x6D73, 0x9BCE, 0x6D74, 0xD4A1, 0x6D75, 0x9BCF, 0x6D76, 0x9BD0,
+	0x6D77, 0xBAA3, 0x6D78, 0xBDFE, 0x6D79, 0x9BD1, 0x6D7A, 0x9BD2,
+	0x6D7B, 0x9BD3, 0x6D7C, 0xE4BC, 0x6D7D, 0x9BD4, 0x6D7E, 0x9BD5,
+	0x6D7F, 0x9BD6, 0x6D80, 0x9BD7, 0x6D81, 0x9BD8, 0x6D82, 0xCDBF,
+	0x6D83, 0x9BD9, 0x6D84, 0x9BDA, 0x6D85, 0xC4F9, 0x6D86, 0x9BDB,
+	0x6D87, 0x9BDC, 0x6D88, 0xCFFB, 0x6D89, 0xC9E6, 0x6D8A, 0x9BDD,
+	0x6D8B, 0x9BDE, 0x6D8C, 0xD3BF, 0x6D8D, 0x9BDF, 0x6D8E, 0xCFD1,
+	0x6D8F, 0x9BE0, 0x6D90, 0x9BE1, 0x6D91, 0xE4B3, 0x6D92, 0x9BE2,
+	0x6D93, 0xE4B8, 0x6D94, 0xE4B9, 0x6D95, 0xCCE9, 0x6D96, 0x9BE3,
+	0x6D97, 0x9BE4, 0x6D98, 0x9BE5, 0x6D99, 0x9BE6, 0x6D9A, 0x9BE7,
+	0x6D9B, 0xCCCE, 0x6D9C, 0x9BE8, 0x6D9D, 0xC0D4, 0x6D9E, 0xE4B5,
+	0x6D9F, 0xC1B0, 0x6DA0, 0xE4B6, 0x6DA1, 0xCED0, 0x6DA2, 0x9BE9,
+	0x6DA3, 0xBBC1, 0x6DA4, 0xB5D3, 0x6DA5, 0x9BEA, 0x6DA6, 0xC8F3,
+	0x6DA7, 0xBDA7, 0x6DA8, 0xD5C7, 0x6DA9, 0xC9AC, 0x6DAA, 0xB8A2,
+	0x6DAB, 0xE4CA, 0x6DAC, 0x9BEB, 0x6DAD, 0x9BEC, 0x6DAE, 0xE4CC,
+	0x6DAF, 0xD1C4, 0x6DB0, 0x9BED, 0x6DB1, 0x9BEE, 0x6DB2, 0xD2BA,
+	0x6DB3, 0x9BEF, 0x6DB4, 0x9BF0, 0x6DB5, 0xBAAD, 0x6DB6, 0x9BF1,
+	0x6DB7, 0x9BF2, 0x6DB8, 0xBAD4, 0x6DB9, 0x9BF3, 0x6DBA, 0x9BF4,
+	0x6DBB, 0x9BF5, 0x6DBC, 0x9BF6, 0x6DBD, 0x9BF7, 0x6DBE, 0x9BF8,
+	0x6DBF, 0xE4C3, 0x6DC0, 0xB5ED, 0x6DC1, 0x9BF9, 0x6DC2, 0x9BFA,
+	0x6DC3, 0x9BFB, 0x6DC4, 0xD7CD, 0x6DC5, 0xE4C0, 0x6DC6, 0xCFFD,
+	0x6DC7, 0xE4BF, 0x6DC8, 0x9BFC, 0x6DC9, 0x9BFD, 0x6DCA, 0x9BFE,
+	0x6DCB, 0xC1DC, 0x6DCC, 0xCCCA, 0x6DCD, 0x9C40, 0x6DCE, 0x9C41,
+	0x6DCF, 0x9C42, 0x6DD0, 0x9C43, 0x6DD1, 0xCAE7, 0x6DD2, 0x9C44,
+	0x6DD3, 0x9C45, 0x6DD4, 0x9C46, 0x6DD5, 0x9C47, 0x6DD6, 0xC4D7,
+	0x6DD7, 0x9C48, 0x6DD8, 0xCCD4, 0x6DD9, 0xE4C8, 0x6DDA, 0x9C49,
+	0x6DDB, 0x9C4A, 0x6DDC, 0x9C4B, 0x6DDD, 0xE4C7, 0x6DDE, 0xE4C1,
+	0x6DDF, 0x9C4C, 0x6DE0, 0xE4C4, 0x6DE1, 0xB5AD, 0x6DE2, 0x9C4D,
+	0x6DE3, 0x9C4E, 0x6DE4, 0xD3D9, 0x6DE5, 0x9C4F, 0x6DE6, 0xE4C6,
+	0x6DE7, 0x9C50, 0x6DE8, 0x9C51, 0x6DE9, 0x9C52, 0x6DEA, 0x9C53,
+	0x6DEB, 0xD2F9, 0x6DEC, 0xB4E3, 0x6DED, 0x9C54, 0x6DEE, 0xBBB4,
+	0x6DEF, 0x9C55, 0x6DF0, 0x9C56, 0x6DF1, 0xC9EE, 0x6DF2, 0x9C57,
+	0x6DF3, 0xB4BE, 0x6DF4, 0x9C58, 0x6DF5, 0x9C59, 0x6DF6, 0x9C5A,
+	0x6DF7, 0xBBEC, 0x6DF8, 0x9C5B, 0x6DF9, 0xD1CD, 0x6DFA, 0x9C5C,
+	0x6DFB, 0xCCED, 0x6DFC, 0xEDB5, 0x6DFD, 0x9C5D, 0x6DFE, 0x9C5E,
+	0x6DFF, 0x9C5F, 0x6E00, 0x9C60, 0x6E01, 0x9C61, 0x6E02, 0x9C62,
+	0x6E03, 0x9C63, 0x6E04, 0x9C64, 0x6E05, 0xC7E5, 0x6E06, 0x9C65,
+	0x6E07, 0x9C66, 0x6E08, 0x9C67, 0x6E09, 0x9C68, 0x6E0A, 0xD4A8,
+	0x6E0B, 0x9C69, 0x6E0C, 0xE4CB, 0x6E0D, 0xD7D5, 0x6E0E, 0xE4C2,
+	0x6E0F, 0x9C6A, 0x6E10, 0xBDA5, 0x6E11, 0xE4C5, 0x6E12, 0x9C6B,
+	0x6E13, 0x9C6C, 0x6E14, 0xD3E6, 0x6E15, 0x9C6D, 0x6E16, 0xE4C9,
+	0x6E17, 0xC9F8, 0x6E18, 0x9C6E, 0x6E19, 0x9C6F, 0x6E1A, 0xE4BE,
+	0x6E1B, 0x9C70, 0x6E1C, 0x9C71, 0x6E1D, 0xD3E5, 0x6E1E, 0x9C72,
+	0x6E1F, 0x9C73, 0x6E20, 0xC7FE, 0x6E21, 0xB6C9, 0x6E22, 0x9C74,
+	0x6E23, 0xD4FC, 0x6E24, 0xB2B3, 0x6E25, 0xE4D7, 0x6E26, 0x9C75,
+	0x6E27, 0x9C76, 0x6E28, 0x9C77, 0x6E29, 0xCEC2, 0x6E2A, 0x9C78,
+	0x6E2B, 0xE4CD, 0x6E2C, 0x9C79, 0x6E2D, 0xCEBC, 0x6E2E, 0x9C7A,
+	0x6E2F, 0xB8DB, 0x6E30, 0x9C7B, 0x6E31, 0x9C7C, 0x6E32, 0xE4D6,
+	0x6E33, 0x9C7D, 0x6E34, 0xBFCA, 0x6E35, 0x9C7E, 0x6E36, 0x9C80,
+	0x6E37, 0x9C81, 0x6E38, 0xD3CE, 0x6E39, 0x9C82, 0x6E3A, 0xC3EC,
+	0x6E3B, 0x9C83, 0x6E3C, 0x9C84, 0x6E3D, 0x9C85, 0x6E3E, 0x9C86,
+	0x6E3F, 0x9C87, 0x6E40, 0x9C88, 0x6E41, 0x9C89, 0x6E42, 0x9C8A,
+	0x6E43, 0xC5C8, 0x6E44, 0xE4D8, 0x6E45, 0x9C8B, 0x6E46, 0x9C8C,
+	0x6E47, 0x9C8D, 0x6E48, 0x9C8E, 0x6E49, 0x9C8F, 0x6E4A, 0x9C90,
+	0x6E4B, 0x9C91, 0x6E4C, 0x9C92, 0x6E4D, 0xCDC4, 0x6E4E, 0xE4CF,
+	0x6E4F, 0x9C93, 0x6E50, 0x9C94, 0x6E51, 0x9C95, 0x6E52, 0x9C96,
+	0x6E53, 0xE4D4, 0x6E54, 0xE4D5, 0x6E55, 0x9C97, 0x6E56, 0xBAFE,
+	0x6E57, 0x9C98, 0x6E58, 0xCFE6, 0x6E59, 0x9C99, 0x6E5A, 0x9C9A,
+	0x6E5B, 0xD5BF, 0x6E5C, 0x9C9B, 0x6E5D, 0x9C9C, 0x6E5E, 0x9C9D,
+	0x6E5F, 0xE4D2, 0x6E60, 0x9C9E, 0x6E61, 0x9C9F, 0x6E62, 0x9CA0,
+	0x6E63, 0x9CA1, 0x6E64, 0x9CA2, 0x6E65, 0x9CA3, 0x6E66, 0x9CA4,
+	0x6E67, 0x9CA5, 0x6E68, 0x9CA6, 0x6E69, 0x9CA7, 0x6E6A, 0x9CA8,
+	0x6E6B, 0xE4D0, 0x6E6C, 0x9CA9, 0x6E6D, 0x9CAA, 0x6E6E, 0xE4CE,
+	0x6E6F, 0x9CAB, 0x6E70, 0x9CAC, 0x6E71, 0x9CAD, 0x6E72, 0x9CAE,
+	0x6E73, 0x9CAF, 0x6E74, 0x9CB0, 0x6E75, 0x9CB1, 0x6E76, 0x9CB2,
+	0x6E77, 0x9CB3, 0x6E78, 0x9CB4, 0x6E79, 0x9CB5, 0x6E7A, 0x9CB6,
+	0x6E7B, 0x9CB7, 0x6E7C, 0x9CB8, 0x6E7D, 0x9CB9, 0x6E7E, 0xCDE5,
+	0x6E7F, 0xCAAA, 0x6E80, 0x9CBA, 0x6E81, 0x9CBB, 0x6E82, 0x9CBC,
+	0x6E83, 0xC0A3, 0x6E84, 0x9CBD, 0x6E85, 0xBDA6, 0x6E86, 0xE4D3,
+	0x6E87, 0x9CBE, 0x6E88, 0x9CBF, 0x6E89, 0xB8C8, 0x6E8A, 0x9CC0,
+	0x6E8B, 0x9CC1, 0x6E8C, 0x9CC2, 0x6E8D, 0x9CC3, 0x6E8E, 0x9CC4,
+	0x6E8F, 0xE4E7, 0x6E90, 0xD4B4, 0x6E91, 0x9CC5, 0x6E92, 0x9CC6,
+	0x6E93, 0x9CC7, 0x6E94, 0x9CC8, 0x6E95, 0x9CC9, 0x6E96, 0x9CCA,
+	0x6E97, 0x9CCB, 0x6E98, 0xE4DB, 0x6E99, 0x9CCC, 0x6E9A, 0x9CCD,
+	0x6E9B, 0x9CCE, 0x6E9C, 0xC1EF, 0x6E9D, 0x9CCF, 0x6E9E, 0x9CD0,
+	0x6E9F, 0xE4E9, 0x6EA0, 0x9CD1, 0x6EA1, 0x9CD2, 0x6EA2, 0xD2E7,
+	0x6EA3, 0x9CD3, 0x6EA4, 0x9CD4, 0x6EA5, 0xE4DF, 0x6EA6, 0x9CD5,
+	0x6EA7, 0xE4E0, 0x6EA8, 0x9CD6, 0x6EA9, 0x9CD7, 0x6EAA, 0xCFAA,
+	0x6EAB, 0x9CD8, 0x6EAC, 0x9CD9, 0x6EAD, 0x9CDA, 0x6EAE, 0x9CDB,
+	0x6EAF, 0xCBDD, 0x6EB0, 0x9CDC, 0x6EB1, 0xE4DA, 0x6EB2, 0xE4D1,
+	0x6EB3, 0x9CDD, 0x6EB4, 0xE4E5, 0x6EB5, 0x9CDE, 0x6EB6, 0xC8DC,
+	0x6EB7, 0xE4E3, 0x6EB8, 0x9CDF, 0x6EB9, 0x9CE0, 0x6EBA, 0xC4E7,
+	0x6EBB, 0xE4E2, 0x6EBC, 0x9CE1, 0x6EBD, 0xE4E1, 0x6EBE, 0x9CE2,
+	0x6EBF, 0x9CE3, 0x6EC0, 0x9CE4, 0x6EC1, 0xB3FC, 0x6EC2, 0xE4E8,
+	0x6EC3, 0x9CE5, 0x6EC4, 0x9CE6, 0x6EC5, 0x9CE7, 0x6EC6, 0x9CE8,
+	0x6EC7, 0xB5E1, 0x6EC8, 0x9CE9, 0x6EC9, 0x9CEA, 0x6ECA, 0x9CEB,
+	0x6ECB, 0xD7CC, 0x6ECC, 0x9CEC, 0x6ECD, 0x9CED, 0x6ECE, 0x9CEE,
+	0x6ECF, 0xE4E6, 0x6ED0, 0x9CEF, 0x6ED1, 0xBBAC, 0x6ED2, 0x9CF0,
+	0x6ED3, 0xD7D2, 0x6ED4, 0xCCCF, 0x6ED5, 0xEBF8, 0x6ED6, 0x9CF1,
+	0x6ED7, 0xE4E4, 0x6ED8, 0x9CF2, 0x6ED9, 0x9CF3, 0x6EDA, 0xB9F6,
+	0x6EDB, 0x9CF4, 0x6EDC, 0x9CF5, 0x6EDD, 0x9CF6, 0x6EDE, 0xD6CD,
+	0x6EDF, 0xE4D9, 0x6EE0, 0xE4DC, 0x6EE1, 0xC2FA, 0x6EE2, 0xE4DE,
+	0x6EE3, 0x9CF7, 0x6EE4, 0xC2CB, 0x6EE5, 0xC0C4, 0x6EE6, 0xC2D0,
+	0x6EE7, 0x9CF8, 0x6EE8, 0xB1F5, 0x6EE9, 0xCCB2, 0x6EEA, 0x9CF9,
+	0x6EEB, 0x9CFA, 0x6EEC, 0x9CFB, 0x6EED, 0x9CFC, 0x6EEE, 0x9CFD,
+	0x6EEF, 0x9CFE, 0x6EF0, 0x9D40, 0x6EF1, 0x9D41, 0x6EF2, 0x9D42,
+	0x6EF3, 0x9D43, 0x6EF4, 0xB5CE, 0x6EF5, 0x9D44, 0x6EF6, 0x9D45,
+	0x6EF7, 0x9D46, 0x6EF8, 0x9D47, 0x6EF9, 0xE4EF, 0x6EFA, 0x9D48,
+	0x6EFB, 0x9D49, 0x6EFC, 0x9D4A, 0x6EFD, 0x9D4B, 0x6EFE, 0x9D4C,
+	0x6EFF, 0x9D4D, 0x6F00, 0x9D4E, 0x6F01, 0x9D4F, 0x6F02, 0xC6AF,
+	0x6F03, 0x9D50, 0x6F04, 0x9D51, 0x6F05, 0x9D52, 0x6F06, 0xC6E1,
+	0x6F07, 0x9D53, 0x6F08, 0x9D54, 0x6F09, 0xE4F5, 0x6F0A, 0x9D55,
+	0x6F0B, 0x9D56, 0x6F0C, 0x9D57, 0x6F0D, 0x9D58, 0x6F0E, 0x9D59,
+	0x6F0F, 0xC2A9, 0x6F10, 0x9D5A, 0x6F11, 0x9D5B, 0x6F12, 0x9D5C,
+	0x6F13, 0xC0EC, 0x6F14, 0xD1DD, 0x6F15, 0xE4EE, 0x6F16, 0x9D5D,
+	0x6F17, 0x9D5E, 0x6F18, 0x9D5F, 0x6F19, 0x9D60, 0x6F1A, 0x9D61,
+	0x6F1B, 0x9D62, 0x6F1C, 0x9D63, 0x6F1D, 0x9D64, 0x6F1E, 0x9D65,
+	0x6F1F, 0x9D66, 0x6F20, 0xC4AE, 0x6F21, 0x9D67, 0x6F22, 0x9D68,
+	0x6F23, 0x9D69, 0x6F24, 0xE4ED, 0x6F25, 0x9D6A, 0x6F26, 0x9D6B,
+	0x6F27, 0x9D6C, 0x6F28, 0x9D6D, 0x6F29, 0xE4F6, 0x6F2A, 0xE4F4,
+	0x6F2B, 0xC2FE, 0x6F2C, 0x9D6E, 0x6F2D, 0xE4DD, 0x6F2E, 0x9D6F,
+	0x6F2F, 0xE4F0, 0x6F30, 0x9D70, 0x6F31, 0xCAFE, 0x6F32, 0x9D71,
+	0x6F33, 0xD5C4, 0x6F34, 0x9D72, 0x6F35, 0x9D73, 0x6F36, 0xE4F1,
+	0x6F37, 0x9D74, 0x6F38, 0x9D75, 0x6F39, 0x9D76, 0x6F3A, 0x9D77,
+	0x6F3B, 0x9D78, 0x6F3C, 0x9D79, 0x6F3D, 0x9D7A, 0x6F3E, 0xD1FA,
+	0x6F3F, 0x9D7B, 0x6F40, 0x9D7C, 0x6F41, 0x9D7D, 0x6F42, 0x9D7E,
+	0x6F43, 0x9D80, 0x6F44, 0x9D81, 0x6F45, 0x9D82, 0x6F46, 0xE4EB,
+	0x6F47, 0xE4EC, 0x6F48, 0x9D83, 0x6F49, 0x9D84, 0x6F4A, 0x9D85,
+	0x6F4B, 0xE4F2, 0x6F4C, 0x9D86, 0x6F4D, 0xCEAB, 0x6F4E, 0x9D87,
+	0x6F4F, 0x9D88, 0x6F50, 0x9D89, 0x6F51, 0x9D8A, 0x6F52, 0x9D8B,
+	0x6F53, 0x9D8C, 0x6F54, 0x9D8D, 0x6F55, 0x9D8E, 0x6F56, 0x9D8F,
+	0x6F57, 0x9D90, 0x6F58, 0xC5CB, 0x6F59, 0x9D91, 0x6F5A, 0x9D92,
+	0x6F5B, 0x9D93, 0x6F5C, 0xC7B1, 0x6F5D, 0x9D94, 0x6F5E, 0xC2BA,
+	0x6F5F, 0x9D95, 0x6F60, 0x9D96, 0x6F61, 0x9D97, 0x6F62, 0xE4EA,
+	0x6F63, 0x9D98, 0x6F64, 0x9D99, 0x6F65, 0x9D9A, 0x6F66, 0xC1CA,
+	0x6F67, 0x9D9B, 0x6F68, 0x9D9C, 0x6F69, 0x9D9D, 0x6F6A, 0x9D9E,
+	0x6F6B, 0x9D9F, 0x6F6C, 0x9DA0, 0x6F6D, 0xCCB6, 0x6F6E, 0xB3B1,
+	0x6F6F, 0x9DA1, 0x6F70, 0x9DA2, 0x6F71, 0x9DA3, 0x6F72, 0xE4FB,
+	0x6F73, 0x9DA4, 0x6F74, 0xE4F3, 0x6F75, 0x9DA5, 0x6F76, 0x9DA6,
+	0x6F77, 0x9DA7, 0x6F78, 0xE4FA, 0x6F79, 0x9DA8, 0x6F7A, 0xE4FD,
+	0x6F7B, 0x9DA9, 0x6F7C, 0xE4FC, 0x6F7D, 0x9DAA, 0x6F7E, 0x9DAB,
+	0x6F7F, 0x9DAC, 0x6F80, 0x9DAD, 0x6F81, 0x9DAE, 0x6F82, 0x9DAF,
+	0x6F83, 0x9DB0, 0x6F84, 0xB3CE, 0x6F85, 0x9DB1, 0x6F86, 0x9DB2,
+	0x6F87, 0x9DB3, 0x6F88, 0xB3BA, 0x6F89, 0xE4F7, 0x6F8A, 0x9DB4,
+	0x6F8B, 0x9DB5, 0x6F8C, 0xE4F9, 0x6F8D, 0xE4F8, 0x6F8E, 0xC5EC,
+	0x6F8F, 0x9DB6, 0x6F90, 0x9DB7, 0x6F91, 0x9DB8, 0x6F92, 0x9DB9,
+	0x6F93, 0x9DBA, 0x6F94, 0x9DBB, 0x6F95, 0x9DBC, 0x6F96, 0x9DBD,
+	0x6F97, 0x9DBE, 0x6F98, 0x9DBF, 0x6F99, 0x9DC0, 0x6F9A, 0x9DC1,
+	0x6F9B, 0x9DC2, 0x6F9C, 0xC0BD, 0x6F9D, 0x9DC3, 0x6F9E, 0x9DC4,
+	0x6F9F, 0x9DC5, 0x6FA0, 0x9DC6, 0x6FA1, 0xD4E8, 0x6FA2, 0x9DC7,
+	0x6FA3, 0x9DC8, 0x6FA4, 0x9DC9, 0x6FA5, 0x9DCA, 0x6FA6, 0x9DCB,
+	0x6FA7, 0xE5A2, 0x6FA8, 0x9DCC, 0x6FA9, 0x9DCD, 0x6FAA, 0x9DCE,
+	0x6FAB, 0x9DCF, 0x6FAC, 0x9DD0, 0x6FAD, 0x9DD1, 0x6FAE, 0x9DD2,
+	0x6FAF, 0x9DD3, 0x6FB0, 0x9DD4, 0x6FB1, 0x9DD5, 0x6FB2, 0x9DD6,
+	0x6FB3, 0xB0C4, 0x6FB4, 0x9DD7, 0x6FB5, 0x9DD8, 0x6FB6, 0xE5A4,
+	0x6FB7, 0x9DD9, 0x6FB8, 0x9DDA, 0x6FB9, 0xE5A3, 0x6FBA, 0x9DDB,
+	0x6FBB, 0x9DDC, 0x6FBC, 0x9DDD, 0x6FBD, 0x9DDE, 0x6FBE, 0x9DDF,
+	0x6FBF, 0x9DE0, 0x6FC0, 0xBCA4, 0x6FC1, 0x9DE1, 0x6FC2, 0xE5A5,
+	0x6FC3, 0x9DE2, 0x6FC4, 0x9DE3, 0x6FC5, 0x9DE4, 0x6FC6, 0x9DE5,
+	0x6FC7, 0x9DE6, 0x6FC8, 0x9DE7, 0x6FC9, 0xE5A1, 0x6FCA, 0x9DE8,
+	0x6FCB, 0x9DE9, 0x6FCC, 0x9DEA, 0x6FCD, 0x9DEB, 0x6FCE, 0x9DEC,
+	0x6FCF, 0x9DED, 0x6FD0, 0x9DEE, 0x6FD1, 0xE4FE, 0x6FD2, 0xB1F4,
+	0x6FD3, 0x9DEF, 0x6FD4, 0x9DF0, 0x6FD5, 0x9DF1, 0x6FD6, 0x9DF2,
+	0x6FD7, 0x9DF3, 0x6FD8, 0x9DF4, 0x6FD9, 0x9DF5, 0x6FDA, 0x9DF6,
+	0x6FDB, 0x9DF7, 0x6FDC, 0x9DF8, 0x6FDD, 0x9DF9, 0x6FDE, 0xE5A8,
+	0x6FDF, 0x9DFA, 0x6FE0, 0xE5A9, 0x6FE1, 0xE5A6, 0x6FE2, 0x9DFB,
+	0x6FE3, 0x9DFC, 0x6FE4, 0x9DFD, 0x6FE5, 0x9DFE, 0x6FE6, 0x9E40,
+	0x6FE7, 0x9E41, 0x6FE8, 0x9E42, 0x6FE9, 0x9E43, 0x6FEA, 0x9E44,
+	0x6FEB, 0x9E45, 0x6FEC, 0x9E46, 0x6FED, 0x9E47, 0x6FEE, 0xE5A7,
+	0x6FEF, 0xE5AA, 0x6FF0, 0x9E48, 0x6FF1, 0x9E49, 0x6FF2, 0x9E4A,
+	0x6FF3, 0x9E4B, 0x6FF4, 0x9E4C, 0x6FF5, 0x9E4D, 0x6FF6, 0x9E4E,
+	0x6FF7, 0x9E4F, 0x6FF8, 0x9E50, 0x6FF9, 0x9E51, 0x6FFA, 0x9E52,
+	0x6FFB, 0x9E53, 0x6FFC, 0x9E54, 0x6FFD, 0x9E55, 0x6FFE, 0x9E56,
+	0x6FFF, 0x9E57, 0x7000, 0x9E58, 0x7001, 0x9E59, 0x7002, 0x9E5A,
+	0x7003, 0x9E5B, 0x7004, 0x9E5C, 0x7005, 0x9E5D, 0x7006, 0x9E5E,
+	0x7007, 0x9E5F, 0x7008, 0x9E60, 0x7009, 0x9E61, 0x700A, 0x9E62,
+	0x700B, 0x9E63, 0x700C, 0x9E64, 0x700D, 0x9E65, 0x700E, 0x9E66,
+	0x700F, 0x9E67, 0x7010, 0x9E68, 0x7011, 0xC6D9, 0x7012, 0x9E69,
+	0x7013, 0x9E6A, 0x7014, 0x9E6B, 0x7015, 0x9E6C, 0x7016, 0x9E6D,
+	0x7017, 0x9E6E, 0x7018, 0x9E6F, 0x7019, 0x9E70, 0x701A, 0xE5AB,
+	0x701B, 0xE5AD, 0x701C, 0x9E71, 0x701D, 0x9E72, 0x701E, 0x9E73,
+	0x701F, 0x9E74, 0x7020, 0x9E75, 0x7021, 0x9E76, 0x7022, 0x9E77,
+	0x7023, 0xE5AC, 0x7024, 0x9E78, 0x7025, 0x9E79, 0x7026, 0x9E7A,
+	0x7027, 0x9E7B, 0x7028, 0x9E7C, 0x7029, 0x9E7D, 0x702A, 0x9E7E,
+	0x702B, 0x9E80, 0x702C, 0x9E81, 0x702D, 0x9E82, 0x702E, 0x9E83,
+	0x702F, 0x9E84, 0x7030, 0x9E85, 0x7031, 0x9E86, 0x7032, 0x9E87,
+	0x7033, 0x9E88, 0x7034, 0x9E89, 0x7035, 0xE5AF, 0x7036, 0x9E8A,
+	0x7037, 0x9E8B, 0x7038, 0x9E8C, 0x7039, 0xE5AE, 0x703A, 0x9E8D,
+	0x703B, 0x9E8E, 0x703C, 0x9E8F, 0x703D, 0x9E90, 0x703E, 0x9E91,
+	0x703F, 0x9E92, 0x7040, 0x9E93, 0x7041, 0x9E94, 0x7042, 0x9E95,
+	0x7043, 0x9E96, 0x7044, 0x9E97, 0x7045, 0x9E98, 0x7046, 0x9E99,
+	0x7047, 0x9E9A, 0x7048, 0x9E9B, 0x7049, 0x9E9C, 0x704A, 0x9E9D,
+	0x704B, 0x9E9E, 0x704C, 0xB9E0, 0x704D, 0x9E9F, 0x704E, 0x9EA0,
+	0x704F, 0xE5B0, 0x7050, 0x9EA1, 0x7051, 0x9EA2, 0x7052, 0x9EA3,
+	0x7053, 0x9EA4, 0x7054, 0x9EA5, 0x7055, 0x9EA6, 0x7056, 0x9EA7,
+	0x7057, 0x9EA8, 0x7058, 0x9EA9, 0x7059, 0x9EAA, 0x705A, 0x9EAB,
+	0x705B, 0x9EAC, 0x705C, 0x9EAD, 0x705D, 0x9EAE, 0x705E, 0xE5B1,
+	0x705F, 0x9EAF, 0x7060, 0x9EB0, 0x7061, 0x9EB1, 0x7062, 0x9EB2,
+	0x7063, 0x9EB3, 0x7064, 0x9EB4, 0x7065, 0x9EB5, 0x7066, 0x9EB6,
+	0x7067, 0x9EB7, 0x7068, 0x9EB8, 0x7069, 0x9EB9, 0x706A, 0x9EBA,
+	0x706B, 0xBBF0, 0x706C, 0xECE1, 0x706D, 0xC3F0, 0x706E, 0x9EBB,
+	0x706F, 0xB5C6, 0x7070, 0xBBD2, 0x7071, 0x9EBC, 0x7072, 0x9EBD,
+	0x7073, 0x9EBE, 0x7074, 0x9EBF, 0x7075, 0xC1E9, 0x7076, 0xD4EE,
+	0x7077, 0x9EC0, 0x7078, 0xBEC4, 0x7079, 0x9EC1, 0x707A, 0x9EC2,
+	0x707B, 0x9EC3, 0x707C, 0xD7C6, 0x707D, 0x9EC4, 0x707E, 0xD4D6,
+	0x707F, 0xB2D3, 0x7080, 0xECBE, 0x7081, 0x9EC5, 0x7082, 0x9EC6,
+	0x7083, 0x9EC7, 0x7084, 0x9EC8, 0x7085, 0xEAC1, 0x7086, 0x9EC9,
+	0x7087, 0x9ECA, 0x7088, 0x9ECB, 0x7089, 0xC2AF, 0x708A, 0xB4B6,
+	0x708B, 0x9ECC, 0x708C, 0x9ECD, 0x708D, 0x9ECE, 0x708E, 0xD1D7,
+	0x708F, 0x9ECF, 0x7090, 0x9ED0, 0x7091, 0x9ED1, 0x7092, 0xB3B4,
+	0x7093, 0x9ED2, 0x7094, 0xC8B2, 0x7095, 0xBFBB, 0x7096, 0xECC0,
+	0x7097, 0x9ED3, 0x7098, 0x9ED4, 0x7099, 0xD6CB, 0x709A, 0x9ED5,
+	0x709B, 0x9ED6, 0x709C, 0xECBF, 0x709D, 0xECC1, 0x709E, 0x9ED7,
+	0x709F, 0x9ED8, 0x70A0, 0x9ED9, 0x70A1, 0x9EDA, 0x70A2, 0x9EDB,
+	0x70A3, 0x9EDC, 0x70A4, 0x9EDD, 0x70A5, 0x9EDE, 0x70A6, 0x9EDF,
+	0x70A7, 0x9EE0, 0x70A8, 0x9EE1, 0x70A9, 0x9EE2, 0x70AA, 0x9EE3,
+	0x70AB, 0xECC5, 0x70AC, 0xBEE6, 0x70AD, 0xCCBF, 0x70AE, 0xC5DA,
+	0x70AF, 0xBEBC, 0x70B0, 0x9EE4, 0x70B1, 0xECC6, 0x70B2, 0x9EE5,
+	0x70B3, 0xB1FE, 0x70B4, 0x9EE6, 0x70B5, 0x9EE7, 0x70B6, 0x9EE8,
+	0x70B7, 0xECC4, 0x70B8, 0xD5A8, 0x70B9, 0xB5E3, 0x70BA, 0x9EE9,
+	0x70BB, 0xECC2, 0x70BC, 0xC1B6, 0x70BD, 0xB3E3, 0x70BE, 0x9EEA,
+	0x70BF, 0x9EEB, 0x70C0, 0xECC3, 0x70C1, 0xCBB8, 0x70C2, 0xC0C3,
+	0x70C3, 0xCCFE, 0x70C4, 0x9EEC, 0x70C5, 0x9EED, 0x70C6, 0x9EEE,
+	0x70C7, 0x9EEF, 0x70C8, 0xC1D2, 0x70C9, 0x9EF0, 0x70CA, 0xECC8,
+	0x70CB, 0x9EF1, 0x70CC, 0x9EF2, 0x70CD, 0x9EF3, 0x70CE, 0x9EF4,
+	0x70CF, 0x9EF5, 0x70D0, 0x9EF6, 0x70D1, 0x9EF7, 0x70D2, 0x9EF8,
+	0x70D3, 0x9EF9, 0x70D4, 0x9EFA, 0x70D5, 0x9EFB, 0x70D6, 0x9EFC,
+	0x70D7, 0x9EFD, 0x70D8, 0xBAE6, 0x70D9, 0xC0D3, 0x70DA, 0x9EFE,
+	0x70DB, 0xD6F2, 0x70DC, 0x9F40, 0x70DD, 0x9F41, 0x70DE, 0x9F42,
+	0x70DF, 0xD1CC, 0x70E0, 0x9F43, 0x70E1, 0x9F44, 0x70E2, 0x9F45,
+	0x70E3, 0x9F46, 0x70E4, 0xBFBE, 0x70E5, 0x9F47, 0x70E6, 0xB7B3,
+	0x70E7, 0xC9D5, 0x70E8, 0xECC7, 0x70E9, 0xBBE2, 0x70EA, 0x9F48,
+	0x70EB, 0xCCCC, 0x70EC, 0xBDFD, 0x70ED, 0xC8C8, 0x70EE, 0x9F49,
+	0x70EF, 0xCFA9, 0x70F0, 0x9F4A, 0x70F1, 0x9F4B, 0x70F2, 0x9F4C,
+	0x70F3, 0x9F4D, 0x70F4, 0x9F4E, 0x70F5, 0x9F4F, 0x70F6, 0x9F50,
+	0x70F7, 0xCDE9, 0x70F8, 0x9F51, 0x70F9, 0xC5EB, 0x70FA, 0x9F52,
+	0x70FB, 0x9F53, 0x70FC, 0x9F54, 0x70FD, 0xB7E9, 0x70FE, 0x9F55,
+	0x70FF, 0x9F56, 0x7100, 0x9F57, 0x7101, 0x9F58, 0x7102, 0x9F59,
+	0x7103, 0x9F5A, 0x7104, 0x9F5B, 0x7105, 0x9F5C, 0x7106, 0x9F5D,
+	0x7107, 0x9F5E, 0x7108, 0x9F5F, 0x7109, 0xD1C9, 0x710A, 0xBAB8,
+	0x710B, 0x9F60, 0x710C, 0x9F61, 0x710D, 0x9F62, 0x710E, 0x9F63,
+	0x710F, 0x9F64, 0x7110, 0xECC9, 0x7111, 0x9F65, 0x7112, 0x9F66,
+	0x7113, 0xECCA, 0x7114, 0x9F67, 0x7115, 0xBBC0, 0x7116, 0xECCB,
+	0x7117, 0x9F68, 0x7118, 0xECE2, 0x7119, 0xB1BA, 0x711A, 0xB7D9,
+	0x711B, 0x9F69, 0x711C, 0x9F6A, 0x711D, 0x9F6B, 0x711E, 0x9F6C,
+	0x711F, 0x9F6D, 0x7120, 0x9F6E, 0x7121, 0x9F6F, 0x7122, 0x9F70,
+	0x7123, 0x9F71, 0x7124, 0x9F72, 0x7125, 0x9F73, 0x7126, 0xBDB9,
+	0x7127, 0x9F74, 0x7128, 0x9F75, 0x7129, 0x9F76, 0x712A, 0x9F77,
+	0x712B, 0x9F78, 0x712C, 0x9F79, 0x712D, 0x9F7A, 0x712E, 0x9F7B,
+	0x712F, 0xECCC, 0x7130, 0xD1E6, 0x7131, 0xECCD, 0x7132, 0x9F7C,
+	0x7133, 0x9F7D, 0x7134, 0x9F7E, 0x7135, 0x9F80, 0x7136, 0xC8BB,
+	0x7137, 0x9F81, 0x7138, 0x9F82, 0x7139, 0x9F83, 0x713A, 0x9F84,
+	0x713B, 0x9F85, 0x713C, 0x9F86, 0x713D, 0x9F87, 0x713E, 0x9F88,
+	0x713F, 0x9F89, 0x7140, 0x9F8A, 0x7141, 0x9F8B, 0x7142, 0x9F8C,
+	0x7143, 0x9F8D, 0x7144, 0x9F8E, 0x7145, 0xECD1, 0x7146, 0x9F8F,
+	0x7147, 0x9F90, 0x7148, 0x9F91, 0x7149, 0x9F92, 0x714A, 0xECD3,
+	0x714B, 0x9F93, 0x714C, 0xBBCD, 0x714D, 0x9F94, 0x714E, 0xBCE5,
+	0x714F, 0x9F95, 0x7150, 0x9F96, 0x7151, 0x9F97, 0x7152, 0x9F98,
+	0x7153, 0x9F99, 0x7154, 0x9F9A, 0x7155, 0x9F9B, 0x7156, 0x9F9C,
+	0x7157, 0x9F9D, 0x7158, 0x9F9E, 0x7159, 0x9F9F, 0x715A, 0x9FA0,
+	0x715B, 0x9FA1, 0x715C, 0xECCF, 0x715D, 0x9FA2, 0x715E, 0xC9B7,
+	0x715F, 0x9FA3, 0x7160, 0x9FA4, 0x7161, 0x9FA5, 0x7162, 0x9FA6,
+	0x7163, 0x9FA7, 0x7164, 0xC3BA, 0x7165, 0x9FA8, 0x7166, 0xECE3,
+	0x7167, 0xD5D5, 0x7168, 0xECD0, 0x7169, 0x9FA9, 0x716A, 0x9FAA,
+	0x716B, 0x9FAB, 0x716C, 0x9FAC, 0x716D, 0x9FAD, 0x716E, 0xD6F3,
+	0x716F, 0x9FAE, 0x7170, 0x9FAF, 0x7171, 0x9FB0, 0x7172, 0xECD2,
+	0x7173, 0xECCE, 0x7174, 0x9FB1, 0x7175, 0x9FB2, 0x7176, 0x9FB3,
+	0x7177, 0x9FB4, 0x7178, 0xECD4, 0x7179, 0x9FB5, 0x717A, 0xECD5,
+	0x717B, 0x9FB6, 0x717C, 0x9FB7, 0x717D, 0xC9BF, 0x717E, 0x9FB8,
+	0x717F, 0x9FB9, 0x7180, 0x9FBA, 0x7181, 0x9FBB, 0x7182, 0x9FBC,
+	0x7183, 0x9FBD, 0x7184, 0xCFA8, 0x7185, 0x9FBE, 0x7186, 0x9FBF,
+	0x7187, 0x9FC0, 0x7188, 0x9FC1, 0x7189, 0x9FC2, 0x718A, 0xD0DC,
+	0x718B, 0x9FC3, 0x718C, 0x9FC4, 0x718D, 0x9FC5, 0x718E, 0x9FC6,
+	0x718F, 0xD1AC, 0x7190, 0x9FC7, 0x7191, 0x9FC8, 0x7192, 0x9FC9,
+	0x7193, 0x9FCA, 0x7194, 0xC8DB, 0x7195, 0x9FCB, 0x7196, 0x9FCC,
+	0x7197, 0x9FCD, 0x7198, 0xECD6, 0x7199, 0xCEF5, 0x719A, 0x9FCE,
+	0x719B, 0x9FCF, 0x719C, 0x9FD0, 0x719D, 0x9FD1, 0x719E, 0x9FD2,
+	0x719F, 0xCAEC, 0x71A0, 0xECDA, 0x71A1, 0x9FD3, 0x71A2, 0x9FD4,
+	0x71A3, 0x9FD5, 0x71A4, 0x9FD6, 0x71A5, 0x9FD7, 0x71A6, 0x9FD8,
+	0x71A7, 0x9FD9, 0x71A8, 0xECD9, 0x71A9, 0x9FDA, 0x71AA, 0x9FDB,
+	0x71AB, 0x9FDC, 0x71AC, 0xB0BE, 0x71AD, 0x9FDD, 0x71AE, 0x9FDE,
+	0x71AF, 0x9FDF, 0x71B0, 0x9FE0, 0x71B1, 0x9FE1, 0x71B2, 0x9FE2,
+	0x71B3, 0xECD7, 0x71B4, 0x9FE3, 0x71B5, 0xECD8, 0x71B6, 0x9FE4,
+	0x71B7, 0x9FE5, 0x71B8, 0x9FE6, 0x71B9, 0xECE4, 0x71BA, 0x9FE7,
+	0x71BB, 0x9FE8, 0x71BC, 0x9FE9, 0x71BD, 0x9FEA, 0x71BE, 0x9FEB,
+	0x71BF, 0x9FEC, 0x71C0, 0x9FED, 0x71C1, 0x9FEE, 0x71C2, 0x9FEF,
+	0x71C3, 0xC8BC, 0x71C4, 0x9FF0, 0x71C5, 0x9FF1, 0x71C6, 0x9FF2,
+	0x71C7, 0x9FF3, 0x71C8, 0x9FF4, 0x71C9, 0x9FF5, 0x71CA, 0x9FF6,
+	0x71CB, 0x9FF7, 0x71CC, 0x9FF8, 0x71CD, 0x9FF9, 0x71CE, 0xC1C7,
+	0x71CF, 0x9FFA, 0x71D0, 0x9FFB, 0x71D1, 0x9FFC, 0x71D2, 0x9FFD,
+	0x71D3, 0x9FFE, 0x71D4, 0xECDC, 0x71D5, 0xD1E0, 0x71D6, 0xA040,
+	0x71D7, 0xA041, 0x71D8, 0xA042, 0x71D9, 0xA043, 0x71DA, 0xA044,
+	0x71DB, 0xA045, 0x71DC, 0xA046, 0x71DD, 0xA047, 0x71DE, 0xA048,
+	0x71DF, 0xA049, 0x71E0, 0xECDB, 0x71E1, 0xA04A, 0x71E2, 0xA04B,
+	0x71E3, 0xA04C, 0x71E4, 0xA04D, 0x71E5, 0xD4EF, 0x71E6, 0xA04E,
+	0x71E7, 0xECDD, 0x71E8, 0xA04F, 0x71E9, 0xA050, 0x71EA, 0xA051,
+	0x71EB, 0xA052, 0x71EC, 0xA053, 0x71ED, 0xA054, 0x71EE, 0xDBC6,
+	0x71EF, 0xA055, 0x71F0, 0xA056, 0x71F1, 0xA057, 0x71F2, 0xA058,
+	0x71F3, 0xA059, 0x71F4, 0xA05A, 0x71F5, 0xA05B, 0x71F6, 0xA05C,
+	0x71F7, 0xA05D, 0x71F8, 0xA05E, 0x71F9, 0xECDE, 0x71FA, 0xA05F,
+	0x71FB, 0xA060, 0x71FC, 0xA061, 0x71FD, 0xA062, 0x71FE, 0xA063,
+	0x71FF, 0xA064, 0x7200, 0xA065, 0x7201, 0xA066, 0x7202, 0xA067,
+	0x7203, 0xA068, 0x7204, 0xA069, 0x7205, 0xA06A, 0x7206, 0xB1AC,
+	0x7207, 0xA06B, 0x7208, 0xA06C, 0x7209, 0xA06D, 0x720A, 0xA06E,
+	0x720B, 0xA06F, 0x720C, 0xA070, 0x720D, 0xA071, 0x720E, 0xA072,
+	0x720F, 0xA073, 0x7210, 0xA074, 0x7211, 0xA075, 0x7212, 0xA076,
+	0x7213, 0xA077, 0x7214, 0xA078, 0x7215, 0xA079, 0x7216, 0xA07A,
+	0x7217, 0xA07B, 0x7218, 0xA07C, 0x7219, 0xA07D, 0x721A, 0xA07E,
+	0x721B, 0xA080, 0x721C, 0xA081, 0x721D, 0xECDF, 0x721E, 0xA082,
+	0x721F, 0xA083, 0x7220, 0xA084, 0x7221, 0xA085, 0x7222, 0xA086,
+	0x7223, 0xA087, 0x7224, 0xA088, 0x7225, 0xA089, 0x7226, 0xA08A,
+	0x7227, 0xA08B, 0x7228, 0xECE0, 0x7229, 0xA08C, 0x722A, 0xD7A6,
+	0x722B, 0xA08D, 0x722C, 0xC5C0, 0x722D, 0xA08E, 0x722E, 0xA08F,
+	0x722F, 0xA090, 0x7230, 0xEBBC, 0x7231, 0xB0AE, 0x7232, 0xA091,
+	0x7233, 0xA092, 0x7234, 0xA093, 0x7235, 0xBEF4, 0x7236, 0xB8B8,
+	0x7237, 0xD2AF, 0x7238, 0xB0D6, 0x7239, 0xB5F9, 0x723A, 0xA094,
+	0x723B, 0xD8B3, 0x723C, 0xA095, 0x723D, 0xCBAC, 0x723E, 0xA096,
+	0x723F, 0xE3DD, 0x7240, 0xA097, 0x7241, 0xA098, 0x7242, 0xA099,
+	0x7243, 0xA09A, 0x7244, 0xA09B, 0x7245, 0xA09C, 0x7246, 0xA09D,
+	0x7247, 0xC6AC, 0x7248, 0xB0E6, 0x7249, 0xA09E, 0x724A, 0xA09F,
+	0x724B, 0xA0A0, 0x724C, 0xC5C6, 0x724D, 0xEBB9, 0x724E, 0xA0A1,
+	0x724F, 0xA0A2, 0x7250, 0xA0A3, 0x7251, 0xA0A4, 0x7252, 0xEBBA,
+	0x7253, 0xA0A5, 0x7254, 0xA0A6, 0x7255, 0xA0A7, 0x7256, 0xEBBB,
+	0x7257, 0xA0A8, 0x7258, 0xA0A9, 0x7259, 0xD1C0, 0x725A, 0xA0AA,
+	0x725B, 0xC5A3, 0x725C, 0xA0AB, 0x725D, 0xEAF2, 0x725E, 0xA0AC,
+	0x725F, 0xC4B2, 0x7260, 0xA0AD, 0x7261, 0xC4B5, 0x7262, 0xC0CE,
+	0x7263, 0xA0AE, 0x7264, 0xA0AF, 0x7265, 0xA0B0, 0x7266, 0xEAF3,
+	0x7267, 0xC4C1, 0x7268, 0xA0B1, 0x7269, 0xCEEF, 0x726A, 0xA0B2,
+	0x726B, 0xA0B3, 0x726C, 0xA0B4, 0x726D, 0xA0B5, 0x726E, 0xEAF0,
+	0x726F, 0xEAF4, 0x7270, 0xA0B6, 0x7271, 0xA0B7, 0x7272, 0xC9FC,
+	0x7273, 0xA0B8, 0x7274, 0xA0B9, 0x7275, 0xC7A3, 0x7276, 0xA0BA,
+	0x7277, 0xA0BB, 0x7278, 0xA0BC, 0x7279, 0xCCD8, 0x727A, 0xCEFE,
+	0x727B, 0xA0BD, 0x727C, 0xA0BE, 0x727D, 0xA0BF, 0x727E, 0xEAF5,
+	0x727F, 0xEAF6, 0x7280, 0xCFAC, 0x7281, 0xC0E7, 0x7282, 0xA0C0,
+	0x7283, 0xA0C1, 0x7284, 0xEAF7, 0x7285, 0xA0C2, 0x7286, 0xA0C3,
+	0x7287, 0xA0C4, 0x7288, 0xA0C5, 0x7289, 0xA0C6, 0x728A, 0xB6BF,
+	0x728B, 0xEAF8, 0x728C, 0xA0C7, 0x728D, 0xEAF9, 0x728E, 0xA0C8,
+	0x728F, 0xEAFA, 0x7290, 0xA0C9, 0x7291, 0xA0CA, 0x7292, 0xEAFB,
+	0x7293, 0xA0CB, 0x7294, 0xA0CC, 0x7295, 0xA0CD, 0x7296, 0xA0CE,
+	0x7297, 0xA0CF, 0x7298, 0xA0D0, 0x7299, 0xA0D1, 0x729A, 0xA0D2,
+	0x729B, 0xA0D3, 0x729C, 0xA0D4, 0x729D, 0xA0D5, 0x729E, 0xA0D6,
+	0x729F, 0xEAF1, 0x72A0, 0xA0D7, 0x72A1, 0xA0D8, 0x72A2, 0xA0D9,
+	0x72A3, 0xA0DA, 0x72A4, 0xA0DB, 0x72A5, 0xA0DC, 0x72A6, 0xA0DD,
+	0x72A7, 0xA0DE, 0x72A8, 0xA0DF, 0x72A9, 0xA0E0, 0x72AA, 0xA0E1,
+	0x72AB, 0xA0E2, 0x72AC, 0xC8AE, 0x72AD, 0xE1EB, 0x72AE, 0xA0E3,
+	0x72AF, 0xB7B8, 0x72B0, 0xE1EC, 0x72B1, 0xA0E4, 0x72B2, 0xA0E5,
+	0x72B3, 0xA0E6, 0x72B4, 0xE1ED, 0x72B5, 0xA0E7, 0x72B6, 0xD7B4,
+	0x72B7, 0xE1EE, 0x72B8, 0xE1EF, 0x72B9, 0xD3CC, 0x72BA, 0xA0E8,
+	0x72BB, 0xA0E9, 0x72BC, 0xA0EA, 0x72BD, 0xA0EB, 0x72BE, 0xA0EC,
+	0x72BF, 0xA0ED, 0x72C0, 0xA0EE, 0x72C1, 0xE1F1, 0x72C2, 0xBFF1,
+	0x72C3, 0xE1F0, 0x72C4, 0xB5D2, 0x72C5, 0xA0EF, 0x72C6, 0xA0F0,
+	0x72C7, 0xA0F1, 0x72C8, 0xB1B7, 0x72C9, 0xA0F2, 0x72CA, 0xA0F3,
+	0x72CB, 0xA0F4, 0x72CC, 0xA0F5, 0x72CD, 0xE1F3, 0x72CE, 0xE1F2,
+	0x72CF, 0xA0F6, 0x72D0, 0xBAFC, 0x72D1, 0xA0F7, 0x72D2, 0xE1F4,
+	0x72D3, 0xA0F8, 0x72D4, 0xA0F9, 0x72D5, 0xA0FA, 0x72D6, 0xA0FB,
+	0x72D7, 0xB9B7, 0x72D8, 0xA0FC, 0x72D9, 0xBED1, 0x72DA, 0xA0FD,
+	0x72DB, 0xA0FE, 0x72DC, 0xAA40, 0x72DD, 0xAA41, 0x72DE, 0xC4FC,
+	0x72DF, 0xAA42, 0x72E0, 0xBADD, 0x72E1, 0xBDC6, 0x72E2, 0xAA43,
+	0x72E3, 0xAA44, 0x72E4, 0xAA45, 0x72E5, 0xAA46, 0x72E6, 0xAA47,
+	0x72E7, 0xAA48, 0x72E8, 0xE1F5, 0x72E9, 0xE1F7, 0x72EA, 0xAA49,
+	0x72EB, 0xAA4A, 0x72EC, 0xB6C0, 0x72ED, 0xCFC1, 0x72EE, 0xCAA8,
+	0x72EF, 0xE1F6, 0x72F0, 0xD5F8, 0x72F1, 0xD3FC, 0x72F2, 0xE1F8,
+	0x72F3, 0xE1FC, 0x72F4, 0xE1F9, 0x72F5, 0xAA4B, 0x72F6, 0xAA4C,
+	0x72F7, 0xE1FA, 0x72F8, 0xC0EA, 0x72F9, 0xAA4D, 0x72FA, 0xE1FE,
+	0x72FB, 0xE2A1, 0x72FC, 0xC0C7, 0x72FD, 0xAA4E, 0x72FE, 0xAA4F,
+	0x72FF, 0xAA50, 0x7300, 0xAA51, 0x7301, 0xE1FB, 0x7302, 0xAA52,
+	0x7303, 0xE1FD, 0x7304, 0xAA53, 0x7305, 0xAA54, 0x7306, 0xAA55,
+	0x7307, 0xAA56, 0x7308, 0xAA57, 0x7309, 0xAA58, 0x730A, 0xE2A5,
+	0x730B, 0xAA59, 0x730C, 0xAA5A, 0x730D, 0xAA5B, 0x730E, 0xC1D4,
+	0x730F, 0xAA5C, 0x7310, 0xAA5D, 0x7311, 0xAA5E, 0x7312, 0xAA5F,
+	0x7313, 0xE2A3, 0x7314, 0xAA60, 0x7315, 0xE2A8, 0x7316, 0xB2FE,
+	0x7317, 0xE2A2, 0x7318, 0xAA61, 0x7319, 0xAA62, 0x731A, 0xAA63,
+	0x731B, 0xC3CD, 0x731C, 0xB2C2, 0x731D, 0xE2A7, 0x731E, 0xE2A6,
+	0x731F, 0xAA64, 0x7320, 0xAA65, 0x7321, 0xE2A4, 0x7322, 0xE2A9,
+	0x7323, 0xAA66, 0x7324, 0xAA67, 0x7325, 0xE2AB, 0x7326, 0xAA68,
+	0x7327, 0xAA69, 0x7328, 0xAA6A, 0x7329, 0xD0C9, 0x732A, 0xD6ED,
+	0x732B, 0xC3A8, 0x732C, 0xE2AC, 0x732D, 0xAA6B, 0x732E, 0xCFD7,
+	0x732F, 0xAA6C, 0x7330, 0xAA6D, 0x7331, 0xE2AE, 0x7332, 0xAA6E,
+	0x7333, 0xAA6F, 0x7334, 0xBAEF, 0x7335, 0xAA70, 0x7336, 0xAA71,
+	0x7337, 0xE9E0, 0x7338, 0xE2AD, 0x7339, 0xE2AA, 0x733A, 0xAA72,
+	0x733B, 0xAA73, 0x733C, 0xAA74, 0x733D, 0xAA75, 0x733E, 0xBBAB,
+	0x733F, 0xD4B3, 0x7340, 0xAA76, 0x7341, 0xAA77, 0x7342, 0xAA78,
+	0x7343, 0xAA79, 0x7344, 0xAA7A, 0x7345, 0xAA7B, 0x7346, 0xAA7C,
+	0x7347, 0xAA7D, 0x7348, 0xAA7E, 0x7349, 0xAA80, 0x734A, 0xAA81,
+	0x734B, 0xAA82, 0x734C, 0xAA83, 0x734D, 0xE2B0, 0x734E, 0xAA84,
+	0x734F, 0xAA85, 0x7350, 0xE2AF, 0x7351, 0xAA86, 0x7352, 0xE9E1,
+	0x7353, 0xAA87, 0x7354, 0xAA88, 0x7355, 0xAA89, 0x7356, 0xAA8A,
+	0x7357, 0xE2B1, 0x7358, 0xAA8B, 0x7359, 0xAA8C, 0x735A, 0xAA8D,
+	0x735B, 0xAA8E, 0x735C, 0xAA8F, 0x735D, 0xAA90, 0x735E, 0xAA91,
+	0x735F, 0xAA92, 0x7360, 0xE2B2, 0x7361, 0xAA93, 0x7362, 0xAA94,
+	0x7363, 0xAA95, 0x7364, 0xAA96, 0x7365, 0xAA97, 0x7366, 0xAA98,
+	0x7367, 0xAA99, 0x7368, 0xAA9A, 0x7369, 0xAA9B, 0x736A, 0xAA9C,
+	0x736B, 0xAA9D, 0x736C, 0xE2B3, 0x736D, 0xCCA1, 0x736E, 0xAA9E,
+	0x736F, 0xE2B4, 0x7370, 0xAA9F, 0x7371, 0xAAA0, 0x7372, 0xAB40,
+	0x7373, 0xAB41, 0x7374, 0xAB42, 0x7375, 0xAB43, 0x7376, 0xAB44,
+	0x7377, 0xAB45, 0x7378, 0xAB46, 0x7379, 0xAB47, 0x737A, 0xAB48,
+	0x737B, 0xAB49, 0x737C, 0xAB4A, 0x737D, 0xAB4B, 0x737E, 0xE2B5,
+	0x737F, 0xAB4C, 0x7380, 0xAB4D, 0x7381, 0xAB4E, 0x7382, 0xAB4F,
+	0x7383, 0xAB50, 0x7384, 0xD0FE, 0x7385, 0xAB51, 0x7386, 0xAB52,
+	0x7387, 0xC2CA, 0x7388, 0xAB53, 0x7389, 0xD3F1, 0x738A, 0xAB54,
+	0x738B, 0xCDF5, 0x738C, 0xAB55, 0x738D, 0xAB56, 0x738E, 0xE7E0,
+	0x738F, 0xAB57, 0x7390, 0xAB58, 0x7391, 0xE7E1, 0x7392, 0xAB59,
+	0x7393, 0xAB5A, 0x7394, 0xAB5B, 0x7395, 0xAB5C, 0x7396, 0xBEC1,
+	0x7397, 0xAB5D, 0x7398, 0xAB5E, 0x7399, 0xAB5F, 0x739A, 0xAB60,
+	0x739B, 0xC2EA, 0x739C, 0xAB61, 0x739D, 0xAB62, 0x739E, 0xAB63,
+	0x739F, 0xE7E4, 0x73A0, 0xAB64, 0x73A1, 0xAB65, 0x73A2, 0xE7E3,
+	0x73A3, 0xAB66, 0x73A4, 0xAB67, 0x73A5, 0xAB68, 0x73A6, 0xAB69,
+	0x73A7, 0xAB6A, 0x73A8, 0xAB6B, 0x73A9, 0xCDE6, 0x73AA, 0xAB6C,
+	0x73AB, 0xC3B5, 0x73AC, 0xAB6D, 0x73AD, 0xAB6E, 0x73AE, 0xE7E2,
+	0x73AF, 0xBBB7, 0x73B0, 0xCFD6, 0x73B1, 0xAB6F, 0x73B2, 0xC1E1,
+	0x73B3, 0xE7E9, 0x73B4, 0xAB70, 0x73B5, 0xAB71, 0x73B6, 0xAB72,
+	0x73B7, 0xE7E8, 0x73B8, 0xAB73, 0x73B9, 0xAB74, 0x73BA, 0xE7F4,
+	0x73BB, 0xB2A3, 0x73BC, 0xAB75, 0x73BD, 0xAB76, 0x73BE, 0xAB77,
+	0x73BF, 0xAB78, 0x73C0, 0xE7EA, 0x73C1, 0xAB79, 0x73C2, 0xE7E6,
+	0x73C3, 0xAB7A, 0x73C4, 0xAB7B, 0x73C5, 0xAB7C, 0x73C6, 0xAB7D,
+	0x73C7, 0xAB7E, 0x73C8, 0xE7EC, 0x73C9, 0xE7EB, 0x73CA, 0xC9BA,
+	0x73CB, 0xAB80, 0x73CC, 0xAB81, 0x73CD, 0xD5E4, 0x73CE, 0xAB82,
+	0x73CF, 0xE7E5, 0x73D0, 0xB7A9, 0x73D1, 0xE7E7, 0x73D2, 0xAB83,
+	0x73D3, 0xAB84, 0x73D4, 0xAB85, 0x73D5, 0xAB86, 0x73D6, 0xAB87,
+	0x73D7, 0xAB88, 0x73D8, 0xAB89, 0x73D9, 0xE7EE, 0x73DA, 0xAB8A,
+	0x73DB, 0xAB8B, 0x73DC, 0xAB8C, 0x73DD, 0xAB8D, 0x73DE, 0xE7F3,
+	0x73DF, 0xAB8E, 0x73E0, 0xD6E9, 0x73E1, 0xAB8F, 0x73E2, 0xAB90,
+	0x73E3, 0xAB91, 0x73E4, 0xAB92, 0x73E5, 0xE7ED, 0x73E6, 0xAB93,
+	0x73E7, 0xE7F2, 0x73E8, 0xAB94, 0x73E9, 0xE7F1, 0x73EA, 0xAB95,
+	0x73EB, 0xAB96, 0x73EC, 0xAB97, 0x73ED, 0xB0E0, 0x73EE, 0xAB98,
+	0x73EF, 0xAB99, 0x73F0, 0xAB9A, 0x73F1, 0xAB9B, 0x73F2, 0xE7F5,
+	0x73F3, 0xAB9C, 0x73F4, 0xAB9D, 0x73F5, 0xAB9E, 0x73F6, 0xAB9F,
+	0x73F7, 0xABA0, 0x73F8, 0xAC40, 0x73F9, 0xAC41, 0x73FA, 0xAC42,
+	0x73FB, 0xAC43, 0x73FC, 0xAC44, 0x73FD, 0xAC45, 0x73FE, 0xAC46,
+	0x73FF, 0xAC47, 0x7400, 0xAC48, 0x7401, 0xAC49, 0x7402, 0xAC4A,
+	0x7403, 0xC7F2, 0x7404, 0xAC4B, 0x7405, 0xC0C5, 0x7406, 0xC0ED,
+	0x7407, 0xAC4C, 0x7408, 0xAC4D, 0x7409, 0xC1F0, 0x740A, 0xE7F0,
+	0x740B, 0xAC4E, 0x740C, 0xAC4F, 0x740D, 0xAC50, 0x740E, 0xAC51,
+	0x740F, 0xE7F6, 0x7410, 0xCBF6, 0x7411, 0xAC52, 0x7412, 0xAC53,
+	0x7413, 0xAC54, 0x7414, 0xAC55, 0x7415, 0xAC56, 0x7416, 0xAC57,
+	0x7417, 0xAC58, 0x7418, 0xAC59, 0x7419, 0xAC5A, 0x741A, 0xE8A2,
+	0x741B, 0xE8A1, 0x741C, 0xAC5B, 0x741D, 0xAC5C, 0x741E, 0xAC5D,
+	0x741F, 0xAC5E, 0x7420, 0xAC5F, 0x7421, 0xAC60, 0x7422, 0xD7C1,
+	0x7423, 0xAC61, 0x7424, 0xAC62, 0x7425, 0xE7FA, 0x7426, 0xE7F9,
+	0x7427, 0xAC63, 0x7428, 0xE7FB, 0x7429, 0xAC64, 0x742A, 0xE7F7,
+	0x742B, 0xAC65, 0x742C, 0xE7FE, 0x742D, 0xAC66, 0x742E, 0xE7FD,
+	0x742F, 0xAC67, 0x7430, 0xE7FC, 0x7431, 0xAC68, 0x7432, 0xAC69,
+	0x7433, 0xC1D5, 0x7434, 0xC7D9, 0x7435, 0xC5FD, 0x7436, 0xC5C3,
+	0x7437, 0xAC6A, 0x7438, 0xAC6B, 0x7439, 0xAC6C, 0x743A, 0xAC6D,
+	0x743B, 0xAC6E, 0x743C, 0xC7ED, 0x743D, 0xAC6F, 0x743E, 0xAC70,
+	0x743F, 0xAC71, 0x7440, 0xAC72, 0x7441, 0xE8A3, 0x7442, 0xAC73,
+	0x7443, 0xAC74, 0x7444, 0xAC75, 0x7445, 0xAC76, 0x7446, 0xAC77,
+	0x7447, 0xAC78, 0x7448, 0xAC79, 0x7449, 0xAC7A, 0x744A, 0xAC7B,
+	0x744B, 0xAC7C, 0x744C, 0xAC7D, 0x744D, 0xAC7E, 0x744E, 0xAC80,
+	0x744F, 0xAC81, 0x7450, 0xAC82, 0x7451, 0xAC83, 0x7452, 0xAC84,
+	0x7453, 0xAC85, 0x7454, 0xAC86, 0x7455, 0xE8A6, 0x7456, 0xAC87,
+	0x7457, 0xE8A5, 0x7458, 0xAC88, 0x7459, 0xE8A7, 0x745A, 0xBAF7,
+	0x745B, 0xE7F8, 0x745C, 0xE8A4, 0x745D, 0xAC89, 0x745E, 0xC8F0,
+	0x745F, 0xC9AA, 0x7460, 0xAC8A, 0x7461, 0xAC8B, 0x7462, 0xAC8C,
+	0x7463, 0xAC8D, 0x7464, 0xAC8E, 0x7465, 0xAC8F, 0x7466, 0xAC90,
+	0x7467, 0xAC91, 0x7468, 0xAC92, 0x7469, 0xAC93, 0x746A, 0xAC94,
+	0x746B, 0xAC95, 0x746C, 0xAC96, 0x746D, 0xE8A9, 0x746E, 0xAC97,
+	0x746F, 0xAC98, 0x7470, 0xB9E5, 0x7471, 0xAC99, 0x7472, 0xAC9A,
+	0x7473, 0xAC9B, 0x7474, 0xAC9C, 0x7475, 0xAC9D, 0x7476, 0xD1FE,
+	0x7477, 0xE8A8, 0x7478, 0xAC9E, 0x7479, 0xAC9F, 0x747A, 0xACA0,
+	0x747B, 0xAD40, 0x747C, 0xAD41, 0x747D, 0xAD42, 0x747E, 0xE8AA,
+	0x747F, 0xAD43, 0x7480, 0xE8AD, 0x7481, 0xE8AE, 0x7482, 0xAD44,
+	0x7483, 0xC1A7, 0x7484, 0xAD45, 0x7485, 0xAD46, 0x7486, 0xAD47,
+	0x7487, 0xE8AF, 0x7488, 0xAD48, 0x7489, 0xAD49, 0x748A, 0xAD4A,
+	0x748B, 0xE8B0, 0x748C, 0xAD4B, 0x748D, 0xAD4C, 0x748E, 0xE8AC,
+	0x748F, 0xAD4D, 0x7490, 0xE8B4, 0x7491, 0xAD4E, 0x7492, 0xAD4F,
+	0x7493, 0xAD50, 0x7494, 0xAD51, 0x7495, 0xAD52, 0x7496, 0xAD53,
+	0x7497, 0xAD54, 0x7498, 0xAD55, 0x7499, 0xAD56, 0x749A, 0xAD57,
+	0x749B, 0xAD58, 0x749C, 0xE8AB, 0x749D, 0xAD59, 0x749E, 0xE8B1,
+	0x749F, 0xAD5A, 0x74A0, 0xAD5B, 0x74A1, 0xAD5C, 0x74A2, 0xAD5D,
+	0x74A3, 0xAD5E, 0x74A4, 0xAD5F, 0x74A5, 0xAD60, 0x74A6, 0xAD61,
+	0x74A7, 0xE8B5, 0x74A8, 0xE8B2, 0x74A9, 0xE8B3, 0x74AA, 0xAD62,
+	0x74AB, 0xAD63, 0x74AC, 0xAD64, 0x74AD, 0xAD65, 0x74AE, 0xAD66,
+	0x74AF, 0xAD67, 0x74B0, 0xAD68, 0x74B1, 0xAD69, 0x74B2, 0xAD6A,
+	0x74B3, 0xAD6B, 0x74B4, 0xAD6C, 0x74B5, 0xAD6D, 0x74B6, 0xAD6E,
+	0x74B7, 0xAD6F, 0x74B8, 0xAD70, 0x74B9, 0xAD71, 0x74BA, 0xE8B7,
+	0x74BB, 0xAD72, 0x74BC, 0xAD73, 0x74BD, 0xAD74, 0x74BE, 0xAD75,
+	0x74BF, 0xAD76, 0x74C0, 0xAD77, 0x74C1, 0xAD78, 0x74C2, 0xAD79,
+	0x74C3, 0xAD7A, 0x74C4, 0xAD7B, 0x74C5, 0xAD7C, 0x74C6, 0xAD7D,
+	0x74C7, 0xAD7E, 0x74C8, 0xAD80, 0x74C9, 0xAD81, 0x74CA, 0xAD82,
+	0x74CB, 0xAD83, 0x74CC, 0xAD84, 0x74CD, 0xAD85, 0x74CE, 0xAD86,
+	0x74CF, 0xAD87, 0x74D0, 0xAD88, 0x74D1, 0xAD89, 0x74D2, 0xE8B6,
+	0x74D3, 0xAD8A, 0x74D4, 0xAD8B, 0x74D5, 0xAD8C, 0x74D6, 0xAD8D,
+	0x74D7, 0xAD8E, 0x74D8, 0xAD8F, 0x74D9, 0xAD90, 0x74DA, 0xAD91,
+	0x74DB, 0xAD92, 0x74DC, 0xB9CF, 0x74DD, 0xAD93, 0x74DE, 0xF0AC,
+	0x74DF, 0xAD94, 0x74E0, 0xF0AD, 0x74E1, 0xAD95, 0x74E2, 0xC6B0,
+	0x74E3, 0xB0EA, 0x74E4, 0xC8BF, 0x74E5, 0xAD96, 0x74E6, 0xCDDF,
+	0x74E7, 0xAD97, 0x74E8, 0xAD98, 0x74E9, 0xAD99, 0x74EA, 0xAD9A,
+	0x74EB, 0xAD9B, 0x74EC, 0xAD9C, 0x74ED, 0xAD9D, 0x74EE, 0xCECD,
+	0x74EF, 0xEAB1, 0x74F0, 0xAD9E, 0x74F1, 0xAD9F, 0x74F2, 0xADA0,
+	0x74F3, 0xAE40, 0x74F4, 0xEAB2, 0x74F5, 0xAE41, 0x74F6, 0xC6BF,
+	0x74F7, 0xB4C9, 0x74F8, 0xAE42, 0x74F9, 0xAE43, 0x74FA, 0xAE44,
+	0x74FB, 0xAE45, 0x74FC, 0xAE46, 0x74FD, 0xAE47, 0x74FE, 0xAE48,
+	0x74FF, 0xEAB3, 0x7500, 0xAE49, 0x7501, 0xAE4A, 0x7502, 0xAE4B,
+	0x7503, 0xAE4C, 0x7504, 0xD5E7, 0x7505, 0xAE4D, 0x7506, 0xAE4E,
+	0x7507, 0xAE4F, 0x7508, 0xAE50, 0x7509, 0xAE51, 0x750A, 0xAE52,
+	0x750B, 0xAE53, 0x750C, 0xAE54, 0x750D, 0xDDF9, 0x750E, 0xAE55,
+	0x750F, 0xEAB4, 0x7510, 0xAE56, 0x7511, 0xEAB5, 0x7512, 0xAE57,
+	0x7513, 0xEAB6, 0x7514, 0xAE58, 0x7515, 0xAE59, 0x7516, 0xAE5A,
+	0x7517, 0xAE5B, 0x7518, 0xB8CA, 0x7519, 0xDFB0, 0x751A, 0xC9F5,
+	0x751B, 0xAE5C, 0x751C, 0xCCF0, 0x751D, 0xAE5D, 0x751E, 0xAE5E,
+	0x751F, 0xC9FA, 0x7520, 0xAE5F, 0x7521, 0xAE60, 0x7522, 0xAE61,
+	0x7523, 0xAE62, 0x7524, 0xAE63, 0x7525, 0xC9FB, 0x7526, 0xAE64,
+	0x7527, 0xAE65, 0x7528, 0xD3C3, 0x7529, 0xCBA6, 0x752A, 0xAE66,
+	0x752B, 0xB8A6, 0x752C, 0xF0AE, 0x752D, 0xB1C2, 0x752E, 0xAE67,
+	0x752F, 0xE5B8, 0x7530, 0xCCEF, 0x7531, 0xD3C9, 0x7532, 0xBCD7,
+	0x7533, 0xC9EA, 0x7534, 0xAE68, 0x7535, 0xB5E7, 0x7536, 0xAE69,
+	0x7537, 0xC4D0, 0x7538, 0xB5E9, 0x7539, 0xAE6A, 0x753A, 0xEEAE,
+	0x753B, 0xBBAD, 0x753C, 0xAE6B, 0x753D, 0xAE6C, 0x753E, 0xE7DE,
+	0x753F, 0xAE6D, 0x7540, 0xEEAF, 0x7541, 0xAE6E, 0x7542, 0xAE6F,
+	0x7543, 0xAE70, 0x7544, 0xAE71, 0x7545, 0xB3A9, 0x7546, 0xAE72,
+	0x7547, 0xAE73, 0x7548, 0xEEB2, 0x7549, 0xAE74, 0x754A, 0xAE75,
+	0x754B, 0xEEB1, 0x754C, 0xBDE7, 0x754D, 0xAE76, 0x754E, 0xEEB0,
+	0x754F, 0xCEB7, 0x7550, 0xAE77, 0x7551, 0xAE78, 0x7552, 0xAE79,
+	0x7553, 0xAE7A, 0x7554, 0xC5CF, 0x7555, 0xAE7B, 0x7556, 0xAE7C,
+	0x7557, 0xAE7D, 0x7558, 0xAE7E, 0x7559, 0xC1F4, 0x755A, 0xDBCE,
+	0x755B, 0xEEB3, 0x755C, 0xD0F3, 0x755D, 0xAE80, 0x755E, 0xAE81,
+	0x755F, 0xAE82, 0x7560, 0xAE83, 0x7561, 0xAE84, 0x7562, 0xAE85,
+	0x7563, 0xAE86, 0x7564, 0xAE87, 0x7565, 0xC2D4, 0x7566, 0xC6E8,
+	0x7567, 0xAE88, 0x7568, 0xAE89, 0x7569, 0xAE8A, 0x756A, 0xB7AC,
+	0x756B, 0xAE8B, 0x756C, 0xAE8C, 0x756D, 0xAE8D, 0x756E, 0xAE8E,
+	0x756F, 0xAE8F, 0x7570, 0xAE90, 0x7571, 0xAE91, 0x7572, 0xEEB4,
+	0x7573, 0xAE92, 0x7574, 0xB3EB, 0x7575, 0xAE93, 0x7576, 0xAE94,
+	0x7577, 0xAE95, 0x7578, 0xBBFB, 0x7579, 0xEEB5, 0x757A, 0xAE96,
+	0x757B, 0xAE97, 0x757C, 0xAE98, 0x757D, 0xAE99, 0x757E, 0xAE9A,
+	0x757F, 0xE7DC, 0x7580, 0xAE9B, 0x7581, 0xAE9C, 0x7582, 0xAE9D,
+	0x7583, 0xEEB6, 0x7584, 0xAE9E, 0x7585, 0xAE9F, 0x7586, 0xBDAE,
+	0x7587, 0xAEA0, 0x7588, 0xAF40, 0x7589, 0xAF41, 0x758A, 0xAF42,
+	0x758B, 0xF1E2, 0x758C, 0xAF43, 0x758D, 0xAF44, 0x758E, 0xAF45,
+	0x758F, 0xCAE8, 0x7590, 0xAF46, 0x7591, 0xD2C9, 0x7592, 0xF0DA,
+	0x7593, 0xAF47, 0x7594, 0xF0DB, 0x7595, 0xAF48, 0x7596, 0xF0DC,
+	0x7597, 0xC1C6, 0x7598, 0xAF49, 0x7599, 0xB8ED, 0x759A, 0xBECE,
+	0x759B, 0xAF4A, 0x759C, 0xAF4B, 0x759D, 0xF0DE, 0x759E, 0xAF4C,
+	0x759F, 0xC5B1, 0x75A0, 0xF0DD, 0x75A1, 0xD1F1, 0x75A2, 0xAF4D,
+	0x75A3, 0xF0E0, 0x75A4, 0xB0CC, 0x75A5, 0xBDEA, 0x75A6, 0xAF4E,
+	0x75A7, 0xAF4F, 0x75A8, 0xAF50, 0x75A9, 0xAF51, 0x75AA, 0xAF52,
+	0x75AB, 0xD2DF, 0x75AC, 0xF0DF, 0x75AD, 0xAF53, 0x75AE, 0xB4AF,
+	0x75AF, 0xB7E8, 0x75B0, 0xF0E6, 0x75B1, 0xF0E5, 0x75B2, 0xC6A3,
+	0x75B3, 0xF0E1, 0x75B4, 0xF0E2, 0x75B5, 0xB4C3, 0x75B6, 0xAF54,
+	0x75B7, 0xAF55, 0x75B8, 0xF0E3, 0x75B9, 0xD5EE, 0x75BA, 0xAF56,
+	0x75BB, 0xAF57, 0x75BC, 0xCCDB, 0x75BD, 0xBED2, 0x75BE, 0xBCB2,
+	0x75BF, 0xAF58, 0x75C0, 0xAF59, 0x75C1, 0xAF5A, 0x75C2, 0xF0E8,
+	0x75C3, 0xF0E7, 0x75C4, 0xF0E4, 0x75C5, 0xB2A1, 0x75C6, 0xAF5B,
+	0x75C7, 0xD6A2, 0x75C8, 0xD3B8, 0x75C9, 0xBEB7, 0x75CA, 0xC8AC,
+	0x75CB, 0xAF5C, 0x75CC, 0xAF5D, 0x75CD, 0xF0EA, 0x75CE, 0xAF5E,
+	0x75CF, 0xAF5F, 0x75D0, 0xAF60, 0x75D1, 0xAF61, 0x75D2, 0xD1F7,
+	0x75D3, 0xAF62, 0x75D4, 0xD6CC, 0x75D5, 0xBADB, 0x75D6, 0xF0E9,
+	0x75D7, 0xAF63, 0x75D8, 0xB6BB, 0x75D9, 0xAF64, 0x75DA, 0xAF65,
+	0x75DB, 0xCDB4, 0x75DC, 0xAF66, 0x75DD, 0xAF67, 0x75DE, 0xC6A6,
+	0x75DF, 0xAF68, 0x75E0, 0xAF69, 0x75E1, 0xAF6A, 0x75E2, 0xC1A1,
+	0x75E3, 0xF0EB, 0x75E4, 0xF0EE, 0x75E5, 0xAF6B, 0x75E6, 0xF0ED,
+	0x75E7, 0xF0F0, 0x75E8, 0xF0EC, 0x75E9, 0xAF6C, 0x75EA, 0xBBBE,
+	0x75EB, 0xF0EF, 0x75EC, 0xAF6D, 0x75ED, 0xAF6E, 0x75EE, 0xAF6F,
+	0x75EF, 0xAF70, 0x75F0, 0xCCB5, 0x75F1, 0xF0F2, 0x75F2, 0xAF71,
+	0x75F3, 0xAF72, 0x75F4, 0xB3D5, 0x75F5, 0xAF73, 0x75F6, 0xAF74,
+	0x75F7, 0xAF75, 0x75F8, 0xAF76, 0x75F9, 0xB1D4, 0x75FA, 0xAF77,
+	0x75FB, 0xAF78, 0x75FC, 0xF0F3, 0x75FD, 0xAF79, 0x75FE, 0xAF7A,
+	0x75FF, 0xF0F4, 0x7600, 0xF0F6, 0x7601, 0xB4E1, 0x7602, 0xAF7B,
+	0x7603, 0xF0F1, 0x7604, 0xAF7C, 0x7605, 0xF0F7, 0x7606, 0xAF7D,
+	0x7607, 0xAF7E, 0x7608, 0xAF80, 0x7609, 0xAF81, 0x760A, 0xF0FA,
+	0x760B, 0xAF82, 0x760C, 0xF0F8, 0x760D, 0xAF83, 0x760E, 0xAF84,
+	0x760F, 0xAF85, 0x7610, 0xF0F5, 0x7611, 0xAF86, 0x7612, 0xAF87,
+	0x7613, 0xAF88, 0x7614, 0xAF89, 0x7615, 0xF0FD, 0x7616, 0xAF8A,
+	0x7617, 0xF0F9, 0x7618, 0xF0FC, 0x7619, 0xF0FE, 0x761A, 0xAF8B,
+	0x761B, 0xF1A1, 0x761C, 0xAF8C, 0x761D, 0xAF8D, 0x761E, 0xAF8E,
+	0x761F, 0xCEC1, 0x7620, 0xF1A4, 0x7621, 0xAF8F, 0x7622, 0xF1A3,
+	0x7623, 0xAF90, 0x7624, 0xC1F6, 0x7625, 0xF0FB, 0x7626, 0xCADD,
+	0x7627, 0xAF91, 0x7628, 0xAF92, 0x7629, 0xB4F1, 0x762A, 0xB1F1,
+	0x762B, 0xCCB1, 0x762C, 0xAF93, 0x762D, 0xF1A6, 0x762E, 0xAF94,
+	0x762F, 0xAF95, 0x7630, 0xF1A7, 0x7631, 0xAF96, 0x7632, 0xAF97,
+	0x7633, 0xF1AC, 0x7634, 0xD5CE, 0x7635, 0xF1A9, 0x7636, 0xAF98,
+	0x7637, 0xAF99, 0x7638, 0xC8B3, 0x7639, 0xAF9A, 0x763A, 0xAF9B,
+	0x763B, 0xAF9C, 0x763C, 0xF1A2, 0x763D, 0xAF9D, 0x763E, 0xF1AB,
+	0x763F, 0xF1A8, 0x7640, 0xF1A5, 0x7641, 0xAF9E, 0x7642, 0xAF9F,
+	0x7643, 0xF1AA, 0x7644, 0xAFA0, 0x7645, 0xB040, 0x7646, 0xB041,
+	0x7647, 0xB042, 0x7648, 0xB043, 0x7649, 0xB044, 0x764A, 0xB045,
+	0x764B, 0xB046, 0x764C, 0xB0A9, 0x764D, 0xF1AD, 0x764E, 0xB047,
+	0x764F, 0xB048, 0x7650, 0xB049, 0x7651, 0xB04A, 0x7652, 0xB04B,
+	0x7653, 0xB04C, 0x7654, 0xF1AF, 0x7655, 0xB04D, 0x7656, 0xF1B1,
+	0x7657, 0xB04E, 0x7658, 0xB04F, 0x7659, 0xB050, 0x765A, 0xB051,
+	0x765B, 0xB052, 0x765C, 0xF1B0, 0x765D, 0xB053, 0x765E, 0xF1AE,
+	0x765F, 0xB054, 0x7660, 0xB055, 0x7661, 0xB056, 0x7662, 0xB057,
+	0x7663, 0xD1A2, 0x7664, 0xB058, 0x7665, 0xB059, 0x7666, 0xB05A,
+	0x7667, 0xB05B, 0x7668, 0xB05C, 0x7669, 0xB05D, 0x766A, 0xB05E,
+	0x766B, 0xF1B2, 0x766C, 0xB05F, 0x766D, 0xB060, 0x766E, 0xB061,
+	0x766F, 0xF1B3, 0x7670, 0xB062, 0x7671, 0xB063, 0x7672, 0xB064,
+	0x7673, 0xB065, 0x7674, 0xB066, 0x7675, 0xB067, 0x7676, 0xB068,
+	0x7677, 0xB069, 0x7678, 0xB9EF, 0x7679, 0xB06A, 0x767A, 0xB06B,
+	0x767B, 0xB5C7, 0x767C, 0xB06C, 0x767D, 0xB0D7, 0x767E, 0xB0D9,
+	0x767F, 0xB06D, 0x7680, 0xB06E, 0x7681, 0xB06F, 0x7682, 0xD4ED,
+	0x7683, 0xB070, 0x7684, 0xB5C4, 0x7685, 0xB071, 0x7686, 0xBDD4,
+	0x7687, 0xBBCA, 0x7688, 0xF0A7, 0x7689, 0xB072, 0x768A, 0xB073,
+	0x768B, 0xB8DE, 0x768C, 0xB074, 0x768D, 0xB075, 0x768E, 0xF0A8,
+	0x768F, 0xB076, 0x7690, 0xB077, 0x7691, 0xB0A8, 0x7692, 0xB078,
+	0x7693, 0xF0A9, 0x7694, 0xB079, 0x7695, 0xB07A, 0x7696, 0xCDEE,
+	0x7697, 0xB07B, 0x7698, 0xB07C, 0x7699, 0xF0AA, 0x769A, 0xB07D,
+	0x769B, 0xB07E, 0x769C, 0xB080, 0x769D, 0xB081, 0x769E, 0xB082,
+	0x769F, 0xB083, 0x76A0, 0xB084, 0x76A1, 0xB085, 0x76A2, 0xB086,
+	0x76A3, 0xB087, 0x76A4, 0xF0AB, 0x76A5, 0xB088, 0x76A6, 0xB089,
+	0x76A7, 0xB08A, 0x76A8, 0xB08B, 0x76A9, 0xB08C, 0x76AA, 0xB08D,
+	0x76AB, 0xB08E, 0x76AC, 0xB08F, 0x76AD, 0xB090, 0x76AE, 0xC6A4,
+	0x76AF, 0xB091, 0x76B0, 0xB092, 0x76B1, 0xD6E5, 0x76B2, 0xF1E4,
+	0x76B3, 0xB093, 0x76B4, 0xF1E5, 0x76B5, 0xB094, 0x76B6, 0xB095,
+	0x76B7, 0xB096, 0x76B8, 0xB097, 0x76B9, 0xB098, 0x76BA, 0xB099,
+	0x76BB, 0xB09A, 0x76BC, 0xB09B, 0x76BD, 0xB09C, 0x76BE, 0xB09D,
+	0x76BF, 0xC3F3, 0x76C0, 0xB09E, 0x76C1, 0xB09F, 0x76C2, 0xD3DB,
+	0x76C3, 0xB0A0, 0x76C4, 0xB140, 0x76C5, 0xD6D1, 0x76C6, 0xC5E8,
+	0x76C7, 0xB141, 0x76C8, 0xD3AF, 0x76C9, 0xB142, 0x76CA, 0xD2E6,
+	0x76CB, 0xB143, 0x76CC, 0xB144, 0x76CD, 0xEEC1, 0x76CE, 0xB0BB,
+	0x76CF, 0xD5B5, 0x76D0, 0xD1CE, 0x76D1, 0xBCE0, 0x76D2, 0xBAD0,
+	0x76D3, 0xB145, 0x76D4, 0xBFF8, 0x76D5, 0xB146, 0x76D6, 0xB8C7,
+	0x76D7, 0xB5C1, 0x76D8, 0xC5CC, 0x76D9, 0xB147, 0x76DA, 0xB148,
+	0x76DB, 0xCAA2, 0x76DC, 0xB149, 0x76DD, 0xB14A, 0x76DE, 0xB14B,
+	0x76DF, 0xC3CB, 0x76E0, 0xB14C, 0x76E1, 0xB14D, 0x76E2, 0xB14E,
+	0x76E3, 0xB14F, 0x76E4, 0xB150, 0x76E5, 0xEEC2, 0x76E6, 0xB151,
+	0x76E7, 0xB152, 0x76E8, 0xB153, 0x76E9, 0xB154, 0x76EA, 0xB155,
+	0x76EB, 0xB156, 0x76EC, 0xB157, 0x76ED, 0xB158, 0x76EE, 0xC4BF,
+	0x76EF, 0xB6A2, 0x76F0, 0xB159, 0x76F1, 0xEDEC, 0x76F2, 0xC3A4,
+	0x76F3, 0xB15A, 0x76F4, 0xD6B1, 0x76F5, 0xB15B, 0x76F6, 0xB15C,
+	0x76F7, 0xB15D, 0x76F8, 0xCFE0, 0x76F9, 0xEDEF, 0x76FA, 0xB15E,
+	0x76FB, 0xB15F, 0x76FC, 0xC5CE, 0x76FD, 0xB160, 0x76FE, 0xB6DC,
+	0x76FF, 0xB161, 0x7700, 0xB162, 0x7701, 0xCAA1, 0x7702, 0xB163,
+	0x7703, 0xB164, 0x7704, 0xEDED, 0x7705, 0xB165, 0x7706, 0xB166,
+	0x7707, 0xEDF0, 0x7708, 0xEDF1, 0x7709, 0xC3BC, 0x770A, 0xB167,
+	0x770B, 0xBFB4, 0x770C, 0xB168, 0x770D, 0xEDEE, 0x770E, 0xB169,
+	0x770F, 0xB16A, 0x7710, 0xB16B, 0x7711, 0xB16C, 0x7712, 0xB16D,
+	0x7713, 0xB16E, 0x7714, 0xB16F, 0x7715, 0xB170, 0x7716, 0xB171,
+	0x7717, 0xB172, 0x7718, 0xB173, 0x7719, 0xEDF4, 0x771A, 0xEDF2,
+	0x771B, 0xB174, 0x771C, 0xB175, 0x771D, 0xB176, 0x771E, 0xB177,
+	0x771F, 0xD5E6, 0x7720, 0xC3DF, 0x7721, 0xB178, 0x7722, 0xEDF3,
+	0x7723, 0xB179, 0x7724, 0xB17A, 0x7725, 0xB17B, 0x7726, 0xEDF6,
+	0x7727, 0xB17C, 0x7728, 0xD5A3, 0x7729, 0xD1A3, 0x772A, 0xB17D,
+	0x772B, 0xB17E, 0x772C, 0xB180, 0x772D, 0xEDF5, 0x772E, 0xB181,
+	0x772F, 0xC3D0, 0x7730, 0xB182, 0x7731, 0xB183, 0x7732, 0xB184,
+	0x7733, 0xB185, 0x7734, 0xB186, 0x7735, 0xEDF7, 0x7736, 0xBFF4,
+	0x7737, 0xBEEC, 0x7738, 0xEDF8, 0x7739, 0xB187, 0x773A, 0xCCF7,
+	0x773B, 0xB188, 0x773C, 0xD1DB, 0x773D, 0xB189, 0x773E, 0xB18A,
+	0x773F, 0xB18B, 0x7740, 0xD7C5, 0x7741, 0xD5F6, 0x7742, 0xB18C,
+	0x7743, 0xEDFC, 0x7744, 0xB18D, 0x7745, 0xB18E, 0x7746, 0xB18F,
+	0x7747, 0xEDFB, 0x7748, 0xB190, 0x7749, 0xB191, 0x774A, 0xB192,
+	0x774B, 0xB193, 0x774C, 0xB194, 0x774D, 0xB195, 0x774E, 0xB196,
+	0x774F, 0xB197, 0x7750, 0xEDF9, 0x7751, 0xEDFA, 0x7752, 0xB198,
+	0x7753, 0xB199, 0x7754, 0xB19A, 0x7755, 0xB19B, 0x7756, 0xB19C,
+	0x7757, 0xB19D, 0x7758, 0xB19E, 0x7759, 0xB19F, 0x775A, 0xEDFD,
+	0x775B, 0xBEA6, 0x775C, 0xB1A0, 0x775D, 0xB240, 0x775E, 0xB241,
+	0x775F, 0xB242, 0x7760, 0xB243, 0x7761, 0xCBAF, 0x7762, 0xEEA1,
+	0x7763, 0xB6BD, 0x7764, 0xB244, 0x7765, 0xEEA2, 0x7766, 0xC4C0,
+	0x7767, 0xB245, 0x7768, 0xEDFE, 0x7769, 0xB246, 0x776A, 0xB247,
+	0x776B, 0xBDDE, 0x776C, 0xB2C7, 0x776D, 0xB248, 0x776E, 0xB249,
+	0x776F, 0xB24A, 0x7770, 0xB24B, 0x7771, 0xB24C, 0x7772, 0xB24D,
+	0x7773, 0xB24E, 0x7774, 0xB24F, 0x7775, 0xB250, 0x7776, 0xB251,
+	0x7777, 0xB252, 0x7778, 0xB253, 0x7779, 0xB6C3, 0x777A, 0xB254,
+	0x777B, 0xB255, 0x777C, 0xB256, 0x777D, 0xEEA5, 0x777E, 0xD8BA,
+	0x777F, 0xEEA3, 0x7780, 0xEEA6, 0x7781, 0xB257, 0x7782, 0xB258,
+	0x7783, 0xB259, 0x7784, 0xC3E9, 0x7785, 0xB3F2, 0x7786, 0xB25A,
+	0x7787, 0xB25B, 0x7788, 0xB25C, 0x7789, 0xB25D, 0x778A, 0xB25E,
+	0x778B, 0xB25F, 0x778C, 0xEEA7, 0x778D, 0xEEA4, 0x778E, 0xCFB9,
+	0x778F, 0xB260, 0x7790, 0xB261, 0x7791, 0xEEA8, 0x7792, 0xC2F7,
+	0x7793, 0xB262, 0x7794, 0xB263, 0x7795, 0xB264, 0x7796, 0xB265,
+	0x7797, 0xB266, 0x7798, 0xB267, 0x7799, 0xB268, 0x779A, 0xB269,
+	0x779B, 0xB26A, 0x779C, 0xB26B, 0x779D, 0xB26C, 0x779E, 0xB26D,
+	0x779F, 0xEEA9, 0x77A0, 0xEEAA, 0x77A1, 0xB26E, 0x77A2, 0xDEAB,
+	0x77A3, 0xB26F, 0x77A4, 0xB270, 0x77A5, 0xC6B3, 0x77A6, 0xB271,
+	0x77A7, 0xC7C6, 0x77A8, 0xB272, 0x77A9, 0xD6F5, 0x77AA, 0xB5C9,
+	0x77AB, 0xB273, 0x77AC, 0xCBB2, 0x77AD, 0xB274, 0x77AE, 0xB275,
+	0x77AF, 0xB276, 0x77B0, 0xEEAB, 0x77B1, 0xB277, 0x77B2, 0xB278,
+	0x77B3, 0xCDAB, 0x77B4, 0xB279, 0x77B5, 0xEEAC, 0x77B6, 0xB27A,
+	0x77B7, 0xB27B, 0x77B8, 0xB27C, 0x77B9, 0xB27D, 0x77BA, 0xB27E,
+	0x77BB, 0xD5B0, 0x77BC, 0xB280, 0x77BD, 0xEEAD, 0x77BE, 0xB281,
+	0x77BF, 0xF6C4, 0x77C0, 0xB282, 0x77C1, 0xB283, 0x77C2, 0xB284,
+	0x77C3, 0xB285, 0x77C4, 0xB286, 0x77C5, 0xB287, 0x77C6, 0xB288,
+	0x77C7, 0xB289, 0x77C8, 0xB28A, 0x77C9, 0xB28B, 0x77CA, 0xB28C,
+	0x77CB, 0xB28D, 0x77CC, 0xB28E, 0x77CD, 0xDBC7, 0x77CE, 0xB28F,
+	0x77CF, 0xB290, 0x77D0, 0xB291, 0x77D1, 0xB292, 0x77D2, 0xB293,
+	0x77D3, 0xB294, 0x77D4, 0xB295, 0x77D5, 0xB296, 0x77D6, 0xB297,
+	0x77D7, 0xB4A3, 0x77D8, 0xB298, 0x77D9, 0xB299, 0x77DA, 0xB29A,
+	0x77DB, 0xC3AC, 0x77DC, 0xF1E6, 0x77DD, 0xB29B, 0x77DE, 0xB29C,
+	0x77DF, 0xB29D, 0x77E0, 0xB29E, 0x77E1, 0xB29F, 0x77E2, 0xCAB8,
+	0x77E3, 0xD2D3, 0x77E4, 0xB2A0, 0x77E5, 0xD6AA, 0x77E6, 0xB340,
+	0x77E7, 0xEFF2, 0x77E8, 0xB341, 0x77E9, 0xBED8, 0x77EA, 0xB342,
+	0x77EB, 0xBDC3, 0x77EC, 0xEFF3, 0x77ED, 0xB6CC, 0x77EE, 0xB0AB,
+	0x77EF, 0xB343, 0x77F0, 0xB344, 0x77F1, 0xB345, 0x77F2, 0xB346,
+	0x77F3, 0xCAAF, 0x77F4, 0xB347, 0x77F5, 0xB348, 0x77F6, 0xEDB6,
+	0x77F7, 0xB349, 0x77F8, 0xEDB7, 0x77F9, 0xB34A, 0x77FA, 0xB34B,
+	0x77FB, 0xB34C, 0x77FC, 0xB34D, 0x77FD, 0xCEF9, 0x77FE, 0xB7AF,
+	0x77FF, 0xBFF3, 0x7800, 0xEDB8, 0x7801, 0xC2EB, 0x7802, 0xC9B0,
+	0x7803, 0xB34E, 0x7804, 0xB34F, 0x7805, 0xB350, 0x7806, 0xB351,
+	0x7807, 0xB352, 0x7808, 0xB353, 0x7809, 0xEDB9, 0x780A, 0xB354,
+	0x780B, 0xB355, 0x780C, 0xC6F6, 0x780D, 0xBFB3, 0x780E, 0xB356,
+	0x780F, 0xB357, 0x7810, 0xB358, 0x7811, 0xEDBC, 0x7812, 0xC5F8,
+	0x7813, 0xB359, 0x7814, 0xD1D0, 0x7815, 0xB35A, 0x7816, 0xD7A9,
+	0x7817, 0xEDBA, 0x7818, 0xEDBB, 0x7819, 0xB35B, 0x781A, 0xD1E2,
+	0x781B, 0xB35C, 0x781C, 0xEDBF, 0x781D, 0xEDC0, 0x781E, 0xB35D,
+	0x781F, 0xEDC4, 0x7820, 0xB35E, 0x7821, 0xB35F, 0x7822, 0xB360,
+	0x7823, 0xEDC8, 0x7824, 0xB361, 0x7825, 0xEDC6, 0x7826, 0xEDCE,
+	0x7827, 0xD5E8, 0x7828, 0xB362, 0x7829, 0xEDC9, 0x782A, 0xB363,
+	0x782B, 0xB364, 0x782C, 0xEDC7, 0x782D, 0xEDBE, 0x782E, 0xB365,
+	0x782F, 0xB366, 0x7830, 0xC5E9, 0x7831, 0xB367, 0x7832, 0xB368,
+	0x7833, 0xB369, 0x7834, 0xC6C6, 0x7835, 0xB36A, 0x7836, 0xB36B,
+	0x7837, 0xC9E9, 0x7838, 0xD4D2, 0x7839, 0xEDC1, 0x783A, 0xEDC2,
+	0x783B, 0xEDC3, 0x783C, 0xEDC5, 0x783D, 0xB36C, 0x783E, 0xC0F9,
+	0x783F, 0xB36D, 0x7840, 0xB4A1, 0x7841, 0xB36E, 0x7842, 0xB36F,
+	0x7843, 0xB370, 0x7844, 0xB371, 0x7845, 0xB9E8, 0x7846, 0xB372,
+	0x7847, 0xEDD0, 0x7848, 0xB373, 0x7849, 0xB374, 0x784A, 0xB375,
+	0x784B, 0xB376, 0x784C, 0xEDD1, 0x784D, 0xB377, 0x784E, 0xEDCA,
+	0x784F, 0xB378, 0x7850, 0xEDCF, 0x7851, 0xB379, 0x7852, 0xCEF8,
+	0x7853, 0xB37A, 0x7854, 0xB37B, 0x7855, 0xCBB6, 0x7856, 0xEDCC,
+	0x7857, 0xEDCD, 0x7858, 0xB37C, 0x7859, 0xB37D, 0x785A, 0xB37E,
+	0x785B, 0xB380, 0x785C, 0xB381, 0x785D, 0xCFF5, 0x785E, 0xB382,
+	0x785F, 0xB383, 0x7860, 0xB384, 0x7861, 0xB385, 0x7862, 0xB386,
+	0x7863, 0xB387, 0x7864, 0xB388, 0x7865, 0xB389, 0x7866, 0xB38A,
+	0x7867, 0xB38B, 0x7868, 0xB38C, 0x7869, 0xB38D, 0x786A, 0xEDD2,
+	0x786B, 0xC1F2, 0x786C, 0xD3B2, 0x786D, 0xEDCB, 0x786E, 0xC8B7,
+	0x786F, 0xB38E, 0x7870, 0xB38F, 0x7871, 0xB390, 0x7872, 0xB391,
+	0x7873, 0xB392, 0x7874, 0xB393, 0x7875, 0xB394, 0x7876, 0xB395,
+	0x7877, 0xBCEF, 0x7878, 0xB396, 0x7879, 0xB397, 0x787A, 0xB398,
+	0x787B, 0xB399, 0x787C, 0xC5F0, 0x787D, 0xB39A, 0x787E, 0xB39B,
+	0x787F, 0xB39C, 0x7880, 0xB39D, 0x7881, 0xB39E, 0x7882, 0xB39F,
+	0x7883, 0xB3A0, 0x7884, 0xB440, 0x7885, 0xB441, 0x7886, 0xB442,
+	0x7887, 0xEDD6, 0x7888, 0xB443, 0x7889, 0xB5EF, 0x788A, 0xB444,
+	0x788B, 0xB445, 0x788C, 0xC2B5, 0x788D, 0xB0AD, 0x788E, 0xCBE9,
+	0x788F, 0xB446, 0x7890, 0xB447, 0x7891, 0xB1AE, 0x7892, 0xB448,
+	0x7893, 0xEDD4, 0x7894, 0xB449, 0x7895, 0xB44A, 0x7896, 0xB44B,
+	0x7897, 0xCDEB, 0x7898, 0xB5E2, 0x7899, 0xB44C, 0x789A, 0xEDD5,
+	0x789B, 0xEDD3, 0x789C, 0xEDD7, 0x789D, 0xB44D, 0x789E, 0xB44E,
+	0x789F, 0xB5FA, 0x78A0, 0xB44F, 0x78A1, 0xEDD8, 0x78A2, 0xB450,
+	0x78A3, 0xEDD9, 0x78A4, 0xB451, 0x78A5, 0xEDDC, 0x78A6, 0xB452,
+	0x78A7, 0xB1CC, 0x78A8, 0xB453, 0x78A9, 0xB454, 0x78AA, 0xB455,
+	0x78AB, 0xB456, 0x78AC, 0xB457, 0x78AD, 0xB458, 0x78AE, 0xB459,
+	0x78AF, 0xB45A, 0x78B0, 0xC5F6, 0x78B1, 0xBCEE, 0x78B2, 0xEDDA,
+	0x78B3, 0xCCBC, 0x78B4, 0xB2EA, 0x78B5, 0xB45B, 0x78B6, 0xB45C,
+	0x78B7, 0xB45D, 0x78B8, 0xB45E, 0x78B9, 0xEDDB, 0x78BA, 0xB45F,
+	0x78BB, 0xB460, 0x78BC, 0xB461, 0x78BD, 0xB462, 0x78BE, 0xC4EB,
+	0x78BF, 0xB463, 0x78C0, 0xB464, 0x78C1, 0xB4C5, 0x78C2, 0xB465,
+	0x78C3, 0xB466, 0x78C4, 0xB467, 0x78C5, 0xB0F5, 0x78C6, 0xB468,
+	0x78C7, 0xB469, 0x78C8, 0xB46A, 0x78C9, 0xEDDF, 0x78CA, 0xC0DA,
+	0x78CB, 0xB4E8, 0x78CC, 0xB46B, 0x78CD, 0xB46C, 0x78CE, 0xB46D,
+	0x78CF, 0xB46E, 0x78D0, 0xC5CD, 0x78D1, 0xB46F, 0x78D2, 0xB470,
+	0x78D3, 0xB471, 0x78D4, 0xEDDD, 0x78D5, 0xBFC4, 0x78D6, 0xB472,
+	0x78D7, 0xB473, 0x78D8, 0xB474, 0x78D9, 0xEDDE, 0x78DA, 0xB475,
+	0x78DB, 0xB476, 0x78DC, 0xB477, 0x78DD, 0xB478, 0x78DE, 0xB479,
+	0x78DF, 0xB47A, 0x78E0, 0xB47B, 0x78E1, 0xB47C, 0x78E2, 0xB47D,
+	0x78E3, 0xB47E, 0x78E4, 0xB480, 0x78E5, 0xB481, 0x78E6, 0xB482,
+	0x78E7, 0xB483, 0x78E8, 0xC4A5, 0x78E9, 0xB484, 0x78EA, 0xB485,
+	0x78EB, 0xB486, 0x78EC, 0xEDE0, 0x78ED, 0xB487, 0x78EE, 0xB488,
+	0x78EF, 0xB489, 0x78F0, 0xB48A, 0x78F1, 0xB48B, 0x78F2, 0xEDE1,
+	0x78F3, 0xB48C, 0x78F4, 0xEDE3, 0x78F5, 0xB48D, 0x78F6, 0xB48E,
+	0x78F7, 0xC1D7, 0x78F8, 0xB48F, 0x78F9, 0xB490, 0x78FA, 0xBBC7,
+	0x78FB, 0xB491, 0x78FC, 0xB492, 0x78FD, 0xB493, 0x78FE, 0xB494,
+	0x78FF, 0xB495, 0x7900, 0xB496, 0x7901, 0xBDB8, 0x7902, 0xB497,
+	0x7903, 0xB498, 0x7904, 0xB499, 0x7905, 0xEDE2, 0x7906, 0xB49A,
+	0x7907, 0xB49B, 0x7908, 0xB49C, 0x7909, 0xB49D, 0x790A, 0xB49E,
+	0x790B, 0xB49F, 0x790C, 0xB4A0, 0x790D, 0xB540, 0x790E, 0xB541,
+	0x790F, 0xB542, 0x7910, 0xB543, 0x7911, 0xB544, 0x7912, 0xB545,
+	0x7913, 0xEDE4, 0x7914, 0xB546, 0x7915, 0xB547, 0x7916, 0xB548,
+	0x7917, 0xB549, 0x7918, 0xB54A, 0x7919, 0xB54B, 0x791A, 0xB54C,
+	0x791B, 0xB54D, 0x791C, 0xB54E, 0x791D, 0xB54F, 0x791E, 0xEDE6,
+	0x791F, 0xB550, 0x7920, 0xB551, 0x7921, 0xB552, 0x7922, 0xB553,
+	0x7923, 0xB554, 0x7924, 0xEDE5, 0x7925, 0xB555, 0x7926, 0xB556,
+	0x7927, 0xB557, 0x7928, 0xB558, 0x7929, 0xB559, 0x792A, 0xB55A,
+	0x792B, 0xB55B, 0x792C, 0xB55C, 0x792D, 0xB55D, 0x792E, 0xB55E,
+	0x792F, 0xB55F, 0x7930, 0xB560, 0x7931, 0xB561, 0x7932, 0xB562,
+	0x7933, 0xB563, 0x7934, 0xEDE7, 0x7935, 0xB564, 0x7936, 0xB565,
+	0x7937, 0xB566, 0x7938, 0xB567, 0x7939, 0xB568, 0x793A, 0xCABE,
+	0x793B, 0xECEA, 0x793C, 0xC0F1, 0x793D, 0xB569, 0x793E, 0xC9E7,
+	0x793F, 0xB56A, 0x7940, 0xECEB, 0x7941, 0xC6EE, 0x7942, 0xB56B,
+	0x7943, 0xB56C, 0x7944, 0xB56D, 0x7945, 0xB56E, 0x7946, 0xECEC,
+	0x7947, 0xB56F, 0x7948, 0xC6ED, 0x7949, 0xECED, 0x794A, 0xB570,
+	0x794B, 0xB571, 0x794C, 0xB572, 0x794D, 0xB573, 0x794E, 0xB574,
+	0x794F, 0xB575, 0x7950, 0xB576, 0x7951, 0xB577, 0x7952, 0xB578,
+	0x7953, 0xECF0, 0x7954, 0xB579, 0x7955, 0xB57A, 0x7956, 0xD7E6,
+	0x7957, 0xECF3, 0x7958, 0xB57B, 0x7959, 0xB57C, 0x795A, 0xECF1,
+	0x795B, 0xECEE, 0x795C, 0xECEF, 0x795D, 0xD7A3, 0x795E, 0xC9F1,
+	0x795F, 0xCBEE, 0x7960, 0xECF4, 0x7961, 0xB57D, 0x7962, 0xECF2,
+	0x7963, 0xB57E, 0x7964, 0xB580, 0x7965, 0xCFE9, 0x7966, 0xB581,
+	0x7967, 0xECF6, 0x7968, 0xC6B1, 0x7969, 0xB582, 0x796A, 0xB583,
+	0x796B, 0xB584, 0x796C, 0xB585, 0x796D, 0xBCC0, 0x796E, 0xB586,
+	0x796F, 0xECF5, 0x7970, 0xB587, 0x7971, 0xB588, 0x7972, 0xB589,
+	0x7973, 0xB58A, 0x7974, 0xB58B, 0x7975, 0xB58C, 0x7976, 0xB58D,
+	0x7977, 0xB5BB, 0x7978, 0xBBF6, 0x7979, 0xB58E, 0x797A, 0xECF7,
+	0x797B, 0xB58F, 0x797C, 0xB590, 0x797D, 0xB591, 0x797E, 0xB592,
+	0x797F, 0xB593, 0x7980, 0xD9F7, 0x7981, 0xBDFB, 0x7982, 0xB594,
+	0x7983, 0xB595, 0x7984, 0xC2BB, 0x7985, 0xECF8, 0x7986, 0xB596,
+	0x7987, 0xB597, 0x7988, 0xB598, 0x7989, 0xB599, 0x798A, 0xECF9,
+	0x798B, 0xB59A, 0x798C, 0xB59B, 0x798D, 0xB59C, 0x798E, 0xB59D,
+	0x798F, 0xB8A3, 0x7990, 0xB59E, 0x7991, 0xB59F, 0x7992, 0xB5A0,
+	0x7993, 0xB640, 0x7994, 0xB641, 0x7995, 0xB642, 0x7996, 0xB643,
+	0x7997, 0xB644, 0x7998, 0xB645, 0x7999, 0xB646, 0x799A, 0xECFA,
+	0x799B, 0xB647, 0x799C, 0xB648, 0x799D, 0xB649, 0x799E, 0xB64A,
+	0x799F, 0xB64B, 0x79A0, 0xB64C, 0x79A1, 0xB64D, 0x79A2, 0xB64E,
+	0x79A3, 0xB64F, 0x79A4, 0xB650, 0x79A5, 0xB651, 0x79A6, 0xB652,
+	0x79A7, 0xECFB, 0x79A8, 0xB653, 0x79A9, 0xB654, 0x79AA, 0xB655,
+	0x79AB, 0xB656, 0x79AC, 0xB657, 0x79AD, 0xB658, 0x79AE, 0xB659,
+	0x79AF, 0xB65A, 0x79B0, 0xB65B, 0x79B1, 0xB65C, 0x79B2, 0xB65D,
+	0x79B3, 0xECFC, 0x79B4, 0xB65E, 0x79B5, 0xB65F, 0x79B6, 0xB660,
+	0x79B7, 0xB661, 0x79B8, 0xB662, 0x79B9, 0xD3ED, 0x79BA, 0xD8AE,
+	0x79BB, 0xC0EB, 0x79BC, 0xB663, 0x79BD, 0xC7DD, 0x79BE, 0xBACC,
+	0x79BF, 0xB664, 0x79C0, 0xD0E3, 0x79C1, 0xCBBD, 0x79C2, 0xB665,
+	0x79C3, 0xCDBA, 0x79C4, 0xB666, 0x79C5, 0xB667, 0x79C6, 0xB8D1,
+	0x79C7, 0xB668, 0x79C8, 0xB669, 0x79C9, 0xB1FC, 0x79CA, 0xB66A,
+	0x79CB, 0xC7EF, 0x79CC, 0xB66B, 0x79CD, 0xD6D6, 0x79CE, 0xB66C,
+	0x79CF, 0xB66D, 0x79D0, 0xB66E, 0x79D1, 0xBFC6, 0x79D2, 0xC3EB,
+	0x79D3, 0xB66F, 0x79D4, 0xB670, 0x79D5, 0xEFF5, 0x79D6, 0xB671,
+	0x79D7, 0xB672, 0x79D8, 0xC3D8, 0x79D9, 0xB673, 0x79DA, 0xB674,
+	0x79DB, 0xB675, 0x79DC, 0xB676, 0x79DD, 0xB677, 0x79DE, 0xB678,
+	0x79DF, 0xD7E2, 0x79E0, 0xB679, 0x79E1, 0xB67A, 0x79E2, 0xB67B,
+	0x79E3, 0xEFF7, 0x79E4, 0xB3D3, 0x79E5, 0xB67C, 0x79E6, 0xC7D8,
+	0x79E7, 0xD1ED, 0x79E8, 0xB67D, 0x79E9, 0xD6C8, 0x79EA, 0xB67E,
+	0x79EB, 0xEFF8, 0x79EC, 0xB680, 0x79ED, 0xEFF6, 0x79EE, 0xB681,
+	0x79EF, 0xBBFD, 0x79F0, 0xB3C6, 0x79F1, 0xB682, 0x79F2, 0xB683,
+	0x79F3, 0xB684, 0x79F4, 0xB685, 0x79F5, 0xB686, 0x79F6, 0xB687,
+	0x79F7, 0xB688, 0x79F8, 0xBDD5, 0x79F9, 0xB689, 0x79FA, 0xB68A,
+	0x79FB, 0xD2C6, 0x79FC, 0xB68B, 0x79FD, 0xBBE0, 0x79FE, 0xB68C,
+	0x79FF, 0xB68D, 0x7A00, 0xCFA1, 0x7A01, 0xB68E, 0x7A02, 0xEFFC,
+	0x7A03, 0xEFFB, 0x7A04, 0xB68F, 0x7A05, 0xB690, 0x7A06, 0xEFF9,
+	0x7A07, 0xB691, 0x7A08, 0xB692, 0x7A09, 0xB693, 0x7A0A, 0xB694,
+	0x7A0B, 0xB3CC, 0x7A0C, 0xB695, 0x7A0D, 0xC9D4, 0x7A0E, 0xCBB0,
+	0x7A0F, 0xB696, 0x7A10, 0xB697, 0x7A11, 0xB698, 0x7A12, 0xB699,
+	0x7A13, 0xB69A, 0x7A14, 0xEFFE, 0x7A15, 0xB69B, 0x7A16, 0xB69C,
+	0x7A17, 0xB0DE, 0x7A18, 0xB69D, 0x7A19, 0xB69E, 0x7A1A, 0xD6C9,
+	0x7A1B, 0xB69F, 0x7A1C, 0xB6A0, 0x7A1D, 0xB740, 0x7A1E, 0xEFFD,
+	0x7A1F, 0xB741, 0x7A20, 0xB3ED, 0x7A21, 0xB742, 0x7A22, 0xB743,
+	0x7A23, 0xF6D5, 0x7A24, 0xB744, 0x7A25, 0xB745, 0x7A26, 0xB746,
+	0x7A27, 0xB747, 0x7A28, 0xB748, 0x7A29, 0xB749, 0x7A2A, 0xB74A,
+	0x7A2B, 0xB74B, 0x7A2C, 0xB74C, 0x7A2D, 0xB74D, 0x7A2E, 0xB74E,
+	0x7A2F, 0xB74F, 0x7A30, 0xB750, 0x7A31, 0xB751, 0x7A32, 0xB752,
+	0x7A33, 0xCEC8, 0x7A34, 0xB753, 0x7A35, 0xB754, 0x7A36, 0xB755,
+	0x7A37, 0xF0A2, 0x7A38, 0xB756, 0x7A39, 0xF0A1, 0x7A3A, 0xB757,
+	0x7A3B, 0xB5BE, 0x7A3C, 0xBCDA, 0x7A3D, 0xBBFC, 0x7A3E, 0xB758,
+	0x7A3F, 0xB8E5, 0x7A40, 0xB759, 0x7A41, 0xB75A, 0x7A42, 0xB75B,
+	0x7A43, 0xB75C, 0x7A44, 0xB75D, 0x7A45, 0xB75E, 0x7A46, 0xC4C2,
+	0x7A47, 0xB75F, 0x7A48, 0xB760, 0x7A49, 0xB761, 0x7A4A, 0xB762,
+	0x7A4B, 0xB763, 0x7A4C, 0xB764, 0x7A4D, 0xB765, 0x7A4E, 0xB766,
+	0x7A4F, 0xB767, 0x7A50, 0xB768, 0x7A51, 0xF0A3, 0x7A52, 0xB769,
+	0x7A53, 0xB76A, 0x7A54, 0xB76B, 0x7A55, 0xB76C, 0x7A56, 0xB76D,
+	0x7A57, 0xCBEB, 0x7A58, 0xB76E, 0x7A59, 0xB76F, 0x7A5A, 0xB770,
+	0x7A5B, 0xB771, 0x7A5C, 0xB772, 0x7A5D, 0xB773, 0x7A5E, 0xB774,
+	0x7A5F, 0xB775, 0x7A60, 0xB776, 0x7A61, 0xB777, 0x7A62, 0xB778,
+	0x7A63, 0xB779, 0x7A64, 0xB77A, 0x7A65, 0xB77B, 0x7A66, 0xB77C,
+	0x7A67, 0xB77D, 0x7A68, 0xB77E, 0x7A69, 0xB780, 0x7A6A, 0xB781,
+	0x7A6B, 0xB782, 0x7A6C, 0xB783, 0x7A6D, 0xB784, 0x7A6E, 0xB785,
+	0x7A6F, 0xB786, 0x7A70, 0xF0A6, 0x7A71, 0xB787, 0x7A72, 0xB788,
+	0x7A73, 0xB789, 0x7A74, 0xD1A8, 0x7A75, 0xB78A, 0x7A76, 0xBEBF,
+	0x7A77, 0xC7EE, 0x7A78, 0xF1B6, 0x7A79, 0xF1B7, 0x7A7A, 0xBFD5,
+	0x7A7B, 0xB78B, 0x7A7C, 0xB78C, 0x7A7D, 0xB78D, 0x7A7E, 0xB78E,
+	0x7A7F, 0xB4A9, 0x7A80, 0xF1B8, 0x7A81, 0xCDBB, 0x7A82, 0xB78F,
+	0x7A83, 0xC7D4, 0x7A84, 0xD5AD, 0x7A85, 0xB790, 0x7A86, 0xF1B9,
+	0x7A87, 0xB791, 0x7A88, 0xF1BA, 0x7A89, 0xB792, 0x7A8A, 0xB793,
+	0x7A8B, 0xB794, 0x7A8C, 0xB795, 0x7A8D, 0xC7CF, 0x7A8E, 0xB796,
+	0x7A8F, 0xB797, 0x7A90, 0xB798, 0x7A91, 0xD2A4, 0x7A92, 0xD6CF,
+	0x7A93, 0xB799, 0x7A94, 0xB79A, 0x7A95, 0xF1BB, 0x7A96, 0xBDD1,
+	0x7A97, 0xB4B0, 0x7A98, 0xBEBD, 0x7A99, 0xB79B, 0x7A9A, 0xB79C,
+	0x7A9B, 0xB79D, 0x7A9C, 0xB4DC, 0x7A9D, 0xCED1, 0x7A9E, 0xB79E,
+	0x7A9F, 0xBFDF, 0x7AA0, 0xF1BD, 0x7AA1, 0xB79F, 0x7AA2, 0xB7A0,
+	0x7AA3, 0xB840, 0x7AA4, 0xB841, 0x7AA5, 0xBFFA, 0x7AA6, 0xF1BC,
+	0x7AA7, 0xB842, 0x7AA8, 0xF1BF, 0x7AA9, 0xB843, 0x7AAA, 0xB844,
+	0x7AAB, 0xB845, 0x7AAC, 0xF1BE, 0x7AAD, 0xF1C0, 0x7AAE, 0xB846,
+	0x7AAF, 0xB847, 0x7AB0, 0xB848, 0x7AB1, 0xB849, 0x7AB2, 0xB84A,
+	0x7AB3, 0xF1C1, 0x7AB4, 0xB84B, 0x7AB5, 0xB84C, 0x7AB6, 0xB84D,
+	0x7AB7, 0xB84E, 0x7AB8, 0xB84F, 0x7AB9, 0xB850, 0x7ABA, 0xB851,
+	0x7ABB, 0xB852, 0x7ABC, 0xB853, 0x7ABD, 0xB854, 0x7ABE, 0xB855,
+	0x7ABF, 0xC1FE, 0x7AC0, 0xB856, 0x7AC1, 0xB857, 0x7AC2, 0xB858,
+	0x7AC3, 0xB859, 0x7AC4, 0xB85A, 0x7AC5, 0xB85B, 0x7AC6, 0xB85C,
+	0x7AC7, 0xB85D, 0x7AC8, 0xB85E, 0x7AC9, 0xB85F, 0x7ACA, 0xB860,
+	0x7ACB, 0xC1A2, 0x7ACC, 0xB861, 0x7ACD, 0xB862, 0x7ACE, 0xB863,
+	0x7ACF, 0xB864, 0x7AD0, 0xB865, 0x7AD1, 0xB866, 0x7AD2, 0xB867,
+	0x7AD3, 0xB868, 0x7AD4, 0xB869, 0x7AD5, 0xB86A, 0x7AD6, 0xCAFA,
+	0x7AD7, 0xB86B, 0x7AD8, 0xB86C, 0x7AD9, 0xD5BE, 0x7ADA, 0xB86D,
+	0x7ADB, 0xB86E, 0x7ADC, 0xB86F, 0x7ADD, 0xB870, 0x7ADE, 0xBEBA,
+	0x7ADF, 0xBEB9, 0x7AE0, 0xD5C2, 0x7AE1, 0xB871, 0x7AE2, 0xB872,
+	0x7AE3, 0xBFA2, 0x7AE4, 0xB873, 0x7AE5, 0xCDAF, 0x7AE6, 0xF1B5,
+	0x7AE7, 0xB874, 0x7AE8, 0xB875, 0x7AE9, 0xB876, 0x7AEA, 0xB877,
+	0x7AEB, 0xB878, 0x7AEC, 0xB879, 0x7AED, 0xBDDF, 0x7AEE, 0xB87A,
+	0x7AEF, 0xB6CB, 0x7AF0, 0xB87B, 0x7AF1, 0xB87C, 0x7AF2, 0xB87D,
+	0x7AF3, 0xB87E, 0x7AF4, 0xB880, 0x7AF5, 0xB881, 0x7AF6, 0xB882,
+	0x7AF7, 0xB883, 0x7AF8, 0xB884, 0x7AF9, 0xD6F1, 0x7AFA, 0xF3C3,
+	0x7AFB, 0xB885, 0x7AFC, 0xB886, 0x7AFD, 0xF3C4, 0x7AFE, 0xB887,
+	0x7AFF, 0xB8CD, 0x7B00, 0xB888, 0x7B01, 0xB889, 0x7B02, 0xB88A,
+	0x7B03, 0xF3C6, 0x7B04, 0xF3C7, 0x7B05, 0xB88B, 0x7B06, 0xB0CA,
+	0x7B07, 0xB88C, 0x7B08, 0xF3C5, 0x7B09, 0xB88D, 0x7B0A, 0xF3C9,
+	0x7B0B, 0xCBF1, 0x7B0C, 0xB88E, 0x7B0D, 0xB88F, 0x7B0E, 0xB890,
+	0x7B0F, 0xF3CB, 0x7B10, 0xB891, 0x7B11, 0xD0A6, 0x7B12, 0xB892,
+	0x7B13, 0xB893, 0x7B14, 0xB1CA, 0x7B15, 0xF3C8, 0x7B16, 0xB894,
+	0x7B17, 0xB895, 0x7B18, 0xB896, 0x7B19, 0xF3CF, 0x7B1A, 0xB897,
+	0x7B1B, 0xB5D1, 0x7B1C, 0xB898, 0x7B1D, 0xB899, 0x7B1E, 0xF3D7,
+	0x7B1F, 0xB89A, 0x7B20, 0xF3D2, 0x7B21, 0xB89B, 0x7B22, 0xB89C,
+	0x7B23, 0xB89D, 0x7B24, 0xF3D4, 0x7B25, 0xF3D3, 0x7B26, 0xB7FB,
+	0x7B27, 0xB89E, 0x7B28, 0xB1BF, 0x7B29, 0xB89F, 0x7B2A, 0xF3CE,
+	0x7B2B, 0xF3CA, 0x7B2C, 0xB5DA, 0x7B2D, 0xB8A0, 0x7B2E, 0xF3D0,
+	0x7B2F, 0xB940, 0x7B30, 0xB941, 0x7B31, 0xF3D1, 0x7B32, 0xB942,
+	0x7B33, 0xF3D5, 0x7B34, 0xB943, 0x7B35, 0xB944, 0x7B36, 0xB945,
+	0x7B37, 0xB946, 0x7B38, 0xF3CD, 0x7B39, 0xB947, 0x7B3A, 0xBCE3,
+	0x7B3B, 0xB948, 0x7B3C, 0xC1FD, 0x7B3D, 0xB949, 0x7B3E, 0xF3D6,
+	0x7B3F, 0xB94A, 0x7B40, 0xB94B, 0x7B41, 0xB94C, 0x7B42, 0xB94D,
+	0x7B43, 0xB94E, 0x7B44, 0xB94F, 0x7B45, 0xF3DA, 0x7B46, 0xB950,
+	0x7B47, 0xF3CC, 0x7B48, 0xB951, 0x7B49, 0xB5C8, 0x7B4A, 0xB952,
+	0x7B4B, 0xBDEE, 0x7B4C, 0xF3DC, 0x7B4D, 0xB953, 0x7B4E, 0xB954,
+	0x7B4F, 0xB7A4, 0x7B50, 0xBFF0, 0x7B51, 0xD6FE, 0x7B52, 0xCDB2,
+	0x7B53, 0xB955, 0x7B54, 0xB4F0, 0x7B55, 0xB956, 0x7B56, 0xB2DF,
+	0x7B57, 0xB957, 0x7B58, 0xF3D8, 0x7B59, 0xB958, 0x7B5A, 0xF3D9,
+	0x7B5B, 0xC9B8, 0x7B5C, 0xB959, 0x7B5D, 0xF3DD, 0x7B5E, 0xB95A,
+	0x7B5F, 0xB95B, 0x7B60, 0xF3DE, 0x7B61, 0xB95C, 0x7B62, 0xF3E1,
+	0x7B63, 0xB95D, 0x7B64, 0xB95E, 0x7B65, 0xB95F, 0x7B66, 0xB960,
+	0x7B67, 0xB961, 0x7B68, 0xB962, 0x7B69, 0xB963, 0x7B6A, 0xB964,
+	0x7B6B, 0xB965, 0x7B6C, 0xB966, 0x7B6D, 0xB967, 0x7B6E, 0xF3DF,
+	0x7B6F, 0xB968, 0x7B70, 0xB969, 0x7B71, 0xF3E3, 0x7B72, 0xF3E2,
+	0x7B73, 0xB96A, 0x7B74, 0xB96B, 0x7B75, 0xF3DB, 0x7B76, 0xB96C,
+	0x7B77, 0xBFEA, 0x7B78, 0xB96D, 0x7B79, 0xB3EF, 0x7B7A, 0xB96E,
+	0x7B7B, 0xF3E0, 0x7B7C, 0xB96F, 0x7B7D, 0xB970, 0x7B7E, 0xC7A9,
+	0x7B7F, 0xB971, 0x7B80, 0xBCF2, 0x7B81, 0xB972, 0x7B82, 0xB973,
+	0x7B83, 0xB974, 0x7B84, 0xB975, 0x7B85, 0xF3EB, 0x7B86, 0xB976,
+	0x7B87, 0xB977, 0x7B88, 0xB978, 0x7B89, 0xB979, 0x7B8A, 0xB97A,
+	0x7B8B, 0xB97B, 0x7B8C, 0xB97C, 0x7B8D, 0xB9BF, 0x7B8E, 0xB97D,
+	0x7B8F, 0xB97E, 0x7B90, 0xF3E4, 0x7B91, 0xB980, 0x7B92, 0xB981,
+	0x7B93, 0xB982, 0x7B94, 0xB2AD, 0x7B95, 0xBBFE, 0x7B96, 0xB983,
+	0x7B97, 0xCBE3, 0x7B98, 0xB984, 0x7B99, 0xB985, 0x7B9A, 0xB986,
+	0x7B9B, 0xB987, 0x7B9C, 0xF3ED, 0x7B9D, 0xF3E9, 0x7B9E, 0xB988,
+	0x7B9F, 0xB989, 0x7BA0, 0xB98A, 0x7BA1, 0xB9DC, 0x7BA2, 0xF3EE,
+	0x7BA3, 0xB98B, 0x7BA4, 0xB98C, 0x7BA5, 0xB98D, 0x7BA6, 0xF3E5,
+	0x7BA7, 0xF3E6, 0x7BA8, 0xF3EA, 0x7BA9, 0xC2E1, 0x7BAA, 0xF3EC,
+	0x7BAB, 0xF3EF, 0x7BAC, 0xF3E8, 0x7BAD, 0xBCFD, 0x7BAE, 0xB98E,
+	0x7BAF, 0xB98F, 0x7BB0, 0xB990, 0x7BB1, 0xCFE4, 0x7BB2, 0xB991,
+	0x7BB3, 0xB992, 0x7BB4, 0xF3F0, 0x7BB5, 0xB993, 0x7BB6, 0xB994,
+	0x7BB7, 0xB995, 0x7BB8, 0xF3E7, 0x7BB9, 0xB996, 0x7BBA, 0xB997,
+	0x7BBB, 0xB998, 0x7BBC, 0xB999, 0x7BBD, 0xB99A, 0x7BBE, 0xB99B,
+	0x7BBF, 0xB99C, 0x7BC0, 0xB99D, 0x7BC1, 0xF3F2, 0x7BC2, 0xB99E,
+	0x7BC3, 0xB99F, 0x7BC4, 0xB9A0, 0x7BC5, 0xBA40, 0x7BC6, 0xD7AD,
+	0x7BC7, 0xC6AA, 0x7BC8, 0xBA41, 0x7BC9, 0xBA42, 0x7BCA, 0xBA43,
+	0x7BCB, 0xBA44, 0x7BCC, 0xF3F3, 0x7BCD, 0xBA45, 0x7BCE, 0xBA46,
+	0x7BCF, 0xBA47, 0x7BD0, 0xBA48, 0x7BD1, 0xF3F1, 0x7BD2, 0xBA49,
+	0x7BD3, 0xC2A8, 0x7BD4, 0xBA4A, 0x7BD5, 0xBA4B, 0x7BD6, 0xBA4C,
+	0x7BD7, 0xBA4D, 0x7BD8, 0xBA4E, 0x7BD9, 0xB8DD, 0x7BDA, 0xF3F5,
+	0x7BDB, 0xBA4F, 0x7BDC, 0xBA50, 0x7BDD, 0xF3F4, 0x7BDE, 0xBA51,
+	0x7BDF, 0xBA52, 0x7BE0, 0xBA53, 0x7BE1, 0xB4DB, 0x7BE2, 0xBA54,
+	0x7BE3, 0xBA55, 0x7BE4, 0xBA56, 0x7BE5, 0xF3F6, 0x7BE6, 0xF3F7,
+	0x7BE7, 0xBA57, 0x7BE8, 0xBA58, 0x7BE9, 0xBA59, 0x7BEA, 0xF3F8,
+	0x7BEB, 0xBA5A, 0x7BEC, 0xBA5B, 0x7BED, 0xBA5C, 0x7BEE, 0xC0BA,
+	0x7BEF, 0xBA5D, 0x7BF0, 0xBA5E, 0x7BF1, 0xC0E9, 0x7BF2, 0xBA5F,
+	0x7BF3, 0xBA60, 0x7BF4, 0xBA61, 0x7BF5, 0xBA62, 0x7BF6, 0xBA63,
+	0x7BF7, 0xC5F1, 0x7BF8, 0xBA64, 0x7BF9, 0xBA65, 0x7BFA, 0xBA66,
+	0x7BFB, 0xBA67, 0x7BFC, 0xF3FB, 0x7BFD, 0xBA68, 0x7BFE, 0xF3FA,
+	0x7BFF, 0xBA69, 0x7C00, 0xBA6A, 0x7C01, 0xBA6B, 0x7C02, 0xBA6C,
+	0x7C03, 0xBA6D, 0x7C04, 0xBA6E, 0x7C05, 0xBA6F, 0x7C06, 0xBA70,
+	0x7C07, 0xB4D8, 0x7C08, 0xBA71, 0x7C09, 0xBA72, 0x7C0A, 0xBA73,
+	0x7C0B, 0xF3FE, 0x7C0C, 0xF3F9, 0x7C0D, 0xBA74, 0x7C0E, 0xBA75,
+	0x7C0F, 0xF3FC, 0x7C10, 0xBA76, 0x7C11, 0xBA77, 0x7C12, 0xBA78,
+	0x7C13, 0xBA79, 0x7C14, 0xBA7A, 0x7C15, 0xBA7B, 0x7C16, 0xF3FD,
+	0x7C17, 0xBA7C, 0x7C18, 0xBA7D, 0x7C19, 0xBA7E, 0x7C1A, 0xBA80,
+	0x7C1B, 0xBA81, 0x7C1C, 0xBA82, 0x7C1D, 0xBA83, 0x7C1E, 0xBA84,
+	0x7C1F, 0xF4A1, 0x7C20, 0xBA85, 0x7C21, 0xBA86, 0x7C22, 0xBA87,
+	0x7C23, 0xBA88, 0x7C24, 0xBA89, 0x7C25, 0xBA8A, 0x7C26, 0xF4A3,
+	0x7C27, 0xBBC9, 0x7C28, 0xBA8B, 0x7C29, 0xBA8C, 0x7C2A, 0xF4A2,
+	0x7C2B, 0xBA8D, 0x7C2C, 0xBA8E, 0x7C2D, 0xBA8F, 0x7C2E, 0xBA90,
+	0x7C2F, 0xBA91, 0x7C30, 0xBA92, 0x7C31, 0xBA93, 0x7C32, 0xBA94,
+	0x7C33, 0xBA95, 0x7C34, 0xBA96, 0x7C35, 0xBA97, 0x7C36, 0xBA98,
+	0x7C37, 0xBA99, 0x7C38, 0xF4A4, 0x7C39, 0xBA9A, 0x7C3A, 0xBA9B,
+	0x7C3B, 0xBA9C, 0x7C3C, 0xBA9D, 0x7C3D, 0xBA9E, 0x7C3E, 0xBA9F,
+	0x7C3F, 0xB2BE, 0x7C40, 0xF4A6, 0x7C41, 0xF4A5, 0x7C42, 0xBAA0,
+	0x7C43, 0xBB40, 0x7C44, 0xBB41, 0x7C45, 0xBB42, 0x7C46, 0xBB43,
+	0x7C47, 0xBB44, 0x7C48, 0xBB45, 0x7C49, 0xBB46, 0x7C4A, 0xBB47,
+	0x7C4B, 0xBB48, 0x7C4C, 0xBB49, 0x7C4D, 0xBCAE, 0x7C4E, 0xBB4A,
+	0x7C4F, 0xBB4B, 0x7C50, 0xBB4C, 0x7C51, 0xBB4D, 0x7C52, 0xBB4E,
+	0x7C53, 0xBB4F, 0x7C54, 0xBB50, 0x7C55, 0xBB51, 0x7C56, 0xBB52,
+	0x7C57, 0xBB53, 0x7C58, 0xBB54, 0x7C59, 0xBB55, 0x7C5A, 0xBB56,
+	0x7C5B, 0xBB57, 0x7C5C, 0xBB58, 0x7C5D, 0xBB59, 0x7C5E, 0xBB5A,
+	0x7C5F, 0xBB5B, 0x7C60, 0xBB5C, 0x7C61, 0xBB5D, 0x7C62, 0xBB5E,
+	0x7C63, 0xBB5F, 0x7C64, 0xBB60, 0x7C65, 0xBB61, 0x7C66, 0xBB62,
+	0x7C67, 0xBB63, 0x7C68, 0xBB64, 0x7C69, 0xBB65, 0x7C6A, 0xBB66,
+	0x7C6B, 0xBB67, 0x7C6C, 0xBB68, 0x7C6D, 0xBB69, 0x7C6E, 0xBB6A,
+	0x7C6F, 0xBB6B, 0x7C70, 0xBB6C, 0x7C71, 0xBB6D, 0x7C72, 0xBB6E,
+	0x7C73, 0xC3D7, 0x7C74, 0xD9E1, 0x7C75, 0xBB6F, 0x7C76, 0xBB70,
+	0x7C77, 0xBB71, 0x7C78, 0xBB72, 0x7C79, 0xBB73, 0x7C7A, 0xBB74,
+	0x7C7B, 0xC0E0, 0x7C7C, 0xF4CC, 0x7C7D, 0xD7D1, 0x7C7E, 0xBB75,
+	0x7C7F, 0xBB76, 0x7C80, 0xBB77, 0x7C81, 0xBB78, 0x7C82, 0xBB79,
+	0x7C83, 0xBB7A, 0x7C84, 0xBB7B, 0x7C85, 0xBB7C, 0x7C86, 0xBB7D,
+	0x7C87, 0xBB7E, 0x7C88, 0xBB80, 0x7C89, 0xB7DB, 0x7C8A, 0xBB81,
+	0x7C8B, 0xBB82, 0x7C8C, 0xBB83, 0x7C8D, 0xBB84, 0x7C8E, 0xBB85,
+	0x7C8F, 0xBB86, 0x7C90, 0xBB87, 0x7C91, 0xF4CE, 0x7C92, 0xC1A3,
+	0x7C93, 0xBB88, 0x7C94, 0xBB89, 0x7C95, 0xC6C9, 0x7C96, 0xBB8A,
+	0x7C97, 0xB4D6, 0x7C98, 0xD5B3, 0x7C99, 0xBB8B, 0x7C9A, 0xBB8C,
+	0x7C9B, 0xBB8D, 0x7C9C, 0xF4D0, 0x7C9D, 0xF4CF, 0x7C9E, 0xF4D1,
+	0x7C9F, 0xCBDA, 0x7CA0, 0xBB8E, 0x7CA1, 0xBB8F, 0x7CA2, 0xF4D2,
+	0x7CA3, 0xBB90, 0x7CA4, 0xD4C1, 0x7CA5, 0xD6E0, 0x7CA6, 0xBB91,
+	0x7CA7, 0xBB92, 0x7CA8, 0xBB93, 0x7CA9, 0xBB94, 0x7CAA, 0xB7E0,
+	0x7CAB, 0xBB95, 0x7CAC, 0xBB96, 0x7CAD, 0xBB97, 0x7CAE, 0xC1B8,
+	0x7CAF, 0xBB98, 0x7CB0, 0xBB99, 0x7CB1, 0xC1BB, 0x7CB2, 0xF4D3,
+	0x7CB3, 0xBEAC, 0x7CB4, 0xBB9A, 0x7CB5, 0xBB9B, 0x7CB6, 0xBB9C,
+	0x7CB7, 0xBB9D, 0x7CB8, 0xBB9E, 0x7CB9, 0xB4E2, 0x7CBA, 0xBB9F,
+	0x7CBB, 0xBBA0, 0x7CBC, 0xF4D4, 0x7CBD, 0xF4D5, 0x7CBE, 0xBEAB,
+	0x7CBF, 0xBC40, 0x7CC0, 0xBC41, 0x7CC1, 0xF4D6, 0x7CC2, 0xBC42,
+	0x7CC3, 0xBC43, 0x7CC4, 0xBC44, 0x7CC5, 0xF4DB, 0x7CC6, 0xBC45,
+	0x7CC7, 0xF4D7, 0x7CC8, 0xF4DA, 0x7CC9, 0xBC46, 0x7CCA, 0xBAFD,
+	0x7CCB, 0xBC47, 0x7CCC, 0xF4D8, 0x7CCD, 0xF4D9, 0x7CCE, 0xBC48,
+	0x7CCF, 0xBC49, 0x7CD0, 0xBC4A, 0x7CD1, 0xBC4B, 0x7CD2, 0xBC4C,
+	0x7CD3, 0xBC4D, 0x7CD4, 0xBC4E, 0x7CD5, 0xB8E2, 0x7CD6, 0xCCC7,
+	0x7CD7, 0xF4DC, 0x7CD8, 0xBC4F, 0x7CD9, 0xB2DA, 0x7CDA, 0xBC50,
+	0x7CDB, 0xBC51, 0x7CDC, 0xC3D3, 0x7CDD, 0xBC52, 0x7CDE, 0xBC53,
+	0x7CDF, 0xD4E3, 0x7CE0, 0xBFB7, 0x7CE1, 0xBC54, 0x7CE2, 0xBC55,
+	0x7CE3, 0xBC56, 0x7CE4, 0xBC57, 0x7CE5, 0xBC58, 0x7CE6, 0xBC59,
+	0x7CE7, 0xBC5A, 0x7CE8, 0xF4DD, 0x7CE9, 0xBC5B, 0x7CEA, 0xBC5C,
+	0x7CEB, 0xBC5D, 0x7CEC, 0xBC5E, 0x7CED, 0xBC5F, 0x7CEE, 0xBC60,
+	0x7CEF, 0xC5B4, 0x7CF0, 0xBC61, 0x7CF1, 0xBC62, 0x7CF2, 0xBC63,
+	0x7CF3, 0xBC64, 0x7CF4, 0xBC65, 0x7CF5, 0xBC66, 0x7CF6, 0xBC67,
+	0x7CF7, 0xBC68, 0x7CF8, 0xF4E9, 0x7CF9, 0xBC69, 0x7CFA, 0xBC6A,
+	0x7CFB, 0xCFB5, 0x7CFC, 0xBC6B, 0x7CFD, 0xBC6C, 0x7CFE, 0xBC6D,
+	0x7CFF, 0xBC6E, 0x7D00, 0xBC6F, 0x7D01, 0xBC70, 0x7D02, 0xBC71,
+	0x7D03, 0xBC72, 0x7D04, 0xBC73, 0x7D05, 0xBC74, 0x7D06, 0xBC75,
+	0x7D07, 0xBC76, 0x7D08, 0xBC77, 0x7D09, 0xBC78, 0x7D0A, 0xCEC9,
+	0x7D0B, 0xBC79, 0x7D0C, 0xBC7A, 0x7D0D, 0xBC7B, 0x7D0E, 0xBC7C,
+	0x7D0F, 0xBC7D, 0x7D10, 0xBC7E, 0x7D11, 0xBC80, 0x7D12, 0xBC81,
+	0x7D13, 0xBC82, 0x7D14, 0xBC83, 0x7D15, 0xBC84, 0x7D16, 0xBC85,
+	0x7D17, 0xBC86, 0x7D18, 0xBC87, 0x7D19, 0xBC88, 0x7D1A, 0xBC89,
+	0x7D1B, 0xBC8A, 0x7D1C, 0xBC8B, 0x7D1D, 0xBC8C, 0x7D1E, 0xBC8D,
+	0x7D1F, 0xBC8E, 0x7D20, 0xCBD8, 0x7D21, 0xBC8F, 0x7D22, 0xCBF7,
+	0x7D23, 0xBC90, 0x7D24, 0xBC91, 0x7D25, 0xBC92, 0x7D26, 0xBC93,
+	0x7D27, 0xBDF4, 0x7D28, 0xBC94, 0x7D29, 0xBC95, 0x7D2A, 0xBC96,
+	0x7D2B, 0xD7CF, 0x7D2C, 0xBC97, 0x7D2D, 0xBC98, 0x7D2E, 0xBC99,
+	0x7D2F, 0xC0DB, 0x7D30, 0xBC9A, 0x7D31, 0xBC9B, 0x7D32, 0xBC9C,
+	0x7D33, 0xBC9D, 0x7D34, 0xBC9E, 0x7D35, 0xBC9F, 0x7D36, 0xBCA0,
+	0x7D37, 0xBD40, 0x7D38, 0xBD41, 0x7D39, 0xBD42, 0x7D3A, 0xBD43,
+	0x7D3B, 0xBD44, 0x7D3C, 0xBD45, 0x7D3D, 0xBD46, 0x7D3E, 0xBD47,
+	0x7D3F, 0xBD48, 0x7D40, 0xBD49, 0x7D41, 0xBD4A, 0x7D42, 0xBD4B,
+	0x7D43, 0xBD4C, 0x7D44, 0xBD4D, 0x7D45, 0xBD4E, 0x7D46, 0xBD4F,
+	0x7D47, 0xBD50, 0x7D48, 0xBD51, 0x7D49, 0xBD52, 0x7D4A, 0xBD53,
+	0x7D4B, 0xBD54, 0x7D4C, 0xBD55, 0x7D4D, 0xBD56, 0x7D4E, 0xBD57,
+	0x7D4F, 0xBD58, 0x7D50, 0xBD59, 0x7D51, 0xBD5A, 0x7D52, 0xBD5B,
+	0x7D53, 0xBD5C, 0x7D54, 0xBD5D, 0x7D55, 0xBD5E, 0x7D56, 0xBD5F,
+	0x7D57, 0xBD60, 0x7D58, 0xBD61, 0x7D59, 0xBD62, 0x7D5A, 0xBD63,
+	0x7D5B, 0xBD64, 0x7D5C, 0xBD65, 0x7D5D, 0xBD66, 0x7D5E, 0xBD67,
+	0x7D5F, 0xBD68, 0x7D60, 0xBD69, 0x7D61, 0xBD6A, 0x7D62, 0xBD6B,
+	0x7D63, 0xBD6C, 0x7D64, 0xBD6D, 0x7D65, 0xBD6E, 0x7D66, 0xBD6F,
+	0x7D67, 0xBD70, 0x7D68, 0xBD71, 0x7D69, 0xBD72, 0x7D6A, 0xBD73,
+	0x7D6B, 0xBD74, 0x7D6C, 0xBD75, 0x7D6D, 0xBD76, 0x7D6E, 0xD0F5,
+	0x7D6F, 0xBD77, 0x7D70, 0xBD78, 0x7D71, 0xBD79, 0x7D72, 0xBD7A,
+	0x7D73, 0xBD7B, 0x7D74, 0xBD7C, 0x7D75, 0xBD7D, 0x7D76, 0xBD7E,
+	0x7D77, 0xF4EA, 0x7D78, 0xBD80, 0x7D79, 0xBD81, 0x7D7A, 0xBD82,
+	0x7D7B, 0xBD83, 0x7D7C, 0xBD84, 0x7D7D, 0xBD85, 0x7D7E, 0xBD86,
+	0x7D7F, 0xBD87, 0x7D80, 0xBD88, 0x7D81, 0xBD89, 0x7D82, 0xBD8A,
+	0x7D83, 0xBD8B, 0x7D84, 0xBD8C, 0x7D85, 0xBD8D, 0x7D86, 0xBD8E,
+	0x7D87, 0xBD8F, 0x7D88, 0xBD90, 0x7D89, 0xBD91, 0x7D8A, 0xBD92,
+	0x7D8B, 0xBD93, 0x7D8C, 0xBD94, 0x7D8D, 0xBD95, 0x7D8E, 0xBD96,
+	0x7D8F, 0xBD97, 0x7D90, 0xBD98, 0x7D91, 0xBD99, 0x7D92, 0xBD9A,
+	0x7D93, 0xBD9B, 0x7D94, 0xBD9C, 0x7D95, 0xBD9D, 0x7D96, 0xBD9E,
+	0x7D97, 0xBD9F, 0x7D98, 0xBDA0, 0x7D99, 0xBE40, 0x7D9A, 0xBE41,
+	0x7D9B, 0xBE42, 0x7D9C, 0xBE43, 0x7D9D, 0xBE44, 0x7D9E, 0xBE45,
+	0x7D9F, 0xBE46, 0x7DA0, 0xBE47, 0x7DA1, 0xBE48, 0x7DA2, 0xBE49,
+	0x7DA3, 0xBE4A, 0x7DA4, 0xBE4B, 0x7DA5, 0xBE4C, 0x7DA6, 0xF4EB,
+	0x7DA7, 0xBE4D, 0x7DA8, 0xBE4E, 0x7DA9, 0xBE4F, 0x7DAA, 0xBE50,
+	0x7DAB, 0xBE51, 0x7DAC, 0xBE52, 0x7DAD, 0xBE53, 0x7DAE, 0xF4EC,
+	0x7DAF, 0xBE54, 0x7DB0, 0xBE55, 0x7DB1, 0xBE56, 0x7DB2, 0xBE57,
+	0x7DB3, 0xBE58, 0x7DB4, 0xBE59, 0x7DB5, 0xBE5A, 0x7DB6, 0xBE5B,
+	0x7DB7, 0xBE5C, 0x7DB8, 0xBE5D, 0x7DB9, 0xBE5E, 0x7DBA, 0xBE5F,
+	0x7DBB, 0xBE60, 0x7DBC, 0xBE61, 0x7DBD, 0xBE62, 0x7DBE, 0xBE63,
+	0x7DBF, 0xBE64, 0x7DC0, 0xBE65, 0x7DC1, 0xBE66, 0x7DC2, 0xBE67,
+	0x7DC3, 0xBE68, 0x7DC4, 0xBE69, 0x7DC5, 0xBE6A, 0x7DC6, 0xBE6B,
+	0x7DC7, 0xBE6C, 0x7DC8, 0xBE6D, 0x7DC9, 0xBE6E, 0x7DCA, 0xBE6F,
+	0x7DCB, 0xBE70, 0x7DCC, 0xBE71, 0x7DCD, 0xBE72, 0x7DCE, 0xBE73,
+	0x7DCF, 0xBE74, 0x7DD0, 0xBE75, 0x7DD1, 0xBE76, 0x7DD2, 0xBE77,
+	0x7DD3, 0xBE78, 0x7DD4, 0xBE79, 0x7DD5, 0xBE7A, 0x7DD6, 0xBE7B,
+	0x7DD7, 0xBE7C, 0x7DD8, 0xBE7D, 0x7DD9, 0xBE7E, 0x7DDA, 0xBE80,
+	0x7DDB, 0xBE81, 0x7DDC, 0xBE82, 0x7DDD, 0xBE83, 0x7DDE, 0xBE84,
+	0x7DDF, 0xBE85, 0x7DE0, 0xBE86, 0x7DE1, 0xBE87, 0x7DE2, 0xBE88,
+	0x7DE3, 0xBE89, 0x7DE4, 0xBE8A, 0x7DE5, 0xBE8B, 0x7DE6, 0xBE8C,
+	0x7DE7, 0xBE8D, 0x7DE8, 0xBE8E, 0x7DE9, 0xBE8F, 0x7DEA, 0xBE90,
+	0x7DEB, 0xBE91, 0x7DEC, 0xBE92, 0x7DED, 0xBE93, 0x7DEE, 0xBE94,
+	0x7DEF, 0xBE95, 0x7DF0, 0xBE96, 0x7DF1, 0xBE97, 0x7DF2, 0xBE98,
+	0x7DF3, 0xBE99, 0x7DF4, 0xBE9A, 0x7DF5, 0xBE9B, 0x7DF6, 0xBE9C,
+	0x7DF7, 0xBE9D, 0x7DF8, 0xBE9E, 0x7DF9, 0xBE9F, 0x7DFA, 0xBEA0,
+	0x7DFB, 0xBF40, 0x7DFC, 0xBF41, 0x7DFD, 0xBF42, 0x7DFE, 0xBF43,
+	0x7DFF, 0xBF44, 0x7E00, 0xBF45, 0x7E01, 0xBF46, 0x7E02, 0xBF47,
+	0x7E03, 0xBF48, 0x7E04, 0xBF49, 0x7E05, 0xBF4A, 0x7E06, 0xBF4B,
+	0x7E07, 0xBF4C, 0x7E08, 0xBF4D, 0x7E09, 0xBF4E, 0x7E0A, 0xBF4F,
+	0x7E0B, 0xBF50, 0x7E0C, 0xBF51, 0x7E0D, 0xBF52, 0x7E0E, 0xBF53,
+	0x7E0F, 0xBF54, 0x7E10, 0xBF55, 0x7E11, 0xBF56, 0x7E12, 0xBF57,
+	0x7E13, 0xBF58, 0x7E14, 0xBF59, 0x7E15, 0xBF5A, 0x7E16, 0xBF5B,
+	0x7E17, 0xBF5C, 0x7E18, 0xBF5D, 0x7E19, 0xBF5E, 0x7E1A, 0xBF5F,
+	0x7E1B, 0xBF60, 0x7E1C, 0xBF61, 0x7E1D, 0xBF62, 0x7E1E, 0xBF63,
+	0x7E1F, 0xBF64, 0x7E20, 0xBF65, 0x7E21, 0xBF66, 0x7E22, 0xBF67,
+	0x7E23, 0xBF68, 0x7E24, 0xBF69, 0x7E25, 0xBF6A, 0x7E26, 0xBF6B,
+	0x7E27, 0xBF6C, 0x7E28, 0xBF6D, 0x7E29, 0xBF6E, 0x7E2A, 0xBF6F,
+	0x7E2B, 0xBF70, 0x7E2C, 0xBF71, 0x7E2D, 0xBF72, 0x7E2E, 0xBF73,
+	0x7E2F, 0xBF74, 0x7E30, 0xBF75, 0x7E31, 0xBF76, 0x7E32, 0xBF77,
+	0x7E33, 0xBF78, 0x7E34, 0xBF79, 0x7E35, 0xBF7A, 0x7E36, 0xBF7B,
+	0x7E37, 0xBF7C, 0x7E38, 0xBF7D, 0x7E39, 0xBF7E, 0x7E3A, 0xBF80,
+	0x7E3B, 0xF7E3, 0x7E3C, 0xBF81, 0x7E3D, 0xBF82, 0x7E3E, 0xBF83,
+	0x7E3F, 0xBF84, 0x7E40, 0xBF85, 0x7E41, 0xB7B1, 0x7E42, 0xBF86,
+	0x7E43, 0xBF87, 0x7E44, 0xBF88, 0x7E45, 0xBF89, 0x7E46, 0xBF8A,
+	0x7E47, 0xF4ED, 0x7E48, 0xBF8B, 0x7E49, 0xBF8C, 0x7E4A, 0xBF8D,
+	0x7E4B, 0xBF8E, 0x7E4C, 0xBF8F, 0x7E4D, 0xBF90, 0x7E4E, 0xBF91,
+	0x7E4F, 0xBF92, 0x7E50, 0xBF93, 0x7E51, 0xBF94, 0x7E52, 0xBF95,
+	0x7E53, 0xBF96, 0x7E54, 0xBF97, 0x7E55, 0xBF98, 0x7E56, 0xBF99,
+	0x7E57, 0xBF9A, 0x7E58, 0xBF9B, 0x7E59, 0xBF9C, 0x7E5A, 0xBF9D,
+	0x7E5B, 0xBF9E, 0x7E5C, 0xBF9F, 0x7E5D, 0xBFA0, 0x7E5E, 0xC040,
+	0x7E5F, 0xC041, 0x7E60, 0xC042, 0x7E61, 0xC043, 0x7E62, 0xC044,
+	0x7E63, 0xC045, 0x7E64, 0xC046, 0x7E65, 0xC047, 0x7E66, 0xC048,
+	0x7E67, 0xC049, 0x7E68, 0xC04A, 0x7E69, 0xC04B, 0x7E6A, 0xC04C,
+	0x7E6B, 0xC04D, 0x7E6C, 0xC04E, 0x7E6D, 0xC04F, 0x7E6E, 0xC050,
+	0x7E6F, 0xC051, 0x7E70, 0xC052, 0x7E71, 0xC053, 0x7E72, 0xC054,
+	0x7E73, 0xC055, 0x7E74, 0xC056, 0x7E75, 0xC057, 0x7E76, 0xC058,
+	0x7E77, 0xC059, 0x7E78, 0xC05A, 0x7E79, 0xC05B, 0x7E7A, 0xC05C,
+	0x7E7B, 0xC05D, 0x7E7C, 0xC05E, 0x7E7D, 0xC05F, 0x7E7E, 0xC060,
+	0x7E7F, 0xC061, 0x7E80, 0xC062, 0x7E81, 0xC063, 0x7E82, 0xD7EB,
+	0x7E83, 0xC064, 0x7E84, 0xC065, 0x7E85, 0xC066, 0x7E86, 0xC067,
+	0x7E87, 0xC068, 0x7E88, 0xC069, 0x7E89, 0xC06A, 0x7E8A, 0xC06B,
+	0x7E8B, 0xC06C, 0x7E8C, 0xC06D, 0x7E8D, 0xC06E, 0x7E8E, 0xC06F,
+	0x7E8F, 0xC070, 0x7E90, 0xC071, 0x7E91, 0xC072, 0x7E92, 0xC073,
+	0x7E93, 0xC074, 0x7E94, 0xC075, 0x7E95, 0xC076, 0x7E96, 0xC077,
+	0x7E97, 0xC078, 0x7E98, 0xC079, 0x7E99, 0xC07A, 0x7E9A, 0xC07B,
+	0x7E9B, 0xF4EE, 0x7E9C, 0xC07C, 0x7E9D, 0xC07D, 0x7E9E, 0xC07E,
+	0x7E9F, 0xE6F9, 0x7EA0, 0xBEC0, 0x7EA1, 0xE6FA, 0x7EA2, 0xBAEC,
+	0x7EA3, 0xE6FB, 0x7EA4, 0xCFCB, 0x7EA5, 0xE6FC, 0x7EA6, 0xD4BC,
+	0x7EA7, 0xBCB6, 0x7EA8, 0xE6FD, 0x7EA9, 0xE6FE, 0x7EAA, 0xBCCD,
+	0x7EAB, 0xC8D2, 0x7EAC, 0xCEB3, 0x7EAD, 0xE7A1, 0x7EAE, 0xC080,
+	0x7EAF, 0xB4BF, 0x7EB0, 0xE7A2, 0x7EB1, 0xC9B4, 0x7EB2, 0xB8D9,
+	0x7EB3, 0xC4C9, 0x7EB4, 0xC081, 0x7EB5, 0xD7DD, 0x7EB6, 0xC2DA,
+	0x7EB7, 0xB7D7, 0x7EB8, 0xD6BD, 0x7EB9, 0xCEC6, 0x7EBA, 0xB7C4,
+	0x7EBB, 0xC082, 0x7EBC, 0xC083, 0x7EBD, 0xC5A6, 0x7EBE, 0xE7A3,
+	0x7EBF, 0xCFDF, 0x7EC0, 0xE7A4, 0x7EC1, 0xE7A5, 0x7EC2, 0xE7A6,
+	0x7EC3, 0xC1B7, 0x7EC4, 0xD7E9, 0x7EC5, 0xC9F0, 0x7EC6, 0xCFB8,
+	0x7EC7, 0xD6AF, 0x7EC8, 0xD6D5, 0x7EC9, 0xE7A7, 0x7ECA, 0xB0ED,
+	0x7ECB, 0xE7A8, 0x7ECC, 0xE7A9, 0x7ECD, 0xC9DC, 0x7ECE, 0xD2EF,
+	0x7ECF, 0xBEAD, 0x7ED0, 0xE7AA, 0x7ED1, 0xB0F3, 0x7ED2, 0xC8DE,
+	0x7ED3, 0xBDE1, 0x7ED4, 0xE7AB, 0x7ED5, 0xC8C6, 0x7ED6, 0xC084,
+	0x7ED7, 0xE7AC, 0x7ED8, 0xBBE6, 0x7ED9, 0xB8F8, 0x7EDA, 0xD1A4,
+	0x7EDB, 0xE7AD, 0x7EDC, 0xC2E7, 0x7EDD, 0xBEF8, 0x7EDE, 0xBDCA,
+	0x7EDF, 0xCDB3, 0x7EE0, 0xE7AE, 0x7EE1, 0xE7AF, 0x7EE2, 0xBEEE,
+	0x7EE3, 0xD0E5, 0x7EE4, 0xC085, 0x7EE5, 0xCBE7, 0x7EE6, 0xCCD0,
+	0x7EE7, 0xBCCC, 0x7EE8, 0xE7B0, 0x7EE9, 0xBCA8, 0x7EEA, 0xD0F7,
+	0x7EEB, 0xE7B1, 0x7EEC, 0xC086, 0x7EED, 0xD0F8, 0x7EEE, 0xE7B2,
+	0x7EEF, 0xE7B3, 0x7EF0, 0xB4C2, 0x7EF1, 0xE7B4, 0x7EF2, 0xE7B5,
+	0x7EF3, 0xC9FE, 0x7EF4, 0xCEAC, 0x7EF5, 0xC3E0, 0x7EF6, 0xE7B7,
+	0x7EF7, 0xB1C1, 0x7EF8, 0xB3F1, 0x7EF9, 0xC087, 0x7EFA, 0xE7B8,
+	0x7EFB, 0xE7B9, 0x7EFC, 0xD7DB, 0x7EFD, 0xD5C0, 0x7EFE, 0xE7BA,
+	0x7EFF, 0xC2CC, 0x7F00, 0xD7BA, 0x7F01, 0xE7BB, 0x7F02, 0xE7BC,
+	0x7F03, 0xE7BD, 0x7F04, 0xBCEA, 0x7F05, 0xC3E5, 0x7F06, 0xC0C2,
+	0x7F07, 0xE7BE, 0x7F08, 0xE7BF, 0x7F09, 0xBCA9, 0x7F0A, 0xC088,
+	0x7F0B, 0xE7C0, 0x7F0C, 0xE7C1, 0x7F0D, 0xE7B6, 0x7F0E, 0xB6D0,
+	0x7F0F, 0xE7C2, 0x7F10, 0xC089, 0x7F11, 0xE7C3, 0x7F12, 0xE7C4,
+	0x7F13, 0xBBBA, 0x7F14, 0xB5DE, 0x7F15, 0xC2C6, 0x7F16, 0xB1E0,
+	0x7F17, 0xE7C5, 0x7F18, 0xD4B5, 0x7F19, 0xE7C6, 0x7F1A, 0xB8BF,
+	0x7F1B, 0xE7C8, 0x7F1C, 0xE7C7, 0x7F1D, 0xB7EC, 0x7F1E, 0xC08A,
+	0x7F1F, 0xE7C9, 0x7F20, 0xB2F8, 0x7F21, 0xE7CA, 0x7F22, 0xE7CB,
+	0x7F23, 0xE7CC, 0x7F24, 0xE7CD, 0x7F25, 0xE7CE, 0x7F26, 0xE7CF,
+	0x7F27, 0xE7D0, 0x7F28, 0xD3A7, 0x7F29, 0xCBF5, 0x7F2A, 0xE7D1,
+	0x7F2B, 0xE7D2, 0x7F2C, 0xE7D3, 0x7F2D, 0xE7D4, 0x7F2E, 0xC9C9,
+	0x7F2F, 0xE7D5, 0x7F30, 0xE7D6, 0x7F31, 0xE7D7, 0x7F32, 0xE7D8,
+	0x7F33, 0xE7D9, 0x7F34, 0xBDC9, 0x7F35, 0xE7DA, 0x7F36, 0xF3BE,
+	0x7F37, 0xC08B, 0x7F38, 0xB8D7, 0x7F39, 0xC08C, 0x7F3A, 0xC8B1,
+	0x7F3B, 0xC08D, 0x7F3C, 0xC08E, 0x7F3D, 0xC08F, 0x7F3E, 0xC090,
+	0x7F3F, 0xC091, 0x7F40, 0xC092, 0x7F41, 0xC093, 0x7F42, 0xF3BF,
+	0x7F43, 0xC094, 0x7F44, 0xF3C0, 0x7F45, 0xF3C1, 0x7F46, 0xC095,
+	0x7F47, 0xC096, 0x7F48, 0xC097, 0x7F49, 0xC098, 0x7F4A, 0xC099,
+	0x7F4B, 0xC09A, 0x7F4C, 0xC09B, 0x7F4D, 0xC09C, 0x7F4E, 0xC09D,
+	0x7F4F, 0xC09E, 0x7F50, 0xB9DE, 0x7F51, 0xCDF8, 0x7F52, 0xC09F,
+	0x7F53, 0xC0A0, 0x7F54, 0xD8E8, 0x7F55, 0xBAB1, 0x7F56, 0xC140,
+	0x7F57, 0xC2DE, 0x7F58, 0xEEB7, 0x7F59, 0xC141, 0x7F5A, 0xB7A3,
+	0x7F5B, 0xC142, 0x7F5C, 0xC143, 0x7F5D, 0xC144, 0x7F5E, 0xC145,
+	0x7F5F, 0xEEB9, 0x7F60, 0xC146, 0x7F61, 0xEEB8, 0x7F62, 0xB0D5,
+	0x7F63, 0xC147, 0x7F64, 0xC148, 0x7F65, 0xC149, 0x7F66, 0xC14A,
+	0x7F67, 0xC14B, 0x7F68, 0xEEBB, 0x7F69, 0xD5D6, 0x7F6A, 0xD7EF,
+	0x7F6B, 0xC14C, 0x7F6C, 0xC14D, 0x7F6D, 0xC14E, 0x7F6E, 0xD6C3,
+	0x7F6F, 0xC14F, 0x7F70, 0xC150, 0x7F71, 0xEEBD, 0x7F72, 0xCAF0,
+	0x7F73, 0xC151, 0x7F74, 0xEEBC, 0x7F75, 0xC152, 0x7F76, 0xC153,
+	0x7F77, 0xC154, 0x7F78, 0xC155, 0x7F79, 0xEEBE, 0x7F7A, 0xC156,
+	0x7F7B, 0xC157, 0x7F7C, 0xC158, 0x7F7D, 0xC159, 0x7F7E, 0xEEC0,
+	0x7F7F, 0xC15A, 0x7F80, 0xC15B, 0x7F81, 0xEEBF, 0x7F82, 0xC15C,
+	0x7F83, 0xC15D, 0x7F84, 0xC15E, 0x7F85, 0xC15F, 0x7F86, 0xC160,
+	0x7F87, 0xC161, 0x7F88, 0xC162, 0x7F89, 0xC163, 0x7F8A, 0xD1F2,
+	0x7F8B, 0xC164, 0x7F8C, 0xC7BC, 0x7F8D, 0xC165, 0x7F8E, 0xC3C0,
+	0x7F8F, 0xC166, 0x7F90, 0xC167, 0x7F91, 0xC168, 0x7F92, 0xC169,
+	0x7F93, 0xC16A, 0x7F94, 0xB8E1, 0x7F95, 0xC16B, 0x7F96, 0xC16C,
+	0x7F97, 0xC16D, 0x7F98, 0xC16E, 0x7F99, 0xC16F, 0x7F9A, 0xC1E7,
+	0x7F9B, 0xC170, 0x7F9C, 0xC171, 0x7F9D, 0xF4C6, 0x7F9E, 0xD0DF,
+	0x7F9F, 0xF4C7, 0x7FA0, 0xC172, 0x7FA1, 0xCFDB, 0x7FA2, 0xC173,
+	0x7FA3, 0xC174, 0x7FA4, 0xC8BA, 0x7FA5, 0xC175, 0x7FA6, 0xC176,
+	0x7FA7, 0xF4C8, 0x7FA8, 0xC177, 0x7FA9, 0xC178, 0x7FAA, 0xC179,
+	0x7FAB, 0xC17A, 0x7FAC, 0xC17B, 0x7FAD, 0xC17C, 0x7FAE, 0xC17D,
+	0x7FAF, 0xF4C9, 0x7FB0, 0xF4CA, 0x7FB1, 0xC17E, 0x7FB2, 0xF4CB,
+	0x7FB3, 0xC180, 0x7FB4, 0xC181, 0x7FB5, 0xC182, 0x7FB6, 0xC183,
+	0x7FB7, 0xC184, 0x7FB8, 0xD9FA, 0x7FB9, 0xB8FE, 0x7FBA, 0xC185,
+	0x7FBB, 0xC186, 0x7FBC, 0xE5F1, 0x7FBD, 0xD3F0, 0x7FBE, 0xC187,
+	0x7FBF, 0xF4E0, 0x7FC0, 0xC188, 0x7FC1, 0xCECC, 0x7FC2, 0xC189,
+	0x7FC3, 0xC18A, 0x7FC4, 0xC18B, 0x7FC5, 0xB3E1, 0x7FC6, 0xC18C,
+	0x7FC7, 0xC18D, 0x7FC8, 0xC18E, 0x7FC9, 0xC18F, 0x7FCA, 0xF1B4,
+	0x7FCB, 0xC190, 0x7FCC, 0xD2EE, 0x7FCD, 0xC191, 0x7FCE, 0xF4E1,
+	0x7FCF, 0xC192, 0x7FD0, 0xC193, 0x7FD1, 0xC194, 0x7FD2, 0xC195,
+	0x7FD3, 0xC196, 0x7FD4, 0xCFE8, 0x7FD5, 0xF4E2, 0x7FD6, 0xC197,
+	0x7FD7, 0xC198, 0x7FD8, 0xC7CC, 0x7FD9, 0xC199, 0x7FDA, 0xC19A,
+	0x7FDB, 0xC19B, 0x7FDC, 0xC19C, 0x7FDD, 0xC19D, 0x7FDE, 0xC19E,
+	0x7FDF, 0xB5D4, 0x7FE0, 0xB4E4, 0x7FE1, 0xF4E4, 0x7FE2, 0xC19F,
+	0x7FE3, 0xC1A0, 0x7FE4, 0xC240, 0x7FE5, 0xF4E3, 0x7FE6, 0xF4E5,
+	0x7FE7, 0xC241, 0x7FE8, 0xC242, 0x7FE9, 0xF4E6, 0x7FEA, 0xC243,
+	0x7FEB, 0xC244, 0x7FEC, 0xC245, 0x7FED, 0xC246, 0x7FEE, 0xF4E7,
+	0x7FEF, 0xC247, 0x7FF0, 0xBAB2, 0x7FF1, 0xB0BF, 0x7FF2, 0xC248,
+	0x7FF3, 0xF4E8, 0x7FF4, 0xC249, 0x7FF5, 0xC24A, 0x7FF6, 0xC24B,
+	0x7FF7, 0xC24C, 0x7FF8, 0xC24D, 0x7FF9, 0xC24E, 0x7FFA, 0xC24F,
+	0x7FFB, 0xB7AD, 0x7FFC, 0xD2ED, 0x7FFD, 0xC250, 0x7FFE, 0xC251,
+	0x7FFF, 0xC252, 0x8000, 0xD2AB, 0x8001, 0xC0CF, 0x8002, 0xC253,
+	0x8003, 0xBFBC, 0x8004, 0xEBA3, 0x8005, 0xD5DF, 0x8006, 0xEAC8,
+	0x8007, 0xC254, 0x8008, 0xC255, 0x8009, 0xC256, 0x800A, 0xC257,
+	0x800B, 0xF1F3, 0x800C, 0xB6F8, 0x800D, 0xCBA3, 0x800E, 0xC258,
+	0x800F, 0xC259, 0x8010, 0xC4CD, 0x8011, 0xC25A, 0x8012, 0xF1E7,
+	0x8013, 0xC25B, 0x8014, 0xF1E8, 0x8015, 0xB8FB, 0x8016, 0xF1E9,
+	0x8017, 0xBAC4, 0x8018, 0xD4C5, 0x8019, 0xB0D2, 0x801A, 0xC25C,
+	0x801B, 0xC25D, 0x801C, 0xF1EA, 0x801D, 0xC25E, 0x801E, 0xC25F,
+	0x801F, 0xC260, 0x8020, 0xF1EB, 0x8021, 0xC261, 0x8022, 0xF1EC,
+	0x8023, 0xC262, 0x8024, 0xC263, 0x8025, 0xF1ED, 0x8026, 0xF1EE,
+	0x8027, 0xF1EF, 0x8028, 0xF1F1, 0x8029, 0xF1F0, 0x802A, 0xC5D5,
+	0x802B, 0xC264, 0x802C, 0xC265, 0x802D, 0xC266, 0x802E, 0xC267,
+	0x802F, 0xC268, 0x8030, 0xC269, 0x8031, 0xF1F2, 0x8032, 0xC26A,
+	0x8033, 0xB6FA, 0x8034, 0xC26B, 0x8035, 0xF1F4, 0x8036, 0xD2AE,
+	0x8037, 0xDEC7, 0x8038, 0xCBCA, 0x8039, 0xC26C, 0x803A, 0xC26D,
+	0x803B, 0xB3DC, 0x803C, 0xC26E, 0x803D, 0xB5A2, 0x803E, 0xC26F,
+	0x803F, 0xB9A2, 0x8040, 0xC270, 0x8041, 0xC271, 0x8042, 0xC4F4,
+	0x8043, 0xF1F5, 0x8044, 0xC272, 0x8045, 0xC273, 0x8046, 0xF1F6,
+	0x8047, 0xC274, 0x8048, 0xC275, 0x8049, 0xC276, 0x804A, 0xC1C4,
+	0x804B, 0xC1FB, 0x804C, 0xD6B0, 0x804D, 0xF1F7, 0x804E, 0xC277,
+	0x804F, 0xC278, 0x8050, 0xC279, 0x8051, 0xC27A, 0x8052, 0xF1F8,
+	0x8053, 0xC27B, 0x8054, 0xC1AA, 0x8055, 0xC27C, 0x8056, 0xC27D,
+	0x8057, 0xC27E, 0x8058, 0xC6B8, 0x8059, 0xC280, 0x805A, 0xBEDB,
+	0x805B, 0xC281, 0x805C, 0xC282, 0x805D, 0xC283, 0x805E, 0xC284,
+	0x805F, 0xC285, 0x8060, 0xC286, 0x8061, 0xC287, 0x8062, 0xC288,
+	0x8063, 0xC289, 0x8064, 0xC28A, 0x8065, 0xC28B, 0x8066, 0xC28C,
+	0x8067, 0xC28D, 0x8068, 0xC28E, 0x8069, 0xF1F9, 0x806A, 0xB4CF,
+	0x806B, 0xC28F, 0x806C, 0xC290, 0x806D, 0xC291, 0x806E, 0xC292,
+	0x806F, 0xC293, 0x8070, 0xC294, 0x8071, 0xF1FA, 0x8072, 0xC295,
+	0x8073, 0xC296, 0x8074, 0xC297, 0x8075, 0xC298, 0x8076, 0xC299,
+	0x8077, 0xC29A, 0x8078, 0xC29B, 0x8079, 0xC29C, 0x807A, 0xC29D,
+	0x807B, 0xC29E, 0x807C, 0xC29F, 0x807D, 0xC2A0, 0x807E, 0xC340,
+	0x807F, 0xEDB2, 0x8080, 0xEDB1, 0x8081, 0xC341, 0x8082, 0xC342,
+	0x8083, 0xCBE0, 0x8084, 0xD2DE, 0x8085, 0xC343, 0x8086, 0xCBC1,
+	0x8087, 0xD5D8, 0x8088, 0xC344, 0x8089, 0xC8E2, 0x808A, 0xC345,
+	0x808B, 0xC0DF, 0x808C, 0xBCA1, 0x808D, 0xC346, 0x808E, 0xC347,
+	0x808F, 0xC348, 0x8090, 0xC349, 0x8091, 0xC34A, 0x8092, 0xC34B,
+	0x8093, 0xEBC1, 0x8094, 0xC34C, 0x8095, 0xC34D, 0x8096, 0xD0A4,
+	0x8097, 0xC34E, 0x8098, 0xD6E2, 0x8099, 0xC34F, 0x809A, 0xB6C7,
+	0x809B, 0xB8D8, 0x809C, 0xEBC0, 0x809D, 0xB8CE, 0x809E, 0xC350,
+	0x809F, 0xEBBF, 0x80A0, 0xB3A6, 0x80A1, 0xB9C9, 0x80A2, 0xD6AB,
+	0x80A3, 0xC351, 0x80A4, 0xB7F4, 0x80A5, 0xB7CA, 0x80A6, 0xC352,
+	0x80A7, 0xC353, 0x80A8, 0xC354, 0x80A9, 0xBCE7, 0x80AA, 0xB7BE,
+	0x80AB, 0xEBC6, 0x80AC, 0xC355, 0x80AD, 0xEBC7, 0x80AE, 0xB0B9,
+	0x80AF, 0xBFCF, 0x80B0, 0xC356, 0x80B1, 0xEBC5, 0x80B2, 0xD3FD,
+	0x80B3, 0xC357, 0x80B4, 0xEBC8, 0x80B5, 0xC358, 0x80B6, 0xC359,
+	0x80B7, 0xEBC9, 0x80B8, 0xC35A, 0x80B9, 0xC35B, 0x80BA, 0xB7CE,
+	0x80BB, 0xC35C, 0x80BC, 0xEBC2, 0x80BD, 0xEBC4, 0x80BE, 0xC9F6,
+	0x80BF, 0xD6D7, 0x80C0, 0xD5CD, 0x80C1, 0xD0B2, 0x80C2, 0xEBCF,
+	0x80C3, 0xCEB8, 0x80C4, 0xEBD0, 0x80C5, 0xC35D, 0x80C6, 0xB5A8,
+	0x80C7, 0xC35E, 0x80C8, 0xC35F, 0x80C9, 0xC360, 0x80CA, 0xC361,
+	0x80CB, 0xC362, 0x80CC, 0xB1B3, 0x80CD, 0xEBD2, 0x80CE, 0xCCA5,
+	0x80CF, 0xC363, 0x80D0, 0xC364, 0x80D1, 0xC365, 0x80D2, 0xC366,
+	0x80D3, 0xC367, 0x80D4, 0xC368, 0x80D5, 0xC369, 0x80D6, 0xC5D6,
+	0x80D7, 0xEBD3, 0x80D8, 0xC36A, 0x80D9, 0xEBD1, 0x80DA, 0xC5DF,
+	0x80DB, 0xEBCE, 0x80DC, 0xCAA4, 0x80DD, 0xEBD5, 0x80DE, 0xB0FB,
+	0x80DF, 0xC36B, 0x80E0, 0xC36C, 0x80E1, 0xBAFA, 0x80E2, 0xC36D,
+	0x80E3, 0xC36E, 0x80E4, 0xD8B7, 0x80E5, 0xF1E3, 0x80E6, 0xC36F,
+	0x80E7, 0xEBCA, 0x80E8, 0xEBCB, 0x80E9, 0xEBCC, 0x80EA, 0xEBCD,
+	0x80EB, 0xEBD6, 0x80EC, 0xE6C0, 0x80ED, 0xEBD9, 0x80EE, 0xC370,
+	0x80EF, 0xBFE8, 0x80F0, 0xD2C8, 0x80F1, 0xEBD7, 0x80F2, 0xEBDC,
+	0x80F3, 0xB8EC, 0x80F4, 0xEBD8, 0x80F5, 0xC371, 0x80F6, 0xBDBA,
+	0x80F7, 0xC372, 0x80F8, 0xD0D8, 0x80F9, 0xC373, 0x80FA, 0xB0B7,
+	0x80FB, 0xC374, 0x80FC, 0xEBDD, 0x80FD, 0xC4DC, 0x80FE, 0xC375,
+	0x80FF, 0xC376, 0x8100, 0xC377, 0x8101, 0xC378, 0x8102, 0xD6AC,
+	0x8103, 0xC379, 0x8104, 0xC37A, 0x8105, 0xC37B, 0x8106, 0xB4E0,
+	0x8107, 0xC37C, 0x8108, 0xC37D, 0x8109, 0xC2F6, 0x810A, 0xBCB9,
+	0x810B, 0xC37E, 0x810C, 0xC380, 0x810D, 0xEBDA, 0x810E, 0xEBDB,
+	0x810F, 0xD4E0, 0x8110, 0xC6EA, 0x8111, 0xC4D4, 0x8112, 0xEBDF,
+	0x8113, 0xC5A7, 0x8114, 0xD9F5, 0x8115, 0xC381, 0x8116, 0xB2B1,
+	0x8117, 0xC382, 0x8118, 0xEBE4, 0x8119, 0xC383, 0x811A, 0xBDC5,
+	0x811B, 0xC384, 0x811C, 0xC385, 0x811D, 0xC386, 0x811E, 0xEBE2,
+	0x811F, 0xC387, 0x8120, 0xC388, 0x8121, 0xC389, 0x8122, 0xC38A,
+	0x8123, 0xC38B, 0x8124, 0xC38C, 0x8125, 0xC38D, 0x8126, 0xC38E,
+	0x8127, 0xC38F, 0x8128, 0xC390, 0x8129, 0xC391, 0x812A, 0xC392,
+	0x812B, 0xC393, 0x812C, 0xEBE3, 0x812D, 0xC394, 0x812E, 0xC395,
+	0x812F, 0xB8AC, 0x8130, 0xC396, 0x8131, 0xCDD1, 0x8132, 0xEBE5,
+	0x8133, 0xC397, 0x8134, 0xC398, 0x8135, 0xC399, 0x8136, 0xEBE1,
+	0x8137, 0xC39A, 0x8138, 0xC1B3, 0x8139, 0xC39B, 0x813A, 0xC39C,
+	0x813B, 0xC39D, 0x813C, 0xC39E, 0x813D, 0xC39F, 0x813E, 0xC6A2,
+	0x813F, 0xC3A0, 0x8140, 0xC440, 0x8141, 0xC441, 0x8142, 0xC442,
+	0x8143, 0xC443, 0x8144, 0xC444, 0x8145, 0xC445, 0x8146, 0xCCF3,
+	0x8147, 0xC446, 0x8148, 0xEBE6, 0x8149, 0xC447, 0x814A, 0xC0B0,
+	0x814B, 0xD2B8, 0x814C, 0xEBE7, 0x814D, 0xC448, 0x814E, 0xC449,
+	0x814F, 0xC44A, 0x8150, 0xB8AF, 0x8151, 0xB8AD, 0x8152, 0xC44B,
+	0x8153, 0xEBE8, 0x8154, 0xC7BB, 0x8155, 0xCDF3, 0x8156, 0xC44C,
+	0x8157, 0xC44D, 0x8158, 0xC44E, 0x8159, 0xEBEA, 0x815A, 0xEBEB,
+	0x815B, 0xC44F, 0x815C, 0xC450, 0x815D, 0xC451, 0x815E, 0xC452,
+	0x815F, 0xC453, 0x8160, 0xEBED, 0x8161, 0xC454, 0x8162, 0xC455,
+	0x8163, 0xC456, 0x8164, 0xC457, 0x8165, 0xD0C8, 0x8166, 0xC458,
+	0x8167, 0xEBF2, 0x8168, 0xC459, 0x8169, 0xEBEE, 0x816A, 0xC45A,
+	0x816B, 0xC45B, 0x816C, 0xC45C, 0x816D, 0xEBF1, 0x816E, 0xC8F9,
+	0x816F, 0xC45D, 0x8170, 0xD1FC, 0x8171, 0xEBEC, 0x8172, 0xC45E,
+	0x8173, 0xC45F, 0x8174, 0xEBE9, 0x8175, 0xC460, 0x8176, 0xC461,
+	0x8177, 0xC462, 0x8178, 0xC463, 0x8179, 0xB8B9, 0x817A, 0xCFD9,
+	0x817B, 0xC4E5, 0x817C, 0xEBEF, 0x817D, 0xEBF0, 0x817E, 0xCCDA,
+	0x817F, 0xCDC8, 0x8180, 0xB0F2, 0x8181, 0xC464, 0x8182, 0xEBF6,
+	0x8183, 0xC465, 0x8184, 0xC466, 0x8185, 0xC467, 0x8186, 0xC468,
+	0x8187, 0xC469, 0x8188, 0xEBF5, 0x8189, 0xC46A, 0x818A, 0xB2B2,
+	0x818B, 0xC46B, 0x818C, 0xC46C, 0x818D, 0xC46D, 0x818E, 0xC46E,
+	0x818F, 0xB8E0, 0x8190, 0xC46F, 0x8191, 0xEBF7, 0x8192, 0xC470,
+	0x8193, 0xC471, 0x8194, 0xC472, 0x8195, 0xC473, 0x8196, 0xC474,
+	0x8197, 0xC475, 0x8198, 0xB1EC, 0x8199, 0xC476, 0x819A, 0xC477,
+	0x819B, 0xCCC5, 0x819C, 0xC4A4, 0x819D, 0xCFA5, 0x819E, 0xC478,
+	0x819F, 0xC479, 0x81A0, 0xC47A, 0x81A1, 0xC47B, 0x81A2, 0xC47C,
+	0x81A3, 0xEBF9, 0x81A4, 0xC47D, 0x81A5, 0xC47E, 0x81A6, 0xECA2,
+	0x81A7, 0xC480, 0x81A8, 0xC5F2, 0x81A9, 0xC481, 0x81AA, 0xEBFA,
+	0x81AB, 0xC482, 0x81AC, 0xC483, 0x81AD, 0xC484, 0x81AE, 0xC485,
+	0x81AF, 0xC486, 0x81B0, 0xC487, 0x81B1, 0xC488, 0x81B2, 0xC489,
+	0x81B3, 0xC9C5, 0x81B4, 0xC48A, 0x81B5, 0xC48B, 0x81B6, 0xC48C,
+	0x81B7, 0xC48D, 0x81B8, 0xC48E, 0x81B9, 0xC48F, 0x81BA, 0xE2DF,
+	0x81BB, 0xEBFE, 0x81BC, 0xC490, 0x81BD, 0xC491, 0x81BE, 0xC492,
+	0x81BF, 0xC493, 0x81C0, 0xCDCE, 0x81C1, 0xECA1, 0x81C2, 0xB1DB,
+	0x81C3, 0xD3B7, 0x81C4, 0xC494, 0x81C5, 0xC495, 0x81C6, 0xD2DC,
+	0x81C7, 0xC496, 0x81C8, 0xC497, 0x81C9, 0xC498, 0x81CA, 0xEBFD,
+	0x81CB, 0xC499, 0x81CC, 0xEBFB, 0x81CD, 0xC49A, 0x81CE, 0xC49B,
+	0x81CF, 0xC49C, 0x81D0, 0xC49D, 0x81D1, 0xC49E, 0x81D2, 0xC49F,
+	0x81D3, 0xC4A0, 0x81D4, 0xC540, 0x81D5, 0xC541, 0x81D6, 0xC542,
+	0x81D7, 0xC543, 0x81D8, 0xC544, 0x81D9, 0xC545, 0x81DA, 0xC546,
+	0x81DB, 0xC547, 0x81DC, 0xC548, 0x81DD, 0xC549, 0x81DE, 0xC54A,
+	0x81DF, 0xC54B, 0x81E0, 0xC54C, 0x81E1, 0xC54D, 0x81E2, 0xC54E,
+	0x81E3, 0xB3BC, 0x81E4, 0xC54F, 0x81E5, 0xC550, 0x81E6, 0xC551,
+	0x81E7, 0xEAB0, 0x81E8, 0xC552, 0x81E9, 0xC553, 0x81EA, 0xD7D4,
+	0x81EB, 0xC554, 0x81EC, 0xF4AB, 0x81ED, 0xB3F4, 0x81EE, 0xC555,
+	0x81EF, 0xC556, 0x81F0, 0xC557, 0x81F1, 0xC558, 0x81F2, 0xC559,
+	0x81F3, 0xD6C1, 0x81F4, 0xD6C2, 0x81F5, 0xC55A, 0x81F6, 0xC55B,
+	0x81F7, 0xC55C, 0x81F8, 0xC55D, 0x81F9, 0xC55E, 0x81FA, 0xC55F,
+	0x81FB, 0xD5E9, 0x81FC, 0xBECA, 0x81FD, 0xC560, 0x81FE, 0xF4A7,
+	0x81FF, 0xC561, 0x8200, 0xD2A8, 0x8201, 0xF4A8, 0x8202, 0xF4A9,
+	0x8203, 0xC562, 0x8204, 0xF4AA, 0x8205, 0xBECB, 0x8206, 0xD3DF,
+	0x8207, 0xC563, 0x8208, 0xC564, 0x8209, 0xC565, 0x820A, 0xC566,
+	0x820B, 0xC567, 0x820C, 0xC9E0, 0x820D, 0xC9E1, 0x820E, 0xC568,
+	0x820F, 0xC569, 0x8210, 0xF3C2, 0x8211, 0xC56A, 0x8212, 0xCAE6,
+	0x8213, 0xC56B, 0x8214, 0xCCF2, 0x8215, 0xC56C, 0x8216, 0xC56D,
+	0x8217, 0xC56E, 0x8218, 0xC56F, 0x8219, 0xC570, 0x821A, 0xC571,
+	0x821B, 0xE2B6, 0x821C, 0xCBB4, 0x821D, 0xC572, 0x821E, 0xCEE8,
+	0x821F, 0xD6DB, 0x8220, 0xC573, 0x8221, 0xF4AD, 0x8222, 0xF4AE,
+	0x8223, 0xF4AF, 0x8224, 0xC574, 0x8225, 0xC575, 0x8226, 0xC576,
+	0x8227, 0xC577, 0x8228, 0xF4B2, 0x8229, 0xC578, 0x822A, 0xBABD,
+	0x822B, 0xF4B3, 0x822C, 0xB0E3, 0x822D, 0xF4B0, 0x822E, 0xC579,
+	0x822F, 0xF4B1, 0x8230, 0xBDA2, 0x8231, 0xB2D5, 0x8232, 0xC57A,
+	0x8233, 0xF4B6, 0x8234, 0xF4B7, 0x8235, 0xB6E6, 0x8236, 0xB2B0,
+	0x8237, 0xCFCF, 0x8238, 0xF4B4, 0x8239, 0xB4AC, 0x823A, 0xC57B,
+	0x823B, 0xF4B5, 0x823C, 0xC57C, 0x823D, 0xC57D, 0x823E, 0xF4B8,
+	0x823F, 0xC57E, 0x8240, 0xC580, 0x8241, 0xC581, 0x8242, 0xC582,
+	0x8243, 0xC583, 0x8244, 0xF4B9, 0x8245, 0xC584, 0x8246, 0xC585,
+	0x8247, 0xCDA7, 0x8248, 0xC586, 0x8249, 0xF4BA, 0x824A, 0xC587,
+	0x824B, 0xF4BB, 0x824C, 0xC588, 0x824D, 0xC589, 0x824E, 0xC58A,
+	0x824F, 0xF4BC, 0x8250, 0xC58B, 0x8251, 0xC58C, 0x8252, 0xC58D,
+	0x8253, 0xC58E, 0x8254, 0xC58F, 0x8255, 0xC590, 0x8256, 0xC591,
+	0x8257, 0xC592, 0x8258, 0xCBD2, 0x8259, 0xC593, 0x825A, 0xF4BD,
+	0x825B, 0xC594, 0x825C, 0xC595, 0x825D, 0xC596, 0x825E, 0xC597,
+	0x825F, 0xF4BE, 0x8260, 0xC598, 0x8261, 0xC599, 0x8262, 0xC59A,
+	0x8263, 0xC59B, 0x8264, 0xC59C, 0x8265, 0xC59D, 0x8266, 0xC59E,
+	0x8267, 0xC59F, 0x8268, 0xF4BF, 0x8269, 0xC5A0, 0x826A, 0xC640,
+	0x826B, 0xC641, 0x826C, 0xC642, 0x826D, 0xC643, 0x826E, 0xF4DE,
+	0x826F, 0xC1BC, 0x8270, 0xBCE8, 0x8271, 0xC644, 0x8272, 0xC9AB,
+	0x8273, 0xD1DE, 0x8274, 0xE5F5, 0x8275, 0xC645, 0x8276, 0xC646,
+	0x8277, 0xC647, 0x8278, 0xC648, 0x8279, 0xDCB3, 0x827A, 0xD2D5,
+	0x827B, 0xC649, 0x827C, 0xC64A, 0x827D, 0xDCB4, 0x827E, 0xB0AC,
+	0x827F, 0xDCB5, 0x8280, 0xC64B, 0x8281, 0xC64C, 0x8282, 0xBDDA,
+	0x8283, 0xC64D, 0x8284, 0xDCB9, 0x8285, 0xC64E, 0x8286, 0xC64F,
+	0x8287, 0xC650, 0x8288, 0xD8C2, 0x8289, 0xC651, 0x828A, 0xDCB7,
+	0x828B, 0xD3F3, 0x828C, 0xC652, 0x828D, 0xC9D6, 0x828E, 0xDCBA,
+	0x828F, 0xDCB6, 0x8290, 0xC653, 0x8291, 0xDCBB, 0x8292, 0xC3A2,
+	0x8293, 0xC654, 0x8294, 0xC655, 0x8295, 0xC656, 0x8296, 0xC657,
+	0x8297, 0xDCBC, 0x8298, 0xDCC5, 0x8299, 0xDCBD, 0x829A, 0xC658,
+	0x829B, 0xC659, 0x829C, 0xCEDF, 0x829D, 0xD6A5, 0x829E, 0xC65A,
+	0x829F, 0xDCCF, 0x82A0, 0xC65B, 0x82A1, 0xDCCD, 0x82A2, 0xC65C,
+	0x82A3, 0xC65D, 0x82A4, 0xDCD2, 0x82A5, 0xBDE6, 0x82A6, 0xC2AB,
+	0x82A7, 0xC65E, 0x82A8, 0xDCB8, 0x82A9, 0xDCCB, 0x82AA, 0xDCCE,
+	0x82AB, 0xDCBE, 0x82AC, 0xB7D2, 0x82AD, 0xB0C5, 0x82AE, 0xDCC7,
+	0x82AF, 0xD0BE, 0x82B0, 0xDCC1, 0x82B1, 0xBBA8, 0x82B2, 0xC65F,
+	0x82B3, 0xB7BC, 0x82B4, 0xDCCC, 0x82B5, 0xC660, 0x82B6, 0xC661,
+	0x82B7, 0xDCC6, 0x82B8, 0xDCBF, 0x82B9, 0xC7DB, 0x82BA, 0xC662,
+	0x82BB, 0xC663, 0x82BC, 0xC664, 0x82BD, 0xD1BF, 0x82BE, 0xDCC0,
+	0x82BF, 0xC665, 0x82C0, 0xC666, 0x82C1, 0xDCCA, 0x82C2, 0xC667,
+	0x82C3, 0xC668, 0x82C4, 0xDCD0, 0x82C5, 0xC669, 0x82C6, 0xC66A,
+	0x82C7, 0xCEAD, 0x82C8, 0xDCC2, 0x82C9, 0xC66B, 0x82CA, 0xDCC3,
+	0x82CB, 0xDCC8, 0x82CC, 0xDCC9, 0x82CD, 0xB2D4, 0x82CE, 0xDCD1,
+	0x82CF, 0xCBD5, 0x82D0, 0xC66C, 0x82D1, 0xD4B7, 0x82D2, 0xDCDB,
+	0x82D3, 0xDCDF, 0x82D4, 0xCCA6, 0x82D5, 0xDCE6, 0x82D6, 0xC66D,
+	0x82D7, 0xC3E7, 0x82D8, 0xDCDC, 0x82D9, 0xC66E, 0x82DA, 0xC66F,
+	0x82DB, 0xBFC1, 0x82DC, 0xDCD9, 0x82DD, 0xC670, 0x82DE, 0xB0FA,
+	0x82DF, 0xB9B6, 0x82E0, 0xDCE5, 0x82E1, 0xDCD3, 0x82E2, 0xC671,
+	0x82E3, 0xDCC4, 0x82E4, 0xDCD6, 0x82E5, 0xC8F4, 0x82E6, 0xBFE0,
+	0x82E7, 0xC672, 0x82E8, 0xC673, 0x82E9, 0xC674, 0x82EA, 0xC675,
+	0x82EB, 0xC9BB, 0x82EC, 0xC676, 0x82ED, 0xC677, 0x82EE, 0xC678,
+	0x82EF, 0xB1BD, 0x82F0, 0xC679, 0x82F1, 0xD3A2, 0x82F2, 0xC67A,
+	0x82F3, 0xC67B, 0x82F4, 0xDCDA, 0x82F5, 0xC67C, 0x82F6, 0xC67D,
+	0x82F7, 0xDCD5, 0x82F8, 0xC67E, 0x82F9, 0xC6BB, 0x82FA, 0xC680,
+	0x82FB, 0xDCDE, 0x82FC, 0xC681, 0x82FD, 0xC682, 0x82FE, 0xC683,
+	0x82FF, 0xC684, 0x8300, 0xC685, 0x8301, 0xD7C2, 0x8302, 0xC3AF,
+	0x8303, 0xB7B6, 0x8304, 0xC7D1, 0x8305, 0xC3A9, 0x8306, 0xDCE2,
+	0x8307, 0xDCD8, 0x8308, 0xDCEB, 0x8309, 0xDCD4, 0x830A, 0xC686,
+	0x830B, 0xC687, 0x830C, 0xDCDD, 0x830D, 0xC688, 0x830E, 0xBEA5,
+	0x830F, 0xDCD7, 0x8310, 0xC689, 0x8311, 0xDCE0, 0x8312, 0xC68A,
+	0x8313, 0xC68B, 0x8314, 0xDCE3, 0x8315, 0xDCE4, 0x8316, 0xC68C,
+	0x8317, 0xDCF8, 0x8318, 0xC68D, 0x8319, 0xC68E, 0x831A, 0xDCE1,
+	0x831B, 0xDDA2, 0x831C, 0xDCE7, 0x831D, 0xC68F, 0x831E, 0xC690,
+	0x831F, 0xC691, 0x8320, 0xC692, 0x8321, 0xC693, 0x8322, 0xC694,
+	0x8323, 0xC695, 0x8324, 0xC696, 0x8325, 0xC697, 0x8326, 0xC698,
+	0x8327, 0xBCEB, 0x8328, 0xB4C4, 0x8329, 0xC699, 0x832A, 0xC69A,
+	0x832B, 0xC3A3, 0x832C, 0xB2E7, 0x832D, 0xDCFA, 0x832E, 0xC69B,
+	0x832F, 0xDCF2, 0x8330, 0xC69C, 0x8331, 0xDCEF, 0x8332, 0xC69D,
+	0x8333, 0xDCFC, 0x8334, 0xDCEE, 0x8335, 0xD2F0, 0x8336, 0xB2E8,
+	0x8337, 0xC69E, 0x8338, 0xC8D7, 0x8339, 0xC8E3, 0x833A, 0xDCFB,
+	0x833B, 0xC69F, 0x833C, 0xDCED, 0x833D, 0xC6A0, 0x833E, 0xC740,
+	0x833F, 0xC741, 0x8340, 0xDCF7, 0x8341, 0xC742, 0x8342, 0xC743,
+	0x8343, 0xDCF5, 0x8344, 0xC744, 0x8345, 0xC745, 0x8346, 0xBEA3,
+	0x8347, 0xDCF4, 0x8348, 0xC746, 0x8349, 0xB2DD, 0x834A, 0xC747,
+	0x834B, 0xC748, 0x834C, 0xC749, 0x834D, 0xC74A, 0x834E, 0xC74B,
+	0x834F, 0xDCF3, 0x8350, 0xBCF6, 0x8351, 0xDCE8, 0x8352, 0xBBC4,
+	0x8353, 0xC74C, 0x8354, 0xC0F3, 0x8355, 0xC74D, 0x8356, 0xC74E,
+	0x8357, 0xC74F, 0x8358, 0xC750, 0x8359, 0xC751, 0x835A, 0xBCD4,
+	0x835B, 0xDCE9, 0x835C, 0xDCEA, 0x835D, 0xC752, 0x835E, 0xDCF1,
+	0x835F, 0xDCF6, 0x8360, 0xDCF9, 0x8361, 0xB5B4, 0x8362, 0xC753,
+	0x8363, 0xC8D9, 0x8364, 0xBBE7, 0x8365, 0xDCFE, 0x8366, 0xDCFD,
+	0x8367, 0xD3AB, 0x8368, 0xDDA1, 0x8369, 0xDDA3, 0x836A, 0xDDA5,
+	0x836B, 0xD2F1, 0x836C, 0xDDA4, 0x836D, 0xDDA6, 0x836E, 0xDDA7,
+	0x836F, 0xD2A9, 0x8370, 0xC754, 0x8371, 0xC755, 0x8372, 0xC756,
+	0x8373, 0xC757, 0x8374, 0xC758, 0x8375, 0xC759, 0x8376, 0xC75A,
+	0x8377, 0xBAC9, 0x8378, 0xDDA9, 0x8379, 0xC75B, 0x837A, 0xC75C,
+	0x837B, 0xDDB6, 0x837C, 0xDDB1, 0x837D, 0xDDB4, 0x837E, 0xC75D,
+	0x837F, 0xC75E, 0x8380, 0xC75F, 0x8381, 0xC760, 0x8382, 0xC761,
+	0x8383, 0xC762, 0x8384, 0xC763, 0x8385, 0xDDB0, 0x8386, 0xC6CE,
+	0x8387, 0xC764, 0x8388, 0xC765, 0x8389, 0xC0F2, 0x838A, 0xC766,
+	0x838B, 0xC767, 0x838C, 0xC768, 0x838D, 0xC769, 0x838E, 0xC9AF,
+	0x838F, 0xC76A, 0x8390, 0xC76B, 0x8391, 0xC76C, 0x8392, 0xDCEC,
+	0x8393, 0xDDAE, 0x8394, 0xC76D, 0x8395, 0xC76E, 0x8396, 0xC76F,
+	0x8397, 0xC770, 0x8398, 0xDDB7, 0x8399, 0xC771, 0x839A, 0xC772,
+	0x839B, 0xDCF0, 0x839C, 0xDDAF, 0x839D, 0xC773, 0x839E, 0xDDB8,
+	0x839F, 0xC774, 0x83A0, 0xDDAC, 0x83A1, 0xC775, 0x83A2, 0xC776,
+	0x83A3, 0xC777, 0x83A4, 0xC778, 0x83A5, 0xC779, 0x83A6, 0xC77A,
+	0x83A7, 0xC77B, 0x83A8, 0xDDB9, 0x83A9, 0xDDB3, 0x83AA, 0xDDAD,
+	0x83AB, 0xC4AA, 0x83AC, 0xC77C, 0x83AD, 0xC77D, 0x83AE, 0xC77E,
+	0x83AF, 0xC780, 0x83B0, 0xDDA8, 0x83B1, 0xC0B3, 0x83B2, 0xC1AB,
+	0x83B3, 0xDDAA, 0x83B4, 0xDDAB, 0x83B5, 0xC781, 0x83B6, 0xDDB2,
+	0x83B7, 0xBBF1, 0x83B8, 0xDDB5, 0x83B9, 0xD3A8, 0x83BA, 0xDDBA,
+	0x83BB, 0xC782, 0x83BC, 0xDDBB, 0x83BD, 0xC3A7, 0x83BE, 0xC783,
+	0x83BF, 0xC784, 0x83C0, 0xDDD2, 0x83C1, 0xDDBC, 0x83C2, 0xC785,
+	0x83C3, 0xC786, 0x83C4, 0xC787, 0x83C5, 0xDDD1, 0x83C6, 0xC788,
+	0x83C7, 0xB9BD, 0x83C8, 0xC789, 0x83C9, 0xC78A, 0x83CA, 0xBED5,
+	0x83CB, 0xC78B, 0x83CC, 0xBEFA, 0x83CD, 0xC78C, 0x83CE, 0xC78D,
+	0x83CF, 0xBACA, 0x83D0, 0xC78E, 0x83D1, 0xC78F, 0x83D2, 0xC790,
+	0x83D3, 0xC791, 0x83D4, 0xDDCA, 0x83D5, 0xC792, 0x83D6, 0xDDC5,
+	0x83D7, 0xC793, 0x83D8, 0xDDBF, 0x83D9, 0xC794, 0x83DA, 0xC795,
+	0x83DB, 0xC796, 0x83DC, 0xB2CB, 0x83DD, 0xDDC3, 0x83DE, 0xC797,
+	0x83DF, 0xDDCB, 0x83E0, 0xB2A4, 0x83E1, 0xDDD5, 0x83E2, 0xC798,
+	0x83E3, 0xC799, 0x83E4, 0xC79A, 0x83E5, 0xDDBE, 0x83E6, 0xC79B,
+	0x83E7, 0xC79C, 0x83E8, 0xC79D, 0x83E9, 0xC6D0, 0x83EA, 0xDDD0,
+	0x83EB, 0xC79E, 0x83EC, 0xC79F, 0x83ED, 0xC7A0, 0x83EE, 0xC840,
+	0x83EF, 0xC841, 0x83F0, 0xDDD4, 0x83F1, 0xC1E2, 0x83F2, 0xB7C6,
+	0x83F3, 0xC842, 0x83F4, 0xC843, 0x83F5, 0xC844, 0x83F6, 0xC845,
+	0x83F7, 0xC846, 0x83F8, 0xDDCE, 0x83F9, 0xDDCF, 0x83FA, 0xC847,
+	0x83FB, 0xC848, 0x83FC, 0xC849, 0x83FD, 0xDDC4, 0x83FE, 0xC84A,
+	0x83FF, 0xC84B, 0x8400, 0xC84C, 0x8401, 0xDDBD, 0x8402, 0xC84D,
+	0x8403, 0xDDCD, 0x8404, 0xCCD1, 0x8405, 0xC84E, 0x8406, 0xDDC9,
+	0x8407, 0xC84F, 0x8408, 0xC850, 0x8409, 0xC851, 0x840A, 0xC852,
+	0x840B, 0xDDC2, 0x840C, 0xC3C8, 0x840D, 0xC6BC, 0x840E, 0xCEAE,
+	0x840F, 0xDDCC, 0x8410, 0xC853, 0x8411, 0xDDC8, 0x8412, 0xC854,
+	0x8413, 0xC855, 0x8414, 0xC856, 0x8415, 0xC857, 0x8416, 0xC858,
+	0x8417, 0xC859, 0x8418, 0xDDC1, 0x8419, 0xC85A, 0x841A, 0xC85B,
+	0x841B, 0xC85C, 0x841C, 0xDDC6, 0x841D, 0xC2DC, 0x841E, 0xC85D,
+	0x841F, 0xC85E, 0x8420, 0xC85F, 0x8421, 0xC860, 0x8422, 0xC861,
+	0x8423, 0xC862, 0x8424, 0xD3A9, 0x8425, 0xD3AA, 0x8426, 0xDDD3,
+	0x8427, 0xCFF4, 0x8428, 0xC8F8, 0x8429, 0xC863, 0x842A, 0xC864,
+	0x842B, 0xC865, 0x842C, 0xC866, 0x842D, 0xC867, 0x842E, 0xC868,
+	0x842F, 0xC869, 0x8430, 0xC86A, 0x8431, 0xDDE6, 0x8432, 0xC86B,
+	0x8433, 0xC86C, 0x8434, 0xC86D, 0x8435, 0xC86E, 0x8436, 0xC86F,
+	0x8437, 0xC870, 0x8438, 0xDDC7, 0x8439, 0xC871, 0x843A, 0xC872,
+	0x843B, 0xC873, 0x843C, 0xDDE0, 0x843D, 0xC2E4, 0x843E, 0xC874,
+	0x843F, 0xC875, 0x8440, 0xC876, 0x8441, 0xC877, 0x8442, 0xC878,
+	0x8443, 0xC879, 0x8444, 0xC87A, 0x8445, 0xC87B, 0x8446, 0xDDE1,
+	0x8447, 0xC87C, 0x8448, 0xC87D, 0x8449, 0xC87E, 0x844A, 0xC880,
+	0x844B, 0xC881, 0x844C, 0xC882, 0x844D, 0xC883, 0x844E, 0xC884,
+	0x844F, 0xC885, 0x8450, 0xC886, 0x8451, 0xDDD7, 0x8452, 0xC887,
+	0x8453, 0xC888, 0x8454, 0xC889, 0x8455, 0xC88A, 0x8456, 0xC88B,
+	0x8457, 0xD6F8, 0x8458, 0xC88C, 0x8459, 0xDDD9, 0x845A, 0xDDD8,
+	0x845B, 0xB8F0, 0x845C, 0xDDD6, 0x845D, 0xC88D, 0x845E, 0xC88E,
+	0x845F, 0xC88F, 0x8460, 0xC890, 0x8461, 0xC6CF, 0x8462, 0xC891,
+	0x8463, 0xB6AD, 0x8464, 0xC892, 0x8465, 0xC893, 0x8466, 0xC894,
+	0x8467, 0xC895, 0x8468, 0xC896, 0x8469, 0xDDE2, 0x846A, 0xC897,
+	0x846B, 0xBAF9, 0x846C, 0xD4E1, 0x846D, 0xDDE7, 0x846E, 0xC898,
+	0x846F, 0xC899, 0x8470, 0xC89A, 0x8471, 0xB4D0, 0x8472, 0xC89B,
+	0x8473, 0xDDDA, 0x8474, 0xC89C, 0x8475, 0xBFFB, 0x8476, 0xDDE3,
+	0x8477, 0xC89D, 0x8478, 0xDDDF, 0x8479, 0xC89E, 0x847A, 0xDDDD,
+	0x847B, 0xC89F, 0x847C, 0xC8A0, 0x847D, 0xC940, 0x847E, 0xC941,
+	0x847F, 0xC942, 0x8480, 0xC943, 0x8481, 0xC944, 0x8482, 0xB5D9,
+	0x8483, 0xC945, 0x8484, 0xC946, 0x8485, 0xC947, 0x8486, 0xC948,
+	0x8487, 0xDDDB, 0x8488, 0xDDDC, 0x8489, 0xDDDE, 0x848A, 0xC949,
+	0x848B, 0xBDAF, 0x848C, 0xDDE4, 0x848D, 0xC94A, 0x848E, 0xDDE5,
+	0x848F, 0xC94B, 0x8490, 0xC94C, 0x8491, 0xC94D, 0x8492, 0xC94E,
+	0x8493, 0xC94F, 0x8494, 0xC950, 0x8495, 0xC951, 0x8496, 0xC952,
+	0x8497, 0xDDF5, 0x8498, 0xC953, 0x8499, 0xC3C9, 0x849A, 0xC954,
+	0x849B, 0xC955, 0x849C, 0xCBE2, 0x849D, 0xC956, 0x849E, 0xC957,
+	0x849F, 0xC958, 0x84A0, 0xC959, 0x84A1, 0xDDF2, 0x84A2, 0xC95A,
+	0x84A3, 0xC95B, 0x84A4, 0xC95C, 0x84A5, 0xC95D, 0x84A6, 0xC95E,
+	0x84A7, 0xC95F, 0x84A8, 0xC960, 0x84A9, 0xC961, 0x84AA, 0xC962,
+	0x84AB, 0xC963, 0x84AC, 0xC964, 0x84AD, 0xC965, 0x84AE, 0xC966,
+	0x84AF, 0xD8E1, 0x84B0, 0xC967, 0x84B1, 0xC968, 0x84B2, 0xC6D1,
+	0x84B3, 0xC969, 0x84B4, 0xDDF4, 0x84B5, 0xC96A, 0x84B6, 0xC96B,
+	0x84B7, 0xC96C, 0x84B8, 0xD5F4, 0x84B9, 0xDDF3, 0x84BA, 0xDDF0,
+	0x84BB, 0xC96D, 0x84BC, 0xC96E, 0x84BD, 0xDDEC, 0x84BE, 0xC96F,
+	0x84BF, 0xDDEF, 0x84C0, 0xC970, 0x84C1, 0xDDE8, 0x84C2, 0xC971,
+	0x84C3, 0xC972, 0x84C4, 0xD0EE, 0x84C5, 0xC973, 0x84C6, 0xC974,
+	0x84C7, 0xC975, 0x84C8, 0xC976, 0x84C9, 0xC8D8, 0x84CA, 0xDDEE,
+	0x84CB, 0xC977, 0x84CC, 0xC978, 0x84CD, 0xDDE9, 0x84CE, 0xC979,
+	0x84CF, 0xC97A, 0x84D0, 0xDDEA, 0x84D1, 0xCBF2, 0x84D2, 0xC97B,
+	0x84D3, 0xDDED, 0x84D4, 0xC97C, 0x84D5, 0xC97D, 0x84D6, 0xB1CD,
+	0x84D7, 0xC97E, 0x84D8, 0xC980, 0x84D9, 0xC981, 0x84DA, 0xC982,
+	0x84DB, 0xC983, 0x84DC, 0xC984, 0x84DD, 0xC0B6, 0x84DE, 0xC985,
+	0x84DF, 0xBCBB, 0x84E0, 0xDDF1, 0x84E1, 0xC986, 0x84E2, 0xC987,
+	0x84E3, 0xDDF7, 0x84E4, 0xC988, 0x84E5, 0xDDF6, 0x84E6, 0xDDEB,
+	0x84E7, 0xC989, 0x84E8, 0xC98A, 0x84E9, 0xC98B, 0x84EA, 0xC98C,
+	0x84EB, 0xC98D, 0x84EC, 0xC5EE, 0x84ED, 0xC98E, 0x84EE, 0xC98F,
+	0x84EF, 0xC990, 0x84F0, 0xDDFB, 0x84F1, 0xC991, 0x84F2, 0xC992,
+	0x84F3, 0xC993, 0x84F4, 0xC994, 0x84F5, 0xC995, 0x84F6, 0xC996,
+	0x84F7, 0xC997, 0x84F8, 0xC998, 0x84F9, 0xC999, 0x84FA, 0xC99A,
+	0x84FB, 0xC99B, 0x84FC, 0xDEA4, 0x84FD, 0xC99C, 0x84FE, 0xC99D,
+	0x84FF, 0xDEA3, 0x8500, 0xC99E, 0x8501, 0xC99F, 0x8502, 0xC9A0,
+	0x8503, 0xCA40, 0x8504, 0xCA41, 0x8505, 0xCA42, 0x8506, 0xCA43,
+	0x8507, 0xCA44, 0x8508, 0xCA45, 0x8509, 0xCA46, 0x850A, 0xCA47,
+	0x850B, 0xCA48, 0x850C, 0xDDF8, 0x850D, 0xCA49, 0x850E, 0xCA4A,
+	0x850F, 0xCA4B, 0x8510, 0xCA4C, 0x8511, 0xC3EF, 0x8512, 0xCA4D,
+	0x8513, 0xC2FB, 0x8514, 0xCA4E, 0x8515, 0xCA4F, 0x8516, 0xCA50,
+	0x8517, 0xD5E1, 0x8518, 0xCA51, 0x8519, 0xCA52, 0x851A, 0xCEB5,
+	0x851B, 0xCA53, 0x851C, 0xCA54, 0x851D, 0xCA55, 0x851E, 0xCA56,
+	0x851F, 0xDDFD, 0x8520, 0xCA57, 0x8521, 0xB2CC, 0x8522, 0xCA58,
+	0x8523, 0xCA59, 0x8524, 0xCA5A, 0x8525, 0xCA5B, 0x8526, 0xCA5C,
+	0x8527, 0xCA5D, 0x8528, 0xCA5E, 0x8529, 0xCA5F, 0x852A, 0xCA60,
+	0x852B, 0xC4E8, 0x852C, 0xCADF, 0x852D, 0xCA61, 0x852E, 0xCA62,
+	0x852F, 0xCA63, 0x8530, 0xCA64, 0x8531, 0xCA65, 0x8532, 0xCA66,
+	0x8533, 0xCA67, 0x8534, 0xCA68, 0x8535, 0xCA69, 0x8536, 0xCA6A,
+	0x8537, 0xC7BE, 0x8538, 0xDDFA, 0x8539, 0xDDFC, 0x853A, 0xDDFE,
+	0x853B, 0xDEA2, 0x853C, 0xB0AA, 0x853D, 0xB1CE, 0x853E, 0xCA6B,
+	0x853F, 0xCA6C, 0x8540, 0xCA6D, 0x8541, 0xCA6E, 0x8542, 0xCA6F,
+	0x8543, 0xDEAC, 0x8544, 0xCA70, 0x8545, 0xCA71, 0x8546, 0xCA72,
+	0x8547, 0xCA73, 0x8548, 0xDEA6, 0x8549, 0xBDB6, 0x854A, 0xC8EF,
+	0x854B, 0xCA74, 0x854C, 0xCA75, 0x854D, 0xCA76, 0x854E, 0xCA77,
+	0x854F, 0xCA78, 0x8550, 0xCA79, 0x8551, 0xCA7A, 0x8552, 0xCA7B,
+	0x8553, 0xCA7C, 0x8554, 0xCA7D, 0x8555, 0xCA7E, 0x8556, 0xDEA1,
+	0x8557, 0xCA80, 0x8558, 0xCA81, 0x8559, 0xDEA5, 0x855A, 0xCA82,
+	0x855B, 0xCA83, 0x855C, 0xCA84, 0x855D, 0xCA85, 0x855E, 0xDEA9,
+	0x855F, 0xCA86, 0x8560, 0xCA87, 0x8561, 0xCA88, 0x8562, 0xCA89,
+	0x8563, 0xCA8A, 0x8564, 0xDEA8, 0x8565, 0xCA8B, 0x8566, 0xCA8C,
+	0x8567, 0xCA8D, 0x8568, 0xDEA7, 0x8569, 0xCA8E, 0x856A, 0xCA8F,
+	0x856B, 0xCA90, 0x856C, 0xCA91, 0x856D, 0xCA92, 0x856E, 0xCA93,
+	0x856F, 0xCA94, 0x8570, 0xCA95, 0x8571, 0xCA96, 0x8572, 0xDEAD,
+	0x8573, 0xCA97, 0x8574, 0xD4CC, 0x8575, 0xCA98, 0x8576, 0xCA99,
+	0x8577, 0xCA9A, 0x8578, 0xCA9B, 0x8579, 0xDEB3, 0x857A, 0xDEAA,
+	0x857B, 0xDEAE, 0x857C, 0xCA9C, 0x857D, 0xCA9D, 0x857E, 0xC0D9,
+	0x857F, 0xCA9E, 0x8580, 0xCA9F, 0x8581, 0xCAA0, 0x8582, 0xCB40,
+	0x8583, 0xCB41, 0x8584, 0xB1A1, 0x8585, 0xDEB6, 0x8586, 0xCB42,
+	0x8587, 0xDEB1, 0x8588, 0xCB43, 0x8589, 0xCB44, 0x858A, 0xCB45,
+	0x858B, 0xCB46, 0x858C, 0xCB47, 0x858D, 0xCB48, 0x858E, 0xCB49,
+	0x858F, 0xDEB2, 0x8590, 0xCB4A, 0x8591, 0xCB4B, 0x8592, 0xCB4C,
+	0x8593, 0xCB4D, 0x8594, 0xCB4E, 0x8595, 0xCB4F, 0x8596, 0xCB50,
+	0x8597, 0xCB51, 0x8598, 0xCB52, 0x8599, 0xCB53, 0x859A, 0xCB54,
+	0x859B, 0xD1A6, 0x859C, 0xDEB5, 0x859D, 0xCB55, 0x859E, 0xCB56,
+	0x859F, 0xCB57, 0x85A0, 0xCB58, 0x85A1, 0xCB59, 0x85A2, 0xCB5A,
+	0x85A3, 0xCB5B, 0x85A4, 0xDEAF, 0x85A5, 0xCB5C, 0x85A6, 0xCB5D,
+	0x85A7, 0xCB5E, 0x85A8, 0xDEB0, 0x85A9, 0xCB5F, 0x85AA, 0xD0BD,
+	0x85AB, 0xCB60, 0x85AC, 0xCB61, 0x85AD, 0xCB62, 0x85AE, 0xDEB4,
+	0x85AF, 0xCAED, 0x85B0, 0xDEB9, 0x85B1, 0xCB63, 0x85B2, 0xCB64,
+	0x85B3, 0xCB65, 0x85B4, 0xCB66, 0x85B5, 0xCB67, 0x85B6, 0xCB68,
+	0x85B7, 0xDEB8, 0x85B8, 0xCB69, 0x85B9, 0xDEB7, 0x85BA, 0xCB6A,
+	0x85BB, 0xCB6B, 0x85BC, 0xCB6C, 0x85BD, 0xCB6D, 0x85BE, 0xCB6E,
+	0x85BF, 0xCB6F, 0x85C0, 0xCB70, 0x85C1, 0xDEBB, 0x85C2, 0xCB71,
+	0x85C3, 0xCB72, 0x85C4, 0xCB73, 0x85C5, 0xCB74, 0x85C6, 0xCB75,
+	0x85C7, 0xCB76, 0x85C8, 0xCB77, 0x85C9, 0xBDE5, 0x85CA, 0xCB78,
+	0x85CB, 0xCB79, 0x85CC, 0xCB7A, 0x85CD, 0xCB7B, 0x85CE, 0xCB7C,
+	0x85CF, 0xB2D8, 0x85D0, 0xC3EA, 0x85D1, 0xCB7D, 0x85D2, 0xCB7E,
+	0x85D3, 0xDEBA, 0x85D4, 0xCB80, 0x85D5, 0xC5BA, 0x85D6, 0xCB81,
+	0x85D7, 0xCB82, 0x85D8, 0xCB83, 0x85D9, 0xCB84, 0x85DA, 0xCB85,
+	0x85DB, 0xCB86, 0x85DC, 0xDEBC, 0x85DD, 0xCB87, 0x85DE, 0xCB88,
+	0x85DF, 0xCB89, 0x85E0, 0xCB8A, 0x85E1, 0xCB8B, 0x85E2, 0xCB8C,
+	0x85E3, 0xCB8D, 0x85E4, 0xCCD9, 0x85E5, 0xCB8E, 0x85E6, 0xCB8F,
+	0x85E7, 0xCB90, 0x85E8, 0xCB91, 0x85E9, 0xB7AA, 0x85EA, 0xCB92,
+	0x85EB, 0xCB93, 0x85EC, 0xCB94, 0x85ED, 0xCB95, 0x85EE, 0xCB96,
+	0x85EF, 0xCB97, 0x85F0, 0xCB98, 0x85F1, 0xCB99, 0x85F2, 0xCB9A,
+	0x85F3, 0xCB9B, 0x85F4, 0xCB9C, 0x85F5, 0xCB9D, 0x85F6, 0xCB9E,
+	0x85F7, 0xCB9F, 0x85F8, 0xCBA0, 0x85F9, 0xCC40, 0x85FA, 0xCC41,
+	0x85FB, 0xD4E5, 0x85FC, 0xCC42, 0x85FD, 0xCC43, 0x85FE, 0xCC44,
+	0x85FF, 0xDEBD, 0x8600, 0xCC45, 0x8601, 0xCC46, 0x8602, 0xCC47,
+	0x8603, 0xCC48, 0x8604, 0xCC49, 0x8605, 0xDEBF, 0x8606, 0xCC4A,
+	0x8607, 0xCC4B, 0x8608, 0xCC4C, 0x8609, 0xCC4D, 0x860A, 0xCC4E,
+	0x860B, 0xCC4F, 0x860C, 0xCC50, 0x860D, 0xCC51, 0x860E, 0xCC52,
+	0x860F, 0xCC53, 0x8610, 0xCC54, 0x8611, 0xC4A2, 0x8612, 0xCC55,
+	0x8613, 0xCC56, 0x8614, 0xCC57, 0x8615, 0xCC58, 0x8616, 0xDEC1,
+	0x8617, 0xCC59, 0x8618, 0xCC5A, 0x8619, 0xCC5B, 0x861A, 0xCC5C,
+	0x861B, 0xCC5D, 0x861C, 0xCC5E, 0x861D, 0xCC5F, 0x861E, 0xCC60,
+	0x861F, 0xCC61, 0x8620, 0xCC62, 0x8621, 0xCC63, 0x8622, 0xCC64,
+	0x8623, 0xCC65, 0x8624, 0xCC66, 0x8625, 0xCC67, 0x8626, 0xCC68,
+	0x8627, 0xDEBE, 0x8628, 0xCC69, 0x8629, 0xDEC0, 0x862A, 0xCC6A,
+	0x862B, 0xCC6B, 0x862C, 0xCC6C, 0x862D, 0xCC6D, 0x862E, 0xCC6E,
+	0x862F, 0xCC6F, 0x8630, 0xCC70, 0x8631, 0xCC71, 0x8632, 0xCC72,
+	0x8633, 0xCC73, 0x8634, 0xCC74, 0x8635, 0xCC75, 0x8636, 0xCC76,
+	0x8637, 0xCC77, 0x8638, 0xD5BA, 0x8639, 0xCC78, 0x863A, 0xCC79,
+	0x863B, 0xCC7A, 0x863C, 0xDEC2, 0x863D, 0xCC7B, 0x863E, 0xCC7C,
+	0x863F, 0xCC7D, 0x8640, 0xCC7E, 0x8641, 0xCC80, 0x8642, 0xCC81,
+	0x8643, 0xCC82, 0x8644, 0xCC83, 0x8645, 0xCC84, 0x8646, 0xCC85,
+	0x8647, 0xCC86, 0x8648, 0xCC87, 0x8649, 0xCC88, 0x864A, 0xCC89,
+	0x864B, 0xCC8A, 0x864C, 0xCC8B, 0x864D, 0xF2AE, 0x864E, 0xBBA2,
+	0x864F, 0xC2B2, 0x8650, 0xC5B0, 0x8651, 0xC2C7, 0x8652, 0xCC8C,
+	0x8653, 0xCC8D, 0x8654, 0xF2AF, 0x8655, 0xCC8E, 0x8656, 0xCC8F,
+	0x8657, 0xCC90, 0x8658, 0xCC91, 0x8659, 0xCC92, 0x865A, 0xD0E9,
+	0x865B, 0xCC93, 0x865C, 0xCC94, 0x865D, 0xCC95, 0x865E, 0xD3DD,
+	0x865F, 0xCC96, 0x8660, 0xCC97, 0x8661, 0xCC98, 0x8662, 0xEBBD,
+	0x8663, 0xCC99, 0x8664, 0xCC9A, 0x8665, 0xCC9B, 0x8666, 0xCC9C,
+	0x8667, 0xCC9D, 0x8668, 0xCC9E, 0x8669, 0xCC9F, 0x866A, 0xCCA0,
+	0x866B, 0xB3E6, 0x866C, 0xF2B0, 0x866D, 0xCD40, 0x866E, 0xF2B1,
+	0x866F, 0xCD41, 0x8670, 0xCD42, 0x8671, 0xCAAD, 0x8672, 0xCD43,
+	0x8673, 0xCD44, 0x8674, 0xCD45, 0x8675, 0xCD46, 0x8676, 0xCD47,
+	0x8677, 0xCD48, 0x8678, 0xCD49, 0x8679, 0xBAE7, 0x867A, 0xF2B3,
+	0x867B, 0xF2B5, 0x867C, 0xF2B4, 0x867D, 0xCBE4, 0x867E, 0xCFBA,
+	0x867F, 0xF2B2, 0x8680, 0xCAB4, 0x8681, 0xD2CF, 0x8682, 0xC2EC,
+	0x8683, 0xCD4A, 0x8684, 0xCD4B, 0x8685, 0xCD4C, 0x8686, 0xCD4D,
+	0x8687, 0xCD4E, 0x8688, 0xCD4F, 0x8689, 0xCD50, 0x868A, 0xCEC3,
+	0x868B, 0xF2B8, 0x868C, 0xB0F6, 0x868D, 0xF2B7, 0x868E, 0xCD51,
+	0x868F, 0xCD52, 0x8690, 0xCD53, 0x8691, 0xCD54, 0x8692, 0xCD55,
+	0x8693, 0xF2BE, 0x8694, 0xCD56, 0x8695, 0xB2CF, 0x8696, 0xCD57,
+	0x8697, 0xCD58, 0x8698, 0xCD59, 0x8699, 0xCD5A, 0x869A, 0xCD5B,
+	0x869B, 0xCD5C, 0x869C, 0xD1C1, 0x869D, 0xF2BA, 0x869E, 0xCD5D,
+	0x869F, 0xCD5E, 0x86A0, 0xCD5F, 0x86A1, 0xCD60, 0x86A2, 0xCD61,
+	0x86A3, 0xF2BC, 0x86A4, 0xD4E9, 0x86A5, 0xCD62, 0x86A6, 0xCD63,
+	0x86A7, 0xF2BB, 0x86A8, 0xF2B6, 0x86A9, 0xF2BF, 0x86AA, 0xF2BD,
+	0x86AB, 0xCD64, 0x86AC, 0xF2B9, 0x86AD, 0xCD65, 0x86AE, 0xCD66,
+	0x86AF, 0xF2C7, 0x86B0, 0xF2C4, 0x86B1, 0xF2C6, 0x86B2, 0xCD67,
+	0x86B3, 0xCD68, 0x86B4, 0xF2CA, 0x86B5, 0xF2C2, 0x86B6, 0xF2C0,
+	0x86B7, 0xCD69, 0x86B8, 0xCD6A, 0x86B9, 0xCD6B, 0x86BA, 0xF2C5,
+	0x86BB, 0xCD6C, 0x86BC, 0xCD6D, 0x86BD, 0xCD6E, 0x86BE, 0xCD6F,
+	0x86BF, 0xCD70, 0x86C0, 0xD6FB, 0x86C1, 0xCD71, 0x86C2, 0xCD72,
+	0x86C3, 0xCD73, 0x86C4, 0xF2C1, 0x86C5, 0xCD74, 0x86C6, 0xC7F9,
+	0x86C7, 0xC9DF, 0x86C8, 0xCD75, 0x86C9, 0xF2C8, 0x86CA, 0xB9C6,
+	0x86CB, 0xB5B0, 0x86CC, 0xCD76, 0x86CD, 0xCD77, 0x86CE, 0xF2C3,
+	0x86CF, 0xF2C9, 0x86D0, 0xF2D0, 0x86D1, 0xF2D6, 0x86D2, 0xCD78,
+	0x86D3, 0xCD79, 0x86D4, 0xBBD7, 0x86D5, 0xCD7A, 0x86D6, 0xCD7B,
+	0x86D7, 0xCD7C, 0x86D8, 0xF2D5, 0x86D9, 0xCDDC, 0x86DA, 0xCD7D,
+	0x86DB, 0xD6EB, 0x86DC, 0xCD7E, 0x86DD, 0xCD80, 0x86DE, 0xF2D2,
+	0x86DF, 0xF2D4, 0x86E0, 0xCD81, 0x86E1, 0xCD82, 0x86E2, 0xCD83,
+	0x86E3, 0xCD84, 0x86E4, 0xB8F2, 0x86E5, 0xCD85, 0x86E6, 0xCD86,
+	0x86E7, 0xCD87, 0x86E8, 0xCD88, 0x86E9, 0xF2CB, 0x86EA, 0xCD89,
+	0x86EB, 0xCD8A, 0x86EC, 0xCD8B, 0x86ED, 0xF2CE, 0x86EE, 0xC2F9,
+	0x86EF, 0xCD8C, 0x86F0, 0xD5DD, 0x86F1, 0xF2CC, 0x86F2, 0xF2CD,
+	0x86F3, 0xF2CF, 0x86F4, 0xF2D3, 0x86F5, 0xCD8D, 0x86F6, 0xCD8E,
+	0x86F7, 0xCD8F, 0x86F8, 0xF2D9, 0x86F9, 0xD3BC, 0x86FA, 0xCD90,
+	0x86FB, 0xCD91, 0x86FC, 0xCD92, 0x86FD, 0xCD93, 0x86FE, 0xB6EA,
+	0x86FF, 0xCD94, 0x8700, 0xCAF1, 0x8701, 0xCD95, 0x8702, 0xB7E4,
+	0x8703, 0xF2D7, 0x8704, 0xCD96, 0x8705, 0xCD97, 0x8706, 0xCD98,
+	0x8707, 0xF2D8, 0x8708, 0xF2DA, 0x8709, 0xF2DD, 0x870A, 0xF2DB,
+	0x870B, 0xCD99, 0x870C, 0xCD9A, 0x870D, 0xF2DC, 0x870E, 0xCD9B,
+	0x870F, 0xCD9C, 0x8710, 0xCD9D, 0x8711, 0xCD9E, 0x8712, 0xD1D1,
+	0x8713, 0xF2D1, 0x8714, 0xCD9F, 0x8715, 0xCDC9, 0x8716, 0xCDA0,
+	0x8717, 0xCECF, 0x8718, 0xD6A9, 0x8719, 0xCE40, 0x871A, 0xF2E3,
+	0x871B, 0xCE41, 0x871C, 0xC3DB, 0x871D, 0xCE42, 0x871E, 0xF2E0,
+	0x871F, 0xCE43, 0x8720, 0xCE44, 0x8721, 0xC0AF, 0x8722, 0xF2EC,
+	0x8723, 0xF2DE, 0x8724, 0xCE45, 0x8725, 0xF2E1, 0x8726, 0xCE46,
+	0x8727, 0xCE47, 0x8728, 0xCE48, 0x8729, 0xF2E8, 0x872A, 0xCE49,
+	0x872B, 0xCE4A, 0x872C, 0xCE4B, 0x872D, 0xCE4C, 0x872E, 0xF2E2,
+	0x872F, 0xCE4D, 0x8730, 0xCE4E, 0x8731, 0xF2E7, 0x8732, 0xCE4F,
+	0x8733, 0xCE50, 0x8734, 0xF2E6, 0x8735, 0xCE51, 0x8736, 0xCE52,
+	0x8737, 0xF2E9, 0x8738, 0xCE53, 0x8739, 0xCE54, 0x873A, 0xCE55,
+	0x873B, 0xF2DF, 0x873C, 0xCE56, 0x873D, 0xCE57, 0x873E, 0xF2E4,
+	0x873F, 0xF2EA, 0x8740, 0xCE58, 0x8741, 0xCE59, 0x8742, 0xCE5A,
+	0x8743, 0xCE5B, 0x8744, 0xCE5C, 0x8745, 0xCE5D, 0x8746, 0xCE5E,
+	0x8747, 0xD3AC, 0x8748, 0xF2E5, 0x8749, 0xB2F5, 0x874A, 0xCE5F,
+	0x874B, 0xCE60, 0x874C, 0xF2F2, 0x874D, 0xCE61, 0x874E, 0xD0AB,
+	0x874F, 0xCE62, 0x8750, 0xCE63, 0x8751, 0xCE64, 0x8752, 0xCE65,
+	0x8753, 0xF2F5, 0x8754, 0xCE66, 0x8755, 0xCE67, 0x8756, 0xCE68,
+	0x8757, 0xBBC8, 0x8758, 0xCE69, 0x8759, 0xF2F9, 0x875A, 0xCE6A,
+	0x875B, 0xCE6B, 0x875C, 0xCE6C, 0x875D, 0xCE6D, 0x875E, 0xCE6E,
+	0x875F, 0xCE6F, 0x8760, 0xF2F0, 0x8761, 0xCE70, 0x8762, 0xCE71,
+	0x8763, 0xF2F6, 0x8764, 0xF2F8, 0x8765, 0xF2FA, 0x8766, 0xCE72,
+	0x8767, 0xCE73, 0x8768, 0xCE74, 0x8769, 0xCE75, 0x876A, 0xCE76,
+	0x876B, 0xCE77, 0x876C, 0xCE78, 0x876D, 0xCE79, 0x876E, 0xF2F3,
+	0x876F, 0xCE7A, 0x8770, 0xF2F1, 0x8771, 0xCE7B, 0x8772, 0xCE7C,
+	0x8773, 0xCE7D, 0x8774, 0xBAFB, 0x8775, 0xCE7E, 0x8776, 0xB5FB,
+	0x8777, 0xCE80, 0x8778, 0xCE81, 0x8779, 0xCE82, 0x877A, 0xCE83,
+	0x877B, 0xF2EF, 0x877C, 0xF2F7, 0x877D, 0xF2ED, 0x877E, 0xF2EE,
+	0x877F, 0xCE84, 0x8780, 0xCE85, 0x8781, 0xCE86, 0x8782, 0xF2EB,
+	0x8783, 0xF3A6, 0x8784, 0xCE87, 0x8785, 0xF3A3, 0x8786, 0xCE88,
+	0x8787, 0xCE89, 0x8788, 0xF3A2, 0x8789, 0xCE8A, 0x878A, 0xCE8B,
+	0x878B, 0xF2F4, 0x878C, 0xCE8C, 0x878D, 0xC8DA, 0x878E, 0xCE8D,
+	0x878F, 0xCE8E, 0x8790, 0xCE8F, 0x8791, 0xCE90, 0x8792, 0xCE91,
+	0x8793, 0xF2FB, 0x8794, 0xCE92, 0x8795, 0xCE93, 0x8796, 0xCE94,
+	0x8797, 0xF3A5, 0x8798, 0xCE95, 0x8799, 0xCE96, 0x879A, 0xCE97,
+	0x879B, 0xCE98, 0x879C, 0xCE99, 0x879D, 0xCE9A, 0x879E, 0xCE9B,
+	0x879F, 0xC3F8, 0x87A0, 0xCE9C, 0x87A1, 0xCE9D, 0x87A2, 0xCE9E,
+	0x87A3, 0xCE9F, 0x87A4, 0xCEA0, 0x87A5, 0xCF40, 0x87A6, 0xCF41,
+	0x87A7, 0xCF42, 0x87A8, 0xF2FD, 0x87A9, 0xCF43, 0x87AA, 0xCF44,
+	0x87AB, 0xF3A7, 0x87AC, 0xF3A9, 0x87AD, 0xF3A4, 0x87AE, 0xCF45,
+	0x87AF, 0xF2FC, 0x87B0, 0xCF46, 0x87B1, 0xCF47, 0x87B2, 0xCF48,
+	0x87B3, 0xF3AB, 0x87B4, 0xCF49, 0x87B5, 0xF3AA, 0x87B6, 0xCF4A,
+	0x87B7, 0xCF4B, 0x87B8, 0xCF4C, 0x87B9, 0xCF4D, 0x87BA, 0xC2DD,
+	0x87BB, 0xCF4E, 0x87BC, 0xCF4F, 0x87BD, 0xF3AE, 0x87BE, 0xCF50,
+	0x87BF, 0xCF51, 0x87C0, 0xF3B0, 0x87C1, 0xCF52, 0x87C2, 0xCF53,
+	0x87C3, 0xCF54, 0x87C4, 0xCF55, 0x87C5, 0xCF56, 0x87C6, 0xF3A1,
+	0x87C7, 0xCF57, 0x87C8, 0xCF58, 0x87C9, 0xCF59, 0x87CA, 0xF3B1,
+	0x87CB, 0xF3AC, 0x87CC, 0xCF5A, 0x87CD, 0xCF5B, 0x87CE, 0xCF5C,
+	0x87CF, 0xCF5D, 0x87D0, 0xCF5E, 0x87D1, 0xF3AF, 0x87D2, 0xF2FE,
+	0x87D3, 0xF3AD, 0x87D4, 0xCF5F, 0x87D5, 0xCF60, 0x87D6, 0xCF61,
+	0x87D7, 0xCF62, 0x87D8, 0xCF63, 0x87D9, 0xCF64, 0x87DA, 0xCF65,
+	0x87DB, 0xF3B2, 0x87DC, 0xCF66, 0x87DD, 0xCF67, 0x87DE, 0xCF68,
+	0x87DF, 0xCF69, 0x87E0, 0xF3B4, 0x87E1, 0xCF6A, 0x87E2, 0xCF6B,
+	0x87E3, 0xCF6C, 0x87E4, 0xCF6D, 0x87E5, 0xF3A8, 0x87E6, 0xCF6E,
+	0x87E7, 0xCF6F, 0x87E8, 0xCF70, 0x87E9, 0xCF71, 0x87EA, 0xF3B3,
+	0x87EB, 0xCF72, 0x87EC, 0xCF73, 0x87ED, 0xCF74, 0x87EE, 0xF3B5,
+	0x87EF, 0xCF75, 0x87F0, 0xCF76, 0x87F1, 0xCF77, 0x87F2, 0xCF78,
+	0x87F3, 0xCF79, 0x87F4, 0xCF7A, 0x87F5, 0xCF7B, 0x87F6, 0xCF7C,
+	0x87F7, 0xCF7D, 0x87F8, 0xCF7E, 0x87F9, 0xD0B7, 0x87FA, 0xCF80,
+	0x87FB, 0xCF81, 0x87FC, 0xCF82, 0x87FD, 0xCF83, 0x87FE, 0xF3B8,
+	0x87FF, 0xCF84, 0x8800, 0xCF85, 0x8801, 0xCF86, 0x8802, 0xCF87,
+	0x8803, 0xD9F9, 0x8804, 0xCF88, 0x8805, 0xCF89, 0x8806, 0xCF8A,
+	0x8807, 0xCF8B, 0x8808, 0xCF8C, 0x8809, 0xCF8D, 0x880A, 0xF3B9,
+	0x880B, 0xCF8E, 0x880C, 0xCF8F, 0x880D, 0xCF90, 0x880E, 0xCF91,
+	0x880F, 0xCF92, 0x8810, 0xCF93, 0x8811, 0xCF94, 0x8812, 0xCF95,
+	0x8813, 0xF3B7, 0x8814, 0xCF96, 0x8815, 0xC8E4, 0x8816, 0xF3B6,
+	0x8817, 0xCF97, 0x8818, 0xCF98, 0x8819, 0xCF99, 0x881A, 0xCF9A,
+	0x881B, 0xF3BA, 0x881C, 0xCF9B, 0x881D, 0xCF9C, 0x881E, 0xCF9D,
+	0x881F, 0xCF9E, 0x8820, 0xCF9F, 0x8821, 0xF3BB, 0x8822, 0xB4C0,
+	0x8823, 0xCFA0, 0x8824, 0xD040, 0x8825, 0xD041, 0x8826, 0xD042,
+	0x8827, 0xD043, 0x8828, 0xD044, 0x8829, 0xD045, 0x882A, 0xD046,
+	0x882B, 0xD047, 0x882C, 0xD048, 0x882D, 0xD049, 0x882E, 0xD04A,
+	0x882F, 0xD04B, 0x8830, 0xD04C, 0x8831, 0xD04D, 0x8832, 0xEEC3,
+	0x8833, 0xD04E, 0x8834, 0xD04F, 0x8835, 0xD050, 0x8836, 0xD051,
+	0x8837, 0xD052, 0x8838, 0xD053, 0x8839, 0xF3BC, 0x883A, 0xD054,
+	0x883B, 0xD055, 0x883C, 0xF3BD, 0x883D, 0xD056, 0x883E, 0xD057,
+	0x883F, 0xD058, 0x8840, 0xD1AA, 0x8841, 0xD059, 0x8842, 0xD05A,
+	0x8843, 0xD05B, 0x8844, 0xF4AC, 0x8845, 0xD0C6, 0x8846, 0xD05C,
+	0x8847, 0xD05D, 0x8848, 0xD05E, 0x8849, 0xD05F, 0x884A, 0xD060,
+	0x884B, 0xD061, 0x884C, 0xD0D0, 0x884D, 0xD1DC, 0x884E, 0xD062,
+	0x884F, 0xD063, 0x8850, 0xD064, 0x8851, 0xD065, 0x8852, 0xD066,
+	0x8853, 0xD067, 0x8854, 0xCFCE, 0x8855, 0xD068, 0x8856, 0xD069,
+	0x8857, 0xBDD6, 0x8858, 0xD06A, 0x8859, 0xD1C3, 0x885A, 0xD06B,
+	0x885B, 0xD06C, 0x885C, 0xD06D, 0x885D, 0xD06E, 0x885E, 0xD06F,
+	0x885F, 0xD070, 0x8860, 0xD071, 0x8861, 0xBAE2, 0x8862, 0xE1E9,
+	0x8863, 0xD2C2, 0x8864, 0xF1C2, 0x8865, 0xB2B9, 0x8866, 0xD072,
+	0x8867, 0xD073, 0x8868, 0xB1ED, 0x8869, 0xF1C3, 0x886A, 0xD074,
+	0x886B, 0xC9C0, 0x886C, 0xB3C4, 0x886D, 0xD075, 0x886E, 0xD9F2,
+	0x886F, 0xD076, 0x8870, 0xCBA5, 0x8871, 0xD077, 0x8872, 0xF1C4,
+	0x8873, 0xD078, 0x8874, 0xD079, 0x8875, 0xD07A, 0x8876, 0xD07B,
+	0x8877, 0xD6D4, 0x8878, 0xD07C, 0x8879, 0xD07D, 0x887A, 0xD07E,
+	0x887B, 0xD080, 0x887C, 0xD081, 0x887D, 0xF1C5, 0x887E, 0xF4C0,
+	0x887F, 0xF1C6, 0x8880, 0xD082, 0x8881, 0xD4AC, 0x8882, 0xF1C7,
+	0x8883, 0xD083, 0x8884, 0xB0C0, 0x8885, 0xF4C1, 0x8886, 0xD084,
+	0x8887, 0xD085, 0x8888, 0xF4C2, 0x8889, 0xD086, 0x888A, 0xD087,
+	0x888B, 0xB4FC, 0x888C, 0xD088, 0x888D, 0xC5DB, 0x888E, 0xD089,
+	0x888F, 0xD08A, 0x8890, 0xD08B, 0x8891, 0xD08C, 0x8892, 0xCCBB,
+	0x8893, 0xD08D, 0x8894, 0xD08E, 0x8895, 0xD08F, 0x8896, 0xD0E4,
+	0x8897, 0xD090, 0x8898, 0xD091, 0x8899, 0xD092, 0x889A, 0xD093,
+	0x889B, 0xD094, 0x889C, 0xCDE0, 0x889D, 0xD095, 0x889E, 0xD096,
+	0x889F, 0xD097, 0x88A0, 0xD098, 0x88A1, 0xD099, 0x88A2, 0xF1C8,
+	0x88A3, 0xD09A, 0x88A4, 0xD9F3, 0x88A5, 0xD09B, 0x88A6, 0xD09C,
+	0x88A7, 0xD09D, 0x88A8, 0xD09E, 0x88A9, 0xD09F, 0x88AA, 0xD0A0,
+	0x88AB, 0xB1BB, 0x88AC, 0xD140, 0x88AD, 0xCFAE, 0x88AE, 0xD141,
+	0x88AF, 0xD142, 0x88B0, 0xD143, 0x88B1, 0xB8A4, 0x88B2, 0xD144,
+	0x88B3, 0xD145, 0x88B4, 0xD146, 0x88B5, 0xD147, 0x88B6, 0xD148,
+	0x88B7, 0xF1CA, 0x88B8, 0xD149, 0x88B9, 0xD14A, 0x88BA, 0xD14B,
+	0x88BB, 0xD14C, 0x88BC, 0xF1CB, 0x88BD, 0xD14D, 0x88BE, 0xD14E,
+	0x88BF, 0xD14F, 0x88C0, 0xD150, 0x88C1, 0xB2C3, 0x88C2, 0xC1D1,
+	0x88C3, 0xD151, 0x88C4, 0xD152, 0x88C5, 0xD7B0, 0x88C6, 0xF1C9,
+	0x88C7, 0xD153, 0x88C8, 0xD154, 0x88C9, 0xF1CC, 0x88CA, 0xD155,
+	0x88CB, 0xD156, 0x88CC, 0xD157, 0x88CD, 0xD158, 0x88CE, 0xF1CE,
+	0x88CF, 0xD159, 0x88D0, 0xD15A, 0x88D1, 0xD15B, 0x88D2, 0xD9F6,
+	0x88D3, 0xD15C, 0x88D4, 0xD2E1, 0x88D5, 0xD4A3, 0x88D6, 0xD15D,
+	0x88D7, 0xD15E, 0x88D8, 0xF4C3, 0x88D9, 0xC8B9, 0x88DA, 0xD15F,
+	0x88DB, 0xD160, 0x88DC, 0xD161, 0x88DD, 0xD162, 0x88DE, 0xD163,
+	0x88DF, 0xF4C4, 0x88E0, 0xD164, 0x88E1, 0xD165, 0x88E2, 0xF1CD,
+	0x88E3, 0xF1CF, 0x88E4, 0xBFE3, 0x88E5, 0xF1D0, 0x88E6, 0xD166,
+	0x88E7, 0xD167, 0x88E8, 0xF1D4, 0x88E9, 0xD168, 0x88EA, 0xD169,
+	0x88EB, 0xD16A, 0x88EC, 0xD16B, 0x88ED, 0xD16C, 0x88EE, 0xD16D,
+	0x88EF, 0xD16E, 0x88F0, 0xF1D6, 0x88F1, 0xF1D1, 0x88F2, 0xD16F,
+	0x88F3, 0xC9D1, 0x88F4, 0xC5E1, 0x88F5, 0xD170, 0x88F6, 0xD171,
+	0x88F7, 0xD172, 0x88F8, 0xC2E3, 0x88F9, 0xB9FC, 0x88FA, 0xD173,
+	0x88FB, 0xD174, 0x88FC, 0xF1D3, 0x88FD, 0xD175, 0x88FE, 0xF1D5,
+	0x88FF, 0xD176, 0x8900, 0xD177, 0x8901, 0xD178, 0x8902, 0xB9D3,
+	0x8903, 0xD179, 0x8904, 0xD17A, 0x8905, 0xD17B, 0x8906, 0xD17C,
+	0x8907, 0xD17D, 0x8908, 0xD17E, 0x8909, 0xD180, 0x890A, 0xF1DB,
+	0x890B, 0xD181, 0x890C, 0xD182, 0x890D, 0xD183, 0x890E, 0xD184,
+	0x890F, 0xD185, 0x8910, 0xBAD6, 0x8911, 0xD186, 0x8912, 0xB0FD,
+	0x8913, 0xF1D9, 0x8914, 0xD187, 0x8915, 0xD188, 0x8916, 0xD189,
+	0x8917, 0xD18A, 0x8918, 0xD18B, 0x8919, 0xF1D8, 0x891A, 0xF1D2,
+	0x891B, 0xF1DA, 0x891C, 0xD18C, 0x891D, 0xD18D, 0x891E, 0xD18E,
+	0x891F, 0xD18F, 0x8920, 0xD190, 0x8921, 0xF1D7, 0x8922, 0xD191,
+	0x8923, 0xD192, 0x8924, 0xD193, 0x8925, 0xC8EC, 0x8926, 0xD194,
+	0x8927, 0xD195, 0x8928, 0xD196, 0x8929, 0xD197, 0x892A, 0xCDCA,
+	0x892B, 0xF1DD, 0x892C, 0xD198, 0x892D, 0xD199, 0x892E, 0xD19A,
+	0x892F, 0xD19B, 0x8930, 0xE5BD, 0x8931, 0xD19C, 0x8932, 0xD19D,
+	0x8933, 0xD19E, 0x8934, 0xF1DC, 0x8935, 0xD19F, 0x8936, 0xF1DE,
+	0x8937, 0xD1A0, 0x8938, 0xD240, 0x8939, 0xD241, 0x893A, 0xD242,
+	0x893B, 0xD243, 0x893C, 0xD244, 0x893D, 0xD245, 0x893E, 0xD246,
+	0x893F, 0xD247, 0x8940, 0xD248, 0x8941, 0xF1DF, 0x8942, 0xD249,
+	0x8943, 0xD24A, 0x8944, 0xCFE5, 0x8945, 0xD24B, 0x8946, 0xD24C,
+	0x8947, 0xD24D, 0x8948, 0xD24E, 0x8949, 0xD24F, 0x894A, 0xD250,
+	0x894B, 0xD251, 0x894C, 0xD252, 0x894D, 0xD253, 0x894E, 0xD254,
+	0x894F, 0xD255, 0x8950, 0xD256, 0x8951, 0xD257, 0x8952, 0xD258,
+	0x8953, 0xD259, 0x8954, 0xD25A, 0x8955, 0xD25B, 0x8956, 0xD25C,
+	0x8957, 0xD25D, 0x8958, 0xD25E, 0x8959, 0xD25F, 0x895A, 0xD260,
+	0x895B, 0xD261, 0x895C, 0xD262, 0x895D, 0xD263, 0x895E, 0xF4C5,
+	0x895F, 0xBDF3, 0x8960, 0xD264, 0x8961, 0xD265, 0x8962, 0xD266,
+	0x8963, 0xD267, 0x8964, 0xD268, 0x8965, 0xD269, 0x8966, 0xF1E0,
+	0x8967, 0xD26A, 0x8968, 0xD26B, 0x8969, 0xD26C, 0x896A, 0xD26D,
+	0x896B, 0xD26E, 0x896C, 0xD26F, 0x896D, 0xD270, 0x896E, 0xD271,
+	0x896F, 0xD272, 0x8970, 0xD273, 0x8971, 0xD274, 0x8972, 0xD275,
+	0x8973, 0xD276, 0x8974, 0xD277, 0x8975, 0xD278, 0x8976, 0xD279,
+	0x8977, 0xD27A, 0x8978, 0xD27B, 0x8979, 0xD27C, 0x897A, 0xD27D,
+	0x897B, 0xF1E1, 0x897C, 0xD27E, 0x897D, 0xD280, 0x897E, 0xD281,
+	0x897F, 0xCEF7, 0x8980, 0xD282, 0x8981, 0xD2AA, 0x8982, 0xD283,
+	0x8983, 0xF1FB, 0x8984, 0xD284, 0x8985, 0xD285, 0x8986, 0xB8B2,
+	0x8987, 0xD286, 0x8988, 0xD287, 0x8989, 0xD288, 0x898A, 0xD289,
+	0x898B, 0xD28A, 0x898C, 0xD28B, 0x898D, 0xD28C, 0x898E, 0xD28D,
+	0x898F, 0xD28E, 0x8990, 0xD28F, 0x8991, 0xD290, 0x8992, 0xD291,
+	0x8993, 0xD292, 0x8994, 0xD293, 0x8995, 0xD294, 0x8996, 0xD295,
+	0x8997, 0xD296, 0x8998, 0xD297, 0x8999, 0xD298, 0x899A, 0xD299,
+	0x899B, 0xD29A, 0x899C, 0xD29B, 0x899D, 0xD29C, 0x899E, 0xD29D,
+	0x899F, 0xD29E, 0x89A0, 0xD29F, 0x89A1, 0xD2A0, 0x89A2, 0xD340,
+	0x89A3, 0xD341, 0x89A4, 0xD342, 0x89A5, 0xD343, 0x89A6, 0xD344,
+	0x89A7, 0xD345, 0x89A8, 0xD346, 0x89A9, 0xD347, 0x89AA, 0xD348,
+	0x89AB, 0xD349, 0x89AC, 0xD34A, 0x89AD, 0xD34B, 0x89AE, 0xD34C,
+	0x89AF, 0xD34D, 0x89B0, 0xD34E, 0x89B1, 0xD34F, 0x89B2, 0xD350,
+	0x89B3, 0xD351, 0x89B4, 0xD352, 0x89B5, 0xD353, 0x89B6, 0xD354,
+	0x89B7, 0xD355, 0x89B8, 0xD356, 0x89B9, 0xD357, 0x89BA, 0xD358,
+	0x89BB, 0xD359, 0x89BC, 0xD35A, 0x89BD, 0xD35B, 0x89BE, 0xD35C,
+	0x89BF, 0xD35D, 0x89C0, 0xD35E, 0x89C1, 0xBCFB, 0x89C2, 0xB9DB,
+	0x89C3, 0xD35F, 0x89C4, 0xB9E6, 0x89C5, 0xC3D9, 0x89C6, 0xCAD3,
+	0x89C7, 0xEAE8, 0x89C8, 0xC0C0, 0x89C9, 0xBEF5, 0x89CA, 0xEAE9,
+	0x89CB, 0xEAEA, 0x89CC, 0xEAEB, 0x89CD, 0xD360, 0x89CE, 0xEAEC,
+	0x89CF, 0xEAED, 0x89D0, 0xEAEE, 0x89D1, 0xEAEF, 0x89D2, 0xBDC7,
+	0x89D3, 0xD361, 0x89D4, 0xD362, 0x89D5, 0xD363, 0x89D6, 0xF5FB,
+	0x89D7, 0xD364, 0x89D8, 0xD365, 0x89D9, 0xD366, 0x89DA, 0xF5FD,
+	0x89DB, 0xD367, 0x89DC, 0xF5FE, 0x89DD, 0xD368, 0x89DE, 0xF5FC,
+	0x89DF, 0xD369, 0x89E0, 0xD36A, 0x89E1, 0xD36B, 0x89E2, 0xD36C,
+	0x89E3, 0xBDE2, 0x89E4, 0xD36D, 0x89E5, 0xF6A1, 0x89E6, 0xB4A5,
+	0x89E7, 0xD36E, 0x89E8, 0xD36F, 0x89E9, 0xD370, 0x89EA, 0xD371,
+	0x89EB, 0xF6A2, 0x89EC, 0xD372, 0x89ED, 0xD373, 0x89EE, 0xD374,
+	0x89EF, 0xF6A3, 0x89F0, 0xD375, 0x89F1, 0xD376, 0x89F2, 0xD377,
+	0x89F3, 0xECB2, 0x89F4, 0xD378, 0x89F5, 0xD379, 0x89F6, 0xD37A,
+	0x89F7, 0xD37B, 0x89F8, 0xD37C, 0x89F9, 0xD37D, 0x89FA, 0xD37E,
+	0x89FB, 0xD380, 0x89FC, 0xD381, 0x89FD, 0xD382, 0x89FE, 0xD383,
+	0x89FF, 0xD384, 0x8A00, 0xD1D4, 0x8A01, 0xD385, 0x8A02, 0xD386,
+	0x8A03, 0xD387, 0x8A04, 0xD388, 0x8A05, 0xD389, 0x8A06, 0xD38A,
+	0x8A07, 0xD9EA, 0x8A08, 0xD38B, 0x8A09, 0xD38C, 0x8A0A, 0xD38D,
+	0x8A0B, 0xD38E, 0x8A0C, 0xD38F, 0x8A0D, 0xD390, 0x8A0E, 0xD391,
+	0x8A0F, 0xD392, 0x8A10, 0xD393, 0x8A11, 0xD394, 0x8A12, 0xD395,
+	0x8A13, 0xD396, 0x8A14, 0xD397, 0x8A15, 0xD398, 0x8A16, 0xD399,
+	0x8A17, 0xD39A, 0x8A18, 0xD39B, 0x8A19, 0xD39C, 0x8A1A, 0xD39D,
+	0x8A1B, 0xD39E, 0x8A1C, 0xD39F, 0x8A1D, 0xD3A0, 0x8A1E, 0xD440,
+	0x8A1F, 0xD441, 0x8A20, 0xD442, 0x8A21, 0xD443, 0x8A22, 0xD444,
+	0x8A23, 0xD445, 0x8A24, 0xD446, 0x8A25, 0xD447, 0x8A26, 0xD448,
+	0x8A27, 0xD449, 0x8A28, 0xD44A, 0x8A29, 0xD44B, 0x8A2A, 0xD44C,
+	0x8A2B, 0xD44D, 0x8A2C, 0xD44E, 0x8A2D, 0xD44F, 0x8A2E, 0xD450,
+	0x8A2F, 0xD451, 0x8A30, 0xD452, 0x8A31, 0xD453, 0x8A32, 0xD454,
+	0x8A33, 0xD455, 0x8A34, 0xD456, 0x8A35, 0xD457, 0x8A36, 0xD458,
+	0x8A37, 0xD459, 0x8A38, 0xD45A, 0x8A39, 0xD45B, 0x8A3A, 0xD45C,
+	0x8A3B, 0xD45D, 0x8A3C, 0xD45E, 0x8A3D, 0xD45F, 0x8A3E, 0xF6A4,
+	0x8A3F, 0xD460, 0x8A40, 0xD461, 0x8A41, 0xD462, 0x8A42, 0xD463,
+	0x8A43, 0xD464, 0x8A44, 0xD465, 0x8A45, 0xD466, 0x8A46, 0xD467,
+	0x8A47, 0xD468, 0x8A48, 0xEEBA, 0x8A49, 0xD469, 0x8A4A, 0xD46A,
+	0x8A4B, 0xD46B, 0x8A4C, 0xD46C, 0x8A4D, 0xD46D, 0x8A4E, 0xD46E,
+	0x8A4F, 0xD46F, 0x8A50, 0xD470, 0x8A51, 0xD471, 0x8A52, 0xD472,
+	0x8A53, 0xD473, 0x8A54, 0xD474, 0x8A55, 0xD475, 0x8A56, 0xD476,
+	0x8A57, 0xD477, 0x8A58, 0xD478, 0x8A59, 0xD479, 0x8A5A, 0xD47A,
+	0x8A5B, 0xD47B, 0x8A5C, 0xD47C, 0x8A5D, 0xD47D, 0x8A5E, 0xD47E,
+	0x8A5F, 0xD480, 0x8A60, 0xD481, 0x8A61, 0xD482, 0x8A62, 0xD483,
+	0x8A63, 0xD484, 0x8A64, 0xD485, 0x8A65, 0xD486, 0x8A66, 0xD487,
+	0x8A67, 0xD488, 0x8A68, 0xD489, 0x8A69, 0xD48A, 0x8A6A, 0xD48B,
+	0x8A6B, 0xD48C, 0x8A6C, 0xD48D, 0x8A6D, 0xD48E, 0x8A6E, 0xD48F,
+	0x8A6F, 0xD490, 0x8A70, 0xD491, 0x8A71, 0xD492, 0x8A72, 0xD493,
+	0x8A73, 0xD494, 0x8A74, 0xD495, 0x8A75, 0xD496, 0x8A76, 0xD497,
+	0x8A77, 0xD498, 0x8A78, 0xD499, 0x8A79, 0xD5B2, 0x8A7A, 0xD49A,
+	0x8A7B, 0xD49B, 0x8A7C, 0xD49C, 0x8A7D, 0xD49D, 0x8A7E, 0xD49E,
+	0x8A7F, 0xD49F, 0x8A80, 0xD4A0, 0x8A81, 0xD540, 0x8A82, 0xD541,
+	0x8A83, 0xD542, 0x8A84, 0xD543, 0x8A85, 0xD544, 0x8A86, 0xD545,
+	0x8A87, 0xD546, 0x8A88, 0xD547, 0x8A89, 0xD3FE, 0x8A8A, 0xCCDC,
+	0x8A8B, 0xD548, 0x8A8C, 0xD549, 0x8A8D, 0xD54A, 0x8A8E, 0xD54B,
+	0x8A8F, 0xD54C, 0x8A90, 0xD54D, 0x8A91, 0xD54E, 0x8A92, 0xD54F,
+	0x8A93, 0xCAC4, 0x8A94, 0xD550, 0x8A95, 0xD551, 0x8A96, 0xD552,
+	0x8A97, 0xD553, 0x8A98, 0xD554, 0x8A99, 0xD555, 0x8A9A, 0xD556,
+	0x8A9B, 0xD557, 0x8A9C, 0xD558, 0x8A9D, 0xD559, 0x8A9E, 0xD55A,
+	0x8A9F, 0xD55B, 0x8AA0, 0xD55C, 0x8AA1, 0xD55D, 0x8AA2, 0xD55E,
+	0x8AA3, 0xD55F, 0x8AA4, 0xD560, 0x8AA5, 0xD561, 0x8AA6, 0xD562,
+	0x8AA7, 0xD563, 0x8AA8, 0xD564, 0x8AA9, 0xD565, 0x8AAA, 0xD566,
+	0x8AAB, 0xD567, 0x8AAC, 0xD568, 0x8AAD, 0xD569, 0x8AAE, 0xD56A,
+	0x8AAF, 0xD56B, 0x8AB0, 0xD56C, 0x8AB1, 0xD56D, 0x8AB2, 0xD56E,
+	0x8AB3, 0xD56F, 0x8AB4, 0xD570, 0x8AB5, 0xD571, 0x8AB6, 0xD572,
+	0x8AB7, 0xD573, 0x8AB8, 0xD574, 0x8AB9, 0xD575, 0x8ABA, 0xD576,
+	0x8ABB, 0xD577, 0x8ABC, 0xD578, 0x8ABD, 0xD579, 0x8ABE, 0xD57A,
+	0x8ABF, 0xD57B, 0x8AC0, 0xD57C, 0x8AC1, 0xD57D, 0x8AC2, 0xD57E,
+	0x8AC3, 0xD580, 0x8AC4, 0xD581, 0x8AC5, 0xD582, 0x8AC6, 0xD583,
+	0x8AC7, 0xD584, 0x8AC8, 0xD585, 0x8AC9, 0xD586, 0x8ACA, 0xD587,
+	0x8ACB, 0xD588, 0x8ACC, 0xD589, 0x8ACD, 0xD58A, 0x8ACE, 0xD58B,
+	0x8ACF, 0xD58C, 0x8AD0, 0xD58D, 0x8AD1, 0xD58E, 0x8AD2, 0xD58F,
+	0x8AD3, 0xD590, 0x8AD4, 0xD591, 0x8AD5, 0xD592, 0x8AD6, 0xD593,
+	0x8AD7, 0xD594, 0x8AD8, 0xD595, 0x8AD9, 0xD596, 0x8ADA, 0xD597,
+	0x8ADB, 0xD598, 0x8ADC, 0xD599, 0x8ADD, 0xD59A, 0x8ADE, 0xD59B,
+	0x8ADF, 0xD59C, 0x8AE0, 0xD59D, 0x8AE1, 0xD59E, 0x8AE2, 0xD59F,
+	0x8AE3, 0xD5A0, 0x8AE4, 0xD640, 0x8AE5, 0xD641, 0x8AE6, 0xD642,
+	0x8AE7, 0xD643, 0x8AE8, 0xD644, 0x8AE9, 0xD645, 0x8AEA, 0xD646,
+	0x8AEB, 0xD647, 0x8AEC, 0xD648, 0x8AED, 0xD649, 0x8AEE, 0xD64A,
+	0x8AEF, 0xD64B, 0x8AF0, 0xD64C, 0x8AF1, 0xD64D, 0x8AF2, 0xD64E,
+	0x8AF3, 0xD64F, 0x8AF4, 0xD650, 0x8AF5, 0xD651, 0x8AF6, 0xD652,
+	0x8AF7, 0xD653, 0x8AF8, 0xD654, 0x8AF9, 0xD655, 0x8AFA, 0xD656,
+	0x8AFB, 0xD657, 0x8AFC, 0xD658, 0x8AFD, 0xD659, 0x8AFE, 0xD65A,
+	0x8AFF, 0xD65B, 0x8B00, 0xD65C, 0x8B01, 0xD65D, 0x8B02, 0xD65E,
+	0x8B03, 0xD65F, 0x8B04, 0xD660, 0x8B05, 0xD661, 0x8B06, 0xD662,
+	0x8B07, 0xE5C0, 0x8B08, 0xD663, 0x8B09, 0xD664, 0x8B0A, 0xD665,
+	0x8B0B, 0xD666, 0x8B0C, 0xD667, 0x8B0D, 0xD668, 0x8B0E, 0xD669,
+	0x8B0F, 0xD66A, 0x8B10, 0xD66B, 0x8B11, 0xD66C, 0x8B12, 0xD66D,
+	0x8B13, 0xD66E, 0x8B14, 0xD66F, 0x8B15, 0xD670, 0x8B16, 0xD671,
+	0x8B17, 0xD672, 0x8B18, 0xD673, 0x8B19, 0xD674, 0x8B1A, 0xD675,
+	0x8B1B, 0xD676, 0x8B1C, 0xD677, 0x8B1D, 0xD678, 0x8B1E, 0xD679,
+	0x8B1F, 0xD67A, 0x8B20, 0xD67B, 0x8B21, 0xD67C, 0x8B22, 0xD67D,
+	0x8B23, 0xD67E, 0x8B24, 0xD680, 0x8B25, 0xD681, 0x8B26, 0xF6A5,
+	0x8B27, 0xD682, 0x8B28, 0xD683, 0x8B29, 0xD684, 0x8B2A, 0xD685,
+	0x8B2B, 0xD686, 0x8B2C, 0xD687, 0x8B2D, 0xD688, 0x8B2E, 0xD689,
+	0x8B2F, 0xD68A, 0x8B30, 0xD68B, 0x8B31, 0xD68C, 0x8B32, 0xD68D,
+	0x8B33, 0xD68E, 0x8B34, 0xD68F, 0x8B35, 0xD690, 0x8B36, 0xD691,
+	0x8B37, 0xD692, 0x8B38, 0xD693, 0x8B39, 0xD694, 0x8B3A, 0xD695,
+	0x8B3B, 0xD696, 0x8B3C, 0xD697, 0x8B3D, 0xD698, 0x8B3E, 0xD699,
+	0x8B3F, 0xD69A, 0x8B40, 0xD69B, 0x8B41, 0xD69C, 0x8B42, 0xD69D,
+	0x8B43, 0xD69E, 0x8B44, 0xD69F, 0x8B45, 0xD6A0, 0x8B46, 0xD740,
+	0x8B47, 0xD741, 0x8B48, 0xD742, 0x8B49, 0xD743, 0x8B4A, 0xD744,
+	0x8B4B, 0xD745, 0x8B4C, 0xD746, 0x8B4D, 0xD747, 0x8B4E, 0xD748,
+	0x8B4F, 0xD749, 0x8B50, 0xD74A, 0x8B51, 0xD74B, 0x8B52, 0xD74C,
+	0x8B53, 0xD74D, 0x8B54, 0xD74E, 0x8B55, 0xD74F, 0x8B56, 0xD750,
+	0x8B57, 0xD751, 0x8B58, 0xD752, 0x8B59, 0xD753, 0x8B5A, 0xD754,
+	0x8B5B, 0xD755, 0x8B5C, 0xD756, 0x8B5D, 0xD757, 0x8B5E, 0xD758,
+	0x8B5F, 0xD759, 0x8B60, 0xD75A, 0x8B61, 0xD75B, 0x8B62, 0xD75C,
+	0x8B63, 0xD75D, 0x8B64, 0xD75E, 0x8B65, 0xD75F, 0x8B66, 0xBEAF,
+	0x8B67, 0xD760, 0x8B68, 0xD761, 0x8B69, 0xD762, 0x8B6A, 0xD763,
+	0x8B6B, 0xD764, 0x8B6C, 0xC6A9, 0x8B6D, 0xD765, 0x8B6E, 0xD766,
+	0x8B6F, 0xD767, 0x8B70, 0xD768, 0x8B71, 0xD769, 0x8B72, 0xD76A,
+	0x8B73, 0xD76B, 0x8B74, 0xD76C, 0x8B75, 0xD76D, 0x8B76, 0xD76E,
+	0x8B77, 0xD76F, 0x8B78, 0xD770, 0x8B79, 0xD771, 0x8B7A, 0xD772,
+	0x8B7B, 0xD773, 0x8B7C, 0xD774, 0x8B7D, 0xD775, 0x8B7E, 0xD776,
+	0x8B7F, 0xD777, 0x8B80, 0xD778, 0x8B81, 0xD779, 0x8B82, 0xD77A,
+	0x8B83, 0xD77B, 0x8B84, 0xD77C, 0x8B85, 0xD77D, 0x8B86, 0xD77E,
+	0x8B87, 0xD780, 0x8B88, 0xD781, 0x8B89, 0xD782, 0x8B8A, 0xD783,
+	0x8B8B, 0xD784, 0x8B8C, 0xD785, 0x8B8D, 0xD786, 0x8B8E, 0xD787,
+	0x8B8F, 0xD788, 0x8B90, 0xD789, 0x8B91, 0xD78A, 0x8B92, 0xD78B,
+	0x8B93, 0xD78C, 0x8B94, 0xD78D, 0x8B95, 0xD78E, 0x8B96, 0xD78F,
+	0x8B97, 0xD790, 0x8B98, 0xD791, 0x8B99, 0xD792, 0x8B9A, 0xD793,
+	0x8B9B, 0xD794, 0x8B9C, 0xD795, 0x8B9D, 0xD796, 0x8B9E, 0xD797,
+	0x8B9F, 0xD798, 0x8BA0, 0xDAA5, 0x8BA1, 0xBCC6, 0x8BA2, 0xB6A9,
+	0x8BA3, 0xB8BC, 0x8BA4, 0xC8CF, 0x8BA5, 0xBCA5, 0x8BA6, 0xDAA6,
+	0x8BA7, 0xDAA7, 0x8BA8, 0xCCD6, 0x8BA9, 0xC8C3, 0x8BAA, 0xDAA8,
+	0x8BAB, 0xC6FD, 0x8BAC, 0xD799, 0x8BAD, 0xD1B5, 0x8BAE, 0xD2E9,
+	0x8BAF, 0xD1B6, 0x8BB0, 0xBCC7, 0x8BB1, 0xD79A, 0x8BB2, 0xBDB2,
+	0x8BB3, 0xBBE4, 0x8BB4, 0xDAA9, 0x8BB5, 0xDAAA, 0x8BB6, 0xD1C8,
+	0x8BB7, 0xDAAB, 0x8BB8, 0xD0ED, 0x8BB9, 0xB6EF, 0x8BBA, 0xC2DB,
+	0x8BBB, 0xD79B, 0x8BBC, 0xCBCF, 0x8BBD, 0xB7ED, 0x8BBE, 0xC9E8,
+	0x8BBF, 0xB7C3, 0x8BC0, 0xBEF7, 0x8BC1, 0xD6A4, 0x8BC2, 0xDAAC,
+	0x8BC3, 0xDAAD, 0x8BC4, 0xC6C0, 0x8BC5, 0xD7E7, 0x8BC6, 0xCAB6,
+	0x8BC7, 0xD79C, 0x8BC8, 0xD5A9, 0x8BC9, 0xCBDF, 0x8BCA, 0xD5EF,
+	0x8BCB, 0xDAAE, 0x8BCC, 0xD6DF, 0x8BCD, 0xB4CA, 0x8BCE, 0xDAB0,
+	0x8BCF, 0xDAAF, 0x8BD0, 0xD79D, 0x8BD1, 0xD2EB, 0x8BD2, 0xDAB1,
+	0x8BD3, 0xDAB2, 0x8BD4, 0xDAB3, 0x8BD5, 0xCAD4, 0x8BD6, 0xDAB4,
+	0x8BD7, 0xCAAB, 0x8BD8, 0xDAB5, 0x8BD9, 0xDAB6, 0x8BDA, 0xB3CF,
+	0x8BDB, 0xD6EF, 0x8BDC, 0xDAB7, 0x8BDD, 0xBBB0, 0x8BDE, 0xB5AE,
+	0x8BDF, 0xDAB8, 0x8BE0, 0xDAB9, 0x8BE1, 0xB9EE, 0x8BE2, 0xD1AF,
+	0x8BE3, 0xD2E8, 0x8BE4, 0xDABA, 0x8BE5, 0xB8C3, 0x8BE6, 0xCFEA,
+	0x8BE7, 0xB2EF, 0x8BE8, 0xDABB, 0x8BE9, 0xDABC, 0x8BEA, 0xD79E,
+	0x8BEB, 0xBDEB, 0x8BEC, 0xCEDC, 0x8BED, 0xD3EF, 0x8BEE, 0xDABD,
+	0x8BEF, 0xCEF3, 0x8BF0, 0xDABE, 0x8BF1, 0xD3D5, 0x8BF2, 0xBBE5,
+	0x8BF3, 0xDABF, 0x8BF4, 0xCBB5, 0x8BF5, 0xCBD0, 0x8BF6, 0xDAC0,
+	0x8BF7, 0xC7EB, 0x8BF8, 0xD6EE, 0x8BF9, 0xDAC1, 0x8BFA, 0xC5B5,
+	0x8BFB, 0xB6C1, 0x8BFC, 0xDAC2, 0x8BFD, 0xB7CC, 0x8BFE, 0xBFCE,
+	0x8BFF, 0xDAC3, 0x8C00, 0xDAC4, 0x8C01, 0xCBAD, 0x8C02, 0xDAC5,
+	0x8C03, 0xB5F7, 0x8C04, 0xDAC6, 0x8C05, 0xC1C2, 0x8C06, 0xD7BB,
+	0x8C07, 0xDAC7, 0x8C08, 0xCCB8, 0x8C09, 0xD79F, 0x8C0A, 0xD2EA,
+	0x8C0B, 0xC4B1, 0x8C0C, 0xDAC8, 0x8C0D, 0xB5FD, 0x8C0E, 0xBBD1,
+	0x8C0F, 0xDAC9, 0x8C10, 0xD0B3, 0x8C11, 0xDACA, 0x8C12, 0xDACB,
+	0x8C13, 0xCEBD, 0x8C14, 0xDACC, 0x8C15, 0xDACD, 0x8C16, 0xDACE,
+	0x8C17, 0xB2F7, 0x8C18, 0xDAD1, 0x8C19, 0xDACF, 0x8C1A, 0xD1E8,
+	0x8C1B, 0xDAD0, 0x8C1C, 0xC3D5, 0x8C1D, 0xDAD2, 0x8C1E, 0xD7A0,
+	0x8C1F, 0xDAD3, 0x8C20, 0xDAD4, 0x8C21, 0xDAD5, 0x8C22, 0xD0BB,
+	0x8C23, 0xD2A5, 0x8C24, 0xB0F9, 0x8C25, 0xDAD6, 0x8C26, 0xC7AB,
+	0x8C27, 0xDAD7, 0x8C28, 0xBDF7, 0x8C29, 0xC3A1, 0x8C2A, 0xDAD8,
+	0x8C2B, 0xDAD9, 0x8C2C, 0xC3FD, 0x8C2D, 0xCCB7, 0x8C2E, 0xDADA,
+	0x8C2F, 0xDADB, 0x8C30, 0xC0BE, 0x8C31, 0xC6D7, 0x8C32, 0xDADC,
+	0x8C33, 0xDADD, 0x8C34, 0xC7B4, 0x8C35, 0xDADE, 0x8C36, 0xDADF,
+	0x8C37, 0xB9C8, 0x8C38, 0xD840, 0x8C39, 0xD841, 0x8C3A, 0xD842,
+	0x8C3B, 0xD843, 0x8C3C, 0xD844, 0x8C3D, 0xD845, 0x8C3E, 0xD846,
+	0x8C3F, 0xD847, 0x8C40, 0xD848, 0x8C41, 0xBBED, 0x8C42, 0xD849,
+	0x8C43, 0xD84A, 0x8C44, 0xD84B, 0x8C45, 0xD84C, 0x8C46, 0xB6B9,
+	0x8C47, 0xF4F8, 0x8C48, 0xD84D, 0x8C49, 0xF4F9, 0x8C4A, 0xD84E,
+	0x8C4B, 0xD84F, 0x8C4C, 0xCDE3, 0x8C4D, 0xD850, 0x8C4E, 0xD851,
+	0x8C4F, 0xD852, 0x8C50, 0xD853, 0x8C51, 0xD854, 0x8C52, 0xD855,
+	0x8C53, 0xD856, 0x8C54, 0xD857, 0x8C55, 0xF5B9, 0x8C56, 0xD858,
+	0x8C57, 0xD859, 0x8C58, 0xD85A, 0x8C59, 0xD85B, 0x8C5A, 0xEBE0,
+	0x8C5B, 0xD85C, 0x8C5C, 0xD85D, 0x8C5D, 0xD85E, 0x8C5E, 0xD85F,
+	0x8C5F, 0xD860, 0x8C60, 0xD861, 0x8C61, 0xCFF3, 0x8C62, 0xBBBF,
+	0x8C63, 0xD862, 0x8C64, 0xD863, 0x8C65, 0xD864, 0x8C66, 0xD865,
+	0x8C67, 0xD866, 0x8C68, 0xD867, 0x8C69, 0xD868, 0x8C6A, 0xBAC0,
+	0x8C6B, 0xD4A5, 0x8C6C, 0xD869, 0x8C6D, 0xD86A, 0x8C6E, 0xD86B,
+	0x8C6F, 0xD86C, 0x8C70, 0xD86D, 0x8C71, 0xD86E, 0x8C72, 0xD86F,
+	0x8C73, 0xE1D9, 0x8C74, 0xD870, 0x8C75, 0xD871, 0x8C76, 0xD872,
+	0x8C77, 0xD873, 0x8C78, 0xF5F4, 0x8C79, 0xB1AA, 0x8C7A, 0xB2F2,
+	0x8C7B, 0xD874, 0x8C7C, 0xD875, 0x8C7D, 0xD876, 0x8C7E, 0xD877,
+	0x8C7F, 0xD878, 0x8C80, 0xD879, 0x8C81, 0xD87A, 0x8C82, 0xF5F5,
+	0x8C83, 0xD87B, 0x8C84, 0xD87C, 0x8C85, 0xF5F7, 0x8C86, 0xD87D,
+	0x8C87, 0xD87E, 0x8C88, 0xD880, 0x8C89, 0xBAD1, 0x8C8A, 0xF5F6,
+	0x8C8B, 0xD881, 0x8C8C, 0xC3B2, 0x8C8D, 0xD882, 0x8C8E, 0xD883,
+	0x8C8F, 0xD884, 0x8C90, 0xD885, 0x8C91, 0xD886, 0x8C92, 0xD887,
+	0x8C93, 0xD888, 0x8C94, 0xF5F9, 0x8C95, 0xD889, 0x8C96, 0xD88A,
+	0x8C97, 0xD88B, 0x8C98, 0xF5F8, 0x8C99, 0xD88C, 0x8C9A, 0xD88D,
+	0x8C9B, 0xD88E, 0x8C9C, 0xD88F, 0x8C9D, 0xD890, 0x8C9E, 0xD891,
+	0x8C9F, 0xD892, 0x8CA0, 0xD893, 0x8CA1, 0xD894, 0x8CA2, 0xD895,
+	0x8CA3, 0xD896, 0x8CA4, 0xD897, 0x8CA5, 0xD898, 0x8CA6, 0xD899,
+	0x8CA7, 0xD89A, 0x8CA8, 0xD89B, 0x8CA9, 0xD89C, 0x8CAA, 0xD89D,
+	0x8CAB, 0xD89E, 0x8CAC, 0xD89F, 0x8CAD, 0xD8A0, 0x8CAE, 0xD940,
+	0x8CAF, 0xD941, 0x8CB0, 0xD942, 0x8CB1, 0xD943, 0x8CB2, 0xD944,
+	0x8CB3, 0xD945, 0x8CB4, 0xD946, 0x8CB5, 0xD947, 0x8CB6, 0xD948,
+	0x8CB7, 0xD949, 0x8CB8, 0xD94A, 0x8CB9, 0xD94B, 0x8CBA, 0xD94C,
+	0x8CBB, 0xD94D, 0x8CBC, 0xD94E, 0x8CBD, 0xD94F, 0x8CBE, 0xD950,
+	0x8CBF, 0xD951, 0x8CC0, 0xD952, 0x8CC1, 0xD953, 0x8CC2, 0xD954,
+	0x8CC3, 0xD955, 0x8CC4, 0xD956, 0x8CC5, 0xD957, 0x8CC6, 0xD958,
+	0x8CC7, 0xD959, 0x8CC8, 0xD95A, 0x8CC9, 0xD95B, 0x8CCA, 0xD95C,
+	0x8CCB, 0xD95D, 0x8CCC, 0xD95E, 0x8CCD, 0xD95F, 0x8CCE, 0xD960,
+	0x8CCF, 0xD961, 0x8CD0, 0xD962, 0x8CD1, 0xD963, 0x8CD2, 0xD964,
+	0x8CD3, 0xD965, 0x8CD4, 0xD966, 0x8CD5, 0xD967, 0x8CD6, 0xD968,
+	0x8CD7, 0xD969, 0x8CD8, 0xD96A, 0x8CD9, 0xD96B, 0x8CDA, 0xD96C,
+	0x8CDB, 0xD96D, 0x8CDC, 0xD96E, 0x8CDD, 0xD96F, 0x8CDE, 0xD970,
+	0x8CDF, 0xD971, 0x8CE0, 0xD972, 0x8CE1, 0xD973, 0x8CE2, 0xD974,
+	0x8CE3, 0xD975, 0x8CE4, 0xD976, 0x8CE5, 0xD977, 0x8CE6, 0xD978,
+	0x8CE7, 0xD979, 0x8CE8, 0xD97A, 0x8CE9, 0xD97B, 0x8CEA, 0xD97C,
+	0x8CEB, 0xD97D, 0x8CEC, 0xD97E, 0x8CED, 0xD980, 0x8CEE, 0xD981,
+	0x8CEF, 0xD982, 0x8CF0, 0xD983, 0x8CF1, 0xD984, 0x8CF2, 0xD985,
+	0x8CF3, 0xD986, 0x8CF4, 0xD987, 0x8CF5, 0xD988, 0x8CF6, 0xD989,
+	0x8CF7, 0xD98A, 0x8CF8, 0xD98B, 0x8CF9, 0xD98C, 0x8CFA, 0xD98D,
+	0x8CFB, 0xD98E, 0x8CFC, 0xD98F, 0x8CFD, 0xD990, 0x8CFE, 0xD991,
+	0x8CFF, 0xD992, 0x8D00, 0xD993, 0x8D01, 0xD994, 0x8D02, 0xD995,
+	0x8D03, 0xD996, 0x8D04, 0xD997, 0x8D05, 0xD998, 0x8D06, 0xD999,
+	0x8D07, 0xD99A, 0x8D08, 0xD99B, 0x8D09, 0xD99C, 0x8D0A, 0xD99D,
+	0x8D0B, 0xD99E, 0x8D0C, 0xD99F, 0x8D0D, 0xD9A0, 0x8D0E, 0xDA40,
+	0x8D0F, 0xDA41, 0x8D10, 0xDA42, 0x8D11, 0xDA43, 0x8D12, 0xDA44,
+	0x8D13, 0xDA45, 0x8D14, 0xDA46, 0x8D15, 0xDA47, 0x8D16, 0xDA48,
+	0x8D17, 0xDA49, 0x8D18, 0xDA4A, 0x8D19, 0xDA4B, 0x8D1A, 0xDA4C,
+	0x8D1B, 0xDA4D, 0x8D1C, 0xDA4E, 0x8D1D, 0xB1B4, 0x8D1E, 0xD5EA,
+	0x8D1F, 0xB8BA, 0x8D20, 0xDA4F, 0x8D21, 0xB9B1, 0x8D22, 0xB2C6,
+	0x8D23, 0xD4F0, 0x8D24, 0xCFCD, 0x8D25, 0xB0DC, 0x8D26, 0xD5CB,
+	0x8D27, 0xBBF5, 0x8D28, 0xD6CA, 0x8D29, 0xB7B7, 0x8D2A, 0xCCB0,
+	0x8D2B, 0xC6B6, 0x8D2C, 0xB1E1, 0x8D2D, 0xB9BA, 0x8D2E, 0xD6FC,
+	0x8D2F, 0xB9E1, 0x8D30, 0xB7A1, 0x8D31, 0xBCFA, 0x8D32, 0xEADA,
+	0x8D33, 0xEADB, 0x8D34, 0xCCF9, 0x8D35, 0xB9F3, 0x8D36, 0xEADC,
+	0x8D37, 0xB4FB, 0x8D38, 0xC3B3, 0x8D39, 0xB7D1, 0x8D3A, 0xBAD8,
+	0x8D3B, 0xEADD, 0x8D3C, 0xD4F4, 0x8D3D, 0xEADE, 0x8D3E, 0xBCD6,
+	0x8D3F, 0xBBDF, 0x8D40, 0xEADF, 0x8D41, 0xC1DE, 0x8D42, 0xC2B8,
+	0x8D43, 0xD4DF, 0x8D44, 0xD7CA, 0x8D45, 0xEAE0, 0x8D46, 0xEAE1,
+	0x8D47, 0xEAE4, 0x8D48, 0xEAE2, 0x8D49, 0xEAE3, 0x8D4A, 0xC9DE,
+	0x8D4B, 0xB8B3, 0x8D4C, 0xB6C4, 0x8D4D, 0xEAE5, 0x8D4E, 0xCAEA,
+	0x8D4F, 0xC9CD, 0x8D50, 0xB4CD, 0x8D51, 0xDA50, 0x8D52, 0xDA51,
+	0x8D53, 0xE2D9, 0x8D54, 0xC5E2, 0x8D55, 0xEAE6, 0x8D56, 0xC0B5,
+	0x8D57, 0xDA52, 0x8D58, 0xD7B8, 0x8D59, 0xEAE7, 0x8D5A, 0xD7AC,
+	0x8D5B, 0xC8FC, 0x8D5C, 0xD8D3, 0x8D5D, 0xD8CD, 0x8D5E, 0xD4DE,
+	0x8D5F, 0xDA53, 0x8D60, 0xD4F9, 0x8D61, 0xC9C4, 0x8D62, 0xD3AE,
+	0x8D63, 0xB8D3, 0x8D64, 0xB3E0, 0x8D65, 0xDA54, 0x8D66, 0xC9E2,
+	0x8D67, 0xF4F6, 0x8D68, 0xDA55, 0x8D69, 0xDA56, 0x8D6A, 0xDA57,
+	0x8D6B, 0xBAD5, 0x8D6C, 0xDA58, 0x8D6D, 0xF4F7, 0x8D6E, 0xDA59,
+	0x8D6F, 0xDA5A, 0x8D70, 0xD7DF, 0x8D71, 0xDA5B, 0x8D72, 0xDA5C,
+	0x8D73, 0xF4F1, 0x8D74, 0xB8B0, 0x8D75, 0xD5D4, 0x8D76, 0xB8CF,
+	0x8D77, 0xC6F0, 0x8D78, 0xDA5D, 0x8D79, 0xDA5E, 0x8D7A, 0xDA5F,
+	0x8D7B, 0xDA60, 0x8D7C, 0xDA61, 0x8D7D, 0xDA62, 0x8D7E, 0xDA63,
+	0x8D7F, 0xDA64, 0x8D80, 0xDA65, 0x8D81, 0xB3C3, 0x8D82, 0xDA66,
+	0x8D83, 0xDA67, 0x8D84, 0xF4F2, 0x8D85, 0xB3AC, 0x8D86, 0xDA68,
+	0x8D87, 0xDA69, 0x8D88, 0xDA6A, 0x8D89, 0xDA6B, 0x8D8A, 0xD4BD,
+	0x8D8B, 0xC7F7, 0x8D8C, 0xDA6C, 0x8D8D, 0xDA6D, 0x8D8E, 0xDA6E,
+	0x8D8F, 0xDA6F, 0x8D90, 0xDA70, 0x8D91, 0xF4F4, 0x8D92, 0xDA71,
+	0x8D93, 0xDA72, 0x8D94, 0xF4F3, 0x8D95, 0xDA73, 0x8D96, 0xDA74,
+	0x8D97, 0xDA75, 0x8D98, 0xDA76, 0x8D99, 0xDA77, 0x8D9A, 0xDA78,
+	0x8D9B, 0xDA79, 0x8D9C, 0xDA7A, 0x8D9D, 0xDA7B, 0x8D9E, 0xDA7C,
+	0x8D9F, 0xCCCB, 0x8DA0, 0xDA7D, 0x8DA1, 0xDA7E, 0x8DA2, 0xDA80,
+	0x8DA3, 0xC8A4, 0x8DA4, 0xDA81, 0x8DA5, 0xDA82, 0x8DA6, 0xDA83,
+	0x8DA7, 0xDA84, 0x8DA8, 0xDA85, 0x8DA9, 0xDA86, 0x8DAA, 0xDA87,
+	0x8DAB, 0xDA88, 0x8DAC, 0xDA89, 0x8DAD, 0xDA8A, 0x8DAE, 0xDA8B,
+	0x8DAF, 0xDA8C, 0x8DB0, 0xDA8D, 0x8DB1, 0xF4F5, 0x8DB2, 0xDA8E,
+	0x8DB3, 0xD7E3, 0x8DB4, 0xC5BF, 0x8DB5, 0xF5C0, 0x8DB6, 0xDA8F,
+	0x8DB7, 0xDA90, 0x8DB8, 0xF5BB, 0x8DB9, 0xDA91, 0x8DBA, 0xF5C3,
+	0x8DBB, 0xDA92, 0x8DBC, 0xF5C2, 0x8DBD, 0xDA93, 0x8DBE, 0xD6BA,
+	0x8DBF, 0xF5C1, 0x8DC0, 0xDA94, 0x8DC1, 0xDA95, 0x8DC2, 0xDA96,
+	0x8DC3, 0xD4BE, 0x8DC4, 0xF5C4, 0x8DC5, 0xDA97, 0x8DC6, 0xF5CC,
+	0x8DC7, 0xDA98, 0x8DC8, 0xDA99, 0x8DC9, 0xDA9A, 0x8DCA, 0xDA9B,
+	0x8DCB, 0xB0CF, 0x8DCC, 0xB5F8, 0x8DCD, 0xDA9C, 0x8DCE, 0xF5C9,
+	0x8DCF, 0xF5CA, 0x8DD0, 0xDA9D, 0x8DD1, 0xC5DC, 0x8DD2, 0xDA9E,
+	0x8DD3, 0xDA9F, 0x8DD4, 0xDAA0, 0x8DD5, 0xDB40, 0x8DD6, 0xF5C5,
+	0x8DD7, 0xF5C6, 0x8DD8, 0xDB41, 0x8DD9, 0xDB42, 0x8DDA, 0xF5C7,
+	0x8DDB, 0xF5CB, 0x8DDC, 0xDB43, 0x8DDD, 0xBEE0, 0x8DDE, 0xF5C8,
+	0x8DDF, 0xB8FA, 0x8DE0, 0xDB44, 0x8DE1, 0xDB45, 0x8DE2, 0xDB46,
+	0x8DE3, 0xF5D0, 0x8DE4, 0xF5D3, 0x8DE5, 0xDB47, 0x8DE6, 0xDB48,
+	0x8DE7, 0xDB49, 0x8DE8, 0xBFE7, 0x8DE9, 0xDB4A, 0x8DEA, 0xB9F2,
+	0x8DEB, 0xF5BC, 0x8DEC, 0xF5CD, 0x8DED, 0xDB4B, 0x8DEE, 0xDB4C,
+	0x8DEF, 0xC2B7, 0x8DF0, 0xDB4D, 0x8DF1, 0xDB4E, 0x8DF2, 0xDB4F,
+	0x8DF3, 0xCCF8, 0x8DF4, 0xDB50, 0x8DF5, 0xBCF9, 0x8DF6, 0xDB51,
+	0x8DF7, 0xF5CE, 0x8DF8, 0xF5CF, 0x8DF9, 0xF5D1, 0x8DFA, 0xB6E5,
+	0x8DFB, 0xF5D2, 0x8DFC, 0xDB52, 0x8DFD, 0xF5D5, 0x8DFE, 0xDB53,
+	0x8DFF, 0xDB54, 0x8E00, 0xDB55, 0x8E01, 0xDB56, 0x8E02, 0xDB57,
+	0x8E03, 0xDB58, 0x8E04, 0xDB59, 0x8E05, 0xF5BD, 0x8E06, 0xDB5A,
+	0x8E07, 0xDB5B, 0x8E08, 0xDB5C, 0x8E09, 0xF5D4, 0x8E0A, 0xD3BB,
+	0x8E0B, 0xDB5D, 0x8E0C, 0xB3EC, 0x8E0D, 0xDB5E, 0x8E0E, 0xDB5F,
+	0x8E0F, 0xCCA4, 0x8E10, 0xDB60, 0x8E11, 0xDB61, 0x8E12, 0xDB62,
+	0x8E13, 0xDB63, 0x8E14, 0xF5D6, 0x8E15, 0xDB64, 0x8E16, 0xDB65,
+	0x8E17, 0xDB66, 0x8E18, 0xDB67, 0x8E19, 0xDB68, 0x8E1A, 0xDB69,
+	0x8E1B, 0xDB6A, 0x8E1C, 0xDB6B, 0x8E1D, 0xF5D7, 0x8E1E, 0xBEE1,
+	0x8E1F, 0xF5D8, 0x8E20, 0xDB6C, 0x8E21, 0xDB6D, 0x8E22, 0xCCDF,
+	0x8E23, 0xF5DB, 0x8E24, 0xDB6E, 0x8E25, 0xDB6F, 0x8E26, 0xDB70,
+	0x8E27, 0xDB71, 0x8E28, 0xDB72, 0x8E29, 0xB2C8, 0x8E2A, 0xD7D9,
+	0x8E2B, 0xDB73, 0x8E2C, 0xF5D9, 0x8E2D, 0xDB74, 0x8E2E, 0xF5DA,
+	0x8E2F, 0xF5DC, 0x8E30, 0xDB75, 0x8E31, 0xF5E2, 0x8E32, 0xDB76,
+	0x8E33, 0xDB77, 0x8E34, 0xDB78, 0x8E35, 0xF5E0, 0x8E36, 0xDB79,
+	0x8E37, 0xDB7A, 0x8E38, 0xDB7B, 0x8E39, 0xF5DF, 0x8E3A, 0xF5DD,
+	0x8E3B, 0xDB7C, 0x8E3C, 0xDB7D, 0x8E3D, 0xF5E1, 0x8E3E, 0xDB7E,
+	0x8E3F, 0xDB80, 0x8E40, 0xF5DE, 0x8E41, 0xF5E4, 0x8E42, 0xF5E5,
+	0x8E43, 0xDB81, 0x8E44, 0xCCE3, 0x8E45, 0xDB82, 0x8E46, 0xDB83,
+	0x8E47, 0xE5BF, 0x8E48, 0xB5B8, 0x8E49, 0xF5E3, 0x8E4A, 0xF5E8,
+	0x8E4B, 0xCCA3, 0x8E4C, 0xDB84, 0x8E4D, 0xDB85, 0x8E4E, 0xDB86,
+	0x8E4F, 0xDB87, 0x8E50, 0xDB88, 0x8E51, 0xF5E6, 0x8E52, 0xF5E7,
+	0x8E53, 0xDB89, 0x8E54, 0xDB8A, 0x8E55, 0xDB8B, 0x8E56, 0xDB8C,
+	0x8E57, 0xDB8D, 0x8E58, 0xDB8E, 0x8E59, 0xF5BE, 0x8E5A, 0xDB8F,
+	0x8E5B, 0xDB90, 0x8E5C, 0xDB91, 0x8E5D, 0xDB92, 0x8E5E, 0xDB93,
+	0x8E5F, 0xDB94, 0x8E60, 0xDB95, 0x8E61, 0xDB96, 0x8E62, 0xDB97,
+	0x8E63, 0xDB98, 0x8E64, 0xDB99, 0x8E65, 0xDB9A, 0x8E66, 0xB1C4,
+	0x8E67, 0xDB9B, 0x8E68, 0xDB9C, 0x8E69, 0xF5BF, 0x8E6A, 0xDB9D,
+	0x8E6B, 0xDB9E, 0x8E6C, 0xB5C5, 0x8E6D, 0xB2E4, 0x8E6E, 0xDB9F,
+	0x8E6F, 0xF5EC, 0x8E70, 0xF5E9, 0x8E71, 0xDBA0, 0x8E72, 0xB6D7,
+	0x8E73, 0xDC40, 0x8E74, 0xF5ED, 0x8E75, 0xDC41, 0x8E76, 0xF5EA,
+	0x8E77, 0xDC42, 0x8E78, 0xDC43, 0x8E79, 0xDC44, 0x8E7A, 0xDC45,
+	0x8E7B, 0xDC46, 0x8E7C, 0xF5EB, 0x8E7D, 0xDC47, 0x8E7E, 0xDC48,
+	0x8E7F, 0xB4DA, 0x8E80, 0xDC49, 0x8E81, 0xD4EA, 0x8E82, 0xDC4A,
+	0x8E83, 0xDC4B, 0x8E84, 0xDC4C, 0x8E85, 0xF5EE, 0x8E86, 0xDC4D,
+	0x8E87, 0xB3F9, 0x8E88, 0xDC4E, 0x8E89, 0xDC4F, 0x8E8A, 0xDC50,
+	0x8E8B, 0xDC51, 0x8E8C, 0xDC52, 0x8E8D, 0xDC53, 0x8E8E, 0xDC54,
+	0x8E8F, 0xF5EF, 0x8E90, 0xF5F1, 0x8E91, 0xDC55, 0x8E92, 0xDC56,
+	0x8E93, 0xDC57, 0x8E94, 0xF5F0, 0x8E95, 0xDC58, 0x8E96, 0xDC59,
+	0x8E97, 0xDC5A, 0x8E98, 0xDC5B, 0x8E99, 0xDC5C, 0x8E9A, 0xDC5D,
+	0x8E9B, 0xDC5E, 0x8E9C, 0xF5F2, 0x8E9D, 0xDC5F, 0x8E9E, 0xF5F3,
+	0x8E9F, 0xDC60, 0x8EA0, 0xDC61, 0x8EA1, 0xDC62, 0x8EA2, 0xDC63,
+	0x8EA3, 0xDC64, 0x8EA4, 0xDC65, 0x8EA5, 0xDC66, 0x8EA6, 0xDC67,
+	0x8EA7, 0xDC68, 0x8EA8, 0xDC69, 0x8EA9, 0xDC6A, 0x8EAA, 0xDC6B,
+	0x8EAB, 0xC9ED, 0x8EAC, 0xB9AA, 0x8EAD, 0xDC6C, 0x8EAE, 0xDC6D,
+	0x8EAF, 0xC7FB, 0x8EB0, 0xDC6E, 0x8EB1, 0xDC6F, 0x8EB2, 0xB6E3,
+	0x8EB3, 0xDC70, 0x8EB4, 0xDC71, 0x8EB5, 0xDC72, 0x8EB6, 0xDC73,
+	0x8EB7, 0xDC74, 0x8EB8, 0xDC75, 0x8EB9, 0xDC76, 0x8EBA, 0xCCC9,
+	0x8EBB, 0xDC77, 0x8EBC, 0xDC78, 0x8EBD, 0xDC79, 0x8EBE, 0xDC7A,
+	0x8EBF, 0xDC7B, 0x8EC0, 0xDC7C, 0x8EC1, 0xDC7D, 0x8EC2, 0xDC7E,
+	0x8EC3, 0xDC80, 0x8EC4, 0xDC81, 0x8EC5, 0xDC82, 0x8EC6, 0xDC83,
+	0x8EC7, 0xDC84, 0x8EC8, 0xDC85, 0x8EC9, 0xDC86, 0x8ECA, 0xDC87,
+	0x8ECB, 0xDC88, 0x8ECC, 0xDC89, 0x8ECD, 0xDC8A, 0x8ECE, 0xEAA6,
+	0x8ECF, 0xDC8B, 0x8ED0, 0xDC8C, 0x8ED1, 0xDC8D, 0x8ED2, 0xDC8E,
+	0x8ED3, 0xDC8F, 0x8ED4, 0xDC90, 0x8ED5, 0xDC91, 0x8ED6, 0xDC92,
+	0x8ED7, 0xDC93, 0x8ED8, 0xDC94, 0x8ED9, 0xDC95, 0x8EDA, 0xDC96,
+	0x8EDB, 0xDC97, 0x8EDC, 0xDC98, 0x8EDD, 0xDC99, 0x8EDE, 0xDC9A,
+	0x8EDF, 0xDC9B, 0x8EE0, 0xDC9C, 0x8EE1, 0xDC9D, 0x8EE2, 0xDC9E,
+	0x8EE3, 0xDC9F, 0x8EE4, 0xDCA0, 0x8EE5, 0xDD40, 0x8EE6, 0xDD41,
+	0x8EE7, 0xDD42, 0x8EE8, 0xDD43, 0x8EE9, 0xDD44, 0x8EEA, 0xDD45,
+	0x8EEB, 0xDD46, 0x8EEC, 0xDD47, 0x8EED, 0xDD48, 0x8EEE, 0xDD49,
+	0x8EEF, 0xDD4A, 0x8EF0, 0xDD4B, 0x8EF1, 0xDD4C, 0x8EF2, 0xDD4D,
+	0x8EF3, 0xDD4E, 0x8EF4, 0xDD4F, 0x8EF5, 0xDD50, 0x8EF6, 0xDD51,
+	0x8EF7, 0xDD52, 0x8EF8, 0xDD53, 0x8EF9, 0xDD54, 0x8EFA, 0xDD55,
+	0x8EFB, 0xDD56, 0x8EFC, 0xDD57, 0x8EFD, 0xDD58, 0x8EFE, 0xDD59,
+	0x8EFF, 0xDD5A, 0x8F00, 0xDD5B, 0x8F01, 0xDD5C, 0x8F02, 0xDD5D,
+	0x8F03, 0xDD5E, 0x8F04, 0xDD5F, 0x8F05, 0xDD60, 0x8F06, 0xDD61,
+	0x8F07, 0xDD62, 0x8F08, 0xDD63, 0x8F09, 0xDD64, 0x8F0A, 0xDD65,
+	0x8F0B, 0xDD66, 0x8F0C, 0xDD67, 0x8F0D, 0xDD68, 0x8F0E, 0xDD69,
+	0x8F0F, 0xDD6A, 0x8F10, 0xDD6B, 0x8F11, 0xDD6C, 0x8F12, 0xDD6D,
+	0x8F13, 0xDD6E, 0x8F14, 0xDD6F, 0x8F15, 0xDD70, 0x8F16, 0xDD71,
+	0x8F17, 0xDD72, 0x8F18, 0xDD73, 0x8F19, 0xDD74, 0x8F1A, 0xDD75,
+	0x8F1B, 0xDD76, 0x8F1C, 0xDD77, 0x8F1D, 0xDD78, 0x8F1E, 0xDD79,
+	0x8F1F, 0xDD7A, 0x8F20, 0xDD7B, 0x8F21, 0xDD7C, 0x8F22, 0xDD7D,
+	0x8F23, 0xDD7E, 0x8F24, 0xDD80, 0x8F25, 0xDD81, 0x8F26, 0xDD82,
+	0x8F27, 0xDD83, 0x8F28, 0xDD84, 0x8F29, 0xDD85, 0x8F2A, 0xDD86,
+	0x8F2B, 0xDD87, 0x8F2C, 0xDD88, 0x8F2D, 0xDD89, 0x8F2E, 0xDD8A,
+	0x8F2F, 0xDD8B, 0x8F30, 0xDD8C, 0x8F31, 0xDD8D, 0x8F32, 0xDD8E,
+	0x8F33, 0xDD8F, 0x8F34, 0xDD90, 0x8F35, 0xDD91, 0x8F36, 0xDD92,
+	0x8F37, 0xDD93, 0x8F38, 0xDD94, 0x8F39, 0xDD95, 0x8F3A, 0xDD96,
+	0x8F3B, 0xDD97, 0x8F3C, 0xDD98, 0x8F3D, 0xDD99, 0x8F3E, 0xDD9A,
+	0x8F3F, 0xDD9B, 0x8F40, 0xDD9C, 0x8F41, 0xDD9D, 0x8F42, 0xDD9E,
+	0x8F43, 0xDD9F, 0x8F44, 0xDDA0, 0x8F45, 0xDE40, 0x8F46, 0xDE41,
+	0x8F47, 0xDE42, 0x8F48, 0xDE43, 0x8F49, 0xDE44, 0x8F4A, 0xDE45,
+	0x8F4B, 0xDE46, 0x8F4C, 0xDE47, 0x8F4D, 0xDE48, 0x8F4E, 0xDE49,
+	0x8F4F, 0xDE4A, 0x8F50, 0xDE4B, 0x8F51, 0xDE4C, 0x8F52, 0xDE4D,
+	0x8F53, 0xDE4E, 0x8F54, 0xDE4F, 0x8F55, 0xDE50, 0x8F56, 0xDE51,
+	0x8F57, 0xDE52, 0x8F58, 0xDE53, 0x8F59, 0xDE54, 0x8F5A, 0xDE55,
+	0x8F5B, 0xDE56, 0x8F5C, 0xDE57, 0x8F5D, 0xDE58, 0x8F5E, 0xDE59,
+	0x8F5F, 0xDE5A, 0x8F60, 0xDE5B, 0x8F61, 0xDE5C, 0x8F62, 0xDE5D,
+	0x8F63, 0xDE5E, 0x8F64, 0xDE5F, 0x8F65, 0xDE60, 0x8F66, 0xB3B5,
+	0x8F67, 0xD4FE, 0x8F68, 0xB9EC, 0x8F69, 0xD0F9, 0x8F6A, 0xDE61,
+	0x8F6B, 0xE9ED, 0x8F6C, 0xD7AA, 0x8F6D, 0xE9EE, 0x8F6E, 0xC2D6,
+	0x8F6F, 0xC8ED, 0x8F70, 0xBAE4, 0x8F71, 0xE9EF, 0x8F72, 0xE9F0,
+	0x8F73, 0xE9F1, 0x8F74, 0xD6E1, 0x8F75, 0xE9F2, 0x8F76, 0xE9F3,
+	0x8F77, 0xE9F5, 0x8F78, 0xE9F4, 0x8F79, 0xE9F6, 0x8F7A, 0xE9F7,
+	0x8F7B, 0xC7E1, 0x8F7C, 0xE9F8, 0x8F7D, 0xD4D8, 0x8F7E, 0xE9F9,
+	0x8F7F, 0xBDCE, 0x8F80, 0xDE62, 0x8F81, 0xE9FA, 0x8F82, 0xE9FB,
+	0x8F83, 0xBDCF, 0x8F84, 0xE9FC, 0x8F85, 0xB8A8, 0x8F86, 0xC1BE,
+	0x8F87, 0xE9FD, 0x8F88, 0xB1B2, 0x8F89, 0xBBD4, 0x8F8A, 0xB9F5,
+	0x8F8B, 0xE9FE, 0x8F8C, 0xDE63, 0x8F8D, 0xEAA1, 0x8F8E, 0xEAA2,
+	0x8F8F, 0xEAA3, 0x8F90, 0xB7F8, 0x8F91, 0xBCAD, 0x8F92, 0xDE64,
+	0x8F93, 0xCAE4, 0x8F94, 0xE0CE, 0x8F95, 0xD4AF, 0x8F96, 0xCFBD,
+	0x8F97, 0xD5B7, 0x8F98, 0xEAA4, 0x8F99, 0xD5DE, 0x8F9A, 0xEAA5,
+	0x8F9B, 0xD0C1, 0x8F9C, 0xB9BC, 0x8F9D, 0xDE65, 0x8F9E, 0xB4C7,
+	0x8F9F, 0xB1D9, 0x8FA0, 0xDE66, 0x8FA1, 0xDE67, 0x8FA2, 0xDE68,
+	0x8FA3, 0xC0B1, 0x8FA4, 0xDE69, 0x8FA5, 0xDE6A, 0x8FA6, 0xDE6B,
+	0x8FA7, 0xDE6C, 0x8FA8, 0xB1E6, 0x8FA9, 0xB1E7, 0x8FAA, 0xDE6D,
+	0x8FAB, 0xB1E8, 0x8FAC, 0xDE6E, 0x8FAD, 0xDE6F, 0x8FAE, 0xDE70,
+	0x8FAF, 0xDE71, 0x8FB0, 0xB3BD, 0x8FB1, 0xC8E8, 0x8FB2, 0xDE72,
+	0x8FB3, 0xDE73, 0x8FB4, 0xDE74, 0x8FB5, 0xDE75, 0x8FB6, 0xE5C1,
+	0x8FB7, 0xDE76, 0x8FB8, 0xDE77, 0x8FB9, 0xB1DF, 0x8FBA, 0xDE78,
+	0x8FBB, 0xDE79, 0x8FBC, 0xDE7A, 0x8FBD, 0xC1C9, 0x8FBE, 0xB4EF,
+	0x8FBF, 0xDE7B, 0x8FC0, 0xDE7C, 0x8FC1, 0xC7A8, 0x8FC2, 0xD3D8,
+	0x8FC3, 0xDE7D, 0x8FC4, 0xC6F9, 0x8FC5, 0xD1B8, 0x8FC6, 0xDE7E,
+	0x8FC7, 0xB9FD, 0x8FC8, 0xC2F5, 0x8FC9, 0xDE80, 0x8FCA, 0xDE81,
+	0x8FCB, 0xDE82, 0x8FCC, 0xDE83, 0x8FCD, 0xDE84, 0x8FCE, 0xD3AD,
+	0x8FCF, 0xDE85, 0x8FD0, 0xD4CB, 0x8FD1, 0xBDFC, 0x8FD2, 0xDE86,
+	0x8FD3, 0xE5C2, 0x8FD4, 0xB7B5, 0x8FD5, 0xE5C3, 0x8FD6, 0xDE87,
+	0x8FD7, 0xDE88, 0x8FD8, 0xBBB9, 0x8FD9, 0xD5E2, 0x8FDA, 0xDE89,
+	0x8FDB, 0xBDF8, 0x8FDC, 0xD4B6, 0x8FDD, 0xCEA5, 0x8FDE, 0xC1AC,
+	0x8FDF, 0xB3D9, 0x8FE0, 0xDE8A, 0x8FE1, 0xDE8B, 0x8FE2, 0xCCF6,
+	0x8FE3, 0xDE8C, 0x8FE4, 0xE5C6, 0x8FE5, 0xE5C4, 0x8FE6, 0xE5C8,
+	0x8FE7, 0xDE8D, 0x8FE8, 0xE5CA, 0x8FE9, 0xE5C7, 0x8FEA, 0xB5CF,
+	0x8FEB, 0xC6C8, 0x8FEC, 0xDE8E, 0x8FED, 0xB5FC, 0x8FEE, 0xE5C5,
+	0x8FEF, 0xDE8F, 0x8FF0, 0xCAF6, 0x8FF1, 0xDE90, 0x8FF2, 0xDE91,
+	0x8FF3, 0xE5C9, 0x8FF4, 0xDE92, 0x8FF5, 0xDE93, 0x8FF6, 0xDE94,
+	0x8FF7, 0xC3D4, 0x8FF8, 0xB1C5, 0x8FF9, 0xBCA3, 0x8FFA, 0xDE95,
+	0x8FFB, 0xDE96, 0x8FFC, 0xDE97, 0x8FFD, 0xD7B7, 0x8FFE, 0xDE98,
+	0x8FFF, 0xDE99, 0x9000, 0xCDCB, 0x9001, 0xCBCD, 0x9002, 0xCACA,
+	0x9003, 0xCCD3, 0x9004, 0xE5CC, 0x9005, 0xE5CB, 0x9006, 0xC4E6,
+	0x9007, 0xDE9A, 0x9008, 0xDE9B, 0x9009, 0xD1A1, 0x900A, 0xD1B7,
+	0x900B, 0xE5CD, 0x900C, 0xDE9C, 0x900D, 0xE5D0, 0x900E, 0xDE9D,
+	0x900F, 0xCDB8, 0x9010, 0xD6F0, 0x9011, 0xE5CF, 0x9012, 0xB5DD,
+	0x9013, 0xDE9E, 0x9014, 0xCDBE, 0x9015, 0xDE9F, 0x9016, 0xE5D1,
+	0x9017, 0xB6BA, 0x9018, 0xDEA0, 0x9019, 0xDF40, 0x901A, 0xCDA8,
+	0x901B, 0xB9E4, 0x901C, 0xDF41, 0x901D, 0xCAC5, 0x901E, 0xB3D1,
+	0x901F, 0xCBD9, 0x9020, 0xD4EC, 0x9021, 0xE5D2, 0x9022, 0xB7EA,
+	0x9023, 0xDF42, 0x9024, 0xDF43, 0x9025, 0xDF44, 0x9026, 0xE5CE,
+	0x9027, 0xDF45, 0x9028, 0xDF46, 0x9029, 0xDF47, 0x902A, 0xDF48,
+	0x902B, 0xDF49, 0x902C, 0xDF4A, 0x902D, 0xE5D5, 0x902E, 0xB4FE,
+	0x902F, 0xE5D6, 0x9030, 0xDF4B, 0x9031, 0xDF4C, 0x9032, 0xDF4D,
+	0x9033, 0xDF4E, 0x9034, 0xDF4F, 0x9035, 0xE5D3, 0x9036, 0xE5D4,
+	0x9037, 0xDF50, 0x9038, 0xD2DD, 0x9039, 0xDF51, 0x903A, 0xDF52,
+	0x903B, 0xC2DF, 0x903C, 0xB1C6, 0x903D, 0xDF53, 0x903E, 0xD3E2,
+	0x903F, 0xDF54, 0x9040, 0xDF55, 0x9041, 0xB6DD, 0x9042, 0xCBEC,
+	0x9043, 0xDF56, 0x9044, 0xE5D7, 0x9045, 0xDF57, 0x9046, 0xDF58,
+	0x9047, 0xD3F6, 0x9048, 0xDF59, 0x9049, 0xDF5A, 0x904A, 0xDF5B,
+	0x904B, 0xDF5C, 0x904C, 0xDF5D, 0x904D, 0xB1E9, 0x904E, 0xDF5E,
+	0x904F, 0xB6F4, 0x9050, 0xE5DA, 0x9051, 0xE5D8, 0x9052, 0xE5D9,
+	0x9053, 0xB5C0, 0x9054, 0xDF5F, 0x9055, 0xDF60, 0x9056, 0xDF61,
+	0x9057, 0xD2C5, 0x9058, 0xE5DC, 0x9059, 0xDF62, 0x905A, 0xDF63,
+	0x905B, 0xE5DE, 0x905C, 0xDF64, 0x905D, 0xDF65, 0x905E, 0xDF66,
+	0x905F, 0xDF67, 0x9060, 0xDF68, 0x9061, 0xDF69, 0x9062, 0xE5DD,
+	0x9063, 0xC7B2, 0x9064, 0xDF6A, 0x9065, 0xD2A3, 0x9066, 0xDF6B,
+	0x9067, 0xDF6C, 0x9068, 0xE5DB, 0x9069, 0xDF6D, 0x906A, 0xDF6E,
+	0x906B, 0xDF6F, 0x906C, 0xDF70, 0x906D, 0xD4E2, 0x906E, 0xD5DA,
+	0x906F, 0xDF71, 0x9070, 0xDF72, 0x9071, 0xDF73, 0x9072, 0xDF74,
+	0x9073, 0xDF75, 0x9074, 0xE5E0, 0x9075, 0xD7F1, 0x9076, 0xDF76,
+	0x9077, 0xDF77, 0x9078, 0xDF78, 0x9079, 0xDF79, 0x907A, 0xDF7A,
+	0x907B, 0xDF7B, 0x907C, 0xDF7C, 0x907D, 0xE5E1, 0x907E, 0xDF7D,
+	0x907F, 0xB1DC, 0x9080, 0xD1FB, 0x9081, 0xDF7E, 0x9082, 0xE5E2,
+	0x9083, 0xE5E4, 0x9084, 0xDF80, 0x9085, 0xDF81, 0x9086, 0xDF82,
+	0x9087, 0xDF83, 0x9088, 0xE5E3, 0x9089, 0xDF84, 0x908A, 0xDF85,
+	0x908B, 0xE5E5, 0x908C, 0xDF86, 0x908D, 0xDF87, 0x908E, 0xDF88,
+	0x908F, 0xDF89, 0x9090, 0xDF8A, 0x9091, 0xD2D8, 0x9092, 0xDF8B,
+	0x9093, 0xB5CB, 0x9094, 0xDF8C, 0x9095, 0xE7DF, 0x9096, 0xDF8D,
+	0x9097, 0xDAF5, 0x9098, 0xDF8E, 0x9099, 0xDAF8, 0x909A, 0xDF8F,
+	0x909B, 0xDAF6, 0x909C, 0xDF90, 0x909D, 0xDAF7, 0x909E, 0xDF91,
+	0x909F, 0xDF92, 0x90A0, 0xDF93, 0x90A1, 0xDAFA, 0x90A2, 0xD0CF,
+	0x90A3, 0xC4C7, 0x90A4, 0xDF94, 0x90A5, 0xDF95, 0x90A6, 0xB0EE,
+	0x90A7, 0xDF96, 0x90A8, 0xDF97, 0x90A9, 0xDF98, 0x90AA, 0xD0B0,
+	0x90AB, 0xDF99, 0x90AC, 0xDAF9, 0x90AD, 0xDF9A, 0x90AE, 0xD3CA,
+	0x90AF, 0xBAAA, 0x90B0, 0xDBA2, 0x90B1, 0xC7F1, 0x90B2, 0xDF9B,
+	0x90B3, 0xDAFC, 0x90B4, 0xDAFB, 0x90B5, 0xC9DB, 0x90B6, 0xDAFD,
+	0x90B7, 0xDF9C, 0x90B8, 0xDBA1, 0x90B9, 0xD7DE, 0x90BA, 0xDAFE,
+	0x90BB, 0xC1DA, 0x90BC, 0xDF9D, 0x90BD, 0xDF9E, 0x90BE, 0xDBA5,
+	0x90BF, 0xDF9F, 0x90C0, 0xDFA0, 0x90C1, 0xD3F4, 0x90C2, 0xE040,
+	0x90C3, 0xE041, 0x90C4, 0xDBA7, 0x90C5, 0xDBA4, 0x90C6, 0xE042,
+	0x90C7, 0xDBA8, 0x90C8, 0xE043, 0x90C9, 0xE044, 0x90CA, 0xBDBC,
+	0x90CB, 0xE045, 0x90CC, 0xE046, 0x90CD, 0xE047, 0x90CE, 0xC0C9,
+	0x90CF, 0xDBA3, 0x90D0, 0xDBA6, 0x90D1, 0xD6A3, 0x90D2, 0xE048,
+	0x90D3, 0xDBA9, 0x90D4, 0xE049, 0x90D5, 0xE04A, 0x90D6, 0xE04B,
+	0x90D7, 0xDBAD, 0x90D8, 0xE04C, 0x90D9, 0xE04D, 0x90DA, 0xE04E,
+	0x90DB, 0xDBAE, 0x90DC, 0xDBAC, 0x90DD, 0xBAC2, 0x90DE, 0xE04F,
+	0x90DF, 0xE050, 0x90E0, 0xE051, 0x90E1, 0xBFA4, 0x90E2, 0xDBAB,
+	0x90E3, 0xE052, 0x90E4, 0xE053, 0x90E5, 0xE054, 0x90E6, 0xDBAA,
+	0x90E7, 0xD4C7, 0x90E8, 0xB2BF, 0x90E9, 0xE055, 0x90EA, 0xE056,
+	0x90EB, 0xDBAF, 0x90EC, 0xE057, 0x90ED, 0xB9F9, 0x90EE, 0xE058,
+	0x90EF, 0xDBB0, 0x90F0, 0xE059, 0x90F1, 0xE05A, 0x90F2, 0xE05B,
+	0x90F3, 0xE05C, 0x90F4, 0xB3BB, 0x90F5, 0xE05D, 0x90F6, 0xE05E,
+	0x90F7, 0xE05F, 0x90F8, 0xB5A6, 0x90F9, 0xE060, 0x90FA, 0xE061,
+	0x90FB, 0xE062, 0x90FC, 0xE063, 0x90FD, 0xB6BC, 0x90FE, 0xDBB1,
+	0x90FF, 0xE064, 0x9100, 0xE065, 0x9101, 0xE066, 0x9102, 0xB6F5,
+	0x9103, 0xE067, 0x9104, 0xDBB2, 0x9105, 0xE068, 0x9106, 0xE069,
+	0x9107, 0xE06A, 0x9108, 0xE06B, 0x9109, 0xE06C, 0x910A, 0xE06D,
+	0x910B, 0xE06E, 0x910C, 0xE06F, 0x910D, 0xE070, 0x910E, 0xE071,
+	0x910F, 0xE072, 0x9110, 0xE073, 0x9111, 0xE074, 0x9112, 0xE075,
+	0x9113, 0xE076, 0x9114, 0xE077, 0x9115, 0xE078, 0x9116, 0xE079,
+	0x9117, 0xE07A, 0x9118, 0xE07B, 0x9119, 0xB1C9, 0x911A, 0xE07C,
+	0x911B, 0xE07D, 0x911C, 0xE07E, 0x911D, 0xE080, 0x911E, 0xDBB4,
+	0x911F, 0xE081, 0x9120, 0xE082, 0x9121, 0xE083, 0x9122, 0xDBB3,
+	0x9123, 0xDBB5, 0x9124, 0xE084, 0x9125, 0xE085, 0x9126, 0xE086,
+	0x9127, 0xE087, 0x9128, 0xE088, 0x9129, 0xE089, 0x912A, 0xE08A,
+	0x912B, 0xE08B, 0x912C, 0xE08C, 0x912D, 0xE08D, 0x912E, 0xE08E,
+	0x912F, 0xDBB7, 0x9130, 0xE08F, 0x9131, 0xDBB6, 0x9132, 0xE090,
+	0x9133, 0xE091, 0x9134, 0xE092, 0x9135, 0xE093, 0x9136, 0xE094,
+	0x9137, 0xE095, 0x9138, 0xE096, 0x9139, 0xDBB8, 0x913A, 0xE097,
+	0x913B, 0xE098, 0x913C, 0xE099, 0x913D, 0xE09A, 0x913E, 0xE09B,
+	0x913F, 0xE09C, 0x9140, 0xE09D, 0x9141, 0xE09E, 0x9142, 0xE09F,
+	0x9143, 0xDBB9, 0x9144, 0xE0A0, 0x9145, 0xE140, 0x9146, 0xDBBA,
+	0x9147, 0xE141, 0x9148, 0xE142, 0x9149, 0xD3CF, 0x914A, 0xF4FA,
+	0x914B, 0xC7F5, 0x914C, 0xD7C3, 0x914D, 0xC5E4, 0x914E, 0xF4FC,
+	0x914F, 0xF4FD, 0x9150, 0xF4FB, 0x9151, 0xE143, 0x9152, 0xBEC6,
+	0x9153, 0xE144, 0x9154, 0xE145, 0x9155, 0xE146, 0x9156, 0xE147,
+	0x9157, 0xD0EF, 0x9158, 0xE148, 0x9159, 0xE149, 0x915A, 0xB7D3,
+	0x915B, 0xE14A, 0x915C, 0xE14B, 0x915D, 0xD4CD, 0x915E, 0xCCAA,
+	0x915F, 0xE14C, 0x9160, 0xE14D, 0x9161, 0xF5A2, 0x9162, 0xF5A1,
+	0x9163, 0xBAA8, 0x9164, 0xF4FE, 0x9165, 0xCBD6, 0x9166, 0xE14E,
+	0x9167, 0xE14F, 0x9168, 0xE150, 0x9169, 0xF5A4, 0x916A, 0xC0D2,
+	0x916B, 0xE151, 0x916C, 0xB3EA, 0x916D, 0xE152, 0x916E, 0xCDAA,
+	0x916F, 0xF5A5, 0x9170, 0xF5A3, 0x9171, 0xBDB4, 0x9172, 0xF5A8,
+	0x9173, 0xE153, 0x9174, 0xF5A9, 0x9175, 0xBDCD, 0x9176, 0xC3B8,
+	0x9177, 0xBFE1, 0x9178, 0xCBE1, 0x9179, 0xF5AA, 0x917A, 0xE154,
+	0x917B, 0xE155, 0x917C, 0xE156, 0x917D, 0xF5A6, 0x917E, 0xF5A7,
+	0x917F, 0xC4F0, 0x9180, 0xE157, 0x9181, 0xE158, 0x9182, 0xE159,
+	0x9183, 0xE15A, 0x9184, 0xE15B, 0x9185, 0xF5AC, 0x9186, 0xE15C,
+	0x9187, 0xB4BC, 0x9188, 0xE15D, 0x9189, 0xD7ED, 0x918A, 0xE15E,
+	0x918B, 0xB4D7, 0x918C, 0xF5AB, 0x918D, 0xF5AE, 0x918E, 0xE15F,
+	0x918F, 0xE160, 0x9190, 0xF5AD, 0x9191, 0xF5AF, 0x9192, 0xD0D1,
+	0x9193, 0xE161, 0x9194, 0xE162, 0x9195, 0xE163, 0x9196, 0xE164,
+	0x9197, 0xE165, 0x9198, 0xE166, 0x9199, 0xE167, 0x919A, 0xC3D1,
+	0x919B, 0xC8A9, 0x919C, 0xE168, 0x919D, 0xE169, 0x919E, 0xE16A,
+	0x919F, 0xE16B, 0x91A0, 0xE16C, 0x91A1, 0xE16D, 0x91A2, 0xF5B0,
+	0x91A3, 0xF5B1, 0x91A4, 0xE16E, 0x91A5, 0xE16F, 0x91A6, 0xE170,
+	0x91A7, 0xE171, 0x91A8, 0xE172, 0x91A9, 0xE173, 0x91AA, 0xF5B2,
+	0x91AB, 0xE174, 0x91AC, 0xE175, 0x91AD, 0xF5B3, 0x91AE, 0xF5B4,
+	0x91AF, 0xF5B5, 0x91B0, 0xE176, 0x91B1, 0xE177, 0x91B2, 0xE178,
+	0x91B3, 0xE179, 0x91B4, 0xF5B7, 0x91B5, 0xF5B6, 0x91B6, 0xE17A,
+	0x91B7, 0xE17B, 0x91B8, 0xE17C, 0x91B9, 0xE17D, 0x91BA, 0xF5B8,
+	0x91BB, 0xE17E, 0x91BC, 0xE180, 0x91BD, 0xE181, 0x91BE, 0xE182,
+	0x91BF, 0xE183, 0x91C0, 0xE184, 0x91C1, 0xE185, 0x91C2, 0xE186,
+	0x91C3, 0xE187, 0x91C4, 0xE188, 0x91C5, 0xE189, 0x91C6, 0xE18A,
+	0x91C7, 0xB2C9, 0x91C8, 0xE18B, 0x91C9, 0xD3D4, 0x91CA, 0xCACD,
+	0x91CB, 0xE18C, 0x91CC, 0xC0EF, 0x91CD, 0xD6D8, 0x91CE, 0xD2B0,
+	0x91CF, 0xC1BF, 0x91D0, 0xE18D, 0x91D1, 0xBDF0, 0x91D2, 0xE18E,
+	0x91D3, 0xE18F, 0x91D4, 0xE190, 0x91D5, 0xE191, 0x91D6, 0xE192,
+	0x91D7, 0xE193, 0x91D8, 0xE194, 0x91D9, 0xE195, 0x91DA, 0xE196,
+	0x91DB, 0xE197, 0x91DC, 0xB8AA, 0x91DD, 0xE198, 0x91DE, 0xE199,
+	0x91DF, 0xE19A, 0x91E0, 0xE19B, 0x91E1, 0xE19C, 0x91E2, 0xE19D,
+	0x91E3, 0xE19E, 0x91E4, 0xE19F, 0x91E5, 0xE1A0, 0x91E6, 0xE240,
+	0x91E7, 0xE241, 0x91E8, 0xE242, 0x91E9, 0xE243, 0x91EA, 0xE244,
+	0x91EB, 0xE245, 0x91EC, 0xE246, 0x91ED, 0xE247, 0x91EE, 0xE248,
+	0x91EF, 0xE249, 0x91F0, 0xE24A, 0x91F1, 0xE24B, 0x91F2, 0xE24C,
+	0x91F3, 0xE24D, 0x91F4, 0xE24E, 0x91F5, 0xE24F, 0x91F6, 0xE250,
+	0x91F7, 0xE251, 0x91F8, 0xE252, 0x91F9, 0xE253, 0x91FA, 0xE254,
+	0x91FB, 0xE255, 0x91FC, 0xE256, 0x91FD, 0xE257, 0x91FE, 0xE258,
+	0x91FF, 0xE259, 0x9200, 0xE25A, 0x9201, 0xE25B, 0x9202, 0xE25C,
+	0x9203, 0xE25D, 0x9204, 0xE25E, 0x9205, 0xE25F, 0x9206, 0xE260,
+	0x9207, 0xE261, 0x9208, 0xE262, 0x9209, 0xE263, 0x920A, 0xE264,
+	0x920B, 0xE265, 0x920C, 0xE266, 0x920D, 0xE267, 0x920E, 0xE268,
+	0x920F, 0xE269, 0x9210, 0xE26A, 0x9211, 0xE26B, 0x9212, 0xE26C,
+	0x9213, 0xE26D, 0x9214, 0xE26E, 0x9215, 0xE26F, 0x9216, 0xE270,
+	0x9217, 0xE271, 0x9218, 0xE272, 0x9219, 0xE273, 0x921A, 0xE274,
+	0x921B, 0xE275, 0x921C, 0xE276, 0x921D, 0xE277, 0x921E, 0xE278,
+	0x921F, 0xE279, 0x9220, 0xE27A, 0x9221, 0xE27B, 0x9222, 0xE27C,
+	0x9223, 0xE27D, 0x9224, 0xE27E, 0x9225, 0xE280, 0x9226, 0xE281,
+	0x9227, 0xE282, 0x9228, 0xE283, 0x9229, 0xE284, 0x922A, 0xE285,
+	0x922B, 0xE286, 0x922C, 0xE287, 0x922D, 0xE288, 0x922E, 0xE289,
+	0x922F, 0xE28A, 0x9230, 0xE28B, 0x9231, 0xE28C, 0x9232, 0xE28D,
+	0x9233, 0xE28E, 0x9234, 0xE28F, 0x9235, 0xE290, 0x9236, 0xE291,
+	0x9237, 0xE292, 0x9238, 0xE293, 0x9239, 0xE294, 0x923A, 0xE295,
+	0x923B, 0xE296, 0x923C, 0xE297, 0x923D, 0xE298, 0x923E, 0xE299,
+	0x923F, 0xE29A, 0x9240, 0xE29B, 0x9241, 0xE29C, 0x9242, 0xE29D,
+	0x9243, 0xE29E, 0x9244, 0xE29F, 0x9245, 0xE2A0, 0x9246, 0xE340,
+	0x9247, 0xE341, 0x9248, 0xE342, 0x9249, 0xE343, 0x924A, 0xE344,
+	0x924B, 0xE345, 0x924C, 0xE346, 0x924D, 0xE347, 0x924E, 0xE348,
+	0x924F, 0xE349, 0x9250, 0xE34A, 0x9251, 0xE34B, 0x9252, 0xE34C,
+	0x9253, 0xE34D, 0x9254, 0xE34E, 0x9255, 0xE34F, 0x9256, 0xE350,
+	0x9257, 0xE351, 0x9258, 0xE352, 0x9259, 0xE353, 0x925A, 0xE354,
+	0x925B, 0xE355, 0x925C, 0xE356, 0x925D, 0xE357, 0x925E, 0xE358,
+	0x925F, 0xE359, 0x9260, 0xE35A, 0x9261, 0xE35B, 0x9262, 0xE35C,
+	0x9263, 0xE35D, 0x9264, 0xE35E, 0x9265, 0xE35F, 0x9266, 0xE360,
+	0x9267, 0xE361, 0x9268, 0xE362, 0x9269, 0xE363, 0x926A, 0xE364,
+	0x926B, 0xE365, 0x926C, 0xE366, 0x926D, 0xE367, 0x926E, 0xE368,
+	0x926F, 0xE369, 0x9270, 0xE36A, 0x9271, 0xE36B, 0x9272, 0xE36C,
+	0x9273, 0xE36D, 0x9274, 0xBCF8, 0x9275, 0xE36E, 0x9276, 0xE36F,
+	0x9277, 0xE370, 0x9278, 0xE371, 0x9279, 0xE372, 0x927A, 0xE373,
+	0x927B, 0xE374, 0x927C, 0xE375, 0x927D, 0xE376, 0x927E, 0xE377,
+	0x927F, 0xE378, 0x9280, 0xE379, 0x9281, 0xE37A, 0x9282, 0xE37B,
+	0x9283, 0xE37C, 0x9284, 0xE37D, 0x9285, 0xE37E, 0x9286, 0xE380,
+	0x9287, 0xE381, 0x9288, 0xE382, 0x9289, 0xE383, 0x928A, 0xE384,
+	0x928B, 0xE385, 0x928C, 0xE386, 0x928D, 0xE387, 0x928E, 0xF6C6,
+	0x928F, 0xE388, 0x9290, 0xE389, 0x9291, 0xE38A, 0x9292, 0xE38B,
+	0x9293, 0xE38C, 0x9294, 0xE38D, 0x9295, 0xE38E, 0x9296, 0xE38F,
+	0x9297, 0xE390, 0x9298, 0xE391, 0x9299, 0xE392, 0x929A, 0xE393,
+	0x929B, 0xE394, 0x929C, 0xE395, 0x929D, 0xE396, 0x929E, 0xE397,
+	0x929F, 0xE398, 0x92A0, 0xE399, 0x92A1, 0xE39A, 0x92A2, 0xE39B,
+	0x92A3, 0xE39C, 0x92A4, 0xE39D, 0x92A5, 0xE39E, 0x92A6, 0xE39F,
+	0x92A7, 0xE3A0, 0x92A8, 0xE440, 0x92A9, 0xE441, 0x92AA, 0xE442,
+	0x92AB, 0xE443, 0x92AC, 0xE444, 0x92AD, 0xE445, 0x92AE, 0xF6C7,
+	0x92AF, 0xE446, 0x92B0, 0xE447, 0x92B1, 0xE448, 0x92B2, 0xE449,
+	0x92B3, 0xE44A, 0x92B4, 0xE44B, 0x92B5, 0xE44C, 0x92B6, 0xE44D,
+	0x92B7, 0xE44E, 0x92B8, 0xE44F, 0x92B9, 0xE450, 0x92BA, 0xE451,
+	0x92BB, 0xE452, 0x92BC, 0xE453, 0x92BD, 0xE454, 0x92BE, 0xE455,
+	0x92BF, 0xE456, 0x92C0, 0xE457, 0x92C1, 0xE458, 0x92C2, 0xE459,
+	0x92C3, 0xE45A, 0x92C4, 0xE45B, 0x92C5, 0xE45C, 0x92C6, 0xE45D,
+	0x92C7, 0xE45E, 0x92C8, 0xF6C8, 0x92C9, 0xE45F, 0x92CA, 0xE460,
+	0x92CB, 0xE461, 0x92CC, 0xE462, 0x92CD, 0xE463, 0x92CE, 0xE464,
+	0x92CF, 0xE465, 0x92D0, 0xE466, 0x92D1, 0xE467, 0x92D2, 0xE468,
+	0x92D3, 0xE469, 0x92D4, 0xE46A, 0x92D5, 0xE46B, 0x92D6, 0xE46C,
+	0x92D7, 0xE46D, 0x92D8, 0xE46E, 0x92D9, 0xE46F, 0x92DA, 0xE470,
+	0x92DB, 0xE471, 0x92DC, 0xE472, 0x92DD, 0xE473, 0x92DE, 0xE474,
+	0x92DF, 0xE475, 0x92E0, 0xE476, 0x92E1, 0xE477, 0x92E2, 0xE478,
+	0x92E3, 0xE479, 0x92E4, 0xE47A, 0x92E5, 0xE47B, 0x92E6, 0xE47C,
+	0x92E7, 0xE47D, 0x92E8, 0xE47E, 0x92E9, 0xE480, 0x92EA, 0xE481,
+	0x92EB, 0xE482, 0x92EC, 0xE483, 0x92ED, 0xE484, 0x92EE, 0xE485,
+	0x92EF, 0xE486, 0x92F0, 0xE487, 0x92F1, 0xE488, 0x92F2, 0xE489,
+	0x92F3, 0xE48A, 0x92F4, 0xE48B, 0x92F5, 0xE48C, 0x92F6, 0xE48D,
+	0x92F7, 0xE48E, 0x92F8, 0xE48F, 0x92F9, 0xE490, 0x92FA, 0xE491,
+	0x92FB, 0xE492, 0x92FC, 0xE493, 0x92FD, 0xE494, 0x92FE, 0xE495,
+	0x92FF, 0xE496, 0x9300, 0xE497, 0x9301, 0xE498, 0x9302, 0xE499,
+	0x9303, 0xE49A, 0x9304, 0xE49B, 0x9305, 0xE49C, 0x9306, 0xE49D,
+	0x9307, 0xE49E, 0x9308, 0xE49F, 0x9309, 0xE4A0, 0x930A, 0xE540,
+	0x930B, 0xE541, 0x930C, 0xE542, 0x930D, 0xE543, 0x930E, 0xE544,
+	0x930F, 0xE545, 0x9310, 0xE546, 0x9311, 0xE547, 0x9312, 0xE548,
+	0x9313, 0xE549, 0x9314, 0xE54A, 0x9315, 0xE54B, 0x9316, 0xE54C,
+	0x9317, 0xE54D, 0x9318, 0xE54E, 0x9319, 0xE54F, 0x931A, 0xE550,
+	0x931B, 0xE551, 0x931C, 0xE552, 0x931D, 0xE553, 0x931E, 0xE554,
+	0x931F, 0xE555, 0x9320, 0xE556, 0x9321, 0xE557, 0x9322, 0xE558,
+	0x9323, 0xE559, 0x9324, 0xE55A, 0x9325, 0xE55B, 0x9326, 0xE55C,
+	0x9327, 0xE55D, 0x9328, 0xE55E, 0x9329, 0xE55F, 0x932A, 0xE560,
+	0x932B, 0xE561, 0x932C, 0xE562, 0x932D, 0xE563, 0x932E, 0xE564,
+	0x932F, 0xE565, 0x9330, 0xE566, 0x9331, 0xE567, 0x9332, 0xE568,
+	0x9333, 0xE569, 0x9334, 0xE56A, 0x9335, 0xE56B, 0x9336, 0xE56C,
+	0x9337, 0xE56D, 0x9338, 0xE56E, 0x9339, 0xE56F, 0x933A, 0xE570,
+	0x933B, 0xE571, 0x933C, 0xE572, 0x933D, 0xE573, 0x933E, 0xF6C9,
+	0x933F, 0xE574, 0x9340, 0xE575, 0x9341, 0xE576, 0x9342, 0xE577,
+	0x9343, 0xE578, 0x9344, 0xE579, 0x9345, 0xE57A, 0x9346, 0xE57B,
+	0x9347, 0xE57C, 0x9348, 0xE57D, 0x9349, 0xE57E, 0x934A, 0xE580,
+	0x934B, 0xE581, 0x934C, 0xE582, 0x934D, 0xE583, 0x934E, 0xE584,
+	0x934F, 0xE585, 0x9350, 0xE586, 0x9351, 0xE587, 0x9352, 0xE588,
+	0x9353, 0xE589, 0x9354, 0xE58A, 0x9355, 0xE58B, 0x9356, 0xE58C,
+	0x9357, 0xE58D, 0x9358, 0xE58E, 0x9359, 0xE58F, 0x935A, 0xE590,
+	0x935B, 0xE591, 0x935C, 0xE592, 0x935D, 0xE593, 0x935E, 0xE594,
+	0x935F, 0xE595, 0x9360, 0xE596, 0x9361, 0xE597, 0x9362, 0xE598,
+	0x9363, 0xE599, 0x9364, 0xE59A, 0x9365, 0xE59B, 0x9366, 0xE59C,
+	0x9367, 0xE59D, 0x9368, 0xE59E, 0x9369, 0xE59F, 0x936A, 0xF6CA,
+	0x936B, 0xE5A0, 0x936C, 0xE640, 0x936D, 0xE641, 0x936E, 0xE642,
+	0x936F, 0xE643, 0x9370, 0xE644, 0x9371, 0xE645, 0x9372, 0xE646,
+	0x9373, 0xE647, 0x9374, 0xE648, 0x9375, 0xE649, 0x9376, 0xE64A,
+	0x9377, 0xE64B, 0x9378, 0xE64C, 0x9379, 0xE64D, 0x937A, 0xE64E,
+	0x937B, 0xE64F, 0x937C, 0xE650, 0x937D, 0xE651, 0x937E, 0xE652,
+	0x937F, 0xE653, 0x9380, 0xE654, 0x9381, 0xE655, 0x9382, 0xE656,
+	0x9383, 0xE657, 0x9384, 0xE658, 0x9385, 0xE659, 0x9386, 0xE65A,
+	0x9387, 0xE65B, 0x9388, 0xE65C, 0x9389, 0xE65D, 0x938A, 0xE65E,
+	0x938B, 0xE65F, 0x938C, 0xE660, 0x938D, 0xE661, 0x938E, 0xE662,
+	0x938F, 0xF6CC, 0x9390, 0xE663, 0x9391, 0xE664, 0x9392, 0xE665,
+	0x9393, 0xE666, 0x9394, 0xE667, 0x9395, 0xE668, 0x9396, 0xE669,
+	0x9397, 0xE66A, 0x9398, 0xE66B, 0x9399, 0xE66C, 0x939A, 0xE66D,
+	0x939B, 0xE66E, 0x939C, 0xE66F, 0x939D, 0xE670, 0x939E, 0xE671,
+	0x939F, 0xE672, 0x93A0, 0xE673, 0x93A1, 0xE674, 0x93A2, 0xE675,
+	0x93A3, 0xE676, 0x93A4, 0xE677, 0x93A5, 0xE678, 0x93A6, 0xE679,
+	0x93A7, 0xE67A, 0x93A8, 0xE67B, 0x93A9, 0xE67C, 0x93AA, 0xE67D,
+	0x93AB, 0xE67E, 0x93AC, 0xE680, 0x93AD, 0xE681, 0x93AE, 0xE682,
+	0x93AF, 0xE683, 0x93B0, 0xE684, 0x93B1, 0xE685, 0x93B2, 0xE686,
+	0x93B3, 0xE687, 0x93B4, 0xE688, 0x93B5, 0xE689, 0x93B6, 0xE68A,
+	0x93B7, 0xE68B, 0x93B8, 0xE68C, 0x93B9, 0xE68D, 0x93BA, 0xE68E,
+	0x93BB, 0xE68F, 0x93BC, 0xE690, 0x93BD, 0xE691, 0x93BE, 0xE692,
+	0x93BF, 0xE693, 0x93C0, 0xE694, 0x93C1, 0xE695, 0x93C2, 0xE696,
+	0x93C3, 0xE697, 0x93C4, 0xE698, 0x93C5, 0xE699, 0x93C6, 0xE69A,
+	0x93C7, 0xE69B, 0x93C8, 0xE69C, 0x93C9, 0xE69D, 0x93CA, 0xF6CB,
+	0x93CB, 0xE69E, 0x93CC, 0xE69F, 0x93CD, 0xE6A0, 0x93CE, 0xE740,
+	0x93CF, 0xE741, 0x93D0, 0xE742, 0x93D1, 0xE743, 0x93D2, 0xE744,
+	0x93D3, 0xE745, 0x93D4, 0xE746, 0x93D5, 0xE747, 0x93D6, 0xF7E9,
+	0x93D7, 0xE748, 0x93D8, 0xE749, 0x93D9, 0xE74A, 0x93DA, 0xE74B,
+	0x93DB, 0xE74C, 0x93DC, 0xE74D, 0x93DD, 0xE74E, 0x93DE, 0xE74F,
+	0x93DF, 0xE750, 0x93E0, 0xE751, 0x93E1, 0xE752, 0x93E2, 0xE753,
+	0x93E3, 0xE754, 0x93E4, 0xE755, 0x93E5, 0xE756, 0x93E6, 0xE757,
+	0x93E7, 0xE758, 0x93E8, 0xE759, 0x93E9, 0xE75A, 0x93EA, 0xE75B,
+	0x93EB, 0xE75C, 0x93EC, 0xE75D, 0x93ED, 0xE75E, 0x93EE, 0xE75F,
+	0x93EF, 0xE760, 0x93F0, 0xE761, 0x93F1, 0xE762, 0x93F2, 0xE763,
+	0x93F3, 0xE764, 0x93F4, 0xE765, 0x93F5, 0xE766, 0x93F6, 0xE767,
+	0x93F7, 0xE768, 0x93F8, 0xE769, 0x93F9, 0xE76A, 0x93FA, 0xE76B,
+	0x93FB, 0xE76C, 0x93FC, 0xE76D, 0x93FD, 0xE76E, 0x93FE, 0xE76F,
+	0x93FF, 0xE770, 0x9400, 0xE771, 0x9401, 0xE772, 0x9402, 0xE773,
+	0x9403, 0xE774, 0x9404, 0xE775, 0x9405, 0xE776, 0x9406, 0xE777,
+	0x9407, 0xE778, 0x9408, 0xE779, 0x9409, 0xE77A, 0x940A, 0xE77B,
+	0x940B, 0xE77C, 0x940C, 0xE77D, 0x940D, 0xE77E, 0x940E, 0xE780,
+	0x940F, 0xE781, 0x9410, 0xE782, 0x9411, 0xE783, 0x9412, 0xE784,
+	0x9413, 0xE785, 0x9414, 0xE786, 0x9415, 0xE787, 0x9416, 0xE788,
+	0x9417, 0xE789, 0x9418, 0xE78A, 0x9419, 0xE78B, 0x941A, 0xE78C,
+	0x941B, 0xE78D, 0x941C, 0xE78E, 0x941D, 0xE78F, 0x941E, 0xE790,
+	0x941F, 0xE791, 0x9420, 0xE792, 0x9421, 0xE793, 0x9422, 0xE794,
+	0x9423, 0xE795, 0x9424, 0xE796, 0x9425, 0xE797, 0x9426, 0xE798,
+	0x9427, 0xE799, 0x9428, 0xE79A, 0x9429, 0xE79B, 0x942A, 0xE79C,
+	0x942B, 0xE79D, 0x942C, 0xE79E, 0x942D, 0xE79F, 0x942E, 0xE7A0,
+	0x942F, 0xE840, 0x9430, 0xE841, 0x9431, 0xE842, 0x9432, 0xE843,
+	0x9433, 0xE844, 0x9434, 0xE845, 0x9435, 0xE846, 0x9436, 0xE847,
+	0x9437, 0xE848, 0x9438, 0xE849, 0x9439, 0xE84A, 0x943A, 0xE84B,
+	0x943B, 0xE84C, 0x943C, 0xE84D, 0x943D, 0xE84E, 0x943E, 0xF6CD,
+	0x943F, 0xE84F, 0x9440, 0xE850, 0x9441, 0xE851, 0x9442, 0xE852,
+	0x9443, 0xE853, 0x9444, 0xE854, 0x9445, 0xE855, 0x9446, 0xE856,
+	0x9447, 0xE857, 0x9448, 0xE858, 0x9449, 0xE859, 0x944A, 0xE85A,
+	0x944B, 0xE85B, 0x944C, 0xE85C, 0x944D, 0xE85D, 0x944E, 0xE85E,
+	0x944F, 0xE85F, 0x9450, 0xE860, 0x9451, 0xE861, 0x9452, 0xE862,
+	0x9453, 0xE863, 0x9454, 0xE864, 0x9455, 0xE865, 0x9456, 0xE866,
+	0x9457, 0xE867, 0x9458, 0xE868, 0x9459, 0xE869, 0x945A, 0xE86A,
+	0x945B, 0xE86B, 0x945C, 0xE86C, 0x945D, 0xE86D, 0x945E, 0xE86E,
+	0x945F, 0xE86F, 0x9460, 0xE870, 0x9461, 0xE871, 0x9462, 0xE872,
+	0x9463, 0xE873, 0x9464, 0xE874, 0x9465, 0xE875, 0x9466, 0xE876,
+	0x9467, 0xE877, 0x9468, 0xE878, 0x9469, 0xE879, 0x946A, 0xE87A,
+	0x946B, 0xF6CE, 0x946C, 0xE87B, 0x946D, 0xE87C, 0x946E, 0xE87D,
+	0x946F, 0xE87E, 0x9470, 0xE880, 0x9471, 0xE881, 0x9472, 0xE882,
+	0x9473, 0xE883, 0x9474, 0xE884, 0x9475, 0xE885, 0x9476, 0xE886,
+	0x9477, 0xE887, 0x9478, 0xE888, 0x9479, 0xE889, 0x947A, 0xE88A,
+	0x947B, 0xE88B, 0x947C, 0xE88C, 0x947D, 0xE88D, 0x947E, 0xE88E,
+	0x947F, 0xE88F, 0x9480, 0xE890, 0x9481, 0xE891, 0x9482, 0xE892,
+	0x9483, 0xE893, 0x9484, 0xE894, 0x9485, 0xEEC4, 0x9486, 0xEEC5,
+	0x9487, 0xEEC6, 0x9488, 0xD5EB, 0x9489, 0xB6A4, 0x948A, 0xEEC8,
+	0x948B, 0xEEC7, 0x948C, 0xEEC9, 0x948D, 0xEECA, 0x948E, 0xC7A5,
+	0x948F, 0xEECB, 0x9490, 0xEECC, 0x9491, 0xE895, 0x9492, 0xB7B0,
+	0x9493, 0xB5F6, 0x9494, 0xEECD, 0x9495, 0xEECF, 0x9496, 0xE896,
+	0x9497, 0xEECE, 0x9498, 0xE897, 0x9499, 0xB8C6, 0x949A, 0xEED0,
+	0x949B, 0xEED1, 0x949C, 0xEED2, 0x949D, 0xB6DB, 0x949E, 0xB3AE,
+	0x949F, 0xD6D3, 0x94A0, 0xC4C6, 0x94A1, 0xB1B5, 0x94A2, 0xB8D6,
+	0x94A3, 0xEED3, 0x94A4, 0xEED4, 0x94A5, 0xD4BF, 0x94A6, 0xC7D5,
+	0x94A7, 0xBEFB, 0x94A8, 0xCED9, 0x94A9, 0xB9B3, 0x94AA, 0xEED6,
+	0x94AB, 0xEED5, 0x94AC, 0xEED8, 0x94AD, 0xEED7, 0x94AE, 0xC5A5,
+	0x94AF, 0xEED9, 0x94B0, 0xEEDA, 0x94B1, 0xC7AE, 0x94B2, 0xEEDB,
+	0x94B3, 0xC7AF, 0x94B4, 0xEEDC, 0x94B5, 0xB2A7, 0x94B6, 0xEEDD,
+	0x94B7, 0xEEDE, 0x94B8, 0xEEDF, 0x94B9, 0xEEE0, 0x94BA, 0xEEE1,
+	0x94BB, 0xD7EA, 0x94BC, 0xEEE2, 0x94BD, 0xEEE3, 0x94BE, 0xBCD8,
+	0x94BF, 0xEEE4, 0x94C0, 0xD3CB, 0x94C1, 0xCCFA, 0x94C2, 0xB2AC,
+	0x94C3, 0xC1E5, 0x94C4, 0xEEE5, 0x94C5, 0xC7A6, 0x94C6, 0xC3AD,
+	0x94C7, 0xE898, 0x94C8, 0xEEE6, 0x94C9, 0xEEE7, 0x94CA, 0xEEE8,
+	0x94CB, 0xEEE9, 0x94CC, 0xEEEA, 0x94CD, 0xEEEB, 0x94CE, 0xEEEC,
+	0x94CF, 0xE899, 0x94D0, 0xEEED, 0x94D1, 0xEEEE, 0x94D2, 0xEEEF,
+	0x94D3, 0xE89A, 0x94D4, 0xE89B, 0x94D5, 0xEEF0, 0x94D6, 0xEEF1,
+	0x94D7, 0xEEF2, 0x94D8, 0xEEF4, 0x94D9, 0xEEF3, 0x94DA, 0xE89C,
+	0x94DB, 0xEEF5, 0x94DC, 0xCDAD, 0x94DD, 0xC2C1, 0x94DE, 0xEEF6,
+	0x94DF, 0xEEF7, 0x94E0, 0xEEF8, 0x94E1, 0xD5A1, 0x94E2, 0xEEF9,
+	0x94E3, 0xCFB3, 0x94E4, 0xEEFA, 0x94E5, 0xEEFB, 0x94E6, 0xE89D,
+	0x94E7, 0xEEFC, 0x94E8, 0xEEFD, 0x94E9, 0xEFA1, 0x94EA, 0xEEFE,
+	0x94EB, 0xEFA2, 0x94EC, 0xB8F5, 0x94ED, 0xC3FA, 0x94EE, 0xEFA3,
+	0x94EF, 0xEFA4, 0x94F0, 0xBDC2, 0x94F1, 0xD2BF, 0x94F2, 0xB2F9,
+	0x94F3, 0xEFA5, 0x94F4, 0xEFA6, 0x94F5, 0xEFA7, 0x94F6, 0xD2F8,
+	0x94F7, 0xEFA8, 0x94F8, 0xD6FD, 0x94F9, 0xEFA9, 0x94FA, 0xC6CC,
+	0x94FB, 0xE89E, 0x94FC, 0xEFAA, 0x94FD, 0xEFAB, 0x94FE, 0xC1B4,
+	0x94FF, 0xEFAC, 0x9500, 0xCFFA, 0x9501, 0xCBF8, 0x9502, 0xEFAE,
+	0x9503, 0xEFAD, 0x9504, 0xB3FA, 0x9505, 0xB9F8, 0x9506, 0xEFAF,
+	0x9507, 0xEFB0, 0x9508, 0xD0E2, 0x9509, 0xEFB1, 0x950A, 0xEFB2,
+	0x950B, 0xB7E6, 0x950C, 0xD0BF, 0x950D, 0xEFB3, 0x950E, 0xEFB4,
+	0x950F, 0xEFB5, 0x9510, 0xC8F1, 0x9511, 0xCCE0, 0x9512, 0xEFB6,
+	0x9513, 0xEFB7, 0x9514, 0xEFB8, 0x9515, 0xEFB9, 0x9516, 0xEFBA,
+	0x9517, 0xD5E0, 0x9518, 0xEFBB, 0x9519, 0xB4ED, 0x951A, 0xC3AA,
+	0x951B, 0xEFBC, 0x951C, 0xE89F, 0x951D, 0xEFBD, 0x951E, 0xEFBE,
+	0x951F, 0xEFBF, 0x9520, 0xE8A0, 0x9521, 0xCEFD, 0x9522, 0xEFC0,
+	0x9523, 0xC2E0, 0x9524, 0xB4B8, 0x9525, 0xD7B6, 0x9526, 0xBDF5,
+	0x9527, 0xE940, 0x9528, 0xCFC7, 0x9529, 0xEFC3, 0x952A, 0xEFC1,
+	0x952B, 0xEFC2, 0x952C, 0xEFC4, 0x952D, 0xB6A7, 0x952E, 0xBCFC,
+	0x952F, 0xBEE2, 0x9530, 0xC3CC, 0x9531, 0xEFC5, 0x9532, 0xEFC6,
+	0x9533, 0xE941, 0x9534, 0xEFC7, 0x9535, 0xEFCF, 0x9536, 0xEFC8,
+	0x9537, 0xEFC9, 0x9538, 0xEFCA, 0x9539, 0xC7C2, 0x953A, 0xEFF1,
+	0x953B, 0xB6CD, 0x953C, 0xEFCB, 0x953D, 0xE942, 0x953E, 0xEFCC,
+	0x953F, 0xEFCD, 0x9540, 0xB6C6, 0x9541, 0xC3BE, 0x9542, 0xEFCE,
+	0x9543, 0xE943, 0x9544, 0xEFD0, 0x9545, 0xEFD1, 0x9546, 0xEFD2,
+	0x9547, 0xD5F2, 0x9548, 0xE944, 0x9549, 0xEFD3, 0x954A, 0xC4F7,
+	0x954B, 0xE945, 0x954C, 0xEFD4, 0x954D, 0xC4F8, 0x954E, 0xEFD5,
+	0x954F, 0xEFD6, 0x9550, 0xB8E4, 0x9551, 0xB0F7, 0x9552, 0xEFD7,
+	0x9553, 0xEFD8, 0x9554, 0xEFD9, 0x9555, 0xE946, 0x9556, 0xEFDA,
+	0x9557, 0xEFDB, 0x9558, 0xEFDC, 0x9559, 0xEFDD, 0x955A, 0xE947,
+	0x955B, 0xEFDE, 0x955C, 0xBEB5, 0x955D, 0xEFE1, 0x955E, 0xEFDF,
+	0x955F, 0xEFE0, 0x9560, 0xE948, 0x9561, 0xEFE2, 0x9562, 0xEFE3,
+	0x9563, 0xC1CD, 0x9564, 0xEFE4, 0x9565, 0xEFE5, 0x9566, 0xEFE6,
+	0x9567, 0xEFE7, 0x9568, 0xEFE8, 0x9569, 0xEFE9, 0x956A, 0xEFEA,
+	0x956B, 0xEFEB, 0x956C, 0xEFEC, 0x956D, 0xC0D8, 0x956E, 0xE949,
+	0x956F, 0xEFED, 0x9570, 0xC1AD, 0x9571, 0xEFEE, 0x9572, 0xEFEF,
+	0x9573, 0xEFF0, 0x9574, 0xE94A, 0x9575, 0xE94B, 0x9576, 0xCFE2,
+	0x9577, 0xE94C, 0x9578, 0xE94D, 0x9579, 0xE94E, 0x957A, 0xE94F,
+	0x957B, 0xE950, 0x957C, 0xE951, 0x957D, 0xE952, 0x957E, 0xE953,
+	0x957F, 0xB3A4, 0x9580, 0xE954, 0x9581, 0xE955, 0x9582, 0xE956,
+	0x9583, 0xE957, 0x9584, 0xE958, 0x9585, 0xE959, 0x9586, 0xE95A,
+	0x9587, 0xE95B, 0x9588, 0xE95C, 0x9589, 0xE95D, 0x958A, 0xE95E,
+	0x958B, 0xE95F, 0x958C, 0xE960, 0x958D, 0xE961, 0x958E, 0xE962,
+	0x958F, 0xE963, 0x9590, 0xE964, 0x9591, 0xE965, 0x9592, 0xE966,
+	0x9593, 0xE967, 0x9594, 0xE968, 0x9595, 0xE969, 0x9596, 0xE96A,
+	0x9597, 0xE96B, 0x9598, 0xE96C, 0x9599, 0xE96D, 0x959A, 0xE96E,
+	0x959B, 0xE96F, 0x959C, 0xE970, 0x959D, 0xE971, 0x959E, 0xE972,
+	0x959F, 0xE973, 0x95A0, 0xE974, 0x95A1, 0xE975, 0x95A2, 0xE976,
+	0x95A3, 0xE977, 0x95A4, 0xE978, 0x95A5, 0xE979, 0x95A6, 0xE97A,
+	0x95A7, 0xE97B, 0x95A8, 0xE97C, 0x95A9, 0xE97D, 0x95AA, 0xE97E,
+	0x95AB, 0xE980, 0x95AC, 0xE981, 0x95AD, 0xE982, 0x95AE, 0xE983,
+	0x95AF, 0xE984, 0x95B0, 0xE985, 0x95B1, 0xE986, 0x95B2, 0xE987,
+	0x95B3, 0xE988, 0x95B4, 0xE989, 0x95B5, 0xE98A, 0x95B6, 0xE98B,
+	0x95B7, 0xE98C, 0x95B8, 0xE98D, 0x95B9, 0xE98E, 0x95BA, 0xE98F,
+	0x95BB, 0xE990, 0x95BC, 0xE991, 0x95BD, 0xE992, 0x95BE, 0xE993,
+	0x95BF, 0xE994, 0x95C0, 0xE995, 0x95C1, 0xE996, 0x95C2, 0xE997,
+	0x95C3, 0xE998, 0x95C4, 0xE999, 0x95C5, 0xE99A, 0x95C6, 0xE99B,
+	0x95C7, 0xE99C, 0x95C8, 0xE99D, 0x95C9, 0xE99E, 0x95CA, 0xE99F,
+	0x95CB, 0xE9A0, 0x95CC, 0xEA40, 0x95CD, 0xEA41, 0x95CE, 0xEA42,
+	0x95CF, 0xEA43, 0x95D0, 0xEA44, 0x95D1, 0xEA45, 0x95D2, 0xEA46,
+	0x95D3, 0xEA47, 0x95D4, 0xEA48, 0x95D5, 0xEA49, 0x95D6, 0xEA4A,
+	0x95D7, 0xEA4B, 0x95D8, 0xEA4C, 0x95D9, 0xEA4D, 0x95DA, 0xEA4E,
+	0x95DB, 0xEA4F, 0x95DC, 0xEA50, 0x95DD, 0xEA51, 0x95DE, 0xEA52,
+	0x95DF, 0xEA53, 0x95E0, 0xEA54, 0x95E1, 0xEA55, 0x95E2, 0xEA56,
+	0x95E3, 0xEA57, 0x95E4, 0xEA58, 0x95E5, 0xEA59, 0x95E6, 0xEA5A,
+	0x95E7, 0xEA5B, 0x95E8, 0xC3C5, 0x95E9, 0xE3C5, 0x95EA, 0xC9C1,
+	0x95EB, 0xE3C6, 0x95EC, 0xEA5C, 0x95ED, 0xB1D5, 0x95EE, 0xCECA,
+	0x95EF, 0xB4B3, 0x95F0, 0xC8F2, 0x95F1, 0xE3C7, 0x95F2, 0xCFD0,
+	0x95F3, 0xE3C8, 0x95F4, 0xBCE4, 0x95F5, 0xE3C9, 0x95F6, 0xE3CA,
+	0x95F7, 0xC3C6, 0x95F8, 0xD5A2, 0x95F9, 0xC4D6, 0x95FA, 0xB9EB,
+	0x95FB, 0xCEC5, 0x95FC, 0xE3CB, 0x95FD, 0xC3F6, 0x95FE, 0xE3CC,
+	0x95FF, 0xEA5D, 0x9600, 0xB7A7, 0x9601, 0xB8F3, 0x9602, 0xBAD2,
+	0x9603, 0xE3CD, 0x9604, 0xE3CE, 0x9605, 0xD4C4, 0x9606, 0xE3CF,
+	0x9607, 0xEA5E, 0x9608, 0xE3D0, 0x9609, 0xD1CB, 0x960A, 0xE3D1,
+	0x960B, 0xE3D2, 0x960C, 0xE3D3, 0x960D, 0xE3D4, 0x960E, 0xD1D6,
+	0x960F, 0xE3D5, 0x9610, 0xB2FB, 0x9611, 0xC0BB, 0x9612, 0xE3D6,
+	0x9613, 0xEA5F, 0x9614, 0xC0AB, 0x9615, 0xE3D7, 0x9616, 0xE3D8,
+	0x9617, 0xE3D9, 0x9618, 0xEA60, 0x9619, 0xE3DA, 0x961A, 0xE3DB,
+	0x961B, 0xEA61, 0x961C, 0xB8B7, 0x961D, 0xDAE2, 0x961E, 0xEA62,
+	0x961F, 0xB6D3, 0x9620, 0xEA63, 0x9621, 0xDAE4, 0x9622, 0xDAE3,
+	0x9623, 0xEA64, 0x9624, 0xEA65, 0x9625, 0xEA66, 0x9626, 0xEA67,
+	0x9627, 0xEA68, 0x9628, 0xEA69, 0x9629, 0xEA6A, 0x962A, 0xDAE6,
+	0x962B, 0xEA6B, 0x962C, 0xEA6C, 0x962D, 0xEA6D, 0x962E, 0xC8EE,
+	0x962F, 0xEA6E, 0x9630, 0xEA6F, 0x9631, 0xDAE5, 0x9632, 0xB7C0,
+	0x9633, 0xD1F4, 0x9634, 0xD2F5, 0x9635, 0xD5F3, 0x9636, 0xBDD7,
+	0x9637, 0xEA70, 0x9638, 0xEA71, 0x9639, 0xEA72, 0x963A, 0xEA73,
+	0x963B, 0xD7E8, 0x963C, 0xDAE8, 0x963D, 0xDAE7, 0x963E, 0xEA74,
+	0x963F, 0xB0A2, 0x9640, 0xCDD3, 0x9641, 0xEA75, 0x9642, 0xDAE9,
+	0x9643, 0xEA76, 0x9644, 0xB8BD, 0x9645, 0xBCCA, 0x9646, 0xC2BD,
+	0x9647, 0xC2A4, 0x9648, 0xB3C2, 0x9649, 0xDAEA, 0x964A, 0xEA77,
+	0x964B, 0xC2AA, 0x964C, 0xC4B0, 0x964D, 0xBDB5, 0x964E, 0xEA78,
+	0x964F, 0xEA79, 0x9650, 0xCFDE, 0x9651, 0xEA7A, 0x9652, 0xEA7B,
+	0x9653, 0xEA7C, 0x9654, 0xDAEB, 0x9655, 0xC9C2, 0x9656, 0xEA7D,
+	0x9657, 0xEA7E, 0x9658, 0xEA80, 0x9659, 0xEA81, 0x965A, 0xEA82,
+	0x965B, 0xB1DD, 0x965C, 0xEA83, 0x965D, 0xEA84, 0x965E, 0xEA85,
+	0x965F, 0xDAEC, 0x9660, 0xEA86, 0x9661, 0xB6B8, 0x9662, 0xD4BA,
+	0x9663, 0xEA87, 0x9664, 0xB3FD, 0x9665, 0xEA88, 0x9666, 0xEA89,
+	0x9667, 0xDAED, 0x9668, 0xD4C9, 0x9669, 0xCFD5, 0x966A, 0xC5E3,
+	0x966B, 0xEA8A, 0x966C, 0xDAEE, 0x966D, 0xEA8B, 0x966E, 0xEA8C,
+	0x966F, 0xEA8D, 0x9670, 0xEA8E, 0x9671, 0xEA8F, 0x9672, 0xDAEF,
+	0x9673, 0xEA90, 0x9674, 0xDAF0, 0x9675, 0xC1EA, 0x9676, 0xCCD5,
+	0x9677, 0xCFDD, 0x9678, 0xEA91, 0x9679, 0xEA92, 0x967A, 0xEA93,
+	0x967B, 0xEA94, 0x967C, 0xEA95, 0x967D, 0xEA96, 0x967E, 0xEA97,
+	0x967F, 0xEA98, 0x9680, 0xEA99, 0x9681, 0xEA9A, 0x9682, 0xEA9B,
+	0x9683, 0xEA9C, 0x9684, 0xEA9D, 0x9685, 0xD3E7, 0x9686, 0xC2A1,
+	0x9687, 0xEA9E, 0x9688, 0xDAF1, 0x9689, 0xEA9F, 0x968A, 0xEAA0,
+	0x968B, 0xCBE5, 0x968C, 0xEB40, 0x968D, 0xDAF2, 0x968E, 0xEB41,
+	0x968F, 0xCBE6, 0x9690, 0xD2FE, 0x9691, 0xEB42, 0x9692, 0xEB43,
+	0x9693, 0xEB44, 0x9694, 0xB8F4, 0x9695, 0xEB45, 0x9696, 0xEB46,
+	0x9697, 0xDAF3, 0x9698, 0xB0AF, 0x9699, 0xCFB6, 0x969A, 0xEB47,
+	0x969B, 0xEB48, 0x969C, 0xD5CF, 0x969D, 0xEB49, 0x969E, 0xEB4A,
+	0x969F, 0xEB4B, 0x96A0, 0xEB4C, 0x96A1, 0xEB4D, 0x96A2, 0xEB4E,
+	0x96A3, 0xEB4F, 0x96A4, 0xEB50, 0x96A5, 0xEB51, 0x96A6, 0xEB52,
+	0x96A7, 0xCBED, 0x96A8, 0xEB53, 0x96A9, 0xEB54, 0x96AA, 0xEB55,
+	0x96AB, 0xEB56, 0x96AC, 0xEB57, 0x96AD, 0xEB58, 0x96AE, 0xEB59,
+	0x96AF, 0xEB5A, 0x96B0, 0xDAF4, 0x96B1, 0xEB5B, 0x96B2, 0xEB5C,
+	0x96B3, 0xE3C4, 0x96B4, 0xEB5D, 0x96B5, 0xEB5E, 0x96B6, 0xC1A5,
+	0x96B7, 0xEB5F, 0x96B8, 0xEB60, 0x96B9, 0xF6BF, 0x96BA, 0xEB61,
+	0x96BB, 0xEB62, 0x96BC, 0xF6C0, 0x96BD, 0xF6C1, 0x96BE, 0xC4D1,
+	0x96BF, 0xEB63, 0x96C0, 0xC8B8, 0x96C1, 0xD1E3, 0x96C2, 0xEB64,
+	0x96C3, 0xEB65, 0x96C4, 0xD0DB, 0x96C5, 0xD1C5, 0x96C6, 0xBCAF,
+	0x96C7, 0xB9CD, 0x96C8, 0xEB66, 0x96C9, 0xEFF4, 0x96CA, 0xEB67,
+	0x96CB, 0xEB68, 0x96CC, 0xB4C6, 0x96CD, 0xD3BA, 0x96CE, 0xF6C2,
+	0x96CF, 0xB3FB, 0x96D0, 0xEB69, 0x96D1, 0xEB6A, 0x96D2, 0xF6C3,
+	0x96D3, 0xEB6B, 0x96D4, 0xEB6C, 0x96D5, 0xB5F1, 0x96D6, 0xEB6D,
+	0x96D7, 0xEB6E, 0x96D8, 0xEB6F, 0x96D9, 0xEB70, 0x96DA, 0xEB71,
+	0x96DB, 0xEB72, 0x96DC, 0xEB73, 0x96DD, 0xEB74, 0x96DE, 0xEB75,
+	0x96DF, 0xEB76, 0x96E0, 0xF6C5, 0x96E1, 0xEB77, 0x96E2, 0xEB78,
+	0x96E3, 0xEB79, 0x96E4, 0xEB7A, 0x96E5, 0xEB7B, 0x96E6, 0xEB7C,
+	0x96E7, 0xEB7D, 0x96E8, 0xD3EA, 0x96E9, 0xF6A7, 0x96EA, 0xD1A9,
+	0x96EB, 0xEB7E, 0x96EC, 0xEB80, 0x96ED, 0xEB81, 0x96EE, 0xEB82,
+	0x96EF, 0xF6A9, 0x96F0, 0xEB83, 0x96F1, 0xEB84, 0x96F2, 0xEB85,
+	0x96F3, 0xF6A8, 0x96F4, 0xEB86, 0x96F5, 0xEB87, 0x96F6, 0xC1E3,
+	0x96F7, 0xC0D7, 0x96F8, 0xEB88, 0x96F9, 0xB1A2, 0x96FA, 0xEB89,
+	0x96FB, 0xEB8A, 0x96FC, 0xEB8B, 0x96FD, 0xEB8C, 0x96FE, 0xCEED,
+	0x96FF, 0xEB8D, 0x9700, 0xD0E8, 0x9701, 0xF6AB, 0x9702, 0xEB8E,
+	0x9703, 0xEB8F, 0x9704, 0xCFF6, 0x9705, 0xEB90, 0x9706, 0xF6AA,
+	0x9707, 0xD5F0, 0x9708, 0xF6AC, 0x9709, 0xC3B9, 0x970A, 0xEB91,
+	0x970B, 0xEB92, 0x970C, 0xEB93, 0x970D, 0xBBF4, 0x970E, 0xF6AE,
+	0x970F, 0xF6AD, 0x9710, 0xEB94, 0x9711, 0xEB95, 0x9712, 0xEB96,
+	0x9713, 0xC4DE, 0x9714, 0xEB97, 0x9715, 0xEB98, 0x9716, 0xC1D8,
+	0x9717, 0xEB99, 0x9718, 0xEB9A, 0x9719, 0xEB9B, 0x971A, 0xEB9C,
+	0x971B, 0xEB9D, 0x971C, 0xCBAA, 0x971D, 0xEB9E, 0x971E, 0xCFBC,
+	0x971F, 0xEB9F, 0x9720, 0xEBA0, 0x9721, 0xEC40, 0x9722, 0xEC41,
+	0x9723, 0xEC42, 0x9724, 0xEC43, 0x9725, 0xEC44, 0x9726, 0xEC45,
+	0x9727, 0xEC46, 0x9728, 0xEC47, 0x9729, 0xEC48, 0x972A, 0xF6AF,
+	0x972B, 0xEC49, 0x972C, 0xEC4A, 0x972D, 0xF6B0, 0x972E, 0xEC4B,
+	0x972F, 0xEC4C, 0x9730, 0xF6B1, 0x9731, 0xEC4D, 0x9732, 0xC2B6,
+	0x9733, 0xEC4E, 0x9734, 0xEC4F, 0x9735, 0xEC50, 0x9736, 0xEC51,
+	0x9737, 0xEC52, 0x9738, 0xB0D4, 0x9739, 0xC5F9, 0x973A, 0xEC53,
+	0x973B, 0xEC54, 0x973C, 0xEC55, 0x973D, 0xEC56, 0x973E, 0xF6B2,
+	0x973F, 0xEC57, 0x9740, 0xEC58, 0x9741, 0xEC59, 0x9742, 0xEC5A,
+	0x9743, 0xEC5B, 0x9744, 0xEC5C, 0x9745, 0xEC5D, 0x9746, 0xEC5E,
+	0x9747, 0xEC5F, 0x9748, 0xEC60, 0x9749, 0xEC61, 0x974A, 0xEC62,
+	0x974B, 0xEC63, 0x974C, 0xEC64, 0x974D, 0xEC65, 0x974E, 0xEC66,
+	0x974F, 0xEC67, 0x9750, 0xEC68, 0x9751, 0xEC69, 0x9752, 0xC7E0,
+	0x9753, 0xF6A6, 0x9754, 0xEC6A, 0x9755, 0xEC6B, 0x9756, 0xBEB8,
+	0x9757, 0xEC6C, 0x9758, 0xEC6D, 0x9759, 0xBEB2, 0x975A, 0xEC6E,
+	0x975B, 0xB5E5, 0x975C, 0xEC6F, 0x975D, 0xEC70, 0x975E, 0xB7C7,
+	0x975F, 0xEC71, 0x9760, 0xBFBF, 0x9761, 0xC3D2, 0x9762, 0xC3E6,
+	0x9763, 0xEC72, 0x9764, 0xEC73, 0x9765, 0xD8CC, 0x9766, 0xEC74,
+	0x9767, 0xEC75, 0x9768, 0xEC76, 0x9769, 0xB8EF, 0x976A, 0xEC77,
+	0x976B, 0xEC78, 0x976C, 0xEC79, 0x976D, 0xEC7A, 0x976E, 0xEC7B,
+	0x976F, 0xEC7C, 0x9770, 0xEC7D, 0x9771, 0xEC7E, 0x9772, 0xEC80,
+	0x9773, 0xBDF9, 0x9774, 0xD1A5, 0x9775, 0xEC81, 0x9776, 0xB0D0,
+	0x9777, 0xEC82, 0x9778, 0xEC83, 0x9779, 0xEC84, 0x977A, 0xEC85,
+	0x977B, 0xEC86, 0x977C, 0xF7B0, 0x977D, 0xEC87, 0x977E, 0xEC88,
+	0x977F, 0xEC89, 0x9780, 0xEC8A, 0x9781, 0xEC8B, 0x9782, 0xEC8C,
+	0x9783, 0xEC8D, 0x9784, 0xEC8E, 0x9785, 0xF7B1, 0x9786, 0xEC8F,
+	0x9787, 0xEC90, 0x9788, 0xEC91, 0x9789, 0xEC92, 0x978A, 0xEC93,
+	0x978B, 0xD0AC, 0x978C, 0xEC94, 0x978D, 0xB0B0, 0x978E, 0xEC95,
+	0x978F, 0xEC96, 0x9790, 0xEC97, 0x9791, 0xF7B2, 0x9792, 0xF7B3,
+	0x9793, 0xEC98, 0x9794, 0xF7B4, 0x9795, 0xEC99, 0x9796, 0xEC9A,
+	0x9797, 0xEC9B, 0x9798, 0xC7CA, 0x9799, 0xEC9C, 0x979A, 0xEC9D,
+	0x979B, 0xEC9E, 0x979C, 0xEC9F, 0x979D, 0xECA0, 0x979E, 0xED40,
+	0x979F, 0xED41, 0x97A0, 0xBECF, 0x97A1, 0xED42, 0x97A2, 0xED43,
+	0x97A3, 0xF7B7, 0x97A4, 0xED44, 0x97A5, 0xED45, 0x97A6, 0xED46,
+	0x97A7, 0xED47, 0x97A8, 0xED48, 0x97A9, 0xED49, 0x97AA, 0xED4A,
+	0x97AB, 0xF7B6, 0x97AC, 0xED4B, 0x97AD, 0xB1DE, 0x97AE, 0xED4C,
+	0x97AF, 0xF7B5, 0x97B0, 0xED4D, 0x97B1, 0xED4E, 0x97B2, 0xF7B8,
+	0x97B3, 0xED4F, 0x97B4, 0xF7B9, 0x97B5, 0xED50, 0x97B6, 0xED51,
+	0x97B7, 0xED52, 0x97B8, 0xED53, 0x97B9, 0xED54, 0x97BA, 0xED55,
+	0x97BB, 0xED56, 0x97BC, 0xED57, 0x97BD, 0xED58, 0x97BE, 0xED59,
+	0x97BF, 0xED5A, 0x97C0, 0xED5B, 0x97C1, 0xED5C, 0x97C2, 0xED5D,
+	0x97C3, 0xED5E, 0x97C4, 0xED5F, 0x97C5, 0xED60, 0x97C6, 0xED61,
+	0x97C7, 0xED62, 0x97C8, 0xED63, 0x97C9, 0xED64, 0x97CA, 0xED65,
+	0x97CB, 0xED66, 0x97CC, 0xED67, 0x97CD, 0xED68, 0x97CE, 0xED69,
+	0x97CF, 0xED6A, 0x97D0, 0xED6B, 0x97D1, 0xED6C, 0x97D2, 0xED6D,
+	0x97D3, 0xED6E, 0x97D4, 0xED6F, 0x97D5, 0xED70, 0x97D6, 0xED71,
+	0x97D7, 0xED72, 0x97D8, 0xED73, 0x97D9, 0xED74, 0x97DA, 0xED75,
+	0x97DB, 0xED76, 0x97DC, 0xED77, 0x97DD, 0xED78, 0x97DE, 0xED79,
+	0x97DF, 0xED7A, 0x97E0, 0xED7B, 0x97E1, 0xED7C, 0x97E2, 0xED7D,
+	0x97E3, 0xED7E, 0x97E4, 0xED80, 0x97E5, 0xED81, 0x97E6, 0xCEA4,
+	0x97E7, 0xC8CD, 0x97E8, 0xED82, 0x97E9, 0xBAAB, 0x97EA, 0xE8B8,
+	0x97EB, 0xE8B9, 0x97EC, 0xE8BA, 0x97ED, 0xBEC2, 0x97EE, 0xED83,
+	0x97EF, 0xED84, 0x97F0, 0xED85, 0x97F1, 0xED86, 0x97F2, 0xED87,
+	0x97F3, 0xD2F4, 0x97F4, 0xED88, 0x97F5, 0xD4CF, 0x97F6, 0xC9D8,
+	0x97F7, 0xED89, 0x97F8, 0xED8A, 0x97F9, 0xED8B, 0x97FA, 0xED8C,
+	0x97FB, 0xED8D, 0x97FC, 0xED8E, 0x97FD, 0xED8F, 0x97FE, 0xED90,
+	0x97FF, 0xED91, 0x9800, 0xED92, 0x9801, 0xED93, 0x9802, 0xED94,
+	0x9803, 0xED95, 0x9804, 0xED96, 0x9805, 0xED97, 0x9806, 0xED98,
+	0x9807, 0xED99, 0x9808, 0xED9A, 0x9809, 0xED9B, 0x980A, 0xED9C,
+	0x980B, 0xED9D, 0x980C, 0xED9E, 0x980D, 0xED9F, 0x980E, 0xEDA0,
+	0x980F, 0xEE40, 0x9810, 0xEE41, 0x9811, 0xEE42, 0x9812, 0xEE43,
+	0x9813, 0xEE44, 0x9814, 0xEE45, 0x9815, 0xEE46, 0x9816, 0xEE47,
+	0x9817, 0xEE48, 0x9818, 0xEE49, 0x9819, 0xEE4A, 0x981A, 0xEE4B,
+	0x981B, 0xEE4C, 0x981C, 0xEE4D, 0x981D, 0xEE4E, 0x981E, 0xEE4F,
+	0x981F, 0xEE50, 0x9820, 0xEE51, 0x9821, 0xEE52, 0x9822, 0xEE53,
+	0x9823, 0xEE54, 0x9824, 0xEE55, 0x9825, 0xEE56, 0x9826, 0xEE57,
+	0x9827, 0xEE58, 0x9828, 0xEE59, 0x9829, 0xEE5A, 0x982A, 0xEE5B,
+	0x982B, 0xEE5C, 0x982C, 0xEE5D, 0x982D, 0xEE5E, 0x982E, 0xEE5F,
+	0x982F, 0xEE60, 0x9830, 0xEE61, 0x9831, 0xEE62, 0x9832, 0xEE63,
+	0x9833, 0xEE64, 0x9834, 0xEE65, 0x9835, 0xEE66, 0x9836, 0xEE67,
+	0x9837, 0xEE68, 0x9838, 0xEE69, 0x9839, 0xEE6A, 0x983A, 0xEE6B,
+	0x983B, 0xEE6C, 0x983C, 0xEE6D, 0x983D, 0xEE6E, 0x983E, 0xEE6F,
+	0x983F, 0xEE70, 0x9840, 0xEE71, 0x9841, 0xEE72, 0x9842, 0xEE73,
+	0x9843, 0xEE74, 0x9844, 0xEE75, 0x9845, 0xEE76, 0x9846, 0xEE77,
+	0x9847, 0xEE78, 0x9848, 0xEE79, 0x9849, 0xEE7A, 0x984A, 0xEE7B,
+	0x984B, 0xEE7C, 0x984C, 0xEE7D, 0x984D, 0xEE7E, 0x984E, 0xEE80,
+	0x984F, 0xEE81, 0x9850, 0xEE82, 0x9851, 0xEE83, 0x9852, 0xEE84,
+	0x9853, 0xEE85, 0x9854, 0xEE86, 0x9855, 0xEE87, 0x9856, 0xEE88,
+	0x9857, 0xEE89, 0x9858, 0xEE8A, 0x9859, 0xEE8B, 0x985A, 0xEE8C,
+	0x985B, 0xEE8D, 0x985C, 0xEE8E, 0x985D, 0xEE8F, 0x985E, 0xEE90,
+	0x985F, 0xEE91, 0x9860, 0xEE92, 0x9861, 0xEE93, 0x9862, 0xEE94,
+	0x9863, 0xEE95, 0x9864, 0xEE96, 0x9865, 0xEE97, 0x9866, 0xEE98,
+	0x9867, 0xEE99, 0x9868, 0xEE9A, 0x9869, 0xEE9B, 0x986A, 0xEE9C,
+	0x986B, 0xEE9D, 0x986C, 0xEE9E, 0x986D, 0xEE9F, 0x986E, 0xEEA0,
+	0x986F, 0xEF40, 0x9870, 0xEF41, 0x9871, 0xEF42, 0x9872, 0xEF43,
+	0x9873, 0xEF44, 0x9874, 0xEF45, 0x9875, 0xD2B3, 0x9876, 0xB6A5,
+	0x9877, 0xC7EA, 0x9878, 0xF1FC, 0x9879, 0xCFEE, 0x987A, 0xCBB3,
+	0x987B, 0xD0EB, 0x987C, 0xE7EF, 0x987D, 0xCDE7, 0x987E, 0xB9CB,
+	0x987F, 0xB6D9, 0x9880, 0xF1FD, 0x9881, 0xB0E4, 0x9882, 0xCBCC,
+	0x9883, 0xF1FE, 0x9884, 0xD4A4, 0x9885, 0xC2AD, 0x9886, 0xC1EC,
+	0x9887, 0xC6C4, 0x9888, 0xBEB1, 0x9889, 0xF2A1, 0x988A, 0xBCD5,
+	0x988B, 0xEF46, 0x988C, 0xF2A2, 0x988D, 0xF2A3, 0x988E, 0xEF47,
+	0x988F, 0xF2A4, 0x9890, 0xD2C3, 0x9891, 0xC6B5, 0x9892, 0xEF48,
+	0x9893, 0xCDC7, 0x9894, 0xF2A5, 0x9895, 0xEF49, 0x9896, 0xD3B1,
+	0x9897, 0xBFC5, 0x9898, 0xCCE2, 0x9899, 0xEF4A, 0x989A, 0xF2A6,
+	0x989B, 0xF2A7, 0x989C, 0xD1D5, 0x989D, 0xB6EE, 0x989E, 0xF2A8,
+	0x989F, 0xF2A9, 0x98A0, 0xB5DF, 0x98A1, 0xF2AA, 0x98A2, 0xF2AB,
+	0x98A3, 0xEF4B, 0x98A4, 0xB2FC, 0x98A5, 0xF2AC, 0x98A6, 0xF2AD,
+	0x98A7, 0xC8A7, 0x98A8, 0xEF4C, 0x98A9, 0xEF4D, 0x98AA, 0xEF4E,
+	0x98AB, 0xEF4F, 0x98AC, 0xEF50, 0x98AD, 0xEF51, 0x98AE, 0xEF52,
+	0x98AF, 0xEF53, 0x98B0, 0xEF54, 0x98B1, 0xEF55, 0x98B2, 0xEF56,
+	0x98B3, 0xEF57, 0x98B4, 0xEF58, 0x98B5, 0xEF59, 0x98B6, 0xEF5A,
+	0x98B7, 0xEF5B, 0x98B8, 0xEF5C, 0x98B9, 0xEF5D, 0x98BA, 0xEF5E,
+	0x98BB, 0xEF5F, 0x98BC, 0xEF60, 0x98BD, 0xEF61, 0x98BE, 0xEF62,
+	0x98BF, 0xEF63, 0x98C0, 0xEF64, 0x98C1, 0xEF65, 0x98C2, 0xEF66,
+	0x98C3, 0xEF67, 0x98C4, 0xEF68, 0x98C5, 0xEF69, 0x98C6, 0xEF6A,
+	0x98C7, 0xEF6B, 0x98C8, 0xEF6C, 0x98C9, 0xEF6D, 0x98CA, 0xEF6E,
+	0x98CB, 0xEF6F, 0x98CC, 0xEF70, 0x98CD, 0xEF71, 0x98CE, 0xB7E7,
+	0x98CF, 0xEF72, 0x98D0, 0xEF73, 0x98D1, 0xECA9, 0x98D2, 0xECAA,
+	0x98D3, 0xECAB, 0x98D4, 0xEF74, 0x98D5, 0xECAC, 0x98D6, 0xEF75,
+	0x98D7, 0xEF76, 0x98D8, 0xC6AE, 0x98D9, 0xECAD, 0x98DA, 0xECAE,
+	0x98DB, 0xEF77, 0x98DC, 0xEF78, 0x98DD, 0xEF79, 0x98DE, 0xB7C9,
+	0x98DF, 0xCAB3, 0x98E0, 0xEF7A, 0x98E1, 0xEF7B, 0x98E2, 0xEF7C,
+	0x98E3, 0xEF7D, 0x98E4, 0xEF7E, 0x98E5, 0xEF80, 0x98E6, 0xEF81,
+	0x98E7, 0xE2B8, 0x98E8, 0xF7CF, 0x98E9, 0xEF82, 0x98EA, 0xEF83,
+	0x98EB, 0xEF84, 0x98EC, 0xEF85, 0x98ED, 0xEF86, 0x98EE, 0xEF87,
+	0x98EF, 0xEF88, 0x98F0, 0xEF89, 0x98F1, 0xEF8A, 0x98F2, 0xEF8B,
+	0x98F3, 0xEF8C, 0x98F4, 0xEF8D, 0x98F5, 0xEF8E, 0x98F6, 0xEF8F,
+	0x98F7, 0xEF90, 0x98F8, 0xEF91, 0x98F9, 0xEF92, 0x98FA, 0xEF93,
+	0x98FB, 0xEF94, 0x98FC, 0xEF95, 0x98FD, 0xEF96, 0x98FE, 0xEF97,
+	0x98FF, 0xEF98, 0x9900, 0xEF99, 0x9901, 0xEF9A, 0x9902, 0xEF9B,
+	0x9903, 0xEF9C, 0x9904, 0xEF9D, 0x9905, 0xEF9E, 0x9906, 0xEF9F,
+	0x9907, 0xEFA0, 0x9908, 0xF040, 0x9909, 0xF041, 0x990A, 0xF042,
+	0x990B, 0xF043, 0x990C, 0xF044, 0x990D, 0xF7D0, 0x990E, 0xF045,
+	0x990F, 0xF046, 0x9910, 0xB2CD, 0x9911, 0xF047, 0x9912, 0xF048,
+	0x9913, 0xF049, 0x9914, 0xF04A, 0x9915, 0xF04B, 0x9916, 0xF04C,
+	0x9917, 0xF04D, 0x9918, 0xF04E, 0x9919, 0xF04F, 0x991A, 0xF050,
+	0x991B, 0xF051, 0x991C, 0xF052, 0x991D, 0xF053, 0x991E, 0xF054,
+	0x991F, 0xF055, 0x9920, 0xF056, 0x9921, 0xF057, 0x9922, 0xF058,
+	0x9923, 0xF059, 0x9924, 0xF05A, 0x9925, 0xF05B, 0x9926, 0xF05C,
+	0x9927, 0xF05D, 0x9928, 0xF05E, 0x9929, 0xF05F, 0x992A, 0xF060,
+	0x992B, 0xF061, 0x992C, 0xF062, 0x992D, 0xF063, 0x992E, 0xF7D1,
+	0x992F, 0xF064, 0x9930, 0xF065, 0x9931, 0xF066, 0x9932, 0xF067,
+	0x9933, 0xF068, 0x9934, 0xF069, 0x9935, 0xF06A, 0x9936, 0xF06B,
+	0x9937, 0xF06C, 0x9938, 0xF06D, 0x9939, 0xF06E, 0x993A, 0xF06F,
+	0x993B, 0xF070, 0x993C, 0xF071, 0x993D, 0xF072, 0x993E, 0xF073,
+	0x993F, 0xF074, 0x9940, 0xF075, 0x9941, 0xF076, 0x9942, 0xF077,
+	0x9943, 0xF078, 0x9944, 0xF079, 0x9945, 0xF07A, 0x9946, 0xF07B,
+	0x9947, 0xF07C, 0x9948, 0xF07D, 0x9949, 0xF07E, 0x994A, 0xF080,
+	0x994B, 0xF081, 0x994C, 0xF082, 0x994D, 0xF083, 0x994E, 0xF084,
+	0x994F, 0xF085, 0x9950, 0xF086, 0x9951, 0xF087, 0x9952, 0xF088,
+	0x9953, 0xF089, 0x9954, 0xF7D3, 0x9955, 0xF7D2, 0x9956, 0xF08A,
+	0x9957, 0xF08B, 0x9958, 0xF08C, 0x9959, 0xF08D, 0x995A, 0xF08E,
+	0x995B, 0xF08F, 0x995C, 0xF090, 0x995D, 0xF091, 0x995E, 0xF092,
+	0x995F, 0xF093, 0x9960, 0xF094, 0x9961, 0xF095, 0x9962, 0xF096,
+	0x9963, 0xE2BB, 0x9964, 0xF097, 0x9965, 0xBCA2, 0x9966, 0xF098,
+	0x9967, 0xE2BC, 0x9968, 0xE2BD, 0x9969, 0xE2BE, 0x996A, 0xE2BF,
+	0x996B, 0xE2C0, 0x996C, 0xE2C1, 0x996D, 0xB7B9, 0x996E, 0xD2FB,
+	0x996F, 0xBDA4, 0x9970, 0xCACE, 0x9971, 0xB1A5, 0x9972, 0xCBC7,
+	0x9973, 0xF099, 0x9974, 0xE2C2, 0x9975, 0xB6FC, 0x9976, 0xC8C4,
+	0x9977, 0xE2C3, 0x9978, 0xF09A, 0x9979, 0xF09B, 0x997A, 0xBDC8,
+	0x997B, 0xF09C, 0x997C, 0xB1FD, 0x997D, 0xE2C4, 0x997E, 0xF09D,
+	0x997F, 0xB6F6, 0x9980, 0xE2C5, 0x9981, 0xC4D9, 0x9982, 0xF09E,
+	0x9983, 0xF09F, 0x9984, 0xE2C6, 0x9985, 0xCFDA, 0x9986, 0xB9DD,
+	0x9987, 0xE2C7, 0x9988, 0xC0A1, 0x9989, 0xF0A0, 0x998A, 0xE2C8,
+	0x998B, 0xB2F6, 0x998C, 0xF140, 0x998D, 0xE2C9, 0x998E, 0xF141,
+	0x998F, 0xC1F3, 0x9990, 0xE2CA, 0x9991, 0xE2CB, 0x9992, 0xC2F8,
+	0x9993, 0xE2CC, 0x9994, 0xE2CD, 0x9995, 0xE2CE, 0x9996, 0xCAD7,
+	0x9997, 0xD8B8, 0x9998, 0xD9E5, 0x9999, 0xCFE3, 0x999A, 0xF142,
+	0x999B, 0xF143, 0x999C, 0xF144, 0x999D, 0xF145, 0x999E, 0xF146,
+	0x999F, 0xF147, 0x99A0, 0xF148, 0x99A1, 0xF149, 0x99A2, 0xF14A,
+	0x99A3, 0xF14B, 0x99A4, 0xF14C, 0x99A5, 0xF0A5, 0x99A6, 0xF14D,
+	0x99A7, 0xF14E, 0x99A8, 0xDCB0, 0x99A9, 0xF14F, 0x99AA, 0xF150,
+	0x99AB, 0xF151, 0x99AC, 0xF152, 0x99AD, 0xF153, 0x99AE, 0xF154,
+	0x99AF, 0xF155, 0x99B0, 0xF156, 0x99B1, 0xF157, 0x99B2, 0xF158,
+	0x99B3, 0xF159, 0x99B4, 0xF15A, 0x99B5, 0xF15B, 0x99B6, 0xF15C,
+	0x99B7, 0xF15D, 0x99B8, 0xF15E, 0x99B9, 0xF15F, 0x99BA, 0xF160,
+	0x99BB, 0xF161, 0x99BC, 0xF162, 0x99BD, 0xF163, 0x99BE, 0xF164,
+	0x99BF, 0xF165, 0x99C0, 0xF166, 0x99C1, 0xF167, 0x99C2, 0xF168,
+	0x99C3, 0xF169, 0x99C4, 0xF16A, 0x99C5, 0xF16B, 0x99C6, 0xF16C,
+	0x99C7, 0xF16D, 0x99C8, 0xF16E, 0x99C9, 0xF16F, 0x99CA, 0xF170,
+	0x99CB, 0xF171, 0x99CC, 0xF172, 0x99CD, 0xF173, 0x99CE, 0xF174,
+	0x99CF, 0xF175, 0x99D0, 0xF176, 0x99D1, 0xF177, 0x99D2, 0xF178,
+	0x99D3, 0xF179, 0x99D4, 0xF17A, 0x99D5, 0xF17B, 0x99D6, 0xF17C,
+	0x99D7, 0xF17D, 0x99D8, 0xF17E, 0x99D9, 0xF180, 0x99DA, 0xF181,
+	0x99DB, 0xF182, 0x99DC, 0xF183, 0x99DD, 0xF184, 0x99DE, 0xF185,
+	0x99DF, 0xF186, 0x99E0, 0xF187, 0x99E1, 0xF188, 0x99E2, 0xF189,
+	0x99E3, 0xF18A, 0x99E4, 0xF18B, 0x99E5, 0xF18C, 0x99E6, 0xF18D,
+	0x99E7, 0xF18E, 0x99E8, 0xF18F, 0x99E9, 0xF190, 0x99EA, 0xF191,
+	0x99EB, 0xF192, 0x99EC, 0xF193, 0x99ED, 0xF194, 0x99EE, 0xF195,
+	0x99EF, 0xF196, 0x99F0, 0xF197, 0x99F1, 0xF198, 0x99F2, 0xF199,
+	0x99F3, 0xF19A, 0x99F4, 0xF19B, 0x99F5, 0xF19C, 0x99F6, 0xF19D,
+	0x99F7, 0xF19E, 0x99F8, 0xF19F, 0x99F9, 0xF1A0, 0x99FA, 0xF240,
+	0x99FB, 0xF241, 0x99FC, 0xF242, 0x99FD, 0xF243, 0x99FE, 0xF244,
+	0x99FF, 0xF245, 0x9A00, 0xF246, 0x9A01, 0xF247, 0x9A02, 0xF248,
+	0x9A03, 0xF249, 0x9A04, 0xF24A, 0x9A05, 0xF24B, 0x9A06, 0xF24C,
+	0x9A07, 0xF24D, 0x9A08, 0xF24E, 0x9A09, 0xF24F, 0x9A0A, 0xF250,
+	0x9A0B, 0xF251, 0x9A0C, 0xF252, 0x9A0D, 0xF253, 0x9A0E, 0xF254,
+	0x9A0F, 0xF255, 0x9A10, 0xF256, 0x9A11, 0xF257, 0x9A12, 0xF258,
+	0x9A13, 0xF259, 0x9A14, 0xF25A, 0x9A15, 0xF25B, 0x9A16, 0xF25C,
+	0x9A17, 0xF25D, 0x9A18, 0xF25E, 0x9A19, 0xF25F, 0x9A1A, 0xF260,
+	0x9A1B, 0xF261, 0x9A1C, 0xF262, 0x9A1D, 0xF263, 0x9A1E, 0xF264,
+	0x9A1F, 0xF265, 0x9A20, 0xF266, 0x9A21, 0xF267, 0x9A22, 0xF268,
+	0x9A23, 0xF269, 0x9A24, 0xF26A, 0x9A25, 0xF26B, 0x9A26, 0xF26C,
+	0x9A27, 0xF26D, 0x9A28, 0xF26E, 0x9A29, 0xF26F, 0x9A2A, 0xF270,
+	0x9A2B, 0xF271, 0x9A2C, 0xF272, 0x9A2D, 0xF273, 0x9A2E, 0xF274,
+	0x9A2F, 0xF275, 0x9A30, 0xF276, 0x9A31, 0xF277, 0x9A32, 0xF278,
+	0x9A33, 0xF279, 0x9A34, 0xF27A, 0x9A35, 0xF27B, 0x9A36, 0xF27C,
+	0x9A37, 0xF27D, 0x9A38, 0xF27E, 0x9A39, 0xF280, 0x9A3A, 0xF281,
+	0x9A3B, 0xF282, 0x9A3C, 0xF283, 0x9A3D, 0xF284, 0x9A3E, 0xF285,
+	0x9A3F, 0xF286, 0x9A40, 0xF287, 0x9A41, 0xF288, 0x9A42, 0xF289,
+	0x9A43, 0xF28A, 0x9A44, 0xF28B, 0x9A45, 0xF28C, 0x9A46, 0xF28D,
+	0x9A47, 0xF28E, 0x9A48, 0xF28F, 0x9A49, 0xF290, 0x9A4A, 0xF291,
+	0x9A4B, 0xF292, 0x9A4C, 0xF293, 0x9A4D, 0xF294, 0x9A4E, 0xF295,
+	0x9A4F, 0xF296, 0x9A50, 0xF297, 0x9A51, 0xF298, 0x9A52, 0xF299,
+	0x9A53, 0xF29A, 0x9A54, 0xF29B, 0x9A55, 0xF29C, 0x9A56, 0xF29D,
+	0x9A57, 0xF29E, 0x9A58, 0xF29F, 0x9A59, 0xF2A0, 0x9A5A, 0xF340,
+	0x9A5B, 0xF341, 0x9A5C, 0xF342, 0x9A5D, 0xF343, 0x9A5E, 0xF344,
+	0x9A5F, 0xF345, 0x9A60, 0xF346, 0x9A61, 0xF347, 0x9A62, 0xF348,
+	0x9A63, 0xF349, 0x9A64, 0xF34A, 0x9A65, 0xF34B, 0x9A66, 0xF34C,
+	0x9A67, 0xF34D, 0x9A68, 0xF34E, 0x9A69, 0xF34F, 0x9A6A, 0xF350,
+	0x9A6B, 0xF351, 0x9A6C, 0xC2ED, 0x9A6D, 0xD4A6, 0x9A6E, 0xCDD4,
+	0x9A6F, 0xD1B1, 0x9A70, 0xB3DB, 0x9A71, 0xC7FD, 0x9A72, 0xF352,
+	0x9A73, 0xB2B5, 0x9A74, 0xC2BF, 0x9A75, 0xE6E0, 0x9A76, 0xCABB,
+	0x9A77, 0xE6E1, 0x9A78, 0xE6E2, 0x9A79, 0xBED4, 0x9A7A, 0xE6E3,
+	0x9A7B, 0xD7A4, 0x9A7C, 0xCDD5, 0x9A7D, 0xE6E5, 0x9A7E, 0xBCDD,
+	0x9A7F, 0xE6E4, 0x9A80, 0xE6E6, 0x9A81, 0xE6E7, 0x9A82, 0xC2EE,
+	0x9A83, 0xF353, 0x9A84, 0xBDBE, 0x9A85, 0xE6E8, 0x9A86, 0xC2E6,
+	0x9A87, 0xBAA7, 0x9A88, 0xE6E9, 0x9A89, 0xF354, 0x9A8A, 0xE6EA,
+	0x9A8B, 0xB3D2, 0x9A8C, 0xD1E9, 0x9A8D, 0xF355, 0x9A8E, 0xF356,
+	0x9A8F, 0xBFA5, 0x9A90, 0xE6EB, 0x9A91, 0xC6EF, 0x9A92, 0xE6EC,
+	0x9A93, 0xE6ED, 0x9A94, 0xF357, 0x9A95, 0xF358, 0x9A96, 0xE6EE,
+	0x9A97, 0xC6AD, 0x9A98, 0xE6EF, 0x9A99, 0xF359, 0x9A9A, 0xC9A7,
+	0x9A9B, 0xE6F0, 0x9A9C, 0xE6F1, 0x9A9D, 0xE6F2, 0x9A9E, 0xE5B9,
+	0x9A9F, 0xE6F3, 0x9AA0, 0xE6F4, 0x9AA1, 0xC2E2, 0x9AA2, 0xE6F5,
+	0x9AA3, 0xE6F6, 0x9AA4, 0xD6E8, 0x9AA5, 0xE6F7, 0x9AA6, 0xF35A,
+	0x9AA7, 0xE6F8, 0x9AA8, 0xB9C7, 0x9AA9, 0xF35B, 0x9AAA, 0xF35C,
+	0x9AAB, 0xF35D, 0x9AAC, 0xF35E, 0x9AAD, 0xF35F, 0x9AAE, 0xF360,
+	0x9AAF, 0xF361, 0x9AB0, 0xF7BB, 0x9AB1, 0xF7BA, 0x9AB2, 0xF362,
+	0x9AB3, 0xF363, 0x9AB4, 0xF364, 0x9AB5, 0xF365, 0x9AB6, 0xF7BE,
+	0x9AB7, 0xF7BC, 0x9AB8, 0xBAA1, 0x9AB9, 0xF366, 0x9ABA, 0xF7BF,
+	0x9ABB, 0xF367, 0x9ABC, 0xF7C0, 0x9ABD, 0xF368, 0x9ABE, 0xF369,
+	0x9ABF, 0xF36A, 0x9AC0, 0xF7C2, 0x9AC1, 0xF7C1, 0x9AC2, 0xF7C4,
+	0x9AC3, 0xF36B, 0x9AC4, 0xF36C, 0x9AC5, 0xF7C3, 0x9AC6, 0xF36D,
+	0x9AC7, 0xF36E, 0x9AC8, 0xF36F, 0x9AC9, 0xF370, 0x9ACA, 0xF371,
+	0x9ACB, 0xF7C5, 0x9ACC, 0xF7C6, 0x9ACD, 0xF372, 0x9ACE, 0xF373,
+	0x9ACF, 0xF374, 0x9AD0, 0xF375, 0x9AD1, 0xF7C7, 0x9AD2, 0xF376,
+	0x9AD3, 0xCBE8, 0x9AD4, 0xF377, 0x9AD5, 0xF378, 0x9AD6, 0xF379,
+	0x9AD7, 0xF37A, 0x9AD8, 0xB8DF, 0x9AD9, 0xF37B, 0x9ADA, 0xF37C,
+	0x9ADB, 0xF37D, 0x9ADC, 0xF37E, 0x9ADD, 0xF380, 0x9ADE, 0xF381,
+	0x9ADF, 0xF7D4, 0x9AE0, 0xF382, 0x9AE1, 0xF7D5, 0x9AE2, 0xF383,
+	0x9AE3, 0xF384, 0x9AE4, 0xF385, 0x9AE5, 0xF386, 0x9AE6, 0xF7D6,
+	0x9AE7, 0xF387, 0x9AE8, 0xF388, 0x9AE9, 0xF389, 0x9AEA, 0xF38A,
+	0x9AEB, 0xF7D8, 0x9AEC, 0xF38B, 0x9AED, 0xF7DA, 0x9AEE, 0xF38C,
+	0x9AEF, 0xF7D7, 0x9AF0, 0xF38D, 0x9AF1, 0xF38E, 0x9AF2, 0xF38F,
+	0x9AF3, 0xF390, 0x9AF4, 0xF391, 0x9AF5, 0xF392, 0x9AF6, 0xF393,
+	0x9AF7, 0xF394, 0x9AF8, 0xF395, 0x9AF9, 0xF7DB, 0x9AFA, 0xF396,
+	0x9AFB, 0xF7D9, 0x9AFC, 0xF397, 0x9AFD, 0xF398, 0x9AFE, 0xF399,
+	0x9AFF, 0xF39A, 0x9B00, 0xF39B, 0x9B01, 0xF39C, 0x9B02, 0xF39D,
+	0x9B03, 0xD7D7, 0x9B04, 0xF39E, 0x9B05, 0xF39F, 0x9B06, 0xF3A0,
+	0x9B07, 0xF440, 0x9B08, 0xF7DC, 0x9B09, 0xF441, 0x9B0A, 0xF442,
+	0x9B0B, 0xF443, 0x9B0C, 0xF444, 0x9B0D, 0xF445, 0x9B0E, 0xF446,
+	0x9B0F, 0xF7DD, 0x9B10, 0xF447, 0x9B11, 0xF448, 0x9B12, 0xF449,
+	0x9B13, 0xF7DE, 0x9B14, 0xF44A, 0x9B15, 0xF44B, 0x9B16, 0xF44C,
+	0x9B17, 0xF44D, 0x9B18, 0xF44E, 0x9B19, 0xF44F, 0x9B1A, 0xF450,
+	0x9B1B, 0xF451, 0x9B1C, 0xF452, 0x9B1D, 0xF453, 0x9B1E, 0xF454,
+	0x9B1F, 0xF7DF, 0x9B20, 0xF455, 0x9B21, 0xF456, 0x9B22, 0xF457,
+	0x9B23, 0xF7E0, 0x9B24, 0xF458, 0x9B25, 0xF459, 0x9B26, 0xF45A,
+	0x9B27, 0xF45B, 0x9B28, 0xF45C, 0x9B29, 0xF45D, 0x9B2A, 0xF45E,
+	0x9B2B, 0xF45F, 0x9B2C, 0xF460, 0x9B2D, 0xF461, 0x9B2E, 0xF462,
+	0x9B2F, 0xDBCB, 0x9B30, 0xF463, 0x9B31, 0xF464, 0x9B32, 0xD8AA,
+	0x9B33, 0xF465, 0x9B34, 0xF466, 0x9B35, 0xF467, 0x9B36, 0xF468,
+	0x9B37, 0xF469, 0x9B38, 0xF46A, 0x9B39, 0xF46B, 0x9B3A, 0xF46C,
+	0x9B3B, 0xE5F7, 0x9B3C, 0xB9ED, 0x9B3D, 0xF46D, 0x9B3E, 0xF46E,
+	0x9B3F, 0xF46F, 0x9B40, 0xF470, 0x9B41, 0xBFFD, 0x9B42, 0xBBEA,
+	0x9B43, 0xF7C9, 0x9B44, 0xC6C7, 0x9B45, 0xF7C8, 0x9B46, 0xF471,
+	0x9B47, 0xF7CA, 0x9B48, 0xF7CC, 0x9B49, 0xF7CB, 0x9B4A, 0xF472,
+	0x9B4B, 0xF473, 0x9B4C, 0xF474, 0x9B4D, 0xF7CD, 0x9B4E, 0xF475,
+	0x9B4F, 0xCEBA, 0x9B50, 0xF476, 0x9B51, 0xF7CE, 0x9B52, 0xF477,
+	0x9B53, 0xF478, 0x9B54, 0xC4A7, 0x9B55, 0xF479, 0x9B56, 0xF47A,
+	0x9B57, 0xF47B, 0x9B58, 0xF47C, 0x9B59, 0xF47D, 0x9B5A, 0xF47E,
+	0x9B5B, 0xF480, 0x9B5C, 0xF481, 0x9B5D, 0xF482, 0x9B5E, 0xF483,
+	0x9B5F, 0xF484, 0x9B60, 0xF485, 0x9B61, 0xF486, 0x9B62, 0xF487,
+	0x9B63, 0xF488, 0x9B64, 0xF489, 0x9B65, 0xF48A, 0x9B66, 0xF48B,
+	0x9B67, 0xF48C, 0x9B68, 0xF48D, 0x9B69, 0xF48E, 0x9B6A, 0xF48F,
+	0x9B6B, 0xF490, 0x9B6C, 0xF491, 0x9B6D, 0xF492, 0x9B6E, 0xF493,
+	0x9B6F, 0xF494, 0x9B70, 0xF495, 0x9B71, 0xF496, 0x9B72, 0xF497,
+	0x9B73, 0xF498, 0x9B74, 0xF499, 0x9B75, 0xF49A, 0x9B76, 0xF49B,
+	0x9B77, 0xF49C, 0x9B78, 0xF49D, 0x9B79, 0xF49E, 0x9B7A, 0xF49F,
+	0x9B7B, 0xF4A0, 0x9B7C, 0xF540, 0x9B7D, 0xF541, 0x9B7E, 0xF542,
+	0x9B7F, 0xF543, 0x9B80, 0xF544, 0x9B81, 0xF545, 0x9B82, 0xF546,
+	0x9B83, 0xF547, 0x9B84, 0xF548, 0x9B85, 0xF549, 0x9B86, 0xF54A,
+	0x9B87, 0xF54B, 0x9B88, 0xF54C, 0x9B89, 0xF54D, 0x9B8A, 0xF54E,
+	0x9B8B, 0xF54F, 0x9B8C, 0xF550, 0x9B8D, 0xF551, 0x9B8E, 0xF552,
+	0x9B8F, 0xF553, 0x9B90, 0xF554, 0x9B91, 0xF555, 0x9B92, 0xF556,
+	0x9B93, 0xF557, 0x9B94, 0xF558, 0x9B95, 0xF559, 0x9B96, 0xF55A,
+	0x9B97, 0xF55B, 0x9B98, 0xF55C, 0x9B99, 0xF55D, 0x9B9A, 0xF55E,
+	0x9B9B, 0xF55F, 0x9B9C, 0xF560, 0x9B9D, 0xF561, 0x9B9E, 0xF562,
+	0x9B9F, 0xF563, 0x9BA0, 0xF564, 0x9BA1, 0xF565, 0x9BA2, 0xF566,
+	0x9BA3, 0xF567, 0x9BA4, 0xF568, 0x9BA5, 0xF569, 0x9BA6, 0xF56A,
+	0x9BA7, 0xF56B, 0x9BA8, 0xF56C, 0x9BA9, 0xF56D, 0x9BAA, 0xF56E,
+	0x9BAB, 0xF56F, 0x9BAC, 0xF570, 0x9BAD, 0xF571, 0x9BAE, 0xF572,
+	0x9BAF, 0xF573, 0x9BB0, 0xF574, 0x9BB1, 0xF575, 0x9BB2, 0xF576,
+	0x9BB3, 0xF577, 0x9BB4, 0xF578, 0x9BB5, 0xF579, 0x9BB6, 0xF57A,
+	0x9BB7, 0xF57B, 0x9BB8, 0xF57C, 0x9BB9, 0xF57D, 0x9BBA, 0xF57E,
+	0x9BBB, 0xF580, 0x9BBC, 0xF581, 0x9BBD, 0xF582, 0x9BBE, 0xF583,
+	0x9BBF, 0xF584, 0x9BC0, 0xF585, 0x9BC1, 0xF586, 0x9BC2, 0xF587,
+	0x9BC3, 0xF588, 0x9BC4, 0xF589, 0x9BC5, 0xF58A, 0x9BC6, 0xF58B,
+	0x9BC7, 0xF58C, 0x9BC8, 0xF58D, 0x9BC9, 0xF58E, 0x9BCA, 0xF58F,
+	0x9BCB, 0xF590, 0x9BCC, 0xF591, 0x9BCD, 0xF592, 0x9BCE, 0xF593,
+	0x9BCF, 0xF594, 0x9BD0, 0xF595, 0x9BD1, 0xF596, 0x9BD2, 0xF597,
+	0x9BD3, 0xF598, 0x9BD4, 0xF599, 0x9BD5, 0xF59A, 0x9BD6, 0xF59B,
+	0x9BD7, 0xF59C, 0x9BD8, 0xF59D, 0x9BD9, 0xF59E, 0x9BDA, 0xF59F,
+	0x9BDB, 0xF5A0, 0x9BDC, 0xF640, 0x9BDD, 0xF641, 0x9BDE, 0xF642,
+	0x9BDF, 0xF643, 0x9BE0, 0xF644, 0x9BE1, 0xF645, 0x9BE2, 0xF646,
+	0x9BE3, 0xF647, 0x9BE4, 0xF648, 0x9BE5, 0xF649, 0x9BE6, 0xF64A,
+	0x9BE7, 0xF64B, 0x9BE8, 0xF64C, 0x9BE9, 0xF64D, 0x9BEA, 0xF64E,
+	0x9BEB, 0xF64F, 0x9BEC, 0xF650, 0x9BED, 0xF651, 0x9BEE, 0xF652,
+	0x9BEF, 0xF653, 0x9BF0, 0xF654, 0x9BF1, 0xF655, 0x9BF2, 0xF656,
+	0x9BF3, 0xF657, 0x9BF4, 0xF658, 0x9BF5, 0xF659, 0x9BF6, 0xF65A,
+	0x9BF7, 0xF65B, 0x9BF8, 0xF65C, 0x9BF9, 0xF65D, 0x9BFA, 0xF65E,
+	0x9BFB, 0xF65F, 0x9BFC, 0xF660, 0x9BFD, 0xF661, 0x9BFE, 0xF662,
+	0x9BFF, 0xF663, 0x9C00, 0xF664, 0x9C01, 0xF665, 0x9C02, 0xF666,
+	0x9C03, 0xF667, 0x9C04, 0xF668, 0x9C05, 0xF669, 0x9C06, 0xF66A,
+	0x9C07, 0xF66B, 0x9C08, 0xF66C, 0x9C09, 0xF66D, 0x9C0A, 0xF66E,
+	0x9C0B, 0xF66F, 0x9C0C, 0xF670, 0x9C0D, 0xF671, 0x9C0E, 0xF672,
+	0x9C0F, 0xF673, 0x9C10, 0xF674, 0x9C11, 0xF675, 0x9C12, 0xF676,
+	0x9C13, 0xF677, 0x9C14, 0xF678, 0x9C15, 0xF679, 0x9C16, 0xF67A,
+	0x9C17, 0xF67B, 0x9C18, 0xF67C, 0x9C19, 0xF67D, 0x9C1A, 0xF67E,
+	0x9C1B, 0xF680, 0x9C1C, 0xF681, 0x9C1D, 0xF682, 0x9C1E, 0xF683,
+	0x9C1F, 0xF684, 0x9C20, 0xF685, 0x9C21, 0xF686, 0x9C22, 0xF687,
+	0x9C23, 0xF688, 0x9C24, 0xF689, 0x9C25, 0xF68A, 0x9C26, 0xF68B,
+	0x9C27, 0xF68C, 0x9C28, 0xF68D, 0x9C29, 0xF68E, 0x9C2A, 0xF68F,
+	0x9C2B, 0xF690, 0x9C2C, 0xF691, 0x9C2D, 0xF692, 0x9C2E, 0xF693,
+	0x9C2F, 0xF694, 0x9C30, 0xF695, 0x9C31, 0xF696, 0x9C32, 0xF697,
+	0x9C33, 0xF698, 0x9C34, 0xF699, 0x9C35, 0xF69A, 0x9C36, 0xF69B,
+	0x9C37, 0xF69C, 0x9C38, 0xF69D, 0x9C39, 0xF69E, 0x9C3A, 0xF69F,
+	0x9C3B, 0xF6A0, 0x9C3C, 0xF740, 0x9C3D, 0xF741, 0x9C3E, 0xF742,
+	0x9C3F, 0xF743, 0x9C40, 0xF744, 0x9C41, 0xF745, 0x9C42, 0xF746,
+	0x9C43, 0xF747, 0x9C44, 0xF748, 0x9C45, 0xF749, 0x9C46, 0xF74A,
+	0x9C47, 0xF74B, 0x9C48, 0xF74C, 0x9C49, 0xF74D, 0x9C4A, 0xF74E,
+	0x9C4B, 0xF74F, 0x9C4C, 0xF750, 0x9C4D, 0xF751, 0x9C4E, 0xF752,
+	0x9C4F, 0xF753, 0x9C50, 0xF754, 0x9C51, 0xF755, 0x9C52, 0xF756,
+	0x9C53, 0xF757, 0x9C54, 0xF758, 0x9C55, 0xF759, 0x9C56, 0xF75A,
+	0x9C57, 0xF75B, 0x9C58, 0xF75C, 0x9C59, 0xF75D, 0x9C5A, 0xF75E,
+	0x9C5B, 0xF75F, 0x9C5C, 0xF760, 0x9C5D, 0xF761, 0x9C5E, 0xF762,
+	0x9C5F, 0xF763, 0x9C60, 0xF764, 0x9C61, 0xF765, 0x9C62, 0xF766,
+	0x9C63, 0xF767, 0x9C64, 0xF768, 0x9C65, 0xF769, 0x9C66, 0xF76A,
+	0x9C67, 0xF76B, 0x9C68, 0xF76C, 0x9C69, 0xF76D, 0x9C6A, 0xF76E,
+	0x9C6B, 0xF76F, 0x9C6C, 0xF770, 0x9C6D, 0xF771, 0x9C6E, 0xF772,
+	0x9C6F, 0xF773, 0x9C70, 0xF774, 0x9C71, 0xF775, 0x9C72, 0xF776,
+	0x9C73, 0xF777, 0x9C74, 0xF778, 0x9C75, 0xF779, 0x9C76, 0xF77A,
+	0x9C77, 0xF77B, 0x9C78, 0xF77C, 0x9C79, 0xF77D, 0x9C7A, 0xF77E,
+	0x9C7B, 0xF780, 0x9C7C, 0xD3E3, 0x9C7D, 0xF781, 0x9C7E, 0xF782,
+	0x9C7F, 0xF6CF, 0x9C80, 0xF783, 0x9C81, 0xC2B3, 0x9C82, 0xF6D0,
+	0x9C83, 0xF784, 0x9C84, 0xF785, 0x9C85, 0xF6D1, 0x9C86, 0xF6D2,
+	0x9C87, 0xF6D3, 0x9C88, 0xF6D4, 0x9C89, 0xF786, 0x9C8A, 0xF787,
+	0x9C8B, 0xF6D6, 0x9C8C, 0xF788, 0x9C8D, 0xB1AB, 0x9C8E, 0xF6D7,
+	0x9C8F, 0xF789, 0x9C90, 0xF6D8, 0x9C91, 0xF6D9, 0x9C92, 0xF6DA,
+	0x9C93, 0xF78A, 0x9C94, 0xF6DB, 0x9C95, 0xF6DC, 0x9C96, 0xF78B,
+	0x9C97, 0xF78C, 0x9C98, 0xF78D, 0x9C99, 0xF78E, 0x9C9A, 0xF6DD,
+	0x9C9B, 0xF6DE, 0x9C9C, 0xCFCA, 0x9C9D, 0xF78F, 0x9C9E, 0xF6DF,
+	0x9C9F, 0xF6E0, 0x9CA0, 0xF6E1, 0x9CA1, 0xF6E2, 0x9CA2, 0xF6E3,
+	0x9CA3, 0xF6E4, 0x9CA4, 0xC0F0, 0x9CA5, 0xF6E5, 0x9CA6, 0xF6E6,
+	0x9CA7, 0xF6E7, 0x9CA8, 0xF6E8, 0x9CA9, 0xF6E9, 0x9CAA, 0xF790,
+	0x9CAB, 0xF6EA, 0x9CAC, 0xF791, 0x9CAD, 0xF6EB, 0x9CAE, 0xF6EC,
+	0x9CAF, 0xF792, 0x9CB0, 0xF6ED, 0x9CB1, 0xF6EE, 0x9CB2, 0xF6EF,
+	0x9CB3, 0xF6F0, 0x9CB4, 0xF6F1, 0x9CB5, 0xF6F2, 0x9CB6, 0xF6F3,
+	0x9CB7, 0xF6F4, 0x9CB8, 0xBEA8, 0x9CB9, 0xF793, 0x9CBA, 0xF6F5,
+	0x9CBB, 0xF6F6, 0x9CBC, 0xF6F7, 0x9CBD, 0xF6F8, 0x9CBE, 0xF794,
+	0x9CBF, 0xF795, 0x9CC0, 0xF796, 0x9CC1, 0xF797, 0x9CC2, 0xF798,
+	0x9CC3, 0xC8FA, 0x9CC4, 0xF6F9, 0x9CC5, 0xF6FA, 0x9CC6, 0xF6FB,
+	0x9CC7, 0xF6FC, 0x9CC8, 0xF799, 0x9CC9, 0xF79A, 0x9CCA, 0xF6FD,
+	0x9CCB, 0xF6FE, 0x9CCC, 0xF7A1, 0x9CCD, 0xF7A2, 0x9CCE, 0xF7A3,
+	0x9CCF, 0xF7A4, 0x9CD0, 0xF7A5, 0x9CD1, 0xF79B, 0x9CD2, 0xF79C,
+	0x9CD3, 0xF7A6, 0x9CD4, 0xF7A7, 0x9CD5, 0xF7A8, 0x9CD6, 0xB1EE,
+	0x9CD7, 0xF7A9, 0x9CD8, 0xF7AA, 0x9CD9, 0xF7AB, 0x9CDA, 0xF79D,
+	0x9CDB, 0xF79E, 0x9CDC, 0xF7AC, 0x9CDD, 0xF7AD, 0x9CDE, 0xC1DB,
+	0x9CDF, 0xF7AE, 0x9CE0, 0xF79F, 0x9CE1, 0xF7A0, 0x9CE2, 0xF7AF,
+	0x9CE3, 0xF840, 0x9CE4, 0xF841, 0x9CE5, 0xF842, 0x9CE6, 0xF843,
+	0x9CE7, 0xF844, 0x9CE8, 0xF845, 0x9CE9, 0xF846, 0x9CEA, 0xF847,
+	0x9CEB, 0xF848, 0x9CEC, 0xF849, 0x9CED, 0xF84A, 0x9CEE, 0xF84B,
+	0x9CEF, 0xF84C, 0x9CF0, 0xF84D, 0x9CF1, 0xF84E, 0x9CF2, 0xF84F,
+	0x9CF3, 0xF850, 0x9CF4, 0xF851, 0x9CF5, 0xF852, 0x9CF6, 0xF853,
+	0x9CF7, 0xF854, 0x9CF8, 0xF855, 0x9CF9, 0xF856, 0x9CFA, 0xF857,
+	0x9CFB, 0xF858, 0x9CFC, 0xF859, 0x9CFD, 0xF85A, 0x9CFE, 0xF85B,
+	0x9CFF, 0xF85C, 0x9D00, 0xF85D, 0x9D01, 0xF85E, 0x9D02, 0xF85F,
+	0x9D03, 0xF860, 0x9D04, 0xF861, 0x9D05, 0xF862, 0x9D06, 0xF863,
+	0x9D07, 0xF864, 0x9D08, 0xF865, 0x9D09, 0xF866, 0x9D0A, 0xF867,
+	0x9D0B, 0xF868, 0x9D0C, 0xF869, 0x9D0D, 0xF86A, 0x9D0E, 0xF86B,
+	0x9D0F, 0xF86C, 0x9D10, 0xF86D, 0x9D11, 0xF86E, 0x9D12, 0xF86F,
+	0x9D13, 0xF870, 0x9D14, 0xF871, 0x9D15, 0xF872, 0x9D16, 0xF873,
+	0x9D17, 0xF874, 0x9D18, 0xF875, 0x9D19, 0xF876, 0x9D1A, 0xF877,
+	0x9D1B, 0xF878, 0x9D1C, 0xF879, 0x9D1D, 0xF87A, 0x9D1E, 0xF87B,
+	0x9D1F, 0xF87C, 0x9D20, 0xF87D, 0x9D21, 0xF87E, 0x9D22, 0xF880,
+	0x9D23, 0xF881, 0x9D24, 0xF882, 0x9D25, 0xF883, 0x9D26, 0xF884,
+	0x9D27, 0xF885, 0x9D28, 0xF886, 0x9D29, 0xF887, 0x9D2A, 0xF888,
+	0x9D2B, 0xF889, 0x9D2C, 0xF88A, 0x9D2D, 0xF88B, 0x9D2E, 0xF88C,
+	0x9D2F, 0xF88D, 0x9D30, 0xF88E, 0x9D31, 0xF88F, 0x9D32, 0xF890,
+	0x9D33, 0xF891, 0x9D34, 0xF892, 0x9D35, 0xF893, 0x9D36, 0xF894,
+	0x9D37, 0xF895, 0x9D38, 0xF896, 0x9D39, 0xF897, 0x9D3A, 0xF898,
+	0x9D3B, 0xF899, 0x9D3C, 0xF89A, 0x9D3D, 0xF89B, 0x9D3E, 0xF89C,
+	0x9D3F, 0xF89D, 0x9D40, 0xF89E, 0x9D41, 0xF89F, 0x9D42, 0xF8A0,
+	0x9D43, 0xF940, 0x9D44, 0xF941, 0x9D45, 0xF942, 0x9D46, 0xF943,
+	0x9D47, 0xF944, 0x9D48, 0xF945, 0x9D49, 0xF946, 0x9D4A, 0xF947,
+	0x9D4B, 0xF948, 0x9D4C, 0xF949, 0x9D4D, 0xF94A, 0x9D4E, 0xF94B,
+	0x9D4F, 0xF94C, 0x9D50, 0xF94D, 0x9D51, 0xF94E, 0x9D52, 0xF94F,
+	0x9D53, 0xF950, 0x9D54, 0xF951, 0x9D55, 0xF952, 0x9D56, 0xF953,
+	0x9D57, 0xF954, 0x9D58, 0xF955, 0x9D59, 0xF956, 0x9D5A, 0xF957,
+	0x9D5B, 0xF958, 0x9D5C, 0xF959, 0x9D5D, 0xF95A, 0x9D5E, 0xF95B,
+	0x9D5F, 0xF95C, 0x9D60, 0xF95D, 0x9D61, 0xF95E, 0x9D62, 0xF95F,
+	0x9D63, 0xF960, 0x9D64, 0xF961, 0x9D65, 0xF962, 0x9D66, 0xF963,
+	0x9D67, 0xF964, 0x9D68, 0xF965, 0x9D69, 0xF966, 0x9D6A, 0xF967,
+	0x9D6B, 0xF968, 0x9D6C, 0xF969, 0x9D6D, 0xF96A, 0x9D6E, 0xF96B,
+	0x9D6F, 0xF96C, 0x9D70, 0xF96D, 0x9D71, 0xF96E, 0x9D72, 0xF96F,
+	0x9D73, 0xF970, 0x9D74, 0xF971, 0x9D75, 0xF972, 0x9D76, 0xF973,
+	0x9D77, 0xF974, 0x9D78, 0xF975, 0x9D79, 0xF976, 0x9D7A, 0xF977,
+	0x9D7B, 0xF978, 0x9D7C, 0xF979, 0x9D7D, 0xF97A, 0x9D7E, 0xF97B,
+	0x9D7F, 0xF97C, 0x9D80, 0xF97D, 0x9D81, 0xF97E, 0x9D82, 0xF980,
+	0x9D83, 0xF981, 0x9D84, 0xF982, 0x9D85, 0xF983, 0x9D86, 0xF984,
+	0x9D87, 0xF985, 0x9D88, 0xF986, 0x9D89, 0xF987, 0x9D8A, 0xF988,
+	0x9D8B, 0xF989, 0x9D8C, 0xF98A, 0x9D8D, 0xF98B, 0x9D8E, 0xF98C,
+	0x9D8F, 0xF98D, 0x9D90, 0xF98E, 0x9D91, 0xF98F, 0x9D92, 0xF990,
+	0x9D93, 0xF991, 0x9D94, 0xF992, 0x9D95, 0xF993, 0x9D96, 0xF994,
+	0x9D97, 0xF995, 0x9D98, 0xF996, 0x9D99, 0xF997, 0x9D9A, 0xF998,
+	0x9D9B, 0xF999, 0x9D9C, 0xF99A, 0x9D9D, 0xF99B, 0x9D9E, 0xF99C,
+	0x9D9F, 0xF99D, 0x9DA0, 0xF99E, 0x9DA1, 0xF99F, 0x9DA2, 0xF9A0,
+	0x9DA3, 0xFA40, 0x9DA4, 0xFA41, 0x9DA5, 0xFA42, 0x9DA6, 0xFA43,
+	0x9DA7, 0xFA44, 0x9DA8, 0xFA45, 0x9DA9, 0xFA46, 0x9DAA, 0xFA47,
+	0x9DAB, 0xFA48, 0x9DAC, 0xFA49, 0x9DAD, 0xFA4A, 0x9DAE, 0xFA4B,
+	0x9DAF, 0xFA4C, 0x9DB0, 0xFA4D, 0x9DB1, 0xFA4E, 0x9DB2, 0xFA4F,
+	0x9DB3, 0xFA50, 0x9DB4, 0xFA51, 0x9DB5, 0xFA52, 0x9DB6, 0xFA53,
+	0x9DB7, 0xFA54, 0x9DB8, 0xFA55, 0x9DB9, 0xFA56, 0x9DBA, 0xFA57,
+	0x9DBB, 0xFA58, 0x9DBC, 0xFA59, 0x9DBD, 0xFA5A, 0x9DBE, 0xFA5B,
+	0x9DBF, 0xFA5C, 0x9DC0, 0xFA5D, 0x9DC1, 0xFA5E, 0x9DC2, 0xFA5F,
+	0x9DC3, 0xFA60, 0x9DC4, 0xFA61, 0x9DC5, 0xFA62, 0x9DC6, 0xFA63,
+	0x9DC7, 0xFA64, 0x9DC8, 0xFA65, 0x9DC9, 0xFA66, 0x9DCA, 0xFA67,
+	0x9DCB, 0xFA68, 0x9DCC, 0xFA69, 0x9DCD, 0xFA6A, 0x9DCE, 0xFA6B,
+	0x9DCF, 0xFA6C, 0x9DD0, 0xFA6D, 0x9DD1, 0xFA6E, 0x9DD2, 0xFA6F,
+	0x9DD3, 0xFA70, 0x9DD4, 0xFA71, 0x9DD5, 0xFA72, 0x9DD6, 0xFA73,
+	0x9DD7, 0xFA74, 0x9DD8, 0xFA75, 0x9DD9, 0xFA76, 0x9DDA, 0xFA77,
+	0x9DDB, 0xFA78, 0x9DDC, 0xFA79, 0x9DDD, 0xFA7A, 0x9DDE, 0xFA7B,
+	0x9DDF, 0xFA7C, 0x9DE0, 0xFA7D, 0x9DE1, 0xFA7E, 0x9DE2, 0xFA80,
+	0x9DE3, 0xFA81, 0x9DE4, 0xFA82, 0x9DE5, 0xFA83, 0x9DE6, 0xFA84,
+	0x9DE7, 0xFA85, 0x9DE8, 0xFA86, 0x9DE9, 0xFA87, 0x9DEA, 0xFA88,
+	0x9DEB, 0xFA89, 0x9DEC, 0xFA8A, 0x9DED, 0xFA8B, 0x9DEE, 0xFA8C,
+	0x9DEF, 0xFA8D, 0x9DF0, 0xFA8E, 0x9DF1, 0xFA8F, 0x9DF2, 0xFA90,
+	0x9DF3, 0xFA91, 0x9DF4, 0xFA92, 0x9DF5, 0xFA93, 0x9DF6, 0xFA94,
+	0x9DF7, 0xFA95, 0x9DF8, 0xFA96, 0x9DF9, 0xFA97, 0x9DFA, 0xFA98,
+	0x9DFB, 0xFA99, 0x9DFC, 0xFA9A, 0x9DFD, 0xFA9B, 0x9DFE, 0xFA9C,
+	0x9DFF, 0xFA9D, 0x9E00, 0xFA9E, 0x9E01, 0xFA9F, 0x9E02, 0xFAA0,
+	0x9E03, 0xFB40, 0x9E04, 0xFB41, 0x9E05, 0xFB42, 0x9E06, 0xFB43,
+	0x9E07, 0xFB44, 0x9E08, 0xFB45, 0x9E09, 0xFB46, 0x9E0A, 0xFB47,
+	0x9E0B, 0xFB48, 0x9E0C, 0xFB49, 0x9E0D, 0xFB4A, 0x9E0E, 0xFB4B,
+	0x9E0F, 0xFB4C, 0x9E10, 0xFB4D, 0x9E11, 0xFB4E, 0x9E12, 0xFB4F,
+	0x9E13, 0xFB50, 0x9E14, 0xFB51, 0x9E15, 0xFB52, 0x9E16, 0xFB53,
+	0x9E17, 0xFB54, 0x9E18, 0xFB55, 0x9E19, 0xFB56, 0x9E1A, 0xFB57,
+	0x9E1B, 0xFB58, 0x9E1C, 0xFB59, 0x9E1D, 0xFB5A, 0x9E1E, 0xFB5B,
+	0x9E1F, 0xC4F1, 0x9E20, 0xF0AF, 0x9E21, 0xBCA6, 0x9E22, 0xF0B0,
+	0x9E23, 0xC3F9, 0x9E24, 0xFB5C, 0x9E25, 0xC5B8, 0x9E26, 0xD1BB,
+	0x9E27, 0xFB5D, 0x9E28, 0xF0B1, 0x9E29, 0xF0B2, 0x9E2A, 0xF0B3,
+	0x9E2B, 0xF0B4, 0x9E2C, 0xF0B5, 0x9E2D, 0xD1BC, 0x9E2E, 0xFB5E,
+	0x9E2F, 0xD1EC, 0x9E30, 0xFB5F, 0x9E31, 0xF0B7, 0x9E32, 0xF0B6,
+	0x9E33, 0xD4A7, 0x9E34, 0xFB60, 0x9E35, 0xCDD2, 0x9E36, 0xF0B8,
+	0x9E37, 0xF0BA, 0x9E38, 0xF0B9, 0x9E39, 0xF0BB, 0x9E3A, 0xF0BC,
+	0x9E3B, 0xFB61, 0x9E3C, 0xFB62, 0x9E3D, 0xB8EB, 0x9E3E, 0xF0BD,
+	0x9E3F, 0xBAE8, 0x9E40, 0xFB63, 0x9E41, 0xF0BE, 0x9E42, 0xF0BF,
+	0x9E43, 0xBEE9, 0x9E44, 0xF0C0, 0x9E45, 0xB6EC, 0x9E46, 0xF0C1,
+	0x9E47, 0xF0C2, 0x9E48, 0xF0C3, 0x9E49, 0xF0C4, 0x9E4A, 0xC8B5,
+	0x9E4B, 0xF0C5, 0x9E4C, 0xF0C6, 0x9E4D, 0xFB64, 0x9E4E, 0xF0C7,
+	0x9E4F, 0xC5F4, 0x9E50, 0xFB65, 0x9E51, 0xF0C8, 0x9E52, 0xFB66,
+	0x9E53, 0xFB67, 0x9E54, 0xFB68, 0x9E55, 0xF0C9, 0x9E56, 0xFB69,
+	0x9E57, 0xF0CA, 0x9E58, 0xF7BD, 0x9E59, 0xFB6A, 0x9E5A, 0xF0CB,
+	0x9E5B, 0xF0CC, 0x9E5C, 0xF0CD, 0x9E5D, 0xFB6B, 0x9E5E, 0xF0CE,
+	0x9E5F, 0xFB6C, 0x9E60, 0xFB6D, 0x9E61, 0xFB6E, 0x9E62, 0xFB6F,
+	0x9E63, 0xF0CF, 0x9E64, 0xBAD7, 0x9E65, 0xFB70, 0x9E66, 0xF0D0,
+	0x9E67, 0xF0D1, 0x9E68, 0xF0D2, 0x9E69, 0xF0D3, 0x9E6A, 0xF0D4,
+	0x9E6B, 0xF0D5, 0x9E6C, 0xF0D6, 0x9E6D, 0xF0D8, 0x9E6E, 0xFB71,
+	0x9E6F, 0xFB72, 0x9E70, 0xD3A5, 0x9E71, 0xF0D7, 0x9E72, 0xFB73,
+	0x9E73, 0xF0D9, 0x9E74, 0xFB74, 0x9E75, 0xFB75, 0x9E76, 0xFB76,
+	0x9E77, 0xFB77, 0x9E78, 0xFB78, 0x9E79, 0xFB79, 0x9E7A, 0xFB7A,
+	0x9E7B, 0xFB7B, 0x9E7C, 0xFB7C, 0x9E7D, 0xFB7D, 0x9E7E, 0xF5BA,
+	0x9E7F, 0xC2B9, 0x9E80, 0xFB7E, 0x9E81, 0xFB80, 0x9E82, 0xF7E4,
+	0x9E83, 0xFB81, 0x9E84, 0xFB82, 0x9E85, 0xFB83, 0x9E86, 0xFB84,
+	0x9E87, 0xF7E5, 0x9E88, 0xF7E6, 0x9E89, 0xFB85, 0x9E8A, 0xFB86,
+	0x9E8B, 0xF7E7, 0x9E8C, 0xFB87, 0x9E8D, 0xFB88, 0x9E8E, 0xFB89,
+	0x9E8F, 0xFB8A, 0x9E90, 0xFB8B, 0x9E91, 0xFB8C, 0x9E92, 0xF7E8,
+	0x9E93, 0xC2B4, 0x9E94, 0xFB8D, 0x9E95, 0xFB8E, 0x9E96, 0xFB8F,
+	0x9E97, 0xFB90, 0x9E98, 0xFB91, 0x9E99, 0xFB92, 0x9E9A, 0xFB93,
+	0x9E9B, 0xFB94, 0x9E9C, 0xFB95, 0x9E9D, 0xF7EA, 0x9E9E, 0xFB96,
+	0x9E9F, 0xF7EB, 0x9EA0, 0xFB97, 0x9EA1, 0xFB98, 0x9EA2, 0xFB99,
+	0x9EA3, 0xFB9A, 0x9EA4, 0xFB9B, 0x9EA5, 0xFB9C, 0x9EA6, 0xC2F3,
+	0x9EA7, 0xFB9D, 0x9EA8, 0xFB9E, 0x9EA9, 0xFB9F, 0x9EAA, 0xFBA0,
+	0x9EAB, 0xFC40, 0x9EAC, 0xFC41, 0x9EAD, 0xFC42, 0x9EAE, 0xFC43,
+	0x9EAF, 0xFC44, 0x9EB0, 0xFC45, 0x9EB1, 0xFC46, 0x9EB2, 0xFC47,
+	0x9EB3, 0xFC48, 0x9EB4, 0xF4F0, 0x9EB5, 0xFC49, 0x9EB6, 0xFC4A,
+	0x9EB7, 0xFC4B, 0x9EB8, 0xF4EF, 0x9EB9, 0xFC4C, 0x9EBA, 0xFC4D,
+	0x9EBB, 0xC2E9, 0x9EBC, 0xFC4E, 0x9EBD, 0xF7E1, 0x9EBE, 0xF7E2,
+	0x9EBF, 0xFC4F, 0x9EC0, 0xFC50, 0x9EC1, 0xFC51, 0x9EC2, 0xFC52,
+	0x9EC3, 0xFC53, 0x9EC4, 0xBBC6, 0x9EC5, 0xFC54, 0x9EC6, 0xFC55,
+	0x9EC7, 0xFC56, 0x9EC8, 0xFC57, 0x9EC9, 0xD9E4, 0x9ECA, 0xFC58,
+	0x9ECB, 0xFC59, 0x9ECC, 0xFC5A, 0x9ECD, 0xCAF2, 0x9ECE, 0xC0E8,
+	0x9ECF, 0xF0A4, 0x9ED0, 0xFC5B, 0x9ED1, 0xBADA, 0x9ED2, 0xFC5C,
+	0x9ED3, 0xFC5D, 0x9ED4, 0xC7AD, 0x9ED5, 0xFC5E, 0x9ED6, 0xFC5F,
+	0x9ED7, 0xFC60, 0x9ED8, 0xC4AC, 0x9ED9, 0xFC61, 0x9EDA, 0xFC62,
+	0x9EDB, 0xF7EC, 0x9EDC, 0xF7ED, 0x9EDD, 0xF7EE, 0x9EDE, 0xFC63,
+	0x9EDF, 0xF7F0, 0x9EE0, 0xF7EF, 0x9EE1, 0xFC64, 0x9EE2, 0xF7F1,
+	0x9EE3, 0xFC65, 0x9EE4, 0xFC66, 0x9EE5, 0xF7F4, 0x9EE6, 0xFC67,
+	0x9EE7, 0xF7F3, 0x9EE8, 0xFC68, 0x9EE9, 0xF7F2, 0x9EEA, 0xF7F5,
+	0x9EEB, 0xFC69, 0x9EEC, 0xFC6A, 0x9EED, 0xFC6B, 0x9EEE, 0xFC6C,
+	0x9EEF, 0xF7F6, 0x9EF0, 0xFC6D, 0x9EF1, 0xFC6E, 0x9EF2, 0xFC6F,
+	0x9EF3, 0xFC70, 0x9EF4, 0xFC71, 0x9EF5, 0xFC72, 0x9EF6, 0xFC73,
+	0x9EF7, 0xFC74, 0x9EF8, 0xFC75, 0x9EF9, 0xEDE9, 0x9EFA, 0xFC76,
+	0x9EFB, 0xEDEA, 0x9EFC, 0xEDEB, 0x9EFD, 0xFC77, 0x9EFE, 0xF6BC,
+	0x9EFF, 0xFC78, 0x9F00, 0xFC79, 0x9F01, 0xFC7A, 0x9F02, 0xFC7B,
+	0x9F03, 0xFC7C, 0x9F04, 0xFC7D, 0x9F05, 0xFC7E, 0x9F06, 0xFC80,
+	0x9F07, 0xFC81, 0x9F08, 0xFC82, 0x9F09, 0xFC83, 0x9F0A, 0xFC84,
+	0x9F0B, 0xF6BD, 0x9F0C, 0xFC85, 0x9F0D, 0xF6BE, 0x9F0E, 0xB6A6,
+	0x9F0F, 0xFC86, 0x9F10, 0xD8BE, 0x9F11, 0xFC87, 0x9F12, 0xFC88,
+	0x9F13, 0xB9C4, 0x9F14, 0xFC89, 0x9F15, 0xFC8A, 0x9F16, 0xFC8B,
+	0x9F17, 0xD8BB, 0x9F18, 0xFC8C, 0x9F19, 0xDCB1, 0x9F1A, 0xFC8D,
+	0x9F1B, 0xFC8E, 0x9F1C, 0xFC8F, 0x9F1D, 0xFC90, 0x9F1E, 0xFC91,
+	0x9F1F, 0xFC92, 0x9F20, 0xCAF3, 0x9F21, 0xFC93, 0x9F22, 0xF7F7,
+	0x9F23, 0xFC94, 0x9F24, 0xFC95, 0x9F25, 0xFC96, 0x9F26, 0xFC97,
+	0x9F27, 0xFC98, 0x9F28, 0xFC99, 0x9F29, 0xFC9A, 0x9F2A, 0xFC9B,
+	0x9F2B, 0xFC9C, 0x9F2C, 0xF7F8, 0x9F2D, 0xFC9D, 0x9F2E, 0xFC9E,
+	0x9F2F, 0xF7F9, 0x9F30, 0xFC9F, 0x9F31, 0xFCA0, 0x9F32, 0xFD40,
+	0x9F33, 0xFD41, 0x9F34, 0xFD42, 0x9F35, 0xFD43, 0x9F36, 0xFD44,
+	0x9F37, 0xF7FB, 0x9F38, 0xFD45, 0x9F39, 0xF7FA, 0x9F3A, 0xFD46,
+	0x9F3B, 0xB1C7, 0x9F3C, 0xFD47, 0x9F3D, 0xF7FC, 0x9F3E, 0xF7FD,
+	0x9F3F, 0xFD48, 0x9F40, 0xFD49, 0x9F41, 0xFD4A, 0x9F42, 0xFD4B,
+	0x9F43, 0xFD4C, 0x9F44, 0xF7FE, 0x9F45, 0xFD4D, 0x9F46, 0xFD4E,
+	0x9F47, 0xFD4F, 0x9F48, 0xFD50, 0x9F49, 0xFD51, 0x9F4A, 0xFD52,
+	0x9F4B, 0xFD53, 0x9F4C, 0xFD54, 0x9F4D, 0xFD55, 0x9F4E, 0xFD56,
+	0x9F4F, 0xFD57, 0x9F50, 0xC6EB, 0x9F51, 0xECB4, 0x9F52, 0xFD58,
+	0x9F53, 0xFD59, 0x9F54, 0xFD5A, 0x9F55, 0xFD5B, 0x9F56, 0xFD5C,
+	0x9F57, 0xFD5D, 0x9F58, 0xFD5E, 0x9F59, 0xFD5F, 0x9F5A, 0xFD60,
+	0x9F5B, 0xFD61, 0x9F5C, 0xFD62, 0x9F5D, 0xFD63, 0x9F5E, 0xFD64,
+	0x9F5F, 0xFD65, 0x9F60, 0xFD66, 0x9F61, 0xFD67, 0x9F62, 0xFD68,
+	0x9F63, 0xFD69, 0x9F64, 0xFD6A, 0x9F65, 0xFD6B, 0x9F66, 0xFD6C,
+	0x9F67, 0xFD6D, 0x9F68, 0xFD6E, 0x9F69, 0xFD6F, 0x9F6A, 0xFD70,
+	0x9F6B, 0xFD71, 0x9F6C, 0xFD72, 0x9F6D, 0xFD73, 0x9F6E, 0xFD74,
+	0x9F6F, 0xFD75, 0x9F70, 0xFD76, 0x9F71, 0xFD77, 0x9F72, 0xFD78,
+	0x9F73, 0xFD79, 0x9F74, 0xFD7A, 0x9F75, 0xFD7B, 0x9F76, 0xFD7C,
+	0x9F77, 0xFD7D, 0x9F78, 0xFD7E, 0x9F79, 0xFD80, 0x9F7A, 0xFD81,
+	0x9F7B, 0xFD82, 0x9F7C, 0xFD83, 0x9F7D, 0xFD84, 0x9F7E, 0xFD85,
+	0x9F7F, 0xB3DD, 0x9F80, 0xF6B3, 0x9F81, 0xFD86, 0x9F82, 0xFD87,
+	0x9F83, 0xF6B4, 0x9F84, 0xC1E4, 0x9F85, 0xF6B5, 0x9F86, 0xF6B6,
+	0x9F87, 0xF6B7, 0x9F88, 0xF6B8, 0x9F89, 0xF6B9, 0x9F8A, 0xF6BA,
+	0x9F8B, 0xC8A3, 0x9F8C, 0xF6BB, 0x9F8D, 0xFD88, 0x9F8E, 0xFD89,
+	0x9F8F, 0xFD8A, 0x9F90, 0xFD8B, 0x9F91, 0xFD8C, 0x9F92, 0xFD8D,
+	0x9F93, 0xFD8E, 0x9F94, 0xFD8F, 0x9F95, 0xFD90, 0x9F96, 0xFD91,
+	0x9F97, 0xFD92, 0x9F98, 0xFD93, 0x9F99, 0xC1FA, 0x9F9A, 0xB9A8,
+	0x9F9B, 0xEDE8, 0x9F9C, 0xFD94, 0x9F9D, 0xFD95, 0x9F9E, 0xFD96,
+	0x9F9F, 0xB9EA, 0x9FA0, 0xD9DF, 0x9FA1, 0xFD97, 0x9FA2, 0xFD98,
+	0x9FA3, 0xFD99, 0x9FA4, 0xFD9A, 0x9FA5, 0xFD9B, 0xF92C, 0xFD9C,
+	0xF979, 0xFD9D, 0xF995, 0xFD9E, 0xF9E7, 0xFD9F, 0xF9F1, 0xFDA0,
+	0xFA0C, 0xFE40, 0xFA0D, 0xFE41, 0xFA0E, 0xFE42, 0xFA0F, 0xFE43,
+	0xFA11, 0xFE44, 0xFA13, 0xFE45, 0xFA14, 0xFE46, 0xFA18, 0xFE47,
+	0xFA1F, 0xFE48, 0xFA20, 0xFE49, 0xFA21, 0xFE4A, 0xFA23, 0xFE4B,
+	0xFA24, 0xFE4C, 0xFA27, 0xFE4D, 0xFA28, 0xFE4E, 0xFA29, 0xFE4F,
+	0xFE30, 0xA955, 0xFE31, 0xA6F2, 0xFE33, 0xA6F4, 0xFE34, 0xA6F5,
+	0xFE35, 0xA6E0, 0xFE36, 0xA6E1, 0xFE37, 0xA6F0, 0xFE38, 0xA6F1,
+	0xFE39, 0xA6E2, 0xFE3A, 0xA6E3, 0xFE3B, 0xA6EE, 0xFE3C, 0xA6EF,
+	0xFE3D, 0xA6E6, 0xFE3E, 0xA6E7, 0xFE3F, 0xA6E4, 0xFE40, 0xA6E5,
+	0xFE41, 0xA6E8, 0xFE42, 0xA6E9, 0xFE43, 0xA6EA, 0xFE44, 0xA6EB,
+	0xFE49, 0xA968, 0xFE4A, 0xA969, 0xFE4B, 0xA96A, 0xFE4C, 0xA96B,
+	0xFE4D, 0xA96C, 0xFE4E, 0xA96D, 0xFE4F, 0xA96E, 0xFE50, 0xA96F,
+	0xFE51, 0xA970, 0xFE52, 0xA971, 0xFE54, 0xA972, 0xFE55, 0xA973,
+	0xFE56, 0xA974, 0xFE57, 0xA975, 0xFE59, 0xA976, 0xFE5A, 0xA977,
+	0xFE5B, 0xA978, 0xFE5C, 0xA979, 0xFE5D, 0xA97A, 0xFE5E, 0xA97B,
+	0xFE5F, 0xA97C, 0xFE60, 0xA97D, 0xFE61, 0xA97E, 0xFE62, 0xA980,
+	0xFE63, 0xA981, 0xFE64, 0xA982, 0xFE65, 0xA983, 0xFE66, 0xA984,
+	0xFE68, 0xA985, 0xFE69, 0xA986, 0xFE6A, 0xA987, 0xFE6B, 0xA988,
+	0xFF01, 0xA3A1, 0xFF02, 0xA3A2, 0xFF03, 0xA3A3, 0xFF04, 0xA1E7,
+	0xFF05, 0xA3A5, 0xFF06, 0xA3A6, 0xFF07, 0xA3A7, 0xFF08, 0xA3A8,
+	0xFF09, 0xA3A9, 0xFF0A, 0xA3AA, 0xFF0B, 0xA3AB, 0xFF0C, 0xA3AC,
+	0xFF0D, 0xA3AD, 0xFF0E, 0xA3AE, 0xFF0F, 0xA3AF, 0xFF10, 0xA3B0,
+	0xFF11, 0xA3B1, 0xFF12, 0xA3B2, 0xFF13, 0xA3B3, 0xFF14, 0xA3B4,
+	0xFF15, 0xA3B5, 0xFF16, 0xA3B6, 0xFF17, 0xA3B7, 0xFF18, 0xA3B8,
+	0xFF19, 0xA3B9, 0xFF1A, 0xA3BA, 0xFF1B, 0xA3BB, 0xFF1C, 0xA3BC,
+	0xFF1D, 0xA3BD, 0xFF1E, 0xA3BE, 0xFF1F, 0xA3BF, 0xFF20, 0xA3C0,
+	0xFF21, 0xA3C1, 0xFF22, 0xA3C2, 0xFF23, 0xA3C3, 0xFF24, 0xA3C4,
+	0xFF25, 0xA3C5, 0xFF26, 0xA3C6, 0xFF27, 0xA3C7, 0xFF28, 0xA3C8,
+	0xFF29, 0xA3C9, 0xFF2A, 0xA3CA, 0xFF2B, 0xA3CB, 0xFF2C, 0xA3CC,
+	0xFF2D, 0xA3CD, 0xFF2E, 0xA3CE, 0xFF2F, 0xA3CF, 0xFF30, 0xA3D0,
+	0xFF31, 0xA3D1, 0xFF32, 0xA3D2, 0xFF33, 0xA3D3, 0xFF34, 0xA3D4,
+	0xFF35, 0xA3D5, 0xFF36, 0xA3D6, 0xFF37, 0xA3D7, 0xFF38, 0xA3D8,
+	0xFF39, 0xA3D9, 0xFF3A, 0xA3DA, 0xFF3B, 0xA3DB, 0xFF3C, 0xA3DC,
+	0xFF3D, 0xA3DD, 0xFF3E, 0xA3DE, 0xFF3F, 0xA3DF, 0xFF40, 0xA3E0,
+	0xFF41, 0xA3E1, 0xFF42, 0xA3E2, 0xFF43, 0xA3E3, 0xFF44, 0xA3E4,
+	0xFF45, 0xA3E5, 0xFF46, 0xA3E6, 0xFF47, 0xA3E7, 0xFF48, 0xA3E8,
+	0xFF49, 0xA3E9, 0xFF4A, 0xA3EA, 0xFF4B, 0xA3EB, 0xFF4C, 0xA3EC,
+	0xFF4D, 0xA3ED, 0xFF4E, 0xA3EE, 0xFF4F, 0xA3EF, 0xFF50, 0xA3F0,
+	0xFF51, 0xA3F1, 0xFF52, 0xA3F2, 0xFF53, 0xA3F3, 0xFF54, 0xA3F4,
+	0xFF55, 0xA3F5, 0xFF56, 0xA3F6, 0xFF57, 0xA3F7, 0xFF58, 0xA3F8,
+	0xFF59, 0xA3F9, 0xFF5A, 0xA3FA, 0xFF5B, 0xA3FB, 0xFF5C, 0xA3FC,
+	0xFF5D, 0xA3FD, 0xFF5E, 0xA1AB, 0xFFE0, 0xA1E9, 0xFFE1, 0xA1EA,
+	0xFFE2, 0xA956, 0xFFE3, 0xA3FE, 0xFFE4, 0xA957, 0xFFE5, 0xA3A4,
+	0, 0
+};
+
+static
+const WCHAR oem2uni[] = {
+/*	OEM - Unicode,  OEM - Unicode,  OEM - Unicode,  OEM - Unicode */
+	0x0080, 0x20AC, 0x8140, 0x4E02, 0x8141, 0x4E04, 0x8142, 0x4E05,
+	0x8143, 0x4E06, 0x8144, 0x4E0F, 0x8145, 0x4E12, 0x8146, 0x4E17,
+	0x8147, 0x4E1F, 0x8148, 0x4E20, 0x8149, 0x4E21, 0x814A, 0x4E23,
+	0x814B, 0x4E26, 0x814C, 0x4E29, 0x814D, 0x4E2E, 0x814E, 0x4E2F,
+	0x814F, 0x4E31, 0x8150, 0x4E33, 0x8151, 0x4E35, 0x8152, 0x4E37,
+	0x8153, 0x4E3C, 0x8154, 0x4E40, 0x8155, 0x4E41, 0x8156, 0x4E42,
+	0x8157, 0x4E44, 0x8158, 0x4E46, 0x8159, 0x4E4A, 0x815A, 0x4E51,
+	0x815B, 0x4E55, 0x815C, 0x4E57, 0x815D, 0x4E5A, 0x815E, 0x4E5B,
+	0x815F, 0x4E62, 0x8160, 0x4E63, 0x8161, 0x4E64, 0x8162, 0x4E65,
+	0x8163, 0x4E67, 0x8164, 0x4E68, 0x8165, 0x4E6A, 0x8166, 0x4E6B,
+	0x8167, 0x4E6C, 0x8168, 0x4E6D, 0x8169, 0x4E6E, 0x816A, 0x4E6F,
+	0x816B, 0x4E72, 0x816C, 0x4E74, 0x816D, 0x4E75, 0x816E, 0x4E76,
+	0x816F, 0x4E77, 0x8170, 0x4E78, 0x8171, 0x4E79, 0x8172, 0x4E7A,
+	0x8173, 0x4E7B, 0x8174, 0x4E7C, 0x8175, 0x4E7D, 0x8176, 0x4E7F,
+	0x8177, 0x4E80, 0x8178, 0x4E81, 0x8179, 0x4E82, 0x817A, 0x4E83,
+	0x817B, 0x4E84, 0x817C, 0x4E85, 0x817D, 0x4E87, 0x817E, 0x4E8A,
+	0x8180, 0x4E90, 0x8181, 0x4E96, 0x8182, 0x4E97, 0x8183, 0x4E99,
+	0x8184, 0x4E9C, 0x8185, 0x4E9D, 0x8186, 0x4E9E, 0x8187, 0x4EA3,
+	0x8188, 0x4EAA, 0x8189, 0x4EAF, 0x818A, 0x4EB0, 0x818B, 0x4EB1,
+	0x818C, 0x4EB4, 0x818D, 0x4EB6, 0x818E, 0x4EB7, 0x818F, 0x4EB8,
+	0x8190, 0x4EB9, 0x8191, 0x4EBC, 0x8192, 0x4EBD, 0x8193, 0x4EBE,
+	0x8194, 0x4EC8, 0x8195, 0x4ECC, 0x8196, 0x4ECF, 0x8197, 0x4ED0,
+	0x8198, 0x4ED2, 0x8199, 0x4EDA, 0x819A, 0x4EDB, 0x819B, 0x4EDC,
+	0x819C, 0x4EE0, 0x819D, 0x4EE2, 0x819E, 0x4EE6, 0x819F, 0x4EE7,
+	0x81A0, 0x4EE9, 0x81A1, 0x4EED, 0x81A2, 0x4EEE, 0x81A3, 0x4EEF,
+	0x81A4, 0x4EF1, 0x81A5, 0x4EF4, 0x81A6, 0x4EF8, 0x81A7, 0x4EF9,
+	0x81A8, 0x4EFA, 0x81A9, 0x4EFC, 0x81AA, 0x4EFE, 0x81AB, 0x4F00,
+	0x81AC, 0x4F02, 0x81AD, 0x4F03, 0x81AE, 0x4F04, 0x81AF, 0x4F05,
+	0x81B0, 0x4F06, 0x81B1, 0x4F07, 0x81B2, 0x4F08, 0x81B3, 0x4F0B,
+	0x81B4, 0x4F0C, 0x81B5, 0x4F12, 0x81B6, 0x4F13, 0x81B7, 0x4F14,
+	0x81B8, 0x4F15, 0x81B9, 0x4F16, 0x81BA, 0x4F1C, 0x81BB, 0x4F1D,
+	0x81BC, 0x4F21, 0x81BD, 0x4F23, 0x81BE, 0x4F28, 0x81BF, 0x4F29,
+	0x81C0, 0x4F2C, 0x81C1, 0x4F2D, 0x81C2, 0x4F2E, 0x81C3, 0x4F31,
+	0x81C4, 0x4F33, 0x81C5, 0x4F35, 0x81C6, 0x4F37, 0x81C7, 0x4F39,
+	0x81C8, 0x4F3B, 0x81C9, 0x4F3E, 0x81CA, 0x4F3F, 0x81CB, 0x4F40,
+	0x81CC, 0x4F41, 0x81CD, 0x4F42, 0x81CE, 0x4F44, 0x81CF, 0x4F45,
+	0x81D0, 0x4F47, 0x81D1, 0x4F48, 0x81D2, 0x4F49, 0x81D3, 0x4F4A,
+	0x81D4, 0x4F4B, 0x81D5, 0x4F4C, 0x81D6, 0x4F52, 0x81D7, 0x4F54,
+	0x81D8, 0x4F56, 0x81D9, 0x4F61, 0x81DA, 0x4F62, 0x81DB, 0x4F66,
+	0x81DC, 0x4F68, 0x81DD, 0x4F6A, 0x81DE, 0x4F6B, 0x81DF, 0x4F6D,
+	0x81E0, 0x4F6E, 0x81E1, 0x4F71, 0x81E2, 0x4F72, 0x81E3, 0x4F75,
+	0x81E4, 0x4F77, 0x81E5, 0x4F78, 0x81E6, 0x4F79, 0x81E7, 0x4F7A,
+	0x81E8, 0x4F7D, 0x81E9, 0x4F80, 0x81EA, 0x4F81, 0x81EB, 0x4F82,
+	0x81EC, 0x4F85, 0x81ED, 0x4F86, 0x81EE, 0x4F87, 0x81EF, 0x4F8A,
+	0x81F0, 0x4F8C, 0x81F1, 0x4F8E, 0x81F2, 0x4F90, 0x81F3, 0x4F92,
+	0x81F4, 0x4F93, 0x81F5, 0x4F95, 0x81F6, 0x4F96, 0x81F7, 0x4F98,
+	0x81F8, 0x4F99, 0x81F9, 0x4F9A, 0x81FA, 0x4F9C, 0x81FB, 0x4F9E,
+	0x81FC, 0x4F9F, 0x81FD, 0x4FA1, 0x81FE, 0x4FA2, 0x8240, 0x4FA4,
+	0x8241, 0x4FAB, 0x8242, 0x4FAD, 0x8243, 0x4FB0, 0x8244, 0x4FB1,
+	0x8245, 0x4FB2, 0x8246, 0x4FB3, 0x8247, 0x4FB4, 0x8248, 0x4FB6,
+	0x8249, 0x4FB7, 0x824A, 0x4FB8, 0x824B, 0x4FB9, 0x824C, 0x4FBA,
+	0x824D, 0x4FBB, 0x824E, 0x4FBC, 0x824F, 0x4FBD, 0x8250, 0x4FBE,
+	0x8251, 0x4FC0, 0x8252, 0x4FC1, 0x8253, 0x4FC2, 0x8254, 0x4FC6,
+	0x8255, 0x4FC7, 0x8256, 0x4FC8, 0x8257, 0x4FC9, 0x8258, 0x4FCB,
+	0x8259, 0x4FCC, 0x825A, 0x4FCD, 0x825B, 0x4FD2, 0x825C, 0x4FD3,
+	0x825D, 0x4FD4, 0x825E, 0x4FD5, 0x825F, 0x4FD6, 0x8260, 0x4FD9,
+	0x8261, 0x4FDB, 0x8262, 0x4FE0, 0x8263, 0x4FE2, 0x8264, 0x4FE4,
+	0x8265, 0x4FE5, 0x8266, 0x4FE7, 0x8267, 0x4FEB, 0x8268, 0x4FEC,
+	0x8269, 0x4FF0, 0x826A, 0x4FF2, 0x826B, 0x4FF4, 0x826C, 0x4FF5,
+	0x826D, 0x4FF6, 0x826E, 0x4FF7, 0x826F, 0x4FF9, 0x8270, 0x4FFB,
+	0x8271, 0x4FFC, 0x8272, 0x4FFD, 0x8273, 0x4FFF, 0x8274, 0x5000,
+	0x8275, 0x5001, 0x8276, 0x5002, 0x8277, 0x5003, 0x8278, 0x5004,
+	0x8279, 0x5005, 0x827A, 0x5006, 0x827B, 0x5007, 0x827C, 0x5008,
+	0x827D, 0x5009, 0x827E, 0x500A, 0x8280, 0x500B, 0x8281, 0x500E,
+	0x8282, 0x5010, 0x8283, 0x5011, 0x8284, 0x5013, 0x8285, 0x5015,
+	0x8286, 0x5016, 0x8287, 0x5017, 0x8288, 0x501B, 0x8289, 0x501D,
+	0x828A, 0x501E, 0x828B, 0x5020, 0x828C, 0x5022, 0x828D, 0x5023,
+	0x828E, 0x5024, 0x828F, 0x5027, 0x8290, 0x502B, 0x8291, 0x502F,
+	0x8292, 0x5030, 0x8293, 0x5031, 0x8294, 0x5032, 0x8295, 0x5033,
+	0x8296, 0x5034, 0x8297, 0x5035, 0x8298, 0x5036, 0x8299, 0x5037,
+	0x829A, 0x5038, 0x829B, 0x5039, 0x829C, 0x503B, 0x829D, 0x503D,
+	0x829E, 0x503F, 0x829F, 0x5040, 0x82A0, 0x5041, 0x82A1, 0x5042,
+	0x82A2, 0x5044, 0x82A3, 0x5045, 0x82A4, 0x5046, 0x82A5, 0x5049,
+	0x82A6, 0x504A, 0x82A7, 0x504B, 0x82A8, 0x504D, 0x82A9, 0x5050,
+	0x82AA, 0x5051, 0x82AB, 0x5052, 0x82AC, 0x5053, 0x82AD, 0x5054,
+	0x82AE, 0x5056, 0x82AF, 0x5057, 0x82B0, 0x5058, 0x82B1, 0x5059,
+	0x82B2, 0x505B, 0x82B3, 0x505D, 0x82B4, 0x505E, 0x82B5, 0x505F,
+	0x82B6, 0x5060, 0x82B7, 0x5061, 0x82B8, 0x5062, 0x82B9, 0x5063,
+	0x82BA, 0x5064, 0x82BB, 0x5066, 0x82BC, 0x5067, 0x82BD, 0x5068,
+	0x82BE, 0x5069, 0x82BF, 0x506A, 0x82C0, 0x506B, 0x82C1, 0x506D,
+	0x82C2, 0x506E, 0x82C3, 0x506F, 0x82C4, 0x5070, 0x82C5, 0x5071,
+	0x82C6, 0x5072, 0x82C7, 0x5073, 0x82C8, 0x5074, 0x82C9, 0x5075,
+	0x82CA, 0x5078, 0x82CB, 0x5079, 0x82CC, 0x507A, 0x82CD, 0x507C,
+	0x82CE, 0x507D, 0x82CF, 0x5081, 0x82D0, 0x5082, 0x82D1, 0x5083,
+	0x82D2, 0x5084, 0x82D3, 0x5086, 0x82D4, 0x5087, 0x82D5, 0x5089,
+	0x82D6, 0x508A, 0x82D7, 0x508B, 0x82D8, 0x508C, 0x82D9, 0x508E,
+	0x82DA, 0x508F, 0x82DB, 0x5090, 0x82DC, 0x5091, 0x82DD, 0x5092,
+	0x82DE, 0x5093, 0x82DF, 0x5094, 0x82E0, 0x5095, 0x82E1, 0x5096,
+	0x82E2, 0x5097, 0x82E3, 0x5098, 0x82E4, 0x5099, 0x82E5, 0x509A,
+	0x82E6, 0x509B, 0x82E7, 0x509C, 0x82E8, 0x509D, 0x82E9, 0x509E,
+	0x82EA, 0x509F, 0x82EB, 0x50A0, 0x82EC, 0x50A1, 0x82ED, 0x50A2,
+	0x82EE, 0x50A4, 0x82EF, 0x50A6, 0x82F0, 0x50AA, 0x82F1, 0x50AB,
+	0x82F2, 0x50AD, 0x82F3, 0x50AE, 0x82F4, 0x50AF, 0x82F5, 0x50B0,
+	0x82F6, 0x50B1, 0x82F7, 0x50B3, 0x82F8, 0x50B4, 0x82F9, 0x50B5,
+	0x82FA, 0x50B6, 0x82FB, 0x50B7, 0x82FC, 0x50B8, 0x82FD, 0x50B9,
+	0x82FE, 0x50BC, 0x8340, 0x50BD, 0x8341, 0x50BE, 0x8342, 0x50BF,
+	0x8343, 0x50C0, 0x8344, 0x50C1, 0x8345, 0x50C2, 0x8346, 0x50C3,
+	0x8347, 0x50C4, 0x8348, 0x50C5, 0x8349, 0x50C6, 0x834A, 0x50C7,
+	0x834B, 0x50C8, 0x834C, 0x50C9, 0x834D, 0x50CA, 0x834E, 0x50CB,
+	0x834F, 0x50CC, 0x8350, 0x50CD, 0x8351, 0x50CE, 0x8352, 0x50D0,
+	0x8353, 0x50D1, 0x8354, 0x50D2, 0x8355, 0x50D3, 0x8356, 0x50D4,
+	0x8357, 0x50D5, 0x8358, 0x50D7, 0x8359, 0x50D8, 0x835A, 0x50D9,
+	0x835B, 0x50DB, 0x835C, 0x50DC, 0x835D, 0x50DD, 0x835E, 0x50DE,
+	0x835F, 0x50DF, 0x8360, 0x50E0, 0x8361, 0x50E1, 0x8362, 0x50E2,
+	0x8363, 0x50E3, 0x8364, 0x50E4, 0x8365, 0x50E5, 0x8366, 0x50E8,
+	0x8367, 0x50E9, 0x8368, 0x50EA, 0x8369, 0x50EB, 0x836A, 0x50EF,
+	0x836B, 0x50F0, 0x836C, 0x50F1, 0x836D, 0x50F2, 0x836E, 0x50F4,
+	0x836F, 0x50F6, 0x8370, 0x50F7, 0x8371, 0x50F8, 0x8372, 0x50F9,
+	0x8373, 0x50FA, 0x8374, 0x50FC, 0x8375, 0x50FD, 0x8376, 0x50FE,
+	0x8377, 0x50FF, 0x8378, 0x5100, 0x8379, 0x5101, 0x837A, 0x5102,
+	0x837B, 0x5103, 0x837C, 0x5104, 0x837D, 0x5105, 0x837E, 0x5108,
+	0x8380, 0x5109, 0x8381, 0x510A, 0x8382, 0x510C, 0x8383, 0x510D,
+	0x8384, 0x510E, 0x8385, 0x510F, 0x8386, 0x5110, 0x8387, 0x5111,
+	0x8388, 0x5113, 0x8389, 0x5114, 0x838A, 0x5115, 0x838B, 0x5116,
+	0x838C, 0x5117, 0x838D, 0x5118, 0x838E, 0x5119, 0x838F, 0x511A,
+	0x8390, 0x511B, 0x8391, 0x511C, 0x8392, 0x511D, 0x8393, 0x511E,
+	0x8394, 0x511F, 0x8395, 0x5120, 0x8396, 0x5122, 0x8397, 0x5123,
+	0x8398, 0x5124, 0x8399, 0x5125, 0x839A, 0x5126, 0x839B, 0x5127,
+	0x839C, 0x5128, 0x839D, 0x5129, 0x839E, 0x512A, 0x839F, 0x512B,
+	0x83A0, 0x512C, 0x83A1, 0x512D, 0x83A2, 0x512E, 0x83A3, 0x512F,
+	0x83A4, 0x5130, 0x83A5, 0x5131, 0x83A6, 0x5132, 0x83A7, 0x5133,
+	0x83A8, 0x5134, 0x83A9, 0x5135, 0x83AA, 0x5136, 0x83AB, 0x5137,
+	0x83AC, 0x5138, 0x83AD, 0x5139, 0x83AE, 0x513A, 0x83AF, 0x513B,
+	0x83B0, 0x513C, 0x83B1, 0x513D, 0x83B2, 0x513E, 0x83B3, 0x5142,
+	0x83B4, 0x5147, 0x83B5, 0x514A, 0x83B6, 0x514C, 0x83B7, 0x514E,
+	0x83B8, 0x514F, 0x83B9, 0x5150, 0x83BA, 0x5152, 0x83BB, 0x5153,
+	0x83BC, 0x5157, 0x83BD, 0x5158, 0x83BE, 0x5159, 0x83BF, 0x515B,
+	0x83C0, 0x515D, 0x83C1, 0x515E, 0x83C2, 0x515F, 0x83C3, 0x5160,
+	0x83C4, 0x5161, 0x83C5, 0x5163, 0x83C6, 0x5164, 0x83C7, 0x5166,
+	0x83C8, 0x5167, 0x83C9, 0x5169, 0x83CA, 0x516A, 0x83CB, 0x516F,
+	0x83CC, 0x5172, 0x83CD, 0x517A, 0x83CE, 0x517E, 0x83CF, 0x517F,
+	0x83D0, 0x5183, 0x83D1, 0x5184, 0x83D2, 0x5186, 0x83D3, 0x5187,
+	0x83D4, 0x518A, 0x83D5, 0x518B, 0x83D6, 0x518E, 0x83D7, 0x518F,
+	0x83D8, 0x5190, 0x83D9, 0x5191, 0x83DA, 0x5193, 0x83DB, 0x5194,
+	0x83DC, 0x5198, 0x83DD, 0x519A, 0x83DE, 0x519D, 0x83DF, 0x519E,
+	0x83E0, 0x519F, 0x83E1, 0x51A1, 0x83E2, 0x51A3, 0x83E3, 0x51A6,
+	0x83E4, 0x51A7, 0x83E5, 0x51A8, 0x83E6, 0x51A9, 0x83E7, 0x51AA,
+	0x83E8, 0x51AD, 0x83E9, 0x51AE, 0x83EA, 0x51B4, 0x83EB, 0x51B8,
+	0x83EC, 0x51B9, 0x83ED, 0x51BA, 0x83EE, 0x51BE, 0x83EF, 0x51BF,
+	0x83F0, 0x51C1, 0x83F1, 0x51C2, 0x83F2, 0x51C3, 0x83F3, 0x51C5,
+	0x83F4, 0x51C8, 0x83F5, 0x51CA, 0x83F6, 0x51CD, 0x83F7, 0x51CE,
+	0x83F8, 0x51D0, 0x83F9, 0x51D2, 0x83FA, 0x51D3, 0x83FB, 0x51D4,
+	0x83FC, 0x51D5, 0x83FD, 0x51D6, 0x83FE, 0x51D7, 0x8440, 0x51D8,
+	0x8441, 0x51D9, 0x8442, 0x51DA, 0x8443, 0x51DC, 0x8444, 0x51DE,
+	0x8445, 0x51DF, 0x8446, 0x51E2, 0x8447, 0x51E3, 0x8448, 0x51E5,
+	0x8449, 0x51E6, 0x844A, 0x51E7, 0x844B, 0x51E8, 0x844C, 0x51E9,
+	0x844D, 0x51EA, 0x844E, 0x51EC, 0x844F, 0x51EE, 0x8450, 0x51F1,
+	0x8451, 0x51F2, 0x8452, 0x51F4, 0x8453, 0x51F7, 0x8454, 0x51FE,
+	0x8455, 0x5204, 0x8456, 0x5205, 0x8457, 0x5209, 0x8458, 0x520B,
+	0x8459, 0x520C, 0x845A, 0x520F, 0x845B, 0x5210, 0x845C, 0x5213,
+	0x845D, 0x5214, 0x845E, 0x5215, 0x845F, 0x521C, 0x8460, 0x521E,
+	0x8461, 0x521F, 0x8462, 0x5221, 0x8463, 0x5222, 0x8464, 0x5223,
+	0x8465, 0x5225, 0x8466, 0x5226, 0x8467, 0x5227, 0x8468, 0x522A,
+	0x8469, 0x522C, 0x846A, 0x522F, 0x846B, 0x5231, 0x846C, 0x5232,
+	0x846D, 0x5234, 0x846E, 0x5235, 0x846F, 0x523C, 0x8470, 0x523E,
+	0x8471, 0x5244, 0x8472, 0x5245, 0x8473, 0x5246, 0x8474, 0x5247,
+	0x8475, 0x5248, 0x8476, 0x5249, 0x8477, 0x524B, 0x8478, 0x524E,
+	0x8479, 0x524F, 0x847A, 0x5252, 0x847B, 0x5253, 0x847C, 0x5255,
+	0x847D, 0x5257, 0x847E, 0x5258, 0x8480, 0x5259, 0x8481, 0x525A,
+	0x8482, 0x525B, 0x8483, 0x525D, 0x8484, 0x525F, 0x8485, 0x5260,
+	0x8486, 0x5262, 0x8487, 0x5263, 0x8488, 0x5264, 0x8489, 0x5266,
+	0x848A, 0x5268, 0x848B, 0x526B, 0x848C, 0x526C, 0x848D, 0x526D,
+	0x848E, 0x526E, 0x848F, 0x5270, 0x8490, 0x5271, 0x8491, 0x5273,
+	0x8492, 0x5274, 0x8493, 0x5275, 0x8494, 0x5276, 0x8495, 0x5277,
+	0x8496, 0x5278, 0x8497, 0x5279, 0x8498, 0x527A, 0x8499, 0x527B,
+	0x849A, 0x527C, 0x849B, 0x527E, 0x849C, 0x5280, 0x849D, 0x5283,
+	0x849E, 0x5284, 0x849F, 0x5285, 0x84A0, 0x5286, 0x84A1, 0x5287,
+	0x84A2, 0x5289, 0x84A3, 0x528A, 0x84A4, 0x528B, 0x84A5, 0x528C,
+	0x84A6, 0x528D, 0x84A7, 0x528E, 0x84A8, 0x528F, 0x84A9, 0x5291,
+	0x84AA, 0x5292, 0x84AB, 0x5294, 0x84AC, 0x5295, 0x84AD, 0x5296,
+	0x84AE, 0x5297, 0x84AF, 0x5298, 0x84B0, 0x5299, 0x84B1, 0x529A,
+	0x84B2, 0x529C, 0x84B3, 0x52A4, 0x84B4, 0x52A5, 0x84B5, 0x52A6,
+	0x84B6, 0x52A7, 0x84B7, 0x52AE, 0x84B8, 0x52AF, 0x84B9, 0x52B0,
+	0x84BA, 0x52B4, 0x84BB, 0x52B5, 0x84BC, 0x52B6, 0x84BD, 0x52B7,
+	0x84BE, 0x52B8, 0x84BF, 0x52B9, 0x84C0, 0x52BA, 0x84C1, 0x52BB,
+	0x84C2, 0x52BC, 0x84C3, 0x52BD, 0x84C4, 0x52C0, 0x84C5, 0x52C1,
+	0x84C6, 0x52C2, 0x84C7, 0x52C4, 0x84C8, 0x52C5, 0x84C9, 0x52C6,
+	0x84CA, 0x52C8, 0x84CB, 0x52CA, 0x84CC, 0x52CC, 0x84CD, 0x52CD,
+	0x84CE, 0x52CE, 0x84CF, 0x52CF, 0x84D0, 0x52D1, 0x84D1, 0x52D3,
+	0x84D2, 0x52D4, 0x84D3, 0x52D5, 0x84D4, 0x52D7, 0x84D5, 0x52D9,
+	0x84D6, 0x52DA, 0x84D7, 0x52DB, 0x84D8, 0x52DC, 0x84D9, 0x52DD,
+	0x84DA, 0x52DE, 0x84DB, 0x52E0, 0x84DC, 0x52E1, 0x84DD, 0x52E2,
+	0x84DE, 0x52E3, 0x84DF, 0x52E5, 0x84E0, 0x52E6, 0x84E1, 0x52E7,
+	0x84E2, 0x52E8, 0x84E3, 0x52E9, 0x84E4, 0x52EA, 0x84E5, 0x52EB,
+	0x84E6, 0x52EC, 0x84E7, 0x52ED, 0x84E8, 0x52EE, 0x84E9, 0x52EF,
+	0x84EA, 0x52F1, 0x84EB, 0x52F2, 0x84EC, 0x52F3, 0x84ED, 0x52F4,
+	0x84EE, 0x52F5, 0x84EF, 0x52F6, 0x84F0, 0x52F7, 0x84F1, 0x52F8,
+	0x84F2, 0x52FB, 0x84F3, 0x52FC, 0x84F4, 0x52FD, 0x84F5, 0x5301,
+	0x84F6, 0x5302, 0x84F7, 0x5303, 0x84F8, 0x5304, 0x84F9, 0x5307,
+	0x84FA, 0x5309, 0x84FB, 0x530A, 0x84FC, 0x530B, 0x84FD, 0x530C,
+	0x84FE, 0x530E, 0x8540, 0x5311, 0x8541, 0x5312, 0x8542, 0x5313,
+	0x8543, 0x5314, 0x8544, 0x5318, 0x8545, 0x531B, 0x8546, 0x531C,
+	0x8547, 0x531E, 0x8548, 0x531F, 0x8549, 0x5322, 0x854A, 0x5324,
+	0x854B, 0x5325, 0x854C, 0x5327, 0x854D, 0x5328, 0x854E, 0x5329,
+	0x854F, 0x532B, 0x8550, 0x532C, 0x8551, 0x532D, 0x8552, 0x532F,
+	0x8553, 0x5330, 0x8554, 0x5331, 0x8555, 0x5332, 0x8556, 0x5333,
+	0x8557, 0x5334, 0x8558, 0x5335, 0x8559, 0x5336, 0x855A, 0x5337,
+	0x855B, 0x5338, 0x855C, 0x533C, 0x855D, 0x533D, 0x855E, 0x5340,
+	0x855F, 0x5342, 0x8560, 0x5344, 0x8561, 0x5346, 0x8562, 0x534B,
+	0x8563, 0x534C, 0x8564, 0x534D, 0x8565, 0x5350, 0x8566, 0x5354,
+	0x8567, 0x5358, 0x8568, 0x5359, 0x8569, 0x535B, 0x856A, 0x535D,
+	0x856B, 0x5365, 0x856C, 0x5368, 0x856D, 0x536A, 0x856E, 0x536C,
+	0x856F, 0x536D, 0x8570, 0x5372, 0x8571, 0x5376, 0x8572, 0x5379,
+	0x8573, 0x537B, 0x8574, 0x537C, 0x8575, 0x537D, 0x8576, 0x537E,
+	0x8577, 0x5380, 0x8578, 0x5381, 0x8579, 0x5383, 0x857A, 0x5387,
+	0x857B, 0x5388, 0x857C, 0x538A, 0x857D, 0x538E, 0x857E, 0x538F,
+	0x8580, 0x5390, 0x8581, 0x5391, 0x8582, 0x5392, 0x8583, 0x5393,
+	0x8584, 0x5394, 0x8585, 0x5396, 0x8586, 0x5397, 0x8587, 0x5399,
+	0x8588, 0x539B, 0x8589, 0x539C, 0x858A, 0x539E, 0x858B, 0x53A0,
+	0x858C, 0x53A1, 0x858D, 0x53A4, 0x858E, 0x53A7, 0x858F, 0x53AA,
+	0x8590, 0x53AB, 0x8591, 0x53AC, 0x8592, 0x53AD, 0x8593, 0x53AF,
+	0x8594, 0x53B0, 0x8595, 0x53B1, 0x8596, 0x53B2, 0x8597, 0x53B3,
+	0x8598, 0x53B4, 0x8599, 0x53B5, 0x859A, 0x53B7, 0x859B, 0x53B8,
+	0x859C, 0x53B9, 0x859D, 0x53BA, 0x859E, 0x53BC, 0x859F, 0x53BD,
+	0x85A0, 0x53BE, 0x85A1, 0x53C0, 0x85A2, 0x53C3, 0x85A3, 0x53C4,
+	0x85A4, 0x53C5, 0x85A5, 0x53C6, 0x85A6, 0x53C7, 0x85A7, 0x53CE,
+	0x85A8, 0x53CF, 0x85A9, 0x53D0, 0x85AA, 0x53D2, 0x85AB, 0x53D3,
+	0x85AC, 0x53D5, 0x85AD, 0x53DA, 0x85AE, 0x53DC, 0x85AF, 0x53DD,
+	0x85B0, 0x53DE, 0x85B1, 0x53E1, 0x85B2, 0x53E2, 0x85B3, 0x53E7,
+	0x85B4, 0x53F4, 0x85B5, 0x53FA, 0x85B6, 0x53FE, 0x85B7, 0x53FF,
+	0x85B8, 0x5400, 0x85B9, 0x5402, 0x85BA, 0x5405, 0x85BB, 0x5407,
+	0x85BC, 0x540B, 0x85BD, 0x5414, 0x85BE, 0x5418, 0x85BF, 0x5419,
+	0x85C0, 0x541A, 0x85C1, 0x541C, 0x85C2, 0x5422, 0x85C3, 0x5424,
+	0x85C4, 0x5425, 0x85C5, 0x542A, 0x85C6, 0x5430, 0x85C7, 0x5433,
+	0x85C8, 0x5436, 0x85C9, 0x5437, 0x85CA, 0x543A, 0x85CB, 0x543D,
+	0x85CC, 0x543F, 0x85CD, 0x5441, 0x85CE, 0x5442, 0x85CF, 0x5444,
+	0x85D0, 0x5445, 0x85D1, 0x5447, 0x85D2, 0x5449, 0x85D3, 0x544C,
+	0x85D4, 0x544D, 0x85D5, 0x544E, 0x85D6, 0x544F, 0x85D7, 0x5451,
+	0x85D8, 0x545A, 0x85D9, 0x545D, 0x85DA, 0x545E, 0x85DB, 0x545F,
+	0x85DC, 0x5460, 0x85DD, 0x5461, 0x85DE, 0x5463, 0x85DF, 0x5465,
+	0x85E0, 0x5467, 0x85E1, 0x5469, 0x85E2, 0x546A, 0x85E3, 0x546B,
+	0x85E4, 0x546C, 0x85E5, 0x546D, 0x85E6, 0x546E, 0x85E7, 0x546F,
+	0x85E8, 0x5470, 0x85E9, 0x5474, 0x85EA, 0x5479, 0x85EB, 0x547A,
+	0x85EC, 0x547E, 0x85ED, 0x547F, 0x85EE, 0x5481, 0x85EF, 0x5483,
+	0x85F0, 0x5485, 0x85F1, 0x5487, 0x85F2, 0x5488, 0x85F3, 0x5489,
+	0x85F4, 0x548A, 0x85F5, 0x548D, 0x85F6, 0x5491, 0x85F7, 0x5493,
+	0x85F8, 0x5497, 0x85F9, 0x5498, 0x85FA, 0x549C, 0x85FB, 0x549E,
+	0x85FC, 0x549F, 0x85FD, 0x54A0, 0x85FE, 0x54A1, 0x8640, 0x54A2,
+	0x8641, 0x54A5, 0x8642, 0x54AE, 0x8643, 0x54B0, 0x8644, 0x54B2,
+	0x8645, 0x54B5, 0x8646, 0x54B6, 0x8647, 0x54B7, 0x8648, 0x54B9,
+	0x8649, 0x54BA, 0x864A, 0x54BC, 0x864B, 0x54BE, 0x864C, 0x54C3,
+	0x864D, 0x54C5, 0x864E, 0x54CA, 0x864F, 0x54CB, 0x8650, 0x54D6,
+	0x8651, 0x54D8, 0x8652, 0x54DB, 0x8653, 0x54E0, 0x8654, 0x54E1,
+	0x8655, 0x54E2, 0x8656, 0x54E3, 0x8657, 0x54E4, 0x8658, 0x54EB,
+	0x8659, 0x54EC, 0x865A, 0x54EF, 0x865B, 0x54F0, 0x865C, 0x54F1,
+	0x865D, 0x54F4, 0x865E, 0x54F5, 0x865F, 0x54F6, 0x8660, 0x54F7,
+	0x8661, 0x54F8, 0x8662, 0x54F9, 0x8663, 0x54FB, 0x8664, 0x54FE,
+	0x8665, 0x5500, 0x8666, 0x5502, 0x8667, 0x5503, 0x8668, 0x5504,
+	0x8669, 0x5505, 0x866A, 0x5508, 0x866B, 0x550A, 0x866C, 0x550B,
+	0x866D, 0x550C, 0x866E, 0x550D, 0x866F, 0x550E, 0x8670, 0x5512,
+	0x8671, 0x5513, 0x8672, 0x5515, 0x8673, 0x5516, 0x8674, 0x5517,
+	0x8675, 0x5518, 0x8676, 0x5519, 0x8677, 0x551A, 0x8678, 0x551C,
+	0x8679, 0x551D, 0x867A, 0x551E, 0x867B, 0x551F, 0x867C, 0x5521,
+	0x867D, 0x5525, 0x867E, 0x5526, 0x8680, 0x5528, 0x8681, 0x5529,
+	0x8682, 0x552B, 0x8683, 0x552D, 0x8684, 0x5532, 0x8685, 0x5534,
+	0x8686, 0x5535, 0x8687, 0x5536, 0x8688, 0x5538, 0x8689, 0x5539,
+	0x868A, 0x553A, 0x868B, 0x553B, 0x868C, 0x553D, 0x868D, 0x5540,
+	0x868E, 0x5542, 0x868F, 0x5545, 0x8690, 0x5547, 0x8691, 0x5548,
+	0x8692, 0x554B, 0x8693, 0x554C, 0x8694, 0x554D, 0x8695, 0x554E,
+	0x8696, 0x554F, 0x8697, 0x5551, 0x8698, 0x5552, 0x8699, 0x5553,
+	0x869A, 0x5554, 0x869B, 0x5557, 0x869C, 0x5558, 0x869D, 0x5559,
+	0x869E, 0x555A, 0x869F, 0x555B, 0x86A0, 0x555D, 0x86A1, 0x555E,
+	0x86A2, 0x555F, 0x86A3, 0x5560, 0x86A4, 0x5562, 0x86A5, 0x5563,
+	0x86A6, 0x5568, 0x86A7, 0x5569, 0x86A8, 0x556B, 0x86A9, 0x556F,
+	0x86AA, 0x5570, 0x86AB, 0x5571, 0x86AC, 0x5572, 0x86AD, 0x5573,
+	0x86AE, 0x5574, 0x86AF, 0x5579, 0x86B0, 0x557A, 0x86B1, 0x557D,
+	0x86B2, 0x557F, 0x86B3, 0x5585, 0x86B4, 0x5586, 0x86B5, 0x558C,
+	0x86B6, 0x558D, 0x86B7, 0x558E, 0x86B8, 0x5590, 0x86B9, 0x5592,
+	0x86BA, 0x5593, 0x86BB, 0x5595, 0x86BC, 0x5596, 0x86BD, 0x5597,
+	0x86BE, 0x559A, 0x86BF, 0x559B, 0x86C0, 0x559E, 0x86C1, 0x55A0,
+	0x86C2, 0x55A1, 0x86C3, 0x55A2, 0x86C4, 0x55A3, 0x86C5, 0x55A4,
+	0x86C6, 0x55A5, 0x86C7, 0x55A6, 0x86C8, 0x55A8, 0x86C9, 0x55A9,
+	0x86CA, 0x55AA, 0x86CB, 0x55AB, 0x86CC, 0x55AC, 0x86CD, 0x55AD,
+	0x86CE, 0x55AE, 0x86CF, 0x55AF, 0x86D0, 0x55B0, 0x86D1, 0x55B2,
+	0x86D2, 0x55B4, 0x86D3, 0x55B6, 0x86D4, 0x55B8, 0x86D5, 0x55BA,
+	0x86D6, 0x55BC, 0x86D7, 0x55BF, 0x86D8, 0x55C0, 0x86D9, 0x55C1,
+	0x86DA, 0x55C2, 0x86DB, 0x55C3, 0x86DC, 0x55C6, 0x86DD, 0x55C7,
+	0x86DE, 0x55C8, 0x86DF, 0x55CA, 0x86E0, 0x55CB, 0x86E1, 0x55CE,
+	0x86E2, 0x55CF, 0x86E3, 0x55D0, 0x86E4, 0x55D5, 0x86E5, 0x55D7,
+	0x86E6, 0x55D8, 0x86E7, 0x55D9, 0x86E8, 0x55DA, 0x86E9, 0x55DB,
+	0x86EA, 0x55DE, 0x86EB, 0x55E0, 0x86EC, 0x55E2, 0x86ED, 0x55E7,
+	0x86EE, 0x55E9, 0x86EF, 0x55ED, 0x86F0, 0x55EE, 0x86F1, 0x55F0,
+	0x86F2, 0x55F1, 0x86F3, 0x55F4, 0x86F4, 0x55F6, 0x86F5, 0x55F8,
+	0x86F6, 0x55F9, 0x86F7, 0x55FA, 0x86F8, 0x55FB, 0x86F9, 0x55FC,
+	0x86FA, 0x55FF, 0x86FB, 0x5602, 0x86FC, 0x5603, 0x86FD, 0x5604,
+	0x86FE, 0x5605, 0x8740, 0x5606, 0x8741, 0x5607, 0x8742, 0x560A,
+	0x8743, 0x560B, 0x8744, 0x560D, 0x8745, 0x5610, 0x8746, 0x5611,
+	0x8747, 0x5612, 0x8748, 0x5613, 0x8749, 0x5614, 0x874A, 0x5615,
+	0x874B, 0x5616, 0x874C, 0x5617, 0x874D, 0x5619, 0x874E, 0x561A,
+	0x874F, 0x561C, 0x8750, 0x561D, 0x8751, 0x5620, 0x8752, 0x5621,
+	0x8753, 0x5622, 0x8754, 0x5625, 0x8755, 0x5626, 0x8756, 0x5628,
+	0x8757, 0x5629, 0x8758, 0x562A, 0x8759, 0x562B, 0x875A, 0x562E,
+	0x875B, 0x562F, 0x875C, 0x5630, 0x875D, 0x5633, 0x875E, 0x5635,
+	0x875F, 0x5637, 0x8760, 0x5638, 0x8761, 0x563A, 0x8762, 0x563C,
+	0x8763, 0x563D, 0x8764, 0x563E, 0x8765, 0x5640, 0x8766, 0x5641,
+	0x8767, 0x5642, 0x8768, 0x5643, 0x8769, 0x5644, 0x876A, 0x5645,
+	0x876B, 0x5646, 0x876C, 0x5647, 0x876D, 0x5648, 0x876E, 0x5649,
+	0x876F, 0x564A, 0x8770, 0x564B, 0x8771, 0x564F, 0x8772, 0x5650,
+	0x8773, 0x5651, 0x8774, 0x5652, 0x8775, 0x5653, 0x8776, 0x5655,
+	0x8777, 0x5656, 0x8778, 0x565A, 0x8779, 0x565B, 0x877A, 0x565D,
+	0x877B, 0x565E, 0x877C, 0x565F, 0x877D, 0x5660, 0x877E, 0x5661,
+	0x8780, 0x5663, 0x8781, 0x5665, 0x8782, 0x5666, 0x8783, 0x5667,
+	0x8784, 0x566D, 0x8785, 0x566E, 0x8786, 0x566F, 0x8787, 0x5670,
+	0x8788, 0x5672, 0x8789, 0x5673, 0x878A, 0x5674, 0x878B, 0x5675,
+	0x878C, 0x5677, 0x878D, 0x5678, 0x878E, 0x5679, 0x878F, 0x567A,
+	0x8790, 0x567D, 0x8791, 0x567E, 0x8792, 0x567F, 0x8793, 0x5680,
+	0x8794, 0x5681, 0x8795, 0x5682, 0x8796, 0x5683, 0x8797, 0x5684,
+	0x8798, 0x5687, 0x8799, 0x5688, 0x879A, 0x5689, 0x879B, 0x568A,
+	0x879C, 0x568B, 0x879D, 0x568C, 0x879E, 0x568D, 0x879F, 0x5690,
+	0x87A0, 0x5691, 0x87A1, 0x5692, 0x87A2, 0x5694, 0x87A3, 0x5695,
+	0x87A4, 0x5696, 0x87A5, 0x5697, 0x87A6, 0x5698, 0x87A7, 0x5699,
+	0x87A8, 0x569A, 0x87A9, 0x569B, 0x87AA, 0x569C, 0x87AB, 0x569D,
+	0x87AC, 0x569E, 0x87AD, 0x569F, 0x87AE, 0x56A0, 0x87AF, 0x56A1,
+	0x87B0, 0x56A2, 0x87B1, 0x56A4, 0x87B2, 0x56A5, 0x87B3, 0x56A6,
+	0x87B4, 0x56A7, 0x87B5, 0x56A8, 0x87B6, 0x56A9, 0x87B7, 0x56AA,
+	0x87B8, 0x56AB, 0x87B9, 0x56AC, 0x87BA, 0x56AD, 0x87BB, 0x56AE,
+	0x87BC, 0x56B0, 0x87BD, 0x56B1, 0x87BE, 0x56B2, 0x87BF, 0x56B3,
+	0x87C0, 0x56B4, 0x87C1, 0x56B5, 0x87C2, 0x56B6, 0x87C3, 0x56B8,
+	0x87C4, 0x56B9, 0x87C5, 0x56BA, 0x87C6, 0x56BB, 0x87C7, 0x56BD,
+	0x87C8, 0x56BE, 0x87C9, 0x56BF, 0x87CA, 0x56C0, 0x87CB, 0x56C1,
+	0x87CC, 0x56C2, 0x87CD, 0x56C3, 0x87CE, 0x56C4, 0x87CF, 0x56C5,
+	0x87D0, 0x56C6, 0x87D1, 0x56C7, 0x87D2, 0x56C8, 0x87D3, 0x56C9,
+	0x87D4, 0x56CB, 0x87D5, 0x56CC, 0x87D6, 0x56CD, 0x87D7, 0x56CE,
+	0x87D8, 0x56CF, 0x87D9, 0x56D0, 0x87DA, 0x56D1, 0x87DB, 0x56D2,
+	0x87DC, 0x56D3, 0x87DD, 0x56D5, 0x87DE, 0x56D6, 0x87DF, 0x56D8,
+	0x87E0, 0x56D9, 0x87E1, 0x56DC, 0x87E2, 0x56E3, 0x87E3, 0x56E5,
+	0x87E4, 0x56E6, 0x87E5, 0x56E7, 0x87E6, 0x56E8, 0x87E7, 0x56E9,
+	0x87E8, 0x56EA, 0x87E9, 0x56EC, 0x87EA, 0x56EE, 0x87EB, 0x56EF,
+	0x87EC, 0x56F2, 0x87ED, 0x56F3, 0x87EE, 0x56F6, 0x87EF, 0x56F7,
+	0x87F0, 0x56F8, 0x87F1, 0x56FB, 0x87F2, 0x56FC, 0x87F3, 0x5700,
+	0x87F4, 0x5701, 0x87F5, 0x5702, 0x87F6, 0x5705, 0x87F7, 0x5707,
+	0x87F8, 0x570B, 0x87F9, 0x570C, 0x87FA, 0x570D, 0x87FB, 0x570E,
+	0x87FC, 0x570F, 0x87FD, 0x5710, 0x87FE, 0x5711, 0x8840, 0x5712,
+	0x8841, 0x5713, 0x8842, 0x5714, 0x8843, 0x5715, 0x8844, 0x5716,
+	0x8845, 0x5717, 0x8846, 0x5718, 0x8847, 0x5719, 0x8848, 0x571A,
+	0x8849, 0x571B, 0x884A, 0x571D, 0x884B, 0x571E, 0x884C, 0x5720,
+	0x884D, 0x5721, 0x884E, 0x5722, 0x884F, 0x5724, 0x8850, 0x5725,
+	0x8851, 0x5726, 0x8852, 0x5727, 0x8853, 0x572B, 0x8854, 0x5731,
+	0x8855, 0x5732, 0x8856, 0x5734, 0x8857, 0x5735, 0x8858, 0x5736,
+	0x8859, 0x5737, 0x885A, 0x5738, 0x885B, 0x573C, 0x885C, 0x573D,
+	0x885D, 0x573F, 0x885E, 0x5741, 0x885F, 0x5743, 0x8860, 0x5744,
+	0x8861, 0x5745, 0x8862, 0x5746, 0x8863, 0x5748, 0x8864, 0x5749,
+	0x8865, 0x574B, 0x8866, 0x5752, 0x8867, 0x5753, 0x8868, 0x5754,
+	0x8869, 0x5755, 0x886A, 0x5756, 0x886B, 0x5758, 0x886C, 0x5759,
+	0x886D, 0x5762, 0x886E, 0x5763, 0x886F, 0x5765, 0x8870, 0x5767,
+	0x8871, 0x576C, 0x8872, 0x576E, 0x8873, 0x5770, 0x8874, 0x5771,
+	0x8875, 0x5772, 0x8876, 0x5774, 0x8877, 0x5775, 0x8878, 0x5778,
+	0x8879, 0x5779, 0x887A, 0x577A, 0x887B, 0x577D, 0x887C, 0x577E,
+	0x887D, 0x577F, 0x887E, 0x5780, 0x8880, 0x5781, 0x8881, 0x5787,
+	0x8882, 0x5788, 0x8883, 0x5789, 0x8884, 0x578A, 0x8885, 0x578D,
+	0x8886, 0x578E, 0x8887, 0x578F, 0x8888, 0x5790, 0x8889, 0x5791,
+	0x888A, 0x5794, 0x888B, 0x5795, 0x888C, 0x5796, 0x888D, 0x5797,
+	0x888E, 0x5798, 0x888F, 0x5799, 0x8890, 0x579A, 0x8891, 0x579C,
+	0x8892, 0x579D, 0x8893, 0x579E, 0x8894, 0x579F, 0x8895, 0x57A5,
+	0x8896, 0x57A8, 0x8897, 0x57AA, 0x8898, 0x57AC, 0x8899, 0x57AF,
+	0x889A, 0x57B0, 0x889B, 0x57B1, 0x889C, 0x57B3, 0x889D, 0x57B5,
+	0x889E, 0x57B6, 0x889F, 0x57B7, 0x88A0, 0x57B9, 0x88A1, 0x57BA,
+	0x88A2, 0x57BB, 0x88A3, 0x57BC, 0x88A4, 0x57BD, 0x88A5, 0x57BE,
+	0x88A6, 0x57BF, 0x88A7, 0x57C0, 0x88A8, 0x57C1, 0x88A9, 0x57C4,
+	0x88AA, 0x57C5, 0x88AB, 0x57C6, 0x88AC, 0x57C7, 0x88AD, 0x57C8,
+	0x88AE, 0x57C9, 0x88AF, 0x57CA, 0x88B0, 0x57CC, 0x88B1, 0x57CD,
+	0x88B2, 0x57D0, 0x88B3, 0x57D1, 0x88B4, 0x57D3, 0x88B5, 0x57D6,
+	0x88B6, 0x57D7, 0x88B7, 0x57DB, 0x88B8, 0x57DC, 0x88B9, 0x57DE,
+	0x88BA, 0x57E1, 0x88BB, 0x57E2, 0x88BC, 0x57E3, 0x88BD, 0x57E5,
+	0x88BE, 0x57E6, 0x88BF, 0x57E7, 0x88C0, 0x57E8, 0x88C1, 0x57E9,
+	0x88C2, 0x57EA, 0x88C3, 0x57EB, 0x88C4, 0x57EC, 0x88C5, 0x57EE,
+	0x88C6, 0x57F0, 0x88C7, 0x57F1, 0x88C8, 0x57F2, 0x88C9, 0x57F3,
+	0x88CA, 0x57F5, 0x88CB, 0x57F6, 0x88CC, 0x57F7, 0x88CD, 0x57FB,
+	0x88CE, 0x57FC, 0x88CF, 0x57FE, 0x88D0, 0x57FF, 0x88D1, 0x5801,
+	0x88D2, 0x5803, 0x88D3, 0x5804, 0x88D4, 0x5805, 0x88D5, 0x5808,
+	0x88D6, 0x5809, 0x88D7, 0x580A, 0x88D8, 0x580C, 0x88D9, 0x580E,
+	0x88DA, 0x580F, 0x88DB, 0x5810, 0x88DC, 0x5812, 0x88DD, 0x5813,
+	0x88DE, 0x5814, 0x88DF, 0x5816, 0x88E0, 0x5817, 0x88E1, 0x5818,
+	0x88E2, 0x581A, 0x88E3, 0x581B, 0x88E4, 0x581C, 0x88E5, 0x581D,
+	0x88E6, 0x581F, 0x88E7, 0x5822, 0x88E8, 0x5823, 0x88E9, 0x5825,
+	0x88EA, 0x5826, 0x88EB, 0x5827, 0x88EC, 0x5828, 0x88ED, 0x5829,
+	0x88EE, 0x582B, 0x88EF, 0x582C, 0x88F0, 0x582D, 0x88F1, 0x582E,
+	0x88F2, 0x582F, 0x88F3, 0x5831, 0x88F4, 0x5832, 0x88F5, 0x5833,
+	0x88F6, 0x5834, 0x88F7, 0x5836, 0x88F8, 0x5837, 0x88F9, 0x5838,
+	0x88FA, 0x5839, 0x88FB, 0x583A, 0x88FC, 0x583B, 0x88FD, 0x583C,
+	0x88FE, 0x583D, 0x8940, 0x583E, 0x8941, 0x583F, 0x8942, 0x5840,
+	0x8943, 0x5841, 0x8944, 0x5842, 0x8945, 0x5843, 0x8946, 0x5845,
+	0x8947, 0x5846, 0x8948, 0x5847, 0x8949, 0x5848, 0x894A, 0x5849,
+	0x894B, 0x584A, 0x894C, 0x584B, 0x894D, 0x584E, 0x894E, 0x584F,
+	0x894F, 0x5850, 0x8950, 0x5852, 0x8951, 0x5853, 0x8952, 0x5855,
+	0x8953, 0x5856, 0x8954, 0x5857, 0x8955, 0x5859, 0x8956, 0x585A,
+	0x8957, 0x585B, 0x8958, 0x585C, 0x8959, 0x585D, 0x895A, 0x585F,
+	0x895B, 0x5860, 0x895C, 0x5861, 0x895D, 0x5862, 0x895E, 0x5863,
+	0x895F, 0x5864, 0x8960, 0x5866, 0x8961, 0x5867, 0x8962, 0x5868,
+	0x8963, 0x5869, 0x8964, 0x586A, 0x8965, 0x586D, 0x8966, 0x586E,
+	0x8967, 0x586F, 0x8968, 0x5870, 0x8969, 0x5871, 0x896A, 0x5872,
+	0x896B, 0x5873, 0x896C, 0x5874, 0x896D, 0x5875, 0x896E, 0x5876,
+	0x896F, 0x5877, 0x8970, 0x5878, 0x8971, 0x5879, 0x8972, 0x587A,
+	0x8973, 0x587B, 0x8974, 0x587C, 0x8975, 0x587D, 0x8976, 0x587F,
+	0x8977, 0x5882, 0x8978, 0x5884, 0x8979, 0x5886, 0x897A, 0x5887,
+	0x897B, 0x5888, 0x897C, 0x588A, 0x897D, 0x588B, 0x897E, 0x588C,
+	0x8980, 0x588D, 0x8981, 0x588E, 0x8982, 0x588F, 0x8983, 0x5890,
+	0x8984, 0x5891, 0x8985, 0x5894, 0x8986, 0x5895, 0x8987, 0x5896,
+	0x8988, 0x5897, 0x8989, 0x5898, 0x898A, 0x589B, 0x898B, 0x589C,
+	0x898C, 0x589D, 0x898D, 0x58A0, 0x898E, 0x58A1, 0x898F, 0x58A2,
+	0x8990, 0x58A3, 0x8991, 0x58A4, 0x8992, 0x58A5, 0x8993, 0x58A6,
+	0x8994, 0x58A7, 0x8995, 0x58AA, 0x8996, 0x58AB, 0x8997, 0x58AC,
+	0x8998, 0x58AD, 0x8999, 0x58AE, 0x899A, 0x58AF, 0x899B, 0x58B0,
+	0x899C, 0x58B1, 0x899D, 0x58B2, 0x899E, 0x58B3, 0x899F, 0x58B4,
+	0x89A0, 0x58B5, 0x89A1, 0x58B6, 0x89A2, 0x58B7, 0x89A3, 0x58B8,
+	0x89A4, 0x58B9, 0x89A5, 0x58BA, 0x89A6, 0x58BB, 0x89A7, 0x58BD,
+	0x89A8, 0x58BE, 0x89A9, 0x58BF, 0x89AA, 0x58C0, 0x89AB, 0x58C2,
+	0x89AC, 0x58C3, 0x89AD, 0x58C4, 0x89AE, 0x58C6, 0x89AF, 0x58C7,
+	0x89B0, 0x58C8, 0x89B1, 0x58C9, 0x89B2, 0x58CA, 0x89B3, 0x58CB,
+	0x89B4, 0x58CC, 0x89B5, 0x58CD, 0x89B6, 0x58CE, 0x89B7, 0x58CF,
+	0x89B8, 0x58D0, 0x89B9, 0x58D2, 0x89BA, 0x58D3, 0x89BB, 0x58D4,
+	0x89BC, 0x58D6, 0x89BD, 0x58D7, 0x89BE, 0x58D8, 0x89BF, 0x58D9,
+	0x89C0, 0x58DA, 0x89C1, 0x58DB, 0x89C2, 0x58DC, 0x89C3, 0x58DD,
+	0x89C4, 0x58DE, 0x89C5, 0x58DF, 0x89C6, 0x58E0, 0x89C7, 0x58E1,
+	0x89C8, 0x58E2, 0x89C9, 0x58E3, 0x89CA, 0x58E5, 0x89CB, 0x58E6,
+	0x89CC, 0x58E7, 0x89CD, 0x58E8, 0x89CE, 0x58E9, 0x89CF, 0x58EA,
+	0x89D0, 0x58ED, 0x89D1, 0x58EF, 0x89D2, 0x58F1, 0x89D3, 0x58F2,
+	0x89D4, 0x58F4, 0x89D5, 0x58F5, 0x89D6, 0x58F7, 0x89D7, 0x58F8,
+	0x89D8, 0x58FA, 0x89D9, 0x58FB, 0x89DA, 0x58FC, 0x89DB, 0x58FD,
+	0x89DC, 0x58FE, 0x89DD, 0x58FF, 0x89DE, 0x5900, 0x89DF, 0x5901,
+	0x89E0, 0x5903, 0x89E1, 0x5905, 0x89E2, 0x5906, 0x89E3, 0x5908,
+	0x89E4, 0x5909, 0x89E5, 0x590A, 0x89E6, 0x590B, 0x89E7, 0x590C,
+	0x89E8, 0x590E, 0x89E9, 0x5910, 0x89EA, 0x5911, 0x89EB, 0x5912,
+	0x89EC, 0x5913, 0x89ED, 0x5917, 0x89EE, 0x5918, 0x89EF, 0x591B,
+	0x89F0, 0x591D, 0x89F1, 0x591E, 0x89F2, 0x5920, 0x89F3, 0x5921,
+	0x89F4, 0x5922, 0x89F5, 0x5923, 0x89F6, 0x5926, 0x89F7, 0x5928,
+	0x89F8, 0x592C, 0x89F9, 0x5930, 0x89FA, 0x5932, 0x89FB, 0x5933,
+	0x89FC, 0x5935, 0x89FD, 0x5936, 0x89FE, 0x593B, 0x8A40, 0x593D,
+	0x8A41, 0x593E, 0x8A42, 0x593F, 0x8A43, 0x5940, 0x8A44, 0x5943,
+	0x8A45, 0x5945, 0x8A46, 0x5946, 0x8A47, 0x594A, 0x8A48, 0x594C,
+	0x8A49, 0x594D, 0x8A4A, 0x5950, 0x8A4B, 0x5952, 0x8A4C, 0x5953,
+	0x8A4D, 0x5959, 0x8A4E, 0x595B, 0x8A4F, 0x595C, 0x8A50, 0x595D,
+	0x8A51, 0x595E, 0x8A52, 0x595F, 0x8A53, 0x5961, 0x8A54, 0x5963,
+	0x8A55, 0x5964, 0x8A56, 0x5966, 0x8A57, 0x5967, 0x8A58, 0x5968,
+	0x8A59, 0x5969, 0x8A5A, 0x596A, 0x8A5B, 0x596B, 0x8A5C, 0x596C,
+	0x8A5D, 0x596D, 0x8A5E, 0x596E, 0x8A5F, 0x596F, 0x8A60, 0x5970,
+	0x8A61, 0x5971, 0x8A62, 0x5972, 0x8A63, 0x5975, 0x8A64, 0x5977,
+	0x8A65, 0x597A, 0x8A66, 0x597B, 0x8A67, 0x597C, 0x8A68, 0x597E,
+	0x8A69, 0x597F, 0x8A6A, 0x5980, 0x8A6B, 0x5985, 0x8A6C, 0x5989,
+	0x8A6D, 0x598B, 0x8A6E, 0x598C, 0x8A6F, 0x598E, 0x8A70, 0x598F,
+	0x8A71, 0x5990, 0x8A72, 0x5991, 0x8A73, 0x5994, 0x8A74, 0x5995,
+	0x8A75, 0x5998, 0x8A76, 0x599A, 0x8A77, 0x599B, 0x8A78, 0x599C,
+	0x8A79, 0x599D, 0x8A7A, 0x599F, 0x8A7B, 0x59A0, 0x8A7C, 0x59A1,
+	0x8A7D, 0x59A2, 0x8A7E, 0x59A6, 0x8A80, 0x59A7, 0x8A81, 0x59AC,
+	0x8A82, 0x59AD, 0x8A83, 0x59B0, 0x8A84, 0x59B1, 0x8A85, 0x59B3,
+	0x8A86, 0x59B4, 0x8A87, 0x59B5, 0x8A88, 0x59B6, 0x8A89, 0x59B7,
+	0x8A8A, 0x59B8, 0x8A8B, 0x59BA, 0x8A8C, 0x59BC, 0x8A8D, 0x59BD,
+	0x8A8E, 0x59BF, 0x8A8F, 0x59C0, 0x8A90, 0x59C1, 0x8A91, 0x59C2,
+	0x8A92, 0x59C3, 0x8A93, 0x59C4, 0x8A94, 0x59C5, 0x8A95, 0x59C7,
+	0x8A96, 0x59C8, 0x8A97, 0x59C9, 0x8A98, 0x59CC, 0x8A99, 0x59CD,
+	0x8A9A, 0x59CE, 0x8A9B, 0x59CF, 0x8A9C, 0x59D5, 0x8A9D, 0x59D6,
+	0x8A9E, 0x59D9, 0x8A9F, 0x59DB, 0x8AA0, 0x59DE, 0x8AA1, 0x59DF,
+	0x8AA2, 0x59E0, 0x8AA3, 0x59E1, 0x8AA4, 0x59E2, 0x8AA5, 0x59E4,
+	0x8AA6, 0x59E6, 0x8AA7, 0x59E7, 0x8AA8, 0x59E9, 0x8AA9, 0x59EA,
+	0x8AAA, 0x59EB, 0x8AAB, 0x59ED, 0x8AAC, 0x59EE, 0x8AAD, 0x59EF,
+	0x8AAE, 0x59F0, 0x8AAF, 0x59F1, 0x8AB0, 0x59F2, 0x8AB1, 0x59F3,
+	0x8AB2, 0x59F4, 0x8AB3, 0x59F5, 0x8AB4, 0x59F6, 0x8AB5, 0x59F7,
+	0x8AB6, 0x59F8, 0x8AB7, 0x59FA, 0x8AB8, 0x59FC, 0x8AB9, 0x59FD,
+	0x8ABA, 0x59FE, 0x8ABB, 0x5A00, 0x8ABC, 0x5A02, 0x8ABD, 0x5A0A,
+	0x8ABE, 0x5A0B, 0x8ABF, 0x5A0D, 0x8AC0, 0x5A0E, 0x8AC1, 0x5A0F,
+	0x8AC2, 0x5A10, 0x8AC3, 0x5A12, 0x8AC4, 0x5A14, 0x8AC5, 0x5A15,
+	0x8AC6, 0x5A16, 0x8AC7, 0x5A17, 0x8AC8, 0x5A19, 0x8AC9, 0x5A1A,
+	0x8ACA, 0x5A1B, 0x8ACB, 0x5A1D, 0x8ACC, 0x5A1E, 0x8ACD, 0x5A21,
+	0x8ACE, 0x5A22, 0x8ACF, 0x5A24, 0x8AD0, 0x5A26, 0x8AD1, 0x5A27,
+	0x8AD2, 0x5A28, 0x8AD3, 0x5A2A, 0x8AD4, 0x5A2B, 0x8AD5, 0x5A2C,
+	0x8AD6, 0x5A2D, 0x8AD7, 0x5A2E, 0x8AD8, 0x5A2F, 0x8AD9, 0x5A30,
+	0x8ADA, 0x5A33, 0x8ADB, 0x5A35, 0x8ADC, 0x5A37, 0x8ADD, 0x5A38,
+	0x8ADE, 0x5A39, 0x8ADF, 0x5A3A, 0x8AE0, 0x5A3B, 0x8AE1, 0x5A3D,
+	0x8AE2, 0x5A3E, 0x8AE3, 0x5A3F, 0x8AE4, 0x5A41, 0x8AE5, 0x5A42,
+	0x8AE6, 0x5A43, 0x8AE7, 0x5A44, 0x8AE8, 0x5A45, 0x8AE9, 0x5A47,
+	0x8AEA, 0x5A48, 0x8AEB, 0x5A4B, 0x8AEC, 0x5A4C, 0x8AED, 0x5A4D,
+	0x8AEE, 0x5A4E, 0x8AEF, 0x5A4F, 0x8AF0, 0x5A50, 0x8AF1, 0x5A51,
+	0x8AF2, 0x5A52, 0x8AF3, 0x5A53, 0x8AF4, 0x5A54, 0x8AF5, 0x5A56,
+	0x8AF6, 0x5A57, 0x8AF7, 0x5A58, 0x8AF8, 0x5A59, 0x8AF9, 0x5A5B,
+	0x8AFA, 0x5A5C, 0x8AFB, 0x5A5D, 0x8AFC, 0x5A5E, 0x8AFD, 0x5A5F,
+	0x8AFE, 0x5A60, 0x8B40, 0x5A61, 0x8B41, 0x5A63, 0x8B42, 0x5A64,
+	0x8B43, 0x5A65, 0x8B44, 0x5A66, 0x8B45, 0x5A68, 0x8B46, 0x5A69,
+	0x8B47, 0x5A6B, 0x8B48, 0x5A6C, 0x8B49, 0x5A6D, 0x8B4A, 0x5A6E,
+	0x8B4B, 0x5A6F, 0x8B4C, 0x5A70, 0x8B4D, 0x5A71, 0x8B4E, 0x5A72,
+	0x8B4F, 0x5A73, 0x8B50, 0x5A78, 0x8B51, 0x5A79, 0x8B52, 0x5A7B,
+	0x8B53, 0x5A7C, 0x8B54, 0x5A7D, 0x8B55, 0x5A7E, 0x8B56, 0x5A80,
+	0x8B57, 0x5A81, 0x8B58, 0x5A82, 0x8B59, 0x5A83, 0x8B5A, 0x5A84,
+	0x8B5B, 0x5A85, 0x8B5C, 0x5A86, 0x8B5D, 0x5A87, 0x8B5E, 0x5A88,
+	0x8B5F, 0x5A89, 0x8B60, 0x5A8A, 0x8B61, 0x5A8B, 0x8B62, 0x5A8C,
+	0x8B63, 0x5A8D, 0x8B64, 0x5A8E, 0x8B65, 0x5A8F, 0x8B66, 0x5A90,
+	0x8B67, 0x5A91, 0x8B68, 0x5A93, 0x8B69, 0x5A94, 0x8B6A, 0x5A95,
+	0x8B6B, 0x5A96, 0x8B6C, 0x5A97, 0x8B6D, 0x5A98, 0x8B6E, 0x5A99,
+	0x8B6F, 0x5A9C, 0x8B70, 0x5A9D, 0x8B71, 0x5A9E, 0x8B72, 0x5A9F,
+	0x8B73, 0x5AA0, 0x8B74, 0x5AA1, 0x8B75, 0x5AA2, 0x8B76, 0x5AA3,
+	0x8B77, 0x5AA4, 0x8B78, 0x5AA5, 0x8B79, 0x5AA6, 0x8B7A, 0x5AA7,
+	0x8B7B, 0x5AA8, 0x8B7C, 0x5AA9, 0x8B7D, 0x5AAB, 0x8B7E, 0x5AAC,
+	0x8B80, 0x5AAD, 0x8B81, 0x5AAE, 0x8B82, 0x5AAF, 0x8B83, 0x5AB0,
+	0x8B84, 0x5AB1, 0x8B85, 0x5AB4, 0x8B86, 0x5AB6, 0x8B87, 0x5AB7,
+	0x8B88, 0x5AB9, 0x8B89, 0x5ABA, 0x8B8A, 0x5ABB, 0x8B8B, 0x5ABC,
+	0x8B8C, 0x5ABD, 0x8B8D, 0x5ABF, 0x8B8E, 0x5AC0, 0x8B8F, 0x5AC3,
+	0x8B90, 0x5AC4, 0x8B91, 0x5AC5, 0x8B92, 0x5AC6, 0x8B93, 0x5AC7,
+	0x8B94, 0x5AC8, 0x8B95, 0x5ACA, 0x8B96, 0x5ACB, 0x8B97, 0x5ACD,
+	0x8B98, 0x5ACE, 0x8B99, 0x5ACF, 0x8B9A, 0x5AD0, 0x8B9B, 0x5AD1,
+	0x8B9C, 0x5AD3, 0x8B9D, 0x5AD5, 0x8B9E, 0x5AD7, 0x8B9F, 0x5AD9,
+	0x8BA0, 0x5ADA, 0x8BA1, 0x5ADB, 0x8BA2, 0x5ADD, 0x8BA3, 0x5ADE,
+	0x8BA4, 0x5ADF, 0x8BA5, 0x5AE2, 0x8BA6, 0x5AE4, 0x8BA7, 0x5AE5,
+	0x8BA8, 0x5AE7, 0x8BA9, 0x5AE8, 0x8BAA, 0x5AEA, 0x8BAB, 0x5AEC,
+	0x8BAC, 0x5AED, 0x8BAD, 0x5AEE, 0x8BAE, 0x5AEF, 0x8BAF, 0x5AF0,
+	0x8BB0, 0x5AF2, 0x8BB1, 0x5AF3, 0x8BB2, 0x5AF4, 0x8BB3, 0x5AF5,
+	0x8BB4, 0x5AF6, 0x8BB5, 0x5AF7, 0x8BB6, 0x5AF8, 0x8BB7, 0x5AF9,
+	0x8BB8, 0x5AFA, 0x8BB9, 0x5AFB, 0x8BBA, 0x5AFC, 0x8BBB, 0x5AFD,
+	0x8BBC, 0x5AFE, 0x8BBD, 0x5AFF, 0x8BBE, 0x5B00, 0x8BBF, 0x5B01,
+	0x8BC0, 0x5B02, 0x8BC1, 0x5B03, 0x8BC2, 0x5B04, 0x8BC3, 0x5B05,
+	0x8BC4, 0x5B06, 0x8BC5, 0x5B07, 0x8BC6, 0x5B08, 0x8BC7, 0x5B0A,
+	0x8BC8, 0x5B0B, 0x8BC9, 0x5B0C, 0x8BCA, 0x5B0D, 0x8BCB, 0x5B0E,
+	0x8BCC, 0x5B0F, 0x8BCD, 0x5B10, 0x8BCE, 0x5B11, 0x8BCF, 0x5B12,
+	0x8BD0, 0x5B13, 0x8BD1, 0x5B14, 0x8BD2, 0x5B15, 0x8BD3, 0x5B18,
+	0x8BD4, 0x5B19, 0x8BD5, 0x5B1A, 0x8BD6, 0x5B1B, 0x8BD7, 0x5B1C,
+	0x8BD8, 0x5B1D, 0x8BD9, 0x5B1E, 0x8BDA, 0x5B1F, 0x8BDB, 0x5B20,
+	0x8BDC, 0x5B21, 0x8BDD, 0x5B22, 0x8BDE, 0x5B23, 0x8BDF, 0x5B24,
+	0x8BE0, 0x5B25, 0x8BE1, 0x5B26, 0x8BE2, 0x5B27, 0x8BE3, 0x5B28,
+	0x8BE4, 0x5B29, 0x8BE5, 0x5B2A, 0x8BE6, 0x5B2B, 0x8BE7, 0x5B2C,
+	0x8BE8, 0x5B2D, 0x8BE9, 0x5B2E, 0x8BEA, 0x5B2F, 0x8BEB, 0x5B30,
+	0x8BEC, 0x5B31, 0x8BED, 0x5B33, 0x8BEE, 0x5B35, 0x8BEF, 0x5B36,
+	0x8BF0, 0x5B38, 0x8BF1, 0x5B39, 0x8BF2, 0x5B3A, 0x8BF3, 0x5B3B,
+	0x8BF4, 0x5B3C, 0x8BF5, 0x5B3D, 0x8BF6, 0x5B3E, 0x8BF7, 0x5B3F,
+	0x8BF8, 0x5B41, 0x8BF9, 0x5B42, 0x8BFA, 0x5B43, 0x8BFB, 0x5B44,
+	0x8BFC, 0x5B45, 0x8BFD, 0x5B46, 0x8BFE, 0x5B47, 0x8C40, 0x5B48,
+	0x8C41, 0x5B49, 0x8C42, 0x5B4A, 0x8C43, 0x5B4B, 0x8C44, 0x5B4C,
+	0x8C45, 0x5B4D, 0x8C46, 0x5B4E, 0x8C47, 0x5B4F, 0x8C48, 0x5B52,
+	0x8C49, 0x5B56, 0x8C4A, 0x5B5E, 0x8C4B, 0x5B60, 0x8C4C, 0x5B61,
+	0x8C4D, 0x5B67, 0x8C4E, 0x5B68, 0x8C4F, 0x5B6B, 0x8C50, 0x5B6D,
+	0x8C51, 0x5B6E, 0x8C52, 0x5B6F, 0x8C53, 0x5B72, 0x8C54, 0x5B74,
+	0x8C55, 0x5B76, 0x8C56, 0x5B77, 0x8C57, 0x5B78, 0x8C58, 0x5B79,
+	0x8C59, 0x5B7B, 0x8C5A, 0x5B7C, 0x8C5B, 0x5B7E, 0x8C5C, 0x5B7F,
+	0x8C5D, 0x5B82, 0x8C5E, 0x5B86, 0x8C5F, 0x5B8A, 0x8C60, 0x5B8D,
+	0x8C61, 0x5B8E, 0x8C62, 0x5B90, 0x8C63, 0x5B91, 0x8C64, 0x5B92,
+	0x8C65, 0x5B94, 0x8C66, 0x5B96, 0x8C67, 0x5B9F, 0x8C68, 0x5BA7,
+	0x8C69, 0x5BA8, 0x8C6A, 0x5BA9, 0x8C6B, 0x5BAC, 0x8C6C, 0x5BAD,
+	0x8C6D, 0x5BAE, 0x8C6E, 0x5BAF, 0x8C6F, 0x5BB1, 0x8C70, 0x5BB2,
+	0x8C71, 0x5BB7, 0x8C72, 0x5BBA, 0x8C73, 0x5BBB, 0x8C74, 0x5BBC,
+	0x8C75, 0x5BC0, 0x8C76, 0x5BC1, 0x8C77, 0x5BC3, 0x8C78, 0x5BC8,
+	0x8C79, 0x5BC9, 0x8C7A, 0x5BCA, 0x8C7B, 0x5BCB, 0x8C7C, 0x5BCD,
+	0x8C7D, 0x5BCE, 0x8C7E, 0x5BCF, 0x8C80, 0x5BD1, 0x8C81, 0x5BD4,
+	0x8C82, 0x5BD5, 0x8C83, 0x5BD6, 0x8C84, 0x5BD7, 0x8C85, 0x5BD8,
+	0x8C86, 0x5BD9, 0x8C87, 0x5BDA, 0x8C88, 0x5BDB, 0x8C89, 0x5BDC,
+	0x8C8A, 0x5BE0, 0x8C8B, 0x5BE2, 0x8C8C, 0x5BE3, 0x8C8D, 0x5BE6,
+	0x8C8E, 0x5BE7, 0x8C8F, 0x5BE9, 0x8C90, 0x5BEA, 0x8C91, 0x5BEB,
+	0x8C92, 0x5BEC, 0x8C93, 0x5BED, 0x8C94, 0x5BEF, 0x8C95, 0x5BF1,
+	0x8C96, 0x5BF2, 0x8C97, 0x5BF3, 0x8C98, 0x5BF4, 0x8C99, 0x5BF5,
+	0x8C9A, 0x5BF6, 0x8C9B, 0x5BF7, 0x8C9C, 0x5BFD, 0x8C9D, 0x5BFE,
+	0x8C9E, 0x5C00, 0x8C9F, 0x5C02, 0x8CA0, 0x5C03, 0x8CA1, 0x5C05,
+	0x8CA2, 0x5C07, 0x8CA3, 0x5C08, 0x8CA4, 0x5C0B, 0x8CA5, 0x5C0C,
+	0x8CA6, 0x5C0D, 0x8CA7, 0x5C0E, 0x8CA8, 0x5C10, 0x8CA9, 0x5C12,
+	0x8CAA, 0x5C13, 0x8CAB, 0x5C17, 0x8CAC, 0x5C19, 0x8CAD, 0x5C1B,
+	0x8CAE, 0x5C1E, 0x8CAF, 0x5C1F, 0x8CB0, 0x5C20, 0x8CB1, 0x5C21,
+	0x8CB2, 0x5C23, 0x8CB3, 0x5C26, 0x8CB4, 0x5C28, 0x8CB5, 0x5C29,
+	0x8CB6, 0x5C2A, 0x8CB7, 0x5C2B, 0x8CB8, 0x5C2D, 0x8CB9, 0x5C2E,
+	0x8CBA, 0x5C2F, 0x8CBB, 0x5C30, 0x8CBC, 0x5C32, 0x8CBD, 0x5C33,
+	0x8CBE, 0x5C35, 0x8CBF, 0x5C36, 0x8CC0, 0x5C37, 0x8CC1, 0x5C43,
+	0x8CC2, 0x5C44, 0x8CC3, 0x5C46, 0x8CC4, 0x5C47, 0x8CC5, 0x5C4C,
+	0x8CC6, 0x5C4D, 0x8CC7, 0x5C52, 0x8CC8, 0x5C53, 0x8CC9, 0x5C54,
+	0x8CCA, 0x5C56, 0x8CCB, 0x5C57, 0x8CCC, 0x5C58, 0x8CCD, 0x5C5A,
+	0x8CCE, 0x5C5B, 0x8CCF, 0x5C5C, 0x8CD0, 0x5C5D, 0x8CD1, 0x5C5F,
+	0x8CD2, 0x5C62, 0x8CD3, 0x5C64, 0x8CD4, 0x5C67, 0x8CD5, 0x5C68,
+	0x8CD6, 0x5C69, 0x8CD7, 0x5C6A, 0x8CD8, 0x5C6B, 0x8CD9, 0x5C6C,
+	0x8CDA, 0x5C6D, 0x8CDB, 0x5C70, 0x8CDC, 0x5C72, 0x8CDD, 0x5C73,
+	0x8CDE, 0x5C74, 0x8CDF, 0x5C75, 0x8CE0, 0x5C76, 0x8CE1, 0x5C77,
+	0x8CE2, 0x5C78, 0x8CE3, 0x5C7B, 0x8CE4, 0x5C7C, 0x8CE5, 0x5C7D,
+	0x8CE6, 0x5C7E, 0x8CE7, 0x5C80, 0x8CE8, 0x5C83, 0x8CE9, 0x5C84,
+	0x8CEA, 0x5C85, 0x8CEB, 0x5C86, 0x8CEC, 0x5C87, 0x8CED, 0x5C89,
+	0x8CEE, 0x5C8A, 0x8CEF, 0x5C8B, 0x8CF0, 0x5C8E, 0x8CF1, 0x5C8F,
+	0x8CF2, 0x5C92, 0x8CF3, 0x5C93, 0x8CF4, 0x5C95, 0x8CF5, 0x5C9D,
+	0x8CF6, 0x5C9E, 0x8CF7, 0x5C9F, 0x8CF8, 0x5CA0, 0x8CF9, 0x5CA1,
+	0x8CFA, 0x5CA4, 0x8CFB, 0x5CA5, 0x8CFC, 0x5CA6, 0x8CFD, 0x5CA7,
+	0x8CFE, 0x5CA8, 0x8D40, 0x5CAA, 0x8D41, 0x5CAE, 0x8D42, 0x5CAF,
+	0x8D43, 0x5CB0, 0x8D44, 0x5CB2, 0x8D45, 0x5CB4, 0x8D46, 0x5CB6,
+	0x8D47, 0x5CB9, 0x8D48, 0x5CBA, 0x8D49, 0x5CBB, 0x8D4A, 0x5CBC,
+	0x8D4B, 0x5CBE, 0x8D4C, 0x5CC0, 0x8D4D, 0x5CC2, 0x8D4E, 0x5CC3,
+	0x8D4F, 0x5CC5, 0x8D50, 0x5CC6, 0x8D51, 0x5CC7, 0x8D52, 0x5CC8,
+	0x8D53, 0x5CC9, 0x8D54, 0x5CCA, 0x8D55, 0x5CCC, 0x8D56, 0x5CCD,
+	0x8D57, 0x5CCE, 0x8D58, 0x5CCF, 0x8D59, 0x5CD0, 0x8D5A, 0x5CD1,
+	0x8D5B, 0x5CD3, 0x8D5C, 0x5CD4, 0x8D5D, 0x5CD5, 0x8D5E, 0x5CD6,
+	0x8D5F, 0x5CD7, 0x8D60, 0x5CD8, 0x8D61, 0x5CDA, 0x8D62, 0x5CDB,
+	0x8D63, 0x5CDC, 0x8D64, 0x5CDD, 0x8D65, 0x5CDE, 0x8D66, 0x5CDF,
+	0x8D67, 0x5CE0, 0x8D68, 0x5CE2, 0x8D69, 0x5CE3, 0x8D6A, 0x5CE7,
+	0x8D6B, 0x5CE9, 0x8D6C, 0x5CEB, 0x8D6D, 0x5CEC, 0x8D6E, 0x5CEE,
+	0x8D6F, 0x5CEF, 0x8D70, 0x5CF1, 0x8D71, 0x5CF2, 0x8D72, 0x5CF3,
+	0x8D73, 0x5CF4, 0x8D74, 0x5CF5, 0x8D75, 0x5CF6, 0x8D76, 0x5CF7,
+	0x8D77, 0x5CF8, 0x8D78, 0x5CF9, 0x8D79, 0x5CFA, 0x8D7A, 0x5CFC,
+	0x8D7B, 0x5CFD, 0x8D7C, 0x5CFE, 0x8D7D, 0x5CFF, 0x8D7E, 0x5D00,
+	0x8D80, 0x5D01, 0x8D81, 0x5D04, 0x8D82, 0x5D05, 0x8D83, 0x5D08,
+	0x8D84, 0x5D09, 0x8D85, 0x5D0A, 0x8D86, 0x5D0B, 0x8D87, 0x5D0C,
+	0x8D88, 0x5D0D, 0x8D89, 0x5D0F, 0x8D8A, 0x5D10, 0x8D8B, 0x5D11,
+	0x8D8C, 0x5D12, 0x8D8D, 0x5D13, 0x8D8E, 0x5D15, 0x8D8F, 0x5D17,
+	0x8D90, 0x5D18, 0x8D91, 0x5D19, 0x8D92, 0x5D1A, 0x8D93, 0x5D1C,
+	0x8D94, 0x5D1D, 0x8D95, 0x5D1F, 0x8D96, 0x5D20, 0x8D97, 0x5D21,
+	0x8D98, 0x5D22, 0x8D99, 0x5D23, 0x8D9A, 0x5D25, 0x8D9B, 0x5D28,
+	0x8D9C, 0x5D2A, 0x8D9D, 0x5D2B, 0x8D9E, 0x5D2C, 0x8D9F, 0x5D2F,
+	0x8DA0, 0x5D30, 0x8DA1, 0x5D31, 0x8DA2, 0x5D32, 0x8DA3, 0x5D33,
+	0x8DA4, 0x5D35, 0x8DA5, 0x5D36, 0x8DA6, 0x5D37, 0x8DA7, 0x5D38,
+	0x8DA8, 0x5D39, 0x8DA9, 0x5D3A, 0x8DAA, 0x5D3B, 0x8DAB, 0x5D3C,
+	0x8DAC, 0x5D3F, 0x8DAD, 0x5D40, 0x8DAE, 0x5D41, 0x8DAF, 0x5D42,
+	0x8DB0, 0x5D43, 0x8DB1, 0x5D44, 0x8DB2, 0x5D45, 0x8DB3, 0x5D46,
+	0x8DB4, 0x5D48, 0x8DB5, 0x5D49, 0x8DB6, 0x5D4D, 0x8DB7, 0x5D4E,
+	0x8DB8, 0x5D4F, 0x8DB9, 0x5D50, 0x8DBA, 0x5D51, 0x8DBB, 0x5D52,
+	0x8DBC, 0x5D53, 0x8DBD, 0x5D54, 0x8DBE, 0x5D55, 0x8DBF, 0x5D56,
+	0x8DC0, 0x5D57, 0x8DC1, 0x5D59, 0x8DC2, 0x5D5A, 0x8DC3, 0x5D5C,
+	0x8DC4, 0x5D5E, 0x8DC5, 0x5D5F, 0x8DC6, 0x5D60, 0x8DC7, 0x5D61,
+	0x8DC8, 0x5D62, 0x8DC9, 0x5D63, 0x8DCA, 0x5D64, 0x8DCB, 0x5D65,
+	0x8DCC, 0x5D66, 0x8DCD, 0x5D67, 0x8DCE, 0x5D68, 0x8DCF, 0x5D6A,
+	0x8DD0, 0x5D6D, 0x8DD1, 0x5D6E, 0x8DD2, 0x5D70, 0x8DD3, 0x5D71,
+	0x8DD4, 0x5D72, 0x8DD5, 0x5D73, 0x8DD6, 0x5D75, 0x8DD7, 0x5D76,
+	0x8DD8, 0x5D77, 0x8DD9, 0x5D78, 0x8DDA, 0x5D79, 0x8DDB, 0x5D7A,
+	0x8DDC, 0x5D7B, 0x8DDD, 0x5D7C, 0x8DDE, 0x5D7D, 0x8DDF, 0x5D7E,
+	0x8DE0, 0x5D7F, 0x8DE1, 0x5D80, 0x8DE2, 0x5D81, 0x8DE3, 0x5D83,
+	0x8DE4, 0x5D84, 0x8DE5, 0x5D85, 0x8DE6, 0x5D86, 0x8DE7, 0x5D87,
+	0x8DE8, 0x5D88, 0x8DE9, 0x5D89, 0x8DEA, 0x5D8A, 0x8DEB, 0x5D8B,
+	0x8DEC, 0x5D8C, 0x8DED, 0x5D8D, 0x8DEE, 0x5D8E, 0x8DEF, 0x5D8F,
+	0x8DF0, 0x5D90, 0x8DF1, 0x5D91, 0x8DF2, 0x5D92, 0x8DF3, 0x5D93,
+	0x8DF4, 0x5D94, 0x8DF5, 0x5D95, 0x8DF6, 0x5D96, 0x8DF7, 0x5D97,
+	0x8DF8, 0x5D98, 0x8DF9, 0x5D9A, 0x8DFA, 0x5D9B, 0x8DFB, 0x5D9C,
+	0x8DFC, 0x5D9E, 0x8DFD, 0x5D9F, 0x8DFE, 0x5DA0, 0x8E40, 0x5DA1,
+	0x8E41, 0x5DA2, 0x8E42, 0x5DA3, 0x8E43, 0x5DA4, 0x8E44, 0x5DA5,
+	0x8E45, 0x5DA6, 0x8E46, 0x5DA7, 0x8E47, 0x5DA8, 0x8E48, 0x5DA9,
+	0x8E49, 0x5DAA, 0x8E4A, 0x5DAB, 0x8E4B, 0x5DAC, 0x8E4C, 0x5DAD,
+	0x8E4D, 0x5DAE, 0x8E4E, 0x5DAF, 0x8E4F, 0x5DB0, 0x8E50, 0x5DB1,
+	0x8E51, 0x5DB2, 0x8E52, 0x5DB3, 0x8E53, 0x5DB4, 0x8E54, 0x5DB5,
+	0x8E55, 0x5DB6, 0x8E56, 0x5DB8, 0x8E57, 0x5DB9, 0x8E58, 0x5DBA,
+	0x8E59, 0x5DBB, 0x8E5A, 0x5DBC, 0x8E5B, 0x5DBD, 0x8E5C, 0x5DBE,
+	0x8E5D, 0x5DBF, 0x8E5E, 0x5DC0, 0x8E5F, 0x5DC1, 0x8E60, 0x5DC2,
+	0x8E61, 0x5DC3, 0x8E62, 0x5DC4, 0x8E63, 0x5DC6, 0x8E64, 0x5DC7,
+	0x8E65, 0x5DC8, 0x8E66, 0x5DC9, 0x8E67, 0x5DCA, 0x8E68, 0x5DCB,
+	0x8E69, 0x5DCC, 0x8E6A, 0x5DCE, 0x8E6B, 0x5DCF, 0x8E6C, 0x5DD0,
+	0x8E6D, 0x5DD1, 0x8E6E, 0x5DD2, 0x8E6F, 0x5DD3, 0x8E70, 0x5DD4,
+	0x8E71, 0x5DD5, 0x8E72, 0x5DD6, 0x8E73, 0x5DD7, 0x8E74, 0x5DD8,
+	0x8E75, 0x5DD9, 0x8E76, 0x5DDA, 0x8E77, 0x5DDC, 0x8E78, 0x5DDF,
+	0x8E79, 0x5DE0, 0x8E7A, 0x5DE3, 0x8E7B, 0x5DE4, 0x8E7C, 0x5DEA,
+	0x8E7D, 0x5DEC, 0x8E7E, 0x5DED, 0x8E80, 0x5DF0, 0x8E81, 0x5DF5,
+	0x8E82, 0x5DF6, 0x8E83, 0x5DF8, 0x8E84, 0x5DF9, 0x8E85, 0x5DFA,
+	0x8E86, 0x5DFB, 0x8E87, 0x5DFC, 0x8E88, 0x5DFF, 0x8E89, 0x5E00,
+	0x8E8A, 0x5E04, 0x8E8B, 0x5E07, 0x8E8C, 0x5E09, 0x8E8D, 0x5E0A,
+	0x8E8E, 0x5E0B, 0x8E8F, 0x5E0D, 0x8E90, 0x5E0E, 0x8E91, 0x5E12,
+	0x8E92, 0x5E13, 0x8E93, 0x5E17, 0x8E94, 0x5E1E, 0x8E95, 0x5E1F,
+	0x8E96, 0x5E20, 0x8E97, 0x5E21, 0x8E98, 0x5E22, 0x8E99, 0x5E23,
+	0x8E9A, 0x5E24, 0x8E9B, 0x5E25, 0x8E9C, 0x5E28, 0x8E9D, 0x5E29,
+	0x8E9E, 0x5E2A, 0x8E9F, 0x5E2B, 0x8EA0, 0x5E2C, 0x8EA1, 0x5E2F,
+	0x8EA2, 0x5E30, 0x8EA3, 0x5E32, 0x8EA4, 0x5E33, 0x8EA5, 0x5E34,
+	0x8EA6, 0x5E35, 0x8EA7, 0x5E36, 0x8EA8, 0x5E39, 0x8EA9, 0x5E3A,
+	0x8EAA, 0x5E3E, 0x8EAB, 0x5E3F, 0x8EAC, 0x5E40, 0x8EAD, 0x5E41,
+	0x8EAE, 0x5E43, 0x8EAF, 0x5E46, 0x8EB0, 0x5E47, 0x8EB1, 0x5E48,
+	0x8EB2, 0x5E49, 0x8EB3, 0x5E4A, 0x8EB4, 0x5E4B, 0x8EB5, 0x5E4D,
+	0x8EB6, 0x5E4E, 0x8EB7, 0x5E4F, 0x8EB8, 0x5E50, 0x8EB9, 0x5E51,
+	0x8EBA, 0x5E52, 0x8EBB, 0x5E53, 0x8EBC, 0x5E56, 0x8EBD, 0x5E57,
+	0x8EBE, 0x5E58, 0x8EBF, 0x5E59, 0x8EC0, 0x5E5A, 0x8EC1, 0x5E5C,
+	0x8EC2, 0x5E5D, 0x8EC3, 0x5E5F, 0x8EC4, 0x5E60, 0x8EC5, 0x5E63,
+	0x8EC6, 0x5E64, 0x8EC7, 0x5E65, 0x8EC8, 0x5E66, 0x8EC9, 0x5E67,
+	0x8ECA, 0x5E68, 0x8ECB, 0x5E69, 0x8ECC, 0x5E6A, 0x8ECD, 0x5E6B,
+	0x8ECE, 0x5E6C, 0x8ECF, 0x5E6D, 0x8ED0, 0x5E6E, 0x8ED1, 0x5E6F,
+	0x8ED2, 0x5E70, 0x8ED3, 0x5E71, 0x8ED4, 0x5E75, 0x8ED5, 0x5E77,
+	0x8ED6, 0x5E79, 0x8ED7, 0x5E7E, 0x8ED8, 0x5E81, 0x8ED9, 0x5E82,
+	0x8EDA, 0x5E83, 0x8EDB, 0x5E85, 0x8EDC, 0x5E88, 0x8EDD, 0x5E89,
+	0x8EDE, 0x5E8C, 0x8EDF, 0x5E8D, 0x8EE0, 0x5E8E, 0x8EE1, 0x5E92,
+	0x8EE2, 0x5E98, 0x8EE3, 0x5E9B, 0x8EE4, 0x5E9D, 0x8EE5, 0x5EA1,
+	0x8EE6, 0x5EA2, 0x8EE7, 0x5EA3, 0x8EE8, 0x5EA4, 0x8EE9, 0x5EA8,
+	0x8EEA, 0x5EA9, 0x8EEB, 0x5EAA, 0x8EEC, 0x5EAB, 0x8EED, 0x5EAC,
+	0x8EEE, 0x5EAE, 0x8EEF, 0x5EAF, 0x8EF0, 0x5EB0, 0x8EF1, 0x5EB1,
+	0x8EF2, 0x5EB2, 0x8EF3, 0x5EB4, 0x8EF4, 0x5EBA, 0x8EF5, 0x5EBB,
+	0x8EF6, 0x5EBC, 0x8EF7, 0x5EBD, 0x8EF8, 0x5EBF, 0x8EF9, 0x5EC0,
+	0x8EFA, 0x5EC1, 0x8EFB, 0x5EC2, 0x8EFC, 0x5EC3, 0x8EFD, 0x5EC4,
+	0x8EFE, 0x5EC5, 0x8F40, 0x5EC6, 0x8F41, 0x5EC7, 0x8F42, 0x5EC8,
+	0x8F43, 0x5ECB, 0x8F44, 0x5ECC, 0x8F45, 0x5ECD, 0x8F46, 0x5ECE,
+	0x8F47, 0x5ECF, 0x8F48, 0x5ED0, 0x8F49, 0x5ED4, 0x8F4A, 0x5ED5,
+	0x8F4B, 0x5ED7, 0x8F4C, 0x5ED8, 0x8F4D, 0x5ED9, 0x8F4E, 0x5EDA,
+	0x8F4F, 0x5EDC, 0x8F50, 0x5EDD, 0x8F51, 0x5EDE, 0x8F52, 0x5EDF,
+	0x8F53, 0x5EE0, 0x8F54, 0x5EE1, 0x8F55, 0x5EE2, 0x8F56, 0x5EE3,
+	0x8F57, 0x5EE4, 0x8F58, 0x5EE5, 0x8F59, 0x5EE6, 0x8F5A, 0x5EE7,
+	0x8F5B, 0x5EE9, 0x8F5C, 0x5EEB, 0x8F5D, 0x5EEC, 0x8F5E, 0x5EED,
+	0x8F5F, 0x5EEE, 0x8F60, 0x5EEF, 0x8F61, 0x5EF0, 0x8F62, 0x5EF1,
+	0x8F63, 0x5EF2, 0x8F64, 0x5EF3, 0x8F65, 0x5EF5, 0x8F66, 0x5EF8,
+	0x8F67, 0x5EF9, 0x8F68, 0x5EFB, 0x8F69, 0x5EFC, 0x8F6A, 0x5EFD,
+	0x8F6B, 0x5F05, 0x8F6C, 0x5F06, 0x8F6D, 0x5F07, 0x8F6E, 0x5F09,
+	0x8F6F, 0x5F0C, 0x8F70, 0x5F0D, 0x8F71, 0x5F0E, 0x8F72, 0x5F10,
+	0x8F73, 0x5F12, 0x8F74, 0x5F14, 0x8F75, 0x5F16, 0x8F76, 0x5F19,
+	0x8F77, 0x5F1A, 0x8F78, 0x5F1C, 0x8F79, 0x5F1D, 0x8F7A, 0x5F1E,
+	0x8F7B, 0x5F21, 0x8F7C, 0x5F22, 0x8F7D, 0x5F23, 0x8F7E, 0x5F24,
+	0x8F80, 0x5F28, 0x8F81, 0x5F2B, 0x8F82, 0x5F2C, 0x8F83, 0x5F2E,
+	0x8F84, 0x5F30, 0x8F85, 0x5F32, 0x8F86, 0x5F33, 0x8F87, 0x5F34,
+	0x8F88, 0x5F35, 0x8F89, 0x5F36, 0x8F8A, 0x5F37, 0x8F8B, 0x5F38,
+	0x8F8C, 0x5F3B, 0x8F8D, 0x5F3D, 0x8F8E, 0x5F3E, 0x8F8F, 0x5F3F,
+	0x8F90, 0x5F41, 0x8F91, 0x5F42, 0x8F92, 0x5F43, 0x8F93, 0x5F44,
+	0x8F94, 0x5F45, 0x8F95, 0x5F46, 0x8F96, 0x5F47, 0x8F97, 0x5F48,
+	0x8F98, 0x5F49, 0x8F99, 0x5F4A, 0x8F9A, 0x5F4B, 0x8F9B, 0x5F4C,
+	0x8F9C, 0x5F4D, 0x8F9D, 0x5F4E, 0x8F9E, 0x5F4F, 0x8F9F, 0x5F51,
+	0x8FA0, 0x5F54, 0x8FA1, 0x5F59, 0x8FA2, 0x5F5A, 0x8FA3, 0x5F5B,
+	0x8FA4, 0x5F5C, 0x8FA5, 0x5F5E, 0x8FA6, 0x5F5F, 0x8FA7, 0x5F60,
+	0x8FA8, 0x5F63, 0x8FA9, 0x5F65, 0x8FAA, 0x5F67, 0x8FAB, 0x5F68,
+	0x8FAC, 0x5F6B, 0x8FAD, 0x5F6E, 0x8FAE, 0x5F6F, 0x8FAF, 0x5F72,
+	0x8FB0, 0x5F74, 0x8FB1, 0x5F75, 0x8FB2, 0x5F76, 0x8FB3, 0x5F78,
+	0x8FB4, 0x5F7A, 0x8FB5, 0x5F7D, 0x8FB6, 0x5F7E, 0x8FB7, 0x5F7F,
+	0x8FB8, 0x5F83, 0x8FB9, 0x5F86, 0x8FBA, 0x5F8D, 0x8FBB, 0x5F8E,
+	0x8FBC, 0x5F8F, 0x8FBD, 0x5F91, 0x8FBE, 0x5F93, 0x8FBF, 0x5F94,
+	0x8FC0, 0x5F96, 0x8FC1, 0x5F9A, 0x8FC2, 0x5F9B, 0x8FC3, 0x5F9D,
+	0x8FC4, 0x5F9E, 0x8FC5, 0x5F9F, 0x8FC6, 0x5FA0, 0x8FC7, 0x5FA2,
+	0x8FC8, 0x5FA3, 0x8FC9, 0x5FA4, 0x8FCA, 0x5FA5, 0x8FCB, 0x5FA6,
+	0x8FCC, 0x5FA7, 0x8FCD, 0x5FA9, 0x8FCE, 0x5FAB, 0x8FCF, 0x5FAC,
+	0x8FD0, 0x5FAF, 0x8FD1, 0x5FB0, 0x8FD2, 0x5FB1, 0x8FD3, 0x5FB2,
+	0x8FD4, 0x5FB3, 0x8FD5, 0x5FB4, 0x8FD6, 0x5FB6, 0x8FD7, 0x5FB8,
+	0x8FD8, 0x5FB9, 0x8FD9, 0x5FBA, 0x8FDA, 0x5FBB, 0x8FDB, 0x5FBE,
+	0x8FDC, 0x5FBF, 0x8FDD, 0x5FC0, 0x8FDE, 0x5FC1, 0x8FDF, 0x5FC2,
+	0x8FE0, 0x5FC7, 0x8FE1, 0x5FC8, 0x8FE2, 0x5FCA, 0x8FE3, 0x5FCB,
+	0x8FE4, 0x5FCE, 0x8FE5, 0x5FD3, 0x8FE6, 0x5FD4, 0x8FE7, 0x5FD5,
+	0x8FE8, 0x5FDA, 0x8FE9, 0x5FDB, 0x8FEA, 0x5FDC, 0x8FEB, 0x5FDE,
+	0x8FEC, 0x5FDF, 0x8FED, 0x5FE2, 0x8FEE, 0x5FE3, 0x8FEF, 0x5FE5,
+	0x8FF0, 0x5FE6, 0x8FF1, 0x5FE8, 0x8FF2, 0x5FE9, 0x8FF3, 0x5FEC,
+	0x8FF4, 0x5FEF, 0x8FF5, 0x5FF0, 0x8FF6, 0x5FF2, 0x8FF7, 0x5FF3,
+	0x8FF8, 0x5FF4, 0x8FF9, 0x5FF6, 0x8FFA, 0x5FF7, 0x8FFB, 0x5FF9,
+	0x8FFC, 0x5FFA, 0x8FFD, 0x5FFC, 0x8FFE, 0x6007, 0x9040, 0x6008,
+	0x9041, 0x6009, 0x9042, 0x600B, 0x9043, 0x600C, 0x9044, 0x6010,
+	0x9045, 0x6011, 0x9046, 0x6013, 0x9047, 0x6017, 0x9048, 0x6018,
+	0x9049, 0x601A, 0x904A, 0x601E, 0x904B, 0x601F, 0x904C, 0x6022,
+	0x904D, 0x6023, 0x904E, 0x6024, 0x904F, 0x602C, 0x9050, 0x602D,
+	0x9051, 0x602E, 0x9052, 0x6030, 0x9053, 0x6031, 0x9054, 0x6032,
+	0x9055, 0x6033, 0x9056, 0x6034, 0x9057, 0x6036, 0x9058, 0x6037,
+	0x9059, 0x6038, 0x905A, 0x6039, 0x905B, 0x603A, 0x905C, 0x603D,
+	0x905D, 0x603E, 0x905E, 0x6040, 0x905F, 0x6044, 0x9060, 0x6045,
+	0x9061, 0x6046, 0x9062, 0x6047, 0x9063, 0x6048, 0x9064, 0x6049,
+	0x9065, 0x604A, 0x9066, 0x604C, 0x9067, 0x604E, 0x9068, 0x604F,
+	0x9069, 0x6051, 0x906A, 0x6053, 0x906B, 0x6054, 0x906C, 0x6056,
+	0x906D, 0x6057, 0x906E, 0x6058, 0x906F, 0x605B, 0x9070, 0x605C,
+	0x9071, 0x605E, 0x9072, 0x605F, 0x9073, 0x6060, 0x9074, 0x6061,
+	0x9075, 0x6065, 0x9076, 0x6066, 0x9077, 0x606E, 0x9078, 0x6071,
+	0x9079, 0x6072, 0x907A, 0x6074, 0x907B, 0x6075, 0x907C, 0x6077,
+	0x907D, 0x607E, 0x907E, 0x6080, 0x9080, 0x6081, 0x9081, 0x6082,
+	0x9082, 0x6085, 0x9083, 0x6086, 0x9084, 0x6087, 0x9085, 0x6088,
+	0x9086, 0x608A, 0x9087, 0x608B, 0x9088, 0x608E, 0x9089, 0x608F,
+	0x908A, 0x6090, 0x908B, 0x6091, 0x908C, 0x6093, 0x908D, 0x6095,
+	0x908E, 0x6097, 0x908F, 0x6098, 0x9090, 0x6099, 0x9091, 0x609C,
+	0x9092, 0x609E, 0x9093, 0x60A1, 0x9094, 0x60A2, 0x9095, 0x60A4,
+	0x9096, 0x60A5, 0x9097, 0x60A7, 0x9098, 0x60A9, 0x9099, 0x60AA,
+	0x909A, 0x60AE, 0x909B, 0x60B0, 0x909C, 0x60B3, 0x909D, 0x60B5,
+	0x909E, 0x60B6, 0x909F, 0x60B7, 0x90A0, 0x60B9, 0x90A1, 0x60BA,
+	0x90A2, 0x60BD, 0x90A3, 0x60BE, 0x90A4, 0x60BF, 0x90A5, 0x60C0,
+	0x90A6, 0x60C1, 0x90A7, 0x60C2, 0x90A8, 0x60C3, 0x90A9, 0x60C4,
+	0x90AA, 0x60C7, 0x90AB, 0x60C8, 0x90AC, 0x60C9, 0x90AD, 0x60CC,
+	0x90AE, 0x60CD, 0x90AF, 0x60CE, 0x90B0, 0x60CF, 0x90B1, 0x60D0,
+	0x90B2, 0x60D2, 0x90B3, 0x60D3, 0x90B4, 0x60D4, 0x90B5, 0x60D6,
+	0x90B6, 0x60D7, 0x90B7, 0x60D9, 0x90B8, 0x60DB, 0x90B9, 0x60DE,
+	0x90BA, 0x60E1, 0x90BB, 0x60E2, 0x90BC, 0x60E3, 0x90BD, 0x60E4,
+	0x90BE, 0x60E5, 0x90BF, 0x60EA, 0x90C0, 0x60F1, 0x90C1, 0x60F2,
+	0x90C2, 0x60F5, 0x90C3, 0x60F7, 0x90C4, 0x60F8, 0x90C5, 0x60FB,
+	0x90C6, 0x60FC, 0x90C7, 0x60FD, 0x90C8, 0x60FE, 0x90C9, 0x60FF,
+	0x90CA, 0x6102, 0x90CB, 0x6103, 0x90CC, 0x6104, 0x90CD, 0x6105,
+	0x90CE, 0x6107, 0x90CF, 0x610A, 0x90D0, 0x610B, 0x90D1, 0x610C,
+	0x90D2, 0x6110, 0x90D3, 0x6111, 0x90D4, 0x6112, 0x90D5, 0x6113,
+	0x90D6, 0x6114, 0x90D7, 0x6116, 0x90D8, 0x6117, 0x90D9, 0x6118,
+	0x90DA, 0x6119, 0x90DB, 0x611B, 0x90DC, 0x611C, 0x90DD, 0x611D,
+	0x90DE, 0x611E, 0x90DF, 0x6121, 0x90E0, 0x6122, 0x90E1, 0x6125,
+	0x90E2, 0x6128, 0x90E3, 0x6129, 0x90E4, 0x612A, 0x90E5, 0x612C,
+	0x90E6, 0x612D, 0x90E7, 0x612E, 0x90E8, 0x612F, 0x90E9, 0x6130,
+	0x90EA, 0x6131, 0x90EB, 0x6132, 0x90EC, 0x6133, 0x90ED, 0x6134,
+	0x90EE, 0x6135, 0x90EF, 0x6136, 0x90F0, 0x6137, 0x90F1, 0x6138,
+	0x90F2, 0x6139, 0x90F3, 0x613A, 0x90F4, 0x613B, 0x90F5, 0x613C,
+	0x90F6, 0x613D, 0x90F7, 0x613E, 0x90F8, 0x6140, 0x90F9, 0x6141,
+	0x90FA, 0x6142, 0x90FB, 0x6143, 0x90FC, 0x6144, 0x90FD, 0x6145,
+	0x90FE, 0x6146, 0x9140, 0x6147, 0x9141, 0x6149, 0x9142, 0x614B,
+	0x9143, 0x614D, 0x9144, 0x614F, 0x9145, 0x6150, 0x9146, 0x6152,
+	0x9147, 0x6153, 0x9148, 0x6154, 0x9149, 0x6156, 0x914A, 0x6157,
+	0x914B, 0x6158, 0x914C, 0x6159, 0x914D, 0x615A, 0x914E, 0x615B,
+	0x914F, 0x615C, 0x9150, 0x615E, 0x9151, 0x615F, 0x9152, 0x6160,
+	0x9153, 0x6161, 0x9154, 0x6163, 0x9155, 0x6164, 0x9156, 0x6165,
+	0x9157, 0x6166, 0x9158, 0x6169, 0x9159, 0x616A, 0x915A, 0x616B,
+	0x915B, 0x616C, 0x915C, 0x616D, 0x915D, 0x616E, 0x915E, 0x616F,
+	0x915F, 0x6171, 0x9160, 0x6172, 0x9161, 0x6173, 0x9162, 0x6174,
+	0x9163, 0x6176, 0x9164, 0x6178, 0x9165, 0x6179, 0x9166, 0x617A,
+	0x9167, 0x617B, 0x9168, 0x617C, 0x9169, 0x617D, 0x916A, 0x617E,
+	0x916B, 0x617F, 0x916C, 0x6180, 0x916D, 0x6181, 0x916E, 0x6182,
+	0x916F, 0x6183, 0x9170, 0x6184, 0x9171, 0x6185, 0x9172, 0x6186,
+	0x9173, 0x6187, 0x9174, 0x6188, 0x9175, 0x6189, 0x9176, 0x618A,
+	0x9177, 0x618C, 0x9178, 0x618D, 0x9179, 0x618F, 0x917A, 0x6190,
+	0x917B, 0x6191, 0x917C, 0x6192, 0x917D, 0x6193, 0x917E, 0x6195,
+	0x9180, 0x6196, 0x9181, 0x6197, 0x9182, 0x6198, 0x9183, 0x6199,
+	0x9184, 0x619A, 0x9185, 0x619B, 0x9186, 0x619C, 0x9187, 0x619E,
+	0x9188, 0x619F, 0x9189, 0x61A0, 0x918A, 0x61A1, 0x918B, 0x61A2,
+	0x918C, 0x61A3, 0x918D, 0x61A4, 0x918E, 0x61A5, 0x918F, 0x61A6,
+	0x9190, 0x61AA, 0x9191, 0x61AB, 0x9192, 0x61AD, 0x9193, 0x61AE,
+	0x9194, 0x61AF, 0x9195, 0x61B0, 0x9196, 0x61B1, 0x9197, 0x61B2,
+	0x9198, 0x61B3, 0x9199, 0x61B4, 0x919A, 0x61B5, 0x919B, 0x61B6,
+	0x919C, 0x61B8, 0x919D, 0x61B9, 0x919E, 0x61BA, 0x919F, 0x61BB,
+	0x91A0, 0x61BC, 0x91A1, 0x61BD, 0x91A2, 0x61BF, 0x91A3, 0x61C0,
+	0x91A4, 0x61C1, 0x91A5, 0x61C3, 0x91A6, 0x61C4, 0x91A7, 0x61C5,
+	0x91A8, 0x61C6, 0x91A9, 0x61C7, 0x91AA, 0x61C9, 0x91AB, 0x61CC,
+	0x91AC, 0x61CD, 0x91AD, 0x61CE, 0x91AE, 0x61CF, 0x91AF, 0x61D0,
+	0x91B0, 0x61D3, 0x91B1, 0x61D5, 0x91B2, 0x61D6, 0x91B3, 0x61D7,
+	0x91B4, 0x61D8, 0x91B5, 0x61D9, 0x91B6, 0x61DA, 0x91B7, 0x61DB,
+	0x91B8, 0x61DC, 0x91B9, 0x61DD, 0x91BA, 0x61DE, 0x91BB, 0x61DF,
+	0x91BC, 0x61E0, 0x91BD, 0x61E1, 0x91BE, 0x61E2, 0x91BF, 0x61E3,
+	0x91C0, 0x61E4, 0x91C1, 0x61E5, 0x91C2, 0x61E7, 0x91C3, 0x61E8,
+	0x91C4, 0x61E9, 0x91C5, 0x61EA, 0x91C6, 0x61EB, 0x91C7, 0x61EC,
+	0x91C8, 0x61ED, 0x91C9, 0x61EE, 0x91CA, 0x61EF, 0x91CB, 0x61F0,
+	0x91CC, 0x61F1, 0x91CD, 0x61F2, 0x91CE, 0x61F3, 0x91CF, 0x61F4,
+	0x91D0, 0x61F6, 0x91D1, 0x61F7, 0x91D2, 0x61F8, 0x91D3, 0x61F9,
+	0x91D4, 0x61FA, 0x91D5, 0x61FB, 0x91D6, 0x61FC, 0x91D7, 0x61FD,
+	0x91D8, 0x61FE, 0x91D9, 0x6200, 0x91DA, 0x6201, 0x91DB, 0x6202,
+	0x91DC, 0x6203, 0x91DD, 0x6204, 0x91DE, 0x6205, 0x91DF, 0x6207,
+	0x91E0, 0x6209, 0x91E1, 0x6213, 0x91E2, 0x6214, 0x91E3, 0x6219,
+	0x91E4, 0x621C, 0x91E5, 0x621D, 0x91E6, 0x621E, 0x91E7, 0x6220,
+	0x91E8, 0x6223, 0x91E9, 0x6226, 0x91EA, 0x6227, 0x91EB, 0x6228,
+	0x91EC, 0x6229, 0x91ED, 0x622B, 0x91EE, 0x622D, 0x91EF, 0x622F,
+	0x91F0, 0x6230, 0x91F1, 0x6231, 0x91F2, 0x6232, 0x91F3, 0x6235,
+	0x91F4, 0x6236, 0x91F5, 0x6238, 0x91F6, 0x6239, 0x91F7, 0x623A,
+	0x91F8, 0x623B, 0x91F9, 0x623C, 0x91FA, 0x6242, 0x91FB, 0x6244,
+	0x91FC, 0x6245, 0x91FD, 0x6246, 0x91FE, 0x624A, 0x9240, 0x624F,
+	0x9241, 0x6250, 0x9242, 0x6255, 0x9243, 0x6256, 0x9244, 0x6257,
+	0x9245, 0x6259, 0x9246, 0x625A, 0x9247, 0x625C, 0x9248, 0x625D,
+	0x9249, 0x625E, 0x924A, 0x625F, 0x924B, 0x6260, 0x924C, 0x6261,
+	0x924D, 0x6262, 0x924E, 0x6264, 0x924F, 0x6265, 0x9250, 0x6268,
+	0x9251, 0x6271, 0x9252, 0x6272, 0x9253, 0x6274, 0x9254, 0x6275,
+	0x9255, 0x6277, 0x9256, 0x6278, 0x9257, 0x627A, 0x9258, 0x627B,
+	0x9259, 0x627D, 0x925A, 0x6281, 0x925B, 0x6282, 0x925C, 0x6283,
+	0x925D, 0x6285, 0x925E, 0x6286, 0x925F, 0x6287, 0x9260, 0x6288,
+	0x9261, 0x628B, 0x9262, 0x628C, 0x9263, 0x628D, 0x9264, 0x628E,
+	0x9265, 0x628F, 0x9266, 0x6290, 0x9267, 0x6294, 0x9268, 0x6299,
+	0x9269, 0x629C, 0x926A, 0x629D, 0x926B, 0x629E, 0x926C, 0x62A3,
+	0x926D, 0x62A6, 0x926E, 0x62A7, 0x926F, 0x62A9, 0x9270, 0x62AA,
+	0x9271, 0x62AD, 0x9272, 0x62AE, 0x9273, 0x62AF, 0x9274, 0x62B0,
+	0x9275, 0x62B2, 0x9276, 0x62B3, 0x9277, 0x62B4, 0x9278, 0x62B6,
+	0x9279, 0x62B7, 0x927A, 0x62B8, 0x927B, 0x62BA, 0x927C, 0x62BE,
+	0x927D, 0x62C0, 0x927E, 0x62C1, 0x9280, 0x62C3, 0x9281, 0x62CB,
+	0x9282, 0x62CF, 0x9283, 0x62D1, 0x9284, 0x62D5, 0x9285, 0x62DD,
+	0x9286, 0x62DE, 0x9287, 0x62E0, 0x9288, 0x62E1, 0x9289, 0x62E4,
+	0x928A, 0x62EA, 0x928B, 0x62EB, 0x928C, 0x62F0, 0x928D, 0x62F2,
+	0x928E, 0x62F5, 0x928F, 0x62F8, 0x9290, 0x62F9, 0x9291, 0x62FA,
+	0x9292, 0x62FB, 0x9293, 0x6300, 0x9294, 0x6303, 0x9295, 0x6304,
+	0x9296, 0x6305, 0x9297, 0x6306, 0x9298, 0x630A, 0x9299, 0x630B,
+	0x929A, 0x630C, 0x929B, 0x630D, 0x929C, 0x630F, 0x929D, 0x6310,
+	0x929E, 0x6312, 0x929F, 0x6313, 0x92A0, 0x6314, 0x92A1, 0x6315,
+	0x92A2, 0x6317, 0x92A3, 0x6318, 0x92A4, 0x6319, 0x92A5, 0x631C,
+	0x92A6, 0x6326, 0x92A7, 0x6327, 0x92A8, 0x6329, 0x92A9, 0x632C,
+	0x92AA, 0x632D, 0x92AB, 0x632E, 0x92AC, 0x6330, 0x92AD, 0x6331,
+	0x92AE, 0x6333, 0x92AF, 0x6334, 0x92B0, 0x6335, 0x92B1, 0x6336,
+	0x92B2, 0x6337, 0x92B3, 0x6338, 0x92B4, 0x633B, 0x92B5, 0x633C,
+	0x92B6, 0x633E, 0x92B7, 0x633F, 0x92B8, 0x6340, 0x92B9, 0x6341,
+	0x92BA, 0x6344, 0x92BB, 0x6347, 0x92BC, 0x6348, 0x92BD, 0x634A,
+	0x92BE, 0x6351, 0x92BF, 0x6352, 0x92C0, 0x6353, 0x92C1, 0x6354,
+	0x92C2, 0x6356, 0x92C3, 0x6357, 0x92C4, 0x6358, 0x92C5, 0x6359,
+	0x92C6, 0x635A, 0x92C7, 0x635B, 0x92C8, 0x635C, 0x92C9, 0x635D,
+	0x92CA, 0x6360, 0x92CB, 0x6364, 0x92CC, 0x6365, 0x92CD, 0x6366,
+	0x92CE, 0x6368, 0x92CF, 0x636A, 0x92D0, 0x636B, 0x92D1, 0x636C,
+	0x92D2, 0x636F, 0x92D3, 0x6370, 0x92D4, 0x6372, 0x92D5, 0x6373,
+	0x92D6, 0x6374, 0x92D7, 0x6375, 0x92D8, 0x6378, 0x92D9, 0x6379,
+	0x92DA, 0x637C, 0x92DB, 0x637D, 0x92DC, 0x637E, 0x92DD, 0x637F,
+	0x92DE, 0x6381, 0x92DF, 0x6383, 0x92E0, 0x6384, 0x92E1, 0x6385,
+	0x92E2, 0x6386, 0x92E3, 0x638B, 0x92E4, 0x638D, 0x92E5, 0x6391,
+	0x92E6, 0x6393, 0x92E7, 0x6394, 0x92E8, 0x6395, 0x92E9, 0x6397,
+	0x92EA, 0x6399, 0x92EB, 0x639A, 0x92EC, 0x639B, 0x92ED, 0x639C,
+	0x92EE, 0x639D, 0x92EF, 0x639E, 0x92F0, 0x639F, 0x92F1, 0x63A1,
+	0x92F2, 0x63A4, 0x92F3, 0x63A6, 0x92F4, 0x63AB, 0x92F5, 0x63AF,
+	0x92F6, 0x63B1, 0x92F7, 0x63B2, 0x92F8, 0x63B5, 0x92F9, 0x63B6,
+	0x92FA, 0x63B9, 0x92FB, 0x63BB, 0x92FC, 0x63BD, 0x92FD, 0x63BF,
+	0x92FE, 0x63C0, 0x9340, 0x63C1, 0x9341, 0x63C2, 0x9342, 0x63C3,
+	0x9343, 0x63C5, 0x9344, 0x63C7, 0x9345, 0x63C8, 0x9346, 0x63CA,
+	0x9347, 0x63CB, 0x9348, 0x63CC, 0x9349, 0x63D1, 0x934A, 0x63D3,
+	0x934B, 0x63D4, 0x934C, 0x63D5, 0x934D, 0x63D7, 0x934E, 0x63D8,
+	0x934F, 0x63D9, 0x9350, 0x63DA, 0x9351, 0x63DB, 0x9352, 0x63DC,
+	0x9353, 0x63DD, 0x9354, 0x63DF, 0x9355, 0x63E2, 0x9356, 0x63E4,
+	0x9357, 0x63E5, 0x9358, 0x63E6, 0x9359, 0x63E7, 0x935A, 0x63E8,
+	0x935B, 0x63EB, 0x935C, 0x63EC, 0x935D, 0x63EE, 0x935E, 0x63EF,
+	0x935F, 0x63F0, 0x9360, 0x63F1, 0x9361, 0x63F3, 0x9362, 0x63F5,
+	0x9363, 0x63F7, 0x9364, 0x63F9, 0x9365, 0x63FA, 0x9366, 0x63FB,
+	0x9367, 0x63FC, 0x9368, 0x63FE, 0x9369, 0x6403, 0x936A, 0x6404,
+	0x936B, 0x6406, 0x936C, 0x6407, 0x936D, 0x6408, 0x936E, 0x6409,
+	0x936F, 0x640A, 0x9370, 0x640D, 0x9371, 0x640E, 0x9372, 0x6411,
+	0x9373, 0x6412, 0x9374, 0x6415, 0x9375, 0x6416, 0x9376, 0x6417,
+	0x9377, 0x6418, 0x9378, 0x6419, 0x9379, 0x641A, 0x937A, 0x641D,
+	0x937B, 0x641F, 0x937C, 0x6422, 0x937D, 0x6423, 0x937E, 0x6424,
+	0x9380, 0x6425, 0x9381, 0x6427, 0x9382, 0x6428, 0x9383, 0x6429,
+	0x9384, 0x642B, 0x9385, 0x642E, 0x9386, 0x642F, 0x9387, 0x6430,
+	0x9388, 0x6431, 0x9389, 0x6432, 0x938A, 0x6433, 0x938B, 0x6435,
+	0x938C, 0x6436, 0x938D, 0x6437, 0x938E, 0x6438, 0x938F, 0x6439,
+	0x9390, 0x643B, 0x9391, 0x643C, 0x9392, 0x643E, 0x9393, 0x6440,
+	0x9394, 0x6442, 0x9395, 0x6443, 0x9396, 0x6449, 0x9397, 0x644B,
+	0x9398, 0x644C, 0x9399, 0x644D, 0x939A, 0x644E, 0x939B, 0x644F,
+	0x939C, 0x6450, 0x939D, 0x6451, 0x939E, 0x6453, 0x939F, 0x6455,
+	0x93A0, 0x6456, 0x93A1, 0x6457, 0x93A2, 0x6459, 0x93A3, 0x645A,
+	0x93A4, 0x645B, 0x93A5, 0x645C, 0x93A6, 0x645D, 0x93A7, 0x645F,
+	0x93A8, 0x6460, 0x93A9, 0x6461, 0x93AA, 0x6462, 0x93AB, 0x6463,
+	0x93AC, 0x6464, 0x93AD, 0x6465, 0x93AE, 0x6466, 0x93AF, 0x6468,
+	0x93B0, 0x646A, 0x93B1, 0x646B, 0x93B2, 0x646C, 0x93B3, 0x646E,
+	0x93B4, 0x646F, 0x93B5, 0x6470, 0x93B6, 0x6471, 0x93B7, 0x6472,
+	0x93B8, 0x6473, 0x93B9, 0x6474, 0x93BA, 0x6475, 0x93BB, 0x6476,
+	0x93BC, 0x6477, 0x93BD, 0x647B, 0x93BE, 0x647C, 0x93BF, 0x647D,
+	0x93C0, 0x647E, 0x93C1, 0x647F, 0x93C2, 0x6480, 0x93C3, 0x6481,
+	0x93C4, 0x6483, 0x93C5, 0x6486, 0x93C6, 0x6488, 0x93C7, 0x6489,
+	0x93C8, 0x648A, 0x93C9, 0x648B, 0x93CA, 0x648C, 0x93CB, 0x648D,
+	0x93CC, 0x648E, 0x93CD, 0x648F, 0x93CE, 0x6490, 0x93CF, 0x6493,
+	0x93D0, 0x6494, 0x93D1, 0x6497, 0x93D2, 0x6498, 0x93D3, 0x649A,
+	0x93D4, 0x649B, 0x93D5, 0x649C, 0x93D6, 0x649D, 0x93D7, 0x649F,
+	0x93D8, 0x64A0, 0x93D9, 0x64A1, 0x93DA, 0x64A2, 0x93DB, 0x64A3,
+	0x93DC, 0x64A5, 0x93DD, 0x64A6, 0x93DE, 0x64A7, 0x93DF, 0x64A8,
+	0x93E0, 0x64AA, 0x93E1, 0x64AB, 0x93E2, 0x64AF, 0x93E3, 0x64B1,
+	0x93E4, 0x64B2, 0x93E5, 0x64B3, 0x93E6, 0x64B4, 0x93E7, 0x64B6,
+	0x93E8, 0x64B9, 0x93E9, 0x64BB, 0x93EA, 0x64BD, 0x93EB, 0x64BE,
+	0x93EC, 0x64BF, 0x93ED, 0x64C1, 0x93EE, 0x64C3, 0x93EF, 0x64C4,
+	0x93F0, 0x64C6, 0x93F1, 0x64C7, 0x93F2, 0x64C8, 0x93F3, 0x64C9,
+	0x93F4, 0x64CA, 0x93F5, 0x64CB, 0x93F6, 0x64CC, 0x93F7, 0x64CF,
+	0x93F8, 0x64D1, 0x93F9, 0x64D3, 0x93FA, 0x64D4, 0x93FB, 0x64D5,
+	0x93FC, 0x64D6, 0x93FD, 0x64D9, 0x93FE, 0x64DA, 0x9440, 0x64DB,
+	0x9441, 0x64DC, 0x9442, 0x64DD, 0x9443, 0x64DF, 0x9444, 0x64E0,
+	0x9445, 0x64E1, 0x9446, 0x64E3, 0x9447, 0x64E5, 0x9448, 0x64E7,
+	0x9449, 0x64E8, 0x944A, 0x64E9, 0x944B, 0x64EA, 0x944C, 0x64EB,
+	0x944D, 0x64EC, 0x944E, 0x64ED, 0x944F, 0x64EE, 0x9450, 0x64EF,
+	0x9451, 0x64F0, 0x9452, 0x64F1, 0x9453, 0x64F2, 0x9454, 0x64F3,
+	0x9455, 0x64F4, 0x9456, 0x64F5, 0x9457, 0x64F6, 0x9458, 0x64F7,
+	0x9459, 0x64F8, 0x945A, 0x64F9, 0x945B, 0x64FA, 0x945C, 0x64FB,
+	0x945D, 0x64FC, 0x945E, 0x64FD, 0x945F, 0x64FE, 0x9460, 0x64FF,
+	0x9461, 0x6501, 0x9462, 0x6502, 0x9463, 0x6503, 0x9464, 0x6504,
+	0x9465, 0x6505, 0x9466, 0x6506, 0x9467, 0x6507, 0x9468, 0x6508,
+	0x9469, 0x650A, 0x946A, 0x650B, 0x946B, 0x650C, 0x946C, 0x650D,
+	0x946D, 0x650E, 0x946E, 0x650F, 0x946F, 0x6510, 0x9470, 0x6511,
+	0x9471, 0x6513, 0x9472, 0x6514, 0x9473, 0x6515, 0x9474, 0x6516,
+	0x9475, 0x6517, 0x9476, 0x6519, 0x9477, 0x651A, 0x9478, 0x651B,
+	0x9479, 0x651C, 0x947A, 0x651D, 0x947B, 0x651E, 0x947C, 0x651F,
+	0x947D, 0x6520, 0x947E, 0x6521, 0x9480, 0x6522, 0x9481, 0x6523,
+	0x9482, 0x6524, 0x9483, 0x6526, 0x9484, 0x6527, 0x9485, 0x6528,
+	0x9486, 0x6529, 0x9487, 0x652A, 0x9488, 0x652C, 0x9489, 0x652D,
+	0x948A, 0x6530, 0x948B, 0x6531, 0x948C, 0x6532, 0x948D, 0x6533,
+	0x948E, 0x6537, 0x948F, 0x653A, 0x9490, 0x653C, 0x9491, 0x653D,
+	0x9492, 0x6540, 0x9493, 0x6541, 0x9494, 0x6542, 0x9495, 0x6543,
+	0x9496, 0x6544, 0x9497, 0x6546, 0x9498, 0x6547, 0x9499, 0x654A,
+	0x949A, 0x654B, 0x949B, 0x654D, 0x949C, 0x654E, 0x949D, 0x6550,
+	0x949E, 0x6552, 0x949F, 0x6553, 0x94A0, 0x6554, 0x94A1, 0x6557,
+	0x94A2, 0x6558, 0x94A3, 0x655A, 0x94A4, 0x655C, 0x94A5, 0x655F,
+	0x94A6, 0x6560, 0x94A7, 0x6561, 0x94A8, 0x6564, 0x94A9, 0x6565,
+	0x94AA, 0x6567, 0x94AB, 0x6568, 0x94AC, 0x6569, 0x94AD, 0x656A,
+	0x94AE, 0x656D, 0x94AF, 0x656E, 0x94B0, 0x656F, 0x94B1, 0x6571,
+	0x94B2, 0x6573, 0x94B3, 0x6575, 0x94B4, 0x6576, 0x94B5, 0x6578,
+	0x94B6, 0x6579, 0x94B7, 0x657A, 0x94B8, 0x657B, 0x94B9, 0x657C,
+	0x94BA, 0x657D, 0x94BB, 0x657E, 0x94BC, 0x657F, 0x94BD, 0x6580,
+	0x94BE, 0x6581, 0x94BF, 0x6582, 0x94C0, 0x6583, 0x94C1, 0x6584,
+	0x94C2, 0x6585, 0x94C3, 0x6586, 0x94C4, 0x6588, 0x94C5, 0x6589,
+	0x94C6, 0x658A, 0x94C7, 0x658D, 0x94C8, 0x658E, 0x94C9, 0x658F,
+	0x94CA, 0x6592, 0x94CB, 0x6594, 0x94CC, 0x6595, 0x94CD, 0x6596,
+	0x94CE, 0x6598, 0x94CF, 0x659A, 0x94D0, 0x659D, 0x94D1, 0x659E,
+	0x94D2, 0x65A0, 0x94D3, 0x65A2, 0x94D4, 0x65A3, 0x94D5, 0x65A6,
+	0x94D6, 0x65A8, 0x94D7, 0x65AA, 0x94D8, 0x65AC, 0x94D9, 0x65AE,
+	0x94DA, 0x65B1, 0x94DB, 0x65B2, 0x94DC, 0x65B3, 0x94DD, 0x65B4,
+	0x94DE, 0x65B5, 0x94DF, 0x65B6, 0x94E0, 0x65B7, 0x94E1, 0x65B8,
+	0x94E2, 0x65BA, 0x94E3, 0x65BB, 0x94E4, 0x65BE, 0x94E5, 0x65BF,
+	0x94E6, 0x65C0, 0x94E7, 0x65C2, 0x94E8, 0x65C7, 0x94E9, 0x65C8,
+	0x94EA, 0x65C9, 0x94EB, 0x65CA, 0x94EC, 0x65CD, 0x94ED, 0x65D0,
+	0x94EE, 0x65D1, 0x94EF, 0x65D3, 0x94F0, 0x65D4, 0x94F1, 0x65D5,
+	0x94F2, 0x65D8, 0x94F3, 0x65D9, 0x94F4, 0x65DA, 0x94F5, 0x65DB,
+	0x94F6, 0x65DC, 0x94F7, 0x65DD, 0x94F8, 0x65DE, 0x94F9, 0x65DF,
+	0x94FA, 0x65E1, 0x94FB, 0x65E3, 0x94FC, 0x65E4, 0x94FD, 0x65EA,
+	0x94FE, 0x65EB, 0x9540, 0x65F2, 0x9541, 0x65F3, 0x9542, 0x65F4,
+	0x9543, 0x65F5, 0x9544, 0x65F8, 0x9545, 0x65F9, 0x9546, 0x65FB,
+	0x9547, 0x65FC, 0x9548, 0x65FD, 0x9549, 0x65FE, 0x954A, 0x65FF,
+	0x954B, 0x6601, 0x954C, 0x6604, 0x954D, 0x6605, 0x954E, 0x6607,
+	0x954F, 0x6608, 0x9550, 0x6609, 0x9551, 0x660B, 0x9552, 0x660D,
+	0x9553, 0x6610, 0x9554, 0x6611, 0x9555, 0x6612, 0x9556, 0x6616,
+	0x9557, 0x6617, 0x9558, 0x6618, 0x9559, 0x661A, 0x955A, 0x661B,
+	0x955B, 0x661C, 0x955C, 0x661E, 0x955D, 0x6621, 0x955E, 0x6622,
+	0x955F, 0x6623, 0x9560, 0x6624, 0x9561, 0x6626, 0x9562, 0x6629,
+	0x9563, 0x662A, 0x9564, 0x662B, 0x9565, 0x662C, 0x9566, 0x662E,
+	0x9567, 0x6630, 0x9568, 0x6632, 0x9569, 0x6633, 0x956A, 0x6637,
+	0x956B, 0x6638, 0x956C, 0x6639, 0x956D, 0x663A, 0x956E, 0x663B,
+	0x956F, 0x663D, 0x9570, 0x663F, 0x9571, 0x6640, 0x9572, 0x6642,
+	0x9573, 0x6644, 0x9574, 0x6645, 0x9575, 0x6646, 0x9576, 0x6647,
+	0x9577, 0x6648, 0x9578, 0x6649, 0x9579, 0x664A, 0x957A, 0x664D,
+	0x957B, 0x664E, 0x957C, 0x6650, 0x957D, 0x6651, 0x957E, 0x6658,
+	0x9580, 0x6659, 0x9581, 0x665B, 0x9582, 0x665C, 0x9583, 0x665D,
+	0x9584, 0x665E, 0x9585, 0x6660, 0x9586, 0x6662, 0x9587, 0x6663,
+	0x9588, 0x6665, 0x9589, 0x6667, 0x958A, 0x6669, 0x958B, 0x666A,
+	0x958C, 0x666B, 0x958D, 0x666C, 0x958E, 0x666D, 0x958F, 0x6671,
+	0x9590, 0x6672, 0x9591, 0x6673, 0x9592, 0x6675, 0x9593, 0x6678,
+	0x9594, 0x6679, 0x9595, 0x667B, 0x9596, 0x667C, 0x9597, 0x667D,
+	0x9598, 0x667F, 0x9599, 0x6680, 0x959A, 0x6681, 0x959B, 0x6683,
+	0x959C, 0x6685, 0x959D, 0x6686, 0x959E, 0x6688, 0x959F, 0x6689,
+	0x95A0, 0x668A, 0x95A1, 0x668B, 0x95A2, 0x668D, 0x95A3, 0x668E,
+	0x95A4, 0x668F, 0x95A5, 0x6690, 0x95A6, 0x6692, 0x95A7, 0x6693,
+	0x95A8, 0x6694, 0x95A9, 0x6695, 0x95AA, 0x6698, 0x95AB, 0x6699,
+	0x95AC, 0x669A, 0x95AD, 0x669B, 0x95AE, 0x669C, 0x95AF, 0x669E,
+	0x95B0, 0x669F, 0x95B1, 0x66A0, 0x95B2, 0x66A1, 0x95B3, 0x66A2,
+	0x95B4, 0x66A3, 0x95B5, 0x66A4, 0x95B6, 0x66A5, 0x95B7, 0x66A6,
+	0x95B8, 0x66A9, 0x95B9, 0x66AA, 0x95BA, 0x66AB, 0x95BB, 0x66AC,
+	0x95BC, 0x66AD, 0x95BD, 0x66AF, 0x95BE, 0x66B0, 0x95BF, 0x66B1,
+	0x95C0, 0x66B2, 0x95C1, 0x66B3, 0x95C2, 0x66B5, 0x95C3, 0x66B6,
+	0x95C4, 0x66B7, 0x95C5, 0x66B8, 0x95C6, 0x66BA, 0x95C7, 0x66BB,
+	0x95C8, 0x66BC, 0x95C9, 0x66BD, 0x95CA, 0x66BF, 0x95CB, 0x66C0,
+	0x95CC, 0x66C1, 0x95CD, 0x66C2, 0x95CE, 0x66C3, 0x95CF, 0x66C4,
+	0x95D0, 0x66C5, 0x95D1, 0x66C6, 0x95D2, 0x66C7, 0x95D3, 0x66C8,
+	0x95D4, 0x66C9, 0x95D5, 0x66CA, 0x95D6, 0x66CB, 0x95D7, 0x66CC,
+	0x95D8, 0x66CD, 0x95D9, 0x66CE, 0x95DA, 0x66CF, 0x95DB, 0x66D0,
+	0x95DC, 0x66D1, 0x95DD, 0x66D2, 0x95DE, 0x66D3, 0x95DF, 0x66D4,
+	0x95E0, 0x66D5, 0x95E1, 0x66D6, 0x95E2, 0x66D7, 0x95E3, 0x66D8,
+	0x95E4, 0x66DA, 0x95E5, 0x66DE, 0x95E6, 0x66DF, 0x95E7, 0x66E0,
+	0x95E8, 0x66E1, 0x95E9, 0x66E2, 0x95EA, 0x66E3, 0x95EB, 0x66E4,
+	0x95EC, 0x66E5, 0x95ED, 0x66E7, 0x95EE, 0x66E8, 0x95EF, 0x66EA,
+	0x95F0, 0x66EB, 0x95F1, 0x66EC, 0x95F2, 0x66ED, 0x95F3, 0x66EE,
+	0x95F4, 0x66EF, 0x95F5, 0x66F1, 0x95F6, 0x66F5, 0x95F7, 0x66F6,
+	0x95F8, 0x66F8, 0x95F9, 0x66FA, 0x95FA, 0x66FB, 0x95FB, 0x66FD,
+	0x95FC, 0x6701, 0x95FD, 0x6702, 0x95FE, 0x6703, 0x9640, 0x6704,
+	0x9641, 0x6705, 0x9642, 0x6706, 0x9643, 0x6707, 0x9644, 0x670C,
+	0x9645, 0x670E, 0x9646, 0x670F, 0x9647, 0x6711, 0x9648, 0x6712,
+	0x9649, 0x6713, 0x964A, 0x6716, 0x964B, 0x6718, 0x964C, 0x6719,
+	0x964D, 0x671A, 0x964E, 0x671C, 0x964F, 0x671E, 0x9650, 0x6720,
+	0x9651, 0x6721, 0x9652, 0x6722, 0x9653, 0x6723, 0x9654, 0x6724,
+	0x9655, 0x6725, 0x9656, 0x6727, 0x9657, 0x6729, 0x9658, 0x672E,
+	0x9659, 0x6730, 0x965A, 0x6732, 0x965B, 0x6733, 0x965C, 0x6736,
+	0x965D, 0x6737, 0x965E, 0x6738, 0x965F, 0x6739, 0x9660, 0x673B,
+	0x9661, 0x673C, 0x9662, 0x673E, 0x9663, 0x673F, 0x9664, 0x6741,
+	0x9665, 0x6744, 0x9666, 0x6745, 0x9667, 0x6747, 0x9668, 0x674A,
+	0x9669, 0x674B, 0x966A, 0x674D, 0x966B, 0x6752, 0x966C, 0x6754,
+	0x966D, 0x6755, 0x966E, 0x6757, 0x966F, 0x6758, 0x9670, 0x6759,
+	0x9671, 0x675A, 0x9672, 0x675B, 0x9673, 0x675D, 0x9674, 0x6762,
+	0x9675, 0x6763, 0x9676, 0x6764, 0x9677, 0x6766, 0x9678, 0x6767,
+	0x9679, 0x676B, 0x967A, 0x676C, 0x967B, 0x676E, 0x967C, 0x6771,
+	0x967D, 0x6774, 0x967E, 0x6776, 0x9680, 0x6778, 0x9681, 0x6779,
+	0x9682, 0x677A, 0x9683, 0x677B, 0x9684, 0x677D, 0x9685, 0x6780,
+	0x9686, 0x6782, 0x9687, 0x6783, 0x9688, 0x6785, 0x9689, 0x6786,
+	0x968A, 0x6788, 0x968B, 0x678A, 0x968C, 0x678C, 0x968D, 0x678D,
+	0x968E, 0x678E, 0x968F, 0x678F, 0x9690, 0x6791, 0x9691, 0x6792,
+	0x9692, 0x6793, 0x9693, 0x6794, 0x9694, 0x6796, 0x9695, 0x6799,
+	0x9696, 0x679B, 0x9697, 0x679F, 0x9698, 0x67A0, 0x9699, 0x67A1,
+	0x969A, 0x67A4, 0x969B, 0x67A6, 0x969C, 0x67A9, 0x969D, 0x67AC,
+	0x969E, 0x67AE, 0x969F, 0x67B1, 0x96A0, 0x67B2, 0x96A1, 0x67B4,
+	0x96A2, 0x67B9, 0x96A3, 0x67BA, 0x96A4, 0x67BB, 0x96A5, 0x67BC,
+	0x96A6, 0x67BD, 0x96A7, 0x67BE, 0x96A8, 0x67BF, 0x96A9, 0x67C0,
+	0x96AA, 0x67C2, 0x96AB, 0x67C5, 0x96AC, 0x67C6, 0x96AD, 0x67C7,
+	0x96AE, 0x67C8, 0x96AF, 0x67C9, 0x96B0, 0x67CA, 0x96B1, 0x67CB,
+	0x96B2, 0x67CC, 0x96B3, 0x67CD, 0x96B4, 0x67CE, 0x96B5, 0x67D5,
+	0x96B6, 0x67D6, 0x96B7, 0x67D7, 0x96B8, 0x67DB, 0x96B9, 0x67DF,
+	0x96BA, 0x67E1, 0x96BB, 0x67E3, 0x96BC, 0x67E4, 0x96BD, 0x67E6,
+	0x96BE, 0x67E7, 0x96BF, 0x67E8, 0x96C0, 0x67EA, 0x96C1, 0x67EB,
+	0x96C2, 0x67ED, 0x96C3, 0x67EE, 0x96C4, 0x67F2, 0x96C5, 0x67F5,
+	0x96C6, 0x67F6, 0x96C7, 0x67F7, 0x96C8, 0x67F8, 0x96C9, 0x67F9,
+	0x96CA, 0x67FA, 0x96CB, 0x67FB, 0x96CC, 0x67FC, 0x96CD, 0x67FE,
+	0x96CE, 0x6801, 0x96CF, 0x6802, 0x96D0, 0x6803, 0x96D1, 0x6804,
+	0x96D2, 0x6806, 0x96D3, 0x680D, 0x96D4, 0x6810, 0x96D5, 0x6812,
+	0x96D6, 0x6814, 0x96D7, 0x6815, 0x96D8, 0x6818, 0x96D9, 0x6819,
+	0x96DA, 0x681A, 0x96DB, 0x681B, 0x96DC, 0x681C, 0x96DD, 0x681E,
+	0x96DE, 0x681F, 0x96DF, 0x6820, 0x96E0, 0x6822, 0x96E1, 0x6823,
+	0x96E2, 0x6824, 0x96E3, 0x6825, 0x96E4, 0x6826, 0x96E5, 0x6827,
+	0x96E6, 0x6828, 0x96E7, 0x682B, 0x96E8, 0x682C, 0x96E9, 0x682D,
+	0x96EA, 0x682E, 0x96EB, 0x682F, 0x96EC, 0x6830, 0x96ED, 0x6831,
+	0x96EE, 0x6834, 0x96EF, 0x6835, 0x96F0, 0x6836, 0x96F1, 0x683A,
+	0x96F2, 0x683B, 0x96F3, 0x683F, 0x96F4, 0x6847, 0x96F5, 0x684B,
+	0x96F6, 0x684D, 0x96F7, 0x684F, 0x96F8, 0x6852, 0x96F9, 0x6856,
+	0x96FA, 0x6857, 0x96FB, 0x6858, 0x96FC, 0x6859, 0x96FD, 0x685A,
+	0x96FE, 0x685B, 0x9740, 0x685C, 0x9741, 0x685D, 0x9742, 0x685E,
+	0x9743, 0x685F, 0x9744, 0x686A, 0x9745, 0x686C, 0x9746, 0x686D,
+	0x9747, 0x686E, 0x9748, 0x686F, 0x9749, 0x6870, 0x974A, 0x6871,
+	0x974B, 0x6872, 0x974C, 0x6873, 0x974D, 0x6875, 0x974E, 0x6878,
+	0x974F, 0x6879, 0x9750, 0x687A, 0x9751, 0x687B, 0x9752, 0x687C,
+	0x9753, 0x687D, 0x9754, 0x687E, 0x9755, 0x687F, 0x9756, 0x6880,
+	0x9757, 0x6882, 0x9758, 0x6884, 0x9759, 0x6887, 0x975A, 0x6888,
+	0x975B, 0x6889, 0x975C, 0x688A, 0x975D, 0x688B, 0x975E, 0x688C,
+	0x975F, 0x688D, 0x9760, 0x688E, 0x9761, 0x6890, 0x9762, 0x6891,
+	0x9763, 0x6892, 0x9764, 0x6894, 0x9765, 0x6895, 0x9766, 0x6896,
+	0x9767, 0x6898, 0x9768, 0x6899, 0x9769, 0x689A, 0x976A, 0x689B,
+	0x976B, 0x689C, 0x976C, 0x689D, 0x976D, 0x689E, 0x976E, 0x689F,
+	0x976F, 0x68A0, 0x9770, 0x68A1, 0x9771, 0x68A3, 0x9772, 0x68A4,
+	0x9773, 0x68A5, 0x9774, 0x68A9, 0x9775, 0x68AA, 0x9776, 0x68AB,
+	0x9777, 0x68AC, 0x9778, 0x68AE, 0x9779, 0x68B1, 0x977A, 0x68B2,
+	0x977B, 0x68B4, 0x977C, 0x68B6, 0x977D, 0x68B7, 0x977E, 0x68B8,
+	0x9780, 0x68B9, 0x9781, 0x68BA, 0x9782, 0x68BB, 0x9783, 0x68BC,
+	0x9784, 0x68BD, 0x9785, 0x68BE, 0x9786, 0x68BF, 0x9787, 0x68C1,
+	0x9788, 0x68C3, 0x9789, 0x68C4, 0x978A, 0x68C5, 0x978B, 0x68C6,
+	0x978C, 0x68C7, 0x978D, 0x68C8, 0x978E, 0x68CA, 0x978F, 0x68CC,
+	0x9790, 0x68CE, 0x9791, 0x68CF, 0x9792, 0x68D0, 0x9793, 0x68D1,
+	0x9794, 0x68D3, 0x9795, 0x68D4, 0x9796, 0x68D6, 0x9797, 0x68D7,
+	0x9798, 0x68D9, 0x9799, 0x68DB, 0x979A, 0x68DC, 0x979B, 0x68DD,
+	0x979C, 0x68DE, 0x979D, 0x68DF, 0x979E, 0x68E1, 0x979F, 0x68E2,
+	0x97A0, 0x68E4, 0x97A1, 0x68E5, 0x97A2, 0x68E6, 0x97A3, 0x68E7,
+	0x97A4, 0x68E8, 0x97A5, 0x68E9, 0x97A6, 0x68EA, 0x97A7, 0x68EB,
+	0x97A8, 0x68EC, 0x97A9, 0x68ED, 0x97AA, 0x68EF, 0x97AB, 0x68F2,
+	0x97AC, 0x68F3, 0x97AD, 0x68F4, 0x97AE, 0x68F6, 0x97AF, 0x68F7,
+	0x97B0, 0x68F8, 0x97B1, 0x68FB, 0x97B2, 0x68FD, 0x97B3, 0x68FE,
+	0x97B4, 0x68FF, 0x97B5, 0x6900, 0x97B6, 0x6902, 0x97B7, 0x6903,
+	0x97B8, 0x6904, 0x97B9, 0x6906, 0x97BA, 0x6907, 0x97BB, 0x6908,
+	0x97BC, 0x6909, 0x97BD, 0x690A, 0x97BE, 0x690C, 0x97BF, 0x690F,
+	0x97C0, 0x6911, 0x97C1, 0x6913, 0x97C2, 0x6914, 0x97C3, 0x6915,
+	0x97C4, 0x6916, 0x97C5, 0x6917, 0x97C6, 0x6918, 0x97C7, 0x6919,
+	0x97C8, 0x691A, 0x97C9, 0x691B, 0x97CA, 0x691C, 0x97CB, 0x691D,
+	0x97CC, 0x691E, 0x97CD, 0x6921, 0x97CE, 0x6922, 0x97CF, 0x6923,
+	0x97D0, 0x6925, 0x97D1, 0x6926, 0x97D2, 0x6927, 0x97D3, 0x6928,
+	0x97D4, 0x6929, 0x97D5, 0x692A, 0x97D6, 0x692B, 0x97D7, 0x692C,
+	0x97D8, 0x692E, 0x97D9, 0x692F, 0x97DA, 0x6931, 0x97DB, 0x6932,
+	0x97DC, 0x6933, 0x97DD, 0x6935, 0x97DE, 0x6936, 0x97DF, 0x6937,
+	0x97E0, 0x6938, 0x97E1, 0x693A, 0x97E2, 0x693B, 0x97E3, 0x693C,
+	0x97E4, 0x693E, 0x97E5, 0x6940, 0x97E6, 0x6941, 0x97E7, 0x6943,
+	0x97E8, 0x6944, 0x97E9, 0x6945, 0x97EA, 0x6946, 0x97EB, 0x6947,
+	0x97EC, 0x6948, 0x97ED, 0x6949, 0x97EE, 0x694A, 0x97EF, 0x694B,
+	0x97F0, 0x694C, 0x97F1, 0x694D, 0x97F2, 0x694E, 0x97F3, 0x694F,
+	0x97F4, 0x6950, 0x97F5, 0x6951, 0x97F6, 0x6952, 0x97F7, 0x6953,
+	0x97F8, 0x6955, 0x97F9, 0x6956, 0x97FA, 0x6958, 0x97FB, 0x6959,
+	0x97FC, 0x695B, 0x97FD, 0x695C, 0x97FE, 0x695F, 0x9840, 0x6961,
+	0x9841, 0x6962, 0x9842, 0x6964, 0x9843, 0x6965, 0x9844, 0x6967,
+	0x9845, 0x6968, 0x9846, 0x6969, 0x9847, 0x696A, 0x9848, 0x696C,
+	0x9849, 0x696D, 0x984A, 0x696F, 0x984B, 0x6970, 0x984C, 0x6972,
+	0x984D, 0x6973, 0x984E, 0x6974, 0x984F, 0x6975, 0x9850, 0x6976,
+	0x9851, 0x697A, 0x9852, 0x697B, 0x9853, 0x697D, 0x9854, 0x697E,
+	0x9855, 0x697F, 0x9856, 0x6981, 0x9857, 0x6983, 0x9858, 0x6985,
+	0x9859, 0x698A, 0x985A, 0x698B, 0x985B, 0x698C, 0x985C, 0x698E,
+	0x985D, 0x698F, 0x985E, 0x6990, 0x985F, 0x6991, 0x9860, 0x6992,
+	0x9861, 0x6993, 0x9862, 0x6996, 0x9863, 0x6997, 0x9864, 0x6999,
+	0x9865, 0x699A, 0x9866, 0x699D, 0x9867, 0x699E, 0x9868, 0x699F,
+	0x9869, 0x69A0, 0x986A, 0x69A1, 0x986B, 0x69A2, 0x986C, 0x69A3,
+	0x986D, 0x69A4, 0x986E, 0x69A5, 0x986F, 0x69A6, 0x9870, 0x69A9,
+	0x9871, 0x69AA, 0x9872, 0x69AC, 0x9873, 0x69AE, 0x9874, 0x69AF,
+	0x9875, 0x69B0, 0x9876, 0x69B2, 0x9877, 0x69B3, 0x9878, 0x69B5,
+	0x9879, 0x69B6, 0x987A, 0x69B8, 0x987B, 0x69B9, 0x987C, 0x69BA,
+	0x987D, 0x69BC, 0x987E, 0x69BD, 0x9880, 0x69BE, 0x9881, 0x69BF,
+	0x9882, 0x69C0, 0x9883, 0x69C2, 0x9884, 0x69C3, 0x9885, 0x69C4,
+	0x9886, 0x69C5, 0x9887, 0x69C6, 0x9888, 0x69C7, 0x9889, 0x69C8,
+	0x988A, 0x69C9, 0x988B, 0x69CB, 0x988C, 0x69CD, 0x988D, 0x69CF,
+	0x988E, 0x69D1, 0x988F, 0x69D2, 0x9890, 0x69D3, 0x9891, 0x69D5,
+	0x9892, 0x69D6, 0x9893, 0x69D7, 0x9894, 0x69D8, 0x9895, 0x69D9,
+	0x9896, 0x69DA, 0x9897, 0x69DC, 0x9898, 0x69DD, 0x9899, 0x69DE,
+	0x989A, 0x69E1, 0x989B, 0x69E2, 0x989C, 0x69E3, 0x989D, 0x69E4,
+	0x989E, 0x69E5, 0x989F, 0x69E6, 0x98A0, 0x69E7, 0x98A1, 0x69E8,
+	0x98A2, 0x69E9, 0x98A3, 0x69EA, 0x98A4, 0x69EB, 0x98A5, 0x69EC,
+	0x98A6, 0x69EE, 0x98A7, 0x69EF, 0x98A8, 0x69F0, 0x98A9, 0x69F1,
+	0x98AA, 0x69F3, 0x98AB, 0x69F4, 0x98AC, 0x69F5, 0x98AD, 0x69F6,
+	0x98AE, 0x69F7, 0x98AF, 0x69F8, 0x98B0, 0x69F9, 0x98B1, 0x69FA,
+	0x98B2, 0x69FB, 0x98B3, 0x69FC, 0x98B4, 0x69FE, 0x98B5, 0x6A00,
+	0x98B6, 0x6A01, 0x98B7, 0x6A02, 0x98B8, 0x6A03, 0x98B9, 0x6A04,
+	0x98BA, 0x6A05, 0x98BB, 0x6A06, 0x98BC, 0x6A07, 0x98BD, 0x6A08,
+	0x98BE, 0x6A09, 0x98BF, 0x6A0B, 0x98C0, 0x6A0C, 0x98C1, 0x6A0D,
+	0x98C2, 0x6A0E, 0x98C3, 0x6A0F, 0x98C4, 0x6A10, 0x98C5, 0x6A11,
+	0x98C6, 0x6A12, 0x98C7, 0x6A13, 0x98C8, 0x6A14, 0x98C9, 0x6A15,
+	0x98CA, 0x6A16, 0x98CB, 0x6A19, 0x98CC, 0x6A1A, 0x98CD, 0x6A1B,
+	0x98CE, 0x6A1C, 0x98CF, 0x6A1D, 0x98D0, 0x6A1E, 0x98D1, 0x6A20,
+	0x98D2, 0x6A22, 0x98D3, 0x6A23, 0x98D4, 0x6A24, 0x98D5, 0x6A25,
+	0x98D6, 0x6A26, 0x98D7, 0x6A27, 0x98D8, 0x6A29, 0x98D9, 0x6A2B,
+	0x98DA, 0x6A2C, 0x98DB, 0x6A2D, 0x98DC, 0x6A2E, 0x98DD, 0x6A30,
+	0x98DE, 0x6A32, 0x98DF, 0x6A33, 0x98E0, 0x6A34, 0x98E1, 0x6A36,
+	0x98E2, 0x6A37, 0x98E3, 0x6A38, 0x98E4, 0x6A39, 0x98E5, 0x6A3A,
+	0x98E6, 0x6A3B, 0x98E7, 0x6A3C, 0x98E8, 0x6A3F, 0x98E9, 0x6A40,
+	0x98EA, 0x6A41, 0x98EB, 0x6A42, 0x98EC, 0x6A43, 0x98ED, 0x6A45,
+	0x98EE, 0x6A46, 0x98EF, 0x6A48, 0x98F0, 0x6A49, 0x98F1, 0x6A4A,
+	0x98F2, 0x6A4B, 0x98F3, 0x6A4C, 0x98F4, 0x6A4D, 0x98F5, 0x6A4E,
+	0x98F6, 0x6A4F, 0x98F7, 0x6A51, 0x98F8, 0x6A52, 0x98F9, 0x6A53,
+	0x98FA, 0x6A54, 0x98FB, 0x6A55, 0x98FC, 0x6A56, 0x98FD, 0x6A57,
+	0x98FE, 0x6A5A, 0x9940, 0x6A5C, 0x9941, 0x6A5D, 0x9942, 0x6A5E,
+	0x9943, 0x6A5F, 0x9944, 0x6A60, 0x9945, 0x6A62, 0x9946, 0x6A63,
+	0x9947, 0x6A64, 0x9948, 0x6A66, 0x9949, 0x6A67, 0x994A, 0x6A68,
+	0x994B, 0x6A69, 0x994C, 0x6A6A, 0x994D, 0x6A6B, 0x994E, 0x6A6C,
+	0x994F, 0x6A6D, 0x9950, 0x6A6E, 0x9951, 0x6A6F, 0x9952, 0x6A70,
+	0x9953, 0x6A72, 0x9954, 0x6A73, 0x9955, 0x6A74, 0x9956, 0x6A75,
+	0x9957, 0x6A76, 0x9958, 0x6A77, 0x9959, 0x6A78, 0x995A, 0x6A7A,
+	0x995B, 0x6A7B, 0x995C, 0x6A7D, 0x995D, 0x6A7E, 0x995E, 0x6A7F,
+	0x995F, 0x6A81, 0x9960, 0x6A82, 0x9961, 0x6A83, 0x9962, 0x6A85,
+	0x9963, 0x6A86, 0x9964, 0x6A87, 0x9965, 0x6A88, 0x9966, 0x6A89,
+	0x9967, 0x6A8A, 0x9968, 0x6A8B, 0x9969, 0x6A8C, 0x996A, 0x6A8D,
+	0x996B, 0x6A8F, 0x996C, 0x6A92, 0x996D, 0x6A93, 0x996E, 0x6A94,
+	0x996F, 0x6A95, 0x9970, 0x6A96, 0x9971, 0x6A98, 0x9972, 0x6A99,
+	0x9973, 0x6A9A, 0x9974, 0x6A9B, 0x9975, 0x6A9C, 0x9976, 0x6A9D,
+	0x9977, 0x6A9E, 0x9978, 0x6A9F, 0x9979, 0x6AA1, 0x997A, 0x6AA2,
+	0x997B, 0x6AA3, 0x997C, 0x6AA4, 0x997D, 0x6AA5, 0x997E, 0x6AA6,
+	0x9980, 0x6AA7, 0x9981, 0x6AA8, 0x9982, 0x6AAA, 0x9983, 0x6AAD,
+	0x9984, 0x6AAE, 0x9985, 0x6AAF, 0x9986, 0x6AB0, 0x9987, 0x6AB1,
+	0x9988, 0x6AB2, 0x9989, 0x6AB3, 0x998A, 0x6AB4, 0x998B, 0x6AB5,
+	0x998C, 0x6AB6, 0x998D, 0x6AB7, 0x998E, 0x6AB8, 0x998F, 0x6AB9,
+	0x9990, 0x6ABA, 0x9991, 0x6ABB, 0x9992, 0x6ABC, 0x9993, 0x6ABD,
+	0x9994, 0x6ABE, 0x9995, 0x6ABF, 0x9996, 0x6AC0, 0x9997, 0x6AC1,
+	0x9998, 0x6AC2, 0x9999, 0x6AC3, 0x999A, 0x6AC4, 0x999B, 0x6AC5,
+	0x999C, 0x6AC6, 0x999D, 0x6AC7, 0x999E, 0x6AC8, 0x999F, 0x6AC9,
+	0x99A0, 0x6ACA, 0x99A1, 0x6ACB, 0x99A2, 0x6ACC, 0x99A3, 0x6ACD,
+	0x99A4, 0x6ACE, 0x99A5, 0x6ACF, 0x99A6, 0x6AD0, 0x99A7, 0x6AD1,
+	0x99A8, 0x6AD2, 0x99A9, 0x6AD3, 0x99AA, 0x6AD4, 0x99AB, 0x6AD5,
+	0x99AC, 0x6AD6, 0x99AD, 0x6AD7, 0x99AE, 0x6AD8, 0x99AF, 0x6AD9,
+	0x99B0, 0x6ADA, 0x99B1, 0x6ADB, 0x99B2, 0x6ADC, 0x99B3, 0x6ADD,
+	0x99B4, 0x6ADE, 0x99B5, 0x6ADF, 0x99B6, 0x6AE0, 0x99B7, 0x6AE1,
+	0x99B8, 0x6AE2, 0x99B9, 0x6AE3, 0x99BA, 0x6AE4, 0x99BB, 0x6AE5,
+	0x99BC, 0x6AE6, 0x99BD, 0x6AE7, 0x99BE, 0x6AE8, 0x99BF, 0x6AE9,
+	0x99C0, 0x6AEA, 0x99C1, 0x6AEB, 0x99C2, 0x6AEC, 0x99C3, 0x6AED,
+	0x99C4, 0x6AEE, 0x99C5, 0x6AEF, 0x99C6, 0x6AF0, 0x99C7, 0x6AF1,
+	0x99C8, 0x6AF2, 0x99C9, 0x6AF3, 0x99CA, 0x6AF4, 0x99CB, 0x6AF5,
+	0x99CC, 0x6AF6, 0x99CD, 0x6AF7, 0x99CE, 0x6AF8, 0x99CF, 0x6AF9,
+	0x99D0, 0x6AFA, 0x99D1, 0x6AFB, 0x99D2, 0x6AFC, 0x99D3, 0x6AFD,
+	0x99D4, 0x6AFE, 0x99D5, 0x6AFF, 0x99D6, 0x6B00, 0x99D7, 0x6B01,
+	0x99D8, 0x6B02, 0x99D9, 0x6B03, 0x99DA, 0x6B04, 0x99DB, 0x6B05,
+	0x99DC, 0x6B06, 0x99DD, 0x6B07, 0x99DE, 0x6B08, 0x99DF, 0x6B09,
+	0x99E0, 0x6B0A, 0x99E1, 0x6B0B, 0x99E2, 0x6B0C, 0x99E3, 0x6B0D,
+	0x99E4, 0x6B0E, 0x99E5, 0x6B0F, 0x99E6, 0x6B10, 0x99E7, 0x6B11,
+	0x99E8, 0x6B12, 0x99E9, 0x6B13, 0x99EA, 0x6B14, 0x99EB, 0x6B15,
+	0x99EC, 0x6B16, 0x99ED, 0x6B17, 0x99EE, 0x6B18, 0x99EF, 0x6B19,
+	0x99F0, 0x6B1A, 0x99F1, 0x6B1B, 0x99F2, 0x6B1C, 0x99F3, 0x6B1D,
+	0x99F4, 0x6B1E, 0x99F5, 0x6B1F, 0x99F6, 0x6B25, 0x99F7, 0x6B26,
+	0x99F8, 0x6B28, 0x99F9, 0x6B29, 0x99FA, 0x6B2A, 0x99FB, 0x6B2B,
+	0x99FC, 0x6B2C, 0x99FD, 0x6B2D, 0x99FE, 0x6B2E, 0x9A40, 0x6B2F,
+	0x9A41, 0x6B30, 0x9A42, 0x6B31, 0x9A43, 0x6B33, 0x9A44, 0x6B34,
+	0x9A45, 0x6B35, 0x9A46, 0x6B36, 0x9A47, 0x6B38, 0x9A48, 0x6B3B,
+	0x9A49, 0x6B3C, 0x9A4A, 0x6B3D, 0x9A4B, 0x6B3F, 0x9A4C, 0x6B40,
+	0x9A4D, 0x6B41, 0x9A4E, 0x6B42, 0x9A4F, 0x6B44, 0x9A50, 0x6B45,
+	0x9A51, 0x6B48, 0x9A52, 0x6B4A, 0x9A53, 0x6B4B, 0x9A54, 0x6B4D,
+	0x9A55, 0x6B4E, 0x9A56, 0x6B4F, 0x9A57, 0x6B50, 0x9A58, 0x6B51,
+	0x9A59, 0x6B52, 0x9A5A, 0x6B53, 0x9A5B, 0x6B54, 0x9A5C, 0x6B55,
+	0x9A5D, 0x6B56, 0x9A5E, 0x6B57, 0x9A5F, 0x6B58, 0x9A60, 0x6B5A,
+	0x9A61, 0x6B5B, 0x9A62, 0x6B5C, 0x9A63, 0x6B5D, 0x9A64, 0x6B5E,
+	0x9A65, 0x6B5F, 0x9A66, 0x6B60, 0x9A67, 0x6B61, 0x9A68, 0x6B68,
+	0x9A69, 0x6B69, 0x9A6A, 0x6B6B, 0x9A6B, 0x6B6C, 0x9A6C, 0x6B6D,
+	0x9A6D, 0x6B6E, 0x9A6E, 0x6B6F, 0x9A6F, 0x6B70, 0x9A70, 0x6B71,
+	0x9A71, 0x6B72, 0x9A72, 0x6B73, 0x9A73, 0x6B74, 0x9A74, 0x6B75,
+	0x9A75, 0x6B76, 0x9A76, 0x6B77, 0x9A77, 0x6B78, 0x9A78, 0x6B7A,
+	0x9A79, 0x6B7D, 0x9A7A, 0x6B7E, 0x9A7B, 0x6B7F, 0x9A7C, 0x6B80,
+	0x9A7D, 0x6B85, 0x9A7E, 0x6B88, 0x9A80, 0x6B8C, 0x9A81, 0x6B8E,
+	0x9A82, 0x6B8F, 0x9A83, 0x6B90, 0x9A84, 0x6B91, 0x9A85, 0x6B94,
+	0x9A86, 0x6B95, 0x9A87, 0x6B97, 0x9A88, 0x6B98, 0x9A89, 0x6B99,
+	0x9A8A, 0x6B9C, 0x9A8B, 0x6B9D, 0x9A8C, 0x6B9E, 0x9A8D, 0x6B9F,
+	0x9A8E, 0x6BA0, 0x9A8F, 0x6BA2, 0x9A90, 0x6BA3, 0x9A91, 0x6BA4,
+	0x9A92, 0x6BA5, 0x9A93, 0x6BA6, 0x9A94, 0x6BA7, 0x9A95, 0x6BA8,
+	0x9A96, 0x6BA9, 0x9A97, 0x6BAB, 0x9A98, 0x6BAC, 0x9A99, 0x6BAD,
+	0x9A9A, 0x6BAE, 0x9A9B, 0x6BAF, 0x9A9C, 0x6BB0, 0x9A9D, 0x6BB1,
+	0x9A9E, 0x6BB2, 0x9A9F, 0x6BB6, 0x9AA0, 0x6BB8, 0x9AA1, 0x6BB9,
+	0x9AA2, 0x6BBA, 0x9AA3, 0x6BBB, 0x9AA4, 0x6BBC, 0x9AA5, 0x6BBD,
+	0x9AA6, 0x6BBE, 0x9AA7, 0x6BC0, 0x9AA8, 0x6BC3, 0x9AA9, 0x6BC4,
+	0x9AAA, 0x6BC6, 0x9AAB, 0x6BC7, 0x9AAC, 0x6BC8, 0x9AAD, 0x6BC9,
+	0x9AAE, 0x6BCA, 0x9AAF, 0x6BCC, 0x9AB0, 0x6BCE, 0x9AB1, 0x6BD0,
+	0x9AB2, 0x6BD1, 0x9AB3, 0x6BD8, 0x9AB4, 0x6BDA, 0x9AB5, 0x6BDC,
+	0x9AB6, 0x6BDD, 0x9AB7, 0x6BDE, 0x9AB8, 0x6BDF, 0x9AB9, 0x6BE0,
+	0x9ABA, 0x6BE2, 0x9ABB, 0x6BE3, 0x9ABC, 0x6BE4, 0x9ABD, 0x6BE5,
+	0x9ABE, 0x6BE6, 0x9ABF, 0x6BE7, 0x9AC0, 0x6BE8, 0x9AC1, 0x6BE9,
+	0x9AC2, 0x6BEC, 0x9AC3, 0x6BED, 0x9AC4, 0x6BEE, 0x9AC5, 0x6BF0,
+	0x9AC6, 0x6BF1, 0x9AC7, 0x6BF2, 0x9AC8, 0x6BF4, 0x9AC9, 0x6BF6,
+	0x9ACA, 0x6BF7, 0x9ACB, 0x6BF8, 0x9ACC, 0x6BFA, 0x9ACD, 0x6BFB,
+	0x9ACE, 0x6BFC, 0x9ACF, 0x6BFE, 0x9AD0, 0x6BFF, 0x9AD1, 0x6C00,
+	0x9AD2, 0x6C01, 0x9AD3, 0x6C02, 0x9AD4, 0x6C03, 0x9AD5, 0x6C04,
+	0x9AD6, 0x6C08, 0x9AD7, 0x6C09, 0x9AD8, 0x6C0A, 0x9AD9, 0x6C0B,
+	0x9ADA, 0x6C0C, 0x9ADB, 0x6C0E, 0x9ADC, 0x6C12, 0x9ADD, 0x6C17,
+	0x9ADE, 0x6C1C, 0x9ADF, 0x6C1D, 0x9AE0, 0x6C1E, 0x9AE1, 0x6C20,
+	0x9AE2, 0x6C23, 0x9AE3, 0x6C25, 0x9AE4, 0x6C2B, 0x9AE5, 0x6C2C,
+	0x9AE6, 0x6C2D, 0x9AE7, 0x6C31, 0x9AE8, 0x6C33, 0x9AE9, 0x6C36,
+	0x9AEA, 0x6C37, 0x9AEB, 0x6C39, 0x9AEC, 0x6C3A, 0x9AED, 0x6C3B,
+	0x9AEE, 0x6C3C, 0x9AEF, 0x6C3E, 0x9AF0, 0x6C3F, 0x9AF1, 0x6C43,
+	0x9AF2, 0x6C44, 0x9AF3, 0x6C45, 0x9AF4, 0x6C48, 0x9AF5, 0x6C4B,
+	0x9AF6, 0x6C4C, 0x9AF7, 0x6C4D, 0x9AF8, 0x6C4E, 0x9AF9, 0x6C4F,
+	0x9AFA, 0x6C51, 0x9AFB, 0x6C52, 0x9AFC, 0x6C53, 0x9AFD, 0x6C56,
+	0x9AFE, 0x6C58, 0x9B40, 0x6C59, 0x9B41, 0x6C5A, 0x9B42, 0x6C62,
+	0x9B43, 0x6C63, 0x9B44, 0x6C65, 0x9B45, 0x6C66, 0x9B46, 0x6C67,
+	0x9B47, 0x6C6B, 0x9B48, 0x6C6C, 0x9B49, 0x6C6D, 0x9B4A, 0x6C6E,
+	0x9B4B, 0x6C6F, 0x9B4C, 0x6C71, 0x9B4D, 0x6C73, 0x9B4E, 0x6C75,
+	0x9B4F, 0x6C77, 0x9B50, 0x6C78, 0x9B51, 0x6C7A, 0x9B52, 0x6C7B,
+	0x9B53, 0x6C7C, 0x9B54, 0x6C7F, 0x9B55, 0x6C80, 0x9B56, 0x6C84,
+	0x9B57, 0x6C87, 0x9B58, 0x6C8A, 0x9B59, 0x6C8B, 0x9B5A, 0x6C8D,
+	0x9B5B, 0x6C8E, 0x9B5C, 0x6C91, 0x9B5D, 0x6C92, 0x9B5E, 0x6C95,
+	0x9B5F, 0x6C96, 0x9B60, 0x6C97, 0x9B61, 0x6C98, 0x9B62, 0x6C9A,
+	0x9B63, 0x6C9C, 0x9B64, 0x6C9D, 0x9B65, 0x6C9E, 0x9B66, 0x6CA0,
+	0x9B67, 0x6CA2, 0x9B68, 0x6CA8, 0x9B69, 0x6CAC, 0x9B6A, 0x6CAF,
+	0x9B6B, 0x6CB0, 0x9B6C, 0x6CB4, 0x9B6D, 0x6CB5, 0x9B6E, 0x6CB6,
+	0x9B6F, 0x6CB7, 0x9B70, 0x6CBA, 0x9B71, 0x6CC0, 0x9B72, 0x6CC1,
+	0x9B73, 0x6CC2, 0x9B74, 0x6CC3, 0x9B75, 0x6CC6, 0x9B76, 0x6CC7,
+	0x9B77, 0x6CC8, 0x9B78, 0x6CCB, 0x9B79, 0x6CCD, 0x9B7A, 0x6CCE,
+	0x9B7B, 0x6CCF, 0x9B7C, 0x6CD1, 0x9B7D, 0x6CD2, 0x9B7E, 0x6CD8,
+	0x9B80, 0x6CD9, 0x9B81, 0x6CDA, 0x9B82, 0x6CDC, 0x9B83, 0x6CDD,
+	0x9B84, 0x6CDF, 0x9B85, 0x6CE4, 0x9B86, 0x6CE6, 0x9B87, 0x6CE7,
+	0x9B88, 0x6CE9, 0x9B89, 0x6CEC, 0x9B8A, 0x6CED, 0x9B8B, 0x6CF2,
+	0x9B8C, 0x6CF4, 0x9B8D, 0x6CF9, 0x9B8E, 0x6CFF, 0x9B8F, 0x6D00,
+	0x9B90, 0x6D02, 0x9B91, 0x6D03, 0x9B92, 0x6D05, 0x9B93, 0x6D06,
+	0x9B94, 0x6D08, 0x9B95, 0x6D09, 0x9B96, 0x6D0A, 0x9B97, 0x6D0D,
+	0x9B98, 0x6D0F, 0x9B99, 0x6D10, 0x9B9A, 0x6D11, 0x9B9B, 0x6D13,
+	0x9B9C, 0x6D14, 0x9B9D, 0x6D15, 0x9B9E, 0x6D16, 0x9B9F, 0x6D18,
+	0x9BA0, 0x6D1C, 0x9BA1, 0x6D1D, 0x9BA2, 0x6D1F, 0x9BA3, 0x6D20,
+	0x9BA4, 0x6D21, 0x9BA5, 0x6D22, 0x9BA6, 0x6D23, 0x9BA7, 0x6D24,
+	0x9BA8, 0x6D26, 0x9BA9, 0x6D28, 0x9BAA, 0x6D29, 0x9BAB, 0x6D2C,
+	0x9BAC, 0x6D2D, 0x9BAD, 0x6D2F, 0x9BAE, 0x6D30, 0x9BAF, 0x6D34,
+	0x9BB0, 0x6D36, 0x9BB1, 0x6D37, 0x9BB2, 0x6D38, 0x9BB3, 0x6D3A,
+	0x9BB4, 0x6D3F, 0x9BB5, 0x6D40, 0x9BB6, 0x6D42, 0x9BB7, 0x6D44,
+	0x9BB8, 0x6D49, 0x9BB9, 0x6D4C, 0x9BBA, 0x6D50, 0x9BBB, 0x6D55,
+	0x9BBC, 0x6D56, 0x9BBD, 0x6D57, 0x9BBE, 0x6D58, 0x9BBF, 0x6D5B,
+	0x9BC0, 0x6D5D, 0x9BC1, 0x6D5F, 0x9BC2, 0x6D61, 0x9BC3, 0x6D62,
+	0x9BC4, 0x6D64, 0x9BC5, 0x6D65, 0x9BC6, 0x6D67, 0x9BC7, 0x6D68,
+	0x9BC8, 0x6D6B, 0x9BC9, 0x6D6C, 0x9BCA, 0x6D6D, 0x9BCB, 0x6D70,
+	0x9BCC, 0x6D71, 0x9BCD, 0x6D72, 0x9BCE, 0x6D73, 0x9BCF, 0x6D75,
+	0x9BD0, 0x6D76, 0x9BD1, 0x6D79, 0x9BD2, 0x6D7A, 0x9BD3, 0x6D7B,
+	0x9BD4, 0x6D7D, 0x9BD5, 0x6D7E, 0x9BD6, 0x6D7F, 0x9BD7, 0x6D80,
+	0x9BD8, 0x6D81, 0x9BD9, 0x6D83, 0x9BDA, 0x6D84, 0x9BDB, 0x6D86,
+	0x9BDC, 0x6D87, 0x9BDD, 0x6D8A, 0x9BDE, 0x6D8B, 0x9BDF, 0x6D8D,
+	0x9BE0, 0x6D8F, 0x9BE1, 0x6D90, 0x9BE2, 0x6D92, 0x9BE3, 0x6D96,
+	0x9BE4, 0x6D97, 0x9BE5, 0x6D98, 0x9BE6, 0x6D99, 0x9BE7, 0x6D9A,
+	0x9BE8, 0x6D9C, 0x9BE9, 0x6DA2, 0x9BEA, 0x6DA5, 0x9BEB, 0x6DAC,
+	0x9BEC, 0x6DAD, 0x9BED, 0x6DB0, 0x9BEE, 0x6DB1, 0x9BEF, 0x6DB3,
+	0x9BF0, 0x6DB4, 0x9BF1, 0x6DB6, 0x9BF2, 0x6DB7, 0x9BF3, 0x6DB9,
+	0x9BF4, 0x6DBA, 0x9BF5, 0x6DBB, 0x9BF6, 0x6DBC, 0x9BF7, 0x6DBD,
+	0x9BF8, 0x6DBE, 0x9BF9, 0x6DC1, 0x9BFA, 0x6DC2, 0x9BFB, 0x6DC3,
+	0x9BFC, 0x6DC8, 0x9BFD, 0x6DC9, 0x9BFE, 0x6DCA, 0x9C40, 0x6DCD,
+	0x9C41, 0x6DCE, 0x9C42, 0x6DCF, 0x9C43, 0x6DD0, 0x9C44, 0x6DD2,
+	0x9C45, 0x6DD3, 0x9C46, 0x6DD4, 0x9C47, 0x6DD5, 0x9C48, 0x6DD7,
+	0x9C49, 0x6DDA, 0x9C4A, 0x6DDB, 0x9C4B, 0x6DDC, 0x9C4C, 0x6DDF,
+	0x9C4D, 0x6DE2, 0x9C4E, 0x6DE3, 0x9C4F, 0x6DE5, 0x9C50, 0x6DE7,
+	0x9C51, 0x6DE8, 0x9C52, 0x6DE9, 0x9C53, 0x6DEA, 0x9C54, 0x6DED,
+	0x9C55, 0x6DEF, 0x9C56, 0x6DF0, 0x9C57, 0x6DF2, 0x9C58, 0x6DF4,
+	0x9C59, 0x6DF5, 0x9C5A, 0x6DF6, 0x9C5B, 0x6DF8, 0x9C5C, 0x6DFA,
+	0x9C5D, 0x6DFD, 0x9C5E, 0x6DFE, 0x9C5F, 0x6DFF, 0x9C60, 0x6E00,
+	0x9C61, 0x6E01, 0x9C62, 0x6E02, 0x9C63, 0x6E03, 0x9C64, 0x6E04,
+	0x9C65, 0x6E06, 0x9C66, 0x6E07, 0x9C67, 0x6E08, 0x9C68, 0x6E09,
+	0x9C69, 0x6E0B, 0x9C6A, 0x6E0F, 0x9C6B, 0x6E12, 0x9C6C, 0x6E13,
+	0x9C6D, 0x6E15, 0x9C6E, 0x6E18, 0x9C6F, 0x6E19, 0x9C70, 0x6E1B,
+	0x9C71, 0x6E1C, 0x9C72, 0x6E1E, 0x9C73, 0x6E1F, 0x9C74, 0x6E22,
+	0x9C75, 0x6E26, 0x9C76, 0x6E27, 0x9C77, 0x6E28, 0x9C78, 0x6E2A,
+	0x9C79, 0x6E2C, 0x9C7A, 0x6E2E, 0x9C7B, 0x6E30, 0x9C7C, 0x6E31,
+	0x9C7D, 0x6E33, 0x9C7E, 0x6E35, 0x9C80, 0x6E36, 0x9C81, 0x6E37,
+	0x9C82, 0x6E39, 0x9C83, 0x6E3B, 0x9C84, 0x6E3C, 0x9C85, 0x6E3D,
+	0x9C86, 0x6E3E, 0x9C87, 0x6E3F, 0x9C88, 0x6E40, 0x9C89, 0x6E41,
+	0x9C8A, 0x6E42, 0x9C8B, 0x6E45, 0x9C8C, 0x6E46, 0x9C8D, 0x6E47,
+	0x9C8E, 0x6E48, 0x9C8F, 0x6E49, 0x9C90, 0x6E4A, 0x9C91, 0x6E4B,
+	0x9C92, 0x6E4C, 0x9C93, 0x6E4F, 0x9C94, 0x6E50, 0x9C95, 0x6E51,
+	0x9C96, 0x6E52, 0x9C97, 0x6E55, 0x9C98, 0x6E57, 0x9C99, 0x6E59,
+	0x9C9A, 0x6E5A, 0x9C9B, 0x6E5C, 0x9C9C, 0x6E5D, 0x9C9D, 0x6E5E,
+	0x9C9E, 0x6E60, 0x9C9F, 0x6E61, 0x9CA0, 0x6E62, 0x9CA1, 0x6E63,
+	0x9CA2, 0x6E64, 0x9CA3, 0x6E65, 0x9CA4, 0x6E66, 0x9CA5, 0x6E67,
+	0x9CA6, 0x6E68, 0x9CA7, 0x6E69, 0x9CA8, 0x6E6A, 0x9CA9, 0x6E6C,
+	0x9CAA, 0x6E6D, 0x9CAB, 0x6E6F, 0x9CAC, 0x6E70, 0x9CAD, 0x6E71,
+	0x9CAE, 0x6E72, 0x9CAF, 0x6E73, 0x9CB0, 0x6E74, 0x9CB1, 0x6E75,
+	0x9CB2, 0x6E76, 0x9CB3, 0x6E77, 0x9CB4, 0x6E78, 0x9CB5, 0x6E79,
+	0x9CB6, 0x6E7A, 0x9CB7, 0x6E7B, 0x9CB8, 0x6E7C, 0x9CB9, 0x6E7D,
+	0x9CBA, 0x6E80, 0x9CBB, 0x6E81, 0x9CBC, 0x6E82, 0x9CBD, 0x6E84,
+	0x9CBE, 0x6E87, 0x9CBF, 0x6E88, 0x9CC0, 0x6E8A, 0x9CC1, 0x6E8B,
+	0x9CC2, 0x6E8C, 0x9CC3, 0x6E8D, 0x9CC4, 0x6E8E, 0x9CC5, 0x6E91,
+	0x9CC6, 0x6E92, 0x9CC7, 0x6E93, 0x9CC8, 0x6E94, 0x9CC9, 0x6E95,
+	0x9CCA, 0x6E96, 0x9CCB, 0x6E97, 0x9CCC, 0x6E99, 0x9CCD, 0x6E9A,
+	0x9CCE, 0x6E9B, 0x9CCF, 0x6E9D, 0x9CD0, 0x6E9E, 0x9CD1, 0x6EA0,
+	0x9CD2, 0x6EA1, 0x9CD3, 0x6EA3, 0x9CD4, 0x6EA4, 0x9CD5, 0x6EA6,
+	0x9CD6, 0x6EA8, 0x9CD7, 0x6EA9, 0x9CD8, 0x6EAB, 0x9CD9, 0x6EAC,
+	0x9CDA, 0x6EAD, 0x9CDB, 0x6EAE, 0x9CDC, 0x6EB0, 0x9CDD, 0x6EB3,
+	0x9CDE, 0x6EB5, 0x9CDF, 0x6EB8, 0x9CE0, 0x6EB9, 0x9CE1, 0x6EBC,
+	0x9CE2, 0x6EBE, 0x9CE3, 0x6EBF, 0x9CE4, 0x6EC0, 0x9CE5, 0x6EC3,
+	0x9CE6, 0x6EC4, 0x9CE7, 0x6EC5, 0x9CE8, 0x6EC6, 0x9CE9, 0x6EC8,
+	0x9CEA, 0x6EC9, 0x9CEB, 0x6ECA, 0x9CEC, 0x6ECC, 0x9CED, 0x6ECD,
+	0x9CEE, 0x6ECE, 0x9CEF, 0x6ED0, 0x9CF0, 0x6ED2, 0x9CF1, 0x6ED6,
+	0x9CF2, 0x6ED8, 0x9CF3, 0x6ED9, 0x9CF4, 0x6EDB, 0x9CF5, 0x6EDC,
+	0x9CF6, 0x6EDD, 0x9CF7, 0x6EE3, 0x9CF8, 0x6EE7, 0x9CF9, 0x6EEA,
+	0x9CFA, 0x6EEB, 0x9CFB, 0x6EEC, 0x9CFC, 0x6EED, 0x9CFD, 0x6EEE,
+	0x9CFE, 0x6EEF, 0x9D40, 0x6EF0, 0x9D41, 0x6EF1, 0x9D42, 0x6EF2,
+	0x9D43, 0x6EF3, 0x9D44, 0x6EF5, 0x9D45, 0x6EF6, 0x9D46, 0x6EF7,
+	0x9D47, 0x6EF8, 0x9D48, 0x6EFA, 0x9D49, 0x6EFB, 0x9D4A, 0x6EFC,
+	0x9D4B, 0x6EFD, 0x9D4C, 0x6EFE, 0x9D4D, 0x6EFF, 0x9D4E, 0x6F00,
+	0x9D4F, 0x6F01, 0x9D50, 0x6F03, 0x9D51, 0x6F04, 0x9D52, 0x6F05,
+	0x9D53, 0x6F07, 0x9D54, 0x6F08, 0x9D55, 0x6F0A, 0x9D56, 0x6F0B,
+	0x9D57, 0x6F0C, 0x9D58, 0x6F0D, 0x9D59, 0x6F0E, 0x9D5A, 0x6F10,
+	0x9D5B, 0x6F11, 0x9D5C, 0x6F12, 0x9D5D, 0x6F16, 0x9D5E, 0x6F17,
+	0x9D5F, 0x6F18, 0x9D60, 0x6F19, 0x9D61, 0x6F1A, 0x9D62, 0x6F1B,
+	0x9D63, 0x6F1C, 0x9D64, 0x6F1D, 0x9D65, 0x6F1E, 0x9D66, 0x6F1F,
+	0x9D67, 0x6F21, 0x9D68, 0x6F22, 0x9D69, 0x6F23, 0x9D6A, 0x6F25,
+	0x9D6B, 0x6F26, 0x9D6C, 0x6F27, 0x9D6D, 0x6F28, 0x9D6E, 0x6F2C,
+	0x9D6F, 0x6F2E, 0x9D70, 0x6F30, 0x9D71, 0x6F32, 0x9D72, 0x6F34,
+	0x9D73, 0x6F35, 0x9D74, 0x6F37, 0x9D75, 0x6F38, 0x9D76, 0x6F39,
+	0x9D77, 0x6F3A, 0x9D78, 0x6F3B, 0x9D79, 0x6F3C, 0x9D7A, 0x6F3D,
+	0x9D7B, 0x6F3F, 0x9D7C, 0x6F40, 0x9D7D, 0x6F41, 0x9D7E, 0x6F42,
+	0x9D80, 0x6F43, 0x9D81, 0x6F44, 0x9D82, 0x6F45, 0x9D83, 0x6F48,
+	0x9D84, 0x6F49, 0x9D85, 0x6F4A, 0x9D86, 0x6F4C, 0x9D87, 0x6F4E,
+	0x9D88, 0x6F4F, 0x9D89, 0x6F50, 0x9D8A, 0x6F51, 0x9D8B, 0x6F52,
+	0x9D8C, 0x6F53, 0x9D8D, 0x6F54, 0x9D8E, 0x6F55, 0x9D8F, 0x6F56,
+	0x9D90, 0x6F57, 0x9D91, 0x6F59, 0x9D92, 0x6F5A, 0x9D93, 0x6F5B,
+	0x9D94, 0x6F5D, 0x9D95, 0x6F5F, 0x9D96, 0x6F60, 0x9D97, 0x6F61,
+	0x9D98, 0x6F63, 0x9D99, 0x6F64, 0x9D9A, 0x6F65, 0x9D9B, 0x6F67,
+	0x9D9C, 0x6F68, 0x9D9D, 0x6F69, 0x9D9E, 0x6F6A, 0x9D9F, 0x6F6B,
+	0x9DA0, 0x6F6C, 0x9DA1, 0x6F6F, 0x9DA2, 0x6F70, 0x9DA3, 0x6F71,
+	0x9DA4, 0x6F73, 0x9DA5, 0x6F75, 0x9DA6, 0x6F76, 0x9DA7, 0x6F77,
+	0x9DA8, 0x6F79, 0x9DA9, 0x6F7B, 0x9DAA, 0x6F7D, 0x9DAB, 0x6F7E,
+	0x9DAC, 0x6F7F, 0x9DAD, 0x6F80, 0x9DAE, 0x6F81, 0x9DAF, 0x6F82,
+	0x9DB0, 0x6F83, 0x9DB1, 0x6F85, 0x9DB2, 0x6F86, 0x9DB3, 0x6F87,
+	0x9DB4, 0x6F8A, 0x9DB5, 0x6F8B, 0x9DB6, 0x6F8F, 0x9DB7, 0x6F90,
+	0x9DB8, 0x6F91, 0x9DB9, 0x6F92, 0x9DBA, 0x6F93, 0x9DBB, 0x6F94,
+	0x9DBC, 0x6F95, 0x9DBD, 0x6F96, 0x9DBE, 0x6F97, 0x9DBF, 0x6F98,
+	0x9DC0, 0x6F99, 0x9DC1, 0x6F9A, 0x9DC2, 0x6F9B, 0x9DC3, 0x6F9D,
+	0x9DC4, 0x6F9E, 0x9DC5, 0x6F9F, 0x9DC6, 0x6FA0, 0x9DC7, 0x6FA2,
+	0x9DC8, 0x6FA3, 0x9DC9, 0x6FA4, 0x9DCA, 0x6FA5, 0x9DCB, 0x6FA6,
+	0x9DCC, 0x6FA8, 0x9DCD, 0x6FA9, 0x9DCE, 0x6FAA, 0x9DCF, 0x6FAB,
+	0x9DD0, 0x6FAC, 0x9DD1, 0x6FAD, 0x9DD2, 0x6FAE, 0x9DD3, 0x6FAF,
+	0x9DD4, 0x6FB0, 0x9DD5, 0x6FB1, 0x9DD6, 0x6FB2, 0x9DD7, 0x6FB4,
+	0x9DD8, 0x6FB5, 0x9DD9, 0x6FB7, 0x9DDA, 0x6FB8, 0x9DDB, 0x6FBA,
+	0x9DDC, 0x6FBB, 0x9DDD, 0x6FBC, 0x9DDE, 0x6FBD, 0x9DDF, 0x6FBE,
+	0x9DE0, 0x6FBF, 0x9DE1, 0x6FC1, 0x9DE2, 0x6FC3, 0x9DE3, 0x6FC4,
+	0x9DE4, 0x6FC5, 0x9DE5, 0x6FC6, 0x9DE6, 0x6FC7, 0x9DE7, 0x6FC8,
+	0x9DE8, 0x6FCA, 0x9DE9, 0x6FCB, 0x9DEA, 0x6FCC, 0x9DEB, 0x6FCD,
+	0x9DEC, 0x6FCE, 0x9DED, 0x6FCF, 0x9DEE, 0x6FD0, 0x9DEF, 0x6FD3,
+	0x9DF0, 0x6FD4, 0x9DF1, 0x6FD5, 0x9DF2, 0x6FD6, 0x9DF3, 0x6FD7,
+	0x9DF4, 0x6FD8, 0x9DF5, 0x6FD9, 0x9DF6, 0x6FDA, 0x9DF7, 0x6FDB,
+	0x9DF8, 0x6FDC, 0x9DF9, 0x6FDD, 0x9DFA, 0x6FDF, 0x9DFB, 0x6FE2,
+	0x9DFC, 0x6FE3, 0x9DFD, 0x6FE4, 0x9DFE, 0x6FE5, 0x9E40, 0x6FE6,
+	0x9E41, 0x6FE7, 0x9E42, 0x6FE8, 0x9E43, 0x6FE9, 0x9E44, 0x6FEA,
+	0x9E45, 0x6FEB, 0x9E46, 0x6FEC, 0x9E47, 0x6FED, 0x9E48, 0x6FF0,
+	0x9E49, 0x6FF1, 0x9E4A, 0x6FF2, 0x9E4B, 0x6FF3, 0x9E4C, 0x6FF4,
+	0x9E4D, 0x6FF5, 0x9E4E, 0x6FF6, 0x9E4F, 0x6FF7, 0x9E50, 0x6FF8,
+	0x9E51, 0x6FF9, 0x9E52, 0x6FFA, 0x9E53, 0x6FFB, 0x9E54, 0x6FFC,
+	0x9E55, 0x6FFD, 0x9E56, 0x6FFE, 0x9E57, 0x6FFF, 0x9E58, 0x7000,
+	0x9E59, 0x7001, 0x9E5A, 0x7002, 0x9E5B, 0x7003, 0x9E5C, 0x7004,
+	0x9E5D, 0x7005, 0x9E5E, 0x7006, 0x9E5F, 0x7007, 0x9E60, 0x7008,
+	0x9E61, 0x7009, 0x9E62, 0x700A, 0x9E63, 0x700B, 0x9E64, 0x700C,
+	0x9E65, 0x700D, 0x9E66, 0x700E, 0x9E67, 0x700F, 0x9E68, 0x7010,
+	0x9E69, 0x7012, 0x9E6A, 0x7013, 0x9E6B, 0x7014, 0x9E6C, 0x7015,
+	0x9E6D, 0x7016, 0x9E6E, 0x7017, 0x9E6F, 0x7018, 0x9E70, 0x7019,
+	0x9E71, 0x701C, 0x9E72, 0x701D, 0x9E73, 0x701E, 0x9E74, 0x701F,
+	0x9E75, 0x7020, 0x9E76, 0x7021, 0x9E77, 0x7022, 0x9E78, 0x7024,
+	0x9E79, 0x7025, 0x9E7A, 0x7026, 0x9E7B, 0x7027, 0x9E7C, 0x7028,
+	0x9E7D, 0x7029, 0x9E7E, 0x702A, 0x9E80, 0x702B, 0x9E81, 0x702C,
+	0x9E82, 0x702D, 0x9E83, 0x702E, 0x9E84, 0x702F, 0x9E85, 0x7030,
+	0x9E86, 0x7031, 0x9E87, 0x7032, 0x9E88, 0x7033, 0x9E89, 0x7034,
+	0x9E8A, 0x7036, 0x9E8B, 0x7037, 0x9E8C, 0x7038, 0x9E8D, 0x703A,
+	0x9E8E, 0x703B, 0x9E8F, 0x703C, 0x9E90, 0x703D, 0x9E91, 0x703E,
+	0x9E92, 0x703F, 0x9E93, 0x7040, 0x9E94, 0x7041, 0x9E95, 0x7042,
+	0x9E96, 0x7043, 0x9E97, 0x7044, 0x9E98, 0x7045, 0x9E99, 0x7046,
+	0x9E9A, 0x7047, 0x9E9B, 0x7048, 0x9E9C, 0x7049, 0x9E9D, 0x704A,
+	0x9E9E, 0x704B, 0x9E9F, 0x704D, 0x9EA0, 0x704E, 0x9EA1, 0x7050,
+	0x9EA2, 0x7051, 0x9EA3, 0x7052, 0x9EA4, 0x7053, 0x9EA5, 0x7054,
+	0x9EA6, 0x7055, 0x9EA7, 0x7056, 0x9EA8, 0x7057, 0x9EA9, 0x7058,
+	0x9EAA, 0x7059, 0x9EAB, 0x705A, 0x9EAC, 0x705B, 0x9EAD, 0x705C,
+	0x9EAE, 0x705D, 0x9EAF, 0x705F, 0x9EB0, 0x7060, 0x9EB1, 0x7061,
+	0x9EB2, 0x7062, 0x9EB3, 0x7063, 0x9EB4, 0x7064, 0x9EB5, 0x7065,
+	0x9EB6, 0x7066, 0x9EB7, 0x7067, 0x9EB8, 0x7068, 0x9EB9, 0x7069,
+	0x9EBA, 0x706A, 0x9EBB, 0x706E, 0x9EBC, 0x7071, 0x9EBD, 0x7072,
+	0x9EBE, 0x7073, 0x9EBF, 0x7074, 0x9EC0, 0x7077, 0x9EC1, 0x7079,
+	0x9EC2, 0x707A, 0x9EC3, 0x707B, 0x9EC4, 0x707D, 0x9EC5, 0x7081,
+	0x9EC6, 0x7082, 0x9EC7, 0x7083, 0x9EC8, 0x7084, 0x9EC9, 0x7086,
+	0x9ECA, 0x7087, 0x9ECB, 0x7088, 0x9ECC, 0x708B, 0x9ECD, 0x708C,
+	0x9ECE, 0x708D, 0x9ECF, 0x708F, 0x9ED0, 0x7090, 0x9ED1, 0x7091,
+	0x9ED2, 0x7093, 0x9ED3, 0x7097, 0x9ED4, 0x7098, 0x9ED5, 0x709A,
+	0x9ED6, 0x709B, 0x9ED7, 0x709E, 0x9ED8, 0x709F, 0x9ED9, 0x70A0,
+	0x9EDA, 0x70A1, 0x9EDB, 0x70A2, 0x9EDC, 0x70A3, 0x9EDD, 0x70A4,
+	0x9EDE, 0x70A5, 0x9EDF, 0x70A6, 0x9EE0, 0x70A7, 0x9EE1, 0x70A8,
+	0x9EE2, 0x70A9, 0x9EE3, 0x70AA, 0x9EE4, 0x70B0, 0x9EE5, 0x70B2,
+	0x9EE6, 0x70B4, 0x9EE7, 0x70B5, 0x9EE8, 0x70B6, 0x9EE9, 0x70BA,
+	0x9EEA, 0x70BE, 0x9EEB, 0x70BF, 0x9EEC, 0x70C4, 0x9EED, 0x70C5,
+	0x9EEE, 0x70C6, 0x9EEF, 0x70C7, 0x9EF0, 0x70C9, 0x9EF1, 0x70CB,
+	0x9EF2, 0x70CC, 0x9EF3, 0x70CD, 0x9EF4, 0x70CE, 0x9EF5, 0x70CF,
+	0x9EF6, 0x70D0, 0x9EF7, 0x70D1, 0x9EF8, 0x70D2, 0x9EF9, 0x70D3,
+	0x9EFA, 0x70D4, 0x9EFB, 0x70D5, 0x9EFC, 0x70D6, 0x9EFD, 0x70D7,
+	0x9EFE, 0x70DA, 0x9F40, 0x70DC, 0x9F41, 0x70DD, 0x9F42, 0x70DE,
+	0x9F43, 0x70E0, 0x9F44, 0x70E1, 0x9F45, 0x70E2, 0x9F46, 0x70E3,
+	0x9F47, 0x70E5, 0x9F48, 0x70EA, 0x9F49, 0x70EE, 0x9F4A, 0x70F0,
+	0x9F4B, 0x70F1, 0x9F4C, 0x70F2, 0x9F4D, 0x70F3, 0x9F4E, 0x70F4,
+	0x9F4F, 0x70F5, 0x9F50, 0x70F6, 0x9F51, 0x70F8, 0x9F52, 0x70FA,
+	0x9F53, 0x70FB, 0x9F54, 0x70FC, 0x9F55, 0x70FE, 0x9F56, 0x70FF,
+	0x9F57, 0x7100, 0x9F58, 0x7101, 0x9F59, 0x7102, 0x9F5A, 0x7103,
+	0x9F5B, 0x7104, 0x9F5C, 0x7105, 0x9F5D, 0x7106, 0x9F5E, 0x7107,
+	0x9F5F, 0x7108, 0x9F60, 0x710B, 0x9F61, 0x710C, 0x9F62, 0x710D,
+	0x9F63, 0x710E, 0x9F64, 0x710F, 0x9F65, 0x7111, 0x9F66, 0x7112,
+	0x9F67, 0x7114, 0x9F68, 0x7117, 0x9F69, 0x711B, 0x9F6A, 0x711C,
+	0x9F6B, 0x711D, 0x9F6C, 0x711E, 0x9F6D, 0x711F, 0x9F6E, 0x7120,
+	0x9F6F, 0x7121, 0x9F70, 0x7122, 0x9F71, 0x7123, 0x9F72, 0x7124,
+	0x9F73, 0x7125, 0x9F74, 0x7127, 0x9F75, 0x7128, 0x9F76, 0x7129,
+	0x9F77, 0x712A, 0x9F78, 0x712B, 0x9F79, 0x712C, 0x9F7A, 0x712D,
+	0x9F7B, 0x712E, 0x9F7C, 0x7132, 0x9F7D, 0x7133, 0x9F7E, 0x7134,
+	0x9F80, 0x7135, 0x9F81, 0x7137, 0x9F82, 0x7138, 0x9F83, 0x7139,
+	0x9F84, 0x713A, 0x9F85, 0x713B, 0x9F86, 0x713C, 0x9F87, 0x713D,
+	0x9F88, 0x713E, 0x9F89, 0x713F, 0x9F8A, 0x7140, 0x9F8B, 0x7141,
+	0x9F8C, 0x7142, 0x9F8D, 0x7143, 0x9F8E, 0x7144, 0x9F8F, 0x7146,
+	0x9F90, 0x7147, 0x9F91, 0x7148, 0x9F92, 0x7149, 0x9F93, 0x714B,
+	0x9F94, 0x714D, 0x9F95, 0x714F, 0x9F96, 0x7150, 0x9F97, 0x7151,
+	0x9F98, 0x7152, 0x9F99, 0x7153, 0x9F9A, 0x7154, 0x9F9B, 0x7155,
+	0x9F9C, 0x7156, 0x9F9D, 0x7157, 0x9F9E, 0x7158, 0x9F9F, 0x7159,
+	0x9FA0, 0x715A, 0x9FA1, 0x715B, 0x9FA2, 0x715D, 0x9FA3, 0x715F,
+	0x9FA4, 0x7160, 0x9FA5, 0x7161, 0x9FA6, 0x7162, 0x9FA7, 0x7163,
+	0x9FA8, 0x7165, 0x9FA9, 0x7169, 0x9FAA, 0x716A, 0x9FAB, 0x716B,
+	0x9FAC, 0x716C, 0x9FAD, 0x716D, 0x9FAE, 0x716F, 0x9FAF, 0x7170,
+	0x9FB0, 0x7171, 0x9FB1, 0x7174, 0x9FB2, 0x7175, 0x9FB3, 0x7176,
+	0x9FB4, 0x7177, 0x9FB5, 0x7179, 0x9FB6, 0x717B, 0x9FB7, 0x717C,
+	0x9FB8, 0x717E, 0x9FB9, 0x717F, 0x9FBA, 0x7180, 0x9FBB, 0x7181,
+	0x9FBC, 0x7182, 0x9FBD, 0x7183, 0x9FBE, 0x7185, 0x9FBF, 0x7186,
+	0x9FC0, 0x7187, 0x9FC1, 0x7188, 0x9FC2, 0x7189, 0x9FC3, 0x718B,
+	0x9FC4, 0x718C, 0x9FC5, 0x718D, 0x9FC6, 0x718E, 0x9FC7, 0x7190,
+	0x9FC8, 0x7191, 0x9FC9, 0x7192, 0x9FCA, 0x7193, 0x9FCB, 0x7195,
+	0x9FCC, 0x7196, 0x9FCD, 0x7197, 0x9FCE, 0x719A, 0x9FCF, 0x719B,
+	0x9FD0, 0x719C, 0x9FD1, 0x719D, 0x9FD2, 0x719E, 0x9FD3, 0x71A1,
+	0x9FD4, 0x71A2, 0x9FD5, 0x71A3, 0x9FD6, 0x71A4, 0x9FD7, 0x71A5,
+	0x9FD8, 0x71A6, 0x9FD9, 0x71A7, 0x9FDA, 0x71A9, 0x9FDB, 0x71AA,
+	0x9FDC, 0x71AB, 0x9FDD, 0x71AD, 0x9FDE, 0x71AE, 0x9FDF, 0x71AF,
+	0x9FE0, 0x71B0, 0x9FE1, 0x71B1, 0x9FE2, 0x71B2, 0x9FE3, 0x71B4,
+	0x9FE4, 0x71B6, 0x9FE5, 0x71B7, 0x9FE6, 0x71B8, 0x9FE7, 0x71BA,
+	0x9FE8, 0x71BB, 0x9FE9, 0x71BC, 0x9FEA, 0x71BD, 0x9FEB, 0x71BE,
+	0x9FEC, 0x71BF, 0x9FED, 0x71C0, 0x9FEE, 0x71C1, 0x9FEF, 0x71C2,
+	0x9FF0, 0x71C4, 0x9FF1, 0x71C5, 0x9FF2, 0x71C6, 0x9FF3, 0x71C7,
+	0x9FF4, 0x71C8, 0x9FF5, 0x71C9, 0x9FF6, 0x71CA, 0x9FF7, 0x71CB,
+	0x9FF8, 0x71CC, 0x9FF9, 0x71CD, 0x9FFA, 0x71CF, 0x9FFB, 0x71D0,
+	0x9FFC, 0x71D1, 0x9FFD, 0x71D2, 0x9FFE, 0x71D3, 0xA040, 0x71D6,
+	0xA041, 0x71D7, 0xA042, 0x71D8, 0xA043, 0x71D9, 0xA044, 0x71DA,
+	0xA045, 0x71DB, 0xA046, 0x71DC, 0xA047, 0x71DD, 0xA048, 0x71DE,
+	0xA049, 0x71DF, 0xA04A, 0x71E1, 0xA04B, 0x71E2, 0xA04C, 0x71E3,
+	0xA04D, 0x71E4, 0xA04E, 0x71E6, 0xA04F, 0x71E8, 0xA050, 0x71E9,
+	0xA051, 0x71EA, 0xA052, 0x71EB, 0xA053, 0x71EC, 0xA054, 0x71ED,
+	0xA055, 0x71EF, 0xA056, 0x71F0, 0xA057, 0x71F1, 0xA058, 0x71F2,
+	0xA059, 0x71F3, 0xA05A, 0x71F4, 0xA05B, 0x71F5, 0xA05C, 0x71F6,
+	0xA05D, 0x71F7, 0xA05E, 0x71F8, 0xA05F, 0x71FA, 0xA060, 0x71FB,
+	0xA061, 0x71FC, 0xA062, 0x71FD, 0xA063, 0x71FE, 0xA064, 0x71FF,
+	0xA065, 0x7200, 0xA066, 0x7201, 0xA067, 0x7202, 0xA068, 0x7203,
+	0xA069, 0x7204, 0xA06A, 0x7205, 0xA06B, 0x7207, 0xA06C, 0x7208,
+	0xA06D, 0x7209, 0xA06E, 0x720A, 0xA06F, 0x720B, 0xA070, 0x720C,
+	0xA071, 0x720D, 0xA072, 0x720E, 0xA073, 0x720F, 0xA074, 0x7210,
+	0xA075, 0x7211, 0xA076, 0x7212, 0xA077, 0x7213, 0xA078, 0x7214,
+	0xA079, 0x7215, 0xA07A, 0x7216, 0xA07B, 0x7217, 0xA07C, 0x7218,
+	0xA07D, 0x7219, 0xA07E, 0x721A, 0xA080, 0x721B, 0xA081, 0x721C,
+	0xA082, 0x721E, 0xA083, 0x721F, 0xA084, 0x7220, 0xA085, 0x7221,
+	0xA086, 0x7222, 0xA087, 0x7223, 0xA088, 0x7224, 0xA089, 0x7225,
+	0xA08A, 0x7226, 0xA08B, 0x7227, 0xA08C, 0x7229, 0xA08D, 0x722B,
+	0xA08E, 0x722D, 0xA08F, 0x722E, 0xA090, 0x722F, 0xA091, 0x7232,
+	0xA092, 0x7233, 0xA093, 0x7234, 0xA094, 0x723A, 0xA095, 0x723C,
+	0xA096, 0x723E, 0xA097, 0x7240, 0xA098, 0x7241, 0xA099, 0x7242,
+	0xA09A, 0x7243, 0xA09B, 0x7244, 0xA09C, 0x7245, 0xA09D, 0x7246,
+	0xA09E, 0x7249, 0xA09F, 0x724A, 0xA0A0, 0x724B, 0xA0A1, 0x724E,
+	0xA0A2, 0x724F, 0xA0A3, 0x7250, 0xA0A4, 0x7251, 0xA0A5, 0x7253,
+	0xA0A6, 0x7254, 0xA0A7, 0x7255, 0xA0A8, 0x7257, 0xA0A9, 0x7258,
+	0xA0AA, 0x725A, 0xA0AB, 0x725C, 0xA0AC, 0x725E, 0xA0AD, 0x7260,
+	0xA0AE, 0x7263, 0xA0AF, 0x7264, 0xA0B0, 0x7265, 0xA0B1, 0x7268,
+	0xA0B2, 0x726A, 0xA0B3, 0x726B, 0xA0B4, 0x726C, 0xA0B5, 0x726D,
+	0xA0B6, 0x7270, 0xA0B7, 0x7271, 0xA0B8, 0x7273, 0xA0B9, 0x7274,
+	0xA0BA, 0x7276, 0xA0BB, 0x7277, 0xA0BC, 0x7278, 0xA0BD, 0x727B,
+	0xA0BE, 0x727C, 0xA0BF, 0x727D, 0xA0C0, 0x7282, 0xA0C1, 0x7283,
+	0xA0C2, 0x7285, 0xA0C3, 0x7286, 0xA0C4, 0x7287, 0xA0C5, 0x7288,
+	0xA0C6, 0x7289, 0xA0C7, 0x728C, 0xA0C8, 0x728E, 0xA0C9, 0x7290,
+	0xA0CA, 0x7291, 0xA0CB, 0x7293, 0xA0CC, 0x7294, 0xA0CD, 0x7295,
+	0xA0CE, 0x7296, 0xA0CF, 0x7297, 0xA0D0, 0x7298, 0xA0D1, 0x7299,
+	0xA0D2, 0x729A, 0xA0D3, 0x729B, 0xA0D4, 0x729C, 0xA0D5, 0x729D,
+	0xA0D6, 0x729E, 0xA0D7, 0x72A0, 0xA0D8, 0x72A1, 0xA0D9, 0x72A2,
+	0xA0DA, 0x72A3, 0xA0DB, 0x72A4, 0xA0DC, 0x72A5, 0xA0DD, 0x72A6,
+	0xA0DE, 0x72A7, 0xA0DF, 0x72A8, 0xA0E0, 0x72A9, 0xA0E1, 0x72AA,
+	0xA0E2, 0x72AB, 0xA0E3, 0x72AE, 0xA0E4, 0x72B1, 0xA0E5, 0x72B2,
+	0xA0E6, 0x72B3, 0xA0E7, 0x72B5, 0xA0E8, 0x72BA, 0xA0E9, 0x72BB,
+	0xA0EA, 0x72BC, 0xA0EB, 0x72BD, 0xA0EC, 0x72BE, 0xA0ED, 0x72BF,
+	0xA0EE, 0x72C0, 0xA0EF, 0x72C5, 0xA0F0, 0x72C6, 0xA0F1, 0x72C7,
+	0xA0F2, 0x72C9, 0xA0F3, 0x72CA, 0xA0F4, 0x72CB, 0xA0F5, 0x72CC,
+	0xA0F6, 0x72CF, 0xA0F7, 0x72D1, 0xA0F8, 0x72D3, 0xA0F9, 0x72D4,
+	0xA0FA, 0x72D5, 0xA0FB, 0x72D6, 0xA0FC, 0x72D8, 0xA0FD, 0x72DA,
+	0xA0FE, 0x72DB, 0xA1A1, 0x3000, 0xA1A2, 0x3001, 0xA1A3, 0x3002,
+	0xA1A4, 0x00B7, 0xA1A5, 0x02C9, 0xA1A6, 0x02C7, 0xA1A7, 0x00A8,
+	0xA1A8, 0x3003, 0xA1A9, 0x3005, 0xA1AA, 0x2014, 0xA1AB, 0xFF5E,
+	0xA1AC, 0x2016, 0xA1AD, 0x2026, 0xA1AE, 0x2018, 0xA1AF, 0x2019,
+	0xA1B0, 0x201C, 0xA1B1, 0x201D, 0xA1B2, 0x3014, 0xA1B3, 0x3015,
+	0xA1B4, 0x3008, 0xA1B5, 0x3009, 0xA1B6, 0x300A, 0xA1B7, 0x300B,
+	0xA1B8, 0x300C, 0xA1B9, 0x300D, 0xA1BA, 0x300E, 0xA1BB, 0x300F,
+	0xA1BC, 0x3016, 0xA1BD, 0x3017, 0xA1BE, 0x3010, 0xA1BF, 0x3011,
+	0xA1C0, 0x00B1, 0xA1C1, 0x00D7, 0xA1C2, 0x00F7, 0xA1C3, 0x2236,
+	0xA1C4, 0x2227, 0xA1C5, 0x2228, 0xA1C6, 0x2211, 0xA1C7, 0x220F,
+	0xA1C8, 0x222A, 0xA1C9, 0x2229, 0xA1CA, 0x2208, 0xA1CB, 0x2237,
+	0xA1CC, 0x221A, 0xA1CD, 0x22A5, 0xA1CE, 0x2225, 0xA1CF, 0x2220,
+	0xA1D0, 0x2312, 0xA1D1, 0x2299, 0xA1D2, 0x222B, 0xA1D3, 0x222E,
+	0xA1D4, 0x2261, 0xA1D5, 0x224C, 0xA1D6, 0x2248, 0xA1D7, 0x223D,
+	0xA1D8, 0x221D, 0xA1D9, 0x2260, 0xA1DA, 0x226E, 0xA1DB, 0x226F,
+	0xA1DC, 0x2264, 0xA1DD, 0x2265, 0xA1DE, 0x221E, 0xA1DF, 0x2235,
+	0xA1E0, 0x2234, 0xA1E1, 0x2642, 0xA1E2, 0x2640, 0xA1E3, 0x00B0,
+	0xA1E4, 0x2032, 0xA1E5, 0x2033, 0xA1E6, 0x2103, 0xA1E7, 0xFF04,
+	0xA1E8, 0x00A4, 0xA1E9, 0xFFE0, 0xA1EA, 0xFFE1, 0xA1EB, 0x2030,
+	0xA1EC, 0x00A7, 0xA1ED, 0x2116, 0xA1EE, 0x2606, 0xA1EF, 0x2605,
+	0xA1F0, 0x25CB, 0xA1F1, 0x25CF, 0xA1F2, 0x25CE, 0xA1F3, 0x25C7,
+	0xA1F4, 0x25C6, 0xA1F5, 0x25A1, 0xA1F6, 0x25A0, 0xA1F7, 0x25B3,
+	0xA1F8, 0x25B2, 0xA1F9, 0x203B, 0xA1FA, 0x2192, 0xA1FB, 0x2190,
+	0xA1FC, 0x2191, 0xA1FD, 0x2193, 0xA1FE, 0x3013, 0xA2A1, 0x2170,
+	0xA2A2, 0x2171, 0xA2A3, 0x2172, 0xA2A4, 0x2173, 0xA2A5, 0x2174,
+	0xA2A6, 0x2175, 0xA2A7, 0x2176, 0xA2A8, 0x2177, 0xA2A9, 0x2178,
+	0xA2AA, 0x2179, 0xA2B1, 0x2488, 0xA2B2, 0x2489, 0xA2B3, 0x248A,
+	0xA2B4, 0x248B, 0xA2B5, 0x248C, 0xA2B6, 0x248D, 0xA2B7, 0x248E,
+	0xA2B8, 0x248F, 0xA2B9, 0x2490, 0xA2BA, 0x2491, 0xA2BB, 0x2492,
+	0xA2BC, 0x2493, 0xA2BD, 0x2494, 0xA2BE, 0x2495, 0xA2BF, 0x2496,
+	0xA2C0, 0x2497, 0xA2C1, 0x2498, 0xA2C2, 0x2499, 0xA2C3, 0x249A,
+	0xA2C4, 0x249B, 0xA2C5, 0x2474, 0xA2C6, 0x2475, 0xA2C7, 0x2476,
+	0xA2C8, 0x2477, 0xA2C9, 0x2478, 0xA2CA, 0x2479, 0xA2CB, 0x247A,
+	0xA2CC, 0x247B, 0xA2CD, 0x247C, 0xA2CE, 0x247D, 0xA2CF, 0x247E,
+	0xA2D0, 0x247F, 0xA2D1, 0x2480, 0xA2D2, 0x2481, 0xA2D3, 0x2482,
+	0xA2D4, 0x2483, 0xA2D5, 0x2484, 0xA2D6, 0x2485, 0xA2D7, 0x2486,
+	0xA2D8, 0x2487, 0xA2D9, 0x2460, 0xA2DA, 0x2461, 0xA2DB, 0x2462,
+	0xA2DC, 0x2463, 0xA2DD, 0x2464, 0xA2DE, 0x2465, 0xA2DF, 0x2466,
+	0xA2E0, 0x2467, 0xA2E1, 0x2468, 0xA2E2, 0x2469, 0xA2E5, 0x3220,
+	0xA2E6, 0x3221, 0xA2E7, 0x3222, 0xA2E8, 0x3223, 0xA2E9, 0x3224,
+	0xA2EA, 0x3225, 0xA2EB, 0x3226, 0xA2EC, 0x3227, 0xA2ED, 0x3228,
+	0xA2EE, 0x3229, 0xA2F1, 0x2160, 0xA2F2, 0x2161, 0xA2F3, 0x2162,
+	0xA2F4, 0x2163, 0xA2F5, 0x2164, 0xA2F6, 0x2165, 0xA2F7, 0x2166,
+	0xA2F8, 0x2167, 0xA2F9, 0x2168, 0xA2FA, 0x2169, 0xA2FB, 0x216A,
+	0xA2FC, 0x216B, 0xA3A1, 0xFF01, 0xA3A2, 0xFF02, 0xA3A3, 0xFF03,
+	0xA3A4, 0xFFE5, 0xA3A5, 0xFF05, 0xA3A6, 0xFF06, 0xA3A7, 0xFF07,
+	0xA3A8, 0xFF08, 0xA3A9, 0xFF09, 0xA3AA, 0xFF0A, 0xA3AB, 0xFF0B,
+	0xA3AC, 0xFF0C, 0xA3AD, 0xFF0D, 0xA3AE, 0xFF0E, 0xA3AF, 0xFF0F,
+	0xA3B0, 0xFF10, 0xA3B1, 0xFF11, 0xA3B2, 0xFF12, 0xA3B3, 0xFF13,
+	0xA3B4, 0xFF14, 0xA3B5, 0xFF15, 0xA3B6, 0xFF16, 0xA3B7, 0xFF17,
+	0xA3B8, 0xFF18, 0xA3B9, 0xFF19, 0xA3BA, 0xFF1A, 0xA3BB, 0xFF1B,
+	0xA3BC, 0xFF1C, 0xA3BD, 0xFF1D, 0xA3BE, 0xFF1E, 0xA3BF, 0xFF1F,
+	0xA3C0, 0xFF20, 0xA3C1, 0xFF21, 0xA3C2, 0xFF22, 0xA3C3, 0xFF23,
+	0xA3C4, 0xFF24, 0xA3C5, 0xFF25, 0xA3C6, 0xFF26, 0xA3C7, 0xFF27,
+	0xA3C8, 0xFF28, 0xA3C9, 0xFF29, 0xA3CA, 0xFF2A, 0xA3CB, 0xFF2B,
+	0xA3CC, 0xFF2C, 0xA3CD, 0xFF2D, 0xA3CE, 0xFF2E, 0xA3CF, 0xFF2F,
+	0xA3D0, 0xFF30, 0xA3D1, 0xFF31, 0xA3D2, 0xFF32, 0xA3D3, 0xFF33,
+	0xA3D4, 0xFF34, 0xA3D5, 0xFF35, 0xA3D6, 0xFF36, 0xA3D7, 0xFF37,
+	0xA3D8, 0xFF38, 0xA3D9, 0xFF39, 0xA3DA, 0xFF3A, 0xA3DB, 0xFF3B,
+	0xA3DC, 0xFF3C, 0xA3DD, 0xFF3D, 0xA3DE, 0xFF3E, 0xA3DF, 0xFF3F,
+	0xA3E0, 0xFF40, 0xA3E1, 0xFF41, 0xA3E2, 0xFF42, 0xA3E3, 0xFF43,
+	0xA3E4, 0xFF44, 0xA3E5, 0xFF45, 0xA3E6, 0xFF46, 0xA3E7, 0xFF47,
+	0xA3E8, 0xFF48, 0xA3E9, 0xFF49, 0xA3EA, 0xFF4A, 0xA3EB, 0xFF4B,
+	0xA3EC, 0xFF4C, 0xA3ED, 0xFF4D, 0xA3EE, 0xFF4E, 0xA3EF, 0xFF4F,
+	0xA3F0, 0xFF50, 0xA3F1, 0xFF51, 0xA3F2, 0xFF52, 0xA3F3, 0xFF53,
+	0xA3F4, 0xFF54, 0xA3F5, 0xFF55, 0xA3F6, 0xFF56, 0xA3F7, 0xFF57,
+	0xA3F8, 0xFF58, 0xA3F9, 0xFF59, 0xA3FA, 0xFF5A, 0xA3FB, 0xFF5B,
+	0xA3FC, 0xFF5C, 0xA3FD, 0xFF5D, 0xA3FE, 0xFFE3, 0xA4A1, 0x3041,
+	0xA4A2, 0x3042, 0xA4A3, 0x3043, 0xA4A4, 0x3044, 0xA4A5, 0x3045,
+	0xA4A6, 0x3046, 0xA4A7, 0x3047, 0xA4A8, 0x3048, 0xA4A9, 0x3049,
+	0xA4AA, 0x304A, 0xA4AB, 0x304B, 0xA4AC, 0x304C, 0xA4AD, 0x304D,
+	0xA4AE, 0x304E, 0xA4AF, 0x304F, 0xA4B0, 0x3050, 0xA4B1, 0x3051,
+	0xA4B2, 0x3052, 0xA4B3, 0x3053, 0xA4B4, 0x3054, 0xA4B5, 0x3055,
+	0xA4B6, 0x3056, 0xA4B7, 0x3057, 0xA4B8, 0x3058, 0xA4B9, 0x3059,
+	0xA4BA, 0x305A, 0xA4BB, 0x305B, 0xA4BC, 0x305C, 0xA4BD, 0x305D,
+	0xA4BE, 0x305E, 0xA4BF, 0x305F, 0xA4C0, 0x3060, 0xA4C1, 0x3061,
+	0xA4C2, 0x3062, 0xA4C3, 0x3063, 0xA4C4, 0x3064, 0xA4C5, 0x3065,
+	0xA4C6, 0x3066, 0xA4C7, 0x3067, 0xA4C8, 0x3068, 0xA4C9, 0x3069,
+	0xA4CA, 0x306A, 0xA4CB, 0x306B, 0xA4CC, 0x306C, 0xA4CD, 0x306D,
+	0xA4CE, 0x306E, 0xA4CF, 0x306F, 0xA4D0, 0x3070, 0xA4D1, 0x3071,
+	0xA4D2, 0x3072, 0xA4D3, 0x3073, 0xA4D4, 0x3074, 0xA4D5, 0x3075,
+	0xA4D6, 0x3076, 0xA4D7, 0x3077, 0xA4D8, 0x3078, 0xA4D9, 0x3079,
+	0xA4DA, 0x307A, 0xA4DB, 0x307B, 0xA4DC, 0x307C, 0xA4DD, 0x307D,
+	0xA4DE, 0x307E, 0xA4DF, 0x307F, 0xA4E0, 0x3080, 0xA4E1, 0x3081,
+	0xA4E2, 0x3082, 0xA4E3, 0x3083, 0xA4E4, 0x3084, 0xA4E5, 0x3085,
+	0xA4E6, 0x3086, 0xA4E7, 0x3087, 0xA4E8, 0x3088, 0xA4E9, 0x3089,
+	0xA4EA, 0x308A, 0xA4EB, 0x308B, 0xA4EC, 0x308C, 0xA4ED, 0x308D,
+	0xA4EE, 0x308E, 0xA4EF, 0x308F, 0xA4F0, 0x3090, 0xA4F1, 0x3091,
+	0xA4F2, 0x3092, 0xA4F3, 0x3093, 0xA5A1, 0x30A1, 0xA5A2, 0x30A2,
+	0xA5A3, 0x30A3, 0xA5A4, 0x30A4, 0xA5A5, 0x30A5, 0xA5A6, 0x30A6,
+	0xA5A7, 0x30A7, 0xA5A8, 0x30A8, 0xA5A9, 0x30A9, 0xA5AA, 0x30AA,
+	0xA5AB, 0x30AB, 0xA5AC, 0x30AC, 0xA5AD, 0x30AD, 0xA5AE, 0x30AE,
+	0xA5AF, 0x30AF, 0xA5B0, 0x30B0, 0xA5B1, 0x30B1, 0xA5B2, 0x30B2,
+	0xA5B3, 0x30B3, 0xA5B4, 0x30B4, 0xA5B5, 0x30B5, 0xA5B6, 0x30B6,
+	0xA5B7, 0x30B7, 0xA5B8, 0x30B8, 0xA5B9, 0x30B9, 0xA5BA, 0x30BA,
+	0xA5BB, 0x30BB, 0xA5BC, 0x30BC, 0xA5BD, 0x30BD, 0xA5BE, 0x30BE,
+	0xA5BF, 0x30BF, 0xA5C0, 0x30C0, 0xA5C1, 0x30C1, 0xA5C2, 0x30C2,
+	0xA5C3, 0x30C3, 0xA5C4, 0x30C4, 0xA5C5, 0x30C5, 0xA5C6, 0x30C6,
+	0xA5C7, 0x30C7, 0xA5C8, 0x30C8, 0xA5C9, 0x30C9, 0xA5CA, 0x30CA,
+	0xA5CB, 0x30CB, 0xA5CC, 0x30CC, 0xA5CD, 0x30CD, 0xA5CE, 0x30CE,
+	0xA5CF, 0x30CF, 0xA5D0, 0x30D0, 0xA5D1, 0x30D1, 0xA5D2, 0x30D2,
+	0xA5D3, 0x30D3, 0xA5D4, 0x30D4, 0xA5D5, 0x30D5, 0xA5D6, 0x30D6,
+	0xA5D7, 0x30D7, 0xA5D8, 0x30D8, 0xA5D9, 0x30D9, 0xA5DA, 0x30DA,
+	0xA5DB, 0x30DB, 0xA5DC, 0x30DC, 0xA5DD, 0x30DD, 0xA5DE, 0x30DE,
+	0xA5DF, 0x30DF, 0xA5E0, 0x30E0, 0xA5E1, 0x30E1, 0xA5E2, 0x30E2,
+	0xA5E3, 0x30E3, 0xA5E4, 0x30E4, 0xA5E5, 0x30E5, 0xA5E6, 0x30E6,
+	0xA5E7, 0x30E7, 0xA5E8, 0x30E8, 0xA5E9, 0x30E9, 0xA5EA, 0x30EA,
+	0xA5EB, 0x30EB, 0xA5EC, 0x30EC, 0xA5ED, 0x30ED, 0xA5EE, 0x30EE,
+	0xA5EF, 0x30EF, 0xA5F0, 0x30F0, 0xA5F1, 0x30F1, 0xA5F2, 0x30F2,
+	0xA5F3, 0x30F3, 0xA5F4, 0x30F4, 0xA5F5, 0x30F5, 0xA5F6, 0x30F6,
+	0xA6A1, 0x0391, 0xA6A2, 0x0392, 0xA6A3, 0x0393, 0xA6A4, 0x0394,
+	0xA6A5, 0x0395, 0xA6A6, 0x0396, 0xA6A7, 0x0397, 0xA6A8, 0x0398,
+	0xA6A9, 0x0399, 0xA6AA, 0x039A, 0xA6AB, 0x039B, 0xA6AC, 0x039C,
+	0xA6AD, 0x039D, 0xA6AE, 0x039E, 0xA6AF, 0x039F, 0xA6B0, 0x03A0,
+	0xA6B1, 0x03A1, 0xA6B2, 0x03A3, 0xA6B3, 0x03A4, 0xA6B4, 0x03A5,
+	0xA6B5, 0x03A6, 0xA6B6, 0x03A7, 0xA6B7, 0x03A8, 0xA6B8, 0x03A9,
+	0xA6C1, 0x03B1, 0xA6C2, 0x03B2, 0xA6C3, 0x03B3, 0xA6C4, 0x03B4,
+	0xA6C5, 0x03B5, 0xA6C6, 0x03B6, 0xA6C7, 0x03B7, 0xA6C8, 0x03B8,
+	0xA6C9, 0x03B9, 0xA6CA, 0x03BA, 0xA6CB, 0x03BB, 0xA6CC, 0x03BC,
+	0xA6CD, 0x03BD, 0xA6CE, 0x03BE, 0xA6CF, 0x03BF, 0xA6D0, 0x03C0,
+	0xA6D1, 0x03C1, 0xA6D2, 0x03C3, 0xA6D3, 0x03C4, 0xA6D4, 0x03C5,
+	0xA6D5, 0x03C6, 0xA6D6, 0x03C7, 0xA6D7, 0x03C8, 0xA6D8, 0x03C9,
+	0xA6E0, 0xFE35, 0xA6E1, 0xFE36, 0xA6E2, 0xFE39, 0xA6E3, 0xFE3A,
+	0xA6E4, 0xFE3F, 0xA6E5, 0xFE40, 0xA6E6, 0xFE3D, 0xA6E7, 0xFE3E,
+	0xA6E8, 0xFE41, 0xA6E9, 0xFE42, 0xA6EA, 0xFE43, 0xA6EB, 0xFE44,
+	0xA6EE, 0xFE3B, 0xA6EF, 0xFE3C, 0xA6F0, 0xFE37, 0xA6F1, 0xFE38,
+	0xA6F2, 0xFE31, 0xA6F4, 0xFE33, 0xA6F5, 0xFE34, 0xA7A1, 0x0410,
+	0xA7A2, 0x0411, 0xA7A3, 0x0412, 0xA7A4, 0x0413, 0xA7A5, 0x0414,
+	0xA7A6, 0x0415, 0xA7A7, 0x0401, 0xA7A8, 0x0416, 0xA7A9, 0x0417,
+	0xA7AA, 0x0418, 0xA7AB, 0x0419, 0xA7AC, 0x041A, 0xA7AD, 0x041B,
+	0xA7AE, 0x041C, 0xA7AF, 0x041D, 0xA7B0, 0x041E, 0xA7B1, 0x041F,
+	0xA7B2, 0x0420, 0xA7B3, 0x0421, 0xA7B4, 0x0422, 0xA7B5, 0x0423,
+	0xA7B6, 0x0424, 0xA7B7, 0x0425, 0xA7B8, 0x0426, 0xA7B9, 0x0427,
+	0xA7BA, 0x0428, 0xA7BB, 0x0429, 0xA7BC, 0x042A, 0xA7BD, 0x042B,
+	0xA7BE, 0x042C, 0xA7BF, 0x042D, 0xA7C0, 0x042E, 0xA7C1, 0x042F,
+	0xA7D1, 0x0430, 0xA7D2, 0x0431, 0xA7D3, 0x0432, 0xA7D4, 0x0433,
+	0xA7D5, 0x0434, 0xA7D6, 0x0435, 0xA7D7, 0x0451, 0xA7D8, 0x0436,
+	0xA7D9, 0x0437, 0xA7DA, 0x0438, 0xA7DB, 0x0439, 0xA7DC, 0x043A,
+	0xA7DD, 0x043B, 0xA7DE, 0x043C, 0xA7DF, 0x043D, 0xA7E0, 0x043E,
+	0xA7E1, 0x043F, 0xA7E2, 0x0440, 0xA7E3, 0x0441, 0xA7E4, 0x0442,
+	0xA7E5, 0x0443, 0xA7E6, 0x0444, 0xA7E7, 0x0445, 0xA7E8, 0x0446,
+	0xA7E9, 0x0447, 0xA7EA, 0x0448, 0xA7EB, 0x0449, 0xA7EC, 0x044A,
+	0xA7ED, 0x044B, 0xA7EE, 0x044C, 0xA7EF, 0x044D, 0xA7F0, 0x044E,
+	0xA7F1, 0x044F, 0xA840, 0x02CA, 0xA841, 0x02CB, 0xA842, 0x02D9,
+	0xA843, 0x2013, 0xA844, 0x2015, 0xA845, 0x2025, 0xA846, 0x2035,
+	0xA847, 0x2105, 0xA848, 0x2109, 0xA849, 0x2196, 0xA84A, 0x2197,
+	0xA84B, 0x2198, 0xA84C, 0x2199, 0xA84D, 0x2215, 0xA84E, 0x221F,
+	0xA84F, 0x2223, 0xA850, 0x2252, 0xA851, 0x2266, 0xA852, 0x2267,
+	0xA853, 0x22BF, 0xA854, 0x2550, 0xA855, 0x2551, 0xA856, 0x2552,
+	0xA857, 0x2553, 0xA858, 0x2554, 0xA859, 0x2555, 0xA85A, 0x2556,
+	0xA85B, 0x2557, 0xA85C, 0x2558, 0xA85D, 0x2559, 0xA85E, 0x255A,
+	0xA85F, 0x255B, 0xA860, 0x255C, 0xA861, 0x255D, 0xA862, 0x255E,
+	0xA863, 0x255F, 0xA864, 0x2560, 0xA865, 0x2561, 0xA866, 0x2562,
+	0xA867, 0x2563, 0xA868, 0x2564, 0xA869, 0x2565, 0xA86A, 0x2566,
+	0xA86B, 0x2567, 0xA86C, 0x2568, 0xA86D, 0x2569, 0xA86E, 0x256A,
+	0xA86F, 0x256B, 0xA870, 0x256C, 0xA871, 0x256D, 0xA872, 0x256E,
+	0xA873, 0x256F, 0xA874, 0x2570, 0xA875, 0x2571, 0xA876, 0x2572,
+	0xA877, 0x2573, 0xA878, 0x2581, 0xA879, 0x2582, 0xA87A, 0x2583,
+	0xA87B, 0x2584, 0xA87C, 0x2585, 0xA87D, 0x2586, 0xA87E, 0x2587,
+	0xA880, 0x2588, 0xA881, 0x2589, 0xA882, 0x258A, 0xA883, 0x258B,
+	0xA884, 0x258C, 0xA885, 0x258D, 0xA886, 0x258E, 0xA887, 0x258F,
+	0xA888, 0x2593, 0xA889, 0x2594, 0xA88A, 0x2595, 0xA88B, 0x25BC,
+	0xA88C, 0x25BD, 0xA88D, 0x25E2, 0xA88E, 0x25E3, 0xA88F, 0x25E4,
+	0xA890, 0x25E5, 0xA891, 0x2609, 0xA892, 0x2295, 0xA893, 0x3012,
+	0xA894, 0x301D, 0xA895, 0x301E, 0xA8A1, 0x0101, 0xA8A2, 0x00E1,
+	0xA8A3, 0x01CE, 0xA8A4, 0x00E0, 0xA8A5, 0x0113, 0xA8A6, 0x00E9,
+	0xA8A7, 0x011B, 0xA8A8, 0x00E8, 0xA8A9, 0x012B, 0xA8AA, 0x00ED,
+	0xA8AB, 0x01D0, 0xA8AC, 0x00EC, 0xA8AD, 0x014D, 0xA8AE, 0x00F3,
+	0xA8AF, 0x01D2, 0xA8B0, 0x00F2, 0xA8B1, 0x016B, 0xA8B2, 0x00FA,
+	0xA8B3, 0x01D4, 0xA8B4, 0x00F9, 0xA8B5, 0x01D6, 0xA8B6, 0x01D8,
+	0xA8B7, 0x01DA, 0xA8B8, 0x01DC, 0xA8B9, 0x00FC, 0xA8BA, 0x00EA,
+	0xA8BB, 0x0251, 0xA8BD, 0x0144, 0xA8BE, 0x0148, 0xA8C0, 0x0261,
+	0xA8C5, 0x3105, 0xA8C6, 0x3106, 0xA8C7, 0x3107, 0xA8C8, 0x3108,
+	0xA8C9, 0x3109, 0xA8CA, 0x310A, 0xA8CB, 0x310B, 0xA8CC, 0x310C,
+	0xA8CD, 0x310D, 0xA8CE, 0x310E, 0xA8CF, 0x310F, 0xA8D0, 0x3110,
+	0xA8D1, 0x3111, 0xA8D2, 0x3112, 0xA8D3, 0x3113, 0xA8D4, 0x3114,
+	0xA8D5, 0x3115, 0xA8D6, 0x3116, 0xA8D7, 0x3117, 0xA8D8, 0x3118,
+	0xA8D9, 0x3119, 0xA8DA, 0x311A, 0xA8DB, 0x311B, 0xA8DC, 0x311C,
+	0xA8DD, 0x311D, 0xA8DE, 0x311E, 0xA8DF, 0x311F, 0xA8E0, 0x3120,
+	0xA8E1, 0x3121, 0xA8E2, 0x3122, 0xA8E3, 0x3123, 0xA8E4, 0x3124,
+	0xA8E5, 0x3125, 0xA8E6, 0x3126, 0xA8E7, 0x3127, 0xA8E8, 0x3128,
+	0xA8E9, 0x3129, 0xA940, 0x3021, 0xA941, 0x3022, 0xA942, 0x3023,
+	0xA943, 0x3024, 0xA944, 0x3025, 0xA945, 0x3026, 0xA946, 0x3027,
+	0xA947, 0x3028, 0xA948, 0x3029, 0xA949, 0x32A3, 0xA94A, 0x338E,
+	0xA94B, 0x338F, 0xA94C, 0x339C, 0xA94D, 0x339D, 0xA94E, 0x339E,
+	0xA94F, 0x33A1, 0xA950, 0x33C4, 0xA951, 0x33CE, 0xA952, 0x33D1,
+	0xA953, 0x33D2, 0xA954, 0x33D5, 0xA955, 0xFE30, 0xA956, 0xFFE2,
+	0xA957, 0xFFE4, 0xA959, 0x2121, 0xA95A, 0x3231, 0xA95C, 0x2010,
+	0xA960, 0x30FC, 0xA961, 0x309B, 0xA962, 0x309C, 0xA963, 0x30FD,
+	0xA964, 0x30FE, 0xA965, 0x3006, 0xA966, 0x309D, 0xA967, 0x309E,
+	0xA968, 0xFE49, 0xA969, 0xFE4A, 0xA96A, 0xFE4B, 0xA96B, 0xFE4C,
+	0xA96C, 0xFE4D, 0xA96D, 0xFE4E, 0xA96E, 0xFE4F, 0xA96F, 0xFE50,
+	0xA970, 0xFE51, 0xA971, 0xFE52, 0xA972, 0xFE54, 0xA973, 0xFE55,
+	0xA974, 0xFE56, 0xA975, 0xFE57, 0xA976, 0xFE59, 0xA977, 0xFE5A,
+	0xA978, 0xFE5B, 0xA979, 0xFE5C, 0xA97A, 0xFE5D, 0xA97B, 0xFE5E,
+	0xA97C, 0xFE5F, 0xA97D, 0xFE60, 0xA97E, 0xFE61, 0xA980, 0xFE62,
+	0xA981, 0xFE63, 0xA982, 0xFE64, 0xA983, 0xFE65, 0xA984, 0xFE66,
+	0xA985, 0xFE68, 0xA986, 0xFE69, 0xA987, 0xFE6A, 0xA988, 0xFE6B,
+	0xA996, 0x3007, 0xA9A4, 0x2500, 0xA9A5, 0x2501, 0xA9A6, 0x2502,
+	0xA9A7, 0x2503, 0xA9A8, 0x2504, 0xA9A9, 0x2505, 0xA9AA, 0x2506,
+	0xA9AB, 0x2507, 0xA9AC, 0x2508, 0xA9AD, 0x2509, 0xA9AE, 0x250A,
+	0xA9AF, 0x250B, 0xA9B0, 0x250C, 0xA9B1, 0x250D, 0xA9B2, 0x250E,
+	0xA9B3, 0x250F, 0xA9B4, 0x2510, 0xA9B5, 0x2511, 0xA9B6, 0x2512,
+	0xA9B7, 0x2513, 0xA9B8, 0x2514, 0xA9B9, 0x2515, 0xA9BA, 0x2516,
+	0xA9BB, 0x2517, 0xA9BC, 0x2518, 0xA9BD, 0x2519, 0xA9BE, 0x251A,
+	0xA9BF, 0x251B, 0xA9C0, 0x251C, 0xA9C1, 0x251D, 0xA9C2, 0x251E,
+	0xA9C3, 0x251F, 0xA9C4, 0x2520, 0xA9C5, 0x2521, 0xA9C6, 0x2522,
+	0xA9C7, 0x2523, 0xA9C8, 0x2524, 0xA9C9, 0x2525, 0xA9CA, 0x2526,
+	0xA9CB, 0x2527, 0xA9CC, 0x2528, 0xA9CD, 0x2529, 0xA9CE, 0x252A,
+	0xA9CF, 0x252B, 0xA9D0, 0x252C, 0xA9D1, 0x252D, 0xA9D2, 0x252E,
+	0xA9D3, 0x252F, 0xA9D4, 0x2530, 0xA9D5, 0x2531, 0xA9D6, 0x2532,
+	0xA9D7, 0x2533, 0xA9D8, 0x2534, 0xA9D9, 0x2535, 0xA9DA, 0x2536,
+	0xA9DB, 0x2537, 0xA9DC, 0x2538, 0xA9DD, 0x2539, 0xA9DE, 0x253A,
+	0xA9DF, 0x253B, 0xA9E0, 0x253C, 0xA9E1, 0x253D, 0xA9E2, 0x253E,
+	0xA9E3, 0x253F, 0xA9E4, 0x2540, 0xA9E5, 0x2541, 0xA9E6, 0x2542,
+	0xA9E7, 0x2543, 0xA9E8, 0x2544, 0xA9E9, 0x2545, 0xA9EA, 0x2546,
+	0xA9EB, 0x2547, 0xA9EC, 0x2548, 0xA9ED, 0x2549, 0xA9EE, 0x254A,
+	0xA9EF, 0x254B, 0xAA40, 0x72DC, 0xAA41, 0x72DD, 0xAA42, 0x72DF,
+	0xAA43, 0x72E2, 0xAA44, 0x72E3, 0xAA45, 0x72E4, 0xAA46, 0x72E5,
+	0xAA47, 0x72E6, 0xAA48, 0x72E7, 0xAA49, 0x72EA, 0xAA4A, 0x72EB,
+	0xAA4B, 0x72F5, 0xAA4C, 0x72F6, 0xAA4D, 0x72F9, 0xAA4E, 0x72FD,
+	0xAA4F, 0x72FE, 0xAA50, 0x72FF, 0xAA51, 0x7300, 0xAA52, 0x7302,
+	0xAA53, 0x7304, 0xAA54, 0x7305, 0xAA55, 0x7306, 0xAA56, 0x7307,
+	0xAA57, 0x7308, 0xAA58, 0x7309, 0xAA59, 0x730B, 0xAA5A, 0x730C,
+	0xAA5B, 0x730D, 0xAA5C, 0x730F, 0xAA5D, 0x7310, 0xAA5E, 0x7311,
+	0xAA5F, 0x7312, 0xAA60, 0x7314, 0xAA61, 0x7318, 0xAA62, 0x7319,
+	0xAA63, 0x731A, 0xAA64, 0x731F, 0xAA65, 0x7320, 0xAA66, 0x7323,
+	0xAA67, 0x7324, 0xAA68, 0x7326, 0xAA69, 0x7327, 0xAA6A, 0x7328,
+	0xAA6B, 0x732D, 0xAA6C, 0x732F, 0xAA6D, 0x7330, 0xAA6E, 0x7332,
+	0xAA6F, 0x7333, 0xAA70, 0x7335, 0xAA71, 0x7336, 0xAA72, 0x733A,
+	0xAA73, 0x733B, 0xAA74, 0x733C, 0xAA75, 0x733D, 0xAA76, 0x7340,
+	0xAA77, 0x7341, 0xAA78, 0x7342, 0xAA79, 0x7343, 0xAA7A, 0x7344,
+	0xAA7B, 0x7345, 0xAA7C, 0x7346, 0xAA7D, 0x7347, 0xAA7E, 0x7348,
+	0xAA80, 0x7349, 0xAA81, 0x734A, 0xAA82, 0x734B, 0xAA83, 0x734C,
+	0xAA84, 0x734E, 0xAA85, 0x734F, 0xAA86, 0x7351, 0xAA87, 0x7353,
+	0xAA88, 0x7354, 0xAA89, 0x7355, 0xAA8A, 0x7356, 0xAA8B, 0x7358,
+	0xAA8C, 0x7359, 0xAA8D, 0x735A, 0xAA8E, 0x735B, 0xAA8F, 0x735C,
+	0xAA90, 0x735D, 0xAA91, 0x735E, 0xAA92, 0x735F, 0xAA93, 0x7361,
+	0xAA94, 0x7362, 0xAA95, 0x7363, 0xAA96, 0x7364, 0xAA97, 0x7365,
+	0xAA98, 0x7366, 0xAA99, 0x7367, 0xAA9A, 0x7368, 0xAA9B, 0x7369,
+	0xAA9C, 0x736A, 0xAA9D, 0x736B, 0xAA9E, 0x736E, 0xAA9F, 0x7370,
+	0xAAA0, 0x7371, 0xAB40, 0x7372, 0xAB41, 0x7373, 0xAB42, 0x7374,
+	0xAB43, 0x7375, 0xAB44, 0x7376, 0xAB45, 0x7377, 0xAB46, 0x7378,
+	0xAB47, 0x7379, 0xAB48, 0x737A, 0xAB49, 0x737B, 0xAB4A, 0x737C,
+	0xAB4B, 0x737D, 0xAB4C, 0x737F, 0xAB4D, 0x7380, 0xAB4E, 0x7381,
+	0xAB4F, 0x7382, 0xAB50, 0x7383, 0xAB51, 0x7385, 0xAB52, 0x7386,
+	0xAB53, 0x7388, 0xAB54, 0x738A, 0xAB55, 0x738C, 0xAB56, 0x738D,
+	0xAB57, 0x738F, 0xAB58, 0x7390, 0xAB59, 0x7392, 0xAB5A, 0x7393,
+	0xAB5B, 0x7394, 0xAB5C, 0x7395, 0xAB5D, 0x7397, 0xAB5E, 0x7398,
+	0xAB5F, 0x7399, 0xAB60, 0x739A, 0xAB61, 0x739C, 0xAB62, 0x739D,
+	0xAB63, 0x739E, 0xAB64, 0x73A0, 0xAB65, 0x73A1, 0xAB66, 0x73A3,
+	0xAB67, 0x73A4, 0xAB68, 0x73A5, 0xAB69, 0x73A6, 0xAB6A, 0x73A7,
+	0xAB6B, 0x73A8, 0xAB6C, 0x73AA, 0xAB6D, 0x73AC, 0xAB6E, 0x73AD,
+	0xAB6F, 0x73B1, 0xAB70, 0x73B4, 0xAB71, 0x73B5, 0xAB72, 0x73B6,
+	0xAB73, 0x73B8, 0xAB74, 0x73B9, 0xAB75, 0x73BC, 0xAB76, 0x73BD,
+	0xAB77, 0x73BE, 0xAB78, 0x73BF, 0xAB79, 0x73C1, 0xAB7A, 0x73C3,
+	0xAB7B, 0x73C4, 0xAB7C, 0x73C5, 0xAB7D, 0x73C6, 0xAB7E, 0x73C7,
+	0xAB80, 0x73CB, 0xAB81, 0x73CC, 0xAB82, 0x73CE, 0xAB83, 0x73D2,
+	0xAB84, 0x73D3, 0xAB85, 0x73D4, 0xAB86, 0x73D5, 0xAB87, 0x73D6,
+	0xAB88, 0x73D7, 0xAB89, 0x73D8, 0xAB8A, 0x73DA, 0xAB8B, 0x73DB,
+	0xAB8C, 0x73DC, 0xAB8D, 0x73DD, 0xAB8E, 0x73DF, 0xAB8F, 0x73E1,
+	0xAB90, 0x73E2, 0xAB91, 0x73E3, 0xAB92, 0x73E4, 0xAB93, 0x73E6,
+	0xAB94, 0x73E8, 0xAB95, 0x73EA, 0xAB96, 0x73EB, 0xAB97, 0x73EC,
+	0xAB98, 0x73EE, 0xAB99, 0x73EF, 0xAB9A, 0x73F0, 0xAB9B, 0x73F1,
+	0xAB9C, 0x73F3, 0xAB9D, 0x73F4, 0xAB9E, 0x73F5, 0xAB9F, 0x73F6,
+	0xABA0, 0x73F7, 0xAC40, 0x73F8, 0xAC41, 0x73F9, 0xAC42, 0x73FA,
+	0xAC43, 0x73FB, 0xAC44, 0x73FC, 0xAC45, 0x73FD, 0xAC46, 0x73FE,
+	0xAC47, 0x73FF, 0xAC48, 0x7400, 0xAC49, 0x7401, 0xAC4A, 0x7402,
+	0xAC4B, 0x7404, 0xAC4C, 0x7407, 0xAC4D, 0x7408, 0xAC4E, 0x740B,
+	0xAC4F, 0x740C, 0xAC50, 0x740D, 0xAC51, 0x740E, 0xAC52, 0x7411,
+	0xAC53, 0x7412, 0xAC54, 0x7413, 0xAC55, 0x7414, 0xAC56, 0x7415,
+	0xAC57, 0x7416, 0xAC58, 0x7417, 0xAC59, 0x7418, 0xAC5A, 0x7419,
+	0xAC5B, 0x741C, 0xAC5C, 0x741D, 0xAC5D, 0x741E, 0xAC5E, 0x741F,
+	0xAC5F, 0x7420, 0xAC60, 0x7421, 0xAC61, 0x7423, 0xAC62, 0x7424,
+	0xAC63, 0x7427, 0xAC64, 0x7429, 0xAC65, 0x742B, 0xAC66, 0x742D,
+	0xAC67, 0x742F, 0xAC68, 0x7431, 0xAC69, 0x7432, 0xAC6A, 0x7437,
+	0xAC6B, 0x7438, 0xAC6C, 0x7439, 0xAC6D, 0x743A, 0xAC6E, 0x743B,
+	0xAC6F, 0x743D, 0xAC70, 0x743E, 0xAC71, 0x743F, 0xAC72, 0x7440,
+	0xAC73, 0x7442, 0xAC74, 0x7443, 0xAC75, 0x7444, 0xAC76, 0x7445,
+	0xAC77, 0x7446, 0xAC78, 0x7447, 0xAC79, 0x7448, 0xAC7A, 0x7449,
+	0xAC7B, 0x744A, 0xAC7C, 0x744B, 0xAC7D, 0x744C, 0xAC7E, 0x744D,
+	0xAC80, 0x744E, 0xAC81, 0x744F, 0xAC82, 0x7450, 0xAC83, 0x7451,
+	0xAC84, 0x7452, 0xAC85, 0x7453, 0xAC86, 0x7454, 0xAC87, 0x7456,
+	0xAC88, 0x7458, 0xAC89, 0x745D, 0xAC8A, 0x7460, 0xAC8B, 0x7461,
+	0xAC8C, 0x7462, 0xAC8D, 0x7463, 0xAC8E, 0x7464, 0xAC8F, 0x7465,
+	0xAC90, 0x7466, 0xAC91, 0x7467, 0xAC92, 0x7468, 0xAC93, 0x7469,
+	0xAC94, 0x746A, 0xAC95, 0x746B, 0xAC96, 0x746C, 0xAC97, 0x746E,
+	0xAC98, 0x746F, 0xAC99, 0x7471, 0xAC9A, 0x7472, 0xAC9B, 0x7473,
+	0xAC9C, 0x7474, 0xAC9D, 0x7475, 0xAC9E, 0x7478, 0xAC9F, 0x7479,
+	0xACA0, 0x747A, 0xAD40, 0x747B, 0xAD41, 0x747C, 0xAD42, 0x747D,
+	0xAD43, 0x747F, 0xAD44, 0x7482, 0xAD45, 0x7484, 0xAD46, 0x7485,
+	0xAD47, 0x7486, 0xAD48, 0x7488, 0xAD49, 0x7489, 0xAD4A, 0x748A,
+	0xAD4B, 0x748C, 0xAD4C, 0x748D, 0xAD4D, 0x748F, 0xAD4E, 0x7491,
+	0xAD4F, 0x7492, 0xAD50, 0x7493, 0xAD51, 0x7494, 0xAD52, 0x7495,
+	0xAD53, 0x7496, 0xAD54, 0x7497, 0xAD55, 0x7498, 0xAD56, 0x7499,
+	0xAD57, 0x749A, 0xAD58, 0x749B, 0xAD59, 0x749D, 0xAD5A, 0x749F,
+	0xAD5B, 0x74A0, 0xAD5C, 0x74A1, 0xAD5D, 0x74A2, 0xAD5E, 0x74A3,
+	0xAD5F, 0x74A4, 0xAD60, 0x74A5, 0xAD61, 0x74A6, 0xAD62, 0x74AA,
+	0xAD63, 0x74AB, 0xAD64, 0x74AC, 0xAD65, 0x74AD, 0xAD66, 0x74AE,
+	0xAD67, 0x74AF, 0xAD68, 0x74B0, 0xAD69, 0x74B1, 0xAD6A, 0x74B2,
+	0xAD6B, 0x74B3, 0xAD6C, 0x74B4, 0xAD6D, 0x74B5, 0xAD6E, 0x74B6,
+	0xAD6F, 0x74B7, 0xAD70, 0x74B8, 0xAD71, 0x74B9, 0xAD72, 0x74BB,
+	0xAD73, 0x74BC, 0xAD74, 0x74BD, 0xAD75, 0x74BE, 0xAD76, 0x74BF,
+	0xAD77, 0x74C0, 0xAD78, 0x74C1, 0xAD79, 0x74C2, 0xAD7A, 0x74C3,
+	0xAD7B, 0x74C4, 0xAD7C, 0x74C5, 0xAD7D, 0x74C6, 0xAD7E, 0x74C7,
+	0xAD80, 0x74C8, 0xAD81, 0x74C9, 0xAD82, 0x74CA, 0xAD83, 0x74CB,
+	0xAD84, 0x74CC, 0xAD85, 0x74CD, 0xAD86, 0x74CE, 0xAD87, 0x74CF,
+	0xAD88, 0x74D0, 0xAD89, 0x74D1, 0xAD8A, 0x74D3, 0xAD8B, 0x74D4,
+	0xAD8C, 0x74D5, 0xAD8D, 0x74D6, 0xAD8E, 0x74D7, 0xAD8F, 0x74D8,
+	0xAD90, 0x74D9, 0xAD91, 0x74DA, 0xAD92, 0x74DB, 0xAD93, 0x74DD,
+	0xAD94, 0x74DF, 0xAD95, 0x74E1, 0xAD96, 0x74E5, 0xAD97, 0x74E7,
+	0xAD98, 0x74E8, 0xAD99, 0x74E9, 0xAD9A, 0x74EA, 0xAD9B, 0x74EB,
+	0xAD9C, 0x74EC, 0xAD9D, 0x74ED, 0xAD9E, 0x74F0, 0xAD9F, 0x74F1,
+	0xADA0, 0x74F2, 0xAE40, 0x74F3, 0xAE41, 0x74F5, 0xAE42, 0x74F8,
+	0xAE43, 0x74F9, 0xAE44, 0x74FA, 0xAE45, 0x74FB, 0xAE46, 0x74FC,
+	0xAE47, 0x74FD, 0xAE48, 0x74FE, 0xAE49, 0x7500, 0xAE4A, 0x7501,
+	0xAE4B, 0x7502, 0xAE4C, 0x7503, 0xAE4D, 0x7505, 0xAE4E, 0x7506,
+	0xAE4F, 0x7507, 0xAE50, 0x7508, 0xAE51, 0x7509, 0xAE52, 0x750A,
+	0xAE53, 0x750B, 0xAE54, 0x750C, 0xAE55, 0x750E, 0xAE56, 0x7510,
+	0xAE57, 0x7512, 0xAE58, 0x7514, 0xAE59, 0x7515, 0xAE5A, 0x7516,
+	0xAE5B, 0x7517, 0xAE5C, 0x751B, 0xAE5D, 0x751D, 0xAE5E, 0x751E,
+	0xAE5F, 0x7520, 0xAE60, 0x7521, 0xAE61, 0x7522, 0xAE62, 0x7523,
+	0xAE63, 0x7524, 0xAE64, 0x7526, 0xAE65, 0x7527, 0xAE66, 0x752A,
+	0xAE67, 0x752E, 0xAE68, 0x7534, 0xAE69, 0x7536, 0xAE6A, 0x7539,
+	0xAE6B, 0x753C, 0xAE6C, 0x753D, 0xAE6D, 0x753F, 0xAE6E, 0x7541,
+	0xAE6F, 0x7542, 0xAE70, 0x7543, 0xAE71, 0x7544, 0xAE72, 0x7546,
+	0xAE73, 0x7547, 0xAE74, 0x7549, 0xAE75, 0x754A, 0xAE76, 0x754D,
+	0xAE77, 0x7550, 0xAE78, 0x7551, 0xAE79, 0x7552, 0xAE7A, 0x7553,
+	0xAE7B, 0x7555, 0xAE7C, 0x7556, 0xAE7D, 0x7557, 0xAE7E, 0x7558,
+	0xAE80, 0x755D, 0xAE81, 0x755E, 0xAE82, 0x755F, 0xAE83, 0x7560,
+	0xAE84, 0x7561, 0xAE85, 0x7562, 0xAE86, 0x7563, 0xAE87, 0x7564,
+	0xAE88, 0x7567, 0xAE89, 0x7568, 0xAE8A, 0x7569, 0xAE8B, 0x756B,
+	0xAE8C, 0x756C, 0xAE8D, 0x756D, 0xAE8E, 0x756E, 0xAE8F, 0x756F,
+	0xAE90, 0x7570, 0xAE91, 0x7571, 0xAE92, 0x7573, 0xAE93, 0x7575,
+	0xAE94, 0x7576, 0xAE95, 0x7577, 0xAE96, 0x757A, 0xAE97, 0x757B,
+	0xAE98, 0x757C, 0xAE99, 0x757D, 0xAE9A, 0x757E, 0xAE9B, 0x7580,
+	0xAE9C, 0x7581, 0xAE9D, 0x7582, 0xAE9E, 0x7584, 0xAE9F, 0x7585,
+	0xAEA0, 0x7587, 0xAF40, 0x7588, 0xAF41, 0x7589, 0xAF42, 0x758A,
+	0xAF43, 0x758C, 0xAF44, 0x758D, 0xAF45, 0x758E, 0xAF46, 0x7590,
+	0xAF47, 0x7593, 0xAF48, 0x7595, 0xAF49, 0x7598, 0xAF4A, 0x759B,
+	0xAF4B, 0x759C, 0xAF4C, 0x759E, 0xAF4D, 0x75A2, 0xAF4E, 0x75A6,
+	0xAF4F, 0x75A7, 0xAF50, 0x75A8, 0xAF51, 0x75A9, 0xAF52, 0x75AA,
+	0xAF53, 0x75AD, 0xAF54, 0x75B6, 0xAF55, 0x75B7, 0xAF56, 0x75BA,
+	0xAF57, 0x75BB, 0xAF58, 0x75BF, 0xAF59, 0x75C0, 0xAF5A, 0x75C1,
+	0xAF5B, 0x75C6, 0xAF5C, 0x75CB, 0xAF5D, 0x75CC, 0xAF5E, 0x75CE,
+	0xAF5F, 0x75CF, 0xAF60, 0x75D0, 0xAF61, 0x75D1, 0xAF62, 0x75D3,
+	0xAF63, 0x75D7, 0xAF64, 0x75D9, 0xAF65, 0x75DA, 0xAF66, 0x75DC,
+	0xAF67, 0x75DD, 0xAF68, 0x75DF, 0xAF69, 0x75E0, 0xAF6A, 0x75E1,
+	0xAF6B, 0x75E5, 0xAF6C, 0x75E9, 0xAF6D, 0x75EC, 0xAF6E, 0x75ED,
+	0xAF6F, 0x75EE, 0xAF70, 0x75EF, 0xAF71, 0x75F2, 0xAF72, 0x75F3,
+	0xAF73, 0x75F5, 0xAF74, 0x75F6, 0xAF75, 0x75F7, 0xAF76, 0x75F8,
+	0xAF77, 0x75FA, 0xAF78, 0x75FB, 0xAF79, 0x75FD, 0xAF7A, 0x75FE,
+	0xAF7B, 0x7602, 0xAF7C, 0x7604, 0xAF7D, 0x7606, 0xAF7E, 0x7607,
+	0xAF80, 0x7608, 0xAF81, 0x7609, 0xAF82, 0x760B, 0xAF83, 0x760D,
+	0xAF84, 0x760E, 0xAF85, 0x760F, 0xAF86, 0x7611, 0xAF87, 0x7612,
+	0xAF88, 0x7613, 0xAF89, 0x7614, 0xAF8A, 0x7616, 0xAF8B, 0x761A,
+	0xAF8C, 0x761C, 0xAF8D, 0x761D, 0xAF8E, 0x761E, 0xAF8F, 0x7621,
+	0xAF90, 0x7623, 0xAF91, 0x7627, 0xAF92, 0x7628, 0xAF93, 0x762C,
+	0xAF94, 0x762E, 0xAF95, 0x762F, 0xAF96, 0x7631, 0xAF97, 0x7632,
+	0xAF98, 0x7636, 0xAF99, 0x7637, 0xAF9A, 0x7639, 0xAF9B, 0x763A,
+	0xAF9C, 0x763B, 0xAF9D, 0x763D, 0xAF9E, 0x7641, 0xAF9F, 0x7642,
+	0xAFA0, 0x7644, 0xB040, 0x7645, 0xB041, 0x7646, 0xB042, 0x7647,
+	0xB043, 0x7648, 0xB044, 0x7649, 0xB045, 0x764A, 0xB046, 0x764B,
+	0xB047, 0x764E, 0xB048, 0x764F, 0xB049, 0x7650, 0xB04A, 0x7651,
+	0xB04B, 0x7652, 0xB04C, 0x7653, 0xB04D, 0x7655, 0xB04E, 0x7657,
+	0xB04F, 0x7658, 0xB050, 0x7659, 0xB051, 0x765A, 0xB052, 0x765B,
+	0xB053, 0x765D, 0xB054, 0x765F, 0xB055, 0x7660, 0xB056, 0x7661,
+	0xB057, 0x7662, 0xB058, 0x7664, 0xB059, 0x7665, 0xB05A, 0x7666,
+	0xB05B, 0x7667, 0xB05C, 0x7668, 0xB05D, 0x7669, 0xB05E, 0x766A,
+	0xB05F, 0x766C, 0xB060, 0x766D, 0xB061, 0x766E, 0xB062, 0x7670,
+	0xB063, 0x7671, 0xB064, 0x7672, 0xB065, 0x7673, 0xB066, 0x7674,
+	0xB067, 0x7675, 0xB068, 0x7676, 0xB069, 0x7677, 0xB06A, 0x7679,
+	0xB06B, 0x767A, 0xB06C, 0x767C, 0xB06D, 0x767F, 0xB06E, 0x7680,
+	0xB06F, 0x7681, 0xB070, 0x7683, 0xB071, 0x7685, 0xB072, 0x7689,
+	0xB073, 0x768A, 0xB074, 0x768C, 0xB075, 0x768D, 0xB076, 0x768F,
+	0xB077, 0x7690, 0xB078, 0x7692, 0xB079, 0x7694, 0xB07A, 0x7695,
+	0xB07B, 0x7697, 0xB07C, 0x7698, 0xB07D, 0x769A, 0xB07E, 0x769B,
+	0xB080, 0x769C, 0xB081, 0x769D, 0xB082, 0x769E, 0xB083, 0x769F,
+	0xB084, 0x76A0, 0xB085, 0x76A1, 0xB086, 0x76A2, 0xB087, 0x76A3,
+	0xB088, 0x76A5, 0xB089, 0x76A6, 0xB08A, 0x76A7, 0xB08B, 0x76A8,
+	0xB08C, 0x76A9, 0xB08D, 0x76AA, 0xB08E, 0x76AB, 0xB08F, 0x76AC,
+	0xB090, 0x76AD, 0xB091, 0x76AF, 0xB092, 0x76B0, 0xB093, 0x76B3,
+	0xB094, 0x76B5, 0xB095, 0x76B6, 0xB096, 0x76B7, 0xB097, 0x76B8,
+	0xB098, 0x76B9, 0xB099, 0x76BA, 0xB09A, 0x76BB, 0xB09B, 0x76BC,
+	0xB09C, 0x76BD, 0xB09D, 0x76BE, 0xB09E, 0x76C0, 0xB09F, 0x76C1,
+	0xB0A0, 0x76C3, 0xB0A1, 0x554A, 0xB0A2, 0x963F, 0xB0A3, 0x57C3,
+	0xB0A4, 0x6328, 0xB0A5, 0x54CE, 0xB0A6, 0x5509, 0xB0A7, 0x54C0,
+	0xB0A8, 0x7691, 0xB0A9, 0x764C, 0xB0AA, 0x853C, 0xB0AB, 0x77EE,
+	0xB0AC, 0x827E, 0xB0AD, 0x788D, 0xB0AE, 0x7231, 0xB0AF, 0x9698,
+	0xB0B0, 0x978D, 0xB0B1, 0x6C28, 0xB0B2, 0x5B89, 0xB0B3, 0x4FFA,
+	0xB0B4, 0x6309, 0xB0B5, 0x6697, 0xB0B6, 0x5CB8, 0xB0B7, 0x80FA,
+	0xB0B8, 0x6848, 0xB0B9, 0x80AE, 0xB0BA, 0x6602, 0xB0BB, 0x76CE,
+	0xB0BC, 0x51F9, 0xB0BD, 0x6556, 0xB0BE, 0x71AC, 0xB0BF, 0x7FF1,
+	0xB0C0, 0x8884, 0xB0C1, 0x50B2, 0xB0C2, 0x5965, 0xB0C3, 0x61CA,
+	0xB0C4, 0x6FB3, 0xB0C5, 0x82AD, 0xB0C6, 0x634C, 0xB0C7, 0x6252,
+	0xB0C8, 0x53ED, 0xB0C9, 0x5427, 0xB0CA, 0x7B06, 0xB0CB, 0x516B,
+	0xB0CC, 0x75A4, 0xB0CD, 0x5DF4, 0xB0CE, 0x62D4, 0xB0CF, 0x8DCB,
+	0xB0D0, 0x9776, 0xB0D1, 0x628A, 0xB0D2, 0x8019, 0xB0D3, 0x575D,
+	0xB0D4, 0x9738, 0xB0D5, 0x7F62, 0xB0D6, 0x7238, 0xB0D7, 0x767D,
+	0xB0D8, 0x67CF, 0xB0D9, 0x767E, 0xB0DA, 0x6446, 0xB0DB, 0x4F70,
+	0xB0DC, 0x8D25, 0xB0DD, 0x62DC, 0xB0DE, 0x7A17, 0xB0DF, 0x6591,
+	0xB0E0, 0x73ED, 0xB0E1, 0x642C, 0xB0E2, 0x6273, 0xB0E3, 0x822C,
+	0xB0E4, 0x9881, 0xB0E5, 0x677F, 0xB0E6, 0x7248, 0xB0E7, 0x626E,
+	0xB0E8, 0x62CC, 0xB0E9, 0x4F34, 0xB0EA, 0x74E3, 0xB0EB, 0x534A,
+	0xB0EC, 0x529E, 0xB0ED, 0x7ECA, 0xB0EE, 0x90A6, 0xB0EF, 0x5E2E,
+	0xB0F0, 0x6886, 0xB0F1, 0x699C, 0xB0F2, 0x8180, 0xB0F3, 0x7ED1,
+	0xB0F4, 0x68D2, 0xB0F5, 0x78C5, 0xB0F6, 0x868C, 0xB0F7, 0x9551,
+	0xB0F8, 0x508D, 0xB0F9, 0x8C24, 0xB0FA, 0x82DE, 0xB0FB, 0x80DE,
+	0xB0FC, 0x5305, 0xB0FD, 0x8912, 0xB0FE, 0x5265, 0xB140, 0x76C4,
+	0xB141, 0x76C7, 0xB142, 0x76C9, 0xB143, 0x76CB, 0xB144, 0x76CC,
+	0xB145, 0x76D3, 0xB146, 0x76D5, 0xB147, 0x76D9, 0xB148, 0x76DA,
+	0xB149, 0x76DC, 0xB14A, 0x76DD, 0xB14B, 0x76DE, 0xB14C, 0x76E0,
+	0xB14D, 0x76E1, 0xB14E, 0x76E2, 0xB14F, 0x76E3, 0xB150, 0x76E4,
+	0xB151, 0x76E6, 0xB152, 0x76E7, 0xB153, 0x76E8, 0xB154, 0x76E9,
+	0xB155, 0x76EA, 0xB156, 0x76EB, 0xB157, 0x76EC, 0xB158, 0x76ED,
+	0xB159, 0x76F0, 0xB15A, 0x76F3, 0xB15B, 0x76F5, 0xB15C, 0x76F6,
+	0xB15D, 0x76F7, 0xB15E, 0x76FA, 0xB15F, 0x76FB, 0xB160, 0x76FD,
+	0xB161, 0x76FF, 0xB162, 0x7700, 0xB163, 0x7702, 0xB164, 0x7703,
+	0xB165, 0x7705, 0xB166, 0x7706, 0xB167, 0x770A, 0xB168, 0x770C,
+	0xB169, 0x770E, 0xB16A, 0x770F, 0xB16B, 0x7710, 0xB16C, 0x7711,
+	0xB16D, 0x7712, 0xB16E, 0x7713, 0xB16F, 0x7714, 0xB170, 0x7715,
+	0xB171, 0x7716, 0xB172, 0x7717, 0xB173, 0x7718, 0xB174, 0x771B,
+	0xB175, 0x771C, 0xB176, 0x771D, 0xB177, 0x771E, 0xB178, 0x7721,
+	0xB179, 0x7723, 0xB17A, 0x7724, 0xB17B, 0x7725, 0xB17C, 0x7727,
+	0xB17D, 0x772A, 0xB17E, 0x772B, 0xB180, 0x772C, 0xB181, 0x772E,
+	0xB182, 0x7730, 0xB183, 0x7731, 0xB184, 0x7732, 0xB185, 0x7733,
+	0xB186, 0x7734, 0xB187, 0x7739, 0xB188, 0x773B, 0xB189, 0x773D,
+	0xB18A, 0x773E, 0xB18B, 0x773F, 0xB18C, 0x7742, 0xB18D, 0x7744,
+	0xB18E, 0x7745, 0xB18F, 0x7746, 0xB190, 0x7748, 0xB191, 0x7749,
+	0xB192, 0x774A, 0xB193, 0x774B, 0xB194, 0x774C, 0xB195, 0x774D,
+	0xB196, 0x774E, 0xB197, 0x774F, 0xB198, 0x7752, 0xB199, 0x7753,
+	0xB19A, 0x7754, 0xB19B, 0x7755, 0xB19C, 0x7756, 0xB19D, 0x7757,
+	0xB19E, 0x7758, 0xB19F, 0x7759, 0xB1A0, 0x775C, 0xB1A1, 0x8584,
+	0xB1A2, 0x96F9, 0xB1A3, 0x4FDD, 0xB1A4, 0x5821, 0xB1A5, 0x9971,
+	0xB1A6, 0x5B9D, 0xB1A7, 0x62B1, 0xB1A8, 0x62A5, 0xB1A9, 0x66B4,
+	0xB1AA, 0x8C79, 0xB1AB, 0x9C8D, 0xB1AC, 0x7206, 0xB1AD, 0x676F,
+	0xB1AE, 0x7891, 0xB1AF, 0x60B2, 0xB1B0, 0x5351, 0xB1B1, 0x5317,
+	0xB1B2, 0x8F88, 0xB1B3, 0x80CC, 0xB1B4, 0x8D1D, 0xB1B5, 0x94A1,
+	0xB1B6, 0x500D, 0xB1B7, 0x72C8, 0xB1B8, 0x5907, 0xB1B9, 0x60EB,
+	0xB1BA, 0x7119, 0xB1BB, 0x88AB, 0xB1BC, 0x5954, 0xB1BD, 0x82EF,
+	0xB1BE, 0x672C, 0xB1BF, 0x7B28, 0xB1C0, 0x5D29, 0xB1C1, 0x7EF7,
+	0xB1C2, 0x752D, 0xB1C3, 0x6CF5, 0xB1C4, 0x8E66, 0xB1C5, 0x8FF8,
+	0xB1C6, 0x903C, 0xB1C7, 0x9F3B, 0xB1C8, 0x6BD4, 0xB1C9, 0x9119,
+	0xB1CA, 0x7B14, 0xB1CB, 0x5F7C, 0xB1CC, 0x78A7, 0xB1CD, 0x84D6,
+	0xB1CE, 0x853D, 0xB1CF, 0x6BD5, 0xB1D0, 0x6BD9, 0xB1D1, 0x6BD6,
+	0xB1D2, 0x5E01, 0xB1D3, 0x5E87, 0xB1D4, 0x75F9, 0xB1D5, 0x95ED,
+	0xB1D6, 0x655D, 0xB1D7, 0x5F0A, 0xB1D8, 0x5FC5, 0xB1D9, 0x8F9F,
+	0xB1DA, 0x58C1, 0xB1DB, 0x81C2, 0xB1DC, 0x907F, 0xB1DD, 0x965B,
+	0xB1DE, 0x97AD, 0xB1DF, 0x8FB9, 0xB1E0, 0x7F16, 0xB1E1, 0x8D2C,
+	0xB1E2, 0x6241, 0xB1E3, 0x4FBF, 0xB1E4, 0x53D8, 0xB1E5, 0x535E,
+	0xB1E6, 0x8FA8, 0xB1E7, 0x8FA9, 0xB1E8, 0x8FAB, 0xB1E9, 0x904D,
+	0xB1EA, 0x6807, 0xB1EB, 0x5F6A, 0xB1EC, 0x8198, 0xB1ED, 0x8868,
+	0xB1EE, 0x9CD6, 0xB1EF, 0x618B, 0xB1F0, 0x522B, 0xB1F1, 0x762A,
+	0xB1F2, 0x5F6C, 0xB1F3, 0x658C, 0xB1F4, 0x6FD2, 0xB1F5, 0x6EE8,
+	0xB1F6, 0x5BBE, 0xB1F7, 0x6448, 0xB1F8, 0x5175, 0xB1F9, 0x51B0,
+	0xB1FA, 0x67C4, 0xB1FB, 0x4E19, 0xB1FC, 0x79C9, 0xB1FD, 0x997C,
+	0xB1FE, 0x70B3, 0xB240, 0x775D, 0xB241, 0x775E, 0xB242, 0x775F,
+	0xB243, 0x7760, 0xB244, 0x7764, 0xB245, 0x7767, 0xB246, 0x7769,
+	0xB247, 0x776A, 0xB248, 0x776D, 0xB249, 0x776E, 0xB24A, 0x776F,
+	0xB24B, 0x7770, 0xB24C, 0x7771, 0xB24D, 0x7772, 0xB24E, 0x7773,
+	0xB24F, 0x7774, 0xB250, 0x7775, 0xB251, 0x7776, 0xB252, 0x7777,
+	0xB253, 0x7778, 0xB254, 0x777A, 0xB255, 0x777B, 0xB256, 0x777C,
+	0xB257, 0x7781, 0xB258, 0x7782, 0xB259, 0x7783, 0xB25A, 0x7786,
+	0xB25B, 0x7787, 0xB25C, 0x7788, 0xB25D, 0x7789, 0xB25E, 0x778A,
+	0xB25F, 0x778B, 0xB260, 0x778F, 0xB261, 0x7790, 0xB262, 0x7793,
+	0xB263, 0x7794, 0xB264, 0x7795, 0xB265, 0x7796, 0xB266, 0x7797,
+	0xB267, 0x7798, 0xB268, 0x7799, 0xB269, 0x779A, 0xB26A, 0x779B,
+	0xB26B, 0x779C, 0xB26C, 0x779D, 0xB26D, 0x779E, 0xB26E, 0x77A1,
+	0xB26F, 0x77A3, 0xB270, 0x77A4, 0xB271, 0x77A6, 0xB272, 0x77A8,
+	0xB273, 0x77AB, 0xB274, 0x77AD, 0xB275, 0x77AE, 0xB276, 0x77AF,
+	0xB277, 0x77B1, 0xB278, 0x77B2, 0xB279, 0x77B4, 0xB27A, 0x77B6,
+	0xB27B, 0x77B7, 0xB27C, 0x77B8, 0xB27D, 0x77B9, 0xB27E, 0x77BA,
+	0xB280, 0x77BC, 0xB281, 0x77BE, 0xB282, 0x77C0, 0xB283, 0x77C1,
+	0xB284, 0x77C2, 0xB285, 0x77C3, 0xB286, 0x77C4, 0xB287, 0x77C5,
+	0xB288, 0x77C6, 0xB289, 0x77C7, 0xB28A, 0x77C8, 0xB28B, 0x77C9,
+	0xB28C, 0x77CA, 0xB28D, 0x77CB, 0xB28E, 0x77CC, 0xB28F, 0x77CE,
+	0xB290, 0x77CF, 0xB291, 0x77D0, 0xB292, 0x77D1, 0xB293, 0x77D2,
+	0xB294, 0x77D3, 0xB295, 0x77D4, 0xB296, 0x77D5, 0xB297, 0x77D6,
+	0xB298, 0x77D8, 0xB299, 0x77D9, 0xB29A, 0x77DA, 0xB29B, 0x77DD,
+	0xB29C, 0x77DE, 0xB29D, 0x77DF, 0xB29E, 0x77E0, 0xB29F, 0x77E1,
+	0xB2A0, 0x77E4, 0xB2A1, 0x75C5, 0xB2A2, 0x5E76, 0xB2A3, 0x73BB,
+	0xB2A4, 0x83E0, 0xB2A5, 0x64AD, 0xB2A6, 0x62E8, 0xB2A7, 0x94B5,
+	0xB2A8, 0x6CE2, 0xB2A9, 0x535A, 0xB2AA, 0x52C3, 0xB2AB, 0x640F,
+	0xB2AC, 0x94C2, 0xB2AD, 0x7B94, 0xB2AE, 0x4F2F, 0xB2AF, 0x5E1B,
+	0xB2B0, 0x8236, 0xB2B1, 0x8116, 0xB2B2, 0x818A, 0xB2B3, 0x6E24,
+	0xB2B4, 0x6CCA, 0xB2B5, 0x9A73, 0xB2B6, 0x6355, 0xB2B7, 0x535C,
+	0xB2B8, 0x54FA, 0xB2B9, 0x8865, 0xB2BA, 0x57E0, 0xB2BB, 0x4E0D,
+	0xB2BC, 0x5E03, 0xB2BD, 0x6B65, 0xB2BE, 0x7C3F, 0xB2BF, 0x90E8,
+	0xB2C0, 0x6016, 0xB2C1, 0x64E6, 0xB2C2, 0x731C, 0xB2C3, 0x88C1,
+	0xB2C4, 0x6750, 0xB2C5, 0x624D, 0xB2C6, 0x8D22, 0xB2C7, 0x776C,
+	0xB2C8, 0x8E29, 0xB2C9, 0x91C7, 0xB2CA, 0x5F69, 0xB2CB, 0x83DC,
+	0xB2CC, 0x8521, 0xB2CD, 0x9910, 0xB2CE, 0x53C2, 0xB2CF, 0x8695,
+	0xB2D0, 0x6B8B, 0xB2D1, 0x60ED, 0xB2D2, 0x60E8, 0xB2D3, 0x707F,
+	0xB2D4, 0x82CD, 0xB2D5, 0x8231, 0xB2D6, 0x4ED3, 0xB2D7, 0x6CA7,
+	0xB2D8, 0x85CF, 0xB2D9, 0x64CD, 0xB2DA, 0x7CD9, 0xB2DB, 0x69FD,
+	0xB2DC, 0x66F9, 0xB2DD, 0x8349, 0xB2DE, 0x5395, 0xB2DF, 0x7B56,
+	0xB2E0, 0x4FA7, 0xB2E1, 0x518C, 0xB2E2, 0x6D4B, 0xB2E3, 0x5C42,
+	0xB2E4, 0x8E6D, 0xB2E5, 0x63D2, 0xB2E6, 0x53C9, 0xB2E7, 0x832C,
+	0xB2E8, 0x8336, 0xB2E9, 0x67E5, 0xB2EA, 0x78B4, 0xB2EB, 0x643D,
+	0xB2EC, 0x5BDF, 0xB2ED, 0x5C94, 0xB2EE, 0x5DEE, 0xB2EF, 0x8BE7,
+	0xB2F0, 0x62C6, 0xB2F1, 0x67F4, 0xB2F2, 0x8C7A, 0xB2F3, 0x6400,
+	0xB2F4, 0x63BA, 0xB2F5, 0x8749, 0xB2F6, 0x998B, 0xB2F7, 0x8C17,
+	0xB2F8, 0x7F20, 0xB2F9, 0x94F2, 0xB2FA, 0x4EA7, 0xB2FB, 0x9610,
+	0xB2FC, 0x98A4, 0xB2FD, 0x660C, 0xB2FE, 0x7316, 0xB340, 0x77E6,
+	0xB341, 0x77E8, 0xB342, 0x77EA, 0xB343, 0x77EF, 0xB344, 0x77F0,
+	0xB345, 0x77F1, 0xB346, 0x77F2, 0xB347, 0x77F4, 0xB348, 0x77F5,
+	0xB349, 0x77F7, 0xB34A, 0x77F9, 0xB34B, 0x77FA, 0xB34C, 0x77FB,
+	0xB34D, 0x77FC, 0xB34E, 0x7803, 0xB34F, 0x7804, 0xB350, 0x7805,
+	0xB351, 0x7806, 0xB352, 0x7807, 0xB353, 0x7808, 0xB354, 0x780A,
+	0xB355, 0x780B, 0xB356, 0x780E, 0xB357, 0x780F, 0xB358, 0x7810,
+	0xB359, 0x7813, 0xB35A, 0x7815, 0xB35B, 0x7819, 0xB35C, 0x781B,
+	0xB35D, 0x781E, 0xB35E, 0x7820, 0xB35F, 0x7821, 0xB360, 0x7822,
+	0xB361, 0x7824, 0xB362, 0x7828, 0xB363, 0x782A, 0xB364, 0x782B,
+	0xB365, 0x782E, 0xB366, 0x782F, 0xB367, 0x7831, 0xB368, 0x7832,
+	0xB369, 0x7833, 0xB36A, 0x7835, 0xB36B, 0x7836, 0xB36C, 0x783D,
+	0xB36D, 0x783F, 0xB36E, 0x7841, 0xB36F, 0x7842, 0xB370, 0x7843,
+	0xB371, 0x7844, 0xB372, 0x7846, 0xB373, 0x7848, 0xB374, 0x7849,
+	0xB375, 0x784A, 0xB376, 0x784B, 0xB377, 0x784D, 0xB378, 0x784F,
+	0xB379, 0x7851, 0xB37A, 0x7853, 0xB37B, 0x7854, 0xB37C, 0x7858,
+	0xB37D, 0x7859, 0xB37E, 0x785A, 0xB380, 0x785B, 0xB381, 0x785C,
+	0xB382, 0x785E, 0xB383, 0x785F, 0xB384, 0x7860, 0xB385, 0x7861,
+	0xB386, 0x7862, 0xB387, 0x7863, 0xB388, 0x7864, 0xB389, 0x7865,
+	0xB38A, 0x7866, 0xB38B, 0x7867, 0xB38C, 0x7868, 0xB38D, 0x7869,
+	0xB38E, 0x786F, 0xB38F, 0x7870, 0xB390, 0x7871, 0xB391, 0x7872,
+	0xB392, 0x7873, 0xB393, 0x7874, 0xB394, 0x7875, 0xB395, 0x7876,
+	0xB396, 0x7878, 0xB397, 0x7879, 0xB398, 0x787A, 0xB399, 0x787B,
+	0xB39A, 0x787D, 0xB39B, 0x787E, 0xB39C, 0x787F, 0xB39D, 0x7880,
+	0xB39E, 0x7881, 0xB39F, 0x7882, 0xB3A0, 0x7883, 0xB3A1, 0x573A,
+	0xB3A2, 0x5C1D, 0xB3A3, 0x5E38, 0xB3A4, 0x957F, 0xB3A5, 0x507F,
+	0xB3A6, 0x80A0, 0xB3A7, 0x5382, 0xB3A8, 0x655E, 0xB3A9, 0x7545,
+	0xB3AA, 0x5531, 0xB3AB, 0x5021, 0xB3AC, 0x8D85, 0xB3AD, 0x6284,
+	0xB3AE, 0x949E, 0xB3AF, 0x671D, 0xB3B0, 0x5632, 0xB3B1, 0x6F6E,
+	0xB3B2, 0x5DE2, 0xB3B3, 0x5435, 0xB3B4, 0x7092, 0xB3B5, 0x8F66,
+	0xB3B6, 0x626F, 0xB3B7, 0x64A4, 0xB3B8, 0x63A3, 0xB3B9, 0x5F7B,
+	0xB3BA, 0x6F88, 0xB3BB, 0x90F4, 0xB3BC, 0x81E3, 0xB3BD, 0x8FB0,
+	0xB3BE, 0x5C18, 0xB3BF, 0x6668, 0xB3C0, 0x5FF1, 0xB3C1, 0x6C89,
+	0xB3C2, 0x9648, 0xB3C3, 0x8D81, 0xB3C4, 0x886C, 0xB3C5, 0x6491,
+	0xB3C6, 0x79F0, 0xB3C7, 0x57CE, 0xB3C8, 0x6A59, 0xB3C9, 0x6210,
+	0xB3CA, 0x5448, 0xB3CB, 0x4E58, 0xB3CC, 0x7A0B, 0xB3CD, 0x60E9,
+	0xB3CE, 0x6F84, 0xB3CF, 0x8BDA, 0xB3D0, 0x627F, 0xB3D1, 0x901E,
+	0xB3D2, 0x9A8B, 0xB3D3, 0x79E4, 0xB3D4, 0x5403, 0xB3D5, 0x75F4,
+	0xB3D6, 0x6301, 0xB3D7, 0x5319, 0xB3D8, 0x6C60, 0xB3D9, 0x8FDF,
+	0xB3DA, 0x5F1B, 0xB3DB, 0x9A70, 0xB3DC, 0x803B, 0xB3DD, 0x9F7F,
+	0xB3DE, 0x4F88, 0xB3DF, 0x5C3A, 0xB3E0, 0x8D64, 0xB3E1, 0x7FC5,
+	0xB3E2, 0x65A5, 0xB3E3, 0x70BD, 0xB3E4, 0x5145, 0xB3E5, 0x51B2,
+	0xB3E6, 0x866B, 0xB3E7, 0x5D07, 0xB3E8, 0x5BA0, 0xB3E9, 0x62BD,
+	0xB3EA, 0x916C, 0xB3EB, 0x7574, 0xB3EC, 0x8E0C, 0xB3ED, 0x7A20,
+	0xB3EE, 0x6101, 0xB3EF, 0x7B79, 0xB3F0, 0x4EC7, 0xB3F1, 0x7EF8,
+	0xB3F2, 0x7785, 0xB3F3, 0x4E11, 0xB3F4, 0x81ED, 0xB3F5, 0x521D,
+	0xB3F6, 0x51FA, 0xB3F7, 0x6A71, 0xB3F8, 0x53A8, 0xB3F9, 0x8E87,
+	0xB3FA, 0x9504, 0xB3FB, 0x96CF, 0xB3FC, 0x6EC1, 0xB3FD, 0x9664,
+	0xB3FE, 0x695A, 0xB440, 0x7884, 0xB441, 0x7885, 0xB442, 0x7886,
+	0xB443, 0x7888, 0xB444, 0x788A, 0xB445, 0x788B, 0xB446, 0x788F,
+	0xB447, 0x7890, 0xB448, 0x7892, 0xB449, 0x7894, 0xB44A, 0x7895,
+	0xB44B, 0x7896, 0xB44C, 0x7899, 0xB44D, 0x789D, 0xB44E, 0x789E,
+	0xB44F, 0x78A0, 0xB450, 0x78A2, 0xB451, 0x78A4, 0xB452, 0x78A6,
+	0xB453, 0x78A8, 0xB454, 0x78A9, 0xB455, 0x78AA, 0xB456, 0x78AB,
+	0xB457, 0x78AC, 0xB458, 0x78AD, 0xB459, 0x78AE, 0xB45A, 0x78AF,
+	0xB45B, 0x78B5, 0xB45C, 0x78B6, 0xB45D, 0x78B7, 0xB45E, 0x78B8,
+	0xB45F, 0x78BA, 0xB460, 0x78BB, 0xB461, 0x78BC, 0xB462, 0x78BD,
+	0xB463, 0x78BF, 0xB464, 0x78C0, 0xB465, 0x78C2, 0xB466, 0x78C3,
+	0xB467, 0x78C4, 0xB468, 0x78C6, 0xB469, 0x78C7, 0xB46A, 0x78C8,
+	0xB46B, 0x78CC, 0xB46C, 0x78CD, 0xB46D, 0x78CE, 0xB46E, 0x78CF,
+	0xB46F, 0x78D1, 0xB470, 0x78D2, 0xB471, 0x78D3, 0xB472, 0x78D6,
+	0xB473, 0x78D7, 0xB474, 0x78D8, 0xB475, 0x78DA, 0xB476, 0x78DB,
+	0xB477, 0x78DC, 0xB478, 0x78DD, 0xB479, 0x78DE, 0xB47A, 0x78DF,
+	0xB47B, 0x78E0, 0xB47C, 0x78E1, 0xB47D, 0x78E2, 0xB47E, 0x78E3,
+	0xB480, 0x78E4, 0xB481, 0x78E5, 0xB482, 0x78E6, 0xB483, 0x78E7,
+	0xB484, 0x78E9, 0xB485, 0x78EA, 0xB486, 0x78EB, 0xB487, 0x78ED,
+	0xB488, 0x78EE, 0xB489, 0x78EF, 0xB48A, 0x78F0, 0xB48B, 0x78F1,
+	0xB48C, 0x78F3, 0xB48D, 0x78F5, 0xB48E, 0x78F6, 0xB48F, 0x78F8,
+	0xB490, 0x78F9, 0xB491, 0x78FB, 0xB492, 0x78FC, 0xB493, 0x78FD,
+	0xB494, 0x78FE, 0xB495, 0x78FF, 0xB496, 0x7900, 0xB497, 0x7902,
+	0xB498, 0x7903, 0xB499, 0x7904, 0xB49A, 0x7906, 0xB49B, 0x7907,
+	0xB49C, 0x7908, 0xB49D, 0x7909, 0xB49E, 0x790A, 0xB49F, 0x790B,
+	0xB4A0, 0x790C, 0xB4A1, 0x7840, 0xB4A2, 0x50A8, 0xB4A3, 0x77D7,
+	0xB4A4, 0x6410, 0xB4A5, 0x89E6, 0xB4A6, 0x5904, 0xB4A7, 0x63E3,
+	0xB4A8, 0x5DDD, 0xB4A9, 0x7A7F, 0xB4AA, 0x693D, 0xB4AB, 0x4F20,
+	0xB4AC, 0x8239, 0xB4AD, 0x5598, 0xB4AE, 0x4E32, 0xB4AF, 0x75AE,
+	0xB4B0, 0x7A97, 0xB4B1, 0x5E62, 0xB4B2, 0x5E8A, 0xB4B3, 0x95EF,
+	0xB4B4, 0x521B, 0xB4B5, 0x5439, 0xB4B6, 0x708A, 0xB4B7, 0x6376,
+	0xB4B8, 0x9524, 0xB4B9, 0x5782, 0xB4BA, 0x6625, 0xB4BB, 0x693F,
+	0xB4BC, 0x9187, 0xB4BD, 0x5507, 0xB4BE, 0x6DF3, 0xB4BF, 0x7EAF,
+	0xB4C0, 0x8822, 0xB4C1, 0x6233, 0xB4C2, 0x7EF0, 0xB4C3, 0x75B5,
+	0xB4C4, 0x8328, 0xB4C5, 0x78C1, 0xB4C6, 0x96CC, 0xB4C7, 0x8F9E,
+	0xB4C8, 0x6148, 0xB4C9, 0x74F7, 0xB4CA, 0x8BCD, 0xB4CB, 0x6B64,
+	0xB4CC, 0x523A, 0xB4CD, 0x8D50, 0xB4CE, 0x6B21, 0xB4CF, 0x806A,
+	0xB4D0, 0x8471, 0xB4D1, 0x56F1, 0xB4D2, 0x5306, 0xB4D3, 0x4ECE,
+	0xB4D4, 0x4E1B, 0xB4D5, 0x51D1, 0xB4D6, 0x7C97, 0xB4D7, 0x918B,
+	0xB4D8, 0x7C07, 0xB4D9, 0x4FC3, 0xB4DA, 0x8E7F, 0xB4DB, 0x7BE1,
+	0xB4DC, 0x7A9C, 0xB4DD, 0x6467, 0xB4DE, 0x5D14, 0xB4DF, 0x50AC,
+	0xB4E0, 0x8106, 0xB4E1, 0x7601, 0xB4E2, 0x7CB9, 0xB4E3, 0x6DEC,
+	0xB4E4, 0x7FE0, 0xB4E5, 0x6751, 0xB4E6, 0x5B58, 0xB4E7, 0x5BF8,
+	0xB4E8, 0x78CB, 0xB4E9, 0x64AE, 0xB4EA, 0x6413, 0xB4EB, 0x63AA,
+	0xB4EC, 0x632B, 0xB4ED, 0x9519, 0xB4EE, 0x642D, 0xB4EF, 0x8FBE,
+	0xB4F0, 0x7B54, 0xB4F1, 0x7629, 0xB4F2, 0x6253, 0xB4F3, 0x5927,
+	0xB4F4, 0x5446, 0xB4F5, 0x6B79, 0xB4F6, 0x50A3, 0xB4F7, 0x6234,
+	0xB4F8, 0x5E26, 0xB4F9, 0x6B86, 0xB4FA, 0x4EE3, 0xB4FB, 0x8D37,
+	0xB4FC, 0x888B, 0xB4FD, 0x5F85, 0xB4FE, 0x902E, 0xB540, 0x790D,
+	0xB541, 0x790E, 0xB542, 0x790F, 0xB543, 0x7910, 0xB544, 0x7911,
+	0xB545, 0x7912, 0xB546, 0x7914, 0xB547, 0x7915, 0xB548, 0x7916,
+	0xB549, 0x7917, 0xB54A, 0x7918, 0xB54B, 0x7919, 0xB54C, 0x791A,
+	0xB54D, 0x791B, 0xB54E, 0x791C, 0xB54F, 0x791D, 0xB550, 0x791F,
+	0xB551, 0x7920, 0xB552, 0x7921, 0xB553, 0x7922, 0xB554, 0x7923,
+	0xB555, 0x7925, 0xB556, 0x7926, 0xB557, 0x7927, 0xB558, 0x7928,
+	0xB559, 0x7929, 0xB55A, 0x792A, 0xB55B, 0x792B, 0xB55C, 0x792C,
+	0xB55D, 0x792D, 0xB55E, 0x792E, 0xB55F, 0x792F, 0xB560, 0x7930,
+	0xB561, 0x7931, 0xB562, 0x7932, 0xB563, 0x7933, 0xB564, 0x7935,
+	0xB565, 0x7936, 0xB566, 0x7937, 0xB567, 0x7938, 0xB568, 0x7939,
+	0xB569, 0x793D, 0xB56A, 0x793F, 0xB56B, 0x7942, 0xB56C, 0x7943,
+	0xB56D, 0x7944, 0xB56E, 0x7945, 0xB56F, 0x7947, 0xB570, 0x794A,
+	0xB571, 0x794B, 0xB572, 0x794C, 0xB573, 0x794D, 0xB574, 0x794E,
+	0xB575, 0x794F, 0xB576, 0x7950, 0xB577, 0x7951, 0xB578, 0x7952,
+	0xB579, 0x7954, 0xB57A, 0x7955, 0xB57B, 0x7958, 0xB57C, 0x7959,
+	0xB57D, 0x7961, 0xB57E, 0x7963, 0xB580, 0x7964, 0xB581, 0x7966,
+	0xB582, 0x7969, 0xB583, 0x796A, 0xB584, 0x796B, 0xB585, 0x796C,
+	0xB586, 0x796E, 0xB587, 0x7970, 0xB588, 0x7971, 0xB589, 0x7972,
+	0xB58A, 0x7973, 0xB58B, 0x7974, 0xB58C, 0x7975, 0xB58D, 0x7976,
+	0xB58E, 0x7979, 0xB58F, 0x797B, 0xB590, 0x797C, 0xB591, 0x797D,
+	0xB592, 0x797E, 0xB593, 0x797F, 0xB594, 0x7982, 0xB595, 0x7983,
+	0xB596, 0x7986, 0xB597, 0x7987, 0xB598, 0x7988, 0xB599, 0x7989,
+	0xB59A, 0x798B, 0xB59B, 0x798C, 0xB59C, 0x798D, 0xB59D, 0x798E,
+	0xB59E, 0x7990, 0xB59F, 0x7991, 0xB5A0, 0x7992, 0xB5A1, 0x6020,
+	0xB5A2, 0x803D, 0xB5A3, 0x62C5, 0xB5A4, 0x4E39, 0xB5A5, 0x5355,
+	0xB5A6, 0x90F8, 0xB5A7, 0x63B8, 0xB5A8, 0x80C6, 0xB5A9, 0x65E6,
+	0xB5AA, 0x6C2E, 0xB5AB, 0x4F46, 0xB5AC, 0x60EE, 0xB5AD, 0x6DE1,
+	0xB5AE, 0x8BDE, 0xB5AF, 0x5F39, 0xB5B0, 0x86CB, 0xB5B1, 0x5F53,
+	0xB5B2, 0x6321, 0xB5B3, 0x515A, 0xB5B4, 0x8361, 0xB5B5, 0x6863,
+	0xB5B6, 0x5200, 0xB5B7, 0x6363, 0xB5B8, 0x8E48, 0xB5B9, 0x5012,
+	0xB5BA, 0x5C9B, 0xB5BB, 0x7977, 0xB5BC, 0x5BFC, 0xB5BD, 0x5230,
+	0xB5BE, 0x7A3B, 0xB5BF, 0x60BC, 0xB5C0, 0x9053, 0xB5C1, 0x76D7,
+	0xB5C2, 0x5FB7, 0xB5C3, 0x5F97, 0xB5C4, 0x7684, 0xB5C5, 0x8E6C,
+	0xB5C6, 0x706F, 0xB5C7, 0x767B, 0xB5C8, 0x7B49, 0xB5C9, 0x77AA,
+	0xB5CA, 0x51F3, 0xB5CB, 0x9093, 0xB5CC, 0x5824, 0xB5CD, 0x4F4E,
+	0xB5CE, 0x6EF4, 0xB5CF, 0x8FEA, 0xB5D0, 0x654C, 0xB5D1, 0x7B1B,
+	0xB5D2, 0x72C4, 0xB5D3, 0x6DA4, 0xB5D4, 0x7FDF, 0xB5D5, 0x5AE1,
+	0xB5D6, 0x62B5, 0xB5D7, 0x5E95, 0xB5D8, 0x5730, 0xB5D9, 0x8482,
+	0xB5DA, 0x7B2C, 0xB5DB, 0x5E1D, 0xB5DC, 0x5F1F, 0xB5DD, 0x9012,
+	0xB5DE, 0x7F14, 0xB5DF, 0x98A0, 0xB5E0, 0x6382, 0xB5E1, 0x6EC7,
+	0xB5E2, 0x7898, 0xB5E3, 0x70B9, 0xB5E4, 0x5178, 0xB5E5, 0x975B,
+	0xB5E6, 0x57AB, 0xB5E7, 0x7535, 0xB5E8, 0x4F43, 0xB5E9, 0x7538,
+	0xB5EA, 0x5E97, 0xB5EB, 0x60E6, 0xB5EC, 0x5960, 0xB5ED, 0x6DC0,
+	0xB5EE, 0x6BBF, 0xB5EF, 0x7889, 0xB5F0, 0x53FC, 0xB5F1, 0x96D5,
+	0xB5F2, 0x51CB, 0xB5F3, 0x5201, 0xB5F4, 0x6389, 0xB5F5, 0x540A,
+	0xB5F6, 0x9493, 0xB5F7, 0x8C03, 0xB5F8, 0x8DCC, 0xB5F9, 0x7239,
+	0xB5FA, 0x789F, 0xB5FB, 0x8776, 0xB5FC, 0x8FED, 0xB5FD, 0x8C0D,
+	0xB5FE, 0x53E0, 0xB640, 0x7993, 0xB641, 0x7994, 0xB642, 0x7995,
+	0xB643, 0x7996, 0xB644, 0x7997, 0xB645, 0x7998, 0xB646, 0x7999,
+	0xB647, 0x799B, 0xB648, 0x799C, 0xB649, 0x799D, 0xB64A, 0x799E,
+	0xB64B, 0x799F, 0xB64C, 0x79A0, 0xB64D, 0x79A1, 0xB64E, 0x79A2,
+	0xB64F, 0x79A3, 0xB650, 0x79A4, 0xB651, 0x79A5, 0xB652, 0x79A6,
+	0xB653, 0x79A8, 0xB654, 0x79A9, 0xB655, 0x79AA, 0xB656, 0x79AB,
+	0xB657, 0x79AC, 0xB658, 0x79AD, 0xB659, 0x79AE, 0xB65A, 0x79AF,
+	0xB65B, 0x79B0, 0xB65C, 0x79B1, 0xB65D, 0x79B2, 0xB65E, 0x79B4,
+	0xB65F, 0x79B5, 0xB660, 0x79B6, 0xB661, 0x79B7, 0xB662, 0x79B8,
+	0xB663, 0x79BC, 0xB664, 0x79BF, 0xB665, 0x79C2, 0xB666, 0x79C4,
+	0xB667, 0x79C5, 0xB668, 0x79C7, 0xB669, 0x79C8, 0xB66A, 0x79CA,
+	0xB66B, 0x79CC, 0xB66C, 0x79CE, 0xB66D, 0x79CF, 0xB66E, 0x79D0,
+	0xB66F, 0x79D3, 0xB670, 0x79D4, 0xB671, 0x79D6, 0xB672, 0x79D7,
+	0xB673, 0x79D9, 0xB674, 0x79DA, 0xB675, 0x79DB, 0xB676, 0x79DC,
+	0xB677, 0x79DD, 0xB678, 0x79DE, 0xB679, 0x79E0, 0xB67A, 0x79E1,
+	0xB67B, 0x79E2, 0xB67C, 0x79E5, 0xB67D, 0x79E8, 0xB67E, 0x79EA,
+	0xB680, 0x79EC, 0xB681, 0x79EE, 0xB682, 0x79F1, 0xB683, 0x79F2,
+	0xB684, 0x79F3, 0xB685, 0x79F4, 0xB686, 0x79F5, 0xB687, 0x79F6,
+	0xB688, 0x79F7, 0xB689, 0x79F9, 0xB68A, 0x79FA, 0xB68B, 0x79FC,
+	0xB68C, 0x79FE, 0xB68D, 0x79FF, 0xB68E, 0x7A01, 0xB68F, 0x7A04,
+	0xB690, 0x7A05, 0xB691, 0x7A07, 0xB692, 0x7A08, 0xB693, 0x7A09,
+	0xB694, 0x7A0A, 0xB695, 0x7A0C, 0xB696, 0x7A0F, 0xB697, 0x7A10,
+	0xB698, 0x7A11, 0xB699, 0x7A12, 0xB69A, 0x7A13, 0xB69B, 0x7A15,
+	0xB69C, 0x7A16, 0xB69D, 0x7A18, 0xB69E, 0x7A19, 0xB69F, 0x7A1B,
+	0xB6A0, 0x7A1C, 0xB6A1, 0x4E01, 0xB6A2, 0x76EF, 0xB6A3, 0x53EE,
+	0xB6A4, 0x9489, 0xB6A5, 0x9876, 0xB6A6, 0x9F0E, 0xB6A7, 0x952D,
+	0xB6A8, 0x5B9A, 0xB6A9, 0x8BA2, 0xB6AA, 0x4E22, 0xB6AB, 0x4E1C,
+	0xB6AC, 0x51AC, 0xB6AD, 0x8463, 0xB6AE, 0x61C2, 0xB6AF, 0x52A8,
+	0xB6B0, 0x680B, 0xB6B1, 0x4F97, 0xB6B2, 0x606B, 0xB6B3, 0x51BB,
+	0xB6B4, 0x6D1E, 0xB6B5, 0x515C, 0xB6B6, 0x6296, 0xB6B7, 0x6597,
+	0xB6B8, 0x9661, 0xB6B9, 0x8C46, 0xB6BA, 0x9017, 0xB6BB, 0x75D8,
+	0xB6BC, 0x90FD, 0xB6BD, 0x7763, 0xB6BE, 0x6BD2, 0xB6BF, 0x728A,
+	0xB6C0, 0x72EC, 0xB6C1, 0x8BFB, 0xB6C2, 0x5835, 0xB6C3, 0x7779,
+	0xB6C4, 0x8D4C, 0xB6C5, 0x675C, 0xB6C6, 0x9540, 0xB6C7, 0x809A,
+	0xB6C8, 0x5EA6, 0xB6C9, 0x6E21, 0xB6CA, 0x5992, 0xB6CB, 0x7AEF,
+	0xB6CC, 0x77ED, 0xB6CD, 0x953B, 0xB6CE, 0x6BB5, 0xB6CF, 0x65AD,
+	0xB6D0, 0x7F0E, 0xB6D1, 0x5806, 0xB6D2, 0x5151, 0xB6D3, 0x961F,
+	0xB6D4, 0x5BF9, 0xB6D5, 0x58A9, 0xB6D6, 0x5428, 0xB6D7, 0x8E72,
+	0xB6D8, 0x6566, 0xB6D9, 0x987F, 0xB6DA, 0x56E4, 0xB6DB, 0x949D,
+	0xB6DC, 0x76FE, 0xB6DD, 0x9041, 0xB6DE, 0x6387, 0xB6DF, 0x54C6,
+	0xB6E0, 0x591A, 0xB6E1, 0x593A, 0xB6E2, 0x579B, 0xB6E3, 0x8EB2,
+	0xB6E4, 0x6735, 0xB6E5, 0x8DFA, 0xB6E6, 0x8235, 0xB6E7, 0x5241,
+	0xB6E8, 0x60F0, 0xB6E9, 0x5815, 0xB6EA, 0x86FE, 0xB6EB, 0x5CE8,
+	0xB6EC, 0x9E45, 0xB6ED, 0x4FC4, 0xB6EE, 0x989D, 0xB6EF, 0x8BB9,
+	0xB6F0, 0x5A25, 0xB6F1, 0x6076, 0xB6F2, 0x5384, 0xB6F3, 0x627C,
+	0xB6F4, 0x904F, 0xB6F5, 0x9102, 0xB6F6, 0x997F, 0xB6F7, 0x6069,
+	0xB6F8, 0x800C, 0xB6F9, 0x513F, 0xB6FA, 0x8033, 0xB6FB, 0x5C14,
+	0xB6FC, 0x9975, 0xB6FD, 0x6D31, 0xB6FE, 0x4E8C, 0xB740, 0x7A1D,
+	0xB741, 0x7A1F, 0xB742, 0x7A21, 0xB743, 0x7A22, 0xB744, 0x7A24,
+	0xB745, 0x7A25, 0xB746, 0x7A26, 0xB747, 0x7A27, 0xB748, 0x7A28,
+	0xB749, 0x7A29, 0xB74A, 0x7A2A, 0xB74B, 0x7A2B, 0xB74C, 0x7A2C,
+	0xB74D, 0x7A2D, 0xB74E, 0x7A2E, 0xB74F, 0x7A2F, 0xB750, 0x7A30,
+	0xB751, 0x7A31, 0xB752, 0x7A32, 0xB753, 0x7A34, 0xB754, 0x7A35,
+	0xB755, 0x7A36, 0xB756, 0x7A38, 0xB757, 0x7A3A, 0xB758, 0x7A3E,
+	0xB759, 0x7A40, 0xB75A, 0x7A41, 0xB75B, 0x7A42, 0xB75C, 0x7A43,
+	0xB75D, 0x7A44, 0xB75E, 0x7A45, 0xB75F, 0x7A47, 0xB760, 0x7A48,
+	0xB761, 0x7A49, 0xB762, 0x7A4A, 0xB763, 0x7A4B, 0xB764, 0x7A4C,
+	0xB765, 0x7A4D, 0xB766, 0x7A4E, 0xB767, 0x7A4F, 0xB768, 0x7A50,
+	0xB769, 0x7A52, 0xB76A, 0x7A53, 0xB76B, 0x7A54, 0xB76C, 0x7A55,
+	0xB76D, 0x7A56, 0xB76E, 0x7A58, 0xB76F, 0x7A59, 0xB770, 0x7A5A,
+	0xB771, 0x7A5B, 0xB772, 0x7A5C, 0xB773, 0x7A5D, 0xB774, 0x7A5E,
+	0xB775, 0x7A5F, 0xB776, 0x7A60, 0xB777, 0x7A61, 0xB778, 0x7A62,
+	0xB779, 0x7A63, 0xB77A, 0x7A64, 0xB77B, 0x7A65, 0xB77C, 0x7A66,
+	0xB77D, 0x7A67, 0xB77E, 0x7A68, 0xB780, 0x7A69, 0xB781, 0x7A6A,
+	0xB782, 0x7A6B, 0xB783, 0x7A6C, 0xB784, 0x7A6D, 0xB785, 0x7A6E,
+	0xB786, 0x7A6F, 0xB787, 0x7A71, 0xB788, 0x7A72, 0xB789, 0x7A73,
+	0xB78A, 0x7A75, 0xB78B, 0x7A7B, 0xB78C, 0x7A7C, 0xB78D, 0x7A7D,
+	0xB78E, 0x7A7E, 0xB78F, 0x7A82, 0xB790, 0x7A85, 0xB791, 0x7A87,
+	0xB792, 0x7A89, 0xB793, 0x7A8A, 0xB794, 0x7A8B, 0xB795, 0x7A8C,
+	0xB796, 0x7A8E, 0xB797, 0x7A8F, 0xB798, 0x7A90, 0xB799, 0x7A93,
+	0xB79A, 0x7A94, 0xB79B, 0x7A99, 0xB79C, 0x7A9A, 0xB79D, 0x7A9B,
+	0xB79E, 0x7A9E, 0xB79F, 0x7AA1, 0xB7A0, 0x7AA2, 0xB7A1, 0x8D30,
+	0xB7A2, 0x53D1, 0xB7A3, 0x7F5A, 0xB7A4, 0x7B4F, 0xB7A5, 0x4F10,
+	0xB7A6, 0x4E4F, 0xB7A7, 0x9600, 0xB7A8, 0x6CD5, 0xB7A9, 0x73D0,
+	0xB7AA, 0x85E9, 0xB7AB, 0x5E06, 0xB7AC, 0x756A, 0xB7AD, 0x7FFB,
+	0xB7AE, 0x6A0A, 0xB7AF, 0x77FE, 0xB7B0, 0x9492, 0xB7B1, 0x7E41,
+	0xB7B2, 0x51E1, 0xB7B3, 0x70E6, 0xB7B4, 0x53CD, 0xB7B5, 0x8FD4,
+	0xB7B6, 0x8303, 0xB7B7, 0x8D29, 0xB7B8, 0x72AF, 0xB7B9, 0x996D,
+	0xB7BA, 0x6CDB, 0xB7BB, 0x574A, 0xB7BC, 0x82B3, 0xB7BD, 0x65B9,
+	0xB7BE, 0x80AA, 0xB7BF, 0x623F, 0xB7C0, 0x9632, 0xB7C1, 0x59A8,
+	0xB7C2, 0x4EFF, 0xB7C3, 0x8BBF, 0xB7C4, 0x7EBA, 0xB7C5, 0x653E,
+	0xB7C6, 0x83F2, 0xB7C7, 0x975E, 0xB7C8, 0x5561, 0xB7C9, 0x98DE,
+	0xB7CA, 0x80A5, 0xB7CB, 0x532A, 0xB7CC, 0x8BFD, 0xB7CD, 0x5420,
+	0xB7CE, 0x80BA, 0xB7CF, 0x5E9F, 0xB7D0, 0x6CB8, 0xB7D1, 0x8D39,
+	0xB7D2, 0x82AC, 0xB7D3, 0x915A, 0xB7D4, 0x5429, 0xB7D5, 0x6C1B,
+	0xB7D6, 0x5206, 0xB7D7, 0x7EB7, 0xB7D8, 0x575F, 0xB7D9, 0x711A,
+	0xB7DA, 0x6C7E, 0xB7DB, 0x7C89, 0xB7DC, 0x594B, 0xB7DD, 0x4EFD,
+	0xB7DE, 0x5FFF, 0xB7DF, 0x6124, 0xB7E0, 0x7CAA, 0xB7E1, 0x4E30,
+	0xB7E2, 0x5C01, 0xB7E3, 0x67AB, 0xB7E4, 0x8702, 0xB7E5, 0x5CF0,
+	0xB7E6, 0x950B, 0xB7E7, 0x98CE, 0xB7E8, 0x75AF, 0xB7E9, 0x70FD,
+	0xB7EA, 0x9022, 0xB7EB, 0x51AF, 0xB7EC, 0x7F1D, 0xB7ED, 0x8BBD,
+	0xB7EE, 0x5949, 0xB7EF, 0x51E4, 0xB7F0, 0x4F5B, 0xB7F1, 0x5426,
+	0xB7F2, 0x592B, 0xB7F3, 0x6577, 0xB7F4, 0x80A4, 0xB7F5, 0x5B75,
+	0xB7F6, 0x6276, 0xB7F7, 0x62C2, 0xB7F8, 0x8F90, 0xB7F9, 0x5E45,
+	0xB7FA, 0x6C1F, 0xB7FB, 0x7B26, 0xB7FC, 0x4F0F, 0xB7FD, 0x4FD8,
+	0xB7FE, 0x670D, 0xB840, 0x7AA3, 0xB841, 0x7AA4, 0xB842, 0x7AA7,
+	0xB843, 0x7AA9, 0xB844, 0x7AAA, 0xB845, 0x7AAB, 0xB846, 0x7AAE,
+	0xB847, 0x7AAF, 0xB848, 0x7AB0, 0xB849, 0x7AB1, 0xB84A, 0x7AB2,
+	0xB84B, 0x7AB4, 0xB84C, 0x7AB5, 0xB84D, 0x7AB6, 0xB84E, 0x7AB7,
+	0xB84F, 0x7AB8, 0xB850, 0x7AB9, 0xB851, 0x7ABA, 0xB852, 0x7ABB,
+	0xB853, 0x7ABC, 0xB854, 0x7ABD, 0xB855, 0x7ABE, 0xB856, 0x7AC0,
+	0xB857, 0x7AC1, 0xB858, 0x7AC2, 0xB859, 0x7AC3, 0xB85A, 0x7AC4,
+	0xB85B, 0x7AC5, 0xB85C, 0x7AC6, 0xB85D, 0x7AC7, 0xB85E, 0x7AC8,
+	0xB85F, 0x7AC9, 0xB860, 0x7ACA, 0xB861, 0x7ACC, 0xB862, 0x7ACD,
+	0xB863, 0x7ACE, 0xB864, 0x7ACF, 0xB865, 0x7AD0, 0xB866, 0x7AD1,
+	0xB867, 0x7AD2, 0xB868, 0x7AD3, 0xB869, 0x7AD4, 0xB86A, 0x7AD5,
+	0xB86B, 0x7AD7, 0xB86C, 0x7AD8, 0xB86D, 0x7ADA, 0xB86E, 0x7ADB,
+	0xB86F, 0x7ADC, 0xB870, 0x7ADD, 0xB871, 0x7AE1, 0xB872, 0x7AE2,
+	0xB873, 0x7AE4, 0xB874, 0x7AE7, 0xB875, 0x7AE8, 0xB876, 0x7AE9,
+	0xB877, 0x7AEA, 0xB878, 0x7AEB, 0xB879, 0x7AEC, 0xB87A, 0x7AEE,
+	0xB87B, 0x7AF0, 0xB87C, 0x7AF1, 0xB87D, 0x7AF2, 0xB87E, 0x7AF3,
+	0xB880, 0x7AF4, 0xB881, 0x7AF5, 0xB882, 0x7AF6, 0xB883, 0x7AF7,
+	0xB884, 0x7AF8, 0xB885, 0x7AFB, 0xB886, 0x7AFC, 0xB887, 0x7AFE,
+	0xB888, 0x7B00, 0xB889, 0x7B01, 0xB88A, 0x7B02, 0xB88B, 0x7B05,
+	0xB88C, 0x7B07, 0xB88D, 0x7B09, 0xB88E, 0x7B0C, 0xB88F, 0x7B0D,
+	0xB890, 0x7B0E, 0xB891, 0x7B10, 0xB892, 0x7B12, 0xB893, 0x7B13,
+	0xB894, 0x7B16, 0xB895, 0x7B17, 0xB896, 0x7B18, 0xB897, 0x7B1A,
+	0xB898, 0x7B1C, 0xB899, 0x7B1D, 0xB89A, 0x7B1F, 0xB89B, 0x7B21,
+	0xB89C, 0x7B22, 0xB89D, 0x7B23, 0xB89E, 0x7B27, 0xB89F, 0x7B29,
+	0xB8A0, 0x7B2D, 0xB8A1, 0x6D6E, 0xB8A2, 0x6DAA, 0xB8A3, 0x798F,
+	0xB8A4, 0x88B1, 0xB8A5, 0x5F17, 0xB8A6, 0x752B, 0xB8A7, 0x629A,
+	0xB8A8, 0x8F85, 0xB8A9, 0x4FEF, 0xB8AA, 0x91DC, 0xB8AB, 0x65A7,
+	0xB8AC, 0x812F, 0xB8AD, 0x8151, 0xB8AE, 0x5E9C, 0xB8AF, 0x8150,
+	0xB8B0, 0x8D74, 0xB8B1, 0x526F, 0xB8B2, 0x8986, 0xB8B3, 0x8D4B,
+	0xB8B4, 0x590D, 0xB8B5, 0x5085, 0xB8B6, 0x4ED8, 0xB8B7, 0x961C,
+	0xB8B8, 0x7236, 0xB8B9, 0x8179, 0xB8BA, 0x8D1F, 0xB8BB, 0x5BCC,
+	0xB8BC, 0x8BA3, 0xB8BD, 0x9644, 0xB8BE, 0x5987, 0xB8BF, 0x7F1A,
+	0xB8C0, 0x5490, 0xB8C1, 0x5676, 0xB8C2, 0x560E, 0xB8C3, 0x8BE5,
+	0xB8C4, 0x6539, 0xB8C5, 0x6982, 0xB8C6, 0x9499, 0xB8C7, 0x76D6,
+	0xB8C8, 0x6E89, 0xB8C9, 0x5E72, 0xB8CA, 0x7518, 0xB8CB, 0x6746,
+	0xB8CC, 0x67D1, 0xB8CD, 0x7AFF, 0xB8CE, 0x809D, 0xB8CF, 0x8D76,
+	0xB8D0, 0x611F, 0xB8D1, 0x79C6, 0xB8D2, 0x6562, 0xB8D3, 0x8D63,
+	0xB8D4, 0x5188, 0xB8D5, 0x521A, 0xB8D6, 0x94A2, 0xB8D7, 0x7F38,
+	0xB8D8, 0x809B, 0xB8D9, 0x7EB2, 0xB8DA, 0x5C97, 0xB8DB, 0x6E2F,
+	0xB8DC, 0x6760, 0xB8DD, 0x7BD9, 0xB8DE, 0x768B, 0xB8DF, 0x9AD8,
+	0xB8E0, 0x818F, 0xB8E1, 0x7F94, 0xB8E2, 0x7CD5, 0xB8E3, 0x641E,
+	0xB8E4, 0x9550, 0xB8E5, 0x7A3F, 0xB8E6, 0x544A, 0xB8E7, 0x54E5,
+	0xB8E8, 0x6B4C, 0xB8E9, 0x6401, 0xB8EA, 0x6208, 0xB8EB, 0x9E3D,
+	0xB8EC, 0x80F3, 0xB8ED, 0x7599, 0xB8EE, 0x5272, 0xB8EF, 0x9769,
+	0xB8F0, 0x845B, 0xB8F1, 0x683C, 0xB8F2, 0x86E4, 0xB8F3, 0x9601,
+	0xB8F4, 0x9694, 0xB8F5, 0x94EC, 0xB8F6, 0x4E2A, 0xB8F7, 0x5404,
+	0xB8F8, 0x7ED9, 0xB8F9, 0x6839, 0xB8FA, 0x8DDF, 0xB8FB, 0x8015,
+	0xB8FC, 0x66F4, 0xB8FD, 0x5E9A, 0xB8FE, 0x7FB9, 0xB940, 0x7B2F,
+	0xB941, 0x7B30, 0xB942, 0x7B32, 0xB943, 0x7B34, 0xB944, 0x7B35,
+	0xB945, 0x7B36, 0xB946, 0x7B37, 0xB947, 0x7B39, 0xB948, 0x7B3B,
+	0xB949, 0x7B3D, 0xB94A, 0x7B3F, 0xB94B, 0x7B40, 0xB94C, 0x7B41,
+	0xB94D, 0x7B42, 0xB94E, 0x7B43, 0xB94F, 0x7B44, 0xB950, 0x7B46,
+	0xB951, 0x7B48, 0xB952, 0x7B4A, 0xB953, 0x7B4D, 0xB954, 0x7B4E,
+	0xB955, 0x7B53, 0xB956, 0x7B55, 0xB957, 0x7B57, 0xB958, 0x7B59,
+	0xB959, 0x7B5C, 0xB95A, 0x7B5E, 0xB95B, 0x7B5F, 0xB95C, 0x7B61,
+	0xB95D, 0x7B63, 0xB95E, 0x7B64, 0xB95F, 0x7B65, 0xB960, 0x7B66,
+	0xB961, 0x7B67, 0xB962, 0x7B68, 0xB963, 0x7B69, 0xB964, 0x7B6A,
+	0xB965, 0x7B6B, 0xB966, 0x7B6C, 0xB967, 0x7B6D, 0xB968, 0x7B6F,
+	0xB969, 0x7B70, 0xB96A, 0x7B73, 0xB96B, 0x7B74, 0xB96C, 0x7B76,
+	0xB96D, 0x7B78, 0xB96E, 0x7B7A, 0xB96F, 0x7B7C, 0xB970, 0x7B7D,
+	0xB971, 0x7B7F, 0xB972, 0x7B81, 0xB973, 0x7B82, 0xB974, 0x7B83,
+	0xB975, 0x7B84, 0xB976, 0x7B86, 0xB977, 0x7B87, 0xB978, 0x7B88,
+	0xB979, 0x7B89, 0xB97A, 0x7B8A, 0xB97B, 0x7B8B, 0xB97C, 0x7B8C,
+	0xB97D, 0x7B8E, 0xB97E, 0x7B8F, 0xB980, 0x7B91, 0xB981, 0x7B92,
+	0xB982, 0x7B93, 0xB983, 0x7B96, 0xB984, 0x7B98, 0xB985, 0x7B99,
+	0xB986, 0x7B9A, 0xB987, 0x7B9B, 0xB988, 0x7B9E, 0xB989, 0x7B9F,
+	0xB98A, 0x7BA0, 0xB98B, 0x7BA3, 0xB98C, 0x7BA4, 0xB98D, 0x7BA5,
+	0xB98E, 0x7BAE, 0xB98F, 0x7BAF, 0xB990, 0x7BB0, 0xB991, 0x7BB2,
+	0xB992, 0x7BB3, 0xB993, 0x7BB5, 0xB994, 0x7BB6, 0xB995, 0x7BB7,
+	0xB996, 0x7BB9, 0xB997, 0x7BBA, 0xB998, 0x7BBB, 0xB999, 0x7BBC,
+	0xB99A, 0x7BBD, 0xB99B, 0x7BBE, 0xB99C, 0x7BBF, 0xB99D, 0x7BC0,
+	0xB99E, 0x7BC2, 0xB99F, 0x7BC3, 0xB9A0, 0x7BC4, 0xB9A1, 0x57C2,
+	0xB9A2, 0x803F, 0xB9A3, 0x6897, 0xB9A4, 0x5DE5, 0xB9A5, 0x653B,
+	0xB9A6, 0x529F, 0xB9A7, 0x606D, 0xB9A8, 0x9F9A, 0xB9A9, 0x4F9B,
+	0xB9AA, 0x8EAC, 0xB9AB, 0x516C, 0xB9AC, 0x5BAB, 0xB9AD, 0x5F13,
+	0xB9AE, 0x5DE9, 0xB9AF, 0x6C5E, 0xB9B0, 0x62F1, 0xB9B1, 0x8D21,
+	0xB9B2, 0x5171, 0xB9B3, 0x94A9, 0xB9B4, 0x52FE, 0xB9B5, 0x6C9F,
+	0xB9B6, 0x82DF, 0xB9B7, 0x72D7, 0xB9B8, 0x57A2, 0xB9B9, 0x6784,
+	0xB9BA, 0x8D2D, 0xB9BB, 0x591F, 0xB9BC, 0x8F9C, 0xB9BD, 0x83C7,
+	0xB9BE, 0x5495, 0xB9BF, 0x7B8D, 0xB9C0, 0x4F30, 0xB9C1, 0x6CBD,
+	0xB9C2, 0x5B64, 0xB9C3, 0x59D1, 0xB9C4, 0x9F13, 0xB9C5, 0x53E4,
+	0xB9C6, 0x86CA, 0xB9C7, 0x9AA8, 0xB9C8, 0x8C37, 0xB9C9, 0x80A1,
+	0xB9CA, 0x6545, 0xB9CB, 0x987E, 0xB9CC, 0x56FA, 0xB9CD, 0x96C7,
+	0xB9CE, 0x522E, 0xB9CF, 0x74DC, 0xB9D0, 0x5250, 0xB9D1, 0x5BE1,
+	0xB9D2, 0x6302, 0xB9D3, 0x8902, 0xB9D4, 0x4E56, 0xB9D5, 0x62D0,
+	0xB9D6, 0x602A, 0xB9D7, 0x68FA, 0xB9D8, 0x5173, 0xB9D9, 0x5B98,
+	0xB9DA, 0x51A0, 0xB9DB, 0x89C2, 0xB9DC, 0x7BA1, 0xB9DD, 0x9986,
+	0xB9DE, 0x7F50, 0xB9DF, 0x60EF, 0xB9E0, 0x704C, 0xB9E1, 0x8D2F,
+	0xB9E2, 0x5149, 0xB9E3, 0x5E7F, 0xB9E4, 0x901B, 0xB9E5, 0x7470,
+	0xB9E6, 0x89C4, 0xB9E7, 0x572D, 0xB9E8, 0x7845, 0xB9E9, 0x5F52,
+	0xB9EA, 0x9F9F, 0xB9EB, 0x95FA, 0xB9EC, 0x8F68, 0xB9ED, 0x9B3C,
+	0xB9EE, 0x8BE1, 0xB9EF, 0x7678, 0xB9F0, 0x6842, 0xB9F1, 0x67DC,
+	0xB9F2, 0x8DEA, 0xB9F3, 0x8D35, 0xB9F4, 0x523D, 0xB9F5, 0x8F8A,
+	0xB9F6, 0x6EDA, 0xB9F7, 0x68CD, 0xB9F8, 0x9505, 0xB9F9, 0x90ED,
+	0xB9FA, 0x56FD, 0xB9FB, 0x679C, 0xB9FC, 0x88F9, 0xB9FD, 0x8FC7,
+	0xB9FE, 0x54C8, 0xBA40, 0x7BC5, 0xBA41, 0x7BC8, 0xBA42, 0x7BC9,
+	0xBA43, 0x7BCA, 0xBA44, 0x7BCB, 0xBA45, 0x7BCD, 0xBA46, 0x7BCE,
+	0xBA47, 0x7BCF, 0xBA48, 0x7BD0, 0xBA49, 0x7BD2, 0xBA4A, 0x7BD4,
+	0xBA4B, 0x7BD5, 0xBA4C, 0x7BD6, 0xBA4D, 0x7BD7, 0xBA4E, 0x7BD8,
+	0xBA4F, 0x7BDB, 0xBA50, 0x7BDC, 0xBA51, 0x7BDE, 0xBA52, 0x7BDF,
+	0xBA53, 0x7BE0, 0xBA54, 0x7BE2, 0xBA55, 0x7BE3, 0xBA56, 0x7BE4,
+	0xBA57, 0x7BE7, 0xBA58, 0x7BE8, 0xBA59, 0x7BE9, 0xBA5A, 0x7BEB,
+	0xBA5B, 0x7BEC, 0xBA5C, 0x7BED, 0xBA5D, 0x7BEF, 0xBA5E, 0x7BF0,
+	0xBA5F, 0x7BF2, 0xBA60, 0x7BF3, 0xBA61, 0x7BF4, 0xBA62, 0x7BF5,
+	0xBA63, 0x7BF6, 0xBA64, 0x7BF8, 0xBA65, 0x7BF9, 0xBA66, 0x7BFA,
+	0xBA67, 0x7BFB, 0xBA68, 0x7BFD, 0xBA69, 0x7BFF, 0xBA6A, 0x7C00,
+	0xBA6B, 0x7C01, 0xBA6C, 0x7C02, 0xBA6D, 0x7C03, 0xBA6E, 0x7C04,
+	0xBA6F, 0x7C05, 0xBA70, 0x7C06, 0xBA71, 0x7C08, 0xBA72, 0x7C09,
+	0xBA73, 0x7C0A, 0xBA74, 0x7C0D, 0xBA75, 0x7C0E, 0xBA76, 0x7C10,
+	0xBA77, 0x7C11, 0xBA78, 0x7C12, 0xBA79, 0x7C13, 0xBA7A, 0x7C14,
+	0xBA7B, 0x7C15, 0xBA7C, 0x7C17, 0xBA7D, 0x7C18, 0xBA7E, 0x7C19,
+	0xBA80, 0x7C1A, 0xBA81, 0x7C1B, 0xBA82, 0x7C1C, 0xBA83, 0x7C1D,
+	0xBA84, 0x7C1E, 0xBA85, 0x7C20, 0xBA86, 0x7C21, 0xBA87, 0x7C22,
+	0xBA88, 0x7C23, 0xBA89, 0x7C24, 0xBA8A, 0x7C25, 0xBA8B, 0x7C28,
+	0xBA8C, 0x7C29, 0xBA8D, 0x7C2B, 0xBA8E, 0x7C2C, 0xBA8F, 0x7C2D,
+	0xBA90, 0x7C2E, 0xBA91, 0x7C2F, 0xBA92, 0x7C30, 0xBA93, 0x7C31,
+	0xBA94, 0x7C32, 0xBA95, 0x7C33, 0xBA96, 0x7C34, 0xBA97, 0x7C35,
+	0xBA98, 0x7C36, 0xBA99, 0x7C37, 0xBA9A, 0x7C39, 0xBA9B, 0x7C3A,
+	0xBA9C, 0x7C3B, 0xBA9D, 0x7C3C, 0xBA9E, 0x7C3D, 0xBA9F, 0x7C3E,
+	0xBAA0, 0x7C42, 0xBAA1, 0x9AB8, 0xBAA2, 0x5B69, 0xBAA3, 0x6D77,
+	0xBAA4, 0x6C26, 0xBAA5, 0x4EA5, 0xBAA6, 0x5BB3, 0xBAA7, 0x9A87,
+	0xBAA8, 0x9163, 0xBAA9, 0x61A8, 0xBAAA, 0x90AF, 0xBAAB, 0x97E9,
+	0xBAAC, 0x542B, 0xBAAD, 0x6DB5, 0xBAAE, 0x5BD2, 0xBAAF, 0x51FD,
+	0xBAB0, 0x558A, 0xBAB1, 0x7F55, 0xBAB2, 0x7FF0, 0xBAB3, 0x64BC,
+	0xBAB4, 0x634D, 0xBAB5, 0x65F1, 0xBAB6, 0x61BE, 0xBAB7, 0x608D,
+	0xBAB8, 0x710A, 0xBAB9, 0x6C57, 0xBABA, 0x6C49, 0xBABB, 0x592F,
+	0xBABC, 0x676D, 0xBABD, 0x822A, 0xBABE, 0x58D5, 0xBABF, 0x568E,
+	0xBAC0, 0x8C6A, 0xBAC1, 0x6BEB, 0xBAC2, 0x90DD, 0xBAC3, 0x597D,
+	0xBAC4, 0x8017, 0xBAC5, 0x53F7, 0xBAC6, 0x6D69, 0xBAC7, 0x5475,
+	0xBAC8, 0x559D, 0xBAC9, 0x8377, 0xBACA, 0x83CF, 0xBACB, 0x6838,
+	0xBACC, 0x79BE, 0xBACD, 0x548C, 0xBACE, 0x4F55, 0xBACF, 0x5408,
+	0xBAD0, 0x76D2, 0xBAD1, 0x8C89, 0xBAD2, 0x9602, 0xBAD3, 0x6CB3,
+	0xBAD4, 0x6DB8, 0xBAD5, 0x8D6B, 0xBAD6, 0x8910, 0xBAD7, 0x9E64,
+	0xBAD8, 0x8D3A, 0xBAD9, 0x563F, 0xBADA, 0x9ED1, 0xBADB, 0x75D5,
+	0xBADC, 0x5F88, 0xBADD, 0x72E0, 0xBADE, 0x6068, 0xBADF, 0x54FC,
+	0xBAE0, 0x4EA8, 0xBAE1, 0x6A2A, 0xBAE2, 0x8861, 0xBAE3, 0x6052,
+	0xBAE4, 0x8F70, 0xBAE5, 0x54C4, 0xBAE6, 0x70D8, 0xBAE7, 0x8679,
+	0xBAE8, 0x9E3F, 0xBAE9, 0x6D2A, 0xBAEA, 0x5B8F, 0xBAEB, 0x5F18,
+	0xBAEC, 0x7EA2, 0xBAED, 0x5589, 0xBAEE, 0x4FAF, 0xBAEF, 0x7334,
+	0xBAF0, 0x543C, 0xBAF1, 0x539A, 0xBAF2, 0x5019, 0xBAF3, 0x540E,
+	0xBAF4, 0x547C, 0xBAF5, 0x4E4E, 0xBAF6, 0x5FFD, 0xBAF7, 0x745A,
+	0xBAF8, 0x58F6, 0xBAF9, 0x846B, 0xBAFA, 0x80E1, 0xBAFB, 0x8774,
+	0xBAFC, 0x72D0, 0xBAFD, 0x7CCA, 0xBAFE, 0x6E56, 0xBB40, 0x7C43,
+	0xBB41, 0x7C44, 0xBB42, 0x7C45, 0xBB43, 0x7C46, 0xBB44, 0x7C47,
+	0xBB45, 0x7C48, 0xBB46, 0x7C49, 0xBB47, 0x7C4A, 0xBB48, 0x7C4B,
+	0xBB49, 0x7C4C, 0xBB4A, 0x7C4E, 0xBB4B, 0x7C4F, 0xBB4C, 0x7C50,
+	0xBB4D, 0x7C51, 0xBB4E, 0x7C52, 0xBB4F, 0x7C53, 0xBB50, 0x7C54,
+	0xBB51, 0x7C55, 0xBB52, 0x7C56, 0xBB53, 0x7C57, 0xBB54, 0x7C58,
+	0xBB55, 0x7C59, 0xBB56, 0x7C5A, 0xBB57, 0x7C5B, 0xBB58, 0x7C5C,
+	0xBB59, 0x7C5D, 0xBB5A, 0x7C5E, 0xBB5B, 0x7C5F, 0xBB5C, 0x7C60,
+	0xBB5D, 0x7C61, 0xBB5E, 0x7C62, 0xBB5F, 0x7C63, 0xBB60, 0x7C64,
+	0xBB61, 0x7C65, 0xBB62, 0x7C66, 0xBB63, 0x7C67, 0xBB64, 0x7C68,
+	0xBB65, 0x7C69, 0xBB66, 0x7C6A, 0xBB67, 0x7C6B, 0xBB68, 0x7C6C,
+	0xBB69, 0x7C6D, 0xBB6A, 0x7C6E, 0xBB6B, 0x7C6F, 0xBB6C, 0x7C70,
+	0xBB6D, 0x7C71, 0xBB6E, 0x7C72, 0xBB6F, 0x7C75, 0xBB70, 0x7C76,
+	0xBB71, 0x7C77, 0xBB72, 0x7C78, 0xBB73, 0x7C79, 0xBB74, 0x7C7A,
+	0xBB75, 0x7C7E, 0xBB76, 0x7C7F, 0xBB77, 0x7C80, 0xBB78, 0x7C81,
+	0xBB79, 0x7C82, 0xBB7A, 0x7C83, 0xBB7B, 0x7C84, 0xBB7C, 0x7C85,
+	0xBB7D, 0x7C86, 0xBB7E, 0x7C87, 0xBB80, 0x7C88, 0xBB81, 0x7C8A,
+	0xBB82, 0x7C8B, 0xBB83, 0x7C8C, 0xBB84, 0x7C8D, 0xBB85, 0x7C8E,
+	0xBB86, 0x7C8F, 0xBB87, 0x7C90, 0xBB88, 0x7C93, 0xBB89, 0x7C94,
+	0xBB8A, 0x7C96, 0xBB8B, 0x7C99, 0xBB8C, 0x7C9A, 0xBB8D, 0x7C9B,
+	0xBB8E, 0x7CA0, 0xBB8F, 0x7CA1, 0xBB90, 0x7CA3, 0xBB91, 0x7CA6,
+	0xBB92, 0x7CA7, 0xBB93, 0x7CA8, 0xBB94, 0x7CA9, 0xBB95, 0x7CAB,
+	0xBB96, 0x7CAC, 0xBB97, 0x7CAD, 0xBB98, 0x7CAF, 0xBB99, 0x7CB0,
+	0xBB9A, 0x7CB4, 0xBB9B, 0x7CB5, 0xBB9C, 0x7CB6, 0xBB9D, 0x7CB7,
+	0xBB9E, 0x7CB8, 0xBB9F, 0x7CBA, 0xBBA0, 0x7CBB, 0xBBA1, 0x5F27,
+	0xBBA2, 0x864E, 0xBBA3, 0x552C, 0xBBA4, 0x62A4, 0xBBA5, 0x4E92,
+	0xBBA6, 0x6CAA, 0xBBA7, 0x6237, 0xBBA8, 0x82B1, 0xBBA9, 0x54D7,
+	0xBBAA, 0x534E, 0xBBAB, 0x733E, 0xBBAC, 0x6ED1, 0xBBAD, 0x753B,
+	0xBBAE, 0x5212, 0xBBAF, 0x5316, 0xBBB0, 0x8BDD, 0xBBB1, 0x69D0,
+	0xBBB2, 0x5F8A, 0xBBB3, 0x6000, 0xBBB4, 0x6DEE, 0xBBB5, 0x574F,
+	0xBBB6, 0x6B22, 0xBBB7, 0x73AF, 0xBBB8, 0x6853, 0xBBB9, 0x8FD8,
+	0xBBBA, 0x7F13, 0xBBBB, 0x6362, 0xBBBC, 0x60A3, 0xBBBD, 0x5524,
+	0xBBBE, 0x75EA, 0xBBBF, 0x8C62, 0xBBC0, 0x7115, 0xBBC1, 0x6DA3,
+	0xBBC2, 0x5BA6, 0xBBC3, 0x5E7B, 0xBBC4, 0x8352, 0xBBC5, 0x614C,
+	0xBBC6, 0x9EC4, 0xBBC7, 0x78FA, 0xBBC8, 0x8757, 0xBBC9, 0x7C27,
+	0xBBCA, 0x7687, 0xBBCB, 0x51F0, 0xBBCC, 0x60F6, 0xBBCD, 0x714C,
+	0xBBCE, 0x6643, 0xBBCF, 0x5E4C, 0xBBD0, 0x604D, 0xBBD1, 0x8C0E,
+	0xBBD2, 0x7070, 0xBBD3, 0x6325, 0xBBD4, 0x8F89, 0xBBD5, 0x5FBD,
+	0xBBD6, 0x6062, 0xBBD7, 0x86D4, 0xBBD8, 0x56DE, 0xBBD9, 0x6BC1,
+	0xBBDA, 0x6094, 0xBBDB, 0x6167, 0xBBDC, 0x5349, 0xBBDD, 0x60E0,
+	0xBBDE, 0x6666, 0xBBDF, 0x8D3F, 0xBBE0, 0x79FD, 0xBBE1, 0x4F1A,
+	0xBBE2, 0x70E9, 0xBBE3, 0x6C47, 0xBBE4, 0x8BB3, 0xBBE5, 0x8BF2,
+	0xBBE6, 0x7ED8, 0xBBE7, 0x8364, 0xBBE8, 0x660F, 0xBBE9, 0x5A5A,
+	0xBBEA, 0x9B42, 0xBBEB, 0x6D51, 0xBBEC, 0x6DF7, 0xBBED, 0x8C41,
+	0xBBEE, 0x6D3B, 0xBBEF, 0x4F19, 0xBBF0, 0x706B, 0xBBF1, 0x83B7,
+	0xBBF2, 0x6216, 0xBBF3, 0x60D1, 0xBBF4, 0x970D, 0xBBF5, 0x8D27,
+	0xBBF6, 0x7978, 0xBBF7, 0x51FB, 0xBBF8, 0x573E, 0xBBF9, 0x57FA,
+	0xBBFA, 0x673A, 0xBBFB, 0x7578, 0xBBFC, 0x7A3D, 0xBBFD, 0x79EF,
+	0xBBFE, 0x7B95, 0xBC40, 0x7CBF, 0xBC41, 0x7CC0, 0xBC42, 0x7CC2,
+	0xBC43, 0x7CC3, 0xBC44, 0x7CC4, 0xBC45, 0x7CC6, 0xBC46, 0x7CC9,
+	0xBC47, 0x7CCB, 0xBC48, 0x7CCE, 0xBC49, 0x7CCF, 0xBC4A, 0x7CD0,
+	0xBC4B, 0x7CD1, 0xBC4C, 0x7CD2, 0xBC4D, 0x7CD3, 0xBC4E, 0x7CD4,
+	0xBC4F, 0x7CD8, 0xBC50, 0x7CDA, 0xBC51, 0x7CDB, 0xBC52, 0x7CDD,
+	0xBC53, 0x7CDE, 0xBC54, 0x7CE1, 0xBC55, 0x7CE2, 0xBC56, 0x7CE3,
+	0xBC57, 0x7CE4, 0xBC58, 0x7CE5, 0xBC59, 0x7CE6, 0xBC5A, 0x7CE7,
+	0xBC5B, 0x7CE9, 0xBC5C, 0x7CEA, 0xBC5D, 0x7CEB, 0xBC5E, 0x7CEC,
+	0xBC5F, 0x7CED, 0xBC60, 0x7CEE, 0xBC61, 0x7CF0, 0xBC62, 0x7CF1,
+	0xBC63, 0x7CF2, 0xBC64, 0x7CF3, 0xBC65, 0x7CF4, 0xBC66, 0x7CF5,
+	0xBC67, 0x7CF6, 0xBC68, 0x7CF7, 0xBC69, 0x7CF9, 0xBC6A, 0x7CFA,
+	0xBC6B, 0x7CFC, 0xBC6C, 0x7CFD, 0xBC6D, 0x7CFE, 0xBC6E, 0x7CFF,
+	0xBC6F, 0x7D00, 0xBC70, 0x7D01, 0xBC71, 0x7D02, 0xBC72, 0x7D03,
+	0xBC73, 0x7D04, 0xBC74, 0x7D05, 0xBC75, 0x7D06, 0xBC76, 0x7D07,
+	0xBC77, 0x7D08, 0xBC78, 0x7D09, 0xBC79, 0x7D0B, 0xBC7A, 0x7D0C,
+	0xBC7B, 0x7D0D, 0xBC7C, 0x7D0E, 0xBC7D, 0x7D0F, 0xBC7E, 0x7D10,
+	0xBC80, 0x7D11, 0xBC81, 0x7D12, 0xBC82, 0x7D13, 0xBC83, 0x7D14,
+	0xBC84, 0x7D15, 0xBC85, 0x7D16, 0xBC86, 0x7D17, 0xBC87, 0x7D18,
+	0xBC88, 0x7D19, 0xBC89, 0x7D1A, 0xBC8A, 0x7D1B, 0xBC8B, 0x7D1C,
+	0xBC8C, 0x7D1D, 0xBC8D, 0x7D1E, 0xBC8E, 0x7D1F, 0xBC8F, 0x7D21,
+	0xBC90, 0x7D23, 0xBC91, 0x7D24, 0xBC92, 0x7D25, 0xBC93, 0x7D26,
+	0xBC94, 0x7D28, 0xBC95, 0x7D29, 0xBC96, 0x7D2A, 0xBC97, 0x7D2C,
+	0xBC98, 0x7D2D, 0xBC99, 0x7D2E, 0xBC9A, 0x7D30, 0xBC9B, 0x7D31,
+	0xBC9C, 0x7D32, 0xBC9D, 0x7D33, 0xBC9E, 0x7D34, 0xBC9F, 0x7D35,
+	0xBCA0, 0x7D36, 0xBCA1, 0x808C, 0xBCA2, 0x9965, 0xBCA3, 0x8FF9,
+	0xBCA4, 0x6FC0, 0xBCA5, 0x8BA5, 0xBCA6, 0x9E21, 0xBCA7, 0x59EC,
+	0xBCA8, 0x7EE9, 0xBCA9, 0x7F09, 0xBCAA, 0x5409, 0xBCAB, 0x6781,
+	0xBCAC, 0x68D8, 0xBCAD, 0x8F91, 0xBCAE, 0x7C4D, 0xBCAF, 0x96C6,
+	0xBCB0, 0x53CA, 0xBCB1, 0x6025, 0xBCB2, 0x75BE, 0xBCB3, 0x6C72,
+	0xBCB4, 0x5373, 0xBCB5, 0x5AC9, 0xBCB6, 0x7EA7, 0xBCB7, 0x6324,
+	0xBCB8, 0x51E0, 0xBCB9, 0x810A, 0xBCBA, 0x5DF1, 0xBCBB, 0x84DF,
+	0xBCBC, 0x6280, 0xBCBD, 0x5180, 0xBCBE, 0x5B63, 0xBCBF, 0x4F0E,
+	0xBCC0, 0x796D, 0xBCC1, 0x5242, 0xBCC2, 0x60B8, 0xBCC3, 0x6D4E,
+	0xBCC4, 0x5BC4, 0xBCC5, 0x5BC2, 0xBCC6, 0x8BA1, 0xBCC7, 0x8BB0,
+	0xBCC8, 0x65E2, 0xBCC9, 0x5FCC, 0xBCCA, 0x9645, 0xBCCB, 0x5993,
+	0xBCCC, 0x7EE7, 0xBCCD, 0x7EAA, 0xBCCE, 0x5609, 0xBCCF, 0x67B7,
+	0xBCD0, 0x5939, 0xBCD1, 0x4F73, 0xBCD2, 0x5BB6, 0xBCD3, 0x52A0,
+	0xBCD4, 0x835A, 0xBCD5, 0x988A, 0xBCD6, 0x8D3E, 0xBCD7, 0x7532,
+	0xBCD8, 0x94BE, 0xBCD9, 0x5047, 0xBCDA, 0x7A3C, 0xBCDB, 0x4EF7,
+	0xBCDC, 0x67B6, 0xBCDD, 0x9A7E, 0xBCDE, 0x5AC1, 0xBCDF, 0x6B7C,
+	0xBCE0, 0x76D1, 0xBCE1, 0x575A, 0xBCE2, 0x5C16, 0xBCE3, 0x7B3A,
+	0xBCE4, 0x95F4, 0xBCE5, 0x714E, 0xBCE6, 0x517C, 0xBCE7, 0x80A9,
+	0xBCE8, 0x8270, 0xBCE9, 0x5978, 0xBCEA, 0x7F04, 0xBCEB, 0x8327,
+	0xBCEC, 0x68C0, 0xBCED, 0x67EC, 0xBCEE, 0x78B1, 0xBCEF, 0x7877,
+	0xBCF0, 0x62E3, 0xBCF1, 0x6361, 0xBCF2, 0x7B80, 0xBCF3, 0x4FED,
+	0xBCF4, 0x526A, 0xBCF5, 0x51CF, 0xBCF6, 0x8350, 0xBCF7, 0x69DB,
+	0xBCF8, 0x9274, 0xBCF9, 0x8DF5, 0xBCFA, 0x8D31, 0xBCFB, 0x89C1,
+	0xBCFC, 0x952E, 0xBCFD, 0x7BAD, 0xBCFE, 0x4EF6, 0xBD40, 0x7D37,
+	0xBD41, 0x7D38, 0xBD42, 0x7D39, 0xBD43, 0x7D3A, 0xBD44, 0x7D3B,
+	0xBD45, 0x7D3C, 0xBD46, 0x7D3D, 0xBD47, 0x7D3E, 0xBD48, 0x7D3F,
+	0xBD49, 0x7D40, 0xBD4A, 0x7D41, 0xBD4B, 0x7D42, 0xBD4C, 0x7D43,
+	0xBD4D, 0x7D44, 0xBD4E, 0x7D45, 0xBD4F, 0x7D46, 0xBD50, 0x7D47,
+	0xBD51, 0x7D48, 0xBD52, 0x7D49, 0xBD53, 0x7D4A, 0xBD54, 0x7D4B,
+	0xBD55, 0x7D4C, 0xBD56, 0x7D4D, 0xBD57, 0x7D4E, 0xBD58, 0x7D4F,
+	0xBD59, 0x7D50, 0xBD5A, 0x7D51, 0xBD5B, 0x7D52, 0xBD5C, 0x7D53,
+	0xBD5D, 0x7D54, 0xBD5E, 0x7D55, 0xBD5F, 0x7D56, 0xBD60, 0x7D57,
+	0xBD61, 0x7D58, 0xBD62, 0x7D59, 0xBD63, 0x7D5A, 0xBD64, 0x7D5B,
+	0xBD65, 0x7D5C, 0xBD66, 0x7D5D, 0xBD67, 0x7D5E, 0xBD68, 0x7D5F,
+	0xBD69, 0x7D60, 0xBD6A, 0x7D61, 0xBD6B, 0x7D62, 0xBD6C, 0x7D63,
+	0xBD6D, 0x7D64, 0xBD6E, 0x7D65, 0xBD6F, 0x7D66, 0xBD70, 0x7D67,
+	0xBD71, 0x7D68, 0xBD72, 0x7D69, 0xBD73, 0x7D6A, 0xBD74, 0x7D6B,
+	0xBD75, 0x7D6C, 0xBD76, 0x7D6D, 0xBD77, 0x7D6F, 0xBD78, 0x7D70,
+	0xBD79, 0x7D71, 0xBD7A, 0x7D72, 0xBD7B, 0x7D73, 0xBD7C, 0x7D74,
+	0xBD7D, 0x7D75, 0xBD7E, 0x7D76, 0xBD80, 0x7D78, 0xBD81, 0x7D79,
+	0xBD82, 0x7D7A, 0xBD83, 0x7D7B, 0xBD84, 0x7D7C, 0xBD85, 0x7D7D,
+	0xBD86, 0x7D7E, 0xBD87, 0x7D7F, 0xBD88, 0x7D80, 0xBD89, 0x7D81,
+	0xBD8A, 0x7D82, 0xBD8B, 0x7D83, 0xBD8C, 0x7D84, 0xBD8D, 0x7D85,
+	0xBD8E, 0x7D86, 0xBD8F, 0x7D87, 0xBD90, 0x7D88, 0xBD91, 0x7D89,
+	0xBD92, 0x7D8A, 0xBD93, 0x7D8B, 0xBD94, 0x7D8C, 0xBD95, 0x7D8D,
+	0xBD96, 0x7D8E, 0xBD97, 0x7D8F, 0xBD98, 0x7D90, 0xBD99, 0x7D91,
+	0xBD9A, 0x7D92, 0xBD9B, 0x7D93, 0xBD9C, 0x7D94, 0xBD9D, 0x7D95,
+	0xBD9E, 0x7D96, 0xBD9F, 0x7D97, 0xBDA0, 0x7D98, 0xBDA1, 0x5065,
+	0xBDA2, 0x8230, 0xBDA3, 0x5251, 0xBDA4, 0x996F, 0xBDA5, 0x6E10,
+	0xBDA6, 0x6E85, 0xBDA7, 0x6DA7, 0xBDA8, 0x5EFA, 0xBDA9, 0x50F5,
+	0xBDAA, 0x59DC, 0xBDAB, 0x5C06, 0xBDAC, 0x6D46, 0xBDAD, 0x6C5F,
+	0xBDAE, 0x7586, 0xBDAF, 0x848B, 0xBDB0, 0x6868, 0xBDB1, 0x5956,
+	0xBDB2, 0x8BB2, 0xBDB3, 0x5320, 0xBDB4, 0x9171, 0xBDB5, 0x964D,
+	0xBDB6, 0x8549, 0xBDB7, 0x6912, 0xBDB8, 0x7901, 0xBDB9, 0x7126,
+	0xBDBA, 0x80F6, 0xBDBB, 0x4EA4, 0xBDBC, 0x90CA, 0xBDBD, 0x6D47,
+	0xBDBE, 0x9A84, 0xBDBF, 0x5A07, 0xBDC0, 0x56BC, 0xBDC1, 0x6405,
+	0xBDC2, 0x94F0, 0xBDC3, 0x77EB, 0xBDC4, 0x4FA5, 0xBDC5, 0x811A,
+	0xBDC6, 0x72E1, 0xBDC7, 0x89D2, 0xBDC8, 0x997A, 0xBDC9, 0x7F34,
+	0xBDCA, 0x7EDE, 0xBDCB, 0x527F, 0xBDCC, 0x6559, 0xBDCD, 0x9175,
+	0xBDCE, 0x8F7F, 0xBDCF, 0x8F83, 0xBDD0, 0x53EB, 0xBDD1, 0x7A96,
+	0xBDD2, 0x63ED, 0xBDD3, 0x63A5, 0xBDD4, 0x7686, 0xBDD5, 0x79F8,
+	0xBDD6, 0x8857, 0xBDD7, 0x9636, 0xBDD8, 0x622A, 0xBDD9, 0x52AB,
+	0xBDDA, 0x8282, 0xBDDB, 0x6854, 0xBDDC, 0x6770, 0xBDDD, 0x6377,
+	0xBDDE, 0x776B, 0xBDDF, 0x7AED, 0xBDE0, 0x6D01, 0xBDE1, 0x7ED3,
+	0xBDE2, 0x89E3, 0xBDE3, 0x59D0, 0xBDE4, 0x6212, 0xBDE5, 0x85C9,
+	0xBDE6, 0x82A5, 0xBDE7, 0x754C, 0xBDE8, 0x501F, 0xBDE9, 0x4ECB,
+	0xBDEA, 0x75A5, 0xBDEB, 0x8BEB, 0xBDEC, 0x5C4A, 0xBDED, 0x5DFE,
+	0xBDEE, 0x7B4B, 0xBDEF, 0x65A4, 0xBDF0, 0x91D1, 0xBDF1, 0x4ECA,
+	0xBDF2, 0x6D25, 0xBDF3, 0x895F, 0xBDF4, 0x7D27, 0xBDF5, 0x9526,
+	0xBDF6, 0x4EC5, 0xBDF7, 0x8C28, 0xBDF8, 0x8FDB, 0xBDF9, 0x9773,
+	0xBDFA, 0x664B, 0xBDFB, 0x7981, 0xBDFC, 0x8FD1, 0xBDFD, 0x70EC,
+	0xBDFE, 0x6D78, 0xBE40, 0x7D99, 0xBE41, 0x7D9A, 0xBE42, 0x7D9B,
+	0xBE43, 0x7D9C, 0xBE44, 0x7D9D, 0xBE45, 0x7D9E, 0xBE46, 0x7D9F,
+	0xBE47, 0x7DA0, 0xBE48, 0x7DA1, 0xBE49, 0x7DA2, 0xBE4A, 0x7DA3,
+	0xBE4B, 0x7DA4, 0xBE4C, 0x7DA5, 0xBE4D, 0x7DA7, 0xBE4E, 0x7DA8,
+	0xBE4F, 0x7DA9, 0xBE50, 0x7DAA, 0xBE51, 0x7DAB, 0xBE52, 0x7DAC,
+	0xBE53, 0x7DAD, 0xBE54, 0x7DAF, 0xBE55, 0x7DB0, 0xBE56, 0x7DB1,
+	0xBE57, 0x7DB2, 0xBE58, 0x7DB3, 0xBE59, 0x7DB4, 0xBE5A, 0x7DB5,
+	0xBE5B, 0x7DB6, 0xBE5C, 0x7DB7, 0xBE5D, 0x7DB8, 0xBE5E, 0x7DB9,
+	0xBE5F, 0x7DBA, 0xBE60, 0x7DBB, 0xBE61, 0x7DBC, 0xBE62, 0x7DBD,
+	0xBE63, 0x7DBE, 0xBE64, 0x7DBF, 0xBE65, 0x7DC0, 0xBE66, 0x7DC1,
+	0xBE67, 0x7DC2, 0xBE68, 0x7DC3, 0xBE69, 0x7DC4, 0xBE6A, 0x7DC5,
+	0xBE6B, 0x7DC6, 0xBE6C, 0x7DC7, 0xBE6D, 0x7DC8, 0xBE6E, 0x7DC9,
+	0xBE6F, 0x7DCA, 0xBE70, 0x7DCB, 0xBE71, 0x7DCC, 0xBE72, 0x7DCD,
+	0xBE73, 0x7DCE, 0xBE74, 0x7DCF, 0xBE75, 0x7DD0, 0xBE76, 0x7DD1,
+	0xBE77, 0x7DD2, 0xBE78, 0x7DD3, 0xBE79, 0x7DD4, 0xBE7A, 0x7DD5,
+	0xBE7B, 0x7DD6, 0xBE7C, 0x7DD7, 0xBE7D, 0x7DD8, 0xBE7E, 0x7DD9,
+	0xBE80, 0x7DDA, 0xBE81, 0x7DDB, 0xBE82, 0x7DDC, 0xBE83, 0x7DDD,
+	0xBE84, 0x7DDE, 0xBE85, 0x7DDF, 0xBE86, 0x7DE0, 0xBE87, 0x7DE1,
+	0xBE88, 0x7DE2, 0xBE89, 0x7DE3, 0xBE8A, 0x7DE4, 0xBE8B, 0x7DE5,
+	0xBE8C, 0x7DE6, 0xBE8D, 0x7DE7, 0xBE8E, 0x7DE8, 0xBE8F, 0x7DE9,
+	0xBE90, 0x7DEA, 0xBE91, 0x7DEB, 0xBE92, 0x7DEC, 0xBE93, 0x7DED,
+	0xBE94, 0x7DEE, 0xBE95, 0x7DEF, 0xBE96, 0x7DF0, 0xBE97, 0x7DF1,
+	0xBE98, 0x7DF2, 0xBE99, 0x7DF3, 0xBE9A, 0x7DF4, 0xBE9B, 0x7DF5,
+	0xBE9C, 0x7DF6, 0xBE9D, 0x7DF7, 0xBE9E, 0x7DF8, 0xBE9F, 0x7DF9,
+	0xBEA0, 0x7DFA, 0xBEA1, 0x5C3D, 0xBEA2, 0x52B2, 0xBEA3, 0x8346,
+	0xBEA4, 0x5162, 0xBEA5, 0x830E, 0xBEA6, 0x775B, 0xBEA7, 0x6676,
+	0xBEA8, 0x9CB8, 0xBEA9, 0x4EAC, 0xBEAA, 0x60CA, 0xBEAB, 0x7CBE,
+	0xBEAC, 0x7CB3, 0xBEAD, 0x7ECF, 0xBEAE, 0x4E95, 0xBEAF, 0x8B66,
+	0xBEB0, 0x666F, 0xBEB1, 0x9888, 0xBEB2, 0x9759, 0xBEB3, 0x5883,
+	0xBEB4, 0x656C, 0xBEB5, 0x955C, 0xBEB6, 0x5F84, 0xBEB7, 0x75C9,
+	0xBEB8, 0x9756, 0xBEB9, 0x7ADF, 0xBEBA, 0x7ADE, 0xBEBB, 0x51C0,
+	0xBEBC, 0x70AF, 0xBEBD, 0x7A98, 0xBEBE, 0x63EA, 0xBEBF, 0x7A76,
+	0xBEC0, 0x7EA0, 0xBEC1, 0x7396, 0xBEC2, 0x97ED, 0xBEC3, 0x4E45,
+	0xBEC4, 0x7078, 0xBEC5, 0x4E5D, 0xBEC6, 0x9152, 0xBEC7, 0x53A9,
+	0xBEC8, 0x6551, 0xBEC9, 0x65E7, 0xBECA, 0x81FC, 0xBECB, 0x8205,
+	0xBECC, 0x548E, 0xBECD, 0x5C31, 0xBECE, 0x759A, 0xBECF, 0x97A0,
+	0xBED0, 0x62D8, 0xBED1, 0x72D9, 0xBED2, 0x75BD, 0xBED3, 0x5C45,
+	0xBED4, 0x9A79, 0xBED5, 0x83CA, 0xBED6, 0x5C40, 0xBED7, 0x5480,
+	0xBED8, 0x77E9, 0xBED9, 0x4E3E, 0xBEDA, 0x6CAE, 0xBEDB, 0x805A,
+	0xBEDC, 0x62D2, 0xBEDD, 0x636E, 0xBEDE, 0x5DE8, 0xBEDF, 0x5177,
+	0xBEE0, 0x8DDD, 0xBEE1, 0x8E1E, 0xBEE2, 0x952F, 0xBEE3, 0x4FF1,
+	0xBEE4, 0x53E5, 0xBEE5, 0x60E7, 0xBEE6, 0x70AC, 0xBEE7, 0x5267,
+	0xBEE8, 0x6350, 0xBEE9, 0x9E43, 0xBEEA, 0x5A1F, 0xBEEB, 0x5026,
+	0xBEEC, 0x7737, 0xBEED, 0x5377, 0xBEEE, 0x7EE2, 0xBEEF, 0x6485,
+	0xBEF0, 0x652B, 0xBEF1, 0x6289, 0xBEF2, 0x6398, 0xBEF3, 0x5014,
+	0xBEF4, 0x7235, 0xBEF5, 0x89C9, 0xBEF6, 0x51B3, 0xBEF7, 0x8BC0,
+	0xBEF8, 0x7EDD, 0xBEF9, 0x5747, 0xBEFA, 0x83CC, 0xBEFB, 0x94A7,
+	0xBEFC, 0x519B, 0xBEFD, 0x541B, 0xBEFE, 0x5CFB, 0xBF40, 0x7DFB,
+	0xBF41, 0x7DFC, 0xBF42, 0x7DFD, 0xBF43, 0x7DFE, 0xBF44, 0x7DFF,
+	0xBF45, 0x7E00, 0xBF46, 0x7E01, 0xBF47, 0x7E02, 0xBF48, 0x7E03,
+	0xBF49, 0x7E04, 0xBF4A, 0x7E05, 0xBF4B, 0x7E06, 0xBF4C, 0x7E07,
+	0xBF4D, 0x7E08, 0xBF4E, 0x7E09, 0xBF4F, 0x7E0A, 0xBF50, 0x7E0B,
+	0xBF51, 0x7E0C, 0xBF52, 0x7E0D, 0xBF53, 0x7E0E, 0xBF54, 0x7E0F,
+	0xBF55, 0x7E10, 0xBF56, 0x7E11, 0xBF57, 0x7E12, 0xBF58, 0x7E13,
+	0xBF59, 0x7E14, 0xBF5A, 0x7E15, 0xBF5B, 0x7E16, 0xBF5C, 0x7E17,
+	0xBF5D, 0x7E18, 0xBF5E, 0x7E19, 0xBF5F, 0x7E1A, 0xBF60, 0x7E1B,
+	0xBF61, 0x7E1C, 0xBF62, 0x7E1D, 0xBF63, 0x7E1E, 0xBF64, 0x7E1F,
+	0xBF65, 0x7E20, 0xBF66, 0x7E21, 0xBF67, 0x7E22, 0xBF68, 0x7E23,
+	0xBF69, 0x7E24, 0xBF6A, 0x7E25, 0xBF6B, 0x7E26, 0xBF6C, 0x7E27,
+	0xBF6D, 0x7E28, 0xBF6E, 0x7E29, 0xBF6F, 0x7E2A, 0xBF70, 0x7E2B,
+	0xBF71, 0x7E2C, 0xBF72, 0x7E2D, 0xBF73, 0x7E2E, 0xBF74, 0x7E2F,
+	0xBF75, 0x7E30, 0xBF76, 0x7E31, 0xBF77, 0x7E32, 0xBF78, 0x7E33,
+	0xBF79, 0x7E34, 0xBF7A, 0x7E35, 0xBF7B, 0x7E36, 0xBF7C, 0x7E37,
+	0xBF7D, 0x7E38, 0xBF7E, 0x7E39, 0xBF80, 0x7E3A, 0xBF81, 0x7E3C,
+	0xBF82, 0x7E3D, 0xBF83, 0x7E3E, 0xBF84, 0x7E3F, 0xBF85, 0x7E40,
+	0xBF86, 0x7E42, 0xBF87, 0x7E43, 0xBF88, 0x7E44, 0xBF89, 0x7E45,
+	0xBF8A, 0x7E46, 0xBF8B, 0x7E48, 0xBF8C, 0x7E49, 0xBF8D, 0x7E4A,
+	0xBF8E, 0x7E4B, 0xBF8F, 0x7E4C, 0xBF90, 0x7E4D, 0xBF91, 0x7E4E,
+	0xBF92, 0x7E4F, 0xBF93, 0x7E50, 0xBF94, 0x7E51, 0xBF95, 0x7E52,
+	0xBF96, 0x7E53, 0xBF97, 0x7E54, 0xBF98, 0x7E55, 0xBF99, 0x7E56,
+	0xBF9A, 0x7E57, 0xBF9B, 0x7E58, 0xBF9C, 0x7E59, 0xBF9D, 0x7E5A,
+	0xBF9E, 0x7E5B, 0xBF9F, 0x7E5C, 0xBFA0, 0x7E5D, 0xBFA1, 0x4FCA,
+	0xBFA2, 0x7AE3, 0xBFA3, 0x6D5A, 0xBFA4, 0x90E1, 0xBFA5, 0x9A8F,
+	0xBFA6, 0x5580, 0xBFA7, 0x5496, 0xBFA8, 0x5361, 0xBFA9, 0x54AF,
+	0xBFAA, 0x5F00, 0xBFAB, 0x63E9, 0xBFAC, 0x6977, 0xBFAD, 0x51EF,
+	0xBFAE, 0x6168, 0xBFAF, 0x520A, 0xBFB0, 0x582A, 0xBFB1, 0x52D8,
+	0xBFB2, 0x574E, 0xBFB3, 0x780D, 0xBFB4, 0x770B, 0xBFB5, 0x5EB7,
+	0xBFB6, 0x6177, 0xBFB7, 0x7CE0, 0xBFB8, 0x625B, 0xBFB9, 0x6297,
+	0xBFBA, 0x4EA2, 0xBFBB, 0x7095, 0xBFBC, 0x8003, 0xBFBD, 0x62F7,
+	0xBFBE, 0x70E4, 0xBFBF, 0x9760, 0xBFC0, 0x5777, 0xBFC1, 0x82DB,
+	0xBFC2, 0x67EF, 0xBFC3, 0x68F5, 0xBFC4, 0x78D5, 0xBFC5, 0x9897,
+	0xBFC6, 0x79D1, 0xBFC7, 0x58F3, 0xBFC8, 0x54B3, 0xBFC9, 0x53EF,
+	0xBFCA, 0x6E34, 0xBFCB, 0x514B, 0xBFCC, 0x523B, 0xBFCD, 0x5BA2,
+	0xBFCE, 0x8BFE, 0xBFCF, 0x80AF, 0xBFD0, 0x5543, 0xBFD1, 0x57A6,
+	0xBFD2, 0x6073, 0xBFD3, 0x5751, 0xBFD4, 0x542D, 0xBFD5, 0x7A7A,
+	0xBFD6, 0x6050, 0xBFD7, 0x5B54, 0xBFD8, 0x63A7, 0xBFD9, 0x62A0,
+	0xBFDA, 0x53E3, 0xBFDB, 0x6263, 0xBFDC, 0x5BC7, 0xBFDD, 0x67AF,
+	0xBFDE, 0x54ED, 0xBFDF, 0x7A9F, 0xBFE0, 0x82E6, 0xBFE1, 0x9177,
+	0xBFE2, 0x5E93, 0xBFE3, 0x88E4, 0xBFE4, 0x5938, 0xBFE5, 0x57AE,
+	0xBFE6, 0x630E, 0xBFE7, 0x8DE8, 0xBFE8, 0x80EF, 0xBFE9, 0x5757,
+	0xBFEA, 0x7B77, 0xBFEB, 0x4FA9, 0xBFEC, 0x5FEB, 0xBFED, 0x5BBD,
+	0xBFEE, 0x6B3E, 0xBFEF, 0x5321, 0xBFF0, 0x7B50, 0xBFF1, 0x72C2,
+	0xBFF2, 0x6846, 0xBFF3, 0x77FF, 0xBFF4, 0x7736, 0xBFF5, 0x65F7,
+	0xBFF6, 0x51B5, 0xBFF7, 0x4E8F, 0xBFF8, 0x76D4, 0xBFF9, 0x5CBF,
+	0xBFFA, 0x7AA5, 0xBFFB, 0x8475, 0xBFFC, 0x594E, 0xBFFD, 0x9B41,
+	0xBFFE, 0x5080, 0xC040, 0x7E5E, 0xC041, 0x7E5F, 0xC042, 0x7E60,
+	0xC043, 0x7E61, 0xC044, 0x7E62, 0xC045, 0x7E63, 0xC046, 0x7E64,
+	0xC047, 0x7E65, 0xC048, 0x7E66, 0xC049, 0x7E67, 0xC04A, 0x7E68,
+	0xC04B, 0x7E69, 0xC04C, 0x7E6A, 0xC04D, 0x7E6B, 0xC04E, 0x7E6C,
+	0xC04F, 0x7E6D, 0xC050, 0x7E6E, 0xC051, 0x7E6F, 0xC052, 0x7E70,
+	0xC053, 0x7E71, 0xC054, 0x7E72, 0xC055, 0x7E73, 0xC056, 0x7E74,
+	0xC057, 0x7E75, 0xC058, 0x7E76, 0xC059, 0x7E77, 0xC05A, 0x7E78,
+	0xC05B, 0x7E79, 0xC05C, 0x7E7A, 0xC05D, 0x7E7B, 0xC05E, 0x7E7C,
+	0xC05F, 0x7E7D, 0xC060, 0x7E7E, 0xC061, 0x7E7F, 0xC062, 0x7E80,
+	0xC063, 0x7E81, 0xC064, 0x7E83, 0xC065, 0x7E84, 0xC066, 0x7E85,
+	0xC067, 0x7E86, 0xC068, 0x7E87, 0xC069, 0x7E88, 0xC06A, 0x7E89,
+	0xC06B, 0x7E8A, 0xC06C, 0x7E8B, 0xC06D, 0x7E8C, 0xC06E, 0x7E8D,
+	0xC06F, 0x7E8E, 0xC070, 0x7E8F, 0xC071, 0x7E90, 0xC072, 0x7E91,
+	0xC073, 0x7E92, 0xC074, 0x7E93, 0xC075, 0x7E94, 0xC076, 0x7E95,
+	0xC077, 0x7E96, 0xC078, 0x7E97, 0xC079, 0x7E98, 0xC07A, 0x7E99,
+	0xC07B, 0x7E9A, 0xC07C, 0x7E9C, 0xC07D, 0x7E9D, 0xC07E, 0x7E9E,
+	0xC080, 0x7EAE, 0xC081, 0x7EB4, 0xC082, 0x7EBB, 0xC083, 0x7EBC,
+	0xC084, 0x7ED6, 0xC085, 0x7EE4, 0xC086, 0x7EEC, 0xC087, 0x7EF9,
+	0xC088, 0x7F0A, 0xC089, 0x7F10, 0xC08A, 0x7F1E, 0xC08B, 0x7F37,
+	0xC08C, 0x7F39, 0xC08D, 0x7F3B, 0xC08E, 0x7F3C, 0xC08F, 0x7F3D,
+	0xC090, 0x7F3E, 0xC091, 0x7F3F, 0xC092, 0x7F40, 0xC093, 0x7F41,
+	0xC094, 0x7F43, 0xC095, 0x7F46, 0xC096, 0x7F47, 0xC097, 0x7F48,
+	0xC098, 0x7F49, 0xC099, 0x7F4A, 0xC09A, 0x7F4B, 0xC09B, 0x7F4C,
+	0xC09C, 0x7F4D, 0xC09D, 0x7F4E, 0xC09E, 0x7F4F, 0xC09F, 0x7F52,
+	0xC0A0, 0x7F53, 0xC0A1, 0x9988, 0xC0A2, 0x6127, 0xC0A3, 0x6E83,
+	0xC0A4, 0x5764, 0xC0A5, 0x6606, 0xC0A6, 0x6346, 0xC0A7, 0x56F0,
+	0xC0A8, 0x62EC, 0xC0A9, 0x6269, 0xC0AA, 0x5ED3, 0xC0AB, 0x9614,
+	0xC0AC, 0x5783, 0xC0AD, 0x62C9, 0xC0AE, 0x5587, 0xC0AF, 0x8721,
+	0xC0B0, 0x814A, 0xC0B1, 0x8FA3, 0xC0B2, 0x5566, 0xC0B3, 0x83B1,
+	0xC0B4, 0x6765, 0xC0B5, 0x8D56, 0xC0B6, 0x84DD, 0xC0B7, 0x5A6A,
+	0xC0B8, 0x680F, 0xC0B9, 0x62E6, 0xC0BA, 0x7BEE, 0xC0BB, 0x9611,
+	0xC0BC, 0x5170, 0xC0BD, 0x6F9C, 0xC0BE, 0x8C30, 0xC0BF, 0x63FD,
+	0xC0C0, 0x89C8, 0xC0C1, 0x61D2, 0xC0C2, 0x7F06, 0xC0C3, 0x70C2,
+	0xC0C4, 0x6EE5, 0xC0C5, 0x7405, 0xC0C6, 0x6994, 0xC0C7, 0x72FC,
+	0xC0C8, 0x5ECA, 0xC0C9, 0x90CE, 0xC0CA, 0x6717, 0xC0CB, 0x6D6A,
+	0xC0CC, 0x635E, 0xC0CD, 0x52B3, 0xC0CE, 0x7262, 0xC0CF, 0x8001,
+	0xC0D0, 0x4F6C, 0xC0D1, 0x59E5, 0xC0D2, 0x916A, 0xC0D3, 0x70D9,
+	0xC0D4, 0x6D9D, 0xC0D5, 0x52D2, 0xC0D6, 0x4E50, 0xC0D7, 0x96F7,
+	0xC0D8, 0x956D, 0xC0D9, 0x857E, 0xC0DA, 0x78CA, 0xC0DB, 0x7D2F,
+	0xC0DC, 0x5121, 0xC0DD, 0x5792, 0xC0DE, 0x64C2, 0xC0DF, 0x808B,
+	0xC0E0, 0x7C7B, 0xC0E1, 0x6CEA, 0xC0E2, 0x68F1, 0xC0E3, 0x695E,
+	0xC0E4, 0x51B7, 0xC0E5, 0x5398, 0xC0E6, 0x68A8, 0xC0E7, 0x7281,
+	0xC0E8, 0x9ECE, 0xC0E9, 0x7BF1, 0xC0EA, 0x72F8, 0xC0EB, 0x79BB,
+	0xC0EC, 0x6F13, 0xC0ED, 0x7406, 0xC0EE, 0x674E, 0xC0EF, 0x91CC,
+	0xC0F0, 0x9CA4, 0xC0F1, 0x793C, 0xC0F2, 0x8389, 0xC0F3, 0x8354,
+	0xC0F4, 0x540F, 0xC0F5, 0x6817, 0xC0F6, 0x4E3D, 0xC0F7, 0x5389,
+	0xC0F8, 0x52B1, 0xC0F9, 0x783E, 0xC0FA, 0x5386, 0xC0FB, 0x5229,
+	0xC0FC, 0x5088, 0xC0FD, 0x4F8B, 0xC0FE, 0x4FD0, 0xC140, 0x7F56,
+	0xC141, 0x7F59, 0xC142, 0x7F5B, 0xC143, 0x7F5C, 0xC144, 0x7F5D,
+	0xC145, 0x7F5E, 0xC146, 0x7F60, 0xC147, 0x7F63, 0xC148, 0x7F64,
+	0xC149, 0x7F65, 0xC14A, 0x7F66, 0xC14B, 0x7F67, 0xC14C, 0x7F6B,
+	0xC14D, 0x7F6C, 0xC14E, 0x7F6D, 0xC14F, 0x7F6F, 0xC150, 0x7F70,
+	0xC151, 0x7F73, 0xC152, 0x7F75, 0xC153, 0x7F76, 0xC154, 0x7F77,
+	0xC155, 0x7F78, 0xC156, 0x7F7A, 0xC157, 0x7F7B, 0xC158, 0x7F7C,
+	0xC159, 0x7F7D, 0xC15A, 0x7F7F, 0xC15B, 0x7F80, 0xC15C, 0x7F82,
+	0xC15D, 0x7F83, 0xC15E, 0x7F84, 0xC15F, 0x7F85, 0xC160, 0x7F86,
+	0xC161, 0x7F87, 0xC162, 0x7F88, 0xC163, 0x7F89, 0xC164, 0x7F8B,
+	0xC165, 0x7F8D, 0xC166, 0x7F8F, 0xC167, 0x7F90, 0xC168, 0x7F91,
+	0xC169, 0x7F92, 0xC16A, 0x7F93, 0xC16B, 0x7F95, 0xC16C, 0x7F96,
+	0xC16D, 0x7F97, 0xC16E, 0x7F98, 0xC16F, 0x7F99, 0xC170, 0x7F9B,
+	0xC171, 0x7F9C, 0xC172, 0x7FA0, 0xC173, 0x7FA2, 0xC174, 0x7FA3,
+	0xC175, 0x7FA5, 0xC176, 0x7FA6, 0xC177, 0x7FA8, 0xC178, 0x7FA9,
+	0xC179, 0x7FAA, 0xC17A, 0x7FAB, 0xC17B, 0x7FAC, 0xC17C, 0x7FAD,
+	0xC17D, 0x7FAE, 0xC17E, 0x7FB1, 0xC180, 0x7FB3, 0xC181, 0x7FB4,
+	0xC182, 0x7FB5, 0xC183, 0x7FB6, 0xC184, 0x7FB7, 0xC185, 0x7FBA,
+	0xC186, 0x7FBB, 0xC187, 0x7FBE, 0xC188, 0x7FC0, 0xC189, 0x7FC2,
+	0xC18A, 0x7FC3, 0xC18B, 0x7FC4, 0xC18C, 0x7FC6, 0xC18D, 0x7FC7,
+	0xC18E, 0x7FC8, 0xC18F, 0x7FC9, 0xC190, 0x7FCB, 0xC191, 0x7FCD,
+	0xC192, 0x7FCF, 0xC193, 0x7FD0, 0xC194, 0x7FD1, 0xC195, 0x7FD2,
+	0xC196, 0x7FD3, 0xC197, 0x7FD6, 0xC198, 0x7FD7, 0xC199, 0x7FD9,
+	0xC19A, 0x7FDA, 0xC19B, 0x7FDB, 0xC19C, 0x7FDC, 0xC19D, 0x7FDD,
+	0xC19E, 0x7FDE, 0xC19F, 0x7FE2, 0xC1A0, 0x7FE3, 0xC1A1, 0x75E2,
+	0xC1A2, 0x7ACB, 0xC1A3, 0x7C92, 0xC1A4, 0x6CA5, 0xC1A5, 0x96B6,
+	0xC1A6, 0x529B, 0xC1A7, 0x7483, 0xC1A8, 0x54E9, 0xC1A9, 0x4FE9,
+	0xC1AA, 0x8054, 0xC1AB, 0x83B2, 0xC1AC, 0x8FDE, 0xC1AD, 0x9570,
+	0xC1AE, 0x5EC9, 0xC1AF, 0x601C, 0xC1B0, 0x6D9F, 0xC1B1, 0x5E18,
+	0xC1B2, 0x655B, 0xC1B3, 0x8138, 0xC1B4, 0x94FE, 0xC1B5, 0x604B,
+	0xC1B6, 0x70BC, 0xC1B7, 0x7EC3, 0xC1B8, 0x7CAE, 0xC1B9, 0x51C9,
+	0xC1BA, 0x6881, 0xC1BB, 0x7CB1, 0xC1BC, 0x826F, 0xC1BD, 0x4E24,
+	0xC1BE, 0x8F86, 0xC1BF, 0x91CF, 0xC1C0, 0x667E, 0xC1C1, 0x4EAE,
+	0xC1C2, 0x8C05, 0xC1C3, 0x64A9, 0xC1C4, 0x804A, 0xC1C5, 0x50DA,
+	0xC1C6, 0x7597, 0xC1C7, 0x71CE, 0xC1C8, 0x5BE5, 0xC1C9, 0x8FBD,
+	0xC1CA, 0x6F66, 0xC1CB, 0x4E86, 0xC1CC, 0x6482, 0xC1CD, 0x9563,
+	0xC1CE, 0x5ED6, 0xC1CF, 0x6599, 0xC1D0, 0x5217, 0xC1D1, 0x88C2,
+	0xC1D2, 0x70C8, 0xC1D3, 0x52A3, 0xC1D4, 0x730E, 0xC1D5, 0x7433,
+	0xC1D6, 0x6797, 0xC1D7, 0x78F7, 0xC1D8, 0x9716, 0xC1D9, 0x4E34,
+	0xC1DA, 0x90BB, 0xC1DB, 0x9CDE, 0xC1DC, 0x6DCB, 0xC1DD, 0x51DB,
+	0xC1DE, 0x8D41, 0xC1DF, 0x541D, 0xC1E0, 0x62CE, 0xC1E1, 0x73B2,
+	0xC1E2, 0x83F1, 0xC1E3, 0x96F6, 0xC1E4, 0x9F84, 0xC1E5, 0x94C3,
+	0xC1E6, 0x4F36, 0xC1E7, 0x7F9A, 0xC1E8, 0x51CC, 0xC1E9, 0x7075,
+	0xC1EA, 0x9675, 0xC1EB, 0x5CAD, 0xC1EC, 0x9886, 0xC1ED, 0x53E6,
+	0xC1EE, 0x4EE4, 0xC1EF, 0x6E9C, 0xC1F0, 0x7409, 0xC1F1, 0x69B4,
+	0xC1F2, 0x786B, 0xC1F3, 0x998F, 0xC1F4, 0x7559, 0xC1F5, 0x5218,
+	0xC1F6, 0x7624, 0xC1F7, 0x6D41, 0xC1F8, 0x67F3, 0xC1F9, 0x516D,
+	0xC1FA, 0x9F99, 0xC1FB, 0x804B, 0xC1FC, 0x5499, 0xC1FD, 0x7B3C,
+	0xC1FE, 0x7ABF, 0xC240, 0x7FE4, 0xC241, 0x7FE7, 0xC242, 0x7FE8,
+	0xC243, 0x7FEA, 0xC244, 0x7FEB, 0xC245, 0x7FEC, 0xC246, 0x7FED,
+	0xC247, 0x7FEF, 0xC248, 0x7FF2, 0xC249, 0x7FF4, 0xC24A, 0x7FF5,
+	0xC24B, 0x7FF6, 0xC24C, 0x7FF7, 0xC24D, 0x7FF8, 0xC24E, 0x7FF9,
+	0xC24F, 0x7FFA, 0xC250, 0x7FFD, 0xC251, 0x7FFE, 0xC252, 0x7FFF,
+	0xC253, 0x8002, 0xC254, 0x8007, 0xC255, 0x8008, 0xC256, 0x8009,
+	0xC257, 0x800A, 0xC258, 0x800E, 0xC259, 0x800F, 0xC25A, 0x8011,
+	0xC25B, 0x8013, 0xC25C, 0x801A, 0xC25D, 0x801B, 0xC25E, 0x801D,
+	0xC25F, 0x801E, 0xC260, 0x801F, 0xC261, 0x8021, 0xC262, 0x8023,
+	0xC263, 0x8024, 0xC264, 0x802B, 0xC265, 0x802C, 0xC266, 0x802D,
+	0xC267, 0x802E, 0xC268, 0x802F, 0xC269, 0x8030, 0xC26A, 0x8032,
+	0xC26B, 0x8034, 0xC26C, 0x8039, 0xC26D, 0x803A, 0xC26E, 0x803C,
+	0xC26F, 0x803E, 0xC270, 0x8040, 0xC271, 0x8041, 0xC272, 0x8044,
+	0xC273, 0x8045, 0xC274, 0x8047, 0xC275, 0x8048, 0xC276, 0x8049,
+	0xC277, 0x804E, 0xC278, 0x804F, 0xC279, 0x8050, 0xC27A, 0x8051,
+	0xC27B, 0x8053, 0xC27C, 0x8055, 0xC27D, 0x8056, 0xC27E, 0x8057,
+	0xC280, 0x8059, 0xC281, 0x805B, 0xC282, 0x805C, 0xC283, 0x805D,
+	0xC284, 0x805E, 0xC285, 0x805F, 0xC286, 0x8060, 0xC287, 0x8061,
+	0xC288, 0x8062, 0xC289, 0x8063, 0xC28A, 0x8064, 0xC28B, 0x8065,
+	0xC28C, 0x8066, 0xC28D, 0x8067, 0xC28E, 0x8068, 0xC28F, 0x806B,
+	0xC290, 0x806C, 0xC291, 0x806D, 0xC292, 0x806E, 0xC293, 0x806F,
+	0xC294, 0x8070, 0xC295, 0x8072, 0xC296, 0x8073, 0xC297, 0x8074,
+	0xC298, 0x8075, 0xC299, 0x8076, 0xC29A, 0x8077, 0xC29B, 0x8078,
+	0xC29C, 0x8079, 0xC29D, 0x807A, 0xC29E, 0x807B, 0xC29F, 0x807C,
+	0xC2A0, 0x807D, 0xC2A1, 0x9686, 0xC2A2, 0x5784, 0xC2A3, 0x62E2,
+	0xC2A4, 0x9647, 0xC2A5, 0x697C, 0xC2A6, 0x5A04, 0xC2A7, 0x6402,
+	0xC2A8, 0x7BD3, 0xC2A9, 0x6F0F, 0xC2AA, 0x964B, 0xC2AB, 0x82A6,
+	0xC2AC, 0x5362, 0xC2AD, 0x9885, 0xC2AE, 0x5E90, 0xC2AF, 0x7089,
+	0xC2B0, 0x63B3, 0xC2B1, 0x5364, 0xC2B2, 0x864F, 0xC2B3, 0x9C81,
+	0xC2B4, 0x9E93, 0xC2B5, 0x788C, 0xC2B6, 0x9732, 0xC2B7, 0x8DEF,
+	0xC2B8, 0x8D42, 0xC2B9, 0x9E7F, 0xC2BA, 0x6F5E, 0xC2BB, 0x7984,
+	0xC2BC, 0x5F55, 0xC2BD, 0x9646, 0xC2BE, 0x622E, 0xC2BF, 0x9A74,
+	0xC2C0, 0x5415, 0xC2C1, 0x94DD, 0xC2C2, 0x4FA3, 0xC2C3, 0x65C5,
+	0xC2C4, 0x5C65, 0xC2C5, 0x5C61, 0xC2C6, 0x7F15, 0xC2C7, 0x8651,
+	0xC2C8, 0x6C2F, 0xC2C9, 0x5F8B, 0xC2CA, 0x7387, 0xC2CB, 0x6EE4,
+	0xC2CC, 0x7EFF, 0xC2CD, 0x5CE6, 0xC2CE, 0x631B, 0xC2CF, 0x5B6A,
+	0xC2D0, 0x6EE6, 0xC2D1, 0x5375, 0xC2D2, 0x4E71, 0xC2D3, 0x63A0,
+	0xC2D4, 0x7565, 0xC2D5, 0x62A1, 0xC2D6, 0x8F6E, 0xC2D7, 0x4F26,
+	0xC2D8, 0x4ED1, 0xC2D9, 0x6CA6, 0xC2DA, 0x7EB6, 0xC2DB, 0x8BBA,
+	0xC2DC, 0x841D, 0xC2DD, 0x87BA, 0xC2DE, 0x7F57, 0xC2DF, 0x903B,
+	0xC2E0, 0x9523, 0xC2E1, 0x7BA9, 0xC2E2, 0x9AA1, 0xC2E3, 0x88F8,
+	0xC2E4, 0x843D, 0xC2E5, 0x6D1B, 0xC2E6, 0x9A86, 0xC2E7, 0x7EDC,
+	0xC2E8, 0x5988, 0xC2E9, 0x9EBB, 0xC2EA, 0x739B, 0xC2EB, 0x7801,
+	0xC2EC, 0x8682, 0xC2ED, 0x9A6C, 0xC2EE, 0x9A82, 0xC2EF, 0x561B,
+	0xC2F0, 0x5417, 0xC2F1, 0x57CB, 0xC2F2, 0x4E70, 0xC2F3, 0x9EA6,
+	0xC2F4, 0x5356, 0xC2F5, 0x8FC8, 0xC2F6, 0x8109, 0xC2F7, 0x7792,
+	0xC2F8, 0x9992, 0xC2F9, 0x86EE, 0xC2FA, 0x6EE1, 0xC2FB, 0x8513,
+	0xC2FC, 0x66FC, 0xC2FD, 0x6162, 0xC2FE, 0x6F2B, 0xC340, 0x807E,
+	0xC341, 0x8081, 0xC342, 0x8082, 0xC343, 0x8085, 0xC344, 0x8088,
+	0xC345, 0x808A, 0xC346, 0x808D, 0xC347, 0x808E, 0xC348, 0x808F,
+	0xC349, 0x8090, 0xC34A, 0x8091, 0xC34B, 0x8092, 0xC34C, 0x8094,
+	0xC34D, 0x8095, 0xC34E, 0x8097, 0xC34F, 0x8099, 0xC350, 0x809E,
+	0xC351, 0x80A3, 0xC352, 0x80A6, 0xC353, 0x80A7, 0xC354, 0x80A8,
+	0xC355, 0x80AC, 0xC356, 0x80B0, 0xC357, 0x80B3, 0xC358, 0x80B5,
+	0xC359, 0x80B6, 0xC35A, 0x80B8, 0xC35B, 0x80B9, 0xC35C, 0x80BB,
+	0xC35D, 0x80C5, 0xC35E, 0x80C7, 0xC35F, 0x80C8, 0xC360, 0x80C9,
+	0xC361, 0x80CA, 0xC362, 0x80CB, 0xC363, 0x80CF, 0xC364, 0x80D0,
+	0xC365, 0x80D1, 0xC366, 0x80D2, 0xC367, 0x80D3, 0xC368, 0x80D4,
+	0xC369, 0x80D5, 0xC36A, 0x80D8, 0xC36B, 0x80DF, 0xC36C, 0x80E0,
+	0xC36D, 0x80E2, 0xC36E, 0x80E3, 0xC36F, 0x80E6, 0xC370, 0x80EE,
+	0xC371, 0x80F5, 0xC372, 0x80F7, 0xC373, 0x80F9, 0xC374, 0x80FB,
+	0xC375, 0x80FE, 0xC376, 0x80FF, 0xC377, 0x8100, 0xC378, 0x8101,
+	0xC379, 0x8103, 0xC37A, 0x8104, 0xC37B, 0x8105, 0xC37C, 0x8107,
+	0xC37D, 0x8108, 0xC37E, 0x810B, 0xC380, 0x810C, 0xC381, 0x8115,
+	0xC382, 0x8117, 0xC383, 0x8119, 0xC384, 0x811B, 0xC385, 0x811C,
+	0xC386, 0x811D, 0xC387, 0x811F, 0xC388, 0x8120, 0xC389, 0x8121,
+	0xC38A, 0x8122, 0xC38B, 0x8123, 0xC38C, 0x8124, 0xC38D, 0x8125,
+	0xC38E, 0x8126, 0xC38F, 0x8127, 0xC390, 0x8128, 0xC391, 0x8129,
+	0xC392, 0x812A, 0xC393, 0x812B, 0xC394, 0x812D, 0xC395, 0x812E,
+	0xC396, 0x8130, 0xC397, 0x8133, 0xC398, 0x8134, 0xC399, 0x8135,
+	0xC39A, 0x8137, 0xC39B, 0x8139, 0xC39C, 0x813A, 0xC39D, 0x813B,
+	0xC39E, 0x813C, 0xC39F, 0x813D, 0xC3A0, 0x813F, 0xC3A1, 0x8C29,
+	0xC3A2, 0x8292, 0xC3A3, 0x832B, 0xC3A4, 0x76F2, 0xC3A5, 0x6C13,
+	0xC3A6, 0x5FD9, 0xC3A7, 0x83BD, 0xC3A8, 0x732B, 0xC3A9, 0x8305,
+	0xC3AA, 0x951A, 0xC3AB, 0x6BDB, 0xC3AC, 0x77DB, 0xC3AD, 0x94C6,
+	0xC3AE, 0x536F, 0xC3AF, 0x8302, 0xC3B0, 0x5192, 0xC3B1, 0x5E3D,
+	0xC3B2, 0x8C8C, 0xC3B3, 0x8D38, 0xC3B4, 0x4E48, 0xC3B5, 0x73AB,
+	0xC3B6, 0x679A, 0xC3B7, 0x6885, 0xC3B8, 0x9176, 0xC3B9, 0x9709,
+	0xC3BA, 0x7164, 0xC3BB, 0x6CA1, 0xC3BC, 0x7709, 0xC3BD, 0x5A92,
+	0xC3BE, 0x9541, 0xC3BF, 0x6BCF, 0xC3C0, 0x7F8E, 0xC3C1, 0x6627,
+	0xC3C2, 0x5BD0, 0xC3C3, 0x59B9, 0xC3C4, 0x5A9A, 0xC3C5, 0x95E8,
+	0xC3C6, 0x95F7, 0xC3C7, 0x4EEC, 0xC3C8, 0x840C, 0xC3C9, 0x8499,
+	0xC3CA, 0x6AAC, 0xC3CB, 0x76DF, 0xC3CC, 0x9530, 0xC3CD, 0x731B,
+	0xC3CE, 0x68A6, 0xC3CF, 0x5B5F, 0xC3D0, 0x772F, 0xC3D1, 0x919A,
+	0xC3D2, 0x9761, 0xC3D3, 0x7CDC, 0xC3D4, 0x8FF7, 0xC3D5, 0x8C1C,
+	0xC3D6, 0x5F25, 0xC3D7, 0x7C73, 0xC3D8, 0x79D8, 0xC3D9, 0x89C5,
+	0xC3DA, 0x6CCC, 0xC3DB, 0x871C, 0xC3DC, 0x5BC6, 0xC3DD, 0x5E42,
+	0xC3DE, 0x68C9, 0xC3DF, 0x7720, 0xC3E0, 0x7EF5, 0xC3E1, 0x5195,
+	0xC3E2, 0x514D, 0xC3E3, 0x52C9, 0xC3E4, 0x5A29, 0xC3E5, 0x7F05,
+	0xC3E6, 0x9762, 0xC3E7, 0x82D7, 0xC3E8, 0x63CF, 0xC3E9, 0x7784,
+	0xC3EA, 0x85D0, 0xC3EB, 0x79D2, 0xC3EC, 0x6E3A, 0xC3ED, 0x5E99,
+	0xC3EE, 0x5999, 0xC3EF, 0x8511, 0xC3F0, 0x706D, 0xC3F1, 0x6C11,
+	0xC3F2, 0x62BF, 0xC3F3, 0x76BF, 0xC3F4, 0x654F, 0xC3F5, 0x60AF,
+	0xC3F6, 0x95FD, 0xC3F7, 0x660E, 0xC3F8, 0x879F, 0xC3F9, 0x9E23,
+	0xC3FA, 0x94ED, 0xC3FB, 0x540D, 0xC3FC, 0x547D, 0xC3FD, 0x8C2C,
+	0xC3FE, 0x6478, 0xC440, 0x8140, 0xC441, 0x8141, 0xC442, 0x8142,
+	0xC443, 0x8143, 0xC444, 0x8144, 0xC445, 0x8145, 0xC446, 0x8147,
+	0xC447, 0x8149, 0xC448, 0x814D, 0xC449, 0x814E, 0xC44A, 0x814F,
+	0xC44B, 0x8152, 0xC44C, 0x8156, 0xC44D, 0x8157, 0xC44E, 0x8158,
+	0xC44F, 0x815B, 0xC450, 0x815C, 0xC451, 0x815D, 0xC452, 0x815E,
+	0xC453, 0x815F, 0xC454, 0x8161, 0xC455, 0x8162, 0xC456, 0x8163,
+	0xC457, 0x8164, 0xC458, 0x8166, 0xC459, 0x8168, 0xC45A, 0x816A,
+	0xC45B, 0x816B, 0xC45C, 0x816C, 0xC45D, 0x816F, 0xC45E, 0x8172,
+	0xC45F, 0x8173, 0xC460, 0x8175, 0xC461, 0x8176, 0xC462, 0x8177,
+	0xC463, 0x8178, 0xC464, 0x8181, 0xC465, 0x8183, 0xC466, 0x8184,
+	0xC467, 0x8185, 0xC468, 0x8186, 0xC469, 0x8187, 0xC46A, 0x8189,
+	0xC46B, 0x818B, 0xC46C, 0x818C, 0xC46D, 0x818D, 0xC46E, 0x818E,
+	0xC46F, 0x8190, 0xC470, 0x8192, 0xC471, 0x8193, 0xC472, 0x8194,
+	0xC473, 0x8195, 0xC474, 0x8196, 0xC475, 0x8197, 0xC476, 0x8199,
+	0xC477, 0x819A, 0xC478, 0x819E, 0xC479, 0x819F, 0xC47A, 0x81A0,
+	0xC47B, 0x81A1, 0xC47C, 0x81A2, 0xC47D, 0x81A4, 0xC47E, 0x81A5,
+	0xC480, 0x81A7, 0xC481, 0x81A9, 0xC482, 0x81AB, 0xC483, 0x81AC,
+	0xC484, 0x81AD, 0xC485, 0x81AE, 0xC486, 0x81AF, 0xC487, 0x81B0,
+	0xC488, 0x81B1, 0xC489, 0x81B2, 0xC48A, 0x81B4, 0xC48B, 0x81B5,
+	0xC48C, 0x81B6, 0xC48D, 0x81B7, 0xC48E, 0x81B8, 0xC48F, 0x81B9,
+	0xC490, 0x81BC, 0xC491, 0x81BD, 0xC492, 0x81BE, 0xC493, 0x81BF,
+	0xC494, 0x81C4, 0xC495, 0x81C5, 0xC496, 0x81C7, 0xC497, 0x81C8,
+	0xC498, 0x81C9, 0xC499, 0x81CB, 0xC49A, 0x81CD, 0xC49B, 0x81CE,
+	0xC49C, 0x81CF, 0xC49D, 0x81D0, 0xC49E, 0x81D1, 0xC49F, 0x81D2,
+	0xC4A0, 0x81D3, 0xC4A1, 0x6479, 0xC4A2, 0x8611, 0xC4A3, 0x6A21,
+	0xC4A4, 0x819C, 0xC4A5, 0x78E8, 0xC4A6, 0x6469, 0xC4A7, 0x9B54,
+	0xC4A8, 0x62B9, 0xC4A9, 0x672B, 0xC4AA, 0x83AB, 0xC4AB, 0x58A8,
+	0xC4AC, 0x9ED8, 0xC4AD, 0x6CAB, 0xC4AE, 0x6F20, 0xC4AF, 0x5BDE,
+	0xC4B0, 0x964C, 0xC4B1, 0x8C0B, 0xC4B2, 0x725F, 0xC4B3, 0x67D0,
+	0xC4B4, 0x62C7, 0xC4B5, 0x7261, 0xC4B6, 0x4EA9, 0xC4B7, 0x59C6,
+	0xC4B8, 0x6BCD, 0xC4B9, 0x5893, 0xC4BA, 0x66AE, 0xC4BB, 0x5E55,
+	0xC4BC, 0x52DF, 0xC4BD, 0x6155, 0xC4BE, 0x6728, 0xC4BF, 0x76EE,
+	0xC4C0, 0x7766, 0xC4C1, 0x7267, 0xC4C2, 0x7A46, 0xC4C3, 0x62FF,
+	0xC4C4, 0x54EA, 0xC4C5, 0x5450, 0xC4C6, 0x94A0, 0xC4C7, 0x90A3,
+	0xC4C8, 0x5A1C, 0xC4C9, 0x7EB3, 0xC4CA, 0x6C16, 0xC4CB, 0x4E43,
+	0xC4CC, 0x5976, 0xC4CD, 0x8010, 0xC4CE, 0x5948, 0xC4CF, 0x5357,
+	0xC4D0, 0x7537, 0xC4D1, 0x96BE, 0xC4D2, 0x56CA, 0xC4D3, 0x6320,
+	0xC4D4, 0x8111, 0xC4D5, 0x607C, 0xC4D6, 0x95F9, 0xC4D7, 0x6DD6,
+	0xC4D8, 0x5462, 0xC4D9, 0x9981, 0xC4DA, 0x5185, 0xC4DB, 0x5AE9,
+	0xC4DC, 0x80FD, 0xC4DD, 0x59AE, 0xC4DE, 0x9713, 0xC4DF, 0x502A,
+	0xC4E0, 0x6CE5, 0xC4E1, 0x5C3C, 0xC4E2, 0x62DF, 0xC4E3, 0x4F60,
+	0xC4E4, 0x533F, 0xC4E5, 0x817B, 0xC4E6, 0x9006, 0xC4E7, 0x6EBA,
+	0xC4E8, 0x852B, 0xC4E9, 0x62C8, 0xC4EA, 0x5E74, 0xC4EB, 0x78BE,
+	0xC4EC, 0x64B5, 0xC4ED, 0x637B, 0xC4EE, 0x5FF5, 0xC4EF, 0x5A18,
+	0xC4F0, 0x917F, 0xC4F1, 0x9E1F, 0xC4F2, 0x5C3F, 0xC4F3, 0x634F,
+	0xC4F4, 0x8042, 0xC4F5, 0x5B7D, 0xC4F6, 0x556E, 0xC4F7, 0x954A,
+	0xC4F8, 0x954D, 0xC4F9, 0x6D85, 0xC4FA, 0x60A8, 0xC4FB, 0x67E0,
+	0xC4FC, 0x72DE, 0xC4FD, 0x51DD, 0xC4FE, 0x5B81, 0xC540, 0x81D4,
+	0xC541, 0x81D5, 0xC542, 0x81D6, 0xC543, 0x81D7, 0xC544, 0x81D8,
+	0xC545, 0x81D9, 0xC546, 0x81DA, 0xC547, 0x81DB, 0xC548, 0x81DC,
+	0xC549, 0x81DD, 0xC54A, 0x81DE, 0xC54B, 0x81DF, 0xC54C, 0x81E0,
+	0xC54D, 0x81E1, 0xC54E, 0x81E2, 0xC54F, 0x81E4, 0xC550, 0x81E5,
+	0xC551, 0x81E6, 0xC552, 0x81E8, 0xC553, 0x81E9, 0xC554, 0x81EB,
+	0xC555, 0x81EE, 0xC556, 0x81EF, 0xC557, 0x81F0, 0xC558, 0x81F1,
+	0xC559, 0x81F2, 0xC55A, 0x81F5, 0xC55B, 0x81F6, 0xC55C, 0x81F7,
+	0xC55D, 0x81F8, 0xC55E, 0x81F9, 0xC55F, 0x81FA, 0xC560, 0x81FD,
+	0xC561, 0x81FF, 0xC562, 0x8203, 0xC563, 0x8207, 0xC564, 0x8208,
+	0xC565, 0x8209, 0xC566, 0x820A, 0xC567, 0x820B, 0xC568, 0x820E,
+	0xC569, 0x820F, 0xC56A, 0x8211, 0xC56B, 0x8213, 0xC56C, 0x8215,
+	0xC56D, 0x8216, 0xC56E, 0x8217, 0xC56F, 0x8218, 0xC570, 0x8219,
+	0xC571, 0x821A, 0xC572, 0x821D, 0xC573, 0x8220, 0xC574, 0x8224,
+	0xC575, 0x8225, 0xC576, 0x8226, 0xC577, 0x8227, 0xC578, 0x8229,
+	0xC579, 0x822E, 0xC57A, 0x8232, 0xC57B, 0x823A, 0xC57C, 0x823C,
+	0xC57D, 0x823D, 0xC57E, 0x823F, 0xC580, 0x8240, 0xC581, 0x8241,
+	0xC582, 0x8242, 0xC583, 0x8243, 0xC584, 0x8245, 0xC585, 0x8246,
+	0xC586, 0x8248, 0xC587, 0x824A, 0xC588, 0x824C, 0xC589, 0x824D,
+	0xC58A, 0x824E, 0xC58B, 0x8250, 0xC58C, 0x8251, 0xC58D, 0x8252,
+	0xC58E, 0x8253, 0xC58F, 0x8254, 0xC590, 0x8255, 0xC591, 0x8256,
+	0xC592, 0x8257, 0xC593, 0x8259, 0xC594, 0x825B, 0xC595, 0x825C,
+	0xC596, 0x825D, 0xC597, 0x825E, 0xC598, 0x8260, 0xC599, 0x8261,
+	0xC59A, 0x8262, 0xC59B, 0x8263, 0xC59C, 0x8264, 0xC59D, 0x8265,
+	0xC59E, 0x8266, 0xC59F, 0x8267, 0xC5A0, 0x8269, 0xC5A1, 0x62E7,
+	0xC5A2, 0x6CDE, 0xC5A3, 0x725B, 0xC5A4, 0x626D, 0xC5A5, 0x94AE,
+	0xC5A6, 0x7EBD, 0xC5A7, 0x8113, 0xC5A8, 0x6D53, 0xC5A9, 0x519C,
+	0xC5AA, 0x5F04, 0xC5AB, 0x5974, 0xC5AC, 0x52AA, 0xC5AD, 0x6012,
+	0xC5AE, 0x5973, 0xC5AF, 0x6696, 0xC5B0, 0x8650, 0xC5B1, 0x759F,
+	0xC5B2, 0x632A, 0xC5B3, 0x61E6, 0xC5B4, 0x7CEF, 0xC5B5, 0x8BFA,
+	0xC5B6, 0x54E6, 0xC5B7, 0x6B27, 0xC5B8, 0x9E25, 0xC5B9, 0x6BB4,
+	0xC5BA, 0x85D5, 0xC5BB, 0x5455, 0xC5BC, 0x5076, 0xC5BD, 0x6CA4,
+	0xC5BE, 0x556A, 0xC5BF, 0x8DB4, 0xC5C0, 0x722C, 0xC5C1, 0x5E15,
+	0xC5C2, 0x6015, 0xC5C3, 0x7436, 0xC5C4, 0x62CD, 0xC5C5, 0x6392,
+	0xC5C6, 0x724C, 0xC5C7, 0x5F98, 0xC5C8, 0x6E43, 0xC5C9, 0x6D3E,
+	0xC5CA, 0x6500, 0xC5CB, 0x6F58, 0xC5CC, 0x76D8, 0xC5CD, 0x78D0,
+	0xC5CE, 0x76FC, 0xC5CF, 0x7554, 0xC5D0, 0x5224, 0xC5D1, 0x53DB,
+	0xC5D2, 0x4E53, 0xC5D3, 0x5E9E, 0xC5D4, 0x65C1, 0xC5D5, 0x802A,
+	0xC5D6, 0x80D6, 0xC5D7, 0x629B, 0xC5D8, 0x5486, 0xC5D9, 0x5228,
+	0xC5DA, 0x70AE, 0xC5DB, 0x888D, 0xC5DC, 0x8DD1, 0xC5DD, 0x6CE1,
+	0xC5DE, 0x5478, 0xC5DF, 0x80DA, 0xC5E0, 0x57F9, 0xC5E1, 0x88F4,
+	0xC5E2, 0x8D54, 0xC5E3, 0x966A, 0xC5E4, 0x914D, 0xC5E5, 0x4F69,
+	0xC5E6, 0x6C9B, 0xC5E7, 0x55B7, 0xC5E8, 0x76C6, 0xC5E9, 0x7830,
+	0xC5EA, 0x62A8, 0xC5EB, 0x70F9, 0xC5EC, 0x6F8E, 0xC5ED, 0x5F6D,
+	0xC5EE, 0x84EC, 0xC5EF, 0x68DA, 0xC5F0, 0x787C, 0xC5F1, 0x7BF7,
+	0xC5F2, 0x81A8, 0xC5F3, 0x670B, 0xC5F4, 0x9E4F, 0xC5F5, 0x6367,
+	0xC5F6, 0x78B0, 0xC5F7, 0x576F, 0xC5F8, 0x7812, 0xC5F9, 0x9739,
+	0xC5FA, 0x6279, 0xC5FB, 0x62AB, 0xC5FC, 0x5288, 0xC5FD, 0x7435,
+	0xC5FE, 0x6BD7, 0xC640, 0x826A, 0xC641, 0x826B, 0xC642, 0x826C,
+	0xC643, 0x826D, 0xC644, 0x8271, 0xC645, 0x8275, 0xC646, 0x8276,
+	0xC647, 0x8277, 0xC648, 0x8278, 0xC649, 0x827B, 0xC64A, 0x827C,
+	0xC64B, 0x8280, 0xC64C, 0x8281, 0xC64D, 0x8283, 0xC64E, 0x8285,
+	0xC64F, 0x8286, 0xC650, 0x8287, 0xC651, 0x8289, 0xC652, 0x828C,
+	0xC653, 0x8290, 0xC654, 0x8293, 0xC655, 0x8294, 0xC656, 0x8295,
+	0xC657, 0x8296, 0xC658, 0x829A, 0xC659, 0x829B, 0xC65A, 0x829E,
+	0xC65B, 0x82A0, 0xC65C, 0x82A2, 0xC65D, 0x82A3, 0xC65E, 0x82A7,
+	0xC65F, 0x82B2, 0xC660, 0x82B5, 0xC661, 0x82B6, 0xC662, 0x82BA,
+	0xC663, 0x82BB, 0xC664, 0x82BC, 0xC665, 0x82BF, 0xC666, 0x82C0,
+	0xC667, 0x82C2, 0xC668, 0x82C3, 0xC669, 0x82C5, 0xC66A, 0x82C6,
+	0xC66B, 0x82C9, 0xC66C, 0x82D0, 0xC66D, 0x82D6, 0xC66E, 0x82D9,
+	0xC66F, 0x82DA, 0xC670, 0x82DD, 0xC671, 0x82E2, 0xC672, 0x82E7,
+	0xC673, 0x82E8, 0xC674, 0x82E9, 0xC675, 0x82EA, 0xC676, 0x82EC,
+	0xC677, 0x82ED, 0xC678, 0x82EE, 0xC679, 0x82F0, 0xC67A, 0x82F2,
+	0xC67B, 0x82F3, 0xC67C, 0x82F5, 0xC67D, 0x82F6, 0xC67E, 0x82F8,
+	0xC680, 0x82FA, 0xC681, 0x82FC, 0xC682, 0x82FD, 0xC683, 0x82FE,
+	0xC684, 0x82FF, 0xC685, 0x8300, 0xC686, 0x830A, 0xC687, 0x830B,
+	0xC688, 0x830D, 0xC689, 0x8310, 0xC68A, 0x8312, 0xC68B, 0x8313,
+	0xC68C, 0x8316, 0xC68D, 0x8318, 0xC68E, 0x8319, 0xC68F, 0x831D,
+	0xC690, 0x831E, 0xC691, 0x831F, 0xC692, 0x8320, 0xC693, 0x8321,
+	0xC694, 0x8322, 0xC695, 0x8323, 0xC696, 0x8324, 0xC697, 0x8325,
+	0xC698, 0x8326, 0xC699, 0x8329, 0xC69A, 0x832A, 0xC69B, 0x832E,
+	0xC69C, 0x8330, 0xC69D, 0x8332, 0xC69E, 0x8337, 0xC69F, 0x833B,
+	0xC6A0, 0x833D, 0xC6A1, 0x5564, 0xC6A2, 0x813E, 0xC6A3, 0x75B2,
+	0xC6A4, 0x76AE, 0xC6A5, 0x5339, 0xC6A6, 0x75DE, 0xC6A7, 0x50FB,
+	0xC6A8, 0x5C41, 0xC6A9, 0x8B6C, 0xC6AA, 0x7BC7, 0xC6AB, 0x504F,
+	0xC6AC, 0x7247, 0xC6AD, 0x9A97, 0xC6AE, 0x98D8, 0xC6AF, 0x6F02,
+	0xC6B0, 0x74E2, 0xC6B1, 0x7968, 0xC6B2, 0x6487, 0xC6B3, 0x77A5,
+	0xC6B4, 0x62FC, 0xC6B5, 0x9891, 0xC6B6, 0x8D2B, 0xC6B7, 0x54C1,
+	0xC6B8, 0x8058, 0xC6B9, 0x4E52, 0xC6BA, 0x576A, 0xC6BB, 0x82F9,
+	0xC6BC, 0x840D, 0xC6BD, 0x5E73, 0xC6BE, 0x51ED, 0xC6BF, 0x74F6,
+	0xC6C0, 0x8BC4, 0xC6C1, 0x5C4F, 0xC6C2, 0x5761, 0xC6C3, 0x6CFC,
+	0xC6C4, 0x9887, 0xC6C5, 0x5A46, 0xC6C6, 0x7834, 0xC6C7, 0x9B44,
+	0xC6C8, 0x8FEB, 0xC6C9, 0x7C95, 0xC6CA, 0x5256, 0xC6CB, 0x6251,
+	0xC6CC, 0x94FA, 0xC6CD, 0x4EC6, 0xC6CE, 0x8386, 0xC6CF, 0x8461,
+	0xC6D0, 0x83E9, 0xC6D1, 0x84B2, 0xC6D2, 0x57D4, 0xC6D3, 0x6734,
+	0xC6D4, 0x5703, 0xC6D5, 0x666E, 0xC6D6, 0x6D66, 0xC6D7, 0x8C31,
+	0xC6D8, 0x66DD, 0xC6D9, 0x7011, 0xC6DA, 0x671F, 0xC6DB, 0x6B3A,
+	0xC6DC, 0x6816, 0xC6DD, 0x621A, 0xC6DE, 0x59BB, 0xC6DF, 0x4E03,
+	0xC6E0, 0x51C4, 0xC6E1, 0x6F06, 0xC6E2, 0x67D2, 0xC6E3, 0x6C8F,
+	0xC6E4, 0x5176, 0xC6E5, 0x68CB, 0xC6E6, 0x5947, 0xC6E7, 0x6B67,
+	0xC6E8, 0x7566, 0xC6E9, 0x5D0E, 0xC6EA, 0x8110, 0xC6EB, 0x9F50,
+	0xC6EC, 0x65D7, 0xC6ED, 0x7948, 0xC6EE, 0x7941, 0xC6EF, 0x9A91,
+	0xC6F0, 0x8D77, 0xC6F1, 0x5C82, 0xC6F2, 0x4E5E, 0xC6F3, 0x4F01,
+	0xC6F4, 0x542F, 0xC6F5, 0x5951, 0xC6F6, 0x780C, 0xC6F7, 0x5668,
+	0xC6F8, 0x6C14, 0xC6F9, 0x8FC4, 0xC6FA, 0x5F03, 0xC6FB, 0x6C7D,
+	0xC6FC, 0x6CE3, 0xC6FD, 0x8BAB, 0xC6FE, 0x6390, 0xC740, 0x833E,
+	0xC741, 0x833F, 0xC742, 0x8341, 0xC743, 0x8342, 0xC744, 0x8344,
+	0xC745, 0x8345, 0xC746, 0x8348, 0xC747, 0x834A, 0xC748, 0x834B,
+	0xC749, 0x834C, 0xC74A, 0x834D, 0xC74B, 0x834E, 0xC74C, 0x8353,
+	0xC74D, 0x8355, 0xC74E, 0x8356, 0xC74F, 0x8357, 0xC750, 0x8358,
+	0xC751, 0x8359, 0xC752, 0x835D, 0xC753, 0x8362, 0xC754, 0x8370,
+	0xC755, 0x8371, 0xC756, 0x8372, 0xC757, 0x8373, 0xC758, 0x8374,
+	0xC759, 0x8375, 0xC75A, 0x8376, 0xC75B, 0x8379, 0xC75C, 0x837A,
+	0xC75D, 0x837E, 0xC75E, 0x837F, 0xC75F, 0x8380, 0xC760, 0x8381,
+	0xC761, 0x8382, 0xC762, 0x8383, 0xC763, 0x8384, 0xC764, 0x8387,
+	0xC765, 0x8388, 0xC766, 0x838A, 0xC767, 0x838B, 0xC768, 0x838C,
+	0xC769, 0x838D, 0xC76A, 0x838F, 0xC76B, 0x8390, 0xC76C, 0x8391,
+	0xC76D, 0x8394, 0xC76E, 0x8395, 0xC76F, 0x8396, 0xC770, 0x8397,
+	0xC771, 0x8399, 0xC772, 0x839A, 0xC773, 0x839D, 0xC774, 0x839F,
+	0xC775, 0x83A1, 0xC776, 0x83A2, 0xC777, 0x83A3, 0xC778, 0x83A4,
+	0xC779, 0x83A5, 0xC77A, 0x83A6, 0xC77B, 0x83A7, 0xC77C, 0x83AC,
+	0xC77D, 0x83AD, 0xC77E, 0x83AE, 0xC780, 0x83AF, 0xC781, 0x83B5,
+	0xC782, 0x83BB, 0xC783, 0x83BE, 0xC784, 0x83BF, 0xC785, 0x83C2,
+	0xC786, 0x83C3, 0xC787, 0x83C4, 0xC788, 0x83C6, 0xC789, 0x83C8,
+	0xC78A, 0x83C9, 0xC78B, 0x83CB, 0xC78C, 0x83CD, 0xC78D, 0x83CE,
+	0xC78E, 0x83D0, 0xC78F, 0x83D1, 0xC790, 0x83D2, 0xC791, 0x83D3,
+	0xC792, 0x83D5, 0xC793, 0x83D7, 0xC794, 0x83D9, 0xC795, 0x83DA,
+	0xC796, 0x83DB, 0xC797, 0x83DE, 0xC798, 0x83E2, 0xC799, 0x83E3,
+	0xC79A, 0x83E4, 0xC79B, 0x83E6, 0xC79C, 0x83E7, 0xC79D, 0x83E8,
+	0xC79E, 0x83EB, 0xC79F, 0x83EC, 0xC7A0, 0x83ED, 0xC7A1, 0x6070,
+	0xC7A2, 0x6D3D, 0xC7A3, 0x7275, 0xC7A4, 0x6266, 0xC7A5, 0x948E,
+	0xC7A6, 0x94C5, 0xC7A7, 0x5343, 0xC7A8, 0x8FC1, 0xC7A9, 0x7B7E,
+	0xC7AA, 0x4EDF, 0xC7AB, 0x8C26, 0xC7AC, 0x4E7E, 0xC7AD, 0x9ED4,
+	0xC7AE, 0x94B1, 0xC7AF, 0x94B3, 0xC7B0, 0x524D, 0xC7B1, 0x6F5C,
+	0xC7B2, 0x9063, 0xC7B3, 0x6D45, 0xC7B4, 0x8C34, 0xC7B5, 0x5811,
+	0xC7B6, 0x5D4C, 0xC7B7, 0x6B20, 0xC7B8, 0x6B49, 0xC7B9, 0x67AA,
+	0xC7BA, 0x545B, 0xC7BB, 0x8154, 0xC7BC, 0x7F8C, 0xC7BD, 0x5899,
+	0xC7BE, 0x8537, 0xC7BF, 0x5F3A, 0xC7C0, 0x62A2, 0xC7C1, 0x6A47,
+	0xC7C2, 0x9539, 0xC7C3, 0x6572, 0xC7C4, 0x6084, 0xC7C5, 0x6865,
+	0xC7C6, 0x77A7, 0xC7C7, 0x4E54, 0xC7C8, 0x4FA8, 0xC7C9, 0x5DE7,
+	0xC7CA, 0x9798, 0xC7CB, 0x64AC, 0xC7CC, 0x7FD8, 0xC7CD, 0x5CED,
+	0xC7CE, 0x4FCF, 0xC7CF, 0x7A8D, 0xC7D0, 0x5207, 0xC7D1, 0x8304,
+	0xC7D2, 0x4E14, 0xC7D3, 0x602F, 0xC7D4, 0x7A83, 0xC7D5, 0x94A6,
+	0xC7D6, 0x4FB5, 0xC7D7, 0x4EB2, 0xC7D8, 0x79E6, 0xC7D9, 0x7434,
+	0xC7DA, 0x52E4, 0xC7DB, 0x82B9, 0xC7DC, 0x64D2, 0xC7DD, 0x79BD,
+	0xC7DE, 0x5BDD, 0xC7DF, 0x6C81, 0xC7E0, 0x9752, 0xC7E1, 0x8F7B,
+	0xC7E2, 0x6C22, 0xC7E3, 0x503E, 0xC7E4, 0x537F, 0xC7E5, 0x6E05,
+	0xC7E6, 0x64CE, 0xC7E7, 0x6674, 0xC7E8, 0x6C30, 0xC7E9, 0x60C5,
+	0xC7EA, 0x9877, 0xC7EB, 0x8BF7, 0xC7EC, 0x5E86, 0xC7ED, 0x743C,
+	0xC7EE, 0x7A77, 0xC7EF, 0x79CB, 0xC7F0, 0x4E18, 0xC7F1, 0x90B1,
+	0xC7F2, 0x7403, 0xC7F3, 0x6C42, 0xC7F4, 0x56DA, 0xC7F5, 0x914B,
+	0xC7F6, 0x6CC5, 0xC7F7, 0x8D8B, 0xC7F8, 0x533A, 0xC7F9, 0x86C6,
+	0xC7FA, 0x66F2, 0xC7FB, 0x8EAF, 0xC7FC, 0x5C48, 0xC7FD, 0x9A71,
+	0xC7FE, 0x6E20, 0xC840, 0x83EE, 0xC841, 0x83EF, 0xC842, 0x83F3,
+	0xC843, 0x83F4, 0xC844, 0x83F5, 0xC845, 0x83F6, 0xC846, 0x83F7,
+	0xC847, 0x83FA, 0xC848, 0x83FB, 0xC849, 0x83FC, 0xC84A, 0x83FE,
+	0xC84B, 0x83FF, 0xC84C, 0x8400, 0xC84D, 0x8402, 0xC84E, 0x8405,
+	0xC84F, 0x8407, 0xC850, 0x8408, 0xC851, 0x8409, 0xC852, 0x840A,
+	0xC853, 0x8410, 0xC854, 0x8412, 0xC855, 0x8413, 0xC856, 0x8414,
+	0xC857, 0x8415, 0xC858, 0x8416, 0xC859, 0x8417, 0xC85A, 0x8419,
+	0xC85B, 0x841A, 0xC85C, 0x841B, 0xC85D, 0x841E, 0xC85E, 0x841F,
+	0xC85F, 0x8420, 0xC860, 0x8421, 0xC861, 0x8422, 0xC862, 0x8423,
+	0xC863, 0x8429, 0xC864, 0x842A, 0xC865, 0x842B, 0xC866, 0x842C,
+	0xC867, 0x842D, 0xC868, 0x842E, 0xC869, 0x842F, 0xC86A, 0x8430,
+	0xC86B, 0x8432, 0xC86C, 0x8433, 0xC86D, 0x8434, 0xC86E, 0x8435,
+	0xC86F, 0x8436, 0xC870, 0x8437, 0xC871, 0x8439, 0xC872, 0x843A,
+	0xC873, 0x843B, 0xC874, 0x843E, 0xC875, 0x843F, 0xC876, 0x8440,
+	0xC877, 0x8441, 0xC878, 0x8442, 0xC879, 0x8443, 0xC87A, 0x8444,
+	0xC87B, 0x8445, 0xC87C, 0x8447, 0xC87D, 0x8448, 0xC87E, 0x8449,
+	0xC880, 0x844A, 0xC881, 0x844B, 0xC882, 0x844C, 0xC883, 0x844D,
+	0xC884, 0x844E, 0xC885, 0x844F, 0xC886, 0x8450, 0xC887, 0x8452,
+	0xC888, 0x8453, 0xC889, 0x8454, 0xC88A, 0x8455, 0xC88B, 0x8456,
+	0xC88C, 0x8458, 0xC88D, 0x845D, 0xC88E, 0x845E, 0xC88F, 0x845F,
+	0xC890, 0x8460, 0xC891, 0x8462, 0xC892, 0x8464, 0xC893, 0x8465,
+	0xC894, 0x8466, 0xC895, 0x8467, 0xC896, 0x8468, 0xC897, 0x846A,
+	0xC898, 0x846E, 0xC899, 0x846F, 0xC89A, 0x8470, 0xC89B, 0x8472,
+	0xC89C, 0x8474, 0xC89D, 0x8477, 0xC89E, 0x8479, 0xC89F, 0x847B,
+	0xC8A0, 0x847C, 0xC8A1, 0x53D6, 0xC8A2, 0x5A36, 0xC8A3, 0x9F8B,
+	0xC8A4, 0x8DA3, 0xC8A5, 0x53BB, 0xC8A6, 0x5708, 0xC8A7, 0x98A7,
+	0xC8A8, 0x6743, 0xC8A9, 0x919B, 0xC8AA, 0x6CC9, 0xC8AB, 0x5168,
+	0xC8AC, 0x75CA, 0xC8AD, 0x62F3, 0xC8AE, 0x72AC, 0xC8AF, 0x5238,
+	0xC8B0, 0x529D, 0xC8B1, 0x7F3A, 0xC8B2, 0x7094, 0xC8B3, 0x7638,
+	0xC8B4, 0x5374, 0xC8B5, 0x9E4A, 0xC8B6, 0x69B7, 0xC8B7, 0x786E,
+	0xC8B8, 0x96C0, 0xC8B9, 0x88D9, 0xC8BA, 0x7FA4, 0xC8BB, 0x7136,
+	0xC8BC, 0x71C3, 0xC8BD, 0x5189, 0xC8BE, 0x67D3, 0xC8BF, 0x74E4,
+	0xC8C0, 0x58E4, 0xC8C1, 0x6518, 0xC8C2, 0x56B7, 0xC8C3, 0x8BA9,
+	0xC8C4, 0x9976, 0xC8C5, 0x6270, 0xC8C6, 0x7ED5, 0xC8C7, 0x60F9,
+	0xC8C8, 0x70ED, 0xC8C9, 0x58EC, 0xC8CA, 0x4EC1, 0xC8CB, 0x4EBA,
+	0xC8CC, 0x5FCD, 0xC8CD, 0x97E7, 0xC8CE, 0x4EFB, 0xC8CF, 0x8BA4,
+	0xC8D0, 0x5203, 0xC8D1, 0x598A, 0xC8D2, 0x7EAB, 0xC8D3, 0x6254,
+	0xC8D4, 0x4ECD, 0xC8D5, 0x65E5, 0xC8D6, 0x620E, 0xC8D7, 0x8338,
+	0xC8D8, 0x84C9, 0xC8D9, 0x8363, 0xC8DA, 0x878D, 0xC8DB, 0x7194,
+	0xC8DC, 0x6EB6, 0xC8DD, 0x5BB9, 0xC8DE, 0x7ED2, 0xC8DF, 0x5197,
+	0xC8E0, 0x63C9, 0xC8E1, 0x67D4, 0xC8E2, 0x8089, 0xC8E3, 0x8339,
+	0xC8E4, 0x8815, 0xC8E5, 0x5112, 0xC8E6, 0x5B7A, 0xC8E7, 0x5982,
+	0xC8E8, 0x8FB1, 0xC8E9, 0x4E73, 0xC8EA, 0x6C5D, 0xC8EB, 0x5165,
+	0xC8EC, 0x8925, 0xC8ED, 0x8F6F, 0xC8EE, 0x962E, 0xC8EF, 0x854A,
+	0xC8F0, 0x745E, 0xC8F1, 0x9510, 0xC8F2, 0x95F0, 0xC8F3, 0x6DA6,
+	0xC8F4, 0x82E5, 0xC8F5, 0x5F31, 0xC8F6, 0x6492, 0xC8F7, 0x6D12,
+	0xC8F8, 0x8428, 0xC8F9, 0x816E, 0xC8FA, 0x9CC3, 0xC8FB, 0x585E,
+	0xC8FC, 0x8D5B, 0xC8FD, 0x4E09, 0xC8FE, 0x53C1, 0xC940, 0x847D,
+	0xC941, 0x847E, 0xC942, 0x847F, 0xC943, 0x8480, 0xC944, 0x8481,
+	0xC945, 0x8483, 0xC946, 0x8484, 0xC947, 0x8485, 0xC948, 0x8486,
+	0xC949, 0x848A, 0xC94A, 0x848D, 0xC94B, 0x848F, 0xC94C, 0x8490,
+	0xC94D, 0x8491, 0xC94E, 0x8492, 0xC94F, 0x8493, 0xC950, 0x8494,
+	0xC951, 0x8495, 0xC952, 0x8496, 0xC953, 0x8498, 0xC954, 0x849A,
+	0xC955, 0x849B, 0xC956, 0x849D, 0xC957, 0x849E, 0xC958, 0x849F,
+	0xC959, 0x84A0, 0xC95A, 0x84A2, 0xC95B, 0x84A3, 0xC95C, 0x84A4,
+	0xC95D, 0x84A5, 0xC95E, 0x84A6, 0xC95F, 0x84A7, 0xC960, 0x84A8,
+	0xC961, 0x84A9, 0xC962, 0x84AA, 0xC963, 0x84AB, 0xC964, 0x84AC,
+	0xC965, 0x84AD, 0xC966, 0x84AE, 0xC967, 0x84B0, 0xC968, 0x84B1,
+	0xC969, 0x84B3, 0xC96A, 0x84B5, 0xC96B, 0x84B6, 0xC96C, 0x84B7,
+	0xC96D, 0x84BB, 0xC96E, 0x84BC, 0xC96F, 0x84BE, 0xC970, 0x84C0,
+	0xC971, 0x84C2, 0xC972, 0x84C3, 0xC973, 0x84C5, 0xC974, 0x84C6,
+	0xC975, 0x84C7, 0xC976, 0x84C8, 0xC977, 0x84CB, 0xC978, 0x84CC,
+	0xC979, 0x84CE, 0xC97A, 0x84CF, 0xC97B, 0x84D2, 0xC97C, 0x84D4,
+	0xC97D, 0x84D5, 0xC97E, 0x84D7, 0xC980, 0x84D8, 0xC981, 0x84D9,
+	0xC982, 0x84DA, 0xC983, 0x84DB, 0xC984, 0x84DC, 0xC985, 0x84DE,
+	0xC986, 0x84E1, 0xC987, 0x84E2, 0xC988, 0x84E4, 0xC989, 0x84E7,
+	0xC98A, 0x84E8, 0xC98B, 0x84E9, 0xC98C, 0x84EA, 0xC98D, 0x84EB,
+	0xC98E, 0x84ED, 0xC98F, 0x84EE, 0xC990, 0x84EF, 0xC991, 0x84F1,
+	0xC992, 0x84F2, 0xC993, 0x84F3, 0xC994, 0x84F4, 0xC995, 0x84F5,
+	0xC996, 0x84F6, 0xC997, 0x84F7, 0xC998, 0x84F8, 0xC999, 0x84F9,
+	0xC99A, 0x84FA, 0xC99B, 0x84FB, 0xC99C, 0x84FD, 0xC99D, 0x84FE,
+	0xC99E, 0x8500, 0xC99F, 0x8501, 0xC9A0, 0x8502, 0xC9A1, 0x4F1E,
+	0xC9A2, 0x6563, 0xC9A3, 0x6851, 0xC9A4, 0x55D3, 0xC9A5, 0x4E27,
+	0xC9A6, 0x6414, 0xC9A7, 0x9A9A, 0xC9A8, 0x626B, 0xC9A9, 0x5AC2,
+	0xC9AA, 0x745F, 0xC9AB, 0x8272, 0xC9AC, 0x6DA9, 0xC9AD, 0x68EE,
+	0xC9AE, 0x50E7, 0xC9AF, 0x838E, 0xC9B0, 0x7802, 0xC9B1, 0x6740,
+	0xC9B2, 0x5239, 0xC9B3, 0x6C99, 0xC9B4, 0x7EB1, 0xC9B5, 0x50BB,
+	0xC9B6, 0x5565, 0xC9B7, 0x715E, 0xC9B8, 0x7B5B, 0xC9B9, 0x6652,
+	0xC9BA, 0x73CA, 0xC9BB, 0x82EB, 0xC9BC, 0x6749, 0xC9BD, 0x5C71,
+	0xC9BE, 0x5220, 0xC9BF, 0x717D, 0xC9C0, 0x886B, 0xC9C1, 0x95EA,
+	0xC9C2, 0x9655, 0xC9C3, 0x64C5, 0xC9C4, 0x8D61, 0xC9C5, 0x81B3,
+	0xC9C6, 0x5584, 0xC9C7, 0x6C55, 0xC9C8, 0x6247, 0xC9C9, 0x7F2E,
+	0xC9CA, 0x5892, 0xC9CB, 0x4F24, 0xC9CC, 0x5546, 0xC9CD, 0x8D4F,
+	0xC9CE, 0x664C, 0xC9CF, 0x4E0A, 0xC9D0, 0x5C1A, 0xC9D1, 0x88F3,
+	0xC9D2, 0x68A2, 0xC9D3, 0x634E, 0xC9D4, 0x7A0D, 0xC9D5, 0x70E7,
+	0xC9D6, 0x828D, 0xC9D7, 0x52FA, 0xC9D8, 0x97F6, 0xC9D9, 0x5C11,
+	0xC9DA, 0x54E8, 0xC9DB, 0x90B5, 0xC9DC, 0x7ECD, 0xC9DD, 0x5962,
+	0xC9DE, 0x8D4A, 0xC9DF, 0x86C7, 0xC9E0, 0x820C, 0xC9E1, 0x820D,
+	0xC9E2, 0x8D66, 0xC9E3, 0x6444, 0xC9E4, 0x5C04, 0xC9E5, 0x6151,
+	0xC9E6, 0x6D89, 0xC9E7, 0x793E, 0xC9E8, 0x8BBE, 0xC9E9, 0x7837,
+	0xC9EA, 0x7533, 0xC9EB, 0x547B, 0xC9EC, 0x4F38, 0xC9ED, 0x8EAB,
+	0xC9EE, 0x6DF1, 0xC9EF, 0x5A20, 0xC9F0, 0x7EC5, 0xC9F1, 0x795E,
+	0xC9F2, 0x6C88, 0xC9F3, 0x5BA1, 0xC9F4, 0x5A76, 0xC9F5, 0x751A,
+	0xC9F6, 0x80BE, 0xC9F7, 0x614E, 0xC9F8, 0x6E17, 0xC9F9, 0x58F0,
+	0xC9FA, 0x751F, 0xC9FB, 0x7525, 0xC9FC, 0x7272, 0xC9FD, 0x5347,
+	0xC9FE, 0x7EF3, 0xCA40, 0x8503, 0xCA41, 0x8504, 0xCA42, 0x8505,
+	0xCA43, 0x8506, 0xCA44, 0x8507, 0xCA45, 0x8508, 0xCA46, 0x8509,
+	0xCA47, 0x850A, 0xCA48, 0x850B, 0xCA49, 0x850D, 0xCA4A, 0x850E,
+	0xCA4B, 0x850F, 0xCA4C, 0x8510, 0xCA4D, 0x8512, 0xCA4E, 0x8514,
+	0xCA4F, 0x8515, 0xCA50, 0x8516, 0xCA51, 0x8518, 0xCA52, 0x8519,
+	0xCA53, 0x851B, 0xCA54, 0x851C, 0xCA55, 0x851D, 0xCA56, 0x851E,
+	0xCA57, 0x8520, 0xCA58, 0x8522, 0xCA59, 0x8523, 0xCA5A, 0x8524,
+	0xCA5B, 0x8525, 0xCA5C, 0x8526, 0xCA5D, 0x8527, 0xCA5E, 0x8528,
+	0xCA5F, 0x8529, 0xCA60, 0x852A, 0xCA61, 0x852D, 0xCA62, 0x852E,
+	0xCA63, 0x852F, 0xCA64, 0x8530, 0xCA65, 0x8531, 0xCA66, 0x8532,
+	0xCA67, 0x8533, 0xCA68, 0x8534, 0xCA69, 0x8535, 0xCA6A, 0x8536,
+	0xCA6B, 0x853E, 0xCA6C, 0x853F, 0xCA6D, 0x8540, 0xCA6E, 0x8541,
+	0xCA6F, 0x8542, 0xCA70, 0x8544, 0xCA71, 0x8545, 0xCA72, 0x8546,
+	0xCA73, 0x8547, 0xCA74, 0x854B, 0xCA75, 0x854C, 0xCA76, 0x854D,
+	0xCA77, 0x854E, 0xCA78, 0x854F, 0xCA79, 0x8550, 0xCA7A, 0x8551,
+	0xCA7B, 0x8552, 0xCA7C, 0x8553, 0xCA7D, 0x8554, 0xCA7E, 0x8555,
+	0xCA80, 0x8557, 0xCA81, 0x8558, 0xCA82, 0x855A, 0xCA83, 0x855B,
+	0xCA84, 0x855C, 0xCA85, 0x855D, 0xCA86, 0x855F, 0xCA87, 0x8560,
+	0xCA88, 0x8561, 0xCA89, 0x8562, 0xCA8A, 0x8563, 0xCA8B, 0x8565,
+	0xCA8C, 0x8566, 0xCA8D, 0x8567, 0xCA8E, 0x8569, 0xCA8F, 0x856A,
+	0xCA90, 0x856B, 0xCA91, 0x856C, 0xCA92, 0x856D, 0xCA93, 0x856E,
+	0xCA94, 0x856F, 0xCA95, 0x8570, 0xCA96, 0x8571, 0xCA97, 0x8573,
+	0xCA98, 0x8575, 0xCA99, 0x8576, 0xCA9A, 0x8577, 0xCA9B, 0x8578,
+	0xCA9C, 0x857C, 0xCA9D, 0x857D, 0xCA9E, 0x857F, 0xCA9F, 0x8580,
+	0xCAA0, 0x8581, 0xCAA1, 0x7701, 0xCAA2, 0x76DB, 0xCAA3, 0x5269,
+	0xCAA4, 0x80DC, 0xCAA5, 0x5723, 0xCAA6, 0x5E08, 0xCAA7, 0x5931,
+	0xCAA8, 0x72EE, 0xCAA9, 0x65BD, 0xCAAA, 0x6E7F, 0xCAAB, 0x8BD7,
+	0xCAAC, 0x5C38, 0xCAAD, 0x8671, 0xCAAE, 0x5341, 0xCAAF, 0x77F3,
+	0xCAB0, 0x62FE, 0xCAB1, 0x65F6, 0xCAB2, 0x4EC0, 0xCAB3, 0x98DF,
+	0xCAB4, 0x8680, 0xCAB5, 0x5B9E, 0xCAB6, 0x8BC6, 0xCAB7, 0x53F2,
+	0xCAB8, 0x77E2, 0xCAB9, 0x4F7F, 0xCABA, 0x5C4E, 0xCABB, 0x9A76,
+	0xCABC, 0x59CB, 0xCABD, 0x5F0F, 0xCABE, 0x793A, 0xCABF, 0x58EB,
+	0xCAC0, 0x4E16, 0xCAC1, 0x67FF, 0xCAC2, 0x4E8B, 0xCAC3, 0x62ED,
+	0xCAC4, 0x8A93, 0xCAC5, 0x901D, 0xCAC6, 0x52BF, 0xCAC7, 0x662F,
+	0xCAC8, 0x55DC, 0xCAC9, 0x566C, 0xCACA, 0x9002, 0xCACB, 0x4ED5,
+	0xCACC, 0x4F8D, 0xCACD, 0x91CA, 0xCACE, 0x9970, 0xCACF, 0x6C0F,
+	0xCAD0, 0x5E02, 0xCAD1, 0x6043, 0xCAD2, 0x5BA4, 0xCAD3, 0x89C6,
+	0xCAD4, 0x8BD5, 0xCAD5, 0x6536, 0xCAD6, 0x624B, 0xCAD7, 0x9996,
+	0xCAD8, 0x5B88, 0xCAD9, 0x5BFF, 0xCADA, 0x6388, 0xCADB, 0x552E,
+	0xCADC, 0x53D7, 0xCADD, 0x7626, 0xCADE, 0x517D, 0xCADF, 0x852C,
+	0xCAE0, 0x67A2, 0xCAE1, 0x68B3, 0xCAE2, 0x6B8A, 0xCAE3, 0x6292,
+	0xCAE4, 0x8F93, 0xCAE5, 0x53D4, 0xCAE6, 0x8212, 0xCAE7, 0x6DD1,
+	0xCAE8, 0x758F, 0xCAE9, 0x4E66, 0xCAEA, 0x8D4E, 0xCAEB, 0x5B70,
+	0xCAEC, 0x719F, 0xCAED, 0x85AF, 0xCAEE, 0x6691, 0xCAEF, 0x66D9,
+	0xCAF0, 0x7F72, 0xCAF1, 0x8700, 0xCAF2, 0x9ECD, 0xCAF3, 0x9F20,
+	0xCAF4, 0x5C5E, 0xCAF5, 0x672F, 0xCAF6, 0x8FF0, 0xCAF7, 0x6811,
+	0xCAF8, 0x675F, 0xCAF9, 0x620D, 0xCAFA, 0x7AD6, 0xCAFB, 0x5885,
+	0xCAFC, 0x5EB6, 0xCAFD, 0x6570, 0xCAFE, 0x6F31, 0xCB40, 0x8582,
+	0xCB41, 0x8583, 0xCB42, 0x8586, 0xCB43, 0x8588, 0xCB44, 0x8589,
+	0xCB45, 0x858A, 0xCB46, 0x858B, 0xCB47, 0x858C, 0xCB48, 0x858D,
+	0xCB49, 0x858E, 0xCB4A, 0x8590, 0xCB4B, 0x8591, 0xCB4C, 0x8592,
+	0xCB4D, 0x8593, 0xCB4E, 0x8594, 0xCB4F, 0x8595, 0xCB50, 0x8596,
+	0xCB51, 0x8597, 0xCB52, 0x8598, 0xCB53, 0x8599, 0xCB54, 0x859A,
+	0xCB55, 0x859D, 0xCB56, 0x859E, 0xCB57, 0x859F, 0xCB58, 0x85A0,
+	0xCB59, 0x85A1, 0xCB5A, 0x85A2, 0xCB5B, 0x85A3, 0xCB5C, 0x85A5,
+	0xCB5D, 0x85A6, 0xCB5E, 0x85A7, 0xCB5F, 0x85A9, 0xCB60, 0x85AB,
+	0xCB61, 0x85AC, 0xCB62, 0x85AD, 0xCB63, 0x85B1, 0xCB64, 0x85B2,
+	0xCB65, 0x85B3, 0xCB66, 0x85B4, 0xCB67, 0x85B5, 0xCB68, 0x85B6,
+	0xCB69, 0x85B8, 0xCB6A, 0x85BA, 0xCB6B, 0x85BB, 0xCB6C, 0x85BC,
+	0xCB6D, 0x85BD, 0xCB6E, 0x85BE, 0xCB6F, 0x85BF, 0xCB70, 0x85C0,
+	0xCB71, 0x85C2, 0xCB72, 0x85C3, 0xCB73, 0x85C4, 0xCB74, 0x85C5,
+	0xCB75, 0x85C6, 0xCB76, 0x85C7, 0xCB77, 0x85C8, 0xCB78, 0x85CA,
+	0xCB79, 0x85CB, 0xCB7A, 0x85CC, 0xCB7B, 0x85CD, 0xCB7C, 0x85CE,
+	0xCB7D, 0x85D1, 0xCB7E, 0x85D2, 0xCB80, 0x85D4, 0xCB81, 0x85D6,
+	0xCB82, 0x85D7, 0xCB83, 0x85D8, 0xCB84, 0x85D9, 0xCB85, 0x85DA,
+	0xCB86, 0x85DB, 0xCB87, 0x85DD, 0xCB88, 0x85DE, 0xCB89, 0x85DF,
+	0xCB8A, 0x85E0, 0xCB8B, 0x85E1, 0xCB8C, 0x85E2, 0xCB8D, 0x85E3,
+	0xCB8E, 0x85E5, 0xCB8F, 0x85E6, 0xCB90, 0x85E7, 0xCB91, 0x85E8,
+	0xCB92, 0x85EA, 0xCB93, 0x85EB, 0xCB94, 0x85EC, 0xCB95, 0x85ED,
+	0xCB96, 0x85EE, 0xCB97, 0x85EF, 0xCB98, 0x85F0, 0xCB99, 0x85F1,
+	0xCB9A, 0x85F2, 0xCB9B, 0x85F3, 0xCB9C, 0x85F4, 0xCB9D, 0x85F5,
+	0xCB9E, 0x85F6, 0xCB9F, 0x85F7, 0xCBA0, 0x85F8, 0xCBA1, 0x6055,
+	0xCBA2, 0x5237, 0xCBA3, 0x800D, 0xCBA4, 0x6454, 0xCBA5, 0x8870,
+	0xCBA6, 0x7529, 0xCBA7, 0x5E05, 0xCBA8, 0x6813, 0xCBA9, 0x62F4,
+	0xCBAA, 0x971C, 0xCBAB, 0x53CC, 0xCBAC, 0x723D, 0xCBAD, 0x8C01,
+	0xCBAE, 0x6C34, 0xCBAF, 0x7761, 0xCBB0, 0x7A0E, 0xCBB1, 0x542E,
+	0xCBB2, 0x77AC, 0xCBB3, 0x987A, 0xCBB4, 0x821C, 0xCBB5, 0x8BF4,
+	0xCBB6, 0x7855, 0xCBB7, 0x6714, 0xCBB8, 0x70C1, 0xCBB9, 0x65AF,
+	0xCBBA, 0x6495, 0xCBBB, 0x5636, 0xCBBC, 0x601D, 0xCBBD, 0x79C1,
+	0xCBBE, 0x53F8, 0xCBBF, 0x4E1D, 0xCBC0, 0x6B7B, 0xCBC1, 0x8086,
+	0xCBC2, 0x5BFA, 0xCBC3, 0x55E3, 0xCBC4, 0x56DB, 0xCBC5, 0x4F3A,
+	0xCBC6, 0x4F3C, 0xCBC7, 0x9972, 0xCBC8, 0x5DF3, 0xCBC9, 0x677E,
+	0xCBCA, 0x8038, 0xCBCB, 0x6002, 0xCBCC, 0x9882, 0xCBCD, 0x9001,
+	0xCBCE, 0x5B8B, 0xCBCF, 0x8BBC, 0xCBD0, 0x8BF5, 0xCBD1, 0x641C,
+	0xCBD2, 0x8258, 0xCBD3, 0x64DE, 0xCBD4, 0x55FD, 0xCBD5, 0x82CF,
+	0xCBD6, 0x9165, 0xCBD7, 0x4FD7, 0xCBD8, 0x7D20, 0xCBD9, 0x901F,
+	0xCBDA, 0x7C9F, 0xCBDB, 0x50F3, 0xCBDC, 0x5851, 0xCBDD, 0x6EAF,
+	0xCBDE, 0x5BBF, 0xCBDF, 0x8BC9, 0xCBE0, 0x8083, 0xCBE1, 0x9178,
+	0xCBE2, 0x849C, 0xCBE3, 0x7B97, 0xCBE4, 0x867D, 0xCBE5, 0x968B,
+	0xCBE6, 0x968F, 0xCBE7, 0x7EE5, 0xCBE8, 0x9AD3, 0xCBE9, 0x788E,
+	0xCBEA, 0x5C81, 0xCBEB, 0x7A57, 0xCBEC, 0x9042, 0xCBED, 0x96A7,
+	0xCBEE, 0x795F, 0xCBEF, 0x5B59, 0xCBF0, 0x635F, 0xCBF1, 0x7B0B,
+	0xCBF2, 0x84D1, 0xCBF3, 0x68AD, 0xCBF4, 0x5506, 0xCBF5, 0x7F29,
+	0xCBF6, 0x7410, 0xCBF7, 0x7D22, 0xCBF8, 0x9501, 0xCBF9, 0x6240,
+	0xCBFA, 0x584C, 0xCBFB, 0x4ED6, 0xCBFC, 0x5B83, 0xCBFD, 0x5979,
+	0xCBFE, 0x5854, 0xCC40, 0x85F9, 0xCC41, 0x85FA, 0xCC42, 0x85FC,
+	0xCC43, 0x85FD, 0xCC44, 0x85FE, 0xCC45, 0x8600, 0xCC46, 0x8601,
+	0xCC47, 0x8602, 0xCC48, 0x8603, 0xCC49, 0x8604, 0xCC4A, 0x8606,
+	0xCC4B, 0x8607, 0xCC4C, 0x8608, 0xCC4D, 0x8609, 0xCC4E, 0x860A,
+	0xCC4F, 0x860B, 0xCC50, 0x860C, 0xCC51, 0x860D, 0xCC52, 0x860E,
+	0xCC53, 0x860F, 0xCC54, 0x8610, 0xCC55, 0x8612, 0xCC56, 0x8613,
+	0xCC57, 0x8614, 0xCC58, 0x8615, 0xCC59, 0x8617, 0xCC5A, 0x8618,
+	0xCC5B, 0x8619, 0xCC5C, 0x861A, 0xCC5D, 0x861B, 0xCC5E, 0x861C,
+	0xCC5F, 0x861D, 0xCC60, 0x861E, 0xCC61, 0x861F, 0xCC62, 0x8620,
+	0xCC63, 0x8621, 0xCC64, 0x8622, 0xCC65, 0x8623, 0xCC66, 0x8624,
+	0xCC67, 0x8625, 0xCC68, 0x8626, 0xCC69, 0x8628, 0xCC6A, 0x862A,
+	0xCC6B, 0x862B, 0xCC6C, 0x862C, 0xCC6D, 0x862D, 0xCC6E, 0x862E,
+	0xCC6F, 0x862F, 0xCC70, 0x8630, 0xCC71, 0x8631, 0xCC72, 0x8632,
+	0xCC73, 0x8633, 0xCC74, 0x8634, 0xCC75, 0x8635, 0xCC76, 0x8636,
+	0xCC77, 0x8637, 0xCC78, 0x8639, 0xCC79, 0x863A, 0xCC7A, 0x863B,
+	0xCC7B, 0x863D, 0xCC7C, 0x863E, 0xCC7D, 0x863F, 0xCC7E, 0x8640,
+	0xCC80, 0x8641, 0xCC81, 0x8642, 0xCC82, 0x8643, 0xCC83, 0x8644,
+	0xCC84, 0x8645, 0xCC85, 0x8646, 0xCC86, 0x8647, 0xCC87, 0x8648,
+	0xCC88, 0x8649, 0xCC89, 0x864A, 0xCC8A, 0x864B, 0xCC8B, 0x864C,
+	0xCC8C, 0x8652, 0xCC8D, 0x8653, 0xCC8E, 0x8655, 0xCC8F, 0x8656,
+	0xCC90, 0x8657, 0xCC91, 0x8658, 0xCC92, 0x8659, 0xCC93, 0x865B,
+	0xCC94, 0x865C, 0xCC95, 0x865D, 0xCC96, 0x865F, 0xCC97, 0x8660,
+	0xCC98, 0x8661, 0xCC99, 0x8663, 0xCC9A, 0x8664, 0xCC9B, 0x8665,
+	0xCC9C, 0x8666, 0xCC9D, 0x8667, 0xCC9E, 0x8668, 0xCC9F, 0x8669,
+	0xCCA0, 0x866A, 0xCCA1, 0x736D, 0xCCA2, 0x631E, 0xCCA3, 0x8E4B,
+	0xCCA4, 0x8E0F, 0xCCA5, 0x80CE, 0xCCA6, 0x82D4, 0xCCA7, 0x62AC,
+	0xCCA8, 0x53F0, 0xCCA9, 0x6CF0, 0xCCAA, 0x915E, 0xCCAB, 0x592A,
+	0xCCAC, 0x6001, 0xCCAD, 0x6C70, 0xCCAE, 0x574D, 0xCCAF, 0x644A,
+	0xCCB0, 0x8D2A, 0xCCB1, 0x762B, 0xCCB2, 0x6EE9, 0xCCB3, 0x575B,
+	0xCCB4, 0x6A80, 0xCCB5, 0x75F0, 0xCCB6, 0x6F6D, 0xCCB7, 0x8C2D,
+	0xCCB8, 0x8C08, 0xCCB9, 0x5766, 0xCCBA, 0x6BEF, 0xCCBB, 0x8892,
+	0xCCBC, 0x78B3, 0xCCBD, 0x63A2, 0xCCBE, 0x53F9, 0xCCBF, 0x70AD,
+	0xCCC0, 0x6C64, 0xCCC1, 0x5858, 0xCCC2, 0x642A, 0xCCC3, 0x5802,
+	0xCCC4, 0x68E0, 0xCCC5, 0x819B, 0xCCC6, 0x5510, 0xCCC7, 0x7CD6,
+	0xCCC8, 0x5018, 0xCCC9, 0x8EBA, 0xCCCA, 0x6DCC, 0xCCCB, 0x8D9F,
+	0xCCCC, 0x70EB, 0xCCCD, 0x638F, 0xCCCE, 0x6D9B, 0xCCCF, 0x6ED4,
+	0xCCD0, 0x7EE6, 0xCCD1, 0x8404, 0xCCD2, 0x6843, 0xCCD3, 0x9003,
+	0xCCD4, 0x6DD8, 0xCCD5, 0x9676, 0xCCD6, 0x8BA8, 0xCCD7, 0x5957,
+	0xCCD8, 0x7279, 0xCCD9, 0x85E4, 0xCCDA, 0x817E, 0xCCDB, 0x75BC,
+	0xCCDC, 0x8A8A, 0xCCDD, 0x68AF, 0xCCDE, 0x5254, 0xCCDF, 0x8E22,
+	0xCCE0, 0x9511, 0xCCE1, 0x63D0, 0xCCE2, 0x9898, 0xCCE3, 0x8E44,
+	0xCCE4, 0x557C, 0xCCE5, 0x4F53, 0xCCE6, 0x66FF, 0xCCE7, 0x568F,
+	0xCCE8, 0x60D5, 0xCCE9, 0x6D95, 0xCCEA, 0x5243, 0xCCEB, 0x5C49,
+	0xCCEC, 0x5929, 0xCCED, 0x6DFB, 0xCCEE, 0x586B, 0xCCEF, 0x7530,
+	0xCCF0, 0x751C, 0xCCF1, 0x606C, 0xCCF2, 0x8214, 0xCCF3, 0x8146,
+	0xCCF4, 0x6311, 0xCCF5, 0x6761, 0xCCF6, 0x8FE2, 0xCCF7, 0x773A,
+	0xCCF8, 0x8DF3, 0xCCF9, 0x8D34, 0xCCFA, 0x94C1, 0xCCFB, 0x5E16,
+	0xCCFC, 0x5385, 0xCCFD, 0x542C, 0xCCFE, 0x70C3, 0xCD40, 0x866D,
+	0xCD41, 0x866F, 0xCD42, 0x8670, 0xCD43, 0x8672, 0xCD44, 0x8673,
+	0xCD45, 0x8674, 0xCD46, 0x8675, 0xCD47, 0x8676, 0xCD48, 0x8677,
+	0xCD49, 0x8678, 0xCD4A, 0x8683, 0xCD4B, 0x8684, 0xCD4C, 0x8685,
+	0xCD4D, 0x8686, 0xCD4E, 0x8687, 0xCD4F, 0x8688, 0xCD50, 0x8689,
+	0xCD51, 0x868E, 0xCD52, 0x868F, 0xCD53, 0x8690, 0xCD54, 0x8691,
+	0xCD55, 0x8692, 0xCD56, 0x8694, 0xCD57, 0x8696, 0xCD58, 0x8697,
+	0xCD59, 0x8698, 0xCD5A, 0x8699, 0xCD5B, 0x869A, 0xCD5C, 0x869B,
+	0xCD5D, 0x869E, 0xCD5E, 0x869F, 0xCD5F, 0x86A0, 0xCD60, 0x86A1,
+	0xCD61, 0x86A2, 0xCD62, 0x86A5, 0xCD63, 0x86A6, 0xCD64, 0x86AB,
+	0xCD65, 0x86AD, 0xCD66, 0x86AE, 0xCD67, 0x86B2, 0xCD68, 0x86B3,
+	0xCD69, 0x86B7, 0xCD6A, 0x86B8, 0xCD6B, 0x86B9, 0xCD6C, 0x86BB,
+	0xCD6D, 0x86BC, 0xCD6E, 0x86BD, 0xCD6F, 0x86BE, 0xCD70, 0x86BF,
+	0xCD71, 0x86C1, 0xCD72, 0x86C2, 0xCD73, 0x86C3, 0xCD74, 0x86C5,
+	0xCD75, 0x86C8, 0xCD76, 0x86CC, 0xCD77, 0x86CD, 0xCD78, 0x86D2,
+	0xCD79, 0x86D3, 0xCD7A, 0x86D5, 0xCD7B, 0x86D6, 0xCD7C, 0x86D7,
+	0xCD7D, 0x86DA, 0xCD7E, 0x86DC, 0xCD80, 0x86DD, 0xCD81, 0x86E0,
+	0xCD82, 0x86E1, 0xCD83, 0x86E2, 0xCD84, 0x86E3, 0xCD85, 0x86E5,
+	0xCD86, 0x86E6, 0xCD87, 0x86E7, 0xCD88, 0x86E8, 0xCD89, 0x86EA,
+	0xCD8A, 0x86EB, 0xCD8B, 0x86EC, 0xCD8C, 0x86EF, 0xCD8D, 0x86F5,
+	0xCD8E, 0x86F6, 0xCD8F, 0x86F7, 0xCD90, 0x86FA, 0xCD91, 0x86FB,
+	0xCD92, 0x86FC, 0xCD93, 0x86FD, 0xCD94, 0x86FF, 0xCD95, 0x8701,
+	0xCD96, 0x8704, 0xCD97, 0x8705, 0xCD98, 0x8706, 0xCD99, 0x870B,
+	0xCD9A, 0x870C, 0xCD9B, 0x870E, 0xCD9C, 0x870F, 0xCD9D, 0x8710,
+	0xCD9E, 0x8711, 0xCD9F, 0x8714, 0xCDA0, 0x8716, 0xCDA1, 0x6C40,
+	0xCDA2, 0x5EF7, 0xCDA3, 0x505C, 0xCDA4, 0x4EAD, 0xCDA5, 0x5EAD,
+	0xCDA6, 0x633A, 0xCDA7, 0x8247, 0xCDA8, 0x901A, 0xCDA9, 0x6850,
+	0xCDAA, 0x916E, 0xCDAB, 0x77B3, 0xCDAC, 0x540C, 0xCDAD, 0x94DC,
+	0xCDAE, 0x5F64, 0xCDAF, 0x7AE5, 0xCDB0, 0x6876, 0xCDB1, 0x6345,
+	0xCDB2, 0x7B52, 0xCDB3, 0x7EDF, 0xCDB4, 0x75DB, 0xCDB5, 0x5077,
+	0xCDB6, 0x6295, 0xCDB7, 0x5934, 0xCDB8, 0x900F, 0xCDB9, 0x51F8,
+	0xCDBA, 0x79C3, 0xCDBB, 0x7A81, 0xCDBC, 0x56FE, 0xCDBD, 0x5F92,
+	0xCDBE, 0x9014, 0xCDBF, 0x6D82, 0xCDC0, 0x5C60, 0xCDC1, 0x571F,
+	0xCDC2, 0x5410, 0xCDC3, 0x5154, 0xCDC4, 0x6E4D, 0xCDC5, 0x56E2,
+	0xCDC6, 0x63A8, 0xCDC7, 0x9893, 0xCDC8, 0x817F, 0xCDC9, 0x8715,
+	0xCDCA, 0x892A, 0xCDCB, 0x9000, 0xCDCC, 0x541E, 0xCDCD, 0x5C6F,
+	0xCDCE, 0x81C0, 0xCDCF, 0x62D6, 0xCDD0, 0x6258, 0xCDD1, 0x8131,
+	0xCDD2, 0x9E35, 0xCDD3, 0x9640, 0xCDD4, 0x9A6E, 0xCDD5, 0x9A7C,
+	0xCDD6, 0x692D, 0xCDD7, 0x59A5, 0xCDD8, 0x62D3, 0xCDD9, 0x553E,
+	0xCDDA, 0x6316, 0xCDDB, 0x54C7, 0xCDDC, 0x86D9, 0xCDDD, 0x6D3C,
+	0xCDDE, 0x5A03, 0xCDDF, 0x74E6, 0xCDE0, 0x889C, 0xCDE1, 0x6B6A,
+	0xCDE2, 0x5916, 0xCDE3, 0x8C4C, 0xCDE4, 0x5F2F, 0xCDE5, 0x6E7E,
+	0xCDE6, 0x73A9, 0xCDE7, 0x987D, 0xCDE8, 0x4E38, 0xCDE9, 0x70F7,
+	0xCDEA, 0x5B8C, 0xCDEB, 0x7897, 0xCDEC, 0x633D, 0xCDED, 0x665A,
+	0xCDEE, 0x7696, 0xCDEF, 0x60CB, 0xCDF0, 0x5B9B, 0xCDF1, 0x5A49,
+	0xCDF2, 0x4E07, 0xCDF3, 0x8155, 0xCDF4, 0x6C6A, 0xCDF5, 0x738B,
+	0xCDF6, 0x4EA1, 0xCDF7, 0x6789, 0xCDF8, 0x7F51, 0xCDF9, 0x5F80,
+	0xCDFA, 0x65FA, 0xCDFB, 0x671B, 0xCDFC, 0x5FD8, 0xCDFD, 0x5984,
+	0xCDFE, 0x5A01, 0xCE40, 0x8719, 0xCE41, 0x871B, 0xCE42, 0x871D,
+	0xCE43, 0x871F, 0xCE44, 0x8720, 0xCE45, 0x8724, 0xCE46, 0x8726,
+	0xCE47, 0x8727, 0xCE48, 0x8728, 0xCE49, 0x872A, 0xCE4A, 0x872B,
+	0xCE4B, 0x872C, 0xCE4C, 0x872D, 0xCE4D, 0x872F, 0xCE4E, 0x8730,
+	0xCE4F, 0x8732, 0xCE50, 0x8733, 0xCE51, 0x8735, 0xCE52, 0x8736,
+	0xCE53, 0x8738, 0xCE54, 0x8739, 0xCE55, 0x873A, 0xCE56, 0x873C,
+	0xCE57, 0x873D, 0xCE58, 0x8740, 0xCE59, 0x8741, 0xCE5A, 0x8742,
+	0xCE5B, 0x8743, 0xCE5C, 0x8744, 0xCE5D, 0x8745, 0xCE5E, 0x8746,
+	0xCE5F, 0x874A, 0xCE60, 0x874B, 0xCE61, 0x874D, 0xCE62, 0x874F,
+	0xCE63, 0x8750, 0xCE64, 0x8751, 0xCE65, 0x8752, 0xCE66, 0x8754,
+	0xCE67, 0x8755, 0xCE68, 0x8756, 0xCE69, 0x8758, 0xCE6A, 0x875A,
+	0xCE6B, 0x875B, 0xCE6C, 0x875C, 0xCE6D, 0x875D, 0xCE6E, 0x875E,
+	0xCE6F, 0x875F, 0xCE70, 0x8761, 0xCE71, 0x8762, 0xCE72, 0x8766,
+	0xCE73, 0x8767, 0xCE74, 0x8768, 0xCE75, 0x8769, 0xCE76, 0x876A,
+	0xCE77, 0x876B, 0xCE78, 0x876C, 0xCE79, 0x876D, 0xCE7A, 0x876F,
+	0xCE7B, 0x8771, 0xCE7C, 0x8772, 0xCE7D, 0x8773, 0xCE7E, 0x8775,
+	0xCE80, 0x8777, 0xCE81, 0x8778, 0xCE82, 0x8779, 0xCE83, 0x877A,
+	0xCE84, 0x877F, 0xCE85, 0x8780, 0xCE86, 0x8781, 0xCE87, 0x8784,
+	0xCE88, 0x8786, 0xCE89, 0x8787, 0xCE8A, 0x8789, 0xCE8B, 0x878A,
+	0xCE8C, 0x878C, 0xCE8D, 0x878E, 0xCE8E, 0x878F, 0xCE8F, 0x8790,
+	0xCE90, 0x8791, 0xCE91, 0x8792, 0xCE92, 0x8794, 0xCE93, 0x8795,
+	0xCE94, 0x8796, 0xCE95, 0x8798, 0xCE96, 0x8799, 0xCE97, 0x879A,
+	0xCE98, 0x879B, 0xCE99, 0x879C, 0xCE9A, 0x879D, 0xCE9B, 0x879E,
+	0xCE9C, 0x87A0, 0xCE9D, 0x87A1, 0xCE9E, 0x87A2, 0xCE9F, 0x87A3,
+	0xCEA0, 0x87A4, 0xCEA1, 0x5DCD, 0xCEA2, 0x5FAE, 0xCEA3, 0x5371,
+	0xCEA4, 0x97E6, 0xCEA5, 0x8FDD, 0xCEA6, 0x6845, 0xCEA7, 0x56F4,
+	0xCEA8, 0x552F, 0xCEA9, 0x60DF, 0xCEAA, 0x4E3A, 0xCEAB, 0x6F4D,
+	0xCEAC, 0x7EF4, 0xCEAD, 0x82C7, 0xCEAE, 0x840E, 0xCEAF, 0x59D4,
+	0xCEB0, 0x4F1F, 0xCEB1, 0x4F2A, 0xCEB2, 0x5C3E, 0xCEB3, 0x7EAC,
+	0xCEB4, 0x672A, 0xCEB5, 0x851A, 0xCEB6, 0x5473, 0xCEB7, 0x754F,
+	0xCEB8, 0x80C3, 0xCEB9, 0x5582, 0xCEBA, 0x9B4F, 0xCEBB, 0x4F4D,
+	0xCEBC, 0x6E2D, 0xCEBD, 0x8C13, 0xCEBE, 0x5C09, 0xCEBF, 0x6170,
+	0xCEC0, 0x536B, 0xCEC1, 0x761F, 0xCEC2, 0x6E29, 0xCEC3, 0x868A,
+	0xCEC4, 0x6587, 0xCEC5, 0x95FB, 0xCEC6, 0x7EB9, 0xCEC7, 0x543B,
+	0xCEC8, 0x7A33, 0xCEC9, 0x7D0A, 0xCECA, 0x95EE, 0xCECB, 0x55E1,
+	0xCECC, 0x7FC1, 0xCECD, 0x74EE, 0xCECE, 0x631D, 0xCECF, 0x8717,
+	0xCED0, 0x6DA1, 0xCED1, 0x7A9D, 0xCED2, 0x6211, 0xCED3, 0x65A1,
+	0xCED4, 0x5367, 0xCED5, 0x63E1, 0xCED6, 0x6C83, 0xCED7, 0x5DEB,
+	0xCED8, 0x545C, 0xCED9, 0x94A8, 0xCEDA, 0x4E4C, 0xCEDB, 0x6C61,
+	0xCEDC, 0x8BEC, 0xCEDD, 0x5C4B, 0xCEDE, 0x65E0, 0xCEDF, 0x829C,
+	0xCEE0, 0x68A7, 0xCEE1, 0x543E, 0xCEE2, 0x5434, 0xCEE3, 0x6BCB,
+	0xCEE4, 0x6B66, 0xCEE5, 0x4E94, 0xCEE6, 0x6342, 0xCEE7, 0x5348,
+	0xCEE8, 0x821E, 0xCEE9, 0x4F0D, 0xCEEA, 0x4FAE, 0xCEEB, 0x575E,
+	0xCEEC, 0x620A, 0xCEED, 0x96FE, 0xCEEE, 0x6664, 0xCEEF, 0x7269,
+	0xCEF0, 0x52FF, 0xCEF1, 0x52A1, 0xCEF2, 0x609F, 0xCEF3, 0x8BEF,
+	0xCEF4, 0x6614, 0xCEF5, 0x7199, 0xCEF6, 0x6790, 0xCEF7, 0x897F,
+	0xCEF8, 0x7852, 0xCEF9, 0x77FD, 0xCEFA, 0x6670, 0xCEFB, 0x563B,
+	0xCEFC, 0x5438, 0xCEFD, 0x9521, 0xCEFE, 0x727A, 0xCF40, 0x87A5,
+	0xCF41, 0x87A6, 0xCF42, 0x87A7, 0xCF43, 0x87A9, 0xCF44, 0x87AA,
+	0xCF45, 0x87AE, 0xCF46, 0x87B0, 0xCF47, 0x87B1, 0xCF48, 0x87B2,
+	0xCF49, 0x87B4, 0xCF4A, 0x87B6, 0xCF4B, 0x87B7, 0xCF4C, 0x87B8,
+	0xCF4D, 0x87B9, 0xCF4E, 0x87BB, 0xCF4F, 0x87BC, 0xCF50, 0x87BE,
+	0xCF51, 0x87BF, 0xCF52, 0x87C1, 0xCF53, 0x87C2, 0xCF54, 0x87C3,
+	0xCF55, 0x87C4, 0xCF56, 0x87C5, 0xCF57, 0x87C7, 0xCF58, 0x87C8,
+	0xCF59, 0x87C9, 0xCF5A, 0x87CC, 0xCF5B, 0x87CD, 0xCF5C, 0x87CE,
+	0xCF5D, 0x87CF, 0xCF5E, 0x87D0, 0xCF5F, 0x87D4, 0xCF60, 0x87D5,
+	0xCF61, 0x87D6, 0xCF62, 0x87D7, 0xCF63, 0x87D8, 0xCF64, 0x87D9,
+	0xCF65, 0x87DA, 0xCF66, 0x87DC, 0xCF67, 0x87DD, 0xCF68, 0x87DE,
+	0xCF69, 0x87DF, 0xCF6A, 0x87E1, 0xCF6B, 0x87E2, 0xCF6C, 0x87E3,
+	0xCF6D, 0x87E4, 0xCF6E, 0x87E6, 0xCF6F, 0x87E7, 0xCF70, 0x87E8,
+	0xCF71, 0x87E9, 0xCF72, 0x87EB, 0xCF73, 0x87EC, 0xCF74, 0x87ED,
+	0xCF75, 0x87EF, 0xCF76, 0x87F0, 0xCF77, 0x87F1, 0xCF78, 0x87F2,
+	0xCF79, 0x87F3, 0xCF7A, 0x87F4, 0xCF7B, 0x87F5, 0xCF7C, 0x87F6,
+	0xCF7D, 0x87F7, 0xCF7E, 0x87F8, 0xCF80, 0x87FA, 0xCF81, 0x87FB,
+	0xCF82, 0x87FC, 0xCF83, 0x87FD, 0xCF84, 0x87FF, 0xCF85, 0x8800,
+	0xCF86, 0x8801, 0xCF87, 0x8802, 0xCF88, 0x8804, 0xCF89, 0x8805,
+	0xCF8A, 0x8806, 0xCF8B, 0x8807, 0xCF8C, 0x8808, 0xCF8D, 0x8809,
+	0xCF8E, 0x880B, 0xCF8F, 0x880C, 0xCF90, 0x880D, 0xCF91, 0x880E,
+	0xCF92, 0x880F, 0xCF93, 0x8810, 0xCF94, 0x8811, 0xCF95, 0x8812,
+	0xCF96, 0x8814, 0xCF97, 0x8817, 0xCF98, 0x8818, 0xCF99, 0x8819,
+	0xCF9A, 0x881A, 0xCF9B, 0x881C, 0xCF9C, 0x881D, 0xCF9D, 0x881E,
+	0xCF9E, 0x881F, 0xCF9F, 0x8820, 0xCFA0, 0x8823, 0xCFA1, 0x7A00,
+	0xCFA2, 0x606F, 0xCFA3, 0x5E0C, 0xCFA4, 0x6089, 0xCFA5, 0x819D,
+	0xCFA6, 0x5915, 0xCFA7, 0x60DC, 0xCFA8, 0x7184, 0xCFA9, 0x70EF,
+	0xCFAA, 0x6EAA, 0xCFAB, 0x6C50, 0xCFAC, 0x7280, 0xCFAD, 0x6A84,
+	0xCFAE, 0x88AD, 0xCFAF, 0x5E2D, 0xCFB0, 0x4E60, 0xCFB1, 0x5AB3,
+	0xCFB2, 0x559C, 0xCFB3, 0x94E3, 0xCFB4, 0x6D17, 0xCFB5, 0x7CFB,
+	0xCFB6, 0x9699, 0xCFB7, 0x620F, 0xCFB8, 0x7EC6, 0xCFB9, 0x778E,
+	0xCFBA, 0x867E, 0xCFBB, 0x5323, 0xCFBC, 0x971E, 0xCFBD, 0x8F96,
+	0xCFBE, 0x6687, 0xCFBF, 0x5CE1, 0xCFC0, 0x4FA0, 0xCFC1, 0x72ED,
+	0xCFC2, 0x4E0B, 0xCFC3, 0x53A6, 0xCFC4, 0x590F, 0xCFC5, 0x5413,
+	0xCFC6, 0x6380, 0xCFC7, 0x9528, 0xCFC8, 0x5148, 0xCFC9, 0x4ED9,
+	0xCFCA, 0x9C9C, 0xCFCB, 0x7EA4, 0xCFCC, 0x54B8, 0xCFCD, 0x8D24,
+	0xCFCE, 0x8854, 0xCFCF, 0x8237, 0xCFD0, 0x95F2, 0xCFD1, 0x6D8E,
+	0xCFD2, 0x5F26, 0xCFD3, 0x5ACC, 0xCFD4, 0x663E, 0xCFD5, 0x9669,
+	0xCFD6, 0x73B0, 0xCFD7, 0x732E, 0xCFD8, 0x53BF, 0xCFD9, 0x817A,
+	0xCFDA, 0x9985, 0xCFDB, 0x7FA1, 0xCFDC, 0x5BAA, 0xCFDD, 0x9677,
+	0xCFDE, 0x9650, 0xCFDF, 0x7EBF, 0xCFE0, 0x76F8, 0xCFE1, 0x53A2,
+	0xCFE2, 0x9576, 0xCFE3, 0x9999, 0xCFE4, 0x7BB1, 0xCFE5, 0x8944,
+	0xCFE6, 0x6E58, 0xCFE7, 0x4E61, 0xCFE8, 0x7FD4, 0xCFE9, 0x7965,
+	0xCFEA, 0x8BE6, 0xCFEB, 0x60F3, 0xCFEC, 0x54CD, 0xCFED, 0x4EAB,
+	0xCFEE, 0x9879, 0xCFEF, 0x5DF7, 0xCFF0, 0x6A61, 0xCFF1, 0x50CF,
+	0xCFF2, 0x5411, 0xCFF3, 0x8C61, 0xCFF4, 0x8427, 0xCFF5, 0x785D,
+	0xCFF6, 0x9704, 0xCFF7, 0x524A, 0xCFF8, 0x54EE, 0xCFF9, 0x56A3,
+	0xCFFA, 0x9500, 0xCFFB, 0x6D88, 0xCFFC, 0x5BB5, 0xCFFD, 0x6DC6,
+	0xCFFE, 0x6653, 0xD040, 0x8824, 0xD041, 0x8825, 0xD042, 0x8826,
+	0xD043, 0x8827, 0xD044, 0x8828, 0xD045, 0x8829, 0xD046, 0x882A,
+	0xD047, 0x882B, 0xD048, 0x882C, 0xD049, 0x882D, 0xD04A, 0x882E,
+	0xD04B, 0x882F, 0xD04C, 0x8830, 0xD04D, 0x8831, 0xD04E, 0x8833,
+	0xD04F, 0x8834, 0xD050, 0x8835, 0xD051, 0x8836, 0xD052, 0x8837,
+	0xD053, 0x8838, 0xD054, 0x883A, 0xD055, 0x883B, 0xD056, 0x883D,
+	0xD057, 0x883E, 0xD058, 0x883F, 0xD059, 0x8841, 0xD05A, 0x8842,
+	0xD05B, 0x8843, 0xD05C, 0x8846, 0xD05D, 0x8847, 0xD05E, 0x8848,
+	0xD05F, 0x8849, 0xD060, 0x884A, 0xD061, 0x884B, 0xD062, 0x884E,
+	0xD063, 0x884F, 0xD064, 0x8850, 0xD065, 0x8851, 0xD066, 0x8852,
+	0xD067, 0x8853, 0xD068, 0x8855, 0xD069, 0x8856, 0xD06A, 0x8858,
+	0xD06B, 0x885A, 0xD06C, 0x885B, 0xD06D, 0x885C, 0xD06E, 0x885D,
+	0xD06F, 0x885E, 0xD070, 0x885F, 0xD071, 0x8860, 0xD072, 0x8866,
+	0xD073, 0x8867, 0xD074, 0x886A, 0xD075, 0x886D, 0xD076, 0x886F,
+	0xD077, 0x8871, 0xD078, 0x8873, 0xD079, 0x8874, 0xD07A, 0x8875,
+	0xD07B, 0x8876, 0xD07C, 0x8878, 0xD07D, 0x8879, 0xD07E, 0x887A,
+	0xD080, 0x887B, 0xD081, 0x887C, 0xD082, 0x8880, 0xD083, 0x8883,
+	0xD084, 0x8886, 0xD085, 0x8887, 0xD086, 0x8889, 0xD087, 0x888A,
+	0xD088, 0x888C, 0xD089, 0x888E, 0xD08A, 0x888F, 0xD08B, 0x8890,
+	0xD08C, 0x8891, 0xD08D, 0x8893, 0xD08E, 0x8894, 0xD08F, 0x8895,
+	0xD090, 0x8897, 0xD091, 0x8898, 0xD092, 0x8899, 0xD093, 0x889A,
+	0xD094, 0x889B, 0xD095, 0x889D, 0xD096, 0x889E, 0xD097, 0x889F,
+	0xD098, 0x88A0, 0xD099, 0x88A1, 0xD09A, 0x88A3, 0xD09B, 0x88A5,
+	0xD09C, 0x88A6, 0xD09D, 0x88A7, 0xD09E, 0x88A8, 0xD09F, 0x88A9,
+	0xD0A0, 0x88AA, 0xD0A1, 0x5C0F, 0xD0A2, 0x5B5D, 0xD0A3, 0x6821,
+	0xD0A4, 0x8096, 0xD0A5, 0x5578, 0xD0A6, 0x7B11, 0xD0A7, 0x6548,
+	0xD0A8, 0x6954, 0xD0A9, 0x4E9B, 0xD0AA, 0x6B47, 0xD0AB, 0x874E,
+	0xD0AC, 0x978B, 0xD0AD, 0x534F, 0xD0AE, 0x631F, 0xD0AF, 0x643A,
+	0xD0B0, 0x90AA, 0xD0B1, 0x659C, 0xD0B2, 0x80C1, 0xD0B3, 0x8C10,
+	0xD0B4, 0x5199, 0xD0B5, 0x68B0, 0xD0B6, 0x5378, 0xD0B7, 0x87F9,
+	0xD0B8, 0x61C8, 0xD0B9, 0x6CC4, 0xD0BA, 0x6CFB, 0xD0BB, 0x8C22,
+	0xD0BC, 0x5C51, 0xD0BD, 0x85AA, 0xD0BE, 0x82AF, 0xD0BF, 0x950C,
+	0xD0C0, 0x6B23, 0xD0C1, 0x8F9B, 0xD0C2, 0x65B0, 0xD0C3, 0x5FFB,
+	0xD0C4, 0x5FC3, 0xD0C5, 0x4FE1, 0xD0C6, 0x8845, 0xD0C7, 0x661F,
+	0xD0C8, 0x8165, 0xD0C9, 0x7329, 0xD0CA, 0x60FA, 0xD0CB, 0x5174,
+	0xD0CC, 0x5211, 0xD0CD, 0x578B, 0xD0CE, 0x5F62, 0xD0CF, 0x90A2,
+	0xD0D0, 0x884C, 0xD0D1, 0x9192, 0xD0D2, 0x5E78, 0xD0D3, 0x674F,
+	0xD0D4, 0x6027, 0xD0D5, 0x59D3, 0xD0D6, 0x5144, 0xD0D7, 0x51F6,
+	0xD0D8, 0x80F8, 0xD0D9, 0x5308, 0xD0DA, 0x6C79, 0xD0DB, 0x96C4,
+	0xD0DC, 0x718A, 0xD0DD, 0x4F11, 0xD0DE, 0x4FEE, 0xD0DF, 0x7F9E,
+	0xD0E0, 0x673D, 0xD0E1, 0x55C5, 0xD0E2, 0x9508, 0xD0E3, 0x79C0,
+	0xD0E4, 0x8896, 0xD0E5, 0x7EE3, 0xD0E6, 0x589F, 0xD0E7, 0x620C,
+	0xD0E8, 0x9700, 0xD0E9, 0x865A, 0xD0EA, 0x5618, 0xD0EB, 0x987B,
+	0xD0EC, 0x5F90, 0xD0ED, 0x8BB8, 0xD0EE, 0x84C4, 0xD0EF, 0x9157,
+	0xD0F0, 0x53D9, 0xD0F1, 0x65ED, 0xD0F2, 0x5E8F, 0xD0F3, 0x755C,
+	0xD0F4, 0x6064, 0xD0F5, 0x7D6E, 0xD0F6, 0x5A7F, 0xD0F7, 0x7EEA,
+	0xD0F8, 0x7EED, 0xD0F9, 0x8F69, 0xD0FA, 0x55A7, 0xD0FB, 0x5BA3,
+	0xD0FC, 0x60AC, 0xD0FD, 0x65CB, 0xD0FE, 0x7384, 0xD140, 0x88AC,
+	0xD141, 0x88AE, 0xD142, 0x88AF, 0xD143, 0x88B0, 0xD144, 0x88B2,
+	0xD145, 0x88B3, 0xD146, 0x88B4, 0xD147, 0x88B5, 0xD148, 0x88B6,
+	0xD149, 0x88B8, 0xD14A, 0x88B9, 0xD14B, 0x88BA, 0xD14C, 0x88BB,
+	0xD14D, 0x88BD, 0xD14E, 0x88BE, 0xD14F, 0x88BF, 0xD150, 0x88C0,
+	0xD151, 0x88C3, 0xD152, 0x88C4, 0xD153, 0x88C7, 0xD154, 0x88C8,
+	0xD155, 0x88CA, 0xD156, 0x88CB, 0xD157, 0x88CC, 0xD158, 0x88CD,
+	0xD159, 0x88CF, 0xD15A, 0x88D0, 0xD15B, 0x88D1, 0xD15C, 0x88D3,
+	0xD15D, 0x88D6, 0xD15E, 0x88D7, 0xD15F, 0x88DA, 0xD160, 0x88DB,
+	0xD161, 0x88DC, 0xD162, 0x88DD, 0xD163, 0x88DE, 0xD164, 0x88E0,
+	0xD165, 0x88E1, 0xD166, 0x88E6, 0xD167, 0x88E7, 0xD168, 0x88E9,
+	0xD169, 0x88EA, 0xD16A, 0x88EB, 0xD16B, 0x88EC, 0xD16C, 0x88ED,
+	0xD16D, 0x88EE, 0xD16E, 0x88EF, 0xD16F, 0x88F2, 0xD170, 0x88F5,
+	0xD171, 0x88F6, 0xD172, 0x88F7, 0xD173, 0x88FA, 0xD174, 0x88FB,
+	0xD175, 0x88FD, 0xD176, 0x88FF, 0xD177, 0x8900, 0xD178, 0x8901,
+	0xD179, 0x8903, 0xD17A, 0x8904, 0xD17B, 0x8905, 0xD17C, 0x8906,
+	0xD17D, 0x8907, 0xD17E, 0x8908, 0xD180, 0x8909, 0xD181, 0x890B,
+	0xD182, 0x890C, 0xD183, 0x890D, 0xD184, 0x890E, 0xD185, 0x890F,
+	0xD186, 0x8911, 0xD187, 0x8914, 0xD188, 0x8915, 0xD189, 0x8916,
+	0xD18A, 0x8917, 0xD18B, 0x8918, 0xD18C, 0x891C, 0xD18D, 0x891D,
+	0xD18E, 0x891E, 0xD18F, 0x891F, 0xD190, 0x8920, 0xD191, 0x8922,
+	0xD192, 0x8923, 0xD193, 0x8924, 0xD194, 0x8926, 0xD195, 0x8927,
+	0xD196, 0x8928, 0xD197, 0x8929, 0xD198, 0x892C, 0xD199, 0x892D,
+	0xD19A, 0x892E, 0xD19B, 0x892F, 0xD19C, 0x8931, 0xD19D, 0x8932,
+	0xD19E, 0x8933, 0xD19F, 0x8935, 0xD1A0, 0x8937, 0xD1A1, 0x9009,
+	0xD1A2, 0x7663, 0xD1A3, 0x7729, 0xD1A4, 0x7EDA, 0xD1A5, 0x9774,
+	0xD1A6, 0x859B, 0xD1A7, 0x5B66, 0xD1A8, 0x7A74, 0xD1A9, 0x96EA,
+	0xD1AA, 0x8840, 0xD1AB, 0x52CB, 0xD1AC, 0x718F, 0xD1AD, 0x5FAA,
+	0xD1AE, 0x65EC, 0xD1AF, 0x8BE2, 0xD1B0, 0x5BFB, 0xD1B1, 0x9A6F,
+	0xD1B2, 0x5DE1, 0xD1B3, 0x6B89, 0xD1B4, 0x6C5B, 0xD1B5, 0x8BAD,
+	0xD1B6, 0x8BAF, 0xD1B7, 0x900A, 0xD1B8, 0x8FC5, 0xD1B9, 0x538B,
+	0xD1BA, 0x62BC, 0xD1BB, 0x9E26, 0xD1BC, 0x9E2D, 0xD1BD, 0x5440,
+	0xD1BE, 0x4E2B, 0xD1BF, 0x82BD, 0xD1C0, 0x7259, 0xD1C1, 0x869C,
+	0xD1C2, 0x5D16, 0xD1C3, 0x8859, 0xD1C4, 0x6DAF, 0xD1C5, 0x96C5,
+	0xD1C6, 0x54D1, 0xD1C7, 0x4E9A, 0xD1C8, 0x8BB6, 0xD1C9, 0x7109,
+	0xD1CA, 0x54BD, 0xD1CB, 0x9609, 0xD1CC, 0x70DF, 0xD1CD, 0x6DF9,
+	0xD1CE, 0x76D0, 0xD1CF, 0x4E25, 0xD1D0, 0x7814, 0xD1D1, 0x8712,
+	0xD1D2, 0x5CA9, 0xD1D3, 0x5EF6, 0xD1D4, 0x8A00, 0xD1D5, 0x989C,
+	0xD1D6, 0x960E, 0xD1D7, 0x708E, 0xD1D8, 0x6CBF, 0xD1D9, 0x5944,
+	0xD1DA, 0x63A9, 0xD1DB, 0x773C, 0xD1DC, 0x884D, 0xD1DD, 0x6F14,
+	0xD1DE, 0x8273, 0xD1DF, 0x5830, 0xD1E0, 0x71D5, 0xD1E1, 0x538C,
+	0xD1E2, 0x781A, 0xD1E3, 0x96C1, 0xD1E4, 0x5501, 0xD1E5, 0x5F66,
+	0xD1E6, 0x7130, 0xD1E7, 0x5BB4, 0xD1E8, 0x8C1A, 0xD1E9, 0x9A8C,
+	0xD1EA, 0x6B83, 0xD1EB, 0x592E, 0xD1EC, 0x9E2F, 0xD1ED, 0x79E7,
+	0xD1EE, 0x6768, 0xD1EF, 0x626C, 0xD1F0, 0x4F6F, 0xD1F1, 0x75A1,
+	0xD1F2, 0x7F8A, 0xD1F3, 0x6D0B, 0xD1F4, 0x9633, 0xD1F5, 0x6C27,
+	0xD1F6, 0x4EF0, 0xD1F7, 0x75D2, 0xD1F8, 0x517B, 0xD1F9, 0x6837,
+	0xD1FA, 0x6F3E, 0xD1FB, 0x9080, 0xD1FC, 0x8170, 0xD1FD, 0x5996,
+	0xD1FE, 0x7476, 0xD240, 0x8938, 0xD241, 0x8939, 0xD242, 0x893A,
+	0xD243, 0x893B, 0xD244, 0x893C, 0xD245, 0x893D, 0xD246, 0x893E,
+	0xD247, 0x893F, 0xD248, 0x8940, 0xD249, 0x8942, 0xD24A, 0x8943,
+	0xD24B, 0x8945, 0xD24C, 0x8946, 0xD24D, 0x8947, 0xD24E, 0x8948,
+	0xD24F, 0x8949, 0xD250, 0x894A, 0xD251, 0x894B, 0xD252, 0x894C,
+	0xD253, 0x894D, 0xD254, 0x894E, 0xD255, 0x894F, 0xD256, 0x8950,
+	0xD257, 0x8951, 0xD258, 0x8952, 0xD259, 0x8953, 0xD25A, 0x8954,
+	0xD25B, 0x8955, 0xD25C, 0x8956, 0xD25D, 0x8957, 0xD25E, 0x8958,
+	0xD25F, 0x8959, 0xD260, 0x895A, 0xD261, 0x895B, 0xD262, 0x895C,
+	0xD263, 0x895D, 0xD264, 0x8960, 0xD265, 0x8961, 0xD266, 0x8962,
+	0xD267, 0x8963, 0xD268, 0x8964, 0xD269, 0x8965, 0xD26A, 0x8967,
+	0xD26B, 0x8968, 0xD26C, 0x8969, 0xD26D, 0x896A, 0xD26E, 0x896B,
+	0xD26F, 0x896C, 0xD270, 0x896D, 0xD271, 0x896E, 0xD272, 0x896F,
+	0xD273, 0x8970, 0xD274, 0x8971, 0xD275, 0x8972, 0xD276, 0x8973,
+	0xD277, 0x8974, 0xD278, 0x8975, 0xD279, 0x8976, 0xD27A, 0x8977,
+	0xD27B, 0x8978, 0xD27C, 0x8979, 0xD27D, 0x897A, 0xD27E, 0x897C,
+	0xD280, 0x897D, 0xD281, 0x897E, 0xD282, 0x8980, 0xD283, 0x8982,
+	0xD284, 0x8984, 0xD285, 0x8985, 0xD286, 0x8987, 0xD287, 0x8988,
+	0xD288, 0x8989, 0xD289, 0x898A, 0xD28A, 0x898B, 0xD28B, 0x898C,
+	0xD28C, 0x898D, 0xD28D, 0x898E, 0xD28E, 0x898F, 0xD28F, 0x8990,
+	0xD290, 0x8991, 0xD291, 0x8992, 0xD292, 0x8993, 0xD293, 0x8994,
+	0xD294, 0x8995, 0xD295, 0x8996, 0xD296, 0x8997, 0xD297, 0x8998,
+	0xD298, 0x8999, 0xD299, 0x899A, 0xD29A, 0x899B, 0xD29B, 0x899C,
+	0xD29C, 0x899D, 0xD29D, 0x899E, 0xD29E, 0x899F, 0xD29F, 0x89A0,
+	0xD2A0, 0x89A1, 0xD2A1, 0x6447, 0xD2A2, 0x5C27, 0xD2A3, 0x9065,
+	0xD2A4, 0x7A91, 0xD2A5, 0x8C23, 0xD2A6, 0x59DA, 0xD2A7, 0x54AC,
+	0xD2A8, 0x8200, 0xD2A9, 0x836F, 0xD2AA, 0x8981, 0xD2AB, 0x8000,
+	0xD2AC, 0x6930, 0xD2AD, 0x564E, 0xD2AE, 0x8036, 0xD2AF, 0x7237,
+	0xD2B0, 0x91CE, 0xD2B1, 0x51B6, 0xD2B2, 0x4E5F, 0xD2B3, 0x9875,
+	0xD2B4, 0x6396, 0xD2B5, 0x4E1A, 0xD2B6, 0x53F6, 0xD2B7, 0x66F3,
+	0xD2B8, 0x814B, 0xD2B9, 0x591C, 0xD2BA, 0x6DB2, 0xD2BB, 0x4E00,
+	0xD2BC, 0x58F9, 0xD2BD, 0x533B, 0xD2BE, 0x63D6, 0xD2BF, 0x94F1,
+	0xD2C0, 0x4F9D, 0xD2C1, 0x4F0A, 0xD2C2, 0x8863, 0xD2C3, 0x9890,
+	0xD2C4, 0x5937, 0xD2C5, 0x9057, 0xD2C6, 0x79FB, 0xD2C7, 0x4EEA,
+	0xD2C8, 0x80F0, 0xD2C9, 0x7591, 0xD2CA, 0x6C82, 0xD2CB, 0x5B9C,
+	0xD2CC, 0x59E8, 0xD2CD, 0x5F5D, 0xD2CE, 0x6905, 0xD2CF, 0x8681,
+	0xD2D0, 0x501A, 0xD2D1, 0x5DF2, 0xD2D2, 0x4E59, 0xD2D3, 0x77E3,
+	0xD2D4, 0x4EE5, 0xD2D5, 0x827A, 0xD2D6, 0x6291, 0xD2D7, 0x6613,
+	0xD2D8, 0x9091, 0xD2D9, 0x5C79, 0xD2DA, 0x4EBF, 0xD2DB, 0x5F79,
+	0xD2DC, 0x81C6, 0xD2DD, 0x9038, 0xD2DE, 0x8084, 0xD2DF, 0x75AB,
+	0xD2E0, 0x4EA6, 0xD2E1, 0x88D4, 0xD2E2, 0x610F, 0xD2E3, 0x6BC5,
+	0xD2E4, 0x5FC6, 0xD2E5, 0x4E49, 0xD2E6, 0x76CA, 0xD2E7, 0x6EA2,
+	0xD2E8, 0x8BE3, 0xD2E9, 0x8BAE, 0xD2EA, 0x8C0A, 0xD2EB, 0x8BD1,
+	0xD2EC, 0x5F02, 0xD2ED, 0x7FFC, 0xD2EE, 0x7FCC, 0xD2EF, 0x7ECE,
+	0xD2F0, 0x8335, 0xD2F1, 0x836B, 0xD2F2, 0x56E0, 0xD2F3, 0x6BB7,
+	0xD2F4, 0x97F3, 0xD2F5, 0x9634, 0xD2F6, 0x59FB, 0xD2F7, 0x541F,
+	0xD2F8, 0x94F6, 0xD2F9, 0x6DEB, 0xD2FA, 0x5BC5, 0xD2FB, 0x996E,
+	0xD2FC, 0x5C39, 0xD2FD, 0x5F15, 0xD2FE, 0x9690, 0xD340, 0x89A2,
+	0xD341, 0x89A3, 0xD342, 0x89A4, 0xD343, 0x89A5, 0xD344, 0x89A6,
+	0xD345, 0x89A7, 0xD346, 0x89A8, 0xD347, 0x89A9, 0xD348, 0x89AA,
+	0xD349, 0x89AB, 0xD34A, 0x89AC, 0xD34B, 0x89AD, 0xD34C, 0x89AE,
+	0xD34D, 0x89AF, 0xD34E, 0x89B0, 0xD34F, 0x89B1, 0xD350, 0x89B2,
+	0xD351, 0x89B3, 0xD352, 0x89B4, 0xD353, 0x89B5, 0xD354, 0x89B6,
+	0xD355, 0x89B7, 0xD356, 0x89B8, 0xD357, 0x89B9, 0xD358, 0x89BA,
+	0xD359, 0x89BB, 0xD35A, 0x89BC, 0xD35B, 0x89BD, 0xD35C, 0x89BE,
+	0xD35D, 0x89BF, 0xD35E, 0x89C0, 0xD35F, 0x89C3, 0xD360, 0x89CD,
+	0xD361, 0x89D3, 0xD362, 0x89D4, 0xD363, 0x89D5, 0xD364, 0x89D7,
+	0xD365, 0x89D8, 0xD366, 0x89D9, 0xD367, 0x89DB, 0xD368, 0x89DD,
+	0xD369, 0x89DF, 0xD36A, 0x89E0, 0xD36B, 0x89E1, 0xD36C, 0x89E2,
+	0xD36D, 0x89E4, 0xD36E, 0x89E7, 0xD36F, 0x89E8, 0xD370, 0x89E9,
+	0xD371, 0x89EA, 0xD372, 0x89EC, 0xD373, 0x89ED, 0xD374, 0x89EE,
+	0xD375, 0x89F0, 0xD376, 0x89F1, 0xD377, 0x89F2, 0xD378, 0x89F4,
+	0xD379, 0x89F5, 0xD37A, 0x89F6, 0xD37B, 0x89F7, 0xD37C, 0x89F8,
+	0xD37D, 0x89F9, 0xD37E, 0x89FA, 0xD380, 0x89FB, 0xD381, 0x89FC,
+	0xD382, 0x89FD, 0xD383, 0x89FE, 0xD384, 0x89FF, 0xD385, 0x8A01,
+	0xD386, 0x8A02, 0xD387, 0x8A03, 0xD388, 0x8A04, 0xD389, 0x8A05,
+	0xD38A, 0x8A06, 0xD38B, 0x8A08, 0xD38C, 0x8A09, 0xD38D, 0x8A0A,
+	0xD38E, 0x8A0B, 0xD38F, 0x8A0C, 0xD390, 0x8A0D, 0xD391, 0x8A0E,
+	0xD392, 0x8A0F, 0xD393, 0x8A10, 0xD394, 0x8A11, 0xD395, 0x8A12,
+	0xD396, 0x8A13, 0xD397, 0x8A14, 0xD398, 0x8A15, 0xD399, 0x8A16,
+	0xD39A, 0x8A17, 0xD39B, 0x8A18, 0xD39C, 0x8A19, 0xD39D, 0x8A1A,
+	0xD39E, 0x8A1B, 0xD39F, 0x8A1C, 0xD3A0, 0x8A1D, 0xD3A1, 0x5370,
+	0xD3A2, 0x82F1, 0xD3A3, 0x6A31, 0xD3A4, 0x5A74, 0xD3A5, 0x9E70,
+	0xD3A6, 0x5E94, 0xD3A7, 0x7F28, 0xD3A8, 0x83B9, 0xD3A9, 0x8424,
+	0xD3AA, 0x8425, 0xD3AB, 0x8367, 0xD3AC, 0x8747, 0xD3AD, 0x8FCE,
+	0xD3AE, 0x8D62, 0xD3AF, 0x76C8, 0xD3B0, 0x5F71, 0xD3B1, 0x9896,
+	0xD3B2, 0x786C, 0xD3B3, 0x6620, 0xD3B4, 0x54DF, 0xD3B5, 0x62E5,
+	0xD3B6, 0x4F63, 0xD3B7, 0x81C3, 0xD3B8, 0x75C8, 0xD3B9, 0x5EB8,
+	0xD3BA, 0x96CD, 0xD3BB, 0x8E0A, 0xD3BC, 0x86F9, 0xD3BD, 0x548F,
+	0xD3BE, 0x6CF3, 0xD3BF, 0x6D8C, 0xD3C0, 0x6C38, 0xD3C1, 0x607F,
+	0xD3C2, 0x52C7, 0xD3C3, 0x7528, 0xD3C4, 0x5E7D, 0xD3C5, 0x4F18,
+	0xD3C6, 0x60A0, 0xD3C7, 0x5FE7, 0xD3C8, 0x5C24, 0xD3C9, 0x7531,
+	0xD3CA, 0x90AE, 0xD3CB, 0x94C0, 0xD3CC, 0x72B9, 0xD3CD, 0x6CB9,
+	0xD3CE, 0x6E38, 0xD3CF, 0x9149, 0xD3D0, 0x6709, 0xD3D1, 0x53CB,
+	0xD3D2, 0x53F3, 0xD3D3, 0x4F51, 0xD3D4, 0x91C9, 0xD3D5, 0x8BF1,
+	0xD3D6, 0x53C8, 0xD3D7, 0x5E7C, 0xD3D8, 0x8FC2, 0xD3D9, 0x6DE4,
+	0xD3DA, 0x4E8E, 0xD3DB, 0x76C2, 0xD3DC, 0x6986, 0xD3DD, 0x865E,
+	0xD3DE, 0x611A, 0xD3DF, 0x8206, 0xD3E0, 0x4F59, 0xD3E1, 0x4FDE,
+	0xD3E2, 0x903E, 0xD3E3, 0x9C7C, 0xD3E4, 0x6109, 0xD3E5, 0x6E1D,
+	0xD3E6, 0x6E14, 0xD3E7, 0x9685, 0xD3E8, 0x4E88, 0xD3E9, 0x5A31,
+	0xD3EA, 0x96E8, 0xD3EB, 0x4E0E, 0xD3EC, 0x5C7F, 0xD3ED, 0x79B9,
+	0xD3EE, 0x5B87, 0xD3EF, 0x8BED, 0xD3F0, 0x7FBD, 0xD3F1, 0x7389,
+	0xD3F2, 0x57DF, 0xD3F3, 0x828B, 0xD3F4, 0x90C1, 0xD3F5, 0x5401,
+	0xD3F6, 0x9047, 0xD3F7, 0x55BB, 0xD3F8, 0x5CEA, 0xD3F9, 0x5FA1,
+	0xD3FA, 0x6108, 0xD3FB, 0x6B32, 0xD3FC, 0x72F1, 0xD3FD, 0x80B2,
+	0xD3FE, 0x8A89, 0xD440, 0x8A1E, 0xD441, 0x8A1F, 0xD442, 0x8A20,
+	0xD443, 0x8A21, 0xD444, 0x8A22, 0xD445, 0x8A23, 0xD446, 0x8A24,
+	0xD447, 0x8A25, 0xD448, 0x8A26, 0xD449, 0x8A27, 0xD44A, 0x8A28,
+	0xD44B, 0x8A29, 0xD44C, 0x8A2A, 0xD44D, 0x8A2B, 0xD44E, 0x8A2C,
+	0xD44F, 0x8A2D, 0xD450, 0x8A2E, 0xD451, 0x8A2F, 0xD452, 0x8A30,
+	0xD453, 0x8A31, 0xD454, 0x8A32, 0xD455, 0x8A33, 0xD456, 0x8A34,
+	0xD457, 0x8A35, 0xD458, 0x8A36, 0xD459, 0x8A37, 0xD45A, 0x8A38,
+	0xD45B, 0x8A39, 0xD45C, 0x8A3A, 0xD45D, 0x8A3B, 0xD45E, 0x8A3C,
+	0xD45F, 0x8A3D, 0xD460, 0x8A3F, 0xD461, 0x8A40, 0xD462, 0x8A41,
+	0xD463, 0x8A42, 0xD464, 0x8A43, 0xD465, 0x8A44, 0xD466, 0x8A45,
+	0xD467, 0x8A46, 0xD468, 0x8A47, 0xD469, 0x8A49, 0xD46A, 0x8A4A,
+	0xD46B, 0x8A4B, 0xD46C, 0x8A4C, 0xD46D, 0x8A4D, 0xD46E, 0x8A4E,
+	0xD46F, 0x8A4F, 0xD470, 0x8A50, 0xD471, 0x8A51, 0xD472, 0x8A52,
+	0xD473, 0x8A53, 0xD474, 0x8A54, 0xD475, 0x8A55, 0xD476, 0x8A56,
+	0xD477, 0x8A57, 0xD478, 0x8A58, 0xD479, 0x8A59, 0xD47A, 0x8A5A,
+	0xD47B, 0x8A5B, 0xD47C, 0x8A5C, 0xD47D, 0x8A5D, 0xD47E, 0x8A5E,
+	0xD480, 0x8A5F, 0xD481, 0x8A60, 0xD482, 0x8A61, 0xD483, 0x8A62,
+	0xD484, 0x8A63, 0xD485, 0x8A64, 0xD486, 0x8A65, 0xD487, 0x8A66,
+	0xD488, 0x8A67, 0xD489, 0x8A68, 0xD48A, 0x8A69, 0xD48B, 0x8A6A,
+	0xD48C, 0x8A6B, 0xD48D, 0x8A6C, 0xD48E, 0x8A6D, 0xD48F, 0x8A6E,
+	0xD490, 0x8A6F, 0xD491, 0x8A70, 0xD492, 0x8A71, 0xD493, 0x8A72,
+	0xD494, 0x8A73, 0xD495, 0x8A74, 0xD496, 0x8A75, 0xD497, 0x8A76,
+	0xD498, 0x8A77, 0xD499, 0x8A78, 0xD49A, 0x8A7A, 0xD49B, 0x8A7B,
+	0xD49C, 0x8A7C, 0xD49D, 0x8A7D, 0xD49E, 0x8A7E, 0xD49F, 0x8A7F,
+	0xD4A0, 0x8A80, 0xD4A1, 0x6D74, 0xD4A2, 0x5BD3, 0xD4A3, 0x88D5,
+	0xD4A4, 0x9884, 0xD4A5, 0x8C6B, 0xD4A6, 0x9A6D, 0xD4A7, 0x9E33,
+	0xD4A8, 0x6E0A, 0xD4A9, 0x51A4, 0xD4AA, 0x5143, 0xD4AB, 0x57A3,
+	0xD4AC, 0x8881, 0xD4AD, 0x539F, 0xD4AE, 0x63F4, 0xD4AF, 0x8F95,
+	0xD4B0, 0x56ED, 0xD4B1, 0x5458, 0xD4B2, 0x5706, 0xD4B3, 0x733F,
+	0xD4B4, 0x6E90, 0xD4B5, 0x7F18, 0xD4B6, 0x8FDC, 0xD4B7, 0x82D1,
+	0xD4B8, 0x613F, 0xD4B9, 0x6028, 0xD4BA, 0x9662, 0xD4BB, 0x66F0,
+	0xD4BC, 0x7EA6, 0xD4BD, 0x8D8A, 0xD4BE, 0x8DC3, 0xD4BF, 0x94A5,
+	0xD4C0, 0x5CB3, 0xD4C1, 0x7CA4, 0xD4C2, 0x6708, 0xD4C3, 0x60A6,
+	0xD4C4, 0x9605, 0xD4C5, 0x8018, 0xD4C6, 0x4E91, 0xD4C7, 0x90E7,
+	0xD4C8, 0x5300, 0xD4C9, 0x9668, 0xD4CA, 0x5141, 0xD4CB, 0x8FD0,
+	0xD4CC, 0x8574, 0xD4CD, 0x915D, 0xD4CE, 0x6655, 0xD4CF, 0x97F5,
+	0xD4D0, 0x5B55, 0xD4D1, 0x531D, 0xD4D2, 0x7838, 0xD4D3, 0x6742,
+	0xD4D4, 0x683D, 0xD4D5, 0x54C9, 0xD4D6, 0x707E, 0xD4D7, 0x5BB0,
+	0xD4D8, 0x8F7D, 0xD4D9, 0x518D, 0xD4DA, 0x5728, 0xD4DB, 0x54B1,
+	0xD4DC, 0x6512, 0xD4DD, 0x6682, 0xD4DE, 0x8D5E, 0xD4DF, 0x8D43,
+	0xD4E0, 0x810F, 0xD4E1, 0x846C, 0xD4E2, 0x906D, 0xD4E3, 0x7CDF,
+	0xD4E4, 0x51FF, 0xD4E5, 0x85FB, 0xD4E6, 0x67A3, 0xD4E7, 0x65E9,
+	0xD4E8, 0x6FA1, 0xD4E9, 0x86A4, 0xD4EA, 0x8E81, 0xD4EB, 0x566A,
+	0xD4EC, 0x9020, 0xD4ED, 0x7682, 0xD4EE, 0x7076, 0xD4EF, 0x71E5,
+	0xD4F0, 0x8D23, 0xD4F1, 0x62E9, 0xD4F2, 0x5219, 0xD4F3, 0x6CFD,
+	0xD4F4, 0x8D3C, 0xD4F5, 0x600E, 0xD4F6, 0x589E, 0xD4F7, 0x618E,
+	0xD4F8, 0x66FE, 0xD4F9, 0x8D60, 0xD4FA, 0x624E, 0xD4FB, 0x55B3,
+	0xD4FC, 0x6E23, 0xD4FD, 0x672D, 0xD4FE, 0x8F67, 0xD540, 0x8A81,
+	0xD541, 0x8A82, 0xD542, 0x8A83, 0xD543, 0x8A84, 0xD544, 0x8A85,
+	0xD545, 0x8A86, 0xD546, 0x8A87, 0xD547, 0x8A88, 0xD548, 0x8A8B,
+	0xD549, 0x8A8C, 0xD54A, 0x8A8D, 0xD54B, 0x8A8E, 0xD54C, 0x8A8F,
+	0xD54D, 0x8A90, 0xD54E, 0x8A91, 0xD54F, 0x8A92, 0xD550, 0x8A94,
+	0xD551, 0x8A95, 0xD552, 0x8A96, 0xD553, 0x8A97, 0xD554, 0x8A98,
+	0xD555, 0x8A99, 0xD556, 0x8A9A, 0xD557, 0x8A9B, 0xD558, 0x8A9C,
+	0xD559, 0x8A9D, 0xD55A, 0x8A9E, 0xD55B, 0x8A9F, 0xD55C, 0x8AA0,
+	0xD55D, 0x8AA1, 0xD55E, 0x8AA2, 0xD55F, 0x8AA3, 0xD560, 0x8AA4,
+	0xD561, 0x8AA5, 0xD562, 0x8AA6, 0xD563, 0x8AA7, 0xD564, 0x8AA8,
+	0xD565, 0x8AA9, 0xD566, 0x8AAA, 0xD567, 0x8AAB, 0xD568, 0x8AAC,
+	0xD569, 0x8AAD, 0xD56A, 0x8AAE, 0xD56B, 0x8AAF, 0xD56C, 0x8AB0,
+	0xD56D, 0x8AB1, 0xD56E, 0x8AB2, 0xD56F, 0x8AB3, 0xD570, 0x8AB4,
+	0xD571, 0x8AB5, 0xD572, 0x8AB6, 0xD573, 0x8AB7, 0xD574, 0x8AB8,
+	0xD575, 0x8AB9, 0xD576, 0x8ABA, 0xD577, 0x8ABB, 0xD578, 0x8ABC,
+	0xD579, 0x8ABD, 0xD57A, 0x8ABE, 0xD57B, 0x8ABF, 0xD57C, 0x8AC0,
+	0xD57D, 0x8AC1, 0xD57E, 0x8AC2, 0xD580, 0x8AC3, 0xD581, 0x8AC4,
+	0xD582, 0x8AC5, 0xD583, 0x8AC6, 0xD584, 0x8AC7, 0xD585, 0x8AC8,
+	0xD586, 0x8AC9, 0xD587, 0x8ACA, 0xD588, 0x8ACB, 0xD589, 0x8ACC,
+	0xD58A, 0x8ACD, 0xD58B, 0x8ACE, 0xD58C, 0x8ACF, 0xD58D, 0x8AD0,
+	0xD58E, 0x8AD1, 0xD58F, 0x8AD2, 0xD590, 0x8AD3, 0xD591, 0x8AD4,
+	0xD592, 0x8AD5, 0xD593, 0x8AD6, 0xD594, 0x8AD7, 0xD595, 0x8AD8,
+	0xD596, 0x8AD9, 0xD597, 0x8ADA, 0xD598, 0x8ADB, 0xD599, 0x8ADC,
+	0xD59A, 0x8ADD, 0xD59B, 0x8ADE, 0xD59C, 0x8ADF, 0xD59D, 0x8AE0,
+	0xD59E, 0x8AE1, 0xD59F, 0x8AE2, 0xD5A0, 0x8AE3, 0xD5A1, 0x94E1,
+	0xD5A2, 0x95F8, 0xD5A3, 0x7728, 0xD5A4, 0x6805, 0xD5A5, 0x69A8,
+	0xD5A6, 0x548B, 0xD5A7, 0x4E4D, 0xD5A8, 0x70B8, 0xD5A9, 0x8BC8,
+	0xD5AA, 0x6458, 0xD5AB, 0x658B, 0xD5AC, 0x5B85, 0xD5AD, 0x7A84,
+	0xD5AE, 0x503A, 0xD5AF, 0x5BE8, 0xD5B0, 0x77BB, 0xD5B1, 0x6BE1,
+	0xD5B2, 0x8A79, 0xD5B3, 0x7C98, 0xD5B4, 0x6CBE, 0xD5B5, 0x76CF,
+	0xD5B6, 0x65A9, 0xD5B7, 0x8F97, 0xD5B8, 0x5D2D, 0xD5B9, 0x5C55,
+	0xD5BA, 0x8638, 0xD5BB, 0x6808, 0xD5BC, 0x5360, 0xD5BD, 0x6218,
+	0xD5BE, 0x7AD9, 0xD5BF, 0x6E5B, 0xD5C0, 0x7EFD, 0xD5C1, 0x6A1F,
+	0xD5C2, 0x7AE0, 0xD5C3, 0x5F70, 0xD5C4, 0x6F33, 0xD5C5, 0x5F20,
+	0xD5C6, 0x638C, 0xD5C7, 0x6DA8, 0xD5C8, 0x6756, 0xD5C9, 0x4E08,
+	0xD5CA, 0x5E10, 0xD5CB, 0x8D26, 0xD5CC, 0x4ED7, 0xD5CD, 0x80C0,
+	0xD5CE, 0x7634, 0xD5CF, 0x969C, 0xD5D0, 0x62DB, 0xD5D1, 0x662D,
+	0xD5D2, 0x627E, 0xD5D3, 0x6CBC, 0xD5D4, 0x8D75, 0xD5D5, 0x7167,
+	0xD5D6, 0x7F69, 0xD5D7, 0x5146, 0xD5D8, 0x8087, 0xD5D9, 0x53EC,
+	0xD5DA, 0x906E, 0xD5DB, 0x6298, 0xD5DC, 0x54F2, 0xD5DD, 0x86F0,
+	0xD5DE, 0x8F99, 0xD5DF, 0x8005, 0xD5E0, 0x9517, 0xD5E1, 0x8517,
+	0xD5E2, 0x8FD9, 0xD5E3, 0x6D59, 0xD5E4, 0x73CD, 0xD5E5, 0x659F,
+	0xD5E6, 0x771F, 0xD5E7, 0x7504, 0xD5E8, 0x7827, 0xD5E9, 0x81FB,
+	0xD5EA, 0x8D1E, 0xD5EB, 0x9488, 0xD5EC, 0x4FA6, 0xD5ED, 0x6795,
+	0xD5EE, 0x75B9, 0xD5EF, 0x8BCA, 0xD5F0, 0x9707, 0xD5F1, 0x632F,
+	0xD5F2, 0x9547, 0xD5F3, 0x9635, 0xD5F4, 0x84B8, 0xD5F5, 0x6323,
+	0xD5F6, 0x7741, 0xD5F7, 0x5F81, 0xD5F8, 0x72F0, 0xD5F9, 0x4E89,
+	0xD5FA, 0x6014, 0xD5FB, 0x6574, 0xD5FC, 0x62EF, 0xD5FD, 0x6B63,
+	0xD5FE, 0x653F, 0xD640, 0x8AE4, 0xD641, 0x8AE5, 0xD642, 0x8AE6,
+	0xD643, 0x8AE7, 0xD644, 0x8AE8, 0xD645, 0x8AE9, 0xD646, 0x8AEA,
+	0xD647, 0x8AEB, 0xD648, 0x8AEC, 0xD649, 0x8AED, 0xD64A, 0x8AEE,
+	0xD64B, 0x8AEF, 0xD64C, 0x8AF0, 0xD64D, 0x8AF1, 0xD64E, 0x8AF2,
+	0xD64F, 0x8AF3, 0xD650, 0x8AF4, 0xD651, 0x8AF5, 0xD652, 0x8AF6,
+	0xD653, 0x8AF7, 0xD654, 0x8AF8, 0xD655, 0x8AF9, 0xD656, 0x8AFA,
+	0xD657, 0x8AFB, 0xD658, 0x8AFC, 0xD659, 0x8AFD, 0xD65A, 0x8AFE,
+	0xD65B, 0x8AFF, 0xD65C, 0x8B00, 0xD65D, 0x8B01, 0xD65E, 0x8B02,
+	0xD65F, 0x8B03, 0xD660, 0x8B04, 0xD661, 0x8B05, 0xD662, 0x8B06,
+	0xD663, 0x8B08, 0xD664, 0x8B09, 0xD665, 0x8B0A, 0xD666, 0x8B0B,
+	0xD667, 0x8B0C, 0xD668, 0x8B0D, 0xD669, 0x8B0E, 0xD66A, 0x8B0F,
+	0xD66B, 0x8B10, 0xD66C, 0x8B11, 0xD66D, 0x8B12, 0xD66E, 0x8B13,
+	0xD66F, 0x8B14, 0xD670, 0x8B15, 0xD671, 0x8B16, 0xD672, 0x8B17,
+	0xD673, 0x8B18, 0xD674, 0x8B19, 0xD675, 0x8B1A, 0xD676, 0x8B1B,
+	0xD677, 0x8B1C, 0xD678, 0x8B1D, 0xD679, 0x8B1E, 0xD67A, 0x8B1F,
+	0xD67B, 0x8B20, 0xD67C, 0x8B21, 0xD67D, 0x8B22, 0xD67E, 0x8B23,
+	0xD680, 0x8B24, 0xD681, 0x8B25, 0xD682, 0x8B27, 0xD683, 0x8B28,
+	0xD684, 0x8B29, 0xD685, 0x8B2A, 0xD686, 0x8B2B, 0xD687, 0x8B2C,
+	0xD688, 0x8B2D, 0xD689, 0x8B2E, 0xD68A, 0x8B2F, 0xD68B, 0x8B30,
+	0xD68C, 0x8B31, 0xD68D, 0x8B32, 0xD68E, 0x8B33, 0xD68F, 0x8B34,
+	0xD690, 0x8B35, 0xD691, 0x8B36, 0xD692, 0x8B37, 0xD693, 0x8B38,
+	0xD694, 0x8B39, 0xD695, 0x8B3A, 0xD696, 0x8B3B, 0xD697, 0x8B3C,
+	0xD698, 0x8B3D, 0xD699, 0x8B3E, 0xD69A, 0x8B3F, 0xD69B, 0x8B40,
+	0xD69C, 0x8B41, 0xD69D, 0x8B42, 0xD69E, 0x8B43, 0xD69F, 0x8B44,
+	0xD6A0, 0x8B45, 0xD6A1, 0x5E27, 0xD6A2, 0x75C7, 0xD6A3, 0x90D1,
+	0xD6A4, 0x8BC1, 0xD6A5, 0x829D, 0xD6A6, 0x679D, 0xD6A7, 0x652F,
+	0xD6A8, 0x5431, 0xD6A9, 0x8718, 0xD6AA, 0x77E5, 0xD6AB, 0x80A2,
+	0xD6AC, 0x8102, 0xD6AD, 0x6C41, 0xD6AE, 0x4E4B, 0xD6AF, 0x7EC7,
+	0xD6B0, 0x804C, 0xD6B1, 0x76F4, 0xD6B2, 0x690D, 0xD6B3, 0x6B96,
+	0xD6B4, 0x6267, 0xD6B5, 0x503C, 0xD6B6, 0x4F84, 0xD6B7, 0x5740,
+	0xD6B8, 0x6307, 0xD6B9, 0x6B62, 0xD6BA, 0x8DBE, 0xD6BB, 0x53EA,
+	0xD6BC, 0x65E8, 0xD6BD, 0x7EB8, 0xD6BE, 0x5FD7, 0xD6BF, 0x631A,
+	0xD6C0, 0x63B7, 0xD6C1, 0x81F3, 0xD6C2, 0x81F4, 0xD6C3, 0x7F6E,
+	0xD6C4, 0x5E1C, 0xD6C5, 0x5CD9, 0xD6C6, 0x5236, 0xD6C7, 0x667A,
+	0xD6C8, 0x79E9, 0xD6C9, 0x7A1A, 0xD6CA, 0x8D28, 0xD6CB, 0x7099,
+	0xD6CC, 0x75D4, 0xD6CD, 0x6EDE, 0xD6CE, 0x6CBB, 0xD6CF, 0x7A92,
+	0xD6D0, 0x4E2D, 0xD6D1, 0x76C5, 0xD6D2, 0x5FE0, 0xD6D3, 0x949F,
+	0xD6D4, 0x8877, 0xD6D5, 0x7EC8, 0xD6D6, 0x79CD, 0xD6D7, 0x80BF,
+	0xD6D8, 0x91CD, 0xD6D9, 0x4EF2, 0xD6DA, 0x4F17, 0xD6DB, 0x821F,
+	0xD6DC, 0x5468, 0xD6DD, 0x5DDE, 0xD6DE, 0x6D32, 0xD6DF, 0x8BCC,
+	0xD6E0, 0x7CA5, 0xD6E1, 0x8F74, 0xD6E2, 0x8098, 0xD6E3, 0x5E1A,
+	0xD6E4, 0x5492, 0xD6E5, 0x76B1, 0xD6E6, 0x5B99, 0xD6E7, 0x663C,
+	0xD6E8, 0x9AA4, 0xD6E9, 0x73E0, 0xD6EA, 0x682A, 0xD6EB, 0x86DB,
+	0xD6EC, 0x6731, 0xD6ED, 0x732A, 0xD6EE, 0x8BF8, 0xD6EF, 0x8BDB,
+	0xD6F0, 0x9010, 0xD6F1, 0x7AF9, 0xD6F2, 0x70DB, 0xD6F3, 0x716E,
+	0xD6F4, 0x62C4, 0xD6F5, 0x77A9, 0xD6F6, 0x5631, 0xD6F7, 0x4E3B,
+	0xD6F8, 0x8457, 0xD6F9, 0x67F1, 0xD6FA, 0x52A9, 0xD6FB, 0x86C0,
+	0xD6FC, 0x8D2E, 0xD6FD, 0x94F8, 0xD6FE, 0x7B51, 0xD740, 0x8B46,
+	0xD741, 0x8B47, 0xD742, 0x8B48, 0xD743, 0x8B49, 0xD744, 0x8B4A,
+	0xD745, 0x8B4B, 0xD746, 0x8B4C, 0xD747, 0x8B4D, 0xD748, 0x8B4E,
+	0xD749, 0x8B4F, 0xD74A, 0x8B50, 0xD74B, 0x8B51, 0xD74C, 0x8B52,
+	0xD74D, 0x8B53, 0xD74E, 0x8B54, 0xD74F, 0x8B55, 0xD750, 0x8B56,
+	0xD751, 0x8B57, 0xD752, 0x8B58, 0xD753, 0x8B59, 0xD754, 0x8B5A,
+	0xD755, 0x8B5B, 0xD756, 0x8B5C, 0xD757, 0x8B5D, 0xD758, 0x8B5E,
+	0xD759, 0x8B5F, 0xD75A, 0x8B60, 0xD75B, 0x8B61, 0xD75C, 0x8B62,
+	0xD75D, 0x8B63, 0xD75E, 0x8B64, 0xD75F, 0x8B65, 0xD760, 0x8B67,
+	0xD761, 0x8B68, 0xD762, 0x8B69, 0xD763, 0x8B6A, 0xD764, 0x8B6B,
+	0xD765, 0x8B6D, 0xD766, 0x8B6E, 0xD767, 0x8B6F, 0xD768, 0x8B70,
+	0xD769, 0x8B71, 0xD76A, 0x8B72, 0xD76B, 0x8B73, 0xD76C, 0x8B74,
+	0xD76D, 0x8B75, 0xD76E, 0x8B76, 0xD76F, 0x8B77, 0xD770, 0x8B78,
+	0xD771, 0x8B79, 0xD772, 0x8B7A, 0xD773, 0x8B7B, 0xD774, 0x8B7C,
+	0xD775, 0x8B7D, 0xD776, 0x8B7E, 0xD777, 0x8B7F, 0xD778, 0x8B80,
+	0xD779, 0x8B81, 0xD77A, 0x8B82, 0xD77B, 0x8B83, 0xD77C, 0x8B84,
+	0xD77D, 0x8B85, 0xD77E, 0x8B86, 0xD780, 0x8B87, 0xD781, 0x8B88,
+	0xD782, 0x8B89, 0xD783, 0x8B8A, 0xD784, 0x8B8B, 0xD785, 0x8B8C,
+	0xD786, 0x8B8D, 0xD787, 0x8B8E, 0xD788, 0x8B8F, 0xD789, 0x8B90,
+	0xD78A, 0x8B91, 0xD78B, 0x8B92, 0xD78C, 0x8B93, 0xD78D, 0x8B94,
+	0xD78E, 0x8B95, 0xD78F, 0x8B96, 0xD790, 0x8B97, 0xD791, 0x8B98,
+	0xD792, 0x8B99, 0xD793, 0x8B9A, 0xD794, 0x8B9B, 0xD795, 0x8B9C,
+	0xD796, 0x8B9D, 0xD797, 0x8B9E, 0xD798, 0x8B9F, 0xD799, 0x8BAC,
+	0xD79A, 0x8BB1, 0xD79B, 0x8BBB, 0xD79C, 0x8BC7, 0xD79D, 0x8BD0,
+	0xD79E, 0x8BEA, 0xD79F, 0x8C09, 0xD7A0, 0x8C1E, 0xD7A1, 0x4F4F,
+	0xD7A2, 0x6CE8, 0xD7A3, 0x795D, 0xD7A4, 0x9A7B, 0xD7A5, 0x6293,
+	0xD7A6, 0x722A, 0xD7A7, 0x62FD, 0xD7A8, 0x4E13, 0xD7A9, 0x7816,
+	0xD7AA, 0x8F6C, 0xD7AB, 0x64B0, 0xD7AC, 0x8D5A, 0xD7AD, 0x7BC6,
+	0xD7AE, 0x6869, 0xD7AF, 0x5E84, 0xD7B0, 0x88C5, 0xD7B1, 0x5986,
+	0xD7B2, 0x649E, 0xD7B3, 0x58EE, 0xD7B4, 0x72B6, 0xD7B5, 0x690E,
+	0xD7B6, 0x9525, 0xD7B7, 0x8FFD, 0xD7B8, 0x8D58, 0xD7B9, 0x5760,
+	0xD7BA, 0x7F00, 0xD7BB, 0x8C06, 0xD7BC, 0x51C6, 0xD7BD, 0x6349,
+	0xD7BE, 0x62D9, 0xD7BF, 0x5353, 0xD7C0, 0x684C, 0xD7C1, 0x7422,
+	0xD7C2, 0x8301, 0xD7C3, 0x914C, 0xD7C4, 0x5544, 0xD7C5, 0x7740,
+	0xD7C6, 0x707C, 0xD7C7, 0x6D4A, 0xD7C8, 0x5179, 0xD7C9, 0x54A8,
+	0xD7CA, 0x8D44, 0xD7CB, 0x59FF, 0xD7CC, 0x6ECB, 0xD7CD, 0x6DC4,
+	0xD7CE, 0x5B5C, 0xD7CF, 0x7D2B, 0xD7D0, 0x4ED4, 0xD7D1, 0x7C7D,
+	0xD7D2, 0x6ED3, 0xD7D3, 0x5B50, 0xD7D4, 0x81EA, 0xD7D5, 0x6E0D,
+	0xD7D6, 0x5B57, 0xD7D7, 0x9B03, 0xD7D8, 0x68D5, 0xD7D9, 0x8E2A,
+	0xD7DA, 0x5B97, 0xD7DB, 0x7EFC, 0xD7DC, 0x603B, 0xD7DD, 0x7EB5,
+	0xD7DE, 0x90B9, 0xD7DF, 0x8D70, 0xD7E0, 0x594F, 0xD7E1, 0x63CD,
+	0xD7E2, 0x79DF, 0xD7E3, 0x8DB3, 0xD7E4, 0x5352, 0xD7E5, 0x65CF,
+	0xD7E6, 0x7956, 0xD7E7, 0x8BC5, 0xD7E8, 0x963B, 0xD7E9, 0x7EC4,
+	0xD7EA, 0x94BB, 0xD7EB, 0x7E82, 0xD7EC, 0x5634, 0xD7ED, 0x9189,
+	0xD7EE, 0x6700, 0xD7EF, 0x7F6A, 0xD7F0, 0x5C0A, 0xD7F1, 0x9075,
+	0xD7F2, 0x6628, 0xD7F3, 0x5DE6, 0xD7F4, 0x4F50, 0xD7F5, 0x67DE,
+	0xD7F6, 0x505A, 0xD7F7, 0x4F5C, 0xD7F8, 0x5750, 0xD7F9, 0x5EA7,
+	0xD840, 0x8C38, 0xD841, 0x8C39, 0xD842, 0x8C3A, 0xD843, 0x8C3B,
+	0xD844, 0x8C3C, 0xD845, 0x8C3D, 0xD846, 0x8C3E, 0xD847, 0x8C3F,
+	0xD848, 0x8C40, 0xD849, 0x8C42, 0xD84A, 0x8C43, 0xD84B, 0x8C44,
+	0xD84C, 0x8C45, 0xD84D, 0x8C48, 0xD84E, 0x8C4A, 0xD84F, 0x8C4B,
+	0xD850, 0x8C4D, 0xD851, 0x8C4E, 0xD852, 0x8C4F, 0xD853, 0x8C50,
+	0xD854, 0x8C51, 0xD855, 0x8C52, 0xD856, 0x8C53, 0xD857, 0x8C54,
+	0xD858, 0x8C56, 0xD859, 0x8C57, 0xD85A, 0x8C58, 0xD85B, 0x8C59,
+	0xD85C, 0x8C5B, 0xD85D, 0x8C5C, 0xD85E, 0x8C5D, 0xD85F, 0x8C5E,
+	0xD860, 0x8C5F, 0xD861, 0x8C60, 0xD862, 0x8C63, 0xD863, 0x8C64,
+	0xD864, 0x8C65, 0xD865, 0x8C66, 0xD866, 0x8C67, 0xD867, 0x8C68,
+	0xD868, 0x8C69, 0xD869, 0x8C6C, 0xD86A, 0x8C6D, 0xD86B, 0x8C6E,
+	0xD86C, 0x8C6F, 0xD86D, 0x8C70, 0xD86E, 0x8C71, 0xD86F, 0x8C72,
+	0xD870, 0x8C74, 0xD871, 0x8C75, 0xD872, 0x8C76, 0xD873, 0x8C77,
+	0xD874, 0x8C7B, 0xD875, 0x8C7C, 0xD876, 0x8C7D, 0xD877, 0x8C7E,
+	0xD878, 0x8C7F, 0xD879, 0x8C80, 0xD87A, 0x8C81, 0xD87B, 0x8C83,
+	0xD87C, 0x8C84, 0xD87D, 0x8C86, 0xD87E, 0x8C87, 0xD880, 0x8C88,
+	0xD881, 0x8C8B, 0xD882, 0x8C8D, 0xD883, 0x8C8E, 0xD884, 0x8C8F,
+	0xD885, 0x8C90, 0xD886, 0x8C91, 0xD887, 0x8C92, 0xD888, 0x8C93,
+	0xD889, 0x8C95, 0xD88A, 0x8C96, 0xD88B, 0x8C97, 0xD88C, 0x8C99,
+	0xD88D, 0x8C9A, 0xD88E, 0x8C9B, 0xD88F, 0x8C9C, 0xD890, 0x8C9D,
+	0xD891, 0x8C9E, 0xD892, 0x8C9F, 0xD893, 0x8CA0, 0xD894, 0x8CA1,
+	0xD895, 0x8CA2, 0xD896, 0x8CA3, 0xD897, 0x8CA4, 0xD898, 0x8CA5,
+	0xD899, 0x8CA6, 0xD89A, 0x8CA7, 0xD89B, 0x8CA8, 0xD89C, 0x8CA9,
+	0xD89D, 0x8CAA, 0xD89E, 0x8CAB, 0xD89F, 0x8CAC, 0xD8A0, 0x8CAD,
+	0xD8A1, 0x4E8D, 0xD8A2, 0x4E0C, 0xD8A3, 0x5140, 0xD8A4, 0x4E10,
+	0xD8A5, 0x5EFF, 0xD8A6, 0x5345, 0xD8A7, 0x4E15, 0xD8A8, 0x4E98,
+	0xD8A9, 0x4E1E, 0xD8AA, 0x9B32, 0xD8AB, 0x5B6C, 0xD8AC, 0x5669,
+	0xD8AD, 0x4E28, 0xD8AE, 0x79BA, 0xD8AF, 0x4E3F, 0xD8B0, 0x5315,
+	0xD8B1, 0x4E47, 0xD8B2, 0x592D, 0xD8B3, 0x723B, 0xD8B4, 0x536E,
+	0xD8B5, 0x6C10, 0xD8B6, 0x56DF, 0xD8B7, 0x80E4, 0xD8B8, 0x9997,
+	0xD8B9, 0x6BD3, 0xD8BA, 0x777E, 0xD8BB, 0x9F17, 0xD8BC, 0x4E36,
+	0xD8BD, 0x4E9F, 0xD8BE, 0x9F10, 0xD8BF, 0x4E5C, 0xD8C0, 0x4E69,
+	0xD8C1, 0x4E93, 0xD8C2, 0x8288, 0xD8C3, 0x5B5B, 0xD8C4, 0x556C,
+	0xD8C5, 0x560F, 0xD8C6, 0x4EC4, 0xD8C7, 0x538D, 0xD8C8, 0x539D,
+	0xD8C9, 0x53A3, 0xD8CA, 0x53A5, 0xD8CB, 0x53AE, 0xD8CC, 0x9765,
+	0xD8CD, 0x8D5D, 0xD8CE, 0x531A, 0xD8CF, 0x53F5, 0xD8D0, 0x5326,
+	0xD8D1, 0x532E, 0xD8D2, 0x533E, 0xD8D3, 0x8D5C, 0xD8D4, 0x5366,
+	0xD8D5, 0x5363, 0xD8D6, 0x5202, 0xD8D7, 0x5208, 0xD8D8, 0x520E,
+	0xD8D9, 0x522D, 0xD8DA, 0x5233, 0xD8DB, 0x523F, 0xD8DC, 0x5240,
+	0xD8DD, 0x524C, 0xD8DE, 0x525E, 0xD8DF, 0x5261, 0xD8E0, 0x525C,
+	0xD8E1, 0x84AF, 0xD8E2, 0x527D, 0xD8E3, 0x5282, 0xD8E4, 0x5281,
+	0xD8E5, 0x5290, 0xD8E6, 0x5293, 0xD8E7, 0x5182, 0xD8E8, 0x7F54,
+	0xD8E9, 0x4EBB, 0xD8EA, 0x4EC3, 0xD8EB, 0x4EC9, 0xD8EC, 0x4EC2,
+	0xD8ED, 0x4EE8, 0xD8EE, 0x4EE1, 0xD8EF, 0x4EEB, 0xD8F0, 0x4EDE,
+	0xD8F1, 0x4F1B, 0xD8F2, 0x4EF3, 0xD8F3, 0x4F22, 0xD8F4, 0x4F64,
+	0xD8F5, 0x4EF5, 0xD8F6, 0x4F25, 0xD8F7, 0x4F27, 0xD8F8, 0x4F09,
+	0xD8F9, 0x4F2B, 0xD8FA, 0x4F5E, 0xD8FB, 0x4F67, 0xD8FC, 0x6538,
+	0xD8FD, 0x4F5A, 0xD8FE, 0x4F5D, 0xD940, 0x8CAE, 0xD941, 0x8CAF,
+	0xD942, 0x8CB0, 0xD943, 0x8CB1, 0xD944, 0x8CB2, 0xD945, 0x8CB3,
+	0xD946, 0x8CB4, 0xD947, 0x8CB5, 0xD948, 0x8CB6, 0xD949, 0x8CB7,
+	0xD94A, 0x8CB8, 0xD94B, 0x8CB9, 0xD94C, 0x8CBA, 0xD94D, 0x8CBB,
+	0xD94E, 0x8CBC, 0xD94F, 0x8CBD, 0xD950, 0x8CBE, 0xD951, 0x8CBF,
+	0xD952, 0x8CC0, 0xD953, 0x8CC1, 0xD954, 0x8CC2, 0xD955, 0x8CC3,
+	0xD956, 0x8CC4, 0xD957, 0x8CC5, 0xD958, 0x8CC6, 0xD959, 0x8CC7,
+	0xD95A, 0x8CC8, 0xD95B, 0x8CC9, 0xD95C, 0x8CCA, 0xD95D, 0x8CCB,
+	0xD95E, 0x8CCC, 0xD95F, 0x8CCD, 0xD960, 0x8CCE, 0xD961, 0x8CCF,
+	0xD962, 0x8CD0, 0xD963, 0x8CD1, 0xD964, 0x8CD2, 0xD965, 0x8CD3,
+	0xD966, 0x8CD4, 0xD967, 0x8CD5, 0xD968, 0x8CD6, 0xD969, 0x8CD7,
+	0xD96A, 0x8CD8, 0xD96B, 0x8CD9, 0xD96C, 0x8CDA, 0xD96D, 0x8CDB,
+	0xD96E, 0x8CDC, 0xD96F, 0x8CDD, 0xD970, 0x8CDE, 0xD971, 0x8CDF,
+	0xD972, 0x8CE0, 0xD973, 0x8CE1, 0xD974, 0x8CE2, 0xD975, 0x8CE3,
+	0xD976, 0x8CE4, 0xD977, 0x8CE5, 0xD978, 0x8CE6, 0xD979, 0x8CE7,
+	0xD97A, 0x8CE8, 0xD97B, 0x8CE9, 0xD97C, 0x8CEA, 0xD97D, 0x8CEB,
+	0xD97E, 0x8CEC, 0xD980, 0x8CED, 0xD981, 0x8CEE, 0xD982, 0x8CEF,
+	0xD983, 0x8CF0, 0xD984, 0x8CF1, 0xD985, 0x8CF2, 0xD986, 0x8CF3,
+	0xD987, 0x8CF4, 0xD988, 0x8CF5, 0xD989, 0x8CF6, 0xD98A, 0x8CF7,
+	0xD98B, 0x8CF8, 0xD98C, 0x8CF9, 0xD98D, 0x8CFA, 0xD98E, 0x8CFB,
+	0xD98F, 0x8CFC, 0xD990, 0x8CFD, 0xD991, 0x8CFE, 0xD992, 0x8CFF,
+	0xD993, 0x8D00, 0xD994, 0x8D01, 0xD995, 0x8D02, 0xD996, 0x8D03,
+	0xD997, 0x8D04, 0xD998, 0x8D05, 0xD999, 0x8D06, 0xD99A, 0x8D07,
+	0xD99B, 0x8D08, 0xD99C, 0x8D09, 0xD99D, 0x8D0A, 0xD99E, 0x8D0B,
+	0xD99F, 0x8D0C, 0xD9A0, 0x8D0D, 0xD9A1, 0x4F5F, 0xD9A2, 0x4F57,
+	0xD9A3, 0x4F32, 0xD9A4, 0x4F3D, 0xD9A5, 0x4F76, 0xD9A6, 0x4F74,
+	0xD9A7, 0x4F91, 0xD9A8, 0x4F89, 0xD9A9, 0x4F83, 0xD9AA, 0x4F8F,
+	0xD9AB, 0x4F7E, 0xD9AC, 0x4F7B, 0xD9AD, 0x4FAA, 0xD9AE, 0x4F7C,
+	0xD9AF, 0x4FAC, 0xD9B0, 0x4F94, 0xD9B1, 0x4FE6, 0xD9B2, 0x4FE8,
+	0xD9B3, 0x4FEA, 0xD9B4, 0x4FC5, 0xD9B5, 0x4FDA, 0xD9B6, 0x4FE3,
+	0xD9B7, 0x4FDC, 0xD9B8, 0x4FD1, 0xD9B9, 0x4FDF, 0xD9BA, 0x4FF8,
+	0xD9BB, 0x5029, 0xD9BC, 0x504C, 0xD9BD, 0x4FF3, 0xD9BE, 0x502C,
+	0xD9BF, 0x500F, 0xD9C0, 0x502E, 0xD9C1, 0x502D, 0xD9C2, 0x4FFE,
+	0xD9C3, 0x501C, 0xD9C4, 0x500C, 0xD9C5, 0x5025, 0xD9C6, 0x5028,
+	0xD9C7, 0x507E, 0xD9C8, 0x5043, 0xD9C9, 0x5055, 0xD9CA, 0x5048,
+	0xD9CB, 0x504E, 0xD9CC, 0x506C, 0xD9CD, 0x507B, 0xD9CE, 0x50A5,
+	0xD9CF, 0x50A7, 0xD9D0, 0x50A9, 0xD9D1, 0x50BA, 0xD9D2, 0x50D6,
+	0xD9D3, 0x5106, 0xD9D4, 0x50ED, 0xD9D5, 0x50EC, 0xD9D6, 0x50E6,
+	0xD9D7, 0x50EE, 0xD9D8, 0x5107, 0xD9D9, 0x510B, 0xD9DA, 0x4EDD,
+	0xD9DB, 0x6C3D, 0xD9DC, 0x4F58, 0xD9DD, 0x4F65, 0xD9DE, 0x4FCE,
+	0xD9DF, 0x9FA0, 0xD9E0, 0x6C46, 0xD9E1, 0x7C74, 0xD9E2, 0x516E,
+	0xD9E3, 0x5DFD, 0xD9E4, 0x9EC9, 0xD9E5, 0x9998, 0xD9E6, 0x5181,
+	0xD9E7, 0x5914, 0xD9E8, 0x52F9, 0xD9E9, 0x530D, 0xD9EA, 0x8A07,
+	0xD9EB, 0x5310, 0xD9EC, 0x51EB, 0xD9ED, 0x5919, 0xD9EE, 0x5155,
+	0xD9EF, 0x4EA0, 0xD9F0, 0x5156, 0xD9F1, 0x4EB3, 0xD9F2, 0x886E,
+	0xD9F3, 0x88A4, 0xD9F4, 0x4EB5, 0xD9F5, 0x8114, 0xD9F6, 0x88D2,
+	0xD9F7, 0x7980, 0xD9F8, 0x5B34, 0xD9F9, 0x8803, 0xD9FA, 0x7FB8,
+	0xD9FB, 0x51AB, 0xD9FC, 0x51B1, 0xD9FD, 0x51BD, 0xD9FE, 0x51BC,
+	0xDA40, 0x8D0E, 0xDA41, 0x8D0F, 0xDA42, 0x8D10, 0xDA43, 0x8D11,
+	0xDA44, 0x8D12, 0xDA45, 0x8D13, 0xDA46, 0x8D14, 0xDA47, 0x8D15,
+	0xDA48, 0x8D16, 0xDA49, 0x8D17, 0xDA4A, 0x8D18, 0xDA4B, 0x8D19,
+	0xDA4C, 0x8D1A, 0xDA4D, 0x8D1B, 0xDA4E, 0x8D1C, 0xDA4F, 0x8D20,
+	0xDA50, 0x8D51, 0xDA51, 0x8D52, 0xDA52, 0x8D57, 0xDA53, 0x8D5F,
+	0xDA54, 0x8D65, 0xDA55, 0x8D68, 0xDA56, 0x8D69, 0xDA57, 0x8D6A,
+	0xDA58, 0x8D6C, 0xDA59, 0x8D6E, 0xDA5A, 0x8D6F, 0xDA5B, 0x8D71,
+	0xDA5C, 0x8D72, 0xDA5D, 0x8D78, 0xDA5E, 0x8D79, 0xDA5F, 0x8D7A,
+	0xDA60, 0x8D7B, 0xDA61, 0x8D7C, 0xDA62, 0x8D7D, 0xDA63, 0x8D7E,
+	0xDA64, 0x8D7F, 0xDA65, 0x8D80, 0xDA66, 0x8D82, 0xDA67, 0x8D83,
+	0xDA68, 0x8D86, 0xDA69, 0x8D87, 0xDA6A, 0x8D88, 0xDA6B, 0x8D89,
+	0xDA6C, 0x8D8C, 0xDA6D, 0x8D8D, 0xDA6E, 0x8D8E, 0xDA6F, 0x8D8F,
+	0xDA70, 0x8D90, 0xDA71, 0x8D92, 0xDA72, 0x8D93, 0xDA73, 0x8D95,
+	0xDA74, 0x8D96, 0xDA75, 0x8D97, 0xDA76, 0x8D98, 0xDA77, 0x8D99,
+	0xDA78, 0x8D9A, 0xDA79, 0x8D9B, 0xDA7A, 0x8D9C, 0xDA7B, 0x8D9D,
+	0xDA7C, 0x8D9E, 0xDA7D, 0x8DA0, 0xDA7E, 0x8DA1, 0xDA80, 0x8DA2,
+	0xDA81, 0x8DA4, 0xDA82, 0x8DA5, 0xDA83, 0x8DA6, 0xDA84, 0x8DA7,
+	0xDA85, 0x8DA8, 0xDA86, 0x8DA9, 0xDA87, 0x8DAA, 0xDA88, 0x8DAB,
+	0xDA89, 0x8DAC, 0xDA8A, 0x8DAD, 0xDA8B, 0x8DAE, 0xDA8C, 0x8DAF,
+	0xDA8D, 0x8DB0, 0xDA8E, 0x8DB2, 0xDA8F, 0x8DB6, 0xDA90, 0x8DB7,
+	0xDA91, 0x8DB9, 0xDA92, 0x8DBB, 0xDA93, 0x8DBD, 0xDA94, 0x8DC0,
+	0xDA95, 0x8DC1, 0xDA96, 0x8DC2, 0xDA97, 0x8DC5, 0xDA98, 0x8DC7,
+	0xDA99, 0x8DC8, 0xDA9A, 0x8DC9, 0xDA9B, 0x8DCA, 0xDA9C, 0x8DCD,
+	0xDA9D, 0x8DD0, 0xDA9E, 0x8DD2, 0xDA9F, 0x8DD3, 0xDAA0, 0x8DD4,
+	0xDAA1, 0x51C7, 0xDAA2, 0x5196, 0xDAA3, 0x51A2, 0xDAA4, 0x51A5,
+	0xDAA5, 0x8BA0, 0xDAA6, 0x8BA6, 0xDAA7, 0x8BA7, 0xDAA8, 0x8BAA,
+	0xDAA9, 0x8BB4, 0xDAAA, 0x8BB5, 0xDAAB, 0x8BB7, 0xDAAC, 0x8BC2,
+	0xDAAD, 0x8BC3, 0xDAAE, 0x8BCB, 0xDAAF, 0x8BCF, 0xDAB0, 0x8BCE,
+	0xDAB1, 0x8BD2, 0xDAB2, 0x8BD3, 0xDAB3, 0x8BD4, 0xDAB4, 0x8BD6,
+	0xDAB5, 0x8BD8, 0xDAB6, 0x8BD9, 0xDAB7, 0x8BDC, 0xDAB8, 0x8BDF,
+	0xDAB9, 0x8BE0, 0xDABA, 0x8BE4, 0xDABB, 0x8BE8, 0xDABC, 0x8BE9,
+	0xDABD, 0x8BEE, 0xDABE, 0x8BF0, 0xDABF, 0x8BF3, 0xDAC0, 0x8BF6,
+	0xDAC1, 0x8BF9, 0xDAC2, 0x8BFC, 0xDAC3, 0x8BFF, 0xDAC4, 0x8C00,
+	0xDAC5, 0x8C02, 0xDAC6, 0x8C04, 0xDAC7, 0x8C07, 0xDAC8, 0x8C0C,
+	0xDAC9, 0x8C0F, 0xDACA, 0x8C11, 0xDACB, 0x8C12, 0xDACC, 0x8C14,
+	0xDACD, 0x8C15, 0xDACE, 0x8C16, 0xDACF, 0x8C19, 0xDAD0, 0x8C1B,
+	0xDAD1, 0x8C18, 0xDAD2, 0x8C1D, 0xDAD3, 0x8C1F, 0xDAD4, 0x8C20,
+	0xDAD5, 0x8C21, 0xDAD6, 0x8C25, 0xDAD7, 0x8C27, 0xDAD8, 0x8C2A,
+	0xDAD9, 0x8C2B, 0xDADA, 0x8C2E, 0xDADB, 0x8C2F, 0xDADC, 0x8C32,
+	0xDADD, 0x8C33, 0xDADE, 0x8C35, 0xDADF, 0x8C36, 0xDAE0, 0x5369,
+	0xDAE1, 0x537A, 0xDAE2, 0x961D, 0xDAE3, 0x9622, 0xDAE4, 0x9621,
+	0xDAE5, 0x9631, 0xDAE6, 0x962A, 0xDAE7, 0x963D, 0xDAE8, 0x963C,
+	0xDAE9, 0x9642, 0xDAEA, 0x9649, 0xDAEB, 0x9654, 0xDAEC, 0x965F,
+	0xDAED, 0x9667, 0xDAEE, 0x966C, 0xDAEF, 0x9672, 0xDAF0, 0x9674,
+	0xDAF1, 0x9688, 0xDAF2, 0x968D, 0xDAF3, 0x9697, 0xDAF4, 0x96B0,
+	0xDAF5, 0x9097, 0xDAF6, 0x909B, 0xDAF7, 0x909D, 0xDAF8, 0x9099,
+	0xDAF9, 0x90AC, 0xDAFA, 0x90A1, 0xDAFB, 0x90B4, 0xDAFC, 0x90B3,
+	0xDAFD, 0x90B6, 0xDAFE, 0x90BA, 0xDB40, 0x8DD5, 0xDB41, 0x8DD8,
+	0xDB42, 0x8DD9, 0xDB43, 0x8DDC, 0xDB44, 0x8DE0, 0xDB45, 0x8DE1,
+	0xDB46, 0x8DE2, 0xDB47, 0x8DE5, 0xDB48, 0x8DE6, 0xDB49, 0x8DE7,
+	0xDB4A, 0x8DE9, 0xDB4B, 0x8DED, 0xDB4C, 0x8DEE, 0xDB4D, 0x8DF0,
+	0xDB4E, 0x8DF1, 0xDB4F, 0x8DF2, 0xDB50, 0x8DF4, 0xDB51, 0x8DF6,
+	0xDB52, 0x8DFC, 0xDB53, 0x8DFE, 0xDB54, 0x8DFF, 0xDB55, 0x8E00,
+	0xDB56, 0x8E01, 0xDB57, 0x8E02, 0xDB58, 0x8E03, 0xDB59, 0x8E04,
+	0xDB5A, 0x8E06, 0xDB5B, 0x8E07, 0xDB5C, 0x8E08, 0xDB5D, 0x8E0B,
+	0xDB5E, 0x8E0D, 0xDB5F, 0x8E0E, 0xDB60, 0x8E10, 0xDB61, 0x8E11,
+	0xDB62, 0x8E12, 0xDB63, 0x8E13, 0xDB64, 0x8E15, 0xDB65, 0x8E16,
+	0xDB66, 0x8E17, 0xDB67, 0x8E18, 0xDB68, 0x8E19, 0xDB69, 0x8E1A,
+	0xDB6A, 0x8E1B, 0xDB6B, 0x8E1C, 0xDB6C, 0x8E20, 0xDB6D, 0x8E21,
+	0xDB6E, 0x8E24, 0xDB6F, 0x8E25, 0xDB70, 0x8E26, 0xDB71, 0x8E27,
+	0xDB72, 0x8E28, 0xDB73, 0x8E2B, 0xDB74, 0x8E2D, 0xDB75, 0x8E30,
+	0xDB76, 0x8E32, 0xDB77, 0x8E33, 0xDB78, 0x8E34, 0xDB79, 0x8E36,
+	0xDB7A, 0x8E37, 0xDB7B, 0x8E38, 0xDB7C, 0x8E3B, 0xDB7D, 0x8E3C,
+	0xDB7E, 0x8E3E, 0xDB80, 0x8E3F, 0xDB81, 0x8E43, 0xDB82, 0x8E45,
+	0xDB83, 0x8E46, 0xDB84, 0x8E4C, 0xDB85, 0x8E4D, 0xDB86, 0x8E4E,
+	0xDB87, 0x8E4F, 0xDB88, 0x8E50, 0xDB89, 0x8E53, 0xDB8A, 0x8E54,
+	0xDB8B, 0x8E55, 0xDB8C, 0x8E56, 0xDB8D, 0x8E57, 0xDB8E, 0x8E58,
+	0xDB8F, 0x8E5A, 0xDB90, 0x8E5B, 0xDB91, 0x8E5C, 0xDB92, 0x8E5D,
+	0xDB93, 0x8E5E, 0xDB94, 0x8E5F, 0xDB95, 0x8E60, 0xDB96, 0x8E61,
+	0xDB97, 0x8E62, 0xDB98, 0x8E63, 0xDB99, 0x8E64, 0xDB9A, 0x8E65,
+	0xDB9B, 0x8E67, 0xDB9C, 0x8E68, 0xDB9D, 0x8E6A, 0xDB9E, 0x8E6B,
+	0xDB9F, 0x8E6E, 0xDBA0, 0x8E71, 0xDBA1, 0x90B8, 0xDBA2, 0x90B0,
+	0xDBA3, 0x90CF, 0xDBA4, 0x90C5, 0xDBA5, 0x90BE, 0xDBA6, 0x90D0,
+	0xDBA7, 0x90C4, 0xDBA8, 0x90C7, 0xDBA9, 0x90D3, 0xDBAA, 0x90E6,
+	0xDBAB, 0x90E2, 0xDBAC, 0x90DC, 0xDBAD, 0x90D7, 0xDBAE, 0x90DB,
+	0xDBAF, 0x90EB, 0xDBB0, 0x90EF, 0xDBB1, 0x90FE, 0xDBB2, 0x9104,
+	0xDBB3, 0x9122, 0xDBB4, 0x911E, 0xDBB5, 0x9123, 0xDBB6, 0x9131,
+	0xDBB7, 0x912F, 0xDBB8, 0x9139, 0xDBB9, 0x9143, 0xDBBA, 0x9146,
+	0xDBBB, 0x520D, 0xDBBC, 0x5942, 0xDBBD, 0x52A2, 0xDBBE, 0x52AC,
+	0xDBBF, 0x52AD, 0xDBC0, 0x52BE, 0xDBC1, 0x54FF, 0xDBC2, 0x52D0,
+	0xDBC3, 0x52D6, 0xDBC4, 0x52F0, 0xDBC5, 0x53DF, 0xDBC6, 0x71EE,
+	0xDBC7, 0x77CD, 0xDBC8, 0x5EF4, 0xDBC9, 0x51F5, 0xDBCA, 0x51FC,
+	0xDBCB, 0x9B2F, 0xDBCC, 0x53B6, 0xDBCD, 0x5F01, 0xDBCE, 0x755A,
+	0xDBCF, 0x5DEF, 0xDBD0, 0x574C, 0xDBD1, 0x57A9, 0xDBD2, 0x57A1,
+	0xDBD3, 0x587E, 0xDBD4, 0x58BC, 0xDBD5, 0x58C5, 0xDBD6, 0x58D1,
+	0xDBD7, 0x5729, 0xDBD8, 0x572C, 0xDBD9, 0x572A, 0xDBDA, 0x5733,
+	0xDBDB, 0x5739, 0xDBDC, 0x572E, 0xDBDD, 0x572F, 0xDBDE, 0x575C,
+	0xDBDF, 0x573B, 0xDBE0, 0x5742, 0xDBE1, 0x5769, 0xDBE2, 0x5785,
+	0xDBE3, 0x576B, 0xDBE4, 0x5786, 0xDBE5, 0x577C, 0xDBE6, 0x577B,
+	0xDBE7, 0x5768, 0xDBE8, 0x576D, 0xDBE9, 0x5776, 0xDBEA, 0x5773,
+	0xDBEB, 0x57AD, 0xDBEC, 0x57A4, 0xDBED, 0x578C, 0xDBEE, 0x57B2,
+	0xDBEF, 0x57CF, 0xDBF0, 0x57A7, 0xDBF1, 0x57B4, 0xDBF2, 0x5793,
+	0xDBF3, 0x57A0, 0xDBF4, 0x57D5, 0xDBF5, 0x57D8, 0xDBF6, 0x57DA,
+	0xDBF7, 0x57D9, 0xDBF8, 0x57D2, 0xDBF9, 0x57B8, 0xDBFA, 0x57F4,
+	0xDBFB, 0x57EF, 0xDBFC, 0x57F8, 0xDBFD, 0x57E4, 0xDBFE, 0x57DD,
+	0xDC40, 0x8E73, 0xDC41, 0x8E75, 0xDC42, 0x8E77, 0xDC43, 0x8E78,
+	0xDC44, 0x8E79, 0xDC45, 0x8E7A, 0xDC46, 0x8E7B, 0xDC47, 0x8E7D,
+	0xDC48, 0x8E7E, 0xDC49, 0x8E80, 0xDC4A, 0x8E82, 0xDC4B, 0x8E83,
+	0xDC4C, 0x8E84, 0xDC4D, 0x8E86, 0xDC4E, 0x8E88, 0xDC4F, 0x8E89,
+	0xDC50, 0x8E8A, 0xDC51, 0x8E8B, 0xDC52, 0x8E8C, 0xDC53, 0x8E8D,
+	0xDC54, 0x8E8E, 0xDC55, 0x8E91, 0xDC56, 0x8E92, 0xDC57, 0x8E93,
+	0xDC58, 0x8E95, 0xDC59, 0x8E96, 0xDC5A, 0x8E97, 0xDC5B, 0x8E98,
+	0xDC5C, 0x8E99, 0xDC5D, 0x8E9A, 0xDC5E, 0x8E9B, 0xDC5F, 0x8E9D,
+	0xDC60, 0x8E9F, 0xDC61, 0x8EA0, 0xDC62, 0x8EA1, 0xDC63, 0x8EA2,
+	0xDC64, 0x8EA3, 0xDC65, 0x8EA4, 0xDC66, 0x8EA5, 0xDC67, 0x8EA6,
+	0xDC68, 0x8EA7, 0xDC69, 0x8EA8, 0xDC6A, 0x8EA9, 0xDC6B, 0x8EAA,
+	0xDC6C, 0x8EAD, 0xDC6D, 0x8EAE, 0xDC6E, 0x8EB0, 0xDC6F, 0x8EB1,
+	0xDC70, 0x8EB3, 0xDC71, 0x8EB4, 0xDC72, 0x8EB5, 0xDC73, 0x8EB6,
+	0xDC74, 0x8EB7, 0xDC75, 0x8EB8, 0xDC76, 0x8EB9, 0xDC77, 0x8EBB,
+	0xDC78, 0x8EBC, 0xDC79, 0x8EBD, 0xDC7A, 0x8EBE, 0xDC7B, 0x8EBF,
+	0xDC7C, 0x8EC0, 0xDC7D, 0x8EC1, 0xDC7E, 0x8EC2, 0xDC80, 0x8EC3,
+	0xDC81, 0x8EC4, 0xDC82, 0x8EC5, 0xDC83, 0x8EC6, 0xDC84, 0x8EC7,
+	0xDC85, 0x8EC8, 0xDC86, 0x8EC9, 0xDC87, 0x8ECA, 0xDC88, 0x8ECB,
+	0xDC89, 0x8ECC, 0xDC8A, 0x8ECD, 0xDC8B, 0x8ECF, 0xDC8C, 0x8ED0,
+	0xDC8D, 0x8ED1, 0xDC8E, 0x8ED2, 0xDC8F, 0x8ED3, 0xDC90, 0x8ED4,
+	0xDC91, 0x8ED5, 0xDC92, 0x8ED6, 0xDC93, 0x8ED7, 0xDC94, 0x8ED8,
+	0xDC95, 0x8ED9, 0xDC96, 0x8EDA, 0xDC97, 0x8EDB, 0xDC98, 0x8EDC,
+	0xDC99, 0x8EDD, 0xDC9A, 0x8EDE, 0xDC9B, 0x8EDF, 0xDC9C, 0x8EE0,
+	0xDC9D, 0x8EE1, 0xDC9E, 0x8EE2, 0xDC9F, 0x8EE3, 0xDCA0, 0x8EE4,
+	0xDCA1, 0x580B, 0xDCA2, 0x580D, 0xDCA3, 0x57FD, 0xDCA4, 0x57ED,
+	0xDCA5, 0x5800, 0xDCA6, 0x581E, 0xDCA7, 0x5819, 0xDCA8, 0x5844,
+	0xDCA9, 0x5820, 0xDCAA, 0x5865, 0xDCAB, 0x586C, 0xDCAC, 0x5881,
+	0xDCAD, 0x5889, 0xDCAE, 0x589A, 0xDCAF, 0x5880, 0xDCB0, 0x99A8,
+	0xDCB1, 0x9F19, 0xDCB2, 0x61FF, 0xDCB3, 0x8279, 0xDCB4, 0x827D,
+	0xDCB5, 0x827F, 0xDCB6, 0x828F, 0xDCB7, 0x828A, 0xDCB8, 0x82A8,
+	0xDCB9, 0x8284, 0xDCBA, 0x828E, 0xDCBB, 0x8291, 0xDCBC, 0x8297,
+	0xDCBD, 0x8299, 0xDCBE, 0x82AB, 0xDCBF, 0x82B8, 0xDCC0, 0x82BE,
+	0xDCC1, 0x82B0, 0xDCC2, 0x82C8, 0xDCC3, 0x82CA, 0xDCC4, 0x82E3,
+	0xDCC5, 0x8298, 0xDCC6, 0x82B7, 0xDCC7, 0x82AE, 0xDCC8, 0x82CB,
+	0xDCC9, 0x82CC, 0xDCCA, 0x82C1, 0xDCCB, 0x82A9, 0xDCCC, 0x82B4,
+	0xDCCD, 0x82A1, 0xDCCE, 0x82AA, 0xDCCF, 0x829F, 0xDCD0, 0x82C4,
+	0xDCD1, 0x82CE, 0xDCD2, 0x82A4, 0xDCD3, 0x82E1, 0xDCD4, 0x8309,
+	0xDCD5, 0x82F7, 0xDCD6, 0x82E4, 0xDCD7, 0x830F, 0xDCD8, 0x8307,
+	0xDCD9, 0x82DC, 0xDCDA, 0x82F4, 0xDCDB, 0x82D2, 0xDCDC, 0x82D8,
+	0xDCDD, 0x830C, 0xDCDE, 0x82FB, 0xDCDF, 0x82D3, 0xDCE0, 0x8311,
+	0xDCE1, 0x831A, 0xDCE2, 0x8306, 0xDCE3, 0x8314, 0xDCE4, 0x8315,
+	0xDCE5, 0x82E0, 0xDCE6, 0x82D5, 0xDCE7, 0x831C, 0xDCE8, 0x8351,
+	0xDCE9, 0x835B, 0xDCEA, 0x835C, 0xDCEB, 0x8308, 0xDCEC, 0x8392,
+	0xDCED, 0x833C, 0xDCEE, 0x8334, 0xDCEF, 0x8331, 0xDCF0, 0x839B,
+	0xDCF1, 0x835E, 0xDCF2, 0x832F, 0xDCF3, 0x834F, 0xDCF4, 0x8347,
+	0xDCF5, 0x8343, 0xDCF6, 0x835F, 0xDCF7, 0x8340, 0xDCF8, 0x8317,
+	0xDCF9, 0x8360, 0xDCFA, 0x832D, 0xDCFB, 0x833A, 0xDCFC, 0x8333,
+	0xDCFD, 0x8366, 0xDCFE, 0x8365, 0xDD40, 0x8EE5, 0xDD41, 0x8EE6,
+	0xDD42, 0x8EE7, 0xDD43, 0x8EE8, 0xDD44, 0x8EE9, 0xDD45, 0x8EEA,
+	0xDD46, 0x8EEB, 0xDD47, 0x8EEC, 0xDD48, 0x8EED, 0xDD49, 0x8EEE,
+	0xDD4A, 0x8EEF, 0xDD4B, 0x8EF0, 0xDD4C, 0x8EF1, 0xDD4D, 0x8EF2,
+	0xDD4E, 0x8EF3, 0xDD4F, 0x8EF4, 0xDD50, 0x8EF5, 0xDD51, 0x8EF6,
+	0xDD52, 0x8EF7, 0xDD53, 0x8EF8, 0xDD54, 0x8EF9, 0xDD55, 0x8EFA,
+	0xDD56, 0x8EFB, 0xDD57, 0x8EFC, 0xDD58, 0x8EFD, 0xDD59, 0x8EFE,
+	0xDD5A, 0x8EFF, 0xDD5B, 0x8F00, 0xDD5C, 0x8F01, 0xDD5D, 0x8F02,
+	0xDD5E, 0x8F03, 0xDD5F, 0x8F04, 0xDD60, 0x8F05, 0xDD61, 0x8F06,
+	0xDD62, 0x8F07, 0xDD63, 0x8F08, 0xDD64, 0x8F09, 0xDD65, 0x8F0A,
+	0xDD66, 0x8F0B, 0xDD67, 0x8F0C, 0xDD68, 0x8F0D, 0xDD69, 0x8F0E,
+	0xDD6A, 0x8F0F, 0xDD6B, 0x8F10, 0xDD6C, 0x8F11, 0xDD6D, 0x8F12,
+	0xDD6E, 0x8F13, 0xDD6F, 0x8F14, 0xDD70, 0x8F15, 0xDD71, 0x8F16,
+	0xDD72, 0x8F17, 0xDD73, 0x8F18, 0xDD74, 0x8F19, 0xDD75, 0x8F1A,
+	0xDD76, 0x8F1B, 0xDD77, 0x8F1C, 0xDD78, 0x8F1D, 0xDD79, 0x8F1E,
+	0xDD7A, 0x8F1F, 0xDD7B, 0x8F20, 0xDD7C, 0x8F21, 0xDD7D, 0x8F22,
+	0xDD7E, 0x8F23, 0xDD80, 0x8F24, 0xDD81, 0x8F25, 0xDD82, 0x8F26,
+	0xDD83, 0x8F27, 0xDD84, 0x8F28, 0xDD85, 0x8F29, 0xDD86, 0x8F2A,
+	0xDD87, 0x8F2B, 0xDD88, 0x8F2C, 0xDD89, 0x8F2D, 0xDD8A, 0x8F2E,
+	0xDD8B, 0x8F2F, 0xDD8C, 0x8F30, 0xDD8D, 0x8F31, 0xDD8E, 0x8F32,
+	0xDD8F, 0x8F33, 0xDD90, 0x8F34, 0xDD91, 0x8F35, 0xDD92, 0x8F36,
+	0xDD93, 0x8F37, 0xDD94, 0x8F38, 0xDD95, 0x8F39, 0xDD96, 0x8F3A,
+	0xDD97, 0x8F3B, 0xDD98, 0x8F3C, 0xDD99, 0x8F3D, 0xDD9A, 0x8F3E,
+	0xDD9B, 0x8F3F, 0xDD9C, 0x8F40, 0xDD9D, 0x8F41, 0xDD9E, 0x8F42,
+	0xDD9F, 0x8F43, 0xDDA0, 0x8F44, 0xDDA1, 0x8368, 0xDDA2, 0x831B,
+	0xDDA3, 0x8369, 0xDDA4, 0x836C, 0xDDA5, 0x836A, 0xDDA6, 0x836D,
+	0xDDA7, 0x836E, 0xDDA8, 0x83B0, 0xDDA9, 0x8378, 0xDDAA, 0x83B3,
+	0xDDAB, 0x83B4, 0xDDAC, 0x83A0, 0xDDAD, 0x83AA, 0xDDAE, 0x8393,
+	0xDDAF, 0x839C, 0xDDB0, 0x8385, 0xDDB1, 0x837C, 0xDDB2, 0x83B6,
+	0xDDB3, 0x83A9, 0xDDB4, 0x837D, 0xDDB5, 0x83B8, 0xDDB6, 0x837B,
+	0xDDB7, 0x8398, 0xDDB8, 0x839E, 0xDDB9, 0x83A8, 0xDDBA, 0x83BA,
+	0xDDBB, 0x83BC, 0xDDBC, 0x83C1, 0xDDBD, 0x8401, 0xDDBE, 0x83E5,
+	0xDDBF, 0x83D8, 0xDDC0, 0x5807, 0xDDC1, 0x8418, 0xDDC2, 0x840B,
+	0xDDC3, 0x83DD, 0xDDC4, 0x83FD, 0xDDC5, 0x83D6, 0xDDC6, 0x841C,
+	0xDDC7, 0x8438, 0xDDC8, 0x8411, 0xDDC9, 0x8406, 0xDDCA, 0x83D4,
+	0xDDCB, 0x83DF, 0xDDCC, 0x840F, 0xDDCD, 0x8403, 0xDDCE, 0x83F8,
+	0xDDCF, 0x83F9, 0xDDD0, 0x83EA, 0xDDD1, 0x83C5, 0xDDD2, 0x83C0,
+	0xDDD3, 0x8426, 0xDDD4, 0x83F0, 0xDDD5, 0x83E1, 0xDDD6, 0x845C,
+	0xDDD7, 0x8451, 0xDDD8, 0x845A, 0xDDD9, 0x8459, 0xDDDA, 0x8473,
+	0xDDDB, 0x8487, 0xDDDC, 0x8488, 0xDDDD, 0x847A, 0xDDDE, 0x8489,
+	0xDDDF, 0x8478, 0xDDE0, 0x843C, 0xDDE1, 0x8446, 0xDDE2, 0x8469,
+	0xDDE3, 0x8476, 0xDDE4, 0x848C, 0xDDE5, 0x848E, 0xDDE6, 0x8431,
+	0xDDE7, 0x846D, 0xDDE8, 0x84C1, 0xDDE9, 0x84CD, 0xDDEA, 0x84D0,
+	0xDDEB, 0x84E6, 0xDDEC, 0x84BD, 0xDDED, 0x84D3, 0xDDEE, 0x84CA,
+	0xDDEF, 0x84BF, 0xDDF0, 0x84BA, 0xDDF1, 0x84E0, 0xDDF2, 0x84A1,
+	0xDDF3, 0x84B9, 0xDDF4, 0x84B4, 0xDDF5, 0x8497, 0xDDF6, 0x84E5,
+	0xDDF7, 0x84E3, 0xDDF8, 0x850C, 0xDDF9, 0x750D, 0xDDFA, 0x8538,
+	0xDDFB, 0x84F0, 0xDDFC, 0x8539, 0xDDFD, 0x851F, 0xDDFE, 0x853A,
+	0xDE40, 0x8F45, 0xDE41, 0x8F46, 0xDE42, 0x8F47, 0xDE43, 0x8F48,
+	0xDE44, 0x8F49, 0xDE45, 0x8F4A, 0xDE46, 0x8F4B, 0xDE47, 0x8F4C,
+	0xDE48, 0x8F4D, 0xDE49, 0x8F4E, 0xDE4A, 0x8F4F, 0xDE4B, 0x8F50,
+	0xDE4C, 0x8F51, 0xDE4D, 0x8F52, 0xDE4E, 0x8F53, 0xDE4F, 0x8F54,
+	0xDE50, 0x8F55, 0xDE51, 0x8F56, 0xDE52, 0x8F57, 0xDE53, 0x8F58,
+	0xDE54, 0x8F59, 0xDE55, 0x8F5A, 0xDE56, 0x8F5B, 0xDE57, 0x8F5C,
+	0xDE58, 0x8F5D, 0xDE59, 0x8F5E, 0xDE5A, 0x8F5F, 0xDE5B, 0x8F60,
+	0xDE5C, 0x8F61, 0xDE5D, 0x8F62, 0xDE5E, 0x8F63, 0xDE5F, 0x8F64,
+	0xDE60, 0x8F65, 0xDE61, 0x8F6A, 0xDE62, 0x8F80, 0xDE63, 0x8F8C,
+	0xDE64, 0x8F92, 0xDE65, 0x8F9D, 0xDE66, 0x8FA0, 0xDE67, 0x8FA1,
+	0xDE68, 0x8FA2, 0xDE69, 0x8FA4, 0xDE6A, 0x8FA5, 0xDE6B, 0x8FA6,
+	0xDE6C, 0x8FA7, 0xDE6D, 0x8FAA, 0xDE6E, 0x8FAC, 0xDE6F, 0x8FAD,
+	0xDE70, 0x8FAE, 0xDE71, 0x8FAF, 0xDE72, 0x8FB2, 0xDE73, 0x8FB3,
+	0xDE74, 0x8FB4, 0xDE75, 0x8FB5, 0xDE76, 0x8FB7, 0xDE77, 0x8FB8,
+	0xDE78, 0x8FBA, 0xDE79, 0x8FBB, 0xDE7A, 0x8FBC, 0xDE7B, 0x8FBF,
+	0xDE7C, 0x8FC0, 0xDE7D, 0x8FC3, 0xDE7E, 0x8FC6, 0xDE80, 0x8FC9,
+	0xDE81, 0x8FCA, 0xDE82, 0x8FCB, 0xDE83, 0x8FCC, 0xDE84, 0x8FCD,
+	0xDE85, 0x8FCF, 0xDE86, 0x8FD2, 0xDE87, 0x8FD6, 0xDE88, 0x8FD7,
+	0xDE89, 0x8FDA, 0xDE8A, 0x8FE0, 0xDE8B, 0x8FE1, 0xDE8C, 0x8FE3,
+	0xDE8D, 0x8FE7, 0xDE8E, 0x8FEC, 0xDE8F, 0x8FEF, 0xDE90, 0x8FF1,
+	0xDE91, 0x8FF2, 0xDE92, 0x8FF4, 0xDE93, 0x8FF5, 0xDE94, 0x8FF6,
+	0xDE95, 0x8FFA, 0xDE96, 0x8FFB, 0xDE97, 0x8FFC, 0xDE98, 0x8FFE,
+	0xDE99, 0x8FFF, 0xDE9A, 0x9007, 0xDE9B, 0x9008, 0xDE9C, 0x900C,
+	0xDE9D, 0x900E, 0xDE9E, 0x9013, 0xDE9F, 0x9015, 0xDEA0, 0x9018,
+	0xDEA1, 0x8556, 0xDEA2, 0x853B, 0xDEA3, 0x84FF, 0xDEA4, 0x84FC,
+	0xDEA5, 0x8559, 0xDEA6, 0x8548, 0xDEA7, 0x8568, 0xDEA8, 0x8564,
+	0xDEA9, 0x855E, 0xDEAA, 0x857A, 0xDEAB, 0x77A2, 0xDEAC, 0x8543,
+	0xDEAD, 0x8572, 0xDEAE, 0x857B, 0xDEAF, 0x85A4, 0xDEB0, 0x85A8,
+	0xDEB1, 0x8587, 0xDEB2, 0x858F, 0xDEB3, 0x8579, 0xDEB4, 0x85AE,
+	0xDEB5, 0x859C, 0xDEB6, 0x8585, 0xDEB7, 0x85B9, 0xDEB8, 0x85B7,
+	0xDEB9, 0x85B0, 0xDEBA, 0x85D3, 0xDEBB, 0x85C1, 0xDEBC, 0x85DC,
+	0xDEBD, 0x85FF, 0xDEBE, 0x8627, 0xDEBF, 0x8605, 0xDEC0, 0x8629,
+	0xDEC1, 0x8616, 0xDEC2, 0x863C, 0xDEC3, 0x5EFE, 0xDEC4, 0x5F08,
+	0xDEC5, 0x593C, 0xDEC6, 0x5941, 0xDEC7, 0x8037, 0xDEC8, 0x5955,
+	0xDEC9, 0x595A, 0xDECA, 0x5958, 0xDECB, 0x530F, 0xDECC, 0x5C22,
+	0xDECD, 0x5C25, 0xDECE, 0x5C2C, 0xDECF, 0x5C34, 0xDED0, 0x624C,
+	0xDED1, 0x626A, 0xDED2, 0x629F, 0xDED3, 0x62BB, 0xDED4, 0x62CA,
+	0xDED5, 0x62DA, 0xDED6, 0x62D7, 0xDED7, 0x62EE, 0xDED8, 0x6322,
+	0xDED9, 0x62F6, 0xDEDA, 0x6339, 0xDEDB, 0x634B, 0xDEDC, 0x6343,
+	0xDEDD, 0x63AD, 0xDEDE, 0x63F6, 0xDEDF, 0x6371, 0xDEE0, 0x637A,
+	0xDEE1, 0x638E, 0xDEE2, 0x63B4, 0xDEE3, 0x636D, 0xDEE4, 0x63AC,
+	0xDEE5, 0x638A, 0xDEE6, 0x6369, 0xDEE7, 0x63AE, 0xDEE8, 0x63BC,
+	0xDEE9, 0x63F2, 0xDEEA, 0x63F8, 0xDEEB, 0x63E0, 0xDEEC, 0x63FF,
+	0xDEED, 0x63C4, 0xDEEE, 0x63DE, 0xDEEF, 0x63CE, 0xDEF0, 0x6452,
+	0xDEF1, 0x63C6, 0xDEF2, 0x63BE, 0xDEF3, 0x6445, 0xDEF4, 0x6441,
+	0xDEF5, 0x640B, 0xDEF6, 0x641B, 0xDEF7, 0x6420, 0xDEF8, 0x640C,
+	0xDEF9, 0x6426, 0xDEFA, 0x6421, 0xDEFB, 0x645E, 0xDEFC, 0x6484,
+	0xDEFD, 0x646D, 0xDEFE, 0x6496, 0xDF40, 0x9019, 0xDF41, 0x901C,
+	0xDF42, 0x9023, 0xDF43, 0x9024, 0xDF44, 0x9025, 0xDF45, 0x9027,
+	0xDF46, 0x9028, 0xDF47, 0x9029, 0xDF48, 0x902A, 0xDF49, 0x902B,
+	0xDF4A, 0x902C, 0xDF4B, 0x9030, 0xDF4C, 0x9031, 0xDF4D, 0x9032,
+	0xDF4E, 0x9033, 0xDF4F, 0x9034, 0xDF50, 0x9037, 0xDF51, 0x9039,
+	0xDF52, 0x903A, 0xDF53, 0x903D, 0xDF54, 0x903F, 0xDF55, 0x9040,
+	0xDF56, 0x9043, 0xDF57, 0x9045, 0xDF58, 0x9046, 0xDF59, 0x9048,
+	0xDF5A, 0x9049, 0xDF5B, 0x904A, 0xDF5C, 0x904B, 0xDF5D, 0x904C,
+	0xDF5E, 0x904E, 0xDF5F, 0x9054, 0xDF60, 0x9055, 0xDF61, 0x9056,
+	0xDF62, 0x9059, 0xDF63, 0x905A, 0xDF64, 0x905C, 0xDF65, 0x905D,
+	0xDF66, 0x905E, 0xDF67, 0x905F, 0xDF68, 0x9060, 0xDF69, 0x9061,
+	0xDF6A, 0x9064, 0xDF6B, 0x9066, 0xDF6C, 0x9067, 0xDF6D, 0x9069,
+	0xDF6E, 0x906A, 0xDF6F, 0x906B, 0xDF70, 0x906C, 0xDF71, 0x906F,
+	0xDF72, 0x9070, 0xDF73, 0x9071, 0xDF74, 0x9072, 0xDF75, 0x9073,
+	0xDF76, 0x9076, 0xDF77, 0x9077, 0xDF78, 0x9078, 0xDF79, 0x9079,
+	0xDF7A, 0x907A, 0xDF7B, 0x907B, 0xDF7C, 0x907C, 0xDF7D, 0x907E,
+	0xDF7E, 0x9081, 0xDF80, 0x9084, 0xDF81, 0x9085, 0xDF82, 0x9086,
+	0xDF83, 0x9087, 0xDF84, 0x9089, 0xDF85, 0x908A, 0xDF86, 0x908C,
+	0xDF87, 0x908D, 0xDF88, 0x908E, 0xDF89, 0x908F, 0xDF8A, 0x9090,
+	0xDF8B, 0x9092, 0xDF8C, 0x9094, 0xDF8D, 0x9096, 0xDF8E, 0x9098,
+	0xDF8F, 0x909A, 0xDF90, 0x909C, 0xDF91, 0x909E, 0xDF92, 0x909F,
+	0xDF93, 0x90A0, 0xDF94, 0x90A4, 0xDF95, 0x90A5, 0xDF96, 0x90A7,
+	0xDF97, 0x90A8, 0xDF98, 0x90A9, 0xDF99, 0x90AB, 0xDF9A, 0x90AD,
+	0xDF9B, 0x90B2, 0xDF9C, 0x90B7, 0xDF9D, 0x90BC, 0xDF9E, 0x90BD,
+	0xDF9F, 0x90BF, 0xDFA0, 0x90C0, 0xDFA1, 0x647A, 0xDFA2, 0x64B7,
+	0xDFA3, 0x64B8, 0xDFA4, 0x6499, 0xDFA5, 0x64BA, 0xDFA6, 0x64C0,
+	0xDFA7, 0x64D0, 0xDFA8, 0x64D7, 0xDFA9, 0x64E4, 0xDFAA, 0x64E2,
+	0xDFAB, 0x6509, 0xDFAC, 0x6525, 0xDFAD, 0x652E, 0xDFAE, 0x5F0B,
+	0xDFAF, 0x5FD2, 0xDFB0, 0x7519, 0xDFB1, 0x5F11, 0xDFB2, 0x535F,
+	0xDFB3, 0x53F1, 0xDFB4, 0x53FD, 0xDFB5, 0x53E9, 0xDFB6, 0x53E8,
+	0xDFB7, 0x53FB, 0xDFB8, 0x5412, 0xDFB9, 0x5416, 0xDFBA, 0x5406,
+	0xDFBB, 0x544B, 0xDFBC, 0x5452, 0xDFBD, 0x5453, 0xDFBE, 0x5454,
+	0xDFBF, 0x5456, 0xDFC0, 0x5443, 0xDFC1, 0x5421, 0xDFC2, 0x5457,
+	0xDFC3, 0x5459, 0xDFC4, 0x5423, 0xDFC5, 0x5432, 0xDFC6, 0x5482,
+	0xDFC7, 0x5494, 0xDFC8, 0x5477, 0xDFC9, 0x5471, 0xDFCA, 0x5464,
+	0xDFCB, 0x549A, 0xDFCC, 0x549B, 0xDFCD, 0x5484, 0xDFCE, 0x5476,
+	0xDFCF, 0x5466, 0xDFD0, 0x549D, 0xDFD1, 0x54D0, 0xDFD2, 0x54AD,
+	0xDFD3, 0x54C2, 0xDFD4, 0x54B4, 0xDFD5, 0x54D2, 0xDFD6, 0x54A7,
+	0xDFD7, 0x54A6, 0xDFD8, 0x54D3, 0xDFD9, 0x54D4, 0xDFDA, 0x5472,
+	0xDFDB, 0x54A3, 0xDFDC, 0x54D5, 0xDFDD, 0x54BB, 0xDFDE, 0x54BF,
+	0xDFDF, 0x54CC, 0xDFE0, 0x54D9, 0xDFE1, 0x54DA, 0xDFE2, 0x54DC,
+	0xDFE3, 0x54A9, 0xDFE4, 0x54AA, 0xDFE5, 0x54A4, 0xDFE6, 0x54DD,
+	0xDFE7, 0x54CF, 0xDFE8, 0x54DE, 0xDFE9, 0x551B, 0xDFEA, 0x54E7,
+	0xDFEB, 0x5520, 0xDFEC, 0x54FD, 0xDFED, 0x5514, 0xDFEE, 0x54F3,
+	0xDFEF, 0x5522, 0xDFF0, 0x5523, 0xDFF1, 0x550F, 0xDFF2, 0x5511,
+	0xDFF3, 0x5527, 0xDFF4, 0x552A, 0xDFF5, 0x5567, 0xDFF6, 0x558F,
+	0xDFF7, 0x55B5, 0xDFF8, 0x5549, 0xDFF9, 0x556D, 0xDFFA, 0x5541,
+	0xDFFB, 0x5555, 0xDFFC, 0x553F, 0xDFFD, 0x5550, 0xDFFE, 0x553C,
+	0xE040, 0x90C2, 0xE041, 0x90C3, 0xE042, 0x90C6, 0xE043, 0x90C8,
+	0xE044, 0x90C9, 0xE045, 0x90CB, 0xE046, 0x90CC, 0xE047, 0x90CD,
+	0xE048, 0x90D2, 0xE049, 0x90D4, 0xE04A, 0x90D5, 0xE04B, 0x90D6,
+	0xE04C, 0x90D8, 0xE04D, 0x90D9, 0xE04E, 0x90DA, 0xE04F, 0x90DE,
+	0xE050, 0x90DF, 0xE051, 0x90E0, 0xE052, 0x90E3, 0xE053, 0x90E4,
+	0xE054, 0x90E5, 0xE055, 0x90E9, 0xE056, 0x90EA, 0xE057, 0x90EC,
+	0xE058, 0x90EE, 0xE059, 0x90F0, 0xE05A, 0x90F1, 0xE05B, 0x90F2,
+	0xE05C, 0x90F3, 0xE05D, 0x90F5, 0xE05E, 0x90F6, 0xE05F, 0x90F7,
+	0xE060, 0x90F9, 0xE061, 0x90FA, 0xE062, 0x90FB, 0xE063, 0x90FC,
+	0xE064, 0x90FF, 0xE065, 0x9100, 0xE066, 0x9101, 0xE067, 0x9103,
+	0xE068, 0x9105, 0xE069, 0x9106, 0xE06A, 0x9107, 0xE06B, 0x9108,
+	0xE06C, 0x9109, 0xE06D, 0x910A, 0xE06E, 0x910B, 0xE06F, 0x910C,
+	0xE070, 0x910D, 0xE071, 0x910E, 0xE072, 0x910F, 0xE073, 0x9110,
+	0xE074, 0x9111, 0xE075, 0x9112, 0xE076, 0x9113, 0xE077, 0x9114,
+	0xE078, 0x9115, 0xE079, 0x9116, 0xE07A, 0x9117, 0xE07B, 0x9118,
+	0xE07C, 0x911A, 0xE07D, 0x911B, 0xE07E, 0x911C, 0xE080, 0x911D,
+	0xE081, 0x911F, 0xE082, 0x9120, 0xE083, 0x9121, 0xE084, 0x9124,
+	0xE085, 0x9125, 0xE086, 0x9126, 0xE087, 0x9127, 0xE088, 0x9128,
+	0xE089, 0x9129, 0xE08A, 0x912A, 0xE08B, 0x912B, 0xE08C, 0x912C,
+	0xE08D, 0x912D, 0xE08E, 0x912E, 0xE08F, 0x9130, 0xE090, 0x9132,
+	0xE091, 0x9133, 0xE092, 0x9134, 0xE093, 0x9135, 0xE094, 0x9136,
+	0xE095, 0x9137, 0xE096, 0x9138, 0xE097, 0x913A, 0xE098, 0x913B,
+	0xE099, 0x913C, 0xE09A, 0x913D, 0xE09B, 0x913E, 0xE09C, 0x913F,
+	0xE09D, 0x9140, 0xE09E, 0x9141, 0xE09F, 0x9142, 0xE0A0, 0x9144,
+	0xE0A1, 0x5537, 0xE0A2, 0x5556, 0xE0A3, 0x5575, 0xE0A4, 0x5576,
+	0xE0A5, 0x5577, 0xE0A6, 0x5533, 0xE0A7, 0x5530, 0xE0A8, 0x555C,
+	0xE0A9, 0x558B, 0xE0AA, 0x55D2, 0xE0AB, 0x5583, 0xE0AC, 0x55B1,
+	0xE0AD, 0x55B9, 0xE0AE, 0x5588, 0xE0AF, 0x5581, 0xE0B0, 0x559F,
+	0xE0B1, 0x557E, 0xE0B2, 0x55D6, 0xE0B3, 0x5591, 0xE0B4, 0x557B,
+	0xE0B5, 0x55DF, 0xE0B6, 0x55BD, 0xE0B7, 0x55BE, 0xE0B8, 0x5594,
+	0xE0B9, 0x5599, 0xE0BA, 0x55EA, 0xE0BB, 0x55F7, 0xE0BC, 0x55C9,
+	0xE0BD, 0x561F, 0xE0BE, 0x55D1, 0xE0BF, 0x55EB, 0xE0C0, 0x55EC,
+	0xE0C1, 0x55D4, 0xE0C2, 0x55E6, 0xE0C3, 0x55DD, 0xE0C4, 0x55C4,
+	0xE0C5, 0x55EF, 0xE0C6, 0x55E5, 0xE0C7, 0x55F2, 0xE0C8, 0x55F3,
+	0xE0C9, 0x55CC, 0xE0CA, 0x55CD, 0xE0CB, 0x55E8, 0xE0CC, 0x55F5,
+	0xE0CD, 0x55E4, 0xE0CE, 0x8F94, 0xE0CF, 0x561E, 0xE0D0, 0x5608,
+	0xE0D1, 0x560C, 0xE0D2, 0x5601, 0xE0D3, 0x5624, 0xE0D4, 0x5623,
+	0xE0D5, 0x55FE, 0xE0D6, 0x5600, 0xE0D7, 0x5627, 0xE0D8, 0x562D,
+	0xE0D9, 0x5658, 0xE0DA, 0x5639, 0xE0DB, 0x5657, 0xE0DC, 0x562C,
+	0xE0DD, 0x564D, 0xE0DE, 0x5662, 0xE0DF, 0x5659, 0xE0E0, 0x565C,
+	0xE0E1, 0x564C, 0xE0E2, 0x5654, 0xE0E3, 0x5686, 0xE0E4, 0x5664,
+	0xE0E5, 0x5671, 0xE0E6, 0x566B, 0xE0E7, 0x567B, 0xE0E8, 0x567C,
+	0xE0E9, 0x5685, 0xE0EA, 0x5693, 0xE0EB, 0x56AF, 0xE0EC, 0x56D4,
+	0xE0ED, 0x56D7, 0xE0EE, 0x56DD, 0xE0EF, 0x56E1, 0xE0F0, 0x56F5,
+	0xE0F1, 0x56EB, 0xE0F2, 0x56F9, 0xE0F3, 0x56FF, 0xE0F4, 0x5704,
+	0xE0F5, 0x570A, 0xE0F6, 0x5709, 0xE0F7, 0x571C, 0xE0F8, 0x5E0F,
+	0xE0F9, 0x5E19, 0xE0FA, 0x5E14, 0xE0FB, 0x5E11, 0xE0FC, 0x5E31,
+	0xE0FD, 0x5E3B, 0xE0FE, 0x5E3C, 0xE140, 0x9145, 0xE141, 0x9147,
+	0xE142, 0x9148, 0xE143, 0x9151, 0xE144, 0x9153, 0xE145, 0x9154,
+	0xE146, 0x9155, 0xE147, 0x9156, 0xE148, 0x9158, 0xE149, 0x9159,
+	0xE14A, 0x915B, 0xE14B, 0x915C, 0xE14C, 0x915F, 0xE14D, 0x9160,
+	0xE14E, 0x9166, 0xE14F, 0x9167, 0xE150, 0x9168, 0xE151, 0x916B,
+	0xE152, 0x916D, 0xE153, 0x9173, 0xE154, 0x917A, 0xE155, 0x917B,
+	0xE156, 0x917C, 0xE157, 0x9180, 0xE158, 0x9181, 0xE159, 0x9182,
+	0xE15A, 0x9183, 0xE15B, 0x9184, 0xE15C, 0x9186, 0xE15D, 0x9188,
+	0xE15E, 0x918A, 0xE15F, 0x918E, 0xE160, 0x918F, 0xE161, 0x9193,
+	0xE162, 0x9194, 0xE163, 0x9195, 0xE164, 0x9196, 0xE165, 0x9197,
+	0xE166, 0x9198, 0xE167, 0x9199, 0xE168, 0x919C, 0xE169, 0x919D,
+	0xE16A, 0x919E, 0xE16B, 0x919F, 0xE16C, 0x91A0, 0xE16D, 0x91A1,
+	0xE16E, 0x91A4, 0xE16F, 0x91A5, 0xE170, 0x91A6, 0xE171, 0x91A7,
+	0xE172, 0x91A8, 0xE173, 0x91A9, 0xE174, 0x91AB, 0xE175, 0x91AC,
+	0xE176, 0x91B0, 0xE177, 0x91B1, 0xE178, 0x91B2, 0xE179, 0x91B3,
+	0xE17A, 0x91B6, 0xE17B, 0x91B7, 0xE17C, 0x91B8, 0xE17D, 0x91B9,
+	0xE17E, 0x91BB, 0xE180, 0x91BC, 0xE181, 0x91BD, 0xE182, 0x91BE,
+	0xE183, 0x91BF, 0xE184, 0x91C0, 0xE185, 0x91C1, 0xE186, 0x91C2,
+	0xE187, 0x91C3, 0xE188, 0x91C4, 0xE189, 0x91C5, 0xE18A, 0x91C6,
+	0xE18B, 0x91C8, 0xE18C, 0x91CB, 0xE18D, 0x91D0, 0xE18E, 0x91D2,
+	0xE18F, 0x91D3, 0xE190, 0x91D4, 0xE191, 0x91D5, 0xE192, 0x91D6,
+	0xE193, 0x91D7, 0xE194, 0x91D8, 0xE195, 0x91D9, 0xE196, 0x91DA,
+	0xE197, 0x91DB, 0xE198, 0x91DD, 0xE199, 0x91DE, 0xE19A, 0x91DF,
+	0xE19B, 0x91E0, 0xE19C, 0x91E1, 0xE19D, 0x91E2, 0xE19E, 0x91E3,
+	0xE19F, 0x91E4, 0xE1A0, 0x91E5, 0xE1A1, 0x5E37, 0xE1A2, 0x5E44,
+	0xE1A3, 0x5E54, 0xE1A4, 0x5E5B, 0xE1A5, 0x5E5E, 0xE1A6, 0x5E61,
+	0xE1A7, 0x5C8C, 0xE1A8, 0x5C7A, 0xE1A9, 0x5C8D, 0xE1AA, 0x5C90,
+	0xE1AB, 0x5C96, 0xE1AC, 0x5C88, 0xE1AD, 0x5C98, 0xE1AE, 0x5C99,
+	0xE1AF, 0x5C91, 0xE1B0, 0x5C9A, 0xE1B1, 0x5C9C, 0xE1B2, 0x5CB5,
+	0xE1B3, 0x5CA2, 0xE1B4, 0x5CBD, 0xE1B5, 0x5CAC, 0xE1B6, 0x5CAB,
+	0xE1B7, 0x5CB1, 0xE1B8, 0x5CA3, 0xE1B9, 0x5CC1, 0xE1BA, 0x5CB7,
+	0xE1BB, 0x5CC4, 0xE1BC, 0x5CD2, 0xE1BD, 0x5CE4, 0xE1BE, 0x5CCB,
+	0xE1BF, 0x5CE5, 0xE1C0, 0x5D02, 0xE1C1, 0x5D03, 0xE1C2, 0x5D27,
+	0xE1C3, 0x5D26, 0xE1C4, 0x5D2E, 0xE1C5, 0x5D24, 0xE1C6, 0x5D1E,
+	0xE1C7, 0x5D06, 0xE1C8, 0x5D1B, 0xE1C9, 0x5D58, 0xE1CA, 0x5D3E,
+	0xE1CB, 0x5D34, 0xE1CC, 0x5D3D, 0xE1CD, 0x5D6C, 0xE1CE, 0x5D5B,
+	0xE1CF, 0x5D6F, 0xE1D0, 0x5D5D, 0xE1D1, 0x5D6B, 0xE1D2, 0x5D4B,
+	0xE1D3, 0x5D4A, 0xE1D4, 0x5D69, 0xE1D5, 0x5D74, 0xE1D6, 0x5D82,
+	0xE1D7, 0x5D99, 0xE1D8, 0x5D9D, 0xE1D9, 0x8C73, 0xE1DA, 0x5DB7,
+	0xE1DB, 0x5DC5, 0xE1DC, 0x5F73, 0xE1DD, 0x5F77, 0xE1DE, 0x5F82,
+	0xE1DF, 0x5F87, 0xE1E0, 0x5F89, 0xE1E1, 0x5F8C, 0xE1E2, 0x5F95,
+	0xE1E3, 0x5F99, 0xE1E4, 0x5F9C, 0xE1E5, 0x5FA8, 0xE1E6, 0x5FAD,
+	0xE1E7, 0x5FB5, 0xE1E8, 0x5FBC, 0xE1E9, 0x8862, 0xE1EA, 0x5F61,
+	0xE1EB, 0x72AD, 0xE1EC, 0x72B0, 0xE1ED, 0x72B4, 0xE1EE, 0x72B7,
+	0xE1EF, 0x72B8, 0xE1F0, 0x72C3, 0xE1F1, 0x72C1, 0xE1F2, 0x72CE,
+	0xE1F3, 0x72CD, 0xE1F4, 0x72D2, 0xE1F5, 0x72E8, 0xE1F6, 0x72EF,
+	0xE1F7, 0x72E9, 0xE1F8, 0x72F2, 0xE1F9, 0x72F4, 0xE1FA, 0x72F7,
+	0xE1FB, 0x7301, 0xE1FC, 0x72F3, 0xE1FD, 0x7303, 0xE1FE, 0x72FA,
+	0xE240, 0x91E6, 0xE241, 0x91E7, 0xE242, 0x91E8, 0xE243, 0x91E9,
+	0xE244, 0x91EA, 0xE245, 0x91EB, 0xE246, 0x91EC, 0xE247, 0x91ED,
+	0xE248, 0x91EE, 0xE249, 0x91EF, 0xE24A, 0x91F0, 0xE24B, 0x91F1,
+	0xE24C, 0x91F2, 0xE24D, 0x91F3, 0xE24E, 0x91F4, 0xE24F, 0x91F5,
+	0xE250, 0x91F6, 0xE251, 0x91F7, 0xE252, 0x91F8, 0xE253, 0x91F9,
+	0xE254, 0x91FA, 0xE255, 0x91FB, 0xE256, 0x91FC, 0xE257, 0x91FD,
+	0xE258, 0x91FE, 0xE259, 0x91FF, 0xE25A, 0x9200, 0xE25B, 0x9201,
+	0xE25C, 0x9202, 0xE25D, 0x9203, 0xE25E, 0x9204, 0xE25F, 0x9205,
+	0xE260, 0x9206, 0xE261, 0x9207, 0xE262, 0x9208, 0xE263, 0x9209,
+	0xE264, 0x920A, 0xE265, 0x920B, 0xE266, 0x920C, 0xE267, 0x920D,
+	0xE268, 0x920E, 0xE269, 0x920F, 0xE26A, 0x9210, 0xE26B, 0x9211,
+	0xE26C, 0x9212, 0xE26D, 0x9213, 0xE26E, 0x9214, 0xE26F, 0x9215,
+	0xE270, 0x9216, 0xE271, 0x9217, 0xE272, 0x9218, 0xE273, 0x9219,
+	0xE274, 0x921A, 0xE275, 0x921B, 0xE276, 0x921C, 0xE277, 0x921D,
+	0xE278, 0x921E, 0xE279, 0x921F, 0xE27A, 0x9220, 0xE27B, 0x9221,
+	0xE27C, 0x9222, 0xE27D, 0x9223, 0xE27E, 0x9224, 0xE280, 0x9225,
+	0xE281, 0x9226, 0xE282, 0x9227, 0xE283, 0x9228, 0xE284, 0x9229,
+	0xE285, 0x922A, 0xE286, 0x922B, 0xE287, 0x922C, 0xE288, 0x922D,
+	0xE289, 0x922E, 0xE28A, 0x922F, 0xE28B, 0x9230, 0xE28C, 0x9231,
+	0xE28D, 0x9232, 0xE28E, 0x9233, 0xE28F, 0x9234, 0xE290, 0x9235,
+	0xE291, 0x9236, 0xE292, 0x9237, 0xE293, 0x9238, 0xE294, 0x9239,
+	0xE295, 0x923A, 0xE296, 0x923B, 0xE297, 0x923C, 0xE298, 0x923D,
+	0xE299, 0x923E, 0xE29A, 0x923F, 0xE29B, 0x9240, 0xE29C, 0x9241,
+	0xE29D, 0x9242, 0xE29E, 0x9243, 0xE29F, 0x9244, 0xE2A0, 0x9245,
+	0xE2A1, 0x72FB, 0xE2A2, 0x7317, 0xE2A3, 0x7313, 0xE2A4, 0x7321,
+	0xE2A5, 0x730A, 0xE2A6, 0x731E, 0xE2A7, 0x731D, 0xE2A8, 0x7315,
+	0xE2A9, 0x7322, 0xE2AA, 0x7339, 0xE2AB, 0x7325, 0xE2AC, 0x732C,
+	0xE2AD, 0x7338, 0xE2AE, 0x7331, 0xE2AF, 0x7350, 0xE2B0, 0x734D,
+	0xE2B1, 0x7357, 0xE2B2, 0x7360, 0xE2B3, 0x736C, 0xE2B4, 0x736F,
+	0xE2B5, 0x737E, 0xE2B6, 0x821B, 0xE2B7, 0x5925, 0xE2B8, 0x98E7,
+	0xE2B9, 0x5924, 0xE2BA, 0x5902, 0xE2BB, 0x9963, 0xE2BC, 0x9967,
+	0xE2BD, 0x9968, 0xE2BE, 0x9969, 0xE2BF, 0x996A, 0xE2C0, 0x996B,
+	0xE2C1, 0x996C, 0xE2C2, 0x9974, 0xE2C3, 0x9977, 0xE2C4, 0x997D,
+	0xE2C5, 0x9980, 0xE2C6, 0x9984, 0xE2C7, 0x9987, 0xE2C8, 0x998A,
+	0xE2C9, 0x998D, 0xE2CA, 0x9990, 0xE2CB, 0x9991, 0xE2CC, 0x9993,
+	0xE2CD, 0x9994, 0xE2CE, 0x9995, 0xE2CF, 0x5E80, 0xE2D0, 0x5E91,
+	0xE2D1, 0x5E8B, 0xE2D2, 0x5E96, 0xE2D3, 0x5EA5, 0xE2D4, 0x5EA0,
+	0xE2D5, 0x5EB9, 0xE2D6, 0x5EB5, 0xE2D7, 0x5EBE, 0xE2D8, 0x5EB3,
+	0xE2D9, 0x8D53, 0xE2DA, 0x5ED2, 0xE2DB, 0x5ED1, 0xE2DC, 0x5EDB,
+	0xE2DD, 0x5EE8, 0xE2DE, 0x5EEA, 0xE2DF, 0x81BA, 0xE2E0, 0x5FC4,
+	0xE2E1, 0x5FC9, 0xE2E2, 0x5FD6, 0xE2E3, 0x5FCF, 0xE2E4, 0x6003,
+	0xE2E5, 0x5FEE, 0xE2E6, 0x6004, 0xE2E7, 0x5FE1, 0xE2E8, 0x5FE4,
+	0xE2E9, 0x5FFE, 0xE2EA, 0x6005, 0xE2EB, 0x6006, 0xE2EC, 0x5FEA,
+	0xE2ED, 0x5FED, 0xE2EE, 0x5FF8, 0xE2EF, 0x6019, 0xE2F0, 0x6035,
+	0xE2F1, 0x6026, 0xE2F2, 0x601B, 0xE2F3, 0x600F, 0xE2F4, 0x600D,
+	0xE2F5, 0x6029, 0xE2F6, 0x602B, 0xE2F7, 0x600A, 0xE2F8, 0x603F,
+	0xE2F9, 0x6021, 0xE2FA, 0x6078, 0xE2FB, 0x6079, 0xE2FC, 0x607B,
+	0xE2FD, 0x607A, 0xE2FE, 0x6042, 0xE340, 0x9246, 0xE341, 0x9247,
+	0xE342, 0x9248, 0xE343, 0x9249, 0xE344, 0x924A, 0xE345, 0x924B,
+	0xE346, 0x924C, 0xE347, 0x924D, 0xE348, 0x924E, 0xE349, 0x924F,
+	0xE34A, 0x9250, 0xE34B, 0x9251, 0xE34C, 0x9252, 0xE34D, 0x9253,
+	0xE34E, 0x9254, 0xE34F, 0x9255, 0xE350, 0x9256, 0xE351, 0x9257,
+	0xE352, 0x9258, 0xE353, 0x9259, 0xE354, 0x925A, 0xE355, 0x925B,
+	0xE356, 0x925C, 0xE357, 0x925D, 0xE358, 0x925E, 0xE359, 0x925F,
+	0xE35A, 0x9260, 0xE35B, 0x9261, 0xE35C, 0x9262, 0xE35D, 0x9263,
+	0xE35E, 0x9264, 0xE35F, 0x9265, 0xE360, 0x9266, 0xE361, 0x9267,
+	0xE362, 0x9268, 0xE363, 0x9269, 0xE364, 0x926A, 0xE365, 0x926B,
+	0xE366, 0x926C, 0xE367, 0x926D, 0xE368, 0x926E, 0xE369, 0x926F,
+	0xE36A, 0x9270, 0xE36B, 0x9271, 0xE36C, 0x9272, 0xE36D, 0x9273,
+	0xE36E, 0x9275, 0xE36F, 0x9276, 0xE370, 0x9277, 0xE371, 0x9278,
+	0xE372, 0x9279, 0xE373, 0x927A, 0xE374, 0x927B, 0xE375, 0x927C,
+	0xE376, 0x927D, 0xE377, 0x927E, 0xE378, 0x927F, 0xE379, 0x9280,
+	0xE37A, 0x9281, 0xE37B, 0x9282, 0xE37C, 0x9283, 0xE37D, 0x9284,
+	0xE37E, 0x9285, 0xE380, 0x9286, 0xE381, 0x9287, 0xE382, 0x9288,
+	0xE383, 0x9289, 0xE384, 0x928A, 0xE385, 0x928B, 0xE386, 0x928C,
+	0xE387, 0x928D, 0xE388, 0x928F, 0xE389, 0x9290, 0xE38A, 0x9291,
+	0xE38B, 0x9292, 0xE38C, 0x9293, 0xE38D, 0x9294, 0xE38E, 0x9295,
+	0xE38F, 0x9296, 0xE390, 0x9297, 0xE391, 0x9298, 0xE392, 0x9299,
+	0xE393, 0x929A, 0xE394, 0x929B, 0xE395, 0x929C, 0xE396, 0x929D,
+	0xE397, 0x929E, 0xE398, 0x929F, 0xE399, 0x92A0, 0xE39A, 0x92A1,
+	0xE39B, 0x92A2, 0xE39C, 0x92A3, 0xE39D, 0x92A4, 0xE39E, 0x92A5,
+	0xE39F, 0x92A6, 0xE3A0, 0x92A7, 0xE3A1, 0x606A, 0xE3A2, 0x607D,
+	0xE3A3, 0x6096, 0xE3A4, 0x609A, 0xE3A5, 0x60AD, 0xE3A6, 0x609D,
+	0xE3A7, 0x6083, 0xE3A8, 0x6092, 0xE3A9, 0x608C, 0xE3AA, 0x609B,
+	0xE3AB, 0x60EC, 0xE3AC, 0x60BB, 0xE3AD, 0x60B1, 0xE3AE, 0x60DD,
+	0xE3AF, 0x60D8, 0xE3B0, 0x60C6, 0xE3B1, 0x60DA, 0xE3B2, 0x60B4,
+	0xE3B3, 0x6120, 0xE3B4, 0x6126, 0xE3B5, 0x6115, 0xE3B6, 0x6123,
+	0xE3B7, 0x60F4, 0xE3B8, 0x6100, 0xE3B9, 0x610E, 0xE3BA, 0x612B,
+	0xE3BB, 0x614A, 0xE3BC, 0x6175, 0xE3BD, 0x61AC, 0xE3BE, 0x6194,
+	0xE3BF, 0x61A7, 0xE3C0, 0x61B7, 0xE3C1, 0x61D4, 0xE3C2, 0x61F5,
+	0xE3C3, 0x5FDD, 0xE3C4, 0x96B3, 0xE3C5, 0x95E9, 0xE3C6, 0x95EB,
+	0xE3C7, 0x95F1, 0xE3C8, 0x95F3, 0xE3C9, 0x95F5, 0xE3CA, 0x95F6,
+	0xE3CB, 0x95FC, 0xE3CC, 0x95FE, 0xE3CD, 0x9603, 0xE3CE, 0x9604,
+	0xE3CF, 0x9606, 0xE3D0, 0x9608, 0xE3D1, 0x960A, 0xE3D2, 0x960B,
+	0xE3D3, 0x960C, 0xE3D4, 0x960D, 0xE3D5, 0x960F, 0xE3D6, 0x9612,
+	0xE3D7, 0x9615, 0xE3D8, 0x9616, 0xE3D9, 0x9617, 0xE3DA, 0x9619,
+	0xE3DB, 0x961A, 0xE3DC, 0x4E2C, 0xE3DD, 0x723F, 0xE3DE, 0x6215,
+	0xE3DF, 0x6C35, 0xE3E0, 0x6C54, 0xE3E1, 0x6C5C, 0xE3E2, 0x6C4A,
+	0xE3E3, 0x6CA3, 0xE3E4, 0x6C85, 0xE3E5, 0x6C90, 0xE3E6, 0x6C94,
+	0xE3E7, 0x6C8C, 0xE3E8, 0x6C68, 0xE3E9, 0x6C69, 0xE3EA, 0x6C74,
+	0xE3EB, 0x6C76, 0xE3EC, 0x6C86, 0xE3ED, 0x6CA9, 0xE3EE, 0x6CD0,
+	0xE3EF, 0x6CD4, 0xE3F0, 0x6CAD, 0xE3F1, 0x6CF7, 0xE3F2, 0x6CF8,
+	0xE3F3, 0x6CF1, 0xE3F4, 0x6CD7, 0xE3F5, 0x6CB2, 0xE3F6, 0x6CE0,
+	0xE3F7, 0x6CD6, 0xE3F8, 0x6CFA, 0xE3F9, 0x6CEB, 0xE3FA, 0x6CEE,
+	0xE3FB, 0x6CB1, 0xE3FC, 0x6CD3, 0xE3FD, 0x6CEF, 0xE3FE, 0x6CFE,
+	0xE440, 0x92A8, 0xE441, 0x92A9, 0xE442, 0x92AA, 0xE443, 0x92AB,
+	0xE444, 0x92AC, 0xE445, 0x92AD, 0xE446, 0x92AF, 0xE447, 0x92B0,
+	0xE448, 0x92B1, 0xE449, 0x92B2, 0xE44A, 0x92B3, 0xE44B, 0x92B4,
+	0xE44C, 0x92B5, 0xE44D, 0x92B6, 0xE44E, 0x92B7, 0xE44F, 0x92B8,
+	0xE450, 0x92B9, 0xE451, 0x92BA, 0xE452, 0x92BB, 0xE453, 0x92BC,
+	0xE454, 0x92BD, 0xE455, 0x92BE, 0xE456, 0x92BF, 0xE457, 0x92C0,
+	0xE458, 0x92C1, 0xE459, 0x92C2, 0xE45A, 0x92C3, 0xE45B, 0x92C4,
+	0xE45C, 0x92C5, 0xE45D, 0x92C6, 0xE45E, 0x92C7, 0xE45F, 0x92C9,
+	0xE460, 0x92CA, 0xE461, 0x92CB, 0xE462, 0x92CC, 0xE463, 0x92CD,
+	0xE464, 0x92CE, 0xE465, 0x92CF, 0xE466, 0x92D0, 0xE467, 0x92D1,
+	0xE468, 0x92D2, 0xE469, 0x92D3, 0xE46A, 0x92D4, 0xE46B, 0x92D5,
+	0xE46C, 0x92D6, 0xE46D, 0x92D7, 0xE46E, 0x92D8, 0xE46F, 0x92D9,
+	0xE470, 0x92DA, 0xE471, 0x92DB, 0xE472, 0x92DC, 0xE473, 0x92DD,
+	0xE474, 0x92DE, 0xE475, 0x92DF, 0xE476, 0x92E0, 0xE477, 0x92E1,
+	0xE478, 0x92E2, 0xE479, 0x92E3, 0xE47A, 0x92E4, 0xE47B, 0x92E5,
+	0xE47C, 0x92E6, 0xE47D, 0x92E7, 0xE47E, 0x92E8, 0xE480, 0x92E9,
+	0xE481, 0x92EA, 0xE482, 0x92EB, 0xE483, 0x92EC, 0xE484, 0x92ED,
+	0xE485, 0x92EE, 0xE486, 0x92EF, 0xE487, 0x92F0, 0xE488, 0x92F1,
+	0xE489, 0x92F2, 0xE48A, 0x92F3, 0xE48B, 0x92F4, 0xE48C, 0x92F5,
+	0xE48D, 0x92F6, 0xE48E, 0x92F7, 0xE48F, 0x92F8, 0xE490, 0x92F9,
+	0xE491, 0x92FA, 0xE492, 0x92FB, 0xE493, 0x92FC, 0xE494, 0x92FD,
+	0xE495, 0x92FE, 0xE496, 0x92FF, 0xE497, 0x9300, 0xE498, 0x9301,
+	0xE499, 0x9302, 0xE49A, 0x9303, 0xE49B, 0x9304, 0xE49C, 0x9305,
+	0xE49D, 0x9306, 0xE49E, 0x9307, 0xE49F, 0x9308, 0xE4A0, 0x9309,
+	0xE4A1, 0x6D39, 0xE4A2, 0x6D27, 0xE4A3, 0x6D0C, 0xE4A4, 0x6D43,
+	0xE4A5, 0x6D48, 0xE4A6, 0x6D07, 0xE4A7, 0x6D04, 0xE4A8, 0x6D19,
+	0xE4A9, 0x6D0E, 0xE4AA, 0x6D2B, 0xE4AB, 0x6D4D, 0xE4AC, 0x6D2E,
+	0xE4AD, 0x6D35, 0xE4AE, 0x6D1A, 0xE4AF, 0x6D4F, 0xE4B0, 0x6D52,
+	0xE4B1, 0x6D54, 0xE4B2, 0x6D33, 0xE4B3, 0x6D91, 0xE4B4, 0x6D6F,
+	0xE4B5, 0x6D9E, 0xE4B6, 0x6DA0, 0xE4B7, 0x6D5E, 0xE4B8, 0x6D93,
+	0xE4B9, 0x6D94, 0xE4BA, 0x6D5C, 0xE4BB, 0x6D60, 0xE4BC, 0x6D7C,
+	0xE4BD, 0x6D63, 0xE4BE, 0x6E1A, 0xE4BF, 0x6DC7, 0xE4C0, 0x6DC5,
+	0xE4C1, 0x6DDE, 0xE4C2, 0x6E0E, 0xE4C3, 0x6DBF, 0xE4C4, 0x6DE0,
+	0xE4C5, 0x6E11, 0xE4C6, 0x6DE6, 0xE4C7, 0x6DDD, 0xE4C8, 0x6DD9,
+	0xE4C9, 0x6E16, 0xE4CA, 0x6DAB, 0xE4CB, 0x6E0C, 0xE4CC, 0x6DAE,
+	0xE4CD, 0x6E2B, 0xE4CE, 0x6E6E, 0xE4CF, 0x6E4E, 0xE4D0, 0x6E6B,
+	0xE4D1, 0x6EB2, 0xE4D2, 0x6E5F, 0xE4D3, 0x6E86, 0xE4D4, 0x6E53,
+	0xE4D5, 0x6E54, 0xE4D6, 0x6E32, 0xE4D7, 0x6E25, 0xE4D8, 0x6E44,
+	0xE4D9, 0x6EDF, 0xE4DA, 0x6EB1, 0xE4DB, 0x6E98, 0xE4DC, 0x6EE0,
+	0xE4DD, 0x6F2D, 0xE4DE, 0x6EE2, 0xE4DF, 0x6EA5, 0xE4E0, 0x6EA7,
+	0xE4E1, 0x6EBD, 0xE4E2, 0x6EBB, 0xE4E3, 0x6EB7, 0xE4E4, 0x6ED7,
+	0xE4E5, 0x6EB4, 0xE4E6, 0x6ECF, 0xE4E7, 0x6E8F, 0xE4E8, 0x6EC2,
+	0xE4E9, 0x6E9F, 0xE4EA, 0x6F62, 0xE4EB, 0x6F46, 0xE4EC, 0x6F47,
+	0xE4ED, 0x6F24, 0xE4EE, 0x6F15, 0xE4EF, 0x6EF9, 0xE4F0, 0x6F2F,
+	0xE4F1, 0x6F36, 0xE4F2, 0x6F4B, 0xE4F3, 0x6F74, 0xE4F4, 0x6F2A,
+	0xE4F5, 0x6F09, 0xE4F6, 0x6F29, 0xE4F7, 0x6F89, 0xE4F8, 0x6F8D,
+	0xE4F9, 0x6F8C, 0xE4FA, 0x6F78, 0xE4FB, 0x6F72, 0xE4FC, 0x6F7C,
+	0xE4FD, 0x6F7A, 0xE4FE, 0x6FD1, 0xE540, 0x930A, 0xE541, 0x930B,
+	0xE542, 0x930C, 0xE543, 0x930D, 0xE544, 0x930E, 0xE545, 0x930F,
+	0xE546, 0x9310, 0xE547, 0x9311, 0xE548, 0x9312, 0xE549, 0x9313,
+	0xE54A, 0x9314, 0xE54B, 0x9315, 0xE54C, 0x9316, 0xE54D, 0x9317,
+	0xE54E, 0x9318, 0xE54F, 0x9319, 0xE550, 0x931A, 0xE551, 0x931B,
+	0xE552, 0x931C, 0xE553, 0x931D, 0xE554, 0x931E, 0xE555, 0x931F,
+	0xE556, 0x9320, 0xE557, 0x9321, 0xE558, 0x9322, 0xE559, 0x9323,
+	0xE55A, 0x9324, 0xE55B, 0x9325, 0xE55C, 0x9326, 0xE55D, 0x9327,
+	0xE55E, 0x9328, 0xE55F, 0x9329, 0xE560, 0x932A, 0xE561, 0x932B,
+	0xE562, 0x932C, 0xE563, 0x932D, 0xE564, 0x932E, 0xE565, 0x932F,
+	0xE566, 0x9330, 0xE567, 0x9331, 0xE568, 0x9332, 0xE569, 0x9333,
+	0xE56A, 0x9334, 0xE56B, 0x9335, 0xE56C, 0x9336, 0xE56D, 0x9337,
+	0xE56E, 0x9338, 0xE56F, 0x9339, 0xE570, 0x933A, 0xE571, 0x933B,
+	0xE572, 0x933C, 0xE573, 0x933D, 0xE574, 0x933F, 0xE575, 0x9340,
+	0xE576, 0x9341, 0xE577, 0x9342, 0xE578, 0x9343, 0xE579, 0x9344,
+	0xE57A, 0x9345, 0xE57B, 0x9346, 0xE57C, 0x9347, 0xE57D, 0x9348,
+	0xE57E, 0x9349, 0xE580, 0x934A, 0xE581, 0x934B, 0xE582, 0x934C,
+	0xE583, 0x934D, 0xE584, 0x934E, 0xE585, 0x934F, 0xE586, 0x9350,
+	0xE587, 0x9351, 0xE588, 0x9352, 0xE589, 0x9353, 0xE58A, 0x9354,
+	0xE58B, 0x9355, 0xE58C, 0x9356, 0xE58D, 0x9357, 0xE58E, 0x9358,
+	0xE58F, 0x9359, 0xE590, 0x935A, 0xE591, 0x935B, 0xE592, 0x935C,
+	0xE593, 0x935D, 0xE594, 0x935E, 0xE595, 0x935F, 0xE596, 0x9360,
+	0xE597, 0x9361, 0xE598, 0x9362, 0xE599, 0x9363, 0xE59A, 0x9364,
+	0xE59B, 0x9365, 0xE59C, 0x9366, 0xE59D, 0x9367, 0xE59E, 0x9368,
+	0xE59F, 0x9369, 0xE5A0, 0x936B, 0xE5A1, 0x6FC9, 0xE5A2, 0x6FA7,
+	0xE5A3, 0x6FB9, 0xE5A4, 0x6FB6, 0xE5A5, 0x6FC2, 0xE5A6, 0x6FE1,
+	0xE5A7, 0x6FEE, 0xE5A8, 0x6FDE, 0xE5A9, 0x6FE0, 0xE5AA, 0x6FEF,
+	0xE5AB, 0x701A, 0xE5AC, 0x7023, 0xE5AD, 0x701B, 0xE5AE, 0x7039,
+	0xE5AF, 0x7035, 0xE5B0, 0x704F, 0xE5B1, 0x705E, 0xE5B2, 0x5B80,
+	0xE5B3, 0x5B84, 0xE5B4, 0x5B95, 0xE5B5, 0x5B93, 0xE5B6, 0x5BA5,
+	0xE5B7, 0x5BB8, 0xE5B8, 0x752F, 0xE5B9, 0x9A9E, 0xE5BA, 0x6434,
+	0xE5BB, 0x5BE4, 0xE5BC, 0x5BEE, 0xE5BD, 0x8930, 0xE5BE, 0x5BF0,
+	0xE5BF, 0x8E47, 0xE5C0, 0x8B07, 0xE5C1, 0x8FB6, 0xE5C2, 0x8FD3,
+	0xE5C3, 0x8FD5, 0xE5C4, 0x8FE5, 0xE5C5, 0x8FEE, 0xE5C6, 0x8FE4,
+	0xE5C7, 0x8FE9, 0xE5C8, 0x8FE6, 0xE5C9, 0x8FF3, 0xE5CA, 0x8FE8,
+	0xE5CB, 0x9005, 0xE5CC, 0x9004, 0xE5CD, 0x900B, 0xE5CE, 0x9026,
+	0xE5CF, 0x9011, 0xE5D0, 0x900D, 0xE5D1, 0x9016, 0xE5D2, 0x9021,
+	0xE5D3, 0x9035, 0xE5D4, 0x9036, 0xE5D5, 0x902D, 0xE5D6, 0x902F,
+	0xE5D7, 0x9044, 0xE5D8, 0x9051, 0xE5D9, 0x9052, 0xE5DA, 0x9050,
+	0xE5DB, 0x9068, 0xE5DC, 0x9058, 0xE5DD, 0x9062, 0xE5DE, 0x905B,
+	0xE5DF, 0x66B9, 0xE5E0, 0x9074, 0xE5E1, 0x907D, 0xE5E2, 0x9082,
+	0xE5E3, 0x9088, 0xE5E4, 0x9083, 0xE5E5, 0x908B, 0xE5E6, 0x5F50,
+	0xE5E7, 0x5F57, 0xE5E8, 0x5F56, 0xE5E9, 0x5F58, 0xE5EA, 0x5C3B,
+	0xE5EB, 0x54AB, 0xE5EC, 0x5C50, 0xE5ED, 0x5C59, 0xE5EE, 0x5B71,
+	0xE5EF, 0x5C63, 0xE5F0, 0x5C66, 0xE5F1, 0x7FBC, 0xE5F2, 0x5F2A,
+	0xE5F3, 0x5F29, 0xE5F4, 0x5F2D, 0xE5F5, 0x8274, 0xE5F6, 0x5F3C,
+	0xE5F7, 0x9B3B, 0xE5F8, 0x5C6E, 0xE5F9, 0x5981, 0xE5FA, 0x5983,
+	0xE5FB, 0x598D, 0xE5FC, 0x59A9, 0xE5FD, 0x59AA, 0xE5FE, 0x59A3,
+	0xE640, 0x936C, 0xE641, 0x936D, 0xE642, 0x936E, 0xE643, 0x936F,
+	0xE644, 0x9370, 0xE645, 0x9371, 0xE646, 0x9372, 0xE647, 0x9373,
+	0xE648, 0x9374, 0xE649, 0x9375, 0xE64A, 0x9376, 0xE64B, 0x9377,
+	0xE64C, 0x9378, 0xE64D, 0x9379, 0xE64E, 0x937A, 0xE64F, 0x937B,
+	0xE650, 0x937C, 0xE651, 0x937D, 0xE652, 0x937E, 0xE653, 0x937F,
+	0xE654, 0x9380, 0xE655, 0x9381, 0xE656, 0x9382, 0xE657, 0x9383,
+	0xE658, 0x9384, 0xE659, 0x9385, 0xE65A, 0x9386, 0xE65B, 0x9387,
+	0xE65C, 0x9388, 0xE65D, 0x9389, 0xE65E, 0x938A, 0xE65F, 0x938B,
+	0xE660, 0x938C, 0xE661, 0x938D, 0xE662, 0x938E, 0xE663, 0x9390,
+	0xE664, 0x9391, 0xE665, 0x9392, 0xE666, 0x9393, 0xE667, 0x9394,
+	0xE668, 0x9395, 0xE669, 0x9396, 0xE66A, 0x9397, 0xE66B, 0x9398,
+	0xE66C, 0x9399, 0xE66D, 0x939A, 0xE66E, 0x939B, 0xE66F, 0x939C,
+	0xE670, 0x939D, 0xE671, 0x939E, 0xE672, 0x939F, 0xE673, 0x93A0,
+	0xE674, 0x93A1, 0xE675, 0x93A2, 0xE676, 0x93A3, 0xE677, 0x93A4,
+	0xE678, 0x93A5, 0xE679, 0x93A6, 0xE67A, 0x93A7, 0xE67B, 0x93A8,
+	0xE67C, 0x93A9, 0xE67D, 0x93AA, 0xE67E, 0x93AB, 0xE680, 0x93AC,
+	0xE681, 0x93AD, 0xE682, 0x93AE, 0xE683, 0x93AF, 0xE684, 0x93B0,
+	0xE685, 0x93B1, 0xE686, 0x93B2, 0xE687, 0x93B3, 0xE688, 0x93B4,
+	0xE689, 0x93B5, 0xE68A, 0x93B6, 0xE68B, 0x93B7, 0xE68C, 0x93B8,
+	0xE68D, 0x93B9, 0xE68E, 0x93BA, 0xE68F, 0x93BB, 0xE690, 0x93BC,
+	0xE691, 0x93BD, 0xE692, 0x93BE, 0xE693, 0x93BF, 0xE694, 0x93C0,
+	0xE695, 0x93C1, 0xE696, 0x93C2, 0xE697, 0x93C3, 0xE698, 0x93C4,
+	0xE699, 0x93C5, 0xE69A, 0x93C6, 0xE69B, 0x93C7, 0xE69C, 0x93C8,
+	0xE69D, 0x93C9, 0xE69E, 0x93CB, 0xE69F, 0x93CC, 0xE6A0, 0x93CD,
+	0xE6A1, 0x5997, 0xE6A2, 0x59CA, 0xE6A3, 0x59AB, 0xE6A4, 0x599E,
+	0xE6A5, 0x59A4, 0xE6A6, 0x59D2, 0xE6A7, 0x59B2, 0xE6A8, 0x59AF,
+	0xE6A9, 0x59D7, 0xE6AA, 0x59BE, 0xE6AB, 0x5A05, 0xE6AC, 0x5A06,
+	0xE6AD, 0x59DD, 0xE6AE, 0x5A08, 0xE6AF, 0x59E3, 0xE6B0, 0x59D8,
+	0xE6B1, 0x59F9, 0xE6B2, 0x5A0C, 0xE6B3, 0x5A09, 0xE6B4, 0x5A32,
+	0xE6B5, 0x5A34, 0xE6B6, 0x5A11, 0xE6B7, 0x5A23, 0xE6B8, 0x5A13,
+	0xE6B9, 0x5A40, 0xE6BA, 0x5A67, 0xE6BB, 0x5A4A, 0xE6BC, 0x5A55,
+	0xE6BD, 0x5A3C, 0xE6BE, 0x5A62, 0xE6BF, 0x5A75, 0xE6C0, 0x80EC,
+	0xE6C1, 0x5AAA, 0xE6C2, 0x5A9B, 0xE6C3, 0x5A77, 0xE6C4, 0x5A7A,
+	0xE6C5, 0x5ABE, 0xE6C6, 0x5AEB, 0xE6C7, 0x5AB2, 0xE6C8, 0x5AD2,
+	0xE6C9, 0x5AD4, 0xE6CA, 0x5AB8, 0xE6CB, 0x5AE0, 0xE6CC, 0x5AE3,
+	0xE6CD, 0x5AF1, 0xE6CE, 0x5AD6, 0xE6CF, 0x5AE6, 0xE6D0, 0x5AD8,
+	0xE6D1, 0x5ADC, 0xE6D2, 0x5B09, 0xE6D3, 0x5B17, 0xE6D4, 0x5B16,
+	0xE6D5, 0x5B32, 0xE6D6, 0x5B37, 0xE6D7, 0x5B40, 0xE6D8, 0x5C15,
+	0xE6D9, 0x5C1C, 0xE6DA, 0x5B5A, 0xE6DB, 0x5B65, 0xE6DC, 0x5B73,
+	0xE6DD, 0x5B51, 0xE6DE, 0x5B53, 0xE6DF, 0x5B62, 0xE6E0, 0x9A75,
+	0xE6E1, 0x9A77, 0xE6E2, 0x9A78, 0xE6E3, 0x9A7A, 0xE6E4, 0x9A7F,
+	0xE6E5, 0x9A7D, 0xE6E6, 0x9A80, 0xE6E7, 0x9A81, 0xE6E8, 0x9A85,
+	0xE6E9, 0x9A88, 0xE6EA, 0x9A8A, 0xE6EB, 0x9A90, 0xE6EC, 0x9A92,
+	0xE6ED, 0x9A93, 0xE6EE, 0x9A96, 0xE6EF, 0x9A98, 0xE6F0, 0x9A9B,
+	0xE6F1, 0x9A9C, 0xE6F2, 0x9A9D, 0xE6F3, 0x9A9F, 0xE6F4, 0x9AA0,
+	0xE6F5, 0x9AA2, 0xE6F6, 0x9AA3, 0xE6F7, 0x9AA5, 0xE6F8, 0x9AA7,
+	0xE6F9, 0x7E9F, 0xE6FA, 0x7EA1, 0xE6FB, 0x7EA3, 0xE6FC, 0x7EA5,
+	0xE6FD, 0x7EA8, 0xE6FE, 0x7EA9, 0xE740, 0x93CE, 0xE741, 0x93CF,
+	0xE742, 0x93D0, 0xE743, 0x93D1, 0xE744, 0x93D2, 0xE745, 0x93D3,
+	0xE746, 0x93D4, 0xE747, 0x93D5, 0xE748, 0x93D7, 0xE749, 0x93D8,
+	0xE74A, 0x93D9, 0xE74B, 0x93DA, 0xE74C, 0x93DB, 0xE74D, 0x93DC,
+	0xE74E, 0x93DD, 0xE74F, 0x93DE, 0xE750, 0x93DF, 0xE751, 0x93E0,
+	0xE752, 0x93E1, 0xE753, 0x93E2, 0xE754, 0x93E3, 0xE755, 0x93E4,
+	0xE756, 0x93E5, 0xE757, 0x93E6, 0xE758, 0x93E7, 0xE759, 0x93E8,
+	0xE75A, 0x93E9, 0xE75B, 0x93EA, 0xE75C, 0x93EB, 0xE75D, 0x93EC,
+	0xE75E, 0x93ED, 0xE75F, 0x93EE, 0xE760, 0x93EF, 0xE761, 0x93F0,
+	0xE762, 0x93F1, 0xE763, 0x93F2, 0xE764, 0x93F3, 0xE765, 0x93F4,
+	0xE766, 0x93F5, 0xE767, 0x93F6, 0xE768, 0x93F7, 0xE769, 0x93F8,
+	0xE76A, 0x93F9, 0xE76B, 0x93FA, 0xE76C, 0x93FB, 0xE76D, 0x93FC,
+	0xE76E, 0x93FD, 0xE76F, 0x93FE, 0xE770, 0x93FF, 0xE771, 0x9400,
+	0xE772, 0x9401, 0xE773, 0x9402, 0xE774, 0x9403, 0xE775, 0x9404,
+	0xE776, 0x9405, 0xE777, 0x9406, 0xE778, 0x9407, 0xE779, 0x9408,
+	0xE77A, 0x9409, 0xE77B, 0x940A, 0xE77C, 0x940B, 0xE77D, 0x940C,
+	0xE77E, 0x940D, 0xE780, 0x940E, 0xE781, 0x940F, 0xE782, 0x9410,
+	0xE783, 0x9411, 0xE784, 0x9412, 0xE785, 0x9413, 0xE786, 0x9414,
+	0xE787, 0x9415, 0xE788, 0x9416, 0xE789, 0x9417, 0xE78A, 0x9418,
+	0xE78B, 0x9419, 0xE78C, 0x941A, 0xE78D, 0x941B, 0xE78E, 0x941C,
+	0xE78F, 0x941D, 0xE790, 0x941E, 0xE791, 0x941F, 0xE792, 0x9420,
+	0xE793, 0x9421, 0xE794, 0x9422, 0xE795, 0x9423, 0xE796, 0x9424,
+	0xE797, 0x9425, 0xE798, 0x9426, 0xE799, 0x9427, 0xE79A, 0x9428,
+	0xE79B, 0x9429, 0xE79C, 0x942A, 0xE79D, 0x942B, 0xE79E, 0x942C,
+	0xE79F, 0x942D, 0xE7A0, 0x942E, 0xE7A1, 0x7EAD, 0xE7A2, 0x7EB0,
+	0xE7A3, 0x7EBE, 0xE7A4, 0x7EC0, 0xE7A5, 0x7EC1, 0xE7A6, 0x7EC2,
+	0xE7A7, 0x7EC9, 0xE7A8, 0x7ECB, 0xE7A9, 0x7ECC, 0xE7AA, 0x7ED0,
+	0xE7AB, 0x7ED4, 0xE7AC, 0x7ED7, 0xE7AD, 0x7EDB, 0xE7AE, 0x7EE0,
+	0xE7AF, 0x7EE1, 0xE7B0, 0x7EE8, 0xE7B1, 0x7EEB, 0xE7B2, 0x7EEE,
+	0xE7B3, 0x7EEF, 0xE7B4, 0x7EF1, 0xE7B5, 0x7EF2, 0xE7B6, 0x7F0D,
+	0xE7B7, 0x7EF6, 0xE7B8, 0x7EFA, 0xE7B9, 0x7EFB, 0xE7BA, 0x7EFE,
+	0xE7BB, 0x7F01, 0xE7BC, 0x7F02, 0xE7BD, 0x7F03, 0xE7BE, 0x7F07,
+	0xE7BF, 0x7F08, 0xE7C0, 0x7F0B, 0xE7C1, 0x7F0C, 0xE7C2, 0x7F0F,
+	0xE7C3, 0x7F11, 0xE7C4, 0x7F12, 0xE7C5, 0x7F17, 0xE7C6, 0x7F19,
+	0xE7C7, 0x7F1C, 0xE7C8, 0x7F1B, 0xE7C9, 0x7F1F, 0xE7CA, 0x7F21,
+	0xE7CB, 0x7F22, 0xE7CC, 0x7F23, 0xE7CD, 0x7F24, 0xE7CE, 0x7F25,
+	0xE7CF, 0x7F26, 0xE7D0, 0x7F27, 0xE7D1, 0x7F2A, 0xE7D2, 0x7F2B,
+	0xE7D3, 0x7F2C, 0xE7D4, 0x7F2D, 0xE7D5, 0x7F2F, 0xE7D6, 0x7F30,
+	0xE7D7, 0x7F31, 0xE7D8, 0x7F32, 0xE7D9, 0x7F33, 0xE7DA, 0x7F35,
+	0xE7DB, 0x5E7A, 0xE7DC, 0x757F, 0xE7DD, 0x5DDB, 0xE7DE, 0x753E,
+	0xE7DF, 0x9095, 0xE7E0, 0x738E, 0xE7E1, 0x7391, 0xE7E2, 0x73AE,
+	0xE7E3, 0x73A2, 0xE7E4, 0x739F, 0xE7E5, 0x73CF, 0xE7E6, 0x73C2,
+	0xE7E7, 0x73D1, 0xE7E8, 0x73B7, 0xE7E9, 0x73B3, 0xE7EA, 0x73C0,
+	0xE7EB, 0x73C9, 0xE7EC, 0x73C8, 0xE7ED, 0x73E5, 0xE7EE, 0x73D9,
+	0xE7EF, 0x987C, 0xE7F0, 0x740A, 0xE7F1, 0x73E9, 0xE7F2, 0x73E7,
+	0xE7F3, 0x73DE, 0xE7F4, 0x73BA, 0xE7F5, 0x73F2, 0xE7F6, 0x740F,
+	0xE7F7, 0x742A, 0xE7F8, 0x745B, 0xE7F9, 0x7426, 0xE7FA, 0x7425,
+	0xE7FB, 0x7428, 0xE7FC, 0x7430, 0xE7FD, 0x742E, 0xE7FE, 0x742C,
+	0xE840, 0x942F, 0xE841, 0x9430, 0xE842, 0x9431, 0xE843, 0x9432,
+	0xE844, 0x9433, 0xE845, 0x9434, 0xE846, 0x9435, 0xE847, 0x9436,
+	0xE848, 0x9437, 0xE849, 0x9438, 0xE84A, 0x9439, 0xE84B, 0x943A,
+	0xE84C, 0x943B, 0xE84D, 0x943C, 0xE84E, 0x943D, 0xE84F, 0x943F,
+	0xE850, 0x9440, 0xE851, 0x9441, 0xE852, 0x9442, 0xE853, 0x9443,
+	0xE854, 0x9444, 0xE855, 0x9445, 0xE856, 0x9446, 0xE857, 0x9447,
+	0xE858, 0x9448, 0xE859, 0x9449, 0xE85A, 0x944A, 0xE85B, 0x944B,
+	0xE85C, 0x944C, 0xE85D, 0x944D, 0xE85E, 0x944E, 0xE85F, 0x944F,
+	0xE860, 0x9450, 0xE861, 0x9451, 0xE862, 0x9452, 0xE863, 0x9453,
+	0xE864, 0x9454, 0xE865, 0x9455, 0xE866, 0x9456, 0xE867, 0x9457,
+	0xE868, 0x9458, 0xE869, 0x9459, 0xE86A, 0x945A, 0xE86B, 0x945B,
+	0xE86C, 0x945C, 0xE86D, 0x945D, 0xE86E, 0x945E, 0xE86F, 0x945F,
+	0xE870, 0x9460, 0xE871, 0x9461, 0xE872, 0x9462, 0xE873, 0x9463,
+	0xE874, 0x9464, 0xE875, 0x9465, 0xE876, 0x9466, 0xE877, 0x9467,
+	0xE878, 0x9468, 0xE879, 0x9469, 0xE87A, 0x946A, 0xE87B, 0x946C,
+	0xE87C, 0x946D, 0xE87D, 0x946E, 0xE87E, 0x946F, 0xE880, 0x9470,
+	0xE881, 0x9471, 0xE882, 0x9472, 0xE883, 0x9473, 0xE884, 0x9474,
+	0xE885, 0x9475, 0xE886, 0x9476, 0xE887, 0x9477, 0xE888, 0x9478,
+	0xE889, 0x9479, 0xE88A, 0x947A, 0xE88B, 0x947B, 0xE88C, 0x947C,
+	0xE88D, 0x947D, 0xE88E, 0x947E, 0xE88F, 0x947F, 0xE890, 0x9480,
+	0xE891, 0x9481, 0xE892, 0x9482, 0xE893, 0x9483, 0xE894, 0x9484,
+	0xE895, 0x9491, 0xE896, 0x9496, 0xE897, 0x9498, 0xE898, 0x94C7,
+	0xE899, 0x94CF, 0xE89A, 0x94D3, 0xE89B, 0x94D4, 0xE89C, 0x94DA,
+	0xE89D, 0x94E6, 0xE89E, 0x94FB, 0xE89F, 0x951C, 0xE8A0, 0x9520,
+	0xE8A1, 0x741B, 0xE8A2, 0x741A, 0xE8A3, 0x7441, 0xE8A4, 0x745C,
+	0xE8A5, 0x7457, 0xE8A6, 0x7455, 0xE8A7, 0x7459, 0xE8A8, 0x7477,
+	0xE8A9, 0x746D, 0xE8AA, 0x747E, 0xE8AB, 0x749C, 0xE8AC, 0x748E,
+	0xE8AD, 0x7480, 0xE8AE, 0x7481, 0xE8AF, 0x7487, 0xE8B0, 0x748B,
+	0xE8B1, 0x749E, 0xE8B2, 0x74A8, 0xE8B3, 0x74A9, 0xE8B4, 0x7490,
+	0xE8B5, 0x74A7, 0xE8B6, 0x74D2, 0xE8B7, 0x74BA, 0xE8B8, 0x97EA,
+	0xE8B9, 0x97EB, 0xE8BA, 0x97EC, 0xE8BB, 0x674C, 0xE8BC, 0x6753,
+	0xE8BD, 0x675E, 0xE8BE, 0x6748, 0xE8BF, 0x6769, 0xE8C0, 0x67A5,
+	0xE8C1, 0x6787, 0xE8C2, 0x676A, 0xE8C3, 0x6773, 0xE8C4, 0x6798,
+	0xE8C5, 0x67A7, 0xE8C6, 0x6775, 0xE8C7, 0x67A8, 0xE8C8, 0x679E,
+	0xE8C9, 0x67AD, 0xE8CA, 0x678B, 0xE8CB, 0x6777, 0xE8CC, 0x677C,
+	0xE8CD, 0x67F0, 0xE8CE, 0x6809, 0xE8CF, 0x67D8, 0xE8D0, 0x680A,
+	0xE8D1, 0x67E9, 0xE8D2, 0x67B0, 0xE8D3, 0x680C, 0xE8D4, 0x67D9,
+	0xE8D5, 0x67B5, 0xE8D6, 0x67DA, 0xE8D7, 0x67B3, 0xE8D8, 0x67DD,
+	0xE8D9, 0x6800, 0xE8DA, 0x67C3, 0xE8DB, 0x67B8, 0xE8DC, 0x67E2,
+	0xE8DD, 0x680E, 0xE8DE, 0x67C1, 0xE8DF, 0x67FD, 0xE8E0, 0x6832,
+	0xE8E1, 0x6833, 0xE8E2, 0x6860, 0xE8E3, 0x6861, 0xE8E4, 0x684E,
+	0xE8E5, 0x6862, 0xE8E6, 0x6844, 0xE8E7, 0x6864, 0xE8E8, 0x6883,
+	0xE8E9, 0x681D, 0xE8EA, 0x6855, 0xE8EB, 0x6866, 0xE8EC, 0x6841,
+	0xE8ED, 0x6867, 0xE8EE, 0x6840, 0xE8EF, 0x683E, 0xE8F0, 0x684A,
+	0xE8F1, 0x6849, 0xE8F2, 0x6829, 0xE8F3, 0x68B5, 0xE8F4, 0x688F,
+	0xE8F5, 0x6874, 0xE8F6, 0x6877, 0xE8F7, 0x6893, 0xE8F8, 0x686B,
+	0xE8F9, 0x68C2, 0xE8FA, 0x696E, 0xE8FB, 0x68FC, 0xE8FC, 0x691F,
+	0xE8FD, 0x6920, 0xE8FE, 0x68F9, 0xE940, 0x9527, 0xE941, 0x9533,
+	0xE942, 0x953D, 0xE943, 0x9543, 0xE944, 0x9548, 0xE945, 0x954B,
+	0xE946, 0x9555, 0xE947, 0x955A, 0xE948, 0x9560, 0xE949, 0x956E,
+	0xE94A, 0x9574, 0xE94B, 0x9575, 0xE94C, 0x9577, 0xE94D, 0x9578,
+	0xE94E, 0x9579, 0xE94F, 0x957A, 0xE950, 0x957B, 0xE951, 0x957C,
+	0xE952, 0x957D, 0xE953, 0x957E, 0xE954, 0x9580, 0xE955, 0x9581,
+	0xE956, 0x9582, 0xE957, 0x9583, 0xE958, 0x9584, 0xE959, 0x9585,
+	0xE95A, 0x9586, 0xE95B, 0x9587, 0xE95C, 0x9588, 0xE95D, 0x9589,
+	0xE95E, 0x958A, 0xE95F, 0x958B, 0xE960, 0x958C, 0xE961, 0x958D,
+	0xE962, 0x958E, 0xE963, 0x958F, 0xE964, 0x9590, 0xE965, 0x9591,
+	0xE966, 0x9592, 0xE967, 0x9593, 0xE968, 0x9594, 0xE969, 0x9595,
+	0xE96A, 0x9596, 0xE96B, 0x9597, 0xE96C, 0x9598, 0xE96D, 0x9599,
+	0xE96E, 0x959A, 0xE96F, 0x959B, 0xE970, 0x959C, 0xE971, 0x959D,
+	0xE972, 0x959E, 0xE973, 0x959F, 0xE974, 0x95A0, 0xE975, 0x95A1,
+	0xE976, 0x95A2, 0xE977, 0x95A3, 0xE978, 0x95A4, 0xE979, 0x95A5,
+	0xE97A, 0x95A6, 0xE97B, 0x95A7, 0xE97C, 0x95A8, 0xE97D, 0x95A9,
+	0xE97E, 0x95AA, 0xE980, 0x95AB, 0xE981, 0x95AC, 0xE982, 0x95AD,
+	0xE983, 0x95AE, 0xE984, 0x95AF, 0xE985, 0x95B0, 0xE986, 0x95B1,
+	0xE987, 0x95B2, 0xE988, 0x95B3, 0xE989, 0x95B4, 0xE98A, 0x95B5,
+	0xE98B, 0x95B6, 0xE98C, 0x95B7, 0xE98D, 0x95B8, 0xE98E, 0x95B9,
+	0xE98F, 0x95BA, 0xE990, 0x95BB, 0xE991, 0x95BC, 0xE992, 0x95BD,
+	0xE993, 0x95BE, 0xE994, 0x95BF, 0xE995, 0x95C0, 0xE996, 0x95C1,
+	0xE997, 0x95C2, 0xE998, 0x95C3, 0xE999, 0x95C4, 0xE99A, 0x95C5,
+	0xE99B, 0x95C6, 0xE99C, 0x95C7, 0xE99D, 0x95C8, 0xE99E, 0x95C9,
+	0xE99F, 0x95CA, 0xE9A0, 0x95CB, 0xE9A1, 0x6924, 0xE9A2, 0x68F0,
+	0xE9A3, 0x690B, 0xE9A4, 0x6901, 0xE9A5, 0x6957, 0xE9A6, 0x68E3,
+	0xE9A7, 0x6910, 0xE9A8, 0x6971, 0xE9A9, 0x6939, 0xE9AA, 0x6960,
+	0xE9AB, 0x6942, 0xE9AC, 0x695D, 0xE9AD, 0x6984, 0xE9AE, 0x696B,
+	0xE9AF, 0x6980, 0xE9B0, 0x6998, 0xE9B1, 0x6978, 0xE9B2, 0x6934,
+	0xE9B3, 0x69CC, 0xE9B4, 0x6987, 0xE9B5, 0x6988, 0xE9B6, 0x69CE,
+	0xE9B7, 0x6989, 0xE9B8, 0x6966, 0xE9B9, 0x6963, 0xE9BA, 0x6979,
+	0xE9BB, 0x699B, 0xE9BC, 0x69A7, 0xE9BD, 0x69BB, 0xE9BE, 0x69AB,
+	0xE9BF, 0x69AD, 0xE9C0, 0x69D4, 0xE9C1, 0x69B1, 0xE9C2, 0x69C1,
+	0xE9C3, 0x69CA, 0xE9C4, 0x69DF, 0xE9C5, 0x6995, 0xE9C6, 0x69E0,
+	0xE9C7, 0x698D, 0xE9C8, 0x69FF, 0xE9C9, 0x6A2F, 0xE9CA, 0x69ED,
+	0xE9CB, 0x6A17, 0xE9CC, 0x6A18, 0xE9CD, 0x6A65, 0xE9CE, 0x69F2,
+	0xE9CF, 0x6A44, 0xE9D0, 0x6A3E, 0xE9D1, 0x6AA0, 0xE9D2, 0x6A50,
+	0xE9D3, 0x6A5B, 0xE9D4, 0x6A35, 0xE9D5, 0x6A8E, 0xE9D6, 0x6A79,
+	0xE9D7, 0x6A3D, 0xE9D8, 0x6A28, 0xE9D9, 0x6A58, 0xE9DA, 0x6A7C,
+	0xE9DB, 0x6A91, 0xE9DC, 0x6A90, 0xE9DD, 0x6AA9, 0xE9DE, 0x6A97,
+	0xE9DF, 0x6AAB, 0xE9E0, 0x7337, 0xE9E1, 0x7352, 0xE9E2, 0x6B81,
+	0xE9E3, 0x6B82, 0xE9E4, 0x6B87, 0xE9E5, 0x6B84, 0xE9E6, 0x6B92,
+	0xE9E7, 0x6B93, 0xE9E8, 0x6B8D, 0xE9E9, 0x6B9A, 0xE9EA, 0x6B9B,
+	0xE9EB, 0x6BA1, 0xE9EC, 0x6BAA, 0xE9ED, 0x8F6B, 0xE9EE, 0x8F6D,
+	0xE9EF, 0x8F71, 0xE9F0, 0x8F72, 0xE9F1, 0x8F73, 0xE9F2, 0x8F75,
+	0xE9F3, 0x8F76, 0xE9F4, 0x8F78, 0xE9F5, 0x8F77, 0xE9F6, 0x8F79,
+	0xE9F7, 0x8F7A, 0xE9F8, 0x8F7C, 0xE9F9, 0x8F7E, 0xE9FA, 0x8F81,
+	0xE9FB, 0x8F82, 0xE9FC, 0x8F84, 0xE9FD, 0x8F87, 0xE9FE, 0x8F8B,
+	0xEA40, 0x95CC, 0xEA41, 0x95CD, 0xEA42, 0x95CE, 0xEA43, 0x95CF,
+	0xEA44, 0x95D0, 0xEA45, 0x95D1, 0xEA46, 0x95D2, 0xEA47, 0x95D3,
+	0xEA48, 0x95D4, 0xEA49, 0x95D5, 0xEA4A, 0x95D6, 0xEA4B, 0x95D7,
+	0xEA4C, 0x95D8, 0xEA4D, 0x95D9, 0xEA4E, 0x95DA, 0xEA4F, 0x95DB,
+	0xEA50, 0x95DC, 0xEA51, 0x95DD, 0xEA52, 0x95DE, 0xEA53, 0x95DF,
+	0xEA54, 0x95E0, 0xEA55, 0x95E1, 0xEA56, 0x95E2, 0xEA57, 0x95E3,
+	0xEA58, 0x95E4, 0xEA59, 0x95E5, 0xEA5A, 0x95E6, 0xEA5B, 0x95E7,
+	0xEA5C, 0x95EC, 0xEA5D, 0x95FF, 0xEA5E, 0x9607, 0xEA5F, 0x9613,
+	0xEA60, 0x9618, 0xEA61, 0x961B, 0xEA62, 0x961E, 0xEA63, 0x9620,
+	0xEA64, 0x9623, 0xEA65, 0x9624, 0xEA66, 0x9625, 0xEA67, 0x9626,
+	0xEA68, 0x9627, 0xEA69, 0x9628, 0xEA6A, 0x9629, 0xEA6B, 0x962B,
+	0xEA6C, 0x962C, 0xEA6D, 0x962D, 0xEA6E, 0x962F, 0xEA6F, 0x9630,
+	0xEA70, 0x9637, 0xEA71, 0x9638, 0xEA72, 0x9639, 0xEA73, 0x963A,
+	0xEA74, 0x963E, 0xEA75, 0x9641, 0xEA76, 0x9643, 0xEA77, 0x964A,
+	0xEA78, 0x964E, 0xEA79, 0x964F, 0xEA7A, 0x9651, 0xEA7B, 0x9652,
+	0xEA7C, 0x9653, 0xEA7D, 0x9656, 0xEA7E, 0x9657, 0xEA80, 0x9658,
+	0xEA81, 0x9659, 0xEA82, 0x965A, 0xEA83, 0x965C, 0xEA84, 0x965D,
+	0xEA85, 0x965E, 0xEA86, 0x9660, 0xEA87, 0x9663, 0xEA88, 0x9665,
+	0xEA89, 0x9666, 0xEA8A, 0x966B, 0xEA8B, 0x966D, 0xEA8C, 0x966E,
+	0xEA8D, 0x966F, 0xEA8E, 0x9670, 0xEA8F, 0x9671, 0xEA90, 0x9673,
+	0xEA91, 0x9678, 0xEA92, 0x9679, 0xEA93, 0x967A, 0xEA94, 0x967B,
+	0xEA95, 0x967C, 0xEA96, 0x967D, 0xEA97, 0x967E, 0xEA98, 0x967F,
+	0xEA99, 0x9680, 0xEA9A, 0x9681, 0xEA9B, 0x9682, 0xEA9C, 0x9683,
+	0xEA9D, 0x9684, 0xEA9E, 0x9687, 0xEA9F, 0x9689, 0xEAA0, 0x968A,
+	0xEAA1, 0x8F8D, 0xEAA2, 0x8F8E, 0xEAA3, 0x8F8F, 0xEAA4, 0x8F98,
+	0xEAA5, 0x8F9A, 0xEAA6, 0x8ECE, 0xEAA7, 0x620B, 0xEAA8, 0x6217,
+	0xEAA9, 0x621B, 0xEAAA, 0x621F, 0xEAAB, 0x6222, 0xEAAC, 0x6221,
+	0xEAAD, 0x6225, 0xEAAE, 0x6224, 0xEAAF, 0x622C, 0xEAB0, 0x81E7,
+	0xEAB1, 0x74EF, 0xEAB2, 0x74F4, 0xEAB3, 0x74FF, 0xEAB4, 0x750F,
+	0xEAB5, 0x7511, 0xEAB6, 0x7513, 0xEAB7, 0x6534, 0xEAB8, 0x65EE,
+	0xEAB9, 0x65EF, 0xEABA, 0x65F0, 0xEABB, 0x660A, 0xEABC, 0x6619,
+	0xEABD, 0x6772, 0xEABE, 0x6603, 0xEABF, 0x6615, 0xEAC0, 0x6600,
+	0xEAC1, 0x7085, 0xEAC2, 0x66F7, 0xEAC3, 0x661D, 0xEAC4, 0x6634,
+	0xEAC5, 0x6631, 0xEAC6, 0x6636, 0xEAC7, 0x6635, 0xEAC8, 0x8006,
+	0xEAC9, 0x665F, 0xEACA, 0x6654, 0xEACB, 0x6641, 0xEACC, 0x664F,
+	0xEACD, 0x6656, 0xEACE, 0x6661, 0xEACF, 0x6657, 0xEAD0, 0x6677,
+	0xEAD1, 0x6684, 0xEAD2, 0x668C, 0xEAD3, 0x66A7, 0xEAD4, 0x669D,
+	0xEAD5, 0x66BE, 0xEAD6, 0x66DB, 0xEAD7, 0x66DC, 0xEAD8, 0x66E6,
+	0xEAD9, 0x66E9, 0xEADA, 0x8D32, 0xEADB, 0x8D33, 0xEADC, 0x8D36,
+	0xEADD, 0x8D3B, 0xEADE, 0x8D3D, 0xEADF, 0x8D40, 0xEAE0, 0x8D45,
+	0xEAE1, 0x8D46, 0xEAE2, 0x8D48, 0xEAE3, 0x8D49, 0xEAE4, 0x8D47,
+	0xEAE5, 0x8D4D, 0xEAE6, 0x8D55, 0xEAE7, 0x8D59, 0xEAE8, 0x89C7,
+	0xEAE9, 0x89CA, 0xEAEA, 0x89CB, 0xEAEB, 0x89CC, 0xEAEC, 0x89CE,
+	0xEAED, 0x89CF, 0xEAEE, 0x89D0, 0xEAEF, 0x89D1, 0xEAF0, 0x726E,
+	0xEAF1, 0x729F, 0xEAF2, 0x725D, 0xEAF3, 0x7266, 0xEAF4, 0x726F,
+	0xEAF5, 0x727E, 0xEAF6, 0x727F, 0xEAF7, 0x7284, 0xEAF8, 0x728B,
+	0xEAF9, 0x728D, 0xEAFA, 0x728F, 0xEAFB, 0x7292, 0xEAFC, 0x6308,
+	0xEAFD, 0x6332, 0xEAFE, 0x63B0, 0xEB40, 0x968C, 0xEB41, 0x968E,
+	0xEB42, 0x9691, 0xEB43, 0x9692, 0xEB44, 0x9693, 0xEB45, 0x9695,
+	0xEB46, 0x9696, 0xEB47, 0x969A, 0xEB48, 0x969B, 0xEB49, 0x969D,
+	0xEB4A, 0x969E, 0xEB4B, 0x969F, 0xEB4C, 0x96A0, 0xEB4D, 0x96A1,
+	0xEB4E, 0x96A2, 0xEB4F, 0x96A3, 0xEB50, 0x96A4, 0xEB51, 0x96A5,
+	0xEB52, 0x96A6, 0xEB53, 0x96A8, 0xEB54, 0x96A9, 0xEB55, 0x96AA,
+	0xEB56, 0x96AB, 0xEB57, 0x96AC, 0xEB58, 0x96AD, 0xEB59, 0x96AE,
+	0xEB5A, 0x96AF, 0xEB5B, 0x96B1, 0xEB5C, 0x96B2, 0xEB5D, 0x96B4,
+	0xEB5E, 0x96B5, 0xEB5F, 0x96B7, 0xEB60, 0x96B8, 0xEB61, 0x96BA,
+	0xEB62, 0x96BB, 0xEB63, 0x96BF, 0xEB64, 0x96C2, 0xEB65, 0x96C3,
+	0xEB66, 0x96C8, 0xEB67, 0x96CA, 0xEB68, 0x96CB, 0xEB69, 0x96D0,
+	0xEB6A, 0x96D1, 0xEB6B, 0x96D3, 0xEB6C, 0x96D4, 0xEB6D, 0x96D6,
+	0xEB6E, 0x96D7, 0xEB6F, 0x96D8, 0xEB70, 0x96D9, 0xEB71, 0x96DA,
+	0xEB72, 0x96DB, 0xEB73, 0x96DC, 0xEB74, 0x96DD, 0xEB75, 0x96DE,
+	0xEB76, 0x96DF, 0xEB77, 0x96E1, 0xEB78, 0x96E2, 0xEB79, 0x96E3,
+	0xEB7A, 0x96E4, 0xEB7B, 0x96E5, 0xEB7C, 0x96E6, 0xEB7D, 0x96E7,
+	0xEB7E, 0x96EB, 0xEB80, 0x96EC, 0xEB81, 0x96ED, 0xEB82, 0x96EE,
+	0xEB83, 0x96F0, 0xEB84, 0x96F1, 0xEB85, 0x96F2, 0xEB86, 0x96F4,
+	0xEB87, 0x96F5, 0xEB88, 0x96F8, 0xEB89, 0x96FA, 0xEB8A, 0x96FB,
+	0xEB8B, 0x96FC, 0xEB8C, 0x96FD, 0xEB8D, 0x96FF, 0xEB8E, 0x9702,
+	0xEB8F, 0x9703, 0xEB90, 0x9705, 0xEB91, 0x970A, 0xEB92, 0x970B,
+	0xEB93, 0x970C, 0xEB94, 0x9710, 0xEB95, 0x9711, 0xEB96, 0x9712,
+	0xEB97, 0x9714, 0xEB98, 0x9715, 0xEB99, 0x9717, 0xEB9A, 0x9718,
+	0xEB9B, 0x9719, 0xEB9C, 0x971A, 0xEB9D, 0x971B, 0xEB9E, 0x971D,
+	0xEB9F, 0x971F, 0xEBA0, 0x9720, 0xEBA1, 0x643F, 0xEBA2, 0x64D8,
+	0xEBA3, 0x8004, 0xEBA4, 0x6BEA, 0xEBA5, 0x6BF3, 0xEBA6, 0x6BFD,
+	0xEBA7, 0x6BF5, 0xEBA8, 0x6BF9, 0xEBA9, 0x6C05, 0xEBAA, 0x6C07,
+	0xEBAB, 0x6C06, 0xEBAC, 0x6C0D, 0xEBAD, 0x6C15, 0xEBAE, 0x6C18,
+	0xEBAF, 0x6C19, 0xEBB0, 0x6C1A, 0xEBB1, 0x6C21, 0xEBB2, 0x6C29,
+	0xEBB3, 0x6C24, 0xEBB4, 0x6C2A, 0xEBB5, 0x6C32, 0xEBB6, 0x6535,
+	0xEBB7, 0x6555, 0xEBB8, 0x656B, 0xEBB9, 0x724D, 0xEBBA, 0x7252,
+	0xEBBB, 0x7256, 0xEBBC, 0x7230, 0xEBBD, 0x8662, 0xEBBE, 0x5216,
+	0xEBBF, 0x809F, 0xEBC0, 0x809C, 0xEBC1, 0x8093, 0xEBC2, 0x80BC,
+	0xEBC3, 0x670A, 0xEBC4, 0x80BD, 0xEBC5, 0x80B1, 0xEBC6, 0x80AB,
+	0xEBC7, 0x80AD, 0xEBC8, 0x80B4, 0xEBC9, 0x80B7, 0xEBCA, 0x80E7,
+	0xEBCB, 0x80E8, 0xEBCC, 0x80E9, 0xEBCD, 0x80EA, 0xEBCE, 0x80DB,
+	0xEBCF, 0x80C2, 0xEBD0, 0x80C4, 0xEBD1, 0x80D9, 0xEBD2, 0x80CD,
+	0xEBD3, 0x80D7, 0xEBD4, 0x6710, 0xEBD5, 0x80DD, 0xEBD6, 0x80EB,
+	0xEBD7, 0x80F1, 0xEBD8, 0x80F4, 0xEBD9, 0x80ED, 0xEBDA, 0x810D,
+	0xEBDB, 0x810E, 0xEBDC, 0x80F2, 0xEBDD, 0x80FC, 0xEBDE, 0x6715,
+	0xEBDF, 0x8112, 0xEBE0, 0x8C5A, 0xEBE1, 0x8136, 0xEBE2, 0x811E,
+	0xEBE3, 0x812C, 0xEBE4, 0x8118, 0xEBE5, 0x8132, 0xEBE6, 0x8148,
+	0xEBE7, 0x814C, 0xEBE8, 0x8153, 0xEBE9, 0x8174, 0xEBEA, 0x8159,
+	0xEBEB, 0x815A, 0xEBEC, 0x8171, 0xEBED, 0x8160, 0xEBEE, 0x8169,
+	0xEBEF, 0x817C, 0xEBF0, 0x817D, 0xEBF1, 0x816D, 0xEBF2, 0x8167,
+	0xEBF3, 0x584D, 0xEBF4, 0x5AB5, 0xEBF5, 0x8188, 0xEBF6, 0x8182,
+	0xEBF7, 0x8191, 0xEBF8, 0x6ED5, 0xEBF9, 0x81A3, 0xEBFA, 0x81AA,
+	0xEBFB, 0x81CC, 0xEBFC, 0x6726, 0xEBFD, 0x81CA, 0xEBFE, 0x81BB,
+	0xEC40, 0x9721, 0xEC41, 0x9722, 0xEC42, 0x9723, 0xEC43, 0x9724,
+	0xEC44, 0x9725, 0xEC45, 0x9726, 0xEC46, 0x9727, 0xEC47, 0x9728,
+	0xEC48, 0x9729, 0xEC49, 0x972B, 0xEC4A, 0x972C, 0xEC4B, 0x972E,
+	0xEC4C, 0x972F, 0xEC4D, 0x9731, 0xEC4E, 0x9733, 0xEC4F, 0x9734,
+	0xEC50, 0x9735, 0xEC51, 0x9736, 0xEC52, 0x9737, 0xEC53, 0x973A,
+	0xEC54, 0x973B, 0xEC55, 0x973C, 0xEC56, 0x973D, 0xEC57, 0x973F,
+	0xEC58, 0x9740, 0xEC59, 0x9741, 0xEC5A, 0x9742, 0xEC5B, 0x9743,
+	0xEC5C, 0x9744, 0xEC5D, 0x9745, 0xEC5E, 0x9746, 0xEC5F, 0x9747,
+	0xEC60, 0x9748, 0xEC61, 0x9749, 0xEC62, 0x974A, 0xEC63, 0x974B,
+	0xEC64, 0x974C, 0xEC65, 0x974D, 0xEC66, 0x974E, 0xEC67, 0x974F,
+	0xEC68, 0x9750, 0xEC69, 0x9751, 0xEC6A, 0x9754, 0xEC6B, 0x9755,
+	0xEC6C, 0x9757, 0xEC6D, 0x9758, 0xEC6E, 0x975A, 0xEC6F, 0x975C,
+	0xEC70, 0x975D, 0xEC71, 0x975F, 0xEC72, 0x9763, 0xEC73, 0x9764,
+	0xEC74, 0x9766, 0xEC75, 0x9767, 0xEC76, 0x9768, 0xEC77, 0x976A,
+	0xEC78, 0x976B, 0xEC79, 0x976C, 0xEC7A, 0x976D, 0xEC7B, 0x976E,
+	0xEC7C, 0x976F, 0xEC7D, 0x9770, 0xEC7E, 0x9771, 0xEC80, 0x9772,
+	0xEC81, 0x9775, 0xEC82, 0x9777, 0xEC83, 0x9778, 0xEC84, 0x9779,
+	0xEC85, 0x977A, 0xEC86, 0x977B, 0xEC87, 0x977D, 0xEC88, 0x977E,
+	0xEC89, 0x977F, 0xEC8A, 0x9780, 0xEC8B, 0x9781, 0xEC8C, 0x9782,
+	0xEC8D, 0x9783, 0xEC8E, 0x9784, 0xEC8F, 0x9786, 0xEC90, 0x9787,
+	0xEC91, 0x9788, 0xEC92, 0x9789, 0xEC93, 0x978A, 0xEC94, 0x978C,
+	0xEC95, 0x978E, 0xEC96, 0x978F, 0xEC97, 0x9790, 0xEC98, 0x9793,
+	0xEC99, 0x9795, 0xEC9A, 0x9796, 0xEC9B, 0x9797, 0xEC9C, 0x9799,
+	0xEC9D, 0x979A, 0xEC9E, 0x979B, 0xEC9F, 0x979C, 0xECA0, 0x979D,
+	0xECA1, 0x81C1, 0xECA2, 0x81A6, 0xECA3, 0x6B24, 0xECA4, 0x6B37,
+	0xECA5, 0x6B39, 0xECA6, 0x6B43, 0xECA7, 0x6B46, 0xECA8, 0x6B59,
+	0xECA9, 0x98D1, 0xECAA, 0x98D2, 0xECAB, 0x98D3, 0xECAC, 0x98D5,
+	0xECAD, 0x98D9, 0xECAE, 0x98DA, 0xECAF, 0x6BB3, 0xECB0, 0x5F40,
+	0xECB1, 0x6BC2, 0xECB2, 0x89F3, 0xECB3, 0x6590, 0xECB4, 0x9F51,
+	0xECB5, 0x6593, 0xECB6, 0x65BC, 0xECB7, 0x65C6, 0xECB8, 0x65C4,
+	0xECB9, 0x65C3, 0xECBA, 0x65CC, 0xECBB, 0x65CE, 0xECBC, 0x65D2,
+	0xECBD, 0x65D6, 0xECBE, 0x7080, 0xECBF, 0x709C, 0xECC0, 0x7096,
+	0xECC1, 0x709D, 0xECC2, 0x70BB, 0xECC3, 0x70C0, 0xECC4, 0x70B7,
+	0xECC5, 0x70AB, 0xECC6, 0x70B1, 0xECC7, 0x70E8, 0xECC8, 0x70CA,
+	0xECC9, 0x7110, 0xECCA, 0x7113, 0xECCB, 0x7116, 0xECCC, 0x712F,
+	0xECCD, 0x7131, 0xECCE, 0x7173, 0xECCF, 0x715C, 0xECD0, 0x7168,
+	0xECD1, 0x7145, 0xECD2, 0x7172, 0xECD3, 0x714A, 0xECD4, 0x7178,
+	0xECD5, 0x717A, 0xECD6, 0x7198, 0xECD7, 0x71B3, 0xECD8, 0x71B5,
+	0xECD9, 0x71A8, 0xECDA, 0x71A0, 0xECDB, 0x71E0, 0xECDC, 0x71D4,
+	0xECDD, 0x71E7, 0xECDE, 0x71F9, 0xECDF, 0x721D, 0xECE0, 0x7228,
+	0xECE1, 0x706C, 0xECE2, 0x7118, 0xECE3, 0x7166, 0xECE4, 0x71B9,
+	0xECE5, 0x623E, 0xECE6, 0x623D, 0xECE7, 0x6243, 0xECE8, 0x6248,
+	0xECE9, 0x6249, 0xECEA, 0x793B, 0xECEB, 0x7940, 0xECEC, 0x7946,
+	0xECED, 0x7949, 0xECEE, 0x795B, 0xECEF, 0x795C, 0xECF0, 0x7953,
+	0xECF1, 0x795A, 0xECF2, 0x7962, 0xECF3, 0x7957, 0xECF4, 0x7960,
+	0xECF5, 0x796F, 0xECF6, 0x7967, 0xECF7, 0x797A, 0xECF8, 0x7985,
+	0xECF9, 0x798A, 0xECFA, 0x799A, 0xECFB, 0x79A7, 0xECFC, 0x79B3,
+	0xECFD, 0x5FD1, 0xECFE, 0x5FD0, 0xED40, 0x979E, 0xED41, 0x979F,
+	0xED42, 0x97A1, 0xED43, 0x97A2, 0xED44, 0x97A4, 0xED45, 0x97A5,
+	0xED46, 0x97A6, 0xED47, 0x97A7, 0xED48, 0x97A8, 0xED49, 0x97A9,
+	0xED4A, 0x97AA, 0xED4B, 0x97AC, 0xED4C, 0x97AE, 0xED4D, 0x97B0,
+	0xED4E, 0x97B1, 0xED4F, 0x97B3, 0xED50, 0x97B5, 0xED51, 0x97B6,
+	0xED52, 0x97B7, 0xED53, 0x97B8, 0xED54, 0x97B9, 0xED55, 0x97BA,
+	0xED56, 0x97BB, 0xED57, 0x97BC, 0xED58, 0x97BD, 0xED59, 0x97BE,
+	0xED5A, 0x97BF, 0xED5B, 0x97C0, 0xED5C, 0x97C1, 0xED5D, 0x97C2,
+	0xED5E, 0x97C3, 0xED5F, 0x97C4, 0xED60, 0x97C5, 0xED61, 0x97C6,
+	0xED62, 0x97C7, 0xED63, 0x97C8, 0xED64, 0x97C9, 0xED65, 0x97CA,
+	0xED66, 0x97CB, 0xED67, 0x97CC, 0xED68, 0x97CD, 0xED69, 0x97CE,
+	0xED6A, 0x97CF, 0xED6B, 0x97D0, 0xED6C, 0x97D1, 0xED6D, 0x97D2,
+	0xED6E, 0x97D3, 0xED6F, 0x97D4, 0xED70, 0x97D5, 0xED71, 0x97D6,
+	0xED72, 0x97D7, 0xED73, 0x97D8, 0xED74, 0x97D9, 0xED75, 0x97DA,
+	0xED76, 0x97DB, 0xED77, 0x97DC, 0xED78, 0x97DD, 0xED79, 0x97DE,
+	0xED7A, 0x97DF, 0xED7B, 0x97E0, 0xED7C, 0x97E1, 0xED7D, 0x97E2,
+	0xED7E, 0x97E3, 0xED80, 0x97E4, 0xED81, 0x97E5, 0xED82, 0x97E8,
+	0xED83, 0x97EE, 0xED84, 0x97EF, 0xED85, 0x97F0, 0xED86, 0x97F1,
+	0xED87, 0x97F2, 0xED88, 0x97F4, 0xED89, 0x97F7, 0xED8A, 0x97F8,
+	0xED8B, 0x97F9, 0xED8C, 0x97FA, 0xED8D, 0x97FB, 0xED8E, 0x97FC,
+	0xED8F, 0x97FD, 0xED90, 0x97FE, 0xED91, 0x97FF, 0xED92, 0x9800,
+	0xED93, 0x9801, 0xED94, 0x9802, 0xED95, 0x9803, 0xED96, 0x9804,
+	0xED97, 0x9805, 0xED98, 0x9806, 0xED99, 0x9807, 0xED9A, 0x9808,
+	0xED9B, 0x9809, 0xED9C, 0x980A, 0xED9D, 0x980B, 0xED9E, 0x980C,
+	0xED9F, 0x980D, 0xEDA0, 0x980E, 0xEDA1, 0x603C, 0xEDA2, 0x605D,
+	0xEDA3, 0x605A, 0xEDA4, 0x6067, 0xEDA5, 0x6041, 0xEDA6, 0x6059,
+	0xEDA7, 0x6063, 0xEDA8, 0x60AB, 0xEDA9, 0x6106, 0xEDAA, 0x610D,
+	0xEDAB, 0x615D, 0xEDAC, 0x61A9, 0xEDAD, 0x619D, 0xEDAE, 0x61CB,
+	0xEDAF, 0x61D1, 0xEDB0, 0x6206, 0xEDB1, 0x8080, 0xEDB2, 0x807F,
+	0xEDB3, 0x6C93, 0xEDB4, 0x6CF6, 0xEDB5, 0x6DFC, 0xEDB6, 0x77F6,
+	0xEDB7, 0x77F8, 0xEDB8, 0x7800, 0xEDB9, 0x7809, 0xEDBA, 0x7817,
+	0xEDBB, 0x7818, 0xEDBC, 0x7811, 0xEDBD, 0x65AB, 0xEDBE, 0x782D,
+	0xEDBF, 0x781C, 0xEDC0, 0x781D, 0xEDC1, 0x7839, 0xEDC2, 0x783A,
+	0xEDC3, 0x783B, 0xEDC4, 0x781F, 0xEDC5, 0x783C, 0xEDC6, 0x7825,
+	0xEDC7, 0x782C, 0xEDC8, 0x7823, 0xEDC9, 0x7829, 0xEDCA, 0x784E,
+	0xEDCB, 0x786D, 0xEDCC, 0x7856, 0xEDCD, 0x7857, 0xEDCE, 0x7826,
+	0xEDCF, 0x7850, 0xEDD0, 0x7847, 0xEDD1, 0x784C, 0xEDD2, 0x786A,
+	0xEDD3, 0x789B, 0xEDD4, 0x7893, 0xEDD5, 0x789A, 0xEDD6, 0x7887,
+	0xEDD7, 0x789C, 0xEDD8, 0x78A1, 0xEDD9, 0x78A3, 0xEDDA, 0x78B2,
+	0xEDDB, 0x78B9, 0xEDDC, 0x78A5, 0xEDDD, 0x78D4, 0xEDDE, 0x78D9,
+	0xEDDF, 0x78C9, 0xEDE0, 0x78EC, 0xEDE1, 0x78F2, 0xEDE2, 0x7905,
+	0xEDE3, 0x78F4, 0xEDE4, 0x7913, 0xEDE5, 0x7924, 0xEDE6, 0x791E,
+	0xEDE7, 0x7934, 0xEDE8, 0x9F9B, 0xEDE9, 0x9EF9, 0xEDEA, 0x9EFB,
+	0xEDEB, 0x9EFC, 0xEDEC, 0x76F1, 0xEDED, 0x7704, 0xEDEE, 0x770D,
+	0xEDEF, 0x76F9, 0xEDF0, 0x7707, 0xEDF1, 0x7708, 0xEDF2, 0x771A,
+	0xEDF3, 0x7722, 0xEDF4, 0x7719, 0xEDF5, 0x772D, 0xEDF6, 0x7726,
+	0xEDF7, 0x7735, 0xEDF8, 0x7738, 0xEDF9, 0x7750, 0xEDFA, 0x7751,
+	0xEDFB, 0x7747, 0xEDFC, 0x7743, 0xEDFD, 0x775A, 0xEDFE, 0x7768,
+	0xEE40, 0x980F, 0xEE41, 0x9810, 0xEE42, 0x9811, 0xEE43, 0x9812,
+	0xEE44, 0x9813, 0xEE45, 0x9814, 0xEE46, 0x9815, 0xEE47, 0x9816,
+	0xEE48, 0x9817, 0xEE49, 0x9818, 0xEE4A, 0x9819, 0xEE4B, 0x981A,
+	0xEE4C, 0x981B, 0xEE4D, 0x981C, 0xEE4E, 0x981D, 0xEE4F, 0x981E,
+	0xEE50, 0x981F, 0xEE51, 0x9820, 0xEE52, 0x9821, 0xEE53, 0x9822,
+	0xEE54, 0x9823, 0xEE55, 0x9824, 0xEE56, 0x9825, 0xEE57, 0x9826,
+	0xEE58, 0x9827, 0xEE59, 0x9828, 0xEE5A, 0x9829, 0xEE5B, 0x982A,
+	0xEE5C, 0x982B, 0xEE5D, 0x982C, 0xEE5E, 0x982D, 0xEE5F, 0x982E,
+	0xEE60, 0x982F, 0xEE61, 0x9830, 0xEE62, 0x9831, 0xEE63, 0x9832,
+	0xEE64, 0x9833, 0xEE65, 0x9834, 0xEE66, 0x9835, 0xEE67, 0x9836,
+	0xEE68, 0x9837, 0xEE69, 0x9838, 0xEE6A, 0x9839, 0xEE6B, 0x983A,
+	0xEE6C, 0x983B, 0xEE6D, 0x983C, 0xEE6E, 0x983D, 0xEE6F, 0x983E,
+	0xEE70, 0x983F, 0xEE71, 0x9840, 0xEE72, 0x9841, 0xEE73, 0x9842,
+	0xEE74, 0x9843, 0xEE75, 0x9844, 0xEE76, 0x9845, 0xEE77, 0x9846,
+	0xEE78, 0x9847, 0xEE79, 0x9848, 0xEE7A, 0x9849, 0xEE7B, 0x984A,
+	0xEE7C, 0x984B, 0xEE7D, 0x984C, 0xEE7E, 0x984D, 0xEE80, 0x984E,
+	0xEE81, 0x984F, 0xEE82, 0x9850, 0xEE83, 0x9851, 0xEE84, 0x9852,
+	0xEE85, 0x9853, 0xEE86, 0x9854, 0xEE87, 0x9855, 0xEE88, 0x9856,
+	0xEE89, 0x9857, 0xEE8A, 0x9858, 0xEE8B, 0x9859, 0xEE8C, 0x985A,
+	0xEE8D, 0x985B, 0xEE8E, 0x985C, 0xEE8F, 0x985D, 0xEE90, 0x985E,
+	0xEE91, 0x985F, 0xEE92, 0x9860, 0xEE93, 0x9861, 0xEE94, 0x9862,
+	0xEE95, 0x9863, 0xEE96, 0x9864, 0xEE97, 0x9865, 0xEE98, 0x9866,
+	0xEE99, 0x9867, 0xEE9A, 0x9868, 0xEE9B, 0x9869, 0xEE9C, 0x986A,
+	0xEE9D, 0x986B, 0xEE9E, 0x986C, 0xEE9F, 0x986D, 0xEEA0, 0x986E,
+	0xEEA1, 0x7762, 0xEEA2, 0x7765, 0xEEA3, 0x777F, 0xEEA4, 0x778D,
+	0xEEA5, 0x777D, 0xEEA6, 0x7780, 0xEEA7, 0x778C, 0xEEA8, 0x7791,
+	0xEEA9, 0x779F, 0xEEAA, 0x77A0, 0xEEAB, 0x77B0, 0xEEAC, 0x77B5,
+	0xEEAD, 0x77BD, 0xEEAE, 0x753A, 0xEEAF, 0x7540, 0xEEB0, 0x754E,
+	0xEEB1, 0x754B, 0xEEB2, 0x7548, 0xEEB3, 0x755B, 0xEEB4, 0x7572,
+	0xEEB5, 0x7579, 0xEEB6, 0x7583, 0xEEB7, 0x7F58, 0xEEB8, 0x7F61,
+	0xEEB9, 0x7F5F, 0xEEBA, 0x8A48, 0xEEBB, 0x7F68, 0xEEBC, 0x7F74,
+	0xEEBD, 0x7F71, 0xEEBE, 0x7F79, 0xEEBF, 0x7F81, 0xEEC0, 0x7F7E,
+	0xEEC1, 0x76CD, 0xEEC2, 0x76E5, 0xEEC3, 0x8832, 0xEEC4, 0x9485,
+	0xEEC5, 0x9486, 0xEEC6, 0x9487, 0xEEC7, 0x948B, 0xEEC8, 0x948A,
+	0xEEC9, 0x948C, 0xEECA, 0x948D, 0xEECB, 0x948F, 0xEECC, 0x9490,
+	0xEECD, 0x9494, 0xEECE, 0x9497, 0xEECF, 0x9495, 0xEED0, 0x949A,
+	0xEED1, 0x949B, 0xEED2, 0x949C, 0xEED3, 0x94A3, 0xEED4, 0x94A4,
+	0xEED5, 0x94AB, 0xEED6, 0x94AA, 0xEED7, 0x94AD, 0xEED8, 0x94AC,
+	0xEED9, 0x94AF, 0xEEDA, 0x94B0, 0xEEDB, 0x94B2, 0xEEDC, 0x94B4,
+	0xEEDD, 0x94B6, 0xEEDE, 0x94B7, 0xEEDF, 0x94B8, 0xEEE0, 0x94B9,
+	0xEEE1, 0x94BA, 0xEEE2, 0x94BC, 0xEEE3, 0x94BD, 0xEEE4, 0x94BF,
+	0xEEE5, 0x94C4, 0xEEE6, 0x94C8, 0xEEE7, 0x94C9, 0xEEE8, 0x94CA,
+	0xEEE9, 0x94CB, 0xEEEA, 0x94CC, 0xEEEB, 0x94CD, 0xEEEC, 0x94CE,
+	0xEEED, 0x94D0, 0xEEEE, 0x94D1, 0xEEEF, 0x94D2, 0xEEF0, 0x94D5,
+	0xEEF1, 0x94D6, 0xEEF2, 0x94D7, 0xEEF3, 0x94D9, 0xEEF4, 0x94D8,
+	0xEEF5, 0x94DB, 0xEEF6, 0x94DE, 0xEEF7, 0x94DF, 0xEEF8, 0x94E0,
+	0xEEF9, 0x94E2, 0xEEFA, 0x94E4, 0xEEFB, 0x94E5, 0xEEFC, 0x94E7,
+	0xEEFD, 0x94E8, 0xEEFE, 0x94EA, 0xEF40, 0x986F, 0xEF41, 0x9870,
+	0xEF42, 0x9871, 0xEF43, 0x9872, 0xEF44, 0x9873, 0xEF45, 0x9874,
+	0xEF46, 0x988B, 0xEF47, 0x988E, 0xEF48, 0x9892, 0xEF49, 0x9895,
+	0xEF4A, 0x9899, 0xEF4B, 0x98A3, 0xEF4C, 0x98A8, 0xEF4D, 0x98A9,
+	0xEF4E, 0x98AA, 0xEF4F, 0x98AB, 0xEF50, 0x98AC, 0xEF51, 0x98AD,
+	0xEF52, 0x98AE, 0xEF53, 0x98AF, 0xEF54, 0x98B0, 0xEF55, 0x98B1,
+	0xEF56, 0x98B2, 0xEF57, 0x98B3, 0xEF58, 0x98B4, 0xEF59, 0x98B5,
+	0xEF5A, 0x98B6, 0xEF5B, 0x98B7, 0xEF5C, 0x98B8, 0xEF5D, 0x98B9,
+	0xEF5E, 0x98BA, 0xEF5F, 0x98BB, 0xEF60, 0x98BC, 0xEF61, 0x98BD,
+	0xEF62, 0x98BE, 0xEF63, 0x98BF, 0xEF64, 0x98C0, 0xEF65, 0x98C1,
+	0xEF66, 0x98C2, 0xEF67, 0x98C3, 0xEF68, 0x98C4, 0xEF69, 0x98C5,
+	0xEF6A, 0x98C6, 0xEF6B, 0x98C7, 0xEF6C, 0x98C8, 0xEF6D, 0x98C9,
+	0xEF6E, 0x98CA, 0xEF6F, 0x98CB, 0xEF70, 0x98CC, 0xEF71, 0x98CD,
+	0xEF72, 0x98CF, 0xEF73, 0x98D0, 0xEF74, 0x98D4, 0xEF75, 0x98D6,
+	0xEF76, 0x98D7, 0xEF77, 0x98DB, 0xEF78, 0x98DC, 0xEF79, 0x98DD,
+	0xEF7A, 0x98E0, 0xEF7B, 0x98E1, 0xEF7C, 0x98E2, 0xEF7D, 0x98E3,
+	0xEF7E, 0x98E4, 0xEF80, 0x98E5, 0xEF81, 0x98E6, 0xEF82, 0x98E9,
+	0xEF83, 0x98EA, 0xEF84, 0x98EB, 0xEF85, 0x98EC, 0xEF86, 0x98ED,
+	0xEF87, 0x98EE, 0xEF88, 0x98EF, 0xEF89, 0x98F0, 0xEF8A, 0x98F1,
+	0xEF8B, 0x98F2, 0xEF8C, 0x98F3, 0xEF8D, 0x98F4, 0xEF8E, 0x98F5,
+	0xEF8F, 0x98F6, 0xEF90, 0x98F7, 0xEF91, 0x98F8, 0xEF92, 0x98F9,
+	0xEF93, 0x98FA, 0xEF94, 0x98FB, 0xEF95, 0x98FC, 0xEF96, 0x98FD,
+	0xEF97, 0x98FE, 0xEF98, 0x98FF, 0xEF99, 0x9900, 0xEF9A, 0x9901,
+	0xEF9B, 0x9902, 0xEF9C, 0x9903, 0xEF9D, 0x9904, 0xEF9E, 0x9905,
+	0xEF9F, 0x9906, 0xEFA0, 0x9907, 0xEFA1, 0x94E9, 0xEFA2, 0x94EB,
+	0xEFA3, 0x94EE, 0xEFA4, 0x94EF, 0xEFA5, 0x94F3, 0xEFA6, 0x94F4,
+	0xEFA7, 0x94F5, 0xEFA8, 0x94F7, 0xEFA9, 0x94F9, 0xEFAA, 0x94FC,
+	0xEFAB, 0x94FD, 0xEFAC, 0x94FF, 0xEFAD, 0x9503, 0xEFAE, 0x9502,
+	0xEFAF, 0x9506, 0xEFB0, 0x9507, 0xEFB1, 0x9509, 0xEFB2, 0x950A,
+	0xEFB3, 0x950D, 0xEFB4, 0x950E, 0xEFB5, 0x950F, 0xEFB6, 0x9512,
+	0xEFB7, 0x9513, 0xEFB8, 0x9514, 0xEFB9, 0x9515, 0xEFBA, 0x9516,
+	0xEFBB, 0x9518, 0xEFBC, 0x951B, 0xEFBD, 0x951D, 0xEFBE, 0x951E,
+	0xEFBF, 0x951F, 0xEFC0, 0x9522, 0xEFC1, 0x952A, 0xEFC2, 0x952B,
+	0xEFC3, 0x9529, 0xEFC4, 0x952C, 0xEFC5, 0x9531, 0xEFC6, 0x9532,
+	0xEFC7, 0x9534, 0xEFC8, 0x9536, 0xEFC9, 0x9537, 0xEFCA, 0x9538,
+	0xEFCB, 0x953C, 0xEFCC, 0x953E, 0xEFCD, 0x953F, 0xEFCE, 0x9542,
+	0xEFCF, 0x9535, 0xEFD0, 0x9544, 0xEFD1, 0x9545, 0xEFD2, 0x9546,
+	0xEFD3, 0x9549, 0xEFD4, 0x954C, 0xEFD5, 0x954E, 0xEFD6, 0x954F,
+	0xEFD7, 0x9552, 0xEFD8, 0x9553, 0xEFD9, 0x9554, 0xEFDA, 0x9556,
+	0xEFDB, 0x9557, 0xEFDC, 0x9558, 0xEFDD, 0x9559, 0xEFDE, 0x955B,
+	0xEFDF, 0x955E, 0xEFE0, 0x955F, 0xEFE1, 0x955D, 0xEFE2, 0x9561,
+	0xEFE3, 0x9562, 0xEFE4, 0x9564, 0xEFE5, 0x9565, 0xEFE6, 0x9566,
+	0xEFE7, 0x9567, 0xEFE8, 0x9568, 0xEFE9, 0x9569, 0xEFEA, 0x956A,
+	0xEFEB, 0x956B, 0xEFEC, 0x956C, 0xEFED, 0x956F, 0xEFEE, 0x9571,
+	0xEFEF, 0x9572, 0xEFF0, 0x9573, 0xEFF1, 0x953A, 0xEFF2, 0x77E7,
+	0xEFF3, 0x77EC, 0xEFF4, 0x96C9, 0xEFF5, 0x79D5, 0xEFF6, 0x79ED,
+	0xEFF7, 0x79E3, 0xEFF8, 0x79EB, 0xEFF9, 0x7A06, 0xEFFA, 0x5D47,
+	0xEFFB, 0x7A03, 0xEFFC, 0x7A02, 0xEFFD, 0x7A1E, 0xEFFE, 0x7A14,
+	0xF040, 0x9908, 0xF041, 0x9909, 0xF042, 0x990A, 0xF043, 0x990B,
+	0xF044, 0x990C, 0xF045, 0x990E, 0xF046, 0x990F, 0xF047, 0x9911,
+	0xF048, 0x9912, 0xF049, 0x9913, 0xF04A, 0x9914, 0xF04B, 0x9915,
+	0xF04C, 0x9916, 0xF04D, 0x9917, 0xF04E, 0x9918, 0xF04F, 0x9919,
+	0xF050, 0x991A, 0xF051, 0x991B, 0xF052, 0x991C, 0xF053, 0x991D,
+	0xF054, 0x991E, 0xF055, 0x991F, 0xF056, 0x9920, 0xF057, 0x9921,
+	0xF058, 0x9922, 0xF059, 0x9923, 0xF05A, 0x9924, 0xF05B, 0x9925,
+	0xF05C, 0x9926, 0xF05D, 0x9927, 0xF05E, 0x9928, 0xF05F, 0x9929,
+	0xF060, 0x992A, 0xF061, 0x992B, 0xF062, 0x992C, 0xF063, 0x992D,
+	0xF064, 0x992F, 0xF065, 0x9930, 0xF066, 0x9931, 0xF067, 0x9932,
+	0xF068, 0x9933, 0xF069, 0x9934, 0xF06A, 0x9935, 0xF06B, 0x9936,
+	0xF06C, 0x9937, 0xF06D, 0x9938, 0xF06E, 0x9939, 0xF06F, 0x993A,
+	0xF070, 0x993B, 0xF071, 0x993C, 0xF072, 0x993D, 0xF073, 0x993E,
+	0xF074, 0x993F, 0xF075, 0x9940, 0xF076, 0x9941, 0xF077, 0x9942,
+	0xF078, 0x9943, 0xF079, 0x9944, 0xF07A, 0x9945, 0xF07B, 0x9946,
+	0xF07C, 0x9947, 0xF07D, 0x9948, 0xF07E, 0x9949, 0xF080, 0x994A,
+	0xF081, 0x994B, 0xF082, 0x994C, 0xF083, 0x994D, 0xF084, 0x994E,
+	0xF085, 0x994F, 0xF086, 0x9950, 0xF087, 0x9951, 0xF088, 0x9952,
+	0xF089, 0x9953, 0xF08A, 0x9956, 0xF08B, 0x9957, 0xF08C, 0x9958,
+	0xF08D, 0x9959, 0xF08E, 0x995A, 0xF08F, 0x995B, 0xF090, 0x995C,
+	0xF091, 0x995D, 0xF092, 0x995E, 0xF093, 0x995F, 0xF094, 0x9960,
+	0xF095, 0x9961, 0xF096, 0x9962, 0xF097, 0x9964, 0xF098, 0x9966,
+	0xF099, 0x9973, 0xF09A, 0x9978, 0xF09B, 0x9979, 0xF09C, 0x997B,
+	0xF09D, 0x997E, 0xF09E, 0x9982, 0xF09F, 0x9983, 0xF0A0, 0x9989,
+	0xF0A1, 0x7A39, 0xF0A2, 0x7A37, 0xF0A3, 0x7A51, 0xF0A4, 0x9ECF,
+	0xF0A5, 0x99A5, 0xF0A6, 0x7A70, 0xF0A7, 0x7688, 0xF0A8, 0x768E,
+	0xF0A9, 0x7693, 0xF0AA, 0x7699, 0xF0AB, 0x76A4, 0xF0AC, 0x74DE,
+	0xF0AD, 0x74E0, 0xF0AE, 0x752C, 0xF0AF, 0x9E20, 0xF0B0, 0x9E22,
+	0xF0B1, 0x9E28, 0xF0B2, 0x9E29, 0xF0B3, 0x9E2A, 0xF0B4, 0x9E2B,
+	0xF0B5, 0x9E2C, 0xF0B6, 0x9E32, 0xF0B7, 0x9E31, 0xF0B8, 0x9E36,
+	0xF0B9, 0x9E38, 0xF0BA, 0x9E37, 0xF0BB, 0x9E39, 0xF0BC, 0x9E3A,
+	0xF0BD, 0x9E3E, 0xF0BE, 0x9E41, 0xF0BF, 0x9E42, 0xF0C0, 0x9E44,
+	0xF0C1, 0x9E46, 0xF0C2, 0x9E47, 0xF0C3, 0x9E48, 0xF0C4, 0x9E49,
+	0xF0C5, 0x9E4B, 0xF0C6, 0x9E4C, 0xF0C7, 0x9E4E, 0xF0C8, 0x9E51,
+	0xF0C9, 0x9E55, 0xF0CA, 0x9E57, 0xF0CB, 0x9E5A, 0xF0CC, 0x9E5B,
+	0xF0CD, 0x9E5C, 0xF0CE, 0x9E5E, 0xF0CF, 0x9E63, 0xF0D0, 0x9E66,
+	0xF0D1, 0x9E67, 0xF0D2, 0x9E68, 0xF0D3, 0x9E69, 0xF0D4, 0x9E6A,
+	0xF0D5, 0x9E6B, 0xF0D6, 0x9E6C, 0xF0D7, 0x9E71, 0xF0D8, 0x9E6D,
+	0xF0D9, 0x9E73, 0xF0DA, 0x7592, 0xF0DB, 0x7594, 0xF0DC, 0x7596,
+	0xF0DD, 0x75A0, 0xF0DE, 0x759D, 0xF0DF, 0x75AC, 0xF0E0, 0x75A3,
+	0xF0E1, 0x75B3, 0xF0E2, 0x75B4, 0xF0E3, 0x75B8, 0xF0E4, 0x75C4,
+	0xF0E5, 0x75B1, 0xF0E6, 0x75B0, 0xF0E7, 0x75C3, 0xF0E8, 0x75C2,
+	0xF0E9, 0x75D6, 0xF0EA, 0x75CD, 0xF0EB, 0x75E3, 0xF0EC, 0x75E8,
+	0xF0ED, 0x75E6, 0xF0EE, 0x75E4, 0xF0EF, 0x75EB, 0xF0F0, 0x75E7,
+	0xF0F1, 0x7603, 0xF0F2, 0x75F1, 0xF0F3, 0x75FC, 0xF0F4, 0x75FF,
+	0xF0F5, 0x7610, 0xF0F6, 0x7600, 0xF0F7, 0x7605, 0xF0F8, 0x760C,
+	0xF0F9, 0x7617, 0xF0FA, 0x760A, 0xF0FB, 0x7625, 0xF0FC, 0x7618,
+	0xF0FD, 0x7615, 0xF0FE, 0x7619, 0xF140, 0x998C, 0xF141, 0x998E,
+	0xF142, 0x999A, 0xF143, 0x999B, 0xF144, 0x999C, 0xF145, 0x999D,
+	0xF146, 0x999E, 0xF147, 0x999F, 0xF148, 0x99A0, 0xF149, 0x99A1,
+	0xF14A, 0x99A2, 0xF14B, 0x99A3, 0xF14C, 0x99A4, 0xF14D, 0x99A6,
+	0xF14E, 0x99A7, 0xF14F, 0x99A9, 0xF150, 0x99AA, 0xF151, 0x99AB,
+	0xF152, 0x99AC, 0xF153, 0x99AD, 0xF154, 0x99AE, 0xF155, 0x99AF,
+	0xF156, 0x99B0, 0xF157, 0x99B1, 0xF158, 0x99B2, 0xF159, 0x99B3,
+	0xF15A, 0x99B4, 0xF15B, 0x99B5, 0xF15C, 0x99B6, 0xF15D, 0x99B7,
+	0xF15E, 0x99B8, 0xF15F, 0x99B9, 0xF160, 0x99BA, 0xF161, 0x99BB,
+	0xF162, 0x99BC, 0xF163, 0x99BD, 0xF164, 0x99BE, 0xF165, 0x99BF,
+	0xF166, 0x99C0, 0xF167, 0x99C1, 0xF168, 0x99C2, 0xF169, 0x99C3,
+	0xF16A, 0x99C4, 0xF16B, 0x99C5, 0xF16C, 0x99C6, 0xF16D, 0x99C7,
+	0xF16E, 0x99C8, 0xF16F, 0x99C9, 0xF170, 0x99CA, 0xF171, 0x99CB,
+	0xF172, 0x99CC, 0xF173, 0x99CD, 0xF174, 0x99CE, 0xF175, 0x99CF,
+	0xF176, 0x99D0, 0xF177, 0x99D1, 0xF178, 0x99D2, 0xF179, 0x99D3,
+	0xF17A, 0x99D4, 0xF17B, 0x99D5, 0xF17C, 0x99D6, 0xF17D, 0x99D7,
+	0xF17E, 0x99D8, 0xF180, 0x99D9, 0xF181, 0x99DA, 0xF182, 0x99DB,
+	0xF183, 0x99DC, 0xF184, 0x99DD, 0xF185, 0x99DE, 0xF186, 0x99DF,
+	0xF187, 0x99E0, 0xF188, 0x99E1, 0xF189, 0x99E2, 0xF18A, 0x99E3,
+	0xF18B, 0x99E4, 0xF18C, 0x99E5, 0xF18D, 0x99E6, 0xF18E, 0x99E7,
+	0xF18F, 0x99E8, 0xF190, 0x99E9, 0xF191, 0x99EA, 0xF192, 0x99EB,
+	0xF193, 0x99EC, 0xF194, 0x99ED, 0xF195, 0x99EE, 0xF196, 0x99EF,
+	0xF197, 0x99F0, 0xF198, 0x99F1, 0xF199, 0x99F2, 0xF19A, 0x99F3,
+	0xF19B, 0x99F4, 0xF19C, 0x99F5, 0xF19D, 0x99F6, 0xF19E, 0x99F7,
+	0xF19F, 0x99F8, 0xF1A0, 0x99F9, 0xF1A1, 0x761B, 0xF1A2, 0x763C,
+	0xF1A3, 0x7622, 0xF1A4, 0x7620, 0xF1A5, 0x7640, 0xF1A6, 0x762D,
+	0xF1A7, 0x7630, 0xF1A8, 0x763F, 0xF1A9, 0x7635, 0xF1AA, 0x7643,
+	0xF1AB, 0x763E, 0xF1AC, 0x7633, 0xF1AD, 0x764D, 0xF1AE, 0x765E,
+	0xF1AF, 0x7654, 0xF1B0, 0x765C, 0xF1B1, 0x7656, 0xF1B2, 0x766B,
+	0xF1B3, 0x766F, 0xF1B4, 0x7FCA, 0xF1B5, 0x7AE6, 0xF1B6, 0x7A78,
+	0xF1B7, 0x7A79, 0xF1B8, 0x7A80, 0xF1B9, 0x7A86, 0xF1BA, 0x7A88,
+	0xF1BB, 0x7A95, 0xF1BC, 0x7AA6, 0xF1BD, 0x7AA0, 0xF1BE, 0x7AAC,
+	0xF1BF, 0x7AA8, 0xF1C0, 0x7AAD, 0xF1C1, 0x7AB3, 0xF1C2, 0x8864,
+	0xF1C3, 0x8869, 0xF1C4, 0x8872, 0xF1C5, 0x887D, 0xF1C6, 0x887F,
+	0xF1C7, 0x8882, 0xF1C8, 0x88A2, 0xF1C9, 0x88C6, 0xF1CA, 0x88B7,
+	0xF1CB, 0x88BC, 0xF1CC, 0x88C9, 0xF1CD, 0x88E2, 0xF1CE, 0x88CE,
+	0xF1CF, 0x88E3, 0xF1D0, 0x88E5, 0xF1D1, 0x88F1, 0xF1D2, 0x891A,
+	0xF1D3, 0x88FC, 0xF1D4, 0x88E8, 0xF1D5, 0x88FE, 0xF1D6, 0x88F0,
+	0xF1D7, 0x8921, 0xF1D8, 0x8919, 0xF1D9, 0x8913, 0xF1DA, 0x891B,
+	0xF1DB, 0x890A, 0xF1DC, 0x8934, 0xF1DD, 0x892B, 0xF1DE, 0x8936,
+	0xF1DF, 0x8941, 0xF1E0, 0x8966, 0xF1E1, 0x897B, 0xF1E2, 0x758B,
+	0xF1E3, 0x80E5, 0xF1E4, 0x76B2, 0xF1E5, 0x76B4, 0xF1E6, 0x77DC,
+	0xF1E7, 0x8012, 0xF1E8, 0x8014, 0xF1E9, 0x8016, 0xF1EA, 0x801C,
+	0xF1EB, 0x8020, 0xF1EC, 0x8022, 0xF1ED, 0x8025, 0xF1EE, 0x8026,
+	0xF1EF, 0x8027, 0xF1F0, 0x8029, 0xF1F1, 0x8028, 0xF1F2, 0x8031,
+	0xF1F3, 0x800B, 0xF1F4, 0x8035, 0xF1F5, 0x8043, 0xF1F6, 0x8046,
+	0xF1F7, 0x804D, 0xF1F8, 0x8052, 0xF1F9, 0x8069, 0xF1FA, 0x8071,
+	0xF1FB, 0x8983, 0xF1FC, 0x9878, 0xF1FD, 0x9880, 0xF1FE, 0x9883,
+	0xF240, 0x99FA, 0xF241, 0x99FB, 0xF242, 0x99FC, 0xF243, 0x99FD,
+	0xF244, 0x99FE, 0xF245, 0x99FF, 0xF246, 0x9A00, 0xF247, 0x9A01,
+	0xF248, 0x9A02, 0xF249, 0x9A03, 0xF24A, 0x9A04, 0xF24B, 0x9A05,
+	0xF24C, 0x9A06, 0xF24D, 0x9A07, 0xF24E, 0x9A08, 0xF24F, 0x9A09,
+	0xF250, 0x9A0A, 0xF251, 0x9A0B, 0xF252, 0x9A0C, 0xF253, 0x9A0D,
+	0xF254, 0x9A0E, 0xF255, 0x9A0F, 0xF256, 0x9A10, 0xF257, 0x9A11,
+	0xF258, 0x9A12, 0xF259, 0x9A13, 0xF25A, 0x9A14, 0xF25B, 0x9A15,
+	0xF25C, 0x9A16, 0xF25D, 0x9A17, 0xF25E, 0x9A18, 0xF25F, 0x9A19,
+	0xF260, 0x9A1A, 0xF261, 0x9A1B, 0xF262, 0x9A1C, 0xF263, 0x9A1D,
+	0xF264, 0x9A1E, 0xF265, 0x9A1F, 0xF266, 0x9A20, 0xF267, 0x9A21,
+	0xF268, 0x9A22, 0xF269, 0x9A23, 0xF26A, 0x9A24, 0xF26B, 0x9A25,
+	0xF26C, 0x9A26, 0xF26D, 0x9A27, 0xF26E, 0x9A28, 0xF26F, 0x9A29,
+	0xF270, 0x9A2A, 0xF271, 0x9A2B, 0xF272, 0x9A2C, 0xF273, 0x9A2D,
+	0xF274, 0x9A2E, 0xF275, 0x9A2F, 0xF276, 0x9A30, 0xF277, 0x9A31,
+	0xF278, 0x9A32, 0xF279, 0x9A33, 0xF27A, 0x9A34, 0xF27B, 0x9A35,
+	0xF27C, 0x9A36, 0xF27D, 0x9A37, 0xF27E, 0x9A38, 0xF280, 0x9A39,
+	0xF281, 0x9A3A, 0xF282, 0x9A3B, 0xF283, 0x9A3C, 0xF284, 0x9A3D,
+	0xF285, 0x9A3E, 0xF286, 0x9A3F, 0xF287, 0x9A40, 0xF288, 0x9A41,
+	0xF289, 0x9A42, 0xF28A, 0x9A43, 0xF28B, 0x9A44, 0xF28C, 0x9A45,
+	0xF28D, 0x9A46, 0xF28E, 0x9A47, 0xF28F, 0x9A48, 0xF290, 0x9A49,
+	0xF291, 0x9A4A, 0xF292, 0x9A4B, 0xF293, 0x9A4C, 0xF294, 0x9A4D,
+	0xF295, 0x9A4E, 0xF296, 0x9A4F, 0xF297, 0x9A50, 0xF298, 0x9A51,
+	0xF299, 0x9A52, 0xF29A, 0x9A53, 0xF29B, 0x9A54, 0xF29C, 0x9A55,
+	0xF29D, 0x9A56, 0xF29E, 0x9A57, 0xF29F, 0x9A58, 0xF2A0, 0x9A59,
+	0xF2A1, 0x9889, 0xF2A2, 0x988C, 0xF2A3, 0x988D, 0xF2A4, 0x988F,
+	0xF2A5, 0x9894, 0xF2A6, 0x989A, 0xF2A7, 0x989B, 0xF2A8, 0x989E,
+	0xF2A9, 0x989F, 0xF2AA, 0x98A1, 0xF2AB, 0x98A2, 0xF2AC, 0x98A5,
+	0xF2AD, 0x98A6, 0xF2AE, 0x864D, 0xF2AF, 0x8654, 0xF2B0, 0x866C,
+	0xF2B1, 0x866E, 0xF2B2, 0x867F, 0xF2B3, 0x867A, 0xF2B4, 0x867C,
+	0xF2B5, 0x867B, 0xF2B6, 0x86A8, 0xF2B7, 0x868D, 0xF2B8, 0x868B,
+	0xF2B9, 0x86AC, 0xF2BA, 0x869D, 0xF2BB, 0x86A7, 0xF2BC, 0x86A3,
+	0xF2BD, 0x86AA, 0xF2BE, 0x8693, 0xF2BF, 0x86A9, 0xF2C0, 0x86B6,
+	0xF2C1, 0x86C4, 0xF2C2, 0x86B5, 0xF2C3, 0x86CE, 0xF2C4, 0x86B0,
+	0xF2C5, 0x86BA, 0xF2C6, 0x86B1, 0xF2C7, 0x86AF, 0xF2C8, 0x86C9,
+	0xF2C9, 0x86CF, 0xF2CA, 0x86B4, 0xF2CB, 0x86E9, 0xF2CC, 0x86F1,
+	0xF2CD, 0x86F2, 0xF2CE, 0x86ED, 0xF2CF, 0x86F3, 0xF2D0, 0x86D0,
+	0xF2D1, 0x8713, 0xF2D2, 0x86DE, 0xF2D3, 0x86F4, 0xF2D4, 0x86DF,
+	0xF2D5, 0x86D8, 0xF2D6, 0x86D1, 0xF2D7, 0x8703, 0xF2D8, 0x8707,
+	0xF2D9, 0x86F8, 0xF2DA, 0x8708, 0xF2DB, 0x870A, 0xF2DC, 0x870D,
+	0xF2DD, 0x8709, 0xF2DE, 0x8723, 0xF2DF, 0x873B, 0xF2E0, 0x871E,
+	0xF2E1, 0x8725, 0xF2E2, 0x872E, 0xF2E3, 0x871A, 0xF2E4, 0x873E,
+	0xF2E5, 0x8748, 0xF2E6, 0x8734, 0xF2E7, 0x8731, 0xF2E8, 0x8729,
+	0xF2E9, 0x8737, 0xF2EA, 0x873F, 0xF2EB, 0x8782, 0xF2EC, 0x8722,
+	0xF2ED, 0x877D, 0xF2EE, 0x877E, 0xF2EF, 0x877B, 0xF2F0, 0x8760,
+	0xF2F1, 0x8770, 0xF2F2, 0x874C, 0xF2F3, 0x876E, 0xF2F4, 0x878B,
+	0xF2F5, 0x8753, 0xF2F6, 0x8763, 0xF2F7, 0x877C, 0xF2F8, 0x8764,
+	0xF2F9, 0x8759, 0xF2FA, 0x8765, 0xF2FB, 0x8793, 0xF2FC, 0x87AF,
+	0xF2FD, 0x87A8, 0xF2FE, 0x87D2, 0xF340, 0x9A5A, 0xF341, 0x9A5B,
+	0xF342, 0x9A5C, 0xF343, 0x9A5D, 0xF344, 0x9A5E, 0xF345, 0x9A5F,
+	0xF346, 0x9A60, 0xF347, 0x9A61, 0xF348, 0x9A62, 0xF349, 0x9A63,
+	0xF34A, 0x9A64, 0xF34B, 0x9A65, 0xF34C, 0x9A66, 0xF34D, 0x9A67,
+	0xF34E, 0x9A68, 0xF34F, 0x9A69, 0xF350, 0x9A6A, 0xF351, 0x9A6B,
+	0xF352, 0x9A72, 0xF353, 0x9A83, 0xF354, 0x9A89, 0xF355, 0x9A8D,
+	0xF356, 0x9A8E, 0xF357, 0x9A94, 0xF358, 0x9A95, 0xF359, 0x9A99,
+	0xF35A, 0x9AA6, 0xF35B, 0x9AA9, 0xF35C, 0x9AAA, 0xF35D, 0x9AAB,
+	0xF35E, 0x9AAC, 0xF35F, 0x9AAD, 0xF360, 0x9AAE, 0xF361, 0x9AAF,
+	0xF362, 0x9AB2, 0xF363, 0x9AB3, 0xF364, 0x9AB4, 0xF365, 0x9AB5,
+	0xF366, 0x9AB9, 0xF367, 0x9ABB, 0xF368, 0x9ABD, 0xF369, 0x9ABE,
+	0xF36A, 0x9ABF, 0xF36B, 0x9AC3, 0xF36C, 0x9AC4, 0xF36D, 0x9AC6,
+	0xF36E, 0x9AC7, 0xF36F, 0x9AC8, 0xF370, 0x9AC9, 0xF371, 0x9ACA,
+	0xF372, 0x9ACD, 0xF373, 0x9ACE, 0xF374, 0x9ACF, 0xF375, 0x9AD0,
+	0xF376, 0x9AD2, 0xF377, 0x9AD4, 0xF378, 0x9AD5, 0xF379, 0x9AD6,
+	0xF37A, 0x9AD7, 0xF37B, 0x9AD9, 0xF37C, 0x9ADA, 0xF37D, 0x9ADB,
+	0xF37E, 0x9ADC, 0xF380, 0x9ADD, 0xF381, 0x9ADE, 0xF382, 0x9AE0,
+	0xF383, 0x9AE2, 0xF384, 0x9AE3, 0xF385, 0x9AE4, 0xF386, 0x9AE5,
+	0xF387, 0x9AE7, 0xF388, 0x9AE8, 0xF389, 0x9AE9, 0xF38A, 0x9AEA,
+	0xF38B, 0x9AEC, 0xF38C, 0x9AEE, 0xF38D, 0x9AF0, 0xF38E, 0x9AF1,
+	0xF38F, 0x9AF2, 0xF390, 0x9AF3, 0xF391, 0x9AF4, 0xF392, 0x9AF5,
+	0xF393, 0x9AF6, 0xF394, 0x9AF7, 0xF395, 0x9AF8, 0xF396, 0x9AFA,
+	0xF397, 0x9AFC, 0xF398, 0x9AFD, 0xF399, 0x9AFE, 0xF39A, 0x9AFF,
+	0xF39B, 0x9B00, 0xF39C, 0x9B01, 0xF39D, 0x9B02, 0xF39E, 0x9B04,
+	0xF39F, 0x9B05, 0xF3A0, 0x9B06, 0xF3A1, 0x87C6, 0xF3A2, 0x8788,
+	0xF3A3, 0x8785, 0xF3A4, 0x87AD, 0xF3A5, 0x8797, 0xF3A6, 0x8783,
+	0xF3A7, 0x87AB, 0xF3A8, 0x87E5, 0xF3A9, 0x87AC, 0xF3AA, 0x87B5,
+	0xF3AB, 0x87B3, 0xF3AC, 0x87CB, 0xF3AD, 0x87D3, 0xF3AE, 0x87BD,
+	0xF3AF, 0x87D1, 0xF3B0, 0x87C0, 0xF3B1, 0x87CA, 0xF3B2, 0x87DB,
+	0xF3B3, 0x87EA, 0xF3B4, 0x87E0, 0xF3B5, 0x87EE, 0xF3B6, 0x8816,
+	0xF3B7, 0x8813, 0xF3B8, 0x87FE, 0xF3B9, 0x880A, 0xF3BA, 0x881B,
+	0xF3BB, 0x8821, 0xF3BC, 0x8839, 0xF3BD, 0x883C, 0xF3BE, 0x7F36,
+	0xF3BF, 0x7F42, 0xF3C0, 0x7F44, 0xF3C1, 0x7F45, 0xF3C2, 0x8210,
+	0xF3C3, 0x7AFA, 0xF3C4, 0x7AFD, 0xF3C5, 0x7B08, 0xF3C6, 0x7B03,
+	0xF3C7, 0x7B04, 0xF3C8, 0x7B15, 0xF3C9, 0x7B0A, 0xF3CA, 0x7B2B,
+	0xF3CB, 0x7B0F, 0xF3CC, 0x7B47, 0xF3CD, 0x7B38, 0xF3CE, 0x7B2A,
+	0xF3CF, 0x7B19, 0xF3D0, 0x7B2E, 0xF3D1, 0x7B31, 0xF3D2, 0x7B20,
+	0xF3D3, 0x7B25, 0xF3D4, 0x7B24, 0xF3D5, 0x7B33, 0xF3D6, 0x7B3E,
+	0xF3D7, 0x7B1E, 0xF3D8, 0x7B58, 0xF3D9, 0x7B5A, 0xF3DA, 0x7B45,
+	0xF3DB, 0x7B75, 0xF3DC, 0x7B4C, 0xF3DD, 0x7B5D, 0xF3DE, 0x7B60,
+	0xF3DF, 0x7B6E, 0xF3E0, 0x7B7B, 0xF3E1, 0x7B62, 0xF3E2, 0x7B72,
+	0xF3E3, 0x7B71, 0xF3E4, 0x7B90, 0xF3E5, 0x7BA6, 0xF3E6, 0x7BA7,
+	0xF3E7, 0x7BB8, 0xF3E8, 0x7BAC, 0xF3E9, 0x7B9D, 0xF3EA, 0x7BA8,
+	0xF3EB, 0x7B85, 0xF3EC, 0x7BAA, 0xF3ED, 0x7B9C, 0xF3EE, 0x7BA2,
+	0xF3EF, 0x7BAB, 0xF3F0, 0x7BB4, 0xF3F1, 0x7BD1, 0xF3F2, 0x7BC1,
+	0xF3F3, 0x7BCC, 0xF3F4, 0x7BDD, 0xF3F5, 0x7BDA, 0xF3F6, 0x7BE5,
+	0xF3F7, 0x7BE6, 0xF3F8, 0x7BEA, 0xF3F9, 0x7C0C, 0xF3FA, 0x7BFE,
+	0xF3FB, 0x7BFC, 0xF3FC, 0x7C0F, 0xF3FD, 0x7C16, 0xF3FE, 0x7C0B,
+	0xF440, 0x9B07, 0xF441, 0x9B09, 0xF442, 0x9B0A, 0xF443, 0x9B0B,
+	0xF444, 0x9B0C, 0xF445, 0x9B0D, 0xF446, 0x9B0E, 0xF447, 0x9B10,
+	0xF448, 0x9B11, 0xF449, 0x9B12, 0xF44A, 0x9B14, 0xF44B, 0x9B15,
+	0xF44C, 0x9B16, 0xF44D, 0x9B17, 0xF44E, 0x9B18, 0xF44F, 0x9B19,
+	0xF450, 0x9B1A, 0xF451, 0x9B1B, 0xF452, 0x9B1C, 0xF453, 0x9B1D,
+	0xF454, 0x9B1E, 0xF455, 0x9B20, 0xF456, 0x9B21, 0xF457, 0x9B22,
+	0xF458, 0x9B24, 0xF459, 0x9B25, 0xF45A, 0x9B26, 0xF45B, 0x9B27,
+	0xF45C, 0x9B28, 0xF45D, 0x9B29, 0xF45E, 0x9B2A, 0xF45F, 0x9B2B,
+	0xF460, 0x9B2C, 0xF461, 0x9B2D, 0xF462, 0x9B2E, 0xF463, 0x9B30,
+	0xF464, 0x9B31, 0xF465, 0x9B33, 0xF466, 0x9B34, 0xF467, 0x9B35,
+	0xF468, 0x9B36, 0xF469, 0x9B37, 0xF46A, 0x9B38, 0xF46B, 0x9B39,
+	0xF46C, 0x9B3A, 0xF46D, 0x9B3D, 0xF46E, 0x9B3E, 0xF46F, 0x9B3F,
+	0xF470, 0x9B40, 0xF471, 0x9B46, 0xF472, 0x9B4A, 0xF473, 0x9B4B,
+	0xF474, 0x9B4C, 0xF475, 0x9B4E, 0xF476, 0x9B50, 0xF477, 0x9B52,
+	0xF478, 0x9B53, 0xF479, 0x9B55, 0xF47A, 0x9B56, 0xF47B, 0x9B57,
+	0xF47C, 0x9B58, 0xF47D, 0x9B59, 0xF47E, 0x9B5A, 0xF480, 0x9B5B,
+	0xF481, 0x9B5C, 0xF482, 0x9B5D, 0xF483, 0x9B5E, 0xF484, 0x9B5F,
+	0xF485, 0x9B60, 0xF486, 0x9B61, 0xF487, 0x9B62, 0xF488, 0x9B63,
+	0xF489, 0x9B64, 0xF48A, 0x9B65, 0xF48B, 0x9B66, 0xF48C, 0x9B67,
+	0xF48D, 0x9B68, 0xF48E, 0x9B69, 0xF48F, 0x9B6A, 0xF490, 0x9B6B,
+	0xF491, 0x9B6C, 0xF492, 0x9B6D, 0xF493, 0x9B6E, 0xF494, 0x9B6F,
+	0xF495, 0x9B70, 0xF496, 0x9B71, 0xF497, 0x9B72, 0xF498, 0x9B73,
+	0xF499, 0x9B74, 0xF49A, 0x9B75, 0xF49B, 0x9B76, 0xF49C, 0x9B77,
+	0xF49D, 0x9B78, 0xF49E, 0x9B79, 0xF49F, 0x9B7A, 0xF4A0, 0x9B7B,
+	0xF4A1, 0x7C1F, 0xF4A2, 0x7C2A, 0xF4A3, 0x7C26, 0xF4A4, 0x7C38,
+	0xF4A5, 0x7C41, 0xF4A6, 0x7C40, 0xF4A7, 0x81FE, 0xF4A8, 0x8201,
+	0xF4A9, 0x8202, 0xF4AA, 0x8204, 0xF4AB, 0x81EC, 0xF4AC, 0x8844,
+	0xF4AD, 0x8221, 0xF4AE, 0x8222, 0xF4AF, 0x8223, 0xF4B0, 0x822D,
+	0xF4B1, 0x822F, 0xF4B2, 0x8228, 0xF4B3, 0x822B, 0xF4B4, 0x8238,
+	0xF4B5, 0x823B, 0xF4B6, 0x8233, 0xF4B7, 0x8234, 0xF4B8, 0x823E,
+	0xF4B9, 0x8244, 0xF4BA, 0x8249, 0xF4BB, 0x824B, 0xF4BC, 0x824F,
+	0xF4BD, 0x825A, 0xF4BE, 0x825F, 0xF4BF, 0x8268, 0xF4C0, 0x887E,
+	0xF4C1, 0x8885, 0xF4C2, 0x8888, 0xF4C3, 0x88D8, 0xF4C4, 0x88DF,
+	0xF4C5, 0x895E, 0xF4C6, 0x7F9D, 0xF4C7, 0x7F9F, 0xF4C8, 0x7FA7,
+	0xF4C9, 0x7FAF, 0xF4CA, 0x7FB0, 0xF4CB, 0x7FB2, 0xF4CC, 0x7C7C,
+	0xF4CD, 0x6549, 0xF4CE, 0x7C91, 0xF4CF, 0x7C9D, 0xF4D0, 0x7C9C,
+	0xF4D1, 0x7C9E, 0xF4D2, 0x7CA2, 0xF4D3, 0x7CB2, 0xF4D4, 0x7CBC,
+	0xF4D5, 0x7CBD, 0xF4D6, 0x7CC1, 0xF4D7, 0x7CC7, 0xF4D8, 0x7CCC,
+	0xF4D9, 0x7CCD, 0xF4DA, 0x7CC8, 0xF4DB, 0x7CC5, 0xF4DC, 0x7CD7,
+	0xF4DD, 0x7CE8, 0xF4DE, 0x826E, 0xF4DF, 0x66A8, 0xF4E0, 0x7FBF,
+	0xF4E1, 0x7FCE, 0xF4E2, 0x7FD5, 0xF4E3, 0x7FE5, 0xF4E4, 0x7FE1,
+	0xF4E5, 0x7FE6, 0xF4E6, 0x7FE9, 0xF4E7, 0x7FEE, 0xF4E8, 0x7FF3,
+	0xF4E9, 0x7CF8, 0xF4EA, 0x7D77, 0xF4EB, 0x7DA6, 0xF4EC, 0x7DAE,
+	0xF4ED, 0x7E47, 0xF4EE, 0x7E9B, 0xF4EF, 0x9EB8, 0xF4F0, 0x9EB4,
+	0xF4F1, 0x8D73, 0xF4F2, 0x8D84, 0xF4F3, 0x8D94, 0xF4F4, 0x8D91,
+	0xF4F5, 0x8DB1, 0xF4F6, 0x8D67, 0xF4F7, 0x8D6D, 0xF4F8, 0x8C47,
+	0xF4F9, 0x8C49, 0xF4FA, 0x914A, 0xF4FB, 0x9150, 0xF4FC, 0x914E,
+	0xF4FD, 0x914F, 0xF4FE, 0x9164, 0xF540, 0x9B7C, 0xF541, 0x9B7D,
+	0xF542, 0x9B7E, 0xF543, 0x9B7F, 0xF544, 0x9B80, 0xF545, 0x9B81,
+	0xF546, 0x9B82, 0xF547, 0x9B83, 0xF548, 0x9B84, 0xF549, 0x9B85,
+	0xF54A, 0x9B86, 0xF54B, 0x9B87, 0xF54C, 0x9B88, 0xF54D, 0x9B89,
+	0xF54E, 0x9B8A, 0xF54F, 0x9B8B, 0xF550, 0x9B8C, 0xF551, 0x9B8D,
+	0xF552, 0x9B8E, 0xF553, 0x9B8F, 0xF554, 0x9B90, 0xF555, 0x9B91,
+	0xF556, 0x9B92, 0xF557, 0x9B93, 0xF558, 0x9B94, 0xF559, 0x9B95,
+	0xF55A, 0x9B96, 0xF55B, 0x9B97, 0xF55C, 0x9B98, 0xF55D, 0x9B99,
+	0xF55E, 0x9B9A, 0xF55F, 0x9B9B, 0xF560, 0x9B9C, 0xF561, 0x9B9D,
+	0xF562, 0x9B9E, 0xF563, 0x9B9F, 0xF564, 0x9BA0, 0xF565, 0x9BA1,
+	0xF566, 0x9BA2, 0xF567, 0x9BA3, 0xF568, 0x9BA4, 0xF569, 0x9BA5,
+	0xF56A, 0x9BA6, 0xF56B, 0x9BA7, 0xF56C, 0x9BA8, 0xF56D, 0x9BA9,
+	0xF56E, 0x9BAA, 0xF56F, 0x9BAB, 0xF570, 0x9BAC, 0xF571, 0x9BAD,
+	0xF572, 0x9BAE, 0xF573, 0x9BAF, 0xF574, 0x9BB0, 0xF575, 0x9BB1,
+	0xF576, 0x9BB2, 0xF577, 0x9BB3, 0xF578, 0x9BB4, 0xF579, 0x9BB5,
+	0xF57A, 0x9BB6, 0xF57B, 0x9BB7, 0xF57C, 0x9BB8, 0xF57D, 0x9BB9,
+	0xF57E, 0x9BBA, 0xF580, 0x9BBB, 0xF581, 0x9BBC, 0xF582, 0x9BBD,
+	0xF583, 0x9BBE, 0xF584, 0x9BBF, 0xF585, 0x9BC0, 0xF586, 0x9BC1,
+	0xF587, 0x9BC2, 0xF588, 0x9BC3, 0xF589, 0x9BC4, 0xF58A, 0x9BC5,
+	0xF58B, 0x9BC6, 0xF58C, 0x9BC7, 0xF58D, 0x9BC8, 0xF58E, 0x9BC9,
+	0xF58F, 0x9BCA, 0xF590, 0x9BCB, 0xF591, 0x9BCC, 0xF592, 0x9BCD,
+	0xF593, 0x9BCE, 0xF594, 0x9BCF, 0xF595, 0x9BD0, 0xF596, 0x9BD1,
+	0xF597, 0x9BD2, 0xF598, 0x9BD3, 0xF599, 0x9BD4, 0xF59A, 0x9BD5,
+	0xF59B, 0x9BD6, 0xF59C, 0x9BD7, 0xF59D, 0x9BD8, 0xF59E, 0x9BD9,
+	0xF59F, 0x9BDA, 0xF5A0, 0x9BDB, 0xF5A1, 0x9162, 0xF5A2, 0x9161,
+	0xF5A3, 0x9170, 0xF5A4, 0x9169, 0xF5A5, 0x916F, 0xF5A6, 0x917D,
+	0xF5A7, 0x917E, 0xF5A8, 0x9172, 0xF5A9, 0x9174, 0xF5AA, 0x9179,
+	0xF5AB, 0x918C, 0xF5AC, 0x9185, 0xF5AD, 0x9190, 0xF5AE, 0x918D,
+	0xF5AF, 0x9191, 0xF5B0, 0x91A2, 0xF5B1, 0x91A3, 0xF5B2, 0x91AA,
+	0xF5B3, 0x91AD, 0xF5B4, 0x91AE, 0xF5B5, 0x91AF, 0xF5B6, 0x91B5,
+	0xF5B7, 0x91B4, 0xF5B8, 0x91BA, 0xF5B9, 0x8C55, 0xF5BA, 0x9E7E,
+	0xF5BB, 0x8DB8, 0xF5BC, 0x8DEB, 0xF5BD, 0x8E05, 0xF5BE, 0x8E59,
+	0xF5BF, 0x8E69, 0xF5C0, 0x8DB5, 0xF5C1, 0x8DBF, 0xF5C2, 0x8DBC,
+	0xF5C3, 0x8DBA, 0xF5C4, 0x8DC4, 0xF5C5, 0x8DD6, 0xF5C6, 0x8DD7,
+	0xF5C7, 0x8DDA, 0xF5C8, 0x8DDE, 0xF5C9, 0x8DCE, 0xF5CA, 0x8DCF,
+	0xF5CB, 0x8DDB, 0xF5CC, 0x8DC6, 0xF5CD, 0x8DEC, 0xF5CE, 0x8DF7,
+	0xF5CF, 0x8DF8, 0xF5D0, 0x8DE3, 0xF5D1, 0x8DF9, 0xF5D2, 0x8DFB,
+	0xF5D3, 0x8DE4, 0xF5D4, 0x8E09, 0xF5D5, 0x8DFD, 0xF5D6, 0x8E14,
+	0xF5D7, 0x8E1D, 0xF5D8, 0x8E1F, 0xF5D9, 0x8E2C, 0xF5DA, 0x8E2E,
+	0xF5DB, 0x8E23, 0xF5DC, 0x8E2F, 0xF5DD, 0x8E3A, 0xF5DE, 0x8E40,
+	0xF5DF, 0x8E39, 0xF5E0, 0x8E35, 0xF5E1, 0x8E3D, 0xF5E2, 0x8E31,
+	0xF5E3, 0x8E49, 0xF5E4, 0x8E41, 0xF5E5, 0x8E42, 0xF5E6, 0x8E51,
+	0xF5E7, 0x8E52, 0xF5E8, 0x8E4A, 0xF5E9, 0x8E70, 0xF5EA, 0x8E76,
+	0xF5EB, 0x8E7C, 0xF5EC, 0x8E6F, 0xF5ED, 0x8E74, 0xF5EE, 0x8E85,
+	0xF5EF, 0x8E8F, 0xF5F0, 0x8E94, 0xF5F1, 0x8E90, 0xF5F2, 0x8E9C,
+	0xF5F3, 0x8E9E, 0xF5F4, 0x8C78, 0xF5F5, 0x8C82, 0xF5F6, 0x8C8A,
+	0xF5F7, 0x8C85, 0xF5F8, 0x8C98, 0xF5F9, 0x8C94, 0xF5FA, 0x659B,
+	0xF5FB, 0x89D6, 0xF5FC, 0x89DE, 0xF5FD, 0x89DA, 0xF5FE, 0x89DC,
+	0xF640, 0x9BDC, 0xF641, 0x9BDD, 0xF642, 0x9BDE, 0xF643, 0x9BDF,
+	0xF644, 0x9BE0, 0xF645, 0x9BE1, 0xF646, 0x9BE2, 0xF647, 0x9BE3,
+	0xF648, 0x9BE4, 0xF649, 0x9BE5, 0xF64A, 0x9BE6, 0xF64B, 0x9BE7,
+	0xF64C, 0x9BE8, 0xF64D, 0x9BE9, 0xF64E, 0x9BEA, 0xF64F, 0x9BEB,
+	0xF650, 0x9BEC, 0xF651, 0x9BED, 0xF652, 0x9BEE, 0xF653, 0x9BEF,
+	0xF654, 0x9BF0, 0xF655, 0x9BF1, 0xF656, 0x9BF2, 0xF657, 0x9BF3,
+	0xF658, 0x9BF4, 0xF659, 0x9BF5, 0xF65A, 0x9BF6, 0xF65B, 0x9BF7,
+	0xF65C, 0x9BF8, 0xF65D, 0x9BF9, 0xF65E, 0x9BFA, 0xF65F, 0x9BFB,
+	0xF660, 0x9BFC, 0xF661, 0x9BFD, 0xF662, 0x9BFE, 0xF663, 0x9BFF,
+	0xF664, 0x9C00, 0xF665, 0x9C01, 0xF666, 0x9C02, 0xF667, 0x9C03,
+	0xF668, 0x9C04, 0xF669, 0x9C05, 0xF66A, 0x9C06, 0xF66B, 0x9C07,
+	0xF66C, 0x9C08, 0xF66D, 0x9C09, 0xF66E, 0x9C0A, 0xF66F, 0x9C0B,
+	0xF670, 0x9C0C, 0xF671, 0x9C0D, 0xF672, 0x9C0E, 0xF673, 0x9C0F,
+	0xF674, 0x9C10, 0xF675, 0x9C11, 0xF676, 0x9C12, 0xF677, 0x9C13,
+	0xF678, 0x9C14, 0xF679, 0x9C15, 0xF67A, 0x9C16, 0xF67B, 0x9C17,
+	0xF67C, 0x9C18, 0xF67D, 0x9C19, 0xF67E, 0x9C1A, 0xF680, 0x9C1B,
+	0xF681, 0x9C1C, 0xF682, 0x9C1D, 0xF683, 0x9C1E, 0xF684, 0x9C1F,
+	0xF685, 0x9C20, 0xF686, 0x9C21, 0xF687, 0x9C22, 0xF688, 0x9C23,
+	0xF689, 0x9C24, 0xF68A, 0x9C25, 0xF68B, 0x9C26, 0xF68C, 0x9C27,
+	0xF68D, 0x9C28, 0xF68E, 0x9C29, 0xF68F, 0x9C2A, 0xF690, 0x9C2B,
+	0xF691, 0x9C2C, 0xF692, 0x9C2D, 0xF693, 0x9C2E, 0xF694, 0x9C2F,
+	0xF695, 0x9C30, 0xF696, 0x9C31, 0xF697, 0x9C32, 0xF698, 0x9C33,
+	0xF699, 0x9C34, 0xF69A, 0x9C35, 0xF69B, 0x9C36, 0xF69C, 0x9C37,
+	0xF69D, 0x9C38, 0xF69E, 0x9C39, 0xF69F, 0x9C3A, 0xF6A0, 0x9C3B,
+	0xF6A1, 0x89E5, 0xF6A2, 0x89EB, 0xF6A3, 0x89EF, 0xF6A4, 0x8A3E,
+	0xF6A5, 0x8B26, 0xF6A6, 0x9753, 0xF6A7, 0x96E9, 0xF6A8, 0x96F3,
+	0xF6A9, 0x96EF, 0xF6AA, 0x9706, 0xF6AB, 0x9701, 0xF6AC, 0x9708,
+	0xF6AD, 0x970F, 0xF6AE, 0x970E, 0xF6AF, 0x972A, 0xF6B0, 0x972D,
+	0xF6B1, 0x9730, 0xF6B2, 0x973E, 0xF6B3, 0x9F80, 0xF6B4, 0x9F83,
+	0xF6B5, 0x9F85, 0xF6B6, 0x9F86, 0xF6B7, 0x9F87, 0xF6B8, 0x9F88,
+	0xF6B9, 0x9F89, 0xF6BA, 0x9F8A, 0xF6BB, 0x9F8C, 0xF6BC, 0x9EFE,
+	0xF6BD, 0x9F0B, 0xF6BE, 0x9F0D, 0xF6BF, 0x96B9, 0xF6C0, 0x96BC,
+	0xF6C1, 0x96BD, 0xF6C2, 0x96CE, 0xF6C3, 0x96D2, 0xF6C4, 0x77BF,
+	0xF6C5, 0x96E0, 0xF6C6, 0x928E, 0xF6C7, 0x92AE, 0xF6C8, 0x92C8,
+	0xF6C9, 0x933E, 0xF6CA, 0x936A, 0xF6CB, 0x93CA, 0xF6CC, 0x938F,
+	0xF6CD, 0x943E, 0xF6CE, 0x946B, 0xF6CF, 0x9C7F, 0xF6D0, 0x9C82,
+	0xF6D1, 0x9C85, 0xF6D2, 0x9C86, 0xF6D3, 0x9C87, 0xF6D4, 0x9C88,
+	0xF6D5, 0x7A23, 0xF6D6, 0x9C8B, 0xF6D7, 0x9C8E, 0xF6D8, 0x9C90,
+	0xF6D9, 0x9C91, 0xF6DA, 0x9C92, 0xF6DB, 0x9C94, 0xF6DC, 0x9C95,
+	0xF6DD, 0x9C9A, 0xF6DE, 0x9C9B, 0xF6DF, 0x9C9E, 0xF6E0, 0x9C9F,
+	0xF6E1, 0x9CA0, 0xF6E2, 0x9CA1, 0xF6E3, 0x9CA2, 0xF6E4, 0x9CA3,
+	0xF6E5, 0x9CA5, 0xF6E6, 0x9CA6, 0xF6E7, 0x9CA7, 0xF6E8, 0x9CA8,
+	0xF6E9, 0x9CA9, 0xF6EA, 0x9CAB, 0xF6EB, 0x9CAD, 0xF6EC, 0x9CAE,
+	0xF6ED, 0x9CB0, 0xF6EE, 0x9CB1, 0xF6EF, 0x9CB2, 0xF6F0, 0x9CB3,
+	0xF6F1, 0x9CB4, 0xF6F2, 0x9CB5, 0xF6F3, 0x9CB6, 0xF6F4, 0x9CB7,
+	0xF6F5, 0x9CBA, 0xF6F6, 0x9CBB, 0xF6F7, 0x9CBC, 0xF6F8, 0x9CBD,
+	0xF6F9, 0x9CC4, 0xF6FA, 0x9CC5, 0xF6FB, 0x9CC6, 0xF6FC, 0x9CC7,
+	0xF6FD, 0x9CCA, 0xF6FE, 0x9CCB, 0xF740, 0x9C3C, 0xF741, 0x9C3D,
+	0xF742, 0x9C3E, 0xF743, 0x9C3F, 0xF744, 0x9C40, 0xF745, 0x9C41,
+	0xF746, 0x9C42, 0xF747, 0x9C43, 0xF748, 0x9C44, 0xF749, 0x9C45,
+	0xF74A, 0x9C46, 0xF74B, 0x9C47, 0xF74C, 0x9C48, 0xF74D, 0x9C49,
+	0xF74E, 0x9C4A, 0xF74F, 0x9C4B, 0xF750, 0x9C4C, 0xF751, 0x9C4D,
+	0xF752, 0x9C4E, 0xF753, 0x9C4F, 0xF754, 0x9C50, 0xF755, 0x9C51,
+	0xF756, 0x9C52, 0xF757, 0x9C53, 0xF758, 0x9C54, 0xF759, 0x9C55,
+	0xF75A, 0x9C56, 0xF75B, 0x9C57, 0xF75C, 0x9C58, 0xF75D, 0x9C59,
+	0xF75E, 0x9C5A, 0xF75F, 0x9C5B, 0xF760, 0x9C5C, 0xF761, 0x9C5D,
+	0xF762, 0x9C5E, 0xF763, 0x9C5F, 0xF764, 0x9C60, 0xF765, 0x9C61,
+	0xF766, 0x9C62, 0xF767, 0x9C63, 0xF768, 0x9C64, 0xF769, 0x9C65,
+	0xF76A, 0x9C66, 0xF76B, 0x9C67, 0xF76C, 0x9C68, 0xF76D, 0x9C69,
+	0xF76E, 0x9C6A, 0xF76F, 0x9C6B, 0xF770, 0x9C6C, 0xF771, 0x9C6D,
+	0xF772, 0x9C6E, 0xF773, 0x9C6F, 0xF774, 0x9C70, 0xF775, 0x9C71,
+	0xF776, 0x9C72, 0xF777, 0x9C73, 0xF778, 0x9C74, 0xF779, 0x9C75,
+	0xF77A, 0x9C76, 0xF77B, 0x9C77, 0xF77C, 0x9C78, 0xF77D, 0x9C79,
+	0xF77E, 0x9C7A, 0xF780, 0x9C7B, 0xF781, 0x9C7D, 0xF782, 0x9C7E,
+	0xF783, 0x9C80, 0xF784, 0x9C83, 0xF785, 0x9C84, 0xF786, 0x9C89,
+	0xF787, 0x9C8A, 0xF788, 0x9C8C, 0xF789, 0x9C8F, 0xF78A, 0x9C93,
+	0xF78B, 0x9C96, 0xF78C, 0x9C97, 0xF78D, 0x9C98, 0xF78E, 0x9C99,
+	0xF78F, 0x9C9D, 0xF790, 0x9CAA, 0xF791, 0x9CAC, 0xF792, 0x9CAF,
+	0xF793, 0x9CB9, 0xF794, 0x9CBE, 0xF795, 0x9CBF, 0xF796, 0x9CC0,
+	0xF797, 0x9CC1, 0xF798, 0x9CC2, 0xF799, 0x9CC8, 0xF79A, 0x9CC9,
+	0xF79B, 0x9CD1, 0xF79C, 0x9CD2, 0xF79D, 0x9CDA, 0xF79E, 0x9CDB,
+	0xF79F, 0x9CE0, 0xF7A0, 0x9CE1, 0xF7A1, 0x9CCC, 0xF7A2, 0x9CCD,
+	0xF7A3, 0x9CCE, 0xF7A4, 0x9CCF, 0xF7A5, 0x9CD0, 0xF7A6, 0x9CD3,
+	0xF7A7, 0x9CD4, 0xF7A8, 0x9CD5, 0xF7A9, 0x9CD7, 0xF7AA, 0x9CD8,
+	0xF7AB, 0x9CD9, 0xF7AC, 0x9CDC, 0xF7AD, 0x9CDD, 0xF7AE, 0x9CDF,
+	0xF7AF, 0x9CE2, 0xF7B0, 0x977C, 0xF7B1, 0x9785, 0xF7B2, 0x9791,
+	0xF7B3, 0x9792, 0xF7B4, 0x9794, 0xF7B5, 0x97AF, 0xF7B6, 0x97AB,
+	0xF7B7, 0x97A3, 0xF7B8, 0x97B2, 0xF7B9, 0x97B4, 0xF7BA, 0x9AB1,
+	0xF7BB, 0x9AB0, 0xF7BC, 0x9AB7, 0xF7BD, 0x9E58, 0xF7BE, 0x9AB6,
+	0xF7BF, 0x9ABA, 0xF7C0, 0x9ABC, 0xF7C1, 0x9AC1, 0xF7C2, 0x9AC0,
+	0xF7C3, 0x9AC5, 0xF7C4, 0x9AC2, 0xF7C5, 0x9ACB, 0xF7C6, 0x9ACC,
+	0xF7C7, 0x9AD1, 0xF7C8, 0x9B45, 0xF7C9, 0x9B43, 0xF7CA, 0x9B47,
+	0xF7CB, 0x9B49, 0xF7CC, 0x9B48, 0xF7CD, 0x9B4D, 0xF7CE, 0x9B51,
+	0xF7CF, 0x98E8, 0xF7D0, 0x990D, 0xF7D1, 0x992E, 0xF7D2, 0x9955,
+	0xF7D3, 0x9954, 0xF7D4, 0x9ADF, 0xF7D5, 0x9AE1, 0xF7D6, 0x9AE6,
+	0xF7D7, 0x9AEF, 0xF7D8, 0x9AEB, 0xF7D9, 0x9AFB, 0xF7DA, 0x9AED,
+	0xF7DB, 0x9AF9, 0xF7DC, 0x9B08, 0xF7DD, 0x9B0F, 0xF7DE, 0x9B13,
+	0xF7DF, 0x9B1F, 0xF7E0, 0x9B23, 0xF7E1, 0x9EBD, 0xF7E2, 0x9EBE,
+	0xF7E3, 0x7E3B, 0xF7E4, 0x9E82, 0xF7E5, 0x9E87, 0xF7E6, 0x9E88,
+	0xF7E7, 0x9E8B, 0xF7E8, 0x9E92, 0xF7E9, 0x93D6, 0xF7EA, 0x9E9D,
+	0xF7EB, 0x9E9F, 0xF7EC, 0x9EDB, 0xF7ED, 0x9EDC, 0xF7EE, 0x9EDD,
+	0xF7EF, 0x9EE0, 0xF7F0, 0x9EDF, 0xF7F1, 0x9EE2, 0xF7F2, 0x9EE9,
+	0xF7F3, 0x9EE7, 0xF7F4, 0x9EE5, 0xF7F5, 0x9EEA, 0xF7F6, 0x9EEF,
+	0xF7F7, 0x9F22, 0xF7F8, 0x9F2C, 0xF7F9, 0x9F2F, 0xF7FA, 0x9F39,
+	0xF7FB, 0x9F37, 0xF7FC, 0x9F3D, 0xF7FD, 0x9F3E, 0xF7FE, 0x9F44,
+	0xF840, 0x9CE3, 0xF841, 0x9CE4, 0xF842, 0x9CE5, 0xF843, 0x9CE6,
+	0xF844, 0x9CE7, 0xF845, 0x9CE8, 0xF846, 0x9CE9, 0xF847, 0x9CEA,
+	0xF848, 0x9CEB, 0xF849, 0x9CEC, 0xF84A, 0x9CED, 0xF84B, 0x9CEE,
+	0xF84C, 0x9CEF, 0xF84D, 0x9CF0, 0xF84E, 0x9CF1, 0xF84F, 0x9CF2,
+	0xF850, 0x9CF3, 0xF851, 0x9CF4, 0xF852, 0x9CF5, 0xF853, 0x9CF6,
+	0xF854, 0x9CF7, 0xF855, 0x9CF8, 0xF856, 0x9CF9, 0xF857, 0x9CFA,
+	0xF858, 0x9CFB, 0xF859, 0x9CFC, 0xF85A, 0x9CFD, 0xF85B, 0x9CFE,
+	0xF85C, 0x9CFF, 0xF85D, 0x9D00, 0xF85E, 0x9D01, 0xF85F, 0x9D02,
+	0xF860, 0x9D03, 0xF861, 0x9D04, 0xF862, 0x9D05, 0xF863, 0x9D06,
+	0xF864, 0x9D07, 0xF865, 0x9D08, 0xF866, 0x9D09, 0xF867, 0x9D0A,
+	0xF868, 0x9D0B, 0xF869, 0x9D0C, 0xF86A, 0x9D0D, 0xF86B, 0x9D0E,
+	0xF86C, 0x9D0F, 0xF86D, 0x9D10, 0xF86E, 0x9D11, 0xF86F, 0x9D12,
+	0xF870, 0x9D13, 0xF871, 0x9D14, 0xF872, 0x9D15, 0xF873, 0x9D16,
+	0xF874, 0x9D17, 0xF875, 0x9D18, 0xF876, 0x9D19, 0xF877, 0x9D1A,
+	0xF878, 0x9D1B, 0xF879, 0x9D1C, 0xF87A, 0x9D1D, 0xF87B, 0x9D1E,
+	0xF87C, 0x9D1F, 0xF87D, 0x9D20, 0xF87E, 0x9D21, 0xF880, 0x9D22,
+	0xF881, 0x9D23, 0xF882, 0x9D24, 0xF883, 0x9D25, 0xF884, 0x9D26,
+	0xF885, 0x9D27, 0xF886, 0x9D28, 0xF887, 0x9D29, 0xF888, 0x9D2A,
+	0xF889, 0x9D2B, 0xF88A, 0x9D2C, 0xF88B, 0x9D2D, 0xF88C, 0x9D2E,
+	0xF88D, 0x9D2F, 0xF88E, 0x9D30, 0xF88F, 0x9D31, 0xF890, 0x9D32,
+	0xF891, 0x9D33, 0xF892, 0x9D34, 0xF893, 0x9D35, 0xF894, 0x9D36,
+	0xF895, 0x9D37, 0xF896, 0x9D38, 0xF897, 0x9D39, 0xF898, 0x9D3A,
+	0xF899, 0x9D3B, 0xF89A, 0x9D3C, 0xF89B, 0x9D3D, 0xF89C, 0x9D3E,
+	0xF89D, 0x9D3F, 0xF89E, 0x9D40, 0xF89F, 0x9D41, 0xF8A0, 0x9D42,
+	0xF940, 0x9D43, 0xF941, 0x9D44, 0xF942, 0x9D45, 0xF943, 0x9D46,
+	0xF944, 0x9D47, 0xF945, 0x9D48, 0xF946, 0x9D49, 0xF947, 0x9D4A,
+	0xF948, 0x9D4B, 0xF949, 0x9D4C, 0xF94A, 0x9D4D, 0xF94B, 0x9D4E,
+	0xF94C, 0x9D4F, 0xF94D, 0x9D50, 0xF94E, 0x9D51, 0xF94F, 0x9D52,
+	0xF950, 0x9D53, 0xF951, 0x9D54, 0xF952, 0x9D55, 0xF953, 0x9D56,
+	0xF954, 0x9D57, 0xF955, 0x9D58, 0xF956, 0x9D59, 0xF957, 0x9D5A,
+	0xF958, 0x9D5B, 0xF959, 0x9D5C, 0xF95A, 0x9D5D, 0xF95B, 0x9D5E,
+	0xF95C, 0x9D5F, 0xF95D, 0x9D60, 0xF95E, 0x9D61, 0xF95F, 0x9D62,
+	0xF960, 0x9D63, 0xF961, 0x9D64, 0xF962, 0x9D65, 0xF963, 0x9D66,
+	0xF964, 0x9D67, 0xF965, 0x9D68, 0xF966, 0x9D69, 0xF967, 0x9D6A,
+	0xF968, 0x9D6B, 0xF969, 0x9D6C, 0xF96A, 0x9D6D, 0xF96B, 0x9D6E,
+	0xF96C, 0x9D6F, 0xF96D, 0x9D70, 0xF96E, 0x9D71, 0xF96F, 0x9D72,
+	0xF970, 0x9D73, 0xF971, 0x9D74, 0xF972, 0x9D75, 0xF973, 0x9D76,
+	0xF974, 0x9D77, 0xF975, 0x9D78, 0xF976, 0x9D79, 0xF977, 0x9D7A,
+	0xF978, 0x9D7B, 0xF979, 0x9D7C, 0xF97A, 0x9D7D, 0xF97B, 0x9D7E,
+	0xF97C, 0x9D7F, 0xF97D, 0x9D80, 0xF97E, 0x9D81, 0xF980, 0x9D82,
+	0xF981, 0x9D83, 0xF982, 0x9D84, 0xF983, 0x9D85, 0xF984, 0x9D86,
+	0xF985, 0x9D87, 0xF986, 0x9D88, 0xF987, 0x9D89, 0xF988, 0x9D8A,
+	0xF989, 0x9D8B, 0xF98A, 0x9D8C, 0xF98B, 0x9D8D, 0xF98C, 0x9D8E,
+	0xF98D, 0x9D8F, 0xF98E, 0x9D90, 0xF98F, 0x9D91, 0xF990, 0x9D92,
+	0xF991, 0x9D93, 0xF992, 0x9D94, 0xF993, 0x9D95, 0xF994, 0x9D96,
+	0xF995, 0x9D97, 0xF996, 0x9D98, 0xF997, 0x9D99, 0xF998, 0x9D9A,
+	0xF999, 0x9D9B, 0xF99A, 0x9D9C, 0xF99B, 0x9D9D, 0xF99C, 0x9D9E,
+	0xF99D, 0x9D9F, 0xF99E, 0x9DA0, 0xF99F, 0x9DA1, 0xF9A0, 0x9DA2,
+	0xFA40, 0x9DA3, 0xFA41, 0x9DA4, 0xFA42, 0x9DA5, 0xFA43, 0x9DA6,
+	0xFA44, 0x9DA7, 0xFA45, 0x9DA8, 0xFA46, 0x9DA9, 0xFA47, 0x9DAA,
+	0xFA48, 0x9DAB, 0xFA49, 0x9DAC, 0xFA4A, 0x9DAD, 0xFA4B, 0x9DAE,
+	0xFA4C, 0x9DAF, 0xFA4D, 0x9DB0, 0xFA4E, 0x9DB1, 0xFA4F, 0x9DB2,
+	0xFA50, 0x9DB3, 0xFA51, 0x9DB4, 0xFA52, 0x9DB5, 0xFA53, 0x9DB6,
+	0xFA54, 0x9DB7, 0xFA55, 0x9DB8, 0xFA56, 0x9DB9, 0xFA57, 0x9DBA,
+	0xFA58, 0x9DBB, 0xFA59, 0x9DBC, 0xFA5A, 0x9DBD, 0xFA5B, 0x9DBE,
+	0xFA5C, 0x9DBF, 0xFA5D, 0x9DC0, 0xFA5E, 0x9DC1, 0xFA5F, 0x9DC2,
+	0xFA60, 0x9DC3, 0xFA61, 0x9DC4, 0xFA62, 0x9DC5, 0xFA63, 0x9DC6,
+	0xFA64, 0x9DC7, 0xFA65, 0x9DC8, 0xFA66, 0x9DC9, 0xFA67, 0x9DCA,
+	0xFA68, 0x9DCB, 0xFA69, 0x9DCC, 0xFA6A, 0x9DCD, 0xFA6B, 0x9DCE,
+	0xFA6C, 0x9DCF, 0xFA6D, 0x9DD0, 0xFA6E, 0x9DD1, 0xFA6F, 0x9DD2,
+	0xFA70, 0x9DD3, 0xFA71, 0x9DD4, 0xFA72, 0x9DD5, 0xFA73, 0x9DD6,
+	0xFA74, 0x9DD7, 0xFA75, 0x9DD8, 0xFA76, 0x9DD9, 0xFA77, 0x9DDA,
+	0xFA78, 0x9DDB, 0xFA79, 0x9DDC, 0xFA7A, 0x9DDD, 0xFA7B, 0x9DDE,
+	0xFA7C, 0x9DDF, 0xFA7D, 0x9DE0, 0xFA7E, 0x9DE1, 0xFA80, 0x9DE2,
+	0xFA81, 0x9DE3, 0xFA82, 0x9DE4, 0xFA83, 0x9DE5, 0xFA84, 0x9DE6,
+	0xFA85, 0x9DE7, 0xFA86, 0x9DE8, 0xFA87, 0x9DE9, 0xFA88, 0x9DEA,
+	0xFA89, 0x9DEB, 0xFA8A, 0x9DEC, 0xFA8B, 0x9DED, 0xFA8C, 0x9DEE,
+	0xFA8D, 0x9DEF, 0xFA8E, 0x9DF0, 0xFA8F, 0x9DF1, 0xFA90, 0x9DF2,
+	0xFA91, 0x9DF3, 0xFA92, 0x9DF4, 0xFA93, 0x9DF5, 0xFA94, 0x9DF6,
+	0xFA95, 0x9DF7, 0xFA96, 0x9DF8, 0xFA97, 0x9DF9, 0xFA98, 0x9DFA,
+	0xFA99, 0x9DFB, 0xFA9A, 0x9DFC, 0xFA9B, 0x9DFD, 0xFA9C, 0x9DFE,
+	0xFA9D, 0x9DFF, 0xFA9E, 0x9E00, 0xFA9F, 0x9E01, 0xFAA0, 0x9E02,
+	0xFB40, 0x9E03, 0xFB41, 0x9E04, 0xFB42, 0x9E05, 0xFB43, 0x9E06,
+	0xFB44, 0x9E07, 0xFB45, 0x9E08, 0xFB46, 0x9E09, 0xFB47, 0x9E0A,
+	0xFB48, 0x9E0B, 0xFB49, 0x9E0C, 0xFB4A, 0x9E0D, 0xFB4B, 0x9E0E,
+	0xFB4C, 0x9E0F, 0xFB4D, 0x9E10, 0xFB4E, 0x9E11, 0xFB4F, 0x9E12,
+	0xFB50, 0x9E13, 0xFB51, 0x9E14, 0xFB52, 0x9E15, 0xFB53, 0x9E16,
+	0xFB54, 0x9E17, 0xFB55, 0x9E18, 0xFB56, 0x9E19, 0xFB57, 0x9E1A,
+	0xFB58, 0x9E1B, 0xFB59, 0x9E1C, 0xFB5A, 0x9E1D, 0xFB5B, 0x9E1E,
+	0xFB5C, 0x9E24, 0xFB5D, 0x9E27, 0xFB5E, 0x9E2E, 0xFB5F, 0x9E30,
+	0xFB60, 0x9E34, 0xFB61, 0x9E3B, 0xFB62, 0x9E3C, 0xFB63, 0x9E40,
+	0xFB64, 0x9E4D, 0xFB65, 0x9E50, 0xFB66, 0x9E52, 0xFB67, 0x9E53,
+	0xFB68, 0x9E54, 0xFB69, 0x9E56, 0xFB6A, 0x9E59, 0xFB6B, 0x9E5D,
+	0xFB6C, 0x9E5F, 0xFB6D, 0x9E60, 0xFB6E, 0x9E61, 0xFB6F, 0x9E62,
+	0xFB70, 0x9E65, 0xFB71, 0x9E6E, 0xFB72, 0x9E6F, 0xFB73, 0x9E72,
+	0xFB74, 0x9E74, 0xFB75, 0x9E75, 0xFB76, 0x9E76, 0xFB77, 0x9E77,
+	0xFB78, 0x9E78, 0xFB79, 0x9E79, 0xFB7A, 0x9E7A, 0xFB7B, 0x9E7B,
+	0xFB7C, 0x9E7C, 0xFB7D, 0x9E7D, 0xFB7E, 0x9E80, 0xFB80, 0x9E81,
+	0xFB81, 0x9E83, 0xFB82, 0x9E84, 0xFB83, 0x9E85, 0xFB84, 0x9E86,
+	0xFB85, 0x9E89, 0xFB86, 0x9E8A, 0xFB87, 0x9E8C, 0xFB88, 0x9E8D,
+	0xFB89, 0x9E8E, 0xFB8A, 0x9E8F, 0xFB8B, 0x9E90, 0xFB8C, 0x9E91,
+	0xFB8D, 0x9E94, 0xFB8E, 0x9E95, 0xFB8F, 0x9E96, 0xFB90, 0x9E97,
+	0xFB91, 0x9E98, 0xFB92, 0x9E99, 0xFB93, 0x9E9A, 0xFB94, 0x9E9B,
+	0xFB95, 0x9E9C, 0xFB96, 0x9E9E, 0xFB97, 0x9EA0, 0xFB98, 0x9EA1,
+	0xFB99, 0x9EA2, 0xFB9A, 0x9EA3, 0xFB9B, 0x9EA4, 0xFB9C, 0x9EA5,
+	0xFB9D, 0x9EA7, 0xFB9E, 0x9EA8, 0xFB9F, 0x9EA9, 0xFBA0, 0x9EAA,
+	0xFC40, 0x9EAB, 0xFC41, 0x9EAC, 0xFC42, 0x9EAD, 0xFC43, 0x9EAE,
+	0xFC44, 0x9EAF, 0xFC45, 0x9EB0, 0xFC46, 0x9EB1, 0xFC47, 0x9EB2,
+	0xFC48, 0x9EB3, 0xFC49, 0x9EB5, 0xFC4A, 0x9EB6, 0xFC4B, 0x9EB7,
+	0xFC4C, 0x9EB9, 0xFC4D, 0x9EBA, 0xFC4E, 0x9EBC, 0xFC4F, 0x9EBF,
+	0xFC50, 0x9EC0, 0xFC51, 0x9EC1, 0xFC52, 0x9EC2, 0xFC53, 0x9EC3,
+	0xFC54, 0x9EC5, 0xFC55, 0x9EC6, 0xFC56, 0x9EC7, 0xFC57, 0x9EC8,
+	0xFC58, 0x9ECA, 0xFC59, 0x9ECB, 0xFC5A, 0x9ECC, 0xFC5B, 0x9ED0,
+	0xFC5C, 0x9ED2, 0xFC5D, 0x9ED3, 0xFC5E, 0x9ED5, 0xFC5F, 0x9ED6,
+	0xFC60, 0x9ED7, 0xFC61, 0x9ED9, 0xFC62, 0x9EDA, 0xFC63, 0x9EDE,
+	0xFC64, 0x9EE1, 0xFC65, 0x9EE3, 0xFC66, 0x9EE4, 0xFC67, 0x9EE6,
+	0xFC68, 0x9EE8, 0xFC69, 0x9EEB, 0xFC6A, 0x9EEC, 0xFC6B, 0x9EED,
+	0xFC6C, 0x9EEE, 0xFC6D, 0x9EF0, 0xFC6E, 0x9EF1, 0xFC6F, 0x9EF2,
+	0xFC70, 0x9EF3, 0xFC71, 0x9EF4, 0xFC72, 0x9EF5, 0xFC73, 0x9EF6,
+	0xFC74, 0x9EF7, 0xFC75, 0x9EF8, 0xFC76, 0x9EFA, 0xFC77, 0x9EFD,
+	0xFC78, 0x9EFF, 0xFC79, 0x9F00, 0xFC7A, 0x9F01, 0xFC7B, 0x9F02,
+	0xFC7C, 0x9F03, 0xFC7D, 0x9F04, 0xFC7E, 0x9F05, 0xFC80, 0x9F06,
+	0xFC81, 0x9F07, 0xFC82, 0x9F08, 0xFC83, 0x9F09, 0xFC84, 0x9F0A,
+	0xFC85, 0x9F0C, 0xFC86, 0x9F0F, 0xFC87, 0x9F11, 0xFC88, 0x9F12,
+	0xFC89, 0x9F14, 0xFC8A, 0x9F15, 0xFC8B, 0x9F16, 0xFC8C, 0x9F18,
+	0xFC8D, 0x9F1A, 0xFC8E, 0x9F1B, 0xFC8F, 0x9F1C, 0xFC90, 0x9F1D,
+	0xFC91, 0x9F1E, 0xFC92, 0x9F1F, 0xFC93, 0x9F21, 0xFC94, 0x9F23,
+	0xFC95, 0x9F24, 0xFC96, 0x9F25, 0xFC97, 0x9F26, 0xFC98, 0x9F27,
+	0xFC99, 0x9F28, 0xFC9A, 0x9F29, 0xFC9B, 0x9F2A, 0xFC9C, 0x9F2B,
+	0xFC9D, 0x9F2D, 0xFC9E, 0x9F2E, 0xFC9F, 0x9F30, 0xFCA0, 0x9F31,
+	0xFD40, 0x9F32, 0xFD41, 0x9F33, 0xFD42, 0x9F34, 0xFD43, 0x9F35,
+	0xFD44, 0x9F36, 0xFD45, 0x9F38, 0xFD46, 0x9F3A, 0xFD47, 0x9F3C,
+	0xFD48, 0x9F3F, 0xFD49, 0x9F40, 0xFD4A, 0x9F41, 0xFD4B, 0x9F42,
+	0xFD4C, 0x9F43, 0xFD4D, 0x9F45, 0xFD4E, 0x9F46, 0xFD4F, 0x9F47,
+	0xFD50, 0x9F48, 0xFD51, 0x9F49, 0xFD52, 0x9F4A, 0xFD53, 0x9F4B,
+	0xFD54, 0x9F4C, 0xFD55, 0x9F4D, 0xFD56, 0x9F4E, 0xFD57, 0x9F4F,
+	0xFD58, 0x9F52, 0xFD59, 0x9F53, 0xFD5A, 0x9F54, 0xFD5B, 0x9F55,
+	0xFD5C, 0x9F56, 0xFD5D, 0x9F57, 0xFD5E, 0x9F58, 0xFD5F, 0x9F59,
+	0xFD60, 0x9F5A, 0xFD61, 0x9F5B, 0xFD62, 0x9F5C, 0xFD63, 0x9F5D,
+	0xFD64, 0x9F5E, 0xFD65, 0x9F5F, 0xFD66, 0x9F60, 0xFD67, 0x9F61,
+	0xFD68, 0x9F62, 0xFD69, 0x9F63, 0xFD6A, 0x9F64, 0xFD6B, 0x9F65,
+	0xFD6C, 0x9F66, 0xFD6D, 0x9F67, 0xFD6E, 0x9F68, 0xFD6F, 0x9F69,
+	0xFD70, 0x9F6A, 0xFD71, 0x9F6B, 0xFD72, 0x9F6C, 0xFD73, 0x9F6D,
+	0xFD74, 0x9F6E, 0xFD75, 0x9F6F, 0xFD76, 0x9F70, 0xFD77, 0x9F71,
+	0xFD78, 0x9F72, 0xFD79, 0x9F73, 0xFD7A, 0x9F74, 0xFD7B, 0x9F75,
+	0xFD7C, 0x9F76, 0xFD7D, 0x9F77, 0xFD7E, 0x9F78, 0xFD80, 0x9F79,
+	0xFD81, 0x9F7A, 0xFD82, 0x9F7B, 0xFD83, 0x9F7C, 0xFD84, 0x9F7D,
+	0xFD85, 0x9F7E, 0xFD86, 0x9F81, 0xFD87, 0x9F82, 0xFD88, 0x9F8D,
+	0xFD89, 0x9F8E, 0xFD8A, 0x9F8F, 0xFD8B, 0x9F90, 0xFD8C, 0x9F91,
+	0xFD8D, 0x9F92, 0xFD8E, 0x9F93, 0xFD8F, 0x9F94, 0xFD90, 0x9F95,
+	0xFD91, 0x9F96, 0xFD92, 0x9F97, 0xFD93, 0x9F98, 0xFD94, 0x9F9C,
+	0xFD95, 0x9F9D, 0xFD96, 0x9F9E, 0xFD97, 0x9FA1, 0xFD98, 0x9FA2,
+	0xFD99, 0x9FA3, 0xFD9A, 0x9FA4, 0xFD9B, 0x9FA5, 0xFD9C, 0xF92C,
+	0xFD9D, 0xF979, 0xFD9E, 0xF995, 0xFD9F, 0xF9E7, 0xFDA0, 0xF9F1,
+	0xFE40, 0xFA0C, 0xFE41, 0xFA0D, 0xFE42, 0xFA0E, 0xFE43, 0xFA0F,
+	0xFE44, 0xFA11, 0xFE45, 0xFA13, 0xFE46, 0xFA14, 0xFE47, 0xFA18,
+	0xFE48, 0xFA1F, 0xFE49, 0xFA20, 0xFE4A, 0xFA21, 0xFE4B, 0xFA23,
+	0xFE4C, 0xFA24, 0xFE4D, 0xFA27, 0xFE4E, 0xFA28, 0xFE4F, 0xFA29,
+	0, 0
+};
+
+
+
+WCHAR ff_convert (	/* Converted code, 0 means conversion error */
+	WCHAR	src,	/* Character code to be converted */
+	UINT	dir		/* 0: Unicode to OEMCP, 1: OEMCP to Unicode */
+)
+{
+	const WCHAR *p;
+	WCHAR c;
+	int i, n, li, hi;
+
+
+	if (src < 0x80) {	/* ASCII */
+		c = src;
+	} else {
+		if (dir) {		/* OEMCP to unicode */
+			p = oem2uni;
+			hi = sizeof(oem2uni) / 4 - 1;
+		} else {		/* Unicode to OEMCP */
+			p = uni2oem;
+			hi = sizeof(uni2oem) / 4 - 1;
+		}
+		li = 0;
+		for (n = 16; n; n--) {
+			i = li + (hi - li) / 2;
+			if (src == p[i * 2]) break;
+			if (src > p[i * 2])
+				li = i;
+			else
+				hi = i;
+		}
+		c = n ? p[i * 2 + 1] : 0;
+	}
+
+	return c;
+}
+#else
+#error This file is not needed in current configuration.
+
+#endif
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/option/cc949.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/option/cc949.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/option/cc949.c	(revision 453)
@@ -0,0 +1,8588 @@
+/*------------------------------------------------------------------------*/
+/* Unicode - OEM code bidirectional converter  (C)ChaN, 2009              */
+/*                                                                        */
+/* CP949 (Korean)                                                         */
+/*------------------------------------------------------------------------*/
+
+#include "../ff.h"
+
+
+#if _USE_LFN && _CODE_PAGE == 949
+
+
+static
+const WCHAR uni2oem[] = {
+/*  Unicode - OEM,  Unicode - OEM,  Unicode - OEM,  Unicode - OEM */
+	0x00A1, 0xA2AE, 0x00A4, 0xA2B4, 0x00A7, 0xA1D7, 0x00A8, 0xA1A7,
+	0x00AA, 0xA8A3, 0x00AD, 0xA1A9, 0x00AE, 0xA2E7, 0x00B0, 0xA1C6,
+	0x00B1, 0xA1BE, 0x00B2, 0xA9F7, 0x00B3, 0xA9F8, 0x00B4, 0xA2A5,
+	0x00B6, 0xA2D2, 0x00B7, 0xA1A4, 0x00B8, 0xA2AC, 0x00B9, 0xA9F6,
+	0x00BA, 0xA8AC, 0x00BC, 0xA8F9, 0x00BD, 0xA8F6, 0x00BE, 0xA8FA,
+	0x00BF, 0xA2AF, 0x00C6, 0xA8A1, 0x00D0, 0xA8A2, 0x00D7, 0xA1BF,
+	0x00D8, 0xA8AA, 0x00DE, 0xA8AD, 0x00DF, 0xA9AC, 0x00E6, 0xA9A1,
+	0x00F0, 0xA9A3, 0x00F7, 0xA1C0, 0x00F8, 0xA9AA, 0x00FE, 0xA9AD,
+	0x0111, 0xA9A2, 0x0126, 0xA8A4, 0x0127, 0xA9A4, 0x0131, 0xA9A5,
+	0x0132, 0xA8A6, 0x0133, 0xA9A6, 0x0138, 0xA9A7, 0x013F, 0xA8A8,
+	0x0140, 0xA9A8, 0x0141, 0xA8A9, 0x0142, 0xA9A9, 0x0149, 0xA9B0,
+	0x014A, 0xA8AF, 0x014B, 0xA9AF, 0x0152, 0xA8AB, 0x0153, 0xA9AB,
+	0x0166, 0xA8AE, 0x0167, 0xA9AE, 0x02C7, 0xA2A7, 0x02D0, 0xA2B0,
+	0x02D8, 0xA2A8, 0x02D9, 0xA2AB, 0x02DA, 0xA2AA, 0x02DB, 0xA2AD,
+	0x02DD, 0xA2A9, 0x0391, 0xA5C1, 0x0392, 0xA5C2, 0x0393, 0xA5C3,
+	0x0394, 0xA5C4, 0x0395, 0xA5C5, 0x0396, 0xA5C6, 0x0397, 0xA5C7,
+	0x0398, 0xA5C8, 0x0399, 0xA5C9, 0x039A, 0xA5CA, 0x039B, 0xA5CB,
+	0x039C, 0xA5CC, 0x039D, 0xA5CD, 0x039E, 0xA5CE, 0x039F, 0xA5CF,
+	0x03A0, 0xA5D0, 0x03A1, 0xA5D1, 0x03A3, 0xA5D2, 0x03A4, 0xA5D3,
+	0x03A5, 0xA5D4, 0x03A6, 0xA5D5, 0x03A7, 0xA5D6, 0x03A8, 0xA5D7,
+	0x03A9, 0xA5D8, 0x03B1, 0xA5E1, 0x03B2, 0xA5E2, 0x03B3, 0xA5E3,
+	0x03B4, 0xA5E4, 0x03B5, 0xA5E5, 0x03B6, 0xA5E6, 0x03B7, 0xA5E7,
+	0x03B8, 0xA5E8, 0x03B9, 0xA5E9, 0x03BA, 0xA5EA, 0x03BB, 0xA5EB,
+	0x03BC, 0xA5EC, 0x03BD, 0xA5ED, 0x03BE, 0xA5EE, 0x03BF, 0xA5EF,
+	0x03C0, 0xA5F0, 0x03C1, 0xA5F1, 0x03C3, 0xA5F2, 0x03C4, 0xA5F3,
+	0x03C5, 0xA5F4, 0x03C6, 0xA5F5, 0x03C7, 0xA5F6, 0x03C8, 0xA5F7,
+	0x03C9, 0xA5F8, 0x0401, 0xACA7, 0x0410, 0xACA1, 0x0411, 0xACA2,
+	0x0412, 0xACA3, 0x0413, 0xACA4, 0x0414, 0xACA5, 0x0415, 0xACA6,
+	0x0416, 0xACA8, 0x0417, 0xACA9, 0x0418, 0xACAA, 0x0419, 0xACAB,
+	0x041A, 0xACAC, 0x041B, 0xACAD, 0x041C, 0xACAE, 0x041D, 0xACAF,
+	0x041E, 0xACB0, 0x041F, 0xACB1, 0x0420, 0xACB2, 0x0421, 0xACB3,
+	0x0422, 0xACB4, 0x0423, 0xACB5, 0x0424, 0xACB6, 0x0425, 0xACB7,
+	0x0426, 0xACB8, 0x0427, 0xACB9, 0x0428, 0xACBA, 0x0429, 0xACBB,
+	0x042A, 0xACBC, 0x042B, 0xACBD, 0x042C, 0xACBE, 0x042D, 0xACBF,
+	0x042E, 0xACC0, 0x042F, 0xACC1, 0x0430, 0xACD1, 0x0431, 0xACD2,
+	0x0432, 0xACD3, 0x0433, 0xACD4, 0x0434, 0xACD5, 0x0435, 0xACD6,
+	0x0436, 0xACD8, 0x0437, 0xACD9, 0x0438, 0xACDA, 0x0439, 0xACDB,
+	0x043A, 0xACDC, 0x043B, 0xACDD, 0x043C, 0xACDE, 0x043D, 0xACDF,
+	0x043E, 0xACE0, 0x043F, 0xACE1, 0x0440, 0xACE2, 0x0441, 0xACE3,
+	0x0442, 0xACE4, 0x0443, 0xACE5, 0x0444, 0xACE6, 0x0445, 0xACE7,
+	0x0446, 0xACE8, 0x0447, 0xACE9, 0x0448, 0xACEA, 0x0449, 0xACEB,
+	0x044A, 0xACEC, 0x044B, 0xACED, 0x044C, 0xACEE, 0x044D, 0xACEF,
+	0x044E, 0xACF0, 0x044F, 0xACF1, 0x0451, 0xACD7, 0x2015, 0xA1AA,
+	0x2018, 0xA1AE, 0x2019, 0xA1AF, 0x201C, 0xA1B0, 0x201D, 0xA1B1,
+	0x2020, 0xA2D3, 0x2021, 0xA2D4, 0x2025, 0xA1A5, 0x2026, 0xA1A6,
+	0x2030, 0xA2B6, 0x2032, 0xA1C7, 0x2033, 0xA1C8, 0x203B, 0xA1D8,
+	0x2074, 0xA9F9, 0x207F, 0xA9FA, 0x2081, 0xA9FB, 0x2082, 0xA9FC,
+	0x2083, 0xA9FD, 0x2084, 0xA9FE, 0x20AC, 0xA2E6, 0x2103, 0xA1C9,
+	0x2109, 0xA2B5, 0x2113, 0xA7A4, 0x2116, 0xA2E0, 0x2121, 0xA2E5,
+	0x2122, 0xA2E2, 0x2126, 0xA7D9, 0x212B, 0xA1CA, 0x2153, 0xA8F7,
+	0x2154, 0xA8F8, 0x215B, 0xA8FB, 0x215C, 0xA8FC, 0x215D, 0xA8FD,
+	0x215E, 0xA8FE, 0x2160, 0xA5B0, 0x2161, 0xA5B1, 0x2162, 0xA5B2,
+	0x2163, 0xA5B3, 0x2164, 0xA5B4, 0x2165, 0xA5B5, 0x2166, 0xA5B6,
+	0x2167, 0xA5B7, 0x2168, 0xA5B8, 0x2169, 0xA5B9, 0x2170, 0xA5A1,
+	0x2171, 0xA5A2, 0x2172, 0xA5A3, 0x2173, 0xA5A4, 0x2174, 0xA5A5,
+	0x2175, 0xA5A6, 0x2176, 0xA5A7, 0x2177, 0xA5A8, 0x2178, 0xA5A9,
+	0x2179, 0xA5AA, 0x2190, 0xA1E7, 0x2191, 0xA1E8, 0x2192, 0xA1E6,
+	0x2193, 0xA1E9, 0x2194, 0xA1EA, 0x2195, 0xA2D5, 0x2196, 0xA2D8,
+	0x2197, 0xA2D6, 0x2198, 0xA2D9, 0x2199, 0xA2D7, 0x21D2, 0xA2A1,
+	0x21D4, 0xA2A2, 0x2200, 0xA2A3, 0x2202, 0xA1D3, 0x2203, 0xA2A4,
+	0x2207, 0xA1D4, 0x2208, 0xA1F4, 0x220B, 0xA1F5, 0x220F, 0xA2B3,
+	0x2211, 0xA2B2, 0x221A, 0xA1EE, 0x221D, 0xA1F0, 0x221E, 0xA1C4,
+	0x2220, 0xA1D0, 0x2225, 0xA1AB, 0x2227, 0xA1FC, 0x2228, 0xA1FD,
+	0x2229, 0xA1FB, 0x222A, 0xA1FA, 0x222B, 0xA1F2, 0x222C, 0xA1F3,
+	0x222E, 0xA2B1, 0x2234, 0xA1C5, 0x2235, 0xA1F1, 0x223C, 0xA1AD,
+	0x223D, 0xA1EF, 0x2252, 0xA1D6, 0x2260, 0xA1C1, 0x2261, 0xA1D5,
+	0x2264, 0xA1C2, 0x2265, 0xA1C3, 0x226A, 0xA1EC, 0x226B, 0xA1ED,
+	0x2282, 0xA1F8, 0x2283, 0xA1F9, 0x2286, 0xA1F6, 0x2287, 0xA1F7,
+	0x2299, 0xA2C1, 0x22A5, 0xA1D1, 0x2312, 0xA1D2, 0x2460, 0xA8E7,
+	0x2461, 0xA8E8, 0x2462, 0xA8E9, 0x2463, 0xA8EA, 0x2464, 0xA8EB,
+	0x2465, 0xA8EC, 0x2466, 0xA8ED, 0x2467, 0xA8EE, 0x2468, 0xA8EF,
+	0x2469, 0xA8F0, 0x246A, 0xA8F1, 0x246B, 0xA8F2, 0x246C, 0xA8F3,
+	0x246D, 0xA8F4, 0x246E, 0xA8F5, 0x2474, 0xA9E7, 0x2475, 0xA9E8,
+	0x2476, 0xA9E9, 0x2477, 0xA9EA, 0x2478, 0xA9EB, 0x2479, 0xA9EC,
+	0x247A, 0xA9ED, 0x247B, 0xA9EE, 0x247C, 0xA9EF, 0x247D, 0xA9F0,
+	0x247E, 0xA9F1, 0x247F, 0xA9F2, 0x2480, 0xA9F3, 0x2481, 0xA9F4,
+	0x2482, 0xA9F5, 0x249C, 0xA9CD, 0x249D, 0xA9CE, 0x249E, 0xA9CF,
+	0x249F, 0xA9D0, 0x24A0, 0xA9D1, 0x24A1, 0xA9D2, 0x24A2, 0xA9D3,
+	0x24A3, 0xA9D4, 0x24A4, 0xA9D5, 0x24A5, 0xA9D6, 0x24A6, 0xA9D7,
+	0x24A7, 0xA9D8, 0x24A8, 0xA9D9, 0x24A9, 0xA9DA, 0x24AA, 0xA9DB,
+	0x24AB, 0xA9DC, 0x24AC, 0xA9DD, 0x24AD, 0xA9DE, 0x24AE, 0xA9DF,
+	0x24AF, 0xA9E0, 0x24B0, 0xA9E1, 0x24B1, 0xA9E2, 0x24B2, 0xA9E3,
+	0x24B3, 0xA9E4, 0x24B4, 0xA9E5, 0x24B5, 0xA9E6, 0x24D0, 0xA8CD,
+	0x24D1, 0xA8CE, 0x24D2, 0xA8CF, 0x24D3, 0xA8D0, 0x24D4, 0xA8D1,
+	0x24D5, 0xA8D2, 0x24D6, 0xA8D3, 0x24D7, 0xA8D4, 0x24D8, 0xA8D5,
+	0x24D9, 0xA8D6, 0x24DA, 0xA8D7, 0x24DB, 0xA8D8, 0x24DC, 0xA8D9,
+	0x24DD, 0xA8DA, 0x24DE, 0xA8DB, 0x24DF, 0xA8DC, 0x24E0, 0xA8DD,
+	0x24E1, 0xA8DE, 0x24E2, 0xA8DF, 0x24E3, 0xA8E0, 0x24E4, 0xA8E1,
+	0x24E5, 0xA8E2, 0x24E6, 0xA8E3, 0x24E7, 0xA8E4, 0x24E8, 0xA8E5,
+	0x24E9, 0xA8E6, 0x2500, 0xA6A1, 0x2501, 0xA6AC, 0x2502, 0xA6A2,
+	0x2503, 0xA6AD, 0x250C, 0xA6A3, 0x250D, 0xA6C8, 0x250E, 0xA6C7,
+	0x250F, 0xA6AE, 0x2510, 0xA6A4, 0x2511, 0xA6C2, 0x2512, 0xA6C1,
+	0x2513, 0xA6AF, 0x2514, 0xA6A6, 0x2515, 0xA6C6, 0x2516, 0xA6C5,
+	0x2517, 0xA6B1, 0x2518, 0xA6A5, 0x2519, 0xA6C4, 0x251A, 0xA6C3,
+	0x251B, 0xA6B0, 0x251C, 0xA6A7, 0x251D, 0xA6BC, 0x251E, 0xA6C9,
+	0x251F, 0xA6CA, 0x2520, 0xA6B7, 0x2521, 0xA6CB, 0x2522, 0xA6CC,
+	0x2523, 0xA6B2, 0x2524, 0xA6A9, 0x2525, 0xA6BE, 0x2526, 0xA6CD,
+	0x2527, 0xA6CE, 0x2528, 0xA6B9, 0x2529, 0xA6CF, 0x252A, 0xA6D0,
+	0x252B, 0xA6B4, 0x252C, 0xA6A8, 0x252D, 0xA6D1, 0x252E, 0xA6D2,
+	0x252F, 0xA6B8, 0x2530, 0xA6BD, 0x2531, 0xA6D3, 0x2532, 0xA6D4,
+	0x2533, 0xA6B3, 0x2534, 0xA6AA, 0x2535, 0xA6D5, 0x2536, 0xA6D6,
+	0x2537, 0xA6BA, 0x2538, 0xA6BF, 0x2539, 0xA6D7, 0x253A, 0xA6D8,
+	0x253B, 0xA6B5, 0x253C, 0xA6AB, 0x253D, 0xA6D9, 0x253E, 0xA6DA,
+	0x253F, 0xA6BB, 0x2540, 0xA6DB, 0x2541, 0xA6DC, 0x2542, 0xA6C0,
+	0x2543, 0xA6DD, 0x2544, 0xA6DE, 0x2545, 0xA6DF, 0x2546, 0xA6E0,
+	0x2547, 0xA6E1, 0x2548, 0xA6E2, 0x2549, 0xA6E3, 0x254A, 0xA6E4,
+	0x254B, 0xA6B6, 0x2592, 0xA2C6, 0x25A0, 0xA1E1, 0x25A1, 0xA1E0,
+	0x25A3, 0xA2C3, 0x25A4, 0xA2C7, 0x25A5, 0xA2C8, 0x25A6, 0xA2CB,
+	0x25A7, 0xA2CA, 0x25A8, 0xA2C9, 0x25A9, 0xA2CC, 0x25B2, 0xA1E3,
+	0x25B3, 0xA1E2, 0x25B6, 0xA2BA, 0x25B7, 0xA2B9, 0x25BC, 0xA1E5,
+	0x25BD, 0xA1E4, 0x25C0, 0xA2B8, 0x25C1, 0xA2B7, 0x25C6, 0xA1DF,
+	0x25C7, 0xA1DE, 0x25C8, 0xA2C2, 0x25CB, 0xA1DB, 0x25CE, 0xA1DD,
+	0x25CF, 0xA1DC, 0x25D0, 0xA2C4, 0x25D1, 0xA2C5, 0x2605, 0xA1DA,
+	0x2606, 0xA1D9, 0x260E, 0xA2CF, 0x260F, 0xA2CE, 0x261C, 0xA2D0,
+	0x261E, 0xA2D1, 0x2640, 0xA1CF, 0x2642, 0xA1CE, 0x2660, 0xA2BC,
+	0x2661, 0xA2BD, 0x2663, 0xA2C0, 0x2664, 0xA2BB, 0x2665, 0xA2BE,
+	0x2667, 0xA2BF, 0x2668, 0xA2CD, 0x2669, 0xA2DB, 0x266A, 0xA2DC,
+	0x266C, 0xA2DD, 0x266D, 0xA2DA, 0x3000, 0xA1A1, 0x3001, 0xA1A2,
+	0x3002, 0xA1A3, 0x3003, 0xA1A8, 0x3008, 0xA1B4, 0x3009, 0xA1B5,
+	0x300A, 0xA1B6, 0x300B, 0xA1B7, 0x300C, 0xA1B8, 0x300D, 0xA1B9,
+	0x300E, 0xA1BA, 0x300F, 0xA1BB, 0x3010, 0xA1BC, 0x3011, 0xA1BD,
+	0x3013, 0xA1EB, 0x3014, 0xA1B2, 0x3015, 0xA1B3, 0x3041, 0xAAA1,
+	0x3042, 0xAAA2, 0x3043, 0xAAA3, 0x3044, 0xAAA4, 0x3045, 0xAAA5,
+	0x3046, 0xAAA6, 0x3047, 0xAAA7, 0x3048, 0xAAA8, 0x3049, 0xAAA9,
+	0x304A, 0xAAAA, 0x304B, 0xAAAB, 0x304C, 0xAAAC, 0x304D, 0xAAAD,
+	0x304E, 0xAAAE, 0x304F, 0xAAAF, 0x3050, 0xAAB0, 0x3051, 0xAAB1,
+	0x3052, 0xAAB2, 0x3053, 0xAAB3, 0x3054, 0xAAB4, 0x3055, 0xAAB5,
+	0x3056, 0xAAB6, 0x3057, 0xAAB7, 0x3058, 0xAAB8, 0x3059, 0xAAB9,
+	0x305A, 0xAABA, 0x305B, 0xAABB, 0x305C, 0xAABC, 0x305D, 0xAABD,
+	0x305E, 0xAABE, 0x305F, 0xAABF, 0x3060, 0xAAC0, 0x3061, 0xAAC1,
+	0x3062, 0xAAC2, 0x3063, 0xAAC3, 0x3064, 0xAAC4, 0x3065, 0xAAC5,
+	0x3066, 0xAAC6, 0x3067, 0xAAC7, 0x3068, 0xAAC8, 0x3069, 0xAAC9,
+	0x306A, 0xAACA, 0x306B, 0xAACB, 0x306C, 0xAACC, 0x306D, 0xAACD,
+	0x306E, 0xAACE, 0x306F, 0xAACF, 0x3070, 0xAAD0, 0x3071, 0xAAD1,
+	0x3072, 0xAAD2, 0x3073, 0xAAD3, 0x3074, 0xAAD4, 0x3075, 0xAAD5,
+	0x3076, 0xAAD6, 0x3077, 0xAAD7, 0x3078, 0xAAD8, 0x3079, 0xAAD9,
+	0x307A, 0xAADA, 0x307B, 0xAADB, 0x307C, 0xAADC, 0x307D, 0xAADD,
+	0x307E, 0xAADE, 0x307F, 0xAADF, 0x3080, 0xAAE0, 0x3081, 0xAAE1,
+	0x3082, 0xAAE2, 0x3083, 0xAAE3, 0x3084, 0xAAE4, 0x3085, 0xAAE5,
+	0x3086, 0xAAE6, 0x3087, 0xAAE7, 0x3088, 0xAAE8, 0x3089, 0xAAE9,
+	0x308A, 0xAAEA, 0x308B, 0xAAEB, 0x308C, 0xAAEC, 0x308D, 0xAAED,
+	0x308E, 0xAAEE, 0x308F, 0xAAEF, 0x3090, 0xAAF0, 0x3091, 0xAAF1,
+	0x3092, 0xAAF2, 0x3093, 0xAAF3, 0x30A1, 0xABA1, 0x30A2, 0xABA2,
+	0x30A3, 0xABA3, 0x30A4, 0xABA4, 0x30A5, 0xABA5, 0x30A6, 0xABA6,
+	0x30A7, 0xABA7, 0x30A8, 0xABA8, 0x30A9, 0xABA9, 0x30AA, 0xABAA,
+	0x30AB, 0xABAB, 0x30AC, 0xABAC, 0x30AD, 0xABAD, 0x30AE, 0xABAE,
+	0x30AF, 0xABAF, 0x30B0, 0xABB0, 0x30B1, 0xABB1, 0x30B2, 0xABB2,
+	0x30B3, 0xABB3, 0x30B4, 0xABB4, 0x30B5, 0xABB5, 0x30B6, 0xABB6,
+	0x30B7, 0xABB7, 0x30B8, 0xABB8, 0x30B9, 0xABB9, 0x30BA, 0xABBA,
+	0x30BB, 0xABBB, 0x30BC, 0xABBC, 0x30BD, 0xABBD, 0x30BE, 0xABBE,
+	0x30BF, 0xABBF, 0x30C0, 0xABC0, 0x30C1, 0xABC1, 0x30C2, 0xABC2,
+	0x30C3, 0xABC3, 0x30C4, 0xABC4, 0x30C5, 0xABC5, 0x30C6, 0xABC6,
+	0x30C7, 0xABC7, 0x30C8, 0xABC8, 0x30C9, 0xABC9, 0x30CA, 0xABCA,
+	0x30CB, 0xABCB, 0x30CC, 0xABCC, 0x30CD, 0xABCD, 0x30CE, 0xABCE,
+	0x30CF, 0xABCF, 0x30D0, 0xABD0, 0x30D1, 0xABD1, 0x30D2, 0xABD2,
+	0x30D3, 0xABD3, 0x30D4, 0xABD4, 0x30D5, 0xABD5, 0x30D6, 0xABD6,
+	0x30D7, 0xABD7, 0x30D8, 0xABD8, 0x30D9, 0xABD9, 0x30DA, 0xABDA,
+	0x30DB, 0xABDB, 0x30DC, 0xABDC, 0x30DD, 0xABDD, 0x30DE, 0xABDE,
+	0x30DF, 0xABDF, 0x30E0, 0xABE0, 0x30E1, 0xABE1, 0x30E2, 0xABE2,
+	0x30E3, 0xABE3, 0x30E4, 0xABE4, 0x30E5, 0xABE5, 0x30E6, 0xABE6,
+	0x30E7, 0xABE7, 0x30E8, 0xABE8, 0x30E9, 0xABE9, 0x30EA, 0xABEA,
+	0x30EB, 0xABEB, 0x30EC, 0xABEC, 0x30ED, 0xABED, 0x30EE, 0xABEE,
+	0x30EF, 0xABEF, 0x30F0, 0xABF0, 0x30F1, 0xABF1, 0x30F2, 0xABF2,
+	0x30F3, 0xABF3, 0x30F4, 0xABF4, 0x30F5, 0xABF5, 0x30F6, 0xABF6,
+	0x3131, 0xA4A1, 0x3132, 0xA4A2, 0x3133, 0xA4A3, 0x3134, 0xA4A4,
+	0x3135, 0xA4A5, 0x3136, 0xA4A6, 0x3137, 0xA4A7, 0x3138, 0xA4A8,
+	0x3139, 0xA4A9, 0x313A, 0xA4AA, 0x313B, 0xA4AB, 0x313C, 0xA4AC,
+	0x313D, 0xA4AD, 0x313E, 0xA4AE, 0x313F, 0xA4AF, 0x3140, 0xA4B0,
+	0x3141, 0xA4B1, 0x3142, 0xA4B2, 0x3143, 0xA4B3, 0x3144, 0xA4B4,
+	0x3145, 0xA4B5, 0x3146, 0xA4B6, 0x3147, 0xA4B7, 0x3148, 0xA4B8,
+	0x3149, 0xA4B9, 0x314A, 0xA4BA, 0x314B, 0xA4BB, 0x314C, 0xA4BC,
+	0x314D, 0xA4BD, 0x314E, 0xA4BE, 0x314F, 0xA4BF, 0x3150, 0xA4C0,
+	0x3151, 0xA4C1, 0x3152, 0xA4C2, 0x3153, 0xA4C3, 0x3154, 0xA4C4,
+	0x3155, 0xA4C5, 0x3156, 0xA4C6, 0x3157, 0xA4C7, 0x3158, 0xA4C8,
+	0x3159, 0xA4C9, 0x315A, 0xA4CA, 0x315B, 0xA4CB, 0x315C, 0xA4CC,
+	0x315D, 0xA4CD, 0x315E, 0xA4CE, 0x315F, 0xA4CF, 0x3160, 0xA4D0,
+	0x3161, 0xA4D1, 0x3162, 0xA4D2, 0x3163, 0xA4D3, 0x3164, 0xA4D4,
+	0x3165, 0xA4D5, 0x3166, 0xA4D6, 0x3167, 0xA4D7, 0x3168, 0xA4D8,
+	0x3169, 0xA4D9, 0x316A, 0xA4DA, 0x316B, 0xA4DB, 0x316C, 0xA4DC,
+	0x316D, 0xA4DD, 0x316E, 0xA4DE, 0x316F, 0xA4DF, 0x3170, 0xA4E0,
+	0x3171, 0xA4E1, 0x3172, 0xA4E2, 0x3173, 0xA4E3, 0x3174, 0xA4E4,
+	0x3175, 0xA4E5, 0x3176, 0xA4E6, 0x3177, 0xA4E7, 0x3178, 0xA4E8,
+	0x3179, 0xA4E9, 0x317A, 0xA4EA, 0x317B, 0xA4EB, 0x317C, 0xA4EC,
+	0x317D, 0xA4ED, 0x317E, 0xA4EE, 0x317F, 0xA4EF, 0x3180, 0xA4F0,
+	0x3181, 0xA4F1, 0x3182, 0xA4F2, 0x3183, 0xA4F3, 0x3184, 0xA4F4,
+	0x3185, 0xA4F5, 0x3186, 0xA4F6, 0x3187, 0xA4F7, 0x3188, 0xA4F8,
+	0x3189, 0xA4F9, 0x318A, 0xA4FA, 0x318B, 0xA4FB, 0x318C, 0xA4FC,
+	0x318D, 0xA4FD, 0x318E, 0xA4FE, 0x3200, 0xA9B1, 0x3201, 0xA9B2,
+	0x3202, 0xA9B3, 0x3203, 0xA9B4, 0x3204, 0xA9B5, 0x3205, 0xA9B6,
+	0x3206, 0xA9B7, 0x3207, 0xA9B8, 0x3208, 0xA9B9, 0x3209, 0xA9BA,
+	0x320A, 0xA9BB, 0x320B, 0xA9BC, 0x320C, 0xA9BD, 0x320D, 0xA9BE,
+	0x320E, 0xA9BF, 0x320F, 0xA9C0, 0x3210, 0xA9C1, 0x3211, 0xA9C2,
+	0x3212, 0xA9C3, 0x3213, 0xA9C4, 0x3214, 0xA9C5, 0x3215, 0xA9C6,
+	0x3216, 0xA9C7, 0x3217, 0xA9C8, 0x3218, 0xA9C9, 0x3219, 0xA9CA,
+	0x321A, 0xA9CB, 0x321B, 0xA9CC, 0x321C, 0xA2DF, 0x3260, 0xA8B1,
+	0x3261, 0xA8B2, 0x3262, 0xA8B3, 0x3263, 0xA8B4, 0x3264, 0xA8B5,
+	0x3265, 0xA8B6, 0x3266, 0xA8B7, 0x3267, 0xA8B8, 0x3268, 0xA8B9,
+	0x3269, 0xA8BA, 0x326A, 0xA8BB, 0x326B, 0xA8BC, 0x326C, 0xA8BD,
+	0x326D, 0xA8BE, 0x326E, 0xA8BF, 0x326F, 0xA8C0, 0x3270, 0xA8C1,
+	0x3271, 0xA8C2, 0x3272, 0xA8C3, 0x3273, 0xA8C4, 0x3274, 0xA8C5,
+	0x3275, 0xA8C6, 0x3276, 0xA8C7, 0x3277, 0xA8C8, 0x3278, 0xA8C9,
+	0x3279, 0xA8CA, 0x327A, 0xA8CB, 0x327B, 0xA8CC, 0x327F, 0xA2DE,
+	0x3380, 0xA7C9, 0x3381, 0xA7CA, 0x3382, 0xA7CB, 0x3383, 0xA7CC,
+	0x3384, 0xA7CD, 0x3388, 0xA7BA, 0x3389, 0xA7BB, 0x338A, 0xA7DC,
+	0x338B, 0xA7DD, 0x338C, 0xA7DE, 0x338D, 0xA7B6, 0x338E, 0xA7B7,
+	0x338F, 0xA7B8, 0x3390, 0xA7D4, 0x3391, 0xA7D5, 0x3392, 0xA7D6,
+	0x3393, 0xA7D7, 0x3394, 0xA7D8, 0x3395, 0xA7A1, 0x3396, 0xA7A2,
+	0x3397, 0xA7A3, 0x3398, 0xA7A5, 0x3399, 0xA7AB, 0x339A, 0xA7AC,
+	0x339B, 0xA7AD, 0x339C, 0xA7AE, 0x339D, 0xA7AF, 0x339E, 0xA7B0,
+	0x339F, 0xA7B1, 0x33A0, 0xA7B2, 0x33A1, 0xA7B3, 0x33A2, 0xA7B4,
+	0x33A3, 0xA7A7, 0x33A4, 0xA7A8, 0x33A5, 0xA7A9, 0x33A6, 0xA7AA,
+	0x33A7, 0xA7BD, 0x33A8, 0xA7BE, 0x33A9, 0xA7E5, 0x33AA, 0xA7E6,
+	0x33AB, 0xA7E7, 0x33AC, 0xA7E8, 0x33AD, 0xA7E1, 0x33AE, 0xA7E2,
+	0x33AF, 0xA7E3, 0x33B0, 0xA7BF, 0x33B1, 0xA7C0, 0x33B2, 0xA7C1,
+	0x33B3, 0xA7C2, 0x33B4, 0xA7C3, 0x33B5, 0xA7C4, 0x33B6, 0xA7C5,
+	0x33B7, 0xA7C6, 0x33B8, 0xA7C7, 0x33B9, 0xA7C8, 0x33BA, 0xA7CE,
+	0x33BB, 0xA7CF, 0x33BC, 0xA7D0, 0x33BD, 0xA7D1, 0x33BE, 0xA7D2,
+	0x33BF, 0xA7D3, 0x33C0, 0xA7DA, 0x33C1, 0xA7DB, 0x33C2, 0xA2E3,
+	0x33C3, 0xA7EC, 0x33C4, 0xA7A6, 0x33C5, 0xA7E0, 0x33C6, 0xA7EF,
+	0x33C7, 0xA2E1, 0x33C8, 0xA7BC, 0x33C9, 0xA7ED, 0x33CA, 0xA7B5,
+	0x33CF, 0xA7B9, 0x33D0, 0xA7EA, 0x33D3, 0xA7EB, 0x33D6, 0xA7DF,
+	0x33D8, 0xA2E4, 0x33DB, 0xA7E4, 0x33DC, 0xA7EE, 0x33DD, 0xA7E9,
+	0x4E00, 0xECE9, 0x4E01, 0xEFCB, 0x4E03, 0xF6D2, 0x4E07, 0xD8B2,
+	0x4E08, 0xEDDB, 0x4E09, 0xDFB2, 0x4E0A, 0xDFBE, 0x4E0B, 0xF9BB,
+	0x4E0D, 0xDCF4, 0x4E11, 0xF5E4, 0x4E14, 0xF3A6, 0x4E15, 0xDDE0,
+	0x4E16, 0xE1A6, 0x4E18, 0xCEF8, 0x4E19, 0xDCB0, 0x4E1E, 0xE3AA,
+	0x4E2D, 0xF1E9, 0x4E32, 0xCDFA, 0x4E38, 0xFCAF, 0x4E39, 0xD3A1,
+	0x4E3B, 0xF1AB, 0x4E42, 0xE7D1, 0x4E43, 0xD2AC, 0x4E45, 0xCEF9,
+	0x4E4B, 0xF1FD, 0x4E4D, 0xDEBF, 0x4E4E, 0xFBBA, 0x4E4F, 0xF9B9,
+	0x4E56, 0xCED2, 0x4E58, 0xE3AB, 0x4E59, 0xEBE0, 0x4E5D, 0xCEFA,
+	0x4E5E, 0xCBF7, 0x4E5F, 0xE5A5, 0x4E6B, 0xCAE1, 0x4E6D, 0xD4CC,
+	0x4E73, 0xEAE1, 0x4E76, 0xDCE3, 0x4E77, 0xDFAD, 0x4E7E, 0xCBEB,
+	0x4E82, 0xD5AF, 0x4E86, 0xD6F5, 0x4E88, 0xE5F8, 0x4E8B, 0xDEC0,
+	0x4E8C, 0xECA3, 0x4E8E, 0xE9CD, 0x4E90, 0xEAA7, 0x4E91, 0xE9F6,
+	0x4E92, 0xFBBB, 0x4E94, 0xE7E9, 0x4E95, 0xEFCC, 0x4E98, 0xD0E6,
+	0x4E9B, 0xDEC1, 0x4E9E, 0xE4AC, 0x4EA1, 0xD8CC, 0x4EA2, 0xF9F1,
+	0x4EA4, 0xCEDF, 0x4EA5, 0xFAA4, 0x4EA6, 0xE6B2, 0x4EA8, 0xFAFB,
+	0x4EAB, 0xFABD, 0x4EAC, 0xCCC8, 0x4EAD, 0xEFCD, 0x4EAE, 0xD5D5,
+	0x4EB6, 0xD3A2, 0x4EBA, 0xECD1, 0x4EC0, 0xE4A7, 0x4EC1, 0xECD2,
+	0x4EC4, 0xF6B1, 0x4EC7, 0xCEFB, 0x4ECA, 0xD0D1, 0x4ECB, 0xCBBF,
+	0x4ECD, 0xEDA4, 0x4ED4, 0xEDA8, 0x4ED5, 0xDEC2, 0x4ED6, 0xF6E2,
+	0x4ED7, 0xEDDC, 0x4ED8, 0xDCF5, 0x4ED9, 0xE0B9, 0x4EDD, 0xD4CE,
+	0x4EDF, 0xF4B5, 0x4EE3, 0xD3DB, 0x4EE4, 0xD6B5, 0x4EE5, 0xECA4,
+	0x4EF0, 0xE4E6, 0x4EF2, 0xF1EA, 0x4EF6, 0xCBEC, 0x4EF7, 0xCBC0,
+	0x4EFB, 0xECF2, 0x4F01, 0xD0EA, 0x4F09, 0xF9F2, 0x4F0A, 0xECA5,
+	0x4F0B, 0xD0DF, 0x4F0D, 0xE7EA, 0x4F0E, 0xD0EB, 0x4F0F, 0xDCD1,
+	0x4F10, 0xDBE9, 0x4F11, 0xFDCC, 0x4F2F, 0xDBD7, 0x4F34, 0xDAE1,
+	0x4F36, 0xD6B6, 0x4F38, 0xE3DF, 0x4F3A, 0xDEC3, 0x4F3C, 0xDEC4,
+	0x4F3D, 0xCAA1, 0x4F43, 0xEEEC, 0x4F46, 0xD3A3, 0x4F47, 0xEEB7,
+	0x4F48, 0xF8CF, 0x4F4D, 0xEAC8, 0x4F4E, 0xEEB8, 0x4F4F, 0xF1AC,
+	0x4F50, 0xF1A5, 0x4F51, 0xE9CE, 0x4F55, 0xF9BC, 0x4F59, 0xE5F9,
+	0x4F5A, 0xECEA, 0x4F5B, 0xDDD6, 0x4F5C, 0xEDC2, 0x4F69, 0xF8A5,
+	0x4F6F, 0xE5BA, 0x4F70, 0xDBD8, 0x4F73, 0xCAA2, 0x4F76, 0xD1CD,
+	0x4F7A, 0xEEED, 0x4F7E, 0xECEB, 0x4F7F, 0xDEC5, 0x4F81, 0xE3E0,
+	0x4F83, 0xCAC9, 0x4F84, 0xF2E9, 0x4F86, 0xD5CE, 0x4F88, 0xF6B6,
+	0x4F8A, 0xCEC2, 0x4F8B, 0xD6C7, 0x4F8D, 0xE3B4, 0x4F8F, 0xF1AD,
+	0x4F91, 0xEAE2, 0x4F96, 0xD7C2, 0x4F98, 0xF3A7, 0x4F9B, 0xCDEA,
+	0x4F9D, 0xEBEE, 0x4FAE, 0xD9B2, 0x4FAF, 0xFDA5, 0x4FB5, 0xF6D5,
+	0x4FB6, 0xD5E2, 0x4FBF, 0xF8B5, 0x4FC2, 0xCCF5, 0x4FC3, 0xF5B5,
+	0x4FC4, 0xE4AD, 0x4FC9, 0xE7EB, 0x4FCA, 0xF1D5, 0x4FCE, 0xF0BB,
+	0x4FD1, 0xE9B5, 0x4FD3, 0xCCC9, 0x4FD4, 0xFAD5, 0x4FD7, 0xE1D4,
+	0x4FDA, 0xD7D6, 0x4FDD, 0xDCC1, 0x4FDF, 0xDEC6, 0x4FE0, 0xFAEF,
+	0x4FE1, 0xE3E1, 0x4FEE, 0xE1F3, 0x4FEF, 0xDCF6, 0x4FF1, 0xCEFC,
+	0x4FF3, 0xDBC4, 0x4FF5, 0xF8F1, 0x4FF8, 0xDCE4, 0x4FFA, 0xE5EF,
+	0x5002, 0xDCB1, 0x5006, 0xD5D6, 0x5009, 0xF3DA, 0x500B, 0xCBC1,
+	0x500D, 0xDBC3, 0x5011, 0xD9FA, 0x5012, 0xD3EE, 0x5016, 0xFAB8,
+	0x5019, 0xFDA6, 0x501A, 0xEBEF, 0x501C, 0xF4A6, 0x501E, 0xCCCA,
+	0x501F, 0xF3A8, 0x5021, 0xF3DB, 0x5023, 0xDBA7, 0x5024, 0xF6B7,
+	0x5026, 0xCFE6, 0x5027, 0xF0F2, 0x5028, 0xCBDA, 0x502A, 0xE7D2,
+	0x502B, 0xD7C3, 0x502C, 0xF6F0, 0x502D, 0xE8DE, 0x503B, 0xE5A6,
+	0x5043, 0xE5E7, 0x5047, 0xCAA3, 0x5048, 0xCCA7, 0x5049, 0xEAC9,
+	0x504F, 0xF8B6, 0x5055, 0xFAA5, 0x505A, 0xF1AE, 0x505C, 0xEFCE,
+	0x5065, 0xCBED, 0x5074, 0xF6B0, 0x5075, 0xEFCF, 0x5076, 0xE9CF,
+	0x5078, 0xF7DE, 0x5080, 0xCED3, 0x5085, 0xDCF7, 0x508D, 0xDBA8,
+	0x5091, 0xCBF8, 0x5098, 0xDFA1, 0x5099, 0xDDE1, 0x50AC, 0xF5CA,
+	0x50AD, 0xE9B6, 0x50B2, 0xE7EC, 0x50B3, 0xEEEE, 0x50B5, 0xF3F0,
+	0x50B7, 0xDFBF, 0x50BE, 0xCCCB, 0x50C5, 0xD0C1, 0x50C9, 0xF4D2,
+	0x50CA, 0xE0BA, 0x50CF, 0xDFC0, 0x50D1, 0xCEE0, 0x50D5, 0xDCD2,
+	0x50D6, 0xFDEA, 0x50DA, 0xD6F6, 0x50DE, 0xEACA, 0x50E5, 0xE8E9,
+	0x50E7, 0xE3AC, 0x50ED, 0xF3D0, 0x50F9, 0xCAA4, 0x50FB, 0xDBF8,
+	0x50FF, 0xDEC7, 0x5100, 0xEBF0, 0x5101, 0xF1D6, 0x5104, 0xE5E2,
+	0x5106, 0xCCCC, 0x5109, 0xCBFB, 0x5112, 0xEAE3, 0x511F, 0xDFC1,
+	0x5121, 0xD6ED, 0x512A, 0xE9D0, 0x5132, 0xEEB9, 0x5137, 0xD5E3,
+	0x513A, 0xD1D3, 0x513C, 0xE5F0, 0x5140, 0xE8B4, 0x5141, 0xEBC3,
+	0x5143, 0xEAAA, 0x5144, 0xFAFC, 0x5145, 0xF5F6, 0x5146, 0xF0BC,
+	0x5147, 0xFDD4, 0x5148, 0xE0BB, 0x5149, 0xCEC3, 0x514B, 0xD0BA,
+	0x514C, 0xF7BA, 0x514D, 0xD8F3, 0x514E, 0xF7CD, 0x5152, 0xE4AE,
+	0x515C, 0xD4DF, 0x5162, 0xD0E7, 0x5165, 0xECFD, 0x5167, 0xD2AE,
+	0x5168, 0xEEEF, 0x5169, 0xD5D7, 0x516A, 0xEAE4, 0x516B, 0xF8A2,
+	0x516C, 0xCDEB, 0x516D, 0xD7BF, 0x516E, 0xFBB1, 0x5171, 0xCDEC,
+	0x5175, 0xDCB2, 0x5176, 0xD0EC, 0x5177, 0xCEFD, 0x5178, 0xEEF0,
+	0x517C, 0xCCC2, 0x5180, 0xD0ED, 0x5186, 0xE5F7, 0x518A, 0xF3FC,
+	0x518D, 0xEEA2, 0x5192, 0xD9B3, 0x5195, 0xD8F4, 0x5197, 0xE9B7,
+	0x51A0, 0xCEAE, 0x51A5, 0xD9A2, 0x51AA, 0xD8F1, 0x51AC, 0xD4CF,
+	0x51B6, 0xE5A7, 0x51B7, 0xD5D2, 0x51BD, 0xD6A9, 0x51C4, 0xF4A2,
+	0x51C6, 0xF1D7, 0x51C9, 0xD5D8, 0x51CB, 0xF0BD, 0x51CC, 0xD7D0,
+	0x51CD, 0xD4D0, 0x51DC, 0xD7CF, 0x51DD, 0xEBEA, 0x51DE, 0xFDEB,
+	0x51E1, 0xDBED, 0x51F0, 0xFCC5, 0x51F1, 0xCBC2, 0x51F6, 0xFDD5,
+	0x51F8, 0xF4C8, 0x51F9, 0xE8EA, 0x51FA, 0xF5F3, 0x51FD, 0xF9DE,
+	0x5200, 0xD3EF, 0x5203, 0xECD3, 0x5206, 0xDDC2, 0x5207, 0xEFB7,
+	0x5208, 0xE7D4, 0x520A, 0xCACA, 0x520E, 0xD9FB, 0x5211, 0xFAFD,
+	0x5217, 0xD6AA, 0x521D, 0xF4F8, 0x5224, 0xF7F7, 0x5225, 0xDCAC,
+	0x5229, 0xD7D7, 0x522A, 0xDFA2, 0x522E, 0xCEBE, 0x5230, 0xD3F0,
+	0x5236, 0xF0A4, 0x5237, 0xE1EC, 0x5238, 0xCFE7, 0x5239, 0xF3CB,
+	0x523A, 0xEDA9, 0x523B, 0xCABE, 0x5243, 0xF4EF, 0x5247, 0xF6CE,
+	0x524A, 0xDEFB, 0x524B, 0xD0BB, 0x524C, 0xD5B7, 0x524D, 0xEEF1,
+	0x5254, 0xF4A8, 0x5256, 0xDCF8, 0x525B, 0xCBA7, 0x525D, 0xDACE,
+	0x5261, 0xE0E6, 0x5269, 0xEDA5, 0x526A, 0xEEF2, 0x526F, 0xDCF9,
+	0x5272, 0xF9DC, 0x5275, 0xF3DC, 0x527D, 0xF8F2, 0x527F, 0xF4F9,
+	0x5283, 0xFCF1, 0x5287, 0xD0BC, 0x5288, 0xDBF9, 0x5289, 0xD7B1,
+	0x528D, 0xCBFC, 0x5291, 0xF0A5, 0x5292, 0xCBFD, 0x529B, 0xD5F4,
+	0x529F, 0xCDED, 0x52A0, 0xCAA5, 0x52A3, 0xD6AB, 0x52A4, 0xD0C2,
+	0x52A9, 0xF0BE, 0x52AA, 0xD2BD, 0x52AB, 0xCCA4, 0x52BE, 0xFAB6,
+	0x52C1, 0xCCCD, 0x52C3, 0xDAFA, 0x52C5, 0xF6CF, 0x52C7, 0xE9B8,
+	0x52C9, 0xD8F5, 0x52CD, 0xCCCE, 0x52D2, 0xD7CD, 0x52D5, 0xD4D1,
+	0x52D6, 0xE9ED, 0x52D8, 0xCAEB, 0x52D9, 0xD9E2, 0x52DB, 0xFDB2,
+	0x52DD, 0xE3AD, 0x52DE, 0xD6CC, 0x52DF, 0xD9B4, 0x52E2, 0xE1A7,
+	0x52E3, 0xEED3, 0x52E4, 0xD0C3, 0x52F3, 0xFDB3, 0x52F5, 0xD5E4,
+	0x52F8, 0xCFE8, 0x52FA, 0xEDC3, 0x52FB, 0xD0B2, 0x52FE, 0xCEFE,
+	0x52FF, 0xDAA8, 0x5305, 0xF8D0, 0x5308, 0xFDD6, 0x530D, 0xF8D1,
+	0x530F, 0xF8D2, 0x5310, 0xDCD3, 0x5315, 0xDDE2, 0x5316, 0xFBF9,
+	0x5317, 0xDDC1, 0x5319, 0xE3B5, 0x5320, 0xEDDD, 0x5321, 0xCEC4,
+	0x5323, 0xCBA1, 0x532A, 0xDDE3, 0x532F, 0xFCDD, 0x5339, 0xF9AF,
+	0x533F, 0xD2FB, 0x5340, 0xCFA1, 0x5341, 0xE4A8, 0x5343, 0xF4B6,
+	0x5344, 0xECFE, 0x5347, 0xE3AE, 0x5348, 0xE7ED, 0x5349, 0xFDC1,
+	0x534A, 0xDAE2, 0x534D, 0xD8B3, 0x5351, 0xDDE4, 0x5352, 0xF0EF,
+	0x5353, 0xF6F1, 0x5354, 0xFAF0, 0x5357, 0xD1F5, 0x535A, 0xDACF,
+	0x535C, 0xDCD4, 0x535E, 0xDCA6, 0x5360, 0xEFBF, 0x5366, 0xCECF,
+	0x5368, 0xE0D9, 0x536F, 0xD9D6, 0x5370, 0xECD4, 0x5371, 0xEACB,
+	0x5374, 0xCABF, 0x5375, 0xD5B0, 0x5377, 0xCFE9, 0x537D, 0xF1ED,
+	0x537F, 0xCCCF, 0x5384, 0xE4F8, 0x5393, 0xE4ED, 0x5398, 0xD7D8,
+	0x539A, 0xFDA7, 0x539F, 0xEAAB, 0x53A0, 0xF6B2, 0x53A5, 0xCFF0,
+	0x53A6, 0xF9BD, 0x53AD, 0xE6F4, 0x53BB, 0xCBDB, 0x53C3, 0xF3D1,
+	0x53C8, 0xE9D1, 0x53C9, 0xF3A9, 0x53CA, 0xD0E0, 0x53CB, 0xE9D2,
+	0x53CD, 0xDAE3, 0x53D4, 0xE2D2, 0x53D6, 0xF6A2, 0x53D7, 0xE1F4,
+	0x53DB, 0xDAE4, 0x53E1, 0xE7D5, 0x53E2, 0xF5BF, 0x53E3, 0xCFA2,
+	0x53E4, 0xCDAF, 0x53E5, 0xCFA3, 0x53E9, 0xCDB0, 0x53EA, 0xF1FE,
+	0x53EB, 0xD0A3, 0x53EC, 0xE1AF, 0x53ED, 0xF8A3, 0x53EF, 0xCAA6,
+	0x53F0, 0xF7BB, 0x53F1, 0xF2EA, 0x53F2, 0xDEC8, 0x53F3, 0xE9D3,
+	0x53F8, 0xDEC9, 0x5403, 0xFDDE, 0x5404, 0xCAC0, 0x5408, 0xF9EA,
+	0x5409, 0xD1CE, 0x540A, 0xEED4, 0x540C, 0xD4D2, 0x540D, 0xD9A3,
+	0x540E, 0xFDA8, 0x540F, 0xD7D9, 0x5410, 0xF7CE, 0x5411, 0xFABE,
+	0x541B, 0xCFD6, 0x541D, 0xD7F0, 0x541F, 0xEBE1, 0x5420, 0xF8C5,
+	0x5426, 0xDCFA, 0x5429, 0xDDC3, 0x542B, 0xF9DF, 0x5433, 0xE7EF,
+	0x5438, 0xFDE5, 0x5439, 0xF6A3, 0x543B, 0xD9FC, 0x543C, 0xFDA9,
+	0x543E, 0xE7EE, 0x5442, 0xD5E5, 0x5448, 0xEFD0, 0x544A, 0xCDB1,
+	0x5451, 0xF7A2, 0x5468, 0xF1B2, 0x546A, 0xF1B1, 0x5471, 0xCDB2,
+	0x5473, 0xDAAB, 0x5475, 0xCAA7, 0x547B, 0xE3E2, 0x547C, 0xFBBC,
+	0x547D, 0xD9A4, 0x5480, 0xEEBA, 0x5486, 0xF8D3, 0x548C, 0xFBFA,
+	0x548E, 0xCFA4, 0x5490, 0xDCFB, 0x54A4, 0xF6E3, 0x54A8, 0xEDAA,
+	0x54AB, 0xF2A1, 0x54AC, 0xCEE1, 0x54B3, 0xFAA6, 0x54B8, 0xF9E0,
+	0x54BD, 0xECD6, 0x54C0, 0xE4EE, 0x54C1, 0xF9A1, 0x54C4, 0xFBEF,
+	0x54C8, 0xF9EB, 0x54C9, 0xEEA3, 0x54E1, 0xEAAC, 0x54E5, 0xCAA8,
+	0x54E8, 0xF4FA, 0x54ED, 0xCDD6, 0x54EE, 0xFCF6, 0x54F2, 0xF4C9,
+	0x54FA, 0xF8D4, 0x5504, 0xF8A6, 0x5506, 0xDECA, 0x5507, 0xF2C6,
+	0x550E, 0xD7DA, 0x5510, 0xD3D0, 0x551C, 0xD8C5, 0x552F, 0xEAE6,
+	0x5531, 0xF3DD, 0x5535, 0xE4DA, 0x553E, 0xF6E4, 0x5544, 0xF6F2,
+	0x5546, 0xDFC2, 0x554F, 0xD9FD, 0x5553, 0xCCF6, 0x5556, 0xD3BA,
+	0x555E, 0xE4AF, 0x5563, 0xF9E1, 0x557C, 0xF0A6, 0x5580, 0xCBD3,
+	0x5584, 0xE0BC, 0x5586, 0xF4CA, 0x5587, 0xD4FA, 0x5589, 0xFDAA,
+	0x558A, 0xF9E2, 0x5598, 0xF4B7, 0x5599, 0xFDC2, 0x559A, 0xFCB0,
+	0x559C, 0xFDEC, 0x559D, 0xCAE2, 0x55A7, 0xFDBD, 0x55A9, 0xEAE7,
+	0x55AA, 0xDFC3, 0x55AB, 0xD1D2, 0x55AC, 0xCEE2, 0x55AE, 0xD3A4,
+	0x55C5, 0xFDAB, 0x55C7, 0xDFE0, 0x55D4, 0xF2C7, 0x55DA, 0xE7F0,
+	0x55DC, 0xD0EE, 0x55DF, 0xF3AA, 0x55E3, 0xDECB, 0x55E4, 0xF6B8,
+	0x55FD, 0xE1F5, 0x55FE, 0xF1B3, 0x5606, 0xF7A3, 0x5609, 0xCAA9,
+	0x5614, 0xCFA5, 0x5617, 0xDFC4, 0x562F, 0xE1B0, 0x5632, 0xF0BF,
+	0x5634, 0xF6A4, 0x5636, 0xE3B6, 0x5653, 0xFAC6, 0x5668, 0xD0EF,
+	0x566B, 0xFDED, 0x5674, 0xDDC4, 0x5686, 0xFCF7, 0x56A5, 0xE6BF,
+	0x56AC, 0xDEAD, 0x56AE, 0xFABF, 0x56B4, 0xE5F1, 0x56BC, 0xEDC4,
+	0x56CA, 0xD2A5, 0x56CD, 0xFDEE, 0x56D1, 0xF5B6, 0x56DA, 0xE1F6,
+	0x56DB, 0xDECC, 0x56DE, 0xFCDE, 0x56E0, 0xECD7, 0x56F0, 0xCDDD,
+	0x56F9, 0xD6B7, 0x56FA, 0xCDB3, 0x5703, 0xF8D5, 0x5704, 0xE5D8,
+	0x5708, 0xCFEA, 0x570B, 0xCFD0, 0x570D, 0xEACC, 0x5712, 0xEAAE,
+	0x5713, 0xEAAD, 0x5716, 0xD3F1, 0x5718, 0xD3A5, 0x571F, 0xF7CF,
+	0x5728, 0xEEA4, 0x572D, 0xD0A4, 0x5730, 0xF2A2, 0x573B, 0xD0F0,
+	0x5740, 0xF2A3, 0x5742, 0xF7F8, 0x5747, 0xD0B3, 0x574A, 0xDBA9,
+	0x574D, 0xD3BB, 0x574E, 0xCAEC, 0x5750, 0xF1A6, 0x5751, 0xCBD5,
+	0x5761, 0xF7E7, 0x5764, 0xCDDE, 0x5766, 0xF7A4, 0x576A, 0xF8C0,
+	0x576E, 0xD3DD, 0x5770, 0xCCD0, 0x5775, 0xCFA6, 0x577C, 0xF6F3,
+	0x5782, 0xE1F7, 0x5788, 0xD3DC, 0x578B, 0xFAFE, 0x5793, 0xFAA7,
+	0x57A0, 0xEBD9, 0x57A2, 0xCFA7, 0x57A3, 0xEAAF, 0x57C3, 0xE4EF,
+	0x57C7, 0xE9B9, 0x57C8, 0xF1D8, 0x57CB, 0xD8D8, 0x57CE, 0xE0F2,
+	0x57DF, 0xE6B4, 0x57E0, 0xDCFC, 0x57F0, 0xF3F1, 0x57F4, 0xE3D0,
+	0x57F7, 0xF2FB, 0x57F9, 0xDBC6, 0x57FA, 0xD0F1, 0x57FC, 0xD0F2,
+	0x5800, 0xCFDC, 0x5802, 0xD3D1, 0x5805, 0xCCB1, 0x5806, 0xF7D8,
+	0x5808, 0xCBA8, 0x5809, 0xEBBC, 0x580A, 0xE4BE, 0x581E, 0xF4DC,
+	0x5821, 0xDCC2, 0x5824, 0xF0A7, 0x5827, 0xE6C0, 0x582A, 0xCAED,
+	0x582F, 0xE8EB, 0x5830, 0xE5E8, 0x5831, 0xDCC3, 0x5834, 0xEDDE,
+	0x5835, 0xD3F2, 0x583A, 0xCCF7, 0x584A, 0xCED4, 0x584B, 0xE7AB,
+	0x584F, 0xCBC3, 0x5851, 0xE1B1, 0x5854, 0xF7B2, 0x5857, 0xD3F3,
+	0x5858, 0xD3D2, 0x585A, 0xF5C0, 0x585E, 0xDFDD, 0x5861, 0xEEF3,
+	0x5862, 0xE7F1, 0x5864, 0xFDB4, 0x5875, 0xF2C8, 0x5879, 0xF3D2,
+	0x587C, 0xEEF4, 0x587E, 0xE2D3, 0x5883, 0xCCD1, 0x5885, 0xDFEA,
+	0x5889, 0xE9BA, 0x5893, 0xD9D7, 0x589C, 0xF5CD, 0x589E, 0xF1F2,
+	0x589F, 0xFAC7, 0x58A8, 0xD9F8, 0x58A9, 0xD4C2, 0x58AE, 0xF6E5,
+	0x58B3, 0xDDC5, 0x58BA, 0xE7F2, 0x58BB, 0xEDDF, 0x58BE, 0xCACB,
+	0x58C1, 0xDBFA, 0x58C5, 0xE8B5, 0x58C7, 0xD3A6, 0x58CE, 0xFDB5,
+	0x58D1, 0xF9C9, 0x58D3, 0xE4E2, 0x58D5, 0xFBBD, 0x58D8, 0xD7A4,
+	0x58D9, 0xCEC5, 0x58DE, 0xCED5, 0x58DF, 0xD6E6, 0x58E4, 0xE5BD,
+	0x58EB, 0xDECD, 0x58EC, 0xECF3, 0x58EF, 0xEDE0, 0x58F9, 0xECEC,
+	0x58FA, 0xFBBE, 0x58FB, 0xDFEB, 0x58FD, 0xE1F8, 0x590F, 0xF9BE,
+	0x5914, 0xD0F3, 0x5915, 0xE0AA, 0x5916, 0xE8E2, 0x5919, 0xE2D4,
+	0x591A, 0xD2FD, 0x591C, 0xE5A8, 0x5922, 0xD9D3, 0x5927, 0xD3DE,
+	0x5929, 0xF4B8, 0x592A, 0xF7BC, 0x592B, 0xDCFD, 0x592D, 0xE8EC,
+	0x592E, 0xE4E7, 0x5931, 0xE3F7, 0x5937, 0xECA8, 0x593E, 0xFAF1,
+	0x5944, 0xE5F2, 0x5947, 0xD0F4, 0x5948, 0xD2AF, 0x5949, 0xDCE5,
+	0x594E, 0xD0A5, 0x594F, 0xF1B4, 0x5950, 0xFCB1, 0x5951, 0xCCF8,
+	0x5954, 0xDDC6, 0x5955, 0xFAD1, 0x5957, 0xF7DF, 0x595A, 0xFAA8,
+	0x5960, 0xEEF5, 0x5962, 0xDECE, 0x5967, 0xE7F3, 0x596A, 0xF7AC,
+	0x596B, 0xEBC4, 0x596C, 0xEDE1, 0x596D, 0xE0AB, 0x596E, 0xDDC7,
+	0x5973, 0xD2B3, 0x5974, 0xD2BF, 0x5978, 0xCACC, 0x597D, 0xFBBF,
+	0x5982, 0xE5FD, 0x5983, 0xDDE5, 0x5984, 0xD8CD, 0x598A, 0xECF4,
+	0x5993, 0xD0F5, 0x5996, 0xE8ED, 0x5997, 0xD0D2, 0x5999, 0xD9D8,
+	0x59A5, 0xF6E6, 0x59A8, 0xDBAA, 0x59AC, 0xF7E0, 0x59B9, 0xD8D9,
+	0x59BB, 0xF4A3, 0x59BE, 0xF4DD, 0x59C3, 0xEFD1, 0x59C6, 0xD9B5,
+	0x59C9, 0xEDAB, 0x59CB, 0xE3B7, 0x59D0, 0xEEBB, 0x59D1, 0xCDB4,
+	0x59D3, 0xE0F3, 0x59D4, 0xEACD, 0x59D9, 0xECF5, 0x59DA, 0xE8EE,
+	0x59DC, 0xCBA9, 0x59DD, 0xF1AF, 0x59E6, 0xCACD, 0x59E8, 0xECA9,
+	0x59EA, 0xF2EB, 0x59EC, 0xFDEF, 0x59EE, 0xF9F3, 0x59F8, 0xE6C1,
+	0x59FB, 0xECD8, 0x59FF, 0xEDAC, 0x5A01, 0xEACE, 0x5A03, 0xE8DF,
+	0x5A11, 0xDECF, 0x5A18, 0xD2A6, 0x5A1B, 0xE7F4, 0x5A1C, 0xD1D6,
+	0x5A1F, 0xE6C2, 0x5A20, 0xE3E3, 0x5A25, 0xE4B0, 0x5A29, 0xD8B4,
+	0x5A36, 0xF6A5, 0x5A3C, 0xF3DE, 0x5A41, 0xD7A5, 0x5A46, 0xF7E8,
+	0x5A49, 0xE8C6, 0x5A5A, 0xFBE6, 0x5A62, 0xDDE6, 0x5A66, 0xDCFE,
+	0x5A92, 0xD8DA, 0x5A9A, 0xDAAC, 0x5A9B, 0xEAB0, 0x5AA4, 0xE3B8,
+	0x5AC1, 0xCAAA, 0x5AC2, 0xE1F9, 0x5AC4, 0xEAB1, 0x5AC9, 0xF2EC,
+	0x5ACC, 0xFAEE, 0x5AE1, 0xEED5, 0x5AE6, 0xF9F4, 0x5AE9, 0xD2EC,
+	0x5B05, 0xFBFB, 0x5B09, 0xFDF0, 0x5B0B, 0xE0BD, 0x5B0C, 0xCEE3,
+	0x5B16, 0xF8C6, 0x5B2A, 0xDEAE, 0x5B40, 0xDFC5, 0x5B43, 0xE5BE,
+	0x5B50, 0xEDAD, 0x5B51, 0xFAEA, 0x5B54, 0xCDEE, 0x5B55, 0xEDA6,
+	0x5B57, 0xEDAE, 0x5B58, 0xF0ED, 0x5B5A, 0xDDA1, 0x5B5C, 0xEDAF,
+	0x5B5D, 0xFCF8, 0x5B5F, 0xD8EB, 0x5B63, 0xCCF9, 0x5B64, 0xCDB5,
+	0x5B69, 0xFAA9, 0x5B6B, 0xE1DD, 0x5B70, 0xE2D5, 0x5B71, 0xEDCF,
+	0x5B75, 0xDDA2, 0x5B78, 0xF9CA, 0x5B7A, 0xEAE8, 0x5B7C, 0xE5ED,
+	0x5B85, 0xD3EB, 0x5B87, 0xE9D4, 0x5B88, 0xE1FA, 0x5B89, 0xE4CC,
+	0x5B8B, 0xE1E4, 0x5B8C, 0xE8C7, 0x5B8F, 0xCEDB, 0x5B93, 0xDCD5,
+	0x5B95, 0xF7B5, 0x5B96, 0xFCF3, 0x5B97, 0xF0F3, 0x5B98, 0xCEAF,
+	0x5B99, 0xF1B5, 0x5B9A, 0xEFD2, 0x5B9B, 0xE8C8, 0x5B9C, 0xEBF1,
+	0x5BA2, 0xCBD4, 0x5BA3, 0xE0BE, 0x5BA4, 0xE3F8, 0x5BA5, 0xEAE9,
+	0x5BA6, 0xFCB2, 0x5BAC, 0xE0F4, 0x5BAE, 0xCFE0, 0x5BB0, 0xEEA5,
+	0x5BB3, 0xFAAA, 0x5BB4, 0xE6C3, 0x5BB5, 0xE1B2, 0x5BB6, 0xCAAB,
+	0x5BB8, 0xE3E4, 0x5BB9, 0xE9BB, 0x5BBF, 0xE2D6, 0x5BC0, 0xF3F2,
+	0x5BC2, 0xEED6, 0x5BC3, 0xEAB2, 0x5BC4, 0xD0F6, 0x5BC5, 0xECD9,
+	0x5BC6, 0xDACB, 0x5BC7, 0xCFA8, 0x5BCC, 0xDDA3, 0x5BD0, 0xD8DB,
+	0x5BD2, 0xF9CE, 0x5BD3, 0xE9D5, 0x5BD4, 0xE3D1, 0x5BD7, 0xD2BC,
+	0x5BDE, 0xD8AC, 0x5BDF, 0xF3CC, 0x5BE1, 0xCDFB, 0x5BE2, 0xF6D6,
+	0x5BE4, 0xE7F5, 0x5BE5, 0xE8EF, 0x5BE6, 0xE3F9, 0x5BE7, 0xD2BB,
+	0x5BE8, 0xF3F3, 0x5BE9, 0xE3FB, 0x5BEB, 0xDED0, 0x5BEC, 0xCEB0,
+	0x5BEE, 0xD6F7, 0x5BEF, 0xF1D9, 0x5BF5, 0xF5C1, 0x5BF6, 0xDCC4,
+	0x5BF8, 0xF5BB, 0x5BFA, 0xDED1, 0x5C01, 0xDCE6, 0x5C04, 0xDED2,
+	0x5C07, 0xEDE2, 0x5C08, 0xEEF6, 0x5C09, 0xEACF, 0x5C0A, 0xF0EE,
+	0x5C0B, 0xE3FC, 0x5C0D, 0xD3DF, 0x5C0E, 0xD3F4, 0x5C0F, 0xE1B3,
+	0x5C11, 0xE1B4, 0x5C16, 0xF4D3, 0x5C19, 0xDFC6, 0x5C24, 0xE9D6,
+	0x5C28, 0xDBAB, 0x5C31, 0xF6A6, 0x5C38, 0xE3B9, 0x5C39, 0xEBC5,
+	0x5C3A, 0xF4A9, 0x5C3B, 0xCDB6, 0x5C3C, 0xD2F9, 0x5C3E, 0xDAAD,
+	0x5C3F, 0xD2E3, 0x5C40, 0xCFD1, 0x5C45, 0xCBDC, 0x5C46, 0xCCFA,
+	0x5C48, 0xCFDD, 0x5C4B, 0xE8A9, 0x5C4D, 0xE3BB, 0x5C4E, 0xE3BA,
+	0x5C51, 0xE0DA, 0x5C55, 0xEEF7, 0x5C5B, 0xDCB3, 0x5C60, 0xD3F5,
+	0x5C62, 0xD7A6, 0x5C64, 0xF6B5, 0x5C65, 0xD7DB, 0x5C6C, 0xE1D5,
+	0x5C6F, 0xD4EA, 0x5C71, 0xDFA3, 0x5C79, 0xFDDF, 0x5C90, 0xD0F7,
+	0x5C91, 0xEDD4, 0x5CA1, 0xCBAA, 0x5CA9, 0xE4DB, 0x5CAB, 0xE1FB,
+	0x5CAC, 0xCBA2, 0x5CB1, 0xD3E0, 0x5CB3, 0xE4BF, 0x5CB5, 0xFBC0,
+	0x5CB7, 0xDABE, 0x5CB8, 0xE4CD, 0x5CBA, 0xD6B9, 0x5CBE, 0xEFC0,
+	0x5CC0, 0xE1FC, 0x5CD9, 0xF6B9, 0x5CE0, 0xDFC7, 0x5CE8, 0xE4B1,
+	0x5CEF, 0xDCE7, 0x5CF0, 0xDCE8, 0x5CF4, 0xFAD6, 0x5CF6, 0xD3F6,
+	0x5CFB, 0xF1DA, 0x5CFD, 0xFAF2, 0x5D07, 0xE2FD, 0x5D0D, 0xD5CF,
+	0x5D0E, 0xD0F8, 0x5D11, 0xCDDF, 0x5D14, 0xF5CB, 0x5D16, 0xE4F0,
+	0x5D17, 0xCBAB, 0x5D19, 0xD7C4, 0x5D27, 0xE2FE, 0x5D29, 0xDDDA,
+	0x5D4B, 0xDAAE, 0x5D4C, 0xCAEE, 0x5D50, 0xD5B9, 0x5D69, 0xE3A1,
+	0x5D6C, 0xE8E3, 0x5D6F, 0xF3AB, 0x5D87, 0xCFA9, 0x5D8B, 0xD3F7,
+	0x5D9D, 0xD4F1, 0x5DA0, 0xCEE4, 0x5DA2, 0xE8F2, 0x5DAA, 0xE5F5,
+	0x5DB8, 0xE7AE, 0x5DBA, 0xD6BA, 0x5DBC, 0xDFEC, 0x5DBD, 0xE4C0,
+	0x5DCD, 0xE8E4, 0x5DD2, 0xD8B5, 0x5DD6, 0xE4DC, 0x5DDD, 0xF4B9,
+	0x5DDE, 0xF1B6, 0x5DE1, 0xE2DE, 0x5DE2, 0xE1B5, 0x5DE5, 0xCDEF,
+	0x5DE6, 0xF1A7, 0x5DE7, 0xCEE5, 0x5DE8, 0xCBDD, 0x5DEB, 0xD9E3,
+	0x5DEE, 0xF3AC, 0x5DF1, 0xD0F9, 0x5DF2, 0xECAB, 0x5DF3, 0xDED3,
+	0x5DF4, 0xF7E9, 0x5DF7, 0xF9F5, 0x5DFD, 0xE1DE, 0x5DFE, 0xCBEE,
+	0x5E02, 0xE3BC, 0x5E03, 0xF8D6, 0x5E06, 0xDBEE, 0x5E0C, 0xFDF1,
+	0x5E11, 0xF7B6, 0x5E16, 0xF4DE, 0x5E19, 0xF2ED, 0x5E1B, 0xDBD9,
+	0x5E1D, 0xF0A8, 0x5E25, 0xE1FD, 0x5E2B, 0xDED4, 0x5E2D, 0xE0AC,
+	0x5E33, 0xEDE3, 0x5E36, 0xD3E1, 0x5E38, 0xDFC8, 0x5E3D, 0xD9B6,
+	0x5E3F, 0xFDAC, 0x5E40, 0xEFD3, 0x5E44, 0xE4C1, 0x5E45, 0xF8EB,
+	0x5E47, 0xDBAC, 0x5E4C, 0xFCC6, 0x5E55, 0xD8AD, 0x5E5F, 0xF6BA,
+	0x5E61, 0xDBDF, 0x5E62, 0xD3D3, 0x5E63, 0xF8C7, 0x5E72, 0xCACE,
+	0x5E73, 0xF8C1, 0x5E74, 0xD2B4, 0x5E77, 0xDCB4, 0x5E78, 0xFAB9,
+	0x5E79, 0xCACF, 0x5E7B, 0xFCB3, 0x5E7C, 0xEAEA, 0x5E7D, 0xEAEB,
+	0x5E7E, 0xD0FA, 0x5E84, 0xEDE4, 0x5E87, 0xDDE7, 0x5E8A, 0xDFC9,
+	0x5E8F, 0xDFED, 0x5E95, 0xEEBC, 0x5E97, 0xEFC1, 0x5E9A, 0xCCD2,
+	0x5E9C, 0xDDA4, 0x5EA0, 0xDFCA, 0x5EA6, 0xD3F8, 0x5EA7, 0xF1A8,
+	0x5EAB, 0xCDB7, 0x5EAD, 0xEFD4, 0x5EB5, 0xE4DD, 0x5EB6, 0xDFEE,
+	0x5EB7, 0xCBAC, 0x5EB8, 0xE9BC, 0x5EBE, 0xEAEC, 0x5EC2, 0xDFCB,
+	0x5EC8, 0xF9BF, 0x5EC9, 0xD6AF, 0x5ECA, 0xD5C6, 0x5ED0, 0xCFAA,
+	0x5ED3, 0xCEA9, 0x5ED6, 0xD6F8, 0x5EDA, 0xF1B7, 0x5EDB, 0xEEF8,
+	0x5EDF, 0xD9D9, 0x5EE0, 0xF3DF, 0x5EE2, 0xF8C8, 0x5EE3, 0xCEC6,
+	0x5EEC, 0xD5E6, 0x5EF3, 0xF4E6, 0x5EF6, 0xE6C5, 0x5EF7, 0xEFD5,
+	0x5EFA, 0xCBEF, 0x5EFB, 0xFCDF, 0x5F01, 0xDCA7, 0x5F04, 0xD6E7,
+	0x5F0A, 0xF8C9, 0x5F0F, 0xE3D2, 0x5F11, 0xE3BD, 0x5F13, 0xCFE1,
+	0x5F14, 0xF0C0, 0x5F15, 0xECDA, 0x5F17, 0xDDD7, 0x5F18, 0xFBF0,
+	0x5F1B, 0xECAC, 0x5F1F, 0xF0A9, 0x5F26, 0xFAD7, 0x5F27, 0xFBC1,
+	0x5F29, 0xD2C0, 0x5F31, 0xE5B0, 0x5F35, 0xEDE5, 0x5F3A, 0xCBAD,
+	0x5F3C, 0xF9B0, 0x5F48, 0xF7A5, 0x5F4A, 0xCBAE, 0x5F4C, 0xDAAF,
+	0x5F4E, 0xD8B6, 0x5F56, 0xD3A7, 0x5F57, 0xFBB2, 0x5F59, 0xFDC4,
+	0x5F5B, 0xECAD, 0x5F62, 0xFBA1, 0x5F66, 0xE5E9, 0x5F67, 0xE9EE,
+	0x5F69, 0xF3F4, 0x5F6A, 0xF8F3, 0x5F6B, 0xF0C1, 0x5F6C, 0xDEAF,
+	0x5F6D, 0xF8B0, 0x5F70, 0xF3E0, 0x5F71, 0xE7AF, 0x5F77, 0xDBAD,
+	0x5F79, 0xE6B5, 0x5F7C, 0xF9A8, 0x5F7F, 0xDDD8, 0x5F80, 0xE8D9,
+	0x5F81, 0xEFD6, 0x5F85, 0xD3E2, 0x5F87, 0xE2DF, 0x5F8A, 0xFCE0,
+	0x5F8B, 0xD7C8, 0x5F8C, 0xFDAD, 0x5F90, 0xDFEF, 0x5F91, 0xCCD3,
+	0x5F92, 0xD3F9, 0x5F97, 0xD4F0, 0x5F98, 0xDBC7, 0x5F99, 0xDED5,
+	0x5F9E, 0xF0F4, 0x5FA0, 0xD5D0, 0x5FA1, 0xE5D9, 0x5FA8, 0xFCC7,
+	0x5FA9, 0xDCD6, 0x5FAA, 0xE2E0, 0x5FAE, 0xDAB0, 0x5FB5, 0xF3A3,
+	0x5FB7, 0xD3EC, 0x5FB9, 0xF4CB, 0x5FBD, 0xFDC5, 0x5FC3, 0xE3FD,
+	0x5FC5, 0xF9B1, 0x5FCC, 0xD0FB, 0x5FCD, 0xECDB, 0x5FD6, 0xF5BC,
+	0x5FD7, 0xF2A4, 0x5FD8, 0xD8CE, 0x5FD9, 0xD8CF, 0x5FE0, 0xF5F7,
+	0x5FEB, 0xF6E1, 0x5FF5, 0xD2B7, 0x5FFD, 0xFBEC, 0x5FFF, 0xDDC8,
+	0x600F, 0xE4E8, 0x6012, 0xD2C1, 0x6016, 0xF8D7, 0x601C, 0xD6BB,
+	0x601D, 0xDED6, 0x6020, 0xF7BD, 0x6021, 0xECAE, 0x6025, 0xD0E1,
+	0x6027, 0xE0F5, 0x6028, 0xEAB3, 0x602A, 0xCED6, 0x602F, 0xCCA5,
+	0x6041, 0xECF6, 0x6042, 0xE2E1, 0x6043, 0xE3BE, 0x604D, 0xFCC8,
+	0x6050, 0xCDF0, 0x6052, 0xF9F6, 0x6055, 0xDFF0, 0x6059, 0xE5BF,
+	0x605D, 0xCEBF, 0x6062, 0xFCE1, 0x6063, 0xEDB0, 0x6064, 0xFDD1,
+	0x6065, 0xF6BB, 0x6068, 0xF9CF, 0x6069, 0xEBDA, 0x606A, 0xCAC1,
+	0x606C, 0xD2B8, 0x606D, 0xCDF1, 0x606F, 0xE3D3, 0x6070, 0xFDE6,
+	0x6085, 0xE6ED, 0x6089, 0xE3FA, 0x608C, 0xF0AA, 0x608D, 0xF9D0,
+	0x6094, 0xFCE2, 0x6096, 0xF8A7, 0x609A, 0xE1E5, 0x609B, 0xEEF9,
+	0x609F, 0xE7F6, 0x60A0, 0xEAED, 0x60A3, 0xFCB4, 0x60A4, 0xF5C2,
+	0x60A7, 0xD7DC, 0x60B0, 0xF0F5, 0x60B2, 0xDDE8, 0x60B3, 0xD3ED,
+	0x60B4, 0xF5FC, 0x60B6, 0xDABF, 0x60B8, 0xCCFB, 0x60BC, 0xD3FA,
+	0x60BD, 0xF4A4, 0x60C5, 0xEFD7, 0x60C7, 0xD4C3, 0x60D1, 0xFBE3,
+	0x60DA, 0xFBED, 0x60DC, 0xE0AD, 0x60DF, 0xEAEE, 0x60E0, 0xFBB3,
+	0x60E1, 0xE4C2, 0x60F0, 0xF6E7, 0x60F1, 0xD2DD, 0x60F3, 0xDFCC,
+	0x60F6, 0xFCC9, 0x60F9, 0xE5A9, 0x60FA, 0xE0F6, 0x60FB, 0xF6B3,
+	0x6101, 0xE1FE, 0x6106, 0xCBF0, 0x6108, 0xEAEF, 0x6109, 0xEAF0,
+	0x610D, 0xDAC0, 0x610E, 0xF8B4, 0x610F, 0xEBF2, 0x6115, 0xE4C3,
+	0x611A, 0xE9D7, 0x611B, 0xE4F1, 0x611F, 0xCAEF, 0x6127, 0xCED7,
+	0x6130, 0xFCCA, 0x6134, 0xF3E1, 0x6137, 0xCBC4, 0x613C, 0xE3E5,
+	0x613E, 0xCBC5, 0x613F, 0xEAB4, 0x6142, 0xE9BD, 0x6144, 0xD7C9,
+	0x6147, 0xEBDB, 0x6148, 0xEDB1, 0x614A, 0xCCC3, 0x614B, 0xF7BE,
+	0x614C, 0xFCCB, 0x6153, 0xF8F4, 0x6155, 0xD9B7, 0x6158, 0xF3D3,
+	0x6159, 0xF3D4, 0x615D, 0xF7E4, 0x615F, 0xF7D1, 0x6162, 0xD8B7,
+	0x6163, 0xCEB1, 0x6164, 0xCAC2, 0x6167, 0xFBB4, 0x6168, 0xCBC6,
+	0x616B, 0xF0F6, 0x616E, 0xD5E7, 0x6170, 0xEAD0, 0x6176, 0xCCD4,
+	0x6177, 0xCBAF, 0x617D, 0xF4AA, 0x617E, 0xE9AF, 0x6181, 0xF5C3,
+	0x6182, 0xE9D8, 0x618A, 0xDDE9, 0x618E, 0xF1F3, 0x6190, 0xD5FB,
+	0x6191, 0xDEBB, 0x6194, 0xF4FB, 0x6198, 0xFDF3, 0x6199, 0xFDF2,
+	0x619A, 0xF7A6, 0x61A4, 0xDDC9, 0x61A7, 0xD4D3, 0x61A9, 0xCCA8,
+	0x61AB, 0xDAC1, 0x61AC, 0xCCD5, 0x61AE, 0xD9E4, 0x61B2, 0xFACA,
+	0x61B6, 0xE5E3, 0x61BA, 0xD3BC, 0x61BE, 0xCAF0, 0x61C3, 0xD0C4,
+	0x61C7, 0xCAD0, 0x61C8, 0xFAAB, 0x61C9, 0xEBEB, 0x61CA, 0xE7F8,
+	0x61CB, 0xD9E5, 0x61E6, 0xD1D7, 0x61F2, 0xF3A4, 0x61F6, 0xD4FB,
+	0x61F7, 0xFCE3, 0x61F8, 0xFAD8, 0x61FA, 0xF3D5, 0x61FC, 0xCFAB,
+	0x61FF, 0xEBF3, 0x6200, 0xD5FC, 0x6207, 0xD3D4, 0x6208, 0xCDFC,
+	0x620A, 0xD9E6, 0x620C, 0xE2F9, 0x620D, 0xE2A1, 0x620E, 0xEBD4,
+	0x6210, 0xE0F7, 0x6211, 0xE4B2, 0x6212, 0xCCFC, 0x6216, 0xFBE4,
+	0x621A, 0xF4AB, 0x621F, 0xD0BD, 0x6221, 0xCAF1, 0x622A, 0xEFB8,
+	0x622E, 0xD7C0, 0x6230, 0xEEFA, 0x6231, 0xFDF4, 0x6234, 0xD3E3,
+	0x6236, 0xFBC2, 0x623E, 0xD5E8, 0x623F, 0xDBAE, 0x6240, 0xE1B6,
+	0x6241, 0xF8B7, 0x6247, 0xE0BF, 0x6248, 0xFBC3, 0x6249, 0xDDEA,
+	0x624B, 0xE2A2, 0x624D, 0xEEA6, 0x6253, 0xF6E8, 0x6258, 0xF6F5,
+	0x626E, 0xDDCA, 0x6271, 0xD0E2, 0x6276, 0xDDA6, 0x6279, 0xDDEB,
+	0x627C, 0xE4F9, 0x627F, 0xE3AF, 0x6280, 0xD0FC, 0x6284, 0xF4FC,
+	0x6289, 0xCCBC, 0x628A, 0xF7EA, 0x6291, 0xE5E4, 0x6292, 0xDFF1,
+	0x6295, 0xF7E1, 0x6297, 0xF9F7, 0x6298, 0xEFB9, 0x629B, 0xF8D8,
+	0x62AB, 0xF9A9, 0x62B1, 0xF8D9, 0x62B5, 0xEEBD, 0x62B9, 0xD8C6,
+	0x62BC, 0xE4E3, 0x62BD, 0xF5CE, 0x62C2, 0xDDD9, 0x62C7, 0xD9E7,
+	0x62C8, 0xD2B9, 0x62C9, 0xD5C3, 0x62CC, 0xDAE5, 0x62CD, 0xDAD0,
+	0x62CF, 0xD1D9, 0x62D0, 0xCED8, 0x62D2, 0xCBDE, 0x62D3, 0xF4AC,
+	0x62D4, 0xDAFB, 0x62D6, 0xF6E9, 0x62D7, 0xE8F3, 0x62D8, 0xCFAC,
+	0x62D9, 0xF0F0, 0x62DB, 0xF4FD, 0x62DC, 0xDBC8, 0x62EC, 0xCEC0,
+	0x62ED, 0xE3D4, 0x62EE, 0xD1CF, 0x62EF, 0xF1F5, 0x62F1, 0xCDF2,
+	0x62F3, 0xCFEB, 0x62F7, 0xCDB8, 0x62FE, 0xE3A6, 0x62FF, 0xD1DA,
+	0x6301, 0xF2A5, 0x6307, 0xF2A6, 0x6309, 0xE4CE, 0x6311, 0xD3FB,
+	0x632B, 0xF1A9, 0x632F, 0xF2C9, 0x633A, 0xEFD8, 0x633B, 0xE6C9,
+	0x633D, 0xD8B8, 0x633E, 0xFAF3, 0x6349, 0xF3B5, 0x634C, 0xF8A4,
+	0x634F, 0xD1F3, 0x6350, 0xE6C8, 0x6355, 0xF8DA, 0x6367, 0xDCE9,
+	0x6368, 0xDED7, 0x636E, 0xCBDF, 0x6372, 0xCFEC, 0x6377, 0xF4DF,
+	0x637A, 0xD1F4, 0x637B, 0xD2BA, 0x637F, 0xDFF2, 0x6383, 0xE1B7,
+	0x6388, 0xE2A3, 0x6389, 0xD3FC, 0x638C, 0xEDE6, 0x6392, 0xDBC9,
+	0x6396, 0xE4FA, 0x6398, 0xCFDE, 0x639B, 0xCED0, 0x63A0, 0xD5D3,
+	0x63A1, 0xF3F5, 0x63A2, 0xF7AE, 0x63A5, 0xEFC8, 0x63A7, 0xCDF3,
+	0x63A8, 0xF5CF, 0x63A9, 0xE5F3, 0x63AA, 0xF0C2, 0x63C0, 0xCAD1,
+	0x63C4, 0xEAF1, 0x63C6, 0xD0A6, 0x63CF, 0xD9DA, 0x63D0, 0xF0AB,
+	0x63D6, 0xEBE7, 0x63DA, 0xE5C0, 0x63DB, 0xFCB5, 0x63E1, 0xE4C4,
+	0x63ED, 0xCCA9, 0x63EE, 0xFDC6, 0x63F4, 0xEAB5, 0x63F6, 0xE5AA,
+	0x63F7, 0xDFBA, 0x640D, 0xE1DF, 0x640F, 0xDAD1, 0x6414, 0xE1B8,
+	0x6416, 0xE8F4, 0x6417, 0xD3FD, 0x641C, 0xE2A4, 0x6422, 0xF2CA,
+	0x642C, 0xDAE6, 0x642D, 0xF7B3, 0x643A, 0xFDCD, 0x643E, 0xF3B6,
+	0x6458, 0xEED7, 0x6460, 0xF5C4, 0x6469, 0xD8A4, 0x646F, 0xF2A7,
+	0x6478, 0xD9B8, 0x6479, 0xD9B9, 0x647A, 0xEFC9, 0x6488, 0xD6CE,
+	0x6491, 0xF7CB, 0x6492, 0xDFAE, 0x6493, 0xE8F5, 0x649A, 0xD2B5,
+	0x649E, 0xD3D5, 0x64A4, 0xF4CC, 0x64A5, 0xDAFC, 0x64AB, 0xD9E8,
+	0x64AD, 0xF7EB, 0x64AE, 0xF5C9, 0x64B0, 0xF3BC, 0x64B2, 0xDAD2,
+	0x64BB, 0xD3B5, 0x64C1, 0xE8B6, 0x64C4, 0xD6CF, 0x64C5, 0xF4BA,
+	0x64C7, 0xF7C9, 0x64CA, 0xCCAA, 0x64CD, 0xF0C3, 0x64CE, 0xCCD6,
+	0x64D2, 0xD0D3, 0x64D4, 0xD3BD, 0x64D8, 0xDBFB, 0x64DA, 0xCBE0,
+	0x64E1, 0xD3E4, 0x64E2, 0xF6F7, 0x64E5, 0xD5BA, 0x64E6, 0xF3CD,
+	0x64E7, 0xCBE1, 0x64EC, 0xEBF4, 0x64F2, 0xF4AD, 0x64F4, 0xFCAA,
+	0x64FA, 0xF7EC, 0x64FE, 0xE8F6, 0x6500, 0xDAE7, 0x6504, 0xF7CC,
+	0x6518, 0xE5C1, 0x651D, 0xE0EE, 0x6523, 0xD5FD, 0x652A, 0xCEE6,
+	0x652B, 0xFCAB, 0x652C, 0xD5BB, 0x652F, 0xF2A8, 0x6536, 0xE2A5,
+	0x6537, 0xCDB9, 0x6538, 0xEAF2, 0x6539, 0xCBC7, 0x653B, 0xCDF4,
+	0x653E, 0xDBAF, 0x653F, 0xEFD9, 0x6545, 0xCDBA, 0x6548, 0xFCF9,
+	0x654D, 0xDFF3, 0x654E, 0xCEE7, 0x654F, 0xDAC2, 0x6551, 0xCFAD,
+	0x6556, 0xE7F9, 0x6557, 0xF8A8, 0x655E, 0xF3E2, 0x6562, 0xCAF2,
+	0x6563, 0xDFA4, 0x6566, 0xD4C4, 0x656C, 0xCCD7, 0x656D, 0xE5C2,
+	0x6572, 0xCDBB, 0x6574, 0xEFDA, 0x6575, 0xEED8, 0x6577, 0xDDA7,
+	0x6578, 0xE2A6, 0x657E, 0xE0C0, 0x6582, 0xD6B0, 0x6583, 0xF8CA,
+	0x6585, 0xFCFA, 0x6587, 0xD9FE, 0x658C, 0xDEB0, 0x6590, 0xDDEC,
+	0x6591, 0xDAE8, 0x6597, 0xD4E0, 0x6599, 0xD6F9, 0x659B, 0xCDD7,
+	0x659C, 0xDED8, 0x659F, 0xF2F8, 0x65A1, 0xE4D6, 0x65A4, 0xD0C5,
+	0x65A5, 0xF4AE, 0x65A7, 0xDDA8, 0x65AB, 0xEDC5, 0x65AC, 0xF3D6,
+	0x65AF, 0xDED9, 0x65B0, 0xE3E6, 0x65B7, 0xD3A8, 0x65B9, 0xDBB0,
+	0x65BC, 0xE5DA, 0x65BD, 0xE3BF, 0x65C1, 0xDBB1, 0x65C5, 0xD5E9,
+	0x65CB, 0xE0C1, 0x65CC, 0xEFDB, 0x65CF, 0xF0E9, 0x65D2, 0xD7B2,
+	0x65D7, 0xD0FD, 0x65E0, 0xD9E9, 0x65E3, 0xD0FE, 0x65E5, 0xECED,
+	0x65E6, 0xD3A9, 0x65E8, 0xF2A9, 0x65E9, 0xF0C4, 0x65EC, 0xE2E2,
+	0x65ED, 0xE9EF, 0x65F1, 0xF9D1, 0x65F4, 0xE9D9, 0x65FA, 0xE8DA,
+	0x65FB, 0xDAC3, 0x65FC, 0xDAC4, 0x65FD, 0xD4C5, 0x65FF, 0xE7FA,
+	0x6606, 0xCDE0, 0x6607, 0xE3B0, 0x6609, 0xDBB2, 0x660A, 0xFBC4,
+	0x660C, 0xF3E3, 0x660E, 0xD9A5, 0x660F, 0xFBE7, 0x6610, 0xDDCB,
+	0x6611, 0xD0D4, 0x6613, 0xE6B6, 0x6614, 0xE0AE, 0x6615, 0xFDDA,
+	0x661E, 0xDCB5, 0x661F, 0xE0F8, 0x6620, 0xE7B1, 0x6625, 0xF5F0,
+	0x6627, 0xD8DC, 0x6628, 0xEDC6, 0x662D, 0xE1B9, 0x662F, 0xE3C0,
+	0x6630, 0xF9C0, 0x6631, 0xE9F0, 0x6634, 0xD9DB, 0x6636, 0xF3E4,
+	0x663A, 0xDCB6, 0x663B, 0xE4E9, 0x6641, 0xF0C5, 0x6642, 0xE3C1,
+	0x6643, 0xFCCC, 0x6644, 0xFCCD, 0x6649, 0xF2CB, 0x664B, 0xF2CC,
+	0x664F, 0xE4CF, 0x6659, 0xF1DB, 0x665B, 0xFAD9, 0x665D, 0xF1B8,
+	0x665E, 0xFDF5, 0x665F, 0xE0F9, 0x6664, 0xE7FB, 0x6665, 0xFCB7,
+	0x6666, 0xFCE4, 0x6667, 0xFBC5, 0x6668, 0xE3E7, 0x6669, 0xD8B9,
+	0x666B, 0xF6F8, 0x666E, 0xDCC5, 0x666F, 0xCCD8, 0x6673, 0xE0AF,
+	0x6674, 0xF4E7, 0x6676, 0xEFDC, 0x6677, 0xCFFC, 0x6678, 0xEFDD,
+	0x667A, 0xF2AA, 0x6684, 0xFDBE, 0x6687, 0xCAAC, 0x6688, 0xFDBB,
+	0x6689, 0xFDC7, 0x668E, 0xE7B2, 0x6690, 0xEAD1, 0x6691, 0xDFF4,
+	0x6696, 0xD1EC, 0x6697, 0xE4DE, 0x6698, 0xE5C3, 0x669D, 0xD9A6,
+	0x66A0, 0xCDBC, 0x66A2, 0xF3E5, 0x66AB, 0xEDD5, 0x66AE, 0xD9BA,
+	0x66B2, 0xEDE7, 0x66B3, 0xFBB5, 0x66B4, 0xF8EC, 0x66B9, 0xE0E7,
+	0x66BB, 0xCCD9, 0x66BE, 0xD4C6, 0x66C4, 0xE7A5, 0x66C6, 0xD5F5,
+	0x66C7, 0xD3BE, 0x66C9, 0xFCFB, 0x66D6, 0xE4F2, 0x66D9, 0xDFF5,
+	0x66DC, 0xE8F8, 0x66DD, 0xF8ED, 0x66E0, 0xCEC7, 0x66E6, 0xFDF6,
+	0x66F0, 0xE8D8, 0x66F2, 0xCDD8, 0x66F3, 0xE7D6, 0x66F4, 0xCCDA,
+	0x66F7, 0xCAE3, 0x66F8, 0xDFF6, 0x66F9, 0xF0C7, 0x66FA, 0xF0C6,
+	0x66FC, 0xD8BA, 0x66FE, 0xF1F4, 0x66FF, 0xF4F0, 0x6700, 0xF5CC,
+	0x6703, 0xFCE5, 0x6708, 0xEAC5, 0x6709, 0xEAF3, 0x670B, 0xDDDB,
+	0x670D, 0xDCD7, 0x6714, 0xDEFD, 0x6715, 0xF2F9, 0x6717, 0xD5C7,
+	0x671B, 0xD8D0, 0x671D, 0xF0C8, 0x671E, 0xD1A1, 0x671F, 0xD1A2,
+	0x6726, 0xD9D4, 0x6727, 0xD6E8, 0x6728, 0xD9CA, 0x672A, 0xDAB1,
+	0x672B, 0xD8C7, 0x672C, 0xDCE2, 0x672D, 0xF3CE, 0x672E, 0xF5F4,
+	0x6731, 0xF1B9, 0x6734, 0xDAD3, 0x6736, 0xF6EA, 0x673A, 0xCFF5,
+	0x673D, 0xFDAE, 0x6746, 0xCAD2, 0x6749, 0xDFB4, 0x674E, 0xD7DD,
+	0x674F, 0xFABA, 0x6750, 0xEEA7, 0x6751, 0xF5BD, 0x6753, 0xF8F5,
+	0x6756, 0xEDE8, 0x675C, 0xD4E1, 0x675E, 0xD1A3, 0x675F, 0xE1D6,
+	0x676D, 0xF9F8, 0x676F, 0xDBCA, 0x6770, 0xCBF9, 0x6771, 0xD4D4,
+	0x6773, 0xD9DC, 0x6775, 0xEEBE, 0x6777, 0xF7ED, 0x677B, 0xD2EE,
+	0x677E, 0xE1E6, 0x677F, 0xF7F9, 0x6787, 0xDDED, 0x6789, 0xE8DB,
+	0x678B, 0xDBB3, 0x678F, 0xD1F7, 0x6790, 0xE0B0, 0x6793, 0xD4E2,
+	0x6795, 0xF6D7, 0x6797, 0xD7F9, 0x679A, 0xD8DD, 0x679C, 0xCDFD,
+	0x679D, 0xF2AB, 0x67AF, 0xCDBD, 0x67B0, 0xF8C2, 0x67B3, 0xF2AC,
+	0x67B6, 0xCAAD, 0x67B7, 0xCAAE, 0x67B8, 0xCFAE, 0x67BE, 0xE3C2,
+	0x67C4, 0xDCB7, 0x67CF, 0xDBDA, 0x67D0, 0xD9BB, 0x67D1, 0xCAF3,
+	0x67D2, 0xF6D3, 0x67D3, 0xE6F8, 0x67D4, 0xEAF5, 0x67DA, 0xEAF6,
+	0x67DD, 0xF6F9, 0x67E9, 0xCFAF, 0x67EC, 0xCAD3, 0x67EF, 0xCAAF,
+	0x67F0, 0xD2B0, 0x67F1, 0xF1BA, 0x67F3, 0xD7B3, 0x67F4, 0xE3C3,
+	0x67F5, 0xF3FD, 0x67F6, 0xDEDA, 0x67FB, 0xDEDB, 0x67FE, 0xEFDE,
+	0x6812, 0xE2E3, 0x6813, 0xEEFB, 0x6816, 0xDFF7, 0x6817, 0xD7CA,
+	0x6821, 0xCEE8, 0x6822, 0xDBDB, 0x682A, 0xF1BB, 0x682F, 0xE9F1,
+	0x6838, 0xFAB7, 0x6839, 0xD0C6, 0x683C, 0xCCAB, 0x683D, 0xEEA8,
+	0x6840, 0xCBFA, 0x6841, 0xF9F9, 0x6842, 0xCCFD, 0x6843, 0xD3FE,
+	0x6848, 0xE4D0, 0x684E, 0xF2EE, 0x6850, 0xD4D5, 0x6851, 0xDFCD,
+	0x6853, 0xFCB8, 0x6854, 0xD1D0, 0x686D, 0xF2CD, 0x6876, 0xF7D2,
+	0x687F, 0xCAD4, 0x6881, 0xD5D9, 0x6885, 0xD8DE, 0x688F, 0xCDD9,
+	0x6893, 0xEEA9, 0x6894, 0xF6BC, 0x6897, 0xCCDB, 0x689D, 0xF0C9,
+	0x689F, 0xFCFC, 0x68A1, 0xE8C9, 0x68A2, 0xF4FE, 0x68A7, 0xE7FC,
+	0x68A8, 0xD7DE, 0x68AD, 0xDEDC, 0x68AF, 0xF0AC, 0x68B0, 0xCCFE,
+	0x68B1, 0xCDE1, 0x68B3, 0xE1BA, 0x68B5, 0xDBEF, 0x68B6, 0xDAB2,
+	0x68C4, 0xD1A5, 0x68C5, 0xDCB8, 0x68C9, 0xD8F6, 0x68CB, 0xD1A4,
+	0x68CD, 0xCDE2, 0x68D2, 0xDCEA, 0x68D5, 0xF0F7, 0x68D7, 0xF0CA,
+	0x68D8, 0xD0BE, 0x68DA, 0xDDDC, 0x68DF, 0xD4D6, 0x68E0, 0xD3D6,
+	0x68E7, 0xEDD0, 0x68E8, 0xCDA1, 0x68EE, 0xDFB5, 0x68F2, 0xDFF8,
+	0x68F9, 0xD4A1, 0x68FA, 0xCEB2, 0x6900, 0xE8CA, 0x6905, 0xEBF5,
+	0x690D, 0xE3D5, 0x690E, 0xF5D0, 0x6912, 0xF5A1, 0x6927, 0xD9A7,
+	0x6930, 0xE5AB, 0x693D, 0xE6CB, 0x693F, 0xF5F1, 0x694A, 0xE5C5,
+	0x6953, 0xF9A3, 0x6954, 0xE0DB, 0x6955, 0xF6EB, 0x6957, 0xCBF1,
+	0x6959, 0xD9EA, 0x695A, 0xF5A2, 0x695E, 0xD7D1, 0x6960, 0xD1F8,
+	0x6961, 0xEAF8, 0x6962, 0xEAF9, 0x6963, 0xDAB3, 0x6968, 0xEFDF,
+	0x696B, 0xF1EF, 0x696D, 0xE5F6, 0x696E, 0xEEBF, 0x696F, 0xE2E4,
+	0x6975, 0xD0BF, 0x6977, 0xFAAC, 0x6978, 0xF5D1, 0x6979, 0xE7B3,
+	0x6995, 0xE9BE, 0x699B, 0xF2CE, 0x699C, 0xDBB4, 0x69A5, 0xFCCE,
+	0x69A7, 0xDDEE, 0x69AE, 0xE7B4, 0x69B4, 0xD7B4, 0x69BB, 0xF7B4,
+	0x69C1, 0xCDBE, 0x69C3, 0xDAE9, 0x69CB, 0xCFB0, 0x69CC, 0xF7D9,
+	0x69CD, 0xF3E6, 0x69D0, 0xCED9, 0x69E8, 0xCEAA, 0x69EA, 0xCBC8,
+	0x69FB, 0xD0A7, 0x69FD, 0xF0CB, 0x69FF, 0xD0C7, 0x6A02, 0xE4C5,
+	0x6A0A, 0xDBE0, 0x6A11, 0xD5DA, 0x6A13, 0xD7A7, 0x6A17, 0xEEC0,
+	0x6A19, 0xF8F6, 0x6A1E, 0xF5D2, 0x6A1F, 0xEDE9, 0x6A21, 0xD9BC,
+	0x6A23, 0xE5C6, 0x6A35, 0xF5A3, 0x6A38, 0xDAD4, 0x6A39, 0xE2A7,
+	0x6A3A, 0xFBFC, 0x6A3D, 0xF1DC, 0x6A44, 0xCAF4, 0x6A48, 0xE8FA,
+	0x6A4B, 0xCEE9, 0x6A52, 0xE9F8, 0x6A53, 0xE2E5, 0x6A58, 0xD0B9,
+	0x6A59, 0xD4F2, 0x6A5F, 0xD1A6, 0x6A61, 0xDFCE, 0x6A6B, 0xFCF4,
+	0x6A80, 0xD3AA, 0x6A84, 0xCCAC, 0x6A89, 0xEFE0, 0x6A8D, 0xE5E5,
+	0x6A8E, 0xD0D5, 0x6A97, 0xDBFC, 0x6A9C, 0xFCE6, 0x6AA2, 0xCBFE,
+	0x6AA3, 0xEDEA, 0x6AB3, 0xDEB1, 0x6ABB, 0xF9E3, 0x6AC2, 0xD4A2,
+	0x6AC3, 0xCFF6, 0x6AD3, 0xD6D0, 0x6ADA, 0xD5EA, 0x6ADB, 0xF1EE,
+	0x6AF6, 0xFACB, 0x6AFB, 0xE5A1, 0x6B04, 0xD5B1, 0x6B0A, 0xCFED,
+	0x6B0C, 0xEDEB, 0x6B12, 0xD5B2, 0x6B16, 0xD5BC, 0x6B20, 0xFDE2,
+	0x6B21, 0xF3AD, 0x6B23, 0xFDDB, 0x6B32, 0xE9B0, 0x6B3A, 0xD1A7,
+	0x6B3D, 0xFDE3, 0x6B3E, 0xCEB3, 0x6B46, 0xFDE4, 0x6B47, 0xFACE,
+	0x6B4C, 0xCAB0, 0x6B4E, 0xF7A7, 0x6B50, 0xCFB1, 0x6B5F, 0xE6A2,
+	0x6B61, 0xFCB6, 0x6B62, 0xF2AD, 0x6B63, 0xEFE1, 0x6B64, 0xF3AE,
+	0x6B65, 0xDCC6, 0x6B66, 0xD9EB, 0x6B6A, 0xE8E0, 0x6B72, 0xE1A8,
+	0x6B77, 0xD5F6, 0x6B78, 0xCFFD, 0x6B7B, 0xDEDD, 0x6B7F, 0xD9D1,
+	0x6B83, 0xE4EA, 0x6B84, 0xF2CF, 0x6B86, 0xF7BF, 0x6B89, 0xE2E6,
+	0x6B8A, 0xE2A8, 0x6B96, 0xE3D6, 0x6B98, 0xEDD1, 0x6B9E, 0xE9F9,
+	0x6BAE, 0xD6B1, 0x6BAF, 0xDEB2, 0x6BB2, 0xE0E8, 0x6BB5, 0xD3AB,
+	0x6BB7, 0xEBDC, 0x6BBA, 0xDFAF, 0x6BBC, 0xCAC3, 0x6BBF, 0xEEFC,
+	0x6BC1, 0xFDC3, 0x6BC5, 0xEBF6, 0x6BC6, 0xCFB2, 0x6BCB, 0xD9EC,
+	0x6BCD, 0xD9BD, 0x6BCF, 0xD8DF, 0x6BD2, 0xD4B8, 0x6BD3, 0xEBBE,
+	0x6BD4, 0xDDEF, 0x6BD6, 0xDDF0, 0x6BD7, 0xDDF1, 0x6BD8, 0xDDF2,
+	0x6BDB, 0xD9BE, 0x6BEB, 0xFBC6, 0x6BEC, 0xCFB3, 0x6C08, 0xEEFD,
+	0x6C0F, 0xE4AB, 0x6C11, 0xDAC5, 0x6C13, 0xD8EC, 0x6C23, 0xD1A8,
+	0x6C34, 0xE2A9, 0x6C37, 0xDEBC, 0x6C38, 0xE7B5, 0x6C3E, 0xDBF0,
+	0x6C40, 0xEFE2, 0x6C41, 0xF1F0, 0x6C42, 0xCFB4, 0x6C4E, 0xDBF1,
+	0x6C50, 0xE0B1, 0x6C55, 0xDFA5, 0x6C57, 0xF9D2, 0x6C5A, 0xE7FD,
+	0x6C5D, 0xE6A3, 0x6C5E, 0xFBF1, 0x6C5F, 0xCBB0, 0x6C60, 0xF2AE,
+	0x6C68, 0xCDE7, 0x6C6A, 0xE8DC, 0x6C6D, 0xE7D7, 0x6C70, 0xF7C0,
+	0x6C72, 0xD0E3, 0x6C76, 0xDAA1, 0x6C7A, 0xCCBD, 0x6C7D, 0xD1A9,
+	0x6C7E, 0xDDCC, 0x6C81, 0xE3FE, 0x6C82, 0xD1AA, 0x6C83, 0xE8AA,
+	0x6C85, 0xEAB6, 0x6C86, 0xF9FA, 0x6C87, 0xE6CC, 0x6C88, 0xF6D8,
+	0x6C8C, 0xD4C7, 0x6C90, 0xD9CB, 0x6C92, 0xD9D2, 0x6C93, 0xD3CB,
+	0x6C94, 0xD8F7, 0x6C95, 0xDAA9, 0x6C96, 0xF5F8, 0x6C99, 0xDEDE,
+	0x6C9A, 0xF2AF, 0x6C9B, 0xF8A9, 0x6CAB, 0xD8C8, 0x6CAE, 0xEEC1,
+	0x6CB3, 0xF9C1, 0x6CB8, 0xDDF3, 0x6CB9, 0xEAFA, 0x6CBB, 0xF6BD,
+	0x6CBC, 0xE1BB, 0x6CBD, 0xCDBF, 0x6CBE, 0xF4D4, 0x6CBF, 0xE6CD,
+	0x6CC1, 0xFCCF, 0x6CC2, 0xFBA2, 0x6CC4, 0xE0DC, 0x6CC9, 0xF4BB,
+	0x6CCA, 0xDAD5, 0x6CCC, 0xF9B2, 0x6CD3, 0xFBF2, 0x6CD5, 0xDBF6,
+	0x6CD7, 0xDEDF, 0x6CDB, 0xDBF2, 0x6CE1, 0xF8DC, 0x6CE2, 0xF7EE,
+	0x6CE3, 0xEBE8, 0x6CE5, 0xD2FA, 0x6CE8, 0xF1BC, 0x6CEB, 0xFADA,
+	0x6CEE, 0xDAEA, 0x6CEF, 0xDAC6, 0x6CF0, 0xF7C1, 0x6CF3, 0xE7B6,
+	0x6D0B, 0xE5C7, 0x6D0C, 0xD6AC, 0x6D11, 0xDCC7, 0x6D17, 0xE1A9,
+	0x6D19, 0xE2AA, 0x6D1B, 0xD5A6, 0x6D1E, 0xD4D7, 0x6D25, 0xF2D0,
+	0x6D27, 0xEAFB, 0x6D29, 0xE0DD, 0x6D2A, 0xFBF3, 0x6D32, 0xF1BD,
+	0x6D35, 0xE2E7, 0x6D36, 0xFDD7, 0x6D38, 0xCEC8, 0x6D39, 0xEAB7,
+	0x6D3B, 0xFCC0, 0x6D3D, 0xFDE7, 0x6D3E, 0xF7EF, 0x6D41, 0xD7B5,
+	0x6D59, 0xEFBA, 0x6D5A, 0xF1DD, 0x6D5C, 0xDEB3, 0x6D63, 0xE8CB,
+	0x6D66, 0xF8DD, 0x6D69, 0xFBC7, 0x6D6A, 0xD5C8, 0x6D6C, 0xD7DF,
+	0x6D6E, 0xDDA9, 0x6D74, 0xE9B1, 0x6D77, 0xFAAD, 0x6D78, 0xF6D9,
+	0x6D79, 0xFAF4, 0x6D7F, 0xF8AA, 0x6D85, 0xE6EE, 0x6D87, 0xCCDC,
+	0x6D88, 0xE1BC, 0x6D89, 0xE0EF, 0x6D8C, 0xE9BF, 0x6D8D, 0xFCFD,
+	0x6D8E, 0xE6CE, 0x6D91, 0xE1D7, 0x6D93, 0xE6CF, 0x6D95, 0xF4F1,
+	0x6DAF, 0xE4F3, 0x6DB2, 0xE4FB, 0x6DB5, 0xF9E4, 0x6DC0, 0xEFE3,
+	0x6DC3, 0xCFEE, 0x6DC4, 0xF6BE, 0x6DC5, 0xE0B2, 0x6DC6, 0xFCFE,
+	0x6DC7, 0xD1AB, 0x6DCB, 0xD7FA, 0x6DCF, 0xFBC8, 0x6DD1, 0xE2D7,
+	0x6DD8, 0xD4A3, 0x6DD9, 0xF0F8, 0x6DDA, 0xD7A8, 0x6DDE, 0xE1E7,
+	0x6DE1, 0xD3BF, 0x6DE8, 0xEFE4, 0x6DEA, 0xD7C5, 0x6DEB, 0xEBE2,
+	0x6DEE, 0xFCE7, 0x6DF1, 0xE4A2, 0x6DF3, 0xE2E8, 0x6DF5, 0xE6D0,
+	0x6DF7, 0xFBE8, 0x6DF8, 0xF4E8, 0x6DF9, 0xE5F4, 0x6DFA, 0xF4BC,
+	0x6DFB, 0xF4D5, 0x6E17, 0xDFB6, 0x6E19, 0xFCB9, 0x6E1A, 0xEEC2,
+	0x6E1B, 0xCAF5, 0x6E1F, 0xEFE5, 0x6E20, 0xCBE2, 0x6E21, 0xD4A4,
+	0x6E23, 0xDEE0, 0x6E24, 0xDAFD, 0x6E25, 0xE4C6, 0x6E26, 0xE8BE,
+	0x6E2B, 0xE0DE, 0x6E2C, 0xF6B4, 0x6E2D, 0xEAD2, 0x6E2F, 0xF9FB,
+	0x6E32, 0xE0C2, 0x6E34, 0xCAE4, 0x6E36, 0xE7B7, 0x6E38, 0xEAFD,
+	0x6E3A, 0xD9DD, 0x6E3C, 0xDAB4, 0x6E3D, 0xEEAA, 0x6E3E, 0xFBE9,
+	0x6E43, 0xDBCB, 0x6E44, 0xDAB5, 0x6E4A, 0xF1BE, 0x6E4D, 0xD3AC,
+	0x6E56, 0xFBC9, 0x6E58, 0xDFCF, 0x6E5B, 0xD3C0, 0x6E5C, 0xE3D7,
+	0x6E5E, 0xEFE6, 0x6E5F, 0xFCD0, 0x6E67, 0xE9C0, 0x6E6B, 0xF5D3,
+	0x6E6E, 0xECDC, 0x6E6F, 0xF7B7, 0x6E72, 0xEAB8, 0x6E73, 0xD1F9,
+	0x6E7A, 0xDCC8, 0x6E90, 0xEAB9, 0x6E96, 0xF1DE, 0x6E9C, 0xD7B6,
+	0x6E9D, 0xCFB5, 0x6E9F, 0xD9A8, 0x6EA2, 0xECEE, 0x6EA5, 0xDDAA,
+	0x6EAA, 0xCDA2, 0x6EAB, 0xE8AE, 0x6EAF, 0xE1BD, 0x6EB1, 0xF2D1,
+	0x6EB6, 0xE9C1, 0x6EBA, 0xD2FC, 0x6EC2, 0xDBB5, 0x6EC4, 0xF3E7,
+	0x6EC5, 0xD8FE, 0x6EC9, 0xFCD1, 0x6ECB, 0xEDB2, 0x6ECC, 0xF4AF,
+	0x6ECE, 0xFBA3, 0x6ED1, 0xFCC1, 0x6ED3, 0xEEAB, 0x6ED4, 0xD4A5,
+	0x6EEF, 0xF4F2, 0x6EF4, 0xEED9, 0x6EF8, 0xFBCA, 0x6EFE, 0xCDE3,
+	0x6EFF, 0xD8BB, 0x6F01, 0xE5DB, 0x6F02, 0xF8F7, 0x6F06, 0xF6D4,
+	0x6F0F, 0xD7A9, 0x6F11, 0xCBC9, 0x6F14, 0xE6D1, 0x6F15, 0xF0CC,
+	0x6F20, 0xD8AE, 0x6F22, 0xF9D3, 0x6F23, 0xD5FE, 0x6F2B, 0xD8BC,
+	0x6F2C, 0xF2B0, 0x6F31, 0xE2AB, 0x6F32, 0xF3E8, 0x6F38, 0xEFC2,
+	0x6F3F, 0xEDEC, 0x6F41, 0xE7B8, 0x6F51, 0xDAFE, 0x6F54, 0xCCBE,
+	0x6F57, 0xF2FC, 0x6F58, 0xDAEB, 0x6F5A, 0xE2D8, 0x6F5B, 0xEDD6,
+	0x6F5E, 0xD6D1, 0x6F5F, 0xE0B3, 0x6F62, 0xFCD2, 0x6F64, 0xEBC8,
+	0x6F6D, 0xD3C1, 0x6F6E, 0xF0CD, 0x6F70, 0xCFF7, 0x6F7A, 0xEDD2,
+	0x6F7C, 0xD4D8, 0x6F7D, 0xDCC9, 0x6F7E, 0xD7F1, 0x6F81, 0xDFBB,
+	0x6F84, 0xF3A5, 0x6F88, 0xF4CD, 0x6F8D, 0xF1BF, 0x6F8E, 0xF8B1,
+	0x6F90, 0xE9FA, 0x6F94, 0xFBCB, 0x6F97, 0xCAD5, 0x6FA3, 0xF9D4,
+	0x6FA4, 0xF7CA, 0x6FA7, 0xD6C8, 0x6FAE, 0xFCE8, 0x6FAF, 0xF3BD,
+	0x6FB1, 0xEEFE, 0x6FB3, 0xE7FE, 0x6FB9, 0xD3C2, 0x6FBE, 0xD3B6,
+	0x6FC0, 0xCCAD, 0x6FC1, 0xF6FA, 0x6FC2, 0xD6B2, 0x6FC3, 0xD2D8,
+	0x6FCA, 0xE7D8, 0x6FD5, 0xE3A5, 0x6FDA, 0xE7B9, 0x6FDF, 0xF0AD,
+	0x6FE0, 0xFBCC, 0x6FE1, 0xEBA1, 0x6FE4, 0xD4A6, 0x6FE9, 0xFBCD,
+	0x6FEB, 0xD5BD, 0x6FEC, 0xF1DF, 0x6FEF, 0xF6FB, 0x6FF1, 0xDEB4,
+	0x6FFE, 0xD5EB, 0x7001, 0xE5C8, 0x7005, 0xFBA4, 0x7006, 0xD4B9,
+	0x7009, 0xDEE1, 0x700B, 0xE4A3, 0x700F, 0xD7B7, 0x7011, 0xF8EE,
+	0x7015, 0xDEB5, 0x7018, 0xD6D2, 0x701A, 0xF9D5, 0x701B, 0xE7BA,
+	0x701C, 0xEBD5, 0x701D, 0xD5F7, 0x701E, 0xEFE7, 0x701F, 0xE1BE,
+	0x7023, 0xFAAE, 0x7027, 0xD6E9, 0x7028, 0xD6EE, 0x702F, 0xE7BB,
+	0x7037, 0xECCB, 0x703E, 0xD5B3, 0x704C, 0xCEB4, 0x7050, 0xFBA5,
+	0x7051, 0xE1EE, 0x7058, 0xF7A8, 0x705D, 0xFBCE, 0x7063, 0xD8BD,
+	0x706B, 0xFBFD, 0x7070, 0xFCE9, 0x7078, 0xCFB6, 0x707C, 0xEDC7,
+	0x707D, 0xEEAC, 0x7085, 0xCCDD, 0x708A, 0xF6A7, 0x708E, 0xE6FA,
+	0x7092, 0xF5A4, 0x7098, 0xFDDC, 0x7099, 0xEDB3, 0x709A, 0xCEC9,
+	0x70A1, 0xEFE8, 0x70A4, 0xE1BF, 0x70AB, 0xFADB, 0x70AC, 0xCBE3,
+	0x70AD, 0xF7A9, 0x70AF, 0xFBA6, 0x70B3, 0xDCB9, 0x70B7, 0xF1C0,
+	0x70B8, 0xEDC8, 0x70B9, 0xEFC3, 0x70C8, 0xD6AD, 0x70CB, 0xFDCE,
+	0x70CF, 0xE8A1, 0x70D8, 0xFBF4, 0x70D9, 0xD5A7, 0x70DD, 0xF1F6,
+	0x70DF, 0xE6D3, 0x70F1, 0xCCDE, 0x70F9, 0xF8B2, 0x70FD, 0xDCEB,
+	0x7104, 0xFDB6, 0x7109, 0xE5EA, 0x710C, 0xF1E0, 0x7119, 0xDBCC,
+	0x711A, 0xDDCD, 0x711E, 0xD4C8, 0x7121, 0xD9ED, 0x7126, 0xF5A5,
+	0x7130, 0xE6FB, 0x7136, 0xE6D4, 0x7147, 0xFDC8, 0x7149, 0xD6A1,
+	0x714A, 0xFDBF, 0x714C, 0xFCD3, 0x714E, 0xEFA1, 0x7150, 0xE7BC,
+	0x7156, 0xD1EE, 0x7159, 0xE6D5, 0x715C, 0xE9F2, 0x715E, 0xDFB0,
+	0x7164, 0xD8E0, 0x7165, 0xFCBA, 0x7166, 0xFDAF, 0x7167, 0xF0CE,
+	0x7169, 0xDBE1, 0x716C, 0xE5C9, 0x716E, 0xEDB4, 0x717D, 0xE0C3,
+	0x7184, 0xE3D8, 0x7189, 0xE9FB, 0x718A, 0xEAA8, 0x718F, 0xFDB7,
+	0x7192, 0xFBA7, 0x7194, 0xE9C2, 0x7199, 0xFDF7, 0x719F, 0xE2D9,
+	0x71A2, 0xDCEC, 0x71AC, 0xE8A2, 0x71B1, 0xE6F0, 0x71B9, 0xFDF8,
+	0x71BA, 0xFDF9, 0x71BE, 0xF6BF, 0x71C1, 0xE7A7, 0x71C3, 0xE6D7,
+	0x71C8, 0xD4F3, 0x71C9, 0xD4C9, 0x71CE, 0xD6FA, 0x71D0, 0xD7F2,
+	0x71D2, 0xE1C0, 0x71D4, 0xDBE2, 0x71D5, 0xE6D8, 0x71DF, 0xE7BD,
+	0x71E5, 0xF0CF, 0x71E6, 0xF3BE, 0x71E7, 0xE2AC, 0x71ED, 0xF5B7,
+	0x71EE, 0xE0F0, 0x71FB, 0xFDB8, 0x71FC, 0xE3E8, 0x71FE, 0xD4A7,
+	0x71FF, 0xE8FC, 0x7200, 0xFAD2, 0x7206, 0xF8EF, 0x7210, 0xD6D3,
+	0x721B, 0xD5B4, 0x722A, 0xF0D0, 0x722C, 0xF7F0, 0x722D, 0xEEB3,
+	0x7230, 0xEABA, 0x7232, 0xEAD3, 0x7235, 0xEDC9, 0x7236, 0xDDAB,
+	0x723A, 0xE5AC, 0x723B, 0xFDA1, 0x723D, 0xDFD0, 0x723E, 0xECB3,
+	0x7240, 0xDFD1, 0x7246, 0xEDED, 0x7247, 0xF8B8, 0x7248, 0xF7FA,
+	0x724C, 0xF8AB, 0x7252, 0xF4E0, 0x7258, 0xD4BA, 0x7259, 0xE4B3,
+	0x725B, 0xE9DA, 0x725D, 0xDEB6, 0x725F, 0xD9BF, 0x7261, 0xD9C0,
+	0x7262, 0xD6EF, 0x7267, 0xD9CC, 0x7269, 0xDAAA, 0x7272, 0xDFE5,
+	0x7279, 0xF7E5, 0x727D, 0xCCB2, 0x7280, 0xDFF9, 0x7281, 0xD7E0,
+	0x72A2, 0xD4BB, 0x72A7, 0xFDFA, 0x72AC, 0xCCB3, 0x72AF, 0xDBF3,
+	0x72C0, 0xDFD2, 0x72C2, 0xCECA, 0x72C4, 0xEEDA, 0x72CE, 0xE4E4,
+	0x72D0, 0xFBCF, 0x72D7, 0xCFB7, 0x72D9, 0xEEC3, 0x72E1, 0xCEEA,
+	0x72E9, 0xE2AD, 0x72F8, 0xD7E1, 0x72F9, 0xFAF5, 0x72FC, 0xD5C9,
+	0x72FD, 0xF8AC, 0x730A, 0xE7D9, 0x7316, 0xF3E9, 0x731B, 0xD8ED,
+	0x731C, 0xE3C4, 0x731D, 0xF0F1, 0x7325, 0xE8E5, 0x7329, 0xE0FA,
+	0x732A, 0xEEC4, 0x732B, 0xD9DE, 0x7336, 0xEBA2, 0x7337, 0xEBA3,
+	0x733E, 0xFCC2, 0x733F, 0xEABB, 0x7344, 0xE8AB, 0x7345, 0xDEE2,
+	0x7350, 0xEDEF, 0x7352, 0xE8A3, 0x7357, 0xCFF1, 0x7368, 0xD4BC,
+	0x736A, 0xFCEA, 0x7370, 0xE7BE, 0x7372, 0xFCF2, 0x7375, 0xD6B4,
+	0x7378, 0xE2AE, 0x737A, 0xD3B7, 0x737B, 0xFACC, 0x7384, 0xFADC,
+	0x7386, 0xEDB5, 0x7387, 0xE1E3, 0x7389, 0xE8AC, 0x738B, 0xE8DD,
+	0x738E, 0xEFE9, 0x7394, 0xF4BD, 0x7396, 0xCFB8, 0x7397, 0xE9DB,
+	0x7398, 0xD1AC, 0x739F, 0xDAC7, 0x73A7, 0xEBC9, 0x73A9, 0xE8CC,
+	0x73AD, 0xDEB7, 0x73B2, 0xD6BC, 0x73B3, 0xD3E5, 0x73B9, 0xFADD,
+	0x73C0, 0xDAD6, 0x73C2, 0xCAB1, 0x73C9, 0xDAC8, 0x73CA, 0xDFA6,
+	0x73CC, 0xF9B3, 0x73CD, 0xF2D2, 0x73CF, 0xCAC4, 0x73D6, 0xCECB,
+	0x73D9, 0xCDF5, 0x73DD, 0xFDB0, 0x73DE, 0xD5A8, 0x73E0, 0xF1C1,
+	0x73E3, 0xE2E9, 0x73E4, 0xDCCA, 0x73E5, 0xECB4, 0x73E6, 0xFAC0,
+	0x73E9, 0xFBA8, 0x73EA, 0xD0A8, 0x73ED, 0xDAEC, 0x73F7, 0xD9EE,
+	0x73F9, 0xE0FB, 0x73FD, 0xEFEA, 0x73FE, 0xFADE, 0x7401, 0xE0C4,
+	0x7403, 0xCFB9, 0x7405, 0xD5CA, 0x7406, 0xD7E2, 0x7407, 0xE2AF,
+	0x7409, 0xD7B8, 0x7413, 0xE8CD, 0x741B, 0xF6DA, 0x7420, 0xEFA2,
+	0x7421, 0xE2DA, 0x7422, 0xF6FC, 0x7425, 0xFBD0, 0x7426, 0xD1AD,
+	0x7428, 0xCDE4, 0x742A, 0xD1AE, 0x742B, 0xDCED, 0x742C, 0xE8CE,
+	0x742E, 0xF0F9, 0x742F, 0xCEB5, 0x7430, 0xE6FC, 0x7433, 0xD7FB,
+	0x7434, 0xD0D6, 0x7435, 0xDDF5, 0x7436, 0xF7F1, 0x7438, 0xF6FD,
+	0x743A, 0xDBF7, 0x743F, 0xFBEA, 0x7440, 0xE9DC, 0x7441, 0xD9C1,
+	0x7443, 0xF5F2, 0x7444, 0xE0C5, 0x744B, 0xEAD4, 0x7455, 0xF9C2,
+	0x7457, 0xEABC, 0x7459, 0xD2C5, 0x745A, 0xFBD1, 0x745B, 0xE7C0,
+	0x745C, 0xEBA5, 0x745E, 0xDFFA, 0x745F, 0xE3A2, 0x7460, 0xD7B9,
+	0x7462, 0xE9C3, 0x7464, 0xE8FD, 0x7465, 0xE8AF, 0x7468, 0xF2D3,
+	0x7469, 0xFBA9, 0x746A, 0xD8A5, 0x746F, 0xD5CB, 0x747E, 0xD0C8,
+	0x7482, 0xD1AF, 0x7483, 0xD7E3, 0x7487, 0xE0C6, 0x7489, 0xD6A2,
+	0x748B, 0xEDF0, 0x7498, 0xD7F3, 0x749C, 0xFCD4, 0x749E, 0xDAD7,
+	0x749F, 0xCCDF, 0x74A1, 0xF2D4, 0x74A3, 0xD1B0, 0x74A5, 0xCCE0,
+	0x74A7, 0xDBFD, 0x74A8, 0xF3BF, 0x74AA, 0xF0D1, 0x74B0, 0xFCBB,
+	0x74B2, 0xE2B0, 0x74B5, 0xE6A5, 0x74B9, 0xE2DB, 0x74BD, 0xDFDE,
+	0x74BF, 0xE0C7, 0x74C6, 0xF2EF, 0x74CA, 0xCCE1, 0x74CF, 0xD6EA,
+	0x74D4, 0xE7C2, 0x74D8, 0xCEB6, 0x74DA, 0xF3C0, 0x74DC, 0xCDFE,
+	0x74E0, 0xFBD2, 0x74E2, 0xF8F8, 0x74E3, 0xF7FB, 0x74E6, 0xE8BF,
+	0x74EE, 0xE8B7, 0x74F7, 0xEDB6, 0x7501, 0xDCBA, 0x7504, 0xCCB4,
+	0x7511, 0xF1F7, 0x7515, 0xE8B8, 0x7518, 0xCAF6, 0x751A, 0xE4A4,
+	0x751B, 0xF4D6, 0x751F, 0xDFE6, 0x7523, 0xDFA7, 0x7525, 0xDFE7,
+	0x7526, 0xE1C1, 0x7528, 0xE9C4, 0x752B, 0xDCCB, 0x752C, 0xE9C5,
+	0x7530, 0xEFA3, 0x7531, 0xEBA6, 0x7532, 0xCBA3, 0x7533, 0xE3E9,
+	0x7537, 0xD1FB, 0x7538, 0xEFA4, 0x753A, 0xEFEB, 0x7547, 0xD0B4,
+	0x754C, 0xCDA3, 0x754F, 0xE8E6, 0x7551, 0xEFA5, 0x7553, 0xD3CC,
+	0x7554, 0xDAED, 0x7559, 0xD7BA, 0x755B, 0xF2D5, 0x755C, 0xF5E5,
+	0x755D, 0xD9EF, 0x7562, 0xF9B4, 0x7565, 0xD5D4, 0x7566, 0xFDCF,
+	0x756A, 0xDBE3, 0x756F, 0xF1E1, 0x7570, 0xECB6, 0x7575, 0xFBFE,
+	0x7576, 0xD3D7, 0x7578, 0xD1B1, 0x757A, 0xCBB1, 0x757F, 0xD1B2,
+	0x7586, 0xCBB2, 0x7587, 0xF1C2, 0x758A, 0xF4E1, 0x758B, 0xF9B5,
+	0x758E, 0xE1C3, 0x758F, 0xE1C2, 0x7591, 0xEBF7, 0x759D, 0xDFA8,
+	0x75A5, 0xCBCA, 0x75AB, 0xE6B9, 0x75B1, 0xF8DE, 0x75B2, 0xF9AA,
+	0x75B3, 0xCAF7, 0x75B5, 0xEDB7, 0x75B8, 0xD3B8, 0x75B9, 0xF2D6,
+	0x75BC, 0xD4D9, 0x75BD, 0xEEC5, 0x75BE, 0xF2F0, 0x75C2, 0xCAB2,
+	0x75C5, 0xDCBB, 0x75C7, 0xF1F8, 0x75CD, 0xECB7, 0x75D2, 0xE5CA,
+	0x75D4, 0xF6C0, 0x75D5, 0xFDDD, 0x75D8, 0xD4E3, 0x75D9, 0xCCE2,
+	0x75DB, 0xF7D4, 0x75E2, 0xD7E5, 0x75F0, 0xD3C3, 0x75F2, 0xD8A6,
+	0x75F4, 0xF6C1, 0x75FA, 0xDDF6, 0x75FC, 0xCDC0, 0x7600, 0xE5DC,
+	0x760D, 0xE5CB, 0x7619, 0xE1C4, 0x761F, 0xE8B0, 0x7620, 0xF4B0,
+	0x7621, 0xF3EA, 0x7622, 0xDAEE, 0x7624, 0xD7BB, 0x7626, 0xE2B1,
+	0x763B, 0xD7AA, 0x7642, 0xD6FB, 0x764C, 0xE4DF, 0x764E, 0xCAD6,
+	0x7652, 0xEBA8, 0x7656, 0xDBFE, 0x7661, 0xF6C2, 0x7664, 0xEFBB,
+	0x7669, 0xD4FD, 0x766C, 0xE0C8, 0x7670, 0xE8B9, 0x7672, 0xEFA6,
+	0x7678, 0xCDA4, 0x767B, 0xD4F4, 0x767C, 0xDBA1, 0x767D, 0xDBDC,
+	0x767E, 0xDBDD, 0x7684, 0xEEDC, 0x7686, 0xCBCB, 0x7687, 0xFCD5,
+	0x768E, 0xCEEB, 0x7690, 0xCDC1, 0x7693, 0xFBD3, 0x76AE, 0xF9AB,
+	0x76BA, 0xF5D4, 0x76BF, 0xD9A9, 0x76C2, 0xE9DD, 0x76C3, 0xDBCD,
+	0x76C6, 0xDDCE, 0x76C8, 0xE7C3, 0x76CA, 0xECCC, 0x76D2, 0xF9EC,
+	0x76D6, 0xCBCC, 0x76DB, 0xE0FC, 0x76DC, 0xD4A8, 0x76DE, 0xEDD3,
+	0x76DF, 0xD8EF, 0x76E1, 0xF2D7, 0x76E3, 0xCAF8, 0x76E4, 0xDAEF,
+	0x76E7, 0xD6D4, 0x76EE, 0xD9CD, 0x76F2, 0xD8EE, 0x76F4, 0xF2C1,
+	0x76F8, 0xDFD3, 0x76FC, 0xDAF0, 0x76FE, 0xE2EA, 0x7701, 0xE0FD,
+	0x7704, 0xD8F8, 0x7708, 0xF7AF, 0x7709, 0xDAB6, 0x770B, 0xCAD7,
+	0x771E, 0xF2D8, 0x7720, 0xD8F9, 0x7729, 0xFADF, 0x7737, 0xCFEF,
+	0x7738, 0xD9C2, 0x773A, 0xF0D2, 0x773C, 0xE4D1, 0x7740, 0xF3B7,
+	0x774D, 0xFAE0, 0x775B, 0xEFEC, 0x7761, 0xE2B2, 0x7763, 0xD4BD,
+	0x7766, 0xD9CE, 0x776B, 0xF4E2, 0x7779, 0xD4A9, 0x777E, 0xCDC2,
+	0x777F, 0xE7DA, 0x778B, 0xF2D9, 0x7791, 0xD9AA, 0x779E, 0xD8BE,
+	0x77A5, 0xDCAD, 0x77AC, 0xE2EB, 0x77AD, 0xD6FC, 0x77B0, 0xCAF9,
+	0x77B3, 0xD4DA, 0x77BB, 0xF4D7, 0x77BC, 0xCCA1, 0x77BF, 0xCFBA,
+	0x77D7, 0xF5B8, 0x77DB, 0xD9C3, 0x77DC, 0xD0E8, 0x77E2, 0xE3C5,
+	0x77E3, 0xEBF8, 0x77E5, 0xF2B1, 0x77E9, 0xCFBB, 0x77ED, 0xD3AD,
+	0x77EE, 0xE8E1, 0x77EF, 0xCEEC, 0x77F3, 0xE0B4, 0x7802, 0xDEE3,
+	0x7812, 0xDDF7, 0x7825, 0xF2B2, 0x7826, 0xF3F6, 0x7827, 0xF6DB,
+	0x782C, 0xD7FE, 0x7832, 0xF8DF, 0x7834, 0xF7F2, 0x7845, 0xD0A9,
+	0x784F, 0xE6DA, 0x785D, 0xF5A6, 0x786B, 0xD7BC, 0x786C, 0xCCE3,
+	0x786F, 0xE6DB, 0x787C, 0xDDDD, 0x7881, 0xD1B3, 0x7887, 0xEFED,
+	0x788C, 0xD6DE, 0x788D, 0xE4F4, 0x788E, 0xE1EF, 0x7891, 0xDDF8,
+	0x7897, 0xE8CF, 0x78A3, 0xCAE5, 0x78A7, 0xDCA1, 0x78A9, 0xE0B5,
+	0x78BA, 0xFCAC, 0x78BB, 0xFCAD, 0x78BC, 0xD8A7, 0x78C1, 0xEDB8,
+	0x78C5, 0xDBB6, 0x78CA, 0xD6F0, 0x78CB, 0xF3AF, 0x78CE, 0xCDA5,
+	0x78D0, 0xDAF1, 0x78E8, 0xD8A8, 0x78EC, 0xCCE4, 0x78EF, 0xD1B4,
+	0x78F5, 0xCAD8, 0x78FB, 0xDAF2, 0x7901, 0xF5A7, 0x790E, 0xF5A8,
+	0x7916, 0xE6A6, 0x792A, 0xD5EC, 0x792B, 0xD5F8, 0x792C, 0xDAF3,
+	0x793A, 0xE3C6, 0x793E, 0xDEE4, 0x7940, 0xDEE5, 0x7941, 0xD1B5,
+	0x7947, 0xD1B6, 0x7948, 0xD1B7, 0x7949, 0xF2B3, 0x7950, 0xE9DE,
+	0x7956, 0xF0D3, 0x7957, 0xF2B4, 0x795A, 0xF0D4, 0x795B, 0xCBE4,
+	0x795C, 0xFBD4, 0x795D, 0xF5E6, 0x795E, 0xE3EA, 0x7960, 0xDEE6,
+	0x7965, 0xDFD4, 0x7968, 0xF8F9, 0x796D, 0xF0AE, 0x797A, 0xD1B8,
+	0x797F, 0xD6DF, 0x7981, 0xD0D7, 0x798D, 0xFCA1, 0x798E, 0xEFEE,
+	0x798F, 0xDCD8, 0x7991, 0xE9DF, 0x79A6, 0xE5DD, 0x79A7, 0xFDFB,
+	0x79AA, 0xE0C9, 0x79AE, 0xD6C9, 0x79B1, 0xD4AA, 0x79B3, 0xE5CC,
+	0x79B9, 0xE9E0, 0x79BD, 0xD0D8, 0x79BE, 0xFCA2, 0x79BF, 0xD4BE,
+	0x79C0, 0xE2B3, 0x79C1, 0xDEE7, 0x79C9, 0xDCBC, 0x79CA, 0xD2B6,
+	0x79CB, 0xF5D5, 0x79D1, 0xCEA1, 0x79D2, 0xF5A9, 0x79D5, 0xDDF9,
+	0x79D8, 0xDDFA, 0x79DF, 0xF0D5, 0x79E4, 0xF6DF, 0x79E6, 0xF2DA,
+	0x79E7, 0xE4EB, 0x79E9, 0xF2F1, 0x79FB, 0xECB9, 0x7A00, 0xFDFC,
+	0x7A05, 0xE1AA, 0x7A08, 0xCAD9, 0x7A0B, 0xEFEF, 0x7A0D, 0xF5AA,
+	0x7A14, 0xECF9, 0x7A17, 0xF8AD, 0x7A19, 0xF2C2, 0x7A1A, 0xF6C3,
+	0x7A1C, 0xD7D2, 0x7A1F, 0xF9A2, 0x7A20, 0xF0D6, 0x7A2E, 0xF0FA,
+	0x7A31, 0xF6E0, 0x7A36, 0xE9F3, 0x7A37, 0xF2C3, 0x7A3B, 0xD4AB,
+	0x7A3C, 0xCAB3, 0x7A3D, 0xCDA6, 0x7A3F, 0xCDC3, 0x7A40, 0xCDDA,
+	0x7A46, 0xD9CF, 0x7A49, 0xF6C4, 0x7A4D, 0xEEDD, 0x7A4E, 0xE7C4,
+	0x7A57, 0xE2B4, 0x7A61, 0xDFE2, 0x7A62, 0xE7DB, 0x7A69, 0xE8B1,
+	0x7A6B, 0xFCAE, 0x7A70, 0xE5CD, 0x7A74, 0xFAEB, 0x7A76, 0xCFBC,
+	0x7A79, 0xCFE2, 0x7A7A, 0xCDF6, 0x7A7D, 0xEFF0, 0x7A7F, 0xF4BE,
+	0x7A81, 0xD4CD, 0x7A84, 0xF3B8, 0x7A88, 0xE9A1, 0x7A92, 0xF2F2,
+	0x7A93, 0xF3EB, 0x7A95, 0xF0D7, 0x7A98, 0xCFD7, 0x7A9F, 0xCFDF,
+	0x7AA9, 0xE8C0, 0x7AAA, 0xE8C1, 0x7AAE, 0xCFE3, 0x7AAF, 0xE9A2,
+	0x7ABA, 0xD0AA, 0x7AC4, 0xF3C1, 0x7AC5, 0xD0AB, 0x7AC7, 0xD4E4,
+	0x7ACA, 0xEFBC, 0x7ACB, 0xD8A1, 0x7AD7, 0xD9DF, 0x7AD9, 0xF3D7,
+	0x7ADD, 0xDCBD, 0x7ADF, 0xCCE5, 0x7AE0, 0xEDF1, 0x7AE3, 0xF1E2,
+	0x7AE5, 0xD4DB, 0x7AEA, 0xE2B5, 0x7AED, 0xCAE6, 0x7AEF, 0xD3AE,
+	0x7AF6, 0xCCE6, 0x7AF9, 0xF1D3, 0x7AFA, 0xF5E7, 0x7AFF, 0xCADA,
+	0x7B0F, 0xFBEE, 0x7B11, 0xE1C5, 0x7B19, 0xDFE9, 0x7B1B, 0xEEDE,
+	0x7B1E, 0xF7C2, 0x7B20, 0xD8A2, 0x7B26, 0xDDAC, 0x7B2C, 0xF0AF,
+	0x7B2D, 0xD6BD, 0x7B39, 0xE1AB, 0x7B46, 0xF9B6, 0x7B49, 0xD4F5,
+	0x7B4B, 0xD0C9, 0x7B4C, 0xEFA7, 0x7B4D, 0xE2EC, 0x7B4F, 0xDBEA,
+	0x7B50, 0xCECC, 0x7B51, 0xF5E8, 0x7B52, 0xF7D5, 0x7B54, 0xD3CD,
+	0x7B56, 0xF3FE, 0x7B60, 0xD0B5, 0x7B6C, 0xE0FE, 0x7B6E, 0xDFFB,
+	0x7B75, 0xE6DD, 0x7B7D, 0xE8A4, 0x7B87, 0xCBCD, 0x7B8B, 0xEFA8,
+	0x7B8F, 0xEEB4, 0x7B94, 0xDAD8, 0x7B95, 0xD1B9, 0x7B97, 0xDFA9,
+	0x7B9A, 0xF3B0, 0x7B9D, 0xCCC4, 0x7BA1, 0xCEB7, 0x7BAD, 0xEFA9,
+	0x7BB1, 0xDFD5, 0x7BB4, 0xEDD7, 0x7BB8, 0xEEC6, 0x7BC0, 0xEFBD,
+	0x7BC1, 0xFCD6, 0x7BC4, 0xDBF4, 0x7BC6, 0xEFAA, 0x7BC7, 0xF8B9,
+	0x7BC9, 0xF5E9, 0x7BD2, 0xE3D9, 0x7BE0, 0xE1C6, 0x7BE4, 0xD4BF,
+	0x7BE9, 0xDEE8, 0x7C07, 0xF0EA, 0x7C12, 0xF3C2, 0x7C1E, 0xD3AF,
+	0x7C21, 0xCADB, 0x7C27, 0xFCD7, 0x7C2A, 0xEDD8, 0x7C2B, 0xE1C7,
+	0x7C3D, 0xF4D8, 0x7C3E, 0xD6B3, 0x7C3F, 0xDDAD, 0x7C43, 0xD5BE,
+	0x7C4C, 0xF1C3, 0x7C4D, 0xEEDF, 0x7C60, 0xD6EB, 0x7C64, 0xF4D9,
+	0x7C6C, 0xD7E6, 0x7C73, 0xDAB7, 0x7C83, 0xDDFB, 0x7C89, 0xDDCF,
+	0x7C92, 0xD8A3, 0x7C95, 0xDAD9, 0x7C97, 0xF0D8, 0x7C98, 0xEFC4,
+	0x7C9F, 0xE1D8, 0x7CA5, 0xF1D4, 0x7CA7, 0xEDF2, 0x7CAE, 0xD5DB,
+	0x7CB1, 0xD5DC, 0x7CB2, 0xF3C4, 0x7CB3, 0xCBD7, 0x7CB9, 0xE2B6,
+	0x7CBE, 0xEFF1, 0x7CCA, 0xFBD5, 0x7CD6, 0xD3D8, 0x7CDE, 0xDDD0,
+	0x7CDF, 0xF0D9, 0x7CE0, 0xCBB3, 0x7CE7, 0xD5DD, 0x7CFB, 0xCDA7,
+	0x7CFE, 0xD0AC, 0x7D00, 0xD1BA, 0x7D02, 0xF1C4, 0x7D04, 0xE5B3,
+	0x7D05, 0xFBF5, 0x7D06, 0xE9E1, 0x7D07, 0xFDE0, 0x7D08, 0xFCBC,
+	0x7D0A, 0xDAA2, 0x7D0B, 0xDAA3, 0x7D0D, 0xD2A1, 0x7D10, 0xD2EF,
+	0x7D14, 0xE2ED, 0x7D17, 0xDEE9, 0x7D18, 0xCEDC, 0x7D19, 0xF2B5,
+	0x7D1A, 0xD0E4, 0x7D1B, 0xDDD1, 0x7D20, 0xE1C8, 0x7D21, 0xDBB7,
+	0x7D22, 0xDFE3, 0x7D2B, 0xEDB9, 0x7D2C, 0xF1C5, 0x7D2E, 0xF3CF,
+	0x7D2F, 0xD7AB, 0x7D30, 0xE1AC, 0x7D33, 0xE3EB, 0x7D35, 0xEEC7,
+	0x7D39, 0xE1C9, 0x7D3A, 0xCAFA, 0x7D42, 0xF0FB, 0x7D43, 0xFAE1,
+	0x7D44, 0xF0DA, 0x7D45, 0xCCE7, 0x7D46, 0xDAF4, 0x7D50, 0xCCBF,
+	0x7D5E, 0xCEED, 0x7D61, 0xD5A9, 0x7D62, 0xFAE2, 0x7D66, 0xD0E5,
+	0x7D68, 0xEBD6, 0x7D6A, 0xECDF, 0x7D6E, 0xDFFC, 0x7D71, 0xF7D6,
+	0x7D72, 0xDEEA, 0x7D73, 0xCBB4, 0x7D76, 0xEFBE, 0x7D79, 0xCCB5,
+	0x7D7F, 0xCFBD, 0x7D8E, 0xEFF2, 0x7D8F, 0xE2B7, 0x7D93, 0xCCE8,
+	0x7D9C, 0xF0FC, 0x7DA0, 0xD6E0, 0x7DA2, 0xF1C6, 0x7DAC, 0xE2B8,
+	0x7DAD, 0xEBAB, 0x7DB1, 0xCBB5, 0x7DB2, 0xD8D1, 0x7DB4, 0xF4CE,
+	0x7DB5, 0xF3F7, 0x7DB8, 0xD7C6, 0x7DBA, 0xD1BB, 0x7DBB, 0xF7AA,
+	0x7DBD, 0xEDCA, 0x7DBE, 0xD7D3, 0x7DBF, 0xD8FA, 0x7DC7, 0xF6C5,
+	0x7DCA, 0xD1CC, 0x7DCB, 0xDDFC, 0x7DD6, 0xDFFD, 0x7DD8, 0xF9E5,
+	0x7DDA, 0xE0CA, 0x7DDD, 0xF2FD, 0x7DDE, 0xD3B0, 0x7DE0, 0xF4F3,
+	0x7DE1, 0xDAC9, 0x7DE3, 0xE6DE, 0x7DE8, 0xF8BA, 0x7DE9, 0xE8D0,
+	0x7DEC, 0xD8FB, 0x7DEF, 0xEAD5, 0x7DF4, 0xD6A3, 0x7DFB, 0xF6C6,
+	0x7E09, 0xF2DB, 0x7E0A, 0xE4FC, 0x7E15, 0xE8B2, 0x7E1B, 0xDADA,
+	0x7E1D, 0xF2DC, 0x7E1E, 0xFBD6, 0x7E1F, 0xE9B2, 0x7E21, 0xEEAD,
+	0x7E23, 0xFAE3, 0x7E2B, 0xDCEE, 0x7E2E, 0xF5EA, 0x7E2F, 0xE6E0,
+	0x7E31, 0xF0FD, 0x7E37, 0xD7AC, 0x7E3D, 0xF5C5, 0x7E3E, 0xEEE0,
+	0x7E41, 0xDBE5, 0x7E43, 0xDDDE, 0x7E46, 0xD9F0, 0x7E47, 0xE9A3,
+	0x7E52, 0xF1F9, 0x7E54, 0xF2C4, 0x7E55, 0xE0CB, 0x7E5E, 0xE9A4,
+	0x7E61, 0xE2B9, 0x7E69, 0xE3B1, 0x7E6A, 0xFCEB, 0x7E6B, 0xCDA8,
+	0x7E6D, 0xCCB6, 0x7E70, 0xF0DB, 0x7E79, 0xE6BA, 0x7E7C, 0xCDA9,
+	0x7E82, 0xF3C3, 0x7E8C, 0xE1D9, 0x7E8F, 0xEFAB, 0x7E93, 0xE7C5,
+	0x7E96, 0xE0E9, 0x7E98, 0xF3C5, 0x7E9B, 0xD4C0, 0x7E9C, 0xD5BF,
+	0x7F36, 0xDDAE, 0x7F38, 0xF9FC, 0x7F3A, 0xCCC0, 0x7F4C, 0xE5A2,
+	0x7F50, 0xCEB8, 0x7F54, 0xD8D2, 0x7F55, 0xF9D6, 0x7F6A, 0xF1AA,
+	0x7F6B, 0xCED1, 0x7F6E, 0xF6C7, 0x7F70, 0xDBEB, 0x7F72, 0xDFFE,
+	0x7F75, 0xD8E1, 0x7F77, 0xF7F3, 0x7F79, 0xD7E7, 0x7F85, 0xD4FE,
+	0x7F88, 0xD1BC, 0x7F8A, 0xE5CF, 0x7F8C, 0xCBB6, 0x7F8E, 0xDAB8,
+	0x7F94, 0xCDC4, 0x7F9A, 0xD6BE, 0x7F9E, 0xE2BA, 0x7FA4, 0xCFD8,
+	0x7FA8, 0xE0CC, 0x7FA9, 0xEBF9, 0x7FB2, 0xFDFD, 0x7FB8, 0xD7E8,
+	0x7FB9, 0xCBD8, 0x7FBD, 0xE9E2, 0x7FC1, 0xE8BA, 0x7FC5, 0xE3C7,
+	0x7FCA, 0xECCD, 0x7FCC, 0xECCE, 0x7FCE, 0xD6BF, 0x7FD2, 0xE3A7,
+	0x7FD4, 0xDFD6, 0x7FD5, 0xFDE8, 0x7FDF, 0xEEE1, 0x7FE0, 0xF6A8,
+	0x7FE1, 0xDDFD, 0x7FE9, 0xF8BB, 0x7FEB, 0xE8D1, 0x7FF0, 0xF9D7,
+	0x7FF9, 0xCEEE, 0x7FFC, 0xECCF, 0x8000, 0xE9A5, 0x8001, 0xD6D5,
+	0x8003, 0xCDC5, 0x8005, 0xEDBA, 0x8006, 0xD1BD, 0x8009, 0xCFBE,
+	0x800C, 0xECBB, 0x8010, 0xD2B1, 0x8015, 0xCCE9, 0x8017, 0xD9C4,
+	0x8018, 0xE9FC, 0x802D, 0xD1BE, 0x8033, 0xECBC, 0x8036, 0xE5AD,
+	0x803D, 0xF7B0, 0x803F, 0xCCEA, 0x8043, 0xD3C4, 0x8046, 0xD6C0,
+	0x804A, 0xD6FD, 0x8056, 0xE1A1, 0x8058, 0xDEBD, 0x805A, 0xF6A9,
+	0x805E, 0xDAA4, 0x806F, 0xD6A4, 0x8070, 0xF5C6, 0x8072, 0xE1A2,
+	0x8073, 0xE9C6, 0x8077, 0xF2C5, 0x807D, 0xF4E9, 0x807E, 0xD6EC,
+	0x807F, 0xEBD3, 0x8084, 0xECBD, 0x8085, 0xE2DC, 0x8086, 0xDEEB,
+	0x8087, 0xF0DC, 0x8089, 0xEBBF, 0x808B, 0xD7CE, 0x808C, 0xD1BF,
+	0x8096, 0xF5AB, 0x809B, 0xF9FD, 0x809D, 0xCADC, 0x80A1, 0xCDC6,
+	0x80A2, 0xF2B6, 0x80A5, 0xDDFE, 0x80A9, 0xCCB7, 0x80AA, 0xDBB8,
+	0x80AF, 0xD0E9, 0x80B1, 0xCEDD, 0x80B2, 0xEBC0, 0x80B4, 0xFDA2,
+	0x80BA, 0xF8CB, 0x80C3, 0xEAD6, 0x80C4, 0xF1B0, 0x80CC, 0xDBCE,
+	0x80CE, 0xF7C3, 0x80DA, 0xDBCF, 0x80DB, 0xCBA4, 0x80DE, 0xF8E0,
+	0x80E1, 0xFBD7, 0x80E4, 0xEBCA, 0x80E5, 0xE0A1, 0x80F1, 0xCECD,
+	0x80F4, 0xD4DC, 0x80F8, 0xFDD8, 0x80FD, 0xD2F6, 0x8102, 0xF2B7,
+	0x8105, 0xFAF6, 0x8106, 0xF6AA, 0x8107, 0xFAF7, 0x8108, 0xD8E6,
+	0x810A, 0xF4B1, 0x8118, 0xE8D2, 0x811A, 0xCAC5, 0x811B, 0xCCEB,
+	0x8123, 0xE2EE, 0x8129, 0xE2BB, 0x812B, 0xF7AD, 0x812F, 0xF8E1,
+	0x8139, 0xF3EC, 0x813E, 0xDEA1, 0x814B, 0xE4FD, 0x814E, 0xE3EC,
+	0x8150, 0xDDAF, 0x8151, 0xDDB0, 0x8154, 0xCBB7, 0x8155, 0xE8D3,
+	0x8165, 0xE1A3, 0x8166, 0xD2E0, 0x816B, 0xF0FE, 0x8170, 0xE9A6,
+	0x8171, 0xCBF2, 0x8178, 0xEDF3, 0x8179, 0xDCD9, 0x817A, 0xE0CD,
+	0x817F, 0xF7DA, 0x8180, 0xDBB9, 0x8188, 0xCCAE, 0x818A, 0xDADB,
+	0x818F, 0xCDC7, 0x819A, 0xDDB1, 0x819C, 0xD8AF, 0x819D, 0xE3A3,
+	0x81A0, 0xCEEF, 0x81A3, 0xF2F3, 0x81A8, 0xF8B3, 0x81B3, 0xE0CE,
+	0x81B5, 0xF5FD, 0x81BA, 0xEBEC, 0x81BD, 0xD3C5, 0x81BE, 0xFCEC,
+	0x81BF, 0xD2DB, 0x81C0, 0xD4EB, 0x81C2, 0xDEA2, 0x81C6, 0xE5E6,
+	0x81CD, 0xF0B0, 0x81D8, 0xD5C4, 0x81DF, 0xEDF4, 0x81E3, 0xE3ED,
+	0x81E5, 0xE8C2, 0x81E7, 0xEDF5, 0x81E8, 0xD7FC, 0x81EA, 0xEDBB,
+	0x81ED, 0xF6AB, 0x81F3, 0xF2B8, 0x81F4, 0xF6C8, 0x81FA, 0xD3E6,
+	0x81FB, 0xF2DD, 0x81FC, 0xCFBF, 0x81FE, 0xEBAC, 0x8205, 0xCFC0,
+	0x8207, 0xE6A8, 0x8208, 0xFDE9, 0x820A, 0xCFC1, 0x820C, 0xE0DF,
+	0x820D, 0xDEEC, 0x8212, 0xE0A2, 0x821B, 0xF4BF, 0x821C, 0xE2EF,
+	0x821E, 0xD9F1, 0x821F, 0xF1C7, 0x8221, 0xCBB8, 0x822A, 0xF9FE,
+	0x822B, 0xDBBA, 0x822C, 0xDAF5, 0x8235, 0xF6EC, 0x8236, 0xDADC,
+	0x8237, 0xFAE4, 0x8239, 0xE0CF, 0x8240, 0xDDB2, 0x8245, 0xE6A9,
+	0x8247, 0xEFF3, 0x8259, 0xF3ED, 0x8264, 0xEBFA, 0x8266, 0xF9E6,
+	0x826E, 0xCADD, 0x826F, 0xD5DE, 0x8271, 0xCADE, 0x8272, 0xDFE4,
+	0x8276, 0xE6FD, 0x8278, 0xF5AC, 0x827E, 0xE4F5, 0x828B, 0xE9E3,
+	0x828D, 0xEDCB, 0x828E, 0xCFE4, 0x8292, 0xD8D3, 0x8299, 0xDDB3,
+	0x829A, 0xD4EC, 0x829D, 0xF2B9, 0x829F, 0xDFB7, 0x82A5, 0xCBCE,
+	0x82A6, 0xFBD8, 0x82A9, 0xD0D9, 0x82AC, 0xDDD2, 0x82AD, 0xF7F4,
+	0x82AE, 0xE7DC, 0x82AF, 0xE4A5, 0x82B1, 0xFCA3, 0x82B3, 0xDBBB,
+	0x82B7, 0xF2BA, 0x82B8, 0xE9FD, 0x82B9, 0xD0CA, 0x82BB, 0xF5D6,
+	0x82BC, 0xD9C5, 0x82BD, 0xE4B4, 0x82BF, 0xEDA7, 0x82D1, 0xEABD,
+	0x82D2, 0xE6FE, 0x82D4, 0xF7C4, 0x82D5, 0xF5AD, 0x82D7, 0xD9E0,
+	0x82DB, 0xCAB4, 0x82DE, 0xF8E2, 0x82DF, 0xCFC2, 0x82E1, 0xECBE,
+	0x82E5, 0xE5B4, 0x82E6, 0xCDC8, 0x82E7, 0xEEC8, 0x82F1, 0xE7C8,
+	0x82FD, 0xCDC9, 0x82FE, 0xF9B7, 0x8301, 0xF1E8, 0x8302, 0xD9F2,
+	0x8303, 0xDBF5, 0x8304, 0xCAB5, 0x8305, 0xD9C6, 0x8309, 0xD8C9,
+	0x8317, 0xD9AB, 0x8328, 0xEDBC, 0x832B, 0xD8D4, 0x832F, 0xDCDA,
+	0x8331, 0xE2BC, 0x8334, 0xFCED, 0x8335, 0xECE0, 0x8336, 0xD2FE,
+	0x8338, 0xE9C7, 0x8339, 0xE6AA, 0x8340, 0xE2F0, 0x8347, 0xFABB,
+	0x8349, 0xF5AE, 0x834A, 0xFBAA, 0x834F, 0xECFB, 0x8351, 0xECBF,
+	0x8352, 0xFCD8, 0x8373, 0xD4E5, 0x8377, 0xF9C3, 0x837B, 0xEEE2,
+	0x8389, 0xD7E9, 0x838A, 0xEDF6, 0x838E, 0xDEED, 0x8396, 0xCCEC,
+	0x8398, 0xE3EE, 0x839E, 0xE8D4, 0x83A2, 0xFAF8, 0x83A9, 0xDDB4,
+	0x83AA, 0xE4B5, 0x83AB, 0xD8B0, 0x83BD, 0xD8D5, 0x83C1, 0xF4EA,
+	0x83C5, 0xCEB9, 0x83C9, 0xD6E1, 0x83CA, 0xCFD2, 0x83CC, 0xD0B6,
+	0x83D3, 0xCEA2, 0x83D6, 0xF3EE, 0x83DC, 0xF3F8, 0x83E9, 0xDCCC,
+	0x83EB, 0xD0CB, 0x83EF, 0xFCA4, 0x83F0, 0xCDCA, 0x83F1, 0xD7D4,
+	0x83F2, 0xDEA3, 0x83F4, 0xE4E0, 0x83F9, 0xEEC9, 0x83FD, 0xE2DD,
+	0x8403, 0xF5FE, 0x8404, 0xD4AC, 0x840A, 0xD5D1, 0x840C, 0xD8F0,
+	0x840D, 0xF8C3, 0x840E, 0xEAD7, 0x8429, 0xF5D7, 0x842C, 0xD8BF,
+	0x8431, 0xFDC0, 0x8438, 0xEBAD, 0x843D, 0xD5AA, 0x8449, 0xE7A8,
+	0x8457, 0xEECA, 0x845B, 0xCAE7, 0x8461, 0xF8E3, 0x8463, 0xD4DD,
+	0x8466, 0xEAD8, 0x846B, 0xFBD9, 0x846C, 0xEDF7, 0x846F, 0xE5B5,
+	0x8475, 0xD0AD, 0x847A, 0xF1F1, 0x8490, 0xE2BD, 0x8494, 0xE3C8,
+	0x8499, 0xD9D5, 0x849C, 0xDFAA, 0x84A1, 0xDBBC, 0x84B2, 0xF8E4,
+	0x84B8, 0xF1FA, 0x84BB, 0xE5B6, 0x84BC, 0xF3EF, 0x84BF, 0xFBDA,
+	0x84C0, 0xE1E0, 0x84C2, 0xD9AC, 0x84C4, 0xF5EB, 0x84C6, 0xE0B6,
+	0x84C9, 0xE9C8, 0x84CB, 0xCBCF, 0x84CD, 0xE3C9, 0x84D1, 0xDEEE,
+	0x84DA, 0xE2BE, 0x84EC, 0xDCEF, 0x84EE, 0xD6A5, 0x84F4, 0xE2F1,
+	0x84FC, 0xD6FE, 0x8511, 0xD9A1, 0x8513, 0xD8C0, 0x8514, 0xDCDB,
+	0x8517, 0xEDBD, 0x8518, 0xDFB8, 0x851A, 0xEAA5, 0x851E, 0xD7AD,
+	0x8521, 0xF3F9, 0x8523, 0xEDF8, 0x8525, 0xF5C7, 0x852C, 0xE1CA,
+	0x852D, 0xEBE3, 0x852F, 0xF2DE, 0x853D, 0xF8CC, 0x853F, 0xEAD9,
+	0x8541, 0xD3C6, 0x8543, 0xDBE6, 0x8549, 0xF5AF, 0x854E, 0xCEF0,
+	0x8553, 0xE9FE, 0x8559, 0xFBB6, 0x8563, 0xE2F2, 0x8568, 0xCFF2,
+	0x8569, 0xF7B9, 0x856A, 0xD9F3, 0x856D, 0xE1CB, 0x8584, 0xDADD,
+	0x8587, 0xDAB9, 0x858F, 0xEBFB, 0x8591, 0xCBB9, 0x8594, 0xEDF9,
+	0x859B, 0xE0E0, 0x85A6, 0xF4C0, 0x85A8, 0xFDBC, 0x85A9, 0xDFB1,
+	0x85AA, 0xE3EF, 0x85AF, 0xE0A3, 0x85B0, 0xFDB9, 0x85BA, 0xF0B1,
+	0x85C1, 0xCDCB, 0x85C9, 0xEDBE, 0x85CD, 0xD5C0, 0x85CE, 0xE3F0,
+	0x85CF, 0xEDFA, 0x85D5, 0xE9E4, 0x85DC, 0xD5ED, 0x85DD, 0xE7DD,
+	0x85E4, 0xD4F6, 0x85E5, 0xE5B7, 0x85E9, 0xDBE7, 0x85EA, 0xE2BF,
+	0x85F7, 0xEECB, 0x85FA, 0xD7F4, 0x85FB, 0xF0DD, 0x85FF, 0xCEAB,
+	0x8602, 0xE7DE, 0x8606, 0xD6D6, 0x8607, 0xE1CC, 0x860A, 0xE8B3,
+	0x8616, 0xE5EE, 0x8617, 0xDCA2, 0x861A, 0xE0D0, 0x862D, 0xD5B5,
+	0x863F, 0xD5A1, 0x864E, 0xFBDB, 0x8650, 0xF9CB, 0x8654, 0xCBF3,
+	0x8655, 0xF4A5, 0x865B, 0xFAC8, 0x865C, 0xD6D7, 0x865E, 0xE9E5,
+	0x865F, 0xFBDC, 0x8667, 0xFDD0, 0x8679, 0xFBF6, 0x868A, 0xDAA5,
+	0x868C, 0xDBBD, 0x8693, 0xECE2, 0x86A3, 0xCDF7, 0x86A4, 0xF0DE,
+	0x86A9, 0xF6C9, 0x86C7, 0xDEEF, 0x86CB, 0xD3B1, 0x86D4, 0xFCEE,
+	0x86D9, 0xE8C3, 0x86DB, 0xF1C8, 0x86DF, 0xCEF1, 0x86E4, 0xF9ED,
+	0x86ED, 0xF2F4, 0x86FE, 0xE4B6, 0x8700, 0xF5B9, 0x8702, 0xDCF0,
+	0x8703, 0xE3F1, 0x8708, 0xE8A5, 0x8718, 0xF2BB, 0x871A, 0xDEA4,
+	0x871C, 0xDACC, 0x874E, 0xCAE9, 0x8755, 0xE3DA, 0x8757, 0xFCD9,
+	0x875F, 0xEADA, 0x8766, 0xF9C4, 0x8768, 0xE3A4, 0x8774, 0xFBDD,
+	0x8776, 0xEFCA, 0x8778, 0xE8C4, 0x8782, 0xD5CC, 0x878D, 0xEBD7,
+	0x879F, 0xD9AD, 0x87A2, 0xFBAB, 0x87B3, 0xD3D9, 0x87BA, 0xD5A2,
+	0x87C4, 0xF6DE, 0x87E0, 0xDAF6, 0x87EC, 0xE0D1, 0x87EF, 0xE9A8,
+	0x87F2, 0xF5F9, 0x87F9, 0xFAAF, 0x87FB, 0xEBFC, 0x87FE, 0xE0EA,
+	0x8805, 0xE3B2, 0x881F, 0xD5C5, 0x8822, 0xF1E3, 0x8823, 0xD5EE,
+	0x8831, 0xCDCC, 0x8836, 0xEDD9, 0x883B, 0xD8C1, 0x8840, 0xFAEC,
+	0x8846, 0xF1EB, 0x884C, 0xFABC, 0x884D, 0xE6E2, 0x8852, 0xFAE5,
+	0x8853, 0xE2FA, 0x8857, 0xCAB6, 0x8859, 0xE4B7, 0x885B, 0xEADB,
+	0x885D, 0xF5FA, 0x8861, 0xFBAC, 0x8862, 0xCFC3, 0x8863, 0xEBFD,
+	0x8868, 0xF8FA, 0x886B, 0xDFB9, 0x8870, 0xE1F1, 0x8872, 0xD2A4,
+	0x8877, 0xF5FB, 0x887E, 0xD0DA, 0x887F, 0xD0DB, 0x8881, 0xEABE,
+	0x8882, 0xD9B1, 0x8888, 0xCAB7, 0x888B, 0xD3E7, 0x888D, 0xF8E5,
+	0x8892, 0xD3B2, 0x8896, 0xE2C0, 0x8897, 0xF2DF, 0x889E, 0xCDE5,
+	0x88AB, 0xF9AC, 0x88B4, 0xCDCD, 0x88C1, 0xEEAE, 0x88C2, 0xD6AE,
+	0x88CF, 0xD7EA, 0x88D4, 0xE7E0, 0x88D5, 0xEBAE, 0x88D9, 0xCFD9,
+	0x88DC, 0xDCCD, 0x88DD, 0xEDFB, 0x88DF, 0xDEF0, 0x88E1, 0xD7EB,
+	0x88E8, 0xDEA5, 0x88F3, 0xDFD7, 0x88F4, 0xDBD0, 0x88F5, 0xDBD1,
+	0x88F8, 0xD5A3, 0x88FD, 0xF0B2, 0x8907, 0xDCDC, 0x8910, 0xCAE8,
+	0x8912, 0xF8E6, 0x8913, 0xDCCE, 0x8918, 0xEADC, 0x8919, 0xDBD2,
+	0x8925, 0xE9B3, 0x892A, 0xF7DB, 0x8936, 0xE3A8, 0x8938, 0xD7AE,
+	0x893B, 0xE0E1, 0x8941, 0xCBBA, 0x8944, 0xE5D1, 0x895F, 0xD0DC,
+	0x8964, 0xD5C1, 0x896A, 0xD8CA, 0x8972, 0xE3A9, 0x897F, 0xE0A4,
+	0x8981, 0xE9A9, 0x8983, 0xD3C7, 0x8986, 0xDCDD, 0x8987, 0xF8AE,
+	0x898B, 0xCCB8, 0x898F, 0xD0AE, 0x8993, 0xD8F2, 0x8996, 0xE3CA,
+	0x89A1, 0xCCAF, 0x89A9, 0xD4AD, 0x89AA, 0xF6D1, 0x89B2, 0xD0CC,
+	0x89BA, 0xCAC6, 0x89BD, 0xD5C2, 0x89C0, 0xCEBA, 0x89D2, 0xCAC7,
+	0x89E3, 0xFAB0, 0x89F4, 0xDFD8, 0x89F8, 0xF5BA, 0x8A00, 0xE5EB,
+	0x8A02, 0xEFF4, 0x8A03, 0xDDB5, 0x8A08, 0xCDAA, 0x8A0A, 0xE3F2,
+	0x8A0C, 0xFBF7, 0x8A0E, 0xF7D0, 0x8A13, 0xFDBA, 0x8A16, 0xFDE1,
+	0x8A17, 0xF6FE, 0x8A18, 0xD1C0, 0x8A1B, 0xE8C5, 0x8A1D, 0xE4B8,
+	0x8A1F, 0xE1E8, 0x8A23, 0xCCC1, 0x8A25, 0xD2ED, 0x8A2A, 0xDBBE,
+	0x8A2D, 0xE0E2, 0x8A31, 0xFAC9, 0x8A34, 0xE1CD, 0x8A36, 0xCAB8,
+	0x8A3A, 0xF2E0, 0x8A3B, 0xF1C9, 0x8A50, 0xDEF1, 0x8A54, 0xF0DF,
+	0x8A55, 0xF8C4, 0x8A5B, 0xEECC, 0x8A5E, 0xDEF2, 0x8A60, 0xE7C9,
+	0x8A62, 0xE2F3, 0x8A63, 0xE7E1, 0x8A66, 0xE3CB, 0x8A69, 0xE3CC,
+	0x8A6D, 0xCFF8, 0x8A6E, 0xEFAC, 0x8A70, 0xFDFE, 0x8A71, 0xFCA5,
+	0x8A72, 0xFAB1, 0x8A73, 0xDFD9, 0x8A75, 0xE0D2, 0x8A79, 0xF4DA,
+	0x8A85, 0xF1CA, 0x8A87, 0xCEA3, 0x8A8C, 0xF2BC, 0x8A8D, 0xECE3,
+	0x8A93, 0xE0A5, 0x8A95, 0xF7AB, 0x8A98, 0xEBAF, 0x8A9E, 0xE5DE,
+	0x8AA0, 0xE1A4, 0x8AA1, 0xCDAB, 0x8AA3, 0xD9F4, 0x8AA4, 0xE8A6,
+	0x8AA5, 0xCDCE, 0x8AA6, 0xE1E9, 0x8AA8, 0xFCEF, 0x8AAA, 0xE0E3,
+	0x8AB0, 0xE2C1, 0x8AB2, 0xCEA4, 0x8AB9, 0xDEA6, 0x8ABC, 0xEBFE,
+	0x8ABE, 0xEBDD, 0x8ABF, 0xF0E0, 0x8AC2, 0xF4DB, 0x8AC4, 0xE2F4,
+	0x8AC7, 0xD3C8, 0x8ACB, 0xF4EB, 0x8ACD, 0xEEB5, 0x8ACF, 0xF5D8,
+	0x8AD2, 0xD5DF, 0x8AD6, 0xD6E5, 0x8ADB, 0xEBB0, 0x8ADC, 0xF4E3,
+	0x8AE1, 0xE3CD, 0x8AE6, 0xF4F4, 0x8AE7, 0xFAB2, 0x8AEA, 0xEFF5,
+	0x8AEB, 0xCADF, 0x8AED, 0xEBB1, 0x8AEE, 0xEDBF, 0x8AF1, 0xFDC9,
+	0x8AF6, 0xE4A6, 0x8AF7, 0xF9A4, 0x8AF8, 0xF0B3, 0x8AFA, 0xE5EC,
+	0x8AFE, 0xD1E7, 0x8B00, 0xD9C7, 0x8B01, 0xE4D7, 0x8B02, 0xEADD,
+	0x8B04, 0xD4F7, 0x8B0E, 0xDABA, 0x8B10, 0xDACD, 0x8B14, 0xF9CC,
+	0x8B16, 0xE1DA, 0x8B17, 0xDBBF, 0x8B19, 0xCCC5, 0x8B1A, 0xECD0,
+	0x8B1B, 0xCBBB, 0x8B1D, 0xDEF3, 0x8B20, 0xE9AA, 0x8B28, 0xD9C8,
+	0x8B2B, 0xEEE3, 0x8B2C, 0xD7BD, 0x8B33, 0xCFC4, 0x8B39, 0xD0CD,
+	0x8B41, 0xFCA6, 0x8B49, 0xF1FB, 0x8B4E, 0xFDD2, 0x8B4F, 0xD1C1,
+	0x8B58, 0xE3DB, 0x8B5A, 0xD3C9, 0x8B5C, 0xDCCF, 0x8B66, 0xCCED,
+	0x8B6C, 0xDEA7, 0x8B6F, 0xE6BB, 0x8B70, 0xECA1, 0x8B74, 0xCCB9,
+	0x8B77, 0xFBDE, 0x8B7D, 0xE7E2, 0x8B80, 0xD4C1, 0x8B8A, 0xDCA8,
+	0x8B90, 0xE2C2, 0x8B92, 0xF3D8, 0x8B93, 0xE5D3, 0x8B96, 0xF3D9,
+	0x8B9A, 0xF3C6, 0x8C37, 0xCDDB, 0x8C3F, 0xCDAC, 0x8C41, 0xFCC3,
+	0x8C46, 0xD4E7, 0x8C48, 0xD1C2, 0x8C4A, 0xF9A5, 0x8C4C, 0xE8D5,
+	0x8C55, 0xE3CE, 0x8C5A, 0xD4CA, 0x8C61, 0xDFDA, 0x8C6A, 0xFBDF,
+	0x8C6B, 0xE7E3, 0x8C79, 0xF8FB, 0x8C7A, 0xE3CF, 0x8C82, 0xF5B0,
+	0x8C8A, 0xD8E7, 0x8C8C, 0xD9C9, 0x8C9D, 0xF8AF, 0x8C9E, 0xEFF6,
+	0x8CA0, 0xDDB6, 0x8CA1, 0xEEAF, 0x8CA2, 0xCDF8, 0x8CA7, 0xDEB8,
+	0x8CA8, 0xFCA7, 0x8CA9, 0xF7FC, 0x8CAA, 0xF7B1, 0x8CAB, 0xCEBB,
+	0x8CAC, 0xF4A1, 0x8CAF, 0xEECD, 0x8CB0, 0xE1AE, 0x8CB3, 0xECC3,
+	0x8CB4, 0xCFFE, 0x8CB6, 0xF8BF, 0x8CB7, 0xD8E2, 0x8CB8, 0xD3E8,
+	0x8CBB, 0xDEA8, 0x8CBC, 0xF4E4, 0x8CBD, 0xECC2, 0x8CBF, 0xD9F5,
+	0x8CC0, 0xF9C5, 0x8CC1, 0xDDD3, 0x8CC2, 0xD6F1, 0x8CC3, 0xECFC,
+	0x8CC4, 0xFCF0, 0x8CC7, 0xEDC0, 0x8CC8, 0xCAB9, 0x8CCA, 0xEEE4,
+	0x8CD1, 0xF2E1, 0x8CD3, 0xDEB9, 0x8CDA, 0xD6F2, 0x8CDC, 0xDEF4,
+	0x8CDE, 0xDFDB, 0x8CE0, 0xDBD3, 0x8CE2, 0xFAE7, 0x8CE3, 0xD8E3,
+	0x8CE4, 0xF4C1, 0x8CE6, 0xDDB7, 0x8CEA, 0xF2F5, 0x8CED, 0xD4AE,
+	0x8CF4, 0xD6F3, 0x8CFB, 0xDDB8, 0x8CFC, 0xCFC5, 0x8CFD, 0xDFDF,
+	0x8D04, 0xF2BE, 0x8D05, 0xF6A1, 0x8D07, 0xEBCB, 0x8D08, 0xF1FC,
+	0x8D0A, 0xF3C7, 0x8D0D, 0xE0EB, 0x8D13, 0xEDFC, 0x8D16, 0xE1DB,
+	0x8D64, 0xEEE5, 0x8D66, 0xDEF5, 0x8D6B, 0xFAD3, 0x8D70, 0xF1CB,
+	0x8D73, 0xD0AF, 0x8D74, 0xDDB9, 0x8D77, 0xD1C3, 0x8D85, 0xF5B1,
+	0x8D8A, 0xEAC6, 0x8D99, 0xF0E1, 0x8DA3, 0xF6AC, 0x8DA8, 0xF5D9,
+	0x8DB3, 0xF0EB, 0x8DBA, 0xDDBA, 0x8DBE, 0xF2BF, 0x8DC6, 0xF7C5,
+	0x8DCB, 0xDBA2, 0x8DCC, 0xF2F6, 0x8DCF, 0xCABA, 0x8DDB, 0xF7F5,
+	0x8DDD, 0xCBE5, 0x8DE1, 0xEEE6, 0x8DE3, 0xE0D3, 0x8DE8, 0xCEA5,
+	0x8DEF, 0xD6D8, 0x8DF3, 0xD4AF, 0x8E0A, 0xE9C9, 0x8E0F, 0xD3CE,
+	0x8E10, 0xF4C2, 0x8E1E, 0xCBE6, 0x8E2A, 0xF1A1, 0x8E30, 0xEBB2,
+	0x8E35, 0xF1A2, 0x8E42, 0xEBB3, 0x8E44, 0xF0B4, 0x8E47, 0xCBF4,
+	0x8E48, 0xD4B0, 0x8E49, 0xF3B2, 0x8E4A, 0xFBB7, 0x8E59, 0xF5EC,
+	0x8E5F, 0xEEE7, 0x8E60, 0xF4B2, 0x8E74, 0xF5ED, 0x8E76, 0xCFF3,
+	0x8E81, 0xF0E2, 0x8E87, 0xEECE, 0x8E8A, 0xF1CC, 0x8E8D, 0xE5B8,
+	0x8EAA, 0xD7F5, 0x8EAB, 0xE3F3, 0x8EAC, 0xCFE5, 0x8EC0, 0xCFC6,
+	0x8ECA, 0xF3B3, 0x8ECB, 0xE4D8, 0x8ECC, 0xCFF9, 0x8ECD, 0xCFDA,
+	0x8ED2, 0xFACD, 0x8EDF, 0xE6E3, 0x8EEB, 0xF2E2, 0x8EF8, 0xF5EE,
+	0x8EFB, 0xCABB, 0x8EFE, 0xE3DC, 0x8F03, 0xCEF2, 0x8F05, 0xD6D9,
+	0x8F09, 0xEEB0, 0x8F12, 0xF4E5, 0x8F13, 0xD8C2, 0x8F14, 0xDCD0,
+	0x8F15, 0xCCEE, 0x8F1B, 0xD5E0, 0x8F1C, 0xF6CA, 0x8F1D, 0xFDCA,
+	0x8F1E, 0xD8D6, 0x8F1F, 0xF4CF, 0x8F26, 0xD6A6, 0x8F27, 0xDCBE,
+	0x8F29, 0xDBD4, 0x8F2A, 0xD7C7, 0x8F2F, 0xF2FE, 0x8F33, 0xF1CD,
+	0x8F38, 0xE2C3, 0x8F39, 0xDCDE, 0x8F3B, 0xDCDF, 0x8F3E, 0xEFAD,
+	0x8F3F, 0xE6AB, 0x8F44, 0xF9DD, 0x8F45, 0xEABF, 0x8F49, 0xEFAE,
+	0x8F4D, 0xF4D0, 0x8F4E, 0xCEF3, 0x8F5D, 0xE6AC, 0x8F5F, 0xCEDE,
+	0x8F62, 0xD5F9, 0x8F9B, 0xE3F4, 0x8F9C, 0xCDD0, 0x8FA3, 0xD5B8,
+	0x8FA6, 0xF7FD, 0x8FA8, 0xDCA9, 0x8FAD, 0xDEF6, 0x8FAF, 0xDCAA,
+	0x8FB0, 0xF2E3, 0x8FB1, 0xE9B4, 0x8FB2, 0xD2DC, 0x8FC2, 0xE9E6,
+	0x8FC5, 0xE3F6, 0x8FCE, 0xE7CA, 0x8FD1, 0xD0CE, 0x8FD4, 0xDAF7,
+	0x8FE6, 0xCABC, 0x8FEA, 0xEEE8, 0x8FEB, 0xDADE, 0x8FED, 0xF2F7,
+	0x8FF0, 0xE2FB, 0x8FF2, 0xCCA6, 0x8FF7, 0xDABB, 0x8FF9, 0xEEE9,
+	0x8FFD, 0xF5DA, 0x9000, 0xF7DC, 0x9001, 0xE1EA, 0x9002, 0xCEC1,
+	0x9003, 0xD4B1, 0x9005, 0xFDB1, 0x9006, 0xE6BD, 0x9008, 0xFBAD,
+	0x900B, 0xF8E7, 0x900D, 0xE1CE, 0x900F, 0xF7E2, 0x9010, 0xF5EF,
+	0x9011, 0xCFC7, 0x9014, 0xD4B2, 0x9015, 0xCCEF, 0x9017, 0xD4E8,
+	0x9019, 0xEECF, 0x901A, 0xF7D7, 0x901D, 0xE0A6, 0x901E, 0xD6C1,
+	0x901F, 0xE1DC, 0x9020, 0xF0E3, 0x9021, 0xF1E4, 0x9022, 0xDCF1,
+	0x9023, 0xD6A7, 0x902E, 0xF4F5, 0x9031, 0xF1CE, 0x9032, 0xF2E4,
+	0x9035, 0xD0B0, 0x9038, 0xECEF, 0x903C, 0xF9BA, 0x903E, 0xEBB5,
+	0x9041, 0xD4ED, 0x9042, 0xE2C4, 0x9047, 0xE9E7, 0x904A, 0xEBB4,
+	0x904B, 0xEAA1, 0x904D, 0xF8BC, 0x904E, 0xCEA6, 0x9050, 0xF9C6,
+	0x9051, 0xFCDA, 0x9053, 0xD4B3, 0x9054, 0xD3B9, 0x9055, 0xEADE,
+	0x9059, 0xE9AB, 0x905C, 0xE1E1, 0x905D, 0xD3CF, 0x905E, 0xF4F6,
+	0x9060, 0xEAC0, 0x9061, 0xE1CF, 0x9063, 0xCCBA, 0x9069, 0xEEEA,
+	0x906D, 0xF0E4, 0x906E, 0xF3B4, 0x906F, 0xD4EE, 0x9072, 0xF2C0,
+	0x9075, 0xF1E5, 0x9077, 0xF4C3, 0x9078, 0xE0D4, 0x907A, 0xEBB6,
+	0x907C, 0xD7A1, 0x907D, 0xCBE8, 0x907F, 0xF9AD, 0x9080, 0xE9AD,
+	0x9081, 0xD8E4, 0x9082, 0xFAB3, 0x9083, 0xE2C5, 0x9084, 0xFCBD,
+	0x9087, 0xECC4, 0x9088, 0xD8B1, 0x908A, 0xDCAB, 0x908F, 0xD5A4,
+	0x9091, 0xEBE9, 0x9095, 0xE8BB, 0x9099, 0xD8D7, 0x90A2, 0xFBAE,
+	0x90A3, 0xD1E1, 0x90A6, 0xDBC0, 0x90A8, 0xF5BE, 0x90AA, 0xDEF7,
+	0x90AF, 0xCAFB, 0x90B0, 0xF7C6, 0x90B1, 0xCFC8, 0x90B5, 0xE1D0,
+	0x90B8, 0xEED0, 0x90C1, 0xE9F4, 0x90CA, 0xCEF4, 0x90DE, 0xD5CD,
+	0x90E1, 0xCFDB, 0x90E8, 0xDDBB, 0x90ED, 0xCEAC, 0x90F5, 0xE9E8,
+	0x90FD, 0xD4B4, 0x9102, 0xE4C7, 0x9112, 0xF5DB, 0x9115, 0xFAC1,
+	0x9119, 0xDEA9, 0x9127, 0xD4F8, 0x912D, 0xEFF7, 0x9132, 0xD3B3,
+	0x9149, 0xEBB7, 0x914A, 0xEFF8, 0x914B, 0xF5DC, 0x914C, 0xEDCC,
+	0x914D, 0xDBD5, 0x914E, 0xF1CF, 0x9152, 0xF1D0, 0x9162, 0xF5B2,
+	0x9169, 0xD9AE, 0x916A, 0xD5AC, 0x916C, 0xE2C6, 0x9175, 0xFDA3,
+	0x9177, 0xFBE5, 0x9178, 0xDFAB, 0x9187, 0xE2F5, 0x9189, 0xF6AD,
+	0x918B, 0xF5B3, 0x918D, 0xF0B5, 0x9192, 0xE1A5, 0x919C, 0xF5DD,
+	0x91AB, 0xECA2, 0x91AC, 0xEDFD, 0x91AE, 0xF5B4, 0x91AF, 0xFBB8,
+	0x91B1, 0xDBA3, 0x91B4, 0xD6CA, 0x91B5, 0xCBD9, 0x91C0, 0xE5D4,
+	0x91C7, 0xF3FA, 0x91C9, 0xEBB8, 0x91CB, 0xE0B7, 0x91CC, 0xD7EC,
+	0x91CD, 0xF1EC, 0x91CE, 0xE5AF, 0x91CF, 0xD5E1, 0x91D0, 0xD7ED,
+	0x91D1, 0xD1D1, 0x91D7, 0xE1F2, 0x91D8, 0xEFF9, 0x91DC, 0xDDBC,
+	0x91DD, 0xF6DC, 0x91E3, 0xF0E5, 0x91E7, 0xF4C4, 0x91EA, 0xE9E9,
+	0x91F5, 0xF3FB, 0x920D, 0xD4EF, 0x9210, 0xCCA2, 0x9211, 0xF7FE,
+	0x9212, 0xDFBC, 0x9217, 0xEBCD, 0x921E, 0xD0B7, 0x9234, 0xD6C2,
+	0x923A, 0xE8AD, 0x923F, 0xEFAF, 0x9240, 0xCBA5, 0x9245, 0xCBE9,
+	0x9249, 0xFAE8, 0x9257, 0xCCC6, 0x925B, 0xE6E7, 0x925E, 0xEAC7,
+	0x9262, 0xDBA4, 0x9264, 0xCFC9, 0x9265, 0xE2FC, 0x9266, 0xEFFA,
+	0x9280, 0xEBDE, 0x9283, 0xF5C8, 0x9285, 0xD4DE, 0x9291, 0xE0D5,
+	0x9293, 0xEFB0, 0x9296, 0xE2C7, 0x9298, 0xD9AF, 0x929C, 0xF9E7,
+	0x92B3, 0xE7E5, 0x92B6, 0xCFCA, 0x92B7, 0xE1D1, 0x92B9, 0xE2C8,
+	0x92CC, 0xEFFB, 0x92CF, 0xFAF9, 0x92D2, 0xDCF2, 0x92E4, 0xE0A7,
+	0x92EA, 0xF8E8, 0x92F8, 0xCBEA, 0x92FC, 0xCBBC, 0x9304, 0xD6E2,
+	0x9310, 0xF5DE, 0x9318, 0xF5DF, 0x931A, 0xEEB6, 0x931E, 0xE2F6,
+	0x931F, 0xD3CA, 0x9320, 0xEFFC, 0x9321, 0xD1C4, 0x9322, 0xEFB1,
+	0x9324, 0xD1C5, 0x9326, 0xD0DE, 0x9328, 0xD9E1, 0x932B, 0xE0B8,
+	0x932E, 0xCDD1, 0x932F, 0xF3B9, 0x9348, 0xE7CC, 0x934A, 0xD6A8,
+	0x934B, 0xCEA7, 0x934D, 0xD4B5, 0x9354, 0xE4C8, 0x935B, 0xD3B4,
+	0x936E, 0xEBB9, 0x9375, 0xCBF5, 0x937C, 0xF6DD, 0x937E, 0xF1A3,
+	0x938C, 0xCCC7, 0x9394, 0xE9CA, 0x9396, 0xE1F0, 0x939A, 0xF5E0,
+	0x93A3, 0xFBAF, 0x93A7, 0xCBD1, 0x93AC, 0xFBE0, 0x93AD, 0xF2E5,
+	0x93B0, 0xECF0, 0x93C3, 0xF0EC, 0x93D1, 0xEEEB, 0x93DE, 0xE9CB,
+	0x93E1, 0xCCF0, 0x93E4, 0xD7AF, 0x93F6, 0xF3A1, 0x9404, 0xFCF5,
+	0x9418, 0xF1A4, 0x9425, 0xE0D6, 0x942B, 0xEFB2, 0x9435, 0xF4D1,
+	0x9438, 0xF7A1, 0x9444, 0xF1D1, 0x9451, 0xCAFC, 0x9452, 0xCAFD,
+	0x945B, 0xCECE, 0x947D, 0xF3C8, 0x947F, 0xF3BA, 0x9577, 0xEDFE,
+	0x9580, 0xDAA6, 0x9583, 0xE0EC, 0x9589, 0xF8CD, 0x958B, 0xCBD2,
+	0x958F, 0xEBCE, 0x9591, 0xF9D8, 0x9592, 0xF9D9, 0x9593, 0xCAE0,
+	0x9594, 0xDACA, 0x9598, 0xCBA6, 0x95A3, 0xCAC8, 0x95A4, 0xF9EE,
+	0x95A5, 0xDBEC, 0x95A8, 0xD0B1, 0x95AD, 0xD5EF, 0x95B1, 0xE6F3,
+	0x95BB, 0xE7A2, 0x95BC, 0xE4D9, 0x95C7, 0xE4E1, 0x95CA, 0xFCC4,
+	0x95D4, 0xF9EF, 0x95D5, 0xCFF4, 0x95D6, 0xF7E6, 0x95DC, 0xCEBC,
+	0x95E1, 0xF4C5, 0x95E2, 0xDCA3, 0x961C, 0xDDBD, 0x9621, 0xF4C6,
+	0x962A, 0xF8A1, 0x962E, 0xE8D6, 0x9632, 0xDBC1, 0x963B, 0xF0E6,
+	0x963F, 0xE4B9, 0x9640, 0xF6ED, 0x9642, 0xF9AE, 0x9644, 0xDDBE,
+	0x964B, 0xD7B0, 0x964C, 0xD8E8, 0x964D, 0xCBBD, 0x9650, 0xF9DA,
+	0x965B, 0xF8CE, 0x965C, 0xF9F0, 0x965D, 0xE0ED, 0x965E, 0xE3B3,
+	0x965F, 0xF4B3, 0x9662, 0xEAC2, 0x9663, 0xF2E6, 0x9664, 0xF0B6,
+	0x966A, 0xDBD6, 0x9670, 0xEBE4, 0x9673, 0xF2E7, 0x9675, 0xD7D5,
+	0x9676, 0xD4B6, 0x9677, 0xF9E8, 0x9678, 0xD7C1, 0x967D, 0xE5D5,
+	0x9685, 0xE9EA, 0x9686, 0xD7CC, 0x968A, 0xD3E9, 0x968B, 0xE2C9,
+	0x968D, 0xFCDB, 0x968E, 0xCDAD, 0x9694, 0xCCB0, 0x9695, 0xEAA2,
+	0x9698, 0xE4F6, 0x9699, 0xD0C0, 0x969B, 0xF0B7, 0x969C, 0xEEA1,
+	0x96A3, 0xD7F6, 0x96A7, 0xE2CA, 0x96A8, 0xE2CB, 0x96AA, 0xFACF,
+	0x96B1, 0xEBDF, 0x96B7, 0xD6CB, 0x96BB, 0xF4B4, 0x96C0, 0xEDCD,
+	0x96C1, 0xE4D2, 0x96C4, 0xEAA9, 0x96C5, 0xE4BA, 0x96C6, 0xF3A2,
+	0x96C7, 0xCDD2, 0x96C9, 0xF6CB, 0x96CB, 0xF1E6, 0x96CC, 0xEDC1,
+	0x96CD, 0xE8BC, 0x96CE, 0xEED1, 0x96D5, 0xF0E7, 0x96D6, 0xE2CC,
+	0x96D9, 0xE4AA, 0x96DB, 0xF5E1, 0x96DC, 0xEDDA, 0x96E2, 0xD7EE,
+	0x96E3, 0xD1F1, 0x96E8, 0xE9EB, 0x96E9, 0xE9EC, 0x96EA, 0xE0E4,
+	0x96EF, 0xDAA7, 0x96F0, 0xDDD4, 0x96F2, 0xEAA3, 0x96F6, 0xD6C3,
+	0x96F7, 0xD6F4, 0x96F9, 0xDADF, 0x96FB, 0xEFB3, 0x9700, 0xE2CD,
+	0x9706, 0xEFFD, 0x9707, 0xF2E8, 0x9711, 0xEFC5, 0x9713, 0xE7E7,
+	0x9716, 0xD7FD, 0x9719, 0xE7CE, 0x971C, 0xDFDC, 0x971E, 0xF9C7,
+	0x9727, 0xD9F6, 0x9730, 0xDFAC, 0x9732, 0xD6DA, 0x9739, 0xDCA4,
+	0x973D, 0xF0B8, 0x9742, 0xD5FA, 0x9744, 0xE4F7, 0x9748, 0xD6C4,
+	0x9751, 0xF4EC, 0x9756, 0xEFFE, 0x975C, 0xF0A1, 0x975E, 0xDEAA,
+	0x9761, 0xDABC, 0x9762, 0xD8FC, 0x9769, 0xFAD4, 0x976D, 0xECE5,
+	0x9774, 0xFCA8, 0x9777, 0xECE6, 0x977A, 0xD8CB, 0x978B, 0xFBB9,
+	0x978D, 0xE4D3, 0x978F, 0xCDF9, 0x97A0, 0xCFD3, 0x97A8, 0xCAEA,
+	0x97AB, 0xCFD4, 0x97AD, 0xF8BD, 0x97C6, 0xF4C7, 0x97CB, 0xEADF,
+	0x97D3, 0xF9DB, 0x97DC, 0xD4B7, 0x97F3, 0xEBE5, 0x97F6, 0xE1D2,
+	0x97FB, 0xEAA4, 0x97FF, 0xFAC2, 0x9800, 0xFBE1, 0x9801, 0xFAED,
+	0x9802, 0xF0A2, 0x9803, 0xCCF1, 0x9805, 0xFAA3, 0x9806, 0xE2F7,
+	0x9808, 0xE2CE, 0x980A, 0xE9F5, 0x980C, 0xE1EB, 0x9810, 0xE7E8,
+	0x9811, 0xE8D7, 0x9812, 0xDAF8, 0x9813, 0xD4CB, 0x9817, 0xF7F6,
+	0x9818, 0xD6C5, 0x982D, 0xD4E9, 0x9830, 0xFAFA, 0x9838, 0xCCF2,
+	0x9839, 0xF7DD, 0x983B, 0xDEBA, 0x9846, 0xCEA8, 0x984C, 0xF0B9,
+	0x984D, 0xE4FE, 0x984E, 0xE4C9, 0x9854, 0xE4D4, 0x9858, 0xEAC3,
+	0x985A, 0xEFB4, 0x985E, 0xD7BE, 0x9865, 0xFBE2, 0x9867, 0xCDD3,
+	0x986B, 0xEFB5, 0x986F, 0xFAE9, 0x98A8, 0xF9A6, 0x98AF, 0xDFBD,
+	0x98B1, 0xF7C7, 0x98C4, 0xF8FD, 0x98C7, 0xF8FC, 0x98DB, 0xDEAB,
+	0x98DC, 0xDBE8, 0x98DF, 0xE3DD, 0x98E1, 0xE1E2, 0x98E2, 0xD1C6,
+	0x98ED, 0xF6D0, 0x98EE, 0xEBE6, 0x98EF, 0xDAF9, 0x98F4, 0xECC7,
+	0x98FC, 0xDEF8, 0x98FD, 0xF8E9, 0x98FE, 0xE3DE, 0x9903, 0xCEF5,
+	0x9909, 0xFAC3, 0x990A, 0xE5D7, 0x990C, 0xECC8, 0x9910, 0xF3C9,
+	0x9913, 0xE4BB, 0x9918, 0xE6AE, 0x991E, 0xEFB6, 0x9920, 0xDCBF,
+	0x9928, 0xCEBD, 0x9945, 0xD8C3, 0x9949, 0xD0CF, 0x994B, 0xCFFA,
+	0x994C, 0xF3CA, 0x994D, 0xE0D7, 0x9951, 0xD1C7, 0x9952, 0xE9AE,
+	0x9954, 0xE8BD, 0x9957, 0xFAC4, 0x9996, 0xE2CF, 0x9999, 0xFAC5,
+	0x999D, 0xF9B8, 0x99A5, 0xDCE0, 0x99A8, 0xFBB0, 0x99AC, 0xD8A9,
+	0x99AD, 0xE5DF, 0x99AE, 0xF9A7, 0x99B1, 0xF6EE, 0x99B3, 0xF6CC,
+	0x99B4, 0xE2F8, 0x99B9, 0xECF1, 0x99C1, 0xDAE0, 0x99D0, 0xF1D2,
+	0x99D1, 0xD2CC, 0x99D2, 0xCFCB, 0x99D5, 0xCABD, 0x99D9, 0xDDBF,
+	0x99DD, 0xF6EF, 0x99DF, 0xDEF9, 0x99ED, 0xFAB4, 0x99F1, 0xD5AD,
+	0x99FF, 0xF1E7, 0x9A01, 0xDEBE, 0x9A08, 0xDCC0, 0x9A0E, 0xD1C8,
+	0x9A0F, 0xD1C9, 0x9A19, 0xF8BE, 0x9A2B, 0xCBF6, 0x9A30, 0xD4F9,
+	0x9A36, 0xF5E2, 0x9A37, 0xE1D3, 0x9A40, 0xD8E9, 0x9A43, 0xF8FE,
+	0x9A45, 0xCFCC, 0x9A4D, 0xFDA4, 0x9A55, 0xCEF6, 0x9A57, 0xFAD0,
+	0x9A5A, 0xCCF3, 0x9A5B, 0xE6BE, 0x9A5F, 0xF6AE, 0x9A62, 0xD5F0,
+	0x9A65, 0xD1CA, 0x9A69, 0xFCBE, 0x9A6A, 0xD5F1, 0x9AA8, 0xCDE9,
+	0x9AB8, 0xFAB5, 0x9AD3, 0xE2D0, 0x9AD4, 0xF4F7, 0x9AD8, 0xCDD4,
+	0x9AE5, 0xE7A3, 0x9AEE, 0xDBA5, 0x9B1A, 0xE2D1, 0x9B27, 0xD7A2,
+	0x9B2A, 0xF7E3, 0x9B31, 0xEAA6, 0x9B3C, 0xD0A1, 0x9B41, 0xCEDA,
+	0x9B42, 0xFBEB, 0x9B43, 0xDBA6, 0x9B44, 0xDBDE, 0x9B45, 0xD8E5,
+	0x9B4F, 0xEAE0, 0x9B54, 0xD8AA, 0x9B5A, 0xE5E0, 0x9B6F, 0xD6DB,
+	0x9B8E, 0xEFC6, 0x9B91, 0xF8EA, 0x9B9F, 0xE4D5, 0x9BAB, 0xCEF7,
+	0x9BAE, 0xE0D8, 0x9BC9, 0xD7EF, 0x9BD6, 0xF4ED, 0x9BE4, 0xCDE6,
+	0x9BE8, 0xCCF4, 0x9C0D, 0xF5E3, 0x9C10, 0xE4CA, 0x9C12, 0xDCE1,
+	0x9C15, 0xF9C8, 0x9C25, 0xFCBF, 0x9C32, 0xE8A7, 0x9C3B, 0xD8C4,
+	0x9C47, 0xCBBE, 0x9C49, 0xDCAE, 0x9C57, 0xD7F7, 0x9CE5, 0xF0E8,
+	0x9CE7, 0xDDC0, 0x9CE9, 0xCFCD, 0x9CF3, 0xDCF3, 0x9CF4, 0xD9B0,
+	0x9CF6, 0xE6E9, 0x9D09, 0xE4BC, 0x9D1B, 0xEAC4, 0x9D26, 0xE4EC,
+	0x9D28, 0xE4E5, 0x9D3B, 0xFBF8, 0x9D51, 0xCCBB, 0x9D5D, 0xE4BD,
+	0x9D60, 0xCDDC, 0x9D61, 0xD9F7, 0x9D6C, 0xDDDF, 0x9D72, 0xEDCE,
+	0x9DA9, 0xD9D0, 0x9DAF, 0xE5A3, 0x9DB4, 0xF9CD, 0x9DC4, 0xCDAE,
+	0x9DD7, 0xCFCE, 0x9DF2, 0xF6AF, 0x9DF8, 0xFDD3, 0x9DF9, 0xEBED,
+	0x9DFA, 0xD6DC, 0x9E1A, 0xE5A4, 0x9E1E, 0xD5B6, 0x9E75, 0xD6DD,
+	0x9E79, 0xF9E9, 0x9E7D, 0xE7A4, 0x9E7F, 0xD6E3, 0x9E92, 0xD1CB,
+	0x9E93, 0xD6E4, 0x9E97, 0xD5F2, 0x9E9D, 0xDEFA, 0x9E9F, 0xD7F8,
+	0x9EA5, 0xD8EA, 0x9EB4, 0xCFD5, 0x9EB5, 0xD8FD, 0x9EBB, 0xD8AB,
+	0x9EBE, 0xFDCB, 0x9EC3, 0xFCDC, 0x9ECD, 0xE0A8, 0x9ECE, 0xD5F3,
+	0x9ED1, 0xFDD9, 0x9ED4, 0xCCA3, 0x9ED8, 0xD9F9, 0x9EDB, 0xD3EA,
+	0x9EDC, 0xF5F5, 0x9EDE, 0xEFC7, 0x9EE8, 0xD3DA, 0x9EF4, 0xDABD,
+	0x9F07, 0xE8A8, 0x9F08, 0xDCAF, 0x9F0E, 0xF0A3, 0x9F13, 0xCDD5,
+	0x9F20, 0xE0A9, 0x9F3B, 0xDEAC, 0x9F4A, 0xF0BA, 0x9F4B, 0xEEB1,
+	0x9F4E, 0xEEB2, 0x9F52, 0xF6CD, 0x9F5F, 0xEED2, 0x9F61, 0xD6C6,
+	0x9F67, 0xE0E5, 0x9F6A, 0xF3BB, 0x9F6C, 0xE5E1, 0x9F77, 0xE4CB,
+	0x9F8D, 0xD7A3, 0x9F90, 0xDBC2, 0x9F95, 0xCAFE, 0x9F9C, 0xCFCF,
+	0xAC00, 0xB0A1, 0xAC01, 0xB0A2, 0xAC02, 0x8141, 0xAC03, 0x8142,
+	0xAC04, 0xB0A3, 0xAC05, 0x8143, 0xAC06, 0x8144, 0xAC07, 0xB0A4,
+	0xAC08, 0xB0A5, 0xAC09, 0xB0A6, 0xAC0A, 0xB0A7, 0xAC0B, 0x8145,
+	0xAC0C, 0x8146, 0xAC0D, 0x8147, 0xAC0E, 0x8148, 0xAC0F, 0x8149,
+	0xAC10, 0xB0A8, 0xAC11, 0xB0A9, 0xAC12, 0xB0AA, 0xAC13, 0xB0AB,
+	0xAC14, 0xB0AC, 0xAC15, 0xB0AD, 0xAC16, 0xB0AE, 0xAC17, 0xB0AF,
+	0xAC18, 0x814A, 0xAC19, 0xB0B0, 0xAC1A, 0xB0B1, 0xAC1B, 0xB0B2,
+	0xAC1C, 0xB0B3, 0xAC1D, 0xB0B4, 0xAC1E, 0x814B, 0xAC1F, 0x814C,
+	0xAC20, 0xB0B5, 0xAC21, 0x814D, 0xAC22, 0x814E, 0xAC23, 0x814F,
+	0xAC24, 0xB0B6, 0xAC25, 0x8150, 0xAC26, 0x8151, 0xAC27, 0x8152,
+	0xAC28, 0x8153, 0xAC29, 0x8154, 0xAC2A, 0x8155, 0xAC2B, 0x8156,
+	0xAC2C, 0xB0B7, 0xAC2D, 0xB0B8, 0xAC2E, 0x8157, 0xAC2F, 0xB0B9,
+	0xAC30, 0xB0BA, 0xAC31, 0xB0BB, 0xAC32, 0x8158, 0xAC33, 0x8159,
+	0xAC34, 0x815A, 0xAC35, 0x8161, 0xAC36, 0x8162, 0xAC37, 0x8163,
+	0xAC38, 0xB0BC, 0xAC39, 0xB0BD, 0xAC3A, 0x8164, 0xAC3B, 0x8165,
+	0xAC3C, 0xB0BE, 0xAC3D, 0x8166, 0xAC3E, 0x8167, 0xAC3F, 0x8168,
+	0xAC40, 0xB0BF, 0xAC41, 0x8169, 0xAC42, 0x816A, 0xAC43, 0x816B,
+	0xAC44, 0x816C, 0xAC45, 0x816D, 0xAC46, 0x816E, 0xAC47, 0x816F,
+	0xAC48, 0x8170, 0xAC49, 0x8171, 0xAC4A, 0x8172, 0xAC4B, 0xB0C0,
+	0xAC4C, 0x8173, 0xAC4D, 0xB0C1, 0xAC4E, 0x8174, 0xAC4F, 0x8175,
+	0xAC50, 0x8176, 0xAC51, 0x8177, 0xAC52, 0x8178, 0xAC53, 0x8179,
+	0xAC54, 0xB0C2, 0xAC55, 0x817A, 0xAC56, 0x8181, 0xAC57, 0x8182,
+	0xAC58, 0xB0C3, 0xAC59, 0x8183, 0xAC5A, 0x8184, 0xAC5B, 0x8185,
+	0xAC5C, 0xB0C4, 0xAC5D, 0x8186, 0xAC5E, 0x8187, 0xAC5F, 0x8188,
+	0xAC60, 0x8189, 0xAC61, 0x818A, 0xAC62, 0x818B, 0xAC63, 0x818C,
+	0xAC64, 0x818D, 0xAC65, 0x818E, 0xAC66, 0x818F, 0xAC67, 0x8190,
+	0xAC68, 0x8191, 0xAC69, 0x8192, 0xAC6A, 0x8193, 0xAC6B, 0x8194,
+	0xAC6C, 0x8195, 0xAC6D, 0x8196, 0xAC6E, 0x8197, 0xAC6F, 0x8198,
+	0xAC70, 0xB0C5, 0xAC71, 0xB0C6, 0xAC72, 0x8199, 0xAC73, 0x819A,
+	0xAC74, 0xB0C7, 0xAC75, 0x819B, 0xAC76, 0x819C, 0xAC77, 0xB0C8,
+	0xAC78, 0xB0C9, 0xAC79, 0x819D, 0xAC7A, 0xB0CA, 0xAC7B, 0x819E,
+	0xAC7C, 0x819F, 0xAC7D, 0x81A0, 0xAC7E, 0x81A1, 0xAC7F, 0x81A2,
+	0xAC80, 0xB0CB, 0xAC81, 0xB0CC, 0xAC82, 0x81A3, 0xAC83, 0xB0CD,
+	0xAC84, 0xB0CE, 0xAC85, 0xB0CF, 0xAC86, 0xB0D0, 0xAC87, 0x81A4,
+	0xAC88, 0x81A5, 0xAC89, 0xB0D1, 0xAC8A, 0xB0D2, 0xAC8B, 0xB0D3,
+	0xAC8C, 0xB0D4, 0xAC8D, 0x81A6, 0xAC8E, 0x81A7, 0xAC8F, 0x81A8,
+	0xAC90, 0xB0D5, 0xAC91, 0x81A9, 0xAC92, 0x81AA, 0xAC93, 0x81AB,
+	0xAC94, 0xB0D6, 0xAC95, 0x81AC, 0xAC96, 0x81AD, 0xAC97, 0x81AE,
+	0xAC98, 0x81AF, 0xAC99, 0x81B0, 0xAC9A, 0x81B1, 0xAC9B, 0x81B2,
+	0xAC9C, 0xB0D7, 0xAC9D, 0xB0D8, 0xAC9E, 0x81B3, 0xAC9F, 0xB0D9,
+	0xACA0, 0xB0DA, 0xACA1, 0xB0DB, 0xACA2, 0x81B4, 0xACA3, 0x81B5,
+	0xACA4, 0x81B6, 0xACA5, 0x81B7, 0xACA6, 0x81B8, 0xACA7, 0x81B9,
+	0xACA8, 0xB0DC, 0xACA9, 0xB0DD, 0xACAA, 0xB0DE, 0xACAB, 0x81BA,
+	0xACAC, 0xB0DF, 0xACAD, 0x81BB, 0xACAE, 0x81BC, 0xACAF, 0xB0E0,
+	0xACB0, 0xB0E1, 0xACB1, 0x81BD, 0xACB2, 0x81BE, 0xACB3, 0x81BF,
+	0xACB4, 0x81C0, 0xACB5, 0x81C1, 0xACB6, 0x81C2, 0xACB7, 0x81C3,
+	0xACB8, 0xB0E2, 0xACB9, 0xB0E3, 0xACBA, 0x81C4, 0xACBB, 0xB0E4,
+	0xACBC, 0xB0E5, 0xACBD, 0xB0E6, 0xACBE, 0x81C5, 0xACBF, 0x81C6,
+	0xACC0, 0x81C7, 0xACC1, 0xB0E7, 0xACC2, 0x81C8, 0xACC3, 0x81C9,
+	0xACC4, 0xB0E8, 0xACC5, 0x81CA, 0xACC6, 0x81CB, 0xACC7, 0x81CC,
+	0xACC8, 0xB0E9, 0xACC9, 0x81CD, 0xACCA, 0x81CE, 0xACCB, 0x81CF,
+	0xACCC, 0xB0EA, 0xACCD, 0x81D0, 0xACCE, 0x81D1, 0xACCF, 0x81D2,
+	0xACD0, 0x81D3, 0xACD1, 0x81D4, 0xACD2, 0x81D5, 0xACD3, 0x81D6,
+	0xACD4, 0x81D7, 0xACD5, 0xB0EB, 0xACD6, 0x81D8, 0xACD7, 0xB0EC,
+	0xACD8, 0x81D9, 0xACD9, 0x81DA, 0xACDA, 0x81DB, 0xACDB, 0x81DC,
+	0xACDC, 0x81DD, 0xACDD, 0x81DE, 0xACDE, 0x81DF, 0xACDF, 0x81E0,
+	0xACE0, 0xB0ED, 0xACE1, 0xB0EE, 0xACE2, 0x81E1, 0xACE3, 0x81E2,
+	0xACE4, 0xB0EF, 0xACE5, 0x81E3, 0xACE6, 0x81E4, 0xACE7, 0xB0F0,
+	0xACE8, 0xB0F1, 0xACE9, 0x81E5, 0xACEA, 0xB0F2, 0xACEB, 0x81E6,
+	0xACEC, 0xB0F3, 0xACED, 0x81E7, 0xACEE, 0x81E8, 0xACEF, 0xB0F4,
+	0xACF0, 0xB0F5, 0xACF1, 0xB0F6, 0xACF2, 0x81E9, 0xACF3, 0xB0F7,
+	0xACF4, 0x81EA, 0xACF5, 0xB0F8, 0xACF6, 0xB0F9, 0xACF7, 0x81EB,
+	0xACF8, 0x81EC, 0xACF9, 0x81ED, 0xACFA, 0x81EE, 0xACFB, 0x81EF,
+	0xACFC, 0xB0FA, 0xACFD, 0xB0FB, 0xACFE, 0x81F0, 0xACFF, 0x81F1,
+	0xAD00, 0xB0FC, 0xAD01, 0x81F2, 0xAD02, 0x81F3, 0xAD03, 0x81F4,
+	0xAD04, 0xB0FD, 0xAD05, 0x81F5, 0xAD06, 0xB0FE, 0xAD07, 0x81F6,
+	0xAD08, 0x81F7, 0xAD09, 0x81F8, 0xAD0A, 0x81F9, 0xAD0B, 0x81FA,
+	0xAD0C, 0xB1A1, 0xAD0D, 0xB1A2, 0xAD0E, 0x81FB, 0xAD0F, 0xB1A3,
+	0xAD10, 0x81FC, 0xAD11, 0xB1A4, 0xAD12, 0x81FD, 0xAD13, 0x81FE,
+	0xAD14, 0x8241, 0xAD15, 0x8242, 0xAD16, 0x8243, 0xAD17, 0x8244,
+	0xAD18, 0xB1A5, 0xAD19, 0x8245, 0xAD1A, 0x8246, 0xAD1B, 0x8247,
+	0xAD1C, 0xB1A6, 0xAD1D, 0x8248, 0xAD1E, 0x8249, 0xAD1F, 0x824A,
+	0xAD20, 0xB1A7, 0xAD21, 0x824B, 0xAD22, 0x824C, 0xAD23, 0x824D,
+	0xAD24, 0x824E, 0xAD25, 0x824F, 0xAD26, 0x8250, 0xAD27, 0x8251,
+	0xAD28, 0x8252, 0xAD29, 0xB1A8, 0xAD2A, 0x8253, 0xAD2B, 0x8254,
+	0xAD2C, 0xB1A9, 0xAD2D, 0xB1AA, 0xAD2E, 0x8255, 0xAD2F, 0x8256,
+	0xAD30, 0x8257, 0xAD31, 0x8258, 0xAD32, 0x8259, 0xAD33, 0x825A,
+	0xAD34, 0xB1AB, 0xAD35, 0xB1AC, 0xAD36, 0x8261, 0xAD37, 0x8262,
+	0xAD38, 0xB1AD, 0xAD39, 0x8263, 0xAD3A, 0x8264, 0xAD3B, 0x8265,
+	0xAD3C, 0xB1AE, 0xAD3D, 0x8266, 0xAD3E, 0x8267, 0xAD3F, 0x8268,
+	0xAD40, 0x8269, 0xAD41, 0x826A, 0xAD42, 0x826B, 0xAD43, 0x826C,
+	0xAD44, 0xB1AF, 0xAD45, 0xB1B0, 0xAD46, 0x826D, 0xAD47, 0xB1B1,
+	0xAD48, 0x826E, 0xAD49, 0xB1B2, 0xAD4A, 0x826F, 0xAD4B, 0x8270,
+	0xAD4C, 0x8271, 0xAD4D, 0x8272, 0xAD4E, 0x8273, 0xAD4F, 0x8274,
+	0xAD50, 0xB1B3, 0xAD51, 0x8275, 0xAD52, 0x8276, 0xAD53, 0x8277,
+	0xAD54, 0xB1B4, 0xAD55, 0x8278, 0xAD56, 0x8279, 0xAD57, 0x827A,
+	0xAD58, 0xB1B5, 0xAD59, 0x8281, 0xAD5A, 0x8282, 0xAD5B, 0x8283,
+	0xAD5C, 0x8284, 0xAD5D, 0x8285, 0xAD5E, 0x8286, 0xAD5F, 0x8287,
+	0xAD60, 0x8288, 0xAD61, 0xB1B6, 0xAD62, 0x8289, 0xAD63, 0xB1B7,
+	0xAD64, 0x828A, 0xAD65, 0x828B, 0xAD66, 0x828C, 0xAD67, 0x828D,
+	0xAD68, 0x828E, 0xAD69, 0x828F, 0xAD6A, 0x8290, 0xAD6B, 0x8291,
+	0xAD6C, 0xB1B8, 0xAD6D, 0xB1B9, 0xAD6E, 0x8292, 0xAD6F, 0x8293,
+	0xAD70, 0xB1BA, 0xAD71, 0x8294, 0xAD72, 0x8295, 0xAD73, 0xB1BB,
+	0xAD74, 0xB1BC, 0xAD75, 0xB1BD, 0xAD76, 0xB1BE, 0xAD77, 0x8296,
+	0xAD78, 0x8297, 0xAD79, 0x8298, 0xAD7A, 0x8299, 0xAD7B, 0xB1BF,
+	0xAD7C, 0xB1C0, 0xAD7D, 0xB1C1, 0xAD7E, 0x829A, 0xAD7F, 0xB1C2,
+	0xAD80, 0x829B, 0xAD81, 0xB1C3, 0xAD82, 0xB1C4, 0xAD83, 0x829C,
+	0xAD84, 0x829D, 0xAD85, 0x829E, 0xAD86, 0x829F, 0xAD87, 0x82A0,
+	0xAD88, 0xB1C5, 0xAD89, 0xB1C6, 0xAD8A, 0x82A1, 0xAD8B, 0x82A2,
+	0xAD8C, 0xB1C7, 0xAD8D, 0x82A3, 0xAD8E, 0x82A4, 0xAD8F, 0x82A5,
+	0xAD90, 0xB1C8, 0xAD91, 0x82A6, 0xAD92, 0x82A7, 0xAD93, 0x82A8,
+	0xAD94, 0x82A9, 0xAD95, 0x82AA, 0xAD96, 0x82AB, 0xAD97, 0x82AC,
+	0xAD98, 0x82AD, 0xAD99, 0x82AE, 0xAD9A, 0x82AF, 0xAD9B, 0x82B0,
+	0xAD9C, 0xB1C9, 0xAD9D, 0xB1CA, 0xAD9E, 0x82B1, 0xAD9F, 0x82B2,
+	0xADA0, 0x82B3, 0xADA1, 0x82B4, 0xADA2, 0x82B5, 0xADA3, 0x82B6,
+	0xADA4, 0xB1CB, 0xADA5, 0x82B7, 0xADA6, 0x82B8, 0xADA7, 0x82B9,
+	0xADA8, 0x82BA, 0xADA9, 0x82BB, 0xADAA, 0x82BC, 0xADAB, 0x82BD,
+	0xADAC, 0x82BE, 0xADAD, 0x82BF, 0xADAE, 0x82C0, 0xADAF, 0x82C1,
+	0xADB0, 0x82C2, 0xADB1, 0x82C3, 0xADB2, 0x82C4, 0xADB3, 0x82C5,
+	0xADB4, 0x82C6, 0xADB5, 0x82C7, 0xADB6, 0x82C8, 0xADB7, 0xB1CC,
+	0xADB8, 0x82C9, 0xADB9, 0x82CA, 0xADBA, 0x82CB, 0xADBB, 0x82CC,
+	0xADBC, 0x82CD, 0xADBD, 0x82CE, 0xADBE, 0x82CF, 0xADBF, 0x82D0,
+	0xADC0, 0xB1CD, 0xADC1, 0xB1CE, 0xADC2, 0x82D1, 0xADC3, 0x82D2,
+	0xADC4, 0xB1CF, 0xADC5, 0x82D3, 0xADC6, 0x82D4, 0xADC7, 0x82D5,
+	0xADC8, 0xB1D0, 0xADC9, 0x82D6, 0xADCA, 0x82D7, 0xADCB, 0x82D8,
+	0xADCC, 0x82D9, 0xADCD, 0x82DA, 0xADCE, 0x82DB, 0xADCF, 0x82DC,
+	0xADD0, 0xB1D1, 0xADD1, 0xB1D2, 0xADD2, 0x82DD, 0xADD3, 0xB1D3,
+	0xADD4, 0x82DE, 0xADD5, 0x82DF, 0xADD6, 0x82E0, 0xADD7, 0x82E1,
+	0xADD8, 0x82E2, 0xADD9, 0x82E3, 0xADDA, 0x82E4, 0xADDB, 0x82E5,
+	0xADDC, 0xB1D4, 0xADDD, 0x82E6, 0xADDE, 0x82E7, 0xADDF, 0x82E8,
+	0xADE0, 0xB1D5, 0xADE1, 0x82E9, 0xADE2, 0x82EA, 0xADE3, 0x82EB,
+	0xADE4, 0xB1D6, 0xADE5, 0x82EC, 0xADE6, 0x82ED, 0xADE7, 0x82EE,
+	0xADE8, 0x82EF, 0xADE9, 0x82F0, 0xADEA, 0x82F1, 0xADEB, 0x82F2,
+	0xADEC, 0x82F3, 0xADED, 0x82F4, 0xADEE, 0x82F5, 0xADEF, 0x82F6,
+	0xADF0, 0x82F7, 0xADF1, 0x82F8, 0xADF2, 0x82F9, 0xADF3, 0x82FA,
+	0xADF4, 0x82FB, 0xADF5, 0x82FC, 0xADF6, 0x82FD, 0xADF7, 0x82FE,
+	0xADF8, 0xB1D7, 0xADF9, 0xB1D8, 0xADFA, 0x8341, 0xADFB, 0x8342,
+	0xADFC, 0xB1D9, 0xADFD, 0x8343, 0xADFE, 0x8344, 0xADFF, 0xB1DA,
+	0xAE00, 0xB1DB, 0xAE01, 0xB1DC, 0xAE02, 0x8345, 0xAE03, 0x8346,
+	0xAE04, 0x8347, 0xAE05, 0x8348, 0xAE06, 0x8349, 0xAE07, 0x834A,
+	0xAE08, 0xB1DD, 0xAE09, 0xB1DE, 0xAE0A, 0x834B, 0xAE0B, 0xB1DF,
+	0xAE0C, 0x834C, 0xAE0D, 0xB1E0, 0xAE0E, 0x834D, 0xAE0F, 0x834E,
+	0xAE10, 0x834F, 0xAE11, 0x8350, 0xAE12, 0x8351, 0xAE13, 0x8352,
+	0xAE14, 0xB1E1, 0xAE15, 0x8353, 0xAE16, 0x8354, 0xAE17, 0x8355,
+	0xAE18, 0x8356, 0xAE19, 0x8357, 0xAE1A, 0x8358, 0xAE1B, 0x8359,
+	0xAE1C, 0x835A, 0xAE1D, 0x8361, 0xAE1E, 0x8362, 0xAE1F, 0x8363,
+	0xAE20, 0x8364, 0xAE21, 0x8365, 0xAE22, 0x8366, 0xAE23, 0x8367,
+	0xAE24, 0x8368, 0xAE25, 0x8369, 0xAE26, 0x836A, 0xAE27, 0x836B,
+	0xAE28, 0x836C, 0xAE29, 0x836D, 0xAE2A, 0x836E, 0xAE2B, 0x836F,
+	0xAE2C, 0x8370, 0xAE2D, 0x8371, 0xAE2E, 0x8372, 0xAE2F, 0x8373,
+	0xAE30, 0xB1E2, 0xAE31, 0xB1E3, 0xAE32, 0x8374, 0xAE33, 0x8375,
+	0xAE34, 0xB1E4, 0xAE35, 0x8376, 0xAE36, 0x8377, 0xAE37, 0xB1E5,
+	0xAE38, 0xB1E6, 0xAE39, 0x8378, 0xAE3A, 0xB1E7, 0xAE3B, 0x8379,
+	0xAE3C, 0x837A, 0xAE3D, 0x8381, 0xAE3E, 0x8382, 0xAE3F, 0x8383,
+	0xAE40, 0xB1E8, 0xAE41, 0xB1E9, 0xAE42, 0x8384, 0xAE43, 0xB1EA,
+	0xAE44, 0x8385, 0xAE45, 0xB1EB, 0xAE46, 0xB1EC, 0xAE47, 0x8386,
+	0xAE48, 0x8387, 0xAE49, 0x8388, 0xAE4A, 0xB1ED, 0xAE4B, 0x8389,
+	0xAE4C, 0xB1EE, 0xAE4D, 0xB1EF, 0xAE4E, 0xB1F0, 0xAE4F, 0x838A,
+	0xAE50, 0xB1F1, 0xAE51, 0x838B, 0xAE52, 0x838C, 0xAE53, 0x838D,
+	0xAE54, 0xB1F2, 0xAE55, 0x838E, 0xAE56, 0xB1F3, 0xAE57, 0x838F,
+	0xAE58, 0x8390, 0xAE59, 0x8391, 0xAE5A, 0x8392, 0xAE5B, 0x8393,
+	0xAE5C, 0xB1F4, 0xAE5D, 0xB1F5, 0xAE5E, 0x8394, 0xAE5F, 0xB1F6,
+	0xAE60, 0xB1F7, 0xAE61, 0xB1F8, 0xAE62, 0x8395, 0xAE63, 0x8396,
+	0xAE64, 0x8397, 0xAE65, 0xB1F9, 0xAE66, 0x8398, 0xAE67, 0x8399,
+	0xAE68, 0xB1FA, 0xAE69, 0xB1FB, 0xAE6A, 0x839A, 0xAE6B, 0x839B,
+	0xAE6C, 0xB1FC, 0xAE6D, 0x839C, 0xAE6E, 0x839D, 0xAE6F, 0x839E,
+	0xAE70, 0xB1FD, 0xAE71, 0x839F, 0xAE72, 0x83A0, 0xAE73, 0x83A1,
+	0xAE74, 0x83A2, 0xAE75, 0x83A3, 0xAE76, 0x83A4, 0xAE77, 0x83A5,
+	0xAE78, 0xB1FE, 0xAE79, 0xB2A1, 0xAE7A, 0x83A6, 0xAE7B, 0xB2A2,
+	0xAE7C, 0xB2A3, 0xAE7D, 0xB2A4, 0xAE7E, 0x83A7, 0xAE7F, 0x83A8,
+	0xAE80, 0x83A9, 0xAE81, 0x83AA, 0xAE82, 0x83AB, 0xAE83, 0x83AC,
+	0xAE84, 0xB2A5, 0xAE85, 0xB2A6, 0xAE86, 0x83AD, 0xAE87, 0x83AE,
+	0xAE88, 0x83AF, 0xAE89, 0x83B0, 0xAE8A, 0x83B1, 0xAE8B, 0x83B2,
+	0xAE8C, 0xB2A7, 0xAE8D, 0x83B3, 0xAE8E, 0x83B4, 0xAE8F, 0x83B5,
+	0xAE90, 0x83B6, 0xAE91, 0x83B7, 0xAE92, 0x83B8, 0xAE93, 0x83B9,
+	0xAE94, 0x83BA, 0xAE95, 0x83BB, 0xAE96, 0x83BC, 0xAE97, 0x83BD,
+	0xAE98, 0x83BE, 0xAE99, 0x83BF, 0xAE9A, 0x83C0, 0xAE9B, 0x83C1,
+	0xAE9C, 0x83C2, 0xAE9D, 0x83C3, 0xAE9E, 0x83C4, 0xAE9F, 0x83C5,
+	0xAEA0, 0x83C6, 0xAEA1, 0x83C7, 0xAEA2, 0x83C8, 0xAEA3, 0x83C9,
+	0xAEA4, 0x83CA, 0xAEA5, 0x83CB, 0xAEA6, 0x83CC, 0xAEA7, 0x83CD,
+	0xAEA8, 0x83CE, 0xAEA9, 0x83CF, 0xAEAA, 0x83D0, 0xAEAB, 0x83D1,
+	0xAEAC, 0x83D2, 0xAEAD, 0x83D3, 0xAEAE, 0x83D4, 0xAEAF, 0x83D5,
+	0xAEB0, 0x83D6, 0xAEB1, 0x83D7, 0xAEB2, 0x83D8, 0xAEB3, 0x83D9,
+	0xAEB4, 0x83DA, 0xAEB5, 0x83DB, 0xAEB6, 0x83DC, 0xAEB7, 0x83DD,
+	0xAEB8, 0x83DE, 0xAEB9, 0x83DF, 0xAEBA, 0x83E0, 0xAEBB, 0x83E1,
+	0xAEBC, 0xB2A8, 0xAEBD, 0xB2A9, 0xAEBE, 0xB2AA, 0xAEBF, 0x83E2,
+	0xAEC0, 0xB2AB, 0xAEC1, 0x83E3, 0xAEC2, 0x83E4, 0xAEC3, 0x83E5,
+	0xAEC4, 0xB2AC, 0xAEC5, 0x83E6, 0xAEC6, 0x83E7, 0xAEC7, 0x83E8,
+	0xAEC8, 0x83E9, 0xAEC9, 0x83EA, 0xAECA, 0x83EB, 0xAECB, 0x83EC,
+	0xAECC, 0xB2AD, 0xAECD, 0xB2AE, 0xAECE, 0x83ED, 0xAECF, 0xB2AF,
+	0xAED0, 0xB2B0, 0xAED1, 0xB2B1, 0xAED2, 0x83EE, 0xAED3, 0x83EF,
+	0xAED4, 0x83F0, 0xAED5, 0x83F1, 0xAED6, 0x83F2, 0xAED7, 0x83F3,
+	0xAED8, 0xB2B2, 0xAED9, 0xB2B3, 0xAEDA, 0x83F4, 0xAEDB, 0x83F5,
+	0xAEDC, 0xB2B4, 0xAEDD, 0x83F6, 0xAEDE, 0x83F7, 0xAEDF, 0x83F8,
+	0xAEE0, 0x83F9, 0xAEE1, 0x83FA, 0xAEE2, 0x83FB, 0xAEE3, 0x83FC,
+	0xAEE4, 0x83FD, 0xAEE5, 0x83FE, 0xAEE6, 0x8441, 0xAEE7, 0x8442,
+	0xAEE8, 0xB2B5, 0xAEE9, 0x8443, 0xAEEA, 0x8444, 0xAEEB, 0xB2B6,
+	0xAEEC, 0x8445, 0xAEED, 0xB2B7, 0xAEEE, 0x8446, 0xAEEF, 0x8447,
+	0xAEF0, 0x8448, 0xAEF1, 0x8449, 0xAEF2, 0x844A, 0xAEF3, 0x844B,
+	0xAEF4, 0xB2B8, 0xAEF5, 0x844C, 0xAEF6, 0x844D, 0xAEF7, 0x844E,
+	0xAEF8, 0xB2B9, 0xAEF9, 0x844F, 0xAEFA, 0x8450, 0xAEFB, 0x8451,
+	0xAEFC, 0xB2BA, 0xAEFD, 0x8452, 0xAEFE, 0x8453, 0xAEFF, 0x8454,
+	0xAF00, 0x8455, 0xAF01, 0x8456, 0xAF02, 0x8457, 0xAF03, 0x8458,
+	0xAF04, 0x8459, 0xAF05, 0x845A, 0xAF06, 0x8461, 0xAF07, 0xB2BB,
+	0xAF08, 0xB2BC, 0xAF09, 0x8462, 0xAF0A, 0x8463, 0xAF0B, 0x8464,
+	0xAF0C, 0x8465, 0xAF0D, 0xB2BD, 0xAF0E, 0x8466, 0xAF0F, 0x8467,
+	0xAF10, 0xB2BE, 0xAF11, 0x8468, 0xAF12, 0x8469, 0xAF13, 0x846A,
+	0xAF14, 0x846B, 0xAF15, 0x846C, 0xAF16, 0x846D, 0xAF17, 0x846E,
+	0xAF18, 0x846F, 0xAF19, 0x8470, 0xAF1A, 0x8471, 0xAF1B, 0x8472,
+	0xAF1C, 0x8473, 0xAF1D, 0x8474, 0xAF1E, 0x8475, 0xAF1F, 0x8476,
+	0xAF20, 0x8477, 0xAF21, 0x8478, 0xAF22, 0x8479, 0xAF23, 0x847A,
+	0xAF24, 0x8481, 0xAF25, 0x8482, 0xAF26, 0x8483, 0xAF27, 0x8484,
+	0xAF28, 0x8485, 0xAF29, 0x8486, 0xAF2A, 0x8487, 0xAF2B, 0x8488,
+	0xAF2C, 0xB2BF, 0xAF2D, 0xB2C0, 0xAF2E, 0x8489, 0xAF2F, 0x848A,
+	0xAF30, 0xB2C1, 0xAF31, 0x848B, 0xAF32, 0xB2C2, 0xAF33, 0x848C,
+	0xAF34, 0xB2C3, 0xAF35, 0x848D, 0xAF36, 0x848E, 0xAF37, 0x848F,
+	0xAF38, 0x8490, 0xAF39, 0x8491, 0xAF3A, 0x8492, 0xAF3B, 0x8493,
+	0xAF3C, 0xB2C4, 0xAF3D, 0xB2C5, 0xAF3E, 0x8494, 0xAF3F, 0xB2C6,
+	0xAF40, 0x8495, 0xAF41, 0xB2C7, 0xAF42, 0xB2C8, 0xAF43, 0xB2C9,
+	0xAF44, 0x8496, 0xAF45, 0x8497, 0xAF46, 0x8498, 0xAF47, 0x8499,
+	0xAF48, 0xB2CA, 0xAF49, 0xB2CB, 0xAF4A, 0x849A, 0xAF4B, 0x849B,
+	0xAF4C, 0x849C, 0xAF4D, 0x849D, 0xAF4E, 0x849E, 0xAF4F, 0x849F,
+	0xAF50, 0xB2CC, 0xAF51, 0x84A0, 0xAF52, 0x84A1, 0xAF53, 0x84A2,
+	0xAF54, 0x84A3, 0xAF55, 0x84A4, 0xAF56, 0x84A5, 0xAF57, 0x84A6,
+	0xAF58, 0x84A7, 0xAF59, 0x84A8, 0xAF5A, 0x84A9, 0xAF5B, 0x84AA,
+	0xAF5C, 0xB2CD, 0xAF5D, 0xB2CE, 0xAF5E, 0x84AB, 0xAF5F, 0x84AC,
+	0xAF60, 0x84AD, 0xAF61, 0x84AE, 0xAF62, 0x84AF, 0xAF63, 0x84B0,
+	0xAF64, 0xB2CF, 0xAF65, 0xB2D0, 0xAF66, 0x84B1, 0xAF67, 0x84B2,
+	0xAF68, 0x84B3, 0xAF69, 0x84B4, 0xAF6A, 0x84B5, 0xAF6B, 0x84B6,
+	0xAF6C, 0x84B7, 0xAF6D, 0x84B8, 0xAF6E, 0x84B9, 0xAF6F, 0x84BA,
+	0xAF70, 0x84BB, 0xAF71, 0x84BC, 0xAF72, 0x84BD, 0xAF73, 0x84BE,
+	0xAF74, 0x84BF, 0xAF75, 0x84C0, 0xAF76, 0x84C1, 0xAF77, 0x84C2,
+	0xAF78, 0x84C3, 0xAF79, 0xB2D1, 0xAF7A, 0x84C4, 0xAF7B, 0x84C5,
+	0xAF7C, 0x84C6, 0xAF7D, 0x84C7, 0xAF7E, 0x84C8, 0xAF7F, 0x84C9,
+	0xAF80, 0xB2D2, 0xAF81, 0x84CA, 0xAF82, 0x84CB, 0xAF83, 0x84CC,
+	0xAF84, 0xB2D3, 0xAF85, 0x84CD, 0xAF86, 0x84CE, 0xAF87, 0x84CF,
+	0xAF88, 0xB2D4, 0xAF89, 0x84D0, 0xAF8A, 0x84D1, 0xAF8B, 0x84D2,
+	0xAF8C, 0x84D3, 0xAF8D, 0x84D4, 0xAF8E, 0x84D5, 0xAF8F, 0x84D6,
+	0xAF90, 0xB2D5, 0xAF91, 0xB2D6, 0xAF92, 0x84D7, 0xAF93, 0x84D8,
+	0xAF94, 0x84D9, 0xAF95, 0xB2D7, 0xAF96, 0x84DA, 0xAF97, 0x84DB,
+	0xAF98, 0x84DC, 0xAF99, 0x84DD, 0xAF9A, 0x84DE, 0xAF9B, 0x84DF,
+	0xAF9C, 0xB2D8, 0xAF9D, 0x84E0, 0xAF9E, 0x84E1, 0xAF9F, 0x84E2,
+	0xAFA0, 0x84E3, 0xAFA1, 0x84E4, 0xAFA2, 0x84E5, 0xAFA3, 0x84E6,
+	0xAFA4, 0x84E7, 0xAFA5, 0x84E8, 0xAFA6, 0x84E9, 0xAFA7, 0x84EA,
+	0xAFA8, 0x84EB, 0xAFA9, 0x84EC, 0xAFAA, 0x84ED, 0xAFAB, 0x84EE,
+	0xAFAC, 0x84EF, 0xAFAD, 0x84F0, 0xAFAE, 0x84F1, 0xAFAF, 0x84F2,
+	0xAFB0, 0x84F3, 0xAFB1, 0x84F4, 0xAFB2, 0x84F5, 0xAFB3, 0x84F6,
+	0xAFB4, 0x84F7, 0xAFB5, 0x84F8, 0xAFB6, 0x84F9, 0xAFB7, 0x84FA,
+	0xAFB8, 0xB2D9, 0xAFB9, 0xB2DA, 0xAFBA, 0x84FB, 0xAFBB, 0x84FC,
+	0xAFBC, 0xB2DB, 0xAFBD, 0x84FD, 0xAFBE, 0x84FE, 0xAFBF, 0x8541,
+	0xAFC0, 0xB2DC, 0xAFC1, 0x8542, 0xAFC2, 0x8543, 0xAFC3, 0x8544,
+	0xAFC4, 0x8545, 0xAFC5, 0x8546, 0xAFC6, 0x8547, 0xAFC7, 0xB2DD,
+	0xAFC8, 0xB2DE, 0xAFC9, 0xB2DF, 0xAFCA, 0x8548, 0xAFCB, 0xB2E0,
+	0xAFCC, 0x8549, 0xAFCD, 0xB2E1, 0xAFCE, 0xB2E2, 0xAFCF, 0x854A,
+	0xAFD0, 0x854B, 0xAFD1, 0x854C, 0xAFD2, 0x854D, 0xAFD3, 0x854E,
+	0xAFD4, 0xB2E3, 0xAFD5, 0x854F, 0xAFD6, 0x8550, 0xAFD7, 0x8551,
+	0xAFD8, 0x8552, 0xAFD9, 0x8553, 0xAFDA, 0x8554, 0xAFDB, 0x8555,
+	0xAFDC, 0xB2E4, 0xAFDD, 0x8556, 0xAFDE, 0x8557, 0xAFDF, 0x8558,
+	0xAFE0, 0x8559, 0xAFE1, 0x855A, 0xAFE2, 0x8561, 0xAFE3, 0x8562,
+	0xAFE4, 0x8563, 0xAFE5, 0x8564, 0xAFE6, 0x8565, 0xAFE7, 0x8566,
+	0xAFE8, 0xB2E5, 0xAFE9, 0xB2E6, 0xAFEA, 0x8567, 0xAFEB, 0x8568,
+	0xAFEC, 0x8569, 0xAFED, 0x856A, 0xAFEE, 0x856B, 0xAFEF, 0x856C,
+	0xAFF0, 0xB2E7, 0xAFF1, 0xB2E8, 0xAFF2, 0x856D, 0xAFF3, 0x856E,
+	0xAFF4, 0xB2E9, 0xAFF5, 0x856F, 0xAFF6, 0x8570, 0xAFF7, 0x8571,
+	0xAFF8, 0xB2EA, 0xAFF9, 0x8572, 0xAFFA, 0x8573, 0xAFFB, 0x8574,
+	0xAFFC, 0x8575, 0xAFFD, 0x8576, 0xAFFE, 0x8577, 0xAFFF, 0x8578,
+	0xB000, 0xB2EB, 0xB001, 0xB2EC, 0xB002, 0x8579, 0xB003, 0x857A,
+	0xB004, 0xB2ED, 0xB005, 0x8581, 0xB006, 0x8582, 0xB007, 0x8583,
+	0xB008, 0x8584, 0xB009, 0x8585, 0xB00A, 0x8586, 0xB00B, 0x8587,
+	0xB00C, 0xB2EE, 0xB00D, 0x8588, 0xB00E, 0x8589, 0xB00F, 0x858A,
+	0xB010, 0xB2EF, 0xB011, 0x858B, 0xB012, 0x858C, 0xB013, 0x858D,
+	0xB014, 0xB2F0, 0xB015, 0x858E, 0xB016, 0x858F, 0xB017, 0x8590,
+	0xB018, 0x8591, 0xB019, 0x8592, 0xB01A, 0x8593, 0xB01B, 0x8594,
+	0xB01C, 0xB2F1, 0xB01D, 0xB2F2, 0xB01E, 0x8595, 0xB01F, 0x8596,
+	0xB020, 0x8597, 0xB021, 0x8598, 0xB022, 0x8599, 0xB023, 0x859A,
+	0xB024, 0x859B, 0xB025, 0x859C, 0xB026, 0x859D, 0xB027, 0x859E,
+	0xB028, 0xB2F3, 0xB029, 0x859F, 0xB02A, 0x85A0, 0xB02B, 0x85A1,
+	0xB02C, 0x85A2, 0xB02D, 0x85A3, 0xB02E, 0x85A4, 0xB02F, 0x85A5,
+	0xB030, 0x85A6, 0xB031, 0x85A7, 0xB032, 0x85A8, 0xB033, 0x85A9,
+	0xB034, 0x85AA, 0xB035, 0x85AB, 0xB036, 0x85AC, 0xB037, 0x85AD,
+	0xB038, 0x85AE, 0xB039, 0x85AF, 0xB03A, 0x85B0, 0xB03B, 0x85B1,
+	0xB03C, 0x85B2, 0xB03D, 0x85B3, 0xB03E, 0x85B4, 0xB03F, 0x85B5,
+	0xB040, 0x85B6, 0xB041, 0x85B7, 0xB042, 0x85B8, 0xB043, 0x85B9,
+	0xB044, 0xB2F4, 0xB045, 0xB2F5, 0xB046, 0x85BA, 0xB047, 0x85BB,
+	0xB048, 0xB2F6, 0xB049, 0x85BC, 0xB04A, 0xB2F7, 0xB04B, 0x85BD,
+	0xB04C, 0xB2F8, 0xB04D, 0x85BE, 0xB04E, 0xB2F9, 0xB04F, 0x85BF,
+	0xB050, 0x85C0, 0xB051, 0x85C1, 0xB052, 0x85C2, 0xB053, 0xB2FA,
+	0xB054, 0xB2FB, 0xB055, 0xB2FC, 0xB056, 0x85C3, 0xB057, 0xB2FD,
+	0xB058, 0x85C4, 0xB059, 0xB2FE, 0xB05A, 0x85C5, 0xB05B, 0x85C6,
+	0xB05C, 0x85C7, 0xB05D, 0xB3A1, 0xB05E, 0x85C8, 0xB05F, 0x85C9,
+	0xB060, 0x85CA, 0xB061, 0x85CB, 0xB062, 0x85CC, 0xB063, 0x85CD,
+	0xB064, 0x85CE, 0xB065, 0x85CF, 0xB066, 0x85D0, 0xB067, 0x85D1,
+	0xB068, 0x85D2, 0xB069, 0x85D3, 0xB06A, 0x85D4, 0xB06B, 0x85D5,
+	0xB06C, 0x85D6, 0xB06D, 0x85D7, 0xB06E, 0x85D8, 0xB06F, 0x85D9,
+	0xB070, 0x85DA, 0xB071, 0x85DB, 0xB072, 0x85DC, 0xB073, 0x85DD,
+	0xB074, 0x85DE, 0xB075, 0x85DF, 0xB076, 0x85E0, 0xB077, 0x85E1,
+	0xB078, 0x85E2, 0xB079, 0x85E3, 0xB07A, 0x85E4, 0xB07B, 0x85E5,
+	0xB07C, 0xB3A2, 0xB07D, 0xB3A3, 0xB07E, 0x85E6, 0xB07F, 0x85E7,
+	0xB080, 0xB3A4, 0xB081, 0x85E8, 0xB082, 0x85E9, 0xB083, 0x85EA,
+	0xB084, 0xB3A5, 0xB085, 0x85EB, 0xB086, 0x85EC, 0xB087, 0x85ED,
+	0xB088, 0x85EE, 0xB089, 0x85EF, 0xB08A, 0x85F0, 0xB08B, 0x85F1,
+	0xB08C, 0xB3A6, 0xB08D, 0xB3A7, 0xB08E, 0x85F2, 0xB08F, 0xB3A8,
+	0xB090, 0x85F3, 0xB091, 0xB3A9, 0xB092, 0x85F4, 0xB093, 0x85F5,
+	0xB094, 0x85F6, 0xB095, 0x85F7, 0xB096, 0x85F8, 0xB097, 0x85F9,
+	0xB098, 0xB3AA, 0xB099, 0xB3AB, 0xB09A, 0xB3AC, 0xB09B, 0x85FA,
+	0xB09C, 0xB3AD, 0xB09D, 0x85FB, 0xB09E, 0x85FC, 0xB09F, 0xB3AE,
+	0xB0A0, 0xB3AF, 0xB0A1, 0xB3B0, 0xB0A2, 0xB3B1, 0xB0A3, 0x85FD,
+	0xB0A4, 0x85FE, 0xB0A5, 0x8641, 0xB0A6, 0x8642, 0xB0A7, 0x8643,
+	0xB0A8, 0xB3B2, 0xB0A9, 0xB3B3, 0xB0AA, 0x8644, 0xB0AB, 0xB3B4,
+	0xB0AC, 0xB3B5, 0xB0AD, 0xB3B6, 0xB0AE, 0xB3B7, 0xB0AF, 0xB3B8,
+	0xB0B0, 0x8645, 0xB0B1, 0xB3B9, 0xB0B2, 0x8646, 0xB0B3, 0xB3BA,
+	0xB0B4, 0xB3BB, 0xB0B5, 0xB3BC, 0xB0B6, 0x8647, 0xB0B7, 0x8648,
+	0xB0B8, 0xB3BD, 0xB0B9, 0x8649, 0xB0BA, 0x864A, 0xB0BB, 0x864B,
+	0xB0BC, 0xB3BE, 0xB0BD, 0x864C, 0xB0BE, 0x864D, 0xB0BF, 0x864E,
+	0xB0C0, 0x864F, 0xB0C1, 0x8650, 0xB0C2, 0x8651, 0xB0C3, 0x8652,
+	0xB0C4, 0xB3BF, 0xB0C5, 0xB3C0, 0xB0C6, 0x8653, 0xB0C7, 0xB3C1,
+	0xB0C8, 0xB3C2, 0xB0C9, 0xB3C3, 0xB0CA, 0x8654, 0xB0CB, 0x8655,
+	0xB0CC, 0x8656, 0xB0CD, 0x8657, 0xB0CE, 0x8658, 0xB0CF, 0x8659,
+	0xB0D0, 0xB3C4, 0xB0D1, 0xB3C5, 0xB0D2, 0x865A, 0xB0D3, 0x8661,
+	0xB0D4, 0xB3C6, 0xB0D5, 0x8662, 0xB0D6, 0x8663, 0xB0D7, 0x8664,
+	0xB0D8, 0xB3C7, 0xB0D9, 0x8665, 0xB0DA, 0x8666, 0xB0DB, 0x8667,
+	0xB0DC, 0x8668, 0xB0DD, 0x8669, 0xB0DE, 0x866A, 0xB0DF, 0x866B,
+	0xB0E0, 0xB3C8, 0xB0E1, 0x866C, 0xB0E2, 0x866D, 0xB0E3, 0x866E,
+	0xB0E4, 0x866F, 0xB0E5, 0xB3C9, 0xB0E6, 0x8670, 0xB0E7, 0x8671,
+	0xB0E8, 0x8672, 0xB0E9, 0x8673, 0xB0EA, 0x8674, 0xB0EB, 0x8675,
+	0xB0EC, 0x8676, 0xB0ED, 0x8677, 0xB0EE, 0x8678, 0xB0EF, 0x8679,
+	0xB0F0, 0x867A, 0xB0F1, 0x8681, 0xB0F2, 0x8682, 0xB0F3, 0x8683,
+	0xB0F4, 0x8684, 0xB0F5, 0x8685, 0xB0F6, 0x8686, 0xB0F7, 0x8687,
+	0xB0F8, 0x8688, 0xB0F9, 0x8689, 0xB0FA, 0x868A, 0xB0FB, 0x868B,
+	0xB0FC, 0x868C, 0xB0FD, 0x868D, 0xB0FE, 0x868E, 0xB0FF, 0x868F,
+	0xB100, 0x8690, 0xB101, 0x8691, 0xB102, 0x8692, 0xB103, 0x8693,
+	0xB104, 0x8694, 0xB105, 0x8695, 0xB106, 0x8696, 0xB107, 0x8697,
+	0xB108, 0xB3CA, 0xB109, 0xB3CB, 0xB10A, 0x8698, 0xB10B, 0xB3CC,
+	0xB10C, 0xB3CD, 0xB10D, 0x8699, 0xB10E, 0x869A, 0xB10F, 0x869B,
+	0xB110, 0xB3CE, 0xB111, 0x869C, 0xB112, 0xB3CF, 0xB113, 0xB3D0,
+	0xB114, 0x869D, 0xB115, 0x869E, 0xB116, 0x869F, 0xB117, 0x86A0,
+	0xB118, 0xB3D1, 0xB119, 0xB3D2, 0xB11A, 0x86A1, 0xB11B, 0xB3D3,
+	0xB11C, 0xB3D4, 0xB11D, 0xB3D5, 0xB11E, 0x86A2, 0xB11F, 0x86A3,
+	0xB120, 0x86A4, 0xB121, 0x86A5, 0xB122, 0x86A6, 0xB123, 0xB3D6,
+	0xB124, 0xB3D7, 0xB125, 0xB3D8, 0xB126, 0x86A7, 0xB127, 0x86A8,
+	0xB128, 0xB3D9, 0xB129, 0x86A9, 0xB12A, 0x86AA, 0xB12B, 0x86AB,
+	0xB12C, 0xB3DA, 0xB12D, 0x86AC, 0xB12E, 0x86AD, 0xB12F, 0x86AE,
+	0xB130, 0x86AF, 0xB131, 0x86B0, 0xB132, 0x86B1, 0xB133, 0x86B2,
+	0xB134, 0xB3DB, 0xB135, 0xB3DC, 0xB136, 0x86B3, 0xB137, 0xB3DD,
+	0xB138, 0xB3DE, 0xB139, 0xB3DF, 0xB13A, 0x86B4, 0xB13B, 0x86B5,
+	0xB13C, 0x86B6, 0xB13D, 0x86B7, 0xB13E, 0x86B8, 0xB13F, 0x86B9,
+	0xB140, 0xB3E0, 0xB141, 0xB3E1, 0xB142, 0x86BA, 0xB143, 0x86BB,
+	0xB144, 0xB3E2, 0xB145, 0x86BC, 0xB146, 0x86BD, 0xB147, 0x86BE,
+	0xB148, 0xB3E3, 0xB149, 0x86BF, 0xB14A, 0x86C0, 0xB14B, 0x86C1,
+	0xB14C, 0x86C2, 0xB14D, 0x86C3, 0xB14E, 0x86C4, 0xB14F, 0x86C5,
+	0xB150, 0xB3E4, 0xB151, 0xB3E5, 0xB152, 0x86C6, 0xB153, 0x86C7,
+	0xB154, 0xB3E6, 0xB155, 0xB3E7, 0xB156, 0x86C8, 0xB157, 0x86C9,
+	0xB158, 0xB3E8, 0xB159, 0x86CA, 0xB15A, 0x86CB, 0xB15B, 0x86CC,
+	0xB15C, 0xB3E9, 0xB15D, 0x86CD, 0xB15E, 0x86CE, 0xB15F, 0x86CF,
+	0xB160, 0xB3EA, 0xB161, 0x86D0, 0xB162, 0x86D1, 0xB163, 0x86D2,
+	0xB164, 0x86D3, 0xB165, 0x86D4, 0xB166, 0x86D5, 0xB167, 0x86D6,
+	0xB168, 0x86D7, 0xB169, 0x86D8, 0xB16A, 0x86D9, 0xB16B, 0x86DA,
+	0xB16C, 0x86DB, 0xB16D, 0x86DC, 0xB16E, 0x86DD, 0xB16F, 0x86DE,
+	0xB170, 0x86DF, 0xB171, 0x86E0, 0xB172, 0x86E1, 0xB173, 0x86E2,
+	0xB174, 0x86E3, 0xB175, 0x86E4, 0xB176, 0x86E5, 0xB177, 0x86E6,
+	0xB178, 0xB3EB, 0xB179, 0xB3EC, 0xB17A, 0x86E7, 0xB17B, 0x86E8,
+	0xB17C, 0xB3ED, 0xB17D, 0x86E9, 0xB17E, 0x86EA, 0xB17F, 0x86EB,
+	0xB180, 0xB3EE, 0xB181, 0x86EC, 0xB182, 0xB3EF, 0xB183, 0x86ED,
+	0xB184, 0x86EE, 0xB185, 0x86EF, 0xB186, 0x86F0, 0xB187, 0x86F1,
+	0xB188, 0xB3F0, 0xB189, 0xB3F1, 0xB18A, 0x86F2, 0xB18B, 0xB3F2,
+	0xB18C, 0x86F3, 0xB18D, 0xB3F3, 0xB18E, 0x86F4, 0xB18F, 0x86F5,
+	0xB190, 0x86F6, 0xB191, 0x86F7, 0xB192, 0xB3F4, 0xB193, 0xB3F5,
+	0xB194, 0xB3F6, 0xB195, 0x86F8, 0xB196, 0x86F9, 0xB197, 0x86FA,
+	0xB198, 0xB3F7, 0xB199, 0x86FB, 0xB19A, 0x86FC, 0xB19B, 0x86FD,
+	0xB19C, 0xB3F8, 0xB19D, 0x86FE, 0xB19E, 0x8741, 0xB19F, 0x8742,
+	0xB1A0, 0x8743, 0xB1A1, 0x8744, 0xB1A2, 0x8745, 0xB1A3, 0x8746,
+	0xB1A4, 0x8747, 0xB1A5, 0x8748, 0xB1A6, 0x8749, 0xB1A7, 0x874A,
+	0xB1A8, 0xB3F9, 0xB1A9, 0x874B, 0xB1AA, 0x874C, 0xB1AB, 0x874D,
+	0xB1AC, 0x874E, 0xB1AD, 0x874F, 0xB1AE, 0x8750, 0xB1AF, 0x8751,
+	0xB1B0, 0x8752, 0xB1B1, 0x8753, 0xB1B2, 0x8754, 0xB1B3, 0x8755,
+	0xB1B4, 0x8756, 0xB1B5, 0x8757, 0xB1B6, 0x8758, 0xB1B7, 0x8759,
+	0xB1B8, 0x875A, 0xB1B9, 0x8761, 0xB1BA, 0x8762, 0xB1BB, 0x8763,
+	0xB1BC, 0x8764, 0xB1BD, 0x8765, 0xB1BE, 0x8766, 0xB1BF, 0x8767,
+	0xB1C0, 0x8768, 0xB1C1, 0x8769, 0xB1C2, 0x876A, 0xB1C3, 0x876B,
+	0xB1C4, 0x876C, 0xB1C5, 0x876D, 0xB1C6, 0x876E, 0xB1C7, 0x876F,
+	0xB1C8, 0x8770, 0xB1C9, 0x8771, 0xB1CA, 0x8772, 0xB1CB, 0x8773,
+	0xB1CC, 0xB3FA, 0xB1CD, 0x8774, 0xB1CE, 0x8775, 0xB1CF, 0x8776,
+	0xB1D0, 0xB3FB, 0xB1D1, 0x8777, 0xB1D2, 0x8778, 0xB1D3, 0x8779,
+	0xB1D4, 0xB3FC, 0xB1D5, 0x877A, 0xB1D6, 0x8781, 0xB1D7, 0x8782,
+	0xB1D8, 0x8783, 0xB1D9, 0x8784, 0xB1DA, 0x8785, 0xB1DB, 0x8786,
+	0xB1DC, 0xB3FD, 0xB1DD, 0xB3FE, 0xB1DE, 0x8787, 0xB1DF, 0xB4A1,
+	0xB1E0, 0x8788, 0xB1E1, 0x8789, 0xB1E2, 0x878A, 0xB1E3, 0x878B,
+	0xB1E4, 0x878C, 0xB1E5, 0x878D, 0xB1E6, 0x878E, 0xB1E7, 0x878F,
+	0xB1E8, 0xB4A2, 0xB1E9, 0xB4A3, 0xB1EA, 0x8790, 0xB1EB, 0x8791,
+	0xB1EC, 0xB4A4, 0xB1ED, 0x8792, 0xB1EE, 0x8793, 0xB1EF, 0x8794,
+	0xB1F0, 0xB4A5, 0xB1F1, 0x8795, 0xB1F2, 0x8796, 0xB1F3, 0x8797,
+	0xB1F4, 0x8798, 0xB1F5, 0x8799, 0xB1F6, 0x879A, 0xB1F7, 0x879B,
+	0xB1F8, 0x879C, 0xB1F9, 0xB4A6, 0xB1FA, 0x879D, 0xB1FB, 0xB4A7,
+	0xB1FC, 0x879E, 0xB1FD, 0xB4A8, 0xB1FE, 0x879F, 0xB1FF, 0x87A0,
+	0xB200, 0x87A1, 0xB201, 0x87A2, 0xB202, 0x87A3, 0xB203, 0x87A4,
+	0xB204, 0xB4A9, 0xB205, 0xB4AA, 0xB206, 0x87A5, 0xB207, 0x87A6,
+	0xB208, 0xB4AB, 0xB209, 0x87A7, 0xB20A, 0x87A8, 0xB20B, 0xB4AC,
+	0xB20C, 0xB4AD, 0xB20D, 0x87A9, 0xB20E, 0x87AA, 0xB20F, 0x87AB,
+	0xB210, 0x87AC, 0xB211, 0x87AD, 0xB212, 0x87AE, 0xB213, 0x87AF,
+	0xB214, 0xB4AE, 0xB215, 0xB4AF, 0xB216, 0x87B0, 0xB217, 0xB4B0,
+	0xB218, 0x87B1, 0xB219, 0xB4B1, 0xB21A, 0x87B2, 0xB21B, 0x87B3,
+	0xB21C, 0x87B4, 0xB21D, 0x87B5, 0xB21E, 0x87B6, 0xB21F, 0x87B7,
+	0xB220, 0xB4B2, 0xB221, 0x87B8, 0xB222, 0x87B9, 0xB223, 0x87BA,
+	0xB224, 0x87BB, 0xB225, 0x87BC, 0xB226, 0x87BD, 0xB227, 0x87BE,
+	0xB228, 0x87BF, 0xB229, 0x87C0, 0xB22A, 0x87C1, 0xB22B, 0x87C2,
+	0xB22C, 0x87C3, 0xB22D, 0x87C4, 0xB22E, 0x87C5, 0xB22F, 0x87C6,
+	0xB230, 0x87C7, 0xB231, 0x87C8, 0xB232, 0x87C9, 0xB233, 0x87CA,
+	0xB234, 0xB4B3, 0xB235, 0x87CB, 0xB236, 0x87CC, 0xB237, 0x87CD,
+	0xB238, 0x87CE, 0xB239, 0x87CF, 0xB23A, 0x87D0, 0xB23B, 0x87D1,
+	0xB23C, 0xB4B4, 0xB23D, 0x87D2, 0xB23E, 0x87D3, 0xB23F, 0x87D4,
+	0xB240, 0x87D5, 0xB241, 0x87D6, 0xB242, 0x87D7, 0xB243, 0x87D8,
+	0xB244, 0x87D9, 0xB245, 0x87DA, 0xB246, 0x87DB, 0xB247, 0x87DC,
+	0xB248, 0x87DD, 0xB249, 0x87DE, 0xB24A, 0x87DF, 0xB24B, 0x87E0,
+	0xB24C, 0x87E1, 0xB24D, 0x87E2, 0xB24E, 0x87E3, 0xB24F, 0x87E4,
+	0xB250, 0x87E5, 0xB251, 0x87E6, 0xB252, 0x87E7, 0xB253, 0x87E8,
+	0xB254, 0x87E9, 0xB255, 0x87EA, 0xB256, 0x87EB, 0xB257, 0x87EC,
+	0xB258, 0xB4B5, 0xB259, 0x87ED, 0xB25A, 0x87EE, 0xB25B, 0x87EF,
+	0xB25C, 0xB4B6, 0xB25D, 0x87F0, 0xB25E, 0x87F1, 0xB25F, 0x87F2,
+	0xB260, 0xB4B7, 0xB261, 0x87F3, 0xB262, 0x87F4, 0xB263, 0x87F5,
+	0xB264, 0x87F6, 0xB265, 0x87F7, 0xB266, 0x87F8, 0xB267, 0x87F9,
+	0xB268, 0xB4B8, 0xB269, 0xB4B9, 0xB26A, 0x87FA, 0xB26B, 0x87FB,
+	0xB26C, 0x87FC, 0xB26D, 0x87FD, 0xB26E, 0x87FE, 0xB26F, 0x8841,
+	0xB270, 0x8842, 0xB271, 0x8843, 0xB272, 0x8844, 0xB273, 0x8845,
+	0xB274, 0xB4BA, 0xB275, 0xB4BB, 0xB276, 0x8846, 0xB277, 0x8847,
+	0xB278, 0x8848, 0xB279, 0x8849, 0xB27A, 0x884A, 0xB27B, 0x884B,
+	0xB27C, 0xB4BC, 0xB27D, 0x884C, 0xB27E, 0x884D, 0xB27F, 0x884E,
+	0xB280, 0x884F, 0xB281, 0x8850, 0xB282, 0x8851, 0xB283, 0x8852,
+	0xB284, 0xB4BD, 0xB285, 0xB4BE, 0xB286, 0x8853, 0xB287, 0x8854,
+	0xB288, 0x8855, 0xB289, 0xB4BF, 0xB28A, 0x8856, 0xB28B, 0x8857,
+	0xB28C, 0x8858, 0xB28D, 0x8859, 0xB28E, 0x885A, 0xB28F, 0x8861,
+	0xB290, 0xB4C0, 0xB291, 0xB4C1, 0xB292, 0x8862, 0xB293, 0x8863,
+	0xB294, 0xB4C2, 0xB295, 0x8864, 0xB296, 0x8865, 0xB297, 0x8866,
+	0xB298, 0xB4C3, 0xB299, 0xB4C4, 0xB29A, 0xB4C5, 0xB29B, 0x8867,
+	0xB29C, 0x8868, 0xB29D, 0x8869, 0xB29E, 0x886A, 0xB29F, 0x886B,
+	0xB2A0, 0xB4C6, 0xB2A1, 0xB4C7, 0xB2A2, 0x886C, 0xB2A3, 0xB4C8,
+	0xB2A4, 0x886D, 0xB2A5, 0xB4C9, 0xB2A6, 0xB4CA, 0xB2A7, 0x886E,
+	0xB2A8, 0x886F, 0xB2A9, 0x8870, 0xB2AA, 0xB4CB, 0xB2AB, 0x8871,
+	0xB2AC, 0xB4CC, 0xB2AD, 0x8872, 0xB2AE, 0x8873, 0xB2AF, 0x8874,
+	0xB2B0, 0xB4CD, 0xB2B1, 0x8875, 0xB2B2, 0x8876, 0xB2B3, 0x8877,
+	0xB2B4, 0xB4CE, 0xB2B5, 0x8878, 0xB2B6, 0x8879, 0xB2B7, 0x887A,
+	0xB2B8, 0x8881, 0xB2B9, 0x8882, 0xB2BA, 0x8883, 0xB2BB, 0x8884,
+	0xB2BC, 0x8885, 0xB2BD, 0x8886, 0xB2BE, 0x8887, 0xB2BF, 0x8888,
+	0xB2C0, 0x8889, 0xB2C1, 0x888A, 0xB2C2, 0x888B, 0xB2C3, 0x888C,
+	0xB2C4, 0x888D, 0xB2C5, 0x888E, 0xB2C6, 0x888F, 0xB2C7, 0x8890,
+	0xB2C8, 0xB4CF, 0xB2C9, 0xB4D0, 0xB2CA, 0x8891, 0xB2CB, 0x8892,
+	0xB2CC, 0xB4D1, 0xB2CD, 0x8893, 0xB2CE, 0x8894, 0xB2CF, 0x8895,
+	0xB2D0, 0xB4D2, 0xB2D1, 0x8896, 0xB2D2, 0xB4D3, 0xB2D3, 0x8897,
+	0xB2D4, 0x8898, 0xB2D5, 0x8899, 0xB2D6, 0x889A, 0xB2D7, 0x889B,
+	0xB2D8, 0xB4D4, 0xB2D9, 0xB4D5, 0xB2DA, 0x889C, 0xB2DB, 0xB4D6,
+	0xB2DC, 0x889D, 0xB2DD, 0xB4D7, 0xB2DE, 0x889E, 0xB2DF, 0x889F,
+	0xB2E0, 0x88A0, 0xB2E1, 0x88A1, 0xB2E2, 0xB4D8, 0xB2E3, 0x88A2,
+	0xB2E4, 0xB4D9, 0xB2E5, 0xB4DA, 0xB2E6, 0xB4DB, 0xB2E7, 0x88A3,
+	0xB2E8, 0xB4DC, 0xB2E9, 0x88A4, 0xB2EA, 0x88A5, 0xB2EB, 0xB4DD,
+	0xB2EC, 0xB4DE, 0xB2ED, 0xB4DF, 0xB2EE, 0xB4E0, 0xB2EF, 0xB4E1,
+	0xB2F0, 0x88A6, 0xB2F1, 0x88A7, 0xB2F2, 0x88A8, 0xB2F3, 0xB4E2,
+	0xB2F4, 0xB4E3, 0xB2F5, 0xB4E4, 0xB2F6, 0x88A9, 0xB2F7, 0xB4E5,
+	0xB2F8, 0xB4E6, 0xB2F9, 0xB4E7, 0xB2FA, 0xB4E8, 0xB2FB, 0xB4E9,
+	0xB2FC, 0x88AA, 0xB2FD, 0x88AB, 0xB2FE, 0x88AC, 0xB2FF, 0xB4EA,
+	0xB300, 0xB4EB, 0xB301, 0xB4EC, 0xB302, 0x88AD, 0xB303, 0x88AE,
+	0xB304, 0xB4ED, 0xB305, 0x88AF, 0xB306, 0x88B0, 0xB307, 0x88B1,
+	0xB308, 0xB4EE, 0xB309, 0x88B2, 0xB30A, 0x88B3, 0xB30B, 0x88B4,
+	0xB30C, 0x88B5, 0xB30D, 0x88B6, 0xB30E, 0x88B7, 0xB30F, 0x88B8,
+	0xB310, 0xB4EF, 0xB311, 0xB4F0, 0xB312, 0x88B9, 0xB313, 0xB4F1,
+	0xB314, 0xB4F2, 0xB315, 0xB4F3, 0xB316, 0x88BA, 0xB317, 0x88BB,
+	0xB318, 0x88BC, 0xB319, 0x88BD, 0xB31A, 0x88BE, 0xB31B, 0x88BF,
+	0xB31C, 0xB4F4, 0xB31D, 0x88C0, 0xB31E, 0x88C1, 0xB31F, 0x88C2,
+	0xB320, 0x88C3, 0xB321, 0x88C4, 0xB322, 0x88C5, 0xB323, 0x88C6,
+	0xB324, 0x88C7, 0xB325, 0x88C8, 0xB326, 0x88C9, 0xB327, 0x88CA,
+	0xB328, 0x88CB, 0xB329, 0x88CC, 0xB32A, 0x88CD, 0xB32B, 0x88CE,
+	0xB32C, 0x88CF, 0xB32D, 0x88D0, 0xB32E, 0x88D1, 0xB32F, 0x88D2,
+	0xB330, 0x88D3, 0xB331, 0x88D4, 0xB332, 0x88D5, 0xB333, 0x88D6,
+	0xB334, 0x88D7, 0xB335, 0x88D8, 0xB336, 0x88D9, 0xB337, 0x88DA,
+	0xB338, 0x88DB, 0xB339, 0x88DC, 0xB33A, 0x88DD, 0xB33B, 0x88DE,
+	0xB33C, 0x88DF, 0xB33D, 0x88E0, 0xB33E, 0x88E1, 0xB33F, 0x88E2,
+	0xB340, 0x88E3, 0xB341, 0x88E4, 0xB342, 0x88E5, 0xB343, 0x88E6,
+	0xB344, 0x88E7, 0xB345, 0x88E8, 0xB346, 0x88E9, 0xB347, 0x88EA,
+	0xB348, 0x88EB, 0xB349, 0x88EC, 0xB34A, 0x88ED, 0xB34B, 0x88EE,
+	0xB34C, 0x88EF, 0xB34D, 0x88F0, 0xB34E, 0x88F1, 0xB34F, 0x88F2,
+	0xB350, 0x88F3, 0xB351, 0x88F4, 0xB352, 0x88F5, 0xB353, 0x88F6,
+	0xB354, 0xB4F5, 0xB355, 0xB4F6, 0xB356, 0xB4F7, 0xB357, 0x88F7,
+	0xB358, 0xB4F8, 0xB359, 0x88F8, 0xB35A, 0x88F9, 0xB35B, 0xB4F9,
+	0xB35C, 0xB4FA, 0xB35D, 0x88FA, 0xB35E, 0xB4FB, 0xB35F, 0xB4FC,
+	0xB360, 0x88FB, 0xB361, 0x88FC, 0xB362, 0x88FD, 0xB363, 0x88FE,
+	0xB364, 0xB4FD, 0xB365, 0xB4FE, 0xB366, 0x8941, 0xB367, 0xB5A1,
+	0xB368, 0x8942, 0xB369, 0xB5A2, 0xB36A, 0x8943, 0xB36B, 0xB5A3,
+	0xB36C, 0x8944, 0xB36D, 0x8945, 0xB36E, 0xB5A4, 0xB36F, 0x8946,
+	0xB370, 0xB5A5, 0xB371, 0xB5A6, 0xB372, 0x8947, 0xB373, 0x8948,
+	0xB374, 0xB5A7, 0xB375, 0x8949, 0xB376, 0x894A, 0xB377, 0x894B,
+	0xB378, 0xB5A8, 0xB379, 0x894C, 0xB37A, 0x894D, 0xB37B, 0x894E,
+	0xB37C, 0x894F, 0xB37D, 0x8950, 0xB37E, 0x8951, 0xB37F, 0x8952,
+	0xB380, 0xB5A9, 0xB381, 0xB5AA, 0xB382, 0x8953, 0xB383, 0xB5AB,
+	0xB384, 0xB5AC, 0xB385, 0xB5AD, 0xB386, 0x8954, 0xB387, 0x8955,
+	0xB388, 0x8956, 0xB389, 0x8957, 0xB38A, 0x8958, 0xB38B, 0x8959,
+	0xB38C, 0xB5AE, 0xB38D, 0x895A, 0xB38E, 0x8961, 0xB38F, 0x8962,
+	0xB390, 0xB5AF, 0xB391, 0x8963, 0xB392, 0x8964, 0xB393, 0x8965,
+	0xB394, 0xB5B0, 0xB395, 0x8966, 0xB396, 0x8967, 0xB397, 0x8968,
+	0xB398, 0x8969, 0xB399, 0x896A, 0xB39A, 0x896B, 0xB39B, 0x896C,
+	0xB39C, 0x896D, 0xB39D, 0x896E, 0xB39E, 0x896F, 0xB39F, 0x8970,
+	0xB3A0, 0xB5B1, 0xB3A1, 0xB5B2, 0xB3A2, 0x8971, 0xB3A3, 0x8972,
+	0xB3A4, 0x8973, 0xB3A5, 0x8974, 0xB3A6, 0x8975, 0xB3A7, 0x8976,
+	0xB3A8, 0xB5B3, 0xB3A9, 0x8977, 0xB3AA, 0x8978, 0xB3AB, 0x8979,
+	0xB3AC, 0xB5B4, 0xB3AD, 0x897A, 0xB3AE, 0x8981, 0xB3AF, 0x8982,
+	0xB3B0, 0x8983, 0xB3B1, 0x8984, 0xB3B2, 0x8985, 0xB3B3, 0x8986,
+	0xB3B4, 0x8987, 0xB3B5, 0x8988, 0xB3B6, 0x8989, 0xB3B7, 0x898A,
+	0xB3B8, 0x898B, 0xB3B9, 0x898C, 0xB3BA, 0x898D, 0xB3BB, 0x898E,
+	0xB3BC, 0x898F, 0xB3BD, 0x8990, 0xB3BE, 0x8991, 0xB3BF, 0x8992,
+	0xB3C0, 0x8993, 0xB3C1, 0x8994, 0xB3C2, 0x8995, 0xB3C3, 0x8996,
+	0xB3C4, 0xB5B5, 0xB3C5, 0xB5B6, 0xB3C6, 0x8997, 0xB3C7, 0x8998,
+	0xB3C8, 0xB5B7, 0xB3C9, 0x8999, 0xB3CA, 0x899A, 0xB3CB, 0xB5B8,
+	0xB3CC, 0xB5B9, 0xB3CD, 0x899B, 0xB3CE, 0xB5BA, 0xB3CF, 0x899C,
+	0xB3D0, 0xB5BB, 0xB3D1, 0x899D, 0xB3D2, 0x899E, 0xB3D3, 0x899F,
+	0xB3D4, 0xB5BC, 0xB3D5, 0xB5BD, 0xB3D6, 0x89A0, 0xB3D7, 0xB5BE,
+	0xB3D8, 0x89A1, 0xB3D9, 0xB5BF, 0xB3DA, 0x89A2, 0xB3DB, 0xB5C0,
+	0xB3DC, 0x89A3, 0xB3DD, 0xB5C1, 0xB3DE, 0x89A4, 0xB3DF, 0x89A5,
+	0xB3E0, 0xB5C2, 0xB3E1, 0x89A6, 0xB3E2, 0x89A7, 0xB3E3, 0x89A8,
+	0xB3E4, 0xB5C3, 0xB3E5, 0x89A9, 0xB3E6, 0x89AA, 0xB3E7, 0x89AB,
+	0xB3E8, 0xB5C4, 0xB3E9, 0x89AC, 0xB3EA, 0x89AD, 0xB3EB, 0x89AE,
+	0xB3EC, 0x89AF, 0xB3ED, 0x89B0, 0xB3EE, 0x89B1, 0xB3EF, 0x89B2,
+	0xB3F0, 0x89B3, 0xB3F1, 0x89B4, 0xB3F2, 0x89B5, 0xB3F3, 0x89B6,
+	0xB3F4, 0x89B7, 0xB3F5, 0x89B8, 0xB3F6, 0x89B9, 0xB3F7, 0x89BA,
+	0xB3F8, 0x89BB, 0xB3F9, 0x89BC, 0xB3FA, 0x89BD, 0xB3FB, 0x89BE,
+	0xB3FC, 0xB5C5, 0xB3FD, 0x89BF, 0xB3FE, 0x89C0, 0xB3FF, 0x89C1,
+	0xB400, 0x89C2, 0xB401, 0x89C3, 0xB402, 0x89C4, 0xB403, 0x89C5,
+	0xB404, 0x89C6, 0xB405, 0x89C7, 0xB406, 0x89C8, 0xB407, 0x89C9,
+	0xB408, 0x89CA, 0xB409, 0x89CB, 0xB40A, 0x89CC, 0xB40B, 0x89CD,
+	0xB40C, 0x89CE, 0xB40D, 0x89CF, 0xB40E, 0x89D0, 0xB40F, 0x89D1,
+	0xB410, 0xB5C6, 0xB411, 0x89D2, 0xB412, 0x89D3, 0xB413, 0x89D4,
+	0xB414, 0x89D5, 0xB415, 0x89D6, 0xB416, 0x89D7, 0xB417, 0x89D8,
+	0xB418, 0xB5C7, 0xB419, 0x89D9, 0xB41A, 0x89DA, 0xB41B, 0x89DB,
+	0xB41C, 0xB5C8, 0xB41D, 0x89DC, 0xB41E, 0x89DD, 0xB41F, 0x89DE,
+	0xB420, 0xB5C9, 0xB421, 0x89DF, 0xB422, 0x89E0, 0xB423, 0x89E1,
+	0xB424, 0x89E2, 0xB425, 0x89E3, 0xB426, 0x89E4, 0xB427, 0x89E5,
+	0xB428, 0xB5CA, 0xB429, 0xB5CB, 0xB42A, 0x89E6, 0xB42B, 0xB5CC,
+	0xB42C, 0x89E7, 0xB42D, 0x89E8, 0xB42E, 0x89E9, 0xB42F, 0x89EA,
+	0xB430, 0x89EB, 0xB431, 0x89EC, 0xB432, 0x89ED, 0xB433, 0x89EE,
+	0xB434, 0xB5CD, 0xB435, 0x89EF, 0xB436, 0x89F0, 0xB437, 0x89F1,
+	0xB438, 0x89F2, 0xB439, 0x89F3, 0xB43A, 0x89F4, 0xB43B, 0x89F5,
+	0xB43C, 0x89F6, 0xB43D, 0x89F7, 0xB43E, 0x89F8, 0xB43F, 0x89F9,
+	0xB440, 0x89FA, 0xB441, 0x89FB, 0xB442, 0x89FC, 0xB443, 0x89FD,
+	0xB444, 0x89FE, 0xB445, 0x8A41, 0xB446, 0x8A42, 0xB447, 0x8A43,
+	0xB448, 0x8A44, 0xB449, 0x8A45, 0xB44A, 0x8A46, 0xB44B, 0x8A47,
+	0xB44C, 0x8A48, 0xB44D, 0x8A49, 0xB44E, 0x8A4A, 0xB44F, 0x8A4B,
+	0xB450, 0xB5CE, 0xB451, 0xB5CF, 0xB452, 0x8A4C, 0xB453, 0x8A4D,
+	0xB454, 0xB5D0, 0xB455, 0x8A4E, 0xB456, 0x8A4F, 0xB457, 0x8A50,
+	0xB458, 0xB5D1, 0xB459, 0x8A51, 0xB45A, 0x8A52, 0xB45B, 0x8A53,
+	0xB45C, 0x8A54, 0xB45D, 0x8A55, 0xB45E, 0x8A56, 0xB45F, 0x8A57,
+	0xB460, 0xB5D2, 0xB461, 0xB5D3, 0xB462, 0x8A58, 0xB463, 0xB5D4,
+	0xB464, 0x8A59, 0xB465, 0xB5D5, 0xB466, 0x8A5A, 0xB467, 0x8A61,
+	0xB468, 0x8A62, 0xB469, 0x8A63, 0xB46A, 0x8A64, 0xB46B, 0x8A65,
+	0xB46C, 0xB5D6, 0xB46D, 0x8A66, 0xB46E, 0x8A67, 0xB46F, 0x8A68,
+	0xB470, 0x8A69, 0xB471, 0x8A6A, 0xB472, 0x8A6B, 0xB473, 0x8A6C,
+	0xB474, 0x8A6D, 0xB475, 0x8A6E, 0xB476, 0x8A6F, 0xB477, 0x8A70,
+	0xB478, 0x8A71, 0xB479, 0x8A72, 0xB47A, 0x8A73, 0xB47B, 0x8A74,
+	0xB47C, 0x8A75, 0xB47D, 0x8A76, 0xB47E, 0x8A77, 0xB47F, 0x8A78,
+	0xB480, 0xB5D7, 0xB481, 0x8A79, 0xB482, 0x8A7A, 0xB483, 0x8A81,
+	0xB484, 0x8A82, 0xB485, 0x8A83, 0xB486, 0x8A84, 0xB487, 0x8A85,
+	0xB488, 0xB5D8, 0xB489, 0x8A86, 0xB48A, 0x8A87, 0xB48B, 0x8A88,
+	0xB48C, 0x8A89, 0xB48D, 0x8A8A, 0xB48E, 0x8A8B, 0xB48F, 0x8A8C,
+	0xB490, 0x8A8D, 0xB491, 0x8A8E, 0xB492, 0x8A8F, 0xB493, 0x8A90,
+	0xB494, 0x8A91, 0xB495, 0x8A92, 0xB496, 0x8A93, 0xB497, 0x8A94,
+	0xB498, 0x8A95, 0xB499, 0x8A96, 0xB49A, 0x8A97, 0xB49B, 0x8A98,
+	0xB49C, 0x8A99, 0xB49D, 0xB5D9, 0xB49E, 0x8A9A, 0xB49F, 0x8A9B,
+	0xB4A0, 0x8A9C, 0xB4A1, 0x8A9D, 0xB4A2, 0x8A9E, 0xB4A3, 0x8A9F,
+	0xB4A4, 0xB5DA, 0xB4A5, 0x8AA0, 0xB4A6, 0x8AA1, 0xB4A7, 0x8AA2,
+	0xB4A8, 0xB5DB, 0xB4A9, 0x8AA3, 0xB4AA, 0x8AA4, 0xB4AB, 0x8AA5,
+	0xB4AC, 0xB5DC, 0xB4AD, 0x8AA6, 0xB4AE, 0x8AA7, 0xB4AF, 0x8AA8,
+	0xB4B0, 0x8AA9, 0xB4B1, 0x8AAA, 0xB4B2, 0x8AAB, 0xB4B3, 0x8AAC,
+	0xB4B4, 0x8AAD, 0xB4B5, 0xB5DD, 0xB4B6, 0x8AAE, 0xB4B7, 0xB5DE,
+	0xB4B8, 0x8AAF, 0xB4B9, 0xB5DF, 0xB4BA, 0x8AB0, 0xB4BB, 0x8AB1,
+	0xB4BC, 0x8AB2, 0xB4BD, 0x8AB3, 0xB4BE, 0x8AB4, 0xB4BF, 0x8AB5,
+	0xB4C0, 0xB5E0, 0xB4C1, 0x8AB6, 0xB4C2, 0x8AB7, 0xB4C3, 0x8AB8,
+	0xB4C4, 0xB5E1, 0xB4C5, 0x8AB9, 0xB4C6, 0x8ABA, 0xB4C7, 0x8ABB,
+	0xB4C8, 0xB5E2, 0xB4C9, 0x8ABC, 0xB4CA, 0x8ABD, 0xB4CB, 0x8ABE,
+	0xB4CC, 0x8ABF, 0xB4CD, 0x8AC0, 0xB4CE, 0x8AC1, 0xB4CF, 0x8AC2,
+	0xB4D0, 0xB5E3, 0xB4D1, 0x8AC3, 0xB4D2, 0x8AC4, 0xB4D3, 0x8AC5,
+	0xB4D4, 0x8AC6, 0xB4D5, 0xB5E4, 0xB4D6, 0x8AC7, 0xB4D7, 0x8AC8,
+	0xB4D8, 0x8AC9, 0xB4D9, 0x8ACA, 0xB4DA, 0x8ACB, 0xB4DB, 0x8ACC,
+	0xB4DC, 0xB5E5, 0xB4DD, 0xB5E6, 0xB4DE, 0x8ACD, 0xB4DF, 0x8ACE,
+	0xB4E0, 0xB5E7, 0xB4E1, 0x8ACF, 0xB4E2, 0x8AD0, 0xB4E3, 0xB5E8,
+	0xB4E4, 0xB5E9, 0xB4E5, 0x8AD1, 0xB4E6, 0xB5EA, 0xB4E7, 0x8AD2,
+	0xB4E8, 0x8AD3, 0xB4E9, 0x8AD4, 0xB4EA, 0x8AD5, 0xB4EB, 0x8AD6,
+	0xB4EC, 0xB5EB, 0xB4ED, 0xB5EC, 0xB4EE, 0x8AD7, 0xB4EF, 0xB5ED,
+	0xB4F0, 0x8AD8, 0xB4F1, 0xB5EE, 0xB4F2, 0x8AD9, 0xB4F3, 0x8ADA,
+	0xB4F4, 0x8ADB, 0xB4F5, 0x8ADC, 0xB4F6, 0x8ADD, 0xB4F7, 0x8ADE,
+	0xB4F8, 0xB5EF, 0xB4F9, 0x8ADF, 0xB4FA, 0x8AE0, 0xB4FB, 0x8AE1,
+	0xB4FC, 0x8AE2, 0xB4FD, 0x8AE3, 0xB4FE, 0x8AE4, 0xB4FF, 0x8AE5,
+	0xB500, 0x8AE6, 0xB501, 0x8AE7, 0xB502, 0x8AE8, 0xB503, 0x8AE9,
+	0xB504, 0x8AEA, 0xB505, 0x8AEB, 0xB506, 0x8AEC, 0xB507, 0x8AED,
+	0xB508, 0x8AEE, 0xB509, 0x8AEF, 0xB50A, 0x8AF0, 0xB50B, 0x8AF1,
+	0xB50C, 0x8AF2, 0xB50D, 0x8AF3, 0xB50E, 0x8AF4, 0xB50F, 0x8AF5,
+	0xB510, 0x8AF6, 0xB511, 0x8AF7, 0xB512, 0x8AF8, 0xB513, 0x8AF9,
+	0xB514, 0xB5F0, 0xB515, 0xB5F1, 0xB516, 0x8AFA, 0xB517, 0x8AFB,
+	0xB518, 0xB5F2, 0xB519, 0x8AFC, 0xB51A, 0x8AFD, 0xB51B, 0xB5F3,
+	0xB51C, 0xB5F4, 0xB51D, 0x8AFE, 0xB51E, 0x8B41, 0xB51F, 0x8B42,
+	0xB520, 0x8B43, 0xB521, 0x8B44, 0xB522, 0x8B45, 0xB523, 0x8B46,
+	0xB524, 0xB5F5, 0xB525, 0xB5F6, 0xB526, 0x8B47, 0xB527, 0xB5F7,
+	0xB528, 0xB5F8, 0xB529, 0xB5F9, 0xB52A, 0xB5FA, 0xB52B, 0x8B48,
+	0xB52C, 0x8B49, 0xB52D, 0x8B4A, 0xB52E, 0x8B4B, 0xB52F, 0x8B4C,
+	0xB530, 0xB5FB, 0xB531, 0xB5FC, 0xB532, 0x8B4D, 0xB533, 0x8B4E,
+	0xB534, 0xB5FD, 0xB535, 0x8B4F, 0xB536, 0x8B50, 0xB537, 0x8B51,
+	0xB538, 0xB5FE, 0xB539, 0x8B52, 0xB53A, 0x8B53, 0xB53B, 0x8B54,
+	0xB53C, 0x8B55, 0xB53D, 0x8B56, 0xB53E, 0x8B57, 0xB53F, 0x8B58,
+	0xB540, 0xB6A1, 0xB541, 0xB6A2, 0xB542, 0x8B59, 0xB543, 0xB6A3,
+	0xB544, 0xB6A4, 0xB545, 0xB6A5, 0xB546, 0x8B5A, 0xB547, 0x8B61,
+	0xB548, 0x8B62, 0xB549, 0x8B63, 0xB54A, 0x8B64, 0xB54B, 0xB6A6,
+	0xB54C, 0xB6A7, 0xB54D, 0xB6A8, 0xB54E, 0x8B65, 0xB54F, 0x8B66,
+	0xB550, 0xB6A9, 0xB551, 0x8B67, 0xB552, 0x8B68, 0xB553, 0x8B69,
+	0xB554, 0xB6AA, 0xB555, 0x8B6A, 0xB556, 0x8B6B, 0xB557, 0x8B6C,
+	0xB558, 0x8B6D, 0xB559, 0x8B6E, 0xB55A, 0x8B6F, 0xB55B, 0x8B70,
+	0xB55C, 0xB6AB, 0xB55D, 0xB6AC, 0xB55E, 0x8B71, 0xB55F, 0xB6AD,
+	0xB560, 0xB6AE, 0xB561, 0xB6AF, 0xB562, 0x8B72, 0xB563, 0x8B73,
+	0xB564, 0x8B74, 0xB565, 0x8B75, 0xB566, 0x8B76, 0xB567, 0x8B77,
+	0xB568, 0x8B78, 0xB569, 0x8B79, 0xB56A, 0x8B7A, 0xB56B, 0x8B81,
+	0xB56C, 0x8B82, 0xB56D, 0x8B83, 0xB56E, 0x8B84, 0xB56F, 0x8B85,
+	0xB570, 0x8B86, 0xB571, 0x8B87, 0xB572, 0x8B88, 0xB573, 0x8B89,
+	0xB574, 0x8B8A, 0xB575, 0x8B8B, 0xB576, 0x8B8C, 0xB577, 0x8B8D,
+	0xB578, 0x8B8E, 0xB579, 0x8B8F, 0xB57A, 0x8B90, 0xB57B, 0x8B91,
+	0xB57C, 0x8B92, 0xB57D, 0x8B93, 0xB57E, 0x8B94, 0xB57F, 0x8B95,
+	0xB580, 0x8B96, 0xB581, 0x8B97, 0xB582, 0x8B98, 0xB583, 0x8B99,
+	0xB584, 0x8B9A, 0xB585, 0x8B9B, 0xB586, 0x8B9C, 0xB587, 0x8B9D,
+	0xB588, 0x8B9E, 0xB589, 0x8B9F, 0xB58A, 0x8BA0, 0xB58B, 0x8BA1,
+	0xB58C, 0x8BA2, 0xB58D, 0x8BA3, 0xB58E, 0x8BA4, 0xB58F, 0x8BA5,
+	0xB590, 0x8BA6, 0xB591, 0x8BA7, 0xB592, 0x8BA8, 0xB593, 0x8BA9,
+	0xB594, 0x8BAA, 0xB595, 0x8BAB, 0xB596, 0x8BAC, 0xB597, 0x8BAD,
+	0xB598, 0x8BAE, 0xB599, 0x8BAF, 0xB59A, 0x8BB0, 0xB59B, 0x8BB1,
+	0xB59C, 0x8BB2, 0xB59D, 0x8BB3, 0xB59E, 0x8BB4, 0xB59F, 0x8BB5,
+	0xB5A0, 0xB6B0, 0xB5A1, 0xB6B1, 0xB5A2, 0x8BB6, 0xB5A3, 0x8BB7,
+	0xB5A4, 0xB6B2, 0xB5A5, 0x8BB8, 0xB5A6, 0x8BB9, 0xB5A7, 0x8BBA,
+	0xB5A8, 0xB6B3, 0xB5A9, 0x8BBB, 0xB5AA, 0xB6B4, 0xB5AB, 0xB6B5,
+	0xB5AC, 0x8BBC, 0xB5AD, 0x8BBD, 0xB5AE, 0x8BBE, 0xB5AF, 0x8BBF,
+	0xB5B0, 0xB6B6, 0xB5B1, 0xB6B7, 0xB5B2, 0x8BC0, 0xB5B3, 0xB6B8,
+	0xB5B4, 0xB6B9, 0xB5B5, 0xB6BA, 0xB5B6, 0x8BC1, 0xB5B7, 0x8BC2,
+	0xB5B8, 0x8BC3, 0xB5B9, 0x8BC4, 0xB5BA, 0x8BC5, 0xB5BB, 0xB6BB,
+	0xB5BC, 0xB6BC, 0xB5BD, 0xB6BD, 0xB5BE, 0x8BC6, 0xB5BF, 0x8BC7,
+	0xB5C0, 0xB6BE, 0xB5C1, 0x8BC8, 0xB5C2, 0x8BC9, 0xB5C3, 0x8BCA,
+	0xB5C4, 0xB6BF, 0xB5C5, 0x8BCB, 0xB5C6, 0x8BCC, 0xB5C7, 0x8BCD,
+	0xB5C8, 0x8BCE, 0xB5C9, 0x8BCF, 0xB5CA, 0x8BD0, 0xB5CB, 0x8BD1,
+	0xB5CC, 0xB6C0, 0xB5CD, 0xB6C1, 0xB5CE, 0x8BD2, 0xB5CF, 0xB6C2,
+	0xB5D0, 0xB6C3, 0xB5D1, 0xB6C4, 0xB5D2, 0x8BD3, 0xB5D3, 0x8BD4,
+	0xB5D4, 0x8BD5, 0xB5D5, 0x8BD6, 0xB5D6, 0x8BD7, 0xB5D7, 0x8BD8,
+	0xB5D8, 0xB6C5, 0xB5D9, 0x8BD9, 0xB5DA, 0x8BDA, 0xB5DB, 0x8BDB,
+	0xB5DC, 0x8BDC, 0xB5DD, 0x8BDD, 0xB5DE, 0x8BDE, 0xB5DF, 0x8BDF,
+	0xB5E0, 0x8BE0, 0xB5E1, 0x8BE1, 0xB5E2, 0x8BE2, 0xB5E3, 0x8BE3,
+	0xB5E4, 0x8BE4, 0xB5E5, 0x8BE5, 0xB5E6, 0x8BE6, 0xB5E7, 0x8BE7,
+	0xB5E8, 0x8BE8, 0xB5E9, 0x8BE9, 0xB5EA, 0x8BEA, 0xB5EB, 0x8BEB,
+	0xB5EC, 0xB6C6, 0xB5ED, 0x8BEC, 0xB5EE, 0x8BED, 0xB5EF, 0x8BEE,
+	0xB5F0, 0x8BEF, 0xB5F1, 0x8BF0, 0xB5F2, 0x8BF1, 0xB5F3, 0x8BF2,
+	0xB5F4, 0x8BF3, 0xB5F5, 0x8BF4, 0xB5F6, 0x8BF5, 0xB5F7, 0x8BF6,
+	0xB5F8, 0x8BF7, 0xB5F9, 0x8BF8, 0xB5FA, 0x8BF9, 0xB5FB, 0x8BFA,
+	0xB5FC, 0x8BFB, 0xB5FD, 0x8BFC, 0xB5FE, 0x8BFD, 0xB5FF, 0x8BFE,
+	0xB600, 0x8C41, 0xB601, 0x8C42, 0xB602, 0x8C43, 0xB603, 0x8C44,
+	0xB604, 0x8C45, 0xB605, 0x8C46, 0xB606, 0x8C47, 0xB607, 0x8C48,
+	0xB608, 0x8C49, 0xB609, 0x8C4A, 0xB60A, 0x8C4B, 0xB60B, 0x8C4C,
+	0xB60C, 0x8C4D, 0xB60D, 0x8C4E, 0xB60E, 0x8C4F, 0xB60F, 0x8C50,
+	0xB610, 0xB6C7, 0xB611, 0xB6C8, 0xB612, 0x8C51, 0xB613, 0x8C52,
+	0xB614, 0xB6C9, 0xB615, 0x8C53, 0xB616, 0x8C54, 0xB617, 0x8C55,
+	0xB618, 0xB6CA, 0xB619, 0x8C56, 0xB61A, 0x8C57, 0xB61B, 0x8C58,
+	0xB61C, 0x8C59, 0xB61D, 0x8C5A, 0xB61E, 0x8C61, 0xB61F, 0x8C62,
+	0xB620, 0x8C63, 0xB621, 0x8C64, 0xB622, 0x8C65, 0xB623, 0x8C66,
+	0xB624, 0x8C67, 0xB625, 0xB6CB, 0xB626, 0x8C68, 0xB627, 0x8C69,
+	0xB628, 0x8C6A, 0xB629, 0x8C6B, 0xB62A, 0x8C6C, 0xB62B, 0x8C6D,
+	0xB62C, 0xB6CC, 0xB62D, 0x8C6E, 0xB62E, 0x8C6F, 0xB62F, 0x8C70,
+	0xB630, 0x8C71, 0xB631, 0x8C72, 0xB632, 0x8C73, 0xB633, 0x8C74,
+	0xB634, 0xB6CD, 0xB635, 0x8C75, 0xB636, 0x8C76, 0xB637, 0x8C77,
+	0xB638, 0x8C78, 0xB639, 0x8C79, 0xB63A, 0x8C7A, 0xB63B, 0x8C81,
+	0xB63C, 0x8C82, 0xB63D, 0x8C83, 0xB63E, 0x8C84, 0xB63F, 0x8C85,
+	0xB640, 0x8C86, 0xB641, 0x8C87, 0xB642, 0x8C88, 0xB643, 0x8C89,
+	0xB644, 0x8C8A, 0xB645, 0x8C8B, 0xB646, 0x8C8C, 0xB647, 0x8C8D,
+	0xB648, 0xB6CE, 0xB649, 0x8C8E, 0xB64A, 0x8C8F, 0xB64B, 0x8C90,
+	0xB64C, 0x8C91, 0xB64D, 0x8C92, 0xB64E, 0x8C93, 0xB64F, 0x8C94,
+	0xB650, 0x8C95, 0xB651, 0x8C96, 0xB652, 0x8C97, 0xB653, 0x8C98,
+	0xB654, 0x8C99, 0xB655, 0x8C9A, 0xB656, 0x8C9B, 0xB657, 0x8C9C,
+	0xB658, 0x8C9D, 0xB659, 0x8C9E, 0xB65A, 0x8C9F, 0xB65B, 0x8CA0,
+	0xB65C, 0x8CA1, 0xB65D, 0x8CA2, 0xB65E, 0x8CA3, 0xB65F, 0x8CA4,
+	0xB660, 0x8CA5, 0xB661, 0x8CA6, 0xB662, 0x8CA7, 0xB663, 0x8CA8,
+	0xB664, 0xB6CF, 0xB665, 0x8CA9, 0xB666, 0x8CAA, 0xB667, 0x8CAB,
+	0xB668, 0xB6D0, 0xB669, 0x8CAC, 0xB66A, 0x8CAD, 0xB66B, 0x8CAE,
+	0xB66C, 0x8CAF, 0xB66D, 0x8CB0, 0xB66E, 0x8CB1, 0xB66F, 0x8CB2,
+	0xB670, 0x8CB3, 0xB671, 0x8CB4, 0xB672, 0x8CB5, 0xB673, 0x8CB6,
+	0xB674, 0x8CB7, 0xB675, 0x8CB8, 0xB676, 0x8CB9, 0xB677, 0x8CBA,
+	0xB678, 0x8CBB, 0xB679, 0x8CBC, 0xB67A, 0x8CBD, 0xB67B, 0x8CBE,
+	0xB67C, 0x8CBF, 0xB67D, 0x8CC0, 0xB67E, 0x8CC1, 0xB67F, 0x8CC2,
+	0xB680, 0x8CC3, 0xB681, 0x8CC4, 0xB682, 0x8CC5, 0xB683, 0x8CC6,
+	0xB684, 0x8CC7, 0xB685, 0x8CC8, 0xB686, 0x8CC9, 0xB687, 0x8CCA,
+	0xB688, 0x8CCB, 0xB689, 0x8CCC, 0xB68A, 0x8CCD, 0xB68B, 0x8CCE,
+	0xB68C, 0x8CCF, 0xB68D, 0x8CD0, 0xB68E, 0x8CD1, 0xB68F, 0x8CD2,
+	0xB690, 0x8CD3, 0xB691, 0x8CD4, 0xB692, 0x8CD5, 0xB693, 0x8CD6,
+	0xB694, 0x8CD7, 0xB695, 0x8CD8, 0xB696, 0x8CD9, 0xB697, 0x8CDA,
+	0xB698, 0x8CDB, 0xB699, 0x8CDC, 0xB69A, 0x8CDD, 0xB69B, 0x8CDE,
+	0xB69C, 0xB6D1, 0xB69D, 0xB6D2, 0xB69E, 0x8CDF, 0xB69F, 0x8CE0,
+	0xB6A0, 0xB6D3, 0xB6A1, 0x8CE1, 0xB6A2, 0x8CE2, 0xB6A3, 0x8CE3,
+	0xB6A4, 0xB6D4, 0xB6A5, 0x8CE4, 0xB6A6, 0x8CE5, 0xB6A7, 0x8CE6,
+	0xB6A8, 0x8CE7, 0xB6A9, 0x8CE8, 0xB6AA, 0x8CE9, 0xB6AB, 0xB6D5,
+	0xB6AC, 0xB6D6, 0xB6AD, 0x8CEA, 0xB6AE, 0x8CEB, 0xB6AF, 0x8CEC,
+	0xB6B0, 0x8CED, 0xB6B1, 0xB6D7, 0xB6B2, 0x8CEE, 0xB6B3, 0x8CEF,
+	0xB6B4, 0x8CF0, 0xB6B5, 0x8CF1, 0xB6B6, 0x8CF2, 0xB6B7, 0x8CF3,
+	0xB6B8, 0x8CF4, 0xB6B9, 0x8CF5, 0xB6BA, 0x8CF6, 0xB6BB, 0x8CF7,
+	0xB6BC, 0x8CF8, 0xB6BD, 0x8CF9, 0xB6BE, 0x8CFA, 0xB6BF, 0x8CFB,
+	0xB6C0, 0x8CFC, 0xB6C1, 0x8CFD, 0xB6C2, 0x8CFE, 0xB6C3, 0x8D41,
+	0xB6C4, 0x8D42, 0xB6C5, 0x8D43, 0xB6C6, 0x8D44, 0xB6C7, 0x8D45,
+	0xB6C8, 0x8D46, 0xB6C9, 0x8D47, 0xB6CA, 0x8D48, 0xB6CB, 0x8D49,
+	0xB6CC, 0x8D4A, 0xB6CD, 0x8D4B, 0xB6CE, 0x8D4C, 0xB6CF, 0x8D4D,
+	0xB6D0, 0x8D4E, 0xB6D1, 0x8D4F, 0xB6D2, 0x8D50, 0xB6D3, 0x8D51,
+	0xB6D4, 0xB6D8, 0xB6D5, 0x8D52, 0xB6D6, 0x8D53, 0xB6D7, 0x8D54,
+	0xB6D8, 0x8D55, 0xB6D9, 0x8D56, 0xB6DA, 0x8D57, 0xB6DB, 0x8D58,
+	0xB6DC, 0x8D59, 0xB6DD, 0x8D5A, 0xB6DE, 0x8D61, 0xB6DF, 0x8D62,
+	0xB6E0, 0x8D63, 0xB6E1, 0x8D64, 0xB6E2, 0x8D65, 0xB6E3, 0x8D66,
+	0xB6E4, 0x8D67, 0xB6E5, 0x8D68, 0xB6E6, 0x8D69, 0xB6E7, 0x8D6A,
+	0xB6E8, 0x8D6B, 0xB6E9, 0x8D6C, 0xB6EA, 0x8D6D, 0xB6EB, 0x8D6E,
+	0xB6EC, 0x8D6F, 0xB6ED, 0x8D70, 0xB6EE, 0x8D71, 0xB6EF, 0x8D72,
+	0xB6F0, 0xB6D9, 0xB6F1, 0x8D73, 0xB6F2, 0x8D74, 0xB6F3, 0x8D75,
+	0xB6F4, 0xB6DA, 0xB6F5, 0x8D76, 0xB6F6, 0x8D77, 0xB6F7, 0x8D78,
+	0xB6F8, 0xB6DB, 0xB6F9, 0x8D79, 0xB6FA, 0x8D7A, 0xB6FB, 0x8D81,
+	0xB6FC, 0x8D82, 0xB6FD, 0x8D83, 0xB6FE, 0x8D84, 0xB6FF, 0x8D85,
+	0xB700, 0xB6DC, 0xB701, 0xB6DD, 0xB702, 0x8D86, 0xB703, 0x8D87,
+	0xB704, 0x8D88, 0xB705, 0xB6DE, 0xB706, 0x8D89, 0xB707, 0x8D8A,
+	0xB708, 0x8D8B, 0xB709, 0x8D8C, 0xB70A, 0x8D8D, 0xB70B, 0x8D8E,
+	0xB70C, 0x8D8F, 0xB70D, 0x8D90, 0xB70E, 0x8D91, 0xB70F, 0x8D92,
+	0xB710, 0x8D93, 0xB711, 0x8D94, 0xB712, 0x8D95, 0xB713, 0x8D96,
+	0xB714, 0x8D97, 0xB715, 0x8D98, 0xB716, 0x8D99, 0xB717, 0x8D9A,
+	0xB718, 0x8D9B, 0xB719, 0x8D9C, 0xB71A, 0x8D9D, 0xB71B, 0x8D9E,
+	0xB71C, 0x8D9F, 0xB71D, 0x8DA0, 0xB71E, 0x8DA1, 0xB71F, 0x8DA2,
+	0xB720, 0x8DA3, 0xB721, 0x8DA4, 0xB722, 0x8DA5, 0xB723, 0x8DA6,
+	0xB724, 0x8DA7, 0xB725, 0x8DA8, 0xB726, 0x8DA9, 0xB727, 0x8DAA,
+	0xB728, 0xB6DF, 0xB729, 0xB6E0, 0xB72A, 0x8DAB, 0xB72B, 0x8DAC,
+	0xB72C, 0xB6E1, 0xB72D, 0x8DAD, 0xB72E, 0x8DAE, 0xB72F, 0xB6E2,
+	0xB730, 0xB6E3, 0xB731, 0x8DAF, 0xB732, 0x8DB0, 0xB733, 0x8DB1,
+	0xB734, 0x8DB2, 0xB735, 0x8DB3, 0xB736, 0x8DB4, 0xB737, 0x8DB5,
+	0xB738, 0xB6E4, 0xB739, 0xB6E5, 0xB73A, 0x8DB6, 0xB73B, 0xB6E6,
+	0xB73C, 0x8DB7, 0xB73D, 0x8DB8, 0xB73E, 0x8DB9, 0xB73F, 0x8DBA,
+	0xB740, 0x8DBB, 0xB741, 0x8DBC, 0xB742, 0x8DBD, 0xB743, 0x8DBE,
+	0xB744, 0xB6E7, 0xB745, 0x8DBF, 0xB746, 0x8DC0, 0xB747, 0x8DC1,
+	0xB748, 0xB6E8, 0xB749, 0x8DC2, 0xB74A, 0x8DC3, 0xB74B, 0x8DC4,
+	0xB74C, 0xB6E9, 0xB74D, 0x8DC5, 0xB74E, 0x8DC6, 0xB74F, 0x8DC7,
+	0xB750, 0x8DC8, 0xB751, 0x8DC9, 0xB752, 0x8DCA, 0xB753, 0x8DCB,
+	0xB754, 0xB6EA, 0xB755, 0xB6EB, 0xB756, 0x8DCC, 0xB757, 0x8DCD,
+	0xB758, 0x8DCE, 0xB759, 0x8DCF, 0xB75A, 0x8DD0, 0xB75B, 0x8DD1,
+	0xB75C, 0x8DD2, 0xB75D, 0x8DD3, 0xB75E, 0x8DD4, 0xB75F, 0x8DD5,
+	0xB760, 0xB6EC, 0xB761, 0x8DD6, 0xB762, 0x8DD7, 0xB763, 0x8DD8,
+	0xB764, 0xB6ED, 0xB765, 0x8DD9, 0xB766, 0x8DDA, 0xB767, 0x8DDB,
+	0xB768, 0xB6EE, 0xB769, 0x8DDC, 0xB76A, 0x8DDD, 0xB76B, 0x8DDE,
+	0xB76C, 0x8DDF, 0xB76D, 0x8DE0, 0xB76E, 0x8DE1, 0xB76F, 0x8DE2,
+	0xB770, 0xB6EF, 0xB771, 0xB6F0, 0xB772, 0x8DE3, 0xB773, 0xB6F1,
+	0xB774, 0x8DE4, 0xB775, 0xB6F2, 0xB776, 0x8DE5, 0xB777, 0x8DE6,
+	0xB778, 0x8DE7, 0xB779, 0x8DE8, 0xB77A, 0x8DE9, 0xB77B, 0x8DEA,
+	0xB77C, 0xB6F3, 0xB77D, 0xB6F4, 0xB77E, 0x8DEB, 0xB77F, 0x8DEC,
+	0xB780, 0xB6F5, 0xB781, 0x8DED, 0xB782, 0x8DEE, 0xB783, 0x8DEF,
+	0xB784, 0xB6F6, 0xB785, 0x8DF0, 0xB786, 0x8DF1, 0xB787, 0x8DF2,
+	0xB788, 0x8DF3, 0xB789, 0x8DF4, 0xB78A, 0x8DF5, 0xB78B, 0x8DF6,
+	0xB78C, 0xB6F7, 0xB78D, 0xB6F8, 0xB78E, 0x8DF7, 0xB78F, 0xB6F9,
+	0xB790, 0xB6FA, 0xB791, 0xB6FB, 0xB792, 0xB6FC, 0xB793, 0x8DF8,
+	0xB794, 0x8DF9, 0xB795, 0x8DFA, 0xB796, 0xB6FD, 0xB797, 0xB6FE,
+	0xB798, 0xB7A1, 0xB799, 0xB7A2, 0xB79A, 0x8DFB, 0xB79B, 0x8DFC,
+	0xB79C, 0xB7A3, 0xB79D, 0x8DFD, 0xB79E, 0x8DFE, 0xB79F, 0x8E41,
+	0xB7A0, 0xB7A4, 0xB7A1, 0x8E42, 0xB7A2, 0x8E43, 0xB7A3, 0x8E44,
+	0xB7A4, 0x8E45, 0xB7A5, 0x8E46, 0xB7A6, 0x8E47, 0xB7A7, 0x8E48,
+	0xB7A8, 0xB7A5, 0xB7A9, 0xB7A6, 0xB7AA, 0x8E49, 0xB7AB, 0xB7A7,
+	0xB7AC, 0xB7A8, 0xB7AD, 0xB7A9, 0xB7AE, 0x8E4A, 0xB7AF, 0x8E4B,
+	0xB7B0, 0x8E4C, 0xB7B1, 0x8E4D, 0xB7B2, 0x8E4E, 0xB7B3, 0x8E4F,
+	0xB7B4, 0xB7AA, 0xB7B5, 0xB7AB, 0xB7B6, 0x8E50, 0xB7B7, 0x8E51,
+	0xB7B8, 0xB7AC, 0xB7B9, 0x8E52, 0xB7BA, 0x8E53, 0xB7BB, 0x8E54,
+	0xB7BC, 0x8E55, 0xB7BD, 0x8E56, 0xB7BE, 0x8E57, 0xB7BF, 0x8E58,
+	0xB7C0, 0x8E59, 0xB7C1, 0x8E5A, 0xB7C2, 0x8E61, 0xB7C3, 0x8E62,
+	0xB7C4, 0x8E63, 0xB7C5, 0x8E64, 0xB7C6, 0x8E65, 0xB7C7, 0xB7AD,
+	0xB7C8, 0x8E66, 0xB7C9, 0xB7AE, 0xB7CA, 0x8E67, 0xB7CB, 0x8E68,
+	0xB7CC, 0x8E69, 0xB7CD, 0x8E6A, 0xB7CE, 0x8E6B, 0xB7CF, 0x8E6C,
+	0xB7D0, 0x8E6D, 0xB7D1, 0x8E6E, 0xB7D2, 0x8E6F, 0xB7D3, 0x8E70,
+	0xB7D4, 0x8E71, 0xB7D5, 0x8E72, 0xB7D6, 0x8E73, 0xB7D7, 0x8E74,
+	0xB7D8, 0x8E75, 0xB7D9, 0x8E76, 0xB7DA, 0x8E77, 0xB7DB, 0x8E78,
+	0xB7DC, 0x8E79, 0xB7DD, 0x8E7A, 0xB7DE, 0x8E81, 0xB7DF, 0x8E82,
+	0xB7E0, 0x8E83, 0xB7E1, 0x8E84, 0xB7E2, 0x8E85, 0xB7E3, 0x8E86,
+	0xB7E4, 0x8E87, 0xB7E5, 0x8E88, 0xB7E6, 0x8E89, 0xB7E7, 0x8E8A,
+	0xB7E8, 0x8E8B, 0xB7E9, 0x8E8C, 0xB7EA, 0x8E8D, 0xB7EB, 0x8E8E,
+	0xB7EC, 0xB7AF, 0xB7ED, 0xB7B0, 0xB7EE, 0x8E8F, 0xB7EF, 0x8E90,
+	0xB7F0, 0xB7B1, 0xB7F1, 0x8E91, 0xB7F2, 0x8E92, 0xB7F3, 0x8E93,
+	0xB7F4, 0xB7B2, 0xB7F5, 0x8E94, 0xB7F6, 0x8E95, 0xB7F7, 0x8E96,
+	0xB7F8, 0x8E97, 0xB7F9, 0x8E98, 0xB7FA, 0x8E99, 0xB7FB, 0x8E9A,
+	0xB7FC, 0xB7B3, 0xB7FD, 0xB7B4, 0xB7FE, 0x8E9B, 0xB7FF, 0xB7B5,
+	0xB800, 0xB7B6, 0xB801, 0xB7B7, 0xB802, 0x8E9C, 0xB803, 0x8E9D,
+	0xB804, 0x8E9E, 0xB805, 0x8E9F, 0xB806, 0x8EA0, 0xB807, 0xB7B8,
+	0xB808, 0xB7B9, 0xB809, 0xB7BA, 0xB80A, 0x8EA1, 0xB80B, 0x8EA2,
+	0xB80C, 0xB7BB, 0xB80D, 0x8EA3, 0xB80E, 0x8EA4, 0xB80F, 0x8EA5,
+	0xB810, 0xB7BC, 0xB811, 0x8EA6, 0xB812, 0x8EA7, 0xB813, 0x8EA8,
+	0xB814, 0x8EA9, 0xB815, 0x8EAA, 0xB816, 0x8EAB, 0xB817, 0x8EAC,
+	0xB818, 0xB7BD, 0xB819, 0xB7BE, 0xB81A, 0x8EAD, 0xB81B, 0xB7BF,
+	0xB81C, 0x8EAE, 0xB81D, 0xB7C0, 0xB81E, 0x8EAF, 0xB81F, 0x8EB0,
+	0xB820, 0x8EB1, 0xB821, 0x8EB2, 0xB822, 0x8EB3, 0xB823, 0x8EB4,
+	0xB824, 0xB7C1, 0xB825, 0xB7C2, 0xB826, 0x8EB5, 0xB827, 0x8EB6,
+	0xB828, 0xB7C3, 0xB829, 0x8EB7, 0xB82A, 0x8EB8, 0xB82B, 0x8EB9,
+	0xB82C, 0xB7C4, 0xB82D, 0x8EBA, 0xB82E, 0x8EBB, 0xB82F, 0x8EBC,
+	0xB830, 0x8EBD, 0xB831, 0x8EBE, 0xB832, 0x8EBF, 0xB833, 0x8EC0,
+	0xB834, 0xB7C5, 0xB835, 0xB7C6, 0xB836, 0x8EC1, 0xB837, 0xB7C7,
+	0xB838, 0xB7C8, 0xB839, 0xB7C9, 0xB83A, 0x8EC2, 0xB83B, 0x8EC3,
+	0xB83C, 0x8EC4, 0xB83D, 0x8EC5, 0xB83E, 0x8EC6, 0xB83F, 0x8EC7,
+	0xB840, 0xB7CA, 0xB841, 0x8EC8, 0xB842, 0x8EC9, 0xB843, 0x8ECA,
+	0xB844, 0xB7CB, 0xB845, 0x8ECB, 0xB846, 0x8ECC, 0xB847, 0x8ECD,
+	0xB848, 0x8ECE, 0xB849, 0x8ECF, 0xB84A, 0x8ED0, 0xB84B, 0x8ED1,
+	0xB84C, 0x8ED2, 0xB84D, 0x8ED3, 0xB84E, 0x8ED4, 0xB84F, 0x8ED5,
+	0xB850, 0x8ED6, 0xB851, 0xB7CC, 0xB852, 0x8ED7, 0xB853, 0xB7CD,
+	0xB854, 0x8ED8, 0xB855, 0x8ED9, 0xB856, 0x8EDA, 0xB857, 0x8EDB,
+	0xB858, 0x8EDC, 0xB859, 0x8EDD, 0xB85A, 0x8EDE, 0xB85B, 0x8EDF,
+	0xB85C, 0xB7CE, 0xB85D, 0xB7CF, 0xB85E, 0x8EE0, 0xB85F, 0x8EE1,
+	0xB860, 0xB7D0, 0xB861, 0x8EE2, 0xB862, 0x8EE3, 0xB863, 0x8EE4,
+	0xB864, 0xB7D1, 0xB865, 0x8EE5, 0xB866, 0x8EE6, 0xB867, 0x8EE7,
+	0xB868, 0x8EE8, 0xB869, 0x8EE9, 0xB86A, 0x8EEA, 0xB86B, 0x8EEB,
+	0xB86C, 0xB7D2, 0xB86D, 0xB7D3, 0xB86E, 0x8EEC, 0xB86F, 0xB7D4,
+	0xB870, 0x8EED, 0xB871, 0xB7D5, 0xB872, 0x8EEE, 0xB873, 0x8EEF,
+	0xB874, 0x8EF0, 0xB875, 0x8EF1, 0xB876, 0x8EF2, 0xB877, 0x8EF3,
+	0xB878, 0xB7D6, 0xB879, 0x8EF4, 0xB87A, 0x8EF5, 0xB87B, 0x8EF6,
+	0xB87C, 0xB7D7, 0xB87D, 0x8EF7, 0xB87E, 0x8EF8, 0xB87F, 0x8EF9,
+	0xB880, 0x8EFA, 0xB881, 0x8EFB, 0xB882, 0x8EFC, 0xB883, 0x8EFD,
+	0xB884, 0x8EFE, 0xB885, 0x8F41, 0xB886, 0x8F42, 0xB887, 0x8F43,
+	0xB888, 0x8F44, 0xB889, 0x8F45, 0xB88A, 0x8F46, 0xB88B, 0x8F47,
+	0xB88C, 0x8F48, 0xB88D, 0xB7D8, 0xB88E, 0x8F49, 0xB88F, 0x8F4A,
+	0xB890, 0x8F4B, 0xB891, 0x8F4C, 0xB892, 0x8F4D, 0xB893, 0x8F4E,
+	0xB894, 0x8F4F, 0xB895, 0x8F50, 0xB896, 0x8F51, 0xB897, 0x8F52,
+	0xB898, 0x8F53, 0xB899, 0x8F54, 0xB89A, 0x8F55, 0xB89B, 0x8F56,
+	0xB89C, 0x8F57, 0xB89D, 0x8F58, 0xB89E, 0x8F59, 0xB89F, 0x8F5A,
+	0xB8A0, 0x8F61, 0xB8A1, 0x8F62, 0xB8A2, 0x8F63, 0xB8A3, 0x8F64,
+	0xB8A4, 0x8F65, 0xB8A5, 0x8F66, 0xB8A6, 0x8F67, 0xB8A7, 0x8F68,
+	0xB8A8, 0xB7D9, 0xB8A9, 0x8F69, 0xB8AA, 0x8F6A, 0xB8AB, 0x8F6B,
+	0xB8AC, 0x8F6C, 0xB8AD, 0x8F6D, 0xB8AE, 0x8F6E, 0xB8AF, 0x8F6F,
+	0xB8B0, 0xB7DA, 0xB8B1, 0x8F70, 0xB8B2, 0x8F71, 0xB8B3, 0x8F72,
+	0xB8B4, 0xB7DB, 0xB8B5, 0x8F73, 0xB8B6, 0x8F74, 0xB8B7, 0x8F75,
+	0xB8B8, 0xB7DC, 0xB8B9, 0x8F76, 0xB8BA, 0x8F77, 0xB8BB, 0x8F78,
+	0xB8BC, 0x8F79, 0xB8BD, 0x8F7A, 0xB8BE, 0x8F81, 0xB8BF, 0x8F82,
+	0xB8C0, 0xB7DD, 0xB8C1, 0xB7DE, 0xB8C2, 0x8F83, 0xB8C3, 0xB7DF,
+	0xB8C4, 0x8F84, 0xB8C5, 0xB7E0, 0xB8C6, 0x8F85, 0xB8C7, 0x8F86,
+	0xB8C8, 0x8F87, 0xB8C9, 0x8F88, 0xB8CA, 0x8F89, 0xB8CB, 0x8F8A,
+	0xB8CC, 0xB7E1, 0xB8CD, 0x8F8B, 0xB8CE, 0x8F8C, 0xB8CF, 0x8F8D,
+	0xB8D0, 0xB7E2, 0xB8D1, 0x8F8E, 0xB8D2, 0x8F8F, 0xB8D3, 0x8F90,
+	0xB8D4, 0xB7E3, 0xB8D5, 0x8F91, 0xB8D6, 0x8F92, 0xB8D7, 0x8F93,
+	0xB8D8, 0x8F94, 0xB8D9, 0x8F95, 0xB8DA, 0x8F96, 0xB8DB, 0x8F97,
+	0xB8DC, 0x8F98, 0xB8DD, 0xB7E4, 0xB8DE, 0x8F99, 0xB8DF, 0xB7E5,
+	0xB8E0, 0x8F9A, 0xB8E1, 0xB7E6, 0xB8E2, 0x8F9B, 0xB8E3, 0x8F9C,
+	0xB8E4, 0x8F9D, 0xB8E5, 0x8F9E, 0xB8E6, 0x8F9F, 0xB8E7, 0x8FA0,
+	0xB8E8, 0xB7E7, 0xB8E9, 0xB7E8, 0xB8EA, 0x8FA1, 0xB8EB, 0x8FA2,
+	0xB8EC, 0xB7E9, 0xB8ED, 0x8FA3, 0xB8EE, 0x8FA4, 0xB8EF, 0x8FA5,
+	0xB8F0, 0xB7EA, 0xB8F1, 0x8FA6, 0xB8F2, 0x8FA7, 0xB8F3, 0x8FA8,
+	0xB8F4, 0x8FA9, 0xB8F5, 0x8FAA, 0xB8F6, 0x8FAB, 0xB8F7, 0x8FAC,
+	0xB8F8, 0xB7EB, 0xB8F9, 0xB7EC, 0xB8FA, 0x8FAD, 0xB8FB, 0xB7ED,
+	0xB8FC, 0x8FAE, 0xB8FD, 0xB7EE, 0xB8FE, 0x8FAF, 0xB8FF, 0x8FB0,
+	0xB900, 0x8FB1, 0xB901, 0x8FB2, 0xB902, 0x8FB3, 0xB903, 0x8FB4,
+	0xB904, 0xB7EF, 0xB905, 0x8FB5, 0xB906, 0x8FB6, 0xB907, 0x8FB7,
+	0xB908, 0x8FB8, 0xB909, 0x8FB9, 0xB90A, 0x8FBA, 0xB90B, 0x8FBB,
+	0xB90C, 0x8FBC, 0xB90D, 0x8FBD, 0xB90E, 0x8FBE, 0xB90F, 0x8FBF,
+	0xB910, 0x8FC0, 0xB911, 0x8FC1, 0xB912, 0x8FC2, 0xB913, 0x8FC3,
+	0xB914, 0x8FC4, 0xB915, 0x8FC5, 0xB916, 0x8FC6, 0xB917, 0x8FC7,
+	0xB918, 0xB7F0, 0xB919, 0x8FC8, 0xB91A, 0x8FC9, 0xB91B, 0x8FCA,
+	0xB91C, 0x8FCB, 0xB91D, 0x8FCC, 0xB91E, 0x8FCD, 0xB91F, 0x8FCE,
+	0xB920, 0xB7F1, 0xB921, 0x8FCF, 0xB922, 0x8FD0, 0xB923, 0x8FD1,
+	0xB924, 0x8FD2, 0xB925, 0x8FD3, 0xB926, 0x8FD4, 0xB927, 0x8FD5,
+	0xB928, 0x8FD6, 0xB929, 0x8FD7, 0xB92A, 0x8FD8, 0xB92B, 0x8FD9,
+	0xB92C, 0x8FDA, 0xB92D, 0x8FDB, 0xB92E, 0x8FDC, 0xB92F, 0x8FDD,
+	0xB930, 0x8FDE, 0xB931, 0x8FDF, 0xB932, 0x8FE0, 0xB933, 0x8FE1,
+	0xB934, 0x8FE2, 0xB935, 0x8FE3, 0xB936, 0x8FE4, 0xB937, 0x8FE5,
+	0xB938, 0x8FE6, 0xB939, 0x8FE7, 0xB93A, 0x8FE8, 0xB93B, 0x8FE9,
+	0xB93C, 0xB7F2, 0xB93D, 0xB7F3, 0xB93E, 0x8FEA, 0xB93F, 0x8FEB,
+	0xB940, 0xB7F4, 0xB941, 0x8FEC, 0xB942, 0x8FED, 0xB943, 0x8FEE,
+	0xB944, 0xB7F5, 0xB945, 0x8FEF, 0xB946, 0x8FF0, 0xB947, 0x8FF1,
+	0xB948, 0x8FF2, 0xB949, 0x8FF3, 0xB94A, 0x8FF4, 0xB94B, 0x8FF5,
+	0xB94C, 0xB7F6, 0xB94D, 0x8FF6, 0xB94E, 0x8FF7, 0xB94F, 0xB7F7,
+	0xB950, 0x8FF8, 0xB951, 0xB7F8, 0xB952, 0x8FF9, 0xB953, 0x8FFA,
+	0xB954, 0x8FFB, 0xB955, 0x8FFC, 0xB956, 0x8FFD, 0xB957, 0x8FFE,
+	0xB958, 0xB7F9, 0xB959, 0xB7FA, 0xB95A, 0x9041, 0xB95B, 0x9042,
+	0xB95C, 0xB7FB, 0xB95D, 0x9043, 0xB95E, 0x9044, 0xB95F, 0x9045,
+	0xB960, 0xB7FC, 0xB961, 0x9046, 0xB962, 0x9047, 0xB963, 0x9048,
+	0xB964, 0x9049, 0xB965, 0x904A, 0xB966, 0x904B, 0xB967, 0x904C,
+	0xB968, 0xB7FD, 0xB969, 0xB7FE, 0xB96A, 0x904D, 0xB96B, 0xB8A1,
+	0xB96C, 0x904E, 0xB96D, 0xB8A2, 0xB96E, 0x904F, 0xB96F, 0x9050,
+	0xB970, 0x9051, 0xB971, 0x9052, 0xB972, 0x9053, 0xB973, 0x9054,
+	0xB974, 0xB8A3, 0xB975, 0xB8A4, 0xB976, 0x9055, 0xB977, 0x9056,
+	0xB978, 0xB8A5, 0xB979, 0x9057, 0xB97A, 0x9058, 0xB97B, 0x9059,
+	0xB97C, 0xB8A6, 0xB97D, 0x905A, 0xB97E, 0x9061, 0xB97F, 0x9062,
+	0xB980, 0x9063, 0xB981, 0x9064, 0xB982, 0x9065, 0xB983, 0x9066,
+	0xB984, 0xB8A7, 0xB985, 0xB8A8, 0xB986, 0x9067, 0xB987, 0xB8A9,
+	0xB988, 0x9068, 0xB989, 0xB8AA, 0xB98A, 0xB8AB, 0xB98B, 0x9069,
+	0xB98C, 0x906A, 0xB98D, 0xB8AC, 0xB98E, 0xB8AD, 0xB98F, 0x906B,
+	0xB990, 0x906C, 0xB991, 0x906D, 0xB992, 0x906E, 0xB993, 0x906F,
+	0xB994, 0x9070, 0xB995, 0x9071, 0xB996, 0x9072, 0xB997, 0x9073,
+	0xB998, 0x9074, 0xB999, 0x9075, 0xB99A, 0x9076, 0xB99B, 0x9077,
+	0xB99C, 0x9078, 0xB99D, 0x9079, 0xB99E, 0x907A, 0xB99F, 0x9081,
+	0xB9A0, 0x9082, 0xB9A1, 0x9083, 0xB9A2, 0x9084, 0xB9A3, 0x9085,
+	0xB9A4, 0x9086, 0xB9A5, 0x9087, 0xB9A6, 0x9088, 0xB9A7, 0x9089,
+	0xB9A8, 0x908A, 0xB9A9, 0x908B, 0xB9AA, 0x908C, 0xB9AB, 0x908D,
+	0xB9AC, 0xB8AE, 0xB9AD, 0xB8AF, 0xB9AE, 0x908E, 0xB9AF, 0x908F,
+	0xB9B0, 0xB8B0, 0xB9B1, 0x9090, 0xB9B2, 0x9091, 0xB9B3, 0x9092,
+	0xB9B4, 0xB8B1, 0xB9B5, 0x9093, 0xB9B6, 0x9094, 0xB9B7, 0x9095,
+	0xB9B8, 0x9096, 0xB9B9, 0x9097, 0xB9BA, 0x9098, 0xB9BB, 0x9099,
+	0xB9BC, 0xB8B2, 0xB9BD, 0xB8B3, 0xB9BE, 0x909A, 0xB9BF, 0xB8B4,
+	0xB9C0, 0x909B, 0xB9C1, 0xB8B5, 0xB9C2, 0x909C, 0xB9C3, 0x909D,
+	0xB9C4, 0x909E, 0xB9C5, 0x909F, 0xB9C6, 0x90A0, 0xB9C7, 0x90A1,
+	0xB9C8, 0xB8B6, 0xB9C9, 0xB8B7, 0xB9CA, 0x90A2, 0xB9CB, 0x90A3,
+	0xB9CC, 0xB8B8, 0xB9CD, 0x90A4, 0xB9CE, 0xB8B9, 0xB9CF, 0xB8BA,
+	0xB9D0, 0xB8BB, 0xB9D1, 0xB8BC, 0xB9D2, 0xB8BD, 0xB9D3, 0x90A5,
+	0xB9D4, 0x90A6, 0xB9D5, 0x90A7, 0xB9D6, 0x90A8, 0xB9D7, 0x90A9,
+	0xB9D8, 0xB8BE, 0xB9D9, 0xB8BF, 0xB9DA, 0x90AA, 0xB9DB, 0xB8C0,
+	0xB9DC, 0x90AB, 0xB9DD, 0xB8C1, 0xB9DE, 0xB8C2, 0xB9DF, 0x90AC,
+	0xB9E0, 0x90AD, 0xB9E1, 0xB8C3, 0xB9E2, 0x90AE, 0xB9E3, 0xB8C4,
+	0xB9E4, 0xB8C5, 0xB9E5, 0xB8C6, 0xB9E6, 0x90AF, 0xB9E7, 0x90B0,
+	0xB9E8, 0xB8C7, 0xB9E9, 0x90B1, 0xB9EA, 0x90B2, 0xB9EB, 0x90B3,
+	0xB9EC, 0xB8C8, 0xB9ED, 0x90B4, 0xB9EE, 0x90B5, 0xB9EF, 0x90B6,
+	0xB9F0, 0x90B7, 0xB9F1, 0x90B8, 0xB9F2, 0x90B9, 0xB9F3, 0x90BA,
+	0xB9F4, 0xB8C9, 0xB9F5, 0xB8CA, 0xB9F6, 0x90BB, 0xB9F7, 0xB8CB,
+	0xB9F8, 0xB8CC, 0xB9F9, 0xB8CD, 0xB9FA, 0xB8CE, 0xB9FB, 0x90BC,
+	0xB9FC, 0x90BD, 0xB9FD, 0x90BE, 0xB9FE, 0x90BF, 0xB9FF, 0x90C0,
+	0xBA00, 0xB8CF, 0xBA01, 0xB8D0, 0xBA02, 0x90C1, 0xBA03, 0x90C2,
+	0xBA04, 0x90C3, 0xBA05, 0x90C4, 0xBA06, 0x90C5, 0xBA07, 0x90C6,
+	0xBA08, 0xB8D1, 0xBA09, 0x90C7, 0xBA0A, 0x90C8, 0xBA0B, 0x90C9,
+	0xBA0C, 0x90CA, 0xBA0D, 0x90CB, 0xBA0E, 0x90CC, 0xBA0F, 0x90CD,
+	0xBA10, 0x90CE, 0xBA11, 0x90CF, 0xBA12, 0x90D0, 0xBA13, 0x90D1,
+	0xBA14, 0x90D2, 0xBA15, 0xB8D2, 0xBA16, 0x90D3, 0xBA17, 0x90D4,
+	0xBA18, 0x90D5, 0xBA19, 0x90D6, 0xBA1A, 0x90D7, 0xBA1B, 0x90D8,
+	0xBA1C, 0x90D9, 0xBA1D, 0x90DA, 0xBA1E, 0x90DB, 0xBA1F, 0x90DC,
+	0xBA20, 0x90DD, 0xBA21, 0x90DE, 0xBA22, 0x90DF, 0xBA23, 0x90E0,
+	0xBA24, 0x90E1, 0xBA25, 0x90E2, 0xBA26, 0x90E3, 0xBA27, 0x90E4,
+	0xBA28, 0x90E5, 0xBA29, 0x90E6, 0xBA2A, 0x90E7, 0xBA2B, 0x90E8,
+	0xBA2C, 0x90E9, 0xBA2D, 0x90EA, 0xBA2E, 0x90EB, 0xBA2F, 0x90EC,
+	0xBA30, 0x90ED, 0xBA31, 0x90EE, 0xBA32, 0x90EF, 0xBA33, 0x90F0,
+	0xBA34, 0x90F1, 0xBA35, 0x90F2, 0xBA36, 0x90F3, 0xBA37, 0x90F4,
+	0xBA38, 0xB8D3, 0xBA39, 0xB8D4, 0xBA3A, 0x90F5, 0xBA3B, 0x90F6,
+	0xBA3C, 0xB8D5, 0xBA3D, 0x90F7, 0xBA3E, 0x90F8, 0xBA3F, 0x90F9,
+	0xBA40, 0xB8D6, 0xBA41, 0x90FA, 0xBA42, 0xB8D7, 0xBA43, 0x90FB,
+	0xBA44, 0x90FC, 0xBA45, 0x90FD, 0xBA46, 0x90FE, 0xBA47, 0x9141,
+	0xBA48, 0xB8D8, 0xBA49, 0xB8D9, 0xBA4A, 0x9142, 0xBA4B, 0xB8DA,
+	0xBA4C, 0x9143, 0xBA4D, 0xB8DB, 0xBA4E, 0xB8DC, 0xBA4F, 0x9144,
+	0xBA50, 0x9145, 0xBA51, 0x9146, 0xBA52, 0x9147, 0xBA53, 0xB8DD,
+	0xBA54, 0xB8DE, 0xBA55, 0xB8DF, 0xBA56, 0x9148, 0xBA57, 0x9149,
+	0xBA58, 0xB8E0, 0xBA59, 0x914A, 0xBA5A, 0x914B, 0xBA5B, 0x914C,
+	0xBA5C, 0xB8E1, 0xBA5D, 0x914D, 0xBA5E, 0x914E, 0xBA5F, 0x914F,
+	0xBA60, 0x9150, 0xBA61, 0x9151, 0xBA62, 0x9152, 0xBA63, 0x9153,
+	0xBA64, 0xB8E2, 0xBA65, 0xB8E3, 0xBA66, 0x9154, 0xBA67, 0xB8E4,
+	0xBA68, 0xB8E5, 0xBA69, 0xB8E6, 0xBA6A, 0x9155, 0xBA6B, 0x9156,
+	0xBA6C, 0x9157, 0xBA6D, 0x9158, 0xBA6E, 0x9159, 0xBA6F, 0x915A,
+	0xBA70, 0xB8E7, 0xBA71, 0xB8E8, 0xBA72, 0x9161, 0xBA73, 0x9162,
+	0xBA74, 0xB8E9, 0xBA75, 0x9163, 0xBA76, 0x9164, 0xBA77, 0x9165,
+	0xBA78, 0xB8EA, 0xBA79, 0x9166, 0xBA7A, 0x9167, 0xBA7B, 0x9168,
+	0xBA7C, 0x9169, 0xBA7D, 0x916A, 0xBA7E, 0x916B, 0xBA7F, 0x916C,
+	0xBA80, 0x916D, 0xBA81, 0x916E, 0xBA82, 0x916F, 0xBA83, 0xB8EB,
+	0xBA84, 0xB8EC, 0xBA85, 0xB8ED, 0xBA86, 0x9170, 0xBA87, 0xB8EE,
+	0xBA88, 0x9171, 0xBA89, 0x9172, 0xBA8A, 0x9173, 0xBA8B, 0x9174,
+	0xBA8C, 0xB8EF, 0xBA8D, 0x9175, 0xBA8E, 0x9176, 0xBA8F, 0x9177,
+	0xBA90, 0x9178, 0xBA91, 0x9179, 0xBA92, 0x917A, 0xBA93, 0x9181,
+	0xBA94, 0x9182, 0xBA95, 0x9183, 0xBA96, 0x9184, 0xBA97, 0x9185,
+	0xBA98, 0x9186, 0xBA99, 0x9187, 0xBA9A, 0x9188, 0xBA9B, 0x9189,
+	0xBA9C, 0x918A, 0xBA9D, 0x918B, 0xBA9E, 0x918C, 0xBA9F, 0x918D,
+	0xBAA0, 0x918E, 0xBAA1, 0x918F, 0xBAA2, 0x9190, 0xBAA3, 0x9191,
+	0xBAA4, 0x9192, 0xBAA5, 0x9193, 0xBAA6, 0x9194, 0xBAA7, 0x9195,
+	0xBAA8, 0xB8F0, 0xBAA9, 0xB8F1, 0xBAAA, 0x9196, 0xBAAB, 0xB8F2,
+	0xBAAC, 0xB8F3, 0xBAAD, 0x9197, 0xBAAE, 0x9198, 0xBAAF, 0x9199,
+	0xBAB0, 0xB8F4, 0xBAB1, 0x919A, 0xBAB2, 0xB8F5, 0xBAB3, 0x919B,
+	0xBAB4, 0x919C, 0xBAB5, 0x919D, 0xBAB6, 0x919E, 0xBAB7, 0x919F,
+	0xBAB8, 0xB8F6, 0xBAB9, 0xB8F7, 0xBABA, 0x91A0, 0xBABB, 0xB8F8,
+	0xBABC, 0x91A1, 0xBABD, 0xB8F9, 0xBABE, 0x91A2, 0xBABF, 0x91A3,
+	0xBAC0, 0x91A4, 0xBAC1, 0x91A5, 0xBAC2, 0x91A6, 0xBAC3, 0x91A7,
+	0xBAC4, 0xB8FA, 0xBAC5, 0x91A8, 0xBAC6, 0x91A9, 0xBAC7, 0x91AA,
+	0xBAC8, 0xB8FB, 0xBAC9, 0x91AB, 0xBACA, 0x91AC, 0xBACB, 0x91AD,
+	0xBACC, 0x91AE, 0xBACD, 0x91AF, 0xBACE, 0x91B0, 0xBACF, 0x91B1,
+	0xBAD0, 0x91B2, 0xBAD1, 0x91B3, 0xBAD2, 0x91B4, 0xBAD3, 0x91B5,
+	0xBAD4, 0x91B6, 0xBAD5, 0x91B7, 0xBAD6, 0x91B8, 0xBAD7, 0x91B9,
+	0xBAD8, 0xB8FC, 0xBAD9, 0xB8FD, 0xBADA, 0x91BA, 0xBADB, 0x91BB,
+	0xBADC, 0x91BC, 0xBADD, 0x91BD, 0xBADE, 0x91BE, 0xBADF, 0x91BF,
+	0xBAE0, 0x91C0, 0xBAE1, 0x91C1, 0xBAE2, 0x91C2, 0xBAE3, 0x91C3,
+	0xBAE4, 0x91C4, 0xBAE5, 0x91C5, 0xBAE6, 0x91C6, 0xBAE7, 0x91C7,
+	0xBAE8, 0x91C8, 0xBAE9, 0x91C9, 0xBAEA, 0x91CA, 0xBAEB, 0x91CB,
+	0xBAEC, 0x91CC, 0xBAED, 0x91CD, 0xBAEE, 0x91CE, 0xBAEF, 0x91CF,
+	0xBAF0, 0x91D0, 0xBAF1, 0x91D1, 0xBAF2, 0x91D2, 0xBAF3, 0x91D3,
+	0xBAF4, 0x91D4, 0xBAF5, 0x91D5, 0xBAF6, 0x91D6, 0xBAF7, 0x91D7,
+	0xBAF8, 0x91D8, 0xBAF9, 0x91D9, 0xBAFA, 0x91DA, 0xBAFB, 0x91DB,
+	0xBAFC, 0xB8FE, 0xBAFD, 0x91DC, 0xBAFE, 0x91DD, 0xBAFF, 0x91DE,
+	0xBB00, 0xB9A1, 0xBB01, 0x91DF, 0xBB02, 0x91E0, 0xBB03, 0x91E1,
+	0xBB04, 0xB9A2, 0xBB05, 0x91E2, 0xBB06, 0x91E3, 0xBB07, 0x91E4,
+	0xBB08, 0x91E5, 0xBB09, 0x91E6, 0xBB0A, 0x91E7, 0xBB0B, 0x91E8,
+	0xBB0C, 0x91E9, 0xBB0D, 0xB9A3, 0xBB0E, 0x91EA, 0xBB0F, 0xB9A4,
+	0xBB10, 0x91EB, 0xBB11, 0xB9A5, 0xBB12, 0x91EC, 0xBB13, 0x91ED,
+	0xBB14, 0x91EE, 0xBB15, 0x91EF, 0xBB16, 0x91F0, 0xBB17, 0x91F1,
+	0xBB18, 0xB9A6, 0xBB19, 0x91F2, 0xBB1A, 0x91F3, 0xBB1B, 0x91F4,
+	0xBB1C, 0xB9A7, 0xBB1D, 0x91F5, 0xBB1E, 0x91F6, 0xBB1F, 0x91F7,
+	0xBB20, 0xB9A8, 0xBB21, 0x91F8, 0xBB22, 0x91F9, 0xBB23, 0x91FA,
+	0xBB24, 0x91FB, 0xBB25, 0x91FC, 0xBB26, 0x91FD, 0xBB27, 0x91FE,
+	0xBB28, 0x9241, 0xBB29, 0xB9A9, 0xBB2A, 0x9242, 0xBB2B, 0xB9AA,
+	0xBB2C, 0x9243, 0xBB2D, 0x9244, 0xBB2E, 0x9245, 0xBB2F, 0x9246,
+	0xBB30, 0x9247, 0xBB31, 0x9248, 0xBB32, 0x9249, 0xBB33, 0x924A,
+	0xBB34, 0xB9AB, 0xBB35, 0xB9AC, 0xBB36, 0xB9AD, 0xBB37, 0x924B,
+	0xBB38, 0xB9AE, 0xBB39, 0x924C, 0xBB3A, 0x924D, 0xBB3B, 0xB9AF,
+	0xBB3C, 0xB9B0, 0xBB3D, 0xB9B1, 0xBB3E, 0xB9B2, 0xBB3F, 0x924E,
+	0xBB40, 0x924F, 0xBB41, 0x9250, 0xBB42, 0x9251, 0xBB43, 0x9252,
+	0xBB44, 0xB9B3, 0xBB45, 0xB9B4, 0xBB46, 0x9253, 0xBB47, 0xB9B5,
+	0xBB48, 0x9254, 0xBB49, 0xB9B6, 0xBB4A, 0x9255, 0xBB4B, 0x9256,
+	0xBB4C, 0x9257, 0xBB4D, 0xB9B7, 0xBB4E, 0x9258, 0xBB4F, 0xB9B8,
+	0xBB50, 0xB9B9, 0xBB51, 0x9259, 0xBB52, 0x925A, 0xBB53, 0x9261,
+	0xBB54, 0xB9BA, 0xBB55, 0x9262, 0xBB56, 0x9263, 0xBB57, 0x9264,
+	0xBB58, 0xB9BB, 0xBB59, 0x9265, 0xBB5A, 0x9266, 0xBB5B, 0x9267,
+	0xBB5C, 0x9268, 0xBB5D, 0x9269, 0xBB5E, 0x926A, 0xBB5F, 0x926B,
+	0xBB60, 0x926C, 0xBB61, 0xB9BC, 0xBB62, 0x926D, 0xBB63, 0xB9BD,
+	0xBB64, 0x926E, 0xBB65, 0x926F, 0xBB66, 0x9270, 0xBB67, 0x9271,
+	0xBB68, 0x9272, 0xBB69, 0x9273, 0xBB6A, 0x9274, 0xBB6B, 0x9275,
+	0xBB6C, 0xB9BE, 0xBB6D, 0x9276, 0xBB6E, 0x9277, 0xBB6F, 0x9278,
+	0xBB70, 0x9279, 0xBB71, 0x927A, 0xBB72, 0x9281, 0xBB73, 0x9282,
+	0xBB74, 0x9283, 0xBB75, 0x9284, 0xBB76, 0x9285, 0xBB77, 0x9286,
+	0xBB78, 0x9287, 0xBB79, 0x9288, 0xBB7A, 0x9289, 0xBB7B, 0x928A,
+	0xBB7C, 0x928B, 0xBB7D, 0x928C, 0xBB7E, 0x928D, 0xBB7F, 0x928E,
+	0xBB80, 0x928F, 0xBB81, 0x9290, 0xBB82, 0x9291, 0xBB83, 0x9292,
+	0xBB84, 0x9293, 0xBB85, 0x9294, 0xBB86, 0x9295, 0xBB87, 0x9296,
+	0xBB88, 0xB9BF, 0xBB89, 0x9297, 0xBB8A, 0x9298, 0xBB8B, 0x9299,
+	0xBB8C, 0xB9C0, 0xBB8D, 0x929A, 0xBB8E, 0x929B, 0xBB8F, 0x929C,
+	0xBB90, 0xB9C1, 0xBB91, 0x929D, 0xBB92, 0x929E, 0xBB93, 0x929F,
+	0xBB94, 0x92A0, 0xBB95, 0x92A1, 0xBB96, 0x92A2, 0xBB97, 0x92A3,
+	0xBB98, 0x92A4, 0xBB99, 0x92A5, 0xBB9A, 0x92A6, 0xBB9B, 0x92A7,
+	0xBB9C, 0x92A8, 0xBB9D, 0x92A9, 0xBB9E, 0x92AA, 0xBB9F, 0x92AB,
+	0xBBA0, 0x92AC, 0xBBA1, 0x92AD, 0xBBA2, 0x92AE, 0xBBA3, 0x92AF,
+	0xBBA4, 0xB9C2, 0xBBA5, 0x92B0, 0xBBA6, 0x92B1, 0xBBA7, 0x92B2,
+	0xBBA8, 0xB9C3, 0xBBA9, 0x92B3, 0xBBAA, 0x92B4, 0xBBAB, 0x92B5,
+	0xBBAC, 0xB9C4, 0xBBAD, 0x92B6, 0xBBAE, 0x92B7, 0xBBAF, 0x92B8,
+	0xBBB0, 0x92B9, 0xBBB1, 0x92BA, 0xBBB2, 0x92BB, 0xBBB3, 0x92BC,
+	0xBBB4, 0xB9C5, 0xBBB5, 0x92BD, 0xBBB6, 0x92BE, 0xBBB7, 0xB9C6,
+	0xBBB8, 0x92BF, 0xBBB9, 0x92C0, 0xBBBA, 0x92C1, 0xBBBB, 0x92C2,
+	0xBBBC, 0x92C3, 0xBBBD, 0x92C4, 0xBBBE, 0x92C5, 0xBBBF, 0x92C6,
+	0xBBC0, 0xB9C7, 0xBBC1, 0x92C7, 0xBBC2, 0x92C8, 0xBBC3, 0x92C9,
+	0xBBC4, 0xB9C8, 0xBBC5, 0x92CA, 0xBBC6, 0x92CB, 0xBBC7, 0x92CC,
+	0xBBC8, 0xB9C9, 0xBBC9, 0x92CD, 0xBBCA, 0x92CE, 0xBBCB, 0x92CF,
+	0xBBCC, 0x92D0, 0xBBCD, 0x92D1, 0xBBCE, 0x92D2, 0xBBCF, 0x92D3,
+	0xBBD0, 0xB9CA, 0xBBD1, 0x92D4, 0xBBD2, 0x92D5, 0xBBD3, 0xB9CB,
+	0xBBD4, 0x92D6, 0xBBD5, 0x92D7, 0xBBD6, 0x92D8, 0xBBD7, 0x92D9,
+	0xBBD8, 0x92DA, 0xBBD9, 0x92DB, 0xBBDA, 0x92DC, 0xBBDB, 0x92DD,
+	0xBBDC, 0x92DE, 0xBBDD, 0x92DF, 0xBBDE, 0x92E0, 0xBBDF, 0x92E1,
+	0xBBE0, 0x92E2, 0xBBE1, 0x92E3, 0xBBE2, 0x92E4, 0xBBE3, 0x92E5,
+	0xBBE4, 0x92E6, 0xBBE5, 0x92E7, 0xBBE6, 0x92E8, 0xBBE7, 0x92E9,
+	0xBBE8, 0x92EA, 0xBBE9, 0x92EB, 0xBBEA, 0x92EC, 0xBBEB, 0x92ED,
+	0xBBEC, 0x92EE, 0xBBED, 0x92EF, 0xBBEE, 0x92F0, 0xBBEF, 0x92F1,
+	0xBBF0, 0x92F2, 0xBBF1, 0x92F3, 0xBBF2, 0x92F4, 0xBBF3, 0x92F5,
+	0xBBF4, 0x92F6, 0xBBF5, 0x92F7, 0xBBF6, 0x92F8, 0xBBF7, 0x92F9,
+	0xBBF8, 0xB9CC, 0xBBF9, 0xB9CD, 0xBBFA, 0x92FA, 0xBBFB, 0x92FB,
+	0xBBFC, 0xB9CE, 0xBBFD, 0x92FC, 0xBBFE, 0x92FD, 0xBBFF, 0xB9CF,
+	0xBC00, 0xB9D0, 0xBC01, 0x92FE, 0xBC02, 0xB9D1, 0xBC03, 0x9341,
+	0xBC04, 0x9342, 0xBC05, 0x9343, 0xBC06, 0x9344, 0xBC07, 0x9345,
+	0xBC08, 0xB9D2, 0xBC09, 0xB9D3, 0xBC0A, 0x9346, 0xBC0B, 0xB9D4,
+	0xBC0C, 0xB9D5, 0xBC0D, 0xB9D6, 0xBC0E, 0x9347, 0xBC0F, 0xB9D7,
+	0xBC10, 0x9348, 0xBC11, 0xB9D8, 0xBC12, 0x9349, 0xBC13, 0x934A,
+	0xBC14, 0xB9D9, 0xBC15, 0xB9DA, 0xBC16, 0xB9DB, 0xBC17, 0xB9DC,
+	0xBC18, 0xB9DD, 0xBC19, 0x934B, 0xBC1A, 0x934C, 0xBC1B, 0xB9DE,
+	0xBC1C, 0xB9DF, 0xBC1D, 0xB9E0, 0xBC1E, 0xB9E1, 0xBC1F, 0xB9E2,
+	0xBC20, 0x934D, 0xBC21, 0x934E, 0xBC22, 0x934F, 0xBC23, 0x9350,
+	0xBC24, 0xB9E3, 0xBC25, 0xB9E4, 0xBC26, 0x9351, 0xBC27, 0xB9E5,
+	0xBC28, 0x9352, 0xBC29, 0xB9E6, 0xBC2A, 0x9353, 0xBC2B, 0x9354,
+	0xBC2C, 0x9355, 0xBC2D, 0xB9E7, 0xBC2E, 0x9356, 0xBC2F, 0x9357,
+	0xBC30, 0xB9E8, 0xBC31, 0xB9E9, 0xBC32, 0x9358, 0xBC33, 0x9359,
+	0xBC34, 0xB9EA, 0xBC35, 0x935A, 0xBC36, 0x9361, 0xBC37, 0x9362,
+	0xBC38, 0xB9EB, 0xBC39, 0x9363, 0xBC3A, 0x9364, 0xBC3B, 0x9365,
+	0xBC3C, 0x9366, 0xBC3D, 0x9367, 0xBC3E, 0x9368, 0xBC3F, 0x9369,
+	0xBC40, 0xB9EC, 0xBC41, 0xB9ED, 0xBC42, 0x936A, 0xBC43, 0xB9EE,
+	0xBC44, 0xB9EF, 0xBC45, 0xB9F0, 0xBC46, 0x936B, 0xBC47, 0x936C,
+	0xBC48, 0x936D, 0xBC49, 0xB9F1, 0xBC4A, 0x936E, 0xBC4B, 0x936F,
+	0xBC4C, 0xB9F2, 0xBC4D, 0xB9F3, 0xBC4E, 0x9370, 0xBC4F, 0x9371,
+	0xBC50, 0xB9F4, 0xBC51, 0x9372, 0xBC52, 0x9373, 0xBC53, 0x9374,
+	0xBC54, 0x9375, 0xBC55, 0x9376, 0xBC56, 0x9377, 0xBC57, 0x9378,
+	0xBC58, 0x9379, 0xBC59, 0x937A, 0xBC5A, 0x9381, 0xBC5B, 0x9382,
+	0xBC5C, 0x9383, 0xBC5D, 0xB9F5, 0xBC5E, 0x9384, 0xBC5F, 0x9385,
+	0xBC60, 0x9386, 0xBC61, 0x9387, 0xBC62, 0x9388, 0xBC63, 0x9389,
+	0xBC64, 0x938A, 0xBC65, 0x938B, 0xBC66, 0x938C, 0xBC67, 0x938D,
+	0xBC68, 0x938E, 0xBC69, 0x938F, 0xBC6A, 0x9390, 0xBC6B, 0x9391,
+	0xBC6C, 0x9392, 0xBC6D, 0x9393, 0xBC6E, 0x9394, 0xBC6F, 0x9395,
+	0xBC70, 0x9396, 0xBC71, 0x9397, 0xBC72, 0x9398, 0xBC73, 0x9399,
+	0xBC74, 0x939A, 0xBC75, 0x939B, 0xBC76, 0x939C, 0xBC77, 0x939D,
+	0xBC78, 0x939E, 0xBC79, 0x939F, 0xBC7A, 0x93A0, 0xBC7B, 0x93A1,
+	0xBC7C, 0x93A2, 0xBC7D, 0x93A3, 0xBC7E, 0x93A4, 0xBC7F, 0x93A5,
+	0xBC80, 0x93A6, 0xBC81, 0x93A7, 0xBC82, 0x93A8, 0xBC83, 0x93A9,
+	0xBC84, 0xB9F6, 0xBC85, 0xB9F7, 0xBC86, 0x93AA, 0xBC87, 0x93AB,
+	0xBC88, 0xB9F8, 0xBC89, 0x93AC, 0xBC8A, 0x93AD, 0xBC8B, 0xB9F9,
+	0xBC8C, 0xB9FA, 0xBC8D, 0x93AE, 0xBC8E, 0xB9FB, 0xBC8F, 0x93AF,
+	0xBC90, 0x93B0, 0xBC91, 0x93B1, 0xBC92, 0x93B2, 0xBC93, 0x93B3,
+	0xBC94, 0xB9FC, 0xBC95, 0xB9FD, 0xBC96, 0x93B4, 0xBC97, 0xB9FE,
+	0xBC98, 0x93B5, 0xBC99, 0xBAA1, 0xBC9A, 0xBAA2, 0xBC9B, 0x93B6,
+	0xBC9C, 0x93B7, 0xBC9D, 0x93B8, 0xBC9E, 0x93B9, 0xBC9F, 0x93BA,
+	0xBCA0, 0xBAA3, 0xBCA1, 0xBAA4, 0xBCA2, 0x93BB, 0xBCA3, 0x93BC,
+	0xBCA4, 0xBAA5, 0xBCA5, 0x93BD, 0xBCA6, 0x93BE, 0xBCA7, 0xBAA6,
+	0xBCA8, 0xBAA7, 0xBCA9, 0x93BF, 0xBCAA, 0x93C0, 0xBCAB, 0x93C1,
+	0xBCAC, 0x93C2, 0xBCAD, 0x93C3, 0xBCAE, 0x93C4, 0xBCAF, 0x93C5,
+	0xBCB0, 0xBAA8, 0xBCB1, 0xBAA9, 0xBCB2, 0x93C6, 0xBCB3, 0xBAAA,
+	0xBCB4, 0xBAAB, 0xBCB5, 0xBAAC, 0xBCB6, 0x93C7, 0xBCB7, 0x93C8,
+	0xBCB8, 0x93C9, 0xBCB9, 0x93CA, 0xBCBA, 0x93CB, 0xBCBB, 0x93CC,
+	0xBCBC, 0xBAAD, 0xBCBD, 0xBAAE, 0xBCBE, 0x93CD, 0xBCBF, 0x93CE,
+	0xBCC0, 0xBAAF, 0xBCC1, 0x93CF, 0xBCC2, 0x93D0, 0xBCC3, 0x93D1,
+	0xBCC4, 0xBAB0, 0xBCC5, 0x93D2, 0xBCC6, 0x93D3, 0xBCC7, 0x93D4,
+	0xBCC8, 0x93D5, 0xBCC9, 0x93D6, 0xBCCA, 0x93D7, 0xBCCB, 0x93D8,
+	0xBCCC, 0x93D9, 0xBCCD, 0xBAB1, 0xBCCE, 0x93DA, 0xBCCF, 0xBAB2,
+	0xBCD0, 0xBAB3, 0xBCD1, 0xBAB4, 0xBCD2, 0x93DB, 0xBCD3, 0x93DC,
+	0xBCD4, 0x93DD, 0xBCD5, 0xBAB5, 0xBCD6, 0x93DE, 0xBCD7, 0x93DF,
+	0xBCD8, 0xBAB6, 0xBCD9, 0x93E0, 0xBCDA, 0x93E1, 0xBCDB, 0x93E2,
+	0xBCDC, 0xBAB7, 0xBCDD, 0x93E3, 0xBCDE, 0x93E4, 0xBCDF, 0x93E5,
+	0xBCE0, 0x93E6, 0xBCE1, 0x93E7, 0xBCE2, 0x93E8, 0xBCE3, 0x93E9,
+	0xBCE4, 0x93EA, 0xBCE5, 0x93EB, 0xBCE6, 0x93EC, 0xBCE7, 0x93ED,
+	0xBCE8, 0x93EE, 0xBCE9, 0x93EF, 0xBCEA, 0x93F0, 0xBCEB, 0x93F1,
+	0xBCEC, 0x93F2, 0xBCED, 0x93F3, 0xBCEE, 0x93F4, 0xBCEF, 0x93F5,
+	0xBCF0, 0x93F6, 0xBCF1, 0x93F7, 0xBCF2, 0x93F8, 0xBCF3, 0x93F9,
+	0xBCF4, 0xBAB8, 0xBCF5, 0xBAB9, 0xBCF6, 0xBABA, 0xBCF7, 0x93FA,
+	0xBCF8, 0xBABB, 0xBCF9, 0x93FB, 0xBCFA, 0x93FC, 0xBCFB, 0x93FD,
+	0xBCFC, 0xBABC, 0xBCFD, 0x93FE, 0xBCFE, 0x9441, 0xBCFF, 0x9442,
+	0xBD00, 0x9443, 0xBD01, 0x9444, 0xBD02, 0x9445, 0xBD03, 0x9446,
+	0xBD04, 0xBABD, 0xBD05, 0xBABE, 0xBD06, 0x9447, 0xBD07, 0xBABF,
+	0xBD08, 0x9448, 0xBD09, 0xBAC0, 0xBD0A, 0x9449, 0xBD0B, 0x944A,
+	0xBD0C, 0x944B, 0xBD0D, 0x944C, 0xBD0E, 0x944D, 0xBD0F, 0x944E,
+	0xBD10, 0xBAC1, 0xBD11, 0x944F, 0xBD12, 0x9450, 0xBD13, 0x9451,
+	0xBD14, 0xBAC2, 0xBD15, 0x9452, 0xBD16, 0x9453, 0xBD17, 0x9454,
+	0xBD18, 0x9455, 0xBD19, 0x9456, 0xBD1A, 0x9457, 0xBD1B, 0x9458,
+	0xBD1C, 0x9459, 0xBD1D, 0x945A, 0xBD1E, 0x9461, 0xBD1F, 0x9462,
+	0xBD20, 0x9463, 0xBD21, 0x9464, 0xBD22, 0x9465, 0xBD23, 0x9466,
+	0xBD24, 0xBAC3, 0xBD25, 0x9467, 0xBD26, 0x9468, 0xBD27, 0x9469,
+	0xBD28, 0x946A, 0xBD29, 0x946B, 0xBD2A, 0x946C, 0xBD2B, 0x946D,
+	0xBD2C, 0xBAC4, 0xBD2D, 0x946E, 0xBD2E, 0x946F, 0xBD2F, 0x9470,
+	0xBD30, 0x9471, 0xBD31, 0x9472, 0xBD32, 0x9473, 0xBD33, 0x9474,
+	0xBD34, 0x9475, 0xBD35, 0x9476, 0xBD36, 0x9477, 0xBD37, 0x9478,
+	0xBD38, 0x9479, 0xBD39, 0x947A, 0xBD3A, 0x9481, 0xBD3B, 0x9482,
+	0xBD3C, 0x9483, 0xBD3D, 0x9484, 0xBD3E, 0x9485, 0xBD3F, 0x9486,
+	0xBD40, 0xBAC5, 0xBD41, 0x9487, 0xBD42, 0x9488, 0xBD43, 0x9489,
+	0xBD44, 0x948A, 0xBD45, 0x948B, 0xBD46, 0x948C, 0xBD47, 0x948D,
+	0xBD48, 0xBAC6, 0xBD49, 0xBAC7, 0xBD4A, 0x948E, 0xBD4B, 0x948F,
+	0xBD4C, 0xBAC8, 0xBD4D, 0x9490, 0xBD4E, 0x9491, 0xBD4F, 0x9492,
+	0xBD50, 0xBAC9, 0xBD51, 0x9493, 0xBD52, 0x9494, 0xBD53, 0x9495,
+	0xBD54, 0x9496, 0xBD55, 0x9497, 0xBD56, 0x9498, 0xBD57, 0x9499,
+	0xBD58, 0xBACA, 0xBD59, 0xBACB, 0xBD5A, 0x949A, 0xBD5B, 0x949B,
+	0xBD5C, 0x949C, 0xBD5D, 0x949D, 0xBD5E, 0x949E, 0xBD5F, 0x949F,
+	0xBD60, 0x94A0, 0xBD61, 0x94A1, 0xBD62, 0x94A2, 0xBD63, 0x94A3,
+	0xBD64, 0xBACC, 0xBD65, 0x94A4, 0xBD66, 0x94A5, 0xBD67, 0x94A6,
+	0xBD68, 0xBACD, 0xBD69, 0x94A7, 0xBD6A, 0x94A8, 0xBD6B, 0x94A9,
+	0xBD6C, 0x94AA, 0xBD6D, 0x94AB, 0xBD6E, 0x94AC, 0xBD6F, 0x94AD,
+	0xBD70, 0x94AE, 0xBD71, 0x94AF, 0xBD72, 0x94B0, 0xBD73, 0x94B1,
+	0xBD74, 0x94B2, 0xBD75, 0x94B3, 0xBD76, 0x94B4, 0xBD77, 0x94B5,
+	0xBD78, 0x94B6, 0xBD79, 0x94B7, 0xBD7A, 0x94B8, 0xBD7B, 0x94B9,
+	0xBD7C, 0x94BA, 0xBD7D, 0x94BB, 0xBD7E, 0x94BC, 0xBD7F, 0x94BD,
+	0xBD80, 0xBACE, 0xBD81, 0xBACF, 0xBD82, 0x94BE, 0xBD83, 0x94BF,
+	0xBD84, 0xBAD0, 0xBD85, 0x94C0, 0xBD86, 0x94C1, 0xBD87, 0xBAD1,
+	0xBD88, 0xBAD2, 0xBD89, 0xBAD3, 0xBD8A, 0xBAD4, 0xBD8B, 0x94C2,
+	0xBD8C, 0x94C3, 0xBD8D, 0x94C4, 0xBD8E, 0x94C5, 0xBD8F, 0x94C6,
+	0xBD90, 0xBAD5, 0xBD91, 0xBAD6, 0xBD92, 0x94C7, 0xBD93, 0xBAD7,
+	0xBD94, 0x94C8, 0xBD95, 0xBAD8, 0xBD96, 0x94C9, 0xBD97, 0x94CA,
+	0xBD98, 0x94CB, 0xBD99, 0xBAD9, 0xBD9A, 0xBADA, 0xBD9B, 0x94CC,
+	0xBD9C, 0xBADB, 0xBD9D, 0x94CD, 0xBD9E, 0x94CE, 0xBD9F, 0x94CF,
+	0xBDA0, 0x94D0, 0xBDA1, 0x94D1, 0xBDA2, 0x94D2, 0xBDA3, 0x94D3,
+	0xBDA4, 0xBADC, 0xBDA5, 0x94D4, 0xBDA6, 0x94D5, 0xBDA7, 0x94D6,
+	0xBDA8, 0x94D7, 0xBDA9, 0x94D8, 0xBDAA, 0x94D9, 0xBDAB, 0x94DA,
+	0xBDAC, 0x94DB, 0xBDAD, 0x94DC, 0xBDAE, 0x94DD, 0xBDAF, 0x94DE,
+	0xBDB0, 0xBADD, 0xBDB1, 0x94DF, 0xBDB2, 0x94E0, 0xBDB3, 0x94E1,
+	0xBDB4, 0x94E2, 0xBDB5, 0x94E3, 0xBDB6, 0x94E4, 0xBDB7, 0x94E5,
+	0xBDB8, 0xBADE, 0xBDB9, 0x94E6, 0xBDBA, 0x94E7, 0xBDBB, 0x94E8,
+	0xBDBC, 0x94E9, 0xBDBD, 0x94EA, 0xBDBE, 0x94EB, 0xBDBF, 0x94EC,
+	0xBDC0, 0x94ED, 0xBDC1, 0x94EE, 0xBDC2, 0x94EF, 0xBDC3, 0x94F0,
+	0xBDC4, 0x94F1, 0xBDC5, 0x94F2, 0xBDC6, 0x94F3, 0xBDC7, 0x94F4,
+	0xBDC8, 0x94F5, 0xBDC9, 0x94F6, 0xBDCA, 0x94F7, 0xBDCB, 0x94F8,
+	0xBDCC, 0x94F9, 0xBDCD, 0x94FA, 0xBDCE, 0x94FB, 0xBDCF, 0x94FC,
+	0xBDD0, 0x94FD, 0xBDD1, 0x94FE, 0xBDD2, 0x9541, 0xBDD3, 0x9542,
+	0xBDD4, 0xBADF, 0xBDD5, 0xBAE0, 0xBDD6, 0x9543, 0xBDD7, 0x9544,
+	0xBDD8, 0xBAE1, 0xBDD9, 0x9545, 0xBDDA, 0x9546, 0xBDDB, 0x9547,
+	0xBDDC, 0xBAE2, 0xBDDD, 0x9548, 0xBDDE, 0x9549, 0xBDDF, 0x954A,
+	0xBDE0, 0x954B, 0xBDE1, 0x954C, 0xBDE2, 0x954D, 0xBDE3, 0x954E,
+	0xBDE4, 0x954F, 0xBDE5, 0x9550, 0xBDE6, 0x9551, 0xBDE7, 0x9552,
+	0xBDE8, 0x9553, 0xBDE9, 0xBAE3, 0xBDEA, 0x9554, 0xBDEB, 0x9555,
+	0xBDEC, 0x9556, 0xBDED, 0x9557, 0xBDEE, 0x9558, 0xBDEF, 0x9559,
+	0xBDF0, 0xBAE4, 0xBDF1, 0x955A, 0xBDF2, 0x9561, 0xBDF3, 0x9562,
+	0xBDF4, 0xBAE5, 0xBDF5, 0x9563, 0xBDF6, 0x9564, 0xBDF7, 0x9565,
+	0xBDF8, 0xBAE6, 0xBDF9, 0x9566, 0xBDFA, 0x9567, 0xBDFB, 0x9568,
+	0xBDFC, 0x9569, 0xBDFD, 0x956A, 0xBDFE, 0x956B, 0xBDFF, 0x956C,
+	0xBE00, 0xBAE7, 0xBE01, 0x956D, 0xBE02, 0x956E, 0xBE03, 0xBAE8,
+	0xBE04, 0x956F, 0xBE05, 0xBAE9, 0xBE06, 0x9570, 0xBE07, 0x9571,
+	0xBE08, 0x9572, 0xBE09, 0x9573, 0xBE0A, 0x9574, 0xBE0B, 0x9575,
+	0xBE0C, 0xBAEA, 0xBE0D, 0xBAEB, 0xBE0E, 0x9576, 0xBE0F, 0x9577,
+	0xBE10, 0xBAEC, 0xBE11, 0x9578, 0xBE12, 0x9579, 0xBE13, 0x957A,
+	0xBE14, 0xBAED, 0xBE15, 0x9581, 0xBE16, 0x9582, 0xBE17, 0x9583,
+	0xBE18, 0x9584, 0xBE19, 0x9585, 0xBE1A, 0x9586, 0xBE1B, 0x9587,
+	0xBE1C, 0xBAEE, 0xBE1D, 0xBAEF, 0xBE1E, 0x9588, 0xBE1F, 0xBAF0,
+	0xBE20, 0x9589, 0xBE21, 0x958A, 0xBE22, 0x958B, 0xBE23, 0x958C,
+	0xBE24, 0x958D, 0xBE25, 0x958E, 0xBE26, 0x958F, 0xBE27, 0x9590,
+	0xBE28, 0x9591, 0xBE29, 0x9592, 0xBE2A, 0x9593, 0xBE2B, 0x9594,
+	0xBE2C, 0x9595, 0xBE2D, 0x9596, 0xBE2E, 0x9597, 0xBE2F, 0x9598,
+	0xBE30, 0x9599, 0xBE31, 0x959A, 0xBE32, 0x959B, 0xBE33, 0x959C,
+	0xBE34, 0x959D, 0xBE35, 0x959E, 0xBE36, 0x959F, 0xBE37, 0x95A0,
+	0xBE38, 0x95A1, 0xBE39, 0x95A2, 0xBE3A, 0x95A3, 0xBE3B, 0x95A4,
+	0xBE3C, 0x95A5, 0xBE3D, 0x95A6, 0xBE3E, 0x95A7, 0xBE3F, 0x95A8,
+	0xBE40, 0x95A9, 0xBE41, 0x95AA, 0xBE42, 0x95AB, 0xBE43, 0x95AC,
+	0xBE44, 0xBAF1, 0xBE45, 0xBAF2, 0xBE46, 0x95AD, 0xBE47, 0x95AE,
+	0xBE48, 0xBAF3, 0xBE49, 0x95AF, 0xBE4A, 0x95B0, 0xBE4B, 0x95B1,
+	0xBE4C, 0xBAF4, 0xBE4D, 0x95B2, 0xBE4E, 0xBAF5, 0xBE4F, 0x95B3,
+	0xBE50, 0x95B4, 0xBE51, 0x95B5, 0xBE52, 0x95B6, 0xBE53, 0x95B7,
+	0xBE54, 0xBAF6, 0xBE55, 0xBAF7, 0xBE56, 0x95B8, 0xBE57, 0xBAF8,
+	0xBE58, 0x95B9, 0xBE59, 0xBAF9, 0xBE5A, 0xBAFA, 0xBE5B, 0xBAFB,
+	0xBE5C, 0x95BA, 0xBE5D, 0x95BB, 0xBE5E, 0x95BC, 0xBE5F, 0x95BD,
+	0xBE60, 0xBAFC, 0xBE61, 0xBAFD, 0xBE62, 0x95BE, 0xBE63, 0x95BF,
+	0xBE64, 0xBAFE, 0xBE65, 0x95C0, 0xBE66, 0x95C1, 0xBE67, 0x95C2,
+	0xBE68, 0xBBA1, 0xBE69, 0x95C3, 0xBE6A, 0xBBA2, 0xBE6B, 0x95C4,
+	0xBE6C, 0x95C5, 0xBE6D, 0x95C6, 0xBE6E, 0x95C7, 0xBE6F, 0x95C8,
+	0xBE70, 0xBBA3, 0xBE71, 0xBBA4, 0xBE72, 0x95C9, 0xBE73, 0xBBA5,
+	0xBE74, 0xBBA6, 0xBE75, 0xBBA7, 0xBE76, 0x95CA, 0xBE77, 0x95CB,
+	0xBE78, 0x95CC, 0xBE79, 0x95CD, 0xBE7A, 0x95CE, 0xBE7B, 0xBBA8,
+	0xBE7C, 0xBBA9, 0xBE7D, 0xBBAA, 0xBE7E, 0x95CF, 0xBE7F, 0x95D0,
+	0xBE80, 0xBBAB, 0xBE81, 0x95D1, 0xBE82, 0x95D2, 0xBE83, 0x95D3,
+	0xBE84, 0xBBAC, 0xBE85, 0x95D4, 0xBE86, 0x95D5, 0xBE87, 0x95D6,
+	0xBE88, 0x95D7, 0xBE89, 0x95D8, 0xBE8A, 0x95D9, 0xBE8B, 0x95DA,
+	0xBE8C, 0xBBAD, 0xBE8D, 0xBBAE, 0xBE8E, 0x95DB, 0xBE8F, 0xBBAF,
+	0xBE90, 0xBBB0, 0xBE91, 0xBBB1, 0xBE92, 0x95DC, 0xBE93, 0x95DD,
+	0xBE94, 0x95DE, 0xBE95, 0x95DF, 0xBE96, 0x95E0, 0xBE97, 0x95E1,
+	0xBE98, 0xBBB2, 0xBE99, 0xBBB3, 0xBE9A, 0x95E2, 0xBE9B, 0x95E3,
+	0xBE9C, 0x95E4, 0xBE9D, 0x95E5, 0xBE9E, 0x95E6, 0xBE9F, 0x95E7,
+	0xBEA0, 0x95E8, 0xBEA1, 0x95E9, 0xBEA2, 0x95EA, 0xBEA3, 0x95EB,
+	0xBEA4, 0x95EC, 0xBEA5, 0x95ED, 0xBEA6, 0x95EE, 0xBEA7, 0x95EF,
+	0xBEA8, 0xBBB4, 0xBEA9, 0x95F0, 0xBEAA, 0x95F1, 0xBEAB, 0x95F2,
+	0xBEAC, 0x95F3, 0xBEAD, 0x95F4, 0xBEAE, 0x95F5, 0xBEAF, 0x95F6,
+	0xBEB0, 0x95F7, 0xBEB1, 0x95F8, 0xBEB2, 0x95F9, 0xBEB3, 0x95FA,
+	0xBEB4, 0x95FB, 0xBEB5, 0x95FC, 0xBEB6, 0x95FD, 0xBEB7, 0x95FE,
+	0xBEB8, 0x9641, 0xBEB9, 0x9642, 0xBEBA, 0x9643, 0xBEBB, 0x9644,
+	0xBEBC, 0x9645, 0xBEBD, 0x9646, 0xBEBE, 0x9647, 0xBEBF, 0x9648,
+	0xBEC0, 0x9649, 0xBEC1, 0x964A, 0xBEC2, 0x964B, 0xBEC3, 0x964C,
+	0xBEC4, 0x964D, 0xBEC5, 0x964E, 0xBEC6, 0x964F, 0xBEC7, 0x9650,
+	0xBEC8, 0x9651, 0xBEC9, 0x9652, 0xBECA, 0x9653, 0xBECB, 0x9654,
+	0xBECC, 0x9655, 0xBECD, 0x9656, 0xBECE, 0x9657, 0xBECF, 0x9658,
+	0xBED0, 0xBBB5, 0xBED1, 0xBBB6, 0xBED2, 0x9659, 0xBED3, 0x965A,
+	0xBED4, 0xBBB7, 0xBED5, 0x9661, 0xBED6, 0x9662, 0xBED7, 0xBBB8,
+	0xBED8, 0xBBB9, 0xBED9, 0x9663, 0xBEDA, 0x9664, 0xBEDB, 0x9665,
+	0xBEDC, 0x9666, 0xBEDD, 0x9667, 0xBEDE, 0x9668, 0xBEDF, 0x9669,
+	0xBEE0, 0xBBBA, 0xBEE1, 0x966A, 0xBEE2, 0x966B, 0xBEE3, 0xBBBB,
+	0xBEE4, 0xBBBC, 0xBEE5, 0xBBBD, 0xBEE6, 0x966C, 0xBEE7, 0x966D,
+	0xBEE8, 0x966E, 0xBEE9, 0x966F, 0xBEEA, 0x9670, 0xBEEB, 0x9671,
+	0xBEEC, 0xBBBE, 0xBEED, 0x9672, 0xBEEE, 0x9673, 0xBEEF, 0x9674,
+	0xBEF0, 0x9675, 0xBEF1, 0x9676, 0xBEF2, 0x9677, 0xBEF3, 0x9678,
+	0xBEF4, 0x9679, 0xBEF5, 0x967A, 0xBEF6, 0x9681, 0xBEF7, 0x9682,
+	0xBEF8, 0x9683, 0xBEF9, 0x9684, 0xBEFA, 0x9685, 0xBEFB, 0x9686,
+	0xBEFC, 0x9687, 0xBEFD, 0x9688, 0xBEFE, 0x9689, 0xBEFF, 0x968A,
+	0xBF00, 0x968B, 0xBF01, 0xBBBF, 0xBF02, 0x968C, 0xBF03, 0x968D,
+	0xBF04, 0x968E, 0xBF05, 0x968F, 0xBF06, 0x9690, 0xBF07, 0x9691,
+	0xBF08, 0xBBC0, 0xBF09, 0xBBC1, 0xBF0A, 0x9692, 0xBF0B, 0x9693,
+	0xBF0C, 0x9694, 0xBF0D, 0x9695, 0xBF0E, 0x9696, 0xBF0F, 0x9697,
+	0xBF10, 0x9698, 0xBF11, 0x9699, 0xBF12, 0x969A, 0xBF13, 0x969B,
+	0xBF14, 0x969C, 0xBF15, 0x969D, 0xBF16, 0x969E, 0xBF17, 0x969F,
+	0xBF18, 0xBBC2, 0xBF19, 0xBBC3, 0xBF1A, 0x96A0, 0xBF1B, 0xBBC4,
+	0xBF1C, 0xBBC5, 0xBF1D, 0xBBC6, 0xBF1E, 0x96A1, 0xBF1F, 0x96A2,
+	0xBF20, 0x96A3, 0xBF21, 0x96A4, 0xBF22, 0x96A5, 0xBF23, 0x96A6,
+	0xBF24, 0x96A7, 0xBF25, 0x96A8, 0xBF26, 0x96A9, 0xBF27, 0x96AA,
+	0xBF28, 0x96AB, 0xBF29, 0x96AC, 0xBF2A, 0x96AD, 0xBF2B, 0x96AE,
+	0xBF2C, 0x96AF, 0xBF2D, 0x96B0, 0xBF2E, 0x96B1, 0xBF2F, 0x96B2,
+	0xBF30, 0x96B3, 0xBF31, 0x96B4, 0xBF32, 0x96B5, 0xBF33, 0x96B6,
+	0xBF34, 0x96B7, 0xBF35, 0x96B8, 0xBF36, 0x96B9, 0xBF37, 0x96BA,
+	0xBF38, 0x96BB, 0xBF39, 0x96BC, 0xBF3A, 0x96BD, 0xBF3B, 0x96BE,
+	0xBF3C, 0x96BF, 0xBF3D, 0x96C0, 0xBF3E, 0x96C1, 0xBF3F, 0x96C2,
+	0xBF40, 0xBBC7, 0xBF41, 0xBBC8, 0xBF42, 0x96C3, 0xBF43, 0x96C4,
+	0xBF44, 0xBBC9, 0xBF45, 0x96C5, 0xBF46, 0x96C6, 0xBF47, 0x96C7,
+	0xBF48, 0xBBCA, 0xBF49, 0x96C8, 0xBF4A, 0x96C9, 0xBF4B, 0x96CA,
+	0xBF4C, 0x96CB, 0xBF4D, 0x96CC, 0xBF4E, 0x96CD, 0xBF4F, 0x96CE,
+	0xBF50, 0xBBCB, 0xBF51, 0xBBCC, 0xBF52, 0x96CF, 0xBF53, 0x96D0,
+	0xBF54, 0x96D1, 0xBF55, 0xBBCD, 0xBF56, 0x96D2, 0xBF57, 0x96D3,
+	0xBF58, 0x96D4, 0xBF59, 0x96D5, 0xBF5A, 0x96D6, 0xBF5B, 0x96D7,
+	0xBF5C, 0x96D8, 0xBF5D, 0x96D9, 0xBF5E, 0x96DA, 0xBF5F, 0x96DB,
+	0xBF60, 0x96DC, 0xBF61, 0x96DD, 0xBF62, 0x96DE, 0xBF63, 0x96DF,
+	0xBF64, 0x96E0, 0xBF65, 0x96E1, 0xBF66, 0x96E2, 0xBF67, 0x96E3,
+	0xBF68, 0x96E4, 0xBF69, 0x96E5, 0xBF6A, 0x96E6, 0xBF6B, 0x96E7,
+	0xBF6C, 0x96E8, 0xBF6D, 0x96E9, 0xBF6E, 0x96EA, 0xBF6F, 0x96EB,
+	0xBF70, 0x96EC, 0xBF71, 0x96ED, 0xBF72, 0x96EE, 0xBF73, 0x96EF,
+	0xBF74, 0x96F0, 0xBF75, 0x96F1, 0xBF76, 0x96F2, 0xBF77, 0x96F3,
+	0xBF78, 0x96F4, 0xBF79, 0x96F5, 0xBF7A, 0x96F6, 0xBF7B, 0x96F7,
+	0xBF7C, 0x96F8, 0xBF7D, 0x96F9, 0xBF7E, 0x96FA, 0xBF7F, 0x96FB,
+	0xBF80, 0x96FC, 0xBF81, 0x96FD, 0xBF82, 0x96FE, 0xBF83, 0x9741,
+	0xBF84, 0x9742, 0xBF85, 0x9743, 0xBF86, 0x9744, 0xBF87, 0x9745,
+	0xBF88, 0x9746, 0xBF89, 0x9747, 0xBF8A, 0x9748, 0xBF8B, 0x9749,
+	0xBF8C, 0x974A, 0xBF8D, 0x974B, 0xBF8E, 0x974C, 0xBF8F, 0x974D,
+	0xBF90, 0x974E, 0xBF91, 0x974F, 0xBF92, 0x9750, 0xBF93, 0x9751,
+	0xBF94, 0xBBCE, 0xBF95, 0x9752, 0xBF96, 0x9753, 0xBF97, 0x9754,
+	0xBF98, 0x9755, 0xBF99, 0x9756, 0xBF9A, 0x9757, 0xBF9B, 0x9758,
+	0xBF9C, 0x9759, 0xBF9D, 0x975A, 0xBF9E, 0x9761, 0xBF9F, 0x9762,
+	0xBFA0, 0x9763, 0xBFA1, 0x9764, 0xBFA2, 0x9765, 0xBFA3, 0x9766,
+	0xBFA4, 0x9767, 0xBFA5, 0x9768, 0xBFA6, 0x9769, 0xBFA7, 0x976A,
+	0xBFA8, 0x976B, 0xBFA9, 0x976C, 0xBFAA, 0x976D, 0xBFAB, 0x976E,
+	0xBFAC, 0x976F, 0xBFAD, 0x9770, 0xBFAE, 0x9771, 0xBFAF, 0x9772,
+	0xBFB0, 0xBBCF, 0xBFB1, 0x9773, 0xBFB2, 0x9774, 0xBFB3, 0x9775,
+	0xBFB4, 0x9776, 0xBFB5, 0x9777, 0xBFB6, 0x9778, 0xBFB7, 0x9779,
+	0xBFB8, 0x977A, 0xBFB9, 0x9781, 0xBFBA, 0x9782, 0xBFBB, 0x9783,
+	0xBFBC, 0x9784, 0xBFBD, 0x9785, 0xBFBE, 0x9786, 0xBFBF, 0x9787,
+	0xBFC0, 0x9788, 0xBFC1, 0x9789, 0xBFC2, 0x978A, 0xBFC3, 0x978B,
+	0xBFC4, 0x978C, 0xBFC5, 0xBBD0, 0xBFC6, 0x978D, 0xBFC7, 0x978E,
+	0xBFC8, 0x978F, 0xBFC9, 0x9790, 0xBFCA, 0x9791, 0xBFCB, 0x9792,
+	0xBFCC, 0xBBD1, 0xBFCD, 0xBBD2, 0xBFCE, 0x9793, 0xBFCF, 0x9794,
+	0xBFD0, 0xBBD3, 0xBFD1, 0x9795, 0xBFD2, 0x9796, 0xBFD3, 0x9797,
+	0xBFD4, 0xBBD4, 0xBFD5, 0x9798, 0xBFD6, 0x9799, 0xBFD7, 0x979A,
+	0xBFD8, 0x979B, 0xBFD9, 0x979C, 0xBFDA, 0x979D, 0xBFDB, 0x979E,
+	0xBFDC, 0xBBD5, 0xBFDD, 0x979F, 0xBFDE, 0x97A0, 0xBFDF, 0xBBD6,
+	0xBFE0, 0x97A1, 0xBFE1, 0xBBD7, 0xBFE2, 0x97A2, 0xBFE3, 0x97A3,
+	0xBFE4, 0x97A4, 0xBFE5, 0x97A5, 0xBFE6, 0x97A6, 0xBFE7, 0x97A7,
+	0xBFE8, 0x97A8, 0xBFE9, 0x97A9, 0xBFEA, 0x97AA, 0xBFEB, 0x97AB,
+	0xBFEC, 0x97AC, 0xBFED, 0x97AD, 0xBFEE, 0x97AE, 0xBFEF, 0x97AF,
+	0xBFF0, 0x97B0, 0xBFF1, 0x97B1, 0xBFF2, 0x97B2, 0xBFF3, 0x97B3,
+	0xBFF4, 0x97B4, 0xBFF5, 0x97B5, 0xBFF6, 0x97B6, 0xBFF7, 0x97B7,
+	0xBFF8, 0x97B8, 0xBFF9, 0x97B9, 0xBFFA, 0x97BA, 0xBFFB, 0x97BB,
+	0xBFFC, 0x97BC, 0xBFFD, 0x97BD, 0xBFFE, 0x97BE, 0xBFFF, 0x97BF,
+	0xC000, 0x97C0, 0xC001, 0x97C1, 0xC002, 0x97C2, 0xC003, 0x97C3,
+	0xC004, 0x97C4, 0xC005, 0x97C5, 0xC006, 0x97C6, 0xC007, 0x97C7,
+	0xC008, 0x97C8, 0xC009, 0x97C9, 0xC00A, 0x97CA, 0xC00B, 0x97CB,
+	0xC00C, 0x97CC, 0xC00D, 0x97CD, 0xC00E, 0x97CE, 0xC00F, 0x97CF,
+	0xC010, 0x97D0, 0xC011, 0x97D1, 0xC012, 0x97D2, 0xC013, 0x97D3,
+	0xC014, 0x97D4, 0xC015, 0x97D5, 0xC016, 0x97D6, 0xC017, 0x97D7,
+	0xC018, 0x97D8, 0xC019, 0x97D9, 0xC01A, 0x97DA, 0xC01B, 0x97DB,
+	0xC01C, 0x97DC, 0xC01D, 0x97DD, 0xC01E, 0x97DE, 0xC01F, 0x97DF,
+	0xC020, 0x97E0, 0xC021, 0x97E1, 0xC022, 0x97E2, 0xC023, 0x97E3,
+	0xC024, 0x97E4, 0xC025, 0x97E5, 0xC026, 0x97E6, 0xC027, 0x97E7,
+	0xC028, 0x97E8, 0xC029, 0x97E9, 0xC02A, 0x97EA, 0xC02B, 0x97EB,
+	0xC02C, 0x97EC, 0xC02D, 0x97ED, 0xC02E, 0x97EE, 0xC02F, 0x97EF,
+	0xC030, 0x97F0, 0xC031, 0x97F1, 0xC032, 0x97F2, 0xC033, 0x97F3,
+	0xC034, 0x97F4, 0xC035, 0x97F5, 0xC036, 0x97F6, 0xC037, 0x97F7,
+	0xC038, 0x97F8, 0xC039, 0x97F9, 0xC03A, 0x97FA, 0xC03B, 0x97FB,
+	0xC03C, 0xBBD8, 0xC03D, 0x97FC, 0xC03E, 0x97FD, 0xC03F, 0x97FE,
+	0xC040, 0x9841, 0xC041, 0x9842, 0xC042, 0x9843, 0xC043, 0x9844,
+	0xC044, 0x9845, 0xC045, 0x9846, 0xC046, 0x9847, 0xC047, 0x9848,
+	0xC048, 0x9849, 0xC049, 0x984A, 0xC04A, 0x984B, 0xC04B, 0x984C,
+	0xC04C, 0x984D, 0xC04D, 0x984E, 0xC04E, 0x984F, 0xC04F, 0x9850,
+	0xC050, 0x9851, 0xC051, 0xBBD9, 0xC052, 0x9852, 0xC053, 0x9853,
+	0xC054, 0x9854, 0xC055, 0x9855, 0xC056, 0x9856, 0xC057, 0x9857,
+	0xC058, 0xBBDA, 0xC059, 0x9858, 0xC05A, 0x9859, 0xC05B, 0x985A,
+	0xC05C, 0xBBDB, 0xC05D, 0x9861, 0xC05E, 0x9862, 0xC05F, 0x9863,
+	0xC060, 0xBBDC, 0xC061, 0x9864, 0xC062, 0x9865, 0xC063, 0x9866,
+	0xC064, 0x9867, 0xC065, 0x9868, 0xC066, 0x9869, 0xC067, 0x986A,
+	0xC068, 0xBBDD, 0xC069, 0xBBDE, 0xC06A, 0x986B, 0xC06B, 0x986C,
+	0xC06C, 0x986D, 0xC06D, 0x986E, 0xC06E, 0x986F, 0xC06F, 0x9870,
+	0xC070, 0x9871, 0xC071, 0x9872, 0xC072, 0x9873, 0xC073, 0x9874,
+	0xC074, 0x9875, 0xC075, 0x9876, 0xC076, 0x9877, 0xC077, 0x9878,
+	0xC078, 0x9879, 0xC079, 0x987A, 0xC07A, 0x9881, 0xC07B, 0x9882,
+	0xC07C, 0x9883, 0xC07D, 0x9884, 0xC07E, 0x9885, 0xC07F, 0x9886,
+	0xC080, 0x9887, 0xC081, 0x9888, 0xC082, 0x9889, 0xC083, 0x988A,
+	0xC084, 0x988B, 0xC085, 0x988C, 0xC086, 0x988D, 0xC087, 0x988E,
+	0xC088, 0x988F, 0xC089, 0x9890, 0xC08A, 0x9891, 0xC08B, 0x9892,
+	0xC08C, 0x9893, 0xC08D, 0x9894, 0xC08E, 0x9895, 0xC08F, 0x9896,
+	0xC090, 0xBBDF, 0xC091, 0xBBE0, 0xC092, 0x9897, 0xC093, 0x9898,
+	0xC094, 0xBBE1, 0xC095, 0x9899, 0xC096, 0x989A, 0xC097, 0x989B,
+	0xC098, 0xBBE2, 0xC099, 0x989C, 0xC09A, 0x989D, 0xC09B, 0x989E,
+	0xC09C, 0x989F, 0xC09D, 0x98A0, 0xC09E, 0x98A1, 0xC09F, 0x98A2,
+	0xC0A0, 0xBBE3, 0xC0A1, 0xBBE4, 0xC0A2, 0x98A3, 0xC0A3, 0xBBE5,
+	0xC0A4, 0x98A4, 0xC0A5, 0xBBE6, 0xC0A6, 0x98A5, 0xC0A7, 0x98A6,
+	0xC0A8, 0x98A7, 0xC0A9, 0x98A8, 0xC0AA, 0x98A9, 0xC0AB, 0x98AA,
+	0xC0AC, 0xBBE7, 0xC0AD, 0xBBE8, 0xC0AE, 0x98AB, 0xC0AF, 0xBBE9,
+	0xC0B0, 0xBBEA, 0xC0B1, 0x98AC, 0xC0B2, 0x98AD, 0xC0B3, 0xBBEB,
+	0xC0B4, 0xBBEC, 0xC0B5, 0xBBED, 0xC0B6, 0xBBEE, 0xC0B7, 0x98AE,
+	0xC0B8, 0x98AF, 0xC0B9, 0x98B0, 0xC0BA, 0x98B1, 0xC0BB, 0x98B2,
+	0xC0BC, 0xBBEF, 0xC0BD, 0xBBF0, 0xC0BE, 0x98B3, 0xC0BF, 0xBBF1,
+	0xC0C0, 0xBBF2, 0xC0C1, 0xBBF3, 0xC0C2, 0x98B4, 0xC0C3, 0x98B5,
+	0xC0C4, 0x98B6, 0xC0C5, 0xBBF4, 0xC0C6, 0x98B7, 0xC0C7, 0x98B8,
+	0xC0C8, 0xBBF5, 0xC0C9, 0xBBF6, 0xC0CA, 0x98B9, 0xC0CB, 0x98BA,
+	0xC0CC, 0xBBF7, 0xC0CD, 0x98BB, 0xC0CE, 0x98BC, 0xC0CF, 0x98BD,
+	0xC0D0, 0xBBF8, 0xC0D1, 0x98BE, 0xC0D2, 0x98BF, 0xC0D3, 0x98C0,
+	0xC0D4, 0x98C1, 0xC0D5, 0x98C2, 0xC0D6, 0x98C3, 0xC0D7, 0x98C4,
+	0xC0D8, 0xBBF9, 0xC0D9, 0xBBFA, 0xC0DA, 0x98C5, 0xC0DB, 0xBBFB,
+	0xC0DC, 0xBBFC, 0xC0DD, 0xBBFD, 0xC0DE, 0x98C6, 0xC0DF, 0x98C7,
+	0xC0E0, 0x98C8, 0xC0E1, 0x98C9, 0xC0E2, 0x98CA, 0xC0E3, 0x98CB,
+	0xC0E4, 0xBBFE, 0xC0E5, 0xBCA1, 0xC0E6, 0x98CC, 0xC0E7, 0x98CD,
+	0xC0E8, 0xBCA2, 0xC0E9, 0x98CE, 0xC0EA, 0x98CF, 0xC0EB, 0x98D0,
+	0xC0EC, 0xBCA3, 0xC0ED, 0x98D1, 0xC0EE, 0x98D2, 0xC0EF, 0x98D3,
+	0xC0F0, 0x98D4, 0xC0F1, 0x98D5, 0xC0F2, 0x98D6, 0xC0F3, 0x98D7,
+	0xC0F4, 0xBCA4, 0xC0F5, 0xBCA5, 0xC0F6, 0x98D8, 0xC0F7, 0xBCA6,
+	0xC0F8, 0x98D9, 0xC0F9, 0xBCA7, 0xC0FA, 0x98DA, 0xC0FB, 0x98DB,
+	0xC0FC, 0x98DC, 0xC0FD, 0x98DD, 0xC0FE, 0x98DE, 0xC0FF, 0x98DF,
+	0xC100, 0xBCA8, 0xC101, 0x98E0, 0xC102, 0x98E1, 0xC103, 0x98E2,
+	0xC104, 0xBCA9, 0xC105, 0x98E3, 0xC106, 0x98E4, 0xC107, 0x98E5,
+	0xC108, 0xBCAA, 0xC109, 0x98E6, 0xC10A, 0x98E7, 0xC10B, 0x98E8,
+	0xC10C, 0x98E9, 0xC10D, 0x98EA, 0xC10E, 0x98EB, 0xC10F, 0x98EC,
+	0xC110, 0xBCAB, 0xC111, 0x98ED, 0xC112, 0x98EE, 0xC113, 0x98EF,
+	0xC114, 0x98F0, 0xC115, 0xBCAC, 0xC116, 0x98F1, 0xC117, 0x98F2,
+	0xC118, 0x98F3, 0xC119, 0x98F4, 0xC11A, 0x98F5, 0xC11B, 0x98F6,
+	0xC11C, 0xBCAD, 0xC11D, 0xBCAE, 0xC11E, 0xBCAF, 0xC11F, 0xBCB0,
+	0xC120, 0xBCB1, 0xC121, 0x98F7, 0xC122, 0x98F8, 0xC123, 0xBCB2,
+	0xC124, 0xBCB3, 0xC125, 0x98F9, 0xC126, 0xBCB4, 0xC127, 0xBCB5,
+	0xC128, 0x98FA, 0xC129, 0x98FB, 0xC12A, 0x98FC, 0xC12B, 0x98FD,
+	0xC12C, 0xBCB6, 0xC12D, 0xBCB7, 0xC12E, 0x98FE, 0xC12F, 0xBCB8,
+	0xC130, 0xBCB9, 0xC131, 0xBCBA, 0xC132, 0x9941, 0xC133, 0x9942,
+	0xC134, 0x9943, 0xC135, 0x9944, 0xC136, 0xBCBB, 0xC137, 0x9945,
+	0xC138, 0xBCBC, 0xC139, 0xBCBD, 0xC13A, 0x9946, 0xC13B, 0x9947,
+	0xC13C, 0xBCBE, 0xC13D, 0x9948, 0xC13E, 0x9949, 0xC13F, 0x994A,
+	0xC140, 0xBCBF, 0xC141, 0x994B, 0xC142, 0x994C, 0xC143, 0x994D,
+	0xC144, 0x994E, 0xC145, 0x994F, 0xC146, 0x9950, 0xC147, 0x9951,
+	0xC148, 0xBCC0, 0xC149, 0xBCC1, 0xC14A, 0x9952, 0xC14B, 0xBCC2,
+	0xC14C, 0xBCC3, 0xC14D, 0xBCC4, 0xC14E, 0x9953, 0xC14F, 0x9954,
+	0xC150, 0x9955, 0xC151, 0x9956, 0xC152, 0x9957, 0xC153, 0x9958,
+	0xC154, 0xBCC5, 0xC155, 0xBCC6, 0xC156, 0x9959, 0xC157, 0x995A,
+	0xC158, 0xBCC7, 0xC159, 0x9961, 0xC15A, 0x9962, 0xC15B, 0x9963,
+	0xC15C, 0xBCC8, 0xC15D, 0x9964, 0xC15E, 0x9965, 0xC15F, 0x9966,
+	0xC160, 0x9967, 0xC161, 0x9968, 0xC162, 0x9969, 0xC163, 0x996A,
+	0xC164, 0xBCC9, 0xC165, 0xBCCA, 0xC166, 0x996B, 0xC167, 0xBCCB,
+	0xC168, 0xBCCC, 0xC169, 0xBCCD, 0xC16A, 0x996C, 0xC16B, 0x996D,
+	0xC16C, 0x996E, 0xC16D, 0x996F, 0xC16E, 0x9970, 0xC16F, 0x9971,
+	0xC170, 0xBCCE, 0xC171, 0x9972, 0xC172, 0x9973, 0xC173, 0x9974,
+	0xC174, 0xBCCF, 0xC175, 0x9975, 0xC176, 0x9976, 0xC177, 0x9977,
+	0xC178, 0xBCD0, 0xC179, 0x9978, 0xC17A, 0x9979, 0xC17B, 0x997A,
+	0xC17C, 0x9981, 0xC17D, 0x9982, 0xC17E, 0x9983, 0xC17F, 0x9984,
+	0xC180, 0x9985, 0xC181, 0x9986, 0xC182, 0x9987, 0xC183, 0x9988,
+	0xC184, 0x9989, 0xC185, 0xBCD1, 0xC186, 0x998A, 0xC187, 0x998B,
+	0xC188, 0x998C, 0xC189, 0x998D, 0xC18A, 0x998E, 0xC18B, 0x998F,
+	0xC18C, 0xBCD2, 0xC18D, 0xBCD3, 0xC18E, 0xBCD4, 0xC18F, 0x9990,
+	0xC190, 0xBCD5, 0xC191, 0x9991, 0xC192, 0x9992, 0xC193, 0x9993,
+	0xC194, 0xBCD6, 0xC195, 0x9994, 0xC196, 0xBCD7, 0xC197, 0x9995,
+	0xC198, 0x9996, 0xC199, 0x9997, 0xC19A, 0x9998, 0xC19B, 0x9999,
+	0xC19C, 0xBCD8, 0xC19D, 0xBCD9, 0xC19E, 0x999A, 0xC19F, 0xBCDA,
+	0xC1A0, 0x999B, 0xC1A1, 0xBCDB, 0xC1A2, 0x999C, 0xC1A3, 0x999D,
+	0xC1A4, 0x999E, 0xC1A5, 0xBCDC, 0xC1A6, 0x999F, 0xC1A7, 0x99A0,
+	0xC1A8, 0xBCDD, 0xC1A9, 0xBCDE, 0xC1AA, 0x99A1, 0xC1AB, 0x99A2,
+	0xC1AC, 0xBCDF, 0xC1AD, 0x99A3, 0xC1AE, 0x99A4, 0xC1AF, 0x99A5,
+	0xC1B0, 0xBCE0, 0xC1B1, 0x99A6, 0xC1B2, 0x99A7, 0xC1B3, 0x99A8,
+	0xC1B4, 0x99A9, 0xC1B5, 0x99AA, 0xC1B6, 0x99AB, 0xC1B7, 0x99AC,
+	0xC1B8, 0x99AD, 0xC1B9, 0x99AE, 0xC1BA, 0x99AF, 0xC1BB, 0x99B0,
+	0xC1BC, 0x99B1, 0xC1BD, 0xBCE1, 0xC1BE, 0x99B2, 0xC1BF, 0x99B3,
+	0xC1C0, 0x99B4, 0xC1C1, 0x99B5, 0xC1C2, 0x99B6, 0xC1C3, 0x99B7,
+	0xC1C4, 0xBCE2, 0xC1C5, 0x99B8, 0xC1C6, 0x99B9, 0xC1C7, 0x99BA,
+	0xC1C8, 0xBCE3, 0xC1C9, 0x99BB, 0xC1CA, 0x99BC, 0xC1CB, 0x99BD,
+	0xC1CC, 0xBCE4, 0xC1CD, 0x99BE, 0xC1CE, 0x99BF, 0xC1CF, 0x99C0,
+	0xC1D0, 0x99C1, 0xC1D1, 0x99C2, 0xC1D2, 0x99C3, 0xC1D3, 0x99C4,
+	0xC1D4, 0xBCE5, 0xC1D5, 0x99C5, 0xC1D6, 0x99C6, 0xC1D7, 0xBCE6,
+	0xC1D8, 0xBCE7, 0xC1D9, 0x99C7, 0xC1DA, 0x99C8, 0xC1DB, 0x99C9,
+	0xC1DC, 0x99CA, 0xC1DD, 0x99CB, 0xC1DE, 0x99CC, 0xC1DF, 0x99CD,
+	0xC1E0, 0xBCE8, 0xC1E1, 0x99CE, 0xC1E2, 0x99CF, 0xC1E3, 0x99D0,
+	0xC1E4, 0xBCE9, 0xC1E5, 0x99D1, 0xC1E6, 0x99D2, 0xC1E7, 0x99D3,
+	0xC1E8, 0xBCEA, 0xC1E9, 0x99D4, 0xC1EA, 0x99D5, 0xC1EB, 0x99D6,
+	0xC1EC, 0x99D7, 0xC1ED, 0x99D8, 0xC1EE, 0x99D9, 0xC1EF, 0x99DA,
+	0xC1F0, 0xBCEB, 0xC1F1, 0xBCEC, 0xC1F2, 0x99DB, 0xC1F3, 0xBCED,
+	0xC1F4, 0x99DC, 0xC1F5, 0x99DD, 0xC1F6, 0x99DE, 0xC1F7, 0x99DF,
+	0xC1F8, 0x99E0, 0xC1F9, 0x99E1, 0xC1FA, 0x99E2, 0xC1FB, 0x99E3,
+	0xC1FC, 0xBCEE, 0xC1FD, 0xBCEF, 0xC1FE, 0x99E4, 0xC1FF, 0x99E5,
+	0xC200, 0xBCF0, 0xC201, 0x99E6, 0xC202, 0x99E7, 0xC203, 0x99E8,
+	0xC204, 0xBCF1, 0xC205, 0x99E9, 0xC206, 0x99EA, 0xC207, 0x99EB,
+	0xC208, 0x99EC, 0xC209, 0x99ED, 0xC20A, 0x99EE, 0xC20B, 0x99EF,
+	0xC20C, 0xBCF2, 0xC20D, 0xBCF3, 0xC20E, 0x99F0, 0xC20F, 0xBCF4,
+	0xC210, 0x99F1, 0xC211, 0xBCF5, 0xC212, 0x99F2, 0xC213, 0x99F3,
+	0xC214, 0x99F4, 0xC215, 0x99F5, 0xC216, 0x99F6, 0xC217, 0x99F7,
+	0xC218, 0xBCF6, 0xC219, 0xBCF7, 0xC21A, 0x99F8, 0xC21B, 0x99F9,
+	0xC21C, 0xBCF8, 0xC21D, 0x99FA, 0xC21E, 0x99FB, 0xC21F, 0xBCF9,
+	0xC220, 0xBCFA, 0xC221, 0x99FC, 0xC222, 0x99FD, 0xC223, 0x99FE,
+	0xC224, 0x9A41, 0xC225, 0x9A42, 0xC226, 0x9A43, 0xC227, 0x9A44,
+	0xC228, 0xBCFB, 0xC229, 0xBCFC, 0xC22A, 0x9A45, 0xC22B, 0xBCFD,
+	0xC22C, 0x9A46, 0xC22D, 0xBCFE, 0xC22E, 0x9A47, 0xC22F, 0xBDA1,
+	0xC230, 0x9A48, 0xC231, 0xBDA2, 0xC232, 0xBDA3, 0xC233, 0x9A49,
+	0xC234, 0xBDA4, 0xC235, 0x9A4A, 0xC236, 0x9A4B, 0xC237, 0x9A4C,
+	0xC238, 0x9A4D, 0xC239, 0x9A4E, 0xC23A, 0x9A4F, 0xC23B, 0x9A50,
+	0xC23C, 0x9A51, 0xC23D, 0x9A52, 0xC23E, 0x9A53, 0xC23F, 0x9A54,
+	0xC240, 0x9A55, 0xC241, 0x9A56, 0xC242, 0x9A57, 0xC243, 0x9A58,
+	0xC244, 0x9A59, 0xC245, 0x9A5A, 0xC246, 0x9A61, 0xC247, 0x9A62,
+	0xC248, 0xBDA5, 0xC249, 0x9A63, 0xC24A, 0x9A64, 0xC24B, 0x9A65,
+	0xC24C, 0x9A66, 0xC24D, 0x9A67, 0xC24E, 0x9A68, 0xC24F, 0x9A69,
+	0xC250, 0xBDA6, 0xC251, 0xBDA7, 0xC252, 0x9A6A, 0xC253, 0x9A6B,
+	0xC254, 0xBDA8, 0xC255, 0x9A6C, 0xC256, 0x9A6D, 0xC257, 0x9A6E,
+	0xC258, 0xBDA9, 0xC259, 0x9A6F, 0xC25A, 0x9A70, 0xC25B, 0x9A71,
+	0xC25C, 0x9A72, 0xC25D, 0x9A73, 0xC25E, 0x9A74, 0xC25F, 0x9A75,
+	0xC260, 0xBDAA, 0xC261, 0x9A76, 0xC262, 0x9A77, 0xC263, 0x9A78,
+	0xC264, 0x9A79, 0xC265, 0xBDAB, 0xC266, 0x9A7A, 0xC267, 0x9A81,
+	0xC268, 0x9A82, 0xC269, 0x9A83, 0xC26A, 0x9A84, 0xC26B, 0x9A85,
+	0xC26C, 0xBDAC, 0xC26D, 0xBDAD, 0xC26E, 0x9A86, 0xC26F, 0x9A87,
+	0xC270, 0xBDAE, 0xC271, 0x9A88, 0xC272, 0x9A89, 0xC273, 0x9A8A,
+	0xC274, 0xBDAF, 0xC275, 0x9A8B, 0xC276, 0x9A8C, 0xC277, 0x9A8D,
+	0xC278, 0x9A8E, 0xC279, 0x9A8F, 0xC27A, 0x9A90, 0xC27B, 0x9A91,
+	0xC27C, 0xBDB0, 0xC27D, 0xBDB1, 0xC27E, 0x9A92, 0xC27F, 0xBDB2,
+	0xC280, 0x9A93, 0xC281, 0xBDB3, 0xC282, 0x9A94, 0xC283, 0x9A95,
+	0xC284, 0x9A96, 0xC285, 0x9A97, 0xC286, 0x9A98, 0xC287, 0x9A99,
+	0xC288, 0xBDB4, 0xC289, 0xBDB5, 0xC28A, 0x9A9A, 0xC28B, 0x9A9B,
+	0xC28C, 0x9A9C, 0xC28D, 0x9A9D, 0xC28E, 0x9A9E, 0xC28F, 0x9A9F,
+	0xC290, 0xBDB6, 0xC291, 0x9AA0, 0xC292, 0x9AA1, 0xC293, 0x9AA2,
+	0xC294, 0x9AA3, 0xC295, 0x9AA4, 0xC296, 0x9AA5, 0xC297, 0x9AA6,
+	0xC298, 0xBDB7, 0xC299, 0x9AA7, 0xC29A, 0x9AA8, 0xC29B, 0xBDB8,
+	0xC29C, 0x9AA9, 0xC29D, 0xBDB9, 0xC29E, 0x9AAA, 0xC29F, 0x9AAB,
+	0xC2A0, 0x9AAC, 0xC2A1, 0x9AAD, 0xC2A2, 0x9AAE, 0xC2A3, 0x9AAF,
+	0xC2A4, 0xBDBA, 0xC2A5, 0xBDBB, 0xC2A6, 0x9AB0, 0xC2A7, 0x9AB1,
+	0xC2A8, 0xBDBC, 0xC2A9, 0x9AB2, 0xC2AA, 0x9AB3, 0xC2AB, 0x9AB4,
+	0xC2AC, 0xBDBD, 0xC2AD, 0xBDBE, 0xC2AE, 0x9AB5, 0xC2AF, 0x9AB6,
+	0xC2B0, 0x9AB7, 0xC2B1, 0x9AB8, 0xC2B2, 0x9AB9, 0xC2B3, 0x9ABA,
+	0xC2B4, 0xBDBF, 0xC2B5, 0xBDC0, 0xC2B6, 0x9ABB, 0xC2B7, 0xBDC1,
+	0xC2B8, 0x9ABC, 0xC2B9, 0xBDC2, 0xC2BA, 0x9ABD, 0xC2BB, 0x9ABE,
+	0xC2BC, 0x9ABF, 0xC2BD, 0x9AC0, 0xC2BE, 0x9AC1, 0xC2BF, 0x9AC2,
+	0xC2C0, 0x9AC3, 0xC2C1, 0x9AC4, 0xC2C2, 0x9AC5, 0xC2C3, 0x9AC6,
+	0xC2C4, 0x9AC7, 0xC2C5, 0x9AC8, 0xC2C6, 0x9AC9, 0xC2C7, 0x9ACA,
+	0xC2C8, 0x9ACB, 0xC2C9, 0x9ACC, 0xC2CA, 0x9ACD, 0xC2CB, 0x9ACE,
+	0xC2CC, 0x9ACF, 0xC2CD, 0x9AD0, 0xC2CE, 0x9AD1, 0xC2CF, 0x9AD2,
+	0xC2D0, 0x9AD3, 0xC2D1, 0x9AD4, 0xC2D2, 0x9AD5, 0xC2D3, 0x9AD6,
+	0xC2D4, 0x9AD7, 0xC2D5, 0x9AD8, 0xC2D6, 0x9AD9, 0xC2D7, 0x9ADA,
+	0xC2D8, 0x9ADB, 0xC2D9, 0x9ADC, 0xC2DA, 0x9ADD, 0xC2DB, 0x9ADE,
+	0xC2DC, 0xBDC3, 0xC2DD, 0xBDC4, 0xC2DE, 0x9ADF, 0xC2DF, 0x9AE0,
+	0xC2E0, 0xBDC5, 0xC2E1, 0x9AE1, 0xC2E2, 0x9AE2, 0xC2E3, 0xBDC6,
+	0xC2E4, 0xBDC7, 0xC2E5, 0x9AE3, 0xC2E6, 0x9AE4, 0xC2E7, 0x9AE5,
+	0xC2E8, 0x9AE6, 0xC2E9, 0x9AE7, 0xC2EA, 0x9AE8, 0xC2EB, 0xBDC8,
+	0xC2EC, 0xBDC9, 0xC2ED, 0xBDCA, 0xC2EE, 0x9AE9, 0xC2EF, 0xBDCB,
+	0xC2F0, 0x9AEA, 0xC2F1, 0xBDCC, 0xC2F2, 0x9AEB, 0xC2F3, 0x9AEC,
+	0xC2F4, 0x9AED, 0xC2F5, 0x9AEE, 0xC2F6, 0xBDCD, 0xC2F7, 0x9AEF,
+	0xC2F8, 0xBDCE, 0xC2F9, 0xBDCF, 0xC2FA, 0x9AF0, 0xC2FB, 0xBDD0,
+	0xC2FC, 0xBDD1, 0xC2FD, 0x9AF1, 0xC2FE, 0x9AF2, 0xC2FF, 0x9AF3,
+	0xC300, 0xBDD2, 0xC301, 0x9AF4, 0xC302, 0x9AF5, 0xC303, 0x9AF6,
+	0xC304, 0x9AF7, 0xC305, 0x9AF8, 0xC306, 0x9AF9, 0xC307, 0x9AFA,
+	0xC308, 0xBDD3, 0xC309, 0xBDD4, 0xC30A, 0x9AFB, 0xC30B, 0x9AFC,
+	0xC30C, 0xBDD5, 0xC30D, 0xBDD6, 0xC30E, 0x9AFD, 0xC30F, 0x9AFE,
+	0xC310, 0x9B41, 0xC311, 0x9B42, 0xC312, 0x9B43, 0xC313, 0xBDD7,
+	0xC314, 0xBDD8, 0xC315, 0xBDD9, 0xC316, 0x9B44, 0xC317, 0x9B45,
+	0xC318, 0xBDDA, 0xC319, 0x9B46, 0xC31A, 0x9B47, 0xC31B, 0x9B48,
+	0xC31C, 0xBDDB, 0xC31D, 0x9B49, 0xC31E, 0x9B4A, 0xC31F, 0x9B4B,
+	0xC320, 0x9B4C, 0xC321, 0x9B4D, 0xC322, 0x9B4E, 0xC323, 0x9B4F,
+	0xC324, 0xBDDC, 0xC325, 0xBDDD, 0xC326, 0x9B50, 0xC327, 0x9B51,
+	0xC328, 0xBDDE, 0xC329, 0xBDDF, 0xC32A, 0x9B52, 0xC32B, 0x9B53,
+	0xC32C, 0x9B54, 0xC32D, 0x9B55, 0xC32E, 0x9B56, 0xC32F, 0x9B57,
+	0xC330, 0x9B58, 0xC331, 0x9B59, 0xC332, 0x9B5A, 0xC333, 0x9B61,
+	0xC334, 0x9B62, 0xC335, 0x9B63, 0xC336, 0x9B64, 0xC337, 0x9B65,
+	0xC338, 0x9B66, 0xC339, 0x9B67, 0xC33A, 0x9B68, 0xC33B, 0x9B69,
+	0xC33C, 0x9B6A, 0xC33D, 0x9B6B, 0xC33E, 0x9B6C, 0xC33F, 0x9B6D,
+	0xC340, 0x9B6E, 0xC341, 0x9B6F, 0xC342, 0x9B70, 0xC343, 0x9B71,
+	0xC344, 0x9B72, 0xC345, 0xBDE0, 0xC346, 0x9B73, 0xC347, 0x9B74,
+	0xC348, 0x9B75, 0xC349, 0x9B76, 0xC34A, 0x9B77, 0xC34B, 0x9B78,
+	0xC34C, 0x9B79, 0xC34D, 0x9B7A, 0xC34E, 0x9B81, 0xC34F, 0x9B82,
+	0xC350, 0x9B83, 0xC351, 0x9B84, 0xC352, 0x9B85, 0xC353, 0x9B86,
+	0xC354, 0x9B87, 0xC355, 0x9B88, 0xC356, 0x9B89, 0xC357, 0x9B8A,
+	0xC358, 0x9B8B, 0xC359, 0x9B8C, 0xC35A, 0x9B8D, 0xC35B, 0x9B8E,
+	0xC35C, 0x9B8F, 0xC35D, 0x9B90, 0xC35E, 0x9B91, 0xC35F, 0x9B92,
+	0xC360, 0x9B93, 0xC361, 0x9B94, 0xC362, 0x9B95, 0xC363, 0x9B96,
+	0xC364, 0x9B97, 0xC365, 0x9B98, 0xC366, 0x9B99, 0xC367, 0x9B9A,
+	0xC368, 0xBDE1, 0xC369, 0xBDE2, 0xC36A, 0x9B9B, 0xC36B, 0x9B9C,
+	0xC36C, 0xBDE3, 0xC36D, 0x9B9D, 0xC36E, 0x9B9E, 0xC36F, 0x9B9F,
+	0xC370, 0xBDE4, 0xC371, 0x9BA0, 0xC372, 0xBDE5, 0xC373, 0x9BA1,
+	0xC374, 0x9BA2, 0xC375, 0x9BA3, 0xC376, 0x9BA4, 0xC377, 0x9BA5,
+	0xC378, 0xBDE6, 0xC379, 0xBDE7, 0xC37A, 0x9BA6, 0xC37B, 0x9BA7,
+	0xC37C, 0xBDE8, 0xC37D, 0xBDE9, 0xC37E, 0x9BA8, 0xC37F, 0x9BA9,
+	0xC380, 0x9BAA, 0xC381, 0x9BAB, 0xC382, 0x9BAC, 0xC383, 0x9BAD,
+	0xC384, 0xBDEA, 0xC385, 0x9BAE, 0xC386, 0x9BAF, 0xC387, 0x9BB0,
+	0xC388, 0xBDEB, 0xC389, 0x9BB1, 0xC38A, 0x9BB2, 0xC38B, 0x9BB3,
+	0xC38C, 0xBDEC, 0xC38D, 0x9BB4, 0xC38E, 0x9BB5, 0xC38F, 0x9BB6,
+	0xC390, 0x9BB7, 0xC391, 0x9BB8, 0xC392, 0x9BB9, 0xC393, 0x9BBA,
+	0xC394, 0x9BBB, 0xC395, 0x9BBC, 0xC396, 0x9BBD, 0xC397, 0x9BBE,
+	0xC398, 0x9BBF, 0xC399, 0x9BC0, 0xC39A, 0x9BC1, 0xC39B, 0x9BC2,
+	0xC39C, 0x9BC3, 0xC39D, 0x9BC4, 0xC39E, 0x9BC5, 0xC39F, 0x9BC6,
+	0xC3A0, 0x9BC7, 0xC3A1, 0x9BC8, 0xC3A2, 0x9BC9, 0xC3A3, 0x9BCA,
+	0xC3A4, 0x9BCB, 0xC3A5, 0x9BCC, 0xC3A6, 0x9BCD, 0xC3A7, 0x9BCE,
+	0xC3A8, 0x9BCF, 0xC3A9, 0x9BD0, 0xC3AA, 0x9BD1, 0xC3AB, 0x9BD2,
+	0xC3AC, 0x9BD3, 0xC3AD, 0x9BD4, 0xC3AE, 0x9BD5, 0xC3AF, 0x9BD6,
+	0xC3B0, 0x9BD7, 0xC3B1, 0x9BD8, 0xC3B2, 0x9BD9, 0xC3B3, 0x9BDA,
+	0xC3B4, 0x9BDB, 0xC3B5, 0x9BDC, 0xC3B6, 0x9BDD, 0xC3B7, 0x9BDE,
+	0xC3B8, 0x9BDF, 0xC3B9, 0x9BE0, 0xC3BA, 0x9BE1, 0xC3BB, 0x9BE2,
+	0xC3BC, 0x9BE3, 0xC3BD, 0x9BE4, 0xC3BE, 0x9BE5, 0xC3BF, 0x9BE6,
+	0xC3C0, 0xBDED, 0xC3C1, 0x9BE7, 0xC3C2, 0x9BE8, 0xC3C3, 0x9BE9,
+	0xC3C4, 0x9BEA, 0xC3C5, 0x9BEB, 0xC3C6, 0x9BEC, 0xC3C7, 0x9BED,
+	0xC3C8, 0x9BEE, 0xC3C9, 0x9BEF, 0xC3CA, 0x9BF0, 0xC3CB, 0x9BF1,
+	0xC3CC, 0x9BF2, 0xC3CD, 0x9BF3, 0xC3CE, 0x9BF4, 0xC3CF, 0x9BF5,
+	0xC3D0, 0x9BF6, 0xC3D1, 0x9BF7, 0xC3D2, 0x9BF8, 0xC3D3, 0x9BF9,
+	0xC3D4, 0x9BFA, 0xC3D5, 0x9BFB, 0xC3D6, 0x9BFC, 0xC3D7, 0x9BFD,
+	0xC3D8, 0xBDEE, 0xC3D9, 0xBDEF, 0xC3DA, 0x9BFE, 0xC3DB, 0x9C41,
+	0xC3DC, 0xBDF0, 0xC3DD, 0x9C42, 0xC3DE, 0x9C43, 0xC3DF, 0xBDF1,
+	0xC3E0, 0xBDF2, 0xC3E1, 0x9C44, 0xC3E2, 0xBDF3, 0xC3E3, 0x9C45,
+	0xC3E4, 0x9C46, 0xC3E5, 0x9C47, 0xC3E6, 0x9C48, 0xC3E7, 0x9C49,
+	0xC3E8, 0xBDF4, 0xC3E9, 0xBDF5, 0xC3EA, 0x9C4A, 0xC3EB, 0x9C4B,
+	0xC3EC, 0x9C4C, 0xC3ED, 0xBDF6, 0xC3EE, 0x9C4D, 0xC3EF, 0x9C4E,
+	0xC3F0, 0x9C4F, 0xC3F1, 0x9C50, 0xC3F2, 0x9C51, 0xC3F3, 0x9C52,
+	0xC3F4, 0xBDF7, 0xC3F5, 0xBDF8, 0xC3F6, 0x9C53, 0xC3F7, 0x9C54,
+	0xC3F8, 0xBDF9, 0xC3F9, 0x9C55, 0xC3FA, 0x9C56, 0xC3FB, 0x9C57,
+	0xC3FC, 0x9C58, 0xC3FD, 0x9C59, 0xC3FE, 0x9C5A, 0xC3FF, 0x9C61,
+	0xC400, 0x9C62, 0xC401, 0x9C63, 0xC402, 0x9C64, 0xC403, 0x9C65,
+	0xC404, 0x9C66, 0xC405, 0x9C67, 0xC406, 0x9C68, 0xC407, 0x9C69,
+	0xC408, 0xBDFA, 0xC409, 0x9C6A, 0xC40A, 0x9C6B, 0xC40B, 0x9C6C,
+	0xC40C, 0x9C6D, 0xC40D, 0x9C6E, 0xC40E, 0x9C6F, 0xC40F, 0x9C70,
+	0xC410, 0xBDFB, 0xC411, 0x9C71, 0xC412, 0x9C72, 0xC413, 0x9C73,
+	0xC414, 0x9C74, 0xC415, 0x9C75, 0xC416, 0x9C76, 0xC417, 0x9C77,
+	0xC418, 0x9C78, 0xC419, 0x9C79, 0xC41A, 0x9C7A, 0xC41B, 0x9C81,
+	0xC41C, 0x9C82, 0xC41D, 0x9C83, 0xC41E, 0x9C84, 0xC41F, 0x9C85,
+	0xC420, 0x9C86, 0xC421, 0x9C87, 0xC422, 0x9C88, 0xC423, 0x9C89,
+	0xC424, 0xBDFC, 0xC425, 0x9C8A, 0xC426, 0x9C8B, 0xC427, 0x9C8C,
+	0xC428, 0x9C8D, 0xC429, 0x9C8E, 0xC42A, 0x9C8F, 0xC42B, 0x9C90,
+	0xC42C, 0xBDFD, 0xC42D, 0x9C91, 0xC42E, 0x9C92, 0xC42F, 0x9C93,
+	0xC430, 0xBDFE, 0xC431, 0x9C94, 0xC432, 0x9C95, 0xC433, 0x9C96,
+	0xC434, 0xBEA1, 0xC435, 0x9C97, 0xC436, 0x9C98, 0xC437, 0x9C99,
+	0xC438, 0x9C9A, 0xC439, 0x9C9B, 0xC43A, 0x9C9C, 0xC43B, 0x9C9D,
+	0xC43C, 0xBEA2, 0xC43D, 0xBEA3, 0xC43E, 0x9C9E, 0xC43F, 0x9C9F,
+	0xC440, 0x9CA0, 0xC441, 0x9CA1, 0xC442, 0x9CA2, 0xC443, 0x9CA3,
+	0xC444, 0x9CA4, 0xC445, 0x9CA5, 0xC446, 0x9CA6, 0xC447, 0x9CA7,
+	0xC448, 0xBEA4, 0xC449, 0x9CA8, 0xC44A, 0x9CA9, 0xC44B, 0x9CAA,
+	0xC44C, 0x9CAB, 0xC44D, 0x9CAC, 0xC44E, 0x9CAD, 0xC44F, 0x9CAE,
+	0xC450, 0x9CAF, 0xC451, 0x9CB0, 0xC452, 0x9CB1, 0xC453, 0x9CB2,
+	0xC454, 0x9CB3, 0xC455, 0x9CB4, 0xC456, 0x9CB5, 0xC457, 0x9CB6,
+	0xC458, 0x9CB7, 0xC459, 0x9CB8, 0xC45A, 0x9CB9, 0xC45B, 0x9CBA,
+	0xC45C, 0x9CBB, 0xC45D, 0x9CBC, 0xC45E, 0x9CBD, 0xC45F, 0x9CBE,
+	0xC460, 0x9CBF, 0xC461, 0x9CC0, 0xC462, 0x9CC1, 0xC463, 0x9CC2,
+	0xC464, 0xBEA5, 0xC465, 0xBEA6, 0xC466, 0x9CC3, 0xC467, 0x9CC4,
+	0xC468, 0xBEA7, 0xC469, 0x9CC5, 0xC46A, 0x9CC6, 0xC46B, 0x9CC7,
+	0xC46C, 0xBEA8, 0xC46D, 0x9CC8, 0xC46E, 0x9CC9, 0xC46F, 0x9CCA,
+	0xC470, 0x9CCB, 0xC471, 0x9CCC, 0xC472, 0x9CCD, 0xC473, 0x9CCE,
+	0xC474, 0xBEA9, 0xC475, 0xBEAA, 0xC476, 0x9CCF, 0xC477, 0x9CD0,
+	0xC478, 0x9CD1, 0xC479, 0xBEAB, 0xC47A, 0x9CD2, 0xC47B, 0x9CD3,
+	0xC47C, 0x9CD4, 0xC47D, 0x9CD5, 0xC47E, 0x9CD6, 0xC47F, 0x9CD7,
+	0xC480, 0xBEAC, 0xC481, 0x9CD8, 0xC482, 0x9CD9, 0xC483, 0x9CDA,
+	0xC484, 0x9CDB, 0xC485, 0x9CDC, 0xC486, 0x9CDD, 0xC487, 0x9CDE,
+	0xC488, 0x9CDF, 0xC489, 0x9CE0, 0xC48A, 0x9CE1, 0xC48B, 0x9CE2,
+	0xC48C, 0x9CE3, 0xC48D, 0x9CE4, 0xC48E, 0x9CE5, 0xC48F, 0x9CE6,
+	0xC490, 0x9CE7, 0xC491, 0x9CE8, 0xC492, 0x9CE9, 0xC493, 0x9CEA,
+	0xC494, 0xBEAD, 0xC495, 0x9CEB, 0xC496, 0x9CEC, 0xC497, 0x9CED,
+	0xC498, 0x9CEE, 0xC499, 0x9CEF, 0xC49A, 0x9CF0, 0xC49B, 0x9CF1,
+	0xC49C, 0xBEAE, 0xC49D, 0x9CF2, 0xC49E, 0x9CF3, 0xC49F, 0x9CF4,
+	0xC4A0, 0x9CF5, 0xC4A1, 0x9CF6, 0xC4A2, 0x9CF7, 0xC4A3, 0x9CF8,
+	0xC4A4, 0x9CF9, 0xC4A5, 0x9CFA, 0xC4A6, 0x9CFB, 0xC4A7, 0x9CFC,
+	0xC4A8, 0x9CFD, 0xC4A9, 0x9CFE, 0xC4AA, 0x9D41, 0xC4AB, 0x9D42,
+	0xC4AC, 0x9D43, 0xC4AD, 0x9D44, 0xC4AE, 0x9D45, 0xC4AF, 0x9D46,
+	0xC4B0, 0x9D47, 0xC4B1, 0x9D48, 0xC4B2, 0x9D49, 0xC4B3, 0x9D4A,
+	0xC4B4, 0x9D4B, 0xC4B5, 0x9D4C, 0xC4B6, 0x9D4D, 0xC4B7, 0x9D4E,
+	0xC4B8, 0xBEAF, 0xC4B9, 0x9D4F, 0xC4BA, 0x9D50, 0xC4BB, 0x9D51,
+	0xC4BC, 0xBEB0, 0xC4BD, 0x9D52, 0xC4BE, 0x9D53, 0xC4BF, 0x9D54,
+	0xC4C0, 0x9D55, 0xC4C1, 0x9D56, 0xC4C2, 0x9D57, 0xC4C3, 0x9D58,
+	0xC4C4, 0x9D59, 0xC4C5, 0x9D5A, 0xC4C6, 0x9D61, 0xC4C7, 0x9D62,
+	0xC4C8, 0x9D63, 0xC4C9, 0x9D64, 0xC4CA, 0x9D65, 0xC4CB, 0x9D66,
+	0xC4CC, 0x9D67, 0xC4CD, 0x9D68, 0xC4CE, 0x9D69, 0xC4CF, 0x9D6A,
+	0xC4D0, 0x9D6B, 0xC4D1, 0x9D6C, 0xC4D2, 0x9D6D, 0xC4D3, 0x9D6E,
+	0xC4D4, 0x9D6F, 0xC4D5, 0x9D70, 0xC4D6, 0x9D71, 0xC4D7, 0x9D72,
+	0xC4D8, 0x9D73, 0xC4D9, 0x9D74, 0xC4DA, 0x9D75, 0xC4DB, 0x9D76,
+	0xC4DC, 0x9D77, 0xC4DD, 0x9D78, 0xC4DE, 0x9D79, 0xC4DF, 0x9D7A,
+	0xC4E0, 0x9D81, 0xC4E1, 0x9D82, 0xC4E2, 0x9D83, 0xC4E3, 0x9D84,
+	0xC4E4, 0x9D85, 0xC4E5, 0x9D86, 0xC4E6, 0x9D87, 0xC4E7, 0x9D88,
+	0xC4E8, 0x9D89, 0xC4E9, 0xBEB1, 0xC4EA, 0x9D8A, 0xC4EB, 0x9D8B,
+	0xC4EC, 0x9D8C, 0xC4ED, 0x9D8D, 0xC4EE, 0x9D8E, 0xC4EF, 0x9D8F,
+	0xC4F0, 0xBEB2, 0xC4F1, 0xBEB3, 0xC4F2, 0x9D90, 0xC4F3, 0x9D91,
+	0xC4F4, 0xBEB4, 0xC4F5, 0x9D92, 0xC4F6, 0x9D93, 0xC4F7, 0x9D94,
+	0xC4F8, 0xBEB5, 0xC4F9, 0x9D95, 0xC4FA, 0xBEB6, 0xC4FB, 0x9D96,
+	0xC4FC, 0x9D97, 0xC4FD, 0x9D98, 0xC4FE, 0x9D99, 0xC4FF, 0xBEB7,
+	0xC500, 0xBEB8, 0xC501, 0xBEB9, 0xC502, 0x9D9A, 0xC503, 0x9D9B,
+	0xC504, 0x9D9C, 0xC505, 0x9D9D, 0xC506, 0x9D9E, 0xC507, 0x9D9F,
+	0xC508, 0x9DA0, 0xC509, 0x9DA1, 0xC50A, 0x9DA2, 0xC50B, 0x9DA3,
+	0xC50C, 0xBEBA, 0xC50D, 0x9DA4, 0xC50E, 0x9DA5, 0xC50F, 0x9DA6,
+	0xC510, 0xBEBB, 0xC511, 0x9DA7, 0xC512, 0x9DA8, 0xC513, 0x9DA9,
+	0xC514, 0xBEBC, 0xC515, 0x9DAA, 0xC516, 0x9DAB, 0xC517, 0x9DAC,
+	0xC518, 0x9DAD, 0xC519, 0x9DAE, 0xC51A, 0x9DAF, 0xC51B, 0x9DB0,
+	0xC51C, 0xBEBD, 0xC51D, 0x9DB1, 0xC51E, 0x9DB2, 0xC51F, 0x9DB3,
+	0xC520, 0x9DB4, 0xC521, 0x9DB5, 0xC522, 0x9DB6, 0xC523, 0x9DB7,
+	0xC524, 0x9DB8, 0xC525, 0x9DB9, 0xC526, 0x9DBA, 0xC527, 0x9DBB,
+	0xC528, 0xBEBE, 0xC529, 0xBEBF, 0xC52A, 0x9DBC, 0xC52B, 0x9DBD,
+	0xC52C, 0xBEC0, 0xC52D, 0x9DBE, 0xC52E, 0x9DBF, 0xC52F, 0x9DC0,
+	0xC530, 0xBEC1, 0xC531, 0x9DC1, 0xC532, 0x9DC2, 0xC533, 0x9DC3,
+	0xC534, 0x9DC4, 0xC535, 0x9DC5, 0xC536, 0x9DC6, 0xC537, 0x9DC7,
+	0xC538, 0xBEC2, 0xC539, 0xBEC3, 0xC53A, 0x9DC8, 0xC53B, 0xBEC4,
+	0xC53C, 0x9DC9, 0xC53D, 0xBEC5, 0xC53E, 0x9DCA, 0xC53F, 0x9DCB,
+	0xC540, 0x9DCC, 0xC541, 0x9DCD, 0xC542, 0x9DCE, 0xC543, 0x9DCF,
+	0xC544, 0xBEC6, 0xC545, 0xBEC7, 0xC546, 0x9DD0, 0xC547, 0x9DD1,
+	0xC548, 0xBEC8, 0xC549, 0xBEC9, 0xC54A, 0xBECA, 0xC54B, 0x9DD2,
+	0xC54C, 0xBECB, 0xC54D, 0xBECC, 0xC54E, 0xBECD, 0xC54F, 0x9DD3,
+	0xC550, 0x9DD4, 0xC551, 0x9DD5, 0xC552, 0x9DD6, 0xC553, 0xBECE,
+	0xC554, 0xBECF, 0xC555, 0xBED0, 0xC556, 0x9DD7, 0xC557, 0xBED1,
+	0xC558, 0xBED2, 0xC559, 0xBED3, 0xC55A, 0x9DD8, 0xC55B, 0x9DD9,
+	0xC55C, 0x9DDA, 0xC55D, 0xBED4, 0xC55E, 0xBED5, 0xC55F, 0x9DDB,
+	0xC560, 0xBED6, 0xC561, 0xBED7, 0xC562, 0x9DDC, 0xC563, 0x9DDD,
+	0xC564, 0xBED8, 0xC565, 0x9DDE, 0xC566, 0x9DDF, 0xC567, 0x9DE0,
+	0xC568, 0xBED9, 0xC569, 0x9DE1, 0xC56A, 0x9DE2, 0xC56B, 0x9DE3,
+	0xC56C, 0x9DE4, 0xC56D, 0x9DE5, 0xC56E, 0x9DE6, 0xC56F, 0x9DE7,
+	0xC570, 0xBEDA, 0xC571, 0xBEDB, 0xC572, 0x9DE8, 0xC573, 0xBEDC,
+	0xC574, 0xBEDD, 0xC575, 0xBEDE, 0xC576, 0x9DE9, 0xC577, 0x9DEA,
+	0xC578, 0x9DEB, 0xC579, 0x9DEC, 0xC57A, 0x9DED, 0xC57B, 0x9DEE,
+	0xC57C, 0xBEDF, 0xC57D, 0xBEE0, 0xC57E, 0x9DEF, 0xC57F, 0x9DF0,
+	0xC580, 0xBEE1, 0xC581, 0x9DF1, 0xC582, 0x9DF2, 0xC583, 0x9DF3,
+	0xC584, 0xBEE2, 0xC585, 0x9DF4, 0xC586, 0x9DF5, 0xC587, 0xBEE3,
+	0xC588, 0x9DF6, 0xC589, 0x9DF7, 0xC58A, 0x9DF8, 0xC58B, 0x9DF9,
+	0xC58C, 0xBEE4, 0xC58D, 0xBEE5, 0xC58E, 0x9DFA, 0xC58F, 0xBEE6,
+	0xC590, 0x9DFB, 0xC591, 0xBEE7, 0xC592, 0x9DFC, 0xC593, 0x9DFD,
+	0xC594, 0x9DFE, 0xC595, 0xBEE8, 0xC596, 0x9E41, 0xC597, 0xBEE9,
+	0xC598, 0xBEEA, 0xC599, 0x9E42, 0xC59A, 0x9E43, 0xC59B, 0x9E44,
+	0xC59C, 0xBEEB, 0xC59D, 0x9E45, 0xC59E, 0x9E46, 0xC59F, 0x9E47,
+	0xC5A0, 0xBEEC, 0xC5A1, 0x9E48, 0xC5A2, 0x9E49, 0xC5A3, 0x9E4A,
+	0xC5A4, 0x9E4B, 0xC5A5, 0x9E4C, 0xC5A6, 0x9E4D, 0xC5A7, 0x9E4E,
+	0xC5A8, 0x9E4F, 0xC5A9, 0xBEED, 0xC5AA, 0x9E50, 0xC5AB, 0x9E51,
+	0xC5AC, 0x9E52, 0xC5AD, 0x9E53, 0xC5AE, 0x9E54, 0xC5AF, 0x9E55,
+	0xC5B0, 0x9E56, 0xC5B1, 0x9E57, 0xC5B2, 0x9E58, 0xC5B3, 0x9E59,
+	0xC5B4, 0xBEEE, 0xC5B5, 0xBEEF, 0xC5B6, 0x9E5A, 0xC5B7, 0x9E61,
+	0xC5B8, 0xBEF0, 0xC5B9, 0xBEF1, 0xC5BA, 0x9E62, 0xC5BB, 0xBEF2,
+	0xC5BC, 0xBEF3, 0xC5BD, 0xBEF4, 0xC5BE, 0xBEF5, 0xC5BF, 0x9E63,
+	0xC5C0, 0x9E64, 0xC5C1, 0x9E65, 0xC5C2, 0x9E66, 0xC5C3, 0x9E67,
+	0xC5C4, 0xBEF6, 0xC5C5, 0xBEF7, 0xC5C6, 0xBEF8, 0xC5C7, 0xBEF9,
+	0xC5C8, 0xBEFA, 0xC5C9, 0xBEFB, 0xC5CA, 0xBEFC, 0xC5CB, 0x9E68,
+	0xC5CC, 0xBEFD, 0xC5CD, 0x9E69, 0xC5CE, 0xBEFE, 0xC5CF, 0x9E6A,
+	0xC5D0, 0xBFA1, 0xC5D1, 0xBFA2, 0xC5D2, 0x9E6B, 0xC5D3, 0x9E6C,
+	0xC5D4, 0xBFA3, 0xC5D5, 0x9E6D, 0xC5D6, 0x9E6E, 0xC5D7, 0x9E6F,
+	0xC5D8, 0xBFA4, 0xC5D9, 0x9E70, 0xC5DA, 0x9E71, 0xC5DB, 0x9E72,
+	0xC5DC, 0x9E73, 0xC5DD, 0x9E74, 0xC5DE, 0x9E75, 0xC5DF, 0x9E76,
+	0xC5E0, 0xBFA5, 0xC5E1, 0xBFA6, 0xC5E2, 0x9E77, 0xC5E3, 0xBFA7,
+	0xC5E4, 0x9E78, 0xC5E5, 0xBFA8, 0xC5E6, 0x9E79, 0xC5E7, 0x9E7A,
+	0xC5E8, 0x9E81, 0xC5E9, 0x9E82, 0xC5EA, 0x9E83, 0xC5EB, 0x9E84,
+	0xC5EC, 0xBFA9, 0xC5ED, 0xBFAA, 0xC5EE, 0xBFAB, 0xC5EF, 0x9E85,
+	0xC5F0, 0xBFAC, 0xC5F1, 0x9E86, 0xC5F2, 0x9E87, 0xC5F3, 0x9E88,
+	0xC5F4, 0xBFAD, 0xC5F5, 0x9E89, 0xC5F6, 0xBFAE, 0xC5F7, 0xBFAF,
+	0xC5F8, 0x9E8A, 0xC5F9, 0x9E8B, 0xC5FA, 0x9E8C, 0xC5FB, 0x9E8D,
+	0xC5FC, 0xBFB0, 0xC5FD, 0xBFB1, 0xC5FE, 0xBFB2, 0xC5FF, 0xBFB3,
+	0xC600, 0xBFB4, 0xC601, 0xBFB5, 0xC602, 0x9E8E, 0xC603, 0x9E8F,
+	0xC604, 0x9E90, 0xC605, 0xBFB6, 0xC606, 0xBFB7, 0xC607, 0xBFB8,
+	0xC608, 0xBFB9, 0xC609, 0x9E91, 0xC60A, 0x9E92, 0xC60B, 0x9E93,
+	0xC60C, 0xBFBA, 0xC60D, 0x9E94, 0xC60E, 0x9E95, 0xC60F, 0x9E96,
+	0xC610, 0xBFBB, 0xC611, 0x9E97, 0xC612, 0x9E98, 0xC613, 0x9E99,
+	0xC614, 0x9E9A, 0xC615, 0x9E9B, 0xC616, 0x9E9C, 0xC617, 0x9E9D,
+	0xC618, 0xBFBC, 0xC619, 0xBFBD, 0xC61A, 0x9E9E, 0xC61B, 0xBFBE,
+	0xC61C, 0xBFBF, 0xC61D, 0x9E9F, 0xC61E, 0x9EA0, 0xC61F, 0x9EA1,
+	0xC620, 0x9EA2, 0xC621, 0x9EA3, 0xC622, 0x9EA4, 0xC623, 0x9EA5,
+	0xC624, 0xBFC0, 0xC625, 0xBFC1, 0xC626, 0x9EA6, 0xC627, 0x9EA7,
+	0xC628, 0xBFC2, 0xC629, 0x9EA8, 0xC62A, 0x9EA9, 0xC62B, 0x9EAA,
+	0xC62C, 0xBFC3, 0xC62D, 0xBFC4, 0xC62E, 0xBFC5, 0xC62F, 0x9EAB,
+	0xC630, 0xBFC6, 0xC631, 0x9EAC, 0xC632, 0x9EAD, 0xC633, 0xBFC7,
+	0xC634, 0xBFC8, 0xC635, 0xBFC9, 0xC636, 0x9EAE, 0xC637, 0xBFCA,
+	0xC638, 0x9EAF, 0xC639, 0xBFCB, 0xC63A, 0x9EB0, 0xC63B, 0xBFCC,
+	0xC63C, 0x9EB1, 0xC63D, 0x9EB2, 0xC63E, 0x9EB3, 0xC63F, 0x9EB4,
+	0xC640, 0xBFCD, 0xC641, 0xBFCE, 0xC642, 0x9EB5, 0xC643, 0x9EB6,
+	0xC644, 0xBFCF, 0xC645, 0x9EB7, 0xC646, 0x9EB8, 0xC647, 0x9EB9,
+	0xC648, 0xBFD0, 0xC649, 0x9EBA, 0xC64A, 0x9EBB, 0xC64B, 0x9EBC,
+	0xC64C, 0x9EBD, 0xC64D, 0x9EBE, 0xC64E, 0x9EBF, 0xC64F, 0x9EC0,
+	0xC650, 0xBFD1, 0xC651, 0xBFD2, 0xC652, 0x9EC1, 0xC653, 0xBFD3,
+	0xC654, 0xBFD4, 0xC655, 0xBFD5, 0xC656, 0x9EC2, 0xC657, 0x9EC3,
+	0xC658, 0x9EC4, 0xC659, 0x9EC5, 0xC65A, 0x9EC6, 0xC65B, 0x9EC7,
+	0xC65C, 0xBFD6, 0xC65D, 0xBFD7, 0xC65E, 0x9EC8, 0xC65F, 0x9EC9,
+	0xC660, 0xBFD8, 0xC661, 0x9ECA, 0xC662, 0x9ECB, 0xC663, 0x9ECC,
+	0xC664, 0x9ECD, 0xC665, 0x9ECE, 0xC666, 0x9ECF, 0xC667, 0x9ED0,
+	0xC668, 0x9ED1, 0xC669, 0x9ED2, 0xC66A, 0x9ED3, 0xC66B, 0x9ED4,
+	0xC66C, 0xBFD9, 0xC66D, 0x9ED5, 0xC66E, 0x9ED6, 0xC66F, 0xBFDA,
+	0xC670, 0x9ED7, 0xC671, 0xBFDB, 0xC672, 0x9ED8, 0xC673, 0x9ED9,
+	0xC674, 0x9EDA, 0xC675, 0x9EDB, 0xC676, 0x9EDC, 0xC677, 0x9EDD,
+	0xC678, 0xBFDC, 0xC679, 0xBFDD, 0xC67A, 0x9EDE, 0xC67B, 0x9EDF,
+	0xC67C, 0xBFDE, 0xC67D, 0x9EE0, 0xC67E, 0x9EE1, 0xC67F, 0x9EE2,
+	0xC680, 0xBFDF, 0xC681, 0x9EE3, 0xC682, 0x9EE4, 0xC683, 0x9EE5,
+	0xC684, 0x9EE6, 0xC685, 0x9EE7, 0xC686, 0x9EE8, 0xC687, 0x9EE9,
+	0xC688, 0xBFE0, 0xC689, 0xBFE1, 0xC68A, 0x9EEA, 0xC68B, 0xBFE2,
+	0xC68C, 0x9EEB, 0xC68D, 0xBFE3, 0xC68E, 0x9EEC, 0xC68F, 0x9EED,
+	0xC690, 0x9EEE, 0xC691, 0x9EEF, 0xC692, 0x9EF0, 0xC693, 0x9EF1,
+	0xC694, 0xBFE4, 0xC695, 0xBFE5, 0xC696, 0x9EF2, 0xC697, 0x9EF3,
+	0xC698, 0xBFE6, 0xC699, 0x9EF4, 0xC69A, 0x9EF5, 0xC69B, 0x9EF6,
+	0xC69C, 0xBFE7, 0xC69D, 0x9EF7, 0xC69E, 0x9EF8, 0xC69F, 0x9EF9,
+	0xC6A0, 0x9EFA, 0xC6A1, 0x9EFB, 0xC6A2, 0x9EFC, 0xC6A3, 0x9EFD,
+	0xC6A4, 0xBFE8, 0xC6A5, 0xBFE9, 0xC6A6, 0x9EFE, 0xC6A7, 0xBFEA,
+	0xC6A8, 0x9F41, 0xC6A9, 0xBFEB, 0xC6AA, 0x9F42, 0xC6AB, 0x9F43,
+	0xC6AC, 0x9F44, 0xC6AD, 0x9F45, 0xC6AE, 0x9F46, 0xC6AF, 0x9F47,
+	0xC6B0, 0xBFEC, 0xC6B1, 0xBFED, 0xC6B2, 0x9F48, 0xC6B3, 0x9F49,
+	0xC6B4, 0xBFEE, 0xC6B5, 0x9F4A, 0xC6B6, 0x9F4B, 0xC6B7, 0x9F4C,
+	0xC6B8, 0xBFEF, 0xC6B9, 0xBFF0, 0xC6BA, 0xBFF1, 0xC6BB, 0x9F4D,
+	0xC6BC, 0x9F4E, 0xC6BD, 0x9F4F, 0xC6BE, 0x9F50, 0xC6BF, 0x9F51,
+	0xC6C0, 0xBFF2, 0xC6C1, 0xBFF3, 0xC6C2, 0x9F52, 0xC6C3, 0xBFF4,
+	0xC6C4, 0x9F53, 0xC6C5, 0xBFF5, 0xC6C6, 0x9F54, 0xC6C7, 0x9F55,
+	0xC6C8, 0x9F56, 0xC6C9, 0x9F57, 0xC6CA, 0x9F58, 0xC6CB, 0x9F59,
+	0xC6CC, 0xBFF6, 0xC6CD, 0xBFF7, 0xC6CE, 0x9F5A, 0xC6CF, 0x9F61,
+	0xC6D0, 0xBFF8, 0xC6D1, 0x9F62, 0xC6D2, 0x9F63, 0xC6D3, 0x9F64,
+	0xC6D4, 0xBFF9, 0xC6D5, 0x9F65, 0xC6D6, 0x9F66, 0xC6D7, 0x9F67,
+	0xC6D8, 0x9F68, 0xC6D9, 0x9F69, 0xC6DA, 0x9F6A, 0xC6DB, 0x9F6B,
+	0xC6DC, 0xBFFA, 0xC6DD, 0xBFFB, 0xC6DE, 0x9F6C, 0xC6DF, 0x9F6D,
+	0xC6E0, 0xBFFC, 0xC6E1, 0xBFFD, 0xC6E2, 0x9F6E, 0xC6E3, 0x9F6F,
+	0xC6E4, 0x9F70, 0xC6E5, 0x9F71, 0xC6E6, 0x9F72, 0xC6E7, 0x9F73,
+	0xC6E8, 0xBFFE, 0xC6E9, 0xC0A1, 0xC6EA, 0x9F74, 0xC6EB, 0x9F75,
+	0xC6EC, 0xC0A2, 0xC6ED, 0x9F76, 0xC6EE, 0x9F77, 0xC6EF, 0x9F78,
+	0xC6F0, 0xC0A3, 0xC6F1, 0x9F79, 0xC6F2, 0x9F7A, 0xC6F3, 0x9F81,
+	0xC6F4, 0x9F82, 0xC6F5, 0x9F83, 0xC6F6, 0x9F84, 0xC6F7, 0x9F85,
+	0xC6F8, 0xC0A4, 0xC6F9, 0xC0A5, 0xC6FA, 0x9F86, 0xC6FB, 0x9F87,
+	0xC6FC, 0x9F88, 0xC6FD, 0xC0A6, 0xC6FE, 0x9F89, 0xC6FF, 0x9F8A,
+	0xC700, 0x9F8B, 0xC701, 0x9F8C, 0xC702, 0x9F8D, 0xC703, 0x9F8E,
+	0xC704, 0xC0A7, 0xC705, 0xC0A8, 0xC706, 0x9F8F, 0xC707, 0x9F90,
+	0xC708, 0xC0A9, 0xC709, 0x9F91, 0xC70A, 0x9F92, 0xC70B, 0x9F93,
+	0xC70C, 0xC0AA, 0xC70D, 0x9F94, 0xC70E, 0x9F95, 0xC70F, 0x9F96,
+	0xC710, 0x9F97, 0xC711, 0x9F98, 0xC712, 0x9F99, 0xC713, 0x9F9A,
+	0xC714, 0xC0AB, 0xC715, 0xC0AC, 0xC716, 0x9F9B, 0xC717, 0xC0AD,
+	0xC718, 0x9F9C, 0xC719, 0xC0AE, 0xC71A, 0x9F9D, 0xC71B, 0x9F9E,
+	0xC71C, 0x9F9F, 0xC71D, 0x9FA0, 0xC71E, 0x9FA1, 0xC71F, 0x9FA2,
+	0xC720, 0xC0AF, 0xC721, 0xC0B0, 0xC722, 0x9FA3, 0xC723, 0x9FA4,
+	0xC724, 0xC0B1, 0xC725, 0x9FA5, 0xC726, 0x9FA6, 0xC727, 0x9FA7,
+	0xC728, 0xC0B2, 0xC729, 0x9FA8, 0xC72A, 0x9FA9, 0xC72B, 0x9FAA,
+	0xC72C, 0x9FAB, 0xC72D, 0x9FAC, 0xC72E, 0x9FAD, 0xC72F, 0x9FAE,
+	0xC730, 0xC0B3, 0xC731, 0xC0B4, 0xC732, 0x9FAF, 0xC733, 0xC0B5,
+	0xC734, 0x9FB0, 0xC735, 0xC0B6, 0xC736, 0x9FB1, 0xC737, 0xC0B7,
+	0xC738, 0x9FB2, 0xC739, 0x9FB3, 0xC73A, 0x9FB4, 0xC73B, 0x9FB5,
+	0xC73C, 0xC0B8, 0xC73D, 0xC0B9, 0xC73E, 0x9FB6, 0xC73F, 0x9FB7,
+	0xC740, 0xC0BA, 0xC741, 0x9FB8, 0xC742, 0x9FB9, 0xC743, 0x9FBA,
+	0xC744, 0xC0BB, 0xC745, 0x9FBB, 0xC746, 0x9FBC, 0xC747, 0x9FBD,
+	0xC748, 0x9FBE, 0xC749, 0x9FBF, 0xC74A, 0xC0BC, 0xC74B, 0x9FC0,
+	0xC74C, 0xC0BD, 0xC74D, 0xC0BE, 0xC74E, 0x9FC1, 0xC74F, 0xC0BF,
+	0xC750, 0x9FC2, 0xC751, 0xC0C0, 0xC752, 0xC0C1, 0xC753, 0xC0C2,
+	0xC754, 0xC0C3, 0xC755, 0xC0C4, 0xC756, 0xC0C5, 0xC757, 0xC0C6,
+	0xC758, 0xC0C7, 0xC759, 0x9FC3, 0xC75A, 0x9FC4, 0xC75B, 0x9FC5,
+	0xC75C, 0xC0C8, 0xC75D, 0x9FC6, 0xC75E, 0x9FC7, 0xC75F, 0x9FC8,
+	0xC760, 0xC0C9, 0xC761, 0x9FC9, 0xC762, 0x9FCA, 0xC763, 0x9FCB,
+	0xC764, 0x9FCC, 0xC765, 0x9FCD, 0xC766, 0x9FCE, 0xC767, 0x9FCF,
+	0xC768, 0xC0CA, 0xC769, 0x9FD0, 0xC76A, 0x9FD1, 0xC76B, 0xC0CB,
+	0xC76C, 0x9FD2, 0xC76D, 0x9FD3, 0xC76E, 0x9FD4, 0xC76F, 0x9FD5,
+	0xC770, 0x9FD6, 0xC771, 0x9FD7, 0xC772, 0x9FD8, 0xC773, 0x9FD9,
+	0xC774, 0xC0CC, 0xC775, 0xC0CD, 0xC776, 0x9FDA, 0xC777, 0x9FDB,
+	0xC778, 0xC0CE, 0xC779, 0x9FDC, 0xC77A, 0x9FDD, 0xC77B, 0x9FDE,
+	0xC77C, 0xC0CF, 0xC77D, 0xC0D0, 0xC77E, 0xC0D1, 0xC77F, 0x9FDF,
+	0xC780, 0x9FE0, 0xC781, 0x9FE1, 0xC782, 0x9FE2, 0xC783, 0xC0D2,
+	0xC784, 0xC0D3, 0xC785, 0xC0D4, 0xC786, 0x9FE3, 0xC787, 0xC0D5,
+	0xC788, 0xC0D6, 0xC789, 0xC0D7, 0xC78A, 0xC0D8, 0xC78B, 0x9FE4,
+	0xC78C, 0x9FE5, 0xC78D, 0x9FE6, 0xC78E, 0xC0D9, 0xC78F, 0x9FE7,
+	0xC790, 0xC0DA, 0xC791, 0xC0DB, 0xC792, 0x9FE8, 0xC793, 0x9FE9,
+	0xC794, 0xC0DC, 0xC795, 0x9FEA, 0xC796, 0xC0DD, 0xC797, 0xC0DE,
+	0xC798, 0xC0DF, 0xC799, 0x9FEB, 0xC79A, 0xC0E0, 0xC79B, 0x9FEC,
+	0xC79C, 0x9FED, 0xC79D, 0x9FEE, 0xC79E, 0x9FEF, 0xC79F, 0x9FF0,
+	0xC7A0, 0xC0E1, 0xC7A1, 0xC0E2, 0xC7A2, 0x9FF1, 0xC7A3, 0xC0E3,
+	0xC7A4, 0xC0E4, 0xC7A5, 0xC0E5, 0xC7A6, 0xC0E6, 0xC7A7, 0x9FF2,
+	0xC7A8, 0x9FF3, 0xC7A9, 0x9FF4, 0xC7AA, 0x9FF5, 0xC7AB, 0x9FF6,
+	0xC7AC, 0xC0E7, 0xC7AD, 0xC0E8, 0xC7AE, 0x9FF7, 0xC7AF, 0x9FF8,
+	0xC7B0, 0xC0E9, 0xC7B1, 0x9FF9, 0xC7B2, 0x9FFA, 0xC7B3, 0x9FFB,
+	0xC7B4, 0xC0EA, 0xC7B5, 0x9FFC, 0xC7B6, 0x9FFD, 0xC7B7, 0x9FFE,
+	0xC7B8, 0xA041, 0xC7B9, 0xA042, 0xC7BA, 0xA043, 0xC7BB, 0xA044,
+	0xC7BC, 0xC0EB, 0xC7BD, 0xC0EC, 0xC7BE, 0xA045, 0xC7BF, 0xC0ED,
+	0xC7C0, 0xC0EE, 0xC7C1, 0xC0EF, 0xC7C2, 0xA046, 0xC7C3, 0xA047,
+	0xC7C4, 0xA048, 0xC7C5, 0xA049, 0xC7C6, 0xA04A, 0xC7C7, 0xA04B,
+	0xC7C8, 0xC0F0, 0xC7C9, 0xC0F1, 0xC7CA, 0xA04C, 0xC7CB, 0xA04D,
+	0xC7CC, 0xC0F2, 0xC7CD, 0xA04E, 0xC7CE, 0xC0F3, 0xC7CF, 0xA04F,
+	0xC7D0, 0xC0F4, 0xC7D1, 0xA050, 0xC7D2, 0xA051, 0xC7D3, 0xA052,
+	0xC7D4, 0xA053, 0xC7D5, 0xA054, 0xC7D6, 0xA055, 0xC7D7, 0xA056,
+	0xC7D8, 0xC0F5, 0xC7D9, 0xA057, 0xC7DA, 0xA058, 0xC7DB, 0xA059,
+	0xC7DC, 0xA05A, 0xC7DD, 0xC0F6, 0xC7DE, 0xA061, 0xC7DF, 0xA062,
+	0xC7E0, 0xA063, 0xC7E1, 0xA064, 0xC7E2, 0xA065, 0xC7E3, 0xA066,
+	0xC7E4, 0xC0F7, 0xC7E5, 0xA067, 0xC7E6, 0xA068, 0xC7E7, 0xA069,
+	0xC7E8, 0xC0F8, 0xC7E9, 0xA06A, 0xC7EA, 0xA06B, 0xC7EB, 0xA06C,
+	0xC7EC, 0xC0F9, 0xC7ED, 0xA06D, 0xC7EE, 0xA06E, 0xC7EF, 0xA06F,
+	0xC7F0, 0xA070, 0xC7F1, 0xA071, 0xC7F2, 0xA072, 0xC7F3, 0xA073,
+	0xC7F4, 0xA074, 0xC7F5, 0xA075, 0xC7F6, 0xA076, 0xC7F7, 0xA077,
+	0xC7F8, 0xA078, 0xC7F9, 0xA079, 0xC7FA, 0xA07A, 0xC7FB, 0xA081,
+	0xC7FC, 0xA082, 0xC7FD, 0xA083, 0xC7FE, 0xA084, 0xC7FF, 0xA085,
+	0xC800, 0xC0FA, 0xC801, 0xC0FB, 0xC802, 0xA086, 0xC803, 0xA087,
+	0xC804, 0xC0FC, 0xC805, 0xA088, 0xC806, 0xA089, 0xC807, 0xA08A,
+	0xC808, 0xC0FD, 0xC809, 0xA08B, 0xC80A, 0xC0FE, 0xC80B, 0xA08C,
+	0xC80C, 0xA08D, 0xC80D, 0xA08E, 0xC80E, 0xA08F, 0xC80F, 0xA090,
+	0xC810, 0xC1A1, 0xC811, 0xC1A2, 0xC812, 0xA091, 0xC813, 0xC1A3,
+	0xC814, 0xA092, 0xC815, 0xC1A4, 0xC816, 0xC1A5, 0xC817, 0xA093,
+	0xC818, 0xA094, 0xC819, 0xA095, 0xC81A, 0xA096, 0xC81B, 0xA097,
+	0xC81C, 0xC1A6, 0xC81D, 0xC1A7, 0xC81E, 0xA098, 0xC81F, 0xA099,
+	0xC820, 0xC1A8, 0xC821, 0xA09A, 0xC822, 0xA09B, 0xC823, 0xA09C,
+	0xC824, 0xC1A9, 0xC825, 0xA09D, 0xC826, 0xA09E, 0xC827, 0xA09F,
+	0xC828, 0xA0A0, 0xC829, 0xA0A1, 0xC82A, 0xA0A2, 0xC82B, 0xA0A3,
+	0xC82C, 0xC1AA, 0xC82D, 0xC1AB, 0xC82E, 0xA0A4, 0xC82F, 0xC1AC,
+	0xC830, 0xA0A5, 0xC831, 0xC1AD, 0xC832, 0xA0A6, 0xC833, 0xA0A7,
+	0xC834, 0xA0A8, 0xC835, 0xA0A9, 0xC836, 0xA0AA, 0xC837, 0xA0AB,
+	0xC838, 0xC1AE, 0xC839, 0xA0AC, 0xC83A, 0xA0AD, 0xC83B, 0xA0AE,
+	0xC83C, 0xC1AF, 0xC83D, 0xA0AF, 0xC83E, 0xA0B0, 0xC83F, 0xA0B1,
+	0xC840, 0xC1B0, 0xC841, 0xA0B2, 0xC842, 0xA0B3, 0xC843, 0xA0B4,
+	0xC844, 0xA0B5, 0xC845, 0xA0B6, 0xC846, 0xA0B7, 0xC847, 0xA0B8,
+	0xC848, 0xC1B1, 0xC849, 0xC1B2, 0xC84A, 0xA0B9, 0xC84B, 0xA0BA,
+	0xC84C, 0xC1B3, 0xC84D, 0xC1B4, 0xC84E, 0xA0BB, 0xC84F, 0xA0BC,
+	0xC850, 0xA0BD, 0xC851, 0xA0BE, 0xC852, 0xA0BF, 0xC853, 0xA0C0,
+	0xC854, 0xC1B5, 0xC855, 0xA0C1, 0xC856, 0xA0C2, 0xC857, 0xA0C3,
+	0xC858, 0xA0C4, 0xC859, 0xA0C5, 0xC85A, 0xA0C6, 0xC85B, 0xA0C7,
+	0xC85C, 0xA0C8, 0xC85D, 0xA0C9, 0xC85E, 0xA0CA, 0xC85F, 0xA0CB,
+	0xC860, 0xA0CC, 0xC861, 0xA0CD, 0xC862, 0xA0CE, 0xC863, 0xA0CF,
+	0xC864, 0xA0D0, 0xC865, 0xA0D1, 0xC866, 0xA0D2, 0xC867, 0xA0D3,
+	0xC868, 0xA0D4, 0xC869, 0xA0D5, 0xC86A, 0xA0D6, 0xC86B, 0xA0D7,
+	0xC86C, 0xA0D8, 0xC86D, 0xA0D9, 0xC86E, 0xA0DA, 0xC86F, 0xA0DB,
+	0xC870, 0xC1B6, 0xC871, 0xC1B7, 0xC872, 0xA0DC, 0xC873, 0xA0DD,
+	0xC874, 0xC1B8, 0xC875, 0xA0DE, 0xC876, 0xA0DF, 0xC877, 0xA0E0,
+	0xC878, 0xC1B9, 0xC879, 0xA0E1, 0xC87A, 0xC1BA, 0xC87B, 0xA0E2,
+	0xC87C, 0xA0E3, 0xC87D, 0xA0E4, 0xC87E, 0xA0E5, 0xC87F, 0xA0E6,
+	0xC880, 0xC1BB, 0xC881, 0xC1BC, 0xC882, 0xA0E7, 0xC883, 0xC1BD,
+	0xC884, 0xA0E8, 0xC885, 0xC1BE, 0xC886, 0xC1BF, 0xC887, 0xC1C0,
+	0xC888, 0xA0E9, 0xC889, 0xA0EA, 0xC88A, 0xA0EB, 0xC88B, 0xC1C1,
+	0xC88C, 0xC1C2, 0xC88D, 0xC1C3, 0xC88E, 0xA0EC, 0xC88F, 0xA0ED,
+	0xC890, 0xA0EE, 0xC891, 0xA0EF, 0xC892, 0xA0F0, 0xC893, 0xA0F1,
+	0xC894, 0xC1C4, 0xC895, 0xA0F2, 0xC896, 0xA0F3, 0xC897, 0xA0F4,
+	0xC898, 0xA0F5, 0xC899, 0xA0F6, 0xC89A, 0xA0F7, 0xC89B, 0xA0F8,
+	0xC89C, 0xA0F9, 0xC89D, 0xC1C5, 0xC89E, 0xA0FA, 0xC89F, 0xC1C6,
+	0xC8A0, 0xA0FB, 0xC8A1, 0xC1C7, 0xC8A2, 0xA0FC, 0xC8A3, 0xA0FD,
+	0xC8A4, 0xA0FE, 0xC8A5, 0xA141, 0xC8A6, 0xA142, 0xC8A7, 0xA143,
+	0xC8A8, 0xC1C8, 0xC8A9, 0xA144, 0xC8AA, 0xA145, 0xC8AB, 0xA146,
+	0xC8AC, 0xA147, 0xC8AD, 0xA148, 0xC8AE, 0xA149, 0xC8AF, 0xA14A,
+	0xC8B0, 0xA14B, 0xC8B1, 0xA14C, 0xC8B2, 0xA14D, 0xC8B3, 0xA14E,
+	0xC8B4, 0xA14F, 0xC8B5, 0xA150, 0xC8B6, 0xA151, 0xC8B7, 0xA152,
+	0xC8B8, 0xA153, 0xC8B9, 0xA154, 0xC8BA, 0xA155, 0xC8BB, 0xA156,
+	0xC8BC, 0xC1C9, 0xC8BD, 0xC1CA, 0xC8BE, 0xA157, 0xC8BF, 0xA158,
+	0xC8C0, 0xA159, 0xC8C1, 0xA15A, 0xC8C2, 0xA161, 0xC8C3, 0xA162,
+	0xC8C4, 0xC1CB, 0xC8C5, 0xA163, 0xC8C6, 0xA164, 0xC8C7, 0xA165,
+	0xC8C8, 0xC1CC, 0xC8C9, 0xA166, 0xC8CA, 0xA167, 0xC8CB, 0xA168,
+	0xC8CC, 0xC1CD, 0xC8CD, 0xA169, 0xC8CE, 0xA16A, 0xC8CF, 0xA16B,
+	0xC8D0, 0xA16C, 0xC8D1, 0xA16D, 0xC8D2, 0xA16E, 0xC8D3, 0xA16F,
+	0xC8D4, 0xC1CE, 0xC8D5, 0xC1CF, 0xC8D6, 0xA170, 0xC8D7, 0xC1D0,
+	0xC8D8, 0xA171, 0xC8D9, 0xC1D1, 0xC8DA, 0xA172, 0xC8DB, 0xA173,
+	0xC8DC, 0xA174, 0xC8DD, 0xA175, 0xC8DE, 0xA176, 0xC8DF, 0xA177,
+	0xC8E0, 0xC1D2, 0xC8E1, 0xC1D3, 0xC8E2, 0xA178, 0xC8E3, 0xA179,
+	0xC8E4, 0xC1D4, 0xC8E5, 0xA17A, 0xC8E6, 0xA181, 0xC8E7, 0xA182,
+	0xC8E8, 0xA183, 0xC8E9, 0xA184, 0xC8EA, 0xA185, 0xC8EB, 0xA186,
+	0xC8EC, 0xA187, 0xC8ED, 0xA188, 0xC8EE, 0xA189, 0xC8EF, 0xA18A,
+	0xC8F0, 0xA18B, 0xC8F1, 0xA18C, 0xC8F2, 0xA18D, 0xC8F3, 0xA18E,
+	0xC8F4, 0xA18F, 0xC8F5, 0xC1D5, 0xC8F6, 0xA190, 0xC8F7, 0xA191,
+	0xC8F8, 0xA192, 0xC8F9, 0xA193, 0xC8FA, 0xA194, 0xC8FB, 0xA195,
+	0xC8FC, 0xC1D6, 0xC8FD, 0xC1D7, 0xC8FE, 0xA196, 0xC8FF, 0xA197,
+	0xC900, 0xC1D8, 0xC901, 0xA198, 0xC902, 0xA199, 0xC903, 0xA19A,
+	0xC904, 0xC1D9, 0xC905, 0xC1DA, 0xC906, 0xC1DB, 0xC907, 0xA19B,
+	0xC908, 0xA19C, 0xC909, 0xA19D, 0xC90A, 0xA19E, 0xC90B, 0xA19F,
+	0xC90C, 0xC1DC, 0xC90D, 0xC1DD, 0xC90E, 0xA1A0, 0xC90F, 0xC1DE,
+	0xC910, 0xA241, 0xC911, 0xC1DF, 0xC912, 0xA242, 0xC913, 0xA243,
+	0xC914, 0xA244, 0xC915, 0xA245, 0xC916, 0xA246, 0xC917, 0xA247,
+	0xC918, 0xC1E0, 0xC919, 0xA248, 0xC91A, 0xA249, 0xC91B, 0xA24A,
+	0xC91C, 0xA24B, 0xC91D, 0xA24C, 0xC91E, 0xA24D, 0xC91F, 0xA24E,
+	0xC920, 0xA24F, 0xC921, 0xA250, 0xC922, 0xA251, 0xC923, 0xA252,
+	0xC924, 0xA253, 0xC925, 0xA254, 0xC926, 0xA255, 0xC927, 0xA256,
+	0xC928, 0xA257, 0xC929, 0xA258, 0xC92A, 0xA259, 0xC92B, 0xA25A,
+	0xC92C, 0xC1E1, 0xC92D, 0xA261, 0xC92E, 0xA262, 0xC92F, 0xA263,
+	0xC930, 0xA264, 0xC931, 0xA265, 0xC932, 0xA266, 0xC933, 0xA267,
+	0xC934, 0xC1E2, 0xC935, 0xA268, 0xC936, 0xA269, 0xC937, 0xA26A,
+	0xC938, 0xA26B, 0xC939, 0xA26C, 0xC93A, 0xA26D, 0xC93B, 0xA26E,
+	0xC93C, 0xA26F, 0xC93D, 0xA270, 0xC93E, 0xA271, 0xC93F, 0xA272,
+	0xC940, 0xA273, 0xC941, 0xA274, 0xC942, 0xA275, 0xC943, 0xA276,
+	0xC944, 0xA277, 0xC945, 0xA278, 0xC946, 0xA279, 0xC947, 0xA27A,
+	0xC948, 0xA281, 0xC949, 0xA282, 0xC94A, 0xA283, 0xC94B, 0xA284,
+	0xC94C, 0xA285, 0xC94D, 0xA286, 0xC94E, 0xA287, 0xC94F, 0xA288,
+	0xC950, 0xC1E3, 0xC951, 0xC1E4, 0xC952, 0xA289, 0xC953, 0xA28A,
+	0xC954, 0xC1E5, 0xC955, 0xA28B, 0xC956, 0xA28C, 0xC957, 0xA28D,
+	0xC958, 0xC1E6, 0xC959, 0xA28E, 0xC95A, 0xA28F, 0xC95B, 0xA290,
+	0xC95C, 0xA291, 0xC95D, 0xA292, 0xC95E, 0xA293, 0xC95F, 0xA294,
+	0xC960, 0xC1E7, 0xC961, 0xC1E8, 0xC962, 0xA295, 0xC963, 0xC1E9,
+	0xC964, 0xA296, 0xC965, 0xA297, 0xC966, 0xA298, 0xC967, 0xA299,
+	0xC968, 0xA29A, 0xC969, 0xA29B, 0xC96A, 0xA29C, 0xC96B, 0xA29D,
+	0xC96C, 0xC1EA, 0xC96D, 0xA29E, 0xC96E, 0xA29F, 0xC96F, 0xA2A0,
+	0xC970, 0xC1EB, 0xC971, 0xA341, 0xC972, 0xA342, 0xC973, 0xA343,
+	0xC974, 0xC1EC, 0xC975, 0xA344, 0xC976, 0xA345, 0xC977, 0xA346,
+	0xC978, 0xA347, 0xC979, 0xA348, 0xC97A, 0xA349, 0xC97B, 0xA34A,
+	0xC97C, 0xC1ED, 0xC97D, 0xA34B, 0xC97E, 0xA34C, 0xC97F, 0xA34D,
+	0xC980, 0xA34E, 0xC981, 0xA34F, 0xC982, 0xA350, 0xC983, 0xA351,
+	0xC984, 0xA352, 0xC985, 0xA353, 0xC986, 0xA354, 0xC987, 0xA355,
+	0xC988, 0xC1EE, 0xC989, 0xC1EF, 0xC98A, 0xA356, 0xC98B, 0xA357,
+	0xC98C, 0xC1F0, 0xC98D, 0xA358, 0xC98E, 0xA359, 0xC98F, 0xA35A,
+	0xC990, 0xC1F1, 0xC991, 0xA361, 0xC992, 0xA362, 0xC993, 0xA363,
+	0xC994, 0xA364, 0xC995, 0xA365, 0xC996, 0xA366, 0xC997, 0xA367,
+	0xC998, 0xC1F2, 0xC999, 0xC1F3, 0xC99A, 0xA368, 0xC99B, 0xC1F4,
+	0xC99C, 0xA369, 0xC99D, 0xC1F5, 0xC99E, 0xA36A, 0xC99F, 0xA36B,
+	0xC9A0, 0xA36C, 0xC9A1, 0xA36D, 0xC9A2, 0xA36E, 0xC9A3, 0xA36F,
+	0xC9A4, 0xA370, 0xC9A5, 0xA371, 0xC9A6, 0xA372, 0xC9A7, 0xA373,
+	0xC9A8, 0xA374, 0xC9A9, 0xA375, 0xC9AA, 0xA376, 0xC9AB, 0xA377,
+	0xC9AC, 0xA378, 0xC9AD, 0xA379, 0xC9AE, 0xA37A, 0xC9AF, 0xA381,
+	0xC9B0, 0xA382, 0xC9B1, 0xA383, 0xC9B2, 0xA384, 0xC9B3, 0xA385,
+	0xC9B4, 0xA386, 0xC9B5, 0xA387, 0xC9B6, 0xA388, 0xC9B7, 0xA389,
+	0xC9B8, 0xA38A, 0xC9B9, 0xA38B, 0xC9BA, 0xA38C, 0xC9BB, 0xA38D,
+	0xC9BC, 0xA38E, 0xC9BD, 0xA38F, 0xC9BE, 0xA390, 0xC9BF, 0xA391,
+	0xC9C0, 0xC1F6, 0xC9C1, 0xC1F7, 0xC9C2, 0xA392, 0xC9C3, 0xA393,
+	0xC9C4, 0xC1F8, 0xC9C5, 0xA394, 0xC9C6, 0xA395, 0xC9C7, 0xC1F9,
+	0xC9C8, 0xC1FA, 0xC9C9, 0xA396, 0xC9CA, 0xC1FB, 0xC9CB, 0xA397,
+	0xC9CC, 0xA398, 0xC9CD, 0xA399, 0xC9CE, 0xA39A, 0xC9CF, 0xA39B,
+	0xC9D0, 0xC1FC, 0xC9D1, 0xC1FD, 0xC9D2, 0xA39C, 0xC9D3, 0xC1FE,
+	0xC9D4, 0xA39D, 0xC9D5, 0xC2A1, 0xC9D6, 0xC2A2, 0xC9D7, 0xA39E,
+	0xC9D8, 0xA39F, 0xC9D9, 0xC2A3, 0xC9DA, 0xC2A4, 0xC9DB, 0xA3A0,
+	0xC9DC, 0xC2A5, 0xC9DD, 0xC2A6, 0xC9DE, 0xA441, 0xC9DF, 0xA442,
+	0xC9E0, 0xC2A7, 0xC9E1, 0xA443, 0xC9E2, 0xC2A8, 0xC9E3, 0xA444,
+	0xC9E4, 0xC2A9, 0xC9E5, 0xA445, 0xC9E6, 0xA446, 0xC9E7, 0xC2AA,
+	0xC9E8, 0xA447, 0xC9E9, 0xA448, 0xC9EA, 0xA449, 0xC9EB, 0xA44A,
+	0xC9EC, 0xC2AB, 0xC9ED, 0xC2AC, 0xC9EE, 0xA44B, 0xC9EF, 0xC2AD,
+	0xC9F0, 0xC2AE, 0xC9F1, 0xC2AF, 0xC9F2, 0xA44C, 0xC9F3, 0xA44D,
+	0xC9F4, 0xA44E, 0xC9F5, 0xA44F, 0xC9F6, 0xA450, 0xC9F7, 0xA451,
+	0xC9F8, 0xC2B0, 0xC9F9, 0xC2B1, 0xC9FA, 0xA452, 0xC9FB, 0xA453,
+	0xC9FC, 0xC2B2, 0xC9FD, 0xA454, 0xC9FE, 0xA455, 0xC9FF, 0xA456,
+	0xCA00, 0xC2B3, 0xCA01, 0xA457, 0xCA02, 0xA458, 0xCA03, 0xA459,
+	0xCA04, 0xA45A, 0xCA05, 0xA461, 0xCA06, 0xA462, 0xCA07, 0xA463,
+	0xCA08, 0xC2B4, 0xCA09, 0xC2B5, 0xCA0A, 0xA464, 0xCA0B, 0xC2B6,
+	0xCA0C, 0xC2B7, 0xCA0D, 0xC2B8, 0xCA0E, 0xA465, 0xCA0F, 0xA466,
+	0xCA10, 0xA467, 0xCA11, 0xA468, 0xCA12, 0xA469, 0xCA13, 0xA46A,
+	0xCA14, 0xC2B9, 0xCA15, 0xA46B, 0xCA16, 0xA46C, 0xCA17, 0xA46D,
+	0xCA18, 0xC2BA, 0xCA19, 0xA46E, 0xCA1A, 0xA46F, 0xCA1B, 0xA470,
+	0xCA1C, 0xA471, 0xCA1D, 0xA472, 0xCA1E, 0xA473, 0xCA1F, 0xA474,
+	0xCA20, 0xA475, 0xCA21, 0xA476, 0xCA22, 0xA477, 0xCA23, 0xA478,
+	0xCA24, 0xA479, 0xCA25, 0xA47A, 0xCA26, 0xA481, 0xCA27, 0xA482,
+	0xCA28, 0xA483, 0xCA29, 0xC2BB, 0xCA2A, 0xA484, 0xCA2B, 0xA485,
+	0xCA2C, 0xA486, 0xCA2D, 0xA487, 0xCA2E, 0xA488, 0xCA2F, 0xA489,
+	0xCA30, 0xA48A, 0xCA31, 0xA48B, 0xCA32, 0xA48C, 0xCA33, 0xA48D,
+	0xCA34, 0xA48E, 0xCA35, 0xA48F, 0xCA36, 0xA490, 0xCA37, 0xA491,
+	0xCA38, 0xA492, 0xCA39, 0xA493, 0xCA3A, 0xA494, 0xCA3B, 0xA495,
+	0xCA3C, 0xA496, 0xCA3D, 0xA497, 0xCA3E, 0xA498, 0xCA3F, 0xA499,
+	0xCA40, 0xA49A, 0xCA41, 0xA49B, 0xCA42, 0xA49C, 0xCA43, 0xA49D,
+	0xCA44, 0xA49E, 0xCA45, 0xA49F, 0xCA46, 0xA4A0, 0xCA47, 0xA541,
+	0xCA48, 0xA542, 0xCA49, 0xA543, 0xCA4A, 0xA544, 0xCA4B, 0xA545,
+	0xCA4C, 0xC2BC, 0xCA4D, 0xC2BD, 0xCA4E, 0xA546, 0xCA4F, 0xA547,
+	0xCA50, 0xC2BE, 0xCA51, 0xA548, 0xCA52, 0xA549, 0xCA53, 0xA54A,
+	0xCA54, 0xC2BF, 0xCA55, 0xA54B, 0xCA56, 0xA54C, 0xCA57, 0xA54D,
+	0xCA58, 0xA54E, 0xCA59, 0xA54F, 0xCA5A, 0xA550, 0xCA5B, 0xA551,
+	0xCA5C, 0xC2C0, 0xCA5D, 0xC2C1, 0xCA5E, 0xA552, 0xCA5F, 0xC2C2,
+	0xCA60, 0xC2C3, 0xCA61, 0xC2C4, 0xCA62, 0xA553, 0xCA63, 0xA554,
+	0xCA64, 0xA555, 0xCA65, 0xA556, 0xCA66, 0xA557, 0xCA67, 0xA558,
+	0xCA68, 0xC2C5, 0xCA69, 0xA559, 0xCA6A, 0xA55A, 0xCA6B, 0xA561,
+	0xCA6C, 0xA562, 0xCA6D, 0xA563, 0xCA6E, 0xA564, 0xCA6F, 0xA565,
+	0xCA70, 0xA566, 0xCA71, 0xA567, 0xCA72, 0xA568, 0xCA73, 0xA569,
+	0xCA74, 0xA56A, 0xCA75, 0xA56B, 0xCA76, 0xA56C, 0xCA77, 0xA56D,
+	0xCA78, 0xA56E, 0xCA79, 0xA56F, 0xCA7A, 0xA570, 0xCA7B, 0xA571,
+	0xCA7C, 0xA572, 0xCA7D, 0xC2C6, 0xCA7E, 0xA573, 0xCA7F, 0xA574,
+	0xCA80, 0xA575, 0xCA81, 0xA576, 0xCA82, 0xA577, 0xCA83, 0xA578,
+	0xCA84, 0xC2C7, 0xCA85, 0xA579, 0xCA86, 0xA57A, 0xCA87, 0xA581,
+	0xCA88, 0xA582, 0xCA89, 0xA583, 0xCA8A, 0xA584, 0xCA8B, 0xA585,
+	0xCA8C, 0xA586, 0xCA8D, 0xA587, 0xCA8E, 0xA588, 0xCA8F, 0xA589,
+	0xCA90, 0xA58A, 0xCA91, 0xA58B, 0xCA92, 0xA58C, 0xCA93, 0xA58D,
+	0xCA94, 0xA58E, 0xCA95, 0xA58F, 0xCA96, 0xA590, 0xCA97, 0xA591,
+	0xCA98, 0xC2C8, 0xCA99, 0xA592, 0xCA9A, 0xA593, 0xCA9B, 0xA594,
+	0xCA9C, 0xA595, 0xCA9D, 0xA596, 0xCA9E, 0xA597, 0xCA9F, 0xA598,
+	0xCAA0, 0xA599, 0xCAA1, 0xA59A, 0xCAA2, 0xA59B, 0xCAA3, 0xA59C,
+	0xCAA4, 0xA59D, 0xCAA5, 0xA59E, 0xCAA6, 0xA59F, 0xCAA7, 0xA5A0,
+	0xCAA8, 0xA641, 0xCAA9, 0xA642, 0xCAAA, 0xA643, 0xCAAB, 0xA644,
+	0xCAAC, 0xA645, 0xCAAD, 0xA646, 0xCAAE, 0xA647, 0xCAAF, 0xA648,
+	0xCAB0, 0xA649, 0xCAB1, 0xA64A, 0xCAB2, 0xA64B, 0xCAB3, 0xA64C,
+	0xCAB4, 0xA64D, 0xCAB5, 0xA64E, 0xCAB6, 0xA64F, 0xCAB7, 0xA650,
+	0xCAB8, 0xA651, 0xCAB9, 0xA652, 0xCABA, 0xA653, 0xCABB, 0xA654,
+	0xCABC, 0xC2C9, 0xCABD, 0xC2CA, 0xCABE, 0xA655, 0xCABF, 0xA656,
+	0xCAC0, 0xC2CB, 0xCAC1, 0xA657, 0xCAC2, 0xA658, 0xCAC3, 0xA659,
+	0xCAC4, 0xC2CC, 0xCAC5, 0xA65A, 0xCAC6, 0xA661, 0xCAC7, 0xA662,
+	0xCAC8, 0xA663, 0xCAC9, 0xA664, 0xCACA, 0xA665, 0xCACB, 0xA666,
+	0xCACC, 0xC2CD, 0xCACD, 0xC2CE, 0xCACE, 0xA667, 0xCACF, 0xC2CF,
+	0xCAD0, 0xA668, 0xCAD1, 0xC2D0, 0xCAD2, 0xA669, 0xCAD3, 0xC2D1,
+	0xCAD4, 0xA66A, 0xCAD5, 0xA66B, 0xCAD6, 0xA66C, 0xCAD7, 0xA66D,
+	0xCAD8, 0xC2D2, 0xCAD9, 0xC2D3, 0xCADA, 0xA66E, 0xCADB, 0xA66F,
+	0xCADC, 0xA670, 0xCADD, 0xA671, 0xCADE, 0xA672, 0xCADF, 0xA673,
+	0xCAE0, 0xC2D4, 0xCAE1, 0xA674, 0xCAE2, 0xA675, 0xCAE3, 0xA676,
+	0xCAE4, 0xA677, 0xCAE5, 0xA678, 0xCAE6, 0xA679, 0xCAE7, 0xA67A,
+	0xCAE8, 0xA681, 0xCAE9, 0xA682, 0xCAEA, 0xA683, 0xCAEB, 0xA684,
+	0xCAEC, 0xC2D5, 0xCAED, 0xA685, 0xCAEE, 0xA686, 0xCAEF, 0xA687,
+	0xCAF0, 0xA688, 0xCAF1, 0xA689, 0xCAF2, 0xA68A, 0xCAF3, 0xA68B,
+	0xCAF4, 0xC2D6, 0xCAF5, 0xA68C, 0xCAF6, 0xA68D, 0xCAF7, 0xA68E,
+	0xCAF8, 0xA68F, 0xCAF9, 0xA690, 0xCAFA, 0xA691, 0xCAFB, 0xA692,
+	0xCAFC, 0xA693, 0xCAFD, 0xA694, 0xCAFE, 0xA695, 0xCAFF, 0xA696,
+	0xCB00, 0xA697, 0xCB01, 0xA698, 0xCB02, 0xA699, 0xCB03, 0xA69A,
+	0xCB04, 0xA69B, 0xCB05, 0xA69C, 0xCB06, 0xA69D, 0xCB07, 0xA69E,
+	0xCB08, 0xC2D7, 0xCB09, 0xA69F, 0xCB0A, 0xA6A0, 0xCB0B, 0xA741,
+	0xCB0C, 0xA742, 0xCB0D, 0xA743, 0xCB0E, 0xA744, 0xCB0F, 0xA745,
+	0xCB10, 0xC2D8, 0xCB11, 0xA746, 0xCB12, 0xA747, 0xCB13, 0xA748,
+	0xCB14, 0xC2D9, 0xCB15, 0xA749, 0xCB16, 0xA74A, 0xCB17, 0xA74B,
+	0xCB18, 0xC2DA, 0xCB19, 0xA74C, 0xCB1A, 0xA74D, 0xCB1B, 0xA74E,
+	0xCB1C, 0xA74F, 0xCB1D, 0xA750, 0xCB1E, 0xA751, 0xCB1F, 0xA752,
+	0xCB20, 0xC2DB, 0xCB21, 0xC2DC, 0xCB22, 0xA753, 0xCB23, 0xA754,
+	0xCB24, 0xA755, 0xCB25, 0xA756, 0xCB26, 0xA757, 0xCB27, 0xA758,
+	0xCB28, 0xA759, 0xCB29, 0xA75A, 0xCB2A, 0xA761, 0xCB2B, 0xA762,
+	0xCB2C, 0xA763, 0xCB2D, 0xA764, 0xCB2E, 0xA765, 0xCB2F, 0xA766,
+	0xCB30, 0xA767, 0xCB31, 0xA768, 0xCB32, 0xA769, 0xCB33, 0xA76A,
+	0xCB34, 0xA76B, 0xCB35, 0xA76C, 0xCB36, 0xA76D, 0xCB37, 0xA76E,
+	0xCB38, 0xA76F, 0xCB39, 0xA770, 0xCB3A, 0xA771, 0xCB3B, 0xA772,
+	0xCB3C, 0xA773, 0xCB3D, 0xA774, 0xCB3E, 0xA775, 0xCB3F, 0xA776,
+	0xCB40, 0xA777, 0xCB41, 0xC2DD, 0xCB42, 0xA778, 0xCB43, 0xA779,
+	0xCB44, 0xA77A, 0xCB45, 0xA781, 0xCB46, 0xA782, 0xCB47, 0xA783,
+	0xCB48, 0xC2DE, 0xCB49, 0xC2DF, 0xCB4A, 0xA784, 0xCB4B, 0xA785,
+	0xCB4C, 0xC2E0, 0xCB4D, 0xA786, 0xCB4E, 0xA787, 0xCB4F, 0xA788,
+	0xCB50, 0xC2E1, 0xCB51, 0xA789, 0xCB52, 0xA78A, 0xCB53, 0xA78B,
+	0xCB54, 0xA78C, 0xCB55, 0xA78D, 0xCB56, 0xA78E, 0xCB57, 0xA78F,
+	0xCB58, 0xC2E2, 0xCB59, 0xC2E3, 0xCB5A, 0xA790, 0xCB5B, 0xA791,
+	0xCB5C, 0xA792, 0xCB5D, 0xC2E4, 0xCB5E, 0xA793, 0xCB5F, 0xA794,
+	0xCB60, 0xA795, 0xCB61, 0xA796, 0xCB62, 0xA797, 0xCB63, 0xA798,
+	0xCB64, 0xC2E5, 0xCB65, 0xA799, 0xCB66, 0xA79A, 0xCB67, 0xA79B,
+	0xCB68, 0xA79C, 0xCB69, 0xA79D, 0xCB6A, 0xA79E, 0xCB6B, 0xA79F,
+	0xCB6C, 0xA7A0, 0xCB6D, 0xA841, 0xCB6E, 0xA842, 0xCB6F, 0xA843,
+	0xCB70, 0xA844, 0xCB71, 0xA845, 0xCB72, 0xA846, 0xCB73, 0xA847,
+	0xCB74, 0xA848, 0xCB75, 0xA849, 0xCB76, 0xA84A, 0xCB77, 0xA84B,
+	0xCB78, 0xC2E6, 0xCB79, 0xC2E7, 0xCB7A, 0xA84C, 0xCB7B, 0xA84D,
+	0xCB7C, 0xA84E, 0xCB7D, 0xA84F, 0xCB7E, 0xA850, 0xCB7F, 0xA851,
+	0xCB80, 0xA852, 0xCB81, 0xA853, 0xCB82, 0xA854, 0xCB83, 0xA855,
+	0xCB84, 0xA856, 0xCB85, 0xA857, 0xCB86, 0xA858, 0xCB87, 0xA859,
+	0xCB88, 0xA85A, 0xCB89, 0xA861, 0xCB8A, 0xA862, 0xCB8B, 0xA863,
+	0xCB8C, 0xA864, 0xCB8D, 0xA865, 0xCB8E, 0xA866, 0xCB8F, 0xA867,
+	0xCB90, 0xA868, 0xCB91, 0xA869, 0xCB92, 0xA86A, 0xCB93, 0xA86B,
+	0xCB94, 0xA86C, 0xCB95, 0xA86D, 0xCB96, 0xA86E, 0xCB97, 0xA86F,
+	0xCB98, 0xA870, 0xCB99, 0xA871, 0xCB9A, 0xA872, 0xCB9B, 0xA873,
+	0xCB9C, 0xC2E8, 0xCB9D, 0xA874, 0xCB9E, 0xA875, 0xCB9F, 0xA876,
+	0xCBA0, 0xA877, 0xCBA1, 0xA878, 0xCBA2, 0xA879, 0xCBA3, 0xA87A,
+	0xCBA4, 0xA881, 0xCBA5, 0xA882, 0xCBA6, 0xA883, 0xCBA7, 0xA884,
+	0xCBA8, 0xA885, 0xCBA9, 0xA886, 0xCBAA, 0xA887, 0xCBAB, 0xA888,
+	0xCBAC, 0xA889, 0xCBAD, 0xA88A, 0xCBAE, 0xA88B, 0xCBAF, 0xA88C,
+	0xCBB0, 0xA88D, 0xCBB1, 0xA88E, 0xCBB2, 0xA88F, 0xCBB3, 0xA890,
+	0xCBB4, 0xA891, 0xCBB5, 0xA892, 0xCBB6, 0xA893, 0xCBB7, 0xA894,
+	0xCBB8, 0xC2E9, 0xCBB9, 0xA895, 0xCBBA, 0xA896, 0xCBBB, 0xA897,
+	0xCBBC, 0xA898, 0xCBBD, 0xA899, 0xCBBE, 0xA89A, 0xCBBF, 0xA89B,
+	0xCBC0, 0xA89C, 0xCBC1, 0xA89D, 0xCBC2, 0xA89E, 0xCBC3, 0xA89F,
+	0xCBC4, 0xA8A0, 0xCBC5, 0xA941, 0xCBC6, 0xA942, 0xCBC7, 0xA943,
+	0xCBC8, 0xA944, 0xCBC9, 0xA945, 0xCBCA, 0xA946, 0xCBCB, 0xA947,
+	0xCBCC, 0xA948, 0xCBCD, 0xA949, 0xCBCE, 0xA94A, 0xCBCF, 0xA94B,
+	0xCBD0, 0xA94C, 0xCBD1, 0xA94D, 0xCBD2, 0xA94E, 0xCBD3, 0xA94F,
+	0xCBD4, 0xC2EA, 0xCBD5, 0xA950, 0xCBD6, 0xA951, 0xCBD7, 0xA952,
+	0xCBD8, 0xA953, 0xCBD9, 0xA954, 0xCBDA, 0xA955, 0xCBDB, 0xA956,
+	0xCBDC, 0xA957, 0xCBDD, 0xA958, 0xCBDE, 0xA959, 0xCBDF, 0xA95A,
+	0xCBE0, 0xA961, 0xCBE1, 0xA962, 0xCBE2, 0xA963, 0xCBE3, 0xA964,
+	0xCBE4, 0xC2EB, 0xCBE5, 0xA965, 0xCBE6, 0xA966, 0xCBE7, 0xC2EC,
+	0xCBE8, 0xA967, 0xCBE9, 0xC2ED, 0xCBEA, 0xA968, 0xCBEB, 0xA969,
+	0xCBEC, 0xA96A, 0xCBED, 0xA96B, 0xCBEE, 0xA96C, 0xCBEF, 0xA96D,
+	0xCBF0, 0xA96E, 0xCBF1, 0xA96F, 0xCBF2, 0xA970, 0xCBF3, 0xA971,
+	0xCBF4, 0xA972, 0xCBF5, 0xA973, 0xCBF6, 0xA974, 0xCBF7, 0xA975,
+	0xCBF8, 0xA976, 0xCBF9, 0xA977, 0xCBFA, 0xA978, 0xCBFB, 0xA979,
+	0xCBFC, 0xA97A, 0xCBFD, 0xA981, 0xCBFE, 0xA982, 0xCBFF, 0xA983,
+	0xCC00, 0xA984, 0xCC01, 0xA985, 0xCC02, 0xA986, 0xCC03, 0xA987,
+	0xCC04, 0xA988, 0xCC05, 0xA989, 0xCC06, 0xA98A, 0xCC07, 0xA98B,
+	0xCC08, 0xA98C, 0xCC09, 0xA98D, 0xCC0A, 0xA98E, 0xCC0B, 0xA98F,
+	0xCC0C, 0xC2EE, 0xCC0D, 0xC2EF, 0xCC0E, 0xA990, 0xCC0F, 0xA991,
+	0xCC10, 0xC2F0, 0xCC11, 0xA992, 0xCC12, 0xA993, 0xCC13, 0xA994,
+	0xCC14, 0xC2F1, 0xCC15, 0xA995, 0xCC16, 0xA996, 0xCC17, 0xA997,
+	0xCC18, 0xA998, 0xCC19, 0xA999, 0xCC1A, 0xA99A, 0xCC1B, 0xA99B,
+	0xCC1C, 0xC2F2, 0xCC1D, 0xC2F3, 0xCC1E, 0xA99C, 0xCC1F, 0xA99D,
+	0xCC20, 0xA99E, 0xCC21, 0xC2F4, 0xCC22, 0xC2F5, 0xCC23, 0xA99F,
+	0xCC24, 0xA9A0, 0xCC25, 0xAA41, 0xCC26, 0xAA42, 0xCC27, 0xC2F6,
+	0xCC28, 0xC2F7, 0xCC29, 0xC2F8, 0xCC2A, 0xAA43, 0xCC2B, 0xAA44,
+	0xCC2C, 0xC2F9, 0xCC2D, 0xAA45, 0xCC2E, 0xC2FA, 0xCC2F, 0xAA46,
+	0xCC30, 0xC2FB, 0xCC31, 0xAA47, 0xCC32, 0xAA48, 0xCC33, 0xAA49,
+	0xCC34, 0xAA4A, 0xCC35, 0xAA4B, 0xCC36, 0xAA4C, 0xCC37, 0xAA4D,
+	0xCC38, 0xC2FC, 0xCC39, 0xC2FD, 0xCC3A, 0xAA4E, 0xCC3B, 0xC2FE,
+	0xCC3C, 0xC3A1, 0xCC3D, 0xC3A2, 0xCC3E, 0xC3A3, 0xCC3F, 0xAA4F,
+	0xCC40, 0xAA50, 0xCC41, 0xAA51, 0xCC42, 0xAA52, 0xCC43, 0xAA53,
+	0xCC44, 0xC3A4, 0xCC45, 0xC3A5, 0xCC46, 0xAA54, 0xCC47, 0xAA55,
+	0xCC48, 0xC3A6, 0xCC49, 0xAA56, 0xCC4A, 0xAA57, 0xCC4B, 0xAA58,
+	0xCC4C, 0xC3A7, 0xCC4D, 0xAA59, 0xCC4E, 0xAA5A, 0xCC4F, 0xAA61,
+	0xCC50, 0xAA62, 0xCC51, 0xAA63, 0xCC52, 0xAA64, 0xCC53, 0xAA65,
+	0xCC54, 0xC3A8, 0xCC55, 0xC3A9, 0xCC56, 0xAA66, 0xCC57, 0xC3AA,
+	0xCC58, 0xC3AB, 0xCC59, 0xC3AC, 0xCC5A, 0xAA67, 0xCC5B, 0xAA68,
+	0xCC5C, 0xAA69, 0xCC5D, 0xAA6A, 0xCC5E, 0xAA6B, 0xCC5F, 0xAA6C,
+	0xCC60, 0xC3AD, 0xCC61, 0xAA6D, 0xCC62, 0xAA6E, 0xCC63, 0xAA6F,
+	0xCC64, 0xC3AE, 0xCC65, 0xAA70, 0xCC66, 0xC3AF, 0xCC67, 0xAA71,
+	0xCC68, 0xC3B0, 0xCC69, 0xAA72, 0xCC6A, 0xAA73, 0xCC6B, 0xAA74,
+	0xCC6C, 0xAA75, 0xCC6D, 0xAA76, 0xCC6E, 0xAA77, 0xCC6F, 0xAA78,
+	0xCC70, 0xC3B1, 0xCC71, 0xAA79, 0xCC72, 0xAA7A, 0xCC73, 0xAA81,
+	0xCC74, 0xAA82, 0xCC75, 0xC3B2, 0xCC76, 0xAA83, 0xCC77, 0xAA84,
+	0xCC78, 0xAA85, 0xCC79, 0xAA86, 0xCC7A, 0xAA87, 0xCC7B, 0xAA88,
+	0xCC7C, 0xAA89, 0xCC7D, 0xAA8A, 0xCC7E, 0xAA8B, 0xCC7F, 0xAA8C,
+	0xCC80, 0xAA8D, 0xCC81, 0xAA8E, 0xCC82, 0xAA8F, 0xCC83, 0xAA90,
+	0xCC84, 0xAA91, 0xCC85, 0xAA92, 0xCC86, 0xAA93, 0xCC87, 0xAA94,
+	0xCC88, 0xAA95, 0xCC89, 0xAA96, 0xCC8A, 0xAA97, 0xCC8B, 0xAA98,
+	0xCC8C, 0xAA99, 0xCC8D, 0xAA9A, 0xCC8E, 0xAA9B, 0xCC8F, 0xAA9C,
+	0xCC90, 0xAA9D, 0xCC91, 0xAA9E, 0xCC92, 0xAA9F, 0xCC93, 0xAAA0,
+	0xCC94, 0xAB41, 0xCC95, 0xAB42, 0xCC96, 0xAB43, 0xCC97, 0xAB44,
+	0xCC98, 0xC3B3, 0xCC99, 0xC3B4, 0xCC9A, 0xAB45, 0xCC9B, 0xAB46,
+	0xCC9C, 0xC3B5, 0xCC9D, 0xAB47, 0xCC9E, 0xAB48, 0xCC9F, 0xAB49,
+	0xCCA0, 0xC3B6, 0xCCA1, 0xAB4A, 0xCCA2, 0xAB4B, 0xCCA3, 0xAB4C,
+	0xCCA4, 0xAB4D, 0xCCA5, 0xAB4E, 0xCCA6, 0xAB4F, 0xCCA7, 0xAB50,
+	0xCCA8, 0xC3B7, 0xCCA9, 0xC3B8, 0xCCAA, 0xAB51, 0xCCAB, 0xC3B9,
+	0xCCAC, 0xC3BA, 0xCCAD, 0xC3BB, 0xCCAE, 0xAB52, 0xCCAF, 0xAB53,
+	0xCCB0, 0xAB54, 0xCCB1, 0xAB55, 0xCCB2, 0xAB56, 0xCCB3, 0xAB57,
+	0xCCB4, 0xC3BC, 0xCCB5, 0xC3BD, 0xCCB6, 0xAB58, 0xCCB7, 0xAB59,
+	0xCCB8, 0xC3BE, 0xCCB9, 0xAB5A, 0xCCBA, 0xAB61, 0xCCBB, 0xAB62,
+	0xCCBC, 0xC3BF, 0xCCBD, 0xAB63, 0xCCBE, 0xAB64, 0xCCBF, 0xAB65,
+	0xCCC0, 0xAB66, 0xCCC1, 0xAB67, 0xCCC2, 0xAB68, 0xCCC3, 0xAB69,
+	0xCCC4, 0xC3C0, 0xCCC5, 0xC3C1, 0xCCC6, 0xAB6A, 0xCCC7, 0xC3C2,
+	0xCCC8, 0xAB6B, 0xCCC9, 0xC3C3, 0xCCCA, 0xAB6C, 0xCCCB, 0xAB6D,
+	0xCCCC, 0xAB6E, 0xCCCD, 0xAB6F, 0xCCCE, 0xAB70, 0xCCCF, 0xAB71,
+	0xCCD0, 0xC3C4, 0xCCD1, 0xAB72, 0xCCD2, 0xAB73, 0xCCD3, 0xAB74,
+	0xCCD4, 0xC3C5, 0xCCD5, 0xAB75, 0xCCD6, 0xAB76, 0xCCD7, 0xAB77,
+	0xCCD8, 0xAB78, 0xCCD9, 0xAB79, 0xCCDA, 0xAB7A, 0xCCDB, 0xAB81,
+	0xCCDC, 0xAB82, 0xCCDD, 0xAB83, 0xCCDE, 0xAB84, 0xCCDF, 0xAB85,
+	0xCCE0, 0xAB86, 0xCCE1, 0xAB87, 0xCCE2, 0xAB88, 0xCCE3, 0xAB89,
+	0xCCE4, 0xC3C6, 0xCCE5, 0xAB8A, 0xCCE6, 0xAB8B, 0xCCE7, 0xAB8C,
+	0xCCE8, 0xAB8D, 0xCCE9, 0xAB8E, 0xCCEA, 0xAB8F, 0xCCEB, 0xAB90,
+	0xCCEC, 0xC3C7, 0xCCED, 0xAB91, 0xCCEE, 0xAB92, 0xCCEF, 0xAB93,
+	0xCCF0, 0xC3C8, 0xCCF1, 0xAB94, 0xCCF2, 0xAB95, 0xCCF3, 0xAB96,
+	0xCCF4, 0xAB97, 0xCCF5, 0xAB98, 0xCCF6, 0xAB99, 0xCCF7, 0xAB9A,
+	0xCCF8, 0xAB9B, 0xCCF9, 0xAB9C, 0xCCFA, 0xAB9D, 0xCCFB, 0xAB9E,
+	0xCCFC, 0xAB9F, 0xCCFD, 0xABA0, 0xCCFE, 0xAC41, 0xCCFF, 0xAC42,
+	0xCD00, 0xAC43, 0xCD01, 0xC3C9, 0xCD02, 0xAC44, 0xCD03, 0xAC45,
+	0xCD04, 0xAC46, 0xCD05, 0xAC47, 0xCD06, 0xAC48, 0xCD07, 0xAC49,
+	0xCD08, 0xC3CA, 0xCD09, 0xC3CB, 0xCD0A, 0xAC4A, 0xCD0B, 0xAC4B,
+	0xCD0C, 0xC3CC, 0xCD0D, 0xAC4C, 0xCD0E, 0xAC4D, 0xCD0F, 0xAC4E,
+	0xCD10, 0xC3CD, 0xCD11, 0xAC4F, 0xCD12, 0xAC50, 0xCD13, 0xAC51,
+	0xCD14, 0xAC52, 0xCD15, 0xAC53, 0xCD16, 0xAC54, 0xCD17, 0xAC55,
+	0xCD18, 0xC3CE, 0xCD19, 0xC3CF, 0xCD1A, 0xAC56, 0xCD1B, 0xC3D0,
+	0xCD1C, 0xAC57, 0xCD1D, 0xC3D1, 0xCD1E, 0xAC58, 0xCD1F, 0xAC59,
+	0xCD20, 0xAC5A, 0xCD21, 0xAC61, 0xCD22, 0xAC62, 0xCD23, 0xAC63,
+	0xCD24, 0xC3D2, 0xCD25, 0xAC64, 0xCD26, 0xAC65, 0xCD27, 0xAC66,
+	0xCD28, 0xC3D3, 0xCD29, 0xAC67, 0xCD2A, 0xAC68, 0xCD2B, 0xAC69,
+	0xCD2C, 0xC3D4, 0xCD2D, 0xAC6A, 0xCD2E, 0xAC6B, 0xCD2F, 0xAC6C,
+	0xCD30, 0xAC6D, 0xCD31, 0xAC6E, 0xCD32, 0xAC6F, 0xCD33, 0xAC70,
+	0xCD34, 0xAC71, 0xCD35, 0xAC72, 0xCD36, 0xAC73, 0xCD37, 0xAC74,
+	0xCD38, 0xAC75, 0xCD39, 0xC3D5, 0xCD3A, 0xAC76, 0xCD3B, 0xAC77,
+	0xCD3C, 0xAC78, 0xCD3D, 0xAC79, 0xCD3E, 0xAC7A, 0xCD3F, 0xAC81,
+	0xCD40, 0xAC82, 0xCD41, 0xAC83, 0xCD42, 0xAC84, 0xCD43, 0xAC85,
+	0xCD44, 0xAC86, 0xCD45, 0xAC87, 0xCD46, 0xAC88, 0xCD47, 0xAC89,
+	0xCD48, 0xAC8A, 0xCD49, 0xAC8B, 0xCD4A, 0xAC8C, 0xCD4B, 0xAC8D,
+	0xCD4C, 0xAC8E, 0xCD4D, 0xAC8F, 0xCD4E, 0xAC90, 0xCD4F, 0xAC91,
+	0xCD50, 0xAC92, 0xCD51, 0xAC93, 0xCD52, 0xAC94, 0xCD53, 0xAC95,
+	0xCD54, 0xAC96, 0xCD55, 0xAC97, 0xCD56, 0xAC98, 0xCD57, 0xAC99,
+	0xCD58, 0xAC9A, 0xCD59, 0xAC9B, 0xCD5A, 0xAC9C, 0xCD5B, 0xAC9D,
+	0xCD5C, 0xC3D6, 0xCD5D, 0xAC9E, 0xCD5E, 0xAC9F, 0xCD5F, 0xACA0,
+	0xCD60, 0xC3D7, 0xCD61, 0xAD41, 0xCD62, 0xAD42, 0xCD63, 0xAD43,
+	0xCD64, 0xC3D8, 0xCD65, 0xAD44, 0xCD66, 0xAD45, 0xCD67, 0xAD46,
+	0xCD68, 0xAD47, 0xCD69, 0xAD48, 0xCD6A, 0xAD49, 0xCD6B, 0xAD4A,
+	0xCD6C, 0xC3D9, 0xCD6D, 0xC3DA, 0xCD6E, 0xAD4B, 0xCD6F, 0xC3DB,
+	0xCD70, 0xAD4C, 0xCD71, 0xC3DC, 0xCD72, 0xAD4D, 0xCD73, 0xAD4E,
+	0xCD74, 0xAD4F, 0xCD75, 0xAD50, 0xCD76, 0xAD51, 0xCD77, 0xAD52,
+	0xCD78, 0xC3DD, 0xCD79, 0xAD53, 0xCD7A, 0xAD54, 0xCD7B, 0xAD55,
+	0xCD7C, 0xAD56, 0xCD7D, 0xAD57, 0xCD7E, 0xAD58, 0xCD7F, 0xAD59,
+	0xCD80, 0xAD5A, 0xCD81, 0xAD61, 0xCD82, 0xAD62, 0xCD83, 0xAD63,
+	0xCD84, 0xAD64, 0xCD85, 0xAD65, 0xCD86, 0xAD66, 0xCD87, 0xAD67,
+	0xCD88, 0xC3DE, 0xCD89, 0xAD68, 0xCD8A, 0xAD69, 0xCD8B, 0xAD6A,
+	0xCD8C, 0xAD6B, 0xCD8D, 0xAD6C, 0xCD8E, 0xAD6D, 0xCD8F, 0xAD6E,
+	0xCD90, 0xAD6F, 0xCD91, 0xAD70, 0xCD92, 0xAD71, 0xCD93, 0xAD72,
+	0xCD94, 0xC3DF, 0xCD95, 0xC3E0, 0xCD96, 0xAD73, 0xCD97, 0xAD74,
+	0xCD98, 0xC3E1, 0xCD99, 0xAD75, 0xCD9A, 0xAD76, 0xCD9B, 0xAD77,
+	0xCD9C, 0xC3E2, 0xCD9D, 0xAD78, 0xCD9E, 0xAD79, 0xCD9F, 0xAD7A,
+	0xCDA0, 0xAD81, 0xCDA1, 0xAD82, 0xCDA2, 0xAD83, 0xCDA3, 0xAD84,
+	0xCDA4, 0xC3E3, 0xCDA5, 0xC3E4, 0xCDA6, 0xAD85, 0xCDA7, 0xC3E5,
+	0xCDA8, 0xAD86, 0xCDA9, 0xC3E6, 0xCDAA, 0xAD87, 0xCDAB, 0xAD88,
+	0xCDAC, 0xAD89, 0xCDAD, 0xAD8A, 0xCDAE, 0xAD8B, 0xCDAF, 0xAD8C,
+	0xCDB0, 0xC3E7, 0xCDB1, 0xAD8D, 0xCDB2, 0xAD8E, 0xCDB3, 0xAD8F,
+	0xCDB4, 0xAD90, 0xCDB5, 0xAD91, 0xCDB6, 0xAD92, 0xCDB7, 0xAD93,
+	0xCDB8, 0xAD94, 0xCDB9, 0xAD95, 0xCDBA, 0xAD96, 0xCDBB, 0xAD97,
+	0xCDBC, 0xAD98, 0xCDBD, 0xAD99, 0xCDBE, 0xAD9A, 0xCDBF, 0xAD9B,
+	0xCDC0, 0xAD9C, 0xCDC1, 0xAD9D, 0xCDC2, 0xAD9E, 0xCDC3, 0xAD9F,
+	0xCDC4, 0xC3E8, 0xCDC5, 0xADA0, 0xCDC6, 0xAE41, 0xCDC7, 0xAE42,
+	0xCDC8, 0xAE43, 0xCDC9, 0xAE44, 0xCDCA, 0xAE45, 0xCDCB, 0xAE46,
+	0xCDCC, 0xC3E9, 0xCDCD, 0xAE47, 0xCDCE, 0xAE48, 0xCDCF, 0xAE49,
+	0xCDD0, 0xC3EA, 0xCDD1, 0xAE4A, 0xCDD2, 0xAE4B, 0xCDD3, 0xAE4C,
+	0xCDD4, 0xAE4D, 0xCDD5, 0xAE4E, 0xCDD6, 0xAE4F, 0xCDD7, 0xAE50,
+	0xCDD8, 0xAE51, 0xCDD9, 0xAE52, 0xCDDA, 0xAE53, 0xCDDB, 0xAE54,
+	0xCDDC, 0xAE55, 0xCDDD, 0xAE56, 0xCDDE, 0xAE57, 0xCDDF, 0xAE58,
+	0xCDE0, 0xAE59, 0xCDE1, 0xAE5A, 0xCDE2, 0xAE61, 0xCDE3, 0xAE62,
+	0xCDE4, 0xAE63, 0xCDE5, 0xAE64, 0xCDE6, 0xAE65, 0xCDE7, 0xAE66,
+	0xCDE8, 0xC3EB, 0xCDE9, 0xAE67, 0xCDEA, 0xAE68, 0xCDEB, 0xAE69,
+	0xCDEC, 0xC3EC, 0xCDED, 0xAE6A, 0xCDEE, 0xAE6B, 0xCDEF, 0xAE6C,
+	0xCDF0, 0xC3ED, 0xCDF1, 0xAE6D, 0xCDF2, 0xAE6E, 0xCDF3, 0xAE6F,
+	0xCDF4, 0xAE70, 0xCDF5, 0xAE71, 0xCDF6, 0xAE72, 0xCDF7, 0xAE73,
+	0xCDF8, 0xC3EE, 0xCDF9, 0xC3EF, 0xCDFA, 0xAE74, 0xCDFB, 0xC3F0,
+	0xCDFC, 0xAE75, 0xCDFD, 0xC3F1, 0xCDFE, 0xAE76, 0xCDFF, 0xAE77,
+	0xCE00, 0xAE78, 0xCE01, 0xAE79, 0xCE02, 0xAE7A, 0xCE03, 0xAE81,
+	0xCE04, 0xC3F2, 0xCE05, 0xAE82, 0xCE06, 0xAE83, 0xCE07, 0xAE84,
+	0xCE08, 0xC3F3, 0xCE09, 0xAE85, 0xCE0A, 0xAE86, 0xCE0B, 0xAE87,
+	0xCE0C, 0xC3F4, 0xCE0D, 0xAE88, 0xCE0E, 0xAE89, 0xCE0F, 0xAE8A,
+	0xCE10, 0xAE8B, 0xCE11, 0xAE8C, 0xCE12, 0xAE8D, 0xCE13, 0xAE8E,
+	0xCE14, 0xC3F5, 0xCE15, 0xAE8F, 0xCE16, 0xAE90, 0xCE17, 0xAE91,
+	0xCE18, 0xAE92, 0xCE19, 0xC3F6, 0xCE1A, 0xAE93, 0xCE1B, 0xAE94,
+	0xCE1C, 0xAE95, 0xCE1D, 0xAE96, 0xCE1E, 0xAE97, 0xCE1F, 0xAE98,
+	0xCE20, 0xC3F7, 0xCE21, 0xC3F8, 0xCE22, 0xAE99, 0xCE23, 0xAE9A,
+	0xCE24, 0xC3F9, 0xCE25, 0xAE9B, 0xCE26, 0xAE9C, 0xCE27, 0xAE9D,
+	0xCE28, 0xC3FA, 0xCE29, 0xAE9E, 0xCE2A, 0xAE9F, 0xCE2B, 0xAEA0,
+	0xCE2C, 0xAF41, 0xCE2D, 0xAF42, 0xCE2E, 0xAF43, 0xCE2F, 0xAF44,
+	0xCE30, 0xC3FB, 0xCE31, 0xC3FC, 0xCE32, 0xAF45, 0xCE33, 0xC3FD,
+	0xCE34, 0xAF46, 0xCE35, 0xC3FE, 0xCE36, 0xAF47, 0xCE37, 0xAF48,
+	0xCE38, 0xAF49, 0xCE39, 0xAF4A, 0xCE3A, 0xAF4B, 0xCE3B, 0xAF4C,
+	0xCE3C, 0xAF4D, 0xCE3D, 0xAF4E, 0xCE3E, 0xAF4F, 0xCE3F, 0xAF50,
+	0xCE40, 0xAF51, 0xCE41, 0xAF52, 0xCE42, 0xAF53, 0xCE43, 0xAF54,
+	0xCE44, 0xAF55, 0xCE45, 0xAF56, 0xCE46, 0xAF57, 0xCE47, 0xAF58,
+	0xCE48, 0xAF59, 0xCE49, 0xAF5A, 0xCE4A, 0xAF61, 0xCE4B, 0xAF62,
+	0xCE4C, 0xAF63, 0xCE4D, 0xAF64, 0xCE4E, 0xAF65, 0xCE4F, 0xAF66,
+	0xCE50, 0xAF67, 0xCE51, 0xAF68, 0xCE52, 0xAF69, 0xCE53, 0xAF6A,
+	0xCE54, 0xAF6B, 0xCE55, 0xAF6C, 0xCE56, 0xAF6D, 0xCE57, 0xAF6E,
+	0xCE58, 0xC4A1, 0xCE59, 0xC4A2, 0xCE5A, 0xAF6F, 0xCE5B, 0xAF70,
+	0xCE5C, 0xC4A3, 0xCE5D, 0xAF71, 0xCE5E, 0xAF72, 0xCE5F, 0xC4A4,
+	0xCE60, 0xC4A5, 0xCE61, 0xC4A6, 0xCE62, 0xAF73, 0xCE63, 0xAF74,
+	0xCE64, 0xAF75, 0xCE65, 0xAF76, 0xCE66, 0xAF77, 0xCE67, 0xAF78,
+	0xCE68, 0xC4A7, 0xCE69, 0xC4A8, 0xCE6A, 0xAF79, 0xCE6B, 0xC4A9,
+	0xCE6C, 0xAF7A, 0xCE6D, 0xC4AA, 0xCE6E, 0xAF81, 0xCE6F, 0xAF82,
+	0xCE70, 0xAF83, 0xCE71, 0xAF84, 0xCE72, 0xAF85, 0xCE73, 0xAF86,
+	0xCE74, 0xC4AB, 0xCE75, 0xC4AC, 0xCE76, 0xAF87, 0xCE77, 0xAF88,
+	0xCE78, 0xC4AD, 0xCE79, 0xAF89, 0xCE7A, 0xAF8A, 0xCE7B, 0xAF8B,
+	0xCE7C, 0xC4AE, 0xCE7D, 0xAF8C, 0xCE7E, 0xAF8D, 0xCE7F, 0xAF8E,
+	0xCE80, 0xAF8F, 0xCE81, 0xAF90, 0xCE82, 0xAF91, 0xCE83, 0xAF92,
+	0xCE84, 0xC4AF, 0xCE85, 0xC4B0, 0xCE86, 0xAF93, 0xCE87, 0xC4B1,
+	0xCE88, 0xAF94, 0xCE89, 0xC4B2, 0xCE8A, 0xAF95, 0xCE8B, 0xAF96,
+	0xCE8C, 0xAF97, 0xCE8D, 0xAF98, 0xCE8E, 0xAF99, 0xCE8F, 0xAF9A,
+	0xCE90, 0xC4B3, 0xCE91, 0xC4B4, 0xCE92, 0xAF9B, 0xCE93, 0xAF9C,
+	0xCE94, 0xC4B5, 0xCE95, 0xAF9D, 0xCE96, 0xAF9E, 0xCE97, 0xAF9F,
+	0xCE98, 0xC4B6, 0xCE99, 0xAFA0, 0xCE9A, 0xB041, 0xCE9B, 0xB042,
+	0xCE9C, 0xB043, 0xCE9D, 0xB044, 0xCE9E, 0xB045, 0xCE9F, 0xB046,
+	0xCEA0, 0xC4B7, 0xCEA1, 0xC4B8, 0xCEA2, 0xB047, 0xCEA3, 0xC4B9,
+	0xCEA4, 0xC4BA, 0xCEA5, 0xC4BB, 0xCEA6, 0xB048, 0xCEA7, 0xB049,
+	0xCEA8, 0xB04A, 0xCEA9, 0xB04B, 0xCEAA, 0xB04C, 0xCEAB, 0xB04D,
+	0xCEAC, 0xC4BC, 0xCEAD, 0xC4BD, 0xCEAE, 0xB04E, 0xCEAF, 0xB04F,
+	0xCEB0, 0xB050, 0xCEB1, 0xB051, 0xCEB2, 0xB052, 0xCEB3, 0xB053,
+	0xCEB4, 0xB054, 0xCEB5, 0xB055, 0xCEB6, 0xB056, 0xCEB7, 0xB057,
+	0xCEB8, 0xB058, 0xCEB9, 0xB059, 0xCEBA, 0xB05A, 0xCEBB, 0xB061,
+	0xCEBC, 0xB062, 0xCEBD, 0xB063, 0xCEBE, 0xB064, 0xCEBF, 0xB065,
+	0xCEC0, 0xB066, 0xCEC1, 0xC4BE, 0xCEC2, 0xB067, 0xCEC3, 0xB068,
+	0xCEC4, 0xB069, 0xCEC5, 0xB06A, 0xCEC6, 0xB06B, 0xCEC7, 0xB06C,
+	0xCEC8, 0xB06D, 0xCEC9, 0xB06E, 0xCECA, 0xB06F, 0xCECB, 0xB070,
+	0xCECC, 0xB071, 0xCECD, 0xB072, 0xCECE, 0xB073, 0xCECF, 0xB074,
+	0xCED0, 0xB075, 0xCED1, 0xB076, 0xCED2, 0xB077, 0xCED3, 0xB078,
+	0xCED4, 0xB079, 0xCED5, 0xB07A, 0xCED6, 0xB081, 0xCED7, 0xB082,
+	0xCED8, 0xB083, 0xCED9, 0xB084, 0xCEDA, 0xB085, 0xCEDB, 0xB086,
+	0xCEDC, 0xB087, 0xCEDD, 0xB088, 0xCEDE, 0xB089, 0xCEDF, 0xB08A,
+	0xCEE0, 0xB08B, 0xCEE1, 0xB08C, 0xCEE2, 0xB08D, 0xCEE3, 0xB08E,
+	0xCEE4, 0xC4BF, 0xCEE5, 0xC4C0, 0xCEE6, 0xB08F, 0xCEE7, 0xB090,
+	0xCEE8, 0xC4C1, 0xCEE9, 0xB091, 0xCEEA, 0xB092, 0xCEEB, 0xC4C2,
+	0xCEEC, 0xC4C3, 0xCEED, 0xB093, 0xCEEE, 0xB094, 0xCEEF, 0xB095,
+	0xCEF0, 0xB096, 0xCEF1, 0xB097, 0xCEF2, 0xB098, 0xCEF3, 0xB099,
+	0xCEF4, 0xC4C4, 0xCEF5, 0xC4C5, 0xCEF6, 0xB09A, 0xCEF7, 0xC4C6,
+	0xCEF8, 0xC4C7, 0xCEF9, 0xC4C8, 0xCEFA, 0xB09B, 0xCEFB, 0xB09C,
+	0xCEFC, 0xB09D, 0xCEFD, 0xB09E, 0xCEFE, 0xB09F, 0xCEFF, 0xB0A0,
+	0xCF00, 0xC4C9, 0xCF01, 0xC4CA, 0xCF02, 0xB141, 0xCF03, 0xB142,
+	0xCF04, 0xC4CB, 0xCF05, 0xB143, 0xCF06, 0xB144, 0xCF07, 0xB145,
+	0xCF08, 0xC4CC, 0xCF09, 0xB146, 0xCF0A, 0xB147, 0xCF0B, 0xB148,
+	0xCF0C, 0xB149, 0xCF0D, 0xB14A, 0xCF0E, 0xB14B, 0xCF0F, 0xB14C,
+	0xCF10, 0xC4CD, 0xCF11, 0xC4CE, 0xCF12, 0xB14D, 0xCF13, 0xC4CF,
+	0xCF14, 0xB14E, 0xCF15, 0xC4D0, 0xCF16, 0xB14F, 0xCF17, 0xB150,
+	0xCF18, 0xB151, 0xCF19, 0xB152, 0xCF1A, 0xB153, 0xCF1B, 0xB154,
+	0xCF1C, 0xC4D1, 0xCF1D, 0xB155, 0xCF1E, 0xB156, 0xCF1F, 0xB157,
+	0xCF20, 0xC4D2, 0xCF21, 0xB158, 0xCF22, 0xB159, 0xCF23, 0xB15A,
+	0xCF24, 0xC4D3, 0xCF25, 0xB161, 0xCF26, 0xB162, 0xCF27, 0xB163,
+	0xCF28, 0xB164, 0xCF29, 0xB165, 0xCF2A, 0xB166, 0xCF2B, 0xB167,
+	0xCF2C, 0xC4D4, 0xCF2D, 0xC4D5, 0xCF2E, 0xB168, 0xCF2F, 0xC4D6,
+	0xCF30, 0xC4D7, 0xCF31, 0xC4D8, 0xCF32, 0xB169, 0xCF33, 0xB16A,
+	0xCF34, 0xB16B, 0xCF35, 0xB16C, 0xCF36, 0xB16D, 0xCF37, 0xB16E,
+	0xCF38, 0xC4D9, 0xCF39, 0xB16F, 0xCF3A, 0xB170, 0xCF3B, 0xB171,
+	0xCF3C, 0xB172, 0xCF3D, 0xB173, 0xCF3E, 0xB174, 0xCF3F, 0xB175,
+	0xCF40, 0xB176, 0xCF41, 0xB177, 0xCF42, 0xB178, 0xCF43, 0xB179,
+	0xCF44, 0xB17A, 0xCF45, 0xB181, 0xCF46, 0xB182, 0xCF47, 0xB183,
+	0xCF48, 0xB184, 0xCF49, 0xB185, 0xCF4A, 0xB186, 0xCF4B, 0xB187,
+	0xCF4C, 0xB188, 0xCF4D, 0xB189, 0xCF4E, 0xB18A, 0xCF4F, 0xB18B,
+	0xCF50, 0xB18C, 0xCF51, 0xB18D, 0xCF52, 0xB18E, 0xCF53, 0xB18F,
+	0xCF54, 0xC4DA, 0xCF55, 0xC4DB, 0xCF56, 0xB190, 0xCF57, 0xB191,
+	0xCF58, 0xC4DC, 0xCF59, 0xB192, 0xCF5A, 0xB193, 0xCF5B, 0xB194,
+	0xCF5C, 0xC4DD, 0xCF5D, 0xB195, 0xCF5E, 0xB196, 0xCF5F, 0xB197,
+	0xCF60, 0xB198, 0xCF61, 0xB199, 0xCF62, 0xB19A, 0xCF63, 0xB19B,
+	0xCF64, 0xC4DE, 0xCF65, 0xC4DF, 0xCF66, 0xB19C, 0xCF67, 0xC4E0,
+	0xCF68, 0xB19D, 0xCF69, 0xC4E1, 0xCF6A, 0xB19E, 0xCF6B, 0xB19F,
+	0xCF6C, 0xB1A0, 0xCF6D, 0xB241, 0xCF6E, 0xB242, 0xCF6F, 0xB243,
+	0xCF70, 0xC4E2, 0xCF71, 0xC4E3, 0xCF72, 0xB244, 0xCF73, 0xB245,
+	0xCF74, 0xC4E4, 0xCF75, 0xB246, 0xCF76, 0xB247, 0xCF77, 0xB248,
+	0xCF78, 0xC4E5, 0xCF79, 0xB249, 0xCF7A, 0xB24A, 0xCF7B, 0xB24B,
+	0xCF7C, 0xB24C, 0xCF7D, 0xB24D, 0xCF7E, 0xB24E, 0xCF7F, 0xB24F,
+	0xCF80, 0xC4E6, 0xCF81, 0xB250, 0xCF82, 0xB251, 0xCF83, 0xB252,
+	0xCF84, 0xB253, 0xCF85, 0xC4E7, 0xCF86, 0xB254, 0xCF87, 0xB255,
+	0xCF88, 0xB256, 0xCF89, 0xB257, 0xCF8A, 0xB258, 0xCF8B, 0xB259,
+	0xCF8C, 0xC4E8, 0xCF8D, 0xB25A, 0xCF8E, 0xB261, 0xCF8F, 0xB262,
+	0xCF90, 0xB263, 0xCF91, 0xB264, 0xCF92, 0xB265, 0xCF93, 0xB266,
+	0xCF94, 0xB267, 0xCF95, 0xB268, 0xCF96, 0xB269, 0xCF97, 0xB26A,
+	0xCF98, 0xB26B, 0xCF99, 0xB26C, 0xCF9A, 0xB26D, 0xCF9B, 0xB26E,
+	0xCF9C, 0xB26F, 0xCF9D, 0xB270, 0xCF9E, 0xB271, 0xCF9F, 0xB272,
+	0xCFA0, 0xB273, 0xCFA1, 0xC4E9, 0xCFA2, 0xB274, 0xCFA3, 0xB275,
+	0xCFA4, 0xB276, 0xCFA5, 0xB277, 0xCFA6, 0xB278, 0xCFA7, 0xB279,
+	0xCFA8, 0xC4EA, 0xCFA9, 0xB27A, 0xCFAA, 0xB281, 0xCFAB, 0xB282,
+	0xCFAC, 0xB283, 0xCFAD, 0xB284, 0xCFAE, 0xB285, 0xCFAF, 0xB286,
+	0xCFB0, 0xC4EB, 0xCFB1, 0xB287, 0xCFB2, 0xB288, 0xCFB3, 0xB289,
+	0xCFB4, 0xB28A, 0xCFB5, 0xB28B, 0xCFB6, 0xB28C, 0xCFB7, 0xB28D,
+	0xCFB8, 0xB28E, 0xCFB9, 0xB28F, 0xCFBA, 0xB290, 0xCFBB, 0xB291,
+	0xCFBC, 0xB292, 0xCFBD, 0xB293, 0xCFBE, 0xB294, 0xCFBF, 0xB295,
+	0xCFC0, 0xB296, 0xCFC1, 0xB297, 0xCFC2, 0xB298, 0xCFC3, 0xB299,
+	0xCFC4, 0xC4EC, 0xCFC5, 0xB29A, 0xCFC6, 0xB29B, 0xCFC7, 0xB29C,
+	0xCFC8, 0xB29D, 0xCFC9, 0xB29E, 0xCFCA, 0xB29F, 0xCFCB, 0xB2A0,
+	0xCFCC, 0xB341, 0xCFCD, 0xB342, 0xCFCE, 0xB343, 0xCFCF, 0xB344,
+	0xCFD0, 0xB345, 0xCFD1, 0xB346, 0xCFD2, 0xB347, 0xCFD3, 0xB348,
+	0xCFD4, 0xB349, 0xCFD5, 0xB34A, 0xCFD6, 0xB34B, 0xCFD7, 0xB34C,
+	0xCFD8, 0xB34D, 0xCFD9, 0xB34E, 0xCFDA, 0xB34F, 0xCFDB, 0xB350,
+	0xCFDC, 0xB351, 0xCFDD, 0xB352, 0xCFDE, 0xB353, 0xCFDF, 0xB354,
+	0xCFE0, 0xC4ED, 0xCFE1, 0xC4EE, 0xCFE2, 0xB355, 0xCFE3, 0xB356,
+	0xCFE4, 0xC4EF, 0xCFE5, 0xB357, 0xCFE6, 0xB358, 0xCFE7, 0xB359,
+	0xCFE8, 0xC4F0, 0xCFE9, 0xB35A, 0xCFEA, 0xB361, 0xCFEB, 0xB362,
+	0xCFEC, 0xB363, 0xCFED, 0xB364, 0xCFEE, 0xB365, 0xCFEF, 0xB366,
+	0xCFF0, 0xC4F1, 0xCFF1, 0xC4F2, 0xCFF2, 0xB367, 0xCFF3, 0xC4F3,
+	0xCFF4, 0xB368, 0xCFF5, 0xC4F4, 0xCFF6, 0xB369, 0xCFF7, 0xB36A,
+	0xCFF8, 0xB36B, 0xCFF9, 0xB36C, 0xCFFA, 0xB36D, 0xCFFB, 0xB36E,
+	0xCFFC, 0xC4F5, 0xCFFD, 0xB36F, 0xCFFE, 0xB370, 0xCFFF, 0xB371,
+	0xD000, 0xC4F6, 0xD001, 0xB372, 0xD002, 0xB373, 0xD003, 0xB374,
+	0xD004, 0xC4F7, 0xD005, 0xB375, 0xD006, 0xB376, 0xD007, 0xB377,
+	0xD008, 0xB378, 0xD009, 0xB379, 0xD00A, 0xB37A, 0xD00B, 0xB381,
+	0xD00C, 0xB382, 0xD00D, 0xB383, 0xD00E, 0xB384, 0xD00F, 0xB385,
+	0xD010, 0xB386, 0xD011, 0xC4F8, 0xD012, 0xB387, 0xD013, 0xB388,
+	0xD014, 0xB389, 0xD015, 0xB38A, 0xD016, 0xB38B, 0xD017, 0xB38C,
+	0xD018, 0xC4F9, 0xD019, 0xB38D, 0xD01A, 0xB38E, 0xD01B, 0xB38F,
+	0xD01C, 0xB390, 0xD01D, 0xB391, 0xD01E, 0xB392, 0xD01F, 0xB393,
+	0xD020, 0xB394, 0xD021, 0xB395, 0xD022, 0xB396, 0xD023, 0xB397,
+	0xD024, 0xB398, 0xD025, 0xB399, 0xD026, 0xB39A, 0xD027, 0xB39B,
+	0xD028, 0xB39C, 0xD029, 0xB39D, 0xD02A, 0xB39E, 0xD02B, 0xB39F,
+	0xD02C, 0xB3A0, 0xD02D, 0xC4FA, 0xD02E, 0xB441, 0xD02F, 0xB442,
+	0xD030, 0xB443, 0xD031, 0xB444, 0xD032, 0xB445, 0xD033, 0xB446,
+	0xD034, 0xC4FB, 0xD035, 0xC4FC, 0xD036, 0xB447, 0xD037, 0xB448,
+	0xD038, 0xC4FD, 0xD039, 0xB449, 0xD03A, 0xB44A, 0xD03B, 0xB44B,
+	0xD03C, 0xC4FE, 0xD03D, 0xB44C, 0xD03E, 0xB44D, 0xD03F, 0xB44E,
+	0xD040, 0xB44F, 0xD041, 0xB450, 0xD042, 0xB451, 0xD043, 0xB452,
+	0xD044, 0xC5A1, 0xD045, 0xC5A2, 0xD046, 0xB453, 0xD047, 0xC5A3,
+	0xD048, 0xB454, 0xD049, 0xC5A4, 0xD04A, 0xB455, 0xD04B, 0xB456,
+	0xD04C, 0xB457, 0xD04D, 0xB458, 0xD04E, 0xB459, 0xD04F, 0xB45A,
+	0xD050, 0xC5A5, 0xD051, 0xB461, 0xD052, 0xB462, 0xD053, 0xB463,
+	0xD054, 0xC5A6, 0xD055, 0xB464, 0xD056, 0xB465, 0xD057, 0xB466,
+	0xD058, 0xC5A7, 0xD059, 0xB467, 0xD05A, 0xB468, 0xD05B, 0xB469,
+	0xD05C, 0xB46A, 0xD05D, 0xB46B, 0xD05E, 0xB46C, 0xD05F, 0xB46D,
+	0xD060, 0xC5A8, 0xD061, 0xB46E, 0xD062, 0xB46F, 0xD063, 0xB470,
+	0xD064, 0xB471, 0xD065, 0xB472, 0xD066, 0xB473, 0xD067, 0xB474,
+	0xD068, 0xB475, 0xD069, 0xB476, 0xD06A, 0xB477, 0xD06B, 0xB478,
+	0xD06C, 0xC5A9, 0xD06D, 0xC5AA, 0xD06E, 0xB479, 0xD06F, 0xB47A,
+	0xD070, 0xC5AB, 0xD071, 0xB481, 0xD072, 0xB482, 0xD073, 0xB483,
+	0xD074, 0xC5AC, 0xD075, 0xB484, 0xD076, 0xB485, 0xD077, 0xB486,
+	0xD078, 0xB487, 0xD079, 0xB488, 0xD07A, 0xB489, 0xD07B, 0xB48A,
+	0xD07C, 0xC5AD, 0xD07D, 0xC5AE, 0xD07E, 0xB48B, 0xD07F, 0xB48C,
+	0xD080, 0xB48D, 0xD081, 0xC5AF, 0xD082, 0xB48E, 0xD083, 0xB48F,
+	0xD084, 0xB490, 0xD085, 0xB491, 0xD086, 0xB492, 0xD087, 0xB493,
+	0xD088, 0xB494, 0xD089, 0xB495, 0xD08A, 0xB496, 0xD08B, 0xB497,
+	0xD08C, 0xB498, 0xD08D, 0xB499, 0xD08E, 0xB49A, 0xD08F, 0xB49B,
+	0xD090, 0xB49C, 0xD091, 0xB49D, 0xD092, 0xB49E, 0xD093, 0xB49F,
+	0xD094, 0xB4A0, 0xD095, 0xB541, 0xD096, 0xB542, 0xD097, 0xB543,
+	0xD098, 0xB544, 0xD099, 0xB545, 0xD09A, 0xB546, 0xD09B, 0xB547,
+	0xD09C, 0xB548, 0xD09D, 0xB549, 0xD09E, 0xB54A, 0xD09F, 0xB54B,
+	0xD0A0, 0xB54C, 0xD0A1, 0xB54D, 0xD0A2, 0xB54E, 0xD0A3, 0xB54F,
+	0xD0A4, 0xC5B0, 0xD0A5, 0xC5B1, 0xD0A6, 0xB550, 0xD0A7, 0xB551,
+	0xD0A8, 0xC5B2, 0xD0A9, 0xB552, 0xD0AA, 0xB553, 0xD0AB, 0xB554,
+	0xD0AC, 0xC5B3, 0xD0AD, 0xB555, 0xD0AE, 0xB556, 0xD0AF, 0xB557,
+	0xD0B0, 0xB558, 0xD0B1, 0xB559, 0xD0B2, 0xB55A, 0xD0B3, 0xB561,
+	0xD0B4, 0xC5B4, 0xD0B5, 0xC5B5, 0xD0B6, 0xB562, 0xD0B7, 0xC5B6,
+	0xD0B8, 0xB563, 0xD0B9, 0xC5B7, 0xD0BA, 0xB564, 0xD0BB, 0xB565,
+	0xD0BC, 0xB566, 0xD0BD, 0xB567, 0xD0BE, 0xB568, 0xD0BF, 0xB569,
+	0xD0C0, 0xC5B8, 0xD0C1, 0xC5B9, 0xD0C2, 0xB56A, 0xD0C3, 0xB56B,
+	0xD0C4, 0xC5BA, 0xD0C5, 0xB56C, 0xD0C6, 0xB56D, 0xD0C7, 0xB56E,
+	0xD0C8, 0xC5BB, 0xD0C9, 0xC5BC, 0xD0CA, 0xB56F, 0xD0CB, 0xB570,
+	0xD0CC, 0xB571, 0xD0CD, 0xB572, 0xD0CE, 0xB573, 0xD0CF, 0xB574,
+	0xD0D0, 0xC5BD, 0xD0D1, 0xC5BE, 0xD0D2, 0xB575, 0xD0D3, 0xC5BF,
+	0xD0D4, 0xC5C0, 0xD0D5, 0xC5C1, 0xD0D6, 0xB576, 0xD0D7, 0xB577,
+	0xD0D8, 0xB578, 0xD0D9, 0xB579, 0xD0DA, 0xB57A, 0xD0DB, 0xB581,
+	0xD0DC, 0xC5C2, 0xD0DD, 0xC5C3, 0xD0DE, 0xB582, 0xD0DF, 0xB583,
+	0xD0E0, 0xC5C4, 0xD0E1, 0xB584, 0xD0E2, 0xB585, 0xD0E3, 0xB586,
+	0xD0E4, 0xC5C5, 0xD0E5, 0xB587, 0xD0E6, 0xB588, 0xD0E7, 0xB589,
+	0xD0E8, 0xB58A, 0xD0E9, 0xB58B, 0xD0EA, 0xB58C, 0xD0EB, 0xB58D,
+	0xD0EC, 0xC5C6, 0xD0ED, 0xC5C7, 0xD0EE, 0xB58E, 0xD0EF, 0xC5C8,
+	0xD0F0, 0xC5C9, 0xD0F1, 0xC5CA, 0xD0F2, 0xB58F, 0xD0F3, 0xB590,
+	0xD0F4, 0xB591, 0xD0F5, 0xB592, 0xD0F6, 0xB593, 0xD0F7, 0xB594,
+	0xD0F8, 0xC5CB, 0xD0F9, 0xB595, 0xD0FA, 0xB596, 0xD0FB, 0xB597,
+	0xD0FC, 0xB598, 0xD0FD, 0xB599, 0xD0FE, 0xB59A, 0xD0FF, 0xB59B,
+	0xD100, 0xB59C, 0xD101, 0xB59D, 0xD102, 0xB59E, 0xD103, 0xB59F,
+	0xD104, 0xB5A0, 0xD105, 0xB641, 0xD106, 0xB642, 0xD107, 0xB643,
+	0xD108, 0xB644, 0xD109, 0xB645, 0xD10A, 0xB646, 0xD10B, 0xB647,
+	0xD10C, 0xB648, 0xD10D, 0xC5CC, 0xD10E, 0xB649, 0xD10F, 0xB64A,
+	0xD110, 0xB64B, 0xD111, 0xB64C, 0xD112, 0xB64D, 0xD113, 0xB64E,
+	0xD114, 0xB64F, 0xD115, 0xB650, 0xD116, 0xB651, 0xD117, 0xB652,
+	0xD118, 0xB653, 0xD119, 0xB654, 0xD11A, 0xB655, 0xD11B, 0xB656,
+	0xD11C, 0xB657, 0xD11D, 0xB658, 0xD11E, 0xB659, 0xD11F, 0xB65A,
+	0xD120, 0xB661, 0xD121, 0xB662, 0xD122, 0xB663, 0xD123, 0xB664,
+	0xD124, 0xB665, 0xD125, 0xB666, 0xD126, 0xB667, 0xD127, 0xB668,
+	0xD128, 0xB669, 0xD129, 0xB66A, 0xD12A, 0xB66B, 0xD12B, 0xB66C,
+	0xD12C, 0xB66D, 0xD12D, 0xB66E, 0xD12E, 0xB66F, 0xD12F, 0xB670,
+	0xD130, 0xC5CD, 0xD131, 0xC5CE, 0xD132, 0xB671, 0xD133, 0xB672,
+	0xD134, 0xC5CF, 0xD135, 0xB673, 0xD136, 0xB674, 0xD137, 0xB675,
+	0xD138, 0xC5D0, 0xD139, 0xB676, 0xD13A, 0xC5D1, 0xD13B, 0xB677,
+	0xD13C, 0xB678, 0xD13D, 0xB679, 0xD13E, 0xB67A, 0xD13F, 0xB681,
+	0xD140, 0xC5D2, 0xD141, 0xC5D3, 0xD142, 0xB682, 0xD143, 0xC5D4,
+	0xD144, 0xC5D5, 0xD145, 0xC5D6, 0xD146, 0xB683, 0xD147, 0xB684,
+	0xD148, 0xB685, 0xD149, 0xB686, 0xD14A, 0xB687, 0xD14B, 0xB688,
+	0xD14C, 0xC5D7, 0xD14D, 0xC5D8, 0xD14E, 0xB689, 0xD14F, 0xB68A,
+	0xD150, 0xC5D9, 0xD151, 0xB68B, 0xD152, 0xB68C, 0xD153, 0xB68D,
+	0xD154, 0xC5DA, 0xD155, 0xB68E, 0xD156, 0xB68F, 0xD157, 0xB690,
+	0xD158, 0xB691, 0xD159, 0xB692, 0xD15A, 0xB693, 0xD15B, 0xB694,
+	0xD15C, 0xC5DB, 0xD15D, 0xC5DC, 0xD15E, 0xB695, 0xD15F, 0xC5DD,
+	0xD160, 0xB696, 0xD161, 0xC5DE, 0xD162, 0xB697, 0xD163, 0xB698,
+	0xD164, 0xB699, 0xD165, 0xB69A, 0xD166, 0xB69B, 0xD167, 0xB69C,
+	0xD168, 0xC5DF, 0xD169, 0xB69D, 0xD16A, 0xB69E, 0xD16B, 0xB69F,
+	0xD16C, 0xC5E0, 0xD16D, 0xB6A0, 0xD16E, 0xB741, 0xD16F, 0xB742,
+	0xD170, 0xB743, 0xD171, 0xB744, 0xD172, 0xB745, 0xD173, 0xB746,
+	0xD174, 0xB747, 0xD175, 0xB748, 0xD176, 0xB749, 0xD177, 0xB74A,
+	0xD178, 0xB74B, 0xD179, 0xB74C, 0xD17A, 0xB74D, 0xD17B, 0xB74E,
+	0xD17C, 0xC5E1, 0xD17D, 0xB74F, 0xD17E, 0xB750, 0xD17F, 0xB751,
+	0xD180, 0xB752, 0xD181, 0xB753, 0xD182, 0xB754, 0xD183, 0xB755,
+	0xD184, 0xC5E2, 0xD185, 0xB756, 0xD186, 0xB757, 0xD187, 0xB758,
+	0xD188, 0xC5E3, 0xD189, 0xB759, 0xD18A, 0xB75A, 0xD18B, 0xB761,
+	0xD18C, 0xB762, 0xD18D, 0xB763, 0xD18E, 0xB764, 0xD18F, 0xB765,
+	0xD190, 0xB766, 0xD191, 0xB767, 0xD192, 0xB768, 0xD193, 0xB769,
+	0xD194, 0xB76A, 0xD195, 0xB76B, 0xD196, 0xB76C, 0xD197, 0xB76D,
+	0xD198, 0xB76E, 0xD199, 0xB76F, 0xD19A, 0xB770, 0xD19B, 0xB771,
+	0xD19C, 0xB772, 0xD19D, 0xB773, 0xD19E, 0xB774, 0xD19F, 0xB775,
+	0xD1A0, 0xC5E4, 0xD1A1, 0xC5E5, 0xD1A2, 0xB776, 0xD1A3, 0xB777,
+	0xD1A4, 0xC5E6, 0xD1A5, 0xB778, 0xD1A6, 0xB779, 0xD1A7, 0xB77A,
+	0xD1A8, 0xC5E7, 0xD1A9, 0xB781, 0xD1AA, 0xB782, 0xD1AB, 0xB783,
+	0xD1AC, 0xB784, 0xD1AD, 0xB785, 0xD1AE, 0xB786, 0xD1AF, 0xB787,
+	0xD1B0, 0xC5E8, 0xD1B1, 0xC5E9, 0xD1B2, 0xB788, 0xD1B3, 0xC5EA,
+	0xD1B4, 0xB789, 0xD1B5, 0xC5EB, 0xD1B6, 0xB78A, 0xD1B7, 0xB78B,
+	0xD1B8, 0xB78C, 0xD1B9, 0xB78D, 0xD1BA, 0xC5EC, 0xD1BB, 0xB78E,
+	0xD1BC, 0xC5ED, 0xD1BD, 0xB78F, 0xD1BE, 0xB790, 0xD1BF, 0xB791,
+	0xD1C0, 0xC5EE, 0xD1C1, 0xB792, 0xD1C2, 0xB793, 0xD1C3, 0xB794,
+	0xD1C4, 0xB795, 0xD1C5, 0xB796, 0xD1C6, 0xB797, 0xD1C7, 0xB798,
+	0xD1C8, 0xB799, 0xD1C9, 0xB79A, 0xD1CA, 0xB79B, 0xD1CB, 0xB79C,
+	0xD1CC, 0xB79D, 0xD1CD, 0xB79E, 0xD1CE, 0xB79F, 0xD1CF, 0xB7A0,
+	0xD1D0, 0xB841, 0xD1D1, 0xB842, 0xD1D2, 0xB843, 0xD1D3, 0xB844,
+	0xD1D4, 0xB845, 0xD1D5, 0xB846, 0xD1D6, 0xB847, 0xD1D7, 0xB848,
+	0xD1D8, 0xC5EF, 0xD1D9, 0xB849, 0xD1DA, 0xB84A, 0xD1DB, 0xB84B,
+	0xD1DC, 0xB84C, 0xD1DD, 0xB84D, 0xD1DE, 0xB84E, 0xD1DF, 0xB84F,
+	0xD1E0, 0xB850, 0xD1E1, 0xB851, 0xD1E2, 0xB852, 0xD1E3, 0xB853,
+	0xD1E4, 0xB854, 0xD1E5, 0xB855, 0xD1E6, 0xB856, 0xD1E7, 0xB857,
+	0xD1E8, 0xB858, 0xD1E9, 0xB859, 0xD1EA, 0xB85A, 0xD1EB, 0xB861,
+	0xD1EC, 0xB862, 0xD1ED, 0xB863, 0xD1EE, 0xB864, 0xD1EF, 0xB865,
+	0xD1F0, 0xB866, 0xD1F1, 0xB867, 0xD1F2, 0xB868, 0xD1F3, 0xB869,
+	0xD1F4, 0xC5F0, 0xD1F5, 0xB86A, 0xD1F6, 0xB86B, 0xD1F7, 0xB86C,
+	0xD1F8, 0xC5F1, 0xD1F9, 0xB86D, 0xD1FA, 0xB86E, 0xD1FB, 0xB86F,
+	0xD1FC, 0xB870, 0xD1FD, 0xB871, 0xD1FE, 0xB872, 0xD1FF, 0xB873,
+	0xD200, 0xB874, 0xD201, 0xB875, 0xD202, 0xB876, 0xD203, 0xB877,
+	0xD204, 0xB878, 0xD205, 0xB879, 0xD206, 0xB87A, 0xD207, 0xC5F2,
+	0xD208, 0xB881, 0xD209, 0xC5F3, 0xD20A, 0xB882, 0xD20B, 0xB883,
+	0xD20C, 0xB884, 0xD20D, 0xB885, 0xD20E, 0xB886, 0xD20F, 0xB887,
+	0xD210, 0xC5F4, 0xD211, 0xB888, 0xD212, 0xB889, 0xD213, 0xB88A,
+	0xD214, 0xB88B, 0xD215, 0xB88C, 0xD216, 0xB88D, 0xD217, 0xB88E,
+	0xD218, 0xB88F, 0xD219, 0xB890, 0xD21A, 0xB891, 0xD21B, 0xB892,
+	0xD21C, 0xB893, 0xD21D, 0xB894, 0xD21E, 0xB895, 0xD21F, 0xB896,
+	0xD220, 0xB897, 0xD221, 0xB898, 0xD222, 0xB899, 0xD223, 0xB89A,
+	0xD224, 0xB89B, 0xD225, 0xB89C, 0xD226, 0xB89D, 0xD227, 0xB89E,
+	0xD228, 0xB89F, 0xD229, 0xB8A0, 0xD22A, 0xB941, 0xD22B, 0xB942,
+	0xD22C, 0xC5F5, 0xD22D, 0xC5F6, 0xD22E, 0xB943, 0xD22F, 0xB944,
+	0xD230, 0xC5F7, 0xD231, 0xB945, 0xD232, 0xB946, 0xD233, 0xB947,
+	0xD234, 0xC5F8, 0xD235, 0xB948, 0xD236, 0xB949, 0xD237, 0xB94A,
+	0xD238, 0xB94B, 0xD239, 0xB94C, 0xD23A, 0xB94D, 0xD23B, 0xB94E,
+	0xD23C, 0xC5F9, 0xD23D, 0xC5FA, 0xD23E, 0xB94F, 0xD23F, 0xC5FB,
+	0xD240, 0xB950, 0xD241, 0xC5FC, 0xD242, 0xB951, 0xD243, 0xB952,
+	0xD244, 0xB953, 0xD245, 0xB954, 0xD246, 0xB955, 0xD247, 0xB956,
+	0xD248, 0xC5FD, 0xD249, 0xB957, 0xD24A, 0xB958, 0xD24B, 0xB959,
+	0xD24C, 0xB95A, 0xD24D, 0xB961, 0xD24E, 0xB962, 0xD24F, 0xB963,
+	0xD250, 0xB964, 0xD251, 0xB965, 0xD252, 0xB966, 0xD253, 0xB967,
+	0xD254, 0xB968, 0xD255, 0xB969, 0xD256, 0xB96A, 0xD257, 0xB96B,
+	0xD258, 0xB96C, 0xD259, 0xB96D, 0xD25A, 0xB96E, 0xD25B, 0xB96F,
+	0xD25C, 0xC5FE, 0xD25D, 0xB970, 0xD25E, 0xB971, 0xD25F, 0xB972,
+	0xD260, 0xB973, 0xD261, 0xB974, 0xD262, 0xB975, 0xD263, 0xB976,
+	0xD264, 0xC6A1, 0xD265, 0xB977, 0xD266, 0xB978, 0xD267, 0xB979,
+	0xD268, 0xB97A, 0xD269, 0xB981, 0xD26A, 0xB982, 0xD26B, 0xB983,
+	0xD26C, 0xB984, 0xD26D, 0xB985, 0xD26E, 0xB986, 0xD26F, 0xB987,
+	0xD270, 0xB988, 0xD271, 0xB989, 0xD272, 0xB98A, 0xD273, 0xB98B,
+	0xD274, 0xB98C, 0xD275, 0xB98D, 0xD276, 0xB98E, 0xD277, 0xB98F,
+	0xD278, 0xB990, 0xD279, 0xB991, 0xD27A, 0xB992, 0xD27B, 0xB993,
+	0xD27C, 0xB994, 0xD27D, 0xB995, 0xD27E, 0xB996, 0xD27F, 0xB997,
+	0xD280, 0xC6A2, 0xD281, 0xC6A3, 0xD282, 0xB998, 0xD283, 0xB999,
+	0xD284, 0xC6A4, 0xD285, 0xB99A, 0xD286, 0xB99B, 0xD287, 0xB99C,
+	0xD288, 0xC6A5, 0xD289, 0xB99D, 0xD28A, 0xB99E, 0xD28B, 0xB99F,
+	0xD28C, 0xB9A0, 0xD28D, 0xBA41, 0xD28E, 0xBA42, 0xD28F, 0xBA43,
+	0xD290, 0xC6A6, 0xD291, 0xC6A7, 0xD292, 0xBA44, 0xD293, 0xBA45,
+	0xD294, 0xBA46, 0xD295, 0xC6A8, 0xD296, 0xBA47, 0xD297, 0xBA48,
+	0xD298, 0xBA49, 0xD299, 0xBA4A, 0xD29A, 0xBA4B, 0xD29B, 0xBA4C,
+	0xD29C, 0xC6A9, 0xD29D, 0xBA4D, 0xD29E, 0xBA4E, 0xD29F, 0xBA4F,
+	0xD2A0, 0xC6AA, 0xD2A1, 0xBA50, 0xD2A2, 0xBA51, 0xD2A3, 0xBA52,
+	0xD2A4, 0xC6AB, 0xD2A5, 0xBA53, 0xD2A6, 0xBA54, 0xD2A7, 0xBA55,
+	0xD2A8, 0xBA56, 0xD2A9, 0xBA57, 0xD2AA, 0xBA58, 0xD2AB, 0xBA59,
+	0xD2AC, 0xC6AC, 0xD2AD, 0xBA5A, 0xD2AE, 0xBA61, 0xD2AF, 0xBA62,
+	0xD2B0, 0xBA63, 0xD2B1, 0xC6AD, 0xD2B2, 0xBA64, 0xD2B3, 0xBA65,
+	0xD2B4, 0xBA66, 0xD2B5, 0xBA67, 0xD2B6, 0xBA68, 0xD2B7, 0xBA69,
+	0xD2B8, 0xC6AE, 0xD2B9, 0xC6AF, 0xD2BA, 0xBA6A, 0xD2BB, 0xBA6B,
+	0xD2BC, 0xC6B0, 0xD2BD, 0xBA6C, 0xD2BE, 0xBA6D, 0xD2BF, 0xC6B1,
+	0xD2C0, 0xC6B2, 0xD2C1, 0xBA6E, 0xD2C2, 0xC6B3, 0xD2C3, 0xBA6F,
+	0xD2C4, 0xBA70, 0xD2C5, 0xBA71, 0xD2C6, 0xBA72, 0xD2C7, 0xBA73,
+	0xD2C8, 0xC6B4, 0xD2C9, 0xC6B5, 0xD2CA, 0xBA74, 0xD2CB, 0xC6B6,
+	0xD2CC, 0xBA75, 0xD2CD, 0xBA76, 0xD2CE, 0xBA77, 0xD2CF, 0xBA78,
+	0xD2D0, 0xBA79, 0xD2D1, 0xBA7A, 0xD2D2, 0xBA81, 0xD2D3, 0xBA82,
+	0xD2D4, 0xC6B7, 0xD2D5, 0xBA83, 0xD2D6, 0xBA84, 0xD2D7, 0xBA85,
+	0xD2D8, 0xC6B8, 0xD2D9, 0xBA86, 0xD2DA, 0xBA87, 0xD2DB, 0xBA88,
+	0xD2DC, 0xC6B9, 0xD2DD, 0xBA89, 0xD2DE, 0xBA8A, 0xD2DF, 0xBA8B,
+	0xD2E0, 0xBA8C, 0xD2E1, 0xBA8D, 0xD2E2, 0xBA8E, 0xD2E3, 0xBA8F,
+	0xD2E4, 0xC6BA, 0xD2E5, 0xC6BB, 0xD2E6, 0xBA90, 0xD2E7, 0xBA91,
+	0xD2E8, 0xBA92, 0xD2E9, 0xBA93, 0xD2EA, 0xBA94, 0xD2EB, 0xBA95,
+	0xD2EC, 0xBA96, 0xD2ED, 0xBA97, 0xD2EE, 0xBA98, 0xD2EF, 0xBA99,
+	0xD2F0, 0xC6BC, 0xD2F1, 0xC6BD, 0xD2F2, 0xBA9A, 0xD2F3, 0xBA9B,
+	0xD2F4, 0xC6BE, 0xD2F5, 0xBA9C, 0xD2F6, 0xBA9D, 0xD2F7, 0xBA9E,
+	0xD2F8, 0xC6BF, 0xD2F9, 0xBA9F, 0xD2FA, 0xBAA0, 0xD2FB, 0xBB41,
+	0xD2FC, 0xBB42, 0xD2FD, 0xBB43, 0xD2FE, 0xBB44, 0xD2FF, 0xBB45,
+	0xD300, 0xC6C0, 0xD301, 0xC6C1, 0xD302, 0xBB46, 0xD303, 0xC6C2,
+	0xD304, 0xBB47, 0xD305, 0xC6C3, 0xD306, 0xBB48, 0xD307, 0xBB49,
+	0xD308, 0xBB4A, 0xD309, 0xBB4B, 0xD30A, 0xBB4C, 0xD30B, 0xBB4D,
+	0xD30C, 0xC6C4, 0xD30D, 0xC6C5, 0xD30E, 0xC6C6, 0xD30F, 0xBB4E,
+	0xD310, 0xC6C7, 0xD311, 0xBB4F, 0xD312, 0xBB50, 0xD313, 0xBB51,
+	0xD314, 0xC6C8, 0xD315, 0xBB52, 0xD316, 0xC6C9, 0xD317, 0xBB53,
+	0xD318, 0xBB54, 0xD319, 0xBB55, 0xD31A, 0xBB56, 0xD31B, 0xBB57,
+	0xD31C, 0xC6CA, 0xD31D, 0xC6CB, 0xD31E, 0xBB58, 0xD31F, 0xC6CC,
+	0xD320, 0xC6CD, 0xD321, 0xC6CE, 0xD322, 0xBB59, 0xD323, 0xBB5A,
+	0xD324, 0xBB61, 0xD325, 0xC6CF, 0xD326, 0xBB62, 0xD327, 0xBB63,
+	0xD328, 0xC6D0, 0xD329, 0xC6D1, 0xD32A, 0xBB64, 0xD32B, 0xBB65,
+	0xD32C, 0xC6D2, 0xD32D, 0xBB66, 0xD32E, 0xBB67, 0xD32F, 0xBB68,
+	0xD330, 0xC6D3, 0xD331, 0xBB69, 0xD332, 0xBB6A, 0xD333, 0xBB6B,
+	0xD334, 0xBB6C, 0xD335, 0xBB6D, 0xD336, 0xBB6E, 0xD337, 0xBB6F,
+	0xD338, 0xC6D4, 0xD339, 0xC6D5, 0xD33A, 0xBB70, 0xD33B, 0xC6D6,
+	0xD33C, 0xC6D7, 0xD33D, 0xC6D8, 0xD33E, 0xBB71, 0xD33F, 0xBB72,
+	0xD340, 0xBB73, 0xD341, 0xBB74, 0xD342, 0xBB75, 0xD343, 0xBB76,
+	0xD344, 0xC6D9, 0xD345, 0xC6DA, 0xD346, 0xBB77, 0xD347, 0xBB78,
+	0xD348, 0xBB79, 0xD349, 0xBB7A, 0xD34A, 0xBB81, 0xD34B, 0xBB82,
+	0xD34C, 0xBB83, 0xD34D, 0xBB84, 0xD34E, 0xBB85, 0xD34F, 0xBB86,
+	0xD350, 0xBB87, 0xD351, 0xBB88, 0xD352, 0xBB89, 0xD353, 0xBB8A,
+	0xD354, 0xBB8B, 0xD355, 0xBB8C, 0xD356, 0xBB8D, 0xD357, 0xBB8E,
+	0xD358, 0xBB8F, 0xD359, 0xBB90, 0xD35A, 0xBB91, 0xD35B, 0xBB92,
+	0xD35C, 0xBB93, 0xD35D, 0xBB94, 0xD35E, 0xBB95, 0xD35F, 0xBB96,
+	0xD360, 0xBB97, 0xD361, 0xBB98, 0xD362, 0xBB99, 0xD363, 0xBB9A,
+	0xD364, 0xBB9B, 0xD365, 0xBB9C, 0xD366, 0xBB9D, 0xD367, 0xBB9E,
+	0xD368, 0xBB9F, 0xD369, 0xBBA0, 0xD36A, 0xBC41, 0xD36B, 0xBC42,
+	0xD36C, 0xBC43, 0xD36D, 0xBC44, 0xD36E, 0xBC45, 0xD36F, 0xBC46,
+	0xD370, 0xBC47, 0xD371, 0xBC48, 0xD372, 0xBC49, 0xD373, 0xBC4A,
+	0xD374, 0xBC4B, 0xD375, 0xBC4C, 0xD376, 0xBC4D, 0xD377, 0xBC4E,
+	0xD378, 0xBC4F, 0xD379, 0xBC50, 0xD37A, 0xBC51, 0xD37B, 0xBC52,
+	0xD37C, 0xC6DB, 0xD37D, 0xC6DC, 0xD37E, 0xBC53, 0xD37F, 0xBC54,
+	0xD380, 0xC6DD, 0xD381, 0xBC55, 0xD382, 0xBC56, 0xD383, 0xBC57,
+	0xD384, 0xC6DE, 0xD385, 0xBC58, 0xD386, 0xBC59, 0xD387, 0xBC5A,
+	0xD388, 0xBC61, 0xD389, 0xBC62, 0xD38A, 0xBC63, 0xD38B, 0xBC64,
+	0xD38C, 0xC6DF, 0xD38D, 0xC6E0, 0xD38E, 0xBC65, 0xD38F, 0xC6E1,
+	0xD390, 0xC6E2, 0xD391, 0xC6E3, 0xD392, 0xBC66, 0xD393, 0xBC67,
+	0xD394, 0xBC68, 0xD395, 0xBC69, 0xD396, 0xBC6A, 0xD397, 0xBC6B,
+	0xD398, 0xC6E4, 0xD399, 0xC6E5, 0xD39A, 0xBC6C, 0xD39B, 0xBC6D,
+	0xD39C, 0xC6E6, 0xD39D, 0xBC6E, 0xD39E, 0xBC6F, 0xD39F, 0xBC70,
+	0xD3A0, 0xC6E7, 0xD3A1, 0xBC71, 0xD3A2, 0xBC72, 0xD3A3, 0xBC73,
+	0xD3A4, 0xBC74, 0xD3A5, 0xBC75, 0xD3A6, 0xBC76, 0xD3A7, 0xBC77,
+	0xD3A8, 0xC6E8, 0xD3A9, 0xC6E9, 0xD3AA, 0xBC78, 0xD3AB, 0xC6EA,
+	0xD3AC, 0xBC79, 0xD3AD, 0xC6EB, 0xD3AE, 0xBC7A, 0xD3AF, 0xBC81,
+	0xD3B0, 0xBC82, 0xD3B1, 0xBC83, 0xD3B2, 0xBC84, 0xD3B3, 0xBC85,
+	0xD3B4, 0xC6EC, 0xD3B5, 0xBC86, 0xD3B6, 0xBC87, 0xD3B7, 0xBC88,
+	0xD3B8, 0xC6ED, 0xD3B9, 0xBC89, 0xD3BA, 0xBC8A, 0xD3BB, 0xBC8B,
+	0xD3BC, 0xC6EE, 0xD3BD, 0xBC8C, 0xD3BE, 0xBC8D, 0xD3BF, 0xBC8E,
+	0xD3C0, 0xBC8F, 0xD3C1, 0xBC90, 0xD3C2, 0xBC91, 0xD3C3, 0xBC92,
+	0xD3C4, 0xC6EF, 0xD3C5, 0xC6F0, 0xD3C6, 0xBC93, 0xD3C7, 0xBC94,
+	0xD3C8, 0xC6F1, 0xD3C9, 0xC6F2, 0xD3CA, 0xBC95, 0xD3CB, 0xBC96,
+	0xD3CC, 0xBC97, 0xD3CD, 0xBC98, 0xD3CE, 0xBC99, 0xD3CF, 0xBC9A,
+	0xD3D0, 0xC6F3, 0xD3D1, 0xBC9B, 0xD3D2, 0xBC9C, 0xD3D3, 0xBC9D,
+	0xD3D4, 0xBC9E, 0xD3D5, 0xBC9F, 0xD3D6, 0xBCA0, 0xD3D7, 0xBD41,
+	0xD3D8, 0xC6F4, 0xD3D9, 0xBD42, 0xD3DA, 0xBD43, 0xD3DB, 0xBD44,
+	0xD3DC, 0xBD45, 0xD3DD, 0xBD46, 0xD3DE, 0xBD47, 0xD3DF, 0xBD48,
+	0xD3E0, 0xBD49, 0xD3E1, 0xC6F5, 0xD3E2, 0xBD4A, 0xD3E3, 0xC6F6,
+	0xD3E4, 0xBD4B, 0xD3E5, 0xBD4C, 0xD3E6, 0xBD4D, 0xD3E7, 0xBD4E,
+	0xD3E8, 0xBD4F, 0xD3E9, 0xBD50, 0xD3EA, 0xBD51, 0xD3EB, 0xBD52,
+	0xD3EC, 0xC6F7, 0xD3ED, 0xC6F8, 0xD3EE, 0xBD53, 0xD3EF, 0xBD54,
+	0xD3F0, 0xC6F9, 0xD3F1, 0xBD55, 0xD3F2, 0xBD56, 0xD3F3, 0xBD57,
+	0xD3F4, 0xC6FA, 0xD3F5, 0xBD58, 0xD3F6, 0xBD59, 0xD3F7, 0xBD5A,
+	0xD3F8, 0xBD61, 0xD3F9, 0xBD62, 0xD3FA, 0xBD63, 0xD3FB, 0xBD64,
+	0xD3FC, 0xC6FB, 0xD3FD, 0xC6FC, 0xD3FE, 0xBD65, 0xD3FF, 0xC6FD,
+	0xD400, 0xBD66, 0xD401, 0xC6FE, 0xD402, 0xBD67, 0xD403, 0xBD68,
+	0xD404, 0xBD69, 0xD405, 0xBD6A, 0xD406, 0xBD6B, 0xD407, 0xBD6C,
+	0xD408, 0xC7A1, 0xD409, 0xBD6D, 0xD40A, 0xBD6E, 0xD40B, 0xBD6F,
+	0xD40C, 0xBD70, 0xD40D, 0xBD71, 0xD40E, 0xBD72, 0xD40F, 0xBD73,
+	0xD410, 0xBD74, 0xD411, 0xBD75, 0xD412, 0xBD76, 0xD413, 0xBD77,
+	0xD414, 0xBD78, 0xD415, 0xBD79, 0xD416, 0xBD7A, 0xD417, 0xBD81,
+	0xD418, 0xBD82, 0xD419, 0xBD83, 0xD41A, 0xBD84, 0xD41B, 0xBD85,
+	0xD41C, 0xBD86, 0xD41D, 0xC7A2, 0xD41E, 0xBD87, 0xD41F, 0xBD88,
+	0xD420, 0xBD89, 0xD421, 0xBD8A, 0xD422, 0xBD8B, 0xD423, 0xBD8C,
+	0xD424, 0xBD8D, 0xD425, 0xBD8E, 0xD426, 0xBD8F, 0xD427, 0xBD90,
+	0xD428, 0xBD91, 0xD429, 0xBD92, 0xD42A, 0xBD93, 0xD42B, 0xBD94,
+	0xD42C, 0xBD95, 0xD42D, 0xBD96, 0xD42E, 0xBD97, 0xD42F, 0xBD98,
+	0xD430, 0xBD99, 0xD431, 0xBD9A, 0xD432, 0xBD9B, 0xD433, 0xBD9C,
+	0xD434, 0xBD9D, 0xD435, 0xBD9E, 0xD436, 0xBD9F, 0xD437, 0xBDA0,
+	0xD438, 0xBE41, 0xD439, 0xBE42, 0xD43A, 0xBE43, 0xD43B, 0xBE44,
+	0xD43C, 0xBE45, 0xD43D, 0xBE46, 0xD43E, 0xBE47, 0xD43F, 0xBE48,
+	0xD440, 0xC7A3, 0xD441, 0xBE49, 0xD442, 0xBE4A, 0xD443, 0xBE4B,
+	0xD444, 0xC7A4, 0xD445, 0xBE4C, 0xD446, 0xBE4D, 0xD447, 0xBE4E,
+	0xD448, 0xBE4F, 0xD449, 0xBE50, 0xD44A, 0xBE51, 0xD44B, 0xBE52,
+	0xD44C, 0xBE53, 0xD44D, 0xBE54, 0xD44E, 0xBE55, 0xD44F, 0xBE56,
+	0xD450, 0xBE57, 0xD451, 0xBE58, 0xD452, 0xBE59, 0xD453, 0xBE5A,
+	0xD454, 0xBE61, 0xD455, 0xBE62, 0xD456, 0xBE63, 0xD457, 0xBE64,
+	0xD458, 0xBE65, 0xD459, 0xBE66, 0xD45A, 0xBE67, 0xD45B, 0xBE68,
+	0xD45C, 0xC7A5, 0xD45D, 0xBE69, 0xD45E, 0xBE6A, 0xD45F, 0xBE6B,
+	0xD460, 0xC7A6, 0xD461, 0xBE6C, 0xD462, 0xBE6D, 0xD463, 0xBE6E,
+	0xD464, 0xC7A7, 0xD465, 0xBE6F, 0xD466, 0xBE70, 0xD467, 0xBE71,
+	0xD468, 0xBE72, 0xD469, 0xBE73, 0xD46A, 0xBE74, 0xD46B, 0xBE75,
+	0xD46C, 0xBE76, 0xD46D, 0xC7A8, 0xD46E, 0xBE77, 0xD46F, 0xC7A9,
+	0xD470, 0xBE78, 0xD471, 0xBE79, 0xD472, 0xBE7A, 0xD473, 0xBE81,
+	0xD474, 0xBE82, 0xD475, 0xBE83, 0xD476, 0xBE84, 0xD477, 0xBE85,
+	0xD478, 0xC7AA, 0xD479, 0xC7AB, 0xD47A, 0xBE86, 0xD47B, 0xBE87,
+	0xD47C, 0xC7AC, 0xD47D, 0xBE88, 0xD47E, 0xBE89, 0xD47F, 0xC7AD,
+	0xD480, 0xC7AE, 0xD481, 0xBE8A, 0xD482, 0xC7AF, 0xD483, 0xBE8B,
+	0xD484, 0xBE8C, 0xD485, 0xBE8D, 0xD486, 0xBE8E, 0xD487, 0xBE8F,
+	0xD488, 0xC7B0, 0xD489, 0xC7B1, 0xD48A, 0xBE90, 0xD48B, 0xC7B2,
+	0xD48C, 0xBE91, 0xD48D, 0xC7B3, 0xD48E, 0xBE92, 0xD48F, 0xBE93,
+	0xD490, 0xBE94, 0xD491, 0xBE95, 0xD492, 0xBE96, 0xD493, 0xBE97,
+	0xD494, 0xC7B4, 0xD495, 0xBE98, 0xD496, 0xBE99, 0xD497, 0xBE9A,
+	0xD498, 0xBE9B, 0xD499, 0xBE9C, 0xD49A, 0xBE9D, 0xD49B, 0xBE9E,
+	0xD49C, 0xBE9F, 0xD49D, 0xBEA0, 0xD49E, 0xBF41, 0xD49F, 0xBF42,
+	0xD4A0, 0xBF43, 0xD4A1, 0xBF44, 0xD4A2, 0xBF45, 0xD4A3, 0xBF46,
+	0xD4A4, 0xBF47, 0xD4A5, 0xBF48, 0xD4A6, 0xBF49, 0xD4A7, 0xBF4A,
+	0xD4A8, 0xBF4B, 0xD4A9, 0xC7B5, 0xD4AA, 0xBF4C, 0xD4AB, 0xBF4D,
+	0xD4AC, 0xBF4E, 0xD4AD, 0xBF4F, 0xD4AE, 0xBF50, 0xD4AF, 0xBF51,
+	0xD4B0, 0xBF52, 0xD4B1, 0xBF53, 0xD4B2, 0xBF54, 0xD4B3, 0xBF55,
+	0xD4B4, 0xBF56, 0xD4B5, 0xBF57, 0xD4B6, 0xBF58, 0xD4B7, 0xBF59,
+	0xD4B8, 0xBF5A, 0xD4B9, 0xBF61, 0xD4BA, 0xBF62, 0xD4BB, 0xBF63,
+	0xD4BC, 0xBF64, 0xD4BD, 0xBF65, 0xD4BE, 0xBF66, 0xD4BF, 0xBF67,
+	0xD4C0, 0xBF68, 0xD4C1, 0xBF69, 0xD4C2, 0xBF6A, 0xD4C3, 0xBF6B,
+	0xD4C4, 0xBF6C, 0xD4C5, 0xBF6D, 0xD4C6, 0xBF6E, 0xD4C7, 0xBF6F,
+	0xD4C8, 0xBF70, 0xD4C9, 0xBF71, 0xD4CA, 0xBF72, 0xD4CB, 0xBF73,
+	0xD4CC, 0xC7B6, 0xD4CD, 0xBF74, 0xD4CE, 0xBF75, 0xD4CF, 0xBF76,
+	0xD4D0, 0xC7B7, 0xD4D1, 0xBF77, 0xD4D2, 0xBF78, 0xD4D3, 0xBF79,
+	0xD4D4, 0xC7B8, 0xD4D5, 0xBF7A, 0xD4D6, 0xBF81, 0xD4D7, 0xBF82,
+	0xD4D8, 0xBF83, 0xD4D9, 0xBF84, 0xD4DA, 0xBF85, 0xD4DB, 0xBF86,
+	0xD4DC, 0xC7B9, 0xD4DD, 0xBF87, 0xD4DE, 0xBF88, 0xD4DF, 0xC7BA,
+	0xD4E0, 0xBF89, 0xD4E1, 0xBF8A, 0xD4E2, 0xBF8B, 0xD4E3, 0xBF8C,
+	0xD4E4, 0xBF8D, 0xD4E5, 0xBF8E, 0xD4E6, 0xBF8F, 0xD4E7, 0xBF90,
+	0xD4E8, 0xC7BB, 0xD4E9, 0xBF91, 0xD4EA, 0xBF92, 0xD4EB, 0xBF93,
+	0xD4EC, 0xC7BC, 0xD4ED, 0xBF94, 0xD4EE, 0xBF95, 0xD4EF, 0xBF96,
+	0xD4F0, 0xC7BD, 0xD4F1, 0xBF97, 0xD4F2, 0xBF98, 0xD4F3, 0xBF99,
+	0xD4F4, 0xBF9A, 0xD4F5, 0xBF9B, 0xD4F6, 0xBF9C, 0xD4F7, 0xBF9D,
+	0xD4F8, 0xC7BE, 0xD4F9, 0xBF9E, 0xD4FA, 0xBF9F, 0xD4FB, 0xC7BF,
+	0xD4FC, 0xBFA0, 0xD4FD, 0xC7C0, 0xD4FE, 0xC041, 0xD4FF, 0xC042,
+	0xD500, 0xC043, 0xD501, 0xC044, 0xD502, 0xC045, 0xD503, 0xC046,
+	0xD504, 0xC7C1, 0xD505, 0xC047, 0xD506, 0xC048, 0xD507, 0xC049,
+	0xD508, 0xC7C2, 0xD509, 0xC04A, 0xD50A, 0xC04B, 0xD50B, 0xC04C,
+	0xD50C, 0xC7C3, 0xD50D, 0xC04D, 0xD50E, 0xC04E, 0xD50F, 0xC04F,
+	0xD510, 0xC050, 0xD511, 0xC051, 0xD512, 0xC052, 0xD513, 0xC053,
+	0xD514, 0xC7C4, 0xD515, 0xC7C5, 0xD516, 0xC054, 0xD517, 0xC7C6,
+	0xD518, 0xC055, 0xD519, 0xC056, 0xD51A, 0xC057, 0xD51B, 0xC058,
+	0xD51C, 0xC059, 0xD51D, 0xC05A, 0xD51E, 0xC061, 0xD51F, 0xC062,
+	0xD520, 0xC063, 0xD521, 0xC064, 0xD522, 0xC065, 0xD523, 0xC066,
+	0xD524, 0xC067, 0xD525, 0xC068, 0xD526, 0xC069, 0xD527, 0xC06A,
+	0xD528, 0xC06B, 0xD529, 0xC06C, 0xD52A, 0xC06D, 0xD52B, 0xC06E,
+	0xD52C, 0xC06F, 0xD52D, 0xC070, 0xD52E, 0xC071, 0xD52F, 0xC072,
+	0xD530, 0xC073, 0xD531, 0xC074, 0xD532, 0xC075, 0xD533, 0xC076,
+	0xD534, 0xC077, 0xD535, 0xC078, 0xD536, 0xC079, 0xD537, 0xC07A,
+	0xD538, 0xC081, 0xD539, 0xC082, 0xD53A, 0xC083, 0xD53B, 0xC084,
+	0xD53C, 0xC7C7, 0xD53D, 0xC7C8, 0xD53E, 0xC085, 0xD53F, 0xC086,
+	0xD540, 0xC7C9, 0xD541, 0xC087, 0xD542, 0xC088, 0xD543, 0xC089,
+	0xD544, 0xC7CA, 0xD545, 0xC08A, 0xD546, 0xC08B, 0xD547, 0xC08C,
+	0xD548, 0xC08D, 0xD549, 0xC08E, 0xD54A, 0xC08F, 0xD54B, 0xC090,
+	0xD54C, 0xC7CB, 0xD54D, 0xC7CC, 0xD54E, 0xC091, 0xD54F, 0xC7CD,
+	0xD550, 0xC092, 0xD551, 0xC7CE, 0xD552, 0xC093, 0xD553, 0xC094,
+	0xD554, 0xC095, 0xD555, 0xC096, 0xD556, 0xC097, 0xD557, 0xC098,
+	0xD558, 0xC7CF, 0xD559, 0xC7D0, 0xD55A, 0xC099, 0xD55B, 0xC09A,
+	0xD55C, 0xC7D1, 0xD55D, 0xC09B, 0xD55E, 0xC09C, 0xD55F, 0xC09D,
+	0xD560, 0xC7D2, 0xD561, 0xC09E, 0xD562, 0xC09F, 0xD563, 0xC0A0,
+	0xD564, 0xC141, 0xD565, 0xC7D3, 0xD566, 0xC142, 0xD567, 0xC143,
+	0xD568, 0xC7D4, 0xD569, 0xC7D5, 0xD56A, 0xC144, 0xD56B, 0xC7D6,
+	0xD56C, 0xC145, 0xD56D, 0xC7D7, 0xD56E, 0xC146, 0xD56F, 0xC147,
+	0xD570, 0xC148, 0xD571, 0xC149, 0xD572, 0xC14A, 0xD573, 0xC14B,
+	0xD574, 0xC7D8, 0xD575, 0xC7D9, 0xD576, 0xC14C, 0xD577, 0xC14D,
+	0xD578, 0xC7DA, 0xD579, 0xC14E, 0xD57A, 0xC14F, 0xD57B, 0xC150,
+	0xD57C, 0xC7DB, 0xD57D, 0xC151, 0xD57E, 0xC152, 0xD57F, 0xC153,
+	0xD580, 0xC154, 0xD581, 0xC155, 0xD582, 0xC156, 0xD583, 0xC157,
+	0xD584, 0xC7DC, 0xD585, 0xC7DD, 0xD586, 0xC158, 0xD587, 0xC7DE,
+	0xD588, 0xC7DF, 0xD589, 0xC7E0, 0xD58A, 0xC159, 0xD58B, 0xC15A,
+	0xD58C, 0xC161, 0xD58D, 0xC162, 0xD58E, 0xC163, 0xD58F, 0xC164,
+	0xD590, 0xC7E1, 0xD591, 0xC165, 0xD592, 0xC166, 0xD593, 0xC167,
+	0xD594, 0xC168, 0xD595, 0xC169, 0xD596, 0xC16A, 0xD597, 0xC16B,
+	0xD598, 0xC16C, 0xD599, 0xC16D, 0xD59A, 0xC16E, 0xD59B, 0xC16F,
+	0xD59C, 0xC170, 0xD59D, 0xC171, 0xD59E, 0xC172, 0xD59F, 0xC173,
+	0xD5A0, 0xC174, 0xD5A1, 0xC175, 0xD5A2, 0xC176, 0xD5A3, 0xC177,
+	0xD5A4, 0xC178, 0xD5A5, 0xC7E2, 0xD5A6, 0xC179, 0xD5A7, 0xC17A,
+	0xD5A8, 0xC181, 0xD5A9, 0xC182, 0xD5AA, 0xC183, 0xD5AB, 0xC184,
+	0xD5AC, 0xC185, 0xD5AD, 0xC186, 0xD5AE, 0xC187, 0xD5AF, 0xC188,
+	0xD5B0, 0xC189, 0xD5B1, 0xC18A, 0xD5B2, 0xC18B, 0xD5B3, 0xC18C,
+	0xD5B4, 0xC18D, 0xD5B5, 0xC18E, 0xD5B6, 0xC18F, 0xD5B7, 0xC190,
+	0xD5B8, 0xC191, 0xD5B9, 0xC192, 0xD5BA, 0xC193, 0xD5BB, 0xC194,
+	0xD5BC, 0xC195, 0xD5BD, 0xC196, 0xD5BE, 0xC197, 0xD5BF, 0xC198,
+	0xD5C0, 0xC199, 0xD5C1, 0xC19A, 0xD5C2, 0xC19B, 0xD5C3, 0xC19C,
+	0xD5C4, 0xC19D, 0xD5C5, 0xC19E, 0xD5C6, 0xC19F, 0xD5C7, 0xC1A0,
+	0xD5C8, 0xC7E3, 0xD5C9, 0xC7E4, 0xD5CA, 0xC241, 0xD5CB, 0xC242,
+	0xD5CC, 0xC7E5, 0xD5CD, 0xC243, 0xD5CE, 0xC244, 0xD5CF, 0xC245,
+	0xD5D0, 0xC7E6, 0xD5D1, 0xC246, 0xD5D2, 0xC7E7, 0xD5D3, 0xC247,
+	0xD5D4, 0xC248, 0xD5D5, 0xC249, 0xD5D6, 0xC24A, 0xD5D7, 0xC24B,
+	0xD5D8, 0xC7E8, 0xD5D9, 0xC7E9, 0xD5DA, 0xC24C, 0xD5DB, 0xC7EA,
+	0xD5DC, 0xC24D, 0xD5DD, 0xC7EB, 0xD5DE, 0xC24E, 0xD5DF, 0xC24F,
+	0xD5E0, 0xC250, 0xD5E1, 0xC251, 0xD5E2, 0xC252, 0xD5E3, 0xC253,
+	0xD5E4, 0xC7EC, 0xD5E5, 0xC7ED, 0xD5E6, 0xC254, 0xD5E7, 0xC255,
+	0xD5E8, 0xC7EE, 0xD5E9, 0xC256, 0xD5EA, 0xC257, 0xD5EB, 0xC258,
+	0xD5EC, 0xC7EF, 0xD5ED, 0xC259, 0xD5EE, 0xC25A, 0xD5EF, 0xC261,
+	0xD5F0, 0xC262, 0xD5F1, 0xC263, 0xD5F2, 0xC264, 0xD5F3, 0xC265,
+	0xD5F4, 0xC7F0, 0xD5F5, 0xC7F1, 0xD5F6, 0xC266, 0xD5F7, 0xC7F2,
+	0xD5F8, 0xC267, 0xD5F9, 0xC7F3, 0xD5FA, 0xC268, 0xD5FB, 0xC269,
+	0xD5FC, 0xC26A, 0xD5FD, 0xC26B, 0xD5FE, 0xC26C, 0xD5FF, 0xC26D,
+	0xD600, 0xC7F4, 0xD601, 0xC7F5, 0xD602, 0xC26E, 0xD603, 0xC26F,
+	0xD604, 0xC7F6, 0xD605, 0xC270, 0xD606, 0xC271, 0xD607, 0xC272,
+	0xD608, 0xC7F7, 0xD609, 0xC273, 0xD60A, 0xC274, 0xD60B, 0xC275,
+	0xD60C, 0xC276, 0xD60D, 0xC277, 0xD60E, 0xC278, 0xD60F, 0xC279,
+	0xD610, 0xC7F8, 0xD611, 0xC7F9, 0xD612, 0xC27A, 0xD613, 0xC7FA,
+	0xD614, 0xC7FB, 0xD615, 0xC7FC, 0xD616, 0xC281, 0xD617, 0xC282,
+	0xD618, 0xC283, 0xD619, 0xC284, 0xD61A, 0xC285, 0xD61B, 0xC286,
+	0xD61C, 0xC7FD, 0xD61D, 0xC287, 0xD61E, 0xC288, 0xD61F, 0xC289,
+	0xD620, 0xC7FE, 0xD621, 0xC28A, 0xD622, 0xC28B, 0xD623, 0xC28C,
+	0xD624, 0xC8A1, 0xD625, 0xC28D, 0xD626, 0xC28E, 0xD627, 0xC28F,
+	0xD628, 0xC290, 0xD629, 0xC291, 0xD62A, 0xC292, 0xD62B, 0xC293,
+	0xD62C, 0xC294, 0xD62D, 0xC8A2, 0xD62E, 0xC295, 0xD62F, 0xC296,
+	0xD630, 0xC297, 0xD631, 0xC298, 0xD632, 0xC299, 0xD633, 0xC29A,
+	0xD634, 0xC29B, 0xD635, 0xC29C, 0xD636, 0xC29D, 0xD637, 0xC29E,
+	0xD638, 0xC8A3, 0xD639, 0xC8A4, 0xD63A, 0xC29F, 0xD63B, 0xC2A0,
+	0xD63C, 0xC8A5, 0xD63D, 0xC341, 0xD63E, 0xC342, 0xD63F, 0xC343,
+	0xD640, 0xC8A6, 0xD641, 0xC344, 0xD642, 0xC345, 0xD643, 0xC346,
+	0xD644, 0xC347, 0xD645, 0xC8A7, 0xD646, 0xC348, 0xD647, 0xC349,
+	0xD648, 0xC8A8, 0xD649, 0xC8A9, 0xD64A, 0xC34A, 0xD64B, 0xC8AA,
+	0xD64C, 0xC34B, 0xD64D, 0xC8AB, 0xD64E, 0xC34C, 0xD64F, 0xC34D,
+	0xD650, 0xC34E, 0xD651, 0xC8AC, 0xD652, 0xC34F, 0xD653, 0xC350,
+	0xD654, 0xC8AD, 0xD655, 0xC8AE, 0xD656, 0xC351, 0xD657, 0xC352,
+	0xD658, 0xC8AF, 0xD659, 0xC353, 0xD65A, 0xC354, 0xD65B, 0xC355,
+	0xD65C, 0xC8B0, 0xD65D, 0xC356, 0xD65E, 0xC357, 0xD65F, 0xC358,
+	0xD660, 0xC359, 0xD661, 0xC35A, 0xD662, 0xC361, 0xD663, 0xC362,
+	0xD664, 0xC363, 0xD665, 0xC364, 0xD666, 0xC365, 0xD667, 0xC8B1,
+	0xD668, 0xC366, 0xD669, 0xC8B2, 0xD66A, 0xC367, 0xD66B, 0xC368,
+	0xD66C, 0xC369, 0xD66D, 0xC36A, 0xD66E, 0xC36B, 0xD66F, 0xC36C,
+	0xD670, 0xC8B3, 0xD671, 0xC8B4, 0xD672, 0xC36D, 0xD673, 0xC36E,
+	0xD674, 0xC8B5, 0xD675, 0xC36F, 0xD676, 0xC370, 0xD677, 0xC371,
+	0xD678, 0xC372, 0xD679, 0xC373, 0xD67A, 0xC374, 0xD67B, 0xC375,
+	0xD67C, 0xC376, 0xD67D, 0xC377, 0xD67E, 0xC378, 0xD67F, 0xC379,
+	0xD680, 0xC37A, 0xD681, 0xC381, 0xD682, 0xC382, 0xD683, 0xC8B6,
+	0xD684, 0xC383, 0xD685, 0xC8B7, 0xD686, 0xC384, 0xD687, 0xC385,
+	0xD688, 0xC386, 0xD689, 0xC387, 0xD68A, 0xC388, 0xD68B, 0xC389,
+	0xD68C, 0xC8B8, 0xD68D, 0xC8B9, 0xD68E, 0xC38A, 0xD68F, 0xC38B,
+	0xD690, 0xC8BA, 0xD691, 0xC38C, 0xD692, 0xC38D, 0xD693, 0xC38E,
+	0xD694, 0xC8BB, 0xD695, 0xC38F, 0xD696, 0xC390, 0xD697, 0xC391,
+	0xD698, 0xC392, 0xD699, 0xC393, 0xD69A, 0xC394, 0xD69B, 0xC395,
+	0xD69C, 0xC396, 0xD69D, 0xC8BC, 0xD69E, 0xC397, 0xD69F, 0xC8BD,
+	0xD6A0, 0xC398, 0xD6A1, 0xC8BE, 0xD6A2, 0xC399, 0xD6A3, 0xC39A,
+	0xD6A4, 0xC39B, 0xD6A5, 0xC39C, 0xD6A6, 0xC39D, 0xD6A7, 0xC39E,
+	0xD6A8, 0xC8BF, 0xD6A9, 0xC39F, 0xD6AA, 0xC3A0, 0xD6AB, 0xC441,
+	0xD6AC, 0xC8C0, 0xD6AD, 0xC442, 0xD6AE, 0xC443, 0xD6AF, 0xC444,
+	0xD6B0, 0xC8C1, 0xD6B1, 0xC445, 0xD6B2, 0xC446, 0xD6B3, 0xC447,
+	0xD6B4, 0xC448, 0xD6B5, 0xC449, 0xD6B6, 0xC44A, 0xD6B7, 0xC44B,
+	0xD6B8, 0xC44C, 0xD6B9, 0xC8C2, 0xD6BA, 0xC44D, 0xD6BB, 0xC8C3,
+	0xD6BC, 0xC44E, 0xD6BD, 0xC44F, 0xD6BE, 0xC450, 0xD6BF, 0xC451,
+	0xD6C0, 0xC452, 0xD6C1, 0xC453, 0xD6C2, 0xC454, 0xD6C3, 0xC455,
+	0xD6C4, 0xC8C4, 0xD6C5, 0xC8C5, 0xD6C6, 0xC456, 0xD6C7, 0xC457,
+	0xD6C8, 0xC8C6, 0xD6C9, 0xC458, 0xD6CA, 0xC459, 0xD6CB, 0xC45A,
+	0xD6CC, 0xC8C7, 0xD6CD, 0xC461, 0xD6CE, 0xC462, 0xD6CF, 0xC463,
+	0xD6D0, 0xC464, 0xD6D1, 0xC8C8, 0xD6D2, 0xC465, 0xD6D3, 0xC466,
+	0xD6D4, 0xC8C9, 0xD6D5, 0xC467, 0xD6D6, 0xC468, 0xD6D7, 0xC8CA,
+	0xD6D8, 0xC469, 0xD6D9, 0xC8CB, 0xD6DA, 0xC46A, 0xD6DB, 0xC46B,
+	0xD6DC, 0xC46C, 0xD6DD, 0xC46D, 0xD6DE, 0xC46E, 0xD6DF, 0xC46F,
+	0xD6E0, 0xC8CC, 0xD6E1, 0xC470, 0xD6E2, 0xC471, 0xD6E3, 0xC472,
+	0xD6E4, 0xC8CD, 0xD6E5, 0xC473, 0xD6E6, 0xC474, 0xD6E7, 0xC475,
+	0xD6E8, 0xC8CE, 0xD6E9, 0xC476, 0xD6EA, 0xC477, 0xD6EB, 0xC478,
+	0xD6EC, 0xC479, 0xD6ED, 0xC47A, 0xD6EE, 0xC481, 0xD6EF, 0xC482,
+	0xD6F0, 0xC8CF, 0xD6F1, 0xC483, 0xD6F2, 0xC484, 0xD6F3, 0xC485,
+	0xD6F4, 0xC486, 0xD6F5, 0xC8D0, 0xD6F6, 0xC487, 0xD6F7, 0xC488,
+	0xD6F8, 0xC489, 0xD6F9, 0xC48A, 0xD6FA, 0xC48B, 0xD6FB, 0xC48C,
+	0xD6FC, 0xC8D1, 0xD6FD, 0xC8D2, 0xD6FE, 0xC48D, 0xD6FF, 0xC48E,
+	0xD700, 0xC8D3, 0xD701, 0xC48F, 0xD702, 0xC490, 0xD703, 0xC491,
+	0xD704, 0xC8D4, 0xD705, 0xC492, 0xD706, 0xC493, 0xD707, 0xC494,
+	0xD708, 0xC495, 0xD709, 0xC496, 0xD70A, 0xC497, 0xD70B, 0xC498,
+	0xD70C, 0xC499, 0xD70D, 0xC49A, 0xD70E, 0xC49B, 0xD70F, 0xC49C,
+	0xD710, 0xC49D, 0xD711, 0xC8D5, 0xD712, 0xC49E, 0xD713, 0xC49F,
+	0xD714, 0xC4A0, 0xD715, 0xC541, 0xD716, 0xC542, 0xD717, 0xC543,
+	0xD718, 0xC8D6, 0xD719, 0xC8D7, 0xD71A, 0xC544, 0xD71B, 0xC545,
+	0xD71C, 0xC8D8, 0xD71D, 0xC546, 0xD71E, 0xC547, 0xD71F, 0xC548,
+	0xD720, 0xC8D9, 0xD721, 0xC549, 0xD722, 0xC54A, 0xD723, 0xC54B,
+	0xD724, 0xC54C, 0xD725, 0xC54D, 0xD726, 0xC54E, 0xD727, 0xC54F,
+	0xD728, 0xC8DA, 0xD729, 0xC8DB, 0xD72A, 0xC550, 0xD72B, 0xC8DC,
+	0xD72C, 0xC551, 0xD72D, 0xC8DD, 0xD72E, 0xC552, 0xD72F, 0xC553,
+	0xD730, 0xC554, 0xD731, 0xC555, 0xD732, 0xC556, 0xD733, 0xC557,
+	0xD734, 0xC8DE, 0xD735, 0xC8DF, 0xD736, 0xC558, 0xD737, 0xC559,
+	0xD738, 0xC8E0, 0xD739, 0xC55A, 0xD73A, 0xC561, 0xD73B, 0xC562,
+	0xD73C, 0xC8E1, 0xD73D, 0xC563, 0xD73E, 0xC564, 0xD73F, 0xC565,
+	0xD740, 0xC566, 0xD741, 0xC567, 0xD742, 0xC568, 0xD743, 0xC569,
+	0xD744, 0xC8E2, 0xD745, 0xC56A, 0xD746, 0xC56B, 0xD747, 0xC8E3,
+	0xD748, 0xC56C, 0xD749, 0xC8E4, 0xD74A, 0xC56D, 0xD74B, 0xC56E,
+	0xD74C, 0xC56F, 0xD74D, 0xC570, 0xD74E, 0xC571, 0xD74F, 0xC572,
+	0xD750, 0xC8E5, 0xD751, 0xC8E6, 0xD752, 0xC573, 0xD753, 0xC574,
+	0xD754, 0xC8E7, 0xD755, 0xC575, 0xD756, 0xC8E8, 0xD757, 0xC8E9,
+	0xD758, 0xC8EA, 0xD759, 0xC8EB, 0xD75A, 0xC576, 0xD75B, 0xC577,
+	0xD75C, 0xC578, 0xD75D, 0xC579, 0xD75E, 0xC57A, 0xD75F, 0xC581,
+	0xD760, 0xC8EC, 0xD761, 0xC8ED, 0xD762, 0xC582, 0xD763, 0xC8EE,
+	0xD764, 0xC583, 0xD765, 0xC8EF, 0xD766, 0xC584, 0xD767, 0xC585,
+	0xD768, 0xC586, 0xD769, 0xC8F0, 0xD76A, 0xC587, 0xD76B, 0xC588,
+	0xD76C, 0xC8F1, 0xD76D, 0xC589, 0xD76E, 0xC58A, 0xD76F, 0xC58B,
+	0xD770, 0xC8F2, 0xD771, 0xC58C, 0xD772, 0xC58D, 0xD773, 0xC58E,
+	0xD774, 0xC8F3, 0xD775, 0xC58F, 0xD776, 0xC590, 0xD777, 0xC591,
+	0xD778, 0xC592, 0xD779, 0xC593, 0xD77A, 0xC594, 0xD77B, 0xC595,
+	0xD77C, 0xC8F4, 0xD77D, 0xC8F5, 0xD77E, 0xC596, 0xD77F, 0xC597,
+	0xD780, 0xC598, 0xD781, 0xC8F6, 0xD782, 0xC599, 0xD783, 0xC59A,
+	0xD784, 0xC59B, 0xD785, 0xC59C, 0xD786, 0xC59D, 0xD787, 0xC59E,
+	0xD788, 0xC8F7, 0xD789, 0xC8F8, 0xD78A, 0xC59F, 0xD78B, 0xC5A0,
+	0xD78C, 0xC8F9, 0xD78D, 0xC641, 0xD78E, 0xC642, 0xD78F, 0xC643,
+	0xD790, 0xC8FA, 0xD791, 0xC644, 0xD792, 0xC645, 0xD793, 0xC646,
+	0xD794, 0xC647, 0xD795, 0xC648, 0xD796, 0xC649, 0xD797, 0xC64A,
+	0xD798, 0xC8FB, 0xD799, 0xC8FC, 0xD79A, 0xC64B, 0xD79B, 0xC8FD,
+	0xD79C, 0xC64C, 0xD79D, 0xC8FE, 0xD79E, 0xC64D, 0xD79F, 0xC64E,
+	0xD7A0, 0xC64F, 0xD7A1, 0xC650, 0xD7A2, 0xC651, 0xD7A3, 0xC652,
+	0xF900, 0xCBD0, 0xF901, 0xCBD6, 0xF902, 0xCBE7, 0xF903, 0xCDCF,
+	0xF904, 0xCDE8, 0xF905, 0xCEAD, 0xF906, 0xCFFB, 0xF907, 0xD0A2,
+	0xF908, 0xD0B8, 0xF909, 0xD0D0, 0xF90A, 0xD0DD, 0xF90B, 0xD1D4,
+	0xF90C, 0xD1D5, 0xF90D, 0xD1D8, 0xF90E, 0xD1DB, 0xF90F, 0xD1DC,
+	0xF910, 0xD1DD, 0xF911, 0xD1DE, 0xF912, 0xD1DF, 0xF913, 0xD1E0,
+	0xF914, 0xD1E2, 0xF915, 0xD1E3, 0xF916, 0xD1E4, 0xF917, 0xD1E5,
+	0xF918, 0xD1E6, 0xF919, 0xD1E8, 0xF91A, 0xD1E9, 0xF91B, 0xD1EA,
+	0xF91C, 0xD1EB, 0xF91D, 0xD1ED, 0xF91E, 0xD1EF, 0xF91F, 0xD1F0,
+	0xF920, 0xD1F2, 0xF921, 0xD1F6, 0xF922, 0xD1FA, 0xF923, 0xD1FC,
+	0xF924, 0xD1FD, 0xF925, 0xD1FE, 0xF926, 0xD2A2, 0xF927, 0xD2A3,
+	0xF928, 0xD2A7, 0xF929, 0xD2A8, 0xF92A, 0xD2A9, 0xF92B, 0xD2AA,
+	0xF92C, 0xD2AB, 0xF92D, 0xD2AD, 0xF92E, 0xD2B2, 0xF92F, 0xD2BE,
+	0xF930, 0xD2C2, 0xF931, 0xD2C3, 0xF932, 0xD2C4, 0xF933, 0xD2C6,
+	0xF934, 0xD2C7, 0xF935, 0xD2C8, 0xF936, 0xD2C9, 0xF937, 0xD2CA,
+	0xF938, 0xD2CB, 0xF939, 0xD2CD, 0xF93A, 0xD2CE, 0xF93B, 0xD2CF,
+	0xF93C, 0xD2D0, 0xF93D, 0xD2D1, 0xF93E, 0xD2D2, 0xF93F, 0xD2D3,
+	0xF940, 0xD2D4, 0xF941, 0xD2D5, 0xF942, 0xD2D6, 0xF943, 0xD2D7,
+	0xF944, 0xD2D9, 0xF945, 0xD2DA, 0xF946, 0xD2DE, 0xF947, 0xD2DF,
+	0xF948, 0xD2E1, 0xF949, 0xD2E2, 0xF94A, 0xD2E4, 0xF94B, 0xD2E5,
+	0xF94C, 0xD2E6, 0xF94D, 0xD2E7, 0xF94E, 0xD2E8, 0xF94F, 0xD2E9,
+	0xF950, 0xD2EA, 0xF951, 0xD2EB, 0xF952, 0xD2F0, 0xF953, 0xD2F1,
+	0xF954, 0xD2F2, 0xF955, 0xD2F3, 0xF956, 0xD2F4, 0xF957, 0xD2F5,
+	0xF958, 0xD2F7, 0xF959, 0xD2F8, 0xF95A, 0xD4E6, 0xF95B, 0xD4FC,
+	0xF95C, 0xD5A5, 0xF95D, 0xD5AB, 0xF95E, 0xD5AE, 0xF95F, 0xD6B8,
+	0xF960, 0xD6CD, 0xF961, 0xD7CB, 0xF962, 0xD7E4, 0xF963, 0xDBC5,
+	0xF964, 0xDBE4, 0xF965, 0xDCA5, 0xF966, 0xDDA5, 0xF967, 0xDDD5,
+	0xF968, 0xDDF4, 0xF969, 0xDEFC, 0xF96A, 0xDEFE, 0xF96B, 0xDFB3,
+	0xF96C, 0xDFE1, 0xF96D, 0xDFE8, 0xF96E, 0xE0F1, 0xF96F, 0xE1AD,
+	0xF970, 0xE1ED, 0xF971, 0xE3F5, 0xF972, 0xE4A1, 0xF973, 0xE4A9,
+	0xF974, 0xE5AE, 0xF975, 0xE5B1, 0xF976, 0xE5B2, 0xF977, 0xE5B9,
+	0xF978, 0xE5BB, 0xF979, 0xE5BC, 0xF97A, 0xE5C4, 0xF97B, 0xE5CE,
+	0xF97C, 0xE5D0, 0xF97D, 0xE5D2, 0xF97E, 0xE5D6, 0xF97F, 0xE5FA,
+	0xF980, 0xE5FB, 0xF981, 0xE5FC, 0xF982, 0xE5FE, 0xF983, 0xE6A1,
+	0xF984, 0xE6A4, 0xF985, 0xE6A7, 0xF986, 0xE6AD, 0xF987, 0xE6AF,
+	0xF988, 0xE6B0, 0xF989, 0xE6B1, 0xF98A, 0xE6B3, 0xF98B, 0xE6B7,
+	0xF98C, 0xE6B8, 0xF98D, 0xE6BC, 0xF98E, 0xE6C4, 0xF98F, 0xE6C6,
+	0xF990, 0xE6C7, 0xF991, 0xE6CA, 0xF992, 0xE6D2, 0xF993, 0xE6D6,
+	0xF994, 0xE6D9, 0xF995, 0xE6DC, 0xF996, 0xE6DF, 0xF997, 0xE6E1,
+	0xF998, 0xE6E4, 0xF999, 0xE6E5, 0xF99A, 0xE6E6, 0xF99B, 0xE6E8,
+	0xF99C, 0xE6EA, 0xF99D, 0xE6EB, 0xF99E, 0xE6EC, 0xF99F, 0xE6EF,
+	0xF9A0, 0xE6F1, 0xF9A1, 0xE6F2, 0xF9A2, 0xE6F5, 0xF9A3, 0xE6F6,
+	0xF9A4, 0xE6F7, 0xF9A5, 0xE6F9, 0xF9A6, 0xE7A1, 0xF9A7, 0xE7A6,
+	0xF9A8, 0xE7A9, 0xF9A9, 0xE7AA, 0xF9AA, 0xE7AC, 0xF9AB, 0xE7AD,
+	0xF9AC, 0xE7B0, 0xF9AD, 0xE7BF, 0xF9AE, 0xE7C1, 0xF9AF, 0xE7C6,
+	0xF9B0, 0xE7C7, 0xF9B1, 0xE7CB, 0xF9B2, 0xE7CD, 0xF9B3, 0xE7CF,
+	0xF9B4, 0xE7D0, 0xF9B5, 0xE7D3, 0xF9B6, 0xE7DF, 0xF9B7, 0xE7E4,
+	0xF9B8, 0xE7E6, 0xF9B9, 0xE7F7, 0xF9BA, 0xE8E7, 0xF9BB, 0xE8E8,
+	0xF9BC, 0xE8F0, 0xF9BD, 0xE8F1, 0xF9BE, 0xE8F7, 0xF9BF, 0xE8F9,
+	0xF9C0, 0xE8FB, 0xF9C1, 0xE8FE, 0xF9C2, 0xE9A7, 0xF9C3, 0xE9AC,
+	0xF9C4, 0xE9CC, 0xF9C5, 0xE9F7, 0xF9C6, 0xEAC1, 0xF9C7, 0xEAE5,
+	0xF9C8, 0xEAF4, 0xF9C9, 0xEAF7, 0xF9CA, 0xEAFC, 0xF9CB, 0xEAFE,
+	0xF9CC, 0xEBA4, 0xF9CD, 0xEBA7, 0xF9CE, 0xEBA9, 0xF9CF, 0xEBAA,
+	0xF9D0, 0xEBBA, 0xF9D1, 0xEBBB, 0xF9D2, 0xEBBD, 0xF9D3, 0xEBC1,
+	0xF9D4, 0xEBC2, 0xF9D5, 0xEBC6, 0xF9D6, 0xEBC7, 0xF9D7, 0xEBCC,
+	0xF9D8, 0xEBCF, 0xF9D9, 0xEBD0, 0xF9DA, 0xEBD1, 0xF9DB, 0xEBD2,
+	0xF9DC, 0xEBD8, 0xF9DD, 0xECA6, 0xF9DE, 0xECA7, 0xF9DF, 0xECAA,
+	0xF9E0, 0xECAF, 0xF9E1, 0xECB0, 0xF9E2, 0xECB1, 0xF9E3, 0xECB2,
+	0xF9E4, 0xECB5, 0xF9E5, 0xECB8, 0xF9E6, 0xECBA, 0xF9E7, 0xECC0,
+	0xF9E8, 0xECC1, 0xF9E9, 0xECC5, 0xF9EA, 0xECC6, 0xF9EB, 0xECC9,
+	0xF9EC, 0xECCA, 0xF9ED, 0xECD5, 0xF9EE, 0xECDD, 0xF9EF, 0xECDE,
+	0xF9F0, 0xECE1, 0xF9F1, 0xECE4, 0xF9F2, 0xECE7, 0xF9F3, 0xECE8,
+	0xF9F4, 0xECF7, 0xF9F5, 0xECF8, 0xF9F6, 0xECFA, 0xF9F7, 0xEDA1,
+	0xF9F8, 0xEDA2, 0xF9F9, 0xEDA3, 0xF9FA, 0xEDEE, 0xF9FB, 0xEEDB,
+	0xF9FC, 0xF2BD, 0xF9FD, 0xF2FA, 0xF9FE, 0xF3B1, 0xF9FF, 0xF4A7,
+	0xFA00, 0xF4EE, 0xFA01, 0xF6F4, 0xFA02, 0xF6F6, 0xFA03, 0xF7B8,
+	0xFA04, 0xF7C8, 0xFA05, 0xF7D3, 0xFA06, 0xF8DB, 0xFA07, 0xF8F0,
+	0xFA08, 0xFAA1, 0xFA09, 0xFAA2, 0xFA0A, 0xFAE6, 0xFA0B, 0xFCA9,
+	0xFF01, 0xA3A1, 0xFF02, 0xA3A2, 0xFF03, 0xA3A3, 0xFF04, 0xA3A4,
+	0xFF05, 0xA3A5, 0xFF06, 0xA3A6, 0xFF07, 0xA3A7, 0xFF08, 0xA3A8,
+	0xFF09, 0xA3A9, 0xFF0A, 0xA3AA, 0xFF0B, 0xA3AB, 0xFF0C, 0xA3AC,
+	0xFF0D, 0xA3AD, 0xFF0E, 0xA3AE, 0xFF0F, 0xA3AF, 0xFF10, 0xA3B0,
+	0xFF11, 0xA3B1, 0xFF12, 0xA3B2, 0xFF13, 0xA3B3, 0xFF14, 0xA3B4,
+	0xFF15, 0xA3B5, 0xFF16, 0xA3B6, 0xFF17, 0xA3B7, 0xFF18, 0xA3B8,
+	0xFF19, 0xA3B9, 0xFF1A, 0xA3BA, 0xFF1B, 0xA3BB, 0xFF1C, 0xA3BC,
+	0xFF1D, 0xA3BD, 0xFF1E, 0xA3BE, 0xFF1F, 0xA3BF, 0xFF20, 0xA3C0,
+	0xFF21, 0xA3C1, 0xFF22, 0xA3C2, 0xFF23, 0xA3C3, 0xFF24, 0xA3C4,
+	0xFF25, 0xA3C5, 0xFF26, 0xA3C6, 0xFF27, 0xA3C7, 0xFF28, 0xA3C8,
+	0xFF29, 0xA3C9, 0xFF2A, 0xA3CA, 0xFF2B, 0xA3CB, 0xFF2C, 0xA3CC,
+	0xFF2D, 0xA3CD, 0xFF2E, 0xA3CE, 0xFF2F, 0xA3CF, 0xFF30, 0xA3D0,
+	0xFF31, 0xA3D1, 0xFF32, 0xA3D2, 0xFF33, 0xA3D3, 0xFF34, 0xA3D4,
+	0xFF35, 0xA3D5, 0xFF36, 0xA3D6, 0xFF37, 0xA3D7, 0xFF38, 0xA3D8,
+	0xFF39, 0xA3D9, 0xFF3A, 0xA3DA, 0xFF3B, 0xA3DB, 0xFF3C, 0xA1AC,
+	0xFF3D, 0xA3DD, 0xFF3E, 0xA3DE, 0xFF3F, 0xA3DF, 0xFF40, 0xA3E0,
+	0xFF41, 0xA3E1, 0xFF42, 0xA3E2, 0xFF43, 0xA3E3, 0xFF44, 0xA3E4,
+	0xFF45, 0xA3E5, 0xFF46, 0xA3E6, 0xFF47, 0xA3E7, 0xFF48, 0xA3E8,
+	0xFF49, 0xA3E9, 0xFF4A, 0xA3EA, 0xFF4B, 0xA3EB, 0xFF4C, 0xA3EC,
+	0xFF4D, 0xA3ED, 0xFF4E, 0xA3EE, 0xFF4F, 0xA3EF, 0xFF50, 0xA3F0,
+	0xFF51, 0xA3F1, 0xFF52, 0xA3F2, 0xFF53, 0xA3F3, 0xFF54, 0xA3F4,
+	0xFF55, 0xA3F5, 0xFF56, 0xA3F6, 0xFF57, 0xA3F7, 0xFF58, 0xA3F8,
+	0xFF59, 0xA3F9, 0xFF5A, 0xA3FA, 0xFF5B, 0xA3FB, 0xFF5C, 0xA3FC,
+	0xFF5D, 0xA3FD, 0xFF5E, 0xA2A6, 0xFFE0, 0xA1CB, 0xFFE1, 0xA1CC,
+	0xFFE2, 0xA1FE, 0xFFE3, 0xA3FE, 0xFFE5, 0xA1CD, 0xFFE6, 0xA3DC,
+	0, 0
+};
+
+static
+const WCHAR oem2uni[] = {
+/*	OEM - Unicode,  OEM - Unicode,  OEM - Unicode,  OEM - Unicode */
+	0x8141, 0xAC02, 0x8142, 0xAC03, 0x8143, 0xAC05, 0x8144, 0xAC06,
+	0x8145, 0xAC0B, 0x8146, 0xAC0C, 0x8147, 0xAC0D, 0x8148, 0xAC0E,
+	0x8149, 0xAC0F, 0x814A, 0xAC18, 0x814B, 0xAC1E, 0x814C, 0xAC1F,
+	0x814D, 0xAC21, 0x814E, 0xAC22, 0x814F, 0xAC23, 0x8150, 0xAC25,
+	0x8151, 0xAC26, 0x8152, 0xAC27, 0x8153, 0xAC28, 0x8154, 0xAC29,
+	0x8155, 0xAC2A, 0x8156, 0xAC2B, 0x8157, 0xAC2E, 0x8158, 0xAC32,
+	0x8159, 0xAC33, 0x815A, 0xAC34, 0x8161, 0xAC35, 0x8162, 0xAC36,
+	0x8163, 0xAC37, 0x8164, 0xAC3A, 0x8165, 0xAC3B, 0x8166, 0xAC3D,
+	0x8167, 0xAC3E, 0x8168, 0xAC3F, 0x8169, 0xAC41, 0x816A, 0xAC42,
+	0x816B, 0xAC43, 0x816C, 0xAC44, 0x816D, 0xAC45, 0x816E, 0xAC46,
+	0x816F, 0xAC47, 0x8170, 0xAC48, 0x8171, 0xAC49, 0x8172, 0xAC4A,
+	0x8173, 0xAC4C, 0x8174, 0xAC4E, 0x8175, 0xAC4F, 0x8176, 0xAC50,
+	0x8177, 0xAC51, 0x8178, 0xAC52, 0x8179, 0xAC53, 0x817A, 0xAC55,
+	0x8181, 0xAC56, 0x8182, 0xAC57, 0x8183, 0xAC59, 0x8184, 0xAC5A,
+	0x8185, 0xAC5B, 0x8186, 0xAC5D, 0x8187, 0xAC5E, 0x8188, 0xAC5F,
+	0x8189, 0xAC60, 0x818A, 0xAC61, 0x818B, 0xAC62, 0x818C, 0xAC63,
+	0x818D, 0xAC64, 0x818E, 0xAC65, 0x818F, 0xAC66, 0x8190, 0xAC67,
+	0x8191, 0xAC68, 0x8192, 0xAC69, 0x8193, 0xAC6A, 0x8194, 0xAC6B,
+	0x8195, 0xAC6C, 0x8196, 0xAC6D, 0x8197, 0xAC6E, 0x8198, 0xAC6F,
+	0x8199, 0xAC72, 0x819A, 0xAC73, 0x819B, 0xAC75, 0x819C, 0xAC76,
+	0x819D, 0xAC79, 0x819E, 0xAC7B, 0x819F, 0xAC7C, 0x81A0, 0xAC7D,
+	0x81A1, 0xAC7E, 0x81A2, 0xAC7F, 0x81A3, 0xAC82, 0x81A4, 0xAC87,
+	0x81A5, 0xAC88, 0x81A6, 0xAC8D, 0x81A7, 0xAC8E, 0x81A8, 0xAC8F,
+	0x81A9, 0xAC91, 0x81AA, 0xAC92, 0x81AB, 0xAC93, 0x81AC, 0xAC95,
+	0x81AD, 0xAC96, 0x81AE, 0xAC97, 0x81AF, 0xAC98, 0x81B0, 0xAC99,
+	0x81B1, 0xAC9A, 0x81B2, 0xAC9B, 0x81B3, 0xAC9E, 0x81B4, 0xACA2,
+	0x81B5, 0xACA3, 0x81B6, 0xACA4, 0x81B7, 0xACA5, 0x81B8, 0xACA6,
+	0x81B9, 0xACA7, 0x81BA, 0xACAB, 0x81BB, 0xACAD, 0x81BC, 0xACAE,
+	0x81BD, 0xACB1, 0x81BE, 0xACB2, 0x81BF, 0xACB3, 0x81C0, 0xACB4,
+	0x81C1, 0xACB5, 0x81C2, 0xACB6, 0x81C3, 0xACB7, 0x81C4, 0xACBA,
+	0x81C5, 0xACBE, 0x81C6, 0xACBF, 0x81C7, 0xACC0, 0x81C8, 0xACC2,
+	0x81C9, 0xACC3, 0x81CA, 0xACC5, 0x81CB, 0xACC6, 0x81CC, 0xACC7,
+	0x81CD, 0xACC9, 0x81CE, 0xACCA, 0x81CF, 0xACCB, 0x81D0, 0xACCD,
+	0x81D1, 0xACCE, 0x81D2, 0xACCF, 0x81D3, 0xACD0, 0x81D4, 0xACD1,
+	0x81D5, 0xACD2, 0x81D6, 0xACD3, 0x81D7, 0xACD4, 0x81D8, 0xACD6,
+	0x81D9, 0xACD8, 0x81DA, 0xACD9, 0x81DB, 0xACDA, 0x81DC, 0xACDB,
+	0x81DD, 0xACDC, 0x81DE, 0xACDD, 0x81DF, 0xACDE, 0x81E0, 0xACDF,
+	0x81E1, 0xACE2, 0x81E2, 0xACE3, 0x81E3, 0xACE5, 0x81E4, 0xACE6,
+	0x81E5, 0xACE9, 0x81E6, 0xACEB, 0x81E7, 0xACED, 0x81E8, 0xACEE,
+	0x81E9, 0xACF2, 0x81EA, 0xACF4, 0x81EB, 0xACF7, 0x81EC, 0xACF8,
+	0x81ED, 0xACF9, 0x81EE, 0xACFA, 0x81EF, 0xACFB, 0x81F0, 0xACFE,
+	0x81F1, 0xACFF, 0x81F2, 0xAD01, 0x81F3, 0xAD02, 0x81F4, 0xAD03,
+	0x81F5, 0xAD05, 0x81F6, 0xAD07, 0x81F7, 0xAD08, 0x81F8, 0xAD09,
+	0x81F9, 0xAD0A, 0x81FA, 0xAD0B, 0x81FB, 0xAD0E, 0x81FC, 0xAD10,
+	0x81FD, 0xAD12, 0x81FE, 0xAD13, 0x8241, 0xAD14, 0x8242, 0xAD15,
+	0x8243, 0xAD16, 0x8244, 0xAD17, 0x8245, 0xAD19, 0x8246, 0xAD1A,
+	0x8247, 0xAD1B, 0x8248, 0xAD1D, 0x8249, 0xAD1E, 0x824A, 0xAD1F,
+	0x824B, 0xAD21, 0x824C, 0xAD22, 0x824D, 0xAD23, 0x824E, 0xAD24,
+	0x824F, 0xAD25, 0x8250, 0xAD26, 0x8251, 0xAD27, 0x8252, 0xAD28,
+	0x8253, 0xAD2A, 0x8254, 0xAD2B, 0x8255, 0xAD2E, 0x8256, 0xAD2F,
+	0x8257, 0xAD30, 0x8258, 0xAD31, 0x8259, 0xAD32, 0x825A, 0xAD33,
+	0x8261, 0xAD36, 0x8262, 0xAD37, 0x8263, 0xAD39, 0x8264, 0xAD3A,
+	0x8265, 0xAD3B, 0x8266, 0xAD3D, 0x8267, 0xAD3E, 0x8268, 0xAD3F,
+	0x8269, 0xAD40, 0x826A, 0xAD41, 0x826B, 0xAD42, 0x826C, 0xAD43,
+	0x826D, 0xAD46, 0x826E, 0xAD48, 0x826F, 0xAD4A, 0x8270, 0xAD4B,
+	0x8271, 0xAD4C, 0x8272, 0xAD4D, 0x8273, 0xAD4E, 0x8274, 0xAD4F,
+	0x8275, 0xAD51, 0x8276, 0xAD52, 0x8277, 0xAD53, 0x8278, 0xAD55,
+	0x8279, 0xAD56, 0x827A, 0xAD57, 0x8281, 0xAD59, 0x8282, 0xAD5A,
+	0x8283, 0xAD5B, 0x8284, 0xAD5C, 0x8285, 0xAD5D, 0x8286, 0xAD5E,
+	0x8287, 0xAD5F, 0x8288, 0xAD60, 0x8289, 0xAD62, 0x828A, 0xAD64,
+	0x828B, 0xAD65, 0x828C, 0xAD66, 0x828D, 0xAD67, 0x828E, 0xAD68,
+	0x828F, 0xAD69, 0x8290, 0xAD6A, 0x8291, 0xAD6B, 0x8292, 0xAD6E,
+	0x8293, 0xAD6F, 0x8294, 0xAD71, 0x8295, 0xAD72, 0x8296, 0xAD77,
+	0x8297, 0xAD78, 0x8298, 0xAD79, 0x8299, 0xAD7A, 0x829A, 0xAD7E,
+	0x829B, 0xAD80, 0x829C, 0xAD83, 0x829D, 0xAD84, 0x829E, 0xAD85,
+	0x829F, 0xAD86, 0x82A0, 0xAD87, 0x82A1, 0xAD8A, 0x82A2, 0xAD8B,
+	0x82A3, 0xAD8D, 0x82A4, 0xAD8E, 0x82A5, 0xAD8F, 0x82A6, 0xAD91,
+	0x82A7, 0xAD92, 0x82A8, 0xAD93, 0x82A9, 0xAD94, 0x82AA, 0xAD95,
+	0x82AB, 0xAD96, 0x82AC, 0xAD97, 0x82AD, 0xAD98, 0x82AE, 0xAD99,
+	0x82AF, 0xAD9A, 0x82B0, 0xAD9B, 0x82B1, 0xAD9E, 0x82B2, 0xAD9F,
+	0x82B3, 0xADA0, 0x82B4, 0xADA1, 0x82B5, 0xADA2, 0x82B6, 0xADA3,
+	0x82B7, 0xADA5, 0x82B8, 0xADA6, 0x82B9, 0xADA7, 0x82BA, 0xADA8,
+	0x82BB, 0xADA9, 0x82BC, 0xADAA, 0x82BD, 0xADAB, 0x82BE, 0xADAC,
+	0x82BF, 0xADAD, 0x82C0, 0xADAE, 0x82C1, 0xADAF, 0x82C2, 0xADB0,
+	0x82C3, 0xADB1, 0x82C4, 0xADB2, 0x82C5, 0xADB3, 0x82C6, 0xADB4,
+	0x82C7, 0xADB5, 0x82C8, 0xADB6, 0x82C9, 0xADB8, 0x82CA, 0xADB9,
+	0x82CB, 0xADBA, 0x82CC, 0xADBB, 0x82CD, 0xADBC, 0x82CE, 0xADBD,
+	0x82CF, 0xADBE, 0x82D0, 0xADBF, 0x82D1, 0xADC2, 0x82D2, 0xADC3,
+	0x82D3, 0xADC5, 0x82D4, 0xADC6, 0x82D5, 0xADC7, 0x82D6, 0xADC9,
+	0x82D7, 0xADCA, 0x82D8, 0xADCB, 0x82D9, 0xADCC, 0x82DA, 0xADCD,
+	0x82DB, 0xADCE, 0x82DC, 0xADCF, 0x82DD, 0xADD2, 0x82DE, 0xADD4,
+	0x82DF, 0xADD5, 0x82E0, 0xADD6, 0x82E1, 0xADD7, 0x82E2, 0xADD8,
+	0x82E3, 0xADD9, 0x82E4, 0xADDA, 0x82E5, 0xADDB, 0x82E6, 0xADDD,
+	0x82E7, 0xADDE, 0x82E8, 0xADDF, 0x82E9, 0xADE1, 0x82EA, 0xADE2,
+	0x82EB, 0xADE3, 0x82EC, 0xADE5, 0x82ED, 0xADE6, 0x82EE, 0xADE7,
+	0x82EF, 0xADE8, 0x82F0, 0xADE9, 0x82F1, 0xADEA, 0x82F2, 0xADEB,
+	0x82F3, 0xADEC, 0x82F4, 0xADED, 0x82F5, 0xADEE, 0x82F6, 0xADEF,
+	0x82F7, 0xADF0, 0x82F8, 0xADF1, 0x82F9, 0xADF2, 0x82FA, 0xADF3,
+	0x82FB, 0xADF4, 0x82FC, 0xADF5, 0x82FD, 0xADF6, 0x82FE, 0xADF7,
+	0x8341, 0xADFA, 0x8342, 0xADFB, 0x8343, 0xADFD, 0x8344, 0xADFE,
+	0x8345, 0xAE02, 0x8346, 0xAE03, 0x8347, 0xAE04, 0x8348, 0xAE05,
+	0x8349, 0xAE06, 0x834A, 0xAE07, 0x834B, 0xAE0A, 0x834C, 0xAE0C,
+	0x834D, 0xAE0E, 0x834E, 0xAE0F, 0x834F, 0xAE10, 0x8350, 0xAE11,
+	0x8351, 0xAE12, 0x8352, 0xAE13, 0x8353, 0xAE15, 0x8354, 0xAE16,
+	0x8355, 0xAE17, 0x8356, 0xAE18, 0x8357, 0xAE19, 0x8358, 0xAE1A,
+	0x8359, 0xAE1B, 0x835A, 0xAE1C, 0x8361, 0xAE1D, 0x8362, 0xAE1E,
+	0x8363, 0xAE1F, 0x8364, 0xAE20, 0x8365, 0xAE21, 0x8366, 0xAE22,
+	0x8367, 0xAE23, 0x8368, 0xAE24, 0x8369, 0xAE25, 0x836A, 0xAE26,
+	0x836B, 0xAE27, 0x836C, 0xAE28, 0x836D, 0xAE29, 0x836E, 0xAE2A,
+	0x836F, 0xAE2B, 0x8370, 0xAE2C, 0x8371, 0xAE2D, 0x8372, 0xAE2E,
+	0x8373, 0xAE2F, 0x8374, 0xAE32, 0x8375, 0xAE33, 0x8376, 0xAE35,
+	0x8377, 0xAE36, 0x8378, 0xAE39, 0x8379, 0xAE3B, 0x837A, 0xAE3C,
+	0x8381, 0xAE3D, 0x8382, 0xAE3E, 0x8383, 0xAE3F, 0x8384, 0xAE42,
+	0x8385, 0xAE44, 0x8386, 0xAE47, 0x8387, 0xAE48, 0x8388, 0xAE49,
+	0x8389, 0xAE4B, 0x838A, 0xAE4F, 0x838B, 0xAE51, 0x838C, 0xAE52,
+	0x838D, 0xAE53, 0x838E, 0xAE55, 0x838F, 0xAE57, 0x8390, 0xAE58,
+	0x8391, 0xAE59, 0x8392, 0xAE5A, 0x8393, 0xAE5B, 0x8394, 0xAE5E,
+	0x8395, 0xAE62, 0x8396, 0xAE63, 0x8397, 0xAE64, 0x8398, 0xAE66,
+	0x8399, 0xAE67, 0x839A, 0xAE6A, 0x839B, 0xAE6B, 0x839C, 0xAE6D,
+	0x839D, 0xAE6E, 0x839E, 0xAE6F, 0x839F, 0xAE71, 0x83A0, 0xAE72,
+	0x83A1, 0xAE73, 0x83A2, 0xAE74, 0x83A3, 0xAE75, 0x83A4, 0xAE76,
+	0x83A5, 0xAE77, 0x83A6, 0xAE7A, 0x83A7, 0xAE7E, 0x83A8, 0xAE7F,
+	0x83A9, 0xAE80, 0x83AA, 0xAE81, 0x83AB, 0xAE82, 0x83AC, 0xAE83,
+	0x83AD, 0xAE86, 0x83AE, 0xAE87, 0x83AF, 0xAE88, 0x83B0, 0xAE89,
+	0x83B1, 0xAE8A, 0x83B2, 0xAE8B, 0x83B3, 0xAE8D, 0x83B4, 0xAE8E,
+	0x83B5, 0xAE8F, 0x83B6, 0xAE90, 0x83B7, 0xAE91, 0x83B8, 0xAE92,
+	0x83B9, 0xAE93, 0x83BA, 0xAE94, 0x83BB, 0xAE95, 0x83BC, 0xAE96,
+	0x83BD, 0xAE97, 0x83BE, 0xAE98, 0x83BF, 0xAE99, 0x83C0, 0xAE9A,
+	0x83C1, 0xAE9B, 0x83C2, 0xAE9C, 0x83C3, 0xAE9D, 0x83C4, 0xAE9E,
+	0x83C5, 0xAE9F, 0x83C6, 0xAEA0, 0x83C7, 0xAEA1, 0x83C8, 0xAEA2,
+	0x83C9, 0xAEA3, 0x83CA, 0xAEA4, 0x83CB, 0xAEA5, 0x83CC, 0xAEA6,
+	0x83CD, 0xAEA7, 0x83CE, 0xAEA8, 0x83CF, 0xAEA9, 0x83D0, 0xAEAA,
+	0x83D1, 0xAEAB, 0x83D2, 0xAEAC, 0x83D3, 0xAEAD, 0x83D4, 0xAEAE,
+	0x83D5, 0xAEAF, 0x83D6, 0xAEB0, 0x83D7, 0xAEB1, 0x83D8, 0xAEB2,
+	0x83D9, 0xAEB3, 0x83DA, 0xAEB4, 0x83DB, 0xAEB5, 0x83DC, 0xAEB6,
+	0x83DD, 0xAEB7, 0x83DE, 0xAEB8, 0x83DF, 0xAEB9, 0x83E0, 0xAEBA,
+	0x83E1, 0xAEBB, 0x83E2, 0xAEBF, 0x83E3, 0xAEC1, 0x83E4, 0xAEC2,
+	0x83E5, 0xAEC3, 0x83E6, 0xAEC5, 0x83E7, 0xAEC6, 0x83E8, 0xAEC7,
+	0x83E9, 0xAEC8, 0x83EA, 0xAEC9, 0x83EB, 0xAECA, 0x83EC, 0xAECB,
+	0x83ED, 0xAECE, 0x83EE, 0xAED2, 0x83EF, 0xAED3, 0x83F0, 0xAED4,
+	0x83F1, 0xAED5, 0x83F2, 0xAED6, 0x83F3, 0xAED7, 0x83F4, 0xAEDA,
+	0x83F5, 0xAEDB, 0x83F6, 0xAEDD, 0x83F7, 0xAEDE, 0x83F8, 0xAEDF,
+	0x83F9, 0xAEE0, 0x83FA, 0xAEE1, 0x83FB, 0xAEE2, 0x83FC, 0xAEE3,
+	0x83FD, 0xAEE4, 0x83FE, 0xAEE5, 0x8441, 0xAEE6, 0x8442, 0xAEE7,
+	0x8443, 0xAEE9, 0x8444, 0xAEEA, 0x8445, 0xAEEC, 0x8446, 0xAEEE,
+	0x8447, 0xAEEF, 0x8448, 0xAEF0, 0x8449, 0xAEF1, 0x844A, 0xAEF2,
+	0x844B, 0xAEF3, 0x844C, 0xAEF5, 0x844D, 0xAEF6, 0x844E, 0xAEF7,
+	0x844F, 0xAEF9, 0x8450, 0xAEFA, 0x8451, 0xAEFB, 0x8452, 0xAEFD,
+	0x8453, 0xAEFE, 0x8454, 0xAEFF, 0x8455, 0xAF00, 0x8456, 0xAF01,
+	0x8457, 0xAF02, 0x8458, 0xAF03, 0x8459, 0xAF04, 0x845A, 0xAF05,
+	0x8461, 0xAF06, 0x8462, 0xAF09, 0x8463, 0xAF0A, 0x8464, 0xAF0B,
+	0x8465, 0xAF0C, 0x8466, 0xAF0E, 0x8467, 0xAF0F, 0x8468, 0xAF11,
+	0x8469, 0xAF12, 0x846A, 0xAF13, 0x846B, 0xAF14, 0x846C, 0xAF15,
+	0x846D, 0xAF16, 0x846E, 0xAF17, 0x846F, 0xAF18, 0x8470, 0xAF19,
+	0x8471, 0xAF1A, 0x8472, 0xAF1B, 0x8473, 0xAF1C, 0x8474, 0xAF1D,
+	0x8475, 0xAF1E, 0x8476, 0xAF1F, 0x8477, 0xAF20, 0x8478, 0xAF21,
+	0x8479, 0xAF22, 0x847A, 0xAF23, 0x8481, 0xAF24, 0x8482, 0xAF25,
+	0x8483, 0xAF26, 0x8484, 0xAF27, 0x8485, 0xAF28, 0x8486, 0xAF29,
+	0x8487, 0xAF2A, 0x8488, 0xAF2B, 0x8489, 0xAF2E, 0x848A, 0xAF2F,
+	0x848B, 0xAF31, 0x848C, 0xAF33, 0x848D, 0xAF35, 0x848E, 0xAF36,
+	0x848F, 0xAF37, 0x8490, 0xAF38, 0x8491, 0xAF39, 0x8492, 0xAF3A,
+	0x8493, 0xAF3B, 0x8494, 0xAF3E, 0x8495, 0xAF40, 0x8496, 0xAF44,
+	0x8497, 0xAF45, 0x8498, 0xAF46, 0x8499, 0xAF47, 0x849A, 0xAF4A,
+	0x849B, 0xAF4B, 0x849C, 0xAF4C, 0x849D, 0xAF4D, 0x849E, 0xAF4E,
+	0x849F, 0xAF4F, 0x84A0, 0xAF51, 0x84A1, 0xAF52, 0x84A2, 0xAF53,
+	0x84A3, 0xAF54, 0x84A4, 0xAF55, 0x84A5, 0xAF56, 0x84A6, 0xAF57,
+	0x84A7, 0xAF58, 0x84A8, 0xAF59, 0x84A9, 0xAF5A, 0x84AA, 0xAF5B,
+	0x84AB, 0xAF5E, 0x84AC, 0xAF5F, 0x84AD, 0xAF60, 0x84AE, 0xAF61,
+	0x84AF, 0xAF62, 0x84B0, 0xAF63, 0x84B1, 0xAF66, 0x84B2, 0xAF67,
+	0x84B3, 0xAF68, 0x84B4, 0xAF69, 0x84B5, 0xAF6A, 0x84B6, 0xAF6B,
+	0x84B7, 0xAF6C, 0x84B8, 0xAF6D, 0x84B9, 0xAF6E, 0x84BA, 0xAF6F,
+	0x84BB, 0xAF70, 0x84BC, 0xAF71, 0x84BD, 0xAF72, 0x84BE, 0xAF73,
+	0x84BF, 0xAF74, 0x84C0, 0xAF75, 0x84C1, 0xAF76, 0x84C2, 0xAF77,
+	0x84C3, 0xAF78, 0x84C4, 0xAF7A, 0x84C5, 0xAF7B, 0x84C6, 0xAF7C,
+	0x84C7, 0xAF7D, 0x84C8, 0xAF7E, 0x84C9, 0xAF7F, 0x84CA, 0xAF81,
+	0x84CB, 0xAF82, 0x84CC, 0xAF83, 0x84CD, 0xAF85, 0x84CE, 0xAF86,
+	0x84CF, 0xAF87, 0x84D0, 0xAF89, 0x84D1, 0xAF8A, 0x84D2, 0xAF8B,
+	0x84D3, 0xAF8C, 0x84D4, 0xAF8D, 0x84D5, 0xAF8E, 0x84D6, 0xAF8F,
+	0x84D7, 0xAF92, 0x84D8, 0xAF93, 0x84D9, 0xAF94, 0x84DA, 0xAF96,
+	0x84DB, 0xAF97, 0x84DC, 0xAF98, 0x84DD, 0xAF99, 0x84DE, 0xAF9A,
+	0x84DF, 0xAF9B, 0x84E0, 0xAF9D, 0x84E1, 0xAF9E, 0x84E2, 0xAF9F,
+	0x84E3, 0xAFA0, 0x84E4, 0xAFA1, 0x84E5, 0xAFA2, 0x84E6, 0xAFA3,
+	0x84E7, 0xAFA4, 0x84E8, 0xAFA5, 0x84E9, 0xAFA6, 0x84EA, 0xAFA7,
+	0x84EB, 0xAFA8, 0x84EC, 0xAFA9, 0x84ED, 0xAFAA, 0x84EE, 0xAFAB,
+	0x84EF, 0xAFAC, 0x84F0, 0xAFAD, 0x84F1, 0xAFAE, 0x84F2, 0xAFAF,
+	0x84F3, 0xAFB0, 0x84F4, 0xAFB1, 0x84F5, 0xAFB2, 0x84F6, 0xAFB3,
+	0x84F7, 0xAFB4, 0x84F8, 0xAFB5, 0x84F9, 0xAFB6, 0x84FA, 0xAFB7,
+	0x84FB, 0xAFBA, 0x84FC, 0xAFBB, 0x84FD, 0xAFBD, 0x84FE, 0xAFBE,
+	0x8541, 0xAFBF, 0x8542, 0xAFC1, 0x8543, 0xAFC2, 0x8544, 0xAFC3,
+	0x8545, 0xAFC4, 0x8546, 0xAFC5, 0x8547, 0xAFC6, 0x8548, 0xAFCA,
+	0x8549, 0xAFCC, 0x854A, 0xAFCF, 0x854B, 0xAFD0, 0x854C, 0xAFD1,
+	0x854D, 0xAFD2, 0x854E, 0xAFD3, 0x854F, 0xAFD5, 0x8550, 0xAFD6,
+	0x8551, 0xAFD7, 0x8552, 0xAFD8, 0x8553, 0xAFD9, 0x8554, 0xAFDA,
+	0x8555, 0xAFDB, 0x8556, 0xAFDD, 0x8557, 0xAFDE, 0x8558, 0xAFDF,
+	0x8559, 0xAFE0, 0x855A, 0xAFE1, 0x8561, 0xAFE2, 0x8562, 0xAFE3,
+	0x8563, 0xAFE4, 0x8564, 0xAFE5, 0x8565, 0xAFE6, 0x8566, 0xAFE7,
+	0x8567, 0xAFEA, 0x8568, 0xAFEB, 0x8569, 0xAFEC, 0x856A, 0xAFED,
+	0x856B, 0xAFEE, 0x856C, 0xAFEF, 0x856D, 0xAFF2, 0x856E, 0xAFF3,
+	0x856F, 0xAFF5, 0x8570, 0xAFF6, 0x8571, 0xAFF7, 0x8572, 0xAFF9,
+	0x8573, 0xAFFA, 0x8574, 0xAFFB, 0x8575, 0xAFFC, 0x8576, 0xAFFD,
+	0x8577, 0xAFFE, 0x8578, 0xAFFF, 0x8579, 0xB002, 0x857A, 0xB003,
+	0x8581, 0xB005, 0x8582, 0xB006, 0x8583, 0xB007, 0x8584, 0xB008,
+	0x8585, 0xB009, 0x8586, 0xB00A, 0x8587, 0xB00B, 0x8588, 0xB00D,
+	0x8589, 0xB00E, 0x858A, 0xB00F, 0x858B, 0xB011, 0x858C, 0xB012,
+	0x858D, 0xB013, 0x858E, 0xB015, 0x858F, 0xB016, 0x8590, 0xB017,
+	0x8591, 0xB018, 0x8592, 0xB019, 0x8593, 0xB01A, 0x8594, 0xB01B,
+	0x8595, 0xB01E, 0x8596, 0xB01F, 0x8597, 0xB020, 0x8598, 0xB021,
+	0x8599, 0xB022, 0x859A, 0xB023, 0x859B, 0xB024, 0x859C, 0xB025,
+	0x859D, 0xB026, 0x859E, 0xB027, 0x859F, 0xB029, 0x85A0, 0xB02A,
+	0x85A1, 0xB02B, 0x85A2, 0xB02C, 0x85A3, 0xB02D, 0x85A4, 0xB02E,
+	0x85A5, 0xB02F, 0x85A6, 0xB030, 0x85A7, 0xB031, 0x85A8, 0xB032,
+	0x85A9, 0xB033, 0x85AA, 0xB034, 0x85AB, 0xB035, 0x85AC, 0xB036,
+	0x85AD, 0xB037, 0x85AE, 0xB038, 0x85AF, 0xB039, 0x85B0, 0xB03A,
+	0x85B1, 0xB03B, 0x85B2, 0xB03C, 0x85B3, 0xB03D, 0x85B4, 0xB03E,
+	0x85B5, 0xB03F, 0x85B6, 0xB040, 0x85B7, 0xB041, 0x85B8, 0xB042,
+	0x85B9, 0xB043, 0x85BA, 0xB046, 0x85BB, 0xB047, 0x85BC, 0xB049,
+	0x85BD, 0xB04B, 0x85BE, 0xB04D, 0x85BF, 0xB04F, 0x85C0, 0xB050,
+	0x85C1, 0xB051, 0x85C2, 0xB052, 0x85C3, 0xB056, 0x85C4, 0xB058,
+	0x85C5, 0xB05A, 0x85C6, 0xB05B, 0x85C7, 0xB05C, 0x85C8, 0xB05E,
+	0x85C9, 0xB05F, 0x85CA, 0xB060, 0x85CB, 0xB061, 0x85CC, 0xB062,
+	0x85CD, 0xB063, 0x85CE, 0xB064, 0x85CF, 0xB065, 0x85D0, 0xB066,
+	0x85D1, 0xB067, 0x85D2, 0xB068, 0x85D3, 0xB069, 0x85D4, 0xB06A,
+	0x85D5, 0xB06B, 0x85D6, 0xB06C, 0x85D7, 0xB06D, 0x85D8, 0xB06E,
+	0x85D9, 0xB06F, 0x85DA, 0xB070, 0x85DB, 0xB071, 0x85DC, 0xB072,
+	0x85DD, 0xB073, 0x85DE, 0xB074, 0x85DF, 0xB075, 0x85E0, 0xB076,
+	0x85E1, 0xB077, 0x85E2, 0xB078, 0x85E3, 0xB079, 0x85E4, 0xB07A,
+	0x85E5, 0xB07B, 0x85E6, 0xB07E, 0x85E7, 0xB07F, 0x85E8, 0xB081,
+	0x85E9, 0xB082, 0x85EA, 0xB083, 0x85EB, 0xB085, 0x85EC, 0xB086,
+	0x85ED, 0xB087, 0x85EE, 0xB088, 0x85EF, 0xB089, 0x85F0, 0xB08A,
+	0x85F1, 0xB08B, 0x85F2, 0xB08E, 0x85F3, 0xB090, 0x85F4, 0xB092,
+	0x85F5, 0xB093, 0x85F6, 0xB094, 0x85F7, 0xB095, 0x85F8, 0xB096,
+	0x85F9, 0xB097, 0x85FA, 0xB09B, 0x85FB, 0xB09D, 0x85FC, 0xB09E,
+	0x85FD, 0xB0A3, 0x85FE, 0xB0A4, 0x8641, 0xB0A5, 0x8642, 0xB0A6,
+	0x8643, 0xB0A7, 0x8644, 0xB0AA, 0x8645, 0xB0B0, 0x8646, 0xB0B2,
+	0x8647, 0xB0B6, 0x8648, 0xB0B7, 0x8649, 0xB0B9, 0x864A, 0xB0BA,
+	0x864B, 0xB0BB, 0x864C, 0xB0BD, 0x864D, 0xB0BE, 0x864E, 0xB0BF,
+	0x864F, 0xB0C0, 0x8650, 0xB0C1, 0x8651, 0xB0C2, 0x8652, 0xB0C3,
+	0x8653, 0xB0C6, 0x8654, 0xB0CA, 0x8655, 0xB0CB, 0x8656, 0xB0CC,
+	0x8657, 0xB0CD, 0x8658, 0xB0CE, 0x8659, 0xB0CF, 0x865A, 0xB0D2,
+	0x8661, 0xB0D3, 0x8662, 0xB0D5, 0x8663, 0xB0D6, 0x8664, 0xB0D7,
+	0x8665, 0xB0D9, 0x8666, 0xB0DA, 0x8667, 0xB0DB, 0x8668, 0xB0DC,
+	0x8669, 0xB0DD, 0x866A, 0xB0DE, 0x866B, 0xB0DF, 0x866C, 0xB0E1,
+	0x866D, 0xB0E2, 0x866E, 0xB0E3, 0x866F, 0xB0E4, 0x8670, 0xB0E6,
+	0x8671, 0xB0E7, 0x8672, 0xB0E8, 0x8673, 0xB0E9, 0x8674, 0xB0EA,
+	0x8675, 0xB0EB, 0x8676, 0xB0EC, 0x8677, 0xB0ED, 0x8678, 0xB0EE,
+	0x8679, 0xB0EF, 0x867A, 0xB0F0, 0x8681, 0xB0F1, 0x8682, 0xB0F2,
+	0x8683, 0xB0F3, 0x8684, 0xB0F4, 0x8685, 0xB0F5, 0x8686, 0xB0F6,
+	0x8687, 0xB0F7, 0x8688, 0xB0F8, 0x8689, 0xB0F9, 0x868A, 0xB0FA,
+	0x868B, 0xB0FB, 0x868C, 0xB0FC, 0x868D, 0xB0FD, 0x868E, 0xB0FE,
+	0x868F, 0xB0FF, 0x8690, 0xB100, 0x8691, 0xB101, 0x8692, 0xB102,
+	0x8693, 0xB103, 0x8694, 0xB104, 0x8695, 0xB105, 0x8696, 0xB106,
+	0x8697, 0xB107, 0x8698, 0xB10A, 0x8699, 0xB10D, 0x869A, 0xB10E,
+	0x869B, 0xB10F, 0x869C, 0xB111, 0x869D, 0xB114, 0x869E, 0xB115,
+	0x869F, 0xB116, 0x86A0, 0xB117, 0x86A1, 0xB11A, 0x86A2, 0xB11E,
+	0x86A3, 0xB11F, 0x86A4, 0xB120, 0x86A5, 0xB121, 0x86A6, 0xB122,
+	0x86A7, 0xB126, 0x86A8, 0xB127, 0x86A9, 0xB129, 0x86AA, 0xB12A,
+	0x86AB, 0xB12B, 0x86AC, 0xB12D, 0x86AD, 0xB12E, 0x86AE, 0xB12F,
+	0x86AF, 0xB130, 0x86B0, 0xB131, 0x86B1, 0xB132, 0x86B2, 0xB133,
+	0x86B3, 0xB136, 0x86B4, 0xB13A, 0x86B5, 0xB13B, 0x86B6, 0xB13C,
+	0x86B7, 0xB13D, 0x86B8, 0xB13E, 0x86B9, 0xB13F, 0x86BA, 0xB142,
+	0x86BB, 0xB143, 0x86BC, 0xB145, 0x86BD, 0xB146, 0x86BE, 0xB147,
+	0x86BF, 0xB149, 0x86C0, 0xB14A, 0x86C1, 0xB14B, 0x86C2, 0xB14C,
+	0x86C3, 0xB14D, 0x86C4, 0xB14E, 0x86C5, 0xB14F, 0x86C6, 0xB152,
+	0x86C7, 0xB153, 0x86C8, 0xB156, 0x86C9, 0xB157, 0x86CA, 0xB159,
+	0x86CB, 0xB15A, 0x86CC, 0xB15B, 0x86CD, 0xB15D, 0x86CE, 0xB15E,
+	0x86CF, 0xB15F, 0x86D0, 0xB161, 0x86D1, 0xB162, 0x86D2, 0xB163,
+	0x86D3, 0xB164, 0x86D4, 0xB165, 0x86D5, 0xB166, 0x86D6, 0xB167,
+	0x86D7, 0xB168, 0x86D8, 0xB169, 0x86D9, 0xB16A, 0x86DA, 0xB16B,
+	0x86DB, 0xB16C, 0x86DC, 0xB16D, 0x86DD, 0xB16E, 0x86DE, 0xB16F,
+	0x86DF, 0xB170, 0x86E0, 0xB171, 0x86E1, 0xB172, 0x86E2, 0xB173,
+	0x86E3, 0xB174, 0x86E4, 0xB175, 0x86E5, 0xB176, 0x86E6, 0xB177,
+	0x86E7, 0xB17A, 0x86E8, 0xB17B, 0x86E9, 0xB17D, 0x86EA, 0xB17E,
+	0x86EB, 0xB17F, 0x86EC, 0xB181, 0x86ED, 0xB183, 0x86EE, 0xB184,
+	0x86EF, 0xB185, 0x86F0, 0xB186, 0x86F1, 0xB187, 0x86F2, 0xB18A,
+	0x86F3, 0xB18C, 0x86F4, 0xB18E, 0x86F5, 0xB18F, 0x86F6, 0xB190,
+	0x86F7, 0xB191, 0x86F8, 0xB195, 0x86F9, 0xB196, 0x86FA, 0xB197,
+	0x86FB, 0xB199, 0x86FC, 0xB19A, 0x86FD, 0xB19B, 0x86FE, 0xB19D,
+	0x8741, 0xB19E, 0x8742, 0xB19F, 0x8743, 0xB1A0, 0x8744, 0xB1A1,
+	0x8745, 0xB1A2, 0x8746, 0xB1A3, 0x8747, 0xB1A4, 0x8748, 0xB1A5,
+	0x8749, 0xB1A6, 0x874A, 0xB1A7, 0x874B, 0xB1A9, 0x874C, 0xB1AA,
+	0x874D, 0xB1AB, 0x874E, 0xB1AC, 0x874F, 0xB1AD, 0x8750, 0xB1AE,
+	0x8751, 0xB1AF, 0x8752, 0xB1B0, 0x8753, 0xB1B1, 0x8754, 0xB1B2,
+	0x8755, 0xB1B3, 0x8756, 0xB1B4, 0x8757, 0xB1B5, 0x8758, 0xB1B6,
+	0x8759, 0xB1B7, 0x875A, 0xB1B8, 0x8761, 0xB1B9, 0x8762, 0xB1BA,
+	0x8763, 0xB1BB, 0x8764, 0xB1BC, 0x8765, 0xB1BD, 0x8766, 0xB1BE,
+	0x8767, 0xB1BF, 0x8768, 0xB1C0, 0x8769, 0xB1C1, 0x876A, 0xB1C2,
+	0x876B, 0xB1C3, 0x876C, 0xB1C4, 0x876D, 0xB1C5, 0x876E, 0xB1C6,
+	0x876F, 0xB1C7, 0x8770, 0xB1C8, 0x8771, 0xB1C9, 0x8772, 0xB1CA,
+	0x8773, 0xB1CB, 0x8774, 0xB1CD, 0x8775, 0xB1CE, 0x8776, 0xB1CF,
+	0x8777, 0xB1D1, 0x8778, 0xB1D2, 0x8779, 0xB1D3, 0x877A, 0xB1D5,
+	0x8781, 0xB1D6, 0x8782, 0xB1D7, 0x8783, 0xB1D8, 0x8784, 0xB1D9,
+	0x8785, 0xB1DA, 0x8786, 0xB1DB, 0x8787, 0xB1DE, 0x8788, 0xB1E0,
+	0x8789, 0xB1E1, 0x878A, 0xB1E2, 0x878B, 0xB1E3, 0x878C, 0xB1E4,
+	0x878D, 0xB1E5, 0x878E, 0xB1E6, 0x878F, 0xB1E7, 0x8790, 0xB1EA,
+	0x8791, 0xB1EB, 0x8792, 0xB1ED, 0x8793, 0xB1EE, 0x8794, 0xB1EF,
+	0x8795, 0xB1F1, 0x8796, 0xB1F2, 0x8797, 0xB1F3, 0x8798, 0xB1F4,
+	0x8799, 0xB1F5, 0x879A, 0xB1F6, 0x879B, 0xB1F7, 0x879C, 0xB1F8,
+	0x879D, 0xB1FA, 0x879E, 0xB1FC, 0x879F, 0xB1FE, 0x87A0, 0xB1FF,
+	0x87A1, 0xB200, 0x87A2, 0xB201, 0x87A3, 0xB202, 0x87A4, 0xB203,
+	0x87A5, 0xB206, 0x87A6, 0xB207, 0x87A7, 0xB209, 0x87A8, 0xB20A,
+	0x87A9, 0xB20D, 0x87AA, 0xB20E, 0x87AB, 0xB20F, 0x87AC, 0xB210,
+	0x87AD, 0xB211, 0x87AE, 0xB212, 0x87AF, 0xB213, 0x87B0, 0xB216,
+	0x87B1, 0xB218, 0x87B2, 0xB21A, 0x87B3, 0xB21B, 0x87B4, 0xB21C,
+	0x87B5, 0xB21D, 0x87B6, 0xB21E, 0x87B7, 0xB21F, 0x87B8, 0xB221,
+	0x87B9, 0xB222, 0x87BA, 0xB223, 0x87BB, 0xB224, 0x87BC, 0xB225,
+	0x87BD, 0xB226, 0x87BE, 0xB227, 0x87BF, 0xB228, 0x87C0, 0xB229,
+	0x87C1, 0xB22A, 0x87C2, 0xB22B, 0x87C3, 0xB22C, 0x87C4, 0xB22D,
+	0x87C5, 0xB22E, 0x87C6, 0xB22F, 0x87C7, 0xB230, 0x87C8, 0xB231,
+	0x87C9, 0xB232, 0x87CA, 0xB233, 0x87CB, 0xB235, 0x87CC, 0xB236,
+	0x87CD, 0xB237, 0x87CE, 0xB238, 0x87CF, 0xB239, 0x87D0, 0xB23A,
+	0x87D1, 0xB23B, 0x87D2, 0xB23D, 0x87D3, 0xB23E, 0x87D4, 0xB23F,
+	0x87D5, 0xB240, 0x87D6, 0xB241, 0x87D7, 0xB242, 0x87D8, 0xB243,
+	0x87D9, 0xB244, 0x87DA, 0xB245, 0x87DB, 0xB246, 0x87DC, 0xB247,
+	0x87DD, 0xB248, 0x87DE, 0xB249, 0x87DF, 0xB24A, 0x87E0, 0xB24B,
+	0x87E1, 0xB24C, 0x87E2, 0xB24D, 0x87E3, 0xB24E, 0x87E4, 0xB24F,
+	0x87E5, 0xB250, 0x87E6, 0xB251, 0x87E7, 0xB252, 0x87E8, 0xB253,
+	0x87E9, 0xB254, 0x87EA, 0xB255, 0x87EB, 0xB256, 0x87EC, 0xB257,
+	0x87ED, 0xB259, 0x87EE, 0xB25A, 0x87EF, 0xB25B, 0x87F0, 0xB25D,
+	0x87F1, 0xB25E, 0x87F2, 0xB25F, 0x87F3, 0xB261, 0x87F4, 0xB262,
+	0x87F5, 0xB263, 0x87F6, 0xB264, 0x87F7, 0xB265, 0x87F8, 0xB266,
+	0x87F9, 0xB267, 0x87FA, 0xB26A, 0x87FB, 0xB26B, 0x87FC, 0xB26C,
+	0x87FD, 0xB26D, 0x87FE, 0xB26E, 0x8841, 0xB26F, 0x8842, 0xB270,
+	0x8843, 0xB271, 0x8844, 0xB272, 0x8845, 0xB273, 0x8846, 0xB276,
+	0x8847, 0xB277, 0x8848, 0xB278, 0x8849, 0xB279, 0x884A, 0xB27A,
+	0x884B, 0xB27B, 0x884C, 0xB27D, 0x884D, 0xB27E, 0x884E, 0xB27F,
+	0x884F, 0xB280, 0x8850, 0xB281, 0x8851, 0xB282, 0x8852, 0xB283,
+	0x8853, 0xB286, 0x8854, 0xB287, 0x8855, 0xB288, 0x8856, 0xB28A,
+	0x8857, 0xB28B, 0x8858, 0xB28C, 0x8859, 0xB28D, 0x885A, 0xB28E,
+	0x8861, 0xB28F, 0x8862, 0xB292, 0x8863, 0xB293, 0x8864, 0xB295,
+	0x8865, 0xB296, 0x8866, 0xB297, 0x8867, 0xB29B, 0x8868, 0xB29C,
+	0x8869, 0xB29D, 0x886A, 0xB29E, 0x886B, 0xB29F, 0x886C, 0xB2A2,
+	0x886D, 0xB2A4, 0x886E, 0xB2A7, 0x886F, 0xB2A8, 0x8870, 0xB2A9,
+	0x8871, 0xB2AB, 0x8872, 0xB2AD, 0x8873, 0xB2AE, 0x8874, 0xB2AF,
+	0x8875, 0xB2B1, 0x8876, 0xB2B2, 0x8877, 0xB2B3, 0x8878, 0xB2B5,
+	0x8879, 0xB2B6, 0x887A, 0xB2B7, 0x8881, 0xB2B8, 0x8882, 0xB2B9,
+	0x8883, 0xB2BA, 0x8884, 0xB2BB, 0x8885, 0xB2BC, 0x8886, 0xB2BD,
+	0x8887, 0xB2BE, 0x8888, 0xB2BF, 0x8889, 0xB2C0, 0x888A, 0xB2C1,
+	0x888B, 0xB2C2, 0x888C, 0xB2C3, 0x888D, 0xB2C4, 0x888E, 0xB2C5,
+	0x888F, 0xB2C6, 0x8890, 0xB2C7, 0x8891, 0xB2CA, 0x8892, 0xB2CB,
+	0x8893, 0xB2CD, 0x8894, 0xB2CE, 0x8895, 0xB2CF, 0x8896, 0xB2D1,
+	0x8897, 0xB2D3, 0x8898, 0xB2D4, 0x8899, 0xB2D5, 0x889A, 0xB2D6,
+	0x889B, 0xB2D7, 0x889C, 0xB2DA, 0x889D, 0xB2DC, 0x889E, 0xB2DE,
+	0x889F, 0xB2DF, 0x88A0, 0xB2E0, 0x88A1, 0xB2E1, 0x88A2, 0xB2E3,
+	0x88A3, 0xB2E7, 0x88A4, 0xB2E9, 0x88A5, 0xB2EA, 0x88A6, 0xB2F0,
+	0x88A7, 0xB2F1, 0x88A8, 0xB2F2, 0x88A9, 0xB2F6, 0x88AA, 0xB2FC,
+	0x88AB, 0xB2FD, 0x88AC, 0xB2FE, 0x88AD, 0xB302, 0x88AE, 0xB303,
+	0x88AF, 0xB305, 0x88B0, 0xB306, 0x88B1, 0xB307, 0x88B2, 0xB309,
+	0x88B3, 0xB30A, 0x88B4, 0xB30B, 0x88B5, 0xB30C, 0x88B6, 0xB30D,
+	0x88B7, 0xB30E, 0x88B8, 0xB30F, 0x88B9, 0xB312, 0x88BA, 0xB316,
+	0x88BB, 0xB317, 0x88BC, 0xB318, 0x88BD, 0xB319, 0x88BE, 0xB31A,
+	0x88BF, 0xB31B, 0x88C0, 0xB31D, 0x88C1, 0xB31E, 0x88C2, 0xB31F,
+	0x88C3, 0xB320, 0x88C4, 0xB321, 0x88C5, 0xB322, 0x88C6, 0xB323,
+	0x88C7, 0xB324, 0x88C8, 0xB325, 0x88C9, 0xB326, 0x88CA, 0xB327,
+	0x88CB, 0xB328, 0x88CC, 0xB329, 0x88CD, 0xB32A, 0x88CE, 0xB32B,
+	0x88CF, 0xB32C, 0x88D0, 0xB32D, 0x88D1, 0xB32E, 0x88D2, 0xB32F,
+	0x88D3, 0xB330, 0x88D4, 0xB331, 0x88D5, 0xB332, 0x88D6, 0xB333,
+	0x88D7, 0xB334, 0x88D8, 0xB335, 0x88D9, 0xB336, 0x88DA, 0xB337,
+	0x88DB, 0xB338, 0x88DC, 0xB339, 0x88DD, 0xB33A, 0x88DE, 0xB33B,
+	0x88DF, 0xB33C, 0x88E0, 0xB33D, 0x88E1, 0xB33E, 0x88E2, 0xB33F,
+	0x88E3, 0xB340, 0x88E4, 0xB341, 0x88E5, 0xB342, 0x88E6, 0xB343,
+	0x88E7, 0xB344, 0x88E8, 0xB345, 0x88E9, 0xB346, 0x88EA, 0xB347,
+	0x88EB, 0xB348, 0x88EC, 0xB349, 0x88ED, 0xB34A, 0x88EE, 0xB34B,
+	0x88EF, 0xB34C, 0x88F0, 0xB34D, 0x88F1, 0xB34E, 0x88F2, 0xB34F,
+	0x88F3, 0xB350, 0x88F4, 0xB351, 0x88F5, 0xB352, 0x88F6, 0xB353,
+	0x88F7, 0xB357, 0x88F8, 0xB359, 0x88F9, 0xB35A, 0x88FA, 0xB35D,
+	0x88FB, 0xB360, 0x88FC, 0xB361, 0x88FD, 0xB362, 0x88FE, 0xB363,
+	0x8941, 0xB366, 0x8942, 0xB368, 0x8943, 0xB36A, 0x8944, 0xB36C,
+	0x8945, 0xB36D, 0x8946, 0xB36F, 0x8947, 0xB372, 0x8948, 0xB373,
+	0x8949, 0xB375, 0x894A, 0xB376, 0x894B, 0xB377, 0x894C, 0xB379,
+	0x894D, 0xB37A, 0x894E, 0xB37B, 0x894F, 0xB37C, 0x8950, 0xB37D,
+	0x8951, 0xB37E, 0x8952, 0xB37F, 0x8953, 0xB382, 0x8954, 0xB386,
+	0x8955, 0xB387, 0x8956, 0xB388, 0x8957, 0xB389, 0x8958, 0xB38A,
+	0x8959, 0xB38B, 0x895A, 0xB38D, 0x8961, 0xB38E, 0x8962, 0xB38F,
+	0x8963, 0xB391, 0x8964, 0xB392, 0x8965, 0xB393, 0x8966, 0xB395,
+	0x8967, 0xB396, 0x8968, 0xB397, 0x8969, 0xB398, 0x896A, 0xB399,
+	0x896B, 0xB39A, 0x896C, 0xB39B, 0x896D, 0xB39C, 0x896E, 0xB39D,
+	0x896F, 0xB39E, 0x8970, 0xB39F, 0x8971, 0xB3A2, 0x8972, 0xB3A3,
+	0x8973, 0xB3A4, 0x8974, 0xB3A5, 0x8975, 0xB3A6, 0x8976, 0xB3A7,
+	0x8977, 0xB3A9, 0x8978, 0xB3AA, 0x8979, 0xB3AB, 0x897A, 0xB3AD,
+	0x8981, 0xB3AE, 0x8982, 0xB3AF, 0x8983, 0xB3B0, 0x8984, 0xB3B1,
+	0x8985, 0xB3B2, 0x8986, 0xB3B3, 0x8987, 0xB3B4, 0x8988, 0xB3B5,
+	0x8989, 0xB3B6, 0x898A, 0xB3B7, 0x898B, 0xB3B8, 0x898C, 0xB3B9,
+	0x898D, 0xB3BA, 0x898E, 0xB3BB, 0x898F, 0xB3BC, 0x8990, 0xB3BD,
+	0x8991, 0xB3BE, 0x8992, 0xB3BF, 0x8993, 0xB3C0, 0x8994, 0xB3C1,
+	0x8995, 0xB3C2, 0x8996, 0xB3C3, 0x8997, 0xB3C6, 0x8998, 0xB3C7,
+	0x8999, 0xB3C9, 0x899A, 0xB3CA, 0x899B, 0xB3CD, 0x899C, 0xB3CF,
+	0x899D, 0xB3D1, 0x899E, 0xB3D2, 0x899F, 0xB3D3, 0x89A0, 0xB3D6,
+	0x89A1, 0xB3D8, 0x89A2, 0xB3DA, 0x89A3, 0xB3DC, 0x89A4, 0xB3DE,
+	0x89A5, 0xB3DF, 0x89A6, 0xB3E1, 0x89A7, 0xB3E2, 0x89A8, 0xB3E3,
+	0x89A9, 0xB3E5, 0x89AA, 0xB3E6, 0x89AB, 0xB3E7, 0x89AC, 0xB3E9,
+	0x89AD, 0xB3EA, 0x89AE, 0xB3EB, 0x89AF, 0xB3EC, 0x89B0, 0xB3ED,
+	0x89B1, 0xB3EE, 0x89B2, 0xB3EF, 0x89B3, 0xB3F0, 0x89B4, 0xB3F1,
+	0x89B5, 0xB3F2, 0x89B6, 0xB3F3, 0x89B7, 0xB3F4, 0x89B8, 0xB3F5,
+	0x89B9, 0xB3F6, 0x89BA, 0xB3F7, 0x89BB, 0xB3F8, 0x89BC, 0xB3F9,
+	0x89BD, 0xB3FA, 0x89BE, 0xB3FB, 0x89BF, 0xB3FD, 0x89C0, 0xB3FE,
+	0x89C1, 0xB3FF, 0x89C2, 0xB400, 0x89C3, 0xB401, 0x89C4, 0xB402,
+	0x89C5, 0xB403, 0x89C6, 0xB404, 0x89C7, 0xB405, 0x89C8, 0xB406,
+	0x89C9, 0xB407, 0x89CA, 0xB408, 0x89CB, 0xB409, 0x89CC, 0xB40A,
+	0x89CD, 0xB40B, 0x89CE, 0xB40C, 0x89CF, 0xB40D, 0x89D0, 0xB40E,
+	0x89D1, 0xB40F, 0x89D2, 0xB411, 0x89D3, 0xB412, 0x89D4, 0xB413,
+	0x89D5, 0xB414, 0x89D6, 0xB415, 0x89D7, 0xB416, 0x89D8, 0xB417,
+	0x89D9, 0xB419, 0x89DA, 0xB41A, 0x89DB, 0xB41B, 0x89DC, 0xB41D,
+	0x89DD, 0xB41E, 0x89DE, 0xB41F, 0x89DF, 0xB421, 0x89E0, 0xB422,
+	0x89E1, 0xB423, 0x89E2, 0xB424, 0x89E3, 0xB425, 0x89E4, 0xB426,
+	0x89E5, 0xB427, 0x89E6, 0xB42A, 0x89E7, 0xB42C, 0x89E8, 0xB42D,
+	0x89E9, 0xB42E, 0x89EA, 0xB42F, 0x89EB, 0xB430, 0x89EC, 0xB431,
+	0x89ED, 0xB432, 0x89EE, 0xB433, 0x89EF, 0xB435, 0x89F0, 0xB436,
+	0x89F1, 0xB437, 0x89F2, 0xB438, 0x89F3, 0xB439, 0x89F4, 0xB43A,
+	0x89F5, 0xB43B, 0x89F6, 0xB43C, 0x89F7, 0xB43D, 0x89F8, 0xB43E,
+	0x89F9, 0xB43F, 0x89FA, 0xB440, 0x89FB, 0xB441, 0x89FC, 0xB442,
+	0x89FD, 0xB443, 0x89FE, 0xB444, 0x8A41, 0xB445, 0x8A42, 0xB446,
+	0x8A43, 0xB447, 0x8A44, 0xB448, 0x8A45, 0xB449, 0x8A46, 0xB44A,
+	0x8A47, 0xB44B, 0x8A48, 0xB44C, 0x8A49, 0xB44D, 0x8A4A, 0xB44E,
+	0x8A4B, 0xB44F, 0x8A4C, 0xB452, 0x8A4D, 0xB453, 0x8A4E, 0xB455,
+	0x8A4F, 0xB456, 0x8A50, 0xB457, 0x8A51, 0xB459, 0x8A52, 0xB45A,
+	0x8A53, 0xB45B, 0x8A54, 0xB45C, 0x8A55, 0xB45D, 0x8A56, 0xB45E,
+	0x8A57, 0xB45F, 0x8A58, 0xB462, 0x8A59, 0xB464, 0x8A5A, 0xB466,
+	0x8A61, 0xB467, 0x8A62, 0xB468, 0x8A63, 0xB469, 0x8A64, 0xB46A,
+	0x8A65, 0xB46B, 0x8A66, 0xB46D, 0x8A67, 0xB46E, 0x8A68, 0xB46F,
+	0x8A69, 0xB470, 0x8A6A, 0xB471, 0x8A6B, 0xB472, 0x8A6C, 0xB473,
+	0x8A6D, 0xB474, 0x8A6E, 0xB475, 0x8A6F, 0xB476, 0x8A70, 0xB477,
+	0x8A71, 0xB478, 0x8A72, 0xB479, 0x8A73, 0xB47A, 0x8A74, 0xB47B,
+	0x8A75, 0xB47C, 0x8A76, 0xB47D, 0x8A77, 0xB47E, 0x8A78, 0xB47F,
+	0x8A79, 0xB481, 0x8A7A, 0xB482, 0x8A81, 0xB483, 0x8A82, 0xB484,
+	0x8A83, 0xB485, 0x8A84, 0xB486, 0x8A85, 0xB487, 0x8A86, 0xB489,
+	0x8A87, 0xB48A, 0x8A88, 0xB48B, 0x8A89, 0xB48C, 0x8A8A, 0xB48D,
+	0x8A8B, 0xB48E, 0x8A8C, 0xB48F, 0x8A8D, 0xB490, 0x8A8E, 0xB491,
+	0x8A8F, 0xB492, 0x8A90, 0xB493, 0x8A91, 0xB494, 0x8A92, 0xB495,
+	0x8A93, 0xB496, 0x8A94, 0xB497, 0x8A95, 0xB498, 0x8A96, 0xB499,
+	0x8A97, 0xB49A, 0x8A98, 0xB49B, 0x8A99, 0xB49C, 0x8A9A, 0xB49E,
+	0x8A9B, 0xB49F, 0x8A9C, 0xB4A0, 0x8A9D, 0xB4A1, 0x8A9E, 0xB4A2,
+	0x8A9F, 0xB4A3, 0x8AA0, 0xB4A5, 0x8AA1, 0xB4A6, 0x8AA2, 0xB4A7,
+	0x8AA3, 0xB4A9, 0x8AA4, 0xB4AA, 0x8AA5, 0xB4AB, 0x8AA6, 0xB4AD,
+	0x8AA7, 0xB4AE, 0x8AA8, 0xB4AF, 0x8AA9, 0xB4B0, 0x8AAA, 0xB4B1,
+	0x8AAB, 0xB4B2, 0x8AAC, 0xB4B3, 0x8AAD, 0xB4B4, 0x8AAE, 0xB4B6,
+	0x8AAF, 0xB4B8, 0x8AB0, 0xB4BA, 0x8AB1, 0xB4BB, 0x8AB2, 0xB4BC,
+	0x8AB3, 0xB4BD, 0x8AB4, 0xB4BE, 0x8AB5, 0xB4BF, 0x8AB6, 0xB4C1,
+	0x8AB7, 0xB4C2, 0x8AB8, 0xB4C3, 0x8AB9, 0xB4C5, 0x8ABA, 0xB4C6,
+	0x8ABB, 0xB4C7, 0x8ABC, 0xB4C9, 0x8ABD, 0xB4CA, 0x8ABE, 0xB4CB,
+	0x8ABF, 0xB4CC, 0x8AC0, 0xB4CD, 0x8AC1, 0xB4CE, 0x8AC2, 0xB4CF,
+	0x8AC3, 0xB4D1, 0x8AC4, 0xB4D2, 0x8AC5, 0xB4D3, 0x8AC6, 0xB4D4,
+	0x8AC7, 0xB4D6, 0x8AC8, 0xB4D7, 0x8AC9, 0xB4D8, 0x8ACA, 0xB4D9,
+	0x8ACB, 0xB4DA, 0x8ACC, 0xB4DB, 0x8ACD, 0xB4DE, 0x8ACE, 0xB4DF,
+	0x8ACF, 0xB4E1, 0x8AD0, 0xB4E2, 0x8AD1, 0xB4E5, 0x8AD2, 0xB4E7,
+	0x8AD3, 0xB4E8, 0x8AD4, 0xB4E9, 0x8AD5, 0xB4EA, 0x8AD6, 0xB4EB,
+	0x8AD7, 0xB4EE, 0x8AD8, 0xB4F0, 0x8AD9, 0xB4F2, 0x8ADA, 0xB4F3,
+	0x8ADB, 0xB4F4, 0x8ADC, 0xB4F5, 0x8ADD, 0xB4F6, 0x8ADE, 0xB4F7,
+	0x8ADF, 0xB4F9, 0x8AE0, 0xB4FA, 0x8AE1, 0xB4FB, 0x8AE2, 0xB4FC,
+	0x8AE3, 0xB4FD, 0x8AE4, 0xB4FE, 0x8AE5, 0xB4FF, 0x8AE6, 0xB500,
+	0x8AE7, 0xB501, 0x8AE8, 0xB502, 0x8AE9, 0xB503, 0x8AEA, 0xB504,
+	0x8AEB, 0xB505, 0x8AEC, 0xB506, 0x8AED, 0xB507, 0x8AEE, 0xB508,
+	0x8AEF, 0xB509, 0x8AF0, 0xB50A, 0x8AF1, 0xB50B, 0x8AF2, 0xB50C,
+	0x8AF3, 0xB50D, 0x8AF4, 0xB50E, 0x8AF5, 0xB50F, 0x8AF6, 0xB510,
+	0x8AF7, 0xB511, 0x8AF8, 0xB512, 0x8AF9, 0xB513, 0x8AFA, 0xB516,
+	0x8AFB, 0xB517, 0x8AFC, 0xB519, 0x8AFD, 0xB51A, 0x8AFE, 0xB51D,
+	0x8B41, 0xB51E, 0x8B42, 0xB51F, 0x8B43, 0xB520, 0x8B44, 0xB521,
+	0x8B45, 0xB522, 0x8B46, 0xB523, 0x8B47, 0xB526, 0x8B48, 0xB52B,
+	0x8B49, 0xB52C, 0x8B4A, 0xB52D, 0x8B4B, 0xB52E, 0x8B4C, 0xB52F,
+	0x8B4D, 0xB532, 0x8B4E, 0xB533, 0x8B4F, 0xB535, 0x8B50, 0xB536,
+	0x8B51, 0xB537, 0x8B52, 0xB539, 0x8B53, 0xB53A, 0x8B54, 0xB53B,
+	0x8B55, 0xB53C, 0x8B56, 0xB53D, 0x8B57, 0xB53E, 0x8B58, 0xB53F,
+	0x8B59, 0xB542, 0x8B5A, 0xB546, 0x8B61, 0xB547, 0x8B62, 0xB548,
+	0x8B63, 0xB549, 0x8B64, 0xB54A, 0x8B65, 0xB54E, 0x8B66, 0xB54F,
+	0x8B67, 0xB551, 0x8B68, 0xB552, 0x8B69, 0xB553, 0x8B6A, 0xB555,
+	0x8B6B, 0xB556, 0x8B6C, 0xB557, 0x8B6D, 0xB558, 0x8B6E, 0xB559,
+	0x8B6F, 0xB55A, 0x8B70, 0xB55B, 0x8B71, 0xB55E, 0x8B72, 0xB562,
+	0x8B73, 0xB563, 0x8B74, 0xB564, 0x8B75, 0xB565, 0x8B76, 0xB566,
+	0x8B77, 0xB567, 0x8B78, 0xB568, 0x8B79, 0xB569, 0x8B7A, 0xB56A,
+	0x8B81, 0xB56B, 0x8B82, 0xB56C, 0x8B83, 0xB56D, 0x8B84, 0xB56E,
+	0x8B85, 0xB56F, 0x8B86, 0xB570, 0x8B87, 0xB571, 0x8B88, 0xB572,
+	0x8B89, 0xB573, 0x8B8A, 0xB574, 0x8B8B, 0xB575, 0x8B8C, 0xB576,
+	0x8B8D, 0xB577, 0x8B8E, 0xB578, 0x8B8F, 0xB579, 0x8B90, 0xB57A,
+	0x8B91, 0xB57B, 0x8B92, 0xB57C, 0x8B93, 0xB57D, 0x8B94, 0xB57E,
+	0x8B95, 0xB57F, 0x8B96, 0xB580, 0x8B97, 0xB581, 0x8B98, 0xB582,
+	0x8B99, 0xB583, 0x8B9A, 0xB584, 0x8B9B, 0xB585, 0x8B9C, 0xB586,
+	0x8B9D, 0xB587, 0x8B9E, 0xB588, 0x8B9F, 0xB589, 0x8BA0, 0xB58A,
+	0x8BA1, 0xB58B, 0x8BA2, 0xB58C, 0x8BA3, 0xB58D, 0x8BA4, 0xB58E,
+	0x8BA5, 0xB58F, 0x8BA6, 0xB590, 0x8BA7, 0xB591, 0x8BA8, 0xB592,
+	0x8BA9, 0xB593, 0x8BAA, 0xB594, 0x8BAB, 0xB595, 0x8BAC, 0xB596,
+	0x8BAD, 0xB597, 0x8BAE, 0xB598, 0x8BAF, 0xB599, 0x8BB0, 0xB59A,
+	0x8BB1, 0xB59B, 0x8BB2, 0xB59C, 0x8BB3, 0xB59D, 0x8BB4, 0xB59E,
+	0x8BB5, 0xB59F, 0x8BB6, 0xB5A2, 0x8BB7, 0xB5A3, 0x8BB8, 0xB5A5,
+	0x8BB9, 0xB5A6, 0x8BBA, 0xB5A7, 0x8BBB, 0xB5A9, 0x8BBC, 0xB5AC,
+	0x8BBD, 0xB5AD, 0x8BBE, 0xB5AE, 0x8BBF, 0xB5AF, 0x8BC0, 0xB5B2,
+	0x8BC1, 0xB5B6, 0x8BC2, 0xB5B7, 0x8BC3, 0xB5B8, 0x8BC4, 0xB5B9,
+	0x8BC5, 0xB5BA, 0x8BC6, 0xB5BE, 0x8BC7, 0xB5BF, 0x8BC8, 0xB5C1,
+	0x8BC9, 0xB5C2, 0x8BCA, 0xB5C3, 0x8BCB, 0xB5C5, 0x8BCC, 0xB5C6,
+	0x8BCD, 0xB5C7, 0x8BCE, 0xB5C8, 0x8BCF, 0xB5C9, 0x8BD0, 0xB5CA,
+	0x8BD1, 0xB5CB, 0x8BD2, 0xB5CE, 0x8BD3, 0xB5D2, 0x8BD4, 0xB5D3,
+	0x8BD5, 0xB5D4, 0x8BD6, 0xB5D5, 0x8BD7, 0xB5D6, 0x8BD8, 0xB5D7,
+	0x8BD9, 0xB5D9, 0x8BDA, 0xB5DA, 0x8BDB, 0xB5DB, 0x8BDC, 0xB5DC,
+	0x8BDD, 0xB5DD, 0x8BDE, 0xB5DE, 0x8BDF, 0xB5DF, 0x8BE0, 0xB5E0,
+	0x8BE1, 0xB5E1, 0x8BE2, 0xB5E2, 0x8BE3, 0xB5E3, 0x8BE4, 0xB5E4,
+	0x8BE5, 0xB5E5, 0x8BE6, 0xB5E6, 0x8BE7, 0xB5E7, 0x8BE8, 0xB5E8,
+	0x8BE9, 0xB5E9, 0x8BEA, 0xB5EA, 0x8BEB, 0xB5EB, 0x8BEC, 0xB5ED,
+	0x8BED, 0xB5EE, 0x8BEE, 0xB5EF, 0x8BEF, 0xB5F0, 0x8BF0, 0xB5F1,
+	0x8BF1, 0xB5F2, 0x8BF2, 0xB5F3, 0x8BF3, 0xB5F4, 0x8BF4, 0xB5F5,
+	0x8BF5, 0xB5F6, 0x8BF6, 0xB5F7, 0x8BF7, 0xB5F8, 0x8BF8, 0xB5F9,
+	0x8BF9, 0xB5FA, 0x8BFA, 0xB5FB, 0x8BFB, 0xB5FC, 0x8BFC, 0xB5FD,
+	0x8BFD, 0xB5FE, 0x8BFE, 0xB5FF, 0x8C41, 0xB600, 0x8C42, 0xB601,
+	0x8C43, 0xB602, 0x8C44, 0xB603, 0x8C45, 0xB604, 0x8C46, 0xB605,
+	0x8C47, 0xB606, 0x8C48, 0xB607, 0x8C49, 0xB608, 0x8C4A, 0xB609,
+	0x8C4B, 0xB60A, 0x8C4C, 0xB60B, 0x8C4D, 0xB60C, 0x8C4E, 0xB60D,
+	0x8C4F, 0xB60E, 0x8C50, 0xB60F, 0x8C51, 0xB612, 0x8C52, 0xB613,
+	0x8C53, 0xB615, 0x8C54, 0xB616, 0x8C55, 0xB617, 0x8C56, 0xB619,
+	0x8C57, 0xB61A, 0x8C58, 0xB61B, 0x8C59, 0xB61C, 0x8C5A, 0xB61D,
+	0x8C61, 0xB61E, 0x8C62, 0xB61F, 0x8C63, 0xB620, 0x8C64, 0xB621,
+	0x8C65, 0xB622, 0x8C66, 0xB623, 0x8C67, 0xB624, 0x8C68, 0xB626,
+	0x8C69, 0xB627, 0x8C6A, 0xB628, 0x8C6B, 0xB629, 0x8C6C, 0xB62A,
+	0x8C6D, 0xB62B, 0x8C6E, 0xB62D, 0x8C6F, 0xB62E, 0x8C70, 0xB62F,
+	0x8C71, 0xB630, 0x8C72, 0xB631, 0x8C73, 0xB632, 0x8C74, 0xB633,
+	0x8C75, 0xB635, 0x8C76, 0xB636, 0x8C77, 0xB637, 0x8C78, 0xB638,
+	0x8C79, 0xB639, 0x8C7A, 0xB63A, 0x8C81, 0xB63B, 0x8C82, 0xB63C,
+	0x8C83, 0xB63D, 0x8C84, 0xB63E, 0x8C85, 0xB63F, 0x8C86, 0xB640,
+	0x8C87, 0xB641, 0x8C88, 0xB642, 0x8C89, 0xB643, 0x8C8A, 0xB644,
+	0x8C8B, 0xB645, 0x8C8C, 0xB646, 0x8C8D, 0xB647, 0x8C8E, 0xB649,
+	0x8C8F, 0xB64A, 0x8C90, 0xB64B, 0x8C91, 0xB64C, 0x8C92, 0xB64D,
+	0x8C93, 0xB64E, 0x8C94, 0xB64F, 0x8C95, 0xB650, 0x8C96, 0xB651,
+	0x8C97, 0xB652, 0x8C98, 0xB653, 0x8C99, 0xB654, 0x8C9A, 0xB655,
+	0x8C9B, 0xB656, 0x8C9C, 0xB657, 0x8C9D, 0xB658, 0x8C9E, 0xB659,
+	0x8C9F, 0xB65A, 0x8CA0, 0xB65B, 0x8CA1, 0xB65C, 0x8CA2, 0xB65D,
+	0x8CA3, 0xB65E, 0x8CA4, 0xB65F, 0x8CA5, 0xB660, 0x8CA6, 0xB661,
+	0x8CA7, 0xB662, 0x8CA8, 0xB663, 0x8CA9, 0xB665, 0x8CAA, 0xB666,
+	0x8CAB, 0xB667, 0x8CAC, 0xB669, 0x8CAD, 0xB66A, 0x8CAE, 0xB66B,
+	0x8CAF, 0xB66C, 0x8CB0, 0xB66D, 0x8CB1, 0xB66E, 0x8CB2, 0xB66F,
+	0x8CB3, 0xB670, 0x8CB4, 0xB671, 0x8CB5, 0xB672, 0x8CB6, 0xB673,
+	0x8CB7, 0xB674, 0x8CB8, 0xB675, 0x8CB9, 0xB676, 0x8CBA, 0xB677,
+	0x8CBB, 0xB678, 0x8CBC, 0xB679, 0x8CBD, 0xB67A, 0x8CBE, 0xB67B,
+	0x8CBF, 0xB67C, 0x8CC0, 0xB67D, 0x8CC1, 0xB67E, 0x8CC2, 0xB67F,
+	0x8CC3, 0xB680, 0x8CC4, 0xB681, 0x8CC5, 0xB682, 0x8CC6, 0xB683,
+	0x8CC7, 0xB684, 0x8CC8, 0xB685, 0x8CC9, 0xB686, 0x8CCA, 0xB687,
+	0x8CCB, 0xB688, 0x8CCC, 0xB689, 0x8CCD, 0xB68A, 0x8CCE, 0xB68B,
+	0x8CCF, 0xB68C, 0x8CD0, 0xB68D, 0x8CD1, 0xB68E, 0x8CD2, 0xB68F,
+	0x8CD3, 0xB690, 0x8CD4, 0xB691, 0x8CD5, 0xB692, 0x8CD6, 0xB693,
+	0x8CD7, 0xB694, 0x8CD8, 0xB695, 0x8CD9, 0xB696, 0x8CDA, 0xB697,
+	0x8CDB, 0xB698, 0x8CDC, 0xB699, 0x8CDD, 0xB69A, 0x8CDE, 0xB69B,
+	0x8CDF, 0xB69E, 0x8CE0, 0xB69F, 0x8CE1, 0xB6A1, 0x8CE2, 0xB6A2,
+	0x8CE3, 0xB6A3, 0x8CE4, 0xB6A5, 0x8CE5, 0xB6A6, 0x8CE6, 0xB6A7,
+	0x8CE7, 0xB6A8, 0x8CE8, 0xB6A9, 0x8CE9, 0xB6AA, 0x8CEA, 0xB6AD,
+	0x8CEB, 0xB6AE, 0x8CEC, 0xB6AF, 0x8CED, 0xB6B0, 0x8CEE, 0xB6B2,
+	0x8CEF, 0xB6B3, 0x8CF0, 0xB6B4, 0x8CF1, 0xB6B5, 0x8CF2, 0xB6B6,
+	0x8CF3, 0xB6B7, 0x8CF4, 0xB6B8, 0x8CF5, 0xB6B9, 0x8CF6, 0xB6BA,
+	0x8CF7, 0xB6BB, 0x8CF8, 0xB6BC, 0x8CF9, 0xB6BD, 0x8CFA, 0xB6BE,
+	0x8CFB, 0xB6BF, 0x8CFC, 0xB6C0, 0x8CFD, 0xB6C1, 0x8CFE, 0xB6C2,
+	0x8D41, 0xB6C3, 0x8D42, 0xB6C4, 0x8D43, 0xB6C5, 0x8D44, 0xB6C6,
+	0x8D45, 0xB6C7, 0x8D46, 0xB6C8, 0x8D47, 0xB6C9, 0x8D48, 0xB6CA,
+	0x8D49, 0xB6CB, 0x8D4A, 0xB6CC, 0x8D4B, 0xB6CD, 0x8D4C, 0xB6CE,
+	0x8D4D, 0xB6CF, 0x8D4E, 0xB6D0, 0x8D4F, 0xB6D1, 0x8D50, 0xB6D2,
+	0x8D51, 0xB6D3, 0x8D52, 0xB6D5, 0x8D53, 0xB6D6, 0x8D54, 0xB6D7,
+	0x8D55, 0xB6D8, 0x8D56, 0xB6D9, 0x8D57, 0xB6DA, 0x8D58, 0xB6DB,
+	0x8D59, 0xB6DC, 0x8D5A, 0xB6DD, 0x8D61, 0xB6DE, 0x8D62, 0xB6DF,
+	0x8D63, 0xB6E0, 0x8D64, 0xB6E1, 0x8D65, 0xB6E2, 0x8D66, 0xB6E3,
+	0x8D67, 0xB6E4, 0x8D68, 0xB6E5, 0x8D69, 0xB6E6, 0x8D6A, 0xB6E7,
+	0x8D6B, 0xB6E8, 0x8D6C, 0xB6E9, 0x8D6D, 0xB6EA, 0x8D6E, 0xB6EB,
+	0x8D6F, 0xB6EC, 0x8D70, 0xB6ED, 0x8D71, 0xB6EE, 0x8D72, 0xB6EF,
+	0x8D73, 0xB6F1, 0x8D74, 0xB6F2, 0x8D75, 0xB6F3, 0x8D76, 0xB6F5,
+	0x8D77, 0xB6F6, 0x8D78, 0xB6F7, 0x8D79, 0xB6F9, 0x8D7A, 0xB6FA,
+	0x8D81, 0xB6FB, 0x8D82, 0xB6FC, 0x8D83, 0xB6FD, 0x8D84, 0xB6FE,
+	0x8D85, 0xB6FF, 0x8D86, 0xB702, 0x8D87, 0xB703, 0x8D88, 0xB704,
+	0x8D89, 0xB706, 0x8D8A, 0xB707, 0x8D8B, 0xB708, 0x8D8C, 0xB709,
+	0x8D8D, 0xB70A, 0x8D8E, 0xB70B, 0x8D8F, 0xB70C, 0x8D90, 0xB70D,
+	0x8D91, 0xB70E, 0x8D92, 0xB70F, 0x8D93, 0xB710, 0x8D94, 0xB711,
+	0x8D95, 0xB712, 0x8D96, 0xB713, 0x8D97, 0xB714, 0x8D98, 0xB715,
+	0x8D99, 0xB716, 0x8D9A, 0xB717, 0x8D9B, 0xB718, 0x8D9C, 0xB719,
+	0x8D9D, 0xB71A, 0x8D9E, 0xB71B, 0x8D9F, 0xB71C, 0x8DA0, 0xB71D,
+	0x8DA1, 0xB71E, 0x8DA2, 0xB71F, 0x8DA3, 0xB720, 0x8DA4, 0xB721,
+	0x8DA5, 0xB722, 0x8DA6, 0xB723, 0x8DA7, 0xB724, 0x8DA8, 0xB725,
+	0x8DA9, 0xB726, 0x8DAA, 0xB727, 0x8DAB, 0xB72A, 0x8DAC, 0xB72B,
+	0x8DAD, 0xB72D, 0x8DAE, 0xB72E, 0x8DAF, 0xB731, 0x8DB0, 0xB732,
+	0x8DB1, 0xB733, 0x8DB2, 0xB734, 0x8DB3, 0xB735, 0x8DB4, 0xB736,
+	0x8DB5, 0xB737, 0x8DB6, 0xB73A, 0x8DB7, 0xB73C, 0x8DB8, 0xB73D,
+	0x8DB9, 0xB73E, 0x8DBA, 0xB73F, 0x8DBB, 0xB740, 0x8DBC, 0xB741,
+	0x8DBD, 0xB742, 0x8DBE, 0xB743, 0x8DBF, 0xB745, 0x8DC0, 0xB746,
+	0x8DC1, 0xB747, 0x8DC2, 0xB749, 0x8DC3, 0xB74A, 0x8DC4, 0xB74B,
+	0x8DC5, 0xB74D, 0x8DC6, 0xB74E, 0x8DC7, 0xB74F, 0x8DC8, 0xB750,
+	0x8DC9, 0xB751, 0x8DCA, 0xB752, 0x8DCB, 0xB753, 0x8DCC, 0xB756,
+	0x8DCD, 0xB757, 0x8DCE, 0xB758, 0x8DCF, 0xB759, 0x8DD0, 0xB75A,
+	0x8DD1, 0xB75B, 0x8DD2, 0xB75C, 0x8DD3, 0xB75D, 0x8DD4, 0xB75E,
+	0x8DD5, 0xB75F, 0x8DD6, 0xB761, 0x8DD7, 0xB762, 0x8DD8, 0xB763,
+	0x8DD9, 0xB765, 0x8DDA, 0xB766, 0x8DDB, 0xB767, 0x8DDC, 0xB769,
+	0x8DDD, 0xB76A, 0x8DDE, 0xB76B, 0x8DDF, 0xB76C, 0x8DE0, 0xB76D,
+	0x8DE1, 0xB76E, 0x8DE2, 0xB76F, 0x8DE3, 0xB772, 0x8DE4, 0xB774,
+	0x8DE5, 0xB776, 0x8DE6, 0xB777, 0x8DE7, 0xB778, 0x8DE8, 0xB779,
+	0x8DE9, 0xB77A, 0x8DEA, 0xB77B, 0x8DEB, 0xB77E, 0x8DEC, 0xB77F,
+	0x8DED, 0xB781, 0x8DEE, 0xB782, 0x8DEF, 0xB783, 0x8DF0, 0xB785,
+	0x8DF1, 0xB786, 0x8DF2, 0xB787, 0x8DF3, 0xB788, 0x8DF4, 0xB789,
+	0x8DF5, 0xB78A, 0x8DF6, 0xB78B, 0x8DF7, 0xB78E, 0x8DF8, 0xB793,
+	0x8DF9, 0xB794, 0x8DFA, 0xB795, 0x8DFB, 0xB79A, 0x8DFC, 0xB79B,
+	0x8DFD, 0xB79D, 0x8DFE, 0xB79E, 0x8E41, 0xB79F, 0x8E42, 0xB7A1,
+	0x8E43, 0xB7A2, 0x8E44, 0xB7A3, 0x8E45, 0xB7A4, 0x8E46, 0xB7A5,
+	0x8E47, 0xB7A6, 0x8E48, 0xB7A7, 0x8E49, 0xB7AA, 0x8E4A, 0xB7AE,
+	0x8E4B, 0xB7AF, 0x8E4C, 0xB7B0, 0x8E4D, 0xB7B1, 0x8E4E, 0xB7B2,
+	0x8E4F, 0xB7B3, 0x8E50, 0xB7B6, 0x8E51, 0xB7B7, 0x8E52, 0xB7B9,
+	0x8E53, 0xB7BA, 0x8E54, 0xB7BB, 0x8E55, 0xB7BC, 0x8E56, 0xB7BD,
+	0x8E57, 0xB7BE, 0x8E58, 0xB7BF, 0x8E59, 0xB7C0, 0x8E5A, 0xB7C1,
+	0x8E61, 0xB7C2, 0x8E62, 0xB7C3, 0x8E63, 0xB7C4, 0x8E64, 0xB7C5,
+	0x8E65, 0xB7C6, 0x8E66, 0xB7C8, 0x8E67, 0xB7CA, 0x8E68, 0xB7CB,
+	0x8E69, 0xB7CC, 0x8E6A, 0xB7CD, 0x8E6B, 0xB7CE, 0x8E6C, 0xB7CF,
+	0x8E6D, 0xB7D0, 0x8E6E, 0xB7D1, 0x8E6F, 0xB7D2, 0x8E70, 0xB7D3,
+	0x8E71, 0xB7D4, 0x8E72, 0xB7D5, 0x8E73, 0xB7D6, 0x8E74, 0xB7D7,
+	0x8E75, 0xB7D8, 0x8E76, 0xB7D9, 0x8E77, 0xB7DA, 0x8E78, 0xB7DB,
+	0x8E79, 0xB7DC, 0x8E7A, 0xB7DD, 0x8E81, 0xB7DE, 0x8E82, 0xB7DF,
+	0x8E83, 0xB7E0, 0x8E84, 0xB7E1, 0x8E85, 0xB7E2, 0x8E86, 0xB7E3,
+	0x8E87, 0xB7E4, 0x8E88, 0xB7E5, 0x8E89, 0xB7E6, 0x8E8A, 0xB7E7,
+	0x8E8B, 0xB7E8, 0x8E8C, 0xB7E9, 0x8E8D, 0xB7EA, 0x8E8E, 0xB7EB,
+	0x8E8F, 0xB7EE, 0x8E90, 0xB7EF, 0x8E91, 0xB7F1, 0x8E92, 0xB7F2,
+	0x8E93, 0xB7F3, 0x8E94, 0xB7F5, 0x8E95, 0xB7F6, 0x8E96, 0xB7F7,
+	0x8E97, 0xB7F8, 0x8E98, 0xB7F9, 0x8E99, 0xB7FA, 0x8E9A, 0xB7FB,
+	0x8E9B, 0xB7FE, 0x8E9C, 0xB802, 0x8E9D, 0xB803, 0x8E9E, 0xB804,
+	0x8E9F, 0xB805, 0x8EA0, 0xB806, 0x8EA1, 0xB80A, 0x8EA2, 0xB80B,
+	0x8EA3, 0xB80D, 0x8EA4, 0xB80E, 0x8EA5, 0xB80F, 0x8EA6, 0xB811,
+	0x8EA7, 0xB812, 0x8EA8, 0xB813, 0x8EA9, 0xB814, 0x8EAA, 0xB815,
+	0x8EAB, 0xB816, 0x8EAC, 0xB817, 0x8EAD, 0xB81A, 0x8EAE, 0xB81C,
+	0x8EAF, 0xB81E, 0x8EB0, 0xB81F, 0x8EB1, 0xB820, 0x8EB2, 0xB821,
+	0x8EB3, 0xB822, 0x8EB4, 0xB823, 0x8EB5, 0xB826, 0x8EB6, 0xB827,
+	0x8EB7, 0xB829, 0x8EB8, 0xB82A, 0x8EB9, 0xB82B, 0x8EBA, 0xB82D,
+	0x8EBB, 0xB82E, 0x8EBC, 0xB82F, 0x8EBD, 0xB830, 0x8EBE, 0xB831,
+	0x8EBF, 0xB832, 0x8EC0, 0xB833, 0x8EC1, 0xB836, 0x8EC2, 0xB83A,
+	0x8EC3, 0xB83B, 0x8EC4, 0xB83C, 0x8EC5, 0xB83D, 0x8EC6, 0xB83E,
+	0x8EC7, 0xB83F, 0x8EC8, 0xB841, 0x8EC9, 0xB842, 0x8ECA, 0xB843,
+	0x8ECB, 0xB845, 0x8ECC, 0xB846, 0x8ECD, 0xB847, 0x8ECE, 0xB848,
+	0x8ECF, 0xB849, 0x8ED0, 0xB84A, 0x8ED1, 0xB84B, 0x8ED2, 0xB84C,
+	0x8ED3, 0xB84D, 0x8ED4, 0xB84E, 0x8ED5, 0xB84F, 0x8ED6, 0xB850,
+	0x8ED7, 0xB852, 0x8ED8, 0xB854, 0x8ED9, 0xB855, 0x8EDA, 0xB856,
+	0x8EDB, 0xB857, 0x8EDC, 0xB858, 0x8EDD, 0xB859, 0x8EDE, 0xB85A,
+	0x8EDF, 0xB85B, 0x8EE0, 0xB85E, 0x8EE1, 0xB85F, 0x8EE2, 0xB861,
+	0x8EE3, 0xB862, 0x8EE4, 0xB863, 0x8EE5, 0xB865, 0x8EE6, 0xB866,
+	0x8EE7, 0xB867, 0x8EE8, 0xB868, 0x8EE9, 0xB869, 0x8EEA, 0xB86A,
+	0x8EEB, 0xB86B, 0x8EEC, 0xB86E, 0x8EED, 0xB870, 0x8EEE, 0xB872,
+	0x8EEF, 0xB873, 0x8EF0, 0xB874, 0x8EF1, 0xB875, 0x8EF2, 0xB876,
+	0x8EF3, 0xB877, 0x8EF4, 0xB879, 0x8EF5, 0xB87A, 0x8EF6, 0xB87B,
+	0x8EF7, 0xB87D, 0x8EF8, 0xB87E, 0x8EF9, 0xB87F, 0x8EFA, 0xB880,
+	0x8EFB, 0xB881, 0x8EFC, 0xB882, 0x8EFD, 0xB883, 0x8EFE, 0xB884,
+	0x8F41, 0xB885, 0x8F42, 0xB886, 0x8F43, 0xB887, 0x8F44, 0xB888,
+	0x8F45, 0xB889, 0x8F46, 0xB88A, 0x8F47, 0xB88B, 0x8F48, 0xB88C,
+	0x8F49, 0xB88E, 0x8F4A, 0xB88F, 0x8F4B, 0xB890, 0x8F4C, 0xB891,
+	0x8F4D, 0xB892, 0x8F4E, 0xB893, 0x8F4F, 0xB894, 0x8F50, 0xB895,
+	0x8F51, 0xB896, 0x8F52, 0xB897, 0x8F53, 0xB898, 0x8F54, 0xB899,
+	0x8F55, 0xB89A, 0x8F56, 0xB89B, 0x8F57, 0xB89C, 0x8F58, 0xB89D,
+	0x8F59, 0xB89E, 0x8F5A, 0xB89F, 0x8F61, 0xB8A0, 0x8F62, 0xB8A1,
+	0x8F63, 0xB8A2, 0x8F64, 0xB8A3, 0x8F65, 0xB8A4, 0x8F66, 0xB8A5,
+	0x8F67, 0xB8A6, 0x8F68, 0xB8A7, 0x8F69, 0xB8A9, 0x8F6A, 0xB8AA,
+	0x8F6B, 0xB8AB, 0x8F6C, 0xB8AC, 0x8F6D, 0xB8AD, 0x8F6E, 0xB8AE,
+	0x8F6F, 0xB8AF, 0x8F70, 0xB8B1, 0x8F71, 0xB8B2, 0x8F72, 0xB8B3,
+	0x8F73, 0xB8B5, 0x8F74, 0xB8B6, 0x8F75, 0xB8B7, 0x8F76, 0xB8B9,
+	0x8F77, 0xB8BA, 0x8F78, 0xB8BB, 0x8F79, 0xB8BC, 0x8F7A, 0xB8BD,
+	0x8F81, 0xB8BE, 0x8F82, 0xB8BF, 0x8F83, 0xB8C2, 0x8F84, 0xB8C4,
+	0x8F85, 0xB8C6, 0x8F86, 0xB8C7, 0x8F87, 0xB8C8, 0x8F88, 0xB8C9,
+	0x8F89, 0xB8CA, 0x8F8A, 0xB8CB, 0x8F8B, 0xB8CD, 0x8F8C, 0xB8CE,
+	0x8F8D, 0xB8CF, 0x8F8E, 0xB8D1, 0x8F8F, 0xB8D2, 0x8F90, 0xB8D3,
+	0x8F91, 0xB8D5, 0x8F92, 0xB8D6, 0x8F93, 0xB8D7, 0x8F94, 0xB8D8,
+	0x8F95, 0xB8D9, 0x8F96, 0xB8DA, 0x8F97, 0xB8DB, 0x8F98, 0xB8DC,
+	0x8F99, 0xB8DE, 0x8F9A, 0xB8E0, 0x8F9B, 0xB8E2, 0x8F9C, 0xB8E3,
+	0x8F9D, 0xB8E4, 0x8F9E, 0xB8E5, 0x8F9F, 0xB8E6, 0x8FA0, 0xB8E7,
+	0x8FA1, 0xB8EA, 0x8FA2, 0xB8EB, 0x8FA3, 0xB8ED, 0x8FA4, 0xB8EE,
+	0x8FA5, 0xB8EF, 0x8FA6, 0xB8F1, 0x8FA7, 0xB8F2, 0x8FA8, 0xB8F3,
+	0x8FA9, 0xB8F4, 0x8FAA, 0xB8F5, 0x8FAB, 0xB8F6, 0x8FAC, 0xB8F7,
+	0x8FAD, 0xB8FA, 0x8FAE, 0xB8FC, 0x8FAF, 0xB8FE, 0x8FB0, 0xB8FF,
+	0x8FB1, 0xB900, 0x8FB2, 0xB901, 0x8FB3, 0xB902, 0x8FB4, 0xB903,
+	0x8FB5, 0xB905, 0x8FB6, 0xB906, 0x8FB7, 0xB907, 0x8FB8, 0xB908,
+	0x8FB9, 0xB909, 0x8FBA, 0xB90A, 0x8FBB, 0xB90B, 0x8FBC, 0xB90C,
+	0x8FBD, 0xB90D, 0x8FBE, 0xB90E, 0x8FBF, 0xB90F, 0x8FC0, 0xB910,
+	0x8FC1, 0xB911, 0x8FC2, 0xB912, 0x8FC3, 0xB913, 0x8FC4, 0xB914,
+	0x8FC5, 0xB915, 0x8FC6, 0xB916, 0x8FC7, 0xB917, 0x8FC8, 0xB919,
+	0x8FC9, 0xB91A, 0x8FCA, 0xB91B, 0x8FCB, 0xB91C, 0x8FCC, 0xB91D,
+	0x8FCD, 0xB91E, 0x8FCE, 0xB91F, 0x8FCF, 0xB921, 0x8FD0, 0xB922,
+	0x8FD1, 0xB923, 0x8FD2, 0xB924, 0x8FD3, 0xB925, 0x8FD4, 0xB926,
+	0x8FD5, 0xB927, 0x8FD6, 0xB928, 0x8FD7, 0xB929, 0x8FD8, 0xB92A,
+	0x8FD9, 0xB92B, 0x8FDA, 0xB92C, 0x8FDB, 0xB92D, 0x8FDC, 0xB92E,
+	0x8FDD, 0xB92F, 0x8FDE, 0xB930, 0x8FDF, 0xB931, 0x8FE0, 0xB932,
+	0x8FE1, 0xB933, 0x8FE2, 0xB934, 0x8FE3, 0xB935, 0x8FE4, 0xB936,
+	0x8FE5, 0xB937, 0x8FE6, 0xB938, 0x8FE7, 0xB939, 0x8FE8, 0xB93A,
+	0x8FE9, 0xB93B, 0x8FEA, 0xB93E, 0x8FEB, 0xB93F, 0x8FEC, 0xB941,
+	0x8FED, 0xB942, 0x8FEE, 0xB943, 0x8FEF, 0xB945, 0x8FF0, 0xB946,
+	0x8FF1, 0xB947, 0x8FF2, 0xB948, 0x8FF3, 0xB949, 0x8FF4, 0xB94A,
+	0x8FF5, 0xB94B, 0x8FF6, 0xB94D, 0x8FF7, 0xB94E, 0x8FF8, 0xB950,
+	0x8FF9, 0xB952, 0x8FFA, 0xB953, 0x8FFB, 0xB954, 0x8FFC, 0xB955,
+	0x8FFD, 0xB956, 0x8FFE, 0xB957, 0x9041, 0xB95A, 0x9042, 0xB95B,
+	0x9043, 0xB95D, 0x9044, 0xB95E, 0x9045, 0xB95F, 0x9046, 0xB961,
+	0x9047, 0xB962, 0x9048, 0xB963, 0x9049, 0xB964, 0x904A, 0xB965,
+	0x904B, 0xB966, 0x904C, 0xB967, 0x904D, 0xB96A, 0x904E, 0xB96C,
+	0x904F, 0xB96E, 0x9050, 0xB96F, 0x9051, 0xB970, 0x9052, 0xB971,
+	0x9053, 0xB972, 0x9054, 0xB973, 0x9055, 0xB976, 0x9056, 0xB977,
+	0x9057, 0xB979, 0x9058, 0xB97A, 0x9059, 0xB97B, 0x905A, 0xB97D,
+	0x9061, 0xB97E, 0x9062, 0xB97F, 0x9063, 0xB980, 0x9064, 0xB981,
+	0x9065, 0xB982, 0x9066, 0xB983, 0x9067, 0xB986, 0x9068, 0xB988,
+	0x9069, 0xB98B, 0x906A, 0xB98C, 0x906B, 0xB98F, 0x906C, 0xB990,
+	0x906D, 0xB991, 0x906E, 0xB992, 0x906F, 0xB993, 0x9070, 0xB994,
+	0x9071, 0xB995, 0x9072, 0xB996, 0x9073, 0xB997, 0x9074, 0xB998,
+	0x9075, 0xB999, 0x9076, 0xB99A, 0x9077, 0xB99B, 0x9078, 0xB99C,
+	0x9079, 0xB99D, 0x907A, 0xB99E, 0x9081, 0xB99F, 0x9082, 0xB9A0,
+	0x9083, 0xB9A1, 0x9084, 0xB9A2, 0x9085, 0xB9A3, 0x9086, 0xB9A4,
+	0x9087, 0xB9A5, 0x9088, 0xB9A6, 0x9089, 0xB9A7, 0x908A, 0xB9A8,
+	0x908B, 0xB9A9, 0x908C, 0xB9AA, 0x908D, 0xB9AB, 0x908E, 0xB9AE,
+	0x908F, 0xB9AF, 0x9090, 0xB9B1, 0x9091, 0xB9B2, 0x9092, 0xB9B3,
+	0x9093, 0xB9B5, 0x9094, 0xB9B6, 0x9095, 0xB9B7, 0x9096, 0xB9B8,
+	0x9097, 0xB9B9, 0x9098, 0xB9BA, 0x9099, 0xB9BB, 0x909A, 0xB9BE,
+	0x909B, 0xB9C0, 0x909C, 0xB9C2, 0x909D, 0xB9C3, 0x909E, 0xB9C4,
+	0x909F, 0xB9C5, 0x90A0, 0xB9C6, 0x90A1, 0xB9C7, 0x90A2, 0xB9CA,
+	0x90A3, 0xB9CB, 0x90A4, 0xB9CD, 0x90A5, 0xB9D3, 0x90A6, 0xB9D4,
+	0x90A7, 0xB9D5, 0x90A8, 0xB9D6, 0x90A9, 0xB9D7, 0x90AA, 0xB9DA,
+	0x90AB, 0xB9DC, 0x90AC, 0xB9DF, 0x90AD, 0xB9E0, 0x90AE, 0xB9E2,
+	0x90AF, 0xB9E6, 0x90B0, 0xB9E7, 0x90B1, 0xB9E9, 0x90B2, 0xB9EA,
+	0x90B3, 0xB9EB, 0x90B4, 0xB9ED, 0x90B5, 0xB9EE, 0x90B6, 0xB9EF,
+	0x90B7, 0xB9F0, 0x90B8, 0xB9F1, 0x90B9, 0xB9F2, 0x90BA, 0xB9F3,
+	0x90BB, 0xB9F6, 0x90BC, 0xB9FB, 0x90BD, 0xB9FC, 0x90BE, 0xB9FD,
+	0x90BF, 0xB9FE, 0x90C0, 0xB9FF, 0x90C1, 0xBA02, 0x90C2, 0xBA03,
+	0x90C3, 0xBA04, 0x90C4, 0xBA05, 0x90C5, 0xBA06, 0x90C6, 0xBA07,
+	0x90C7, 0xBA09, 0x90C8, 0xBA0A, 0x90C9, 0xBA0B, 0x90CA, 0xBA0C,
+	0x90CB, 0xBA0D, 0x90CC, 0xBA0E, 0x90CD, 0xBA0F, 0x90CE, 0xBA10,
+	0x90CF, 0xBA11, 0x90D0, 0xBA12, 0x90D1, 0xBA13, 0x90D2, 0xBA14,
+	0x90D3, 0xBA16, 0x90D4, 0xBA17, 0x90D5, 0xBA18, 0x90D6, 0xBA19,
+	0x90D7, 0xBA1A, 0x90D8, 0xBA1B, 0x90D9, 0xBA1C, 0x90DA, 0xBA1D,
+	0x90DB, 0xBA1E, 0x90DC, 0xBA1F, 0x90DD, 0xBA20, 0x90DE, 0xBA21,
+	0x90DF, 0xBA22, 0x90E0, 0xBA23, 0x90E1, 0xBA24, 0x90E2, 0xBA25,
+	0x90E3, 0xBA26, 0x90E4, 0xBA27, 0x90E5, 0xBA28, 0x90E6, 0xBA29,
+	0x90E7, 0xBA2A, 0x90E8, 0xBA2B, 0x90E9, 0xBA2C, 0x90EA, 0xBA2D,
+	0x90EB, 0xBA2E, 0x90EC, 0xBA2F, 0x90ED, 0xBA30, 0x90EE, 0xBA31,
+	0x90EF, 0xBA32, 0x90F0, 0xBA33, 0x90F1, 0xBA34, 0x90F2, 0xBA35,
+	0x90F3, 0xBA36, 0x90F4, 0xBA37, 0x90F5, 0xBA3A, 0x90F6, 0xBA3B,
+	0x90F7, 0xBA3D, 0x90F8, 0xBA3E, 0x90F9, 0xBA3F, 0x90FA, 0xBA41,
+	0x90FB, 0xBA43, 0x90FC, 0xBA44, 0x90FD, 0xBA45, 0x90FE, 0xBA46,
+	0x9141, 0xBA47, 0x9142, 0xBA4A, 0x9143, 0xBA4C, 0x9144, 0xBA4F,
+	0x9145, 0xBA50, 0x9146, 0xBA51, 0x9147, 0xBA52, 0x9148, 0xBA56,
+	0x9149, 0xBA57, 0x914A, 0xBA59, 0x914B, 0xBA5A, 0x914C, 0xBA5B,
+	0x914D, 0xBA5D, 0x914E, 0xBA5E, 0x914F, 0xBA5F, 0x9150, 0xBA60,
+	0x9151, 0xBA61, 0x9152, 0xBA62, 0x9153, 0xBA63, 0x9154, 0xBA66,
+	0x9155, 0xBA6A, 0x9156, 0xBA6B, 0x9157, 0xBA6C, 0x9158, 0xBA6D,
+	0x9159, 0xBA6E, 0x915A, 0xBA6F, 0x9161, 0xBA72, 0x9162, 0xBA73,
+	0x9163, 0xBA75, 0x9164, 0xBA76, 0x9165, 0xBA77, 0x9166, 0xBA79,
+	0x9167, 0xBA7A, 0x9168, 0xBA7B, 0x9169, 0xBA7C, 0x916A, 0xBA7D,
+	0x916B, 0xBA7E, 0x916C, 0xBA7F, 0x916D, 0xBA80, 0x916E, 0xBA81,
+	0x916F, 0xBA82, 0x9170, 0xBA86, 0x9171, 0xBA88, 0x9172, 0xBA89,
+	0x9173, 0xBA8A, 0x9174, 0xBA8B, 0x9175, 0xBA8D, 0x9176, 0xBA8E,
+	0x9177, 0xBA8F, 0x9178, 0xBA90, 0x9179, 0xBA91, 0x917A, 0xBA92,
+	0x9181, 0xBA93, 0x9182, 0xBA94, 0x9183, 0xBA95, 0x9184, 0xBA96,
+	0x9185, 0xBA97, 0x9186, 0xBA98, 0x9187, 0xBA99, 0x9188, 0xBA9A,
+	0x9189, 0xBA9B, 0x918A, 0xBA9C, 0x918B, 0xBA9D, 0x918C, 0xBA9E,
+	0x918D, 0xBA9F, 0x918E, 0xBAA0, 0x918F, 0xBAA1, 0x9190, 0xBAA2,
+	0x9191, 0xBAA3, 0x9192, 0xBAA4, 0x9193, 0xBAA5, 0x9194, 0xBAA6,
+	0x9195, 0xBAA7, 0x9196, 0xBAAA, 0x9197, 0xBAAD, 0x9198, 0xBAAE,
+	0x9199, 0xBAAF, 0x919A, 0xBAB1, 0x919B, 0xBAB3, 0x919C, 0xBAB4,
+	0x919D, 0xBAB5, 0x919E, 0xBAB6, 0x919F, 0xBAB7, 0x91A0, 0xBABA,
+	0x91A1, 0xBABC, 0x91A2, 0xBABE, 0x91A3, 0xBABF, 0x91A4, 0xBAC0,
+	0x91A5, 0xBAC1, 0x91A6, 0xBAC2, 0x91A7, 0xBAC3, 0x91A8, 0xBAC5,
+	0x91A9, 0xBAC6, 0x91AA, 0xBAC7, 0x91AB, 0xBAC9, 0x91AC, 0xBACA,
+	0x91AD, 0xBACB, 0x91AE, 0xBACC, 0x91AF, 0xBACD, 0x91B0, 0xBACE,
+	0x91B1, 0xBACF, 0x91B2, 0xBAD0, 0x91B3, 0xBAD1, 0x91B4, 0xBAD2,
+	0x91B5, 0xBAD3, 0x91B6, 0xBAD4, 0x91B7, 0xBAD5, 0x91B8, 0xBAD6,
+	0x91B9, 0xBAD7, 0x91BA, 0xBADA, 0x91BB, 0xBADB, 0x91BC, 0xBADC,
+	0x91BD, 0xBADD, 0x91BE, 0xBADE, 0x91BF, 0xBADF, 0x91C0, 0xBAE0,
+	0x91C1, 0xBAE1, 0x91C2, 0xBAE2, 0x91C3, 0xBAE3, 0x91C4, 0xBAE4,
+	0x91C5, 0xBAE5, 0x91C6, 0xBAE6, 0x91C7, 0xBAE7, 0x91C8, 0xBAE8,
+	0x91C9, 0xBAE9, 0x91CA, 0xBAEA, 0x91CB, 0xBAEB, 0x91CC, 0xBAEC,
+	0x91CD, 0xBAED, 0x91CE, 0xBAEE, 0x91CF, 0xBAEF, 0x91D0, 0xBAF0,
+	0x91D1, 0xBAF1, 0x91D2, 0xBAF2, 0x91D3, 0xBAF3, 0x91D4, 0xBAF4,
+	0x91D5, 0xBAF5, 0x91D6, 0xBAF6, 0x91D7, 0xBAF7, 0x91D8, 0xBAF8,
+	0x91D9, 0xBAF9, 0x91DA, 0xBAFA, 0x91DB, 0xBAFB, 0x91DC, 0xBAFD,
+	0x91DD, 0xBAFE, 0x91DE, 0xBAFF, 0x91DF, 0xBB01, 0x91E0, 0xBB02,
+	0x91E1, 0xBB03, 0x91E2, 0xBB05, 0x91E3, 0xBB06, 0x91E4, 0xBB07,
+	0x91E5, 0xBB08, 0x91E6, 0xBB09, 0x91E7, 0xBB0A, 0x91E8, 0xBB0B,
+	0x91E9, 0xBB0C, 0x91EA, 0xBB0E, 0x91EB, 0xBB10, 0x91EC, 0xBB12,
+	0x91ED, 0xBB13, 0x91EE, 0xBB14, 0x91EF, 0xBB15, 0x91F0, 0xBB16,
+	0x91F1, 0xBB17, 0x91F2, 0xBB19, 0x91F3, 0xBB1A, 0x91F4, 0xBB1B,
+	0x91F5, 0xBB1D, 0x91F6, 0xBB1E, 0x91F7, 0xBB1F, 0x91F8, 0xBB21,
+	0x91F9, 0xBB22, 0x91FA, 0xBB23, 0x91FB, 0xBB24, 0x91FC, 0xBB25,
+	0x91FD, 0xBB26, 0x91FE, 0xBB27, 0x9241, 0xBB28, 0x9242, 0xBB2A,
+	0x9243, 0xBB2C, 0x9244, 0xBB2D, 0x9245, 0xBB2E, 0x9246, 0xBB2F,
+	0x9247, 0xBB30, 0x9248, 0xBB31, 0x9249, 0xBB32, 0x924A, 0xBB33,
+	0x924B, 0xBB37, 0x924C, 0xBB39, 0x924D, 0xBB3A, 0x924E, 0xBB3F,
+	0x924F, 0xBB40, 0x9250, 0xBB41, 0x9251, 0xBB42, 0x9252, 0xBB43,
+	0x9253, 0xBB46, 0x9254, 0xBB48, 0x9255, 0xBB4A, 0x9256, 0xBB4B,
+	0x9257, 0xBB4C, 0x9258, 0xBB4E, 0x9259, 0xBB51, 0x925A, 0xBB52,
+	0x9261, 0xBB53, 0x9262, 0xBB55, 0x9263, 0xBB56, 0x9264, 0xBB57,
+	0x9265, 0xBB59, 0x9266, 0xBB5A, 0x9267, 0xBB5B, 0x9268, 0xBB5C,
+	0x9269, 0xBB5D, 0x926A, 0xBB5E, 0x926B, 0xBB5F, 0x926C, 0xBB60,
+	0x926D, 0xBB62, 0x926E, 0xBB64, 0x926F, 0xBB65, 0x9270, 0xBB66,
+	0x9271, 0xBB67, 0x9272, 0xBB68, 0x9273, 0xBB69, 0x9274, 0xBB6A,
+	0x9275, 0xBB6B, 0x9276, 0xBB6D, 0x9277, 0xBB6E, 0x9278, 0xBB6F,
+	0x9279, 0xBB70, 0x927A, 0xBB71, 0x9281, 0xBB72, 0x9282, 0xBB73,
+	0x9283, 0xBB74, 0x9284, 0xBB75, 0x9285, 0xBB76, 0x9286, 0xBB77,
+	0x9287, 0xBB78, 0x9288, 0xBB79, 0x9289, 0xBB7A, 0x928A, 0xBB7B,
+	0x928B, 0xBB7C, 0x928C, 0xBB7D, 0x928D, 0xBB7E, 0x928E, 0xBB7F,
+	0x928F, 0xBB80, 0x9290, 0xBB81, 0x9291, 0xBB82, 0x9292, 0xBB83,
+	0x9293, 0xBB84, 0x9294, 0xBB85, 0x9295, 0xBB86, 0x9296, 0xBB87,
+	0x9297, 0xBB89, 0x9298, 0xBB8A, 0x9299, 0xBB8B, 0x929A, 0xBB8D,
+	0x929B, 0xBB8E, 0x929C, 0xBB8F, 0x929D, 0xBB91, 0x929E, 0xBB92,
+	0x929F, 0xBB93, 0x92A0, 0xBB94, 0x92A1, 0xBB95, 0x92A2, 0xBB96,
+	0x92A3, 0xBB97, 0x92A4, 0xBB98, 0x92A5, 0xBB99, 0x92A6, 0xBB9A,
+	0x92A7, 0xBB9B, 0x92A8, 0xBB9C, 0x92A9, 0xBB9D, 0x92AA, 0xBB9E,
+	0x92AB, 0xBB9F, 0x92AC, 0xBBA0, 0x92AD, 0xBBA1, 0x92AE, 0xBBA2,
+	0x92AF, 0xBBA3, 0x92B0, 0xBBA5, 0x92B1, 0xBBA6, 0x92B2, 0xBBA7,
+	0x92B3, 0xBBA9, 0x92B4, 0xBBAA, 0x92B5, 0xBBAB, 0x92B6, 0xBBAD,
+	0x92B7, 0xBBAE, 0x92B8, 0xBBAF, 0x92B9, 0xBBB0, 0x92BA, 0xBBB1,
+	0x92BB, 0xBBB2, 0x92BC, 0xBBB3, 0x92BD, 0xBBB5, 0x92BE, 0xBBB6,
+	0x92BF, 0xBBB8, 0x92C0, 0xBBB9, 0x92C1, 0xBBBA, 0x92C2, 0xBBBB,
+	0x92C3, 0xBBBC, 0x92C4, 0xBBBD, 0x92C5, 0xBBBE, 0x92C6, 0xBBBF,
+	0x92C7, 0xBBC1, 0x92C8, 0xBBC2, 0x92C9, 0xBBC3, 0x92CA, 0xBBC5,
+	0x92CB, 0xBBC6, 0x92CC, 0xBBC7, 0x92CD, 0xBBC9, 0x92CE, 0xBBCA,
+	0x92CF, 0xBBCB, 0x92D0, 0xBBCC, 0x92D1, 0xBBCD, 0x92D2, 0xBBCE,
+	0x92D3, 0xBBCF, 0x92D4, 0xBBD1, 0x92D5, 0xBBD2, 0x92D6, 0xBBD4,
+	0x92D7, 0xBBD5, 0x92D8, 0xBBD6, 0x92D9, 0xBBD7, 0x92DA, 0xBBD8,
+	0x92DB, 0xBBD9, 0x92DC, 0xBBDA, 0x92DD, 0xBBDB, 0x92DE, 0xBBDC,
+	0x92DF, 0xBBDD, 0x92E0, 0xBBDE, 0x92E1, 0xBBDF, 0x92E2, 0xBBE0,
+	0x92E3, 0xBBE1, 0x92E4, 0xBBE2, 0x92E5, 0xBBE3, 0x92E6, 0xBBE4,
+	0x92E7, 0xBBE5, 0x92E8, 0xBBE6, 0x92E9, 0xBBE7, 0x92EA, 0xBBE8,
+	0x92EB, 0xBBE9, 0x92EC, 0xBBEA, 0x92ED, 0xBBEB, 0x92EE, 0xBBEC,
+	0x92EF, 0xBBED, 0x92F0, 0xBBEE, 0x92F1, 0xBBEF, 0x92F2, 0xBBF0,
+	0x92F3, 0xBBF1, 0x92F4, 0xBBF2, 0x92F5, 0xBBF3, 0x92F6, 0xBBF4,
+	0x92F7, 0xBBF5, 0x92F8, 0xBBF6, 0x92F9, 0xBBF7, 0x92FA, 0xBBFA,
+	0x92FB, 0xBBFB, 0x92FC, 0xBBFD, 0x92FD, 0xBBFE, 0x92FE, 0xBC01,
+	0x9341, 0xBC03, 0x9342, 0xBC04, 0x9343, 0xBC05, 0x9344, 0xBC06,
+	0x9345, 0xBC07, 0x9346, 0xBC0A, 0x9347, 0xBC0E, 0x9348, 0xBC10,
+	0x9349, 0xBC12, 0x934A, 0xBC13, 0x934B, 0xBC19, 0x934C, 0xBC1A,
+	0x934D, 0xBC20, 0x934E, 0xBC21, 0x934F, 0xBC22, 0x9350, 0xBC23,
+	0x9351, 0xBC26, 0x9352, 0xBC28, 0x9353, 0xBC2A, 0x9354, 0xBC2B,
+	0x9355, 0xBC2C, 0x9356, 0xBC2E, 0x9357, 0xBC2F, 0x9358, 0xBC32,
+	0x9359, 0xBC33, 0x935A, 0xBC35, 0x9361, 0xBC36, 0x9362, 0xBC37,
+	0x9363, 0xBC39, 0x9364, 0xBC3A, 0x9365, 0xBC3B, 0x9366, 0xBC3C,
+	0x9367, 0xBC3D, 0x9368, 0xBC3E, 0x9369, 0xBC3F, 0x936A, 0xBC42,
+	0x936B, 0xBC46, 0x936C, 0xBC47, 0x936D, 0xBC48, 0x936E, 0xBC4A,
+	0x936F, 0xBC4B, 0x9370, 0xBC4E, 0x9371, 0xBC4F, 0x9372, 0xBC51,
+	0x9373, 0xBC52, 0x9374, 0xBC53, 0x9375, 0xBC54, 0x9376, 0xBC55,
+	0x9377, 0xBC56, 0x9378, 0xBC57, 0x9379, 0xBC58, 0x937A, 0xBC59,
+	0x9381, 0xBC5A, 0x9382, 0xBC5B, 0x9383, 0xBC5C, 0x9384, 0xBC5E,
+	0x9385, 0xBC5F, 0x9386, 0xBC60, 0x9387, 0xBC61, 0x9388, 0xBC62,
+	0x9389, 0xBC63, 0x938A, 0xBC64, 0x938B, 0xBC65, 0x938C, 0xBC66,
+	0x938D, 0xBC67, 0x938E, 0xBC68, 0x938F, 0xBC69, 0x9390, 0xBC6A,
+	0x9391, 0xBC6B, 0x9392, 0xBC6C, 0x9393, 0xBC6D, 0x9394, 0xBC6E,
+	0x9395, 0xBC6F, 0x9396, 0xBC70, 0x9397, 0xBC71, 0x9398, 0xBC72,
+	0x9399, 0xBC73, 0x939A, 0xBC74, 0x939B, 0xBC75, 0x939C, 0xBC76,
+	0x939D, 0xBC77, 0x939E, 0xBC78, 0x939F, 0xBC79, 0x93A0, 0xBC7A,
+	0x93A1, 0xBC7B, 0x93A2, 0xBC7C, 0x93A3, 0xBC7D, 0x93A4, 0xBC7E,
+	0x93A5, 0xBC7F, 0x93A6, 0xBC80, 0x93A7, 0xBC81, 0x93A8, 0xBC82,
+	0x93A9, 0xBC83, 0x93AA, 0xBC86, 0x93AB, 0xBC87, 0x93AC, 0xBC89,
+	0x93AD, 0xBC8A, 0x93AE, 0xBC8D, 0x93AF, 0xBC8F, 0x93B0, 0xBC90,
+	0x93B1, 0xBC91, 0x93B2, 0xBC92, 0x93B3, 0xBC93, 0x93B4, 0xBC96,
+	0x93B5, 0xBC98, 0x93B6, 0xBC9B, 0x93B7, 0xBC9C, 0x93B8, 0xBC9D,
+	0x93B9, 0xBC9E, 0x93BA, 0xBC9F, 0x93BB, 0xBCA2, 0x93BC, 0xBCA3,
+	0x93BD, 0xBCA5, 0x93BE, 0xBCA6, 0x93BF, 0xBCA9, 0x93C0, 0xBCAA,
+	0x93C1, 0xBCAB, 0x93C2, 0xBCAC, 0x93C3, 0xBCAD, 0x93C4, 0xBCAE,
+	0x93C5, 0xBCAF, 0x93C6, 0xBCB2, 0x93C7, 0xBCB6, 0x93C8, 0xBCB7,
+	0x93C9, 0xBCB8, 0x93CA, 0xBCB9, 0x93CB, 0xBCBA, 0x93CC, 0xBCBB,
+	0x93CD, 0xBCBE, 0x93CE, 0xBCBF, 0x93CF, 0xBCC1, 0x93D0, 0xBCC2,
+	0x93D1, 0xBCC3, 0x93D2, 0xBCC5, 0x93D3, 0xBCC6, 0x93D4, 0xBCC7,
+	0x93D5, 0xBCC8, 0x93D6, 0xBCC9, 0x93D7, 0xBCCA, 0x93D8, 0xBCCB,
+	0x93D9, 0xBCCC, 0x93DA, 0xBCCE, 0x93DB, 0xBCD2, 0x93DC, 0xBCD3,
+	0x93DD, 0xBCD4, 0x93DE, 0xBCD6, 0x93DF, 0xBCD7, 0x93E0, 0xBCD9,
+	0x93E1, 0xBCDA, 0x93E2, 0xBCDB, 0x93E3, 0xBCDD, 0x93E4, 0xBCDE,
+	0x93E5, 0xBCDF, 0x93E6, 0xBCE0, 0x93E7, 0xBCE1, 0x93E8, 0xBCE2,
+	0x93E9, 0xBCE3, 0x93EA, 0xBCE4, 0x93EB, 0xBCE5, 0x93EC, 0xBCE6,
+	0x93ED, 0xBCE7, 0x93EE, 0xBCE8, 0x93EF, 0xBCE9, 0x93F0, 0xBCEA,
+	0x93F1, 0xBCEB, 0x93F2, 0xBCEC, 0x93F3, 0xBCED, 0x93F4, 0xBCEE,
+	0x93F5, 0xBCEF, 0x93F6, 0xBCF0, 0x93F7, 0xBCF1, 0x93F8, 0xBCF2,
+	0x93F9, 0xBCF3, 0x93FA, 0xBCF7, 0x93FB, 0xBCF9, 0x93FC, 0xBCFA,
+	0x93FD, 0xBCFB, 0x93FE, 0xBCFD, 0x9441, 0xBCFE, 0x9442, 0xBCFF,
+	0x9443, 0xBD00, 0x9444, 0xBD01, 0x9445, 0xBD02, 0x9446, 0xBD03,
+	0x9447, 0xBD06, 0x9448, 0xBD08, 0x9449, 0xBD0A, 0x944A, 0xBD0B,
+	0x944B, 0xBD0C, 0x944C, 0xBD0D, 0x944D, 0xBD0E, 0x944E, 0xBD0F,
+	0x944F, 0xBD11, 0x9450, 0xBD12, 0x9451, 0xBD13, 0x9452, 0xBD15,
+	0x9453, 0xBD16, 0x9454, 0xBD17, 0x9455, 0xBD18, 0x9456, 0xBD19,
+	0x9457, 0xBD1A, 0x9458, 0xBD1B, 0x9459, 0xBD1C, 0x945A, 0xBD1D,
+	0x9461, 0xBD1E, 0x9462, 0xBD1F, 0x9463, 0xBD20, 0x9464, 0xBD21,
+	0x9465, 0xBD22, 0x9466, 0xBD23, 0x9467, 0xBD25, 0x9468, 0xBD26,
+	0x9469, 0xBD27, 0x946A, 0xBD28, 0x946B, 0xBD29, 0x946C, 0xBD2A,
+	0x946D, 0xBD2B, 0x946E, 0xBD2D, 0x946F, 0xBD2E, 0x9470, 0xBD2F,
+	0x9471, 0xBD30, 0x9472, 0xBD31, 0x9473, 0xBD32, 0x9474, 0xBD33,
+	0x9475, 0xBD34, 0x9476, 0xBD35, 0x9477, 0xBD36, 0x9478, 0xBD37,
+	0x9479, 0xBD38, 0x947A, 0xBD39, 0x9481, 0xBD3A, 0x9482, 0xBD3B,
+	0x9483, 0xBD3C, 0x9484, 0xBD3D, 0x9485, 0xBD3E, 0x9486, 0xBD3F,
+	0x9487, 0xBD41, 0x9488, 0xBD42, 0x9489, 0xBD43, 0x948A, 0xBD44,
+	0x948B, 0xBD45, 0x948C, 0xBD46, 0x948D, 0xBD47, 0x948E, 0xBD4A,
+	0x948F, 0xBD4B, 0x9490, 0xBD4D, 0x9491, 0xBD4E, 0x9492, 0xBD4F,
+	0x9493, 0xBD51, 0x9494, 0xBD52, 0x9495, 0xBD53, 0x9496, 0xBD54,
+	0x9497, 0xBD55, 0x9498, 0xBD56, 0x9499, 0xBD57, 0x949A, 0xBD5A,
+	0x949B, 0xBD5B, 0x949C, 0xBD5C, 0x949D, 0xBD5D, 0x949E, 0xBD5E,
+	0x949F, 0xBD5F, 0x94A0, 0xBD60, 0x94A1, 0xBD61, 0x94A2, 0xBD62,
+	0x94A3, 0xBD63, 0x94A4, 0xBD65, 0x94A5, 0xBD66, 0x94A6, 0xBD67,
+	0x94A7, 0xBD69, 0x94A8, 0xBD6A, 0x94A9, 0xBD6B, 0x94AA, 0xBD6C,
+	0x94AB, 0xBD6D, 0x94AC, 0xBD6E, 0x94AD, 0xBD6F, 0x94AE, 0xBD70,
+	0x94AF, 0xBD71, 0x94B0, 0xBD72, 0x94B1, 0xBD73, 0x94B2, 0xBD74,
+	0x94B3, 0xBD75, 0x94B4, 0xBD76, 0x94B5, 0xBD77, 0x94B6, 0xBD78,
+	0x94B7, 0xBD79, 0x94B8, 0xBD7A, 0x94B9, 0xBD7B, 0x94BA, 0xBD7C,
+	0x94BB, 0xBD7D, 0x94BC, 0xBD7E, 0x94BD, 0xBD7F, 0x94BE, 0xBD82,
+	0x94BF, 0xBD83, 0x94C0, 0xBD85, 0x94C1, 0xBD86, 0x94C2, 0xBD8B,
+	0x94C3, 0xBD8C, 0x94C4, 0xBD8D, 0x94C5, 0xBD8E, 0x94C6, 0xBD8F,
+	0x94C7, 0xBD92, 0x94C8, 0xBD94, 0x94C9, 0xBD96, 0x94CA, 0xBD97,
+	0x94CB, 0xBD98, 0x94CC, 0xBD9B, 0x94CD, 0xBD9D, 0x94CE, 0xBD9E,
+	0x94CF, 0xBD9F, 0x94D0, 0xBDA0, 0x94D1, 0xBDA1, 0x94D2, 0xBDA2,
+	0x94D3, 0xBDA3, 0x94D4, 0xBDA5, 0x94D5, 0xBDA6, 0x94D6, 0xBDA7,
+	0x94D7, 0xBDA8, 0x94D8, 0xBDA9, 0x94D9, 0xBDAA, 0x94DA, 0xBDAB,
+	0x94DB, 0xBDAC, 0x94DC, 0xBDAD, 0x94DD, 0xBDAE, 0x94DE, 0xBDAF,
+	0x94DF, 0xBDB1, 0x94E0, 0xBDB2, 0x94E1, 0xBDB3, 0x94E2, 0xBDB4,
+	0x94E3, 0xBDB5, 0x94E4, 0xBDB6, 0x94E5, 0xBDB7, 0x94E6, 0xBDB9,
+	0x94E7, 0xBDBA, 0x94E8, 0xBDBB, 0x94E9, 0xBDBC, 0x94EA, 0xBDBD,
+	0x94EB, 0xBDBE, 0x94EC, 0xBDBF, 0x94ED, 0xBDC0, 0x94EE, 0xBDC1,
+	0x94EF, 0xBDC2, 0x94F0, 0xBDC3, 0x94F1, 0xBDC4, 0x94F2, 0xBDC5,
+	0x94F3, 0xBDC6, 0x94F4, 0xBDC7, 0x94F5, 0xBDC8, 0x94F6, 0xBDC9,
+	0x94F7, 0xBDCA, 0x94F8, 0xBDCB, 0x94F9, 0xBDCC, 0x94FA, 0xBDCD,
+	0x94FB, 0xBDCE, 0x94FC, 0xBDCF, 0x94FD, 0xBDD0, 0x94FE, 0xBDD1,
+	0x9541, 0xBDD2, 0x9542, 0xBDD3, 0x9543, 0xBDD6, 0x9544, 0xBDD7,
+	0x9545, 0xBDD9, 0x9546, 0xBDDA, 0x9547, 0xBDDB, 0x9548, 0xBDDD,
+	0x9549, 0xBDDE, 0x954A, 0xBDDF, 0x954B, 0xBDE0, 0x954C, 0xBDE1,
+	0x954D, 0xBDE2, 0x954E, 0xBDE3, 0x954F, 0xBDE4, 0x9550, 0xBDE5,
+	0x9551, 0xBDE6, 0x9552, 0xBDE7, 0x9553, 0xBDE8, 0x9554, 0xBDEA,
+	0x9555, 0xBDEB, 0x9556, 0xBDEC, 0x9557, 0xBDED, 0x9558, 0xBDEE,
+	0x9559, 0xBDEF, 0x955A, 0xBDF1, 0x9561, 0xBDF2, 0x9562, 0xBDF3,
+	0x9563, 0xBDF5, 0x9564, 0xBDF6, 0x9565, 0xBDF7, 0x9566, 0xBDF9,
+	0x9567, 0xBDFA, 0x9568, 0xBDFB, 0x9569, 0xBDFC, 0x956A, 0xBDFD,
+	0x956B, 0xBDFE, 0x956C, 0xBDFF, 0x956D, 0xBE01, 0x956E, 0xBE02,
+	0x956F, 0xBE04, 0x9570, 0xBE06, 0x9571, 0xBE07, 0x9572, 0xBE08,
+	0x9573, 0xBE09, 0x9574, 0xBE0A, 0x9575, 0xBE0B, 0x9576, 0xBE0E,
+	0x9577, 0xBE0F, 0x9578, 0xBE11, 0x9579, 0xBE12, 0x957A, 0xBE13,
+	0x9581, 0xBE15, 0x9582, 0xBE16, 0x9583, 0xBE17, 0x9584, 0xBE18,
+	0x9585, 0xBE19, 0x9586, 0xBE1A, 0x9587, 0xBE1B, 0x9588, 0xBE1E,
+	0x9589, 0xBE20, 0x958A, 0xBE21, 0x958B, 0xBE22, 0x958C, 0xBE23,
+	0x958D, 0xBE24, 0x958E, 0xBE25, 0x958F, 0xBE26, 0x9590, 0xBE27,
+	0x9591, 0xBE28, 0x9592, 0xBE29, 0x9593, 0xBE2A, 0x9594, 0xBE2B,
+	0x9595, 0xBE2C, 0x9596, 0xBE2D, 0x9597, 0xBE2E, 0x9598, 0xBE2F,
+	0x9599, 0xBE30, 0x959A, 0xBE31, 0x959B, 0xBE32, 0x959C, 0xBE33,
+	0x959D, 0xBE34, 0x959E, 0xBE35, 0x959F, 0xBE36, 0x95A0, 0xBE37,
+	0x95A1, 0xBE38, 0x95A2, 0xBE39, 0x95A3, 0xBE3A, 0x95A4, 0xBE3B,
+	0x95A5, 0xBE3C, 0x95A6, 0xBE3D, 0x95A7, 0xBE3E, 0x95A8, 0xBE3F,
+	0x95A9, 0xBE40, 0x95AA, 0xBE41, 0x95AB, 0xBE42, 0x95AC, 0xBE43,
+	0x95AD, 0xBE46, 0x95AE, 0xBE47, 0x95AF, 0xBE49, 0x95B0, 0xBE4A,
+	0x95B1, 0xBE4B, 0x95B2, 0xBE4D, 0x95B3, 0xBE4F, 0x95B4, 0xBE50,
+	0x95B5, 0xBE51, 0x95B6, 0xBE52, 0x95B7, 0xBE53, 0x95B8, 0xBE56,
+	0x95B9, 0xBE58, 0x95BA, 0xBE5C, 0x95BB, 0xBE5D, 0x95BC, 0xBE5E,
+	0x95BD, 0xBE5F, 0x95BE, 0xBE62, 0x95BF, 0xBE63, 0x95C0, 0xBE65,
+	0x95C1, 0xBE66, 0x95C2, 0xBE67, 0x95C3, 0xBE69, 0x95C4, 0xBE6B,
+	0x95C5, 0xBE6C, 0x95C6, 0xBE6D, 0x95C7, 0xBE6E, 0x95C8, 0xBE6F,
+	0x95C9, 0xBE72, 0x95CA, 0xBE76, 0x95CB, 0xBE77, 0x95CC, 0xBE78,
+	0x95CD, 0xBE79, 0x95CE, 0xBE7A, 0x95CF, 0xBE7E, 0x95D0, 0xBE7F,
+	0x95D1, 0xBE81, 0x95D2, 0xBE82, 0x95D3, 0xBE83, 0x95D4, 0xBE85,
+	0x95D5, 0xBE86, 0x95D6, 0xBE87, 0x95D7, 0xBE88, 0x95D8, 0xBE89,
+	0x95D9, 0xBE8A, 0x95DA, 0xBE8B, 0x95DB, 0xBE8E, 0x95DC, 0xBE92,
+	0x95DD, 0xBE93, 0x95DE, 0xBE94, 0x95DF, 0xBE95, 0x95E0, 0xBE96,
+	0x95E1, 0xBE97, 0x95E2, 0xBE9A, 0x95E3, 0xBE9B, 0x95E4, 0xBE9C,
+	0x95E5, 0xBE9D, 0x95E6, 0xBE9E, 0x95E7, 0xBE9F, 0x95E8, 0xBEA0,
+	0x95E9, 0xBEA1, 0x95EA, 0xBEA2, 0x95EB, 0xBEA3, 0x95EC, 0xBEA4,
+	0x95ED, 0xBEA5, 0x95EE, 0xBEA6, 0x95EF, 0xBEA7, 0x95F0, 0xBEA9,
+	0x95F1, 0xBEAA, 0x95F2, 0xBEAB, 0x95F3, 0xBEAC, 0x95F4, 0xBEAD,
+	0x95F5, 0xBEAE, 0x95F6, 0xBEAF, 0x95F7, 0xBEB0, 0x95F8, 0xBEB1,
+	0x95F9, 0xBEB2, 0x95FA, 0xBEB3, 0x95FB, 0xBEB4, 0x95FC, 0xBEB5,
+	0x95FD, 0xBEB6, 0x95FE, 0xBEB7, 0x9641, 0xBEB8, 0x9642, 0xBEB9,
+	0x9643, 0xBEBA, 0x9644, 0xBEBB, 0x9645, 0xBEBC, 0x9646, 0xBEBD,
+	0x9647, 0xBEBE, 0x9648, 0xBEBF, 0x9649, 0xBEC0, 0x964A, 0xBEC1,
+	0x964B, 0xBEC2, 0x964C, 0xBEC3, 0x964D, 0xBEC4, 0x964E, 0xBEC5,
+	0x964F, 0xBEC6, 0x9650, 0xBEC7, 0x9651, 0xBEC8, 0x9652, 0xBEC9,
+	0x9653, 0xBECA, 0x9654, 0xBECB, 0x9655, 0xBECC, 0x9656, 0xBECD,
+	0x9657, 0xBECE, 0x9658, 0xBECF, 0x9659, 0xBED2, 0x965A, 0xBED3,
+	0x9661, 0xBED5, 0x9662, 0xBED6, 0x9663, 0xBED9, 0x9664, 0xBEDA,
+	0x9665, 0xBEDB, 0x9666, 0xBEDC, 0x9667, 0xBEDD, 0x9668, 0xBEDE,
+	0x9669, 0xBEDF, 0x966A, 0xBEE1, 0x966B, 0xBEE2, 0x966C, 0xBEE6,
+	0x966D, 0xBEE7, 0x966E, 0xBEE8, 0x966F, 0xBEE9, 0x9670, 0xBEEA,
+	0x9671, 0xBEEB, 0x9672, 0xBEED, 0x9673, 0xBEEE, 0x9674, 0xBEEF,
+	0x9675, 0xBEF0, 0x9676, 0xBEF1, 0x9677, 0xBEF2, 0x9678, 0xBEF3,
+	0x9679, 0xBEF4, 0x967A, 0xBEF5, 0x9681, 0xBEF6, 0x9682, 0xBEF7,
+	0x9683, 0xBEF8, 0x9684, 0xBEF9, 0x9685, 0xBEFA, 0x9686, 0xBEFB,
+	0x9687, 0xBEFC, 0x9688, 0xBEFD, 0x9689, 0xBEFE, 0x968A, 0xBEFF,
+	0x968B, 0xBF00, 0x968C, 0xBF02, 0x968D, 0xBF03, 0x968E, 0xBF04,
+	0x968F, 0xBF05, 0x9690, 0xBF06, 0x9691, 0xBF07, 0x9692, 0xBF0A,
+	0x9693, 0xBF0B, 0x9694, 0xBF0C, 0x9695, 0xBF0D, 0x9696, 0xBF0E,
+	0x9697, 0xBF0F, 0x9698, 0xBF10, 0x9699, 0xBF11, 0x969A, 0xBF12,
+	0x969B, 0xBF13, 0x969C, 0xBF14, 0x969D, 0xBF15, 0x969E, 0xBF16,
+	0x969F, 0xBF17, 0x96A0, 0xBF1A, 0x96A1, 0xBF1E, 0x96A2, 0xBF1F,
+	0x96A3, 0xBF20, 0x96A4, 0xBF21, 0x96A5, 0xBF22, 0x96A6, 0xBF23,
+	0x96A7, 0xBF24, 0x96A8, 0xBF25, 0x96A9, 0xBF26, 0x96AA, 0xBF27,
+	0x96AB, 0xBF28, 0x96AC, 0xBF29, 0x96AD, 0xBF2A, 0x96AE, 0xBF2B,
+	0x96AF, 0xBF2C, 0x96B0, 0xBF2D, 0x96B1, 0xBF2E, 0x96B2, 0xBF2F,
+	0x96B3, 0xBF30, 0x96B4, 0xBF31, 0x96B5, 0xBF32, 0x96B6, 0xBF33,
+	0x96B7, 0xBF34, 0x96B8, 0xBF35, 0x96B9, 0xBF36, 0x96BA, 0xBF37,
+	0x96BB, 0xBF38, 0x96BC, 0xBF39, 0x96BD, 0xBF3A, 0x96BE, 0xBF3B,
+	0x96BF, 0xBF3C, 0x96C0, 0xBF3D, 0x96C1, 0xBF3E, 0x96C2, 0xBF3F,
+	0x96C3, 0xBF42, 0x96C4, 0xBF43, 0x96C5, 0xBF45, 0x96C6, 0xBF46,
+	0x96C7, 0xBF47, 0x96C8, 0xBF49, 0x96C9, 0xBF4A, 0x96CA, 0xBF4B,
+	0x96CB, 0xBF4C, 0x96CC, 0xBF4D, 0x96CD, 0xBF4E, 0x96CE, 0xBF4F,
+	0x96CF, 0xBF52, 0x96D0, 0xBF53, 0x96D1, 0xBF54, 0x96D2, 0xBF56,
+	0x96D3, 0xBF57, 0x96D4, 0xBF58, 0x96D5, 0xBF59, 0x96D6, 0xBF5A,
+	0x96D7, 0xBF5B, 0x96D8, 0xBF5C, 0x96D9, 0xBF5D, 0x96DA, 0xBF5E,
+	0x96DB, 0xBF5F, 0x96DC, 0xBF60, 0x96DD, 0xBF61, 0x96DE, 0xBF62,
+	0x96DF, 0xBF63, 0x96E0, 0xBF64, 0x96E1, 0xBF65, 0x96E2, 0xBF66,
+	0x96E3, 0xBF67, 0x96E4, 0xBF68, 0x96E5, 0xBF69, 0x96E6, 0xBF6A,
+	0x96E7, 0xBF6B, 0x96E8, 0xBF6C, 0x96E9, 0xBF6D, 0x96EA, 0xBF6E,
+	0x96EB, 0xBF6F, 0x96EC, 0xBF70, 0x96ED, 0xBF71, 0x96EE, 0xBF72,
+	0x96EF, 0xBF73, 0x96F0, 0xBF74, 0x96F1, 0xBF75, 0x96F2, 0xBF76,
+	0x96F3, 0xBF77, 0x96F4, 0xBF78, 0x96F5, 0xBF79, 0x96F6, 0xBF7A,
+	0x96F7, 0xBF7B, 0x96F8, 0xBF7C, 0x96F9, 0xBF7D, 0x96FA, 0xBF7E,
+	0x96FB, 0xBF7F, 0x96FC, 0xBF80, 0x96FD, 0xBF81, 0x96FE, 0xBF82,
+	0x9741, 0xBF83, 0x9742, 0xBF84, 0x9743, 0xBF85, 0x9744, 0xBF86,
+	0x9745, 0xBF87, 0x9746, 0xBF88, 0x9747, 0xBF89, 0x9748, 0xBF8A,
+	0x9749, 0xBF8B, 0x974A, 0xBF8C, 0x974B, 0xBF8D, 0x974C, 0xBF8E,
+	0x974D, 0xBF8F, 0x974E, 0xBF90, 0x974F, 0xBF91, 0x9750, 0xBF92,
+	0x9751, 0xBF93, 0x9752, 0xBF95, 0x9753, 0xBF96, 0x9754, 0xBF97,
+	0x9755, 0xBF98, 0x9756, 0xBF99, 0x9757, 0xBF9A, 0x9758, 0xBF9B,
+	0x9759, 0xBF9C, 0x975A, 0xBF9D, 0x9761, 0xBF9E, 0x9762, 0xBF9F,
+	0x9763, 0xBFA0, 0x9764, 0xBFA1, 0x9765, 0xBFA2, 0x9766, 0xBFA3,
+	0x9767, 0xBFA4, 0x9768, 0xBFA5, 0x9769, 0xBFA6, 0x976A, 0xBFA7,
+	0x976B, 0xBFA8, 0x976C, 0xBFA9, 0x976D, 0xBFAA, 0x976E, 0xBFAB,
+	0x976F, 0xBFAC, 0x9770, 0xBFAD, 0x9771, 0xBFAE, 0x9772, 0xBFAF,
+	0x9773, 0xBFB1, 0x9774, 0xBFB2, 0x9775, 0xBFB3, 0x9776, 0xBFB4,
+	0x9777, 0xBFB5, 0x9778, 0xBFB6, 0x9779, 0xBFB7, 0x977A, 0xBFB8,
+	0x9781, 0xBFB9, 0x9782, 0xBFBA, 0x9783, 0xBFBB, 0x9784, 0xBFBC,
+	0x9785, 0xBFBD, 0x9786, 0xBFBE, 0x9787, 0xBFBF, 0x9788, 0xBFC0,
+	0x9789, 0xBFC1, 0x978A, 0xBFC2, 0x978B, 0xBFC3, 0x978C, 0xBFC4,
+	0x978D, 0xBFC6, 0x978E, 0xBFC7, 0x978F, 0xBFC8, 0x9790, 0xBFC9,
+	0x9791, 0xBFCA, 0x9792, 0xBFCB, 0x9793, 0xBFCE, 0x9794, 0xBFCF,
+	0x9795, 0xBFD1, 0x9796, 0xBFD2, 0x9797, 0xBFD3, 0x9798, 0xBFD5,
+	0x9799, 0xBFD6, 0x979A, 0xBFD7, 0x979B, 0xBFD8, 0x979C, 0xBFD9,
+	0x979D, 0xBFDA, 0x979E, 0xBFDB, 0x979F, 0xBFDD, 0x97A0, 0xBFDE,
+	0x97A1, 0xBFE0, 0x97A2, 0xBFE2, 0x97A3, 0xBFE3, 0x97A4, 0xBFE4,
+	0x97A5, 0xBFE5, 0x97A6, 0xBFE6, 0x97A7, 0xBFE7, 0x97A8, 0xBFE8,
+	0x97A9, 0xBFE9, 0x97AA, 0xBFEA, 0x97AB, 0xBFEB, 0x97AC, 0xBFEC,
+	0x97AD, 0xBFED, 0x97AE, 0xBFEE, 0x97AF, 0xBFEF, 0x97B0, 0xBFF0,
+	0x97B1, 0xBFF1, 0x97B2, 0xBFF2, 0x97B3, 0xBFF3, 0x97B4, 0xBFF4,
+	0x97B5, 0xBFF5, 0x97B6, 0xBFF6, 0x97B7, 0xBFF7, 0x97B8, 0xBFF8,
+	0x97B9, 0xBFF9, 0x97BA, 0xBFFA, 0x97BB, 0xBFFB, 0x97BC, 0xBFFC,
+	0x97BD, 0xBFFD, 0x97BE, 0xBFFE, 0x97BF, 0xBFFF, 0x97C0, 0xC000,
+	0x97C1, 0xC001, 0x97C2, 0xC002, 0x97C3, 0xC003, 0x97C4, 0xC004,
+	0x97C5, 0xC005, 0x97C6, 0xC006, 0x97C7, 0xC007, 0x97C8, 0xC008,
+	0x97C9, 0xC009, 0x97CA, 0xC00A, 0x97CB, 0xC00B, 0x97CC, 0xC00C,
+	0x97CD, 0xC00D, 0x97CE, 0xC00E, 0x97CF, 0xC00F, 0x97D0, 0xC010,
+	0x97D1, 0xC011, 0x97D2, 0xC012, 0x97D3, 0xC013, 0x97D4, 0xC014,
+	0x97D5, 0xC015, 0x97D6, 0xC016, 0x97D7, 0xC017, 0x97D8, 0xC018,
+	0x97D9, 0xC019, 0x97DA, 0xC01A, 0x97DB, 0xC01B, 0x97DC, 0xC01C,
+	0x97DD, 0xC01D, 0x97DE, 0xC01E, 0x97DF, 0xC01F, 0x97E0, 0xC020,
+	0x97E1, 0xC021, 0x97E2, 0xC022, 0x97E3, 0xC023, 0x97E4, 0xC024,
+	0x97E5, 0xC025, 0x97E6, 0xC026, 0x97E7, 0xC027, 0x97E8, 0xC028,
+	0x97E9, 0xC029, 0x97EA, 0xC02A, 0x97EB, 0xC02B, 0x97EC, 0xC02C,
+	0x97ED, 0xC02D, 0x97EE, 0xC02E, 0x97EF, 0xC02F, 0x97F0, 0xC030,
+	0x97F1, 0xC031, 0x97F2, 0xC032, 0x97F3, 0xC033, 0x97F4, 0xC034,
+	0x97F5, 0xC035, 0x97F6, 0xC036, 0x97F7, 0xC037, 0x97F8, 0xC038,
+	0x97F9, 0xC039, 0x97FA, 0xC03A, 0x97FB, 0xC03B, 0x97FC, 0xC03D,
+	0x97FD, 0xC03E, 0x97FE, 0xC03F, 0x9841, 0xC040, 0x9842, 0xC041,
+	0x9843, 0xC042, 0x9844, 0xC043, 0x9845, 0xC044, 0x9846, 0xC045,
+	0x9847, 0xC046, 0x9848, 0xC047, 0x9849, 0xC048, 0x984A, 0xC049,
+	0x984B, 0xC04A, 0x984C, 0xC04B, 0x984D, 0xC04C, 0x984E, 0xC04D,
+	0x984F, 0xC04E, 0x9850, 0xC04F, 0x9851, 0xC050, 0x9852, 0xC052,
+	0x9853, 0xC053, 0x9854, 0xC054, 0x9855, 0xC055, 0x9856, 0xC056,
+	0x9857, 0xC057, 0x9858, 0xC059, 0x9859, 0xC05A, 0x985A, 0xC05B,
+	0x9861, 0xC05D, 0x9862, 0xC05E, 0x9863, 0xC05F, 0x9864, 0xC061,
+	0x9865, 0xC062, 0x9866, 0xC063, 0x9867, 0xC064, 0x9868, 0xC065,
+	0x9869, 0xC066, 0x986A, 0xC067, 0x986B, 0xC06A, 0x986C, 0xC06B,
+	0x986D, 0xC06C, 0x986E, 0xC06D, 0x986F, 0xC06E, 0x9870, 0xC06F,
+	0x9871, 0xC070, 0x9872, 0xC071, 0x9873, 0xC072, 0x9874, 0xC073,
+	0x9875, 0xC074, 0x9876, 0xC075, 0x9877, 0xC076, 0x9878, 0xC077,
+	0x9879, 0xC078, 0x987A, 0xC079, 0x9881, 0xC07A, 0x9882, 0xC07B,
+	0x9883, 0xC07C, 0x9884, 0xC07D, 0x9885, 0xC07E, 0x9886, 0xC07F,
+	0x9887, 0xC080, 0x9888, 0xC081, 0x9889, 0xC082, 0x988A, 0xC083,
+	0x988B, 0xC084, 0x988C, 0xC085, 0x988D, 0xC086, 0x988E, 0xC087,
+	0x988F, 0xC088, 0x9890, 0xC089, 0x9891, 0xC08A, 0x9892, 0xC08B,
+	0x9893, 0xC08C, 0x9894, 0xC08D, 0x9895, 0xC08E, 0x9896, 0xC08F,
+	0x9897, 0xC092, 0x9898, 0xC093, 0x9899, 0xC095, 0x989A, 0xC096,
+	0x989B, 0xC097, 0x989C, 0xC099, 0x989D, 0xC09A, 0x989E, 0xC09B,
+	0x989F, 0xC09C, 0x98A0, 0xC09D, 0x98A1, 0xC09E, 0x98A2, 0xC09F,
+	0x98A3, 0xC0A2, 0x98A4, 0xC0A4, 0x98A5, 0xC0A6, 0x98A6, 0xC0A7,
+	0x98A7, 0xC0A8, 0x98A8, 0xC0A9, 0x98A9, 0xC0AA, 0x98AA, 0xC0AB,
+	0x98AB, 0xC0AE, 0x98AC, 0xC0B1, 0x98AD, 0xC0B2, 0x98AE, 0xC0B7,
+	0x98AF, 0xC0B8, 0x98B0, 0xC0B9, 0x98B1, 0xC0BA, 0x98B2, 0xC0BB,
+	0x98B3, 0xC0BE, 0x98B4, 0xC0C2, 0x98B5, 0xC0C3, 0x98B6, 0xC0C4,
+	0x98B7, 0xC0C6, 0x98B8, 0xC0C7, 0x98B9, 0xC0CA, 0x98BA, 0xC0CB,
+	0x98BB, 0xC0CD, 0x98BC, 0xC0CE, 0x98BD, 0xC0CF, 0x98BE, 0xC0D1,
+	0x98BF, 0xC0D2, 0x98C0, 0xC0D3, 0x98C1, 0xC0D4, 0x98C2, 0xC0D5,
+	0x98C3, 0xC0D6, 0x98C4, 0xC0D7, 0x98C5, 0xC0DA, 0x98C6, 0xC0DE,
+	0x98C7, 0xC0DF, 0x98C8, 0xC0E0, 0x98C9, 0xC0E1, 0x98CA, 0xC0E2,
+	0x98CB, 0xC0E3, 0x98CC, 0xC0E6, 0x98CD, 0xC0E7, 0x98CE, 0xC0E9,
+	0x98CF, 0xC0EA, 0x98D0, 0xC0EB, 0x98D1, 0xC0ED, 0x98D2, 0xC0EE,
+	0x98D3, 0xC0EF, 0x98D4, 0xC0F0, 0x98D5, 0xC0F1, 0x98D6, 0xC0F2,
+	0x98D7, 0xC0F3, 0x98D8, 0xC0F6, 0x98D9, 0xC0F8, 0x98DA, 0xC0FA,
+	0x98DB, 0xC0FB, 0x98DC, 0xC0FC, 0x98DD, 0xC0FD, 0x98DE, 0xC0FE,
+	0x98DF, 0xC0FF, 0x98E0, 0xC101, 0x98E1, 0xC102, 0x98E2, 0xC103,
+	0x98E3, 0xC105, 0x98E4, 0xC106, 0x98E5, 0xC107, 0x98E6, 0xC109,
+	0x98E7, 0xC10A, 0x98E8, 0xC10B, 0x98E9, 0xC10C, 0x98EA, 0xC10D,
+	0x98EB, 0xC10E, 0x98EC, 0xC10F, 0x98ED, 0xC111, 0x98EE, 0xC112,
+	0x98EF, 0xC113, 0x98F0, 0xC114, 0x98F1, 0xC116, 0x98F2, 0xC117,
+	0x98F3, 0xC118, 0x98F4, 0xC119, 0x98F5, 0xC11A, 0x98F6, 0xC11B,
+	0x98F7, 0xC121, 0x98F8, 0xC122, 0x98F9, 0xC125, 0x98FA, 0xC128,
+	0x98FB, 0xC129, 0x98FC, 0xC12A, 0x98FD, 0xC12B, 0x98FE, 0xC12E,
+	0x9941, 0xC132, 0x9942, 0xC133, 0x9943, 0xC134, 0x9944, 0xC135,
+	0x9945, 0xC137, 0x9946, 0xC13A, 0x9947, 0xC13B, 0x9948, 0xC13D,
+	0x9949, 0xC13E, 0x994A, 0xC13F, 0x994B, 0xC141, 0x994C, 0xC142,
+	0x994D, 0xC143, 0x994E, 0xC144, 0x994F, 0xC145, 0x9950, 0xC146,
+	0x9951, 0xC147, 0x9952, 0xC14A, 0x9953, 0xC14E, 0x9954, 0xC14F,
+	0x9955, 0xC150, 0x9956, 0xC151, 0x9957, 0xC152, 0x9958, 0xC153,
+	0x9959, 0xC156, 0x995A, 0xC157, 0x9961, 0xC159, 0x9962, 0xC15A,
+	0x9963, 0xC15B, 0x9964, 0xC15D, 0x9965, 0xC15E, 0x9966, 0xC15F,
+	0x9967, 0xC160, 0x9968, 0xC161, 0x9969, 0xC162, 0x996A, 0xC163,
+	0x996B, 0xC166, 0x996C, 0xC16A, 0x996D, 0xC16B, 0x996E, 0xC16C,
+	0x996F, 0xC16D, 0x9970, 0xC16E, 0x9971, 0xC16F, 0x9972, 0xC171,
+	0x9973, 0xC172, 0x9974, 0xC173, 0x9975, 0xC175, 0x9976, 0xC176,
+	0x9977, 0xC177, 0x9978, 0xC179, 0x9979, 0xC17A, 0x997A, 0xC17B,
+	0x9981, 0xC17C, 0x9982, 0xC17D, 0x9983, 0xC17E, 0x9984, 0xC17F,
+	0x9985, 0xC180, 0x9986, 0xC181, 0x9987, 0xC182, 0x9988, 0xC183,
+	0x9989, 0xC184, 0x998A, 0xC186, 0x998B, 0xC187, 0x998C, 0xC188,
+	0x998D, 0xC189, 0x998E, 0xC18A, 0x998F, 0xC18B, 0x9990, 0xC18F,
+	0x9991, 0xC191, 0x9992, 0xC192, 0x9993, 0xC193, 0x9994, 0xC195,
+	0x9995, 0xC197, 0x9996, 0xC198, 0x9997, 0xC199, 0x9998, 0xC19A,
+	0x9999, 0xC19B, 0x999A, 0xC19E, 0x999B, 0xC1A0, 0x999C, 0xC1A2,
+	0x999D, 0xC1A3, 0x999E, 0xC1A4, 0x999F, 0xC1A6, 0x99A0, 0xC1A7,
+	0x99A1, 0xC1AA, 0x99A2, 0xC1AB, 0x99A3, 0xC1AD, 0x99A4, 0xC1AE,
+	0x99A5, 0xC1AF, 0x99A6, 0xC1B1, 0x99A7, 0xC1B2, 0x99A8, 0xC1B3,
+	0x99A9, 0xC1B4, 0x99AA, 0xC1B5, 0x99AB, 0xC1B6, 0x99AC, 0xC1B7,
+	0x99AD, 0xC1B8, 0x99AE, 0xC1B9, 0x99AF, 0xC1BA, 0x99B0, 0xC1BB,
+	0x99B1, 0xC1BC, 0x99B2, 0xC1BE, 0x99B3, 0xC1BF, 0x99B4, 0xC1C0,
+	0x99B5, 0xC1C1, 0x99B6, 0xC1C2, 0x99B7, 0xC1C3, 0x99B8, 0xC1C5,
+	0x99B9, 0xC1C6, 0x99BA, 0xC1C7, 0x99BB, 0xC1C9, 0x99BC, 0xC1CA,
+	0x99BD, 0xC1CB, 0x99BE, 0xC1CD, 0x99BF, 0xC1CE, 0x99C0, 0xC1CF,
+	0x99C1, 0xC1D0, 0x99C2, 0xC1D1, 0x99C3, 0xC1D2, 0x99C4, 0xC1D3,
+	0x99C5, 0xC1D5, 0x99C6, 0xC1D6, 0x99C7, 0xC1D9, 0x99C8, 0xC1DA,
+	0x99C9, 0xC1DB, 0x99CA, 0xC1DC, 0x99CB, 0xC1DD, 0x99CC, 0xC1DE,
+	0x99CD, 0xC1DF, 0x99CE, 0xC1E1, 0x99CF, 0xC1E2, 0x99D0, 0xC1E3,
+	0x99D1, 0xC1E5, 0x99D2, 0xC1E6, 0x99D3, 0xC1E7, 0x99D4, 0xC1E9,
+	0x99D5, 0xC1EA, 0x99D6, 0xC1EB, 0x99D7, 0xC1EC, 0x99D8, 0xC1ED,
+	0x99D9, 0xC1EE, 0x99DA, 0xC1EF, 0x99DB, 0xC1F2, 0x99DC, 0xC1F4,
+	0x99DD, 0xC1F5, 0x99DE, 0xC1F6, 0x99DF, 0xC1F7, 0x99E0, 0xC1F8,
+	0x99E1, 0xC1F9, 0x99E2, 0xC1FA, 0x99E3, 0xC1FB, 0x99E4, 0xC1FE,
+	0x99E5, 0xC1FF, 0x99E6, 0xC201, 0x99E7, 0xC202, 0x99E8, 0xC203,
+	0x99E9, 0xC205, 0x99EA, 0xC206, 0x99EB, 0xC207, 0x99EC, 0xC208,
+	0x99ED, 0xC209, 0x99EE, 0xC20A, 0x99EF, 0xC20B, 0x99F0, 0xC20E,
+	0x99F1, 0xC210, 0x99F2, 0xC212, 0x99F3, 0xC213, 0x99F4, 0xC214,
+	0x99F5, 0xC215, 0x99F6, 0xC216, 0x99F7, 0xC217, 0x99F8, 0xC21A,
+	0x99F9, 0xC21B, 0x99FA, 0xC21D, 0x99FB, 0xC21E, 0x99FC, 0xC221,
+	0x99FD, 0xC222, 0x99FE, 0xC223, 0x9A41, 0xC224, 0x9A42, 0xC225,
+	0x9A43, 0xC226, 0x9A44, 0xC227, 0x9A45, 0xC22A, 0x9A46, 0xC22C,
+	0x9A47, 0xC22E, 0x9A48, 0xC230, 0x9A49, 0xC233, 0x9A4A, 0xC235,
+	0x9A4B, 0xC236, 0x9A4C, 0xC237, 0x9A4D, 0xC238, 0x9A4E, 0xC239,
+	0x9A4F, 0xC23A, 0x9A50, 0xC23B, 0x9A51, 0xC23C, 0x9A52, 0xC23D,
+	0x9A53, 0xC23E, 0x9A54, 0xC23F, 0x9A55, 0xC240, 0x9A56, 0xC241,
+	0x9A57, 0xC242, 0x9A58, 0xC243, 0x9A59, 0xC244, 0x9A5A, 0xC245,
+	0x9A61, 0xC246, 0x9A62, 0xC247, 0x9A63, 0xC249, 0x9A64, 0xC24A,
+	0x9A65, 0xC24B, 0x9A66, 0xC24C, 0x9A67, 0xC24D, 0x9A68, 0xC24E,
+	0x9A69, 0xC24F, 0x9A6A, 0xC252, 0x9A6B, 0xC253, 0x9A6C, 0xC255,
+	0x9A6D, 0xC256, 0x9A6E, 0xC257, 0x9A6F, 0xC259, 0x9A70, 0xC25A,
+	0x9A71, 0xC25B, 0x9A72, 0xC25C, 0x9A73, 0xC25D, 0x9A74, 0xC25E,
+	0x9A75, 0xC25F, 0x9A76, 0xC261, 0x9A77, 0xC262, 0x9A78, 0xC263,
+	0x9A79, 0xC264, 0x9A7A, 0xC266, 0x9A81, 0xC267, 0x9A82, 0xC268,
+	0x9A83, 0xC269, 0x9A84, 0xC26A, 0x9A85, 0xC26B, 0x9A86, 0xC26E,
+	0x9A87, 0xC26F, 0x9A88, 0xC271, 0x9A89, 0xC272, 0x9A8A, 0xC273,
+	0x9A8B, 0xC275, 0x9A8C, 0xC276, 0x9A8D, 0xC277, 0x9A8E, 0xC278,
+	0x9A8F, 0xC279, 0x9A90, 0xC27A, 0x9A91, 0xC27B, 0x9A92, 0xC27E,
+	0x9A93, 0xC280, 0x9A94, 0xC282, 0x9A95, 0xC283, 0x9A96, 0xC284,
+	0x9A97, 0xC285, 0x9A98, 0xC286, 0x9A99, 0xC287, 0x9A9A, 0xC28A,
+	0x9A9B, 0xC28B, 0x9A9C, 0xC28C, 0x9A9D, 0xC28D, 0x9A9E, 0xC28E,
+	0x9A9F, 0xC28F, 0x9AA0, 0xC291, 0x9AA1, 0xC292, 0x9AA2, 0xC293,
+	0x9AA3, 0xC294, 0x9AA4, 0xC295, 0x9AA5, 0xC296, 0x9AA6, 0xC297,
+	0x9AA7, 0xC299, 0x9AA8, 0xC29A, 0x9AA9, 0xC29C, 0x9AAA, 0xC29E,
+	0x9AAB, 0xC29F, 0x9AAC, 0xC2A0, 0x9AAD, 0xC2A1, 0x9AAE, 0xC2A2,
+	0x9AAF, 0xC2A3, 0x9AB0, 0xC2A6, 0x9AB1, 0xC2A7, 0x9AB2, 0xC2A9,
+	0x9AB3, 0xC2AA, 0x9AB4, 0xC2AB, 0x9AB5, 0xC2AE, 0x9AB6, 0xC2AF,
+	0x9AB7, 0xC2B0, 0x9AB8, 0xC2B1, 0x9AB9, 0xC2B2, 0x9ABA, 0xC2B3,
+	0x9ABB, 0xC2B6, 0x9ABC, 0xC2B8, 0x9ABD, 0xC2BA, 0x9ABE, 0xC2BB,
+	0x9ABF, 0xC2BC, 0x9AC0, 0xC2BD, 0x9AC1, 0xC2BE, 0x9AC2, 0xC2BF,
+	0x9AC3, 0xC2C0, 0x9AC4, 0xC2C1, 0x9AC5, 0xC2C2, 0x9AC6, 0xC2C3,
+	0x9AC7, 0xC2C4, 0x9AC8, 0xC2C5, 0x9AC9, 0xC2C6, 0x9ACA, 0xC2C7,
+	0x9ACB, 0xC2C8, 0x9ACC, 0xC2C9, 0x9ACD, 0xC2CA, 0x9ACE, 0xC2CB,
+	0x9ACF, 0xC2CC, 0x9AD0, 0xC2CD, 0x9AD1, 0xC2CE, 0x9AD2, 0xC2CF,
+	0x9AD3, 0xC2D0, 0x9AD4, 0xC2D1, 0x9AD5, 0xC2D2, 0x9AD6, 0xC2D3,
+	0x9AD7, 0xC2D4, 0x9AD8, 0xC2D5, 0x9AD9, 0xC2D6, 0x9ADA, 0xC2D7,
+	0x9ADB, 0xC2D8, 0x9ADC, 0xC2D9, 0x9ADD, 0xC2DA, 0x9ADE, 0xC2DB,
+	0x9ADF, 0xC2DE, 0x9AE0, 0xC2DF, 0x9AE1, 0xC2E1, 0x9AE2, 0xC2E2,
+	0x9AE3, 0xC2E5, 0x9AE4, 0xC2E6, 0x9AE5, 0xC2E7, 0x9AE6, 0xC2E8,
+	0x9AE7, 0xC2E9, 0x9AE8, 0xC2EA, 0x9AE9, 0xC2EE, 0x9AEA, 0xC2F0,
+	0x9AEB, 0xC2F2, 0x9AEC, 0xC2F3, 0x9AED, 0xC2F4, 0x9AEE, 0xC2F5,
+	0x9AEF, 0xC2F7, 0x9AF0, 0xC2FA, 0x9AF1, 0xC2FD, 0x9AF2, 0xC2FE,
+	0x9AF3, 0xC2FF, 0x9AF4, 0xC301, 0x9AF5, 0xC302, 0x9AF6, 0xC303,
+	0x9AF7, 0xC304, 0x9AF8, 0xC305, 0x9AF9, 0xC306, 0x9AFA, 0xC307,
+	0x9AFB, 0xC30A, 0x9AFC, 0xC30B, 0x9AFD, 0xC30E, 0x9AFE, 0xC30F,
+	0x9B41, 0xC310, 0x9B42, 0xC311, 0x9B43, 0xC312, 0x9B44, 0xC316,
+	0x9B45, 0xC317, 0x9B46, 0xC319, 0x9B47, 0xC31A, 0x9B48, 0xC31B,
+	0x9B49, 0xC31D, 0x9B4A, 0xC31E, 0x9B4B, 0xC31F, 0x9B4C, 0xC320,
+	0x9B4D, 0xC321, 0x9B4E, 0xC322, 0x9B4F, 0xC323, 0x9B50, 0xC326,
+	0x9B51, 0xC327, 0x9B52, 0xC32A, 0x9B53, 0xC32B, 0x9B54, 0xC32C,
+	0x9B55, 0xC32D, 0x9B56, 0xC32E, 0x9B57, 0xC32F, 0x9B58, 0xC330,
+	0x9B59, 0xC331, 0x9B5A, 0xC332, 0x9B61, 0xC333, 0x9B62, 0xC334,
+	0x9B63, 0xC335, 0x9B64, 0xC336, 0x9B65, 0xC337, 0x9B66, 0xC338,
+	0x9B67, 0xC339, 0x9B68, 0xC33A, 0x9B69, 0xC33B, 0x9B6A, 0xC33C,
+	0x9B6B, 0xC33D, 0x9B6C, 0xC33E, 0x9B6D, 0xC33F, 0x9B6E, 0xC340,
+	0x9B6F, 0xC341, 0x9B70, 0xC342, 0x9B71, 0xC343, 0x9B72, 0xC344,
+	0x9B73, 0xC346, 0x9B74, 0xC347, 0x9B75, 0xC348, 0x9B76, 0xC349,
+	0x9B77, 0xC34A, 0x9B78, 0xC34B, 0x9B79, 0xC34C, 0x9B7A, 0xC34D,
+	0x9B81, 0xC34E, 0x9B82, 0xC34F, 0x9B83, 0xC350, 0x9B84, 0xC351,
+	0x9B85, 0xC352, 0x9B86, 0xC353, 0x9B87, 0xC354, 0x9B88, 0xC355,
+	0x9B89, 0xC356, 0x9B8A, 0xC357, 0x9B8B, 0xC358, 0x9B8C, 0xC359,
+	0x9B8D, 0xC35A, 0x9B8E, 0xC35B, 0x9B8F, 0xC35C, 0x9B90, 0xC35D,
+	0x9B91, 0xC35E, 0x9B92, 0xC35F, 0x9B93, 0xC360, 0x9B94, 0xC361,
+	0x9B95, 0xC362, 0x9B96, 0xC363, 0x9B97, 0xC364, 0x9B98, 0xC365,
+	0x9B99, 0xC366, 0x9B9A, 0xC367, 0x9B9B, 0xC36A, 0x9B9C, 0xC36B,
+	0x9B9D, 0xC36D, 0x9B9E, 0xC36E, 0x9B9F, 0xC36F, 0x9BA0, 0xC371,
+	0x9BA1, 0xC373, 0x9BA2, 0xC374, 0x9BA3, 0xC375, 0x9BA4, 0xC376,
+	0x9BA5, 0xC377, 0x9BA6, 0xC37A, 0x9BA7, 0xC37B, 0x9BA8, 0xC37E,
+	0x9BA9, 0xC37F, 0x9BAA, 0xC380, 0x9BAB, 0xC381, 0x9BAC, 0xC382,
+	0x9BAD, 0xC383, 0x9BAE, 0xC385, 0x9BAF, 0xC386, 0x9BB0, 0xC387,
+	0x9BB1, 0xC389, 0x9BB2, 0xC38A, 0x9BB3, 0xC38B, 0x9BB4, 0xC38D,
+	0x9BB5, 0xC38E, 0x9BB6, 0xC38F, 0x9BB7, 0xC390, 0x9BB8, 0xC391,
+	0x9BB9, 0xC392, 0x9BBA, 0xC393, 0x9BBB, 0xC394, 0x9BBC, 0xC395,
+	0x9BBD, 0xC396, 0x9BBE, 0xC397, 0x9BBF, 0xC398, 0x9BC0, 0xC399,
+	0x9BC1, 0xC39A, 0x9BC2, 0xC39B, 0x9BC3, 0xC39C, 0x9BC4, 0xC39D,
+	0x9BC5, 0xC39E, 0x9BC6, 0xC39F, 0x9BC7, 0xC3A0, 0x9BC8, 0xC3A1,
+	0x9BC9, 0xC3A2, 0x9BCA, 0xC3A3, 0x9BCB, 0xC3A4, 0x9BCC, 0xC3A5,
+	0x9BCD, 0xC3A6, 0x9BCE, 0xC3A7, 0x9BCF, 0xC3A8, 0x9BD0, 0xC3A9,
+	0x9BD1, 0xC3AA, 0x9BD2, 0xC3AB, 0x9BD3, 0xC3AC, 0x9BD4, 0xC3AD,
+	0x9BD5, 0xC3AE, 0x9BD6, 0xC3AF, 0x9BD7, 0xC3B0, 0x9BD8, 0xC3B1,
+	0x9BD9, 0xC3B2, 0x9BDA, 0xC3B3, 0x9BDB, 0xC3B4, 0x9BDC, 0xC3B5,
+	0x9BDD, 0xC3B6, 0x9BDE, 0xC3B7, 0x9BDF, 0xC3B8, 0x9BE0, 0xC3B9,
+	0x9BE1, 0xC3BA, 0x9BE2, 0xC3BB, 0x9BE3, 0xC3BC, 0x9BE4, 0xC3BD,
+	0x9BE5, 0xC3BE, 0x9BE6, 0xC3BF, 0x9BE7, 0xC3C1, 0x9BE8, 0xC3C2,
+	0x9BE9, 0xC3C3, 0x9BEA, 0xC3C4, 0x9BEB, 0xC3C5, 0x9BEC, 0xC3C6,
+	0x9BED, 0xC3C7, 0x9BEE, 0xC3C8, 0x9BEF, 0xC3C9, 0x9BF0, 0xC3CA,
+	0x9BF1, 0xC3CB, 0x9BF2, 0xC3CC, 0x9BF3, 0xC3CD, 0x9BF4, 0xC3CE,
+	0x9BF5, 0xC3CF, 0x9BF6, 0xC3D0, 0x9BF7, 0xC3D1, 0x9BF8, 0xC3D2,
+	0x9BF9, 0xC3D3, 0x9BFA, 0xC3D4, 0x9BFB, 0xC3D5, 0x9BFC, 0xC3D6,
+	0x9BFD, 0xC3D7, 0x9BFE, 0xC3DA, 0x9C41, 0xC3DB, 0x9C42, 0xC3DD,
+	0x9C43, 0xC3DE, 0x9C44, 0xC3E1, 0x9C45, 0xC3E3, 0x9C46, 0xC3E4,
+	0x9C47, 0xC3E5, 0x9C48, 0xC3E6, 0x9C49, 0xC3E7, 0x9C4A, 0xC3EA,
+	0x9C4B, 0xC3EB, 0x9C4C, 0xC3EC, 0x9C4D, 0xC3EE, 0x9C4E, 0xC3EF,
+	0x9C4F, 0xC3F0, 0x9C50, 0xC3F1, 0x9C51, 0xC3F2, 0x9C52, 0xC3F3,
+	0x9C53, 0xC3F6, 0x9C54, 0xC3F7, 0x9C55, 0xC3F9, 0x9C56, 0xC3FA,
+	0x9C57, 0xC3FB, 0x9C58, 0xC3FC, 0x9C59, 0xC3FD, 0x9C5A, 0xC3FE,
+	0x9C61, 0xC3FF, 0x9C62, 0xC400, 0x9C63, 0xC401, 0x9C64, 0xC402,
+	0x9C65, 0xC403, 0x9C66, 0xC404, 0x9C67, 0xC405, 0x9C68, 0xC406,
+	0x9C69, 0xC407, 0x9C6A, 0xC409, 0x9C6B, 0xC40A, 0x9C6C, 0xC40B,
+	0x9C6D, 0xC40C, 0x9C6E, 0xC40D, 0x9C6F, 0xC40E, 0x9C70, 0xC40F,
+	0x9C71, 0xC411, 0x9C72, 0xC412, 0x9C73, 0xC413, 0x9C74, 0xC414,
+	0x9C75, 0xC415, 0x9C76, 0xC416, 0x9C77, 0xC417, 0x9C78, 0xC418,
+	0x9C79, 0xC419, 0x9C7A, 0xC41A, 0x9C81, 0xC41B, 0x9C82, 0xC41C,
+	0x9C83, 0xC41D, 0x9C84, 0xC41E, 0x9C85, 0xC41F, 0x9C86, 0xC420,
+	0x9C87, 0xC421, 0x9C88, 0xC422, 0x9C89, 0xC423, 0x9C8A, 0xC425,
+	0x9C8B, 0xC426, 0x9C8C, 0xC427, 0x9C8D, 0xC428, 0x9C8E, 0xC429,
+	0x9C8F, 0xC42A, 0x9C90, 0xC42B, 0x9C91, 0xC42D, 0x9C92, 0xC42E,
+	0x9C93, 0xC42F, 0x9C94, 0xC431, 0x9C95, 0xC432, 0x9C96, 0xC433,
+	0x9C97, 0xC435, 0x9C98, 0xC436, 0x9C99, 0xC437, 0x9C9A, 0xC438,
+	0x9C9B, 0xC439, 0x9C9C, 0xC43A, 0x9C9D, 0xC43B, 0x9C9E, 0xC43E,
+	0x9C9F, 0xC43F, 0x9CA0, 0xC440, 0x9CA1, 0xC441, 0x9CA2, 0xC442,
+	0x9CA3, 0xC443, 0x9CA4, 0xC444, 0x9CA5, 0xC445, 0x9CA6, 0xC446,
+	0x9CA7, 0xC447, 0x9CA8, 0xC449, 0x9CA9, 0xC44A, 0x9CAA, 0xC44B,
+	0x9CAB, 0xC44C, 0x9CAC, 0xC44D, 0x9CAD, 0xC44E, 0x9CAE, 0xC44F,
+	0x9CAF, 0xC450, 0x9CB0, 0xC451, 0x9CB1, 0xC452, 0x9CB2, 0xC453,
+	0x9CB3, 0xC454, 0x9CB4, 0xC455, 0x9CB5, 0xC456, 0x9CB6, 0xC457,
+	0x9CB7, 0xC458, 0x9CB8, 0xC459, 0x9CB9, 0xC45A, 0x9CBA, 0xC45B,
+	0x9CBB, 0xC45C, 0x9CBC, 0xC45D, 0x9CBD, 0xC45E, 0x9CBE, 0xC45F,
+	0x9CBF, 0xC460, 0x9CC0, 0xC461, 0x9CC1, 0xC462, 0x9CC2, 0xC463,
+	0x9CC3, 0xC466, 0x9CC4, 0xC467, 0x9CC5, 0xC469, 0x9CC6, 0xC46A,
+	0x9CC7, 0xC46B, 0x9CC8, 0xC46D, 0x9CC9, 0xC46E, 0x9CCA, 0xC46F,
+	0x9CCB, 0xC470, 0x9CCC, 0xC471, 0x9CCD, 0xC472, 0x9CCE, 0xC473,
+	0x9CCF, 0xC476, 0x9CD0, 0xC477, 0x9CD1, 0xC478, 0x9CD2, 0xC47A,
+	0x9CD3, 0xC47B, 0x9CD4, 0xC47C, 0x9CD5, 0xC47D, 0x9CD6, 0xC47E,
+	0x9CD7, 0xC47F, 0x9CD8, 0xC481, 0x9CD9, 0xC482, 0x9CDA, 0xC483,
+	0x9CDB, 0xC484, 0x9CDC, 0xC485, 0x9CDD, 0xC486, 0x9CDE, 0xC487,
+	0x9CDF, 0xC488, 0x9CE0, 0xC489, 0x9CE1, 0xC48A, 0x9CE2, 0xC48B,
+	0x9CE3, 0xC48C, 0x9CE4, 0xC48D, 0x9CE5, 0xC48E, 0x9CE6, 0xC48F,
+	0x9CE7, 0xC490, 0x9CE8, 0xC491, 0x9CE9, 0xC492, 0x9CEA, 0xC493,
+	0x9CEB, 0xC495, 0x9CEC, 0xC496, 0x9CED, 0xC497, 0x9CEE, 0xC498,
+	0x9CEF, 0xC499, 0x9CF0, 0xC49A, 0x9CF1, 0xC49B, 0x9CF2, 0xC49D,
+	0x9CF3, 0xC49E, 0x9CF4, 0xC49F, 0x9CF5, 0xC4A0, 0x9CF6, 0xC4A1,
+	0x9CF7, 0xC4A2, 0x9CF8, 0xC4A3, 0x9CF9, 0xC4A4, 0x9CFA, 0xC4A5,
+	0x9CFB, 0xC4A6, 0x9CFC, 0xC4A7, 0x9CFD, 0xC4A8, 0x9CFE, 0xC4A9,
+	0x9D41, 0xC4AA, 0x9D42, 0xC4AB, 0x9D43, 0xC4AC, 0x9D44, 0xC4AD,
+	0x9D45, 0xC4AE, 0x9D46, 0xC4AF, 0x9D47, 0xC4B0, 0x9D48, 0xC4B1,
+	0x9D49, 0xC4B2, 0x9D4A, 0xC4B3, 0x9D4B, 0xC4B4, 0x9D4C, 0xC4B5,
+	0x9D4D, 0xC4B6, 0x9D4E, 0xC4B7, 0x9D4F, 0xC4B9, 0x9D50, 0xC4BA,
+	0x9D51, 0xC4BB, 0x9D52, 0xC4BD, 0x9D53, 0xC4BE, 0x9D54, 0xC4BF,
+	0x9D55, 0xC4C0, 0x9D56, 0xC4C1, 0x9D57, 0xC4C2, 0x9D58, 0xC4C3,
+	0x9D59, 0xC4C4, 0x9D5A, 0xC4C5, 0x9D61, 0xC4C6, 0x9D62, 0xC4C7,
+	0x9D63, 0xC4C8, 0x9D64, 0xC4C9, 0x9D65, 0xC4CA, 0x9D66, 0xC4CB,
+	0x9D67, 0xC4CC, 0x9D68, 0xC4CD, 0x9D69, 0xC4CE, 0x9D6A, 0xC4CF,
+	0x9D6B, 0xC4D0, 0x9D6C, 0xC4D1, 0x9D6D, 0xC4D2, 0x9D6E, 0xC4D3,
+	0x9D6F, 0xC4D4, 0x9D70, 0xC4D5, 0x9D71, 0xC4D6, 0x9D72, 0xC4D7,
+	0x9D73, 0xC4D8, 0x9D74, 0xC4D9, 0x9D75, 0xC4DA, 0x9D76, 0xC4DB,
+	0x9D77, 0xC4DC, 0x9D78, 0xC4DD, 0x9D79, 0xC4DE, 0x9D7A, 0xC4DF,
+	0x9D81, 0xC4E0, 0x9D82, 0xC4E1, 0x9D83, 0xC4E2, 0x9D84, 0xC4E3,
+	0x9D85, 0xC4E4, 0x9D86, 0xC4E5, 0x9D87, 0xC4E6, 0x9D88, 0xC4E7,
+	0x9D89, 0xC4E8, 0x9D8A, 0xC4EA, 0x9D8B, 0xC4EB, 0x9D8C, 0xC4EC,
+	0x9D8D, 0xC4ED, 0x9D8E, 0xC4EE, 0x9D8F, 0xC4EF, 0x9D90, 0xC4F2,
+	0x9D91, 0xC4F3, 0x9D92, 0xC4F5, 0x9D93, 0xC4F6, 0x9D94, 0xC4F7,
+	0x9D95, 0xC4F9, 0x9D96, 0xC4FB, 0x9D97, 0xC4FC, 0x9D98, 0xC4FD,
+	0x9D99, 0xC4FE, 0x9D9A, 0xC502, 0x9D9B, 0xC503, 0x9D9C, 0xC504,
+	0x9D9D, 0xC505, 0x9D9E, 0xC506, 0x9D9F, 0xC507, 0x9DA0, 0xC508,
+	0x9DA1, 0xC509, 0x9DA2, 0xC50A, 0x9DA3, 0xC50B, 0x9DA4, 0xC50D,
+	0x9DA5, 0xC50E, 0x9DA6, 0xC50F, 0x9DA7, 0xC511, 0x9DA8, 0xC512,
+	0x9DA9, 0xC513, 0x9DAA, 0xC515, 0x9DAB, 0xC516, 0x9DAC, 0xC517,
+	0x9DAD, 0xC518, 0x9DAE, 0xC519, 0x9DAF, 0xC51A, 0x9DB0, 0xC51B,
+	0x9DB1, 0xC51D, 0x9DB2, 0xC51E, 0x9DB3, 0xC51F, 0x9DB4, 0xC520,
+	0x9DB5, 0xC521, 0x9DB6, 0xC522, 0x9DB7, 0xC523, 0x9DB8, 0xC524,
+	0x9DB9, 0xC525, 0x9DBA, 0xC526, 0x9DBB, 0xC527, 0x9DBC, 0xC52A,
+	0x9DBD, 0xC52B, 0x9DBE, 0xC52D, 0x9DBF, 0xC52E, 0x9DC0, 0xC52F,
+	0x9DC1, 0xC531, 0x9DC2, 0xC532, 0x9DC3, 0xC533, 0x9DC4, 0xC534,
+	0x9DC5, 0xC535, 0x9DC6, 0xC536, 0x9DC7, 0xC537, 0x9DC8, 0xC53A,
+	0x9DC9, 0xC53C, 0x9DCA, 0xC53E, 0x9DCB, 0xC53F, 0x9DCC, 0xC540,
+	0x9DCD, 0xC541, 0x9DCE, 0xC542, 0x9DCF, 0xC543, 0x9DD0, 0xC546,
+	0x9DD1, 0xC547, 0x9DD2, 0xC54B, 0x9DD3, 0xC54F, 0x9DD4, 0xC550,
+	0x9DD5, 0xC551, 0x9DD6, 0xC552, 0x9DD7, 0xC556, 0x9DD8, 0xC55A,
+	0x9DD9, 0xC55B, 0x9DDA, 0xC55C, 0x9DDB, 0xC55F, 0x9DDC, 0xC562,
+	0x9DDD, 0xC563, 0x9DDE, 0xC565, 0x9DDF, 0xC566, 0x9DE0, 0xC567,
+	0x9DE1, 0xC569, 0x9DE2, 0xC56A, 0x9DE3, 0xC56B, 0x9DE4, 0xC56C,
+	0x9DE5, 0xC56D, 0x9DE6, 0xC56E, 0x9DE7, 0xC56F, 0x9DE8, 0xC572,
+	0x9DE9, 0xC576, 0x9DEA, 0xC577, 0x9DEB, 0xC578, 0x9DEC, 0xC579,
+	0x9DED, 0xC57A, 0x9DEE, 0xC57B, 0x9DEF, 0xC57E, 0x9DF0, 0xC57F,
+	0x9DF1, 0xC581, 0x9DF2, 0xC582, 0x9DF3, 0xC583, 0x9DF4, 0xC585,
+	0x9DF5, 0xC586, 0x9DF6, 0xC588, 0x9DF7, 0xC589, 0x9DF8, 0xC58A,
+	0x9DF9, 0xC58B, 0x9DFA, 0xC58E, 0x9DFB, 0xC590, 0x9DFC, 0xC592,
+	0x9DFD, 0xC593, 0x9DFE, 0xC594, 0x9E41, 0xC596, 0x9E42, 0xC599,
+	0x9E43, 0xC59A, 0x9E44, 0xC59B, 0x9E45, 0xC59D, 0x9E46, 0xC59E,
+	0x9E47, 0xC59F, 0x9E48, 0xC5A1, 0x9E49, 0xC5A2, 0x9E4A, 0xC5A3,
+	0x9E4B, 0xC5A4, 0x9E4C, 0xC5A5, 0x9E4D, 0xC5A6, 0x9E4E, 0xC5A7,
+	0x9E4F, 0xC5A8, 0x9E50, 0xC5AA, 0x9E51, 0xC5AB, 0x9E52, 0xC5AC,
+	0x9E53, 0xC5AD, 0x9E54, 0xC5AE, 0x9E55, 0xC5AF, 0x9E56, 0xC5B0,
+	0x9E57, 0xC5B1, 0x9E58, 0xC5B2, 0x9E59, 0xC5B3, 0x9E5A, 0xC5B6,
+	0x9E61, 0xC5B7, 0x9E62, 0xC5BA, 0x9E63, 0xC5BF, 0x9E64, 0xC5C0,
+	0x9E65, 0xC5C1, 0x9E66, 0xC5C2, 0x9E67, 0xC5C3, 0x9E68, 0xC5CB,
+	0x9E69, 0xC5CD, 0x9E6A, 0xC5CF, 0x9E6B, 0xC5D2, 0x9E6C, 0xC5D3,
+	0x9E6D, 0xC5D5, 0x9E6E, 0xC5D6, 0x9E6F, 0xC5D7, 0x9E70, 0xC5D9,
+	0x9E71, 0xC5DA, 0x9E72, 0xC5DB, 0x9E73, 0xC5DC, 0x9E74, 0xC5DD,
+	0x9E75, 0xC5DE, 0x9E76, 0xC5DF, 0x9E77, 0xC5E2, 0x9E78, 0xC5E4,
+	0x9E79, 0xC5E6, 0x9E7A, 0xC5E7, 0x9E81, 0xC5E8, 0x9E82, 0xC5E9,
+	0x9E83, 0xC5EA, 0x9E84, 0xC5EB, 0x9E85, 0xC5EF, 0x9E86, 0xC5F1,
+	0x9E87, 0xC5F2, 0x9E88, 0xC5F3, 0x9E89, 0xC5F5, 0x9E8A, 0xC5F8,
+	0x9E8B, 0xC5F9, 0x9E8C, 0xC5FA, 0x9E8D, 0xC5FB, 0x9E8E, 0xC602,
+	0x9E8F, 0xC603, 0x9E90, 0xC604, 0x9E91, 0xC609, 0x9E92, 0xC60A,
+	0x9E93, 0xC60B, 0x9E94, 0xC60D, 0x9E95, 0xC60E, 0x9E96, 0xC60F,
+	0x9E97, 0xC611, 0x9E98, 0xC612, 0x9E99, 0xC613, 0x9E9A, 0xC614,
+	0x9E9B, 0xC615, 0x9E9C, 0xC616, 0x9E9D, 0xC617, 0x9E9E, 0xC61A,
+	0x9E9F, 0xC61D, 0x9EA0, 0xC61E, 0x9EA1, 0xC61F, 0x9EA2, 0xC620,
+	0x9EA3, 0xC621, 0x9EA4, 0xC622, 0x9EA5, 0xC623, 0x9EA6, 0xC626,
+	0x9EA7, 0xC627, 0x9EA8, 0xC629, 0x9EA9, 0xC62A, 0x9EAA, 0xC62B,
+	0x9EAB, 0xC62F, 0x9EAC, 0xC631, 0x9EAD, 0xC632, 0x9EAE, 0xC636,
+	0x9EAF, 0xC638, 0x9EB0, 0xC63A, 0x9EB1, 0xC63C, 0x9EB2, 0xC63D,
+	0x9EB3, 0xC63E, 0x9EB4, 0xC63F, 0x9EB5, 0xC642, 0x9EB6, 0xC643,
+	0x9EB7, 0xC645, 0x9EB8, 0xC646, 0x9EB9, 0xC647, 0x9EBA, 0xC649,
+	0x9EBB, 0xC64A, 0x9EBC, 0xC64B, 0x9EBD, 0xC64C, 0x9EBE, 0xC64D,
+	0x9EBF, 0xC64E, 0x9EC0, 0xC64F, 0x9EC1, 0xC652, 0x9EC2, 0xC656,
+	0x9EC3, 0xC657, 0x9EC4, 0xC658, 0x9EC5, 0xC659, 0x9EC6, 0xC65A,
+	0x9EC7, 0xC65B, 0x9EC8, 0xC65E, 0x9EC9, 0xC65F, 0x9ECA, 0xC661,
+	0x9ECB, 0xC662, 0x9ECC, 0xC663, 0x9ECD, 0xC664, 0x9ECE, 0xC665,
+	0x9ECF, 0xC666, 0x9ED0, 0xC667, 0x9ED1, 0xC668, 0x9ED2, 0xC669,
+	0x9ED3, 0xC66A, 0x9ED4, 0xC66B, 0x9ED5, 0xC66D, 0x9ED6, 0xC66E,
+	0x9ED7, 0xC670, 0x9ED8, 0xC672, 0x9ED9, 0xC673, 0x9EDA, 0xC674,
+	0x9EDB, 0xC675, 0x9EDC, 0xC676, 0x9EDD, 0xC677, 0x9EDE, 0xC67A,
+	0x9EDF, 0xC67B, 0x9EE0, 0xC67D, 0x9EE1, 0xC67E, 0x9EE2, 0xC67F,
+	0x9EE3, 0xC681, 0x9EE4, 0xC682, 0x9EE5, 0xC683, 0x9EE6, 0xC684,
+	0x9EE7, 0xC685, 0x9EE8, 0xC686, 0x9EE9, 0xC687, 0x9EEA, 0xC68A,
+	0x9EEB, 0xC68C, 0x9EEC, 0xC68E, 0x9EED, 0xC68F, 0x9EEE, 0xC690,
+	0x9EEF, 0xC691, 0x9EF0, 0xC692, 0x9EF1, 0xC693, 0x9EF2, 0xC696,
+	0x9EF3, 0xC697, 0x9EF4, 0xC699, 0x9EF5, 0xC69A, 0x9EF6, 0xC69B,
+	0x9EF7, 0xC69D, 0x9EF8, 0xC69E, 0x9EF9, 0xC69F, 0x9EFA, 0xC6A0,
+	0x9EFB, 0xC6A1, 0x9EFC, 0xC6A2, 0x9EFD, 0xC6A3, 0x9EFE, 0xC6A6,
+	0x9F41, 0xC6A8, 0x9F42, 0xC6AA, 0x9F43, 0xC6AB, 0x9F44, 0xC6AC,
+	0x9F45, 0xC6AD, 0x9F46, 0xC6AE, 0x9F47, 0xC6AF, 0x9F48, 0xC6B2,
+	0x9F49, 0xC6B3, 0x9F4A, 0xC6B5, 0x9F4B, 0xC6B6, 0x9F4C, 0xC6B7,
+	0x9F4D, 0xC6BB, 0x9F4E, 0xC6BC, 0x9F4F, 0xC6BD, 0x9F50, 0xC6BE,
+	0x9F51, 0xC6BF, 0x9F52, 0xC6C2, 0x9F53, 0xC6C4, 0x9F54, 0xC6C6,
+	0x9F55, 0xC6C7, 0x9F56, 0xC6C8, 0x9F57, 0xC6C9, 0x9F58, 0xC6CA,
+	0x9F59, 0xC6CB, 0x9F5A, 0xC6CE, 0x9F61, 0xC6CF, 0x9F62, 0xC6D1,
+	0x9F63, 0xC6D2, 0x9F64, 0xC6D3, 0x9F65, 0xC6D5, 0x9F66, 0xC6D6,
+	0x9F67, 0xC6D7, 0x9F68, 0xC6D8, 0x9F69, 0xC6D9, 0x9F6A, 0xC6DA,
+	0x9F6B, 0xC6DB, 0x9F6C, 0xC6DE, 0x9F6D, 0xC6DF, 0x9F6E, 0xC6E2,
+	0x9F6F, 0xC6E3, 0x9F70, 0xC6E4, 0x9F71, 0xC6E5, 0x9F72, 0xC6E6,
+	0x9F73, 0xC6E7, 0x9F74, 0xC6EA, 0x9F75, 0xC6EB, 0x9F76, 0xC6ED,
+	0x9F77, 0xC6EE, 0x9F78, 0xC6EF, 0x9F79, 0xC6F1, 0x9F7A, 0xC6F2,
+	0x9F81, 0xC6F3, 0x9F82, 0xC6F4, 0x9F83, 0xC6F5, 0x9F84, 0xC6F6,
+	0x9F85, 0xC6F7, 0x9F86, 0xC6FA, 0x9F87, 0xC6FB, 0x9F88, 0xC6FC,
+	0x9F89, 0xC6FE, 0x9F8A, 0xC6FF, 0x9F8B, 0xC700, 0x9F8C, 0xC701,
+	0x9F8D, 0xC702, 0x9F8E, 0xC703, 0x9F8F, 0xC706, 0x9F90, 0xC707,
+	0x9F91, 0xC709, 0x9F92, 0xC70A, 0x9F93, 0xC70B, 0x9F94, 0xC70D,
+	0x9F95, 0xC70E, 0x9F96, 0xC70F, 0x9F97, 0xC710, 0x9F98, 0xC711,
+	0x9F99, 0xC712, 0x9F9A, 0xC713, 0x9F9B, 0xC716, 0x9F9C, 0xC718,
+	0x9F9D, 0xC71A, 0x9F9E, 0xC71B, 0x9F9F, 0xC71C, 0x9FA0, 0xC71D,
+	0x9FA1, 0xC71E, 0x9FA2, 0xC71F, 0x9FA3, 0xC722, 0x9FA4, 0xC723,
+	0x9FA5, 0xC725, 0x9FA6, 0xC726, 0x9FA7, 0xC727, 0x9FA8, 0xC729,
+	0x9FA9, 0xC72A, 0x9FAA, 0xC72B, 0x9FAB, 0xC72C, 0x9FAC, 0xC72D,
+	0x9FAD, 0xC72E, 0x9FAE, 0xC72F, 0x9FAF, 0xC732, 0x9FB0, 0xC734,
+	0x9FB1, 0xC736, 0x9FB2, 0xC738, 0x9FB3, 0xC739, 0x9FB4, 0xC73A,
+	0x9FB5, 0xC73B, 0x9FB6, 0xC73E, 0x9FB7, 0xC73F, 0x9FB8, 0xC741,
+	0x9FB9, 0xC742, 0x9FBA, 0xC743, 0x9FBB, 0xC745, 0x9FBC, 0xC746,
+	0x9FBD, 0xC747, 0x9FBE, 0xC748, 0x9FBF, 0xC749, 0x9FC0, 0xC74B,
+	0x9FC1, 0xC74E, 0x9FC2, 0xC750, 0x9FC3, 0xC759, 0x9FC4, 0xC75A,
+	0x9FC5, 0xC75B, 0x9FC6, 0xC75D, 0x9FC7, 0xC75E, 0x9FC8, 0xC75F,
+	0x9FC9, 0xC761, 0x9FCA, 0xC762, 0x9FCB, 0xC763, 0x9FCC, 0xC764,
+	0x9FCD, 0xC765, 0x9FCE, 0xC766, 0x9FCF, 0xC767, 0x9FD0, 0xC769,
+	0x9FD1, 0xC76A, 0x9FD2, 0xC76C, 0x9FD3, 0xC76D, 0x9FD4, 0xC76E,
+	0x9FD5, 0xC76F, 0x9FD6, 0xC770, 0x9FD7, 0xC771, 0x9FD8, 0xC772,
+	0x9FD9, 0xC773, 0x9FDA, 0xC776, 0x9FDB, 0xC777, 0x9FDC, 0xC779,
+	0x9FDD, 0xC77A, 0x9FDE, 0xC77B, 0x9FDF, 0xC77F, 0x9FE0, 0xC780,
+	0x9FE1, 0xC781, 0x9FE2, 0xC782, 0x9FE3, 0xC786, 0x9FE4, 0xC78B,
+	0x9FE5, 0xC78C, 0x9FE6, 0xC78D, 0x9FE7, 0xC78F, 0x9FE8, 0xC792,
+	0x9FE9, 0xC793, 0x9FEA, 0xC795, 0x9FEB, 0xC799, 0x9FEC, 0xC79B,
+	0x9FED, 0xC79C, 0x9FEE, 0xC79D, 0x9FEF, 0xC79E, 0x9FF0, 0xC79F,
+	0x9FF1, 0xC7A2, 0x9FF2, 0xC7A7, 0x9FF3, 0xC7A8, 0x9FF4, 0xC7A9,
+	0x9FF5, 0xC7AA, 0x9FF6, 0xC7AB, 0x9FF7, 0xC7AE, 0x9FF8, 0xC7AF,
+	0x9FF9, 0xC7B1, 0x9FFA, 0xC7B2, 0x9FFB, 0xC7B3, 0x9FFC, 0xC7B5,
+	0x9FFD, 0xC7B6, 0x9FFE, 0xC7B7, 0xA041, 0xC7B8, 0xA042, 0xC7B9,
+	0xA043, 0xC7BA, 0xA044, 0xC7BB, 0xA045, 0xC7BE, 0xA046, 0xC7C2,
+	0xA047, 0xC7C3, 0xA048, 0xC7C4, 0xA049, 0xC7C5, 0xA04A, 0xC7C6,
+	0xA04B, 0xC7C7, 0xA04C, 0xC7CA, 0xA04D, 0xC7CB, 0xA04E, 0xC7CD,
+	0xA04F, 0xC7CF, 0xA050, 0xC7D1, 0xA051, 0xC7D2, 0xA052, 0xC7D3,
+	0xA053, 0xC7D4, 0xA054, 0xC7D5, 0xA055, 0xC7D6, 0xA056, 0xC7D7,
+	0xA057, 0xC7D9, 0xA058, 0xC7DA, 0xA059, 0xC7DB, 0xA05A, 0xC7DC,
+	0xA061, 0xC7DE, 0xA062, 0xC7DF, 0xA063, 0xC7E0, 0xA064, 0xC7E1,
+	0xA065, 0xC7E2, 0xA066, 0xC7E3, 0xA067, 0xC7E5, 0xA068, 0xC7E6,
+	0xA069, 0xC7E7, 0xA06A, 0xC7E9, 0xA06B, 0xC7EA, 0xA06C, 0xC7EB,
+	0xA06D, 0xC7ED, 0xA06E, 0xC7EE, 0xA06F, 0xC7EF, 0xA070, 0xC7F0,
+	0xA071, 0xC7F1, 0xA072, 0xC7F2, 0xA073, 0xC7F3, 0xA074, 0xC7F4,
+	0xA075, 0xC7F5, 0xA076, 0xC7F6, 0xA077, 0xC7F7, 0xA078, 0xC7F8,
+	0xA079, 0xC7F9, 0xA07A, 0xC7FA, 0xA081, 0xC7FB, 0xA082, 0xC7FC,
+	0xA083, 0xC7FD, 0xA084, 0xC7FE, 0xA085, 0xC7FF, 0xA086, 0xC802,
+	0xA087, 0xC803, 0xA088, 0xC805, 0xA089, 0xC806, 0xA08A, 0xC807,
+	0xA08B, 0xC809, 0xA08C, 0xC80B, 0xA08D, 0xC80C, 0xA08E, 0xC80D,
+	0xA08F, 0xC80E, 0xA090, 0xC80F, 0xA091, 0xC812, 0xA092, 0xC814,
+	0xA093, 0xC817, 0xA094, 0xC818, 0xA095, 0xC819, 0xA096, 0xC81A,
+	0xA097, 0xC81B, 0xA098, 0xC81E, 0xA099, 0xC81F, 0xA09A, 0xC821,
+	0xA09B, 0xC822, 0xA09C, 0xC823, 0xA09D, 0xC825, 0xA09E, 0xC826,
+	0xA09F, 0xC827, 0xA0A0, 0xC828, 0xA0A1, 0xC829, 0xA0A2, 0xC82A,
+	0xA0A3, 0xC82B, 0xA0A4, 0xC82E, 0xA0A5, 0xC830, 0xA0A6, 0xC832,
+	0xA0A7, 0xC833, 0xA0A8, 0xC834, 0xA0A9, 0xC835, 0xA0AA, 0xC836,
+	0xA0AB, 0xC837, 0xA0AC, 0xC839, 0xA0AD, 0xC83A, 0xA0AE, 0xC83B,
+	0xA0AF, 0xC83D, 0xA0B0, 0xC83E, 0xA0B1, 0xC83F, 0xA0B2, 0xC841,
+	0xA0B3, 0xC842, 0xA0B4, 0xC843, 0xA0B5, 0xC844, 0xA0B6, 0xC845,
+	0xA0B7, 0xC846, 0xA0B8, 0xC847, 0xA0B9, 0xC84A, 0xA0BA, 0xC84B,
+	0xA0BB, 0xC84E, 0xA0BC, 0xC84F, 0xA0BD, 0xC850, 0xA0BE, 0xC851,
+	0xA0BF, 0xC852, 0xA0C0, 0xC853, 0xA0C1, 0xC855, 0xA0C2, 0xC856,
+	0xA0C3, 0xC857, 0xA0C4, 0xC858, 0xA0C5, 0xC859, 0xA0C6, 0xC85A,
+	0xA0C7, 0xC85B, 0xA0C8, 0xC85C, 0xA0C9, 0xC85D, 0xA0CA, 0xC85E,
+	0xA0CB, 0xC85F, 0xA0CC, 0xC860, 0xA0CD, 0xC861, 0xA0CE, 0xC862,
+	0xA0CF, 0xC863, 0xA0D0, 0xC864, 0xA0D1, 0xC865, 0xA0D2, 0xC866,
+	0xA0D3, 0xC867, 0xA0D4, 0xC868, 0xA0D5, 0xC869, 0xA0D6, 0xC86A,
+	0xA0D7, 0xC86B, 0xA0D8, 0xC86C, 0xA0D9, 0xC86D, 0xA0DA, 0xC86E,
+	0xA0DB, 0xC86F, 0xA0DC, 0xC872, 0xA0DD, 0xC873, 0xA0DE, 0xC875,
+	0xA0DF, 0xC876, 0xA0E0, 0xC877, 0xA0E1, 0xC879, 0xA0E2, 0xC87B,
+	0xA0E3, 0xC87C, 0xA0E4, 0xC87D, 0xA0E5, 0xC87E, 0xA0E6, 0xC87F,
+	0xA0E7, 0xC882, 0xA0E8, 0xC884, 0xA0E9, 0xC888, 0xA0EA, 0xC889,
+	0xA0EB, 0xC88A, 0xA0EC, 0xC88E, 0xA0ED, 0xC88F, 0xA0EE, 0xC890,
+	0xA0EF, 0xC891, 0xA0F0, 0xC892, 0xA0F1, 0xC893, 0xA0F2, 0xC895,
+	0xA0F3, 0xC896, 0xA0F4, 0xC897, 0xA0F5, 0xC898, 0xA0F6, 0xC899,
+	0xA0F7, 0xC89A, 0xA0F8, 0xC89B, 0xA0F9, 0xC89C, 0xA0FA, 0xC89E,
+	0xA0FB, 0xC8A0, 0xA0FC, 0xC8A2, 0xA0FD, 0xC8A3, 0xA0FE, 0xC8A4,
+	0xA141, 0xC8A5, 0xA142, 0xC8A6, 0xA143, 0xC8A7, 0xA144, 0xC8A9,
+	0xA145, 0xC8AA, 0xA146, 0xC8AB, 0xA147, 0xC8AC, 0xA148, 0xC8AD,
+	0xA149, 0xC8AE, 0xA14A, 0xC8AF, 0xA14B, 0xC8B0, 0xA14C, 0xC8B1,
+	0xA14D, 0xC8B2, 0xA14E, 0xC8B3, 0xA14F, 0xC8B4, 0xA150, 0xC8B5,
+	0xA151, 0xC8B6, 0xA152, 0xC8B7, 0xA153, 0xC8B8, 0xA154, 0xC8B9,
+	0xA155, 0xC8BA, 0xA156, 0xC8BB, 0xA157, 0xC8BE, 0xA158, 0xC8BF,
+	0xA159, 0xC8C0, 0xA15A, 0xC8C1, 0xA161, 0xC8C2, 0xA162, 0xC8C3,
+	0xA163, 0xC8C5, 0xA164, 0xC8C6, 0xA165, 0xC8C7, 0xA166, 0xC8C9,
+	0xA167, 0xC8CA, 0xA168, 0xC8CB, 0xA169, 0xC8CD, 0xA16A, 0xC8CE,
+	0xA16B, 0xC8CF, 0xA16C, 0xC8D0, 0xA16D, 0xC8D1, 0xA16E, 0xC8D2,
+	0xA16F, 0xC8D3, 0xA170, 0xC8D6, 0xA171, 0xC8D8, 0xA172, 0xC8DA,
+	0xA173, 0xC8DB, 0xA174, 0xC8DC, 0xA175, 0xC8DD, 0xA176, 0xC8DE,
+	0xA177, 0xC8DF, 0xA178, 0xC8E2, 0xA179, 0xC8E3, 0xA17A, 0xC8E5,
+	0xA181, 0xC8E6, 0xA182, 0xC8E7, 0xA183, 0xC8E8, 0xA184, 0xC8E9,
+	0xA185, 0xC8EA, 0xA186, 0xC8EB, 0xA187, 0xC8EC, 0xA188, 0xC8ED,
+	0xA189, 0xC8EE, 0xA18A, 0xC8EF, 0xA18B, 0xC8F0, 0xA18C, 0xC8F1,
+	0xA18D, 0xC8F2, 0xA18E, 0xC8F3, 0xA18F, 0xC8F4, 0xA190, 0xC8F6,
+	0xA191, 0xC8F7, 0xA192, 0xC8F8, 0xA193, 0xC8F9, 0xA194, 0xC8FA,
+	0xA195, 0xC8FB, 0xA196, 0xC8FE, 0xA197, 0xC8FF, 0xA198, 0xC901,
+	0xA199, 0xC902, 0xA19A, 0xC903, 0xA19B, 0xC907, 0xA19C, 0xC908,
+	0xA19D, 0xC909, 0xA19E, 0xC90A, 0xA19F, 0xC90B, 0xA1A0, 0xC90E,
+	0xA1A1, 0x3000, 0xA1A2, 0x3001, 0xA1A3, 0x3002, 0xA1A4, 0x00B7,
+	0xA1A5, 0x2025, 0xA1A6, 0x2026, 0xA1A7, 0x00A8, 0xA1A8, 0x3003,
+	0xA1A9, 0x00AD, 0xA1AA, 0x2015, 0xA1AB, 0x2225, 0xA1AC, 0xFF3C,
+	0xA1AD, 0x223C, 0xA1AE, 0x2018, 0xA1AF, 0x2019, 0xA1B0, 0x201C,
+	0xA1B1, 0x201D, 0xA1B2, 0x3014, 0xA1B3, 0x3015, 0xA1B4, 0x3008,
+	0xA1B5, 0x3009, 0xA1B6, 0x300A, 0xA1B7, 0x300B, 0xA1B8, 0x300C,
+	0xA1B9, 0x300D, 0xA1BA, 0x300E, 0xA1BB, 0x300F, 0xA1BC, 0x3010,
+	0xA1BD, 0x3011, 0xA1BE, 0x00B1, 0xA1BF, 0x00D7, 0xA1C0, 0x00F7,
+	0xA1C1, 0x2260, 0xA1C2, 0x2264, 0xA1C3, 0x2265, 0xA1C4, 0x221E,
+	0xA1C5, 0x2234, 0xA1C6, 0x00B0, 0xA1C7, 0x2032, 0xA1C8, 0x2033,
+	0xA1C9, 0x2103, 0xA1CA, 0x212B, 0xA1CB, 0xFFE0, 0xA1CC, 0xFFE1,
+	0xA1CD, 0xFFE5, 0xA1CE, 0x2642, 0xA1CF, 0x2640, 0xA1D0, 0x2220,
+	0xA1D1, 0x22A5, 0xA1D2, 0x2312, 0xA1D3, 0x2202, 0xA1D4, 0x2207,
+	0xA1D5, 0x2261, 0xA1D6, 0x2252, 0xA1D7, 0x00A7, 0xA1D8, 0x203B,
+	0xA1D9, 0x2606, 0xA1DA, 0x2605, 0xA1DB, 0x25CB, 0xA1DC, 0x25CF,
+	0xA1DD, 0x25CE, 0xA1DE, 0x25C7, 0xA1DF, 0x25C6, 0xA1E0, 0x25A1,
+	0xA1E1, 0x25A0, 0xA1E2, 0x25B3, 0xA1E3, 0x25B2, 0xA1E4, 0x25BD,
+	0xA1E5, 0x25BC, 0xA1E6, 0x2192, 0xA1E7, 0x2190, 0xA1E8, 0x2191,
+	0xA1E9, 0x2193, 0xA1EA, 0x2194, 0xA1EB, 0x3013, 0xA1EC, 0x226A,
+	0xA1ED, 0x226B, 0xA1EE, 0x221A, 0xA1EF, 0x223D, 0xA1F0, 0x221D,
+	0xA1F1, 0x2235, 0xA1F2, 0x222B, 0xA1F3, 0x222C, 0xA1F4, 0x2208,
+	0xA1F5, 0x220B, 0xA1F6, 0x2286, 0xA1F7, 0x2287, 0xA1F8, 0x2282,
+	0xA1F9, 0x2283, 0xA1FA, 0x222A, 0xA1FB, 0x2229, 0xA1FC, 0x2227,
+	0xA1FD, 0x2228, 0xA1FE, 0xFFE2, 0xA241, 0xC910, 0xA242, 0xC912,
+	0xA243, 0xC913, 0xA244, 0xC914, 0xA245, 0xC915, 0xA246, 0xC916,
+	0xA247, 0xC917, 0xA248, 0xC919, 0xA249, 0xC91A, 0xA24A, 0xC91B,
+	0xA24B, 0xC91C, 0xA24C, 0xC91D, 0xA24D, 0xC91E, 0xA24E, 0xC91F,
+	0xA24F, 0xC920, 0xA250, 0xC921, 0xA251, 0xC922, 0xA252, 0xC923,
+	0xA253, 0xC924, 0xA254, 0xC925, 0xA255, 0xC926, 0xA256, 0xC927,
+	0xA257, 0xC928, 0xA258, 0xC929, 0xA259, 0xC92A, 0xA25A, 0xC92B,
+	0xA261, 0xC92D, 0xA262, 0xC92E, 0xA263, 0xC92F, 0xA264, 0xC930,
+	0xA265, 0xC931, 0xA266, 0xC932, 0xA267, 0xC933, 0xA268, 0xC935,
+	0xA269, 0xC936, 0xA26A, 0xC937, 0xA26B, 0xC938, 0xA26C, 0xC939,
+	0xA26D, 0xC93A, 0xA26E, 0xC93B, 0xA26F, 0xC93C, 0xA270, 0xC93D,
+	0xA271, 0xC93E, 0xA272, 0xC93F, 0xA273, 0xC940, 0xA274, 0xC941,
+	0xA275, 0xC942, 0xA276, 0xC943, 0xA277, 0xC944, 0xA278, 0xC945,
+	0xA279, 0xC946, 0xA27A, 0xC947, 0xA281, 0xC948, 0xA282, 0xC949,
+	0xA283, 0xC94A, 0xA284, 0xC94B, 0xA285, 0xC94C, 0xA286, 0xC94D,
+	0xA287, 0xC94E, 0xA288, 0xC94F, 0xA289, 0xC952, 0xA28A, 0xC953,
+	0xA28B, 0xC955, 0xA28C, 0xC956, 0xA28D, 0xC957, 0xA28E, 0xC959,
+	0xA28F, 0xC95A, 0xA290, 0xC95B, 0xA291, 0xC95C, 0xA292, 0xC95D,
+	0xA293, 0xC95E, 0xA294, 0xC95F, 0xA295, 0xC962, 0xA296, 0xC964,
+	0xA297, 0xC965, 0xA298, 0xC966, 0xA299, 0xC967, 0xA29A, 0xC968,
+	0xA29B, 0xC969, 0xA29C, 0xC96A, 0xA29D, 0xC96B, 0xA29E, 0xC96D,
+	0xA29F, 0xC96E, 0xA2A0, 0xC96F, 0xA2A1, 0x21D2, 0xA2A2, 0x21D4,
+	0xA2A3, 0x2200, 0xA2A4, 0x2203, 0xA2A5, 0x00B4, 0xA2A6, 0xFF5E,
+	0xA2A7, 0x02C7, 0xA2A8, 0x02D8, 0xA2A9, 0x02DD, 0xA2AA, 0x02DA,
+	0xA2AB, 0x02D9, 0xA2AC, 0x00B8, 0xA2AD, 0x02DB, 0xA2AE, 0x00A1,
+	0xA2AF, 0x00BF, 0xA2B0, 0x02D0, 0xA2B1, 0x222E, 0xA2B2, 0x2211,
+	0xA2B3, 0x220F, 0xA2B4, 0x00A4, 0xA2B5, 0x2109, 0xA2B6, 0x2030,
+	0xA2B7, 0x25C1, 0xA2B8, 0x25C0, 0xA2B9, 0x25B7, 0xA2BA, 0x25B6,
+	0xA2BB, 0x2664, 0xA2BC, 0x2660, 0xA2BD, 0x2661, 0xA2BE, 0x2665,
+	0xA2BF, 0x2667, 0xA2C0, 0x2663, 0xA2C1, 0x2299, 0xA2C2, 0x25C8,
+	0xA2C3, 0x25A3, 0xA2C4, 0x25D0, 0xA2C5, 0x25D1, 0xA2C6, 0x2592,
+	0xA2C7, 0x25A4, 0xA2C8, 0x25A5, 0xA2C9, 0x25A8, 0xA2CA, 0x25A7,
+	0xA2CB, 0x25A6, 0xA2CC, 0x25A9, 0xA2CD, 0x2668, 0xA2CE, 0x260F,
+	0xA2CF, 0x260E, 0xA2D0, 0x261C, 0xA2D1, 0x261E, 0xA2D2, 0x00B6,
+	0xA2D3, 0x2020, 0xA2D4, 0x2021, 0xA2D5, 0x2195, 0xA2D6, 0x2197,
+	0xA2D7, 0x2199, 0xA2D8, 0x2196, 0xA2D9, 0x2198, 0xA2DA, 0x266D,
+	0xA2DB, 0x2669, 0xA2DC, 0x266A, 0xA2DD, 0x266C, 0xA2DE, 0x327F,
+	0xA2DF, 0x321C, 0xA2E0, 0x2116, 0xA2E1, 0x33C7, 0xA2E2, 0x2122,
+	0xA2E3, 0x33C2, 0xA2E4, 0x33D8, 0xA2E5, 0x2121, 0xA2E6, 0x20AC,
+	0xA2E7, 0x00AE, 0xA341, 0xC971, 0xA342, 0xC972, 0xA343, 0xC973,
+	0xA344, 0xC975, 0xA345, 0xC976, 0xA346, 0xC977, 0xA347, 0xC978,
+	0xA348, 0xC979, 0xA349, 0xC97A, 0xA34A, 0xC97B, 0xA34B, 0xC97D,
+	0xA34C, 0xC97E, 0xA34D, 0xC97F, 0xA34E, 0xC980, 0xA34F, 0xC981,
+	0xA350, 0xC982, 0xA351, 0xC983, 0xA352, 0xC984, 0xA353, 0xC985,
+	0xA354, 0xC986, 0xA355, 0xC987, 0xA356, 0xC98A, 0xA357, 0xC98B,
+	0xA358, 0xC98D, 0xA359, 0xC98E, 0xA35A, 0xC98F, 0xA361, 0xC991,
+	0xA362, 0xC992, 0xA363, 0xC993, 0xA364, 0xC994, 0xA365, 0xC995,
+	0xA366, 0xC996, 0xA367, 0xC997, 0xA368, 0xC99A, 0xA369, 0xC99C,
+	0xA36A, 0xC99E, 0xA36B, 0xC99F, 0xA36C, 0xC9A0, 0xA36D, 0xC9A1,
+	0xA36E, 0xC9A2, 0xA36F, 0xC9A3, 0xA370, 0xC9A4, 0xA371, 0xC9A5,
+	0xA372, 0xC9A6, 0xA373, 0xC9A7, 0xA374, 0xC9A8, 0xA375, 0xC9A9,
+	0xA376, 0xC9AA, 0xA377, 0xC9AB, 0xA378, 0xC9AC, 0xA379, 0xC9AD,
+	0xA37A, 0xC9AE, 0xA381, 0xC9AF, 0xA382, 0xC9B0, 0xA383, 0xC9B1,
+	0xA384, 0xC9B2, 0xA385, 0xC9B3, 0xA386, 0xC9B4, 0xA387, 0xC9B5,
+	0xA388, 0xC9B6, 0xA389, 0xC9B7, 0xA38A, 0xC9B8, 0xA38B, 0xC9B9,
+	0xA38C, 0xC9BA, 0xA38D, 0xC9BB, 0xA38E, 0xC9BC, 0xA38F, 0xC9BD,
+	0xA390, 0xC9BE, 0xA391, 0xC9BF, 0xA392, 0xC9C2, 0xA393, 0xC9C3,
+	0xA394, 0xC9C5, 0xA395, 0xC9C6, 0xA396, 0xC9C9, 0xA397, 0xC9CB,
+	0xA398, 0xC9CC, 0xA399, 0xC9CD, 0xA39A, 0xC9CE, 0xA39B, 0xC9CF,
+	0xA39C, 0xC9D2, 0xA39D, 0xC9D4, 0xA39E, 0xC9D7, 0xA39F, 0xC9D8,
+	0xA3A0, 0xC9DB, 0xA3A1, 0xFF01, 0xA3A2, 0xFF02, 0xA3A3, 0xFF03,
+	0xA3A4, 0xFF04, 0xA3A5, 0xFF05, 0xA3A6, 0xFF06, 0xA3A7, 0xFF07,
+	0xA3A8, 0xFF08, 0xA3A9, 0xFF09, 0xA3AA, 0xFF0A, 0xA3AB, 0xFF0B,
+	0xA3AC, 0xFF0C, 0xA3AD, 0xFF0D, 0xA3AE, 0xFF0E, 0xA3AF, 0xFF0F,
+	0xA3B0, 0xFF10, 0xA3B1, 0xFF11, 0xA3B2, 0xFF12, 0xA3B3, 0xFF13,
+	0xA3B4, 0xFF14, 0xA3B5, 0xFF15, 0xA3B6, 0xFF16, 0xA3B7, 0xFF17,
+	0xA3B8, 0xFF18, 0xA3B9, 0xFF19, 0xA3BA, 0xFF1A, 0xA3BB, 0xFF1B,
+	0xA3BC, 0xFF1C, 0xA3BD, 0xFF1D, 0xA3BE, 0xFF1E, 0xA3BF, 0xFF1F,
+	0xA3C0, 0xFF20, 0xA3C1, 0xFF21, 0xA3C2, 0xFF22, 0xA3C3, 0xFF23,
+	0xA3C4, 0xFF24, 0xA3C5, 0xFF25, 0xA3C6, 0xFF26, 0xA3C7, 0xFF27,
+	0xA3C8, 0xFF28, 0xA3C9, 0xFF29, 0xA3CA, 0xFF2A, 0xA3CB, 0xFF2B,
+	0xA3CC, 0xFF2C, 0xA3CD, 0xFF2D, 0xA3CE, 0xFF2E, 0xA3CF, 0xFF2F,
+	0xA3D0, 0xFF30, 0xA3D1, 0xFF31, 0xA3D2, 0xFF32, 0xA3D3, 0xFF33,
+	0xA3D4, 0xFF34, 0xA3D5, 0xFF35, 0xA3D6, 0xFF36, 0xA3D7, 0xFF37,
+	0xA3D8, 0xFF38, 0xA3D9, 0xFF39, 0xA3DA, 0xFF3A, 0xA3DB, 0xFF3B,
+	0xA3DC, 0xFFE6, 0xA3DD, 0xFF3D, 0xA3DE, 0xFF3E, 0xA3DF, 0xFF3F,
+	0xA3E0, 0xFF40, 0xA3E1, 0xFF41, 0xA3E2, 0xFF42, 0xA3E3, 0xFF43,
+	0xA3E4, 0xFF44, 0xA3E5, 0xFF45, 0xA3E6, 0xFF46, 0xA3E7, 0xFF47,
+	0xA3E8, 0xFF48, 0xA3E9, 0xFF49, 0xA3EA, 0xFF4A, 0xA3EB, 0xFF4B,
+	0xA3EC, 0xFF4C, 0xA3ED, 0xFF4D, 0xA3EE, 0xFF4E, 0xA3EF, 0xFF4F,
+	0xA3F0, 0xFF50, 0xA3F1, 0xFF51, 0xA3F2, 0xFF52, 0xA3F3, 0xFF53,
+	0xA3F4, 0xFF54, 0xA3F5, 0xFF55, 0xA3F6, 0xFF56, 0xA3F7, 0xFF57,
+	0xA3F8, 0xFF58, 0xA3F9, 0xFF59, 0xA3FA, 0xFF5A, 0xA3FB, 0xFF5B,
+	0xA3FC, 0xFF5C, 0xA3FD, 0xFF5D, 0xA3FE, 0xFFE3, 0xA441, 0xC9DE,
+	0xA442, 0xC9DF, 0xA443, 0xC9E1, 0xA444, 0xC9E3, 0xA445, 0xC9E5,
+	0xA446, 0xC9E6, 0xA447, 0xC9E8, 0xA448, 0xC9E9, 0xA449, 0xC9EA,
+	0xA44A, 0xC9EB, 0xA44B, 0xC9EE, 0xA44C, 0xC9F2, 0xA44D, 0xC9F3,
+	0xA44E, 0xC9F4, 0xA44F, 0xC9F5, 0xA450, 0xC9F6, 0xA451, 0xC9F7,
+	0xA452, 0xC9FA, 0xA453, 0xC9FB, 0xA454, 0xC9FD, 0xA455, 0xC9FE,
+	0xA456, 0xC9FF, 0xA457, 0xCA01, 0xA458, 0xCA02, 0xA459, 0xCA03,
+	0xA45A, 0xCA04, 0xA461, 0xCA05, 0xA462, 0xCA06, 0xA463, 0xCA07,
+	0xA464, 0xCA0A, 0xA465, 0xCA0E, 0xA466, 0xCA0F, 0xA467, 0xCA10,
+	0xA468, 0xCA11, 0xA469, 0xCA12, 0xA46A, 0xCA13, 0xA46B, 0xCA15,
+	0xA46C, 0xCA16, 0xA46D, 0xCA17, 0xA46E, 0xCA19, 0xA46F, 0xCA1A,
+	0xA470, 0xCA1B, 0xA471, 0xCA1C, 0xA472, 0xCA1D, 0xA473, 0xCA1E,
+	0xA474, 0xCA1F, 0xA475, 0xCA20, 0xA476, 0xCA21, 0xA477, 0xCA22,
+	0xA478, 0xCA23, 0xA479, 0xCA24, 0xA47A, 0xCA25, 0xA481, 0xCA26,
+	0xA482, 0xCA27, 0xA483, 0xCA28, 0xA484, 0xCA2A, 0xA485, 0xCA2B,
+	0xA486, 0xCA2C, 0xA487, 0xCA2D, 0xA488, 0xCA2E, 0xA489, 0xCA2F,
+	0xA48A, 0xCA30, 0xA48B, 0xCA31, 0xA48C, 0xCA32, 0xA48D, 0xCA33,
+	0xA48E, 0xCA34, 0xA48F, 0xCA35, 0xA490, 0xCA36, 0xA491, 0xCA37,
+	0xA492, 0xCA38, 0xA493, 0xCA39, 0xA494, 0xCA3A, 0xA495, 0xCA3B,
+	0xA496, 0xCA3C, 0xA497, 0xCA3D, 0xA498, 0xCA3E, 0xA499, 0xCA3F,
+	0xA49A, 0xCA40, 0xA49B, 0xCA41, 0xA49C, 0xCA42, 0xA49D, 0xCA43,
+	0xA49E, 0xCA44, 0xA49F, 0xCA45, 0xA4A0, 0xCA46, 0xA4A1, 0x3131,
+	0xA4A2, 0x3132, 0xA4A3, 0x3133, 0xA4A4, 0x3134, 0xA4A5, 0x3135,
+	0xA4A6, 0x3136, 0xA4A7, 0x3137, 0xA4A8, 0x3138, 0xA4A9, 0x3139,
+	0xA4AA, 0x313A, 0xA4AB, 0x313B, 0xA4AC, 0x313C, 0xA4AD, 0x313D,
+	0xA4AE, 0x313E, 0xA4AF, 0x313F, 0xA4B0, 0x3140, 0xA4B1, 0x3141,
+	0xA4B2, 0x3142, 0xA4B3, 0x3143, 0xA4B4, 0x3144, 0xA4B5, 0x3145,
+	0xA4B6, 0x3146, 0xA4B7, 0x3147, 0xA4B8, 0x3148, 0xA4B9, 0x3149,
+	0xA4BA, 0x314A, 0xA4BB, 0x314B, 0xA4BC, 0x314C, 0xA4BD, 0x314D,
+	0xA4BE, 0x314E, 0xA4BF, 0x314F, 0xA4C0, 0x3150, 0xA4C1, 0x3151,
+	0xA4C2, 0x3152, 0xA4C3, 0x3153, 0xA4C4, 0x3154, 0xA4C5, 0x3155,
+	0xA4C6, 0x3156, 0xA4C7, 0x3157, 0xA4C8, 0x3158, 0xA4C9, 0x3159,
+	0xA4CA, 0x315A, 0xA4CB, 0x315B, 0xA4CC, 0x315C, 0xA4CD, 0x315D,
+	0xA4CE, 0x315E, 0xA4CF, 0x315F, 0xA4D0, 0x3160, 0xA4D1, 0x3161,
+	0xA4D2, 0x3162, 0xA4D3, 0x3163, 0xA4D4, 0x3164, 0xA4D5, 0x3165,
+	0xA4D6, 0x3166, 0xA4D7, 0x3167, 0xA4D8, 0x3168, 0xA4D9, 0x3169,
+	0xA4DA, 0x316A, 0xA4DB, 0x316B, 0xA4DC, 0x316C, 0xA4DD, 0x316D,
+	0xA4DE, 0x316E, 0xA4DF, 0x316F, 0xA4E0, 0x3170, 0xA4E1, 0x3171,
+	0xA4E2, 0x3172, 0xA4E3, 0x3173, 0xA4E4, 0x3174, 0xA4E5, 0x3175,
+	0xA4E6, 0x3176, 0xA4E7, 0x3177, 0xA4E8, 0x3178, 0xA4E9, 0x3179,
+	0xA4EA, 0x317A, 0xA4EB, 0x317B, 0xA4EC, 0x317C, 0xA4ED, 0x317D,
+	0xA4EE, 0x317E, 0xA4EF, 0x317F, 0xA4F0, 0x3180, 0xA4F1, 0x3181,
+	0xA4F2, 0x3182, 0xA4F3, 0x3183, 0xA4F4, 0x3184, 0xA4F5, 0x3185,
+	0xA4F6, 0x3186, 0xA4F7, 0x3187, 0xA4F8, 0x3188, 0xA4F9, 0x3189,
+	0xA4FA, 0x318A, 0xA4FB, 0x318B, 0xA4FC, 0x318C, 0xA4FD, 0x318D,
+	0xA4FE, 0x318E, 0xA541, 0xCA47, 0xA542, 0xCA48, 0xA543, 0xCA49,
+	0xA544, 0xCA4A, 0xA545, 0xCA4B, 0xA546, 0xCA4E, 0xA547, 0xCA4F,
+	0xA548, 0xCA51, 0xA549, 0xCA52, 0xA54A, 0xCA53, 0xA54B, 0xCA55,
+	0xA54C, 0xCA56, 0xA54D, 0xCA57, 0xA54E, 0xCA58, 0xA54F, 0xCA59,
+	0xA550, 0xCA5A, 0xA551, 0xCA5B, 0xA552, 0xCA5E, 0xA553, 0xCA62,
+	0xA554, 0xCA63, 0xA555, 0xCA64, 0xA556, 0xCA65, 0xA557, 0xCA66,
+	0xA558, 0xCA67, 0xA559, 0xCA69, 0xA55A, 0xCA6A, 0xA561, 0xCA6B,
+	0xA562, 0xCA6C, 0xA563, 0xCA6D, 0xA564, 0xCA6E, 0xA565, 0xCA6F,
+	0xA566, 0xCA70, 0xA567, 0xCA71, 0xA568, 0xCA72, 0xA569, 0xCA73,
+	0xA56A, 0xCA74, 0xA56B, 0xCA75, 0xA56C, 0xCA76, 0xA56D, 0xCA77,
+	0xA56E, 0xCA78, 0xA56F, 0xCA79, 0xA570, 0xCA7A, 0xA571, 0xCA7B,
+	0xA572, 0xCA7C, 0xA573, 0xCA7E, 0xA574, 0xCA7F, 0xA575, 0xCA80,
+	0xA576, 0xCA81, 0xA577, 0xCA82, 0xA578, 0xCA83, 0xA579, 0xCA85,
+	0xA57A, 0xCA86, 0xA581, 0xCA87, 0xA582, 0xCA88, 0xA583, 0xCA89,
+	0xA584, 0xCA8A, 0xA585, 0xCA8B, 0xA586, 0xCA8C, 0xA587, 0xCA8D,
+	0xA588, 0xCA8E, 0xA589, 0xCA8F, 0xA58A, 0xCA90, 0xA58B, 0xCA91,
+	0xA58C, 0xCA92, 0xA58D, 0xCA93, 0xA58E, 0xCA94, 0xA58F, 0xCA95,
+	0xA590, 0xCA96, 0xA591, 0xCA97, 0xA592, 0xCA99, 0xA593, 0xCA9A,
+	0xA594, 0xCA9B, 0xA595, 0xCA9C, 0xA596, 0xCA9D, 0xA597, 0xCA9E,
+	0xA598, 0xCA9F, 0xA599, 0xCAA0, 0xA59A, 0xCAA1, 0xA59B, 0xCAA2,
+	0xA59C, 0xCAA3, 0xA59D, 0xCAA4, 0xA59E, 0xCAA5, 0xA59F, 0xCAA6,
+	0xA5A0, 0xCAA7, 0xA5A1, 0x2170, 0xA5A2, 0x2171, 0xA5A3, 0x2172,
+	0xA5A4, 0x2173, 0xA5A5, 0x2174, 0xA5A6, 0x2175, 0xA5A7, 0x2176,
+	0xA5A8, 0x2177, 0xA5A9, 0x2178, 0xA5AA, 0x2179, 0xA5B0, 0x2160,
+	0xA5B1, 0x2161, 0xA5B2, 0x2162, 0xA5B3, 0x2163, 0xA5B4, 0x2164,
+	0xA5B5, 0x2165, 0xA5B6, 0x2166, 0xA5B7, 0x2167, 0xA5B8, 0x2168,
+	0xA5B9, 0x2169, 0xA5C1, 0x0391, 0xA5C2, 0x0392, 0xA5C3, 0x0393,
+	0xA5C4, 0x0394, 0xA5C5, 0x0395, 0xA5C6, 0x0396, 0xA5C7, 0x0397,
+	0xA5C8, 0x0398, 0xA5C9, 0x0399, 0xA5CA, 0x039A, 0xA5CB, 0x039B,
+	0xA5CC, 0x039C, 0xA5CD, 0x039D, 0xA5CE, 0x039E, 0xA5CF, 0x039F,
+	0xA5D0, 0x03A0, 0xA5D1, 0x03A1, 0xA5D2, 0x03A3, 0xA5D3, 0x03A4,
+	0xA5D4, 0x03A5, 0xA5D5, 0x03A6, 0xA5D6, 0x03A7, 0xA5D7, 0x03A8,
+	0xA5D8, 0x03A9, 0xA5E1, 0x03B1, 0xA5E2, 0x03B2, 0xA5E3, 0x03B3,
+	0xA5E4, 0x03B4, 0xA5E5, 0x03B5, 0xA5E6, 0x03B6, 0xA5E7, 0x03B7,
+	0xA5E8, 0x03B8, 0xA5E9, 0x03B9, 0xA5EA, 0x03BA, 0xA5EB, 0x03BB,
+	0xA5EC, 0x03BC, 0xA5ED, 0x03BD, 0xA5EE, 0x03BE, 0xA5EF, 0x03BF,
+	0xA5F0, 0x03C0, 0xA5F1, 0x03C1, 0xA5F2, 0x03C3, 0xA5F3, 0x03C4,
+	0xA5F4, 0x03C5, 0xA5F5, 0x03C6, 0xA5F6, 0x03C7, 0xA5F7, 0x03C8,
+	0xA5F8, 0x03C9, 0xA641, 0xCAA8, 0xA642, 0xCAA9, 0xA643, 0xCAAA,
+	0xA644, 0xCAAB, 0xA645, 0xCAAC, 0xA646, 0xCAAD, 0xA647, 0xCAAE,
+	0xA648, 0xCAAF, 0xA649, 0xCAB0, 0xA64A, 0xCAB1, 0xA64B, 0xCAB2,
+	0xA64C, 0xCAB3, 0xA64D, 0xCAB4, 0xA64E, 0xCAB5, 0xA64F, 0xCAB6,
+	0xA650, 0xCAB7, 0xA651, 0xCAB8, 0xA652, 0xCAB9, 0xA653, 0xCABA,
+	0xA654, 0xCABB, 0xA655, 0xCABE, 0xA656, 0xCABF, 0xA657, 0xCAC1,
+	0xA658, 0xCAC2, 0xA659, 0xCAC3, 0xA65A, 0xCAC5, 0xA661, 0xCAC6,
+	0xA662, 0xCAC7, 0xA663, 0xCAC8, 0xA664, 0xCAC9, 0xA665, 0xCACA,
+	0xA666, 0xCACB, 0xA667, 0xCACE, 0xA668, 0xCAD0, 0xA669, 0xCAD2,
+	0xA66A, 0xCAD4, 0xA66B, 0xCAD5, 0xA66C, 0xCAD6, 0xA66D, 0xCAD7,
+	0xA66E, 0xCADA, 0xA66F, 0xCADB, 0xA670, 0xCADC, 0xA671, 0xCADD,
+	0xA672, 0xCADE, 0xA673, 0xCADF, 0xA674, 0xCAE1, 0xA675, 0xCAE2,
+	0xA676, 0xCAE3, 0xA677, 0xCAE4, 0xA678, 0xCAE5, 0xA679, 0xCAE6,
+	0xA67A, 0xCAE7, 0xA681, 0xCAE8, 0xA682, 0xCAE9, 0xA683, 0xCAEA,
+	0xA684, 0xCAEB, 0xA685, 0xCAED, 0xA686, 0xCAEE, 0xA687, 0xCAEF,
+	0xA688, 0xCAF0, 0xA689, 0xCAF1, 0xA68A, 0xCAF2, 0xA68B, 0xCAF3,
+	0xA68C, 0xCAF5, 0xA68D, 0xCAF6, 0xA68E, 0xCAF7, 0xA68F, 0xCAF8,
+	0xA690, 0xCAF9, 0xA691, 0xCAFA, 0xA692, 0xCAFB, 0xA693, 0xCAFC,
+	0xA694, 0xCAFD, 0xA695, 0xCAFE, 0xA696, 0xCAFF, 0xA697, 0xCB00,
+	0xA698, 0xCB01, 0xA699, 0xCB02, 0xA69A, 0xCB03, 0xA69B, 0xCB04,
+	0xA69C, 0xCB05, 0xA69D, 0xCB06, 0xA69E, 0xCB07, 0xA69F, 0xCB09,
+	0xA6A0, 0xCB0A, 0xA6A1, 0x2500, 0xA6A2, 0x2502, 0xA6A3, 0x250C,
+	0xA6A4, 0x2510, 0xA6A5, 0x2518, 0xA6A6, 0x2514, 0xA6A7, 0x251C,
+	0xA6A8, 0x252C, 0xA6A9, 0x2524, 0xA6AA, 0x2534, 0xA6AB, 0x253C,
+	0xA6AC, 0x2501, 0xA6AD, 0x2503, 0xA6AE, 0x250F, 0xA6AF, 0x2513,
+	0xA6B0, 0x251B, 0xA6B1, 0x2517, 0xA6B2, 0x2523, 0xA6B3, 0x2533,
+	0xA6B4, 0x252B, 0xA6B5, 0x253B, 0xA6B6, 0x254B, 0xA6B7, 0x2520,
+	0xA6B8, 0x252F, 0xA6B9, 0x2528, 0xA6BA, 0x2537, 0xA6BB, 0x253F,
+	0xA6BC, 0x251D, 0xA6BD, 0x2530, 0xA6BE, 0x2525, 0xA6BF, 0x2538,
+	0xA6C0, 0x2542, 0xA6C1, 0x2512, 0xA6C2, 0x2511, 0xA6C3, 0x251A,
+	0xA6C4, 0x2519, 0xA6C5, 0x2516, 0xA6C6, 0x2515, 0xA6C7, 0x250E,
+	0xA6C8, 0x250D, 0xA6C9, 0x251E, 0xA6CA, 0x251F, 0xA6CB, 0x2521,
+	0xA6CC, 0x2522, 0xA6CD, 0x2526, 0xA6CE, 0x2527, 0xA6CF, 0x2529,
+	0xA6D0, 0x252A, 0xA6D1, 0x252D, 0xA6D2, 0x252E, 0xA6D3, 0x2531,
+	0xA6D4, 0x2532, 0xA6D5, 0x2535, 0xA6D6, 0x2536, 0xA6D7, 0x2539,
+	0xA6D8, 0x253A, 0xA6D9, 0x253D, 0xA6DA, 0x253E, 0xA6DB, 0x2540,
+	0xA6DC, 0x2541, 0xA6DD, 0x2543, 0xA6DE, 0x2544, 0xA6DF, 0x2545,
+	0xA6E0, 0x2546, 0xA6E1, 0x2547, 0xA6E2, 0x2548, 0xA6E3, 0x2549,
+	0xA6E4, 0x254A, 0xA741, 0xCB0B, 0xA742, 0xCB0C, 0xA743, 0xCB0D,
+	0xA744, 0xCB0E, 0xA745, 0xCB0F, 0xA746, 0xCB11, 0xA747, 0xCB12,
+	0xA748, 0xCB13, 0xA749, 0xCB15, 0xA74A, 0xCB16, 0xA74B, 0xCB17,
+	0xA74C, 0xCB19, 0xA74D, 0xCB1A, 0xA74E, 0xCB1B, 0xA74F, 0xCB1C,
+	0xA750, 0xCB1D, 0xA751, 0xCB1E, 0xA752, 0xCB1F, 0xA753, 0xCB22,
+	0xA754, 0xCB23, 0xA755, 0xCB24, 0xA756, 0xCB25, 0xA757, 0xCB26,
+	0xA758, 0xCB27, 0xA759, 0xCB28, 0xA75A, 0xCB29, 0xA761, 0xCB2A,
+	0xA762, 0xCB2B, 0xA763, 0xCB2C, 0xA764, 0xCB2D, 0xA765, 0xCB2E,
+	0xA766, 0xCB2F, 0xA767, 0xCB30, 0xA768, 0xCB31, 0xA769, 0xCB32,
+	0xA76A, 0xCB33, 0xA76B, 0xCB34, 0xA76C, 0xCB35, 0xA76D, 0xCB36,
+	0xA76E, 0xCB37, 0xA76F, 0xCB38, 0xA770, 0xCB39, 0xA771, 0xCB3A,
+	0xA772, 0xCB3B, 0xA773, 0xCB3C, 0xA774, 0xCB3D, 0xA775, 0xCB3E,
+	0xA776, 0xCB3F, 0xA777, 0xCB40, 0xA778, 0xCB42, 0xA779, 0xCB43,
+	0xA77A, 0xCB44, 0xA781, 0xCB45, 0xA782, 0xCB46, 0xA783, 0xCB47,
+	0xA784, 0xCB4A, 0xA785, 0xCB4B, 0xA786, 0xCB4D, 0xA787, 0xCB4E,
+	0xA788, 0xCB4F, 0xA789, 0xCB51, 0xA78A, 0xCB52, 0xA78B, 0xCB53,
+	0xA78C, 0xCB54, 0xA78D, 0xCB55, 0xA78E, 0xCB56, 0xA78F, 0xCB57,
+	0xA790, 0xCB5A, 0xA791, 0xCB5B, 0xA792, 0xCB5C, 0xA793, 0xCB5E,
+	0xA794, 0xCB5F, 0xA795, 0xCB60, 0xA796, 0xCB61, 0xA797, 0xCB62,
+	0xA798, 0xCB63, 0xA799, 0xCB65, 0xA79A, 0xCB66, 0xA79B, 0xCB67,
+	0xA79C, 0xCB68, 0xA79D, 0xCB69, 0xA79E, 0xCB6A, 0xA79F, 0xCB6B,
+	0xA7A0, 0xCB6C, 0xA7A1, 0x3395, 0xA7A2, 0x3396, 0xA7A3, 0x3397,
+	0xA7A4, 0x2113, 0xA7A5, 0x3398, 0xA7A6, 0x33C4, 0xA7A7, 0x33A3,
+	0xA7A8, 0x33A4, 0xA7A9, 0x33A5, 0xA7AA, 0x33A6, 0xA7AB, 0x3399,
+	0xA7AC, 0x339A, 0xA7AD, 0x339B, 0xA7AE, 0x339C, 0xA7AF, 0x339D,
+	0xA7B0, 0x339E, 0xA7B1, 0x339F, 0xA7B2, 0x33A0, 0xA7B3, 0x33A1,
+	0xA7B4, 0x33A2, 0xA7B5, 0x33CA, 0xA7B6, 0x338D, 0xA7B7, 0x338E,
+	0xA7B8, 0x338F, 0xA7B9, 0x33CF, 0xA7BA, 0x3388, 0xA7BB, 0x3389,
+	0xA7BC, 0x33C8, 0xA7BD, 0x33A7, 0xA7BE, 0x33A8, 0xA7BF, 0x33B0,
+	0xA7C0, 0x33B1, 0xA7C1, 0x33B2, 0xA7C2, 0x33B3, 0xA7C3, 0x33B4,
+	0xA7C4, 0x33B5, 0xA7C5, 0x33B6, 0xA7C6, 0x33B7, 0xA7C7, 0x33B8,
+	0xA7C8, 0x33B9, 0xA7C9, 0x3380, 0xA7CA, 0x3381, 0xA7CB, 0x3382,
+	0xA7CC, 0x3383, 0xA7CD, 0x3384, 0xA7CE, 0x33BA, 0xA7CF, 0x33BB,
+	0xA7D0, 0x33BC, 0xA7D1, 0x33BD, 0xA7D2, 0x33BE, 0xA7D3, 0x33BF,
+	0xA7D4, 0x3390, 0xA7D5, 0x3391, 0xA7D6, 0x3392, 0xA7D7, 0x3393,
+	0xA7D8, 0x3394, 0xA7D9, 0x2126, 0xA7DA, 0x33C0, 0xA7DB, 0x33C1,
+	0xA7DC, 0x338A, 0xA7DD, 0x338B, 0xA7DE, 0x338C, 0xA7DF, 0x33D6,
+	0xA7E0, 0x33C5, 0xA7E1, 0x33AD, 0xA7E2, 0x33AE, 0xA7E3, 0x33AF,
+	0xA7E4, 0x33DB, 0xA7E5, 0x33A9, 0xA7E6, 0x33AA, 0xA7E7, 0x33AB,
+	0xA7E8, 0x33AC, 0xA7E9, 0x33DD, 0xA7EA, 0x33D0, 0xA7EB, 0x33D3,
+	0xA7EC, 0x33C3, 0xA7ED, 0x33C9, 0xA7EE, 0x33DC, 0xA7EF, 0x33C6,
+	0xA841, 0xCB6D, 0xA842, 0xCB6E, 0xA843, 0xCB6F, 0xA844, 0xCB70,
+	0xA845, 0xCB71, 0xA846, 0xCB72, 0xA847, 0xCB73, 0xA848, 0xCB74,
+	0xA849, 0xCB75, 0xA84A, 0xCB76, 0xA84B, 0xCB77, 0xA84C, 0xCB7A,
+	0xA84D, 0xCB7B, 0xA84E, 0xCB7C, 0xA84F, 0xCB7D, 0xA850, 0xCB7E,
+	0xA851, 0xCB7F, 0xA852, 0xCB80, 0xA853, 0xCB81, 0xA854, 0xCB82,
+	0xA855, 0xCB83, 0xA856, 0xCB84, 0xA857, 0xCB85, 0xA858, 0xCB86,
+	0xA859, 0xCB87, 0xA85A, 0xCB88, 0xA861, 0xCB89, 0xA862, 0xCB8A,
+	0xA863, 0xCB8B, 0xA864, 0xCB8C, 0xA865, 0xCB8D, 0xA866, 0xCB8E,
+	0xA867, 0xCB8F, 0xA868, 0xCB90, 0xA869, 0xCB91, 0xA86A, 0xCB92,
+	0xA86B, 0xCB93, 0xA86C, 0xCB94, 0xA86D, 0xCB95, 0xA86E, 0xCB96,
+	0xA86F, 0xCB97, 0xA870, 0xCB98, 0xA871, 0xCB99, 0xA872, 0xCB9A,
+	0xA873, 0xCB9B, 0xA874, 0xCB9D, 0xA875, 0xCB9E, 0xA876, 0xCB9F,
+	0xA877, 0xCBA0, 0xA878, 0xCBA1, 0xA879, 0xCBA2, 0xA87A, 0xCBA3,
+	0xA881, 0xCBA4, 0xA882, 0xCBA5, 0xA883, 0xCBA6, 0xA884, 0xCBA7,
+	0xA885, 0xCBA8, 0xA886, 0xCBA9, 0xA887, 0xCBAA, 0xA888, 0xCBAB,
+	0xA889, 0xCBAC, 0xA88A, 0xCBAD, 0xA88B, 0xCBAE, 0xA88C, 0xCBAF,
+	0xA88D, 0xCBB0, 0xA88E, 0xCBB1, 0xA88F, 0xCBB2, 0xA890, 0xCBB3,
+	0xA891, 0xCBB4, 0xA892, 0xCBB5, 0xA893, 0xCBB6, 0xA894, 0xCBB7,
+	0xA895, 0xCBB9, 0xA896, 0xCBBA, 0xA897, 0xCBBB, 0xA898, 0xCBBC,
+	0xA899, 0xCBBD, 0xA89A, 0xCBBE, 0xA89B, 0xCBBF, 0xA89C, 0xCBC0,
+	0xA89D, 0xCBC1, 0xA89E, 0xCBC2, 0xA89F, 0xCBC3, 0xA8A0, 0xCBC4,
+	0xA8A1, 0x00C6, 0xA8A2, 0x00D0, 0xA8A3, 0x00AA, 0xA8A4, 0x0126,
+	0xA8A6, 0x0132, 0xA8A8, 0x013F, 0xA8A9, 0x0141, 0xA8AA, 0x00D8,
+	0xA8AB, 0x0152, 0xA8AC, 0x00BA, 0xA8AD, 0x00DE, 0xA8AE, 0x0166,
+	0xA8AF, 0x014A, 0xA8B1, 0x3260, 0xA8B2, 0x3261, 0xA8B3, 0x3262,
+	0xA8B4, 0x3263, 0xA8B5, 0x3264, 0xA8B6, 0x3265, 0xA8B7, 0x3266,
+	0xA8B8, 0x3267, 0xA8B9, 0x3268, 0xA8BA, 0x3269, 0xA8BB, 0x326A,
+	0xA8BC, 0x326B, 0xA8BD, 0x326C, 0xA8BE, 0x326D, 0xA8BF, 0x326E,
+	0xA8C0, 0x326F, 0xA8C1, 0x3270, 0xA8C2, 0x3271, 0xA8C3, 0x3272,
+	0xA8C4, 0x3273, 0xA8C5, 0x3274, 0xA8C6, 0x3275, 0xA8C7, 0x3276,
+	0xA8C8, 0x3277, 0xA8C9, 0x3278, 0xA8CA, 0x3279, 0xA8CB, 0x327A,
+	0xA8CC, 0x327B, 0xA8CD, 0x24D0, 0xA8CE, 0x24D1, 0xA8CF, 0x24D2,
+	0xA8D0, 0x24D3, 0xA8D1, 0x24D4, 0xA8D2, 0x24D5, 0xA8D3, 0x24D6,
+	0xA8D4, 0x24D7, 0xA8D5, 0x24D8, 0xA8D6, 0x24D9, 0xA8D7, 0x24DA,
+	0xA8D8, 0x24DB, 0xA8D9, 0x24DC, 0xA8DA, 0x24DD, 0xA8DB, 0x24DE,
+	0xA8DC, 0x24DF, 0xA8DD, 0x24E0, 0xA8DE, 0x24E1, 0xA8DF, 0x24E2,
+	0xA8E0, 0x24E3, 0xA8E1, 0x24E4, 0xA8E2, 0x24E5, 0xA8E3, 0x24E6,
+	0xA8E4, 0x24E7, 0xA8E5, 0x24E8, 0xA8E6, 0x24E9, 0xA8E7, 0x2460,
+	0xA8E8, 0x2461, 0xA8E9, 0x2462, 0xA8EA, 0x2463, 0xA8EB, 0x2464,
+	0xA8EC, 0x2465, 0xA8ED, 0x2466, 0xA8EE, 0x2467, 0xA8EF, 0x2468,
+	0xA8F0, 0x2469, 0xA8F1, 0x246A, 0xA8F2, 0x246B, 0xA8F3, 0x246C,
+	0xA8F4, 0x246D, 0xA8F5, 0x246E, 0xA8F6, 0x00BD, 0xA8F7, 0x2153,
+	0xA8F8, 0x2154, 0xA8F9, 0x00BC, 0xA8FA, 0x00BE, 0xA8FB, 0x215B,
+	0xA8FC, 0x215C, 0xA8FD, 0x215D, 0xA8FE, 0x215E, 0xA941, 0xCBC5,
+	0xA942, 0xCBC6, 0xA943, 0xCBC7, 0xA944, 0xCBC8, 0xA945, 0xCBC9,
+	0xA946, 0xCBCA, 0xA947, 0xCBCB, 0xA948, 0xCBCC, 0xA949, 0xCBCD,
+	0xA94A, 0xCBCE, 0xA94B, 0xCBCF, 0xA94C, 0xCBD0, 0xA94D, 0xCBD1,
+	0xA94E, 0xCBD2, 0xA94F, 0xCBD3, 0xA950, 0xCBD5, 0xA951, 0xCBD6,
+	0xA952, 0xCBD7, 0xA953, 0xCBD8, 0xA954, 0xCBD9, 0xA955, 0xCBDA,
+	0xA956, 0xCBDB, 0xA957, 0xCBDC, 0xA958, 0xCBDD, 0xA959, 0xCBDE,
+	0xA95A, 0xCBDF, 0xA961, 0xCBE0, 0xA962, 0xCBE1, 0xA963, 0xCBE2,
+	0xA964, 0xCBE3, 0xA965, 0xCBE5, 0xA966, 0xCBE6, 0xA967, 0xCBE8,
+	0xA968, 0xCBEA, 0xA969, 0xCBEB, 0xA96A, 0xCBEC, 0xA96B, 0xCBED,
+	0xA96C, 0xCBEE, 0xA96D, 0xCBEF, 0xA96E, 0xCBF0, 0xA96F, 0xCBF1,
+	0xA970, 0xCBF2, 0xA971, 0xCBF3, 0xA972, 0xCBF4, 0xA973, 0xCBF5,
+	0xA974, 0xCBF6, 0xA975, 0xCBF7, 0xA976, 0xCBF8, 0xA977, 0xCBF9,
+	0xA978, 0xCBFA, 0xA979, 0xCBFB, 0xA97A, 0xCBFC, 0xA981, 0xCBFD,
+	0xA982, 0xCBFE, 0xA983, 0xCBFF, 0xA984, 0xCC00, 0xA985, 0xCC01,
+	0xA986, 0xCC02, 0xA987, 0xCC03, 0xA988, 0xCC04, 0xA989, 0xCC05,
+	0xA98A, 0xCC06, 0xA98B, 0xCC07, 0xA98C, 0xCC08, 0xA98D, 0xCC09,
+	0xA98E, 0xCC0A, 0xA98F, 0xCC0B, 0xA990, 0xCC0E, 0xA991, 0xCC0F,
+	0xA992, 0xCC11, 0xA993, 0xCC12, 0xA994, 0xCC13, 0xA995, 0xCC15,
+	0xA996, 0xCC16, 0xA997, 0xCC17, 0xA998, 0xCC18, 0xA999, 0xCC19,
+	0xA99A, 0xCC1A, 0xA99B, 0xCC1B, 0xA99C, 0xCC1E, 0xA99D, 0xCC1F,
+	0xA99E, 0xCC20, 0xA99F, 0xCC23, 0xA9A0, 0xCC24, 0xA9A1, 0x00E6,
+	0xA9A2, 0x0111, 0xA9A3, 0x00F0, 0xA9A4, 0x0127, 0xA9A5, 0x0131,
+	0xA9A6, 0x0133, 0xA9A7, 0x0138, 0xA9A8, 0x0140, 0xA9A9, 0x0142,
+	0xA9AA, 0x00F8, 0xA9AB, 0x0153, 0xA9AC, 0x00DF, 0xA9AD, 0x00FE,
+	0xA9AE, 0x0167, 0xA9AF, 0x014B, 0xA9B0, 0x0149, 0xA9B1, 0x3200,
+	0xA9B2, 0x3201, 0xA9B3, 0x3202, 0xA9B4, 0x3203, 0xA9B5, 0x3204,
+	0xA9B6, 0x3205, 0xA9B7, 0x3206, 0xA9B8, 0x3207, 0xA9B9, 0x3208,
+	0xA9BA, 0x3209, 0xA9BB, 0x320A, 0xA9BC, 0x320B, 0xA9BD, 0x320C,
+	0xA9BE, 0x320D, 0xA9BF, 0x320E, 0xA9C0, 0x320F, 0xA9C1, 0x3210,
+	0xA9C2, 0x3211, 0xA9C3, 0x3212, 0xA9C4, 0x3213, 0xA9C5, 0x3214,
+	0xA9C6, 0x3215, 0xA9C7, 0x3216, 0xA9C8, 0x3217, 0xA9C9, 0x3218,
+	0xA9CA, 0x3219, 0xA9CB, 0x321A, 0xA9CC, 0x321B, 0xA9CD, 0x249C,
+	0xA9CE, 0x249D, 0xA9CF, 0x249E, 0xA9D0, 0x249F, 0xA9D1, 0x24A0,
+	0xA9D2, 0x24A1, 0xA9D3, 0x24A2, 0xA9D4, 0x24A3, 0xA9D5, 0x24A4,
+	0xA9D6, 0x24A5, 0xA9D7, 0x24A6, 0xA9D8, 0x24A7, 0xA9D9, 0x24A8,
+	0xA9DA, 0x24A9, 0xA9DB, 0x24AA, 0xA9DC, 0x24AB, 0xA9DD, 0x24AC,
+	0xA9DE, 0x24AD, 0xA9DF, 0x24AE, 0xA9E0, 0x24AF, 0xA9E1, 0x24B0,
+	0xA9E2, 0x24B1, 0xA9E3, 0x24B2, 0xA9E4, 0x24B3, 0xA9E5, 0x24B4,
+	0xA9E6, 0x24B5, 0xA9E7, 0x2474, 0xA9E8, 0x2475, 0xA9E9, 0x2476,
+	0xA9EA, 0x2477, 0xA9EB, 0x2478, 0xA9EC, 0x2479, 0xA9ED, 0x247A,
+	0xA9EE, 0x247B, 0xA9EF, 0x247C, 0xA9F0, 0x247D, 0xA9F1, 0x247E,
+	0xA9F2, 0x247F, 0xA9F3, 0x2480, 0xA9F4, 0x2481, 0xA9F5, 0x2482,
+	0xA9F6, 0x00B9, 0xA9F7, 0x00B2, 0xA9F8, 0x00B3, 0xA9F9, 0x2074,
+	0xA9FA, 0x207F, 0xA9FB, 0x2081, 0xA9FC, 0x2082, 0xA9FD, 0x2083,
+	0xA9FE, 0x2084, 0xAA41, 0xCC25, 0xAA42, 0xCC26, 0xAA43, 0xCC2A,
+	0xAA44, 0xCC2B, 0xAA45, 0xCC2D, 0xAA46, 0xCC2F, 0xAA47, 0xCC31,
+	0xAA48, 0xCC32, 0xAA49, 0xCC33, 0xAA4A, 0xCC34, 0xAA4B, 0xCC35,
+	0xAA4C, 0xCC36, 0xAA4D, 0xCC37, 0xAA4E, 0xCC3A, 0xAA4F, 0xCC3F,
+	0xAA50, 0xCC40, 0xAA51, 0xCC41, 0xAA52, 0xCC42, 0xAA53, 0xCC43,
+	0xAA54, 0xCC46, 0xAA55, 0xCC47, 0xAA56, 0xCC49, 0xAA57, 0xCC4A,
+	0xAA58, 0xCC4B, 0xAA59, 0xCC4D, 0xAA5A, 0xCC4E, 0xAA61, 0xCC4F,
+	0xAA62, 0xCC50, 0xAA63, 0xCC51, 0xAA64, 0xCC52, 0xAA65, 0xCC53,
+	0xAA66, 0xCC56, 0xAA67, 0xCC5A, 0xAA68, 0xCC5B, 0xAA69, 0xCC5C,
+	0xAA6A, 0xCC5D, 0xAA6B, 0xCC5E, 0xAA6C, 0xCC5F, 0xAA6D, 0xCC61,
+	0xAA6E, 0xCC62, 0xAA6F, 0xCC63, 0xAA70, 0xCC65, 0xAA71, 0xCC67,
+	0xAA72, 0xCC69, 0xAA73, 0xCC6A, 0xAA74, 0xCC6B, 0xAA75, 0xCC6C,
+	0xAA76, 0xCC6D, 0xAA77, 0xCC6E, 0xAA78, 0xCC6F, 0xAA79, 0xCC71,
+	0xAA7A, 0xCC72, 0xAA81, 0xCC73, 0xAA82, 0xCC74, 0xAA83, 0xCC76,
+	0xAA84, 0xCC77, 0xAA85, 0xCC78, 0xAA86, 0xCC79, 0xAA87, 0xCC7A,
+	0xAA88, 0xCC7B, 0xAA89, 0xCC7C, 0xAA8A, 0xCC7D, 0xAA8B, 0xCC7E,
+	0xAA8C, 0xCC7F, 0xAA8D, 0xCC80, 0xAA8E, 0xCC81, 0xAA8F, 0xCC82,
+	0xAA90, 0xCC83, 0xAA91, 0xCC84, 0xAA92, 0xCC85, 0xAA93, 0xCC86,
+	0xAA94, 0xCC87, 0xAA95, 0xCC88, 0xAA96, 0xCC89, 0xAA97, 0xCC8A,
+	0xAA98, 0xCC8B, 0xAA99, 0xCC8C, 0xAA9A, 0xCC8D, 0xAA9B, 0xCC8E,
+	0xAA9C, 0xCC8F, 0xAA9D, 0xCC90, 0xAA9E, 0xCC91, 0xAA9F, 0xCC92,
+	0xAAA0, 0xCC93, 0xAAA1, 0x3041, 0xAAA2, 0x3042, 0xAAA3, 0x3043,
+	0xAAA4, 0x3044, 0xAAA5, 0x3045, 0xAAA6, 0x3046, 0xAAA7, 0x3047,
+	0xAAA8, 0x3048, 0xAAA9, 0x3049, 0xAAAA, 0x304A, 0xAAAB, 0x304B,
+	0xAAAC, 0x304C, 0xAAAD, 0x304D, 0xAAAE, 0x304E, 0xAAAF, 0x304F,
+	0xAAB0, 0x3050, 0xAAB1, 0x3051, 0xAAB2, 0x3052, 0xAAB3, 0x3053,
+	0xAAB4, 0x3054, 0xAAB5, 0x3055, 0xAAB6, 0x3056, 0xAAB7, 0x3057,
+	0xAAB8, 0x3058, 0xAAB9, 0x3059, 0xAABA, 0x305A, 0xAABB, 0x305B,
+	0xAABC, 0x305C, 0xAABD, 0x305D, 0xAABE, 0x305E, 0xAABF, 0x305F,
+	0xAAC0, 0x3060, 0xAAC1, 0x3061, 0xAAC2, 0x3062, 0xAAC3, 0x3063,
+	0xAAC4, 0x3064, 0xAAC5, 0x3065, 0xAAC6, 0x3066, 0xAAC7, 0x3067,
+	0xAAC8, 0x3068, 0xAAC9, 0x3069, 0xAACA, 0x306A, 0xAACB, 0x306B,
+	0xAACC, 0x306C, 0xAACD, 0x306D, 0xAACE, 0x306E, 0xAACF, 0x306F,
+	0xAAD0, 0x3070, 0xAAD1, 0x3071, 0xAAD2, 0x3072, 0xAAD3, 0x3073,
+	0xAAD4, 0x3074, 0xAAD5, 0x3075, 0xAAD6, 0x3076, 0xAAD7, 0x3077,
+	0xAAD8, 0x3078, 0xAAD9, 0x3079, 0xAADA, 0x307A, 0xAADB, 0x307B,
+	0xAADC, 0x307C, 0xAADD, 0x307D, 0xAADE, 0x307E, 0xAADF, 0x307F,
+	0xAAE0, 0x3080, 0xAAE1, 0x3081, 0xAAE2, 0x3082, 0xAAE3, 0x3083,
+	0xAAE4, 0x3084, 0xAAE5, 0x3085, 0xAAE6, 0x3086, 0xAAE7, 0x3087,
+	0xAAE8, 0x3088, 0xAAE9, 0x3089, 0xAAEA, 0x308A, 0xAAEB, 0x308B,
+	0xAAEC, 0x308C, 0xAAED, 0x308D, 0xAAEE, 0x308E, 0xAAEF, 0x308F,
+	0xAAF0, 0x3090, 0xAAF1, 0x3091, 0xAAF2, 0x3092, 0xAAF3, 0x3093,
+	0xAB41, 0xCC94, 0xAB42, 0xCC95, 0xAB43, 0xCC96, 0xAB44, 0xCC97,
+	0xAB45, 0xCC9A, 0xAB46, 0xCC9B, 0xAB47, 0xCC9D, 0xAB48, 0xCC9E,
+	0xAB49, 0xCC9F, 0xAB4A, 0xCCA1, 0xAB4B, 0xCCA2, 0xAB4C, 0xCCA3,
+	0xAB4D, 0xCCA4, 0xAB4E, 0xCCA5, 0xAB4F, 0xCCA6, 0xAB50, 0xCCA7,
+	0xAB51, 0xCCAA, 0xAB52, 0xCCAE, 0xAB53, 0xCCAF, 0xAB54, 0xCCB0,
+	0xAB55, 0xCCB1, 0xAB56, 0xCCB2, 0xAB57, 0xCCB3, 0xAB58, 0xCCB6,
+	0xAB59, 0xCCB7, 0xAB5A, 0xCCB9, 0xAB61, 0xCCBA, 0xAB62, 0xCCBB,
+	0xAB63, 0xCCBD, 0xAB64, 0xCCBE, 0xAB65, 0xCCBF, 0xAB66, 0xCCC0,
+	0xAB67, 0xCCC1, 0xAB68, 0xCCC2, 0xAB69, 0xCCC3, 0xAB6A, 0xCCC6,
+	0xAB6B, 0xCCC8, 0xAB6C, 0xCCCA, 0xAB6D, 0xCCCB, 0xAB6E, 0xCCCC,
+	0xAB6F, 0xCCCD, 0xAB70, 0xCCCE, 0xAB71, 0xCCCF, 0xAB72, 0xCCD1,
+	0xAB73, 0xCCD2, 0xAB74, 0xCCD3, 0xAB75, 0xCCD5, 0xAB76, 0xCCD6,
+	0xAB77, 0xCCD7, 0xAB78, 0xCCD8, 0xAB79, 0xCCD9, 0xAB7A, 0xCCDA,
+	0xAB81, 0xCCDB, 0xAB82, 0xCCDC, 0xAB83, 0xCCDD, 0xAB84, 0xCCDE,
+	0xAB85, 0xCCDF, 0xAB86, 0xCCE0, 0xAB87, 0xCCE1, 0xAB88, 0xCCE2,
+	0xAB89, 0xCCE3, 0xAB8A, 0xCCE5, 0xAB8B, 0xCCE6, 0xAB8C, 0xCCE7,
+	0xAB8D, 0xCCE8, 0xAB8E, 0xCCE9, 0xAB8F, 0xCCEA, 0xAB90, 0xCCEB,
+	0xAB91, 0xCCED, 0xAB92, 0xCCEE, 0xAB93, 0xCCEF, 0xAB94, 0xCCF1,
+	0xAB95, 0xCCF2, 0xAB96, 0xCCF3, 0xAB97, 0xCCF4, 0xAB98, 0xCCF5,
+	0xAB99, 0xCCF6, 0xAB9A, 0xCCF7, 0xAB9B, 0xCCF8, 0xAB9C, 0xCCF9,
+	0xAB9D, 0xCCFA, 0xAB9E, 0xCCFB, 0xAB9F, 0xCCFC, 0xABA0, 0xCCFD,
+	0xABA1, 0x30A1, 0xABA2, 0x30A2, 0xABA3, 0x30A3, 0xABA4, 0x30A4,
+	0xABA5, 0x30A5, 0xABA6, 0x30A6, 0xABA7, 0x30A7, 0xABA8, 0x30A8,
+	0xABA9, 0x30A9, 0xABAA, 0x30AA, 0xABAB, 0x30AB, 0xABAC, 0x30AC,
+	0xABAD, 0x30AD, 0xABAE, 0x30AE, 0xABAF, 0x30AF, 0xABB0, 0x30B0,
+	0xABB1, 0x30B1, 0xABB2, 0x30B2, 0xABB3, 0x30B3, 0xABB4, 0x30B4,
+	0xABB5, 0x30B5, 0xABB6, 0x30B6, 0xABB7, 0x30B7, 0xABB8, 0x30B8,
+	0xABB9, 0x30B9, 0xABBA, 0x30BA, 0xABBB, 0x30BB, 0xABBC, 0x30BC,
+	0xABBD, 0x30BD, 0xABBE, 0x30BE, 0xABBF, 0x30BF, 0xABC0, 0x30C0,
+	0xABC1, 0x30C1, 0xABC2, 0x30C2, 0xABC3, 0x30C3, 0xABC4, 0x30C4,
+	0xABC5, 0x30C5, 0xABC6, 0x30C6, 0xABC7, 0x30C7, 0xABC8, 0x30C8,
+	0xABC9, 0x30C9, 0xABCA, 0x30CA, 0xABCB, 0x30CB, 0xABCC, 0x30CC,
+	0xABCD, 0x30CD, 0xABCE, 0x30CE, 0xABCF, 0x30CF, 0xABD0, 0x30D0,
+	0xABD1, 0x30D1, 0xABD2, 0x30D2, 0xABD3, 0x30D3, 0xABD4, 0x30D4,
+	0xABD5, 0x30D5, 0xABD6, 0x30D6, 0xABD7, 0x30D7, 0xABD8, 0x30D8,
+	0xABD9, 0x30D9, 0xABDA, 0x30DA, 0xABDB, 0x30DB, 0xABDC, 0x30DC,
+	0xABDD, 0x30DD, 0xABDE, 0x30DE, 0xABDF, 0x30DF, 0xABE0, 0x30E0,
+	0xABE1, 0x30E1, 0xABE2, 0x30E2, 0xABE3, 0x30E3, 0xABE4, 0x30E4,
+	0xABE5, 0x30E5, 0xABE6, 0x30E6, 0xABE7, 0x30E7, 0xABE8, 0x30E8,
+	0xABE9, 0x30E9, 0xABEA, 0x30EA, 0xABEB, 0x30EB, 0xABEC, 0x30EC,
+	0xABED, 0x30ED, 0xABEE, 0x30EE, 0xABEF, 0x30EF, 0xABF0, 0x30F0,
+	0xABF1, 0x30F1, 0xABF2, 0x30F2, 0xABF3, 0x30F3, 0xABF4, 0x30F4,
+	0xABF5, 0x30F5, 0xABF6, 0x30F6, 0xAC41, 0xCCFE, 0xAC42, 0xCCFF,
+	0xAC43, 0xCD00, 0xAC44, 0xCD02, 0xAC45, 0xCD03, 0xAC46, 0xCD04,
+	0xAC47, 0xCD05, 0xAC48, 0xCD06, 0xAC49, 0xCD07, 0xAC4A, 0xCD0A,
+	0xAC4B, 0xCD0B, 0xAC4C, 0xCD0D, 0xAC4D, 0xCD0E, 0xAC4E, 0xCD0F,
+	0xAC4F, 0xCD11, 0xAC50, 0xCD12, 0xAC51, 0xCD13, 0xAC52, 0xCD14,
+	0xAC53, 0xCD15, 0xAC54, 0xCD16, 0xAC55, 0xCD17, 0xAC56, 0xCD1A,
+	0xAC57, 0xCD1C, 0xAC58, 0xCD1E, 0xAC59, 0xCD1F, 0xAC5A, 0xCD20,
+	0xAC61, 0xCD21, 0xAC62, 0xCD22, 0xAC63, 0xCD23, 0xAC64, 0xCD25,
+	0xAC65, 0xCD26, 0xAC66, 0xCD27, 0xAC67, 0xCD29, 0xAC68, 0xCD2A,
+	0xAC69, 0xCD2B, 0xAC6A, 0xCD2D, 0xAC6B, 0xCD2E, 0xAC6C, 0xCD2F,
+	0xAC6D, 0xCD30, 0xAC6E, 0xCD31, 0xAC6F, 0xCD32, 0xAC70, 0xCD33,
+	0xAC71, 0xCD34, 0xAC72, 0xCD35, 0xAC73, 0xCD36, 0xAC74, 0xCD37,
+	0xAC75, 0xCD38, 0xAC76, 0xCD3A, 0xAC77, 0xCD3B, 0xAC78, 0xCD3C,
+	0xAC79, 0xCD3D, 0xAC7A, 0xCD3E, 0xAC81, 0xCD3F, 0xAC82, 0xCD40,
+	0xAC83, 0xCD41, 0xAC84, 0xCD42, 0xAC85, 0xCD43, 0xAC86, 0xCD44,
+	0xAC87, 0xCD45, 0xAC88, 0xCD46, 0xAC89, 0xCD47, 0xAC8A, 0xCD48,
+	0xAC8B, 0xCD49, 0xAC8C, 0xCD4A, 0xAC8D, 0xCD4B, 0xAC8E, 0xCD4C,
+	0xAC8F, 0xCD4D, 0xAC90, 0xCD4E, 0xAC91, 0xCD4F, 0xAC92, 0xCD50,
+	0xAC93, 0xCD51, 0xAC94, 0xCD52, 0xAC95, 0xCD53, 0xAC96, 0xCD54,
+	0xAC97, 0xCD55, 0xAC98, 0xCD56, 0xAC99, 0xCD57, 0xAC9A, 0xCD58,
+	0xAC9B, 0xCD59, 0xAC9C, 0xCD5A, 0xAC9D, 0xCD5B, 0xAC9E, 0xCD5D,
+	0xAC9F, 0xCD5E, 0xACA0, 0xCD5F, 0xACA1, 0x0410, 0xACA2, 0x0411,
+	0xACA3, 0x0412, 0xACA4, 0x0413, 0xACA5, 0x0414, 0xACA6, 0x0415,
+	0xACA7, 0x0401, 0xACA8, 0x0416, 0xACA9, 0x0417, 0xACAA, 0x0418,
+	0xACAB, 0x0419, 0xACAC, 0x041A, 0xACAD, 0x041B, 0xACAE, 0x041C,
+	0xACAF, 0x041D, 0xACB0, 0x041E, 0xACB1, 0x041F, 0xACB2, 0x0420,
+	0xACB3, 0x0421, 0xACB4, 0x0422, 0xACB5, 0x0423, 0xACB6, 0x0424,
+	0xACB7, 0x0425, 0xACB8, 0x0426, 0xACB9, 0x0427, 0xACBA, 0x0428,
+	0xACBB, 0x0429, 0xACBC, 0x042A, 0xACBD, 0x042B, 0xACBE, 0x042C,
+	0xACBF, 0x042D, 0xACC0, 0x042E, 0xACC1, 0x042F, 0xACD1, 0x0430,
+	0xACD2, 0x0431, 0xACD3, 0x0432, 0xACD4, 0x0433, 0xACD5, 0x0434,
+	0xACD6, 0x0435, 0xACD7, 0x0451, 0xACD8, 0x0436, 0xACD9, 0x0437,
+	0xACDA, 0x0438, 0xACDB, 0x0439, 0xACDC, 0x043A, 0xACDD, 0x043B,
+	0xACDE, 0x043C, 0xACDF, 0x043D, 0xACE0, 0x043E, 0xACE1, 0x043F,
+	0xACE2, 0x0440, 0xACE3, 0x0441, 0xACE4, 0x0442, 0xACE5, 0x0443,
+	0xACE6, 0x0444, 0xACE7, 0x0445, 0xACE8, 0x0446, 0xACE9, 0x0447,
+	0xACEA, 0x0448, 0xACEB, 0x0449, 0xACEC, 0x044A, 0xACED, 0x044B,
+	0xACEE, 0x044C, 0xACEF, 0x044D, 0xACF0, 0x044E, 0xACF1, 0x044F,
+	0xAD41, 0xCD61, 0xAD42, 0xCD62, 0xAD43, 0xCD63, 0xAD44, 0xCD65,
+	0xAD45, 0xCD66, 0xAD46, 0xCD67, 0xAD47, 0xCD68, 0xAD48, 0xCD69,
+	0xAD49, 0xCD6A, 0xAD4A, 0xCD6B, 0xAD4B, 0xCD6E, 0xAD4C, 0xCD70,
+	0xAD4D, 0xCD72, 0xAD4E, 0xCD73, 0xAD4F, 0xCD74, 0xAD50, 0xCD75,
+	0xAD51, 0xCD76, 0xAD52, 0xCD77, 0xAD53, 0xCD79, 0xAD54, 0xCD7A,
+	0xAD55, 0xCD7B, 0xAD56, 0xCD7C, 0xAD57, 0xCD7D, 0xAD58, 0xCD7E,
+	0xAD59, 0xCD7F, 0xAD5A, 0xCD80, 0xAD61, 0xCD81, 0xAD62, 0xCD82,
+	0xAD63, 0xCD83, 0xAD64, 0xCD84, 0xAD65, 0xCD85, 0xAD66, 0xCD86,
+	0xAD67, 0xCD87, 0xAD68, 0xCD89, 0xAD69, 0xCD8A, 0xAD6A, 0xCD8B,
+	0xAD6B, 0xCD8C, 0xAD6C, 0xCD8D, 0xAD6D, 0xCD8E, 0xAD6E, 0xCD8F,
+	0xAD6F, 0xCD90, 0xAD70, 0xCD91, 0xAD71, 0xCD92, 0xAD72, 0xCD93,
+	0xAD73, 0xCD96, 0xAD74, 0xCD97, 0xAD75, 0xCD99, 0xAD76, 0xCD9A,
+	0xAD77, 0xCD9B, 0xAD78, 0xCD9D, 0xAD79, 0xCD9E, 0xAD7A, 0xCD9F,
+	0xAD81, 0xCDA0, 0xAD82, 0xCDA1, 0xAD83, 0xCDA2, 0xAD84, 0xCDA3,
+	0xAD85, 0xCDA6, 0xAD86, 0xCDA8, 0xAD87, 0xCDAA, 0xAD88, 0xCDAB,
+	0xAD89, 0xCDAC, 0xAD8A, 0xCDAD, 0xAD8B, 0xCDAE, 0xAD8C, 0xCDAF,
+	0xAD8D, 0xCDB1, 0xAD8E, 0xCDB2, 0xAD8F, 0xCDB3, 0xAD90, 0xCDB4,
+	0xAD91, 0xCDB5, 0xAD92, 0xCDB6, 0xAD93, 0xCDB7, 0xAD94, 0xCDB8,
+	0xAD95, 0xCDB9, 0xAD96, 0xCDBA, 0xAD97, 0xCDBB, 0xAD98, 0xCDBC,
+	0xAD99, 0xCDBD, 0xAD9A, 0xCDBE, 0xAD9B, 0xCDBF, 0xAD9C, 0xCDC0,
+	0xAD9D, 0xCDC1, 0xAD9E, 0xCDC2, 0xAD9F, 0xCDC3, 0xADA0, 0xCDC5,
+	0xAE41, 0xCDC6, 0xAE42, 0xCDC7, 0xAE43, 0xCDC8, 0xAE44, 0xCDC9,
+	0xAE45, 0xCDCA, 0xAE46, 0xCDCB, 0xAE47, 0xCDCD, 0xAE48, 0xCDCE,
+	0xAE49, 0xCDCF, 0xAE4A, 0xCDD1, 0xAE4B, 0xCDD2, 0xAE4C, 0xCDD3,
+	0xAE4D, 0xCDD4, 0xAE4E, 0xCDD5, 0xAE4F, 0xCDD6, 0xAE50, 0xCDD7,
+	0xAE51, 0xCDD8, 0xAE52, 0xCDD9, 0xAE53, 0xCDDA, 0xAE54, 0xCDDB,
+	0xAE55, 0xCDDC, 0xAE56, 0xCDDD, 0xAE57, 0xCDDE, 0xAE58, 0xCDDF,
+	0xAE59, 0xCDE0, 0xAE5A, 0xCDE1, 0xAE61, 0xCDE2, 0xAE62, 0xCDE3,
+	0xAE63, 0xCDE4, 0xAE64, 0xCDE5, 0xAE65, 0xCDE6, 0xAE66, 0xCDE7,
+	0xAE67, 0xCDE9, 0xAE68, 0xCDEA, 0xAE69, 0xCDEB, 0xAE6A, 0xCDED,
+	0xAE6B, 0xCDEE, 0xAE6C, 0xCDEF, 0xAE6D, 0xCDF1, 0xAE6E, 0xCDF2,
+	0xAE6F, 0xCDF3, 0xAE70, 0xCDF4, 0xAE71, 0xCDF5, 0xAE72, 0xCDF6,
+	0xAE73, 0xCDF7, 0xAE74, 0xCDFA, 0xAE75, 0xCDFC, 0xAE76, 0xCDFE,
+	0xAE77, 0xCDFF, 0xAE78, 0xCE00, 0xAE79, 0xCE01, 0xAE7A, 0xCE02,
+	0xAE81, 0xCE03, 0xAE82, 0xCE05, 0xAE83, 0xCE06, 0xAE84, 0xCE07,
+	0xAE85, 0xCE09, 0xAE86, 0xCE0A, 0xAE87, 0xCE0B, 0xAE88, 0xCE0D,
+	0xAE89, 0xCE0E, 0xAE8A, 0xCE0F, 0xAE8B, 0xCE10, 0xAE8C, 0xCE11,
+	0xAE8D, 0xCE12, 0xAE8E, 0xCE13, 0xAE8F, 0xCE15, 0xAE90, 0xCE16,
+	0xAE91, 0xCE17, 0xAE92, 0xCE18, 0xAE93, 0xCE1A, 0xAE94, 0xCE1B,
+	0xAE95, 0xCE1C, 0xAE96, 0xCE1D, 0xAE97, 0xCE1E, 0xAE98, 0xCE1F,
+	0xAE99, 0xCE22, 0xAE9A, 0xCE23, 0xAE9B, 0xCE25, 0xAE9C, 0xCE26,
+	0xAE9D, 0xCE27, 0xAE9E, 0xCE29, 0xAE9F, 0xCE2A, 0xAEA0, 0xCE2B,
+	0xAF41, 0xCE2C, 0xAF42, 0xCE2D, 0xAF43, 0xCE2E, 0xAF44, 0xCE2F,
+	0xAF45, 0xCE32, 0xAF46, 0xCE34, 0xAF47, 0xCE36, 0xAF48, 0xCE37,
+	0xAF49, 0xCE38, 0xAF4A, 0xCE39, 0xAF4B, 0xCE3A, 0xAF4C, 0xCE3B,
+	0xAF4D, 0xCE3C, 0xAF4E, 0xCE3D, 0xAF4F, 0xCE3E, 0xAF50, 0xCE3F,
+	0xAF51, 0xCE40, 0xAF52, 0xCE41, 0xAF53, 0xCE42, 0xAF54, 0xCE43,
+	0xAF55, 0xCE44, 0xAF56, 0xCE45, 0xAF57, 0xCE46, 0xAF58, 0xCE47,
+	0xAF59, 0xCE48, 0xAF5A, 0xCE49, 0xAF61, 0xCE4A, 0xAF62, 0xCE4B,
+	0xAF63, 0xCE4C, 0xAF64, 0xCE4D, 0xAF65, 0xCE4E, 0xAF66, 0xCE4F,
+	0xAF67, 0xCE50, 0xAF68, 0xCE51, 0xAF69, 0xCE52, 0xAF6A, 0xCE53,
+	0xAF6B, 0xCE54, 0xAF6C, 0xCE55, 0xAF6D, 0xCE56, 0xAF6E, 0xCE57,
+	0xAF6F, 0xCE5A, 0xAF70, 0xCE5B, 0xAF71, 0xCE5D, 0xAF72, 0xCE5E,
+	0xAF73, 0xCE62, 0xAF74, 0xCE63, 0xAF75, 0xCE64, 0xAF76, 0xCE65,
+	0xAF77, 0xCE66, 0xAF78, 0xCE67, 0xAF79, 0xCE6A, 0xAF7A, 0xCE6C,
+	0xAF81, 0xCE6E, 0xAF82, 0xCE6F, 0xAF83, 0xCE70, 0xAF84, 0xCE71,
+	0xAF85, 0xCE72, 0xAF86, 0xCE73, 0xAF87, 0xCE76, 0xAF88, 0xCE77,
+	0xAF89, 0xCE79, 0xAF8A, 0xCE7A, 0xAF8B, 0xCE7B, 0xAF8C, 0xCE7D,
+	0xAF8D, 0xCE7E, 0xAF8E, 0xCE7F, 0xAF8F, 0xCE80, 0xAF90, 0xCE81,
+	0xAF91, 0xCE82, 0xAF92, 0xCE83, 0xAF93, 0xCE86, 0xAF94, 0xCE88,
+	0xAF95, 0xCE8A, 0xAF96, 0xCE8B, 0xAF97, 0xCE8C, 0xAF98, 0xCE8D,
+	0xAF99, 0xCE8E, 0xAF9A, 0xCE8F, 0xAF9B, 0xCE92, 0xAF9C, 0xCE93,
+	0xAF9D, 0xCE95, 0xAF9E, 0xCE96, 0xAF9F, 0xCE97, 0xAFA0, 0xCE99,
+	0xB041, 0xCE9A, 0xB042, 0xCE9B, 0xB043, 0xCE9C, 0xB044, 0xCE9D,
+	0xB045, 0xCE9E, 0xB046, 0xCE9F, 0xB047, 0xCEA2, 0xB048, 0xCEA6,
+	0xB049, 0xCEA7, 0xB04A, 0xCEA8, 0xB04B, 0xCEA9, 0xB04C, 0xCEAA,
+	0xB04D, 0xCEAB, 0xB04E, 0xCEAE, 0xB04F, 0xCEAF, 0xB050, 0xCEB0,
+	0xB051, 0xCEB1, 0xB052, 0xCEB2, 0xB053, 0xCEB3, 0xB054, 0xCEB4,
+	0xB055, 0xCEB5, 0xB056, 0xCEB6, 0xB057, 0xCEB7, 0xB058, 0xCEB8,
+	0xB059, 0xCEB9, 0xB05A, 0xCEBA, 0xB061, 0xCEBB, 0xB062, 0xCEBC,
+	0xB063, 0xCEBD, 0xB064, 0xCEBE, 0xB065, 0xCEBF, 0xB066, 0xCEC0,
+	0xB067, 0xCEC2, 0xB068, 0xCEC3, 0xB069, 0xCEC4, 0xB06A, 0xCEC5,
+	0xB06B, 0xCEC6, 0xB06C, 0xCEC7, 0xB06D, 0xCEC8, 0xB06E, 0xCEC9,
+	0xB06F, 0xCECA, 0xB070, 0xCECB, 0xB071, 0xCECC, 0xB072, 0xCECD,
+	0xB073, 0xCECE, 0xB074, 0xCECF, 0xB075, 0xCED0, 0xB076, 0xCED1,
+	0xB077, 0xCED2, 0xB078, 0xCED3, 0xB079, 0xCED4, 0xB07A, 0xCED5,
+	0xB081, 0xCED6, 0xB082, 0xCED7, 0xB083, 0xCED8, 0xB084, 0xCED9,
+	0xB085, 0xCEDA, 0xB086, 0xCEDB, 0xB087, 0xCEDC, 0xB088, 0xCEDD,
+	0xB089, 0xCEDE, 0xB08A, 0xCEDF, 0xB08B, 0xCEE0, 0xB08C, 0xCEE1,
+	0xB08D, 0xCEE2, 0xB08E, 0xCEE3, 0xB08F, 0xCEE6, 0xB090, 0xCEE7,
+	0xB091, 0xCEE9, 0xB092, 0xCEEA, 0xB093, 0xCEED, 0xB094, 0xCEEE,
+	0xB095, 0xCEEF, 0xB096, 0xCEF0, 0xB097, 0xCEF1, 0xB098, 0xCEF2,
+	0xB099, 0xCEF3, 0xB09A, 0xCEF6, 0xB09B, 0xCEFA, 0xB09C, 0xCEFB,
+	0xB09D, 0xCEFC, 0xB09E, 0xCEFD, 0xB09F, 0xCEFE, 0xB0A0, 0xCEFF,
+	0xB0A1, 0xAC00, 0xB0A2, 0xAC01, 0xB0A3, 0xAC04, 0xB0A4, 0xAC07,
+	0xB0A5, 0xAC08, 0xB0A6, 0xAC09, 0xB0A7, 0xAC0A, 0xB0A8, 0xAC10,
+	0xB0A9, 0xAC11, 0xB0AA, 0xAC12, 0xB0AB, 0xAC13, 0xB0AC, 0xAC14,
+	0xB0AD, 0xAC15, 0xB0AE, 0xAC16, 0xB0AF, 0xAC17, 0xB0B0, 0xAC19,
+	0xB0B1, 0xAC1A, 0xB0B2, 0xAC1B, 0xB0B3, 0xAC1C, 0xB0B4, 0xAC1D,
+	0xB0B5, 0xAC20, 0xB0B6, 0xAC24, 0xB0B7, 0xAC2C, 0xB0B8, 0xAC2D,
+	0xB0B9, 0xAC2F, 0xB0BA, 0xAC30, 0xB0BB, 0xAC31, 0xB0BC, 0xAC38,
+	0xB0BD, 0xAC39, 0xB0BE, 0xAC3C, 0xB0BF, 0xAC40, 0xB0C0, 0xAC4B,
+	0xB0C1, 0xAC4D, 0xB0C2, 0xAC54, 0xB0C3, 0xAC58, 0xB0C4, 0xAC5C,
+	0xB0C5, 0xAC70, 0xB0C6, 0xAC71, 0xB0C7, 0xAC74, 0xB0C8, 0xAC77,
+	0xB0C9, 0xAC78, 0xB0CA, 0xAC7A, 0xB0CB, 0xAC80, 0xB0CC, 0xAC81,
+	0xB0CD, 0xAC83, 0xB0CE, 0xAC84, 0xB0CF, 0xAC85, 0xB0D0, 0xAC86,
+	0xB0D1, 0xAC89, 0xB0D2, 0xAC8A, 0xB0D3, 0xAC8B, 0xB0D4, 0xAC8C,
+	0xB0D5, 0xAC90, 0xB0D6, 0xAC94, 0xB0D7, 0xAC9C, 0xB0D8, 0xAC9D,
+	0xB0D9, 0xAC9F, 0xB0DA, 0xACA0, 0xB0DB, 0xACA1, 0xB0DC, 0xACA8,
+	0xB0DD, 0xACA9, 0xB0DE, 0xACAA, 0xB0DF, 0xACAC, 0xB0E0, 0xACAF,
+	0xB0E1, 0xACB0, 0xB0E2, 0xACB8, 0xB0E3, 0xACB9, 0xB0E4, 0xACBB,
+	0xB0E5, 0xACBC, 0xB0E6, 0xACBD, 0xB0E7, 0xACC1, 0xB0E8, 0xACC4,
+	0xB0E9, 0xACC8, 0xB0EA, 0xACCC, 0xB0EB, 0xACD5, 0xB0EC, 0xACD7,
+	0xB0ED, 0xACE0, 0xB0EE, 0xACE1, 0xB0EF, 0xACE4, 0xB0F0, 0xACE7,
+	0xB0F1, 0xACE8, 0xB0F2, 0xACEA, 0xB0F3, 0xACEC, 0xB0F4, 0xACEF,
+	0xB0F5, 0xACF0, 0xB0F6, 0xACF1, 0xB0F7, 0xACF3, 0xB0F8, 0xACF5,
+	0xB0F9, 0xACF6, 0xB0FA, 0xACFC, 0xB0FB, 0xACFD, 0xB0FC, 0xAD00,
+	0xB0FD, 0xAD04, 0xB0FE, 0xAD06, 0xB141, 0xCF02, 0xB142, 0xCF03,
+	0xB143, 0xCF05, 0xB144, 0xCF06, 0xB145, 0xCF07, 0xB146, 0xCF09,
+	0xB147, 0xCF0A, 0xB148, 0xCF0B, 0xB149, 0xCF0C, 0xB14A, 0xCF0D,
+	0xB14B, 0xCF0E, 0xB14C, 0xCF0F, 0xB14D, 0xCF12, 0xB14E, 0xCF14,
+	0xB14F, 0xCF16, 0xB150, 0xCF17, 0xB151, 0xCF18, 0xB152, 0xCF19,
+	0xB153, 0xCF1A, 0xB154, 0xCF1B, 0xB155, 0xCF1D, 0xB156, 0xCF1E,
+	0xB157, 0xCF1F, 0xB158, 0xCF21, 0xB159, 0xCF22, 0xB15A, 0xCF23,
+	0xB161, 0xCF25, 0xB162, 0xCF26, 0xB163, 0xCF27, 0xB164, 0xCF28,
+	0xB165, 0xCF29, 0xB166, 0xCF2A, 0xB167, 0xCF2B, 0xB168, 0xCF2E,
+	0xB169, 0xCF32, 0xB16A, 0xCF33, 0xB16B, 0xCF34, 0xB16C, 0xCF35,
+	0xB16D, 0xCF36, 0xB16E, 0xCF37, 0xB16F, 0xCF39, 0xB170, 0xCF3A,
+	0xB171, 0xCF3B, 0xB172, 0xCF3C, 0xB173, 0xCF3D, 0xB174, 0xCF3E,
+	0xB175, 0xCF3F, 0xB176, 0xCF40, 0xB177, 0xCF41, 0xB178, 0xCF42,
+	0xB179, 0xCF43, 0xB17A, 0xCF44, 0xB181, 0xCF45, 0xB182, 0xCF46,
+	0xB183, 0xCF47, 0xB184, 0xCF48, 0xB185, 0xCF49, 0xB186, 0xCF4A,
+	0xB187, 0xCF4B, 0xB188, 0xCF4C, 0xB189, 0xCF4D, 0xB18A, 0xCF4E,
+	0xB18B, 0xCF4F, 0xB18C, 0xCF50, 0xB18D, 0xCF51, 0xB18E, 0xCF52,
+	0xB18F, 0xCF53, 0xB190, 0xCF56, 0xB191, 0xCF57, 0xB192, 0xCF59,
+	0xB193, 0xCF5A, 0xB194, 0xCF5B, 0xB195, 0xCF5D, 0xB196, 0xCF5E,
+	0xB197, 0xCF5F, 0xB198, 0xCF60, 0xB199, 0xCF61, 0xB19A, 0xCF62,
+	0xB19B, 0xCF63, 0xB19C, 0xCF66, 0xB19D, 0xCF68, 0xB19E, 0xCF6A,
+	0xB19F, 0xCF6B, 0xB1A0, 0xCF6C, 0xB1A1, 0xAD0C, 0xB1A2, 0xAD0D,
+	0xB1A3, 0xAD0F, 0xB1A4, 0xAD11, 0xB1A5, 0xAD18, 0xB1A6, 0xAD1C,
+	0xB1A7, 0xAD20, 0xB1A8, 0xAD29, 0xB1A9, 0xAD2C, 0xB1AA, 0xAD2D,
+	0xB1AB, 0xAD34, 0xB1AC, 0xAD35, 0xB1AD, 0xAD38, 0xB1AE, 0xAD3C,
+	0xB1AF, 0xAD44, 0xB1B0, 0xAD45, 0xB1B1, 0xAD47, 0xB1B2, 0xAD49,
+	0xB1B3, 0xAD50, 0xB1B4, 0xAD54, 0xB1B5, 0xAD58, 0xB1B6, 0xAD61,
+	0xB1B7, 0xAD63, 0xB1B8, 0xAD6C, 0xB1B9, 0xAD6D, 0xB1BA, 0xAD70,
+	0xB1BB, 0xAD73, 0xB1BC, 0xAD74, 0xB1BD, 0xAD75, 0xB1BE, 0xAD76,
+	0xB1BF, 0xAD7B, 0xB1C0, 0xAD7C, 0xB1C1, 0xAD7D, 0xB1C2, 0xAD7F,
+	0xB1C3, 0xAD81, 0xB1C4, 0xAD82, 0xB1C5, 0xAD88, 0xB1C6, 0xAD89,
+	0xB1C7, 0xAD8C, 0xB1C8, 0xAD90, 0xB1C9, 0xAD9C, 0xB1CA, 0xAD9D,
+	0xB1CB, 0xADA4, 0xB1CC, 0xADB7, 0xB1CD, 0xADC0, 0xB1CE, 0xADC1,
+	0xB1CF, 0xADC4, 0xB1D0, 0xADC8, 0xB1D1, 0xADD0, 0xB1D2, 0xADD1,
+	0xB1D3, 0xADD3, 0xB1D4, 0xADDC, 0xB1D5, 0xADE0, 0xB1D6, 0xADE4,
+	0xB1D7, 0xADF8, 0xB1D8, 0xADF9, 0xB1D9, 0xADFC, 0xB1DA, 0xADFF,
+	0xB1DB, 0xAE00, 0xB1DC, 0xAE01, 0xB1DD, 0xAE08, 0xB1DE, 0xAE09,
+	0xB1DF, 0xAE0B, 0xB1E0, 0xAE0D, 0xB1E1, 0xAE14, 0xB1E2, 0xAE30,
+	0xB1E3, 0xAE31, 0xB1E4, 0xAE34, 0xB1E5, 0xAE37, 0xB1E6, 0xAE38,
+	0xB1E7, 0xAE3A, 0xB1E8, 0xAE40, 0xB1E9, 0xAE41, 0xB1EA, 0xAE43,
+	0xB1EB, 0xAE45, 0xB1EC, 0xAE46, 0xB1ED, 0xAE4A, 0xB1EE, 0xAE4C,
+	0xB1EF, 0xAE4D, 0xB1F0, 0xAE4E, 0xB1F1, 0xAE50, 0xB1F2, 0xAE54,
+	0xB1F3, 0xAE56, 0xB1F4, 0xAE5C, 0xB1F5, 0xAE5D, 0xB1F6, 0xAE5F,
+	0xB1F7, 0xAE60, 0xB1F8, 0xAE61, 0xB1F9, 0xAE65, 0xB1FA, 0xAE68,
+	0xB1FB, 0xAE69, 0xB1FC, 0xAE6C, 0xB1FD, 0xAE70, 0xB1FE, 0xAE78,
+	0xB241, 0xCF6D, 0xB242, 0xCF6E, 0xB243, 0xCF6F, 0xB244, 0xCF72,
+	0xB245, 0xCF73, 0xB246, 0xCF75, 0xB247, 0xCF76, 0xB248, 0xCF77,
+	0xB249, 0xCF79, 0xB24A, 0xCF7A, 0xB24B, 0xCF7B, 0xB24C, 0xCF7C,
+	0xB24D, 0xCF7D, 0xB24E, 0xCF7E, 0xB24F, 0xCF7F, 0xB250, 0xCF81,
+	0xB251, 0xCF82, 0xB252, 0xCF83, 0xB253, 0xCF84, 0xB254, 0xCF86,
+	0xB255, 0xCF87, 0xB256, 0xCF88, 0xB257, 0xCF89, 0xB258, 0xCF8A,
+	0xB259, 0xCF8B, 0xB25A, 0xCF8D, 0xB261, 0xCF8E, 0xB262, 0xCF8F,
+	0xB263, 0xCF90, 0xB264, 0xCF91, 0xB265, 0xCF92, 0xB266, 0xCF93,
+	0xB267, 0xCF94, 0xB268, 0xCF95, 0xB269, 0xCF96, 0xB26A, 0xCF97,
+	0xB26B, 0xCF98, 0xB26C, 0xCF99, 0xB26D, 0xCF9A, 0xB26E, 0xCF9B,
+	0xB26F, 0xCF9C, 0xB270, 0xCF9D, 0xB271, 0xCF9E, 0xB272, 0xCF9F,
+	0xB273, 0xCFA0, 0xB274, 0xCFA2, 0xB275, 0xCFA3, 0xB276, 0xCFA4,
+	0xB277, 0xCFA5, 0xB278, 0xCFA6, 0xB279, 0xCFA7, 0xB27A, 0xCFA9,
+	0xB281, 0xCFAA, 0xB282, 0xCFAB, 0xB283, 0xCFAC, 0xB284, 0xCFAD,
+	0xB285, 0xCFAE, 0xB286, 0xCFAF, 0xB287, 0xCFB1, 0xB288, 0xCFB2,
+	0xB289, 0xCFB3, 0xB28A, 0xCFB4, 0xB28B, 0xCFB5, 0xB28C, 0xCFB6,
+	0xB28D, 0xCFB7, 0xB28E, 0xCFB8, 0xB28F, 0xCFB9, 0xB290, 0xCFBA,
+	0xB291, 0xCFBB, 0xB292, 0xCFBC, 0xB293, 0xCFBD, 0xB294, 0xCFBE,
+	0xB295, 0xCFBF, 0xB296, 0xCFC0, 0xB297, 0xCFC1, 0xB298, 0xCFC2,
+	0xB299, 0xCFC3, 0xB29A, 0xCFC5, 0xB29B, 0xCFC6, 0xB29C, 0xCFC7,
+	0xB29D, 0xCFC8, 0xB29E, 0xCFC9, 0xB29F, 0xCFCA, 0xB2A0, 0xCFCB,
+	0xB2A1, 0xAE79, 0xB2A2, 0xAE7B, 0xB2A3, 0xAE7C, 0xB2A4, 0xAE7D,
+	0xB2A5, 0xAE84, 0xB2A6, 0xAE85, 0xB2A7, 0xAE8C, 0xB2A8, 0xAEBC,
+	0xB2A9, 0xAEBD, 0xB2AA, 0xAEBE, 0xB2AB, 0xAEC0, 0xB2AC, 0xAEC4,
+	0xB2AD, 0xAECC, 0xB2AE, 0xAECD, 0xB2AF, 0xAECF, 0xB2B0, 0xAED0,
+	0xB2B1, 0xAED1, 0xB2B2, 0xAED8, 0xB2B3, 0xAED9, 0xB2B4, 0xAEDC,
+	0xB2B5, 0xAEE8, 0xB2B6, 0xAEEB, 0xB2B7, 0xAEED, 0xB2B8, 0xAEF4,
+	0xB2B9, 0xAEF8, 0xB2BA, 0xAEFC, 0xB2BB, 0xAF07, 0xB2BC, 0xAF08,
+	0xB2BD, 0xAF0D, 0xB2BE, 0xAF10, 0xB2BF, 0xAF2C, 0xB2C0, 0xAF2D,
+	0xB2C1, 0xAF30, 0xB2C2, 0xAF32, 0xB2C3, 0xAF34, 0xB2C4, 0xAF3C,
+	0xB2C5, 0xAF3D, 0xB2C6, 0xAF3F, 0xB2C7, 0xAF41, 0xB2C8, 0xAF42,
+	0xB2C9, 0xAF43, 0xB2CA, 0xAF48, 0xB2CB, 0xAF49, 0xB2CC, 0xAF50,
+	0xB2CD, 0xAF5C, 0xB2CE, 0xAF5D, 0xB2CF, 0xAF64, 0xB2D0, 0xAF65,
+	0xB2D1, 0xAF79, 0xB2D2, 0xAF80, 0xB2D3, 0xAF84, 0xB2D4, 0xAF88,
+	0xB2D5, 0xAF90, 0xB2D6, 0xAF91, 0xB2D7, 0xAF95, 0xB2D8, 0xAF9C,
+	0xB2D9, 0xAFB8, 0xB2DA, 0xAFB9, 0xB2DB, 0xAFBC, 0xB2DC, 0xAFC0,
+	0xB2DD, 0xAFC7, 0xB2DE, 0xAFC8, 0xB2DF, 0xAFC9, 0xB2E0, 0xAFCB,
+	0xB2E1, 0xAFCD, 0xB2E2, 0xAFCE, 0xB2E3, 0xAFD4, 0xB2E4, 0xAFDC,
+	0xB2E5, 0xAFE8, 0xB2E6, 0xAFE9, 0xB2E7, 0xAFF0, 0xB2E8, 0xAFF1,
+	0xB2E9, 0xAFF4, 0xB2EA, 0xAFF8, 0xB2EB, 0xB000, 0xB2EC, 0xB001,
+	0xB2ED, 0xB004, 0xB2EE, 0xB00C, 0xB2EF, 0xB010, 0xB2F0, 0xB014,
+	0xB2F1, 0xB01C, 0xB2F2, 0xB01D, 0xB2F3, 0xB028, 0xB2F4, 0xB044,
+	0xB2F5, 0xB045, 0xB2F6, 0xB048, 0xB2F7, 0xB04A, 0xB2F8, 0xB04C,
+	0xB2F9, 0xB04E, 0xB2FA, 0xB053, 0xB2FB, 0xB054, 0xB2FC, 0xB055,
+	0xB2FD, 0xB057, 0xB2FE, 0xB059, 0xB341, 0xCFCC, 0xB342, 0xCFCD,
+	0xB343, 0xCFCE, 0xB344, 0xCFCF, 0xB345, 0xCFD0, 0xB346, 0xCFD1,
+	0xB347, 0xCFD2, 0xB348, 0xCFD3, 0xB349, 0xCFD4, 0xB34A, 0xCFD5,
+	0xB34B, 0xCFD6, 0xB34C, 0xCFD7, 0xB34D, 0xCFD8, 0xB34E, 0xCFD9,
+	0xB34F, 0xCFDA, 0xB350, 0xCFDB, 0xB351, 0xCFDC, 0xB352, 0xCFDD,
+	0xB353, 0xCFDE, 0xB354, 0xCFDF, 0xB355, 0xCFE2, 0xB356, 0xCFE3,
+	0xB357, 0xCFE5, 0xB358, 0xCFE6, 0xB359, 0xCFE7, 0xB35A, 0xCFE9,
+	0xB361, 0xCFEA, 0xB362, 0xCFEB, 0xB363, 0xCFEC, 0xB364, 0xCFED,
+	0xB365, 0xCFEE, 0xB366, 0xCFEF, 0xB367, 0xCFF2, 0xB368, 0xCFF4,
+	0xB369, 0xCFF6, 0xB36A, 0xCFF7, 0xB36B, 0xCFF8, 0xB36C, 0xCFF9,
+	0xB36D, 0xCFFA, 0xB36E, 0xCFFB, 0xB36F, 0xCFFD, 0xB370, 0xCFFE,
+	0xB371, 0xCFFF, 0xB372, 0xD001, 0xB373, 0xD002, 0xB374, 0xD003,
+	0xB375, 0xD005, 0xB376, 0xD006, 0xB377, 0xD007, 0xB378, 0xD008,
+	0xB379, 0xD009, 0xB37A, 0xD00A, 0xB381, 0xD00B, 0xB382, 0xD00C,
+	0xB383, 0xD00D, 0xB384, 0xD00E, 0xB385, 0xD00F, 0xB386, 0xD010,
+	0xB387, 0xD012, 0xB388, 0xD013, 0xB389, 0xD014, 0xB38A, 0xD015,
+	0xB38B, 0xD016, 0xB38C, 0xD017, 0xB38D, 0xD019, 0xB38E, 0xD01A,
+	0xB38F, 0xD01B, 0xB390, 0xD01C, 0xB391, 0xD01D, 0xB392, 0xD01E,
+	0xB393, 0xD01F, 0xB394, 0xD020, 0xB395, 0xD021, 0xB396, 0xD022,
+	0xB397, 0xD023, 0xB398, 0xD024, 0xB399, 0xD025, 0xB39A, 0xD026,
+	0xB39B, 0xD027, 0xB39C, 0xD028, 0xB39D, 0xD029, 0xB39E, 0xD02A,
+	0xB39F, 0xD02B, 0xB3A0, 0xD02C, 0xB3A1, 0xB05D, 0xB3A2, 0xB07C,
+	0xB3A3, 0xB07D, 0xB3A4, 0xB080, 0xB3A5, 0xB084, 0xB3A6, 0xB08C,
+	0xB3A7, 0xB08D, 0xB3A8, 0xB08F, 0xB3A9, 0xB091, 0xB3AA, 0xB098,
+	0xB3AB, 0xB099, 0xB3AC, 0xB09A, 0xB3AD, 0xB09C, 0xB3AE, 0xB09F,
+	0xB3AF, 0xB0A0, 0xB3B0, 0xB0A1, 0xB3B1, 0xB0A2, 0xB3B2, 0xB0A8,
+	0xB3B3, 0xB0A9, 0xB3B4, 0xB0AB, 0xB3B5, 0xB0AC, 0xB3B6, 0xB0AD,
+	0xB3B7, 0xB0AE, 0xB3B8, 0xB0AF, 0xB3B9, 0xB0B1, 0xB3BA, 0xB0B3,
+	0xB3BB, 0xB0B4, 0xB3BC, 0xB0B5, 0xB3BD, 0xB0B8, 0xB3BE, 0xB0BC,
+	0xB3BF, 0xB0C4, 0xB3C0, 0xB0C5, 0xB3C1, 0xB0C7, 0xB3C2, 0xB0C8,
+	0xB3C3, 0xB0C9, 0xB3C4, 0xB0D0, 0xB3C5, 0xB0D1, 0xB3C6, 0xB0D4,
+	0xB3C7, 0xB0D8, 0xB3C8, 0xB0E0, 0xB3C9, 0xB0E5, 0xB3CA, 0xB108,
+	0xB3CB, 0xB109, 0xB3CC, 0xB10B, 0xB3CD, 0xB10C, 0xB3CE, 0xB110,
+	0xB3CF, 0xB112, 0xB3D0, 0xB113, 0xB3D1, 0xB118, 0xB3D2, 0xB119,
+	0xB3D3, 0xB11B, 0xB3D4, 0xB11C, 0xB3D5, 0xB11D, 0xB3D6, 0xB123,
+	0xB3D7, 0xB124, 0xB3D8, 0xB125, 0xB3D9, 0xB128, 0xB3DA, 0xB12C,
+	0xB3DB, 0xB134, 0xB3DC, 0xB135, 0xB3DD, 0xB137, 0xB3DE, 0xB138,
+	0xB3DF, 0xB139, 0xB3E0, 0xB140, 0xB3E1, 0xB141, 0xB3E2, 0xB144,
+	0xB3E3, 0xB148, 0xB3E4, 0xB150, 0xB3E5, 0xB151, 0xB3E6, 0xB154,
+	0xB3E7, 0xB155, 0xB3E8, 0xB158, 0xB3E9, 0xB15C, 0xB3EA, 0xB160,
+	0xB3EB, 0xB178, 0xB3EC, 0xB179, 0xB3ED, 0xB17C, 0xB3EE, 0xB180,
+	0xB3EF, 0xB182, 0xB3F0, 0xB188, 0xB3F1, 0xB189, 0xB3F2, 0xB18B,
+	0xB3F3, 0xB18D, 0xB3F4, 0xB192, 0xB3F5, 0xB193, 0xB3F6, 0xB194,
+	0xB3F7, 0xB198, 0xB3F8, 0xB19C, 0xB3F9, 0xB1A8, 0xB3FA, 0xB1CC,
+	0xB3FB, 0xB1D0, 0xB3FC, 0xB1D4, 0xB3FD, 0xB1DC, 0xB3FE, 0xB1DD,
+	0xB441, 0xD02E, 0xB442, 0xD02F, 0xB443, 0xD030, 0xB444, 0xD031,
+	0xB445, 0xD032, 0xB446, 0xD033, 0xB447, 0xD036, 0xB448, 0xD037,
+	0xB449, 0xD039, 0xB44A, 0xD03A, 0xB44B, 0xD03B, 0xB44C, 0xD03D,
+	0xB44D, 0xD03E, 0xB44E, 0xD03F, 0xB44F, 0xD040, 0xB450, 0xD041,
+	0xB451, 0xD042, 0xB452, 0xD043, 0xB453, 0xD046, 0xB454, 0xD048,
+	0xB455, 0xD04A, 0xB456, 0xD04B, 0xB457, 0xD04C, 0xB458, 0xD04D,
+	0xB459, 0xD04E, 0xB45A, 0xD04F, 0xB461, 0xD051, 0xB462, 0xD052,
+	0xB463, 0xD053, 0xB464, 0xD055, 0xB465, 0xD056, 0xB466, 0xD057,
+	0xB467, 0xD059, 0xB468, 0xD05A, 0xB469, 0xD05B, 0xB46A, 0xD05C,
+	0xB46B, 0xD05D, 0xB46C, 0xD05E, 0xB46D, 0xD05F, 0xB46E, 0xD061,
+	0xB46F, 0xD062, 0xB470, 0xD063, 0xB471, 0xD064, 0xB472, 0xD065,
+	0xB473, 0xD066, 0xB474, 0xD067, 0xB475, 0xD068, 0xB476, 0xD069,
+	0xB477, 0xD06A, 0xB478, 0xD06B, 0xB479, 0xD06E, 0xB47A, 0xD06F,
+	0xB481, 0xD071, 0xB482, 0xD072, 0xB483, 0xD073, 0xB484, 0xD075,
+	0xB485, 0xD076, 0xB486, 0xD077, 0xB487, 0xD078, 0xB488, 0xD079,
+	0xB489, 0xD07A, 0xB48A, 0xD07B, 0xB48B, 0xD07E, 0xB48C, 0xD07F,
+	0xB48D, 0xD080, 0xB48E, 0xD082, 0xB48F, 0xD083, 0xB490, 0xD084,
+	0xB491, 0xD085, 0xB492, 0xD086, 0xB493, 0xD087, 0xB494, 0xD088,
+	0xB495, 0xD089, 0xB496, 0xD08A, 0xB497, 0xD08B, 0xB498, 0xD08C,
+	0xB499, 0xD08D, 0xB49A, 0xD08E, 0xB49B, 0xD08F, 0xB49C, 0xD090,
+	0xB49D, 0xD091, 0xB49E, 0xD092, 0xB49F, 0xD093, 0xB4A0, 0xD094,
+	0xB4A1, 0xB1DF, 0xB4A2, 0xB1E8, 0xB4A3, 0xB1E9, 0xB4A4, 0xB1EC,
+	0xB4A5, 0xB1F0, 0xB4A6, 0xB1F9, 0xB4A7, 0xB1FB, 0xB4A8, 0xB1FD,
+	0xB4A9, 0xB204, 0xB4AA, 0xB205, 0xB4AB, 0xB208, 0xB4AC, 0xB20B,
+	0xB4AD, 0xB20C, 0xB4AE, 0xB214, 0xB4AF, 0xB215, 0xB4B0, 0xB217,
+	0xB4B1, 0xB219, 0xB4B2, 0xB220, 0xB4B3, 0xB234, 0xB4B4, 0xB23C,
+	0xB4B5, 0xB258, 0xB4B6, 0xB25C, 0xB4B7, 0xB260, 0xB4B8, 0xB268,
+	0xB4B9, 0xB269, 0xB4BA, 0xB274, 0xB4BB, 0xB275, 0xB4BC, 0xB27C,
+	0xB4BD, 0xB284, 0xB4BE, 0xB285, 0xB4BF, 0xB289, 0xB4C0, 0xB290,
+	0xB4C1, 0xB291, 0xB4C2, 0xB294, 0xB4C3, 0xB298, 0xB4C4, 0xB299,
+	0xB4C5, 0xB29A, 0xB4C6, 0xB2A0, 0xB4C7, 0xB2A1, 0xB4C8, 0xB2A3,
+	0xB4C9, 0xB2A5, 0xB4CA, 0xB2A6, 0xB4CB, 0xB2AA, 0xB4CC, 0xB2AC,
+	0xB4CD, 0xB2B0, 0xB4CE, 0xB2B4, 0xB4CF, 0xB2C8, 0xB4D0, 0xB2C9,
+	0xB4D1, 0xB2CC, 0xB4D2, 0xB2D0, 0xB4D3, 0xB2D2, 0xB4D4, 0xB2D8,
+	0xB4D5, 0xB2D9, 0xB4D6, 0xB2DB, 0xB4D7, 0xB2DD, 0xB4D8, 0xB2E2,
+	0xB4D9, 0xB2E4, 0xB4DA, 0xB2E5, 0xB4DB, 0xB2E6, 0xB4DC, 0xB2E8,
+	0xB4DD, 0xB2EB, 0xB4DE, 0xB2EC, 0xB4DF, 0xB2ED, 0xB4E0, 0xB2EE,
+	0xB4E1, 0xB2EF, 0xB4E2, 0xB2F3, 0xB4E3, 0xB2F4, 0xB4E4, 0xB2F5,
+	0xB4E5, 0xB2F7, 0xB4E6, 0xB2F8, 0xB4E7, 0xB2F9, 0xB4E8, 0xB2FA,
+	0xB4E9, 0xB2FB, 0xB4EA, 0xB2FF, 0xB4EB, 0xB300, 0xB4EC, 0xB301,
+	0xB4ED, 0xB304, 0xB4EE, 0xB308, 0xB4EF, 0xB310, 0xB4F0, 0xB311,
+	0xB4F1, 0xB313, 0xB4F2, 0xB314, 0xB4F3, 0xB315, 0xB4F4, 0xB31C,
+	0xB4F5, 0xB354, 0xB4F6, 0xB355, 0xB4F7, 0xB356, 0xB4F8, 0xB358,
+	0xB4F9, 0xB35B, 0xB4FA, 0xB35C, 0xB4FB, 0xB35E, 0xB4FC, 0xB35F,
+	0xB4FD, 0xB364, 0xB4FE, 0xB365, 0xB541, 0xD095, 0xB542, 0xD096,
+	0xB543, 0xD097, 0xB544, 0xD098, 0xB545, 0xD099, 0xB546, 0xD09A,
+	0xB547, 0xD09B, 0xB548, 0xD09C, 0xB549, 0xD09D, 0xB54A, 0xD09E,
+	0xB54B, 0xD09F, 0xB54C, 0xD0A0, 0xB54D, 0xD0A1, 0xB54E, 0xD0A2,
+	0xB54F, 0xD0A3, 0xB550, 0xD0A6, 0xB551, 0xD0A7, 0xB552, 0xD0A9,
+	0xB553, 0xD0AA, 0xB554, 0xD0AB, 0xB555, 0xD0AD, 0xB556, 0xD0AE,
+	0xB557, 0xD0AF, 0xB558, 0xD0B0, 0xB559, 0xD0B1, 0xB55A, 0xD0B2,
+	0xB561, 0xD0B3, 0xB562, 0xD0B6, 0xB563, 0xD0B8, 0xB564, 0xD0BA,
+	0xB565, 0xD0BB, 0xB566, 0xD0BC, 0xB567, 0xD0BD, 0xB568, 0xD0BE,
+	0xB569, 0xD0BF, 0xB56A, 0xD0C2, 0xB56B, 0xD0C3, 0xB56C, 0xD0C5,
+	0xB56D, 0xD0C6, 0xB56E, 0xD0C7, 0xB56F, 0xD0CA, 0xB570, 0xD0CB,
+	0xB571, 0xD0CC, 0xB572, 0xD0CD, 0xB573, 0xD0CE, 0xB574, 0xD0CF,
+	0xB575, 0xD0D2, 0xB576, 0xD0D6, 0xB577, 0xD0D7, 0xB578, 0xD0D8,
+	0xB579, 0xD0D9, 0xB57A, 0xD0DA, 0xB581, 0xD0DB, 0xB582, 0xD0DE,
+	0xB583, 0xD0DF, 0xB584, 0xD0E1, 0xB585, 0xD0E2, 0xB586, 0xD0E3,
+	0xB587, 0xD0E5, 0xB588, 0xD0E6, 0xB589, 0xD0E7, 0xB58A, 0xD0E8,
+	0xB58B, 0xD0E9, 0xB58C, 0xD0EA, 0xB58D, 0xD0EB, 0xB58E, 0xD0EE,
+	0xB58F, 0xD0F2, 0xB590, 0xD0F3, 0xB591, 0xD0F4, 0xB592, 0xD0F5,
+	0xB593, 0xD0F6, 0xB594, 0xD0F7, 0xB595, 0xD0F9, 0xB596, 0xD0FA,
+	0xB597, 0xD0FB, 0xB598, 0xD0FC, 0xB599, 0xD0FD, 0xB59A, 0xD0FE,
+	0xB59B, 0xD0FF, 0xB59C, 0xD100, 0xB59D, 0xD101, 0xB59E, 0xD102,
+	0xB59F, 0xD103, 0xB5A0, 0xD104, 0xB5A1, 0xB367, 0xB5A2, 0xB369,
+	0xB5A3, 0xB36B, 0xB5A4, 0xB36E, 0xB5A5, 0xB370, 0xB5A6, 0xB371,
+	0xB5A7, 0xB374, 0xB5A8, 0xB378, 0xB5A9, 0xB380, 0xB5AA, 0xB381,
+	0xB5AB, 0xB383, 0xB5AC, 0xB384, 0xB5AD, 0xB385, 0xB5AE, 0xB38C,
+	0xB5AF, 0xB390, 0xB5B0, 0xB394, 0xB5B1, 0xB3A0, 0xB5B2, 0xB3A1,
+	0xB5B3, 0xB3A8, 0xB5B4, 0xB3AC, 0xB5B5, 0xB3C4, 0xB5B6, 0xB3C5,
+	0xB5B7, 0xB3C8, 0xB5B8, 0xB3CB, 0xB5B9, 0xB3CC, 0xB5BA, 0xB3CE,
+	0xB5BB, 0xB3D0, 0xB5BC, 0xB3D4, 0xB5BD, 0xB3D5, 0xB5BE, 0xB3D7,
+	0xB5BF, 0xB3D9, 0xB5C0, 0xB3DB, 0xB5C1, 0xB3DD, 0xB5C2, 0xB3E0,
+	0xB5C3, 0xB3E4, 0xB5C4, 0xB3E8, 0xB5C5, 0xB3FC, 0xB5C6, 0xB410,
+	0xB5C7, 0xB418, 0xB5C8, 0xB41C, 0xB5C9, 0xB420, 0xB5CA, 0xB428,
+	0xB5CB, 0xB429, 0xB5CC, 0xB42B, 0xB5CD, 0xB434, 0xB5CE, 0xB450,
+	0xB5CF, 0xB451, 0xB5D0, 0xB454, 0xB5D1, 0xB458, 0xB5D2, 0xB460,
+	0xB5D3, 0xB461, 0xB5D4, 0xB463, 0xB5D5, 0xB465, 0xB5D6, 0xB46C,
+	0xB5D7, 0xB480, 0xB5D8, 0xB488, 0xB5D9, 0xB49D, 0xB5DA, 0xB4A4,
+	0xB5DB, 0xB4A8, 0xB5DC, 0xB4AC, 0xB5DD, 0xB4B5, 0xB5DE, 0xB4B7,
+	0xB5DF, 0xB4B9, 0xB5E0, 0xB4C0, 0xB5E1, 0xB4C4, 0xB5E2, 0xB4C8,
+	0xB5E3, 0xB4D0, 0xB5E4, 0xB4D5, 0xB5E5, 0xB4DC, 0xB5E6, 0xB4DD,
+	0xB5E7, 0xB4E0, 0xB5E8, 0xB4E3, 0xB5E9, 0xB4E4, 0xB5EA, 0xB4E6,
+	0xB5EB, 0xB4EC, 0xB5EC, 0xB4ED, 0xB5ED, 0xB4EF, 0xB5EE, 0xB4F1,
+	0xB5EF, 0xB4F8, 0xB5F0, 0xB514, 0xB5F1, 0xB515, 0xB5F2, 0xB518,
+	0xB5F3, 0xB51B, 0xB5F4, 0xB51C, 0xB5F5, 0xB524, 0xB5F6, 0xB525,
+	0xB5F7, 0xB527, 0xB5F8, 0xB528, 0xB5F9, 0xB529, 0xB5FA, 0xB52A,
+	0xB5FB, 0xB530, 0xB5FC, 0xB531, 0xB5FD, 0xB534, 0xB5FE, 0xB538,
+	0xB641, 0xD105, 0xB642, 0xD106, 0xB643, 0xD107, 0xB644, 0xD108,
+	0xB645, 0xD109, 0xB646, 0xD10A, 0xB647, 0xD10B, 0xB648, 0xD10C,
+	0xB649, 0xD10E, 0xB64A, 0xD10F, 0xB64B, 0xD110, 0xB64C, 0xD111,
+	0xB64D, 0xD112, 0xB64E, 0xD113, 0xB64F, 0xD114, 0xB650, 0xD115,
+	0xB651, 0xD116, 0xB652, 0xD117, 0xB653, 0xD118, 0xB654, 0xD119,
+	0xB655, 0xD11A, 0xB656, 0xD11B, 0xB657, 0xD11C, 0xB658, 0xD11D,
+	0xB659, 0xD11E, 0xB65A, 0xD11F, 0xB661, 0xD120, 0xB662, 0xD121,
+	0xB663, 0xD122, 0xB664, 0xD123, 0xB665, 0xD124, 0xB666, 0xD125,
+	0xB667, 0xD126, 0xB668, 0xD127, 0xB669, 0xD128, 0xB66A, 0xD129,
+	0xB66B, 0xD12A, 0xB66C, 0xD12B, 0xB66D, 0xD12C, 0xB66E, 0xD12D,
+	0xB66F, 0xD12E, 0xB670, 0xD12F, 0xB671, 0xD132, 0xB672, 0xD133,
+	0xB673, 0xD135, 0xB674, 0xD136, 0xB675, 0xD137, 0xB676, 0xD139,
+	0xB677, 0xD13B, 0xB678, 0xD13C, 0xB679, 0xD13D, 0xB67A, 0xD13E,
+	0xB681, 0xD13F, 0xB682, 0xD142, 0xB683, 0xD146, 0xB684, 0xD147,
+	0xB685, 0xD148, 0xB686, 0xD149, 0xB687, 0xD14A, 0xB688, 0xD14B,
+	0xB689, 0xD14E, 0xB68A, 0xD14F, 0xB68B, 0xD151, 0xB68C, 0xD152,
+	0xB68D, 0xD153, 0xB68E, 0xD155, 0xB68F, 0xD156, 0xB690, 0xD157,
+	0xB691, 0xD158, 0xB692, 0xD159, 0xB693, 0xD15A, 0xB694, 0xD15B,
+	0xB695, 0xD15E, 0xB696, 0xD160, 0xB697, 0xD162, 0xB698, 0xD163,
+	0xB699, 0xD164, 0xB69A, 0xD165, 0xB69B, 0xD166, 0xB69C, 0xD167,
+	0xB69D, 0xD169, 0xB69E, 0xD16A, 0xB69F, 0xD16B, 0xB6A0, 0xD16D,
+	0xB6A1, 0xB540, 0xB6A2, 0xB541, 0xB6A3, 0xB543, 0xB6A4, 0xB544,
+	0xB6A5, 0xB545, 0xB6A6, 0xB54B, 0xB6A7, 0xB54C, 0xB6A8, 0xB54D,
+	0xB6A9, 0xB550, 0xB6AA, 0xB554, 0xB6AB, 0xB55C, 0xB6AC, 0xB55D,
+	0xB6AD, 0xB55F, 0xB6AE, 0xB560, 0xB6AF, 0xB561, 0xB6B0, 0xB5A0,
+	0xB6B1, 0xB5A1, 0xB6B2, 0xB5A4, 0xB6B3, 0xB5A8, 0xB6B4, 0xB5AA,
+	0xB6B5, 0xB5AB, 0xB6B6, 0xB5B0, 0xB6B7, 0xB5B1, 0xB6B8, 0xB5B3,
+	0xB6B9, 0xB5B4, 0xB6BA, 0xB5B5, 0xB6BB, 0xB5BB, 0xB6BC, 0xB5BC,
+	0xB6BD, 0xB5BD, 0xB6BE, 0xB5C0, 0xB6BF, 0xB5C4, 0xB6C0, 0xB5CC,
+	0xB6C1, 0xB5CD, 0xB6C2, 0xB5CF, 0xB6C3, 0xB5D0, 0xB6C4, 0xB5D1,
+	0xB6C5, 0xB5D8, 0xB6C6, 0xB5EC, 0xB6C7, 0xB610, 0xB6C8, 0xB611,
+	0xB6C9, 0xB614, 0xB6CA, 0xB618, 0xB6CB, 0xB625, 0xB6CC, 0xB62C,
+	0xB6CD, 0xB634, 0xB6CE, 0xB648, 0xB6CF, 0xB664, 0xB6D0, 0xB668,
+	0xB6D1, 0xB69C, 0xB6D2, 0xB69D, 0xB6D3, 0xB6A0, 0xB6D4, 0xB6A4,
+	0xB6D5, 0xB6AB, 0xB6D6, 0xB6AC, 0xB6D7, 0xB6B1, 0xB6D8, 0xB6D4,
+	0xB6D9, 0xB6F0, 0xB6DA, 0xB6F4, 0xB6DB, 0xB6F8, 0xB6DC, 0xB700,
+	0xB6DD, 0xB701, 0xB6DE, 0xB705, 0xB6DF, 0xB728, 0xB6E0, 0xB729,
+	0xB6E1, 0xB72C, 0xB6E2, 0xB72F, 0xB6E3, 0xB730, 0xB6E4, 0xB738,
+	0xB6E5, 0xB739, 0xB6E6, 0xB73B, 0xB6E7, 0xB744, 0xB6E8, 0xB748,
+	0xB6E9, 0xB74C, 0xB6EA, 0xB754, 0xB6EB, 0xB755, 0xB6EC, 0xB760,
+	0xB6ED, 0xB764, 0xB6EE, 0xB768, 0xB6EF, 0xB770, 0xB6F0, 0xB771,
+	0xB6F1, 0xB773, 0xB6F2, 0xB775, 0xB6F3, 0xB77C, 0xB6F4, 0xB77D,
+	0xB6F5, 0xB780, 0xB6F6, 0xB784, 0xB6F7, 0xB78C, 0xB6F8, 0xB78D,
+	0xB6F9, 0xB78F, 0xB6FA, 0xB790, 0xB6FB, 0xB791, 0xB6FC, 0xB792,
+	0xB6FD, 0xB796, 0xB6FE, 0xB797, 0xB741, 0xD16E, 0xB742, 0xD16F,
+	0xB743, 0xD170, 0xB744, 0xD171, 0xB745, 0xD172, 0xB746, 0xD173,
+	0xB747, 0xD174, 0xB748, 0xD175, 0xB749, 0xD176, 0xB74A, 0xD177,
+	0xB74B, 0xD178, 0xB74C, 0xD179, 0xB74D, 0xD17A, 0xB74E, 0xD17B,
+	0xB74F, 0xD17D, 0xB750, 0xD17E, 0xB751, 0xD17F, 0xB752, 0xD180,
+	0xB753, 0xD181, 0xB754, 0xD182, 0xB755, 0xD183, 0xB756, 0xD185,
+	0xB757, 0xD186, 0xB758, 0xD187, 0xB759, 0xD189, 0xB75A, 0xD18A,
+	0xB761, 0xD18B, 0xB762, 0xD18C, 0xB763, 0xD18D, 0xB764, 0xD18E,
+	0xB765, 0xD18F, 0xB766, 0xD190, 0xB767, 0xD191, 0xB768, 0xD192,
+	0xB769, 0xD193, 0xB76A, 0xD194, 0xB76B, 0xD195, 0xB76C, 0xD196,
+	0xB76D, 0xD197, 0xB76E, 0xD198, 0xB76F, 0xD199, 0xB770, 0xD19A,
+	0xB771, 0xD19B, 0xB772, 0xD19C, 0xB773, 0xD19D, 0xB774, 0xD19E,
+	0xB775, 0xD19F, 0xB776, 0xD1A2, 0xB777, 0xD1A3, 0xB778, 0xD1A5,
+	0xB779, 0xD1A6, 0xB77A, 0xD1A7, 0xB781, 0xD1A9, 0xB782, 0xD1AA,
+	0xB783, 0xD1AB, 0xB784, 0xD1AC, 0xB785, 0xD1AD, 0xB786, 0xD1AE,
+	0xB787, 0xD1AF, 0xB788, 0xD1B2, 0xB789, 0xD1B4, 0xB78A, 0xD1B6,
+	0xB78B, 0xD1B7, 0xB78C, 0xD1B8, 0xB78D, 0xD1B9, 0xB78E, 0xD1BB,
+	0xB78F, 0xD1BD, 0xB790, 0xD1BE, 0xB791, 0xD1BF, 0xB792, 0xD1C1,
+	0xB793, 0xD1C2, 0xB794, 0xD1C3, 0xB795, 0xD1C4, 0xB796, 0xD1C5,
+	0xB797, 0xD1C6, 0xB798, 0xD1C7, 0xB799, 0xD1C8, 0xB79A, 0xD1C9,
+	0xB79B, 0xD1CA, 0xB79C, 0xD1CB, 0xB79D, 0xD1CC, 0xB79E, 0xD1CD,
+	0xB79F, 0xD1CE, 0xB7A0, 0xD1CF, 0xB7A1, 0xB798, 0xB7A2, 0xB799,
+	0xB7A3, 0xB79C, 0xB7A4, 0xB7A0, 0xB7A5, 0xB7A8, 0xB7A6, 0xB7A9,
+	0xB7A7, 0xB7AB, 0xB7A8, 0xB7AC, 0xB7A9, 0xB7AD, 0xB7AA, 0xB7B4,
+	0xB7AB, 0xB7B5, 0xB7AC, 0xB7B8, 0xB7AD, 0xB7C7, 0xB7AE, 0xB7C9,
+	0xB7AF, 0xB7EC, 0xB7B0, 0xB7ED, 0xB7B1, 0xB7F0, 0xB7B2, 0xB7F4,
+	0xB7B3, 0xB7FC, 0xB7B4, 0xB7FD, 0xB7B5, 0xB7FF, 0xB7B6, 0xB800,
+	0xB7B7, 0xB801, 0xB7B8, 0xB807, 0xB7B9, 0xB808, 0xB7BA, 0xB809,
+	0xB7BB, 0xB80C, 0xB7BC, 0xB810, 0xB7BD, 0xB818, 0xB7BE, 0xB819,
+	0xB7BF, 0xB81B, 0xB7C0, 0xB81D, 0xB7C1, 0xB824, 0xB7C2, 0xB825,
+	0xB7C3, 0xB828, 0xB7C4, 0xB82C, 0xB7C5, 0xB834, 0xB7C6, 0xB835,
+	0xB7C7, 0xB837, 0xB7C8, 0xB838, 0xB7C9, 0xB839, 0xB7CA, 0xB840,
+	0xB7CB, 0xB844, 0xB7CC, 0xB851, 0xB7CD, 0xB853, 0xB7CE, 0xB85C,
+	0xB7CF, 0xB85D, 0xB7D0, 0xB860, 0xB7D1, 0xB864, 0xB7D2, 0xB86C,
+	0xB7D3, 0xB86D, 0xB7D4, 0xB86F, 0xB7D5, 0xB871, 0xB7D6, 0xB878,
+	0xB7D7, 0xB87C, 0xB7D8, 0xB88D, 0xB7D9, 0xB8A8, 0xB7DA, 0xB8B0,
+	0xB7DB, 0xB8B4, 0xB7DC, 0xB8B8, 0xB7DD, 0xB8C0, 0xB7DE, 0xB8C1,
+	0xB7DF, 0xB8C3, 0xB7E0, 0xB8C5, 0xB7E1, 0xB8CC, 0xB7E2, 0xB8D0,
+	0xB7E3, 0xB8D4, 0xB7E4, 0xB8DD, 0xB7E5, 0xB8DF, 0xB7E6, 0xB8E1,
+	0xB7E7, 0xB8E8, 0xB7E8, 0xB8E9, 0xB7E9, 0xB8EC, 0xB7EA, 0xB8F0,
+	0xB7EB, 0xB8F8, 0xB7EC, 0xB8F9, 0xB7ED, 0xB8FB, 0xB7EE, 0xB8FD,
+	0xB7EF, 0xB904, 0xB7F0, 0xB918, 0xB7F1, 0xB920, 0xB7F2, 0xB93C,
+	0xB7F3, 0xB93D, 0xB7F4, 0xB940, 0xB7F5, 0xB944, 0xB7F6, 0xB94C,
+	0xB7F7, 0xB94F, 0xB7F8, 0xB951, 0xB7F9, 0xB958, 0xB7FA, 0xB959,
+	0xB7FB, 0xB95C, 0xB7FC, 0xB960, 0xB7FD, 0xB968, 0xB7FE, 0xB969,
+	0xB841, 0xD1D0, 0xB842, 0xD1D1, 0xB843, 0xD1D2, 0xB844, 0xD1D3,
+	0xB845, 0xD1D4, 0xB846, 0xD1D5, 0xB847, 0xD1D6, 0xB848, 0xD1D7,
+	0xB849, 0xD1D9, 0xB84A, 0xD1DA, 0xB84B, 0xD1DB, 0xB84C, 0xD1DC,
+	0xB84D, 0xD1DD, 0xB84E, 0xD1DE, 0xB84F, 0xD1DF, 0xB850, 0xD1E0,
+	0xB851, 0xD1E1, 0xB852, 0xD1E2, 0xB853, 0xD1E3, 0xB854, 0xD1E4,
+	0xB855, 0xD1E5, 0xB856, 0xD1E6, 0xB857, 0xD1E7, 0xB858, 0xD1E8,
+	0xB859, 0xD1E9, 0xB85A, 0xD1EA, 0xB861, 0xD1EB, 0xB862, 0xD1EC,
+	0xB863, 0xD1ED, 0xB864, 0xD1EE, 0xB865, 0xD1EF, 0xB866, 0xD1F0,
+	0xB867, 0xD1F1, 0xB868, 0xD1F2, 0xB869, 0xD1F3, 0xB86A, 0xD1F5,
+	0xB86B, 0xD1F6, 0xB86C, 0xD1F7, 0xB86D, 0xD1F9, 0xB86E, 0xD1FA,
+	0xB86F, 0xD1FB, 0xB870, 0xD1FC, 0xB871, 0xD1FD, 0xB872, 0xD1FE,
+	0xB873, 0xD1FF, 0xB874, 0xD200, 0xB875, 0xD201, 0xB876, 0xD202,
+	0xB877, 0xD203, 0xB878, 0xD204, 0xB879, 0xD205, 0xB87A, 0xD206,
+	0xB881, 0xD208, 0xB882, 0xD20A, 0xB883, 0xD20B, 0xB884, 0xD20C,
+	0xB885, 0xD20D, 0xB886, 0xD20E, 0xB887, 0xD20F, 0xB888, 0xD211,
+	0xB889, 0xD212, 0xB88A, 0xD213, 0xB88B, 0xD214, 0xB88C, 0xD215,
+	0xB88D, 0xD216, 0xB88E, 0xD217, 0xB88F, 0xD218, 0xB890, 0xD219,
+	0xB891, 0xD21A, 0xB892, 0xD21B, 0xB893, 0xD21C, 0xB894, 0xD21D,
+	0xB895, 0xD21E, 0xB896, 0xD21F, 0xB897, 0xD220, 0xB898, 0xD221,
+	0xB899, 0xD222, 0xB89A, 0xD223, 0xB89B, 0xD224, 0xB89C, 0xD225,
+	0xB89D, 0xD226, 0xB89E, 0xD227, 0xB89F, 0xD228, 0xB8A0, 0xD229,
+	0xB8A1, 0xB96B, 0xB8A2, 0xB96D, 0xB8A3, 0xB974, 0xB8A4, 0xB975,
+	0xB8A5, 0xB978, 0xB8A6, 0xB97C, 0xB8A7, 0xB984, 0xB8A8, 0xB985,
+	0xB8A9, 0xB987, 0xB8AA, 0xB989, 0xB8AB, 0xB98A, 0xB8AC, 0xB98D,
+	0xB8AD, 0xB98E, 0xB8AE, 0xB9AC, 0xB8AF, 0xB9AD, 0xB8B0, 0xB9B0,
+	0xB8B1, 0xB9B4, 0xB8B2, 0xB9BC, 0xB8B3, 0xB9BD, 0xB8B4, 0xB9BF,
+	0xB8B5, 0xB9C1, 0xB8B6, 0xB9C8, 0xB8B7, 0xB9C9, 0xB8B8, 0xB9CC,
+	0xB8B9, 0xB9CE, 0xB8BA, 0xB9CF, 0xB8BB, 0xB9D0, 0xB8BC, 0xB9D1,
+	0xB8BD, 0xB9D2, 0xB8BE, 0xB9D8, 0xB8BF, 0xB9D9, 0xB8C0, 0xB9DB,
+	0xB8C1, 0xB9DD, 0xB8C2, 0xB9DE, 0xB8C3, 0xB9E1, 0xB8C4, 0xB9E3,
+	0xB8C5, 0xB9E4, 0xB8C6, 0xB9E5, 0xB8C7, 0xB9E8, 0xB8C8, 0xB9EC,
+	0xB8C9, 0xB9F4, 0xB8CA, 0xB9F5, 0xB8CB, 0xB9F7, 0xB8CC, 0xB9F8,
+	0xB8CD, 0xB9F9, 0xB8CE, 0xB9FA, 0xB8CF, 0xBA00, 0xB8D0, 0xBA01,
+	0xB8D1, 0xBA08, 0xB8D2, 0xBA15, 0xB8D3, 0xBA38, 0xB8D4, 0xBA39,
+	0xB8D5, 0xBA3C, 0xB8D6, 0xBA40, 0xB8D7, 0xBA42, 0xB8D8, 0xBA48,
+	0xB8D9, 0xBA49, 0xB8DA, 0xBA4B, 0xB8DB, 0xBA4D, 0xB8DC, 0xBA4E,
+	0xB8DD, 0xBA53, 0xB8DE, 0xBA54, 0xB8DF, 0xBA55, 0xB8E0, 0xBA58,
+	0xB8E1, 0xBA5C, 0xB8E2, 0xBA64, 0xB8E3, 0xBA65, 0xB8E4, 0xBA67,
+	0xB8E5, 0xBA68, 0xB8E6, 0xBA69, 0xB8E7, 0xBA70, 0xB8E8, 0xBA71,
+	0xB8E9, 0xBA74, 0xB8EA, 0xBA78, 0xB8EB, 0xBA83, 0xB8EC, 0xBA84,
+	0xB8ED, 0xBA85, 0xB8EE, 0xBA87, 0xB8EF, 0xBA8C, 0xB8F0, 0xBAA8,
+	0xB8F1, 0xBAA9, 0xB8F2, 0xBAAB, 0xB8F3, 0xBAAC, 0xB8F4, 0xBAB0,
+	0xB8F5, 0xBAB2, 0xB8F6, 0xBAB8, 0xB8F7, 0xBAB9, 0xB8F8, 0xBABB,
+	0xB8F9, 0xBABD, 0xB8FA, 0xBAC4, 0xB8FB, 0xBAC8, 0xB8FC, 0xBAD8,
+	0xB8FD, 0xBAD9, 0xB8FE, 0xBAFC, 0xB941, 0xD22A, 0xB942, 0xD22B,
+	0xB943, 0xD22E, 0xB944, 0xD22F, 0xB945, 0xD231, 0xB946, 0xD232,
+	0xB947, 0xD233, 0xB948, 0xD235, 0xB949, 0xD236, 0xB94A, 0xD237,
+	0xB94B, 0xD238, 0xB94C, 0xD239, 0xB94D, 0xD23A, 0xB94E, 0xD23B,
+	0xB94F, 0xD23E, 0xB950, 0xD240, 0xB951, 0xD242, 0xB952, 0xD243,
+	0xB953, 0xD244, 0xB954, 0xD245, 0xB955, 0xD246, 0xB956, 0xD247,
+	0xB957, 0xD249, 0xB958, 0xD24A, 0xB959, 0xD24B, 0xB95A, 0xD24C,
+	0xB961, 0xD24D, 0xB962, 0xD24E, 0xB963, 0xD24F, 0xB964, 0xD250,
+	0xB965, 0xD251, 0xB966, 0xD252, 0xB967, 0xD253, 0xB968, 0xD254,
+	0xB969, 0xD255, 0xB96A, 0xD256, 0xB96B, 0xD257, 0xB96C, 0xD258,
+	0xB96D, 0xD259, 0xB96E, 0xD25A, 0xB96F, 0xD25B, 0xB970, 0xD25D,
+	0xB971, 0xD25E, 0xB972, 0xD25F, 0xB973, 0xD260, 0xB974, 0xD261,
+	0xB975, 0xD262, 0xB976, 0xD263, 0xB977, 0xD265, 0xB978, 0xD266,
+	0xB979, 0xD267, 0xB97A, 0xD268, 0xB981, 0xD269, 0xB982, 0xD26A,
+	0xB983, 0xD26B, 0xB984, 0xD26C, 0xB985, 0xD26D, 0xB986, 0xD26E,
+	0xB987, 0xD26F, 0xB988, 0xD270, 0xB989, 0xD271, 0xB98A, 0xD272,
+	0xB98B, 0xD273, 0xB98C, 0xD274, 0xB98D, 0xD275, 0xB98E, 0xD276,
+	0xB98F, 0xD277, 0xB990, 0xD278, 0xB991, 0xD279, 0xB992, 0xD27A,
+	0xB993, 0xD27B, 0xB994, 0xD27C, 0xB995, 0xD27D, 0xB996, 0xD27E,
+	0xB997, 0xD27F, 0xB998, 0xD282, 0xB999, 0xD283, 0xB99A, 0xD285,
+	0xB99B, 0xD286, 0xB99C, 0xD287, 0xB99D, 0xD289, 0xB99E, 0xD28A,
+	0xB99F, 0xD28B, 0xB9A0, 0xD28C, 0xB9A1, 0xBB00, 0xB9A2, 0xBB04,
+	0xB9A3, 0xBB0D, 0xB9A4, 0xBB0F, 0xB9A5, 0xBB11, 0xB9A6, 0xBB18,
+	0xB9A7, 0xBB1C, 0xB9A8, 0xBB20, 0xB9A9, 0xBB29, 0xB9AA, 0xBB2B,
+	0xB9AB, 0xBB34, 0xB9AC, 0xBB35, 0xB9AD, 0xBB36, 0xB9AE, 0xBB38,
+	0xB9AF, 0xBB3B, 0xB9B0, 0xBB3C, 0xB9B1, 0xBB3D, 0xB9B2, 0xBB3E,
+	0xB9B3, 0xBB44, 0xB9B4, 0xBB45, 0xB9B5, 0xBB47, 0xB9B6, 0xBB49,
+	0xB9B7, 0xBB4D, 0xB9B8, 0xBB4F, 0xB9B9, 0xBB50, 0xB9BA, 0xBB54,
+	0xB9BB, 0xBB58, 0xB9BC, 0xBB61, 0xB9BD, 0xBB63, 0xB9BE, 0xBB6C,
+	0xB9BF, 0xBB88, 0xB9C0, 0xBB8C, 0xB9C1, 0xBB90, 0xB9C2, 0xBBA4,
+	0xB9C3, 0xBBA8, 0xB9C4, 0xBBAC, 0xB9C5, 0xBBB4, 0xB9C6, 0xBBB7,
+	0xB9C7, 0xBBC0, 0xB9C8, 0xBBC4, 0xB9C9, 0xBBC8, 0xB9CA, 0xBBD0,
+	0xB9CB, 0xBBD3, 0xB9CC, 0xBBF8, 0xB9CD, 0xBBF9, 0xB9CE, 0xBBFC,
+	0xB9CF, 0xBBFF, 0xB9D0, 0xBC00, 0xB9D1, 0xBC02, 0xB9D2, 0xBC08,
+	0xB9D3, 0xBC09, 0xB9D4, 0xBC0B, 0xB9D5, 0xBC0C, 0xB9D6, 0xBC0D,
+	0xB9D7, 0xBC0F, 0xB9D8, 0xBC11, 0xB9D9, 0xBC14, 0xB9DA, 0xBC15,
+	0xB9DB, 0xBC16, 0xB9DC, 0xBC17, 0xB9DD, 0xBC18, 0xB9DE, 0xBC1B,
+	0xB9DF, 0xBC1C, 0xB9E0, 0xBC1D, 0xB9E1, 0xBC1E, 0xB9E2, 0xBC1F,
+	0xB9E3, 0xBC24, 0xB9E4, 0xBC25, 0xB9E5, 0xBC27, 0xB9E6, 0xBC29,
+	0xB9E7, 0xBC2D, 0xB9E8, 0xBC30, 0xB9E9, 0xBC31, 0xB9EA, 0xBC34,
+	0xB9EB, 0xBC38, 0xB9EC, 0xBC40, 0xB9ED, 0xBC41, 0xB9EE, 0xBC43,
+	0xB9EF, 0xBC44, 0xB9F0, 0xBC45, 0xB9F1, 0xBC49, 0xB9F2, 0xBC4C,
+	0xB9F3, 0xBC4D, 0xB9F4, 0xBC50, 0xB9F5, 0xBC5D, 0xB9F6, 0xBC84,
+	0xB9F7, 0xBC85, 0xB9F8, 0xBC88, 0xB9F9, 0xBC8B, 0xB9FA, 0xBC8C,
+	0xB9FB, 0xBC8E, 0xB9FC, 0xBC94, 0xB9FD, 0xBC95, 0xB9FE, 0xBC97,
+	0xBA41, 0xD28D, 0xBA42, 0xD28E, 0xBA43, 0xD28F, 0xBA44, 0xD292,
+	0xBA45, 0xD293, 0xBA46, 0xD294, 0xBA47, 0xD296, 0xBA48, 0xD297,
+	0xBA49, 0xD298, 0xBA4A, 0xD299, 0xBA4B, 0xD29A, 0xBA4C, 0xD29B,
+	0xBA4D, 0xD29D, 0xBA4E, 0xD29E, 0xBA4F, 0xD29F, 0xBA50, 0xD2A1,
+	0xBA51, 0xD2A2, 0xBA52, 0xD2A3, 0xBA53, 0xD2A5, 0xBA54, 0xD2A6,
+	0xBA55, 0xD2A7, 0xBA56, 0xD2A8, 0xBA57, 0xD2A9, 0xBA58, 0xD2AA,
+	0xBA59, 0xD2AB, 0xBA5A, 0xD2AD, 0xBA61, 0xD2AE, 0xBA62, 0xD2AF,
+	0xBA63, 0xD2B0, 0xBA64, 0xD2B2, 0xBA65, 0xD2B3, 0xBA66, 0xD2B4,
+	0xBA67, 0xD2B5, 0xBA68, 0xD2B6, 0xBA69, 0xD2B7, 0xBA6A, 0xD2BA,
+	0xBA6B, 0xD2BB, 0xBA6C, 0xD2BD, 0xBA6D, 0xD2BE, 0xBA6E, 0xD2C1,
+	0xBA6F, 0xD2C3, 0xBA70, 0xD2C4, 0xBA71, 0xD2C5, 0xBA72, 0xD2C6,
+	0xBA73, 0xD2C7, 0xBA74, 0xD2CA, 0xBA75, 0xD2CC, 0xBA76, 0xD2CD,
+	0xBA77, 0xD2CE, 0xBA78, 0xD2CF, 0xBA79, 0xD2D0, 0xBA7A, 0xD2D1,
+	0xBA81, 0xD2D2, 0xBA82, 0xD2D3, 0xBA83, 0xD2D5, 0xBA84, 0xD2D6,
+	0xBA85, 0xD2D7, 0xBA86, 0xD2D9, 0xBA87, 0xD2DA, 0xBA88, 0xD2DB,
+	0xBA89, 0xD2DD, 0xBA8A, 0xD2DE, 0xBA8B, 0xD2DF, 0xBA8C, 0xD2E0,
+	0xBA8D, 0xD2E1, 0xBA8E, 0xD2E2, 0xBA8F, 0xD2E3, 0xBA90, 0xD2E6,
+	0xBA91, 0xD2E7, 0xBA92, 0xD2E8, 0xBA93, 0xD2E9, 0xBA94, 0xD2EA,
+	0xBA95, 0xD2EB, 0xBA96, 0xD2EC, 0xBA97, 0xD2ED, 0xBA98, 0xD2EE,
+	0xBA99, 0xD2EF, 0xBA9A, 0xD2F2, 0xBA9B, 0xD2F3, 0xBA9C, 0xD2F5,
+	0xBA9D, 0xD2F6, 0xBA9E, 0xD2F7, 0xBA9F, 0xD2F9, 0xBAA0, 0xD2FA,
+	0xBAA1, 0xBC99, 0xBAA2, 0xBC9A, 0xBAA3, 0xBCA0, 0xBAA4, 0xBCA1,
+	0xBAA5, 0xBCA4, 0xBAA6, 0xBCA7, 0xBAA7, 0xBCA8, 0xBAA8, 0xBCB0,
+	0xBAA9, 0xBCB1, 0xBAAA, 0xBCB3, 0xBAAB, 0xBCB4, 0xBAAC, 0xBCB5,
+	0xBAAD, 0xBCBC, 0xBAAE, 0xBCBD, 0xBAAF, 0xBCC0, 0xBAB0, 0xBCC4,
+	0xBAB1, 0xBCCD, 0xBAB2, 0xBCCF, 0xBAB3, 0xBCD0, 0xBAB4, 0xBCD1,
+	0xBAB5, 0xBCD5, 0xBAB6, 0xBCD8, 0xBAB7, 0xBCDC, 0xBAB8, 0xBCF4,
+	0xBAB9, 0xBCF5, 0xBABA, 0xBCF6, 0xBABB, 0xBCF8, 0xBABC, 0xBCFC,
+	0xBABD, 0xBD04, 0xBABE, 0xBD05, 0xBABF, 0xBD07, 0xBAC0, 0xBD09,
+	0xBAC1, 0xBD10, 0xBAC2, 0xBD14, 0xBAC3, 0xBD24, 0xBAC4, 0xBD2C,
+	0xBAC5, 0xBD40, 0xBAC6, 0xBD48, 0xBAC7, 0xBD49, 0xBAC8, 0xBD4C,
+	0xBAC9, 0xBD50, 0xBACA, 0xBD58, 0xBACB, 0xBD59, 0xBACC, 0xBD64,
+	0xBACD, 0xBD68, 0xBACE, 0xBD80, 0xBACF, 0xBD81, 0xBAD0, 0xBD84,
+	0xBAD1, 0xBD87, 0xBAD2, 0xBD88, 0xBAD3, 0xBD89, 0xBAD4, 0xBD8A,
+	0xBAD5, 0xBD90, 0xBAD6, 0xBD91, 0xBAD7, 0xBD93, 0xBAD8, 0xBD95,
+	0xBAD9, 0xBD99, 0xBADA, 0xBD9A, 0xBADB, 0xBD9C, 0xBADC, 0xBDA4,
+	0xBADD, 0xBDB0, 0xBADE, 0xBDB8, 0xBADF, 0xBDD4, 0xBAE0, 0xBDD5,
+	0xBAE1, 0xBDD8, 0xBAE2, 0xBDDC, 0xBAE3, 0xBDE9, 0xBAE4, 0xBDF0,
+	0xBAE5, 0xBDF4, 0xBAE6, 0xBDF8, 0xBAE7, 0xBE00, 0xBAE8, 0xBE03,
+	0xBAE9, 0xBE05, 0xBAEA, 0xBE0C, 0xBAEB, 0xBE0D, 0xBAEC, 0xBE10,
+	0xBAED, 0xBE14, 0xBAEE, 0xBE1C, 0xBAEF, 0xBE1D, 0xBAF0, 0xBE1F,
+	0xBAF1, 0xBE44, 0xBAF2, 0xBE45, 0xBAF3, 0xBE48, 0xBAF4, 0xBE4C,
+	0xBAF5, 0xBE4E, 0xBAF6, 0xBE54, 0xBAF7, 0xBE55, 0xBAF8, 0xBE57,
+	0xBAF9, 0xBE59, 0xBAFA, 0xBE5A, 0xBAFB, 0xBE5B, 0xBAFC, 0xBE60,
+	0xBAFD, 0xBE61, 0xBAFE, 0xBE64, 0xBB41, 0xD2FB, 0xBB42, 0xD2FC,
+	0xBB43, 0xD2FD, 0xBB44, 0xD2FE, 0xBB45, 0xD2FF, 0xBB46, 0xD302,
+	0xBB47, 0xD304, 0xBB48, 0xD306, 0xBB49, 0xD307, 0xBB4A, 0xD308,
+	0xBB4B, 0xD309, 0xBB4C, 0xD30A, 0xBB4D, 0xD30B, 0xBB4E, 0xD30F,
+	0xBB4F, 0xD311, 0xBB50, 0xD312, 0xBB51, 0xD313, 0xBB52, 0xD315,
+	0xBB53, 0xD317, 0xBB54, 0xD318, 0xBB55, 0xD319, 0xBB56, 0xD31A,
+	0xBB57, 0xD31B, 0xBB58, 0xD31E, 0xBB59, 0xD322, 0xBB5A, 0xD323,
+	0xBB61, 0xD324, 0xBB62, 0xD326, 0xBB63, 0xD327, 0xBB64, 0xD32A,
+	0xBB65, 0xD32B, 0xBB66, 0xD32D, 0xBB67, 0xD32E, 0xBB68, 0xD32F,
+	0xBB69, 0xD331, 0xBB6A, 0xD332, 0xBB6B, 0xD333, 0xBB6C, 0xD334,
+	0xBB6D, 0xD335, 0xBB6E, 0xD336, 0xBB6F, 0xD337, 0xBB70, 0xD33A,
+	0xBB71, 0xD33E, 0xBB72, 0xD33F, 0xBB73, 0xD340, 0xBB74, 0xD341,
+	0xBB75, 0xD342, 0xBB76, 0xD343, 0xBB77, 0xD346, 0xBB78, 0xD347,
+	0xBB79, 0xD348, 0xBB7A, 0xD349, 0xBB81, 0xD34A, 0xBB82, 0xD34B,
+	0xBB83, 0xD34C, 0xBB84, 0xD34D, 0xBB85, 0xD34E, 0xBB86, 0xD34F,
+	0xBB87, 0xD350, 0xBB88, 0xD351, 0xBB89, 0xD352, 0xBB8A, 0xD353,
+	0xBB8B, 0xD354, 0xBB8C, 0xD355, 0xBB8D, 0xD356, 0xBB8E, 0xD357,
+	0xBB8F, 0xD358, 0xBB90, 0xD359, 0xBB91, 0xD35A, 0xBB92, 0xD35B,
+	0xBB93, 0xD35C, 0xBB94, 0xD35D, 0xBB95, 0xD35E, 0xBB96, 0xD35F,
+	0xBB97, 0xD360, 0xBB98, 0xD361, 0xBB99, 0xD362, 0xBB9A, 0xD363,
+	0xBB9B, 0xD364, 0xBB9C, 0xD365, 0xBB9D, 0xD366, 0xBB9E, 0xD367,
+	0xBB9F, 0xD368, 0xBBA0, 0xD369, 0xBBA1, 0xBE68, 0xBBA2, 0xBE6A,
+	0xBBA3, 0xBE70, 0xBBA4, 0xBE71, 0xBBA5, 0xBE73, 0xBBA6, 0xBE74,
+	0xBBA7, 0xBE75, 0xBBA8, 0xBE7B, 0xBBA9, 0xBE7C, 0xBBAA, 0xBE7D,
+	0xBBAB, 0xBE80, 0xBBAC, 0xBE84, 0xBBAD, 0xBE8C, 0xBBAE, 0xBE8D,
+	0xBBAF, 0xBE8F, 0xBBB0, 0xBE90, 0xBBB1, 0xBE91, 0xBBB2, 0xBE98,
+	0xBBB3, 0xBE99, 0xBBB4, 0xBEA8, 0xBBB5, 0xBED0, 0xBBB6, 0xBED1,
+	0xBBB7, 0xBED4, 0xBBB8, 0xBED7, 0xBBB9, 0xBED8, 0xBBBA, 0xBEE0,
+	0xBBBB, 0xBEE3, 0xBBBC, 0xBEE4, 0xBBBD, 0xBEE5, 0xBBBE, 0xBEEC,
+	0xBBBF, 0xBF01, 0xBBC0, 0xBF08, 0xBBC1, 0xBF09, 0xBBC2, 0xBF18,
+	0xBBC3, 0xBF19, 0xBBC4, 0xBF1B, 0xBBC5, 0xBF1C, 0xBBC6, 0xBF1D,
+	0xBBC7, 0xBF40, 0xBBC8, 0xBF41, 0xBBC9, 0xBF44, 0xBBCA, 0xBF48,
+	0xBBCB, 0xBF50, 0xBBCC, 0xBF51, 0xBBCD, 0xBF55, 0xBBCE, 0xBF94,
+	0xBBCF, 0xBFB0, 0xBBD0, 0xBFC5, 0xBBD1, 0xBFCC, 0xBBD2, 0xBFCD,
+	0xBBD3, 0xBFD0, 0xBBD4, 0xBFD4, 0xBBD5, 0xBFDC, 0xBBD6, 0xBFDF,
+	0xBBD7, 0xBFE1, 0xBBD8, 0xC03C, 0xBBD9, 0xC051, 0xBBDA, 0xC058,
+	0xBBDB, 0xC05C, 0xBBDC, 0xC060, 0xBBDD, 0xC068, 0xBBDE, 0xC069,
+	0xBBDF, 0xC090, 0xBBE0, 0xC091, 0xBBE1, 0xC094, 0xBBE2, 0xC098,
+	0xBBE3, 0xC0A0, 0xBBE4, 0xC0A1, 0xBBE5, 0xC0A3, 0xBBE6, 0xC0A5,
+	0xBBE7, 0xC0AC, 0xBBE8, 0xC0AD, 0xBBE9, 0xC0AF, 0xBBEA, 0xC0B0,
+	0xBBEB, 0xC0B3, 0xBBEC, 0xC0B4, 0xBBED, 0xC0B5, 0xBBEE, 0xC0B6,
+	0xBBEF, 0xC0BC, 0xBBF0, 0xC0BD, 0xBBF1, 0xC0BF, 0xBBF2, 0xC0C0,
+	0xBBF3, 0xC0C1, 0xBBF4, 0xC0C5, 0xBBF5, 0xC0C8, 0xBBF6, 0xC0C9,
+	0xBBF7, 0xC0CC, 0xBBF8, 0xC0D0, 0xBBF9, 0xC0D8, 0xBBFA, 0xC0D9,
+	0xBBFB, 0xC0DB, 0xBBFC, 0xC0DC, 0xBBFD, 0xC0DD, 0xBBFE, 0xC0E4,
+	0xBC41, 0xD36A, 0xBC42, 0xD36B, 0xBC43, 0xD36C, 0xBC44, 0xD36D,
+	0xBC45, 0xD36E, 0xBC46, 0xD36F, 0xBC47, 0xD370, 0xBC48, 0xD371,
+	0xBC49, 0xD372, 0xBC4A, 0xD373, 0xBC4B, 0xD374, 0xBC4C, 0xD375,
+	0xBC4D, 0xD376, 0xBC4E, 0xD377, 0xBC4F, 0xD378, 0xBC50, 0xD379,
+	0xBC51, 0xD37A, 0xBC52, 0xD37B, 0xBC53, 0xD37E, 0xBC54, 0xD37F,
+	0xBC55, 0xD381, 0xBC56, 0xD382, 0xBC57, 0xD383, 0xBC58, 0xD385,
+	0xBC59, 0xD386, 0xBC5A, 0xD387, 0xBC61, 0xD388, 0xBC62, 0xD389,
+	0xBC63, 0xD38A, 0xBC64, 0xD38B, 0xBC65, 0xD38E, 0xBC66, 0xD392,
+	0xBC67, 0xD393, 0xBC68, 0xD394, 0xBC69, 0xD395, 0xBC6A, 0xD396,
+	0xBC6B, 0xD397, 0xBC6C, 0xD39A, 0xBC6D, 0xD39B, 0xBC6E, 0xD39D,
+	0xBC6F, 0xD39E, 0xBC70, 0xD39F, 0xBC71, 0xD3A1, 0xBC72, 0xD3A2,
+	0xBC73, 0xD3A3, 0xBC74, 0xD3A4, 0xBC75, 0xD3A5, 0xBC76, 0xD3A6,
+	0xBC77, 0xD3A7, 0xBC78, 0xD3AA, 0xBC79, 0xD3AC, 0xBC7A, 0xD3AE,
+	0xBC81, 0xD3AF, 0xBC82, 0xD3B0, 0xBC83, 0xD3B1, 0xBC84, 0xD3B2,
+	0xBC85, 0xD3B3, 0xBC86, 0xD3B5, 0xBC87, 0xD3B6, 0xBC88, 0xD3B7,
+	0xBC89, 0xD3B9, 0xBC8A, 0xD3BA, 0xBC8B, 0xD3BB, 0xBC8C, 0xD3BD,
+	0xBC8D, 0xD3BE, 0xBC8E, 0xD3BF, 0xBC8F, 0xD3C0, 0xBC90, 0xD3C1,
+	0xBC91, 0xD3C2, 0xBC92, 0xD3C3, 0xBC93, 0xD3C6, 0xBC94, 0xD3C7,
+	0xBC95, 0xD3CA, 0xBC96, 0xD3CB, 0xBC97, 0xD3CC, 0xBC98, 0xD3CD,
+	0xBC99, 0xD3CE, 0xBC9A, 0xD3CF, 0xBC9B, 0xD3D1, 0xBC9C, 0xD3D2,
+	0xBC9D, 0xD3D3, 0xBC9E, 0xD3D4, 0xBC9F, 0xD3D5, 0xBCA0, 0xD3D6,
+	0xBCA1, 0xC0E5, 0xBCA2, 0xC0E8, 0xBCA3, 0xC0EC, 0xBCA4, 0xC0F4,
+	0xBCA5, 0xC0F5, 0xBCA6, 0xC0F7, 0xBCA7, 0xC0F9, 0xBCA8, 0xC100,
+	0xBCA9, 0xC104, 0xBCAA, 0xC108, 0xBCAB, 0xC110, 0xBCAC, 0xC115,
+	0xBCAD, 0xC11C, 0xBCAE, 0xC11D, 0xBCAF, 0xC11E, 0xBCB0, 0xC11F,
+	0xBCB1, 0xC120, 0xBCB2, 0xC123, 0xBCB3, 0xC124, 0xBCB4, 0xC126,
+	0xBCB5, 0xC127, 0xBCB6, 0xC12C, 0xBCB7, 0xC12D, 0xBCB8, 0xC12F,
+	0xBCB9, 0xC130, 0xBCBA, 0xC131, 0xBCBB, 0xC136, 0xBCBC, 0xC138,
+	0xBCBD, 0xC139, 0xBCBE, 0xC13C, 0xBCBF, 0xC140, 0xBCC0, 0xC148,
+	0xBCC1, 0xC149, 0xBCC2, 0xC14B, 0xBCC3, 0xC14C, 0xBCC4, 0xC14D,
+	0xBCC5, 0xC154, 0xBCC6, 0xC155, 0xBCC7, 0xC158, 0xBCC8, 0xC15C,
+	0xBCC9, 0xC164, 0xBCCA, 0xC165, 0xBCCB, 0xC167, 0xBCCC, 0xC168,
+	0xBCCD, 0xC169, 0xBCCE, 0xC170, 0xBCCF, 0xC174, 0xBCD0, 0xC178,
+	0xBCD1, 0xC185, 0xBCD2, 0xC18C, 0xBCD3, 0xC18D, 0xBCD4, 0xC18E,
+	0xBCD5, 0xC190, 0xBCD6, 0xC194, 0xBCD7, 0xC196, 0xBCD8, 0xC19C,
+	0xBCD9, 0xC19D, 0xBCDA, 0xC19F, 0xBCDB, 0xC1A1, 0xBCDC, 0xC1A5,
+	0xBCDD, 0xC1A8, 0xBCDE, 0xC1A9, 0xBCDF, 0xC1AC, 0xBCE0, 0xC1B0,
+	0xBCE1, 0xC1BD, 0xBCE2, 0xC1C4, 0xBCE3, 0xC1C8, 0xBCE4, 0xC1CC,
+	0xBCE5, 0xC1D4, 0xBCE6, 0xC1D7, 0xBCE7, 0xC1D8, 0xBCE8, 0xC1E0,
+	0xBCE9, 0xC1E4, 0xBCEA, 0xC1E8, 0xBCEB, 0xC1F0, 0xBCEC, 0xC1F1,
+	0xBCED, 0xC1F3, 0xBCEE, 0xC1FC, 0xBCEF, 0xC1FD, 0xBCF0, 0xC200,
+	0xBCF1, 0xC204, 0xBCF2, 0xC20C, 0xBCF3, 0xC20D, 0xBCF4, 0xC20F,
+	0xBCF5, 0xC211, 0xBCF6, 0xC218, 0xBCF7, 0xC219, 0xBCF8, 0xC21C,
+	0xBCF9, 0xC21F, 0xBCFA, 0xC220, 0xBCFB, 0xC228, 0xBCFC, 0xC229,
+	0xBCFD, 0xC22B, 0xBCFE, 0xC22D, 0xBD41, 0xD3D7, 0xBD42, 0xD3D9,
+	0xBD43, 0xD3DA, 0xBD44, 0xD3DB, 0xBD45, 0xD3DC, 0xBD46, 0xD3DD,
+	0xBD47, 0xD3DE, 0xBD48, 0xD3DF, 0xBD49, 0xD3E0, 0xBD4A, 0xD3E2,
+	0xBD4B, 0xD3E4, 0xBD4C, 0xD3E5, 0xBD4D, 0xD3E6, 0xBD4E, 0xD3E7,
+	0xBD4F, 0xD3E8, 0xBD50, 0xD3E9, 0xBD51, 0xD3EA, 0xBD52, 0xD3EB,
+	0xBD53, 0xD3EE, 0xBD54, 0xD3EF, 0xBD55, 0xD3F1, 0xBD56, 0xD3F2,
+	0xBD57, 0xD3F3, 0xBD58, 0xD3F5, 0xBD59, 0xD3F6, 0xBD5A, 0xD3F7,
+	0xBD61, 0xD3F8, 0xBD62, 0xD3F9, 0xBD63, 0xD3FA, 0xBD64, 0xD3FB,
+	0xBD65, 0xD3FE, 0xBD66, 0xD400, 0xBD67, 0xD402, 0xBD68, 0xD403,
+	0xBD69, 0xD404, 0xBD6A, 0xD405, 0xBD6B, 0xD406, 0xBD6C, 0xD407,
+	0xBD6D, 0xD409, 0xBD6E, 0xD40A, 0xBD6F, 0xD40B, 0xBD70, 0xD40C,
+	0xBD71, 0xD40D, 0xBD72, 0xD40E, 0xBD73, 0xD40F, 0xBD74, 0xD410,
+	0xBD75, 0xD411, 0xBD76, 0xD412, 0xBD77, 0xD413, 0xBD78, 0xD414,
+	0xBD79, 0xD415, 0xBD7A, 0xD416, 0xBD81, 0xD417, 0xBD82, 0xD418,
+	0xBD83, 0xD419, 0xBD84, 0xD41A, 0xBD85, 0xD41B, 0xBD86, 0xD41C,
+	0xBD87, 0xD41E, 0xBD88, 0xD41F, 0xBD89, 0xD420, 0xBD8A, 0xD421,
+	0xBD8B, 0xD422, 0xBD8C, 0xD423, 0xBD8D, 0xD424, 0xBD8E, 0xD425,
+	0xBD8F, 0xD426, 0xBD90, 0xD427, 0xBD91, 0xD428, 0xBD92, 0xD429,
+	0xBD93, 0xD42A, 0xBD94, 0xD42B, 0xBD95, 0xD42C, 0xBD96, 0xD42D,
+	0xBD97, 0xD42E, 0xBD98, 0xD42F, 0xBD99, 0xD430, 0xBD9A, 0xD431,
+	0xBD9B, 0xD432, 0xBD9C, 0xD433, 0xBD9D, 0xD434, 0xBD9E, 0xD435,
+	0xBD9F, 0xD436, 0xBDA0, 0xD437, 0xBDA1, 0xC22F, 0xBDA2, 0xC231,
+	0xBDA3, 0xC232, 0xBDA4, 0xC234, 0xBDA5, 0xC248, 0xBDA6, 0xC250,
+	0xBDA7, 0xC251, 0xBDA8, 0xC254, 0xBDA9, 0xC258, 0xBDAA, 0xC260,
+	0xBDAB, 0xC265, 0xBDAC, 0xC26C, 0xBDAD, 0xC26D, 0xBDAE, 0xC270,
+	0xBDAF, 0xC274, 0xBDB0, 0xC27C, 0xBDB1, 0xC27D, 0xBDB2, 0xC27F,
+	0xBDB3, 0xC281, 0xBDB4, 0xC288, 0xBDB5, 0xC289, 0xBDB6, 0xC290,
+	0xBDB7, 0xC298, 0xBDB8, 0xC29B, 0xBDB9, 0xC29D, 0xBDBA, 0xC2A4,
+	0xBDBB, 0xC2A5, 0xBDBC, 0xC2A8, 0xBDBD, 0xC2AC, 0xBDBE, 0xC2AD,
+	0xBDBF, 0xC2B4, 0xBDC0, 0xC2B5, 0xBDC1, 0xC2B7, 0xBDC2, 0xC2B9,
+	0xBDC3, 0xC2DC, 0xBDC4, 0xC2DD, 0xBDC5, 0xC2E0, 0xBDC6, 0xC2E3,
+	0xBDC7, 0xC2E4, 0xBDC8, 0xC2EB, 0xBDC9, 0xC2EC, 0xBDCA, 0xC2ED,
+	0xBDCB, 0xC2EF, 0xBDCC, 0xC2F1, 0xBDCD, 0xC2F6, 0xBDCE, 0xC2F8,
+	0xBDCF, 0xC2F9, 0xBDD0, 0xC2FB, 0xBDD1, 0xC2FC, 0xBDD2, 0xC300,
+	0xBDD3, 0xC308, 0xBDD4, 0xC309, 0xBDD5, 0xC30C, 0xBDD6, 0xC30D,
+	0xBDD7, 0xC313, 0xBDD8, 0xC314, 0xBDD9, 0xC315, 0xBDDA, 0xC318,
+	0xBDDB, 0xC31C, 0xBDDC, 0xC324, 0xBDDD, 0xC325, 0xBDDE, 0xC328,
+	0xBDDF, 0xC329, 0xBDE0, 0xC345, 0xBDE1, 0xC368, 0xBDE2, 0xC369,
+	0xBDE3, 0xC36C, 0xBDE4, 0xC370, 0xBDE5, 0xC372, 0xBDE6, 0xC378,
+	0xBDE7, 0xC379, 0xBDE8, 0xC37C, 0xBDE9, 0xC37D, 0xBDEA, 0xC384,
+	0xBDEB, 0xC388, 0xBDEC, 0xC38C, 0xBDED, 0xC3C0, 0xBDEE, 0xC3D8,
+	0xBDEF, 0xC3D9, 0xBDF0, 0xC3DC, 0xBDF1, 0xC3DF, 0xBDF2, 0xC3E0,
+	0xBDF3, 0xC3E2, 0xBDF4, 0xC3E8, 0xBDF5, 0xC3E9, 0xBDF6, 0xC3ED,
+	0xBDF7, 0xC3F4, 0xBDF8, 0xC3F5, 0xBDF9, 0xC3F8, 0xBDFA, 0xC408,
+	0xBDFB, 0xC410, 0xBDFC, 0xC424, 0xBDFD, 0xC42C, 0xBDFE, 0xC430,
+	0xBE41, 0xD438, 0xBE42, 0xD439, 0xBE43, 0xD43A, 0xBE44, 0xD43B,
+	0xBE45, 0xD43C, 0xBE46, 0xD43D, 0xBE47, 0xD43E, 0xBE48, 0xD43F,
+	0xBE49, 0xD441, 0xBE4A, 0xD442, 0xBE4B, 0xD443, 0xBE4C, 0xD445,
+	0xBE4D, 0xD446, 0xBE4E, 0xD447, 0xBE4F, 0xD448, 0xBE50, 0xD449,
+	0xBE51, 0xD44A, 0xBE52, 0xD44B, 0xBE53, 0xD44C, 0xBE54, 0xD44D,
+	0xBE55, 0xD44E, 0xBE56, 0xD44F, 0xBE57, 0xD450, 0xBE58, 0xD451,
+	0xBE59, 0xD452, 0xBE5A, 0xD453, 0xBE61, 0xD454, 0xBE62, 0xD455,
+	0xBE63, 0xD456, 0xBE64, 0xD457, 0xBE65, 0xD458, 0xBE66, 0xD459,
+	0xBE67, 0xD45A, 0xBE68, 0xD45B, 0xBE69, 0xD45D, 0xBE6A, 0xD45E,
+	0xBE6B, 0xD45F, 0xBE6C, 0xD461, 0xBE6D, 0xD462, 0xBE6E, 0xD463,
+	0xBE6F, 0xD465, 0xBE70, 0xD466, 0xBE71, 0xD467, 0xBE72, 0xD468,
+	0xBE73, 0xD469, 0xBE74, 0xD46A, 0xBE75, 0xD46B, 0xBE76, 0xD46C,
+	0xBE77, 0xD46E, 0xBE78, 0xD470, 0xBE79, 0xD471, 0xBE7A, 0xD472,
+	0xBE81, 0xD473, 0xBE82, 0xD474, 0xBE83, 0xD475, 0xBE84, 0xD476,
+	0xBE85, 0xD477, 0xBE86, 0xD47A, 0xBE87, 0xD47B, 0xBE88, 0xD47D,
+	0xBE89, 0xD47E, 0xBE8A, 0xD481, 0xBE8B, 0xD483, 0xBE8C, 0xD484,
+	0xBE8D, 0xD485, 0xBE8E, 0xD486, 0xBE8F, 0xD487, 0xBE90, 0xD48A,
+	0xBE91, 0xD48C, 0xBE92, 0xD48E, 0xBE93, 0xD48F, 0xBE94, 0xD490,
+	0xBE95, 0xD491, 0xBE96, 0xD492, 0xBE97, 0xD493, 0xBE98, 0xD495,
+	0xBE99, 0xD496, 0xBE9A, 0xD497, 0xBE9B, 0xD498, 0xBE9C, 0xD499,
+	0xBE9D, 0xD49A, 0xBE9E, 0xD49B, 0xBE9F, 0xD49C, 0xBEA0, 0xD49D,
+	0xBEA1, 0xC434, 0xBEA2, 0xC43C, 0xBEA3, 0xC43D, 0xBEA4, 0xC448,
+	0xBEA5, 0xC464, 0xBEA6, 0xC465, 0xBEA7, 0xC468, 0xBEA8, 0xC46C,
+	0xBEA9, 0xC474, 0xBEAA, 0xC475, 0xBEAB, 0xC479, 0xBEAC, 0xC480,
+	0xBEAD, 0xC494, 0xBEAE, 0xC49C, 0xBEAF, 0xC4B8, 0xBEB0, 0xC4BC,
+	0xBEB1, 0xC4E9, 0xBEB2, 0xC4F0, 0xBEB3, 0xC4F1, 0xBEB4, 0xC4F4,
+	0xBEB5, 0xC4F8, 0xBEB6, 0xC4FA, 0xBEB7, 0xC4FF, 0xBEB8, 0xC500,
+	0xBEB9, 0xC501, 0xBEBA, 0xC50C, 0xBEBB, 0xC510, 0xBEBC, 0xC514,
+	0xBEBD, 0xC51C, 0xBEBE, 0xC528, 0xBEBF, 0xC529, 0xBEC0, 0xC52C,
+	0xBEC1, 0xC530, 0xBEC2, 0xC538, 0xBEC3, 0xC539, 0xBEC4, 0xC53B,
+	0xBEC5, 0xC53D, 0xBEC6, 0xC544, 0xBEC7, 0xC545, 0xBEC8, 0xC548,
+	0xBEC9, 0xC549, 0xBECA, 0xC54A, 0xBECB, 0xC54C, 0xBECC, 0xC54D,
+	0xBECD, 0xC54E, 0xBECE, 0xC553, 0xBECF, 0xC554, 0xBED0, 0xC555,
+	0xBED1, 0xC557, 0xBED2, 0xC558, 0xBED3, 0xC559, 0xBED4, 0xC55D,
+	0xBED5, 0xC55E, 0xBED6, 0xC560, 0xBED7, 0xC561, 0xBED8, 0xC564,
+	0xBED9, 0xC568, 0xBEDA, 0xC570, 0xBEDB, 0xC571, 0xBEDC, 0xC573,
+	0xBEDD, 0xC574, 0xBEDE, 0xC575, 0xBEDF, 0xC57C, 0xBEE0, 0xC57D,
+	0xBEE1, 0xC580, 0xBEE2, 0xC584, 0xBEE3, 0xC587, 0xBEE4, 0xC58C,
+	0xBEE5, 0xC58D, 0xBEE6, 0xC58F, 0xBEE7, 0xC591, 0xBEE8, 0xC595,
+	0xBEE9, 0xC597, 0xBEEA, 0xC598, 0xBEEB, 0xC59C, 0xBEEC, 0xC5A0,
+	0xBEED, 0xC5A9, 0xBEEE, 0xC5B4, 0xBEEF, 0xC5B5, 0xBEF0, 0xC5B8,
+	0xBEF1, 0xC5B9, 0xBEF2, 0xC5BB, 0xBEF3, 0xC5BC, 0xBEF4, 0xC5BD,
+	0xBEF5, 0xC5BE, 0xBEF6, 0xC5C4, 0xBEF7, 0xC5C5, 0xBEF8, 0xC5C6,
+	0xBEF9, 0xC5C7, 0xBEFA, 0xC5C8, 0xBEFB, 0xC5C9, 0xBEFC, 0xC5CA,
+	0xBEFD, 0xC5CC, 0xBEFE, 0xC5CE, 0xBF41, 0xD49E, 0xBF42, 0xD49F,
+	0xBF43, 0xD4A0, 0xBF44, 0xD4A1, 0xBF45, 0xD4A2, 0xBF46, 0xD4A3,
+	0xBF47, 0xD4A4, 0xBF48, 0xD4A5, 0xBF49, 0xD4A6, 0xBF4A, 0xD4A7,
+	0xBF4B, 0xD4A8, 0xBF4C, 0xD4AA, 0xBF4D, 0xD4AB, 0xBF4E, 0xD4AC,
+	0xBF4F, 0xD4AD, 0xBF50, 0xD4AE, 0xBF51, 0xD4AF, 0xBF52, 0xD4B0,
+	0xBF53, 0xD4B1, 0xBF54, 0xD4B2, 0xBF55, 0xD4B3, 0xBF56, 0xD4B4,
+	0xBF57, 0xD4B5, 0xBF58, 0xD4B6, 0xBF59, 0xD4B7, 0xBF5A, 0xD4B8,
+	0xBF61, 0xD4B9, 0xBF62, 0xD4BA, 0xBF63, 0xD4BB, 0xBF64, 0xD4BC,
+	0xBF65, 0xD4BD, 0xBF66, 0xD4BE, 0xBF67, 0xD4BF, 0xBF68, 0xD4C0,
+	0xBF69, 0xD4C1, 0xBF6A, 0xD4C2, 0xBF6B, 0xD4C3, 0xBF6C, 0xD4C4,
+	0xBF6D, 0xD4C5, 0xBF6E, 0xD4C6, 0xBF6F, 0xD4C7, 0xBF70, 0xD4C8,
+	0xBF71, 0xD4C9, 0xBF72, 0xD4CA, 0xBF73, 0xD4CB, 0xBF74, 0xD4CD,
+	0xBF75, 0xD4CE, 0xBF76, 0xD4CF, 0xBF77, 0xD4D1, 0xBF78, 0xD4D2,
+	0xBF79, 0xD4D3, 0xBF7A, 0xD4D5, 0xBF81, 0xD4D6, 0xBF82, 0xD4D7,
+	0xBF83, 0xD4D8, 0xBF84, 0xD4D9, 0xBF85, 0xD4DA, 0xBF86, 0xD4DB,
+	0xBF87, 0xD4DD, 0xBF88, 0xD4DE, 0xBF89, 0xD4E0, 0xBF8A, 0xD4E1,
+	0xBF8B, 0xD4E2, 0xBF8C, 0xD4E3, 0xBF8D, 0xD4E4, 0xBF8E, 0xD4E5,
+	0xBF8F, 0xD4E6, 0xBF90, 0xD4E7, 0xBF91, 0xD4E9, 0xBF92, 0xD4EA,
+	0xBF93, 0xD4EB, 0xBF94, 0xD4ED, 0xBF95, 0xD4EE, 0xBF96, 0xD4EF,
+	0xBF97, 0xD4F1, 0xBF98, 0xD4F2, 0xBF99, 0xD4F3, 0xBF9A, 0xD4F4,
+	0xBF9B, 0xD4F5, 0xBF9C, 0xD4F6, 0xBF9D, 0xD4F7, 0xBF9E, 0xD4F9,
+	0xBF9F, 0xD4FA, 0xBFA0, 0xD4FC, 0xBFA1, 0xC5D0, 0xBFA2, 0xC5D1,
+	0xBFA3, 0xC5D4, 0xBFA4, 0xC5D8, 0xBFA5, 0xC5E0, 0xBFA6, 0xC5E1,
+	0xBFA7, 0xC5E3, 0xBFA8, 0xC5E5, 0xBFA9, 0xC5EC, 0xBFAA, 0xC5ED,
+	0xBFAB, 0xC5EE, 0xBFAC, 0xC5F0, 0xBFAD, 0xC5F4, 0xBFAE, 0xC5F6,
+	0xBFAF, 0xC5F7, 0xBFB0, 0xC5FC, 0xBFB1, 0xC5FD, 0xBFB2, 0xC5FE,
+	0xBFB3, 0xC5FF, 0xBFB4, 0xC600, 0xBFB5, 0xC601, 0xBFB6, 0xC605,
+	0xBFB7, 0xC606, 0xBFB8, 0xC607, 0xBFB9, 0xC608, 0xBFBA, 0xC60C,
+	0xBFBB, 0xC610, 0xBFBC, 0xC618, 0xBFBD, 0xC619, 0xBFBE, 0xC61B,
+	0xBFBF, 0xC61C, 0xBFC0, 0xC624, 0xBFC1, 0xC625, 0xBFC2, 0xC628,
+	0xBFC3, 0xC62C, 0xBFC4, 0xC62D, 0xBFC5, 0xC62E, 0xBFC6, 0xC630,
+	0xBFC7, 0xC633, 0xBFC8, 0xC634, 0xBFC9, 0xC635, 0xBFCA, 0xC637,
+	0xBFCB, 0xC639, 0xBFCC, 0xC63B, 0xBFCD, 0xC640, 0xBFCE, 0xC641,
+	0xBFCF, 0xC644, 0xBFD0, 0xC648, 0xBFD1, 0xC650, 0xBFD2, 0xC651,
+	0xBFD3, 0xC653, 0xBFD4, 0xC654, 0xBFD5, 0xC655, 0xBFD6, 0xC65C,
+	0xBFD7, 0xC65D, 0xBFD8, 0xC660, 0xBFD9, 0xC66C, 0xBFDA, 0xC66F,
+	0xBFDB, 0xC671, 0xBFDC, 0xC678, 0xBFDD, 0xC679, 0xBFDE, 0xC67C,
+	0xBFDF, 0xC680, 0xBFE0, 0xC688, 0xBFE1, 0xC689, 0xBFE2, 0xC68B,
+	0xBFE3, 0xC68D, 0xBFE4, 0xC694, 0xBFE5, 0xC695, 0xBFE6, 0xC698,
+	0xBFE7, 0xC69C, 0xBFE8, 0xC6A4, 0xBFE9, 0xC6A5, 0xBFEA, 0xC6A7,
+	0xBFEB, 0xC6A9, 0xBFEC, 0xC6B0, 0xBFED, 0xC6B1, 0xBFEE, 0xC6B4,
+	0xBFEF, 0xC6B8, 0xBFF0, 0xC6B9, 0xBFF1, 0xC6BA, 0xBFF2, 0xC6C0,
+	0xBFF3, 0xC6C1, 0xBFF4, 0xC6C3, 0xBFF5, 0xC6C5, 0xBFF6, 0xC6CC,
+	0xBFF7, 0xC6CD, 0xBFF8, 0xC6D0, 0xBFF9, 0xC6D4, 0xBFFA, 0xC6DC,
+	0xBFFB, 0xC6DD, 0xBFFC, 0xC6E0, 0xBFFD, 0xC6E1, 0xBFFE, 0xC6E8,
+	0xC041, 0xD4FE, 0xC042, 0xD4FF, 0xC043, 0xD500, 0xC044, 0xD501,
+	0xC045, 0xD502, 0xC046, 0xD503, 0xC047, 0xD505, 0xC048, 0xD506,
+	0xC049, 0xD507, 0xC04A, 0xD509, 0xC04B, 0xD50A, 0xC04C, 0xD50B,
+	0xC04D, 0xD50D, 0xC04E, 0xD50E, 0xC04F, 0xD50F, 0xC050, 0xD510,
+	0xC051, 0xD511, 0xC052, 0xD512, 0xC053, 0xD513, 0xC054, 0xD516,
+	0xC055, 0xD518, 0xC056, 0xD519, 0xC057, 0xD51A, 0xC058, 0xD51B,
+	0xC059, 0xD51C, 0xC05A, 0xD51D, 0xC061, 0xD51E, 0xC062, 0xD51F,
+	0xC063, 0xD520, 0xC064, 0xD521, 0xC065, 0xD522, 0xC066, 0xD523,
+	0xC067, 0xD524, 0xC068, 0xD525, 0xC069, 0xD526, 0xC06A, 0xD527,
+	0xC06B, 0xD528, 0xC06C, 0xD529, 0xC06D, 0xD52A, 0xC06E, 0xD52B,
+	0xC06F, 0xD52C, 0xC070, 0xD52D, 0xC071, 0xD52E, 0xC072, 0xD52F,
+	0xC073, 0xD530, 0xC074, 0xD531, 0xC075, 0xD532, 0xC076, 0xD533,
+	0xC077, 0xD534, 0xC078, 0xD535, 0xC079, 0xD536, 0xC07A, 0xD537,
+	0xC081, 0xD538, 0xC082, 0xD539, 0xC083, 0xD53A, 0xC084, 0xD53B,
+	0xC085, 0xD53E, 0xC086, 0xD53F, 0xC087, 0xD541, 0xC088, 0xD542,
+	0xC089, 0xD543, 0xC08A, 0xD545, 0xC08B, 0xD546, 0xC08C, 0xD547,
+	0xC08D, 0xD548, 0xC08E, 0xD549, 0xC08F, 0xD54A, 0xC090, 0xD54B,
+	0xC091, 0xD54E, 0xC092, 0xD550, 0xC093, 0xD552, 0xC094, 0xD553,
+	0xC095, 0xD554, 0xC096, 0xD555, 0xC097, 0xD556, 0xC098, 0xD557,
+	0xC099, 0xD55A, 0xC09A, 0xD55B, 0xC09B, 0xD55D, 0xC09C, 0xD55E,
+	0xC09D, 0xD55F, 0xC09E, 0xD561, 0xC09F, 0xD562, 0xC0A0, 0xD563,
+	0xC0A1, 0xC6E9, 0xC0A2, 0xC6EC, 0xC0A3, 0xC6F0, 0xC0A4, 0xC6F8,
+	0xC0A5, 0xC6F9, 0xC0A6, 0xC6FD, 0xC0A7, 0xC704, 0xC0A8, 0xC705,
+	0xC0A9, 0xC708, 0xC0AA, 0xC70C, 0xC0AB, 0xC714, 0xC0AC, 0xC715,
+	0xC0AD, 0xC717, 0xC0AE, 0xC719, 0xC0AF, 0xC720, 0xC0B0, 0xC721,
+	0xC0B1, 0xC724, 0xC0B2, 0xC728, 0xC0B3, 0xC730, 0xC0B4, 0xC731,
+	0xC0B5, 0xC733, 0xC0B6, 0xC735, 0xC0B7, 0xC737, 0xC0B8, 0xC73C,
+	0xC0B9, 0xC73D, 0xC0BA, 0xC740, 0xC0BB, 0xC744, 0xC0BC, 0xC74A,
+	0xC0BD, 0xC74C, 0xC0BE, 0xC74D, 0xC0BF, 0xC74F, 0xC0C0, 0xC751,
+	0xC0C1, 0xC752, 0xC0C2, 0xC753, 0xC0C3, 0xC754, 0xC0C4, 0xC755,
+	0xC0C5, 0xC756, 0xC0C6, 0xC757, 0xC0C7, 0xC758, 0xC0C8, 0xC75C,
+	0xC0C9, 0xC760, 0xC0CA, 0xC768, 0xC0CB, 0xC76B, 0xC0CC, 0xC774,
+	0xC0CD, 0xC775, 0xC0CE, 0xC778, 0xC0CF, 0xC77C, 0xC0D0, 0xC77D,
+	0xC0D1, 0xC77E, 0xC0D2, 0xC783, 0xC0D3, 0xC784, 0xC0D4, 0xC785,
+	0xC0D5, 0xC787, 0xC0D6, 0xC788, 0xC0D7, 0xC789, 0xC0D8, 0xC78A,
+	0xC0D9, 0xC78E, 0xC0DA, 0xC790, 0xC0DB, 0xC791, 0xC0DC, 0xC794,
+	0xC0DD, 0xC796, 0xC0DE, 0xC797, 0xC0DF, 0xC798, 0xC0E0, 0xC79A,
+	0xC0E1, 0xC7A0, 0xC0E2, 0xC7A1, 0xC0E3, 0xC7A3, 0xC0E4, 0xC7A4,
+	0xC0E5, 0xC7A5, 0xC0E6, 0xC7A6, 0xC0E7, 0xC7AC, 0xC0E8, 0xC7AD,
+	0xC0E9, 0xC7B0, 0xC0EA, 0xC7B4, 0xC0EB, 0xC7BC, 0xC0EC, 0xC7BD,
+	0xC0ED, 0xC7BF, 0xC0EE, 0xC7C0, 0xC0EF, 0xC7C1, 0xC0F0, 0xC7C8,
+	0xC0F1, 0xC7C9, 0xC0F2, 0xC7CC, 0xC0F3, 0xC7CE, 0xC0F4, 0xC7D0,
+	0xC0F5, 0xC7D8, 0xC0F6, 0xC7DD, 0xC0F7, 0xC7E4, 0xC0F8, 0xC7E8,
+	0xC0F9, 0xC7EC, 0xC0FA, 0xC800, 0xC0FB, 0xC801, 0xC0FC, 0xC804,
+	0xC0FD, 0xC808, 0xC0FE, 0xC80A, 0xC141, 0xD564, 0xC142, 0xD566,
+	0xC143, 0xD567, 0xC144, 0xD56A, 0xC145, 0xD56C, 0xC146, 0xD56E,
+	0xC147, 0xD56F, 0xC148, 0xD570, 0xC149, 0xD571, 0xC14A, 0xD572,
+	0xC14B, 0xD573, 0xC14C, 0xD576, 0xC14D, 0xD577, 0xC14E, 0xD579,
+	0xC14F, 0xD57A, 0xC150, 0xD57B, 0xC151, 0xD57D, 0xC152, 0xD57E,
+	0xC153, 0xD57F, 0xC154, 0xD580, 0xC155, 0xD581, 0xC156, 0xD582,
+	0xC157, 0xD583, 0xC158, 0xD586, 0xC159, 0xD58A, 0xC15A, 0xD58B,
+	0xC161, 0xD58C, 0xC162, 0xD58D, 0xC163, 0xD58E, 0xC164, 0xD58F,
+	0xC165, 0xD591, 0xC166, 0xD592, 0xC167, 0xD593, 0xC168, 0xD594,
+	0xC169, 0xD595, 0xC16A, 0xD596, 0xC16B, 0xD597, 0xC16C, 0xD598,
+	0xC16D, 0xD599, 0xC16E, 0xD59A, 0xC16F, 0xD59B, 0xC170, 0xD59C,
+	0xC171, 0xD59D, 0xC172, 0xD59E, 0xC173, 0xD59F, 0xC174, 0xD5A0,
+	0xC175, 0xD5A1, 0xC176, 0xD5A2, 0xC177, 0xD5A3, 0xC178, 0xD5A4,
+	0xC179, 0xD5A6, 0xC17A, 0xD5A7, 0xC181, 0xD5A8, 0xC182, 0xD5A9,
+	0xC183, 0xD5AA, 0xC184, 0xD5AB, 0xC185, 0xD5AC, 0xC186, 0xD5AD,
+	0xC187, 0xD5AE, 0xC188, 0xD5AF, 0xC189, 0xD5B0, 0xC18A, 0xD5B1,
+	0xC18B, 0xD5B2, 0xC18C, 0xD5B3, 0xC18D, 0xD5B4, 0xC18E, 0xD5B5,
+	0xC18F, 0xD5B6, 0xC190, 0xD5B7, 0xC191, 0xD5B8, 0xC192, 0xD5B9,
+	0xC193, 0xD5BA, 0xC194, 0xD5BB, 0xC195, 0xD5BC, 0xC196, 0xD5BD,
+	0xC197, 0xD5BE, 0xC198, 0xD5BF, 0xC199, 0xD5C0, 0xC19A, 0xD5C1,
+	0xC19B, 0xD5C2, 0xC19C, 0xD5C3, 0xC19D, 0xD5C4, 0xC19E, 0xD5C5,
+	0xC19F, 0xD5C6, 0xC1A0, 0xD5C7, 0xC1A1, 0xC810, 0xC1A2, 0xC811,
+	0xC1A3, 0xC813, 0xC1A4, 0xC815, 0xC1A5, 0xC816, 0xC1A6, 0xC81C,
+	0xC1A7, 0xC81D, 0xC1A8, 0xC820, 0xC1A9, 0xC824, 0xC1AA, 0xC82C,
+	0xC1AB, 0xC82D, 0xC1AC, 0xC82F, 0xC1AD, 0xC831, 0xC1AE, 0xC838,
+	0xC1AF, 0xC83C, 0xC1B0, 0xC840, 0xC1B1, 0xC848, 0xC1B2, 0xC849,
+	0xC1B3, 0xC84C, 0xC1B4, 0xC84D, 0xC1B5, 0xC854, 0xC1B6, 0xC870,
+	0xC1B7, 0xC871, 0xC1B8, 0xC874, 0xC1B9, 0xC878, 0xC1BA, 0xC87A,
+	0xC1BB, 0xC880, 0xC1BC, 0xC881, 0xC1BD, 0xC883, 0xC1BE, 0xC885,
+	0xC1BF, 0xC886, 0xC1C0, 0xC887, 0xC1C1, 0xC88B, 0xC1C2, 0xC88C,
+	0xC1C3, 0xC88D, 0xC1C4, 0xC894, 0xC1C5, 0xC89D, 0xC1C6, 0xC89F,
+	0xC1C7, 0xC8A1, 0xC1C8, 0xC8A8, 0xC1C9, 0xC8BC, 0xC1CA, 0xC8BD,
+	0xC1CB, 0xC8C4, 0xC1CC, 0xC8C8, 0xC1CD, 0xC8CC, 0xC1CE, 0xC8D4,
+	0xC1CF, 0xC8D5, 0xC1D0, 0xC8D7, 0xC1D1, 0xC8D9, 0xC1D2, 0xC8E0,
+	0xC1D3, 0xC8E1, 0xC1D4, 0xC8E4, 0xC1D5, 0xC8F5, 0xC1D6, 0xC8FC,
+	0xC1D7, 0xC8FD, 0xC1D8, 0xC900, 0xC1D9, 0xC904, 0xC1DA, 0xC905,
+	0xC1DB, 0xC906, 0xC1DC, 0xC90C, 0xC1DD, 0xC90D, 0xC1DE, 0xC90F,
+	0xC1DF, 0xC911, 0xC1E0, 0xC918, 0xC1E1, 0xC92C, 0xC1E2, 0xC934,
+	0xC1E3, 0xC950, 0xC1E4, 0xC951, 0xC1E5, 0xC954, 0xC1E6, 0xC958,
+	0xC1E7, 0xC960, 0xC1E8, 0xC961, 0xC1E9, 0xC963, 0xC1EA, 0xC96C,
+	0xC1EB, 0xC970, 0xC1EC, 0xC974, 0xC1ED, 0xC97C, 0xC1EE, 0xC988,
+	0xC1EF, 0xC989, 0xC1F0, 0xC98C, 0xC1F1, 0xC990, 0xC1F2, 0xC998,
+	0xC1F3, 0xC999, 0xC1F4, 0xC99B, 0xC1F5, 0xC99D, 0xC1F6, 0xC9C0,
+	0xC1F7, 0xC9C1, 0xC1F8, 0xC9C4, 0xC1F9, 0xC9C7, 0xC1FA, 0xC9C8,
+	0xC1FB, 0xC9CA, 0xC1FC, 0xC9D0, 0xC1FD, 0xC9D1, 0xC1FE, 0xC9D3,
+	0xC241, 0xD5CA, 0xC242, 0xD5CB, 0xC243, 0xD5CD, 0xC244, 0xD5CE,
+	0xC245, 0xD5CF, 0xC246, 0xD5D1, 0xC247, 0xD5D3, 0xC248, 0xD5D4,
+	0xC249, 0xD5D5, 0xC24A, 0xD5D6, 0xC24B, 0xD5D7, 0xC24C, 0xD5DA,
+	0xC24D, 0xD5DC, 0xC24E, 0xD5DE, 0xC24F, 0xD5DF, 0xC250, 0xD5E0,
+	0xC251, 0xD5E1, 0xC252, 0xD5E2, 0xC253, 0xD5E3, 0xC254, 0xD5E6,
+	0xC255, 0xD5E7, 0xC256, 0xD5E9, 0xC257, 0xD5EA, 0xC258, 0xD5EB,
+	0xC259, 0xD5ED, 0xC25A, 0xD5EE, 0xC261, 0xD5EF, 0xC262, 0xD5F0,
+	0xC263, 0xD5F1, 0xC264, 0xD5F2, 0xC265, 0xD5F3, 0xC266, 0xD5F6,
+	0xC267, 0xD5F8, 0xC268, 0xD5FA, 0xC269, 0xD5FB, 0xC26A, 0xD5FC,
+	0xC26B, 0xD5FD, 0xC26C, 0xD5FE, 0xC26D, 0xD5FF, 0xC26E, 0xD602,
+	0xC26F, 0xD603, 0xC270, 0xD605, 0xC271, 0xD606, 0xC272, 0xD607,
+	0xC273, 0xD609, 0xC274, 0xD60A, 0xC275, 0xD60B, 0xC276, 0xD60C,
+	0xC277, 0xD60D, 0xC278, 0xD60E, 0xC279, 0xD60F, 0xC27A, 0xD612,
+	0xC281, 0xD616, 0xC282, 0xD617, 0xC283, 0xD618, 0xC284, 0xD619,
+	0xC285, 0xD61A, 0xC286, 0xD61B, 0xC287, 0xD61D, 0xC288, 0xD61E,
+	0xC289, 0xD61F, 0xC28A, 0xD621, 0xC28B, 0xD622, 0xC28C, 0xD623,
+	0xC28D, 0xD625, 0xC28E, 0xD626, 0xC28F, 0xD627, 0xC290, 0xD628,
+	0xC291, 0xD629, 0xC292, 0xD62A, 0xC293, 0xD62B, 0xC294, 0xD62C,
+	0xC295, 0xD62E, 0xC296, 0xD62F, 0xC297, 0xD630, 0xC298, 0xD631,
+	0xC299, 0xD632, 0xC29A, 0xD633, 0xC29B, 0xD634, 0xC29C, 0xD635,
+	0xC29D, 0xD636, 0xC29E, 0xD637, 0xC29F, 0xD63A, 0xC2A0, 0xD63B,
+	0xC2A1, 0xC9D5, 0xC2A2, 0xC9D6, 0xC2A3, 0xC9D9, 0xC2A4, 0xC9DA,
+	0xC2A5, 0xC9DC, 0xC2A6, 0xC9DD, 0xC2A7, 0xC9E0, 0xC2A8, 0xC9E2,
+	0xC2A9, 0xC9E4, 0xC2AA, 0xC9E7, 0xC2AB, 0xC9EC, 0xC2AC, 0xC9ED,
+	0xC2AD, 0xC9EF, 0xC2AE, 0xC9F0, 0xC2AF, 0xC9F1, 0xC2B0, 0xC9F8,
+	0xC2B1, 0xC9F9, 0xC2B2, 0xC9FC, 0xC2B3, 0xCA00, 0xC2B4, 0xCA08,
+	0xC2B5, 0xCA09, 0xC2B6, 0xCA0B, 0xC2B7, 0xCA0C, 0xC2B8, 0xCA0D,
+	0xC2B9, 0xCA14, 0xC2BA, 0xCA18, 0xC2BB, 0xCA29, 0xC2BC, 0xCA4C,
+	0xC2BD, 0xCA4D, 0xC2BE, 0xCA50, 0xC2BF, 0xCA54, 0xC2C0, 0xCA5C,
+	0xC2C1, 0xCA5D, 0xC2C2, 0xCA5F, 0xC2C3, 0xCA60, 0xC2C4, 0xCA61,
+	0xC2C5, 0xCA68, 0xC2C6, 0xCA7D, 0xC2C7, 0xCA84, 0xC2C8, 0xCA98,
+	0xC2C9, 0xCABC, 0xC2CA, 0xCABD, 0xC2CB, 0xCAC0, 0xC2CC, 0xCAC4,
+	0xC2CD, 0xCACC, 0xC2CE, 0xCACD, 0xC2CF, 0xCACF, 0xC2D0, 0xCAD1,
+	0xC2D1, 0xCAD3, 0xC2D2, 0xCAD8, 0xC2D3, 0xCAD9, 0xC2D4, 0xCAE0,
+	0xC2D5, 0xCAEC, 0xC2D6, 0xCAF4, 0xC2D7, 0xCB08, 0xC2D8, 0xCB10,
+	0xC2D9, 0xCB14, 0xC2DA, 0xCB18, 0xC2DB, 0xCB20, 0xC2DC, 0xCB21,
+	0xC2DD, 0xCB41, 0xC2DE, 0xCB48, 0xC2DF, 0xCB49, 0xC2E0, 0xCB4C,
+	0xC2E1, 0xCB50, 0xC2E2, 0xCB58, 0xC2E3, 0xCB59, 0xC2E4, 0xCB5D,
+	0xC2E5, 0xCB64, 0xC2E6, 0xCB78, 0xC2E7, 0xCB79, 0xC2E8, 0xCB9C,
+	0xC2E9, 0xCBB8, 0xC2EA, 0xCBD4, 0xC2EB, 0xCBE4, 0xC2EC, 0xCBE7,
+	0xC2ED, 0xCBE9, 0xC2EE, 0xCC0C, 0xC2EF, 0xCC0D, 0xC2F0, 0xCC10,
+	0xC2F1, 0xCC14, 0xC2F2, 0xCC1C, 0xC2F3, 0xCC1D, 0xC2F4, 0xCC21,
+	0xC2F5, 0xCC22, 0xC2F6, 0xCC27, 0xC2F7, 0xCC28, 0xC2F8, 0xCC29,
+	0xC2F9, 0xCC2C, 0xC2FA, 0xCC2E, 0xC2FB, 0xCC30, 0xC2FC, 0xCC38,
+	0xC2FD, 0xCC39, 0xC2FE, 0xCC3B, 0xC341, 0xD63D, 0xC342, 0xD63E,
+	0xC343, 0xD63F, 0xC344, 0xD641, 0xC345, 0xD642, 0xC346, 0xD643,
+	0xC347, 0xD644, 0xC348, 0xD646, 0xC349, 0xD647, 0xC34A, 0xD64A,
+	0xC34B, 0xD64C, 0xC34C, 0xD64E, 0xC34D, 0xD64F, 0xC34E, 0xD650,
+	0xC34F, 0xD652, 0xC350, 0xD653, 0xC351, 0xD656, 0xC352, 0xD657,
+	0xC353, 0xD659, 0xC354, 0xD65A, 0xC355, 0xD65B, 0xC356, 0xD65D,
+	0xC357, 0xD65E, 0xC358, 0xD65F, 0xC359, 0xD660, 0xC35A, 0xD661,
+	0xC361, 0xD662, 0xC362, 0xD663, 0xC363, 0xD664, 0xC364, 0xD665,
+	0xC365, 0xD666, 0xC366, 0xD668, 0xC367, 0xD66A, 0xC368, 0xD66B,
+	0xC369, 0xD66C, 0xC36A, 0xD66D, 0xC36B, 0xD66E, 0xC36C, 0xD66F,
+	0xC36D, 0xD672, 0xC36E, 0xD673, 0xC36F, 0xD675, 0xC370, 0xD676,
+	0xC371, 0xD677, 0xC372, 0xD678, 0xC373, 0xD679, 0xC374, 0xD67A,
+	0xC375, 0xD67B, 0xC376, 0xD67C, 0xC377, 0xD67D, 0xC378, 0xD67E,
+	0xC379, 0xD67F, 0xC37A, 0xD680, 0xC381, 0xD681, 0xC382, 0xD682,
+	0xC383, 0xD684, 0xC384, 0xD686, 0xC385, 0xD687, 0xC386, 0xD688,
+	0xC387, 0xD689, 0xC388, 0xD68A, 0xC389, 0xD68B, 0xC38A, 0xD68E,
+	0xC38B, 0xD68F, 0xC38C, 0xD691, 0xC38D, 0xD692, 0xC38E, 0xD693,
+	0xC38F, 0xD695, 0xC390, 0xD696, 0xC391, 0xD697, 0xC392, 0xD698,
+	0xC393, 0xD699, 0xC394, 0xD69A, 0xC395, 0xD69B, 0xC396, 0xD69C,
+	0xC397, 0xD69E, 0xC398, 0xD6A0, 0xC399, 0xD6A2, 0xC39A, 0xD6A3,
+	0xC39B, 0xD6A4, 0xC39C, 0xD6A5, 0xC39D, 0xD6A6, 0xC39E, 0xD6A7,
+	0xC39F, 0xD6A9, 0xC3A0, 0xD6AA, 0xC3A1, 0xCC3C, 0xC3A2, 0xCC3D,
+	0xC3A3, 0xCC3E, 0xC3A4, 0xCC44, 0xC3A5, 0xCC45, 0xC3A6, 0xCC48,
+	0xC3A7, 0xCC4C, 0xC3A8, 0xCC54, 0xC3A9, 0xCC55, 0xC3AA, 0xCC57,
+	0xC3AB, 0xCC58, 0xC3AC, 0xCC59, 0xC3AD, 0xCC60, 0xC3AE, 0xCC64,
+	0xC3AF, 0xCC66, 0xC3B0, 0xCC68, 0xC3B1, 0xCC70, 0xC3B2, 0xCC75,
+	0xC3B3, 0xCC98, 0xC3B4, 0xCC99, 0xC3B5, 0xCC9C, 0xC3B6, 0xCCA0,
+	0xC3B7, 0xCCA8, 0xC3B8, 0xCCA9, 0xC3B9, 0xCCAB, 0xC3BA, 0xCCAC,
+	0xC3BB, 0xCCAD, 0xC3BC, 0xCCB4, 0xC3BD, 0xCCB5, 0xC3BE, 0xCCB8,
+	0xC3BF, 0xCCBC, 0xC3C0, 0xCCC4, 0xC3C1, 0xCCC5, 0xC3C2, 0xCCC7,
+	0xC3C3, 0xCCC9, 0xC3C4, 0xCCD0, 0xC3C5, 0xCCD4, 0xC3C6, 0xCCE4,
+	0xC3C7, 0xCCEC, 0xC3C8, 0xCCF0, 0xC3C9, 0xCD01, 0xC3CA, 0xCD08,
+	0xC3CB, 0xCD09, 0xC3CC, 0xCD0C, 0xC3CD, 0xCD10, 0xC3CE, 0xCD18,
+	0xC3CF, 0xCD19, 0xC3D0, 0xCD1B, 0xC3D1, 0xCD1D, 0xC3D2, 0xCD24,
+	0xC3D3, 0xCD28, 0xC3D4, 0xCD2C, 0xC3D5, 0xCD39, 0xC3D6, 0xCD5C,
+	0xC3D7, 0xCD60, 0xC3D8, 0xCD64, 0xC3D9, 0xCD6C, 0xC3DA, 0xCD6D,
+	0xC3DB, 0xCD6F, 0xC3DC, 0xCD71, 0xC3DD, 0xCD78, 0xC3DE, 0xCD88,
+	0xC3DF, 0xCD94, 0xC3E0, 0xCD95, 0xC3E1, 0xCD98, 0xC3E2, 0xCD9C,
+	0xC3E3, 0xCDA4, 0xC3E4, 0xCDA5, 0xC3E5, 0xCDA7, 0xC3E6, 0xCDA9,
+	0xC3E7, 0xCDB0, 0xC3E8, 0xCDC4, 0xC3E9, 0xCDCC, 0xC3EA, 0xCDD0,
+	0xC3EB, 0xCDE8, 0xC3EC, 0xCDEC, 0xC3ED, 0xCDF0, 0xC3EE, 0xCDF8,
+	0xC3EF, 0xCDF9, 0xC3F0, 0xCDFB, 0xC3F1, 0xCDFD, 0xC3F2, 0xCE04,
+	0xC3F3, 0xCE08, 0xC3F4, 0xCE0C, 0xC3F5, 0xCE14, 0xC3F6, 0xCE19,
+	0xC3F7, 0xCE20, 0xC3F8, 0xCE21, 0xC3F9, 0xCE24, 0xC3FA, 0xCE28,
+	0xC3FB, 0xCE30, 0xC3FC, 0xCE31, 0xC3FD, 0xCE33, 0xC3FE, 0xCE35,
+	0xC441, 0xD6AB, 0xC442, 0xD6AD, 0xC443, 0xD6AE, 0xC444, 0xD6AF,
+	0xC445, 0xD6B1, 0xC446, 0xD6B2, 0xC447, 0xD6B3, 0xC448, 0xD6B4,
+	0xC449, 0xD6B5, 0xC44A, 0xD6B6, 0xC44B, 0xD6B7, 0xC44C, 0xD6B8,
+	0xC44D, 0xD6BA, 0xC44E, 0xD6BC, 0xC44F, 0xD6BD, 0xC450, 0xD6BE,
+	0xC451, 0xD6BF, 0xC452, 0xD6C0, 0xC453, 0xD6C1, 0xC454, 0xD6C2,
+	0xC455, 0xD6C3, 0xC456, 0xD6C6, 0xC457, 0xD6C7, 0xC458, 0xD6C9,
+	0xC459, 0xD6CA, 0xC45A, 0xD6CB, 0xC461, 0xD6CD, 0xC462, 0xD6CE,
+	0xC463, 0xD6CF, 0xC464, 0xD6D0, 0xC465, 0xD6D2, 0xC466, 0xD6D3,
+	0xC467, 0xD6D5, 0xC468, 0xD6D6, 0xC469, 0xD6D8, 0xC46A, 0xD6DA,
+	0xC46B, 0xD6DB, 0xC46C, 0xD6DC, 0xC46D, 0xD6DD, 0xC46E, 0xD6DE,
+	0xC46F, 0xD6DF, 0xC470, 0xD6E1, 0xC471, 0xD6E2, 0xC472, 0xD6E3,
+	0xC473, 0xD6E5, 0xC474, 0xD6E6, 0xC475, 0xD6E7, 0xC476, 0xD6E9,
+	0xC477, 0xD6EA, 0xC478, 0xD6EB, 0xC479, 0xD6EC, 0xC47A, 0xD6ED,
+	0xC481, 0xD6EE, 0xC482, 0xD6EF, 0xC483, 0xD6F1, 0xC484, 0xD6F2,
+	0xC485, 0xD6F3, 0xC486, 0xD6F4, 0xC487, 0xD6F6, 0xC488, 0xD6F7,
+	0xC489, 0xD6F8, 0xC48A, 0xD6F9, 0xC48B, 0xD6FA, 0xC48C, 0xD6FB,
+	0xC48D, 0xD6FE, 0xC48E, 0xD6FF, 0xC48F, 0xD701, 0xC490, 0xD702,
+	0xC491, 0xD703, 0xC492, 0xD705, 0xC493, 0xD706, 0xC494, 0xD707,
+	0xC495, 0xD708, 0xC496, 0xD709, 0xC497, 0xD70A, 0xC498, 0xD70B,
+	0xC499, 0xD70C, 0xC49A, 0xD70D, 0xC49B, 0xD70E, 0xC49C, 0xD70F,
+	0xC49D, 0xD710, 0xC49E, 0xD712, 0xC49F, 0xD713, 0xC4A0, 0xD714,
+	0xC4A1, 0xCE58, 0xC4A2, 0xCE59, 0xC4A3, 0xCE5C, 0xC4A4, 0xCE5F,
+	0xC4A5, 0xCE60, 0xC4A6, 0xCE61, 0xC4A7, 0xCE68, 0xC4A8, 0xCE69,
+	0xC4A9, 0xCE6B, 0xC4AA, 0xCE6D, 0xC4AB, 0xCE74, 0xC4AC, 0xCE75,
+	0xC4AD, 0xCE78, 0xC4AE, 0xCE7C, 0xC4AF, 0xCE84, 0xC4B0, 0xCE85,
+	0xC4B1, 0xCE87, 0xC4B2, 0xCE89, 0xC4B3, 0xCE90, 0xC4B4, 0xCE91,
+	0xC4B5, 0xCE94, 0xC4B6, 0xCE98, 0xC4B7, 0xCEA0, 0xC4B8, 0xCEA1,
+	0xC4B9, 0xCEA3, 0xC4BA, 0xCEA4, 0xC4BB, 0xCEA5, 0xC4BC, 0xCEAC,
+	0xC4BD, 0xCEAD, 0xC4BE, 0xCEC1, 0xC4BF, 0xCEE4, 0xC4C0, 0xCEE5,
+	0xC4C1, 0xCEE8, 0xC4C2, 0xCEEB, 0xC4C3, 0xCEEC, 0xC4C4, 0xCEF4,
+	0xC4C5, 0xCEF5, 0xC4C6, 0xCEF7, 0xC4C7, 0xCEF8, 0xC4C8, 0xCEF9,
+	0xC4C9, 0xCF00, 0xC4CA, 0xCF01, 0xC4CB, 0xCF04, 0xC4CC, 0xCF08,
+	0xC4CD, 0xCF10, 0xC4CE, 0xCF11, 0xC4CF, 0xCF13, 0xC4D0, 0xCF15,
+	0xC4D1, 0xCF1C, 0xC4D2, 0xCF20, 0xC4D3, 0xCF24, 0xC4D4, 0xCF2C,
+	0xC4D5, 0xCF2D, 0xC4D6, 0xCF2F, 0xC4D7, 0xCF30, 0xC4D8, 0xCF31,
+	0xC4D9, 0xCF38, 0xC4DA, 0xCF54, 0xC4DB, 0xCF55, 0xC4DC, 0xCF58,
+	0xC4DD, 0xCF5C, 0xC4DE, 0xCF64, 0xC4DF, 0xCF65, 0xC4E0, 0xCF67,
+	0xC4E1, 0xCF69, 0xC4E2, 0xCF70, 0xC4E3, 0xCF71, 0xC4E4, 0xCF74,
+	0xC4E5, 0xCF78, 0xC4E6, 0xCF80, 0xC4E7, 0xCF85, 0xC4E8, 0xCF8C,
+	0xC4E9, 0xCFA1, 0xC4EA, 0xCFA8, 0xC4EB, 0xCFB0, 0xC4EC, 0xCFC4,
+	0xC4ED, 0xCFE0, 0xC4EE, 0xCFE1, 0xC4EF, 0xCFE4, 0xC4F0, 0xCFE8,
+	0xC4F1, 0xCFF0, 0xC4F2, 0xCFF1, 0xC4F3, 0xCFF3, 0xC4F4, 0xCFF5,
+	0xC4F5, 0xCFFC, 0xC4F6, 0xD000, 0xC4F7, 0xD004, 0xC4F8, 0xD011,
+	0xC4F9, 0xD018, 0xC4FA, 0xD02D, 0xC4FB, 0xD034, 0xC4FC, 0xD035,
+	0xC4FD, 0xD038, 0xC4FE, 0xD03C, 0xC541, 0xD715, 0xC542, 0xD716,
+	0xC543, 0xD717, 0xC544, 0xD71A, 0xC545, 0xD71B, 0xC546, 0xD71D,
+	0xC547, 0xD71E, 0xC548, 0xD71F, 0xC549, 0xD721, 0xC54A, 0xD722,
+	0xC54B, 0xD723, 0xC54C, 0xD724, 0xC54D, 0xD725, 0xC54E, 0xD726,
+	0xC54F, 0xD727, 0xC550, 0xD72A, 0xC551, 0xD72C, 0xC552, 0xD72E,
+	0xC553, 0xD72F, 0xC554, 0xD730, 0xC555, 0xD731, 0xC556, 0xD732,
+	0xC557, 0xD733, 0xC558, 0xD736, 0xC559, 0xD737, 0xC55A, 0xD739,
+	0xC561, 0xD73A, 0xC562, 0xD73B, 0xC563, 0xD73D, 0xC564, 0xD73E,
+	0xC565, 0xD73F, 0xC566, 0xD740, 0xC567, 0xD741, 0xC568, 0xD742,
+	0xC569, 0xD743, 0xC56A, 0xD745, 0xC56B, 0xD746, 0xC56C, 0xD748,
+	0xC56D, 0xD74A, 0xC56E, 0xD74B, 0xC56F, 0xD74C, 0xC570, 0xD74D,
+	0xC571, 0xD74E, 0xC572, 0xD74F, 0xC573, 0xD752, 0xC574, 0xD753,
+	0xC575, 0xD755, 0xC576, 0xD75A, 0xC577, 0xD75B, 0xC578, 0xD75C,
+	0xC579, 0xD75D, 0xC57A, 0xD75E, 0xC581, 0xD75F, 0xC582, 0xD762,
+	0xC583, 0xD764, 0xC584, 0xD766, 0xC585, 0xD767, 0xC586, 0xD768,
+	0xC587, 0xD76A, 0xC588, 0xD76B, 0xC589, 0xD76D, 0xC58A, 0xD76E,
+	0xC58B, 0xD76F, 0xC58C, 0xD771, 0xC58D, 0xD772, 0xC58E, 0xD773,
+	0xC58F, 0xD775, 0xC590, 0xD776, 0xC591, 0xD777, 0xC592, 0xD778,
+	0xC593, 0xD779, 0xC594, 0xD77A, 0xC595, 0xD77B, 0xC596, 0xD77E,
+	0xC597, 0xD77F, 0xC598, 0xD780, 0xC599, 0xD782, 0xC59A, 0xD783,
+	0xC59B, 0xD784, 0xC59C, 0xD785, 0xC59D, 0xD786, 0xC59E, 0xD787,
+	0xC59F, 0xD78A, 0xC5A0, 0xD78B, 0xC5A1, 0xD044, 0xC5A2, 0xD045,
+	0xC5A3, 0xD047, 0xC5A4, 0xD049, 0xC5A5, 0xD050, 0xC5A6, 0xD054,
+	0xC5A7, 0xD058, 0xC5A8, 0xD060, 0xC5A9, 0xD06C, 0xC5AA, 0xD06D,
+	0xC5AB, 0xD070, 0xC5AC, 0xD074, 0xC5AD, 0xD07C, 0xC5AE, 0xD07D,
+	0xC5AF, 0xD081, 0xC5B0, 0xD0A4, 0xC5B1, 0xD0A5, 0xC5B2, 0xD0A8,
+	0xC5B3, 0xD0AC, 0xC5B4, 0xD0B4, 0xC5B5, 0xD0B5, 0xC5B6, 0xD0B7,
+	0xC5B7, 0xD0B9, 0xC5B8, 0xD0C0, 0xC5B9, 0xD0C1, 0xC5BA, 0xD0C4,
+	0xC5BB, 0xD0C8, 0xC5BC, 0xD0C9, 0xC5BD, 0xD0D0, 0xC5BE, 0xD0D1,
+	0xC5BF, 0xD0D3, 0xC5C0, 0xD0D4, 0xC5C1, 0xD0D5, 0xC5C2, 0xD0DC,
+	0xC5C3, 0xD0DD, 0xC5C4, 0xD0E0, 0xC5C5, 0xD0E4, 0xC5C6, 0xD0EC,
+	0xC5C7, 0xD0ED, 0xC5C8, 0xD0EF, 0xC5C9, 0xD0F0, 0xC5CA, 0xD0F1,
+	0xC5CB, 0xD0F8, 0xC5CC, 0xD10D, 0xC5CD, 0xD130, 0xC5CE, 0xD131,
+	0xC5CF, 0xD134, 0xC5D0, 0xD138, 0xC5D1, 0xD13A, 0xC5D2, 0xD140,
+	0xC5D3, 0xD141, 0xC5D4, 0xD143, 0xC5D5, 0xD144, 0xC5D6, 0xD145,
+	0xC5D7, 0xD14C, 0xC5D8, 0xD14D, 0xC5D9, 0xD150, 0xC5DA, 0xD154,
+	0xC5DB, 0xD15C, 0xC5DC, 0xD15D, 0xC5DD, 0xD15F, 0xC5DE, 0xD161,
+	0xC5DF, 0xD168, 0xC5E0, 0xD16C, 0xC5E1, 0xD17C, 0xC5E2, 0xD184,
+	0xC5E3, 0xD188, 0xC5E4, 0xD1A0, 0xC5E5, 0xD1A1, 0xC5E6, 0xD1A4,
+	0xC5E7, 0xD1A8, 0xC5E8, 0xD1B0, 0xC5E9, 0xD1B1, 0xC5EA, 0xD1B3,
+	0xC5EB, 0xD1B5, 0xC5EC, 0xD1BA, 0xC5ED, 0xD1BC, 0xC5EE, 0xD1C0,
+	0xC5EF, 0xD1D8, 0xC5F0, 0xD1F4, 0xC5F1, 0xD1F8, 0xC5F2, 0xD207,
+	0xC5F3, 0xD209, 0xC5F4, 0xD210, 0xC5F5, 0xD22C, 0xC5F6, 0xD22D,
+	0xC5F7, 0xD230, 0xC5F8, 0xD234, 0xC5F9, 0xD23C, 0xC5FA, 0xD23D,
+	0xC5FB, 0xD23F, 0xC5FC, 0xD241, 0xC5FD, 0xD248, 0xC5FE, 0xD25C,
+	0xC641, 0xD78D, 0xC642, 0xD78E, 0xC643, 0xD78F, 0xC644, 0xD791,
+	0xC645, 0xD792, 0xC646, 0xD793, 0xC647, 0xD794, 0xC648, 0xD795,
+	0xC649, 0xD796, 0xC64A, 0xD797, 0xC64B, 0xD79A, 0xC64C, 0xD79C,
+	0xC64D, 0xD79E, 0xC64E, 0xD79F, 0xC64F, 0xD7A0, 0xC650, 0xD7A1,
+	0xC651, 0xD7A2, 0xC652, 0xD7A3, 0xC6A1, 0xD264, 0xC6A2, 0xD280,
+	0xC6A3, 0xD281, 0xC6A4, 0xD284, 0xC6A5, 0xD288, 0xC6A6, 0xD290,
+	0xC6A7, 0xD291, 0xC6A8, 0xD295, 0xC6A9, 0xD29C, 0xC6AA, 0xD2A0,
+	0xC6AB, 0xD2A4, 0xC6AC, 0xD2AC, 0xC6AD, 0xD2B1, 0xC6AE, 0xD2B8,
+	0xC6AF, 0xD2B9, 0xC6B0, 0xD2BC, 0xC6B1, 0xD2BF, 0xC6B2, 0xD2C0,
+	0xC6B3, 0xD2C2, 0xC6B4, 0xD2C8, 0xC6B5, 0xD2C9, 0xC6B6, 0xD2CB,
+	0xC6B7, 0xD2D4, 0xC6B8, 0xD2D8, 0xC6B9, 0xD2DC, 0xC6BA, 0xD2E4,
+	0xC6BB, 0xD2E5, 0xC6BC, 0xD2F0, 0xC6BD, 0xD2F1, 0xC6BE, 0xD2F4,
+	0xC6BF, 0xD2F8, 0xC6C0, 0xD300, 0xC6C1, 0xD301, 0xC6C2, 0xD303,
+	0xC6C3, 0xD305, 0xC6C4, 0xD30C, 0xC6C5, 0xD30D, 0xC6C6, 0xD30E,
+	0xC6C7, 0xD310, 0xC6C8, 0xD314, 0xC6C9, 0xD316, 0xC6CA, 0xD31C,
+	0xC6CB, 0xD31D, 0xC6CC, 0xD31F, 0xC6CD, 0xD320, 0xC6CE, 0xD321,
+	0xC6CF, 0xD325, 0xC6D0, 0xD328, 0xC6D1, 0xD329, 0xC6D2, 0xD32C,
+	0xC6D3, 0xD330, 0xC6D4, 0xD338, 0xC6D5, 0xD339, 0xC6D6, 0xD33B,
+	0xC6D7, 0xD33C, 0xC6D8, 0xD33D, 0xC6D9, 0xD344, 0xC6DA, 0xD345,
+	0xC6DB, 0xD37C, 0xC6DC, 0xD37D, 0xC6DD, 0xD380, 0xC6DE, 0xD384,
+	0xC6DF, 0xD38C, 0xC6E0, 0xD38D, 0xC6E1, 0xD38F, 0xC6E2, 0xD390,
+	0xC6E3, 0xD391, 0xC6E4, 0xD398, 0xC6E5, 0xD399, 0xC6E6, 0xD39C,
+	0xC6E7, 0xD3A0, 0xC6E8, 0xD3A8, 0xC6E9, 0xD3A9, 0xC6EA, 0xD3AB,
+	0xC6EB, 0xD3AD, 0xC6EC, 0xD3B4, 0xC6ED, 0xD3B8, 0xC6EE, 0xD3BC,
+	0xC6EF, 0xD3C4, 0xC6F0, 0xD3C5, 0xC6F1, 0xD3C8, 0xC6F2, 0xD3C9,
+	0xC6F3, 0xD3D0, 0xC6F4, 0xD3D8, 0xC6F5, 0xD3E1, 0xC6F6, 0xD3E3,
+	0xC6F7, 0xD3EC, 0xC6F8, 0xD3ED, 0xC6F9, 0xD3F0, 0xC6FA, 0xD3F4,
+	0xC6FB, 0xD3FC, 0xC6FC, 0xD3FD, 0xC6FD, 0xD3FF, 0xC6FE, 0xD401,
+	0xC7A1, 0xD408, 0xC7A2, 0xD41D, 0xC7A3, 0xD440, 0xC7A4, 0xD444,
+	0xC7A5, 0xD45C, 0xC7A6, 0xD460, 0xC7A7, 0xD464, 0xC7A8, 0xD46D,
+	0xC7A9, 0xD46F, 0xC7AA, 0xD478, 0xC7AB, 0xD479, 0xC7AC, 0xD47C,
+	0xC7AD, 0xD47F, 0xC7AE, 0xD480, 0xC7AF, 0xD482, 0xC7B0, 0xD488,
+	0xC7B1, 0xD489, 0xC7B2, 0xD48B, 0xC7B3, 0xD48D, 0xC7B4, 0xD494,
+	0xC7B5, 0xD4A9, 0xC7B6, 0xD4CC, 0xC7B7, 0xD4D0, 0xC7B8, 0xD4D4,
+	0xC7B9, 0xD4DC, 0xC7BA, 0xD4DF, 0xC7BB, 0xD4E8, 0xC7BC, 0xD4EC,
+	0xC7BD, 0xD4F0, 0xC7BE, 0xD4F8, 0xC7BF, 0xD4FB, 0xC7C0, 0xD4FD,
+	0xC7C1, 0xD504, 0xC7C2, 0xD508, 0xC7C3, 0xD50C, 0xC7C4, 0xD514,
+	0xC7C5, 0xD515, 0xC7C6, 0xD517, 0xC7C7, 0xD53C, 0xC7C8, 0xD53D,
+	0xC7C9, 0xD540, 0xC7CA, 0xD544, 0xC7CB, 0xD54C, 0xC7CC, 0xD54D,
+	0xC7CD, 0xD54F, 0xC7CE, 0xD551, 0xC7CF, 0xD558, 0xC7D0, 0xD559,
+	0xC7D1, 0xD55C, 0xC7D2, 0xD560, 0xC7D3, 0xD565, 0xC7D4, 0xD568,
+	0xC7D5, 0xD569, 0xC7D6, 0xD56B, 0xC7D7, 0xD56D, 0xC7D8, 0xD574,
+	0xC7D9, 0xD575, 0xC7DA, 0xD578, 0xC7DB, 0xD57C, 0xC7DC, 0xD584,
+	0xC7DD, 0xD585, 0xC7DE, 0xD587, 0xC7DF, 0xD588, 0xC7E0, 0xD589,
+	0xC7E1, 0xD590, 0xC7E2, 0xD5A5, 0xC7E3, 0xD5C8, 0xC7E4, 0xD5C9,
+	0xC7E5, 0xD5CC, 0xC7E6, 0xD5D0, 0xC7E7, 0xD5D2, 0xC7E8, 0xD5D8,
+	0xC7E9, 0xD5D9, 0xC7EA, 0xD5DB, 0xC7EB, 0xD5DD, 0xC7EC, 0xD5E4,
+	0xC7ED, 0xD5E5, 0xC7EE, 0xD5E8, 0xC7EF, 0xD5EC, 0xC7F0, 0xD5F4,
+	0xC7F1, 0xD5F5, 0xC7F2, 0xD5F7, 0xC7F3, 0xD5F9, 0xC7F4, 0xD600,
+	0xC7F5, 0xD601, 0xC7F6, 0xD604, 0xC7F7, 0xD608, 0xC7F8, 0xD610,
+	0xC7F9, 0xD611, 0xC7FA, 0xD613, 0xC7FB, 0xD614, 0xC7FC, 0xD615,
+	0xC7FD, 0xD61C, 0xC7FE, 0xD620, 0xC8A1, 0xD624, 0xC8A2, 0xD62D,
+	0xC8A3, 0xD638, 0xC8A4, 0xD639, 0xC8A5, 0xD63C, 0xC8A6, 0xD640,
+	0xC8A7, 0xD645, 0xC8A8, 0xD648, 0xC8A9, 0xD649, 0xC8AA, 0xD64B,
+	0xC8AB, 0xD64D, 0xC8AC, 0xD651, 0xC8AD, 0xD654, 0xC8AE, 0xD655,
+	0xC8AF, 0xD658, 0xC8B0, 0xD65C, 0xC8B1, 0xD667, 0xC8B2, 0xD669,
+	0xC8B3, 0xD670, 0xC8B4, 0xD671, 0xC8B5, 0xD674, 0xC8B6, 0xD683,
+	0xC8B7, 0xD685, 0xC8B8, 0xD68C, 0xC8B9, 0xD68D, 0xC8BA, 0xD690,
+	0xC8BB, 0xD694, 0xC8BC, 0xD69D, 0xC8BD, 0xD69F, 0xC8BE, 0xD6A1,
+	0xC8BF, 0xD6A8, 0xC8C0, 0xD6AC, 0xC8C1, 0xD6B0, 0xC8C2, 0xD6B9,
+	0xC8C3, 0xD6BB, 0xC8C4, 0xD6C4, 0xC8C5, 0xD6C5, 0xC8C6, 0xD6C8,
+	0xC8C7, 0xD6CC, 0xC8C8, 0xD6D1, 0xC8C9, 0xD6D4, 0xC8CA, 0xD6D7,
+	0xC8CB, 0xD6D9, 0xC8CC, 0xD6E0, 0xC8CD, 0xD6E4, 0xC8CE, 0xD6E8,
+	0xC8CF, 0xD6F0, 0xC8D0, 0xD6F5, 0xC8D1, 0xD6FC, 0xC8D2, 0xD6FD,
+	0xC8D3, 0xD700, 0xC8D4, 0xD704, 0xC8D5, 0xD711, 0xC8D6, 0xD718,
+	0xC8D7, 0xD719, 0xC8D8, 0xD71C, 0xC8D9, 0xD720, 0xC8DA, 0xD728,
+	0xC8DB, 0xD729, 0xC8DC, 0xD72B, 0xC8DD, 0xD72D, 0xC8DE, 0xD734,
+	0xC8DF, 0xD735, 0xC8E0, 0xD738, 0xC8E1, 0xD73C, 0xC8E2, 0xD744,
+	0xC8E3, 0xD747, 0xC8E4, 0xD749, 0xC8E5, 0xD750, 0xC8E6, 0xD751,
+	0xC8E7, 0xD754, 0xC8E8, 0xD756, 0xC8E9, 0xD757, 0xC8EA, 0xD758,
+	0xC8EB, 0xD759, 0xC8EC, 0xD760, 0xC8ED, 0xD761, 0xC8EE, 0xD763,
+	0xC8EF, 0xD765, 0xC8F0, 0xD769, 0xC8F1, 0xD76C, 0xC8F2, 0xD770,
+	0xC8F3, 0xD774, 0xC8F4, 0xD77C, 0xC8F5, 0xD77D, 0xC8F6, 0xD781,
+	0xC8F7, 0xD788, 0xC8F8, 0xD789, 0xC8F9, 0xD78C, 0xC8FA, 0xD790,
+	0xC8FB, 0xD798, 0xC8FC, 0xD799, 0xC8FD, 0xD79B, 0xC8FE, 0xD79D,
+	0xCAA1, 0x4F3D, 0xCAA2, 0x4F73, 0xCAA3, 0x5047, 0xCAA4, 0x50F9,
+	0xCAA5, 0x52A0, 0xCAA6, 0x53EF, 0xCAA7, 0x5475, 0xCAA8, 0x54E5,
+	0xCAA9, 0x5609, 0xCAAA, 0x5AC1, 0xCAAB, 0x5BB6, 0xCAAC, 0x6687,
+	0xCAAD, 0x67B6, 0xCAAE, 0x67B7, 0xCAAF, 0x67EF, 0xCAB0, 0x6B4C,
+	0xCAB1, 0x73C2, 0xCAB2, 0x75C2, 0xCAB3, 0x7A3C, 0xCAB4, 0x82DB,
+	0xCAB5, 0x8304, 0xCAB6, 0x8857, 0xCAB7, 0x8888, 0xCAB8, 0x8A36,
+	0xCAB9, 0x8CC8, 0xCABA, 0x8DCF, 0xCABB, 0x8EFB, 0xCABC, 0x8FE6,
+	0xCABD, 0x99D5, 0xCABE, 0x523B, 0xCABF, 0x5374, 0xCAC0, 0x5404,
+	0xCAC1, 0x606A, 0xCAC2, 0x6164, 0xCAC3, 0x6BBC, 0xCAC4, 0x73CF,
+	0xCAC5, 0x811A, 0xCAC6, 0x89BA, 0xCAC7, 0x89D2, 0xCAC8, 0x95A3,
+	0xCAC9, 0x4F83, 0xCACA, 0x520A, 0xCACB, 0x58BE, 0xCACC, 0x5978,
+	0xCACD, 0x59E6, 0xCACE, 0x5E72, 0xCACF, 0x5E79, 0xCAD0, 0x61C7,
+	0xCAD1, 0x63C0, 0xCAD2, 0x6746, 0xCAD3, 0x67EC, 0xCAD4, 0x687F,
+	0xCAD5, 0x6F97, 0xCAD6, 0x764E, 0xCAD7, 0x770B, 0xCAD8, 0x78F5,
+	0xCAD9, 0x7A08, 0xCADA, 0x7AFF, 0xCADB, 0x7C21, 0xCADC, 0x809D,
+	0xCADD, 0x826E, 0xCADE, 0x8271, 0xCADF, 0x8AEB, 0xCAE0, 0x9593,
+	0xCAE1, 0x4E6B, 0xCAE2, 0x559D, 0xCAE3, 0x66F7, 0xCAE4, 0x6E34,
+	0xCAE5, 0x78A3, 0xCAE6, 0x7AED, 0xCAE7, 0x845B, 0xCAE8, 0x8910,
+	0xCAE9, 0x874E, 0xCAEA, 0x97A8, 0xCAEB, 0x52D8, 0xCAEC, 0x574E,
+	0xCAED, 0x582A, 0xCAEE, 0x5D4C, 0xCAEF, 0x611F, 0xCAF0, 0x61BE,
+	0xCAF1, 0x6221, 0xCAF2, 0x6562, 0xCAF3, 0x67D1, 0xCAF4, 0x6A44,
+	0xCAF5, 0x6E1B, 0xCAF6, 0x7518, 0xCAF7, 0x75B3, 0xCAF8, 0x76E3,
+	0xCAF9, 0x77B0, 0xCAFA, 0x7D3A, 0xCAFB, 0x90AF, 0xCAFC, 0x9451,
+	0xCAFD, 0x9452, 0xCAFE, 0x9F95, 0xCBA1, 0x5323, 0xCBA2, 0x5CAC,
+	0xCBA3, 0x7532, 0xCBA4, 0x80DB, 0xCBA5, 0x9240, 0xCBA6, 0x9598,
+	0xCBA7, 0x525B, 0xCBA8, 0x5808, 0xCBA9, 0x59DC, 0xCBAA, 0x5CA1,
+	0xCBAB, 0x5D17, 0xCBAC, 0x5EB7, 0xCBAD, 0x5F3A, 0xCBAE, 0x5F4A,
+	0xCBAF, 0x6177, 0xCBB0, 0x6C5F, 0xCBB1, 0x757A, 0xCBB2, 0x7586,
+	0xCBB3, 0x7CE0, 0xCBB4, 0x7D73, 0xCBB5, 0x7DB1, 0xCBB6, 0x7F8C,
+	0xCBB7, 0x8154, 0xCBB8, 0x8221, 0xCBB9, 0x8591, 0xCBBA, 0x8941,
+	0xCBBB, 0x8B1B, 0xCBBC, 0x92FC, 0xCBBD, 0x964D, 0xCBBE, 0x9C47,
+	0xCBBF, 0x4ECB, 0xCBC0, 0x4EF7, 0xCBC1, 0x500B, 0xCBC2, 0x51F1,
+	0xCBC3, 0x584F, 0xCBC4, 0x6137, 0xCBC5, 0x613E, 0xCBC6, 0x6168,
+	0xCBC7, 0x6539, 0xCBC8, 0x69EA, 0xCBC9, 0x6F11, 0xCBCA, 0x75A5,
+	0xCBCB, 0x7686, 0xCBCC, 0x76D6, 0xCBCD, 0x7B87, 0xCBCE, 0x82A5,
+	0xCBCF, 0x84CB, 0xCBD0, 0xF900, 0xCBD1, 0x93A7, 0xCBD2, 0x958B,
+	0xCBD3, 0x5580, 0xCBD4, 0x5BA2, 0xCBD5, 0x5751, 0xCBD6, 0xF901,
+	0xCBD7, 0x7CB3, 0xCBD8, 0x7FB9, 0xCBD9, 0x91B5, 0xCBDA, 0x5028,
+	0xCBDB, 0x53BB, 0xCBDC, 0x5C45, 0xCBDD, 0x5DE8, 0xCBDE, 0x62D2,
+	0xCBDF, 0x636E, 0xCBE0, 0x64DA, 0xCBE1, 0x64E7, 0xCBE2, 0x6E20,
+	0xCBE3, 0x70AC, 0xCBE4, 0x795B, 0xCBE5, 0x8DDD, 0xCBE6, 0x8E1E,
+	0xCBE7, 0xF902, 0xCBE8, 0x907D, 0xCBE9, 0x9245, 0xCBEA, 0x92F8,
+	0xCBEB, 0x4E7E, 0xCBEC, 0x4EF6, 0xCBED, 0x5065, 0xCBEE, 0x5DFE,
+	0xCBEF, 0x5EFA, 0xCBF0, 0x6106, 0xCBF1, 0x6957, 0xCBF2, 0x8171,
+	0xCBF3, 0x8654, 0xCBF4, 0x8E47, 0xCBF5, 0x9375, 0xCBF6, 0x9A2B,
+	0xCBF7, 0x4E5E, 0xCBF8, 0x5091, 0xCBF9, 0x6770, 0xCBFA, 0x6840,
+	0xCBFB, 0x5109, 0xCBFC, 0x528D, 0xCBFD, 0x5292, 0xCBFE, 0x6AA2,
+	0xCCA1, 0x77BC, 0xCCA2, 0x9210, 0xCCA3, 0x9ED4, 0xCCA4, 0x52AB,
+	0xCCA5, 0x602F, 0xCCA6, 0x8FF2, 0xCCA7, 0x5048, 0xCCA8, 0x61A9,
+	0xCCA9, 0x63ED, 0xCCAA, 0x64CA, 0xCCAB, 0x683C, 0xCCAC, 0x6A84,
+	0xCCAD, 0x6FC0, 0xCCAE, 0x8188, 0xCCAF, 0x89A1, 0xCCB0, 0x9694,
+	0xCCB1, 0x5805, 0xCCB2, 0x727D, 0xCCB3, 0x72AC, 0xCCB4, 0x7504,
+	0xCCB5, 0x7D79, 0xCCB6, 0x7E6D, 0xCCB7, 0x80A9, 0xCCB8, 0x898B,
+	0xCCB9, 0x8B74, 0xCCBA, 0x9063, 0xCCBB, 0x9D51, 0xCCBC, 0x6289,
+	0xCCBD, 0x6C7A, 0xCCBE, 0x6F54, 0xCCBF, 0x7D50, 0xCCC0, 0x7F3A,
+	0xCCC1, 0x8A23, 0xCCC2, 0x517C, 0xCCC3, 0x614A, 0xCCC4, 0x7B9D,
+	0xCCC5, 0x8B19, 0xCCC6, 0x9257, 0xCCC7, 0x938C, 0xCCC8, 0x4EAC,
+	0xCCC9, 0x4FD3, 0xCCCA, 0x501E, 0xCCCB, 0x50BE, 0xCCCC, 0x5106,
+	0xCCCD, 0x52C1, 0xCCCE, 0x52CD, 0xCCCF, 0x537F, 0xCCD0, 0x5770,
+	0xCCD1, 0x5883, 0xCCD2, 0x5E9A, 0xCCD3, 0x5F91, 0xCCD4, 0x6176,
+	0xCCD5, 0x61AC, 0xCCD6, 0x64CE, 0xCCD7, 0x656C, 0xCCD8, 0x666F,
+	0xCCD9, 0x66BB, 0xCCDA, 0x66F4, 0xCCDB, 0x6897, 0xCCDC, 0x6D87,
+	0xCCDD, 0x7085, 0xCCDE, 0x70F1, 0xCCDF, 0x749F, 0xCCE0, 0x74A5,
+	0xCCE1, 0x74CA, 0xCCE2, 0x75D9, 0xCCE3, 0x786C, 0xCCE4, 0x78EC,
+	0xCCE5, 0x7ADF, 0xCCE6, 0x7AF6, 0xCCE7, 0x7D45, 0xCCE8, 0x7D93,
+	0xCCE9, 0x8015, 0xCCEA, 0x803F, 0xCCEB, 0x811B, 0xCCEC, 0x8396,
+	0xCCED, 0x8B66, 0xCCEE, 0x8F15, 0xCCEF, 0x9015, 0xCCF0, 0x93E1,
+	0xCCF1, 0x9803, 0xCCF2, 0x9838, 0xCCF3, 0x9A5A, 0xCCF4, 0x9BE8,
+	0xCCF5, 0x4FC2, 0xCCF6, 0x5553, 0xCCF7, 0x583A, 0xCCF8, 0x5951,
+	0xCCF9, 0x5B63, 0xCCFA, 0x5C46, 0xCCFB, 0x60B8, 0xCCFC, 0x6212,
+	0xCCFD, 0x6842, 0xCCFE, 0x68B0, 0xCDA1, 0x68E8, 0xCDA2, 0x6EAA,
+	0xCDA3, 0x754C, 0xCDA4, 0x7678, 0xCDA5, 0x78CE, 0xCDA6, 0x7A3D,
+	0xCDA7, 0x7CFB, 0xCDA8, 0x7E6B, 0xCDA9, 0x7E7C, 0xCDAA, 0x8A08,
+	0xCDAB, 0x8AA1, 0xCDAC, 0x8C3F, 0xCDAD, 0x968E, 0xCDAE, 0x9DC4,
+	0xCDAF, 0x53E4, 0xCDB0, 0x53E9, 0xCDB1, 0x544A, 0xCDB2, 0x5471,
+	0xCDB3, 0x56FA, 0xCDB4, 0x59D1, 0xCDB5, 0x5B64, 0xCDB6, 0x5C3B,
+	0xCDB7, 0x5EAB, 0xCDB8, 0x62F7, 0xCDB9, 0x6537, 0xCDBA, 0x6545,
+	0xCDBB, 0x6572, 0xCDBC, 0x66A0, 0xCDBD, 0x67AF, 0xCDBE, 0x69C1,
+	0xCDBF, 0x6CBD, 0xCDC0, 0x75FC, 0xCDC1, 0x7690, 0xCDC2, 0x777E,
+	0xCDC3, 0x7A3F, 0xCDC4, 0x7F94, 0xCDC5, 0x8003, 0xCDC6, 0x80A1,
+	0xCDC7, 0x818F, 0xCDC8, 0x82E6, 0xCDC9, 0x82FD, 0xCDCA, 0x83F0,
+	0xCDCB, 0x85C1, 0xCDCC, 0x8831, 0xCDCD, 0x88B4, 0xCDCE, 0x8AA5,
+	0xCDCF, 0xF903, 0xCDD0, 0x8F9C, 0xCDD1, 0x932E, 0xCDD2, 0x96C7,
+	0xCDD3, 0x9867, 0xCDD4, 0x9AD8, 0xCDD5, 0x9F13, 0xCDD6, 0x54ED,
+	0xCDD7, 0x659B, 0xCDD8, 0x66F2, 0xCDD9, 0x688F, 0xCDDA, 0x7A40,
+	0xCDDB, 0x8C37, 0xCDDC, 0x9D60, 0xCDDD, 0x56F0, 0xCDDE, 0x5764,
+	0xCDDF, 0x5D11, 0xCDE0, 0x6606, 0xCDE1, 0x68B1, 0xCDE2, 0x68CD,
+	0xCDE3, 0x6EFE, 0xCDE4, 0x7428, 0xCDE5, 0x889E, 0xCDE6, 0x9BE4,
+	0xCDE7, 0x6C68, 0xCDE8, 0xF904, 0xCDE9, 0x9AA8, 0xCDEA, 0x4F9B,
+	0xCDEB, 0x516C, 0xCDEC, 0x5171, 0xCDED, 0x529F, 0xCDEE, 0x5B54,
+	0xCDEF, 0x5DE5, 0xCDF0, 0x6050, 0xCDF1, 0x606D, 0xCDF2, 0x62F1,
+	0xCDF3, 0x63A7, 0xCDF4, 0x653B, 0xCDF5, 0x73D9, 0xCDF6, 0x7A7A,
+	0xCDF7, 0x86A3, 0xCDF8, 0x8CA2, 0xCDF9, 0x978F, 0xCDFA, 0x4E32,
+	0xCDFB, 0x5BE1, 0xCDFC, 0x6208, 0xCDFD, 0x679C, 0xCDFE, 0x74DC,
+	0xCEA1, 0x79D1, 0xCEA2, 0x83D3, 0xCEA3, 0x8A87, 0xCEA4, 0x8AB2,
+	0xCEA5, 0x8DE8, 0xCEA6, 0x904E, 0xCEA7, 0x934B, 0xCEA8, 0x9846,
+	0xCEA9, 0x5ED3, 0xCEAA, 0x69E8, 0xCEAB, 0x85FF, 0xCEAC, 0x90ED,
+	0xCEAD, 0xF905, 0xCEAE, 0x51A0, 0xCEAF, 0x5B98, 0xCEB0, 0x5BEC,
+	0xCEB1, 0x6163, 0xCEB2, 0x68FA, 0xCEB3, 0x6B3E, 0xCEB4, 0x704C,
+	0xCEB5, 0x742F, 0xCEB6, 0x74D8, 0xCEB7, 0x7BA1, 0xCEB8, 0x7F50,
+	0xCEB9, 0x83C5, 0xCEBA, 0x89C0, 0xCEBB, 0x8CAB, 0xCEBC, 0x95DC,
+	0xCEBD, 0x9928, 0xCEBE, 0x522E, 0xCEBF, 0x605D, 0xCEC0, 0x62EC,
+	0xCEC1, 0x9002, 0xCEC2, 0x4F8A, 0xCEC3, 0x5149, 0xCEC4, 0x5321,
+	0xCEC5, 0x58D9, 0xCEC6, 0x5EE3, 0xCEC7, 0x66E0, 0xCEC8, 0x6D38,
+	0xCEC9, 0x709A, 0xCECA, 0x72C2, 0xCECB, 0x73D6, 0xCECC, 0x7B50,
+	0xCECD, 0x80F1, 0xCECE, 0x945B, 0xCECF, 0x5366, 0xCED0, 0x639B,
+	0xCED1, 0x7F6B, 0xCED2, 0x4E56, 0xCED3, 0x5080, 0xCED4, 0x584A,
+	0xCED5, 0x58DE, 0xCED6, 0x602A, 0xCED7, 0x6127, 0xCED8, 0x62D0,
+	0xCED9, 0x69D0, 0xCEDA, 0x9B41, 0xCEDB, 0x5B8F, 0xCEDC, 0x7D18,
+	0xCEDD, 0x80B1, 0xCEDE, 0x8F5F, 0xCEDF, 0x4EA4, 0xCEE0, 0x50D1,
+	0xCEE1, 0x54AC, 0xCEE2, 0x55AC, 0xCEE3, 0x5B0C, 0xCEE4, 0x5DA0,
+	0xCEE5, 0x5DE7, 0xCEE6, 0x652A, 0xCEE7, 0x654E, 0xCEE8, 0x6821,
+	0xCEE9, 0x6A4B, 0xCEEA, 0x72E1, 0xCEEB, 0x768E, 0xCEEC, 0x77EF,
+	0xCEED, 0x7D5E, 0xCEEE, 0x7FF9, 0xCEEF, 0x81A0, 0xCEF0, 0x854E,
+	0xCEF1, 0x86DF, 0xCEF2, 0x8F03, 0xCEF3, 0x8F4E, 0xCEF4, 0x90CA,
+	0xCEF5, 0x9903, 0xCEF6, 0x9A55, 0xCEF7, 0x9BAB, 0xCEF8, 0x4E18,
+	0xCEF9, 0x4E45, 0xCEFA, 0x4E5D, 0xCEFB, 0x4EC7, 0xCEFC, 0x4FF1,
+	0xCEFD, 0x5177, 0xCEFE, 0x52FE, 0xCFA1, 0x5340, 0xCFA2, 0x53E3,
+	0xCFA3, 0x53E5, 0xCFA4, 0x548E, 0xCFA5, 0x5614, 0xCFA6, 0x5775,
+	0xCFA7, 0x57A2, 0xCFA8, 0x5BC7, 0xCFA9, 0x5D87, 0xCFAA, 0x5ED0,
+	0xCFAB, 0x61FC, 0xCFAC, 0x62D8, 0xCFAD, 0x6551, 0xCFAE, 0x67B8,
+	0xCFAF, 0x67E9, 0xCFB0, 0x69CB, 0xCFB1, 0x6B50, 0xCFB2, 0x6BC6,
+	0xCFB3, 0x6BEC, 0xCFB4, 0x6C42, 0xCFB5, 0x6E9D, 0xCFB6, 0x7078,
+	0xCFB7, 0x72D7, 0xCFB8, 0x7396, 0xCFB9, 0x7403, 0xCFBA, 0x77BF,
+	0xCFBB, 0x77E9, 0xCFBC, 0x7A76, 0xCFBD, 0x7D7F, 0xCFBE, 0x8009,
+	0xCFBF, 0x81FC, 0xCFC0, 0x8205, 0xCFC1, 0x820A, 0xCFC2, 0x82DF,
+	0xCFC3, 0x8862, 0xCFC4, 0x8B33, 0xCFC5, 0x8CFC, 0xCFC6, 0x8EC0,
+	0xCFC7, 0x9011, 0xCFC8, 0x90B1, 0xCFC9, 0x9264, 0xCFCA, 0x92B6,
+	0xCFCB, 0x99D2, 0xCFCC, 0x9A45, 0xCFCD, 0x9CE9, 0xCFCE, 0x9DD7,
+	0xCFCF, 0x9F9C, 0xCFD0, 0x570B, 0xCFD1, 0x5C40, 0xCFD2, 0x83CA,
+	0xCFD3, 0x97A0, 0xCFD4, 0x97AB, 0xCFD5, 0x9EB4, 0xCFD6, 0x541B,
+	0xCFD7, 0x7A98, 0xCFD8, 0x7FA4, 0xCFD9, 0x88D9, 0xCFDA, 0x8ECD,
+	0xCFDB, 0x90E1, 0xCFDC, 0x5800, 0xCFDD, 0x5C48, 0xCFDE, 0x6398,
+	0xCFDF, 0x7A9F, 0xCFE0, 0x5BAE, 0xCFE1, 0x5F13, 0xCFE2, 0x7A79,
+	0xCFE3, 0x7AAE, 0xCFE4, 0x828E, 0xCFE5, 0x8EAC, 0xCFE6, 0x5026,
+	0xCFE7, 0x5238, 0xCFE8, 0x52F8, 0xCFE9, 0x5377, 0xCFEA, 0x5708,
+	0xCFEB, 0x62F3, 0xCFEC, 0x6372, 0xCFED, 0x6B0A, 0xCFEE, 0x6DC3,
+	0xCFEF, 0x7737, 0xCFF0, 0x53A5, 0xCFF1, 0x7357, 0xCFF2, 0x8568,
+	0xCFF3, 0x8E76, 0xCFF4, 0x95D5, 0xCFF5, 0x673A, 0xCFF6, 0x6AC3,
+	0xCFF7, 0x6F70, 0xCFF8, 0x8A6D, 0xCFF9, 0x8ECC, 0xCFFA, 0x994B,
+	0xCFFB, 0xF906, 0xCFFC, 0x6677, 0xCFFD, 0x6B78, 0xCFFE, 0x8CB4,
+	0xD0A1, 0x9B3C, 0xD0A2, 0xF907, 0xD0A3, 0x53EB, 0xD0A4, 0x572D,
+	0xD0A5, 0x594E, 0xD0A6, 0x63C6, 0xD0A7, 0x69FB, 0xD0A8, 0x73EA,
+	0xD0A9, 0x7845, 0xD0AA, 0x7ABA, 0xD0AB, 0x7AC5, 0xD0AC, 0x7CFE,
+	0xD0AD, 0x8475, 0xD0AE, 0x898F, 0xD0AF, 0x8D73, 0xD0B0, 0x9035,
+	0xD0B1, 0x95A8, 0xD0B2, 0x52FB, 0xD0B3, 0x5747, 0xD0B4, 0x7547,
+	0xD0B5, 0x7B60, 0xD0B6, 0x83CC, 0xD0B7, 0x921E, 0xD0B8, 0xF908,
+	0xD0B9, 0x6A58, 0xD0BA, 0x514B, 0xD0BB, 0x524B, 0xD0BC, 0x5287,
+	0xD0BD, 0x621F, 0xD0BE, 0x68D8, 0xD0BF, 0x6975, 0xD0C0, 0x9699,
+	0xD0C1, 0x50C5, 0xD0C2, 0x52A4, 0xD0C3, 0x52E4, 0xD0C4, 0x61C3,
+	0xD0C5, 0x65A4, 0xD0C6, 0x6839, 0xD0C7, 0x69FF, 0xD0C8, 0x747E,
+	0xD0C9, 0x7B4B, 0xD0CA, 0x82B9, 0xD0CB, 0x83EB, 0xD0CC, 0x89B2,
+	0xD0CD, 0x8B39, 0xD0CE, 0x8FD1, 0xD0CF, 0x9949, 0xD0D0, 0xF909,
+	0xD0D1, 0x4ECA, 0xD0D2, 0x5997, 0xD0D3, 0x64D2, 0xD0D4, 0x6611,
+	0xD0D5, 0x6A8E, 0xD0D6, 0x7434, 0xD0D7, 0x7981, 0xD0D8, 0x79BD,
+	0xD0D9, 0x82A9, 0xD0DA, 0x887E, 0xD0DB, 0x887F, 0xD0DC, 0x895F,
+	0xD0DD, 0xF90A, 0xD0DE, 0x9326, 0xD0DF, 0x4F0B, 0xD0E0, 0x53CA,
+	0xD0E1, 0x6025, 0xD0E2, 0x6271, 0xD0E3, 0x6C72, 0xD0E4, 0x7D1A,
+	0xD0E5, 0x7D66, 0xD0E6, 0x4E98, 0xD0E7, 0x5162, 0xD0E8, 0x77DC,
+	0xD0E9, 0x80AF, 0xD0EA, 0x4F01, 0xD0EB, 0x4F0E, 0xD0EC, 0x5176,
+	0xD0ED, 0x5180, 0xD0EE, 0x55DC, 0xD0EF, 0x5668, 0xD0F0, 0x573B,
+	0xD0F1, 0x57FA, 0xD0F2, 0x57FC, 0xD0F3, 0x5914, 0xD0F4, 0x5947,
+	0xD0F5, 0x5993, 0xD0F6, 0x5BC4, 0xD0F7, 0x5C90, 0xD0F8, 0x5D0E,
+	0xD0F9, 0x5DF1, 0xD0FA, 0x5E7E, 0xD0FB, 0x5FCC, 0xD0FC, 0x6280,
+	0xD0FD, 0x65D7, 0xD0FE, 0x65E3, 0xD1A1, 0x671E, 0xD1A2, 0x671F,
+	0xD1A3, 0x675E, 0xD1A4, 0x68CB, 0xD1A5, 0x68C4, 0xD1A6, 0x6A5F,
+	0xD1A7, 0x6B3A, 0xD1A8, 0x6C23, 0xD1A9, 0x6C7D, 0xD1AA, 0x6C82,
+	0xD1AB, 0x6DC7, 0xD1AC, 0x7398, 0xD1AD, 0x7426, 0xD1AE, 0x742A,
+	0xD1AF, 0x7482, 0xD1B0, 0x74A3, 0xD1B1, 0x7578, 0xD1B2, 0x757F,
+	0xD1B3, 0x7881, 0xD1B4, 0x78EF, 0xD1B5, 0x7941, 0xD1B6, 0x7947,
+	0xD1B7, 0x7948, 0xD1B8, 0x797A, 0xD1B9, 0x7B95, 0xD1BA, 0x7D00,
+	0xD1BB, 0x7DBA, 0xD1BC, 0x7F88, 0xD1BD, 0x8006, 0xD1BE, 0x802D,
+	0xD1BF, 0x808C, 0xD1C0, 0x8A18, 0xD1C1, 0x8B4F, 0xD1C2, 0x8C48,
+	0xD1C3, 0x8D77, 0xD1C4, 0x9321, 0xD1C5, 0x9324, 0xD1C6, 0x98E2,
+	0xD1C7, 0x9951, 0xD1C8, 0x9A0E, 0xD1C9, 0x9A0F, 0xD1CA, 0x9A65,
+	0xD1CB, 0x9E92, 0xD1CC, 0x7DCA, 0xD1CD, 0x4F76, 0xD1CE, 0x5409,
+	0xD1CF, 0x62EE, 0xD1D0, 0x6854, 0xD1D1, 0x91D1, 0xD1D2, 0x55AB,
+	0xD1D3, 0x513A, 0xD1D4, 0xF90B, 0xD1D5, 0xF90C, 0xD1D6, 0x5A1C,
+	0xD1D7, 0x61E6, 0xD1D8, 0xF90D, 0xD1D9, 0x62CF, 0xD1DA, 0x62FF,
+	0xD1DB, 0xF90E, 0xD1DC, 0xF90F, 0xD1DD, 0xF910, 0xD1DE, 0xF911,
+	0xD1DF, 0xF912, 0xD1E0, 0xF913, 0xD1E1, 0x90A3, 0xD1E2, 0xF914,
+	0xD1E3, 0xF915, 0xD1E4, 0xF916, 0xD1E5, 0xF917, 0xD1E6, 0xF918,
+	0xD1E7, 0x8AFE, 0xD1E8, 0xF919, 0xD1E9, 0xF91A, 0xD1EA, 0xF91B,
+	0xD1EB, 0xF91C, 0xD1EC, 0x6696, 0xD1ED, 0xF91D, 0xD1EE, 0x7156,
+	0xD1EF, 0xF91E, 0xD1F0, 0xF91F, 0xD1F1, 0x96E3, 0xD1F2, 0xF920,
+	0xD1F3, 0x634F, 0xD1F4, 0x637A, 0xD1F5, 0x5357, 0xD1F6, 0xF921,
+	0xD1F7, 0x678F, 0xD1F8, 0x6960, 0xD1F9, 0x6E73, 0xD1FA, 0xF922,
+	0xD1FB, 0x7537, 0xD1FC, 0xF923, 0xD1FD, 0xF924, 0xD1FE, 0xF925,
+	0xD2A1, 0x7D0D, 0xD2A2, 0xF926, 0xD2A3, 0xF927, 0xD2A4, 0x8872,
+	0xD2A5, 0x56CA, 0xD2A6, 0x5A18, 0xD2A7, 0xF928, 0xD2A8, 0xF929,
+	0xD2A9, 0xF92A, 0xD2AA, 0xF92B, 0xD2AB, 0xF92C, 0xD2AC, 0x4E43,
+	0xD2AD, 0xF92D, 0xD2AE, 0x5167, 0xD2AF, 0x5948, 0xD2B0, 0x67F0,
+	0xD2B1, 0x8010, 0xD2B2, 0xF92E, 0xD2B3, 0x5973, 0xD2B4, 0x5E74,
+	0xD2B5, 0x649A, 0xD2B6, 0x79CA, 0xD2B7, 0x5FF5, 0xD2B8, 0x606C,
+	0xD2B9, 0x62C8, 0xD2BA, 0x637B, 0xD2BB, 0x5BE7, 0xD2BC, 0x5BD7,
+	0xD2BD, 0x52AA, 0xD2BE, 0xF92F, 0xD2BF, 0x5974, 0xD2C0, 0x5F29,
+	0xD2C1, 0x6012, 0xD2C2, 0xF930, 0xD2C3, 0xF931, 0xD2C4, 0xF932,
+	0xD2C5, 0x7459, 0xD2C6, 0xF933, 0xD2C7, 0xF934, 0xD2C8, 0xF935,
+	0xD2C9, 0xF936, 0xD2CA, 0xF937, 0xD2CB, 0xF938, 0xD2CC, 0x99D1,
+	0xD2CD, 0xF939, 0xD2CE, 0xF93A, 0xD2CF, 0xF93B, 0xD2D0, 0xF93C,
+	0xD2D1, 0xF93D, 0xD2D2, 0xF93E, 0xD2D3, 0xF93F, 0xD2D4, 0xF940,
+	0xD2D5, 0xF941, 0xD2D6, 0xF942, 0xD2D7, 0xF943, 0xD2D8, 0x6FC3,
+	0xD2D9, 0xF944, 0xD2DA, 0xF945, 0xD2DB, 0x81BF, 0xD2DC, 0x8FB2,
+	0xD2DD, 0x60F1, 0xD2DE, 0xF946, 0xD2DF, 0xF947, 0xD2E0, 0x8166,
+	0xD2E1, 0xF948, 0xD2E2, 0xF949, 0xD2E3, 0x5C3F, 0xD2E4, 0xF94A,
+	0xD2E5, 0xF94B, 0xD2E6, 0xF94C, 0xD2E7, 0xF94D, 0xD2E8, 0xF94E,
+	0xD2E9, 0xF94F, 0xD2EA, 0xF950, 0xD2EB, 0xF951, 0xD2EC, 0x5AE9,
+	0xD2ED, 0x8A25, 0xD2EE, 0x677B, 0xD2EF, 0x7D10, 0xD2F0, 0xF952,
+	0xD2F1, 0xF953, 0xD2F2, 0xF954, 0xD2F3, 0xF955, 0xD2F4, 0xF956,
+	0xD2F5, 0xF957, 0xD2F6, 0x80FD, 0xD2F7, 0xF958, 0xD2F8, 0xF959,
+	0xD2F9, 0x5C3C, 0xD2FA, 0x6CE5, 0xD2FB, 0x533F, 0xD2FC, 0x6EBA,
+	0xD2FD, 0x591A, 0xD2FE, 0x8336, 0xD3A1, 0x4E39, 0xD3A2, 0x4EB6,
+	0xD3A3, 0x4F46, 0xD3A4, 0x55AE, 0xD3A5, 0x5718, 0xD3A6, 0x58C7,
+	0xD3A7, 0x5F56, 0xD3A8, 0x65B7, 0xD3A9, 0x65E6, 0xD3AA, 0x6A80,
+	0xD3AB, 0x6BB5, 0xD3AC, 0x6E4D, 0xD3AD, 0x77ED, 0xD3AE, 0x7AEF,
+	0xD3AF, 0x7C1E, 0xD3B0, 0x7DDE, 0xD3B1, 0x86CB, 0xD3B2, 0x8892,
+	0xD3B3, 0x9132, 0xD3B4, 0x935B, 0xD3B5, 0x64BB, 0xD3B6, 0x6FBE,
+	0xD3B7, 0x737A, 0xD3B8, 0x75B8, 0xD3B9, 0x9054, 0xD3BA, 0x5556,
+	0xD3BB, 0x574D, 0xD3BC, 0x61BA, 0xD3BD, 0x64D4, 0xD3BE, 0x66C7,
+	0xD3BF, 0x6DE1, 0xD3C0, 0x6E5B, 0xD3C1, 0x6F6D, 0xD3C2, 0x6FB9,
+	0xD3C3, 0x75F0, 0xD3C4, 0x8043, 0xD3C5, 0x81BD, 0xD3C6, 0x8541,
+	0xD3C7, 0x8983, 0xD3C8, 0x8AC7, 0xD3C9, 0x8B5A, 0xD3CA, 0x931F,
+	0xD3CB, 0x6C93, 0xD3CC, 0x7553, 0xD3CD, 0x7B54, 0xD3CE, 0x8E0F,
+	0xD3CF, 0x905D, 0xD3D0, 0x5510, 0xD3D1, 0x5802, 0xD3D2, 0x5858,
+	0xD3D3, 0x5E62, 0xD3D4, 0x6207, 0xD3D5, 0x649E, 0xD3D6, 0x68E0,
+	0xD3D7, 0x7576, 0xD3D8, 0x7CD6, 0xD3D9, 0x87B3, 0xD3DA, 0x9EE8,
+	0xD3DB, 0x4EE3, 0xD3DC, 0x5788, 0xD3DD, 0x576E, 0xD3DE, 0x5927,
+	0xD3DF, 0x5C0D, 0xD3E0, 0x5CB1, 0xD3E1, 0x5E36, 0xD3E2, 0x5F85,
+	0xD3E3, 0x6234, 0xD3E4, 0x64E1, 0xD3E5, 0x73B3, 0xD3E6, 0x81FA,
+	0xD3E7, 0x888B, 0xD3E8, 0x8CB8, 0xD3E9, 0x968A, 0xD3EA, 0x9EDB,
+	0xD3EB, 0x5B85, 0xD3EC, 0x5FB7, 0xD3ED, 0x60B3, 0xD3EE, 0x5012,
+	0xD3EF, 0x5200, 0xD3F0, 0x5230, 0xD3F1, 0x5716, 0xD3F2, 0x5835,
+	0xD3F3, 0x5857, 0xD3F4, 0x5C0E, 0xD3F5, 0x5C60, 0xD3F6, 0x5CF6,
+	0xD3F7, 0x5D8B, 0xD3F8, 0x5EA6, 0xD3F9, 0x5F92, 0xD3FA, 0x60BC,
+	0xD3FB, 0x6311, 0xD3FC, 0x6389, 0xD3FD, 0x6417, 0xD3FE, 0x6843,
+	0xD4A1, 0x68F9, 0xD4A2, 0x6AC2, 0xD4A3, 0x6DD8, 0xD4A4, 0x6E21,
+	0xD4A5, 0x6ED4, 0xD4A6, 0x6FE4, 0xD4A7, 0x71FE, 0xD4A8, 0x76DC,
+	0xD4A9, 0x7779, 0xD4AA, 0x79B1, 0xD4AB, 0x7A3B, 0xD4AC, 0x8404,
+	0xD4AD, 0x89A9, 0xD4AE, 0x8CED, 0xD4AF, 0x8DF3, 0xD4B0, 0x8E48,
+	0xD4B1, 0x9003, 0xD4B2, 0x9014, 0xD4B3, 0x9053, 0xD4B4, 0x90FD,
+	0xD4B5, 0x934D, 0xD4B6, 0x9676, 0xD4B7, 0x97DC, 0xD4B8, 0x6BD2,
+	0xD4B9, 0x7006, 0xD4BA, 0x7258, 0xD4BB, 0x72A2, 0xD4BC, 0x7368,
+	0xD4BD, 0x7763, 0xD4BE, 0x79BF, 0xD4BF, 0x7BE4, 0xD4C0, 0x7E9B,
+	0xD4C1, 0x8B80, 0xD4C2, 0x58A9, 0xD4C3, 0x60C7, 0xD4C4, 0x6566,
+	0xD4C5, 0x65FD, 0xD4C6, 0x66BE, 0xD4C7, 0x6C8C, 0xD4C8, 0x711E,
+	0xD4C9, 0x71C9, 0xD4CA, 0x8C5A, 0xD4CB, 0x9813, 0xD4CC, 0x4E6D,
+	0xD4CD, 0x7A81, 0xD4CE, 0x4EDD, 0xD4CF, 0x51AC, 0xD4D0, 0x51CD,
+	0xD4D1, 0x52D5, 0xD4D2, 0x540C, 0xD4D3, 0x61A7, 0xD4D4, 0x6771,
+	0xD4D5, 0x6850, 0xD4D6, 0x68DF, 0xD4D7, 0x6D1E, 0xD4D8, 0x6F7C,
+	0xD4D9, 0x75BC, 0xD4DA, 0x77B3, 0xD4DB, 0x7AE5, 0xD4DC, 0x80F4,
+	0xD4DD, 0x8463, 0xD4DE, 0x9285, 0xD4DF, 0x515C, 0xD4E0, 0x6597,
+	0xD4E1, 0x675C, 0xD4E2, 0x6793, 0xD4E3, 0x75D8, 0xD4E4, 0x7AC7,
+	0xD4E5, 0x8373, 0xD4E6, 0xF95A, 0xD4E7, 0x8C46, 0xD4E8, 0x9017,
+	0xD4E9, 0x982D, 0xD4EA, 0x5C6F, 0xD4EB, 0x81C0, 0xD4EC, 0x829A,
+	0xD4ED, 0x9041, 0xD4EE, 0x906F, 0xD4EF, 0x920D, 0xD4F0, 0x5F97,
+	0xD4F1, 0x5D9D, 0xD4F2, 0x6A59, 0xD4F3, 0x71C8, 0xD4F4, 0x767B,
+	0xD4F5, 0x7B49, 0xD4F6, 0x85E4, 0xD4F7, 0x8B04, 0xD4F8, 0x9127,
+	0xD4F9, 0x9A30, 0xD4FA, 0x5587, 0xD4FB, 0x61F6, 0xD4FC, 0xF95B,
+	0xD4FD, 0x7669, 0xD4FE, 0x7F85, 0xD5A1, 0x863F, 0xD5A2, 0x87BA,
+	0xD5A3, 0x88F8, 0xD5A4, 0x908F, 0xD5A5, 0xF95C, 0xD5A6, 0x6D1B,
+	0xD5A7, 0x70D9, 0xD5A8, 0x73DE, 0xD5A9, 0x7D61, 0xD5AA, 0x843D,
+	0xD5AB, 0xF95D, 0xD5AC, 0x916A, 0xD5AD, 0x99F1, 0xD5AE, 0xF95E,
+	0xD5AF, 0x4E82, 0xD5B0, 0x5375, 0xD5B1, 0x6B04, 0xD5B2, 0x6B12,
+	0xD5B3, 0x703E, 0xD5B4, 0x721B, 0xD5B5, 0x862D, 0xD5B6, 0x9E1E,
+	0xD5B7, 0x524C, 0xD5B8, 0x8FA3, 0xD5B9, 0x5D50, 0xD5BA, 0x64E5,
+	0xD5BB, 0x652C, 0xD5BC, 0x6B16, 0xD5BD, 0x6FEB, 0xD5BE, 0x7C43,
+	0xD5BF, 0x7E9C, 0xD5C0, 0x85CD, 0xD5C1, 0x8964, 0xD5C2, 0x89BD,
+	0xD5C3, 0x62C9, 0xD5C4, 0x81D8, 0xD5C5, 0x881F, 0xD5C6, 0x5ECA,
+	0xD5C7, 0x6717, 0xD5C8, 0x6D6A, 0xD5C9, 0x72FC, 0xD5CA, 0x7405,
+	0xD5CB, 0x746F, 0xD5CC, 0x8782, 0xD5CD, 0x90DE, 0xD5CE, 0x4F86,
+	0xD5CF, 0x5D0D, 0xD5D0, 0x5FA0, 0xD5D1, 0x840A, 0xD5D2, 0x51B7,
+	0xD5D3, 0x63A0, 0xD5D4, 0x7565, 0xD5D5, 0x4EAE, 0xD5D6, 0x5006,
+	0xD5D7, 0x5169, 0xD5D8, 0x51C9, 0xD5D9, 0x6881, 0xD5DA, 0x6A11,
+	0xD5DB, 0x7CAE, 0xD5DC, 0x7CB1, 0xD5DD, 0x7CE7, 0xD5DE, 0x826F,
+	0xD5DF, 0x8AD2, 0xD5E0, 0x8F1B, 0xD5E1, 0x91CF, 0xD5E2, 0x4FB6,
+	0xD5E3, 0x5137, 0xD5E4, 0x52F5, 0xD5E5, 0x5442, 0xD5E6, 0x5EEC,
+	0xD5E7, 0x616E, 0xD5E8, 0x623E, 0xD5E9, 0x65C5, 0xD5EA, 0x6ADA,
+	0xD5EB, 0x6FFE, 0xD5EC, 0x792A, 0xD5ED, 0x85DC, 0xD5EE, 0x8823,
+	0xD5EF, 0x95AD, 0xD5F0, 0x9A62, 0xD5F1, 0x9A6A, 0xD5F2, 0x9E97,
+	0xD5F3, 0x9ECE, 0xD5F4, 0x529B, 0xD5F5, 0x66C6, 0xD5F6, 0x6B77,
+	0xD5F7, 0x701D, 0xD5F8, 0x792B, 0xD5F9, 0x8F62, 0xD5FA, 0x9742,
+	0xD5FB, 0x6190, 0xD5FC, 0x6200, 0xD5FD, 0x6523, 0xD5FE, 0x6F23,
+	0xD6A1, 0x7149, 0xD6A2, 0x7489, 0xD6A3, 0x7DF4, 0xD6A4, 0x806F,
+	0xD6A5, 0x84EE, 0xD6A6, 0x8F26, 0xD6A7, 0x9023, 0xD6A8, 0x934A,
+	0xD6A9, 0x51BD, 0xD6AA, 0x5217, 0xD6AB, 0x52A3, 0xD6AC, 0x6D0C,
+	0xD6AD, 0x70C8, 0xD6AE, 0x88C2, 0xD6AF, 0x5EC9, 0xD6B0, 0x6582,
+	0xD6B1, 0x6BAE, 0xD6B2, 0x6FC2, 0xD6B3, 0x7C3E, 0xD6B4, 0x7375,
+	0xD6B5, 0x4EE4, 0xD6B6, 0x4F36, 0xD6B7, 0x56F9, 0xD6B8, 0xF95F,
+	0xD6B9, 0x5CBA, 0xD6BA, 0x5DBA, 0xD6BB, 0x601C, 0xD6BC, 0x73B2,
+	0xD6BD, 0x7B2D, 0xD6BE, 0x7F9A, 0xD6BF, 0x7FCE, 0xD6C0, 0x8046,
+	0xD6C1, 0x901E, 0xD6C2, 0x9234, 0xD6C3, 0x96F6, 0xD6C4, 0x9748,
+	0xD6C5, 0x9818, 0xD6C6, 0x9F61, 0xD6C7, 0x4F8B, 0xD6C8, 0x6FA7,
+	0xD6C9, 0x79AE, 0xD6CA, 0x91B4, 0xD6CB, 0x96B7, 0xD6CC, 0x52DE,
+	0xD6CD, 0xF960, 0xD6CE, 0x6488, 0xD6CF, 0x64C4, 0xD6D0, 0x6AD3,
+	0xD6D1, 0x6F5E, 0xD6D2, 0x7018, 0xD6D3, 0x7210, 0xD6D4, 0x76E7,
+	0xD6D5, 0x8001, 0xD6D6, 0x8606, 0xD6D7, 0x865C, 0xD6D8, 0x8DEF,
+	0xD6D9, 0x8F05, 0xD6DA, 0x9732, 0xD6DB, 0x9B6F, 0xD6DC, 0x9DFA,
+	0xD6DD, 0x9E75, 0xD6DE, 0x788C, 0xD6DF, 0x797F, 0xD6E0, 0x7DA0,
+	0xD6E1, 0x83C9, 0xD6E2, 0x9304, 0xD6E3, 0x9E7F, 0xD6E4, 0x9E93,
+	0xD6E5, 0x8AD6, 0xD6E6, 0x58DF, 0xD6E7, 0x5F04, 0xD6E8, 0x6727,
+	0xD6E9, 0x7027, 0xD6EA, 0x74CF, 0xD6EB, 0x7C60, 0xD6EC, 0x807E,
+	0xD6ED, 0x5121, 0xD6EE, 0x7028, 0xD6EF, 0x7262, 0xD6F0, 0x78CA,
+	0xD6F1, 0x8CC2, 0xD6F2, 0x8CDA, 0xD6F3, 0x8CF4, 0xD6F4, 0x96F7,
+	0xD6F5, 0x4E86, 0xD6F6, 0x50DA, 0xD6F7, 0x5BEE, 0xD6F8, 0x5ED6,
+	0xD6F9, 0x6599, 0xD6FA, 0x71CE, 0xD6FB, 0x7642, 0xD6FC, 0x77AD,
+	0xD6FD, 0x804A, 0xD6FE, 0x84FC, 0xD7A1, 0x907C, 0xD7A2, 0x9B27,
+	0xD7A3, 0x9F8D, 0xD7A4, 0x58D8, 0xD7A5, 0x5A41, 0xD7A6, 0x5C62,
+	0xD7A7, 0x6A13, 0xD7A8, 0x6DDA, 0xD7A9, 0x6F0F, 0xD7AA, 0x763B,
+	0xD7AB, 0x7D2F, 0xD7AC, 0x7E37, 0xD7AD, 0x851E, 0xD7AE, 0x8938,
+	0xD7AF, 0x93E4, 0xD7B0, 0x964B, 0xD7B1, 0x5289, 0xD7B2, 0x65D2,
+	0xD7B3, 0x67F3, 0xD7B4, 0x69B4, 0xD7B5, 0x6D41, 0xD7B6, 0x6E9C,
+	0xD7B7, 0x700F, 0xD7B8, 0x7409, 0xD7B9, 0x7460, 0xD7BA, 0x7559,
+	0xD7BB, 0x7624, 0xD7BC, 0x786B, 0xD7BD, 0x8B2C, 0xD7BE, 0x985E,
+	0xD7BF, 0x516D, 0xD7C0, 0x622E, 0xD7C1, 0x9678, 0xD7C2, 0x4F96,
+	0xD7C3, 0x502B, 0xD7C4, 0x5D19, 0xD7C5, 0x6DEA, 0xD7C6, 0x7DB8,
+	0xD7C7, 0x8F2A, 0xD7C8, 0x5F8B, 0xD7C9, 0x6144, 0xD7CA, 0x6817,
+	0xD7CB, 0xF961, 0xD7CC, 0x9686, 0xD7CD, 0x52D2, 0xD7CE, 0x808B,
+	0xD7CF, 0x51DC, 0xD7D0, 0x51CC, 0xD7D1, 0x695E, 0xD7D2, 0x7A1C,
+	0xD7D3, 0x7DBE, 0xD7D4, 0x83F1, 0xD7D5, 0x9675, 0xD7D6, 0x4FDA,
+	0xD7D7, 0x5229, 0xD7D8, 0x5398, 0xD7D9, 0x540F, 0xD7DA, 0x550E,
+	0xD7DB, 0x5C65, 0xD7DC, 0x60A7, 0xD7DD, 0x674E, 0xD7DE, 0x68A8,
+	0xD7DF, 0x6D6C, 0xD7E0, 0x7281, 0xD7E1, 0x72F8, 0xD7E2, 0x7406,
+	0xD7E3, 0x7483, 0xD7E4, 0xF962, 0xD7E5, 0x75E2, 0xD7E6, 0x7C6C,
+	0xD7E7, 0x7F79, 0xD7E8, 0x7FB8, 0xD7E9, 0x8389, 0xD7EA, 0x88CF,
+	0xD7EB, 0x88E1, 0xD7EC, 0x91CC, 0xD7ED, 0x91D0, 0xD7EE, 0x96E2,
+	0xD7EF, 0x9BC9, 0xD7F0, 0x541D, 0xD7F1, 0x6F7E, 0xD7F2, 0x71D0,
+	0xD7F3, 0x7498, 0xD7F4, 0x85FA, 0xD7F5, 0x8EAA, 0xD7F6, 0x96A3,
+	0xD7F7, 0x9C57, 0xD7F8, 0x9E9F, 0xD7F9, 0x6797, 0xD7FA, 0x6DCB,
+	0xD7FB, 0x7433, 0xD7FC, 0x81E8, 0xD7FD, 0x9716, 0xD7FE, 0x782C,
+	0xD8A1, 0x7ACB, 0xD8A2, 0x7B20, 0xD8A3, 0x7C92, 0xD8A4, 0x6469,
+	0xD8A5, 0x746A, 0xD8A6, 0x75F2, 0xD8A7, 0x78BC, 0xD8A8, 0x78E8,
+	0xD8A9, 0x99AC, 0xD8AA, 0x9B54, 0xD8AB, 0x9EBB, 0xD8AC, 0x5BDE,
+	0xD8AD, 0x5E55, 0xD8AE, 0x6F20, 0xD8AF, 0x819C, 0xD8B0, 0x83AB,
+	0xD8B1, 0x9088, 0xD8B2, 0x4E07, 0xD8B3, 0x534D, 0xD8B4, 0x5A29,
+	0xD8B5, 0x5DD2, 0xD8B6, 0x5F4E, 0xD8B7, 0x6162, 0xD8B8, 0x633D,
+	0xD8B9, 0x6669, 0xD8BA, 0x66FC, 0xD8BB, 0x6EFF, 0xD8BC, 0x6F2B,
+	0xD8BD, 0x7063, 0xD8BE, 0x779E, 0xD8BF, 0x842C, 0xD8C0, 0x8513,
+	0xD8C1, 0x883B, 0xD8C2, 0x8F13, 0xD8C3, 0x9945, 0xD8C4, 0x9C3B,
+	0xD8C5, 0x551C, 0xD8C6, 0x62B9, 0xD8C7, 0x672B, 0xD8C8, 0x6CAB,
+	0xD8C9, 0x8309, 0xD8CA, 0x896A, 0xD8CB, 0x977A, 0xD8CC, 0x4EA1,
+	0xD8CD, 0x5984, 0xD8CE, 0x5FD8, 0xD8CF, 0x5FD9, 0xD8D0, 0x671B,
+	0xD8D1, 0x7DB2, 0xD8D2, 0x7F54, 0xD8D3, 0x8292, 0xD8D4, 0x832B,
+	0xD8D5, 0x83BD, 0xD8D6, 0x8F1E, 0xD8D7, 0x9099, 0xD8D8, 0x57CB,
+	0xD8D9, 0x59B9, 0xD8DA, 0x5A92, 0xD8DB, 0x5BD0, 0xD8DC, 0x6627,
+	0xD8DD, 0x679A, 0xD8DE, 0x6885, 0xD8DF, 0x6BCF, 0xD8E0, 0x7164,
+	0xD8E1, 0x7F75, 0xD8E2, 0x8CB7, 0xD8E3, 0x8CE3, 0xD8E4, 0x9081,
+	0xD8E5, 0x9B45, 0xD8E6, 0x8108, 0xD8E7, 0x8C8A, 0xD8E8, 0x964C,
+	0xD8E9, 0x9A40, 0xD8EA, 0x9EA5, 0xD8EB, 0x5B5F, 0xD8EC, 0x6C13,
+	0xD8ED, 0x731B, 0xD8EE, 0x76F2, 0xD8EF, 0x76DF, 0xD8F0, 0x840C,
+	0xD8F1, 0x51AA, 0xD8F2, 0x8993, 0xD8F3, 0x514D, 0xD8F4, 0x5195,
+	0xD8F5, 0x52C9, 0xD8F6, 0x68C9, 0xD8F7, 0x6C94, 0xD8F8, 0x7704,
+	0xD8F9, 0x7720, 0xD8FA, 0x7DBF, 0xD8FB, 0x7DEC, 0xD8FC, 0x9762,
+	0xD8FD, 0x9EB5, 0xD8FE, 0x6EC5, 0xD9A1, 0x8511, 0xD9A2, 0x51A5,
+	0xD9A3, 0x540D, 0xD9A4, 0x547D, 0xD9A5, 0x660E, 0xD9A6, 0x669D,
+	0xD9A7, 0x6927, 0xD9A8, 0x6E9F, 0xD9A9, 0x76BF, 0xD9AA, 0x7791,
+	0xD9AB, 0x8317, 0xD9AC, 0x84C2, 0xD9AD, 0x879F, 0xD9AE, 0x9169,
+	0xD9AF, 0x9298, 0xD9B0, 0x9CF4, 0xD9B1, 0x8882, 0xD9B2, 0x4FAE,
+	0xD9B3, 0x5192, 0xD9B4, 0x52DF, 0xD9B5, 0x59C6, 0xD9B6, 0x5E3D,
+	0xD9B7, 0x6155, 0xD9B8, 0x6478, 0xD9B9, 0x6479, 0xD9BA, 0x66AE,
+	0xD9BB, 0x67D0, 0xD9BC, 0x6A21, 0xD9BD, 0x6BCD, 0xD9BE, 0x6BDB,
+	0xD9BF, 0x725F, 0xD9C0, 0x7261, 0xD9C1, 0x7441, 0xD9C2, 0x7738,
+	0xD9C3, 0x77DB, 0xD9C4, 0x8017, 0xD9C5, 0x82BC, 0xD9C6, 0x8305,
+	0xD9C7, 0x8B00, 0xD9C8, 0x8B28, 0xD9C9, 0x8C8C, 0xD9CA, 0x6728,
+	0xD9CB, 0x6C90, 0xD9CC, 0x7267, 0xD9CD, 0x76EE, 0xD9CE, 0x7766,
+	0xD9CF, 0x7A46, 0xD9D0, 0x9DA9, 0xD9D1, 0x6B7F, 0xD9D2, 0x6C92,
+	0xD9D3, 0x5922, 0xD9D4, 0x6726, 0xD9D5, 0x8499, 0xD9D6, 0x536F,
+	0xD9D7, 0x5893, 0xD9D8, 0x5999, 0xD9D9, 0x5EDF, 0xD9DA, 0x63CF,
+	0xD9DB, 0x6634, 0xD9DC, 0x6773, 0xD9DD, 0x6E3A, 0xD9DE, 0x732B,
+	0xD9DF, 0x7AD7, 0xD9E0, 0x82D7, 0xD9E1, 0x9328, 0xD9E2, 0x52D9,
+	0xD9E3, 0x5DEB, 0xD9E4, 0x61AE, 0xD9E5, 0x61CB, 0xD9E6, 0x620A,
+	0xD9E7, 0x62C7, 0xD9E8, 0x64AB, 0xD9E9, 0x65E0, 0xD9EA, 0x6959,
+	0xD9EB, 0x6B66, 0xD9EC, 0x6BCB, 0xD9ED, 0x7121, 0xD9EE, 0x73F7,
+	0xD9EF, 0x755D, 0xD9F0, 0x7E46, 0xD9F1, 0x821E, 0xD9F2, 0x8302,
+	0xD9F3, 0x856A, 0xD9F4, 0x8AA3, 0xD9F5, 0x8CBF, 0xD9F6, 0x9727,
+	0xD9F7, 0x9D61, 0xD9F8, 0x58A8, 0xD9F9, 0x9ED8, 0xD9FA, 0x5011,
+	0xD9FB, 0x520E, 0xD9FC, 0x543B, 0xD9FD, 0x554F, 0xD9FE, 0x6587,
+	0xDAA1, 0x6C76, 0xDAA2, 0x7D0A, 0xDAA3, 0x7D0B, 0xDAA4, 0x805E,
+	0xDAA5, 0x868A, 0xDAA6, 0x9580, 0xDAA7, 0x96EF, 0xDAA8, 0x52FF,
+	0xDAA9, 0x6C95, 0xDAAA, 0x7269, 0xDAAB, 0x5473, 0xDAAC, 0x5A9A,
+	0xDAAD, 0x5C3E, 0xDAAE, 0x5D4B, 0xDAAF, 0x5F4C, 0xDAB0, 0x5FAE,
+	0xDAB1, 0x672A, 0xDAB2, 0x68B6, 0xDAB3, 0x6963, 0xDAB4, 0x6E3C,
+	0xDAB5, 0x6E44, 0xDAB6, 0x7709, 0xDAB7, 0x7C73, 0xDAB8, 0x7F8E,
+	0xDAB9, 0x8587, 0xDABA, 0x8B0E, 0xDABB, 0x8FF7, 0xDABC, 0x9761,
+	0xDABD, 0x9EF4, 0xDABE, 0x5CB7, 0xDABF, 0x60B6, 0xDAC0, 0x610D,
+	0xDAC1, 0x61AB, 0xDAC2, 0x654F, 0xDAC3, 0x65FB, 0xDAC4, 0x65FC,
+	0xDAC5, 0x6C11, 0xDAC6, 0x6CEF, 0xDAC7, 0x739F, 0xDAC8, 0x73C9,
+	0xDAC9, 0x7DE1, 0xDACA, 0x9594, 0xDACB, 0x5BC6, 0xDACC, 0x871C,
+	0xDACD, 0x8B10, 0xDACE, 0x525D, 0xDACF, 0x535A, 0xDAD0, 0x62CD,
+	0xDAD1, 0x640F, 0xDAD2, 0x64B2, 0xDAD3, 0x6734, 0xDAD4, 0x6A38,
+	0xDAD5, 0x6CCA, 0xDAD6, 0x73C0, 0xDAD7, 0x749E, 0xDAD8, 0x7B94,
+	0xDAD9, 0x7C95, 0xDADA, 0x7E1B, 0xDADB, 0x818A, 0xDADC, 0x8236,
+	0xDADD, 0x8584, 0xDADE, 0x8FEB, 0xDADF, 0x96F9, 0xDAE0, 0x99C1,
+	0xDAE1, 0x4F34, 0xDAE2, 0x534A, 0xDAE3, 0x53CD, 0xDAE4, 0x53DB,
+	0xDAE5, 0x62CC, 0xDAE6, 0x642C, 0xDAE7, 0x6500, 0xDAE8, 0x6591,
+	0xDAE9, 0x69C3, 0xDAEA, 0x6CEE, 0xDAEB, 0x6F58, 0xDAEC, 0x73ED,
+	0xDAED, 0x7554, 0xDAEE, 0x7622, 0xDAEF, 0x76E4, 0xDAF0, 0x76FC,
+	0xDAF1, 0x78D0, 0xDAF2, 0x78FB, 0xDAF3, 0x792C, 0xDAF4, 0x7D46,
+	0xDAF5, 0x822C, 0xDAF6, 0x87E0, 0xDAF7, 0x8FD4, 0xDAF8, 0x9812,
+	0xDAF9, 0x98EF, 0xDAFA, 0x52C3, 0xDAFB, 0x62D4, 0xDAFC, 0x64A5,
+	0xDAFD, 0x6E24, 0xDAFE, 0x6F51, 0xDBA1, 0x767C, 0xDBA2, 0x8DCB,
+	0xDBA3, 0x91B1, 0xDBA4, 0x9262, 0xDBA5, 0x9AEE, 0xDBA6, 0x9B43,
+	0xDBA7, 0x5023, 0xDBA8, 0x508D, 0xDBA9, 0x574A, 0xDBAA, 0x59A8,
+	0xDBAB, 0x5C28, 0xDBAC, 0x5E47, 0xDBAD, 0x5F77, 0xDBAE, 0x623F,
+	0xDBAF, 0x653E, 0xDBB0, 0x65B9, 0xDBB1, 0x65C1, 0xDBB2, 0x6609,
+	0xDBB3, 0x678B, 0xDBB4, 0x699C, 0xDBB5, 0x6EC2, 0xDBB6, 0x78C5,
+	0xDBB7, 0x7D21, 0xDBB8, 0x80AA, 0xDBB9, 0x8180, 0xDBBA, 0x822B,
+	0xDBBB, 0x82B3, 0xDBBC, 0x84A1, 0xDBBD, 0x868C, 0xDBBE, 0x8A2A,
+	0xDBBF, 0x8B17, 0xDBC0, 0x90A6, 0xDBC1, 0x9632, 0xDBC2, 0x9F90,
+	0xDBC3, 0x500D, 0xDBC4, 0x4FF3, 0xDBC5, 0xF963, 0xDBC6, 0x57F9,
+	0xDBC7, 0x5F98, 0xDBC8, 0x62DC, 0xDBC9, 0x6392, 0xDBCA, 0x676F,
+	0xDBCB, 0x6E43, 0xDBCC, 0x7119, 0xDBCD, 0x76C3, 0xDBCE, 0x80CC,
+	0xDBCF, 0x80DA, 0xDBD0, 0x88F4, 0xDBD1, 0x88F5, 0xDBD2, 0x8919,
+	0xDBD3, 0x8CE0, 0xDBD4, 0x8F29, 0xDBD5, 0x914D, 0xDBD6, 0x966A,
+	0xDBD7, 0x4F2F, 0xDBD8, 0x4F70, 0xDBD9, 0x5E1B, 0xDBDA, 0x67CF,
+	0xDBDB, 0x6822, 0xDBDC, 0x767D, 0xDBDD, 0x767E, 0xDBDE, 0x9B44,
+	0xDBDF, 0x5E61, 0xDBE0, 0x6A0A, 0xDBE1, 0x7169, 0xDBE2, 0x71D4,
+	0xDBE3, 0x756A, 0xDBE4, 0xF964, 0xDBE5, 0x7E41, 0xDBE6, 0x8543,
+	0xDBE7, 0x85E9, 0xDBE8, 0x98DC, 0xDBE9, 0x4F10, 0xDBEA, 0x7B4F,
+	0xDBEB, 0x7F70, 0xDBEC, 0x95A5, 0xDBED, 0x51E1, 0xDBEE, 0x5E06,
+	0xDBEF, 0x68B5, 0xDBF0, 0x6C3E, 0xDBF1, 0x6C4E, 0xDBF2, 0x6CDB,
+	0xDBF3, 0x72AF, 0xDBF4, 0x7BC4, 0xDBF5, 0x8303, 0xDBF6, 0x6CD5,
+	0xDBF7, 0x743A, 0xDBF8, 0x50FB, 0xDBF9, 0x5288, 0xDBFA, 0x58C1,
+	0xDBFB, 0x64D8, 0xDBFC, 0x6A97, 0xDBFD, 0x74A7, 0xDBFE, 0x7656,
+	0xDCA1, 0x78A7, 0xDCA2, 0x8617, 0xDCA3, 0x95E2, 0xDCA4, 0x9739,
+	0xDCA5, 0xF965, 0xDCA6, 0x535E, 0xDCA7, 0x5F01, 0xDCA8, 0x8B8A,
+	0xDCA9, 0x8FA8, 0xDCAA, 0x8FAF, 0xDCAB, 0x908A, 0xDCAC, 0x5225,
+	0xDCAD, 0x77A5, 0xDCAE, 0x9C49, 0xDCAF, 0x9F08, 0xDCB0, 0x4E19,
+	0xDCB1, 0x5002, 0xDCB2, 0x5175, 0xDCB3, 0x5C5B, 0xDCB4, 0x5E77,
+	0xDCB5, 0x661E, 0xDCB6, 0x663A, 0xDCB7, 0x67C4, 0xDCB8, 0x68C5,
+	0xDCB9, 0x70B3, 0xDCBA, 0x7501, 0xDCBB, 0x75C5, 0xDCBC, 0x79C9,
+	0xDCBD, 0x7ADD, 0xDCBE, 0x8F27, 0xDCBF, 0x9920, 0xDCC0, 0x9A08,
+	0xDCC1, 0x4FDD, 0xDCC2, 0x5821, 0xDCC3, 0x5831, 0xDCC4, 0x5BF6,
+	0xDCC5, 0x666E, 0xDCC6, 0x6B65, 0xDCC7, 0x6D11, 0xDCC8, 0x6E7A,
+	0xDCC9, 0x6F7D, 0xDCCA, 0x73E4, 0xDCCB, 0x752B, 0xDCCC, 0x83E9,
+	0xDCCD, 0x88DC, 0xDCCE, 0x8913, 0xDCCF, 0x8B5C, 0xDCD0, 0x8F14,
+	0xDCD1, 0x4F0F, 0xDCD2, 0x50D5, 0xDCD3, 0x5310, 0xDCD4, 0x535C,
+	0xDCD5, 0x5B93, 0xDCD6, 0x5FA9, 0xDCD7, 0x670D, 0xDCD8, 0x798F,
+	0xDCD9, 0x8179, 0xDCDA, 0x832F, 0xDCDB, 0x8514, 0xDCDC, 0x8907,
+	0xDCDD, 0x8986, 0xDCDE, 0x8F39, 0xDCDF, 0x8F3B, 0xDCE0, 0x99A5,
+	0xDCE1, 0x9C12, 0xDCE2, 0x672C, 0xDCE3, 0x4E76, 0xDCE4, 0x4FF8,
+	0xDCE5, 0x5949, 0xDCE6, 0x5C01, 0xDCE7, 0x5CEF, 0xDCE8, 0x5CF0,
+	0xDCE9, 0x6367, 0xDCEA, 0x68D2, 0xDCEB, 0x70FD, 0xDCEC, 0x71A2,
+	0xDCED, 0x742B, 0xDCEE, 0x7E2B, 0xDCEF, 0x84EC, 0xDCF0, 0x8702,
+	0xDCF1, 0x9022, 0xDCF2, 0x92D2, 0xDCF3, 0x9CF3, 0xDCF4, 0x4E0D,
+	0xDCF5, 0x4ED8, 0xDCF6, 0x4FEF, 0xDCF7, 0x5085, 0xDCF8, 0x5256,
+	0xDCF9, 0x526F, 0xDCFA, 0x5426, 0xDCFB, 0x5490, 0xDCFC, 0x57E0,
+	0xDCFD, 0x592B, 0xDCFE, 0x5A66, 0xDDA1, 0x5B5A, 0xDDA2, 0x5B75,
+	0xDDA3, 0x5BCC, 0xDDA4, 0x5E9C, 0xDDA5, 0xF966, 0xDDA6, 0x6276,
+	0xDDA7, 0x6577, 0xDDA8, 0x65A7, 0xDDA9, 0x6D6E, 0xDDAA, 0x6EA5,
+	0xDDAB, 0x7236, 0xDDAC, 0x7B26, 0xDDAD, 0x7C3F, 0xDDAE, 0x7F36,
+	0xDDAF, 0x8150, 0xDDB0, 0x8151, 0xDDB1, 0x819A, 0xDDB2, 0x8240,
+	0xDDB3, 0x8299, 0xDDB4, 0x83A9, 0xDDB5, 0x8A03, 0xDDB6, 0x8CA0,
+	0xDDB7, 0x8CE6, 0xDDB8, 0x8CFB, 0xDDB9, 0x8D74, 0xDDBA, 0x8DBA,
+	0xDDBB, 0x90E8, 0xDDBC, 0x91DC, 0xDDBD, 0x961C, 0xDDBE, 0x9644,
+	0xDDBF, 0x99D9, 0xDDC0, 0x9CE7, 0xDDC1, 0x5317, 0xDDC2, 0x5206,
+	0xDDC3, 0x5429, 0xDDC4, 0x5674, 0xDDC5, 0x58B3, 0xDDC6, 0x5954,
+	0xDDC7, 0x596E, 0xDDC8, 0x5FFF, 0xDDC9, 0x61A4, 0xDDCA, 0x626E,
+	0xDDCB, 0x6610, 0xDDCC, 0x6C7E, 0xDDCD, 0x711A, 0xDDCE, 0x76C6,
+	0xDDCF, 0x7C89, 0xDDD0, 0x7CDE, 0xDDD1, 0x7D1B, 0xDDD2, 0x82AC,
+	0xDDD3, 0x8CC1, 0xDDD4, 0x96F0, 0xDDD5, 0xF967, 0xDDD6, 0x4F5B,
+	0xDDD7, 0x5F17, 0xDDD8, 0x5F7F, 0xDDD9, 0x62C2, 0xDDDA, 0x5D29,
+	0xDDDB, 0x670B, 0xDDDC, 0x68DA, 0xDDDD, 0x787C, 0xDDDE, 0x7E43,
+	0xDDDF, 0x9D6C, 0xDDE0, 0x4E15, 0xDDE1, 0x5099, 0xDDE2, 0x5315,
+	0xDDE3, 0x532A, 0xDDE4, 0x5351, 0xDDE5, 0x5983, 0xDDE6, 0x5A62,
+	0xDDE7, 0x5E87, 0xDDE8, 0x60B2, 0xDDE9, 0x618A, 0xDDEA, 0x6249,
+	0xDDEB, 0x6279, 0xDDEC, 0x6590, 0xDDED, 0x6787, 0xDDEE, 0x69A7,
+	0xDDEF, 0x6BD4, 0xDDF0, 0x6BD6, 0xDDF1, 0x6BD7, 0xDDF2, 0x6BD8,
+	0xDDF3, 0x6CB8, 0xDDF4, 0xF968, 0xDDF5, 0x7435, 0xDDF6, 0x75FA,
+	0xDDF7, 0x7812, 0xDDF8, 0x7891, 0xDDF9, 0x79D5, 0xDDFA, 0x79D8,
+	0xDDFB, 0x7C83, 0xDDFC, 0x7DCB, 0xDDFD, 0x7FE1, 0xDDFE, 0x80A5,
+	0xDEA1, 0x813E, 0xDEA2, 0x81C2, 0xDEA3, 0x83F2, 0xDEA4, 0x871A,
+	0xDEA5, 0x88E8, 0xDEA6, 0x8AB9, 0xDEA7, 0x8B6C, 0xDEA8, 0x8CBB,
+	0xDEA9, 0x9119, 0xDEAA, 0x975E, 0xDEAB, 0x98DB, 0xDEAC, 0x9F3B,
+	0xDEAD, 0x56AC, 0xDEAE, 0x5B2A, 0xDEAF, 0x5F6C, 0xDEB0, 0x658C,
+	0xDEB1, 0x6AB3, 0xDEB2, 0x6BAF, 0xDEB3, 0x6D5C, 0xDEB4, 0x6FF1,
+	0xDEB5, 0x7015, 0xDEB6, 0x725D, 0xDEB7, 0x73AD, 0xDEB8, 0x8CA7,
+	0xDEB9, 0x8CD3, 0xDEBA, 0x983B, 0xDEBB, 0x6191, 0xDEBC, 0x6C37,
+	0xDEBD, 0x8058, 0xDEBE, 0x9A01, 0xDEBF, 0x4E4D, 0xDEC0, 0x4E8B,
+	0xDEC1, 0x4E9B, 0xDEC2, 0x4ED5, 0xDEC3, 0x4F3A, 0xDEC4, 0x4F3C,
+	0xDEC5, 0x4F7F, 0xDEC6, 0x4FDF, 0xDEC7, 0x50FF, 0xDEC8, 0x53F2,
+	0xDEC9, 0x53F8, 0xDECA, 0x5506, 0xDECB, 0x55E3, 0xDECC, 0x56DB,
+	0xDECD, 0x58EB, 0xDECE, 0x5962, 0xDECF, 0x5A11, 0xDED0, 0x5BEB,
+	0xDED1, 0x5BFA, 0xDED2, 0x5C04, 0xDED3, 0x5DF3, 0xDED4, 0x5E2B,
+	0xDED5, 0x5F99, 0xDED6, 0x601D, 0xDED7, 0x6368, 0xDED8, 0x659C,
+	0xDED9, 0x65AF, 0xDEDA, 0x67F6, 0xDEDB, 0x67FB, 0xDEDC, 0x68AD,
+	0xDEDD, 0x6B7B, 0xDEDE, 0x6C99, 0xDEDF, 0x6CD7, 0xDEE0, 0x6E23,
+	0xDEE1, 0x7009, 0xDEE2, 0x7345, 0xDEE3, 0x7802, 0xDEE4, 0x793E,
+	0xDEE5, 0x7940, 0xDEE6, 0x7960, 0xDEE7, 0x79C1, 0xDEE8, 0x7BE9,
+	0xDEE9, 0x7D17, 0xDEEA, 0x7D72, 0xDEEB, 0x8086, 0xDEEC, 0x820D,
+	0xDEED, 0x838E, 0xDEEE, 0x84D1, 0xDEEF, 0x86C7, 0xDEF0, 0x88DF,
+	0xDEF1, 0x8A50, 0xDEF2, 0x8A5E, 0xDEF3, 0x8B1D, 0xDEF4, 0x8CDC,
+	0xDEF5, 0x8D66, 0xDEF6, 0x8FAD, 0xDEF7, 0x90AA, 0xDEF8, 0x98FC,
+	0xDEF9, 0x99DF, 0xDEFA, 0x9E9D, 0xDEFB, 0x524A, 0xDEFC, 0xF969,
+	0xDEFD, 0x6714, 0xDEFE, 0xF96A, 0xDFA1, 0x5098, 0xDFA2, 0x522A,
+	0xDFA3, 0x5C71, 0xDFA4, 0x6563, 0xDFA5, 0x6C55, 0xDFA6, 0x73CA,
+	0xDFA7, 0x7523, 0xDFA8, 0x759D, 0xDFA9, 0x7B97, 0xDFAA, 0x849C,
+	0xDFAB, 0x9178, 0xDFAC, 0x9730, 0xDFAD, 0x4E77, 0xDFAE, 0x6492,
+	0xDFAF, 0x6BBA, 0xDFB0, 0x715E, 0xDFB1, 0x85A9, 0xDFB2, 0x4E09,
+	0xDFB3, 0xF96B, 0xDFB4, 0x6749, 0xDFB5, 0x68EE, 0xDFB6, 0x6E17,
+	0xDFB7, 0x829F, 0xDFB8, 0x8518, 0xDFB9, 0x886B, 0xDFBA, 0x63F7,
+	0xDFBB, 0x6F81, 0xDFBC, 0x9212, 0xDFBD, 0x98AF, 0xDFBE, 0x4E0A,
+	0xDFBF, 0x50B7, 0xDFC0, 0x50CF, 0xDFC1, 0x511F, 0xDFC2, 0x5546,
+	0xDFC3, 0x55AA, 0xDFC4, 0x5617, 0xDFC5, 0x5B40, 0xDFC6, 0x5C19,
+	0xDFC7, 0x5CE0, 0xDFC8, 0x5E38, 0xDFC9, 0x5E8A, 0xDFCA, 0x5EA0,
+	0xDFCB, 0x5EC2, 0xDFCC, 0x60F3, 0xDFCD, 0x6851, 0xDFCE, 0x6A61,
+	0xDFCF, 0x6E58, 0xDFD0, 0x723D, 0xDFD1, 0x7240, 0xDFD2, 0x72C0,
+	0xDFD3, 0x76F8, 0xDFD4, 0x7965, 0xDFD5, 0x7BB1, 0xDFD6, 0x7FD4,
+	0xDFD7, 0x88F3, 0xDFD8, 0x89F4, 0xDFD9, 0x8A73, 0xDFDA, 0x8C61,
+	0xDFDB, 0x8CDE, 0xDFDC, 0x971C, 0xDFDD, 0x585E, 0xDFDE, 0x74BD,
+	0xDFDF, 0x8CFD, 0xDFE0, 0x55C7, 0xDFE1, 0xF96C, 0xDFE2, 0x7A61,
+	0xDFE3, 0x7D22, 0xDFE4, 0x8272, 0xDFE5, 0x7272, 0xDFE6, 0x751F,
+	0xDFE7, 0x7525, 0xDFE8, 0xF96D, 0xDFE9, 0x7B19, 0xDFEA, 0x5885,
+	0xDFEB, 0x58FB, 0xDFEC, 0x5DBC, 0xDFED, 0x5E8F, 0xDFEE, 0x5EB6,
+	0xDFEF, 0x5F90, 0xDFF0, 0x6055, 0xDFF1, 0x6292, 0xDFF2, 0x637F,
+	0xDFF3, 0x654D, 0xDFF4, 0x6691, 0xDFF5, 0x66D9, 0xDFF6, 0x66F8,
+	0xDFF7, 0x6816, 0xDFF8, 0x68F2, 0xDFF9, 0x7280, 0xDFFA, 0x745E,
+	0xDFFB, 0x7B6E, 0xDFFC, 0x7D6E, 0xDFFD, 0x7DD6, 0xDFFE, 0x7F72,
+	0xE0A1, 0x80E5, 0xE0A2, 0x8212, 0xE0A3, 0x85AF, 0xE0A4, 0x897F,
+	0xE0A5, 0x8A93, 0xE0A6, 0x901D, 0xE0A7, 0x92E4, 0xE0A8, 0x9ECD,
+	0xE0A9, 0x9F20, 0xE0AA, 0x5915, 0xE0AB, 0x596D, 0xE0AC, 0x5E2D,
+	0xE0AD, 0x60DC, 0xE0AE, 0x6614, 0xE0AF, 0x6673, 0xE0B0, 0x6790,
+	0xE0B1, 0x6C50, 0xE0B2, 0x6DC5, 0xE0B3, 0x6F5F, 0xE0B4, 0x77F3,
+	0xE0B5, 0x78A9, 0xE0B6, 0x84C6, 0xE0B7, 0x91CB, 0xE0B8, 0x932B,
+	0xE0B9, 0x4ED9, 0xE0BA, 0x50CA, 0xE0BB, 0x5148, 0xE0BC, 0x5584,
+	0xE0BD, 0x5B0B, 0xE0BE, 0x5BA3, 0xE0BF, 0x6247, 0xE0C0, 0x657E,
+	0xE0C1, 0x65CB, 0xE0C2, 0x6E32, 0xE0C3, 0x717D, 0xE0C4, 0x7401,
+	0xE0C5, 0x7444, 0xE0C6, 0x7487, 0xE0C7, 0x74BF, 0xE0C8, 0x766C,
+	0xE0C9, 0x79AA, 0xE0CA, 0x7DDA, 0xE0CB, 0x7E55, 0xE0CC, 0x7FA8,
+	0xE0CD, 0x817A, 0xE0CE, 0x81B3, 0xE0CF, 0x8239, 0xE0D0, 0x861A,
+	0xE0D1, 0x87EC, 0xE0D2, 0x8A75, 0xE0D3, 0x8DE3, 0xE0D4, 0x9078,
+	0xE0D5, 0x9291, 0xE0D6, 0x9425, 0xE0D7, 0x994D, 0xE0D8, 0x9BAE,
+	0xE0D9, 0x5368, 0xE0DA, 0x5C51, 0xE0DB, 0x6954, 0xE0DC, 0x6CC4,
+	0xE0DD, 0x6D29, 0xE0DE, 0x6E2B, 0xE0DF, 0x820C, 0xE0E0, 0x859B,
+	0xE0E1, 0x893B, 0xE0E2, 0x8A2D, 0xE0E3, 0x8AAA, 0xE0E4, 0x96EA,
+	0xE0E5, 0x9F67, 0xE0E6, 0x5261, 0xE0E7, 0x66B9, 0xE0E8, 0x6BB2,
+	0xE0E9, 0x7E96, 0xE0EA, 0x87FE, 0xE0EB, 0x8D0D, 0xE0EC, 0x9583,
+	0xE0ED, 0x965D, 0xE0EE, 0x651D, 0xE0EF, 0x6D89, 0xE0F0, 0x71EE,
+	0xE0F1, 0xF96E, 0xE0F2, 0x57CE, 0xE0F3, 0x59D3, 0xE0F4, 0x5BAC,
+	0xE0F5, 0x6027, 0xE0F6, 0x60FA, 0xE0F7, 0x6210, 0xE0F8, 0x661F,
+	0xE0F9, 0x665F, 0xE0FA, 0x7329, 0xE0FB, 0x73F9, 0xE0FC, 0x76DB,
+	0xE0FD, 0x7701, 0xE0FE, 0x7B6C, 0xE1A1, 0x8056, 0xE1A2, 0x8072,
+	0xE1A3, 0x8165, 0xE1A4, 0x8AA0, 0xE1A5, 0x9192, 0xE1A6, 0x4E16,
+	0xE1A7, 0x52E2, 0xE1A8, 0x6B72, 0xE1A9, 0x6D17, 0xE1AA, 0x7A05,
+	0xE1AB, 0x7B39, 0xE1AC, 0x7D30, 0xE1AD, 0xF96F, 0xE1AE, 0x8CB0,
+	0xE1AF, 0x53EC, 0xE1B0, 0x562F, 0xE1B1, 0x5851, 0xE1B2, 0x5BB5,
+	0xE1B3, 0x5C0F, 0xE1B4, 0x5C11, 0xE1B5, 0x5DE2, 0xE1B6, 0x6240,
+	0xE1B7, 0x6383, 0xE1B8, 0x6414, 0xE1B9, 0x662D, 0xE1BA, 0x68B3,
+	0xE1BB, 0x6CBC, 0xE1BC, 0x6D88, 0xE1BD, 0x6EAF, 0xE1BE, 0x701F,
+	0xE1BF, 0x70A4, 0xE1C0, 0x71D2, 0xE1C1, 0x7526, 0xE1C2, 0x758F,
+	0xE1C3, 0x758E, 0xE1C4, 0x7619, 0xE1C5, 0x7B11, 0xE1C6, 0x7BE0,
+	0xE1C7, 0x7C2B, 0xE1C8, 0x7D20, 0xE1C9, 0x7D39, 0xE1CA, 0x852C,
+	0xE1CB, 0x856D, 0xE1CC, 0x8607, 0xE1CD, 0x8A34, 0xE1CE, 0x900D,
+	0xE1CF, 0x9061, 0xE1D0, 0x90B5, 0xE1D1, 0x92B7, 0xE1D2, 0x97F6,
+	0xE1D3, 0x9A37, 0xE1D4, 0x4FD7, 0xE1D5, 0x5C6C, 0xE1D6, 0x675F,
+	0xE1D7, 0x6D91, 0xE1D8, 0x7C9F, 0xE1D9, 0x7E8C, 0xE1DA, 0x8B16,
+	0xE1DB, 0x8D16, 0xE1DC, 0x901F, 0xE1DD, 0x5B6B, 0xE1DE, 0x5DFD,
+	0xE1DF, 0x640D, 0xE1E0, 0x84C0, 0xE1E1, 0x905C, 0xE1E2, 0x98E1,
+	0xE1E3, 0x7387, 0xE1E4, 0x5B8B, 0xE1E5, 0x609A, 0xE1E6, 0x677E,
+	0xE1E7, 0x6DDE, 0xE1E8, 0x8A1F, 0xE1E9, 0x8AA6, 0xE1EA, 0x9001,
+	0xE1EB, 0x980C, 0xE1EC, 0x5237, 0xE1ED, 0xF970, 0xE1EE, 0x7051,
+	0xE1EF, 0x788E, 0xE1F0, 0x9396, 0xE1F1, 0x8870, 0xE1F2, 0x91D7,
+	0xE1F3, 0x4FEE, 0xE1F4, 0x53D7, 0xE1F5, 0x55FD, 0xE1F6, 0x56DA,
+	0xE1F7, 0x5782, 0xE1F8, 0x58FD, 0xE1F9, 0x5AC2, 0xE1FA, 0x5B88,
+	0xE1FB, 0x5CAB, 0xE1FC, 0x5CC0, 0xE1FD, 0x5E25, 0xE1FE, 0x6101,
+	0xE2A1, 0x620D, 0xE2A2, 0x624B, 0xE2A3, 0x6388, 0xE2A4, 0x641C,
+	0xE2A5, 0x6536, 0xE2A6, 0x6578, 0xE2A7, 0x6A39, 0xE2A8, 0x6B8A,
+	0xE2A9, 0x6C34, 0xE2AA, 0x6D19, 0xE2AB, 0x6F31, 0xE2AC, 0x71E7,
+	0xE2AD, 0x72E9, 0xE2AE, 0x7378, 0xE2AF, 0x7407, 0xE2B0, 0x74B2,
+	0xE2B1, 0x7626, 0xE2B2, 0x7761, 0xE2B3, 0x79C0, 0xE2B4, 0x7A57,
+	0xE2B5, 0x7AEA, 0xE2B6, 0x7CB9, 0xE2B7, 0x7D8F, 0xE2B8, 0x7DAC,
+	0xE2B9, 0x7E61, 0xE2BA, 0x7F9E, 0xE2BB, 0x8129, 0xE2BC, 0x8331,
+	0xE2BD, 0x8490, 0xE2BE, 0x84DA, 0xE2BF, 0x85EA, 0xE2C0, 0x8896,
+	0xE2C1, 0x8AB0, 0xE2C2, 0x8B90, 0xE2C3, 0x8F38, 0xE2C4, 0x9042,
+	0xE2C5, 0x9083, 0xE2C6, 0x916C, 0xE2C7, 0x9296, 0xE2C8, 0x92B9,
+	0xE2C9, 0x968B, 0xE2CA, 0x96A7, 0xE2CB, 0x96A8, 0xE2CC, 0x96D6,
+	0xE2CD, 0x9700, 0xE2CE, 0x9808, 0xE2CF, 0x9996, 0xE2D0, 0x9AD3,
+	0xE2D1, 0x9B1A, 0xE2D2, 0x53D4, 0xE2D3, 0x587E, 0xE2D4, 0x5919,
+	0xE2D5, 0x5B70, 0xE2D6, 0x5BBF, 0xE2D7, 0x6DD1, 0xE2D8, 0x6F5A,
+	0xE2D9, 0x719F, 0xE2DA, 0x7421, 0xE2DB, 0x74B9, 0xE2DC, 0x8085,
+	0xE2DD, 0x83FD, 0xE2DE, 0x5DE1, 0xE2DF, 0x5F87, 0xE2E0, 0x5FAA,
+	0xE2E1, 0x6042, 0xE2E2, 0x65EC, 0xE2E3, 0x6812, 0xE2E4, 0x696F,
+	0xE2E5, 0x6A53, 0xE2E6, 0x6B89, 0xE2E7, 0x6D35, 0xE2E8, 0x6DF3,
+	0xE2E9, 0x73E3, 0xE2EA, 0x76FE, 0xE2EB, 0x77AC, 0xE2EC, 0x7B4D,
+	0xE2ED, 0x7D14, 0xE2EE, 0x8123, 0xE2EF, 0x821C, 0xE2F0, 0x8340,
+	0xE2F1, 0x84F4, 0xE2F2, 0x8563, 0xE2F3, 0x8A62, 0xE2F4, 0x8AC4,
+	0xE2F5, 0x9187, 0xE2F6, 0x931E, 0xE2F7, 0x9806, 0xE2F8, 0x99B4,
+	0xE2F9, 0x620C, 0xE2FA, 0x8853, 0xE2FB, 0x8FF0, 0xE2FC, 0x9265,
+	0xE2FD, 0x5D07, 0xE2FE, 0x5D27, 0xE3A1, 0x5D69, 0xE3A2, 0x745F,
+	0xE3A3, 0x819D, 0xE3A4, 0x8768, 0xE3A5, 0x6FD5, 0xE3A6, 0x62FE,
+	0xE3A7, 0x7FD2, 0xE3A8, 0x8936, 0xE3A9, 0x8972, 0xE3AA, 0x4E1E,
+	0xE3AB, 0x4E58, 0xE3AC, 0x50E7, 0xE3AD, 0x52DD, 0xE3AE, 0x5347,
+	0xE3AF, 0x627F, 0xE3B0, 0x6607, 0xE3B1, 0x7E69, 0xE3B2, 0x8805,
+	0xE3B3, 0x965E, 0xE3B4, 0x4F8D, 0xE3B5, 0x5319, 0xE3B6, 0x5636,
+	0xE3B7, 0x59CB, 0xE3B8, 0x5AA4, 0xE3B9, 0x5C38, 0xE3BA, 0x5C4E,
+	0xE3BB, 0x5C4D, 0xE3BC, 0x5E02, 0xE3BD, 0x5F11, 0xE3BE, 0x6043,
+	0xE3BF, 0x65BD, 0xE3C0, 0x662F, 0xE3C1, 0x6642, 0xE3C2, 0x67BE,
+	0xE3C3, 0x67F4, 0xE3C4, 0x731C, 0xE3C5, 0x77E2, 0xE3C6, 0x793A,
+	0xE3C7, 0x7FC5, 0xE3C8, 0x8494, 0xE3C9, 0x84CD, 0xE3CA, 0x8996,
+	0xE3CB, 0x8A66, 0xE3CC, 0x8A69, 0xE3CD, 0x8AE1, 0xE3CE, 0x8C55,
+	0xE3CF, 0x8C7A, 0xE3D0, 0x57F4, 0xE3D1, 0x5BD4, 0xE3D2, 0x5F0F,
+	0xE3D3, 0x606F, 0xE3D4, 0x62ED, 0xE3D5, 0x690D, 0xE3D6, 0x6B96,
+	0xE3D7, 0x6E5C, 0xE3D8, 0x7184, 0xE3D9, 0x7BD2, 0xE3DA, 0x8755,
+	0xE3DB, 0x8B58, 0xE3DC, 0x8EFE, 0xE3DD, 0x98DF, 0xE3DE, 0x98FE,
+	0xE3DF, 0x4F38, 0xE3E0, 0x4F81, 0xE3E1, 0x4FE1, 0xE3E2, 0x547B,
+	0xE3E3, 0x5A20, 0xE3E4, 0x5BB8, 0xE3E5, 0x613C, 0xE3E6, 0x65B0,
+	0xE3E7, 0x6668, 0xE3E8, 0x71FC, 0xE3E9, 0x7533, 0xE3EA, 0x795E,
+	0xE3EB, 0x7D33, 0xE3EC, 0x814E, 0xE3ED, 0x81E3, 0xE3EE, 0x8398,
+	0xE3EF, 0x85AA, 0xE3F0, 0x85CE, 0xE3F1, 0x8703, 0xE3F2, 0x8A0A,
+	0xE3F3, 0x8EAB, 0xE3F4, 0x8F9B, 0xE3F5, 0xF971, 0xE3F6, 0x8FC5,
+	0xE3F7, 0x5931, 0xE3F8, 0x5BA4, 0xE3F9, 0x5BE6, 0xE3FA, 0x6089,
+	0xE3FB, 0x5BE9, 0xE3FC, 0x5C0B, 0xE3FD, 0x5FC3, 0xE3FE, 0x6C81,
+	0xE4A1, 0xF972, 0xE4A2, 0x6DF1, 0xE4A3, 0x700B, 0xE4A4, 0x751A,
+	0xE4A5, 0x82AF, 0xE4A6, 0x8AF6, 0xE4A7, 0x4EC0, 0xE4A8, 0x5341,
+	0xE4A9, 0xF973, 0xE4AA, 0x96D9, 0xE4AB, 0x6C0F, 0xE4AC, 0x4E9E,
+	0xE4AD, 0x4FC4, 0xE4AE, 0x5152, 0xE4AF, 0x555E, 0xE4B0, 0x5A25,
+	0xE4B1, 0x5CE8, 0xE4B2, 0x6211, 0xE4B3, 0x7259, 0xE4B4, 0x82BD,
+	0xE4B5, 0x83AA, 0xE4B6, 0x86FE, 0xE4B7, 0x8859, 0xE4B8, 0x8A1D,
+	0xE4B9, 0x963F, 0xE4BA, 0x96C5, 0xE4BB, 0x9913, 0xE4BC, 0x9D09,
+	0xE4BD, 0x9D5D, 0xE4BE, 0x580A, 0xE4BF, 0x5CB3, 0xE4C0, 0x5DBD,
+	0xE4C1, 0x5E44, 0xE4C2, 0x60E1, 0xE4C3, 0x6115, 0xE4C4, 0x63E1,
+	0xE4C5, 0x6A02, 0xE4C6, 0x6E25, 0xE4C7, 0x9102, 0xE4C8, 0x9354,
+	0xE4C9, 0x984E, 0xE4CA, 0x9C10, 0xE4CB, 0x9F77, 0xE4CC, 0x5B89,
+	0xE4CD, 0x5CB8, 0xE4CE, 0x6309, 0xE4CF, 0x664F, 0xE4D0, 0x6848,
+	0xE4D1, 0x773C, 0xE4D2, 0x96C1, 0xE4D3, 0x978D, 0xE4D4, 0x9854,
+	0xE4D5, 0x9B9F, 0xE4D6, 0x65A1, 0xE4D7, 0x8B01, 0xE4D8, 0x8ECB,
+	0xE4D9, 0x95BC, 0xE4DA, 0x5535, 0xE4DB, 0x5CA9, 0xE4DC, 0x5DD6,
+	0xE4DD, 0x5EB5, 0xE4DE, 0x6697, 0xE4DF, 0x764C, 0xE4E0, 0x83F4,
+	0xE4E1, 0x95C7, 0xE4E2, 0x58D3, 0xE4E3, 0x62BC, 0xE4E4, 0x72CE,
+	0xE4E5, 0x9D28, 0xE4E6, 0x4EF0, 0xE4E7, 0x592E, 0xE4E8, 0x600F,
+	0xE4E9, 0x663B, 0xE4EA, 0x6B83, 0xE4EB, 0x79E7, 0xE4EC, 0x9D26,
+	0xE4ED, 0x5393, 0xE4EE, 0x54C0, 0xE4EF, 0x57C3, 0xE4F0, 0x5D16,
+	0xE4F1, 0x611B, 0xE4F2, 0x66D6, 0xE4F3, 0x6DAF, 0xE4F4, 0x788D,
+	0xE4F5, 0x827E, 0xE4F6, 0x9698, 0xE4F7, 0x9744, 0xE4F8, 0x5384,
+	0xE4F9, 0x627C, 0xE4FA, 0x6396, 0xE4FB, 0x6DB2, 0xE4FC, 0x7E0A,
+	0xE4FD, 0x814B, 0xE4FE, 0x984D, 0xE5A1, 0x6AFB, 0xE5A2, 0x7F4C,
+	0xE5A3, 0x9DAF, 0xE5A4, 0x9E1A, 0xE5A5, 0x4E5F, 0xE5A6, 0x503B,
+	0xE5A7, 0x51B6, 0xE5A8, 0x591C, 0xE5A9, 0x60F9, 0xE5AA, 0x63F6,
+	0xE5AB, 0x6930, 0xE5AC, 0x723A, 0xE5AD, 0x8036, 0xE5AE, 0xF974,
+	0xE5AF, 0x91CE, 0xE5B0, 0x5F31, 0xE5B1, 0xF975, 0xE5B2, 0xF976,
+	0xE5B3, 0x7D04, 0xE5B4, 0x82E5, 0xE5B5, 0x846F, 0xE5B6, 0x84BB,
+	0xE5B7, 0x85E5, 0xE5B8, 0x8E8D, 0xE5B9, 0xF977, 0xE5BA, 0x4F6F,
+	0xE5BB, 0xF978, 0xE5BC, 0xF979, 0xE5BD, 0x58E4, 0xE5BE, 0x5B43,
+	0xE5BF, 0x6059, 0xE5C0, 0x63DA, 0xE5C1, 0x6518, 0xE5C2, 0x656D,
+	0xE5C3, 0x6698, 0xE5C4, 0xF97A, 0xE5C5, 0x694A, 0xE5C6, 0x6A23,
+	0xE5C7, 0x6D0B, 0xE5C8, 0x7001, 0xE5C9, 0x716C, 0xE5CA, 0x75D2,
+	0xE5CB, 0x760D, 0xE5CC, 0x79B3, 0xE5CD, 0x7A70, 0xE5CE, 0xF97B,
+	0xE5CF, 0x7F8A, 0xE5D0, 0xF97C, 0xE5D1, 0x8944, 0xE5D2, 0xF97D,
+	0xE5D3, 0x8B93, 0xE5D4, 0x91C0, 0xE5D5, 0x967D, 0xE5D6, 0xF97E,
+	0xE5D7, 0x990A, 0xE5D8, 0x5704, 0xE5D9, 0x5FA1, 0xE5DA, 0x65BC,
+	0xE5DB, 0x6F01, 0xE5DC, 0x7600, 0xE5DD, 0x79A6, 0xE5DE, 0x8A9E,
+	0xE5DF, 0x99AD, 0xE5E0, 0x9B5A, 0xE5E1, 0x9F6C, 0xE5E2, 0x5104,
+	0xE5E3, 0x61B6, 0xE5E4, 0x6291, 0xE5E5, 0x6A8D, 0xE5E6, 0x81C6,
+	0xE5E7, 0x5043, 0xE5E8, 0x5830, 0xE5E9, 0x5F66, 0xE5EA, 0x7109,
+	0xE5EB, 0x8A00, 0xE5EC, 0x8AFA, 0xE5ED, 0x5B7C, 0xE5EE, 0x8616,
+	0xE5EF, 0x4FFA, 0xE5F0, 0x513C, 0xE5F1, 0x56B4, 0xE5F2, 0x5944,
+	0xE5F3, 0x63A9, 0xE5F4, 0x6DF9, 0xE5F5, 0x5DAA, 0xE5F6, 0x696D,
+	0xE5F7, 0x5186, 0xE5F8, 0x4E88, 0xE5F9, 0x4F59, 0xE5FA, 0xF97F,
+	0xE5FB, 0xF980, 0xE5FC, 0xF981, 0xE5FD, 0x5982, 0xE5FE, 0xF982,
+	0xE6A1, 0xF983, 0xE6A2, 0x6B5F, 0xE6A3, 0x6C5D, 0xE6A4, 0xF984,
+	0xE6A5, 0x74B5, 0xE6A6, 0x7916, 0xE6A7, 0xF985, 0xE6A8, 0x8207,
+	0xE6A9, 0x8245, 0xE6AA, 0x8339, 0xE6AB, 0x8F3F, 0xE6AC, 0x8F5D,
+	0xE6AD, 0xF986, 0xE6AE, 0x9918, 0xE6AF, 0xF987, 0xE6B0, 0xF988,
+	0xE6B1, 0xF989, 0xE6B2, 0x4EA6, 0xE6B3, 0xF98A, 0xE6B4, 0x57DF,
+	0xE6B5, 0x5F79, 0xE6B6, 0x6613, 0xE6B7, 0xF98B, 0xE6B8, 0xF98C,
+	0xE6B9, 0x75AB, 0xE6BA, 0x7E79, 0xE6BB, 0x8B6F, 0xE6BC, 0xF98D,
+	0xE6BD, 0x9006, 0xE6BE, 0x9A5B, 0xE6BF, 0x56A5, 0xE6C0, 0x5827,
+	0xE6C1, 0x59F8, 0xE6C2, 0x5A1F, 0xE6C3, 0x5BB4, 0xE6C4, 0xF98E,
+	0xE6C5, 0x5EF6, 0xE6C6, 0xF98F, 0xE6C7, 0xF990, 0xE6C8, 0x6350,
+	0xE6C9, 0x633B, 0xE6CA, 0xF991, 0xE6CB, 0x693D, 0xE6CC, 0x6C87,
+	0xE6CD, 0x6CBF, 0xE6CE, 0x6D8E, 0xE6CF, 0x6D93, 0xE6D0, 0x6DF5,
+	0xE6D1, 0x6F14, 0xE6D2, 0xF992, 0xE6D3, 0x70DF, 0xE6D4, 0x7136,
+	0xE6D5, 0x7159, 0xE6D6, 0xF993, 0xE6D7, 0x71C3, 0xE6D8, 0x71D5,
+	0xE6D9, 0xF994, 0xE6DA, 0x784F, 0xE6DB, 0x786F, 0xE6DC, 0xF995,
+	0xE6DD, 0x7B75, 0xE6DE, 0x7DE3, 0xE6DF, 0xF996, 0xE6E0, 0x7E2F,
+	0xE6E1, 0xF997, 0xE6E2, 0x884D, 0xE6E3, 0x8EDF, 0xE6E4, 0xF998,
+	0xE6E5, 0xF999, 0xE6E6, 0xF99A, 0xE6E7, 0x925B, 0xE6E8, 0xF99B,
+	0xE6E9, 0x9CF6, 0xE6EA, 0xF99C, 0xE6EB, 0xF99D, 0xE6EC, 0xF99E,
+	0xE6ED, 0x6085, 0xE6EE, 0x6D85, 0xE6EF, 0xF99F, 0xE6F0, 0x71B1,
+	0xE6F1, 0xF9A0, 0xE6F2, 0xF9A1, 0xE6F3, 0x95B1, 0xE6F4, 0x53AD,
+	0xE6F5, 0xF9A2, 0xE6F6, 0xF9A3, 0xE6F7, 0xF9A4, 0xE6F8, 0x67D3,
+	0xE6F9, 0xF9A5, 0xE6FA, 0x708E, 0xE6FB, 0x7130, 0xE6FC, 0x7430,
+	0xE6FD, 0x8276, 0xE6FE, 0x82D2, 0xE7A1, 0xF9A6, 0xE7A2, 0x95BB,
+	0xE7A3, 0x9AE5, 0xE7A4, 0x9E7D, 0xE7A5, 0x66C4, 0xE7A6, 0xF9A7,
+	0xE7A7, 0x71C1, 0xE7A8, 0x8449, 0xE7A9, 0xF9A8, 0xE7AA, 0xF9A9,
+	0xE7AB, 0x584B, 0xE7AC, 0xF9AA, 0xE7AD, 0xF9AB, 0xE7AE, 0x5DB8,
+	0xE7AF, 0x5F71, 0xE7B0, 0xF9AC, 0xE7B1, 0x6620, 0xE7B2, 0x668E,
+	0xE7B3, 0x6979, 0xE7B4, 0x69AE, 0xE7B5, 0x6C38, 0xE7B6, 0x6CF3,
+	0xE7B7, 0x6E36, 0xE7B8, 0x6F41, 0xE7B9, 0x6FDA, 0xE7BA, 0x701B,
+	0xE7BB, 0x702F, 0xE7BC, 0x7150, 0xE7BD, 0x71DF, 0xE7BE, 0x7370,
+	0xE7BF, 0xF9AD, 0xE7C0, 0x745B, 0xE7C1, 0xF9AE, 0xE7C2, 0x74D4,
+	0xE7C3, 0x76C8, 0xE7C4, 0x7A4E, 0xE7C5, 0x7E93, 0xE7C6, 0xF9AF,
+	0xE7C7, 0xF9B0, 0xE7C8, 0x82F1, 0xE7C9, 0x8A60, 0xE7CA, 0x8FCE,
+	0xE7CB, 0xF9B1, 0xE7CC, 0x9348, 0xE7CD, 0xF9B2, 0xE7CE, 0x9719,
+	0xE7CF, 0xF9B3, 0xE7D0, 0xF9B4, 0xE7D1, 0x4E42, 0xE7D2, 0x502A,
+	0xE7D3, 0xF9B5, 0xE7D4, 0x5208, 0xE7D5, 0x53E1, 0xE7D6, 0x66F3,
+	0xE7D7, 0x6C6D, 0xE7D8, 0x6FCA, 0xE7D9, 0x730A, 0xE7DA, 0x777F,
+	0xE7DB, 0x7A62, 0xE7DC, 0x82AE, 0xE7DD, 0x85DD, 0xE7DE, 0x8602,
+	0xE7DF, 0xF9B6, 0xE7E0, 0x88D4, 0xE7E1, 0x8A63, 0xE7E2, 0x8B7D,
+	0xE7E3, 0x8C6B, 0xE7E4, 0xF9B7, 0xE7E5, 0x92B3, 0xE7E6, 0xF9B8,
+	0xE7E7, 0x9713, 0xE7E8, 0x9810, 0xE7E9, 0x4E94, 0xE7EA, 0x4F0D,
+	0xE7EB, 0x4FC9, 0xE7EC, 0x50B2, 0xE7ED, 0x5348, 0xE7EE, 0x543E,
+	0xE7EF, 0x5433, 0xE7F0, 0x55DA, 0xE7F1, 0x5862, 0xE7F2, 0x58BA,
+	0xE7F3, 0x5967, 0xE7F4, 0x5A1B, 0xE7F5, 0x5BE4, 0xE7F6, 0x609F,
+	0xE7F7, 0xF9B9, 0xE7F8, 0x61CA, 0xE7F9, 0x6556, 0xE7FA, 0x65FF,
+	0xE7FB, 0x6664, 0xE7FC, 0x68A7, 0xE7FD, 0x6C5A, 0xE7FE, 0x6FB3,
+	0xE8A1, 0x70CF, 0xE8A2, 0x71AC, 0xE8A3, 0x7352, 0xE8A4, 0x7B7D,
+	0xE8A5, 0x8708, 0xE8A6, 0x8AA4, 0xE8A7, 0x9C32, 0xE8A8, 0x9F07,
+	0xE8A9, 0x5C4B, 0xE8AA, 0x6C83, 0xE8AB, 0x7344, 0xE8AC, 0x7389,
+	0xE8AD, 0x923A, 0xE8AE, 0x6EAB, 0xE8AF, 0x7465, 0xE8B0, 0x761F,
+	0xE8B1, 0x7A69, 0xE8B2, 0x7E15, 0xE8B3, 0x860A, 0xE8B4, 0x5140,
+	0xE8B5, 0x58C5, 0xE8B6, 0x64C1, 0xE8B7, 0x74EE, 0xE8B8, 0x7515,
+	0xE8B9, 0x7670, 0xE8BA, 0x7FC1, 0xE8BB, 0x9095, 0xE8BC, 0x96CD,
+	0xE8BD, 0x9954, 0xE8BE, 0x6E26, 0xE8BF, 0x74E6, 0xE8C0, 0x7AA9,
+	0xE8C1, 0x7AAA, 0xE8C2, 0x81E5, 0xE8C3, 0x86D9, 0xE8C4, 0x8778,
+	0xE8C5, 0x8A1B, 0xE8C6, 0x5A49, 0xE8C7, 0x5B8C, 0xE8C8, 0x5B9B,
+	0xE8C9, 0x68A1, 0xE8CA, 0x6900, 0xE8CB, 0x6D63, 0xE8CC, 0x73A9,
+	0xE8CD, 0x7413, 0xE8CE, 0x742C, 0xE8CF, 0x7897, 0xE8D0, 0x7DE9,
+	0xE8D1, 0x7FEB, 0xE8D2, 0x8118, 0xE8D3, 0x8155, 0xE8D4, 0x839E,
+	0xE8D5, 0x8C4C, 0xE8D6, 0x962E, 0xE8D7, 0x9811, 0xE8D8, 0x66F0,
+	0xE8D9, 0x5F80, 0xE8DA, 0x65FA, 0xE8DB, 0x6789, 0xE8DC, 0x6C6A,
+	0xE8DD, 0x738B, 0xE8DE, 0x502D, 0xE8DF, 0x5A03, 0xE8E0, 0x6B6A,
+	0xE8E1, 0x77EE, 0xE8E2, 0x5916, 0xE8E3, 0x5D6C, 0xE8E4, 0x5DCD,
+	0xE8E5, 0x7325, 0xE8E6, 0x754F, 0xE8E7, 0xF9BA, 0xE8E8, 0xF9BB,
+	0xE8E9, 0x50E5, 0xE8EA, 0x51F9, 0xE8EB, 0x582F, 0xE8EC, 0x592D,
+	0xE8ED, 0x5996, 0xE8EE, 0x59DA, 0xE8EF, 0x5BE5, 0xE8F0, 0xF9BC,
+	0xE8F1, 0xF9BD, 0xE8F2, 0x5DA2, 0xE8F3, 0x62D7, 0xE8F4, 0x6416,
+	0xE8F5, 0x6493, 0xE8F6, 0x64FE, 0xE8F7, 0xF9BE, 0xE8F8, 0x66DC,
+	0xE8F9, 0xF9BF, 0xE8FA, 0x6A48, 0xE8FB, 0xF9C0, 0xE8FC, 0x71FF,
+	0xE8FD, 0x7464, 0xE8FE, 0xF9C1, 0xE9A1, 0x7A88, 0xE9A2, 0x7AAF,
+	0xE9A3, 0x7E47, 0xE9A4, 0x7E5E, 0xE9A5, 0x8000, 0xE9A6, 0x8170,
+	0xE9A7, 0xF9C2, 0xE9A8, 0x87EF, 0xE9A9, 0x8981, 0xE9AA, 0x8B20,
+	0xE9AB, 0x9059, 0xE9AC, 0xF9C3, 0xE9AD, 0x9080, 0xE9AE, 0x9952,
+	0xE9AF, 0x617E, 0xE9B0, 0x6B32, 0xE9B1, 0x6D74, 0xE9B2, 0x7E1F,
+	0xE9B3, 0x8925, 0xE9B4, 0x8FB1, 0xE9B5, 0x4FD1, 0xE9B6, 0x50AD,
+	0xE9B7, 0x5197, 0xE9B8, 0x52C7, 0xE9B9, 0x57C7, 0xE9BA, 0x5889,
+	0xE9BB, 0x5BB9, 0xE9BC, 0x5EB8, 0xE9BD, 0x6142, 0xE9BE, 0x6995,
+	0xE9BF, 0x6D8C, 0xE9C0, 0x6E67, 0xE9C1, 0x6EB6, 0xE9C2, 0x7194,
+	0xE9C3, 0x7462, 0xE9C4, 0x7528, 0xE9C5, 0x752C, 0xE9C6, 0x8073,
+	0xE9C7, 0x8338, 0xE9C8, 0x84C9, 0xE9C9, 0x8E0A, 0xE9CA, 0x9394,
+	0xE9CB, 0x93DE, 0xE9CC, 0xF9C4, 0xE9CD, 0x4E8E, 0xE9CE, 0x4F51,
+	0xE9CF, 0x5076, 0xE9D0, 0x512A, 0xE9D1, 0x53C8, 0xE9D2, 0x53CB,
+	0xE9D3, 0x53F3, 0xE9D4, 0x5B87, 0xE9D5, 0x5BD3, 0xE9D6, 0x5C24,
+	0xE9D7, 0x611A, 0xE9D8, 0x6182, 0xE9D9, 0x65F4, 0xE9DA, 0x725B,
+	0xE9DB, 0x7397, 0xE9DC, 0x7440, 0xE9DD, 0x76C2, 0xE9DE, 0x7950,
+	0xE9DF, 0x7991, 0xE9E0, 0x79B9, 0xE9E1, 0x7D06, 0xE9E2, 0x7FBD,
+	0xE9E3, 0x828B, 0xE9E4, 0x85D5, 0xE9E5, 0x865E, 0xE9E6, 0x8FC2,
+	0xE9E7, 0x9047, 0xE9E8, 0x90F5, 0xE9E9, 0x91EA, 0xE9EA, 0x9685,
+	0xE9EB, 0x96E8, 0xE9EC, 0x96E9, 0xE9ED, 0x52D6, 0xE9EE, 0x5F67,
+	0xE9EF, 0x65ED, 0xE9F0, 0x6631, 0xE9F1, 0x682F, 0xE9F2, 0x715C,
+	0xE9F3, 0x7A36, 0xE9F4, 0x90C1, 0xE9F5, 0x980A, 0xE9F6, 0x4E91,
+	0xE9F7, 0xF9C5, 0xE9F8, 0x6A52, 0xE9F9, 0x6B9E, 0xE9FA, 0x6F90,
+	0xE9FB, 0x7189, 0xE9FC, 0x8018, 0xE9FD, 0x82B8, 0xE9FE, 0x8553,
+	0xEAA1, 0x904B, 0xEAA2, 0x9695, 0xEAA3, 0x96F2, 0xEAA4, 0x97FB,
+	0xEAA5, 0x851A, 0xEAA6, 0x9B31, 0xEAA7, 0x4E90, 0xEAA8, 0x718A,
+	0xEAA9, 0x96C4, 0xEAAA, 0x5143, 0xEAAB, 0x539F, 0xEAAC, 0x54E1,
+	0xEAAD, 0x5713, 0xEAAE, 0x5712, 0xEAAF, 0x57A3, 0xEAB0, 0x5A9B,
+	0xEAB1, 0x5AC4, 0xEAB2, 0x5BC3, 0xEAB3, 0x6028, 0xEAB4, 0x613F,
+	0xEAB5, 0x63F4, 0xEAB6, 0x6C85, 0xEAB7, 0x6D39, 0xEAB8, 0x6E72,
+	0xEAB9, 0x6E90, 0xEABA, 0x7230, 0xEABB, 0x733F, 0xEABC, 0x7457,
+	0xEABD, 0x82D1, 0xEABE, 0x8881, 0xEABF, 0x8F45, 0xEAC0, 0x9060,
+	0xEAC1, 0xF9C6, 0xEAC2, 0x9662, 0xEAC3, 0x9858, 0xEAC4, 0x9D1B,
+	0xEAC5, 0x6708, 0xEAC6, 0x8D8A, 0xEAC7, 0x925E, 0xEAC8, 0x4F4D,
+	0xEAC9, 0x5049, 0xEACA, 0x50DE, 0xEACB, 0x5371, 0xEACC, 0x570D,
+	0xEACD, 0x59D4, 0xEACE, 0x5A01, 0xEACF, 0x5C09, 0xEAD0, 0x6170,
+	0xEAD1, 0x6690, 0xEAD2, 0x6E2D, 0xEAD3, 0x7232, 0xEAD4, 0x744B,
+	0xEAD5, 0x7DEF, 0xEAD6, 0x80C3, 0xEAD7, 0x840E, 0xEAD8, 0x8466,
+	0xEAD9, 0x853F, 0xEADA, 0x875F, 0xEADB, 0x885B, 0xEADC, 0x8918,
+	0xEADD, 0x8B02, 0xEADE, 0x9055, 0xEADF, 0x97CB, 0xEAE0, 0x9B4F,
+	0xEAE1, 0x4E73, 0xEAE2, 0x4F91, 0xEAE3, 0x5112, 0xEAE4, 0x516A,
+	0xEAE5, 0xF9C7, 0xEAE6, 0x552F, 0xEAE7, 0x55A9, 0xEAE8, 0x5B7A,
+	0xEAE9, 0x5BA5, 0xEAEA, 0x5E7C, 0xEAEB, 0x5E7D, 0xEAEC, 0x5EBE,
+	0xEAED, 0x60A0, 0xEAEE, 0x60DF, 0xEAEF, 0x6108, 0xEAF0, 0x6109,
+	0xEAF1, 0x63C4, 0xEAF2, 0x6538, 0xEAF3, 0x6709, 0xEAF4, 0xF9C8,
+	0xEAF5, 0x67D4, 0xEAF6, 0x67DA, 0xEAF7, 0xF9C9, 0xEAF8, 0x6961,
+	0xEAF9, 0x6962, 0xEAFA, 0x6CB9, 0xEAFB, 0x6D27, 0xEAFC, 0xF9CA,
+	0xEAFD, 0x6E38, 0xEAFE, 0xF9CB, 0xEBA1, 0x6FE1, 0xEBA2, 0x7336,
+	0xEBA3, 0x7337, 0xEBA4, 0xF9CC, 0xEBA5, 0x745C, 0xEBA6, 0x7531,
+	0xEBA7, 0xF9CD, 0xEBA8, 0x7652, 0xEBA9, 0xF9CE, 0xEBAA, 0xF9CF,
+	0xEBAB, 0x7DAD, 0xEBAC, 0x81FE, 0xEBAD, 0x8438, 0xEBAE, 0x88D5,
+	0xEBAF, 0x8A98, 0xEBB0, 0x8ADB, 0xEBB1, 0x8AED, 0xEBB2, 0x8E30,
+	0xEBB3, 0x8E42, 0xEBB4, 0x904A, 0xEBB5, 0x903E, 0xEBB6, 0x907A,
+	0xEBB7, 0x9149, 0xEBB8, 0x91C9, 0xEBB9, 0x936E, 0xEBBA, 0xF9D0,
+	0xEBBB, 0xF9D1, 0xEBBC, 0x5809, 0xEBBD, 0xF9D2, 0xEBBE, 0x6BD3,
+	0xEBBF, 0x8089, 0xEBC0, 0x80B2, 0xEBC1, 0xF9D3, 0xEBC2, 0xF9D4,
+	0xEBC3, 0x5141, 0xEBC4, 0x596B, 0xEBC5, 0x5C39, 0xEBC6, 0xF9D5,
+	0xEBC7, 0xF9D6, 0xEBC8, 0x6F64, 0xEBC9, 0x73A7, 0xEBCA, 0x80E4,
+	0xEBCB, 0x8D07, 0xEBCC, 0xF9D7, 0xEBCD, 0x9217, 0xEBCE, 0x958F,
+	0xEBCF, 0xF9D8, 0xEBD0, 0xF9D9, 0xEBD1, 0xF9DA, 0xEBD2, 0xF9DB,
+	0xEBD3, 0x807F, 0xEBD4, 0x620E, 0xEBD5, 0x701C, 0xEBD6, 0x7D68,
+	0xEBD7, 0x878D, 0xEBD8, 0xF9DC, 0xEBD9, 0x57A0, 0xEBDA, 0x6069,
+	0xEBDB, 0x6147, 0xEBDC, 0x6BB7, 0xEBDD, 0x8ABE, 0xEBDE, 0x9280,
+	0xEBDF, 0x96B1, 0xEBE0, 0x4E59, 0xEBE1, 0x541F, 0xEBE2, 0x6DEB,
+	0xEBE3, 0x852D, 0xEBE4, 0x9670, 0xEBE5, 0x97F3, 0xEBE6, 0x98EE,
+	0xEBE7, 0x63D6, 0xEBE8, 0x6CE3, 0xEBE9, 0x9091, 0xEBEA, 0x51DD,
+	0xEBEB, 0x61C9, 0xEBEC, 0x81BA, 0xEBED, 0x9DF9, 0xEBEE, 0x4F9D,
+	0xEBEF, 0x501A, 0xEBF0, 0x5100, 0xEBF1, 0x5B9C, 0xEBF2, 0x610F,
+	0xEBF3, 0x61FF, 0xEBF4, 0x64EC, 0xEBF5, 0x6905, 0xEBF6, 0x6BC5,
+	0xEBF7, 0x7591, 0xEBF8, 0x77E3, 0xEBF9, 0x7FA9, 0xEBFA, 0x8264,
+	0xEBFB, 0x858F, 0xEBFC, 0x87FB, 0xEBFD, 0x8863, 0xEBFE, 0x8ABC,
+	0xECA1, 0x8B70, 0xECA2, 0x91AB, 0xECA3, 0x4E8C, 0xECA4, 0x4EE5,
+	0xECA5, 0x4F0A, 0xECA6, 0xF9DD, 0xECA7, 0xF9DE, 0xECA8, 0x5937,
+	0xECA9, 0x59E8, 0xECAA, 0xF9DF, 0xECAB, 0x5DF2, 0xECAC, 0x5F1B,
+	0xECAD, 0x5F5B, 0xECAE, 0x6021, 0xECAF, 0xF9E0, 0xECB0, 0xF9E1,
+	0xECB1, 0xF9E2, 0xECB2, 0xF9E3, 0xECB3, 0x723E, 0xECB4, 0x73E5,
+	0xECB5, 0xF9E4, 0xECB6, 0x7570, 0xECB7, 0x75CD, 0xECB8, 0xF9E5,
+	0xECB9, 0x79FB, 0xECBA, 0xF9E6, 0xECBB, 0x800C, 0xECBC, 0x8033,
+	0xECBD, 0x8084, 0xECBE, 0x82E1, 0xECBF, 0x8351, 0xECC0, 0xF9E7,
+	0xECC1, 0xF9E8, 0xECC2, 0x8CBD, 0xECC3, 0x8CB3, 0xECC4, 0x9087,
+	0xECC5, 0xF9E9, 0xECC6, 0xF9EA, 0xECC7, 0x98F4, 0xECC8, 0x990C,
+	0xECC9, 0xF9EB, 0xECCA, 0xF9EC, 0xECCB, 0x7037, 0xECCC, 0x76CA,
+	0xECCD, 0x7FCA, 0xECCE, 0x7FCC, 0xECCF, 0x7FFC, 0xECD0, 0x8B1A,
+	0xECD1, 0x4EBA, 0xECD2, 0x4EC1, 0xECD3, 0x5203, 0xECD4, 0x5370,
+	0xECD5, 0xF9ED, 0xECD6, 0x54BD, 0xECD7, 0x56E0, 0xECD8, 0x59FB,
+	0xECD9, 0x5BC5, 0xECDA, 0x5F15, 0xECDB, 0x5FCD, 0xECDC, 0x6E6E,
+	0xECDD, 0xF9EE, 0xECDE, 0xF9EF, 0xECDF, 0x7D6A, 0xECE0, 0x8335,
+	0xECE1, 0xF9F0, 0xECE2, 0x8693, 0xECE3, 0x8A8D, 0xECE4, 0xF9F1,
+	0xECE5, 0x976D, 0xECE6, 0x9777, 0xECE7, 0xF9F2, 0xECE8, 0xF9F3,
+	0xECE9, 0x4E00, 0xECEA, 0x4F5A, 0xECEB, 0x4F7E, 0xECEC, 0x58F9,
+	0xECED, 0x65E5, 0xECEE, 0x6EA2, 0xECEF, 0x9038, 0xECF0, 0x93B0,
+	0xECF1, 0x99B9, 0xECF2, 0x4EFB, 0xECF3, 0x58EC, 0xECF4, 0x598A,
+	0xECF5, 0x59D9, 0xECF6, 0x6041, 0xECF7, 0xF9F4, 0xECF8, 0xF9F5,
+	0xECF9, 0x7A14, 0xECFA, 0xF9F6, 0xECFB, 0x834F, 0xECFC, 0x8CC3,
+	0xECFD, 0x5165, 0xECFE, 0x5344, 0xEDA1, 0xF9F7, 0xEDA2, 0xF9F8,
+	0xEDA3, 0xF9F9, 0xEDA4, 0x4ECD, 0xEDA5, 0x5269, 0xEDA6, 0x5B55,
+	0xEDA7, 0x82BF, 0xEDA8, 0x4ED4, 0xEDA9, 0x523A, 0xEDAA, 0x54A8,
+	0xEDAB, 0x59C9, 0xEDAC, 0x59FF, 0xEDAD, 0x5B50, 0xEDAE, 0x5B57,
+	0xEDAF, 0x5B5C, 0xEDB0, 0x6063, 0xEDB1, 0x6148, 0xEDB2, 0x6ECB,
+	0xEDB3, 0x7099, 0xEDB4, 0x716E, 0xEDB5, 0x7386, 0xEDB6, 0x74F7,
+	0xEDB7, 0x75B5, 0xEDB8, 0x78C1, 0xEDB9, 0x7D2B, 0xEDBA, 0x8005,
+	0xEDBB, 0x81EA, 0xEDBC, 0x8328, 0xEDBD, 0x8517, 0xEDBE, 0x85C9,
+	0xEDBF, 0x8AEE, 0xEDC0, 0x8CC7, 0xEDC1, 0x96CC, 0xEDC2, 0x4F5C,
+	0xEDC3, 0x52FA, 0xEDC4, 0x56BC, 0xEDC5, 0x65AB, 0xEDC6, 0x6628,
+	0xEDC7, 0x707C, 0xEDC8, 0x70B8, 0xEDC9, 0x7235, 0xEDCA, 0x7DBD,
+	0xEDCB, 0x828D, 0xEDCC, 0x914C, 0xEDCD, 0x96C0, 0xEDCE, 0x9D72,
+	0xEDCF, 0x5B71, 0xEDD0, 0x68E7, 0xEDD1, 0x6B98, 0xEDD2, 0x6F7A,
+	0xEDD3, 0x76DE, 0xEDD4, 0x5C91, 0xEDD5, 0x66AB, 0xEDD6, 0x6F5B,
+	0xEDD7, 0x7BB4, 0xEDD8, 0x7C2A, 0xEDD9, 0x8836, 0xEDDA, 0x96DC,
+	0xEDDB, 0x4E08, 0xEDDC, 0x4ED7, 0xEDDD, 0x5320, 0xEDDE, 0x5834,
+	0xEDDF, 0x58BB, 0xEDE0, 0x58EF, 0xEDE1, 0x596C, 0xEDE2, 0x5C07,
+	0xEDE3, 0x5E33, 0xEDE4, 0x5E84, 0xEDE5, 0x5F35, 0xEDE6, 0x638C,
+	0xEDE7, 0x66B2, 0xEDE8, 0x6756, 0xEDE9, 0x6A1F, 0xEDEA, 0x6AA3,
+	0xEDEB, 0x6B0C, 0xEDEC, 0x6F3F, 0xEDED, 0x7246, 0xEDEE, 0xF9FA,
+	0xEDEF, 0x7350, 0xEDF0, 0x748B, 0xEDF1, 0x7AE0, 0xEDF2, 0x7CA7,
+	0xEDF3, 0x8178, 0xEDF4, 0x81DF, 0xEDF5, 0x81E7, 0xEDF6, 0x838A,
+	0xEDF7, 0x846C, 0xEDF8, 0x8523, 0xEDF9, 0x8594, 0xEDFA, 0x85CF,
+	0xEDFB, 0x88DD, 0xEDFC, 0x8D13, 0xEDFD, 0x91AC, 0xEDFE, 0x9577,
+	0xEEA1, 0x969C, 0xEEA2, 0x518D, 0xEEA3, 0x54C9, 0xEEA4, 0x5728,
+	0xEEA5, 0x5BB0, 0xEEA6, 0x624D, 0xEEA7, 0x6750, 0xEEA8, 0x683D,
+	0xEEA9, 0x6893, 0xEEAA, 0x6E3D, 0xEEAB, 0x6ED3, 0xEEAC, 0x707D,
+	0xEEAD, 0x7E21, 0xEEAE, 0x88C1, 0xEEAF, 0x8CA1, 0xEEB0, 0x8F09,
+	0xEEB1, 0x9F4B, 0xEEB2, 0x9F4E, 0xEEB3, 0x722D, 0xEEB4, 0x7B8F,
+	0xEEB5, 0x8ACD, 0xEEB6, 0x931A, 0xEEB7, 0x4F47, 0xEEB8, 0x4F4E,
+	0xEEB9, 0x5132, 0xEEBA, 0x5480, 0xEEBB, 0x59D0, 0xEEBC, 0x5E95,
+	0xEEBD, 0x62B5, 0xEEBE, 0x6775, 0xEEBF, 0x696E, 0xEEC0, 0x6A17,
+	0xEEC1, 0x6CAE, 0xEEC2, 0x6E1A, 0xEEC3, 0x72D9, 0xEEC4, 0x732A,
+	0xEEC5, 0x75BD, 0xEEC6, 0x7BB8, 0xEEC7, 0x7D35, 0xEEC8, 0x82E7,
+	0xEEC9, 0x83F9, 0xEECA, 0x8457, 0xEECB, 0x85F7, 0xEECC, 0x8A5B,
+	0xEECD, 0x8CAF, 0xEECE, 0x8E87, 0xEECF, 0x9019, 0xEED0, 0x90B8,
+	0xEED1, 0x96CE, 0xEED2, 0x9F5F, 0xEED3, 0x52E3, 0xEED4, 0x540A,
+	0xEED5, 0x5AE1, 0xEED6, 0x5BC2, 0xEED7, 0x6458, 0xEED8, 0x6575,
+	0xEED9, 0x6EF4, 0xEEDA, 0x72C4, 0xEEDB, 0xF9FB, 0xEEDC, 0x7684,
+	0xEEDD, 0x7A4D, 0xEEDE, 0x7B1B, 0xEEDF, 0x7C4D, 0xEEE0, 0x7E3E,
+	0xEEE1, 0x7FDF, 0xEEE2, 0x837B, 0xEEE3, 0x8B2B, 0xEEE4, 0x8CCA,
+	0xEEE5, 0x8D64, 0xEEE6, 0x8DE1, 0xEEE7, 0x8E5F, 0xEEE8, 0x8FEA,
+	0xEEE9, 0x8FF9, 0xEEEA, 0x9069, 0xEEEB, 0x93D1, 0xEEEC, 0x4F43,
+	0xEEED, 0x4F7A, 0xEEEE, 0x50B3, 0xEEEF, 0x5168, 0xEEF0, 0x5178,
+	0xEEF1, 0x524D, 0xEEF2, 0x526A, 0xEEF3, 0x5861, 0xEEF4, 0x587C,
+	0xEEF5, 0x5960, 0xEEF6, 0x5C08, 0xEEF7, 0x5C55, 0xEEF8, 0x5EDB,
+	0xEEF9, 0x609B, 0xEEFA, 0x6230, 0xEEFB, 0x6813, 0xEEFC, 0x6BBF,
+	0xEEFD, 0x6C08, 0xEEFE, 0x6FB1, 0xEFA1, 0x714E, 0xEFA2, 0x7420,
+	0xEFA3, 0x7530, 0xEFA4, 0x7538, 0xEFA5, 0x7551, 0xEFA6, 0x7672,
+	0xEFA7, 0x7B4C, 0xEFA8, 0x7B8B, 0xEFA9, 0x7BAD, 0xEFAA, 0x7BC6,
+	0xEFAB, 0x7E8F, 0xEFAC, 0x8A6E, 0xEFAD, 0x8F3E, 0xEFAE, 0x8F49,
+	0xEFAF, 0x923F, 0xEFB0, 0x9293, 0xEFB1, 0x9322, 0xEFB2, 0x942B,
+	0xEFB3, 0x96FB, 0xEFB4, 0x985A, 0xEFB5, 0x986B, 0xEFB6, 0x991E,
+	0xEFB7, 0x5207, 0xEFB8, 0x622A, 0xEFB9, 0x6298, 0xEFBA, 0x6D59,
+	0xEFBB, 0x7664, 0xEFBC, 0x7ACA, 0xEFBD, 0x7BC0, 0xEFBE, 0x7D76,
+	0xEFBF, 0x5360, 0xEFC0, 0x5CBE, 0xEFC1, 0x5E97, 0xEFC2, 0x6F38,
+	0xEFC3, 0x70B9, 0xEFC4, 0x7C98, 0xEFC5, 0x9711, 0xEFC6, 0x9B8E,
+	0xEFC7, 0x9EDE, 0xEFC8, 0x63A5, 0xEFC9, 0x647A, 0xEFCA, 0x8776,
+	0xEFCB, 0x4E01, 0xEFCC, 0x4E95, 0xEFCD, 0x4EAD, 0xEFCE, 0x505C,
+	0xEFCF, 0x5075, 0xEFD0, 0x5448, 0xEFD1, 0x59C3, 0xEFD2, 0x5B9A,
+	0xEFD3, 0x5E40, 0xEFD4, 0x5EAD, 0xEFD5, 0x5EF7, 0xEFD6, 0x5F81,
+	0xEFD7, 0x60C5, 0xEFD8, 0x633A, 0xEFD9, 0x653F, 0xEFDA, 0x6574,
+	0xEFDB, 0x65CC, 0xEFDC, 0x6676, 0xEFDD, 0x6678, 0xEFDE, 0x67FE,
+	0xEFDF, 0x6968, 0xEFE0, 0x6A89, 0xEFE1, 0x6B63, 0xEFE2, 0x6C40,
+	0xEFE3, 0x6DC0, 0xEFE4, 0x6DE8, 0xEFE5, 0x6E1F, 0xEFE6, 0x6E5E,
+	0xEFE7, 0x701E, 0xEFE8, 0x70A1, 0xEFE9, 0x738E, 0xEFEA, 0x73FD,
+	0xEFEB, 0x753A, 0xEFEC, 0x775B, 0xEFED, 0x7887, 0xEFEE, 0x798E,
+	0xEFEF, 0x7A0B, 0xEFF0, 0x7A7D, 0xEFF1, 0x7CBE, 0xEFF2, 0x7D8E,
+	0xEFF3, 0x8247, 0xEFF4, 0x8A02, 0xEFF5, 0x8AEA, 0xEFF6, 0x8C9E,
+	0xEFF7, 0x912D, 0xEFF8, 0x914A, 0xEFF9, 0x91D8, 0xEFFA, 0x9266,
+	0xEFFB, 0x92CC, 0xEFFC, 0x9320, 0xEFFD, 0x9706, 0xEFFE, 0x9756,
+	0xF0A1, 0x975C, 0xF0A2, 0x9802, 0xF0A3, 0x9F0E, 0xF0A4, 0x5236,
+	0xF0A5, 0x5291, 0xF0A6, 0x557C, 0xF0A7, 0x5824, 0xF0A8, 0x5E1D,
+	0xF0A9, 0x5F1F, 0xF0AA, 0x608C, 0xF0AB, 0x63D0, 0xF0AC, 0x68AF,
+	0xF0AD, 0x6FDF, 0xF0AE, 0x796D, 0xF0AF, 0x7B2C, 0xF0B0, 0x81CD,
+	0xF0B1, 0x85BA, 0xF0B2, 0x88FD, 0xF0B3, 0x8AF8, 0xF0B4, 0x8E44,
+	0xF0B5, 0x918D, 0xF0B6, 0x9664, 0xF0B7, 0x969B, 0xF0B8, 0x973D,
+	0xF0B9, 0x984C, 0xF0BA, 0x9F4A, 0xF0BB, 0x4FCE, 0xF0BC, 0x5146,
+	0xF0BD, 0x51CB, 0xF0BE, 0x52A9, 0xF0BF, 0x5632, 0xF0C0, 0x5F14,
+	0xF0C1, 0x5F6B, 0xF0C2, 0x63AA, 0xF0C3, 0x64CD, 0xF0C4, 0x65E9,
+	0xF0C5, 0x6641, 0xF0C6, 0x66FA, 0xF0C7, 0x66F9, 0xF0C8, 0x671D,
+	0xF0C9, 0x689D, 0xF0CA, 0x68D7, 0xF0CB, 0x69FD, 0xF0CC, 0x6F15,
+	0xF0CD, 0x6F6E, 0xF0CE, 0x7167, 0xF0CF, 0x71E5, 0xF0D0, 0x722A,
+	0xF0D1, 0x74AA, 0xF0D2, 0x773A, 0xF0D3, 0x7956, 0xF0D4, 0x795A,
+	0xF0D5, 0x79DF, 0xF0D6, 0x7A20, 0xF0D7, 0x7A95, 0xF0D8, 0x7C97,
+	0xF0D9, 0x7CDF, 0xF0DA, 0x7D44, 0xF0DB, 0x7E70, 0xF0DC, 0x8087,
+	0xF0DD, 0x85FB, 0xF0DE, 0x86A4, 0xF0DF, 0x8A54, 0xF0E0, 0x8ABF,
+	0xF0E1, 0x8D99, 0xF0E2, 0x8E81, 0xF0E3, 0x9020, 0xF0E4, 0x906D,
+	0xF0E5, 0x91E3, 0xF0E6, 0x963B, 0xF0E7, 0x96D5, 0xF0E8, 0x9CE5,
+	0xF0E9, 0x65CF, 0xF0EA, 0x7C07, 0xF0EB, 0x8DB3, 0xF0EC, 0x93C3,
+	0xF0ED, 0x5B58, 0xF0EE, 0x5C0A, 0xF0EF, 0x5352, 0xF0F0, 0x62D9,
+	0xF0F1, 0x731D, 0xF0F2, 0x5027, 0xF0F3, 0x5B97, 0xF0F4, 0x5F9E,
+	0xF0F5, 0x60B0, 0xF0F6, 0x616B, 0xF0F7, 0x68D5, 0xF0F8, 0x6DD9,
+	0xF0F9, 0x742E, 0xF0FA, 0x7A2E, 0xF0FB, 0x7D42, 0xF0FC, 0x7D9C,
+	0xF0FD, 0x7E31, 0xF0FE, 0x816B, 0xF1A1, 0x8E2A, 0xF1A2, 0x8E35,
+	0xF1A3, 0x937E, 0xF1A4, 0x9418, 0xF1A5, 0x4F50, 0xF1A6, 0x5750,
+	0xF1A7, 0x5DE6, 0xF1A8, 0x5EA7, 0xF1A9, 0x632B, 0xF1AA, 0x7F6A,
+	0xF1AB, 0x4E3B, 0xF1AC, 0x4F4F, 0xF1AD, 0x4F8F, 0xF1AE, 0x505A,
+	0xF1AF, 0x59DD, 0xF1B0, 0x80C4, 0xF1B1, 0x546A, 0xF1B2, 0x5468,
+	0xF1B3, 0x55FE, 0xF1B4, 0x594F, 0xF1B5, 0x5B99, 0xF1B6, 0x5DDE,
+	0xF1B7, 0x5EDA, 0xF1B8, 0x665D, 0xF1B9, 0x6731, 0xF1BA, 0x67F1,
+	0xF1BB, 0x682A, 0xF1BC, 0x6CE8, 0xF1BD, 0x6D32, 0xF1BE, 0x6E4A,
+	0xF1BF, 0x6F8D, 0xF1C0, 0x70B7, 0xF1C1, 0x73E0, 0xF1C2, 0x7587,
+	0xF1C3, 0x7C4C, 0xF1C4, 0x7D02, 0xF1C5, 0x7D2C, 0xF1C6, 0x7DA2,
+	0xF1C7, 0x821F, 0xF1C8, 0x86DB, 0xF1C9, 0x8A3B, 0xF1CA, 0x8A85,
+	0xF1CB, 0x8D70, 0xF1CC, 0x8E8A, 0xF1CD, 0x8F33, 0xF1CE, 0x9031,
+	0xF1CF, 0x914E, 0xF1D0, 0x9152, 0xF1D1, 0x9444, 0xF1D2, 0x99D0,
+	0xF1D3, 0x7AF9, 0xF1D4, 0x7CA5, 0xF1D5, 0x4FCA, 0xF1D6, 0x5101,
+	0xF1D7, 0x51C6, 0xF1D8, 0x57C8, 0xF1D9, 0x5BEF, 0xF1DA, 0x5CFB,
+	0xF1DB, 0x6659, 0xF1DC, 0x6A3D, 0xF1DD, 0x6D5A, 0xF1DE, 0x6E96,
+	0xF1DF, 0x6FEC, 0xF1E0, 0x710C, 0xF1E1, 0x756F, 0xF1E2, 0x7AE3,
+	0xF1E3, 0x8822, 0xF1E4, 0x9021, 0xF1E5, 0x9075, 0xF1E6, 0x96CB,
+	0xF1E7, 0x99FF, 0xF1E8, 0x8301, 0xF1E9, 0x4E2D, 0xF1EA, 0x4EF2,
+	0xF1EB, 0x8846, 0xF1EC, 0x91CD, 0xF1ED, 0x537D, 0xF1EE, 0x6ADB,
+	0xF1EF, 0x696B, 0xF1F0, 0x6C41, 0xF1F1, 0x847A, 0xF1F2, 0x589E,
+	0xF1F3, 0x618E, 0xF1F4, 0x66FE, 0xF1F5, 0x62EF, 0xF1F6, 0x70DD,
+	0xF1F7, 0x7511, 0xF1F8, 0x75C7, 0xF1F9, 0x7E52, 0xF1FA, 0x84B8,
+	0xF1FB, 0x8B49, 0xF1FC, 0x8D08, 0xF1FD, 0x4E4B, 0xF1FE, 0x53EA,
+	0xF2A1, 0x54AB, 0xF2A2, 0x5730, 0xF2A3, 0x5740, 0xF2A4, 0x5FD7,
+	0xF2A5, 0x6301, 0xF2A6, 0x6307, 0xF2A7, 0x646F, 0xF2A8, 0x652F,
+	0xF2A9, 0x65E8, 0xF2AA, 0x667A, 0xF2AB, 0x679D, 0xF2AC, 0x67B3,
+	0xF2AD, 0x6B62, 0xF2AE, 0x6C60, 0xF2AF, 0x6C9A, 0xF2B0, 0x6F2C,
+	0xF2B1, 0x77E5, 0xF2B2, 0x7825, 0xF2B3, 0x7949, 0xF2B4, 0x7957,
+	0xF2B5, 0x7D19, 0xF2B6, 0x80A2, 0xF2B7, 0x8102, 0xF2B8, 0x81F3,
+	0xF2B9, 0x829D, 0xF2BA, 0x82B7, 0xF2BB, 0x8718, 0xF2BC, 0x8A8C,
+	0xF2BD, 0xF9FC, 0xF2BE, 0x8D04, 0xF2BF, 0x8DBE, 0xF2C0, 0x9072,
+	0xF2C1, 0x76F4, 0xF2C2, 0x7A19, 0xF2C3, 0x7A37, 0xF2C4, 0x7E54,
+	0xF2C5, 0x8077, 0xF2C6, 0x5507, 0xF2C7, 0x55D4, 0xF2C8, 0x5875,
+	0xF2C9, 0x632F, 0xF2CA, 0x6422, 0xF2CB, 0x6649, 0xF2CC, 0x664B,
+	0xF2CD, 0x686D, 0xF2CE, 0x699B, 0xF2CF, 0x6B84, 0xF2D0, 0x6D25,
+	0xF2D1, 0x6EB1, 0xF2D2, 0x73CD, 0xF2D3, 0x7468, 0xF2D4, 0x74A1,
+	0xF2D5, 0x755B, 0xF2D6, 0x75B9, 0xF2D7, 0x76E1, 0xF2D8, 0x771E,
+	0xF2D9, 0x778B, 0xF2DA, 0x79E6, 0xF2DB, 0x7E09, 0xF2DC, 0x7E1D,
+	0xF2DD, 0x81FB, 0xF2DE, 0x852F, 0xF2DF, 0x8897, 0xF2E0, 0x8A3A,
+	0xF2E1, 0x8CD1, 0xF2E2, 0x8EEB, 0xF2E3, 0x8FB0, 0xF2E4, 0x9032,
+	0xF2E5, 0x93AD, 0xF2E6, 0x9663, 0xF2E7, 0x9673, 0xF2E8, 0x9707,
+	0xF2E9, 0x4F84, 0xF2EA, 0x53F1, 0xF2EB, 0x59EA, 0xF2EC, 0x5AC9,
+	0xF2ED, 0x5E19, 0xF2EE, 0x684E, 0xF2EF, 0x74C6, 0xF2F0, 0x75BE,
+	0xF2F1, 0x79E9, 0xF2F2, 0x7A92, 0xF2F3, 0x81A3, 0xF2F4, 0x86ED,
+	0xF2F5, 0x8CEA, 0xF2F6, 0x8DCC, 0xF2F7, 0x8FED, 0xF2F8, 0x659F,
+	0xF2F9, 0x6715, 0xF2FA, 0xF9FD, 0xF2FB, 0x57F7, 0xF2FC, 0x6F57,
+	0xF2FD, 0x7DDD, 0xF2FE, 0x8F2F, 0xF3A1, 0x93F6, 0xF3A2, 0x96C6,
+	0xF3A3, 0x5FB5, 0xF3A4, 0x61F2, 0xF3A5, 0x6F84, 0xF3A6, 0x4E14,
+	0xF3A7, 0x4F98, 0xF3A8, 0x501F, 0xF3A9, 0x53C9, 0xF3AA, 0x55DF,
+	0xF3AB, 0x5D6F, 0xF3AC, 0x5DEE, 0xF3AD, 0x6B21, 0xF3AE, 0x6B64,
+	0xF3AF, 0x78CB, 0xF3B0, 0x7B9A, 0xF3B1, 0xF9FE, 0xF3B2, 0x8E49,
+	0xF3B3, 0x8ECA, 0xF3B4, 0x906E, 0xF3B5, 0x6349, 0xF3B6, 0x643E,
+	0xF3B7, 0x7740, 0xF3B8, 0x7A84, 0xF3B9, 0x932F, 0xF3BA, 0x947F,
+	0xF3BB, 0x9F6A, 0xF3BC, 0x64B0, 0xF3BD, 0x6FAF, 0xF3BE, 0x71E6,
+	0xF3BF, 0x74A8, 0xF3C0, 0x74DA, 0xF3C1, 0x7AC4, 0xF3C2, 0x7C12,
+	0xF3C3, 0x7E82, 0xF3C4, 0x7CB2, 0xF3C5, 0x7E98, 0xF3C6, 0x8B9A,
+	0xF3C7, 0x8D0A, 0xF3C8, 0x947D, 0xF3C9, 0x9910, 0xF3CA, 0x994C,
+	0xF3CB, 0x5239, 0xF3CC, 0x5BDF, 0xF3CD, 0x64E6, 0xF3CE, 0x672D,
+	0xF3CF, 0x7D2E, 0xF3D0, 0x50ED, 0xF3D1, 0x53C3, 0xF3D2, 0x5879,
+	0xF3D3, 0x6158, 0xF3D4, 0x6159, 0xF3D5, 0x61FA, 0xF3D6, 0x65AC,
+	0xF3D7, 0x7AD9, 0xF3D8, 0x8B92, 0xF3D9, 0x8B96, 0xF3DA, 0x5009,
+	0xF3DB, 0x5021, 0xF3DC, 0x5275, 0xF3DD, 0x5531, 0xF3DE, 0x5A3C,
+	0xF3DF, 0x5EE0, 0xF3E0, 0x5F70, 0xF3E1, 0x6134, 0xF3E2, 0x655E,
+	0xF3E3, 0x660C, 0xF3E4, 0x6636, 0xF3E5, 0x66A2, 0xF3E6, 0x69CD,
+	0xF3E7, 0x6EC4, 0xF3E8, 0x6F32, 0xF3E9, 0x7316, 0xF3EA, 0x7621,
+	0xF3EB, 0x7A93, 0xF3EC, 0x8139, 0xF3ED, 0x8259, 0xF3EE, 0x83D6,
+	0xF3EF, 0x84BC, 0xF3F0, 0x50B5, 0xF3F1, 0x57F0, 0xF3F2, 0x5BC0,
+	0xF3F3, 0x5BE8, 0xF3F4, 0x5F69, 0xF3F5, 0x63A1, 0xF3F6, 0x7826,
+	0xF3F7, 0x7DB5, 0xF3F8, 0x83DC, 0xF3F9, 0x8521, 0xF3FA, 0x91C7,
+	0xF3FB, 0x91F5, 0xF3FC, 0x518A, 0xF3FD, 0x67F5, 0xF3FE, 0x7B56,
+	0xF4A1, 0x8CAC, 0xF4A2, 0x51C4, 0xF4A3, 0x59BB, 0xF4A4, 0x60BD,
+	0xF4A5, 0x8655, 0xF4A6, 0x501C, 0xF4A7, 0xF9FF, 0xF4A8, 0x5254,
+	0xF4A9, 0x5C3A, 0xF4AA, 0x617D, 0xF4AB, 0x621A, 0xF4AC, 0x62D3,
+	0xF4AD, 0x64F2, 0xF4AE, 0x65A5, 0xF4AF, 0x6ECC, 0xF4B0, 0x7620,
+	0xF4B1, 0x810A, 0xF4B2, 0x8E60, 0xF4B3, 0x965F, 0xF4B4, 0x96BB,
+	0xF4B5, 0x4EDF, 0xF4B6, 0x5343, 0xF4B7, 0x5598, 0xF4B8, 0x5929,
+	0xF4B9, 0x5DDD, 0xF4BA, 0x64C5, 0xF4BB, 0x6CC9, 0xF4BC, 0x6DFA,
+	0xF4BD, 0x7394, 0xF4BE, 0x7A7F, 0xF4BF, 0x821B, 0xF4C0, 0x85A6,
+	0xF4C1, 0x8CE4, 0xF4C2, 0x8E10, 0xF4C3, 0x9077, 0xF4C4, 0x91E7,
+	0xF4C5, 0x95E1, 0xF4C6, 0x9621, 0xF4C7, 0x97C6, 0xF4C8, 0x51F8,
+	0xF4C9, 0x54F2, 0xF4CA, 0x5586, 0xF4CB, 0x5FB9, 0xF4CC, 0x64A4,
+	0xF4CD, 0x6F88, 0xF4CE, 0x7DB4, 0xF4CF, 0x8F1F, 0xF4D0, 0x8F4D,
+	0xF4D1, 0x9435, 0xF4D2, 0x50C9, 0xF4D3, 0x5C16, 0xF4D4, 0x6CBE,
+	0xF4D5, 0x6DFB, 0xF4D6, 0x751B, 0xF4D7, 0x77BB, 0xF4D8, 0x7C3D,
+	0xF4D9, 0x7C64, 0xF4DA, 0x8A79, 0xF4DB, 0x8AC2, 0xF4DC, 0x581E,
+	0xF4DD, 0x59BE, 0xF4DE, 0x5E16, 0xF4DF, 0x6377, 0xF4E0, 0x7252,
+	0xF4E1, 0x758A, 0xF4E2, 0x776B, 0xF4E3, 0x8ADC, 0xF4E4, 0x8CBC,
+	0xF4E5, 0x8F12, 0xF4E6, 0x5EF3, 0xF4E7, 0x6674, 0xF4E8, 0x6DF8,
+	0xF4E9, 0x807D, 0xF4EA, 0x83C1, 0xF4EB, 0x8ACB, 0xF4EC, 0x9751,
+	0xF4ED, 0x9BD6, 0xF4EE, 0xFA00, 0xF4EF, 0x5243, 0xF4F0, 0x66FF,
+	0xF4F1, 0x6D95, 0xF4F2, 0x6EEF, 0xF4F3, 0x7DE0, 0xF4F4, 0x8AE6,
+	0xF4F5, 0x902E, 0xF4F6, 0x905E, 0xF4F7, 0x9AD4, 0xF4F8, 0x521D,
+	0xF4F9, 0x527F, 0xF4FA, 0x54E8, 0xF4FB, 0x6194, 0xF4FC, 0x6284,
+	0xF4FD, 0x62DB, 0xF4FE, 0x68A2, 0xF5A1, 0x6912, 0xF5A2, 0x695A,
+	0xF5A3, 0x6A35, 0xF5A4, 0x7092, 0xF5A5, 0x7126, 0xF5A6, 0x785D,
+	0xF5A7, 0x7901, 0xF5A8, 0x790E, 0xF5A9, 0x79D2, 0xF5AA, 0x7A0D,
+	0xF5AB, 0x8096, 0xF5AC, 0x8278, 0xF5AD, 0x82D5, 0xF5AE, 0x8349,
+	0xF5AF, 0x8549, 0xF5B0, 0x8C82, 0xF5B1, 0x8D85, 0xF5B2, 0x9162,
+	0xF5B3, 0x918B, 0xF5B4, 0x91AE, 0xF5B5, 0x4FC3, 0xF5B6, 0x56D1,
+	0xF5B7, 0x71ED, 0xF5B8, 0x77D7, 0xF5B9, 0x8700, 0xF5BA, 0x89F8,
+	0xF5BB, 0x5BF8, 0xF5BC, 0x5FD6, 0xF5BD, 0x6751, 0xF5BE, 0x90A8,
+	0xF5BF, 0x53E2, 0xF5C0, 0x585A, 0xF5C1, 0x5BF5, 0xF5C2, 0x60A4,
+	0xF5C3, 0x6181, 0xF5C4, 0x6460, 0xF5C5, 0x7E3D, 0xF5C6, 0x8070,
+	0xF5C7, 0x8525, 0xF5C8, 0x9283, 0xF5C9, 0x64AE, 0xF5CA, 0x50AC,
+	0xF5CB, 0x5D14, 0xF5CC, 0x6700, 0xF5CD, 0x589C, 0xF5CE, 0x62BD,
+	0xF5CF, 0x63A8, 0xF5D0, 0x690E, 0xF5D1, 0x6978, 0xF5D2, 0x6A1E,
+	0xF5D3, 0x6E6B, 0xF5D4, 0x76BA, 0xF5D5, 0x79CB, 0xF5D6, 0x82BB,
+	0xF5D7, 0x8429, 0xF5D8, 0x8ACF, 0xF5D9, 0x8DA8, 0xF5DA, 0x8FFD,
+	0xF5DB, 0x9112, 0xF5DC, 0x914B, 0xF5DD, 0x919C, 0xF5DE, 0x9310,
+	0xF5DF, 0x9318, 0xF5E0, 0x939A, 0xF5E1, 0x96DB, 0xF5E2, 0x9A36,
+	0xF5E3, 0x9C0D, 0xF5E4, 0x4E11, 0xF5E5, 0x755C, 0xF5E6, 0x795D,
+	0xF5E7, 0x7AFA, 0xF5E8, 0x7B51, 0xF5E9, 0x7BC9, 0xF5EA, 0x7E2E,
+	0xF5EB, 0x84C4, 0xF5EC, 0x8E59, 0xF5ED, 0x8E74, 0xF5EE, 0x8EF8,
+	0xF5EF, 0x9010, 0xF5F0, 0x6625, 0xF5F1, 0x693F, 0xF5F2, 0x7443,
+	0xF5F3, 0x51FA, 0xF5F4, 0x672E, 0xF5F5, 0x9EDC, 0xF5F6, 0x5145,
+	0xF5F7, 0x5FE0, 0xF5F8, 0x6C96, 0xF5F9, 0x87F2, 0xF5FA, 0x885D,
+	0xF5FB, 0x8877, 0xF5FC, 0x60B4, 0xF5FD, 0x81B5, 0xF5FE, 0x8403,
+	0xF6A1, 0x8D05, 0xF6A2, 0x53D6, 0xF6A3, 0x5439, 0xF6A4, 0x5634,
+	0xF6A5, 0x5A36, 0xF6A6, 0x5C31, 0xF6A7, 0x708A, 0xF6A8, 0x7FE0,
+	0xF6A9, 0x805A, 0xF6AA, 0x8106, 0xF6AB, 0x81ED, 0xF6AC, 0x8DA3,
+	0xF6AD, 0x9189, 0xF6AE, 0x9A5F, 0xF6AF, 0x9DF2, 0xF6B0, 0x5074,
+	0xF6B1, 0x4EC4, 0xF6B2, 0x53A0, 0xF6B3, 0x60FB, 0xF6B4, 0x6E2C,
+	0xF6B5, 0x5C64, 0xF6B6, 0x4F88, 0xF6B7, 0x5024, 0xF6B8, 0x55E4,
+	0xF6B9, 0x5CD9, 0xF6BA, 0x5E5F, 0xF6BB, 0x6065, 0xF6BC, 0x6894,
+	0xF6BD, 0x6CBB, 0xF6BE, 0x6DC4, 0xF6BF, 0x71BE, 0xF6C0, 0x75D4,
+	0xF6C1, 0x75F4, 0xF6C2, 0x7661, 0xF6C3, 0x7A1A, 0xF6C4, 0x7A49,
+	0xF6C5, 0x7DC7, 0xF6C6, 0x7DFB, 0xF6C7, 0x7F6E, 0xF6C8, 0x81F4,
+	0xF6C9, 0x86A9, 0xF6CA, 0x8F1C, 0xF6CB, 0x96C9, 0xF6CC, 0x99B3,
+	0xF6CD, 0x9F52, 0xF6CE, 0x5247, 0xF6CF, 0x52C5, 0xF6D0, 0x98ED,
+	0xF6D1, 0x89AA, 0xF6D2, 0x4E03, 0xF6D3, 0x67D2, 0xF6D4, 0x6F06,
+	0xF6D5, 0x4FB5, 0xF6D6, 0x5BE2, 0xF6D7, 0x6795, 0xF6D8, 0x6C88,
+	0xF6D9, 0x6D78, 0xF6DA, 0x741B, 0xF6DB, 0x7827, 0xF6DC, 0x91DD,
+	0xF6DD, 0x937C, 0xF6DE, 0x87C4, 0xF6DF, 0x79E4, 0xF6E0, 0x7A31,
+	0xF6E1, 0x5FEB, 0xF6E2, 0x4ED6, 0xF6E3, 0x54A4, 0xF6E4, 0x553E,
+	0xF6E5, 0x58AE, 0xF6E6, 0x59A5, 0xF6E7, 0x60F0, 0xF6E8, 0x6253,
+	0xF6E9, 0x62D6, 0xF6EA, 0x6736, 0xF6EB, 0x6955, 0xF6EC, 0x8235,
+	0xF6ED, 0x9640, 0xF6EE, 0x99B1, 0xF6EF, 0x99DD, 0xF6F0, 0x502C,
+	0xF6F1, 0x5353, 0xF6F2, 0x5544, 0xF6F3, 0x577C, 0xF6F4, 0xFA01,
+	0xF6F5, 0x6258, 0xF6F6, 0xFA02, 0xF6F7, 0x64E2, 0xF6F8, 0x666B,
+	0xF6F9, 0x67DD, 0xF6FA, 0x6FC1, 0xF6FB, 0x6FEF, 0xF6FC, 0x7422,
+	0xF6FD, 0x7438, 0xF6FE, 0x8A17, 0xF7A1, 0x9438, 0xF7A2, 0x5451,
+	0xF7A3, 0x5606, 0xF7A4, 0x5766, 0xF7A5, 0x5F48, 0xF7A6, 0x619A,
+	0xF7A7, 0x6B4E, 0xF7A8, 0x7058, 0xF7A9, 0x70AD, 0xF7AA, 0x7DBB,
+	0xF7AB, 0x8A95, 0xF7AC, 0x596A, 0xF7AD, 0x812B, 0xF7AE, 0x63A2,
+	0xF7AF, 0x7708, 0xF7B0, 0x803D, 0xF7B1, 0x8CAA, 0xF7B2, 0x5854,
+	0xF7B3, 0x642D, 0xF7B4, 0x69BB, 0xF7B5, 0x5B95, 0xF7B6, 0x5E11,
+	0xF7B7, 0x6E6F, 0xF7B8, 0xFA03, 0xF7B9, 0x8569, 0xF7BA, 0x514C,
+	0xF7BB, 0x53F0, 0xF7BC, 0x592A, 0xF7BD, 0x6020, 0xF7BE, 0x614B,
+	0xF7BF, 0x6B86, 0xF7C0, 0x6C70, 0xF7C1, 0x6CF0, 0xF7C2, 0x7B1E,
+	0xF7C3, 0x80CE, 0xF7C4, 0x82D4, 0xF7C5, 0x8DC6, 0xF7C6, 0x90B0,
+	0xF7C7, 0x98B1, 0xF7C8, 0xFA04, 0xF7C9, 0x64C7, 0xF7CA, 0x6FA4,
+	0xF7CB, 0x6491, 0xF7CC, 0x6504, 0xF7CD, 0x514E, 0xF7CE, 0x5410,
+	0xF7CF, 0x571F, 0xF7D0, 0x8A0E, 0xF7D1, 0x615F, 0xF7D2, 0x6876,
+	0xF7D3, 0xFA05, 0xF7D4, 0x75DB, 0xF7D5, 0x7B52, 0xF7D6, 0x7D71,
+	0xF7D7, 0x901A, 0xF7D8, 0x5806, 0xF7D9, 0x69CC, 0xF7DA, 0x817F,
+	0xF7DB, 0x892A, 0xF7DC, 0x9000, 0xF7DD, 0x9839, 0xF7DE, 0x5078,
+	0xF7DF, 0x5957, 0xF7E0, 0x59AC, 0xF7E1, 0x6295, 0xF7E2, 0x900F,
+	0xF7E3, 0x9B2A, 0xF7E4, 0x615D, 0xF7E5, 0x7279, 0xF7E6, 0x95D6,
+	0xF7E7, 0x5761, 0xF7E8, 0x5A46, 0xF7E9, 0x5DF4, 0xF7EA, 0x628A,
+	0xF7EB, 0x64AD, 0xF7EC, 0x64FA, 0xF7ED, 0x6777, 0xF7EE, 0x6CE2,
+	0xF7EF, 0x6D3E, 0xF7F0, 0x722C, 0xF7F1, 0x7436, 0xF7F2, 0x7834,
+	0xF7F3, 0x7F77, 0xF7F4, 0x82AD, 0xF7F5, 0x8DDB, 0xF7F6, 0x9817,
+	0xF7F7, 0x5224, 0xF7F8, 0x5742, 0xF7F9, 0x677F, 0xF7FA, 0x7248,
+	0xF7FB, 0x74E3, 0xF7FC, 0x8CA9, 0xF7FD, 0x8FA6, 0xF7FE, 0x9211,
+	0xF8A1, 0x962A, 0xF8A2, 0x516B, 0xF8A3, 0x53ED, 0xF8A4, 0x634C,
+	0xF8A5, 0x4F69, 0xF8A6, 0x5504, 0xF8A7, 0x6096, 0xF8A8, 0x6557,
+	0xF8A9, 0x6C9B, 0xF8AA, 0x6D7F, 0xF8AB, 0x724C, 0xF8AC, 0x72FD,
+	0xF8AD, 0x7A17, 0xF8AE, 0x8987, 0xF8AF, 0x8C9D, 0xF8B0, 0x5F6D,
+	0xF8B1, 0x6F8E, 0xF8B2, 0x70F9, 0xF8B3, 0x81A8, 0xF8B4, 0x610E,
+	0xF8B5, 0x4FBF, 0xF8B6, 0x504F, 0xF8B7, 0x6241, 0xF8B8, 0x7247,
+	0xF8B9, 0x7BC7, 0xF8BA, 0x7DE8, 0xF8BB, 0x7FE9, 0xF8BC, 0x904D,
+	0xF8BD, 0x97AD, 0xF8BE, 0x9A19, 0xF8BF, 0x8CB6, 0xF8C0, 0x576A,
+	0xF8C1, 0x5E73, 0xF8C2, 0x67B0, 0xF8C3, 0x840D, 0xF8C4, 0x8A55,
+	0xF8C5, 0x5420, 0xF8C6, 0x5B16, 0xF8C7, 0x5E63, 0xF8C8, 0x5EE2,
+	0xF8C9, 0x5F0A, 0xF8CA, 0x6583, 0xF8CB, 0x80BA, 0xF8CC, 0x853D,
+	0xF8CD, 0x9589, 0xF8CE, 0x965B, 0xF8CF, 0x4F48, 0xF8D0, 0x5305,
+	0xF8D1, 0x530D, 0xF8D2, 0x530F, 0xF8D3, 0x5486, 0xF8D4, 0x54FA,
+	0xF8D5, 0x5703, 0xF8D6, 0x5E03, 0xF8D7, 0x6016, 0xF8D8, 0x629B,
+	0xF8D9, 0x62B1, 0xF8DA, 0x6355, 0xF8DB, 0xFA06, 0xF8DC, 0x6CE1,
+	0xF8DD, 0x6D66, 0xF8DE, 0x75B1, 0xF8DF, 0x7832, 0xF8E0, 0x80DE,
+	0xF8E1, 0x812F, 0xF8E2, 0x82DE, 0xF8E3, 0x8461, 0xF8E4, 0x84B2,
+	0xF8E5, 0x888D, 0xF8E6, 0x8912, 0xF8E7, 0x900B, 0xF8E8, 0x92EA,
+	0xF8E9, 0x98FD, 0xF8EA, 0x9B91, 0xF8EB, 0x5E45, 0xF8EC, 0x66B4,
+	0xF8ED, 0x66DD, 0xF8EE, 0x7011, 0xF8EF, 0x7206, 0xF8F0, 0xFA07,
+	0xF8F1, 0x4FF5, 0xF8F2, 0x527D, 0xF8F3, 0x5F6A, 0xF8F4, 0x6153,
+	0xF8F5, 0x6753, 0xF8F6, 0x6A19, 0xF8F7, 0x6F02, 0xF8F8, 0x74E2,
+	0xF8F9, 0x7968, 0xF8FA, 0x8868, 0xF8FB, 0x8C79, 0xF8FC, 0x98C7,
+	0xF8FD, 0x98C4, 0xF8FE, 0x9A43, 0xF9A1, 0x54C1, 0xF9A2, 0x7A1F,
+	0xF9A3, 0x6953, 0xF9A4, 0x8AF7, 0xF9A5, 0x8C4A, 0xF9A6, 0x98A8,
+	0xF9A7, 0x99AE, 0xF9A8, 0x5F7C, 0xF9A9, 0x62AB, 0xF9AA, 0x75B2,
+	0xF9AB, 0x76AE, 0xF9AC, 0x88AB, 0xF9AD, 0x907F, 0xF9AE, 0x9642,
+	0xF9AF, 0x5339, 0xF9B0, 0x5F3C, 0xF9B1, 0x5FC5, 0xF9B2, 0x6CCC,
+	0xF9B3, 0x73CC, 0xF9B4, 0x7562, 0xF9B5, 0x758B, 0xF9B6, 0x7B46,
+	0xF9B7, 0x82FE, 0xF9B8, 0x999D, 0xF9B9, 0x4E4F, 0xF9BA, 0x903C,
+	0xF9BB, 0x4E0B, 0xF9BC, 0x4F55, 0xF9BD, 0x53A6, 0xF9BE, 0x590F,
+	0xF9BF, 0x5EC8, 0xF9C0, 0x6630, 0xF9C1, 0x6CB3, 0xF9C2, 0x7455,
+	0xF9C3, 0x8377, 0xF9C4, 0x8766, 0xF9C5, 0x8CC0, 0xF9C6, 0x9050,
+	0xF9C7, 0x971E, 0xF9C8, 0x9C15, 0xF9C9, 0x58D1, 0xF9CA, 0x5B78,
+	0xF9CB, 0x8650, 0xF9CC, 0x8B14, 0xF9CD, 0x9DB4, 0xF9CE, 0x5BD2,
+	0xF9CF, 0x6068, 0xF9D0, 0x608D, 0xF9D1, 0x65F1, 0xF9D2, 0x6C57,
+	0xF9D3, 0x6F22, 0xF9D4, 0x6FA3, 0xF9D5, 0x701A, 0xF9D6, 0x7F55,
+	0xF9D7, 0x7FF0, 0xF9D8, 0x9591, 0xF9D9, 0x9592, 0xF9DA, 0x9650,
+	0xF9DB, 0x97D3, 0xF9DC, 0x5272, 0xF9DD, 0x8F44, 0xF9DE, 0x51FD,
+	0xF9DF, 0x542B, 0xF9E0, 0x54B8, 0xF9E1, 0x5563, 0xF9E2, 0x558A,
+	0xF9E3, 0x6ABB, 0xF9E4, 0x6DB5, 0xF9E5, 0x7DD8, 0xF9E6, 0x8266,
+	0xF9E7, 0x929C, 0xF9E8, 0x9677, 0xF9E9, 0x9E79, 0xF9EA, 0x5408,
+	0xF9EB, 0x54C8, 0xF9EC, 0x76D2, 0xF9ED, 0x86E4, 0xF9EE, 0x95A4,
+	0xF9EF, 0x95D4, 0xF9F0, 0x965C, 0xF9F1, 0x4EA2, 0xF9F2, 0x4F09,
+	0xF9F3, 0x59EE, 0xF9F4, 0x5AE6, 0xF9F5, 0x5DF7, 0xF9F6, 0x6052,
+	0xF9F7, 0x6297, 0xF9F8, 0x676D, 0xF9F9, 0x6841, 0xF9FA, 0x6C86,
+	0xF9FB, 0x6E2F, 0xF9FC, 0x7F38, 0xF9FD, 0x809B, 0xF9FE, 0x822A,
+	0xFAA1, 0xFA08, 0xFAA2, 0xFA09, 0xFAA3, 0x9805, 0xFAA4, 0x4EA5,
+	0xFAA5, 0x5055, 0xFAA6, 0x54B3, 0xFAA7, 0x5793, 0xFAA8, 0x595A,
+	0xFAA9, 0x5B69, 0xFAAA, 0x5BB3, 0xFAAB, 0x61C8, 0xFAAC, 0x6977,
+	0xFAAD, 0x6D77, 0xFAAE, 0x7023, 0xFAAF, 0x87F9, 0xFAB0, 0x89E3,
+	0xFAB1, 0x8A72, 0xFAB2, 0x8AE7, 0xFAB3, 0x9082, 0xFAB4, 0x99ED,
+	0xFAB5, 0x9AB8, 0xFAB6, 0x52BE, 0xFAB7, 0x6838, 0xFAB8, 0x5016,
+	0xFAB9, 0x5E78, 0xFABA, 0x674F, 0xFABB, 0x8347, 0xFABC, 0x884C,
+	0xFABD, 0x4EAB, 0xFABE, 0x5411, 0xFABF, 0x56AE, 0xFAC0, 0x73E6,
+	0xFAC1, 0x9115, 0xFAC2, 0x97FF, 0xFAC3, 0x9909, 0xFAC4, 0x9957,
+	0xFAC5, 0x9999, 0xFAC6, 0x5653, 0xFAC7, 0x589F, 0xFAC8, 0x865B,
+	0xFAC9, 0x8A31, 0xFACA, 0x61B2, 0xFACB, 0x6AF6, 0xFACC, 0x737B,
+	0xFACD, 0x8ED2, 0xFACE, 0x6B47, 0xFACF, 0x96AA, 0xFAD0, 0x9A57,
+	0xFAD1, 0x5955, 0xFAD2, 0x7200, 0xFAD3, 0x8D6B, 0xFAD4, 0x9769,
+	0xFAD5, 0x4FD4, 0xFAD6, 0x5CF4, 0xFAD7, 0x5F26, 0xFAD8, 0x61F8,
+	0xFAD9, 0x665B, 0xFADA, 0x6CEB, 0xFADB, 0x70AB, 0xFADC, 0x7384,
+	0xFADD, 0x73B9, 0xFADE, 0x73FE, 0xFADF, 0x7729, 0xFAE0, 0x774D,
+	0xFAE1, 0x7D43, 0xFAE2, 0x7D62, 0xFAE3, 0x7E23, 0xFAE4, 0x8237,
+	0xFAE5, 0x8852, 0xFAE6, 0xFA0A, 0xFAE7, 0x8CE2, 0xFAE8, 0x9249,
+	0xFAE9, 0x986F, 0xFAEA, 0x5B51, 0xFAEB, 0x7A74, 0xFAEC, 0x8840,
+	0xFAED, 0x9801, 0xFAEE, 0x5ACC, 0xFAEF, 0x4FE0, 0xFAF0, 0x5354,
+	0xFAF1, 0x593E, 0xFAF2, 0x5CFD, 0xFAF3, 0x633E, 0xFAF4, 0x6D79,
+	0xFAF5, 0x72F9, 0xFAF6, 0x8105, 0xFAF7, 0x8107, 0xFAF8, 0x83A2,
+	0xFAF9, 0x92CF, 0xFAFA, 0x9830, 0xFAFB, 0x4EA8, 0xFAFC, 0x5144,
+	0xFAFD, 0x5211, 0xFAFE, 0x578B, 0xFBA1, 0x5F62, 0xFBA2, 0x6CC2,
+	0xFBA3, 0x6ECE, 0xFBA4, 0x7005, 0xFBA5, 0x7050, 0xFBA6, 0x70AF,
+	0xFBA7, 0x7192, 0xFBA8, 0x73E9, 0xFBA9, 0x7469, 0xFBAA, 0x834A,
+	0xFBAB, 0x87A2, 0xFBAC, 0x8861, 0xFBAD, 0x9008, 0xFBAE, 0x90A2,
+	0xFBAF, 0x93A3, 0xFBB0, 0x99A8, 0xFBB1, 0x516E, 0xFBB2, 0x5F57,
+	0xFBB3, 0x60E0, 0xFBB4, 0x6167, 0xFBB5, 0x66B3, 0xFBB6, 0x8559,
+	0xFBB7, 0x8E4A, 0xFBB8, 0x91AF, 0xFBB9, 0x978B, 0xFBBA, 0x4E4E,
+	0xFBBB, 0x4E92, 0xFBBC, 0x547C, 0xFBBD, 0x58D5, 0xFBBE, 0x58FA,
+	0xFBBF, 0x597D, 0xFBC0, 0x5CB5, 0xFBC1, 0x5F27, 0xFBC2, 0x6236,
+	0xFBC3, 0x6248, 0xFBC4, 0x660A, 0xFBC5, 0x6667, 0xFBC6, 0x6BEB,
+	0xFBC7, 0x6D69, 0xFBC8, 0x6DCF, 0xFBC9, 0x6E56, 0xFBCA, 0x6EF8,
+	0xFBCB, 0x6F94, 0xFBCC, 0x6FE0, 0xFBCD, 0x6FE9, 0xFBCE, 0x705D,
+	0xFBCF, 0x72D0, 0xFBD0, 0x7425, 0xFBD1, 0x745A, 0xFBD2, 0x74E0,
+	0xFBD3, 0x7693, 0xFBD4, 0x795C, 0xFBD5, 0x7CCA, 0xFBD6, 0x7E1E,
+	0xFBD7, 0x80E1, 0xFBD8, 0x82A6, 0xFBD9, 0x846B, 0xFBDA, 0x84BF,
+	0xFBDB, 0x864E, 0xFBDC, 0x865F, 0xFBDD, 0x8774, 0xFBDE, 0x8B77,
+	0xFBDF, 0x8C6A, 0xFBE0, 0x93AC, 0xFBE1, 0x9800, 0xFBE2, 0x9865,
+	0xFBE3, 0x60D1, 0xFBE4, 0x6216, 0xFBE5, 0x9177, 0xFBE6, 0x5A5A,
+	0xFBE7, 0x660F, 0xFBE8, 0x6DF7, 0xFBE9, 0x6E3E, 0xFBEA, 0x743F,
+	0xFBEB, 0x9B42, 0xFBEC, 0x5FFD, 0xFBED, 0x60DA, 0xFBEE, 0x7B0F,
+	0xFBEF, 0x54C4, 0xFBF0, 0x5F18, 0xFBF1, 0x6C5E, 0xFBF2, 0x6CD3,
+	0xFBF3, 0x6D2A, 0xFBF4, 0x70D8, 0xFBF5, 0x7D05, 0xFBF6, 0x8679,
+	0xFBF7, 0x8A0C, 0xFBF8, 0x9D3B, 0xFBF9, 0x5316, 0xFBFA, 0x548C,
+	0xFBFB, 0x5B05, 0xFBFC, 0x6A3A, 0xFBFD, 0x706B, 0xFBFE, 0x7575,
+	0xFCA1, 0x798D, 0xFCA2, 0x79BE, 0xFCA3, 0x82B1, 0xFCA4, 0x83EF,
+	0xFCA5, 0x8A71, 0xFCA6, 0x8B41, 0xFCA7, 0x8CA8, 0xFCA8, 0x9774,
+	0xFCA9, 0xFA0B, 0xFCAA, 0x64F4, 0xFCAB, 0x652B, 0xFCAC, 0x78BA,
+	0xFCAD, 0x78BB, 0xFCAE, 0x7A6B, 0xFCAF, 0x4E38, 0xFCB0, 0x559A,
+	0xFCB1, 0x5950, 0xFCB2, 0x5BA6, 0xFCB3, 0x5E7B, 0xFCB4, 0x60A3,
+	0xFCB5, 0x63DB, 0xFCB6, 0x6B61, 0xFCB7, 0x6665, 0xFCB8, 0x6853,
+	0xFCB9, 0x6E19, 0xFCBA, 0x7165, 0xFCBB, 0x74B0, 0xFCBC, 0x7D08,
+	0xFCBD, 0x9084, 0xFCBE, 0x9A69, 0xFCBF, 0x9C25, 0xFCC0, 0x6D3B,
+	0xFCC1, 0x6ED1, 0xFCC2, 0x733E, 0xFCC3, 0x8C41, 0xFCC4, 0x95CA,
+	0xFCC5, 0x51F0, 0xFCC6, 0x5E4C, 0xFCC7, 0x5FA8, 0xFCC8, 0x604D,
+	0xFCC9, 0x60F6, 0xFCCA, 0x6130, 0xFCCB, 0x614C, 0xFCCC, 0x6643,
+	0xFCCD, 0x6644, 0xFCCE, 0x69A5, 0xFCCF, 0x6CC1, 0xFCD0, 0x6E5F,
+	0xFCD1, 0x6EC9, 0xFCD2, 0x6F62, 0xFCD3, 0x714C, 0xFCD4, 0x749C,
+	0xFCD5, 0x7687, 0xFCD6, 0x7BC1, 0xFCD7, 0x7C27, 0xFCD8, 0x8352,
+	0xFCD9, 0x8757, 0xFCDA, 0x9051, 0xFCDB, 0x968D, 0xFCDC, 0x9EC3,
+	0xFCDD, 0x532F, 0xFCDE, 0x56DE, 0xFCDF, 0x5EFB, 0xFCE0, 0x5F8A,
+	0xFCE1, 0x6062, 0xFCE2, 0x6094, 0xFCE3, 0x61F7, 0xFCE4, 0x6666,
+	0xFCE5, 0x6703, 0xFCE6, 0x6A9C, 0xFCE7, 0x6DEE, 0xFCE8, 0x6FAE,
+	0xFCE9, 0x7070, 0xFCEA, 0x736A, 0xFCEB, 0x7E6A, 0xFCEC, 0x81BE,
+	0xFCED, 0x8334, 0xFCEE, 0x86D4, 0xFCEF, 0x8AA8, 0xFCF0, 0x8CC4,
+	0xFCF1, 0x5283, 0xFCF2, 0x7372, 0xFCF3, 0x5B96, 0xFCF4, 0x6A6B,
+	0xFCF5, 0x9404, 0xFCF6, 0x54EE, 0xFCF7, 0x5686, 0xFCF8, 0x5B5D,
+	0xFCF9, 0x6548, 0xFCFA, 0x6585, 0xFCFB, 0x66C9, 0xFCFC, 0x689F,
+	0xFCFD, 0x6D8D, 0xFCFE, 0x6DC6, 0xFDA1, 0x723B, 0xFDA2, 0x80B4,
+	0xFDA3, 0x9175, 0xFDA4, 0x9A4D, 0xFDA5, 0x4FAF, 0xFDA6, 0x5019,
+	0xFDA7, 0x539A, 0xFDA8, 0x540E, 0xFDA9, 0x543C, 0xFDAA, 0x5589,
+	0xFDAB, 0x55C5, 0xFDAC, 0x5E3F, 0xFDAD, 0x5F8C, 0xFDAE, 0x673D,
+	0xFDAF, 0x7166, 0xFDB0, 0x73DD, 0xFDB1, 0x9005, 0xFDB2, 0x52DB,
+	0xFDB3, 0x52F3, 0xFDB4, 0x5864, 0xFDB5, 0x58CE, 0xFDB6, 0x7104,
+	0xFDB7, 0x718F, 0xFDB8, 0x71FB, 0xFDB9, 0x85B0, 0xFDBA, 0x8A13,
+	0xFDBB, 0x6688, 0xFDBC, 0x85A8, 0xFDBD, 0x55A7, 0xFDBE, 0x6684,
+	0xFDBF, 0x714A, 0xFDC0, 0x8431, 0xFDC1, 0x5349, 0xFDC2, 0x5599,
+	0xFDC3, 0x6BC1, 0xFDC4, 0x5F59, 0xFDC5, 0x5FBD, 0xFDC6, 0x63EE,
+	0xFDC7, 0x6689, 0xFDC8, 0x7147, 0xFDC9, 0x8AF1, 0xFDCA, 0x8F1D,
+	0xFDCB, 0x9EBE, 0xFDCC, 0x4F11, 0xFDCD, 0x643A, 0xFDCE, 0x70CB,
+	0xFDCF, 0x7566, 0xFDD0, 0x8667, 0xFDD1, 0x6064, 0xFDD2, 0x8B4E,
+	0xFDD3, 0x9DF8, 0xFDD4, 0x5147, 0xFDD5, 0x51F6, 0xFDD6, 0x5308,
+	0xFDD7, 0x6D36, 0xFDD8, 0x80F8, 0xFDD9, 0x9ED1, 0xFDDA, 0x6615,
+	0xFDDB, 0x6B23, 0xFDDC, 0x7098, 0xFDDD, 0x75D5, 0xFDDE, 0x5403,
+	0xFDDF, 0x5C79, 0xFDE0, 0x7D07, 0xFDE1, 0x8A16, 0xFDE2, 0x6B20,
+	0xFDE3, 0x6B3D, 0xFDE4, 0x6B46, 0xFDE5, 0x5438, 0xFDE6, 0x6070,
+	0xFDE7, 0x6D3D, 0xFDE8, 0x7FD5, 0xFDE9, 0x8208, 0xFDEA, 0x50D6,
+	0xFDEB, 0x51DE, 0xFDEC, 0x559C, 0xFDED, 0x566B, 0xFDEE, 0x56CD,
+	0xFDEF, 0x59EC, 0xFDF0, 0x5B09, 0xFDF1, 0x5E0C, 0xFDF2, 0x6199,
+	0xFDF3, 0x6198, 0xFDF4, 0x6231, 0xFDF5, 0x665E, 0xFDF6, 0x66E6,
+	0xFDF7, 0x7199, 0xFDF8, 0x71B9, 0xFDF9, 0x71BA, 0xFDFA, 0x72A7,
+	0xFDFB, 0x79A7, 0xFDFC, 0x7A00, 0xFDFD, 0x7FB2, 0xFDFE, 0x8A70,
+	0, 0
+};
+
+
+
+WCHAR ff_convert (	/* Converted code, 0 means conversion error */
+	WCHAR	src,	/* Character code to be converted */
+	UINT	dir		/* 0: Unicode to OEMCP, 1: OEMCP to Unicode */
+)
+{
+	const WCHAR *p;
+	WCHAR c;
+	int i, n, li, hi;
+
+
+	if (src < 0x80) {	/* ASCII */
+		c = src;
+	} else {
+		if (dir) {		/* OEMCP to unicode */
+			p = oem2uni;
+			hi = sizeof(oem2uni) / 4 - 1;
+		} else {		/* Unicode to OEMCP */
+			p = uni2oem;
+			hi = sizeof(uni2oem) / 4 - 1;
+		}
+		li = 0;
+		for (n = 16; n; n--) {
+			i = li + (hi - li) / 2;
+			if (src == p[i * 2]) break;
+			if (src > p[i * 2])
+				li = i;
+			else
+				hi = i;
+		}
+		c = n ? p[i * 2 + 1] : 0;
+	}
+
+	return c;
+}
+#else
+#error This file is not needed in current configuration.
+
+#endif
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/option/cc950.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/option/cc950.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/option/cc950.c	(revision 453)
@@ -0,0 +1,6814 @@
+/*------------------------------------------------------------------------*/
+/* Unicode - OEM code bidirectional converter  (C)ChaN, 2009              */
+/*                                                                        */
+/* CP950 (Traditional Chinese Big5)                                       */
+/*------------------------------------------------------------------------*/
+
+#include "../ff.h"
+
+
+#if _USE_LFN && _CODE_PAGE == 950
+
+
+static
+const WCHAR uni2oem[] = {
+/*  Unicode - OEM,  Unicode - OEM,  Unicode - OEM,  Unicode - OEM */
+	0x00A7, 0xA1B1, 0x00AF, 0xA1C2, 0x00B0, 0xA258, 0x00B1, 0xA1D3,
+	0x00B7, 0xA150, 0x00D7, 0xA1D1, 0x00F7, 0xA1D2, 0x02C7, 0xA3BE,
+	0x02C9, 0xA3BC, 0x02CA, 0xA3BD, 0x02CB, 0xA3BF, 0x02CD, 0xA1C5,
+	0x02D9, 0xA3BB, 0x0391, 0xA344, 0x0392, 0xA345, 0x0393, 0xA346,
+	0x0394, 0xA347, 0x0395, 0xA348, 0x0396, 0xA349, 0x0397, 0xA34A,
+	0x0398, 0xA34B, 0x0399, 0xA34C, 0x039A, 0xA34D, 0x039B, 0xA34E,
+	0x039C, 0xA34F, 0x039D, 0xA350, 0x039E, 0xA351, 0x039F, 0xA352,
+	0x03A0, 0xA353, 0x03A1, 0xA354, 0x03A3, 0xA355, 0x03A4, 0xA356,
+	0x03A5, 0xA357, 0x03A6, 0xA358, 0x03A7, 0xA359, 0x03A8, 0xA35A,
+	0x03A9, 0xA35B, 0x03B1, 0xA35C, 0x03B2, 0xA35D, 0x03B3, 0xA35E,
+	0x03B4, 0xA35F, 0x03B5, 0xA360, 0x03B6, 0xA361, 0x03B7, 0xA362,
+	0x03B8, 0xA363, 0x03B9, 0xA364, 0x03BA, 0xA365, 0x03BB, 0xA366,
+	0x03BC, 0xA367, 0x03BD, 0xA368, 0x03BE, 0xA369, 0x03BF, 0xA36A,
+	0x03C0, 0xA36B, 0x03C1, 0xA36C, 0x03C3, 0xA36D, 0x03C4, 0xA36E,
+	0x03C5, 0xA36F, 0x03C6, 0xA370, 0x03C7, 0xA371, 0x03C8, 0xA372,
+	0x03C9, 0xA373, 0x2013, 0xA156, 0x2014, 0xA158, 0x2018, 0xA1A5,
+	0x2019, 0xA1A6, 0x201C, 0xA1A7, 0x201D, 0xA1A8, 0x2025, 0xA14C,
+	0x2026, 0xA14B, 0x2027, 0xA145, 0x2032, 0xA1AC, 0x2035, 0xA1AB,
+	0x203B, 0xA1B0, 0x20AC, 0xA3E1, 0x2103, 0xA24A, 0x2105, 0xA1C1,
+	0x2109, 0xA24B, 0x2160, 0xA2B9, 0x2161, 0xA2BA, 0x2162, 0xA2BB,
+	0x2163, 0xA2BC, 0x2164, 0xA2BD, 0x2165, 0xA2BE, 0x2166, 0xA2BF,
+	0x2167, 0xA2C0, 0x2168, 0xA2C1, 0x2169, 0xA2C2, 0x2190, 0xA1F6,
+	0x2191, 0xA1F4, 0x2192, 0xA1F7, 0x2193, 0xA1F5, 0x2196, 0xA1F8,
+	0x2197, 0xA1F9, 0x2198, 0xA1FB, 0x2199, 0xA1FA, 0x2215, 0xA241,
+	0x221A, 0xA1D4, 0x221E, 0xA1DB, 0x221F, 0xA1E8, 0x2220, 0xA1E7,
+	0x2223, 0xA1FD, 0x2225, 0xA1FC, 0x2229, 0xA1E4, 0x222A, 0xA1E5,
+	0x222B, 0xA1EC, 0x222E, 0xA1ED, 0x2234, 0xA1EF, 0x2235, 0xA1EE,
+	0x2252, 0xA1DC, 0x2260, 0xA1DA, 0x2261, 0xA1DD, 0x2266, 0xA1D8,
+	0x2267, 0xA1D9, 0x2295, 0xA1F2, 0x2299, 0xA1F3, 0x22A5, 0xA1E6,
+	0x22BF, 0xA1E9, 0x2500, 0xA277, 0x2502, 0xA278, 0x250C, 0xA27A,
+	0x2510, 0xA27B, 0x2514, 0xA27C, 0x2518, 0xA27D, 0x251C, 0xA275,
+	0x2524, 0xA274, 0x252C, 0xA273, 0x2534, 0xA272, 0x253C, 0xA271,
+	0x2550, 0xA2A4, 0x2550, 0xF9F9, 0x2551, 0xF9F8, 0x2552, 0xF9E6,
+	0x2553, 0xF9EF, 0x2554, 0xF9DD, 0x2555, 0xF9E8, 0x2556, 0xF9F1,
+	0x2557, 0xF9DF, 0x2558, 0xF9EC, 0x2559, 0xF9F5, 0x255A, 0xF9E3,
+	0x255B, 0xF9EE, 0x255C, 0xF9F7, 0x255D, 0xF9E5, 0x255E, 0xA2A5,
+	0x255E, 0xF9E9, 0x255F, 0xF9F2, 0x2560, 0xF9E0, 0x2561, 0xA2A7,
+	0x2561, 0xF9EB, 0x2562, 0xF9F4, 0x2563, 0xF9E2, 0x2564, 0xF9E7,
+	0x2565, 0xF9F0, 0x2566, 0xF9DE, 0x2567, 0xF9ED, 0x2568, 0xF9F6,
+	0x2569, 0xF9E4, 0x256A, 0xA2A6, 0x256A, 0xF9EA, 0x256B, 0xF9F3,
+	0x256C, 0xF9E1, 0x256D, 0xA27E, 0x256D, 0xF9FA, 0x256E, 0xA2A1,
+	0x256E, 0xF9FB, 0x256F, 0xA2A3, 0x256F, 0xF9FD, 0x2570, 0xA2A2,
+	0x2570, 0xF9FC, 0x2571, 0xA2AC, 0x2572, 0xA2AD, 0x2573, 0xA2AE,
+	0x2574, 0xA15A, 0x2581, 0xA262, 0x2582, 0xA263, 0x2583, 0xA264,
+	0x2584, 0xA265, 0x2585, 0xA266, 0x2586, 0xA267, 0x2587, 0xA268,
+	0x2588, 0xA269, 0x2589, 0xA270, 0x258A, 0xA26F, 0x258B, 0xA26E,
+	0x258C, 0xA26D, 0x258D, 0xA26C, 0x258E, 0xA26B, 0x258F, 0xA26A,
+	0x2593, 0xF9FE, 0x2594, 0xA276, 0x2595, 0xA279, 0x25A0, 0xA1BD,
+	0x25A1, 0xA1BC, 0x25B2, 0xA1B6, 0x25B3, 0xA1B5, 0x25BC, 0xA1BF,
+	0x25BD, 0xA1BE, 0x25C6, 0xA1BB, 0x25C7, 0xA1BA, 0x25CB, 0xA1B3,
+	0x25CE, 0xA1B7, 0x25CF, 0xA1B4, 0x25E2, 0xA2A8, 0x25E3, 0xA2A9,
+	0x25E4, 0xA2AB, 0x25E5, 0xA2AA, 0x2605, 0xA1B9, 0x2606, 0xA1B8,
+	0x2640, 0xA1F0, 0x2642, 0xA1F1, 0x3000, 0xA140, 0x3001, 0xA142,
+	0x3002, 0xA143, 0x3003, 0xA1B2, 0x3008, 0xA171, 0x3009, 0xA172,
+	0x300A, 0xA16D, 0x300B, 0xA16E, 0x300C, 0xA175, 0x300D, 0xA176,
+	0x300E, 0xA179, 0x300F, 0xA17A, 0x3010, 0xA169, 0x3011, 0xA16A,
+	0x3012, 0xA245, 0x3014, 0xA165, 0x3015, 0xA166, 0x301D, 0xA1A9,
+	0x301E, 0xA1AA, 0x3021, 0xA2C3, 0x3022, 0xA2C4, 0x3023, 0xA2C5,
+	0x3024, 0xA2C6, 0x3025, 0xA2C7, 0x3026, 0xA2C8, 0x3027, 0xA2C9,
+	0x3028, 0xA2CA, 0x3029, 0xA2CB, 0x3105, 0xA374, 0x3106, 0xA375,
+	0x3107, 0xA376, 0x3108, 0xA377, 0x3109, 0xA378, 0x310A, 0xA379,
+	0x310B, 0xA37A, 0x310C, 0xA37B, 0x310D, 0xA37C, 0x310E, 0xA37D,
+	0x310F, 0xA37E, 0x3110, 0xA3A1, 0x3111, 0xA3A2, 0x3112, 0xA3A3,
+	0x3113, 0xA3A4, 0x3114, 0xA3A5, 0x3115, 0xA3A6, 0x3116, 0xA3A7,
+	0x3117, 0xA3A8, 0x3118, 0xA3A9, 0x3119, 0xA3AA, 0x311A, 0xA3AB,
+	0x311B, 0xA3AC, 0x311C, 0xA3AD, 0x311D, 0xA3AE, 0x311E, 0xA3AF,
+	0x311F, 0xA3B0, 0x3120, 0xA3B1, 0x3121, 0xA3B2, 0x3122, 0xA3B3,
+	0x3123, 0xA3B4, 0x3124, 0xA3B5, 0x3125, 0xA3B6, 0x3126, 0xA3B7,
+	0x3127, 0xA3B8, 0x3128, 0xA3B9, 0x3129, 0xA3BA, 0x32A3, 0xA1C0,
+	0x338E, 0xA255, 0x338F, 0xA256, 0x339C, 0xA250, 0x339D, 0xA251,
+	0x339E, 0xA252, 0x33A1, 0xA254, 0x33C4, 0xA257, 0x33CE, 0xA253,
+	0x33D1, 0xA1EB, 0x33D2, 0xA1EA, 0x33D5, 0xA24F, 0x4E00, 0xA440,
+	0x4E01, 0xA442, 0x4E03, 0xA443, 0x4E07, 0xC945, 0x4E08, 0xA456,
+	0x4E09, 0xA454, 0x4E0A, 0xA457, 0x4E0B, 0xA455, 0x4E0C, 0xC946,
+	0x4E0D, 0xA4A3, 0x4E0E, 0xC94F, 0x4E0F, 0xC94D, 0x4E10, 0xA4A2,
+	0x4E11, 0xA4A1, 0x4E14, 0xA542, 0x4E15, 0xA541, 0x4E16, 0xA540,
+	0x4E18, 0xA543, 0x4E19, 0xA4FE, 0x4E1E, 0xA5E0, 0x4E1F, 0xA5E1,
+	0x4E26, 0xA8C3, 0x4E2B, 0xA458, 0x4E2D, 0xA4A4, 0x4E2E, 0xC950,
+	0x4E30, 0xA4A5, 0x4E31, 0xC963, 0x4E32, 0xA6EA, 0x4E33, 0xCBB1,
+	0x4E38, 0xA459, 0x4E39, 0xA4A6, 0x4E3B, 0xA544, 0x4E3C, 0xC964,
+	0x4E42, 0xC940, 0x4E43, 0xA444, 0x4E45, 0xA45B, 0x4E47, 0xC947,
+	0x4E48, 0xA45C, 0x4E4B, 0xA4A7, 0x4E4D, 0xA545, 0x4E4E, 0xA547,
+	0x4E4F, 0xA546, 0x4E52, 0xA5E2, 0x4E53, 0xA5E3, 0x4E56, 0xA8C4,
+	0x4E58, 0xADBC, 0x4E59, 0xA441, 0x4E5C, 0xC941, 0x4E5D, 0xA445,
+	0x4E5E, 0xA45E, 0x4E5F, 0xA45D, 0x4E69, 0xA5E4, 0x4E73, 0xA8C5,
+	0x4E7E, 0xB0AE, 0x4E7F, 0xD44B, 0x4E82, 0xB6C3, 0x4E83, 0xDCB1,
+	0x4E84, 0xDCB2, 0x4E86, 0xA446, 0x4E88, 0xA4A9, 0x4E8B, 0xA8C6,
+	0x4E8C, 0xA447, 0x4E8D, 0xC948, 0x4E8E, 0xA45F, 0x4E91, 0xA4AA,
+	0x4E92, 0xA4AC, 0x4E93, 0xC951, 0x4E94, 0xA4AD, 0x4E95, 0xA4AB,
+	0x4E99, 0xA5E5, 0x4E9B, 0xA8C7, 0x4E9E, 0xA8C8, 0x4E9F, 0xAB45,
+	0x4EA1, 0xA460, 0x4EA2, 0xA4AE, 0x4EA4, 0xA5E6, 0x4EA5, 0xA5E8,
+	0x4EA6, 0xA5E7, 0x4EA8, 0xA6EB, 0x4EAB, 0xA8C9, 0x4EAC, 0xA8CA,
+	0x4EAD, 0xAB46, 0x4EAE, 0xAB47, 0x4EB3, 0xADBD, 0x4EB6, 0xDCB3,
+	0x4EB9, 0xF6D6, 0x4EBA, 0xA448, 0x4EC0, 0xA4B0, 0x4EC1, 0xA4AF,
+	0x4EC2, 0xC952, 0x4EC3, 0xA4B1, 0x4EC4, 0xA4B7, 0x4EC6, 0xA4B2,
+	0x4EC7, 0xA4B3, 0x4EC8, 0xC954, 0x4EC9, 0xC953, 0x4ECA, 0xA4B5,
+	0x4ECB, 0xA4B6, 0x4ECD, 0xA4B4, 0x4ED4, 0xA54A, 0x4ED5, 0xA54B,
+	0x4ED6, 0xA54C, 0x4ED7, 0xA54D, 0x4ED8, 0xA549, 0x4ED9, 0xA550,
+	0x4EDA, 0xC96A, 0x4EDC, 0xC966, 0x4EDD, 0xC969, 0x4EDE, 0xA551,
+	0x4EDF, 0xA561, 0x4EE1, 0xC968, 0x4EE3, 0xA54E, 0x4EE4, 0xA54F,
+	0x4EE5, 0xA548, 0x4EE8, 0xC965, 0x4EE9, 0xC967, 0x4EF0, 0xA5F5,
+	0x4EF1, 0xC9B0, 0x4EF2, 0xA5F2, 0x4EF3, 0xA5F6, 0x4EF4, 0xC9BA,
+	0x4EF5, 0xC9AE, 0x4EF6, 0xA5F3, 0x4EF7, 0xC9B2, 0x4EFB, 0xA5F4,
+	0x4EFD, 0xA5F7, 0x4EFF, 0xA5E9, 0x4F00, 0xC9B1, 0x4F01, 0xA5F8,
+	0x4F02, 0xC9B5, 0x4F04, 0xC9B9, 0x4F05, 0xC9B6, 0x4F08, 0xC9B3,
+	0x4F09, 0xA5EA, 0x4F0A, 0xA5EC, 0x4F0B, 0xA5F9, 0x4F0D, 0xA5EE,
+	0x4F0E, 0xC9AB, 0x4F0F, 0xA5F1, 0x4F10, 0xA5EF, 0x4F11, 0xA5F0,
+	0x4F12, 0xC9BB, 0x4F13, 0xC9B8, 0x4F14, 0xC9AF, 0x4F15, 0xA5ED,
+	0x4F18, 0xC9AC, 0x4F19, 0xA5EB, 0x4F1D, 0xC9B4, 0x4F22, 0xC9B7,
+	0x4F2C, 0xC9AD, 0x4F2D, 0xCA66, 0x4F2F, 0xA742, 0x4F30, 0xA6F4,
+	0x4F33, 0xCA67, 0x4F34, 0xA6F1, 0x4F36, 0xA744, 0x4F38, 0xA6F9,
+	0x4F3A, 0xA6F8, 0x4F3B, 0xCA5B, 0x4F3C, 0xA6FC, 0x4F3D, 0xA6F7,
+	0x4F3E, 0xCA60, 0x4F3F, 0xCA68, 0x4F41, 0xCA64, 0x4F43, 0xA6FA,
+	0x4F46, 0xA6FD, 0x4F47, 0xA6EE, 0x4F48, 0xA747, 0x4F49, 0xCA5D,
+	0x4F4C, 0xCBBD, 0x4F4D, 0xA6EC, 0x4F4E, 0xA743, 0x4F4F, 0xA6ED,
+	0x4F50, 0xA6F5, 0x4F51, 0xA6F6, 0x4F52, 0xCA62, 0x4F53, 0xCA5E,
+	0x4F54, 0xA6FB, 0x4F55, 0xA6F3, 0x4F56, 0xCA5A, 0x4F57, 0xA6EF,
+	0x4F58, 0xCA65, 0x4F59, 0xA745, 0x4F5A, 0xA748, 0x4F5B, 0xA6F2,
+	0x4F5C, 0xA740, 0x4F5D, 0xA746, 0x4F5E, 0xA6F0, 0x4F5F, 0xCA63,
+	0x4F60, 0xA741, 0x4F61, 0xCA69, 0x4F62, 0xCA5C, 0x4F63, 0xA6FE,
+	0x4F64, 0xCA5F, 0x4F67, 0xCA61, 0x4F69, 0xA8D8, 0x4F6A, 0xCBBF,
+	0x4F6B, 0xCBCB, 0x4F6C, 0xA8D0, 0x4F6E, 0xCBCC, 0x4F6F, 0xA8CB,
+	0x4F70, 0xA8D5, 0x4F73, 0xA8CE, 0x4F74, 0xCBB9, 0x4F75, 0xA8D6,
+	0x4F76, 0xCBB8, 0x4F77, 0xCBBC, 0x4F78, 0xCBC3, 0x4F79, 0xCBC1,
+	0x4F7A, 0xA8DE, 0x4F7B, 0xA8D9, 0x4F7C, 0xCBB3, 0x4F7D, 0xCBB5,
+	0x4F7E, 0xA8DB, 0x4F7F, 0xA8CF, 0x4F80, 0xCBB6, 0x4F81, 0xCBC2,
+	0x4F82, 0xCBC9, 0x4F83, 0xA8D4, 0x4F84, 0xCBBB, 0x4F85, 0xCBB4,
+	0x4F86, 0xA8D3, 0x4F87, 0xCBB7, 0x4F88, 0xA8D7, 0x4F89, 0xCBBA,
+	0x4F8B, 0xA8D2, 0x4F8D, 0xA8CD, 0x4F8F, 0xA8DC, 0x4F90, 0xCBC4,
+	0x4F91, 0xA8DD, 0x4F92, 0xCBC8, 0x4F94, 0xCBC6, 0x4F95, 0xCBCA,
+	0x4F96, 0xA8DA, 0x4F97, 0xCBBE, 0x4F98, 0xCBB2, 0x4F9A, 0xCBC0,
+	0x4F9B, 0xA8D1, 0x4F9C, 0xCBC5, 0x4F9D, 0xA8CC, 0x4F9E, 0xCBC7,
+	0x4FAE, 0xAB56, 0x4FAF, 0xAB4A, 0x4FB2, 0xCDE0, 0x4FB3, 0xCDE8,
+	0x4FB5, 0xAB49, 0x4FB6, 0xAB51, 0x4FB7, 0xAB5D, 0x4FB9, 0xCDEE,
+	0x4FBA, 0xCDEC, 0x4FBB, 0xCDE7, 0x4FBF, 0xAB4B, 0x4FC0, 0xCDED,
+	0x4FC1, 0xCDE3, 0x4FC2, 0xAB59, 0x4FC3, 0xAB50, 0x4FC4, 0xAB58,
+	0x4FC5, 0xCDDE, 0x4FC7, 0xCDEA, 0x4FC9, 0xCDE1, 0x4FCA, 0xAB54,
+	0x4FCB, 0xCDE2, 0x4FCD, 0xCDDD, 0x4FCE, 0xAB5B, 0x4FCF, 0xAB4E,
+	0x4FD0, 0xAB57, 0x4FD1, 0xAB4D, 0x4FD3, 0xCDDF, 0x4FD4, 0xCDE4,
+	0x4FD6, 0xCDEB, 0x4FD7, 0xAB55, 0x4FD8, 0xAB52, 0x4FD9, 0xCDE6,
+	0x4FDA, 0xAB5A, 0x4FDB, 0xCDE9, 0x4FDC, 0xCDE5, 0x4FDD, 0xAB4F,
+	0x4FDE, 0xAB5C, 0x4FDF, 0xAB53, 0x4FE0, 0xAB4C, 0x4FE1, 0xAB48,
+	0x4FEC, 0xCDEF, 0x4FEE, 0xADD7, 0x4FEF, 0xADC1, 0x4FF1, 0xADD1,
+	0x4FF3, 0xADD6, 0x4FF4, 0xD0D0, 0x4FF5, 0xD0CF, 0x4FF6, 0xD0D4,
+	0x4FF7, 0xD0D5, 0x4FF8, 0xADC4, 0x4FFA, 0xADCD, 0x4FFE, 0xADDA,
+	0x5000, 0xADCE, 0x5005, 0xD0C9, 0x5006, 0xADC7, 0x5007, 0xD0CA,
+	0x5009, 0xADDC, 0x500B, 0xADD3, 0x500C, 0xADBE, 0x500D, 0xADBF,
+	0x500E, 0xD0DD, 0x500F, 0xB0BF, 0x5011, 0xADCC, 0x5012, 0xADCB,
+	0x5013, 0xD0CB, 0x5014, 0xADCF, 0x5015, 0xD45B, 0x5016, 0xADC6,
+	0x5017, 0xD0D6, 0x5018, 0xADD5, 0x5019, 0xADD4, 0x501A, 0xADCA,
+	0x501B, 0xD0CE, 0x501C, 0xD0D7, 0x501E, 0xD0C8, 0x501F, 0xADC9,
+	0x5020, 0xD0D8, 0x5021, 0xADD2, 0x5022, 0xD0CC, 0x5023, 0xADC0,
+	0x5025, 0xADC3, 0x5026, 0xADC2, 0x5027, 0xD0D9, 0x5028, 0xADD0,
+	0x5029, 0xADC5, 0x502A, 0xADD9, 0x502B, 0xADDB, 0x502C, 0xD0D3,
+	0x502D, 0xADD8, 0x502F, 0xD0DB, 0x5030, 0xD0CD, 0x5031, 0xD0DC,
+	0x5033, 0xD0D1, 0x5035, 0xD0DA, 0x5037, 0xD0D2, 0x503C, 0xADC8,
+	0x5040, 0xD463, 0x5041, 0xD457, 0x5043, 0xB0B3, 0x5045, 0xD45C,
+	0x5046, 0xD462, 0x5047, 0xB0B2, 0x5048, 0xD455, 0x5049, 0xB0B6,
+	0x504A, 0xD459, 0x504B, 0xD452, 0x504C, 0xB0B4, 0x504D, 0xD456,
+	0x504E, 0xB0B9, 0x504F, 0xB0BE, 0x5051, 0xD467, 0x5053, 0xD451,
+	0x5055, 0xB0BA, 0x5057, 0xD466, 0x505A, 0xB0B5, 0x505B, 0xD458,
+	0x505C, 0xB0B1, 0x505D, 0xD453, 0x505E, 0xD44F, 0x505F, 0xD45D,
+	0x5060, 0xD450, 0x5061, 0xD44E, 0x5062, 0xD45A, 0x5063, 0xD460,
+	0x5064, 0xD461, 0x5065, 0xB0B7, 0x5068, 0xD85B, 0x5069, 0xD45E,
+	0x506A, 0xD44D, 0x506B, 0xD45F, 0x506D, 0xB0C1, 0x506E, 0xD464,
+	0x506F, 0xB0C0, 0x5070, 0xD44C, 0x5072, 0xD454, 0x5073, 0xD465,
+	0x5074, 0xB0BC, 0x5075, 0xB0BB, 0x5076, 0xB0B8, 0x5077, 0xB0BD,
+	0x507A, 0xB0AF, 0x507D, 0xB0B0, 0x5080, 0xB3C8, 0x5082, 0xD85E,
+	0x5083, 0xD857, 0x5085, 0xB3C5, 0x5087, 0xD85F, 0x508B, 0xD855,
+	0x508C, 0xD858, 0x508D, 0xB3C4, 0x508E, 0xD859, 0x5091, 0xB3C7,
+	0x5092, 0xD85D, 0x5094, 0xD853, 0x5095, 0xD852, 0x5096, 0xB3C9,
+	0x5098, 0xB3CA, 0x5099, 0xB3C6, 0x509A, 0xB3CB, 0x509B, 0xD851,
+	0x509C, 0xD85C, 0x509D, 0xD85A, 0x509E, 0xD854, 0x50A2, 0xB3C3,
+	0x50A3, 0xD856, 0x50AC, 0xB6CA, 0x50AD, 0xB6C4, 0x50AE, 0xDCB7,
+	0x50AF, 0xB6CD, 0x50B0, 0xDCBD, 0x50B1, 0xDCC0, 0x50B2, 0xB6C6,
+	0x50B3, 0xB6C7, 0x50B4, 0xDCBA, 0x50B5, 0xB6C5, 0x50B6, 0xDCC3,
+	0x50B7, 0xB6CB, 0x50B8, 0xDCC4, 0x50BA, 0xDCBF, 0x50BB, 0xB6CC,
+	0x50BD, 0xDCB4, 0x50BE, 0xB6C9, 0x50BF, 0xDCB5, 0x50C1, 0xDCBE,
+	0x50C2, 0xDCBC, 0x50C4, 0xDCB8, 0x50C5, 0xB6C8, 0x50C6, 0xDCB6,
+	0x50C7, 0xB6CE, 0x50C8, 0xDCBB, 0x50C9, 0xDCC2, 0x50CA, 0xDCB9,
+	0x50CB, 0xDCC1, 0x50CE, 0xB9B6, 0x50CF, 0xB9B3, 0x50D1, 0xB9B4,
+	0x50D3, 0xE0F9, 0x50D4, 0xE0F1, 0x50D5, 0xB9B2, 0x50D6, 0xB9AF,
+	0x50D7, 0xE0F2, 0x50DA, 0xB9B1, 0x50DB, 0xE0F5, 0x50DD, 0xE0F7,
+	0x50E0, 0xE0FE, 0x50E3, 0xE0FD, 0x50E4, 0xE0F8, 0x50E5, 0xB9AE,
+	0x50E6, 0xE0F0, 0x50E7, 0xB9AC, 0x50E8, 0xE0F3, 0x50E9, 0xB9B7,
+	0x50EA, 0xE0F6, 0x50EC, 0xE0FA, 0x50ED, 0xB9B0, 0x50EE, 0xB9AD,
+	0x50EF, 0xE0FC, 0x50F0, 0xE0FB, 0x50F1, 0xB9B5, 0x50F3, 0xE0F4,
+	0x50F5, 0xBBF8, 0x50F6, 0xE4EC, 0x50F8, 0xE4E9, 0x50F9, 0xBBF9,
+	0x50FB, 0xBBF7, 0x50FD, 0xE4F0, 0x50FE, 0xE4ED, 0x50FF, 0xE4E6,
+	0x5100, 0xBBF6, 0x5102, 0xBBFA, 0x5103, 0xE4E7, 0x5104, 0xBBF5,
+	0x5105, 0xBBFD, 0x5106, 0xE4EA, 0x5107, 0xE4EB, 0x5108, 0xBBFB,
+	0x5109, 0xBBFC, 0x510A, 0xE4F1, 0x510B, 0xE4EE, 0x510C, 0xE4EF,
+	0x5110, 0xBEAA, 0x5111, 0xE8F8, 0x5112, 0xBEA7, 0x5113, 0xE8F5,
+	0x5114, 0xBEA9, 0x5115, 0xBEAB, 0x5117, 0xE8F6, 0x5118, 0xBEA8,
+	0x511A, 0xE8F7, 0x511C, 0xE8F4, 0x511F, 0xC076, 0x5120, 0xECBD,
+	0x5121, 0xC077, 0x5122, 0xECBB, 0x5124, 0xECBC, 0x5125, 0xECBA,
+	0x5126, 0xECB9, 0x5129, 0xECBE, 0x512A, 0xC075, 0x512D, 0xEFB8,
+	0x512E, 0xEFB9, 0x5130, 0xE4E8, 0x5131, 0xEFB7, 0x5132, 0xC078,
+	0x5133, 0xC35F, 0x5134, 0xF1EB, 0x5135, 0xF1EC, 0x5137, 0xC4D7,
+	0x5138, 0xC4D8, 0x5139, 0xF5C1, 0x513A, 0xF5C0, 0x513B, 0xC56C,
+	0x513C, 0xC56B, 0x513D, 0xF7D0, 0x513F, 0xA449, 0x5140, 0xA461,
+	0x5141, 0xA4B9, 0x5143, 0xA4B8, 0x5144, 0xA553, 0x5145, 0xA552,
+	0x5146, 0xA5FC, 0x5147, 0xA5FB, 0x5148, 0xA5FD, 0x5149, 0xA5FA,
+	0x514B, 0xA74A, 0x514C, 0xA749, 0x514D, 0xA74B, 0x5152, 0xA8E0,
+	0x5154, 0xA8DF, 0x5155, 0xA8E1, 0x5157, 0xAB5E, 0x5159, 0xA259,
+	0x515A, 0xD0DE, 0x515B, 0xA25A, 0x515C, 0xB0C2, 0x515D, 0xA25C,
+	0x515E, 0xA25B, 0x515F, 0xD860, 0x5161, 0xA25D, 0x5162, 0xB9B8,
+	0x5163, 0xA25E, 0x5165, 0xA44A, 0x5167, 0xA4BA, 0x5168, 0xA5FE,
+	0x5169, 0xA8E2, 0x516B, 0xA44B, 0x516C, 0xA4BD, 0x516D, 0xA4BB,
+	0x516E, 0xA4BC, 0x5171, 0xA640, 0x5175, 0xA74C, 0x5176, 0xA8E4,
+	0x5177, 0xA8E3, 0x5178, 0xA8E5, 0x517C, 0xADDD, 0x5180, 0xBEAC,
+	0x5187, 0xC94E, 0x5189, 0xA554, 0x518A, 0xA555, 0x518D, 0xA641,
+	0x518F, 0xCA6A, 0x5191, 0xAB60, 0x5192, 0xAB5F, 0x5193, 0xD0E0,
+	0x5194, 0xD0DF, 0x5195, 0xB0C3, 0x5197, 0xA4BE, 0x5198, 0xC955,
+	0x519E, 0xCBCD, 0x51A0, 0xAB61, 0x51A2, 0xADE0, 0x51A4, 0xADDE,
+	0x51A5, 0xADDF, 0x51AA, 0xBEAD, 0x51AC, 0xA556, 0x51B0, 0xA642,
+	0x51B1, 0xC9BC, 0x51B6, 0xA74D, 0x51B7, 0xA74E, 0x51B9, 0xCA6B,
+	0x51BC, 0xCBCE, 0x51BD, 0xA8E6, 0x51BE, 0xCBCF, 0x51C4, 0xD0E2,
+	0x51C5, 0xD0E3, 0x51C6, 0xADE3, 0x51C8, 0xD0E4, 0x51CA, 0xD0E1,
+	0x51CB, 0xADE4, 0x51CC, 0xADE2, 0x51CD, 0xADE1, 0x51CE, 0xD0E5,
+	0x51D0, 0xD468, 0x51D4, 0xD861, 0x51D7, 0xDCC5, 0x51D8, 0xE140,
+	0x51DC, 0xBBFE, 0x51DD, 0xBEAE, 0x51DE, 0xE8F9, 0x51E0, 0xA44C,
+	0x51E1, 0xA45A, 0x51F0, 0xB0C4, 0x51F1, 0xB3CD, 0x51F3, 0xB9B9,
+	0x51F5, 0xC942, 0x51F6, 0xA4BF, 0x51F8, 0xA559, 0x51F9, 0xA557,
+	0x51FA, 0xA558, 0x51FD, 0xA8E7, 0x5200, 0xA44D, 0x5201, 0xA44E,
+	0x5203, 0xA462, 0x5206, 0xA4C0, 0x5207, 0xA4C1, 0x5208, 0xA4C2,
+	0x5209, 0xC9BE, 0x520A, 0xA55A, 0x520C, 0xC96B, 0x520E, 0xA646,
+	0x5210, 0xC9BF, 0x5211, 0xA644, 0x5212, 0xA645, 0x5213, 0xC9BD,
+	0x5216, 0xA647, 0x5217, 0xA643, 0x521C, 0xCA6C, 0x521D, 0xAAEC,
+	0x521E, 0xCA6D, 0x5221, 0xCA6E, 0x5224, 0xA750, 0x5225, 0xA74F,
+	0x5228, 0xA753, 0x5229, 0xA751, 0x522A, 0xA752, 0x522E, 0xA8ED,
+	0x5230, 0xA8EC, 0x5231, 0xCBD4, 0x5232, 0xCBD1, 0x5233, 0xCBD2,
+	0x5235, 0xCBD0, 0x5236, 0xA8EE, 0x5237, 0xA8EA, 0x5238, 0xA8E9,
+	0x523A, 0xA8EB, 0x523B, 0xA8E8, 0x5241, 0xA8EF, 0x5243, 0xAB63,
+	0x5244, 0xCDF0, 0x5246, 0xCBD3, 0x5247, 0xAB68, 0x5249, 0xCDF1,
+	0x524A, 0xAB64, 0x524B, 0xAB67, 0x524C, 0xAB66, 0x524D, 0xAB65,
+	0x524E, 0xAB62, 0x5252, 0xD0E8, 0x5254, 0xADE7, 0x5255, 0xD0EB,
+	0x5256, 0xADE5, 0x525A, 0xD0E7, 0x525B, 0xADE8, 0x525C, 0xADE6,
+	0x525D, 0xADE9, 0x525E, 0xD0E9, 0x525F, 0xD0EA, 0x5261, 0xD0E6,
+	0x5262, 0xD0EC, 0x5269, 0xB3D1, 0x526A, 0xB0C5, 0x526B, 0xD469,
+	0x526C, 0xD46B, 0x526D, 0xD46A, 0x526E, 0xD46C, 0x526F, 0xB0C6,
+	0x5272, 0xB3CE, 0x5274, 0xB3CF, 0x5275, 0xB3D0, 0x5277, 0xB6D0,
+	0x5278, 0xDCC7, 0x527A, 0xDCC6, 0x527B, 0xDCC8, 0x527C, 0xDCC9,
+	0x527D, 0xB6D1, 0x527F, 0xB6CF, 0x5280, 0xE141, 0x5281, 0xE142,
+	0x5282, 0xB9BB, 0x5283, 0xB9BA, 0x5284, 0xE35A, 0x5287, 0xBC40,
+	0x5288, 0xBC41, 0x5289, 0xBC42, 0x528A, 0xBC44, 0x528B, 0xE4F2,
+	0x528C, 0xE4F3, 0x528D, 0xBC43, 0x5291, 0xBEAF, 0x5293, 0xBEB0,
+	0x5296, 0xF1ED, 0x5297, 0xF5C3, 0x5298, 0xF5C2, 0x5299, 0xF7D1,
+	0x529B, 0xA44F, 0x529F, 0xA55C, 0x52A0, 0xA55B, 0x52A3, 0xA648,
+	0x52A6, 0xC9C0, 0x52A9, 0xA755, 0x52AA, 0xA756, 0x52AB, 0xA754,
+	0x52AC, 0xA757, 0x52AD, 0xCA6F, 0x52AE, 0xCA70, 0x52BB, 0xA8F1,
+	0x52BC, 0xCBD5, 0x52BE, 0xA8F0, 0x52C0, 0xCDF2, 0x52C1, 0xAB6C,
+	0x52C2, 0xCDF3, 0x52C3, 0xAB6B, 0x52C7, 0xAB69, 0x52C9, 0xAB6A,
+	0x52CD, 0xD0ED, 0x52D2, 0xB0C7, 0x52D3, 0xD46E, 0x52D5, 0xB0CA,
+	0x52D6, 0xD46D, 0x52D7, 0xB1E5, 0x52D8, 0xB0C9, 0x52D9, 0xB0C8,
+	0x52DB, 0xB3D4, 0x52DD, 0xB3D3, 0x52DE, 0xB3D2, 0x52DF, 0xB6D2,
+	0x52E2, 0xB6D5, 0x52E3, 0xB6D6, 0x52E4, 0xB6D4, 0x52E6, 0xB6D3,
+	0x52E9, 0xE143, 0x52EB, 0xE144, 0x52EF, 0xE4F5, 0x52F0, 0xBC45,
+	0x52F1, 0xE4F4, 0x52F3, 0xBEB1, 0x52F4, 0xECBF, 0x52F5, 0xC079,
+	0x52F7, 0xF1EE, 0x52F8, 0xC455, 0x52FA, 0xA463, 0x52FB, 0xA4C3,
+	0x52FC, 0xC956, 0x52FE, 0xA4C4, 0x52FF, 0xA4C5, 0x5305, 0xA55D,
+	0x5306, 0xA55E, 0x5308, 0xA649, 0x5309, 0xCA71, 0x530A, 0xCBD6,
+	0x530B, 0xCBD7, 0x530D, 0xAB6D, 0x530E, 0xD0EE, 0x530F, 0xB0CC,
+	0x5310, 0xB0CB, 0x5311, 0xD863, 0x5312, 0xD862, 0x5315, 0xA450,
+	0x5316, 0xA4C6, 0x5317, 0xA55F, 0x5319, 0xB0CD, 0x531A, 0xC943,
+	0x531C, 0xC96C, 0x531D, 0xA560, 0x531F, 0xC9C2, 0x5320, 0xA64B,
+	0x5321, 0xA64A, 0x5322, 0xC9C1, 0x5323, 0xA758, 0x532A, 0xADEA,
+	0x532D, 0xD46F, 0x532F, 0xB6D7, 0x5330, 0xE145, 0x5331, 0xB9BC,
+	0x5334, 0xE8FA, 0x5337, 0xF3FD, 0x5339, 0xA4C7, 0x533C, 0xCBD8,
+	0x533D, 0xCDF4, 0x533E, 0xB0D0, 0x533F, 0xB0CE, 0x5340, 0xB0CF,
+	0x5341, 0xA2CC, 0x5341, 0xA451, 0x5343, 0xA464, 0x5344, 0xA2CD,
+	0x5345, 0xA2CE, 0x5345, 0xA4CA, 0x5347, 0xA4C9, 0x5348, 0xA4C8,
+	0x5349, 0xA563, 0x534A, 0xA562, 0x534C, 0xC96D, 0x534D, 0xC9C3,
+	0x5351, 0xA8F5, 0x5352, 0xA8F2, 0x5353, 0xA8F4, 0x5354, 0xA8F3,
+	0x5357, 0xAB6E, 0x535A, 0xB3D5, 0x535C, 0xA452, 0x535E, 0xA4CB,
+	0x5360, 0xA565, 0x5361, 0xA564, 0x5363, 0xCA72, 0x5366, 0xA8F6,
+	0x536C, 0xC957, 0x536E, 0xA567, 0x536F, 0xA566, 0x5370, 0xA64C,
+	0x5371, 0xA64D, 0x5372, 0xCA73, 0x5373, 0xA759, 0x5375, 0xA75A,
+	0x5377, 0xA8F7, 0x5378, 0xA8F8, 0x5379, 0xA8F9, 0x537B, 0xAB6F,
+	0x537C, 0xCDF5, 0x537F, 0xADEB, 0x5382, 0xC944, 0x5384, 0xA4CC,
+	0x538A, 0xC9C4, 0x538E, 0xCA74, 0x538F, 0xCA75, 0x5392, 0xCBD9,
+	0x5394, 0xCBDA, 0x5396, 0xCDF7, 0x5397, 0xCDF6, 0x5398, 0xCDF9,
+	0x5399, 0xCDF8, 0x539A, 0xAB70, 0x539C, 0xD470, 0x539D, 0xADED,
+	0x539E, 0xD0EF, 0x539F, 0xADEC, 0x53A4, 0xD864, 0x53A5, 0xB3D6,
+	0x53A7, 0xD865, 0x53AC, 0xE146, 0x53AD, 0xB9BD, 0x53B2, 0xBC46,
+	0x53B4, 0xF1EF, 0x53B9, 0xC958, 0x53BB, 0xA568, 0x53C3, 0xB0D1,
+	0x53C8, 0xA453, 0x53C9, 0xA465, 0x53CA, 0xA4CE, 0x53CB, 0xA4CD,
+	0x53CD, 0xA4CF, 0x53D4, 0xA8FB, 0x53D6, 0xA8FA, 0x53D7, 0xA8FC,
+	0x53DB, 0xAB71, 0x53DF, 0xADEE, 0x53E1, 0xE8FB, 0x53E2, 0xC24F,
+	0x53E3, 0xA466, 0x53E4, 0xA56A, 0x53E5, 0xA579, 0x53E6, 0xA574,
+	0x53E8, 0xA56F, 0x53E9, 0xA56E, 0x53EA, 0xA575, 0x53EB, 0xA573,
+	0x53EC, 0xA56C, 0x53ED, 0xA57A, 0x53EE, 0xA56D, 0x53EF, 0xA569,
+	0x53F0, 0xA578, 0x53F1, 0xA577, 0x53F2, 0xA576, 0x53F3, 0xA56B,
+	0x53F5, 0xA572, 0x53F8, 0xA571, 0x53FB, 0xA57B, 0x53FC, 0xA570,
+	0x5401, 0xA653, 0x5403, 0xA659, 0x5404, 0xA655, 0x5406, 0xA65B,
+	0x5407, 0xC9C5, 0x5408, 0xA658, 0x5409, 0xA64E, 0x540A, 0xA651,
+	0x540B, 0xA654, 0x540C, 0xA650, 0x540D, 0xA657, 0x540E, 0xA65A,
+	0x540F, 0xA64F, 0x5410, 0xA652, 0x5411, 0xA656, 0x5412, 0xA65C,
+	0x5418, 0xCA7E, 0x5419, 0xCA7B, 0x541B, 0xA767, 0x541C, 0xCA7C,
+	0x541D, 0xA75B, 0x541E, 0xA75D, 0x541F, 0xA775, 0x5420, 0xA770,
+	0x5424, 0xCAA5, 0x5425, 0xCA7D, 0x5426, 0xA75F, 0x5427, 0xA761,
+	0x5428, 0xCAA4, 0x5429, 0xA768, 0x542A, 0xCA78, 0x542B, 0xA774,
+	0x542C, 0xA776, 0x542D, 0xA75C, 0x542E, 0xA76D, 0x5430, 0xCA76,
+	0x5431, 0xA773, 0x5433, 0xA764, 0x5435, 0xA76E, 0x5436, 0xA76F,
+	0x5437, 0xCA77, 0x5438, 0xA76C, 0x5439, 0xA76A, 0x543B, 0xA76B,
+	0x543C, 0xA771, 0x543D, 0xCAA1, 0x543E, 0xA75E, 0x5440, 0xA772,
+	0x5441, 0xCAA3, 0x5442, 0xA766, 0x5443, 0xA763, 0x5445, 0xCA7A,
+	0x5446, 0xA762, 0x5447, 0xCAA6, 0x5448, 0xA765, 0x544A, 0xA769,
+	0x544E, 0xA760, 0x544F, 0xCAA2, 0x5454, 0xCA79, 0x5460, 0xCBEB,
+	0x5461, 0xCBEA, 0x5462, 0xA94F, 0x5463, 0xCBED, 0x5464, 0xCBEF,
+	0x5465, 0xCBE4, 0x5466, 0xCBE7, 0x5467, 0xCBEE, 0x5468, 0xA950,
+	0x546B, 0xCBE1, 0x546C, 0xCBE5, 0x546F, 0xCBE9, 0x5470, 0xCE49,
+	0x5471, 0xA94B, 0x5472, 0xCE4D, 0x5473, 0xA8FD, 0x5474, 0xCBE6,
+	0x5475, 0xA8FE, 0x5476, 0xA94C, 0x5477, 0xA945, 0x5478, 0xA941,
+	0x547A, 0xCBE2, 0x547B, 0xA944, 0x547C, 0xA949, 0x547D, 0xA952,
+	0x547E, 0xCBE3, 0x547F, 0xCBDC, 0x5480, 0xA943, 0x5481, 0xCBDD,
+	0x5482, 0xCBDF, 0x5484, 0xA946, 0x5486, 0xA948, 0x5487, 0xCBDB,
+	0x5488, 0xCBE0, 0x548B, 0xA951, 0x548C, 0xA94D, 0x548D, 0xCBE8,
+	0x548E, 0xA953, 0x5490, 0xA94A, 0x5491, 0xCBDE, 0x5492, 0xA947,
+	0x5495, 0xA942, 0x5496, 0xA940, 0x5498, 0xCBEC, 0x549A, 0xA94E,
+	0x54A0, 0xCE48, 0x54A1, 0xCDFB, 0x54A2, 0xCE4B, 0x54A5, 0xCDFD,
+	0x54A6, 0xAB78, 0x54A7, 0xABA8, 0x54A8, 0xAB74, 0x54A9, 0xABA7,
+	0x54AA, 0xAB7D, 0x54AB, 0xABA4, 0x54AC, 0xAB72, 0x54AD, 0xCDFC,
+	0x54AE, 0xCE43, 0x54AF, 0xABA3, 0x54B0, 0xCE4F, 0x54B1, 0xABA5,
+	0x54B3, 0xAB79, 0x54B6, 0xCE45, 0x54B7, 0xCE42, 0x54B8, 0xAB77,
+	0x54BA, 0xCDFA, 0x54BB, 0xABA6, 0x54BC, 0xCE4A, 0x54BD, 0xAB7C,
+	0x54BE, 0xCE4C, 0x54BF, 0xABA9, 0x54C0, 0xAB73, 0x54C1, 0xAB7E,
+	0x54C2, 0xAB7B, 0x54C3, 0xCE40, 0x54C4, 0xABA1, 0x54C5, 0xCE46,
+	0x54C6, 0xCE47, 0x54C7, 0xAB7A, 0x54C8, 0xABA2, 0x54C9, 0xAB76,
+	0x54CE, 0xAB75, 0x54CF, 0xCDFE, 0x54D6, 0xCE44, 0x54DE, 0xCE4E,
+	0x54E0, 0xD144, 0x54E1, 0xADFB, 0x54E2, 0xD0F1, 0x54E4, 0xD0F6,
+	0x54E5, 0xADF4, 0x54E6, 0xAE40, 0x54E7, 0xD0F4, 0x54E8, 0xADEF,
+	0x54E9, 0xADF9, 0x54EA, 0xADFE, 0x54EB, 0xD0FB, 0x54ED, 0xADFA,
+	0x54EE, 0xADFD, 0x54F1, 0xD0FE, 0x54F2, 0xADF5, 0x54F3, 0xD0F5,
+	0x54F7, 0xD142, 0x54F8, 0xD143, 0x54FA, 0xADF7, 0x54FB, 0xD141,
+	0x54FC, 0xADF3, 0x54FD, 0xAE43, 0x54FF, 0xD0F8, 0x5501, 0xADF1,
+	0x5503, 0xD146, 0x5504, 0xD0F9, 0x5505, 0xD0FD, 0x5506, 0xADF6,
+	0x5507, 0xAE42, 0x5508, 0xD0FA, 0x5509, 0xADFC, 0x550A, 0xD140,
+	0x550B, 0xD147, 0x550C, 0xD4A1, 0x550E, 0xD145, 0x550F, 0xAE44,
+	0x5510, 0xADF0, 0x5511, 0xD0FC, 0x5512, 0xD0F3, 0x5514, 0xADF8,
+	0x5517, 0xD0F2, 0x551A, 0xD0F7, 0x5526, 0xD0F0, 0x5527, 0xAE41,
+	0x552A, 0xD477, 0x552C, 0xB0E4, 0x552D, 0xD4A7, 0x552E, 0xB0E2,
+	0x552F, 0xB0DF, 0x5530, 0xD47C, 0x5531, 0xB0DB, 0x5532, 0xD4A2,
+	0x5533, 0xB0E6, 0x5534, 0xD476, 0x5535, 0xD47B, 0x5536, 0xD47A,
+	0x5537, 0xADF2, 0x5538, 0xB0E1, 0x5539, 0xD4A5, 0x553B, 0xD4A8,
+	0x553C, 0xD473, 0x553E, 0xB3E8, 0x5540, 0xD4A9, 0x5541, 0xB0E7,
+	0x5543, 0xB0D9, 0x5544, 0xB0D6, 0x5545, 0xD47E, 0x5546, 0xB0D3,
+	0x5548, 0xD4A6, 0x554A, 0xB0DA, 0x554B, 0xD4AA, 0x554D, 0xD474,
+	0x554E, 0xD4A4, 0x554F, 0xB0DD, 0x5550, 0xD475, 0x5551, 0xD478,
+	0x5552, 0xD47D, 0x5555, 0xB0DE, 0x5556, 0xB0DC, 0x5557, 0xB0E8,
+	0x555C, 0xB0E3, 0x555E, 0xB0D7, 0x555F, 0xB1D2, 0x5561, 0xB0D8,
+	0x5562, 0xD479, 0x5563, 0xB0E5, 0x5564, 0xB0E0, 0x5565, 0xD4A3,
+	0x5566, 0xB0D5, 0x556A, 0xB0D4, 0x5575, 0xD471, 0x5576, 0xD472,
+	0x5577, 0xD86A, 0x557B, 0xB3D7, 0x557C, 0xB3DA, 0x557D, 0xD875,
+	0x557E, 0xB3EE, 0x557F, 0xD878, 0x5580, 0xB3D8, 0x5581, 0xD871,
+	0x5582, 0xB3DE, 0x5583, 0xB3E4, 0x5584, 0xB5BD, 0x5587, 0xB3E2,
+	0x5588, 0xD86E, 0x5589, 0xB3EF, 0x558A, 0xB3DB, 0x558B, 0xB3E3,
+	0x558C, 0xD876, 0x558D, 0xDCD7, 0x558E, 0xD87B, 0x558F, 0xD86F,
+	0x5591, 0xD866, 0x5592, 0xD873, 0x5593, 0xD86D, 0x5594, 0xB3E1,
+	0x5595, 0xD879, 0x5598, 0xB3DD, 0x5599, 0xB3F1, 0x559A, 0xB3EA,
+	0x559C, 0xB3DF, 0x559D, 0xB3DC, 0x559F, 0xB3E7, 0x55A1, 0xD87A,
+	0x55A2, 0xD86C, 0x55A3, 0xD872, 0x55A4, 0xD874, 0x55A5, 0xD868,
+	0x55A6, 0xD877, 0x55A7, 0xB3D9, 0x55A8, 0xD867, 0x55AA, 0xB3E0,
+	0x55AB, 0xB3F0, 0x55AC, 0xB3EC, 0x55AD, 0xD869, 0x55AE, 0xB3E6,
+	0x55B1, 0xB3ED, 0x55B2, 0xB3E9, 0x55B3, 0xB3E5, 0x55B5, 0xD870,
+	0x55BB, 0xB3EB, 0x55BF, 0xDCD5, 0x55C0, 0xDCD1, 0x55C2, 0xDCE0,
+	0x55C3, 0xDCCA, 0x55C4, 0xDCD3, 0x55C5, 0xB6E5, 0x55C6, 0xB6E6,
+	0x55C7, 0xB6DE, 0x55C8, 0xDCDC, 0x55C9, 0xB6E8, 0x55CA, 0xDCCF,
+	0x55CB, 0xDCCE, 0x55CC, 0xDCCC, 0x55CD, 0xDCDE, 0x55CE, 0xB6DC,
+	0x55CF, 0xDCD8, 0x55D0, 0xDCCD, 0x55D1, 0xB6DF, 0x55D2, 0xDCD6,
+	0x55D3, 0xB6DA, 0x55D4, 0xDCD2, 0x55D5, 0xDCD9, 0x55D6, 0xDCDB,
+	0x55D9, 0xDCDF, 0x55DA, 0xB6E3, 0x55DB, 0xDCCB, 0x55DC, 0xB6DD,
+	0x55DD, 0xDCD0, 0x55DF, 0xB6D8, 0x55E1, 0xB6E4, 0x55E2, 0xDCDA,
+	0x55E3, 0xB6E0, 0x55E4, 0xB6E1, 0x55E5, 0xB6E7, 0x55E6, 0xB6DB,
+	0x55E7, 0xA25F, 0x55E8, 0xB6D9, 0x55E9, 0xDCD4, 0x55EF, 0xB6E2,
+	0x55F2, 0xDCDD, 0x55F6, 0xB9CD, 0x55F7, 0xB9C8, 0x55F9, 0xE155,
+	0x55FA, 0xE151, 0x55FC, 0xE14B, 0x55FD, 0xB9C2, 0x55FE, 0xB9BE,
+	0x55FF, 0xE154, 0x5600, 0xB9BF, 0x5601, 0xE14E, 0x5602, 0xE150,
+	0x5604, 0xE153, 0x5606, 0xB9C4, 0x5608, 0xB9CB, 0x5609, 0xB9C5,
+	0x560C, 0xE149, 0x560D, 0xB9C6, 0x560E, 0xB9C7, 0x560F, 0xE14C,
+	0x5610, 0xB9CC, 0x5612, 0xE14A, 0x5613, 0xE14F, 0x5614, 0xB9C3,
+	0x5615, 0xE148, 0x5616, 0xB9C9, 0x5617, 0xB9C1, 0x561B, 0xB9C0,
+	0x561C, 0xE14D, 0x561D, 0xE152, 0x561F, 0xB9CA, 0x5627, 0xE147,
+	0x5629, 0xBC4D, 0x562A, 0xE547, 0x562C, 0xE544, 0x562E, 0xBC47,
+	0x562F, 0xBC53, 0x5630, 0xBC54, 0x5632, 0xBC4A, 0x5633, 0xE542,
+	0x5634, 0xBC4C, 0x5635, 0xE4F9, 0x5636, 0xBC52, 0x5638, 0xE546,
+	0x5639, 0xBC49, 0x563A, 0xE548, 0x563B, 0xBC48, 0x563D, 0xE543,
+	0x563E, 0xE545, 0x563F, 0xBC4B, 0x5640, 0xE541, 0x5641, 0xE4FA,
+	0x5642, 0xE4F7, 0x5645, 0xD86B, 0x5646, 0xE4FD, 0x5648, 0xE4F6,
+	0x5649, 0xE4FC, 0x564A, 0xE4FB, 0x564C, 0xE4F8, 0x564E, 0xBC4F,
+	0x5653, 0xBC4E, 0x5657, 0xBC50, 0x5658, 0xE4FE, 0x5659, 0xBEB2,
+	0x565A, 0xE540, 0x565E, 0xE945, 0x5660, 0xE8FD, 0x5662, 0xBEBE,
+	0x5663, 0xE942, 0x5664, 0xBEB6, 0x5665, 0xBEBA, 0x5666, 0xE941,
+	0x5668, 0xBEB9, 0x5669, 0xBEB5, 0x566A, 0xBEB8, 0x566B, 0xBEB3,
+	0x566C, 0xBEBD, 0x566D, 0xE943, 0x566E, 0xE8FE, 0x566F, 0xBEBC,
+	0x5670, 0xE8FC, 0x5671, 0xBEBB, 0x5672, 0xE944, 0x5673, 0xE940,
+	0x5674, 0xBC51, 0x5676, 0xBEBF, 0x5677, 0xE946, 0x5678, 0xBEB7,
+	0x5679, 0xBEB4, 0x567E, 0xECC6, 0x567F, 0xECC8, 0x5680, 0xC07B,
+	0x5681, 0xECC9, 0x5682, 0xECC7, 0x5683, 0xECC5, 0x5684, 0xECC4,
+	0x5685, 0xC07D, 0x5686, 0xECC3, 0x5687, 0xC07E, 0x568C, 0xECC1,
+	0x568D, 0xECC2, 0x568E, 0xC07A, 0x568F, 0xC0A1, 0x5690, 0xC07C,
+	0x5693, 0xECC0, 0x5695, 0xC250, 0x5697, 0xEFBC, 0x5698, 0xEFBA,
+	0x5699, 0xEFBF, 0x569A, 0xEFBD, 0x569C, 0xEFBB, 0x569D, 0xEFBE,
+	0x56A5, 0xC360, 0x56A6, 0xF1F2, 0x56A7, 0xF1F3, 0x56A8, 0xC456,
+	0x56AA, 0xF1F4, 0x56AB, 0xF1F0, 0x56AC, 0xF1F5, 0x56AD, 0xF1F1,
+	0x56AE, 0xC251, 0x56B2, 0xF3FE, 0x56B3, 0xF441, 0x56B4, 0xC459,
+	0x56B5, 0xF440, 0x56B6, 0xC458, 0x56B7, 0xC457, 0x56BC, 0xC45A,
+	0x56BD, 0xF5C5, 0x56BE, 0xF5C6, 0x56C0, 0xC4DA, 0x56C1, 0xC4D9,
+	0x56C2, 0xC4DB, 0x56C3, 0xF5C4, 0x56C5, 0xF6D8, 0x56C6, 0xF6D7,
+	0x56C8, 0xC56D, 0x56C9, 0xC56F, 0x56CA, 0xC56E, 0x56CB, 0xF6D9,
+	0x56CC, 0xC5C8, 0x56CD, 0xF8A6, 0x56D1, 0xC5F1, 0x56D3, 0xF8A5,
+	0x56D4, 0xF8EE, 0x56D7, 0xC949, 0x56DA, 0xA57D, 0x56DB, 0xA57C,
+	0x56DD, 0xA65F, 0x56DE, 0xA65E, 0x56DF, 0xC9C7, 0x56E0, 0xA65D,
+	0x56E1, 0xC9C6, 0x56E4, 0xA779, 0x56E5, 0xCAA9, 0x56E7, 0xCAA8,
+	0x56EA, 0xA777, 0x56EB, 0xA77A, 0x56EE, 0xCAA7, 0x56F0, 0xA778,
+	0x56F7, 0xCBF0, 0x56F9, 0xCBF1, 0x56FA, 0xA954, 0x56FF, 0xABAA,
+	0x5701, 0xD148, 0x5702, 0xD149, 0x5703, 0xAE45, 0x5704, 0xAE46,
+	0x5707, 0xD4AC, 0x5708, 0xB0E9, 0x5709, 0xB0EB, 0x570A, 0xD4AB,
+	0x570B, 0xB0EA, 0x570C, 0xD87C, 0x570D, 0xB3F2, 0x5712, 0xB6E9,
+	0x5713, 0xB6EA, 0x5714, 0xDCE1, 0x5716, 0xB9CF, 0x5718, 0xB9CE,
+	0x571A, 0xE549, 0x571B, 0xE948, 0x571C, 0xE947, 0x571E, 0xF96B,
+	0x571F, 0xA467, 0x5720, 0xC959, 0x5722, 0xC96E, 0x5723, 0xC96F,
+	0x5728, 0xA662, 0x5729, 0xA666, 0x572A, 0xC9C9, 0x572C, 0xA664,
+	0x572D, 0xA663, 0x572E, 0xC9C8, 0x572F, 0xA665, 0x5730, 0xA661,
+	0x5733, 0xA660, 0x5734, 0xC9CA, 0x573B, 0xA7A6, 0x573E, 0xA7A3,
+	0x5740, 0xA77D, 0x5741, 0xCAAA, 0x5745, 0xCAAB, 0x5747, 0xA7A1,
+	0x5749, 0xCAAD, 0x574A, 0xA77B, 0x574B, 0xCAAE, 0x574C, 0xCAAC,
+	0x574D, 0xA77E, 0x574E, 0xA7A2, 0x574F, 0xA7A5, 0x5750, 0xA7A4,
+	0x5751, 0xA77C, 0x5752, 0xCAAF, 0x5761, 0xA959, 0x5762, 0xCBFE,
+	0x5764, 0xA95B, 0x5766, 0xA95A, 0x5768, 0xCC40, 0x5769, 0xA958,
+	0x576A, 0xA957, 0x576B, 0xCBF5, 0x576D, 0xCBF4, 0x576F, 0xCBF2,
+	0x5770, 0xCBF7, 0x5771, 0xCBF6, 0x5772, 0xCBF3, 0x5773, 0xCBFC,
+	0x5774, 0xCBFD, 0x5775, 0xCBFA, 0x5776, 0xCBF8, 0x5777, 0xA956,
+	0x577B, 0xCBFB, 0x577C, 0xA95C, 0x577D, 0xCC41, 0x5780, 0xCBF9,
+	0x5782, 0xABAB, 0x5783, 0xA955, 0x578B, 0xABAC, 0x578C, 0xCE54,
+	0x578F, 0xCE5A, 0x5793, 0xABB2, 0x5794, 0xCE58, 0x5795, 0xCE5E,
+	0x5797, 0xCE55, 0x5798, 0xCE59, 0x5799, 0xCE5B, 0x579A, 0xCE5D,
+	0x579B, 0xCE57, 0x579D, 0xCE56, 0x579E, 0xCE51, 0x579F, 0xCE52,
+	0x57A0, 0xABAD, 0x57A2, 0xABAF, 0x57A3, 0xABAE, 0x57A4, 0xCE53,
+	0x57A5, 0xCE5C, 0x57AE, 0xABB1, 0x57B5, 0xCE50, 0x57B6, 0xD153,
+	0x57B8, 0xD152, 0x57B9, 0xD157, 0x57BA, 0xD14E, 0x57BC, 0xD151,
+	0x57BD, 0xD150, 0x57BF, 0xD154, 0x57C1, 0xD158, 0x57C2, 0xAE47,
+	0x57C3, 0xAE4A, 0x57C6, 0xD14F, 0x57C7, 0xD155, 0x57CB, 0xAE49,
+	0x57CC, 0xD14A, 0x57CE, 0xABB0, 0x57CF, 0xD4BA, 0x57D0, 0xD156,
+	0x57D2, 0xD14D, 0x57D4, 0xAE48, 0x57D5, 0xD14C, 0x57DC, 0xD4B1,
+	0x57DF, 0xB0EC, 0x57E0, 0xB0F0, 0x57E1, 0xD4C1, 0x57E2, 0xD4AF,
+	0x57E3, 0xD4BD, 0x57E4, 0xB0F1, 0x57E5, 0xD4BF, 0x57E7, 0xD4C5,
+	0x57E9, 0xD4C9, 0x57EC, 0xD4C0, 0x57ED, 0xD4B4, 0x57EE, 0xD4BC,
+	0x57F0, 0xD4CA, 0x57F1, 0xD4C8, 0x57F2, 0xD4BE, 0x57F3, 0xD4B9,
+	0x57F4, 0xD4B2, 0x57F5, 0xD8A6, 0x57F6, 0xD4B0, 0x57F7, 0xB0F5,
+	0x57F8, 0xD4B7, 0x57F9, 0xB0F6, 0x57FA, 0xB0F2, 0x57FB, 0xD4AD,
+	0x57FC, 0xD4C3, 0x57FD, 0xD4B5, 0x5800, 0xD4B3, 0x5801, 0xD4C6,
+	0x5802, 0xB0F3, 0x5804, 0xD4CC, 0x5805, 0xB0ED, 0x5806, 0xB0EF,
+	0x5807, 0xD4BB, 0x5808, 0xD4B6, 0x5809, 0xAE4B, 0x580A, 0xB0EE,
+	0x580B, 0xD4B8, 0x580C, 0xD4C7, 0x580D, 0xD4CB, 0x580E, 0xD4C2,
+	0x5810, 0xD4C4, 0x5814, 0xD4AE, 0x5819, 0xD8A1, 0x581B, 0xD8AA,
+	0x581C, 0xD8A9, 0x581D, 0xB3FA, 0x581E, 0xD8A2, 0x5820, 0xB3FB,
+	0x5821, 0xB3F9, 0x5823, 0xD8A4, 0x5824, 0xB3F6, 0x5825, 0xD8A8,
+	0x5827, 0xD8A3, 0x5828, 0xD8A5, 0x5829, 0xD87D, 0x582A, 0xB3F4,
+	0x582C, 0xD8B2, 0x582D, 0xD8B1, 0x582E, 0xD8AE, 0x582F, 0xB3F3,
+	0x5830, 0xB3F7, 0x5831, 0xB3F8, 0x5832, 0xD14B, 0x5833, 0xD8AB,
+	0x5834, 0xB3F5, 0x5835, 0xB0F4, 0x5836, 0xD8AD, 0x5837, 0xD87E,
+	0x5838, 0xD8B0, 0x5839, 0xD8AF, 0x583B, 0xD8B3, 0x583D, 0xDCEF,
+	0x583F, 0xD8AC, 0x5848, 0xD8A7, 0x5849, 0xDCE7, 0x584A, 0xB6F4,
+	0x584B, 0xB6F7, 0x584C, 0xB6F2, 0x584D, 0xDCE6, 0x584E, 0xDCEA,
+	0x584F, 0xDCE5, 0x5851, 0xB6EC, 0x5852, 0xB6F6, 0x5853, 0xDCE2,
+	0x5854, 0xB6F0, 0x5855, 0xDCE9, 0x5857, 0xB6EE, 0x5858, 0xB6ED,
+	0x5859, 0xDCEC, 0x585A, 0xB6EF, 0x585B, 0xDCEE, 0x585D, 0xDCEB,
+	0x585E, 0xB6EB, 0x5862, 0xB6F5, 0x5863, 0xDCF0, 0x5864, 0xDCE4,
+	0x5865, 0xDCED, 0x5868, 0xDCE3, 0x586B, 0xB6F1, 0x586D, 0xB6F3,
+	0x586F, 0xDCE8, 0x5871, 0xDCF1, 0x5874, 0xE15D, 0x5875, 0xB9D0,
+	0x5876, 0xE163, 0x5879, 0xB9D5, 0x587A, 0xE15F, 0x587B, 0xE166,
+	0x587C, 0xE157, 0x587D, 0xB9D7, 0x587E, 0xB9D1, 0x587F, 0xE15C,
+	0x5880, 0xBC55, 0x5881, 0xE15B, 0x5882, 0xE164, 0x5883, 0xB9D2,
+	0x5885, 0xB9D6, 0x5886, 0xE15A, 0x5887, 0xE160, 0x5888, 0xE165,
+	0x5889, 0xE156, 0x588A, 0xB9D4, 0x588B, 0xE15E, 0x588E, 0xE162,
+	0x588F, 0xE168, 0x5890, 0xE158, 0x5891, 0xE161, 0x5893, 0xB9D3,
+	0x5894, 0xE167, 0x5898, 0xE159, 0x589C, 0xBC59, 0x589D, 0xE54B,
+	0x589E, 0xBC57, 0x589F, 0xBC56, 0x58A0, 0xE54D, 0x58A1, 0xE552,
+	0x58A3, 0xE54E, 0x58A5, 0xE551, 0x58A6, 0xBC5C, 0x58A8, 0xBEA5,
+	0x58A9, 0xBC5B, 0x58AB, 0xE54A, 0x58AC, 0xE550, 0x58AE, 0xBC5A,
+	0x58AF, 0xE54F, 0x58B1, 0xE54C, 0x58B3, 0xBC58, 0x58BA, 0xE94D,
+	0x58BB, 0xF9D9, 0x58BC, 0xE94F, 0x58BD, 0xE94A, 0x58BE, 0xBEC1,
+	0x58BF, 0xE94C, 0x58C1, 0xBEC0, 0x58C2, 0xE94E, 0x58C5, 0xBEC3,
+	0x58C6, 0xE950, 0x58C7, 0xBEC2, 0x58C8, 0xE949, 0x58C9, 0xE94B,
+	0x58CE, 0xC0A5, 0x58CF, 0xECCC, 0x58D1, 0xC0A4, 0x58D2, 0xECCD,
+	0x58D3, 0xC0A3, 0x58D4, 0xECCB, 0x58D5, 0xC0A2, 0x58D6, 0xECCA,
+	0x58D8, 0xC253, 0x58D9, 0xC252, 0x58DA, 0xF1F6, 0x58DB, 0xF1F8,
+	0x58DD, 0xF1F7, 0x58DE, 0xC361, 0x58DF, 0xC362, 0x58E2, 0xC363,
+	0x58E3, 0xF442, 0x58E4, 0xC45B, 0x58E7, 0xF7D3, 0x58E8, 0xF7D2,
+	0x58E9, 0xC5F2, 0x58EB, 0xA468, 0x58EC, 0xA4D0, 0x58EF, 0xA7A7,
+	0x58F4, 0xCE5F, 0x58F9, 0xB3FC, 0x58FA, 0xB3FD, 0x58FC, 0xDCF2,
+	0x58FD, 0xB9D8, 0x58FE, 0xE169, 0x58FF, 0xE553, 0x5903, 0xC95A,
+	0x5906, 0xCAB0, 0x590C, 0xCC42, 0x590D, 0xCE60, 0x590E, 0xD159,
+	0x590F, 0xAE4C, 0x5912, 0xF1F9, 0x5914, 0xC4DC, 0x5915, 0xA469,
+	0x5916, 0xA57E, 0x5917, 0xC970, 0x5919, 0xA667, 0x591A, 0xA668,
+	0x591C, 0xA95D, 0x5920, 0xB0F7, 0x5922, 0xB9DA, 0x5924, 0xB9DB,
+	0x5925, 0xB9D9, 0x5927, 0xA46A, 0x5929, 0xA4D1, 0x592A, 0xA4D3,
+	0x592B, 0xA4D2, 0x592C, 0xC95B, 0x592D, 0xA4D4, 0x592E, 0xA5A1,
+	0x592F, 0xC971, 0x5931, 0xA5A2, 0x5937, 0xA669, 0x5938, 0xA66A,
+	0x593C, 0xC9CB, 0x593E, 0xA7A8, 0x5940, 0xCAB1, 0x5944, 0xA961,
+	0x5945, 0xCC43, 0x5947, 0xA95F, 0x5948, 0xA960, 0x5949, 0xA95E,
+	0x594A, 0xD15A, 0x594E, 0xABB6, 0x594F, 0xABB5, 0x5950, 0xABB7,
+	0x5951, 0xABB4, 0x5953, 0xCE61, 0x5954, 0xA962, 0x5955, 0xABB3,
+	0x5957, 0xAE4D, 0x5958, 0xAE4E, 0x595A, 0xAE4F, 0x595C, 0xD4CD,
+	0x5960, 0xB3FE, 0x5961, 0xD8B4, 0x5962, 0xB0F8, 0x5967, 0xB6F8,
+	0x5969, 0xB9DD, 0x596A, 0xB9DC, 0x596B, 0xE16A, 0x596D, 0xBC5D,
+	0x596E, 0xBEC4, 0x5970, 0xEFC0, 0x5971, 0xF6DA, 0x5972, 0xF7D4,
+	0x5973, 0xA46B, 0x5974, 0xA5A3, 0x5976, 0xA5A4, 0x5977, 0xC9D1,
+	0x5978, 0xA66C, 0x5979, 0xA66F, 0x597B, 0xC9CF, 0x597C, 0xC9CD,
+	0x597D, 0xA66E, 0x597E, 0xC9D0, 0x597F, 0xC9D2, 0x5980, 0xC9CC,
+	0x5981, 0xA671, 0x5982, 0xA670, 0x5983, 0xA66D, 0x5984, 0xA66B,
+	0x5985, 0xC9CE, 0x598A, 0xA7B3, 0x598D, 0xA7B0, 0x598E, 0xCAB6,
+	0x598F, 0xCAB9, 0x5990, 0xCAB8, 0x5992, 0xA7AA, 0x5993, 0xA7B2,
+	0x5996, 0xA7AF, 0x5997, 0xCAB5, 0x5998, 0xCAB3, 0x5999, 0xA7AE,
+	0x599D, 0xA7A9, 0x599E, 0xA7AC, 0x59A0, 0xCAB4, 0x59A1, 0xCABB,
+	0x59A2, 0xCAB7, 0x59A3, 0xA7AD, 0x59A4, 0xA7B1, 0x59A5, 0xA7B4,
+	0x59A6, 0xCAB2, 0x59A7, 0xCABA, 0x59A8, 0xA7AB, 0x59AE, 0xA967,
+	0x59AF, 0xA96F, 0x59B1, 0xCC4F, 0x59B2, 0xCC48, 0x59B3, 0xA970,
+	0x59B4, 0xCC53, 0x59B5, 0xCC44, 0x59B6, 0xCC4B, 0x59B9, 0xA966,
+	0x59BA, 0xCC45, 0x59BB, 0xA964, 0x59BC, 0xCC4C, 0x59BD, 0xCC50,
+	0x59BE, 0xA963, 0x59C0, 0xCC51, 0x59C1, 0xCC4A, 0x59C3, 0xCC4D,
+	0x59C5, 0xA972, 0x59C6, 0xA969, 0x59C7, 0xCC54, 0x59C8, 0xCC52,
+	0x59CA, 0xA96E, 0x59CB, 0xA96C, 0x59CC, 0xCC49, 0x59CD, 0xA96B,
+	0x59CE, 0xCC47, 0x59CF, 0xCC46, 0x59D0, 0xA96A, 0x59D1, 0xA968,
+	0x59D2, 0xA971, 0x59D3, 0xA96D, 0x59D4, 0xA965, 0x59D6, 0xCC4E,
+	0x59D8, 0xABB9, 0x59DA, 0xABC0, 0x59DB, 0xCE6F, 0x59DC, 0xABB8,
+	0x59DD, 0xCE67, 0x59DE, 0xCE63, 0x59E0, 0xCE73, 0x59E1, 0xCE62,
+	0x59E3, 0xABBB, 0x59E4, 0xCE6C, 0x59E5, 0xABBE, 0x59E6, 0xABC1,
+	0x59E8, 0xABBC, 0x59E9, 0xCE70, 0x59EA, 0xABBF, 0x59EC, 0xAE56,
+	0x59ED, 0xCE76, 0x59EE, 0xCE64, 0x59F1, 0xCE66, 0x59F2, 0xCE6D,
+	0x59F3, 0xCE71, 0x59F4, 0xCE75, 0x59F5, 0xCE72, 0x59F6, 0xCE6B,
+	0x59F7, 0xCE6E, 0x59FA, 0xCE68, 0x59FB, 0xABC3, 0x59FC, 0xCE6A,
+	0x59FD, 0xCE69, 0x59FE, 0xCE74, 0x59FF, 0xABBA, 0x5A00, 0xCE65,
+	0x5A01, 0xABC2, 0x5A03, 0xABBD, 0x5A09, 0xAE5C, 0x5A0A, 0xD162,
+	0x5A0C, 0xAE5B, 0x5A0F, 0xD160, 0x5A11, 0xAE50, 0x5A13, 0xAE55,
+	0x5A15, 0xD15F, 0x5A16, 0xD15C, 0x5A17, 0xD161, 0x5A18, 0xAE51,
+	0x5A19, 0xD15B, 0x5A1B, 0xAE54, 0x5A1C, 0xAE52, 0x5A1E, 0xD163,
+	0x5A1F, 0xAE53, 0x5A20, 0xAE57, 0x5A23, 0xAE58, 0x5A25, 0xAE5A,
+	0x5A29, 0xAE59, 0x5A2D, 0xD15D, 0x5A2E, 0xD15E, 0x5A33, 0xD164,
+	0x5A35, 0xD4D4, 0x5A36, 0xB0F9, 0x5A37, 0xD8C2, 0x5A38, 0xD4D3,
+	0x5A39, 0xD4E6, 0x5A3C, 0xB140, 0x5A3E, 0xD4E4, 0x5A40, 0xB0FE,
+	0x5A41, 0xB0FA, 0x5A42, 0xD4ED, 0x5A43, 0xD4DD, 0x5A44, 0xD4E0,
+	0x5A46, 0xB143, 0x5A47, 0xD4EA, 0x5A48, 0xD4E2, 0x5A49, 0xB0FB,
+	0x5A4A, 0xB144, 0x5A4C, 0xD4E7, 0x5A4D, 0xD4E5, 0x5A50, 0xD4D6,
+	0x5A51, 0xD4EB, 0x5A52, 0xD4DF, 0x5A53, 0xD4DA, 0x5A55, 0xD4D0,
+	0x5A56, 0xD4EC, 0x5A57, 0xD4DC, 0x5A58, 0xD4CF, 0x5A5A, 0xB142,
+	0x5A5B, 0xD4E1, 0x5A5C, 0xD4EE, 0x5A5D, 0xD4DE, 0x5A5E, 0xD4D2,
+	0x5A5F, 0xD4D7, 0x5A60, 0xD4CE, 0x5A62, 0xB141, 0x5A64, 0xD4DB,
+	0x5A65, 0xD4D8, 0x5A66, 0xB0FC, 0x5A67, 0xD4D1, 0x5A69, 0xD4E9,
+	0x5A6A, 0xB0FD, 0x5A6C, 0xD4D9, 0x5A6D, 0xD4D5, 0x5A70, 0xD4E8,
+	0x5A77, 0xB440, 0x5A78, 0xD8BB, 0x5A7A, 0xD8B8, 0x5A7B, 0xD8C9,
+	0x5A7C, 0xD8BD, 0x5A7D, 0xD8CA, 0x5A7F, 0xB442, 0x5A83, 0xD8C6,
+	0x5A84, 0xD8C3, 0x5A8A, 0xD8C4, 0x5A8B, 0xD8C7, 0x5A8C, 0xD8CB,
+	0x5A8E, 0xD4E3, 0x5A8F, 0xD8CD, 0x5A90, 0xDD47, 0x5A92, 0xB443,
+	0x5A93, 0xD8CE, 0x5A94, 0xD8B6, 0x5A95, 0xD8C0, 0x5A97, 0xD8C5,
+	0x5A9A, 0xB441, 0x5A9B, 0xB444, 0x5A9C, 0xD8CC, 0x5A9D, 0xD8CF,
+	0x5A9E, 0xD8BA, 0x5A9F, 0xD8B7, 0x5AA2, 0xD8B9, 0x5AA5, 0xD8BE,
+	0x5AA6, 0xD8BC, 0x5AA7, 0xB445, 0x5AA9, 0xD8C8, 0x5AAC, 0xD8BF,
+	0x5AAE, 0xD8C1, 0x5AAF, 0xD8B5, 0x5AB0, 0xDCFA, 0x5AB1, 0xDCF8,
+	0x5AB2, 0xB742, 0x5AB3, 0xB740, 0x5AB4, 0xDD43, 0x5AB5, 0xDCF9,
+	0x5AB6, 0xDD44, 0x5AB7, 0xDD40, 0x5AB8, 0xDCF7, 0x5AB9, 0xDD46,
+	0x5ABA, 0xDCF6, 0x5ABB, 0xDCFD, 0x5ABC, 0xB6FE, 0x5ABD, 0xB6FD,
+	0x5ABE, 0xB6FC, 0x5ABF, 0xDCFB, 0x5AC0, 0xDD41, 0x5AC1, 0xB6F9,
+	0x5AC2, 0xB741, 0x5AC4, 0xDCF4, 0x5AC6, 0xDCFE, 0x5AC7, 0xDCF3,
+	0x5AC8, 0xDCFC, 0x5AC9, 0xB6FA, 0x5ACA, 0xDD42, 0x5ACB, 0xDCF5,
+	0x5ACC, 0xB6FB, 0x5ACD, 0xDD45, 0x5AD5, 0xE16E, 0x5AD6, 0xB9E2,
+	0x5AD7, 0xB9E1, 0x5AD8, 0xB9E3, 0x5AD9, 0xE17A, 0x5ADA, 0xE170,
+	0x5ADB, 0xE176, 0x5ADC, 0xE16B, 0x5ADD, 0xE179, 0x5ADE, 0xE178,
+	0x5ADF, 0xE17C, 0x5AE0, 0xE175, 0x5AE1, 0xB9DE, 0x5AE2, 0xE174,
+	0x5AE3, 0xB9E4, 0x5AE5, 0xE16D, 0x5AE6, 0xB9DF, 0x5AE8, 0xE17B,
+	0x5AE9, 0xB9E0, 0x5AEA, 0xE16F, 0x5AEB, 0xE172, 0x5AEC, 0xE177,
+	0x5AED, 0xE171, 0x5AEE, 0xE16C, 0x5AF3, 0xE173, 0x5AF4, 0xE555,
+	0x5AF5, 0xBC61, 0x5AF6, 0xE558, 0x5AF7, 0xE557, 0x5AF8, 0xE55A,
+	0x5AF9, 0xE55C, 0x5AFA, 0xF9DC, 0x5AFB, 0xBC5F, 0x5AFD, 0xE556,
+	0x5AFF, 0xE554, 0x5B01, 0xE55D, 0x5B02, 0xE55B, 0x5B03, 0xE559,
+	0x5B05, 0xE55F, 0x5B07, 0xE55E, 0x5B08, 0xBC63, 0x5B09, 0xBC5E,
+	0x5B0B, 0xBC60, 0x5B0C, 0xBC62, 0x5B0F, 0xE560, 0x5B10, 0xE957,
+	0x5B13, 0xE956, 0x5B14, 0xE955, 0x5B16, 0xE958, 0x5B17, 0xE951,
+	0x5B19, 0xE952, 0x5B1A, 0xE95A, 0x5B1B, 0xE953, 0x5B1D, 0xBEC5,
+	0x5B1E, 0xE95C, 0x5B20, 0xE95B, 0x5B21, 0xE954, 0x5B23, 0xECD1,
+	0x5B24, 0xC0A8, 0x5B25, 0xECCF, 0x5B26, 0xECD4, 0x5B27, 0xECD3,
+	0x5B28, 0xE959, 0x5B2A, 0xC0A7, 0x5B2C, 0xECD2, 0x5B2D, 0xECCE,
+	0x5B2E, 0xECD6, 0x5B2F, 0xECD5, 0x5B30, 0xC0A6, 0x5B32, 0xECD0,
+	0x5B34, 0xBEC6, 0x5B38, 0xC254, 0x5B3C, 0xEFC1, 0x5B3D, 0xF1FA,
+	0x5B3E, 0xF1FB, 0x5B3F, 0xF1FC, 0x5B40, 0xC45C, 0x5B43, 0xC45D,
+	0x5B45, 0xF443, 0x5B47, 0xF5C8, 0x5B48, 0xF5C7, 0x5B4B, 0xF6DB,
+	0x5B4C, 0xF6DC, 0x5B4D, 0xF7D5, 0x5B4E, 0xF8A7, 0x5B50, 0xA46C,
+	0x5B51, 0xA46D, 0x5B53, 0xA46E, 0x5B54, 0xA4D5, 0x5B55, 0xA5A5,
+	0x5B56, 0xC9D3, 0x5B57, 0xA672, 0x5B58, 0xA673, 0x5B5A, 0xA7B7,
+	0x5B5B, 0xA7B8, 0x5B5C, 0xA7B6, 0x5B5D, 0xA7B5, 0x5B5F, 0xA973,
+	0x5B62, 0xCC55, 0x5B63, 0xA975, 0x5B64, 0xA974, 0x5B65, 0xCC56,
+	0x5B69, 0xABC4, 0x5B6B, 0xAE5D, 0x5B6C, 0xD165, 0x5B6E, 0xD4F0,
+	0x5B70, 0xB145, 0x5B71, 0xB447, 0x5B72, 0xD4EF, 0x5B73, 0xB446,
+	0x5B75, 0xB9E5, 0x5B77, 0xE17D, 0x5B78, 0xBEC7, 0x5B7A, 0xC0A9,
+	0x5B7B, 0xECD7, 0x5B7D, 0xC45E, 0x5B7F, 0xC570, 0x5B81, 0xC972,
+	0x5B83, 0xA5A6, 0x5B84, 0xC973, 0x5B85, 0xA676, 0x5B87, 0xA674,
+	0x5B88, 0xA675, 0x5B89, 0xA677, 0x5B8B, 0xA7BA, 0x5B8C, 0xA7B9,
+	0x5B8E, 0xCABC, 0x5B8F, 0xA7BB, 0x5B92, 0xCABD, 0x5B93, 0xCC57,
+	0x5B95, 0xCC58, 0x5B97, 0xA976, 0x5B98, 0xA978, 0x5B99, 0xA97A,
+	0x5B9A, 0xA977, 0x5B9B, 0xA97B, 0x5B9C, 0xA979, 0x5BA2, 0xABC8,
+	0x5BA3, 0xABC5, 0x5BA4, 0xABC7, 0x5BA5, 0xABC9, 0x5BA6, 0xABC6,
+	0x5BA7, 0xD166, 0x5BA8, 0xCE77, 0x5BAC, 0xD168, 0x5BAD, 0xD167,
+	0x5BAE, 0xAE63, 0x5BB0, 0xAE5F, 0x5BB3, 0xAE60, 0x5BB4, 0xAE62,
+	0x5BB5, 0xAE64, 0x5BB6, 0xAE61, 0x5BB8, 0xAE66, 0x5BB9, 0xAE65,
+	0x5BBF, 0xB14A, 0x5BC0, 0xD4F2, 0x5BC1, 0xD4F1, 0x5BC2, 0xB149,
+	0x5BC4, 0xB148, 0x5BC5, 0xB147, 0x5BC6, 0xB14B, 0x5BC7, 0xB146,
+	0x5BCA, 0xD8D5, 0x5BCB, 0xD8D2, 0x5BCC, 0xB449, 0x5BCD, 0xD8D1,
+	0x5BCE, 0xD8D6, 0x5BD0, 0xB44B, 0x5BD1, 0xD8D4, 0x5BD2, 0xB448,
+	0x5BD3, 0xB44A, 0x5BD4, 0xD8D3, 0x5BD6, 0xDD48, 0x5BD8, 0xDD49,
+	0x5BD9, 0xDD4A, 0x5BDE, 0xB9E6, 0x5BDF, 0xB9EE, 0x5BE0, 0xE17E,
+	0x5BE1, 0xB9E8, 0x5BE2, 0xB9EC, 0x5BE3, 0xE1A1, 0x5BE4, 0xB9ED,
+	0x5BE5, 0xB9E9, 0x5BE6, 0xB9EA, 0x5BE7, 0xB9E7, 0x5BE8, 0xB9EB,
+	0x5BE9, 0xBC66, 0x5BEA, 0xD8D0, 0x5BEB, 0xBC67, 0x5BEC, 0xBC65,
+	0x5BEE, 0xBC64, 0x5BEF, 0xE95D, 0x5BF0, 0xBEC8, 0x5BF1, 0xECD8,
+	0x5BF2, 0xECD9, 0x5BF5, 0xC364, 0x5BF6, 0xC45F, 0x5BF8, 0xA46F,
+	0x5BFA, 0xA678, 0x5C01, 0xABCA, 0x5C03, 0xD169, 0x5C04, 0xAE67,
+	0x5C07, 0xB14E, 0x5C08, 0xB14D, 0x5C09, 0xB14C, 0x5C0A, 0xB44C,
+	0x5C0B, 0xB44D, 0x5C0C, 0xD8D7, 0x5C0D, 0xB9EF, 0x5C0E, 0xBEC9,
+	0x5C0F, 0xA470, 0x5C10, 0xC95C, 0x5C11, 0xA4D6, 0x5C12, 0xC974,
+	0x5C15, 0xC9D4, 0x5C16, 0xA679, 0x5C1A, 0xA97C, 0x5C1F, 0xDD4B,
+	0x5C22, 0xA471, 0x5C24, 0xA4D7, 0x5C25, 0xC9D5, 0x5C28, 0xCABE,
+	0x5C2A, 0xCABF, 0x5C2C, 0xA7BC, 0x5C30, 0xD8D8, 0x5C31, 0xB44E,
+	0x5C33, 0xDD4C, 0x5C37, 0xC0AA, 0x5C38, 0xA472, 0x5C39, 0xA4A8,
+	0x5C3A, 0xA4D8, 0x5C3B, 0xC975, 0x5C3C, 0xA5A7, 0x5C3E, 0xA7C0,
+	0x5C3F, 0xA7BF, 0x5C40, 0xA7BD, 0x5C41, 0xA7BE, 0x5C44, 0xCC59,
+	0x5C45, 0xA97E, 0x5C46, 0xA9A1, 0x5C47, 0xCC5A, 0x5C48, 0xA97D,
+	0x5C4B, 0xABCE, 0x5C4C, 0xCE78, 0x5C4D, 0xABCD, 0x5C4E, 0xABCB,
+	0x5C4F, 0xABCC, 0x5C50, 0xAE6A, 0x5C51, 0xAE68, 0x5C54, 0xD16B,
+	0x5C55, 0xAE69, 0x5C56, 0xD16A, 0x5C58, 0xAE5E, 0x5C59, 0xD4F3,
+	0x5C5C, 0xB150, 0x5C5D, 0xB151, 0x5C60, 0xB14F, 0x5C62, 0xB9F0,
+	0x5C63, 0xE1A2, 0x5C64, 0xBC68, 0x5C65, 0xBC69, 0x5C67, 0xE561,
+	0x5C68, 0xC0AB, 0x5C69, 0xEFC2, 0x5C6A, 0xEFC3, 0x5C6C, 0xC4DD,
+	0x5C6D, 0xF8A8, 0x5C6E, 0xC94B, 0x5C6F, 0xA4D9, 0x5C71, 0xA473,
+	0x5C73, 0xC977, 0x5C74, 0xC976, 0x5C79, 0xA67A, 0x5C7A, 0xC9D7,
+	0x5C7B, 0xC9D8, 0x5C7C, 0xC9D6, 0x5C7E, 0xC9D9, 0x5C86, 0xCAC7,
+	0x5C88, 0xCAC2, 0x5C89, 0xCAC4, 0x5C8A, 0xCAC6, 0x5C8B, 0xCAC3,
+	0x5C8C, 0xA7C4, 0x5C8D, 0xCAC0, 0x5C8F, 0xCAC1, 0x5C90, 0xA7C1,
+	0x5C91, 0xA7C2, 0x5C92, 0xCAC5, 0x5C93, 0xCAC8, 0x5C94, 0xA7C3,
+	0x5C95, 0xCAC9, 0x5C9D, 0xCC68, 0x5C9F, 0xCC62, 0x5CA0, 0xCC5D,
+	0x5CA1, 0xA9A3, 0x5CA2, 0xCC65, 0x5CA3, 0xCC63, 0x5CA4, 0xCC5C,
+	0x5CA5, 0xCC69, 0x5CA6, 0xCC6C, 0x5CA7, 0xCC67, 0x5CA8, 0xCC60,
+	0x5CA9, 0xA9A5, 0x5CAA, 0xCC66, 0x5CAB, 0xA9A6, 0x5CAC, 0xCC61,
+	0x5CAD, 0xCC64, 0x5CAE, 0xCC5B, 0x5CAF, 0xCC5F, 0x5CB0, 0xCC6B,
+	0x5CB1, 0xA9A7, 0x5CB3, 0xA9A8, 0x5CB5, 0xCC5E, 0x5CB6, 0xCC6A,
+	0x5CB7, 0xA9A2, 0x5CB8, 0xA9A4, 0x5CC6, 0xCEAB, 0x5CC7, 0xCEA4,
+	0x5CC8, 0xCEAA, 0x5CC9, 0xCEA3, 0x5CCA, 0xCEA5, 0x5CCB, 0xCE7D,
+	0x5CCC, 0xCE7B, 0x5CCE, 0xCEAC, 0x5CCF, 0xCEA9, 0x5CD0, 0xCE79,
+	0x5CD2, 0xABD0, 0x5CD3, 0xCEA7, 0x5CD4, 0xCEA8, 0x5CD6, 0xCEA6,
+	0x5CD7, 0xCE7C, 0x5CD8, 0xCE7A, 0x5CD9, 0xABCF, 0x5CDA, 0xCEA2,
+	0x5CDB, 0xCE7E, 0x5CDE, 0xCEA1, 0x5CDF, 0xCEAD, 0x5CE8, 0xAE6F,
+	0x5CEA, 0xAE6E, 0x5CEC, 0xD16C, 0x5CED, 0xAE6B, 0x5CEE, 0xD16E,
+	0x5CF0, 0xAE70, 0x5CF1, 0xD16F, 0x5CF4, 0xAE73, 0x5CF6, 0xAE71,
+	0x5CF7, 0xD170, 0x5CF8, 0xCEAE, 0x5CF9, 0xD172, 0x5CFB, 0xAE6D,
+	0x5CFD, 0xAE6C, 0x5CFF, 0xD16D, 0x5D00, 0xD171, 0x5D01, 0xAE72,
+	0x5D06, 0xB153, 0x5D07, 0xB152, 0x5D0B, 0xD4F5, 0x5D0C, 0xD4F9,
+	0x5D0D, 0xD4FB, 0x5D0E, 0xB154, 0x5D0F, 0xD4FE, 0x5D11, 0xB158,
+	0x5D12, 0xD541, 0x5D14, 0xB15A, 0x5D16, 0xB156, 0x5D17, 0xB15E,
+	0x5D19, 0xB15B, 0x5D1A, 0xD4F7, 0x5D1B, 0xB155, 0x5D1D, 0xD4F6,
+	0x5D1E, 0xD4F4, 0x5D1F, 0xD543, 0x5D20, 0xD4F8, 0x5D22, 0xB157,
+	0x5D23, 0xD542, 0x5D24, 0xB15C, 0x5D25, 0xD4FD, 0x5D26, 0xD4FC,
+	0x5D27, 0xB15D, 0x5D28, 0xD4FA, 0x5D29, 0xB159, 0x5D2E, 0xD544,
+	0x5D30, 0xD540, 0x5D31, 0xD8E7, 0x5D32, 0xD8EE, 0x5D33, 0xD8E3,
+	0x5D34, 0xB451, 0x5D35, 0xD8DF, 0x5D36, 0xD8EF, 0x5D37, 0xD8D9,
+	0x5D38, 0xD8EC, 0x5D39, 0xD8EA, 0x5D3A, 0xD8E4, 0x5D3C, 0xD8ED,
+	0x5D3D, 0xD8E6, 0x5D3F, 0xD8DE, 0x5D40, 0xD8F0, 0x5D41, 0xD8DC,
+	0x5D42, 0xD8E9, 0x5D43, 0xD8DA, 0x5D45, 0xD8F1, 0x5D47, 0xB452,
+	0x5D49, 0xD8EB, 0x5D4A, 0xDD4F, 0x5D4B, 0xD8DD, 0x5D4C, 0xB44F,
+	0x5D4E, 0xD8E1, 0x5D50, 0xB450, 0x5D51, 0xD8E0, 0x5D52, 0xD8E5,
+	0x5D55, 0xD8E2, 0x5D59, 0xD8E8, 0x5D5E, 0xDD53, 0x5D62, 0xDD56,
+	0x5D63, 0xDD4E, 0x5D65, 0xDD50, 0x5D67, 0xDD55, 0x5D68, 0xDD54,
+	0x5D69, 0xB743, 0x5D6B, 0xD8DB, 0x5D6C, 0xDD52, 0x5D6F, 0xB744,
+	0x5D71, 0xDD4D, 0x5D72, 0xDD51, 0x5D77, 0xE1A9, 0x5D79, 0xE1B0,
+	0x5D7A, 0xE1A7, 0x5D7C, 0xE1AE, 0x5D7D, 0xE1A5, 0x5D7E, 0xE1AD,
+	0x5D7F, 0xE1B1, 0x5D80, 0xE1A4, 0x5D81, 0xE1A8, 0x5D82, 0xE1A3,
+	0x5D84, 0xB9F1, 0x5D86, 0xE1A6, 0x5D87, 0xB9F2, 0x5D88, 0xE1AC,
+	0x5D89, 0xE1AB, 0x5D8A, 0xE1AA, 0x5D8D, 0xE1AF, 0x5D92, 0xE565,
+	0x5D93, 0xE567, 0x5D94, 0xBC6B, 0x5D95, 0xE568, 0x5D97, 0xE563,
+	0x5D99, 0xE562, 0x5D9A, 0xE56C, 0x5D9C, 0xE56A, 0x5D9D, 0xBC6A,
+	0x5D9E, 0xE56D, 0x5D9F, 0xE564, 0x5DA0, 0xE569, 0x5DA1, 0xE56B,
+	0x5DA2, 0xE566, 0x5DA7, 0xE961, 0x5DA8, 0xE966, 0x5DA9, 0xE960,
+	0x5DAA, 0xE965, 0x5DAC, 0xE95E, 0x5DAD, 0xE968, 0x5DAE, 0xE964,
+	0x5DAF, 0xE969, 0x5DB0, 0xE963, 0x5DB1, 0xE95F, 0x5DB2, 0xE967,
+	0x5DB4, 0xE96A, 0x5DB5, 0xE962, 0x5DB7, 0xECDA, 0x5DB8, 0xC0AF,
+	0x5DBA, 0xC0AD, 0x5DBC, 0xC0AC, 0x5DBD, 0xC0AE, 0x5DC0, 0xEFC4,
+	0x5DC2, 0xF172, 0x5DC3, 0xF1FD, 0x5DC6, 0xF444, 0x5DC7, 0xF445,
+	0x5DC9, 0xC460, 0x5DCB, 0xF5C9, 0x5DCD, 0xC4DE, 0x5DCF, 0xF5CA,
+	0x5DD1, 0xF6DE, 0x5DD2, 0xC572, 0x5DD4, 0xC571, 0x5DD5, 0xF6DD,
+	0x5DD6, 0xC5C9, 0x5DD8, 0xF7D6, 0x5DDD, 0xA474, 0x5DDE, 0xA67B,
+	0x5DDF, 0xC9DA, 0x5DE0, 0xCACA, 0x5DE1, 0xA8B5, 0x5DE2, 0xB15F,
+	0x5DE5, 0xA475, 0x5DE6, 0xA5AA, 0x5DE7, 0xA5A9, 0x5DE8, 0xA5A8,
+	0x5DEB, 0xA7C5, 0x5DEE, 0xAE74, 0x5DF0, 0xDD57, 0x5DF1, 0xA476,
+	0x5DF2, 0xA477, 0x5DF3, 0xA478, 0x5DF4, 0xA4DA, 0x5DF7, 0xABD1,
+	0x5DF9, 0xCEAF, 0x5DFD, 0xB453, 0x5DFE, 0xA479, 0x5DFF, 0xC95D,
+	0x5E02, 0xA5AB, 0x5E03, 0xA5AC, 0x5E04, 0xC978, 0x5E06, 0xA67C,
+	0x5E0A, 0xCACB, 0x5E0C, 0xA7C6, 0x5E0E, 0xCACC, 0x5E11, 0xA9AE,
+	0x5E14, 0xCC6E, 0x5E15, 0xA9AC, 0x5E16, 0xA9AB, 0x5E17, 0xCC6D,
+	0x5E18, 0xA9A9, 0x5E19, 0xCC6F, 0x5E1A, 0xA9AA, 0x5E1B, 0xA9AD,
+	0x5E1D, 0xABD2, 0x5E1F, 0xABD4, 0x5E20, 0xCEB3, 0x5E21, 0xCEB0,
+	0x5E22, 0xCEB1, 0x5E23, 0xCEB2, 0x5E24, 0xCEB4, 0x5E25, 0xABD3,
+	0x5E28, 0xD174, 0x5E29, 0xD173, 0x5E2B, 0xAE76, 0x5E2D, 0xAE75,
+	0x5E33, 0xB162, 0x5E34, 0xD546, 0x5E36, 0xB161, 0x5E37, 0xB163,
+	0x5E38, 0xB160, 0x5E3D, 0xB455, 0x5E3E, 0xD545, 0x5E40, 0xB456,
+	0x5E41, 0xD8F3, 0x5E43, 0xB457, 0x5E44, 0xD8F2, 0x5E45, 0xB454,
+	0x5E4A, 0xDD5A, 0x5E4B, 0xDD5C, 0x5E4C, 0xB745, 0x5E4D, 0xDD5B,
+	0x5E4E, 0xDD59, 0x5E4F, 0xDD58, 0x5E53, 0xE1B4, 0x5E54, 0xB9F7,
+	0x5E55, 0xB9F5, 0x5E57, 0xB9F6, 0x5E58, 0xE1B2, 0x5E59, 0xE1B3,
+	0x5E5B, 0xB9F3, 0x5E5C, 0xE571, 0x5E5D, 0xE56F, 0x5E5F, 0xBC6D,
+	0x5E60, 0xE570, 0x5E61, 0xBC6E, 0x5E62, 0xBC6C, 0x5E63, 0xB9F4,
+	0x5E66, 0xE96D, 0x5E67, 0xE96B, 0x5E68, 0xE96C, 0x5E69, 0xE56E,
+	0x5E6A, 0xECDC, 0x5E6B, 0xC0B0, 0x5E6C, 0xECDB, 0x5E6D, 0xEFC5,
+	0x5E6E, 0xEFC6, 0x5E6F, 0xE96E, 0x5E70, 0xF1FE, 0x5E72, 0xA47A,
+	0x5E73, 0xA5AD, 0x5E74, 0xA67E, 0x5E75, 0xC9DB, 0x5E76, 0xA67D,
+	0x5E78, 0xA9AF, 0x5E79, 0xB746, 0x5E7B, 0xA4DB, 0x5E7C, 0xA5AE,
+	0x5E7D, 0xABD5, 0x5E7E, 0xB458, 0x5E80, 0xC979, 0x5E82, 0xC97A,
+	0x5E84, 0xC9DC, 0x5E87, 0xA7C8, 0x5E88, 0xCAD0, 0x5E89, 0xCACE,
+	0x5E8A, 0xA7C9, 0x5E8B, 0xCACD, 0x5E8C, 0xCACF, 0x5E8D, 0xCAD1,
+	0x5E8F, 0xA7C7, 0x5E95, 0xA9B3, 0x5E96, 0xA9B4, 0x5E97, 0xA9B1,
+	0x5E9A, 0xA9B0, 0x5E9B, 0xCEB8, 0x5E9C, 0xA9B2, 0x5EA0, 0xABD6,
+	0x5EA2, 0xCEB7, 0x5EA3, 0xCEB9, 0x5EA4, 0xCEB6, 0x5EA5, 0xCEBA,
+	0x5EA6, 0xABD7, 0x5EA7, 0xAE79, 0x5EA8, 0xD175, 0x5EAA, 0xD177,
+	0x5EAB, 0xAE77, 0x5EAC, 0xD178, 0x5EAD, 0xAE78, 0x5EAE, 0xD176,
+	0x5EB0, 0xCEB5, 0x5EB1, 0xD547, 0x5EB2, 0xD54A, 0x5EB3, 0xD54B,
+	0x5EB4, 0xD548, 0x5EB5, 0xB167, 0x5EB6, 0xB166, 0x5EB7, 0xB164,
+	0x5EB8, 0xB165, 0x5EB9, 0xD549, 0x5EBE, 0xB168, 0x5EC1, 0xB45A,
+	0x5EC2, 0xB45B, 0x5EC4, 0xB45C, 0x5EC5, 0xDD5D, 0x5EC6, 0xDD5F,
+	0x5EC7, 0xDD61, 0x5EC8, 0xB748, 0x5EC9, 0xB747, 0x5ECA, 0xB459,
+	0x5ECB, 0xDD60, 0x5ECC, 0xDD5E, 0x5ECE, 0xE1B8, 0x5ED1, 0xE1B6,
+	0x5ED2, 0xE1BC, 0x5ED3, 0xB9F8, 0x5ED4, 0xE1BD, 0x5ED5, 0xE1BA,
+	0x5ED6, 0xB9F9, 0x5ED7, 0xE1B7, 0x5ED8, 0xE1B5, 0x5ED9, 0xE1BB,
+	0x5EDA, 0xBC70, 0x5EDB, 0xE573, 0x5EDC, 0xE1B9, 0x5EDD, 0xBC72,
+	0x5EDE, 0xE574, 0x5EDF, 0xBC71, 0x5EE0, 0xBC74, 0x5EE1, 0xE575,
+	0x5EE2, 0xBC6F, 0x5EE3, 0xBC73, 0x5EE5, 0xE973, 0x5EE6, 0xE971,
+	0x5EE7, 0xE970, 0x5EE8, 0xE972, 0x5EE9, 0xE96F, 0x5EEC, 0xC366,
+	0x5EEE, 0xF446, 0x5EEF, 0xF447, 0x5EF1, 0xF5CB, 0x5EF2, 0xF6DF,
+	0x5EF3, 0xC655, 0x5EF6, 0xA9B5, 0x5EF7, 0xA7CA, 0x5EFA, 0xABD8,
+	0x5EFE, 0xA47B, 0x5EFF, 0xA4DC, 0x5F01, 0xA5AF, 0x5F02, 0xC9DD,
+	0x5F04, 0xA7CB, 0x5F05, 0xCAD2, 0x5F07, 0xCEBB, 0x5F08, 0xABD9,
+	0x5F0A, 0xB9FA, 0x5F0B, 0xA47C, 0x5F0F, 0xA6A1, 0x5F12, 0xB749,
+	0x5F13, 0xA47D, 0x5F14, 0xA4DD, 0x5F15, 0xA4DE, 0x5F17, 0xA5B1,
+	0x5F18, 0xA5B0, 0x5F1A, 0xC9DE, 0x5F1B, 0xA6A2, 0x5F1D, 0xCAD3,
+	0x5F1F, 0xA7CC, 0x5F22, 0xCC71, 0x5F23, 0xCC72, 0x5F24, 0xCC73,
+	0x5F26, 0xA9B6, 0x5F27, 0xA9B7, 0x5F28, 0xCC70, 0x5F29, 0xA9B8,
+	0x5F2D, 0xABDA, 0x5F2E, 0xCEBC, 0x5F30, 0xD17A, 0x5F31, 0xAE7A,
+	0x5F33, 0xD179, 0x5F35, 0xB169, 0x5F36, 0xD54C, 0x5F37, 0xB16A,
+	0x5F38, 0xD54D, 0x5F3C, 0xB45D, 0x5F40, 0xDD62, 0x5F43, 0xE1BF,
+	0x5F44, 0xE1BE, 0x5F46, 0xB9FB, 0x5F48, 0xBC75, 0x5F49, 0xE576,
+	0x5F4A, 0xBECA, 0x5F4B, 0xE974, 0x5F4C, 0xC0B1, 0x5F4E, 0xC573,
+	0x5F4F, 0xF7D8, 0x5F54, 0xCC74, 0x5F56, 0xCEBD, 0x5F57, 0xB16B,
+	0x5F58, 0xD8F4, 0x5F59, 0xB74A, 0x5F5D, 0xC255, 0x5F62, 0xA7CE,
+	0x5F64, 0xA7CD, 0x5F65, 0xABDB, 0x5F67, 0xD17B, 0x5F69, 0xB16D,
+	0x5F6A, 0xB343, 0x5F6B, 0xB16E, 0x5F6C, 0xB16C, 0x5F6D, 0xB45E,
+	0x5F6F, 0xE1C0, 0x5F70, 0xB9FC, 0x5F71, 0xBC76, 0x5F73, 0xC94C,
+	0x5F74, 0xC9DF, 0x5F76, 0xCAD5, 0x5F77, 0xA7CF, 0x5F78, 0xCAD4,
+	0x5F79, 0xA7D0, 0x5F7C, 0xA9BC, 0x5F7D, 0xCC77, 0x5F7E, 0xCC76,
+	0x5F7F, 0xA9BB, 0x5F80, 0xA9B9, 0x5F81, 0xA9BA, 0x5F82, 0xCC75,
+	0x5F85, 0xABDD, 0x5F86, 0xCEBE, 0x5F87, 0xABE0, 0x5F88, 0xABDC,
+	0x5F89, 0xABE2, 0x5F8A, 0xABDE, 0x5F8B, 0xABDF, 0x5F8C, 0xABE1,
+	0x5F90, 0xAE7D, 0x5F91, 0xAE7C, 0x5F92, 0xAE7B, 0x5F96, 0xD54F,
+	0x5F97, 0xB16F, 0x5F98, 0xB172, 0x5F99, 0xB170, 0x5F9B, 0xD54E,
+	0x5F9C, 0xB175, 0x5F9E, 0xB171, 0x5F9F, 0xD550, 0x5FA0, 0xB174,
+	0x5FA1, 0xB173, 0x5FA5, 0xD8F6, 0x5FA6, 0xD8F5, 0x5FA8, 0xB461,
+	0x5FA9, 0xB45F, 0x5FAA, 0xB460, 0x5FAB, 0xD8F7, 0x5FAC, 0xB74B,
+	0x5FAD, 0xDD64, 0x5FAE, 0xB74C, 0x5FAF, 0xDD63, 0x5FB2, 0xE577,
+	0x5FB5, 0xBC78, 0x5FB6, 0xE1C1, 0x5FB7, 0xBC77, 0x5FB9, 0xB9FD,
+	0x5FBB, 0xECDE, 0x5FBC, 0xE975, 0x5FBD, 0xC0B2, 0x5FBE, 0xECDD,
+	0x5FBF, 0xF240, 0x5FC0, 0xF448, 0x5FC1, 0xF449, 0x5FC3, 0xA4DF,
+	0x5FC5, 0xA5B2, 0x5FC9, 0xC97B, 0x5FCC, 0xA7D2, 0x5FCD, 0xA7D4,
+	0x5FCF, 0xC9E2, 0x5FD0, 0xCAD8, 0x5FD1, 0xCAD7, 0x5FD2, 0xCAD6,
+	0x5FD4, 0xC9E1, 0x5FD5, 0xC9E0, 0x5FD6, 0xA6A4, 0x5FD7, 0xA7D3,
+	0x5FD8, 0xA7D1, 0x5FD9, 0xA6A3, 0x5FDD, 0xA9BD, 0x5FDE, 0xCC78,
+	0x5FE0, 0xA9BE, 0x5FE1, 0xCADD, 0x5FE3, 0xCADF, 0x5FE4, 0xCADE,
+	0x5FE5, 0xCC79, 0x5FE8, 0xCADA, 0x5FEA, 0xA7D8, 0x5FEB, 0xA7D6,
+	0x5FED, 0xCAD9, 0x5FEE, 0xCADB, 0x5FEF, 0xCAE1, 0x5FF1, 0xA7D5,
+	0x5FF3, 0xCADC, 0x5FF4, 0xCAE5, 0x5FF5, 0xA9C0, 0x5FF7, 0xCAE2,
+	0x5FF8, 0xA7D7, 0x5FFA, 0xCAE0, 0x5FFB, 0xCAE3, 0x5FFD, 0xA9BF,
+	0x5FFF, 0xA9C1, 0x6000, 0xCAE4, 0x6009, 0xCCAF, 0x600A, 0xCCA2,
+	0x600B, 0xCC7E, 0x600C, 0xCCAE, 0x600D, 0xCCA9, 0x600E, 0xABE7,
+	0x600F, 0xA9C2, 0x6010, 0xCCAA, 0x6011, 0xCCAD, 0x6012, 0xABE3,
+	0x6013, 0xCCAC, 0x6014, 0xA9C3, 0x6015, 0xA9C8, 0x6016, 0xA9C6,
+	0x6017, 0xCCA3, 0x6019, 0xCC7C, 0x601A, 0xCCA5, 0x601B, 0xA9CD,
+	0x601C, 0xCCB0, 0x601D, 0xABE4, 0x601E, 0xCCA6, 0x6020, 0xABE5,
+	0x6021, 0xA9C9, 0x6022, 0xCCA8, 0x6024, 0xCECD, 0x6025, 0xABE6,
+	0x6026, 0xCC7B, 0x6027, 0xA9CA, 0x6028, 0xABE8, 0x6029, 0xA9CB,
+	0x602A, 0xA9C7, 0x602B, 0xA9CC, 0x602C, 0xCCA7, 0x602D, 0xCC7A,
+	0x602E, 0xCCAB, 0x602F, 0xA9C4, 0x6032, 0xCC7D, 0x6033, 0xCCA4,
+	0x6034, 0xCCA1, 0x6035, 0xA9C5, 0x6037, 0xCEBF, 0x6039, 0xCEC0,
+	0x6040, 0xCECA, 0x6041, 0xD1A1, 0x6042, 0xCECB, 0x6043, 0xABEE,
+	0x6044, 0xCECE, 0x6045, 0xCEC4, 0x6046, 0xABED, 0x6047, 0xCEC6,
+	0x6049, 0xCEC7, 0x604C, 0xCEC9, 0x604D, 0xABE9, 0x6050, 0xAEA3,
+	0x6052, 0xF9DA, 0x6053, 0xCEC5, 0x6054, 0xCEC1, 0x6055, 0xAEA4,
+	0x6058, 0xCECF, 0x6059, 0xAE7E, 0x605A, 0xD17D, 0x605B, 0xCEC8,
+	0x605D, 0xD17C, 0x605E, 0xCEC3, 0x605F, 0xCECC, 0x6062, 0xABEC,
+	0x6063, 0xAEA1, 0x6064, 0xABF2, 0x6065, 0xAEA2, 0x6066, 0xCED0,
+	0x6067, 0xD17E, 0x6068, 0xABEB, 0x6069, 0xAEA6, 0x606A, 0xABF1,
+	0x606B, 0xABF0, 0x606C, 0xABEF, 0x606D, 0xAEA5, 0x606E, 0xCED1,
+	0x606F, 0xAEA7, 0x6070, 0xABEA, 0x6072, 0xCEC2, 0x607F, 0xB176,
+	0x6080, 0xD1A4, 0x6081, 0xD1A6, 0x6083, 0xD1A8, 0x6084, 0xAEA8,
+	0x6085, 0xAEAE, 0x6086, 0xD553, 0x6087, 0xD1AC, 0x6088, 0xD1A3,
+	0x6089, 0xB178, 0x608A, 0xD551, 0x608C, 0xAEAD, 0x608D, 0xAEAB,
+	0x608E, 0xD1AE, 0x6090, 0xD552, 0x6092, 0xD1A5, 0x6094, 0xAEAC,
+	0x6095, 0xD1A9, 0x6096, 0xAEAF, 0x6097, 0xD1AB, 0x609A, 0xAEAA,
+	0x609B, 0xD1AA, 0x609C, 0xD1AD, 0x609D, 0xD1A7, 0x609F, 0xAEA9,
+	0x60A0, 0xB179, 0x60A2, 0xD1A2, 0x60A3, 0xB177, 0x60A8, 0xB17A,
+	0x60B0, 0xD555, 0x60B1, 0xD55E, 0x60B2, 0xB464, 0x60B4, 0xB17C,
+	0x60B5, 0xB1A3, 0x60B6, 0xB465, 0x60B7, 0xD560, 0x60B8, 0xB1AA,
+	0x60B9, 0xD8F9, 0x60BA, 0xD556, 0x60BB, 0xB1A2, 0x60BC, 0xB1A5,
+	0x60BD, 0xB17E, 0x60BE, 0xD554, 0x60BF, 0xD562, 0x60C0, 0xD565,
+	0x60C1, 0xD949, 0x60C3, 0xD563, 0x60C4, 0xD8FD, 0x60C5, 0xB1A1,
+	0x60C6, 0xB1A8, 0x60C7, 0xB1AC, 0x60C8, 0xD55D, 0x60C9, 0xD8F8,
+	0x60CA, 0xD561, 0x60CB, 0xB17B, 0x60CC, 0xD8FA, 0x60CD, 0xD564,
+	0x60CE, 0xD8FC, 0x60CF, 0xD559, 0x60D1, 0xB462, 0x60D3, 0xD557,
+	0x60D4, 0xD558, 0x60D5, 0xB1A7, 0x60D8, 0xB1A6, 0x60D9, 0xD55B,
+	0x60DA, 0xB1AB, 0x60DB, 0xD55F, 0x60DC, 0xB1A4, 0x60DD, 0xD55C,
+	0x60DF, 0xB1A9, 0x60E0, 0xB466, 0x60E1, 0xB463, 0x60E2, 0xD8FB,
+	0x60E4, 0xD55A, 0x60E6, 0xB17D, 0x60F0, 0xB46B, 0x60F1, 0xB46F,
+	0x60F2, 0xD940, 0x60F3, 0xB751, 0x60F4, 0xB46D, 0x60F5, 0xD944,
+	0x60F6, 0xB471, 0x60F7, 0xDD65, 0x60F8, 0xD946, 0x60F9, 0xB753,
+	0x60FA, 0xB469, 0x60FB, 0xB46C, 0x60FC, 0xD947, 0x60FE, 0xD948,
+	0x60FF, 0xD94E, 0x6100, 0xB473, 0x6101, 0xB754, 0x6103, 0xD94A,
+	0x6104, 0xD94F, 0x6105, 0xD943, 0x6106, 0xB75E, 0x6108, 0xB755,
+	0x6109, 0xB472, 0x610A, 0xD941, 0x610B, 0xD950, 0x610D, 0xB75D,
+	0x610E, 0xB470, 0x610F, 0xB74E, 0x6110, 0xD94D, 0x6112, 0xB474,
+	0x6113, 0xD945, 0x6114, 0xD8FE, 0x6115, 0xB46A, 0x6116, 0xD942,
+	0x6118, 0xD94B, 0x611A, 0xB74D, 0x611B, 0xB752, 0x611C, 0xB467,
+	0x611D, 0xD94C, 0x611F, 0xB750, 0x6123, 0xB468, 0x6127, 0xB75C,
+	0x6128, 0xE1C3, 0x6129, 0xDD70, 0x612B, 0xDD68, 0x612C, 0xE1C2,
+	0x612E, 0xDD6C, 0x612F, 0xDD6E, 0x6132, 0xDD6B, 0x6134, 0xB75B,
+	0x6136, 0xDD6A, 0x6137, 0xB75F, 0x613B, 0xE1D2, 0x613E, 0xB75A,
+	0x613F, 0xBA40, 0x6140, 0xDD71, 0x6141, 0xE1C4, 0x6144, 0xB758,
+	0x6145, 0xDD69, 0x6146, 0xDD6D, 0x6147, 0xB9FE, 0x6148, 0xB74F,
+	0x6149, 0xDD66, 0x614A, 0xDD67, 0x614B, 0xBA41, 0x614C, 0xB757,
+	0x614D, 0xB759, 0x614E, 0xB756, 0x614F, 0xDD6F, 0x6152, 0xE1C8,
+	0x6153, 0xE1C9, 0x6154, 0xE1CE, 0x6155, 0xBC7D, 0x6156, 0xE1D5,
+	0x6158, 0xBA47, 0x615A, 0xBA46, 0x615B, 0xE1D0, 0x615D, 0xBC7C,
+	0x615E, 0xE1C5, 0x615F, 0xBA45, 0x6161, 0xE1D4, 0x6162, 0xBA43,
+	0x6163, 0xBA44, 0x6165, 0xE1D1, 0x6166, 0xE5AA, 0x6167, 0xBC7A,
+	0x6168, 0xB46E, 0x616A, 0xE1D3, 0x616B, 0xBCA3, 0x616C, 0xE1CB,
+	0x616E, 0xBC7B, 0x6170, 0xBCA2, 0x6171, 0xE1C6, 0x6172, 0xE1CA,
+	0x6173, 0xE1C7, 0x6174, 0xE1CD, 0x6175, 0xBA48, 0x6176, 0xBC79,
+	0x6177, 0xBA42, 0x6179, 0xE57A, 0x617A, 0xE1CF, 0x617C, 0xBCA1,
+	0x617E, 0xBCA4, 0x6180, 0xE1CC, 0x6182, 0xBC7E, 0x6183, 0xE579,
+	0x6189, 0xE57E, 0x618A, 0xBECE, 0x618B, 0xE578, 0x618C, 0xE9A3,
+	0x618D, 0xE5A9, 0x618E, 0xBCA8, 0x6190, 0xBCA6, 0x6191, 0xBECC,
+	0x6192, 0xE5A6, 0x6193, 0xE5A2, 0x6194, 0xBCAC, 0x6196, 0xE978,
+	0x619A, 0xBCAA, 0x619B, 0xE5A1, 0x619D, 0xE976, 0x619F, 0xE5A5,
+	0x61A1, 0xE5A8, 0x61A2, 0xE57D, 0x61A4, 0xBCAB, 0x61A7, 0xBCA5,
+	0x61A8, 0xE977, 0x61A9, 0xBECD, 0x61AA, 0xE5A7, 0x61AB, 0xBCA7,
+	0x61AC, 0xBCA9, 0x61AD, 0xE5A4, 0x61AE, 0xBCAD, 0x61AF, 0xE5A3,
+	0x61B0, 0xE57C, 0x61B1, 0xE57B, 0x61B2, 0xBECB, 0x61B3, 0xE5AB,
+	0x61B4, 0xE97A, 0x61B5, 0xECE0, 0x61B6, 0xBED0, 0x61B8, 0xE9A2,
+	0x61BA, 0xE97E, 0x61BC, 0xECE1, 0x61BE, 0xBED1, 0x61BF, 0xE9A1,
+	0x61C1, 0xE97C, 0x61C2, 0xC0B4, 0x61C3, 0xECDF, 0x61C5, 0xE979,
+	0x61C6, 0xE97B, 0x61C7, 0xC0B5, 0x61C8, 0xBED3, 0x61C9, 0xC0B3,
+	0x61CA, 0xBED2, 0x61CB, 0xC0B7, 0x61CC, 0xE97D, 0x61CD, 0xBECF,
+	0x61D6, 0xEFCF, 0x61D8, 0xEFC7, 0x61DE, 0xECE7, 0x61DF, 0xEFC8,
+	0x61E0, 0xECE3, 0x61E3, 0xC256, 0x61E4, 0xECE5, 0x61E5, 0xECE4,
+	0x61E6, 0xC0B6, 0x61E7, 0xECE2, 0x61E8, 0xECE6, 0x61E9, 0xEFD0,
+	0x61EA, 0xEFCC, 0x61EB, 0xEFCE, 0x61ED, 0xEFC9, 0x61EE, 0xEFCA,
+	0x61F0, 0xEFCD, 0x61F1, 0xEFCB, 0x61F2, 0xC367, 0x61F5, 0xC36A,
+	0x61F6, 0xC369, 0x61F7, 0xC368, 0x61F8, 0xC461, 0x61F9, 0xF44A,
+	0x61FA, 0xC462, 0x61FB, 0xF241, 0x61FC, 0xC4DF, 0x61FD, 0xF5CC,
+	0x61FE, 0xC4E0, 0x61FF, 0xC574, 0x6200, 0xC5CA, 0x6201, 0xF7D9,
+	0x6203, 0xF7DA, 0x6204, 0xF7DB, 0x6207, 0xF9BA, 0x6208, 0xA4E0,
+	0x6209, 0xC97C, 0x620A, 0xA5B3, 0x620C, 0xA6A6, 0x620D, 0xA6A7,
+	0x620E, 0xA6A5, 0x6210, 0xA6A8, 0x6211, 0xA7DA, 0x6212, 0xA7D9,
+	0x6214, 0xCCB1, 0x6215, 0xA9CF, 0x6216, 0xA9CE, 0x6219, 0xD1AF,
+	0x621A, 0xB1AD, 0x621B, 0xB1AE, 0x621F, 0xB475, 0x6220, 0xDD72,
+	0x6221, 0xB760, 0x6222, 0xB761, 0x6223, 0xDD74, 0x6224, 0xDD76,
+	0x6225, 0xDD75, 0x6227, 0xE1D7, 0x6229, 0xE1D6, 0x622A, 0xBA49,
+	0x622B, 0xE1D8, 0x622D, 0xE5AC, 0x622E, 0xBCAE, 0x6230, 0xBED4,
+	0x6232, 0xC0B8, 0x6233, 0xC257, 0x6234, 0xC0B9, 0x6236, 0xA4E1,
+	0x623A, 0xCAE6, 0x623D, 0xCCB2, 0x623E, 0xA9D1, 0x623F, 0xA9D0,
+	0x6240, 0xA9D2, 0x6241, 0xABF3, 0x6242, 0xCED2, 0x6243, 0xCED3,
+	0x6246, 0xD1B0, 0x6247, 0xAEB0, 0x6248, 0xB1AF, 0x6249, 0xB476,
+	0x624A, 0xD951, 0x624B, 0xA4E2, 0x624D, 0xA47E, 0x624E, 0xA4E3,
+	0x6250, 0xC97D, 0x6251, 0xA5B7, 0x6252, 0xA5B6, 0x6253, 0xA5B4,
+	0x6254, 0xA5B5, 0x6258, 0xA6AB, 0x6259, 0xC9E9, 0x625A, 0xC9EB,
+	0x625B, 0xA6AA, 0x625C, 0xC9E3, 0x625E, 0xC9E4, 0x6260, 0xC9EA,
+	0x6261, 0xC9E6, 0x6262, 0xC9E8, 0x6263, 0xA6A9, 0x6264, 0xC9E5,
+	0x6265, 0xC9EC, 0x6266, 0xC9E7, 0x626D, 0xA7E1, 0x626E, 0xA7EA,
+	0x626F, 0xA7E8, 0x6270, 0xCAF0, 0x6271, 0xCAED, 0x6272, 0xCAF5,
+	0x6273, 0xA7E6, 0x6274, 0xCAF6, 0x6276, 0xA7DF, 0x6277, 0xCAF3,
+	0x6279, 0xA7E5, 0x627A, 0xCAEF, 0x627B, 0xCAEE, 0x627C, 0xA7E3,
+	0x627D, 0xCAF4, 0x627E, 0xA7E4, 0x627F, 0xA9D3, 0x6280, 0xA7DE,
+	0x6281, 0xCAF1, 0x6283, 0xCAE7, 0x6284, 0xA7DB, 0x6286, 0xA7EE,
+	0x6287, 0xCAEC, 0x6288, 0xCAF2, 0x6289, 0xA7E0, 0x628A, 0xA7E2,
+	0x628C, 0xCAE8, 0x628E, 0xCAE9, 0x628F, 0xCAEA, 0x6291, 0xA7ED,
+	0x6292, 0xA7E7, 0x6293, 0xA7EC, 0x6294, 0xCAEB, 0x6295, 0xA7EB,
+	0x6296, 0xA7DD, 0x6297, 0xA7DC, 0x6298, 0xA7E9, 0x62A8, 0xA9E1,
+	0x62A9, 0xCCBE, 0x62AA, 0xCCB7, 0x62AB, 0xA9DC, 0x62AC, 0xA9EF,
+	0x62AD, 0xCCB3, 0x62AE, 0xCCBA, 0x62AF, 0xCCBC, 0x62B0, 0xCCBF,
+	0x62B1, 0xA9EA, 0x62B3, 0xCCBB, 0x62B4, 0xCCB4, 0x62B5, 0xA9E8,
+	0x62B6, 0xCCB8, 0x62B8, 0xCCC0, 0x62B9, 0xA9D9, 0x62BB, 0xCCBD,
+	0x62BC, 0xA9E3, 0x62BD, 0xA9E2, 0x62BE, 0xCCB6, 0x62BF, 0xA9D7,
+	0x62C2, 0xA9D8, 0x62C4, 0xA9D6, 0x62C6, 0xA9EE, 0x62C7, 0xA9E6,
+	0x62C8, 0xA9E0, 0x62C9, 0xA9D4, 0x62CA, 0xCCB9, 0x62CB, 0xA9DF,
+	0x62CC, 0xA9D5, 0x62CD, 0xA9E7, 0x62CE, 0xA9F0, 0x62CF, 0xCED4,
+	0x62D0, 0xA9E4, 0x62D1, 0xCCB5, 0x62D2, 0xA9DA, 0x62D3, 0xA9DD,
+	0x62D4, 0xA9DE, 0x62D6, 0xA9EC, 0x62D7, 0xA9ED, 0x62D8, 0xA9EB,
+	0x62D9, 0xA9E5, 0x62DA, 0xA9E9, 0x62DB, 0xA9DB, 0x62DC, 0xABF4,
+	0x62EB, 0xCEDA, 0x62EC, 0xAC41, 0x62ED, 0xABF8, 0x62EE, 0xABFA,
+	0x62EF, 0xAC40, 0x62F0, 0xCEE6, 0x62F1, 0xABFD, 0x62F2, 0xD1B1,
+	0x62F3, 0xAEB1, 0x62F4, 0xAC43, 0x62F5, 0xCED7, 0x62F6, 0xCEDF,
+	0x62F7, 0xABFE, 0x62F8, 0xCEDE, 0x62F9, 0xCEDB, 0x62FA, 0xCEE3,
+	0x62FB, 0xCEE5, 0x62FC, 0xABF7, 0x62FD, 0xABFB, 0x62FE, 0xAC42,
+	0x62FF, 0xAEB3, 0x6300, 0xCEE0, 0x6301, 0xABF9, 0x6302, 0xAC45,
+	0x6303, 0xCED9, 0x6307, 0xABFC, 0x6308, 0xAEB2, 0x6309, 0xABF6,
+	0x630B, 0xCED6, 0x630C, 0xCEDD, 0x630D, 0xCED5, 0x630E, 0xCED8,
+	0x630F, 0xCEDC, 0x6310, 0xD1B2, 0x6311, 0xAC44, 0x6313, 0xCEE1,
+	0x6314, 0xCEE2, 0x6315, 0xCEE4, 0x6316, 0xABF5, 0x6328, 0xAEC1,
+	0x6329, 0xD1BE, 0x632A, 0xAEBF, 0x632B, 0xAEC0, 0x632C, 0xD1B4,
+	0x632D, 0xD1C4, 0x632F, 0xAEB6, 0x6332, 0xD566, 0x6333, 0xD1C6,
+	0x6334, 0xD1C0, 0x6336, 0xD1B7, 0x6338, 0xD1C9, 0x6339, 0xD1BA,
+	0x633A, 0xAEBC, 0x633B, 0xD57D, 0x633C, 0xD1BD, 0x633D, 0xAEBE,
+	0x633E, 0xAEB5, 0x6340, 0xD1CB, 0x6341, 0xD1BF, 0x6342, 0xAEB8,
+	0x6343, 0xD1B8, 0x6344, 0xD1B5, 0x6345, 0xD1B6, 0x6346, 0xAEB9,
+	0x6347, 0xD1C5, 0x6348, 0xD1CC, 0x6349, 0xAEBB, 0x634A, 0xD1BC,
+	0x634B, 0xD1BB, 0x634C, 0xAEC3, 0x634D, 0xAEC2, 0x634E, 0xAEB4,
+	0x634F, 0xAEBA, 0x6350, 0xAEBD, 0x6351, 0xD1C8, 0x6354, 0xD1C2,
+	0x6355, 0xAEB7, 0x6356, 0xD1B3, 0x6357, 0xD1CA, 0x6358, 0xD1C1,
+	0x6359, 0xD1C3, 0x635A, 0xD1C7, 0x6365, 0xD567, 0x6367, 0xB1B7,
+	0x6368, 0xB1CB, 0x6369, 0xB1CA, 0x636B, 0xB1BF, 0x636D, 0xD579,
+	0x636E, 0xD575, 0x636F, 0xD572, 0x6370, 0xD5A6, 0x6371, 0xB1BA,
+	0x6372, 0xB1B2, 0x6375, 0xD577, 0x6376, 0xB4A8, 0x6377, 0xB1B6,
+	0x6378, 0xD5A1, 0x637A, 0xB1CC, 0x637B, 0xB1C9, 0x637C, 0xD57B,
+	0x637D, 0xD56A, 0x6380, 0xB1C8, 0x6381, 0xD5A3, 0x6382, 0xD569,
+	0x6383, 0xB1BD, 0x6384, 0xB1C1, 0x6385, 0xD5A2, 0x6387, 0xD573,
+	0x6388, 0xB1C2, 0x6389, 0xB1BC, 0x638A, 0xD568, 0x638C, 0xB478,
+	0x638D, 0xD5A5, 0x638E, 0xD571, 0x638F, 0xB1C7, 0x6390, 0xD574,
+	0x6391, 0xD5A4, 0x6392, 0xB1C6, 0x6394, 0xD952, 0x6396, 0xB1B3,
+	0x6397, 0xD56F, 0x6398, 0xB1B8, 0x6399, 0xB1C3, 0x639B, 0xB1BE,
+	0x639C, 0xD578, 0x639D, 0xD56E, 0x639E, 0xD56C, 0x639F, 0xD57E,
+	0x63A0, 0xB1B0, 0x63A1, 0xB1C4, 0x63A2, 0xB1B4, 0x63A3, 0xB477,
+	0x63A4, 0xD57C, 0x63A5, 0xB1B5, 0x63A7, 0xB1B1, 0x63A8, 0xB1C0,
+	0x63A9, 0xB1BB, 0x63AA, 0xB1B9, 0x63AB, 0xD570, 0x63AC, 0xB1C5,
+	0x63AD, 0xD56D, 0x63AE, 0xD57A, 0x63AF, 0xD576, 0x63B0, 0xD954,
+	0x63B1, 0xD953, 0x63BD, 0xD56B, 0x63BE, 0xD964, 0x63C0, 0xB47A,
+	0x63C2, 0xD96A, 0x63C3, 0xD959, 0x63C4, 0xD967, 0x63C5, 0xDD77,
+	0x63C6, 0xB47D, 0x63C7, 0xD96B, 0x63C8, 0xD96E, 0x63C9, 0xB47C,
+	0x63CA, 0xD95C, 0x63CB, 0xD96D, 0x63CC, 0xD96C, 0x63CD, 0xB47E,
+	0x63CE, 0xD955, 0x63CF, 0xB479, 0x63D0, 0xB4A3, 0x63D2, 0xB4A1,
+	0x63D3, 0xD969, 0x63D5, 0xD95F, 0x63D6, 0xB4A5, 0x63D7, 0xD970,
+	0x63D8, 0xD968, 0x63D9, 0xD971, 0x63DA, 0xB4AD, 0x63DB, 0xB4AB,
+	0x63DC, 0xD966, 0x63DD, 0xD965, 0x63DF, 0xD963, 0x63E0, 0xD95D,
+	0x63E1, 0xB4A4, 0x63E3, 0xB4A2, 0x63E4, 0xD1B9, 0x63E5, 0xD956,
+	0x63E7, 0xDDB7, 0x63E8, 0xD957, 0x63E9, 0xB47B, 0x63EA, 0xB4AA,
+	0x63EB, 0xDD79, 0x63ED, 0xB4A6, 0x63EE, 0xB4A7, 0x63EF, 0xD958,
+	0x63F0, 0xD96F, 0x63F1, 0xDD78, 0x63F2, 0xD960, 0x63F3, 0xD95B,
+	0x63F4, 0xB4A9, 0x63F5, 0xD961, 0x63F6, 0xD95E, 0x63F9, 0xB4AE,
+	0x6406, 0xB770, 0x6409, 0xDD7C, 0x640A, 0xDDB1, 0x640B, 0xDDB6,
+	0x640C, 0xDDAA, 0x640D, 0xB76C, 0x640E, 0xDDBB, 0x640F, 0xB769,
+	0x6410, 0xDD7A, 0x6412, 0xDD7B, 0x6413, 0xB762, 0x6414, 0xB76B,
+	0x6415, 0xDDA4, 0x6416, 0xB76E, 0x6417, 0xB76F, 0x6418, 0xDDA5,
+	0x641A, 0xDDB2, 0x641B, 0xDDB8, 0x641C, 0xB76A, 0x641E, 0xB764,
+	0x641F, 0xDDA3, 0x6420, 0xDD7D, 0x6421, 0xDDBA, 0x6422, 0xDDA8,
+	0x6423, 0xDDA9, 0x6424, 0xDD7E, 0x6425, 0xDDB4, 0x6426, 0xDDAB,
+	0x6427, 0xDDB5, 0x6428, 0xDDAD, 0x642A, 0xB765, 0x642B, 0xE1D9,
+	0x642C, 0xB768, 0x642D, 0xB766, 0x642E, 0xDDB9, 0x642F, 0xDDB0,
+	0x6430, 0xDDAC, 0x6433, 0xDDA1, 0x6434, 0xBA53, 0x6435, 0xDDAF,
+	0x6436, 0xB76D, 0x6437, 0xDDA7, 0x6439, 0xDDA6, 0x643D, 0xB767,
+	0x643E, 0xB763, 0x643F, 0xE1EE, 0x6440, 0xDDB3, 0x6441, 0xDDAE,
+	0x6443, 0xDDA2, 0x644B, 0xE1E9, 0x644D, 0xE1DA, 0x644E, 0xE1E5,
+	0x6450, 0xE1EC, 0x6451, 0xBA51, 0x6452, 0xB4AC, 0x6453, 0xE1EA,
+	0x6454, 0xBA4C, 0x6458, 0xBA4B, 0x6459, 0xE1F1, 0x645B, 0xE1DB,
+	0x645C, 0xE1E8, 0x645D, 0xE1DC, 0x645E, 0xE1E7, 0x645F, 0xBA4F,
+	0x6460, 0xE1EB, 0x6461, 0xD962, 0x6465, 0xE1F2, 0x6466, 0xE1E3,
+	0x6467, 0xBA52, 0x6468, 0xE5BA, 0x6469, 0xBCAF, 0x646B, 0xE1F0,
+	0x646C, 0xE1EF, 0x646D, 0xBA54, 0x646E, 0xE5AD, 0x646F, 0xBCB0,
+	0x6470, 0xE5AE, 0x6472, 0xE1DF, 0x6473, 0xE1E0, 0x6474, 0xE1DD,
+	0x6475, 0xE1E2, 0x6476, 0xE1DE, 0x6477, 0xE1F3, 0x6478, 0xBA4E,
+	0x6479, 0xBCB1, 0x647A, 0xBA50, 0x647B, 0xBA55, 0x647D, 0xE1E1,
+	0x647F, 0xE1ED, 0x6482, 0xE1E6, 0x6485, 0xE5B1, 0x6487, 0xBA4A,
+	0x6488, 0xBCB4, 0x6489, 0xE9AA, 0x648A, 0xE5B6, 0x648B, 0xE5B5,
+	0x648C, 0xE5B7, 0x648F, 0xE5B4, 0x6490, 0xBCB5, 0x6492, 0xBCBB,
+	0x6493, 0xBCB8, 0x6495, 0xBCB9, 0x6496, 0xE5AF, 0x6497, 0xE5B2,
+	0x6498, 0xE5BC, 0x6499, 0xBCC1, 0x649A, 0xBCBF, 0x649C, 0xE5B3,
+	0x649D, 0xD95A, 0x649E, 0xBCB2, 0x649F, 0xE5B9, 0x64A0, 0xE5B0,
+	0x64A2, 0xBCC2, 0x64A3, 0xE5B8, 0x64A4, 0xBA4D, 0x64A5, 0xBCB7,
+	0x64A6, 0xE1E4, 0x64A9, 0xBCBA, 0x64AB, 0xBCBE, 0x64AC, 0xBCC0,
+	0x64AD, 0xBCBD, 0x64AE, 0xBCBC, 0x64B0, 0xBCB6, 0x64B1, 0xE5BB,
+	0x64B2, 0xBCB3, 0x64B3, 0xBCC3, 0x64BB, 0xBED8, 0x64BC, 0xBED9,
+	0x64BD, 0xE9A9, 0x64BE, 0xBEE2, 0x64BF, 0xBEDF, 0x64C1, 0xBED6,
+	0x64C2, 0xBEDD, 0x64C3, 0xE9AB, 0x64C4, 0xBEDB, 0x64C5, 0xBED5,
+	0x64C7, 0xBEDC, 0x64C9, 0xE9A8, 0x64CA, 0xC0BB, 0x64CB, 0xBED7,
+	0x64CD, 0xBEDE, 0x64CE, 0xC0BA, 0x64CF, 0xE9A7, 0x64D0, 0xE9A6,
+	0x64D2, 0xBEE0, 0x64D4, 0xBEE1, 0x64D6, 0xE9A5, 0x64D7, 0xE9A4,
+	0x64D8, 0xC0BC, 0x64D9, 0xE9AE, 0x64DA, 0xBEDA, 0x64DB, 0xE9AC,
+	0x64E0, 0xC0BD, 0x64E2, 0xC0C2, 0x64E3, 0xECEA, 0x64E4, 0xECEC,
+	0x64E6, 0xC0BF, 0x64E8, 0xECED, 0x64E9, 0xECE9, 0x64EB, 0xECEB,
+	0x64EC, 0xC0C0, 0x64ED, 0xC0C3, 0x64EF, 0xECE8, 0x64F0, 0xC0BE,
+	0x64F1, 0xC0C1, 0x64F2, 0xC259, 0x64F3, 0xE9AD, 0x64F4, 0xC258,
+	0x64F7, 0xC25E, 0x64F8, 0xEFD4, 0x64FA, 0xC25C, 0x64FB, 0xC25D,
+	0x64FC, 0xEFD7, 0x64FD, 0xEFD3, 0x64FE, 0xC25A, 0x64FF, 0xEFD1,
+	0x6500, 0xC36B, 0x6501, 0xEFD5, 0x6503, 0xEFD6, 0x6504, 0xEFD2,
+	0x6506, 0xC25B, 0x6507, 0xF242, 0x6509, 0xF245, 0x650C, 0xF246,
+	0x650D, 0xF244, 0x650E, 0xF247, 0x650F, 0xC36C, 0x6510, 0xF243,
+	0x6513, 0xF44E, 0x6514, 0xC464, 0x6515, 0xF44D, 0x6516, 0xF44C,
+	0x6517, 0xF44B, 0x6518, 0xC463, 0x6519, 0xC465, 0x651B, 0xF5CD,
+	0x651C, 0xC4E2, 0x651D, 0xC4E1, 0x6520, 0xF6E1, 0x6521, 0xF6E0,
+	0x6522, 0xF6E3, 0x6523, 0xC5CB, 0x6524, 0xC575, 0x6525, 0xF7DD,
+	0x6526, 0xF6E2, 0x6529, 0xF7DC, 0x652A, 0xC5CD, 0x652B, 0xC5CC,
+	0x652C, 0xC5F3, 0x652D, 0xF8A9, 0x652E, 0xF8EF, 0x652F, 0xA4E4,
+	0x6532, 0xD972, 0x6533, 0xE9AF, 0x6536, 0xA6AC, 0x6537, 0xCAF7,
+	0x6538, 0xA7F1, 0x6539, 0xA7EF, 0x653B, 0xA7F0, 0x653D, 0xCCC1,
+	0x653E, 0xA9F1, 0x653F, 0xAC46, 0x6541, 0xCEE7, 0x6543, 0xCEE8,
+	0x6545, 0xAC47, 0x6546, 0xD1CE, 0x6548, 0xAEC4, 0x6549, 0xAEC5,
+	0x654A, 0xD1CD, 0x654F, 0xB1D3, 0x6551, 0xB1CF, 0x6553, 0xD5A7,
+	0x6554, 0xB1D6, 0x6555, 0xB1D5, 0x6556, 0xB1CE, 0x6557, 0xB1D1,
+	0x6558, 0xB1D4, 0x6559, 0xB1D0, 0x655C, 0xD976, 0x655D, 0xB1CD,
+	0x655E, 0xB4AF, 0x6562, 0xB4B1, 0x6563, 0xB4B2, 0x6564, 0xD975,
+	0x6565, 0xD978, 0x6566, 0xB4B0, 0x6567, 0xD973, 0x6568, 0xD977,
+	0x656A, 0xD974, 0x656C, 0xB771, 0x656F, 0xDDBC, 0x6572, 0xBA56,
+	0x6573, 0xE1F4, 0x6574, 0xBEE3, 0x6575, 0xBCC4, 0x6576, 0xE5BD,
+	0x6577, 0xBCC5, 0x6578, 0xBCC6, 0x6579, 0xE5BF, 0x657A, 0xE5BE,
+	0x657B, 0xE5C0, 0x657C, 0xE9B1, 0x657F, 0xE9B0, 0x6580, 0xECEF,
+	0x6581, 0xECEE, 0x6582, 0xC0C4, 0x6583, 0xC0C5, 0x6584, 0xF248,
+	0x6587, 0xA4E5, 0x658C, 0xD979, 0x6590, 0xB4B4, 0x6591, 0xB4B3,
+	0x6592, 0xDDBD, 0x6594, 0xEFD8, 0x6595, 0xC4E3, 0x6596, 0xF7DE,
+	0x6597, 0xA4E6, 0x6599, 0xAEC6, 0x659B, 0xB1D8, 0x659C, 0xB1D7,
+	0x659D, 0xD97A, 0x659E, 0xD97B, 0x659F, 0xB772, 0x65A0, 0xE1F5,
+	0x65A1, 0xBA57, 0x65A2, 0xE9B2, 0x65A4, 0xA4E7, 0x65A5, 0xA5B8,
+	0x65A7, 0xA9F2, 0x65A8, 0xCCC2, 0x65AA, 0xCEE9, 0x65AB, 0xAC48,
+	0x65AC, 0xB1D9, 0x65AE, 0xD97C, 0x65AF, 0xB4B5, 0x65B0, 0xB773,
+	0x65B2, 0xE5C1, 0x65B3, 0xE5C2, 0x65B6, 0xECF0, 0x65B7, 0xC25F,
+	0x65B8, 0xF8F0, 0x65B9, 0xA4E8, 0x65BB, 0xCCC3, 0x65BC, 0xA9F3,
+	0x65BD, 0xAC49, 0x65BF, 0xCEEA, 0x65C1, 0xAEC7, 0x65C2, 0xD1D2,
+	0x65C3, 0xD1D0, 0x65C4, 0xD1D1, 0x65C5, 0xAEC8, 0x65C6, 0xD1CF,
+	0x65CB, 0xB1DB, 0x65CC, 0xB1DC, 0x65CD, 0xD5A8, 0x65CE, 0xB1DD,
+	0x65CF, 0xB1DA, 0x65D0, 0xD97D, 0x65D2, 0xD97E, 0x65D3, 0xDDBE,
+	0x65D6, 0xBA59, 0x65D7, 0xBA58, 0x65DA, 0xECF1, 0x65DB, 0xEFD9,
+	0x65DD, 0xF24A, 0x65DE, 0xF249, 0x65DF, 0xF44F, 0x65E1, 0xC95E,
+	0x65E2, 0xAC4A, 0x65E5, 0xA4E9, 0x65E6, 0xA5B9, 0x65E8, 0xA6AE,
+	0x65E9, 0xA6AD, 0x65EC, 0xA6AF, 0x65ED, 0xA6B0, 0x65EE, 0xC9EE,
+	0x65EF, 0xC9ED, 0x65F0, 0xCAF8, 0x65F1, 0xA7F2, 0x65F2, 0xCAFB,
+	0x65F3, 0xCAFA, 0x65F4, 0xCAF9, 0x65F5, 0xCAFC, 0x65FA, 0xA9F4,
+	0x65FB, 0xCCC9, 0x65FC, 0xCCC5, 0x65FD, 0xCCCE, 0x6600, 0xA9FB,
+	0x6602, 0xA9F9, 0x6603, 0xCCCA, 0x6604, 0xCCC6, 0x6605, 0xCCCD,
+	0x6606, 0xA9F8, 0x6607, 0xAA40, 0x6608, 0xCCC8, 0x6609, 0xCCC4,
+	0x660A, 0xA9FE, 0x660B, 0xCCCB, 0x660C, 0xA9F7, 0x660D, 0xCCCC,
+	0x660E, 0xA9FA, 0x660F, 0xA9FC, 0x6610, 0xCCD0, 0x6611, 0xCCCF,
+	0x6612, 0xCCC7, 0x6613, 0xA9F6, 0x6614, 0xA9F5, 0x6615, 0xA9FD,
+	0x661C, 0xCEEF, 0x661D, 0xCEF5, 0x661F, 0xAC50, 0x6620, 0xAC4D,
+	0x6621, 0xCEEC, 0x6622, 0xCEF1, 0x6624, 0xAC53, 0x6625, 0xAC4B,
+	0x6626, 0xCEF0, 0x6627, 0xAC4E, 0x6628, 0xAC51, 0x662B, 0xCEF3,
+	0x662D, 0xAC4C, 0x662E, 0xCEF8, 0x662F, 0xAC4F, 0x6631, 0xAC52,
+	0x6632, 0xCEED, 0x6633, 0xCEF2, 0x6634, 0xCEF6, 0x6635, 0xCEEE,
+	0x6636, 0xCEEB, 0x6639, 0xCEF7, 0x663A, 0xCEF4, 0x6641, 0xAED0,
+	0x6642, 0xAEC9, 0x6643, 0xAECC, 0x6645, 0xAECF, 0x6647, 0xD1D5,
+	0x6649, 0xAECA, 0x664A, 0xD1D3, 0x664C, 0xAECE, 0x664F, 0xAECB,
+	0x6651, 0xD1D6, 0x6652, 0xAECD, 0x6659, 0xD5AC, 0x665A, 0xB1DF,
+	0x665B, 0xD5AB, 0x665C, 0xD5AD, 0x665D, 0xB1DE, 0x665E, 0xB1E3,
+	0x665F, 0xD1D4, 0x6661, 0xD5AA, 0x6662, 0xD5AE, 0x6664, 0xB1E0,
+	0x6665, 0xD5A9, 0x6666, 0xB1E2, 0x6668, 0xB1E1, 0x666A, 0xD9A7,
+	0x666C, 0xD9A2, 0x666E, 0xB4B6, 0x666F, 0xB4BA, 0x6670, 0xB4B7,
+	0x6671, 0xD9A5, 0x6672, 0xD9A8, 0x6674, 0xB4B8, 0x6676, 0xB4B9,
+	0x6677, 0xB4BE, 0x6678, 0xDDC7, 0x6679, 0xD9A6, 0x667A, 0xB4BC,
+	0x667B, 0xD9A3, 0x667C, 0xD9A1, 0x667E, 0xB4BD, 0x6680, 0xD9A4,
+	0x6684, 0xB779, 0x6686, 0xDDBF, 0x6687, 0xB776, 0x6688, 0xB777,
+	0x6689, 0xB775, 0x668A, 0xDDC4, 0x668B, 0xDDC3, 0x668C, 0xDDC0,
+	0x668D, 0xB77B, 0x6690, 0xDDC2, 0x6691, 0xB4BB, 0x6694, 0xDDC6,
+	0x6695, 0xDDC1, 0x6696, 0xB778, 0x6697, 0xB774, 0x6698, 0xB77A,
+	0x6699, 0xDDC5, 0x669D, 0xBA5C, 0x669F, 0xE1F8, 0x66A0, 0xE1F7,
+	0x66A1, 0xE1F6, 0x66A2, 0xBA5A, 0x66A8, 0xBA5B, 0x66A9, 0xE5C5,
+	0x66AA, 0xE5C8, 0x66AB, 0xBCC8, 0x66AE, 0xBCC7, 0x66AF, 0xE5C9,
+	0x66B0, 0xE5C4, 0x66B1, 0xBCCA, 0x66B2, 0xE5C6, 0x66B4, 0xBCC9,
+	0x66B5, 0xE5C3, 0x66B7, 0xE5C7, 0x66B8, 0xBEE9, 0x66B9, 0xBEE6,
+	0x66BA, 0xE9BB, 0x66BB, 0xE9BA, 0x66BD, 0xE9B9, 0x66BE, 0xE9B4,
+	0x66C0, 0xE9B5, 0x66C4, 0xBEE7, 0x66C6, 0xBEE4, 0x66C7, 0xBEE8,
+	0x66C8, 0xE9B3, 0x66C9, 0xBEE5, 0x66CA, 0xE9B6, 0x66CB, 0xE9B7,
+	0x66CC, 0xE9BC, 0x66CF, 0xE9B8, 0x66D2, 0xECF2, 0x66D6, 0xC0C7,
+	0x66D8, 0xEFDC, 0x66D9, 0xC0C6, 0x66DA, 0xEFDA, 0x66DB, 0xEFDB,
+	0x66DC, 0xC260, 0x66DD, 0xC36E, 0x66DE, 0xF24B, 0x66E0, 0xC36D,
+	0x66E3, 0xF451, 0x66E4, 0xF452, 0x66E6, 0xC466, 0x66E8, 0xF450,
+	0x66E9, 0xC4E4, 0x66EB, 0xF7DF, 0x66EC, 0xC5CE, 0x66ED, 0xF8AA,
+	0x66EE, 0xF8AB, 0x66F0, 0xA4EA, 0x66F2, 0xA6B1, 0x66F3, 0xA6B2,
+	0x66F4, 0xA7F3, 0x66F6, 0xCCD1, 0x66F7, 0xAC54, 0x66F8, 0xAED1,
+	0x66F9, 0xB1E4, 0x66FC, 0xB0D2, 0x66FE, 0xB4BF, 0x66FF, 0xB4C0,
+	0x6700, 0xB3CC, 0x6701, 0xD9A9, 0x6703, 0xB77C, 0x6704, 0xE1FA,
+	0x6705, 0xE1F9, 0x6708, 0xA4EB, 0x6709, 0xA6B3, 0x670A, 0xCCD2,
+	0x670B, 0xAA42, 0x670D, 0xAA41, 0x670F, 0xCEF9, 0x6710, 0xCEFA,
+	0x6712, 0xD1D7, 0x6713, 0xD1D8, 0x6714, 0xAED2, 0x6715, 0xAED3,
+	0x6717, 0xAED4, 0x6718, 0xD5AF, 0x671B, 0xB1E6, 0x671D, 0xB4C2,
+	0x671F, 0xB4C1, 0x6720, 0xDDC8, 0x6721, 0xDF7A, 0x6722, 0xE1FB,
+	0x6723, 0xE9BD, 0x6726, 0xC261, 0x6727, 0xC467, 0x6728, 0xA4EC,
+	0x672A, 0xA5BC, 0x672B, 0xA5BD, 0x672C, 0xA5BB, 0x672D, 0xA5BE,
+	0x672E, 0xA5BA, 0x6731, 0xA6B6, 0x6733, 0xC9F6, 0x6734, 0xA6B5,
+	0x6735, 0xA6B7, 0x6738, 0xC9F1, 0x6739, 0xC9F0, 0x673A, 0xC9F3,
+	0x673B, 0xC9F2, 0x673C, 0xC9F5, 0x673D, 0xA6B4, 0x673E, 0xC9EF,
+	0x673F, 0xC9F4, 0x6745, 0xCAFD, 0x6746, 0xA7FD, 0x6747, 0xCAFE,
+	0x6748, 0xCB43, 0x6749, 0xA7FC, 0x674B, 0xCB47, 0x674C, 0xCB42,
+	0x674D, 0xCB45, 0x674E, 0xA7F5, 0x674F, 0xA7F6, 0x6750, 0xA7F7,
+	0x6751, 0xA7F8, 0x6753, 0xA840, 0x6755, 0xCB41, 0x6756, 0xA7FA,
+	0x6757, 0xA841, 0x6759, 0xCB40, 0x675A, 0xCB46, 0x675C, 0xA7F9,
+	0x675D, 0xCB44, 0x675E, 0xA7FB, 0x675F, 0xA7F4, 0x6760, 0xA7FE,
+	0x676A, 0xAA57, 0x676C, 0xCCD4, 0x676D, 0xAA43, 0x676F, 0xAA4D,
+	0x6770, 0xAA4E, 0x6771, 0xAA46, 0x6772, 0xAA58, 0x6773, 0xAA48,
+	0x6774, 0xCCDC, 0x6775, 0xAA53, 0x6776, 0xCCD7, 0x6777, 0xAA49,
+	0x6778, 0xCCE6, 0x6779, 0xCCE7, 0x677A, 0xCCDF, 0x677B, 0xCCD8,
+	0x677C, 0xAA56, 0x677D, 0xCCE4, 0x677E, 0xAA51, 0x677F, 0xAA4F,
+	0x6781, 0xCCE5, 0x6783, 0xCCE3, 0x6784, 0xCCDB, 0x6785, 0xCCD3,
+	0x6786, 0xCCDA, 0x6787, 0xAA4A, 0x6789, 0xAA50, 0x678B, 0xAA44,
+	0x678C, 0xCCDE, 0x678D, 0xCCDD, 0x678E, 0xCCD5, 0x6790, 0xAA52,
+	0x6791, 0xCCE1, 0x6792, 0xCCD6, 0x6793, 0xAA55, 0x6794, 0xCCE8,
+	0x6795, 0xAA45, 0x6797, 0xAA4C, 0x6798, 0xCCD9, 0x6799, 0xCCE2,
+	0x679A, 0xAA54, 0x679C, 0xAA47, 0x679D, 0xAA4B, 0x679F, 0xCCE0,
+	0x67AE, 0xCF5B, 0x67AF, 0xAC5C, 0x67B0, 0xAC69, 0x67B2, 0xCF56,
+	0x67B3, 0xCF4C, 0x67B4, 0xAC62, 0x67B5, 0xCF4A, 0x67B6, 0xAC5B,
+	0x67B7, 0xCF45, 0x67B8, 0xAC65, 0x67B9, 0xCF52, 0x67BA, 0xCEFE,
+	0x67BB, 0xCF41, 0x67C0, 0xCF44, 0x67C1, 0xCEFB, 0x67C2, 0xCF51,
+	0x67C3, 0xCF61, 0x67C4, 0xAC60, 0x67C5, 0xCF46, 0x67C6, 0xCF58,
+	0x67C8, 0xCEFD, 0x67C9, 0xCF5F, 0x67CA, 0xCF60, 0x67CB, 0xCF63,
+	0x67CC, 0xCF5A, 0x67CD, 0xCF4B, 0x67CE, 0xCF53, 0x67CF, 0xAC66,
+	0x67D0, 0xAC59, 0x67D1, 0xAC61, 0x67D2, 0xAC6D, 0x67D3, 0xAC56,
+	0x67D4, 0xAC58, 0x67D8, 0xCF43, 0x67D9, 0xAC6A, 0x67DA, 0xAC63,
+	0x67DB, 0xCF5D, 0x67DC, 0xCF40, 0x67DD, 0xAC6C, 0x67DE, 0xAC67,
+	0x67DF, 0xCF49, 0x67E2, 0xAC6B, 0x67E3, 0xCF50, 0x67E4, 0xCF48,
+	0x67E5, 0xAC64, 0x67E6, 0xCF5C, 0x67E7, 0xCF54, 0x67E9, 0xAC5E,
+	0x67EA, 0xCF62, 0x67EB, 0xCF47, 0x67EC, 0xAC5A, 0x67ED, 0xCF59,
+	0x67EE, 0xCF4F, 0x67EF, 0xAC5F, 0x67F0, 0xCF55, 0x67F1, 0xAC57,
+	0x67F2, 0xCEFC, 0x67F3, 0xAC68, 0x67F4, 0xAEE3, 0x67F5, 0xAC5D,
+	0x67F6, 0xCF4E, 0x67F7, 0xCF4D, 0x67F8, 0xCF42, 0x67FA, 0xCF5E,
+	0x67FC, 0xCF57, 0x67FF, 0xAC55, 0x6812, 0xD1EC, 0x6813, 0xAEEA,
+	0x6814, 0xD1ED, 0x6816, 0xD1E1, 0x6817, 0xAEDF, 0x6818, 0xAEEB,
+	0x681A, 0xD1DA, 0x681C, 0xD1E3, 0x681D, 0xD1EB, 0x681F, 0xD1D9,
+	0x6820, 0xD1F4, 0x6821, 0xAED5, 0x6825, 0xD1F3, 0x6826, 0xD1EE,
+	0x6828, 0xD1EF, 0x6829, 0xAEDD, 0x682A, 0xAEE8, 0x682B, 0xD1E5,
+	0x682D, 0xD1E6, 0x682E, 0xD1F0, 0x682F, 0xD1E7, 0x6831, 0xD1E2,
+	0x6832, 0xD1DC, 0x6833, 0xD1DD, 0x6834, 0xD1EA, 0x6835, 0xD1E4,
+	0x6838, 0xAED6, 0x6839, 0xAEDA, 0x683A, 0xD1F2, 0x683B, 0xD1DE,
+	0x683C, 0xAEE6, 0x683D, 0xAEE2, 0x6840, 0xAEE5, 0x6841, 0xAEEC,
+	0x6842, 0xAEDB, 0x6843, 0xAEE7, 0x6844, 0xD1E9, 0x6845, 0xAEE9,
+	0x6846, 0xAED8, 0x6848, 0xAED7, 0x6849, 0xD1DB, 0x684B, 0xD1DF,
+	0x684C, 0xAEE0, 0x684D, 0xD1F1, 0x684E, 0xD1E8, 0x684F, 0xD1E0,
+	0x6850, 0xAEE4, 0x6851, 0xAEE1, 0x6853, 0xAED9, 0x6854, 0xAEDC,
+	0x686B, 0xD5C4, 0x686D, 0xD5B4, 0x686E, 0xD5B5, 0x686F, 0xD5B9,
+	0x6871, 0xD5C8, 0x6872, 0xD5C5, 0x6874, 0xD5BE, 0x6875, 0xD5BD,
+	0x6876, 0xB1ED, 0x6877, 0xD5C1, 0x6878, 0xD5D0, 0x6879, 0xD5B0,
+	0x687B, 0xD5D1, 0x687C, 0xD5C3, 0x687D, 0xD5D5, 0x687E, 0xD5C9,
+	0x687F, 0xB1EC, 0x6880, 0xD5C7, 0x6881, 0xB1E7, 0x6882, 0xB1FC,
+	0x6883, 0xB1F2, 0x6885, 0xB1F6, 0x6886, 0xB1F5, 0x6887, 0xD5B1,
+	0x6889, 0xD5CE, 0x688A, 0xD5D4, 0x688B, 0xD5CC, 0x688C, 0xD5D3,
+	0x688F, 0xD5C0, 0x6890, 0xD5B2, 0x6891, 0xD5D2, 0x6892, 0xD5C2,
+	0x6893, 0xB1EA, 0x6894, 0xB1F7, 0x6896, 0xD5CB, 0x6897, 0xB1F0,
+	0x689B, 0xD5CA, 0x689C, 0xD5B3, 0x689D, 0xB1F8, 0x689F, 0xB1FA,
+	0x68A0, 0xD5CD, 0x68A1, 0xB1FB, 0x68A2, 0xB1E9, 0x68A3, 0xD5BA,
+	0x68A4, 0xD5CF, 0x68A7, 0xB1EF, 0x68A8, 0xB1F9, 0x68A9, 0xD5BC,
+	0x68AA, 0xD5C6, 0x68AB, 0xD5B7, 0x68AC, 0xD5BB, 0x68AD, 0xB1F4,
+	0x68AE, 0xD5B6, 0x68AF, 0xB1E8, 0x68B0, 0xB1F1, 0x68B1, 0xB1EE,
+	0x68B2, 0xD5BF, 0x68B3, 0xAEDE, 0x68B4, 0xD9C0, 0x68B5, 0xB1EB,
+	0x68C4, 0xB1F3, 0x68C6, 0xD9C3, 0x68C7, 0xD9D9, 0x68C8, 0xD9CE,
+	0x68C9, 0xB4D6, 0x68CB, 0xB4D1, 0x68CC, 0xD9BD, 0x68CD, 0xB4D2,
+	0x68CE, 0xD9CD, 0x68D0, 0xD9C6, 0x68D1, 0xD9D3, 0x68D2, 0xB4CE,
+	0x68D3, 0xD9AB, 0x68D4, 0xD9D5, 0x68D5, 0xB4C4, 0x68D6, 0xD9B3,
+	0x68D7, 0xB4C7, 0x68D8, 0xB4C6, 0x68DA, 0xB4D7, 0x68DC, 0xD9AD,
+	0x68DD, 0xD9CF, 0x68DE, 0xD9D0, 0x68DF, 0xB4C9, 0x68E0, 0xB4C5,
+	0x68E1, 0xD9BB, 0x68E3, 0xB4D0, 0x68E4, 0xD9B6, 0x68E6, 0xD9D1,
+	0x68E7, 0xB4CC, 0x68E8, 0xD9C9, 0x68E9, 0xD9D6, 0x68EA, 0xD9B0,
+	0x68EB, 0xD9B5, 0x68EC, 0xD9AF, 0x68EE, 0xB4CB, 0x68EF, 0xD9C2,
+	0x68F0, 0xDDDE, 0x68F1, 0xD9B1, 0x68F2, 0xB4CF, 0x68F3, 0xD9BA,
+	0x68F4, 0xD9D2, 0x68F5, 0xB4CA, 0x68F6, 0xD9B7, 0x68F7, 0xD9B4,
+	0x68F8, 0xD9C5, 0x68F9, 0xB4CD, 0x68FA, 0xB4C3, 0x68FB, 0xB4D9,
+	0x68FC, 0xD9C8, 0x68FD, 0xD9C7, 0x6904, 0xD9AC, 0x6905, 0xB4C8,
+	0x6906, 0xD9D4, 0x6907, 0xD9BC, 0x6908, 0xD9BE, 0x690A, 0xD9CB,
+	0x690B, 0xD9CA, 0x690C, 0xD9AA, 0x690D, 0xB4D3, 0x690E, 0xB4D5,
+	0x690F, 0xD9B2, 0x6910, 0xD9B9, 0x6911, 0xD9C1, 0x6912, 0xB4D4,
+	0x6913, 0xD9B8, 0x6914, 0xD9C4, 0x6915, 0xD9D7, 0x6917, 0xD9CC,
+	0x6925, 0xD9D8, 0x692A, 0xD9AE, 0x692F, 0xDDF2, 0x6930, 0xB7A6,
+	0x6932, 0xDDF0, 0x6933, 0xDDDB, 0x6934, 0xDDE0, 0x6935, 0xDDD9,
+	0x6937, 0xDDEC, 0x6938, 0xDDCB, 0x6939, 0xDDD2, 0x693B, 0xDDEA,
+	0x693C, 0xDDF4, 0x693D, 0xDDDC, 0x693F, 0xDDCF, 0x6940, 0xDDE2,
+	0x6941, 0xDDE7, 0x6942, 0xDDD3, 0x6944, 0xDDE4, 0x6945, 0xDDD0,
+	0x6948, 0xDDD7, 0x6949, 0xDDD8, 0x694A, 0xB7A8, 0x694B, 0xDDEB,
+	0x694C, 0xDDE9, 0x694E, 0xDDCC, 0x694F, 0xDDEE, 0x6951, 0xDDEF,
+	0x6952, 0xDDF1, 0x6953, 0xB7AC, 0x6954, 0xB7A4, 0x6956, 0xD5B8,
+	0x6957, 0xDDD4, 0x6958, 0xDDE6, 0x6959, 0xDDD5, 0x695A, 0xB7A1,
+	0x695B, 0xB7B1, 0x695C, 0xDDED, 0x695D, 0xB7AF, 0x695E, 0xB7AB,
+	0x695F, 0xDDCA, 0x6960, 0xB7A3, 0x6962, 0xDDCD, 0x6963, 0xB7B0,
+	0x6965, 0xDDDD, 0x6966, 0xDDC9, 0x6968, 0xB7A9, 0x6969, 0xDDE1,
+	0x696A, 0xDDD1, 0x696B, 0xB7AA, 0x696C, 0xDDDA, 0x696D, 0xB77E,
+	0x696E, 0xB4D8, 0x696F, 0xDDE3, 0x6970, 0xD9BF, 0x6971, 0xDDCE,
+	0x6974, 0xDDE8, 0x6975, 0xB7A5, 0x6976, 0xDDE5, 0x6977, 0xB7A2,
+	0x6978, 0xDDDF, 0x6979, 0xB7AD, 0x697A, 0xDDD6, 0x697B, 0xDDF3,
+	0x6982, 0xB7A7, 0x6983, 0xDEC6, 0x6986, 0xB7AE, 0x698D, 0xE24A,
+	0x698E, 0xE248, 0x6990, 0xE25E, 0x6991, 0xE246, 0x6993, 0xE258,
+	0x6994, 0xB77D, 0x6995, 0xBA5F, 0x6996, 0xE242, 0x6997, 0xE25D,
+	0x6999, 0xE247, 0x699A, 0xE255, 0x699B, 0xBA64, 0x699C, 0xBA5D,
+	0x699E, 0xE25B, 0x69A0, 0xE240, 0x69A1, 0xE25A, 0x69A3, 0xBA6F,
+	0x69A4, 0xE251, 0x69A5, 0xE261, 0x69A6, 0xBA6D, 0x69A7, 0xE249,
+	0x69A8, 0xBA5E, 0x69A9, 0xE24B, 0x69AA, 0xE259, 0x69AB, 0xBA67,
+	0x69AC, 0xE244, 0x69AD, 0xBA6B, 0x69AE, 0xBA61, 0x69AF, 0xE24D,
+	0x69B0, 0xE243, 0x69B1, 0xE1FC, 0x69B3, 0xE257, 0x69B4, 0xBA68,
+	0x69B5, 0xE260, 0x69B6, 0xE1FD, 0x69B7, 0xBA65, 0x69B9, 0xE253,
+	0x69BB, 0xBA66, 0x69BC, 0xE245, 0x69BD, 0xE250, 0x69BE, 0xE24C,
+	0x69BF, 0xE24E, 0x69C1, 0xBA60, 0x69C2, 0xE25F, 0x69C3, 0xBA6E,
+	0x69C4, 0xE24F, 0x69C6, 0xE262, 0x69C9, 0xE1FE, 0x69CA, 0xE254,
+	0x69CB, 0xBA63, 0x69CC, 0xBA6C, 0x69CD, 0xBA6A, 0x69CE, 0xE241,
+	0x69CF, 0xE256, 0x69D0, 0xBA69, 0x69D3, 0xBA62, 0x69D4, 0xE252,
+	0x69D9, 0xE25C, 0x69E2, 0xE5D5, 0x69E4, 0xE5D1, 0x69E5, 0xE5CD,
+	0x69E6, 0xE5E1, 0x69E7, 0xE5DE, 0x69E8, 0xBCCD, 0x69EB, 0xE5E5,
+	0x69EC, 0xE5D4, 0x69ED, 0xBCD8, 0x69EE, 0xE5DB, 0x69F1, 0xE5D0,
+	0x69F2, 0xE5DA, 0x69F3, 0xBCD5, 0x69F4, 0xE5EE, 0x69F6, 0xE5EB,
+	0x69F7, 0xE5DD, 0x69F8, 0xE5CE, 0x69FB, 0xE5E2, 0x69FC, 0xE5E4,
+	0x69FD, 0xBCD1, 0x69FE, 0xE5D8, 0x69FF, 0xE5D3, 0x6A00, 0xE5CA,
+	0x6A01, 0xBCCE, 0x6A02, 0xBCD6, 0x6A04, 0xE5E7, 0x6A05, 0xBCD7,
+	0x6A06, 0xE5CB, 0x6A07, 0xE5ED, 0x6A08, 0xE5E0, 0x6A09, 0xE5E6,
+	0x6A0A, 0xBCD4, 0x6A0D, 0xE5E3, 0x6A0F, 0xE5EA, 0x6A11, 0xBCD9,
+	0x6A13, 0xBCD3, 0x6A14, 0xE5DC, 0x6A15, 0xE5CF, 0x6A16, 0xE5EF,
+	0x6A17, 0xE5CC, 0x6A18, 0xE5E8, 0x6A19, 0xBCD0, 0x6A1B, 0xE5D6,
+	0x6A1D, 0xE5D7, 0x6A1E, 0xBCCF, 0x6A1F, 0xBCCC, 0x6A20, 0xE5D2,
+	0x6A21, 0xBCD2, 0x6A23, 0xBCCB, 0x6A25, 0xE5E9, 0x6A26, 0xE5EC,
+	0x6A27, 0xE5D9, 0x6A28, 0xE9CA, 0x6A32, 0xE9C2, 0x6A34, 0xE9BE,
+	0x6A35, 0xBEF6, 0x6A38, 0xBEEB, 0x6A39, 0xBEF0, 0x6A3A, 0xBEEC,
+	0x6A3B, 0xE9CC, 0x6A3C, 0xE9D7, 0x6A3D, 0xBEEA, 0x6A3E, 0xE9C4,
+	0x6A3F, 0xE9CD, 0x6A40, 0xE5DF, 0x6A41, 0xE9CE, 0x6A44, 0xBEF1,
+	0x6A46, 0xE9DD, 0x6A47, 0xBEF5, 0x6A48, 0xBEF8, 0x6A49, 0xE9C0,
+	0x6A4B, 0xBEF4, 0x6A4D, 0xE9DB, 0x6A4E, 0xE9DC, 0x6A4F, 0xE9D2,
+	0x6A50, 0xE9D1, 0x6A51, 0xE9C9, 0x6A54, 0xE9D3, 0x6A55, 0xE9DA,
+	0x6A56, 0xE9D9, 0x6A58, 0xBEEF, 0x6A59, 0xBEED, 0x6A5A, 0xE9CB,
+	0x6A5B, 0xE9C8, 0x6A5D, 0xE9C5, 0x6A5E, 0xE9D8, 0x6A5F, 0xBEF7,
+	0x6A60, 0xE9D6, 0x6A61, 0xBEF3, 0x6A62, 0xBEF2, 0x6A64, 0xE9D0,
+	0x6A66, 0xE9BF, 0x6A67, 0xE9C1, 0x6A68, 0xE9C3, 0x6A69, 0xE9D5,
+	0x6A6A, 0xE9CF, 0x6A6B, 0xBEEE, 0x6A6D, 0xE9C6, 0x6A6F, 0xE9D4,
+	0x6A76, 0xE9C7, 0x6A7E, 0xC0CF, 0x6A7F, 0xED45, 0x6A80, 0xC0C8,
+	0x6A81, 0xECF5, 0x6A83, 0xED41, 0x6A84, 0xC0CA, 0x6A85, 0xED48,
+	0x6A87, 0xECFC, 0x6A89, 0xECF7, 0x6A8C, 0xED49, 0x6A8D, 0xECF3,
+	0x6A8E, 0xECFE, 0x6A90, 0xC0D1, 0x6A91, 0xED44, 0x6A92, 0xED4A,
+	0x6A93, 0xECFD, 0x6A94, 0xC0C9, 0x6A95, 0xED40, 0x6A96, 0xECF4,
+	0x6A97, 0xC0D0, 0x6A9A, 0xED47, 0x6A9B, 0xECF9, 0x6A9C, 0xC0CC,
+	0x6A9E, 0xECFB, 0x6A9F, 0xECF8, 0x6AA0, 0xC0D2, 0x6AA1, 0xECFA,
+	0x6AA2, 0xC0CB, 0x6AA3, 0xC0CE, 0x6AA4, 0xED43, 0x6AA5, 0xECF6,
+	0x6AA6, 0xED46, 0x6AA8, 0xED42, 0x6AAC, 0xC263, 0x6AAD, 0xEFE7,
+	0x6AAE, 0xC268, 0x6AAF, 0xC269, 0x6AB3, 0xC262, 0x6AB4, 0xEFE6,
+	0x6AB6, 0xEFE3, 0x6AB7, 0xEFE4, 0x6AB8, 0xC266, 0x6AB9, 0xEFDE,
+	0x6ABA, 0xEFE2, 0x6ABB, 0xC265, 0x6ABD, 0xEFDF, 0x6AC2, 0xC267,
+	0x6AC3, 0xC264, 0x6AC5, 0xEFDD, 0x6AC6, 0xEFE1, 0x6AC7, 0xEFE5,
+	0x6ACB, 0xF251, 0x6ACC, 0xF24E, 0x6ACD, 0xF257, 0x6ACF, 0xF256,
+	0x6AD0, 0xF254, 0x6AD1, 0xF24F, 0x6AD3, 0xC372, 0x6AD9, 0xF250,
+	0x6ADA, 0xC371, 0x6ADB, 0xC0CD, 0x6ADC, 0xF253, 0x6ADD, 0xC370,
+	0x6ADE, 0xF258, 0x6ADF, 0xF252, 0x6AE0, 0xF24D, 0x6AE1, 0xEFE0,
+	0x6AE5, 0xC36F, 0x6AE7, 0xF24C, 0x6AE8, 0xF456, 0x6AEA, 0xF455,
+	0x6AEB, 0xF255, 0x6AEC, 0xC468, 0x6AEE, 0xF459, 0x6AEF, 0xF45A,
+	0x6AF0, 0xF454, 0x6AF1, 0xF458, 0x6AF3, 0xF453, 0x6AF8, 0xF5D1,
+	0x6AF9, 0xF457, 0x6AFA, 0xC4E7, 0x6AFB, 0xC4E5, 0x6AFC, 0xF5CF,
+	0x6B00, 0xF5D2, 0x6B02, 0xF5CE, 0x6B03, 0xF5D0, 0x6B04, 0xC4E6,
+	0x6B08, 0xF6E5, 0x6B09, 0xF6E6, 0x6B0A, 0xC576, 0x6B0B, 0xF6E4,
+	0x6B0F, 0xF7E2, 0x6B10, 0xC5CF, 0x6B11, 0xF7E0, 0x6B12, 0xF7E1,
+	0x6B13, 0xF8AC, 0x6B16, 0xC656, 0x6B17, 0xF8F3, 0x6B18, 0xF8F1,
+	0x6B19, 0xF8F2, 0x6B1A, 0xF8F4, 0x6B1E, 0xF9BB, 0x6B20, 0xA4ED,
+	0x6B21, 0xA6B8, 0x6B23, 0xAA59, 0x6B25, 0xCCE9, 0x6B28, 0xCF64,
+	0x6B2C, 0xD1F5, 0x6B2D, 0xD1F7, 0x6B2F, 0xD1F6, 0x6B31, 0xD1F8,
+	0x6B32, 0xB1FD, 0x6B33, 0xD5D7, 0x6B34, 0xD1F9, 0x6B36, 0xD5D6,
+	0x6B37, 0xD5D8, 0x6B38, 0xD5D9, 0x6B39, 0xD9DA, 0x6B3A, 0xB4DB,
+	0x6B3B, 0xD9DB, 0x6B3C, 0xD9DD, 0x6B3D, 0xB4DC, 0x6B3E, 0xB4DA,
+	0x6B3F, 0xD9DC, 0x6B41, 0xDDFA, 0x6B42, 0xDDF8, 0x6B43, 0xDDF7,
+	0x6B45, 0xDDF6, 0x6B46, 0xDDF5, 0x6B47, 0xB7B2, 0x6B48, 0xDDF9,
+	0x6B49, 0xBA70, 0x6B4A, 0xE263, 0x6B4B, 0xE265, 0x6B4C, 0xBA71,
+	0x6B4D, 0xE264, 0x6B4E, 0xBCDB, 0x6B50, 0xBCDA, 0x6B51, 0xE5F0,
+	0x6B54, 0xE9DF, 0x6B55, 0xE9DE, 0x6B56, 0xE9E0, 0x6B59, 0xBEF9,
+	0x6B5B, 0xED4B, 0x6B5C, 0xC0D3, 0x6B5E, 0xEFE8, 0x6B5F, 0xC26A,
+	0x6B60, 0xF259, 0x6B61, 0xC577, 0x6B62, 0xA4EE, 0x6B63, 0xA5BF,
+	0x6B64, 0xA6B9, 0x6B65, 0xA842, 0x6B66, 0xAA5A, 0x6B67, 0xAA5B,
+	0x6B6A, 0xAC6E, 0x6B6D, 0xD1FA, 0x6B72, 0xB7B3, 0x6B76, 0xE6D1,
+	0x6B77, 0xBEFA, 0x6B78, 0xC26B, 0x6B79, 0xA4EF, 0x6B7B, 0xA6BA,
+	0x6B7E, 0xCCEB, 0x6B7F, 0xAA5C, 0x6B80, 0xCCEA, 0x6B82, 0xCF65,
+	0x6B83, 0xAC6F, 0x6B84, 0xCF66, 0x6B86, 0xAC70, 0x6B88, 0xD1FC,
+	0x6B89, 0xAEEE, 0x6B8A, 0xAEED, 0x6B8C, 0xD5DE, 0x6B8D, 0xD5DC,
+	0x6B8E, 0xD5DD, 0x6B8F, 0xD5DB, 0x6B91, 0xD5DA, 0x6B94, 0xD9DE,
+	0x6B95, 0xD9E1, 0x6B96, 0xB4DE, 0x6B97, 0xD9DF, 0x6B98, 0xB4DD,
+	0x6B99, 0xD9E0, 0x6B9B, 0xDDFB, 0x6B9E, 0xE266, 0x6B9F, 0xE267,
+	0x6BA0, 0xE268, 0x6BA2, 0xE5F3, 0x6BA3, 0xE5F2, 0x6BA4, 0xBCDC,
+	0x6BA5, 0xE5F1, 0x6BA6, 0xE5F4, 0x6BA7, 0xE9E1, 0x6BAA, 0xE9E2,
+	0x6BAB, 0xE9E3, 0x6BAD, 0xED4C, 0x6BAE, 0xC0D4, 0x6BAF, 0xC26C,
+	0x6BB0, 0xF25A, 0x6BB2, 0xC4E8, 0x6BB3, 0xC95F, 0x6BB5, 0xAC71,
+	0x6BB6, 0xCF67, 0x6BB7, 0xAEEF, 0x6BBA, 0xB1FE, 0x6BBC, 0xB4DF,
+	0x6BBD, 0xD9E2, 0x6BBF, 0xB7B5, 0x6BC0, 0xB7B4, 0x6BC3, 0xE269,
+	0x6BC4, 0xE26A, 0x6BC5, 0xBCDD, 0x6BC6, 0xBCDE, 0x6BC7, 0xE9E5,
+	0x6BC8, 0xE9E4, 0x6BC9, 0xEFE9, 0x6BCA, 0xF7E3, 0x6BCB, 0xA4F0,
+	0x6BCC, 0xC960, 0x6BCD, 0xA5C0, 0x6BCF, 0xA843, 0x6BD0, 0xCB48,
+	0x6BD2, 0xAC72, 0x6BD3, 0xB7B6, 0x6BD4, 0xA4F1, 0x6BD6, 0xCF68,
+	0x6BD7, 0xAC73, 0x6BD8, 0xCF69, 0x6BDA, 0xC0D5, 0x6BDB, 0xA4F2,
+	0x6BDE, 0xCCEC, 0x6BE0, 0xCF6A, 0x6BE2, 0xD242, 0x6BE3, 0xD241,
+	0x6BE4, 0xD1FE, 0x6BE6, 0xD1FD, 0x6BE7, 0xD243, 0x6BE8, 0xD240,
+	0x6BEB, 0xB240, 0x6BEC, 0xB241, 0x6BEF, 0xB4E0, 0x6BF0, 0xD9E3,
+	0x6BF2, 0xD9E4, 0x6BF3, 0xD9E5, 0x6BF7, 0xDE41, 0x6BF8, 0xDE42,
+	0x6BF9, 0xDE40, 0x6BFB, 0xDDFD, 0x6BFC, 0xDDFE, 0x6BFD, 0xB7B7,
+	0x6BFE, 0xE26B, 0x6BFF, 0xE5F7, 0x6C00, 0xE5F6, 0x6C01, 0xE5F5,
+	0x6C02, 0xE5F8, 0x6C03, 0xE9E7, 0x6C04, 0xE9E6, 0x6C05, 0xBEFB,
+	0x6C06, 0xE9E8, 0x6C08, 0xC0D6, 0x6C09, 0xED4D, 0x6C0B, 0xEFEA,
+	0x6C0C, 0xF25B, 0x6C0D, 0xF6E7, 0x6C0F, 0xA4F3, 0x6C10, 0xA5C2,
+	0x6C11, 0xA5C1, 0x6C13, 0xAA5D, 0x6C14, 0xC961, 0x6C15, 0xC97E,
+	0x6C16, 0xA6BB, 0x6C18, 0xC9F7, 0x6C19, 0xCB49, 0x6C1A, 0xCB4A,
+	0x6C1B, 0xAA5E, 0x6C1D, 0xCCED, 0x6C1F, 0xAC74, 0x6C20, 0xCF6B,
+	0x6C21, 0xCF6C, 0x6C23, 0xAEF0, 0x6C24, 0xAEF4, 0x6C25, 0xD244,
+	0x6C26, 0xAEF3, 0x6C27, 0xAEF1, 0x6C28, 0xAEF2, 0x6C2A, 0xD5DF,
+	0x6C2B, 0xB242, 0x6C2C, 0xB4E3, 0x6C2E, 0xB4E1, 0x6C2F, 0xB4E2,
+	0x6C30, 0xD9E6, 0x6C33, 0xBA72, 0x6C34, 0xA4F4, 0x6C36, 0xC9A1,
+	0x6C38, 0xA5C3, 0x6C3B, 0xC9A4, 0x6C3E, 0xA5C6, 0x6C3F, 0xC9A3,
+	0x6C40, 0xA5C5, 0x6C41, 0xA5C4, 0x6C42, 0xA844, 0x6C43, 0xC9A2,
+	0x6C46, 0xC9F8, 0x6C4A, 0xC9FC, 0x6C4B, 0xC9FE, 0x6C4C, 0xCA40,
+	0x6C4D, 0xA6C5, 0x6C4E, 0xA6C6, 0x6C4F, 0xC9FB, 0x6C50, 0xA6C1,
+	0x6C52, 0xC9F9, 0x6C54, 0xC9FD, 0x6C55, 0xA6C2, 0x6C57, 0xA6BD,
+	0x6C59, 0xA6BE, 0x6C5B, 0xA6C4, 0x6C5C, 0xC9FA, 0x6C5D, 0xA6BC,
+	0x6C5E, 0xA845, 0x6C5F, 0xA6BF, 0x6C60, 0xA6C0, 0x6C61, 0xA6C3,
+	0x6C65, 0xCB5B, 0x6C66, 0xCB59, 0x6C67, 0xCB4C, 0x6C68, 0xA851,
+	0x6C69, 0xCB53, 0x6C6A, 0xA84C, 0x6C6B, 0xCB4D, 0x6C6D, 0xCB55,
+	0x6C6F, 0xCB52, 0x6C70, 0xA84F, 0x6C71, 0xCB51, 0x6C72, 0xA856,
+	0x6C73, 0xCB5A, 0x6C74, 0xA858, 0x6C76, 0xA85A, 0x6C78, 0xCB4B,
+	0x6C7A, 0xA84D, 0x6C7B, 0xCB5C, 0x6C7D, 0xA854, 0x6C7E, 0xA857,
+	0x6C80, 0xCD45, 0x6C81, 0xA847, 0x6C82, 0xA85E, 0x6C83, 0xA855,
+	0x6C84, 0xCB4E, 0x6C85, 0xA84A, 0x6C86, 0xA859, 0x6C87, 0xCB56,
+	0x6C88, 0xA848, 0x6C89, 0xA849, 0x6C8A, 0xCD43, 0x6C8B, 0xCB4F,
+	0x6C8C, 0xA850, 0x6C8D, 0xA85B, 0x6C8E, 0xCB5D, 0x6C8F, 0xCB50,
+	0x6C90, 0xA84E, 0x6C92, 0xA853, 0x6C93, 0xCCEE, 0x6C94, 0xA85C,
+	0x6C95, 0xCB57, 0x6C96, 0xA852, 0x6C98, 0xA85D, 0x6C99, 0xA846,
+	0x6C9A, 0xCB54, 0x6C9B, 0xA84B, 0x6C9C, 0xCB58, 0x6C9D, 0xCD44,
+	0x6CAB, 0xAA6A, 0x6CAC, 0xAA7A, 0x6CAD, 0xCCF5, 0x6CAE, 0xAA71,
+	0x6CB0, 0xCD4B, 0x6CB1, 0xAA62, 0x6CB3, 0xAA65, 0x6CB4, 0xCD42,
+	0x6CB6, 0xCCF3, 0x6CB7, 0xCCF7, 0x6CB8, 0xAA6D, 0x6CB9, 0xAA6F,
+	0x6CBA, 0xCCFA, 0x6CBB, 0xAA76, 0x6CBC, 0xAA68, 0x6CBD, 0xAA66,
+	0x6CBE, 0xAA67, 0x6CBF, 0xAA75, 0x6CC0, 0xCD47, 0x6CC1, 0xAA70,
+	0x6CC2, 0xCCF9, 0x6CC3, 0xCCFB, 0x6CC4, 0xAA6E, 0x6CC5, 0xAA73,
+	0x6CC6, 0xCCFC, 0x6CC7, 0xCD4A, 0x6CC9, 0xAC75, 0x6CCA, 0xAA79,
+	0x6CCC, 0xAA63, 0x6CCD, 0xCD49, 0x6CCF, 0xCD4D, 0x6CD0, 0xCCF8,
+	0x6CD1, 0xCD4F, 0x6CD2, 0xCD40, 0x6CD3, 0xAA6C, 0x6CD4, 0xCCF4,
+	0x6CD5, 0xAA6B, 0x6CD6, 0xAA7D, 0x6CD7, 0xAA72, 0x6CD9, 0xCCF2,
+	0x6CDA, 0xCF75, 0x6CDB, 0xAA78, 0x6CDC, 0xAA7C, 0x6CDD, 0xCD41,
+	0x6CDE, 0xCD46, 0x6CE0, 0xAA7E, 0x6CE1, 0xAA77, 0x6CE2, 0xAA69,
+	0x6CE3, 0xAA5F, 0x6CE5, 0xAA64, 0x6CE7, 0xCCF6, 0x6CE8, 0xAA60,
+	0x6CE9, 0xCD4E, 0x6CEB, 0xCCF0, 0x6CEC, 0xCCEF, 0x6CED, 0xCCFD,
+	0x6CEE, 0xCCF1, 0x6CEF, 0xAA7B, 0x6CF0, 0xAEF5, 0x6CF1, 0xAA74,
+	0x6CF2, 0xCCFE, 0x6CF3, 0xAA61, 0x6CF5, 0xACA6, 0x6CF9, 0xCD4C,
+	0x6D00, 0xCF7C, 0x6D01, 0xCFA1, 0x6D03, 0xCFA4, 0x6D04, 0xCF77,
+	0x6D07, 0xCFA7, 0x6D08, 0xCFAA, 0x6D09, 0xCFAC, 0x6D0A, 0xCF74,
+	0x6D0B, 0xAC76, 0x6D0C, 0xAC7B, 0x6D0D, 0xD249, 0x6D0E, 0xACAD,
+	0x6D0F, 0xCFA5, 0x6D10, 0xCFAD, 0x6D11, 0xCF7B, 0x6D12, 0xCF73,
+	0x6D16, 0xD264, 0x6D17, 0xAC7E, 0x6D18, 0xCFA2, 0x6D19, 0xCF78,
+	0x6D1A, 0xCF7A, 0x6D1B, 0xACA5, 0x6D1D, 0xCF7D, 0x6D1E, 0xAC7D,
+	0x6D1F, 0xCF70, 0x6D20, 0xCFA8, 0x6D22, 0xCFAB, 0x6D25, 0xAC7A,
+	0x6D27, 0xACA8, 0x6D28, 0xCF6D, 0x6D29, 0xACAA, 0x6D2A, 0xAC78,
+	0x6D2B, 0xACAE, 0x6D2C, 0xCFA9, 0x6D2D, 0xCF6F, 0x6D2E, 0xACAB,
+	0x6D2F, 0xD25E, 0x6D30, 0xCD48, 0x6D31, 0xAC7C, 0x6D32, 0xAC77,
+	0x6D33, 0xCF76, 0x6D34, 0xCF6E, 0x6D35, 0xACAC, 0x6D36, 0xACA4,
+	0x6D37, 0xCFA3, 0x6D38, 0xACA9, 0x6D39, 0xACA7, 0x6D3A, 0xCF79,
+	0x6D3B, 0xACA1, 0x6D3C, 0xCF71, 0x6D3D, 0xACA2, 0x6D3E, 0xACA3,
+	0x6D3F, 0xCF72, 0x6D40, 0xCFA6, 0x6D41, 0xAC79, 0x6D42, 0xCF7E,
+	0x6D58, 0xD24C, 0x6D59, 0xAEFD, 0x6D5A, 0xAF43, 0x6D5E, 0xD255,
+	0x6D5F, 0xD25B, 0x6D60, 0xD257, 0x6D61, 0xD24A, 0x6D62, 0xD24D,
+	0x6D63, 0xD246, 0x6D64, 0xD247, 0x6D65, 0xAF4A, 0x6D66, 0xAEFA,
+	0x6D67, 0xD256, 0x6D68, 0xD25F, 0x6D69, 0xAF45, 0x6D6A, 0xAEF6,
+	0x6D6C, 0xAF40, 0x6D6D, 0xD24E, 0x6D6E, 0xAF42, 0x6D6F, 0xD24F,
+	0x6D70, 0xD259, 0x6D74, 0xAF44, 0x6D75, 0xD268, 0x6D76, 0xD248,
+	0x6D77, 0xAEFC, 0x6D78, 0xAEFB, 0x6D79, 0xAF48, 0x6D7A, 0xD245,
+	0x6D7B, 0xD266, 0x6D7C, 0xD25A, 0x6D7D, 0xD267, 0x6D7E, 0xD261,
+	0x6D7F, 0xD253, 0x6D80, 0xD262, 0x6D82, 0xD25C, 0x6D83, 0xD265,
+	0x6D84, 0xD263, 0x6D85, 0xAF49, 0x6D86, 0xD254, 0x6D87, 0xAEF9,
+	0x6D88, 0xAEF8, 0x6D89, 0xAF41, 0x6D8A, 0xAF47, 0x6D8B, 0xD260,
+	0x6D8C, 0xAF46, 0x6D8D, 0xD251, 0x6D8E, 0xB243, 0x6D90, 0xD269,
+	0x6D91, 0xD250, 0x6D92, 0xD24B, 0x6D93, 0xAEFE, 0x6D94, 0xAF4B,
+	0x6D95, 0xAEF7, 0x6D97, 0xD258, 0x6D98, 0xD25D, 0x6DAA, 0xB265,
+	0x6DAB, 0xD5E1, 0x6DAC, 0xD5E5, 0x6DAE, 0xB252, 0x6DAF, 0xB250,
+	0x6DB2, 0xB247, 0x6DB3, 0xD5E3, 0x6DB4, 0xD5E2, 0x6DB5, 0xB25B,
+	0x6DB7, 0xD5E8, 0x6DB8, 0xB255, 0x6DBA, 0xD5FA, 0x6DBB, 0xD647,
+	0x6DBC, 0xB244, 0x6DBD, 0xD5F7, 0x6DBE, 0xD5F0, 0x6DBF, 0xB267,
+	0x6DC0, 0xD5E0, 0x6DC2, 0xD5FC, 0x6DC4, 0xB264, 0x6DC5, 0xB258,
+	0x6DC6, 0xB263, 0x6DC7, 0xB24E, 0x6DC8, 0xD5EC, 0x6DC9, 0xD5FE,
+	0x6DCA, 0xD5F6, 0x6DCB, 0xB24F, 0x6DCC, 0xB249, 0x6DCD, 0xD645,
+	0x6DCF, 0xD5FD, 0x6DD0, 0xD640, 0x6DD1, 0xB251, 0x6DD2, 0xB259,
+	0x6DD3, 0xD642, 0x6DD4, 0xD5EA, 0x6DD5, 0xD5FB, 0x6DD6, 0xD5EF,
+	0x6DD7, 0xD644, 0x6DD8, 0xB25E, 0x6DD9, 0xB246, 0x6DDA, 0xB25C,
+	0x6DDB, 0xD5F4, 0x6DDC, 0xD5F2, 0x6DDD, 0xD5F3, 0x6DDE, 0xB253,
+	0x6DDF, 0xD5EE, 0x6DE0, 0xD5ED, 0x6DE1, 0xB248, 0x6DE2, 0xD5E7,
+	0x6DE3, 0xD646, 0x6DE4, 0xB24A, 0x6DE5, 0xD5F1, 0x6DE6, 0xB268,
+	0x6DE8, 0xB262, 0x6DE9, 0xD5E6, 0x6DEA, 0xB25F, 0x6DEB, 0xB25D,
+	0x6DEC, 0xB266, 0x6DED, 0xD5F8, 0x6DEE, 0xB261, 0x6DEF, 0xD252,
+	0x6DF0, 0xD5F9, 0x6DF1, 0xB260, 0x6DF2, 0xD641, 0x6DF3, 0xB245,
+	0x6DF4, 0xD5F5, 0x6DF5, 0xB257, 0x6DF6, 0xD5E9, 0x6DF7, 0xB256,
+	0x6DF9, 0xB254, 0x6DFA, 0xB24C, 0x6DFB, 0xB24B, 0x6DFC, 0xD9E7,
+	0x6DFD, 0xD643, 0x6E00, 0xD5EB, 0x6E03, 0xD9FC, 0x6E05, 0xB24D,
+	0x6E19, 0xB541, 0x6E1A, 0xB25A, 0x6E1B, 0xB4EE, 0x6E1C, 0xD9F6,
+	0x6E1D, 0xB4FC, 0x6E1F, 0xD9EA, 0x6E20, 0xB4EB, 0x6E21, 0xB4E7,
+	0x6E22, 0xDA49, 0x6E23, 0xB4ED, 0x6E24, 0xB4F1, 0x6E25, 0xB4EC,
+	0x6E26, 0xB4F5, 0x6E27, 0xDA4D, 0x6E28, 0xDA44, 0x6E2B, 0xD9F1,
+	0x6E2C, 0xB4FA, 0x6E2D, 0xB4F4, 0x6E2E, 0xD9FD, 0x6E2F, 0xB4E4,
+	0x6E30, 0xDA4A, 0x6E31, 0xDA43, 0x6E32, 0xB4E8, 0x6E33, 0xD9F7,
+	0x6E34, 0xB4F7, 0x6E35, 0xDA55, 0x6E36, 0xDA56, 0x6E38, 0xB4E5,
+	0x6E39, 0xDA48, 0x6E3A, 0xB4F9, 0x6E3B, 0xD9FB, 0x6E3C, 0xD9ED,
+	0x6E3D, 0xD9EE, 0x6E3E, 0xB4FD, 0x6E3F, 0xD9F2, 0x6E40, 0xD9F9,
+	0x6E41, 0xD9F3, 0x6E43, 0xB4FB, 0x6E44, 0xB544, 0x6E45, 0xD9EF,
+	0x6E46, 0xD9E8, 0x6E47, 0xD9E9, 0x6E49, 0xD9EB, 0x6E4A, 0xB4EA,
+	0x6E4B, 0xD9F8, 0x6E4D, 0xB4F8, 0x6E4E, 0xB542, 0x6E51, 0xD9FA,
+	0x6E52, 0xDA53, 0x6E53, 0xDA4B, 0x6E54, 0xB4E6, 0x6E55, 0xDA51,
+	0x6E56, 0xB4F2, 0x6E58, 0xB4F0, 0x6E5A, 0xDA57, 0x6E5B, 0xB4EF,
+	0x6E5C, 0xDA41, 0x6E5D, 0xD9F4, 0x6E5E, 0xD9FE, 0x6E5F, 0xB547,
+	0x6E60, 0xDA45, 0x6E61, 0xDA42, 0x6E62, 0xD9F0, 0x6E63, 0xB543,
+	0x6E64, 0xDA4F, 0x6E65, 0xDA4C, 0x6E66, 0xDA54, 0x6E67, 0xB4E9,
+	0x6E68, 0xDA40, 0x6E69, 0xB546, 0x6E6B, 0xDA47, 0x6E6E, 0xB4F3,
+	0x6E6F, 0xB4F6, 0x6E71, 0xDA46, 0x6E72, 0xB545, 0x6E73, 0xD9F5,
+	0x6E74, 0xD5E4, 0x6E77, 0xDA50, 0x6E78, 0xDA4E, 0x6E79, 0xDA52,
+	0x6E88, 0xD9EC, 0x6E89, 0xB540, 0x6E8D, 0xDE61, 0x6E8E, 0xDE60,
+	0x6E8F, 0xDE46, 0x6E90, 0xB7BD, 0x6E92, 0xDE5F, 0x6E93, 0xDE49,
+	0x6E94, 0xDE4A, 0x6E96, 0xB7C7, 0x6E97, 0xDE68, 0x6E98, 0xB7C2,
+	0x6E99, 0xDE5E, 0x6E9B, 0xDE43, 0x6E9C, 0xB7C8, 0x6E9D, 0xB7BE,
+	0x6E9E, 0xDE52, 0x6E9F, 0xDE48, 0x6EA0, 0xDE4B, 0x6EA1, 0xDE63,
+	0x6EA2, 0xB7B8, 0x6EA3, 0xDE6A, 0x6EA4, 0xDE62, 0x6EA5, 0xB7C1,
+	0x6EA6, 0xDE57, 0x6EA7, 0xB7CC, 0x6EAA, 0xB7CB, 0x6EAB, 0xB7C5,
+	0x6EAE, 0xDE69, 0x6EAF, 0xB7B9, 0x6EB0, 0xDE55, 0x6EB1, 0xDE4C,
+	0x6EB2, 0xDE59, 0x6EB3, 0xDE65, 0x6EB4, 0xB7CD, 0x6EB6, 0xB7BB,
+	0x6EB7, 0xDE54, 0x6EB9, 0xDE4D, 0x6EBA, 0xB7C4, 0x6EBC, 0xB7C3,
+	0x6EBD, 0xDE50, 0x6EBE, 0xDE5A, 0x6EBF, 0xDE64, 0x6EC0, 0xDE47,
+	0x6EC1, 0xDE51, 0x6EC2, 0xB7BC, 0x6EC3, 0xDE5B, 0x6EC4, 0xB7C9,
+	0x6EC5, 0xB7C0, 0x6EC6, 0xDE4E, 0x6EC7, 0xB7BF, 0x6EC8, 0xDE45,
+	0x6EC9, 0xDE53, 0x6ECA, 0xDE67, 0x6ECB, 0xB4FE, 0x6ECC, 0xBAB0,
+	0x6ECD, 0xDE56, 0x6ECE, 0xE26C, 0x6ECF, 0xDE58, 0x6ED0, 0xDE66,
+	0x6ED1, 0xB7C6, 0x6ED2, 0xDE4F, 0x6ED3, 0xB7BA, 0x6ED4, 0xB7CA,
+	0x6ED5, 0xBCF0, 0x6ED6, 0xDE44, 0x6ED8, 0xDE5D, 0x6EDC, 0xDE5C,
+	0x6EEB, 0xE2AA, 0x6EEC, 0xBAAD, 0x6EED, 0xE27D, 0x6EEE, 0xE2A4,
+	0x6EEF, 0xBAA2, 0x6EF1, 0xE26E, 0x6EF2, 0xBAAF, 0x6EF4, 0xBA77,
+	0x6EF5, 0xE26D, 0x6EF6, 0xE2B0, 0x6EF7, 0xBAB1, 0x6EF8, 0xE271,
+	0x6EF9, 0xE2A3, 0x6EFB, 0xE273, 0x6EFC, 0xE2B3, 0x6EFD, 0xE2AF,
+	0x6EFE, 0xBA75, 0x6EFF, 0xBAA1, 0x6F00, 0xE653, 0x6F01, 0xBAAE,
+	0x6F02, 0xBA7D, 0x6F03, 0xE26F, 0x6F05, 0xE2AE, 0x6F06, 0xBAA3,
+	0x6F07, 0xE2AB, 0x6F08, 0xE2B8, 0x6F09, 0xE275, 0x6F0A, 0xE27E,
+	0x6F0D, 0xE2B6, 0x6F0E, 0xE2AC, 0x6F0F, 0xBA7C, 0x6F12, 0xE27C,
+	0x6F13, 0xBA76, 0x6F14, 0xBA74, 0x6F15, 0xBAA8, 0x6F18, 0xE27A,
+	0x6F19, 0xE277, 0x6F1A, 0xE278, 0x6F1C, 0xE2B2, 0x6F1E, 0xE2B7,
+	0x6F1F, 0xE2B5, 0x6F20, 0xBA7A, 0x6F21, 0xE2B9, 0x6F22, 0xBA7E,
+	0x6F23, 0xBAA7, 0x6F25, 0xE270, 0x6F26, 0xE5FA, 0x6F27, 0xE279,
+	0x6F29, 0xBA78, 0x6F2A, 0xBAAC, 0x6F2B, 0xBAA9, 0x6F2C, 0xBA7B,
+	0x6F2D, 0xE2A5, 0x6F2E, 0xE274, 0x6F2F, 0xBAAA, 0x6F30, 0xE2A7,
+	0x6F31, 0xBAA4, 0x6F32, 0xBAA6, 0x6F33, 0xBA73, 0x6F35, 0xE2A9,
+	0x6F36, 0xE2A1, 0x6F37, 0xE272, 0x6F38, 0xBAA5, 0x6F39, 0xE2B1,
+	0x6F3A, 0xE2B4, 0x6F3B, 0xE27B, 0x6F3C, 0xE2A8, 0x6F3E, 0xBA79,
+	0x6F3F, 0xBCDF, 0x6F40, 0xE2A6, 0x6F41, 0xE5F9, 0x6F43, 0xE2AD,
+	0x6F4E, 0xE276, 0x6F4F, 0xE644, 0x6F50, 0xE64E, 0x6F51, 0xBCE2,
+	0x6F52, 0xE64D, 0x6F53, 0xE659, 0x6F54, 0xBCE4, 0x6F55, 0xE64B,
+	0x6F57, 0xE64F, 0x6F58, 0xBCEF, 0x6F5A, 0xE646, 0x6F5B, 0xBCE7,
+	0x6F5D, 0xE652, 0x6F5E, 0xE9F0, 0x6F5F, 0xBCF3, 0x6F60, 0xBCF2,
+	0x6F61, 0xE654, 0x6F62, 0xE643, 0x6F63, 0xE65E, 0x6F64, 0xBCED,
+	0x6F66, 0xBCE3, 0x6F67, 0xE657, 0x6F69, 0xE65B, 0x6F6A, 0xE660,
+	0x6F6B, 0xE655, 0x6F6C, 0xE649, 0x6F6D, 0xBCE6, 0x6F6E, 0xBCE9,
+	0x6F6F, 0xBCF1, 0x6F70, 0xBCEC, 0x6F72, 0xE64C, 0x6F73, 0xE2A2,
+	0x6F76, 0xE648, 0x6F77, 0xE65F, 0x6F78, 0xBCE8, 0x6F7A, 0xBCEB,
+	0x6F7B, 0xE661, 0x6F7C, 0xBCE0, 0x6F7D, 0xE656, 0x6F7E, 0xE5FB,
+	0x6F7F, 0xE65C, 0x6F80, 0xC0DF, 0x6F82, 0xE64A, 0x6F84, 0xBCE1,
+	0x6F85, 0xE645, 0x6F86, 0xBCE5, 0x6F87, 0xE5FC, 0x6F88, 0xBAAB,
+	0x6F89, 0xE641, 0x6F8B, 0xE65A, 0x6F8C, 0xE642, 0x6F8D, 0xE640,
+	0x6F8E, 0xBCEA, 0x6F90, 0xE658, 0x6F92, 0xE5FE, 0x6F93, 0xE651,
+	0x6F94, 0xE650, 0x6F95, 0xE65D, 0x6F96, 0xE647, 0x6F97, 0xBCEE,
+	0x6F9E, 0xE9F3, 0x6FA0, 0xBF49, 0x6FA1, 0xBEFE, 0x6FA2, 0xEA40,
+	0x6FA3, 0xE9EB, 0x6FA4, 0xBF41, 0x6FA5, 0xE9F7, 0x6FA6, 0xBF48,
+	0x6FA7, 0xBF43, 0x6FA8, 0xE9F5, 0x6FA9, 0xED4F, 0x6FAA, 0xE9FB,
+	0x6FAB, 0xEA42, 0x6FAC, 0xE9FA, 0x6FAD, 0xE9E9, 0x6FAE, 0xE9F8,
+	0x6FAF, 0xEA44, 0x6FB0, 0xEA46, 0x6FB1, 0xBEFD, 0x6FB2, 0xEA45,
+	0x6FB3, 0xBF44, 0x6FB4, 0xBF4A, 0x6FB6, 0xBF47, 0x6FB8, 0xE9FE,
+	0x6FB9, 0xBF46, 0x6FBA, 0xE9F9, 0x6FBC, 0xE9ED, 0x6FBD, 0xE9F2,
+	0x6FBF, 0xE9FD, 0x6FC0, 0xBF45, 0x6FC1, 0xBF42, 0x6FC2, 0xBEFC,
+	0x6FC3, 0xBF40, 0x6FC4, 0xE9F1, 0x6FC6, 0xE5FD, 0x6FC7, 0xE9EC,
+	0x6FC8, 0xE9EF, 0x6FC9, 0xEA41, 0x6FCA, 0xE9F4, 0x6FCB, 0xE9EA,
+	0x6FCC, 0xED4E, 0x6FCD, 0xEA43, 0x6FCE, 0xE9EE, 0x6FCF, 0xE9FC,
+	0x6FD4, 0xED51, 0x6FD5, 0xC0E3, 0x6FD8, 0xC0D7, 0x6FDB, 0xC0DB,
+	0x6FDC, 0xED53, 0x6FDD, 0xED59, 0x6FDE, 0xED57, 0x6FDF, 0xC0D9,
+	0x6FE0, 0xC0DA, 0x6FE1, 0xC0E1, 0x6FE2, 0xED5A, 0x6FE3, 0xED52,
+	0x6FE4, 0xC0DC, 0x6FE6, 0xED56, 0x6FE7, 0xED55, 0x6FE8, 0xED5B,
+	0x6FE9, 0xC0E2, 0x6FEB, 0xC0DD, 0x6FEC, 0xC0E0, 0x6FED, 0xED54,
+	0x6FEE, 0xC0E4, 0x6FEF, 0xC0DE, 0x6FF0, 0xC0E5, 0x6FF1, 0xC0D8,
+	0x6FF2, 0xED58, 0x6FF4, 0xED50, 0x6FF7, 0xEFF7, 0x6FFA, 0xC271,
+	0x6FFB, 0xEFF4, 0x6FFC, 0xEFF6, 0x6FFE, 0xC26F, 0x6FFF, 0xEFF2,
+	0x7000, 0xEFF3, 0x7001, 0xEFEE, 0x7004, 0xE9F6, 0x7005, 0xEFEF,
+	0x7006, 0xC270, 0x7007, 0xEFEB, 0x7009, 0xC26D, 0x700A, 0xEFF8,
+	0x700B, 0xC26E, 0x700C, 0xEFEC, 0x700D, 0xEFED, 0x700E, 0xEFF1,
+	0x700F, 0xC273, 0x7011, 0xC272, 0x7014, 0xEFF0, 0x7015, 0xC378,
+	0x7016, 0xF25F, 0x7017, 0xF265, 0x7018, 0xC379, 0x7019, 0xF25C,
+	0x701A, 0xC376, 0x701B, 0xC373, 0x701C, 0xF267, 0x701D, 0xC377,
+	0x701F, 0xC374, 0x7020, 0xF25E, 0x7021, 0xF261, 0x7022, 0xF262,
+	0x7023, 0xF263, 0x7024, 0xF266, 0x7026, 0xEFF5, 0x7027, 0xF25D,
+	0x7028, 0xC375, 0x7029, 0xF264, 0x702A, 0xF268, 0x702B, 0xF260,
+	0x702F, 0xF45D, 0x7030, 0xC46A, 0x7031, 0xF460, 0x7032, 0xC46B,
+	0x7033, 0xF468, 0x7034, 0xF45F, 0x7035, 0xF45C, 0x7037, 0xF45E,
+	0x7038, 0xF462, 0x7039, 0xF465, 0x703A, 0xF464, 0x703B, 0xF467,
+	0x703C, 0xF45B, 0x703E, 0xC469, 0x703F, 0xF463, 0x7040, 0xF466,
+	0x7041, 0xF469, 0x7042, 0xF461, 0x7043, 0xF5D3, 0x7044, 0xF5D4,
+	0x7045, 0xF5D8, 0x7046, 0xF5D9, 0x7048, 0xF5D6, 0x7049, 0xF5D7,
+	0x704A, 0xF5D5, 0x704C, 0xC4E9, 0x7051, 0xC578, 0x7052, 0xF6EB,
+	0x7055, 0xF6E8, 0x7056, 0xF6E9, 0x7057, 0xF6EA, 0x7058, 0xC579,
+	0x705A, 0xF7E5, 0x705B, 0xF7E4, 0x705D, 0xF8AF, 0x705E, 0xC5F4,
+	0x705F, 0xF8AD, 0x7060, 0xF8B0, 0x7061, 0xF8AE, 0x7062, 0xF8F5,
+	0x7063, 0xC657, 0x7064, 0xC665, 0x7065, 0xF9A3, 0x7066, 0xF96C,
+	0x7068, 0xF9A2, 0x7069, 0xF9D0, 0x706A, 0xF9D1, 0x706B, 0xA4F5,
+	0x7070, 0xA6C7, 0x7071, 0xCA41, 0x7074, 0xCB5E, 0x7076, 0xA85F,
+	0x7078, 0xA862, 0x707A, 0xCB5F, 0x707C, 0xA860, 0x707D, 0xA861,
+	0x7082, 0xCD58, 0x7083, 0xCD5A, 0x7084, 0xCD55, 0x7085, 0xCD52,
+	0x7086, 0xCD54, 0x708A, 0xAAA4, 0x708E, 0xAAA2, 0x7091, 0xCD56,
+	0x7092, 0xAAA3, 0x7093, 0xCD53, 0x7094, 0xCD50, 0x7095, 0xAAA1,
+	0x7096, 0xCD57, 0x7098, 0xCD51, 0x7099, 0xAAA5, 0x709A, 0xCD59,
+	0x709F, 0xCFAF, 0x70A1, 0xCFB3, 0x70A4, 0xACB7, 0x70A9, 0xCFB6,
+	0x70AB, 0xACAF, 0x70AC, 0xACB2, 0x70AD, 0xACB4, 0x70AE, 0xACB6,
+	0x70AF, 0xACB3, 0x70B0, 0xCFB2, 0x70B1, 0xCFB1, 0x70B3, 0xACB1,
+	0x70B4, 0xCFB4, 0x70B5, 0xCFB5, 0x70B7, 0xCFAE, 0x70B8, 0xACB5,
+	0x70BA, 0xACB0, 0x70BE, 0xCFB0, 0x70C5, 0xD277, 0x70C6, 0xD278,
+	0x70C7, 0xD279, 0x70C8, 0xAF50, 0x70CA, 0xAF4C, 0x70CB, 0xD26E,
+	0x70CD, 0xD276, 0x70CE, 0xD27B, 0x70CF, 0xAF51, 0x70D1, 0xD26C,
+	0x70D2, 0xD272, 0x70D3, 0xD26B, 0x70D4, 0xD275, 0x70D7, 0xD271,
+	0x70D8, 0xAF4D, 0x70D9, 0xAF4F, 0x70DA, 0xD27A, 0x70DC, 0xD26A,
+	0x70DD, 0xD26D, 0x70DE, 0xD273, 0x70E0, 0xD274, 0x70E1, 0xD27C,
+	0x70E2, 0xD270, 0x70E4, 0xAF4E, 0x70EF, 0xB26D, 0x70F0, 0xD64E,
+	0x70F3, 0xD650, 0x70F4, 0xD64C, 0x70F6, 0xD658, 0x70F7, 0xD64A,
+	0x70F8, 0xD657, 0x70F9, 0xB269, 0x70FA, 0xD648, 0x70FB, 0xDA5B,
+	0x70FC, 0xD652, 0x70FD, 0xB26C, 0x70FF, 0xD653, 0x7100, 0xD656,
+	0x7102, 0xD65A, 0x7104, 0xD64F, 0x7106, 0xD654, 0x7109, 0xB26A,
+	0x710A, 0xB26B, 0x710B, 0xD659, 0x710C, 0xD64D, 0x710D, 0xD649,
+	0x710E, 0xD65B, 0x7110, 0xD651, 0x7113, 0xD655, 0x7117, 0xD64B,
+	0x7119, 0xB548, 0x711A, 0xB549, 0x711B, 0xDA65, 0x711C, 0xB54F,
+	0x711E, 0xDA59, 0x711F, 0xDA62, 0x7120, 0xDA58, 0x7121, 0xB54C,
+	0x7122, 0xDA60, 0x7123, 0xDA5E, 0x7125, 0xDA5F, 0x7126, 0xB54A,
+	0x7128, 0xDA63, 0x712E, 0xDA5C, 0x712F, 0xDA5A, 0x7130, 0xB54B,
+	0x7131, 0xDA5D, 0x7132, 0xDA61, 0x7136, 0xB54D, 0x713A, 0xDA64,
+	0x7141, 0xDE70, 0x7142, 0xDE77, 0x7143, 0xDE79, 0x7144, 0xDEA1,
+	0x7146, 0xB7DA, 0x7147, 0xDE6B, 0x7149, 0xB7D2, 0x714B, 0xDE7A,
+	0x714C, 0xB7D7, 0x714D, 0xDEA2, 0x714E, 0xB7CE, 0x7150, 0xDE7D,
+	0x7152, 0xDE6D, 0x7153, 0xDE7E, 0x7154, 0xDE6C, 0x7156, 0xB7DC,
+	0x7158, 0xDE78, 0x7159, 0xB7CF, 0x715A, 0xDEA3, 0x715C, 0xB7D4,
+	0x715D, 0xDE71, 0x715E, 0xB7D9, 0x715F, 0xDE7C, 0x7160, 0xDE6F,
+	0x7161, 0xDE76, 0x7162, 0xDE72, 0x7163, 0xDE6E, 0x7164, 0xB7D1,
+	0x7165, 0xB7D8, 0x7166, 0xB7D6, 0x7167, 0xB7D3, 0x7168, 0xB7DB,
+	0x7169, 0xB7D0, 0x716A, 0xDE75, 0x716C, 0xB7D5, 0x716E, 0xB54E,
+	0x7170, 0xDE7B, 0x7172, 0xDE73, 0x7178, 0xDE74, 0x717B, 0xE2C1,
+	0x717D, 0xBAB4, 0x7180, 0xE2BD, 0x7181, 0xE2C3, 0x7182, 0xE2BF,
+	0x7184, 0xBAB6, 0x7185, 0xE2BE, 0x7186, 0xE2C2, 0x7187, 0xE2BA,
+	0x7189, 0xE2BC, 0x718A, 0xBAB5, 0x718F, 0xE2C0, 0x7190, 0xE2BB,
+	0x7192, 0xBAB7, 0x7194, 0xBAB2, 0x7197, 0xE2C4, 0x7199, 0xBAB3,
+	0x719A, 0xE667, 0x719B, 0xE664, 0x719C, 0xE670, 0x719D, 0xE66A,
+	0x719E, 0xE66C, 0x719F, 0xBCF4, 0x71A0, 0xE666, 0x71A1, 0xE66E,
+	0x71A4, 0xE66D, 0x71A5, 0xE66B, 0x71A7, 0xE671, 0x71A8, 0xBCF7,
+	0x71A9, 0xE668, 0x71AA, 0xE66F, 0x71AC, 0xBCF5, 0x71AF, 0xE663,
+	0x71B0, 0xE665, 0x71B1, 0xBCF6, 0x71B2, 0xE662, 0x71B3, 0xE672,
+	0x71B5, 0xE669, 0x71B8, 0xEA4A, 0x71B9, 0xBF51, 0x71BC, 0xEA55,
+	0x71BD, 0xEA53, 0x71BE, 0xBF4B, 0x71BF, 0xEA49, 0x71C0, 0xEA4C,
+	0x71C1, 0xEA4D, 0x71C2, 0xEA48, 0x71C3, 0xBF55, 0x71C4, 0xBF56,
+	0x71C5, 0xEA47, 0x71C6, 0xEA56, 0x71C7, 0xEA51, 0x71C8, 0xBF4F,
+	0x71C9, 0xBF4C, 0x71CA, 0xEA50, 0x71CB, 0xEA4E, 0x71CE, 0xBF52,
+	0x71CF, 0xEA52, 0x71D0, 0xBF4D, 0x71D2, 0xBF4E, 0x71D4, 0xEA4F,
+	0x71D5, 0xBF50, 0x71D6, 0xEA4B, 0x71D8, 0xEA54, 0x71D9, 0xBF53,
+	0x71DA, 0xEA57, 0x71DB, 0xEA58, 0x71DC, 0xBF54, 0x71DF, 0xC0E7,
+	0x71E0, 0xC0EE, 0x71E1, 0xED5C, 0x71E2, 0xED62, 0x71E4, 0xED60,
+	0x71E5, 0xC0EA, 0x71E6, 0xC0E9, 0x71E7, 0xC0E6, 0x71E8, 0xED5E,
+	0x71EC, 0xC0EC, 0x71ED, 0xC0EB, 0x71EE, 0xC0E8, 0x71F0, 0xED61,
+	0x71F1, 0xED5D, 0x71F2, 0xED5F, 0x71F4, 0xC0ED, 0x71F8, 0xC277,
+	0x71F9, 0xEFFB, 0x71FB, 0xC274, 0x71FC, 0xC275, 0x71FD, 0xEFFD,
+	0x71FE, 0xC276, 0x71FF, 0xEFFA, 0x7201, 0xEFF9, 0x7202, 0xF26C,
+	0x7203, 0xEFFC, 0x7205, 0xF26D, 0x7206, 0xC37A, 0x7207, 0xF26B,
+	0x720A, 0xF26A, 0x720C, 0xF269, 0x720D, 0xC37B, 0x7210, 0xC46C,
+	0x7213, 0xF46A, 0x7214, 0xF46B, 0x7219, 0xF5DC, 0x721A, 0xF5DB,
+	0x721B, 0xC4EA, 0x721D, 0xF5DA, 0x721E, 0xF6EC, 0x721F, 0xF6ED,
+	0x7222, 0xF7E6, 0x7223, 0xF8B1, 0x7226, 0xF8F6, 0x7227, 0xF9BC,
+	0x7228, 0xC679, 0x7229, 0xF9C6, 0x722A, 0xA4F6, 0x722C, 0xAAA6,
+	0x722D, 0xAAA7, 0x7230, 0xACB8, 0x7235, 0xC0EF, 0x7236, 0xA4F7,
+	0x7238, 0xAAA8, 0x7239, 0xAF52, 0x723A, 0xB7DD, 0x723B, 0xA4F8,
+	0x723D, 0xB26E, 0x723E, 0xBAB8, 0x723F, 0xC962, 0x7241, 0xCFB7,
+	0x7242, 0xD27D, 0x7244, 0xE2C5, 0x7246, 0xC0F0, 0x7247, 0xA4F9,
+	0x7248, 0xAAA9, 0x7249, 0xCFB8, 0x724A, 0xCFB9, 0x724B, 0xDA66,
+	0x724C, 0xB550, 0x724F, 0xDEA4, 0x7252, 0xB7DE, 0x7253, 0xE2C6,
+	0x7256, 0xBCF8, 0x7258, 0xC37C, 0x7259, 0xA4FA, 0x725A, 0xDA67,
+	0x725B, 0xA4FB, 0x725D, 0xA6C9, 0x725E, 0xCA42, 0x725F, 0xA6C8,
+	0x7260, 0xA865, 0x7261, 0xA864, 0x7262, 0xA863, 0x7263, 0xCB60,
+	0x7267, 0xAAAA, 0x7269, 0xAAAB, 0x726A, 0xCD5B, 0x726C, 0xCFBA,
+	0x726E, 0xCFBD, 0x726F, 0xACBA, 0x7270, 0xCFBB, 0x7272, 0xACB9,
+	0x7273, 0xCFBC, 0x7274, 0xACBB, 0x7276, 0xD2A2, 0x7277, 0xD2A1,
+	0x7278, 0xD27E, 0x7279, 0xAF53, 0x727B, 0xD65D, 0x727C, 0xD65E,
+	0x727D, 0xB26F, 0x727E, 0xD65C, 0x727F, 0xD65F, 0x7280, 0xB552,
+	0x7281, 0xB270, 0x7284, 0xB551, 0x7285, 0xDA6B, 0x7286, 0xDA6A,
+	0x7288, 0xDA68, 0x7289, 0xDA69, 0x728B, 0xDA6C, 0x728C, 0xDEA6,
+	0x728D, 0xDEA5, 0x728E, 0xDEA9, 0x7290, 0xDEA8, 0x7291, 0xDEA7,
+	0x7292, 0xBAB9, 0x7293, 0xE2C9, 0x7295, 0xE2C8, 0x7296, 0xBABA,
+	0x7297, 0xE2C7, 0x7298, 0xE673, 0x729A, 0xE674, 0x729B, 0xBCF9,
+	0x729D, 0xEA59, 0x729E, 0xEA5A, 0x72A1, 0xF272, 0x72A2, 0xC37D,
+	0x72A3, 0xF271, 0x72A4, 0xF270, 0x72A5, 0xF26E, 0x72A6, 0xF26F,
+	0x72A7, 0xC4EB, 0x72A8, 0xF46C, 0x72A9, 0xF6EE, 0x72AA, 0xF8F7,
+	0x72AC, 0xA4FC, 0x72AE, 0xC9A5, 0x72AF, 0xA5C7, 0x72B0, 0xC9A6,
+	0x72B4, 0xCA43, 0x72B5, 0xCA44, 0x72BA, 0xCB66, 0x72BD, 0xCB62,
+	0x72BF, 0xCB61, 0x72C0, 0xAAAC, 0x72C1, 0xCB65, 0x72C2, 0xA867,
+	0x72C3, 0xCB63, 0x72C4, 0xA866, 0x72C5, 0xCB67, 0x72C6, 0xCB64,
+	0x72C9, 0xCD5F, 0x72CA, 0xCFBE, 0x72CB, 0xCD5D, 0x72CC, 0xCD64,
+	0x72CE, 0xAAAD, 0x72D0, 0xAAB0, 0x72D1, 0xCD65, 0x72D2, 0xCD61,
+	0x72D4, 0xCD62, 0x72D6, 0xCD5C, 0x72D7, 0xAAAF, 0x72D8, 0xCD5E,
+	0x72D9, 0xAAAE, 0x72DA, 0xCD63, 0x72DC, 0xCD60, 0x72DF, 0xCFC2,
+	0x72E0, 0xACBD, 0x72E1, 0xACBE, 0x72E3, 0xCFC5, 0x72E4, 0xCFBF,
+	0x72E6, 0xCFC4, 0x72E8, 0xCFC0, 0x72E9, 0xACBC, 0x72EA, 0xCFC3,
+	0x72EB, 0xCFC1, 0x72F3, 0xD2A8, 0x72F4, 0xD2A5, 0x72F6, 0xD2A7,
+	0x72F7, 0xAF58, 0x72F8, 0xAF57, 0x72F9, 0xAF55, 0x72FA, 0xD2A4,
+	0x72FB, 0xD2A9, 0x72FC, 0xAF54, 0x72FD, 0xAF56, 0x72FE, 0xD2A6,
+	0x72FF, 0xD667, 0x7300, 0xD2A3, 0x7301, 0xD2AA, 0x7307, 0xD662,
+	0x7308, 0xD666, 0x730A, 0xD665, 0x730B, 0xDA6E, 0x730C, 0xDA79,
+	0x730F, 0xD668, 0x7311, 0xD663, 0x7312, 0xDA6D, 0x7313, 0xB274,
+	0x7316, 0xB273, 0x7317, 0xD661, 0x7318, 0xD664, 0x7319, 0xB275,
+	0x731B, 0xB272, 0x731C, 0xB271, 0x731D, 0xD660, 0x731E, 0xD669,
+	0x7322, 0xDA70, 0x7323, 0xDA77, 0x7325, 0xB554, 0x7326, 0xDA76,
+	0x7327, 0xDA73, 0x7329, 0xB556, 0x732D, 0xDA75, 0x7330, 0xDA6F,
+	0x7331, 0xDA71, 0x7332, 0xDA74, 0x7333, 0xDA72, 0x7334, 0xB555,
+	0x7335, 0xDA78, 0x7336, 0xB553, 0x7337, 0xB7DF, 0x733A, 0xDEAD,
+	0x733B, 0xDEAC, 0x733C, 0xDEAA, 0x733E, 0xB7E2, 0x733F, 0xB7E1,
+	0x7340, 0xDEAE, 0x7342, 0xDEAB, 0x7343, 0xE2CA, 0x7344, 0xBABB,
+	0x7345, 0xB7E0, 0x7349, 0xDEB0, 0x734A, 0xDEAF, 0x734C, 0xE2CD,
+	0x734D, 0xE2CB, 0x734E, 0xBCFA, 0x7350, 0xBABC, 0x7351, 0xE2CC,
+	0x7352, 0xE676, 0x7357, 0xBCFB, 0x7358, 0xE675, 0x7359, 0xE67E,
+	0x735A, 0xE67D, 0x735B, 0xE67B, 0x735D, 0xE67A, 0x735E, 0xE677,
+	0x735F, 0xE678, 0x7360, 0xE679, 0x7361, 0xE67C, 0x7362, 0xE6A1,
+	0x7365, 0xEA5F, 0x7366, 0xEA5C, 0x7367, 0xEA5D, 0x7368, 0xBF57,
+	0x7369, 0xEA5B, 0x736A, 0xEA61, 0x736B, 0xEA60, 0x736C, 0xEA5E,
+	0x736E, 0xED64, 0x736F, 0xED65, 0x7370, 0xC0F1, 0x7372, 0xC0F2,
+	0x7373, 0xED63, 0x7375, 0xC279, 0x7376, 0xEFFE, 0x7377, 0xC278,
+	0x7378, 0xC37E, 0x737A, 0xC3A1, 0x737B, 0xC46D, 0x737C, 0xF46E,
+	0x737D, 0xF46D, 0x737E, 0xF5DD, 0x737F, 0xF6EF, 0x7380, 0xC57A,
+	0x7381, 0xF7E8, 0x7382, 0xF7E7, 0x7383, 0xF7E9, 0x7384, 0xA5C8,
+	0x7385, 0xCFC6, 0x7386, 0xAF59, 0x7387, 0xB276, 0x7388, 0xD66A,
+	0x7389, 0xA5C9, 0x738A, 0xC9A7, 0x738B, 0xA4FD, 0x738E, 0xCA45,
+	0x7392, 0xCB6C, 0x7393, 0xCB6A, 0x7394, 0xCB6B, 0x7395, 0xCB68,
+	0x7396, 0xA868, 0x7397, 0xCB69, 0x739D, 0xCD6D, 0x739F, 0xAAB3,
+	0x73A0, 0xCD6B, 0x73A1, 0xCD67, 0x73A2, 0xCD6A, 0x73A4, 0xCD66,
+	0x73A5, 0xAAB5, 0x73A6, 0xCD69, 0x73A8, 0xAAB2, 0x73A9, 0xAAB1,
+	0x73AB, 0xAAB4, 0x73AC, 0xCD6C, 0x73AD, 0xCD68, 0x73B2, 0xACC2,
+	0x73B3, 0xACC5, 0x73B4, 0xCFCE, 0x73B5, 0xCFCD, 0x73B6, 0xCFCC,
+	0x73B7, 0xACBF, 0x73B8, 0xCFD5, 0x73B9, 0xCFCB, 0x73BB, 0xACC1,
+	0x73BC, 0xD2AF, 0x73BE, 0xCFD2, 0x73BF, 0xCFD0, 0x73C0, 0xACC4,
+	0x73C2, 0xCFC8, 0x73C3, 0xCFD3, 0x73C5, 0xCFCA, 0x73C6, 0xCFD4,
+	0x73C7, 0xCFD1, 0x73C8, 0xCFC9, 0x73CA, 0xACC0, 0x73CB, 0xCFD6,
+	0x73CC, 0xCFC7, 0x73CD, 0xACC3, 0x73D2, 0xD2B4, 0x73D3, 0xD2AB,
+	0x73D4, 0xD2B6, 0x73D6, 0xD2AE, 0x73D7, 0xD2B9, 0x73D8, 0xD2BA,
+	0x73D9, 0xD2AC, 0x73DA, 0xD2B8, 0x73DB, 0xD2B5, 0x73DC, 0xD2B3,
+	0x73DD, 0xD2B7, 0x73DE, 0xAF5F, 0x73E0, 0xAF5D, 0x73E3, 0xD2B1,
+	0x73E5, 0xD2AD, 0x73E7, 0xD2B0, 0x73E8, 0xD2BB, 0x73E9, 0xD2B2,
+	0x73EA, 0xAF5E, 0x73EB, 0xCFCF, 0x73ED, 0xAF5A, 0x73EE, 0xAF5C,
+	0x73F4, 0xD678, 0x73F5, 0xD66D, 0x73F6, 0xD66B, 0x73F8, 0xD66C,
+	0x73FA, 0xD673, 0x73FC, 0xD674, 0x73FD, 0xD670, 0x73FE, 0xB27B,
+	0x73FF, 0xD675, 0x7400, 0xD672, 0x7401, 0xD66F, 0x7403, 0xB279,
+	0x7404, 0xD66E, 0x7405, 0xB277, 0x7406, 0xB27A, 0x7407, 0xD671,
+	0x7408, 0xD679, 0x7409, 0xAF5B, 0x740A, 0xB278, 0x740B, 0xD677,
+	0x740C, 0xD676, 0x740D, 0xB27C, 0x7416, 0xDA7E, 0x741A, 0xDAA1,
+	0x741B, 0xB560, 0x741D, 0xDAA7, 0x7420, 0xDAA9, 0x7421, 0xDAA2,
+	0x7422, 0xB55A, 0x7423, 0xDAA6, 0x7424, 0xDAA5, 0x7425, 0xB55B,
+	0x7426, 0xB561, 0x7428, 0xB562, 0x7429, 0xDAA8, 0x742A, 0xB558,
+	0x742B, 0xDA7D, 0x742C, 0xDA7B, 0x742D, 0xDAA3, 0x742E, 0xDA7A,
+	0x742F, 0xB55F, 0x7430, 0xDA7C, 0x7431, 0xDAA4, 0x7432, 0xDAAA,
+	0x7433, 0xB559, 0x7434, 0xB55E, 0x7435, 0xB55C, 0x7436, 0xB55D,
+	0x743A, 0xB557, 0x743F, 0xB7E9, 0x7440, 0xDEB7, 0x7441, 0xB7E8,
+	0x7442, 0xDEBB, 0x7444, 0xDEB1, 0x7446, 0xDEBC, 0x744A, 0xDEB2,
+	0x744B, 0xDEB3, 0x744D, 0xDEBD, 0x744E, 0xDEBA, 0x744F, 0xDEB8,
+	0x7450, 0xDEB9, 0x7451, 0xDEB5, 0x7452, 0xDEB4, 0x7454, 0xDEBE,
+	0x7455, 0xB7E5, 0x7457, 0xDEB6, 0x7459, 0xB7EA, 0x745A, 0xB7E4,
+	0x745B, 0xB7EB, 0x745C, 0xB7EC, 0x745E, 0xB7E7, 0x745F, 0xB7E6,
+	0x7462, 0xE2CE, 0x7463, 0xBABE, 0x7464, 0xBABD, 0x7467, 0xE2D3,
+	0x7469, 0xBCFC, 0x746A, 0xBABF, 0x746D, 0xBAC1, 0x746E, 0xE2D4,
+	0x746F, 0xB7E3, 0x7470, 0xBAC0, 0x7471, 0xE2D0, 0x7472, 0xE2D2,
+	0x7473, 0xE2CF, 0x7475, 0xE2D1, 0x7479, 0xE6AB, 0x747C, 0xE6AA,
+	0x747D, 0xE6A7, 0x747E, 0xBD40, 0x747F, 0xEA62, 0x7480, 0xBD41,
+	0x7481, 0xE6A6, 0x7483, 0xBCFE, 0x7485, 0xE6A8, 0x7486, 0xE6A5,
+	0x7487, 0xE6A2, 0x7488, 0xE6A9, 0x7489, 0xE6A3, 0x748A, 0xE6A4,
+	0x748B, 0xBCFD, 0x7490, 0xED69, 0x7492, 0xEA66, 0x7494, 0xEA65,
+	0x7495, 0xEA67, 0x7497, 0xED66, 0x7498, 0xBF5A, 0x749A, 0xEA63,
+	0x749C, 0xBF58, 0x749E, 0xBF5C, 0x749F, 0xBF5B, 0x74A0, 0xEA64,
+	0x74A1, 0xEA68, 0x74A3, 0xBF59, 0x74A5, 0xED6D, 0x74A6, 0xC0F5,
+	0x74A7, 0xC27A, 0x74A8, 0xC0F6, 0x74A9, 0xC0F3, 0x74AA, 0xED6A,
+	0x74AB, 0xED68, 0x74AD, 0xED6B, 0x74AF, 0xED6E, 0x74B0, 0xC0F4,
+	0x74B1, 0xED6C, 0x74B2, 0xED67, 0x74B5, 0xF042, 0x74B6, 0xF045,
+	0x74B7, 0xF275, 0x74B8, 0xF040, 0x74BA, 0xF46F, 0x74BB, 0xF046,
+	0x74BD, 0xC3A2, 0x74BE, 0xF044, 0x74BF, 0xC27B, 0x74C0, 0xF041,
+	0x74C1, 0xF043, 0x74C2, 0xF047, 0x74C3, 0xF276, 0x74C5, 0xF274,
+	0x74CA, 0xC3A3, 0x74CB, 0xF273, 0x74CF, 0xC46E, 0x74D4, 0xC4ED,
+	0x74D5, 0xF6F1, 0x74D6, 0xC4EC, 0x74D7, 0xF6F3, 0x74D8, 0xF6F0,
+	0x74D9, 0xF6F2, 0x74DA, 0xC5D0, 0x74DB, 0xF8B2, 0x74DC, 0xA5CA,
+	0x74DD, 0xCD6E, 0x74DE, 0xD2BC, 0x74DF, 0xD2BD, 0x74E0, 0xB27D,
+	0x74E1, 0xDEBF, 0x74E2, 0xBF5D, 0x74E3, 0xC3A4, 0x74E4, 0xC57B,
+	0x74E5, 0xF8B3, 0x74E6, 0xA5CB, 0x74E8, 0xCD6F, 0x74E9, 0xA260,
+	0x74EC, 0xCFD7, 0x74EE, 0xCFD8, 0x74F4, 0xD2BE, 0x74F5, 0xD2BF,
+	0x74F6, 0xB27E, 0x74F7, 0xB2A1, 0x74FB, 0xDAAB, 0x74FD, 0xDEC2,
+	0x74FE, 0xDEC1, 0x74FF, 0xDEC0, 0x7500, 0xE2D5, 0x7502, 0xE2D6,
+	0x7503, 0xE2D7, 0x7504, 0xBAC2, 0x7507, 0xE6AD, 0x7508, 0xE6AC,
+	0x750B, 0xEA69, 0x750C, 0xBF5E, 0x750D, 0xBF5F, 0x750F, 0xED72,
+	0x7510, 0xED6F, 0x7511, 0xED70, 0x7512, 0xED71, 0x7513, 0xF049,
+	0x7514, 0xF048, 0x7515, 0xC27C, 0x7516, 0xF277, 0x7517, 0xF5DE,
+	0x7518, 0xA5CC, 0x751A, 0xACC6, 0x751C, 0xB2A2, 0x751D, 0xDEC3,
+	0x751F, 0xA5CD, 0x7521, 0xD2C0, 0x7522, 0xB2A3, 0x7525, 0xB563,
+	0x7526, 0xB564, 0x7528, 0xA5CE, 0x7529, 0xA5CF, 0x752A, 0xCA46,
+	0x752B, 0xA86A, 0x752C, 0xA869, 0x752D, 0xACC7, 0x752E, 0xCFD9,
+	0x752F, 0xDAAC, 0x7530, 0xA5D0, 0x7531, 0xA5D1, 0x7532, 0xA5D2,
+	0x7533, 0xA5D3, 0x7537, 0xA86B, 0x7538, 0xA86C, 0x7539, 0xCB6E,
+	0x753A, 0xCB6D, 0x753D, 0xAAB6, 0x753E, 0xCD72, 0x753F, 0xCD70,
+	0x7540, 0xCD71, 0x7547, 0xCFDA, 0x7548, 0xCFDB, 0x754B, 0xACCB,
+	0x754C, 0xACC9, 0x754E, 0xACCA, 0x754F, 0xACC8, 0x7554, 0xAF60,
+	0x7559, 0xAF64, 0x755A, 0xAF63, 0x755B, 0xD2C1, 0x755C, 0xAF62,
+	0x755D, 0xAF61, 0x755F, 0xD2C2, 0x7562, 0xB2A6, 0x7563, 0xD67B,
+	0x7564, 0xD67A, 0x7565, 0xB2A4, 0x7566, 0xB2A5, 0x756A, 0xB566,
+	0x756B, 0xB565, 0x756C, 0xDAAE, 0x756F, 0xDAAD, 0x7570, 0xB2A7,
+	0x7576, 0xB7ED, 0x7577, 0xDEC5, 0x7578, 0xB7EE, 0x7579, 0xDEC4,
+	0x757D, 0xE2D8, 0x757E, 0xE6AE, 0x757F, 0xBD42, 0x7580, 0xEA6A,
+	0x7584, 0xED73, 0x7586, 0xC3A6, 0x7587, 0xC3A5, 0x758A, 0xC57C,
+	0x758B, 0xA5D4, 0x758C, 0xCD73, 0x758F, 0xB2A8, 0x7590, 0xE2D9,
+	0x7591, 0xBAC3, 0x7594, 0xCB6F, 0x7595, 0xCB70, 0x7598, 0xCD74,
+	0x7599, 0xAAB8, 0x759A, 0xAAB9, 0x759D, 0xAAB7, 0x75A2, 0xACCF,
+	0x75A3, 0xACD0, 0x75A4, 0xACCD, 0x75A5, 0xACCE, 0x75A7, 0xCFDC,
+	0x75AA, 0xCFDD, 0x75AB, 0xACCC, 0x75B0, 0xD2C3, 0x75B2, 0xAF68,
+	0x75B3, 0xAF69, 0x75B5, 0xB2AB, 0x75B6, 0xD2C9, 0x75B8, 0xAF6E,
+	0x75B9, 0xAF6C, 0x75BA, 0xD2CA, 0x75BB, 0xD2C5, 0x75BC, 0xAF6B,
+	0x75BD, 0xAF6A, 0x75BE, 0xAF65, 0x75BF, 0xD2C8, 0x75C0, 0xD2C7,
+	0x75C1, 0xD2C4, 0x75C2, 0xAF6D, 0x75C4, 0xD2C6, 0x75C5, 0xAF66,
+	0x75C7, 0xAF67, 0x75CA, 0xB2AC, 0x75CB, 0xD6A1, 0x75CC, 0xD6A2,
+	0x75CD, 0xB2AD, 0x75CE, 0xD67C, 0x75CF, 0xD67E, 0x75D0, 0xD6A4,
+	0x75D1, 0xD6A3, 0x75D2, 0xD67D, 0x75D4, 0xB2A9, 0x75D5, 0xB2AA,
+	0x75D7, 0xDAB6, 0x75D8, 0xB56B, 0x75D9, 0xB56A, 0x75DA, 0xDAB0,
+	0x75DB, 0xB568, 0x75DD, 0xDAB3, 0x75DE, 0xB56C, 0x75DF, 0xDAB4,
+	0x75E0, 0xB56D, 0x75E1, 0xDAB1, 0x75E2, 0xB567, 0x75E3, 0xB569,
+	0x75E4, 0xDAB5, 0x75E6, 0xDAB2, 0x75E7, 0xDAAF, 0x75ED, 0xDED2,
+	0x75EF, 0xDEC7, 0x75F0, 0xB7F0, 0x75F1, 0xB7F3, 0x75F2, 0xB7F2,
+	0x75F3, 0xB7F7, 0x75F4, 0xB7F6, 0x75F5, 0xDED3, 0x75F6, 0xDED1,
+	0x75F7, 0xDECA, 0x75F8, 0xDECE, 0x75F9, 0xDECD, 0x75FA, 0xB7F4,
+	0x75FB, 0xDED0, 0x75FC, 0xDECC, 0x75FD, 0xDED4, 0x75FE, 0xDECB,
+	0x75FF, 0xB7F5, 0x7600, 0xB7EF, 0x7601, 0xB7F1, 0x7603, 0xDEC9,
+	0x7608, 0xE2DB, 0x7609, 0xBAC7, 0x760A, 0xE2DF, 0x760B, 0xBAC6,
+	0x760C, 0xE2DC, 0x760D, 0xBAC5, 0x760F, 0xDEC8, 0x7610, 0xDECF,
+	0x7611, 0xE2DE, 0x7613, 0xBAC8, 0x7614, 0xE2E0, 0x7615, 0xE2DD,
+	0x7616, 0xE2DA, 0x7619, 0xE6B1, 0x761A, 0xE6B5, 0x761B, 0xE6B7,
+	0x761C, 0xE6B3, 0x761D, 0xE6B2, 0x761E, 0xE6B0, 0x761F, 0xBD45,
+	0x7620, 0xBD43, 0x7621, 0xBD48, 0x7622, 0xBD49, 0x7623, 0xE6B4,
+	0x7624, 0xBD46, 0x7625, 0xE6AF, 0x7626, 0xBD47, 0x7627, 0xBAC4,
+	0x7628, 0xE6B6, 0x7629, 0xBD44, 0x762D, 0xEA6C, 0x762F, 0xEA6B,
+	0x7630, 0xEA73, 0x7631, 0xEA6D, 0x7632, 0xEA72, 0x7633, 0xEA6F,
+	0x7634, 0xBF60, 0x7635, 0xEA71, 0x7638, 0xBF61, 0x763A, 0xBF62,
+	0x763C, 0xEA70, 0x763D, 0xEA6E, 0x7642, 0xC0F8, 0x7643, 0xED74,
+	0x7646, 0xC0F7, 0x7647, 0xED77, 0x7648, 0xED75, 0x7649, 0xED76,
+	0x764C, 0xC0F9, 0x7650, 0xF04D, 0x7652, 0xC2A1, 0x7653, 0xF04E,
+	0x7656, 0xC27D, 0x7657, 0xF04F, 0x7658, 0xC27E, 0x7659, 0xF04C,
+	0x765A, 0xF050, 0x765C, 0xF04A, 0x765F, 0xC3A7, 0x7660, 0xF278,
+	0x7661, 0xC3A8, 0x7662, 0xC46F, 0x7664, 0xF04B, 0x7665, 0xC470,
+	0x7669, 0xC4EE, 0x766A, 0xF5DF, 0x766C, 0xC57E, 0x766D, 0xF6F4,
+	0x766E, 0xC57D, 0x7670, 0xF7EA, 0x7671, 0xC5F5, 0x7672, 0xC5F6,
+	0x7675, 0xF9CC, 0x7678, 0xACD1, 0x7679, 0xCFDE, 0x767B, 0xB56E,
+	0x767C, 0xB56F, 0x767D, 0xA5D5, 0x767E, 0xA6CA, 0x767F, 0xCA47,
+	0x7681, 0xCB71, 0x7682, 0xA86D, 0x7684, 0xAABA, 0x7686, 0xACD2,
+	0x7687, 0xACD3, 0x7688, 0xACD4, 0x7689, 0xD6A6, 0x768A, 0xD2CB,
+	0x768B, 0xAF6F, 0x768E, 0xB2AE, 0x768F, 0xD6A5, 0x7692, 0xDAB8,
+	0x7693, 0xB571, 0x7695, 0xDAB7, 0x7696, 0xB570, 0x7699, 0xDED5,
+	0x769A, 0xBD4A, 0x769B, 0xE6BB, 0x769C, 0xE6B8, 0x769D, 0xE6B9,
+	0x769E, 0xE6BA, 0x76A4, 0xED78, 0x76A6, 0xF051, 0x76AA, 0xF471,
+	0x76AB, 0xF470, 0x76AD, 0xF6F5, 0x76AE, 0xA5D6, 0x76AF, 0xCD75,
+	0x76B0, 0xAF70, 0x76B4, 0xB572, 0x76B5, 0xDED6, 0x76B8, 0xE2E1,
+	0x76BA, 0xBD4B, 0x76BB, 0xEA74, 0x76BD, 0xF052, 0x76BE, 0xF472,
+	0x76BF, 0xA5D7, 0x76C2, 0xAABB, 0x76C3, 0xACD7, 0x76C4, 0xCFDF,
+	0x76C5, 0xACD8, 0x76C6, 0xACD6, 0x76C8, 0xACD5, 0x76C9, 0xD2CC,
+	0x76CA, 0xAF71, 0x76CD, 0xAF72, 0x76CE, 0xAF73, 0x76D2, 0xB2B0,
+	0x76D3, 0xD6A7, 0x76D4, 0xB2AF, 0x76DA, 0xDAB9, 0x76DB, 0xB2B1,
+	0x76DC, 0xB573, 0x76DD, 0xDED7, 0x76DE, 0xB7F8, 0x76DF, 0xB7F9,
+	0x76E1, 0xBAC9, 0x76E3, 0xBACA, 0x76E4, 0xBD4C, 0x76E5, 0xBF64,
+	0x76E6, 0xEA75, 0x76E7, 0xBF63, 0x76E9, 0xED79, 0x76EA, 0xC0FA,
+	0x76EC, 0xF053, 0x76ED, 0xF473, 0x76EE, 0xA5D8, 0x76EF, 0xA86E,
+	0x76F0, 0xCD78, 0x76F1, 0xCD77, 0x76F2, 0xAABC, 0x76F3, 0xCD76,
+	0x76F4, 0xAABD, 0x76F5, 0xCD79, 0x76F7, 0xCFE5, 0x76F8, 0xACDB,
+	0x76F9, 0xACDA, 0x76FA, 0xCFE7, 0x76FB, 0xCFE6, 0x76FC, 0xACDF,
+	0x76FE, 0xACDE, 0x7701, 0xACD9, 0x7703, 0xCFE1, 0x7704, 0xCFE2,
+	0x7705, 0xCFE3, 0x7707, 0xACE0, 0x7708, 0xCFE0, 0x7709, 0xACDC,
+	0x770A, 0xCFE4, 0x770B, 0xACDD, 0x7710, 0xD2CF, 0x7711, 0xD2D3,
+	0x7712, 0xD2D1, 0x7713, 0xD2D0, 0x7715, 0xD2D4, 0x7719, 0xD2D5,
+	0x771A, 0xD2D6, 0x771B, 0xD2CE, 0x771D, 0xD2CD, 0x771F, 0xAF75,
+	0x7720, 0xAF76, 0x7722, 0xD2D7, 0x7723, 0xD2D2, 0x7725, 0xD6B0,
+	0x7727, 0xD2D8, 0x7728, 0xAF77, 0x7729, 0xAF74, 0x772D, 0xD6AA,
+	0x772F, 0xD6A9, 0x7731, 0xD6AB, 0x7732, 0xD6AC, 0x7733, 0xD6AE,
+	0x7734, 0xD6AD, 0x7735, 0xD6B2, 0x7736, 0xB2B5, 0x7737, 0xB2B2,
+	0x7738, 0xB2B6, 0x7739, 0xD6A8, 0x773A, 0xB2B7, 0x773B, 0xD6B1,
+	0x773C, 0xB2B4, 0x773D, 0xD6AF, 0x773E, 0xB2B3, 0x7744, 0xDABC,
+	0x7745, 0xDABE, 0x7746, 0xDABA, 0x7747, 0xDABB, 0x774A, 0xDABF,
+	0x774B, 0xDAC1, 0x774C, 0xDAC2, 0x774D, 0xDABD, 0x774E, 0xDAC0,
+	0x774F, 0xB574, 0x7752, 0xDEDB, 0x7754, 0xDEE0, 0x7755, 0xDED8,
+	0x7756, 0xDEDC, 0x7759, 0xDEE1, 0x775A, 0xDEDD, 0x775B, 0xB7FA,
+	0x775C, 0xB843, 0x775E, 0xB7FD, 0x775F, 0xDED9, 0x7760, 0xDEDA,
+	0x7761, 0xBACE, 0x7762, 0xB846, 0x7763, 0xB7FE, 0x7765, 0xB844,
+	0x7766, 0xB7FC, 0x7767, 0xDEDF, 0x7768, 0xB845, 0x7769, 0xDEDE,
+	0x776A, 0xB841, 0x776B, 0xB7FB, 0x776C, 0xB842, 0x776D, 0xDEE2,
+	0x776E, 0xE2E6, 0x776F, 0xE2E8, 0x7779, 0xB840, 0x777C, 0xE2E3,
+	0x777D, 0xBACC, 0x777E, 0xE2E9, 0x777F, 0xBACD, 0x7780, 0xE2E7,
+	0x7781, 0xE2E2, 0x7782, 0xE2E5, 0x7783, 0xE2EA, 0x7784, 0xBACB,
+	0x7785, 0xE2E4, 0x7787, 0xBD4E, 0x7788, 0xE6BF, 0x7789, 0xE6BE,
+	0x778B, 0xBD51, 0x778C, 0xBD4F, 0x778D, 0xE6BC, 0x778E, 0xBD4D,
+	0x778F, 0xE6BD, 0x7791, 0xBD50, 0x7795, 0xEA7D, 0x7797, 0xEAA1,
+	0x7799, 0xEA7E, 0x779A, 0xEA76, 0x779B, 0xEA7A, 0x779C, 0xEA79,
+	0x779D, 0xEA77, 0x779E, 0xBF66, 0x779F, 0xBF67, 0x77A0, 0xBF65,
+	0x77A1, 0xEA78, 0x77A2, 0xEA7B, 0x77A3, 0xEA7C, 0x77A5, 0xBF68,
+	0x77A7, 0xC140, 0x77A8, 0xEDA3, 0x77AA, 0xC0FC, 0x77AB, 0xED7B,
+	0x77AC, 0xC0FE, 0x77AD, 0xC141, 0x77B0, 0xC0FD, 0x77B1, 0xEDA2,
+	0x77B2, 0xED7C, 0x77B3, 0xC0FB, 0x77B4, 0xEDA1, 0x77B5, 0xED7A,
+	0x77B6, 0xED7E, 0x77B7, 0xED7D, 0x77BA, 0xF055, 0x77BB, 0xC2A4,
+	0x77BC, 0xC2A5, 0x77BD, 0xC2A2, 0x77BF, 0xC2A3, 0x77C2, 0xF054,
+	0x77C4, 0xF27B, 0x77C7, 0xC3A9, 0x77C9, 0xF279, 0x77CA, 0xF27A,
+	0x77CC, 0xF474, 0x77CD, 0xF477, 0x77CE, 0xF475, 0x77CF, 0xF476,
+	0x77D0, 0xF5E0, 0x77D3, 0xC4EF, 0x77D4, 0xF7EB, 0x77D5, 0xF8B4,
+	0x77D7, 0xC5F7, 0x77D8, 0xF8F8, 0x77D9, 0xF8F9, 0x77DA, 0xC666,
+	0x77DB, 0xA5D9, 0x77DC, 0xACE1, 0x77DE, 0xDAC3, 0x77E0, 0xDEE3,
+	0x77E2, 0xA5DA, 0x77E3, 0xA86F, 0x77E5, 0xAABE, 0x77E7, 0xCFE8,
+	0x77E8, 0xCFE9, 0x77E9, 0xAF78, 0x77EC, 0xDAC4, 0x77ED, 0xB575,
+	0x77EE, 0xB847, 0x77EF, 0xC142, 0x77F0, 0xEDA4, 0x77F1, 0xF27C,
+	0x77F2, 0xF478, 0x77F3, 0xA5DB, 0x77F7, 0xCDA1, 0x77F8, 0xCD7A,
+	0x77F9, 0xCD7C, 0x77FA, 0xCD7E, 0x77FB, 0xCD7D, 0x77FC, 0xCD7B,
+	0x77FD, 0xAABF, 0x7802, 0xACE2, 0x7803, 0xCFF2, 0x7805, 0xCFED,
+	0x7806, 0xCFEA, 0x7809, 0xCFF1, 0x780C, 0xACE4, 0x780D, 0xACE5,
+	0x780E, 0xCFF0, 0x780F, 0xCFEF, 0x7810, 0xCFEE, 0x7811, 0xCFEB,
+	0x7812, 0xCFEC, 0x7813, 0xCFF3, 0x7814, 0xACE3, 0x781D, 0xAF7C,
+	0x781F, 0xAFA4, 0x7820, 0xAFA3, 0x7821, 0xD2E1, 0x7822, 0xD2DB,
+	0x7823, 0xD2D9, 0x7825, 0xAFA1, 0x7826, 0xD6B9, 0x7827, 0xAF7A,
+	0x7828, 0xD2DE, 0x7829, 0xD2E2, 0x782A, 0xD2E4, 0x782B, 0xD2E0,
+	0x782C, 0xD2DA, 0x782D, 0xAFA2, 0x782E, 0xD2DF, 0x782F, 0xD2DD,
+	0x7830, 0xAF79, 0x7831, 0xD2E5, 0x7832, 0xAFA5, 0x7833, 0xD2E3,
+	0x7834, 0xAF7D, 0x7835, 0xD2DC, 0x7837, 0xAF7E, 0x7838, 0xAF7B,
+	0x7843, 0xB2B9, 0x7845, 0xD6BA, 0x7848, 0xD6B3, 0x7849, 0xD6B5,
+	0x784A, 0xD6B7, 0x784C, 0xD6B8, 0x784D, 0xD6B6, 0x784E, 0xB2BA,
+	0x7850, 0xD6BB, 0x7852, 0xD6B4, 0x785C, 0xDAC8, 0x785D, 0xB576,
+	0x785E, 0xDAD0, 0x7860, 0xDAC5, 0x7862, 0xDAD1, 0x7864, 0xDAC6,
+	0x7865, 0xDAC7, 0x7868, 0xDACF, 0x7869, 0xDACE, 0x786A, 0xDACB,
+	0x786B, 0xB2B8, 0x786C, 0xB577, 0x786D, 0xDAC9, 0x786E, 0xDACC,
+	0x786F, 0xB578, 0x7870, 0xDACD, 0x7871, 0xDACA, 0x7879, 0xDEEE,
+	0x787B, 0xDEF2, 0x787C, 0xB84E, 0x787E, 0xE2F0, 0x787F, 0xB851,
+	0x7880, 0xDEF0, 0x7881, 0xF9D6, 0x7883, 0xDEED, 0x7884, 0xDEE8,
+	0x7885, 0xDEEA, 0x7886, 0xDEEB, 0x7887, 0xDEE4, 0x7889, 0xB84D,
+	0x788C, 0xB84C, 0x788E, 0xB848, 0x788F, 0xDEE7, 0x7891, 0xB84F,
+	0x7893, 0xB850, 0x7894, 0xDEE6, 0x7895, 0xDEE9, 0x7896, 0xDEF1,
+	0x7897, 0xB84A, 0x7898, 0xB84B, 0x7899, 0xDEEF, 0x789A, 0xDEE5,
+	0x789E, 0xE2F2, 0x789F, 0xBAD0, 0x78A0, 0xE2F4, 0x78A1, 0xDEEC,
+	0x78A2, 0xE2F6, 0x78A3, 0xBAD4, 0x78A4, 0xE2F7, 0x78A5, 0xE2F3,
+	0x78A7, 0xBAD1, 0x78A8, 0xE2EF, 0x78A9, 0xBAD3, 0x78AA, 0xE2EC,
+	0x78AB, 0xE2F1, 0x78AC, 0xE2F5, 0x78AD, 0xE2EE, 0x78B0, 0xB849,
+	0x78B2, 0xE2EB, 0x78B3, 0xBAD2, 0x78B4, 0xE2ED, 0x78BA, 0xBD54,
+	0x78BB, 0xE6C1, 0x78BC, 0xBD58, 0x78BE, 0xBD56, 0x78C1, 0xBACF,
+	0x78C3, 0xE6C8, 0x78C4, 0xE6C9, 0x78C5, 0xBD53, 0x78C8, 0xE6C7,
+	0x78C9, 0xE6CA, 0x78CA, 0xBD55, 0x78CB, 0xBD52, 0x78CC, 0xE6C3,
+	0x78CD, 0xE6C0, 0x78CE, 0xE6C5, 0x78CF, 0xE6C2, 0x78D0, 0xBD59,
+	0x78D1, 0xE6C4, 0x78D4, 0xE6C6, 0x78D5, 0xBD57, 0x78DA, 0xBF6A,
+	0x78DB, 0xEAA8, 0x78DD, 0xEAA2, 0x78DE, 0xEAA6, 0x78DF, 0xEAAC,
+	0x78E0, 0xEAAD, 0x78E1, 0xEAA9, 0x78E2, 0xEAAA, 0x78E3, 0xEAA7,
+	0x78E5, 0xEAA4, 0x78E7, 0xBF6C, 0x78E8, 0xBF69, 0x78E9, 0xEAA3,
+	0x78EA, 0xEAA5, 0x78EC, 0xBF6B, 0x78ED, 0xEAAB, 0x78EF, 0xC146,
+	0x78F2, 0xEDAA, 0x78F3, 0xEDA5, 0x78F4, 0xC145, 0x78F7, 0xC143,
+	0x78F9, 0xEDAC, 0x78FA, 0xC144, 0x78FB, 0xEDA8, 0x78FC, 0xEDA9,
+	0x78FD, 0xEDA6, 0x78FE, 0xEDAD, 0x78FF, 0xF056, 0x7901, 0xC147,
+	0x7902, 0xEDA7, 0x7904, 0xEDAE, 0x7905, 0xEDAB, 0x7909, 0xF05A,
+	0x790C, 0xF057, 0x790E, 0xC2A6, 0x7910, 0xF05B, 0x7911, 0xF05D,
+	0x7912, 0xF05C, 0x7913, 0xF058, 0x7914, 0xF059, 0x7917, 0xF2A3,
+	0x7919, 0xC3AA, 0x791B, 0xF27E, 0x791C, 0xF2A2, 0x791D, 0xF27D,
+	0x791E, 0xF2A4, 0x7921, 0xF2A1, 0x7923, 0xF47A, 0x7924, 0xF47D,
+	0x7925, 0xF479, 0x7926, 0xC471, 0x7927, 0xF47B, 0x7928, 0xF47C,
+	0x7929, 0xF47E, 0x792A, 0xC472, 0x792B, 0xC474, 0x792C, 0xC473,
+	0x792D, 0xF5E1, 0x792F, 0xF5E3, 0x7931, 0xF5E2, 0x7935, 0xF6F6,
+	0x7938, 0xF8B5, 0x7939, 0xF8FA, 0x793A, 0xA5DC, 0x793D, 0xCB72,
+	0x793E, 0xAAC0, 0x793F, 0xCDA3, 0x7940, 0xAAC1, 0x7941, 0xAAC2,
+	0x7942, 0xCDA2, 0x7944, 0xCFF8, 0x7945, 0xCFF7, 0x7946, 0xACE6,
+	0x7947, 0xACE9, 0x7948, 0xACE8, 0x7949, 0xACE7, 0x794A, 0xCFF4,
+	0x794B, 0xCFF6, 0x794C, 0xCFF5, 0x794F, 0xD2E8, 0x7950, 0xAFA7,
+	0x7951, 0xD2EC, 0x7952, 0xD2EB, 0x7953, 0xD2EA, 0x7954, 0xD2E6,
+	0x7955, 0xAFA6, 0x7956, 0xAFAA, 0x7957, 0xAFAD, 0x795A, 0xAFAE,
+	0x795B, 0xD2E7, 0x795C, 0xD2E9, 0x795D, 0xAFAC, 0x795E, 0xAFAB,
+	0x795F, 0xAFA9, 0x7960, 0xAFA8, 0x7961, 0xD6C2, 0x7963, 0xD6C0,
+	0x7964, 0xD6BC, 0x7965, 0xB2BB, 0x7967, 0xD6BD, 0x7968, 0xB2BC,
+	0x7969, 0xD6BE, 0x796A, 0xD6BF, 0x796B, 0xD6C1, 0x796D, 0xB2BD,
+	0x7970, 0xDAD5, 0x7972, 0xDAD4, 0x7973, 0xDAD3, 0x7974, 0xDAD2,
+	0x7979, 0xDEF6, 0x797A, 0xB852, 0x797C, 0xDEF3, 0x797D, 0xDEF5,
+	0x797F, 0xB853, 0x7981, 0xB854, 0x7982, 0xDEF4, 0x7988, 0xE341,
+	0x798A, 0xE2F9, 0x798B, 0xE2FA, 0x798D, 0xBAD7, 0x798E, 0xBAD5,
+	0x798F, 0xBAD6, 0x7990, 0xE343, 0x7992, 0xE342, 0x7993, 0xE2FE,
+	0x7994, 0xE2FD, 0x7995, 0xE2FC, 0x7996, 0xE2FB, 0x7997, 0xE340,
+	0x7998, 0xE2F8, 0x799A, 0xE6CB, 0x799B, 0xE6D0, 0x799C, 0xE6CE,
+	0x79A0, 0xE6CD, 0x79A1, 0xE6CC, 0x79A2, 0xE6CF, 0x79A4, 0xEAAE,
+	0x79A6, 0xBF6D, 0x79A7, 0xC148, 0x79A8, 0xEDB0, 0x79AA, 0xC149,
+	0x79AB, 0xEDAF, 0x79AC, 0xF05F, 0x79AD, 0xF05E, 0x79AE, 0xC2A7,
+	0x79B0, 0xF2A5, 0x79B1, 0xC3AB, 0x79B2, 0xF4A1, 0x79B3, 0xC5A1,
+	0x79B4, 0xF6F7, 0x79B6, 0xF8B7, 0x79B7, 0xF8B6, 0x79B8, 0xC9A8,
+	0x79B9, 0xACEA, 0x79BA, 0xACEB, 0x79BB, 0xD6C3, 0x79BD, 0xB856,
+	0x79BE, 0xA5DD, 0x79BF, 0xA872, 0x79C0, 0xA871, 0x79C1, 0xA870,
+	0x79C5, 0xCDA4, 0x79C8, 0xAAC4, 0x79C9, 0xAAC3, 0x79CB, 0xACEE,
+	0x79CD, 0xCFFA, 0x79CE, 0xCFFD, 0x79CF, 0xCFFB, 0x79D1, 0xACEC,
+	0x79D2, 0xACED, 0x79D5, 0xCFF9, 0x79D6, 0xCFFC, 0x79D8, 0xAFB5,
+	0x79DC, 0xD2F3, 0x79DD, 0xD2F5, 0x79DE, 0xD2F4, 0x79DF, 0xAFB2,
+	0x79E0, 0xD2EF, 0x79E3, 0xAFB0, 0x79E4, 0xAFAF, 0x79E6, 0xAFB3,
+	0x79E7, 0xAFB1, 0x79E9, 0xAFB4, 0x79EA, 0xD2F2, 0x79EB, 0xD2ED,
+	0x79EC, 0xD2EE, 0x79ED, 0xD2F1, 0x79EE, 0xD2F0, 0x79F6, 0xD6C6,
+	0x79F7, 0xD6C7, 0x79F8, 0xD6C5, 0x79FA, 0xD6C4, 0x79FB, 0xB2BE,
+	0x7A00, 0xB57D, 0x7A02, 0xDAD6, 0x7A03, 0xDAD8, 0x7A04, 0xDADA,
+	0x7A05, 0xB57C, 0x7A08, 0xB57A, 0x7A0A, 0xDAD7, 0x7A0B, 0xB57B,
+	0x7A0C, 0xDAD9, 0x7A0D, 0xB579, 0x7A10, 0xDF41, 0x7A11, 0xDEF7,
+	0x7A12, 0xDEFA, 0x7A13, 0xDEFE, 0x7A14, 0xB85A, 0x7A15, 0xDEFC,
+	0x7A17, 0xDEFB, 0x7A18, 0xDEF8, 0x7A19, 0xDEF9, 0x7A1A, 0xB858,
+	0x7A1B, 0xDF40, 0x7A1C, 0xB857, 0x7A1E, 0xB85C, 0x7A1F, 0xB85B,
+	0x7A20, 0xB859, 0x7A22, 0xDEFD, 0x7A26, 0xE349, 0x7A28, 0xE348,
+	0x7A2B, 0xE344, 0x7A2E, 0xBAD8, 0x7A2F, 0xE347, 0x7A30, 0xE346,
+	0x7A31, 0xBAD9, 0x7A37, 0xBD5E, 0x7A39, 0xE6D2, 0x7A3B, 0xBD5F,
+	0x7A3C, 0xBD5B, 0x7A3D, 0xBD5D, 0x7A3F, 0xBD5A, 0x7A40, 0xBD5C,
+	0x7A44, 0xEAAF, 0x7A46, 0xBF70, 0x7A47, 0xEAB1, 0x7A48, 0xEAB0,
+	0x7A4A, 0xE345, 0x7A4B, 0xBF72, 0x7A4C, 0xBF71, 0x7A4D, 0xBF6E,
+	0x7A4E, 0xBF6F, 0x7A54, 0xEDB5, 0x7A56, 0xEDB3, 0x7A57, 0xC14A,
+	0x7A58, 0xEDB4, 0x7A5A, 0xEDB6, 0x7A5B, 0xEDB2, 0x7A5C, 0xEDB1,
+	0x7A5F, 0xF060, 0x7A60, 0xC2AA, 0x7A61, 0xC2A8, 0x7A62, 0xC2A9,
+	0x7A67, 0xF2A6, 0x7A68, 0xF2A7, 0x7A69, 0xC3AD, 0x7A6B, 0xC3AC,
+	0x7A6C, 0xF4A3, 0x7A6D, 0xF4A4, 0x7A6E, 0xF4A2, 0x7A70, 0xF6F8,
+	0x7A71, 0xF6F9, 0x7A74, 0xA5DE, 0x7A75, 0xCA48, 0x7A76, 0xA873,
+	0x7A78, 0xCDA5, 0x7A79, 0xAAC6, 0x7A7A, 0xAAC5, 0x7A7B, 0xCDA6,
+	0x7A7E, 0xD040, 0x7A7F, 0xACEF, 0x7A80, 0xCFFE, 0x7A81, 0xACF0,
+	0x7A84, 0xAFB6, 0x7A85, 0xD2F8, 0x7A86, 0xD2F6, 0x7A87, 0xD2FC,
+	0x7A88, 0xAFB7, 0x7A89, 0xD2F7, 0x7A8A, 0xD2FB, 0x7A8B, 0xD2F9,
+	0x7A8C, 0xD2FA, 0x7A8F, 0xD6C8, 0x7A90, 0xD6CA, 0x7A92, 0xB2BF,
+	0x7A94, 0xD6C9, 0x7A95, 0xB2C0, 0x7A96, 0xB5A2, 0x7A97, 0xB5A1,
+	0x7A98, 0xB57E, 0x7A99, 0xDADB, 0x7A9E, 0xDF44, 0x7A9F, 0xB85D,
+	0x7AA0, 0xB85E, 0x7AA2, 0xDF43, 0x7AA3, 0xDF42, 0x7AA8, 0xE34A,
+	0x7AA9, 0xBADB, 0x7AAA, 0xBADA, 0x7AAB, 0xE34B, 0x7AAC, 0xE34C,
+	0x7AAE, 0xBD61, 0x7AAF, 0xBD60, 0x7AB1, 0xEAB5, 0x7AB2, 0xE6D3,
+	0x7AB3, 0xE6D5, 0x7AB4, 0xE6D4, 0x7AB5, 0xEAB4, 0x7AB6, 0xEAB2,
+	0x7AB7, 0xEAB6, 0x7AB8, 0xEAB3, 0x7ABA, 0xBF73, 0x7ABE, 0xEDB7,
+	0x7ABF, 0xC14B, 0x7AC0, 0xEDB8, 0x7AC1, 0xEDB9, 0x7AC4, 0xC2AB,
+	0x7AC5, 0xC2AC, 0x7AC7, 0xC475, 0x7ACA, 0xC5D1, 0x7ACB, 0xA5DF,
+	0x7AD1, 0xD041, 0x7AD8, 0xD2FD, 0x7AD9, 0xAFB8, 0x7ADF, 0xB3BA,
+	0x7AE0, 0xB3B9, 0x7AE3, 0xB5A4, 0x7AE4, 0xDADD, 0x7AE5, 0xB5A3,
+	0x7AE6, 0xDADC, 0x7AEB, 0xDF45, 0x7AED, 0xBADC, 0x7AEE, 0xE34D,
+	0x7AEF, 0xBADD, 0x7AF6, 0xC476, 0x7AF7, 0xF4A5, 0x7AF9, 0xA6CB,
+	0x7AFA, 0xAAC7, 0x7AFB, 0xCDA7, 0x7AFD, 0xACF2, 0x7AFF, 0xACF1,
+	0x7B00, 0xD042, 0x7B01, 0xD043, 0x7B04, 0xD340, 0x7B05, 0xD342,
+	0x7B06, 0xAFB9, 0x7B08, 0xD344, 0x7B09, 0xD347, 0x7B0A, 0xD345,
+	0x7B0E, 0xD346, 0x7B0F, 0xD343, 0x7B10, 0xD2FE, 0x7B11, 0xAFBA,
+	0x7B12, 0xD348, 0x7B13, 0xD341, 0x7B18, 0xD6D3, 0x7B19, 0xB2C6,
+	0x7B1A, 0xD6DC, 0x7B1B, 0xB2C3, 0x7B1D, 0xD6D5, 0x7B1E, 0xB2C7,
+	0x7B20, 0xB2C1, 0x7B22, 0xD6D0, 0x7B23, 0xD6DD, 0x7B24, 0xD6D1,
+	0x7B25, 0xD6CE, 0x7B26, 0xB2C5, 0x7B28, 0xB2C2, 0x7B2A, 0xD6D4,
+	0x7B2B, 0xD6D7, 0x7B2C, 0xB2C4, 0x7B2D, 0xD6D8, 0x7B2E, 0xB2C8,
+	0x7B2F, 0xD6D9, 0x7B30, 0xD6CF, 0x7B31, 0xD6D6, 0x7B32, 0xD6DA,
+	0x7B33, 0xD6D2, 0x7B34, 0xD6CD, 0x7B35, 0xD6CB, 0x7B38, 0xD6DB,
+	0x7B3B, 0xDADF, 0x7B40, 0xDAE4, 0x7B44, 0xDAE0, 0x7B45, 0xDAE6,
+	0x7B46, 0xB5A7, 0x7B47, 0xD6CC, 0x7B48, 0xDAE1, 0x7B49, 0xB5A5,
+	0x7B4A, 0xDADE, 0x7B4B, 0xB5AC, 0x7B4C, 0xDAE2, 0x7B4D, 0xB5AB,
+	0x7B4E, 0xDAE3, 0x7B4F, 0xB5AD, 0x7B50, 0xB5A8, 0x7B51, 0xB5AE,
+	0x7B52, 0xB5A9, 0x7B54, 0xB5AA, 0x7B56, 0xB5A6, 0x7B58, 0xDAE5,
+	0x7B60, 0xB861, 0x7B61, 0xDF50, 0x7B63, 0xDF53, 0x7B64, 0xDF47,
+	0x7B65, 0xDF4C, 0x7B66, 0xDF46, 0x7B67, 0xB863, 0x7B69, 0xDF4A,
+	0x7B6D, 0xDF48, 0x7B6E, 0xB862, 0x7B70, 0xDF4F, 0x7B71, 0xDF4E,
+	0x7B72, 0xDF4B, 0x7B73, 0xDF4D, 0x7B74, 0xDF49, 0x7B75, 0xBAE1,
+	0x7B76, 0xDF52, 0x7B77, 0xB85F, 0x7B78, 0xDF51, 0x7B82, 0xE35D,
+	0x7B84, 0xBAE8, 0x7B85, 0xE358, 0x7B87, 0xBAE7, 0x7B88, 0xE34E,
+	0x7B8A, 0xE350, 0x7B8B, 0xBAE0, 0x7B8C, 0xE355, 0x7B8D, 0xE354,
+	0x7B8E, 0xE357, 0x7B8F, 0xBAE5, 0x7B90, 0xE352, 0x7B91, 0xE351,
+	0x7B94, 0xBAE4, 0x7B95, 0xBADF, 0x7B96, 0xE353, 0x7B97, 0xBAE2,
+	0x7B98, 0xE359, 0x7B99, 0xE35B, 0x7B9B, 0xE356, 0x7B9C, 0xE34F,
+	0x7B9D, 0xBAE3, 0x7BA0, 0xBD69, 0x7BA1, 0xBADE, 0x7BA4, 0xE35C,
+	0x7BAC, 0xE6D9, 0x7BAD, 0xBD62, 0x7BAF, 0xE6DB, 0x7BB1, 0xBD63,
+	0x7BB4, 0xBD65, 0x7BB5, 0xE6DE, 0x7BB7, 0xE6D6, 0x7BB8, 0xBAE6,
+	0x7BB9, 0xE6DC, 0x7BBE, 0xE6D8, 0x7BC0, 0xB860, 0x7BC1, 0xBD68,
+	0x7BC4, 0xBD64, 0x7BC6, 0xBD66, 0x7BC7, 0xBD67, 0x7BC9, 0xBF76,
+	0x7BCA, 0xE6DD, 0x7BCB, 0xE6D7, 0x7BCC, 0xBD6A, 0x7BCE, 0xE6DA,
+	0x7BD4, 0xEAC0, 0x7BD5, 0xEABB, 0x7BD8, 0xEAC5, 0x7BD9, 0xBF74,
+	0x7BDA, 0xEABD, 0x7BDB, 0xBF78, 0x7BDC, 0xEAC3, 0x7BDD, 0xEABA,
+	0x7BDE, 0xEAB7, 0x7BDF, 0xEAC6, 0x7BE0, 0xC151, 0x7BE1, 0xBF79,
+	0x7BE2, 0xEAC2, 0x7BE3, 0xEAB8, 0x7BE4, 0xBF77, 0x7BE5, 0xEABC,
+	0x7BE6, 0xBF7B, 0x7BE7, 0xEAB9, 0x7BE8, 0xEABE, 0x7BE9, 0xBF7A,
+	0x7BEA, 0xEAC1, 0x7BEB, 0xEAC4, 0x7BF0, 0xEDCB, 0x7BF1, 0xEDCC,
+	0x7BF2, 0xEDBC, 0x7BF3, 0xEDC3, 0x7BF4, 0xEDC1, 0x7BF7, 0xC14F,
+	0x7BF8, 0xEDC8, 0x7BF9, 0xEABF, 0x7BFB, 0xEDBF, 0x7BFD, 0xEDC9,
+	0x7BFE, 0xC14E, 0x7BFF, 0xEDBE, 0x7C00, 0xEDBD, 0x7C01, 0xEDC7,
+	0x7C02, 0xEDC4, 0x7C03, 0xEDC6, 0x7C05, 0xEDBA, 0x7C06, 0xEDCA,
+	0x7C07, 0xC14C, 0x7C09, 0xEDC5, 0x7C0A, 0xEDCE, 0x7C0B, 0xEDC2,
+	0x7C0C, 0xC150, 0x7C0D, 0xC14D, 0x7C0E, 0xEDC0, 0x7C0F, 0xEDBB,
+	0x7C10, 0xEDCD, 0x7C11, 0xBF75, 0x7C19, 0xF063, 0x7C1C, 0xF061,
+	0x7C1D, 0xF067, 0x7C1E, 0xC2B0, 0x7C1F, 0xF065, 0x7C20, 0xF064,
+	0x7C21, 0xC2B2, 0x7C22, 0xF06A, 0x7C23, 0xC2B1, 0x7C25, 0xF06B,
+	0x7C26, 0xF068, 0x7C27, 0xC2AE, 0x7C28, 0xF069, 0x7C29, 0xF062,
+	0x7C2A, 0xC2AF, 0x7C2B, 0xC2AD, 0x7C2C, 0xF2AB, 0x7C2D, 0xF066,
+	0x7C30, 0xF06C, 0x7C33, 0xF2A8, 0x7C37, 0xC3B2, 0x7C38, 0xC3B0,
+	0x7C39, 0xF2AA, 0x7C3B, 0xF2AC, 0x7C3C, 0xF2A9, 0x7C3D, 0xC3B1,
+	0x7C3E, 0xC3AE, 0x7C3F, 0xC3AF, 0x7C40, 0xC3B3, 0x7C43, 0xC478,
+	0x7C45, 0xF4AA, 0x7C47, 0xF4A9, 0x7C48, 0xF4A7, 0x7C49, 0xF4A6,
+	0x7C4A, 0xF4A8, 0x7C4C, 0xC477, 0x7C4D, 0xC479, 0x7C50, 0xC4F0,
+	0x7C53, 0xF5E5, 0x7C54, 0xF5E4, 0x7C57, 0xF6FA, 0x7C59, 0xF6FC,
+	0x7C5A, 0xF6FE, 0x7C5B, 0xF6FD, 0x7C5C, 0xF6FB, 0x7C5F, 0xC5A3,
+	0x7C60, 0xC5A2, 0x7C63, 0xC5D3, 0x7C64, 0xC5D2, 0x7C65, 0xC5D4,
+	0x7C66, 0xF7ED, 0x7C67, 0xF7EC, 0x7C69, 0xF8FB, 0x7C6A, 0xF8B8,
+	0x7C6B, 0xF8FC, 0x7C6C, 0xC658, 0x7C6E, 0xC659, 0x7C6F, 0xF96D,
+	0x7C72, 0xC67E, 0x7C73, 0xA6CC, 0x7C75, 0xCDA8, 0x7C78, 0xD045,
+	0x7C79, 0xD046, 0x7C7A, 0xD044, 0x7C7D, 0xACF3, 0x7C7F, 0xD047,
+	0x7C80, 0xD048, 0x7C81, 0xD049, 0x7C84, 0xD349, 0x7C85, 0xD34F,
+	0x7C88, 0xD34D, 0x7C89, 0xAFBB, 0x7C8A, 0xD34B, 0x7C8C, 0xD34C,
+	0x7C8D, 0xD34E, 0x7C91, 0xD34A, 0x7C92, 0xB2C9, 0x7C94, 0xD6DE,
+	0x7C95, 0xB2CB, 0x7C96, 0xD6E0, 0x7C97, 0xB2CA, 0x7C98, 0xD6DF,
+	0x7C9E, 0xDAE8, 0x7C9F, 0xB5AF, 0x7CA1, 0xDAEA, 0x7CA2, 0xDAE7,
+	0x7CA3, 0xD6E1, 0x7CA5, 0xB5B0, 0x7CA7, 0xF9DB, 0x7CA8, 0xDAE9,
+	0x7CAF, 0xDF56, 0x7CB1, 0xB864, 0x7CB2, 0xDF54, 0x7CB3, 0xB865,
+	0x7CB4, 0xDF55, 0x7CB5, 0xB866, 0x7CB9, 0xBAE9, 0x7CBA, 0xE361,
+	0x7CBB, 0xE35E, 0x7CBC, 0xE360, 0x7CBD, 0xBAEA, 0x7CBE, 0xBAEB,
+	0x7CBF, 0xE35F, 0x7CC5, 0xE6DF, 0x7CC8, 0xE6E0, 0x7CCA, 0xBD6B,
+	0x7CCB, 0xE6E2, 0x7CCC, 0xE6E1, 0x7CCE, 0xA261, 0x7CD0, 0xEACA,
+	0x7CD1, 0xEACB, 0x7CD2, 0xEAC7, 0x7CD4, 0xEAC8, 0x7CD5, 0xBF7C,
+	0x7CD6, 0xBF7D, 0x7CD7, 0xEAC9, 0x7CD9, 0xC157, 0x7CDC, 0xC153,
+	0x7CDD, 0xC158, 0x7CDE, 0xC154, 0x7CDF, 0xC156, 0x7CE0, 0xC152,
+	0x7CE2, 0xC155, 0x7CE7, 0xC2B3, 0x7CE8, 0xEDCF, 0x7CEA, 0xF2AE,
+	0x7CEC, 0xF2AD, 0x7CEE, 0xF4AB, 0x7CEF, 0xC47A, 0x7CF0, 0xC47B,
+	0x7CF1, 0xF741, 0x7CF2, 0xF5E6, 0x7CF4, 0xF740, 0x7CF6, 0xF8FD,
+	0x7CF7, 0xF9A4, 0x7CF8, 0xA6CD, 0x7CFB, 0xA874, 0x7CFD, 0xCDA9,
+	0x7CFE, 0xAAC8, 0x7D00, 0xACF6, 0x7D01, 0xD04C, 0x7D02, 0xACF4,
+	0x7D03, 0xD04A, 0x7D04, 0xACF9, 0x7D05, 0xACF5, 0x7D06, 0xACFA,
+	0x7D07, 0xACF8, 0x7D08, 0xD04B, 0x7D09, 0xACF7, 0x7D0A, 0xAFBF,
+	0x7D0B, 0xAFBE, 0x7D0C, 0xD35A, 0x7D0D, 0xAFC7, 0x7D0E, 0xD353,
+	0x7D0F, 0xD359, 0x7D10, 0xAFC3, 0x7D11, 0xD352, 0x7D12, 0xD358,
+	0x7D13, 0xD356, 0x7D14, 0xAFC2, 0x7D15, 0xAFC4, 0x7D16, 0xD355,
+	0x7D17, 0xAFBD, 0x7D18, 0xD354, 0x7D19, 0xAFC8, 0x7D1A, 0xAFC5,
+	0x7D1B, 0xAFC9, 0x7D1C, 0xAFC6, 0x7D1D, 0xD351, 0x7D1E, 0xD350,
+	0x7D1F, 0xD357, 0x7D20, 0xAFC0, 0x7D21, 0xAFBC, 0x7D22, 0xAFC1,
+	0x7D28, 0xD6F0, 0x7D29, 0xD6E9, 0x7D2B, 0xB5B5, 0x7D2C, 0xD6E8,
+	0x7D2E, 0xB2CF, 0x7D2F, 0xB2D6, 0x7D30, 0xB2D3, 0x7D31, 0xB2D9,
+	0x7D32, 0xB2D8, 0x7D33, 0xB2D4, 0x7D35, 0xD6E2, 0x7D36, 0xD6E5,
+	0x7D38, 0xD6E4, 0x7D39, 0xB2D0, 0x7D3A, 0xD6E6, 0x7D3B, 0xD6EF,
+	0x7D3C, 0xB2D1, 0x7D3D, 0xD6E3, 0x7D3E, 0xD6EC, 0x7D3F, 0xD6ED,
+	0x7D40, 0xB2D2, 0x7D41, 0xD6EA, 0x7D42, 0xB2D7, 0x7D43, 0xB2CD,
+	0x7D44, 0xB2D5, 0x7D45, 0xD6E7, 0x7D46, 0xB2CC, 0x7D47, 0xD6EB,
+	0x7D4A, 0xD6EE, 0x7D4E, 0xDAFB, 0x7D4F, 0xDAF2, 0x7D50, 0xB5B2,
+	0x7D51, 0xDAF9, 0x7D52, 0xDAF6, 0x7D53, 0xDAEE, 0x7D54, 0xDAF7,
+	0x7D55, 0xB5B4, 0x7D56, 0xDAEF, 0x7D58, 0xDAEB, 0x7D5B, 0xB86C,
+	0x7D5C, 0xDAF4, 0x7D5E, 0xB5B1, 0x7D5F, 0xDAFA, 0x7D61, 0xB5B8,
+	0x7D62, 0xB5BA, 0x7D63, 0xDAED, 0x7D66, 0xB5B9, 0x7D67, 0xDAF0,
+	0x7D68, 0xB5B3, 0x7D69, 0xDAF8, 0x7D6A, 0xDAF1, 0x7D6B, 0xDAF5,
+	0x7D6D, 0xDAF3, 0x7D6E, 0xB5B6, 0x7D6F, 0xDAEC, 0x7D70, 0xB5BB,
+	0x7D71, 0xB2CE, 0x7D72, 0xB5B7, 0x7D73, 0xB5BC, 0x7D79, 0xB868,
+	0x7D7A, 0xDF5D, 0x7D7B, 0xDF5F, 0x7D7C, 0xDF61, 0x7D7D, 0xDF65,
+	0x7D7F, 0xDF5B, 0x7D80, 0xDF59, 0x7D81, 0xB86A, 0x7D83, 0xDF60,
+	0x7D84, 0xDF64, 0x7D85, 0xDF5C, 0x7D86, 0xDF58, 0x7D88, 0xDF57,
+	0x7D8C, 0xDF62, 0x7D8D, 0xDF5A, 0x7D8E, 0xDF5E, 0x7D8F, 0xB86B,
+	0x7D91, 0xB869, 0x7D92, 0xDF66, 0x7D93, 0xB867, 0x7D94, 0xDF63,
+	0x7D96, 0xE372, 0x7D9C, 0xBAEE, 0x7D9D, 0xE36A, 0x7D9E, 0xBD78,
+	0x7D9F, 0xE374, 0x7DA0, 0xBAF1, 0x7DA1, 0xE378, 0x7DA2, 0xBAF7,
+	0x7DA3, 0xE365, 0x7DA6, 0xE375, 0x7DA7, 0xE362, 0x7DA9, 0xE377,
+	0x7DAA, 0xE366, 0x7DAC, 0xBAFE, 0x7DAD, 0xBAFB, 0x7DAE, 0xE376,
+	0x7DAF, 0xE370, 0x7DB0, 0xBAED, 0x7DB1, 0xBAF5, 0x7DB2, 0xBAF4,
+	0x7DB4, 0xBAF3, 0x7DB5, 0xBAF9, 0x7DB7, 0xE363, 0x7DB8, 0xBAFA,
+	0x7DB9, 0xE371, 0x7DBA, 0xBAF6, 0x7DBB, 0xBAEC, 0x7DBC, 0xE373,
+	0x7DBD, 0xBAEF, 0x7DBE, 0xBAF0, 0x7DBF, 0xBAF8, 0x7DC0, 0xE368,
+	0x7DC1, 0xE367, 0x7DC2, 0xE364, 0x7DC4, 0xE36C, 0x7DC5, 0xE369,
+	0x7DC6, 0xE36D, 0x7DC7, 0xBAFD, 0x7DC9, 0xE379, 0x7DCA, 0xBAF2,
+	0x7DCB, 0xE36E, 0x7DCC, 0xE36F, 0x7DCE, 0xE36B, 0x7DD2, 0xBAFC,
+	0x7DD7, 0xE6E7, 0x7DD8, 0xBD70, 0x7DD9, 0xBD79, 0x7DDA, 0xBD75,
+	0x7DDB, 0xE6E4, 0x7DDD, 0xBD72, 0x7DDE, 0xBD76, 0x7DDF, 0xE6F0,
+	0x7DE0, 0xBD6C, 0x7DE1, 0xE6E8, 0x7DE3, 0xBD74, 0x7DE6, 0xE6EB,
+	0x7DE7, 0xE6E6, 0x7DE8, 0xBD73, 0x7DE9, 0xBD77, 0x7DEA, 0xE6E5,
+	0x7DEC, 0xBD71, 0x7DEE, 0xE6EF, 0x7DEF, 0xBD6E, 0x7DF0, 0xE6EE,
+	0x7DF1, 0xE6ED, 0x7DF2, 0xBD7A, 0x7DF3, 0xE572, 0x7DF4, 0xBD6D,
+	0x7DF6, 0xE6EC, 0x7DF7, 0xE6E3, 0x7DF9, 0xBD7B, 0x7DFA, 0xE6EA,
+	0x7DFB, 0xBD6F, 0x7E03, 0xE6E9, 0x7E08, 0xBFA2, 0x7E09, 0xBFA7,
+	0x7E0A, 0xBF7E, 0x7E0B, 0xEAD8, 0x7E0C, 0xEACF, 0x7E0D, 0xEADB,
+	0x7E0E, 0xEAD3, 0x7E0F, 0xEAD9, 0x7E10, 0xBFA8, 0x7E11, 0xBFA1,
+	0x7E12, 0xEACC, 0x7E13, 0xEAD2, 0x7E14, 0xEADC, 0x7E15, 0xEAD5,
+	0x7E16, 0xEADA, 0x7E17, 0xEACE, 0x7E1A, 0xEAD6, 0x7E1B, 0xBFA3,
+	0x7E1C, 0xEAD4, 0x7E1D, 0xBFA6, 0x7E1E, 0xBFA5, 0x7E1F, 0xEAD0,
+	0x7E20, 0xEAD1, 0x7E21, 0xEACD, 0x7E22, 0xEAD7, 0x7E23, 0xBFA4,
+	0x7E24, 0xEADE, 0x7E25, 0xEADD, 0x7E29, 0xEDDA, 0x7E2A, 0xEDD6,
+	0x7E2B, 0xC15F, 0x7E2D, 0xEDD0, 0x7E2E, 0xC159, 0x7E2F, 0xC169,
+	0x7E30, 0xEDDC, 0x7E31, 0xC161, 0x7E32, 0xC15D, 0x7E33, 0xEDD3,
+	0x7E34, 0xC164, 0x7E35, 0xC167, 0x7E36, 0xEDDE, 0x7E37, 0xC15C,
+	0x7E38, 0xEDD5, 0x7E39, 0xC165, 0x7E3A, 0xEDE0, 0x7E3B, 0xEDDD,
+	0x7E3C, 0xEDD1, 0x7E3D, 0xC160, 0x7E3E, 0xC15A, 0x7E3F, 0xC168,
+	0x7E40, 0xEDD8, 0x7E41, 0xC163, 0x7E42, 0xEDD2, 0x7E43, 0xC15E,
+	0x7E44, 0xEDDF, 0x7E45, 0xC162, 0x7E46, 0xC15B, 0x7E47, 0xEDD9,
+	0x7E48, 0xC166, 0x7E49, 0xEDD7, 0x7E4C, 0xEDDB, 0x7E50, 0xF06E,
+	0x7E51, 0xF074, 0x7E52, 0xC2B9, 0x7E53, 0xF077, 0x7E54, 0xC2B4,
+	0x7E55, 0xC2B5, 0x7E56, 0xF06F, 0x7E57, 0xF076, 0x7E58, 0xF071,
+	0x7E59, 0xC2BA, 0x7E5A, 0xC2B7, 0x7E5C, 0xF06D, 0x7E5E, 0xC2B6,
+	0x7E5F, 0xF073, 0x7E60, 0xF075, 0x7E61, 0xC2B8, 0x7E62, 0xF072,
+	0x7E63, 0xF070, 0x7E68, 0xF2B8, 0x7E69, 0xC3B7, 0x7E6A, 0xC3B8,
+	0x7E6B, 0xC3B4, 0x7E6D, 0xC3B5, 0x7E6F, 0xF2B4, 0x7E70, 0xF2B2,
+	0x7E72, 0xF2B6, 0x7E73, 0xC3BA, 0x7E74, 0xF2B7, 0x7E75, 0xF2B0,
+	0x7E76, 0xF2AF, 0x7E77, 0xF2B3, 0x7E78, 0xF2B1, 0x7E79, 0xC3B6,
+	0x7E7A, 0xF2B5, 0x7E7B, 0xF4AC, 0x7E7C, 0xC47E, 0x7E7D, 0xC47D,
+	0x7E7E, 0xF4AD, 0x7E80, 0xF4AF, 0x7E81, 0xF4AE, 0x7E82, 0xC4A1,
+	0x7E86, 0xF5EB, 0x7E87, 0xF5E8, 0x7E88, 0xF5E9, 0x7E8A, 0xF5E7,
+	0x7E8B, 0xF5EA, 0x7E8C, 0xC4F2, 0x7E8D, 0xF5EC, 0x7E8F, 0xC4F1,
+	0x7E91, 0xF742, 0x7E93, 0xC5D5, 0x7E94, 0xC5D7, 0x7E95, 0xF7EE,
+	0x7E96, 0xC5D6, 0x7E97, 0xF8B9, 0x7E98, 0xF940, 0x7E99, 0xF942,
+	0x7E9A, 0xF8FE, 0x7E9B, 0xF941, 0x7E9C, 0xC66C, 0x7F36, 0xA6CE,
+	0x7F38, 0xACFB, 0x7F39, 0xD26F, 0x7F3A, 0xAFCA, 0x7F3D, 0xB2DA,
+	0x7F3E, 0xDAFC, 0x7F3F, 0xDAFD, 0x7F43, 0xEADF, 0x7F44, 0xC16A,
+	0x7F45, 0xEDE1, 0x7F48, 0xC2BB, 0x7F4A, 0xF2BA, 0x7F4B, 0xF2B9,
+	0x7F4C, 0xC4A2, 0x7F4D, 0xF5ED, 0x7F4F, 0xF743, 0x7F50, 0xC5F8,
+	0x7F51, 0xCA49, 0x7F54, 0xAAC9, 0x7F55, 0xA875, 0x7F58, 0xD04D,
+	0x7F5B, 0xD360, 0x7F5C, 0xD35B, 0x7F5D, 0xD35F, 0x7F5E, 0xD35D,
+	0x7F5F, 0xAFCB, 0x7F60, 0xD35E, 0x7F61, 0xD35C, 0x7F63, 0xD6F1,
+	0x7F65, 0xDAFE, 0x7F66, 0xDB40, 0x7F67, 0xDF69, 0x7F68, 0xDF6A,
+	0x7F69, 0xB86E, 0x7F6A, 0xB86F, 0x7F6B, 0xDF68, 0x7F6C, 0xDF6B,
+	0x7F6D, 0xDF67, 0x7F6E, 0xB86D, 0x7F70, 0xBB40, 0x7F72, 0xB870,
+	0x7F73, 0xE37A, 0x7F75, 0xBD7C, 0x7F76, 0xE6F1, 0x7F77, 0xBD7D,
+	0x7F79, 0xBFA9, 0x7F7A, 0xEAE2, 0x7F7B, 0xEAE0, 0x7F7C, 0xEAE1,
+	0x7F7D, 0xEDE4, 0x7F7E, 0xEDE3, 0x7F7F, 0xEDE2, 0x7F83, 0xF2BB,
+	0x7F85, 0xC3B9, 0x7F86, 0xF2BC, 0x7F87, 0xF744, 0x7F88, 0xC5F9,
+	0x7F89, 0xF8BA, 0x7F8A, 0xA6CF, 0x7F8B, 0xAACB, 0x7F8C, 0xAACA,
+	0x7F8D, 0xD04F, 0x7F8E, 0xACFC, 0x7F91, 0xD04E, 0x7F92, 0xD362,
+	0x7F94, 0xAFCC, 0x7F95, 0xD6F2, 0x7F96, 0xD361, 0x7F9A, 0xB2DC,
+	0x7F9B, 0xD6F5, 0x7F9C, 0xD6F3, 0x7F9D, 0xD6F4, 0x7F9E, 0xB2DB,
+	0x7FA0, 0xDB42, 0x7FA1, 0xDB43, 0x7FA2, 0xDB41, 0x7FA4, 0xB873,
+	0x7FA5, 0xDF6D, 0x7FA6, 0xDF6C, 0x7FA7, 0xDF6E, 0x7FA8, 0xB872,
+	0x7FA9, 0xB871, 0x7FAC, 0xE6F2, 0x7FAD, 0xE6F4, 0x7FAF, 0xBD7E,
+	0x7FB0, 0xE6F3, 0x7FB1, 0xEAE3, 0x7FB2, 0xBFAA, 0x7FB3, 0xF079,
+	0x7FB5, 0xF078, 0x7FB6, 0xC3BB, 0x7FB7, 0xF2BD, 0x7FB8, 0xC3BD,
+	0x7FB9, 0xC3BC, 0x7FBA, 0xF4B0, 0x7FBB, 0xF5EE, 0x7FBC, 0xC4F3,
+	0x7FBD, 0xA6D0, 0x7FBE, 0xD050, 0x7FBF, 0xACFD, 0x7FC0, 0xD365,
+	0x7FC1, 0xAFCE, 0x7FC2, 0xD364, 0x7FC3, 0xD363, 0x7FC5, 0xAFCD,
+	0x7FC7, 0xD6FB, 0x7FC9, 0xD6FD, 0x7FCA, 0xD6F6, 0x7FCB, 0xD6F7,
+	0x7FCC, 0xB2DD, 0x7FCD, 0xD6F8, 0x7FCE, 0xB2DE, 0x7FCF, 0xD6FC,
+	0x7FD0, 0xD6F9, 0x7FD1, 0xD6FA, 0x7FD2, 0xB2DF, 0x7FD4, 0xB5BE,
+	0x7FD5, 0xB5BF, 0x7FD7, 0xDB44, 0x7FDB, 0xDF6F, 0x7FDC, 0xDF70,
+	0x7FDE, 0xE37E, 0x7FDF, 0xBB43, 0x7FE0, 0xBB41, 0x7FE1, 0xBB42,
+	0x7FE2, 0xE37B, 0x7FE3, 0xE37C, 0x7FE5, 0xE37D, 0x7FE6, 0xE6F9,
+	0x7FE8, 0xE6FA, 0x7FE9, 0xBDA1, 0x7FEA, 0xE6F7, 0x7FEB, 0xE6F6,
+	0x7FEC, 0xE6F8, 0x7FED, 0xE6F5, 0x7FEE, 0xBFAD, 0x7FEF, 0xEAE4,
+	0x7FF0, 0xBFAB, 0x7FF1, 0xBFAC, 0x7FF2, 0xEDE6, 0x7FF3, 0xC16B,
+	0x7FF4, 0xEDE5, 0x7FF5, 0xEFA8, 0x7FF7, 0xF07A, 0x7FF8, 0xF07B,
+	0x7FF9, 0xC2BC, 0x7FFB, 0xC2BD, 0x7FFC, 0xC16C, 0x7FFD, 0xF2BE,
+	0x7FFE, 0xF2BF, 0x7FFF, 0xF4B1, 0x8000, 0xC4A3, 0x8001, 0xA6D1,
+	0x8003, 0xA6D2, 0x8004, 0xACFE, 0x8005, 0xAACC, 0x8006, 0xAFCF,
+	0x8007, 0xD051, 0x800B, 0xB5C0, 0x800C, 0xA6D3, 0x800D, 0xAD41,
+	0x800E, 0xD052, 0x800F, 0xD053, 0x8010, 0xAD40, 0x8011, 0xAD42,
+	0x8012, 0xA6D4, 0x8014, 0xD054, 0x8015, 0xAFD1, 0x8016, 0xD366,
+	0x8017, 0xAFD3, 0x8018, 0xAFD0, 0x8019, 0xAFD2, 0x801B, 0xD741,
+	0x801C, 0xB2E0, 0x801E, 0xD740, 0x801F, 0xD6FE, 0x8021, 0xDF71,
+	0x8024, 0xE3A1, 0x8026, 0xBDA2, 0x8028, 0xBFAE, 0x8029, 0xEAE6,
+	0x802A, 0xEAE5, 0x802C, 0xEDE7, 0x8030, 0xF5EF, 0x8033, 0xA6D5,
+	0x8034, 0xCB73, 0x8035, 0xCDAA, 0x8036, 0xAD43, 0x8037, 0xD055,
+	0x8039, 0xD368, 0x803D, 0xAFD4, 0x803E, 0xD367, 0x803F, 0xAFD5,
+	0x8043, 0xD743, 0x8046, 0xB2E2, 0x8047, 0xD742, 0x8048, 0xD744,
+	0x804A, 0xB2E1, 0x804F, 0xDB46, 0x8050, 0xDB47, 0x8051, 0xDB45,
+	0x8052, 0xB5C1, 0x8056, 0xB874, 0x8058, 0xB875, 0x805A, 0xBB45,
+	0x805C, 0xE3A3, 0x805D, 0xE3A2, 0x805E, 0xBB44, 0x8064, 0xE6FB,
+	0x8067, 0xE6FC, 0x806C, 0xEAE7, 0x806F, 0xC170, 0x8070, 0xC16F,
+	0x8071, 0xC16D, 0x8072, 0xC16E, 0x8073, 0xC171, 0x8075, 0xF07C,
+	0x8076, 0xC2BF, 0x8077, 0xC2BE, 0x8078, 0xF2C0, 0x8079, 0xF4B2,
+	0x807D, 0xC5A5, 0x807E, 0xC5A4, 0x807F, 0xA6D6, 0x8082, 0xD1FB,
+	0x8084, 0xB877, 0x8085, 0xB5C2, 0x8086, 0xB876, 0x8087, 0xBB46,
+	0x8089, 0xA6D7, 0x808A, 0xC9A9, 0x808B, 0xA6D8, 0x808C, 0xA6D9,
+	0x808F, 0xCDAB, 0x8090, 0xCB76, 0x8092, 0xCB77, 0x8093, 0xA877,
+	0x8095, 0xCB74, 0x8096, 0xA876, 0x8098, 0xA879, 0x8099, 0xCB75,
+	0x809A, 0xA87B, 0x809B, 0xA87A, 0x809C, 0xCB78, 0x809D, 0xA878,
+	0x80A1, 0xAAD1, 0x80A2, 0xAACF, 0x80A3, 0xCDAD, 0x80A5, 0xAACE,
+	0x80A9, 0xAAD3, 0x80AA, 0xAAD5, 0x80AB, 0xAAD2, 0x80AD, 0xCDB0,
+	0x80AE, 0xCDAC, 0x80AF, 0xAAD6, 0x80B1, 0xAAD0, 0x80B2, 0xA87C,
+	0x80B4, 0xAAD4, 0x80B5, 0xCDAF, 0x80B8, 0xCDAE, 0x80BA, 0xAACD,
+	0x80C2, 0xD05B, 0x80C3, 0xAD47, 0x80C4, 0xAD48, 0x80C5, 0xD05D,
+	0x80C7, 0xD057, 0x80C8, 0xD05A, 0x80C9, 0xD063, 0x80CA, 0xD061,
+	0x80CC, 0xAD49, 0x80CD, 0xD067, 0x80CE, 0xAD4C, 0x80CF, 0xD064,
+	0x80D0, 0xD05C, 0x80D1, 0xD059, 0x80D4, 0xDB49, 0x80D5, 0xD062,
+	0x80D6, 0xAD44, 0x80D7, 0xD065, 0x80D8, 0xD056, 0x80D9, 0xD05F,
+	0x80DA, 0xAD46, 0x80DB, 0xAD4B, 0x80DC, 0xD060, 0x80DD, 0xAD4F,
+	0x80DE, 0xAD4D, 0x80E0, 0xD058, 0x80E1, 0xAD4A, 0x80E3, 0xD05E,
+	0x80E4, 0xAD4E, 0x80E5, 0xAD45, 0x80E6, 0xD066, 0x80ED, 0xAFDA,
+	0x80EF, 0xAFE3, 0x80F0, 0xAFD8, 0x80F1, 0xAFD6, 0x80F2, 0xD36A,
+	0x80F3, 0xAFDE, 0x80F4, 0xAFDB, 0x80F5, 0xD36C, 0x80F8, 0xAFDD,
+	0x80F9, 0xD36B, 0x80FA, 0xD369, 0x80FB, 0xD36E, 0x80FC, 0xAFE2,
+	0x80FD, 0xAFE0, 0x80FE, 0xDB48, 0x8100, 0xD36F, 0x8101, 0xD36D,
+	0x8102, 0xAFD7, 0x8105, 0xAFD9, 0x8106, 0xAFDC, 0x8108, 0xAFDF,
+	0x810A, 0xAFE1, 0x8115, 0xD74E, 0x8116, 0xB2E4, 0x8118, 0xD745,
+	0x8119, 0xD747, 0x811B, 0xD748, 0x811D, 0xD750, 0x811E, 0xD74C,
+	0x811F, 0xD74A, 0x8121, 0xD74D, 0x8122, 0xD751, 0x8123, 0xB2E5,
+	0x8124, 0xB2E9, 0x8125, 0xD746, 0x8127, 0xD74F, 0x8129, 0xB2E7,
+	0x812B, 0xB2E6, 0x812C, 0xD74B, 0x812D, 0xD749, 0x812F, 0xB2E3,
+	0x8130, 0xB2E8, 0x8139, 0xB5C8, 0x813A, 0xDB51, 0x813D, 0xDB4F,
+	0x813E, 0xB5CA, 0x8143, 0xDB4A, 0x8144, 0xDFA1, 0x8146, 0xB5C9,
+	0x8147, 0xDB4E, 0x814A, 0xDB4B, 0x814B, 0xB5C5, 0x814C, 0xB5CB,
+	0x814D, 0xDB50, 0x814E, 0xB5C7, 0x814F, 0xDB4D, 0x8150, 0xBB47,
+	0x8151, 0xB5C6, 0x8152, 0xDB4C, 0x8153, 0xB5CC, 0x8154, 0xB5C4,
+	0x8155, 0xB5C3, 0x815B, 0xDF77, 0x815C, 0xDF75, 0x815E, 0xDF7B,
+	0x8160, 0xDF73, 0x8161, 0xDFA2, 0x8162, 0xDF78, 0x8164, 0xDF72,
+	0x8165, 0xB87B, 0x8166, 0xB8A3, 0x8167, 0xDF7D, 0x8169, 0xDF76,
+	0x816B, 0xB87E, 0x816E, 0xB87C, 0x816F, 0xDF7E, 0x8170, 0xB879,
+	0x8171, 0xB878, 0x8172, 0xDF79, 0x8173, 0xB87D, 0x8174, 0xB5CD,
+	0x8176, 0xDF7C, 0x8177, 0xDF74, 0x8178, 0xB87A, 0x8179, 0xB8A1,
+	0x817A, 0xB8A2, 0x817F, 0xBB4C, 0x8180, 0xBB48, 0x8182, 0xBB4D,
+	0x8183, 0xE3A6, 0x8186, 0xE3A5, 0x8187, 0xE3A7, 0x8188, 0xBB4A,
+	0x8189, 0xE3A4, 0x818A, 0xBB4B, 0x818B, 0xE3AA, 0x818C, 0xE3A9,
+	0x818D, 0xE3A8, 0x818F, 0xBB49, 0x8195, 0xE741, 0x8197, 0xE744,
+	0x8198, 0xBDA8, 0x8199, 0xE743, 0x819A, 0xBDA7, 0x819B, 0xBDA3,
+	0x819C, 0xBDA4, 0x819D, 0xBDA5, 0x819E, 0xE740, 0x819F, 0xE6FE,
+	0x81A0, 0xBDA6, 0x81A2, 0xE742, 0x81A3, 0xE6FD, 0x81A6, 0xEAE9,
+	0x81A7, 0xEAF3, 0x81A8, 0xBFB1, 0x81A9, 0xBFB0, 0x81AB, 0xEAED,
+	0x81AC, 0xEAEF, 0x81AE, 0xEAEA, 0x81B0, 0xEAEE, 0x81B1, 0xEAE8,
+	0x81B2, 0xEAF1, 0x81B3, 0xBFAF, 0x81B4, 0xEAF0, 0x81B5, 0xEAEC,
+	0x81B7, 0xEAF2, 0x81B9, 0xEAEB, 0x81BA, 0xC174, 0x81BB, 0xEDE8,
+	0x81BC, 0xEDEE, 0x81BD, 0xC178, 0x81BE, 0xC17A, 0x81BF, 0xC177,
+	0x81C0, 0xC176, 0x81C2, 0xC175, 0x81C3, 0xC173, 0x81C4, 0xEDE9,
+	0x81C5, 0xEDEC, 0x81C6, 0xC172, 0x81C7, 0xEDED, 0x81C9, 0xC179,
+	0x81CA, 0xEDEB, 0x81CC, 0xEDEA, 0x81CD, 0xC2C0, 0x81CF, 0xC2C1,
+	0x81D0, 0xF0A1, 0x81D1, 0xF07D, 0x81D2, 0xF07E, 0x81D5, 0xF2C2,
+	0x81D7, 0xF2C1, 0x81D8, 0xC3BE, 0x81D9, 0xF4B4, 0x81DA, 0xC4A4,
+	0x81DB, 0xF4B3, 0x81DD, 0xF5F0, 0x81DE, 0xF745, 0x81DF, 0xC5A6,
+	0x81E0, 0xF943, 0x81E1, 0xF944, 0x81E2, 0xC5D8, 0x81E3, 0xA6DA,
+	0x81E5, 0xAAD7, 0x81E6, 0xDB52, 0x81E7, 0xBB4E, 0x81E8, 0xC17B,
+	0x81E9, 0xEDEF, 0x81EA, 0xA6DB, 0x81EC, 0xAFE5, 0x81ED, 0xAFE4,
+	0x81EE, 0xDB53, 0x81F2, 0xEAF4, 0x81F3, 0xA6DC, 0x81F4, 0xAD50,
+	0x81F7, 0xDB54, 0x81F8, 0xDB55, 0x81F9, 0xDB56, 0x81FA, 0xBB4F,
+	0x81FB, 0xBFB2, 0x81FC, 0xA6DD, 0x81FE, 0xAAD8, 0x81FF, 0xD068,
+	0x8200, 0xAFE6, 0x8201, 0xD370, 0x8202, 0xB2EA, 0x8204, 0xDB57,
+	0x8205, 0xB8A4, 0x8207, 0xBB50, 0x8208, 0xBFB3, 0x8209, 0xC17C,
+	0x820A, 0xC2C2, 0x820B, 0xF4B5, 0x820C, 0xA6DE, 0x820D, 0xAAD9,
+	0x8210, 0xAFE7, 0x8211, 0xD752, 0x8212, 0xB5CE, 0x8214, 0xBB51,
+	0x8215, 0xE3AB, 0x8216, 0xE745, 0x821B, 0xA6DF, 0x821C, 0xB5CF,
+	0x821D, 0xDFA3, 0x821E, 0xBB52, 0x821F, 0xA6E0, 0x8220, 0xCDB1,
+	0x8221, 0xD069, 0x8222, 0xAD51, 0x8225, 0xD372, 0x8228, 0xAFEA,
+	0x822A, 0xAFE8, 0x822B, 0xAFE9, 0x822C, 0xAFEB, 0x822F, 0xD371,
+	0x8232, 0xD757, 0x8233, 0xD754, 0x8234, 0xD756, 0x8235, 0xB2EB,
+	0x8236, 0xB2ED, 0x8237, 0xB2EC, 0x8238, 0xD753, 0x8239, 0xB2EE,
+	0x823A, 0xD755, 0x823C, 0xDB58, 0x823D, 0xDB59, 0x823F, 0xDB5A,
+	0x8240, 0xDFA6, 0x8242, 0xDFA7, 0x8244, 0xDFA5, 0x8245, 0xDFA8,
+	0x8247, 0xB8A5, 0x8249, 0xDFA4, 0x824B, 0xBB53, 0x824E, 0xE74A,
+	0x824F, 0xE746, 0x8250, 0xE749, 0x8251, 0xE74B, 0x8252, 0xE748,
+	0x8253, 0xE747, 0x8255, 0xEAF5, 0x8256, 0xEAF6, 0x8257, 0xEAF7,
+	0x8258, 0xBFB4, 0x8259, 0xBFB5, 0x825A, 0xEDF1, 0x825B, 0xEDF0,
+	0x825C, 0xEDF2, 0x825E, 0xF0A3, 0x825F, 0xF0A2, 0x8261, 0xF2C4,
+	0x8263, 0xF2C5, 0x8264, 0xF2C3, 0x8266, 0xC4A5, 0x8268, 0xF4B6,
+	0x8269, 0xF4B7, 0x826B, 0xF746, 0x826C, 0xF7EF, 0x826D, 0xF8BB,
+	0x826E, 0xA6E1, 0x826F, 0xA87D, 0x8271, 0xC17D, 0x8272, 0xA6E2,
+	0x8274, 0xD758, 0x8275, 0xDB5B, 0x8277, 0xC641, 0x8278, 0xCA4A,
+	0x827C, 0xCA4B, 0x827D, 0xCA4D, 0x827E, 0xA6E3, 0x827F, 0xCA4E,
+	0x8280, 0xCA4C, 0x8283, 0xCBA2, 0x8284, 0xCBA3, 0x8285, 0xCB7B,
+	0x828A, 0xCBA1, 0x828B, 0xA8A1, 0x828D, 0xA8A2, 0x828E, 0xCB7C,
+	0x828F, 0xCB7A, 0x8290, 0xCB79, 0x8291, 0xCB7D, 0x8292, 0xA87E,
+	0x8293, 0xCB7E, 0x8294, 0xD06A, 0x8298, 0xCDB6, 0x8299, 0xAADC,
+	0x829A, 0xCDB5, 0x829B, 0xCDB7, 0x829D, 0xAADB, 0x829E, 0xCDBC,
+	0x829F, 0xAADF, 0x82A0, 0xCDB2, 0x82A1, 0xCDC0, 0x82A2, 0xCDC6,
+	0x82A3, 0xAAE6, 0x82A4, 0xCDC3, 0x82A5, 0xAAE3, 0x82A7, 0xCDB9,
+	0x82A8, 0xCDBF, 0x82A9, 0xCDC1, 0x82AB, 0xCDB4, 0x82AC, 0xAAE2,
+	0x82AD, 0xAADD, 0x82AE, 0xCDBA, 0x82AF, 0xAAE4, 0x82B0, 0xAAE7,
+	0x82B1, 0xAAE1, 0x82B3, 0xAADA, 0x82B4, 0xCDBE, 0x82B5, 0xCDB8,
+	0x82B6, 0xCDC5, 0x82B7, 0xAAE9, 0x82B8, 0xAAE5, 0x82B9, 0xAAE0,
+	0x82BA, 0xCDBD, 0x82BB, 0xAFEC, 0x82BC, 0xCDBB, 0x82BD, 0xAADE,
+	0x82BE, 0xAAE8, 0x82C0, 0xCDB3, 0x82C2, 0xCDC2, 0x82C3, 0xCDC4,
+	0x82D1, 0xAD62, 0x82D2, 0xAD5C, 0x82D3, 0xAD64, 0x82D4, 0xAD61,
+	0x82D5, 0xD071, 0x82D6, 0xD074, 0x82D7, 0xAD5D, 0x82D9, 0xD06B,
+	0x82DB, 0xAD56, 0x82DC, 0xAD60, 0x82DE, 0xAD63, 0x82DF, 0xAD65,
+	0x82E0, 0xD0A2, 0x82E1, 0xD077, 0x82E3, 0xAD55, 0x82E4, 0xD0A1,
+	0x82E5, 0xAD59, 0x82E6, 0xAD57, 0x82E7, 0xAD52, 0x82E8, 0xD06F,
+	0x82EA, 0xD07E, 0x82EB, 0xD073, 0x82EC, 0xD076, 0x82ED, 0xD0A5,
+	0x82EF, 0xAD66, 0x82F0, 0xD07D, 0x82F1, 0xAD5E, 0x82F2, 0xD078,
+	0x82F3, 0xD0A4, 0x82F4, 0xD075, 0x82F5, 0xD079, 0x82F6, 0xD07C,
+	0x82F9, 0xD06D, 0x82FA, 0xD0A3, 0x82FB, 0xD07B, 0x82FE, 0xD06C,
+	0x8300, 0xD070, 0x8301, 0xAD5F, 0x8302, 0xAD5A, 0x8303, 0xAD53,
+	0x8304, 0xAD58, 0x8305, 0xAD54, 0x8306, 0xAD67, 0x8307, 0xD06E,
+	0x8308, 0xD3A5, 0x8309, 0xAD5B, 0x830C, 0xD07A, 0x830D, 0xCE41,
+	0x8316, 0xD3A8, 0x8317, 0xAFFA, 0x8319, 0xD376, 0x831B, 0xD3A3,
+	0x831C, 0xD37D, 0x831E, 0xD3B2, 0x8320, 0xD3AA, 0x8322, 0xD37E,
+	0x8324, 0xD3A9, 0x8325, 0xD378, 0x8326, 0xD37C, 0x8327, 0xD3B5,
+	0x8328, 0xAFFD, 0x8329, 0xD3AD, 0x832A, 0xD3A4, 0x832B, 0xAFED,
+	0x832C, 0xD3B3, 0x832D, 0xD374, 0x832F, 0xD3AC, 0x8331, 0xAFFC,
+	0x8332, 0xAFF7, 0x8333, 0xD373, 0x8334, 0xAFF5, 0x8335, 0xAFF4,
+	0x8336, 0xAFF9, 0x8337, 0xD3AB, 0x8338, 0xAFF1, 0x8339, 0xAFF8,
+	0x833A, 0xD072, 0x833B, 0xDB5C, 0x833C, 0xD3A6, 0x833F, 0xD37A,
+	0x8340, 0xAFFB, 0x8341, 0xD37B, 0x8342, 0xD3A1, 0x8343, 0xAFFE,
+	0x8344, 0xD375, 0x8345, 0xD3AF, 0x8347, 0xD3AE, 0x8348, 0xD3B6,
+	0x8349, 0xAFF3, 0x834A, 0xAFF0, 0x834B, 0xD3B4, 0x834C, 0xD3B0,
+	0x834D, 0xD3A7, 0x834E, 0xD3A2, 0x834F, 0xAFF6, 0x8350, 0xAFF2,
+	0x8351, 0xD377, 0x8352, 0xAFEE, 0x8353, 0xD3B1, 0x8354, 0xAFEF,
+	0x8356, 0xD379, 0x8373, 0xD75E, 0x8374, 0xD760, 0x8375, 0xD765,
+	0x8376, 0xD779, 0x8377, 0xB2FC, 0x8378, 0xB2F2, 0x837A, 0xD75D,
+	0x837B, 0xB2FD, 0x837C, 0xB2FE, 0x837D, 0xD768, 0x837E, 0xD76F,
+	0x837F, 0xD775, 0x8381, 0xD762, 0x8383, 0xD769, 0x8386, 0xB340,
+	0x8387, 0xD777, 0x8388, 0xD772, 0x8389, 0xB2FA, 0x838A, 0xB2F8,
+	0x838B, 0xD76E, 0x838C, 0xD76A, 0x838D, 0xD75C, 0x838E, 0xB2EF,
+	0x838F, 0xD761, 0x8390, 0xD759, 0x8392, 0xB2F7, 0x8393, 0xB2F9,
+	0x8394, 0xD766, 0x8395, 0xD763, 0x8396, 0xB2F4, 0x8397, 0xD773,
+	0x8398, 0xB2F1, 0x8399, 0xD764, 0x839A, 0xD77A, 0x839B, 0xD76C,
+	0x839D, 0xD76B, 0x839E, 0xB2F0, 0x83A0, 0xB2FB, 0x83A2, 0xB2F3,
+	0x83A3, 0xD75A, 0x83A4, 0xD75F, 0x83A5, 0xD770, 0x83A6, 0xD776,
+	0x83A7, 0xB341, 0x83A8, 0xD75B, 0x83A9, 0xD767, 0x83AA, 0xD76D,
+	0x83AB, 0xB2F6, 0x83AE, 0xD778, 0x83AF, 0xD771, 0x83B0, 0xD774,
+	0x83BD, 0xB2F5, 0x83BF, 0xDB6C, 0x83C0, 0xDB60, 0x83C1, 0xB5D7,
+	0x83C2, 0xDB7D, 0x83C3, 0xDBA7, 0x83C4, 0xDBAA, 0x83C5, 0xB5D5,
+	0x83C6, 0xDB68, 0x83C7, 0xDBA3, 0x83C8, 0xDB69, 0x83C9, 0xDB77,
+	0x83CA, 0xB5E2, 0x83CB, 0xDB73, 0x83CC, 0xB5DF, 0x83CE, 0xDB74,
+	0x83CF, 0xDB5D, 0x83D1, 0xDBA4, 0x83D4, 0xB5E8, 0x83D5, 0xDBA1,
+	0x83D6, 0xDB75, 0x83D7, 0xDBAC, 0x83D8, 0xDB70, 0x83D9, 0xDFC8,
+	0x83DB, 0xDBAF, 0x83DC, 0xB5E6, 0x83DD, 0xDB6E, 0x83DE, 0xDB7A,
+	0x83DF, 0xB5E9, 0x83E0, 0xB5D4, 0x83E1, 0xDB72, 0x83E2, 0xDBAD,
+	0x83E3, 0xDB6B, 0x83E4, 0xDB64, 0x83E5, 0xDB6F, 0x83E7, 0xDB63,
+	0x83E8, 0xDB61, 0x83E9, 0xB5D0, 0x83EA, 0xDBA5, 0x83EB, 0xDB6A,
+	0x83EC, 0xDBA8, 0x83EE, 0xDBA9, 0x83EF, 0xB5D8, 0x83F0, 0xB5DD,
+	0x83F1, 0xB5D9, 0x83F2, 0xB5E1, 0x83F3, 0xDB7E, 0x83F4, 0xB5DA,
+	0x83F5, 0xDB76, 0x83F6, 0xDB66, 0x83F8, 0xB5D2, 0x83F9, 0xDB5E,
+	0x83FA, 0xDBA2, 0x83FB, 0xDBAB, 0x83FC, 0xDB65, 0x83FD, 0xB5E0,
+	0x83FE, 0xDBB0, 0x83FF, 0xDB71, 0x8401, 0xDB6D, 0x8403, 0xB5D1,
+	0x8404, 0xB5E5, 0x8406, 0xDB7C, 0x8407, 0xB5E7, 0x8409, 0xDB78,
+	0x840A, 0xB5DC, 0x840B, 0xB5D6, 0x840C, 0xB5DE, 0x840D, 0xB5D3,
+	0x840E, 0xB5E4, 0x840F, 0xDB79, 0x8410, 0xDB67, 0x8411, 0xDB7B,
+	0x8412, 0xDB62, 0x8413, 0xDBA6, 0x841B, 0xDBAE, 0x8423, 0xDB5F,
+	0x8429, 0xDFC7, 0x842B, 0xDFDD, 0x842C, 0xB855, 0x842D, 0xDFCC,
+	0x842F, 0xDFCA, 0x8430, 0xDFB5, 0x8431, 0xB8A9, 0x8432, 0xDFC5,
+	0x8433, 0xDFD9, 0x8434, 0xDFC1, 0x8435, 0xB8B1, 0x8436, 0xDFD8,
+	0x8437, 0xDFBF, 0x8438, 0xB5E3, 0x8439, 0xDFCF, 0x843A, 0xDFC0,
+	0x843B, 0xDFD6, 0x843C, 0xB8B0, 0x843D, 0xB8A8, 0x843F, 0xDFAA,
+	0x8440, 0xDFB2, 0x8442, 0xDFCB, 0x8443, 0xDFC3, 0x8444, 0xDFDC,
+	0x8445, 0xDFC6, 0x8446, 0xB8B6, 0x8447, 0xDFD7, 0x8449, 0xB8AD,
+	0x844B, 0xDFC9, 0x844C, 0xDFD1, 0x844D, 0xDFB6, 0x844E, 0xDFD0,
+	0x8450, 0xDFE1, 0x8451, 0xDFB1, 0x8452, 0xDFD2, 0x8454, 0xDFDF,
+	0x8456, 0xDFAB, 0x8457, 0xB5DB, 0x8459, 0xDFB9, 0x845A, 0xDFB8,
+	0x845B, 0xB8AF, 0x845D, 0xDFBC, 0x845E, 0xDFBE, 0x845F, 0xDFCD,
+	0x8460, 0xDFDE, 0x8461, 0xB8B2, 0x8463, 0xB8B3, 0x8465, 0xDFB0,
+	0x8466, 0xB8AB, 0x8467, 0xDFB4, 0x8468, 0xDFDA, 0x8469, 0xB8B4,
+	0x846B, 0xB8AC, 0x846C, 0xB8AE, 0x846D, 0xB8B5, 0x846E, 0xDFE0,
+	0x846F, 0xDFD3, 0x8470, 0xDFCE, 0x8473, 0xDFBB, 0x8474, 0xDFBA,
+	0x8475, 0xB8AA, 0x8476, 0xDFAC, 0x8477, 0xB8A7, 0x8478, 0xDFC4,
+	0x8479, 0xDFAD, 0x847A, 0xDFC2, 0x847D, 0xDFB7, 0x847E, 0xDFDB,
+	0x8482, 0xB8A6, 0x8486, 0xDFB3, 0x848D, 0xDFAF, 0x848E, 0xDFD5,
+	0x848F, 0xDFAE, 0x8490, 0xBB60, 0x8491, 0xE3D3, 0x8494, 0xE3C2,
+	0x8497, 0xE3AC, 0x8498, 0xE3CA, 0x8499, 0xBB58, 0x849A, 0xE3BB,
+	0x849B, 0xE3C5, 0x849C, 0xBB5B, 0x849D, 0xE3BE, 0x849E, 0xBB59,
+	0x849F, 0xE3AF, 0x84A0, 0xE3CD, 0x84A1, 0xE3AE, 0x84A2, 0xE3C1,
+	0x84A4, 0xE3AD, 0x84A7, 0xE3BF, 0x84A8, 0xE3C8, 0x84A9, 0xE3C6,
+	0x84AA, 0xE3BA, 0x84AB, 0xE3B5, 0x84AC, 0xE3B3, 0x84AE, 0xE3B4,
+	0x84AF, 0xE3C7, 0x84B0, 0xE3D2, 0x84B1, 0xE3BC, 0x84B2, 0xBB5A,
+	0x84B4, 0xE3B7, 0x84B6, 0xE3CB, 0x84B8, 0xBB5D, 0x84B9, 0xE3B6,
+	0x84BA, 0xE3B0, 0x84BB, 0xE3C0, 0x84BC, 0xBB61, 0x84BF, 0xBB55,
+	0x84C0, 0xBB5E, 0x84C1, 0xE3B8, 0x84C2, 0xE3B2, 0x84C4, 0xBB57,
+	0x84C5, 0xDFD4, 0x84C6, 0xBB56, 0x84C7, 0xE3C3, 0x84C9, 0xBB54,
+	0x84CA, 0xBB63, 0x84CB, 0xBB5C, 0x84CC, 0xE3C4, 0x84CD, 0xE3B9,
+	0x84CE, 0xE3B1, 0x84CF, 0xE3CC, 0x84D0, 0xE3BD, 0x84D1, 0xBB62,
+	0x84D2, 0xE3D0, 0x84D3, 0xBB5F, 0x84D4, 0xE3CF, 0x84D6, 0xE3C9,
+	0x84D7, 0xE3CE, 0x84DB, 0xE3D1, 0x84E7, 0xE773, 0x84E8, 0xE774,
+	0x84E9, 0xE767, 0x84EA, 0xE766, 0x84EB, 0xE762, 0x84EC, 0xBDB4,
+	0x84EE, 0xBDAC, 0x84EF, 0xE776, 0x84F0, 0xE775, 0x84F1, 0xDFA9,
+	0x84F2, 0xE75F, 0x84F3, 0xE763, 0x84F4, 0xE75D, 0x84F6, 0xE770,
+	0x84F7, 0xE761, 0x84F9, 0xE777, 0x84FA, 0xE75A, 0x84FB, 0xE758,
+	0x84FC, 0xE764, 0x84FD, 0xE76E, 0x84FE, 0xE769, 0x84FF, 0xBDB6,
+	0x8500, 0xE74F, 0x8502, 0xE76D, 0x8506, 0xBDB7, 0x8507, 0xDFBD,
+	0x8508, 0xE75B, 0x8509, 0xE752, 0x850A, 0xE755, 0x850B, 0xE77B,
+	0x850C, 0xE75C, 0x850D, 0xE753, 0x850E, 0xE751, 0x850F, 0xE74E,
+	0x8511, 0xBDB0, 0x8512, 0xE765, 0x8513, 0xBDAF, 0x8514, 0xBDB3,
+	0x8515, 0xE760, 0x8516, 0xE768, 0x8517, 0xBDA9, 0x8518, 0xE778,
+	0x8519, 0xE77C, 0x851A, 0xBDAB, 0x851C, 0xE757, 0x851D, 0xE76B,
+	0x851E, 0xE76F, 0x851F, 0xE754, 0x8520, 0xE779, 0x8521, 0xBDB2,
+	0x8523, 0xBDB1, 0x8524, 0xE74C, 0x8525, 0xBDB5, 0x8526, 0xE772,
+	0x8527, 0xE756, 0x8528, 0xE76A, 0x8529, 0xE750, 0x852A, 0xE75E,
+	0x852B, 0xE759, 0x852C, 0xBDAD, 0x852D, 0xBDAE, 0x852E, 0xE76C,
+	0x852F, 0xE77D, 0x8530, 0xE77A, 0x8531, 0xE771, 0x853B, 0xE74D,
+	0x853D, 0xBDAA, 0x853E, 0xEB49, 0x8540, 0xEB40, 0x8541, 0xEB43,
+	0x8543, 0xBFBB, 0x8544, 0xEB45, 0x8545, 0xEAF9, 0x8546, 0xEB41,
+	0x8547, 0xEB47, 0x8548, 0xBFB8, 0x8549, 0xBFBC, 0x854A, 0xBFB6,
+	0x854D, 0xEAFB, 0x854E, 0xEB4C, 0x8551, 0xEB46, 0x8553, 0xEAFC,
+	0x8554, 0xEB55, 0x8555, 0xEB4F, 0x8556, 0xEAF8, 0x8557, 0xEE46,
+	0x8558, 0xEAFE, 0x8559, 0xBFB7, 0x855B, 0xEB4A, 0x855D, 0xEB54,
+	0x855E, 0xBFBF, 0x8560, 0xEB51, 0x8561, 0xEAFD, 0x8562, 0xEB44,
+	0x8563, 0xEB48, 0x8564, 0xEB42, 0x8565, 0xEB56, 0x8566, 0xEB53,
+	0x8567, 0xEB50, 0x8568, 0xBFB9, 0x8569, 0xBFBA, 0x856A, 0xBFBE,
+	0x856B, 0xEAFA, 0x856C, 0xEB57, 0x856D, 0xBFBD, 0x856E, 0xEB4D,
+	0x8571, 0xEB4B, 0x8575, 0xEB4E, 0x8576, 0xEE53, 0x8577, 0xEE40,
+	0x8578, 0xEE45, 0x8579, 0xEE52, 0x857A, 0xEE44, 0x857B, 0xEDFB,
+	0x857C, 0xEE41, 0x857E, 0xC1A2, 0x8580, 0xEDF4, 0x8581, 0xEE4D,
+	0x8582, 0xEE4F, 0x8583, 0xEDF3, 0x8584, 0xC1A1, 0x8585, 0xEE51,
+	0x8586, 0xEE49, 0x8587, 0xC1A8, 0x8588, 0xEE50, 0x8589, 0xEE42,
+	0x858A, 0xC1AA, 0x858B, 0xEDF9, 0x858C, 0xEB52, 0x858D, 0xEE4A,
+	0x858E, 0xEE47, 0x858F, 0xEDF5, 0x8590, 0xEE55, 0x8591, 0xC1A4,
+	0x8594, 0xC1A5, 0x8595, 0xEDF7, 0x8596, 0xEE48, 0x8598, 0xEE54,
+	0x8599, 0xEE4B, 0x859A, 0xEDFD, 0x859B, 0xC1A7, 0x859C, 0xC1A3,
+	0x859D, 0xEE4C, 0x859E, 0xEDFE, 0x859F, 0xEE56, 0x85A0, 0xEDF8,
+	0x85A1, 0xEE43, 0x85A2, 0xEE4E, 0x85A3, 0xEDFA, 0x85A4, 0xEDFC,
+	0x85A6, 0xC2CB, 0x85A7, 0xEDF6, 0x85A8, 0xC1A9, 0x85A9, 0xC2C4,
+	0x85AA, 0xC17E, 0x85AF, 0xC1A6, 0x85B0, 0xC2C8, 0x85B1, 0xF0B3,
+	0x85B3, 0xF0A9, 0x85B4, 0xF0A4, 0x85B5, 0xF0AA, 0x85B6, 0xF0B4,
+	0x85B7, 0xF0B8, 0x85B8, 0xF0B7, 0x85B9, 0xC2CA, 0x85BA, 0xC2C9,
+	0x85BD, 0xF0AB, 0x85BE, 0xF0B9, 0x85BF, 0xF0AE, 0x85C0, 0xF0A6,
+	0x85C2, 0xF0A8, 0x85C3, 0xF0A7, 0x85C4, 0xF0AD, 0x85C5, 0xF0B2,
+	0x85C6, 0xF0A5, 0x85C7, 0xF0AC, 0x85C8, 0xF0B1, 0x85C9, 0xC2C7,
+	0x85CB, 0xF0AF, 0x85CD, 0xC2C5, 0x85CE, 0xF0B0, 0x85CF, 0xC2C3,
+	0x85D0, 0xC2C6, 0x85D1, 0xF2D5, 0x85D2, 0xF0B5, 0x85D5, 0xC3C2,
+	0x85D7, 0xF2CD, 0x85D8, 0xF2D1, 0x85D9, 0xF2C9, 0x85DA, 0xF2CC,
+	0x85DC, 0xF2D4, 0x85DD, 0xC3C0, 0x85DE, 0xF2D9, 0x85DF, 0xF2D2,
+	0x85E1, 0xF2CA, 0x85E2, 0xF2DA, 0x85E3, 0xF2D3, 0x85E4, 0xC3C3,
+	0x85E5, 0xC3C4, 0x85E6, 0xF2D7, 0x85E8, 0xF2CB, 0x85E9, 0xC3BF,
+	0x85EA, 0xC3C1, 0x85EB, 0xF2C6, 0x85EC, 0xF2CE, 0x85ED, 0xF2C8,
+	0x85EF, 0xF2D8, 0x85F0, 0xF2D6, 0x85F1, 0xF2C7, 0x85F2, 0xF2CF,
+	0x85F6, 0xF4BE, 0x85F7, 0xC3C5, 0x85F8, 0xF2D0, 0x85F9, 0xC4A7,
+	0x85FA, 0xC4A9, 0x85FB, 0xC4A6, 0x85FD, 0xF4C3, 0x85FE, 0xF4BB,
+	0x85FF, 0xF4B9, 0x8600, 0xF4BD, 0x8601, 0xF4BA, 0x8604, 0xF4BF,
+	0x8605, 0xF4C1, 0x8606, 0xC4AA, 0x8607, 0xC4AC, 0x8609, 0xF4C0,
+	0x860A, 0xC4AD, 0x860B, 0xC4AB, 0x860C, 0xF4C2, 0x8611, 0xC4A8,
+	0x8617, 0xC4F4, 0x8618, 0xF5F1, 0x8619, 0xF5F7, 0x861A, 0xC4F6,
+	0x861B, 0xF4BC, 0x861C, 0xF5F6, 0x861E, 0xF5FD, 0x861F, 0xF5F4,
+	0x8620, 0xF5FB, 0x8621, 0xF5FA, 0x8622, 0xF4B8, 0x8623, 0xF5F5,
+	0x8624, 0xF0B6, 0x8625, 0xF5FE, 0x8626, 0xF5F3, 0x8627, 0xF5F8,
+	0x8629, 0xF5FC, 0x862A, 0xF5F2, 0x862C, 0xF74A, 0x862D, 0xC4F5,
+	0x862E, 0xF5F9, 0x8631, 0xF7F4, 0x8632, 0xF74B, 0x8633, 0xF749,
+	0x8634, 0xF747, 0x8635, 0xF748, 0x8636, 0xF74C, 0x8638, 0xC5D9,
+	0x8639, 0xF7F2, 0x863A, 0xF7F0, 0x863B, 0xF7F5, 0x863C, 0xF7F3,
+	0x863E, 0xF7F6, 0x863F, 0xC5DA, 0x8640, 0xF7F1, 0x8643, 0xF8BC,
+	0x8646, 0xF945, 0x8647, 0xF946, 0x8648, 0xF947, 0x864B, 0xF9C7,
+	0x864C, 0xF9BD, 0x864D, 0xCA4F, 0x864E, 0xAAEA, 0x8650, 0xAD68,
+	0x8652, 0xD3B8, 0x8653, 0xD3B7, 0x8654, 0xB040, 0x8655, 0xB342,
+	0x8656, 0xD77C, 0x8659, 0xD77B, 0x865B, 0xB5EA, 0x865C, 0xB8B8,
+	0x865E, 0xB8B7, 0x865F, 0xB8B9, 0x8661, 0xE3D4, 0x8662, 0xE77E,
+	0x8663, 0xEB58, 0x8664, 0xEB5A, 0x8665, 0xEB59, 0x8667, 0xC1AB,
+	0x8668, 0xEE57, 0x8669, 0xF0BA, 0x866A, 0xF9A5, 0x866B, 0xA6E4,
+	0x866D, 0xCDC9, 0x866E, 0xCDCA, 0x866F, 0xCDC8, 0x8670, 0xCDC7,
+	0x8671, 0xAAEB, 0x8673, 0xD0A9, 0x8674, 0xD0A7, 0x8677, 0xD0A6,
+	0x8679, 0xAD69, 0x867A, 0xAD6B, 0x867B, 0xAD6A, 0x867C, 0xD0A8,
+	0x8685, 0xD3C4, 0x8686, 0xD3C1, 0x8687, 0xD3BF, 0x868A, 0xB041,
+	0x868B, 0xD3C2, 0x868C, 0xB046, 0x868D, 0xD3BC, 0x868E, 0xD3CB,
+	0x8690, 0xD3CD, 0x8691, 0xD3BD, 0x8693, 0xB043, 0x8694, 0xD3CE,
+	0x8695, 0xD3C9, 0x8696, 0xD3BB, 0x8697, 0xD3C0, 0x8698, 0xD3CA,
+	0x8699, 0xD3C6, 0x869A, 0xD3C3, 0x869C, 0xB048, 0x869D, 0xD3CC,
+	0x869E, 0xD3BE, 0x86A1, 0xD3C7, 0x86A2, 0xD3B9, 0x86A3, 0xB047,
+	0x86A4, 0xB044, 0x86A5, 0xD3C5, 0x86A7, 0xD3C8, 0x86A8, 0xD3BA,
+	0x86A9, 0xB045, 0x86AA, 0xB042, 0x86AF, 0xB34C, 0x86B0, 0xD7A5,
+	0x86B1, 0xB34B, 0x86B3, 0xD7A8, 0x86B4, 0xD7AB, 0x86B5, 0xB348,
+	0x86B6, 0xB346, 0x86B7, 0xD77E, 0x86B8, 0xD7A9, 0x86B9, 0xD7A7,
+	0x86BA, 0xD7A4, 0x86BB, 0xD7AC, 0x86BC, 0xD7AD, 0x86BD, 0xD7AF,
+	0x86BE, 0xD7B0, 0x86BF, 0xD77D, 0x86C0, 0xB345, 0x86C1, 0xD7A2,
+	0x86C2, 0xD7A1, 0x86C3, 0xD7AE, 0x86C4, 0xB347, 0x86C5, 0xD7A3,
+	0x86C6, 0xB349, 0x86C7, 0xB344, 0x86C8, 0xD7A6, 0x86C9, 0xB34D,
+	0x86CB, 0xB34A, 0x86CC, 0xD7AA, 0x86D0, 0xB5F1, 0x86D1, 0xDBBF,
+	0x86D3, 0xDBB4, 0x86D4, 0xB5EE, 0x86D6, 0xDFE7, 0x86D7, 0xDBBD,
+	0x86D8, 0xDBB1, 0x86D9, 0xB5EC, 0x86DA, 0xDBB6, 0x86DB, 0xB5EF,
+	0x86DC, 0xDBBA, 0x86DD, 0xDBB8, 0x86DE, 0xB5F2, 0x86DF, 0xB5EB,
+	0x86E2, 0xDBB2, 0x86E3, 0xDBB5, 0x86E4, 0xB5F0, 0x86E6, 0xDBB3,
+	0x86E8, 0xDBBE, 0x86E9, 0xDBBC, 0x86EA, 0xDBB7, 0x86EB, 0xDBB9,
+	0x86EC, 0xDBBB, 0x86ED, 0xB5ED, 0x86F5, 0xDFE8, 0x86F6, 0xDFEE,
+	0x86F7, 0xDFE4, 0x86F8, 0xDFEA, 0x86F9, 0xB8BA, 0x86FA, 0xDFE6,
+	0x86FB, 0xB8C0, 0x86FE, 0xB8BF, 0x8700, 0xB8BE, 0x8701, 0xDFED,
+	0x8702, 0xB8C1, 0x8703, 0xB8C2, 0x8704, 0xDFE3, 0x8705, 0xDFF0,
+	0x8706, 0xB8C3, 0x8707, 0xB8BD, 0x8708, 0xB8BC, 0x8709, 0xDFEC,
+	0x870A, 0xB8C4, 0x870B, 0xDFE2, 0x870C, 0xDFE5, 0x870D, 0xDFEF,
+	0x870E, 0xDFEB, 0x8711, 0xE3F4, 0x8712, 0xE3E9, 0x8713, 0xB8BB,
+	0x8718, 0xBB6A, 0x8719, 0xE3DD, 0x871A, 0xE3F2, 0x871B, 0xE3DE,
+	0x871C, 0xBB65, 0x871E, 0xE3DB, 0x8720, 0xE3E4, 0x8721, 0xE3DC,
+	0x8722, 0xBB67, 0x8723, 0xE3D6, 0x8724, 0xE3F1, 0x8725, 0xBB68,
+	0x8726, 0xE3EE, 0x8727, 0xE3EF, 0x8728, 0xE3D7, 0x8729, 0xBB6D,
+	0x872A, 0xE3E6, 0x872C, 0xE3E0, 0x872D, 0xE3E7, 0x872E, 0xE3DA,
+	0x8730, 0xE3F3, 0x8731, 0xE3EB, 0x8732, 0xE3E5, 0x8733, 0xE3D5,
+	0x8734, 0xBB69, 0x8735, 0xE3EC, 0x8737, 0xBB6C, 0x8738, 0xE3F0,
+	0x873A, 0xE3EA, 0x873B, 0xBB66, 0x873C, 0xE3E8, 0x873E, 0xE3E2,
+	0x873F, 0xBB64, 0x8740, 0xE3D9, 0x8741, 0xE3E1, 0x8742, 0xE3ED,
+	0x8743, 0xE3DF, 0x8746, 0xE3E3, 0x874C, 0xBDC1, 0x874D, 0xDFE9,
+	0x874E, 0xE7B2, 0x874F, 0xE7BB, 0x8750, 0xE7B1, 0x8751, 0xE7AD,
+	0x8752, 0xE7AA, 0x8753, 0xBDC2, 0x8754, 0xE7A8, 0x8755, 0xBB6B,
+	0x8756, 0xE7A1, 0x8757, 0xBDC0, 0x8758, 0xE7A7, 0x8759, 0xBDBF,
+	0x875A, 0xE7AC, 0x875B, 0xE7A9, 0x875C, 0xE7B9, 0x875D, 0xE7B4,
+	0x875E, 0xE7AE, 0x875F, 0xE7B3, 0x8760, 0xBDBB, 0x8761, 0xE7AB,
+	0x8762, 0xE7BE, 0x8763, 0xE7A2, 0x8764, 0xE7A3, 0x8765, 0xE7BA,
+	0x8766, 0xBDBC, 0x8767, 0xE7BF, 0x8768, 0xBDBE, 0x8769, 0xE7C0,
+	0x876A, 0xE7B0, 0x876B, 0xE3D8, 0x876C, 0xE7B6, 0x876D, 0xE7AF,
+	0x876E, 0xE7B8, 0x876F, 0xE7B5, 0x8773, 0xE7A6, 0x8774, 0xBDB9,
+	0x8775, 0xE7BD, 0x8776, 0xBDBA, 0x8777, 0xE7A4, 0x8778, 0xBDBD,
+	0x8779, 0xEB64, 0x877A, 0xE7B7, 0x877B, 0xE7BC, 0x8781, 0xEB61,
+	0x8782, 0xBDB8, 0x8783, 0xBFC0, 0x8784, 0xEB6B, 0x8785, 0xEB67,
+	0x8787, 0xEB65, 0x8788, 0xEB60, 0x8789, 0xEB6F, 0x878D, 0xBFC4,
+	0x878F, 0xEB5C, 0x8790, 0xEB68, 0x8791, 0xEB69, 0x8792, 0xEB5F,
+	0x8793, 0xEB5E, 0x8794, 0xEB6C, 0x8796, 0xEB62, 0x8797, 0xEB5D,
+	0x8798, 0xEB63, 0x879A, 0xEB6E, 0x879B, 0xEB5B, 0x879C, 0xEB6D,
+	0x879D, 0xEB6A, 0x879E, 0xBFC2, 0x879F, 0xBFC1, 0x87A2, 0xBFC3,
+	0x87A3, 0xEB66, 0x87A4, 0xF0CB, 0x87AA, 0xEE59, 0x87AB, 0xC1B1,
+	0x87AC, 0xEE5D, 0x87AD, 0xEE5A, 0x87AE, 0xEE61, 0x87AF, 0xEE67,
+	0x87B0, 0xEE5C, 0x87B2, 0xEE70, 0x87B3, 0xC1AE, 0x87B4, 0xEE6A,
+	0x87B5, 0xEE5F, 0x87B6, 0xEE6B, 0x87B7, 0xEE66, 0x87B8, 0xEE6D,
+	0x87B9, 0xEE5E, 0x87BA, 0xC1B3, 0x87BB, 0xC1B2, 0x87BC, 0xEE60,
+	0x87BD, 0xEE6E, 0x87BE, 0xEE58, 0x87BF, 0xEE6C, 0x87C0, 0xC1AC,
+	0x87C2, 0xEE64, 0x87C3, 0xEE63, 0x87C4, 0xEE68, 0x87C5, 0xEE5B,
+	0x87C6, 0xC1B0, 0x87C8, 0xC1B4, 0x87C9, 0xEE62, 0x87CA, 0xEE69,
+	0x87CB, 0xC1B5, 0x87CC, 0xEE65, 0x87D1, 0xC1AD, 0x87D2, 0xC1AF,
+	0x87D3, 0xF0C7, 0x87D4, 0xF0C5, 0x87D7, 0xF0CC, 0x87D8, 0xF0C9,
+	0x87D9, 0xF0CD, 0x87DB, 0xF0BE, 0x87DC, 0xF0C6, 0x87DD, 0xF0D1,
+	0x87DE, 0xEE6F, 0x87DF, 0xF0C2, 0x87E0, 0xC2CF, 0x87E1, 0xE7A5,
+	0x87E2, 0xF0BD, 0x87E3, 0xF0CA, 0x87E4, 0xF0C4, 0x87E5, 0xF0C1,
+	0x87E6, 0xF0BC, 0x87E7, 0xF0BB, 0x87E8, 0xF0D0, 0x87EA, 0xF0C0,
+	0x87EB, 0xF0BF, 0x87EC, 0xC2CD, 0x87ED, 0xF0C8, 0x87EF, 0xC2CC,
+	0x87F2, 0xC2CE, 0x87F3, 0xF0C3, 0x87F4, 0xF0CF, 0x87F6, 0xF2DE,
+	0x87F7, 0xF2DF, 0x87F9, 0xC3C9, 0x87FA, 0xF2DC, 0x87FB, 0xC3C6,
+	0x87FC, 0xF2E4, 0x87FE, 0xC3CA, 0x87FF, 0xF2E6, 0x8800, 0xF2DB,
+	0x8801, 0xF0CE, 0x8802, 0xF2E8, 0x8803, 0xF2DD, 0x8805, 0xC3C7,
+	0x8806, 0xF2E3, 0x8808, 0xF2E5, 0x8809, 0xF2E0, 0x880A, 0xF2E7,
+	0x880B, 0xF2E2, 0x880C, 0xF2E1, 0x880D, 0xC3C8, 0x8810, 0xF4C5,
+	0x8811, 0xF4C6, 0x8813, 0xF4C8, 0x8814, 0xC4AE, 0x8815, 0xC4AF,
+	0x8816, 0xF4C9, 0x8817, 0xF4C7, 0x8819, 0xF4C4, 0x881B, 0xF642,
+	0x881C, 0xF645, 0x881D, 0xF641, 0x881F, 0xC4FA, 0x8820, 0xF643,
+	0x8821, 0xC4F9, 0x8822, 0xC4F8, 0x8823, 0xC4F7, 0x8824, 0xF644,
+	0x8825, 0xF751, 0x8826, 0xF74F, 0x8828, 0xF74E, 0x8829, 0xF640,
+	0x882A, 0xF750, 0x882B, 0xF646, 0x882C, 0xF74D, 0x882E, 0xF7F9,
+	0x882F, 0xF7D7, 0x8830, 0xF7F7, 0x8831, 0xC5DB, 0x8832, 0xF7F8,
+	0x8833, 0xF7FA, 0x8835, 0xF8BF, 0x8836, 0xC5FA, 0x8837, 0xF8BE,
+	0x8838, 0xF8BD, 0x8839, 0xC5FB, 0x883B, 0xC65A, 0x883C, 0xF96E,
+	0x883D, 0xF9A7, 0x883E, 0xF9A6, 0x883F, 0xF9A8, 0x8840, 0xA6E5,
+	0x8841, 0xD0AA, 0x8843, 0xD3CF, 0x8844, 0xD3D0, 0x8848, 0xDBC0,
+	0x884A, 0xF647, 0x884B, 0xF8C0, 0x884C, 0xA6E6, 0x884D, 0xAD6C,
+	0x884E, 0xD0AB, 0x8852, 0xD7B1, 0x8853, 0xB34E, 0x8855, 0xDBC2,
+	0x8856, 0xDBC1, 0x8857, 0xB5F3, 0x8859, 0xB8C5, 0x885A, 0xE7C1,
+	0x885B, 0xBDC3, 0x885D, 0xBDC4, 0x8861, 0xBFC5, 0x8862, 0xC5FC,
+	0x8863, 0xA6E7, 0x8867, 0xD0AC, 0x8868, 0xAAED, 0x8869, 0xD0AE,
+	0x886A, 0xD0AD, 0x886B, 0xAD6D, 0x886D, 0xD3D1, 0x886F, 0xD3D8,
+	0x8870, 0xB049, 0x8871, 0xD3D6, 0x8872, 0xD3D4, 0x8874, 0xD3DB,
+	0x8875, 0xD3D2, 0x8876, 0xD3D3, 0x8877, 0xB04A, 0x8879, 0xB04E,
+	0x887C, 0xD3DC, 0x887D, 0xB04D, 0x887E, 0xD3DA, 0x887F, 0xD3D7,
+	0x8880, 0xD3D5, 0x8881, 0xB04B, 0x8882, 0xB04C, 0x8883, 0xD3D9,
+	0x8888, 0xB350, 0x8889, 0xD7B2, 0x888B, 0xB355, 0x888C, 0xD7C2,
+	0x888D, 0xB354, 0x888E, 0xD7C4, 0x8891, 0xD7B8, 0x8892, 0xB352,
+	0x8893, 0xD7C3, 0x8895, 0xD7B3, 0x8896, 0xB353, 0x8897, 0xD7BF,
+	0x8898, 0xD7BB, 0x8899, 0xD7BD, 0x889A, 0xD7B7, 0x889B, 0xD7BE,
+	0x889E, 0xB34F, 0x889F, 0xD7BA, 0x88A1, 0xD7B9, 0x88A2, 0xD7B5,
+	0x88A4, 0xD7C0, 0x88A7, 0xD7BC, 0x88A8, 0xD7B4, 0x88AA, 0xD7B6,
+	0x88AB, 0xB351, 0x88AC, 0xD7C1, 0x88B1, 0xB5F6, 0x88B2, 0xDBCD,
+	0x88B6, 0xDBC9, 0x88B7, 0xDBCB, 0x88B8, 0xDBC6, 0x88B9, 0xDBC5,
+	0x88BA, 0xDBC3, 0x88BC, 0xDBCA, 0x88BD, 0xDBCC, 0x88BE, 0xDBC8,
+	0x88C0, 0xDBC7, 0x88C1, 0xB5F4, 0x88C2, 0xB5F5, 0x88C9, 0xDBCF,
+	0x88CA, 0xB8CD, 0x88CB, 0xDFF2, 0x88CC, 0xDFF8, 0x88CD, 0xDFF3,
+	0x88CE, 0xDFF4, 0x88CF, 0xF9D8, 0x88D0, 0xDFF9, 0x88D2, 0xB8CF,
+	0x88D4, 0xB8C7, 0x88D5, 0xB8CE, 0x88D6, 0xDFF1, 0x88D7, 0xDBC4,
+	0x88D8, 0xB8CA, 0x88D9, 0xB8C8, 0x88DA, 0xDFF7, 0x88DB, 0xDFF6,
+	0x88DC, 0xB8C9, 0x88DD, 0xB8CB, 0x88DE, 0xDFF5, 0x88DF, 0xB8C6,
+	0x88E1, 0xB8CC, 0x88E7, 0xE3F6, 0x88E8, 0xBB74, 0x88EB, 0xE442,
+	0x88EC, 0xE441, 0x88EE, 0xE3FB, 0x88EF, 0xBB76, 0x88F0, 0xE440,
+	0x88F1, 0xE3F7, 0x88F2, 0xE3F8, 0x88F3, 0xBB6E, 0x88F4, 0xBB70,
+	0x88F6, 0xE3FD, 0x88F7, 0xE3F5, 0x88F8, 0xBB72, 0x88F9, 0xBB71,
+	0x88FA, 0xE3F9, 0x88FB, 0xE3FE, 0x88FC, 0xE3FC, 0x88FD, 0xBB73,
+	0x88FE, 0xE3FA, 0x8901, 0xDBCE, 0x8902, 0xBB6F, 0x8905, 0xE7C2,
+	0x8906, 0xE7C9, 0x8907, 0xBDC6, 0x8909, 0xE7CD, 0x890A, 0xBDCA,
+	0x890B, 0xE7C5, 0x890C, 0xE7C3, 0x890E, 0xE7CC, 0x8910, 0xBDC5,
+	0x8911, 0xE7CB, 0x8912, 0xBDC7, 0x8913, 0xBDC8, 0x8914, 0xE7C4,
+	0x8915, 0xBDC9, 0x8916, 0xE7CA, 0x8917, 0xE7C6, 0x8918, 0xE7C7,
+	0x8919, 0xE7C8, 0x891A, 0xBB75, 0x891E, 0xEB70, 0x891F, 0xEB7C,
+	0x8921, 0xBFCA, 0x8922, 0xEB77, 0x8923, 0xEB79, 0x8925, 0xBFC8,
+	0x8926, 0xEB71, 0x8927, 0xEB75, 0x8929, 0xEB78, 0x892A, 0xBFC6,
+	0x892B, 0xBFC9, 0x892C, 0xEB7B, 0x892D, 0xEB73, 0x892E, 0xEB74,
+	0x892F, 0xEB7A, 0x8930, 0xEB72, 0x8931, 0xEB76, 0x8932, 0xBFC7,
+	0x8933, 0xEE72, 0x8935, 0xEE71, 0x8936, 0xC1B7, 0x8937, 0xEE77,
+	0x8938, 0xC1B9, 0x893B, 0xC1B6, 0x893C, 0xEE73, 0x893D, 0xC1BA,
+	0x893E, 0xEE74, 0x8941, 0xEE75, 0x8942, 0xEE78, 0x8944, 0xC1B8,
+	0x8946, 0xF0D6, 0x8949, 0xF0D9, 0x894B, 0xF0D3, 0x894C, 0xF0D5,
+	0x894F, 0xF0D4, 0x8950, 0xF0D7, 0x8951, 0xF0D8, 0x8952, 0xEE76,
+	0x8953, 0xF0D2, 0x8956, 0xC3CD, 0x8957, 0xF2EC, 0x8958, 0xF2EF,
+	0x8959, 0xF2F1, 0x895A, 0xF2EA, 0x895B, 0xF2EB, 0x895C, 0xF2EE,
+	0x895D, 0xF2F0, 0x895E, 0xC3CE, 0x895F, 0xC3CC, 0x8960, 0xC3CB,
+	0x8961, 0xF2ED, 0x8962, 0xF2E9, 0x8963, 0xF4CA, 0x8964, 0xC4B0,
+	0x8966, 0xF4CB, 0x8969, 0xF649, 0x896A, 0xC4FB, 0x896B, 0xF64B,
+	0x896C, 0xC4FC, 0x896D, 0xF648, 0x896E, 0xF64A, 0x896F, 0xC5A8,
+	0x8971, 0xF752, 0x8972, 0xC5A7, 0x8973, 0xF7FD, 0x8974, 0xF7FC,
+	0x8976, 0xF7FB, 0x8979, 0xF948, 0x897A, 0xF949, 0x897B, 0xF94B,
+	0x897C, 0xF94A, 0x897E, 0xCA50, 0x897F, 0xA6E8, 0x8981, 0xAD6E,
+	0x8982, 0xD7C5, 0x8983, 0xB5F7, 0x8985, 0xDFFA, 0x8986, 0xC2D0,
+	0x8988, 0xF2F2, 0x898B, 0xA8A3, 0x898F, 0xB357, 0x8993, 0xB356,
+	0x8995, 0xDBD0, 0x8996, 0xB5F8, 0x8997, 0xDBD2, 0x8998, 0xDBD1,
+	0x899B, 0xDFFB, 0x899C, 0xB8D0, 0x899D, 0xE443, 0x899E, 0xE446,
+	0x899F, 0xE445, 0x89A1, 0xE444, 0x89A2, 0xE7CE, 0x89A3, 0xE7D0,
+	0x89A4, 0xE7CF, 0x89A6, 0xBFCC, 0x89AA, 0xBFCB, 0x89AC, 0xC1BB,
+	0x89AD, 0xEE79, 0x89AE, 0xEE7B, 0x89AF, 0xEE7A, 0x89B2, 0xC2D1,
+	0x89B6, 0xF2F4, 0x89B7, 0xF2F3, 0x89B9, 0xF4CC, 0x89BA, 0xC4B1,
+	0x89BD, 0xC4FD, 0x89BE, 0xF754, 0x89BF, 0xF753, 0x89C0, 0xC65B,
+	0x89D2, 0xA8A4, 0x89D3, 0xD0AF, 0x89D4, 0xAD6F, 0x89D5, 0xD7C8,
+	0x89D6, 0xD7C6, 0x89D9, 0xD7C7, 0x89DA, 0xDBD4, 0x89DB, 0xDBD5,
+	0x89DC, 0xE043, 0x89DD, 0xDBD3, 0x89DF, 0xDFFC, 0x89E0, 0xE041,
+	0x89E1, 0xE040, 0x89E2, 0xE042, 0x89E3, 0xB8D1, 0x89E4, 0xDFFE,
+	0x89E5, 0xDFFD, 0x89E6, 0xE044, 0x89E8, 0xE449, 0x89E9, 0xE447,
+	0x89EB, 0xE448, 0x89EC, 0xE7D3, 0x89ED, 0xE7D1, 0x89F0, 0xE7D2,
+	0x89F1, 0xEB7D, 0x89F2, 0xEE7C, 0x89F3, 0xEE7D, 0x89F4, 0xC2D2,
+	0x89F6, 0xF2F5, 0x89F7, 0xF4CD, 0x89F8, 0xC4B2, 0x89FA, 0xF64C,
+	0x89FB, 0xF755, 0x89FC, 0xC5A9, 0x89FE, 0xF7FE, 0x89FF, 0xF94C,
+	0x8A00, 0xA8A5, 0x8A02, 0xAD71, 0x8A03, 0xAD72, 0x8A04, 0xD0B0,
+	0x8A07, 0xD0B1, 0x8A08, 0xAD70, 0x8A0A, 0xB054, 0x8A0C, 0xB052,
+	0x8A0E, 0xB051, 0x8A0F, 0xB058, 0x8A10, 0xB050, 0x8A11, 0xB059,
+	0x8A12, 0xD3DD, 0x8A13, 0xB056, 0x8A15, 0xB053, 0x8A16, 0xB057,
+	0x8A17, 0xB055, 0x8A18, 0xB04F, 0x8A1B, 0xB35F, 0x8A1D, 0xB359,
+	0x8A1E, 0xD7CC, 0x8A1F, 0xB35E, 0x8A22, 0xB360, 0x8A23, 0xB35A,
+	0x8A25, 0xB35B, 0x8A27, 0xD7CA, 0x8A2A, 0xB358, 0x8A2C, 0xD7CB,
+	0x8A2D, 0xB35D, 0x8A30, 0xD7C9, 0x8A31, 0xB35C, 0x8A34, 0xB644,
+	0x8A36, 0xB646, 0x8A39, 0xDBD8, 0x8A3A, 0xB645, 0x8A3B, 0xB5F9,
+	0x8A3C, 0xB5FD, 0x8A3E, 0xB8E4, 0x8A3F, 0xE049, 0x8A40, 0xDBDA,
+	0x8A41, 0xB5FE, 0x8A44, 0xDBDD, 0x8A45, 0xDBDE, 0x8A46, 0xB643,
+	0x8A48, 0xDBE0, 0x8A4A, 0xDBE2, 0x8A4C, 0xDBE3, 0x8A4D, 0xDBD7,
+	0x8A4E, 0xDBD6, 0x8A4F, 0xDBE4, 0x8A50, 0xB642, 0x8A51, 0xDBE1,
+	0x8A52, 0xDBDF, 0x8A54, 0xB640, 0x8A55, 0xB5FB, 0x8A56, 0xB647,
+	0x8A57, 0xDBDB, 0x8A58, 0xDBDC, 0x8A59, 0xDBD9, 0x8A5B, 0xB641,
+	0x8A5E, 0xB5FC, 0x8A60, 0xB5FA, 0x8A61, 0xE048, 0x8A62, 0xB8DF,
+	0x8A63, 0xB8DA, 0x8A66, 0xB8D5, 0x8A68, 0xB8E5, 0x8A69, 0xB8D6,
+	0x8A6B, 0xB8D2, 0x8A6C, 0xB8E1, 0x8A6D, 0xB8DE, 0x8A6E, 0xB8E0,
+	0x8A70, 0xB8D7, 0x8A71, 0xB8DC, 0x8A72, 0xB8D3, 0x8A73, 0xB8D4,
+	0x8A74, 0xE050, 0x8A75, 0xE04D, 0x8A76, 0xE045, 0x8A77, 0xE04A,
+	0x8A79, 0xB8E2, 0x8A7A, 0xE051, 0x8A7B, 0xB8E3, 0x8A7C, 0xB8D9,
+	0x8A7F, 0xE047, 0x8A81, 0xE04F, 0x8A82, 0xE04B, 0x8A83, 0xE04E,
+	0x8A84, 0xE04C, 0x8A85, 0xB8DD, 0x8A86, 0xE046, 0x8A87, 0xB8D8,
+	0x8A8B, 0xE44C, 0x8A8C, 0xBB78, 0x8A8D, 0xBB7B, 0x8A8F, 0xE44E,
+	0x8A91, 0xBBA5, 0x8A92, 0xE44D, 0x8A93, 0xBB7D, 0x8A95, 0xBDCF,
+	0x8A96, 0xE44F, 0x8A98, 0xBBA4, 0x8A99, 0xE44B, 0x8A9A, 0xBBA6,
+	0x8A9E, 0xBB79, 0x8AA0, 0xB8DB, 0x8AA1, 0xBB7C, 0x8AA3, 0xBB7A,
+	0x8AA4, 0xBB7E, 0x8AA5, 0xBBA2, 0x8AA6, 0xBB77, 0x8AA7, 0xBBA7,
+	0x8AA8, 0xBBA3, 0x8AAA, 0xBBA1, 0x8AAB, 0xE44A, 0x8AB0, 0xBDD6,
+	0x8AB2, 0xBDD2, 0x8AB6, 0xBDD9, 0x8AB8, 0xE7D6, 0x8AB9, 0xBDDA,
+	0x8ABA, 0xE7E2, 0x8ABB, 0xE7DB, 0x8ABC, 0xBDCB, 0x8ABD, 0xE7E3,
+	0x8ABE, 0xE7DD, 0x8ABF, 0xBDD5, 0x8AC0, 0xE7DE, 0x8AC2, 0xBDD4,
+	0x8AC3, 0xE7E1, 0x8AC4, 0xBDCE, 0x8AC5, 0xE7DF, 0x8AC6, 0xE7D5,
+	0x8AC7, 0xBDCD, 0x8AC8, 0xEBAA, 0x8AC9, 0xBDD3, 0x8ACB, 0xBDD0,
+	0x8ACD, 0xBDD8, 0x8ACF, 0xE7D4, 0x8AD1, 0xE7D8, 0x8AD2, 0xBDCC,
+	0x8AD3, 0xE7D7, 0x8AD4, 0xE7D9, 0x8AD5, 0xE7DA, 0x8AD6, 0xBDD7,
+	0x8AD7, 0xE7DC, 0x8AD8, 0xE7E0, 0x8AD9, 0xE7E4, 0x8ADB, 0xBDDB,
+	0x8ADC, 0xBFD2, 0x8ADD, 0xEBA5, 0x8ADE, 0xEBAB, 0x8ADF, 0xEBA8,
+	0x8AE0, 0xEB7E, 0x8AE1, 0xEBAC, 0x8AE2, 0xEBA1, 0x8AE4, 0xEBA7,
+	0x8AE6, 0xBFCD, 0x8AE7, 0xBFD3, 0x8AE8, 0xEBAD, 0x8AEB, 0xBFCF,
+	0x8AED, 0xBFD9, 0x8AEE, 0xBFD4, 0x8AEF, 0xEBAF, 0x8AF0, 0xEBA9,
+	0x8AF1, 0xBFD0, 0x8AF2, 0xEBA2, 0x8AF3, 0xBFDA, 0x8AF4, 0xEBA3,
+	0x8AF5, 0xEBA4, 0x8AF6, 0xBFDB, 0x8AF7, 0xBFD8, 0x8AF8, 0xBDD1,
+	0x8AFA, 0xBFCE, 0x8AFB, 0xEBB0, 0x8AFC, 0xBFDC, 0x8AFE, 0xBFD5,
+	0x8AFF, 0xEBAE, 0x8B00, 0xBFD1, 0x8B01, 0xBFD6, 0x8B02, 0xBFD7,
+	0x8B04, 0xC1C3, 0x8B05, 0xEEA4, 0x8B06, 0xEEAD, 0x8B07, 0xEEAA,
+	0x8B08, 0xEEAC, 0x8B0A, 0xC1C0, 0x8B0B, 0xEEA5, 0x8B0D, 0xEEAB,
+	0x8B0E, 0xC1BC, 0x8B0F, 0xEEA7, 0x8B10, 0xC1C4, 0x8B11, 0xEEA3,
+	0x8B12, 0xEEA8, 0x8B13, 0xEEAF, 0x8B14, 0xEBA6, 0x8B15, 0xEEA9,
+	0x8B16, 0xEEA2, 0x8B17, 0xC1BD, 0x8B18, 0xEEA1, 0x8B19, 0xC1BE,
+	0x8B1A, 0xEEB0, 0x8B1B, 0xC1BF, 0x8B1C, 0xEEAE, 0x8B1D, 0xC1C2,
+	0x8B1E, 0xEE7E, 0x8B20, 0xC1C1, 0x8B22, 0xEEA6, 0x8B23, 0xF0DC,
+	0x8B24, 0xF0EA, 0x8B25, 0xF0E5, 0x8B26, 0xF0E7, 0x8B27, 0xF0DB,
+	0x8B28, 0xC2D3, 0x8B2A, 0xF0DA, 0x8B2B, 0xC2D6, 0x8B2C, 0xC2D5,
+	0x8B2E, 0xF0E9, 0x8B2F, 0xF0E1, 0x8B30, 0xF0DE, 0x8B31, 0xF0E4,
+	0x8B33, 0xF0DD, 0x8B35, 0xF0DF, 0x8B36, 0xF0E8, 0x8B37, 0xF0E6,
+	0x8B39, 0xC2D4, 0x8B3A, 0xF0ED, 0x8B3B, 0xF0EB, 0x8B3C, 0xF0E2,
+	0x8B3D, 0xF0EC, 0x8B3E, 0xF0E3, 0x8B40, 0xF2F9, 0x8B41, 0xC3CF,
+	0x8B42, 0xF341, 0x8B45, 0xF64F, 0x8B46, 0xC3D6, 0x8B47, 0xF0E0,
+	0x8B48, 0xF2F7, 0x8B49, 0xC3D2, 0x8B4A, 0xF2F8, 0x8B4B, 0xF2FD,
+	0x8B4E, 0xC3D4, 0x8B4F, 0xC3D5, 0x8B50, 0xF2F6, 0x8B51, 0xF340,
+	0x8B52, 0xF342, 0x8B53, 0xF2FA, 0x8B54, 0xF2FC, 0x8B55, 0xF2FE,
+	0x8B56, 0xF2FB, 0x8B57, 0xF343, 0x8B58, 0xC3D1, 0x8B59, 0xC3D7,
+	0x8B5A, 0xC3D3, 0x8B5C, 0xC3D0, 0x8B5D, 0xF4D0, 0x8B5F, 0xC4B7,
+	0x8B60, 0xF4CE, 0x8B63, 0xF4D2, 0x8B65, 0xF4D3, 0x8B66, 0xC4B5,
+	0x8B67, 0xF4D4, 0x8B68, 0xF4D1, 0x8B6A, 0xF4CF, 0x8B6B, 0xC4B8,
+	0x8B6C, 0xC4B4, 0x8B6D, 0xF4D5, 0x8B6F, 0xC4B6, 0x8B70, 0xC4B3,
+	0x8B74, 0xC4FE, 0x8B77, 0xC540, 0x8B78, 0xF64E, 0x8B79, 0xF64D,
+	0x8B7A, 0xF650, 0x8B7B, 0xF651, 0x8B7D, 0xC541, 0x8B7E, 0xF756,
+	0x8B7F, 0xF75B, 0x8B80, 0xC5AA, 0x8B82, 0xF758, 0x8B84, 0xF757,
+	0x8B85, 0xF75A, 0x8B86, 0xF759, 0x8B88, 0xF843, 0x8B8A, 0xC5DC,
+	0x8B8B, 0xF842, 0x8B8C, 0xF840, 0x8B8E, 0xF841, 0x8B92, 0xC5FE,
+	0x8B93, 0xC5FD, 0x8B94, 0xF8C1, 0x8B95, 0xF8C2, 0x8B96, 0xC640,
+	0x8B98, 0xF94D, 0x8B99, 0xF94E, 0x8B9A, 0xC667, 0x8B9C, 0xC66D,
+	0x8B9E, 0xF9A9, 0x8B9F, 0xF9C8, 0x8C37, 0xA8A6, 0x8C39, 0xD7CD,
+	0x8C3B, 0xD7CE, 0x8C3C, 0xE052, 0x8C3D, 0xE450, 0x8C3E, 0xE7E5,
+	0x8C3F, 0xC1C6, 0x8C41, 0xC1C5, 0x8C42, 0xF0EE, 0x8C43, 0xF344,
+	0x8C45, 0xF844, 0x8C46, 0xA8A7, 0x8C47, 0xD3DE, 0x8C48, 0xB05A,
+	0x8C49, 0xB361, 0x8C4A, 0xE054, 0x8C4B, 0xE053, 0x8C4C, 0xBDDC,
+	0x8C4D, 0xE7E6, 0x8C4E, 0xBDDD, 0x8C4F, 0xEEB1, 0x8C50, 0xC2D7,
+	0x8C54, 0xC676, 0x8C55, 0xA8A8, 0x8C56, 0xCDCB, 0x8C57, 0xD3DF,
+	0x8C5A, 0xB362, 0x8C5C, 0xD7CF, 0x8C5D, 0xD7D0, 0x8C5F, 0xDBE5,
+	0x8C61, 0xB648, 0x8C62, 0xB8E6, 0x8C64, 0xE056, 0x8C65, 0xE055,
+	0x8C66, 0xE057, 0x8C68, 0xE451, 0x8C69, 0xE452, 0x8C6A, 0xBBA8,
+	0x8C6B, 0xBFDD, 0x8C6C, 0xBDDE, 0x8C6D, 0xBFDE, 0x8C6F, 0xEEB5,
+	0x8C70, 0xEEB2, 0x8C71, 0xEEB4, 0x8C72, 0xEEB3, 0x8C73, 0xC1C7,
+	0x8C75, 0xF0EF, 0x8C76, 0xF346, 0x8C77, 0xF345, 0x8C78, 0xCBA4,
+	0x8C79, 0xB05C, 0x8C7A, 0xB05B, 0x8C7B, 0xD3E0, 0x8C7D, 0xD7D1,
+	0x8C80, 0xDBE7, 0x8C81, 0xDBE6, 0x8C82, 0xB649, 0x8C84, 0xE059,
+	0x8C85, 0xE05A, 0x8C86, 0xE058, 0x8C89, 0xB8E8, 0x8C8A, 0xB8E7,
+	0x8C8C, 0xBBAA, 0x8C8D, 0xBBA9, 0x8C8F, 0xE7E7, 0x8C90, 0xEBB3,
+	0x8C91, 0xEBB1, 0x8C92, 0xEBB2, 0x8C93, 0xBFDF, 0x8C94, 0xEEB7,
+	0x8C95, 0xEEB6, 0x8C97, 0xF0F2, 0x8C98, 0xF0F1, 0x8C99, 0xF0F0,
+	0x8C9A, 0xF347, 0x8C9C, 0xF9AA, 0x8C9D, 0xA8A9, 0x8C9E, 0xAD73,
+	0x8CA0, 0xAD74, 0x8CA1, 0xB05D, 0x8CA2, 0xB05E, 0x8CA3, 0xD3E2,
+	0x8CA4, 0xD3E1, 0x8CA5, 0xD7D2, 0x8CA7, 0xB368, 0x8CA8, 0xB366,
+	0x8CA9, 0xB363, 0x8CAA, 0xB367, 0x8CAB, 0xB365, 0x8CAC, 0xB364,
+	0x8CAF, 0xB64A, 0x8CB0, 0xDBEA, 0x8CB2, 0xB8ED, 0x8CB3, 0xB64C,
+	0x8CB4, 0xB651, 0x8CB5, 0xDBEC, 0x8CB6, 0xB653, 0x8CB7, 0xB652,
+	0x8CB8, 0xB655, 0x8CB9, 0xDBEB, 0x8CBA, 0xDBE8, 0x8CBB, 0xB64F,
+	0x8CBC, 0xB64B, 0x8CBD, 0xB64D, 0x8CBE, 0xDBE9, 0x8CBF, 0xB654,
+	0x8CC0, 0xB650, 0x8CC1, 0xB64E, 0x8CC2, 0xB8EF, 0x8CC3, 0xB8EE,
+	0x8CC4, 0xB8EC, 0x8CC5, 0xB8F0, 0x8CC7, 0xB8EA, 0x8CC8, 0xB8EB,
+	0x8CCA, 0xB8E9, 0x8CCC, 0xE05B, 0x8CCF, 0xE454, 0x8CD1, 0xBBAC,
+	0x8CD2, 0xBBAD, 0x8CD3, 0xBBAB, 0x8CD5, 0xE453, 0x8CD7, 0xE455,
+	0x8CD9, 0xE7EA, 0x8CDA, 0xE7EC, 0x8CDC, 0xBDE7, 0x8CDD, 0xE7ED,
+	0x8CDE, 0xBDE0, 0x8CDF, 0xE7E9, 0x8CE0, 0xBDDF, 0x8CE1, 0xBDE9,
+	0x8CE2, 0xBDE5, 0x8CE3, 0xBDE6, 0x8CE4, 0xBDE2, 0x8CE5, 0xE7E8,
+	0x8CE6, 0xBDE1, 0x8CE7, 0xE7EE, 0x8CE8, 0xE7EB, 0x8CEA, 0xBDE8,
+	0x8CEC, 0xBDE3, 0x8CED, 0xBDE4, 0x8CEE, 0xEBB5, 0x8CF0, 0xEBB7,
+	0x8CF1, 0xEBB6, 0x8CF3, 0xEBB8, 0x8CF4, 0xBFE0, 0x8CF5, 0xEBB4,
+	0x8CF8, 0xC1CB, 0x8CF9, 0xEEB8, 0x8CFA, 0xC1C8, 0x8CFB, 0xC1CC,
+	0x8CFC, 0xC1CA, 0x8CFD, 0xC1C9, 0x8CFE, 0xF0F3, 0x8D00, 0xF0F6,
+	0x8D02, 0xF0F5, 0x8D04, 0xF0F4, 0x8D05, 0xC2D8, 0x8D06, 0xF348,
+	0x8D07, 0xF349, 0x8D08, 0xC3D8, 0x8D09, 0xF34A, 0x8D0A, 0xC3D9,
+	0x8D0D, 0xC4BA, 0x8D0F, 0xC4B9, 0x8D10, 0xF652, 0x8D13, 0xC542,
+	0x8D14, 0xF653, 0x8D15, 0xF75C, 0x8D16, 0xC5AB, 0x8D17, 0xC5AC,
+	0x8D19, 0xF845, 0x8D1B, 0xC642, 0x8D64, 0xA8AA, 0x8D66, 0xB36A,
+	0x8D67, 0xB369, 0x8D68, 0xE05C, 0x8D69, 0xE05D, 0x8D6B, 0xBBAE,
+	0x8D6C, 0xEBB9, 0x8D6D, 0xBDEA, 0x8D6E, 0xEBBA, 0x8D6F, 0xEEB9,
+	0x8D70, 0xA8AB, 0x8D72, 0xD0B2, 0x8D73, 0xAD76, 0x8D74, 0xAD75,
+	0x8D76, 0xD3E3, 0x8D77, 0xB05F, 0x8D78, 0xD3E4, 0x8D79, 0xD7D5,
+	0x8D7B, 0xD7D4, 0x8D7D, 0xD7D3, 0x8D80, 0xDBEE, 0x8D81, 0xB658,
+	0x8D84, 0xDBED, 0x8D85, 0xB657, 0x8D89, 0xDBEF, 0x8D8A, 0xB656,
+	0x8D8C, 0xE05F, 0x8D8D, 0xE062, 0x8D8E, 0xE060, 0x8D8F, 0xE061,
+	0x8D90, 0xE065, 0x8D91, 0xE05E, 0x8D92, 0xE066, 0x8D93, 0xE063,
+	0x8D94, 0xE064, 0x8D95, 0xBBB0, 0x8D96, 0xE456, 0x8D99, 0xBBAF,
+	0x8D9B, 0xE7F2, 0x8D9C, 0xE7F0, 0x8D9F, 0xBDEB, 0x8DA0, 0xE7EF,
+	0x8DA1, 0xE7F1, 0x8DA3, 0xBDEC, 0x8DA5, 0xEBBB, 0x8DA7, 0xEBBC,
+	0x8DA8, 0xC1CD, 0x8DAA, 0xF34C, 0x8DAB, 0xF34E, 0x8DAC, 0xF34B,
+	0x8DAD, 0xF34D, 0x8DAE, 0xF4D6, 0x8DAF, 0xF654, 0x8DB2, 0xF96F,
+	0x8DB3, 0xA8AC, 0x8DB4, 0xAD77, 0x8DB5, 0xD3E5, 0x8DB6, 0xD3E7,
+	0x8DB7, 0xD3E6, 0x8DB9, 0xD7D8, 0x8DBA, 0xB36C, 0x8DBC, 0xD7D6,
+	0x8DBE, 0xB36B, 0x8DBF, 0xD7D9, 0x8DC1, 0xD7DA, 0x8DC2, 0xD7D7,
+	0x8DC5, 0xDBFB, 0x8DC6, 0xB660, 0x8DC7, 0xDBF3, 0x8DC8, 0xDBF9,
+	0x8DCB, 0xB65B, 0x8DCC, 0xB65E, 0x8DCD, 0xDBF2, 0x8DCE, 0xB659,
+	0x8DCF, 0xDBF6, 0x8DD0, 0xE06C, 0x8DD1, 0xB65D, 0x8DD3, 0xDBF1,
+	0x8DD5, 0xDBF7, 0x8DD6, 0xDBF4, 0x8DD7, 0xDBFA, 0x8DD8, 0xDBF0,
+	0x8DD9, 0xDBF8, 0x8DDA, 0xB65C, 0x8DDB, 0xB65F, 0x8DDC, 0xDBF5,
+	0x8DDD, 0xB65A, 0x8DDF, 0xB8F2, 0x8DE0, 0xE068, 0x8DE1, 0xB8F1,
+	0x8DE2, 0xE06F, 0x8DE3, 0xE06E, 0x8DE4, 0xB8F8, 0x8DE6, 0xB8F9,
+	0x8DE7, 0xE070, 0x8DE8, 0xB8F3, 0x8DE9, 0xE06D, 0x8DEA, 0xB8F7,
+	0x8DEB, 0xE072, 0x8DEC, 0xE069, 0x8DEE, 0xE06B, 0x8DEF, 0xB8F4,
+	0x8DF0, 0xE067, 0x8DF1, 0xE06A, 0x8DF2, 0xE071, 0x8DF3, 0xB8F5,
+	0x8DF4, 0xE073, 0x8DFA, 0xB8F6, 0x8DFC, 0xBBB1, 0x8DFD, 0xE45B,
+	0x8DFE, 0xE461, 0x8DFF, 0xE459, 0x8E00, 0xE462, 0x8E02, 0xE458,
+	0x8E03, 0xE45D, 0x8E04, 0xE463, 0x8E05, 0xE460, 0x8E06, 0xE45F,
+	0x8E07, 0xE45E, 0x8E09, 0xE457, 0x8E0A, 0xE45C, 0x8E0D, 0xE45A,
+	0x8E0F, 0xBDF1, 0x8E10, 0xBDEE, 0x8E11, 0xE7FB, 0x8E12, 0xE841,
+	0x8E13, 0xE843, 0x8E14, 0xE840, 0x8E15, 0xE7F8, 0x8E16, 0xE7FA,
+	0x8E17, 0xE845, 0x8E18, 0xE842, 0x8E19, 0xE7FC, 0x8E1A, 0xE846,
+	0x8E1B, 0xE7F9, 0x8E1C, 0xE844, 0x8E1D, 0xBDEF, 0x8E1E, 0xBDF5,
+	0x8E1F, 0xBDF3, 0x8E20, 0xE7F3, 0x8E21, 0xBDF4, 0x8E22, 0xBDF0,
+	0x8E23, 0xE7F4, 0x8E24, 0xE7F6, 0x8E25, 0xE7F5, 0x8E26, 0xE7FD,
+	0x8E27, 0xE7FE, 0x8E29, 0xBDF2, 0x8E2B, 0xBDED, 0x8E2E, 0xE7F7,
+	0x8E30, 0xEBC6, 0x8E31, 0xBFE2, 0x8E33, 0xEBBD, 0x8E34, 0xBFE3,
+	0x8E35, 0xBFE6, 0x8E36, 0xEBC2, 0x8E38, 0xEBBF, 0x8E39, 0xBFE5,
+	0x8E3C, 0xEBC3, 0x8E3D, 0xEBC4, 0x8E3E, 0xEBBE, 0x8E3F, 0xEBC7,
+	0x8E40, 0xEBC0, 0x8E41, 0xEBC5, 0x8E42, 0xBFE4, 0x8E44, 0xBFE1,
+	0x8E45, 0xEBC1, 0x8E47, 0xEEBF, 0x8E48, 0xC1D0, 0x8E49, 0xC1CE,
+	0x8E4A, 0xC1D1, 0x8E4B, 0xC1CF, 0x8E4C, 0xEEBE, 0x8E4D, 0xEEBB,
+	0x8E4E, 0xEEBA, 0x8E50, 0xEEBD, 0x8E53, 0xEEBC, 0x8E54, 0xF145,
+	0x8E55, 0xC2DE, 0x8E56, 0xF0FB, 0x8E57, 0xF0FA, 0x8E59, 0xC2D9,
+	0x8E5A, 0xF141, 0x8E5B, 0xF140, 0x8E5C, 0xF0F7, 0x8E5D, 0xF143,
+	0x8E5E, 0xF0FC, 0x8E5F, 0xC2DD, 0x8E60, 0xF0F9, 0x8E61, 0xF142,
+	0x8E62, 0xF0F8, 0x8E63, 0xC2DA, 0x8E64, 0xC2DC, 0x8E65, 0xF0FD,
+	0x8E66, 0xC2DB, 0x8E67, 0xF0FE, 0x8E69, 0xF144, 0x8E6A, 0xF352,
+	0x8E6C, 0xC3DE, 0x8E6D, 0xF34F, 0x8E6F, 0xF353, 0x8E72, 0xC3DB,
+	0x8E73, 0xF351, 0x8E74, 0xC3E0, 0x8E76, 0xC3DD, 0x8E78, 0xF350,
+	0x8E7A, 0xC3DF, 0x8E7B, 0xF354, 0x8E7C, 0xC3DA, 0x8E81, 0xC4BC,
+	0x8E82, 0xC4BE, 0x8E84, 0xF4D9, 0x8E85, 0xC4BD, 0x8E86, 0xF4D7,
+	0x8E87, 0xC3DC, 0x8E88, 0xF4D8, 0x8E89, 0xC4BB, 0x8E8A, 0xC543,
+	0x8E8B, 0xC545, 0x8E8C, 0xF656, 0x8E8D, 0xC544, 0x8E8E, 0xF655,
+	0x8E90, 0xF761, 0x8E91, 0xC5AD, 0x8E92, 0xF760, 0x8E93, 0xC5AE,
+	0x8E94, 0xF75E, 0x8E95, 0xF75D, 0x8E96, 0xF762, 0x8E97, 0xF763,
+	0x8E98, 0xF846, 0x8E9A, 0xF75F, 0x8E9D, 0xF8C6, 0x8E9E, 0xF8C3,
+	0x8E9F, 0xF8C4, 0x8EA0, 0xF8C5, 0x8EA1, 0xC65C, 0x8EA3, 0xF951,
+	0x8EA4, 0xF950, 0x8EA5, 0xF94F, 0x8EA6, 0xF970, 0x8EA8, 0xF9BE,
+	0x8EA9, 0xF9AB, 0x8EAA, 0xC66E, 0x8EAB, 0xA8AD, 0x8EAC, 0xB060,
+	0x8EB2, 0xB8FA, 0x8EBA, 0xBDF6, 0x8EBD, 0xEBC8, 0x8EC0, 0xC2DF,
+	0x8EC2, 0xF355, 0x8EC9, 0xF9AC, 0x8ECA, 0xA8AE, 0x8ECB, 0xAAEE,
+	0x8ECC, 0xAD79, 0x8ECD, 0xAD78, 0x8ECF, 0xB063, 0x8ED1, 0xD3E8,
+	0x8ED2, 0xB061, 0x8ED3, 0xD3E9, 0x8ED4, 0xB062, 0x8ED7, 0xD7DF,
+	0x8ED8, 0xD7DB, 0x8EDB, 0xB36D, 0x8EDC, 0xD7DE, 0x8EDD, 0xD7DD,
+	0x8EDE, 0xD7DC, 0x8EDF, 0xB36E, 0x8EE0, 0xD7E0, 0x8EE1, 0xD7E1,
+	0x8EE5, 0xDC43, 0x8EE6, 0xDC41, 0x8EE7, 0xDC45, 0x8EE8, 0xDC46,
+	0x8EE9, 0xDC4C, 0x8EEB, 0xDC48, 0x8EEC, 0xDC4A, 0x8EEE, 0xDC42,
+	0x8EEF, 0xDBFC, 0x8EF1, 0xDC49, 0x8EF4, 0xDC4B, 0x8EF5, 0xDC44,
+	0x8EF6, 0xDC47, 0x8EF7, 0xDBFD, 0x8EF8, 0xB662, 0x8EF9, 0xDC40,
+	0x8EFA, 0xDBFE, 0x8EFB, 0xB661, 0x8EFC, 0xB663, 0x8EFE, 0xB8FD,
+	0x8EFF, 0xE075, 0x8F00, 0xE077, 0x8F01, 0xE076, 0x8F02, 0xE07B,
+	0x8F03, 0xB8FB, 0x8F05, 0xE078, 0x8F06, 0xE074, 0x8F07, 0xE079,
+	0x8F08, 0xE07A, 0x8F09, 0xB8FC, 0x8F0A, 0xB8FE, 0x8F0B, 0xE07C,
+	0x8F0D, 0xE467, 0x8F0E, 0xE466, 0x8F10, 0xE464, 0x8F11, 0xE465,
+	0x8F12, 0xBBB3, 0x8F13, 0xBBB5, 0x8F14, 0xBBB2, 0x8F15, 0xBBB4,
+	0x8F16, 0xE84D, 0x8F17, 0xE84E, 0x8F18, 0xE849, 0x8F1A, 0xE84A,
+	0x8F1B, 0xBDF8, 0x8F1C, 0xBDFD, 0x8F1D, 0xBDF7, 0x8F1E, 0xBDFE,
+	0x8F1F, 0xBDF9, 0x8F20, 0xE84B, 0x8F23, 0xE84C, 0x8F24, 0xE848,
+	0x8F25, 0xBE40, 0x8F26, 0xBDFB, 0x8F29, 0xBDFA, 0x8F2A, 0xBDFC,
+	0x8F2C, 0xE847, 0x8F2E, 0xEBCA, 0x8F2F, 0xBFE8, 0x8F32, 0xEBCC,
+	0x8F33, 0xBFEA, 0x8F34, 0xEBCF, 0x8F35, 0xEBCB, 0x8F36, 0xEBC9,
+	0x8F37, 0xEBCE, 0x8F38, 0xBFE9, 0x8F39, 0xEBCD, 0x8F3B, 0xBFE7,
+	0x8F3E, 0xC1D3, 0x8F3F, 0xC1D6, 0x8F40, 0xEEC1, 0x8F42, 0xC1D4,
+	0x8F43, 0xEEC0, 0x8F44, 0xC1D2, 0x8F45, 0xC1D5, 0x8F46, 0xF146,
+	0x8F47, 0xF147, 0x8F48, 0xF148, 0x8F49, 0xC2E0, 0x8F4B, 0xF149,
+	0x8F4D, 0xC2E1, 0x8F4E, 0xC3E2, 0x8F4F, 0xF358, 0x8F50, 0xF359,
+	0x8F51, 0xF357, 0x8F52, 0xF356, 0x8F53, 0xF35A, 0x8F54, 0xC3E1,
+	0x8F55, 0xF4DD, 0x8F56, 0xF4DB, 0x8F57, 0xF4DC, 0x8F58, 0xF4DE,
+	0x8F59, 0xF4DA, 0x8F5A, 0xF4DF, 0x8F5B, 0xF658, 0x8F5D, 0xF659,
+	0x8F5E, 0xF657, 0x8F5F, 0xC546, 0x8F60, 0xF764, 0x8F61, 0xC5AF,
+	0x8F62, 0xF765, 0x8F63, 0xF848, 0x8F64, 0xF847, 0x8F9B, 0xA8AF,
+	0x8F9C, 0xB664, 0x8F9F, 0xB940, 0x8FA3, 0xBBB6, 0x8FA6, 0xBFEC,
+	0x8FA8, 0xBFEB, 0x8FAD, 0xC3E3, 0x8FAE, 0xC47C, 0x8FAF, 0xC547,
+	0x8FB0, 0xA8B0, 0x8FB1, 0xB064, 0x8FB2, 0xB941, 0x8FB4, 0xF35B,
+	0x8FBF, 0xCBA6, 0x8FC2, 0xA8B1, 0x8FC4, 0xA8B4, 0x8FC5, 0xA8B3,
+	0x8FC6, 0xA8B2, 0x8FC9, 0xCBA5, 0x8FCB, 0xCDCD, 0x8FCD, 0xCDCF,
+	0x8FCE, 0xAAEF, 0x8FD1, 0xAAF1, 0x8FD2, 0xCDCC, 0x8FD3, 0xCDCE,
+	0x8FD4, 0xAAF0, 0x8FD5, 0xCDD1, 0x8FD6, 0xCDD0, 0x8FD7, 0xCDD2,
+	0x8FE0, 0xD0B6, 0x8FE1, 0xD0B4, 0x8FE2, 0xAD7C, 0x8FE3, 0xD0B3,
+	0x8FE4, 0xADA3, 0x8FE5, 0xAD7E, 0x8FE6, 0xAD7B, 0x8FE8, 0xADA4,
+	0x8FEA, 0xAD7D, 0x8FEB, 0xADA2, 0x8FED, 0xADA1, 0x8FEE, 0xD0B5,
+	0x8FF0, 0xAD7A, 0x8FF4, 0xB06A, 0x8FF5, 0xD3EB, 0x8FF6, 0xD3F1,
+	0x8FF7, 0xB067, 0x8FF8, 0xB06E, 0x8FFA, 0xB069, 0x8FFB, 0xD3EE,
+	0x8FFC, 0xD3F0, 0x8FFD, 0xB06C, 0x8FFE, 0xD3EA, 0x8FFF, 0xD3ED,
+	0x9000, 0xB068, 0x9001, 0xB065, 0x9002, 0xD3EC, 0x9003, 0xB06B,
+	0x9004, 0xD3EF, 0x9005, 0xB06D, 0x9006, 0xB066, 0x900B, 0xD7E3,
+	0x900C, 0xD7E6, 0x900D, 0xB370, 0x900F, 0xB37A, 0x9010, 0xB376,
+	0x9011, 0xD7E4, 0x9014, 0xB37E, 0x9015, 0xB377, 0x9016, 0xB37C,
+	0x9017, 0xB372, 0x9019, 0xB36F, 0x901A, 0xB371, 0x901B, 0xB37D,
+	0x901C, 0xD7E5, 0x901D, 0xB375, 0x901E, 0xB378, 0x901F, 0xB374,
+	0x9020, 0xB379, 0x9021, 0xD7E7, 0x9022, 0xB37B, 0x9023, 0xB373,
+	0x9024, 0xD7E2, 0x902D, 0xDC4D, 0x902E, 0xB665, 0x902F, 0xDC4F,
+	0x9031, 0xB667, 0x9032, 0xB669, 0x9034, 0xDC4E, 0x9035, 0xB666,
+	0x9036, 0xB66A, 0x9038, 0xB668, 0x903C, 0xB947, 0x903D, 0xE0A3,
+	0x903E, 0xB94F, 0x903F, 0xE07E, 0x9041, 0xB950, 0x9042, 0xB945,
+	0x9044, 0xE0A1, 0x9047, 0xB94A, 0x9049, 0xE0A2, 0x904A, 0xB943,
+	0x904B, 0xB942, 0x904D, 0xB94D, 0x904E, 0xB94C, 0x904F, 0xB94B,
+	0x9050, 0xB949, 0x9051, 0xB94E, 0x9052, 0xE07D, 0x9053, 0xB944,
+	0x9054, 0xB946, 0x9055, 0xB948, 0x9058, 0xBBB8, 0x9059, 0xBBBB,
+	0x905B, 0xBBBF, 0x905C, 0xBBB9, 0x905D, 0xBBBE, 0x905E, 0xBBBC,
+	0x9060, 0xBBB7, 0x9062, 0xBBBD, 0x9063, 0xBBBA, 0x9067, 0xE852,
+	0x9068, 0xBE43, 0x9069, 0xBE41, 0x906B, 0xE853, 0x906D, 0xBE44,
+	0x906E, 0xBE42, 0x906F, 0xE851, 0x9070, 0xE850, 0x9072, 0xBFF0,
+	0x9073, 0xE84F, 0x9074, 0xBFEE, 0x9075, 0xBFED, 0x9076, 0xEBD0,
+	0x9077, 0xBE45, 0x9078, 0xBFEF, 0x9079, 0xEBD1, 0x907A, 0xBFF2,
+	0x907B, 0xEBD2, 0x907C, 0xBFF1, 0x907D, 0xC1D8, 0x907E, 0xEEC3,
+	0x907F, 0xC1D7, 0x9080, 0xC1DC, 0x9081, 0xC1DA, 0x9082, 0xC1DB,
+	0x9083, 0xC2E3, 0x9084, 0xC1D9, 0x9085, 0xEEC2, 0x9086, 0xEBD3,
+	0x9087, 0xC2E2, 0x9088, 0xC2E4, 0x908A, 0xC3E4, 0x908B, 0xC3E5,
+	0x908D, 0xF4E0, 0x908F, 0xC5DE, 0x9090, 0xC5DD, 0x9091, 0xA8B6,
+	0x9094, 0xCA55, 0x9095, 0xB06F, 0x9097, 0xCA52, 0x9098, 0xCA53,
+	0x9099, 0xCA51, 0x909B, 0xCA54, 0x909E, 0xCBAA, 0x909F, 0xCBA7,
+	0x90A0, 0xCBAC, 0x90A1, 0xCBA8, 0x90A2, 0xA8B7, 0x90A3, 0xA8BA,
+	0x90A5, 0xCBA9, 0x90A6, 0xA8B9, 0x90A7, 0xCBAB, 0x90AA, 0xA8B8,
+	0x90AF, 0xCDD5, 0x90B0, 0xCDD7, 0x90B1, 0xAAF4, 0x90B2, 0xCDD3,
+	0x90B3, 0xCDD6, 0x90B4, 0xCDD4, 0x90B5, 0xAAF2, 0x90B6, 0xAAF5,
+	0x90B8, 0xAAF3, 0x90BD, 0xD0B8, 0x90BE, 0xD0BC, 0x90BF, 0xD0B9,
+	0x90C1, 0xADA7, 0x90C3, 0xADA8, 0x90C5, 0xD0BB, 0x90C7, 0xD0BD,
+	0x90C8, 0xD0BF, 0x90CA, 0xADA5, 0x90CB, 0xD0BE, 0x90CE, 0xADA6,
+	0x90D4, 0xD7EE, 0x90D5, 0xD0BA, 0x90D6, 0xD3F2, 0x90D7, 0xD3FB,
+	0x90D8, 0xD3F9, 0x90D9, 0xD3F4, 0x90DA, 0xD3F5, 0x90DB, 0xD3FA,
+	0x90DC, 0xD3FC, 0x90DD, 0xB071, 0x90DF, 0xD3F7, 0x90E0, 0xD3F3,
+	0x90E1, 0xB070, 0x90E2, 0xB072, 0x90E3, 0xD3F6, 0x90E4, 0xD3FD,
+	0x90E5, 0xD3F8, 0x90E8, 0xB3A1, 0x90E9, 0xD7F1, 0x90EA, 0xD7E9,
+	0x90EB, 0xD7EF, 0x90EC, 0xD7F0, 0x90ED, 0xB3A2, 0x90EF, 0xD7E8,
+	0x90F0, 0xD7EA, 0x90F1, 0xD0B7, 0x90F2, 0xD7EC, 0x90F3, 0xD7ED,
+	0x90F4, 0xD7EB, 0x90F5, 0xB66C, 0x90F9, 0xDC56, 0x90FA, 0xEBD4,
+	0x90FB, 0xDC57, 0x90FC, 0xDC54, 0x90FD, 0xB3A3, 0x90FE, 0xB66E,
+	0x90FF, 0xDC53, 0x9100, 0xDC59, 0x9101, 0xDC58, 0x9102, 0xB66B,
+	0x9103, 0xDC5C, 0x9104, 0xDC52, 0x9105, 0xDC5B, 0x9106, 0xDC50,
+	0x9107, 0xDC5A, 0x9108, 0xDC55, 0x9109, 0xB66D, 0x910B, 0xE0AA,
+	0x910D, 0xE0A5, 0x910E, 0xE0AB, 0x910F, 0xE0A6, 0x9110, 0xE0A4,
+	0x9111, 0xE0A7, 0x9112, 0xB951, 0x9114, 0xE0A9, 0x9116, 0xE0A8,
+	0x9117, 0xB952, 0x9118, 0xBBC1, 0x9119, 0xBBC0, 0x911A, 0xE46E,
+	0x911B, 0xE471, 0x911C, 0xE469, 0x911D, 0xE46D, 0x911E, 0xBBC2,
+	0x911F, 0xE46C, 0x9120, 0xE46A, 0x9121, 0xE470, 0x9122, 0xE46B,
+	0x9123, 0xE468, 0x9124, 0xE46F, 0x9126, 0xE859, 0x9127, 0xBE48,
+	0x9128, 0xF14A, 0x9129, 0xE856, 0x912A, 0xE857, 0x912B, 0xE855,
+	0x912C, 0xDC51, 0x912D, 0xBE47, 0x912E, 0xE85A, 0x912F, 0xE854,
+	0x9130, 0xBE46, 0x9131, 0xBE49, 0x9132, 0xE858, 0x9133, 0xEBD5,
+	0x9134, 0xBFF3, 0x9135, 0xEBD6, 0x9136, 0xEBD7, 0x9138, 0xEEC4,
+	0x9139, 0xC1DD, 0x913A, 0xF14B, 0x913B, 0xF14C, 0x913E, 0xF14D,
+	0x913F, 0xF35D, 0x9140, 0xF35C, 0x9141, 0xF4E2, 0x9143, 0xF4E1,
+	0x9144, 0xF65B, 0x9145, 0xF65C, 0x9146, 0xF65A, 0x9147, 0xF766,
+	0x9148, 0xC5B0, 0x9149, 0xA8BB, 0x914A, 0xADAA, 0x914B, 0xADA9,
+	0x914C, 0xB075, 0x914D, 0xB074, 0x914E, 0xD440, 0x914F, 0xD441,
+	0x9150, 0xD3FE, 0x9152, 0xB073, 0x9153, 0xD7F5, 0x9155, 0xD7F6,
+	0x9156, 0xD7F2, 0x9157, 0xB3A4, 0x9158, 0xD7F3, 0x915A, 0xD7F4,
+	0x915F, 0xDC5F, 0x9160, 0xDC61, 0x9161, 0xDC5D, 0x9162, 0xDC60,
+	0x9163, 0xB66F, 0x9164, 0xDC5E, 0x9165, 0xB670, 0x9168, 0xDD73,
+	0x9169, 0xB955, 0x916A, 0xB954, 0x916C, 0xB953, 0x916E, 0xE0AC,
+	0x916F, 0xE0AD, 0x9172, 0xE473, 0x9173, 0xE475, 0x9174, 0xBBC6,
+	0x9175, 0xBBC3, 0x9177, 0xBBC5, 0x9178, 0xBBC4, 0x9179, 0xE474,
+	0x917A, 0xE472, 0x9180, 0xE861, 0x9181, 0xE85E, 0x9182, 0xE85F,
+	0x9183, 0xBE4D, 0x9184, 0xE860, 0x9185, 0xE85B, 0x9186, 0xE85C,
+	0x9187, 0xBE4A, 0x9189, 0xBE4B, 0x918A, 0xE85D, 0x918B, 0xBE4C,
+	0x918D, 0xEBDB, 0x918F, 0xEBDC, 0x9190, 0xEBD9, 0x9191, 0xEBDA,
+	0x9192, 0xBFF4, 0x9193, 0xEBD8, 0x9199, 0xEEC8, 0x919A, 0xEEC5,
+	0x919B, 0xEEC7, 0x919C, 0xC1E0, 0x919D, 0xEECB, 0x919E, 0xC1DF,
+	0x919F, 0xEEC9, 0x91A0, 0xEECC, 0x91A1, 0xEECA, 0x91A2, 0xEEC6,
+	0x91A3, 0xC1DE, 0x91A5, 0xF14F, 0x91A7, 0xF150, 0x91A8, 0xF14E,
+	0x91AA, 0xF152, 0x91AB, 0xC2E5, 0x91AC, 0xC2E6, 0x91AD, 0xF35F,
+	0x91AE, 0xC3E7, 0x91AF, 0xF151, 0x91B0, 0xF35E, 0x91B1, 0xC3E6,
+	0x91B2, 0xF4E5, 0x91B3, 0xF4E6, 0x91B4, 0xC4BF, 0x91B5, 0xF4E4,
+	0x91B7, 0xF4E3, 0x91B9, 0xF65D, 0x91BA, 0xC548, 0x91BC, 0xF849,
+	0x91BD, 0xF8C8, 0x91BE, 0xF8C7, 0x91C0, 0xC643, 0x91C1, 0xC65D,
+	0x91C2, 0xF8C9, 0x91C3, 0xF971, 0x91C5, 0xC66F, 0x91C6, 0xA8BC,
+	0x91C7, 0xAAF6, 0x91C9, 0xB956, 0x91CB, 0xC4C0, 0x91CC, 0xA8BD,
+	0x91CD, 0xADAB, 0x91CE, 0xB3A5, 0x91CF, 0xB671, 0x91D0, 0xC2E7,
+	0x91D1, 0xAAF7, 0x91D3, 0xD0C1, 0x91D4, 0xD0C0, 0x91D5, 0xD442,
+	0x91D7, 0xB078, 0x91D8, 0xB076, 0x91D9, 0xB07A, 0x91DA, 0xD444,
+	0x91DC, 0xB079, 0x91DD, 0xB077, 0x91E2, 0xD443, 0x91E3, 0xB3A8,
+	0x91E4, 0xD7FC, 0x91E6, 0xB3A7, 0x91E7, 0xB3A9, 0x91E8, 0xD842,
+	0x91E9, 0xB3AB, 0x91EA, 0xD7FE, 0x91EB, 0xD840, 0x91EC, 0xD7F7,
+	0x91ED, 0xB3AA, 0x91EE, 0xD843, 0x91F1, 0xD7F9, 0x91F3, 0xD7FA,
+	0x91F4, 0xD7F8, 0x91F5, 0xB3A6, 0x91F7, 0xD841, 0x91F8, 0xD7FB,
+	0x91F9, 0xD7FD, 0x91FD, 0xDC6D, 0x91FF, 0xDC6C, 0x9200, 0xDC6A,
+	0x9201, 0xDC62, 0x9202, 0xDC71, 0x9203, 0xDC65, 0x9204, 0xDC6F,
+	0x9205, 0xDC76, 0x9206, 0xDC6E, 0x9207, 0xB679, 0x9209, 0xB675,
+	0x920A, 0xDC63, 0x920C, 0xDC69, 0x920D, 0xB677, 0x920F, 0xDC68,
+	0x9210, 0xB678, 0x9211, 0xB67A, 0x9212, 0xDC6B, 0x9214, 0xB672,
+	0x9215, 0xB673, 0x9216, 0xDC77, 0x9217, 0xDC75, 0x9219, 0xDC74,
+	0x921A, 0xDC66, 0x921C, 0xDC72, 0x921E, 0xB676, 0x9223, 0xB674,
+	0x9224, 0xDC73, 0x9225, 0xDC64, 0x9226, 0xDC67, 0x9227, 0xDC70,
+	0x922D, 0xE4BA, 0x922E, 0xE0B7, 0x9230, 0xE0B0, 0x9231, 0xE0C3,
+	0x9232, 0xE0CC, 0x9233, 0xE0B3, 0x9234, 0xB961, 0x9236, 0xE0C0,
+	0x9237, 0xB957, 0x9238, 0xB959, 0x9239, 0xB965, 0x923A, 0xE0B1,
+	0x923D, 0xB95A, 0x923E, 0xB95C, 0x923F, 0xB966, 0x9240, 0xB95B,
+	0x9245, 0xB964, 0x9246, 0xE0B9, 0x9248, 0xE0AE, 0x9249, 0xB962,
+	0x924A, 0xE0B8, 0x924B, 0xB95E, 0x924C, 0xE0CA, 0x924D, 0xB963,
+	0x924E, 0xE0C8, 0x924F, 0xE0BC, 0x9250, 0xE0C6, 0x9251, 0xB960,
+	0x9252, 0xE0AF, 0x9253, 0xE0C9, 0x9254, 0xE0C4, 0x9256, 0xE0CB,
+	0x9257, 0xB958, 0x925A, 0xB967, 0x925B, 0xB95D, 0x925E, 0xE0B5,
+	0x9260, 0xE0BD, 0x9261, 0xE0C1, 0x9263, 0xE0C5, 0x9264, 0xB95F,
+	0x9265, 0xE0B4, 0x9266, 0xE0B2, 0x9267, 0xE0BE, 0x926C, 0xE0BB,
+	0x926D, 0xE0BA, 0x926F, 0xE0BF, 0x9270, 0xE0C2, 0x9272, 0xE0C7,
+	0x9276, 0xE478, 0x9278, 0xBBC7, 0x9279, 0xE4A4, 0x927A, 0xE47A,
+	0x927B, 0xBBCC, 0x927C, 0xBBD0, 0x927D, 0xE4AD, 0x927E, 0xE4B5,
+	0x927F, 0xE4A6, 0x9280, 0xBBC8, 0x9282, 0xE4AA, 0x9283, 0xE0B6,
+	0x9285, 0xBBC9, 0x9286, 0xE4B1, 0x9287, 0xE4B6, 0x9288, 0xE4AE,
+	0x928A, 0xE4B0, 0x928B, 0xE4B9, 0x928C, 0xE4B2, 0x928D, 0xE47E,
+	0x928E, 0xE4A9, 0x9291, 0xBBD1, 0x9293, 0xBBCD, 0x9294, 0xE47C,
+	0x9295, 0xE4AB, 0x9296, 0xBBCB, 0x9297, 0xE4A5, 0x9298, 0xBBCA,
+	0x9299, 0xE4B3, 0x929A, 0xE4A2, 0x929B, 0xE479, 0x929C, 0xBBCE,
+	0x929D, 0xE4B8, 0x92A0, 0xE47B, 0x92A1, 0xE4AF, 0x92A2, 0xE4AC,
+	0x92A3, 0xE4A7, 0x92A4, 0xE477, 0x92A5, 0xE476, 0x92A6, 0xE4A1,
+	0x92A7, 0xE4B4, 0x92A8, 0xBBCF, 0x92A9, 0xE4B7, 0x92AA, 0xE47D,
+	0x92AB, 0xE4A3, 0x92AC, 0xBE52, 0x92B2, 0xBE5A, 0x92B3, 0xBE55,
+	0x92B4, 0xE8A4, 0x92B5, 0xE8A1, 0x92B6, 0xE867, 0x92B7, 0xBE50,
+	0x92B9, 0xF9D7, 0x92BB, 0xBE4F, 0x92BC, 0xBE56, 0x92C0, 0xE865,
+	0x92C1, 0xBE54, 0x92C2, 0xE871, 0x92C3, 0xE863, 0x92C4, 0xE864,
+	0x92C5, 0xBE4E, 0x92C6, 0xE8A3, 0x92C7, 0xBE58, 0x92C8, 0xE874,
+	0x92C9, 0xE879, 0x92CA, 0xE873, 0x92CB, 0xEBEE, 0x92CC, 0xE86F,
+	0x92CD, 0xE877, 0x92CE, 0xE875, 0x92CF, 0xE868, 0x92D0, 0xE862,
+	0x92D1, 0xE87D, 0x92D2, 0xBE57, 0x92D3, 0xE87E, 0x92D5, 0xE878,
+	0x92D7, 0xE86D, 0x92D8, 0xE86B, 0x92D9, 0xE866, 0x92DD, 0xE86E,
+	0x92DE, 0xE87B, 0x92DF, 0xE86A, 0x92E0, 0xE87A, 0x92E1, 0xE8A2,
+	0x92E4, 0xBE53, 0x92E6, 0xE876, 0x92E7, 0xE87C, 0x92E8, 0xE872,
+	0x92E9, 0xE86C, 0x92EA, 0xBE51, 0x92EE, 0xE4A8, 0x92EF, 0xE870,
+	0x92F0, 0xBE59, 0x92F1, 0xE869, 0x92F7, 0xEBF4, 0x92F8, 0xBFF7,
+	0x92F9, 0xEBF3, 0x92FA, 0xEBF0, 0x92FB, 0xEC44, 0x92FC, 0xBFFB,
+	0x92FE, 0xEC41, 0x92FF, 0xEBF8, 0x9300, 0xEC43, 0x9301, 0xEBE9,
+	0x9302, 0xEBF6, 0x9304, 0xBFFD, 0x9306, 0xEBE1, 0x9308, 0xEBDF,
+	0x9309, 0xEC42, 0x930B, 0xEC40, 0x930C, 0xEBFE, 0x930D, 0xEBED,
+	0x930E, 0xEBEC, 0x930F, 0xEBE2, 0x9310, 0xC040, 0x9312, 0xEBE8,
+	0x9313, 0xEBF2, 0x9314, 0xEBFD, 0x9315, 0xC043, 0x9316, 0xEC45,
+	0x9318, 0xC1E8, 0x9319, 0xC045, 0x931A, 0xBFFE, 0x931B, 0xEBE6,
+	0x931D, 0xEBEF, 0x931E, 0xEBDE, 0x931F, 0xEBE0, 0x9320, 0xBFF5,
+	0x9321, 0xC042, 0x9322, 0xBFFA, 0x9323, 0xEBE7, 0x9324, 0xEBF7,
+	0x9325, 0xEBF1, 0x9326, 0xC041, 0x9327, 0xEBDD, 0x9328, 0xC1E3,
+	0x9329, 0xEBF9, 0x932A, 0xEBFC, 0x932B, 0xBFFC, 0x932D, 0xEBEB,
+	0x932E, 0xC044, 0x932F, 0xBFF9, 0x9333, 0xBFF8, 0x9334, 0xEBF5,
+	0x9335, 0xEBFB, 0x9336, 0xBFF6, 0x9338, 0xEBE4, 0x9339, 0xEBFA,
+	0x933C, 0xEBE5, 0x9346, 0xEBEA, 0x9347, 0xEED2, 0x9349, 0xEED7,
+	0x934A, 0xC1E5, 0x934B, 0xC1E7, 0x934C, 0xEEDD, 0x934D, 0xC1E1,
+	0x934E, 0xEEEC, 0x934F, 0xEEE3, 0x9350, 0xEED8, 0x9351, 0xEED9,
+	0x9352, 0xEEE2, 0x9354, 0xC1EE, 0x9355, 0xEEE1, 0x9356, 0xEED1,
+	0x9357, 0xEEE0, 0x9358, 0xEED4, 0x9359, 0xEEED, 0x935A, 0xC1ED,
+	0x935B, 0xC1EB, 0x935C, 0xEED5, 0x935E, 0xEEE8, 0x9360, 0xEEDA,
+	0x9361, 0xEEE7, 0x9363, 0xEEE9, 0x9364, 0xEED0, 0x9365, 0xC1E6,
+	0x9367, 0xEEEA, 0x936A, 0xEEDE, 0x936C, 0xC1EA, 0x936D, 0xEEDB,
+	0x9370, 0xC1EC, 0x9371, 0xEEE4, 0x9375, 0xC1E4, 0x9376, 0xEED6,
+	0x9377, 0xEEE5, 0x9379, 0xEEDF, 0x937A, 0xEBE3, 0x937B, 0xEEE6,
+	0x937C, 0xEED3, 0x937E, 0xC1E9, 0x9380, 0xEEEB, 0x9382, 0xC1E2,
+	0x9383, 0xEECE, 0x9388, 0xF160, 0x9389, 0xF159, 0x938A, 0xC2E9,
+	0x938C, 0xF154, 0x938D, 0xF163, 0x938E, 0xF15B, 0x938F, 0xEEDC,
+	0x9391, 0xF165, 0x9392, 0xF155, 0x9394, 0xC2E8, 0x9395, 0xF15F,
+	0x9396, 0xC2EA, 0x9397, 0xC2F2, 0x9398, 0xC2F0, 0x9399, 0xF161,
+	0x939A, 0xC2F1, 0x939B, 0xF157, 0x939D, 0xF158, 0x939E, 0xF15D,
+	0x939F, 0xF162, 0x93A1, 0xEECD, 0x93A2, 0xC2EB, 0x93A3, 0xF16A,
+	0x93A4, 0xF167, 0x93A5, 0xF16B, 0x93A6, 0xF15E, 0x93A7, 0xF15A,
+	0x93A8, 0xF168, 0x93A9, 0xF36A, 0x93AA, 0xF15C, 0x93AC, 0xC2EE,
+	0x93AE, 0xC2ED, 0x93AF, 0xEECF, 0x93B0, 0xC2EF, 0x93B1, 0xF164,
+	0x93B2, 0xF166, 0x93B3, 0xC2EC, 0x93B4, 0xF169, 0x93B5, 0xF153,
+	0x93B7, 0xF156, 0x93C0, 0xF373, 0x93C2, 0xF363, 0x93C3, 0xC3EB,
+	0x93C4, 0xF371, 0x93C7, 0xF361, 0x93C8, 0xC3EC, 0x93CA, 0xF36C,
+	0x93CC, 0xF368, 0x93CD, 0xC3F1, 0x93CE, 0xF372, 0x93CF, 0xF362,
+	0x93D0, 0xF365, 0x93D1, 0xC3E9, 0x93D2, 0xF374, 0x93D4, 0xF36D,
+	0x93D5, 0xF370, 0x93D6, 0xC3EF, 0x93D7, 0xC3F4, 0x93D8, 0xC3F2,
+	0x93D9, 0xF369, 0x93DA, 0xF364, 0x93DC, 0xC3ED, 0x93DD, 0xC3EE,
+	0x93DE, 0xF360, 0x93DF, 0xC3EA, 0x93E1, 0xC3E8, 0x93E2, 0xC3F0,
+	0x93E3, 0xF36F, 0x93E4, 0xC3F3, 0x93E6, 0xF36B, 0x93E7, 0xF375,
+	0x93E8, 0xC3F5, 0x93EC, 0xF367, 0x93EE, 0xF36E, 0x93F5, 0xF4F3,
+	0x93F6, 0xF542, 0x93F7, 0xF4F5, 0x93F8, 0xF4FC, 0x93F9, 0xF366,
+	0x93FA, 0xF4FA, 0x93FB, 0xF4E9, 0x93FC, 0xF540, 0x93FD, 0xC4C3,
+	0x93FE, 0xF4ED, 0x93FF, 0xF4FE, 0x9400, 0xF4F4, 0x9403, 0xC4C2,
+	0x9406, 0xF544, 0x9407, 0xF4F6, 0x9409, 0xF4FB, 0x940A, 0xF4FD,
+	0x940B, 0xF4E7, 0x940C, 0xF541, 0x940D, 0xF4F2, 0x940E, 0xF4F7,
+	0x940F, 0xF4EB, 0x9410, 0xF4EF, 0x9411, 0xF543, 0x9412, 0xF4F9,
+	0x9413, 0xF4E8, 0x9414, 0xF4EC, 0x9415, 0xF4EE, 0x9416, 0xF4F8,
+	0x9418, 0xC4C1, 0x9419, 0xF4F1, 0x9420, 0xF4EA, 0x9428, 0xF4F0,
+	0x9429, 0xF661, 0x942A, 0xF666, 0x942B, 0xC54F, 0x942C, 0xF668,
+	0x942E, 0xC549, 0x9430, 0xF664, 0x9431, 0xF66A, 0x9432, 0xC54E,
+	0x9433, 0xC54A, 0x9435, 0xC54B, 0x9436, 0xF660, 0x9437, 0xF667,
+	0x9438, 0xC54D, 0x9439, 0xF665, 0x943A, 0xC54C, 0x943B, 0xF65F,
+	0x943C, 0xF663, 0x943D, 0xF662, 0x943F, 0xF65E, 0x9440, 0xF669,
+	0x9444, 0xC5B1, 0x9445, 0xF76D, 0x9446, 0xF770, 0x9447, 0xF76C,
+	0x9448, 0xF76E, 0x9449, 0xF76F, 0x944A, 0xF769, 0x944B, 0xF76A,
+	0x944C, 0xF767, 0x944F, 0xF76B, 0x9450, 0xF768, 0x9451, 0xC5B2,
+	0x9452, 0xC5B3, 0x9455, 0xF84B, 0x9457, 0xF84D, 0x945D, 0xF84C,
+	0x945E, 0xF84E, 0x9460, 0xC5E0, 0x9462, 0xF84A, 0x9463, 0xC5DF,
+	0x9464, 0xC5E1, 0x9468, 0xF8CB, 0x9469, 0xF8CC, 0x946A, 0xC644,
+	0x946B, 0xF8CA, 0x946D, 0xF953, 0x946E, 0xF952, 0x946F, 0xF954,
+	0x9470, 0xC65F, 0x9471, 0xF955, 0x9472, 0xC65E, 0x9473, 0xF956,
+	0x9474, 0xF972, 0x9475, 0xF975, 0x9476, 0xF974, 0x9477, 0xC668,
+	0x9478, 0xF973, 0x947C, 0xC672, 0x947D, 0xC670, 0x947E, 0xC671,
+	0x947F, 0xC677, 0x9480, 0xF9C0, 0x9481, 0xF9C1, 0x9482, 0xF9BF,
+	0x9483, 0xF9C9, 0x9577, 0xAAF8, 0x957A, 0xD844, 0x957B, 0xDC78,
+	0x957C, 0xE8A5, 0x957D, 0xF376, 0x9580, 0xAAF9, 0x9582, 0xADAC,
+	0x9583, 0xB07B, 0x9586, 0xD845, 0x9588, 0xD846, 0x9589, 0xB3AC,
+	0x958B, 0xB67D, 0x958C, 0xDC7A, 0x958D, 0xDC79, 0x958E, 0xB6A3,
+	0x958F, 0xB67C, 0x9590, 0xDC7B, 0x9591, 0xB67E, 0x9592, 0xB6A2,
+	0x9593, 0xB6A1, 0x9594, 0xB67B, 0x9598, 0xB968, 0x959B, 0xE0D0,
+	0x959C, 0xE0CE, 0x959E, 0xE0CF, 0x959F, 0xE0CD, 0x95A1, 0xBBD2,
+	0x95A3, 0xBBD5, 0x95A4, 0xBBD7, 0x95A5, 0xBBD6, 0x95A8, 0xBBD3,
+	0x95A9, 0xBBD4, 0x95AB, 0xE8A7, 0x95AC, 0xE8A6, 0x95AD, 0xBE5B,
+	0x95AE, 0xE8A8, 0x95B0, 0xE8A9, 0x95B1, 0xBE5C, 0x95B5, 0xEC4D,
+	0x95B6, 0xEC4B, 0x95B7, 0xEEF3, 0x95B9, 0xEC49, 0x95BA, 0xEC4A,
+	0x95BB, 0xC046, 0x95BC, 0xEC46, 0x95BD, 0xEC4E, 0x95BE, 0xEC48,
+	0x95BF, 0xEC4C, 0x95C0, 0xEEEF, 0x95C3, 0xEEF1, 0x95C5, 0xEEF2,
+	0x95C6, 0xC1F3, 0x95C7, 0xEEEE, 0x95C8, 0xC1F2, 0x95C9, 0xEEF0,
+	0x95CA, 0xC1EF, 0x95CB, 0xC1F0, 0x95CC, 0xC1F1, 0x95CD, 0xEC47,
+	0x95D0, 0xC2F5, 0x95D1, 0xF16E, 0x95D2, 0xF16C, 0x95D3, 0xF16D,
+	0x95D4, 0xC2F3, 0x95D5, 0xC2F6, 0x95D6, 0xC2F4, 0x95DA, 0xF377,
+	0x95DB, 0xF378, 0x95DC, 0xC3F6, 0x95DE, 0xF545, 0x95DF, 0xF547,
+	0x95E0, 0xF546, 0x95E1, 0xC4C4, 0x95E2, 0xC550, 0x95E3, 0xF66D,
+	0x95E4, 0xF66C, 0x95E5, 0xF66B, 0x961C, 0xAAFA, 0x961E, 0xC9AA,
+	0x9620, 0xCA58, 0x9621, 0xA6E9, 0x9622, 0xCA56, 0x9623, 0xCA59,
+	0x9624, 0xCA57, 0x9628, 0xCBAE, 0x962A, 0xA8C1, 0x962C, 0xA8C2,
+	0x962D, 0xCBB0, 0x962E, 0xA8BF, 0x962F, 0xCBAF, 0x9630, 0xCBAD,
+	0x9631, 0xA8C0, 0x9632, 0xA8BE, 0x9639, 0xCDD8, 0x963A, 0xCDDB,
+	0x963B, 0xAAFD, 0x963C, 0xCDDA, 0x963D, 0xCDD9, 0x963F, 0xAAFC,
+	0x9640, 0xAAFB, 0x9642, 0xAB40, 0x9643, 0xCDDC, 0x9644, 0xAAFE,
+	0x964A, 0xD0C6, 0x964B, 0xADAE, 0x964C, 0xADAF, 0x964D, 0xADB0,
+	0x964E, 0xD0C7, 0x964F, 0xD0C3, 0x9650, 0xADAD, 0x9651, 0xD0C4,
+	0x9653, 0xD0C5, 0x9654, 0xD0C2, 0x9658, 0xB0A4, 0x965B, 0xB0A1,
+	0x965C, 0xD445, 0x965D, 0xB0A2, 0x965E, 0xB0A5, 0x965F, 0xD446,
+	0x9661, 0xB07E, 0x9662, 0xB07C, 0x9663, 0xB07D, 0x9664, 0xB0A3,
+	0x966A, 0xB3AD, 0x966B, 0xD849, 0x966C, 0xB3B5, 0x966D, 0xD848,
+	0x966F, 0xD84B, 0x9670, 0xB3B1, 0x9671, 0xD84A, 0x9672, 0xB6AB,
+	0x9673, 0xB3AF, 0x9674, 0xB3B2, 0x9675, 0xB3AE, 0x9676, 0xB3B3,
+	0x9677, 0xB3B4, 0x9678, 0xB3B0, 0x967C, 0xD847, 0x967D, 0xB6A7,
+	0x967E, 0xDC7D, 0x9680, 0xDCA3, 0x9683, 0xDCA2, 0x9684, 0xB6AC,
+	0x9685, 0xB6A8, 0x9686, 0xB6A9, 0x9687, 0xDC7C, 0x9688, 0xDC7E,
+	0x9689, 0xDCA1, 0x968A, 0xB6A4, 0x968B, 0xB6A6, 0x968D, 0xB6AA,
+	0x968E, 0xB6A5, 0x9691, 0xE0D3, 0x9692, 0xE0D1, 0x9693, 0xE0D2,
+	0x9694, 0xB96A, 0x9695, 0xB96B, 0x9697, 0xE0D4, 0x9698, 0xB969,
+	0x9699, 0xBBD8, 0x969B, 0xBBDA, 0x969C, 0xBBD9, 0x969E, 0xE4BB,
+	0x96A1, 0xE4BC, 0x96A2, 0xE8AB, 0x96A4, 0xE8AA, 0x96A7, 0xC047,
+	0x96A8, 0xC048, 0x96A9, 0xEC4F, 0x96AA, 0xC049, 0x96AC, 0xEEF6,
+	0x96AE, 0xEEF4, 0x96B0, 0xEEF5, 0x96B1, 0xC1F4, 0x96B3, 0xF16F,
+	0x96B4, 0xC3F7, 0x96B8, 0xC1F5, 0x96B9, 0xAB41, 0x96BB, 0xB0A6,
+	0x96BC, 0xD447, 0x96BF, 0xD84C, 0x96C0, 0xB3B6, 0x96C1, 0xB6AD,
+	0x96C2, 0xDCA4, 0x96C3, 0xDCA6, 0x96C4, 0xB6AF, 0x96C5, 0xB6AE,
+	0x96C6, 0xB6B0, 0x96C7, 0xB6B1, 0x96C8, 0xDCA5, 0x96C9, 0xB96E,
+	0x96CA, 0xB96F, 0x96CB, 0xB96D, 0x96CC, 0xBBDB, 0x96CD, 0xB96C,
+	0x96CE, 0xE0D5, 0x96D2, 0xBBDC, 0x96D3, 0xE8AC, 0x96D4, 0xEC50,
+	0x96D5, 0xC04A, 0x96D6, 0xC1F6, 0x96D7, 0xF170, 0x96D8, 0xF174,
+	0x96D9, 0xC2F9, 0x96DA, 0xF171, 0x96DB, 0xC2FA, 0x96DC, 0xC2F8,
+	0x96DD, 0xF175, 0x96DE, 0xC2FB, 0x96DF, 0xF173, 0x96E1, 0xF379,
+	0x96E2, 0xC2F7, 0x96E3, 0xC3F8, 0x96E5, 0xF8CD, 0x96E8, 0xAB42,
+	0x96E9, 0xB3B8, 0x96EA, 0xB3B7, 0x96EF, 0xB6B2, 0x96F0, 0xDCA8,
+	0x96F1, 0xDCA7, 0x96F2, 0xB6B3, 0x96F5, 0xE0D9, 0x96F6, 0xB973,
+	0x96F7, 0xB970, 0x96F8, 0xE0D8, 0x96F9, 0xB972, 0x96FA, 0xE0D6,
+	0x96FB, 0xB971, 0x96FD, 0xE0D7, 0x96FF, 0xE4BD, 0x9700, 0xBBDD,
+	0x9702, 0xE8AF, 0x9704, 0xBE5D, 0x9705, 0xE8AD, 0x9706, 0xBE5E,
+	0x9707, 0xBE5F, 0x9708, 0xE8AE, 0x9709, 0xBE60, 0x970B, 0xEC51,
+	0x970D, 0xC04E, 0x970E, 0xC04B, 0x970F, 0xC050, 0x9710, 0xEC53,
+	0x9711, 0xC04C, 0x9712, 0xEC52, 0x9713, 0xC04F, 0x9716, 0xC04D,
+	0x9718, 0xEEF9, 0x9719, 0xEEFB, 0x971C, 0xC1F7, 0x971D, 0xEEFA,
+	0x971E, 0xC1F8, 0x971F, 0xEEF8, 0x9720, 0xEEF7, 0x9722, 0xF177,
+	0x9723, 0xF176, 0x9724, 0xC2FC, 0x9725, 0xF178, 0x9726, 0xF37E,
+	0x9727, 0xC3FA, 0x9728, 0xF37D, 0x9729, 0xF37A, 0x972A, 0xC3F9,
+	0x972B, 0xF37B, 0x972C, 0xF37C, 0x972E, 0xF548, 0x972F, 0xF549,
+	0x9730, 0xC4C5, 0x9732, 0xC553, 0x9735, 0xF66E, 0x9738, 0xC551,
+	0x9739, 0xC552, 0x973A, 0xF66F, 0x973D, 0xC5B4, 0x973E, 0xC5B5,
+	0x973F, 0xF771, 0x9742, 0xC645, 0x9743, 0xF8CF, 0x9744, 0xC647,
+	0x9746, 0xF8CE, 0x9747, 0xF8D0, 0x9748, 0xC646, 0x9749, 0xF957,
+	0x974B, 0xF9AD, 0x9752, 0xAB43, 0x9756, 0xB974, 0x9758, 0xE4BE,
+	0x975A, 0xE8B0, 0x975B, 0xC051, 0x975C, 0xC052, 0x975E, 0xAB44,
+	0x9760, 0xBE61, 0x9761, 0xC3FB, 0x9762, 0xADB1, 0x9766, 0xC053,
+	0x9768, 0xC5E2, 0x9769, 0xADB2, 0x976A, 0xD84D, 0x976C, 0xDCA9,
+	0x976E, 0xDCAB, 0x9770, 0xDCAA, 0x9772, 0xE0DD, 0x9773, 0xE0DA,
+	0x9774, 0xB975, 0x9776, 0xB976, 0x9777, 0xE0DB, 0x9778, 0xE0DC,
+	0x977A, 0xE4C0, 0x977B, 0xE4C5, 0x977C, 0xBBDE, 0x977D, 0xE4BF,
+	0x977E, 0xE4C1, 0x977F, 0xE4C8, 0x9780, 0xE4C3, 0x9781, 0xE4C7,
+	0x9782, 0xE4C4, 0x9783, 0xE4C2, 0x9784, 0xE4C6, 0x9785, 0xBBDF,
+	0x9788, 0xE8B3, 0x978A, 0xE8B1, 0x978B, 0xBE63, 0x978D, 0xBE62,
+	0x978E, 0xE8B2, 0x978F, 0xBE64, 0x9794, 0xEC56, 0x9797, 0xEC55,
+	0x9798, 0xC054, 0x9799, 0xEC54, 0x979A, 0xEEFC, 0x979C, 0xEEFE,
+	0x979D, 0xEF41, 0x979E, 0xEF40, 0x97A0, 0xC1F9, 0x97A1, 0xEEFD,
+	0x97A2, 0xF1A1, 0x97A3, 0xC2FD, 0x97A4, 0xF17D, 0x97A5, 0xF1A2,
+	0x97A6, 0xC2FE, 0x97A8, 0xF17B, 0x97AA, 0xF17E, 0x97AB, 0xF17C,
+	0x97AC, 0xF179, 0x97AD, 0xC340, 0x97AE, 0xF17A, 0x97B3, 0xF3A1,
+	0x97B6, 0xF3A3, 0x97B7, 0xF3A2, 0x97B9, 0xF54A, 0x97BB, 0xF54B,
+	0x97BF, 0xF670, 0x97C1, 0xC5B7, 0x97C3, 0xC5B6, 0x97C4, 0xF84F,
+	0x97C5, 0xF850, 0x97C6, 0xC648, 0x97C7, 0xF8D1, 0x97C9, 0xC669,
+	0x97CB, 0xADB3, 0x97CC, 0xB6B4, 0x97CD, 0xE4CA, 0x97CE, 0xE4C9,
+	0x97CF, 0xE8B5, 0x97D0, 0xE8B4, 0x97D3, 0xC1FA, 0x97D4, 0xEF43,
+	0x97D5, 0xEF42, 0x97D6, 0xF1A5, 0x97D7, 0xF1A3, 0x97D8, 0xF1A6,
+	0x97D9, 0xF1A4, 0x97DC, 0xC3FC, 0x97DD, 0xF3A4, 0x97DE, 0xF3A5,
+	0x97DF, 0xF3A6, 0x97E1, 0xF671, 0x97E3, 0xF772, 0x97E5, 0xF8D2,
+	0x97ED, 0xADB4, 0x97F0, 0xEC57, 0x97F1, 0xEF44, 0x97F3, 0xADB5,
+	0x97F6, 0xBBE0, 0x97F8, 0xEC58, 0x97F9, 0xC341, 0x97FA, 0xF1A7,
+	0x97FB, 0xC3FD, 0x97FD, 0xF54C, 0x97FE, 0xF54D, 0x97FF, 0xC554,
+	0x9800, 0xF851, 0x9801, 0xADB6, 0x9802, 0xB3BB, 0x9803, 0xB3BC,
+	0x9804, 0xD84E, 0x9805, 0xB6B5, 0x9806, 0xB6B6, 0x9807, 0xDCAC,
+	0x9808, 0xB6B7, 0x980A, 0xB97A, 0x980C, 0xB97C, 0x980D, 0xE0DF,
+	0x980E, 0xE0E0, 0x980F, 0xE0DE, 0x9810, 0xB977, 0x9811, 0xB978,
+	0x9812, 0xB97B, 0x9813, 0xB979, 0x9816, 0xE4CB, 0x9817, 0xBBE1,
+	0x9818, 0xBBE2, 0x981B, 0xE8BC, 0x981C, 0xBE67, 0x981D, 0xE8B7,
+	0x981E, 0xE8B6, 0x9820, 0xE8BB, 0x9821, 0xBE65, 0x9824, 0xC05B,
+	0x9826, 0xE8B8, 0x9827, 0xE8BD, 0x9828, 0xE8BA, 0x9829, 0xE8B9,
+	0x982B, 0xBE66, 0x982D, 0xC059, 0x982F, 0xEC5A, 0x9830, 0xC055,
+	0x9832, 0xEC5B, 0x9835, 0xEC59, 0x9837, 0xC058, 0x9838, 0xC056,
+	0x9839, 0xC05A, 0x983B, 0xC057, 0x9841, 0xEF45, 0x9843, 0xEF4A,
+	0x9844, 0xEF46, 0x9845, 0xEF49, 0x9846, 0xC1FB, 0x9848, 0xEDD4,
+	0x9849, 0xEF48, 0x984A, 0xEF47, 0x984C, 0xC344, 0x984D, 0xC342,
+	0x984E, 0xC345, 0x984F, 0xC343, 0x9850, 0xF1A8, 0x9851, 0xF1A9,
+	0x9852, 0xF1AA, 0x9853, 0xC346, 0x9857, 0xF3AA, 0x9858, 0xC440,
+	0x9859, 0xF3A8, 0x985B, 0xC441, 0x985C, 0xF3A7, 0x985D, 0xF3A9,
+	0x985E, 0xC3FE, 0x985F, 0xF551, 0x9860, 0xF54E, 0x9862, 0xF54F,
+	0x9863, 0xF550, 0x9864, 0xF672, 0x9865, 0xC556, 0x9867, 0xC555,
+	0x9869, 0xF774, 0x986A, 0xF773, 0x986B, 0xC5B8, 0x986F, 0xC5E3,
+	0x9870, 0xC649, 0x9871, 0xC660, 0x9872, 0xF958, 0x9873, 0xF9AE,
+	0x9874, 0xF9AF, 0x98A8, 0xADB7, 0x98A9, 0xDCAD, 0x98AC, 0xE0E1,
+	0x98AD, 0xE4CC, 0x98AE, 0xE4CD, 0x98AF, 0xBBE3, 0x98B1, 0xBBE4,
+	0x98B2, 0xE8BE, 0x98B3, 0xBE68, 0x98B6, 0xC1FC, 0x98B8, 0xF1AB,
+	0x98BA, 0xC347, 0x98BB, 0xF3AD, 0x98BC, 0xC442, 0x98BD, 0xF3AC,
+	0x98BE, 0xF3AE, 0x98BF, 0xF3AB, 0x98C0, 0xF675, 0x98C1, 0xF552,
+	0x98C2, 0xF553, 0x98C4, 0xC4C6, 0x98C6, 0xF674, 0x98C9, 0xF673,
+	0x98CB, 0xF775, 0x98CC, 0xF9B0, 0x98DB, 0xADB8, 0x98DF, 0xADB9,
+	0x98E2, 0xB0A7, 0x98E3, 0xD448, 0x98E5, 0xD84F, 0x98E7, 0xB6B8,
+	0x98E9, 0xB6BB, 0x98EA, 0xB6B9, 0x98EB, 0xDCAE, 0x98ED, 0xB6BD,
+	0x98EF, 0xB6BA, 0x98F2, 0xB6BC, 0x98F4, 0xB97E, 0x98F6, 0xE0E2,
+	0x98F9, 0xE0E3, 0x98FA, 0xE8C0, 0x98FC, 0xB97D, 0x98FD, 0xB9A1,
+	0x98FE, 0xB9A2, 0x9900, 0xE4CF, 0x9902, 0xE4CE, 0x9903, 0xBBE5,
+	0x9905, 0xBBE6, 0x9907, 0xE4D0, 0x9908, 0xE8BF, 0x9909, 0xBBE8,
+	0x990A, 0xBE69, 0x990C, 0xBBE7, 0x9910, 0xC05C, 0x9911, 0xE8C1,
+	0x9912, 0xBE6B, 0x9913, 0xBE6A, 0x9914, 0xE8C2, 0x9915, 0xE8C5,
+	0x9916, 0xE8C3, 0x9917, 0xE8C4, 0x9918, 0xBE6C, 0x991A, 0xC061,
+	0x991B, 0xC05F, 0x991E, 0xC05E, 0x991F, 0xEC5D, 0x9921, 0xC060,
+	0x9924, 0xEC5C, 0x9925, 0xEF4B, 0x9927, 0xEC5E, 0x9928, 0xC05D,
+	0x9929, 0xEC5F, 0x992A, 0xEF4E, 0x992B, 0xEF4C, 0x992C, 0xEF4D,
+	0x992D, 0xEF52, 0x992E, 0xC34B, 0x992F, 0xEF51, 0x9930, 0xEF54,
+	0x9931, 0xEF53, 0x9932, 0xEF50, 0x9933, 0xEF4F, 0x9935, 0xC1FD,
+	0x993A, 0xF1AE, 0x993C, 0xF1AD, 0x993D, 0xC34A, 0x993E, 0xC348,
+	0x993F, 0xC349, 0x9941, 0xF1AC, 0x9943, 0xF3B1, 0x9945, 0xC443,
+	0x9947, 0xF3B0, 0x9948, 0xF3AF, 0x9949, 0xC444, 0x994B, 0xF558,
+	0x994C, 0xF557, 0x994E, 0xF555, 0x9950, 0xF554, 0x9951, 0xC4C8,
+	0x9952, 0xC4C7, 0x9953, 0xF559, 0x9954, 0xF776, 0x9955, 0xC5B9,
+	0x9956, 0xF677, 0x9957, 0xC557, 0x9958, 0xF676, 0x9959, 0xF556,
+	0x995B, 0xF777, 0x995C, 0xC5E4, 0x995E, 0xC661, 0x995F, 0xF959,
+	0x9961, 0xF9B1, 0x9996, 0xADBA, 0x9997, 0xD850, 0x9998, 0xEF55,
+	0x9999, 0xADBB, 0x999C, 0xE4D2, 0x999D, 0xE4D1, 0x999E, 0xEC60,
+	0x99A1, 0xEF57, 0x99A3, 0xEF56, 0x99A5, 0xC34C, 0x99A6, 0xF3B2,
+	0x99A7, 0xF3B3, 0x99A8, 0xC4C9, 0x99AB, 0xF9B2, 0x99AC, 0xB0A8,
+	0x99AD, 0xB6BF, 0x99AE, 0xB6BE, 0x99AF, 0xE0E4, 0x99B0, 0xE0E6,
+	0x99B1, 0xB9A4, 0x99B2, 0xE0E5, 0x99B3, 0xB9A3, 0x99B4, 0xB9A5,
+	0x99B5, 0xE0E7, 0x99B9, 0xE4D4, 0x99BA, 0xE4D6, 0x99BB, 0xE4D5,
+	0x99BD, 0xE4D8, 0x99C1, 0xBBE9, 0x99C2, 0xE4D7, 0x99C3, 0xE4D3,
+	0x99C7, 0xE4D9, 0x99C9, 0xE8CC, 0x99CB, 0xE8CF, 0x99CC, 0xE8D1,
+	0x99CD, 0xE8C7, 0x99CE, 0xE8CB, 0x99CF, 0xE8C8, 0x99D0, 0xBE6E,
+	0x99D1, 0xBE71, 0x99D2, 0xBE73, 0x99D3, 0xE8C9, 0x99D4, 0xE8CA,
+	0x99D5, 0xBE72, 0x99D6, 0xE8CD, 0x99D7, 0xE8D0, 0x99D8, 0xE8CE,
+	0x99D9, 0xBE74, 0x99DB, 0xBE70, 0x99DC, 0xE8C6, 0x99DD, 0xBE6D,
+	0x99DF, 0xBE6F, 0x99E2, 0xC063, 0x99E3, 0xEC66, 0x99E4, 0xEC64,
+	0x99E5, 0xEC63, 0x99E7, 0xEC69, 0x99E9, 0xEC68, 0x99EA, 0xEC67,
+	0x99EC, 0xEC62, 0x99ED, 0xC062, 0x99EE, 0xEC61, 0x99F0, 0xEC65,
+	0x99F1, 0xC064, 0x99F4, 0xEF5A, 0x99F6, 0xEF5E, 0x99F7, 0xEF5B,
+	0x99F8, 0xEF5D, 0x99F9, 0xEF5C, 0x99FA, 0xEF59, 0x99FB, 0xEF5F,
+	0x99FC, 0xEF62, 0x99FD, 0xEF60, 0x99FE, 0xEF61, 0x99FF, 0xC240,
+	0x9A01, 0xC1FE, 0x9A02, 0xEF58, 0x9A03, 0xEF63, 0x9A04, 0xF1B3,
+	0x9A05, 0xF1B6, 0x9A06, 0xF1B8, 0x9A07, 0xF1B7, 0x9A09, 0xF1B1,
+	0x9A0A, 0xF1B5, 0x9A0B, 0xF1B0, 0x9A0D, 0xF1B2, 0x9A0E, 0xC34D,
+	0x9A0F, 0xF1AF, 0x9A11, 0xF1B4, 0x9A14, 0xF3C0, 0x9A15, 0xF3B5,
+	0x9A16, 0xC445, 0x9A19, 0xC446, 0x9A1A, 0xF3B4, 0x9A1B, 0xF3B9,
+	0x9A1C, 0xF3BF, 0x9A1D, 0xF3B7, 0x9A1E, 0xF3BE, 0x9A20, 0xF3BB,
+	0x9A22, 0xF3BA, 0x9A23, 0xF3BD, 0x9A24, 0xF3B8, 0x9A25, 0xF3B6,
+	0x9A27, 0xF3BC, 0x9A29, 0xF560, 0x9A2A, 0xF55E, 0x9A2B, 0xC4CA,
+	0x9A2C, 0xF55D, 0x9A2D, 0xF563, 0x9A2E, 0xF561, 0x9A30, 0xC4CB,
+	0x9A31, 0xF55C, 0x9A32, 0xF55A, 0x9A34, 0xF55B, 0x9A35, 0xC4CD,
+	0x9A36, 0xF55F, 0x9A37, 0xC4CC, 0x9A38, 0xF562, 0x9A39, 0xF678,
+	0x9A3A, 0xF67E, 0x9A3D, 0xF679, 0x9A3E, 0xC55B, 0x9A3F, 0xF6A1,
+	0x9A40, 0xC55A, 0x9A41, 0xF67D, 0x9A42, 0xF67C, 0x9A43, 0xC559,
+	0x9A44, 0xF67B, 0x9A45, 0xC558, 0x9A46, 0xF67A, 0x9A48, 0xF77D,
+	0x9A49, 0xF7A1, 0x9A4A, 0xF77E, 0x9A4C, 0xF77B, 0x9A4D, 0xC5BB,
+	0x9A4E, 0xF778, 0x9A4F, 0xF77C, 0x9A50, 0xF7A3, 0x9A52, 0xF7A2,
+	0x9A53, 0xF779, 0x9A54, 0xF77A, 0x9A55, 0xC5BA, 0x9A56, 0xF852,
+	0x9A57, 0xC5E7, 0x9A59, 0xF853, 0x9A5A, 0xC5E5, 0x9A5B, 0xC5E6,
+	0x9A5E, 0xF8D3, 0x9A5F, 0xC64A, 0x9A60, 0xF976, 0x9A62, 0xC66A,
+	0x9A64, 0xF9B3, 0x9A65, 0xC66B, 0x9A66, 0xF9B4, 0x9A67, 0xF9B5,
+	0x9A68, 0xF9C3, 0x9A69, 0xF9C2, 0x9A6A, 0xC67A, 0x9A6B, 0xF9CD,
+	0x9AA8, 0xB0A9, 0x9AAB, 0xE0E9, 0x9AAD, 0xE0E8, 0x9AAF, 0xBBEA,
+	0x9AB0, 0xBBEB, 0x9AB1, 0xE4DA, 0x9AB3, 0xE8D2, 0x9AB4, 0xEC6C,
+	0x9AB7, 0xBE75, 0x9AB8, 0xC065, 0x9AB9, 0xEC6A, 0x9ABB, 0xEC6D,
+	0x9ABC, 0xC066, 0x9ABE, 0xEF64, 0x9ABF, 0xEC6B, 0x9AC0, 0xF1B9,
+	0x9AC1, 0xC34E, 0x9AC2, 0xF3C1, 0x9AC6, 0xF566, 0x9AC7, 0xF564,
+	0x9ACA, 0xF565, 0x9ACD, 0xF6A2, 0x9ACF, 0xC55C, 0x9AD0, 0xF7A4,
+	0x9AD1, 0xC5EA, 0x9AD2, 0xC5BC, 0x9AD3, 0xC5E8, 0x9AD4, 0xC5E9,
+	0x9AD5, 0xF8D4, 0x9AD6, 0xC662, 0x9AD8, 0xB0AA, 0x9ADC, 0xF1BA,
+	0x9ADF, 0xD449, 0x9AE1, 0xB9A6, 0x9AE3, 0xE4DB, 0x9AE6, 0xBBEC,
+	0x9AE7, 0xE4DC, 0x9AEB, 0xE8D4, 0x9AEC, 0xE8D3, 0x9AED, 0xC068,
+	0x9AEE, 0xBE76, 0x9AEF, 0xBE77, 0x9AF1, 0xE8D7, 0x9AF2, 0xE8D6,
+	0x9AF3, 0xE8D5, 0x9AF6, 0xEC6E, 0x9AF7, 0xEC71, 0x9AF9, 0xEC70,
+	0x9AFA, 0xEC6F, 0x9AFB, 0xC067, 0x9AFC, 0xEF68, 0x9AFD, 0xEF66,
+	0x9AFE, 0xEF65, 0x9B01, 0xEF67, 0x9B03, 0xC34F, 0x9B04, 0xF1BC,
+	0x9B05, 0xF1BD, 0x9B06, 0xC350, 0x9B08, 0xF1BB, 0x9B0A, 0xF3C3,
+	0x9B0B, 0xF3C2, 0x9B0C, 0xF3C5, 0x9B0D, 0xC447, 0x9B0E, 0xF3C4,
+	0x9B10, 0xF567, 0x9B11, 0xF569, 0x9B12, 0xF568, 0x9B15, 0xF6A3,
+	0x9B16, 0xF6A6, 0x9B17, 0xF6A4, 0x9B18, 0xF6A5, 0x9B19, 0xF7A5,
+	0x9B1A, 0xC5BD, 0x9B1E, 0xF854, 0x9B1F, 0xF855, 0x9B20, 0xF856,
+	0x9B22, 0xC64B, 0x9B23, 0xC663, 0x9B24, 0xF9B6, 0x9B25, 0xB0AB,
+	0x9B27, 0xBE78, 0x9B28, 0xC069, 0x9B29, 0xF1BE, 0x9B2B, 0xF7A6,
+	0x9B2E, 0xF9C4, 0x9B2F, 0xD44A, 0x9B31, 0xC67B, 0x9B32, 0xB0AC,
+	0x9B33, 0xEC72, 0x9B35, 0xF1BF, 0x9B37, 0xF3C6, 0x9B3A, 0xF6A7,
+	0x9B3B, 0xF7A7, 0x9B3C, 0xB0AD, 0x9B3E, 0xE4DD, 0x9B3F, 0xE4DE,
+	0x9B41, 0xBBED, 0x9B42, 0xBBEE, 0x9B43, 0xE8D9, 0x9B44, 0xBE7A,
+	0x9B45, 0xBE79, 0x9B46, 0xE8D8, 0x9B48, 0xEF69, 0x9B4A, 0xF1C0,
+	0x9B4B, 0xF1C2, 0x9B4C, 0xF1C1, 0x9B4D, 0xC353, 0x9B4E, 0xC352,
+	0x9B4F, 0xC351, 0x9B51, 0xC55E, 0x9B52, 0xF6A8, 0x9B54, 0xC55D,
+	0x9B55, 0xF7A9, 0x9B56, 0xF7A8, 0x9B58, 0xC64C, 0x9B59, 0xF8D5,
+	0x9B5A, 0xB3BD, 0x9B5B, 0xE0EA, 0x9B5F, 0xE4E1, 0x9B60, 0xE4DF,
+	0x9B61, 0xE4E0, 0x9B64, 0xE8E2, 0x9B66, 0xE8DD, 0x9B67, 0xE8DA,
+	0x9B68, 0xE8E1, 0x9B6C, 0xE8E3, 0x9B6F, 0xBE7C, 0x9B70, 0xE8E0,
+	0x9B71, 0xE8DC, 0x9B74, 0xE8DB, 0x9B75, 0xE8DF, 0x9B76, 0xE8DE,
+	0x9B77, 0xBE7B, 0x9B7A, 0xEC7D, 0x9B7B, 0xEC78, 0x9B7C, 0xEC76,
+	0x9B7D, 0xECA1, 0x9B7E, 0xEC77, 0x9B80, 0xEC73, 0x9B82, 0xEC79,
+	0x9B85, 0xEC74, 0x9B86, 0xEF72, 0x9B87, 0xEC75, 0x9B88, 0xECA2,
+	0x9B90, 0xEC7C, 0x9B91, 0xC06A, 0x9B92, 0xEC7B, 0x9B93, 0xEC7A,
+	0x9B95, 0xEC7E, 0x9B9A, 0xEF6A, 0x9B9B, 0xEF6D, 0x9B9E, 0xEF6C,
+	0x9BA0, 0xEF74, 0x9BA1, 0xEF6F, 0x9BA2, 0xEF73, 0x9BA4, 0xEF71,
+	0x9BA5, 0xEF70, 0x9BA6, 0xEF6E, 0x9BA8, 0xEF6B, 0x9BAA, 0xC243,
+	0x9BAB, 0xC242, 0x9BAD, 0xC244, 0x9BAE, 0xC241, 0x9BAF, 0xEF75,
+	0x9BB5, 0xF1C8, 0x9BB6, 0xF1CB, 0x9BB8, 0xF1C9, 0x9BB9, 0xF1CD,
+	0x9BBD, 0xF1CE, 0x9BBF, 0xF1C6, 0x9BC0, 0xC358, 0x9BC1, 0xF1C7,
+	0x9BC3, 0xF1C5, 0x9BC4, 0xF1CC, 0x9BC6, 0xF1C4, 0x9BC7, 0xF1C3,
+	0x9BC8, 0xC357, 0x9BC9, 0xC355, 0x9BCA, 0xC354, 0x9BD3, 0xF1CA,
+	0x9BD4, 0xF3CF, 0x9BD5, 0xF3D5, 0x9BD6, 0xC44A, 0x9BD7, 0xF3D0,
+	0x9BD9, 0xF3D3, 0x9BDA, 0xF3D7, 0x9BDB, 0xC44B, 0x9BDC, 0xF3D2,
+	0x9BDE, 0xF3CA, 0x9BE0, 0xF3C9, 0x9BE1, 0xF3D6, 0x9BE2, 0xF3CD,
+	0x9BE4, 0xF3CB, 0x9BE5, 0xF3D4, 0x9BE6, 0xF3CC, 0x9BE7, 0xC449,
+	0x9BE8, 0xC448, 0x9BEA, 0xF3C7, 0x9BEB, 0xF3C8, 0x9BEC, 0xF3D1,
+	0x9BF0, 0xF3CE, 0x9BF7, 0xF56C, 0x9BF8, 0xF56F, 0x9BFD, 0xC356,
+	0x9C05, 0xF56D, 0x9C06, 0xF573, 0x9C07, 0xF571, 0x9C08, 0xF56B,
+	0x9C09, 0xF576, 0x9C0B, 0xF56A, 0x9C0D, 0xC4CF, 0x9C0E, 0xF572,
+	0x9C12, 0xF56E, 0x9C13, 0xC4CE, 0x9C14, 0xF575, 0x9C17, 0xF574,
+	0x9C1C, 0xF6AB, 0x9C1D, 0xF6AA, 0x9C21, 0xF6B1, 0x9C23, 0xF6AD,
+	0x9C24, 0xF6B0, 0x9C25, 0xC560, 0x9C28, 0xF6AE, 0x9C29, 0xF6AF,
+	0x9C2B, 0xF6A9, 0x9C2C, 0xF6AC, 0x9C2D, 0xC55F, 0x9C31, 0xC5BF,
+	0x9C32, 0xF7B4, 0x9C33, 0xF7AF, 0x9C34, 0xF7B3, 0x9C36, 0xF7B6,
+	0x9C37, 0xF7B2, 0x9C39, 0xF7AE, 0x9C3B, 0xC5C1, 0x9C3C, 0xF7B1,
+	0x9C3D, 0xF7B5, 0x9C3E, 0xC5C0, 0x9C3F, 0xF7AC, 0x9C40, 0xF570,
+	0x9C41, 0xF7B0, 0x9C44, 0xF7AD, 0x9C46, 0xF7AA, 0x9C48, 0xF7AB,
+	0x9C49, 0xC5BE, 0x9C4A, 0xF85A, 0x9C4B, 0xF85C, 0x9C4C, 0xF85F,
+	0x9C4D, 0xF85B, 0x9C4E, 0xF860, 0x9C50, 0xF859, 0x9C52, 0xF857,
+	0x9C54, 0xC5EB, 0x9C55, 0xF85D, 0x9C56, 0xC5ED, 0x9C57, 0xC5EC,
+	0x9C58, 0xF858, 0x9C59, 0xF85E, 0x9C5E, 0xF8DA, 0x9C5F, 0xC64D,
+	0x9C60, 0xF8DB, 0x9C62, 0xF8D9, 0x9C63, 0xF8D6, 0x9C66, 0xF8D8,
+	0x9C67, 0xF8D7, 0x9C68, 0xF95A, 0x9C6D, 0xF95C, 0x9C6E, 0xF95B,
+	0x9C71, 0xF979, 0x9C73, 0xF978, 0x9C74, 0xF977, 0x9C75, 0xF97A,
+	0x9C77, 0xC673, 0x9C78, 0xC674, 0x9C79, 0xF9CA, 0x9C7A, 0xF9CE,
+	0x9CE5, 0xB3BE, 0x9CE6, 0xDCAF, 0x9CE7, 0xE0ED, 0x9CE9, 0xB9A7,
+	0x9CEA, 0xE0EB, 0x9CED, 0xE0EC, 0x9CF1, 0xE4E2, 0x9CF2, 0xE4E3,
+	0x9CF3, 0xBBF1, 0x9CF4, 0xBBEF, 0x9CF5, 0xE4E4, 0x9CF6, 0xBBF0,
+	0x9CF7, 0xE8E8, 0x9CF9, 0xE8EB, 0x9CFA, 0xE8E5, 0x9CFB, 0xE8EC,
+	0x9CFC, 0xE8E4, 0x9CFD, 0xE8E6, 0x9CFF, 0xE8E7, 0x9D00, 0xE8EA,
+	0x9D03, 0xBEA1, 0x9D04, 0xE8EF, 0x9D05, 0xE8EE, 0x9D06, 0xBE7D,
+	0x9D07, 0xE8E9, 0x9D08, 0xE8ED, 0x9D09, 0xBE7E, 0x9D10, 0xECAC,
+	0x9D12, 0xC06F, 0x9D14, 0xECA7, 0x9D15, 0xC06B, 0x9D17, 0xECA4,
+	0x9D18, 0xECAA, 0x9D19, 0xECAD, 0x9D1B, 0xC070, 0x9D1D, 0xECA9,
+	0x9D1E, 0xECA6, 0x9D1F, 0xECAE, 0x9D20, 0xECA5, 0x9D22, 0xECAB,
+	0x9D23, 0xC06C, 0x9D25, 0xECA3, 0x9D26, 0xC06D, 0x9D28, 0xC06E,
+	0x9D29, 0xECA8, 0x9D2D, 0xEFA9, 0x9D2E, 0xEF7A, 0x9D2F, 0xEF7B,
+	0x9D30, 0xEF7E, 0x9D31, 0xEF7C, 0x9D33, 0xEF76, 0x9D36, 0xEF79,
+	0x9D37, 0xEFA5, 0x9D38, 0xEF7D, 0x9D3B, 0xC245, 0x9D3D, 0xEFA7,
+	0x9D3E, 0xEFA4, 0x9D3F, 0xC246, 0x9D40, 0xEFA6, 0x9D41, 0xEF77,
+	0x9D42, 0xEFA2, 0x9D43, 0xEFA3, 0x9D45, 0xEFA1, 0x9D4A, 0xF1D2,
+	0x9D4B, 0xF1D4, 0x9D4C, 0xF1D7, 0x9D4F, 0xF1D1, 0x9D51, 0xC359,
+	0x9D52, 0xF1D9, 0x9D53, 0xF1D0, 0x9D54, 0xF1DA, 0x9D56, 0xF1D6,
+	0x9D57, 0xF1D8, 0x9D58, 0xF1DC, 0x9D59, 0xF1D5, 0x9D5A, 0xF1DD,
+	0x9D5B, 0xF1D3, 0x9D5C, 0xF1CF, 0x9D5D, 0xC35A, 0x9D5F, 0xF1DB,
+	0x9D60, 0xC35B, 0x9D61, 0xC44D, 0x9D67, 0xEF78, 0x9D68, 0xF3F1,
+	0x9D69, 0xF3E8, 0x9D6A, 0xC44F, 0x9D6B, 0xF3E4, 0x9D6C, 0xC450,
+	0x9D6F, 0xF3ED, 0x9D70, 0xF3E7, 0x9D71, 0xF3DD, 0x9D72, 0xC44E,
+	0x9D73, 0xF3EA, 0x9D74, 0xF3E5, 0x9D75, 0xF3E6, 0x9D77, 0xF3D8,
+	0x9D78, 0xF3DF, 0x9D79, 0xF3EE, 0x9D7B, 0xF3EB, 0x9D7D, 0xF3E3,
+	0x9D7F, 0xF3EF, 0x9D80, 0xF3DE, 0x9D81, 0xF3D9, 0x9D82, 0xF3EC,
+	0x9D84, 0xF3DB, 0x9D85, 0xF3E9, 0x9D86, 0xF3E0, 0x9D87, 0xF3F0,
+	0x9D88, 0xF3DC, 0x9D89, 0xC44C, 0x9D8A, 0xF3DA, 0x9D8B, 0xF3E1,
+	0x9D8C, 0xF3E2, 0x9D90, 0xF57D, 0x9D92, 0xF57B, 0x9D94, 0xF5A2,
+	0x9D96, 0xF5AE, 0x9D97, 0xF5A5, 0x9D98, 0xF57C, 0x9D99, 0xF578,
+	0x9D9A, 0xF5A7, 0x9D9B, 0xF57E, 0x9D9C, 0xF5A3, 0x9D9D, 0xF57A,
+	0x9D9E, 0xF5AA, 0x9D9F, 0xF577, 0x9DA0, 0xF5A1, 0x9DA1, 0xF5A6,
+	0x9DA2, 0xF5A8, 0x9DA3, 0xF5AB, 0x9DA4, 0xF579, 0x9DA6, 0xF5AF,
+	0x9DA7, 0xF5B0, 0x9DA8, 0xF5A9, 0x9DA9, 0xF5AD, 0x9DAA, 0xF5A4,
+	0x9DAC, 0xF6C1, 0x9DAD, 0xF6C4, 0x9DAF, 0xC561, 0x9DB1, 0xF6C3,
+	0x9DB2, 0xF6C8, 0x9DB3, 0xF6C6, 0x9DB4, 0xC562, 0x9DB5, 0xF6BD,
+	0x9DB6, 0xF6B3, 0x9DB7, 0xF6B2, 0x9DB8, 0xC564, 0x9DB9, 0xF6BF,
+	0x9DBA, 0xF6C0, 0x9DBB, 0xF6BC, 0x9DBC, 0xF6B4, 0x9DBE, 0xF6B9,
+	0x9DBF, 0xF5AC, 0x9DC1, 0xF6B5, 0x9DC2, 0xC563, 0x9DC3, 0xF6BB,
+	0x9DC5, 0xF6BA, 0x9DC7, 0xF6B6, 0x9DC8, 0xF6C2, 0x9DCA, 0xF6B7,
+	0x9DCB, 0xF7BB, 0x9DCC, 0xF6C5, 0x9DCD, 0xF6C7, 0x9DCE, 0xF6BE,
+	0x9DCF, 0xF6B8, 0x9DD0, 0xF7BC, 0x9DD1, 0xF7BE, 0x9DD2, 0xF7B8,
+	0x9DD3, 0xC5C2, 0x9DD5, 0xF7C5, 0x9DD6, 0xF7C3, 0x9DD7, 0xC5C3,
+	0x9DD8, 0xF7C2, 0x9DD9, 0xF7C1, 0x9DDA, 0xF7BA, 0x9DDB, 0xF7B7,
+	0x9DDC, 0xF7BD, 0x9DDD, 0xF7C6, 0x9DDE, 0xF7B9, 0x9DDF, 0xF7BF,
+	0x9DE1, 0xF869, 0x9DE2, 0xF86E, 0x9DE3, 0xF864, 0x9DE4, 0xF867,
+	0x9DE5, 0xC5EE, 0x9DE6, 0xF86B, 0x9DE8, 0xF872, 0x9DE9, 0xF7C0,
+	0x9DEB, 0xF865, 0x9DEC, 0xF86F, 0x9DED, 0xF873, 0x9DEE, 0xF86A,
+	0x9DEF, 0xF863, 0x9DF0, 0xF86D, 0x9DF2, 0xF86C, 0x9DF3, 0xF871,
+	0x9DF4, 0xF870, 0x9DF5, 0xF7C4, 0x9DF6, 0xF868, 0x9DF7, 0xF862,
+	0x9DF8, 0xF866, 0x9DF9, 0xC64E, 0x9DFA, 0xC64F, 0x9DFB, 0xF861,
+	0x9DFD, 0xF8E6, 0x9DFE, 0xF8DD, 0x9DFF, 0xF8E5, 0x9E00, 0xF8E2,
+	0x9E01, 0xF8E3, 0x9E02, 0xF8DC, 0x9E03, 0xF8DF, 0x9E04, 0xF8E7,
+	0x9E05, 0xF8E1, 0x9E06, 0xF8E0, 0x9E07, 0xF8DE, 0x9E09, 0xF8E4,
+	0x9E0B, 0xF95D, 0x9E0D, 0xF95E, 0x9E0F, 0xF960, 0x9E10, 0xF95F,
+	0x9E11, 0xF962, 0x9E12, 0xF961, 0x9E13, 0xF97C, 0x9E14, 0xF97B,
+	0x9E15, 0xF9B7, 0x9E17, 0xF9B8, 0x9E19, 0xF9C5, 0x9E1A, 0xC678,
+	0x9E1B, 0xC67C, 0x9E1D, 0xF9CF, 0x9E1E, 0xC67D, 0x9E75, 0xB3BF,
+	0x9E79, 0xC4D0, 0x9E7A, 0xF6C9, 0x9E7C, 0xC650, 0x9E7D, 0xC651,
+	0x9E7F, 0xB3C0, 0x9E80, 0xE0EE, 0x9E82, 0xB9A8, 0x9E83, 0xE8F0,
+	0x9E86, 0xECB0, 0x9E87, 0xECB1, 0x9E88, 0xECAF, 0x9E89, 0xEFAB,
+	0x9E8A, 0xEFAA, 0x9E8B, 0xC247, 0x9E8C, 0xF1DF, 0x9E8D, 0xEFAC,
+	0x9E8E, 0xF1DE, 0x9E91, 0xF3F3, 0x9E92, 0xC451, 0x9E93, 0xC453,
+	0x9E94, 0xF3F2, 0x9E97, 0xC452, 0x9E99, 0xF5B1, 0x9E9A, 0xF5B3,
+	0x9E9B, 0xF5B2, 0x9E9C, 0xF6CA, 0x9E9D, 0xC565, 0x9E9F, 0xC5EF,
+	0x9EA0, 0xF8E8, 0x9EA1, 0xF963, 0x9EA4, 0xF9D2, 0x9EA5, 0xB3C1,
+	0x9EA7, 0xE4E5, 0x9EA9, 0xBEA2, 0x9EAD, 0xECB3, 0x9EAE, 0xECB2,
+	0x9EB0, 0xEFAD, 0x9EB4, 0xC454, 0x9EB5, 0xC4D1, 0x9EB6, 0xF7C7,
+	0x9EB7, 0xF9CB, 0x9EBB, 0xB3C2, 0x9EBC, 0xBBF2, 0x9EBE, 0xBEA3,
+	0x9EC0, 0xF3F4, 0x9EC2, 0xF874, 0x9EC3, 0xB6C0, 0x9EC8, 0xEFAE,
+	0x9ECC, 0xC664, 0x9ECD, 0xB6C1, 0x9ECE, 0xBEA4, 0x9ECF, 0xC248,
+	0x9ED0, 0xF875, 0x9ED1, 0xB6C2, 0x9ED3, 0xE8F1, 0x9ED4, 0xC072,
+	0x9ED5, 0xECB4, 0x9ED6, 0xECB5, 0x9ED8, 0xC071, 0x9EDA, 0xEFAF,
+	0x9EDB, 0xC24C, 0x9EDC, 0xC24A, 0x9EDD, 0xC24B, 0x9EDE, 0xC249,
+	0x9EDF, 0xF1E0, 0x9EE0, 0xC35C, 0x9EE4, 0xF5B5, 0x9EE5, 0xF5B4,
+	0x9EE6, 0xF5B7, 0x9EE7, 0xF5B6, 0x9EE8, 0xC4D2, 0x9EEB, 0xF6CB,
+	0x9EED, 0xF6CD, 0x9EEE, 0xF6CC, 0x9EEF, 0xC566, 0x9EF0, 0xF7C8,
+	0x9EF2, 0xF876, 0x9EF3, 0xF877, 0x9EF4, 0xC5F0, 0x9EF5, 0xF964,
+	0x9EF6, 0xF97D, 0x9EF7, 0xC675, 0x9EF9, 0xDCB0, 0x9EFA, 0xECB6,
+	0x9EFB, 0xEFB0, 0x9EFC, 0xF3F5, 0x9EFD, 0xE0EF, 0x9EFF, 0xEFB1,
+	0x9F00, 0xF1E2, 0x9F01, 0xF1E1, 0x9F06, 0xF878, 0x9F07, 0xC652,
+	0x9F09, 0xF965, 0x9F0A, 0xF97E, 0x9F0E, 0xB9A9, 0x9F0F, 0xE8F2,
+	0x9F10, 0xE8F3, 0x9F12, 0xECB7, 0x9F13, 0xB9AA, 0x9F15, 0xC35D,
+	0x9F16, 0xF1E3, 0x9F18, 0xF6CF, 0x9F19, 0xC567, 0x9F1A, 0xF6D0,
+	0x9F1B, 0xF6CE, 0x9F1C, 0xF879, 0x9F1E, 0xF8E9, 0x9F20, 0xB9AB,
+	0x9F22, 0xEFB4, 0x9F23, 0xEFB3, 0x9F24, 0xEFB2, 0x9F25, 0xF1E4,
+	0x9F28, 0xF1E8, 0x9F29, 0xF1E7, 0x9F2A, 0xF1E6, 0x9F2B, 0xF1E5,
+	0x9F2C, 0xC35E, 0x9F2D, 0xF3F6, 0x9F2E, 0xF5B9, 0x9F2F, 0xC4D3,
+	0x9F30, 0xF5B8, 0x9F31, 0xF6D1, 0x9F32, 0xF7CB, 0x9F33, 0xF7CA,
+	0x9F34, 0xC5C4, 0x9F35, 0xF7C9, 0x9F36, 0xF87C, 0x9F37, 0xF87B,
+	0x9F38, 0xF87A, 0x9F3B, 0xBBF3, 0x9F3D, 0xECB8, 0x9F3E, 0xC24D,
+	0x9F40, 0xF3F7, 0x9F41, 0xF3F8, 0x9F42, 0xF7CC, 0x9F43, 0xF87D,
+	0x9F46, 0xF8EA, 0x9F47, 0xF966, 0x9F48, 0xF9B9, 0x9F49, 0xF9D4,
+	0x9F4A, 0xBBF4, 0x9F4B, 0xC24E, 0x9F4C, 0xF1E9, 0x9F4D, 0xF3F9,
+	0x9F4E, 0xF6D2, 0x9F4F, 0xF87E, 0x9F52, 0xBEA6, 0x9F54, 0xEFB5,
+	0x9F55, 0xF1EA, 0x9F56, 0xF3FA, 0x9F57, 0xF3FB, 0x9F58, 0xF3FC,
+	0x9F59, 0xF5BE, 0x9F5B, 0xF5BA, 0x9F5C, 0xC568, 0x9F5D, 0xF5BD,
+	0x9F5E, 0xF5BC, 0x9F5F, 0xC4D4, 0x9F60, 0xF5BB, 0x9F61, 0xC4D6,
+	0x9F63, 0xC4D5, 0x9F64, 0xF6D4, 0x9F65, 0xF6D3, 0x9F66, 0xC569,
+	0x9F67, 0xC56A, 0x9F6A, 0xC5C6, 0x9F6B, 0xF7CD, 0x9F6C, 0xC5C5,
+	0x9F6E, 0xF8A3, 0x9F6F, 0xF8A4, 0x9F70, 0xF8A2, 0x9F71, 0xF8A1,
+	0x9F72, 0xC654, 0x9F74, 0xF8EB, 0x9F75, 0xF8EC, 0x9F76, 0xF8ED,
+	0x9F77, 0xC653, 0x9F78, 0xF967, 0x9F79, 0xF96A, 0x9F7A, 0xF969,
+	0x9F7B, 0xF968, 0x9F7E, 0xF9D3, 0x9F8D, 0xC073, 0x9F90, 0xC365,
+	0x9F91, 0xF5BF, 0x9F92, 0xF6D5, 0x9F94, 0xC5C7, 0x9F95, 0xF7CE,
+	0x9F98, 0xF9D5, 0x9F9C, 0xC074, 0x9FA0, 0xEFB6, 0x9FA2, 0xF7CF,
+	0x9FA4, 0xF9A1, 0xFA0C, 0xC94A, 0xFA0D, 0xDDFC, 0xFE30, 0xA14A,
+	0xFE31, 0xA157, 0xFE33, 0xA159, 0xFE34, 0xA15B, 0xFE35, 0xA15F,
+	0xFE36, 0xA160, 0xFE37, 0xA163, 0xFE38, 0xA164, 0xFE39, 0xA167,
+	0xFE3A, 0xA168, 0xFE3B, 0xA16B, 0xFE3C, 0xA16C, 0xFE3D, 0xA16F,
+	0xFE3E, 0xA170, 0xFE3F, 0xA173, 0xFE40, 0xA174, 0xFE41, 0xA177,
+	0xFE42, 0xA178, 0xFE43, 0xA17B, 0xFE44, 0xA17C, 0xFE49, 0xA1C6,
+	0xFE4A, 0xA1C7, 0xFE4B, 0xA1CA, 0xFE4C, 0xA1CB, 0xFE4D, 0xA1C8,
+	0xFE4E, 0xA1C9, 0xFE4F, 0xA15C, 0xFE50, 0xA14D, 0xFE51, 0xA14E,
+	0xFE52, 0xA14F, 0xFE54, 0xA151, 0xFE55, 0xA152, 0xFE56, 0xA153,
+	0xFE57, 0xA154, 0xFE59, 0xA17D, 0xFE5A, 0xA17E, 0xFE5B, 0xA1A1,
+	0xFE5C, 0xA1A2, 0xFE5D, 0xA1A3, 0xFE5E, 0xA1A4, 0xFE5F, 0xA1CC,
+	0xFE60, 0xA1CD, 0xFE61, 0xA1CE, 0xFE62, 0xA1DE, 0xFE63, 0xA1DF,
+	0xFE64, 0xA1E0, 0xFE65, 0xA1E1, 0xFE66, 0xA1E2, 0xFE68, 0xA242,
+	0xFE69, 0xA24C, 0xFE6A, 0xA24D, 0xFE6B, 0xA24E, 0xFF01, 0xA149,
+	0xFF03, 0xA1AD, 0xFF04, 0xA243, 0xFF05, 0xA248, 0xFF06, 0xA1AE,
+	0xFF08, 0xA15D, 0xFF09, 0xA15E, 0xFF0A, 0xA1AF, 0xFF0B, 0xA1CF,
+	0xFF0C, 0xA141, 0xFF0D, 0xA1D0, 0xFF0E, 0xA144, 0xFF0F, 0xA1FE,
+	0xFF10, 0xA2AF, 0xFF11, 0xA2B0, 0xFF12, 0xA2B1, 0xFF13, 0xA2B2,
+	0xFF14, 0xA2B3, 0xFF15, 0xA2B4, 0xFF16, 0xA2B5, 0xFF17, 0xA2B6,
+	0xFF18, 0xA2B7, 0xFF19, 0xA2B8, 0xFF1A, 0xA147, 0xFF1B, 0xA146,
+	0xFF1C, 0xA1D5, 0xFF1D, 0xA1D7, 0xFF1E, 0xA1D6, 0xFF1F, 0xA148,
+	0xFF20, 0xA249, 0xFF21, 0xA2CF, 0xFF22, 0xA2D0, 0xFF23, 0xA2D1,
+	0xFF24, 0xA2D2, 0xFF25, 0xA2D3, 0xFF26, 0xA2D4, 0xFF27, 0xA2D5,
+	0xFF28, 0xA2D6, 0xFF29, 0xA2D7, 0xFF2A, 0xA2D8, 0xFF2B, 0xA2D9,
+	0xFF2C, 0xA2DA, 0xFF2D, 0xA2DB, 0xFF2E, 0xA2DC, 0xFF2F, 0xA2DD,
+	0xFF30, 0xA2DE, 0xFF31, 0xA2DF, 0xFF32, 0xA2E0, 0xFF33, 0xA2E1,
+	0xFF34, 0xA2E2, 0xFF35, 0xA2E3, 0xFF36, 0xA2E4, 0xFF37, 0xA2E5,
+	0xFF38, 0xA2E6, 0xFF39, 0xA2E7, 0xFF3A, 0xA2E8, 0xFF3C, 0xA240,
+	0xFF3F, 0xA1C4, 0xFF41, 0xA2E9, 0xFF42, 0xA2EA, 0xFF43, 0xA2EB,
+	0xFF44, 0xA2EC, 0xFF45, 0xA2ED, 0xFF46, 0xA2EE, 0xFF47, 0xA2EF,
+	0xFF48, 0xA2F0, 0xFF49, 0xA2F1, 0xFF4A, 0xA2F2, 0xFF4B, 0xA2F3,
+	0xFF4C, 0xA2F4, 0xFF4D, 0xA2F5, 0xFF4E, 0xA2F6, 0xFF4F, 0xA2F7,
+	0xFF50, 0xA2F8, 0xFF51, 0xA2F9, 0xFF52, 0xA2FA, 0xFF53, 0xA2FB,
+	0xFF54, 0xA2FC, 0xFF55, 0xA2FD, 0xFF56, 0xA2FE, 0xFF57, 0xA340,
+	0xFF58, 0xA341, 0xFF59, 0xA342, 0xFF5A, 0xA343, 0xFF5B, 0xA161,
+	0xFF5C, 0xA155, 0xFF5D, 0xA162, 0xFF5E, 0xA1E3, 0xFFE0, 0xA246,
+	0xFFE1, 0xA247, 0xFFE3, 0xA1C3, 0xFFE5, 0xA244, 0, 0
+};
+
+static
+const WCHAR oem2uni[] = {
+/*	OEM - Unicode,  OEM - Unicode,  OEM - Unicode,  OEM - Unicode */
+	0xA140, 0x3000, 0xA141, 0xFF0C, 0xA142, 0x3001, 0xA143, 0x3002,
+	0xA144, 0xFF0E, 0xA145, 0x2027, 0xA146, 0xFF1B, 0xA147, 0xFF1A,
+	0xA148, 0xFF1F, 0xA149, 0xFF01, 0xA14A, 0xFE30, 0xA14B, 0x2026,
+	0xA14C, 0x2025, 0xA14D, 0xFE50, 0xA14E, 0xFE51, 0xA14F, 0xFE52,
+	0xA150, 0x00B7, 0xA151, 0xFE54, 0xA152, 0xFE55, 0xA153, 0xFE56,
+	0xA154, 0xFE57, 0xA155, 0xFF5C, 0xA156, 0x2013, 0xA157, 0xFE31,
+	0xA158, 0x2014, 0xA159, 0xFE33, 0xA15A, 0x2574, 0xA15B, 0xFE34,
+	0xA15C, 0xFE4F, 0xA15D, 0xFF08, 0xA15E, 0xFF09, 0xA15F, 0xFE35,
+	0xA160, 0xFE36, 0xA161, 0xFF5B, 0xA162, 0xFF5D, 0xA163, 0xFE37,
+	0xA164, 0xFE38, 0xA165, 0x3014, 0xA166, 0x3015, 0xA167, 0xFE39,
+	0xA168, 0xFE3A, 0xA169, 0x3010, 0xA16A, 0x3011, 0xA16B, 0xFE3B,
+	0xA16C, 0xFE3C, 0xA16D, 0x300A, 0xA16E, 0x300B, 0xA16F, 0xFE3D,
+	0xA170, 0xFE3E, 0xA171, 0x3008, 0xA172, 0x3009, 0xA173, 0xFE3F,
+	0xA174, 0xFE40, 0xA175, 0x300C, 0xA176, 0x300D, 0xA177, 0xFE41,
+	0xA178, 0xFE42, 0xA179, 0x300E, 0xA17A, 0x300F, 0xA17B, 0xFE43,
+	0xA17C, 0xFE44, 0xA17D, 0xFE59, 0xA17E, 0xFE5A, 0xA1A1, 0xFE5B,
+	0xA1A2, 0xFE5C, 0xA1A3, 0xFE5D, 0xA1A4, 0xFE5E, 0xA1A5, 0x2018,
+	0xA1A6, 0x2019, 0xA1A7, 0x201C, 0xA1A8, 0x201D, 0xA1A9, 0x301D,
+	0xA1AA, 0x301E, 0xA1AB, 0x2035, 0xA1AC, 0x2032, 0xA1AD, 0xFF03,
+	0xA1AE, 0xFF06, 0xA1AF, 0xFF0A, 0xA1B0, 0x203B, 0xA1B1, 0x00A7,
+	0xA1B2, 0x3003, 0xA1B3, 0x25CB, 0xA1B4, 0x25CF, 0xA1B5, 0x25B3,
+	0xA1B6, 0x25B2, 0xA1B7, 0x25CE, 0xA1B8, 0x2606, 0xA1B9, 0x2605,
+	0xA1BA, 0x25C7, 0xA1BB, 0x25C6, 0xA1BC, 0x25A1, 0xA1BD, 0x25A0,
+	0xA1BE, 0x25BD, 0xA1BF, 0x25BC, 0xA1C0, 0x32A3, 0xA1C1, 0x2105,
+	0xA1C2, 0x00AF, 0xA1C3, 0xFFE3, 0xA1C4, 0xFF3F, 0xA1C5, 0x02CD,
+	0xA1C6, 0xFE49, 0xA1C7, 0xFE4A, 0xA1C8, 0xFE4D, 0xA1C9, 0xFE4E,
+	0xA1CA, 0xFE4B, 0xA1CB, 0xFE4C, 0xA1CC, 0xFE5F, 0xA1CD, 0xFE60,
+	0xA1CE, 0xFE61, 0xA1CF, 0xFF0B, 0xA1D0, 0xFF0D, 0xA1D1, 0x00D7,
+	0xA1D2, 0x00F7, 0xA1D3, 0x00B1, 0xA1D4, 0x221A, 0xA1D5, 0xFF1C,
+	0xA1D6, 0xFF1E, 0xA1D7, 0xFF1D, 0xA1D8, 0x2266, 0xA1D9, 0x2267,
+	0xA1DA, 0x2260, 0xA1DB, 0x221E, 0xA1DC, 0x2252, 0xA1DD, 0x2261,
+	0xA1DE, 0xFE62, 0xA1DF, 0xFE63, 0xA1E0, 0xFE64, 0xA1E1, 0xFE65,
+	0xA1E2, 0xFE66, 0xA1E3, 0xFF5E, 0xA1E4, 0x2229, 0xA1E5, 0x222A,
+	0xA1E6, 0x22A5, 0xA1E7, 0x2220, 0xA1E8, 0x221F, 0xA1E9, 0x22BF,
+	0xA1EA, 0x33D2, 0xA1EB, 0x33D1, 0xA1EC, 0x222B, 0xA1ED, 0x222E,
+	0xA1EE, 0x2235, 0xA1EF, 0x2234, 0xA1F0, 0x2640, 0xA1F1, 0x2642,
+	0xA1F2, 0x2295, 0xA1F3, 0x2299, 0xA1F4, 0x2191, 0xA1F5, 0x2193,
+	0xA1F6, 0x2190, 0xA1F7, 0x2192, 0xA1F8, 0x2196, 0xA1F9, 0x2197,
+	0xA1FA, 0x2199, 0xA1FB, 0x2198, 0xA1FC, 0x2225, 0xA1FD, 0x2223,
+	0xA1FE, 0xFF0F, 0xA240, 0xFF3C, 0xA241, 0x2215, 0xA242, 0xFE68,
+	0xA243, 0xFF04, 0xA244, 0xFFE5, 0xA245, 0x3012, 0xA246, 0xFFE0,
+	0xA247, 0xFFE1, 0xA248, 0xFF05, 0xA249, 0xFF20, 0xA24A, 0x2103,
+	0xA24B, 0x2109, 0xA24C, 0xFE69, 0xA24D, 0xFE6A, 0xA24E, 0xFE6B,
+	0xA24F, 0x33D5, 0xA250, 0x339C, 0xA251, 0x339D, 0xA252, 0x339E,
+	0xA253, 0x33CE, 0xA254, 0x33A1, 0xA255, 0x338E, 0xA256, 0x338F,
+	0xA257, 0x33C4, 0xA258, 0x00B0, 0xA259, 0x5159, 0xA25A, 0x515B,
+	0xA25B, 0x515E, 0xA25C, 0x515D, 0xA25D, 0x5161, 0xA25E, 0x5163,
+	0xA25F, 0x55E7, 0xA260, 0x74E9, 0xA261, 0x7CCE, 0xA262, 0x2581,
+	0xA263, 0x2582, 0xA264, 0x2583, 0xA265, 0x2584, 0xA266, 0x2585,
+	0xA267, 0x2586, 0xA268, 0x2587, 0xA269, 0x2588, 0xA26A, 0x258F,
+	0xA26B, 0x258E, 0xA26C, 0x258D, 0xA26D, 0x258C, 0xA26E, 0x258B,
+	0xA26F, 0x258A, 0xA270, 0x2589, 0xA271, 0x253C, 0xA272, 0x2534,
+	0xA273, 0x252C, 0xA274, 0x2524, 0xA275, 0x251C, 0xA276, 0x2594,
+	0xA277, 0x2500, 0xA278, 0x2502, 0xA279, 0x2595, 0xA27A, 0x250C,
+	0xA27B, 0x2510, 0xA27C, 0x2514, 0xA27D, 0x2518, 0xA27E, 0x256D,
+	0xA2A1, 0x256E, 0xA2A2, 0x2570, 0xA2A3, 0x256F, 0xA2A4, 0x2550,
+	0xA2A5, 0x255E, 0xA2A6, 0x256A, 0xA2A7, 0x2561, 0xA2A8, 0x25E2,
+	0xA2A9, 0x25E3, 0xA2AA, 0x25E5, 0xA2AB, 0x25E4, 0xA2AC, 0x2571,
+	0xA2AD, 0x2572, 0xA2AE, 0x2573, 0xA2AF, 0xFF10, 0xA2B0, 0xFF11,
+	0xA2B1, 0xFF12, 0xA2B2, 0xFF13, 0xA2B3, 0xFF14, 0xA2B4, 0xFF15,
+	0xA2B5, 0xFF16, 0xA2B6, 0xFF17, 0xA2B7, 0xFF18, 0xA2B8, 0xFF19,
+	0xA2B9, 0x2160, 0xA2BA, 0x2161, 0xA2BB, 0x2162, 0xA2BC, 0x2163,
+	0xA2BD, 0x2164, 0xA2BE, 0x2165, 0xA2BF, 0x2166, 0xA2C0, 0x2167,
+	0xA2C1, 0x2168, 0xA2C2, 0x2169, 0xA2C3, 0x3021, 0xA2C4, 0x3022,
+	0xA2C5, 0x3023, 0xA2C6, 0x3024, 0xA2C7, 0x3025, 0xA2C8, 0x3026,
+	0xA2C9, 0x3027, 0xA2CA, 0x3028, 0xA2CB, 0x3029, 0xA2CC, 0x5341,
+	0xA2CD, 0x5344, 0xA2CE, 0x5345, 0xA2CF, 0xFF21, 0xA2D0, 0xFF22,
+	0xA2D1, 0xFF23, 0xA2D2, 0xFF24, 0xA2D3, 0xFF25, 0xA2D4, 0xFF26,
+	0xA2D5, 0xFF27, 0xA2D6, 0xFF28, 0xA2D7, 0xFF29, 0xA2D8, 0xFF2A,
+	0xA2D9, 0xFF2B, 0xA2DA, 0xFF2C, 0xA2DB, 0xFF2D, 0xA2DC, 0xFF2E,
+	0xA2DD, 0xFF2F, 0xA2DE, 0xFF30, 0xA2DF, 0xFF31, 0xA2E0, 0xFF32,
+	0xA2E1, 0xFF33, 0xA2E2, 0xFF34, 0xA2E3, 0xFF35, 0xA2E4, 0xFF36,
+	0xA2E5, 0xFF37, 0xA2E6, 0xFF38, 0xA2E7, 0xFF39, 0xA2E8, 0xFF3A,
+	0xA2E9, 0xFF41, 0xA2EA, 0xFF42, 0xA2EB, 0xFF43, 0xA2EC, 0xFF44,
+	0xA2ED, 0xFF45, 0xA2EE, 0xFF46, 0xA2EF, 0xFF47, 0xA2F0, 0xFF48,
+	0xA2F1, 0xFF49, 0xA2F2, 0xFF4A, 0xA2F3, 0xFF4B, 0xA2F4, 0xFF4C,
+	0xA2F5, 0xFF4D, 0xA2F6, 0xFF4E, 0xA2F7, 0xFF4F, 0xA2F8, 0xFF50,
+	0xA2F9, 0xFF51, 0xA2FA, 0xFF52, 0xA2FB, 0xFF53, 0xA2FC, 0xFF54,
+	0xA2FD, 0xFF55, 0xA2FE, 0xFF56, 0xA340, 0xFF57, 0xA341, 0xFF58,
+	0xA342, 0xFF59, 0xA343, 0xFF5A, 0xA344, 0x0391, 0xA345, 0x0392,
+	0xA346, 0x0393, 0xA347, 0x0394, 0xA348, 0x0395, 0xA349, 0x0396,
+	0xA34A, 0x0397, 0xA34B, 0x0398, 0xA34C, 0x0399, 0xA34D, 0x039A,
+	0xA34E, 0x039B, 0xA34F, 0x039C, 0xA350, 0x039D, 0xA351, 0x039E,
+	0xA352, 0x039F, 0xA353, 0x03A0, 0xA354, 0x03A1, 0xA355, 0x03A3,
+	0xA356, 0x03A4, 0xA357, 0x03A5, 0xA358, 0x03A6, 0xA359, 0x03A7,
+	0xA35A, 0x03A8, 0xA35B, 0x03A9, 0xA35C, 0x03B1, 0xA35D, 0x03B2,
+	0xA35E, 0x03B3, 0xA35F, 0x03B4, 0xA360, 0x03B5, 0xA361, 0x03B6,
+	0xA362, 0x03B7, 0xA363, 0x03B8, 0xA364, 0x03B9, 0xA365, 0x03BA,
+	0xA366, 0x03BB, 0xA367, 0x03BC, 0xA368, 0x03BD, 0xA369, 0x03BE,
+	0xA36A, 0x03BF, 0xA36B, 0x03C0, 0xA36C, 0x03C1, 0xA36D, 0x03C3,
+	0xA36E, 0x03C4, 0xA36F, 0x03C5, 0xA370, 0x03C6, 0xA371, 0x03C7,
+	0xA372, 0x03C8, 0xA373, 0x03C9, 0xA374, 0x3105, 0xA375, 0x3106,
+	0xA376, 0x3107, 0xA377, 0x3108, 0xA378, 0x3109, 0xA379, 0x310A,
+	0xA37A, 0x310B, 0xA37B, 0x310C, 0xA37C, 0x310D, 0xA37D, 0x310E,
+	0xA37E, 0x310F, 0xA3A1, 0x3110, 0xA3A2, 0x3111, 0xA3A3, 0x3112,
+	0xA3A4, 0x3113, 0xA3A5, 0x3114, 0xA3A6, 0x3115, 0xA3A7, 0x3116,
+	0xA3A8, 0x3117, 0xA3A9, 0x3118, 0xA3AA, 0x3119, 0xA3AB, 0x311A,
+	0xA3AC, 0x311B, 0xA3AD, 0x311C, 0xA3AE, 0x311D, 0xA3AF, 0x311E,
+	0xA3B0, 0x311F, 0xA3B1, 0x3120, 0xA3B2, 0x3121, 0xA3B3, 0x3122,
+	0xA3B4, 0x3123, 0xA3B5, 0x3124, 0xA3B6, 0x3125, 0xA3B7, 0x3126,
+	0xA3B8, 0x3127, 0xA3B9, 0x3128, 0xA3BA, 0x3129, 0xA3BB, 0x02D9,
+	0xA3BC, 0x02C9, 0xA3BD, 0x02CA, 0xA3BE, 0x02C7, 0xA3BF, 0x02CB,
+	0xA3E1, 0x20AC, 0xA440, 0x4E00, 0xA441, 0x4E59, 0xA442, 0x4E01,
+	0xA443, 0x4E03, 0xA444, 0x4E43, 0xA445, 0x4E5D, 0xA446, 0x4E86,
+	0xA447, 0x4E8C, 0xA448, 0x4EBA, 0xA449, 0x513F, 0xA44A, 0x5165,
+	0xA44B, 0x516B, 0xA44C, 0x51E0, 0xA44D, 0x5200, 0xA44E, 0x5201,
+	0xA44F, 0x529B, 0xA450, 0x5315, 0xA451, 0x5341, 0xA452, 0x535C,
+	0xA453, 0x53C8, 0xA454, 0x4E09, 0xA455, 0x4E0B, 0xA456, 0x4E08,
+	0xA457, 0x4E0A, 0xA458, 0x4E2B, 0xA459, 0x4E38, 0xA45A, 0x51E1,
+	0xA45B, 0x4E45, 0xA45C, 0x4E48, 0xA45D, 0x4E5F, 0xA45E, 0x4E5E,
+	0xA45F, 0x4E8E, 0xA460, 0x4EA1, 0xA461, 0x5140, 0xA462, 0x5203,
+	0xA463, 0x52FA, 0xA464, 0x5343, 0xA465, 0x53C9, 0xA466, 0x53E3,
+	0xA467, 0x571F, 0xA468, 0x58EB, 0xA469, 0x5915, 0xA46A, 0x5927,
+	0xA46B, 0x5973, 0xA46C, 0x5B50, 0xA46D, 0x5B51, 0xA46E, 0x5B53,
+	0xA46F, 0x5BF8, 0xA470, 0x5C0F, 0xA471, 0x5C22, 0xA472, 0x5C38,
+	0xA473, 0x5C71, 0xA474, 0x5DDD, 0xA475, 0x5DE5, 0xA476, 0x5DF1,
+	0xA477, 0x5DF2, 0xA478, 0x5DF3, 0xA479, 0x5DFE, 0xA47A, 0x5E72,
+	0xA47B, 0x5EFE, 0xA47C, 0x5F0B, 0xA47D, 0x5F13, 0xA47E, 0x624D,
+	0xA4A1, 0x4E11, 0xA4A2, 0x4E10, 0xA4A3, 0x4E0D, 0xA4A4, 0x4E2D,
+	0xA4A5, 0x4E30, 0xA4A6, 0x4E39, 0xA4A7, 0x4E4B, 0xA4A8, 0x5C39,
+	0xA4A9, 0x4E88, 0xA4AA, 0x4E91, 0xA4AB, 0x4E95, 0xA4AC, 0x4E92,
+	0xA4AD, 0x4E94, 0xA4AE, 0x4EA2, 0xA4AF, 0x4EC1, 0xA4B0, 0x4EC0,
+	0xA4B1, 0x4EC3, 0xA4B2, 0x4EC6, 0xA4B3, 0x4EC7, 0xA4B4, 0x4ECD,
+	0xA4B5, 0x4ECA, 0xA4B6, 0x4ECB, 0xA4B7, 0x4EC4, 0xA4B8, 0x5143,
+	0xA4B9, 0x5141, 0xA4BA, 0x5167, 0xA4BB, 0x516D, 0xA4BC, 0x516E,
+	0xA4BD, 0x516C, 0xA4BE, 0x5197, 0xA4BF, 0x51F6, 0xA4C0, 0x5206,
+	0xA4C1, 0x5207, 0xA4C2, 0x5208, 0xA4C3, 0x52FB, 0xA4C4, 0x52FE,
+	0xA4C5, 0x52FF, 0xA4C6, 0x5316, 0xA4C7, 0x5339, 0xA4C8, 0x5348,
+	0xA4C9, 0x5347, 0xA4CA, 0x5345, 0xA4CB, 0x535E, 0xA4CC, 0x5384,
+	0xA4CD, 0x53CB, 0xA4CE, 0x53CA, 0xA4CF, 0x53CD, 0xA4D0, 0x58EC,
+	0xA4D1, 0x5929, 0xA4D2, 0x592B, 0xA4D3, 0x592A, 0xA4D4, 0x592D,
+	0xA4D5, 0x5B54, 0xA4D6, 0x5C11, 0xA4D7, 0x5C24, 0xA4D8, 0x5C3A,
+	0xA4D9, 0x5C6F, 0xA4DA, 0x5DF4, 0xA4DB, 0x5E7B, 0xA4DC, 0x5EFF,
+	0xA4DD, 0x5F14, 0xA4DE, 0x5F15, 0xA4DF, 0x5FC3, 0xA4E0, 0x6208,
+	0xA4E1, 0x6236, 0xA4E2, 0x624B, 0xA4E3, 0x624E, 0xA4E4, 0x652F,
+	0xA4E5, 0x6587, 0xA4E6, 0x6597, 0xA4E7, 0x65A4, 0xA4E8, 0x65B9,
+	0xA4E9, 0x65E5, 0xA4EA, 0x66F0, 0xA4EB, 0x6708, 0xA4EC, 0x6728,
+	0xA4ED, 0x6B20, 0xA4EE, 0x6B62, 0xA4EF, 0x6B79, 0xA4F0, 0x6BCB,
+	0xA4F1, 0x6BD4, 0xA4F2, 0x6BDB, 0xA4F3, 0x6C0F, 0xA4F4, 0x6C34,
+	0xA4F5, 0x706B, 0xA4F6, 0x722A, 0xA4F7, 0x7236, 0xA4F8, 0x723B,
+	0xA4F9, 0x7247, 0xA4FA, 0x7259, 0xA4FB, 0x725B, 0xA4FC, 0x72AC,
+	0xA4FD, 0x738B, 0xA4FE, 0x4E19, 0xA540, 0x4E16, 0xA541, 0x4E15,
+	0xA542, 0x4E14, 0xA543, 0x4E18, 0xA544, 0x4E3B, 0xA545, 0x4E4D,
+	0xA546, 0x4E4F, 0xA547, 0x4E4E, 0xA548, 0x4EE5, 0xA549, 0x4ED8,
+	0xA54A, 0x4ED4, 0xA54B, 0x4ED5, 0xA54C, 0x4ED6, 0xA54D, 0x4ED7,
+	0xA54E, 0x4EE3, 0xA54F, 0x4EE4, 0xA550, 0x4ED9, 0xA551, 0x4EDE,
+	0xA552, 0x5145, 0xA553, 0x5144, 0xA554, 0x5189, 0xA555, 0x518A,
+	0xA556, 0x51AC, 0xA557, 0x51F9, 0xA558, 0x51FA, 0xA559, 0x51F8,
+	0xA55A, 0x520A, 0xA55B, 0x52A0, 0xA55C, 0x529F, 0xA55D, 0x5305,
+	0xA55E, 0x5306, 0xA55F, 0x5317, 0xA560, 0x531D, 0xA561, 0x4EDF,
+	0xA562, 0x534A, 0xA563, 0x5349, 0xA564, 0x5361, 0xA565, 0x5360,
+	0xA566, 0x536F, 0xA567, 0x536E, 0xA568, 0x53BB, 0xA569, 0x53EF,
+	0xA56A, 0x53E4, 0xA56B, 0x53F3, 0xA56C, 0x53EC, 0xA56D, 0x53EE,
+	0xA56E, 0x53E9, 0xA56F, 0x53E8, 0xA570, 0x53FC, 0xA571, 0x53F8,
+	0xA572, 0x53F5, 0xA573, 0x53EB, 0xA574, 0x53E6, 0xA575, 0x53EA,
+	0xA576, 0x53F2, 0xA577, 0x53F1, 0xA578, 0x53F0, 0xA579, 0x53E5,
+	0xA57A, 0x53ED, 0xA57B, 0x53FB, 0xA57C, 0x56DB, 0xA57D, 0x56DA,
+	0xA57E, 0x5916, 0xA5A1, 0x592E, 0xA5A2, 0x5931, 0xA5A3, 0x5974,
+	0xA5A4, 0x5976, 0xA5A5, 0x5B55, 0xA5A6, 0x5B83, 0xA5A7, 0x5C3C,
+	0xA5A8, 0x5DE8, 0xA5A9, 0x5DE7, 0xA5AA, 0x5DE6, 0xA5AB, 0x5E02,
+	0xA5AC, 0x5E03, 0xA5AD, 0x5E73, 0xA5AE, 0x5E7C, 0xA5AF, 0x5F01,
+	0xA5B0, 0x5F18, 0xA5B1, 0x5F17, 0xA5B2, 0x5FC5, 0xA5B3, 0x620A,
+	0xA5B4, 0x6253, 0xA5B5, 0x6254, 0xA5B6, 0x6252, 0xA5B7, 0x6251,
+	0xA5B8, 0x65A5, 0xA5B9, 0x65E6, 0xA5BA, 0x672E, 0xA5BB, 0x672C,
+	0xA5BC, 0x672A, 0xA5BD, 0x672B, 0xA5BE, 0x672D, 0xA5BF, 0x6B63,
+	0xA5C0, 0x6BCD, 0xA5C1, 0x6C11, 0xA5C2, 0x6C10, 0xA5C3, 0x6C38,
+	0xA5C4, 0x6C41, 0xA5C5, 0x6C40, 0xA5C6, 0x6C3E, 0xA5C7, 0x72AF,
+	0xA5C8, 0x7384, 0xA5C9, 0x7389, 0xA5CA, 0x74DC, 0xA5CB, 0x74E6,
+	0xA5CC, 0x7518, 0xA5CD, 0x751F, 0xA5CE, 0x7528, 0xA5CF, 0x7529,
+	0xA5D0, 0x7530, 0xA5D1, 0x7531, 0xA5D2, 0x7532, 0xA5D3, 0x7533,
+	0xA5D4, 0x758B, 0xA5D5, 0x767D, 0xA5D6, 0x76AE, 0xA5D7, 0x76BF,
+	0xA5D8, 0x76EE, 0xA5D9, 0x77DB, 0xA5DA, 0x77E2, 0xA5DB, 0x77F3,
+	0xA5DC, 0x793A, 0xA5DD, 0x79BE, 0xA5DE, 0x7A74, 0xA5DF, 0x7ACB,
+	0xA5E0, 0x4E1E, 0xA5E1, 0x4E1F, 0xA5E2, 0x4E52, 0xA5E3, 0x4E53,
+	0xA5E4, 0x4E69, 0xA5E5, 0x4E99, 0xA5E6, 0x4EA4, 0xA5E7, 0x4EA6,
+	0xA5E8, 0x4EA5, 0xA5E9, 0x4EFF, 0xA5EA, 0x4F09, 0xA5EB, 0x4F19,
+	0xA5EC, 0x4F0A, 0xA5ED, 0x4F15, 0xA5EE, 0x4F0D, 0xA5EF, 0x4F10,
+	0xA5F0, 0x4F11, 0xA5F1, 0x4F0F, 0xA5F2, 0x4EF2, 0xA5F3, 0x4EF6,
+	0xA5F4, 0x4EFB, 0xA5F5, 0x4EF0, 0xA5F6, 0x4EF3, 0xA5F7, 0x4EFD,
+	0xA5F8, 0x4F01, 0xA5F9, 0x4F0B, 0xA5FA, 0x5149, 0xA5FB, 0x5147,
+	0xA5FC, 0x5146, 0xA5FD, 0x5148, 0xA5FE, 0x5168, 0xA640, 0x5171,
+	0xA641, 0x518D, 0xA642, 0x51B0, 0xA643, 0x5217, 0xA644, 0x5211,
+	0xA645, 0x5212, 0xA646, 0x520E, 0xA647, 0x5216, 0xA648, 0x52A3,
+	0xA649, 0x5308, 0xA64A, 0x5321, 0xA64B, 0x5320, 0xA64C, 0x5370,
+	0xA64D, 0x5371, 0xA64E, 0x5409, 0xA64F, 0x540F, 0xA650, 0x540C,
+	0xA651, 0x540A, 0xA652, 0x5410, 0xA653, 0x5401, 0xA654, 0x540B,
+	0xA655, 0x5404, 0xA656, 0x5411, 0xA657, 0x540D, 0xA658, 0x5408,
+	0xA659, 0x5403, 0xA65A, 0x540E, 0xA65B, 0x5406, 0xA65C, 0x5412,
+	0xA65D, 0x56E0, 0xA65E, 0x56DE, 0xA65F, 0x56DD, 0xA660, 0x5733,
+	0xA661, 0x5730, 0xA662, 0x5728, 0xA663, 0x572D, 0xA664, 0x572C,
+	0xA665, 0x572F, 0xA666, 0x5729, 0xA667, 0x5919, 0xA668, 0x591A,
+	0xA669, 0x5937, 0xA66A, 0x5938, 0xA66B, 0x5984, 0xA66C, 0x5978,
+	0xA66D, 0x5983, 0xA66E, 0x597D, 0xA66F, 0x5979, 0xA670, 0x5982,
+	0xA671, 0x5981, 0xA672, 0x5B57, 0xA673, 0x5B58, 0xA674, 0x5B87,
+	0xA675, 0x5B88, 0xA676, 0x5B85, 0xA677, 0x5B89, 0xA678, 0x5BFA,
+	0xA679, 0x5C16, 0xA67A, 0x5C79, 0xA67B, 0x5DDE, 0xA67C, 0x5E06,
+	0xA67D, 0x5E76, 0xA67E, 0x5E74, 0xA6A1, 0x5F0F, 0xA6A2, 0x5F1B,
+	0xA6A3, 0x5FD9, 0xA6A4, 0x5FD6, 0xA6A5, 0x620E, 0xA6A6, 0x620C,
+	0xA6A7, 0x620D, 0xA6A8, 0x6210, 0xA6A9, 0x6263, 0xA6AA, 0x625B,
+	0xA6AB, 0x6258, 0xA6AC, 0x6536, 0xA6AD, 0x65E9, 0xA6AE, 0x65E8,
+	0xA6AF, 0x65EC, 0xA6B0, 0x65ED, 0xA6B1, 0x66F2, 0xA6B2, 0x66F3,
+	0xA6B3, 0x6709, 0xA6B4, 0x673D, 0xA6B5, 0x6734, 0xA6B6, 0x6731,
+	0xA6B7, 0x6735, 0xA6B8, 0x6B21, 0xA6B9, 0x6B64, 0xA6BA, 0x6B7B,
+	0xA6BB, 0x6C16, 0xA6BC, 0x6C5D, 0xA6BD, 0x6C57, 0xA6BE, 0x6C59,
+	0xA6BF, 0x6C5F, 0xA6C0, 0x6C60, 0xA6C1, 0x6C50, 0xA6C2, 0x6C55,
+	0xA6C3, 0x6C61, 0xA6C4, 0x6C5B, 0xA6C5, 0x6C4D, 0xA6C6, 0x6C4E,
+	0xA6C7, 0x7070, 0xA6C8, 0x725F, 0xA6C9, 0x725D, 0xA6CA, 0x767E,
+	0xA6CB, 0x7AF9, 0xA6CC, 0x7C73, 0xA6CD, 0x7CF8, 0xA6CE, 0x7F36,
+	0xA6CF, 0x7F8A, 0xA6D0, 0x7FBD, 0xA6D1, 0x8001, 0xA6D2, 0x8003,
+	0xA6D3, 0x800C, 0xA6D4, 0x8012, 0xA6D5, 0x8033, 0xA6D6, 0x807F,
+	0xA6D7, 0x8089, 0xA6D8, 0x808B, 0xA6D9, 0x808C, 0xA6DA, 0x81E3,
+	0xA6DB, 0x81EA, 0xA6DC, 0x81F3, 0xA6DD, 0x81FC, 0xA6DE, 0x820C,
+	0xA6DF, 0x821B, 0xA6E0, 0x821F, 0xA6E1, 0x826E, 0xA6E2, 0x8272,
+	0xA6E3, 0x827E, 0xA6E4, 0x866B, 0xA6E5, 0x8840, 0xA6E6, 0x884C,
+	0xA6E7, 0x8863, 0xA6E8, 0x897F, 0xA6E9, 0x9621, 0xA6EA, 0x4E32,
+	0xA6EB, 0x4EA8, 0xA6EC, 0x4F4D, 0xA6ED, 0x4F4F, 0xA6EE, 0x4F47,
+	0xA6EF, 0x4F57, 0xA6F0, 0x4F5E, 0xA6F1, 0x4F34, 0xA6F2, 0x4F5B,
+	0xA6F3, 0x4F55, 0xA6F4, 0x4F30, 0xA6F5, 0x4F50, 0xA6F6, 0x4F51,
+	0xA6F7, 0x4F3D, 0xA6F8, 0x4F3A, 0xA6F9, 0x4F38, 0xA6FA, 0x4F43,
+	0xA6FB, 0x4F54, 0xA6FC, 0x4F3C, 0xA6FD, 0x4F46, 0xA6FE, 0x4F63,
+	0xA740, 0x4F5C, 0xA741, 0x4F60, 0xA742, 0x4F2F, 0xA743, 0x4F4E,
+	0xA744, 0x4F36, 0xA745, 0x4F59, 0xA746, 0x4F5D, 0xA747, 0x4F48,
+	0xA748, 0x4F5A, 0xA749, 0x514C, 0xA74A, 0x514B, 0xA74B, 0x514D,
+	0xA74C, 0x5175, 0xA74D, 0x51B6, 0xA74E, 0x51B7, 0xA74F, 0x5225,
+	0xA750, 0x5224, 0xA751, 0x5229, 0xA752, 0x522A, 0xA753, 0x5228,
+	0xA754, 0x52AB, 0xA755, 0x52A9, 0xA756, 0x52AA, 0xA757, 0x52AC,
+	0xA758, 0x5323, 0xA759, 0x5373, 0xA75A, 0x5375, 0xA75B, 0x541D,
+	0xA75C, 0x542D, 0xA75D, 0x541E, 0xA75E, 0x543E, 0xA75F, 0x5426,
+	0xA760, 0x544E, 0xA761, 0x5427, 0xA762, 0x5446, 0xA763, 0x5443,
+	0xA764, 0x5433, 0xA765, 0x5448, 0xA766, 0x5442, 0xA767, 0x541B,
+	0xA768, 0x5429, 0xA769, 0x544A, 0xA76A, 0x5439, 0xA76B, 0x543B,
+	0xA76C, 0x5438, 0xA76D, 0x542E, 0xA76E, 0x5435, 0xA76F, 0x5436,
+	0xA770, 0x5420, 0xA771, 0x543C, 0xA772, 0x5440, 0xA773, 0x5431,
+	0xA774, 0x542B, 0xA775, 0x541F, 0xA776, 0x542C, 0xA777, 0x56EA,
+	0xA778, 0x56F0, 0xA779, 0x56E4, 0xA77A, 0x56EB, 0xA77B, 0x574A,
+	0xA77C, 0x5751, 0xA77D, 0x5740, 0xA77E, 0x574D, 0xA7A1, 0x5747,
+	0xA7A2, 0x574E, 0xA7A3, 0x573E, 0xA7A4, 0x5750, 0xA7A5, 0x574F,
+	0xA7A6, 0x573B, 0xA7A7, 0x58EF, 0xA7A8, 0x593E, 0xA7A9, 0x599D,
+	0xA7AA, 0x5992, 0xA7AB, 0x59A8, 0xA7AC, 0x599E, 0xA7AD, 0x59A3,
+	0xA7AE, 0x5999, 0xA7AF, 0x5996, 0xA7B0, 0x598D, 0xA7B1, 0x59A4,
+	0xA7B2, 0x5993, 0xA7B3, 0x598A, 0xA7B4, 0x59A5, 0xA7B5, 0x5B5D,
+	0xA7B6, 0x5B5C, 0xA7B7, 0x5B5A, 0xA7B8, 0x5B5B, 0xA7B9, 0x5B8C,
+	0xA7BA, 0x5B8B, 0xA7BB, 0x5B8F, 0xA7BC, 0x5C2C, 0xA7BD, 0x5C40,
+	0xA7BE, 0x5C41, 0xA7BF, 0x5C3F, 0xA7C0, 0x5C3E, 0xA7C1, 0x5C90,
+	0xA7C2, 0x5C91, 0xA7C3, 0x5C94, 0xA7C4, 0x5C8C, 0xA7C5, 0x5DEB,
+	0xA7C6, 0x5E0C, 0xA7C7, 0x5E8F, 0xA7C8, 0x5E87, 0xA7C9, 0x5E8A,
+	0xA7CA, 0x5EF7, 0xA7CB, 0x5F04, 0xA7CC, 0x5F1F, 0xA7CD, 0x5F64,
+	0xA7CE, 0x5F62, 0xA7CF, 0x5F77, 0xA7D0, 0x5F79, 0xA7D1, 0x5FD8,
+	0xA7D2, 0x5FCC, 0xA7D3, 0x5FD7, 0xA7D4, 0x5FCD, 0xA7D5, 0x5FF1,
+	0xA7D6, 0x5FEB, 0xA7D7, 0x5FF8, 0xA7D8, 0x5FEA, 0xA7D9, 0x6212,
+	0xA7DA, 0x6211, 0xA7DB, 0x6284, 0xA7DC, 0x6297, 0xA7DD, 0x6296,
+	0xA7DE, 0x6280, 0xA7DF, 0x6276, 0xA7E0, 0x6289, 0xA7E1, 0x626D,
+	0xA7E2, 0x628A, 0xA7E3, 0x627C, 0xA7E4, 0x627E, 0xA7E5, 0x6279,
+	0xA7E6, 0x6273, 0xA7E7, 0x6292, 0xA7E8, 0x626F, 0xA7E9, 0x6298,
+	0xA7EA, 0x626E, 0xA7EB, 0x6295, 0xA7EC, 0x6293, 0xA7ED, 0x6291,
+	0xA7EE, 0x6286, 0xA7EF, 0x6539, 0xA7F0, 0x653B, 0xA7F1, 0x6538,
+	0xA7F2, 0x65F1, 0xA7F3, 0x66F4, 0xA7F4, 0x675F, 0xA7F5, 0x674E,
+	0xA7F6, 0x674F, 0xA7F7, 0x6750, 0xA7F8, 0x6751, 0xA7F9, 0x675C,
+	0xA7FA, 0x6756, 0xA7FB, 0x675E, 0xA7FC, 0x6749, 0xA7FD, 0x6746,
+	0xA7FE, 0x6760, 0xA840, 0x6753, 0xA841, 0x6757, 0xA842, 0x6B65,
+	0xA843, 0x6BCF, 0xA844, 0x6C42, 0xA845, 0x6C5E, 0xA846, 0x6C99,
+	0xA847, 0x6C81, 0xA848, 0x6C88, 0xA849, 0x6C89, 0xA84A, 0x6C85,
+	0xA84B, 0x6C9B, 0xA84C, 0x6C6A, 0xA84D, 0x6C7A, 0xA84E, 0x6C90,
+	0xA84F, 0x6C70, 0xA850, 0x6C8C, 0xA851, 0x6C68, 0xA852, 0x6C96,
+	0xA853, 0x6C92, 0xA854, 0x6C7D, 0xA855, 0x6C83, 0xA856, 0x6C72,
+	0xA857, 0x6C7E, 0xA858, 0x6C74, 0xA859, 0x6C86, 0xA85A, 0x6C76,
+	0xA85B, 0x6C8D, 0xA85C, 0x6C94, 0xA85D, 0x6C98, 0xA85E, 0x6C82,
+	0xA85F, 0x7076, 0xA860, 0x707C, 0xA861, 0x707D, 0xA862, 0x7078,
+	0xA863, 0x7262, 0xA864, 0x7261, 0xA865, 0x7260, 0xA866, 0x72C4,
+	0xA867, 0x72C2, 0xA868, 0x7396, 0xA869, 0x752C, 0xA86A, 0x752B,
+	0xA86B, 0x7537, 0xA86C, 0x7538, 0xA86D, 0x7682, 0xA86E, 0x76EF,
+	0xA86F, 0x77E3, 0xA870, 0x79C1, 0xA871, 0x79C0, 0xA872, 0x79BF,
+	0xA873, 0x7A76, 0xA874, 0x7CFB, 0xA875, 0x7F55, 0xA876, 0x8096,
+	0xA877, 0x8093, 0xA878, 0x809D, 0xA879, 0x8098, 0xA87A, 0x809B,
+	0xA87B, 0x809A, 0xA87C, 0x80B2, 0xA87D, 0x826F, 0xA87E, 0x8292,
+	0xA8A1, 0x828B, 0xA8A2, 0x828D, 0xA8A3, 0x898B, 0xA8A4, 0x89D2,
+	0xA8A5, 0x8A00, 0xA8A6, 0x8C37, 0xA8A7, 0x8C46, 0xA8A8, 0x8C55,
+	0xA8A9, 0x8C9D, 0xA8AA, 0x8D64, 0xA8AB, 0x8D70, 0xA8AC, 0x8DB3,
+	0xA8AD, 0x8EAB, 0xA8AE, 0x8ECA, 0xA8AF, 0x8F9B, 0xA8B0, 0x8FB0,
+	0xA8B1, 0x8FC2, 0xA8B2, 0x8FC6, 0xA8B3, 0x8FC5, 0xA8B4, 0x8FC4,
+	0xA8B5, 0x5DE1, 0xA8B6, 0x9091, 0xA8B7, 0x90A2, 0xA8B8, 0x90AA,
+	0xA8B9, 0x90A6, 0xA8BA, 0x90A3, 0xA8BB, 0x9149, 0xA8BC, 0x91C6,
+	0xA8BD, 0x91CC, 0xA8BE, 0x9632, 0xA8BF, 0x962E, 0xA8C0, 0x9631,
+	0xA8C1, 0x962A, 0xA8C2, 0x962C, 0xA8C3, 0x4E26, 0xA8C4, 0x4E56,
+	0xA8C5, 0x4E73, 0xA8C6, 0x4E8B, 0xA8C7, 0x4E9B, 0xA8C8, 0x4E9E,
+	0xA8C9, 0x4EAB, 0xA8CA, 0x4EAC, 0xA8CB, 0x4F6F, 0xA8CC, 0x4F9D,
+	0xA8CD, 0x4F8D, 0xA8CE, 0x4F73, 0xA8CF, 0x4F7F, 0xA8D0, 0x4F6C,
+	0xA8D1, 0x4F9B, 0xA8D2, 0x4F8B, 0xA8D3, 0x4F86, 0xA8D4, 0x4F83,
+	0xA8D5, 0x4F70, 0xA8D6, 0x4F75, 0xA8D7, 0x4F88, 0xA8D8, 0x4F69,
+	0xA8D9, 0x4F7B, 0xA8DA, 0x4F96, 0xA8DB, 0x4F7E, 0xA8DC, 0x4F8F,
+	0xA8DD, 0x4F91, 0xA8DE, 0x4F7A, 0xA8DF, 0x5154, 0xA8E0, 0x5152,
+	0xA8E1, 0x5155, 0xA8E2, 0x5169, 0xA8E3, 0x5177, 0xA8E4, 0x5176,
+	0xA8E5, 0x5178, 0xA8E6, 0x51BD, 0xA8E7, 0x51FD, 0xA8E8, 0x523B,
+	0xA8E9, 0x5238, 0xA8EA, 0x5237, 0xA8EB, 0x523A, 0xA8EC, 0x5230,
+	0xA8ED, 0x522E, 0xA8EE, 0x5236, 0xA8EF, 0x5241, 0xA8F0, 0x52BE,
+	0xA8F1, 0x52BB, 0xA8F2, 0x5352, 0xA8F3, 0x5354, 0xA8F4, 0x5353,
+	0xA8F5, 0x5351, 0xA8F6, 0x5366, 0xA8F7, 0x5377, 0xA8F8, 0x5378,
+	0xA8F9, 0x5379, 0xA8FA, 0x53D6, 0xA8FB, 0x53D4, 0xA8FC, 0x53D7,
+	0xA8FD, 0x5473, 0xA8FE, 0x5475, 0xA940, 0x5496, 0xA941, 0x5478,
+	0xA942, 0x5495, 0xA943, 0x5480, 0xA944, 0x547B, 0xA945, 0x5477,
+	0xA946, 0x5484, 0xA947, 0x5492, 0xA948, 0x5486, 0xA949, 0x547C,
+	0xA94A, 0x5490, 0xA94B, 0x5471, 0xA94C, 0x5476, 0xA94D, 0x548C,
+	0xA94E, 0x549A, 0xA94F, 0x5462, 0xA950, 0x5468, 0xA951, 0x548B,
+	0xA952, 0x547D, 0xA953, 0x548E, 0xA954, 0x56FA, 0xA955, 0x5783,
+	0xA956, 0x5777, 0xA957, 0x576A, 0xA958, 0x5769, 0xA959, 0x5761,
+	0xA95A, 0x5766, 0xA95B, 0x5764, 0xA95C, 0x577C, 0xA95D, 0x591C,
+	0xA95E, 0x5949, 0xA95F, 0x5947, 0xA960, 0x5948, 0xA961, 0x5944,
+	0xA962, 0x5954, 0xA963, 0x59BE, 0xA964, 0x59BB, 0xA965, 0x59D4,
+	0xA966, 0x59B9, 0xA967, 0x59AE, 0xA968, 0x59D1, 0xA969, 0x59C6,
+	0xA96A, 0x59D0, 0xA96B, 0x59CD, 0xA96C, 0x59CB, 0xA96D, 0x59D3,
+	0xA96E, 0x59CA, 0xA96F, 0x59AF, 0xA970, 0x59B3, 0xA971, 0x59D2,
+	0xA972, 0x59C5, 0xA973, 0x5B5F, 0xA974, 0x5B64, 0xA975, 0x5B63,
+	0xA976, 0x5B97, 0xA977, 0x5B9A, 0xA978, 0x5B98, 0xA979, 0x5B9C,
+	0xA97A, 0x5B99, 0xA97B, 0x5B9B, 0xA97C, 0x5C1A, 0xA97D, 0x5C48,
+	0xA97E, 0x5C45, 0xA9A1, 0x5C46, 0xA9A2, 0x5CB7, 0xA9A3, 0x5CA1,
+	0xA9A4, 0x5CB8, 0xA9A5, 0x5CA9, 0xA9A6, 0x5CAB, 0xA9A7, 0x5CB1,
+	0xA9A8, 0x5CB3, 0xA9A9, 0x5E18, 0xA9AA, 0x5E1A, 0xA9AB, 0x5E16,
+	0xA9AC, 0x5E15, 0xA9AD, 0x5E1B, 0xA9AE, 0x5E11, 0xA9AF, 0x5E78,
+	0xA9B0, 0x5E9A, 0xA9B1, 0x5E97, 0xA9B2, 0x5E9C, 0xA9B3, 0x5E95,
+	0xA9B4, 0x5E96, 0xA9B5, 0x5EF6, 0xA9B6, 0x5F26, 0xA9B7, 0x5F27,
+	0xA9B8, 0x5F29, 0xA9B9, 0x5F80, 0xA9BA, 0x5F81, 0xA9BB, 0x5F7F,
+	0xA9BC, 0x5F7C, 0xA9BD, 0x5FDD, 0xA9BE, 0x5FE0, 0xA9BF, 0x5FFD,
+	0xA9C0, 0x5FF5, 0xA9C1, 0x5FFF, 0xA9C2, 0x600F, 0xA9C3, 0x6014,
+	0xA9C4, 0x602F, 0xA9C5, 0x6035, 0xA9C6, 0x6016, 0xA9C7, 0x602A,
+	0xA9C8, 0x6015, 0xA9C9, 0x6021, 0xA9CA, 0x6027, 0xA9CB, 0x6029,
+	0xA9CC, 0x602B, 0xA9CD, 0x601B, 0xA9CE, 0x6216, 0xA9CF, 0x6215,
+	0xA9D0, 0x623F, 0xA9D1, 0x623E, 0xA9D2, 0x6240, 0xA9D3, 0x627F,
+	0xA9D4, 0x62C9, 0xA9D5, 0x62CC, 0xA9D6, 0x62C4, 0xA9D7, 0x62BF,
+	0xA9D8, 0x62C2, 0xA9D9, 0x62B9, 0xA9DA, 0x62D2, 0xA9DB, 0x62DB,
+	0xA9DC, 0x62AB, 0xA9DD, 0x62D3, 0xA9DE, 0x62D4, 0xA9DF, 0x62CB,
+	0xA9E0, 0x62C8, 0xA9E1, 0x62A8, 0xA9E2, 0x62BD, 0xA9E3, 0x62BC,
+	0xA9E4, 0x62D0, 0xA9E5, 0x62D9, 0xA9E6, 0x62C7, 0xA9E7, 0x62CD,
+	0xA9E8, 0x62B5, 0xA9E9, 0x62DA, 0xA9EA, 0x62B1, 0xA9EB, 0x62D8,
+	0xA9EC, 0x62D6, 0xA9ED, 0x62D7, 0xA9EE, 0x62C6, 0xA9EF, 0x62AC,
+	0xA9F0, 0x62CE, 0xA9F1, 0x653E, 0xA9F2, 0x65A7, 0xA9F3, 0x65BC,
+	0xA9F4, 0x65FA, 0xA9F5, 0x6614, 0xA9F6, 0x6613, 0xA9F7, 0x660C,
+	0xA9F8, 0x6606, 0xA9F9, 0x6602, 0xA9FA, 0x660E, 0xA9FB, 0x6600,
+	0xA9FC, 0x660F, 0xA9FD, 0x6615, 0xA9FE, 0x660A, 0xAA40, 0x6607,
+	0xAA41, 0x670D, 0xAA42, 0x670B, 0xAA43, 0x676D, 0xAA44, 0x678B,
+	0xAA45, 0x6795, 0xAA46, 0x6771, 0xAA47, 0x679C, 0xAA48, 0x6773,
+	0xAA49, 0x6777, 0xAA4A, 0x6787, 0xAA4B, 0x679D, 0xAA4C, 0x6797,
+	0xAA4D, 0x676F, 0xAA4E, 0x6770, 0xAA4F, 0x677F, 0xAA50, 0x6789,
+	0xAA51, 0x677E, 0xAA52, 0x6790, 0xAA53, 0x6775, 0xAA54, 0x679A,
+	0xAA55, 0x6793, 0xAA56, 0x677C, 0xAA57, 0x676A, 0xAA58, 0x6772,
+	0xAA59, 0x6B23, 0xAA5A, 0x6B66, 0xAA5B, 0x6B67, 0xAA5C, 0x6B7F,
+	0xAA5D, 0x6C13, 0xAA5E, 0x6C1B, 0xAA5F, 0x6CE3, 0xAA60, 0x6CE8,
+	0xAA61, 0x6CF3, 0xAA62, 0x6CB1, 0xAA63, 0x6CCC, 0xAA64, 0x6CE5,
+	0xAA65, 0x6CB3, 0xAA66, 0x6CBD, 0xAA67, 0x6CBE, 0xAA68, 0x6CBC,
+	0xAA69, 0x6CE2, 0xAA6A, 0x6CAB, 0xAA6B, 0x6CD5, 0xAA6C, 0x6CD3,
+	0xAA6D, 0x6CB8, 0xAA6E, 0x6CC4, 0xAA6F, 0x6CB9, 0xAA70, 0x6CC1,
+	0xAA71, 0x6CAE, 0xAA72, 0x6CD7, 0xAA73, 0x6CC5, 0xAA74, 0x6CF1,
+	0xAA75, 0x6CBF, 0xAA76, 0x6CBB, 0xAA77, 0x6CE1, 0xAA78, 0x6CDB,
+	0xAA79, 0x6CCA, 0xAA7A, 0x6CAC, 0xAA7B, 0x6CEF, 0xAA7C, 0x6CDC,
+	0xAA7D, 0x6CD6, 0xAA7E, 0x6CE0, 0xAAA1, 0x7095, 0xAAA2, 0x708E,
+	0xAAA3, 0x7092, 0xAAA4, 0x708A, 0xAAA5, 0x7099, 0xAAA6, 0x722C,
+	0xAAA7, 0x722D, 0xAAA8, 0x7238, 0xAAA9, 0x7248, 0xAAAA, 0x7267,
+	0xAAAB, 0x7269, 0xAAAC, 0x72C0, 0xAAAD, 0x72CE, 0xAAAE, 0x72D9,
+	0xAAAF, 0x72D7, 0xAAB0, 0x72D0, 0xAAB1, 0x73A9, 0xAAB2, 0x73A8,
+	0xAAB3, 0x739F, 0xAAB4, 0x73AB, 0xAAB5, 0x73A5, 0xAAB6, 0x753D,
+	0xAAB7, 0x759D, 0xAAB8, 0x7599, 0xAAB9, 0x759A, 0xAABA, 0x7684,
+	0xAABB, 0x76C2, 0xAABC, 0x76F2, 0xAABD, 0x76F4, 0xAABE, 0x77E5,
+	0xAABF, 0x77FD, 0xAAC0, 0x793E, 0xAAC1, 0x7940, 0xAAC2, 0x7941,
+	0xAAC3, 0x79C9, 0xAAC4, 0x79C8, 0xAAC5, 0x7A7A, 0xAAC6, 0x7A79,
+	0xAAC7, 0x7AFA, 0xAAC8, 0x7CFE, 0xAAC9, 0x7F54, 0xAACA, 0x7F8C,
+	0xAACB, 0x7F8B, 0xAACC, 0x8005, 0xAACD, 0x80BA, 0xAACE, 0x80A5,
+	0xAACF, 0x80A2, 0xAAD0, 0x80B1, 0xAAD1, 0x80A1, 0xAAD2, 0x80AB,
+	0xAAD3, 0x80A9, 0xAAD4, 0x80B4, 0xAAD5, 0x80AA, 0xAAD6, 0x80AF,
+	0xAAD7, 0x81E5, 0xAAD8, 0x81FE, 0xAAD9, 0x820D, 0xAADA, 0x82B3,
+	0xAADB, 0x829D, 0xAADC, 0x8299, 0xAADD, 0x82AD, 0xAADE, 0x82BD,
+	0xAADF, 0x829F, 0xAAE0, 0x82B9, 0xAAE1, 0x82B1, 0xAAE2, 0x82AC,
+	0xAAE3, 0x82A5, 0xAAE4, 0x82AF, 0xAAE5, 0x82B8, 0xAAE6, 0x82A3,
+	0xAAE7, 0x82B0, 0xAAE8, 0x82BE, 0xAAE9, 0x82B7, 0xAAEA, 0x864E,
+	0xAAEB, 0x8671, 0xAAEC, 0x521D, 0xAAED, 0x8868, 0xAAEE, 0x8ECB,
+	0xAAEF, 0x8FCE, 0xAAF0, 0x8FD4, 0xAAF1, 0x8FD1, 0xAAF2, 0x90B5,
+	0xAAF3, 0x90B8, 0xAAF4, 0x90B1, 0xAAF5, 0x90B6, 0xAAF6, 0x91C7,
+	0xAAF7, 0x91D1, 0xAAF8, 0x9577, 0xAAF9, 0x9580, 0xAAFA, 0x961C,
+	0xAAFB, 0x9640, 0xAAFC, 0x963F, 0xAAFD, 0x963B, 0xAAFE, 0x9644,
+	0xAB40, 0x9642, 0xAB41, 0x96B9, 0xAB42, 0x96E8, 0xAB43, 0x9752,
+	0xAB44, 0x975E, 0xAB45, 0x4E9F, 0xAB46, 0x4EAD, 0xAB47, 0x4EAE,
+	0xAB48, 0x4FE1, 0xAB49, 0x4FB5, 0xAB4A, 0x4FAF, 0xAB4B, 0x4FBF,
+	0xAB4C, 0x4FE0, 0xAB4D, 0x4FD1, 0xAB4E, 0x4FCF, 0xAB4F, 0x4FDD,
+	0xAB50, 0x4FC3, 0xAB51, 0x4FB6, 0xAB52, 0x4FD8, 0xAB53, 0x4FDF,
+	0xAB54, 0x4FCA, 0xAB55, 0x4FD7, 0xAB56, 0x4FAE, 0xAB57, 0x4FD0,
+	0xAB58, 0x4FC4, 0xAB59, 0x4FC2, 0xAB5A, 0x4FDA, 0xAB5B, 0x4FCE,
+	0xAB5C, 0x4FDE, 0xAB5D, 0x4FB7, 0xAB5E, 0x5157, 0xAB5F, 0x5192,
+	0xAB60, 0x5191, 0xAB61, 0x51A0, 0xAB62, 0x524E, 0xAB63, 0x5243,
+	0xAB64, 0x524A, 0xAB65, 0x524D, 0xAB66, 0x524C, 0xAB67, 0x524B,
+	0xAB68, 0x5247, 0xAB69, 0x52C7, 0xAB6A, 0x52C9, 0xAB6B, 0x52C3,
+	0xAB6C, 0x52C1, 0xAB6D, 0x530D, 0xAB6E, 0x5357, 0xAB6F, 0x537B,
+	0xAB70, 0x539A, 0xAB71, 0x53DB, 0xAB72, 0x54AC, 0xAB73, 0x54C0,
+	0xAB74, 0x54A8, 0xAB75, 0x54CE, 0xAB76, 0x54C9, 0xAB77, 0x54B8,
+	0xAB78, 0x54A6, 0xAB79, 0x54B3, 0xAB7A, 0x54C7, 0xAB7B, 0x54C2,
+	0xAB7C, 0x54BD, 0xAB7D, 0x54AA, 0xAB7E, 0x54C1, 0xABA1, 0x54C4,
+	0xABA2, 0x54C8, 0xABA3, 0x54AF, 0xABA4, 0x54AB, 0xABA5, 0x54B1,
+	0xABA6, 0x54BB, 0xABA7, 0x54A9, 0xABA8, 0x54A7, 0xABA9, 0x54BF,
+	0xABAA, 0x56FF, 0xABAB, 0x5782, 0xABAC, 0x578B, 0xABAD, 0x57A0,
+	0xABAE, 0x57A3, 0xABAF, 0x57A2, 0xABB0, 0x57CE, 0xABB1, 0x57AE,
+	0xABB2, 0x5793, 0xABB3, 0x5955, 0xABB4, 0x5951, 0xABB5, 0x594F,
+	0xABB6, 0x594E, 0xABB7, 0x5950, 0xABB8, 0x59DC, 0xABB9, 0x59D8,
+	0xABBA, 0x59FF, 0xABBB, 0x59E3, 0xABBC, 0x59E8, 0xABBD, 0x5A03,
+	0xABBE, 0x59E5, 0xABBF, 0x59EA, 0xABC0, 0x59DA, 0xABC1, 0x59E6,
+	0xABC2, 0x5A01, 0xABC3, 0x59FB, 0xABC4, 0x5B69, 0xABC5, 0x5BA3,
+	0xABC6, 0x5BA6, 0xABC7, 0x5BA4, 0xABC8, 0x5BA2, 0xABC9, 0x5BA5,
+	0xABCA, 0x5C01, 0xABCB, 0x5C4E, 0xABCC, 0x5C4F, 0xABCD, 0x5C4D,
+	0xABCE, 0x5C4B, 0xABCF, 0x5CD9, 0xABD0, 0x5CD2, 0xABD1, 0x5DF7,
+	0xABD2, 0x5E1D, 0xABD3, 0x5E25, 0xABD4, 0x5E1F, 0xABD5, 0x5E7D,
+	0xABD6, 0x5EA0, 0xABD7, 0x5EA6, 0xABD8, 0x5EFA, 0xABD9, 0x5F08,
+	0xABDA, 0x5F2D, 0xABDB, 0x5F65, 0xABDC, 0x5F88, 0xABDD, 0x5F85,
+	0xABDE, 0x5F8A, 0xABDF, 0x5F8B, 0xABE0, 0x5F87, 0xABE1, 0x5F8C,
+	0xABE2, 0x5F89, 0xABE3, 0x6012, 0xABE4, 0x601D, 0xABE5, 0x6020,
+	0xABE6, 0x6025, 0xABE7, 0x600E, 0xABE8, 0x6028, 0xABE9, 0x604D,
+	0xABEA, 0x6070, 0xABEB, 0x6068, 0xABEC, 0x6062, 0xABED, 0x6046,
+	0xABEE, 0x6043, 0xABEF, 0x606C, 0xABF0, 0x606B, 0xABF1, 0x606A,
+	0xABF2, 0x6064, 0xABF3, 0x6241, 0xABF4, 0x62DC, 0xABF5, 0x6316,
+	0xABF6, 0x6309, 0xABF7, 0x62FC, 0xABF8, 0x62ED, 0xABF9, 0x6301,
+	0xABFA, 0x62EE, 0xABFB, 0x62FD, 0xABFC, 0x6307, 0xABFD, 0x62F1,
+	0xABFE, 0x62F7, 0xAC40, 0x62EF, 0xAC41, 0x62EC, 0xAC42, 0x62FE,
+	0xAC43, 0x62F4, 0xAC44, 0x6311, 0xAC45, 0x6302, 0xAC46, 0x653F,
+	0xAC47, 0x6545, 0xAC48, 0x65AB, 0xAC49, 0x65BD, 0xAC4A, 0x65E2,
+	0xAC4B, 0x6625, 0xAC4C, 0x662D, 0xAC4D, 0x6620, 0xAC4E, 0x6627,
+	0xAC4F, 0x662F, 0xAC50, 0x661F, 0xAC51, 0x6628, 0xAC52, 0x6631,
+	0xAC53, 0x6624, 0xAC54, 0x66F7, 0xAC55, 0x67FF, 0xAC56, 0x67D3,
+	0xAC57, 0x67F1, 0xAC58, 0x67D4, 0xAC59, 0x67D0, 0xAC5A, 0x67EC,
+	0xAC5B, 0x67B6, 0xAC5C, 0x67AF, 0xAC5D, 0x67F5, 0xAC5E, 0x67E9,
+	0xAC5F, 0x67EF, 0xAC60, 0x67C4, 0xAC61, 0x67D1, 0xAC62, 0x67B4,
+	0xAC63, 0x67DA, 0xAC64, 0x67E5, 0xAC65, 0x67B8, 0xAC66, 0x67CF,
+	0xAC67, 0x67DE, 0xAC68, 0x67F3, 0xAC69, 0x67B0, 0xAC6A, 0x67D9,
+	0xAC6B, 0x67E2, 0xAC6C, 0x67DD, 0xAC6D, 0x67D2, 0xAC6E, 0x6B6A,
+	0xAC6F, 0x6B83, 0xAC70, 0x6B86, 0xAC71, 0x6BB5, 0xAC72, 0x6BD2,
+	0xAC73, 0x6BD7, 0xAC74, 0x6C1F, 0xAC75, 0x6CC9, 0xAC76, 0x6D0B,
+	0xAC77, 0x6D32, 0xAC78, 0x6D2A, 0xAC79, 0x6D41, 0xAC7A, 0x6D25,
+	0xAC7B, 0x6D0C, 0xAC7C, 0x6D31, 0xAC7D, 0x6D1E, 0xAC7E, 0x6D17,
+	0xACA1, 0x6D3B, 0xACA2, 0x6D3D, 0xACA3, 0x6D3E, 0xACA4, 0x6D36,
+	0xACA5, 0x6D1B, 0xACA6, 0x6CF5, 0xACA7, 0x6D39, 0xACA8, 0x6D27,
+	0xACA9, 0x6D38, 0xACAA, 0x6D29, 0xACAB, 0x6D2E, 0xACAC, 0x6D35,
+	0xACAD, 0x6D0E, 0xACAE, 0x6D2B, 0xACAF, 0x70AB, 0xACB0, 0x70BA,
+	0xACB1, 0x70B3, 0xACB2, 0x70AC, 0xACB3, 0x70AF, 0xACB4, 0x70AD,
+	0xACB5, 0x70B8, 0xACB6, 0x70AE, 0xACB7, 0x70A4, 0xACB8, 0x7230,
+	0xACB9, 0x7272, 0xACBA, 0x726F, 0xACBB, 0x7274, 0xACBC, 0x72E9,
+	0xACBD, 0x72E0, 0xACBE, 0x72E1, 0xACBF, 0x73B7, 0xACC0, 0x73CA,
+	0xACC1, 0x73BB, 0xACC2, 0x73B2, 0xACC3, 0x73CD, 0xACC4, 0x73C0,
+	0xACC5, 0x73B3, 0xACC6, 0x751A, 0xACC7, 0x752D, 0xACC8, 0x754F,
+	0xACC9, 0x754C, 0xACCA, 0x754E, 0xACCB, 0x754B, 0xACCC, 0x75AB,
+	0xACCD, 0x75A4, 0xACCE, 0x75A5, 0xACCF, 0x75A2, 0xACD0, 0x75A3,
+	0xACD1, 0x7678, 0xACD2, 0x7686, 0xACD3, 0x7687, 0xACD4, 0x7688,
+	0xACD5, 0x76C8, 0xACD6, 0x76C6, 0xACD7, 0x76C3, 0xACD8, 0x76C5,
+	0xACD9, 0x7701, 0xACDA, 0x76F9, 0xACDB, 0x76F8, 0xACDC, 0x7709,
+	0xACDD, 0x770B, 0xACDE, 0x76FE, 0xACDF, 0x76FC, 0xACE0, 0x7707,
+	0xACE1, 0x77DC, 0xACE2, 0x7802, 0xACE3, 0x7814, 0xACE4, 0x780C,
+	0xACE5, 0x780D, 0xACE6, 0x7946, 0xACE7, 0x7949, 0xACE8, 0x7948,
+	0xACE9, 0x7947, 0xACEA, 0x79B9, 0xACEB, 0x79BA, 0xACEC, 0x79D1,
+	0xACED, 0x79D2, 0xACEE, 0x79CB, 0xACEF, 0x7A7F, 0xACF0, 0x7A81,
+	0xACF1, 0x7AFF, 0xACF2, 0x7AFD, 0xACF3, 0x7C7D, 0xACF4, 0x7D02,
+	0xACF5, 0x7D05, 0xACF6, 0x7D00, 0xACF7, 0x7D09, 0xACF8, 0x7D07,
+	0xACF9, 0x7D04, 0xACFA, 0x7D06, 0xACFB, 0x7F38, 0xACFC, 0x7F8E,
+	0xACFD, 0x7FBF, 0xACFE, 0x8004, 0xAD40, 0x8010, 0xAD41, 0x800D,
+	0xAD42, 0x8011, 0xAD43, 0x8036, 0xAD44, 0x80D6, 0xAD45, 0x80E5,
+	0xAD46, 0x80DA, 0xAD47, 0x80C3, 0xAD48, 0x80C4, 0xAD49, 0x80CC,
+	0xAD4A, 0x80E1, 0xAD4B, 0x80DB, 0xAD4C, 0x80CE, 0xAD4D, 0x80DE,
+	0xAD4E, 0x80E4, 0xAD4F, 0x80DD, 0xAD50, 0x81F4, 0xAD51, 0x8222,
+	0xAD52, 0x82E7, 0xAD53, 0x8303, 0xAD54, 0x8305, 0xAD55, 0x82E3,
+	0xAD56, 0x82DB, 0xAD57, 0x82E6, 0xAD58, 0x8304, 0xAD59, 0x82E5,
+	0xAD5A, 0x8302, 0xAD5B, 0x8309, 0xAD5C, 0x82D2, 0xAD5D, 0x82D7,
+	0xAD5E, 0x82F1, 0xAD5F, 0x8301, 0xAD60, 0x82DC, 0xAD61, 0x82D4,
+	0xAD62, 0x82D1, 0xAD63, 0x82DE, 0xAD64, 0x82D3, 0xAD65, 0x82DF,
+	0xAD66, 0x82EF, 0xAD67, 0x8306, 0xAD68, 0x8650, 0xAD69, 0x8679,
+	0xAD6A, 0x867B, 0xAD6B, 0x867A, 0xAD6C, 0x884D, 0xAD6D, 0x886B,
+	0xAD6E, 0x8981, 0xAD6F, 0x89D4, 0xAD70, 0x8A08, 0xAD71, 0x8A02,
+	0xAD72, 0x8A03, 0xAD73, 0x8C9E, 0xAD74, 0x8CA0, 0xAD75, 0x8D74,
+	0xAD76, 0x8D73, 0xAD77, 0x8DB4, 0xAD78, 0x8ECD, 0xAD79, 0x8ECC,
+	0xAD7A, 0x8FF0, 0xAD7B, 0x8FE6, 0xAD7C, 0x8FE2, 0xAD7D, 0x8FEA,
+	0xAD7E, 0x8FE5, 0xADA1, 0x8FED, 0xADA2, 0x8FEB, 0xADA3, 0x8FE4,
+	0xADA4, 0x8FE8, 0xADA5, 0x90CA, 0xADA6, 0x90CE, 0xADA7, 0x90C1,
+	0xADA8, 0x90C3, 0xADA9, 0x914B, 0xADAA, 0x914A, 0xADAB, 0x91CD,
+	0xADAC, 0x9582, 0xADAD, 0x9650, 0xADAE, 0x964B, 0xADAF, 0x964C,
+	0xADB0, 0x964D, 0xADB1, 0x9762, 0xADB2, 0x9769, 0xADB3, 0x97CB,
+	0xADB4, 0x97ED, 0xADB5, 0x97F3, 0xADB6, 0x9801, 0xADB7, 0x98A8,
+	0xADB8, 0x98DB, 0xADB9, 0x98DF, 0xADBA, 0x9996, 0xADBB, 0x9999,
+	0xADBC, 0x4E58, 0xADBD, 0x4EB3, 0xADBE, 0x500C, 0xADBF, 0x500D,
+	0xADC0, 0x5023, 0xADC1, 0x4FEF, 0xADC2, 0x5026, 0xADC3, 0x5025,
+	0xADC4, 0x4FF8, 0xADC5, 0x5029, 0xADC6, 0x5016, 0xADC7, 0x5006,
+	0xADC8, 0x503C, 0xADC9, 0x501F, 0xADCA, 0x501A, 0xADCB, 0x5012,
+	0xADCC, 0x5011, 0xADCD, 0x4FFA, 0xADCE, 0x5000, 0xADCF, 0x5014,
+	0xADD0, 0x5028, 0xADD1, 0x4FF1, 0xADD2, 0x5021, 0xADD3, 0x500B,
+	0xADD4, 0x5019, 0xADD5, 0x5018, 0xADD6, 0x4FF3, 0xADD7, 0x4FEE,
+	0xADD8, 0x502D, 0xADD9, 0x502A, 0xADDA, 0x4FFE, 0xADDB, 0x502B,
+	0xADDC, 0x5009, 0xADDD, 0x517C, 0xADDE, 0x51A4, 0xADDF, 0x51A5,
+	0xADE0, 0x51A2, 0xADE1, 0x51CD, 0xADE2, 0x51CC, 0xADE3, 0x51C6,
+	0xADE4, 0x51CB, 0xADE5, 0x5256, 0xADE6, 0x525C, 0xADE7, 0x5254,
+	0xADE8, 0x525B, 0xADE9, 0x525D, 0xADEA, 0x532A, 0xADEB, 0x537F,
+	0xADEC, 0x539F, 0xADED, 0x539D, 0xADEE, 0x53DF, 0xADEF, 0x54E8,
+	0xADF0, 0x5510, 0xADF1, 0x5501, 0xADF2, 0x5537, 0xADF3, 0x54FC,
+	0xADF4, 0x54E5, 0xADF5, 0x54F2, 0xADF6, 0x5506, 0xADF7, 0x54FA,
+	0xADF8, 0x5514, 0xADF9, 0x54E9, 0xADFA, 0x54ED, 0xADFB, 0x54E1,
+	0xADFC, 0x5509, 0xADFD, 0x54EE, 0xADFE, 0x54EA, 0xAE40, 0x54E6,
+	0xAE41, 0x5527, 0xAE42, 0x5507, 0xAE43, 0x54FD, 0xAE44, 0x550F,
+	0xAE45, 0x5703, 0xAE46, 0x5704, 0xAE47, 0x57C2, 0xAE48, 0x57D4,
+	0xAE49, 0x57CB, 0xAE4A, 0x57C3, 0xAE4B, 0x5809, 0xAE4C, 0x590F,
+	0xAE4D, 0x5957, 0xAE4E, 0x5958, 0xAE4F, 0x595A, 0xAE50, 0x5A11,
+	0xAE51, 0x5A18, 0xAE52, 0x5A1C, 0xAE53, 0x5A1F, 0xAE54, 0x5A1B,
+	0xAE55, 0x5A13, 0xAE56, 0x59EC, 0xAE57, 0x5A20, 0xAE58, 0x5A23,
+	0xAE59, 0x5A29, 0xAE5A, 0x5A25, 0xAE5B, 0x5A0C, 0xAE5C, 0x5A09,
+	0xAE5D, 0x5B6B, 0xAE5E, 0x5C58, 0xAE5F, 0x5BB0, 0xAE60, 0x5BB3,
+	0xAE61, 0x5BB6, 0xAE62, 0x5BB4, 0xAE63, 0x5BAE, 0xAE64, 0x5BB5,
+	0xAE65, 0x5BB9, 0xAE66, 0x5BB8, 0xAE67, 0x5C04, 0xAE68, 0x5C51,
+	0xAE69, 0x5C55, 0xAE6A, 0x5C50, 0xAE6B, 0x5CED, 0xAE6C, 0x5CFD,
+	0xAE6D, 0x5CFB, 0xAE6E, 0x5CEA, 0xAE6F, 0x5CE8, 0xAE70, 0x5CF0,
+	0xAE71, 0x5CF6, 0xAE72, 0x5D01, 0xAE73, 0x5CF4, 0xAE74, 0x5DEE,
+	0xAE75, 0x5E2D, 0xAE76, 0x5E2B, 0xAE77, 0x5EAB, 0xAE78, 0x5EAD,
+	0xAE79, 0x5EA7, 0xAE7A, 0x5F31, 0xAE7B, 0x5F92, 0xAE7C, 0x5F91,
+	0xAE7D, 0x5F90, 0xAE7E, 0x6059, 0xAEA1, 0x6063, 0xAEA2, 0x6065,
+	0xAEA3, 0x6050, 0xAEA4, 0x6055, 0xAEA5, 0x606D, 0xAEA6, 0x6069,
+	0xAEA7, 0x606F, 0xAEA8, 0x6084, 0xAEA9, 0x609F, 0xAEAA, 0x609A,
+	0xAEAB, 0x608D, 0xAEAC, 0x6094, 0xAEAD, 0x608C, 0xAEAE, 0x6085,
+	0xAEAF, 0x6096, 0xAEB0, 0x6247, 0xAEB1, 0x62F3, 0xAEB2, 0x6308,
+	0xAEB3, 0x62FF, 0xAEB4, 0x634E, 0xAEB5, 0x633E, 0xAEB6, 0x632F,
+	0xAEB7, 0x6355, 0xAEB8, 0x6342, 0xAEB9, 0x6346, 0xAEBA, 0x634F,
+	0xAEBB, 0x6349, 0xAEBC, 0x633A, 0xAEBD, 0x6350, 0xAEBE, 0x633D,
+	0xAEBF, 0x632A, 0xAEC0, 0x632B, 0xAEC1, 0x6328, 0xAEC2, 0x634D,
+	0xAEC3, 0x634C, 0xAEC4, 0x6548, 0xAEC5, 0x6549, 0xAEC6, 0x6599,
+	0xAEC7, 0x65C1, 0xAEC8, 0x65C5, 0xAEC9, 0x6642, 0xAECA, 0x6649,
+	0xAECB, 0x664F, 0xAECC, 0x6643, 0xAECD, 0x6652, 0xAECE, 0x664C,
+	0xAECF, 0x6645, 0xAED0, 0x6641, 0xAED1, 0x66F8, 0xAED2, 0x6714,
+	0xAED3, 0x6715, 0xAED4, 0x6717, 0xAED5, 0x6821, 0xAED6, 0x6838,
+	0xAED7, 0x6848, 0xAED8, 0x6846, 0xAED9, 0x6853, 0xAEDA, 0x6839,
+	0xAEDB, 0x6842, 0xAEDC, 0x6854, 0xAEDD, 0x6829, 0xAEDE, 0x68B3,
+	0xAEDF, 0x6817, 0xAEE0, 0x684C, 0xAEE1, 0x6851, 0xAEE2, 0x683D,
+	0xAEE3, 0x67F4, 0xAEE4, 0x6850, 0xAEE5, 0x6840, 0xAEE6, 0x683C,
+	0xAEE7, 0x6843, 0xAEE8, 0x682A, 0xAEE9, 0x6845, 0xAEEA, 0x6813,
+	0xAEEB, 0x6818, 0xAEEC, 0x6841, 0xAEED, 0x6B8A, 0xAEEE, 0x6B89,
+	0xAEEF, 0x6BB7, 0xAEF0, 0x6C23, 0xAEF1, 0x6C27, 0xAEF2, 0x6C28,
+	0xAEF3, 0x6C26, 0xAEF4, 0x6C24, 0xAEF5, 0x6CF0, 0xAEF6, 0x6D6A,
+	0xAEF7, 0x6D95, 0xAEF8, 0x6D88, 0xAEF9, 0x6D87, 0xAEFA, 0x6D66,
+	0xAEFB, 0x6D78, 0xAEFC, 0x6D77, 0xAEFD, 0x6D59, 0xAEFE, 0x6D93,
+	0xAF40, 0x6D6C, 0xAF41, 0x6D89, 0xAF42, 0x6D6E, 0xAF43, 0x6D5A,
+	0xAF44, 0x6D74, 0xAF45, 0x6D69, 0xAF46, 0x6D8C, 0xAF47, 0x6D8A,
+	0xAF48, 0x6D79, 0xAF49, 0x6D85, 0xAF4A, 0x6D65, 0xAF4B, 0x6D94,
+	0xAF4C, 0x70CA, 0xAF4D, 0x70D8, 0xAF4E, 0x70E4, 0xAF4F, 0x70D9,
+	0xAF50, 0x70C8, 0xAF51, 0x70CF, 0xAF52, 0x7239, 0xAF53, 0x7279,
+	0xAF54, 0x72FC, 0xAF55, 0x72F9, 0xAF56, 0x72FD, 0xAF57, 0x72F8,
+	0xAF58, 0x72F7, 0xAF59, 0x7386, 0xAF5A, 0x73ED, 0xAF5B, 0x7409,
+	0xAF5C, 0x73EE, 0xAF5D, 0x73E0, 0xAF5E, 0x73EA, 0xAF5F, 0x73DE,
+	0xAF60, 0x7554, 0xAF61, 0x755D, 0xAF62, 0x755C, 0xAF63, 0x755A,
+	0xAF64, 0x7559, 0xAF65, 0x75BE, 0xAF66, 0x75C5, 0xAF67, 0x75C7,
+	0xAF68, 0x75B2, 0xAF69, 0x75B3, 0xAF6A, 0x75BD, 0xAF6B, 0x75BC,
+	0xAF6C, 0x75B9, 0xAF6D, 0x75C2, 0xAF6E, 0x75B8, 0xAF6F, 0x768B,
+	0xAF70, 0x76B0, 0xAF71, 0x76CA, 0xAF72, 0x76CD, 0xAF73, 0x76CE,
+	0xAF74, 0x7729, 0xAF75, 0x771F, 0xAF76, 0x7720, 0xAF77, 0x7728,
+	0xAF78, 0x77E9, 0xAF79, 0x7830, 0xAF7A, 0x7827, 0xAF7B, 0x7838,
+	0xAF7C, 0x781D, 0xAF7D, 0x7834, 0xAF7E, 0x7837, 0xAFA1, 0x7825,
+	0xAFA2, 0x782D, 0xAFA3, 0x7820, 0xAFA4, 0x781F, 0xAFA5, 0x7832,
+	0xAFA6, 0x7955, 0xAFA7, 0x7950, 0xAFA8, 0x7960, 0xAFA9, 0x795F,
+	0xAFAA, 0x7956, 0xAFAB, 0x795E, 0xAFAC, 0x795D, 0xAFAD, 0x7957,
+	0xAFAE, 0x795A, 0xAFAF, 0x79E4, 0xAFB0, 0x79E3, 0xAFB1, 0x79E7,
+	0xAFB2, 0x79DF, 0xAFB3, 0x79E6, 0xAFB4, 0x79E9, 0xAFB5, 0x79D8,
+	0xAFB6, 0x7A84, 0xAFB7, 0x7A88, 0xAFB8, 0x7AD9, 0xAFB9, 0x7B06,
+	0xAFBA, 0x7B11, 0xAFBB, 0x7C89, 0xAFBC, 0x7D21, 0xAFBD, 0x7D17,
+	0xAFBE, 0x7D0B, 0xAFBF, 0x7D0A, 0xAFC0, 0x7D20, 0xAFC1, 0x7D22,
+	0xAFC2, 0x7D14, 0xAFC3, 0x7D10, 0xAFC4, 0x7D15, 0xAFC5, 0x7D1A,
+	0xAFC6, 0x7D1C, 0xAFC7, 0x7D0D, 0xAFC8, 0x7D19, 0xAFC9, 0x7D1B,
+	0xAFCA, 0x7F3A, 0xAFCB, 0x7F5F, 0xAFCC, 0x7F94, 0xAFCD, 0x7FC5,
+	0xAFCE, 0x7FC1, 0xAFCF, 0x8006, 0xAFD0, 0x8018, 0xAFD1, 0x8015,
+	0xAFD2, 0x8019, 0xAFD3, 0x8017, 0xAFD4, 0x803D, 0xAFD5, 0x803F,
+	0xAFD6, 0x80F1, 0xAFD7, 0x8102, 0xAFD8, 0x80F0, 0xAFD9, 0x8105,
+	0xAFDA, 0x80ED, 0xAFDB, 0x80F4, 0xAFDC, 0x8106, 0xAFDD, 0x80F8,
+	0xAFDE, 0x80F3, 0xAFDF, 0x8108, 0xAFE0, 0x80FD, 0xAFE1, 0x810A,
+	0xAFE2, 0x80FC, 0xAFE3, 0x80EF, 0xAFE4, 0x81ED, 0xAFE5, 0x81EC,
+	0xAFE6, 0x8200, 0xAFE7, 0x8210, 0xAFE8, 0x822A, 0xAFE9, 0x822B,
+	0xAFEA, 0x8228, 0xAFEB, 0x822C, 0xAFEC, 0x82BB, 0xAFED, 0x832B,
+	0xAFEE, 0x8352, 0xAFEF, 0x8354, 0xAFF0, 0x834A, 0xAFF1, 0x8338,
+	0xAFF2, 0x8350, 0xAFF3, 0x8349, 0xAFF4, 0x8335, 0xAFF5, 0x8334,
+	0xAFF6, 0x834F, 0xAFF7, 0x8332, 0xAFF8, 0x8339, 0xAFF9, 0x8336,
+	0xAFFA, 0x8317, 0xAFFB, 0x8340, 0xAFFC, 0x8331, 0xAFFD, 0x8328,
+	0xAFFE, 0x8343, 0xB040, 0x8654, 0xB041, 0x868A, 0xB042, 0x86AA,
+	0xB043, 0x8693, 0xB044, 0x86A4, 0xB045, 0x86A9, 0xB046, 0x868C,
+	0xB047, 0x86A3, 0xB048, 0x869C, 0xB049, 0x8870, 0xB04A, 0x8877,
+	0xB04B, 0x8881, 0xB04C, 0x8882, 0xB04D, 0x887D, 0xB04E, 0x8879,
+	0xB04F, 0x8A18, 0xB050, 0x8A10, 0xB051, 0x8A0E, 0xB052, 0x8A0C,
+	0xB053, 0x8A15, 0xB054, 0x8A0A, 0xB055, 0x8A17, 0xB056, 0x8A13,
+	0xB057, 0x8A16, 0xB058, 0x8A0F, 0xB059, 0x8A11, 0xB05A, 0x8C48,
+	0xB05B, 0x8C7A, 0xB05C, 0x8C79, 0xB05D, 0x8CA1, 0xB05E, 0x8CA2,
+	0xB05F, 0x8D77, 0xB060, 0x8EAC, 0xB061, 0x8ED2, 0xB062, 0x8ED4,
+	0xB063, 0x8ECF, 0xB064, 0x8FB1, 0xB065, 0x9001, 0xB066, 0x9006,
+	0xB067, 0x8FF7, 0xB068, 0x9000, 0xB069, 0x8FFA, 0xB06A, 0x8FF4,
+	0xB06B, 0x9003, 0xB06C, 0x8FFD, 0xB06D, 0x9005, 0xB06E, 0x8FF8,
+	0xB06F, 0x9095, 0xB070, 0x90E1, 0xB071, 0x90DD, 0xB072, 0x90E2,
+	0xB073, 0x9152, 0xB074, 0x914D, 0xB075, 0x914C, 0xB076, 0x91D8,
+	0xB077, 0x91DD, 0xB078, 0x91D7, 0xB079, 0x91DC, 0xB07A, 0x91D9,
+	0xB07B, 0x9583, 0xB07C, 0x9662, 0xB07D, 0x9663, 0xB07E, 0x9661,
+	0xB0A1, 0x965B, 0xB0A2, 0x965D, 0xB0A3, 0x9664, 0xB0A4, 0x9658,
+	0xB0A5, 0x965E, 0xB0A6, 0x96BB, 0xB0A7, 0x98E2, 0xB0A8, 0x99AC,
+	0xB0A9, 0x9AA8, 0xB0AA, 0x9AD8, 0xB0AB, 0x9B25, 0xB0AC, 0x9B32,
+	0xB0AD, 0x9B3C, 0xB0AE, 0x4E7E, 0xB0AF, 0x507A, 0xB0B0, 0x507D,
+	0xB0B1, 0x505C, 0xB0B2, 0x5047, 0xB0B3, 0x5043, 0xB0B4, 0x504C,
+	0xB0B5, 0x505A, 0xB0B6, 0x5049, 0xB0B7, 0x5065, 0xB0B8, 0x5076,
+	0xB0B9, 0x504E, 0xB0BA, 0x5055, 0xB0BB, 0x5075, 0xB0BC, 0x5074,
+	0xB0BD, 0x5077, 0xB0BE, 0x504F, 0xB0BF, 0x500F, 0xB0C0, 0x506F,
+	0xB0C1, 0x506D, 0xB0C2, 0x515C, 0xB0C3, 0x5195, 0xB0C4, 0x51F0,
+	0xB0C5, 0x526A, 0xB0C6, 0x526F, 0xB0C7, 0x52D2, 0xB0C8, 0x52D9,
+	0xB0C9, 0x52D8, 0xB0CA, 0x52D5, 0xB0CB, 0x5310, 0xB0CC, 0x530F,
+	0xB0CD, 0x5319, 0xB0CE, 0x533F, 0xB0CF, 0x5340, 0xB0D0, 0x533E,
+	0xB0D1, 0x53C3, 0xB0D2, 0x66FC, 0xB0D3, 0x5546, 0xB0D4, 0x556A,
+	0xB0D5, 0x5566, 0xB0D6, 0x5544, 0xB0D7, 0x555E, 0xB0D8, 0x5561,
+	0xB0D9, 0x5543, 0xB0DA, 0x554A, 0xB0DB, 0x5531, 0xB0DC, 0x5556,
+	0xB0DD, 0x554F, 0xB0DE, 0x5555, 0xB0DF, 0x552F, 0xB0E0, 0x5564,
+	0xB0E1, 0x5538, 0xB0E2, 0x552E, 0xB0E3, 0x555C, 0xB0E4, 0x552C,
+	0xB0E5, 0x5563, 0xB0E6, 0x5533, 0xB0E7, 0x5541, 0xB0E8, 0x5557,
+	0xB0E9, 0x5708, 0xB0EA, 0x570B, 0xB0EB, 0x5709, 0xB0EC, 0x57DF,
+	0xB0ED, 0x5805, 0xB0EE, 0x580A, 0xB0EF, 0x5806, 0xB0F0, 0x57E0,
+	0xB0F1, 0x57E4, 0xB0F2, 0x57FA, 0xB0F3, 0x5802, 0xB0F4, 0x5835,
+	0xB0F5, 0x57F7, 0xB0F6, 0x57F9, 0xB0F7, 0x5920, 0xB0F8, 0x5962,
+	0xB0F9, 0x5A36, 0xB0FA, 0x5A41, 0xB0FB, 0x5A49, 0xB0FC, 0x5A66,
+	0xB0FD, 0x5A6A, 0xB0FE, 0x5A40, 0xB140, 0x5A3C, 0xB141, 0x5A62,
+	0xB142, 0x5A5A, 0xB143, 0x5A46, 0xB144, 0x5A4A, 0xB145, 0x5B70,
+	0xB146, 0x5BC7, 0xB147, 0x5BC5, 0xB148, 0x5BC4, 0xB149, 0x5BC2,
+	0xB14A, 0x5BBF, 0xB14B, 0x5BC6, 0xB14C, 0x5C09, 0xB14D, 0x5C08,
+	0xB14E, 0x5C07, 0xB14F, 0x5C60, 0xB150, 0x5C5C, 0xB151, 0x5C5D,
+	0xB152, 0x5D07, 0xB153, 0x5D06, 0xB154, 0x5D0E, 0xB155, 0x5D1B,
+	0xB156, 0x5D16, 0xB157, 0x5D22, 0xB158, 0x5D11, 0xB159, 0x5D29,
+	0xB15A, 0x5D14, 0xB15B, 0x5D19, 0xB15C, 0x5D24, 0xB15D, 0x5D27,
+	0xB15E, 0x5D17, 0xB15F, 0x5DE2, 0xB160, 0x5E38, 0xB161, 0x5E36,
+	0xB162, 0x5E33, 0xB163, 0x5E37, 0xB164, 0x5EB7, 0xB165, 0x5EB8,
+	0xB166, 0x5EB6, 0xB167, 0x5EB5, 0xB168, 0x5EBE, 0xB169, 0x5F35,
+	0xB16A, 0x5F37, 0xB16B, 0x5F57, 0xB16C, 0x5F6C, 0xB16D, 0x5F69,
+	0xB16E, 0x5F6B, 0xB16F, 0x5F97, 0xB170, 0x5F99, 0xB171, 0x5F9E,
+	0xB172, 0x5F98, 0xB173, 0x5FA1, 0xB174, 0x5FA0, 0xB175, 0x5F9C,
+	0xB176, 0x607F, 0xB177, 0x60A3, 0xB178, 0x6089, 0xB179, 0x60A0,
+	0xB17A, 0x60A8, 0xB17B, 0x60CB, 0xB17C, 0x60B4, 0xB17D, 0x60E6,
+	0xB17E, 0x60BD, 0xB1A1, 0x60C5, 0xB1A2, 0x60BB, 0xB1A3, 0x60B5,
+	0xB1A4, 0x60DC, 0xB1A5, 0x60BC, 0xB1A6, 0x60D8, 0xB1A7, 0x60D5,
+	0xB1A8, 0x60C6, 0xB1A9, 0x60DF, 0xB1AA, 0x60B8, 0xB1AB, 0x60DA,
+	0xB1AC, 0x60C7, 0xB1AD, 0x621A, 0xB1AE, 0x621B, 0xB1AF, 0x6248,
+	0xB1B0, 0x63A0, 0xB1B1, 0x63A7, 0xB1B2, 0x6372, 0xB1B3, 0x6396,
+	0xB1B4, 0x63A2, 0xB1B5, 0x63A5, 0xB1B6, 0x6377, 0xB1B7, 0x6367,
+	0xB1B8, 0x6398, 0xB1B9, 0x63AA, 0xB1BA, 0x6371, 0xB1BB, 0x63A9,
+	0xB1BC, 0x6389, 0xB1BD, 0x6383, 0xB1BE, 0x639B, 0xB1BF, 0x636B,
+	0xB1C0, 0x63A8, 0xB1C1, 0x6384, 0xB1C2, 0x6388, 0xB1C3, 0x6399,
+	0xB1C4, 0x63A1, 0xB1C5, 0x63AC, 0xB1C6, 0x6392, 0xB1C7, 0x638F,
+	0xB1C8, 0x6380, 0xB1C9, 0x637B, 0xB1CA, 0x6369, 0xB1CB, 0x6368,
+	0xB1CC, 0x637A, 0xB1CD, 0x655D, 0xB1CE, 0x6556, 0xB1CF, 0x6551,
+	0xB1D0, 0x6559, 0xB1D1, 0x6557, 0xB1D2, 0x555F, 0xB1D3, 0x654F,
+	0xB1D4, 0x6558, 0xB1D5, 0x6555, 0xB1D6, 0x6554, 0xB1D7, 0x659C,
+	0xB1D8, 0x659B, 0xB1D9, 0x65AC, 0xB1DA, 0x65CF, 0xB1DB, 0x65CB,
+	0xB1DC, 0x65CC, 0xB1DD, 0x65CE, 0xB1DE, 0x665D, 0xB1DF, 0x665A,
+	0xB1E0, 0x6664, 0xB1E1, 0x6668, 0xB1E2, 0x6666, 0xB1E3, 0x665E,
+	0xB1E4, 0x66F9, 0xB1E5, 0x52D7, 0xB1E6, 0x671B, 0xB1E7, 0x6881,
+	0xB1E8, 0x68AF, 0xB1E9, 0x68A2, 0xB1EA, 0x6893, 0xB1EB, 0x68B5,
+	0xB1EC, 0x687F, 0xB1ED, 0x6876, 0xB1EE, 0x68B1, 0xB1EF, 0x68A7,
+	0xB1F0, 0x6897, 0xB1F1, 0x68B0, 0xB1F2, 0x6883, 0xB1F3, 0x68C4,
+	0xB1F4, 0x68AD, 0xB1F5, 0x6886, 0xB1F6, 0x6885, 0xB1F7, 0x6894,
+	0xB1F8, 0x689D, 0xB1F9, 0x68A8, 0xB1FA, 0x689F, 0xB1FB, 0x68A1,
+	0xB1FC, 0x6882, 0xB1FD, 0x6B32, 0xB1FE, 0x6BBA, 0xB240, 0x6BEB,
+	0xB241, 0x6BEC, 0xB242, 0x6C2B, 0xB243, 0x6D8E, 0xB244, 0x6DBC,
+	0xB245, 0x6DF3, 0xB246, 0x6DD9, 0xB247, 0x6DB2, 0xB248, 0x6DE1,
+	0xB249, 0x6DCC, 0xB24A, 0x6DE4, 0xB24B, 0x6DFB, 0xB24C, 0x6DFA,
+	0xB24D, 0x6E05, 0xB24E, 0x6DC7, 0xB24F, 0x6DCB, 0xB250, 0x6DAF,
+	0xB251, 0x6DD1, 0xB252, 0x6DAE, 0xB253, 0x6DDE, 0xB254, 0x6DF9,
+	0xB255, 0x6DB8, 0xB256, 0x6DF7, 0xB257, 0x6DF5, 0xB258, 0x6DC5,
+	0xB259, 0x6DD2, 0xB25A, 0x6E1A, 0xB25B, 0x6DB5, 0xB25C, 0x6DDA,
+	0xB25D, 0x6DEB, 0xB25E, 0x6DD8, 0xB25F, 0x6DEA, 0xB260, 0x6DF1,
+	0xB261, 0x6DEE, 0xB262, 0x6DE8, 0xB263, 0x6DC6, 0xB264, 0x6DC4,
+	0xB265, 0x6DAA, 0xB266, 0x6DEC, 0xB267, 0x6DBF, 0xB268, 0x6DE6,
+	0xB269, 0x70F9, 0xB26A, 0x7109, 0xB26B, 0x710A, 0xB26C, 0x70FD,
+	0xB26D, 0x70EF, 0xB26E, 0x723D, 0xB26F, 0x727D, 0xB270, 0x7281,
+	0xB271, 0x731C, 0xB272, 0x731B, 0xB273, 0x7316, 0xB274, 0x7313,
+	0xB275, 0x7319, 0xB276, 0x7387, 0xB277, 0x7405, 0xB278, 0x740A,
+	0xB279, 0x7403, 0xB27A, 0x7406, 0xB27B, 0x73FE, 0xB27C, 0x740D,
+	0xB27D, 0x74E0, 0xB27E, 0x74F6, 0xB2A1, 0x74F7, 0xB2A2, 0x751C,
+	0xB2A3, 0x7522, 0xB2A4, 0x7565, 0xB2A5, 0x7566, 0xB2A6, 0x7562,
+	0xB2A7, 0x7570, 0xB2A8, 0x758F, 0xB2A9, 0x75D4, 0xB2AA, 0x75D5,
+	0xB2AB, 0x75B5, 0xB2AC, 0x75CA, 0xB2AD, 0x75CD, 0xB2AE, 0x768E,
+	0xB2AF, 0x76D4, 0xB2B0, 0x76D2, 0xB2B1, 0x76DB, 0xB2B2, 0x7737,
+	0xB2B3, 0x773E, 0xB2B4, 0x773C, 0xB2B5, 0x7736, 0xB2B6, 0x7738,
+	0xB2B7, 0x773A, 0xB2B8, 0x786B, 0xB2B9, 0x7843, 0xB2BA, 0x784E,
+	0xB2BB, 0x7965, 0xB2BC, 0x7968, 0xB2BD, 0x796D, 0xB2BE, 0x79FB,
+	0xB2BF, 0x7A92, 0xB2C0, 0x7A95, 0xB2C1, 0x7B20, 0xB2C2, 0x7B28,
+	0xB2C3, 0x7B1B, 0xB2C4, 0x7B2C, 0xB2C5, 0x7B26, 0xB2C6, 0x7B19,
+	0xB2C7, 0x7B1E, 0xB2C8, 0x7B2E, 0xB2C9, 0x7C92, 0xB2CA, 0x7C97,
+	0xB2CB, 0x7C95, 0xB2CC, 0x7D46, 0xB2CD, 0x7D43, 0xB2CE, 0x7D71,
+	0xB2CF, 0x7D2E, 0xB2D0, 0x7D39, 0xB2D1, 0x7D3C, 0xB2D2, 0x7D40,
+	0xB2D3, 0x7D30, 0xB2D4, 0x7D33, 0xB2D5, 0x7D44, 0xB2D6, 0x7D2F,
+	0xB2D7, 0x7D42, 0xB2D8, 0x7D32, 0xB2D9, 0x7D31, 0xB2DA, 0x7F3D,
+	0xB2DB, 0x7F9E, 0xB2DC, 0x7F9A, 0xB2DD, 0x7FCC, 0xB2DE, 0x7FCE,
+	0xB2DF, 0x7FD2, 0xB2E0, 0x801C, 0xB2E1, 0x804A, 0xB2E2, 0x8046,
+	0xB2E3, 0x812F, 0xB2E4, 0x8116, 0xB2E5, 0x8123, 0xB2E6, 0x812B,
+	0xB2E7, 0x8129, 0xB2E8, 0x8130, 0xB2E9, 0x8124, 0xB2EA, 0x8202,
+	0xB2EB, 0x8235, 0xB2EC, 0x8237, 0xB2ED, 0x8236, 0xB2EE, 0x8239,
+	0xB2EF, 0x838E, 0xB2F0, 0x839E, 0xB2F1, 0x8398, 0xB2F2, 0x8378,
+	0xB2F3, 0x83A2, 0xB2F4, 0x8396, 0xB2F5, 0x83BD, 0xB2F6, 0x83AB,
+	0xB2F7, 0x8392, 0xB2F8, 0x838A, 0xB2F9, 0x8393, 0xB2FA, 0x8389,
+	0xB2FB, 0x83A0, 0xB2FC, 0x8377, 0xB2FD, 0x837B, 0xB2FE, 0x837C,
+	0xB340, 0x8386, 0xB341, 0x83A7, 0xB342, 0x8655, 0xB343, 0x5F6A,
+	0xB344, 0x86C7, 0xB345, 0x86C0, 0xB346, 0x86B6, 0xB347, 0x86C4,
+	0xB348, 0x86B5, 0xB349, 0x86C6, 0xB34A, 0x86CB, 0xB34B, 0x86B1,
+	0xB34C, 0x86AF, 0xB34D, 0x86C9, 0xB34E, 0x8853, 0xB34F, 0x889E,
+	0xB350, 0x8888, 0xB351, 0x88AB, 0xB352, 0x8892, 0xB353, 0x8896,
+	0xB354, 0x888D, 0xB355, 0x888B, 0xB356, 0x8993, 0xB357, 0x898F,
+	0xB358, 0x8A2A, 0xB359, 0x8A1D, 0xB35A, 0x8A23, 0xB35B, 0x8A25,
+	0xB35C, 0x8A31, 0xB35D, 0x8A2D, 0xB35E, 0x8A1F, 0xB35F, 0x8A1B,
+	0xB360, 0x8A22, 0xB361, 0x8C49, 0xB362, 0x8C5A, 0xB363, 0x8CA9,
+	0xB364, 0x8CAC, 0xB365, 0x8CAB, 0xB366, 0x8CA8, 0xB367, 0x8CAA,
+	0xB368, 0x8CA7, 0xB369, 0x8D67, 0xB36A, 0x8D66, 0xB36B, 0x8DBE,
+	0xB36C, 0x8DBA, 0xB36D, 0x8EDB, 0xB36E, 0x8EDF, 0xB36F, 0x9019,
+	0xB370, 0x900D, 0xB371, 0x901A, 0xB372, 0x9017, 0xB373, 0x9023,
+	0xB374, 0x901F, 0xB375, 0x901D, 0xB376, 0x9010, 0xB377, 0x9015,
+	0xB378, 0x901E, 0xB379, 0x9020, 0xB37A, 0x900F, 0xB37B, 0x9022,
+	0xB37C, 0x9016, 0xB37D, 0x901B, 0xB37E, 0x9014, 0xB3A1, 0x90E8,
+	0xB3A2, 0x90ED, 0xB3A3, 0x90FD, 0xB3A4, 0x9157, 0xB3A5, 0x91CE,
+	0xB3A6, 0x91F5, 0xB3A7, 0x91E6, 0xB3A8, 0x91E3, 0xB3A9, 0x91E7,
+	0xB3AA, 0x91ED, 0xB3AB, 0x91E9, 0xB3AC, 0x9589, 0xB3AD, 0x966A,
+	0xB3AE, 0x9675, 0xB3AF, 0x9673, 0xB3B0, 0x9678, 0xB3B1, 0x9670,
+	0xB3B2, 0x9674, 0xB3B3, 0x9676, 0xB3B4, 0x9677, 0xB3B5, 0x966C,
+	0xB3B6, 0x96C0, 0xB3B7, 0x96EA, 0xB3B8, 0x96E9, 0xB3B9, 0x7AE0,
+	0xB3BA, 0x7ADF, 0xB3BB, 0x9802, 0xB3BC, 0x9803, 0xB3BD, 0x9B5A,
+	0xB3BE, 0x9CE5, 0xB3BF, 0x9E75, 0xB3C0, 0x9E7F, 0xB3C1, 0x9EA5,
+	0xB3C2, 0x9EBB, 0xB3C3, 0x50A2, 0xB3C4, 0x508D, 0xB3C5, 0x5085,
+	0xB3C6, 0x5099, 0xB3C7, 0x5091, 0xB3C8, 0x5080, 0xB3C9, 0x5096,
+	0xB3CA, 0x5098, 0xB3CB, 0x509A, 0xB3CC, 0x6700, 0xB3CD, 0x51F1,
+	0xB3CE, 0x5272, 0xB3CF, 0x5274, 0xB3D0, 0x5275, 0xB3D1, 0x5269,
+	0xB3D2, 0x52DE, 0xB3D3, 0x52DD, 0xB3D4, 0x52DB, 0xB3D5, 0x535A,
+	0xB3D6, 0x53A5, 0xB3D7, 0x557B, 0xB3D8, 0x5580, 0xB3D9, 0x55A7,
+	0xB3DA, 0x557C, 0xB3DB, 0x558A, 0xB3DC, 0x559D, 0xB3DD, 0x5598,
+	0xB3DE, 0x5582, 0xB3DF, 0x559C, 0xB3E0, 0x55AA, 0xB3E1, 0x5594,
+	0xB3E2, 0x5587, 0xB3E3, 0x558B, 0xB3E4, 0x5583, 0xB3E5, 0x55B3,
+	0xB3E6, 0x55AE, 0xB3E7, 0x559F, 0xB3E8, 0x553E, 0xB3E9, 0x55B2,
+	0xB3EA, 0x559A, 0xB3EB, 0x55BB, 0xB3EC, 0x55AC, 0xB3ED, 0x55B1,
+	0xB3EE, 0x557E, 0xB3EF, 0x5589, 0xB3F0, 0x55AB, 0xB3F1, 0x5599,
+	0xB3F2, 0x570D, 0xB3F3, 0x582F, 0xB3F4, 0x582A, 0xB3F5, 0x5834,
+	0xB3F6, 0x5824, 0xB3F7, 0x5830, 0xB3F8, 0x5831, 0xB3F9, 0x5821,
+	0xB3FA, 0x581D, 0xB3FB, 0x5820, 0xB3FC, 0x58F9, 0xB3FD, 0x58FA,
+	0xB3FE, 0x5960, 0xB440, 0x5A77, 0xB441, 0x5A9A, 0xB442, 0x5A7F,
+	0xB443, 0x5A92, 0xB444, 0x5A9B, 0xB445, 0x5AA7, 0xB446, 0x5B73,
+	0xB447, 0x5B71, 0xB448, 0x5BD2, 0xB449, 0x5BCC, 0xB44A, 0x5BD3,
+	0xB44B, 0x5BD0, 0xB44C, 0x5C0A, 0xB44D, 0x5C0B, 0xB44E, 0x5C31,
+	0xB44F, 0x5D4C, 0xB450, 0x5D50, 0xB451, 0x5D34, 0xB452, 0x5D47,
+	0xB453, 0x5DFD, 0xB454, 0x5E45, 0xB455, 0x5E3D, 0xB456, 0x5E40,
+	0xB457, 0x5E43, 0xB458, 0x5E7E, 0xB459, 0x5ECA, 0xB45A, 0x5EC1,
+	0xB45B, 0x5EC2, 0xB45C, 0x5EC4, 0xB45D, 0x5F3C, 0xB45E, 0x5F6D,
+	0xB45F, 0x5FA9, 0xB460, 0x5FAA, 0xB461, 0x5FA8, 0xB462, 0x60D1,
+	0xB463, 0x60E1, 0xB464, 0x60B2, 0xB465, 0x60B6, 0xB466, 0x60E0,
+	0xB467, 0x611C, 0xB468, 0x6123, 0xB469, 0x60FA, 0xB46A, 0x6115,
+	0xB46B, 0x60F0, 0xB46C, 0x60FB, 0xB46D, 0x60F4, 0xB46E, 0x6168,
+	0xB46F, 0x60F1, 0xB470, 0x610E, 0xB471, 0x60F6, 0xB472, 0x6109,
+	0xB473, 0x6100, 0xB474, 0x6112, 0xB475, 0x621F, 0xB476, 0x6249,
+	0xB477, 0x63A3, 0xB478, 0x638C, 0xB479, 0x63CF, 0xB47A, 0x63C0,
+	0xB47B, 0x63E9, 0xB47C, 0x63C9, 0xB47D, 0x63C6, 0xB47E, 0x63CD,
+	0xB4A1, 0x63D2, 0xB4A2, 0x63E3, 0xB4A3, 0x63D0, 0xB4A4, 0x63E1,
+	0xB4A5, 0x63D6, 0xB4A6, 0x63ED, 0xB4A7, 0x63EE, 0xB4A8, 0x6376,
+	0xB4A9, 0x63F4, 0xB4AA, 0x63EA, 0xB4AB, 0x63DB, 0xB4AC, 0x6452,
+	0xB4AD, 0x63DA, 0xB4AE, 0x63F9, 0xB4AF, 0x655E, 0xB4B0, 0x6566,
+	0xB4B1, 0x6562, 0xB4B2, 0x6563, 0xB4B3, 0x6591, 0xB4B4, 0x6590,
+	0xB4B5, 0x65AF, 0xB4B6, 0x666E, 0xB4B7, 0x6670, 0xB4B8, 0x6674,
+	0xB4B9, 0x6676, 0xB4BA, 0x666F, 0xB4BB, 0x6691, 0xB4BC, 0x667A,
+	0xB4BD, 0x667E, 0xB4BE, 0x6677, 0xB4BF, 0x66FE, 0xB4C0, 0x66FF,
+	0xB4C1, 0x671F, 0xB4C2, 0x671D, 0xB4C3, 0x68FA, 0xB4C4, 0x68D5,
+	0xB4C5, 0x68E0, 0xB4C6, 0x68D8, 0xB4C7, 0x68D7, 0xB4C8, 0x6905,
+	0xB4C9, 0x68DF, 0xB4CA, 0x68F5, 0xB4CB, 0x68EE, 0xB4CC, 0x68E7,
+	0xB4CD, 0x68F9, 0xB4CE, 0x68D2, 0xB4CF, 0x68F2, 0xB4D0, 0x68E3,
+	0xB4D1, 0x68CB, 0xB4D2, 0x68CD, 0xB4D3, 0x690D, 0xB4D4, 0x6912,
+	0xB4D5, 0x690E, 0xB4D6, 0x68C9, 0xB4D7, 0x68DA, 0xB4D8, 0x696E,
+	0xB4D9, 0x68FB, 0xB4DA, 0x6B3E, 0xB4DB, 0x6B3A, 0xB4DC, 0x6B3D,
+	0xB4DD, 0x6B98, 0xB4DE, 0x6B96, 0xB4DF, 0x6BBC, 0xB4E0, 0x6BEF,
+	0xB4E1, 0x6C2E, 0xB4E2, 0x6C2F, 0xB4E3, 0x6C2C, 0xB4E4, 0x6E2F,
+	0xB4E5, 0x6E38, 0xB4E6, 0x6E54, 0xB4E7, 0x6E21, 0xB4E8, 0x6E32,
+	0xB4E9, 0x6E67, 0xB4EA, 0x6E4A, 0xB4EB, 0x6E20, 0xB4EC, 0x6E25,
+	0xB4ED, 0x6E23, 0xB4EE, 0x6E1B, 0xB4EF, 0x6E5B, 0xB4F0, 0x6E58,
+	0xB4F1, 0x6E24, 0xB4F2, 0x6E56, 0xB4F3, 0x6E6E, 0xB4F4, 0x6E2D,
+	0xB4F5, 0x6E26, 0xB4F6, 0x6E6F, 0xB4F7, 0x6E34, 0xB4F8, 0x6E4D,
+	0xB4F9, 0x6E3A, 0xB4FA, 0x6E2C, 0xB4FB, 0x6E43, 0xB4FC, 0x6E1D,
+	0xB4FD, 0x6E3E, 0xB4FE, 0x6ECB, 0xB540, 0x6E89, 0xB541, 0x6E19,
+	0xB542, 0x6E4E, 0xB543, 0x6E63, 0xB544, 0x6E44, 0xB545, 0x6E72,
+	0xB546, 0x6E69, 0xB547, 0x6E5F, 0xB548, 0x7119, 0xB549, 0x711A,
+	0xB54A, 0x7126, 0xB54B, 0x7130, 0xB54C, 0x7121, 0xB54D, 0x7136,
+	0xB54E, 0x716E, 0xB54F, 0x711C, 0xB550, 0x724C, 0xB551, 0x7284,
+	0xB552, 0x7280, 0xB553, 0x7336, 0xB554, 0x7325, 0xB555, 0x7334,
+	0xB556, 0x7329, 0xB557, 0x743A, 0xB558, 0x742A, 0xB559, 0x7433,
+	0xB55A, 0x7422, 0xB55B, 0x7425, 0xB55C, 0x7435, 0xB55D, 0x7436,
+	0xB55E, 0x7434, 0xB55F, 0x742F, 0xB560, 0x741B, 0xB561, 0x7426,
+	0xB562, 0x7428, 0xB563, 0x7525, 0xB564, 0x7526, 0xB565, 0x756B,
+	0xB566, 0x756A, 0xB567, 0x75E2, 0xB568, 0x75DB, 0xB569, 0x75E3,
+	0xB56A, 0x75D9, 0xB56B, 0x75D8, 0xB56C, 0x75DE, 0xB56D, 0x75E0,
+	0xB56E, 0x767B, 0xB56F, 0x767C, 0xB570, 0x7696, 0xB571, 0x7693,
+	0xB572, 0x76B4, 0xB573, 0x76DC, 0xB574, 0x774F, 0xB575, 0x77ED,
+	0xB576, 0x785D, 0xB577, 0x786C, 0xB578, 0x786F, 0xB579, 0x7A0D,
+	0xB57A, 0x7A08, 0xB57B, 0x7A0B, 0xB57C, 0x7A05, 0xB57D, 0x7A00,
+	0xB57E, 0x7A98, 0xB5A1, 0x7A97, 0xB5A2, 0x7A96, 0xB5A3, 0x7AE5,
+	0xB5A4, 0x7AE3, 0xB5A5, 0x7B49, 0xB5A6, 0x7B56, 0xB5A7, 0x7B46,
+	0xB5A8, 0x7B50, 0xB5A9, 0x7B52, 0xB5AA, 0x7B54, 0xB5AB, 0x7B4D,
+	0xB5AC, 0x7B4B, 0xB5AD, 0x7B4F, 0xB5AE, 0x7B51, 0xB5AF, 0x7C9F,
+	0xB5B0, 0x7CA5, 0xB5B1, 0x7D5E, 0xB5B2, 0x7D50, 0xB5B3, 0x7D68,
+	0xB5B4, 0x7D55, 0xB5B5, 0x7D2B, 0xB5B6, 0x7D6E, 0xB5B7, 0x7D72,
+	0xB5B8, 0x7D61, 0xB5B9, 0x7D66, 0xB5BA, 0x7D62, 0xB5BB, 0x7D70,
+	0xB5BC, 0x7D73, 0xB5BD, 0x5584, 0xB5BE, 0x7FD4, 0xB5BF, 0x7FD5,
+	0xB5C0, 0x800B, 0xB5C1, 0x8052, 0xB5C2, 0x8085, 0xB5C3, 0x8155,
+	0xB5C4, 0x8154, 0xB5C5, 0x814B, 0xB5C6, 0x8151, 0xB5C7, 0x814E,
+	0xB5C8, 0x8139, 0xB5C9, 0x8146, 0xB5CA, 0x813E, 0xB5CB, 0x814C,
+	0xB5CC, 0x8153, 0xB5CD, 0x8174, 0xB5CE, 0x8212, 0xB5CF, 0x821C,
+	0xB5D0, 0x83E9, 0xB5D1, 0x8403, 0xB5D2, 0x83F8, 0xB5D3, 0x840D,
+	0xB5D4, 0x83E0, 0xB5D5, 0x83C5, 0xB5D6, 0x840B, 0xB5D7, 0x83C1,
+	0xB5D8, 0x83EF, 0xB5D9, 0x83F1, 0xB5DA, 0x83F4, 0xB5DB, 0x8457,
+	0xB5DC, 0x840A, 0xB5DD, 0x83F0, 0xB5DE, 0x840C, 0xB5DF, 0x83CC,
+	0xB5E0, 0x83FD, 0xB5E1, 0x83F2, 0xB5E2, 0x83CA, 0xB5E3, 0x8438,
+	0xB5E4, 0x840E, 0xB5E5, 0x8404, 0xB5E6, 0x83DC, 0xB5E7, 0x8407,
+	0xB5E8, 0x83D4, 0xB5E9, 0x83DF, 0xB5EA, 0x865B, 0xB5EB, 0x86DF,
+	0xB5EC, 0x86D9, 0xB5ED, 0x86ED, 0xB5EE, 0x86D4, 0xB5EF, 0x86DB,
+	0xB5F0, 0x86E4, 0xB5F1, 0x86D0, 0xB5F2, 0x86DE, 0xB5F3, 0x8857,
+	0xB5F4, 0x88C1, 0xB5F5, 0x88C2, 0xB5F6, 0x88B1, 0xB5F7, 0x8983,
+	0xB5F8, 0x8996, 0xB5F9, 0x8A3B, 0xB5FA, 0x8A60, 0xB5FB, 0x8A55,
+	0xB5FC, 0x8A5E, 0xB5FD, 0x8A3C, 0xB5FE, 0x8A41, 0xB640, 0x8A54,
+	0xB641, 0x8A5B, 0xB642, 0x8A50, 0xB643, 0x8A46, 0xB644, 0x8A34,
+	0xB645, 0x8A3A, 0xB646, 0x8A36, 0xB647, 0x8A56, 0xB648, 0x8C61,
+	0xB649, 0x8C82, 0xB64A, 0x8CAF, 0xB64B, 0x8CBC, 0xB64C, 0x8CB3,
+	0xB64D, 0x8CBD, 0xB64E, 0x8CC1, 0xB64F, 0x8CBB, 0xB650, 0x8CC0,
+	0xB651, 0x8CB4, 0xB652, 0x8CB7, 0xB653, 0x8CB6, 0xB654, 0x8CBF,
+	0xB655, 0x8CB8, 0xB656, 0x8D8A, 0xB657, 0x8D85, 0xB658, 0x8D81,
+	0xB659, 0x8DCE, 0xB65A, 0x8DDD, 0xB65B, 0x8DCB, 0xB65C, 0x8DDA,
+	0xB65D, 0x8DD1, 0xB65E, 0x8DCC, 0xB65F, 0x8DDB, 0xB660, 0x8DC6,
+	0xB661, 0x8EFB, 0xB662, 0x8EF8, 0xB663, 0x8EFC, 0xB664, 0x8F9C,
+	0xB665, 0x902E, 0xB666, 0x9035, 0xB667, 0x9031, 0xB668, 0x9038,
+	0xB669, 0x9032, 0xB66A, 0x9036, 0xB66B, 0x9102, 0xB66C, 0x90F5,
+	0xB66D, 0x9109, 0xB66E, 0x90FE, 0xB66F, 0x9163, 0xB670, 0x9165,
+	0xB671, 0x91CF, 0xB672, 0x9214, 0xB673, 0x9215, 0xB674, 0x9223,
+	0xB675, 0x9209, 0xB676, 0x921E, 0xB677, 0x920D, 0xB678, 0x9210,
+	0xB679, 0x9207, 0xB67A, 0x9211, 0xB67B, 0x9594, 0xB67C, 0x958F,
+	0xB67D, 0x958B, 0xB67E, 0x9591, 0xB6A1, 0x9593, 0xB6A2, 0x9592,
+	0xB6A3, 0x958E, 0xB6A4, 0x968A, 0xB6A5, 0x968E, 0xB6A6, 0x968B,
+	0xB6A7, 0x967D, 0xB6A8, 0x9685, 0xB6A9, 0x9686, 0xB6AA, 0x968D,
+	0xB6AB, 0x9672, 0xB6AC, 0x9684, 0xB6AD, 0x96C1, 0xB6AE, 0x96C5,
+	0xB6AF, 0x96C4, 0xB6B0, 0x96C6, 0xB6B1, 0x96C7, 0xB6B2, 0x96EF,
+	0xB6B3, 0x96F2, 0xB6B4, 0x97CC, 0xB6B5, 0x9805, 0xB6B6, 0x9806,
+	0xB6B7, 0x9808, 0xB6B8, 0x98E7, 0xB6B9, 0x98EA, 0xB6BA, 0x98EF,
+	0xB6BB, 0x98E9, 0xB6BC, 0x98F2, 0xB6BD, 0x98ED, 0xB6BE, 0x99AE,
+	0xB6BF, 0x99AD, 0xB6C0, 0x9EC3, 0xB6C1, 0x9ECD, 0xB6C2, 0x9ED1,
+	0xB6C3, 0x4E82, 0xB6C4, 0x50AD, 0xB6C5, 0x50B5, 0xB6C6, 0x50B2,
+	0xB6C7, 0x50B3, 0xB6C8, 0x50C5, 0xB6C9, 0x50BE, 0xB6CA, 0x50AC,
+	0xB6CB, 0x50B7, 0xB6CC, 0x50BB, 0xB6CD, 0x50AF, 0xB6CE, 0x50C7,
+	0xB6CF, 0x527F, 0xB6D0, 0x5277, 0xB6D1, 0x527D, 0xB6D2, 0x52DF,
+	0xB6D3, 0x52E6, 0xB6D4, 0x52E4, 0xB6D5, 0x52E2, 0xB6D6, 0x52E3,
+	0xB6D7, 0x532F, 0xB6D8, 0x55DF, 0xB6D9, 0x55E8, 0xB6DA, 0x55D3,
+	0xB6DB, 0x55E6, 0xB6DC, 0x55CE, 0xB6DD, 0x55DC, 0xB6DE, 0x55C7,
+	0xB6DF, 0x55D1, 0xB6E0, 0x55E3, 0xB6E1, 0x55E4, 0xB6E2, 0x55EF,
+	0xB6E3, 0x55DA, 0xB6E4, 0x55E1, 0xB6E5, 0x55C5, 0xB6E6, 0x55C6,
+	0xB6E7, 0x55E5, 0xB6E8, 0x55C9, 0xB6E9, 0x5712, 0xB6EA, 0x5713,
+	0xB6EB, 0x585E, 0xB6EC, 0x5851, 0xB6ED, 0x5858, 0xB6EE, 0x5857,
+	0xB6EF, 0x585A, 0xB6F0, 0x5854, 0xB6F1, 0x586B, 0xB6F2, 0x584C,
+	0xB6F3, 0x586D, 0xB6F4, 0x584A, 0xB6F5, 0x5862, 0xB6F6, 0x5852,
+	0xB6F7, 0x584B, 0xB6F8, 0x5967, 0xB6F9, 0x5AC1, 0xB6FA, 0x5AC9,
+	0xB6FB, 0x5ACC, 0xB6FC, 0x5ABE, 0xB6FD, 0x5ABD, 0xB6FE, 0x5ABC,
+	0xB740, 0x5AB3, 0xB741, 0x5AC2, 0xB742, 0x5AB2, 0xB743, 0x5D69,
+	0xB744, 0x5D6F, 0xB745, 0x5E4C, 0xB746, 0x5E79, 0xB747, 0x5EC9,
+	0xB748, 0x5EC8, 0xB749, 0x5F12, 0xB74A, 0x5F59, 0xB74B, 0x5FAC,
+	0xB74C, 0x5FAE, 0xB74D, 0x611A, 0xB74E, 0x610F, 0xB74F, 0x6148,
+	0xB750, 0x611F, 0xB751, 0x60F3, 0xB752, 0x611B, 0xB753, 0x60F9,
+	0xB754, 0x6101, 0xB755, 0x6108, 0xB756, 0x614E, 0xB757, 0x614C,
+	0xB758, 0x6144, 0xB759, 0x614D, 0xB75A, 0x613E, 0xB75B, 0x6134,
+	0xB75C, 0x6127, 0xB75D, 0x610D, 0xB75E, 0x6106, 0xB75F, 0x6137,
+	0xB760, 0x6221, 0xB761, 0x6222, 0xB762, 0x6413, 0xB763, 0x643E,
+	0xB764, 0x641E, 0xB765, 0x642A, 0xB766, 0x642D, 0xB767, 0x643D,
+	0xB768, 0x642C, 0xB769, 0x640F, 0xB76A, 0x641C, 0xB76B, 0x6414,
+	0xB76C, 0x640D, 0xB76D, 0x6436, 0xB76E, 0x6416, 0xB76F, 0x6417,
+	0xB770, 0x6406, 0xB771, 0x656C, 0xB772, 0x659F, 0xB773, 0x65B0,
+	0xB774, 0x6697, 0xB775, 0x6689, 0xB776, 0x6687, 0xB777, 0x6688,
+	0xB778, 0x6696, 0xB779, 0x6684, 0xB77A, 0x6698, 0xB77B, 0x668D,
+	0xB77C, 0x6703, 0xB77D, 0x6994, 0xB77E, 0x696D, 0xB7A1, 0x695A,
+	0xB7A2, 0x6977, 0xB7A3, 0x6960, 0xB7A4, 0x6954, 0xB7A5, 0x6975,
+	0xB7A6, 0x6930, 0xB7A7, 0x6982, 0xB7A8, 0x694A, 0xB7A9, 0x6968,
+	0xB7AA, 0x696B, 0xB7AB, 0x695E, 0xB7AC, 0x6953, 0xB7AD, 0x6979,
+	0xB7AE, 0x6986, 0xB7AF, 0x695D, 0xB7B0, 0x6963, 0xB7B1, 0x695B,
+	0xB7B2, 0x6B47, 0xB7B3, 0x6B72, 0xB7B4, 0x6BC0, 0xB7B5, 0x6BBF,
+	0xB7B6, 0x6BD3, 0xB7B7, 0x6BFD, 0xB7B8, 0x6EA2, 0xB7B9, 0x6EAF,
+	0xB7BA, 0x6ED3, 0xB7BB, 0x6EB6, 0xB7BC, 0x6EC2, 0xB7BD, 0x6E90,
+	0xB7BE, 0x6E9D, 0xB7BF, 0x6EC7, 0xB7C0, 0x6EC5, 0xB7C1, 0x6EA5,
+	0xB7C2, 0x6E98, 0xB7C3, 0x6EBC, 0xB7C4, 0x6EBA, 0xB7C5, 0x6EAB,
+	0xB7C6, 0x6ED1, 0xB7C7, 0x6E96, 0xB7C8, 0x6E9C, 0xB7C9, 0x6EC4,
+	0xB7CA, 0x6ED4, 0xB7CB, 0x6EAA, 0xB7CC, 0x6EA7, 0xB7CD, 0x6EB4,
+	0xB7CE, 0x714E, 0xB7CF, 0x7159, 0xB7D0, 0x7169, 0xB7D1, 0x7164,
+	0xB7D2, 0x7149, 0xB7D3, 0x7167, 0xB7D4, 0x715C, 0xB7D5, 0x716C,
+	0xB7D6, 0x7166, 0xB7D7, 0x714C, 0xB7D8, 0x7165, 0xB7D9, 0x715E,
+	0xB7DA, 0x7146, 0xB7DB, 0x7168, 0xB7DC, 0x7156, 0xB7DD, 0x723A,
+	0xB7DE, 0x7252, 0xB7DF, 0x7337, 0xB7E0, 0x7345, 0xB7E1, 0x733F,
+	0xB7E2, 0x733E, 0xB7E3, 0x746F, 0xB7E4, 0x745A, 0xB7E5, 0x7455,
+	0xB7E6, 0x745F, 0xB7E7, 0x745E, 0xB7E8, 0x7441, 0xB7E9, 0x743F,
+	0xB7EA, 0x7459, 0xB7EB, 0x745B, 0xB7EC, 0x745C, 0xB7ED, 0x7576,
+	0xB7EE, 0x7578, 0xB7EF, 0x7600, 0xB7F0, 0x75F0, 0xB7F1, 0x7601,
+	0xB7F2, 0x75F2, 0xB7F3, 0x75F1, 0xB7F4, 0x75FA, 0xB7F5, 0x75FF,
+	0xB7F6, 0x75F4, 0xB7F7, 0x75F3, 0xB7F8, 0x76DE, 0xB7F9, 0x76DF,
+	0xB7FA, 0x775B, 0xB7FB, 0x776B, 0xB7FC, 0x7766, 0xB7FD, 0x775E,
+	0xB7FE, 0x7763, 0xB840, 0x7779, 0xB841, 0x776A, 0xB842, 0x776C,
+	0xB843, 0x775C, 0xB844, 0x7765, 0xB845, 0x7768, 0xB846, 0x7762,
+	0xB847, 0x77EE, 0xB848, 0x788E, 0xB849, 0x78B0, 0xB84A, 0x7897,
+	0xB84B, 0x7898, 0xB84C, 0x788C, 0xB84D, 0x7889, 0xB84E, 0x787C,
+	0xB84F, 0x7891, 0xB850, 0x7893, 0xB851, 0x787F, 0xB852, 0x797A,
+	0xB853, 0x797F, 0xB854, 0x7981, 0xB855, 0x842C, 0xB856, 0x79BD,
+	0xB857, 0x7A1C, 0xB858, 0x7A1A, 0xB859, 0x7A20, 0xB85A, 0x7A14,
+	0xB85B, 0x7A1F, 0xB85C, 0x7A1E, 0xB85D, 0x7A9F, 0xB85E, 0x7AA0,
+	0xB85F, 0x7B77, 0xB860, 0x7BC0, 0xB861, 0x7B60, 0xB862, 0x7B6E,
+	0xB863, 0x7B67, 0xB864, 0x7CB1, 0xB865, 0x7CB3, 0xB866, 0x7CB5,
+	0xB867, 0x7D93, 0xB868, 0x7D79, 0xB869, 0x7D91, 0xB86A, 0x7D81,
+	0xB86B, 0x7D8F, 0xB86C, 0x7D5B, 0xB86D, 0x7F6E, 0xB86E, 0x7F69,
+	0xB86F, 0x7F6A, 0xB870, 0x7F72, 0xB871, 0x7FA9, 0xB872, 0x7FA8,
+	0xB873, 0x7FA4, 0xB874, 0x8056, 0xB875, 0x8058, 0xB876, 0x8086,
+	0xB877, 0x8084, 0xB878, 0x8171, 0xB879, 0x8170, 0xB87A, 0x8178,
+	0xB87B, 0x8165, 0xB87C, 0x816E, 0xB87D, 0x8173, 0xB87E, 0x816B,
+	0xB8A1, 0x8179, 0xB8A2, 0x817A, 0xB8A3, 0x8166, 0xB8A4, 0x8205,
+	0xB8A5, 0x8247, 0xB8A6, 0x8482, 0xB8A7, 0x8477, 0xB8A8, 0x843D,
+	0xB8A9, 0x8431, 0xB8AA, 0x8475, 0xB8AB, 0x8466, 0xB8AC, 0x846B,
+	0xB8AD, 0x8449, 0xB8AE, 0x846C, 0xB8AF, 0x845B, 0xB8B0, 0x843C,
+	0xB8B1, 0x8435, 0xB8B2, 0x8461, 0xB8B3, 0x8463, 0xB8B4, 0x8469,
+	0xB8B5, 0x846D, 0xB8B6, 0x8446, 0xB8B7, 0x865E, 0xB8B8, 0x865C,
+	0xB8B9, 0x865F, 0xB8BA, 0x86F9, 0xB8BB, 0x8713, 0xB8BC, 0x8708,
+	0xB8BD, 0x8707, 0xB8BE, 0x8700, 0xB8BF, 0x86FE, 0xB8C0, 0x86FB,
+	0xB8C1, 0x8702, 0xB8C2, 0x8703, 0xB8C3, 0x8706, 0xB8C4, 0x870A,
+	0xB8C5, 0x8859, 0xB8C6, 0x88DF, 0xB8C7, 0x88D4, 0xB8C8, 0x88D9,
+	0xB8C9, 0x88DC, 0xB8CA, 0x88D8, 0xB8CB, 0x88DD, 0xB8CC, 0x88E1,
+	0xB8CD, 0x88CA, 0xB8CE, 0x88D5, 0xB8CF, 0x88D2, 0xB8D0, 0x899C,
+	0xB8D1, 0x89E3, 0xB8D2, 0x8A6B, 0xB8D3, 0x8A72, 0xB8D4, 0x8A73,
+	0xB8D5, 0x8A66, 0xB8D6, 0x8A69, 0xB8D7, 0x8A70, 0xB8D8, 0x8A87,
+	0xB8D9, 0x8A7C, 0xB8DA, 0x8A63, 0xB8DB, 0x8AA0, 0xB8DC, 0x8A71,
+	0xB8DD, 0x8A85, 0xB8DE, 0x8A6D, 0xB8DF, 0x8A62, 0xB8E0, 0x8A6E,
+	0xB8E1, 0x8A6C, 0xB8E2, 0x8A79, 0xB8E3, 0x8A7B, 0xB8E4, 0x8A3E,
+	0xB8E5, 0x8A68, 0xB8E6, 0x8C62, 0xB8E7, 0x8C8A, 0xB8E8, 0x8C89,
+	0xB8E9, 0x8CCA, 0xB8EA, 0x8CC7, 0xB8EB, 0x8CC8, 0xB8EC, 0x8CC4,
+	0xB8ED, 0x8CB2, 0xB8EE, 0x8CC3, 0xB8EF, 0x8CC2, 0xB8F0, 0x8CC5,
+	0xB8F1, 0x8DE1, 0xB8F2, 0x8DDF, 0xB8F3, 0x8DE8, 0xB8F4, 0x8DEF,
+	0xB8F5, 0x8DF3, 0xB8F6, 0x8DFA, 0xB8F7, 0x8DEA, 0xB8F8, 0x8DE4,
+	0xB8F9, 0x8DE6, 0xB8FA, 0x8EB2, 0xB8FB, 0x8F03, 0xB8FC, 0x8F09,
+	0xB8FD, 0x8EFE, 0xB8FE, 0x8F0A, 0xB940, 0x8F9F, 0xB941, 0x8FB2,
+	0xB942, 0x904B, 0xB943, 0x904A, 0xB944, 0x9053, 0xB945, 0x9042,
+	0xB946, 0x9054, 0xB947, 0x903C, 0xB948, 0x9055, 0xB949, 0x9050,
+	0xB94A, 0x9047, 0xB94B, 0x904F, 0xB94C, 0x904E, 0xB94D, 0x904D,
+	0xB94E, 0x9051, 0xB94F, 0x903E, 0xB950, 0x9041, 0xB951, 0x9112,
+	0xB952, 0x9117, 0xB953, 0x916C, 0xB954, 0x916A, 0xB955, 0x9169,
+	0xB956, 0x91C9, 0xB957, 0x9237, 0xB958, 0x9257, 0xB959, 0x9238,
+	0xB95A, 0x923D, 0xB95B, 0x9240, 0xB95C, 0x923E, 0xB95D, 0x925B,
+	0xB95E, 0x924B, 0xB95F, 0x9264, 0xB960, 0x9251, 0xB961, 0x9234,
+	0xB962, 0x9249, 0xB963, 0x924D, 0xB964, 0x9245, 0xB965, 0x9239,
+	0xB966, 0x923F, 0xB967, 0x925A, 0xB968, 0x9598, 0xB969, 0x9698,
+	0xB96A, 0x9694, 0xB96B, 0x9695, 0xB96C, 0x96CD, 0xB96D, 0x96CB,
+	0xB96E, 0x96C9, 0xB96F, 0x96CA, 0xB970, 0x96F7, 0xB971, 0x96FB,
+	0xB972, 0x96F9, 0xB973, 0x96F6, 0xB974, 0x9756, 0xB975, 0x9774,
+	0xB976, 0x9776, 0xB977, 0x9810, 0xB978, 0x9811, 0xB979, 0x9813,
+	0xB97A, 0x980A, 0xB97B, 0x9812, 0xB97C, 0x980C, 0xB97D, 0x98FC,
+	0xB97E, 0x98F4, 0xB9A1, 0x98FD, 0xB9A2, 0x98FE, 0xB9A3, 0x99B3,
+	0xB9A4, 0x99B1, 0xB9A5, 0x99B4, 0xB9A6, 0x9AE1, 0xB9A7, 0x9CE9,
+	0xB9A8, 0x9E82, 0xB9A9, 0x9F0E, 0xB9AA, 0x9F13, 0xB9AB, 0x9F20,
+	0xB9AC, 0x50E7, 0xB9AD, 0x50EE, 0xB9AE, 0x50E5, 0xB9AF, 0x50D6,
+	0xB9B0, 0x50ED, 0xB9B1, 0x50DA, 0xB9B2, 0x50D5, 0xB9B3, 0x50CF,
+	0xB9B4, 0x50D1, 0xB9B5, 0x50F1, 0xB9B6, 0x50CE, 0xB9B7, 0x50E9,
+	0xB9B8, 0x5162, 0xB9B9, 0x51F3, 0xB9BA, 0x5283, 0xB9BB, 0x5282,
+	0xB9BC, 0x5331, 0xB9BD, 0x53AD, 0xB9BE, 0x55FE, 0xB9BF, 0x5600,
+	0xB9C0, 0x561B, 0xB9C1, 0x5617, 0xB9C2, 0x55FD, 0xB9C3, 0x5614,
+	0xB9C4, 0x5606, 0xB9C5, 0x5609, 0xB9C6, 0x560D, 0xB9C7, 0x560E,
+	0xB9C8, 0x55F7, 0xB9C9, 0x5616, 0xB9CA, 0x561F, 0xB9CB, 0x5608,
+	0xB9CC, 0x5610, 0xB9CD, 0x55F6, 0xB9CE, 0x5718, 0xB9CF, 0x5716,
+	0xB9D0, 0x5875, 0xB9D1, 0x587E, 0xB9D2, 0x5883, 0xB9D3, 0x5893,
+	0xB9D4, 0x588A, 0xB9D5, 0x5879, 0xB9D6, 0x5885, 0xB9D7, 0x587D,
+	0xB9D8, 0x58FD, 0xB9D9, 0x5925, 0xB9DA, 0x5922, 0xB9DB, 0x5924,
+	0xB9DC, 0x596A, 0xB9DD, 0x5969, 0xB9DE, 0x5AE1, 0xB9DF, 0x5AE6,
+	0xB9E0, 0x5AE9, 0xB9E1, 0x5AD7, 0xB9E2, 0x5AD6, 0xB9E3, 0x5AD8,
+	0xB9E4, 0x5AE3, 0xB9E5, 0x5B75, 0xB9E6, 0x5BDE, 0xB9E7, 0x5BE7,
+	0xB9E8, 0x5BE1, 0xB9E9, 0x5BE5, 0xB9EA, 0x5BE6, 0xB9EB, 0x5BE8,
+	0xB9EC, 0x5BE2, 0xB9ED, 0x5BE4, 0xB9EE, 0x5BDF, 0xB9EF, 0x5C0D,
+	0xB9F0, 0x5C62, 0xB9F1, 0x5D84, 0xB9F2, 0x5D87, 0xB9F3, 0x5E5B,
+	0xB9F4, 0x5E63, 0xB9F5, 0x5E55, 0xB9F6, 0x5E57, 0xB9F7, 0x5E54,
+	0xB9F8, 0x5ED3, 0xB9F9, 0x5ED6, 0xB9FA, 0x5F0A, 0xB9FB, 0x5F46,
+	0xB9FC, 0x5F70, 0xB9FD, 0x5FB9, 0xB9FE, 0x6147, 0xBA40, 0x613F,
+	0xBA41, 0x614B, 0xBA42, 0x6177, 0xBA43, 0x6162, 0xBA44, 0x6163,
+	0xBA45, 0x615F, 0xBA46, 0x615A, 0xBA47, 0x6158, 0xBA48, 0x6175,
+	0xBA49, 0x622A, 0xBA4A, 0x6487, 0xBA4B, 0x6458, 0xBA4C, 0x6454,
+	0xBA4D, 0x64A4, 0xBA4E, 0x6478, 0xBA4F, 0x645F, 0xBA50, 0x647A,
+	0xBA51, 0x6451, 0xBA52, 0x6467, 0xBA53, 0x6434, 0xBA54, 0x646D,
+	0xBA55, 0x647B, 0xBA56, 0x6572, 0xBA57, 0x65A1, 0xBA58, 0x65D7,
+	0xBA59, 0x65D6, 0xBA5A, 0x66A2, 0xBA5B, 0x66A8, 0xBA5C, 0x669D,
+	0xBA5D, 0x699C, 0xBA5E, 0x69A8, 0xBA5F, 0x6995, 0xBA60, 0x69C1,
+	0xBA61, 0x69AE, 0xBA62, 0x69D3, 0xBA63, 0x69CB, 0xBA64, 0x699B,
+	0xBA65, 0x69B7, 0xBA66, 0x69BB, 0xBA67, 0x69AB, 0xBA68, 0x69B4,
+	0xBA69, 0x69D0, 0xBA6A, 0x69CD, 0xBA6B, 0x69AD, 0xBA6C, 0x69CC,
+	0xBA6D, 0x69A6, 0xBA6E, 0x69C3, 0xBA6F, 0x69A3, 0xBA70, 0x6B49,
+	0xBA71, 0x6B4C, 0xBA72, 0x6C33, 0xBA73, 0x6F33, 0xBA74, 0x6F14,
+	0xBA75, 0x6EFE, 0xBA76, 0x6F13, 0xBA77, 0x6EF4, 0xBA78, 0x6F29,
+	0xBA79, 0x6F3E, 0xBA7A, 0x6F20, 0xBA7B, 0x6F2C, 0xBA7C, 0x6F0F,
+	0xBA7D, 0x6F02, 0xBA7E, 0x6F22, 0xBAA1, 0x6EFF, 0xBAA2, 0x6EEF,
+	0xBAA3, 0x6F06, 0xBAA4, 0x6F31, 0xBAA5, 0x6F38, 0xBAA6, 0x6F32,
+	0xBAA7, 0x6F23, 0xBAA8, 0x6F15, 0xBAA9, 0x6F2B, 0xBAAA, 0x6F2F,
+	0xBAAB, 0x6F88, 0xBAAC, 0x6F2A, 0xBAAD, 0x6EEC, 0xBAAE, 0x6F01,
+	0xBAAF, 0x6EF2, 0xBAB0, 0x6ECC, 0xBAB1, 0x6EF7, 0xBAB2, 0x7194,
+	0xBAB3, 0x7199, 0xBAB4, 0x717D, 0xBAB5, 0x718A, 0xBAB6, 0x7184,
+	0xBAB7, 0x7192, 0xBAB8, 0x723E, 0xBAB9, 0x7292, 0xBABA, 0x7296,
+	0xBABB, 0x7344, 0xBABC, 0x7350, 0xBABD, 0x7464, 0xBABE, 0x7463,
+	0xBABF, 0x746A, 0xBAC0, 0x7470, 0xBAC1, 0x746D, 0xBAC2, 0x7504,
+	0xBAC3, 0x7591, 0xBAC4, 0x7627, 0xBAC5, 0x760D, 0xBAC6, 0x760B,
+	0xBAC7, 0x7609, 0xBAC8, 0x7613, 0xBAC9, 0x76E1, 0xBACA, 0x76E3,
+	0xBACB, 0x7784, 0xBACC, 0x777D, 0xBACD, 0x777F, 0xBACE, 0x7761,
+	0xBACF, 0x78C1, 0xBAD0, 0x789F, 0xBAD1, 0x78A7, 0xBAD2, 0x78B3,
+	0xBAD3, 0x78A9, 0xBAD4, 0x78A3, 0xBAD5, 0x798E, 0xBAD6, 0x798F,
+	0xBAD7, 0x798D, 0xBAD8, 0x7A2E, 0xBAD9, 0x7A31, 0xBADA, 0x7AAA,
+	0xBADB, 0x7AA9, 0xBADC, 0x7AED, 0xBADD, 0x7AEF, 0xBADE, 0x7BA1,
+	0xBADF, 0x7B95, 0xBAE0, 0x7B8B, 0xBAE1, 0x7B75, 0xBAE2, 0x7B97,
+	0xBAE3, 0x7B9D, 0xBAE4, 0x7B94, 0xBAE5, 0x7B8F, 0xBAE6, 0x7BB8,
+	0xBAE7, 0x7B87, 0xBAE8, 0x7B84, 0xBAE9, 0x7CB9, 0xBAEA, 0x7CBD,
+	0xBAEB, 0x7CBE, 0xBAEC, 0x7DBB, 0xBAED, 0x7DB0, 0xBAEE, 0x7D9C,
+	0xBAEF, 0x7DBD, 0xBAF0, 0x7DBE, 0xBAF1, 0x7DA0, 0xBAF2, 0x7DCA,
+	0xBAF3, 0x7DB4, 0xBAF4, 0x7DB2, 0xBAF5, 0x7DB1, 0xBAF6, 0x7DBA,
+	0xBAF7, 0x7DA2, 0xBAF8, 0x7DBF, 0xBAF9, 0x7DB5, 0xBAFA, 0x7DB8,
+	0xBAFB, 0x7DAD, 0xBAFC, 0x7DD2, 0xBAFD, 0x7DC7, 0xBAFE, 0x7DAC,
+	0xBB40, 0x7F70, 0xBB41, 0x7FE0, 0xBB42, 0x7FE1, 0xBB43, 0x7FDF,
+	0xBB44, 0x805E, 0xBB45, 0x805A, 0xBB46, 0x8087, 0xBB47, 0x8150,
+	0xBB48, 0x8180, 0xBB49, 0x818F, 0xBB4A, 0x8188, 0xBB4B, 0x818A,
+	0xBB4C, 0x817F, 0xBB4D, 0x8182, 0xBB4E, 0x81E7, 0xBB4F, 0x81FA,
+	0xBB50, 0x8207, 0xBB51, 0x8214, 0xBB52, 0x821E, 0xBB53, 0x824B,
+	0xBB54, 0x84C9, 0xBB55, 0x84BF, 0xBB56, 0x84C6, 0xBB57, 0x84C4,
+	0xBB58, 0x8499, 0xBB59, 0x849E, 0xBB5A, 0x84B2, 0xBB5B, 0x849C,
+	0xBB5C, 0x84CB, 0xBB5D, 0x84B8, 0xBB5E, 0x84C0, 0xBB5F, 0x84D3,
+	0xBB60, 0x8490, 0xBB61, 0x84BC, 0xBB62, 0x84D1, 0xBB63, 0x84CA,
+	0xBB64, 0x873F, 0xBB65, 0x871C, 0xBB66, 0x873B, 0xBB67, 0x8722,
+	0xBB68, 0x8725, 0xBB69, 0x8734, 0xBB6A, 0x8718, 0xBB6B, 0x8755,
+	0xBB6C, 0x8737, 0xBB6D, 0x8729, 0xBB6E, 0x88F3, 0xBB6F, 0x8902,
+	0xBB70, 0x88F4, 0xBB71, 0x88F9, 0xBB72, 0x88F8, 0xBB73, 0x88FD,
+	0xBB74, 0x88E8, 0xBB75, 0x891A, 0xBB76, 0x88EF, 0xBB77, 0x8AA6,
+	0xBB78, 0x8A8C, 0xBB79, 0x8A9E, 0xBB7A, 0x8AA3, 0xBB7B, 0x8A8D,
+	0xBB7C, 0x8AA1, 0xBB7D, 0x8A93, 0xBB7E, 0x8AA4, 0xBBA1, 0x8AAA,
+	0xBBA2, 0x8AA5, 0xBBA3, 0x8AA8, 0xBBA4, 0x8A98, 0xBBA5, 0x8A91,
+	0xBBA6, 0x8A9A, 0xBBA7, 0x8AA7, 0xBBA8, 0x8C6A, 0xBBA9, 0x8C8D,
+	0xBBAA, 0x8C8C, 0xBBAB, 0x8CD3, 0xBBAC, 0x8CD1, 0xBBAD, 0x8CD2,
+	0xBBAE, 0x8D6B, 0xBBAF, 0x8D99, 0xBBB0, 0x8D95, 0xBBB1, 0x8DFC,
+	0xBBB2, 0x8F14, 0xBBB3, 0x8F12, 0xBBB4, 0x8F15, 0xBBB5, 0x8F13,
+	0xBBB6, 0x8FA3, 0xBBB7, 0x9060, 0xBBB8, 0x9058, 0xBBB9, 0x905C,
+	0xBBBA, 0x9063, 0xBBBB, 0x9059, 0xBBBC, 0x905E, 0xBBBD, 0x9062,
+	0xBBBE, 0x905D, 0xBBBF, 0x905B, 0xBBC0, 0x9119, 0xBBC1, 0x9118,
+	0xBBC2, 0x911E, 0xBBC3, 0x9175, 0xBBC4, 0x9178, 0xBBC5, 0x9177,
+	0xBBC6, 0x9174, 0xBBC7, 0x9278, 0xBBC8, 0x9280, 0xBBC9, 0x9285,
+	0xBBCA, 0x9298, 0xBBCB, 0x9296, 0xBBCC, 0x927B, 0xBBCD, 0x9293,
+	0xBBCE, 0x929C, 0xBBCF, 0x92A8, 0xBBD0, 0x927C, 0xBBD1, 0x9291,
+	0xBBD2, 0x95A1, 0xBBD3, 0x95A8, 0xBBD4, 0x95A9, 0xBBD5, 0x95A3,
+	0xBBD6, 0x95A5, 0xBBD7, 0x95A4, 0xBBD8, 0x9699, 0xBBD9, 0x969C,
+	0xBBDA, 0x969B, 0xBBDB, 0x96CC, 0xBBDC, 0x96D2, 0xBBDD, 0x9700,
+	0xBBDE, 0x977C, 0xBBDF, 0x9785, 0xBBE0, 0x97F6, 0xBBE1, 0x9817,
+	0xBBE2, 0x9818, 0xBBE3, 0x98AF, 0xBBE4, 0x98B1, 0xBBE5, 0x9903,
+	0xBBE6, 0x9905, 0xBBE7, 0x990C, 0xBBE8, 0x9909, 0xBBE9, 0x99C1,
+	0xBBEA, 0x9AAF, 0xBBEB, 0x9AB0, 0xBBEC, 0x9AE6, 0xBBED, 0x9B41,
+	0xBBEE, 0x9B42, 0xBBEF, 0x9CF4, 0xBBF0, 0x9CF6, 0xBBF1, 0x9CF3,
+	0xBBF2, 0x9EBC, 0xBBF3, 0x9F3B, 0xBBF4, 0x9F4A, 0xBBF5, 0x5104,
+	0xBBF6, 0x5100, 0xBBF7, 0x50FB, 0xBBF8, 0x50F5, 0xBBF9, 0x50F9,
+	0xBBFA, 0x5102, 0xBBFB, 0x5108, 0xBBFC, 0x5109, 0xBBFD, 0x5105,
+	0xBBFE, 0x51DC, 0xBC40, 0x5287, 0xBC41, 0x5288, 0xBC42, 0x5289,
+	0xBC43, 0x528D, 0xBC44, 0x528A, 0xBC45, 0x52F0, 0xBC46, 0x53B2,
+	0xBC47, 0x562E, 0xBC48, 0x563B, 0xBC49, 0x5639, 0xBC4A, 0x5632,
+	0xBC4B, 0x563F, 0xBC4C, 0x5634, 0xBC4D, 0x5629, 0xBC4E, 0x5653,
+	0xBC4F, 0x564E, 0xBC50, 0x5657, 0xBC51, 0x5674, 0xBC52, 0x5636,
+	0xBC53, 0x562F, 0xBC54, 0x5630, 0xBC55, 0x5880, 0xBC56, 0x589F,
+	0xBC57, 0x589E, 0xBC58, 0x58B3, 0xBC59, 0x589C, 0xBC5A, 0x58AE,
+	0xBC5B, 0x58A9, 0xBC5C, 0x58A6, 0xBC5D, 0x596D, 0xBC5E, 0x5B09,
+	0xBC5F, 0x5AFB, 0xBC60, 0x5B0B, 0xBC61, 0x5AF5, 0xBC62, 0x5B0C,
+	0xBC63, 0x5B08, 0xBC64, 0x5BEE, 0xBC65, 0x5BEC, 0xBC66, 0x5BE9,
+	0xBC67, 0x5BEB, 0xBC68, 0x5C64, 0xBC69, 0x5C65, 0xBC6A, 0x5D9D,
+	0xBC6B, 0x5D94, 0xBC6C, 0x5E62, 0xBC6D, 0x5E5F, 0xBC6E, 0x5E61,
+	0xBC6F, 0x5EE2, 0xBC70, 0x5EDA, 0xBC71, 0x5EDF, 0xBC72, 0x5EDD,
+	0xBC73, 0x5EE3, 0xBC74, 0x5EE0, 0xBC75, 0x5F48, 0xBC76, 0x5F71,
+	0xBC77, 0x5FB7, 0xBC78, 0x5FB5, 0xBC79, 0x6176, 0xBC7A, 0x6167,
+	0xBC7B, 0x616E, 0xBC7C, 0x615D, 0xBC7D, 0x6155, 0xBC7E, 0x6182,
+	0xBCA1, 0x617C, 0xBCA2, 0x6170, 0xBCA3, 0x616B, 0xBCA4, 0x617E,
+	0xBCA5, 0x61A7, 0xBCA6, 0x6190, 0xBCA7, 0x61AB, 0xBCA8, 0x618E,
+	0xBCA9, 0x61AC, 0xBCAA, 0x619A, 0xBCAB, 0x61A4, 0xBCAC, 0x6194,
+	0xBCAD, 0x61AE, 0xBCAE, 0x622E, 0xBCAF, 0x6469, 0xBCB0, 0x646F,
+	0xBCB1, 0x6479, 0xBCB2, 0x649E, 0xBCB3, 0x64B2, 0xBCB4, 0x6488,
+	0xBCB5, 0x6490, 0xBCB6, 0x64B0, 0xBCB7, 0x64A5, 0xBCB8, 0x6493,
+	0xBCB9, 0x6495, 0xBCBA, 0x64A9, 0xBCBB, 0x6492, 0xBCBC, 0x64AE,
+	0xBCBD, 0x64AD, 0xBCBE, 0x64AB, 0xBCBF, 0x649A, 0xBCC0, 0x64AC,
+	0xBCC1, 0x6499, 0xBCC2, 0x64A2, 0xBCC3, 0x64B3, 0xBCC4, 0x6575,
+	0xBCC5, 0x6577, 0xBCC6, 0x6578, 0xBCC7, 0x66AE, 0xBCC8, 0x66AB,
+	0xBCC9, 0x66B4, 0xBCCA, 0x66B1, 0xBCCB, 0x6A23, 0xBCCC, 0x6A1F,
+	0xBCCD, 0x69E8, 0xBCCE, 0x6A01, 0xBCCF, 0x6A1E, 0xBCD0, 0x6A19,
+	0xBCD1, 0x69FD, 0xBCD2, 0x6A21, 0xBCD3, 0x6A13, 0xBCD4, 0x6A0A,
+	0xBCD5, 0x69F3, 0xBCD6, 0x6A02, 0xBCD7, 0x6A05, 0xBCD8, 0x69ED,
+	0xBCD9, 0x6A11, 0xBCDA, 0x6B50, 0xBCDB, 0x6B4E, 0xBCDC, 0x6BA4,
+	0xBCDD, 0x6BC5, 0xBCDE, 0x6BC6, 0xBCDF, 0x6F3F, 0xBCE0, 0x6F7C,
+	0xBCE1, 0x6F84, 0xBCE2, 0x6F51, 0xBCE3, 0x6F66, 0xBCE4, 0x6F54,
+	0xBCE5, 0x6F86, 0xBCE6, 0x6F6D, 0xBCE7, 0x6F5B, 0xBCE8, 0x6F78,
+	0xBCE9, 0x6F6E, 0xBCEA, 0x6F8E, 0xBCEB, 0x6F7A, 0xBCEC, 0x6F70,
+	0xBCED, 0x6F64, 0xBCEE, 0x6F97, 0xBCEF, 0x6F58, 0xBCF0, 0x6ED5,
+	0xBCF1, 0x6F6F, 0xBCF2, 0x6F60, 0xBCF3, 0x6F5F, 0xBCF4, 0x719F,
+	0xBCF5, 0x71AC, 0xBCF6, 0x71B1, 0xBCF7, 0x71A8, 0xBCF8, 0x7256,
+	0xBCF9, 0x729B, 0xBCFA, 0x734E, 0xBCFB, 0x7357, 0xBCFC, 0x7469,
+	0xBCFD, 0x748B, 0xBCFE, 0x7483, 0xBD40, 0x747E, 0xBD41, 0x7480,
+	0xBD42, 0x757F, 0xBD43, 0x7620, 0xBD44, 0x7629, 0xBD45, 0x761F,
+	0xBD46, 0x7624, 0xBD47, 0x7626, 0xBD48, 0x7621, 0xBD49, 0x7622,
+	0xBD4A, 0x769A, 0xBD4B, 0x76BA, 0xBD4C, 0x76E4, 0xBD4D, 0x778E,
+	0xBD4E, 0x7787, 0xBD4F, 0x778C, 0xBD50, 0x7791, 0xBD51, 0x778B,
+	0xBD52, 0x78CB, 0xBD53, 0x78C5, 0xBD54, 0x78BA, 0xBD55, 0x78CA,
+	0xBD56, 0x78BE, 0xBD57, 0x78D5, 0xBD58, 0x78BC, 0xBD59, 0x78D0,
+	0xBD5A, 0x7A3F, 0xBD5B, 0x7A3C, 0xBD5C, 0x7A40, 0xBD5D, 0x7A3D,
+	0xBD5E, 0x7A37, 0xBD5F, 0x7A3B, 0xBD60, 0x7AAF, 0xBD61, 0x7AAE,
+	0xBD62, 0x7BAD, 0xBD63, 0x7BB1, 0xBD64, 0x7BC4, 0xBD65, 0x7BB4,
+	0xBD66, 0x7BC6, 0xBD67, 0x7BC7, 0xBD68, 0x7BC1, 0xBD69, 0x7BA0,
+	0xBD6A, 0x7BCC, 0xBD6B, 0x7CCA, 0xBD6C, 0x7DE0, 0xBD6D, 0x7DF4,
+	0xBD6E, 0x7DEF, 0xBD6F, 0x7DFB, 0xBD70, 0x7DD8, 0xBD71, 0x7DEC,
+	0xBD72, 0x7DDD, 0xBD73, 0x7DE8, 0xBD74, 0x7DE3, 0xBD75, 0x7DDA,
+	0xBD76, 0x7DDE, 0xBD77, 0x7DE9, 0xBD78, 0x7D9E, 0xBD79, 0x7DD9,
+	0xBD7A, 0x7DF2, 0xBD7B, 0x7DF9, 0xBD7C, 0x7F75, 0xBD7D, 0x7F77,
+	0xBD7E, 0x7FAF, 0xBDA1, 0x7FE9, 0xBDA2, 0x8026, 0xBDA3, 0x819B,
+	0xBDA4, 0x819C, 0xBDA5, 0x819D, 0xBDA6, 0x81A0, 0xBDA7, 0x819A,
+	0xBDA8, 0x8198, 0xBDA9, 0x8517, 0xBDAA, 0x853D, 0xBDAB, 0x851A,
+	0xBDAC, 0x84EE, 0xBDAD, 0x852C, 0xBDAE, 0x852D, 0xBDAF, 0x8513,
+	0xBDB0, 0x8511, 0xBDB1, 0x8523, 0xBDB2, 0x8521, 0xBDB3, 0x8514,
+	0xBDB4, 0x84EC, 0xBDB5, 0x8525, 0xBDB6, 0x84FF, 0xBDB7, 0x8506,
+	0xBDB8, 0x8782, 0xBDB9, 0x8774, 0xBDBA, 0x8776, 0xBDBB, 0x8760,
+	0xBDBC, 0x8766, 0xBDBD, 0x8778, 0xBDBE, 0x8768, 0xBDBF, 0x8759,
+	0xBDC0, 0x8757, 0xBDC1, 0x874C, 0xBDC2, 0x8753, 0xBDC3, 0x885B,
+	0xBDC4, 0x885D, 0xBDC5, 0x8910, 0xBDC6, 0x8907, 0xBDC7, 0x8912,
+	0xBDC8, 0x8913, 0xBDC9, 0x8915, 0xBDCA, 0x890A, 0xBDCB, 0x8ABC,
+	0xBDCC, 0x8AD2, 0xBDCD, 0x8AC7, 0xBDCE, 0x8AC4, 0xBDCF, 0x8A95,
+	0xBDD0, 0x8ACB, 0xBDD1, 0x8AF8, 0xBDD2, 0x8AB2, 0xBDD3, 0x8AC9,
+	0xBDD4, 0x8AC2, 0xBDD5, 0x8ABF, 0xBDD6, 0x8AB0, 0xBDD7, 0x8AD6,
+	0xBDD8, 0x8ACD, 0xBDD9, 0x8AB6, 0xBDDA, 0x8AB9, 0xBDDB, 0x8ADB,
+	0xBDDC, 0x8C4C, 0xBDDD, 0x8C4E, 0xBDDE, 0x8C6C, 0xBDDF, 0x8CE0,
+	0xBDE0, 0x8CDE, 0xBDE1, 0x8CE6, 0xBDE2, 0x8CE4, 0xBDE3, 0x8CEC,
+	0xBDE4, 0x8CED, 0xBDE5, 0x8CE2, 0xBDE6, 0x8CE3, 0xBDE7, 0x8CDC,
+	0xBDE8, 0x8CEA, 0xBDE9, 0x8CE1, 0xBDEA, 0x8D6D, 0xBDEB, 0x8D9F,
+	0xBDEC, 0x8DA3, 0xBDED, 0x8E2B, 0xBDEE, 0x8E10, 0xBDEF, 0x8E1D,
+	0xBDF0, 0x8E22, 0xBDF1, 0x8E0F, 0xBDF2, 0x8E29, 0xBDF3, 0x8E1F,
+	0xBDF4, 0x8E21, 0xBDF5, 0x8E1E, 0xBDF6, 0x8EBA, 0xBDF7, 0x8F1D,
+	0xBDF8, 0x8F1B, 0xBDF9, 0x8F1F, 0xBDFA, 0x8F29, 0xBDFB, 0x8F26,
+	0xBDFC, 0x8F2A, 0xBDFD, 0x8F1C, 0xBDFE, 0x8F1E, 0xBE40, 0x8F25,
+	0xBE41, 0x9069, 0xBE42, 0x906E, 0xBE43, 0x9068, 0xBE44, 0x906D,
+	0xBE45, 0x9077, 0xBE46, 0x9130, 0xBE47, 0x912D, 0xBE48, 0x9127,
+	0xBE49, 0x9131, 0xBE4A, 0x9187, 0xBE4B, 0x9189, 0xBE4C, 0x918B,
+	0xBE4D, 0x9183, 0xBE4E, 0x92C5, 0xBE4F, 0x92BB, 0xBE50, 0x92B7,
+	0xBE51, 0x92EA, 0xBE52, 0x92AC, 0xBE53, 0x92E4, 0xBE54, 0x92C1,
+	0xBE55, 0x92B3, 0xBE56, 0x92BC, 0xBE57, 0x92D2, 0xBE58, 0x92C7,
+	0xBE59, 0x92F0, 0xBE5A, 0x92B2, 0xBE5B, 0x95AD, 0xBE5C, 0x95B1,
+	0xBE5D, 0x9704, 0xBE5E, 0x9706, 0xBE5F, 0x9707, 0xBE60, 0x9709,
+	0xBE61, 0x9760, 0xBE62, 0x978D, 0xBE63, 0x978B, 0xBE64, 0x978F,
+	0xBE65, 0x9821, 0xBE66, 0x982B, 0xBE67, 0x981C, 0xBE68, 0x98B3,
+	0xBE69, 0x990A, 0xBE6A, 0x9913, 0xBE6B, 0x9912, 0xBE6C, 0x9918,
+	0xBE6D, 0x99DD, 0xBE6E, 0x99D0, 0xBE6F, 0x99DF, 0xBE70, 0x99DB,
+	0xBE71, 0x99D1, 0xBE72, 0x99D5, 0xBE73, 0x99D2, 0xBE74, 0x99D9,
+	0xBE75, 0x9AB7, 0xBE76, 0x9AEE, 0xBE77, 0x9AEF, 0xBE78, 0x9B27,
+	0xBE79, 0x9B45, 0xBE7A, 0x9B44, 0xBE7B, 0x9B77, 0xBE7C, 0x9B6F,
+	0xBE7D, 0x9D06, 0xBE7E, 0x9D09, 0xBEA1, 0x9D03, 0xBEA2, 0x9EA9,
+	0xBEA3, 0x9EBE, 0xBEA4, 0x9ECE, 0xBEA5, 0x58A8, 0xBEA6, 0x9F52,
+	0xBEA7, 0x5112, 0xBEA8, 0x5118, 0xBEA9, 0x5114, 0xBEAA, 0x5110,
+	0xBEAB, 0x5115, 0xBEAC, 0x5180, 0xBEAD, 0x51AA, 0xBEAE, 0x51DD,
+	0xBEAF, 0x5291, 0xBEB0, 0x5293, 0xBEB1, 0x52F3, 0xBEB2, 0x5659,
+	0xBEB3, 0x566B, 0xBEB4, 0x5679, 0xBEB5, 0x5669, 0xBEB6, 0x5664,
+	0xBEB7, 0x5678, 0xBEB8, 0x566A, 0xBEB9, 0x5668, 0xBEBA, 0x5665,
+	0xBEBB, 0x5671, 0xBEBC, 0x566F, 0xBEBD, 0x566C, 0xBEBE, 0x5662,
+	0xBEBF, 0x5676, 0xBEC0, 0x58C1, 0xBEC1, 0x58BE, 0xBEC2, 0x58C7,
+	0xBEC3, 0x58C5, 0xBEC4, 0x596E, 0xBEC5, 0x5B1D, 0xBEC6, 0x5B34,
+	0xBEC7, 0x5B78, 0xBEC8, 0x5BF0, 0xBEC9, 0x5C0E, 0xBECA, 0x5F4A,
+	0xBECB, 0x61B2, 0xBECC, 0x6191, 0xBECD, 0x61A9, 0xBECE, 0x618A,
+	0xBECF, 0x61CD, 0xBED0, 0x61B6, 0xBED1, 0x61BE, 0xBED2, 0x61CA,
+	0xBED3, 0x61C8, 0xBED4, 0x6230, 0xBED5, 0x64C5, 0xBED6, 0x64C1,
+	0xBED7, 0x64CB, 0xBED8, 0x64BB, 0xBED9, 0x64BC, 0xBEDA, 0x64DA,
+	0xBEDB, 0x64C4, 0xBEDC, 0x64C7, 0xBEDD, 0x64C2, 0xBEDE, 0x64CD,
+	0xBEDF, 0x64BF, 0xBEE0, 0x64D2, 0xBEE1, 0x64D4, 0xBEE2, 0x64BE,
+	0xBEE3, 0x6574, 0xBEE4, 0x66C6, 0xBEE5, 0x66C9, 0xBEE6, 0x66B9,
+	0xBEE7, 0x66C4, 0xBEE8, 0x66C7, 0xBEE9, 0x66B8, 0xBEEA, 0x6A3D,
+	0xBEEB, 0x6A38, 0xBEEC, 0x6A3A, 0xBEED, 0x6A59, 0xBEEE, 0x6A6B,
+	0xBEEF, 0x6A58, 0xBEF0, 0x6A39, 0xBEF1, 0x6A44, 0xBEF2, 0x6A62,
+	0xBEF3, 0x6A61, 0xBEF4, 0x6A4B, 0xBEF5, 0x6A47, 0xBEF6, 0x6A35,
+	0xBEF7, 0x6A5F, 0xBEF8, 0x6A48, 0xBEF9, 0x6B59, 0xBEFA, 0x6B77,
+	0xBEFB, 0x6C05, 0xBEFC, 0x6FC2, 0xBEFD, 0x6FB1, 0xBEFE, 0x6FA1,
+	0xBF40, 0x6FC3, 0xBF41, 0x6FA4, 0xBF42, 0x6FC1, 0xBF43, 0x6FA7,
+	0xBF44, 0x6FB3, 0xBF45, 0x6FC0, 0xBF46, 0x6FB9, 0xBF47, 0x6FB6,
+	0xBF48, 0x6FA6, 0xBF49, 0x6FA0, 0xBF4A, 0x6FB4, 0xBF4B, 0x71BE,
+	0xBF4C, 0x71C9, 0xBF4D, 0x71D0, 0xBF4E, 0x71D2, 0xBF4F, 0x71C8,
+	0xBF50, 0x71D5, 0xBF51, 0x71B9, 0xBF52, 0x71CE, 0xBF53, 0x71D9,
+	0xBF54, 0x71DC, 0xBF55, 0x71C3, 0xBF56, 0x71C4, 0xBF57, 0x7368,
+	0xBF58, 0x749C, 0xBF59, 0x74A3, 0xBF5A, 0x7498, 0xBF5B, 0x749F,
+	0xBF5C, 0x749E, 0xBF5D, 0x74E2, 0xBF5E, 0x750C, 0xBF5F, 0x750D,
+	0xBF60, 0x7634, 0xBF61, 0x7638, 0xBF62, 0x763A, 0xBF63, 0x76E7,
+	0xBF64, 0x76E5, 0xBF65, 0x77A0, 0xBF66, 0x779E, 0xBF67, 0x779F,
+	0xBF68, 0x77A5, 0xBF69, 0x78E8, 0xBF6A, 0x78DA, 0xBF6B, 0x78EC,
+	0xBF6C, 0x78E7, 0xBF6D, 0x79A6, 0xBF6E, 0x7A4D, 0xBF6F, 0x7A4E,
+	0xBF70, 0x7A46, 0xBF71, 0x7A4C, 0xBF72, 0x7A4B, 0xBF73, 0x7ABA,
+	0xBF74, 0x7BD9, 0xBF75, 0x7C11, 0xBF76, 0x7BC9, 0xBF77, 0x7BE4,
+	0xBF78, 0x7BDB, 0xBF79, 0x7BE1, 0xBF7A, 0x7BE9, 0xBF7B, 0x7BE6,
+	0xBF7C, 0x7CD5, 0xBF7D, 0x7CD6, 0xBF7E, 0x7E0A, 0xBFA1, 0x7E11,
+	0xBFA2, 0x7E08, 0xBFA3, 0x7E1B, 0xBFA4, 0x7E23, 0xBFA5, 0x7E1E,
+	0xBFA6, 0x7E1D, 0xBFA7, 0x7E09, 0xBFA8, 0x7E10, 0xBFA9, 0x7F79,
+	0xBFAA, 0x7FB2, 0xBFAB, 0x7FF0, 0xBFAC, 0x7FF1, 0xBFAD, 0x7FEE,
+	0xBFAE, 0x8028, 0xBFAF, 0x81B3, 0xBFB0, 0x81A9, 0xBFB1, 0x81A8,
+	0xBFB2, 0x81FB, 0xBFB3, 0x8208, 0xBFB4, 0x8258, 0xBFB5, 0x8259,
+	0xBFB6, 0x854A, 0xBFB7, 0x8559, 0xBFB8, 0x8548, 0xBFB9, 0x8568,
+	0xBFBA, 0x8569, 0xBFBB, 0x8543, 0xBFBC, 0x8549, 0xBFBD, 0x856D,
+	0xBFBE, 0x856A, 0xBFBF, 0x855E, 0xBFC0, 0x8783, 0xBFC1, 0x879F,
+	0xBFC2, 0x879E, 0xBFC3, 0x87A2, 0xBFC4, 0x878D, 0xBFC5, 0x8861,
+	0xBFC6, 0x892A, 0xBFC7, 0x8932, 0xBFC8, 0x8925, 0xBFC9, 0x892B,
+	0xBFCA, 0x8921, 0xBFCB, 0x89AA, 0xBFCC, 0x89A6, 0xBFCD, 0x8AE6,
+	0xBFCE, 0x8AFA, 0xBFCF, 0x8AEB, 0xBFD0, 0x8AF1, 0xBFD1, 0x8B00,
+	0xBFD2, 0x8ADC, 0xBFD3, 0x8AE7, 0xBFD4, 0x8AEE, 0xBFD5, 0x8AFE,
+	0xBFD6, 0x8B01, 0xBFD7, 0x8B02, 0xBFD8, 0x8AF7, 0xBFD9, 0x8AED,
+	0xBFDA, 0x8AF3, 0xBFDB, 0x8AF6, 0xBFDC, 0x8AFC, 0xBFDD, 0x8C6B,
+	0xBFDE, 0x8C6D, 0xBFDF, 0x8C93, 0xBFE0, 0x8CF4, 0xBFE1, 0x8E44,
+	0xBFE2, 0x8E31, 0xBFE3, 0x8E34, 0xBFE4, 0x8E42, 0xBFE5, 0x8E39,
+	0xBFE6, 0x8E35, 0xBFE7, 0x8F3B, 0xBFE8, 0x8F2F, 0xBFE9, 0x8F38,
+	0xBFEA, 0x8F33, 0xBFEB, 0x8FA8, 0xBFEC, 0x8FA6, 0xBFED, 0x9075,
+	0xBFEE, 0x9074, 0xBFEF, 0x9078, 0xBFF0, 0x9072, 0xBFF1, 0x907C,
+	0xBFF2, 0x907A, 0xBFF3, 0x9134, 0xBFF4, 0x9192, 0xBFF5, 0x9320,
+	0xBFF6, 0x9336, 0xBFF7, 0x92F8, 0xBFF8, 0x9333, 0xBFF9, 0x932F,
+	0xBFFA, 0x9322, 0xBFFB, 0x92FC, 0xBFFC, 0x932B, 0xBFFD, 0x9304,
+	0xBFFE, 0x931A, 0xC040, 0x9310, 0xC041, 0x9326, 0xC042, 0x9321,
+	0xC043, 0x9315, 0xC044, 0x932E, 0xC045, 0x9319, 0xC046, 0x95BB,
+	0xC047, 0x96A7, 0xC048, 0x96A8, 0xC049, 0x96AA, 0xC04A, 0x96D5,
+	0xC04B, 0x970E, 0xC04C, 0x9711, 0xC04D, 0x9716, 0xC04E, 0x970D,
+	0xC04F, 0x9713, 0xC050, 0x970F, 0xC051, 0x975B, 0xC052, 0x975C,
+	0xC053, 0x9766, 0xC054, 0x9798, 0xC055, 0x9830, 0xC056, 0x9838,
+	0xC057, 0x983B, 0xC058, 0x9837, 0xC059, 0x982D, 0xC05A, 0x9839,
+	0xC05B, 0x9824, 0xC05C, 0x9910, 0xC05D, 0x9928, 0xC05E, 0x991E,
+	0xC05F, 0x991B, 0xC060, 0x9921, 0xC061, 0x991A, 0xC062, 0x99ED,
+	0xC063, 0x99E2, 0xC064, 0x99F1, 0xC065, 0x9AB8, 0xC066, 0x9ABC,
+	0xC067, 0x9AFB, 0xC068, 0x9AED, 0xC069, 0x9B28, 0xC06A, 0x9B91,
+	0xC06B, 0x9D15, 0xC06C, 0x9D23, 0xC06D, 0x9D26, 0xC06E, 0x9D28,
+	0xC06F, 0x9D12, 0xC070, 0x9D1B, 0xC071, 0x9ED8, 0xC072, 0x9ED4,
+	0xC073, 0x9F8D, 0xC074, 0x9F9C, 0xC075, 0x512A, 0xC076, 0x511F,
+	0xC077, 0x5121, 0xC078, 0x5132, 0xC079, 0x52F5, 0xC07A, 0x568E,
+	0xC07B, 0x5680, 0xC07C, 0x5690, 0xC07D, 0x5685, 0xC07E, 0x5687,
+	0xC0A1, 0x568F, 0xC0A2, 0x58D5, 0xC0A3, 0x58D3, 0xC0A4, 0x58D1,
+	0xC0A5, 0x58CE, 0xC0A6, 0x5B30, 0xC0A7, 0x5B2A, 0xC0A8, 0x5B24,
+	0xC0A9, 0x5B7A, 0xC0AA, 0x5C37, 0xC0AB, 0x5C68, 0xC0AC, 0x5DBC,
+	0xC0AD, 0x5DBA, 0xC0AE, 0x5DBD, 0xC0AF, 0x5DB8, 0xC0B0, 0x5E6B,
+	0xC0B1, 0x5F4C, 0xC0B2, 0x5FBD, 0xC0B3, 0x61C9, 0xC0B4, 0x61C2,
+	0xC0B5, 0x61C7, 0xC0B6, 0x61E6, 0xC0B7, 0x61CB, 0xC0B8, 0x6232,
+	0xC0B9, 0x6234, 0xC0BA, 0x64CE, 0xC0BB, 0x64CA, 0xC0BC, 0x64D8,
+	0xC0BD, 0x64E0, 0xC0BE, 0x64F0, 0xC0BF, 0x64E6, 0xC0C0, 0x64EC,
+	0xC0C1, 0x64F1, 0xC0C2, 0x64E2, 0xC0C3, 0x64ED, 0xC0C4, 0x6582,
+	0xC0C5, 0x6583, 0xC0C6, 0x66D9, 0xC0C7, 0x66D6, 0xC0C8, 0x6A80,
+	0xC0C9, 0x6A94, 0xC0CA, 0x6A84, 0xC0CB, 0x6AA2, 0xC0CC, 0x6A9C,
+	0xC0CD, 0x6ADB, 0xC0CE, 0x6AA3, 0xC0CF, 0x6A7E, 0xC0D0, 0x6A97,
+	0xC0D1, 0x6A90, 0xC0D2, 0x6AA0, 0xC0D3, 0x6B5C, 0xC0D4, 0x6BAE,
+	0xC0D5, 0x6BDA, 0xC0D6, 0x6C08, 0xC0D7, 0x6FD8, 0xC0D8, 0x6FF1,
+	0xC0D9, 0x6FDF, 0xC0DA, 0x6FE0, 0xC0DB, 0x6FDB, 0xC0DC, 0x6FE4,
+	0xC0DD, 0x6FEB, 0xC0DE, 0x6FEF, 0xC0DF, 0x6F80, 0xC0E0, 0x6FEC,
+	0xC0E1, 0x6FE1, 0xC0E2, 0x6FE9, 0xC0E3, 0x6FD5, 0xC0E4, 0x6FEE,
+	0xC0E5, 0x6FF0, 0xC0E6, 0x71E7, 0xC0E7, 0x71DF, 0xC0E8, 0x71EE,
+	0xC0E9, 0x71E6, 0xC0EA, 0x71E5, 0xC0EB, 0x71ED, 0xC0EC, 0x71EC,
+	0xC0ED, 0x71F4, 0xC0EE, 0x71E0, 0xC0EF, 0x7235, 0xC0F0, 0x7246,
+	0xC0F1, 0x7370, 0xC0F2, 0x7372, 0xC0F3, 0x74A9, 0xC0F4, 0x74B0,
+	0xC0F5, 0x74A6, 0xC0F6, 0x74A8, 0xC0F7, 0x7646, 0xC0F8, 0x7642,
+	0xC0F9, 0x764C, 0xC0FA, 0x76EA, 0xC0FB, 0x77B3, 0xC0FC, 0x77AA,
+	0xC0FD, 0x77B0, 0xC0FE, 0x77AC, 0xC140, 0x77A7, 0xC141, 0x77AD,
+	0xC142, 0x77EF, 0xC143, 0x78F7, 0xC144, 0x78FA, 0xC145, 0x78F4,
+	0xC146, 0x78EF, 0xC147, 0x7901, 0xC148, 0x79A7, 0xC149, 0x79AA,
+	0xC14A, 0x7A57, 0xC14B, 0x7ABF, 0xC14C, 0x7C07, 0xC14D, 0x7C0D,
+	0xC14E, 0x7BFE, 0xC14F, 0x7BF7, 0xC150, 0x7C0C, 0xC151, 0x7BE0,
+	0xC152, 0x7CE0, 0xC153, 0x7CDC, 0xC154, 0x7CDE, 0xC155, 0x7CE2,
+	0xC156, 0x7CDF, 0xC157, 0x7CD9, 0xC158, 0x7CDD, 0xC159, 0x7E2E,
+	0xC15A, 0x7E3E, 0xC15B, 0x7E46, 0xC15C, 0x7E37, 0xC15D, 0x7E32,
+	0xC15E, 0x7E43, 0xC15F, 0x7E2B, 0xC160, 0x7E3D, 0xC161, 0x7E31,
+	0xC162, 0x7E45, 0xC163, 0x7E41, 0xC164, 0x7E34, 0xC165, 0x7E39,
+	0xC166, 0x7E48, 0xC167, 0x7E35, 0xC168, 0x7E3F, 0xC169, 0x7E2F,
+	0xC16A, 0x7F44, 0xC16B, 0x7FF3, 0xC16C, 0x7FFC, 0xC16D, 0x8071,
+	0xC16E, 0x8072, 0xC16F, 0x8070, 0xC170, 0x806F, 0xC171, 0x8073,
+	0xC172, 0x81C6, 0xC173, 0x81C3, 0xC174, 0x81BA, 0xC175, 0x81C2,
+	0xC176, 0x81C0, 0xC177, 0x81BF, 0xC178, 0x81BD, 0xC179, 0x81C9,
+	0xC17A, 0x81BE, 0xC17B, 0x81E8, 0xC17C, 0x8209, 0xC17D, 0x8271,
+	0xC17E, 0x85AA, 0xC1A1, 0x8584, 0xC1A2, 0x857E, 0xC1A3, 0x859C,
+	0xC1A4, 0x8591, 0xC1A5, 0x8594, 0xC1A6, 0x85AF, 0xC1A7, 0x859B,
+	0xC1A8, 0x8587, 0xC1A9, 0x85A8, 0xC1AA, 0x858A, 0xC1AB, 0x8667,
+	0xC1AC, 0x87C0, 0xC1AD, 0x87D1, 0xC1AE, 0x87B3, 0xC1AF, 0x87D2,
+	0xC1B0, 0x87C6, 0xC1B1, 0x87AB, 0xC1B2, 0x87BB, 0xC1B3, 0x87BA,
+	0xC1B4, 0x87C8, 0xC1B5, 0x87CB, 0xC1B6, 0x893B, 0xC1B7, 0x8936,
+	0xC1B8, 0x8944, 0xC1B9, 0x8938, 0xC1BA, 0x893D, 0xC1BB, 0x89AC,
+	0xC1BC, 0x8B0E, 0xC1BD, 0x8B17, 0xC1BE, 0x8B19, 0xC1BF, 0x8B1B,
+	0xC1C0, 0x8B0A, 0xC1C1, 0x8B20, 0xC1C2, 0x8B1D, 0xC1C3, 0x8B04,
+	0xC1C4, 0x8B10, 0xC1C5, 0x8C41, 0xC1C6, 0x8C3F, 0xC1C7, 0x8C73,
+	0xC1C8, 0x8CFA, 0xC1C9, 0x8CFD, 0xC1CA, 0x8CFC, 0xC1CB, 0x8CF8,
+	0xC1CC, 0x8CFB, 0xC1CD, 0x8DA8, 0xC1CE, 0x8E49, 0xC1CF, 0x8E4B,
+	0xC1D0, 0x8E48, 0xC1D1, 0x8E4A, 0xC1D2, 0x8F44, 0xC1D3, 0x8F3E,
+	0xC1D4, 0x8F42, 0xC1D5, 0x8F45, 0xC1D6, 0x8F3F, 0xC1D7, 0x907F,
+	0xC1D8, 0x907D, 0xC1D9, 0x9084, 0xC1DA, 0x9081, 0xC1DB, 0x9082,
+	0xC1DC, 0x9080, 0xC1DD, 0x9139, 0xC1DE, 0x91A3, 0xC1DF, 0x919E,
+	0xC1E0, 0x919C, 0xC1E1, 0x934D, 0xC1E2, 0x9382, 0xC1E3, 0x9328,
+	0xC1E4, 0x9375, 0xC1E5, 0x934A, 0xC1E6, 0x9365, 0xC1E7, 0x934B,
+	0xC1E8, 0x9318, 0xC1E9, 0x937E, 0xC1EA, 0x936C, 0xC1EB, 0x935B,
+	0xC1EC, 0x9370, 0xC1ED, 0x935A, 0xC1EE, 0x9354, 0xC1EF, 0x95CA,
+	0xC1F0, 0x95CB, 0xC1F1, 0x95CC, 0xC1F2, 0x95C8, 0xC1F3, 0x95C6,
+	0xC1F4, 0x96B1, 0xC1F5, 0x96B8, 0xC1F6, 0x96D6, 0xC1F7, 0x971C,
+	0xC1F8, 0x971E, 0xC1F9, 0x97A0, 0xC1FA, 0x97D3, 0xC1FB, 0x9846,
+	0xC1FC, 0x98B6, 0xC1FD, 0x9935, 0xC1FE, 0x9A01, 0xC240, 0x99FF,
+	0xC241, 0x9BAE, 0xC242, 0x9BAB, 0xC243, 0x9BAA, 0xC244, 0x9BAD,
+	0xC245, 0x9D3B, 0xC246, 0x9D3F, 0xC247, 0x9E8B, 0xC248, 0x9ECF,
+	0xC249, 0x9EDE, 0xC24A, 0x9EDC, 0xC24B, 0x9EDD, 0xC24C, 0x9EDB,
+	0xC24D, 0x9F3E, 0xC24E, 0x9F4B, 0xC24F, 0x53E2, 0xC250, 0x5695,
+	0xC251, 0x56AE, 0xC252, 0x58D9, 0xC253, 0x58D8, 0xC254, 0x5B38,
+	0xC255, 0x5F5D, 0xC256, 0x61E3, 0xC257, 0x6233, 0xC258, 0x64F4,
+	0xC259, 0x64F2, 0xC25A, 0x64FE, 0xC25B, 0x6506, 0xC25C, 0x64FA,
+	0xC25D, 0x64FB, 0xC25E, 0x64F7, 0xC25F, 0x65B7, 0xC260, 0x66DC,
+	0xC261, 0x6726, 0xC262, 0x6AB3, 0xC263, 0x6AAC, 0xC264, 0x6AC3,
+	0xC265, 0x6ABB, 0xC266, 0x6AB8, 0xC267, 0x6AC2, 0xC268, 0x6AAE,
+	0xC269, 0x6AAF, 0xC26A, 0x6B5F, 0xC26B, 0x6B78, 0xC26C, 0x6BAF,
+	0xC26D, 0x7009, 0xC26E, 0x700B, 0xC26F, 0x6FFE, 0xC270, 0x7006,
+	0xC271, 0x6FFA, 0xC272, 0x7011, 0xC273, 0x700F, 0xC274, 0x71FB,
+	0xC275, 0x71FC, 0xC276, 0x71FE, 0xC277, 0x71F8, 0xC278, 0x7377,
+	0xC279, 0x7375, 0xC27A, 0x74A7, 0xC27B, 0x74BF, 0xC27C, 0x7515,
+	0xC27D, 0x7656, 0xC27E, 0x7658, 0xC2A1, 0x7652, 0xC2A2, 0x77BD,
+	0xC2A3, 0x77BF, 0xC2A4, 0x77BB, 0xC2A5, 0x77BC, 0xC2A6, 0x790E,
+	0xC2A7, 0x79AE, 0xC2A8, 0x7A61, 0xC2A9, 0x7A62, 0xC2AA, 0x7A60,
+	0xC2AB, 0x7AC4, 0xC2AC, 0x7AC5, 0xC2AD, 0x7C2B, 0xC2AE, 0x7C27,
+	0xC2AF, 0x7C2A, 0xC2B0, 0x7C1E, 0xC2B1, 0x7C23, 0xC2B2, 0x7C21,
+	0xC2B3, 0x7CE7, 0xC2B4, 0x7E54, 0xC2B5, 0x7E55, 0xC2B6, 0x7E5E,
+	0xC2B7, 0x7E5A, 0xC2B8, 0x7E61, 0xC2B9, 0x7E52, 0xC2BA, 0x7E59,
+	0xC2BB, 0x7F48, 0xC2BC, 0x7FF9, 0xC2BD, 0x7FFB, 0xC2BE, 0x8077,
+	0xC2BF, 0x8076, 0xC2C0, 0x81CD, 0xC2C1, 0x81CF, 0xC2C2, 0x820A,
+	0xC2C3, 0x85CF, 0xC2C4, 0x85A9, 0xC2C5, 0x85CD, 0xC2C6, 0x85D0,
+	0xC2C7, 0x85C9, 0xC2C8, 0x85B0, 0xC2C9, 0x85BA, 0xC2CA, 0x85B9,
+	0xC2CB, 0x85A6, 0xC2CC, 0x87EF, 0xC2CD, 0x87EC, 0xC2CE, 0x87F2,
+	0xC2CF, 0x87E0, 0xC2D0, 0x8986, 0xC2D1, 0x89B2, 0xC2D2, 0x89F4,
+	0xC2D3, 0x8B28, 0xC2D4, 0x8B39, 0xC2D5, 0x8B2C, 0xC2D6, 0x8B2B,
+	0xC2D7, 0x8C50, 0xC2D8, 0x8D05, 0xC2D9, 0x8E59, 0xC2DA, 0x8E63,
+	0xC2DB, 0x8E66, 0xC2DC, 0x8E64, 0xC2DD, 0x8E5F, 0xC2DE, 0x8E55,
+	0xC2DF, 0x8EC0, 0xC2E0, 0x8F49, 0xC2E1, 0x8F4D, 0xC2E2, 0x9087,
+	0xC2E3, 0x9083, 0xC2E4, 0x9088, 0xC2E5, 0x91AB, 0xC2E6, 0x91AC,
+	0xC2E7, 0x91D0, 0xC2E8, 0x9394, 0xC2E9, 0x938A, 0xC2EA, 0x9396,
+	0xC2EB, 0x93A2, 0xC2EC, 0x93B3, 0xC2ED, 0x93AE, 0xC2EE, 0x93AC,
+	0xC2EF, 0x93B0, 0xC2F0, 0x9398, 0xC2F1, 0x939A, 0xC2F2, 0x9397,
+	0xC2F3, 0x95D4, 0xC2F4, 0x95D6, 0xC2F5, 0x95D0, 0xC2F6, 0x95D5,
+	0xC2F7, 0x96E2, 0xC2F8, 0x96DC, 0xC2F9, 0x96D9, 0xC2FA, 0x96DB,
+	0xC2FB, 0x96DE, 0xC2FC, 0x9724, 0xC2FD, 0x97A3, 0xC2FE, 0x97A6,
+	0xC340, 0x97AD, 0xC341, 0x97F9, 0xC342, 0x984D, 0xC343, 0x984F,
+	0xC344, 0x984C, 0xC345, 0x984E, 0xC346, 0x9853, 0xC347, 0x98BA,
+	0xC348, 0x993E, 0xC349, 0x993F, 0xC34A, 0x993D, 0xC34B, 0x992E,
+	0xC34C, 0x99A5, 0xC34D, 0x9A0E, 0xC34E, 0x9AC1, 0xC34F, 0x9B03,
+	0xC350, 0x9B06, 0xC351, 0x9B4F, 0xC352, 0x9B4E, 0xC353, 0x9B4D,
+	0xC354, 0x9BCA, 0xC355, 0x9BC9, 0xC356, 0x9BFD, 0xC357, 0x9BC8,
+	0xC358, 0x9BC0, 0xC359, 0x9D51, 0xC35A, 0x9D5D, 0xC35B, 0x9D60,
+	0xC35C, 0x9EE0, 0xC35D, 0x9F15, 0xC35E, 0x9F2C, 0xC35F, 0x5133,
+	0xC360, 0x56A5, 0xC361, 0x58DE, 0xC362, 0x58DF, 0xC363, 0x58E2,
+	0xC364, 0x5BF5, 0xC365, 0x9F90, 0xC366, 0x5EEC, 0xC367, 0x61F2,
+	0xC368, 0x61F7, 0xC369, 0x61F6, 0xC36A, 0x61F5, 0xC36B, 0x6500,
+	0xC36C, 0x650F, 0xC36D, 0x66E0, 0xC36E, 0x66DD, 0xC36F, 0x6AE5,
+	0xC370, 0x6ADD, 0xC371, 0x6ADA, 0xC372, 0x6AD3, 0xC373, 0x701B,
+	0xC374, 0x701F, 0xC375, 0x7028, 0xC376, 0x701A, 0xC377, 0x701D,
+	0xC378, 0x7015, 0xC379, 0x7018, 0xC37A, 0x7206, 0xC37B, 0x720D,
+	0xC37C, 0x7258, 0xC37D, 0x72A2, 0xC37E, 0x7378, 0xC3A1, 0x737A,
+	0xC3A2, 0x74BD, 0xC3A3, 0x74CA, 0xC3A4, 0x74E3, 0xC3A5, 0x7587,
+	0xC3A6, 0x7586, 0xC3A7, 0x765F, 0xC3A8, 0x7661, 0xC3A9, 0x77C7,
+	0xC3AA, 0x7919, 0xC3AB, 0x79B1, 0xC3AC, 0x7A6B, 0xC3AD, 0x7A69,
+	0xC3AE, 0x7C3E, 0xC3AF, 0x7C3F, 0xC3B0, 0x7C38, 0xC3B1, 0x7C3D,
+	0xC3B2, 0x7C37, 0xC3B3, 0x7C40, 0xC3B4, 0x7E6B, 0xC3B5, 0x7E6D,
+	0xC3B6, 0x7E79, 0xC3B7, 0x7E69, 0xC3B8, 0x7E6A, 0xC3B9, 0x7F85,
+	0xC3BA, 0x7E73, 0xC3BB, 0x7FB6, 0xC3BC, 0x7FB9, 0xC3BD, 0x7FB8,
+	0xC3BE, 0x81D8, 0xC3BF, 0x85E9, 0xC3C0, 0x85DD, 0xC3C1, 0x85EA,
+	0xC3C2, 0x85D5, 0xC3C3, 0x85E4, 0xC3C4, 0x85E5, 0xC3C5, 0x85F7,
+	0xC3C6, 0x87FB, 0xC3C7, 0x8805, 0xC3C8, 0x880D, 0xC3C9, 0x87F9,
+	0xC3CA, 0x87FE, 0xC3CB, 0x8960, 0xC3CC, 0x895F, 0xC3CD, 0x8956,
+	0xC3CE, 0x895E, 0xC3CF, 0x8B41, 0xC3D0, 0x8B5C, 0xC3D1, 0x8B58,
+	0xC3D2, 0x8B49, 0xC3D3, 0x8B5A, 0xC3D4, 0x8B4E, 0xC3D5, 0x8B4F,
+	0xC3D6, 0x8B46, 0xC3D7, 0x8B59, 0xC3D8, 0x8D08, 0xC3D9, 0x8D0A,
+	0xC3DA, 0x8E7C, 0xC3DB, 0x8E72, 0xC3DC, 0x8E87, 0xC3DD, 0x8E76,
+	0xC3DE, 0x8E6C, 0xC3DF, 0x8E7A, 0xC3E0, 0x8E74, 0xC3E1, 0x8F54,
+	0xC3E2, 0x8F4E, 0xC3E3, 0x8FAD, 0xC3E4, 0x908A, 0xC3E5, 0x908B,
+	0xC3E6, 0x91B1, 0xC3E7, 0x91AE, 0xC3E8, 0x93E1, 0xC3E9, 0x93D1,
+	0xC3EA, 0x93DF, 0xC3EB, 0x93C3, 0xC3EC, 0x93C8, 0xC3ED, 0x93DC,
+	0xC3EE, 0x93DD, 0xC3EF, 0x93D6, 0xC3F0, 0x93E2, 0xC3F1, 0x93CD,
+	0xC3F2, 0x93D8, 0xC3F3, 0x93E4, 0xC3F4, 0x93D7, 0xC3F5, 0x93E8,
+	0xC3F6, 0x95DC, 0xC3F7, 0x96B4, 0xC3F8, 0x96E3, 0xC3F9, 0x972A,
+	0xC3FA, 0x9727, 0xC3FB, 0x9761, 0xC3FC, 0x97DC, 0xC3FD, 0x97FB,
+	0xC3FE, 0x985E, 0xC440, 0x9858, 0xC441, 0x985B, 0xC442, 0x98BC,
+	0xC443, 0x9945, 0xC444, 0x9949, 0xC445, 0x9A16, 0xC446, 0x9A19,
+	0xC447, 0x9B0D, 0xC448, 0x9BE8, 0xC449, 0x9BE7, 0xC44A, 0x9BD6,
+	0xC44B, 0x9BDB, 0xC44C, 0x9D89, 0xC44D, 0x9D61, 0xC44E, 0x9D72,
+	0xC44F, 0x9D6A, 0xC450, 0x9D6C, 0xC451, 0x9E92, 0xC452, 0x9E97,
+	0xC453, 0x9E93, 0xC454, 0x9EB4, 0xC455, 0x52F8, 0xC456, 0x56A8,
+	0xC457, 0x56B7, 0xC458, 0x56B6, 0xC459, 0x56B4, 0xC45A, 0x56BC,
+	0xC45B, 0x58E4, 0xC45C, 0x5B40, 0xC45D, 0x5B43, 0xC45E, 0x5B7D,
+	0xC45F, 0x5BF6, 0xC460, 0x5DC9, 0xC461, 0x61F8, 0xC462, 0x61FA,
+	0xC463, 0x6518, 0xC464, 0x6514, 0xC465, 0x6519, 0xC466, 0x66E6,
+	0xC467, 0x6727, 0xC468, 0x6AEC, 0xC469, 0x703E, 0xC46A, 0x7030,
+	0xC46B, 0x7032, 0xC46C, 0x7210, 0xC46D, 0x737B, 0xC46E, 0x74CF,
+	0xC46F, 0x7662, 0xC470, 0x7665, 0xC471, 0x7926, 0xC472, 0x792A,
+	0xC473, 0x792C, 0xC474, 0x792B, 0xC475, 0x7AC7, 0xC476, 0x7AF6,
+	0xC477, 0x7C4C, 0xC478, 0x7C43, 0xC479, 0x7C4D, 0xC47A, 0x7CEF,
+	0xC47B, 0x7CF0, 0xC47C, 0x8FAE, 0xC47D, 0x7E7D, 0xC47E, 0x7E7C,
+	0xC4A1, 0x7E82, 0xC4A2, 0x7F4C, 0xC4A3, 0x8000, 0xC4A4, 0x81DA,
+	0xC4A5, 0x8266, 0xC4A6, 0x85FB, 0xC4A7, 0x85F9, 0xC4A8, 0x8611,
+	0xC4A9, 0x85FA, 0xC4AA, 0x8606, 0xC4AB, 0x860B, 0xC4AC, 0x8607,
+	0xC4AD, 0x860A, 0xC4AE, 0x8814, 0xC4AF, 0x8815, 0xC4B0, 0x8964,
+	0xC4B1, 0x89BA, 0xC4B2, 0x89F8, 0xC4B3, 0x8B70, 0xC4B4, 0x8B6C,
+	0xC4B5, 0x8B66, 0xC4B6, 0x8B6F, 0xC4B7, 0x8B5F, 0xC4B8, 0x8B6B,
+	0xC4B9, 0x8D0F, 0xC4BA, 0x8D0D, 0xC4BB, 0x8E89, 0xC4BC, 0x8E81,
+	0xC4BD, 0x8E85, 0xC4BE, 0x8E82, 0xC4BF, 0x91B4, 0xC4C0, 0x91CB,
+	0xC4C1, 0x9418, 0xC4C2, 0x9403, 0xC4C3, 0x93FD, 0xC4C4, 0x95E1,
+	0xC4C5, 0x9730, 0xC4C6, 0x98C4, 0xC4C7, 0x9952, 0xC4C8, 0x9951,
+	0xC4C9, 0x99A8, 0xC4CA, 0x9A2B, 0xC4CB, 0x9A30, 0xC4CC, 0x9A37,
+	0xC4CD, 0x9A35, 0xC4CE, 0x9C13, 0xC4CF, 0x9C0D, 0xC4D0, 0x9E79,
+	0xC4D1, 0x9EB5, 0xC4D2, 0x9EE8, 0xC4D3, 0x9F2F, 0xC4D4, 0x9F5F,
+	0xC4D5, 0x9F63, 0xC4D6, 0x9F61, 0xC4D7, 0x5137, 0xC4D8, 0x5138,
+	0xC4D9, 0x56C1, 0xC4DA, 0x56C0, 0xC4DB, 0x56C2, 0xC4DC, 0x5914,
+	0xC4DD, 0x5C6C, 0xC4DE, 0x5DCD, 0xC4DF, 0x61FC, 0xC4E0, 0x61FE,
+	0xC4E1, 0x651D, 0xC4E2, 0x651C, 0xC4E3, 0x6595, 0xC4E4, 0x66E9,
+	0xC4E5, 0x6AFB, 0xC4E6, 0x6B04, 0xC4E7, 0x6AFA, 0xC4E8, 0x6BB2,
+	0xC4E9, 0x704C, 0xC4EA, 0x721B, 0xC4EB, 0x72A7, 0xC4EC, 0x74D6,
+	0xC4ED, 0x74D4, 0xC4EE, 0x7669, 0xC4EF, 0x77D3, 0xC4F0, 0x7C50,
+	0xC4F1, 0x7E8F, 0xC4F2, 0x7E8C, 0xC4F3, 0x7FBC, 0xC4F4, 0x8617,
+	0xC4F5, 0x862D, 0xC4F6, 0x861A, 0xC4F7, 0x8823, 0xC4F8, 0x8822,
+	0xC4F9, 0x8821, 0xC4FA, 0x881F, 0xC4FB, 0x896A, 0xC4FC, 0x896C,
+	0xC4FD, 0x89BD, 0xC4FE, 0x8B74, 0xC540, 0x8B77, 0xC541, 0x8B7D,
+	0xC542, 0x8D13, 0xC543, 0x8E8A, 0xC544, 0x8E8D, 0xC545, 0x8E8B,
+	0xC546, 0x8F5F, 0xC547, 0x8FAF, 0xC548, 0x91BA, 0xC549, 0x942E,
+	0xC54A, 0x9433, 0xC54B, 0x9435, 0xC54C, 0x943A, 0xC54D, 0x9438,
+	0xC54E, 0x9432, 0xC54F, 0x942B, 0xC550, 0x95E2, 0xC551, 0x9738,
+	0xC552, 0x9739, 0xC553, 0x9732, 0xC554, 0x97FF, 0xC555, 0x9867,
+	0xC556, 0x9865, 0xC557, 0x9957, 0xC558, 0x9A45, 0xC559, 0x9A43,
+	0xC55A, 0x9A40, 0xC55B, 0x9A3E, 0xC55C, 0x9ACF, 0xC55D, 0x9B54,
+	0xC55E, 0x9B51, 0xC55F, 0x9C2D, 0xC560, 0x9C25, 0xC561, 0x9DAF,
+	0xC562, 0x9DB4, 0xC563, 0x9DC2, 0xC564, 0x9DB8, 0xC565, 0x9E9D,
+	0xC566, 0x9EEF, 0xC567, 0x9F19, 0xC568, 0x9F5C, 0xC569, 0x9F66,
+	0xC56A, 0x9F67, 0xC56B, 0x513C, 0xC56C, 0x513B, 0xC56D, 0x56C8,
+	0xC56E, 0x56CA, 0xC56F, 0x56C9, 0xC570, 0x5B7F, 0xC571, 0x5DD4,
+	0xC572, 0x5DD2, 0xC573, 0x5F4E, 0xC574, 0x61FF, 0xC575, 0x6524,
+	0xC576, 0x6B0A, 0xC577, 0x6B61, 0xC578, 0x7051, 0xC579, 0x7058,
+	0xC57A, 0x7380, 0xC57B, 0x74E4, 0xC57C, 0x758A, 0xC57D, 0x766E,
+	0xC57E, 0x766C, 0xC5A1, 0x79B3, 0xC5A2, 0x7C60, 0xC5A3, 0x7C5F,
+	0xC5A4, 0x807E, 0xC5A5, 0x807D, 0xC5A6, 0x81DF, 0xC5A7, 0x8972,
+	0xC5A8, 0x896F, 0xC5A9, 0x89FC, 0xC5AA, 0x8B80, 0xC5AB, 0x8D16,
+	0xC5AC, 0x8D17, 0xC5AD, 0x8E91, 0xC5AE, 0x8E93, 0xC5AF, 0x8F61,
+	0xC5B0, 0x9148, 0xC5B1, 0x9444, 0xC5B2, 0x9451, 0xC5B3, 0x9452,
+	0xC5B4, 0x973D, 0xC5B5, 0x973E, 0xC5B6, 0x97C3, 0xC5B7, 0x97C1,
+	0xC5B8, 0x986B, 0xC5B9, 0x9955, 0xC5BA, 0x9A55, 0xC5BB, 0x9A4D,
+	0xC5BC, 0x9AD2, 0xC5BD, 0x9B1A, 0xC5BE, 0x9C49, 0xC5BF, 0x9C31,
+	0xC5C0, 0x9C3E, 0xC5C1, 0x9C3B, 0xC5C2, 0x9DD3, 0xC5C3, 0x9DD7,
+	0xC5C4, 0x9F34, 0xC5C5, 0x9F6C, 0xC5C6, 0x9F6A, 0xC5C7, 0x9F94,
+	0xC5C8, 0x56CC, 0xC5C9, 0x5DD6, 0xC5CA, 0x6200, 0xC5CB, 0x6523,
+	0xC5CC, 0x652B, 0xC5CD, 0x652A, 0xC5CE, 0x66EC, 0xC5CF, 0x6B10,
+	0xC5D0, 0x74DA, 0xC5D1, 0x7ACA, 0xC5D2, 0x7C64, 0xC5D3, 0x7C63,
+	0xC5D4, 0x7C65, 0xC5D5, 0x7E93, 0xC5D6, 0x7E96, 0xC5D7, 0x7E94,
+	0xC5D8, 0x81E2, 0xC5D9, 0x8638, 0xC5DA, 0x863F, 0xC5DB, 0x8831,
+	0xC5DC, 0x8B8A, 0xC5DD, 0x9090, 0xC5DE, 0x908F, 0xC5DF, 0x9463,
+	0xC5E0, 0x9460, 0xC5E1, 0x9464, 0xC5E2, 0x9768, 0xC5E3, 0x986F,
+	0xC5E4, 0x995C, 0xC5E5, 0x9A5A, 0xC5E6, 0x9A5B, 0xC5E7, 0x9A57,
+	0xC5E8, 0x9AD3, 0xC5E9, 0x9AD4, 0xC5EA, 0x9AD1, 0xC5EB, 0x9C54,
+	0xC5EC, 0x9C57, 0xC5ED, 0x9C56, 0xC5EE, 0x9DE5, 0xC5EF, 0x9E9F,
+	0xC5F0, 0x9EF4, 0xC5F1, 0x56D1, 0xC5F2, 0x58E9, 0xC5F3, 0x652C,
+	0xC5F4, 0x705E, 0xC5F5, 0x7671, 0xC5F6, 0x7672, 0xC5F7, 0x77D7,
+	0xC5F8, 0x7F50, 0xC5F9, 0x7F88, 0xC5FA, 0x8836, 0xC5FB, 0x8839,
+	0xC5FC, 0x8862, 0xC5FD, 0x8B93, 0xC5FE, 0x8B92, 0xC640, 0x8B96,
+	0xC641, 0x8277, 0xC642, 0x8D1B, 0xC643, 0x91C0, 0xC644, 0x946A,
+	0xC645, 0x9742, 0xC646, 0x9748, 0xC647, 0x9744, 0xC648, 0x97C6,
+	0xC649, 0x9870, 0xC64A, 0x9A5F, 0xC64B, 0x9B22, 0xC64C, 0x9B58,
+	0xC64D, 0x9C5F, 0xC64E, 0x9DF9, 0xC64F, 0x9DFA, 0xC650, 0x9E7C,
+	0xC651, 0x9E7D, 0xC652, 0x9F07, 0xC653, 0x9F77, 0xC654, 0x9F72,
+	0xC655, 0x5EF3, 0xC656, 0x6B16, 0xC657, 0x7063, 0xC658, 0x7C6C,
+	0xC659, 0x7C6E, 0xC65A, 0x883B, 0xC65B, 0x89C0, 0xC65C, 0x8EA1,
+	0xC65D, 0x91C1, 0xC65E, 0x9472, 0xC65F, 0x9470, 0xC660, 0x9871,
+	0xC661, 0x995E, 0xC662, 0x9AD6, 0xC663, 0x9B23, 0xC664, 0x9ECC,
+	0xC665, 0x7064, 0xC666, 0x77DA, 0xC667, 0x8B9A, 0xC668, 0x9477,
+	0xC669, 0x97C9, 0xC66A, 0x9A62, 0xC66B, 0x9A65, 0xC66C, 0x7E9C,
+	0xC66D, 0x8B9C, 0xC66E, 0x8EAA, 0xC66F, 0x91C5, 0xC670, 0x947D,
+	0xC671, 0x947E, 0xC672, 0x947C, 0xC673, 0x9C77, 0xC674, 0x9C78,
+	0xC675, 0x9EF7, 0xC676, 0x8C54, 0xC677, 0x947F, 0xC678, 0x9E1A,
+	0xC679, 0x7228, 0xC67A, 0x9A6A, 0xC67B, 0x9B31, 0xC67C, 0x9E1B,
+	0xC67D, 0x9E1E, 0xC67E, 0x7C72, 0xC940, 0x4E42, 0xC941, 0x4E5C,
+	0xC942, 0x51F5, 0xC943, 0x531A, 0xC944, 0x5382, 0xC945, 0x4E07,
+	0xC946, 0x4E0C, 0xC947, 0x4E47, 0xC948, 0x4E8D, 0xC949, 0x56D7,
+	0xC94A, 0xFA0C, 0xC94B, 0x5C6E, 0xC94C, 0x5F73, 0xC94D, 0x4E0F,
+	0xC94E, 0x5187, 0xC94F, 0x4E0E, 0xC950, 0x4E2E, 0xC951, 0x4E93,
+	0xC952, 0x4EC2, 0xC953, 0x4EC9, 0xC954, 0x4EC8, 0xC955, 0x5198,
+	0xC956, 0x52FC, 0xC957, 0x536C, 0xC958, 0x53B9, 0xC959, 0x5720,
+	0xC95A, 0x5903, 0xC95B, 0x592C, 0xC95C, 0x5C10, 0xC95D, 0x5DFF,
+	0xC95E, 0x65E1, 0xC95F, 0x6BB3, 0xC960, 0x6BCC, 0xC961, 0x6C14,
+	0xC962, 0x723F, 0xC963, 0x4E31, 0xC964, 0x4E3C, 0xC965, 0x4EE8,
+	0xC966, 0x4EDC, 0xC967, 0x4EE9, 0xC968, 0x4EE1, 0xC969, 0x4EDD,
+	0xC96A, 0x4EDA, 0xC96B, 0x520C, 0xC96C, 0x531C, 0xC96D, 0x534C,
+	0xC96E, 0x5722, 0xC96F, 0x5723, 0xC970, 0x5917, 0xC971, 0x592F,
+	0xC972, 0x5B81, 0xC973, 0x5B84, 0xC974, 0x5C12, 0xC975, 0x5C3B,
+	0xC976, 0x5C74, 0xC977, 0x5C73, 0xC978, 0x5E04, 0xC979, 0x5E80,
+	0xC97A, 0x5E82, 0xC97B, 0x5FC9, 0xC97C, 0x6209, 0xC97D, 0x6250,
+	0xC97E, 0x6C15, 0xC9A1, 0x6C36, 0xC9A2, 0x6C43, 0xC9A3, 0x6C3F,
+	0xC9A4, 0x6C3B, 0xC9A5, 0x72AE, 0xC9A6, 0x72B0, 0xC9A7, 0x738A,
+	0xC9A8, 0x79B8, 0xC9A9, 0x808A, 0xC9AA, 0x961E, 0xC9AB, 0x4F0E,
+	0xC9AC, 0x4F18, 0xC9AD, 0x4F2C, 0xC9AE, 0x4EF5, 0xC9AF, 0x4F14,
+	0xC9B0, 0x4EF1, 0xC9B1, 0x4F00, 0xC9B2, 0x4EF7, 0xC9B3, 0x4F08,
+	0xC9B4, 0x4F1D, 0xC9B5, 0x4F02, 0xC9B6, 0x4F05, 0xC9B7, 0x4F22,
+	0xC9B8, 0x4F13, 0xC9B9, 0x4F04, 0xC9BA, 0x4EF4, 0xC9BB, 0x4F12,
+	0xC9BC, 0x51B1, 0xC9BD, 0x5213, 0xC9BE, 0x5209, 0xC9BF, 0x5210,
+	0xC9C0, 0x52A6, 0xC9C1, 0x5322, 0xC9C2, 0x531F, 0xC9C3, 0x534D,
+	0xC9C4, 0x538A, 0xC9C5, 0x5407, 0xC9C6, 0x56E1, 0xC9C7, 0x56DF,
+	0xC9C8, 0x572E, 0xC9C9, 0x572A, 0xC9CA, 0x5734, 0xC9CB, 0x593C,
+	0xC9CC, 0x5980, 0xC9CD, 0x597C, 0xC9CE, 0x5985, 0xC9CF, 0x597B,
+	0xC9D0, 0x597E, 0xC9D1, 0x5977, 0xC9D2, 0x597F, 0xC9D3, 0x5B56,
+	0xC9D4, 0x5C15, 0xC9D5, 0x5C25, 0xC9D6, 0x5C7C, 0xC9D7, 0x5C7A,
+	0xC9D8, 0x5C7B, 0xC9D9, 0x5C7E, 0xC9DA, 0x5DDF, 0xC9DB, 0x5E75,
+	0xC9DC, 0x5E84, 0xC9DD, 0x5F02, 0xC9DE, 0x5F1A, 0xC9DF, 0x5F74,
+	0xC9E0, 0x5FD5, 0xC9E1, 0x5FD4, 0xC9E2, 0x5FCF, 0xC9E3, 0x625C,
+	0xC9E4, 0x625E, 0xC9E5, 0x6264, 0xC9E6, 0x6261, 0xC9E7, 0x6266,
+	0xC9E8, 0x6262, 0xC9E9, 0x6259, 0xC9EA, 0x6260, 0xC9EB, 0x625A,
+	0xC9EC, 0x6265, 0xC9ED, 0x65EF, 0xC9EE, 0x65EE, 0xC9EF, 0x673E,
+	0xC9F0, 0x6739, 0xC9F1, 0x6738, 0xC9F2, 0x673B, 0xC9F3, 0x673A,
+	0xC9F4, 0x673F, 0xC9F5, 0x673C, 0xC9F6, 0x6733, 0xC9F7, 0x6C18,
+	0xC9F8, 0x6C46, 0xC9F9, 0x6C52, 0xC9FA, 0x6C5C, 0xC9FB, 0x6C4F,
+	0xC9FC, 0x6C4A, 0xC9FD, 0x6C54, 0xC9FE, 0x6C4B, 0xCA40, 0x6C4C,
+	0xCA41, 0x7071, 0xCA42, 0x725E, 0xCA43, 0x72B4, 0xCA44, 0x72B5,
+	0xCA45, 0x738E, 0xCA46, 0x752A, 0xCA47, 0x767F, 0xCA48, 0x7A75,
+	0xCA49, 0x7F51, 0xCA4A, 0x8278, 0xCA4B, 0x827C, 0xCA4C, 0x8280,
+	0xCA4D, 0x827D, 0xCA4E, 0x827F, 0xCA4F, 0x864D, 0xCA50, 0x897E,
+	0xCA51, 0x9099, 0xCA52, 0x9097, 0xCA53, 0x9098, 0xCA54, 0x909B,
+	0xCA55, 0x9094, 0xCA56, 0x9622, 0xCA57, 0x9624, 0xCA58, 0x9620,
+	0xCA59, 0x9623, 0xCA5A, 0x4F56, 0xCA5B, 0x4F3B, 0xCA5C, 0x4F62,
+	0xCA5D, 0x4F49, 0xCA5E, 0x4F53, 0xCA5F, 0x4F64, 0xCA60, 0x4F3E,
+	0xCA61, 0x4F67, 0xCA62, 0x4F52, 0xCA63, 0x4F5F, 0xCA64, 0x4F41,
+	0xCA65, 0x4F58, 0xCA66, 0x4F2D, 0xCA67, 0x4F33, 0xCA68, 0x4F3F,
+	0xCA69, 0x4F61, 0xCA6A, 0x518F, 0xCA6B, 0x51B9, 0xCA6C, 0x521C,
+	0xCA6D, 0x521E, 0xCA6E, 0x5221, 0xCA6F, 0x52AD, 0xCA70, 0x52AE,
+	0xCA71, 0x5309, 0xCA72, 0x5363, 0xCA73, 0x5372, 0xCA74, 0x538E,
+	0xCA75, 0x538F, 0xCA76, 0x5430, 0xCA77, 0x5437, 0xCA78, 0x542A,
+	0xCA79, 0x5454, 0xCA7A, 0x5445, 0xCA7B, 0x5419, 0xCA7C, 0x541C,
+	0xCA7D, 0x5425, 0xCA7E, 0x5418, 0xCAA1, 0x543D, 0xCAA2, 0x544F,
+	0xCAA3, 0x5441, 0xCAA4, 0x5428, 0xCAA5, 0x5424, 0xCAA6, 0x5447,
+	0xCAA7, 0x56EE, 0xCAA8, 0x56E7, 0xCAA9, 0x56E5, 0xCAAA, 0x5741,
+	0xCAAB, 0x5745, 0xCAAC, 0x574C, 0xCAAD, 0x5749, 0xCAAE, 0x574B,
+	0xCAAF, 0x5752, 0xCAB0, 0x5906, 0xCAB1, 0x5940, 0xCAB2, 0x59A6,
+	0xCAB3, 0x5998, 0xCAB4, 0x59A0, 0xCAB5, 0x5997, 0xCAB6, 0x598E,
+	0xCAB7, 0x59A2, 0xCAB8, 0x5990, 0xCAB9, 0x598F, 0xCABA, 0x59A7,
+	0xCABB, 0x59A1, 0xCABC, 0x5B8E, 0xCABD, 0x5B92, 0xCABE, 0x5C28,
+	0xCABF, 0x5C2A, 0xCAC0, 0x5C8D, 0xCAC1, 0x5C8F, 0xCAC2, 0x5C88,
+	0xCAC3, 0x5C8B, 0xCAC4, 0x5C89, 0xCAC5, 0x5C92, 0xCAC6, 0x5C8A,
+	0xCAC7, 0x5C86, 0xCAC8, 0x5C93, 0xCAC9, 0x5C95, 0xCACA, 0x5DE0,
+	0xCACB, 0x5E0A, 0xCACC, 0x5E0E, 0xCACD, 0x5E8B, 0xCACE, 0x5E89,
+	0xCACF, 0x5E8C, 0xCAD0, 0x5E88, 0xCAD1, 0x5E8D, 0xCAD2, 0x5F05,
+	0xCAD3, 0x5F1D, 0xCAD4, 0x5F78, 0xCAD5, 0x5F76, 0xCAD6, 0x5FD2,
+	0xCAD7, 0x5FD1, 0xCAD8, 0x5FD0, 0xCAD9, 0x5FED, 0xCADA, 0x5FE8,
+	0xCADB, 0x5FEE, 0xCADC, 0x5FF3, 0xCADD, 0x5FE1, 0xCADE, 0x5FE4,
+	0xCADF, 0x5FE3, 0xCAE0, 0x5FFA, 0xCAE1, 0x5FEF, 0xCAE2, 0x5FF7,
+	0xCAE3, 0x5FFB, 0xCAE4, 0x6000, 0xCAE5, 0x5FF4, 0xCAE6, 0x623A,
+	0xCAE7, 0x6283, 0xCAE8, 0x628C, 0xCAE9, 0x628E, 0xCAEA, 0x628F,
+	0xCAEB, 0x6294, 0xCAEC, 0x6287, 0xCAED, 0x6271, 0xCAEE, 0x627B,
+	0xCAEF, 0x627A, 0xCAF0, 0x6270, 0xCAF1, 0x6281, 0xCAF2, 0x6288,
+	0xCAF3, 0x6277, 0xCAF4, 0x627D, 0xCAF5, 0x6272, 0xCAF6, 0x6274,
+	0xCAF7, 0x6537, 0xCAF8, 0x65F0, 0xCAF9, 0x65F4, 0xCAFA, 0x65F3,
+	0xCAFB, 0x65F2, 0xCAFC, 0x65F5, 0xCAFD, 0x6745, 0xCAFE, 0x6747,
+	0xCB40, 0x6759, 0xCB41, 0x6755, 0xCB42, 0x674C, 0xCB43, 0x6748,
+	0xCB44, 0x675D, 0xCB45, 0x674D, 0xCB46, 0x675A, 0xCB47, 0x674B,
+	0xCB48, 0x6BD0, 0xCB49, 0x6C19, 0xCB4A, 0x6C1A, 0xCB4B, 0x6C78,
+	0xCB4C, 0x6C67, 0xCB4D, 0x6C6B, 0xCB4E, 0x6C84, 0xCB4F, 0x6C8B,
+	0xCB50, 0x6C8F, 0xCB51, 0x6C71, 0xCB52, 0x6C6F, 0xCB53, 0x6C69,
+	0xCB54, 0x6C9A, 0xCB55, 0x6C6D, 0xCB56, 0x6C87, 0xCB57, 0x6C95,
+	0xCB58, 0x6C9C, 0xCB59, 0x6C66, 0xCB5A, 0x6C73, 0xCB5B, 0x6C65,
+	0xCB5C, 0x6C7B, 0xCB5D, 0x6C8E, 0xCB5E, 0x7074, 0xCB5F, 0x707A,
+	0xCB60, 0x7263, 0xCB61, 0x72BF, 0xCB62, 0x72BD, 0xCB63, 0x72C3,
+	0xCB64, 0x72C6, 0xCB65, 0x72C1, 0xCB66, 0x72BA, 0xCB67, 0x72C5,
+	0xCB68, 0x7395, 0xCB69, 0x7397, 0xCB6A, 0x7393, 0xCB6B, 0x7394,
+	0xCB6C, 0x7392, 0xCB6D, 0x753A, 0xCB6E, 0x7539, 0xCB6F, 0x7594,
+	0xCB70, 0x7595, 0xCB71, 0x7681, 0xCB72, 0x793D, 0xCB73, 0x8034,
+	0xCB74, 0x8095, 0xCB75, 0x8099, 0xCB76, 0x8090, 0xCB77, 0x8092,
+	0xCB78, 0x809C, 0xCB79, 0x8290, 0xCB7A, 0x828F, 0xCB7B, 0x8285,
+	0xCB7C, 0x828E, 0xCB7D, 0x8291, 0xCB7E, 0x8293, 0xCBA1, 0x828A,
+	0xCBA2, 0x8283, 0xCBA3, 0x8284, 0xCBA4, 0x8C78, 0xCBA5, 0x8FC9,
+	0xCBA6, 0x8FBF, 0xCBA7, 0x909F, 0xCBA8, 0x90A1, 0xCBA9, 0x90A5,
+	0xCBAA, 0x909E, 0xCBAB, 0x90A7, 0xCBAC, 0x90A0, 0xCBAD, 0x9630,
+	0xCBAE, 0x9628, 0xCBAF, 0x962F, 0xCBB0, 0x962D, 0xCBB1, 0x4E33,
+	0xCBB2, 0x4F98, 0xCBB3, 0x4F7C, 0xCBB4, 0x4F85, 0xCBB5, 0x4F7D,
+	0xCBB6, 0x4F80, 0xCBB7, 0x4F87, 0xCBB8, 0x4F76, 0xCBB9, 0x4F74,
+	0xCBBA, 0x4F89, 0xCBBB, 0x4F84, 0xCBBC, 0x4F77, 0xCBBD, 0x4F4C,
+	0xCBBE, 0x4F97, 0xCBBF, 0x4F6A, 0xCBC0, 0x4F9A, 0xCBC1, 0x4F79,
+	0xCBC2, 0x4F81, 0xCBC3, 0x4F78, 0xCBC4, 0x4F90, 0xCBC5, 0x4F9C,
+	0xCBC6, 0x4F94, 0xCBC7, 0x4F9E, 0xCBC8, 0x4F92, 0xCBC9, 0x4F82,
+	0xCBCA, 0x4F95, 0xCBCB, 0x4F6B, 0xCBCC, 0x4F6E, 0xCBCD, 0x519E,
+	0xCBCE, 0x51BC, 0xCBCF, 0x51BE, 0xCBD0, 0x5235, 0xCBD1, 0x5232,
+	0xCBD2, 0x5233, 0xCBD3, 0x5246, 0xCBD4, 0x5231, 0xCBD5, 0x52BC,
+	0xCBD6, 0x530A, 0xCBD7, 0x530B, 0xCBD8, 0x533C, 0xCBD9, 0x5392,
+	0xCBDA, 0x5394, 0xCBDB, 0x5487, 0xCBDC, 0x547F, 0xCBDD, 0x5481,
+	0xCBDE, 0x5491, 0xCBDF, 0x5482, 0xCBE0, 0x5488, 0xCBE1, 0x546B,
+	0xCBE2, 0x547A, 0xCBE3, 0x547E, 0xCBE4, 0x5465, 0xCBE5, 0x546C,
+	0xCBE6, 0x5474, 0xCBE7, 0x5466, 0xCBE8, 0x548D, 0xCBE9, 0x546F,
+	0xCBEA, 0x5461, 0xCBEB, 0x5460, 0xCBEC, 0x5498, 0xCBED, 0x5463,
+	0xCBEE, 0x5467, 0xCBEF, 0x5464, 0xCBF0, 0x56F7, 0xCBF1, 0x56F9,
+	0xCBF2, 0x576F, 0xCBF3, 0x5772, 0xCBF4, 0x576D, 0xCBF5, 0x576B,
+	0xCBF6, 0x5771, 0xCBF7, 0x5770, 0xCBF8, 0x5776, 0xCBF9, 0x5780,
+	0xCBFA, 0x5775, 0xCBFB, 0x577B, 0xCBFC, 0x5773, 0xCBFD, 0x5774,
+	0xCBFE, 0x5762, 0xCC40, 0x5768, 0xCC41, 0x577D, 0xCC42, 0x590C,
+	0xCC43, 0x5945, 0xCC44, 0x59B5, 0xCC45, 0x59BA, 0xCC46, 0x59CF,
+	0xCC47, 0x59CE, 0xCC48, 0x59B2, 0xCC49, 0x59CC, 0xCC4A, 0x59C1,
+	0xCC4B, 0x59B6, 0xCC4C, 0x59BC, 0xCC4D, 0x59C3, 0xCC4E, 0x59D6,
+	0xCC4F, 0x59B1, 0xCC50, 0x59BD, 0xCC51, 0x59C0, 0xCC52, 0x59C8,
+	0xCC53, 0x59B4, 0xCC54, 0x59C7, 0xCC55, 0x5B62, 0xCC56, 0x5B65,
+	0xCC57, 0x5B93, 0xCC58, 0x5B95, 0xCC59, 0x5C44, 0xCC5A, 0x5C47,
+	0xCC5B, 0x5CAE, 0xCC5C, 0x5CA4, 0xCC5D, 0x5CA0, 0xCC5E, 0x5CB5,
+	0xCC5F, 0x5CAF, 0xCC60, 0x5CA8, 0xCC61, 0x5CAC, 0xCC62, 0x5C9F,
+	0xCC63, 0x5CA3, 0xCC64, 0x5CAD, 0xCC65, 0x5CA2, 0xCC66, 0x5CAA,
+	0xCC67, 0x5CA7, 0xCC68, 0x5C9D, 0xCC69, 0x5CA5, 0xCC6A, 0x5CB6,
+	0xCC6B, 0x5CB0, 0xCC6C, 0x5CA6, 0xCC6D, 0x5E17, 0xCC6E, 0x5E14,
+	0xCC6F, 0x5E19, 0xCC70, 0x5F28, 0xCC71, 0x5F22, 0xCC72, 0x5F23,
+	0xCC73, 0x5F24, 0xCC74, 0x5F54, 0xCC75, 0x5F82, 0xCC76, 0x5F7E,
+	0xCC77, 0x5F7D, 0xCC78, 0x5FDE, 0xCC79, 0x5FE5, 0xCC7A, 0x602D,
+	0xCC7B, 0x6026, 0xCC7C, 0x6019, 0xCC7D, 0x6032, 0xCC7E, 0x600B,
+	0xCCA1, 0x6034, 0xCCA2, 0x600A, 0xCCA3, 0x6017, 0xCCA4, 0x6033,
+	0xCCA5, 0x601A, 0xCCA6, 0x601E, 0xCCA7, 0x602C, 0xCCA8, 0x6022,
+	0xCCA9, 0x600D, 0xCCAA, 0x6010, 0xCCAB, 0x602E, 0xCCAC, 0x6013,
+	0xCCAD, 0x6011, 0xCCAE, 0x600C, 0xCCAF, 0x6009, 0xCCB0, 0x601C,
+	0xCCB1, 0x6214, 0xCCB2, 0x623D, 0xCCB3, 0x62AD, 0xCCB4, 0x62B4,
+	0xCCB5, 0x62D1, 0xCCB6, 0x62BE, 0xCCB7, 0x62AA, 0xCCB8, 0x62B6,
+	0xCCB9, 0x62CA, 0xCCBA, 0x62AE, 0xCCBB, 0x62B3, 0xCCBC, 0x62AF,
+	0xCCBD, 0x62BB, 0xCCBE, 0x62A9, 0xCCBF, 0x62B0, 0xCCC0, 0x62B8,
+	0xCCC1, 0x653D, 0xCCC2, 0x65A8, 0xCCC3, 0x65BB, 0xCCC4, 0x6609,
+	0xCCC5, 0x65FC, 0xCCC6, 0x6604, 0xCCC7, 0x6612, 0xCCC8, 0x6608,
+	0xCCC9, 0x65FB, 0xCCCA, 0x6603, 0xCCCB, 0x660B, 0xCCCC, 0x660D,
+	0xCCCD, 0x6605, 0xCCCE, 0x65FD, 0xCCCF, 0x6611, 0xCCD0, 0x6610,
+	0xCCD1, 0x66F6, 0xCCD2, 0x670A, 0xCCD3, 0x6785, 0xCCD4, 0x676C,
+	0xCCD5, 0x678E, 0xCCD6, 0x6792, 0xCCD7, 0x6776, 0xCCD8, 0x677B,
+	0xCCD9, 0x6798, 0xCCDA, 0x6786, 0xCCDB, 0x6784, 0xCCDC, 0x6774,
+	0xCCDD, 0x678D, 0xCCDE, 0x678C, 0xCCDF, 0x677A, 0xCCE0, 0x679F,
+	0xCCE1, 0x6791, 0xCCE2, 0x6799, 0xCCE3, 0x6783, 0xCCE4, 0x677D,
+	0xCCE5, 0x6781, 0xCCE6, 0x6778, 0xCCE7, 0x6779, 0xCCE8, 0x6794,
+	0xCCE9, 0x6B25, 0xCCEA, 0x6B80, 0xCCEB, 0x6B7E, 0xCCEC, 0x6BDE,
+	0xCCED, 0x6C1D, 0xCCEE, 0x6C93, 0xCCEF, 0x6CEC, 0xCCF0, 0x6CEB,
+	0xCCF1, 0x6CEE, 0xCCF2, 0x6CD9, 0xCCF3, 0x6CB6, 0xCCF4, 0x6CD4,
+	0xCCF5, 0x6CAD, 0xCCF6, 0x6CE7, 0xCCF7, 0x6CB7, 0xCCF8, 0x6CD0,
+	0xCCF9, 0x6CC2, 0xCCFA, 0x6CBA, 0xCCFB, 0x6CC3, 0xCCFC, 0x6CC6,
+	0xCCFD, 0x6CED, 0xCCFE, 0x6CF2, 0xCD40, 0x6CD2, 0xCD41, 0x6CDD,
+	0xCD42, 0x6CB4, 0xCD43, 0x6C8A, 0xCD44, 0x6C9D, 0xCD45, 0x6C80,
+	0xCD46, 0x6CDE, 0xCD47, 0x6CC0, 0xCD48, 0x6D30, 0xCD49, 0x6CCD,
+	0xCD4A, 0x6CC7, 0xCD4B, 0x6CB0, 0xCD4C, 0x6CF9, 0xCD4D, 0x6CCF,
+	0xCD4E, 0x6CE9, 0xCD4F, 0x6CD1, 0xCD50, 0x7094, 0xCD51, 0x7098,
+	0xCD52, 0x7085, 0xCD53, 0x7093, 0xCD54, 0x7086, 0xCD55, 0x7084,
+	0xCD56, 0x7091, 0xCD57, 0x7096, 0xCD58, 0x7082, 0xCD59, 0x709A,
+	0xCD5A, 0x7083, 0xCD5B, 0x726A, 0xCD5C, 0x72D6, 0xCD5D, 0x72CB,
+	0xCD5E, 0x72D8, 0xCD5F, 0x72C9, 0xCD60, 0x72DC, 0xCD61, 0x72D2,
+	0xCD62, 0x72D4, 0xCD63, 0x72DA, 0xCD64, 0x72CC, 0xCD65, 0x72D1,
+	0xCD66, 0x73A4, 0xCD67, 0x73A1, 0xCD68, 0x73AD, 0xCD69, 0x73A6,
+	0xCD6A, 0x73A2, 0xCD6B, 0x73A0, 0xCD6C, 0x73AC, 0xCD6D, 0x739D,
+	0xCD6E, 0x74DD, 0xCD6F, 0x74E8, 0xCD70, 0x753F, 0xCD71, 0x7540,
+	0xCD72, 0x753E, 0xCD73, 0x758C, 0xCD74, 0x7598, 0xCD75, 0x76AF,
+	0xCD76, 0x76F3, 0xCD77, 0x76F1, 0xCD78, 0x76F0, 0xCD79, 0x76F5,
+	0xCD7A, 0x77F8, 0xCD7B, 0x77FC, 0xCD7C, 0x77F9, 0xCD7D, 0x77FB,
+	0xCD7E, 0x77FA, 0xCDA1, 0x77F7, 0xCDA2, 0x7942, 0xCDA3, 0x793F,
+	0xCDA4, 0x79C5, 0xCDA5, 0x7A78, 0xCDA6, 0x7A7B, 0xCDA7, 0x7AFB,
+	0xCDA8, 0x7C75, 0xCDA9, 0x7CFD, 0xCDAA, 0x8035, 0xCDAB, 0x808F,
+	0xCDAC, 0x80AE, 0xCDAD, 0x80A3, 0xCDAE, 0x80B8, 0xCDAF, 0x80B5,
+	0xCDB0, 0x80AD, 0xCDB1, 0x8220, 0xCDB2, 0x82A0, 0xCDB3, 0x82C0,
+	0xCDB4, 0x82AB, 0xCDB5, 0x829A, 0xCDB6, 0x8298, 0xCDB7, 0x829B,
+	0xCDB8, 0x82B5, 0xCDB9, 0x82A7, 0xCDBA, 0x82AE, 0xCDBB, 0x82BC,
+	0xCDBC, 0x829E, 0xCDBD, 0x82BA, 0xCDBE, 0x82B4, 0xCDBF, 0x82A8,
+	0xCDC0, 0x82A1, 0xCDC1, 0x82A9, 0xCDC2, 0x82C2, 0xCDC3, 0x82A4,
+	0xCDC4, 0x82C3, 0xCDC5, 0x82B6, 0xCDC6, 0x82A2, 0xCDC7, 0x8670,
+	0xCDC8, 0x866F, 0xCDC9, 0x866D, 0xCDCA, 0x866E, 0xCDCB, 0x8C56,
+	0xCDCC, 0x8FD2, 0xCDCD, 0x8FCB, 0xCDCE, 0x8FD3, 0xCDCF, 0x8FCD,
+	0xCDD0, 0x8FD6, 0xCDD1, 0x8FD5, 0xCDD2, 0x8FD7, 0xCDD3, 0x90B2,
+	0xCDD4, 0x90B4, 0xCDD5, 0x90AF, 0xCDD6, 0x90B3, 0xCDD7, 0x90B0,
+	0xCDD8, 0x9639, 0xCDD9, 0x963D, 0xCDDA, 0x963C, 0xCDDB, 0x963A,
+	0xCDDC, 0x9643, 0xCDDD, 0x4FCD, 0xCDDE, 0x4FC5, 0xCDDF, 0x4FD3,
+	0xCDE0, 0x4FB2, 0xCDE1, 0x4FC9, 0xCDE2, 0x4FCB, 0xCDE3, 0x4FC1,
+	0xCDE4, 0x4FD4, 0xCDE5, 0x4FDC, 0xCDE6, 0x4FD9, 0xCDE7, 0x4FBB,
+	0xCDE8, 0x4FB3, 0xCDE9, 0x4FDB, 0xCDEA, 0x4FC7, 0xCDEB, 0x4FD6,
+	0xCDEC, 0x4FBA, 0xCDED, 0x4FC0, 0xCDEE, 0x4FB9, 0xCDEF, 0x4FEC,
+	0xCDF0, 0x5244, 0xCDF1, 0x5249, 0xCDF2, 0x52C0, 0xCDF3, 0x52C2,
+	0xCDF4, 0x533D, 0xCDF5, 0x537C, 0xCDF6, 0x5397, 0xCDF7, 0x5396,
+	0xCDF8, 0x5399, 0xCDF9, 0x5398, 0xCDFA, 0x54BA, 0xCDFB, 0x54A1,
+	0xCDFC, 0x54AD, 0xCDFD, 0x54A5, 0xCDFE, 0x54CF, 0xCE40, 0x54C3,
+	0xCE41, 0x830D, 0xCE42, 0x54B7, 0xCE43, 0x54AE, 0xCE44, 0x54D6,
+	0xCE45, 0x54B6, 0xCE46, 0x54C5, 0xCE47, 0x54C6, 0xCE48, 0x54A0,
+	0xCE49, 0x5470, 0xCE4A, 0x54BC, 0xCE4B, 0x54A2, 0xCE4C, 0x54BE,
+	0xCE4D, 0x5472, 0xCE4E, 0x54DE, 0xCE4F, 0x54B0, 0xCE50, 0x57B5,
+	0xCE51, 0x579E, 0xCE52, 0x579F, 0xCE53, 0x57A4, 0xCE54, 0x578C,
+	0xCE55, 0x5797, 0xCE56, 0x579D, 0xCE57, 0x579B, 0xCE58, 0x5794,
+	0xCE59, 0x5798, 0xCE5A, 0x578F, 0xCE5B, 0x5799, 0xCE5C, 0x57A5,
+	0xCE5D, 0x579A, 0xCE5E, 0x5795, 0xCE5F, 0x58F4, 0xCE60, 0x590D,
+	0xCE61, 0x5953, 0xCE62, 0x59E1, 0xCE63, 0x59DE, 0xCE64, 0x59EE,
+	0xCE65, 0x5A00, 0xCE66, 0x59F1, 0xCE67, 0x59DD, 0xCE68, 0x59FA,
+	0xCE69, 0x59FD, 0xCE6A, 0x59FC, 0xCE6B, 0x59F6, 0xCE6C, 0x59E4,
+	0xCE6D, 0x59F2, 0xCE6E, 0x59F7, 0xCE6F, 0x59DB, 0xCE70, 0x59E9,
+	0xCE71, 0x59F3, 0xCE72, 0x59F5, 0xCE73, 0x59E0, 0xCE74, 0x59FE,
+	0xCE75, 0x59F4, 0xCE76, 0x59ED, 0xCE77, 0x5BA8, 0xCE78, 0x5C4C,
+	0xCE79, 0x5CD0, 0xCE7A, 0x5CD8, 0xCE7B, 0x5CCC, 0xCE7C, 0x5CD7,
+	0xCE7D, 0x5CCB, 0xCE7E, 0x5CDB, 0xCEA1, 0x5CDE, 0xCEA2, 0x5CDA,
+	0xCEA3, 0x5CC9, 0xCEA4, 0x5CC7, 0xCEA5, 0x5CCA, 0xCEA6, 0x5CD6,
+	0xCEA7, 0x5CD3, 0xCEA8, 0x5CD4, 0xCEA9, 0x5CCF, 0xCEAA, 0x5CC8,
+	0xCEAB, 0x5CC6, 0xCEAC, 0x5CCE, 0xCEAD, 0x5CDF, 0xCEAE, 0x5CF8,
+	0xCEAF, 0x5DF9, 0xCEB0, 0x5E21, 0xCEB1, 0x5E22, 0xCEB2, 0x5E23,
+	0xCEB3, 0x5E20, 0xCEB4, 0x5E24, 0xCEB5, 0x5EB0, 0xCEB6, 0x5EA4,
+	0xCEB7, 0x5EA2, 0xCEB8, 0x5E9B, 0xCEB9, 0x5EA3, 0xCEBA, 0x5EA5,
+	0xCEBB, 0x5F07, 0xCEBC, 0x5F2E, 0xCEBD, 0x5F56, 0xCEBE, 0x5F86,
+	0xCEBF, 0x6037, 0xCEC0, 0x6039, 0xCEC1, 0x6054, 0xCEC2, 0x6072,
+	0xCEC3, 0x605E, 0xCEC4, 0x6045, 0xCEC5, 0x6053, 0xCEC6, 0x6047,
+	0xCEC7, 0x6049, 0xCEC8, 0x605B, 0xCEC9, 0x604C, 0xCECA, 0x6040,
+	0xCECB, 0x6042, 0xCECC, 0x605F, 0xCECD, 0x6024, 0xCECE, 0x6044,
+	0xCECF, 0x6058, 0xCED0, 0x6066, 0xCED1, 0x606E, 0xCED2, 0x6242,
+	0xCED3, 0x6243, 0xCED4, 0x62CF, 0xCED5, 0x630D, 0xCED6, 0x630B,
+	0xCED7, 0x62F5, 0xCED8, 0x630E, 0xCED9, 0x6303, 0xCEDA, 0x62EB,
+	0xCEDB, 0x62F9, 0xCEDC, 0x630F, 0xCEDD, 0x630C, 0xCEDE, 0x62F8,
+	0xCEDF, 0x62F6, 0xCEE0, 0x6300, 0xCEE1, 0x6313, 0xCEE2, 0x6314,
+	0xCEE3, 0x62FA, 0xCEE4, 0x6315, 0xCEE5, 0x62FB, 0xCEE6, 0x62F0,
+	0xCEE7, 0x6541, 0xCEE8, 0x6543, 0xCEE9, 0x65AA, 0xCEEA, 0x65BF,
+	0xCEEB, 0x6636, 0xCEEC, 0x6621, 0xCEED, 0x6632, 0xCEEE, 0x6635,
+	0xCEEF, 0x661C, 0xCEF0, 0x6626, 0xCEF1, 0x6622, 0xCEF2, 0x6633,
+	0xCEF3, 0x662B, 0xCEF4, 0x663A, 0xCEF5, 0x661D, 0xCEF6, 0x6634,
+	0xCEF7, 0x6639, 0xCEF8, 0x662E, 0xCEF9, 0x670F, 0xCEFA, 0x6710,
+	0xCEFB, 0x67C1, 0xCEFC, 0x67F2, 0xCEFD, 0x67C8, 0xCEFE, 0x67BA,
+	0xCF40, 0x67DC, 0xCF41, 0x67BB, 0xCF42, 0x67F8, 0xCF43, 0x67D8,
+	0xCF44, 0x67C0, 0xCF45, 0x67B7, 0xCF46, 0x67C5, 0xCF47, 0x67EB,
+	0xCF48, 0x67E4, 0xCF49, 0x67DF, 0xCF4A, 0x67B5, 0xCF4B, 0x67CD,
+	0xCF4C, 0x67B3, 0xCF4D, 0x67F7, 0xCF4E, 0x67F6, 0xCF4F, 0x67EE,
+	0xCF50, 0x67E3, 0xCF51, 0x67C2, 0xCF52, 0x67B9, 0xCF53, 0x67CE,
+	0xCF54, 0x67E7, 0xCF55, 0x67F0, 0xCF56, 0x67B2, 0xCF57, 0x67FC,
+	0xCF58, 0x67C6, 0xCF59, 0x67ED, 0xCF5A, 0x67CC, 0xCF5B, 0x67AE,
+	0xCF5C, 0x67E6, 0xCF5D, 0x67DB, 0xCF5E, 0x67FA, 0xCF5F, 0x67C9,
+	0xCF60, 0x67CA, 0xCF61, 0x67C3, 0xCF62, 0x67EA, 0xCF63, 0x67CB,
+	0xCF64, 0x6B28, 0xCF65, 0x6B82, 0xCF66, 0x6B84, 0xCF67, 0x6BB6,
+	0xCF68, 0x6BD6, 0xCF69, 0x6BD8, 0xCF6A, 0x6BE0, 0xCF6B, 0x6C20,
+	0xCF6C, 0x6C21, 0xCF6D, 0x6D28, 0xCF6E, 0x6D34, 0xCF6F, 0x6D2D,
+	0xCF70, 0x6D1F, 0xCF71, 0x6D3C, 0xCF72, 0x6D3F, 0xCF73, 0x6D12,
+	0xCF74, 0x6D0A, 0xCF75, 0x6CDA, 0xCF76, 0x6D33, 0xCF77, 0x6D04,
+	0xCF78, 0x6D19, 0xCF79, 0x6D3A, 0xCF7A, 0x6D1A, 0xCF7B, 0x6D11,
+	0xCF7C, 0x6D00, 0xCF7D, 0x6D1D, 0xCF7E, 0x6D42, 0xCFA1, 0x6D01,
+	0xCFA2, 0x6D18, 0xCFA3, 0x6D37, 0xCFA4, 0x6D03, 0xCFA5, 0x6D0F,
+	0xCFA6, 0x6D40, 0xCFA7, 0x6D07, 0xCFA8, 0x6D20, 0xCFA9, 0x6D2C,
+	0xCFAA, 0x6D08, 0xCFAB, 0x6D22, 0xCFAC, 0x6D09, 0xCFAD, 0x6D10,
+	0xCFAE, 0x70B7, 0xCFAF, 0x709F, 0xCFB0, 0x70BE, 0xCFB1, 0x70B1,
+	0xCFB2, 0x70B0, 0xCFB3, 0x70A1, 0xCFB4, 0x70B4, 0xCFB5, 0x70B5,
+	0xCFB6, 0x70A9, 0xCFB7, 0x7241, 0xCFB8, 0x7249, 0xCFB9, 0x724A,
+	0xCFBA, 0x726C, 0xCFBB, 0x7270, 0xCFBC, 0x7273, 0xCFBD, 0x726E,
+	0xCFBE, 0x72CA, 0xCFBF, 0x72E4, 0xCFC0, 0x72E8, 0xCFC1, 0x72EB,
+	0xCFC2, 0x72DF, 0xCFC3, 0x72EA, 0xCFC4, 0x72E6, 0xCFC5, 0x72E3,
+	0xCFC6, 0x7385, 0xCFC7, 0x73CC, 0xCFC8, 0x73C2, 0xCFC9, 0x73C8,
+	0xCFCA, 0x73C5, 0xCFCB, 0x73B9, 0xCFCC, 0x73B6, 0xCFCD, 0x73B5,
+	0xCFCE, 0x73B4, 0xCFCF, 0x73EB, 0xCFD0, 0x73BF, 0xCFD1, 0x73C7,
+	0xCFD2, 0x73BE, 0xCFD3, 0x73C3, 0xCFD4, 0x73C6, 0xCFD5, 0x73B8,
+	0xCFD6, 0x73CB, 0xCFD7, 0x74EC, 0xCFD8, 0x74EE, 0xCFD9, 0x752E,
+	0xCFDA, 0x7547, 0xCFDB, 0x7548, 0xCFDC, 0x75A7, 0xCFDD, 0x75AA,
+	0xCFDE, 0x7679, 0xCFDF, 0x76C4, 0xCFE0, 0x7708, 0xCFE1, 0x7703,
+	0xCFE2, 0x7704, 0xCFE3, 0x7705, 0xCFE4, 0x770A, 0xCFE5, 0x76F7,
+	0xCFE6, 0x76FB, 0xCFE7, 0x76FA, 0xCFE8, 0x77E7, 0xCFE9, 0x77E8,
+	0xCFEA, 0x7806, 0xCFEB, 0x7811, 0xCFEC, 0x7812, 0xCFED, 0x7805,
+	0xCFEE, 0x7810, 0xCFEF, 0x780F, 0xCFF0, 0x780E, 0xCFF1, 0x7809,
+	0xCFF2, 0x7803, 0xCFF3, 0x7813, 0xCFF4, 0x794A, 0xCFF5, 0x794C,
+	0xCFF6, 0x794B, 0xCFF7, 0x7945, 0xCFF8, 0x7944, 0xCFF9, 0x79D5,
+	0xCFFA, 0x79CD, 0xCFFB, 0x79CF, 0xCFFC, 0x79D6, 0xCFFD, 0x79CE,
+	0xCFFE, 0x7A80, 0xD040, 0x7A7E, 0xD041, 0x7AD1, 0xD042, 0x7B00,
+	0xD043, 0x7B01, 0xD044, 0x7C7A, 0xD045, 0x7C78, 0xD046, 0x7C79,
+	0xD047, 0x7C7F, 0xD048, 0x7C80, 0xD049, 0x7C81, 0xD04A, 0x7D03,
+	0xD04B, 0x7D08, 0xD04C, 0x7D01, 0xD04D, 0x7F58, 0xD04E, 0x7F91,
+	0xD04F, 0x7F8D, 0xD050, 0x7FBE, 0xD051, 0x8007, 0xD052, 0x800E,
+	0xD053, 0x800F, 0xD054, 0x8014, 0xD055, 0x8037, 0xD056, 0x80D8,
+	0xD057, 0x80C7, 0xD058, 0x80E0, 0xD059, 0x80D1, 0xD05A, 0x80C8,
+	0xD05B, 0x80C2, 0xD05C, 0x80D0, 0xD05D, 0x80C5, 0xD05E, 0x80E3,
+	0xD05F, 0x80D9, 0xD060, 0x80DC, 0xD061, 0x80CA, 0xD062, 0x80D5,
+	0xD063, 0x80C9, 0xD064, 0x80CF, 0xD065, 0x80D7, 0xD066, 0x80E6,
+	0xD067, 0x80CD, 0xD068, 0x81FF, 0xD069, 0x8221, 0xD06A, 0x8294,
+	0xD06B, 0x82D9, 0xD06C, 0x82FE, 0xD06D, 0x82F9, 0xD06E, 0x8307,
+	0xD06F, 0x82E8, 0xD070, 0x8300, 0xD071, 0x82D5, 0xD072, 0x833A,
+	0xD073, 0x82EB, 0xD074, 0x82D6, 0xD075, 0x82F4, 0xD076, 0x82EC,
+	0xD077, 0x82E1, 0xD078, 0x82F2, 0xD079, 0x82F5, 0xD07A, 0x830C,
+	0xD07B, 0x82FB, 0xD07C, 0x82F6, 0xD07D, 0x82F0, 0xD07E, 0x82EA,
+	0xD0A1, 0x82E4, 0xD0A2, 0x82E0, 0xD0A3, 0x82FA, 0xD0A4, 0x82F3,
+	0xD0A5, 0x82ED, 0xD0A6, 0x8677, 0xD0A7, 0x8674, 0xD0A8, 0x867C,
+	0xD0A9, 0x8673, 0xD0AA, 0x8841, 0xD0AB, 0x884E, 0xD0AC, 0x8867,
+	0xD0AD, 0x886A, 0xD0AE, 0x8869, 0xD0AF, 0x89D3, 0xD0B0, 0x8A04,
+	0xD0B1, 0x8A07, 0xD0B2, 0x8D72, 0xD0B3, 0x8FE3, 0xD0B4, 0x8FE1,
+	0xD0B5, 0x8FEE, 0xD0B6, 0x8FE0, 0xD0B7, 0x90F1, 0xD0B8, 0x90BD,
+	0xD0B9, 0x90BF, 0xD0BA, 0x90D5, 0xD0BB, 0x90C5, 0xD0BC, 0x90BE,
+	0xD0BD, 0x90C7, 0xD0BE, 0x90CB, 0xD0BF, 0x90C8, 0xD0C0, 0x91D4,
+	0xD0C1, 0x91D3, 0xD0C2, 0x9654, 0xD0C3, 0x964F, 0xD0C4, 0x9651,
+	0xD0C5, 0x9653, 0xD0C6, 0x964A, 0xD0C7, 0x964E, 0xD0C8, 0x501E,
+	0xD0C9, 0x5005, 0xD0CA, 0x5007, 0xD0CB, 0x5013, 0xD0CC, 0x5022,
+	0xD0CD, 0x5030, 0xD0CE, 0x501B, 0xD0CF, 0x4FF5, 0xD0D0, 0x4FF4,
+	0xD0D1, 0x5033, 0xD0D2, 0x5037, 0xD0D3, 0x502C, 0xD0D4, 0x4FF6,
+	0xD0D5, 0x4FF7, 0xD0D6, 0x5017, 0xD0D7, 0x501C, 0xD0D8, 0x5020,
+	0xD0D9, 0x5027, 0xD0DA, 0x5035, 0xD0DB, 0x502F, 0xD0DC, 0x5031,
+	0xD0DD, 0x500E, 0xD0DE, 0x515A, 0xD0DF, 0x5194, 0xD0E0, 0x5193,
+	0xD0E1, 0x51CA, 0xD0E2, 0x51C4, 0xD0E3, 0x51C5, 0xD0E4, 0x51C8,
+	0xD0E5, 0x51CE, 0xD0E6, 0x5261, 0xD0E7, 0x525A, 0xD0E8, 0x5252,
+	0xD0E9, 0x525E, 0xD0EA, 0x525F, 0xD0EB, 0x5255, 0xD0EC, 0x5262,
+	0xD0ED, 0x52CD, 0xD0EE, 0x530E, 0xD0EF, 0x539E, 0xD0F0, 0x5526,
+	0xD0F1, 0x54E2, 0xD0F2, 0x5517, 0xD0F3, 0x5512, 0xD0F4, 0x54E7,
+	0xD0F5, 0x54F3, 0xD0F6, 0x54E4, 0xD0F7, 0x551A, 0xD0F8, 0x54FF,
+	0xD0F9, 0x5504, 0xD0FA, 0x5508, 0xD0FB, 0x54EB, 0xD0FC, 0x5511,
+	0xD0FD, 0x5505, 0xD0FE, 0x54F1, 0xD140, 0x550A, 0xD141, 0x54FB,
+	0xD142, 0x54F7, 0xD143, 0x54F8, 0xD144, 0x54E0, 0xD145, 0x550E,
+	0xD146, 0x5503, 0xD147, 0x550B, 0xD148, 0x5701, 0xD149, 0x5702,
+	0xD14A, 0x57CC, 0xD14B, 0x5832, 0xD14C, 0x57D5, 0xD14D, 0x57D2,
+	0xD14E, 0x57BA, 0xD14F, 0x57C6, 0xD150, 0x57BD, 0xD151, 0x57BC,
+	0xD152, 0x57B8, 0xD153, 0x57B6, 0xD154, 0x57BF, 0xD155, 0x57C7,
+	0xD156, 0x57D0, 0xD157, 0x57B9, 0xD158, 0x57C1, 0xD159, 0x590E,
+	0xD15A, 0x594A, 0xD15B, 0x5A19, 0xD15C, 0x5A16, 0xD15D, 0x5A2D,
+	0xD15E, 0x5A2E, 0xD15F, 0x5A15, 0xD160, 0x5A0F, 0xD161, 0x5A17,
+	0xD162, 0x5A0A, 0xD163, 0x5A1E, 0xD164, 0x5A33, 0xD165, 0x5B6C,
+	0xD166, 0x5BA7, 0xD167, 0x5BAD, 0xD168, 0x5BAC, 0xD169, 0x5C03,
+	0xD16A, 0x5C56, 0xD16B, 0x5C54, 0xD16C, 0x5CEC, 0xD16D, 0x5CFF,
+	0xD16E, 0x5CEE, 0xD16F, 0x5CF1, 0xD170, 0x5CF7, 0xD171, 0x5D00,
+	0xD172, 0x5CF9, 0xD173, 0x5E29, 0xD174, 0x5E28, 0xD175, 0x5EA8,
+	0xD176, 0x5EAE, 0xD177, 0x5EAA, 0xD178, 0x5EAC, 0xD179, 0x5F33,
+	0xD17A, 0x5F30, 0xD17B, 0x5F67, 0xD17C, 0x605D, 0xD17D, 0x605A,
+	0xD17E, 0x6067, 0xD1A1, 0x6041, 0xD1A2, 0x60A2, 0xD1A3, 0x6088,
+	0xD1A4, 0x6080, 0xD1A5, 0x6092, 0xD1A6, 0x6081, 0xD1A7, 0x609D,
+	0xD1A8, 0x6083, 0xD1A9, 0x6095, 0xD1AA, 0x609B, 0xD1AB, 0x6097,
+	0xD1AC, 0x6087, 0xD1AD, 0x609C, 0xD1AE, 0x608E, 0xD1AF, 0x6219,
+	0xD1B0, 0x6246, 0xD1B1, 0x62F2, 0xD1B2, 0x6310, 0xD1B3, 0x6356,
+	0xD1B4, 0x632C, 0xD1B5, 0x6344, 0xD1B6, 0x6345, 0xD1B7, 0x6336,
+	0xD1B8, 0x6343, 0xD1B9, 0x63E4, 0xD1BA, 0x6339, 0xD1BB, 0x634B,
+	0xD1BC, 0x634A, 0xD1BD, 0x633C, 0xD1BE, 0x6329, 0xD1BF, 0x6341,
+	0xD1C0, 0x6334, 0xD1C1, 0x6358, 0xD1C2, 0x6354, 0xD1C3, 0x6359,
+	0xD1C4, 0x632D, 0xD1C5, 0x6347, 0xD1C6, 0x6333, 0xD1C7, 0x635A,
+	0xD1C8, 0x6351, 0xD1C9, 0x6338, 0xD1CA, 0x6357, 0xD1CB, 0x6340,
+	0xD1CC, 0x6348, 0xD1CD, 0x654A, 0xD1CE, 0x6546, 0xD1CF, 0x65C6,
+	0xD1D0, 0x65C3, 0xD1D1, 0x65C4, 0xD1D2, 0x65C2, 0xD1D3, 0x664A,
+	0xD1D4, 0x665F, 0xD1D5, 0x6647, 0xD1D6, 0x6651, 0xD1D7, 0x6712,
+	0xD1D8, 0x6713, 0xD1D9, 0x681F, 0xD1DA, 0x681A, 0xD1DB, 0x6849,
+	0xD1DC, 0x6832, 0xD1DD, 0x6833, 0xD1DE, 0x683B, 0xD1DF, 0x684B,
+	0xD1E0, 0x684F, 0xD1E1, 0x6816, 0xD1E2, 0x6831, 0xD1E3, 0x681C,
+	0xD1E4, 0x6835, 0xD1E5, 0x682B, 0xD1E6, 0x682D, 0xD1E7, 0x682F,
+	0xD1E8, 0x684E, 0xD1E9, 0x6844, 0xD1EA, 0x6834, 0xD1EB, 0x681D,
+	0xD1EC, 0x6812, 0xD1ED, 0x6814, 0xD1EE, 0x6826, 0xD1EF, 0x6828,
+	0xD1F0, 0x682E, 0xD1F1, 0x684D, 0xD1F2, 0x683A, 0xD1F3, 0x6825,
+	0xD1F4, 0x6820, 0xD1F5, 0x6B2C, 0xD1F6, 0x6B2F, 0xD1F7, 0x6B2D,
+	0xD1F8, 0x6B31, 0xD1F9, 0x6B34, 0xD1FA, 0x6B6D, 0xD1FB, 0x8082,
+	0xD1FC, 0x6B88, 0xD1FD, 0x6BE6, 0xD1FE, 0x6BE4, 0xD240, 0x6BE8,
+	0xD241, 0x6BE3, 0xD242, 0x6BE2, 0xD243, 0x6BE7, 0xD244, 0x6C25,
+	0xD245, 0x6D7A, 0xD246, 0x6D63, 0xD247, 0x6D64, 0xD248, 0x6D76,
+	0xD249, 0x6D0D, 0xD24A, 0x6D61, 0xD24B, 0x6D92, 0xD24C, 0x6D58,
+	0xD24D, 0x6D62, 0xD24E, 0x6D6D, 0xD24F, 0x6D6F, 0xD250, 0x6D91,
+	0xD251, 0x6D8D, 0xD252, 0x6DEF, 0xD253, 0x6D7F, 0xD254, 0x6D86,
+	0xD255, 0x6D5E, 0xD256, 0x6D67, 0xD257, 0x6D60, 0xD258, 0x6D97,
+	0xD259, 0x6D70, 0xD25A, 0x6D7C, 0xD25B, 0x6D5F, 0xD25C, 0x6D82,
+	0xD25D, 0x6D98, 0xD25E, 0x6D2F, 0xD25F, 0x6D68, 0xD260, 0x6D8B,
+	0xD261, 0x6D7E, 0xD262, 0x6D80, 0xD263, 0x6D84, 0xD264, 0x6D16,
+	0xD265, 0x6D83, 0xD266, 0x6D7B, 0xD267, 0x6D7D, 0xD268, 0x6D75,
+	0xD269, 0x6D90, 0xD26A, 0x70DC, 0xD26B, 0x70D3, 0xD26C, 0x70D1,
+	0xD26D, 0x70DD, 0xD26E, 0x70CB, 0xD26F, 0x7F39, 0xD270, 0x70E2,
+	0xD271, 0x70D7, 0xD272, 0x70D2, 0xD273, 0x70DE, 0xD274, 0x70E0,
+	0xD275, 0x70D4, 0xD276, 0x70CD, 0xD277, 0x70C5, 0xD278, 0x70C6,
+	0xD279, 0x70C7, 0xD27A, 0x70DA, 0xD27B, 0x70CE, 0xD27C, 0x70E1,
+	0xD27D, 0x7242, 0xD27E, 0x7278, 0xD2A1, 0x7277, 0xD2A2, 0x7276,
+	0xD2A3, 0x7300, 0xD2A4, 0x72FA, 0xD2A5, 0x72F4, 0xD2A6, 0x72FE,
+	0xD2A7, 0x72F6, 0xD2A8, 0x72F3, 0xD2A9, 0x72FB, 0xD2AA, 0x7301,
+	0xD2AB, 0x73D3, 0xD2AC, 0x73D9, 0xD2AD, 0x73E5, 0xD2AE, 0x73D6,
+	0xD2AF, 0x73BC, 0xD2B0, 0x73E7, 0xD2B1, 0x73E3, 0xD2B2, 0x73E9,
+	0xD2B3, 0x73DC, 0xD2B4, 0x73D2, 0xD2B5, 0x73DB, 0xD2B6, 0x73D4,
+	0xD2B7, 0x73DD, 0xD2B8, 0x73DA, 0xD2B9, 0x73D7, 0xD2BA, 0x73D8,
+	0xD2BB, 0x73E8, 0xD2BC, 0x74DE, 0xD2BD, 0x74DF, 0xD2BE, 0x74F4,
+	0xD2BF, 0x74F5, 0xD2C0, 0x7521, 0xD2C1, 0x755B, 0xD2C2, 0x755F,
+	0xD2C3, 0x75B0, 0xD2C4, 0x75C1, 0xD2C5, 0x75BB, 0xD2C6, 0x75C4,
+	0xD2C7, 0x75C0, 0xD2C8, 0x75BF, 0xD2C9, 0x75B6, 0xD2CA, 0x75BA,
+	0xD2CB, 0x768A, 0xD2CC, 0x76C9, 0xD2CD, 0x771D, 0xD2CE, 0x771B,
+	0xD2CF, 0x7710, 0xD2D0, 0x7713, 0xD2D1, 0x7712, 0xD2D2, 0x7723,
+	0xD2D3, 0x7711, 0xD2D4, 0x7715, 0xD2D5, 0x7719, 0xD2D6, 0x771A,
+	0xD2D7, 0x7722, 0xD2D8, 0x7727, 0xD2D9, 0x7823, 0xD2DA, 0x782C,
+	0xD2DB, 0x7822, 0xD2DC, 0x7835, 0xD2DD, 0x782F, 0xD2DE, 0x7828,
+	0xD2DF, 0x782E, 0xD2E0, 0x782B, 0xD2E1, 0x7821, 0xD2E2, 0x7829,
+	0xD2E3, 0x7833, 0xD2E4, 0x782A, 0xD2E5, 0x7831, 0xD2E6, 0x7954,
+	0xD2E7, 0x795B, 0xD2E8, 0x794F, 0xD2E9, 0x795C, 0xD2EA, 0x7953,
+	0xD2EB, 0x7952, 0xD2EC, 0x7951, 0xD2ED, 0x79EB, 0xD2EE, 0x79EC,
+	0xD2EF, 0x79E0, 0xD2F0, 0x79EE, 0xD2F1, 0x79ED, 0xD2F2, 0x79EA,
+	0xD2F3, 0x79DC, 0xD2F4, 0x79DE, 0xD2F5, 0x79DD, 0xD2F6, 0x7A86,
+	0xD2F7, 0x7A89, 0xD2F8, 0x7A85, 0xD2F9, 0x7A8B, 0xD2FA, 0x7A8C,
+	0xD2FB, 0x7A8A, 0xD2FC, 0x7A87, 0xD2FD, 0x7AD8, 0xD2FE, 0x7B10,
+	0xD340, 0x7B04, 0xD341, 0x7B13, 0xD342, 0x7B05, 0xD343, 0x7B0F,
+	0xD344, 0x7B08, 0xD345, 0x7B0A, 0xD346, 0x7B0E, 0xD347, 0x7B09,
+	0xD348, 0x7B12, 0xD349, 0x7C84, 0xD34A, 0x7C91, 0xD34B, 0x7C8A,
+	0xD34C, 0x7C8C, 0xD34D, 0x7C88, 0xD34E, 0x7C8D, 0xD34F, 0x7C85,
+	0xD350, 0x7D1E, 0xD351, 0x7D1D, 0xD352, 0x7D11, 0xD353, 0x7D0E,
+	0xD354, 0x7D18, 0xD355, 0x7D16, 0xD356, 0x7D13, 0xD357, 0x7D1F,
+	0xD358, 0x7D12, 0xD359, 0x7D0F, 0xD35A, 0x7D0C, 0xD35B, 0x7F5C,
+	0xD35C, 0x7F61, 0xD35D, 0x7F5E, 0xD35E, 0x7F60, 0xD35F, 0x7F5D,
+	0xD360, 0x7F5B, 0xD361, 0x7F96, 0xD362, 0x7F92, 0xD363, 0x7FC3,
+	0xD364, 0x7FC2, 0xD365, 0x7FC0, 0xD366, 0x8016, 0xD367, 0x803E,
+	0xD368, 0x8039, 0xD369, 0x80FA, 0xD36A, 0x80F2, 0xD36B, 0x80F9,
+	0xD36C, 0x80F5, 0xD36D, 0x8101, 0xD36E, 0x80FB, 0xD36F, 0x8100,
+	0xD370, 0x8201, 0xD371, 0x822F, 0xD372, 0x8225, 0xD373, 0x8333,
+	0xD374, 0x832D, 0xD375, 0x8344, 0xD376, 0x8319, 0xD377, 0x8351,
+	0xD378, 0x8325, 0xD379, 0x8356, 0xD37A, 0x833F, 0xD37B, 0x8341,
+	0xD37C, 0x8326, 0xD37D, 0x831C, 0xD37E, 0x8322, 0xD3A1, 0x8342,
+	0xD3A2, 0x834E, 0xD3A3, 0x831B, 0xD3A4, 0x832A, 0xD3A5, 0x8308,
+	0xD3A6, 0x833C, 0xD3A7, 0x834D, 0xD3A8, 0x8316, 0xD3A9, 0x8324,
+	0xD3AA, 0x8320, 0xD3AB, 0x8337, 0xD3AC, 0x832F, 0xD3AD, 0x8329,
+	0xD3AE, 0x8347, 0xD3AF, 0x8345, 0xD3B0, 0x834C, 0xD3B1, 0x8353,
+	0xD3B2, 0x831E, 0xD3B3, 0x832C, 0xD3B4, 0x834B, 0xD3B5, 0x8327,
+	0xD3B6, 0x8348, 0xD3B7, 0x8653, 0xD3B8, 0x8652, 0xD3B9, 0x86A2,
+	0xD3BA, 0x86A8, 0xD3BB, 0x8696, 0xD3BC, 0x868D, 0xD3BD, 0x8691,
+	0xD3BE, 0x869E, 0xD3BF, 0x8687, 0xD3C0, 0x8697, 0xD3C1, 0x8686,
+	0xD3C2, 0x868B, 0xD3C3, 0x869A, 0xD3C4, 0x8685, 0xD3C5, 0x86A5,
+	0xD3C6, 0x8699, 0xD3C7, 0x86A1, 0xD3C8, 0x86A7, 0xD3C9, 0x8695,
+	0xD3CA, 0x8698, 0xD3CB, 0x868E, 0xD3CC, 0x869D, 0xD3CD, 0x8690,
+	0xD3CE, 0x8694, 0xD3CF, 0x8843, 0xD3D0, 0x8844, 0xD3D1, 0x886D,
+	0xD3D2, 0x8875, 0xD3D3, 0x8876, 0xD3D4, 0x8872, 0xD3D5, 0x8880,
+	0xD3D6, 0x8871, 0xD3D7, 0x887F, 0xD3D8, 0x886F, 0xD3D9, 0x8883,
+	0xD3DA, 0x887E, 0xD3DB, 0x8874, 0xD3DC, 0x887C, 0xD3DD, 0x8A12,
+	0xD3DE, 0x8C47, 0xD3DF, 0x8C57, 0xD3E0, 0x8C7B, 0xD3E1, 0x8CA4,
+	0xD3E2, 0x8CA3, 0xD3E3, 0x8D76, 0xD3E4, 0x8D78, 0xD3E5, 0x8DB5,
+	0xD3E6, 0x8DB7, 0xD3E7, 0x8DB6, 0xD3E8, 0x8ED1, 0xD3E9, 0x8ED3,
+	0xD3EA, 0x8FFE, 0xD3EB, 0x8FF5, 0xD3EC, 0x9002, 0xD3ED, 0x8FFF,
+	0xD3EE, 0x8FFB, 0xD3EF, 0x9004, 0xD3F0, 0x8FFC, 0xD3F1, 0x8FF6,
+	0xD3F2, 0x90D6, 0xD3F3, 0x90E0, 0xD3F4, 0x90D9, 0xD3F5, 0x90DA,
+	0xD3F6, 0x90E3, 0xD3F7, 0x90DF, 0xD3F8, 0x90E5, 0xD3F9, 0x90D8,
+	0xD3FA, 0x90DB, 0xD3FB, 0x90D7, 0xD3FC, 0x90DC, 0xD3FD, 0x90E4,
+	0xD3FE, 0x9150, 0xD440, 0x914E, 0xD441, 0x914F, 0xD442, 0x91D5,
+	0xD443, 0x91E2, 0xD444, 0x91DA, 0xD445, 0x965C, 0xD446, 0x965F,
+	0xD447, 0x96BC, 0xD448, 0x98E3, 0xD449, 0x9ADF, 0xD44A, 0x9B2F,
+	0xD44B, 0x4E7F, 0xD44C, 0x5070, 0xD44D, 0x506A, 0xD44E, 0x5061,
+	0xD44F, 0x505E, 0xD450, 0x5060, 0xD451, 0x5053, 0xD452, 0x504B,
+	0xD453, 0x505D, 0xD454, 0x5072, 0xD455, 0x5048, 0xD456, 0x504D,
+	0xD457, 0x5041, 0xD458, 0x505B, 0xD459, 0x504A, 0xD45A, 0x5062,
+	0xD45B, 0x5015, 0xD45C, 0x5045, 0xD45D, 0x505F, 0xD45E, 0x5069,
+	0xD45F, 0x506B, 0xD460, 0x5063, 0xD461, 0x5064, 0xD462, 0x5046,
+	0xD463, 0x5040, 0xD464, 0x506E, 0xD465, 0x5073, 0xD466, 0x5057,
+	0xD467, 0x5051, 0xD468, 0x51D0, 0xD469, 0x526B, 0xD46A, 0x526D,
+	0xD46B, 0x526C, 0xD46C, 0x526E, 0xD46D, 0x52D6, 0xD46E, 0x52D3,
+	0xD46F, 0x532D, 0xD470, 0x539C, 0xD471, 0x5575, 0xD472, 0x5576,
+	0xD473, 0x553C, 0xD474, 0x554D, 0xD475, 0x5550, 0xD476, 0x5534,
+	0xD477, 0x552A, 0xD478, 0x5551, 0xD479, 0x5562, 0xD47A, 0x5536,
+	0xD47B, 0x5535, 0xD47C, 0x5530, 0xD47D, 0x5552, 0xD47E, 0x5545,
+	0xD4A1, 0x550C, 0xD4A2, 0x5532, 0xD4A3, 0x5565, 0xD4A4, 0x554E,
+	0xD4A5, 0x5539, 0xD4A6, 0x5548, 0xD4A7, 0x552D, 0xD4A8, 0x553B,
+	0xD4A9, 0x5540, 0xD4AA, 0x554B, 0xD4AB, 0x570A, 0xD4AC, 0x5707,
+	0xD4AD, 0x57FB, 0xD4AE, 0x5814, 0xD4AF, 0x57E2, 0xD4B0, 0x57F6,
+	0xD4B1, 0x57DC, 0xD4B2, 0x57F4, 0xD4B3, 0x5800, 0xD4B4, 0x57ED,
+	0xD4B5, 0x57FD, 0xD4B6, 0x5808, 0xD4B7, 0x57F8, 0xD4B8, 0x580B,
+	0xD4B9, 0x57F3, 0xD4BA, 0x57CF, 0xD4BB, 0x5807, 0xD4BC, 0x57EE,
+	0xD4BD, 0x57E3, 0xD4BE, 0x57F2, 0xD4BF, 0x57E5, 0xD4C0, 0x57EC,
+	0xD4C1, 0x57E1, 0xD4C2, 0x580E, 0xD4C3, 0x57FC, 0xD4C4, 0x5810,
+	0xD4C5, 0x57E7, 0xD4C6, 0x5801, 0xD4C7, 0x580C, 0xD4C8, 0x57F1,
+	0xD4C9, 0x57E9, 0xD4CA, 0x57F0, 0xD4CB, 0x580D, 0xD4CC, 0x5804,
+	0xD4CD, 0x595C, 0xD4CE, 0x5A60, 0xD4CF, 0x5A58, 0xD4D0, 0x5A55,
+	0xD4D1, 0x5A67, 0xD4D2, 0x5A5E, 0xD4D3, 0x5A38, 0xD4D4, 0x5A35,
+	0xD4D5, 0x5A6D, 0xD4D6, 0x5A50, 0xD4D7, 0x5A5F, 0xD4D8, 0x5A65,
+	0xD4D9, 0x5A6C, 0xD4DA, 0x5A53, 0xD4DB, 0x5A64, 0xD4DC, 0x5A57,
+	0xD4DD, 0x5A43, 0xD4DE, 0x5A5D, 0xD4DF, 0x5A52, 0xD4E0, 0x5A44,
+	0xD4E1, 0x5A5B, 0xD4E2, 0x5A48, 0xD4E3, 0x5A8E, 0xD4E4, 0x5A3E,
+	0xD4E5, 0x5A4D, 0xD4E6, 0x5A39, 0xD4E7, 0x5A4C, 0xD4E8, 0x5A70,
+	0xD4E9, 0x5A69, 0xD4EA, 0x5A47, 0xD4EB, 0x5A51, 0xD4EC, 0x5A56,
+	0xD4ED, 0x5A42, 0xD4EE, 0x5A5C, 0xD4EF, 0x5B72, 0xD4F0, 0x5B6E,
+	0xD4F1, 0x5BC1, 0xD4F2, 0x5BC0, 0xD4F3, 0x5C59, 0xD4F4, 0x5D1E,
+	0xD4F5, 0x5D0B, 0xD4F6, 0x5D1D, 0xD4F7, 0x5D1A, 0xD4F8, 0x5D20,
+	0xD4F9, 0x5D0C, 0xD4FA, 0x5D28, 0xD4FB, 0x5D0D, 0xD4FC, 0x5D26,
+	0xD4FD, 0x5D25, 0xD4FE, 0x5D0F, 0xD540, 0x5D30, 0xD541, 0x5D12,
+	0xD542, 0x5D23, 0xD543, 0x5D1F, 0xD544, 0x5D2E, 0xD545, 0x5E3E,
+	0xD546, 0x5E34, 0xD547, 0x5EB1, 0xD548, 0x5EB4, 0xD549, 0x5EB9,
+	0xD54A, 0x5EB2, 0xD54B, 0x5EB3, 0xD54C, 0x5F36, 0xD54D, 0x5F38,
+	0xD54E, 0x5F9B, 0xD54F, 0x5F96, 0xD550, 0x5F9F, 0xD551, 0x608A,
+	0xD552, 0x6090, 0xD553, 0x6086, 0xD554, 0x60BE, 0xD555, 0x60B0,
+	0xD556, 0x60BA, 0xD557, 0x60D3, 0xD558, 0x60D4, 0xD559, 0x60CF,
+	0xD55A, 0x60E4, 0xD55B, 0x60D9, 0xD55C, 0x60DD, 0xD55D, 0x60C8,
+	0xD55E, 0x60B1, 0xD55F, 0x60DB, 0xD560, 0x60B7, 0xD561, 0x60CA,
+	0xD562, 0x60BF, 0xD563, 0x60C3, 0xD564, 0x60CD, 0xD565, 0x60C0,
+	0xD566, 0x6332, 0xD567, 0x6365, 0xD568, 0x638A, 0xD569, 0x6382,
+	0xD56A, 0x637D, 0xD56B, 0x63BD, 0xD56C, 0x639E, 0xD56D, 0x63AD,
+	0xD56E, 0x639D, 0xD56F, 0x6397, 0xD570, 0x63AB, 0xD571, 0x638E,
+	0xD572, 0x636F, 0xD573, 0x6387, 0xD574, 0x6390, 0xD575, 0x636E,
+	0xD576, 0x63AF, 0xD577, 0x6375, 0xD578, 0x639C, 0xD579, 0x636D,
+	0xD57A, 0x63AE, 0xD57B, 0x637C, 0xD57C, 0x63A4, 0xD57D, 0x633B,
+	0xD57E, 0x639F, 0xD5A1, 0x6378, 0xD5A2, 0x6385, 0xD5A3, 0x6381,
+	0xD5A4, 0x6391, 0xD5A5, 0x638D, 0xD5A6, 0x6370, 0xD5A7, 0x6553,
+	0xD5A8, 0x65CD, 0xD5A9, 0x6665, 0xD5AA, 0x6661, 0xD5AB, 0x665B,
+	0xD5AC, 0x6659, 0xD5AD, 0x665C, 0xD5AE, 0x6662, 0xD5AF, 0x6718,
+	0xD5B0, 0x6879, 0xD5B1, 0x6887, 0xD5B2, 0x6890, 0xD5B3, 0x689C,
+	0xD5B4, 0x686D, 0xD5B5, 0x686E, 0xD5B6, 0x68AE, 0xD5B7, 0x68AB,
+	0xD5B8, 0x6956, 0xD5B9, 0x686F, 0xD5BA, 0x68A3, 0xD5BB, 0x68AC,
+	0xD5BC, 0x68A9, 0xD5BD, 0x6875, 0xD5BE, 0x6874, 0xD5BF, 0x68B2,
+	0xD5C0, 0x688F, 0xD5C1, 0x6877, 0xD5C2, 0x6892, 0xD5C3, 0x687C,
+	0xD5C4, 0x686B, 0xD5C5, 0x6872, 0xD5C6, 0x68AA, 0xD5C7, 0x6880,
+	0xD5C8, 0x6871, 0xD5C9, 0x687E, 0xD5CA, 0x689B, 0xD5CB, 0x6896,
+	0xD5CC, 0x688B, 0xD5CD, 0x68A0, 0xD5CE, 0x6889, 0xD5CF, 0x68A4,
+	0xD5D0, 0x6878, 0xD5D1, 0x687B, 0xD5D2, 0x6891, 0xD5D3, 0x688C,
+	0xD5D4, 0x688A, 0xD5D5, 0x687D, 0xD5D6, 0x6B36, 0xD5D7, 0x6B33,
+	0xD5D8, 0x6B37, 0xD5D9, 0x6B38, 0xD5DA, 0x6B91, 0xD5DB, 0x6B8F,
+	0xD5DC, 0x6B8D, 0xD5DD, 0x6B8E, 0xD5DE, 0x6B8C, 0xD5DF, 0x6C2A,
+	0xD5E0, 0x6DC0, 0xD5E1, 0x6DAB, 0xD5E2, 0x6DB4, 0xD5E3, 0x6DB3,
+	0xD5E4, 0x6E74, 0xD5E5, 0x6DAC, 0xD5E6, 0x6DE9, 0xD5E7, 0x6DE2,
+	0xD5E8, 0x6DB7, 0xD5E9, 0x6DF6, 0xD5EA, 0x6DD4, 0xD5EB, 0x6E00,
+	0xD5EC, 0x6DC8, 0xD5ED, 0x6DE0, 0xD5EE, 0x6DDF, 0xD5EF, 0x6DD6,
+	0xD5F0, 0x6DBE, 0xD5F1, 0x6DE5, 0xD5F2, 0x6DDC, 0xD5F3, 0x6DDD,
+	0xD5F4, 0x6DDB, 0xD5F5, 0x6DF4, 0xD5F6, 0x6DCA, 0xD5F7, 0x6DBD,
+	0xD5F8, 0x6DED, 0xD5F9, 0x6DF0, 0xD5FA, 0x6DBA, 0xD5FB, 0x6DD5,
+	0xD5FC, 0x6DC2, 0xD5FD, 0x6DCF, 0xD5FE, 0x6DC9, 0xD640, 0x6DD0,
+	0xD641, 0x6DF2, 0xD642, 0x6DD3, 0xD643, 0x6DFD, 0xD644, 0x6DD7,
+	0xD645, 0x6DCD, 0xD646, 0x6DE3, 0xD647, 0x6DBB, 0xD648, 0x70FA,
+	0xD649, 0x710D, 0xD64A, 0x70F7, 0xD64B, 0x7117, 0xD64C, 0x70F4,
+	0xD64D, 0x710C, 0xD64E, 0x70F0, 0xD64F, 0x7104, 0xD650, 0x70F3,
+	0xD651, 0x7110, 0xD652, 0x70FC, 0xD653, 0x70FF, 0xD654, 0x7106,
+	0xD655, 0x7113, 0xD656, 0x7100, 0xD657, 0x70F8, 0xD658, 0x70F6,
+	0xD659, 0x710B, 0xD65A, 0x7102, 0xD65B, 0x710E, 0xD65C, 0x727E,
+	0xD65D, 0x727B, 0xD65E, 0x727C, 0xD65F, 0x727F, 0xD660, 0x731D,
+	0xD661, 0x7317, 0xD662, 0x7307, 0xD663, 0x7311, 0xD664, 0x7318,
+	0xD665, 0x730A, 0xD666, 0x7308, 0xD667, 0x72FF, 0xD668, 0x730F,
+	0xD669, 0x731E, 0xD66A, 0x7388, 0xD66B, 0x73F6, 0xD66C, 0x73F8,
+	0xD66D, 0x73F5, 0xD66E, 0x7404, 0xD66F, 0x7401, 0xD670, 0x73FD,
+	0xD671, 0x7407, 0xD672, 0x7400, 0xD673, 0x73FA, 0xD674, 0x73FC,
+	0xD675, 0x73FF, 0xD676, 0x740C, 0xD677, 0x740B, 0xD678, 0x73F4,
+	0xD679, 0x7408, 0xD67A, 0x7564, 0xD67B, 0x7563, 0xD67C, 0x75CE,
+	0xD67D, 0x75D2, 0xD67E, 0x75CF, 0xD6A1, 0x75CB, 0xD6A2, 0x75CC,
+	0xD6A3, 0x75D1, 0xD6A4, 0x75D0, 0xD6A5, 0x768F, 0xD6A6, 0x7689,
+	0xD6A7, 0x76D3, 0xD6A8, 0x7739, 0xD6A9, 0x772F, 0xD6AA, 0x772D,
+	0xD6AB, 0x7731, 0xD6AC, 0x7732, 0xD6AD, 0x7734, 0xD6AE, 0x7733,
+	0xD6AF, 0x773D, 0xD6B0, 0x7725, 0xD6B1, 0x773B, 0xD6B2, 0x7735,
+	0xD6B3, 0x7848, 0xD6B4, 0x7852, 0xD6B5, 0x7849, 0xD6B6, 0x784D,
+	0xD6B7, 0x784A, 0xD6B8, 0x784C, 0xD6B9, 0x7826, 0xD6BA, 0x7845,
+	0xD6BB, 0x7850, 0xD6BC, 0x7964, 0xD6BD, 0x7967, 0xD6BE, 0x7969,
+	0xD6BF, 0x796A, 0xD6C0, 0x7963, 0xD6C1, 0x796B, 0xD6C2, 0x7961,
+	0xD6C3, 0x79BB, 0xD6C4, 0x79FA, 0xD6C5, 0x79F8, 0xD6C6, 0x79F6,
+	0xD6C7, 0x79F7, 0xD6C8, 0x7A8F, 0xD6C9, 0x7A94, 0xD6CA, 0x7A90,
+	0xD6CB, 0x7B35, 0xD6CC, 0x7B47, 0xD6CD, 0x7B34, 0xD6CE, 0x7B25,
+	0xD6CF, 0x7B30, 0xD6D0, 0x7B22, 0xD6D1, 0x7B24, 0xD6D2, 0x7B33,
+	0xD6D3, 0x7B18, 0xD6D4, 0x7B2A, 0xD6D5, 0x7B1D, 0xD6D6, 0x7B31,
+	0xD6D7, 0x7B2B, 0xD6D8, 0x7B2D, 0xD6D9, 0x7B2F, 0xD6DA, 0x7B32,
+	0xD6DB, 0x7B38, 0xD6DC, 0x7B1A, 0xD6DD, 0x7B23, 0xD6DE, 0x7C94,
+	0xD6DF, 0x7C98, 0xD6E0, 0x7C96, 0xD6E1, 0x7CA3, 0xD6E2, 0x7D35,
+	0xD6E3, 0x7D3D, 0xD6E4, 0x7D38, 0xD6E5, 0x7D36, 0xD6E6, 0x7D3A,
+	0xD6E7, 0x7D45, 0xD6E8, 0x7D2C, 0xD6E9, 0x7D29, 0xD6EA, 0x7D41,
+	0xD6EB, 0x7D47, 0xD6EC, 0x7D3E, 0xD6ED, 0x7D3F, 0xD6EE, 0x7D4A,
+	0xD6EF, 0x7D3B, 0xD6F0, 0x7D28, 0xD6F1, 0x7F63, 0xD6F2, 0x7F95,
+	0xD6F3, 0x7F9C, 0xD6F4, 0x7F9D, 0xD6F5, 0x7F9B, 0xD6F6, 0x7FCA,
+	0xD6F7, 0x7FCB, 0xD6F8, 0x7FCD, 0xD6F9, 0x7FD0, 0xD6FA, 0x7FD1,
+	0xD6FB, 0x7FC7, 0xD6FC, 0x7FCF, 0xD6FD, 0x7FC9, 0xD6FE, 0x801F,
+	0xD740, 0x801E, 0xD741, 0x801B, 0xD742, 0x8047, 0xD743, 0x8043,
+	0xD744, 0x8048, 0xD745, 0x8118, 0xD746, 0x8125, 0xD747, 0x8119,
+	0xD748, 0x811B, 0xD749, 0x812D, 0xD74A, 0x811F, 0xD74B, 0x812C,
+	0xD74C, 0x811E, 0xD74D, 0x8121, 0xD74E, 0x8115, 0xD74F, 0x8127,
+	0xD750, 0x811D, 0xD751, 0x8122, 0xD752, 0x8211, 0xD753, 0x8238,
+	0xD754, 0x8233, 0xD755, 0x823A, 0xD756, 0x8234, 0xD757, 0x8232,
+	0xD758, 0x8274, 0xD759, 0x8390, 0xD75A, 0x83A3, 0xD75B, 0x83A8,
+	0xD75C, 0x838D, 0xD75D, 0x837A, 0xD75E, 0x8373, 0xD75F, 0x83A4,
+	0xD760, 0x8374, 0xD761, 0x838F, 0xD762, 0x8381, 0xD763, 0x8395,
+	0xD764, 0x8399, 0xD765, 0x8375, 0xD766, 0x8394, 0xD767, 0x83A9,
+	0xD768, 0x837D, 0xD769, 0x8383, 0xD76A, 0x838C, 0xD76B, 0x839D,
+	0xD76C, 0x839B, 0xD76D, 0x83AA, 0xD76E, 0x838B, 0xD76F, 0x837E,
+	0xD770, 0x83A5, 0xD771, 0x83AF, 0xD772, 0x8388, 0xD773, 0x8397,
+	0xD774, 0x83B0, 0xD775, 0x837F, 0xD776, 0x83A6, 0xD777, 0x8387,
+	0xD778, 0x83AE, 0xD779, 0x8376, 0xD77A, 0x839A, 0xD77B, 0x8659,
+	0xD77C, 0x8656, 0xD77D, 0x86BF, 0xD77E, 0x86B7, 0xD7A1, 0x86C2,
+	0xD7A2, 0x86C1, 0xD7A3, 0x86C5, 0xD7A4, 0x86BA, 0xD7A5, 0x86B0,
+	0xD7A6, 0x86C8, 0xD7A7, 0x86B9, 0xD7A8, 0x86B3, 0xD7A9, 0x86B8,
+	0xD7AA, 0x86CC, 0xD7AB, 0x86B4, 0xD7AC, 0x86BB, 0xD7AD, 0x86BC,
+	0xD7AE, 0x86C3, 0xD7AF, 0x86BD, 0xD7B0, 0x86BE, 0xD7B1, 0x8852,
+	0xD7B2, 0x8889, 0xD7B3, 0x8895, 0xD7B4, 0x88A8, 0xD7B5, 0x88A2,
+	0xD7B6, 0x88AA, 0xD7B7, 0x889A, 0xD7B8, 0x8891, 0xD7B9, 0x88A1,
+	0xD7BA, 0x889F, 0xD7BB, 0x8898, 0xD7BC, 0x88A7, 0xD7BD, 0x8899,
+	0xD7BE, 0x889B, 0xD7BF, 0x8897, 0xD7C0, 0x88A4, 0xD7C1, 0x88AC,
+	0xD7C2, 0x888C, 0xD7C3, 0x8893, 0xD7C4, 0x888E, 0xD7C5, 0x8982,
+	0xD7C6, 0x89D6, 0xD7C7, 0x89D9, 0xD7C8, 0x89D5, 0xD7C9, 0x8A30,
+	0xD7CA, 0x8A27, 0xD7CB, 0x8A2C, 0xD7CC, 0x8A1E, 0xD7CD, 0x8C39,
+	0xD7CE, 0x8C3B, 0xD7CF, 0x8C5C, 0xD7D0, 0x8C5D, 0xD7D1, 0x8C7D,
+	0xD7D2, 0x8CA5, 0xD7D3, 0x8D7D, 0xD7D4, 0x8D7B, 0xD7D5, 0x8D79,
+	0xD7D6, 0x8DBC, 0xD7D7, 0x8DC2, 0xD7D8, 0x8DB9, 0xD7D9, 0x8DBF,
+	0xD7DA, 0x8DC1, 0xD7DB, 0x8ED8, 0xD7DC, 0x8EDE, 0xD7DD, 0x8EDD,
+	0xD7DE, 0x8EDC, 0xD7DF, 0x8ED7, 0xD7E0, 0x8EE0, 0xD7E1, 0x8EE1,
+	0xD7E2, 0x9024, 0xD7E3, 0x900B, 0xD7E4, 0x9011, 0xD7E5, 0x901C,
+	0xD7E6, 0x900C, 0xD7E7, 0x9021, 0xD7E8, 0x90EF, 0xD7E9, 0x90EA,
+	0xD7EA, 0x90F0, 0xD7EB, 0x90F4, 0xD7EC, 0x90F2, 0xD7ED, 0x90F3,
+	0xD7EE, 0x90D4, 0xD7EF, 0x90EB, 0xD7F0, 0x90EC, 0xD7F1, 0x90E9,
+	0xD7F2, 0x9156, 0xD7F3, 0x9158, 0xD7F4, 0x915A, 0xD7F5, 0x9153,
+	0xD7F6, 0x9155, 0xD7F7, 0x91EC, 0xD7F8, 0x91F4, 0xD7F9, 0x91F1,
+	0xD7FA, 0x91F3, 0xD7FB, 0x91F8, 0xD7FC, 0x91E4, 0xD7FD, 0x91F9,
+	0xD7FE, 0x91EA, 0xD840, 0x91EB, 0xD841, 0x91F7, 0xD842, 0x91E8,
+	0xD843, 0x91EE, 0xD844, 0x957A, 0xD845, 0x9586, 0xD846, 0x9588,
+	0xD847, 0x967C, 0xD848, 0x966D, 0xD849, 0x966B, 0xD84A, 0x9671,
+	0xD84B, 0x966F, 0xD84C, 0x96BF, 0xD84D, 0x976A, 0xD84E, 0x9804,
+	0xD84F, 0x98E5, 0xD850, 0x9997, 0xD851, 0x509B, 0xD852, 0x5095,
+	0xD853, 0x5094, 0xD854, 0x509E, 0xD855, 0x508B, 0xD856, 0x50A3,
+	0xD857, 0x5083, 0xD858, 0x508C, 0xD859, 0x508E, 0xD85A, 0x509D,
+	0xD85B, 0x5068, 0xD85C, 0x509C, 0xD85D, 0x5092, 0xD85E, 0x5082,
+	0xD85F, 0x5087, 0xD860, 0x515F, 0xD861, 0x51D4, 0xD862, 0x5312,
+	0xD863, 0x5311, 0xD864, 0x53A4, 0xD865, 0x53A7, 0xD866, 0x5591,
+	0xD867, 0x55A8, 0xD868, 0x55A5, 0xD869, 0x55AD, 0xD86A, 0x5577,
+	0xD86B, 0x5645, 0xD86C, 0x55A2, 0xD86D, 0x5593, 0xD86E, 0x5588,
+	0xD86F, 0x558F, 0xD870, 0x55B5, 0xD871, 0x5581, 0xD872, 0x55A3,
+	0xD873, 0x5592, 0xD874, 0x55A4, 0xD875, 0x557D, 0xD876, 0x558C,
+	0xD877, 0x55A6, 0xD878, 0x557F, 0xD879, 0x5595, 0xD87A, 0x55A1,
+	0xD87B, 0x558E, 0xD87C, 0x570C, 0xD87D, 0x5829, 0xD87E, 0x5837,
+	0xD8A1, 0x5819, 0xD8A2, 0x581E, 0xD8A3, 0x5827, 0xD8A4, 0x5823,
+	0xD8A5, 0x5828, 0xD8A6, 0x57F5, 0xD8A7, 0x5848, 0xD8A8, 0x5825,
+	0xD8A9, 0x581C, 0xD8AA, 0x581B, 0xD8AB, 0x5833, 0xD8AC, 0x583F,
+	0xD8AD, 0x5836, 0xD8AE, 0x582E, 0xD8AF, 0x5839, 0xD8B0, 0x5838,
+	0xD8B1, 0x582D, 0xD8B2, 0x582C, 0xD8B3, 0x583B, 0xD8B4, 0x5961,
+	0xD8B5, 0x5AAF, 0xD8B6, 0x5A94, 0xD8B7, 0x5A9F, 0xD8B8, 0x5A7A,
+	0xD8B9, 0x5AA2, 0xD8BA, 0x5A9E, 0xD8BB, 0x5A78, 0xD8BC, 0x5AA6,
+	0xD8BD, 0x5A7C, 0xD8BE, 0x5AA5, 0xD8BF, 0x5AAC, 0xD8C0, 0x5A95,
+	0xD8C1, 0x5AAE, 0xD8C2, 0x5A37, 0xD8C3, 0x5A84, 0xD8C4, 0x5A8A,
+	0xD8C5, 0x5A97, 0xD8C6, 0x5A83, 0xD8C7, 0x5A8B, 0xD8C8, 0x5AA9,
+	0xD8C9, 0x5A7B, 0xD8CA, 0x5A7D, 0xD8CB, 0x5A8C, 0xD8CC, 0x5A9C,
+	0xD8CD, 0x5A8F, 0xD8CE, 0x5A93, 0xD8CF, 0x5A9D, 0xD8D0, 0x5BEA,
+	0xD8D1, 0x5BCD, 0xD8D2, 0x5BCB, 0xD8D3, 0x5BD4, 0xD8D4, 0x5BD1,
+	0xD8D5, 0x5BCA, 0xD8D6, 0x5BCE, 0xD8D7, 0x5C0C, 0xD8D8, 0x5C30,
+	0xD8D9, 0x5D37, 0xD8DA, 0x5D43, 0xD8DB, 0x5D6B, 0xD8DC, 0x5D41,
+	0xD8DD, 0x5D4B, 0xD8DE, 0x5D3F, 0xD8DF, 0x5D35, 0xD8E0, 0x5D51,
+	0xD8E1, 0x5D4E, 0xD8E2, 0x5D55, 0xD8E3, 0x5D33, 0xD8E4, 0x5D3A,
+	0xD8E5, 0x5D52, 0xD8E6, 0x5D3D, 0xD8E7, 0x5D31, 0xD8E8, 0x5D59,
+	0xD8E9, 0x5D42, 0xD8EA, 0x5D39, 0xD8EB, 0x5D49, 0xD8EC, 0x5D38,
+	0xD8ED, 0x5D3C, 0xD8EE, 0x5D32, 0xD8EF, 0x5D36, 0xD8F0, 0x5D40,
+	0xD8F1, 0x5D45, 0xD8F2, 0x5E44, 0xD8F3, 0x5E41, 0xD8F4, 0x5F58,
+	0xD8F5, 0x5FA6, 0xD8F6, 0x5FA5, 0xD8F7, 0x5FAB, 0xD8F8, 0x60C9,
+	0xD8F9, 0x60B9, 0xD8FA, 0x60CC, 0xD8FB, 0x60E2, 0xD8FC, 0x60CE,
+	0xD8FD, 0x60C4, 0xD8FE, 0x6114, 0xD940, 0x60F2, 0xD941, 0x610A,
+	0xD942, 0x6116, 0xD943, 0x6105, 0xD944, 0x60F5, 0xD945, 0x6113,
+	0xD946, 0x60F8, 0xD947, 0x60FC, 0xD948, 0x60FE, 0xD949, 0x60C1,
+	0xD94A, 0x6103, 0xD94B, 0x6118, 0xD94C, 0x611D, 0xD94D, 0x6110,
+	0xD94E, 0x60FF, 0xD94F, 0x6104, 0xD950, 0x610B, 0xD951, 0x624A,
+	0xD952, 0x6394, 0xD953, 0x63B1, 0xD954, 0x63B0, 0xD955, 0x63CE,
+	0xD956, 0x63E5, 0xD957, 0x63E8, 0xD958, 0x63EF, 0xD959, 0x63C3,
+	0xD95A, 0x649D, 0xD95B, 0x63F3, 0xD95C, 0x63CA, 0xD95D, 0x63E0,
+	0xD95E, 0x63F6, 0xD95F, 0x63D5, 0xD960, 0x63F2, 0xD961, 0x63F5,
+	0xD962, 0x6461, 0xD963, 0x63DF, 0xD964, 0x63BE, 0xD965, 0x63DD,
+	0xD966, 0x63DC, 0xD967, 0x63C4, 0xD968, 0x63D8, 0xD969, 0x63D3,
+	0xD96A, 0x63C2, 0xD96B, 0x63C7, 0xD96C, 0x63CC, 0xD96D, 0x63CB,
+	0xD96E, 0x63C8, 0xD96F, 0x63F0, 0xD970, 0x63D7, 0xD971, 0x63D9,
+	0xD972, 0x6532, 0xD973, 0x6567, 0xD974, 0x656A, 0xD975, 0x6564,
+	0xD976, 0x655C, 0xD977, 0x6568, 0xD978, 0x6565, 0xD979, 0x658C,
+	0xD97A, 0x659D, 0xD97B, 0x659E, 0xD97C, 0x65AE, 0xD97D, 0x65D0,
+	0xD97E, 0x65D2, 0xD9A1, 0x667C, 0xD9A2, 0x666C, 0xD9A3, 0x667B,
+	0xD9A4, 0x6680, 0xD9A5, 0x6671, 0xD9A6, 0x6679, 0xD9A7, 0x666A,
+	0xD9A8, 0x6672, 0xD9A9, 0x6701, 0xD9AA, 0x690C, 0xD9AB, 0x68D3,
+	0xD9AC, 0x6904, 0xD9AD, 0x68DC, 0xD9AE, 0x692A, 0xD9AF, 0x68EC,
+	0xD9B0, 0x68EA, 0xD9B1, 0x68F1, 0xD9B2, 0x690F, 0xD9B3, 0x68D6,
+	0xD9B4, 0x68F7, 0xD9B5, 0x68EB, 0xD9B6, 0x68E4, 0xD9B7, 0x68F6,
+	0xD9B8, 0x6913, 0xD9B9, 0x6910, 0xD9BA, 0x68F3, 0xD9BB, 0x68E1,
+	0xD9BC, 0x6907, 0xD9BD, 0x68CC, 0xD9BE, 0x6908, 0xD9BF, 0x6970,
+	0xD9C0, 0x68B4, 0xD9C1, 0x6911, 0xD9C2, 0x68EF, 0xD9C3, 0x68C6,
+	0xD9C4, 0x6914, 0xD9C5, 0x68F8, 0xD9C6, 0x68D0, 0xD9C7, 0x68FD,
+	0xD9C8, 0x68FC, 0xD9C9, 0x68E8, 0xD9CA, 0x690B, 0xD9CB, 0x690A,
+	0xD9CC, 0x6917, 0xD9CD, 0x68CE, 0xD9CE, 0x68C8, 0xD9CF, 0x68DD,
+	0xD9D0, 0x68DE, 0xD9D1, 0x68E6, 0xD9D2, 0x68F4, 0xD9D3, 0x68D1,
+	0xD9D4, 0x6906, 0xD9D5, 0x68D4, 0xD9D6, 0x68E9, 0xD9D7, 0x6915,
+	0xD9D8, 0x6925, 0xD9D9, 0x68C7, 0xD9DA, 0x6B39, 0xD9DB, 0x6B3B,
+	0xD9DC, 0x6B3F, 0xD9DD, 0x6B3C, 0xD9DE, 0x6B94, 0xD9DF, 0x6B97,
+	0xD9E0, 0x6B99, 0xD9E1, 0x6B95, 0xD9E2, 0x6BBD, 0xD9E3, 0x6BF0,
+	0xD9E4, 0x6BF2, 0xD9E5, 0x6BF3, 0xD9E6, 0x6C30, 0xD9E7, 0x6DFC,
+	0xD9E8, 0x6E46, 0xD9E9, 0x6E47, 0xD9EA, 0x6E1F, 0xD9EB, 0x6E49,
+	0xD9EC, 0x6E88, 0xD9ED, 0x6E3C, 0xD9EE, 0x6E3D, 0xD9EF, 0x6E45,
+	0xD9F0, 0x6E62, 0xD9F1, 0x6E2B, 0xD9F2, 0x6E3F, 0xD9F3, 0x6E41,
+	0xD9F4, 0x6E5D, 0xD9F5, 0x6E73, 0xD9F6, 0x6E1C, 0xD9F7, 0x6E33,
+	0xD9F8, 0x6E4B, 0xD9F9, 0x6E40, 0xD9FA, 0x6E51, 0xD9FB, 0x6E3B,
+	0xD9FC, 0x6E03, 0xD9FD, 0x6E2E, 0xD9FE, 0x6E5E, 0xDA40, 0x6E68,
+	0xDA41, 0x6E5C, 0xDA42, 0x6E61, 0xDA43, 0x6E31, 0xDA44, 0x6E28,
+	0xDA45, 0x6E60, 0xDA46, 0x6E71, 0xDA47, 0x6E6B, 0xDA48, 0x6E39,
+	0xDA49, 0x6E22, 0xDA4A, 0x6E30, 0xDA4B, 0x6E53, 0xDA4C, 0x6E65,
+	0xDA4D, 0x6E27, 0xDA4E, 0x6E78, 0xDA4F, 0x6E64, 0xDA50, 0x6E77,
+	0xDA51, 0x6E55, 0xDA52, 0x6E79, 0xDA53, 0x6E52, 0xDA54, 0x6E66,
+	0xDA55, 0x6E35, 0xDA56, 0x6E36, 0xDA57, 0x6E5A, 0xDA58, 0x7120,
+	0xDA59, 0x711E, 0xDA5A, 0x712F, 0xDA5B, 0x70FB, 0xDA5C, 0x712E,
+	0xDA5D, 0x7131, 0xDA5E, 0x7123, 0xDA5F, 0x7125, 0xDA60, 0x7122,
+	0xDA61, 0x7132, 0xDA62, 0x711F, 0xDA63, 0x7128, 0xDA64, 0x713A,
+	0xDA65, 0x711B, 0xDA66, 0x724B, 0xDA67, 0x725A, 0xDA68, 0x7288,
+	0xDA69, 0x7289, 0xDA6A, 0x7286, 0xDA6B, 0x7285, 0xDA6C, 0x728B,
+	0xDA6D, 0x7312, 0xDA6E, 0x730B, 0xDA6F, 0x7330, 0xDA70, 0x7322,
+	0xDA71, 0x7331, 0xDA72, 0x7333, 0xDA73, 0x7327, 0xDA74, 0x7332,
+	0xDA75, 0x732D, 0xDA76, 0x7326, 0xDA77, 0x7323, 0xDA78, 0x7335,
+	0xDA79, 0x730C, 0xDA7A, 0x742E, 0xDA7B, 0x742C, 0xDA7C, 0x7430,
+	0xDA7D, 0x742B, 0xDA7E, 0x7416, 0xDAA1, 0x741A, 0xDAA2, 0x7421,
+	0xDAA3, 0x742D, 0xDAA4, 0x7431, 0xDAA5, 0x7424, 0xDAA6, 0x7423,
+	0xDAA7, 0x741D, 0xDAA8, 0x7429, 0xDAA9, 0x7420, 0xDAAA, 0x7432,
+	0xDAAB, 0x74FB, 0xDAAC, 0x752F, 0xDAAD, 0x756F, 0xDAAE, 0x756C,
+	0xDAAF, 0x75E7, 0xDAB0, 0x75DA, 0xDAB1, 0x75E1, 0xDAB2, 0x75E6,
+	0xDAB3, 0x75DD, 0xDAB4, 0x75DF, 0xDAB5, 0x75E4, 0xDAB6, 0x75D7,
+	0xDAB7, 0x7695, 0xDAB8, 0x7692, 0xDAB9, 0x76DA, 0xDABA, 0x7746,
+	0xDABB, 0x7747, 0xDABC, 0x7744, 0xDABD, 0x774D, 0xDABE, 0x7745,
+	0xDABF, 0x774A, 0xDAC0, 0x774E, 0xDAC1, 0x774B, 0xDAC2, 0x774C,
+	0xDAC3, 0x77DE, 0xDAC4, 0x77EC, 0xDAC5, 0x7860, 0xDAC6, 0x7864,
+	0xDAC7, 0x7865, 0xDAC8, 0x785C, 0xDAC9, 0x786D, 0xDACA, 0x7871,
+	0xDACB, 0x786A, 0xDACC, 0x786E, 0xDACD, 0x7870, 0xDACE, 0x7869,
+	0xDACF, 0x7868, 0xDAD0, 0x785E, 0xDAD1, 0x7862, 0xDAD2, 0x7974,
+	0xDAD3, 0x7973, 0xDAD4, 0x7972, 0xDAD5, 0x7970, 0xDAD6, 0x7A02,
+	0xDAD7, 0x7A0A, 0xDAD8, 0x7A03, 0xDAD9, 0x7A0C, 0xDADA, 0x7A04,
+	0xDADB, 0x7A99, 0xDADC, 0x7AE6, 0xDADD, 0x7AE4, 0xDADE, 0x7B4A,
+	0xDADF, 0x7B3B, 0xDAE0, 0x7B44, 0xDAE1, 0x7B48, 0xDAE2, 0x7B4C,
+	0xDAE3, 0x7B4E, 0xDAE4, 0x7B40, 0xDAE5, 0x7B58, 0xDAE6, 0x7B45,
+	0xDAE7, 0x7CA2, 0xDAE8, 0x7C9E, 0xDAE9, 0x7CA8, 0xDAEA, 0x7CA1,
+	0xDAEB, 0x7D58, 0xDAEC, 0x7D6F, 0xDAED, 0x7D63, 0xDAEE, 0x7D53,
+	0xDAEF, 0x7D56, 0xDAF0, 0x7D67, 0xDAF1, 0x7D6A, 0xDAF2, 0x7D4F,
+	0xDAF3, 0x7D6D, 0xDAF4, 0x7D5C, 0xDAF5, 0x7D6B, 0xDAF6, 0x7D52,
+	0xDAF7, 0x7D54, 0xDAF8, 0x7D69, 0xDAF9, 0x7D51, 0xDAFA, 0x7D5F,
+	0xDAFB, 0x7D4E, 0xDAFC, 0x7F3E, 0xDAFD, 0x7F3F, 0xDAFE, 0x7F65,
+	0xDB40, 0x7F66, 0xDB41, 0x7FA2, 0xDB42, 0x7FA0, 0xDB43, 0x7FA1,
+	0xDB44, 0x7FD7, 0xDB45, 0x8051, 0xDB46, 0x804F, 0xDB47, 0x8050,
+	0xDB48, 0x80FE, 0xDB49, 0x80D4, 0xDB4A, 0x8143, 0xDB4B, 0x814A,
+	0xDB4C, 0x8152, 0xDB4D, 0x814F, 0xDB4E, 0x8147, 0xDB4F, 0x813D,
+	0xDB50, 0x814D, 0xDB51, 0x813A, 0xDB52, 0x81E6, 0xDB53, 0x81EE,
+	0xDB54, 0x81F7, 0xDB55, 0x81F8, 0xDB56, 0x81F9, 0xDB57, 0x8204,
+	0xDB58, 0x823C, 0xDB59, 0x823D, 0xDB5A, 0x823F, 0xDB5B, 0x8275,
+	0xDB5C, 0x833B, 0xDB5D, 0x83CF, 0xDB5E, 0x83F9, 0xDB5F, 0x8423,
+	0xDB60, 0x83C0, 0xDB61, 0x83E8, 0xDB62, 0x8412, 0xDB63, 0x83E7,
+	0xDB64, 0x83E4, 0xDB65, 0x83FC, 0xDB66, 0x83F6, 0xDB67, 0x8410,
+	0xDB68, 0x83C6, 0xDB69, 0x83C8, 0xDB6A, 0x83EB, 0xDB6B, 0x83E3,
+	0xDB6C, 0x83BF, 0xDB6D, 0x8401, 0xDB6E, 0x83DD, 0xDB6F, 0x83E5,
+	0xDB70, 0x83D8, 0xDB71, 0x83FF, 0xDB72, 0x83E1, 0xDB73, 0x83CB,
+	0xDB74, 0x83CE, 0xDB75, 0x83D6, 0xDB76, 0x83F5, 0xDB77, 0x83C9,
+	0xDB78, 0x8409, 0xDB79, 0x840F, 0xDB7A, 0x83DE, 0xDB7B, 0x8411,
+	0xDB7C, 0x8406, 0xDB7D, 0x83C2, 0xDB7E, 0x83F3, 0xDBA1, 0x83D5,
+	0xDBA2, 0x83FA, 0xDBA3, 0x83C7, 0xDBA4, 0x83D1, 0xDBA5, 0x83EA,
+	0xDBA6, 0x8413, 0xDBA7, 0x83C3, 0xDBA8, 0x83EC, 0xDBA9, 0x83EE,
+	0xDBAA, 0x83C4, 0xDBAB, 0x83FB, 0xDBAC, 0x83D7, 0xDBAD, 0x83E2,
+	0xDBAE, 0x841B, 0xDBAF, 0x83DB, 0xDBB0, 0x83FE, 0xDBB1, 0x86D8,
+	0xDBB2, 0x86E2, 0xDBB3, 0x86E6, 0xDBB4, 0x86D3, 0xDBB5, 0x86E3,
+	0xDBB6, 0x86DA, 0xDBB7, 0x86EA, 0xDBB8, 0x86DD, 0xDBB9, 0x86EB,
+	0xDBBA, 0x86DC, 0xDBBB, 0x86EC, 0xDBBC, 0x86E9, 0xDBBD, 0x86D7,
+	0xDBBE, 0x86E8, 0xDBBF, 0x86D1, 0xDBC0, 0x8848, 0xDBC1, 0x8856,
+	0xDBC2, 0x8855, 0xDBC3, 0x88BA, 0xDBC4, 0x88D7, 0xDBC5, 0x88B9,
+	0xDBC6, 0x88B8, 0xDBC7, 0x88C0, 0xDBC8, 0x88BE, 0xDBC9, 0x88B6,
+	0xDBCA, 0x88BC, 0xDBCB, 0x88B7, 0xDBCC, 0x88BD, 0xDBCD, 0x88B2,
+	0xDBCE, 0x8901, 0xDBCF, 0x88C9, 0xDBD0, 0x8995, 0xDBD1, 0x8998,
+	0xDBD2, 0x8997, 0xDBD3, 0x89DD, 0xDBD4, 0x89DA, 0xDBD5, 0x89DB,
+	0xDBD6, 0x8A4E, 0xDBD7, 0x8A4D, 0xDBD8, 0x8A39, 0xDBD9, 0x8A59,
+	0xDBDA, 0x8A40, 0xDBDB, 0x8A57, 0xDBDC, 0x8A58, 0xDBDD, 0x8A44,
+	0xDBDE, 0x8A45, 0xDBDF, 0x8A52, 0xDBE0, 0x8A48, 0xDBE1, 0x8A51,
+	0xDBE2, 0x8A4A, 0xDBE3, 0x8A4C, 0xDBE4, 0x8A4F, 0xDBE5, 0x8C5F,
+	0xDBE6, 0x8C81, 0xDBE7, 0x8C80, 0xDBE8, 0x8CBA, 0xDBE9, 0x8CBE,
+	0xDBEA, 0x8CB0, 0xDBEB, 0x8CB9, 0xDBEC, 0x8CB5, 0xDBED, 0x8D84,
+	0xDBEE, 0x8D80, 0xDBEF, 0x8D89, 0xDBF0, 0x8DD8, 0xDBF1, 0x8DD3,
+	0xDBF2, 0x8DCD, 0xDBF3, 0x8DC7, 0xDBF4, 0x8DD6, 0xDBF5, 0x8DDC,
+	0xDBF6, 0x8DCF, 0xDBF7, 0x8DD5, 0xDBF8, 0x8DD9, 0xDBF9, 0x8DC8,
+	0xDBFA, 0x8DD7, 0xDBFB, 0x8DC5, 0xDBFC, 0x8EEF, 0xDBFD, 0x8EF7,
+	0xDBFE, 0x8EFA, 0xDC40, 0x8EF9, 0xDC41, 0x8EE6, 0xDC42, 0x8EEE,
+	0xDC43, 0x8EE5, 0xDC44, 0x8EF5, 0xDC45, 0x8EE7, 0xDC46, 0x8EE8,
+	0xDC47, 0x8EF6, 0xDC48, 0x8EEB, 0xDC49, 0x8EF1, 0xDC4A, 0x8EEC,
+	0xDC4B, 0x8EF4, 0xDC4C, 0x8EE9, 0xDC4D, 0x902D, 0xDC4E, 0x9034,
+	0xDC4F, 0x902F, 0xDC50, 0x9106, 0xDC51, 0x912C, 0xDC52, 0x9104,
+	0xDC53, 0x90FF, 0xDC54, 0x90FC, 0xDC55, 0x9108, 0xDC56, 0x90F9,
+	0xDC57, 0x90FB, 0xDC58, 0x9101, 0xDC59, 0x9100, 0xDC5A, 0x9107,
+	0xDC5B, 0x9105, 0xDC5C, 0x9103, 0xDC5D, 0x9161, 0xDC5E, 0x9164,
+	0xDC5F, 0x915F, 0xDC60, 0x9162, 0xDC61, 0x9160, 0xDC62, 0x9201,
+	0xDC63, 0x920A, 0xDC64, 0x9225, 0xDC65, 0x9203, 0xDC66, 0x921A,
+	0xDC67, 0x9226, 0xDC68, 0x920F, 0xDC69, 0x920C, 0xDC6A, 0x9200,
+	0xDC6B, 0x9212, 0xDC6C, 0x91FF, 0xDC6D, 0x91FD, 0xDC6E, 0x9206,
+	0xDC6F, 0x9204, 0xDC70, 0x9227, 0xDC71, 0x9202, 0xDC72, 0x921C,
+	0xDC73, 0x9224, 0xDC74, 0x9219, 0xDC75, 0x9217, 0xDC76, 0x9205,
+	0xDC77, 0x9216, 0xDC78, 0x957B, 0xDC79, 0x958D, 0xDC7A, 0x958C,
+	0xDC7B, 0x9590, 0xDC7C, 0x9687, 0xDC7D, 0x967E, 0xDC7E, 0x9688,
+	0xDCA1, 0x9689, 0xDCA2, 0x9683, 0xDCA3, 0x9680, 0xDCA4, 0x96C2,
+	0xDCA5, 0x96C8, 0xDCA6, 0x96C3, 0xDCA7, 0x96F1, 0xDCA8, 0x96F0,
+	0xDCA9, 0x976C, 0xDCAA, 0x9770, 0xDCAB, 0x976E, 0xDCAC, 0x9807,
+	0xDCAD, 0x98A9, 0xDCAE, 0x98EB, 0xDCAF, 0x9CE6, 0xDCB0, 0x9EF9,
+	0xDCB1, 0x4E83, 0xDCB2, 0x4E84, 0xDCB3, 0x4EB6, 0xDCB4, 0x50BD,
+	0xDCB5, 0x50BF, 0xDCB6, 0x50C6, 0xDCB7, 0x50AE, 0xDCB8, 0x50C4,
+	0xDCB9, 0x50CA, 0xDCBA, 0x50B4, 0xDCBB, 0x50C8, 0xDCBC, 0x50C2,
+	0xDCBD, 0x50B0, 0xDCBE, 0x50C1, 0xDCBF, 0x50BA, 0xDCC0, 0x50B1,
+	0xDCC1, 0x50CB, 0xDCC2, 0x50C9, 0xDCC3, 0x50B6, 0xDCC4, 0x50B8,
+	0xDCC5, 0x51D7, 0xDCC6, 0x527A, 0xDCC7, 0x5278, 0xDCC8, 0x527B,
+	0xDCC9, 0x527C, 0xDCCA, 0x55C3, 0xDCCB, 0x55DB, 0xDCCC, 0x55CC,
+	0xDCCD, 0x55D0, 0xDCCE, 0x55CB, 0xDCCF, 0x55CA, 0xDCD0, 0x55DD,
+	0xDCD1, 0x55C0, 0xDCD2, 0x55D4, 0xDCD3, 0x55C4, 0xDCD4, 0x55E9,
+	0xDCD5, 0x55BF, 0xDCD6, 0x55D2, 0xDCD7, 0x558D, 0xDCD8, 0x55CF,
+	0xDCD9, 0x55D5, 0xDCDA, 0x55E2, 0xDCDB, 0x55D6, 0xDCDC, 0x55C8,
+	0xDCDD, 0x55F2, 0xDCDE, 0x55CD, 0xDCDF, 0x55D9, 0xDCE0, 0x55C2,
+	0xDCE1, 0x5714, 0xDCE2, 0x5853, 0xDCE3, 0x5868, 0xDCE4, 0x5864,
+	0xDCE5, 0x584F, 0xDCE6, 0x584D, 0xDCE7, 0x5849, 0xDCE8, 0x586F,
+	0xDCE9, 0x5855, 0xDCEA, 0x584E, 0xDCEB, 0x585D, 0xDCEC, 0x5859,
+	0xDCED, 0x5865, 0xDCEE, 0x585B, 0xDCEF, 0x583D, 0xDCF0, 0x5863,
+	0xDCF1, 0x5871, 0xDCF2, 0x58FC, 0xDCF3, 0x5AC7, 0xDCF4, 0x5AC4,
+	0xDCF5, 0x5ACB, 0xDCF6, 0x5ABA, 0xDCF7, 0x5AB8, 0xDCF8, 0x5AB1,
+	0xDCF9, 0x5AB5, 0xDCFA, 0x5AB0, 0xDCFB, 0x5ABF, 0xDCFC, 0x5AC8,
+	0xDCFD, 0x5ABB, 0xDCFE, 0x5AC6, 0xDD40, 0x5AB7, 0xDD41, 0x5AC0,
+	0xDD42, 0x5ACA, 0xDD43, 0x5AB4, 0xDD44, 0x5AB6, 0xDD45, 0x5ACD,
+	0xDD46, 0x5AB9, 0xDD47, 0x5A90, 0xDD48, 0x5BD6, 0xDD49, 0x5BD8,
+	0xDD4A, 0x5BD9, 0xDD4B, 0x5C1F, 0xDD4C, 0x5C33, 0xDD4D, 0x5D71,
+	0xDD4E, 0x5D63, 0xDD4F, 0x5D4A, 0xDD50, 0x5D65, 0xDD51, 0x5D72,
+	0xDD52, 0x5D6C, 0xDD53, 0x5D5E, 0xDD54, 0x5D68, 0xDD55, 0x5D67,
+	0xDD56, 0x5D62, 0xDD57, 0x5DF0, 0xDD58, 0x5E4F, 0xDD59, 0x5E4E,
+	0xDD5A, 0x5E4A, 0xDD5B, 0x5E4D, 0xDD5C, 0x5E4B, 0xDD5D, 0x5EC5,
+	0xDD5E, 0x5ECC, 0xDD5F, 0x5EC6, 0xDD60, 0x5ECB, 0xDD61, 0x5EC7,
+	0xDD62, 0x5F40, 0xDD63, 0x5FAF, 0xDD64, 0x5FAD, 0xDD65, 0x60F7,
+	0xDD66, 0x6149, 0xDD67, 0x614A, 0xDD68, 0x612B, 0xDD69, 0x6145,
+	0xDD6A, 0x6136, 0xDD6B, 0x6132, 0xDD6C, 0x612E, 0xDD6D, 0x6146,
+	0xDD6E, 0x612F, 0xDD6F, 0x614F, 0xDD70, 0x6129, 0xDD71, 0x6140,
+	0xDD72, 0x6220, 0xDD73, 0x9168, 0xDD74, 0x6223, 0xDD75, 0x6225,
+	0xDD76, 0x6224, 0xDD77, 0x63C5, 0xDD78, 0x63F1, 0xDD79, 0x63EB,
+	0xDD7A, 0x6410, 0xDD7B, 0x6412, 0xDD7C, 0x6409, 0xDD7D, 0x6420,
+	0xDD7E, 0x6424, 0xDDA1, 0x6433, 0xDDA2, 0x6443, 0xDDA3, 0x641F,
+	0xDDA4, 0x6415, 0xDDA5, 0x6418, 0xDDA6, 0x6439, 0xDDA7, 0x6437,
+	0xDDA8, 0x6422, 0xDDA9, 0x6423, 0xDDAA, 0x640C, 0xDDAB, 0x6426,
+	0xDDAC, 0x6430, 0xDDAD, 0x6428, 0xDDAE, 0x6441, 0xDDAF, 0x6435,
+	0xDDB0, 0x642F, 0xDDB1, 0x640A, 0xDDB2, 0x641A, 0xDDB3, 0x6440,
+	0xDDB4, 0x6425, 0xDDB5, 0x6427, 0xDDB6, 0x640B, 0xDDB7, 0x63E7,
+	0xDDB8, 0x641B, 0xDDB9, 0x642E, 0xDDBA, 0x6421, 0xDDBB, 0x640E,
+	0xDDBC, 0x656F, 0xDDBD, 0x6592, 0xDDBE, 0x65D3, 0xDDBF, 0x6686,
+	0xDDC0, 0x668C, 0xDDC1, 0x6695, 0xDDC2, 0x6690, 0xDDC3, 0x668B,
+	0xDDC4, 0x668A, 0xDDC5, 0x6699, 0xDDC6, 0x6694, 0xDDC7, 0x6678,
+	0xDDC8, 0x6720, 0xDDC9, 0x6966, 0xDDCA, 0x695F, 0xDDCB, 0x6938,
+	0xDDCC, 0x694E, 0xDDCD, 0x6962, 0xDDCE, 0x6971, 0xDDCF, 0x693F,
+	0xDDD0, 0x6945, 0xDDD1, 0x696A, 0xDDD2, 0x6939, 0xDDD3, 0x6942,
+	0xDDD4, 0x6957, 0xDDD5, 0x6959, 0xDDD6, 0x697A, 0xDDD7, 0x6948,
+	0xDDD8, 0x6949, 0xDDD9, 0x6935, 0xDDDA, 0x696C, 0xDDDB, 0x6933,
+	0xDDDC, 0x693D, 0xDDDD, 0x6965, 0xDDDE, 0x68F0, 0xDDDF, 0x6978,
+	0xDDE0, 0x6934, 0xDDE1, 0x6969, 0xDDE2, 0x6940, 0xDDE3, 0x696F,
+	0xDDE4, 0x6944, 0xDDE5, 0x6976, 0xDDE6, 0x6958, 0xDDE7, 0x6941,
+	0xDDE8, 0x6974, 0xDDE9, 0x694C, 0xDDEA, 0x693B, 0xDDEB, 0x694B,
+	0xDDEC, 0x6937, 0xDDED, 0x695C, 0xDDEE, 0x694F, 0xDDEF, 0x6951,
+	0xDDF0, 0x6932, 0xDDF1, 0x6952, 0xDDF2, 0x692F, 0xDDF3, 0x697B,
+	0xDDF4, 0x693C, 0xDDF5, 0x6B46, 0xDDF6, 0x6B45, 0xDDF7, 0x6B43,
+	0xDDF8, 0x6B42, 0xDDF9, 0x6B48, 0xDDFA, 0x6B41, 0xDDFB, 0x6B9B,
+	0xDDFC, 0xFA0D, 0xDDFD, 0x6BFB, 0xDDFE, 0x6BFC, 0xDE40, 0x6BF9,
+	0xDE41, 0x6BF7, 0xDE42, 0x6BF8, 0xDE43, 0x6E9B, 0xDE44, 0x6ED6,
+	0xDE45, 0x6EC8, 0xDE46, 0x6E8F, 0xDE47, 0x6EC0, 0xDE48, 0x6E9F,
+	0xDE49, 0x6E93, 0xDE4A, 0x6E94, 0xDE4B, 0x6EA0, 0xDE4C, 0x6EB1,
+	0xDE4D, 0x6EB9, 0xDE4E, 0x6EC6, 0xDE4F, 0x6ED2, 0xDE50, 0x6EBD,
+	0xDE51, 0x6EC1, 0xDE52, 0x6E9E, 0xDE53, 0x6EC9, 0xDE54, 0x6EB7,
+	0xDE55, 0x6EB0, 0xDE56, 0x6ECD, 0xDE57, 0x6EA6, 0xDE58, 0x6ECF,
+	0xDE59, 0x6EB2, 0xDE5A, 0x6EBE, 0xDE5B, 0x6EC3, 0xDE5C, 0x6EDC,
+	0xDE5D, 0x6ED8, 0xDE5E, 0x6E99, 0xDE5F, 0x6E92, 0xDE60, 0x6E8E,
+	0xDE61, 0x6E8D, 0xDE62, 0x6EA4, 0xDE63, 0x6EA1, 0xDE64, 0x6EBF,
+	0xDE65, 0x6EB3, 0xDE66, 0x6ED0, 0xDE67, 0x6ECA, 0xDE68, 0x6E97,
+	0xDE69, 0x6EAE, 0xDE6A, 0x6EA3, 0xDE6B, 0x7147, 0xDE6C, 0x7154,
+	0xDE6D, 0x7152, 0xDE6E, 0x7163, 0xDE6F, 0x7160, 0xDE70, 0x7141,
+	0xDE71, 0x715D, 0xDE72, 0x7162, 0xDE73, 0x7172, 0xDE74, 0x7178,
+	0xDE75, 0x716A, 0xDE76, 0x7161, 0xDE77, 0x7142, 0xDE78, 0x7158,
+	0xDE79, 0x7143, 0xDE7A, 0x714B, 0xDE7B, 0x7170, 0xDE7C, 0x715F,
+	0xDE7D, 0x7150, 0xDE7E, 0x7153, 0xDEA1, 0x7144, 0xDEA2, 0x714D,
+	0xDEA3, 0x715A, 0xDEA4, 0x724F, 0xDEA5, 0x728D, 0xDEA6, 0x728C,
+	0xDEA7, 0x7291, 0xDEA8, 0x7290, 0xDEA9, 0x728E, 0xDEAA, 0x733C,
+	0xDEAB, 0x7342, 0xDEAC, 0x733B, 0xDEAD, 0x733A, 0xDEAE, 0x7340,
+	0xDEAF, 0x734A, 0xDEB0, 0x7349, 0xDEB1, 0x7444, 0xDEB2, 0x744A,
+	0xDEB3, 0x744B, 0xDEB4, 0x7452, 0xDEB5, 0x7451, 0xDEB6, 0x7457,
+	0xDEB7, 0x7440, 0xDEB8, 0x744F, 0xDEB9, 0x7450, 0xDEBA, 0x744E,
+	0xDEBB, 0x7442, 0xDEBC, 0x7446, 0xDEBD, 0x744D, 0xDEBE, 0x7454,
+	0xDEBF, 0x74E1, 0xDEC0, 0x74FF, 0xDEC1, 0x74FE, 0xDEC2, 0x74FD,
+	0xDEC3, 0x751D, 0xDEC4, 0x7579, 0xDEC5, 0x7577, 0xDEC6, 0x6983,
+	0xDEC7, 0x75EF, 0xDEC8, 0x760F, 0xDEC9, 0x7603, 0xDECA, 0x75F7,
+	0xDECB, 0x75FE, 0xDECC, 0x75FC, 0xDECD, 0x75F9, 0xDECE, 0x75F8,
+	0xDECF, 0x7610, 0xDED0, 0x75FB, 0xDED1, 0x75F6, 0xDED2, 0x75ED,
+	0xDED3, 0x75F5, 0xDED4, 0x75FD, 0xDED5, 0x7699, 0xDED6, 0x76B5,
+	0xDED7, 0x76DD, 0xDED8, 0x7755, 0xDED9, 0x775F, 0xDEDA, 0x7760,
+	0xDEDB, 0x7752, 0xDEDC, 0x7756, 0xDEDD, 0x775A, 0xDEDE, 0x7769,
+	0xDEDF, 0x7767, 0xDEE0, 0x7754, 0xDEE1, 0x7759, 0xDEE2, 0x776D,
+	0xDEE3, 0x77E0, 0xDEE4, 0x7887, 0xDEE5, 0x789A, 0xDEE6, 0x7894,
+	0xDEE7, 0x788F, 0xDEE8, 0x7884, 0xDEE9, 0x7895, 0xDEEA, 0x7885,
+	0xDEEB, 0x7886, 0xDEEC, 0x78A1, 0xDEED, 0x7883, 0xDEEE, 0x7879,
+	0xDEEF, 0x7899, 0xDEF0, 0x7880, 0xDEF1, 0x7896, 0xDEF2, 0x787B,
+	0xDEF3, 0x797C, 0xDEF4, 0x7982, 0xDEF5, 0x797D, 0xDEF6, 0x7979,
+	0xDEF7, 0x7A11, 0xDEF8, 0x7A18, 0xDEF9, 0x7A19, 0xDEFA, 0x7A12,
+	0xDEFB, 0x7A17, 0xDEFC, 0x7A15, 0xDEFD, 0x7A22, 0xDEFE, 0x7A13,
+	0xDF40, 0x7A1B, 0xDF41, 0x7A10, 0xDF42, 0x7AA3, 0xDF43, 0x7AA2,
+	0xDF44, 0x7A9E, 0xDF45, 0x7AEB, 0xDF46, 0x7B66, 0xDF47, 0x7B64,
+	0xDF48, 0x7B6D, 0xDF49, 0x7B74, 0xDF4A, 0x7B69, 0xDF4B, 0x7B72,
+	0xDF4C, 0x7B65, 0xDF4D, 0x7B73, 0xDF4E, 0x7B71, 0xDF4F, 0x7B70,
+	0xDF50, 0x7B61, 0xDF51, 0x7B78, 0xDF52, 0x7B76, 0xDF53, 0x7B63,
+	0xDF54, 0x7CB2, 0xDF55, 0x7CB4, 0xDF56, 0x7CAF, 0xDF57, 0x7D88,
+	0xDF58, 0x7D86, 0xDF59, 0x7D80, 0xDF5A, 0x7D8D, 0xDF5B, 0x7D7F,
+	0xDF5C, 0x7D85, 0xDF5D, 0x7D7A, 0xDF5E, 0x7D8E, 0xDF5F, 0x7D7B,
+	0xDF60, 0x7D83, 0xDF61, 0x7D7C, 0xDF62, 0x7D8C, 0xDF63, 0x7D94,
+	0xDF64, 0x7D84, 0xDF65, 0x7D7D, 0xDF66, 0x7D92, 0xDF67, 0x7F6D,
+	0xDF68, 0x7F6B, 0xDF69, 0x7F67, 0xDF6A, 0x7F68, 0xDF6B, 0x7F6C,
+	0xDF6C, 0x7FA6, 0xDF6D, 0x7FA5, 0xDF6E, 0x7FA7, 0xDF6F, 0x7FDB,
+	0xDF70, 0x7FDC, 0xDF71, 0x8021, 0xDF72, 0x8164, 0xDF73, 0x8160,
+	0xDF74, 0x8177, 0xDF75, 0x815C, 0xDF76, 0x8169, 0xDF77, 0x815B,
+	0xDF78, 0x8162, 0xDF79, 0x8172, 0xDF7A, 0x6721, 0xDF7B, 0x815E,
+	0xDF7C, 0x8176, 0xDF7D, 0x8167, 0xDF7E, 0x816F, 0xDFA1, 0x8144,
+	0xDFA2, 0x8161, 0xDFA3, 0x821D, 0xDFA4, 0x8249, 0xDFA5, 0x8244,
+	0xDFA6, 0x8240, 0xDFA7, 0x8242, 0xDFA8, 0x8245, 0xDFA9, 0x84F1,
+	0xDFAA, 0x843F, 0xDFAB, 0x8456, 0xDFAC, 0x8476, 0xDFAD, 0x8479,
+	0xDFAE, 0x848F, 0xDFAF, 0x848D, 0xDFB0, 0x8465, 0xDFB1, 0x8451,
+	0xDFB2, 0x8440, 0xDFB3, 0x8486, 0xDFB4, 0x8467, 0xDFB5, 0x8430,
+	0xDFB6, 0x844D, 0xDFB7, 0x847D, 0xDFB8, 0x845A, 0xDFB9, 0x8459,
+	0xDFBA, 0x8474, 0xDFBB, 0x8473, 0xDFBC, 0x845D, 0xDFBD, 0x8507,
+	0xDFBE, 0x845E, 0xDFBF, 0x8437, 0xDFC0, 0x843A, 0xDFC1, 0x8434,
+	0xDFC2, 0x847A, 0xDFC3, 0x8443, 0xDFC4, 0x8478, 0xDFC5, 0x8432,
+	0xDFC6, 0x8445, 0xDFC7, 0x8429, 0xDFC8, 0x83D9, 0xDFC9, 0x844B,
+	0xDFCA, 0x842F, 0xDFCB, 0x8442, 0xDFCC, 0x842D, 0xDFCD, 0x845F,
+	0xDFCE, 0x8470, 0xDFCF, 0x8439, 0xDFD0, 0x844E, 0xDFD1, 0x844C,
+	0xDFD2, 0x8452, 0xDFD3, 0x846F, 0xDFD4, 0x84C5, 0xDFD5, 0x848E,
+	0xDFD6, 0x843B, 0xDFD7, 0x8447, 0xDFD8, 0x8436, 0xDFD9, 0x8433,
+	0xDFDA, 0x8468, 0xDFDB, 0x847E, 0xDFDC, 0x8444, 0xDFDD, 0x842B,
+	0xDFDE, 0x8460, 0xDFDF, 0x8454, 0xDFE0, 0x846E, 0xDFE1, 0x8450,
+	0xDFE2, 0x870B, 0xDFE3, 0x8704, 0xDFE4, 0x86F7, 0xDFE5, 0x870C,
+	0xDFE6, 0x86FA, 0xDFE7, 0x86D6, 0xDFE8, 0x86F5, 0xDFE9, 0x874D,
+	0xDFEA, 0x86F8, 0xDFEB, 0x870E, 0xDFEC, 0x8709, 0xDFED, 0x8701,
+	0xDFEE, 0x86F6, 0xDFEF, 0x870D, 0xDFF0, 0x8705, 0xDFF1, 0x88D6,
+	0xDFF2, 0x88CB, 0xDFF3, 0x88CD, 0xDFF4, 0x88CE, 0xDFF5, 0x88DE,
+	0xDFF6, 0x88DB, 0xDFF7, 0x88DA, 0xDFF8, 0x88CC, 0xDFF9, 0x88D0,
+	0xDFFA, 0x8985, 0xDFFB, 0x899B, 0xDFFC, 0x89DF, 0xDFFD, 0x89E5,
+	0xDFFE, 0x89E4, 0xE040, 0x89E1, 0xE041, 0x89E0, 0xE042, 0x89E2,
+	0xE043, 0x89DC, 0xE044, 0x89E6, 0xE045, 0x8A76, 0xE046, 0x8A86,
+	0xE047, 0x8A7F, 0xE048, 0x8A61, 0xE049, 0x8A3F, 0xE04A, 0x8A77,
+	0xE04B, 0x8A82, 0xE04C, 0x8A84, 0xE04D, 0x8A75, 0xE04E, 0x8A83,
+	0xE04F, 0x8A81, 0xE050, 0x8A74, 0xE051, 0x8A7A, 0xE052, 0x8C3C,
+	0xE053, 0x8C4B, 0xE054, 0x8C4A, 0xE055, 0x8C65, 0xE056, 0x8C64,
+	0xE057, 0x8C66, 0xE058, 0x8C86, 0xE059, 0x8C84, 0xE05A, 0x8C85,
+	0xE05B, 0x8CCC, 0xE05C, 0x8D68, 0xE05D, 0x8D69, 0xE05E, 0x8D91,
+	0xE05F, 0x8D8C, 0xE060, 0x8D8E, 0xE061, 0x8D8F, 0xE062, 0x8D8D,
+	0xE063, 0x8D93, 0xE064, 0x8D94, 0xE065, 0x8D90, 0xE066, 0x8D92,
+	0xE067, 0x8DF0, 0xE068, 0x8DE0, 0xE069, 0x8DEC, 0xE06A, 0x8DF1,
+	0xE06B, 0x8DEE, 0xE06C, 0x8DD0, 0xE06D, 0x8DE9, 0xE06E, 0x8DE3,
+	0xE06F, 0x8DE2, 0xE070, 0x8DE7, 0xE071, 0x8DF2, 0xE072, 0x8DEB,
+	0xE073, 0x8DF4, 0xE074, 0x8F06, 0xE075, 0x8EFF, 0xE076, 0x8F01,
+	0xE077, 0x8F00, 0xE078, 0x8F05, 0xE079, 0x8F07, 0xE07A, 0x8F08,
+	0xE07B, 0x8F02, 0xE07C, 0x8F0B, 0xE07D, 0x9052, 0xE07E, 0x903F,
+	0xE0A1, 0x9044, 0xE0A2, 0x9049, 0xE0A3, 0x903D, 0xE0A4, 0x9110,
+	0xE0A5, 0x910D, 0xE0A6, 0x910F, 0xE0A7, 0x9111, 0xE0A8, 0x9116,
+	0xE0A9, 0x9114, 0xE0AA, 0x910B, 0xE0AB, 0x910E, 0xE0AC, 0x916E,
+	0xE0AD, 0x916F, 0xE0AE, 0x9248, 0xE0AF, 0x9252, 0xE0B0, 0x9230,
+	0xE0B1, 0x923A, 0xE0B2, 0x9266, 0xE0B3, 0x9233, 0xE0B4, 0x9265,
+	0xE0B5, 0x925E, 0xE0B6, 0x9283, 0xE0B7, 0x922E, 0xE0B8, 0x924A,
+	0xE0B9, 0x9246, 0xE0BA, 0x926D, 0xE0BB, 0x926C, 0xE0BC, 0x924F,
+	0xE0BD, 0x9260, 0xE0BE, 0x9267, 0xE0BF, 0x926F, 0xE0C0, 0x9236,
+	0xE0C1, 0x9261, 0xE0C2, 0x9270, 0xE0C3, 0x9231, 0xE0C4, 0x9254,
+	0xE0C5, 0x9263, 0xE0C6, 0x9250, 0xE0C7, 0x9272, 0xE0C8, 0x924E,
+	0xE0C9, 0x9253, 0xE0CA, 0x924C, 0xE0CB, 0x9256, 0xE0CC, 0x9232,
+	0xE0CD, 0x959F, 0xE0CE, 0x959C, 0xE0CF, 0x959E, 0xE0D0, 0x959B,
+	0xE0D1, 0x9692, 0xE0D2, 0x9693, 0xE0D3, 0x9691, 0xE0D4, 0x9697,
+	0xE0D5, 0x96CE, 0xE0D6, 0x96FA, 0xE0D7, 0x96FD, 0xE0D8, 0x96F8,
+	0xE0D9, 0x96F5, 0xE0DA, 0x9773, 0xE0DB, 0x9777, 0xE0DC, 0x9778,
+	0xE0DD, 0x9772, 0xE0DE, 0x980F, 0xE0DF, 0x980D, 0xE0E0, 0x980E,
+	0xE0E1, 0x98AC, 0xE0E2, 0x98F6, 0xE0E3, 0x98F9, 0xE0E4, 0x99AF,
+	0xE0E5, 0x99B2, 0xE0E6, 0x99B0, 0xE0E7, 0x99B5, 0xE0E8, 0x9AAD,
+	0xE0E9, 0x9AAB, 0xE0EA, 0x9B5B, 0xE0EB, 0x9CEA, 0xE0EC, 0x9CED,
+	0xE0ED, 0x9CE7, 0xE0EE, 0x9E80, 0xE0EF, 0x9EFD, 0xE0F0, 0x50E6,
+	0xE0F1, 0x50D4, 0xE0F2, 0x50D7, 0xE0F3, 0x50E8, 0xE0F4, 0x50F3,
+	0xE0F5, 0x50DB, 0xE0F6, 0x50EA, 0xE0F7, 0x50DD, 0xE0F8, 0x50E4,
+	0xE0F9, 0x50D3, 0xE0FA, 0x50EC, 0xE0FB, 0x50F0, 0xE0FC, 0x50EF,
+	0xE0FD, 0x50E3, 0xE0FE, 0x50E0, 0xE140, 0x51D8, 0xE141, 0x5280,
+	0xE142, 0x5281, 0xE143, 0x52E9, 0xE144, 0x52EB, 0xE145, 0x5330,
+	0xE146, 0x53AC, 0xE147, 0x5627, 0xE148, 0x5615, 0xE149, 0x560C,
+	0xE14A, 0x5612, 0xE14B, 0x55FC, 0xE14C, 0x560F, 0xE14D, 0x561C,
+	0xE14E, 0x5601, 0xE14F, 0x5613, 0xE150, 0x5602, 0xE151, 0x55FA,
+	0xE152, 0x561D, 0xE153, 0x5604, 0xE154, 0x55FF, 0xE155, 0x55F9,
+	0xE156, 0x5889, 0xE157, 0x587C, 0xE158, 0x5890, 0xE159, 0x5898,
+	0xE15A, 0x5886, 0xE15B, 0x5881, 0xE15C, 0x587F, 0xE15D, 0x5874,
+	0xE15E, 0x588B, 0xE15F, 0x587A, 0xE160, 0x5887, 0xE161, 0x5891,
+	0xE162, 0x588E, 0xE163, 0x5876, 0xE164, 0x5882, 0xE165, 0x5888,
+	0xE166, 0x587B, 0xE167, 0x5894, 0xE168, 0x588F, 0xE169, 0x58FE,
+	0xE16A, 0x596B, 0xE16B, 0x5ADC, 0xE16C, 0x5AEE, 0xE16D, 0x5AE5,
+	0xE16E, 0x5AD5, 0xE16F, 0x5AEA, 0xE170, 0x5ADA, 0xE171, 0x5AED,
+	0xE172, 0x5AEB, 0xE173, 0x5AF3, 0xE174, 0x5AE2, 0xE175, 0x5AE0,
+	0xE176, 0x5ADB, 0xE177, 0x5AEC, 0xE178, 0x5ADE, 0xE179, 0x5ADD,
+	0xE17A, 0x5AD9, 0xE17B, 0x5AE8, 0xE17C, 0x5ADF, 0xE17D, 0x5B77,
+	0xE17E, 0x5BE0, 0xE1A1, 0x5BE3, 0xE1A2, 0x5C63, 0xE1A3, 0x5D82,
+	0xE1A4, 0x5D80, 0xE1A5, 0x5D7D, 0xE1A6, 0x5D86, 0xE1A7, 0x5D7A,
+	0xE1A8, 0x5D81, 0xE1A9, 0x5D77, 0xE1AA, 0x5D8A, 0xE1AB, 0x5D89,
+	0xE1AC, 0x5D88, 0xE1AD, 0x5D7E, 0xE1AE, 0x5D7C, 0xE1AF, 0x5D8D,
+	0xE1B0, 0x5D79, 0xE1B1, 0x5D7F, 0xE1B2, 0x5E58, 0xE1B3, 0x5E59,
+	0xE1B4, 0x5E53, 0xE1B5, 0x5ED8, 0xE1B6, 0x5ED1, 0xE1B7, 0x5ED7,
+	0xE1B8, 0x5ECE, 0xE1B9, 0x5EDC, 0xE1BA, 0x5ED5, 0xE1BB, 0x5ED9,
+	0xE1BC, 0x5ED2, 0xE1BD, 0x5ED4, 0xE1BE, 0x5F44, 0xE1BF, 0x5F43,
+	0xE1C0, 0x5F6F, 0xE1C1, 0x5FB6, 0xE1C2, 0x612C, 0xE1C3, 0x6128,
+	0xE1C4, 0x6141, 0xE1C5, 0x615E, 0xE1C6, 0x6171, 0xE1C7, 0x6173,
+	0xE1C8, 0x6152, 0xE1C9, 0x6153, 0xE1CA, 0x6172, 0xE1CB, 0x616C,
+	0xE1CC, 0x6180, 0xE1CD, 0x6174, 0xE1CE, 0x6154, 0xE1CF, 0x617A,
+	0xE1D0, 0x615B, 0xE1D1, 0x6165, 0xE1D2, 0x613B, 0xE1D3, 0x616A,
+	0xE1D4, 0x6161, 0xE1D5, 0x6156, 0xE1D6, 0x6229, 0xE1D7, 0x6227,
+	0xE1D8, 0x622B, 0xE1D9, 0x642B, 0xE1DA, 0x644D, 0xE1DB, 0x645B,
+	0xE1DC, 0x645D, 0xE1DD, 0x6474, 0xE1DE, 0x6476, 0xE1DF, 0x6472,
+	0xE1E0, 0x6473, 0xE1E1, 0x647D, 0xE1E2, 0x6475, 0xE1E3, 0x6466,
+	0xE1E4, 0x64A6, 0xE1E5, 0x644E, 0xE1E6, 0x6482, 0xE1E7, 0x645E,
+	0xE1E8, 0x645C, 0xE1E9, 0x644B, 0xE1EA, 0x6453, 0xE1EB, 0x6460,
+	0xE1EC, 0x6450, 0xE1ED, 0x647F, 0xE1EE, 0x643F, 0xE1EF, 0x646C,
+	0xE1F0, 0x646B, 0xE1F1, 0x6459, 0xE1F2, 0x6465, 0xE1F3, 0x6477,
+	0xE1F4, 0x6573, 0xE1F5, 0x65A0, 0xE1F6, 0x66A1, 0xE1F7, 0x66A0,
+	0xE1F8, 0x669F, 0xE1F9, 0x6705, 0xE1FA, 0x6704, 0xE1FB, 0x6722,
+	0xE1FC, 0x69B1, 0xE1FD, 0x69B6, 0xE1FE, 0x69C9, 0xE240, 0x69A0,
+	0xE241, 0x69CE, 0xE242, 0x6996, 0xE243, 0x69B0, 0xE244, 0x69AC,
+	0xE245, 0x69BC, 0xE246, 0x6991, 0xE247, 0x6999, 0xE248, 0x698E,
+	0xE249, 0x69A7, 0xE24A, 0x698D, 0xE24B, 0x69A9, 0xE24C, 0x69BE,
+	0xE24D, 0x69AF, 0xE24E, 0x69BF, 0xE24F, 0x69C4, 0xE250, 0x69BD,
+	0xE251, 0x69A4, 0xE252, 0x69D4, 0xE253, 0x69B9, 0xE254, 0x69CA,
+	0xE255, 0x699A, 0xE256, 0x69CF, 0xE257, 0x69B3, 0xE258, 0x6993,
+	0xE259, 0x69AA, 0xE25A, 0x69A1, 0xE25B, 0x699E, 0xE25C, 0x69D9,
+	0xE25D, 0x6997, 0xE25E, 0x6990, 0xE25F, 0x69C2, 0xE260, 0x69B5,
+	0xE261, 0x69A5, 0xE262, 0x69C6, 0xE263, 0x6B4A, 0xE264, 0x6B4D,
+	0xE265, 0x6B4B, 0xE266, 0x6B9E, 0xE267, 0x6B9F, 0xE268, 0x6BA0,
+	0xE269, 0x6BC3, 0xE26A, 0x6BC4, 0xE26B, 0x6BFE, 0xE26C, 0x6ECE,
+	0xE26D, 0x6EF5, 0xE26E, 0x6EF1, 0xE26F, 0x6F03, 0xE270, 0x6F25,
+	0xE271, 0x6EF8, 0xE272, 0x6F37, 0xE273, 0x6EFB, 0xE274, 0x6F2E,
+	0xE275, 0x6F09, 0xE276, 0x6F4E, 0xE277, 0x6F19, 0xE278, 0x6F1A,
+	0xE279, 0x6F27, 0xE27A, 0x6F18, 0xE27B, 0x6F3B, 0xE27C, 0x6F12,
+	0xE27D, 0x6EED, 0xE27E, 0x6F0A, 0xE2A1, 0x6F36, 0xE2A2, 0x6F73,
+	0xE2A3, 0x6EF9, 0xE2A4, 0x6EEE, 0xE2A5, 0x6F2D, 0xE2A6, 0x6F40,
+	0xE2A7, 0x6F30, 0xE2A8, 0x6F3C, 0xE2A9, 0x6F35, 0xE2AA, 0x6EEB,
+	0xE2AB, 0x6F07, 0xE2AC, 0x6F0E, 0xE2AD, 0x6F43, 0xE2AE, 0x6F05,
+	0xE2AF, 0x6EFD, 0xE2B0, 0x6EF6, 0xE2B1, 0x6F39, 0xE2B2, 0x6F1C,
+	0xE2B3, 0x6EFC, 0xE2B4, 0x6F3A, 0xE2B5, 0x6F1F, 0xE2B6, 0x6F0D,
+	0xE2B7, 0x6F1E, 0xE2B8, 0x6F08, 0xE2B9, 0x6F21, 0xE2BA, 0x7187,
+	0xE2BB, 0x7190, 0xE2BC, 0x7189, 0xE2BD, 0x7180, 0xE2BE, 0x7185,
+	0xE2BF, 0x7182, 0xE2C0, 0x718F, 0xE2C1, 0x717B, 0xE2C2, 0x7186,
+	0xE2C3, 0x7181, 0xE2C4, 0x7197, 0xE2C5, 0x7244, 0xE2C6, 0x7253,
+	0xE2C7, 0x7297, 0xE2C8, 0x7295, 0xE2C9, 0x7293, 0xE2CA, 0x7343,
+	0xE2CB, 0x734D, 0xE2CC, 0x7351, 0xE2CD, 0x734C, 0xE2CE, 0x7462,
+	0xE2CF, 0x7473, 0xE2D0, 0x7471, 0xE2D1, 0x7475, 0xE2D2, 0x7472,
+	0xE2D3, 0x7467, 0xE2D4, 0x746E, 0xE2D5, 0x7500, 0xE2D6, 0x7502,
+	0xE2D7, 0x7503, 0xE2D8, 0x757D, 0xE2D9, 0x7590, 0xE2DA, 0x7616,
+	0xE2DB, 0x7608, 0xE2DC, 0x760C, 0xE2DD, 0x7615, 0xE2DE, 0x7611,
+	0xE2DF, 0x760A, 0xE2E0, 0x7614, 0xE2E1, 0x76B8, 0xE2E2, 0x7781,
+	0xE2E3, 0x777C, 0xE2E4, 0x7785, 0xE2E5, 0x7782, 0xE2E6, 0x776E,
+	0xE2E7, 0x7780, 0xE2E8, 0x776F, 0xE2E9, 0x777E, 0xE2EA, 0x7783,
+	0xE2EB, 0x78B2, 0xE2EC, 0x78AA, 0xE2ED, 0x78B4, 0xE2EE, 0x78AD,
+	0xE2EF, 0x78A8, 0xE2F0, 0x787E, 0xE2F1, 0x78AB, 0xE2F2, 0x789E,
+	0xE2F3, 0x78A5, 0xE2F4, 0x78A0, 0xE2F5, 0x78AC, 0xE2F6, 0x78A2,
+	0xE2F7, 0x78A4, 0xE2F8, 0x7998, 0xE2F9, 0x798A, 0xE2FA, 0x798B,
+	0xE2FB, 0x7996, 0xE2FC, 0x7995, 0xE2FD, 0x7994, 0xE2FE, 0x7993,
+	0xE340, 0x7997, 0xE341, 0x7988, 0xE342, 0x7992, 0xE343, 0x7990,
+	0xE344, 0x7A2B, 0xE345, 0x7A4A, 0xE346, 0x7A30, 0xE347, 0x7A2F,
+	0xE348, 0x7A28, 0xE349, 0x7A26, 0xE34A, 0x7AA8, 0xE34B, 0x7AAB,
+	0xE34C, 0x7AAC, 0xE34D, 0x7AEE, 0xE34E, 0x7B88, 0xE34F, 0x7B9C,
+	0xE350, 0x7B8A, 0xE351, 0x7B91, 0xE352, 0x7B90, 0xE353, 0x7B96,
+	0xE354, 0x7B8D, 0xE355, 0x7B8C, 0xE356, 0x7B9B, 0xE357, 0x7B8E,
+	0xE358, 0x7B85, 0xE359, 0x7B98, 0xE35A, 0x5284, 0xE35B, 0x7B99,
+	0xE35C, 0x7BA4, 0xE35D, 0x7B82, 0xE35E, 0x7CBB, 0xE35F, 0x7CBF,
+	0xE360, 0x7CBC, 0xE361, 0x7CBA, 0xE362, 0x7DA7, 0xE363, 0x7DB7,
+	0xE364, 0x7DC2, 0xE365, 0x7DA3, 0xE366, 0x7DAA, 0xE367, 0x7DC1,
+	0xE368, 0x7DC0, 0xE369, 0x7DC5, 0xE36A, 0x7D9D, 0xE36B, 0x7DCE,
+	0xE36C, 0x7DC4, 0xE36D, 0x7DC6, 0xE36E, 0x7DCB, 0xE36F, 0x7DCC,
+	0xE370, 0x7DAF, 0xE371, 0x7DB9, 0xE372, 0x7D96, 0xE373, 0x7DBC,
+	0xE374, 0x7D9F, 0xE375, 0x7DA6, 0xE376, 0x7DAE, 0xE377, 0x7DA9,
+	0xE378, 0x7DA1, 0xE379, 0x7DC9, 0xE37A, 0x7F73, 0xE37B, 0x7FE2,
+	0xE37C, 0x7FE3, 0xE37D, 0x7FE5, 0xE37E, 0x7FDE, 0xE3A1, 0x8024,
+	0xE3A2, 0x805D, 0xE3A3, 0x805C, 0xE3A4, 0x8189, 0xE3A5, 0x8186,
+	0xE3A6, 0x8183, 0xE3A7, 0x8187, 0xE3A8, 0x818D, 0xE3A9, 0x818C,
+	0xE3AA, 0x818B, 0xE3AB, 0x8215, 0xE3AC, 0x8497, 0xE3AD, 0x84A4,
+	0xE3AE, 0x84A1, 0xE3AF, 0x849F, 0xE3B0, 0x84BA, 0xE3B1, 0x84CE,
+	0xE3B2, 0x84C2, 0xE3B3, 0x84AC, 0xE3B4, 0x84AE, 0xE3B5, 0x84AB,
+	0xE3B6, 0x84B9, 0xE3B7, 0x84B4, 0xE3B8, 0x84C1, 0xE3B9, 0x84CD,
+	0xE3BA, 0x84AA, 0xE3BB, 0x849A, 0xE3BC, 0x84B1, 0xE3BD, 0x84D0,
+	0xE3BE, 0x849D, 0xE3BF, 0x84A7, 0xE3C0, 0x84BB, 0xE3C1, 0x84A2,
+	0xE3C2, 0x8494, 0xE3C3, 0x84C7, 0xE3C4, 0x84CC, 0xE3C5, 0x849B,
+	0xE3C6, 0x84A9, 0xE3C7, 0x84AF, 0xE3C8, 0x84A8, 0xE3C9, 0x84D6,
+	0xE3CA, 0x8498, 0xE3CB, 0x84B6, 0xE3CC, 0x84CF, 0xE3CD, 0x84A0,
+	0xE3CE, 0x84D7, 0xE3CF, 0x84D4, 0xE3D0, 0x84D2, 0xE3D1, 0x84DB,
+	0xE3D2, 0x84B0, 0xE3D3, 0x8491, 0xE3D4, 0x8661, 0xE3D5, 0x8733,
+	0xE3D6, 0x8723, 0xE3D7, 0x8728, 0xE3D8, 0x876B, 0xE3D9, 0x8740,
+	0xE3DA, 0x872E, 0xE3DB, 0x871E, 0xE3DC, 0x8721, 0xE3DD, 0x8719,
+	0xE3DE, 0x871B, 0xE3DF, 0x8743, 0xE3E0, 0x872C, 0xE3E1, 0x8741,
+	0xE3E2, 0x873E, 0xE3E3, 0x8746, 0xE3E4, 0x8720, 0xE3E5, 0x8732,
+	0xE3E6, 0x872A, 0xE3E7, 0x872D, 0xE3E8, 0x873C, 0xE3E9, 0x8712,
+	0xE3EA, 0x873A, 0xE3EB, 0x8731, 0xE3EC, 0x8735, 0xE3ED, 0x8742,
+	0xE3EE, 0x8726, 0xE3EF, 0x8727, 0xE3F0, 0x8738, 0xE3F1, 0x8724,
+	0xE3F2, 0x871A, 0xE3F3, 0x8730, 0xE3F4, 0x8711, 0xE3F5, 0x88F7,
+	0xE3F6, 0x88E7, 0xE3F7, 0x88F1, 0xE3F8, 0x88F2, 0xE3F9, 0x88FA,
+	0xE3FA, 0x88FE, 0xE3FB, 0x88EE, 0xE3FC, 0x88FC, 0xE3FD, 0x88F6,
+	0xE3FE, 0x88FB, 0xE440, 0x88F0, 0xE441, 0x88EC, 0xE442, 0x88EB,
+	0xE443, 0x899D, 0xE444, 0x89A1, 0xE445, 0x899F, 0xE446, 0x899E,
+	0xE447, 0x89E9, 0xE448, 0x89EB, 0xE449, 0x89E8, 0xE44A, 0x8AAB,
+	0xE44B, 0x8A99, 0xE44C, 0x8A8B, 0xE44D, 0x8A92, 0xE44E, 0x8A8F,
+	0xE44F, 0x8A96, 0xE450, 0x8C3D, 0xE451, 0x8C68, 0xE452, 0x8C69,
+	0xE453, 0x8CD5, 0xE454, 0x8CCF, 0xE455, 0x8CD7, 0xE456, 0x8D96,
+	0xE457, 0x8E09, 0xE458, 0x8E02, 0xE459, 0x8DFF, 0xE45A, 0x8E0D,
+	0xE45B, 0x8DFD, 0xE45C, 0x8E0A, 0xE45D, 0x8E03, 0xE45E, 0x8E07,
+	0xE45F, 0x8E06, 0xE460, 0x8E05, 0xE461, 0x8DFE, 0xE462, 0x8E00,
+	0xE463, 0x8E04, 0xE464, 0x8F10, 0xE465, 0x8F11, 0xE466, 0x8F0E,
+	0xE467, 0x8F0D, 0xE468, 0x9123, 0xE469, 0x911C, 0xE46A, 0x9120,
+	0xE46B, 0x9122, 0xE46C, 0x911F, 0xE46D, 0x911D, 0xE46E, 0x911A,
+	0xE46F, 0x9124, 0xE470, 0x9121, 0xE471, 0x911B, 0xE472, 0x917A,
+	0xE473, 0x9172, 0xE474, 0x9179, 0xE475, 0x9173, 0xE476, 0x92A5,
+	0xE477, 0x92A4, 0xE478, 0x9276, 0xE479, 0x929B, 0xE47A, 0x927A,
+	0xE47B, 0x92A0, 0xE47C, 0x9294, 0xE47D, 0x92AA, 0xE47E, 0x928D,
+	0xE4A1, 0x92A6, 0xE4A2, 0x929A, 0xE4A3, 0x92AB, 0xE4A4, 0x9279,
+	0xE4A5, 0x9297, 0xE4A6, 0x927F, 0xE4A7, 0x92A3, 0xE4A8, 0x92EE,
+	0xE4A9, 0x928E, 0xE4AA, 0x9282, 0xE4AB, 0x9295, 0xE4AC, 0x92A2,
+	0xE4AD, 0x927D, 0xE4AE, 0x9288, 0xE4AF, 0x92A1, 0xE4B0, 0x928A,
+	0xE4B1, 0x9286, 0xE4B2, 0x928C, 0xE4B3, 0x9299, 0xE4B4, 0x92A7,
+	0xE4B5, 0x927E, 0xE4B6, 0x9287, 0xE4B7, 0x92A9, 0xE4B8, 0x929D,
+	0xE4B9, 0x928B, 0xE4BA, 0x922D, 0xE4BB, 0x969E, 0xE4BC, 0x96A1,
+	0xE4BD, 0x96FF, 0xE4BE, 0x9758, 0xE4BF, 0x977D, 0xE4C0, 0x977A,
+	0xE4C1, 0x977E, 0xE4C2, 0x9783, 0xE4C3, 0x9780, 0xE4C4, 0x9782,
+	0xE4C5, 0x977B, 0xE4C6, 0x9784, 0xE4C7, 0x9781, 0xE4C8, 0x977F,
+	0xE4C9, 0x97CE, 0xE4CA, 0x97CD, 0xE4CB, 0x9816, 0xE4CC, 0x98AD,
+	0xE4CD, 0x98AE, 0xE4CE, 0x9902, 0xE4CF, 0x9900, 0xE4D0, 0x9907,
+	0xE4D1, 0x999D, 0xE4D2, 0x999C, 0xE4D3, 0x99C3, 0xE4D4, 0x99B9,
+	0xE4D5, 0x99BB, 0xE4D6, 0x99BA, 0xE4D7, 0x99C2, 0xE4D8, 0x99BD,
+	0xE4D9, 0x99C7, 0xE4DA, 0x9AB1, 0xE4DB, 0x9AE3, 0xE4DC, 0x9AE7,
+	0xE4DD, 0x9B3E, 0xE4DE, 0x9B3F, 0xE4DF, 0x9B60, 0xE4E0, 0x9B61,
+	0xE4E1, 0x9B5F, 0xE4E2, 0x9CF1, 0xE4E3, 0x9CF2, 0xE4E4, 0x9CF5,
+	0xE4E5, 0x9EA7, 0xE4E6, 0x50FF, 0xE4E7, 0x5103, 0xE4E8, 0x5130,
+	0xE4E9, 0x50F8, 0xE4EA, 0x5106, 0xE4EB, 0x5107, 0xE4EC, 0x50F6,
+	0xE4ED, 0x50FE, 0xE4EE, 0x510B, 0xE4EF, 0x510C, 0xE4F0, 0x50FD,
+	0xE4F1, 0x510A, 0xE4F2, 0x528B, 0xE4F3, 0x528C, 0xE4F4, 0x52F1,
+	0xE4F5, 0x52EF, 0xE4F6, 0x5648, 0xE4F7, 0x5642, 0xE4F8, 0x564C,
+	0xE4F9, 0x5635, 0xE4FA, 0x5641, 0xE4FB, 0x564A, 0xE4FC, 0x5649,
+	0xE4FD, 0x5646, 0xE4FE, 0x5658, 0xE540, 0x565A, 0xE541, 0x5640,
+	0xE542, 0x5633, 0xE543, 0x563D, 0xE544, 0x562C, 0xE545, 0x563E,
+	0xE546, 0x5638, 0xE547, 0x562A, 0xE548, 0x563A, 0xE549, 0x571A,
+	0xE54A, 0x58AB, 0xE54B, 0x589D, 0xE54C, 0x58B1, 0xE54D, 0x58A0,
+	0xE54E, 0x58A3, 0xE54F, 0x58AF, 0xE550, 0x58AC, 0xE551, 0x58A5,
+	0xE552, 0x58A1, 0xE553, 0x58FF, 0xE554, 0x5AFF, 0xE555, 0x5AF4,
+	0xE556, 0x5AFD, 0xE557, 0x5AF7, 0xE558, 0x5AF6, 0xE559, 0x5B03,
+	0xE55A, 0x5AF8, 0xE55B, 0x5B02, 0xE55C, 0x5AF9, 0xE55D, 0x5B01,
+	0xE55E, 0x5B07, 0xE55F, 0x5B05, 0xE560, 0x5B0F, 0xE561, 0x5C67,
+	0xE562, 0x5D99, 0xE563, 0x5D97, 0xE564, 0x5D9F, 0xE565, 0x5D92,
+	0xE566, 0x5DA2, 0xE567, 0x5D93, 0xE568, 0x5D95, 0xE569, 0x5DA0,
+	0xE56A, 0x5D9C, 0xE56B, 0x5DA1, 0xE56C, 0x5D9A, 0xE56D, 0x5D9E,
+	0xE56E, 0x5E69, 0xE56F, 0x5E5D, 0xE570, 0x5E60, 0xE571, 0x5E5C,
+	0xE572, 0x7DF3, 0xE573, 0x5EDB, 0xE574, 0x5EDE, 0xE575, 0x5EE1,
+	0xE576, 0x5F49, 0xE577, 0x5FB2, 0xE578, 0x618B, 0xE579, 0x6183,
+	0xE57A, 0x6179, 0xE57B, 0x61B1, 0xE57C, 0x61B0, 0xE57D, 0x61A2,
+	0xE57E, 0x6189, 0xE5A1, 0x619B, 0xE5A2, 0x6193, 0xE5A3, 0x61AF,
+	0xE5A4, 0x61AD, 0xE5A5, 0x619F, 0xE5A6, 0x6192, 0xE5A7, 0x61AA,
+	0xE5A8, 0x61A1, 0xE5A9, 0x618D, 0xE5AA, 0x6166, 0xE5AB, 0x61B3,
+	0xE5AC, 0x622D, 0xE5AD, 0x646E, 0xE5AE, 0x6470, 0xE5AF, 0x6496,
+	0xE5B0, 0x64A0, 0xE5B1, 0x6485, 0xE5B2, 0x6497, 0xE5B3, 0x649C,
+	0xE5B4, 0x648F, 0xE5B5, 0x648B, 0xE5B6, 0x648A, 0xE5B7, 0x648C,
+	0xE5B8, 0x64A3, 0xE5B9, 0x649F, 0xE5BA, 0x6468, 0xE5BB, 0x64B1,
+	0xE5BC, 0x6498, 0xE5BD, 0x6576, 0xE5BE, 0x657A, 0xE5BF, 0x6579,
+	0xE5C0, 0x657B, 0xE5C1, 0x65B2, 0xE5C2, 0x65B3, 0xE5C3, 0x66B5,
+	0xE5C4, 0x66B0, 0xE5C5, 0x66A9, 0xE5C6, 0x66B2, 0xE5C7, 0x66B7,
+	0xE5C8, 0x66AA, 0xE5C9, 0x66AF, 0xE5CA, 0x6A00, 0xE5CB, 0x6A06,
+	0xE5CC, 0x6A17, 0xE5CD, 0x69E5, 0xE5CE, 0x69F8, 0xE5CF, 0x6A15,
+	0xE5D0, 0x69F1, 0xE5D1, 0x69E4, 0xE5D2, 0x6A20, 0xE5D3, 0x69FF,
+	0xE5D4, 0x69EC, 0xE5D5, 0x69E2, 0xE5D6, 0x6A1B, 0xE5D7, 0x6A1D,
+	0xE5D8, 0x69FE, 0xE5D9, 0x6A27, 0xE5DA, 0x69F2, 0xE5DB, 0x69EE,
+	0xE5DC, 0x6A14, 0xE5DD, 0x69F7, 0xE5DE, 0x69E7, 0xE5DF, 0x6A40,
+	0xE5E0, 0x6A08, 0xE5E1, 0x69E6, 0xE5E2, 0x69FB, 0xE5E3, 0x6A0D,
+	0xE5E4, 0x69FC, 0xE5E5, 0x69EB, 0xE5E6, 0x6A09, 0xE5E7, 0x6A04,
+	0xE5E8, 0x6A18, 0xE5E9, 0x6A25, 0xE5EA, 0x6A0F, 0xE5EB, 0x69F6,
+	0xE5EC, 0x6A26, 0xE5ED, 0x6A07, 0xE5EE, 0x69F4, 0xE5EF, 0x6A16,
+	0xE5F0, 0x6B51, 0xE5F1, 0x6BA5, 0xE5F2, 0x6BA3, 0xE5F3, 0x6BA2,
+	0xE5F4, 0x6BA6, 0xE5F5, 0x6C01, 0xE5F6, 0x6C00, 0xE5F7, 0x6BFF,
+	0xE5F8, 0x6C02, 0xE5F9, 0x6F41, 0xE5FA, 0x6F26, 0xE5FB, 0x6F7E,
+	0xE5FC, 0x6F87, 0xE5FD, 0x6FC6, 0xE5FE, 0x6F92, 0xE640, 0x6F8D,
+	0xE641, 0x6F89, 0xE642, 0x6F8C, 0xE643, 0x6F62, 0xE644, 0x6F4F,
+	0xE645, 0x6F85, 0xE646, 0x6F5A, 0xE647, 0x6F96, 0xE648, 0x6F76,
+	0xE649, 0x6F6C, 0xE64A, 0x6F82, 0xE64B, 0x6F55, 0xE64C, 0x6F72,
+	0xE64D, 0x6F52, 0xE64E, 0x6F50, 0xE64F, 0x6F57, 0xE650, 0x6F94,
+	0xE651, 0x6F93, 0xE652, 0x6F5D, 0xE653, 0x6F00, 0xE654, 0x6F61,
+	0xE655, 0x6F6B, 0xE656, 0x6F7D, 0xE657, 0x6F67, 0xE658, 0x6F90,
+	0xE659, 0x6F53, 0xE65A, 0x6F8B, 0xE65B, 0x6F69, 0xE65C, 0x6F7F,
+	0xE65D, 0x6F95, 0xE65E, 0x6F63, 0xE65F, 0x6F77, 0xE660, 0x6F6A,
+	0xE661, 0x6F7B, 0xE662, 0x71B2, 0xE663, 0x71AF, 0xE664, 0x719B,
+	0xE665, 0x71B0, 0xE666, 0x71A0, 0xE667, 0x719A, 0xE668, 0x71A9,
+	0xE669, 0x71B5, 0xE66A, 0x719D, 0xE66B, 0x71A5, 0xE66C, 0x719E,
+	0xE66D, 0x71A4, 0xE66E, 0x71A1, 0xE66F, 0x71AA, 0xE670, 0x719C,
+	0xE671, 0x71A7, 0xE672, 0x71B3, 0xE673, 0x7298, 0xE674, 0x729A,
+	0xE675, 0x7358, 0xE676, 0x7352, 0xE677, 0x735E, 0xE678, 0x735F,
+	0xE679, 0x7360, 0xE67A, 0x735D, 0xE67B, 0x735B, 0xE67C, 0x7361,
+	0xE67D, 0x735A, 0xE67E, 0x7359, 0xE6A1, 0x7362, 0xE6A2, 0x7487,
+	0xE6A3, 0x7489, 0xE6A4, 0x748A, 0xE6A5, 0x7486, 0xE6A6, 0x7481,
+	0xE6A7, 0x747D, 0xE6A8, 0x7485, 0xE6A9, 0x7488, 0xE6AA, 0x747C,
+	0xE6AB, 0x7479, 0xE6AC, 0x7508, 0xE6AD, 0x7507, 0xE6AE, 0x757E,
+	0xE6AF, 0x7625, 0xE6B0, 0x761E, 0xE6B1, 0x7619, 0xE6B2, 0x761D,
+	0xE6B3, 0x761C, 0xE6B4, 0x7623, 0xE6B5, 0x761A, 0xE6B6, 0x7628,
+	0xE6B7, 0x761B, 0xE6B8, 0x769C, 0xE6B9, 0x769D, 0xE6BA, 0x769E,
+	0xE6BB, 0x769B, 0xE6BC, 0x778D, 0xE6BD, 0x778F, 0xE6BE, 0x7789,
+	0xE6BF, 0x7788, 0xE6C0, 0x78CD, 0xE6C1, 0x78BB, 0xE6C2, 0x78CF,
+	0xE6C3, 0x78CC, 0xE6C4, 0x78D1, 0xE6C5, 0x78CE, 0xE6C6, 0x78D4,
+	0xE6C7, 0x78C8, 0xE6C8, 0x78C3, 0xE6C9, 0x78C4, 0xE6CA, 0x78C9,
+	0xE6CB, 0x799A, 0xE6CC, 0x79A1, 0xE6CD, 0x79A0, 0xE6CE, 0x799C,
+	0xE6CF, 0x79A2, 0xE6D0, 0x799B, 0xE6D1, 0x6B76, 0xE6D2, 0x7A39,
+	0xE6D3, 0x7AB2, 0xE6D4, 0x7AB4, 0xE6D5, 0x7AB3, 0xE6D6, 0x7BB7,
+	0xE6D7, 0x7BCB, 0xE6D8, 0x7BBE, 0xE6D9, 0x7BAC, 0xE6DA, 0x7BCE,
+	0xE6DB, 0x7BAF, 0xE6DC, 0x7BB9, 0xE6DD, 0x7BCA, 0xE6DE, 0x7BB5,
+	0xE6DF, 0x7CC5, 0xE6E0, 0x7CC8, 0xE6E1, 0x7CCC, 0xE6E2, 0x7CCB,
+	0xE6E3, 0x7DF7, 0xE6E4, 0x7DDB, 0xE6E5, 0x7DEA, 0xE6E6, 0x7DE7,
+	0xE6E7, 0x7DD7, 0xE6E8, 0x7DE1, 0xE6E9, 0x7E03, 0xE6EA, 0x7DFA,
+	0xE6EB, 0x7DE6, 0xE6EC, 0x7DF6, 0xE6ED, 0x7DF1, 0xE6EE, 0x7DF0,
+	0xE6EF, 0x7DEE, 0xE6F0, 0x7DDF, 0xE6F1, 0x7F76, 0xE6F2, 0x7FAC,
+	0xE6F3, 0x7FB0, 0xE6F4, 0x7FAD, 0xE6F5, 0x7FED, 0xE6F6, 0x7FEB,
+	0xE6F7, 0x7FEA, 0xE6F8, 0x7FEC, 0xE6F9, 0x7FE6, 0xE6FA, 0x7FE8,
+	0xE6FB, 0x8064, 0xE6FC, 0x8067, 0xE6FD, 0x81A3, 0xE6FE, 0x819F,
+	0xE740, 0x819E, 0xE741, 0x8195, 0xE742, 0x81A2, 0xE743, 0x8199,
+	0xE744, 0x8197, 0xE745, 0x8216, 0xE746, 0x824F, 0xE747, 0x8253,
+	0xE748, 0x8252, 0xE749, 0x8250, 0xE74A, 0x824E, 0xE74B, 0x8251,
+	0xE74C, 0x8524, 0xE74D, 0x853B, 0xE74E, 0x850F, 0xE74F, 0x8500,
+	0xE750, 0x8529, 0xE751, 0x850E, 0xE752, 0x8509, 0xE753, 0x850D,
+	0xE754, 0x851F, 0xE755, 0x850A, 0xE756, 0x8527, 0xE757, 0x851C,
+	0xE758, 0x84FB, 0xE759, 0x852B, 0xE75A, 0x84FA, 0xE75B, 0x8508,
+	0xE75C, 0x850C, 0xE75D, 0x84F4, 0xE75E, 0x852A, 0xE75F, 0x84F2,
+	0xE760, 0x8515, 0xE761, 0x84F7, 0xE762, 0x84EB, 0xE763, 0x84F3,
+	0xE764, 0x84FC, 0xE765, 0x8512, 0xE766, 0x84EA, 0xE767, 0x84E9,
+	0xE768, 0x8516, 0xE769, 0x84FE, 0xE76A, 0x8528, 0xE76B, 0x851D,
+	0xE76C, 0x852E, 0xE76D, 0x8502, 0xE76E, 0x84FD, 0xE76F, 0x851E,
+	0xE770, 0x84F6, 0xE771, 0x8531, 0xE772, 0x8526, 0xE773, 0x84E7,
+	0xE774, 0x84E8, 0xE775, 0x84F0, 0xE776, 0x84EF, 0xE777, 0x84F9,
+	0xE778, 0x8518, 0xE779, 0x8520, 0xE77A, 0x8530, 0xE77B, 0x850B,
+	0xE77C, 0x8519, 0xE77D, 0x852F, 0xE77E, 0x8662, 0xE7A1, 0x8756,
+	0xE7A2, 0x8763, 0xE7A3, 0x8764, 0xE7A4, 0x8777, 0xE7A5, 0x87E1,
+	0xE7A6, 0x8773, 0xE7A7, 0x8758, 0xE7A8, 0x8754, 0xE7A9, 0x875B,
+	0xE7AA, 0x8752, 0xE7AB, 0x8761, 0xE7AC, 0x875A, 0xE7AD, 0x8751,
+	0xE7AE, 0x875E, 0xE7AF, 0x876D, 0xE7B0, 0x876A, 0xE7B1, 0x8750,
+	0xE7B2, 0x874E, 0xE7B3, 0x875F, 0xE7B4, 0x875D, 0xE7B5, 0x876F,
+	0xE7B6, 0x876C, 0xE7B7, 0x877A, 0xE7B8, 0x876E, 0xE7B9, 0x875C,
+	0xE7BA, 0x8765, 0xE7BB, 0x874F, 0xE7BC, 0x877B, 0xE7BD, 0x8775,
+	0xE7BE, 0x8762, 0xE7BF, 0x8767, 0xE7C0, 0x8769, 0xE7C1, 0x885A,
+	0xE7C2, 0x8905, 0xE7C3, 0x890C, 0xE7C4, 0x8914, 0xE7C5, 0x890B,
+	0xE7C6, 0x8917, 0xE7C7, 0x8918, 0xE7C8, 0x8919, 0xE7C9, 0x8906,
+	0xE7CA, 0x8916, 0xE7CB, 0x8911, 0xE7CC, 0x890E, 0xE7CD, 0x8909,
+	0xE7CE, 0x89A2, 0xE7CF, 0x89A4, 0xE7D0, 0x89A3, 0xE7D1, 0x89ED,
+	0xE7D2, 0x89F0, 0xE7D3, 0x89EC, 0xE7D4, 0x8ACF, 0xE7D5, 0x8AC6,
+	0xE7D6, 0x8AB8, 0xE7D7, 0x8AD3, 0xE7D8, 0x8AD1, 0xE7D9, 0x8AD4,
+	0xE7DA, 0x8AD5, 0xE7DB, 0x8ABB, 0xE7DC, 0x8AD7, 0xE7DD, 0x8ABE,
+	0xE7DE, 0x8AC0, 0xE7DF, 0x8AC5, 0xE7E0, 0x8AD8, 0xE7E1, 0x8AC3,
+	0xE7E2, 0x8ABA, 0xE7E3, 0x8ABD, 0xE7E4, 0x8AD9, 0xE7E5, 0x8C3E,
+	0xE7E6, 0x8C4D, 0xE7E7, 0x8C8F, 0xE7E8, 0x8CE5, 0xE7E9, 0x8CDF,
+	0xE7EA, 0x8CD9, 0xE7EB, 0x8CE8, 0xE7EC, 0x8CDA, 0xE7ED, 0x8CDD,
+	0xE7EE, 0x8CE7, 0xE7EF, 0x8DA0, 0xE7F0, 0x8D9C, 0xE7F1, 0x8DA1,
+	0xE7F2, 0x8D9B, 0xE7F3, 0x8E20, 0xE7F4, 0x8E23, 0xE7F5, 0x8E25,
+	0xE7F6, 0x8E24, 0xE7F7, 0x8E2E, 0xE7F8, 0x8E15, 0xE7F9, 0x8E1B,
+	0xE7FA, 0x8E16, 0xE7FB, 0x8E11, 0xE7FC, 0x8E19, 0xE7FD, 0x8E26,
+	0xE7FE, 0x8E27, 0xE840, 0x8E14, 0xE841, 0x8E12, 0xE842, 0x8E18,
+	0xE843, 0x8E13, 0xE844, 0x8E1C, 0xE845, 0x8E17, 0xE846, 0x8E1A,
+	0xE847, 0x8F2C, 0xE848, 0x8F24, 0xE849, 0x8F18, 0xE84A, 0x8F1A,
+	0xE84B, 0x8F20, 0xE84C, 0x8F23, 0xE84D, 0x8F16, 0xE84E, 0x8F17,
+	0xE84F, 0x9073, 0xE850, 0x9070, 0xE851, 0x906F, 0xE852, 0x9067,
+	0xE853, 0x906B, 0xE854, 0x912F, 0xE855, 0x912B, 0xE856, 0x9129,
+	0xE857, 0x912A, 0xE858, 0x9132, 0xE859, 0x9126, 0xE85A, 0x912E,
+	0xE85B, 0x9185, 0xE85C, 0x9186, 0xE85D, 0x918A, 0xE85E, 0x9181,
+	0xE85F, 0x9182, 0xE860, 0x9184, 0xE861, 0x9180, 0xE862, 0x92D0,
+	0xE863, 0x92C3, 0xE864, 0x92C4, 0xE865, 0x92C0, 0xE866, 0x92D9,
+	0xE867, 0x92B6, 0xE868, 0x92CF, 0xE869, 0x92F1, 0xE86A, 0x92DF,
+	0xE86B, 0x92D8, 0xE86C, 0x92E9, 0xE86D, 0x92D7, 0xE86E, 0x92DD,
+	0xE86F, 0x92CC, 0xE870, 0x92EF, 0xE871, 0x92C2, 0xE872, 0x92E8,
+	0xE873, 0x92CA, 0xE874, 0x92C8, 0xE875, 0x92CE, 0xE876, 0x92E6,
+	0xE877, 0x92CD, 0xE878, 0x92D5, 0xE879, 0x92C9, 0xE87A, 0x92E0,
+	0xE87B, 0x92DE, 0xE87C, 0x92E7, 0xE87D, 0x92D1, 0xE87E, 0x92D3,
+	0xE8A1, 0x92B5, 0xE8A2, 0x92E1, 0xE8A3, 0x92C6, 0xE8A4, 0x92B4,
+	0xE8A5, 0x957C, 0xE8A6, 0x95AC, 0xE8A7, 0x95AB, 0xE8A8, 0x95AE,
+	0xE8A9, 0x95B0, 0xE8AA, 0x96A4, 0xE8AB, 0x96A2, 0xE8AC, 0x96D3,
+	0xE8AD, 0x9705, 0xE8AE, 0x9708, 0xE8AF, 0x9702, 0xE8B0, 0x975A,
+	0xE8B1, 0x978A, 0xE8B2, 0x978E, 0xE8B3, 0x9788, 0xE8B4, 0x97D0,
+	0xE8B5, 0x97CF, 0xE8B6, 0x981E, 0xE8B7, 0x981D, 0xE8B8, 0x9826,
+	0xE8B9, 0x9829, 0xE8BA, 0x9828, 0xE8BB, 0x9820, 0xE8BC, 0x981B,
+	0xE8BD, 0x9827, 0xE8BE, 0x98B2, 0xE8BF, 0x9908, 0xE8C0, 0x98FA,
+	0xE8C1, 0x9911, 0xE8C2, 0x9914, 0xE8C3, 0x9916, 0xE8C4, 0x9917,
+	0xE8C5, 0x9915, 0xE8C6, 0x99DC, 0xE8C7, 0x99CD, 0xE8C8, 0x99CF,
+	0xE8C9, 0x99D3, 0xE8CA, 0x99D4, 0xE8CB, 0x99CE, 0xE8CC, 0x99C9,
+	0xE8CD, 0x99D6, 0xE8CE, 0x99D8, 0xE8CF, 0x99CB, 0xE8D0, 0x99D7,
+	0xE8D1, 0x99CC, 0xE8D2, 0x9AB3, 0xE8D3, 0x9AEC, 0xE8D4, 0x9AEB,
+	0xE8D5, 0x9AF3, 0xE8D6, 0x9AF2, 0xE8D7, 0x9AF1, 0xE8D8, 0x9B46,
+	0xE8D9, 0x9B43, 0xE8DA, 0x9B67, 0xE8DB, 0x9B74, 0xE8DC, 0x9B71,
+	0xE8DD, 0x9B66, 0xE8DE, 0x9B76, 0xE8DF, 0x9B75, 0xE8E0, 0x9B70,
+	0xE8E1, 0x9B68, 0xE8E2, 0x9B64, 0xE8E3, 0x9B6C, 0xE8E4, 0x9CFC,
+	0xE8E5, 0x9CFA, 0xE8E6, 0x9CFD, 0xE8E7, 0x9CFF, 0xE8E8, 0x9CF7,
+	0xE8E9, 0x9D07, 0xE8EA, 0x9D00, 0xE8EB, 0x9CF9, 0xE8EC, 0x9CFB,
+	0xE8ED, 0x9D08, 0xE8EE, 0x9D05, 0xE8EF, 0x9D04, 0xE8F0, 0x9E83,
+	0xE8F1, 0x9ED3, 0xE8F2, 0x9F0F, 0xE8F3, 0x9F10, 0xE8F4, 0x511C,
+	0xE8F5, 0x5113, 0xE8F6, 0x5117, 0xE8F7, 0x511A, 0xE8F8, 0x5111,
+	0xE8F9, 0x51DE, 0xE8FA, 0x5334, 0xE8FB, 0x53E1, 0xE8FC, 0x5670,
+	0xE8FD, 0x5660, 0xE8FE, 0x566E, 0xE940, 0x5673, 0xE941, 0x5666,
+	0xE942, 0x5663, 0xE943, 0x566D, 0xE944, 0x5672, 0xE945, 0x565E,
+	0xE946, 0x5677, 0xE947, 0x571C, 0xE948, 0x571B, 0xE949, 0x58C8,
+	0xE94A, 0x58BD, 0xE94B, 0x58C9, 0xE94C, 0x58BF, 0xE94D, 0x58BA,
+	0xE94E, 0x58C2, 0xE94F, 0x58BC, 0xE950, 0x58C6, 0xE951, 0x5B17,
+	0xE952, 0x5B19, 0xE953, 0x5B1B, 0xE954, 0x5B21, 0xE955, 0x5B14,
+	0xE956, 0x5B13, 0xE957, 0x5B10, 0xE958, 0x5B16, 0xE959, 0x5B28,
+	0xE95A, 0x5B1A, 0xE95B, 0x5B20, 0xE95C, 0x5B1E, 0xE95D, 0x5BEF,
+	0xE95E, 0x5DAC, 0xE95F, 0x5DB1, 0xE960, 0x5DA9, 0xE961, 0x5DA7,
+	0xE962, 0x5DB5, 0xE963, 0x5DB0, 0xE964, 0x5DAE, 0xE965, 0x5DAA,
+	0xE966, 0x5DA8, 0xE967, 0x5DB2, 0xE968, 0x5DAD, 0xE969, 0x5DAF,
+	0xE96A, 0x5DB4, 0xE96B, 0x5E67, 0xE96C, 0x5E68, 0xE96D, 0x5E66,
+	0xE96E, 0x5E6F, 0xE96F, 0x5EE9, 0xE970, 0x5EE7, 0xE971, 0x5EE6,
+	0xE972, 0x5EE8, 0xE973, 0x5EE5, 0xE974, 0x5F4B, 0xE975, 0x5FBC,
+	0xE976, 0x619D, 0xE977, 0x61A8, 0xE978, 0x6196, 0xE979, 0x61C5,
+	0xE97A, 0x61B4, 0xE97B, 0x61C6, 0xE97C, 0x61C1, 0xE97D, 0x61CC,
+	0xE97E, 0x61BA, 0xE9A1, 0x61BF, 0xE9A2, 0x61B8, 0xE9A3, 0x618C,
+	0xE9A4, 0x64D7, 0xE9A5, 0x64D6, 0xE9A6, 0x64D0, 0xE9A7, 0x64CF,
+	0xE9A8, 0x64C9, 0xE9A9, 0x64BD, 0xE9AA, 0x6489, 0xE9AB, 0x64C3,
+	0xE9AC, 0x64DB, 0xE9AD, 0x64F3, 0xE9AE, 0x64D9, 0xE9AF, 0x6533,
+	0xE9B0, 0x657F, 0xE9B1, 0x657C, 0xE9B2, 0x65A2, 0xE9B3, 0x66C8,
+	0xE9B4, 0x66BE, 0xE9B5, 0x66C0, 0xE9B6, 0x66CA, 0xE9B7, 0x66CB,
+	0xE9B8, 0x66CF, 0xE9B9, 0x66BD, 0xE9BA, 0x66BB, 0xE9BB, 0x66BA,
+	0xE9BC, 0x66CC, 0xE9BD, 0x6723, 0xE9BE, 0x6A34, 0xE9BF, 0x6A66,
+	0xE9C0, 0x6A49, 0xE9C1, 0x6A67, 0xE9C2, 0x6A32, 0xE9C3, 0x6A68,
+	0xE9C4, 0x6A3E, 0xE9C5, 0x6A5D, 0xE9C6, 0x6A6D, 0xE9C7, 0x6A76,
+	0xE9C8, 0x6A5B, 0xE9C9, 0x6A51, 0xE9CA, 0x6A28, 0xE9CB, 0x6A5A,
+	0xE9CC, 0x6A3B, 0xE9CD, 0x6A3F, 0xE9CE, 0x6A41, 0xE9CF, 0x6A6A,
+	0xE9D0, 0x6A64, 0xE9D1, 0x6A50, 0xE9D2, 0x6A4F, 0xE9D3, 0x6A54,
+	0xE9D4, 0x6A6F, 0xE9D5, 0x6A69, 0xE9D6, 0x6A60, 0xE9D7, 0x6A3C,
+	0xE9D8, 0x6A5E, 0xE9D9, 0x6A56, 0xE9DA, 0x6A55, 0xE9DB, 0x6A4D,
+	0xE9DC, 0x6A4E, 0xE9DD, 0x6A46, 0xE9DE, 0x6B55, 0xE9DF, 0x6B54,
+	0xE9E0, 0x6B56, 0xE9E1, 0x6BA7, 0xE9E2, 0x6BAA, 0xE9E3, 0x6BAB,
+	0xE9E4, 0x6BC8, 0xE9E5, 0x6BC7, 0xE9E6, 0x6C04, 0xE9E7, 0x6C03,
+	0xE9E8, 0x6C06, 0xE9E9, 0x6FAD, 0xE9EA, 0x6FCB, 0xE9EB, 0x6FA3,
+	0xE9EC, 0x6FC7, 0xE9ED, 0x6FBC, 0xE9EE, 0x6FCE, 0xE9EF, 0x6FC8,
+	0xE9F0, 0x6F5E, 0xE9F1, 0x6FC4, 0xE9F2, 0x6FBD, 0xE9F3, 0x6F9E,
+	0xE9F4, 0x6FCA, 0xE9F5, 0x6FA8, 0xE9F6, 0x7004, 0xE9F7, 0x6FA5,
+	0xE9F8, 0x6FAE, 0xE9F9, 0x6FBA, 0xE9FA, 0x6FAC, 0xE9FB, 0x6FAA,
+	0xE9FC, 0x6FCF, 0xE9FD, 0x6FBF, 0xE9FE, 0x6FB8, 0xEA40, 0x6FA2,
+	0xEA41, 0x6FC9, 0xEA42, 0x6FAB, 0xEA43, 0x6FCD, 0xEA44, 0x6FAF,
+	0xEA45, 0x6FB2, 0xEA46, 0x6FB0, 0xEA47, 0x71C5, 0xEA48, 0x71C2,
+	0xEA49, 0x71BF, 0xEA4A, 0x71B8, 0xEA4B, 0x71D6, 0xEA4C, 0x71C0,
+	0xEA4D, 0x71C1, 0xEA4E, 0x71CB, 0xEA4F, 0x71D4, 0xEA50, 0x71CA,
+	0xEA51, 0x71C7, 0xEA52, 0x71CF, 0xEA53, 0x71BD, 0xEA54, 0x71D8,
+	0xEA55, 0x71BC, 0xEA56, 0x71C6, 0xEA57, 0x71DA, 0xEA58, 0x71DB,
+	0xEA59, 0x729D, 0xEA5A, 0x729E, 0xEA5B, 0x7369, 0xEA5C, 0x7366,
+	0xEA5D, 0x7367, 0xEA5E, 0x736C, 0xEA5F, 0x7365, 0xEA60, 0x736B,
+	0xEA61, 0x736A, 0xEA62, 0x747F, 0xEA63, 0x749A, 0xEA64, 0x74A0,
+	0xEA65, 0x7494, 0xEA66, 0x7492, 0xEA67, 0x7495, 0xEA68, 0x74A1,
+	0xEA69, 0x750B, 0xEA6A, 0x7580, 0xEA6B, 0x762F, 0xEA6C, 0x762D,
+	0xEA6D, 0x7631, 0xEA6E, 0x763D, 0xEA6F, 0x7633, 0xEA70, 0x763C,
+	0xEA71, 0x7635, 0xEA72, 0x7632, 0xEA73, 0x7630, 0xEA74, 0x76BB,
+	0xEA75, 0x76E6, 0xEA76, 0x779A, 0xEA77, 0x779D, 0xEA78, 0x77A1,
+	0xEA79, 0x779C, 0xEA7A, 0x779B, 0xEA7B, 0x77A2, 0xEA7C, 0x77A3,
+	0xEA7D, 0x7795, 0xEA7E, 0x7799, 0xEAA1, 0x7797, 0xEAA2, 0x78DD,
+	0xEAA3, 0x78E9, 0xEAA4, 0x78E5, 0xEAA5, 0x78EA, 0xEAA6, 0x78DE,
+	0xEAA7, 0x78E3, 0xEAA8, 0x78DB, 0xEAA9, 0x78E1, 0xEAAA, 0x78E2,
+	0xEAAB, 0x78ED, 0xEAAC, 0x78DF, 0xEAAD, 0x78E0, 0xEAAE, 0x79A4,
+	0xEAAF, 0x7A44, 0xEAB0, 0x7A48, 0xEAB1, 0x7A47, 0xEAB2, 0x7AB6,
+	0xEAB3, 0x7AB8, 0xEAB4, 0x7AB5, 0xEAB5, 0x7AB1, 0xEAB6, 0x7AB7,
+	0xEAB7, 0x7BDE, 0xEAB8, 0x7BE3, 0xEAB9, 0x7BE7, 0xEABA, 0x7BDD,
+	0xEABB, 0x7BD5, 0xEABC, 0x7BE5, 0xEABD, 0x7BDA, 0xEABE, 0x7BE8,
+	0xEABF, 0x7BF9, 0xEAC0, 0x7BD4, 0xEAC1, 0x7BEA, 0xEAC2, 0x7BE2,
+	0xEAC3, 0x7BDC, 0xEAC4, 0x7BEB, 0xEAC5, 0x7BD8, 0xEAC6, 0x7BDF,
+	0xEAC7, 0x7CD2, 0xEAC8, 0x7CD4, 0xEAC9, 0x7CD7, 0xEACA, 0x7CD0,
+	0xEACB, 0x7CD1, 0xEACC, 0x7E12, 0xEACD, 0x7E21, 0xEACE, 0x7E17,
+	0xEACF, 0x7E0C, 0xEAD0, 0x7E1F, 0xEAD1, 0x7E20, 0xEAD2, 0x7E13,
+	0xEAD3, 0x7E0E, 0xEAD4, 0x7E1C, 0xEAD5, 0x7E15, 0xEAD6, 0x7E1A,
+	0xEAD7, 0x7E22, 0xEAD8, 0x7E0B, 0xEAD9, 0x7E0F, 0xEADA, 0x7E16,
+	0xEADB, 0x7E0D, 0xEADC, 0x7E14, 0xEADD, 0x7E25, 0xEADE, 0x7E24,
+	0xEADF, 0x7F43, 0xEAE0, 0x7F7B, 0xEAE1, 0x7F7C, 0xEAE2, 0x7F7A,
+	0xEAE3, 0x7FB1, 0xEAE4, 0x7FEF, 0xEAE5, 0x802A, 0xEAE6, 0x8029,
+	0xEAE7, 0x806C, 0xEAE8, 0x81B1, 0xEAE9, 0x81A6, 0xEAEA, 0x81AE,
+	0xEAEB, 0x81B9, 0xEAEC, 0x81B5, 0xEAED, 0x81AB, 0xEAEE, 0x81B0,
+	0xEAEF, 0x81AC, 0xEAF0, 0x81B4, 0xEAF1, 0x81B2, 0xEAF2, 0x81B7,
+	0xEAF3, 0x81A7, 0xEAF4, 0x81F2, 0xEAF5, 0x8255, 0xEAF6, 0x8256,
+	0xEAF7, 0x8257, 0xEAF8, 0x8556, 0xEAF9, 0x8545, 0xEAFA, 0x856B,
+	0xEAFB, 0x854D, 0xEAFC, 0x8553, 0xEAFD, 0x8561, 0xEAFE, 0x8558,
+	0xEB40, 0x8540, 0xEB41, 0x8546, 0xEB42, 0x8564, 0xEB43, 0x8541,
+	0xEB44, 0x8562, 0xEB45, 0x8544, 0xEB46, 0x8551, 0xEB47, 0x8547,
+	0xEB48, 0x8563, 0xEB49, 0x853E, 0xEB4A, 0x855B, 0xEB4B, 0x8571,
+	0xEB4C, 0x854E, 0xEB4D, 0x856E, 0xEB4E, 0x8575, 0xEB4F, 0x8555,
+	0xEB50, 0x8567, 0xEB51, 0x8560, 0xEB52, 0x858C, 0xEB53, 0x8566,
+	0xEB54, 0x855D, 0xEB55, 0x8554, 0xEB56, 0x8565, 0xEB57, 0x856C,
+	0xEB58, 0x8663, 0xEB59, 0x8665, 0xEB5A, 0x8664, 0xEB5B, 0x879B,
+	0xEB5C, 0x878F, 0xEB5D, 0x8797, 0xEB5E, 0x8793, 0xEB5F, 0x8792,
+	0xEB60, 0x8788, 0xEB61, 0x8781, 0xEB62, 0x8796, 0xEB63, 0x8798,
+	0xEB64, 0x8779, 0xEB65, 0x8787, 0xEB66, 0x87A3, 0xEB67, 0x8785,
+	0xEB68, 0x8790, 0xEB69, 0x8791, 0xEB6A, 0x879D, 0xEB6B, 0x8784,
+	0xEB6C, 0x8794, 0xEB6D, 0x879C, 0xEB6E, 0x879A, 0xEB6F, 0x8789,
+	0xEB70, 0x891E, 0xEB71, 0x8926, 0xEB72, 0x8930, 0xEB73, 0x892D,
+	0xEB74, 0x892E, 0xEB75, 0x8927, 0xEB76, 0x8931, 0xEB77, 0x8922,
+	0xEB78, 0x8929, 0xEB79, 0x8923, 0xEB7A, 0x892F, 0xEB7B, 0x892C,
+	0xEB7C, 0x891F, 0xEB7D, 0x89F1, 0xEB7E, 0x8AE0, 0xEBA1, 0x8AE2,
+	0xEBA2, 0x8AF2, 0xEBA3, 0x8AF4, 0xEBA4, 0x8AF5, 0xEBA5, 0x8ADD,
+	0xEBA6, 0x8B14, 0xEBA7, 0x8AE4, 0xEBA8, 0x8ADF, 0xEBA9, 0x8AF0,
+	0xEBAA, 0x8AC8, 0xEBAB, 0x8ADE, 0xEBAC, 0x8AE1, 0xEBAD, 0x8AE8,
+	0xEBAE, 0x8AFF, 0xEBAF, 0x8AEF, 0xEBB0, 0x8AFB, 0xEBB1, 0x8C91,
+	0xEBB2, 0x8C92, 0xEBB3, 0x8C90, 0xEBB4, 0x8CF5, 0xEBB5, 0x8CEE,
+	0xEBB6, 0x8CF1, 0xEBB7, 0x8CF0, 0xEBB8, 0x8CF3, 0xEBB9, 0x8D6C,
+	0xEBBA, 0x8D6E, 0xEBBB, 0x8DA5, 0xEBBC, 0x8DA7, 0xEBBD, 0x8E33,
+	0xEBBE, 0x8E3E, 0xEBBF, 0x8E38, 0xEBC0, 0x8E40, 0xEBC1, 0x8E45,
+	0xEBC2, 0x8E36, 0xEBC3, 0x8E3C, 0xEBC4, 0x8E3D, 0xEBC5, 0x8E41,
+	0xEBC6, 0x8E30, 0xEBC7, 0x8E3F, 0xEBC8, 0x8EBD, 0xEBC9, 0x8F36,
+	0xEBCA, 0x8F2E, 0xEBCB, 0x8F35, 0xEBCC, 0x8F32, 0xEBCD, 0x8F39,
+	0xEBCE, 0x8F37, 0xEBCF, 0x8F34, 0xEBD0, 0x9076, 0xEBD1, 0x9079,
+	0xEBD2, 0x907B, 0xEBD3, 0x9086, 0xEBD4, 0x90FA, 0xEBD5, 0x9133,
+	0xEBD6, 0x9135, 0xEBD7, 0x9136, 0xEBD8, 0x9193, 0xEBD9, 0x9190,
+	0xEBDA, 0x9191, 0xEBDB, 0x918D, 0xEBDC, 0x918F, 0xEBDD, 0x9327,
+	0xEBDE, 0x931E, 0xEBDF, 0x9308, 0xEBE0, 0x931F, 0xEBE1, 0x9306,
+	0xEBE2, 0x930F, 0xEBE3, 0x937A, 0xEBE4, 0x9338, 0xEBE5, 0x933C,
+	0xEBE6, 0x931B, 0xEBE7, 0x9323, 0xEBE8, 0x9312, 0xEBE9, 0x9301,
+	0xEBEA, 0x9346, 0xEBEB, 0x932D, 0xEBEC, 0x930E, 0xEBED, 0x930D,
+	0xEBEE, 0x92CB, 0xEBEF, 0x931D, 0xEBF0, 0x92FA, 0xEBF1, 0x9325,
+	0xEBF2, 0x9313, 0xEBF3, 0x92F9, 0xEBF4, 0x92F7, 0xEBF5, 0x9334,
+	0xEBF6, 0x9302, 0xEBF7, 0x9324, 0xEBF8, 0x92FF, 0xEBF9, 0x9329,
+	0xEBFA, 0x9339, 0xEBFB, 0x9335, 0xEBFC, 0x932A, 0xEBFD, 0x9314,
+	0xEBFE, 0x930C, 0xEC40, 0x930B, 0xEC41, 0x92FE, 0xEC42, 0x9309,
+	0xEC43, 0x9300, 0xEC44, 0x92FB, 0xEC45, 0x9316, 0xEC46, 0x95BC,
+	0xEC47, 0x95CD, 0xEC48, 0x95BE, 0xEC49, 0x95B9, 0xEC4A, 0x95BA,
+	0xEC4B, 0x95B6, 0xEC4C, 0x95BF, 0xEC4D, 0x95B5, 0xEC4E, 0x95BD,
+	0xEC4F, 0x96A9, 0xEC50, 0x96D4, 0xEC51, 0x970B, 0xEC52, 0x9712,
+	0xEC53, 0x9710, 0xEC54, 0x9799, 0xEC55, 0x9797, 0xEC56, 0x9794,
+	0xEC57, 0x97F0, 0xEC58, 0x97F8, 0xEC59, 0x9835, 0xEC5A, 0x982F,
+	0xEC5B, 0x9832, 0xEC5C, 0x9924, 0xEC5D, 0x991F, 0xEC5E, 0x9927,
+	0xEC5F, 0x9929, 0xEC60, 0x999E, 0xEC61, 0x99EE, 0xEC62, 0x99EC,
+	0xEC63, 0x99E5, 0xEC64, 0x99E4, 0xEC65, 0x99F0, 0xEC66, 0x99E3,
+	0xEC67, 0x99EA, 0xEC68, 0x99E9, 0xEC69, 0x99E7, 0xEC6A, 0x9AB9,
+	0xEC6B, 0x9ABF, 0xEC6C, 0x9AB4, 0xEC6D, 0x9ABB, 0xEC6E, 0x9AF6,
+	0xEC6F, 0x9AFA, 0xEC70, 0x9AF9, 0xEC71, 0x9AF7, 0xEC72, 0x9B33,
+	0xEC73, 0x9B80, 0xEC74, 0x9B85, 0xEC75, 0x9B87, 0xEC76, 0x9B7C,
+	0xEC77, 0x9B7E, 0xEC78, 0x9B7B, 0xEC79, 0x9B82, 0xEC7A, 0x9B93,
+	0xEC7B, 0x9B92, 0xEC7C, 0x9B90, 0xEC7D, 0x9B7A, 0xEC7E, 0x9B95,
+	0xECA1, 0x9B7D, 0xECA2, 0x9B88, 0xECA3, 0x9D25, 0xECA4, 0x9D17,
+	0xECA5, 0x9D20, 0xECA6, 0x9D1E, 0xECA7, 0x9D14, 0xECA8, 0x9D29,
+	0xECA9, 0x9D1D, 0xECAA, 0x9D18, 0xECAB, 0x9D22, 0xECAC, 0x9D10,
+	0xECAD, 0x9D19, 0xECAE, 0x9D1F, 0xECAF, 0x9E88, 0xECB0, 0x9E86,
+	0xECB1, 0x9E87, 0xECB2, 0x9EAE, 0xECB3, 0x9EAD, 0xECB4, 0x9ED5,
+	0xECB5, 0x9ED6, 0xECB6, 0x9EFA, 0xECB7, 0x9F12, 0xECB8, 0x9F3D,
+	0xECB9, 0x5126, 0xECBA, 0x5125, 0xECBB, 0x5122, 0xECBC, 0x5124,
+	0xECBD, 0x5120, 0xECBE, 0x5129, 0xECBF, 0x52F4, 0xECC0, 0x5693,
+	0xECC1, 0x568C, 0xECC2, 0x568D, 0xECC3, 0x5686, 0xECC4, 0x5684,
+	0xECC5, 0x5683, 0xECC6, 0x567E, 0xECC7, 0x5682, 0xECC8, 0x567F,
+	0xECC9, 0x5681, 0xECCA, 0x58D6, 0xECCB, 0x58D4, 0xECCC, 0x58CF,
+	0xECCD, 0x58D2, 0xECCE, 0x5B2D, 0xECCF, 0x5B25, 0xECD0, 0x5B32,
+	0xECD1, 0x5B23, 0xECD2, 0x5B2C, 0xECD3, 0x5B27, 0xECD4, 0x5B26,
+	0xECD5, 0x5B2F, 0xECD6, 0x5B2E, 0xECD7, 0x5B7B, 0xECD8, 0x5BF1,
+	0xECD9, 0x5BF2, 0xECDA, 0x5DB7, 0xECDB, 0x5E6C, 0xECDC, 0x5E6A,
+	0xECDD, 0x5FBE, 0xECDE, 0x5FBB, 0xECDF, 0x61C3, 0xECE0, 0x61B5,
+	0xECE1, 0x61BC, 0xECE2, 0x61E7, 0xECE3, 0x61E0, 0xECE4, 0x61E5,
+	0xECE5, 0x61E4, 0xECE6, 0x61E8, 0xECE7, 0x61DE, 0xECE8, 0x64EF,
+	0xECE9, 0x64E9, 0xECEA, 0x64E3, 0xECEB, 0x64EB, 0xECEC, 0x64E4,
+	0xECED, 0x64E8, 0xECEE, 0x6581, 0xECEF, 0x6580, 0xECF0, 0x65B6,
+	0xECF1, 0x65DA, 0xECF2, 0x66D2, 0xECF3, 0x6A8D, 0xECF4, 0x6A96,
+	0xECF5, 0x6A81, 0xECF6, 0x6AA5, 0xECF7, 0x6A89, 0xECF8, 0x6A9F,
+	0xECF9, 0x6A9B, 0xECFA, 0x6AA1, 0xECFB, 0x6A9E, 0xECFC, 0x6A87,
+	0xECFD, 0x6A93, 0xECFE, 0x6A8E, 0xED40, 0x6A95, 0xED41, 0x6A83,
+	0xED42, 0x6AA8, 0xED43, 0x6AA4, 0xED44, 0x6A91, 0xED45, 0x6A7F,
+	0xED46, 0x6AA6, 0xED47, 0x6A9A, 0xED48, 0x6A85, 0xED49, 0x6A8C,
+	0xED4A, 0x6A92, 0xED4B, 0x6B5B, 0xED4C, 0x6BAD, 0xED4D, 0x6C09,
+	0xED4E, 0x6FCC, 0xED4F, 0x6FA9, 0xED50, 0x6FF4, 0xED51, 0x6FD4,
+	0xED52, 0x6FE3, 0xED53, 0x6FDC, 0xED54, 0x6FED, 0xED55, 0x6FE7,
+	0xED56, 0x6FE6, 0xED57, 0x6FDE, 0xED58, 0x6FF2, 0xED59, 0x6FDD,
+	0xED5A, 0x6FE2, 0xED5B, 0x6FE8, 0xED5C, 0x71E1, 0xED5D, 0x71F1,
+	0xED5E, 0x71E8, 0xED5F, 0x71F2, 0xED60, 0x71E4, 0xED61, 0x71F0,
+	0xED62, 0x71E2, 0xED63, 0x7373, 0xED64, 0x736E, 0xED65, 0x736F,
+	0xED66, 0x7497, 0xED67, 0x74B2, 0xED68, 0x74AB, 0xED69, 0x7490,
+	0xED6A, 0x74AA, 0xED6B, 0x74AD, 0xED6C, 0x74B1, 0xED6D, 0x74A5,
+	0xED6E, 0x74AF, 0xED6F, 0x7510, 0xED70, 0x7511, 0xED71, 0x7512,
+	0xED72, 0x750F, 0xED73, 0x7584, 0xED74, 0x7643, 0xED75, 0x7648,
+	0xED76, 0x7649, 0xED77, 0x7647, 0xED78, 0x76A4, 0xED79, 0x76E9,
+	0xED7A, 0x77B5, 0xED7B, 0x77AB, 0xED7C, 0x77B2, 0xED7D, 0x77B7,
+	0xED7E, 0x77B6, 0xEDA1, 0x77B4, 0xEDA2, 0x77B1, 0xEDA3, 0x77A8,
+	0xEDA4, 0x77F0, 0xEDA5, 0x78F3, 0xEDA6, 0x78FD, 0xEDA7, 0x7902,
+	0xEDA8, 0x78FB, 0xEDA9, 0x78FC, 0xEDAA, 0x78F2, 0xEDAB, 0x7905,
+	0xEDAC, 0x78F9, 0xEDAD, 0x78FE, 0xEDAE, 0x7904, 0xEDAF, 0x79AB,
+	0xEDB0, 0x79A8, 0xEDB1, 0x7A5C, 0xEDB2, 0x7A5B, 0xEDB3, 0x7A56,
+	0xEDB4, 0x7A58, 0xEDB5, 0x7A54, 0xEDB6, 0x7A5A, 0xEDB7, 0x7ABE,
+	0xEDB8, 0x7AC0, 0xEDB9, 0x7AC1, 0xEDBA, 0x7C05, 0xEDBB, 0x7C0F,
+	0xEDBC, 0x7BF2, 0xEDBD, 0x7C00, 0xEDBE, 0x7BFF, 0xEDBF, 0x7BFB,
+	0xEDC0, 0x7C0E, 0xEDC1, 0x7BF4, 0xEDC2, 0x7C0B, 0xEDC3, 0x7BF3,
+	0xEDC4, 0x7C02, 0xEDC5, 0x7C09, 0xEDC6, 0x7C03, 0xEDC7, 0x7C01,
+	0xEDC8, 0x7BF8, 0xEDC9, 0x7BFD, 0xEDCA, 0x7C06, 0xEDCB, 0x7BF0,
+	0xEDCC, 0x7BF1, 0xEDCD, 0x7C10, 0xEDCE, 0x7C0A, 0xEDCF, 0x7CE8,
+	0xEDD0, 0x7E2D, 0xEDD1, 0x7E3C, 0xEDD2, 0x7E42, 0xEDD3, 0x7E33,
+	0xEDD4, 0x9848, 0xEDD5, 0x7E38, 0xEDD6, 0x7E2A, 0xEDD7, 0x7E49,
+	0xEDD8, 0x7E40, 0xEDD9, 0x7E47, 0xEDDA, 0x7E29, 0xEDDB, 0x7E4C,
+	0xEDDC, 0x7E30, 0xEDDD, 0x7E3B, 0xEDDE, 0x7E36, 0xEDDF, 0x7E44,
+	0xEDE0, 0x7E3A, 0xEDE1, 0x7F45, 0xEDE2, 0x7F7F, 0xEDE3, 0x7F7E,
+	0xEDE4, 0x7F7D, 0xEDE5, 0x7FF4, 0xEDE6, 0x7FF2, 0xEDE7, 0x802C,
+	0xEDE8, 0x81BB, 0xEDE9, 0x81C4, 0xEDEA, 0x81CC, 0xEDEB, 0x81CA,
+	0xEDEC, 0x81C5, 0xEDED, 0x81C7, 0xEDEE, 0x81BC, 0xEDEF, 0x81E9,
+	0xEDF0, 0x825B, 0xEDF1, 0x825A, 0xEDF2, 0x825C, 0xEDF3, 0x8583,
+	0xEDF4, 0x8580, 0xEDF5, 0x858F, 0xEDF6, 0x85A7, 0xEDF7, 0x8595,
+	0xEDF8, 0x85A0, 0xEDF9, 0x858B, 0xEDFA, 0x85A3, 0xEDFB, 0x857B,
+	0xEDFC, 0x85A4, 0xEDFD, 0x859A, 0xEDFE, 0x859E, 0xEE40, 0x8577,
+	0xEE41, 0x857C, 0xEE42, 0x8589, 0xEE43, 0x85A1, 0xEE44, 0x857A,
+	0xEE45, 0x8578, 0xEE46, 0x8557, 0xEE47, 0x858E, 0xEE48, 0x8596,
+	0xEE49, 0x8586, 0xEE4A, 0x858D, 0xEE4B, 0x8599, 0xEE4C, 0x859D,
+	0xEE4D, 0x8581, 0xEE4E, 0x85A2, 0xEE4F, 0x8582, 0xEE50, 0x8588,
+	0xEE51, 0x8585, 0xEE52, 0x8579, 0xEE53, 0x8576, 0xEE54, 0x8598,
+	0xEE55, 0x8590, 0xEE56, 0x859F, 0xEE57, 0x8668, 0xEE58, 0x87BE,
+	0xEE59, 0x87AA, 0xEE5A, 0x87AD, 0xEE5B, 0x87C5, 0xEE5C, 0x87B0,
+	0xEE5D, 0x87AC, 0xEE5E, 0x87B9, 0xEE5F, 0x87B5, 0xEE60, 0x87BC,
+	0xEE61, 0x87AE, 0xEE62, 0x87C9, 0xEE63, 0x87C3, 0xEE64, 0x87C2,
+	0xEE65, 0x87CC, 0xEE66, 0x87B7, 0xEE67, 0x87AF, 0xEE68, 0x87C4,
+	0xEE69, 0x87CA, 0xEE6A, 0x87B4, 0xEE6B, 0x87B6, 0xEE6C, 0x87BF,
+	0xEE6D, 0x87B8, 0xEE6E, 0x87BD, 0xEE6F, 0x87DE, 0xEE70, 0x87B2,
+	0xEE71, 0x8935, 0xEE72, 0x8933, 0xEE73, 0x893C, 0xEE74, 0x893E,
+	0xEE75, 0x8941, 0xEE76, 0x8952, 0xEE77, 0x8937, 0xEE78, 0x8942,
+	0xEE79, 0x89AD, 0xEE7A, 0x89AF, 0xEE7B, 0x89AE, 0xEE7C, 0x89F2,
+	0xEE7D, 0x89F3, 0xEE7E, 0x8B1E, 0xEEA1, 0x8B18, 0xEEA2, 0x8B16,
+	0xEEA3, 0x8B11, 0xEEA4, 0x8B05, 0xEEA5, 0x8B0B, 0xEEA6, 0x8B22,
+	0xEEA7, 0x8B0F, 0xEEA8, 0x8B12, 0xEEA9, 0x8B15, 0xEEAA, 0x8B07,
+	0xEEAB, 0x8B0D, 0xEEAC, 0x8B08, 0xEEAD, 0x8B06, 0xEEAE, 0x8B1C,
+	0xEEAF, 0x8B13, 0xEEB0, 0x8B1A, 0xEEB1, 0x8C4F, 0xEEB2, 0x8C70,
+	0xEEB3, 0x8C72, 0xEEB4, 0x8C71, 0xEEB5, 0x8C6F, 0xEEB6, 0x8C95,
+	0xEEB7, 0x8C94, 0xEEB8, 0x8CF9, 0xEEB9, 0x8D6F, 0xEEBA, 0x8E4E,
+	0xEEBB, 0x8E4D, 0xEEBC, 0x8E53, 0xEEBD, 0x8E50, 0xEEBE, 0x8E4C,
+	0xEEBF, 0x8E47, 0xEEC0, 0x8F43, 0xEEC1, 0x8F40, 0xEEC2, 0x9085,
+	0xEEC3, 0x907E, 0xEEC4, 0x9138, 0xEEC5, 0x919A, 0xEEC6, 0x91A2,
+	0xEEC7, 0x919B, 0xEEC8, 0x9199, 0xEEC9, 0x919F, 0xEECA, 0x91A1,
+	0xEECB, 0x919D, 0xEECC, 0x91A0, 0xEECD, 0x93A1, 0xEECE, 0x9383,
+	0xEECF, 0x93AF, 0xEED0, 0x9364, 0xEED1, 0x9356, 0xEED2, 0x9347,
+	0xEED3, 0x937C, 0xEED4, 0x9358, 0xEED5, 0x935C, 0xEED6, 0x9376,
+	0xEED7, 0x9349, 0xEED8, 0x9350, 0xEED9, 0x9351, 0xEEDA, 0x9360,
+	0xEEDB, 0x936D, 0xEEDC, 0x938F, 0xEEDD, 0x934C, 0xEEDE, 0x936A,
+	0xEEDF, 0x9379, 0xEEE0, 0x9357, 0xEEE1, 0x9355, 0xEEE2, 0x9352,
+	0xEEE3, 0x934F, 0xEEE4, 0x9371, 0xEEE5, 0x9377, 0xEEE6, 0x937B,
+	0xEEE7, 0x9361, 0xEEE8, 0x935E, 0xEEE9, 0x9363, 0xEEEA, 0x9367,
+	0xEEEB, 0x9380, 0xEEEC, 0x934E, 0xEEED, 0x9359, 0xEEEE, 0x95C7,
+	0xEEEF, 0x95C0, 0xEEF0, 0x95C9, 0xEEF1, 0x95C3, 0xEEF2, 0x95C5,
+	0xEEF3, 0x95B7, 0xEEF4, 0x96AE, 0xEEF5, 0x96B0, 0xEEF6, 0x96AC,
+	0xEEF7, 0x9720, 0xEEF8, 0x971F, 0xEEF9, 0x9718, 0xEEFA, 0x971D,
+	0xEEFB, 0x9719, 0xEEFC, 0x979A, 0xEEFD, 0x97A1, 0xEEFE, 0x979C,
+	0xEF40, 0x979E, 0xEF41, 0x979D, 0xEF42, 0x97D5, 0xEF43, 0x97D4,
+	0xEF44, 0x97F1, 0xEF45, 0x9841, 0xEF46, 0x9844, 0xEF47, 0x984A,
+	0xEF48, 0x9849, 0xEF49, 0x9845, 0xEF4A, 0x9843, 0xEF4B, 0x9925,
+	0xEF4C, 0x992B, 0xEF4D, 0x992C, 0xEF4E, 0x992A, 0xEF4F, 0x9933,
+	0xEF50, 0x9932, 0xEF51, 0x992F, 0xEF52, 0x992D, 0xEF53, 0x9931,
+	0xEF54, 0x9930, 0xEF55, 0x9998, 0xEF56, 0x99A3, 0xEF57, 0x99A1,
+	0xEF58, 0x9A02, 0xEF59, 0x99FA, 0xEF5A, 0x99F4, 0xEF5B, 0x99F7,
+	0xEF5C, 0x99F9, 0xEF5D, 0x99F8, 0xEF5E, 0x99F6, 0xEF5F, 0x99FB,
+	0xEF60, 0x99FD, 0xEF61, 0x99FE, 0xEF62, 0x99FC, 0xEF63, 0x9A03,
+	0xEF64, 0x9ABE, 0xEF65, 0x9AFE, 0xEF66, 0x9AFD, 0xEF67, 0x9B01,
+	0xEF68, 0x9AFC, 0xEF69, 0x9B48, 0xEF6A, 0x9B9A, 0xEF6B, 0x9BA8,
+	0xEF6C, 0x9B9E, 0xEF6D, 0x9B9B, 0xEF6E, 0x9BA6, 0xEF6F, 0x9BA1,
+	0xEF70, 0x9BA5, 0xEF71, 0x9BA4, 0xEF72, 0x9B86, 0xEF73, 0x9BA2,
+	0xEF74, 0x9BA0, 0xEF75, 0x9BAF, 0xEF76, 0x9D33, 0xEF77, 0x9D41,
+	0xEF78, 0x9D67, 0xEF79, 0x9D36, 0xEF7A, 0x9D2E, 0xEF7B, 0x9D2F,
+	0xEF7C, 0x9D31, 0xEF7D, 0x9D38, 0xEF7E, 0x9D30, 0xEFA1, 0x9D45,
+	0xEFA2, 0x9D42, 0xEFA3, 0x9D43, 0xEFA4, 0x9D3E, 0xEFA5, 0x9D37,
+	0xEFA6, 0x9D40, 0xEFA7, 0x9D3D, 0xEFA8, 0x7FF5, 0xEFA9, 0x9D2D,
+	0xEFAA, 0x9E8A, 0xEFAB, 0x9E89, 0xEFAC, 0x9E8D, 0xEFAD, 0x9EB0,
+	0xEFAE, 0x9EC8, 0xEFAF, 0x9EDA, 0xEFB0, 0x9EFB, 0xEFB1, 0x9EFF,
+	0xEFB2, 0x9F24, 0xEFB3, 0x9F23, 0xEFB4, 0x9F22, 0xEFB5, 0x9F54,
+	0xEFB6, 0x9FA0, 0xEFB7, 0x5131, 0xEFB8, 0x512D, 0xEFB9, 0x512E,
+	0xEFBA, 0x5698, 0xEFBB, 0x569C, 0xEFBC, 0x5697, 0xEFBD, 0x569A,
+	0xEFBE, 0x569D, 0xEFBF, 0x5699, 0xEFC0, 0x5970, 0xEFC1, 0x5B3C,
+	0xEFC2, 0x5C69, 0xEFC3, 0x5C6A, 0xEFC4, 0x5DC0, 0xEFC5, 0x5E6D,
+	0xEFC6, 0x5E6E, 0xEFC7, 0x61D8, 0xEFC8, 0x61DF, 0xEFC9, 0x61ED,
+	0xEFCA, 0x61EE, 0xEFCB, 0x61F1, 0xEFCC, 0x61EA, 0xEFCD, 0x61F0,
+	0xEFCE, 0x61EB, 0xEFCF, 0x61D6, 0xEFD0, 0x61E9, 0xEFD1, 0x64FF,
+	0xEFD2, 0x6504, 0xEFD3, 0x64FD, 0xEFD4, 0x64F8, 0xEFD5, 0x6501,
+	0xEFD6, 0x6503, 0xEFD7, 0x64FC, 0xEFD8, 0x6594, 0xEFD9, 0x65DB,
+	0xEFDA, 0x66DA, 0xEFDB, 0x66DB, 0xEFDC, 0x66D8, 0xEFDD, 0x6AC5,
+	0xEFDE, 0x6AB9, 0xEFDF, 0x6ABD, 0xEFE0, 0x6AE1, 0xEFE1, 0x6AC6,
+	0xEFE2, 0x6ABA, 0xEFE3, 0x6AB6, 0xEFE4, 0x6AB7, 0xEFE5, 0x6AC7,
+	0xEFE6, 0x6AB4, 0xEFE7, 0x6AAD, 0xEFE8, 0x6B5E, 0xEFE9, 0x6BC9,
+	0xEFEA, 0x6C0B, 0xEFEB, 0x7007, 0xEFEC, 0x700C, 0xEFED, 0x700D,
+	0xEFEE, 0x7001, 0xEFEF, 0x7005, 0xEFF0, 0x7014, 0xEFF1, 0x700E,
+	0xEFF2, 0x6FFF, 0xEFF3, 0x7000, 0xEFF4, 0x6FFB, 0xEFF5, 0x7026,
+	0xEFF6, 0x6FFC, 0xEFF7, 0x6FF7, 0xEFF8, 0x700A, 0xEFF9, 0x7201,
+	0xEFFA, 0x71FF, 0xEFFB, 0x71F9, 0xEFFC, 0x7203, 0xEFFD, 0x71FD,
+	0xEFFE, 0x7376, 0xF040, 0x74B8, 0xF041, 0x74C0, 0xF042, 0x74B5,
+	0xF043, 0x74C1, 0xF044, 0x74BE, 0xF045, 0x74B6, 0xF046, 0x74BB,
+	0xF047, 0x74C2, 0xF048, 0x7514, 0xF049, 0x7513, 0xF04A, 0x765C,
+	0xF04B, 0x7664, 0xF04C, 0x7659, 0xF04D, 0x7650, 0xF04E, 0x7653,
+	0xF04F, 0x7657, 0xF050, 0x765A, 0xF051, 0x76A6, 0xF052, 0x76BD,
+	0xF053, 0x76EC, 0xF054, 0x77C2, 0xF055, 0x77BA, 0xF056, 0x78FF,
+	0xF057, 0x790C, 0xF058, 0x7913, 0xF059, 0x7914, 0xF05A, 0x7909,
+	0xF05B, 0x7910, 0xF05C, 0x7912, 0xF05D, 0x7911, 0xF05E, 0x79AD,
+	0xF05F, 0x79AC, 0xF060, 0x7A5F, 0xF061, 0x7C1C, 0xF062, 0x7C29,
+	0xF063, 0x7C19, 0xF064, 0x7C20, 0xF065, 0x7C1F, 0xF066, 0x7C2D,
+	0xF067, 0x7C1D, 0xF068, 0x7C26, 0xF069, 0x7C28, 0xF06A, 0x7C22,
+	0xF06B, 0x7C25, 0xF06C, 0x7C30, 0xF06D, 0x7E5C, 0xF06E, 0x7E50,
+	0xF06F, 0x7E56, 0xF070, 0x7E63, 0xF071, 0x7E58, 0xF072, 0x7E62,
+	0xF073, 0x7E5F, 0xF074, 0x7E51, 0xF075, 0x7E60, 0xF076, 0x7E57,
+	0xF077, 0x7E53, 0xF078, 0x7FB5, 0xF079, 0x7FB3, 0xF07A, 0x7FF7,
+	0xF07B, 0x7FF8, 0xF07C, 0x8075, 0xF07D, 0x81D1, 0xF07E, 0x81D2,
+	0xF0A1, 0x81D0, 0xF0A2, 0x825F, 0xF0A3, 0x825E, 0xF0A4, 0x85B4,
+	0xF0A5, 0x85C6, 0xF0A6, 0x85C0, 0xF0A7, 0x85C3, 0xF0A8, 0x85C2,
+	0xF0A9, 0x85B3, 0xF0AA, 0x85B5, 0xF0AB, 0x85BD, 0xF0AC, 0x85C7,
+	0xF0AD, 0x85C4, 0xF0AE, 0x85BF, 0xF0AF, 0x85CB, 0xF0B0, 0x85CE,
+	0xF0B1, 0x85C8, 0xF0B2, 0x85C5, 0xF0B3, 0x85B1, 0xF0B4, 0x85B6,
+	0xF0B5, 0x85D2, 0xF0B6, 0x8624, 0xF0B7, 0x85B8, 0xF0B8, 0x85B7,
+	0xF0B9, 0x85BE, 0xF0BA, 0x8669, 0xF0BB, 0x87E7, 0xF0BC, 0x87E6,
+	0xF0BD, 0x87E2, 0xF0BE, 0x87DB, 0xF0BF, 0x87EB, 0xF0C0, 0x87EA,
+	0xF0C1, 0x87E5, 0xF0C2, 0x87DF, 0xF0C3, 0x87F3, 0xF0C4, 0x87E4,
+	0xF0C5, 0x87D4, 0xF0C6, 0x87DC, 0xF0C7, 0x87D3, 0xF0C8, 0x87ED,
+	0xF0C9, 0x87D8, 0xF0CA, 0x87E3, 0xF0CB, 0x87A4, 0xF0CC, 0x87D7,
+	0xF0CD, 0x87D9, 0xF0CE, 0x8801, 0xF0CF, 0x87F4, 0xF0D0, 0x87E8,
+	0xF0D1, 0x87DD, 0xF0D2, 0x8953, 0xF0D3, 0x894B, 0xF0D4, 0x894F,
+	0xF0D5, 0x894C, 0xF0D6, 0x8946, 0xF0D7, 0x8950, 0xF0D8, 0x8951,
+	0xF0D9, 0x8949, 0xF0DA, 0x8B2A, 0xF0DB, 0x8B27, 0xF0DC, 0x8B23,
+	0xF0DD, 0x8B33, 0xF0DE, 0x8B30, 0xF0DF, 0x8B35, 0xF0E0, 0x8B47,
+	0xF0E1, 0x8B2F, 0xF0E2, 0x8B3C, 0xF0E3, 0x8B3E, 0xF0E4, 0x8B31,
+	0xF0E5, 0x8B25, 0xF0E6, 0x8B37, 0xF0E7, 0x8B26, 0xF0E8, 0x8B36,
+	0xF0E9, 0x8B2E, 0xF0EA, 0x8B24, 0xF0EB, 0x8B3B, 0xF0EC, 0x8B3D,
+	0xF0ED, 0x8B3A, 0xF0EE, 0x8C42, 0xF0EF, 0x8C75, 0xF0F0, 0x8C99,
+	0xF0F1, 0x8C98, 0xF0F2, 0x8C97, 0xF0F3, 0x8CFE, 0xF0F4, 0x8D04,
+	0xF0F5, 0x8D02, 0xF0F6, 0x8D00, 0xF0F7, 0x8E5C, 0xF0F8, 0x8E62,
+	0xF0F9, 0x8E60, 0xF0FA, 0x8E57, 0xF0FB, 0x8E56, 0xF0FC, 0x8E5E,
+	0xF0FD, 0x8E65, 0xF0FE, 0x8E67, 0xF140, 0x8E5B, 0xF141, 0x8E5A,
+	0xF142, 0x8E61, 0xF143, 0x8E5D, 0xF144, 0x8E69, 0xF145, 0x8E54,
+	0xF146, 0x8F46, 0xF147, 0x8F47, 0xF148, 0x8F48, 0xF149, 0x8F4B,
+	0xF14A, 0x9128, 0xF14B, 0x913A, 0xF14C, 0x913B, 0xF14D, 0x913E,
+	0xF14E, 0x91A8, 0xF14F, 0x91A5, 0xF150, 0x91A7, 0xF151, 0x91AF,
+	0xF152, 0x91AA, 0xF153, 0x93B5, 0xF154, 0x938C, 0xF155, 0x9392,
+	0xF156, 0x93B7, 0xF157, 0x939B, 0xF158, 0x939D, 0xF159, 0x9389,
+	0xF15A, 0x93A7, 0xF15B, 0x938E, 0xF15C, 0x93AA, 0xF15D, 0x939E,
+	0xF15E, 0x93A6, 0xF15F, 0x9395, 0xF160, 0x9388, 0xF161, 0x9399,
+	0xF162, 0x939F, 0xF163, 0x938D, 0xF164, 0x93B1, 0xF165, 0x9391,
+	0xF166, 0x93B2, 0xF167, 0x93A4, 0xF168, 0x93A8, 0xF169, 0x93B4,
+	0xF16A, 0x93A3, 0xF16B, 0x93A5, 0xF16C, 0x95D2, 0xF16D, 0x95D3,
+	0xF16E, 0x95D1, 0xF16F, 0x96B3, 0xF170, 0x96D7, 0xF171, 0x96DA,
+	0xF172, 0x5DC2, 0xF173, 0x96DF, 0xF174, 0x96D8, 0xF175, 0x96DD,
+	0xF176, 0x9723, 0xF177, 0x9722, 0xF178, 0x9725, 0xF179, 0x97AC,
+	0xF17A, 0x97AE, 0xF17B, 0x97A8, 0xF17C, 0x97AB, 0xF17D, 0x97A4,
+	0xF17E, 0x97AA, 0xF1A1, 0x97A2, 0xF1A2, 0x97A5, 0xF1A3, 0x97D7,
+	0xF1A4, 0x97D9, 0xF1A5, 0x97D6, 0xF1A6, 0x97D8, 0xF1A7, 0x97FA,
+	0xF1A8, 0x9850, 0xF1A9, 0x9851, 0xF1AA, 0x9852, 0xF1AB, 0x98B8,
+	0xF1AC, 0x9941, 0xF1AD, 0x993C, 0xF1AE, 0x993A, 0xF1AF, 0x9A0F,
+	0xF1B0, 0x9A0B, 0xF1B1, 0x9A09, 0xF1B2, 0x9A0D, 0xF1B3, 0x9A04,
+	0xF1B4, 0x9A11, 0xF1B5, 0x9A0A, 0xF1B6, 0x9A05, 0xF1B7, 0x9A07,
+	0xF1B8, 0x9A06, 0xF1B9, 0x9AC0, 0xF1BA, 0x9ADC, 0xF1BB, 0x9B08,
+	0xF1BC, 0x9B04, 0xF1BD, 0x9B05, 0xF1BE, 0x9B29, 0xF1BF, 0x9B35,
+	0xF1C0, 0x9B4A, 0xF1C1, 0x9B4C, 0xF1C2, 0x9B4B, 0xF1C3, 0x9BC7,
+	0xF1C4, 0x9BC6, 0xF1C5, 0x9BC3, 0xF1C6, 0x9BBF, 0xF1C7, 0x9BC1,
+	0xF1C8, 0x9BB5, 0xF1C9, 0x9BB8, 0xF1CA, 0x9BD3, 0xF1CB, 0x9BB6,
+	0xF1CC, 0x9BC4, 0xF1CD, 0x9BB9, 0xF1CE, 0x9BBD, 0xF1CF, 0x9D5C,
+	0xF1D0, 0x9D53, 0xF1D1, 0x9D4F, 0xF1D2, 0x9D4A, 0xF1D3, 0x9D5B,
+	0xF1D4, 0x9D4B, 0xF1D5, 0x9D59, 0xF1D6, 0x9D56, 0xF1D7, 0x9D4C,
+	0xF1D8, 0x9D57, 0xF1D9, 0x9D52, 0xF1DA, 0x9D54, 0xF1DB, 0x9D5F,
+	0xF1DC, 0x9D58, 0xF1DD, 0x9D5A, 0xF1DE, 0x9E8E, 0xF1DF, 0x9E8C,
+	0xF1E0, 0x9EDF, 0xF1E1, 0x9F01, 0xF1E2, 0x9F00, 0xF1E3, 0x9F16,
+	0xF1E4, 0x9F25, 0xF1E5, 0x9F2B, 0xF1E6, 0x9F2A, 0xF1E7, 0x9F29,
+	0xF1E8, 0x9F28, 0xF1E9, 0x9F4C, 0xF1EA, 0x9F55, 0xF1EB, 0x5134,
+	0xF1EC, 0x5135, 0xF1ED, 0x5296, 0xF1EE, 0x52F7, 0xF1EF, 0x53B4,
+	0xF1F0, 0x56AB, 0xF1F1, 0x56AD, 0xF1F2, 0x56A6, 0xF1F3, 0x56A7,
+	0xF1F4, 0x56AA, 0xF1F5, 0x56AC, 0xF1F6, 0x58DA, 0xF1F7, 0x58DD,
+	0xF1F8, 0x58DB, 0xF1F9, 0x5912, 0xF1FA, 0x5B3D, 0xF1FB, 0x5B3E,
+	0xF1FC, 0x5B3F, 0xF1FD, 0x5DC3, 0xF1FE, 0x5E70, 0xF240, 0x5FBF,
+	0xF241, 0x61FB, 0xF242, 0x6507, 0xF243, 0x6510, 0xF244, 0x650D,
+	0xF245, 0x6509, 0xF246, 0x650C, 0xF247, 0x650E, 0xF248, 0x6584,
+	0xF249, 0x65DE, 0xF24A, 0x65DD, 0xF24B, 0x66DE, 0xF24C, 0x6AE7,
+	0xF24D, 0x6AE0, 0xF24E, 0x6ACC, 0xF24F, 0x6AD1, 0xF250, 0x6AD9,
+	0xF251, 0x6ACB, 0xF252, 0x6ADF, 0xF253, 0x6ADC, 0xF254, 0x6AD0,
+	0xF255, 0x6AEB, 0xF256, 0x6ACF, 0xF257, 0x6ACD, 0xF258, 0x6ADE,
+	0xF259, 0x6B60, 0xF25A, 0x6BB0, 0xF25B, 0x6C0C, 0xF25C, 0x7019,
+	0xF25D, 0x7027, 0xF25E, 0x7020, 0xF25F, 0x7016, 0xF260, 0x702B,
+	0xF261, 0x7021, 0xF262, 0x7022, 0xF263, 0x7023, 0xF264, 0x7029,
+	0xF265, 0x7017, 0xF266, 0x7024, 0xF267, 0x701C, 0xF268, 0x702A,
+	0xF269, 0x720C, 0xF26A, 0x720A, 0xF26B, 0x7207, 0xF26C, 0x7202,
+	0xF26D, 0x7205, 0xF26E, 0x72A5, 0xF26F, 0x72A6, 0xF270, 0x72A4,
+	0xF271, 0x72A3, 0xF272, 0x72A1, 0xF273, 0x74CB, 0xF274, 0x74C5,
+	0xF275, 0x74B7, 0xF276, 0x74C3, 0xF277, 0x7516, 0xF278, 0x7660,
+	0xF279, 0x77C9, 0xF27A, 0x77CA, 0xF27B, 0x77C4, 0xF27C, 0x77F1,
+	0xF27D, 0x791D, 0xF27E, 0x791B, 0xF2A1, 0x7921, 0xF2A2, 0x791C,
+	0xF2A3, 0x7917, 0xF2A4, 0x791E, 0xF2A5, 0x79B0, 0xF2A6, 0x7A67,
+	0xF2A7, 0x7A68, 0xF2A8, 0x7C33, 0xF2A9, 0x7C3C, 0xF2AA, 0x7C39,
+	0xF2AB, 0x7C2C, 0xF2AC, 0x7C3B, 0xF2AD, 0x7CEC, 0xF2AE, 0x7CEA,
+	0xF2AF, 0x7E76, 0xF2B0, 0x7E75, 0xF2B1, 0x7E78, 0xF2B2, 0x7E70,
+	0xF2B3, 0x7E77, 0xF2B4, 0x7E6F, 0xF2B5, 0x7E7A, 0xF2B6, 0x7E72,
+	0xF2B7, 0x7E74, 0xF2B8, 0x7E68, 0xF2B9, 0x7F4B, 0xF2BA, 0x7F4A,
+	0xF2BB, 0x7F83, 0xF2BC, 0x7F86, 0xF2BD, 0x7FB7, 0xF2BE, 0x7FFD,
+	0xF2BF, 0x7FFE, 0xF2C0, 0x8078, 0xF2C1, 0x81D7, 0xF2C2, 0x81D5,
+	0xF2C3, 0x8264, 0xF2C4, 0x8261, 0xF2C5, 0x8263, 0xF2C6, 0x85EB,
+	0xF2C7, 0x85F1, 0xF2C8, 0x85ED, 0xF2C9, 0x85D9, 0xF2CA, 0x85E1,
+	0xF2CB, 0x85E8, 0xF2CC, 0x85DA, 0xF2CD, 0x85D7, 0xF2CE, 0x85EC,
+	0xF2CF, 0x85F2, 0xF2D0, 0x85F8, 0xF2D1, 0x85D8, 0xF2D2, 0x85DF,
+	0xF2D3, 0x85E3, 0xF2D4, 0x85DC, 0xF2D5, 0x85D1, 0xF2D6, 0x85F0,
+	0xF2D7, 0x85E6, 0xF2D8, 0x85EF, 0xF2D9, 0x85DE, 0xF2DA, 0x85E2,
+	0xF2DB, 0x8800, 0xF2DC, 0x87FA, 0xF2DD, 0x8803, 0xF2DE, 0x87F6,
+	0xF2DF, 0x87F7, 0xF2E0, 0x8809, 0xF2E1, 0x880C, 0xF2E2, 0x880B,
+	0xF2E3, 0x8806, 0xF2E4, 0x87FC, 0xF2E5, 0x8808, 0xF2E6, 0x87FF,
+	0xF2E7, 0x880A, 0xF2E8, 0x8802, 0xF2E9, 0x8962, 0xF2EA, 0x895A,
+	0xF2EB, 0x895B, 0xF2EC, 0x8957, 0xF2ED, 0x8961, 0xF2EE, 0x895C,
+	0xF2EF, 0x8958, 0xF2F0, 0x895D, 0xF2F1, 0x8959, 0xF2F2, 0x8988,
+	0xF2F3, 0x89B7, 0xF2F4, 0x89B6, 0xF2F5, 0x89F6, 0xF2F6, 0x8B50,
+	0xF2F7, 0x8B48, 0xF2F8, 0x8B4A, 0xF2F9, 0x8B40, 0xF2FA, 0x8B53,
+	0xF2FB, 0x8B56, 0xF2FC, 0x8B54, 0xF2FD, 0x8B4B, 0xF2FE, 0x8B55,
+	0xF340, 0x8B51, 0xF341, 0x8B42, 0xF342, 0x8B52, 0xF343, 0x8B57,
+	0xF344, 0x8C43, 0xF345, 0x8C77, 0xF346, 0x8C76, 0xF347, 0x8C9A,
+	0xF348, 0x8D06, 0xF349, 0x8D07, 0xF34A, 0x8D09, 0xF34B, 0x8DAC,
+	0xF34C, 0x8DAA, 0xF34D, 0x8DAD, 0xF34E, 0x8DAB, 0xF34F, 0x8E6D,
+	0xF350, 0x8E78, 0xF351, 0x8E73, 0xF352, 0x8E6A, 0xF353, 0x8E6F,
+	0xF354, 0x8E7B, 0xF355, 0x8EC2, 0xF356, 0x8F52, 0xF357, 0x8F51,
+	0xF358, 0x8F4F, 0xF359, 0x8F50, 0xF35A, 0x8F53, 0xF35B, 0x8FB4,
+	0xF35C, 0x9140, 0xF35D, 0x913F, 0xF35E, 0x91B0, 0xF35F, 0x91AD,
+	0xF360, 0x93DE, 0xF361, 0x93C7, 0xF362, 0x93CF, 0xF363, 0x93C2,
+	0xF364, 0x93DA, 0xF365, 0x93D0, 0xF366, 0x93F9, 0xF367, 0x93EC,
+	0xF368, 0x93CC, 0xF369, 0x93D9, 0xF36A, 0x93A9, 0xF36B, 0x93E6,
+	0xF36C, 0x93CA, 0xF36D, 0x93D4, 0xF36E, 0x93EE, 0xF36F, 0x93E3,
+	0xF370, 0x93D5, 0xF371, 0x93C4, 0xF372, 0x93CE, 0xF373, 0x93C0,
+	0xF374, 0x93D2, 0xF375, 0x93E7, 0xF376, 0x957D, 0xF377, 0x95DA,
+	0xF378, 0x95DB, 0xF379, 0x96E1, 0xF37A, 0x9729, 0xF37B, 0x972B,
+	0xF37C, 0x972C, 0xF37D, 0x9728, 0xF37E, 0x9726, 0xF3A1, 0x97B3,
+	0xF3A2, 0x97B7, 0xF3A3, 0x97B6, 0xF3A4, 0x97DD, 0xF3A5, 0x97DE,
+	0xF3A6, 0x97DF, 0xF3A7, 0x985C, 0xF3A8, 0x9859, 0xF3A9, 0x985D,
+	0xF3AA, 0x9857, 0xF3AB, 0x98BF, 0xF3AC, 0x98BD, 0xF3AD, 0x98BB,
+	0xF3AE, 0x98BE, 0xF3AF, 0x9948, 0xF3B0, 0x9947, 0xF3B1, 0x9943,
+	0xF3B2, 0x99A6, 0xF3B3, 0x99A7, 0xF3B4, 0x9A1A, 0xF3B5, 0x9A15,
+	0xF3B6, 0x9A25, 0xF3B7, 0x9A1D, 0xF3B8, 0x9A24, 0xF3B9, 0x9A1B,
+	0xF3BA, 0x9A22, 0xF3BB, 0x9A20, 0xF3BC, 0x9A27, 0xF3BD, 0x9A23,
+	0xF3BE, 0x9A1E, 0xF3BF, 0x9A1C, 0xF3C0, 0x9A14, 0xF3C1, 0x9AC2,
+	0xF3C2, 0x9B0B, 0xF3C3, 0x9B0A, 0xF3C4, 0x9B0E, 0xF3C5, 0x9B0C,
+	0xF3C6, 0x9B37, 0xF3C7, 0x9BEA, 0xF3C8, 0x9BEB, 0xF3C9, 0x9BE0,
+	0xF3CA, 0x9BDE, 0xF3CB, 0x9BE4, 0xF3CC, 0x9BE6, 0xF3CD, 0x9BE2,
+	0xF3CE, 0x9BF0, 0xF3CF, 0x9BD4, 0xF3D0, 0x9BD7, 0xF3D1, 0x9BEC,
+	0xF3D2, 0x9BDC, 0xF3D3, 0x9BD9, 0xF3D4, 0x9BE5, 0xF3D5, 0x9BD5,
+	0xF3D6, 0x9BE1, 0xF3D7, 0x9BDA, 0xF3D8, 0x9D77, 0xF3D9, 0x9D81,
+	0xF3DA, 0x9D8A, 0xF3DB, 0x9D84, 0xF3DC, 0x9D88, 0xF3DD, 0x9D71,
+	0xF3DE, 0x9D80, 0xF3DF, 0x9D78, 0xF3E0, 0x9D86, 0xF3E1, 0x9D8B,
+	0xF3E2, 0x9D8C, 0xF3E3, 0x9D7D, 0xF3E4, 0x9D6B, 0xF3E5, 0x9D74,
+	0xF3E6, 0x9D75, 0xF3E7, 0x9D70, 0xF3E8, 0x9D69, 0xF3E9, 0x9D85,
+	0xF3EA, 0x9D73, 0xF3EB, 0x9D7B, 0xF3EC, 0x9D82, 0xF3ED, 0x9D6F,
+	0xF3EE, 0x9D79, 0xF3EF, 0x9D7F, 0xF3F0, 0x9D87, 0xF3F1, 0x9D68,
+	0xF3F2, 0x9E94, 0xF3F3, 0x9E91, 0xF3F4, 0x9EC0, 0xF3F5, 0x9EFC,
+	0xF3F6, 0x9F2D, 0xF3F7, 0x9F40, 0xF3F8, 0x9F41, 0xF3F9, 0x9F4D,
+	0xF3FA, 0x9F56, 0xF3FB, 0x9F57, 0xF3FC, 0x9F58, 0xF3FD, 0x5337,
+	0xF3FE, 0x56B2, 0xF440, 0x56B5, 0xF441, 0x56B3, 0xF442, 0x58E3,
+	0xF443, 0x5B45, 0xF444, 0x5DC6, 0xF445, 0x5DC7, 0xF446, 0x5EEE,
+	0xF447, 0x5EEF, 0xF448, 0x5FC0, 0xF449, 0x5FC1, 0xF44A, 0x61F9,
+	0xF44B, 0x6517, 0xF44C, 0x6516, 0xF44D, 0x6515, 0xF44E, 0x6513,
+	0xF44F, 0x65DF, 0xF450, 0x66E8, 0xF451, 0x66E3, 0xF452, 0x66E4,
+	0xF453, 0x6AF3, 0xF454, 0x6AF0, 0xF455, 0x6AEA, 0xF456, 0x6AE8,
+	0xF457, 0x6AF9, 0xF458, 0x6AF1, 0xF459, 0x6AEE, 0xF45A, 0x6AEF,
+	0xF45B, 0x703C, 0xF45C, 0x7035, 0xF45D, 0x702F, 0xF45E, 0x7037,
+	0xF45F, 0x7034, 0xF460, 0x7031, 0xF461, 0x7042, 0xF462, 0x7038,
+	0xF463, 0x703F, 0xF464, 0x703A, 0xF465, 0x7039, 0xF466, 0x7040,
+	0xF467, 0x703B, 0xF468, 0x7033, 0xF469, 0x7041, 0xF46A, 0x7213,
+	0xF46B, 0x7214, 0xF46C, 0x72A8, 0xF46D, 0x737D, 0xF46E, 0x737C,
+	0xF46F, 0x74BA, 0xF470, 0x76AB, 0xF471, 0x76AA, 0xF472, 0x76BE,
+	0xF473, 0x76ED, 0xF474, 0x77CC, 0xF475, 0x77CE, 0xF476, 0x77CF,
+	0xF477, 0x77CD, 0xF478, 0x77F2, 0xF479, 0x7925, 0xF47A, 0x7923,
+	0xF47B, 0x7927, 0xF47C, 0x7928, 0xF47D, 0x7924, 0xF47E, 0x7929,
+	0xF4A1, 0x79B2, 0xF4A2, 0x7A6E, 0xF4A3, 0x7A6C, 0xF4A4, 0x7A6D,
+	0xF4A5, 0x7AF7, 0xF4A6, 0x7C49, 0xF4A7, 0x7C48, 0xF4A8, 0x7C4A,
+	0xF4A9, 0x7C47, 0xF4AA, 0x7C45, 0xF4AB, 0x7CEE, 0xF4AC, 0x7E7B,
+	0xF4AD, 0x7E7E, 0xF4AE, 0x7E81, 0xF4AF, 0x7E80, 0xF4B0, 0x7FBA,
+	0xF4B1, 0x7FFF, 0xF4B2, 0x8079, 0xF4B3, 0x81DB, 0xF4B4, 0x81D9,
+	0xF4B5, 0x820B, 0xF4B6, 0x8268, 0xF4B7, 0x8269, 0xF4B8, 0x8622,
+	0xF4B9, 0x85FF, 0xF4BA, 0x8601, 0xF4BB, 0x85FE, 0xF4BC, 0x861B,
+	0xF4BD, 0x8600, 0xF4BE, 0x85F6, 0xF4BF, 0x8604, 0xF4C0, 0x8609,
+	0xF4C1, 0x8605, 0xF4C2, 0x860C, 0xF4C3, 0x85FD, 0xF4C4, 0x8819,
+	0xF4C5, 0x8810, 0xF4C6, 0x8811, 0xF4C7, 0x8817, 0xF4C8, 0x8813,
+	0xF4C9, 0x8816, 0xF4CA, 0x8963, 0xF4CB, 0x8966, 0xF4CC, 0x89B9,
+	0xF4CD, 0x89F7, 0xF4CE, 0x8B60, 0xF4CF, 0x8B6A, 0xF4D0, 0x8B5D,
+	0xF4D1, 0x8B68, 0xF4D2, 0x8B63, 0xF4D3, 0x8B65, 0xF4D4, 0x8B67,
+	0xF4D5, 0x8B6D, 0xF4D6, 0x8DAE, 0xF4D7, 0x8E86, 0xF4D8, 0x8E88,
+	0xF4D9, 0x8E84, 0xF4DA, 0x8F59, 0xF4DB, 0x8F56, 0xF4DC, 0x8F57,
+	0xF4DD, 0x8F55, 0xF4DE, 0x8F58, 0xF4DF, 0x8F5A, 0xF4E0, 0x908D,
+	0xF4E1, 0x9143, 0xF4E2, 0x9141, 0xF4E3, 0x91B7, 0xF4E4, 0x91B5,
+	0xF4E5, 0x91B2, 0xF4E6, 0x91B3, 0xF4E7, 0x940B, 0xF4E8, 0x9413,
+	0xF4E9, 0x93FB, 0xF4EA, 0x9420, 0xF4EB, 0x940F, 0xF4EC, 0x9414,
+	0xF4ED, 0x93FE, 0xF4EE, 0x9415, 0xF4EF, 0x9410, 0xF4F0, 0x9428,
+	0xF4F1, 0x9419, 0xF4F2, 0x940D, 0xF4F3, 0x93F5, 0xF4F4, 0x9400,
+	0xF4F5, 0x93F7, 0xF4F6, 0x9407, 0xF4F7, 0x940E, 0xF4F8, 0x9416,
+	0xF4F9, 0x9412, 0xF4FA, 0x93FA, 0xF4FB, 0x9409, 0xF4FC, 0x93F8,
+	0xF4FD, 0x940A, 0xF4FE, 0x93FF, 0xF540, 0x93FC, 0xF541, 0x940C,
+	0xF542, 0x93F6, 0xF543, 0x9411, 0xF544, 0x9406, 0xF545, 0x95DE,
+	0xF546, 0x95E0, 0xF547, 0x95DF, 0xF548, 0x972E, 0xF549, 0x972F,
+	0xF54A, 0x97B9, 0xF54B, 0x97BB, 0xF54C, 0x97FD, 0xF54D, 0x97FE,
+	0xF54E, 0x9860, 0xF54F, 0x9862, 0xF550, 0x9863, 0xF551, 0x985F,
+	0xF552, 0x98C1, 0xF553, 0x98C2, 0xF554, 0x9950, 0xF555, 0x994E,
+	0xF556, 0x9959, 0xF557, 0x994C, 0xF558, 0x994B, 0xF559, 0x9953,
+	0xF55A, 0x9A32, 0xF55B, 0x9A34, 0xF55C, 0x9A31, 0xF55D, 0x9A2C,
+	0xF55E, 0x9A2A, 0xF55F, 0x9A36, 0xF560, 0x9A29, 0xF561, 0x9A2E,
+	0xF562, 0x9A38, 0xF563, 0x9A2D, 0xF564, 0x9AC7, 0xF565, 0x9ACA,
+	0xF566, 0x9AC6, 0xF567, 0x9B10, 0xF568, 0x9B12, 0xF569, 0x9B11,
+	0xF56A, 0x9C0B, 0xF56B, 0x9C08, 0xF56C, 0x9BF7, 0xF56D, 0x9C05,
+	0xF56E, 0x9C12, 0xF56F, 0x9BF8, 0xF570, 0x9C40, 0xF571, 0x9C07,
+	0xF572, 0x9C0E, 0xF573, 0x9C06, 0xF574, 0x9C17, 0xF575, 0x9C14,
+	0xF576, 0x9C09, 0xF577, 0x9D9F, 0xF578, 0x9D99, 0xF579, 0x9DA4,
+	0xF57A, 0x9D9D, 0xF57B, 0x9D92, 0xF57C, 0x9D98, 0xF57D, 0x9D90,
+	0xF57E, 0x9D9B, 0xF5A1, 0x9DA0, 0xF5A2, 0x9D94, 0xF5A3, 0x9D9C,
+	0xF5A4, 0x9DAA, 0xF5A5, 0x9D97, 0xF5A6, 0x9DA1, 0xF5A7, 0x9D9A,
+	0xF5A8, 0x9DA2, 0xF5A9, 0x9DA8, 0xF5AA, 0x9D9E, 0xF5AB, 0x9DA3,
+	0xF5AC, 0x9DBF, 0xF5AD, 0x9DA9, 0xF5AE, 0x9D96, 0xF5AF, 0x9DA6,
+	0xF5B0, 0x9DA7, 0xF5B1, 0x9E99, 0xF5B2, 0x9E9B, 0xF5B3, 0x9E9A,
+	0xF5B4, 0x9EE5, 0xF5B5, 0x9EE4, 0xF5B6, 0x9EE7, 0xF5B7, 0x9EE6,
+	0xF5B8, 0x9F30, 0xF5B9, 0x9F2E, 0xF5BA, 0x9F5B, 0xF5BB, 0x9F60,
+	0xF5BC, 0x9F5E, 0xF5BD, 0x9F5D, 0xF5BE, 0x9F59, 0xF5BF, 0x9F91,
+	0xF5C0, 0x513A, 0xF5C1, 0x5139, 0xF5C2, 0x5298, 0xF5C3, 0x5297,
+	0xF5C4, 0x56C3, 0xF5C5, 0x56BD, 0xF5C6, 0x56BE, 0xF5C7, 0x5B48,
+	0xF5C8, 0x5B47, 0xF5C9, 0x5DCB, 0xF5CA, 0x5DCF, 0xF5CB, 0x5EF1,
+	0xF5CC, 0x61FD, 0xF5CD, 0x651B, 0xF5CE, 0x6B02, 0xF5CF, 0x6AFC,
+	0xF5D0, 0x6B03, 0xF5D1, 0x6AF8, 0xF5D2, 0x6B00, 0xF5D3, 0x7043,
+	0xF5D4, 0x7044, 0xF5D5, 0x704A, 0xF5D6, 0x7048, 0xF5D7, 0x7049,
+	0xF5D8, 0x7045, 0xF5D9, 0x7046, 0xF5DA, 0x721D, 0xF5DB, 0x721A,
+	0xF5DC, 0x7219, 0xF5DD, 0x737E, 0xF5DE, 0x7517, 0xF5DF, 0x766A,
+	0xF5E0, 0x77D0, 0xF5E1, 0x792D, 0xF5E2, 0x7931, 0xF5E3, 0x792F,
+	0xF5E4, 0x7C54, 0xF5E5, 0x7C53, 0xF5E6, 0x7CF2, 0xF5E7, 0x7E8A,
+	0xF5E8, 0x7E87, 0xF5E9, 0x7E88, 0xF5EA, 0x7E8B, 0xF5EB, 0x7E86,
+	0xF5EC, 0x7E8D, 0xF5ED, 0x7F4D, 0xF5EE, 0x7FBB, 0xF5EF, 0x8030,
+	0xF5F0, 0x81DD, 0xF5F1, 0x8618, 0xF5F2, 0x862A, 0xF5F3, 0x8626,
+	0xF5F4, 0x861F, 0xF5F5, 0x8623, 0xF5F6, 0x861C, 0xF5F7, 0x8619,
+	0xF5F8, 0x8627, 0xF5F9, 0x862E, 0xF5FA, 0x8621, 0xF5FB, 0x8620,
+	0xF5FC, 0x8629, 0xF5FD, 0x861E, 0xF5FE, 0x8625, 0xF640, 0x8829,
+	0xF641, 0x881D, 0xF642, 0x881B, 0xF643, 0x8820, 0xF644, 0x8824,
+	0xF645, 0x881C, 0xF646, 0x882B, 0xF647, 0x884A, 0xF648, 0x896D,
+	0xF649, 0x8969, 0xF64A, 0x896E, 0xF64B, 0x896B, 0xF64C, 0x89FA,
+	0xF64D, 0x8B79, 0xF64E, 0x8B78, 0xF64F, 0x8B45, 0xF650, 0x8B7A,
+	0xF651, 0x8B7B, 0xF652, 0x8D10, 0xF653, 0x8D14, 0xF654, 0x8DAF,
+	0xF655, 0x8E8E, 0xF656, 0x8E8C, 0xF657, 0x8F5E, 0xF658, 0x8F5B,
+	0xF659, 0x8F5D, 0xF65A, 0x9146, 0xF65B, 0x9144, 0xF65C, 0x9145,
+	0xF65D, 0x91B9, 0xF65E, 0x943F, 0xF65F, 0x943B, 0xF660, 0x9436,
+	0xF661, 0x9429, 0xF662, 0x943D, 0xF663, 0x943C, 0xF664, 0x9430,
+	0xF665, 0x9439, 0xF666, 0x942A, 0xF667, 0x9437, 0xF668, 0x942C,
+	0xF669, 0x9440, 0xF66A, 0x9431, 0xF66B, 0x95E5, 0xF66C, 0x95E4,
+	0xF66D, 0x95E3, 0xF66E, 0x9735, 0xF66F, 0x973A, 0xF670, 0x97BF,
+	0xF671, 0x97E1, 0xF672, 0x9864, 0xF673, 0x98C9, 0xF674, 0x98C6,
+	0xF675, 0x98C0, 0xF676, 0x9958, 0xF677, 0x9956, 0xF678, 0x9A39,
+	0xF679, 0x9A3D, 0xF67A, 0x9A46, 0xF67B, 0x9A44, 0xF67C, 0x9A42,
+	0xF67D, 0x9A41, 0xF67E, 0x9A3A, 0xF6A1, 0x9A3F, 0xF6A2, 0x9ACD,
+	0xF6A3, 0x9B15, 0xF6A4, 0x9B17, 0xF6A5, 0x9B18, 0xF6A6, 0x9B16,
+	0xF6A7, 0x9B3A, 0xF6A8, 0x9B52, 0xF6A9, 0x9C2B, 0xF6AA, 0x9C1D,
+	0xF6AB, 0x9C1C, 0xF6AC, 0x9C2C, 0xF6AD, 0x9C23, 0xF6AE, 0x9C28,
+	0xF6AF, 0x9C29, 0xF6B0, 0x9C24, 0xF6B1, 0x9C21, 0xF6B2, 0x9DB7,
+	0xF6B3, 0x9DB6, 0xF6B4, 0x9DBC, 0xF6B5, 0x9DC1, 0xF6B6, 0x9DC7,
+	0xF6B7, 0x9DCA, 0xF6B8, 0x9DCF, 0xF6B9, 0x9DBE, 0xF6BA, 0x9DC5,
+	0xF6BB, 0x9DC3, 0xF6BC, 0x9DBB, 0xF6BD, 0x9DB5, 0xF6BE, 0x9DCE,
+	0xF6BF, 0x9DB9, 0xF6C0, 0x9DBA, 0xF6C1, 0x9DAC, 0xF6C2, 0x9DC8,
+	0xF6C3, 0x9DB1, 0xF6C4, 0x9DAD, 0xF6C5, 0x9DCC, 0xF6C6, 0x9DB3,
+	0xF6C7, 0x9DCD, 0xF6C8, 0x9DB2, 0xF6C9, 0x9E7A, 0xF6CA, 0x9E9C,
+	0xF6CB, 0x9EEB, 0xF6CC, 0x9EEE, 0xF6CD, 0x9EED, 0xF6CE, 0x9F1B,
+	0xF6CF, 0x9F18, 0xF6D0, 0x9F1A, 0xF6D1, 0x9F31, 0xF6D2, 0x9F4E,
+	0xF6D3, 0x9F65, 0xF6D4, 0x9F64, 0xF6D5, 0x9F92, 0xF6D6, 0x4EB9,
+	0xF6D7, 0x56C6, 0xF6D8, 0x56C5, 0xF6D9, 0x56CB, 0xF6DA, 0x5971,
+	0xF6DB, 0x5B4B, 0xF6DC, 0x5B4C, 0xF6DD, 0x5DD5, 0xF6DE, 0x5DD1,
+	0xF6DF, 0x5EF2, 0xF6E0, 0x6521, 0xF6E1, 0x6520, 0xF6E2, 0x6526,
+	0xF6E3, 0x6522, 0xF6E4, 0x6B0B, 0xF6E5, 0x6B08, 0xF6E6, 0x6B09,
+	0xF6E7, 0x6C0D, 0xF6E8, 0x7055, 0xF6E9, 0x7056, 0xF6EA, 0x7057,
+	0xF6EB, 0x7052, 0xF6EC, 0x721E, 0xF6ED, 0x721F, 0xF6EE, 0x72A9,
+	0xF6EF, 0x737F, 0xF6F0, 0x74D8, 0xF6F1, 0x74D5, 0xF6F2, 0x74D9,
+	0xF6F3, 0x74D7, 0xF6F4, 0x766D, 0xF6F5, 0x76AD, 0xF6F6, 0x7935,
+	0xF6F7, 0x79B4, 0xF6F8, 0x7A70, 0xF6F9, 0x7A71, 0xF6FA, 0x7C57,
+	0xF6FB, 0x7C5C, 0xF6FC, 0x7C59, 0xF6FD, 0x7C5B, 0xF6FE, 0x7C5A,
+	0xF740, 0x7CF4, 0xF741, 0x7CF1, 0xF742, 0x7E91, 0xF743, 0x7F4F,
+	0xF744, 0x7F87, 0xF745, 0x81DE, 0xF746, 0x826B, 0xF747, 0x8634,
+	0xF748, 0x8635, 0xF749, 0x8633, 0xF74A, 0x862C, 0xF74B, 0x8632,
+	0xF74C, 0x8636, 0xF74D, 0x882C, 0xF74E, 0x8828, 0xF74F, 0x8826,
+	0xF750, 0x882A, 0xF751, 0x8825, 0xF752, 0x8971, 0xF753, 0x89BF,
+	0xF754, 0x89BE, 0xF755, 0x89FB, 0xF756, 0x8B7E, 0xF757, 0x8B84,
+	0xF758, 0x8B82, 0xF759, 0x8B86, 0xF75A, 0x8B85, 0xF75B, 0x8B7F,
+	0xF75C, 0x8D15, 0xF75D, 0x8E95, 0xF75E, 0x8E94, 0xF75F, 0x8E9A,
+	0xF760, 0x8E92, 0xF761, 0x8E90, 0xF762, 0x8E96, 0xF763, 0x8E97,
+	0xF764, 0x8F60, 0xF765, 0x8F62, 0xF766, 0x9147, 0xF767, 0x944C,
+	0xF768, 0x9450, 0xF769, 0x944A, 0xF76A, 0x944B, 0xF76B, 0x944F,
+	0xF76C, 0x9447, 0xF76D, 0x9445, 0xF76E, 0x9448, 0xF76F, 0x9449,
+	0xF770, 0x9446, 0xF771, 0x973F, 0xF772, 0x97E3, 0xF773, 0x986A,
+	0xF774, 0x9869, 0xF775, 0x98CB, 0xF776, 0x9954, 0xF777, 0x995B,
+	0xF778, 0x9A4E, 0xF779, 0x9A53, 0xF77A, 0x9A54, 0xF77B, 0x9A4C,
+	0xF77C, 0x9A4F, 0xF77D, 0x9A48, 0xF77E, 0x9A4A, 0xF7A1, 0x9A49,
+	0xF7A2, 0x9A52, 0xF7A3, 0x9A50, 0xF7A4, 0x9AD0, 0xF7A5, 0x9B19,
+	0xF7A6, 0x9B2B, 0xF7A7, 0x9B3B, 0xF7A8, 0x9B56, 0xF7A9, 0x9B55,
+	0xF7AA, 0x9C46, 0xF7AB, 0x9C48, 0xF7AC, 0x9C3F, 0xF7AD, 0x9C44,
+	0xF7AE, 0x9C39, 0xF7AF, 0x9C33, 0xF7B0, 0x9C41, 0xF7B1, 0x9C3C,
+	0xF7B2, 0x9C37, 0xF7B3, 0x9C34, 0xF7B4, 0x9C32, 0xF7B5, 0x9C3D,
+	0xF7B6, 0x9C36, 0xF7B7, 0x9DDB, 0xF7B8, 0x9DD2, 0xF7B9, 0x9DDE,
+	0xF7BA, 0x9DDA, 0xF7BB, 0x9DCB, 0xF7BC, 0x9DD0, 0xF7BD, 0x9DDC,
+	0xF7BE, 0x9DD1, 0xF7BF, 0x9DDF, 0xF7C0, 0x9DE9, 0xF7C1, 0x9DD9,
+	0xF7C2, 0x9DD8, 0xF7C3, 0x9DD6, 0xF7C4, 0x9DF5, 0xF7C5, 0x9DD5,
+	0xF7C6, 0x9DDD, 0xF7C7, 0x9EB6, 0xF7C8, 0x9EF0, 0xF7C9, 0x9F35,
+	0xF7CA, 0x9F33, 0xF7CB, 0x9F32, 0xF7CC, 0x9F42, 0xF7CD, 0x9F6B,
+	0xF7CE, 0x9F95, 0xF7CF, 0x9FA2, 0xF7D0, 0x513D, 0xF7D1, 0x5299,
+	0xF7D2, 0x58E8, 0xF7D3, 0x58E7, 0xF7D4, 0x5972, 0xF7D5, 0x5B4D,
+	0xF7D6, 0x5DD8, 0xF7D7, 0x882F, 0xF7D8, 0x5F4F, 0xF7D9, 0x6201,
+	0xF7DA, 0x6203, 0xF7DB, 0x6204, 0xF7DC, 0x6529, 0xF7DD, 0x6525,
+	0xF7DE, 0x6596, 0xF7DF, 0x66EB, 0xF7E0, 0x6B11, 0xF7E1, 0x6B12,
+	0xF7E2, 0x6B0F, 0xF7E3, 0x6BCA, 0xF7E4, 0x705B, 0xF7E5, 0x705A,
+	0xF7E6, 0x7222, 0xF7E7, 0x7382, 0xF7E8, 0x7381, 0xF7E9, 0x7383,
+	0xF7EA, 0x7670, 0xF7EB, 0x77D4, 0xF7EC, 0x7C67, 0xF7ED, 0x7C66,
+	0xF7EE, 0x7E95, 0xF7EF, 0x826C, 0xF7F0, 0x863A, 0xF7F1, 0x8640,
+	0xF7F2, 0x8639, 0xF7F3, 0x863C, 0xF7F4, 0x8631, 0xF7F5, 0x863B,
+	0xF7F6, 0x863E, 0xF7F7, 0x8830, 0xF7F8, 0x8832, 0xF7F9, 0x882E,
+	0xF7FA, 0x8833, 0xF7FB, 0x8976, 0xF7FC, 0x8974, 0xF7FD, 0x8973,
+	0xF7FE, 0x89FE, 0xF840, 0x8B8C, 0xF841, 0x8B8E, 0xF842, 0x8B8B,
+	0xF843, 0x8B88, 0xF844, 0x8C45, 0xF845, 0x8D19, 0xF846, 0x8E98,
+	0xF847, 0x8F64, 0xF848, 0x8F63, 0xF849, 0x91BC, 0xF84A, 0x9462,
+	0xF84B, 0x9455, 0xF84C, 0x945D, 0xF84D, 0x9457, 0xF84E, 0x945E,
+	0xF84F, 0x97C4, 0xF850, 0x97C5, 0xF851, 0x9800, 0xF852, 0x9A56,
+	0xF853, 0x9A59, 0xF854, 0x9B1E, 0xF855, 0x9B1F, 0xF856, 0x9B20,
+	0xF857, 0x9C52, 0xF858, 0x9C58, 0xF859, 0x9C50, 0xF85A, 0x9C4A,
+	0xF85B, 0x9C4D, 0xF85C, 0x9C4B, 0xF85D, 0x9C55, 0xF85E, 0x9C59,
+	0xF85F, 0x9C4C, 0xF860, 0x9C4E, 0xF861, 0x9DFB, 0xF862, 0x9DF7,
+	0xF863, 0x9DEF, 0xF864, 0x9DE3, 0xF865, 0x9DEB, 0xF866, 0x9DF8,
+	0xF867, 0x9DE4, 0xF868, 0x9DF6, 0xF869, 0x9DE1, 0xF86A, 0x9DEE,
+	0xF86B, 0x9DE6, 0xF86C, 0x9DF2, 0xF86D, 0x9DF0, 0xF86E, 0x9DE2,
+	0xF86F, 0x9DEC, 0xF870, 0x9DF4, 0xF871, 0x9DF3, 0xF872, 0x9DE8,
+	0xF873, 0x9DED, 0xF874, 0x9EC2, 0xF875, 0x9ED0, 0xF876, 0x9EF2,
+	0xF877, 0x9EF3, 0xF878, 0x9F06, 0xF879, 0x9F1C, 0xF87A, 0x9F38,
+	0xF87B, 0x9F37, 0xF87C, 0x9F36, 0xF87D, 0x9F43, 0xF87E, 0x9F4F,
+	0xF8A1, 0x9F71, 0xF8A2, 0x9F70, 0xF8A3, 0x9F6E, 0xF8A4, 0x9F6F,
+	0xF8A5, 0x56D3, 0xF8A6, 0x56CD, 0xF8A7, 0x5B4E, 0xF8A8, 0x5C6D,
+	0xF8A9, 0x652D, 0xF8AA, 0x66ED, 0xF8AB, 0x66EE, 0xF8AC, 0x6B13,
+	0xF8AD, 0x705F, 0xF8AE, 0x7061, 0xF8AF, 0x705D, 0xF8B0, 0x7060,
+	0xF8B1, 0x7223, 0xF8B2, 0x74DB, 0xF8B3, 0x74E5, 0xF8B4, 0x77D5,
+	0xF8B5, 0x7938, 0xF8B6, 0x79B7, 0xF8B7, 0x79B6, 0xF8B8, 0x7C6A,
+	0xF8B9, 0x7E97, 0xF8BA, 0x7F89, 0xF8BB, 0x826D, 0xF8BC, 0x8643,
+	0xF8BD, 0x8838, 0xF8BE, 0x8837, 0xF8BF, 0x8835, 0xF8C0, 0x884B,
+	0xF8C1, 0x8B94, 0xF8C2, 0x8B95, 0xF8C3, 0x8E9E, 0xF8C4, 0x8E9F,
+	0xF8C5, 0x8EA0, 0xF8C6, 0x8E9D, 0xF8C7, 0x91BE, 0xF8C8, 0x91BD,
+	0xF8C9, 0x91C2, 0xF8CA, 0x946B, 0xF8CB, 0x9468, 0xF8CC, 0x9469,
+	0xF8CD, 0x96E5, 0xF8CE, 0x9746, 0xF8CF, 0x9743, 0xF8D0, 0x9747,
+	0xF8D1, 0x97C7, 0xF8D2, 0x97E5, 0xF8D3, 0x9A5E, 0xF8D4, 0x9AD5,
+	0xF8D5, 0x9B59, 0xF8D6, 0x9C63, 0xF8D7, 0x9C67, 0xF8D8, 0x9C66,
+	0xF8D9, 0x9C62, 0xF8DA, 0x9C5E, 0xF8DB, 0x9C60, 0xF8DC, 0x9E02,
+	0xF8DD, 0x9DFE, 0xF8DE, 0x9E07, 0xF8DF, 0x9E03, 0xF8E0, 0x9E06,
+	0xF8E1, 0x9E05, 0xF8E2, 0x9E00, 0xF8E3, 0x9E01, 0xF8E4, 0x9E09,
+	0xF8E5, 0x9DFF, 0xF8E6, 0x9DFD, 0xF8E7, 0x9E04, 0xF8E8, 0x9EA0,
+	0xF8E9, 0x9F1E, 0xF8EA, 0x9F46, 0xF8EB, 0x9F74, 0xF8EC, 0x9F75,
+	0xF8ED, 0x9F76, 0xF8EE, 0x56D4, 0xF8EF, 0x652E, 0xF8F0, 0x65B8,
+	0xF8F1, 0x6B18, 0xF8F2, 0x6B19, 0xF8F3, 0x6B17, 0xF8F4, 0x6B1A,
+	0xF8F5, 0x7062, 0xF8F6, 0x7226, 0xF8F7, 0x72AA, 0xF8F8, 0x77D8,
+	0xF8F9, 0x77D9, 0xF8FA, 0x7939, 0xF8FB, 0x7C69, 0xF8FC, 0x7C6B,
+	0xF8FD, 0x7CF6, 0xF8FE, 0x7E9A, 0xF940, 0x7E98, 0xF941, 0x7E9B,
+	0xF942, 0x7E99, 0xF943, 0x81E0, 0xF944, 0x81E1, 0xF945, 0x8646,
+	0xF946, 0x8647, 0xF947, 0x8648, 0xF948, 0x8979, 0xF949, 0x897A,
+	0xF94A, 0x897C, 0xF94B, 0x897B, 0xF94C, 0x89FF, 0xF94D, 0x8B98,
+	0xF94E, 0x8B99, 0xF94F, 0x8EA5, 0xF950, 0x8EA4, 0xF951, 0x8EA3,
+	0xF952, 0x946E, 0xF953, 0x946D, 0xF954, 0x946F, 0xF955, 0x9471,
+	0xF956, 0x9473, 0xF957, 0x9749, 0xF958, 0x9872, 0xF959, 0x995F,
+	0xF95A, 0x9C68, 0xF95B, 0x9C6E, 0xF95C, 0x9C6D, 0xF95D, 0x9E0B,
+	0xF95E, 0x9E0D, 0xF95F, 0x9E10, 0xF960, 0x9E0F, 0xF961, 0x9E12,
+	0xF962, 0x9E11, 0xF963, 0x9EA1, 0xF964, 0x9EF5, 0xF965, 0x9F09,
+	0xF966, 0x9F47, 0xF967, 0x9F78, 0xF968, 0x9F7B, 0xF969, 0x9F7A,
+	0xF96A, 0x9F79, 0xF96B, 0x571E, 0xF96C, 0x7066, 0xF96D, 0x7C6F,
+	0xF96E, 0x883C, 0xF96F, 0x8DB2, 0xF970, 0x8EA6, 0xF971, 0x91C3,
+	0xF972, 0x9474, 0xF973, 0x9478, 0xF974, 0x9476, 0xF975, 0x9475,
+	0xF976, 0x9A60, 0xF977, 0x9C74, 0xF978, 0x9C73, 0xF979, 0x9C71,
+	0xF97A, 0x9C75, 0xF97B, 0x9E14, 0xF97C, 0x9E13, 0xF97D, 0x9EF6,
+	0xF97E, 0x9F0A, 0xF9A1, 0x9FA4, 0xF9A2, 0x7068, 0xF9A3, 0x7065,
+	0xF9A4, 0x7CF7, 0xF9A5, 0x866A, 0xF9A6, 0x883E, 0xF9A7, 0x883D,
+	0xF9A8, 0x883F, 0xF9A9, 0x8B9E, 0xF9AA, 0x8C9C, 0xF9AB, 0x8EA9,
+	0xF9AC, 0x8EC9, 0xF9AD, 0x974B, 0xF9AE, 0x9873, 0xF9AF, 0x9874,
+	0xF9B0, 0x98CC, 0xF9B1, 0x9961, 0xF9B2, 0x99AB, 0xF9B3, 0x9A64,
+	0xF9B4, 0x9A66, 0xF9B5, 0x9A67, 0xF9B6, 0x9B24, 0xF9B7, 0x9E15,
+	0xF9B8, 0x9E17, 0xF9B9, 0x9F48, 0xF9BA, 0x6207, 0xF9BB, 0x6B1E,
+	0xF9BC, 0x7227, 0xF9BD, 0x864C, 0xF9BE, 0x8EA8, 0xF9BF, 0x9482,
+	0xF9C0, 0x9480, 0xF9C1, 0x9481, 0xF9C2, 0x9A69, 0xF9C3, 0x9A68,
+	0xF9C4, 0x9B2E, 0xF9C5, 0x9E19, 0xF9C6, 0x7229, 0xF9C7, 0x864B,
+	0xF9C8, 0x8B9F, 0xF9C9, 0x9483, 0xF9CA, 0x9C79, 0xF9CB, 0x9EB7,
+	0xF9CC, 0x7675, 0xF9CD, 0x9A6B, 0xF9CE, 0x9C7A, 0xF9CF, 0x9E1D,
+	0xF9D0, 0x7069, 0xF9D1, 0x706A, 0xF9D2, 0x9EA4, 0xF9D3, 0x9F7E,
+	0xF9D4, 0x9F49, 0xF9D5, 0x9F98, 0xF9D6, 0x7881, 0xF9D7, 0x92B9,
+	0xF9D8, 0x88CF, 0xF9D9, 0x58BB, 0xF9DA, 0x6052, 0xF9DB, 0x7CA7,
+	0xF9DC, 0x5AFA, 0xF9DD, 0x2554, 0xF9DE, 0x2566, 0xF9DF, 0x2557,
+	0xF9E0, 0x2560, 0xF9E1, 0x256C, 0xF9E2, 0x2563, 0xF9E3, 0x255A,
+	0xF9E4, 0x2569, 0xF9E5, 0x255D, 0xF9E6, 0x2552, 0xF9E7, 0x2564,
+	0xF9E8, 0x2555, 0xF9E9, 0x255E, 0xF9EA, 0x256A, 0xF9EB, 0x2561,
+	0xF9EC, 0x2558, 0xF9ED, 0x2567, 0xF9EE, 0x255B, 0xF9EF, 0x2553,
+	0xF9F0, 0x2565, 0xF9F1, 0x2556, 0xF9F2, 0x255F, 0xF9F3, 0x256B,
+	0xF9F4, 0x2562, 0xF9F5, 0x2559, 0xF9F6, 0x2568, 0xF9F7, 0x255C,
+	0xF9F8, 0x2551, 0xF9F9, 0x2550, 0xF9FA, 0x256D, 0xF9FB, 0x256E,
+	0xF9FC, 0x2570, 0xF9FD, 0x256F, 0xF9FE, 0x2593, 0, 0
+};
+
+
+
+WCHAR ff_convert (	/* Converted code, 0 means conversion error */
+	WCHAR	src,	/* Character code to be converted */
+	UINT	dir		/* 0: Unicode to OEMCP, 1: OEMCP to Unicode */
+)
+{
+	const WCHAR *p;
+	WCHAR c;
+	int i, n, li, hi;
+
+
+	if (src < 0x80) {	/* ASCII */
+		c = src;
+	} else {
+		if (dir) {		/* OEMCP to unicode */
+			p = oem2uni;
+			hi = sizeof(oem2uni) / 4 - 1;
+		} else {		/* Unicode to OEMCP */
+			p = uni2oem;
+			hi = sizeof(uni2oem) / 4 - 1;
+		}
+		li = 0;
+		for (n = 16; n; n--) {
+			i = li + (hi - li) / 2;
+			if (src == p[i * 2]) break;
+			if (src > p[i * 2])
+				li = i;
+			else
+				hi = i;
+		}
+		c = n ? p[i * 2 + 1] : 0;
+	}
+
+	return c;
+}
+#else
+#error This file is not needed in current configuration.
+
+#endif
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/option/ccsbcs.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/option/ccsbcs.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/option/ccsbcs.c	(revision 453)
@@ -0,0 +1,332 @@
+/*------------------------------------------------------------------------*/
+/* Unicode - OEM code bidirectional converter  (C)ChaN, 2009              */
+/*                                                                        */
+/* SBCS code                                                              */
+/*------------------------------------------------------------------------*/
+
+#include "../ff.h"
+
+
+#if _USE_LFN && _CODE_PAGE == 437
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {	/*  CP437(0x80-0xFF) to Unicode conversion table */
+	0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
+	0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
+	0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
+	0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
+	0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
+	0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
+	0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
+	0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
+	0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
+	0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
+	0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
+	0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
+	0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4,
+	0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
+	0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248,
+	0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
+};
+
+#elif _CODE_PAGE == 720
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {	/*  CP720(0x80-0xFF) to Unicode conversion table */
+	0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7,
+	0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9,
+	0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627,
+	0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F,
+	0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB,
+	0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
+	0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
+	0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
+	0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
+	0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
+	0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
+	0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x00B5, 0x0642,
+	0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A,
+	0x2261, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0xO650, 0x2248,
+	0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
+};
+
+#elif _CODE_PAGE == 737
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {	/*  CP737(0x80-0xFF) to Unicode conversion table */
+	0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398,
+	0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0,
+	0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9,
+	0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8,
+	0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0,
+	0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8,
+	0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
+	0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
+	0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
+	0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
+	0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
+	0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
+	0x03C9, 0x03AC, 0x03AD, 0x03AE, 0x03CA, 0x03AF, 0x03CC, 0x03CD,
+	0x03CB, 0x03CE, 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E,
+	0x038F, 0x00B1, 0x2265, 0x2264, 0x03AA, 0x03AB, 0x00F7, 0x2248,
+	0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
+};
+
+#elif _CODE_PAGE == 775
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {	/*  CP775(0x80-0xFF) to Unicode conversion table */
+	0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107,
+	0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5,
+	0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A,
+	0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4,
+	0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6,
+	0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB,
+	0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0104, 0x010C, 0x0118,
+	0x0116, 0x2563, 0x2551, 0x2557, 0x255D, 0x012E, 0x0160, 0x2510,
+	0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0172, 0x016A,
+	0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x017D,
+	0x0105, 0x010D, 0x0119, 0x0117, 0x012F, 0x0161, 0x0173, 0x016B,
+	0x017E, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
+	0x00D3, 0x00DF, 0x014C, 0x0143, 0x00F5, 0x00D5, 0x00B5, 0x0144,
+	0x0136, 0x0137, 0x013B, 0x013C, 0x0146, 0x0112, 0x0145, 0x2019,
+	0x00AD, 0x00B1, 0x201C, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x201E,
+	0x00B0, 0x2219, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
+};
+
+#elif _CODE_PAGE == 850
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {	/*  CP850(0x80-0xFF) to Unicode conversion table */
+	0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
+	0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
+	0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
+	0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192,
+	0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
+	0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
+	0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0,
+	0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
+	0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3,
+	0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
+	0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE,
+	0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
+	0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE,
+	0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4,
+	0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8,
+	0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
+};
+
+#elif _CODE_PAGE == 852
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {	/*  CP852(0x80-0xFF) to Unicode conversion table */
+	0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7,
+	0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106,
+	0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A,
+	0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D,
+	0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E,
+	0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB,
+	0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x011A,
+	0x015E, 0x2563, 0x2551, 0x2557, 0x255D, 0x017B, 0x017C, 0x2510,
+	0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0102, 0x0103,
+	0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
+	0x0111, 0x0110, 0x010E, 0x00CB, 0x010F, 0x0147, 0x00CD, 0x00CE,
+	0x011B, 0x2518, 0x250C, 0x2588, 0x2584, 0x0162, 0x016E, 0x2580,
+	0x00D3, 0x00DF, 0x00D4, 0x0143, 0x0144, 0x0148, 0x0160, 0x0161,
+	0x0154, 0x00DA, 0x0155, 0x0170, 0x00FD, 0x00DD, 0x0163, 0x00B4,
+	0x00AD, 0x02DD, 0x02DB, 0x02C7, 0x02D8, 0x00A7, 0x00F7, 0x00B8,
+	0x00B0, 0x00A8, 0x02D9, 0x0171, 0x0158, 0x0159, 0x25A0, 0x00A0
+};
+
+#elif _CODE_PAGE == 855
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {	/*  CP855(0x80-0xFF) to Unicode conversion table */
+	0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404,
+	0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408,
+	0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C,
+	0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A,
+	0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414,
+	0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB,
+	0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0445, 0x0425, 0x0438,
+	0x0418, 0x2563, 0x2551, 0x2557, 0x255D, 0x0439, 0x0419, 0x2510,
+	0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x043A, 0x041A,
+	0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
+	0x043B, 0x041B, 0x043C, 0x041C, 0x043D, 0x041D, 0x043E, 0x041E,
+	0x043F, 0x2518, 0x250C, 0x2588, 0x2584, 0x041F, 0x044F, 0x2580,
+	0x042F, 0x0440, 0x0420, 0x0441, 0x0421, 0x0442, 0x0422, 0x0443,
+	0x0423, 0x0436, 0x0416, 0x0432, 0x0412, 0x044C, 0x042C, 0x2116,
+	0x00AD, 0x044B, 0x042B, 0x0437, 0x0417, 0x0448, 0x0428, 0x044D,
+	0x042D, 0x0449, 0x0429, 0x0447, 0x0427, 0x00A7, 0x25A0, 0x00A0
+};
+
+#elif _CODE_PAGE == 857
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {	/*  CP857(0x80-0xFF) to Unicode conversion table */
+	0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
+	0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5,
+	0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
+	0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F,
+	0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F,
+	0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
+	0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0,
+	0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
+	0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3,
+	0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
+	0x00BA, 0x00AA, 0x00CA, 0x00CB, 0x00C8, 0x0000, 0x00CD, 0x00CE,
+	0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
+	0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x0000,
+	0x00D7, 0x00DA, 0x00DB, 0x00D9, 0x00EC, 0x00FF, 0x00AF, 0x00B4,
+	0x00AD, 0x00B1, 0x0000, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8,
+	0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
+};
+
+#elif _CODE_PAGE == 858
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {	/*  CP858(0x80-0xFF) to Unicode conversion table */
+	0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
+	0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
+	0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
+	0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192,
+	0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
+	0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
+	0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0,
+	0x00A9, 0x2563, 0x2551, 0x2557, 0x2550, 0x00A2, 0x00A5, 0x2510,
+	0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3,
+	0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
+	0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x20AC, 0x00CD, 0x00CE,
+	0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00C6, 0x00CC, 0x2580,
+	0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE,
+	0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4,
+	0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8,
+	0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
+};
+
+#elif _CODE_PAGE == 862
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {	/*  CP862(0x80-0xFF) to Unicode conversion table */
+	0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
+	0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
+	0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
+	0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
+	0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
+	0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
+	0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
+	0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
+	0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
+	0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
+	0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
+	0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
+	0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4,
+	0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
+	0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248,
+	0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
+};
+
+#elif _CODE_PAGE == 866
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {	/*  CP866(0x80-0xFF) to Unicode conversion table */
+	0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
+	0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
+	0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
+	0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
+	0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
+	0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
+	0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
+	0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
+	0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
+	0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
+	0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
+	0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
+	0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
+	0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
+	0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E,
+	0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0
+};
+
+#elif _CODE_PAGE == 874
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {	/*  CP874(0x80-0xFF) to Unicode conversion table */
+	0x20AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x2026, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07,
+	0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F,
+	0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17,
+	0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F,
+	0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27,
+	0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F,
+	0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37,
+	0x0E38, 0x0E39, 0x0E3A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0E3F,
+	0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47,
+	0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F,
+	0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57,
+	0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+#elif _CODE_PAGE == 1258
+#define _TBLDEF 1
+static
+const WCHAR Tbl[] = {	/*  CP1258(0x80-0xFF) to Unicode conversion table */
+	0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
+	0x02C6, 0x2030, 0x0000, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+	0x02DC, 0x2122, 0x0000, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178,
+	0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+	0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+	0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+	0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+	0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+	0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x0300, 0x00CD, 0x00CE, 0x00CF,
+	0x0110, 0x00D1, 0x0309, 0x00D3, 0x00D4, 0x01A0, 0x00D6, 0x00D7,
+	0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x01AF, 0x0303, 0x00DF,
+	0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+	0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0301, 0x00ED, 0x00EE, 0x00EF,
+	0x0111, 0x00F1, 0x0323, 0x00F3, 0x00F4, 0x01A1, 0x00F6, 0x00F7,
+	0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x01B0, 0x20AB, 0x00FF
+};
+
+#endif
+
+
+#if _TBLDEF
+
+WCHAR ff_convert (	/* Converted code, 0 means conversion error */
+	WCHAR	src,	/* Character code to be converted */
+	UINT	dir		/* 0: Unicode to OEMCP, 1: OEMCP to Unicode */
+)
+{
+	const WCHAR *p;
+	WCHAR c;
+
+
+	if (src < 0x80) {	/* ASCII */
+		c = src;
+
+	} else {
+		if (dir) {		/* OEMCP to Unicode */
+			c = (src >= 0x100) ? 0 : Tbl[src - 0x80];
+
+		} else {		/* Unicode to OEMCP */
+			for (c = 0; c < 0x80; c++) {
+				if (src == Tbl[c]) break;
+			}
+			c = (c + 0x80) & 0xFF;
+		}
+	}
+
+	return c;
+}
+
+#else
+#error This file is not needed in current configuration
+
+#endif
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/option/syncobj.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/option/syncobj.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/option/syncobj.c	(revision 453)
@@ -0,0 +1,124 @@
+/*------------------------------------------------------------------------*/
+/* Sample code of OS dependent synchronization object controls            */
+/* for FatFs R0.07a  (C)ChaN, 2009                                        */
+/*------------------------------------------------------------------------*/
+
+//#include <windows.h>	// Win32
+#include <kernel.h>
+#include "kernel_cfg.h"
+//#include <ucos_ii.h>	// uC/OS-II
+
+#include "../ff.h"
+
+#if _FS_REENTRANT
+
+static const ID VolumeSemId[4] = {
+	SEMID_FATFS1,
+	SEMID_FATFS2,
+	SEMID_FATFS3,
+	SEMID_FATFS4
+};
+
+/*------------------------------------------------------------------------*/
+/* Create a Synchronization Object for a Volume                           */
+/*------------------------------------------------------------------------*/
+/* This function is called in f_mount function to create a new
+/  synchronization object, such as semaphore and mutex. When a FALSE is
+/  returned, the f_mount function fails with FR_INT_ERR.
+*/
+
+BOOL ff_cre_syncobj (	/* TRUE:Function succeeded, FALSE:Could not create due to any error */
+	BYTE vol,			/* Corresponding logical drive being processed */
+	_SYNC_t *sobj		/* Pointer to return the created sync object */
+)
+{
+	BOOL ret;
+
+//	*sobj = CreateMutex(NULL, FALSE, NULL);					// Win32
+//	ret = (*sobj != INVALID_HANDLE_VALUE) ? TRUE : FALSE;	//
+
+	*sobj = VolumeSemId[vol];	// uITRON (give a static created sync object)
+	ret = TRUE;					// The initial value of the semaphore must be 1.
+
+//	*sobj = OSMutexCreate(0, &err);				// uC/OS-II
+//	ret = (err == OS_NO_ERR) ? TRUE : FALSE;	//
+
+	return ret;
+}
+
+
+
+/*------------------------------------------------------------------------*/
+/* Delete a Synchronization Object                                        */
+/*------------------------------------------------------------------------*/
+/* This function is called in f_mount function to delete a synchronization
+/  object that created with ff_cre_syncobj function. When a FALSE is
+/  returned, the f_mount function fails with FR_INT_ERR.
+*/
+
+BOOL ff_del_syncobj (	/* TRUE:Function succeeded, FALSE:Could not delete due to any error */
+	_SYNC_t sobj		/* Sync object tied to the logical drive to be deleted */
+)
+{
+	BOOL ret;
+
+//	ret = CloseHandle(sobj);	// Win32
+
+	ret = TRUE;					// uITRON (nothing to do)
+
+//	OSMutexDel(sobj, OS_DEL_ALWAYS, &err);		// uC/OS-II
+//	ret = (err == OS_NO_ERR) ? TRUE : FALSE;	//
+
+	return ret;
+}
+
+
+
+/*------------------------------------------------------------------------*/
+/* Request Grant to Access the Volume                                     */
+/*------------------------------------------------------------------------*/
+/* This function is called on entering file functions to lock the volume.
+/  When a FALSE is returned, the file function fails with FR_TIMEOUT.
+*/
+
+BOOL ff_req_grant (	/* TRUE:Got a grant to access the volume, FALSE:Could not get a grant */
+	_SYNC_t sobj	/* Sync object to wait */
+)
+{
+	BOOL ret;
+
+//	ret = (WaitForSingleObject(sobj, _TIMEOUT) == WAIT_OBJECT_0) ? TRUE : FALSE;	// Win32
+
+	ret = (wai_sem(sobj) == E_OK) ? TRUE : FALSE;	// uITRON
+
+//	OSMutexPend(sobj, _TIMEOUT, &err));				// uC/OS-II
+//	ret = (err == OS_NO_ERR) ? TRUE : FALSE;		//
+
+	return ret;
+}
+
+
+
+/*------------------------------------------------------------------------*/
+/* Release Grant to Access the Volume                                     */
+/*------------------------------------------------------------------------*/
+/* This function is called on leaving file functions to unlock the volume.
+*/
+
+void ff_rel_grant (
+	_SYNC_t sobj	/* Sync object to be signaled */
+)
+{
+//	ReleaseMutex(sobj);	// Win32
+
+	sig_sem(sobj);		// uITRON
+
+//	OSMutexPost(sobj);	// uC/OS-II
+}
+
+
+#else
+
+#error This file is not needed in this configuration.
+
+#endif
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/sddiskio.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/sddiskio.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/sddiskio.c	(revision 453)
@@ -0,0 +1,336 @@
+/*
+ *  TOPPERS/JSP/ASP/FMP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Just Standard Profile Kernel
+ * 
+ *  Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2018 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+ *  によって公表されている GNU General Public License の Version 2 に記
+ *  述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+ *  を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+ *  含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+ *  接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ * このプログラムはITRON専用のFFドライバ・ソフトウェアである。
+ * ＳＤカード専用ストレージ関数をサポートする
+ * 擬似的なストレージ関数郡であり、標準ライブラリィと分けての使用が望ましい。
+ * 1. sd_init                  この関数郡の初期化関数(bssがゼロ設定の場合この関数は不要)
+ * 2. sdcard_sense             SD-CARDのセンスを行う
+ * 3. sdcard_diskstatus        SD-CARDのステータス取得:なし
+ * 4. sdcard_diskread          SD-CARDの読み込み:なし
+ * 5. sdcard_diskwrite         SD-CARDの書き込み:なし
+ * 6. sdcard_iocil             SD-CARDのIO制御:なし
+ *
+ */
+
+#include "kernel_impl.h"
+#include <stdlib.h>
+#include <string.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include "fcntl.h"
+#include "device.h"
+#include "mcicmd.h"
+#include "storagedevice.h"
+#include "ff.h"
+#include "diskio.h"
+#include "sddiskio.h"
+
+static int sdcard_sense(void *psdev, BOOL on);
+static int sdcard_diskstatus(void *psdev);
+static int sdcard_diskread(void *pif, BYTE *Buffer, DWORD SectorNumber, BYTE SectorCount);
+static int sdcard_diskwrite(void *pif, const BYTE *Buffer, DWORD SectorNumber, BYTE SectorCount);
+static int sdcard_diskioctl(void *pif, BYTE Func, void* Buffer);
+
+static const StorageDeviceFunc_t fatfsSDeviceFunc = {
+	sdcard_sense,
+	sdcard_diskstatus,
+	sdcard_diskstatus,
+	(int (*)())sdcard_diskread,
+	(int (*)())sdcard_diskwrite,
+	(int (*)())sdcard_diskioctl
+};
+
+static MCIINFO SDCardInfo;
+static FATFS ActiveFatFsObj __attribute__ ((aligned (32)));
+
+#ifdef DMA_ALINE
+static unsigned int abuff[512/sizeof(unsigned int)];
+
+static void mem_cpy(unsigned char *d, unsigned char *s, int len)
+{
+	while(len > 0){
+		*d++ = *s++;
+		len--;
+	}
+}
+#endif
+
+/*
+ *  FatFs用SDカードファイルドライバの初期化
+ */
+void sd_init(intptr_t exinf)
+{
+	StorageDevice_t *psdev;
+
+	SDMSetupDevice(SDCARD_DEVNO, &psdev);
+	psdev->pdevf            = (StorageDeviceFunc_t *)&fatfsSDeviceFunc;
+	psdev->pdevff           = (StorageDeviceFileFunc_t *)&fatfsSDeviceFileFunc;
+	psdev->_sdev_secsize    = 512;
+	psdev->_sdev_port       = SDCRAD_PORTID;
+#ifdef SDEV_INSWAIT_TIME
+	psdev->_sdev_inswait    = SDEV_INSWAIT_TIME;
+#else
+	psdev->_sdev_inswait    = 0;
+#endif
+	psdev->_sdev_attribute |= SDEV_INSERTCHK|SDEV_CHKREMOVE;
+	psdev->_sdev_local[0]   = &ActiveFatFsObj;
+}
+
+/*
+ *  SDCARDセンス関数
+ */
+static int sdcard_sense(void *pif, BOOL on)
+{
+	StorageDevice_t *psdev = pif;
+	bool_t   exist = mci_ses_por(((StorageDevice_t *)psdev)->_sdev_port);
+	MCIPCB   *pmci;
+	int      result = FR_DISK_ERR;
+
+	pmci = psdev->_sdev_local[1];
+	if(on && !exist){
+		f_mount(psdev->_sdev_devno, 0);
+		psdev->_sdev_attribute &= ~SDEV_DEVERROR;
+		mci_cls_por(pmci);
+		return TRUE;
+	}
+	else if(!on && exist){
+		psdev->_sdev_instimer += SENSE_TIME;
+		if((psdev->_sdev_attribute & SDEV_ONEEXIT) != 0 && psdev->_sdev_instimer < psdev->_sdev_inswait)
+			return FALSE;
+		pmci = mci_opn_por(((StorageDevice_t *)psdev)->_sdev_port);
+		if(pmci == NULL)
+			return FALSE;
+		psdev->_sdev_local[1] = pmci;
+		if(MciCheckCID(pmci) != E_OK){
+			psdev->_sdev_attribute |= SDEV_DEVERROR;
+			return TRUE;
+		}
+		if(MciSetAddress(pmci) != E_OK){
+			psdev->_sdev_attribute |= SDEV_DEVERROR;
+			return TRUE;
+		}
+		if(MciSendCID(pmci) != E_OK){
+			psdev->_sdev_attribute |= SDEV_DEVERROR;
+			return TRUE;
+		}
+		if(MciGetCardInfo(pmci, &SDCardInfo) != E_OK)
+			psdev->_sdev_attribute |= SDEV_DEVERROR;
+		else{
+			psdev->_sdev_maxsec = SDCardInfo.maxsector;
+			if(MciSelectCard(pmci, (((uint32_t)SDCardInfo.RCA) << 16)) != E_OK)
+				psdev->_sdev_attribute |= SDEV_DEVERROR;
+		}
+		if(MciConfiguration(pmci) != E_OK)
+			psdev->_sdev_attribute |= SDEV_DEVERROR;
+		if(MciSetWideBus(pmci) != E_OK)
+			psdev->_sdev_attribute |= SDEV_DEVERROR;
+		if((psdev->_sdev_attribute & SDEV_DEVERROR) == 0)
+			result = f_mount(psdev->_sdev_devno, &ActiveFatFsObj);
+		if(result != FR_OK)
+			psdev->_sdev_attribute |= SDEV_DEVERROR;
+		else
+			psdev->_sdev_local[0]   = &ActiveFatFsObj;
+#if 1
+		syslog_3(LOG_NOTICE, "## attr[%04x] max(%d) result(%d) ##", psdev->_sdev_attribute, psdev->_sdev_maxsec, result);
+#endif
+		return TRUE;
+	}
+	else
+		return FALSE;
+}
+
+/*
+ *  FatFs用SDCARDステータス関数
+ */
+static int sdcard_diskstatus(void *pif)
+{
+	StorageDevice_t *psdev = pif;
+	MCIPCB          *pmci;
+
+	if(psdev == NULL)
+		return STA_NODISK;
+	pmci = psdev->_sdev_local[1];
+	if((psdev->_sdev_attribute & (SDEV_EMPLOY|SDEV_NOTUSE)) != SDEV_EMPLOY || pmci == NULL)
+		return STA_NOINIT;
+	else if((pmci->status & SDMODE_PROTECT) != 0)
+		return STA_PROTECT;
+	else
+		return 0;
+}
+
+/*
+ *  FatFs用SDCARD読み込み関数
+ */
+static int sdcard_diskread(void *pif, BYTE *Buffer, DWORD SectorNumber, BYTE SectorCount)
+{
+ 	StorageDevice_t *psdev = pif;
+	MCIPCB          *pmci;
+	ER              ercd = E_OK;
+	int             retry = 0;
+#ifdef DMA_ALINE
+	unsigned int    align = ((unsigned int)Buffer) & 3;
+	int             i;
+#endif
+
+	pmci = psdev->_sdev_local[1];
+	if((psdev->_sdev_attribute & (SDEV_EMPLOY|SDEV_NOTUSE)) != SDEV_EMPLOY || pmci == NULL)
+		return RES_ERROR;
+#ifndef DMA_ALINE
+	do{
+		ercd = mci_red_blk(pmci, Buffer, SectorNumber * psdev->_sdev_secsize, psdev->_sdev_secsize, SectorCount);
+		if(ercd == E_OK)
+			ercd = mci_wai_trn(pmci, 30*1000);
+		retry++;
+	}while(ercd != E_OK && retry < RETRY_COUNT);
+#else
+	if(align == 0){
+		do{
+			ercd = mci_red_blk(pmci, Buffer, SectorNumber * psdev->_sdev_secsize, psdev->_sdev_secsize, SectorCount);
+			if(ercd == E_OK)
+				ercd = mci_wai_trn(pmci, 30*1000);
+			retry++;
+		}while(ercd != E_OK && retry < RETRY_COUNT);
+	}
+	else{
+		for(i = 0 ; i < SectorCount ; i++, SectorNumber++, Buffer += psdev->_sdev_secsize){
+			do{
+				ercd = mci_red_blk(pmci, abuff, SectorNumber * psdev->_sdev_secsize, psdev->_sdev_secsize, 1);
+				if(ercd == E_OK)
+					ercd = mci_wai_trn(pmci, 30*1000);
+				retry++;
+			}while(ercd != E_OK && retry < RETRY_COUNT);
+			mem_cpy(Buffer, abuff, psdev->_sdev_secsize);
+		}
+	}
+#endif
+	if(ercd == E_OK)
+		return RES_OK;
+	else
+		return RES_ERROR;
+}
+
+/*
+ *  FatFs用SDCARD書き込み関数
+ */
+static int sdcard_diskwrite(void *pif, const BYTE *Buffer, DWORD SectorNumber, BYTE SectorCount)
+{
+	StorageDevice_t *psdev = pif;
+	MCIPCB          *pmci;
+	ER              ercd = E_OK;
+	int             retry = 0;
+#ifdef DMA_ALINE
+	unsigned int    align = ((unsigned int)Buffer) & 3;
+	int             i;
+#endif
+
+	pmci = psdev->_sdev_local[1];
+	if((psdev->_sdev_attribute & (SDEV_EMPLOY|SDEV_NOTUSE)) != SDEV_EMPLOY || pmci == NULL)
+		return RES_ERROR;
+#ifndef DMA_ALINE
+	do{
+		ercd = mci_wri_blk(pmci, (void *)Buffer, SectorNumber * psdev->_sdev_secsize, psdev->_sdev_secsize, SectorCount);
+		if(ercd == E_OK)
+			ercd = mci_wai_trn(pmci, 30*1000);
+		retry++;
+	}while(ercd != E_OK && retry < RETRY_COUNT);
+#else
+	if(align == 0){
+		do{
+			ercd = mci_wri_blk(pmci, (void *)Buffer, SectorNumber * psdev->_sdev_secsize, psdev->_sdev_secsize, SectorCount);
+			if(ercd == E_OK)
+				ercd = mci_wai_trn(pmci, 30*1000);
+			retry++;
+		}while(ercd != E_OK && retry < RETRY_COUNT);
+	}
+	else{
+		for(i = 0 ; i < SectorCount ; i++, SectorNumber++, Buffer += psdev->_sdev_secsize){
+			mem_cpy(abuff, Buffer, psdev->_sdev_secsize);
+			do{
+				ercd = mci_wri_blk(pmci, (void *)abuff, SectorNumber * psdev->_sdev_secsize, psdev->_sdev_secsize, 1);
+				if(ercd == E_OK)
+					ercd = mci_wai_trn(pmci, 30*1000);
+				retry++;
+			}while(ercd != E_OK && retry < RETRY_COUNT);
+		}
+	}
+#endif
+	if(ercd == E_OK)
+		return RES_OK;
+	else
+		return RES_ERROR;
+}
+
+
+/*
+ *  FatFs用SDCARDIO制御関数
+ */
+static int sdcard_diskioctl(void *pif, BYTE Func, void* Buffer)
+{
+	StorageDevice_t *psdev = (StorageDevice_t *)pif;
+	DRESULT         result;
+
+	if(psdev == NULL)
+		return RES_ERROR;
+	if((psdev->_sdev_attribute & (SDEV_EMPLOY|SDEV_NOTUSE)) != SDEV_EMPLOY)
+		return RES_ERROR;
+	switch(Func){
+	case CTRL_SYNC:
+		result = RES_OK;			/* no action */
+		break;
+	case GET_SECTOR_COUNT:
+		*((DWORD *)Buffer) = psdev->_sdev_maxsec;
+		syslog_2(LOG_NOTICE, "ioctl notuse (%d)(%d) ", (int)Func, psdev->_sdev_maxsec);
+		result = RES_OK;
+		break;
+	case GET_BLOCK_SIZE:
+		*((DWORD *)Buffer) = 135;	/* ERASE_BLK */
+		syslog_1(LOG_NOTICE, "call disk_ioctl(GET_BLOCK_SIZE, %08x)", (int)(*((DWORD *)Buffer)));
+		result = RES_OK;
+		break;
+	default:
+		syslog_2(LOG_NOTICE, "call disk_ioctl(%d, %08x)", (int)psdev->_sdev_devno, (int)Buffer);
+		slp_tsk();
+		result = RES_PARERR;
+		break;
+	}
+	return result;
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/sddiskio.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/sddiskio.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/files/ff/sddiskio.h	(revision 453)
@@ -0,0 +1,56 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2012 by GT Development Center RICOH COMPANY,LTD. JAPAN
+ *  Copyright (C) 2015-2016 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+ *  によって公表されている GNU General Public License の Version 2 に記
+ *  述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+ *  を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+ *  含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+ *  接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+#ifndef _SDDISKIO_H_
+#define _SDDISKIO_H_
+
+#include "storagedevice.h"
+
+#define RETRY_COUNT    8
+
+#define SDCARD_DEVNO   0
+#define SDCRAD_PORTID  0
+
+extern StorageDeviceFileFunc_t fatfsSDeviceFileFunc;
+
+extern void sd_init(intptr_t exinf);
+extern void _sd_setfcntldev(int no);
+
+
+#endif
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/files/stdfile.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/files/stdfile.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/files/stdfile.c	(revision 453)
@@ -0,0 +1,487 @@
+/*
+ *  TOPPERS/ASP/FMP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile/Flexible MultiProcessor Kernel
+ * 
+ *  Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2020 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+ *  によって公表されている GNU General Public License の Version 2 に記
+ *  述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+ *  を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+ *  含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+ *  接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ * TOPPERS/ASP/FMP+FATFS対応のPOSIXファイル関数
+ */
+#include <kernel.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include "storagedevice.h"
+#include "kernel_cfg.h"
+
+#ifndef NUM_FIL
+#define NUM_FIL 16
+#endif
+
+/* sys/dirent.h */
+struct dirent {
+  unsigned long  d_fileno;		/* file number of entry */
+  unsigned short d_reclen;		/* length of this record */
+  unsigned char  d_type; 		/* file type, see below */
+  unsigned char  d_namlen;		/* length of string in d_name */
+#define	MAXNAMLEN	255
+  char	d_name[MAXNAMLEN + 1];	/* name must be no longer than this */
+};
+
+/* File types */
+#define DT_UNKMOWN  0
+#define DT_FIFO     1
+#define DT_CHAR     2
+#define DT_DIR      4
+#define DT_BLK      6
+#define DT_REG      8
+#define DT_LNK      10
+#define DT_SOCK     12
+#define DT_WHT      14
+
+
+static FILE iod[NUM_FIL];
+static StorageDevice_t *pdirpsdev = 0;
+
+extern int _setup_file(FILE *st, StorageDevice_t *pd, int lid);
+
+/*
+ *  allocate file structure
+ */
+static FILE *alloc_file(void)
+{
+  FILE *fp;
+  int i;
+
+  loc_cpu();
+  for(fp = iod, i = 0 ; i < NUM_FIL ; fp++, i++){
+    if(fp->_flags == 0){
+      fp->_flags = __SRW;
+      unl_cpu();
+      return fp;
+    }
+  }
+  unl_cpu();
+  return 0;
+}
+
+/*
+ *  free file structure
+ */
+static void free_file(FILE * fp)
+{
+  if(fp != NULL)
+    fp->_flags = 0;
+}
+
+/*
+ *  fopen - open a file
+ *  notice - not support text mode.
+ *           not support append mode.
+ */
+FILE *__wrap_fopen(const char *name, const char *type)
+{
+  StorageDevice_t         *psdev;
+  StorageDeviceFileFunc_t *pff;
+  FILE                    *fp;
+  int                     devno, i, id;
+  unsigned int            mode = 0;
+  unsigned int            stat = 0;
+
+  if((devno = SDMGetDeviceNo(&name)) < 0)
+    return NULL;
+  if((psdev = SDMGetStorageDevice(devno)) == 0)
+    return NULL;
+  pff = psdev->pdevff;
+  if(pff != 0 && pff->_sdevff_open == 0)
+    return NULL;
+
+  if((fp = alloc_file()) != 0){
+    for(i = 0 ; i < 8 && type[i] >= ' ' ; i++){
+      switch(type[i]){
+      case 'r':
+        stat |= O_RDONLY;
+        fp->_flags |= __SRD;
+        break;
+      case 'w':
+        stat |= O_WRONLY | O_CREAT;
+        fp->_flags |= __SWR;
+        break;
+      case 'a':
+        stat |= O_RDWR | O_CREAT;
+        fp->_flags |= __SRD | __SWR;
+        break;
+      case 'b':
+        break;
+      case '+':
+        break;
+      }
+    }
+    if((stat & O_ACCMODE) == (O_WRONLY | O_RDWR))
+      mode = (stat & ~O_ACCMODE) | O_RDWR;
+    else
+      mode = stat;
+    wai_sem(SEM_STDFILE);
+    id = pff->_sdevff_open(devno, name, mode);
+    sig_sem(SEM_STDFILE);
+    if(id < 0){
+      free_file(fp);
+      return NULL;
+    }
+    _setup_file(fp, psdev, id);
+    return fp;
+  }
+  else
+    return NULL;
+}
+
+/*
+ *  fclose - close a file
+ */
+int __wrap_fclose(FILE *fp)
+{
+  StorageDevice_t  *psdev;
+  int              result;
+
+  if(fp == NULL)
+    return -1;
+  psdev = fp->_dev;
+  wai_sem(SEM_STDFILE);
+  if(psdev->pdevff != 0 && psdev->pdevff->_sdevff_close != 0)
+    result = psdev->pdevff->_sdevff_close(fp->_file);
+  else
+    result = -1;
+  sig_sem(SEM_STDFILE);
+  free_file(fp);
+  return result;
+}
+
+/*
+ *  fseek - seek a file
+ */
+int __wrap_fseek(FILE *fp, long offset, int whence)
+{
+  StorageDevice_t  *psdev;
+  int result, res = 0;
+
+  if(fp == NULL)
+    return -1;
+  psdev = fp->_dev;
+  if(psdev->pdevff != 0 && psdev->pdevff->_sdevff_lseek != 0){
+    result = psdev->pdevff->_sdevff_lseek(fp->_file, offset, whence, &res);
+    if(res < 0)
+        fp->_flags |= __SERR;
+    return result;
+  }
+  else
+    return -1;
+}
+
+/*
+ *  ftell - get position file indicator
+ */
+long ftell(FILE *fp)
+{
+  StorageDevice_t  *psdev;
+  long result;
+  int  res = 0;
+
+  if(fp == NULL)
+    return -1;
+  psdev = fp->_dev;
+  if(psdev->pdevff != 0 && psdev->pdevff->_sdevff_lseek != 0){
+    result = psdev->pdevff->_sdevff_lseek(fp->_file, 0, SEEK_CUR, &res);
+    if(res < 0)
+        fp->_flags |= __SERR;
+    return result;
+  }
+  else
+    return -1;
+}
+
+/*
+ *  stat - get file status
+ *       - set st_mode, st_atime, st_atimensec, st_mtime, st_mtimensec
+ *             st_ctime, st_ctimensec, st_blksize, st_blocks, st_size
+ */
+int _stat(const char *name, struct stat *buf)
+{
+  StorageDevice_t *psdev;
+  int             devno;
+  const char      *sname = name;
+
+  devno = SDMGetDeviceNo((const char **)&name);
+  psdev = SDMGetStorageDevice(devno);
+  if(psdev == NULL)
+    return -1;
+  if(psdev->pdevff == 0 || psdev->pdevff->_sdevff_stat == 0)
+    return -1;
+  if(psdev->pdevff->_sdevff_stat(sname, buf) >= 0)
+    return 0;
+  else
+    return -1;
+}
+
+/*
+ *  lstat from fsiunixlike.c, fslpux.c
+ */
+int lstat(const char *path, struct stat *buf)
+{
+  return _stat(path, buf);
+}
+
+/*
+ *  access from fsiunixlike.c(2)
+ *  mode=0-file exist, mode=2-writeable OK-0 Err--1
+ */
+int access(const char *path, int mode)
+{
+  struct stat     buf;
+  int             res = -1;
+
+  if(_stat(path, &buf) >= 0){
+    res = 0;
+    if((mode & 0x02) != 0 && (buf.st_flags & 0x0001) != 0)	/* read only(no debug) */
+      res = -1;
+  }
+  return res;
+}
+
+/*
+ *  mkdir - make directory
+ *        - not support mode
+ */
+int mkdir(const char *path, mode_t mode)
+{
+  StorageDevice_t *psdev;
+  int             devno;
+
+  devno = SDMGetDeviceNo((const char **)&path);
+  psdev = SDMGetStorageDevice(devno);
+  if(psdev == NULL)
+    return -1;
+  if(psdev->pdevff == 0 || psdev->pdevff->_sdevff_mkdir == 0)
+    return -1;
+  if(psdev->pdevff->_sdevff_mkdir(path) >= 0)
+    return 0;
+  else
+    return -1;
+}
+
+/*
+ *  rmdir from fsiunixlike.c(3), fslpux.c, device.c
+ */
+int rmdir(const char *path)
+{
+  StorageDevice_t *psdev;
+  int             devno;
+
+  devno = SDMGetDeviceNo((const char **)&path);
+  psdev = SDMGetStorageDevice(devno);
+  if(psdev == NULL)
+    return -1;
+  if(psdev->pdevff == 0 || psdev->pdevff->_sdevff_rmdir == 0)
+    return -1;
+  if(psdev->pdevff->_sdevff_rmdir(path) >= 0)
+    return 0;
+  else
+    return -1;
+}
+
+/*
+ *  chmod from fsiunixlike.c(2)
+ */
+int chmod(const char *path, mode_t mode)
+{
+  StorageDevice_t *psdev;
+  int             devno;
+
+  devno = SDMGetDeviceNo((const char **)&path);
+  psdev = SDMGetStorageDevice(devno);
+  if(psdev == NULL)
+    return -1;
+  if(psdev->pdevff == 0 || psdev->pdevff->_sdevff_chmod == 0)
+    return -1;
+  if(psdev->pdevff->_sdevff_chmod(path, mode) >= 0)
+    return 0;
+  else
+    return -1;
+}
+
+/*
+ *  remove - remove a file
+ */
+int remove(const char *name)
+{
+  StorageDevice_t *psdev;
+  int             devno;
+
+  devno = SDMGetDeviceNo((const char **)&name);
+  psdev = SDMGetStorageDevice(devno);
+  if(psdev == NULL)
+    return -1;
+  if(psdev->pdevff == 0 || psdev->pdevff->_sdevff_unlink == 0)
+    return -1;
+  if(psdev->pdevff->_sdevff_unlink(name) >= 0)
+    return 0;
+  else
+    return -1;
+}
+
+/*
+ *  unlink - remove file
+ */
+bool_t unlink(const char *path)
+{
+  StorageDevice_t *psdev;
+  int             devno;
+
+  devno = SDMGetDeviceNo((const char **)&path);
+  psdev = SDMGetStorageDevice(devno);
+  if(psdev == NULL)
+    return -1;
+  if(psdev->pdevff == 0 || psdev->pdevff->_sdevff_unlink == 0)
+    return -1;
+  if(psdev->pdevff->_sdevff_unlink(path) >= 0)
+    return 0;
+  else
+    return -1;
+}
+
+/*
+ *  rename - change file name
+ */
+int rename(const char *oldpath, const char *newpath)
+{
+  StorageDevice_t *psdev;
+  int             devno;
+
+  devno = SDMGetDeviceNo((const char **)&oldpath);
+  psdev = SDMGetStorageDevice(devno);
+  if(psdev == NULL)
+    return -1;
+  if(psdev->pdevff == 0 || psdev->pdevff->_sdevff_rename == 0)
+    return -1;
+  if(psdev->pdevff->_sdevff_rename(oldpath, newpath) >= 0)
+    return 0;
+  else
+    return -1;
+}
+
+/*
+ *  mkstemp from fsiunixlike.c, device.c
+ */
+int mkstemp(char *path)
+{
+	printf("### mkstemp() !! ##\n");
+	slp_tsk();
+	return 0;
+}
+
+/*
+ *  opendir from fsiunixlike.c, fslpux.c(2), device.c
+ */
+void *opendir(const char *path)
+{
+  int             devno;
+
+  devno = SDMGetDeviceNo((const char **)&path);
+  pdirpsdev = SDMGetStorageDevice(devno);
+  if(pdirpsdev == NULL)
+    return NULL;
+  if(pdirpsdev->pdevff == 0 || pdirpsdev->pdevff->_sdevff_opendir == 0)
+    return NULL;
+  return pdirpsdev->pdevff->_sdevff_opendir(path);
+}
+
+/*
+ *  closedir from fsiunixlike.c(2), fslpux.c(4)
+ */
+int closedir(void *dir)
+{
+  if(pdirpsdev == NULL)
+    return 0;
+  if(pdirpsdev->pdevff == 0 || pdirpsdev->pdevff->_sdevff_closedir == 0)
+    return 0;
+  return pdirpsdev->pdevff->_sdevff_closedir(dir);
+}
+
+/*
+ *  readdir from fsiunixlike.c, fslpux.c(2), device.c
+ */
+struct dirent *readdir(void *dir)
+{
+  static struct dirent  Dirent;
+  static struct dirent2 finfo;
+  struct dirent *pdirent;
+  int    i;
+
+  if(pdirpsdev == 0)
+    return NULL;
+  if(pdirpsdev->pdevff == 0 || pdirpsdev->pdevff->_sdevff_readdir == 0)
+    return NULL;
+  if(pdirpsdev->pdevff->_sdevff_readdir(dir, &finfo) == 0)
+    return NULL;
+  pdirent = &Dirent;
+  memset(pdirent, 0, sizeof(struct dirent));
+  for(i = 0 ; i < MAXNAMLEN && finfo.d_name[i] != 0 ; i++)
+    pdirent->d_name[i] = finfo.d_name[i];
+  pdirent->d_namlen = i;
+  pdirent->d_reclen = i;
+  if(finfo.d_type & AM_DIR)
+    Dirent.d_type = DT_DIR;
+  else
+    Dirent.d_type = DT_BLK;
+  return pdirent;
+}
+
+/*
+ *  statfs from fslpux.c
+ */
+int statfs(const char *path, struct statfs2 *status)
+{
+  StorageDevice_t *psdev;
+  int             devno;
+  const char      *name = path;
+
+  devno = SDMGetDeviceNo((const char **)&path);
+  psdev = SDMGetStorageDevice(devno);
+  if(psdev == NULL)
+    return -1;
+  if(psdev->pdevff == 0 || psdev->pdevff->_sdevff_statfs == 0)
+    return -1;
+  return psdev->pdevff->_sdevff_statfs(name, (void *)status);
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/files/stdio.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/files/stdio.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/files/stdio.c	(revision 453)
@@ -0,0 +1,399 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2016 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+ *  によって公表されている GNU General Public License の Version 2 に記
+ *  述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+ *  を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+ *  含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+ *  接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ * このプログラムはITRON専用のTYPE3ソフトウェアである。
+ * POSIXのファイル関数を供給する。
+ * 擬似的なストレージ関数郡であり、標準ライブラリィと分けての使用が望ましい。
+ * 1. _stdfile_init            ファイルインデックスの初期化を行う
+ * 2. open                     ファイルのオープン(特別な専用FDを発行する)
+ * 3. close                    ファイルのクローズ
+ * 4. fstat                    ファイルのステートの取り出し
+ * 5. fseek                    ファイルのシーク
+ * 6. read                     ファイルからのデータ読み出し
+ * 7. write                    ファイルからのデータ書き込み
+ * 8. mmap                     ファイルデータのマップ化
+ * 9. munmap                   ファイルデータのアンマップ化
+ */
+
+#include <kernel.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "kernel_cfg.h"
+#include "fcntl.h"
+#include "storagedevice.h"
+
+#ifndef NUM_FILEIDX
+#define NUM_FILEIDX	128
+#endif
+
+
+static struct StdFileIndex stdfile[NUM_FILEIDX];
+
+
+void stdfile_init(intptr_t exinf)
+{
+	unsigned int idx;
+
+	for(idx = 0 ; idx < NUM_FILEIDX ; idx++){
+		stdfile[idx].sdmdev = 0;
+		stdfile[idx].sdmfd = -1;
+	}
+}
+
+/*
+ *  FDチェック関数
+ */
+static struct StdFileIndex *fdcheck(int fd)
+{
+	struct StdFileIndex *pf;
+
+	if(fd <= 0 || fd > NUM_FILEIDX)
+		return 0;
+	pf = &stdfile[fd-1];
+	if(pf->sdmfd == -1)
+		return 0;
+	else
+		return pf;
+}
+
+/*
+ *  標準ファイルインターフェイス関数(open)
+ */
+int _open(const char *pathname, int flags)
+{
+	StorageDevice_t         *psdev;
+	StorageDeviceFileFunc_t *pff;
+	int             devno, id, no;
+
+	if((devno = SDMGetDeviceNo(&pathname)) < 0)
+		return -1;
+	if((psdev = SDMGetStorageDevice(devno)) == 0)
+		return -1;
+	pff = psdev->pdevff;
+	if(pff != 0 && pff->_sdevff_open == 0)
+		return -1;
+
+	wai_sem(SEM_STDFILE);
+	for(no = 0 ; no < NUM_FILEIDX ; no++){
+		if(stdfile[no].sdmfd == -1)
+			break;
+	}
+	if(no >= NUM_FILEIDX){
+		sig_sem(SEM_STDFILE);
+		return -1;
+	}
+
+	id = pff->_sdevff_open(devno, pathname, flags);
+	if(id < 0){
+		sig_sem(SEM_STDFILE);
+		return id;
+	}
+	stdfile[no].sdmfd  = id;
+	stdfile[no].sdmdev = psdev;
+	sig_sem(SEM_STDFILE);
+	return no+1;
+}
+
+/*
+ *  標準ファイルインターフェイス関数(close)
+ */
+int _close(int fd)
+{
+	struct StdFileIndex *ps;
+	StorageDevice_t     *psdev;
+	int             result;
+
+	if((ps = fdcheck(fd)) == 0)
+		return -1;
+	wai_sem(SEM_STDFILE);
+	psdev = ps->sdmdev;
+	if(psdev->pdevff != 0 && psdev->pdevff->_sdevff_close != 0)
+		result = psdev->pdevff->_sdevff_close(ps->sdmfd);
+	else
+		result = -1;
+	ps->sdmfd = -1;
+	sig_sem(SEM_STDFILE);
+	return result;
+}
+
+/*
+ *  標準ファイルインターフェイス関数(fstat)
+ */
+int _fstat(int fd, struct stat *buf)
+{
+	struct StdFileIndex *ps;
+	StorageDevice_t     *psdev;
+
+	if((ps = fdcheck(fd)) == 0)
+		return -1;
+	psdev = ps->sdmdev;
+	if(psdev->pdevff != 0 && psdev->pdevff->_sdevff_fstat != 0)
+		return psdev->pdevff->_sdevff_fstat(ps->sdmfd, buf);
+	else
+		return -1;
+}
+
+/*
+ *  標準ファイルインターフェイス関数(lseek)
+ */
+off_t _lseek(int fd, off_t offset, int whence)
+{
+	struct StdFileIndex *ps;
+	StorageDevice_t     *psdev;
+	int                 result;
+
+	if((ps = fdcheck(fd)) == 0)
+		return -1;
+	psdev = ps->sdmdev;
+	if(psdev->pdevff != 0 && psdev->pdevff->_sdevff_lseek != 0)
+		return psdev->pdevff->_sdevff_lseek(ps->sdmfd, offset, whence, &result);
+	else
+		return -1;
+}
+
+/*
+ *  標準ファイルインターフェイス関数(read)
+ */
+long _read(int fd, void *buf, long count)
+{
+	struct StdFileIndex *ps;
+	StorageDevice_t     *psdev;
+	int                 result;
+
+	if((ps = fdcheck(fd)) == 0)
+		return -1;
+	psdev = ps->sdmdev;
+	if(psdev->pdevff != 0 && psdev->pdevff->_sdevff_read != 0)
+		return psdev->pdevff->_sdevff_read(ps->sdmfd, buf, count, &result);
+	else
+		return 0;
+}
+
+/*
+ *  標準ファイルインターフェイス関数(write)
+ */
+long _write(int fd, const void *buf, long count)
+{
+	struct StdFileIndex *ps;
+	StorageDevice_t     *psdev;
+	int                 result;
+
+	if((ps = fdcheck(fd)) == 0)
+		return -1;
+	psdev = ps->sdmdev;
+	if(psdev->pdevff != 0 && psdev->pdevff->_sdevff_write != 0)
+		return psdev->pdevff->_sdevff_write(ps->sdmfd, buf, count, &result);
+	else
+		return 0;
+}
+
+int _isatty(int fd)
+{
+	return 1;
+}
+
+/*
+ *  ファイルマップ関数(mmap)
+ */
+void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
+{
+	struct StdFileIndex *ps;
+	StorageDevice_t     *psdev;
+
+	if((ps = fdcheck(fd)) == 0)
+		return (void*)-1;
+	psdev = ps->sdmdev;
+	if(psdev->pdevff != 0 && psdev->pdevff->_sdevff_mmap != 0)
+		return psdev->pdevff->_sdevff_mmap(start, length, prot, flags, ps->sdmfd, offset);
+	else
+		return (void*)-1;
+}
+
+/*
+ *  ファイルアンマップ関数(未処理)
+ */
+int munmap(void *start, size_t length)
+{
+	return 0;
+}
+
+/*
+ *  標入出力用１文字入力文
+ */
+static int local_getc(void *st)
+{
+	StorageDevice_t     *psdev;
+	int  result, res = 0;
+	char buf[2];
+
+	if(st == 0 && ((FILE *)st)->_file < 0)
+		return -1;
+	if((psdev = (StorageDevice_t *)((FILE*)st)->_dev) == 0)
+		return -1;
+	if(psdev->pdevff != 0 && psdev->pdevff->_sdevff_read != 0){
+		result = psdev->pdevff->_sdevff_read(((FILE *)st)->_file, buf, 1, &res);
+		if(res < 0)
+			((FILE *)st)->_flags |= __SERR;
+		if(result == 1)
+			return buf[0];
+		else
+			return -1;
+	}
+	else
+		return -1;
+}
+
+/*
+ *  標入出力用１文字入力文
+ */
+static int local_gets(void *st, unsigned int len, char *s)
+{
+	StorageDevice_t     *psdev;
+	int result, res = 0;
+
+	if(st == 0 && ((FILE *)st)->_file < 0)
+		return -1;
+	if((psdev = (StorageDevice_t *)((FILE*)st)->_dev) == 0)
+		return -1;
+	if(psdev->pdevff != 0 && psdev->pdevff->_sdevff_read != 0){
+		result = psdev->pdevff->_sdevff_read(((FILE *)st)->_file, s, len, &res);
+		if(res < 0)
+			((FILE *)st)->_flags |= __SERR;
+		return result;
+	}
+	else
+		return 0;
+}
+
+/*
+ *  標入出力用文字出力文
+ */
+static void local_putc(void *st, int c)
+{
+	StorageDevice_t     *psdev;
+	int  res = 0;
+	char buf[2];
+
+	if(st == 0 && ((FILE *)st)->_file < 0)
+		return;
+	if((psdev = (StorageDevice_t *)((FILE*)st)->_dev) == 0)
+		return;
+	buf[0] = c;
+	if(psdev->pdevff != 0 && psdev->pdevff->_sdevff_write != 0){
+		psdev->pdevff->_sdevff_write(((FILE *)st)->_file, buf, 1, &res);
+		if(res < 0)
+			((FILE *)st)->_flags |= __SERR;
+	}
+}
+
+/*
+ *  標入出力用文字列出力文
+ */
+static int local_puts(void *st, unsigned int len, char *s)
+{
+	StorageDevice_t     *psdev;
+	int result, res = 0;
+
+	if(st == 0 && ((FILE *)st)->_file < 0)
+		return -1;
+	if((psdev = (StorageDevice_t *)((FILE*)st)->_dev) == 0)
+		return -1;
+	if(psdev->pdevff != 0 && psdev->pdevff->_sdevff_write != 0){
+		result = psdev->pdevff->_sdevff_write(((FILE *)st)->_file, s, len, &res);
+		if(res < 0)
+			((FILE *)st)->_flags |= __SERR;
+		return result;
+	}
+	else
+		return 0;
+}
+
+/*
+ *  標入出力用データフラッシュ文
+ */
+static int local_flush(FILE *st)
+{
+	return 0;
+}
+
+/*
+ *  通常ファイルの設定
+ */
+int _setup_file(FILE *st, StorageDevice_t *pd, int lid)
+{
+	if(st == NULL)
+		return 0;
+	st->_file       = lid;
+	st->_func_in    = local_getc;
+	st->_func_ins   = local_gets;
+	st->_func_out   = local_putc;
+	st->_func_outs  = local_puts;
+	st->_func_flush = local_flush;
+	st->_dev        = pd;
+	return 1;
+}
+
+/*
+ *  標準入出力ファイルの設定
+ */
+int _setupstd_file(FILE *st, int fd)
+{
+	struct StdFileIndex *ps;
+
+	if(st == NULL)
+		return 0;
+
+	st->_func_in    = local_getc;
+	st->_func_ins   = local_gets;
+	st->_func_out   = local_putc;
+	st->_func_outs  = local_puts;
+	st->_func_flush = local_flush;
+
+	if((ps = fdcheck(fd)) == 0){
+		st->_file = -1;
+		st->_dev  = 0;
+		return 0;
+	}
+	else{
+		st->_file       = ps->sdmfd;
+		st->_dev        = ps->sdmdev;
+		return 1;
+	}
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/files/storagedevice.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/files/storagedevice.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/files/storagedevice.c	(revision 453)
@@ -0,0 +1,178 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2016 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+ *  によって公表されている GNU General Public License の Version 2 に記
+ *  述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+ *  を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+ *  含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+ *  接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "kernel_cfg.h"
+#include "storagedevice.h"
+
+#define SENSE_DEVICE    (SDEV_ACTIVE|SDEV_INSERTCHK)
+
+/*
+ *  Storage Device Mnanagerの全体定義
+ */
+StorageDeviceHead_t SDeviceHead;
+
+/*
+ *  デバイス単位の構造体領域定義
+ */
+static StorageDevice_t SDevice[NUM_STORAGEDEVICE];
+
+
+
+void sdev_init(intptr_t exinf)
+{
+	unsigned int no;
+
+	for(no = 0 ; no < NUM_STORAGEDEVICE ; no++){
+		memset(&SDevice[no], 0, sizeof(StorageDevice_t));
+	}
+	memset(&SDeviceHead, 0, sizeof(StorageDeviceHead_t));
+	SDeviceHead._psd            = &SDevice[0];
+	SDeviceHead._default_device = DEFAULT_DEVNO;
+    SDeviceHead._sdev_active    = true;
+}
+
+void sdev_terminate(void)
+{
+	SDeviceHead._sdev_active    = false;
+}
+
+ER SDMSetupDevice(int16_t devno, StorageDevice_t **ppsdev)
+{
+	StorageDevice_t *psdev;
+	unsigned int    no;
+
+	if(devno < MINIMUM_DEVNO || devno > MAXIMUM_DEVNO)
+		return E_ID;
+	if(SDeviceHead._num_activedev >= NUM_STORAGEDEVICE)
+		return E_OBJ;
+	for(no = 0, psdev = SDeviceHead._psd ; no < SDeviceHead._num_activedev ; no++, psdev++){
+		if(devno == psdev->_sdev_devno)
+			return E_ID;
+	}
+	psdev->_sdev_attribute = SDEV_ACTIVE;
+	psdev->_sdev_devno     = devno;
+	*ppsdev = psdev;
+	SDeviceHead._num_activedev++;
+	return E_OK;
+}
+
+ER_ID SDMGetDeviceNo(const char **ppathname)
+{
+	ER_ID devno = DEFAULT_DEVNO;
+	const char *p = *ppathname;
+
+	if(*p >= '0'&& *p <= '9'){
+		devno = *p++ - '0';
+		while(*p >= '0' && *p <= '9'){
+			devno *= 10;
+			devno  = *p++ - '0';
+		}
+		if(devno < MINIMUM_DEVNO || devno > MAXIMUM_DEVNO)
+			devno = E_ID;
+	}
+	if(*p == ':')
+		p++;
+	*ppathname = p;
+	return devno;
+}
+
+StorageDevice_t *SDMGetStorageDevice(int devno)
+{
+	StorageDevice_t *psdev = SDeviceHead._psd;
+	unsigned int no;
+
+    for(no = 0 ; no < SDeviceHead._num_activedev ; no++){
+		if((psdev->_sdev_attribute & SDEV_ACTIVE) != 0
+			 && psdev->_sdev_devno == devno)
+			return psdev;
+		psdev++;
+	}
+	return NULL;
+}
+
+ER SDMEmploy(StorageDevice_t *psdev, bool_t sw)
+{
+	if(psdev == 0)
+		return E_PAR;
+	if((psdev->_sdev_attribute & SDEV_ACTIVE) == 0)
+		return E_PAR;
+	if(sw)
+		psdev->_sdev_attribute |= SDEV_EMPLOY;
+	else
+		psdev->_sdev_attribute &= ~SDEV_EMPLOY;
+	return E_OK;
+}
+
+void SDMSence_task(intptr_t exinf)
+{
+	StorageDevice_t *psdev;
+	unsigned int dno;
+	bool_t       employ;
+
+	while(SDeviceHead._sdev_active == true){
+		psdev = SDeviceHead._psd;
+		for(dno = 0 ; dno < SDeviceHead._num_activedev ; dno++, psdev++){
+			if((psdev->_sdev_attribute & SENSE_DEVICE) == SENSE_DEVICE){
+				employ = (psdev->_sdev_attribute & SDEV_EMPLOY) != 0;
+				if(!employ && psdev->pdevf->_sdevf_sense(psdev, employ) != 0){
+					psdev->_sdev_attribute |= SDEV_EMPLOY;
+                    if(psdev->_sdev_notice)
+						psdev->_sdev_notice(psdev, true);
+				}
+				else if((psdev->_sdev_attribute & SDEV_CHKREMOVE) != 0 && employ){
+					if(psdev->pdevf->_sdevf_sense(psdev, employ) != 0){
+						psdev->_sdev_attribute &= ~SDEV_EMPLOY;
+						psdev->_sdev_attribute |= SDEV_ONEEXIT;
+						psdev->_sdev_instimer   = 0;
+	                    if(psdev->_sdev_notice)
+							psdev->_sdev_notice(psdev, false);
+					}
+				}
+			}
+		}
+		dly_tsk(SENSE_TIME);
+#ifdef SDEV_SENSE_ONETIME
+		break;
+#endif
+	}
+}
+
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/files/storagedevice.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/files/storagedevice.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/files/storagedevice.cfg	(revision 453)
@@ -0,0 +1,18 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *  STORAGE DEVICEのコンフィギュレーションファイル
+ */
+
+#include "storagedevice.h"
+ATT_INI({TA_NULL, 0, sdev_init});
+ATT_INI({TA_NULL, 0, stdfile_init});
+ATT_INI({TA_NULL, 0, volume_info_init});
+CRE_SEM(SEM_STDFILE,  { TA_TPRI, 1, 1 });
+
+#ifndef SDEV_SENSE_ONETIME
+CRE_TSK(SDM_TASK, { TA_ACT, 1, SDMSence_task, 15, 1024, NULL });
+#endif
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/files/storagedevice.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/files/storagedevice.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/files/storagedevice.h	(revision 453)
@@ -0,0 +1,222 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2016 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+ *  によって公表されている GNU General Public License の Version 2 に記
+ *  述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+ *  を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+ *  含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+ *  接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+#ifndef _STORAGEDEVICE_H_
+#define _STORAGEDEVICE_H_
+
+#include <kernel.h>
+#include <stdlib.h>
+#include <string.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#ifndef TOPPERS_MACRO_ONLY
+#include <fcntl.h>
+#endif /* TOPPERS_MACRO_ONLY */
+
+/*
+ * This file includes the definitions for open and fcntl
+ * described by POSIX for <fcntl.h>; it also includes
+ * related kernel definitions.
+ */
+#ifndef TOPPERS_MACRO_ONLY
+#include <sys/types.h>
+#endif /* TOPPERS_MACRO_ONLY */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ *  ストレージデバイスの基本設定
+ */
+#ifndef NUM_STORAGEDEVICE
+#define	NUM_STORAGEDEVICE   4		/* デフォルトのストレージデバイス数 */
+#endif
+#define MINIMUM_DEVNO       0
+#define MAXIMUM_DEVNO       9
+#ifndef DEFAULT_DEVNO
+#define DEFAULT_DEVNO       MINIMUM_DEVNO
+#endif
+
+#define SDEV_ACTIVE         (1<<15)	/* アクティブなデバイス */
+#define SDEV_INSERTCHK      (1<<14)	/* 挿入・排出の設定あり */
+#define SDEV_CHKREMOVE      (1<<13)	/* 排出検査する */
+#define SDEV_ONEEXIT        (1<<12)	/* 一度排出あり */
+#define SDEV_EMPLOY         (1<<8)	/* 使用可能 */
+#define SDEV_DEVERROR       (1<<7)	/* DEVICE ERROR */
+#define SDEV_DEVNOTUSE      (1<<0)	/* DEVICE 使用不可 */
+#define SDEV_NOTUSE         255
+
+
+/* File attribute bits for directory entry */
+
+#define	AM_RDO	0x01	/* Read only */
+#define	AM_HID	0x02	/* Hidden */
+#define	AM_SYS	0x04	/* System */
+#define	AM_VOL	0x08	/* Volume label */
+#define AM_LFN	0x0F	/* LFN entry */
+#define AM_DIR	0x10	/* Directory */
+#define AM_ARC	0x20	/* Archive */
+#define AM_MASK	0x3F	/* Mask of defined bits */
+
+/*
+ *  chmod value
+ */
+#define FF_READ     0x0000444
+#define FF_WRITE    0x0000222
+#define FF_EXEC     0x0000111
+
+#define SENSE_TIME      (500)
+
+#ifndef TOPPERS_MACRO_ONLY
+
+struct dirent2
+{
+/* NOTE: This is OUR VERSION of this structure. It contains all the fields currently used by IPS code.
+	If you add fields here, you will also have to modify vcwrapnt.c::*dir() to fill those fields! */
+	unsigned long  d_fsize;
+	unsigned short d_date;
+	unsigned short d_time;
+	unsigned short d_reclen;
+	unsigned char  d_type;
+	unsigned char  d_dummy;
+	char           d_name[256];		/* FIXME: use NAME_MAX? */
+};
+
+/*
+ * file system statistics
+ */
+struct statfs2 {
+  long           f_type;		/* type of file system (unused; zero) */
+  long           f_bsize;		/* fundamental file system block size */
+  long           f_blocks;		/* total data blocks in file system */
+  long           f_bfree;		/* free blocks in fs */
+  long           f_bavail;		/* free blocks avail to non-superuser */
+};
+
+/*
+ *  デバイスドライバー用関数テーブル定義
+ */
+typedef struct StorageDeviceFunc {
+	int (*_sdevf_sense)(void *psdev, bool_t on);
+	int (*_sdevf_diskinit)();
+	int (*_sdevf_diskstatus)();
+	int (*_sdevf_diskread)();
+	int (*_sdevf_diskwrite)();
+	int (*_sdevf_diskioctl)();
+} StorageDeviceFunc_t;
+
+/*
+ *  POSIXファイルインターフェイス用関数テーブル定義
+ */
+typedef struct StorageDeviceFileFunc {
+	void  *(*_sdevff_opendir)(const char *name);
+	int   (*_sdevff_closedir)(void *dir);
+	int   (*_sdevff_readdir)(void *dir, void *dirent2);
+	int   (*_sdevff_mkdir)(const char *name);
+	int   (*_sdevff_rmdir)(const char *name);
+	int   (*_sdevff_unlink)(const char *name);
+	int   (*_sdevff_rename)(const char *oname, const char *nname);
+	int   (*_sdevff_chmod)(const char *name, int mode);
+	int   (*_sdevff_stat)(const char *name, struct stat *buf);
+	int   (*_sdevff_statfs)(const char *name, void *status);
+	int   (*_sdevff_open)(int devno, const char *name, int flags);
+	int   (*_sdevff_close)(int fd);
+ 	int   (*_sdevff_fstat)(int fd, struct stat *buf);
+	off_t (*_sdevff_lseek)(int fd, off_t offset, int whence, int *res);
+	long  (*_sdevff_read)(int fd, void *buf, long count, int *res);
+	long  (*_sdevff_write)(int fd, const void *buf, long count, int *res);
+	void  *(*_sdevff_mmap)(void *start, size_t length, int prot, int flags, int fd, off_t offset);
+} StorageDeviceFileFunc_t;
+
+/*
+ *  ストレージデバイス型定義
+ */
+typedef struct StorageDevice {
+    uint16_t    _sdev_attribute;
+	uint8_t     _sdev_devno;
+	uint8_t     _sdev_port;
+    uint32_t    _sdev_maxsec;
+    uint32_t    _sdev_secsize;
+	uint16_t    _sdev_instimer;
+	uint16_t    _sdev_inswait;
+    void  (*_sdev_notice)(void *psdev, bool_t sw);
+    void  *_sdev_local[4];
+	StorageDeviceFunc_t     *pdevf;
+	StorageDeviceFileFunc_t *pdevff;
+} StorageDevice_t;
+
+/*
+ *  ストレージデバイスヘッダー型定義
+ */
+typedef struct StorageDeviceHead {
+	int16_t     _num_activedev;
+    int8_t      _sdev_active;
+	int8_t      _default_device;
+	uint32_t    (*_get_datetime)(void);
+    StorageDevice_t *_psd;
+} StorageDeviceHead_t;
+
+/*
+ *  SDMの全体定義
+ */
+extern StorageDeviceHead_t SDeviceHead;
+
+/*
+ *  各サービスのプロトタイプ宣言
+ */
+extern void  sdev_init(intptr_t exinf);
+extern void  sdev_terminate(void);
+extern ER    SDMSetupDevice(int16_t devno, StorageDevice_t **ppsdev);
+extern ER_ID SDMGetDeviceNo(const char **ppathname);
+extern StorageDevice_t *SDMGetStorageDevice(int devno);
+extern ER    SDMEmploy(StorageDevice_t *psdev, bool_t sw);
+extern void  SDMSence_task(intptr_t exinf);
+
+extern void stdfile_init(intptr_t exinf);
+extern void volume_info_init(intptr_t exinf);
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _STORAGEDEVICE_H_ */
+/*  end of file  */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_ILI9341/Makefile.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_ILI9341/Makefile.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_ILI9341/Makefile.config	(revision 453)
@@ -0,0 +1,55 @@
+#
+#   TOPPERS/ASP/FMP Kernel
+#       Toyohashi Open Platform for Embedded Real-Time Systems/
+#       Advanced Standard Profile Kernel
+#
+#   Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                               Toyohashi Univ. of Technology, JAPAN
+#   Copyright (C) 2003-2008 by Ryosuke Takeuchi
+#                Platform Development Center RICOH COMPANY,LTD. JAPAN
+#   Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+ 
+#
+#  Makefile のプロセッサ依存 (adafruit ILI9341:LCD用)
+#
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/gdic/adafruit_ILI9341
+
+#
+#  ADAFRUIT ILI9341 LCD DRIVER(GDIC)に関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR):$(SRCDIR)/gdic/adafruit_ILI9341
+SYSSVC_COBJS := $(SYSSVC_COBJS) adafruit_ILI9341.o
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_ILI9341/adafruit_ILI9341.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_ILI9341/adafruit_ILI9341.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_ILI9341/adafruit_ILI9341.c	(revision 453)
@@ -0,0 +1,757 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *  Written by Limor Fried/Ladyada for Adafruit Industries.
+ *  MIT license, all text above must be included in any redistribution
+ *　http://opensource.org/licenses/mit-license.php 
+ */
+
+/* 
+ *  ADAFRUIT ILI9341 2.8"LCD制御プログラムの本体
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <target_syssvc.h>
+#include "syssvc/syslog.h"
+#include "device.h"
+#include "adafruit_ILI9341.h"
+
+/*
+ *  サービスコールのエラーのログ出力
+ */
+Inline void
+svc_perror(const char *file, int_t line, const char *expr, ER ercd)
+{
+	if (ercd < 0) {
+		t_perror(LOG_ERROR, file, line, expr, ercd);
+	}
+}
+
+#define	SVC_PERROR(expr)	svc_perror(__FILE__, __LINE__, #expr, (expr))
+#define ABS(X)  ((X) > 0 ? (X) : -(X))
+
+
+/* Buffer used for transmission */
+static uint8_t aTxBuffer[4];
+
+#define PORT_HIGH           1
+#define PORT_LOW            0
+
+#define MADCTL_MY           0x80
+#define MADCTL_MX           0x40
+#define MADCTL_MV           0x20
+#define MADCTL_ML           0x10
+#define MADCTL_RGB          0x00
+#define MADCTL_BGR          0x08
+#define MADCTL_MH           0x04
+
+
+#define cs_set(sw)  digitalWrite(hlcd->cs_pin, sw)
+#define dc_set(sw)  digitalWrite(hlcd->dc_pin, sw)
+#define rst_set(sw) digitalWrite(hlcd->rst_pin, sw)
+#define cs2_set(sw) digitalWrite(hlcd->cs2_pin, sw)
+
+
+/*
+ *  LCDへのコマンド送信関数
+ */
+ER
+lcd_writecommand(LCD_Handler_t *hlcd, uint8_t c)
+{
+	ER ercd = E_OK;
+
+	if(hlcd->spi_lock != 0){
+		if((ercd = wai_sem(hlcd->spi_lock)) != E_OK)
+			return ercd;
+	}
+	dc_set(PORT_LOW);
+	cs_set(PORT_LOW);
+
+	aTxBuffer[0] = c;
+#if SPI_WAIT_TIME != 0
+	ercd = spi_transmit(hlcd->hspi, (uint8_t*)aTxBuffer, 1);
+#else
+	if((ercd = spi_transmit(hlcd->hspi, (uint8_t*)aTxBuffer, 1)) == E_OK){
+		ercd = spi_wait(hlcd->hspi, 100);
+	}
+#endif
+
+	cs_set(PORT_HIGH);
+	if(hlcd->spi_lock != 0)
+		sig_sem(hlcd->spi_lock);
+	return ercd;
+}
+
+/*
+ *  LCDへのデータ送信関数
+ */
+ER
+lcd_writedata(LCD_Handler_t *hlcd, uint8_t c)
+{
+	ER ercd = E_OK;
+
+	if(hlcd->spi_lock != 0){
+		if((ercd = wai_sem(hlcd->spi_lock)) != E_OK)
+			return ercd;
+	}
+	dc_set(PORT_HIGH);
+	cs_set(PORT_LOW);
+	sil_dly_nse(100);
+
+	aTxBuffer[0] = c;
+#if SPI_WAIT_TIME != 0
+	ercd = spi_transmit(hlcd->hspi, (uint8_t*)aTxBuffer, 1);
+#else
+	if((ercd = spi_transmit(hlcd->hspi, (uint8_t*)aTxBuffer, 1)) == E_OK){
+		ercd = spi_wait(hlcd->hspi, 100);
+	}
+#endif
+
+	sil_dly_nse(100);
+	cs_set(PORT_HIGH);
+	if(hlcd->spi_lock != 0)
+		sig_sem(hlcd->spi_lock);
+	return ercd;
+}
+
+/*
+ *  LCDへの２バイトデータ送信関数
+ */
+ER
+lcd_writedata2(LCD_Handler_t *hlcd, uint16_t c, int cnt)
+{
+	ER  ercd = E_OK;
+	int i;
+
+	if(cnt == 0)
+		return ercd;
+	if(hlcd->spi_lock != 0){
+		if((ercd = wai_sem(hlcd->spi_lock)) != E_OK)
+			return ercd;
+	}
+	dc_set(PORT_HIGH);
+	cs_set(PORT_LOW);
+	sil_dly_nse(100);
+	aTxBuffer[0] = c >> 8;
+	aTxBuffer[1] = (uint8_t)c;
+	for(i = 0 ; i < cnt ; i++){
+		if((ercd = spi_transmit(hlcd->hspi, (uint8_t*)aTxBuffer, 2)) != E_OK){
+			break;
+		}
+#if SPI_WAIT_TIME == 0
+		if((ercd = spi_wait(hlcd->hspi, 100)) != E_OK){
+			break;
+		}
+#endif
+	}
+	sil_dly_nse(100);
+	cs_set(PORT_HIGH);
+	if(hlcd->spi_lock != 0)
+		sig_sem(hlcd->spi_lock);
+	return ercd;
+}
+
+/*
+ *  LCDへのRGBデータ送信関数
+ */
+ER
+lcd_writedata3(LCD_Handler_t *hlcd, uint8_t *pbmp, uint16_t width, uint16_t height)
+{
+	ER  ercd = E_OK;
+	int index, i;
+
+	if(width == 0 || height == 0)
+		return ercd;
+	if(hlcd->spi_lock != 0){
+		if((ercd = wai_sem(hlcd->spi_lock)) != E_OK)
+			return ercd;
+	}
+	dc_set(PORT_HIGH);
+	cs_set(PORT_LOW);
+	sil_dly_nse(100);
+	for(index=0; index < height; index++){
+		uint8_t *p = pbmp;
+		for (i = 0; i < width; i++){
+			aTxBuffer[0]  = (*p++) & 0xf8;
+			aTxBuffer[0] |= *p >> 5;
+			aTxBuffer[1]  = (*p++ << 3) & 0xE0;
+			aTxBuffer[1] |= (*p++ >> 3) & 0x1F;
+			if((ercd = spi_transmit(hlcd->hspi, (uint8_t*)aTxBuffer, 2)) != E_OK){
+				break;
+			}
+#if SPI_WAIT_TIME == 0
+			if((ercd = spi_wait(hlcd->hspi, 100)) != E_OK){
+				break;
+			}
+#endif
+		}
+		pbmp -= width*3;
+	}
+	sil_dly_nse(100);
+	cs_set(PORT_HIGH);
+	if(hlcd->spi_lock != 0)
+		sig_sem(hlcd->spi_lock);
+	return ercd;
+}
+
+
+/*
+ *  表示ウィンドウ設定
+ */
+void
+lcd_setAddrWindow(LCD_Handler_t *hlcd, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
+{
+	uint16_t tmp;
+
+	SVC_PERROR(lcd_writecommand(hlcd, ILI9341_CASET)); // Column addr set
+	tmp = x0 + hlcd->colstart;
+	SVC_PERROR(lcd_writedata(hlcd, (tmp >> 8)));
+	SVC_PERROR(lcd_writedata(hlcd, (tmp & 0xFF)));     // XSTART 
+	tmp = x1 + hlcd->colstart;
+	SVC_PERROR(lcd_writedata(hlcd, (tmp >> 8)));
+	SVC_PERROR(lcd_writedata(hlcd, (tmp & 0xFF)));     // XEND
+
+	SVC_PERROR(lcd_writecommand(hlcd, ILI9341_PASET)); // Row addr set
+	tmp = y0 + hlcd->rowstart;
+	SVC_PERROR(lcd_writedata(hlcd, (tmp >> 8)));
+	SVC_PERROR(lcd_writedata(hlcd, (tmp & 0xFF)));     // YSTART
+	tmp = y1 + hlcd->rowstart;
+	SVC_PERROR(lcd_writedata(hlcd, (tmp >> 8)));
+	SVC_PERROR(lcd_writedata(hlcd, (tmp & 0xFF)));     // YEND
+
+	SVC_PERROR(lcd_writecommand(hlcd, ILI9341_RAMWR)); // write to RAM
+}
+
+
+/*
+ *  ILI9341 screensの初期化関数
+ */
+void
+lcd_init(LCD_Handler_t *hlcd, uint8_t rotation)
+{
+	hlcd->colstart  = hlcd->rowstart = 0; // May be overridden in init func
+	hlcd->_width = ILI9341_TFTWIDTH;
+	hlcd->_height = ILI9341_TFTHEIGHT;
+
+	// toggle RST low to reset; CS low so it'll listen to us
+	cs_set(PORT_LOW);
+	if(hlcd->rst_pin < 14){
+		rst_set(PORT_HIGH);
+		dly_tsk(5);
+		rst_set(PORT_LOW);
+		dly_tsk(20);
+		rst_set(PORT_HIGH);
+		dly_tsk(150);
+	}
+
+	SVC_PERROR(lcd_writecommand(hlcd, 0xEF));
+	SVC_PERROR(lcd_writedata(hlcd, 0x03));
+	SVC_PERROR(lcd_writedata(hlcd, 0x80));
+	SVC_PERROR(lcd_writedata(hlcd, 0x02));
+
+	SVC_PERROR(lcd_writecommand(hlcd, 0xCF));
+	SVC_PERROR(lcd_writedata(hlcd, 0x00));
+	SVC_PERROR(lcd_writedata(hlcd, 0xC1));
+	SVC_PERROR(lcd_writedata(hlcd, 0x30));
+
+	SVC_PERROR(lcd_writecommand(hlcd, 0xED));
+	SVC_PERROR(lcd_writedata(hlcd, 0x64));
+	SVC_PERROR(lcd_writedata(hlcd, 0x03));
+	SVC_PERROR(lcd_writedata(hlcd, 0x12));
+	SVC_PERROR(lcd_writedata(hlcd, 0x81));
+
+	SVC_PERROR(lcd_writecommand(hlcd, 0xE8));
+	SVC_PERROR(lcd_writedata(hlcd, 0x85));
+	SVC_PERROR(lcd_writedata(hlcd, 0x00));
+	SVC_PERROR(lcd_writedata(hlcd, 0x78));
+
+	SVC_PERROR(lcd_writecommand(hlcd, 0xCB));
+	SVC_PERROR(lcd_writedata(hlcd, 0x39));
+	SVC_PERROR(lcd_writedata(hlcd, 0x2C));
+	SVC_PERROR(lcd_writedata(hlcd, 0x00));
+	SVC_PERROR(lcd_writedata(hlcd, 0x34));
+	SVC_PERROR(lcd_writedata(hlcd, 0x02));
+
+	SVC_PERROR(lcd_writecommand(hlcd, 0xF7));
+	SVC_PERROR(lcd_writedata(hlcd, 0x20));
+
+	SVC_PERROR(lcd_writecommand(hlcd, 0xEA));
+	SVC_PERROR(lcd_writedata(hlcd, 0x00));
+	SVC_PERROR(lcd_writedata(hlcd, 0x00));
+
+	SVC_PERROR(lcd_writecommand(hlcd, ILI9341_PWCTR1));	/* Power control */
+	SVC_PERROR(lcd_writedata(hlcd, 0x23));				/* VRH[5:0] */
+
+	SVC_PERROR(lcd_writecommand(hlcd, ILI9341_PWCTR2));	/* Power control */
+	SVC_PERROR(lcd_writedata(hlcd, 0x10));				/* SAP[2:0];BT[3:0] */
+
+	SVC_PERROR(lcd_writecommand(hlcd, ILI9341_VMCTR1));	/* VCM control */
+	SVC_PERROR(lcd_writedata(hlcd, 0x3e));
+	SVC_PERROR(lcd_writedata(hlcd, 0x28));
+
+	SVC_PERROR(lcd_writecommand(hlcd, ILI9341_VMCTR2));	/* VCM control2 */
+	SVC_PERROR(lcd_writedata(hlcd, 0x86));				/* -- */
+
+	SVC_PERROR(lcd_writecommand(hlcd, ILI9341_MADCTL));	/* Memory Access Control */
+	SVC_PERROR(lcd_writedata(hlcd, 0x48));
+
+	SVC_PERROR(lcd_writecommand(hlcd, ILI9341_PIXFMT));
+	SVC_PERROR(lcd_writedata(hlcd, 0x55));
+
+	SVC_PERROR(lcd_writecommand(hlcd, ILI9341_FRMCTR1));
+	SVC_PERROR(lcd_writedata(hlcd, 0x00));
+	SVC_PERROR(lcd_writedata(hlcd, 0x18));
+
+	SVC_PERROR(lcd_writecommand(hlcd, ILI9341_DFUNCTR)); /* Display Function Control */
+	SVC_PERROR(lcd_writedata(hlcd, 0x08));
+	SVC_PERROR(lcd_writedata(hlcd, 0x82));
+	SVC_PERROR(lcd_writedata(hlcd, 0x27));
+
+	SVC_PERROR(lcd_writecommand(hlcd, 0xF2));			/* 3Gamma Function Disable */
+	SVC_PERROR(lcd_writedata(hlcd, 0x00));
+
+	SVC_PERROR(lcd_writecommand(hlcd, ILI9341_GAMMASET)); /* Gamma curve selected */
+	SVC_PERROR(lcd_writedata(hlcd, 0x01));
+
+	SVC_PERROR(lcd_writecommand(hlcd, ILI9341_GMCTRP1)); /* Set Gamma */
+	SVC_PERROR(lcd_writedata(hlcd, 0x0F));
+	SVC_PERROR(lcd_writedata(hlcd, 0x31));
+	SVC_PERROR(lcd_writedata(hlcd, 0x2B));
+	SVC_PERROR(lcd_writedata(hlcd, 0x0C));
+	SVC_PERROR(lcd_writedata(hlcd, 0x0E));
+	SVC_PERROR(lcd_writedata(hlcd, 0x08));
+	SVC_PERROR(lcd_writedata(hlcd, 0x4E));
+	SVC_PERROR(lcd_writedata(hlcd, 0xF1));
+	SVC_PERROR(lcd_writedata(hlcd, 0x37));
+	SVC_PERROR(lcd_writedata(hlcd, 0x07));
+	SVC_PERROR(lcd_writedata(hlcd, 0x10));
+	SVC_PERROR(lcd_writedata(hlcd, 0x03));
+	SVC_PERROR(lcd_writedata(hlcd, 0x0E));
+	SVC_PERROR(lcd_writedata(hlcd, 0x09));
+	SVC_PERROR(lcd_writedata(hlcd, 0x00));
+
+	SVC_PERROR(lcd_writecommand(hlcd, ILI9341_GMCTRN1)); /* Set Gamma */
+	SVC_PERROR(lcd_writedata(hlcd, 0x00));
+	SVC_PERROR(lcd_writedata(hlcd, 0x0E));
+	SVC_PERROR(lcd_writedata(hlcd, 0x14));
+	SVC_PERROR(lcd_writedata(hlcd, 0x03));
+	SVC_PERROR(lcd_writedata(hlcd, 0x11));
+	SVC_PERROR(lcd_writedata(hlcd, 0x07));
+	SVC_PERROR(lcd_writedata(hlcd, 0x31));
+	SVC_PERROR(lcd_writedata(hlcd, 0xC1));
+	SVC_PERROR(lcd_writedata(hlcd, 0x48));
+	SVC_PERROR(lcd_writedata(hlcd, 0x08));
+	SVC_PERROR(lcd_writedata(hlcd, 0x0F));
+	SVC_PERROR(lcd_writedata(hlcd, 0x0C));
+	SVC_PERROR(lcd_writedata(hlcd, 0x31));
+	SVC_PERROR(lcd_writedata(hlcd, 0x36));
+	SVC_PERROR(lcd_writedata(hlcd, 0x0F));
+
+	SVC_PERROR(lcd_writecommand(hlcd, ILI9341_SLPOUT));	/* Exit Sleep */
+	dly_tsk(120);
+	SVC_PERROR(lcd_writecommand(hlcd, ILI9341_DISPON));	/* Display on */
+	lcd_setRotation(hlcd, rotation);
+}
+
+/*
+ *  RECTANGLEのフィル描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: start X position
+ *  param3  y: start Y position
+ *  param4  w: width
+ *  param5  h: height
+ *  param6  color: color value
+ */
+void
+lcd_fillRect(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t w, int16_t h, color_t color)
+{
+	// rudimentary clipping (drawChar w/big text requires this)
+	if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
+	if((x + w - 1) >= hlcd->_width)  w = hlcd->_width  - x;
+	if((y + h - 1) >= hlcd->_height) h = hlcd->_height - y;
+
+	lcd_setAddrWindow(hlcd, x, y, x+w-1, y+h-1);
+	SVC_PERROR(lcd_writedata2(hlcd, color, h*w));
+}
+
+void
+lcd_pushColor(LCD_Handler_t *hlcd, color_t color)
+{
+	SVC_PERROR(lcd_writedata2(hlcd, color, 1));
+}
+
+/*
+ *  PIXEL描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: X position
+ *  param3  y: Y position
+ *  param4  color: color value
+ */
+void
+lcd_drawPixel(LCD_Handler_t *hlcd, int16_t x, int16_t y, color_t color)
+{
+	if((x < 0) ||(x >= hlcd->_width) || (y < 0) || (y >= hlcd->_height)) return;
+
+	lcd_setAddrWindow(hlcd, x, y, x, y);
+	SVC_PERROR(lcd_writedata2(hlcd, color, 1));
+}
+
+/*
+ *  垂直方向LINEの高速描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: start X position
+ *  param3  y: start Y position
+ *  param4  h: height
+ *  param5  color: color value
+ */
+void
+lcd_drawFastVLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t h, color_t color)
+{
+	// Rudimentary clipping
+	if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
+	if((y+h-1) >= hlcd->_height) h = hlcd->_height-y;
+	lcd_setAddrWindow(hlcd, x, y, x, y+h-1);
+	SVC_PERROR(lcd_writedata2(hlcd, color, h));
+}
+
+/*
+ *  水平方向LINEの高速描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: start X position
+ *  param3  y: start Y position
+ *  param4  w: width
+ *  param5  color: color value
+ */
+void lcd_drawFastHLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t w, color_t color)
+{
+	// Rudimentary clipping
+	if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
+	if((x+w-1) >= hlcd->_width)  w = hlcd->_width-x;
+	lcd_setAddrWindow(hlcd, x, y, x+w-1, y);
+	SVC_PERROR(lcd_writedata2(hlcd, color, w));
+}
+
+/*
+ *  DRAW IMAGE LINE描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: X position
+ *  param3  y: Y position
+ *  param4  w: width
+ *  param5  pcolor: color value
+ */
+void
+lcd_drawImageHLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, uint16_t w, color_t *pcolor)
+{
+	uint32_t i;
+
+	if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
+	if((x+w-1) >= hlcd->_width)  w = hlcd->_width-x;
+
+	lcd_setAddrWindow(hlcd, x, y, x+w-1, y);
+	for(i = 0 ; i < w ; i++, pcolor++)
+		SVC_PERROR(lcd_writedata2(hlcd, *pcolor, 1));
+}
+
+/*
+ *  BITMAP描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x0: Bmp X position in the LCD
+ *  param3  y0: Bmp Y position in the LCD
+ *  param4  pbmp: Pointer to Bmp picture address in the internal Flash
+ */
+void
+lcd_drawBitmap(LCD_Handler_t *hlcd, uint16_t x0, uint16_t y0, uint8_t *pbmp)
+{
+	uint32_t index = 0, width = 0, height = 0, bit_pixel = 0;
+	uint32_t input_color_mode = 0;
+
+	/* Get bitmap data address offset */
+	index = *(uint16_t *) (pbmp + 10);
+	index |= (*(uint16_t *) (pbmp + 12)) << 16;
+
+	/* Read bitmap width */
+	width = *(uint16_t *) (pbmp + 18);
+	width |= (*(uint16_t *) (pbmp + 20)) << 16;
+
+	/* Read bitmap height */
+	height = *(uint16_t *) (pbmp + 22);
+	height |= (*(uint16_t *) (pbmp + 24)) << 16;
+
+	/* Read bit/pixel */
+	bit_pixel = *(uint16_t *) (pbmp + 28);
+
+	/* Get the layer pixel format */
+	if ((bit_pixel/8) == 4){
+		input_color_mode = CM_ARGB8888;
+	}
+	else if ((bit_pixel/8) == 2){
+		input_color_mode = CM_RGB565;
+	}
+	else{
+		input_color_mode = CM_RGB888;
+	}
+
+	/* Bypass the bitmap header */
+	pbmp += (index + (width * (height - 1) * (bit_pixel/8)));  
+	syslog_4(LOG_INFO, "lcd_drawBitmap input_color_mode(%d) width(%d) height(%d) bit_pixel(%d)", input_color_mode, width, height, bit_pixel);
+
+	lcd_setAddrWindow(hlcd, x0, y0, x0+width-1, y0+height-1);
+	lcd_writedata3(hlcd, pbmp, width, height);
+}
+
+/*
+ *  ROTATION設定
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  m: 0:0, 1:90, 2:180, 3:270
+ */
+void
+lcd_setRotation(LCD_Handler_t *hlcd, uint8_t m)
+{
+	SVC_PERROR(lcd_writecommand(hlcd, ILI9341_MADCTL));
+	hlcd->rotation = m % 4;	// can't be higher than 3
+	switch(hlcd->rotation){
+	case 1:
+		SVC_PERROR(lcd_writedata(hlcd, (MADCTL_MV | MADCTL_BGR)));
+		hlcd->_width  = ILI9341_TFTHEIGHT;
+		hlcd->_height = ILI9341_TFTWIDTH;
+		break;
+	case 2:
+		SVC_PERROR(lcd_writedata(hlcd, (MADCTL_MY | MADCTL_BGR)));
+		hlcd->_width  = ILI9341_TFTWIDTH;
+		hlcd->_height = ILI9341_TFTHEIGHT;
+		break;
+	case 3:
+		SVC_PERROR(lcd_writedata(hlcd, (MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR)));
+		hlcd->_width  = ILI9341_TFTHEIGHT;
+		hlcd->_height = ILI9341_TFTWIDTH;
+		break;
+	case 0:
+	default:
+		SVC_PERROR(lcd_writedata(hlcd, (MADCTL_MX | MADCTL_BGR)));
+		hlcd->_width  = ILI9341_TFTWIDTH;
+		hlcd->_height = ILI9341_TFTHEIGHT;
+		break;
+	}
+}
+
+/*
+ *  INVERT DISPLAY
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  i: invert value
+ */
+void
+lcd_invertDisplay(LCD_Handler_t *hlcd, bool_t i)
+{
+	SVC_PERROR(lcd_writecommand(hlcd, i ? ILI9341_INVON : ILI9341_INVOFF));
+}
+
+
+/*
+ *  スクリーンフィル
+ *  param1  pDrawProp: Pointer to Draw Prop
+ */
+void
+lcd_fillScreen(LCD_DrawProp_t *pDrawProp)
+{
+	lcd_fillRect(pDrawProp->hlcd, 0, 0,  pDrawProp->hlcd->_width, pDrawProp->hlcd->_height, pDrawProp->BackColor);
+}
+
+/*
+ *  RECTANGLE描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x: left X position
+ *  param3  y: top Y position
+ *  param4  w: width
+ *  param5  h: height
+ */
+void
+lcd_drawRect(LCD_DrawProp_t *pDrawProp, int16_t x, int16_t y, int16_t w, int16_t h)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	color_t color;
+
+	// rudimentary clipping (drawChar w/big text requires this)
+	if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
+	if((x + w - 1) >= hlcd->_width)  w = hlcd->_width  - x;
+	if((y + h - 1) >= hlcd->_height) h = hlcd->_height - y;
+
+	color = pDrawProp->TextColor;
+	lcd_drawFastVLine(hlcd, x, y, h, color);
+	lcd_drawFastHLine(hlcd, x, y+h-1, w, color);
+	lcd_drawFastVLine(hlcd, x+w-1, y, h, color);
+	lcd_drawFastHLine(hlcd, x, y, w, color);
+}
+
+/*
+ *  円描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x0: X position
+ *  param3  y0: Y position
+ *  param4  Radius: Circle radius
+ */
+void
+lcd_DrawCircle(LCD_DrawProp_t *pDrawProp, uint16_t x0, uint16_t y0, uint16_t Radius)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+ 	int32_t   decision;    /* Decision Variable */ 
+	uint32_t  current_x;   /* Current X Value */
+	uint32_t  current_y;   /* Current Y Value */
+
+	decision = 3 - (Radius << 1);
+	current_x = 0;
+	current_y = Radius;
+
+	while(current_x <= current_y){
+		lcd_drawPixel(hlcd, (x0 + current_x), (y0 - current_y), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 - current_x), (y0 - current_y), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 + current_y), (y0 - current_x), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 - current_y), (y0 - current_x), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 + current_x), (y0 + current_y), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 - current_x), (y0 + current_y), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 + current_y), (y0 + current_x), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 - current_y), (y0 + current_x), pDrawProp->TextColor);
+
+		if (decision < 0){
+			decision += (current_x << 2) + 6;
+		}
+		else{
+			decision += ((current_x - current_y) << 2) + 10;
+			current_y--;
+		}
+		current_x++;
+	}
+}
+
+/*
+ *  線描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x1: Point 1 X position
+ *  param3  y1: Point 1 Y position
+ *  param4  x2: Point 2 X position
+ *  param5  y2: Point 2 Y position
+ */
+void
+lcd_drawLine(LCD_DrawProp_t *pDrawProp, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0, 
+	yinc1 = 0, yinc2 = 0, den = 0, num = 0, num_add = 0, num_pixels = 0, 
+	curpixel = 0;
+
+	deltax = ABS(x2 - x1);		/* The difference between the x's */
+	deltay = ABS(y2 - y1);		/* The difference between the y's */
+	x = x1;						/* Start x off at the first pixel */
+	y = y1;						/* Start y off at the first pixel */
+
+	if(x2 >= x1){				/* The x-values are increasing */
+		xinc1 = 1;
+		xinc2 = 1;
+	}
+	else{						/* The x-values are decreasing */
+		xinc1 = -1;
+		xinc2 = -1;
+	}
+
+	if(y2 >= y1){				/* The y-values are increasing */
+		yinc1 = 1;
+		yinc2 = 1;
+	}
+	else{						/* The y-values are decreasing */
+		yinc1 = -1;
+		yinc2 = -1;
+	}
+
+	if(deltax >= deltay){		/* There is at least one x-value for every y-value */
+		xinc1 = 0;				/* Don't change the x when numerator >= denominator */
+		yinc2 = 0;				/* Don't change the y for every iteration */
+		den = deltax;
+		num = deltax / 2;
+		num_add = deltay;
+		num_pixels = deltax;	/* There are more x-values than y-values */
+	}
+	else{						/* There is at least one y-value for every x-value */
+		xinc2 = 0;				/* Don't change the x for every iteration */
+		yinc1 = 0;				/* Don't change the y when numerator >= denominator */
+		den = deltay;
+		num = deltay / 2;
+		num_add = deltax;
+		num_pixels = deltay;	/* There are more y-values than x-values */
+	}
+
+	for (curpixel = 0; curpixel <= num_pixels; curpixel++){
+		lcd_drawPixel(hlcd, x, y, pDrawProp->TextColor);	/* Draw the current pixel */
+		num += num_add;			/* Increase the numerator by the top of the fraction */
+		if(num >= den){			/* Check if numerator >= denominator */
+			num -= den;			/* Calculate the new numerator value */
+			x += xinc1;			/* Change the x as appropriate */
+			y += yinc1;			/* Change the y as appropriate */
+		}
+		x += xinc2;				/* Change the x as appropriate */
+		y += yinc2;				/* Change the y as appropriate */
+	}
+}
+
+/*
+ *  PLOY-LINE描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  Points: Pointer to the points array
+ *  param3  PointCount: Number of points
+ */
+void
+lcd_drawPolygon(LCD_DrawProp_t *pDrawProp, pPoint Points, uint16_t PointCount)
+{
+	int16_t x = 0, y = 0;
+
+	if(PointCount < 2){
+		return;
+	}
+
+	lcd_drawLine(pDrawProp, Points->X, Points->Y, (Points+PointCount-1)->X, (Points+PointCount-1)->Y);
+	while(--PointCount){
+		x = Points->X;
+		y = Points->Y;
+		Points++;
+		lcd_drawLine(pDrawProp, x, y, Points->X, Points->Y);
+	}
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_ILI9341/adafruit_ILI9341.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_ILI9341/adafruit_ILI9341.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_ILI9341/adafruit_ILI9341.h	(revision 453)
@@ -0,0 +1,210 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ *
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ *
+ *  $Id$
+ */
+
+/*
+ *  Written by Limor Fried/Ladyada for Adafruit Industries.
+ *  MIT license, all text above must be included in any redistribution
+ *　http://opensource.org/licenses/mit-license.php 
+ */
+
+/*
+ *  ADAFRUIT ILI9341 2.8"LCD制御プログラムのヘッダファイル
+ */
+
+#ifndef _ADAFRUIT_ILI9341_H_
+#define _ADAFRUIT_ILI9341_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include "device.h"
+#include "pinmode.h"
+#include "spi.h"
+
+/*
+ *  LCDカラーモード定義
+ */
+#define CM_ARGB8888         0x00000000			/* ARGB8888 color mode */
+#define CM_RGB888           0x00000001			/* RGB888 color mode */
+#define CM_RGB565           0x00000002			/* RGB565 color mode */
+
+
+
+#define ILI9341_TFTWIDTH  240
+#define ILI9341_TFTHEIGHT 320
+
+#define ILI9341_NOP     0x00
+#define ILI9341_SWRESET 0x01
+#define ILI9341_RDDID   0x04
+#define ILI9341_RDDST   0x09
+
+#define ILI9341_SLPIN   0x10
+#define ILI9341_SLPOUT  0x11
+#define ILI9341_PTLON   0x12
+#define ILI9341_NORON   0x13
+
+#define ILI9341_RDMODE  0x0A
+#define ILI9341_RDMADCTL  0x0B
+#define ILI9341_RDPIXFMT  0x0C
+#define ILI9341_RDIMGFMT  0x0A
+#define ILI9341_RDSELFDIAG  0x0F
+
+#define ILI9341_INVOFF  0x20
+#define ILI9341_INVON   0x21
+#define ILI9341_GAMMASET 0x26
+#define ILI9341_DISPOFF 0x28
+#define ILI9341_DISPON  0x29
+
+#define ILI9341_CASET   0x2A
+#define ILI9341_PASET   0x2B
+#define ILI9341_RAMWR   0x2C
+#define ILI9341_RAMRD   0x2E
+
+#define ILI9341_PTLAR   0x30
+#define ILI9341_MADCTL  0x36
+#define ILI9341_PIXFMT  0x3A
+
+#define ILI9341_FRMCTR1 0xB1
+#define ILI9341_FRMCTR2 0xB2
+#define ILI9341_FRMCTR3 0xB3
+#define ILI9341_INVCTR  0xB4
+#define ILI9341_DFUNCTR 0xB6
+
+#define ILI9341_PWCTR1  0xC0
+#define ILI9341_PWCTR2  0xC1
+#define ILI9341_PWCTR3  0xC2
+#define ILI9341_PWCTR4  0xC3
+#define ILI9341_PWCTR5  0xC4
+#define ILI9341_VMCTR1  0xC5
+#define ILI9341_VMCTR2  0xC7
+
+#define ILI9341_RDID1   0xDA
+#define ILI9341_RDID2   0xDB
+#define ILI9341_RDID3   0xDC
+#define ILI9341_RDID4   0xDD
+
+#define ILI9341_GMCTRP1 0xE0
+#define ILI9341_GMCTRN1 0xE1
+
+// Color definitions
+#define	ILI9341_BLACK   0x0000
+#define	ILI9341_BLUE    0x001F
+#define	ILI9341_RED     0xF800
+#define	ILI9341_GREEN   0x07E0
+#define ILI9341_CYAN    0x07FF
+#define ILI9341_MAGENTA 0xF81F
+#define ILI9341_YELLOW  0xFFE0
+#define ILI9341_WHITE   0xFFFF
+
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  カラーの属性を定義
+ */
+typedef uint16_t   color_t;
+
+/*
+ *  LCDハンドラ構造体定義
+ */
+typedef struct
+{
+	SPI_Handle_t            *hspi;		/* spiハンドラ */
+	uint16_t                _width;		/* 幅ピクセル数 */
+	uint16_t				_height;	/* 高さピクセル数 */
+	uint16_t                colstart;
+	uint16_t                rowstart;
+	uint8_t                 rotation;	/* LCD回転設定 */
+	uint8_t                 cs_pin;
+	uint8_t                 dc_pin;
+	uint8_t                 rst_pin;
+	ID                      spi_lock;
+}LCD_Handler_t;
+
+/*
+ *  描画構造体
+ */
+typedef struct
+{
+	LCD_Handler_t           *hlcd;
+	color_t                 TextColor;
+	color_t                 BackColor;
+	void                    *pFont;
+}LCD_DrawProp_t;
+
+typedef struct
+{
+	int16_t X;
+	int16_t Y;
+}Point, * pPoint;
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+extern ER lcd_writecommand(LCD_Handler_t *hlcd, uint8_t c);
+extern ER lcd_writedata(LCD_Handler_t *hlcd, uint8_t c);
+extern ER lcd_writedata2(LCD_Handler_t *hlcd, uint16_t c, int cnt);
+extern ER lcd_writedata3(LCD_Handler_t *hlcd, uint8_t *pbmp, uint16_t width, uint16_t height);
+
+extern void lcd_init(LCD_Handler_t *hlcd, uint8_t rotation);
+extern void lcd_setAddrWindow(LCD_Handler_t *hlcd, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
+extern void lcd_fillRect(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t w, int16_t h, color_t color);
+extern void lcd_pushColor(LCD_Handler_t *hlcd, color_t color);
+extern void lcd_drawPixel(LCD_Handler_t *hlcd, int16_t x, int16_t y, color_t color);
+extern void lcd_drawFastVLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t h, color_t color);
+extern void lcd_drawFastHLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t w, color_t color);
+extern void lcd_drawImageHLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, uint16_t w, color_t *pcolor);
+extern void lcd_drawBitmap(LCD_Handler_t *hlcd, uint16_t x0, uint16_t y0, uint8_t *pbmp);
+extern void lcd_setRotation(LCD_Handler_t *hlcd, uint8_t m);
+extern void lcd_invertDisplay(LCD_Handler_t *hlcd, bool_t i);
+
+extern void lcd_fillScreen(LCD_DrawProp_t *pDrawProp);
+extern void lcd_drawRect(LCD_DrawProp_t *pDrawProp, int16_t x, int16_t y, int16_t w, int16_t h);
+extern void lcd_DrawCircle(LCD_DrawProp_t *pDrawProp, uint16_t x0, uint16_t y0, uint16_t Radius);
+extern void lcd_drawLine(LCD_DrawProp_t *pDrawProp, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
+extern void lcd_drawPolygon(LCD_DrawProp_t *pDrawProp, pPoint Points, uint16_t PointCount);
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _ADAFRUIT_ILI9341_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_ILI9341/glcd_core.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_ILI9341/glcd_core.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_ILI9341/glcd_core.h	(revision 453)
@@ -0,0 +1,45 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+#ifndef _LCD_CORE_H_
+#define _LCD_CORE_H_
+
+#include "adafruit_ILI9341.h"
+
+#endif /* _LCD_CORE_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_st7735/Makefile.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_st7735/Makefile.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_st7735/Makefile.config	(revision 453)
@@ -0,0 +1,55 @@
+#
+#   TOPPERS/ASP/FMP Kernel
+#       Toyohashi Open Platform for Embedded Real-Time Systems/
+#       Advanced Standard Profile Kernel
+#
+#   Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                               Toyohashi Univ. of Technology, JAPAN
+#   Copyright (C) 2003-2008 by Ryosuke Takeuchi
+#                Platform Development Center RICOH COMPANY,LTD. JAPAN
+#   Copyright (C) 2015-2017 by TOPPERS PROJECT Educational Working Group.
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+ 
+#
+#  Makefile のプロセッサ依存 (adafruit st7735:LCD用)
+#
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/gdic/adafruit_st7735
+
+#
+#  ADAFRUIT ST7735 LCD DRIVER(GDIC)に関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR):$(SRCDIR)/gdic/adafruit_st7735
+SYSSVC_COBJS := $(SYSSVC_COBJS) adafruit_st7735.o
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_st7735/adafruit_st7735.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_st7735/adafruit_st7735.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_st7735/adafruit_st7735.c	(revision 453)
@@ -0,0 +1,836 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2012 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2018 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *  Written by Limor Fried/Ladyada for Adafruit Industries.
+ *  MIT license, all text above must be included in any redistribution
+ *　http://opensource.org/licenses/mit-license.php 
+ */
+
+/* 
+ *  ADAFRUIT ST7735 1.8",1.44"LCD制御プログラムの本体
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <target_syssvc.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#include "device.h"
+#include "adafruit_st7735.h"
+
+/*
+ *  サービスコールのエラーのログ出力
+ */
+Inline void
+svc_perror(const char *file, int_t line, const char *expr, ER ercd)
+{
+	if (ercd < 0) {
+		t_perror(LOG_ERROR, file, line, expr, ercd);
+	}
+}
+
+#define	SVC_PERROR(expr)	svc_perror(__FILE__, __LINE__, #expr, (expr))
+#define ABS(X)  ((X) > 0 ? (X) : -(X))
+
+
+// Rather than a bazillion writecommand() and writedata() calls, screen
+// initialization commands and arguments are organized in these tables
+// stored in PROGMEM.  The table may look bulky, but that's mostly the
+// formatting -- storage-wise this is hundreds of bytes more compact
+// than the equivalent code.  Companion function follows.
+#define DELAY 0x80
+static const uint8_t
+  Bcmd[] = {                  // Initialization commands for 7735B screens
+    18,                       // 18 commands in list:
+    ST7735_SWRESET,   DELAY,  //  1: Software reset, no args, w/delay
+      50,                     //     50 ms delay
+    ST7735_SLPOUT ,   DELAY,  //  2: Out of sleep mode, no args, w/delay
+      255,                    //     255 = 500 ms delay
+    ST7735_COLMOD , 1+DELAY,  //  3: Set color mode, 1 arg + delay:
+      0x05,                   //     16-bit color
+      10,                     //     10 ms delay
+    ST7735_FRMCTR1, 3+DELAY,  //  4: Frame rate control, 3 args + delay:
+      0x00,                   //     fastest refresh
+      0x06,                   //     6 lines front porch
+      0x03,                   //     3 lines back porch
+      10,                     //     10 ms delay
+    ST7735_MADCTL , 1      ,  //  5: Memory access ctrl (directions), 1 arg:
+      0x08,                   //     Row addr/col addr, bottom to top refresh
+    ST7735_DISSET5, 2      ,  //  6: Display settings #5, 2 args, no delay:
+      0x15,                   //     1 clk cycle nonoverlap, 2 cycle gate
+                              //     rise, 3 cycle osc equalize
+      0x02,                   //     Fix on VTL
+    ST7735_INVCTR , 1      ,  //  7: Display inversion control, 1 arg:
+      0x0,                    //     Line inversion
+    ST7735_PWCTR1 , 2+DELAY,  //  8: Power control, 2 args + delay:
+      0x02,                   //     GVDD = 4.7V
+      0x70,                   //     1.0uA
+      10,                     //     10 ms delay
+    ST7735_PWCTR2 , 1      ,  //  9: Power control, 1 arg, no delay:
+      0x05,                   //     VGH = 14.7V, VGL = -7.35V
+    ST7735_PWCTR3 , 2      ,  // 10: Power control, 2 args, no delay:
+      0x01,                   //     Opamp current small
+      0x02,                   //     Boost frequency
+    ST7735_VMCTR1 , 2+DELAY,  // 11: Power control, 2 args + delay:
+      0x3C,                   //     VCOMH = 4V
+      0x38,                   //     VCOML = -1.1V
+      10,                     //     10 ms delay
+    ST7735_PWCTR6 , 2      ,  // 12: Power control, 2 args, no delay:
+      0x11, 0x15,
+    ST7735_GMCTRP1,16      ,  // 13: Magical unicorn dust, 16 args, no delay:
+      0x09, 0x16, 0x09, 0x20, //     (seriously though, not sure what
+      0x21, 0x1B, 0x13, 0x19, //      these config values represent)
+      0x17, 0x15, 0x1E, 0x2B,
+      0x04, 0x05, 0x02, 0x0E,
+    ST7735_GMCTRN1,16+DELAY,  // 14: Sparkles and rainbows, 16 args + delay:
+      0x0B, 0x14, 0x08, 0x1E, //     (ditto)
+      0x22, 0x1D, 0x18, 0x1E,
+      0x1B, 0x1A, 0x24, 0x2B,
+      0x06, 0x06, 0x02, 0x0F,
+      10,                     //     10 ms delay
+    ST7735_CASET  , 4      ,  // 15: Column addr set, 4 args, no delay:
+      0x00, 0x02,             //     XSTART = 2
+      0x00, 0x81,             //     XEND = 129
+    ST7735_RASET  , 4      ,  // 16: Row addr set, 4 args, no delay:
+      0x00, 0x02,             //     XSTART = 1
+      0x00, 0x81,             //     XEND = 160
+    ST7735_NORON  ,   DELAY,  // 17: Normal display on, no args, w/delay
+      10,                     //     10 ms delay
+    ST7735_DISPON ,   DELAY,  // 18: Main screen turn on, no args, w/delay
+      255};                   //     255 = 500 ms delay
+
+static const uint8_t
+  Rcmd1[] = {                 // Init for 7735R, part 1 (red or green tab)
+    15,                       // 15 commands in list:
+    ST7735_SWRESET,   DELAY,  //  1: Software reset, 0 args, w/delay
+      150,                    //     150 ms delay
+    ST7735_SLPOUT ,   DELAY,  //  2: Out of sleep mode, 0 args, w/delay
+      255,                    //     500 ms delay
+    ST7735_FRMCTR1, 3      ,  //  3: Frame rate ctrl - normal mode, 3 args:
+      0x01, 0x2C, 0x2D,       //     Rate = fosc/(1x2+40) * (LINE+2C+2D)
+    ST7735_FRMCTR2, 3      ,  //  4: Frame rate control - idle mode, 3 args:
+      0x01, 0x2C, 0x2D,       //     Rate = fosc/(1x2+40) * (LINE+2C+2D)
+    ST7735_FRMCTR3, 6      ,  //  5: Frame rate ctrl - partial mode, 6 args:
+      0x01, 0x2C, 0x2D,       //     Dot inversion mode
+      0x01, 0x2C, 0x2D,       //     Line inversion mode
+    ST7735_INVCTR , 1      ,  //  6: Display inversion ctrl, 1 arg, no delay:
+      0x07,                   //     No inversion
+    ST7735_PWCTR1 , 3      ,  //  7: Power control, 3 args, no delay:
+      0xA2,
+      0x02,                   //     -4.6V
+      0x84,                   //     AUTO mode
+    ST7735_PWCTR2 , 1      ,  //  8: Power control, 1 arg, no delay:
+      0xC5,                   //     VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD
+    ST7735_PWCTR3 , 2      ,  //  9: Power control, 2 args, no delay:
+      0x0A,                   //     Opamp current small
+      0x00,                   //     Boost frequency
+    ST7735_PWCTR4 , 2      ,  // 10: Power control, 2 args, no delay:
+      0x8A,                   //     BCLK/2, Opamp current small & Medium low
+      0x2A,  
+    ST7735_PWCTR5 , 2      ,  // 11: Power control, 2 args, no delay:
+      0x8A, 0xEE,
+    ST7735_VMCTR1 , 1      ,  // 12: Power control, 1 arg, no delay:
+      0x0E,
+    ST7735_INVOFF , 0      ,  // 13: Don't invert display, no args, no delay
+    ST7735_MADCTL , 1      ,  // 14: Memory access control (directions), 1 arg:
+      0xC8,                   //     row addr/col addr, bottom to top refresh
+    ST7735_COLMOD , 1      ,  // 15: set color mode, 1 arg, no delay:
+      0x05 };                 //     16-bit color
+
+static const uint8_t
+  Rcmd2green[] = {            // Init for 7735R, part 2 (green tab only)
+    2,                        //  2 commands in list:
+    ST7735_CASET  , 4      ,  //  1: Column addr set, 4 args, no delay:
+      0x00, 0x02,             //     XSTART = 0
+      0x00, 0x7F+0x02,        //     XEND = 127
+    ST7735_RASET  , 4      ,  //  2: Row addr set, 4 args, no delay:
+      0x00, 0x01,             //     XSTART = 0
+      0x00, 0x9F+0x01 };      //     XEND = 159
+
+static const uint8_t
+  Rcmd2red[] = {              // Init for 7735R, part 2 (red tab only)
+    2,                        //  2 commands in list:
+    ST7735_CASET  , 4      ,  //  1: Column addr set, 4 args, no delay:
+      0x00, 0x00,             //     XSTART = 0
+      0x00, 0x7F,             //     XEND = 127
+    ST7735_RASET  , 4      ,  //  2: Row addr set, 4 args, no delay:
+      0x00, 0x00,             //     XSTART = 0
+      0x00, 0x9F };           //     XEND = 159
+
+static const uint8_t
+  Rcmd2green144[] = {              // Init for 7735R, part 2 (green 1.44 tab)
+    2,                        //  2 commands in list:
+    ST7735_CASET  , 4      ,  //  1: Column addr set, 4 args, no delay:
+      0x00, 0x00,             //     XSTART = 0
+      0x00, 0x7F,             //     XEND = 127
+    ST7735_RASET  , 4      ,  //  2: Row addr set, 4 args, no delay:
+      0x00, 0x00,             //     XSTART = 0
+      0x00, 0x7F };           //     XEND = 127
+
+static const uint8_t
+  Rcmd3[] = {                 // Init for 7735R, part 3 (red or green tab)
+    4,                        //  4 commands in list:
+    ST7735_GMCTRP1, 16      , //  1: Magical unicorn dust, 16 args, no delay:
+      0x02, 0x1c, 0x07, 0x12,
+      0x37, 0x32, 0x29, 0x2d,
+      0x29, 0x25, 0x2B, 0x39,
+      0x00, 0x01, 0x03, 0x10,
+    ST7735_GMCTRN1, 16      , //  2: Sparkles and rainbows, 16 args, no delay:
+      0x03, 0x1d, 0x07, 0x06,
+      0x2E, 0x2C, 0x29, 0x2D,
+      0x2E, 0x2E, 0x37, 0x3F,
+      0x00, 0x00, 0x02, 0x10,
+    ST7735_NORON  ,    DELAY, //  3: Normal display on, no args, w/delay
+      10,                     //     10 ms delay
+    ST7735_DISPON ,    DELAY, //  4: Main screen turn on, no args w/delay
+      100 };                  //     100 ms delay
+
+
+
+
+/* Buffer used for transmission */
+static uint8_t aTxBuffer[4];
+
+#define PORT_HIGH           1
+#define PORT_LOW            0
+
+#define cs_set(sw)  digitalWrite(hlcd->cs_pin, sw)
+#define rs_set(sw)  digitalWrite(hlcd->rs_pin, sw)
+#define rst_set(sw) digitalWrite(hlcd->rst_pin, sw)
+#define cs2_set(sw) digitalWrite(hlcd->cs2_pin, sw)
+
+/*
+ *  LCDへのコマンド送信関数
+ */
+ER
+lcd_writecommand(LCD_Handler_t *hlcd, uint8_t c)
+{
+	ER ercd = E_OK;
+
+	if(hlcd->spi_lock != 0){
+		if((ercd = wai_sem(hlcd->spi_lock)) != E_OK)
+			return ercd;
+	}
+	rs_set(PORT_LOW);
+	cs_set(PORT_LOW);
+
+	aTxBuffer[0] = c;
+#if SPI_WAIT_TIME != 0
+	ercd = spi_transmit(hlcd->hspi, (uint8_t*)aTxBuffer, 1);
+#else
+	if((ercd = spi_transmit(hlcd->hspi, (uint8_t*)aTxBuffer, 1)) == E_OK){
+		ercd = spi_wait(hlcd->hspi, 100);
+	}
+#endif
+
+	cs_set(PORT_HIGH);
+	if(hlcd->spi_lock != 0)
+		sig_sem(hlcd->spi_lock);
+	return ercd;
+}
+
+/*
+ *  LCDへのデータ送信関数
+ */
+ER
+lcd_writedata(LCD_Handler_t *hlcd, uint8_t *p, uint32_t len)
+{
+	ER ercd = E_OK;
+
+	if(hlcd->spi_lock != 0){
+		if((ercd = wai_sem(hlcd->spi_lock)) != E_OK)
+			return ercd;
+	}
+	rs_set(PORT_HIGH);
+	cs_set(PORT_LOW);
+	sil_dly_nse(100);
+
+#if SPI_WAIT_TIME != 0
+	ercd = spi_transmit(hlcd->hspi, (uint8_t*)p, len);
+#else
+	if((ercd = spi_transmit(hlcd->hspi, (uint8_t*)p, len)) == E_OK){
+		ercd = spi_wait(hlcd->hspi, 100);
+	}
+#endif
+
+	sil_dly_nse(100);
+	cs_set(PORT_HIGH);
+	if(hlcd->spi_lock != 0)
+		sig_sem(hlcd->spi_lock);
+	return ercd;
+}
+
+/*
+ *  LCDへの２バイトデータ送信関数
+ */
+ER
+lcd_writedata2(LCD_Handler_t *hlcd, uint16_t c, int cnt)
+{
+	ER  ercd = E_OK;
+	int i;
+
+	if(cnt == 0)
+		return ercd;
+	if(hlcd->spi_lock != 0){
+		if((ercd = wai_sem(hlcd->spi_lock)) != E_OK)
+			return ercd;
+	}
+	rs_set(PORT_HIGH);
+	cs_set(PORT_LOW);
+	sil_dly_nse(100);
+	aTxBuffer[0] = c>>8;
+	aTxBuffer[1] = (uint8_t)c;
+	for(i = 0 ; i < cnt ; i++){
+		if((ercd = spi_transmit(hlcd->hspi, (uint8_t*)aTxBuffer, 2)) != E_OK){
+			break;
+		}
+#if SPI_WAIT_TIME == 0
+		if((ercd = spi_wait(hlcd->hspi, 100)) != E_OK){
+			break;
+		}
+#endif
+	}
+	sil_dly_nse(100);
+	cs_set(PORT_HIGH);
+	if(hlcd->spi_lock != 0)
+		sig_sem(hlcd->spi_lock);
+	return ercd;
+}
+
+/*
+ *  LCDへのRGBデータ送信関数
+ */
+ER
+lcd_writedata3(LCD_Handler_t *hlcd, uint8_t *pbmp, uint16_t width, uint16_t height)
+{
+	ER  ercd = E_OK;
+	int index, i;
+
+	if(width == 0 || height == 0)
+		return ercd;
+	if(hlcd->spi_lock != 0){
+		if((ercd = wai_sem(hlcd->spi_lock)) != E_OK)
+			return ercd;
+	}
+	rs_set(PORT_HIGH);
+	cs_set(PORT_LOW);
+	sil_dly_nse(100);
+	for(index=0; index < height; index++){
+		uint8_t *p = pbmp;
+		for (i = 0; i < width; i++){
+			aTxBuffer[0]  = (*p++) & 0xf8;
+			aTxBuffer[0] |= *p >> 5;
+			aTxBuffer[1]  = (*p++ << 3) & 0xE0;
+			aTxBuffer[1] |= (*p++ >> 3) & 0x1F;
+			if((ercd = spi_transmit(hlcd->hspi, (uint8_t*)aTxBuffer, 2)) != E_OK){
+				break;
+			}
+#if SPI_WAIT_TIME == 0
+			if((ercd = spi_wait(hlcd->hspi, 100)) != E_OK){
+				break;
+			}
+#endif
+		}
+		pbmp -= width*3;
+	}
+	sil_dly_nse(100);
+	cs_set(PORT_HIGH);
+	if(hlcd->spi_lock != 0)
+		sig_sem(hlcd->spi_lock);
+	return ercd;
+}
+
+/*
+ *  ST7735へのコマンドリスト送信
+ */
+static void
+Adafruit_ST7735_commandList(LCD_Handler_t *hlcd, const uint8_t *addr)
+{
+	uint8_t  numCommands, numArgs;
+	uint8_t  data[4];
+	uint16_t ms;
+
+	numCommands = *addr++;   // Number of commands to follow
+	while(numCommands--) {                 // For each command...
+		SVC_PERROR(lcd_writecommand(hlcd, *addr++)); //   Read, issue command
+		numArgs  = *addr++;    //   Number of args to follow
+		ms       = numArgs & DELAY;          //   If hibit set, delay follows args
+		numArgs &= ~DELAY;                   //   Mask out delay bit
+		while(numArgs--) {                   //   For each argument...
+			data[0] = *addr++;
+			SVC_PERROR(lcd_writedata(hlcd, data, 1));  //     Read, issue argument
+		}
+
+		if(ms) {
+			ms = *addr++; // Read post-command delay time (ms)
+			if(ms == 255) ms = 500;     // If 255, delay for 500 ms
+			dly_tsk(ms);
+		}
+	}
+}
+
+
+/*
+ *  ST7735B または ST7735RタイプのLEDの共通初期化関数
+ */
+static void
+Adafruit_ST7735_commonInit(LCD_Handler_t *hlcd, const uint8_t *cmdList)
+{
+	hlcd->colstart  = hlcd->rowstart = 0; // May be overridden in init func
+	hlcd->_width = ST7735_TFTWIDTH;
+	hlcd->_height = ST7735_TFTHEIGHT_18;
+
+	// toggle RST low to reset; CS low so it'll listen to us
+	cs_set(PORT_LOW);
+	rst_set(PORT_HIGH);
+	dly_tsk(500);
+	rst_set(PORT_LOW);
+	dly_tsk(500);
+	rst_set(PORT_HIGH);
+
+	if(cmdList) Adafruit_ST7735_commandList(hlcd, cmdList);
+}
+
+
+/*
+ *  表示ウィンドウ設定
+ */
+void
+lcd_setAddrWindow(LCD_Handler_t *hlcd, uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1)
+{
+	uint8_t  data[4];
+
+	SVC_PERROR(lcd_writecommand(hlcd, ST7735_CASET)); // Column addr set
+	data[0] = (uint8_t)((x0 + hlcd->colstart) >> 8);
+	data[1] = (uint8_t)(x0 + hlcd->colstart);		// XSTART
+	data[2] = (uint8_t)((x1 + hlcd->colstart) >> 8);
+	data[3] = (uint8_t)(x1 + hlcd->colstart);		// XEND
+	SVC_PERROR(lcd_writedata(hlcd, data, 4));
+
+	SVC_PERROR(lcd_writecommand(hlcd, ST7735_RASET)); // Row addr set
+	data[0] = (uint8_t)((y0 + hlcd->rowstart) >> 8);
+	data[1] = (uint8_t)(y0 + hlcd->rowstart);		// YSTART
+	data[2] = (uint8_t)((y1 + hlcd->rowstart) >> 8);
+	data[3] = (uint8_t)(y1 + hlcd->rowstart);		// YEND
+	SVC_PERROR(lcd_writedata(hlcd, data, 4));
+
+	SVC_PERROR(lcd_writecommand(hlcd, ST7735_RAMWR)); // write to RAM
+}
+
+/*
+ *  ST7735B screensの初期化関数
+ */
+void
+lcd_initB(LCD_Handler_t *hlcd)
+{
+	Adafruit_ST7735_commonInit(hlcd, Bcmd);
+}
+
+/*
+ *  ST7735R screens (green or red tabs)の初期化関数
+ */
+void
+lcd_initR(LCD_Handler_t *hlcd, uint8_t options)
+{
+	uint8_t data[4];
+
+	Adafruit_ST7735_commonInit(hlcd, Rcmd1);
+
+	if(options == INITR_GREENTAB){
+		Adafruit_ST7735_commandList(hlcd, Rcmd2green);
+		hlcd->colstart = 2;
+		hlcd->rowstart = 1;
+	}
+	else if(options == INITR_144GREENTAB){
+		hlcd->_height = ST7735_TFTHEIGHT_144;
+		Adafruit_ST7735_commandList(hlcd, Rcmd2green144);
+ 		hlcd->colstart = 2;
+		hlcd->rowstart = 3;
+	}
+	else{
+		// colstart, rowstart left at default '0' values
+		Adafruit_ST7735_commandList(hlcd, Rcmd2red);
+	}
+	Adafruit_ST7735_commandList(hlcd, Rcmd3);
+
+	// if black, change MADCTL color filter
+	if(options == INITR_BLACKTAB){
+		SVC_PERROR(lcd_writecommand(hlcd, ST7735_MADCTL));
+		data[0] = 0xC0;
+		SVC_PERROR(lcd_writedata(hlcd, data, 1));
+	}
+	syslog_2(LOG_NOTICE, "## width(%d) height(%d) ##", hlcd->_width, hlcd->_height);
+	hlcd->tabcolor = options;
+}
+
+/*
+ *  RECTANGLEのフィル描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: start X position
+ *  param3  y: start Y position
+ *  param4  w: width
+ *  param5  h: height
+ *  param6  color: color value
+ */
+void
+lcd_fillRect(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t w, int16_t h, color_t color)
+{
+	// rudimentary clipping (drawChar w/big text requires this)
+	if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
+	if((x + w - 1) >= hlcd->_width)  w = hlcd->_width  - x;
+	if((y + h - 1) >= hlcd->_height) h = hlcd->_height - y;
+
+	lcd_setAddrWindow(hlcd, x, y, x+w-1, y+h-1);
+	SVC_PERROR(lcd_writedata2(hlcd, color, h*w));
+}
+
+void
+lcd_pushColor(LCD_Handler_t *hlcd, color_t color)
+{
+	SVC_PERROR(lcd_writedata2(hlcd, color, 1));
+}
+
+/*
+ *  PIXEL描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: X position
+ *  param3  y: Y position
+ *  param4  color: color value
+ */
+void
+lcd_drawPixel(LCD_Handler_t *hlcd, int16_t x, int16_t y, color_t color)
+{
+	if((x < 0) ||(x >= hlcd->_width) || (y < 0) || (y >= hlcd->_height)) return;
+
+	lcd_setAddrWindow(hlcd, x, y, x, y);
+	SVC_PERROR(lcd_writedata2(hlcd, color, 1));
+}
+
+/*
+ *  垂直方向LINEの高速描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: start X position
+ *  param3  y: start Y position
+ *  param4  h: height
+ *  param5  color: color value
+ */
+void
+lcd_drawFastVLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t h, color_t color)
+{
+	// Rudimentary clipping
+	if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
+	if((y+h-1) >= hlcd->_height) h = hlcd->_height-y;
+	lcd_setAddrWindow(hlcd, x, y, x, y+h-1);
+	SVC_PERROR(lcd_writedata2(hlcd, color, h));
+}
+
+/*
+ *  水平方向LINEの高速描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: start X position
+ *  param3  y: start Y position
+ *  param4  w: width
+ *  param5  color: color value
+ */
+void lcd_drawFastHLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t w, color_t color)
+{
+	// Rudimentary clipping
+	if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
+	if((x+w-1) >= hlcd->_width)  w = hlcd->_width-x;
+	lcd_setAddrWindow(hlcd, x, y, x+w-1, y);
+	SVC_PERROR(lcd_writedata2(hlcd, color, w));
+}
+
+/*
+ *  DRAW IMAGE LINE描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: X position
+ *  param3  y: Y position
+ *  param4  w: width
+ *  param5  pcolor: color value
+ */
+void
+lcd_drawImageHLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, uint16_t w, color_t *pcolor)
+{
+	uint32_t i;
+
+	if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
+	if((x+w-1) >= hlcd->_width)  w = hlcd->_width-x;
+
+	lcd_setAddrWindow(hlcd, x, y, x+w-1, y);
+	for(i = 0 ; i < w ; i++, pcolor++)
+		SVC_PERROR(lcd_writedata2(hlcd, *pcolor, 1));
+}
+
+/*
+ *  BITMAP描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x0: Bmp X position in the LCD
+ *  param3  y0: Bmp Y position in the LCD
+ *  param4  pbmp: Pointer to Bmp picture address in the internal Flash
+ */
+void
+lcd_drawBitmap(LCD_Handler_t *hlcd, uint16_t x0, uint16_t y0, uint8_t *pbmp)
+{
+	uint32_t index = 0, width = 0, height = 0, bit_pixel = 0;
+	uint32_t input_color_mode = 0;
+
+	/* Get bitmap data address offset */
+	index = *(uint16_t *) (pbmp + 10);
+	index |= (*(uint16_t *) (pbmp + 12)) << 16;
+
+	/* Read bitmap width */
+	width = *(uint16_t *) (pbmp + 18);
+	width |= (*(uint16_t *) (pbmp + 20)) << 16;
+
+	/* Read bitmap height */
+	height = *(uint16_t *) (pbmp + 22);
+	height |= (*(uint16_t *) (pbmp + 24)) << 16;
+
+	/* Read bit/pixel */
+	bit_pixel = *(uint16_t *) (pbmp + 28);
+
+	/* Get the layer pixel format */
+	if ((bit_pixel/8) == 4){
+		input_color_mode = CM_ARGB8888;
+	}
+	else if ((bit_pixel/8) == 2){
+		input_color_mode = CM_RGB565;
+	}
+	else{
+		input_color_mode = CM_RGB888;
+	}
+
+	/* Bypass the bitmap header */
+	pbmp += (index + (width * (height - 1) * (bit_pixel/8)));  
+	syslog_4(LOG_NOTICE, "## input_color_mode(%d) width(%d) height(%d) bit_pixel(%d) ##", input_color_mode, width, height, bit_pixel);
+
+	lcd_setAddrWindow(hlcd, x0, y0, x0+width-1, y0+height-1);
+	lcd_writedata3(hlcd, pbmp, width, height);
+}
+
+/*
+ *  INVERT DISPLAY
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  i: invert value
+ */
+void
+lcd_invertDisplay(LCD_Handler_t *hlcd, bool_t i)
+{
+  SVC_PERROR(lcd_writecommand(hlcd, i ? ST7735_INVON : ST7735_INVOFF));
+}
+
+
+/*
+ *  スクリーンフィル
+ *  param1  pDrawProp: Pointer to Draw Prop
+ */
+void
+lcd_fillScreen(LCD_DrawProp_t *pDrawProp)
+{
+	lcd_fillRect(pDrawProp->hlcd, 0, 0,  pDrawProp->hlcd->_width, pDrawProp->hlcd->_height, pDrawProp->BackColor);
+}
+
+/*
+ *  RECTANGLE描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x: left X position
+ *  param3  y: top Y position
+ *  param4  w: width
+ *  param5  h: height
+ */
+void
+lcd_drawRect(LCD_DrawProp_t *pDrawProp, int16_t x, int16_t y, int16_t w, int16_t h)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	color_t color;
+
+	// rudimentary clipping (drawChar w/big text requires this)
+	if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
+	if((x + w - 1) >= hlcd->_width)  w = hlcd->_width  - x;
+	if((y + h - 1) >= hlcd->_height) h = hlcd->_height - y;
+
+	color = pDrawProp->TextColor;
+	lcd_drawFastVLine(hlcd, x, y, h, color);
+	lcd_drawFastHLine(hlcd, x, y+h-1, w, color);
+	lcd_drawFastVLine(hlcd, x+w-1, y, h, color);
+	lcd_drawFastHLine(hlcd, x, y, w, color);
+}
+
+/*
+ *  円描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x0: X position
+ *  param3  y0: Y position
+ *  param4  Radius: Circle radius
+ */
+void
+lcd_DrawCircle(LCD_DrawProp_t *pDrawProp, uint16_t x0, uint16_t y0, uint16_t Radius)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+ 	int32_t   decision;    /* Decision Variable */ 
+	uint32_t  current_x;   /* Current X Value */
+	uint32_t  current_y;   /* Current Y Value */
+
+	decision = 3 - (Radius << 1);
+	current_x = 0;
+	current_y = Radius;
+
+	while(current_x <= current_y){
+		lcd_drawPixel(hlcd, (x0 + current_x), (y0 - current_y), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 - current_x), (y0 - current_y), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 + current_y), (y0 - current_x), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 - current_y), (y0 - current_x), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 + current_x), (y0 + current_y), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 - current_x), (y0 + current_y), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 + current_y), (y0 + current_x), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 - current_y), (y0 + current_x), pDrawProp->TextColor);
+
+		if (decision < 0){
+			decision += (current_x << 2) + 6;
+		}
+		else{
+			decision += ((current_x - current_y) << 2) + 10;
+			current_y--;
+		}
+		current_x++;
+	}
+}
+
+/*
+ *  線描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x1: Point 1 X position
+ *  param3  y1: Point 1 Y position
+ *  param4  x2: Point 2 X position
+ *  param5  y2: Point 2 Y position
+ */
+void
+lcd_drawLine(LCD_DrawProp_t *pDrawProp, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0, 
+	yinc1 = 0, yinc2 = 0, den = 0, num = 0, num_add = 0, num_pixels = 0, 
+	curpixel = 0;
+
+	deltax = ABS(x2 - x1);		/* The difference between the x's */
+	deltay = ABS(y2 - y1);		/* The difference between the y's */
+	x = x1;						/* Start x off at the first pixel */
+	y = y1;						/* Start y off at the first pixel */
+
+	if(x2 >= x1){				/* The x-values are increasing */
+		xinc1 = 1;
+		xinc2 = 1;
+	}
+	else{						/* The x-values are decreasing */
+		xinc1 = -1;
+		xinc2 = -1;
+	}
+
+	if(y2 >= y1){				/* The y-values are increasing */
+		yinc1 = 1;
+		yinc2 = 1;
+	}
+	else{						/* The y-values are decreasing */
+		yinc1 = -1;
+		yinc2 = -1;
+	}
+
+	if(deltax >= deltay){		/* There is at least one x-value for every y-value */
+		xinc1 = 0;				/* Don't change the x when numerator >= denominator */
+		yinc2 = 0;				/* Don't change the y for every iteration */
+		den = deltax;
+		num = deltax / 2;
+		num_add = deltay;
+		num_pixels = deltax;	/* There are more x-values than y-values */
+	}
+	else{						/* There is at least one y-value for every x-value */
+		xinc2 = 0;				/* Don't change the x for every iteration */
+		yinc1 = 0;				/* Don't change the y when numerator >= denominator */
+		den = deltay;
+		num = deltay / 2;
+		num_add = deltax;
+		num_pixels = deltay;	/* There are more y-values than x-values */
+	}
+
+	for (curpixel = 0; curpixel <= num_pixels; curpixel++){
+		lcd_drawPixel(hlcd, x, y, pDrawProp->TextColor);	/* Draw the current pixel */
+		num += num_add;			/* Increase the numerator by the top of the fraction */
+		if(num >= den){			/* Check if numerator >= denominator */
+			num -= den;			/* Calculate the new numerator value */
+			x += xinc1;			/* Change the x as appropriate */
+			y += yinc1;			/* Change the y as appropriate */
+		}
+		x += xinc2;				/* Change the x as appropriate */
+		y += yinc2;				/* Change the y as appropriate */
+	}
+}
+
+/*
+ *  PLOY-LINE描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  Points: Pointer to the points array
+ *  param3  PointCount: Number of points
+ */
+void
+lcd_drawPolygon(LCD_DrawProp_t *pDrawProp, pPoint Points, uint16_t PointCount)
+{
+	int16_t x = 0, y = 0;
+
+	if(PointCount < 2){
+		return;
+	}
+
+	lcd_drawLine(pDrawProp, Points->X, Points->Y, (Points+PointCount-1)->X, (Points+PointCount-1)->Y);
+	while(--PointCount){
+		x = Points->X;
+		y = Points->Y;
+		Points++;
+		lcd_drawLine(pDrawProp, x, y, Points->X, Points->Y);
+	}
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_st7735/adafruit_st7735.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_st7735/adafruit_st7735.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_st7735/adafruit_st7735.h	(revision 453)
@@ -0,0 +1,221 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ *
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+ *
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ *
+ *  $Id$
+ */
+
+/*
+ *  Written by Limor Fried/Ladyada for Adafruit Industries.
+ *  MIT license, all text above must be included in any redistribution
+ *　http://opensource.org/licenses/mit-license.php 
+ */
+
+/*
+ *  ADAFRUIT ST7735 1.8",1.44"LCD制御プログラムのヘッダファイル
+ */
+
+#ifndef _ADAFRUIT_ST7735_H_
+#define _ADAFRUIT_ST7735_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include "device.h"
+#include "pinmode.h"
+#include "spi.h"
+
+/*
+ *  LCDカラーモード定義
+ */
+#define CM_ARGB8888         0x00000000			/* ARGB8888 color mode */
+#define CM_RGB888           0x00000001			/* RGB888 color mode */
+#define CM_RGB565           0x00000002			/* RGB565 color mode */
+
+// some flags for initR() :(
+#define INITR_GREENTAB 0x0
+#define INITR_REDTAB   0x1
+#define INITR_BLACKTAB   0x2
+
+#define INITR_18GREENTAB    INITR_GREENTAB
+#define INITR_18REDTAB      INITR_REDTAB
+#define INITR_18BLACKTAB    INITR_BLACKTAB
+#define INITR_144GREENTAB   0x1
+
+#define ST7735_TFTWIDTH  128
+// for 1.44" display
+#define ST7735_TFTHEIGHT_144 128
+// for 1.8" display
+#define ST7735_TFTHEIGHT_18  160
+
+#define ST7735_NOP     0x00
+#define ST7735_SWRESET 0x01
+#define ST7735_RDDID   0x04
+#define ST7735_RDDST   0x09
+
+#define ST7735_SLPIN   0x10
+#define ST7735_SLPOUT  0x11
+#define ST7735_PTLON   0x12
+#define ST7735_NORON   0x13
+
+#define ST7735_INVOFF  0x20
+#define ST7735_INVON   0x21
+#define ST7735_DISPOFF 0x28
+#define ST7735_DISPON  0x29
+#define ST7735_CASET   0x2A
+#define ST7735_RASET   0x2B
+#define ST7735_RAMWR   0x2C
+#define ST7735_RAMRD   0x2E
+
+#define ST7735_PTLAR   0x30
+#define ST7735_COLMOD  0x3A
+#define ST7735_MADCTL  0x36
+
+#define ST7735_FRMCTR1 0xB1
+#define ST7735_FRMCTR2 0xB2
+#define ST7735_FRMCTR3 0xB3
+#define ST7735_INVCTR  0xB4
+#define ST7735_DISSET5 0xB6
+
+#define ST7735_PWCTR1  0xC0
+#define ST7735_PWCTR2  0xC1
+#define ST7735_PWCTR3  0xC2
+#define ST7735_PWCTR4  0xC3
+#define ST7735_PWCTR5  0xC4
+#define ST7735_VMCTR1  0xC5
+
+#define ST7735_RDID1   0xDA
+#define ST7735_RDID2   0xDB
+#define ST7735_RDID3   0xDC
+#define ST7735_RDID4   0xDD
+
+#define ST7735_PWCTR6  0xFC
+
+#define ST7735_GMCTRP1 0xE0
+#define ST7735_GMCTRN1 0xE1
+
+// Color definitions
+#define	ST7735_BLACK   0x0000
+#define	ST7735_BLUE    0x001F
+#define	ST7735_RED     0xF800
+#define	ST7735_GREEN   0x07E0
+#define ST7735_CYAN    0x07FF
+#define ST7735_MAGENTA 0xF81F
+#define ST7735_YELLOW  0xFFE0
+#define ST7735_WHITE   0xFFFF
+
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  カラーの属性を定義
+ */
+typedef uint16_t   color_t;
+
+/*
+ *  LCDハンドラ構造体定義
+ */
+typedef struct
+{
+	SPI_Handle_t            *hspi;		/* spiハンドラ */
+	uint16_t                _width;		/* 幅ピクセル数 */
+	uint16_t				_height;	/* 高さピクセル数 */
+	uint8_t                 colstart;
+	uint8_t                 rowstart;
+	uint8_t                 tabcolor;	/* some displays need this changed */
+	uint8_t                 dummy;
+	ID                      spi_lock;
+	uint8_t                 cs_pin;
+	uint8_t                 rs_pin;
+	uint8_t                 rst_pin;
+	uint8_t                 cs2_pin;
+}LCD_Handler_t;
+
+/*
+ *  描画構造体
+ */
+typedef struct
+{
+	LCD_Handler_t           *hlcd;
+	color_t                 TextColor;
+	color_t                 BackColor;
+	void                    *pFont;
+}LCD_DrawProp_t;
+
+typedef struct
+{
+	int16_t X;
+	int16_t Y;
+}Point, * pPoint;
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+extern ER lcd_writecommand(LCD_Handler_t *hlcd, uint8_t c);
+extern ER lcd_writedata(LCD_Handler_t *hlcd, uint8_t *p, uint32_t len);
+extern ER lcd_writedata2(LCD_Handler_t *hlcd, uint16_t c, int cnt);
+extern ER lcd_writedata3(LCD_Handler_t *hlcd, uint8_t *pbmp, uint16_t width, uint16_t height);
+
+extern void lcd_initB(LCD_Handler_t *hlcd);
+extern void lcd_initR(LCD_Handler_t *hlcd, uint8_t options);
+extern void lcd_setAddrWindow(LCD_Handler_t *hlcd, uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1);
+extern void lcd_fillRect(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t w, int16_t h, color_t color);
+extern void lcd_pushColor(LCD_Handler_t *hlcd, color_t color);
+extern void lcd_drawPixel(LCD_Handler_t *hlcd, int16_t x, int16_t y, color_t color);
+extern void lcd_drawFastVLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t h, color_t color);
+extern void lcd_drawFastHLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t w, color_t color);
+extern void lcd_drawImageHLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, uint16_t w, color_t *pcolor);
+extern void lcd_drawBitmap(LCD_Handler_t *hlcd, uint16_t x0, uint16_t y0, uint8_t *pbmp);
+extern void lcd_invertDisplay(LCD_Handler_t *hlcd, bool_t i);
+
+extern void lcd_fillScreen(LCD_DrawProp_t *pDrawProp);
+extern void lcd_drawRect(LCD_DrawProp_t *pDrawProp, int16_t x, int16_t y, int16_t w, int16_t h);
+extern void lcd_DrawCircle(LCD_DrawProp_t *pDrawProp, uint16_t x0, uint16_t y0, uint16_t Radius);
+extern void lcd_drawLine(LCD_DrawProp_t *pDrawProp, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
+extern void lcd_drawPolygon(LCD_DrawProp_t *pDrawProp, pPoint Points, uint16_t PointCount);
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _ADAFRUIT_ST7735_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_st7735/glcd_core.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_st7735/glcd_core.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_st7735/glcd_core.h	(revision 453)
@@ -0,0 +1,45 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+#ifndef _LCD_CORE_H_
+#define _LCD_CORE_H_
+
+#include "adafruit_st7735.h"
+
+#endif /* _LCD_CORE_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_st7789/Makefile.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_st7789/Makefile.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_st7789/Makefile.config	(revision 453)
@@ -0,0 +1,49 @@
+#
+#   TOPPERS BASE PLATFORM MIDDLEWARE
+#
+#   Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+ 
+#
+#  Makefile のプロセッサ依存 (adafruit st7789:LCD用)
+#
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/gdic/adafruit_st7789
+
+#
+#  ADAFRUIT ST7735 LCD DRIVER(GDIC)に関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR):$(SRCDIR)/gdic/adafruit_st7789
+SYSSVC_COBJS := $(SYSSVC_COBJS) adafruit_st7789.o
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_st7789/adafruit_st7789.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_st7789/adafruit_st7789.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_st7789/adafruit_st7789.c	(revision 453)
@@ -0,0 +1,754 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2012 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2020 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *  Written by Limor Fried/Ladyada for Adafruit Industries.
+ *  MIT license, all text above must be included in any redistribution
+ *　http://opensource.org/licenses/mit-license.php 
+ */
+
+/* 
+ *  ADAFRUIT ST7789 LCD制御プログラムの本体
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <target_syssvc.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#include "device.h"
+#include "adafruit_st7789.h"
+
+/*
+ *  サービスコールのエラーのログ出力
+ */
+Inline void
+svc_perror(const char *file, int_t line, const char *expr, ER ercd)
+{
+	if (ercd < 0) {
+		t_perror(LOG_ERROR, file, line, expr, ercd);
+	}
+}
+
+#define	SVC_PERROR(expr)	svc_perror(__FILE__, __LINE__, #expr, (expr))
+#define ABS(X)  ((X) > 0 ? (X) : -(X))
+
+
+// Rather than a bazillion writecommand() and writedata() calls, screen
+// initialization commands and arguments are organized in these tables
+// stored in PROGMEM.  The table may look bulky, but that's mostly the
+// formatting -- storage-wise this is hundreds of bytes more compact
+// than the equivalent code.  Companion function follows.
+#define DELAY 0x80
+static const uint8_t
+  Gcmd[] = {                  // Initialization commands for 7789 screens
+    9,                        // 9 commands in list:
+    ST7789_SWRESET,   DELAY,  //  1: Software reset, no args, w/delay
+      150,                    //     150 ms delay
+    ST7789_SLPOUT ,   DELAY,  //  2: Out of sleep mode, no args, w/delay
+      10,                     //     10 ms delay
+    ST7789_COLMOD , 1+DELAY,  //  3: Set color mode, 1 arg + delay:
+      0x55,                   //     16-bit color
+      10,                     //     10 ms delay
+    ST7789_MADCTL , 1,        //  4: Mem access ctrl (directions), 1 arg:
+      0x08,                   //     Row/col addr, bottom-top refresh
+    ST7789_CASET  , 4,        //  5: Column addr set, 4 args, no delay:
+      0x00,                   //
+      0,                      //     XSTART = 0
+      0,                      //
+      240,                    //     XEND = 240
+    ST7789_RASET  , 4,        //  6: Row addr set, 4 args, no delay:
+      0x00,
+      0,                      //     YSTART = 0
+      320>>8,
+      320&0xFF,               //     YEND = 320
+    ST7789_INVON  ,   DELAY,  //  7: hack
+      10,                     //     10 ms delay
+    ST7789_NORON  ,   DELAY,  //  8: Normal display on, no args, w/delay
+      10,                     //     10 ms delay
+    ST7789_DISPON ,   DELAY,  //  9: Main screen turn on, no args, delay
+      10 };                   //    10 ms delay
+
+
+
+
+/* Buffer used for transmission */
+static uint8_t aTxBuffer[4];
+
+#define PORT_HIGH           1
+#define PORT_LOW            0
+
+#define cs_set(sw)  digitalWrite(hlcd->cs_pin, sw)
+#define rs_set(sw)  digitalWrite(hlcd->rs_pin, sw)
+#define rst_set(sw) digitalWrite(hlcd->rst_pin, sw)
+#define cs2_set(sw) digitalWrite(hlcd->cs2_pin, sw)
+
+/*
+ *  LCDへのコマンド送信関数
+ */
+ER
+lcd_writecommand(LCD_Handler_t *hlcd, uint8_t c)
+{
+	ER ercd = E_OK;
+
+	if(hlcd->spi_lock != 0){
+		if((ercd = wai_sem(hlcd->spi_lock)) != E_OK)
+			return ercd;
+	}
+	rs_set(PORT_LOW);
+	cs_set(PORT_LOW);
+
+	aTxBuffer[0] = c;
+#if SPI_WAIT_TIME != 0
+	ercd = spi_transmit(hlcd->hspi, (uint8_t*)aTxBuffer, 1);
+#else
+	if((ercd = spi_transmit(hlcd->hspi, (uint8_t*)aTxBuffer, 1)) == E_OK){
+		ercd = spi_wait(hlcd->hspi, 100);
+	}
+#endif
+
+	cs_set(PORT_HIGH);
+	if(hlcd->spi_lock != 0)
+		sig_sem(hlcd->spi_lock);
+	return ercd;
+}
+
+/*
+ *  LCDへのデータ送信関数
+ */
+ER
+lcd_writedata(LCD_Handler_t *hlcd, uint8_t *p, uint32_t len)
+{
+	ER ercd = E_OK;
+
+	if(hlcd->spi_lock != 0){
+		if((ercd = wai_sem(hlcd->spi_lock)) != E_OK)
+			return ercd;
+	}
+	rs_set(PORT_HIGH);
+	cs_set(PORT_LOW);
+	sil_dly_nse(100);
+
+#if SPI_WAIT_TIME != 0
+	ercd = spi_transmit(hlcd->hspi, (uint8_t*)p, len);
+#else
+	if((ercd = spi_transmit(hlcd->hspi, (uint8_t*)p, len)) == E_OK){
+		ercd = spi_wait(hlcd->hspi, 100);
+	}
+#endif
+
+	sil_dly_nse(100);
+	cs_set(PORT_HIGH);
+	if(hlcd->spi_lock != 0)
+		sig_sem(hlcd->spi_lock);
+	return ercd;
+}
+
+/*
+ *  LCDへの２バイトデータ送信関数
+ */
+ER
+lcd_writedata2(LCD_Handler_t *hlcd, uint16_t c, int cnt)
+{
+	ER  ercd = E_OK;
+	int i;
+
+	if(cnt == 0)
+		return ercd;
+	if(hlcd->spi_lock != 0){
+		if((ercd = wai_sem(hlcd->spi_lock)) != E_OK)
+			return ercd;
+	}
+	rs_set(PORT_HIGH);
+	cs_set(PORT_LOW);
+	sil_dly_nse(100);
+	aTxBuffer[0] = c>>8;
+	aTxBuffer[1] = (uint8_t)c;
+	for(i = 0 ; i < cnt ; i++){
+		if((ercd = spi_transmit(hlcd->hspi, (uint8_t*)aTxBuffer, 2)) != E_OK){
+			break;
+		}
+#if SPI_WAIT_TIME == 0
+		if((ercd = spi_wait(hlcd->hspi, 100)) != E_OK){
+			break;
+		}
+#endif
+	}
+	sil_dly_nse(100);
+	cs_set(PORT_HIGH);
+	if(hlcd->spi_lock != 0)
+		sig_sem(hlcd->spi_lock);
+	return ercd;
+}
+
+/*
+ *  LCDへのRGBデータ送信関数
+ */
+ER
+lcd_writedata3(LCD_Handler_t *hlcd, uint8_t *pbmp, uint16_t width, uint16_t height)
+{
+	ER  ercd = E_OK;
+	int index, i;
+
+	if(width == 0 || height == 0)
+		return ercd;
+	if(hlcd->spi_lock != 0){
+		if((ercd = wai_sem(hlcd->spi_lock)) != E_OK)
+			return ercd;
+	}
+	rs_set(PORT_HIGH);
+	cs_set(PORT_LOW);
+	sil_dly_nse(100);
+	for(index=0; index < height; index++){
+		uint8_t *p = pbmp;
+		for (i = 0; i < width; i++){
+			aTxBuffer[0]  = (*p++) & 0xf8;
+			aTxBuffer[0] |= *p >> 5;
+			aTxBuffer[1]  = (*p++ << 3) & 0xE0;
+			aTxBuffer[1] |= (*p++ >> 3) & 0x1F;
+			if((ercd = spi_transmit(hlcd->hspi, (uint8_t*)aTxBuffer, 2)) != E_OK){
+				break;
+			}
+#if SPI_WAIT_TIME == 0
+			if((ercd = spi_wait(hlcd->hspi, 100)) != E_OK){
+				break;
+			}
+#endif
+		}
+		pbmp -= width*3;
+	}
+	sil_dly_nse(100);
+	cs_set(PORT_HIGH);
+	if(hlcd->spi_lock != 0)
+		sig_sem(hlcd->spi_lock);
+	return ercd;
+}
+
+/*
+ *  ST7789へのコマンドリスト送信
+ */
+static void
+displayInit(LCD_Handler_t *hlcd, const uint8_t *addr)
+{
+	uint8_t  numCommands, numArgs;
+	uint8_t  data[4];
+	uint16_t ms;
+
+	numCommands = *addr++;   // Number of commands to follow
+	while(numCommands--) {                 // For each command...
+		SVC_PERROR(lcd_writecommand(hlcd, *addr++)); //   Read, issue command
+		numArgs  = *addr++;    //   Number of args to follow
+		ms       = numArgs & DELAY;          //   If hibit set, delay follows args
+		numArgs &= ~DELAY;                   //   Mask out delay bit
+		while(numArgs--) {                   //   For each argument...
+			data[0] = *addr++;
+			SVC_PERROR(lcd_writedata(hlcd, data, 1));  //     Read, issue argument
+		}
+
+		if(ms) {
+			ms = *addr++; // Read post-command delay time (ms)
+			if(ms == 255) ms = 500;     // If 255, delay for 500 ms
+			dly_tsk(ms);
+		}
+	}
+}
+
+
+/*
+ *  ST7735B または ST7735RタイプのLEDの共通初期化関数
+ */
+static void
+commonInit(LCD_Handler_t *hlcd, uint16_t width, uint16_t height)
+{
+	hlcd->colstart  = hlcd->rowstart = 0; // May be overridden in init func
+	hlcd->lcd_width = width;
+	hlcd->lcd_height = height;
+	if(width == 240 && height == 240){	/* 1.3" and 1.54 displays */
+		hlcd->lcd_colstart = 0;
+		hlcd->lcd_rowstart = 80;
+	}
+	else if(width == 135 && height == 240){	/*1.13" display */
+		hlcd->lcd_colstart = 53;
+		hlcd->lcd_rowstart = 40;
+	}
+	else{
+		hlcd->lcd_colstart = 0;
+		hlcd->lcd_rowstart = 0;
+	}
+
+	// toggle RST low to reset; CS low so it'll listen to us
+	cs_set(PORT_LOW);
+	rst_set(PORT_HIGH);
+	dly_tsk(500);
+	rst_set(PORT_LOW);
+	dly_tsk(500);
+	rst_set(PORT_HIGH);
+}
+
+/*
+ *  表示ウィンドウ設定
+ */
+void
+lcd_setAddrWindow(LCD_Handler_t *hlcd, uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1)
+{
+	uint8_t  data[4];
+
+	SVC_PERROR(lcd_writecommand(hlcd, ST7789_CASET)); // Column addr set
+	data[0] = (uint8_t)((x0 + hlcd->colstart) >> 8);
+	data[1] = (uint8_t)(x0 + hlcd->colstart);		// XSTART
+	data[2] = (uint8_t)((x1 + hlcd->colstart) >> 8);
+	data[3] = (uint8_t)(x1 + hlcd->colstart);		// XEND
+	SVC_PERROR(lcd_writedata(hlcd, data, 4));
+
+	SVC_PERROR(lcd_writecommand(hlcd, ST7789_RASET)); // Row addr set
+	data[0] = (uint8_t)((y0 + hlcd->rowstart) >> 8);
+	data[1] = (uint8_t)(y0 + hlcd->rowstart);		// YSTART
+	data[2] = (uint8_t)((y1 + hlcd->rowstart) >> 8);
+	data[3] = (uint8_t)(y1 + hlcd->rowstart);		// YEND
+	SVC_PERROR(lcd_writedata(hlcd, data, 4));
+
+	SVC_PERROR(lcd_writecommand(hlcd, ST7789_RAMWR)); // write to RAM
+}
+
+/*
+ *  オリエンテーション設定
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  m: orientation value(0-3)
+ */
+void
+lcd_setRotation(LCD_Handler_t *hlcd, uint8_t m)
+{
+	uint8_t madctl[4];
+
+	hlcd->rotation = m & 3; // can't be higher than 3
+	madctl[0] = 0;
+
+	switch(hlcd->rotation){
+	case 0:
+		madctl[0]  = ST7789_MADCTL_MX | ST7789_MADCTL_MY | ST7789_MADCTL_RGB;
+		hlcd->colstart = hlcd->lcd_colstart;
+		hlcd->rowstart = hlcd->lcd_rowstart;
+		hlcd->_width  = hlcd->lcd_width;
+		hlcd->_height = hlcd->lcd_height;
+		break;
+	case 1:
+		madctl[0]  = ST7789_MADCTL_MY | ST7789_MADCTL_MV | ST7789_MADCTL_RGB;
+		hlcd->colstart = hlcd->lcd_rowstart;
+		hlcd->rowstart = hlcd->lcd_colstart;
+		hlcd->_height = hlcd->lcd_width;
+		hlcd->_width  = hlcd->lcd_height;
+		break;
+	case 2:
+		madctl[0]  = ST7789_MADCTL_RGB;
+		if(hlcd->lcd_width == 135 && hlcd->lcd_height == 240){
+			hlcd->colstart = hlcd->lcd_colstart-1;
+			hlcd->rowstart = hlcd->lcd_rowstart;
+		}
+		else{
+			hlcd->colstart = 0;
+			hlcd->rowstart = 0;
+		}
+		hlcd->_width  = hlcd->lcd_width;
+		hlcd->_height = hlcd->lcd_height;
+		break;
+	case 3:
+		madctl[0]  = ST7789_MADCTL_MX | ST7789_MADCTL_MV | ST7789_MADCTL_RGB;
+		if(hlcd->lcd_width == 135 && hlcd->lcd_height == 240){
+			hlcd->colstart = hlcd->lcd_rowstart;
+			hlcd->rowstart = hlcd->lcd_colstart;
+		}
+		else{
+			hlcd->colstart = 0;
+			hlcd->rowstart = 0;
+		}
+		hlcd->_height = hlcd->lcd_width;
+		hlcd->_width  = hlcd->lcd_height;
+		break;
+	}
+	SVC_PERROR(lcd_writecommand(hlcd, ST7789_MADCTL));
+	SVC_PERROR(lcd_writedata(hlcd, madctl, 1));
+}
+
+/*
+ *  ST7789 screensの初期化関数
+ */
+void
+lcd_init(LCD_Handler_t *hlcd, uint16_t width, uint16_t height)
+{
+	commonInit(hlcd, width, height);
+
+	displayInit(hlcd, Gcmd);
+	lcd_setRotation(hlcd, hlcd->rotation);
+	syslog_2(LOG_NOTICE, "## width(%d) height(%d) ##", hlcd->_width, hlcd->_height);
+}
+
+/*
+ *  RECTANGLEのフィル描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: start X position
+ *  param3  y: start Y position
+ *  param4  w: width
+ *  param5  h: height
+ *  param6  color: color value
+ */
+void
+lcd_fillRect(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t w, int16_t h, color_t color)
+{
+	// rudimentary clipping (drawChar w/big text requires this)
+	if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
+	if((x + w - 1) >= hlcd->_width)  w = hlcd->_width  - x;
+	if((y + h - 1) >= hlcd->_height) h = hlcd->_height - y;
+
+	lcd_setAddrWindow(hlcd, x, y, x+w-1, y+h-1);
+	SVC_PERROR(lcd_writedata2(hlcd, color, h*w));
+}
+
+void
+lcd_pushColor(LCD_Handler_t *hlcd, color_t color)
+{
+	SVC_PERROR(lcd_writedata2(hlcd, color, 1));
+}
+
+/*
+ *  PIXEL描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: X position
+ *  param3  y: Y position
+ *  param4  color: color value
+ */
+void
+lcd_drawPixel(LCD_Handler_t *hlcd, int16_t x, int16_t y, color_t color)
+{
+	if((x < 0) ||(x >= hlcd->_width) || (y < 0) || (y >= hlcd->_height)) return;
+
+	lcd_setAddrWindow(hlcd, x, y, x, y);
+	SVC_PERROR(lcd_writedata2(hlcd, color, 1));
+}
+
+/*
+ *  垂直方向LINEの高速描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: start X position
+ *  param3  y: start Y position
+ *  param4  h: height
+ *  param5  color: color value
+ */
+void
+lcd_drawFastVLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t h, color_t color)
+{
+	// Rudimentary clipping
+	if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
+	if((y+h-1) >= hlcd->_height) h = hlcd->_height-y;
+	lcd_setAddrWindow(hlcd, x, y, x, y+h-1);
+	SVC_PERROR(lcd_writedata2(hlcd, color, h));
+}
+
+/*
+ *  水平方向LINEの高速描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: start X position
+ *  param3  y: start Y position
+ *  param4  w: width
+ *  param5  color: color value
+ */
+void lcd_drawFastHLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t w, color_t color)
+{
+	// Rudimentary clipping
+	if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
+	if((x+w-1) >= hlcd->_width)  w = hlcd->_width-x;
+	lcd_setAddrWindow(hlcd, x, y, x+w-1, y);
+	SVC_PERROR(lcd_writedata2(hlcd, color, w));
+}
+
+/*
+ *  DRAW IMAGE LINE描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: X position
+ *  param3  y: Y position
+ *  param4  w: width
+ *  param5  pcolor: color value
+ */
+void
+lcd_drawImageHLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, uint16_t w, color_t *pcolor)
+{
+	uint32_t i;
+
+	if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
+	if((x+w-1) >= hlcd->_width)  w = hlcd->_width-x;
+
+	lcd_setAddrWindow(hlcd, x, y, x+w-1, y);
+	for(i = 0 ; i < w ; i++, pcolor++)
+		SVC_PERROR(lcd_writedata2(hlcd, *pcolor, 1));
+}
+
+/*
+ *  BITMAP描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x0: Bmp X position in the LCD
+ *  param3  y0: Bmp Y position in the LCD
+ *  param4  pbmp: Pointer to Bmp picture address in the internal Flash
+ */
+void
+lcd_drawBitmap(LCD_Handler_t *hlcd, uint16_t x0, uint16_t y0, uint8_t *pbmp)
+{
+	uint32_t index = 0, width = 0, height = 0, bit_pixel = 0;
+	uint32_t input_color_mode = 0;
+
+	/* Get bitmap data address offset */
+	index = *(uint16_t *) (pbmp + 10);
+	index |= (*(uint16_t *) (pbmp + 12)) << 16;
+
+	/* Read bitmap width */
+	width = *(uint16_t *) (pbmp + 18);
+	width |= (*(uint16_t *) (pbmp + 20)) << 16;
+
+	/* Read bitmap height */
+	height = *(uint16_t *) (pbmp + 22);
+	height |= (*(uint16_t *) (pbmp + 24)) << 16;
+
+	/* Read bit/pixel */
+	bit_pixel = *(uint16_t *) (pbmp + 28);
+
+	/* Get the layer pixel format */
+	if ((bit_pixel/8) == 4){
+		input_color_mode = CM_ARGB8888;
+	}
+	else if ((bit_pixel/8) == 2){
+		input_color_mode = CM_RGB565;
+	}
+	else{
+		input_color_mode = CM_RGB888;
+	}
+
+	/* Bypass the bitmap header */
+	pbmp += (index + (width * (height - 1) * (bit_pixel/8)));  
+	syslog_4(LOG_NOTICE, "## input_color_mode(%d) width(%d) height(%d) bit_pixel(%d) ##", input_color_mode, width, height, bit_pixel);
+
+	lcd_setAddrWindow(hlcd, x0, y0, x0+width-1, y0+height-1);
+	lcd_writedata3(hlcd, pbmp, width, height);
+}
+
+/*
+ *  INVERT DISPLAY
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  i: invert value
+ */
+void
+lcd_invertDisplay(LCD_Handler_t *hlcd, bool_t i)
+{
+  SVC_PERROR(lcd_writecommand(hlcd, i ? ST7789_INVOFF : ST7789_INVON));
+}
+
+
+/*
+ *  スクリーンフィル
+ *  param1  pDrawProp: Pointer to Draw Prop
+ */
+void
+lcd_fillScreen(LCD_DrawProp_t *pDrawProp)
+{
+	lcd_fillRect(pDrawProp->hlcd, 0, 0,  pDrawProp->hlcd->_width, pDrawProp->hlcd->_height, pDrawProp->BackColor);
+}
+
+/*
+ *  RECTANGLE描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x: left X position
+ *  param3  y: top Y position
+ *  param4  w: width
+ *  param5  h: height
+ */
+void
+lcd_drawRect(LCD_DrawProp_t *pDrawProp, int16_t x, int16_t y, int16_t w, int16_t h)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	color_t color;
+
+	// rudimentary clipping (drawChar w/big text requires this)
+	if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
+	if((x + w - 1) >= hlcd->_width)  w = hlcd->_width  - x;
+	if((y + h - 1) >= hlcd->_height) h = hlcd->_height - y;
+
+	color = pDrawProp->TextColor;
+	lcd_drawFastVLine(hlcd, x, y, h, color);
+	lcd_drawFastHLine(hlcd, x, y+h-1, w, color);
+	lcd_drawFastVLine(hlcd, x+w-1, y, h, color);
+	lcd_drawFastHLine(hlcd, x, y, w, color);
+}
+
+/*
+ *  円描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x0: X position
+ *  param3  y0: Y position
+ *  param4  Radius: Circle radius
+ */
+void
+lcd_DrawCircle(LCD_DrawProp_t *pDrawProp, uint16_t x0, uint16_t y0, uint16_t Radius)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+ 	int32_t   decision;    /* Decision Variable */ 
+	uint32_t  current_x;   /* Current X Value */
+	uint32_t  current_y;   /* Current Y Value */
+
+	decision = 3 - (Radius << 1);
+	current_x = 0;
+	current_y = Radius;
+
+	while(current_x <= current_y){
+		lcd_drawPixel(hlcd, (x0 + current_x), (y0 - current_y), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 - current_x), (y0 - current_y), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 + current_y), (y0 - current_x), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 - current_y), (y0 - current_x), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 + current_x), (y0 + current_y), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 - current_x), (y0 + current_y), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 + current_y), (y0 + current_x), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 - current_y), (y0 + current_x), pDrawProp->TextColor);
+
+		if (decision < 0){
+			decision += (current_x << 2) + 6;
+		}
+		else{
+			decision += ((current_x - current_y) << 2) + 10;
+			current_y--;
+		}
+		current_x++;
+	}
+}
+
+/*
+ *  線描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x1: Point 1 X position
+ *  param3  y1: Point 1 Y position
+ *  param4  x2: Point 2 X position
+ *  param5  y2: Point 2 Y position
+ */
+void
+lcd_drawLine(LCD_DrawProp_t *pDrawProp, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0, 
+	yinc1 = 0, yinc2 = 0, den = 0, num = 0, num_add = 0, num_pixels = 0, 
+	curpixel = 0;
+
+	deltax = ABS(x2 - x1);		/* The difference between the x's */
+	deltay = ABS(y2 - y1);		/* The difference between the y's */
+	x = x1;						/* Start x off at the first pixel */
+	y = y1;						/* Start y off at the first pixel */
+
+	if(x2 >= x1){				/* The x-values are increasing */
+		xinc1 = 1;
+		xinc2 = 1;
+	}
+	else{						/* The x-values are decreasing */
+		xinc1 = -1;
+		xinc2 = -1;
+	}
+
+	if(y2 >= y1){				/* The y-values are increasing */
+		yinc1 = 1;
+		yinc2 = 1;
+	}
+	else{						/* The y-values are decreasing */
+		yinc1 = -1;
+		yinc2 = -1;
+	}
+
+	if(deltax >= deltay){		/* There is at least one x-value for every y-value */
+		xinc1 = 0;				/* Don't change the x when numerator >= denominator */
+		yinc2 = 0;				/* Don't change the y for every iteration */
+		den = deltax;
+		num = deltax / 2;
+		num_add = deltay;
+		num_pixels = deltax;	/* There are more x-values than y-values */
+	}
+	else{						/* There is at least one y-value for every x-value */
+		xinc2 = 0;				/* Don't change the x for every iteration */
+		yinc1 = 0;				/* Don't change the y when numerator >= denominator */
+		den = deltay;
+		num = deltay / 2;
+		num_add = deltax;
+		num_pixels = deltay;	/* There are more y-values than x-values */
+	}
+
+	for (curpixel = 0; curpixel <= num_pixels; curpixel++){
+		lcd_drawPixel(hlcd, x, y, pDrawProp->TextColor);	/* Draw the current pixel */
+		num += num_add;			/* Increase the numerator by the top of the fraction */
+		if(num >= den){			/* Check if numerator >= denominator */
+			num -= den;			/* Calculate the new numerator value */
+			x += xinc1;			/* Change the x as appropriate */
+			y += yinc1;			/* Change the y as appropriate */
+		}
+		x += xinc2;				/* Change the x as appropriate */
+		y += yinc2;				/* Change the y as appropriate */
+	}
+}
+
+/*
+ *  PLOY-LINE描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  Points: Pointer to the points array
+ *  param3  PointCount: Number of points
+ */
+void
+lcd_drawPolygon(LCD_DrawProp_t *pDrawProp, pPoint Points, uint16_t PointCount)
+{
+	int16_t x = 0, y = 0;
+
+	if(PointCount < 2){
+		return;
+	}
+
+	lcd_drawLine(pDrawProp, Points->X, Points->Y, (Points+PointCount-1)->X, (Points+PointCount-1)->Y);
+	while(--PointCount){
+		x = Points->X;
+		y = Points->Y;
+		Points++;
+		lcd_drawLine(pDrawProp, x, y, Points->X, Points->Y);
+	}
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_st7789/adafruit_st7789.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_st7789/adafruit_st7789.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_st7789/adafruit_st7789.h	(revision 453)
@@ -0,0 +1,199 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ *
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+ *
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ *
+ *  $Id$
+ */
+
+/*
+ *  Written by Limor Fried/Ladyada for Adafruit Industries.
+ *  MIT license, all text above must be included in any redistribution
+ *　http://opensource.org/licenses/mit-license.php 
+ */
+
+/*
+ *  ADAFRUIT ST7789 LCD制御プログラムのヘッダファイル
+ */
+
+#ifndef _ADAFRUIT_ST7789_H_
+#define _ADAFRUIT_ST7789_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include "device.h"
+#include "pinmode.h"
+#include "spi.h"
+
+/*
+ *  LCDカラーモード定義
+ */
+#define CM_ARGB8888         0x00000000			/* ARGB8888 color mode */
+#define CM_RGB888           0x00000001			/* RGB888 color mode */
+#define CM_RGB565           0x00000002			/* RGB565 color mode */
+
+#define ST7789_NOP          0x00
+#define ST7789_SWRESET      0x01
+#define ST7789_RDDID        0x04
+#define ST7789_RDDST        0x09
+
+#define ST7789_SLPIN        0x10
+#define ST7789_SLPOUT       0x11
+#define ST7789_PTLON        0x12
+#define ST7789_NORON        0x13
+
+#define ST7789_INVOFF       0x20
+#define ST7789_INVON        0x21
+#define ST7789_DISPOFF      0x28
+#define ST7789_DISPON       0x29
+#define ST7789_CASET        0x2A
+#define ST7789_RASET        0x2B
+#define ST7789_RAMWR        0x2C
+#define ST7789_RAMRD        0x2E
+
+#define ST7789_PTLAR        0x30
+#define ST7789_TEOFF        0x34
+#define ST7789_TEON         0x35
+#define ST7789_COLMOD       0x3A
+#define ST7789_MADCTL       0x36
+
+#define ST7789_MADCTL_MY    0x80
+#define ST7789_MADCTL_MX    0x40
+#define ST7789_MADCTL_MV    0x20
+#define ST7789_MADCTL_ML    0x10
+#define ST7789_MADCTL_RGB   0x00
+
+#define ST7789_RDID1        0xDA
+#define ST7789_RDID2        0xDB
+#define ST7789_RDID3        0xDC
+#define ST7789_RDID4        0xDD
+
+// Color definitions
+#define	ST7789_BLACK        0x0000
+#define	ST7789_BLUE         0x001F
+#define	ST7789_RED          0xF800
+#define	ST7789_GREEN        0x07E0
+#define ST7789_CYAN         0x07FF
+#define ST7789_MAGENTA      0xF81F
+#define ST7789_YELLOW       0xFFE0
+#define ST7789_WHITE        0xFFFF
+
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  カラーの属性を定義
+ */
+typedef uint16_t   color_t;
+
+/*
+ *  LCDハンドラ構造体定義
+ */
+typedef struct
+{
+	SPI_Handle_t            *hspi;		/* spiハンドラ */
+	uint16_t                _width;		/* 幅ピクセル数 */
+	uint16_t				_height;	/* 高さピクセル数 */
+	uint16_t                colstart;
+	uint16_t                rowstart;
+	uint16_t                lcd_width;
+	uint16_t                lcd_height;
+	uint16_t                lcd_colstart;
+	uint16_t                lcd_rowstart;
+	uint8_t                 rotation;
+	uint8_t                 dummy[3];
+	ID                      spi_lock;
+	int8_t                  cs_pin;
+	int8_t                  rs_pin;
+	int8_t                  rst_pin;
+	int8_t                  cs2_pin;
+}LCD_Handler_t;
+
+/*
+ *  描画構造体
+ */
+typedef struct
+{
+	LCD_Handler_t           *hlcd;
+	color_t                 TextColor;
+	color_t                 BackColor;
+	void                    *pFont;
+}LCD_DrawProp_t;
+
+typedef struct
+{
+	int16_t X;
+	int16_t Y;
+}Point, * pPoint;
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+extern ER lcd_writecommand(LCD_Handler_t *hlcd, uint8_t c);
+extern ER lcd_writedata(LCD_Handler_t *hlcd, uint8_t *p, uint32_t len);
+extern ER lcd_writedata2(LCD_Handler_t *hlcd, uint16_t c, int cnt);
+extern ER lcd_writedata3(LCD_Handler_t *hlcd, uint8_t *pbmp, uint16_t width, uint16_t height);
+
+extern void lcd_init(LCD_Handler_t *hlcd, uint16_t width, uint16_t height);
+extern void lcd_setAddrWindow(LCD_Handler_t *hlcd, uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1);
+extern void lcd_setRotation(LCD_Handler_t *hlcd, uint8_t m);
+extern void lcd_fillRect(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t w, int16_t h, color_t color);
+extern void lcd_pushColor(LCD_Handler_t *hlcd, color_t color);
+extern void lcd_drawPixel(LCD_Handler_t *hlcd, int16_t x, int16_t y, color_t color);
+extern void lcd_drawFastVLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t h, color_t color);
+extern void lcd_drawFastHLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t w, color_t color);
+extern void lcd_drawImageHLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, uint16_t w, color_t *pcolor);
+extern void lcd_drawBitmap(LCD_Handler_t *hlcd, uint16_t x0, uint16_t y0, uint8_t *pbmp);
+extern void lcd_invertDisplay(LCD_Handler_t *hlcd, bool_t i);
+
+extern void lcd_fillScreen(LCD_DrawProp_t *pDrawProp);
+extern void lcd_drawRect(LCD_DrawProp_t *pDrawProp, int16_t x, int16_t y, int16_t w, int16_t h);
+extern void lcd_DrawCircle(LCD_DrawProp_t *pDrawProp, uint16_t x0, uint16_t y0, uint16_t Radius);
+extern void lcd_drawLine(LCD_DrawProp_t *pDrawProp, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
+extern void lcd_drawPolygon(LCD_DrawProp_t *pDrawProp, pPoint Points, uint16_t PointCount);
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _ADAFRUIT_ST7789_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_st7789/glcd_core.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_st7789/glcd_core.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruit_st7789/glcd_core.h	(revision 453)
@@ -0,0 +1,45 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+#ifndef _LCD_CORE_H_
+#define _LCD_CORE_H_
+
+#include "adafruit_st7789.h"
+
+#endif /* _LCD_CORE_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruitts_stmp610/Makefile.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruitts_stmp610/Makefile.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruitts_stmp610/Makefile.config	(revision 453)
@@ -0,0 +1,55 @@
+#
+#   TOPPERS/ASP/FMP Kernel
+#       Toyohashi Open Platform for Embedded Real-Time Systems/
+#       Advanced Standard Profile Kernel
+#
+#   Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                               Toyohashi Univ. of Technology, JAPAN
+#   Copyright (C) 2003-2008 by Ryosuke Takeuchi
+#                Platform Development Center RICOH COMPANY,LTD. JAPAN
+#   Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+ 
+#
+#  Makefile のプロセッサ依存 (adafruitts_stmp610用)
+#
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/gdic/adafruitts_stmp610
+
+#
+#  USB DEVICE(GDIC)に関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR):$(SRCDIR)/gdic/adafruitts_stmp610
+SYSSVC_COBJS := $(SYSSVC_COBJS) adafruitts_stmp610.o
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruitts_stmp610/adafruitts_stmp610.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruitts_stmp610/adafruitts_stmp610.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruitts_stmp610/adafruitts_stmp610.c	(revision 453)
@@ -0,0 +1,302 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *  Written by Limor Fried/Ladyada for Adafruit Industries.
+ *  MIT license, all text above must be included in any redistribution
+ *　http://opensource.org/licenses/mit-license.php 
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <sil.h>
+#include <target_syssvc.h>
+#include "device.h"
+#include "pinmode.h"
+#include "adafruitts_stmp610.h"
+
+#define PORT_HIGH           1
+#define PORT_LOW            0
+
+#define TS_MINX             150
+#define TS_MINY             130
+#define TS_MAXX             3800
+#define TS_MAXY             4000
+
+#define cs_set(sw)  digitalWrite(hts->cs_pin, (sw))
+
+static uint8_t aTxBuffer[4];
+
+/*
+ *  STMP610レジスタ読み出し
+ */
+static ER_UINT
+touchscreen_readRegister(TouchScreen_Handle_t *hts, uint8_t reg)
+{
+	ER_UINT ercd = E_OK;
+
+	if(hts->spi_lock != 0){
+		if((ercd = wai_sem(hts->spi_lock)) != E_OK)
+			return ercd;
+	}
+	cs_set(PORT_LOW);
+
+	aTxBuffer[0] = 0x80 | reg;
+	aTxBuffer[1] = 0;
+#if SPI_WAIT_TIME != 0
+	ercd = spi_transmit(hts->hspi, (uint8_t*)aTxBuffer, 2);
+#else
+	if((ercd = spi_transmit(hts->hspi, (uint8_t*)aTxBuffer, 2)) == E_OK){
+		ercd = spi_wait(hts->hspi, 100);
+	}
+#endif
+
+	if(ercd == E_OK){
+#if SPI_WAIT_TIME != 0
+		ercd = spi_receive(hts->hspi, (uint8_t*)aTxBuffer, 1);
+#else
+		if((ercd = spi_receive(hts->hspi, (uint8_t*)aTxBuffer, 1)) == E_OK){
+			ercd = spi_wait(hts->hspi, 100);
+		}
+#endif
+	}
+	if(ercd == E_OK)
+		ercd = aTxBuffer[0];
+
+	cs_set(PORT_HIGH);
+	if(hts->spi_lock != 0)
+		sig_sem(hts->spi_lock);
+	return ercd;
+}
+
+/*
+ *  STMP610レジスタ書き込み
+ */
+ER
+touchscreen_writeRegister(TouchScreen_Handle_t *hts, uint8_t reg, uint8_t val)
+{
+	ER ercd = E_OK;
+
+	if(hts->spi_lock != 0){
+		if((ercd = wai_sem(hts->spi_lock)) != E_OK)
+			return ercd;
+	}
+	cs_set(PORT_LOW);
+
+	aTxBuffer[0] = reg;
+	aTxBuffer[1] = val;
+#if SPI_WAIT_TIME != 0
+	ercd = spi_transmit(hts->hspi, (uint8_t*)aTxBuffer, 2);
+#else
+	if((ercd = spi_transmit(hts->hspi, (uint8_t*)aTxBuffer, 2)) == E_OK){
+		ercd = spi_wait(hts->hspi, 100);
+	}
+#endif
+
+	cs_set(PORT_HIGH);
+	if(hts->spi_lock != 0)
+		sig_sem(hts->spi_lock);
+	return ercd;
+}
+
+
+/*
+ *  STMP610 初期化
+ */
+ER
+touchscreen_init(TouchScreen_Handle_t *hts, uint8_t orientation)
+{
+	Arduino_PortControlBlock *pgcb = getGpioTable(DIGITAL_PIN, hts->cs_pin);
+	GPIO_Init_t GPIO_Init_Data;
+	ER ercd;
+	uint32_t i;
+
+	if(hts == NULL)
+		return E_PAR;
+	if(hts->hspi == NULL)
+		return E_PAR;
+	pgcb = getGpioTable(DIGITAL_PIN, hts->cs_pin);
+	if(pgcb == NULL)
+		return E_PAR;
+
+	GPIO_Init_Data.mode  = GPIO_MODE_OUTPUT;
+	GPIO_Init_Data.pull  = hts->pullmode;
+	GPIO_Init_Data.otype = hts->otype;
+	GPIO_Init_Data.speed = GPIO_SPEED_FAST;
+	gpio_setup(pgcb->giobase, &GPIO_Init_Data, pgcb->giopin);
+
+	/*
+	 *  VERSIONを検証
+	 */
+	if(touchscreen_getversion(hts) != 0x811)
+		return E_SYS;
+	hts->min_x = TS_MINX;
+	hts->min_y = TS_MINY;
+	hts->max_x = TS_MAXX;
+	hts->max_y = TS_MAXY;
+
+	ercd = touchscreen_writeRegister(hts, STMPE_SYS_CTRL1, STMPE_SYS_CTRL1_RESET);
+	dly_tsk(10);
+
+	for(i = 0 ; i < 65 ; i++){
+		touchscreen_readRegister(hts, i);
+	}
+
+	if(ercd == E_OK)
+		ercd = touchscreen_writeRegister(hts, STMPE_SYS_CTRL2, 0x0);	/* turn on clocks! */
+	if(ercd == E_OK)
+		ercd = touchscreen_writeRegister(hts, STMPE_TSC_CTRL, STMPE_TSC_CTRL_XYZ | STMPE_TSC_CTRL_EN);	/* XYZ and enable! */
+	if(ercd == E_OK)
+		ercd = touchscreen_writeRegister(hts, STMPE_INT_EN, STMPE_INT_EN_TOUCHDET);
+	if(ercd == E_OK)
+		ercd = touchscreen_writeRegister(hts, STMPE_ADC_CTRL1, STMPE_ADC_CTRL1_10BIT | (0x6 << 4));	/* 96 clocks per conversion */
+	if(ercd == E_OK)
+		ercd = touchscreen_writeRegister(hts, STMPE_ADC_CTRL2, STMPE_ADC_CTRL2_6_5MHZ);
+	if(ercd == E_OK)
+		ercd = touchscreen_writeRegister(hts, STMPE_TSC_CFG, STMPE_TSC_CFG_4SAMPLE | STMPE_TSC_CFG_DELAY_1MS | STMPE_TSC_CFG_SETTLE_5MS);
+	if(ercd == E_OK)
+		ercd = touchscreen_writeRegister(hts, STMPE_TSC_FRACTION_Z, 0x6);
+	if(ercd == E_OK)
+		ercd = touchscreen_writeRegister(hts, STMPE_FIFO_TH, 1);
+	if(ercd == E_OK)
+		ercd = touchscreen_writeRegister(hts, STMPE_FIFO_STA, STMPE_FIFO_STA_RESET);
+	if(ercd == E_OK)
+		ercd = touchscreen_writeRegister(hts, STMPE_FIFO_STA, 0);		/* unreset */
+	if(ercd == E_OK)
+		ercd = touchscreen_writeRegister(hts, STMPE_TSC_I_DRIVE, STMPE_TSC_I_DRIVE_50MA);
+	if(ercd == E_OK)
+		ercd = touchscreen_writeRegister(hts, STMPE_INT_STA, 0xFF);		/* reset all ints */
+	if(ercd == E_OK)
+		ercd = touchscreen_writeRegister(hts, STMPE_INT_CTRL, STMPE_INT_CTRL_POL_HIGH | STMPE_INT_CTRL_ENABLE);
+	return ercd;
+}
+
+/*
+ *  STMP610 タッチ判定
+ *  param1  hts: Pointer to Touch Screen Handler
+ *  result  エラーまたはbool判定
+ */
+ER_BOOL
+touchscreen_touched(TouchScreen_Handle_t *hts)
+{
+	ER_BOOL ercd;
+
+	if(hts == NULL)
+		return E_PAR;
+	if((ercd = touchscreen_readRegister(hts, STMPE_TSC_CTRL)) >= E_OK)
+		ercd = (ercd & 0x80) != 0;
+	return ercd;
+}
+
+/*
+ *  STMP610 FIFOサイズ読み出し
+ *  param1  hts: Pointer to Touch Screen Handler
+ *  result  エラーまたは現在のアイテム数
+ */
+ER_UINT
+touchscreen_buffersize(TouchScreen_Handle_t *hts)
+{
+	ER_BOOL ercd;
+
+	if(hts == NULL)
+		return E_PAR;
+	if((ercd = touchscreen_readRegister(hts, STMPE_FIFO_STA)) >= E_OK){
+		if((ercd & STMPE_FIFO_STA_EMPTY) == 0)
+			ercd = touchscreen_readRegister(hts, STMPE_FIFO_SIZE);
+		else
+			ercd = 0;
+	}
+	return ercd;
+}
+
+/*
+ *  STMP610 ポイント読み出し
+ *  param1  hts: Pointer to Touch Screen Handler
+ *  param2  pt:  Pointer to Point type arry
+ *  param3  len: max number of arry items
+ *  result  エラーまたは設定アイテム数
+ */
+ER_UINT
+touchscreen_getpoint(TouchScreen_Handle_t *hts, TouchScreen_Point_t *pt, uint8_t len)
+{
+	ER_UINT  buffer[4], no = 0, ercd;
+	uint32_t i;
+
+	if(hts == NULL || pt == NULL)
+		return E_PAR;
+	while((ercd = touchscreen_buffersize(hts)) > 0){
+		for(i = 0 ; i < 4 ; i++){
+			if((buffer[i] = touchscreen_readRegister(hts, 0xD7)) < E_OK)
+				return buffer[i];
+		}
+		if(no < len){
+			pt->x  = buffer[0] << 4;
+			pt->x |= (buffer[1] >> 4 & 0x0F);
+			pt->y  = (buffer[1] & 0x0F) << 8;
+			pt->y |= buffer[2] & 0xFF;
+			pt->z = buffer[3];
+			no++;
+			pt++;
+		}
+	}
+	return no;
+}
+
+/*
+ *  STMP610 バージョン読み出し
+ */
+ER_UINT
+touchscreen_getversion(TouchScreen_Handle_t *hts)
+{
+	ER_UINT ercd, ercd2;
+
+	if(hts == NULL)
+		return E_PAR;
+
+	if((ercd = touchscreen_readRegister(hts, 0)) >= E_OK){
+		ercd <<= 8;
+		if((ercd2 = touchscreen_readRegister(hts, 1)) >= E_OK){
+			ercd |= ercd2 & 0xFF;
+			return ercd;
+		}
+		ercd = ercd2;
+	}
+	return ercd;
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruitts_stmp610/adafruitts_stmp610.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruitts_stmp610/adafruitts_stmp610.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/adafruitts_stmp610/adafruitts_stmp610.h	(revision 453)
@@ -0,0 +1,182 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *  Written by Limor Fried/Ladyada for Adafruit Industries.
+ *  MIT license, all text above must be included in any redistribution
+ *　http://opensource.org/licenses/mit-license.php 
+ */
+
+#ifndef _ADAFRUITTS_STMP610_H_
+#define _ADAFRUITTS_STMP610_H_
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include "device.h"
+#include "spi.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#define STMPE_ADDR 0x41
+
+#define STMPE_SYS_CTRL1 0x03
+#define STMPE_SYS_CTRL1_RESET 0x02
+#define STMPE_SYS_CTRL2 0x04
+
+#define STMPE_TSC_CTRL 0x40
+#define STMPE_TSC_CTRL_EN 0x01
+#define STMPE_TSC_CTRL_XYZ 0x00
+#define STMPE_TSC_CTRL_XY 0x02
+
+#define STMPE_INT_CTRL 0x09
+#define STMPE_INT_CTRL_POL_HIGH 0x04
+#define STMPE_INT_CTRL_POL_LOW 0x00
+#define STMPE_INT_CTRL_EDGE 0x02
+#define STMPE_INT_CTRL_LEVEL 0x00
+#define STMPE_INT_CTRL_ENABLE 0x01
+#define STMPE_INT_CTRL_DISABLE 0x00
+
+
+
+#define STMPE_INT_EN 0x0A
+#define STMPE_INT_EN_TOUCHDET 0x01
+#define STMPE_INT_EN_FIFOTH 0x02
+#define STMPE_INT_EN_FIFOOF 0x04
+#define STMPE_INT_EN_FIFOFULL 0x08
+#define STMPE_INT_EN_FIFOEMPTY 0x10
+#define STMPE_INT_EN_ADC 0x40
+#define STMPE_INT_EN_GPIO 0x80
+
+#define STMPE_INT_STA 0x0B
+#define STMPE_INT_STA_TOUCHDET 0x01
+
+#define STMPE_ADC_CTRL1 0x20
+#define STMPE_ADC_CTRL1_12BIT 0x08
+#define STMPE_ADC_CTRL1_10BIT 0x00
+
+#define STMPE_ADC_CTRL2 0x21
+#define STMPE_ADC_CTRL2_1_625MHZ 0x00
+#define STMPE_ADC_CTRL2_3_25MHZ 0x01
+#define STMPE_ADC_CTRL2_6_5MHZ 0x02
+
+#define STMPE_TSC_CFG 0x41
+#define STMPE_TSC_CFG_1SAMPLE 0x00
+#define STMPE_TSC_CFG_2SAMPLE 0x40
+#define STMPE_TSC_CFG_4SAMPLE 0x80
+#define STMPE_TSC_CFG_8SAMPLE 0xC0
+#define STMPE_TSC_CFG_DELAY_10US 0x00
+#define STMPE_TSC_CFG_DELAY_50US 0x08
+#define STMPE_TSC_CFG_DELAY_100US 0x10
+#define STMPE_TSC_CFG_DELAY_500US 0x18
+#define STMPE_TSC_CFG_DELAY_1MS 0x20
+#define STMPE_TSC_CFG_DELAY_5MS 0x28
+#define STMPE_TSC_CFG_DELAY_10MS 0x30
+#define STMPE_TSC_CFG_DELAY_50MS 0x38
+#define STMPE_TSC_CFG_SETTLE_10US 0x00
+#define STMPE_TSC_CFG_SETTLE_100US 0x01
+#define STMPE_TSC_CFG_SETTLE_500US 0x02
+#define STMPE_TSC_CFG_SETTLE_1MS 0x03
+#define STMPE_TSC_CFG_SETTLE_5MS 0x04
+#define STMPE_TSC_CFG_SETTLE_10MS 0x05
+#define STMPE_TSC_CFG_SETTLE_50MS 0x06
+#define STMPE_TSC_CFG_SETTLE_100MS 0x07
+
+#define STMPE_FIFO_TH 0x4A
+
+#define STMPE_FIFO_SIZE 0x4C 
+
+#define STMPE_FIFO_STA 0x4B
+#define STMPE_FIFO_STA_RESET 0x01
+#define STMPE_FIFO_STA_OFLOW 0x80
+#define STMPE_FIFO_STA_FULL 0x40
+#define STMPE_FIFO_STA_EMPTY 0x20
+#define STMPE_FIFO_STA_THTRIG 0x10
+
+#define STMPE_TSC_I_DRIVE 0x58
+#define STMPE_TSC_I_DRIVE_20MA 0x00
+#define STMPE_TSC_I_DRIVE_50MA 0x01
+
+#define STMPE_TSC_DATA_X 0x4D
+#define STMPE_TSC_DATA_Y 0x4F
+#define STMPE_TSC_FRACTION_Z 0x56
+
+#define STMPE_GPIO_SET_PIN 0x10
+#define STMPE_GPIO_CLR_PIN 0x11
+#define STMPE_GPIO_DIR 0x13
+#define STMPE_GPIO_ALT_FUNCT 0x17
+
+typedef struct
+{
+	int16_t                 x;
+	int16_t                 y;
+	int16_t                 z;
+} TouchScreen_Point_t;
+
+/*
+ *  TouchScreenハンドラ構造体定義
+ */
+typedef struct
+{
+	SPI_Handle_t            *hspi;		/* spiハンドラ */
+	uint16_t                min_x;
+	uint16_t                min_y;
+	uint16_t                max_x;
+	uint16_t                max_y;
+	uint8_t                 cs_pin;
+	uint32_t                otype;
+	uint32_t                pullmode;
+	ID                      spi_lock;
+} TouchScreen_Handle_t;
+
+extern ER touchscreen_init(TouchScreen_Handle_t *hts, uint8_t orientation);
+extern ER_BOOL touchscreen_touched(TouchScreen_Handle_t *hts);
+extern ER_UINT touchscreen_buffersize(TouchScreen_Handle_t *hts);
+extern ER_UINT touchscreen_getversion(TouchScreen_Handle_t *hts);
+extern ER touchscreen_getpoint(TouchScreen_Handle_t *hts, TouchScreen_Point_t *point, uint8_t len);
+extern ER touchscreen_writeRegister(TouchScreen_Handle_t *hts, uint8_t reg, uint8_t val);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ADAFRUITTS_STMP610_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/aqm0802_st7032/Makefile.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/aqm0802_st7032/Makefile.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/aqm0802_st7032/Makefile.config	(revision 453)
@@ -0,0 +1,55 @@
+#
+#   TOPPERS/ASP/FMP Kernel
+#       Toyohashi Open Platform for Embedded Real-Time Systems/
+#       Advanced Standard Profile Kernel
+#
+#   Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                               Toyohashi Univ. of Technology, JAPAN
+#   Copyright (C) 2003-2008 by Ryosuke Takeuchi
+#                Platform Development Center RICOH COMPANY,LTD. JAPAN
+#   Copyright (C) 2015-2017 by TOPPERS PROJECT Educational Working Group.
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+ 
+#
+#  Makefile のプロセッサ依存 (aqm0802 st7032:LCD用)
+#
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/gdic/aqm0802_st7032
+
+#
+#  AQM0802 ST7032 LCD DRIVER(GDIC)に関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR):$(SRCDIR)/gdic/aqm0802_st7032
+SYSSVC_COBJS := $(SYSSVC_COBJS) aqm0802_st7032.o
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/aqm0802_st7032/aqm0802_st7032.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/aqm0802_st7032/aqm0802_st7032.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/aqm0802_st7032/aqm0802_st7032.c	(revision 453)
@@ -0,0 +1,210 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2012 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *  AQM0802 ST7032 LCD制御プログラムの本体
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <target_syssvc.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#include "kernel_cfg.h"
+#include "device.h"
+#include "aqm0802_st7032.h"
+
+#define TXBUFFERSIZE  2
+
+#if defined(TOPPERS_BASE_PLATFORM_STF7)
+#define i2c_send(h, a, b, l)    i2c_memwrite((h), (a), 0, 0, (b), (l), 500)
+#else
+#define i2c_send(h, a, b, l)    i2c_memwrite((h), (a), 0, 0, (b), (l))
+#endif
+
+static uint8_t aTxBuffer[TXBUFFERSIZE];
+
+/*
+ *  LCDの初期化
+ */
+ER
+aqm0802_init(CLCD_Handler_t *hlcd)
+{
+	I2C_Handle_t *hi2c = hlcd->hi2c;
+	ER ercd;
+
+	hlcd->max_col = 8;
+	hlcd->max_raw = 2;
+
+	/*
+	 *  LED COMMAND 0x38
+	 */
+    aTxBuffer[0] = ST7032_CMD;
+    aTxBuffer[1] = 0x38;
+	if((ercd = i2c_send(hi2c, hlcd->saddr, aTxBuffer, TXBUFFERSIZE)) != E_OK)
+		return ercd;
+
+    // Wait 70us
+    sil_dly_nse(LCD_INTERVAL1*1000);
+    /*
+	 *  LCD COMMAND 0x39
+	 */
+    aTxBuffer[0] = ST7032_CMD;
+    aTxBuffer[1] = 0x39;
+	if((ercd = i2c_send(hi2c, hlcd->saddr, aTxBuffer, TXBUFFERSIZE)) != E_OK)
+		return ercd;
+
+    // Wait 26.3us
+    sil_dly_nse(LCD_INTERVAL2*1000);
+	/*
+	 *  LCD COMMAND 0x14
+	 */
+    aTxBuffer[0] = ST7032_CMD;
+    aTxBuffer[1] = 0x14;
+	if((ercd = i2c_send(hi2c, hlcd->saddr, aTxBuffer, TXBUFFERSIZE)) != E_OK)
+		return ercd;
+
+    // Wait 26.3us
+    sil_dly_nse(LCD_INTERVAL2*1000);
+	/*
+	 *  LCD COMMAND 0x70
+	 */
+    aTxBuffer[0] = ST7032_CMD;
+    aTxBuffer[1] = 0x70;
+	if((ercd = i2c_send(hi2c, hlcd->saddr, aTxBuffer, TXBUFFERSIZE)) != E_OK)
+		return ercd;
+
+    // Wait 26.3us
+    sil_dly_nse(LCD_INTERVAL2*1000);
+	/*
+	 *  LCD COMMAND 0x56
+	 */
+    aTxBuffer[0] = ST7032_CMD;
+    aTxBuffer[1] = 0x56;
+	if((ercd = i2c_send(hi2c, hlcd->saddr, aTxBuffer, TXBUFFERSIZE)) != E_OK)
+		return ercd;
+
+    // Wait 26.3us
+    sil_dly_nse(LCD_INTERVAL2*1000);
+	/*
+	 *  LCD COMMAND 0x6C
+	 */
+    aTxBuffer[0] = ST7032_CMD;
+    aTxBuffer[1] = 0x6C;
+	if((ercd = i2c_send(hi2c, hlcd->saddr, aTxBuffer, TXBUFFERSIZE)) != E_OK)
+		return ercd;
+
+    // Wait 200ms
+	dly_tsk(200);
+	/*
+	 *  LCD COMMAND 0x38
+	 */
+    aTxBuffer[0] = ST7032_CMD;
+    aTxBuffer[1] = 0x38;
+	if((ercd = i2c_send(hi2c, hlcd->saddr, aTxBuffer, TXBUFFERSIZE)) != E_OK)
+		return ercd;
+
+    // Wait 26.3us
+    sil_dly_nse(LCD_INTERVAL2*1000);
+	/*
+	 * LCD COMMAND 0x0C Display ON/OFF control
+	 */
+    aTxBuffer[0] = ST7032_CMD;
+    aTxBuffer[1] = 0x0C;
+	if((ercd = i2c_send(hi2c, hlcd->saddr, aTxBuffer, TXBUFFERSIZE)) != E_OK)
+		return ercd;
+
+    // Wait 26.3us
+    sil_dly_nse(LCD_INTERVAL2*1000);
+	/*
+	 *  LCD COMMAND 0x01 Clear Display
+	 */
+    aTxBuffer[0] = ST7032_CMD;
+    aTxBuffer[1] = 0x01;
+	if((ercd = i2c_send(hi2c, hlcd->saddr, aTxBuffer, TXBUFFERSIZE)) != E_OK)
+		return ercd;
+
+    // Wait 1.08ms
+	dly_tsk(2);
+	/*
+	 *  LCD COMMAND 0x80
+	 */
+    aTxBuffer[0] = ST7032_CMD;
+    aTxBuffer[1] = 0x80;
+	i2c_send(hi2c, hlcd->saddr, aTxBuffer, TXBUFFERSIZE);
+	return ercd;
+}
+
+/*
+ *  LCDへのコマンド送信関数
+ */
+ER
+aqm0802_set_command(CLCD_Handler_t *hlcd, uint8_t c)
+{
+    aTxBuffer[0] = ST7032_CMD;
+    aTxBuffer[1] = c;
+	return i2c_send(hlcd->hi2c, hlcd->saddr, aTxBuffer, TXBUFFERSIZE);
+}
+
+/*
+ *  LCDへのデータ送信関数
+ */
+ER
+aqm0802_set_data(CLCD_Handler_t *hlcd, uint8_t *p, uint8_t len)
+{
+	ER  ercd = E_OK;
+	int i;
+
+	for(i = 0 ; i < len ; i++){
+	    aTxBuffer[0] = ST7032_DAT;
+    	aTxBuffer[1] = *p++;
+		ercd = i2c_send(hlcd->hi2c, hlcd->saddr, aTxBuffer, TXBUFFERSIZE);
+		if(ercd != E_OK)
+			break;
+    }
+	return ercd;
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/aqm0802_st7032/aqm0802_st7032.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/aqm0802_st7032/aqm0802_st7032.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/aqm0802_st7032/aqm0802_st7032.h	(revision 453)
@@ -0,0 +1,96 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ *
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2017 by TOPPERS PROJECT Educational Working Group.
+ *
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ *
+ *  $Id$
+ */
+
+/*
+ *  AQM0802 ST7032 LCD制御プログラムのヘッダファイル
+ */
+
+#ifndef _AQM0802_ST7032_H_
+#define _AQM0802_ST7032_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include "device.h"
+#include "pinmode.h"
+#include "i2c.h"
+
+/*
+ *  ST7032 RS R/W
+ */
+#define ST7032_CMD          0x00
+#define ST7032_DAT          0x40
+#define ST7032_CONT         0x80
+
+#define LCD_INTERVAL1       70
+#define LCD_INTERVAL2       27
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  LCDハンドラ構造体定義
+ */
+typedef struct
+{
+	I2C_Handle_t            *hi2c;
+	uint16_t                saddr;		/* 幅ピクセル数 */
+	uint8_t                 max_col;	/* 高さピクセル数 */
+	uint8_t                 max_raw;
+}CLCD_Handler_t;
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+extern ER aqm0802_init(CLCD_Handler_t *hlcd);
+extern ER aqm0802_set_command(CLCD_Handler_t *hlcd, uint8_t c);
+extern ER aqm0802_set_data(CLCD_Handler_t *hlcd, uint8_t *p, uint8_t len);
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _AQM0802_ST7032_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/aqm1248_st7565/Makefile.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/aqm1248_st7565/Makefile.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/aqm1248_st7565/Makefile.config	(revision 453)
@@ -0,0 +1,56 @@
+#
+#   TOPPERS/ASP/FMP Kernel
+#       Toyohashi Open Platform for Embedded Real-Time Systems/
+#       Advanced Standard Profile Kernel
+#
+#   Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                               Toyohashi Univ. of Technology, JAPAN
+#   Copyright (C) 2003-2008 by Ryosuke Takeuchi
+#                Platform Development Center RICOH COMPANY,LTD. JAPAN
+#   Copyright (C) 2015-2018 by TOPPERS PROJECT Educational Working Group.
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+ 
+#
+#  Makefile のプロセッサ依存 (aqm1248 st7565:LCD用)
+#
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/gdic/aqm1248_st7565
+
+#
+#  AQM0802 ST7032 LCD DRIVER(GDIC)に関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR):$(SRCDIR)/gdic/aqm1248_st7565
+SYSSVC_COBJS := $(SYSSVC_COBJS) aqm1248_st7565.o
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/aqm1248_st7565/aqm1248_st7565.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/aqm1248_st7565/aqm1248_st7565.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/aqm1248_st7565/aqm1248_st7565.c	(revision 453)
@@ -0,0 +1,631 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *  AQM1248 ST7565 LCD制御プログラムの本体
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <target_syssvc.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#include "kernel_cfg.h"
+#include "device.h"
+#include "aqm1248_st7565.h"
+
+/*
+ *  サービスコールのエラーのログ出力
+ */
+Inline void
+svc_perror(const char *file, int_t line, const char *expr, ER ercd)
+{
+	if (ercd < 0) {
+		t_perror(LOG_ERROR, file, line, expr, ercd);
+	}
+}
+
+#define	SVC_PERROR(expr)	svc_perror(__FILE__, __LINE__, #expr, (expr))
+#define ABS(X)  ((X) > 0 ? (X) : -(X))
+
+#define PORT_HIGH           1
+#define PORT_LOW            0
+
+#define cs_set(sw)  digitalWrite(hlcd->cs_pin, sw)
+#define rs_set(sw)  digitalWrite(hlcd->rs_pin, sw)
+#define rst_set(sw) digitalWrite(hlcd->rst_pin, sw)
+
+static const uint8_t left_mask_table[8] = {
+	0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01
+};
+
+static const uint8_t right_mask_table[8] = {
+	0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF
+};
+
+static const uint8_t dither_table[8][8] = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},	/* BLACK */
+	{0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55},	/* BLUE */
+	{0xFA, 0x5F, 0xF5, 0xAF, 0xFA, 0x5F, 0xF5, 0xAF},	/* GREEN */
+	{0xFD, 0xDF, 0xFB, 0xBF, 0xFD, 0xDF, 0xFB, 0xBF},	/* CYAN */
+	{0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA},	/* RED */
+	{0xAF, 0xF5, 0x5F, 0xFA, 0xAF, 0xF5, 0x5F, 0xFA},	/* MAGENTA */
+	{0xDF, 0xFD, 0xBF, 0xFB, 0xDF, 0xFD, 0xBF, 0xFB},	/* YELLOW */
+	{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}	/* WHITE */
+};
+
+/* Buffer used for transmission */
+static uint8_t aTxBuffer[4];
+
+
+/*
+ *  バッファデータをLCDに転送
+ */
+static void
+lcd_flush_buffer(LCD_Handler_t *hlcd)
+{
+	uint32_t l, col, i;
+	uint8_t page, val1, val2;
+
+	for(l = hlcd->_winy1 ; l <= hlcd->_winy2 ; l += AQM1248_PLINE){
+		page = l / AQM1248_PLINE;
+		col  = hlcd->_winx1;
+		SVC_PERROR(lcd_writecommand(hlcd, ST7565_PAGEADR + page));
+		SVC_PERROR(lcd_writecommand(hlcd, ST7565_COLADR + (col >> 4)));
+		SVC_PERROR(lcd_writecommand(hlcd, (col & 0x0f)));
+		for(; col <= hlcd->_winx2 ; col++){
+			for(i = val1 = 0 ; i < 8 ; i++){
+				val2  = hlcd->buffer[(page * AQM1248_PLINE) + i][col/8] << (col & 7);
+				val1 |= (val2 & 0x80) >> (7 - i);
+			}
+			SVC_PERROR(lcd_writedata(hlcd, val1));
+		}
+	}
+}
+
+/*
+ *  バッファ上にイメージを作る
+ */
+static void
+lcd_fill_buffer(LCD_Handler_t *hlcd, color_t color)
+{
+	uint32_t x, y;
+	uint8_t  *p;
+
+	color &= 7;
+	for(y = hlcd->_winy1 ; y <= hlcd->_winy2 ; y++){
+		p = &hlcd->buffer[y][hlcd->_winx1/8];
+		for(x = 0 ; x < hlcd->stride ; x++, p++){
+			if(x == 0){
+				*p &= ~hlcd->lmask;
+				*p |= dither_table[color][y & 7] & hlcd->lmask;
+			}
+			else if(x == (hlcd->stride-1)){
+				*p &= ~hlcd->rmask;
+				*p |= dither_table[color][y & 7] & hlcd->rmask;
+			}
+			else
+				*p = dither_table[color][y & 7];
+		}
+	}
+}
+
+/*
+ *  LCDへのコマンド送信関数
+ */
+ER
+lcd_writecommand(LCD_Handler_t *hlcd, uint8_t c)
+{
+	ER ercd = E_OK;
+
+	if(hlcd->spi_lock != 0){
+		if((ercd = wai_sem(hlcd->spi_lock)) != E_OK)
+			return ercd;
+	}
+	rs_set(PORT_LOW);
+	cs_set(PORT_LOW);
+
+	aTxBuffer[0] = c;
+#if SPI_WAIT_TIME != 0
+	ercd = spi_transmit(hlcd->hspi, (uint8_t*)aTxBuffer, 1);
+#else
+	if((ercd = spi_transmit(hlcd->hspi, (uint8_t*)aTxBuffer, 1)) == E_OK){
+		ercd = spi_wait(hlcd->hspi, 100);
+	}
+#endif
+
+	cs_set(PORT_HIGH);
+	if(hlcd->spi_lock != 0)
+		sig_sem(hlcd->spi_lock);
+	return ercd;
+}
+
+/*
+ *  LCDへのデータ送信関数
+ */
+ER
+lcd_writedata(LCD_Handler_t *hlcd, uint8_t c)
+{
+	ER ercd = E_OK;
+
+	if(hlcd->spi_lock != 0){
+		if((ercd = wai_sem(hlcd->spi_lock)) != E_OK)
+			return ercd;
+	}
+	rs_set(PORT_HIGH);
+	cs_set(PORT_LOW);
+	sil_dly_nse(100);
+
+	aTxBuffer[0] = c;
+#if SPI_WAIT_TIME != 0
+	ercd = spi_transmit(hlcd->hspi, (uint8_t*)aTxBuffer, 1);
+#else
+	if((ercd = spi_transmit(hlcd->hspi, (uint8_t*)aTxBuffer, 1)) == E_OK){
+		ercd = spi_wait(hlcd->hspi, 100);
+	}
+#endif
+
+	sil_dly_nse(100);
+	cs_set(PORT_HIGH);
+	if(hlcd->spi_lock != 0)
+		sig_sem(hlcd->spi_lock);
+	return ercd;
+}
+
+
+/*
+ *  ST7565 LCDの初期化関数
+ */
+void
+lcd_init(LCD_Handler_t *hlcd)
+{
+	uint32_t i;
+
+	rst_set(PORT_LOW);
+	dly_tsk(100);
+	rst_set(PORT_HIGH);
+	dly_tsk(100);
+
+	hlcd->_width  = AQM1248_WIDTH;
+	hlcd->_height = AQM1248_HEIGHT;
+
+	SVC_PERROR(lcd_writecommand(hlcd, ST7565_DISPOFF));		/* 表示OFF */
+	SVC_PERROR(lcd_writecommand(hlcd, ST7565_ADCSELN));		/* ADC select normal */
+	SVC_PERROR(lcd_writecommand(hlcd, ST7565_COMOUTR));		/* comon output reverse */
+	SVC_PERROR(lcd_writecommand(hlcd, ST7565_BIAS17));		/* lcd bias 1/7 */
+
+	SVC_PERROR(lcd_writecommand(hlcd, ST7565_PWRSEL+4));	/* power select 1 */
+	dly_tsk(2);
+	SVC_PERROR(lcd_writecommand(hlcd, ST7565_PWRSEL+6));	/* power select 2 */
+	dly_tsk(2);
+	SVC_PERROR(lcd_writecommand(hlcd, ST7565_PWRSEL+7));	/* power select 3 */
+
+	SVC_PERROR(lcd_writecommand(hlcd, ST7565_RATSEL+3));	/* voltage resistor ratio 3 */
+	SVC_PERROR(lcd_writecommand(hlcd, ST7565_SETEVOL));		/* electronic volume set */
+	SVC_PERROR(lcd_writecommand(hlcd, 0x1C));				/* volume value */
+
+	SVC_PERROR(lcd_writecommand(hlcd, ST7565_ALLPNL));		/* all point normal */
+	SVC_PERROR(lcd_writecommand(hlcd, ST7565_STRLINE));		/* start line #0 */
+	SVC_PERROR(lcd_writecommand(hlcd, ST7565_DISPREV));		/* 表示reverse */
+	SVC_PERROR(lcd_writecommand(hlcd, ST7565_DISPON));		/* 表示ON */
+	for(i = 0 ; i < AQM1248_HEIGHT ; i++)
+		memset(&hlcd->buffer[i][0], 0xff, AQM1248_WIDTH/8);
+}
+
+/*
+ *  表示ウィンドウ設定
+ */
+void
+lcd_setAddrWindow(LCD_Handler_t *hlcd, uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1)
+{
+	uint8_t hx = x0 & 7;
+
+	hlcd->_winx1 = x0;
+	hlcd->_winy1 = y0;
+	hlcd->_winx2 = x1;
+	hlcd->_winy2 = y1;
+	hlcd->lmask  = left_mask_table[hx];
+	hlcd->rmask  = right_mask_table[x1 & 7];
+	if(hx == 0)
+		hlcd->stride = (x1 - x0 + 8) / 8;
+	else
+		hlcd->stride = (x1 - x0 + hx) / 8 + 1;
+	if(hlcd->stride == 1)
+		hlcd->lmask &= hlcd->rmask;
+}
+
+/*
+ *  RECTANGLEのフィル描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: start X position
+ *  param3  y: start Y position
+ *  param4  w: width
+ *  param5  h: height
+ *  param6  color: color value
+ */
+void
+lcd_fillRect(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t w, int16_t h, color_t color)
+{
+	// rudimentary clipping (drawChar w/big text requires this)
+	if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
+	if((x + w - 1) >= hlcd->_width)  w = hlcd->_width  - x;
+	if((y + h - 1) >= hlcd->_height) h = hlcd->_height - y;
+
+	lcd_setAddrWindow(hlcd, x, y, x+w-1, y+h-1);
+	lcd_fill_buffer(hlcd, color);
+	lcd_flush_buffer(hlcd);
+}
+
+/*
+ *  PIXEL描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: X position
+ *  param3  y: Y position
+ *  param4  color: color value
+ */
+void
+lcd_drawPixel(LCD_Handler_t *hlcd, int16_t x, int16_t y, color_t color)
+{
+	if((x < 0) ||(x >= hlcd->_width) || (y < 0) || (y >= hlcd->_height)) return;
+
+	lcd_setAddrWindow(hlcd, x, y, x, y);
+	lcd_fill_buffer(hlcd, color);
+	lcd_flush_buffer(hlcd);
+}
+
+/*
+ *  垂直方向LINEの高速描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: start X position
+ *  param3  y: start Y position
+ *  param4  h: height
+ *  param5  color: color value
+ */
+void
+lcd_drawFastVLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t h, color_t color)
+{
+	// Rudimentary clipping
+	if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
+	if((y+h-1) >= hlcd->_height) h = hlcd->_height-y;
+	lcd_setAddrWindow(hlcd, x, y, x, y+h-1);
+	lcd_fill_buffer(hlcd, color);
+	lcd_flush_buffer(hlcd);
+}
+
+/*
+ *  水平方向LINEの高速描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: start X position
+ *  param3  y: start Y position
+ *  param4  w: width
+ *  param5  color: color value
+ */
+void lcd_drawFastHLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t w, color_t color)
+{
+	// Rudimentary clipping
+	if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
+	if((x+w-1) >= hlcd->_width)  w = hlcd->_width-x;
+	lcd_setAddrWindow(hlcd, x, y, x+w-1, y);
+	lcd_fill_buffer(hlcd, color);
+	lcd_flush_buffer(hlcd);
+}
+
+/*
+ *  DRAW IMAGE LINE描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: X position
+ *  param3  y: Y position
+ *  param4  w: width
+ *  param5  pcolor: color value
+ */
+void
+lcd_drawImageHLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, uint16_t w, color_t *pcolor)
+{
+	uint32_t i;
+
+	if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
+	if((x+w-1) >= hlcd->_width)  w = hlcd->_width-x;
+
+	for(i = 0 ; i < w ; i++, pcolor++){
+		lcd_setAddrWindow(hlcd, x+i, y, x+i, y);
+		lcd_fill_buffer(hlcd, *pcolor);
+		lcd_flush_buffer(hlcd);
+	}
+}
+
+/*
+ *  BITMAP描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x0: Bmp X position in the LCD
+ *  param3  y0: Bmp Y position in the LCD
+ *  param4  pbmp: Pointer to Bmp picture address in the internal Flash
+ */
+void
+lcd_drawBitmap(LCD_Handler_t *hlcd, uint16_t x0, uint16_t y0, uint8_t *pbmp)
+{
+	uint32_t index = 0, width = 0, height = 0, bit_pixel = 0;
+	uint32_t input_color_mode = 0;
+	uint16_t val, l, col;
+
+	/* Get bitmap data address offset */
+	index = *(uint16_t *) (pbmp + 10);
+	index |= (*(uint16_t *) (pbmp + 12)) << 16;
+
+	/* Read bitmap width */
+	width = *(uint16_t *) (pbmp + 18);
+	width |= (*(uint16_t *) (pbmp + 20)) << 16;
+
+	/* Read bitmap height */
+	height = *(uint16_t *) (pbmp + 22);
+	height |= (*(uint16_t *) (pbmp + 24)) << 16;
+
+	/* Read bit/pixel */
+	bit_pixel = *(uint16_t *) (pbmp + 28);
+
+	/* Get the layer pixel format */
+	if ((bit_pixel/8) == 4){
+		input_color_mode = CM_ARGB8888;
+	}
+	else if ((bit_pixel/8) == 2){
+		input_color_mode = CM_RGB565;
+	}
+	else{
+		input_color_mode = CM_RGB888;
+	}
+
+	/* Bypass the bitmap header */
+	pbmp += (index + (width * (height - 1) * (bit_pixel/8)));  
+	syslog_4(LOG_NOTICE, "## input_color_mode(%d) width(%d) height(%d) bit_pixel(%d) ##", input_color_mode, width, height, bit_pixel);
+
+	for(l = 0 ; l < height ; l++){
+		uint8_t *p = pbmp;
+		for(col = 0 ; col < width ; col++){
+			switch(input_color_mode){
+			case CM_RGB565:
+				if((*p & 0xC0) == 0xC0)
+					val = 0x04;
+				else
+					val = 0x00;
+				if((*p++ & 0x06) == 0x06)
+					val |= 0x02;
+				if((*p++ & 0x18) == 0x18)
+					val |= 0x01;
+				break;
+			default:
+				if((*p++ & 0xE0) == 0xE0)
+					val = 0x04;
+				else
+					val = 0x00;
+				if((*p++ & 0xE0) == 0xE0)
+					val |= 0x02;
+				if((*p++ & 0xE0) == 0xE0)
+					val |= 0x01;
+				break;
+			}
+			if((l+y0) < hlcd->_height)
+				lcd_drawPixel(hlcd, col+x0, l+y0, val);
+		}
+		pbmp -= (bit_pixel/8) * width;
+	}
+}
+
+/*
+ *  INVERT DISPLAY
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  i: invert value
+ */
+void
+lcd_invertDisplay(LCD_Handler_t *hlcd, bool_t i)
+{
+ 	SVC_PERROR(lcd_writecommand(hlcd, i ? ST7565_DISPNOR : ST7565_DISPREV));
+}
+
+
+/*
+ *  スクリーンフィル
+ *  param1  pDrawProp: Pointer to Draw Prop
+ */
+void
+lcd_fillScreen(LCD_DrawProp_t *pDrawProp)
+{
+	lcd_fillRect(pDrawProp->hlcd, 0, 0,  pDrawProp->hlcd->_width, pDrawProp->hlcd->_height, pDrawProp->BackColor);
+}
+
+/*
+ *  RECTANGLE描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x: left X position
+ *  param3  y: top Y position
+ *  param4  w: width
+ *  param5  h: height
+ */
+void
+lcd_drawRect(LCD_DrawProp_t *pDrawProp, int16_t x, int16_t y, int16_t w, int16_t h)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	color_t color;
+
+	// rudimentary clipping (drawChar w/big text requires this)
+	if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
+	if(y < 0) return;
+	if((x + w - 1) >= hlcd->_width)  w = hlcd->_width  - x;
+	if((y + h - 1) >= hlcd->_height) h = hlcd->_height - y;
+
+	color = pDrawProp->TextColor;
+	lcd_drawFastVLine(hlcd, x, y, h, color);
+	lcd_drawFastHLine(hlcd, x, y+h-1, w, color);
+	lcd_drawFastVLine(hlcd, x+w-1, y, h, color);
+	lcd_drawFastHLine(hlcd, x, y, w, color);
+}
+
+/*
+ *  円描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x0: X position
+ *  param3  y0: Y position
+ *  param4  Radius: Circle radius
+ */
+void
+lcd_DrawCircle(LCD_DrawProp_t *pDrawProp, uint16_t x0, uint16_t y0, uint16_t Radius)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+ 	int32_t   decision;    /* Decision Variable */ 
+	uint32_t  current_x;   /* Current X Value */
+	uint32_t  current_y;   /* Current Y Value */
+
+	decision = 3 - (Radius << 1);
+	current_x = 0;
+	current_y = Radius;
+
+	while(current_x <= current_y){
+		lcd_drawPixel(hlcd, (x0 + current_x), (y0 - current_y), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 - current_x), (y0 - current_y), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 + current_y), (y0 - current_x), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 - current_y), (y0 - current_x), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 + current_x), (y0 + current_y), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 - current_x), (y0 + current_y), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 + current_y), (y0 + current_x), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 - current_y), (y0 + current_x), pDrawProp->TextColor);
+
+		if (decision < 0){
+			decision += (current_x << 2) + 6;
+		}
+		else{
+			decision += ((current_x - current_y) << 2) + 10;
+			current_y--;
+		}
+		current_x++;
+	}
+}
+
+/*
+ *  線描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x1: Point 1 X position
+ *  param3  y1: Point 1 Y position
+ *  param4  x2: Point 2 X position
+ *  param5  y2: Point 2 Y position
+ */
+void
+lcd_drawLine(LCD_DrawProp_t *pDrawProp, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0, 
+	yinc1 = 0, yinc2 = 0, den = 0, num = 0, num_add = 0, num_pixels = 0, 
+	curpixel = 0;
+
+	deltax = ABS(x2 - x1);		/* The difference between the x's */
+	deltay = ABS(y2 - y1);		/* The difference between the y's */
+	x = x1;						/* Start x off at the first pixel */
+	y = y1;						/* Start y off at the first pixel */
+
+	if(x2 >= x1){				/* The x-values are increasing */
+		xinc1 = 1;
+		xinc2 = 1;
+	}
+	else{						/* The x-values are decreasing */
+		xinc1 = -1;
+		xinc2 = -1;
+	}
+
+	if(y2 >= y1){				/* The y-values are increasing */
+		yinc1 = 1;
+		yinc2 = 1;
+	}
+	else{						/* The y-values are decreasing */
+		yinc1 = -1;
+		yinc2 = -1;
+	}
+
+	if(deltax >= deltay){		/* There is at least one x-value for every y-value */
+		xinc1 = 0;				/* Don't change the x when numerator >= denominator */
+		yinc2 = 0;				/* Don't change the y for every iteration */
+		den = deltax;
+		num = deltax / 2;
+		num_add = deltay;
+		num_pixels = deltax;	/* There are more x-values than y-values */
+	}
+	else{						/* There is at least one y-value for every x-value */
+		xinc2 = 0;				/* Don't change the x for every iteration */
+		yinc1 = 0;				/* Don't change the y when numerator >= denominator */
+		den = deltay;
+		num = deltay / 2;
+		num_add = deltax;
+		num_pixels = deltay;	/* There are more y-values than x-values */
+	}
+
+	for (curpixel = 0; curpixel <= num_pixels; curpixel++){
+		lcd_drawPixel(hlcd, x, y, pDrawProp->TextColor);	/* Draw the current pixel */
+		num += num_add;			/* Increase the numerator by the top of the fraction */
+		if(num >= den){			/* Check if numerator >= denominator */
+			num -= den;			/* Calculate the new numerator value */
+			x += xinc1;			/* Change the x as appropriate */
+			y += yinc1;			/* Change the y as appropriate */
+		}
+		x += xinc2;				/* Change the x as appropriate */
+		y += yinc2;				/* Change the y as appropriate */
+	}
+}
+
+/*
+ *  PLOY-LINE描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  Points: Pointer to the points array
+ *  param3  PointCount: Number of points
+ */
+void
+lcd_drawPolygon(LCD_DrawProp_t *pDrawProp, pPoint Points, uint16_t PointCount)
+{
+	int16_t x = 0, y = 0;
+
+	if(PointCount < 2){
+		return;
+	}
+
+	lcd_drawLine(pDrawProp, Points->X, Points->Y, (Points+PointCount-1)->X, (Points+PointCount-1)->Y);
+	while(--PointCount){
+		x = Points->X;
+		y = Points->Y;
+		Points++;
+		lcd_drawLine(pDrawProp, x, y, Points->X, Points->Y);
+	}
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/aqm1248_st7565/aqm1248_st7565.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/aqm1248_st7565/aqm1248_st7565.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/aqm1248_st7565/aqm1248_st7565.h	(revision 453)
@@ -0,0 +1,175 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ *
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ *
+ *  $Id$
+ */
+
+/*
+ *  AQM1248 ST7565 LCD制御プログラムのヘッダファイル
+ */
+
+#ifndef _AQM1248_ST7565_H_
+#define _AQM1248_ST7565_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include "device.h"
+#include "pinmode.h"
+#include "spi.h"
+
+/*
+ *  LCDカラーモード定義
+ */
+#define CM_ARGB8888         0x00000000			/* ARGB8888 color mode */
+#define CM_RGB888           0x00000001			/* RGB888 color mode */
+#define CM_RGB565           0x00000002			/* RGB565 color mode */
+
+#define AQM1248_WIDTH  128
+#define AQM1248_HEIGHT 48
+#define AQM1248_PLINE  8
+
+#define ST7565_COLADR  0x10
+#define ST7565_RATSEL  0x20
+#define ST7565_PWRSEL  0x28
+#define ST7565_STRLINE 0x40
+#define ST7565_SETEVOL 0x81
+
+#define ST7565_ADCSELN 0xA0
+#define ST7565_ADCSELR 0xA1
+#define ST7565_BIAS19  0xA2
+#define ST7565_BIAS17  0xA3
+#define ST7565_ALLPNL  0xA4
+#define ST7565_ALLPON  0xA5
+#define ST7565_DISPNOR 0xA6
+#define ST7565_DISPREV 0xA7
+#define ST7565_DISPOFF 0xAE
+#define ST7565_DISPON  0xAF
+#define ST7565_PAGEADR 0xB0
+
+#define ST7565_COMOUTN 0xC0
+#define ST7565_COMOUTR 0xC8
+#define ST7565_NOP     0xE3
+
+// Color definitions
+#define	ST7565_BLACK   0x00
+#define	ST7565_BLUE    0x01
+#define	ST7565_GREEN   0x02
+#define ST7565_CYAN    0x03
+#define	ST7565_RED     0x04
+#define ST7565_MAGENTA 0x05
+#define ST7565_YELLOW  0x06
+#define ST7565_WHITE   0x07
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  カラーの属性を定義
+ */
+typedef uint16_t   color_t;
+
+
+/*
+ *  LCDハンドラ構造体定義
+ */
+typedef struct
+{
+	SPI_Handle_t            *hspi;		/* spiハンドラ */
+	uint16_t                _width;		/* 幅ピクセル数 */
+	uint16_t				_height;	/* 高さピクセル数 */
+	uint16_t                _winx1;
+	uint16_t                _winy1;
+	uint16_t                _winx2;
+	uint16_t                _winy2;
+	ID                      spi_lock;
+	uint8_t                 cs_pin;
+	uint8_t                 rs_pin;
+	uint8_t                 rst_pin;
+	uint8_t                 lmask;
+	uint8_t                 rmask;
+	uint8_t                 stride;
+	uint8_t                 dummy[2];
+	uint8_t                 buffer[AQM1248_HEIGHT][AQM1248_WIDTH/8];
+}LCD_Handler_t;
+
+/*
+ *  描画構造体
+ */
+typedef struct
+{
+	LCD_Handler_t           *hlcd;
+	color_t                 TextColor;
+	color_t                 BackColor;
+	void                    *pFont;
+}LCD_DrawProp_t;
+
+typedef struct
+{
+	int16_t X;
+	int16_t Y;
+}Point, * pPoint;
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+extern ER lcd_writecommand(LCD_Handler_t *hlcd, uint8_t c);
+extern ER lcd_writedata(LCD_Handler_t *hlcd, uint8_t c);
+
+extern void lcd_init(LCD_Handler_t *hlcd);
+extern void lcd_setAddrWindow(LCD_Handler_t *hlcd, uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1);
+extern void lcd_fillRect(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t w, int16_t h, color_t color);
+extern void lcd_pushColor(LCD_Handler_t *hlcd, color_t color);
+extern void lcd_drawPixel(LCD_Handler_t *hlcd, int16_t x, int16_t y, color_t color);
+extern void lcd_drawFastVLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t h, color_t color);
+extern void lcd_drawFastHLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t w, color_t color);
+extern void lcd_drawImageHLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, uint16_t w, color_t *pcolor);
+extern void lcd_drawBitmap(LCD_Handler_t *hlcd, uint16_t x0, uint16_t y0, uint8_t *pbmp);
+extern void lcd_invertDisplay(LCD_Handler_t *hlcd, bool_t i);
+
+extern void lcd_fillScreen(LCD_DrawProp_t *pDrawProp);
+extern void lcd_drawRect(LCD_DrawProp_t *pDrawProp, int16_t x, int16_t y, int16_t w, int16_t h);
+extern void lcd_DrawCircle(LCD_DrawProp_t *pDrawProp, uint16_t x0, uint16_t y0, uint16_t Radius);
+extern void lcd_drawLine(LCD_DrawProp_t *pDrawProp, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
+extern void lcd_drawPolygon(LCD_DrawProp_t *pDrawProp, pPoint Points, uint16_t PointCount);
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _AQM1248_ST7565_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/aqm1248_st7565/glcd_core.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/aqm1248_st7565/glcd_core.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/aqm1248_st7565/glcd_core.h	(revision 453)
@@ -0,0 +1,45 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+#ifndef _LCD_CORE_H_
+#define _LCD_CORE_H_
+
+#include "aqm1248_st7565.h"
+
+#endif /* _LCD_CORE_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/BLEAttribute.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/BLEAttribute.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/BLEAttribute.h	(revision 453)
@@ -0,0 +1,114 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+The MIT License (MIT)
+
+Copyright (c) 2014 Sandeep Mistry
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#ifndef _BLE_ATTRIBUTE_H_
+#define _BLE_ATTRIBUTE_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+enum BLEAttributeType {
+	BLETypeService        = 0x2800,
+	BLETypeCharacteristic = 0x2803,
+	BLETypeDescriptor     = 0x2900
+};
+
+enum BLEProperty {
+	BLERead                 = 0x02,
+	BLEWriteWithoutResponse = 0x04,
+	BLEWrite                = 0x08,
+	BLENotify               = 0x10,
+	BLEIndicate             = 0x20
+};
+
+#define MAX_UUID_LENGTH                   16
+#define BLE_ATTRIBUTE_MAX_VALUE_LENGTH    19
+
+typedef struct _nRF8001 nRF8001;
+
+typedef struct _BLEUuid {
+  const char *   _str;
+  unsigned char  _data[MAX_UUID_LENGTH];
+  unsigned char  _length;
+} BLEUuid;
+
+
+typedef struct _BLEAttribute {
+  BLEUuid               _uuid;
+  enum BLEAttributeType _type;
+} BLEAttribute;
+
+#define BLEService  BLEAttribute
+
+typedef struct _BLEDescriptor {
+  BLEAttribute          _attr;
+  unsigned char         _valueSize;
+  unsigned char*        _value;
+  unsigned char         _valueLength;
+} BLEDescriptor;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _BLE_ATTRIBUTE_H_ */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/BLECentral.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/BLECentral.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/BLECentral.c	(revision 453)
@@ -0,0 +1,134 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+The MIT License (MIT)
+
+Copyright (c) 2014 Sandeep Mistry
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#include <utility/lib_aci.h>
+#include <utility/aci_setup.h>
+#include "BLECentral.h"
+#include "BLECharacteristic.h"
+#include "BLEPeripheral.h"
+
+/*
+ *  BLECentral接続判定
+ */
+bool_t
+BLECentral_connected(BLECentral *pcent)
+{
+	BLEPeripheral *pblep = pcent->_peripheral;
+	if(pblep == NULL)
+		return false;
+	BLECentral_poll(pcent);
+	return pcent->_connected;
+}
+
+/*
+ *  BLECentralポーリング
+ */
+void
+BLECentral_poll(BLECentral *pcent)
+{
+	BLEPeripheral *pblep = pcent->_peripheral;
+	if(pblep == NULL)
+		return;
+	BLEPeripheral_poll(pblep);
+}
+
+/*
+ *  BLECentral切断
+ */
+void
+BLECentral_disconnect(BLECentral *pcent)
+{
+	BLEPeripheral *pblep = pcent->_peripheral;
+	if(pblep == NULL)
+		return;
+	if(BLECentral_connected(pcent)){
+		nRF8001_disconnect(&pblep->_nRF8001);
+	}
+}
+
+/*
+ *  BLECentralアドレス設定
+ */
+void
+BLECentral_setAddress(BLECentral *pcent, const uint8_t *address)
+{
+	memcpy(pcent->_address, address, sizeof(pcent->_address));
+}
+
+/*
+ *  BLECentralアドレスクリア
+ */
+void
+BLECentral_clearAddress(BLECentral *pcent)
+{
+	memset(pcent->_address, 0x00, sizeof(pcent->_address));
+}
+
+/*
+ *  BLECentralアドレス比較
+ */
+bool_t
+BLECentral_cmpAddress(BLECentral *pcent, const uint8_t *address)
+{
+	return (memcmp(pcent->_address, address, sizeof(pcent->_address)) == 0);
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/BLECentral.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/BLECentral.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/BLECentral.h	(revision 453)
@@ -0,0 +1,87 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+The MIT License (MIT)
+
+Copyright (c) 2014 Sandeep Mistry
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#ifndef _BLE_CENTRAL_H_
+#define _BLE_CENTRAL_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+typedef struct _BLECentral {
+	void*          _peripheral;	/* BLEPeripheral */
+	bool_t         _connected;
+	unsigned char  _address[6];
+} BLECentral;
+
+extern bool_t BLECentral_connected(BLECentral *pcent);
+extern void BLECentral_poll(BLECentral *pcent);
+extern void BLECentral_disconnect(BLECentral *pcent);
+extern void BLECentral_setAddress(BLECentral *pcent, const uint8_t *address);
+extern void BLECentral_clearAddress(BLECentral *pcent);
+extern bool_t BLECentral_cmpAddress(BLECentral *pcent, const uint8_t *address);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/BLECharacteristic.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/BLECharacteristic.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/BLECharacteristic.c	(revision 453)
@@ -0,0 +1,263 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+The MIT License (MIT)
+
+Copyright (c) 2014 Sandeep Mistry
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#include <stdlib.h>
+#include <utility/lib_aci.h>
+#include <utility/aci_setup.h>
+#include "BLECentral.h"
+#include "BLECharacteristic.h"
+#include "BLEPeripheral.h"
+
+#define MIN(a, b) ((a) > (b) ? (b) : (a))
+
+static unsigned int
+convert_hex(const char a)
+{
+	if(a >= '0' && a <= '9')
+		return a - '0';
+	else if(a >= 'A' && a <= 'F')
+		return a - 'A' + 10;
+	else if(a >= 'a' && a <= 'f')
+		return a - 'a' + 10;
+	else
+		return 0;
+}
+
+static int
+uuid_setup(BLEUuid* puuid, const char *str)
+{
+  int i, len = 0;
+
+  puuid->_str = str;
+  puuid->_length = 0;
+  for (i = strlen(str) - 1; i >= 0 && puuid->_length < MAX_UUID_LENGTH; i -= 2) {
+    if (str[i] == '-') {
+      i++;
+      continue;
+    }
+
+	len = convert_hex(str[i - 1]) << 4;
+	len |= convert_hex(str[i]);
+	puuid->_data[puuid->_length] = len;
+
+    puuid->_length++;
+  }
+  return puuid->_length;
+}
+
+/*
+ *  BLEServiceセットアップ
+ */
+void
+BLEService_setup(BLEService* pserv, const char *uuid)
+{
+	uuid_setup(&pserv->_uuid, uuid);
+	pserv->_type = BLETypeService;
+}
+
+/*
+ *  BLECharacteristicセットアップ
+ */
+void
+BLECharacteristic_setup(BLECharacteristic* pcharc, const char *uuid, unsigned char properties, unsigned char *value, unsigned char len)
+{
+	memset(pcharc, 0, sizeof(BLECharacteristic));
+	uuid_setup(&pcharc->_attr._uuid, uuid);
+	pcharc->_attr._type  = BLETypeCharacteristic;
+	pcharc->_properties  = properties;
+	pcharc->_valueSize   = MIN(BLE_ATTRIBUTE_MAX_VALUE_LENGTH, len);
+	pcharc->_value = value;
+	pcharc->_valueLength = 0;
+	pcharc->_fixedLength = 0;
+	pcharc->_notify      = false;
+	pcharc->_written     = false;
+	pcharc->_subscribed  = false;
+}
+
+/*
+ *  BLECharacteristic値設定(値の長さあり)
+ */
+bool_t
+BLECharacteristic_setValue1(BLECharacteristic *pcharc, const unsigned char value[], unsigned char length)
+{
+	bool_t success = true;
+
+	if(length > pcharc->_valueSize)
+		pcharc->_valueLength = pcharc->_valueSize;
+	else
+		pcharc->_valueLength = length;
+
+	memcpy(pcharc->_value, value, pcharc->_valueLength);
+
+	if(pcharc->characteristicValueChanged != NULL){
+		BLEPeripheral *pblep = pcharc->_pblePeripheral;
+		success = pcharc->characteristicValueChanged(&pblep->_nRF8001, pcharc);
+	}
+	return success;
+}
+
+/*
+ *  BLECharacteristic 値設定(値の長さなし)
+ */
+bool_t
+BLECharacteristic_setValue2(BLECharacteristic *pcharc, const char* value)
+{
+	return BLECharacteristic_setValue1(pcharc, (const unsigned char *)value, strlen(value));
+}
+
+/*
+ *  BLECharacteristic 値設定(設定後通知)
+ */
+void
+BLECharacteristic_setValue(BLECharacteristic *pcharc, BLECentral* central, const unsigned char value[], unsigned char length)
+{
+	BLECharacteristicEventHandler eventHandler = pcharc->_eventHandlers[BLEWritten];
+
+	BLECharacteristic_setValue1(pcharc, value, length);
+	pcharc->_written = true;
+	if(eventHandler != NULL)
+		eventHandler(central, pcharc);
+}
+
+/*
+ *  BLECharacteristic 通知確認
+ */
+bool_t
+BLECharacteristic_notified(BLECharacteristic *pcharc)
+{
+	bool_t notify = pcharc->_notify;
+
+	if(notify){
+		pcharc->_notify = false;
+	}
+	return notify;
+}
+
+/*
+ *  BLECharacteristic 書き込み確認
+ */
+bool_t
+BLECharacteristic_written(BLECharacteristic *pcharc)
+{
+	bool_t written = pcharc->_written;
+
+	if(written){
+		pcharc->_written = false;
+	}
+	return written;
+}
+
+
+/*
+ *  BLECharacteristic Subscribed設定
+ */
+void
+BLECharacteristic_setSubscribed(BLECharacteristic *pcharc, BLECentral* central, bool_t subscribed)
+{
+	BLECharacteristicEventHandler eventHandler = pcharc->_eventHandlers[subscribed ? BLESubscribed : BLEUnsubscribed];
+
+	pcharc->_subscribed = subscribed;
+	if(eventHandler != NULL)
+		eventHandler(central, pcharc);
+}
+
+/*
+ *  BLECharacteristic Notify可能判定
+ */
+bool_t
+BLECharacteristic_canNotify(BLECharacteristic *pcharc)
+{
+	BLEPeripheral *pblep = pcharc->_pblePeripheral;
+	if(pblep == NULL)
+		return false;
+	if(pcharc->canNotifyCharacteristic != NULL)
+		return pcharc->canNotifyCharacteristic(&pblep->_nRF8001, pcharc);
+	else
+		return false;
+}
+
+/*
+ *  BLECharacteristic Indicate可能判定
+ */
+bool_t
+BLECharacteristic_canIndicate(BLECharacteristic *pcharc)
+{
+	BLEPeripheral *pblep = pcharc->_pblePeripheral;
+	if(pblep == NULL)
+		return false;
+	if(pcharc->canIndicateCharacteristic != NULL)
+		return pcharc->canIndicateCharacteristic(&pblep->_nRF8001, pcharc);
+	else
+		return false;
+}
+
+/*
+ *  BLECharacteristic コールバック関数設定
+ */
+void
+BLECharacteristic_setEventHandler(BLECharacteristic *pcharc, uint8_t event, void *eventHandler)
+{
+	if(event < 3){
+		pcharc->_eventHandlers[event] = eventHandler;
+	}
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/BLECharacteristic.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/BLECharacteristic.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/BLECharacteristic.h	(revision 453)
@@ -0,0 +1,125 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+The MIT License (MIT)
+
+Copyright (c) 2014 Sandeep Mistry
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#ifndef _BLE_CHARACTERISTIC_H_
+#define _BLE_CHARACTERISTIC_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include "BLEAttribute.h"
+
+enum BLECharacteristicEvent {
+	BLEWritten = 0,
+	BLESubscribed = 1,
+	BLEUnsubscribed = 2
+};
+
+typedef struct _BLECharacteristic BLECharacteristic;
+typedef void (*BLECharacteristicEventHandler)(BLECentral* central, BLECharacteristic *pcharc);
+
+struct _BLECharacteristic{
+	BLEAttribute          _attr;
+	unsigned char         _properties;
+	unsigned char         _valueSize;
+	unsigned char*        _value;
+	unsigned char         _valueLength;
+	bool_t                _fixedLength;
+
+	bool_t                _notify;
+	bool_t                _written;
+	bool_t                _subscribed;
+
+	void*                 _pblePeripheral;
+	bool_t (*characteristicValueChanged)(nRF8001* nRF8001, BLECharacteristic *pcharc);
+	bool_t (*canNotifyCharacteristic)(nRF8001* nRF8001, BLECharacteristic *pcharc);
+	bool_t (*canIndicateCharacteristic)(nRF8001* nRF8001, BLECharacteristic *pcharc);
+
+	BLECharacteristicEventHandler  _eventHandlers[3];
+};
+
+#define BLECharacteristic_getproperties(c)   (c)->_properties
+#define BLECharacteristic_getvalueSize(c)    (c)->_valueSize
+#define BLECharacteristic_getvalue(c)        (c)->_value
+#define BLECharacteristic_getvalueLength(c)  (c)->_valueLength
+#define BLECharacteristic_getfixedLength(c)  (c)->_fixedLength
+#define BLECharacteristic_getsubscribed(c)   (c)->_subscribed
+
+
+extern void BLEService_setup(BLEService* pserv, const char *uuid);
+extern void BLECharacteristic_setup(BLECharacteristic* pcharc, const char *uuid, unsigned char properties, unsigned char *value, unsigned char len);
+extern bool_t BLECharacteristic_setValue1(BLECharacteristic *pcharc, const unsigned char value[], unsigned char length);
+extern bool_t BLECharacteristic_setValue2(BLECharacteristic *pcharc, const char* value);
+extern bool_t BLECharacteristic_notified(BLECharacteristic *pcharc);
+extern bool_t BLECharacteristic_written(BLECharacteristic *pcharc);
+extern void BLECharacteristic_setValue(BLECharacteristic *pcharc, BLECentral* central, const unsigned char value[], unsigned char length);
+extern void BLECharacteristic_setSubscribed(BLECharacteristic *pcharc, BLECentral* central, bool_t subscribed);
+extern bool_t BLECharacteristic_canNotify(BLECharacteristic *pcharc);
+extern bool_t BLECharacteristic_canIndicate(BLECharacteristic *pcharc);
+extern void BLECharacteristic_setEventHandler(BLECharacteristic *pcharc, uint8_t event, void *eventHandler);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _BLE_CHARACTERISTIC_H_ */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/BLEPeripheral.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/BLEPeripheral.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/BLEPeripheral.c	(revision 453)
@@ -0,0 +1,487 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+The MIT License (MIT)
+
+Copyright (c) 2014 Sandeep Mistry
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#include <utility/lib_aci.h>
+#include <utility/aci_setup.h>
+#include "BLECentral.h"
+#include "BLECharacteristic.h"
+#include "BLEPeripheral.h"
+
+
+#define DEFAULT_DEVICE_NAME "Arduino"
+#define DEFAULT_APPEARANCE  0x0000
+
+static unsigned char _devicevalue[NUM_DEVICE_NAME];
+static unsigned char _appearvalue[NUM_APPEAR_VALUE];
+static unsigned char _servicevalue[NUM_SERVICE_VALUE];
+
+static BLEService _genericAccessService = {
+	{"1800", {0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 2},
+	BLETypeService
+};
+
+static BLECharacteristic _deviceNameCharacteristic = {
+	{{"2a00", {0x00, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 2},
+	BLETypeCharacteristic},
+	BLERead,        /* _properties */
+	19,             /* _valueSize */
+	_devicevalue,   /* _value */
+	0,              /* _valueLength */
+	0,              /* _fixedLength */
+	false,          /* _notify */
+	false,          /* _written */
+	false,          /* _subscribed */
+	NULL,           /* _pblePeripheral */
+	NULL,           /* characteristicValueChanged */
+	NULL,           /* canNotifyCharacteristic */
+	NULL,           /* canIndicateCharacteristic */
+	{0, 0, 0}       /* _eventHandlers[3] */
+};
+
+static BLECharacteristic _appearanceCharacteristic = {
+	{{"2a01", {0x01, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 2},
+	BLETypeCharacteristic},
+	BLERead,        /* _properties */
+	2,              /* _valueSize */
+	_appearvalue,   /* _value */
+	0,              /* _valueLength */
+	0,              /* _fixedLength */
+	false,          /* _notify */
+	false,          /* _written */
+	false,          /* _subscribed */
+	NULL,           /* _pblePeripheral */
+	NULL,           /* characteristicValueChanged */
+	NULL,           /* canNotifyCharacteristic */
+	NULL,           /* canIndicateCharacteristic */
+	{0, 0, 0}       /* _eventHandlers[3] */
+};
+
+static BLEService _genericAttributeService = {
+	{"1801", {0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 2},
+	BLETypeService
+};
+
+static BLECharacteristic _servicesChangedCharacteristic = {
+	{{"2a05", {0x05, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 2},
+	BLETypeCharacteristic},
+	BLEIndicate,    /* _properties */
+	4,              /* _valueSize */
+	_servicevalue,  /* _value */
+	0,              /* _valueLength */
+	0,              /* _fixedLength */
+	false,          /* _notify */
+	false,          /* _written */
+	false,          /* _subscribed */
+	NULL,           /* _pblePeripheral */
+	NULL,           /* characteristicValueChanged */
+	NULL,           /* canNotifyCharacteristic */
+	NULL,           /* canIndicateCharacteristic */
+	{0, 0, 0}       /* _eventHandlers[3] */
+};
+
+static bool_t
+BLEPeripheral_characteristicValueChanged(nRF8001* nRF8001, BLECharacteristic *pcharc)
+{
+	return nRF8001_updateCharacteristicValue(nRF8001, pcharc);
+}
+
+static bool_t
+BLEPeripheral_canNotifyCharacteristic(nRF8001* nRF8001, BLECharacteristic *pcharc)
+{
+	return nRF8001_canNotifyCharacteristic(nRF8001, pcharc);
+}
+
+static bool_t
+BLEPeripheral_canIndicateCharacteristic(nRF8001* nRF8001, BLECharacteristic *pcharc)
+{
+	return nRF8001_canIndicateCharacteristic(nRF8001, pcharc);
+}
+
+
+/*
+ *  BLEPeripheralのセットアップ
+ */
+void
+BLEPeripheral_setup(BLEPeripheral *pblep, unsigned char req, unsigned char rdy, unsigned char rst)
+{
+	memset(pblep, 0, sizeof(BLEPeripheral));
+	pblep->_nRF8001._aciState.aci_pins.reqn_pin = req;
+	pblep->_nRF8001._aciState.aci_pins.rdyn_pin = rdy;
+	pblep->_nRF8001._aciState.aci_pins.reset_pin = rst;
+
+	pblep->_nRF8001._aciState.aci_pins.board_name = BOARD_DEFAULT;
+	pblep->_nRF8001._aciState.aci_pins.active_pin  = UNUSED;
+	pblep->_nRF8001._aciState.aci_pins.optional_chip_sel_pin = UNUSED;
+	pblep->_nRF8001._aciState.aci_pins.interface_is_interrupt = false;
+	pblep->_nRF8001._aciState.aci_pins.event_taskid = 0;
+	pblep->_nRF8001._pipeInfo = NULL;
+	pblep->_nRF8001._numPipeInfo = 0;
+	pblep->_nRF8001._crcSeed = 0xFFFF;
+	pblep->_nRF8001._pblePeripheral = pblep;
+
+	pblep->_attributes[0] = &_genericAccessService;
+	_deviceNameCharacteristic._valueLength = strlen(DEFAULT_DEVICE_NAME);
+	memcpy(_devicevalue, DEFAULT_DEVICE_NAME, _deviceNameCharacteristic._valueLength);
+	_deviceNameCharacteristic._pblePeripheral = pblep;
+	pblep->_attributes[1] = (BLEAttribute*)&_deviceNameCharacteristic;
+	_appearanceCharacteristic._pblePeripheral = pblep;
+	pblep->_attributes[2] = (BLEAttribute*)&_appearanceCharacteristic;
+	pblep->_attributes[3] = &_genericAttributeService;
+	_servicesChangedCharacteristic._pblePeripheral = pblep;
+	pblep->_attributes[4] = (BLEAttribute*)&_servicesChangedCharacteristic;
+	pblep->_numAttributes = 5;
+	pblep->_central._peripheral = pblep;
+	pblep->_central._connected  = false;
+	memset(pblep->_central._address, 0x00, 6);
+
+	pblep->_manufacturerData = NULL;
+	pblep->_manufacturerDataLength = 0;
+}
+
+/*
+ *  BLEPeripheral開始
+ */
+void
+BLEPeripheral_begin(BLEPeripheral *pblep)
+{
+	uint8_t advertisementData[20];
+	uint8_t scanData[20];
+	uint8_t advertisementDataLength = 0;
+	uint8_t scanDataLength = 0;
+	int i;
+
+	if(pblep->_advertisedServiceUuid){
+		unsigned char advertisedServiceUuidLength = sizeof(pblep->_advertisedServiceUuid);
+		advertisementDataLength = 2 + advertisedServiceUuidLength;
+		advertisementData[0] = (advertisedServiceUuidLength > 2) ? 0x06 : 0x02;
+		advertisementData[1] = advertisedServiceUuidLength;
+		memcpy(&advertisementData[2], pblep->_advertisedServiceUuid, advertisedServiceUuidLength);
+	}
+	else if(pblep->_manufacturerData && pblep->_manufacturerDataLength > 0) {
+		if(pblep->_manufacturerDataLength > sizeof(advertisementData))
+			pblep->_manufacturerDataLength = sizeof(advertisementData);
+
+		advertisementDataLength = 2 + pblep->_manufacturerDataLength;
+		advertisementData[0] = 0xff;
+		advertisementData[1] = pblep->_manufacturerDataLength;
+		memcpy(&advertisementData[2], pblep->_manufacturerData, pblep->_manufacturerDataLength);
+	}
+
+	if(pblep->_localName){
+		unsigned char originalLocalNameLength = strlen(pblep->_localName);
+		unsigned char localNameLength = originalLocalNameLength;
+
+		if(localNameLength > sizeof(scanData))
+			localNameLength = sizeof(scanData);
+		scanDataLength = 2 + localNameLength;
+		scanData[0] = (originalLocalNameLength > sizeof(scanData)) ? 0x08 : 0x09;
+		scanData[1] = localNameLength;
+		memcpy(&scanData[2], pblep->_localName, localNameLength);
+	}
+
+	for(i = 0 ; i < pblep->_numAttributes ; i++){
+		BLEAttribute* attribute = pblep->_attributes[i];
+		if(attribute->_type == BLETypeCharacteristic){
+			BLECharacteristic* pcharc = (BLECharacteristic*)attribute;
+			pcharc->characteristicValueChanged = BLEPeripheral_characteristicValueChanged;
+			pcharc->canNotifyCharacteristic    = BLEPeripheral_canNotifyCharacteristic;
+			pcharc->canIndicateCharacteristic  = BLEPeripheral_canIndicateCharacteristic;
+		}
+	}
+
+	nRF8001_begin(&pblep->_nRF8001, advertisementData, advertisementDataLength, scanData, scanDataLength, pblep->_attributes, pblep->_numAttributes);
+	nRF8001_requestAddress();
+}
+
+/*
+ *  BLEPeripheralの状態ポーリング
+ */
+void
+BLEPeripheral_poll(BLEPeripheral *pblep)
+{
+	nRF8001_poll(&pblep->_nRF8001);
+}
+
+/*
+ *  BLEPeripheral UUIDのセット
+ */
+void
+BLEPeripheral_setAdvertisedServiceUuid(BLEPeripheral *pblep, const char* advertisedServiceUuid)
+{
+	pblep->_advertisedServiceUuid = advertisedServiceUuid;
+}
+
+/*
+ *  BLEPeripheral MANUFACURER DATAのセット
+ */
+void
+BLEPeripheral_setManufacturerData(BLEPeripheral *pblep, const unsigned char manufacturerData[], unsigned char manufacturerDataLength)
+{
+	pblep->_manufacturerData = manufacturerData;
+	pblep->_manufacturerDataLength = manufacturerDataLength;
+}
+
+/*
+ *  BLEPeripheral LOCAL NAMEのセット
+ */
+void
+BLEPeripheral_setLocalName(BLEPeripheral *pblep, const char* localName)
+{
+	pblep->_localName = localName;
+}
+
+/*
+ *  BLEPeripheral ATTRIBUTEの追加
+ */
+void
+BLEPeripheral_addAttribute(BLEPeripheral *pblep, BLEAttribute* attribute)
+{
+	if(attribute->_type == BLETypeCharacteristic){
+		BLECharacteristic *pcharc = (BLECharacteristic*)attribute;
+		pcharc->_pblePeripheral = pblep;
+	}
+	pblep->_attributes[pblep->_numAttributes++] = attribute;
+}
+
+/*
+ *  BLEPeripheral DEVICENMAEのセット
+ */
+void
+BLEPeripheral_setDeviceName(BLEPeripheral *pblep, const char* deviceName)
+{
+	BLECharacteristic_setValue2(&_deviceNameCharacteristic, deviceName);
+}
+
+/*
+ *  BLEPeripheral APPEARANCEのセット
+ */
+void
+BLEPeripheral_setAppearance(BLEPeripheral *pblep, unsigned short appearance)
+{
+	BLECharacteristic_setValue1(&_appearanceCharacteristic, (unsigned char *)&appearance, sizeof(appearance));
+}
+
+/*
+ *  BLEPeripheral切断
+ */
+void
+BLEPeripheral_disconnect(BLEPeripheral *pblep)
+{
+	nRF8001_disconnect(&pblep->_nRF8001);
+}
+
+/*
+ *  BLEPeripheral セントラル構造体の取り出し
+ */
+BLECentral *
+BLEPeripheral_central(BLEPeripheral *pblep)
+{
+	BLEPeripheral_poll(pblep);
+	return &pblep->_central;
+}
+
+/*
+ *  BLEPeripheral セントラル接続判定
+ */
+bool_t
+BLEPeripheral_connected(BLEPeripheral *pblep)
+{
+	BLEPeripheral_poll(pblep);
+	return BLECentral_connected(&pblep->_central);
+}
+
+/*
+ *  BLEPeripheral ペリフェラルのイベントハンドラを設定
+ */
+void
+BLEPeripheral_setEventHandler(BLEPeripheral *pblep, uint8_t event, BLEPeripheralEventHandler eventHandler)
+{
+	if(event < 2){
+		pblep->_eventHandlers[event] = eventHandler;
+	}
+}
+
+/*
+ *  BLEPeripheral バージョン取得
+ */
+bool_t
+BLEPeripheral_version(BLEPeripheral *pblep)
+{
+	return lib_aci_device_version();
+}
+
+
+/*
+ *  nRF8001Connectedデフォルトコールバック関数
+ */
+void
+BLEPeripheral_nRF8001Connected(nRF8001* nRF8001, const unsigned char* address)
+{
+	BLEPeripheral *pblep = nRF8001->_pblePeripheral;
+	memcpy(pblep->_central._address, address, 6);
+	pblep->_central._connected = true;
+
+#ifdef BLE_PERIPHERAL_DEBUG
+	syslog_5(LOG_NOTICE, "Peripheral connected to central:%02:%02:%02:%02:%02:XX ", address[0], address[1], address[2], address[3], address[4]);
+#endif
+
+	BLEPeripheralEventHandler eventHandler = pblep->_eventHandlers[BLEConnected];
+	if(eventHandler)
+		eventHandler(&pblep->_central);
+}
+
+/*
+ *  nRF8001Disconnectedデフォルトコールバック関数
+ */
+void
+BLEPeripheral_nRF8001Disconnected(nRF8001* nRF8001)
+{
+	BLEPeripheral *pblep = nRF8001->_pblePeripheral;
+#ifdef BLE_PERIPHERAL_DEBUG
+	unsigned char *address = pblep->_central._address;
+	syslog_5(LOG_NOTICE, "Peripheral disconnected from central:%02:%02:%02:%02:%02:XX ", address[0], address[1], address[2], address[3], address[4]);
+#endif
+
+	BLEPeripheralEventHandler eventHandler = pblep->_eventHandlers[BLEDisconnected];
+	if(eventHandler)
+		eventHandler(&pblep->_central);
+	pblep->_central._connected = false;
+}
+
+/*
+ *  nRF8001CharacteristicValueChangedデフォルトコールバック関数
+ */
+void
+BLEPeripheral_nRF8001CharacteristicValueChanged(nRF8001* nRF8001, BLECharacteristic *pcharc, const unsigned char* value, unsigned char valueLength)
+{
+	BLEPeripheral *pblep = nRF8001->_pblePeripheral;
+
+	if(valueLength > pcharc->_valueSize)
+		pcharc->_valueLength = pcharc->_valueSize;
+	else
+		pcharc->_valueLength = valueLength;
+	memcpy(pcharc->_value, value, pcharc->_valueLength);
+
+	pcharc->_notify  = true;
+	pcharc->_written = true;
+
+	BLECharacteristicEventHandler eventHandler = pcharc->_eventHandlers[BLEWritten];
+	if(eventHandler)
+		eventHandler(&pblep->_central, pcharc);
+}
+
+/*
+ *  nRF8001CharacteristicSubscribedChangedデフォルトコールバック関数
+ */
+void
+BLEPeripheral_nRF8001CharacteristicSubscribedChanged(nRF8001* nRF8001, BLECharacteristic *pcharc, bool_t subscribed)
+{
+	BLEPeripheral *pblep = nRF8001->_pblePeripheral;
+	pcharc->_subscribed = subscribed;
+
+	BLECharacteristicEventHandler eventHandler = pcharc->_eventHandlers[subscribed ? BLESubscribed : BLEUnsubscribed];
+
+	if(eventHandler)
+		eventHandler(&pblep->_central, pcharc);
+}
+
+/*
+ *  nRF8001AddressReceivedデフォルトコールバック関数
+ */
+void
+BLEPeripheral_nRF8001AddressReceived(nRF8001* nRF8001, const unsigned char* address)
+{
+#ifdef BLE_PERIPHERAL_DEBUG
+	syslog_5(LOG_NOTICE, "Peripheral address:%02:%02:%02:%02:%02:XX ", address[0], address[1], address[2], address[3], address[4]);
+#endif
+}
+
+/*
+ *  nRF8001TemperatureReceivedデフォルトコールバック関数
+ */
+void
+BLEPeripheral_nRF8001TemperatureReceived(nRF8001* nRF8001, float temperature)
+{
+#ifdef BLE_PERIPHERAL_DEBUG
+	int32_t  tmp1 = temperature;
+	uint32_t tmp2;
+
+	tmp2 = (temperature - tmp1) * 100;
+	syslog_2(LOG_NOTICE, "Temperature = %d.%02d", tmp1, tmp2);
+#endif
+}
+
+/*
+ *  nRF8001BatteryLevelReceivedデフォルトコールバック関数
+ */
+void
+BLEPeripheral_nRF8001BatteryLevelReceived(nRF8001* nRF8001, float batteryLevel)
+{
+#ifdef BLE_PERIPHERAL_DEBUG
+	int32_t tmp1 = batteryLevel;
+	uint32_t tmp2;
+
+	tmp2 = (batteryLevel - tmp1) * 10000;
+	syslog_2(LOG_NOTICE, "Battery level = %d.%04d", tmp1, tmp2);
+#endif
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/BLEPeripheral.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/BLEPeripheral.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/BLEPeripheral.h	(revision 453)
@@ -0,0 +1,179 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+The MIT License (MIT)
+
+Copyright (c) 2014 Sandeep Mistry
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#ifndef _BLEPERIPHERAL_H_
+#define _BLEPERIPHERAL_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#define MAX_ATTRIBUTE       32
+#define NB_BASE_SETUP_MESSAGES 7
+#define NUM_DEVICE_NAME     20
+#define NUM_APPEAR_VALUE    4
+#define NUM_SERVICE_VALUE   4
+
+#ifndef _BLE_ATTRIBUTE_H_
+typedef struct _nRF8001 nRF8001;
+#endif
+
+enum BLEPeripheralEvent {
+	BLEConnected = 0,
+	BLEDisconnected = 1
+};
+
+struct pipeInfo {
+	BLECharacteristic  *pcharc;
+
+	uint16_t           valueHandle;
+	uint16_t           configHandle;
+
+	uint8_t            startPipe;
+	uint8_t            txPipe;
+	uint8_t            txAckPipe;
+	uint8_t            rxPipe;
+	uint8_t            rxAckPipe;
+	uint8_t            setPipe;
+
+	bool_t             txPipeOpen;
+	bool_t             txAckPipeOpen;
+};
+
+struct _nRF8001 {
+	struct aci_state_t _aciState;
+	hal_aci_evt_t      _aciData;
+
+	void*              _pblePeripheral;
+	struct pipeInfo*   _pipeInfo;
+	uint8_t            _numPipeInfo;
+	uint16_t           _crcSeed;
+
+	void (*nRF8001Connected)(nRF8001* nRF8001, const unsigned char* address);
+	void (*nRF8001Disconnected)(nRF8001* nRF8001);
+	void (*nRF8001CharacteristicValueChanged)(nRF8001* nRF8001, BLECharacteristic *pcharc, const unsigned char* value, unsigned char valueLength);
+	void (*nRF8001CharacteristicSubscribedChanged)(nRF8001* nRF8001, BLECharacteristic *pcharc, bool_t subscribed);
+	void (*nRF8001AddressReceived)(nRF8001* nRF8001, const unsigned char* address);
+	void (*nRF8001TemperatureReceived)(nRF8001* nRF8001, float temperature);
+	void (*nRF8001BatteryLevelReceived)(nRF8001* nRF8001, float batteryLevel);
+};
+
+
+typedef void (*BLEPeripheralEventHandler)(BLECentral* central);
+
+typedef struct _BLEPeripheral {
+	nRF8001            _nRF8001;
+
+	const char         *_advertisedServiceUuid;
+	const uint8_t      *_manufacturerData;
+	uint8_t            _manufacturerDataLength;
+	const char*        _localName;
+
+	BLEAttribute*      _attributes[MAX_ATTRIBUTE];
+	uint8_t            _numAttributes;
+
+	BLECentral         _central;
+	BLEPeripheralEventHandler _eventHandlers[2];
+} BLEPeripheral;
+
+
+extern void nRF8001_begin(nRF8001* pnRF8001, const uint8_t *advertisementData, uint8_t advertisementDataLength, const uint8_t *scanData,
+                    uint8_t scanDataLength, BLEAttribute** attributes, uint8_t numAttributes);
+extern bool_t nRF8001_poll(nRF8001* pnRF8001);
+extern bool_t nRF8001_updateCharacteristicValue(nRF8001* pnRF8001, BLECharacteristic *pcharc);
+extern bool_t nRF8001_canNotifyCharacteristic(nRF8001* pnRF8001, BLECharacteristic* pcharc);
+extern bool_t nRF8001_canIndicateCharacteristic(nRF8001* pnRF8001, BLECharacteristic* pcharc);
+extern void nRF8001_disconnect(nRF8001* pnRF8001);
+extern void nRF8001_requestAddress(void);
+extern void nRF8001_requestTemperature(void);
+extern void nRF8001_requestBatteryLevel(void);
+extern void nRF8001_waitForSetupMode(nRF8001* pnRF8001);
+extern ER nRF8001_sendSetupMessage(nRF8001* pnRF8001, hal_aci_data_t* data);
+extern void nRF8001_sendCrc(nRF8001* pnRF8001);
+
+extern void BLEPeripheral_setup(BLEPeripheral *pblep, unsigned char req, unsigned char rdy, unsigned char rst);
+extern void BLEPeripheral_begin(BLEPeripheral *pblep);
+extern void BLEPeripheral_poll(BLEPeripheral *pblep);
+extern void BLEPeripheral_setAdvertisedServiceUuid(BLEPeripheral *pblep, const char* advertisedServiceUuid);
+extern void BLEPeripheral_setManufacturerData(BLEPeripheral *pblep, const unsigned char manufacturerData[], unsigned char manufacturerDataLength);
+extern void BLEPeripheral_setLocalName(BLEPeripheral *pblep, const char* localName);
+extern void BLEPeripheral_addAttribute(BLEPeripheral *pblep, BLEAttribute* attribute);
+extern void BLEPeripheral_setDeviceName(BLEPeripheral *pblep, const char* deviceName);
+extern void BLEPeripheral_setAppearance(BLEPeripheral *pblep, unsigned short appearance);
+extern void BLEPeripheral_disconnect(BLEPeripheral *pblep);
+extern BLECentral *BLEPeripheral_central(BLEPeripheral *pblep);
+extern bool_t BLEPeripheral_connected(BLEPeripheral *pblep);
+extern void BLEPeripheral_setEventHandler(BLEPeripheral *pblep, uint8_t event, BLEPeripheralEventHandler eventHandler);
+extern bool_t BLEPeripheral_version(BLEPeripheral *pblep);
+extern void BLEPeripheral_nRF8001Connected(nRF8001* nRF8001, const unsigned char* address);
+extern void BLEPeripheral_nRF8001Disconnected(nRF8001* nRF8001);
+extern void BLEPeripheral_nRF8001CharacteristicValueChanged(nRF8001* nRF8001, BLECharacteristic* pcharc, const unsigned char* value, unsigned char valueLength);
+extern void BLEPeripheral_nRF8001CharacteristicSubscribedChanged(nRF8001* nRF8001, BLECharacteristic* pcharc, bool_t subscribed);
+extern void BLEPeripheral_nRF8001AddressReceived(nRF8001* nRF8001, const unsigned char* address);
+extern void BLEPeripheral_nRF8001TemperatureReceived(nRF8001* nRF8001, float temperature);
+extern void BLEPeripheral_nRF8001BatteryLevelReceived(nRF8001* nRF8001, float batteryLevel);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _BLEPERIPHERAL_H_ */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/Makefile.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/Makefile.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/Makefile.config	(revision 453)
@@ -0,0 +1,57 @@
+#
+#   TOPPERS/ASP/FMP Kernel
+#       Toyohashi Open Platform for Embedded Real-Time Systems/
+#       Advanced Standard Profile Kernel
+#
+#   Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                               Toyohashi Univ. of Technology, JAPAN
+#   Copyright (C) 2003-2008 by Ryosuke Takeuchi
+#                Platform Development Center RICOH COMPANY,LTD. JAPAN
+#   Copyright (C) 2015-2018 by TOPPERS PROJECT Educational Working Group.
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+ 
+#
+#  Makefile のプロセッサ依存 (ble shield2.1用)
+#
+
+#
+#  コンパイルオプション
+#
+INCLUDES	:= $(INCLUDES) -I$(SRCDIR)/gdic/ble_shield2.1 -I$(SRCDIR)/gdic/ble_shield2.1/utility
+
+#
+#  モニターに関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR):$(SRCDIR)/gdic/ble_shield2.1:$(SRCDIR)/gdic/ble_shield2.1/utility
+SYSSVC_COBJS := $(SYSSVC_COBJS) aci_queue.o aci_setup.o acilib.o hal_aci_tl.o lib_aci.o \
+			BLECentral.o BLECharacteristic.o BLEPeripheral.o nRF8001.o
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/nRF8001.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/nRF8001.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/nRF8001.c	(revision 453)
@@ -0,0 +1,900 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+The MIT License (MIT)
+
+Copyright (c) 2014 Sandeep Mistry
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#include <utility/lib_aci.h>
+#include <utility/aci_setup.h>
+#include "BLECentral.h"
+#include "BLECharacteristic.h"
+#include "BLEPeripheral.h"
+
+
+#define ADVERTISING_INTERVAL 0x050
+
+struct setupMsgData {
+	uint8_t length;
+	uint8_t cmd;
+	uint8_t type;
+	uint8_t offset;
+	uint8_t data[28];
+};
+
+/*
+ *  nRF8001セットアップデータ
+ */
+static hal_aci_data_t baseSetupMsgs[NB_BASE_SETUP_MESSAGES] PROGMEM = {
+	{0x00,
+		{0x07,0x06,0x00,0x00,0x03,0x02,0x41,0xfe,},
+	},
+	{0x00,
+		{0x1f,0x06,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x06,0x00,0x06,
+		 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,},
+	},
+	{0x00,
+		{0x1f,0x06,0x10,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x90,0x00,0xff,},
+	},
+	{0x00,
+		{0x1f,0x06,0x10,0x38,0xff,0xff,0x02,0x58,0x0a,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x00,0x00,},
+	},
+	{0x00,
+		{0x05,0x06,0x10,0x54,0x00,0x02,},
+	},
+	{0x00,
+		{0x19,0x06,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0x00,0x00,0x00,0x00,0x00,0x00,},
+	},
+	{0x00,
+		{0x19,0x06,0x70,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0x00,0x00,0x00,0x00,0x00,0x00,},
+	},
+};
+
+static struct pipeInfo _pinfovalue[MAX_ATTRIBUTE];
+
+/*
+ *  CRC16計算
+ */
+static uint16_t
+crc_16_ccitt(uint16_t crc, uint8_t * data_in, uint16_t data_len)
+{
+	uint16_t i;
+
+	for(i = 0 ; i < data_len ; i++){
+		crc  = (unsigned char)(crc >> 8) | (crc << 8);
+		crc ^= data_in[i];
+		crc ^= (unsigned char)(crc & 0xff) >> 4;
+		crc ^= (crc << 8) << 4;
+		crc ^= ((crc & 0xff) << 4) << 1;
+	}
+	return crc;
+}
+
+/*
+ *  nRF8001開始
+ */
+void
+nRF8001_begin(nRF8001* pnRF8001, const uint8_t *advertisementData, uint8_t advertisementDataLength, const uint8_t *scanData,
+                      uint8_t scanDataLength, BLEAttribute** attributes, uint8_t numAttributes)
+{
+	hal_aci_data_t setupMsg;
+	struct setupMsgData *setupMsgData;
+	uint8_t   numPipedCharacteristics = 0;
+	uint8_t   pipeSetupMsgOffet  = 0;
+	uint8_t   gattSetupMsgOffset = 0;
+	uint16_t  handle             = 1;
+	uint8_t   pipe               = 1;
+	uint8_t   numPiped           = 0;
+	ER        ercd;
+	int       i;
+
+	for(i = 0 ; i < numAttributes ; i++){
+		BLEAttribute* attribute = attributes[i];
+
+		if(attribute->_type == BLETypeCharacteristic){
+			BLECharacteristic *pcharc = (BLECharacteristic *)attribute;
+
+			if(pcharc->_properties){
+				numPipedCharacteristics++;
+			}
+		}
+	}
+
+	pnRF8001->_pipeInfo = _pinfovalue;
+
+#if DEBUG == 0
+	lib_aci_init(&pnRF8001->_aciState, false);
+#else
+	lib_aci_init(&pnRF8001->_aciState, true);
+#endif
+
+	nRF8001_waitForSetupMode(pnRF8001);
+
+	setupMsgData = (struct setupMsgData*)setupMsg.buffer;
+	setupMsg.status_byte = 0;
+
+	for (i = 0; i < NB_BASE_SETUP_MESSAGES; i++) {
+		int setupMsgSize = pgm_read_byte_near(&baseSetupMsgs[i].buffer[0]) + 2;
+
+		memcpy(&setupMsg, &baseSetupMsgs[i], setupMsgSize);
+		if(i == 1){
+			setupMsgData->data[6] = numPipedCharacteristics;
+			setupMsgData->data[8] = numPipedCharacteristics;
+		}
+		else if(i == 2 && advertisementData && advertisementDataLength){
+			setupMsgData->data[22] = 0x40;
+		}
+		else if(i == 3 && scanData && scanDataLength){
+			setupMsgData->data[12] = 0x40;
+		}
+		else if(i == 5 && advertisementData && advertisementDataLength){
+			memcpy(setupMsgData->data, advertisementData, advertisementDataLength);
+		}
+		else if(i == 6 && scanData && scanDataLength){
+			memcpy(setupMsgData->data, scanData, scanDataLength);
+		}
+
+		ercd = nRF8001_sendSetupMessage(pnRF8001, &setupMsg);
+		if(ercd != E_OK)
+			i--;
+	}
+
+	// GATT
+	for(i = 0 ; i < numAttributes ; i++){
+		BLEAttribute* attribute = attributes[i];
+		BLEUuid* puuid = &attribute->_uuid;
+
+		if(attribute->_type == BLETypeService){
+			setupMsgData->length  = 12 + puuid->_length;
+			setupMsgData->cmd     = ACI_CMD_SETUP;
+			setupMsgData->type    = 0x20;
+			setupMsgData->offset  = gattSetupMsgOffset;
+
+			setupMsgData->data[0] = 0x04;
+			setupMsgData->data[1] = 0x04;
+			setupMsgData->data[2] = puuid->_length;
+			setupMsgData->data[3] = puuid->_length;
+			setupMsgData->data[4] = (handle >> 8) & 0xff;
+			setupMsgData->data[5] = handle & 0xff;
+			handle++;
+
+			setupMsgData->data[6] = (attribute->_type >> 8) & 0xff;
+			setupMsgData->data[7] = attribute->_type & 0xff;
+			setupMsgData->data[8] = ACI_STORE_LOCAL;
+			memcpy(&setupMsgData->data[9], puuid->_data, puuid->_length);
+			gattSetupMsgOffset += 9 + puuid->_length;
+
+			nRF8001_sendSetupMessage(pnRF8001, &setupMsg);
+		}
+		else if(attribute->_type == BLETypeCharacteristic){
+			BLECharacteristic *pcharc = (BLECharacteristic *)attribute;
+			struct pipeInfo* pipeInfo = &pnRF8001->_pipeInfo[numPiped];
+
+			memset(pipeInfo, 0, sizeof(struct pipeInfo));
+			pipeInfo->pcharc = pcharc;
+			if(pcharc->_properties){
+				numPiped++;
+				pipeInfo->startPipe = pipe;
+				if(pcharc->_properties & BLENotify){
+					pipeInfo->txPipe = pipe;
+					pipe++;
+				}
+
+				if(pcharc->_properties & BLEIndicate){
+					pipeInfo->txAckPipe = pipe;
+					pipe++;
+				}
+				if(pcharc->_properties & BLEWriteWithoutResponse){
+					pipeInfo->rxPipe = pipe;
+					pipe++;
+				}
+				if(pcharc->_properties & BLEWrite){
+					pipeInfo->rxAckPipe = pipe;
+					pipe++;
+				}
+				if(pcharc->_properties & BLERead){
+					pipeInfo->setPipe = pipe;
+					pipe++;
+				}
+			}
+
+			setupMsgData->length   = 15 + puuid->_length;
+			setupMsgData->cmd      = ACI_CMD_SETUP;
+			setupMsgData->type     = 0x20;
+			setupMsgData->offset   = gattSetupMsgOffset;
+
+			setupMsgData->data[0]  = 0x04;
+			setupMsgData->data[1]  = 0x04;
+			setupMsgData->data[2]  = 3 + puuid->_length;
+			setupMsgData->data[3]  = 3 + puuid->_length;
+
+			setupMsgData->data[4]  = (handle >> 8) & 0xff;
+			setupMsgData->data[5]  = handle & 0xff;
+			handle++;
+
+			setupMsgData->data[6]  = (pcharc->_attr._type >> 8) & 0xff;
+			setupMsgData->data[7]  = pcharc->_attr._type & 0xff;
+			setupMsgData->data[8]  = ACI_STORE_LOCAL;
+			setupMsgData->data[9]  = pcharc->_properties;
+			setupMsgData->data[10] = handle & 0xff;
+			setupMsgData->data[11] = (handle >> 8) & 0xff;
+			pipeInfo->valueHandle = handle;
+			handle++;
+
+			memcpy(&setupMsgData->data[12], puuid->_data, puuid->_length);
+
+			gattSetupMsgOffset += 12 + puuid->_length;
+
+			nRF8001_sendSetupMessage(pnRF8001, &setupMsg);
+
+			setupMsgData->length   = 12 + pcharc->_valueSize;
+			setupMsgData->cmd      = ACI_CMD_SETUP;
+			setupMsgData->type     = 0x20;
+			setupMsgData->offset   = gattSetupMsgOffset;
+
+			setupMsgData->data[0]  = 0x04;
+			setupMsgData->data[1]  = 0x00;
+			if(pcharc->_fixedLength)
+				setupMsgData->data[0] |= 0x02;
+
+			if(pcharc->_properties & BLERead)
+				setupMsgData->data[1] |= 0x04;
+			if(pcharc->_properties & (BLEWrite | BLEWriteWithoutResponse)){
+				setupMsgData->data[0] |= 0x40;
+				setupMsgData->data[1] |= 0x10;
+			}
+			if(pcharc->_properties & BLENotify)
+				setupMsgData->data[0] |= 0x10;
+			if(pcharc->_properties & BLEIndicate)
+				setupMsgData->data[0] |= 0x20;
+			setupMsgData->data[2]  = pcharc->_valueSize;
+			if(pcharc->_fixedLength)
+				setupMsgData->data[2]++;
+			setupMsgData->data[3]  = pcharc->_valueLength;
+			setupMsgData->data[4]  = (pipeInfo->valueHandle >> 8) & 0xff;
+			setupMsgData->data[5]  = pipeInfo->valueHandle & 0xff;
+			setupMsgData->data[6]  = 0x00;
+			setupMsgData->data[7]  = 0x00;
+			setupMsgData->data[8]  = 0x02;
+			memset(&setupMsgData->data[9], 0x00, pcharc->_valueSize);
+			memcpy(&setupMsgData->data[9], pcharc->_value, pcharc->_valueLength);
+
+			gattSetupMsgOffset += 9 + pcharc->_valueSize;
+
+			nRF8001_sendSetupMessage(pnRF8001, &setupMsg);
+
+			if(pcharc->_properties & (BLENotify | BLEIndicate)){
+				setupMsgData->length   = 14;
+				setupMsgData->cmd      = ACI_CMD_SETUP;
+				setupMsgData->type     = 0x20;
+				setupMsgData->offset   = gattSetupMsgOffset;
+
+				setupMsgData->data[0]  = 0x46;
+				setupMsgData->data[1]  = 0x14;
+				setupMsgData->data[2]  = 0x03;
+				setupMsgData->data[3]  = 0x02;
+				setupMsgData->data[4]  = (handle >> 8) & 0xff;
+				setupMsgData->data[5]  = handle & 0xff;
+				pipeInfo->configHandle = handle;
+				handle++;
+
+				setupMsgData->data[6]  = 0x29;
+				setupMsgData->data[7]  = 0x02;
+				setupMsgData->data[8]  = ACI_STORE_LOCAL;
+				setupMsgData->data[9]  = 0x00;
+				setupMsgData->data[10] = 0x00;
+
+				gattSetupMsgOffset += 11;
+
+				nRF8001_sendSetupMessage(pnRF8001, &setupMsg);
+			}
+		}
+		else if(attribute->_type == BLETypeDescriptor){
+			BLEDescriptor* descriptor = (BLEDescriptor *)attribute;
+
+			setupMsgData->length   = 12 + descriptor->_valueSize;
+			setupMsgData->cmd      = ACI_CMD_SETUP;
+			setupMsgData->type     = 0x20;
+			setupMsgData->offset   = gattSetupMsgOffset;
+
+			setupMsgData->data[0]  = 0x04;
+			setupMsgData->data[1]  = 0x04;
+			setupMsgData->data[2]  = descriptor->_valueSize;
+			setupMsgData->data[3]  = descriptor->_valueLength;
+			setupMsgData->data[4]  = (handle >> 8) & 0xff;
+			setupMsgData->data[5]  = handle & 0xff;
+			handle++;
+
+			setupMsgData->data[6]  = puuid->_data[1];
+			setupMsgData->data[7]  = puuid->_data[0];
+			setupMsgData->data[8]  = ACI_STORE_LOCAL;
+			memcpy(&setupMsgData->data[9], descriptor->_value, descriptor->_valueLength);
+
+			gattSetupMsgOffset += 9 + descriptor->_valueSize;
+
+			nRF8001_sendSetupMessage(pnRF8001, &setupMsg);
+		}
+	}
+	pnRF8001->_numPipeInfo = numPiped;
+
+	// terminator
+	setupMsgData->length   = 4;
+	setupMsgData->cmd      = ACI_CMD_SETUP;
+	setupMsgData->type     = 0x20;
+	setupMsgData->offset   = gattSetupMsgOffset;
+
+	setupMsgData->data[0]  = 0x00;
+
+	gattSetupMsgOffset += 6;
+
+	nRF8001_sendSetupMessage(pnRF8001, &setupMsg);
+
+	// pipes
+	for(i = 0 ; i < numPiped ; i++){
+		struct pipeInfo pipeInfo = pnRF8001->_pipeInfo[i];
+
+		setupMsgData->length   = 13;
+		setupMsgData->cmd      = ACI_CMD_SETUP;
+		setupMsgData->type     = 0x40;
+		setupMsgData->offset   = pipeSetupMsgOffet;
+
+		setupMsgData->data[0]  = 0x00;
+		setupMsgData->data[1]  = 0x00;
+		setupMsgData->data[2]  = pipeInfo.startPipe;
+		setupMsgData->data[3]  = 0x00;
+		setupMsgData->data[4]  = 0x00;
+		setupMsgData->data[5]  = 0x04;
+		setupMsgData->data[6]  = (pipeInfo.valueHandle >> 8) & 0xff;
+		setupMsgData->data[7]  = pipeInfo.valueHandle & 0xff;
+		setupMsgData->data[8]  = (pipeInfo.configHandle >> 8) & 0xff;
+		setupMsgData->data[9]  = pipeInfo.configHandle & 0xff;
+
+		if(pipeInfo.pcharc->_properties & BLEIndicate)
+			setupMsgData->data[4] |= 0x04; // TX Ack
+		if(pipeInfo.pcharc->_properties & BLENotify)
+			setupMsgData->data[4] |= 0x02; // TX
+		if(pipeInfo.pcharc->_properties & BLEWriteWithoutResponse)
+			setupMsgData->data[4] |= 0x08; // RX Ack
+		if(pipeInfo.pcharc->_properties & BLEWrite)
+			setupMsgData->data[4] |= 0x10; // RX Ack
+		if(pipeInfo.pcharc->_properties & BLERead)
+			setupMsgData->data[4] |= 0x80; // Set
+
+		pipeSetupMsgOffet += 10;
+
+		nRF8001_sendSetupMessage(pnRF8001, &setupMsg);
+	}
+	nRF8001_sendCrc(pnRF8001);
+}
+
+/*
+ *  nRF8001参照
+ */
+bool_t
+nRF8001_poll(nRF8001* pnRF8001)
+{
+	if(lib_aci_event_get(&pnRF8001->_aciState, &pnRF8001->_aciData)){
+		aci_evt_t* aciEvt = &pnRF8001->_aciData.evt;
+		int i;
+#ifdef NRF_8001_DEBUG
+		uint32_t tmp1, tmp2;
+		uint32_t tmp3, tmp4;
+
+		syslog_3(LOG_NOTICE, " nRF8001_poll [%02x][%02x][%08x]", aciEvt->evt_opcode, aciEvt->params.device_started.device_mode, aciEvt);
+#endif
+		switch(aciEvt->evt_opcode){
+		/*
+		 *  スタートイベント(リセット後)
+		 */
+		case ACI_EVT_DEVICE_STARTED: {
+			pnRF8001->_aciState.data_credit_total = aciEvt->params.device_started.credit_available;
+			switch(aciEvt->params.device_started.device_mode) {
+			case ACI_DEVICE_SETUP:
+				/*
+				 *  DEVICEセットアップ
+				 */
+#ifdef NRF_8001_DEBUG
+				syslog_0(LOG_NOTICE, "Evt Device Started: Setup");
+#endif
+				break;
+
+			case ACI_DEVICE_STANDBY:
+				/*
+				 *  DEVICEスタンバイ
+				 */
+#ifdef NRF_8001_DEBUG
+				syslog_0(LOG_NOTICE, "Evt Device Started: Standby");
+#endif
+				if(aciEvt->params.device_started.hw_error){
+					dly_tsk(20);	/* ハードウェアエラー */
+				}
+				else{
+					lib_aci_connect(0/* in seconds : 0 means forever */, ADVERTISING_INTERVAL);
+#ifdef NRF_8001_DEBUG
+					syslog_0(LOG_NOTICE, "Advertising started");
+#endif
+				}
+				break;
+			default:
+				break;
+			}
+		}
+		break;	/* ここまで、DEVICEスタート状態 */
+
+		case ACI_EVT_CMD_RSP:
+			//If an ACI command response event comes with an error -> stop
+			if(ACI_STATUS_SUCCESS != aciEvt->params.cmd_rsp.cmd_status){
+				//ACI ReadDynamicData and ACI WriteDynamicData will have status codes of
+				//TRANSACTION_CONTINUE and TRANSACTION_COMPLETE
+				//all other ACI commands will have status code of ACI_STATUS_SCUCCESS for a successful command
+#ifdef NRF_8001_DEBUG
+				syslog_2(LOG_NOTICE, "ACI Command [%02x] Evt Cmd respone: Status [%02x]",
+					aciEvt->params.cmd_rsp.cmd_opcode,
+					aciEvt->params.cmd_rsp.cmd_status);
+#endif
+			}
+			else{
+				switch (aciEvt->params.cmd_rsp.cmd_opcode) {
+				case ACI_CMD_GET_DEVICE_VERSION:
+					syslog_2(LOG_NOTICE, "VERSION configuration_id[%04x] aci_ver[%02x]",
+						aciEvt->params.cmd_rsp.params.get_device_version.configuration_id,
+						aciEvt->params.cmd_rsp.params.get_device_version.aci_version);
+					syslog_3(LOG_NOTICE, "   setup_format[%02x] setup[%08x] setp_status[%02x]",
+						aciEvt->params.cmd_rsp.params.get_device_version.setup_format,
+						aciEvt->params.cmd_rsp.params.get_device_version.setup_id,
+						aciEvt->params.cmd_rsp.params.get_device_version.setup_status);
+					break;
+
+				case ACI_CMD_GET_DEVICE_ADDRESS: {
+#ifdef NRF_8001_DEBUG
+					syslog_4(LOG_NOTICE, "nRF8001_poll ACI_CMD_GET_DEVICE_ADDRESS type(%d) [%02x][%02x][%02x]",
+						aciEvt->params.cmd_rsp.params.get_device_address.bd_addr_type,
+						aciEvt->params.cmd_rsp.params.get_device_address.bd_addr_own[5],
+						aciEvt->params.cmd_rsp.params.get_device_address.bd_addr_own[4],
+						aciEvt->params.cmd_rsp.params.get_device_address.bd_addr_own[3]);
+					syslog_3(LOG_NOTICE, "nRF8001_poll   [%02x][%02x][%02x]",
+						aciEvt->params.cmd_rsp.params.get_device_address.bd_addr_own[2],
+						aciEvt->params.cmd_rsp.params.get_device_address.bd_addr_own[1],
+						aciEvt->params.cmd_rsp.params.get_device_address.bd_addr_own[0]);
+#endif
+					if(pnRF8001->nRF8001AddressReceived){
+						pnRF8001->nRF8001AddressReceived(pnRF8001, aciEvt->params.cmd_rsp.params.get_device_address.bd_addr_own);
+					}
+					break;
+				}
+
+				case ACI_CMD_GET_BATTERY_LEVEL: {
+					float batteryLevel = aciEvt->params.cmd_rsp.params.get_battery_level.battery_level * 0.00352;
+					if(pnRF8001->nRF8001BatteryLevelReceived){
+						pnRF8001->nRF8001BatteryLevelReceived(pnRF8001, batteryLevel);
+					}
+					break;
+				}
+
+				case ACI_CMD_GET_TEMPERATURE: {
+					float temperature = aciEvt->params.cmd_rsp.params.get_temperature.temperature_value / 4.0;
+					if(pnRF8001->nRF8001TemperatureReceived){
+						pnRF8001->nRF8001TemperatureReceived(pnRF8001, temperature);
+					}
+					break;
+				}
+				default:
+					break;
+				}
+	        }
+    	    break;
+
+		case ACI_EVT_CONNECTED:
+
+#ifdef NRF_8001_DEBUG
+			syslog_3(LOG_NOTICE, "Evt Connected [%02x][%02x][%02x]",
+				aciEvt->params.connected.dev_addr[5],
+				aciEvt->params.connected.dev_addr[4],
+				aciEvt->params.connected.dev_addr[3]):
+			syslog_3(LOG_NOTICE, "              [%02x][%02x][%02x]",
+				aciEvt->params.connected.dev_addr[2],
+				aciEvt->params.connected.dev_addr[1],
+				aciEvt->params.connected.dev_addr[0]);
+#endif
+			if(pnRF8001->nRF8001Connected){
+				pnRF8001->nRF8001Connected(pnRF8001, aciEvt->params.connected.dev_addr);
+			}
+			pnRF8001->_aciState.data_credit_available = pnRF8001->_aciState.data_credit_total;
+			break;
+
+		case ACI_EVT_PIPE_STATUS:
+#ifdef NRF_8001_DEBUG
+			memcpy(&tmp1, &aciEvt->params.pipe_status.pipes_open_bitmap[0], 4);
+			memcpy(&tmp2, &aciEvt->params.pipe_status.pipes_open_bitmap[4], 4);
+			memcpy(&tmp3, &aciEvt->params.pipe_status.pipes_closed_bitmap[0], 4);
+			memcpy(&tmp4, &aciEvt->params.pipe_status.pipes_closed_bitmap[4], 4);
+			syslog_4(LOG_NOTICE, "Evt Pipe Status [%04x%04x][%04x%04x]", tmp1, tmp2, tmp3, tmp4);
+#endif
+			for(i = 0 ; i < pnRF8001->_numPipeInfo ; i++){
+				struct pipeInfo* pipeInfo = &pnRF8001->_pipeInfo[i];
+
+				if(pipeInfo->txPipe){
+					pipeInfo->txPipeOpen = lib_aci_is_pipe_available(&pnRF8001->_aciState, pipeInfo->txPipe);
+				}
+				if(pipeInfo->txAckPipe){
+					pipeInfo->txAckPipeOpen = lib_aci_is_pipe_available(&pnRF8001->_aciState, pipeInfo->txAckPipe);
+				}
+
+				bool subscribed = (pipeInfo->txPipeOpen || pipeInfo->txAckPipeOpen);
+
+				if(pipeInfo->pcharc->_subscribed != subscribed){
+					if(pnRF8001->nRF8001CharacteristicSubscribedChanged){
+						pnRF8001->nRF8001CharacteristicSubscribedChanged(pnRF8001, pipeInfo->pcharc, subscribed);
+					}
+				}
+			}
+			break;
+
+		case ACI_EVT_TIMING:
+			break;
+
+		case ACI_EVT_DISCONNECTED:
+#ifdef NRF_8001_DEBUG
+			syslog_0(LOG_NOTICE, "Evt Disconnected/Advertising timed out");
+#endif
+			// all characteristics unsubscribed on disconnect
+			for(i = 0 ; i < pnRF8001->_numPipeInfo ; i++){
+				struct pipeInfo* pipeInfo = &pnRF8001->_pipeInfo[i];
+
+				if(pipeInfo->pcharc->_subscribed){
+					if(pnRF8001->nRF8001CharacteristicSubscribedChanged){
+						pnRF8001->nRF8001CharacteristicSubscribedChanged(pnRF8001, pipeInfo->pcharc, false);
+					}
+				}
+			}
+			if(pnRF8001->nRF8001Disconnected){
+				pnRF8001->nRF8001Disconnected(pnRF8001);
+			}
+
+			lib_aci_connect(0/* in seconds  : 0 means forever */, ADVERTISING_INTERVAL);
+#ifdef NRF_8001_DEBUG
+			syslog_0(LOG_NOTICE, "Advertising started.");
+#endif
+			break;
+
+		case ACI_EVT_DATA_RECEIVED: {
+			uint8_t dataLen = aciEvt->len - 2;
+			uint8_t pipe = aciEvt->params.data_received.rx_data.pipe_number;
+#ifdef NRF_8001_DEBUG
+			syslog_1(LOG_NOTICE, "Data Received, pipe = %d", aciEvt->params.data_received.rx_data.pipe_number);
+
+			for(int i = 0 ; i < dataLen ; i++){
+				syslog_2(LOG_NOTICE, "%d:%02x", i, aciEvt->params.data_received.rx_data.aci_data[i]);
+	        }
+#endif
+			for(i = 0 ; i < pnRF8001->_numPipeInfo ; i++){
+				struct pipeInfo* pipeInfo = &pnRF8001->_pipeInfo[i];
+
+				if(pipeInfo->rxAckPipe == pipe || pipeInfo->rxPipe == pipe){
+					if(pipeInfo->rxAckPipe == pipe){
+						lib_aci_send_ack(&pnRF8001->_aciState, pipeInfo->rxAckPipe);
+					}
+					if(pnRF8001->nRF8001CharacteristicValueChanged){
+						pnRF8001->nRF8001CharacteristicValueChanged(pnRF8001, pipeInfo->pcharc, aciEvt->params.data_received.rx_data.aci_data, dataLen);
+					}
+					break;
+				}
+			}
+		}
+		break;
+
+		case ACI_EVT_DATA_CREDIT:
+			pnRF8001->_aciState.data_credit_available = pnRF8001->_aciState.data_credit_available + aciEvt->params.data_credit.credit;
+			break;
+
+		case ACI_EVT_PIPE_ERROR:
+			//See the appendix in the nRF8001 Product Specication for details on the error codes
+#ifdef NRF_8001_DEBUG
+			syslog_2(LOG_ERROR, "ACI Evt Pipe Error: Pipe #:%d, Pipe Error Code: 0x%x",
+				aciEvt->params.pipe_error.pipe_number,
+				aciEvt->params.pipe_error.error_code);
+#endif
+			//Increment the credit available as the data packet was not sent.
+			//The pipe error also represents the Attribute protocol Error Response sent from the peer and that should not be counted
+			//for the credit.
+			if(ACI_STATUS_ERROR_PEER_ATT_ERROR != aciEvt->params.pipe_error.error_code){
+				pnRF8001->_aciState.data_credit_available++;
+			}
+			break;
+
+		case ACI_EVT_HW_ERROR:
+#ifdef NRF_8001_DEBUG
+			syslog_1(LOG_ERROR, "HW error: %d", aciEvt->params.hw_error.line_num);
+
+			for(uint8_t counter = 0; counter <= (aciEvt->len - 3); counter++) {
+				syslog_1(LOG_ERROR, "[%s]", aciEvt->params.hw_error.file_name[counter]);
+			}
+#endif
+			lib_aci_connect(0/* in seconds, 0 means forever */, ADVERTISING_INTERVAL);
+#ifdef NRF_8001_DEBUG
+			syslog_0(LOG_ERROR, "Advertising started.");
+#endif
+			break;
+		default:
+			break;
+		}
+		return true;
+	}
+	else
+		return false;
+}
+
+/*
+ *  nRF8001キャラクティクス値更新
+ */
+bool_t
+nRF8001_updateCharacteristicValue(nRF8001* pnRF8001, BLECharacteristic *pcharc)
+{
+	bool_t success = true;
+	int i;
+
+	for(i = 0 ; i < pnRF8001->_numPipeInfo ; i++){
+		struct pipeInfo* pipeInfo = &pnRF8001->_pipeInfo[i];
+
+		if(pipeInfo->pcharc == pcharc){
+			if(pipeInfo->setPipe){
+				success &= lib_aci_set_local_data(&pnRF8001->_aciState, pipeInfo->setPipe, (uint8_t*)pcharc->_value, pcharc->_valueLength);
+			}
+			if(pipeInfo->txPipe && pipeInfo->txPipeOpen){
+				if(pcharc->canNotifyCharacteristic(pnRF8001, pcharc)){
+					pnRF8001->_aciState.data_credit_available--;
+					success &= lib_aci_send_data(pipeInfo->txPipe, (uint8_t*)pcharc->_value, pcharc->_valueLength);
+				}
+				else{
+					success = false;
+				}
+			}
+
+			if(pipeInfo->txAckPipe && pipeInfo->txAckPipeOpen){
+				if(pcharc->canIndicateCharacteristic(pnRF8001, pcharc)){
+					pnRF8001->_aciState.data_credit_available--;
+					success &= lib_aci_send_data(pipeInfo->txAckPipe, (uint8_t*)pcharc->_value, pcharc->_valueLength);
+				}
+				else{
+					success = false;
+				}
+			}
+			break;
+		}
+	}
+	return success;
+}
+
+/*
+ *  nRF8001 NOTIFYキャラクティクス可能判定
+ */
+bool_t
+nRF8001_canNotifyCharacteristic(nRF8001* pnRF8001, BLECharacteristic *pcharc) {
+	return (lib_aci_get_nb_available_credits(&pnRF8001->_aciState) > 0);
+}
+
+/*
+ *  nRF8001 INDICATEキャラクティクス可能判定
+ */
+bool_t
+nRF8001_canIndicateCharacteristic(nRF8001* pnRF8001, BLECharacteristic *pcharc) {
+	return (lib_aci_get_nb_available_credits(&pnRF8001->_aciState) > 0);
+}
+
+/*
+ *  nRF8001切断
+ */
+void
+nRF8001_disconnect(nRF8001* pnRF8001)
+{
+	lib_aci_disconnect(&pnRF8001->_aciState, ACI_REASON_TERMINATE);
+}
+
+/*
+ *  nRF8001アドレス要求
+ */
+void
+nRF8001_requestAddress(void)
+{
+	lib_aci_get_address();
+}
+
+/*
+ *  nRF8001温度要求
+ */
+void
+nRF8001_requestTemperature(void)
+{
+	lib_aci_get_temperature();
+}
+
+/*
+ *  nRF8001バッテリレベル要求
+ */
+void
+nRF8001_requestBatteryLevel(void)
+{
+	lib_aci_get_battery_level();
+}
+
+/*
+ *  nRF8001セットアップモード待ち
+ */
+void
+nRF8001_waitForSetupMode(nRF8001* pnRF8001)
+{
+	bool_t setupMode = false;
+
+	while(!setupMode){
+		if(lib_aci_event_get(&pnRF8001->_aciState, &pnRF8001->_aciData)){
+			aci_evt_t* aciEvt = &pnRF8001->_aciData.evt;
+
+			switch(aciEvt->evt_opcode){
+			case ACI_EVT_DEVICE_STARTED: {
+				switch(aciEvt->params.device_started.device_mode) {
+				case ACI_DEVICE_SETUP:
+					/**
+					When the device is in the setup mode
+					*/
+#ifdef NRF_8001_DEBUG
+					syslog_0(LOG_NOTICE, "Evt Device Started: Setup");
+#endif
+					setupMode = true;
+					break;
+				default:
+					break;
+				}
+				break;
+			}
+			default:
+				break;
+			}
+		}
+		else{
+			dly_tsk(1);
+		}
+	}
+}
+
+/*
+ *  nRF8001セットアップメッセージ送信
+ */
+ER
+nRF8001_sendSetupMessage(nRF8001* pnRF8001, hal_aci_data_t* data)
+{
+	bool_t setupMsgSent = false;
+	int i = 0;
+
+	pnRF8001->_crcSeed = crc_16_ccitt(pnRF8001->_crcSeed, data->buffer, data->buffer[0] + 1);
+	hal_aci_tl_send(data);
+
+	while(!setupMsgSent){
+		if(lib_aci_event_get(&pnRF8001->_aciState, &pnRF8001->_aciData)){
+			aci_evt_t* aciEvt = &pnRF8001->_aciData.evt;
+
+			if(aciEvt->evt_opcode == ACI_EVT_CMD_RSP && aciEvt->params.cmd_rsp.cmd_status == ACI_STATUS_TRANSACTION_CONTINUE){
+#ifdef NRF_8001_DEBUG
+				syslog_2(LOG_NOTICE, "Evt Cmd Rsp: Transaction Continue evt[%02x] sts[%02x]", aciEvt->evt_opcode, aciEvt->params.cmd_rsp.cmd_status);
+#endif
+				setupMsgSent = true;
+				break;
+			}
+		}
+		else{
+			dly_tsk(1);
+			i++;
+		}
+		if(i > 500)
+			return E_TMOUT;
+	}
+	return E_OK;
+}
+
+/*
+ *  nRF8001 CRC送信
+ */
+void
+nRF8001_sendCrc(nRF8001* pnRF8001)
+{
+	bool_t setupMsgSent = false;
+	hal_aci_data_t data;
+	data.status_byte = 0;
+
+	data.buffer[0]  = 3 + 3;
+	data.buffer[1]  = ACI_CMD_SETUP;
+	data.buffer[2]  = 0xf0;
+	data.buffer[3]  = 0x00;
+	data.buffer[4] = 0x03;
+	pnRF8001->_crcSeed = crc_16_ccitt(pnRF8001->_crcSeed, data.buffer, data.buffer[0] - 1);
+	data.buffer[5] = (pnRF8001->_crcSeed >> 8) & 0xff;
+	data.buffer[6] = pnRF8001->_crcSeed & 0xff;
+
+	hal_aci_tl_send(&data);
+
+	while(!setupMsgSent){
+		if(lib_aci_event_get(&pnRF8001->_aciState, &pnRF8001->_aciData)){
+			aci_evt_t* aciEvt = &pnRF8001->_aciData.evt;
+
+			switch(aciEvt->evt_opcode){
+			case ACI_EVT_CMD_RSP: {
+				switch(aciEvt->params.cmd_rsp.cmd_status) {
+				case ACI_STATUS_TRANSACTION_COMPLETE:
+#ifdef NRF_8001_DEBUG
+					syslog_0(LOG_NOTICE, "Evt Cmd Rsp: Transaction Complete");
+#endif
+					setupMsgSent = true;
+					break;
+				default:
+					break;
+				}
+			}
+			break;
+			default:
+				break;
+			}
+		}
+		else{
+			dly_tsk(1);
+		}
+	}
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/README.md
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/README.md	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/README.md	(revision 453)
@@ -0,0 +1,3 @@
+These files are from the [@NordicSemiconductor](https://github.com/NordicSemiconductor)[ble-sdk-arduino](https://github.com/NordicSemiconductor/ble-sdk-arduino).
+
+Some file have been slightly modified.
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/aci.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/aci.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/aci.h	(revision 453)
@@ -0,0 +1,664 @@
+/* Copyright (c) 2014, Nordic Semiconductor ASA
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * @file
+ *
+ * @defgroup aci aci
+ * @{
+ * @ingroup lib
+ *
+ * @brief Definitions for the ACI (Application Control Interface)
+ * @remarks
+ *
+ * Flow control from application mcu to nRF8001
+ *
+ * Data flow control:
+ * The flow control is credit based and the credit is initally given using the "device started" event.
+ * A credit of more than 1 is given to the application mcu.
+ * These credits are used only after the "ACI Connected Event" is sent to the application mcu.
+ *
+ * every send_data that is used decrements the credit available by 1. This is to be tracked by the application mcu.
+ * When the credit available reaches 0, the application mcu shall not send any more send_data.
+ * Credit is returned using the "credit event", this returned credit can then be used to send more send_data.
+ * This flow control is not necessary and not available for Broadcast.
+ * The entire credit available with the external mcu expires when a "disconnected" event arrives.
+ *
+ * Command flow control:
+ * When a command is sent over the ACI, the next command shall not be sent until after a response
+ * for the command sent has arrived.
+ *
+ */
+
+#ifndef ACI_H__
+#define ACI_H__
+
+/**
+ * Define an _aci_packed_ macro we can use in structure and enumerated type
+ * declarations so that the types are sized consistently across different
+ * platforms. In particular Arduino platforms using the GCC compiler and the
+ * Nordic processors using the Keil compiler.
+ *
+ * It's really the GNU compiler platforms that need a special keyword to get
+ * tight packing of values. On GNU platforms we can use the keyword:
+ *     __attribute__((__packed__))
+ * The thing is that while this keyword does the right thing with old and new
+ * versions of the gcc (C) compiler it only works right with g++ (C++) compiler
+ * versions that are version 4 or newer.
+ */
+#ifdef __GNUC__
+#  if __GNUC__ >= 4
+#    define _aci_packed_ __attribute__((__packed__))
+#  else
+#    error "older g++ versions don't handle packed attribute in typedefs"
+#  endif
+#else
+#  define _aci_packed_
+#endif
+
+/*
+ * Define a macro that compares the size of the first parameter to the integer
+ * value of the second parameter. If they do not match, a compile time error
+ * for negative array size occurs (even gnu chokes on negative array size).
+ *
+ * This compare is done by creating a typedef for an array. No variables are
+ * created and no memory is consumed with this check. The created type is
+ * used for checking only and is not for use by any other code. The value
+ * of 10 in this macro is arbitrary, it just needs to be a value larger
+ * than one to result in a positive number for the array size.
+ */
+#define ACI_ASSERT_SIZE(x,y) typedef char x ## _assert_size_t[-1+10*(sizeof(x) == (y))]
+
+/**
+ * @def ACI_VERSION
+ * @brief Current ACI protocol version. 0 means a device that is not yet released.
+ * A numer greater than 0 refers to a specific ACI version documented and released.
+ * The ACI consists of the ACI commands, ACI events and error codes.
+ */
+#define ACI_VERSION   (0x02)
+/**
+ * @def BTLE_DEVICE_ADDRESS_SIZE
+ * @brief Size in bytes of a Bluetooth Address
+ */
+#define BTLE_DEVICE_ADDRESS_SIZE                 (6)
+/**
+ * @def ACI_PACKET_MAX_LEN
+ * @brief Maximum length in bytes of a full ACI packet, including length prefix, opcode and payload
+ */
+#define ACI_PACKET_MAX_LEN                       (32)
+/**
+ * @def ACI_ECHO_DATA_MAX_LEN
+ * @brief Maximum length in bytes of the echo data portion
+ */
+#define ACI_ECHO_DATA_MAX_LEN                    (ACI_PACKET_MAX_LEN - 3)
+/**
+ * @def ACI_DEVICE_MAX_PIPES
+ * @brief Maximum number of ACI pipes
+ */
+#define ACI_DEVICE_MAX_PIPES                       (62)
+/**
+ * @def ACI_PIPE_TX_DATA_MAX_LEN
+ * @brief Maximum length in bytes of a transmission data pipe packet
+ */
+#define ACI_PIPE_TX_DATA_MAX_LEN                   (20)
+/**
+ * @def ACI_PIPE_RX_DATA_MAX_LEN
+ * @brief Maximum length in bytes of a reception data pipe packet
+ */
+#define ACI_PIPE_RX_DATA_MAX_LEN                   (22)
+/**
+ * @def ACI_GAP_DEVNAME_MAX_LEN
+ * @brief Maximum length in bytes of the GAP device name
+ */
+#define ACI_GAP_DEVNAME_MAX_LEN                 (20)
+/**
+ * @def ACI_AD_PACKET_MAX_LEN
+ * @brief Maximum length in bytes of an AD packet
+ */
+#define ACI_AD_PACKET_MAX_LEN                   (31)
+/**
+ * @def ACI_AD_PACKET_MAX_USER_LEN
+ * @brief Maximum usable length in bytes of an AD packet
+ */
+#define ACI_AD_PACKET_MAX_USER_LEN              (31 - 3)
+/**
+ * @def ACI_PIPE_INVALID
+ * @brief Invalid pipe number
+ */
+#define ACI_PIPE_INVALID                        (0xFF)
+
+/**
+ * @enum aci_pipe_store_t
+ * @brief Storage type identifiers: local and remote
+ */
+typedef enum
+{
+  ACI_STORE_INVALID = 0x0,
+  ACI_STORE_LOCAL= 0x01,
+  ACI_STORE_REMOTE= 0x02
+} _aci_packed_ aci_pipe_store_t;
+
+/**
+ * @enum aci_pipe_type_t
+ * @brief Pipe types
+ */
+typedef enum
+{
+  ACI_TX_BROADCAST = 0x0001,
+  ACI_TX           = 0x0002,
+  ACI_TX_ACK       = 0x0004,
+  ACI_RX           = 0x0008,
+  ACI_RX_ACK       = 0x0010,
+  ACI_TX_REQ       = 0x0020,
+  ACI_RX_REQ       = 0x0040,
+  ACI_SET          = 0x0080,
+  ACI_TX_SIGN      = 0x0100,
+  ACI_RX_SIGN      = 0x0200,
+  ACI_RX_ACK_AUTO  = 0x0400
+} _aci_packed_ aci_pipe_type_t;
+
+ACI_ASSERT_SIZE(aci_pipe_type_t, 2);
+
+/**
+ * @enum aci_bd_addr_type_t
+ * @brief Bluetooth Address types
+ */
+typedef enum
+{
+  ACI_BD_ADDR_TYPE_INVALID  = 0x00,
+  ACI_BD_ADDR_TYPE_PUBLIC  = 0x01,
+  ACI_BD_ADDR_TYPE_RANDOM_STATIC  = 0x02,
+  ACI_BD_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE  = 0x03,
+  ACI_BD_ADDR_TYPE_RANDOM_PRIVATE_UNRESOLVABLE  = 0x04
+} _aci_packed_ aci_bd_addr_type_t;
+
+/**
+ * @enum aci_device_output_power_t
+ * @brief Radio output power levels
+ */
+typedef enum
+{
+  ACI_DEVICE_OUTPUT_POWER_MINUS_18DBM = 0x00, /**< Output power set to -18dBm */
+  ACI_DEVICE_OUTPUT_POWER_MINUS_12DBM = 0x01, /**< Output power set to -12dBm */
+  ACI_DEVICE_OUTPUT_POWER_MINUS_6DBM  = 0x02, /**< Output power set to -6dBm  */
+  ACI_DEVICE_OUTPUT_POWER_0DBM  = 0x03  /**< Output power set to 0dBm   - DEFAULT*/
+} _aci_packed_ aci_device_output_power_t;
+
+/**
+ * @enum aci_device_operation_mode_t
+ * @brief Device operation modes
+ */
+typedef enum
+{
+  ACI_DEVICE_INVALID   =0x00,
+  ACI_DEVICE_TEST      =0x01,
+  ACI_DEVICE_SETUP     =0x02,
+  ACI_DEVICE_STANDBY   =0x03,
+  ACI_DEVICE_SLEEP     =0x04
+} _aci_packed_ aci_device_operation_mode_t;
+
+/**
+ * @enum aci_disconnect_reason_t
+ * @brief Reason enumeration for ACI_CMD_DISCONNECT
+ */
+typedef enum
+{
+  ACI_REASON_TERMINATE      =0x01, /**< Use this to disconnect (does a terminate request), you need to wait for the "disconnected" event */
+  ACI_REASON_BAD_TIMING     =0x02 /*<Use this to disconnect and inform the peer, that the timing on the link is not acceptable for the device, you need to wait for the "disconnected" event */
+} _aci_packed_ aci_disconnect_reason_t;
+
+/**
+ * @enum aci_test_mode_change_t
+ * @brief Device test mode control
+ */
+typedef enum
+{
+  ACI_TEST_MODE_DTM_UART    = 0x01,
+  ACI_TEST_MODE_DTM_ACI     = 0x02,
+  ACI_TEST_MODE_EXIT        = 0xFF
+
+} _aci_packed_ aci_test_mode_change_t;
+
+ACI_ASSERT_SIZE(aci_test_mode_change_t, 1);
+
+/**
+ * @enum aci_permissions_t
+ * @brief Data store permissions
+ */
+typedef enum
+{
+  ACI_PERMISSIONS_NONE               =0x00,
+  ACI_PERMISSIONS_LINK_AUTHENTICATED =0x01
+} _aci_packed_ aci_permissions_t;
+
+/**
+ * @def ACI_VS_UUID_128_MAX_COUNT
+ * @brief Maximum number of 128-bit Vendor Specific
+ *        UUIDs that can be set
+ */
+#define ACI_VS_UUID_128_MAX_COUNT  64 /** #0 reserved for invalid, #1 reservered for BT SIG and a maximum of 1024 bytes (16*64) */
+
+/**
+ * @struct aci_ll_conn_params_t
+ * @brief Link Layer Connection Parameters
+ */
+typedef struct
+{
+  uint16_t min_conn_interval;   /**< Minimum connection interval requested from peer */
+    #define ACI_PPCP_MIN_CONN_INTVL_NONE  0xFFFF
+    #define ACI_PPCP_MIN_CONN_INTVL_MIN   0x0006
+    #define ACI_PPCP_MIN_CONN_INTVL_MAX   0x0C80
+  uint16_t max_conn_interval;   /**< Maximum connection interval requested from peer */
+    #define ACI_PPCP_MAX_CONN_INTVL_NONE  0xFFFF
+    #define ACI_PPCP_MAX_CONN_INTVL_MIN   0x0006
+    #define ACI_PPCP_MAX_CONN_INTVL_MAX   0x0C80
+  uint16_t slave_latency;       /**< Connection interval latency requested from peer */
+    #define ACI_PPCP_SLAVE_LATENCY_MAX    0x03E8
+  uint16_t timeout_mult;        /**< Link supervisor timeout multiplier requested from peer */
+    #define ACI_PPCP_TIMEOUT_MULT_NONE    0xFFFF
+    #define ACI_PPCP_TIMEOUT_MULT_MIN     0x000A
+    #define ACI_PPCP_TIMEOUT_MULT_MAX     0x0C80
+} _aci_packed_ aci_ll_conn_params_t;
+
+/**
+ * @def aci_gap_ppcp_t
+ * @brief GAP Peripheral Preferred Connection Parameters
+ */
+#define aci_gap_ppcp_t aci_ll_conn_params_t
+
+/**
+ * @def ACI_AD_LOC_SVCUUID_16_MAX_COUNT
+ * @brief Maximum number of 16-bit UUIDs that can
+ *        be inserted in the Services tag of AD
+ */
+#define ACI_AD_LOC_SVCUUID_16_MAX_COUNT  5
+
+/**
+ * @def ACI_AD_LOC_SVCUUID_128_MAX_COUNT
+ * @brief Maximum number of 128-bit UUIDs that can
+ *        be inserted in the Services tag of AD
+ */
+#define ACI_AD_LOC_SVCUUID_128_MAX_COUNT  1
+
+/**
+ * @def ACI_AD_SOL_SVCUUID_16_MAX_COUNT
+ * @brief Maximum number of UUIDs that can
+ *        be inserted in the Solicited Services tag of AD
+ */
+#define ACI_AD_SOL_SVCUUID_16_MAX_COUNT  5
+
+/**
+ * @def ACI_AD_SOL_SVCUUID_128_MAX_COUNT
+ * @brief Maximum number of UUIDs that can
+ *        be inserted in the Solicited Services tag of AD
+ */
+#define ACI_AD_SOL_SVCUUID_128_MAX_COUNT  1
+
+/**
+ * @def ACI_SEC_ENCKEY_SIZE_MIN
+ * @brief Minimum encryption key size
+ */
+#define ACI_SEC_ENCKEY_SIZE_MIN        7
+/**
+ * @def ACI_SEC_ENCKEY_SIZE_MAX
+ * @brief Maximum encryption key size
+ */
+#define ACI_SEC_ENCKEY_SIZE_MAX        16
+/**
+ * @def ACI_CUSTOM_AD_TYPE_MAX_COUNT
+ * @brief Maximum number of custom ad types
+ */
+#define ACI_CUSTOM_AD_TYPE_MAX_COUNT 8
+/**
+ * @def ACI_CUSTOM_AD_TYPE_MAX_DATA_LENGTH
+ * @brief Maximum custom ad type data size
+ */
+#define ACI_CUSTOM_AD_TYPE_MAX_DATA_LENGTH 20
+
+/**
+ * @struct aci_tx_data_t
+ * @brief Generic ACI transmit data structure
+ */
+typedef struct
+{
+  uint8_t pipe_number;
+  uint8_t aci_data[ACI_PIPE_TX_DATA_MAX_LEN];
+} _aci_packed_ aci_tx_data_t;
+
+ACI_ASSERT_SIZE(aci_tx_data_t, ACI_PIPE_TX_DATA_MAX_LEN + 1);
+
+/**
+ * @struct aci_rx_data_t
+ * @brief Generic ACI receive data structure
+ */
+typedef struct
+{
+  uint8_t pipe_number;
+  uint8_t aci_data[ACI_PIPE_RX_DATA_MAX_LEN];
+} _aci_packed_ aci_rx_data_t;
+
+ACI_ASSERT_SIZE(aci_rx_data_t, ACI_PIPE_RX_DATA_MAX_LEN + 1);
+
+/**
+ * @enum aci_hw_error_t
+ * @brief Hardware Error codes
+ */
+typedef enum
+{
+  ACI_HW_ERROR_NONE     = 0x00,
+  ACI_HW_ERROR_FATAL    = 0x01
+} _aci_packed_ aci_hw_error_t;
+
+/**
+ * @enum aci_clock_accuracy_t
+ * @brief Bluetooth Low Energy Clock Accuracy
+ */
+typedef enum
+{
+  ACI_CLOCK_ACCURACY_500_PPM = 0x00,
+  ACI_CLOCK_ACCURACY_250_PPM = 0x01,
+  ACI_CLOCK_ACCURACY_150_PPM = 0x02,
+  ACI_CLOCK_ACCURACY_100_PPM = 0x03,
+  ACI_CLOCK_ACCURACY_75_PPM  = 0x04,
+  ACI_CLOCK_ACCURACY_50_PPM  = 0x05,
+  ACI_CLOCK_ACCURACY_30_PPM  = 0x06,
+  ACI_CLOCK_ACCURACY_20_PPM  = 0x07
+} _aci_packed_ aci_clock_accuracy_t;
+
+/**
+ * @enum aci_app_latency_mode_t
+ * @brief Application latency modes
+ */
+typedef enum
+{
+  ACI_APP_LATENCY_DISABLE = 0,
+  ACI_APP_LATENCY_ENABLE = 1
+} _aci_packed_ aci_app_latency_mode_t;
+
+/**
+ * @enum gatt_format_t
+ * @brief GATT format definitions
+ */
+typedef enum
+{
+  ACI_GATT_FORMAT_NONE        = 0x00, /**< No characteristic format available */
+  ACI_GATT_FORMAT_BOOLEAN     = 0x01, /**< Not Supported */
+  ACI_GATT_FORMAT_2BIT        = 0x02, /**< Not Supported */
+  ACI_GATT_FORMAT_NIBBLE      = 0x03, /**< Not Supported */
+  ACI_GATT_FORMAT_UINT8       = 0x04,
+  ACI_GATT_FORMAT_UINT12      = 0x05,
+  ACI_GATT_FORMAT_UINT16      = 0x06,
+  ACI_GATT_FORMAT_UINT24      = 0x07,
+  ACI_GATT_FORMAT_UINT32      = 0x08,
+  ACI_GATT_FORMAT_UINT48      = 0x09,
+  ACI_GATT_FORMAT_UINT64      = 0x0A,
+  ACI_GATT_FORMAT_UINT128     = 0x0B,
+  ACI_GATT_FORMAT_SINT8       = 0x0C,
+  ACI_GATT_FORMAT_SINT12      = 0x0D,
+  ACI_GATT_FORMAT_SINT16      = 0x0E,
+  ACI_GATT_FORMAT_SINT24      = 0x0F,
+  ACI_GATT_FORMAT_SINT32      = 0x10,
+  ACI_GATT_FORMAT_SINT48      = 0x11,
+  ACI_GATT_FORMAT_SINT64      = 0x12,
+  ACI_GATT_FORMAT_SINT128     = 0x13,
+  ACI_GATT_FORMAT_FLOAT32     = 0x14,
+  ACI_GATT_FORMAT_FLOAT64     = 0x15,
+  ACI_GATT_FORMAT_SFLOAT      = 0x16,
+  ACI_GATT_FORMAT_FLOAT       = 0x17,
+  ACI_GATT_FORMAT_DUINT16     = 0x18,
+  ACI_GATT_FORMAT_UTF8S       = 0x19,
+  ACI_GATT_FORMAT_UTF16S      = 0x1A,
+  ACI_GATT_FORMAT_STRUCT      = 0x1B
+} _aci_packed_ aci_gatt_format_t;
+
+/**
+ * @brief GATT Bluetooth namespace
+ */
+typedef enum
+{
+  ACI_GATT_NAMESPACE_INVALID  = 0x00,
+  ACI_GATT_NAMESPACE_BTSIG    = 0x01 /**< Bluetooth SIG */
+} _aci_packed_ aci_gatt_namespace_t;
+
+/**
+ * @brief Security key types
+ */
+typedef enum
+{
+  ACI_KEY_TYPE_INVALID  = 0x00,
+  ACI_KEY_TYPE_PASSKEY  = 0x01
+} _aci_packed_ aci_key_type_t;
+
+/**
+ * @enum aci_bond_status_code_t
+ * @brief Bond status code
+ */
+typedef enum
+{
+ /**
+  * Bonding succeeded
+  */
+  ACI_BOND_STATUS_SUCCESS                             = 0x00,
+ /**
+  * Bonding failed
+  */
+  ACI_BOND_STATUS_FAILED                              = 0x01,
+ /**
+  * Bonding error: Timeout can occur when link termination is unexpected or did not get connected OR SMP timer expired
+  */
+  ACI_BOND_STATUS_FAILED_TIMED_OUT                    = 0x02,
+ /**
+  * Bonding error: Passkey entry failed
+  */
+  ACI_BOND_STATUS_FAILED_PASSKEY_ENTRY_FAILED        = 0x81,
+ /**
+  * Bonding error: OOB unavailable
+  */
+  ACI_BOND_STATUS_FAILED_OOB_UNAVAILABLE             = 0x82,
+ /**
+  * Bonding error: Authentication request failed
+  */
+  ACI_BOND_STATUS_FAILED_AUTHENTICATION_REQ          = 0x83,
+ /**
+  * Bonding error: Confirm value failed
+  */
+  ACI_BOND_STATUS_FAILED_CONFIRM_VALUE               = 0x84,
+ /**
+  * Bonding error: Pairing unsupported
+  */
+  ACI_BOND_STATUS_FAILED_PAIRING_UNSUPPORTED         = 0x85,
+ /**
+  * Bonding error: Invalid encryption key size
+  */
+  ACI_BOND_STATUS_FAILED_ENCRYPTION_KEY_SIZE         = 0x86,
+ /**
+  * Bonding error: Unsupported SMP command
+  */
+  ACI_BOND_STATUS_FAILED_SMP_CMD_UNSUPPORTED         = 0x87,
+ /**
+  * Bonding error: Unspecified reason
+  */
+  ACI_BOND_STATUS_FAILED_UNSPECIFIED_REASON          = 0x88,
+ /**
+  * Bonding error: Too many attempts
+  */
+  ACI_BOND_STATUS_FAILED_REPEATED_ATTEMPTS           = 0x89,
+ /**
+  * Bonding error: Invalid parameters
+  */
+  ACI_BOND_STATUS_FAILED_INVALID_PARAMETERS          = 0x8A
+
+} _aci_packed_ aci_bond_status_code_t;
+
+ACI_ASSERT_SIZE(aci_bond_status_code_t, 1);
+
+/**
+ * @enum aci_bond_status_source_t
+ * @brief Source of a bond status code
+ */
+typedef enum
+{
+  ACI_BOND_STATUS_SOURCE_INVALID                  = 0x00,
+  ACI_BOND_STATUS_SOURCE_LOCAL                    = 0x01,
+  ACI_BOND_STATUS_SOURCE_REMOTE                   = 0x02
+
+} _aci_packed_ aci_bond_status_source_t;
+
+/**
+ * @enum aci_status_code_t
+ * @brief ACI status codes
+ */
+typedef enum
+{
+ /**
+  * Success
+  */
+  ACI_STATUS_SUCCESS                                        = 0x00,
+ /**
+  * Transaction continuation status
+  */
+  ACI_STATUS_TRANSACTION_CONTINUE                           = 0x01,
+ /**
+  * Transaction completed
+  */
+  ACI_STATUS_TRANSACTION_COMPLETE                           = 0x02,
+ /**
+  * Extended status, further checks needed
+  */
+  ACI_STATUS_EXTENDED                                       = 0x03,
+ /**
+  * Unknown error.
+  */
+  ACI_STATUS_ERROR_UNKNOWN                                  = 0x80,
+ /**
+  * Internal error.
+  */
+  ACI_STATUS_ERROR_INTERNAL                                 = 0x81,
+ /**
+  * Unknown command
+  */
+  ACI_STATUS_ERROR_CMD_UNKNOWN                              = 0x82,
+ /**
+  * Command invalid in the current device state
+  */
+  ACI_STATUS_ERROR_DEVICE_STATE_INVALID                     = 0x83,
+ /**
+  * Invalid length
+  */
+  ACI_STATUS_ERROR_INVALID_LENGTH                           = 0x84,
+ /**
+  * Invalid input parameters
+  */
+  ACI_STATUS_ERROR_INVALID_PARAMETER                        = 0x85,
+ /**
+  * Busy
+  */
+  ACI_STATUS_ERROR_BUSY                                     = 0x86,
+ /**
+  * Invalid data format or contents
+  */
+  ACI_STATUS_ERROR_INVALID_DATA                             = 0x87,
+ /**
+  * CRC mismatch
+  */
+  ACI_STATUS_ERROR_CRC_MISMATCH                             = 0x88,
+ /**
+  * Unsupported setup format
+  */
+  ACI_STATUS_ERROR_UNSUPPORTED_SETUP_FORMAT                 = 0x89,
+ /**
+  * Invalid sequence number during a write dynamic data sequence
+  */
+  ACI_STATUS_ERROR_INVALID_SEQ_NO                           = 0x8A,
+ /**
+  * Setup data is locked and cannot be modified
+  */
+  ACI_STATUS_ERROR_SETUP_LOCKED                             = 0x8B,
+ /**
+  * Setup error due to lock verification failure
+  */
+  ACI_STATUS_ERROR_LOCK_FAILED                              = 0x8C,
+ /**
+  * Bond required: Local Pipes need bonded/trusted peer
+  */
+  ACI_STATUS_ERROR_BOND_REQUIRED                            = 0x8D,
+ /**
+  * Command rejected as a transaction is still pending
+  */
+  ACI_STATUS_ERROR_REJECTED                                 = 0x8E,
+  /**
+  * Pipe Error Event : Data size exceeds size specified for pipe : Transmit failed
+  */
+  ACI_STATUS_ERROR_DATA_SIZE                                = 0x8F,
+ /**
+  * Pipe Error Event : Invalid pipe
+  */
+  ACI_STATUS_ERROR_PIPE_INVALID                             = 0x90,
+ /**
+  * Pipe Error Event : Credit not available
+  */
+  ACI_STATUS_ERROR_CREDIT_NOT_AVAILABLE                     = 0x91,
+ /**
+  * Pipe Error Event : Peer device has sent an error on an pipe operation on the remote characteristic
+  */
+  ACI_STATUS_ERROR_PEER_ATT_ERROR                           = 0x92,
+ /**
+  * Connection was not established before the BTLE advertising was stopped
+  */
+  ACI_STATUS_ERROR_ADVT_TIMEOUT                             = 0x93,
+ /**
+  * Peer has triggered a Security Manager Protocol Error
+  */
+  ACI_STATUS_ERROR_PEER_SMP_ERROR                           = 0x94,
+ /**
+  * Pipe Error Event : Pipe type invalid for the selected operation
+  */
+  ACI_STATUS_ERROR_PIPE_TYPE_INVALID                        = 0x95,
+ /**
+  * Pipe Error Event : Pipe state invalid for the selected operation
+  */
+  ACI_STATUS_ERROR_PIPE_STATE_INVALID                       = 0x96,
+ /**
+  * Invalid key size provided
+  */
+  ACI_STATUS_ERROR_INVALID_KEY_SIZE                         = 0x97,
+ /**
+  * Invalid key data provided
+  */
+  ACI_STATUS_ERROR_INVALID_KEY_DATA                         = 0x98,
+ /**
+  * Reserved range start
+  */
+  ACI_STATUS_RESERVED_START                                 = 0xF0,
+ /**
+  * Reserved range end
+  */
+  ACI_STATUS_RESERVED_END                                   = 0xFF
+
+} _aci_packed_ aci_status_code_t;
+
+ACI_ASSERT_SIZE(aci_status_code_t, 1);
+
+/**
+ * @}
+ */
+
+#endif // ACI_H__
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/aci_cmds.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/aci_cmds.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/aci_cmds.h	(revision 453)
@@ -0,0 +1,435 @@
+/* Copyright (c) 2014, Nordic Semiconductor ASA
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * @file
+ *
+ * @ingroup aci
+ *
+ * @brief Definitions for the ACI (Application Control Interface) commands
+ * @remarks
+ *
+ */
+
+#ifndef ACI_CMDS_H__
+#define ACI_CMDS_H__
+
+#include "aci.h"
+
+/**
+ * @enum aci_cmd_opcode_t
+ * @brief ACI command opcodes
+ */
+typedef enum
+{
+ /**
+  * Enter test mode
+  */
+  ACI_CMD_TEST                    = 0x01,
+ /**
+  * Echo (loopback) test command
+  */
+  ACI_CMD_ECHO                    = 0x02,
+ /**
+  * Send a BTLE DTM command to the radio
+  */
+  ACI_CMD_DTM_CMD                 = 0x03,
+  /**
+  * Put the device to sleep
+  */
+  ACI_CMD_SLEEP                   = 0x04,
+ /**
+  * Wakeup the device from deep sleep
+  */
+  ACI_CMD_WAKEUP                  = 0x05,
+ /**
+  * Replace the contents of the internal database with
+  * user provided data
+  */
+  ACI_CMD_SETUP                   = 0x06,
+ /**
+  * Read the portions of memory required to be restored after a power cycle
+  */
+  ACI_CMD_READ_DYNAMIC_DATA       = 0x07,
+ /**
+  * Write back the data retrieved using ACI_CMD_READ_DYNAMIC_DATA
+  */
+  ACI_CMD_WRITE_DYNAMIC_DATA      = 0x08,
+  /**
+  * Retrieve the device's version information
+  */
+  ACI_CMD_GET_DEVICE_VERSION      = 0x09,
+ /**
+  * Request the Bluetooth address and its type
+  */
+  ACI_CMD_GET_DEVICE_ADDRESS      = 0x0A,
+  /**
+  * Request the battery level measured by nRF8001
+  */
+  ACI_CMD_GET_BATTERY_LEVEL       = 0x0B,
+ /**
+  * Request the temperature value measured by nRF8001
+  */
+  ACI_CMD_GET_TEMPERATURE         = 0x0C,
+ /**
+  * Write to the local Attribute Database
+  */
+  ACI_CMD_SET_LOCAL_DATA          = 0x0D,
+ /**
+  * Reset the baseband and radio and go back to idle
+  */
+  ACI_CMD_RADIO_RESET          = 0x0E,
+ /**
+  * Start advertising and wait for a master connection
+  */
+  ACI_CMD_CONNECT                 = 0x0F,
+ /**
+  * Start advertising and wait for a master connection
+  */
+  ACI_CMD_BOND                    = 0x10,
+ /**
+  * Start advertising and wait for a master connection
+  */
+  ACI_CMD_DISCONNECT              = 0x11,
+ /**
+  * Throttles the Radio transmit power
+  */
+  ACI_CMD_SET_TX_POWER            = 0x12,
+ /**
+  * Trigger a connection parameter update
+  */
+  ACI_CMD_CHANGE_TIMING           = 0x13,
+ /**
+  * Open a remote pipe for data reception
+  */
+  ACI_CMD_OPEN_REMOTE_PIPE        = 0x14,
+ /**
+  * Transmit data over an open pipe
+  */
+  ACI_CMD_SEND_DATA               = 0x15,
+ /**
+  * Send an acknowledgment of received data
+  */
+  ACI_CMD_SEND_DATA_ACK           = 0x16,
+ /**
+  * Request data over an open pipe
+  */
+  ACI_CMD_REQUEST_DATA            = 0x17,
+ /**
+  * NACK a data reception
+  */
+  ACI_CMD_SEND_DATA_NACK          = 0x18,
+ /**
+  * Set application latency
+  */
+  ACI_CMD_SET_APP_LATENCY         = 0x19,
+ /**
+  * Set a security key
+  */
+  ACI_CMD_SET_KEY                 = 0x1A,
+ /**
+  * Open Advertising Pipes
+  */
+  ACI_CMD_OPEN_ADV_PIPE           = 0x1B,
+ /**
+  * Start non-connectable advertising
+  */
+  ACI_CMD_BROADCAST               = 0x1C,
+ /**
+  * Start a security request in bonding mode
+  */
+  ACI_CMD_BOND_SECURITY_REQUEST   = 0x1D,
+ /**
+  * Start Directed advertising towards a Bonded Peer
+  */
+  ACI_CMD_CONNECT_DIRECT          = 0x1E,
+ /**
+  * Close a previously opened remote pipe
+  */
+  ACI_CMD_CLOSE_REMOTE_PIPE       = 0x1F,
+ /**
+  * Invalid ACI command opcode
+  */
+  ACI_CMD_INVALID                 = 0xFF
+
+} _aci_packed_ aci_cmd_opcode_t;
+
+ACI_ASSERT_SIZE(aci_cmd_opcode_t, 1);
+
+/**
+ * @struct aci_cmd_params_test_t
+ * @brief  Structure for the ACI_CMD_TEST ACI command parameters
+ */
+typedef struct
+{
+  aci_test_mode_change_t test_mode_change; /**< enum aci_test_mode_change_t */
+} _aci_packed_ aci_cmd_params_test_t;
+
+ACI_ASSERT_SIZE(aci_cmd_params_test_t, 1);
+
+/**
+ * @struct aci_cmd_params_echo_t
+ * @brief  Structure for the ACI_CMD_ECHO ACI command parameters
+ */
+typedef struct
+{
+  uint8_t echo_data[ACI_ECHO_DATA_MAX_LEN];
+} _aci_packed_ aci_cmd_params_echo_t;
+
+ACI_ASSERT_SIZE(aci_cmd_params_echo_t, ACI_ECHO_DATA_MAX_LEN);
+
+/**
+ * @struct aci_cmd_params_dtm_cmd_t
+ * @brief  Structure for the ACI_CMD_DTM_CMD ACI command parameters
+ */
+typedef struct
+{
+  uint8_t                 cmd_msb;
+  uint8_t                 cmd_lsb;
+} _aci_packed_ aci_cmd_params_dtm_cmd_t;
+
+/**
+ * @struct aci_cmd_params_setup_t
+ * @brief  Structure for the ACI_CMD_SETUP ACI command parameters
+ */
+typedef struct
+{
+  uint8_t                 setup_data[1];
+} _aci_packed_ aci_cmd_params_setup_t;
+
+ACI_ASSERT_SIZE(aci_cmd_params_setup_t, 1);
+
+/**
+ * @struct aci_cmd_params_write_dynamic_data_t
+ * @brief  Structure for the ACI_CMD_WRITE_DYNAMIC_DATA ACI command parameters 
+ * @note Dynamic data chunk size in this command is defined to go up to ACI_PACKET_MAX_LEN - 3
+ */
+typedef struct
+{
+  uint8_t                 seq_no;
+  uint8_t                 dynamic_data[1];
+} _aci_packed_ aci_cmd_params_write_dynamic_data_t;
+
+/**
+ * @define aci_cmd_params_set_local_data_t
+ * @brief  Structure for the ACI_CMD_SET_LOCAL_DATA ACI command parameters
+ */
+typedef struct
+{
+  aci_tx_data_t tx_data;
+} _aci_packed_ aci_cmd_params_set_local_data_t;
+
+/**
+ * @struct aci_cmd_params_connect_t
+ * @brief  Structure for the ACI_CMD_CONNECT ACI command parameters
+ */
+typedef struct
+{
+  uint16_t        timeout;  /**< 0x0000 (no timeout) to 0x3FFF */
+  uint16_t        adv_interval;     /**< 16 bits of advertising interval for general discovery */
+} _aci_packed_ aci_cmd_params_connect_t;
+
+ACI_ASSERT_SIZE(aci_cmd_params_connect_t, 4);
+
+/**
+ * @define aci_cmd_params_bond_t
+ * @brief  Structure for the ACI_CMD_BOND ACI command parameters
+ */
+typedef struct
+{
+  uint16_t        timeout;  /**< 0x0000 (no timeout) to 0x3FFF */
+  uint16_t        adv_interval;     /**< 16 bits of advertising interval for general discovery */
+} _aci_packed_ aci_cmd_params_bond_t;
+
+ACI_ASSERT_SIZE(aci_cmd_params_bond_t, 4);
+
+/**
+ * @struct aci_cmd_params_disconnect_t
+ * @brief  Structure for the ACI_CMD_DISCONNECT ACI command parameters
+ */
+typedef struct
+{
+  aci_disconnect_reason_t         reason; /**< enum aci_disconnect_reason_t */
+} _aci_packed_ aci_cmd_params_disconnect_t;
+
+ACI_ASSERT_SIZE(aci_cmd_params_disconnect_t, 1);
+
+/**
+ * @struct aci_cmd_params_set_tx_power_t
+ * @brief  Structure for the ACI_CMD_SET_TX_POWER ACI command parameters
+ */
+typedef struct
+{
+  aci_device_output_power_t   device_power; /**< enum aci_device_output_power_t */
+} _aci_packed_ aci_cmd_params_set_tx_power_t;
+
+ACI_ASSERT_SIZE(aci_cmd_params_set_tx_power_t, 1);
+/**
+ * @struct aci_cmd_params_change_timing_t
+ * @brief  Structure for the ACI_CMD_CHANGE_TIMING ACI command parameters
+ */
+typedef struct
+{
+  aci_ll_conn_params_t    conn_params;
+} _aci_packed_ aci_cmd_params_change_timing_t;
+
+ACI_ASSERT_SIZE(aci_cmd_params_change_timing_t, 8);
+
+/**
+ * @struct aci_cmd_params_open_remote_pipe_t
+ * @brief  Structure for the ACI_CMD_OPEN_REMOTE_PIPE ACI command parameters
+ */
+typedef struct
+{
+  uint8_t pipe_number;
+} _aci_packed_ aci_cmd_params_open_remote_pipe_t;
+
+/**
+ * @struct aci_cmd_params_send_data_t
+ * @brief  Structure for the ACI_CMD_SEND_DATA ACI command parameters
+ */
+typedef struct
+{
+  aci_tx_data_t tx_data;
+} _aci_packed_ aci_cmd_params_send_data_t;
+
+/**
+ * @define aci_cmd_params_send_data_ack_t
+ * @brief  Structure for the ACI_CMD_SEND_DATA_ACK ACI command parameters
+ */
+typedef struct
+{
+  uint8_t pipe_number;
+} _aci_packed_ aci_cmd_params_send_data_ack_t;
+
+/**
+ * @struct aci_cmd_params_send_data_t
+ * @brief  Structure for the ACI_CMD_SEND_DATA ACI command parameters
+ */
+typedef struct
+{
+  uint8_t pipe_number;
+} _aci_packed_ aci_cmd_params_request_data_t;
+
+/**
+ * @define aci_cmd_params_send_data_nack_t
+ * @brief  Structure for the ACI_CMD_SEND_DATA_NACK ACI command parameters
+ */
+typedef struct
+{
+  uint8_t pipe_number;
+  uint8_t error_code;
+} _aci_packed_ aci_cmd_params_send_data_nack_t;
+
+ACI_ASSERT_SIZE(aci_cmd_params_send_data_nack_t, 2);
+
+/**
+ * @define aci_cmd_params_set_app_latency_t
+ * @brief  Structure for the ACI_CMD_SET_APP_LATENCY ACI command parameters
+ */
+typedef struct
+{
+  aci_app_latency_mode_t mode;
+  uint16_t latency;
+} _aci_packed_ aci_cmd_params_set_app_latency_t;
+
+ACI_ASSERT_SIZE(aci_cmd_params_set_app_latency_t, 3);
+/**
+ * @define aci_cmd_params_set_key_t
+ * @brief  Structure for the ACI_CMD_SET_KEY ACI command parameters
+ */
+typedef struct
+{
+  aci_key_type_t key_type;
+  union
+  {
+    uint8_t passkey[6];
+    uint8_t oob_key[16];
+  } key;
+} _aci_packed_ aci_cmd_params_set_key_t;
+
+ACI_ASSERT_SIZE(aci_cmd_params_set_key_t, 17);
+/**
+ * @define aci_cmd_params_open_adv_pipe_t
+ * @brief  Structure for the ACI_CMD_OPEN_ADV_PIPE ACI command parameters
+ */
+typedef struct
+{
+  uint8_t pipes[8];
+} _aci_packed_ aci_cmd_params_open_adv_pipe_t;
+
+/**
+ * @define aci_cmd_params_broadcast_t
+ * @brief  Structure for the ACI_CMD_BROADCAST ACI command parameters
+ */
+typedef struct
+{
+  uint16_t        timeout;  /**< 0x0000 (no timeout) to 0x3FFF */
+  uint16_t        adv_interval;     /**< 16 bits of advertising interval for general discovery */
+} _aci_packed_ aci_cmd_params_broadcast_t;
+
+/**
+ * @struct aci_cmd_params_close_remote_pipe_t
+ * @brief  Structure for the ACI_CMD_CLOSE_REMOTE_PIPE ACI command parameters
+ */
+typedef struct
+{
+  uint8_t pipe_number;
+} _aci_packed_ aci_cmd_params_close_remote_pipe_t;
+
+/**
+ * @struct aci_cmd_t
+ * @brief  Encapsulates a generic ACI command
+ */
+typedef struct
+{
+  uint8_t len;        /**< Length of the ACI command */
+  aci_cmd_opcode_t cmd_opcode; /**< enum aci_cmd_opcode_t -> Opcode of the ACI command */
+  union
+  {
+    aci_cmd_params_test_t                       test;
+    aci_cmd_params_echo_t                       echo;
+    aci_cmd_params_dtm_cmd_t                    dtm_cmd;
+    aci_cmd_params_setup_t                      setup;
+    aci_cmd_params_write_dynamic_data_t         write_dynamic_data;
+    aci_cmd_params_set_local_data_t             set_local_data;
+    aci_cmd_params_connect_t                    connect;
+    aci_cmd_params_bond_t                       bond;
+    aci_cmd_params_disconnect_t                 disconnect;
+    aci_cmd_params_set_tx_power_t               set_tx_power;
+    aci_cmd_params_change_timing_t              change_timing;
+    aci_cmd_params_open_remote_pipe_t           open_remote_pipe;
+    aci_cmd_params_send_data_t                  send_data;
+    aci_cmd_params_send_data_ack_t              send_data_ack;
+    aci_cmd_params_request_data_t               request_data;
+    aci_cmd_params_send_data_nack_t             send_data_nack;
+    aci_cmd_params_set_app_latency_t            set_app_latency;
+    aci_cmd_params_set_key_t                    set_key;
+    aci_cmd_params_open_adv_pipe_t              open_adv_pipe;
+    aci_cmd_params_broadcast_t                  broadcast;
+    aci_cmd_params_close_remote_pipe_t          close_remote_pipe;
+
+  } params;
+} _aci_packed_ aci_cmd_t;
+
+#endif // ACI_CMDS_H__
+
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/aci_evts.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/aci_evts.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/aci_evts.h	(revision 453)
@@ -0,0 +1,397 @@
+/* Copyright (c) 2014, Nordic Semiconductor ASA
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * @file
+ *
+ * @ingroup aci
+ *
+ * @brief Definitions for the ACI (Application Control Interface) events
+ */
+
+#ifndef ACI_EVTS_H__
+#define ACI_EVTS_H__
+
+#include "aci.h"
+
+/**
+ * @enum aci_evt_opcode_t
+ * @brief ACI event opcodes
+ */
+typedef enum
+{
+ /**
+  * Invalid event code
+  */
+  ACI_EVT_INVALID                     = 0x00,
+ /**
+  * Sent every time the device starts
+  */
+  ACI_EVT_DEVICE_STARTED              = 0x81,
+ /**
+  * Mirrors the ACI_CMD_ECHO
+  */
+  ACI_EVT_ECHO                        = 0x82,
+ /**
+  * Asynchronous hardware error event
+  */
+  ACI_EVT_HW_ERROR                  = 0x83,
+ /**
+  * Event opcode used as a event response for all commands
+  */
+  ACI_EVT_CMD_RSP                     = 0x84,
+ /**
+  * Link connected
+  */
+  ACI_EVT_CONNECTED                   = 0x85,
+ /**
+  * Link disconnected
+  */
+  ACI_EVT_DISCONNECTED                = 0x86,
+ /**
+  * Bond completion result
+  */
+  ACI_EVT_BOND_STATUS                 = 0x87,
+  /**
+  * Pipe bitmap for available pipes
+  */
+  ACI_EVT_PIPE_STATUS             = 0x88,
+ /**
+  * Sent to the application when the radio enters a connected state
+  * or when the timing of the radio connection changes
+  */
+  ACI_EVT_TIMING                      = 0x89,
+ /**
+  * Notification to the application that transmit credits are
+  * available
+  */
+  ACI_EVT_DATA_CREDIT                 = 0x8A,
+ /**
+  * Data acknowledgement event
+  */
+  ACI_EVT_DATA_ACK                    = 0x8B,
+ /**
+  * Data received notification event
+  */
+  ACI_EVT_DATA_RECEIVED               = 0x8C,
+ /**
+  * Error notification event
+  */
+  ACI_EVT_PIPE_ERROR                  = 0x8D,
+ /**
+  * Display Passkey Event
+  */
+  ACI_EVT_DISPLAY_PASSKEY             = 0x8E,
+ /**
+  * Security Key request
+  */
+  ACI_EVT_KEY_REQUEST                 = 0x8F
+
+} _aci_packed_ aci_evt_opcode_t;
+
+ACI_ASSERT_SIZE(aci_evt_opcode_t, 1);
+
+/**
+ * @struct aci_evt_params_device_started_t
+ * @brief Structure for the ACI_EVT_DEVICE_STARTED event return parameters
+ */
+typedef struct
+{
+  aci_device_operation_mode_t device_mode; /**< Mode in which the device is being started */
+  aci_hw_error_t hw_error;  /**< Hardware Error if available for the start */
+  uint8_t credit_available; /**< Flow control credit available for this specific FW build */
+} _aci_packed_ aci_evt_params_device_started_t;
+
+ACI_ASSERT_SIZE(aci_evt_params_device_started_t, 3);
+
+/**
+ * @struct aci_evt_params_hw_error_t
+ * @brief Structure for the ACI_EVT_HW_ERROR event return parameters
+ */
+typedef struct
+{
+  uint16_t line_num;
+  uint8_t file_name[20];
+} _aci_packed_ aci_evt_params_hw_error_t;
+
+ACI_ASSERT_SIZE(aci_evt_params_hw_error_t, 22);
+
+/**
+ * @struct aci_evt_cmd_rsp_params_dtm_cmd_t
+ * @brief Structure for the ACI_EVT_CMD_RSP event with opcode=ACI_CMD_DTM_CMD event return parameters
+ */
+typedef struct
+{
+  uint8_t  evt_msb;
+  uint8_t  evt_lsb;
+} _aci_packed_ aci_evt_cmd_rsp_params_dtm_cmd_t;
+
+/**
+ * @struct aci_evt_cmd_rsp_read_dynamic_data_t
+ * @brief Structure for the ACI_EVT_CMD_RSP event with opcode=ACI_CMD_READ_DYNAMIC_DATA event return parameters
+ * @note Dynamic data chunk size in this event is defined to go up to ACI_PACKET_MAX_LEN - 5
+ */
+typedef struct
+{
+  uint8_t seq_no;
+  uint8_t dynamic_data[1];
+} _aci_packed_ aci_evt_cmd_rsp_read_dynamic_data_t;
+
+/**
+ * @struct aci_evt_cmd_rsp_params_get_device_version_t
+ * @brief Structure for the ACI_EVT_CMD_RSP event with opcode=ACI_CMD_GET_DEVICE_VERSION event return parameters
+ */
+typedef struct
+{
+  uint16_t  configuration_id;
+  uint8_t   aci_version;
+  uint8_t   setup_format;
+  uint32_t  setup_id;
+  uint8_t   setup_status;
+} _aci_packed_ aci_evt_cmd_rsp_params_get_device_version_t;
+
+ACI_ASSERT_SIZE(aci_evt_cmd_rsp_params_get_device_version_t, 9);
+
+/**
+ * @struct aci_evt_cmd_rsp_params_get_device_address_t
+ * @brief Structure for the ACI_EVT_CMD_RSP event with opcode=ACI_CMD_GET_DEVICE_ADDRESS event return parameters
+ */
+typedef struct
+{
+  uint8_t  bd_addr_own[BTLE_DEVICE_ADDRESS_SIZE];
+  aci_bd_addr_type_t bd_addr_type;
+} _aci_packed_ aci_evt_cmd_rsp_params_get_device_address_t;
+
+ACI_ASSERT_SIZE(aci_evt_cmd_rsp_params_get_device_address_t, BTLE_DEVICE_ADDRESS_SIZE + 1);
+
+/**
+ * @struct aci_evt_cmd_rsp_params_get_battery_level_t
+ * @brief Structure for the ACI_EVT_CMD_RSP event with opcode=ACI_CMD_GET_BATTERY_LEVEL event return parameters
+ */
+typedef struct
+{
+  uint16_t battery_level;
+} _aci_packed_ aci_evt_cmd_rsp_params_get_battery_level_t;
+
+/**
+ * @struct aci_evt_cmd_rsp_params_get_temperature_t
+ * @brief Structure for the ACI_EVT_CMD_RSP event with opcode=ACI_CMD_GET_TEMPERATURE event return parameters
+ */
+typedef struct
+{
+  int16_t temperature_value;
+} _aci_packed_ aci_evt_cmd_rsp_params_get_temperature_t;
+
+/**
+ * @struct aci_evt_params_cmd_rsp_t
+ * @brief Structure for the ACI_EVT_CMD_RSP event return parameters
+ */
+typedef struct
+{
+  aci_cmd_opcode_t cmd_opcode; /**< Command opcode for which the event response is being sent */
+  aci_status_code_t cmd_status; /**< Status of the command that was sent. Used in the context of the command. */
+  union
+  {
+    aci_evt_cmd_rsp_params_dtm_cmd_t dtm_cmd;
+    aci_evt_cmd_rsp_read_dynamic_data_t read_dynamic_data;
+    aci_evt_cmd_rsp_params_get_device_version_t get_device_version;
+    aci_evt_cmd_rsp_params_get_device_address_t get_device_address;
+    aci_evt_cmd_rsp_params_get_battery_level_t  get_battery_level;
+    aci_evt_cmd_rsp_params_get_temperature_t    get_temperature;
+    uint8_t                                     padding[29];  
+  } params;
+} _aci_packed_ aci_evt_params_cmd_rsp_t;
+
+ACI_ASSERT_SIZE(aci_evt_params_cmd_rsp_t, 31);
+
+/**
+ * @struct aci_evt_params_connected_t
+ * @brief Structure for the ACI_EVT_CONNECTED event return parameters
+ */
+typedef struct
+{
+  aci_bd_addr_type_t dev_addr_type;
+  uint8_t  dev_addr[BTLE_DEVICE_ADDRESS_SIZE];
+  uint16_t conn_rf_interval;  /**< rf_interval = conn_rf_interval * 1.25 ms Range:0x0006 to 0x0C80 */
+  uint16_t conn_slave_rf_latency; /**< Number of RF events the slave can skip */
+  uint16_t conn_rf_timeout; /**< Timeout as a multiple of 10ms i.e timeout = conn_rf_timeout * 10ms Range: 0x000A to 0x0C80 */
+  aci_clock_accuracy_t master_clock_accuracy; /**< Clock accuracy of Bluetooth master: Enumerated list of values from 500 ppm to 20 ppm */
+} _aci_packed_ aci_evt_params_connected_t;
+
+ACI_ASSERT_SIZE(aci_evt_params_connected_t, 14);
+
+/**
+ * @struct aci_evt_params_disconnected_t
+ * @brief Structure for the ACI_EVT_DISCONNECTED event return parameters
+ */
+typedef struct
+{
+  aci_status_code_t   aci_status;
+  uint8_t btle_status;
+} _aci_packed_ aci_evt_params_disconnected_t;
+
+ACI_ASSERT_SIZE(aci_evt_params_disconnected_t, 2);
+
+/**
+ * @struct aci_evt_params_bond_status_t
+ * @brief Structure for the ACI_EVT_BOND_STATUS event return parameters
+ */
+typedef struct
+{
+  aci_bond_status_code_t status_code;
+  aci_bond_status_source_t status_source;
+  uint8_t secmode1_bitmap;
+  uint8_t secmode2_bitmap;
+  uint8_t keys_exchanged_slave;
+  uint8_t keys_exchanged_master;
+} _aci_packed_ aci_evt_params_bond_status_t;
+
+ACI_ASSERT_SIZE(aci_evt_params_bond_status_t, 6);
+
+/**
+ * @struct aci_evt_params_pipe_status_t
+ * @brief Structure for the ACI_EVT_PIPE_STATUS event return parameters
+ */
+typedef struct
+{
+  uint8_t  pipes_open_bitmap[8];
+  uint8_t  pipes_closed_bitmap[8];
+} _aci_packed_ aci_evt_params_pipe_status_t;
+
+ACI_ASSERT_SIZE(aci_evt_params_pipe_status_t, 16);
+
+/**
+ * @struct aci_evt_params_timing_t
+ * @brief Structure for the ACI_EVT_TIMING event return parameters
+ */
+typedef struct
+{
+  uint16_t conn_rf_interval;  /**< rf_interval = conn_rf_interval * 1.25 ms Range:0x0006 to 0x0C80 */
+  uint16_t conn_slave_rf_latency; /**< Number of RF events the slave can skip */
+  uint16_t conn_rf_timeout; /**< Timeout as a multiple of 10ms i.e timeout = conn_rf_timeout * 10ms Range: 0x000A to 0x0C80 */
+} _aci_packed_ aci_evt_params_timing_t;
+
+ACI_ASSERT_SIZE(aci_evt_params_timing_t, 6);
+
+/**
+ * @struct aci_evt_params_data_credit_t
+ * @brief Structure for the ACI_EVT_DATA_CREDIT event return parameters
+ */
+typedef struct
+{
+  uint8_t credit;
+} _aci_packed_ aci_evt_params_data_credit_t;
+
+/**
+ * @struct aci_evt_params_data_ack_t
+ * @brief Structure for the ACI_EVT_DATA_ACK event return parameters
+ */
+typedef struct
+{
+  uint8_t pipe_number;
+} _aci_packed_ aci_evt_params_data_ack_t;
+
+/**
+ * @struct aci_evt_params_data_received_t
+ * @brief Structure for the ACI_EVT_DATA_RECEIVED event return parameters
+ */
+typedef struct
+{
+  aci_rx_data_t rx_data;
+} _aci_packed_ aci_evt_params_data_received_t;
+
+typedef struct
+{
+  uint8_t content[1];
+} _aci_packed_ error_data_t;
+
+/**
+ * @struct aci_evt_params_pipe_error_t
+ * @brief Structure for the ACI_EVT_PIPE_ERROR event return parameters
+ */
+typedef struct
+{
+  uint8_t pipe_number;
+  uint8_t error_code;
+  union 
+  {
+    error_data_t  error_data;
+  } params;
+} _aci_packed_ aci_evt_params_pipe_error_t;
+
+/**
+ * @struct aci_evt_params_display_passkey_t
+ * @brief Structure for the ACI_EVT_DISPLAY_PASSKEY event return parameters
+ */
+typedef struct
+{
+  uint8_t passkey[6];
+} _aci_packed_ aci_evt_params_display_passkey_t;
+
+/**
+ * @struct aci_evt_params_key_request_t
+ * @brief Structure for the ACI_EVT_KEY_REQUEST event return parameters
+ */
+typedef struct
+{
+  aci_key_type_t key_type;
+} _aci_packed_ aci_evt_params_key_request_t;
+
+/**
+ * @struct aci_event_params_echo_t
+ * @brief  Structure for the ACI_EVT_ECHO ACI event parameters
+ */
+typedef struct
+{
+  uint8_t echo_data[ACI_ECHO_DATA_MAX_LEN];
+} _aci_packed_ aci_evt_params_echo_t;
+
+/**
+ * @struct aci_evt_t
+ * @brief  Encapsulates a generic ACI event
+ */
+typedef struct
+{
+  uint8_t len;
+  aci_evt_opcode_t evt_opcode;
+  union
+  {
+    aci_evt_params_device_started_t                     device_started;
+    aci_evt_params_echo_t                               echo;
+    aci_evt_params_hw_error_t                           hw_error;
+    aci_evt_params_cmd_rsp_t                            cmd_rsp;
+    aci_evt_params_connected_t                          connected;
+    aci_evt_params_disconnected_t                       disconnected;
+    aci_evt_params_bond_status_t                        bond_status;
+    aci_evt_params_pipe_status_t                        pipe_status;
+    aci_evt_params_timing_t                             timing;
+    aci_evt_params_data_credit_t                        data_credit;
+    aci_evt_params_data_ack_t                           data_ack;
+    aci_evt_params_data_received_t                      data_received;
+    aci_evt_params_pipe_error_t                         pipe_error;
+    aci_evt_params_display_passkey_t                    display_passkey;
+    aci_evt_params_key_request_t                        key_request;
+  } params;
+} _aci_packed_ aci_evt_t;
+
+ACI_ASSERT_SIZE(aci_evt_t, 33);
+
+#endif // ACI_EVTS_H__
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/aci_protocol_defines.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/aci_protocol_defines.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/aci_protocol_defines.h	(revision 453)
@@ -0,0 +1,188 @@
+/* Copyright (c) 2014, Nordic Semiconductor ASA
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * This file contents defines for the position of all the fields of ACI
+ * command or event messages
+ */
+
+#ifndef ACI_OFFSET_H__
+#define ACI_OFFSET_H__
+
+
+	#define OFFSET_ACI_LL_CONN_PARAMS_T_MIN_CONN_INTERVAL_LSB 0
+	#define OFFSET_ACI_LL_CONN_PARAMS_T_MIN_CONN_INTERVAL_MSB 1
+	#define OFFSET_ACI_LL_CONN_PARAMS_T_MAX_CONN_INTERVAL_LSB 2
+	#define OFFSET_ACI_LL_CONN_PARAMS_T_MAX_CONN_INTERVAL_MSB 3
+	#define OFFSET_ACI_LL_CONN_PARAMS_T_SLAVE_LATENCY_LSB 4
+	#define OFFSET_ACI_LL_CONN_PARAMS_T_SLAVE_LATENCY_MSB 5
+	#define OFFSET_ACI_LL_CONN_PARAMS_T_TIMEOUT_MULT_LSB 6
+	#define OFFSET_ACI_LL_CONN_PARAMS_T_TIMEOUT_MULT_MSB 7
+	#define OFFSET_ACI_TX_DATA_T_PIPE_NUMBER 0
+	#define OFFSET_ACI_TX_DATA_T_ACI_DATA 1
+	#define OFFSET_ACI_RX_DATA_T_PIPE_NUMBER 0
+	#define OFFSET_ACI_RX_DATA_T_ACI_DATA 1
+	#define OFFSET_ACI_CMD_PARAMS_TEST_T_TEST_MODE_CHANGE 0
+	#define OFFSET_ACI_CMD_PARAMS_ECHO_T_ECHO_DATA 0
+	#define OFFSET_ACI_CMD_PARAMS_DTM_CMD_T_CMD_MSB 0
+	#define OFFSET_ACI_CMD_PARAMS_DTM_CMD_T_CMD_LSB 1
+	#define OFFSET_ACI_CMD_PARAMS_SETUP_T_SETUP_DATA 0
+	#define OFFSET_ACI_CMD_PARAMS_WRITE_DYNAMIC_DATA_T_SEQ_NO 0
+	#define OFFSET_ACI_CMD_PARAMS_WRITE_DYNAMIC_DATA_T_DYNAMIC_DATA 1
+	#define OFFSET_ACI_CMD_PARAMS_SET_LOCAL_DATA_T_TX_DATA 0
+	#define OFFSET_ACI_CMD_PARAMS_CONNECT_T_TIMEOUT_LSB 0
+	#define OFFSET_ACI_CMD_PARAMS_CONNECT_T_TIMEOUT_MSB 1
+	#define OFFSET_ACI_CMD_PARAMS_CONNECT_T_ADV_INTERVAL_LSB 2
+	#define OFFSET_ACI_CMD_PARAMS_CONNECT_T_ADV_INTERVAL_MSB 3
+	#define OFFSET_ACI_CMD_PARAMS_BOND_T_TIMEOUT_LSB 0
+	#define OFFSET_ACI_CMD_PARAMS_BOND_T_TIMEOUT_MSB 1
+	#define OFFSET_ACI_CMD_PARAMS_BOND_T_ADV_INTERVAL_LSB 2
+	#define OFFSET_ACI_CMD_PARAMS_BOND_T_ADV_INTERVAL_MSB 3
+	#define OFFSET_ACI_CMD_PARAMS_DISCONNECT_T_REASON 0
+	#define OFFSET_ACI_CMD_PARAMS_SET_TX_POWER_T_DEVICE_POWER 0
+	#define OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS 0
+	#define OFFSET_ACI_CMD_PARAMS_OPEN_REMOTE_PIPE_T_PIPE_NUMBER 0
+	#define OFFSET_ACI_CMD_PARAMS_SEND_DATA_T_TX_DATA 0
+	#define OFFSET_ACI_CMD_PARAMS_SEND_DATA_ACK_T_PIPE_NUMBER 0
+	#define OFFSET_ACI_CMD_PARAMS_REQUEST_DATA_T_PIPE_NUMBER 0
+	#define OFFSET_ACI_CMD_PARAMS_SEND_DATA_NACK_T_PIPE_NUMBER 0
+	#define OFFSET_ACI_CMD_PARAMS_SEND_DATA_NACK_T_ERROR_CODE 1
+	#define OFFSET_ACI_CMD_PARAMS_SET_APP_LATENCY_T_MODE 0
+	#define OFFSET_ACI_CMD_PARAMS_SET_APP_LATENCY_T_LATENCY_LSB 1
+	#define OFFSET_ACI_CMD_PARAMS_SET_APP_LATENCY_T_LATENCY_MSB 2
+	#define OFFSET_ACI_CMD_PARAMS_SET_KEY_T_KEY_TYPE 0
+	#define OFFSET_ACI_CMD_PARAMS_SET_KEY_T_PASSKEY 1
+	#define OFFSET_ACI_CMD_PARAMS_SET_KEY_T_OOB_KEY 1
+	#define OFFSET_ACI_CMD_PARAMS_OPEN_ADV_PIPE_T_PIPES 0
+	#define OFFSET_ACI_CMD_PARAMS_BROADCAST_T_TIMEOUT_LSB 0
+	#define OFFSET_ACI_CMD_PARAMS_BROADCAST_T_TIMEOUT_MSB 1
+	#define OFFSET_ACI_CMD_PARAMS_BROADCAST_T_ADV_INTERVAL_LSB 2
+	#define OFFSET_ACI_CMD_PARAMS_BROADCAST_T_ADV_INTERVAL_MSB 3
+	#define OFFSET_ACI_CMD_PARAMS_CLOSE_REMOTE_PIPE_T_PIPE_NUMBER 0
+	#define OFFSET_ACI_CMD_T_LEN 0
+	#define OFFSET_ACI_CMD_T_CMD_OPCODE 1
+	#define OFFSET_ACI_CMD_T_TEST 2
+	#define OFFSET_ACI_CMD_T_ECHO 2
+	#define OFFSET_ACI_CMD_T_DTM_CMD 2
+	#define OFFSET_ACI_CMD_T_SETUP 2
+	#define OFFSET_ACI_CMD_T_WRITE_DYNAMIC_DATA 2
+	#define OFFSET_ACI_CMD_T_SET_LOCAL_DATA 2
+	#define OFFSET_ACI_CMD_T_CONNECT 2
+	#define OFFSET_ACI_CMD_T_BOND 2
+	#define OFFSET_ACI_CMD_T_DISCONNECT 2
+	#define OFFSET_ACI_CMD_T_SET_TX_POWER 2
+	#define OFFSET_ACI_CMD_T_CHANGE_TIMING 2
+	#define OFFSET_ACI_CMD_T_OPEN_REMOTE_PIPE 2
+	#define OFFSET_ACI_CMD_T_SEND_DATA 2
+	#define OFFSET_ACI_CMD_T_SEND_DATA_ACK 2
+	#define OFFSET_ACI_CMD_T_REQUEST_DATA 2
+	#define OFFSET_ACI_CMD_T_SEND_DATA_NACK 2
+	#define OFFSET_ACI_CMD_T_SET_APP_LATENCY 2
+	#define OFFSET_ACI_CMD_T_SET_KEY 2
+	#define OFFSET_ACI_CMD_T_OPEN_ADV_PIPE 2
+	#define OFFSET_ACI_CMD_T_BROADCAST 2
+	#define OFFSET_ACI_CMD_T_CLOSE_REMOTE_PIPE 2
+	#define OFFSET_ACI_EVT_PARAMS_DEVICE_STARTED_T_DEVICE_MODE 0
+	#define OFFSET_ACI_EVT_PARAMS_DEVICE_STARTED_T_HW_ERROR 1
+	#define OFFSET_ACI_EVT_PARAMS_DEVICE_STARTED_T_CREDIT_AVAILABLE 2
+	#define OFFSET_ACI_EVT_PARAMS_HW_ERROR_T_LINE_NUM_LSB 0
+	#define OFFSET_ACI_EVT_PARAMS_HW_ERROR_T_LINE_NUM_MSB 1
+	#define OFFSET_ACI_EVT_PARAMS_HW_ERROR_T_FILE_NAME 2
+	#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_DTM_CMD_T_EVT_MSB 0
+	#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_DTM_CMD_T_EVT_LSB 1
+	#define OFFSET_ACI_EVT_CMD_RSP_READ_DYNAMIC_DATA_T_SEQ_NO 0
+	#define OFFSET_ACI_EVT_CMD_RSP_READ_DYNAMIC_DATA_T_DYNAMIC_DATA 1
+	#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_CONFIGURATION_ID_LSB 0
+	#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_CONFIGURATION_ID_MSB 1
+	#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_ACI_VERSION 2
+	#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_FORMAT 3
+	#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_LSB0 4
+	#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_LSB1 5
+	#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_MSB0 6
+	#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_MSB1 7
+	#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_STATUS 8
+	#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_ADDRESS_T_BD_ADDR_OWN 0
+	#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_ADDRESS_T_BD_ADDR_TYPE 6
+	#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_BATTERY_LEVEL_T_BATTERY_LEVEL_LSB 0
+	#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_BATTERY_LEVEL_T_BATTERY_LEVEL_MSB 1
+	#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_TEMPERATURE_T_TEMPERATURE_VALUE_LSB 0
+	#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_TEMPERATURE_T_TEMPERATURE_VALUE_MSB 1
+	#define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_CMD_OPCODE 0
+	#define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_CMD_STATUS 1
+	#define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_DTM_CMD 2
+	#define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_READ_DYNAMIC_DATA 2
+	#define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION 2
+	#define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_ADDRESS 2
+	#define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_BATTERY_LEVEL 2
+	#define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_TEMPERATURE 2
+	#define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_DEV_ADDR_TYPE 0
+	#define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_DEV_ADDR 1
+	#define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_INTERVAL_LSB 7
+	#define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_INTERVAL_MSB 8
+	#define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_SLAVE_RF_LATENCY_LSB 9
+	#define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_SLAVE_RF_LATENCY_MSB 10
+	#define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_TIMEOUT_LSB 11
+	#define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_TIMEOUT_MSB 12
+	#define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_MASTER_CLOCK_ACCURACY 13
+	#define OFFSET_ACI_EVT_PARAMS_DISCONNECTED_T_ACI_STATUS 0
+	#define OFFSET_ACI_EVT_PARAMS_DISCONNECTED_T_BTLE_STATUS 1
+	#define OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_STATUS_CODE 0
+	#define OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_STATUS_SOURCE 1
+	#define OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_SECMODE1_BITMAP 2
+	#define OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_SECMODE2_BITMAP 3
+	#define OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_KEYS_EXCHANGED_SLAVE 4
+	#define OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_KEYS_EXCHANGED_MASTER 5
+	#define OFFSET_ACI_EVT_PARAMS_PIPE_STATUS_T_PIPES_OPEN_BITMAP 0
+	#define OFFSET_ACI_EVT_PARAMS_PIPE_STATUS_T_PIPES_CLOSED_BITMAP 8
+	#define OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_INTERVAL_LSB 0
+	#define OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_INTERVAL_MSB 1
+	#define OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_SLAVE_RF_LATENCY_LSB 2
+	#define OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_SLAVE_RF_LATENCY_MSB 3
+	#define OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_TIMEOUT_LSB 4
+	#define OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_TIMEOUT_MSB 5
+	#define OFFSET_ACI_EVT_PARAMS_DATA_CREDIT_T_CREDIT 0
+	#define OFFSET_ACI_EVT_PARAMS_DATA_ACK_T_PIPE_NUMBER 0
+	#define OFFSET_ACI_EVT_PARAMS_DATA_RECEIVED_T_RX_DATA 0
+	#define OFFSET_ERROR_DATA_T_CONTENT 0
+	#define OFFSET_ACI_EVT_PARAMS_PIPE_ERROR_T_PIPE_NUMBER 0
+	#define OFFSET_ACI_EVT_PARAMS_PIPE_ERROR_T_ERROR_CODE 1
+	#define OFFSET_ACI_EVT_PARAMS_PIPE_ERROR_T_ERROR_DATA 2
+	#define OFFSET_ACI_EVT_PARAMS_DISPLAY_PASSKEY_T_PASSKEY 0
+	#define OFFSET_ACI_EVT_PARAMS_KEY_REQUEST_T_KEY_TYPE 0
+	#define OFFSET_ACI_EVT_T_LEN 0
+	#define OFFSET_ACI_EVT_T_EVT_OPCODE 1
+	#define OFFSET_ACI_EVT_T_DEVICE_STARTED 2
+	#define OFFSET_ACI_EVT_T_HW_ERROR 2
+	#define OFFSET_ACI_EVT_T_CMD_RSP 2
+	#define OFFSET_ACI_EVT_T_CONNECTED 2
+	#define OFFSET_ACI_EVT_T_DISCONNECTED 2
+	#define OFFSET_ACI_EVT_T_BOND_STATUS 2
+	#define OFFSET_ACI_EVT_T_PIPE_STATUS 2
+	#define OFFSET_ACI_EVT_T_TIMING 2
+	#define OFFSET_ACI_EVT_T_DATA_CREDIT 2
+	#define OFFSET_ACI_EVT_T_DATA_ACK 2
+	#define OFFSET_ACI_EVT_T_DATA_RECEIVED 2
+	#define OFFSET_ACI_EVT_T_PIPE_ERROR 2
+	#define OFFSET_ACI_EVT_T_DISPLAY_PASSKEY 2
+	#define OFFSET_ACI_EVT_T_KEY_REQUEST 2
+
+#endif //ACI_OFFSET_H__
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/aci_queue.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/aci_queue.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/aci_queue.c	(revision 453)
@@ -0,0 +1,141 @@
+/* Copyright (c) 2014, Nordic Semiconductor ASA
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+ /** @file
+@brief Implementation of a circular queue for ACI data
+*/
+
+#include "hal_aci_tl.h"
+#include "aci_queue.h"
+#include "ble_assert.h"
+
+void aci_queue_init(aci_queue_t *aci_q)
+{
+  uint8_t loop;
+
+  ble_assert(NULL != aci_q);
+
+  aci_q->head = 0;
+  aci_q->tail = 0;
+  for(loop=0; loop<ACI_QUEUE_SIZE; loop++)
+  {
+    aci_q->aci_data[loop].buffer[0] = 0x00;
+    aci_q->aci_data[loop].buffer[1] = 0x00;
+  }
+}
+
+bool aci_queue_dequeue(aci_queue_t *aci_q, hal_aci_data_t *p_data)
+{
+  ble_assert(NULL != aci_q);
+  ble_assert(NULL != p_data);
+
+  if (aci_queue_is_empty(aci_q))
+  {
+    return false;
+  }
+
+  noInterrupts();
+  memcpy((uint8_t *)p_data, (uint8_t *)&(aci_q->aci_data[aci_q->head]), sizeof(hal_aci_data_t));
+  aci_q->head = (aci_q->head + 1) % ACI_QUEUE_SIZE;
+  interrupts();
+
+  return true;
+}
+
+bool aci_queue_enqueue(aci_queue_t *aci_q, hal_aci_data_t *p_data)
+{
+  const uint8_t length = p_data->buffer[0];
+
+  ble_assert(NULL != aci_q);
+  ble_assert(NULL != p_data);
+
+  if (aci_queue_is_full(aci_q))
+  {
+    return false;
+  }
+
+  noInterrupts();
+  aci_q->aci_data[aci_q->tail].status_byte = 0;
+  memcpy((uint8_t *)&(aci_q->aci_data[aci_q->tail].buffer[0]), (uint8_t *)&p_data->buffer[0], length + 1);
+  aci_q->tail = (aci_q->tail + 1) % ACI_QUEUE_SIZE;
+  interrupts();
+
+  return true;
+}
+
+bool aci_queue_is_empty(aci_queue_t *aci_q)
+{
+  bool state = false;
+
+  ble_assert(NULL != aci_q);
+
+  //Critical section
+  noInterrupts();
+  if (aci_q->head == aci_q->tail)
+  {
+    state = true;
+  }
+  interrupts();
+
+  return state;
+}
+
+bool aci_queue_is_full(aci_queue_t *aci_q)
+{
+  uint8_t next;
+  bool state;
+
+  ble_assert(NULL != aci_q);
+
+  //This should be done in a critical section
+  noInterrupts();
+  next = (aci_q->tail + 1) % ACI_QUEUE_SIZE;
+
+  if (next == aci_q->head)
+  {
+    state = true;
+  }
+  else
+  {
+    state = false;
+  }
+
+  interrupts();
+  //end
+
+  return state;
+}
+
+bool aci_queue_peek(aci_queue_t *aci_q, hal_aci_data_t *p_data)
+{
+  ble_assert(NULL != aci_q);
+  ble_assert(NULL != p_data);
+
+  if (aci_queue_is_empty(aci_q))
+  {
+    return false;
+  }
+
+  memcpy((uint8_t *)p_data, (uint8_t *)&(aci_q->aci_data[aci_q->head]), sizeof(hal_aci_data_t));
+
+  return true;
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/aci_queue.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/aci_queue.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/aci_queue.h	(revision 453)
@@ -0,0 +1,76 @@
+/* Copyright (c) 2014, Nordic Semiconductor ASA
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/** @file
+ * @brief Interface for buffer.
+ */
+
+/** @defgroup aci_queue aci_queue
+@{
+@ingroup aci_queue
+
+*/
+
+#ifndef ACI_QUEUE_H__
+#define ACI_QUEUE_H__
+
+#include "aci.h"
+#include "hal_aci_tl.h"
+
+/***********************************************************************    */
+/* The ACI_QUEUE_SIZE determines the memory usage of the system.            */
+/* Successfully tested to a ACI_QUEUE_SIZE of 4 (interrupt) and 4 (polling) */
+/***********************************************************************    */
+#define ACI_QUEUE_SIZE  4
+
+/** Data type for queue of data packets to send/receive from radio.
+ *
+ *  A FIFO queue is maintained for packets. New packets are added (enqueued)
+ *  at the tail and taken (dequeued) from the head. The head variable is the
+ *  index of the next packet to dequeue while the tail variable is the index of
+ *  where the next packet should be queued.
+ */
+
+typedef struct {
+	hal_aci_data_t           aci_data[ACI_QUEUE_SIZE];
+	uint8_t                  head;
+	uint8_t                  tail;
+} aci_queue_t;
+
+void aci_queue_init(aci_queue_t *aci_q);
+
+bool aci_queue_dequeue(aci_queue_t *aci_q, hal_aci_data_t *p_data);
+bool aci_queue_dequeue_from_isr(aci_queue_t *aci_q, hal_aci_data_t *p_data);
+
+bool aci_queue_enqueue(aci_queue_t *aci_q, hal_aci_data_t *p_data);
+bool aci_queue_enqueue_from_isr(aci_queue_t *aci_q, hal_aci_data_t *p_data);
+
+bool aci_queue_is_empty(aci_queue_t *aci_q);
+bool aci_queue_is_empty_from_isr(aci_queue_t *aci_q);
+
+bool aci_queue_is_full(aci_queue_t *aci_q);
+bool aci_queue_is_full_from_isr(aci_queue_t *aci_q);
+
+bool aci_queue_peek(aci_queue_t *aci_q, hal_aci_data_t *p_data);
+bool aci_queue_peek_from_isr(aci_queue_t *aci_q, hal_aci_data_t *p_data);
+
+#endif /* ACI_QUEUE_H__ */
+/** @} */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/aci_setup.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/aci_setup.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/aci_setup.c	(revision 453)
@@ -0,0 +1,171 @@
+/* Copyright (c) 2014, Nordic Semiconductor ASA
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <lib_aci.h>
+#include "aci_setup.h"
+
+
+// aci_struct that will contain 
+// total initial credits
+// current credit
+// current state of the aci (setup/standby/active/sleep)
+// open remote pipe pending
+// close remote pipe pending
+// Current pipe available bitmap
+// Current pipe closed bitmap
+// Current connection interval, slave latency and link supervision timeout
+// Current State of the the GATT client (Service Discovery status)
+
+
+extern hal_aci_data_t msg_to_send;
+
+
+
+/**************************************************************************                */
+/* Utility function to fill the the ACI command queue                                      */
+/* aci_stat               Pointer to the ACI state                                         */
+/* num_cmd_offset(in/out) Offset in the Setup message array to start from                  */
+/*                        offset is updated to the new index after the queue is filled     */
+/*                        or the last message us placed in the queue                       */
+/* Returns                true if at least one message was transferred                     */
+/***************************************************************************/
+static bool aci_setup_fill(aci_state_t *aci_stat, uint8_t *num_cmd_offset)
+{
+  bool ret_val = false;
+  
+  while (*num_cmd_offset < aci_stat->aci_setup_info.num_setup_msgs)
+  {
+	//Board dependent defines
+	#if defined (__AVR__)
+		//For Arduino copy the setup ACI message from Flash to RAM.
+		memcpy_P(&msg_to_send, &(aci_stat->aci_setup_info.setup_msgs[*num_cmd_offset]), 
+				  pgm_read_byte_near(&(aci_stat->aci_setup_info.setup_msgs[*num_cmd_offset].buffer[0]))+2); 
+	#elif defined(__PIC32MX__) || defined(__STM32__)
+		//In ChipKit we store the setup messages in RAM
+		//Add 2 bytes to the length byte for status byte, length for the total number of bytes
+		memcpy(&msg_to_send, &(aci_stat->aci_setup_info.setup_msgs[*num_cmd_offset]), 
+				  (aci_stat->aci_setup_info.setup_msgs[*num_cmd_offset].buffer[0]+2)); 
+	#endif
+
+    //Put the Setup ACI message in the command queue
+    if (!hal_aci_tl_send(&msg_to_send))
+    {
+      //ACI Command Queue is full
+      // *num_cmd_offset is now pointing to the index of the Setup command that did not get sent
+      return ret_val;
+    }
+   
+    ret_val = true;
+    
+    (*num_cmd_offset)++;
+  }
+  
+  return ret_val;
+}
+
+uint8_t do_aci_setup(aci_state_t *aci_stat)
+{
+  uint8_t setup_offset         = 0;
+  uint32_t i                   = 0x0000;
+  aci_evt_t * aci_evt          = NULL;
+  aci_status_code_t cmd_status = ACI_STATUS_ERROR_CRC_MISMATCH;
+  
+  /*
+  We are using the same buffer since we are copying the contents of the buffer 
+  when queuing and immediately processing the buffer when receiving
+  */
+  hal_aci_evt_t  *aci_data = (hal_aci_evt_t *)&msg_to_send;
+  
+  /* Messages in the outgoing queue must be handled before the Setup routine can run.
+   * If it is non-empty we return. The user should then process the messages before calling
+   * do_aci_setup() again.
+   */
+  if (!lib_aci_command_queue_empty())
+  {
+    return SETUP_FAIL_COMMAND_QUEUE_NOT_EMPTY;
+  }
+  
+  /* If there are events pending from the device that are not relevant to setup, we return false
+   * so that the user can handle them. At this point we don't care what the event is,
+   * as any event is an error.
+   */
+  if (lib_aci_event_peek(aci_data))
+  {
+    return SETUP_FAIL_EVENT_QUEUE_NOT_EMPTY;
+  }
+  
+  /* Fill the ACI command queue with as many Setup messages as it will hold. */
+  aci_setup_fill(aci_stat, &setup_offset);
+  
+  while (cmd_status != ACI_STATUS_TRANSACTION_COMPLETE)
+  {
+    /* This counter is used to ensure that this function does not loop forever. When the device
+     * returns a valid response, we reset the counter.
+     */
+    if (i++ > 0xFFFFE)
+    {
+      return SETUP_FAIL_TIMEOUT;	
+    }
+    
+    if (lib_aci_event_peek(aci_data))
+    {
+      aci_evt = &(aci_data->evt);
+      
+      if (ACI_EVT_CMD_RSP != aci_evt->evt_opcode)
+      {
+        //Receiving something other than a Command Response Event is an error.
+        return SETUP_FAIL_NOT_COMMAND_RESPONSE;
+      }
+      
+      cmd_status = (aci_status_code_t) aci_evt->params.cmd_rsp.cmd_status;
+      switch (cmd_status)
+      {
+        case ACI_STATUS_TRANSACTION_CONTINUE:
+          //As the device is responding, reset guard counter
+          i = 0;
+          
+          /* As the device has processed the Setup messages we put in the command queue earlier,
+           * we can proceed to fill the queue with new messages
+           */
+          aci_setup_fill(aci_stat, &setup_offset);
+          break;
+        
+        case ACI_STATUS_TRANSACTION_COMPLETE:
+          //Break out of the while loop when this status code appears
+          break;
+        
+        default:
+          //An event with any other status code should be handled by the application
+          return SETUP_FAIL_NOT_SETUP_EVENT;
+      }
+      
+      /* If we haven't returned at this point, the event was either ACI_STATUS_TRANSACTION_CONTINUE
+       * or ACI_STATUS_TRANSACTION_COMPLETE. We don't need the event itself, so we simply
+       * remove it from the queue.
+       */
+       lib_aci_event_get (aci_stat, aci_data);
+    }
+  }
+  
+  return SETUP_SUCCESS;
+}
+  
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/aci_setup.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/aci_setup.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/aci_setup.h	(revision 453)
@@ -0,0 +1,44 @@
+/* Copyright (c) 2014, Nordic Semiconductor ASA
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+ 
+ 
+#ifndef H_ACI_SETUP
+#define H_ACI_SETUP
+
+#define SETUP_SUCCESS                        0
+#define SETUP_FAIL_COMMAND_QUEUE_NOT_EMPTY   1
+#define SETUP_FAIL_EVENT_QUEUE_NOT_EMPTY     2
+#define SETUP_FAIL_TIMEOUT                   3
+#define SETUP_FAIL_NOT_SETUP_EVENT           4
+#define SETUP_FAIL_NOT_COMMAND_RESPONSE      5
+
+/** @brief Setup the nRF8001 device
+ *  @details
+ *  Performs ACI Setup by transmitting the setup messages generated by nRFgo Studio to the
+ *  nRF8001, and should be called when the nRF8001 starts or resets.
+ *  Once all messages are sent, the nRF8001 will send a Device Started Event.
+ *  The function requires that the Command queue is empty when it is invoked, and will fail
+ *  otherwise.
+ *  @returns An integer indicating the reason the function terminated
+ */
+uint8_t do_aci_setup(aci_state_t *aci_stat);
+
+#endif
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/acilib.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/acilib.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/acilib.c	(revision 453)
@@ -0,0 +1,612 @@
+/* Copyright (c) 2014, Nordic Semiconductor ASA
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * @file
+ *
+ * @ingroup group_acilib
+ *
+ * @brief Implementation of the acilib module.
+ */
+
+
+#include "hal_platform.h"
+#include "aci.h"
+#include "aci_cmds.h"
+#include "aci_evts.h"
+#include "acilib.h"
+#include "aci_protocol_defines.h"
+#include "acilib_defs.h"
+#include "acilib_if.h"
+#include "acilib_types.h"
+
+
+void acil_encode_cmd_set_test_mode(uint8_t *buffer, aci_cmd_params_test_t *p_aci_cmd_params_test)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = 2;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_TEST;
+  *(buffer + OFFSET_ACI_CMD_T_TEST + OFFSET_ACI_CMD_PARAMS_TEST_T_TEST_MODE_CHANGE) = p_aci_cmd_params_test->test_mode_change;
+}
+
+void acil_encode_cmd_sleep(uint8_t *buffer)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = 1;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SLEEP;
+}
+
+void acil_encode_cmd_get_device_version(uint8_t *buffer)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = 1;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_GET_DEVICE_VERSION;
+}
+
+void acil_encode_cmd_set_local_data(uint8_t *buffer, aci_cmd_params_set_local_data_t *p_aci_cmd_params_set_local_data, uint8_t data_size)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_SET_LOCAL_DATA_BASE_LEN + data_size;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SET_LOCAL_DATA;
+  *(buffer + OFFSET_ACI_CMD_T_SET_LOCAL_DATA + OFFSET_ACI_CMD_PARAMS_SEND_DATA_T_TX_DATA + OFFSET_ACI_TX_DATA_T_PIPE_NUMBER) = p_aci_cmd_params_set_local_data->tx_data.pipe_number;
+  memcpy(buffer + OFFSET_ACI_CMD_T_SET_LOCAL_DATA + OFFSET_ACI_CMD_PARAMS_SEND_DATA_T_TX_DATA + OFFSET_ACI_TX_DATA_T_ACI_DATA,  &(p_aci_cmd_params_set_local_data->tx_data.aci_data[0]), data_size);
+}
+
+void acil_encode_cmd_connect(uint8_t *buffer, aci_cmd_params_connect_t *p_aci_cmd_params_connect)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_CONNECT_LEN;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_CONNECT;
+  *(buffer + OFFSET_ACI_CMD_T_CONNECT + OFFSET_ACI_CMD_PARAMS_CONNECT_T_TIMEOUT_MSB) = (uint8_t)(p_aci_cmd_params_connect->timeout >> 8);
+  *(buffer + OFFSET_ACI_CMD_T_CONNECT + OFFSET_ACI_CMD_PARAMS_CONNECT_T_TIMEOUT_LSB) = (uint8_t)(p_aci_cmd_params_connect->timeout);
+  *(buffer + OFFSET_ACI_CMD_T_CONNECT + OFFSET_ACI_CMD_PARAMS_CONNECT_T_ADV_INTERVAL_MSB) = (uint8_t)(p_aci_cmd_params_connect->adv_interval >> 8);
+  *(buffer + OFFSET_ACI_CMD_T_CONNECT + OFFSET_ACI_CMD_PARAMS_CONNECT_T_ADV_INTERVAL_LSB) = (uint8_t)(p_aci_cmd_params_connect->adv_interval);
+}
+
+void acil_encode_cmd_bond(uint8_t *buffer, aci_cmd_params_bond_t *p_aci_cmd_params_bond)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_BOND_LEN;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_BOND;
+  *(buffer + OFFSET_ACI_CMD_T_BOND + OFFSET_ACI_CMD_PARAMS_BOND_T_TIMEOUT_MSB) = (uint8_t)(p_aci_cmd_params_bond->timeout >> 8);
+  *(buffer + OFFSET_ACI_CMD_T_BOND + OFFSET_ACI_CMD_PARAMS_BOND_T_TIMEOUT_LSB) = (uint8_t)(p_aci_cmd_params_bond->timeout);
+  *(buffer + OFFSET_ACI_CMD_T_BOND + OFFSET_ACI_CMD_PARAMS_BOND_T_ADV_INTERVAL_MSB) = (uint8_t)(p_aci_cmd_params_bond->adv_interval >> 8);
+  *(buffer + OFFSET_ACI_CMD_T_BOND + OFFSET_ACI_CMD_PARAMS_BOND_T_ADV_INTERVAL_LSB) = (uint8_t)(p_aci_cmd_params_bond->adv_interval);
+}
+
+void acil_encode_cmd_disconnect(uint8_t *buffer, aci_cmd_params_disconnect_t *p_aci_cmd_params_disconnect)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_DISCONNECT_LEN;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_DISCONNECT;
+  *(buffer + OFFSET_ACI_CMD_T_DISCONNECT + OFFSET_ACI_CMD_PARAMS_DISCONNECT_T_REASON) = (uint8_t)(p_aci_cmd_params_disconnect->reason);
+}
+
+void acil_encode_baseband_reset(uint8_t *buffer)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_BASEBAND_RESET_LEN;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_RADIO_RESET;
+}
+
+void acil_encode_direct_connect(uint8_t *buffer)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_DIRECT_CONNECT_LEN;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_CONNECT_DIRECT;
+}
+
+void acil_encode_cmd_wakeup(uint8_t *buffer)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_WAKEUP_LEN;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_WAKEUP;
+}
+
+void acil_encode_cmd_set_radio_tx_power(uint8_t *buffer, aci_cmd_params_set_tx_power_t *p_aci_cmd_params_set_tx_power)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_SET_RADIO_TX_POWER_LEN;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SET_TX_POWER;
+  *(buffer + OFFSET_ACI_CMD_T_SET_TX_POWER + OFFSET_ACI_CMD_PARAMS_SET_TX_POWER_T_DEVICE_POWER) = (uint8_t)p_aci_cmd_params_set_tx_power->device_power;
+}
+
+void acil_encode_cmd_get_address(uint8_t *buffer)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_GET_DEVICE_ADDR_LEN;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_GET_DEVICE_ADDRESS;
+}
+
+void acil_encode_cmd_send_data(uint8_t *buffer, aci_cmd_params_send_data_t *p_aci_cmd_params_send_data_t, uint8_t data_size)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_SEND_DATA_BASE_LEN + data_size;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SEND_DATA;
+  *(buffer + OFFSET_ACI_CMD_T_SEND_DATA + OFFSET_ACI_CMD_PARAMS_SEND_DATA_T_TX_DATA + OFFSET_ACI_TX_DATA_T_PIPE_NUMBER) = p_aci_cmd_params_send_data_t->tx_data.pipe_number;
+  memcpy((buffer + OFFSET_ACI_CMD_T_SEND_DATA + OFFSET_ACI_CMD_PARAMS_SEND_DATA_T_TX_DATA + OFFSET_ACI_TX_DATA_T_ACI_DATA), &(p_aci_cmd_params_send_data_t->tx_data.aci_data[0]), data_size);
+}
+
+void acil_encode_cmd_request_data(uint8_t *buffer, aci_cmd_params_request_data_t *p_aci_cmd_params_request_data)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_DATA_REQUEST_LEN;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_REQUEST_DATA;
+  *(buffer + OFFSET_ACI_CMD_T_REQUEST_DATA + OFFSET_ACI_CMD_PARAMS_REQUEST_DATA_T_PIPE_NUMBER) = p_aci_cmd_params_request_data->pipe_number;
+}
+
+void acil_encode_cmd_open_remote_pipe(uint8_t *buffer, aci_cmd_params_open_remote_pipe_t *p_aci_cmd_params_open_remote_pipe)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_OPEN_REMOTE_PIPE_LEN;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_OPEN_REMOTE_PIPE;
+  *(buffer + OFFSET_ACI_CMD_T_OPEN_REMOTE_PIPE + OFFSET_ACI_CMD_PARAMS_OPEN_REMOTE_PIPE_T_PIPE_NUMBER) = p_aci_cmd_params_open_remote_pipe->pipe_number;
+}
+
+void acil_encode_cmd_close_remote_pipe(uint8_t *buffer, aci_cmd_params_close_remote_pipe_t *p_aci_cmd_params_close_remote_pipe)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_CLOSE_REMOTE_PIPE_LEN;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_CLOSE_REMOTE_PIPE;
+  *(buffer + OFFSET_ACI_CMD_T_CLOSE_REMOTE_PIPE + OFFSET_ACI_CMD_PARAMS_CLOSE_REMOTE_PIPE_T_PIPE_NUMBER) = p_aci_cmd_params_close_remote_pipe->pipe_number;
+}
+
+void acil_encode_cmd_echo_msg(uint8_t *buffer, aci_cmd_params_echo_t *p_cmd_params_echo, uint8_t msg_size)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_ECHO_MSG_CMD_BASE_LEN + msg_size;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_ECHO;
+  memcpy((buffer + OFFSET_ACI_CMD_T_ECHO + OFFSET_ACI_CMD_PARAMS_ECHO_T_ECHO_DATA), &(p_cmd_params_echo->echo_data[0]), msg_size);
+}
+
+void acil_encode_cmd_battery_level(uint8_t *buffer)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = 1;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_GET_BATTERY_LEVEL;
+}
+
+void acil_encode_cmd_temparature(uint8_t *buffer)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = 1;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_GET_TEMPERATURE;
+}
+
+void acil_encode_cmd_read_dynamic_data(uint8_t *buffer)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = 1;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_READ_DYNAMIC_DATA;
+}
+
+void acil_encode_cmd_write_dynamic_data(uint8_t *buffer, uint8_t seq_no, uint8_t* dynamic_data, uint8_t dynamic_data_size)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_WRITE_DYNAMIC_DATA_BASE_LEN + dynamic_data_size;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_WRITE_DYNAMIC_DATA;
+  *(buffer + OFFSET_ACI_CMD_T_WRITE_DYNAMIC_DATA + OFFSET_ACI_CMD_PARAMS_WRITE_DYNAMIC_DATA_T_SEQ_NO) = seq_no;
+  memcpy((buffer + OFFSET_ACI_CMD_T_WRITE_DYNAMIC_DATA + OFFSET_ACI_CMD_PARAMS_WRITE_DYNAMIC_DATA_T_DYNAMIC_DATA), dynamic_data, dynamic_data_size);
+}
+
+void acil_encode_cmd_change_timing_req(uint8_t *buffer, aci_cmd_params_change_timing_t *p_aci_cmd_params_change_timing)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_CHANGE_TIMING_LEN;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_CHANGE_TIMING;
+  *(buffer + OFFSET_ACI_CMD_T_CHANGE_TIMING + OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS + OFFSET_ACI_LL_CONN_PARAMS_T_MIN_CONN_INTERVAL_MSB) = (uint8_t)(p_aci_cmd_params_change_timing->conn_params.min_conn_interval >> 8);
+  *(buffer + OFFSET_ACI_CMD_T_CHANGE_TIMING + OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS + OFFSET_ACI_LL_CONN_PARAMS_T_MIN_CONN_INTERVAL_LSB) = (uint8_t)(p_aci_cmd_params_change_timing->conn_params.min_conn_interval);
+  *(buffer + OFFSET_ACI_CMD_T_CHANGE_TIMING + OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS + OFFSET_ACI_LL_CONN_PARAMS_T_MAX_CONN_INTERVAL_MSB) = (uint8_t)(p_aci_cmd_params_change_timing->conn_params.max_conn_interval >> 8);
+  *(buffer + OFFSET_ACI_CMD_T_CHANGE_TIMING + OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS + OFFSET_ACI_LL_CONN_PARAMS_T_MAX_CONN_INTERVAL_LSB) = (uint8_t)(p_aci_cmd_params_change_timing->conn_params.max_conn_interval);
+  *(buffer + OFFSET_ACI_CMD_T_CHANGE_TIMING + OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS + OFFSET_ACI_LL_CONN_PARAMS_T_SLAVE_LATENCY_MSB    ) = (uint8_t)(p_aci_cmd_params_change_timing->conn_params.slave_latency >> 8);
+  *(buffer + OFFSET_ACI_CMD_T_CHANGE_TIMING + OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS + OFFSET_ACI_LL_CONN_PARAMS_T_SLAVE_LATENCY_LSB    ) = (uint8_t)(p_aci_cmd_params_change_timing->conn_params.slave_latency);
+  *(buffer + OFFSET_ACI_CMD_T_CHANGE_TIMING + OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS + OFFSET_ACI_LL_CONN_PARAMS_T_TIMEOUT_MULT_MSB     ) = (uint8_t)(p_aci_cmd_params_change_timing->conn_params.timeout_mult >> 8);
+  *(buffer + OFFSET_ACI_CMD_T_CHANGE_TIMING + OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS + OFFSET_ACI_LL_CONN_PARAMS_T_TIMEOUT_MULT_LSB     ) = (uint8_t)(p_aci_cmd_params_change_timing->conn_params.timeout_mult);
+}
+
+void acil_encode_cmd_set_app_latency(uint8_t *buffer, aci_cmd_params_set_app_latency_t *p_aci_cmd_params_set_app_latency)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_SET_APP_LATENCY_LEN;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SET_APP_LATENCY;
+  *(buffer + OFFSET_ACI_CMD_T_SET_APP_LATENCY + OFFSET_ACI_CMD_PARAMS_SET_APP_LATENCY_T_MODE) = (uint8_t)( p_aci_cmd_params_set_app_latency->mode);
+  *(buffer + OFFSET_ACI_CMD_T_SET_APP_LATENCY + OFFSET_ACI_CMD_PARAMS_SET_APP_LATENCY_T_LATENCY_MSB) = (uint8_t)( p_aci_cmd_params_set_app_latency->latency>>8);
+  *(buffer + OFFSET_ACI_CMD_T_SET_APP_LATENCY + OFFSET_ACI_CMD_PARAMS_SET_APP_LATENCY_T_LATENCY_LSB) = (uint8_t)( p_aci_cmd_params_set_app_latency->latency);
+}
+
+void acil_encode_cmd_change_timing_req_GAP_PPCP(uint8_t *buffer)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_CHANGE_TIMING_LEN_GAP_PPCP;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_CHANGE_TIMING;
+}
+
+
+void acil_encode_cmd_setup(uint8_t *buffer, aci_cmd_params_setup_t *p_aci_cmd_params_setup, uint8_t setup_data_size)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = setup_data_size + MSG_SETUP_CMD_BASE_LEN;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SETUP;
+  memcpy((buffer + OFFSET_ACI_CMD_T_SETUP), &(p_aci_cmd_params_setup->setup_data[0]), setup_data_size);
+}
+
+void acil_encode_cmd_dtm_cmd(uint8_t *buffer, aci_cmd_params_dtm_cmd_t *p_aci_cmd_params_dtm_cmd)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_DTM_CMD;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_DTM_CMD;
+  *(buffer + OFFSET_ACI_CMD_T_DTM_CMD) = p_aci_cmd_params_dtm_cmd->cmd_msb;
+  *(buffer + OFFSET_ACI_CMD_T_DTM_CMD + 1) = p_aci_cmd_params_dtm_cmd->cmd_lsb;
+}
+
+void acil_encode_cmd_send_data_ack(uint8_t *buffer, const uint8_t pipe_number )
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_ACK_LEN;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SEND_DATA_ACK;
+  *(buffer + OFFSET_ACI_CMD_T_SEND_DATA_ACK + OFFSET_ACI_CMD_PARAMS_SEND_DATA_ACK_T_PIPE_NUMBER) = pipe_number;
+}
+
+void acil_encode_cmd_send_data_nack(uint8_t *buffer, const uint8_t pipe_number, const uint8_t err_code )
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_NACK_LEN;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SEND_DATA_NACK;
+  *(buffer + OFFSET_ACI_CMD_T_SEND_DATA_NACK + OFFSET_ACI_CMD_PARAMS_SEND_DATA_NACK_T_PIPE_NUMBER) = pipe_number;
+  *(buffer + OFFSET_ACI_CMD_T_SEND_DATA_NACK + OFFSET_ACI_CMD_PARAMS_SEND_DATA_NACK_T_ERROR_CODE) = err_code;
+}
+
+void acil_encode_cmd_bond_security_request(uint8_t *buffer)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = 1;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_BOND_SECURITY_REQUEST;
+}
+
+void acil_encode_cmd_broadcast(uint8_t *buffer, aci_cmd_params_broadcast_t * p_aci_cmd_params_broadcast)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_BROADCAST_LEN;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_BROADCAST;
+  *(buffer + OFFSET_ACI_CMD_T_BROADCAST + OFFSET_ACI_CMD_PARAMS_BROADCAST_T_TIMEOUT_LSB) = (p_aci_cmd_params_broadcast->timeout & 0xff);
+  *(buffer + OFFSET_ACI_CMD_T_BROADCAST + OFFSET_ACI_CMD_PARAMS_BROADCAST_T_TIMEOUT_MSB) = (uint8_t)(p_aci_cmd_params_broadcast->timeout >> 8);
+  *(buffer + OFFSET_ACI_CMD_T_BROADCAST + OFFSET_ACI_CMD_PARAMS_BROADCAST_T_ADV_INTERVAL_LSB) = (p_aci_cmd_params_broadcast->adv_interval & 0xff);
+  *(buffer + OFFSET_ACI_CMD_T_BROADCAST + OFFSET_ACI_CMD_PARAMS_BROADCAST_T_ADV_INTERVAL_MSB) = (uint8_t)(p_aci_cmd_params_broadcast->adv_interval >> 8);
+}
+  
+void acil_encode_cmd_open_adv_pipes(uint8_t *buffer, aci_cmd_params_open_adv_pipe_t * p_aci_cmd_params_open_adv_pipe)
+{
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_OPEN_ADV_PIPES_LEN;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_OPEN_ADV_PIPE;
+  memcpy(buffer + OFFSET_ACI_CMD_T_OPEN_ADV_PIPE + OFFSET_ACI_CMD_PARAMS_OPEN_ADV_PIPE_T_PIPES, p_aci_cmd_params_open_adv_pipe->pipes, 8);
+}
+
+
+void acil_encode_cmd_set_key(uint8_t *buffer, aci_cmd_params_set_key_t *p_aci_cmd_params_set_key)
+{
+  /*
+  The length of the key is computed based on the type of key transaction.
+  - Key Reject
+  - Key type is passkey
+  */
+  uint8_t len;
+
+  switch (p_aci_cmd_params_set_key->key_type)
+  {
+    case ACI_KEY_TYPE_INVALID:
+    len = MSG_SET_KEY_REJECT_LEN;
+    break;
+    case ACI_KEY_TYPE_PASSKEY:
+    len = MSG_SET_KEY_PASSKEY_LEN;
+    break;
+    default:
+    len=0;
+    break;
+  }
+  *(buffer + OFFSET_ACI_CMD_T_LEN) = len;
+  *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SET_KEY;
+  *(buffer + OFFSET_ACI_CMD_T_SET_KEY + OFFSET_ACI_CMD_PARAMS_SET_KEY_T_KEY_TYPE) = p_aci_cmd_params_set_key->key_type;
+  memcpy((buffer + OFFSET_ACI_CMD_T_SET_KEY + OFFSET_ACI_CMD_PARAMS_SET_KEY_T_PASSKEY), (uint8_t * )&(p_aci_cmd_params_set_key->key), len-2);//Reducing 2 for the opcode byte and type
+}
+
+bool acil_encode_cmd(uint8_t *buffer, aci_cmd_t *p_aci_cmd)
+{
+  bool ret_val = false;
+
+  switch((aci_cmd_opcode_t)p_aci_cmd->cmd_opcode)
+  {
+    case ACI_CMD_TEST:
+      acil_encode_cmd_set_test_mode(buffer, &(p_aci_cmd->params.test));
+      break;
+    case ACI_CMD_SLEEP:
+      acil_encode_cmd_sleep(buffer);
+      break;
+    case ACI_CMD_GET_DEVICE_VERSION:
+      acil_encode_cmd_get_device_version(buffer);
+      break;
+    case ACI_CMD_WAKEUP:
+      acil_encode_cmd_wakeup(buffer);
+      break;
+    case ACI_CMD_ECHO:
+      acil_encode_cmd_echo_msg(buffer, &(p_aci_cmd->params.echo), (p_aci_cmd->len - MSG_ECHO_MSG_CMD_BASE_LEN));
+      break;
+    case ACI_CMD_GET_BATTERY_LEVEL:
+      acil_encode_cmd_battery_level(buffer);
+      break;
+    case ACI_CMD_GET_TEMPERATURE:
+      acil_encode_cmd_temparature(buffer);
+      break;
+    case ACI_CMD_GET_DEVICE_ADDRESS:
+      acil_encode_cmd_get_address(buffer);
+      break;
+    case ACI_CMD_SET_TX_POWER:
+      acil_encode_cmd_set_radio_tx_power(buffer, &(p_aci_cmd->params.set_tx_power));
+      break;
+    case ACI_CMD_CONNECT:
+      acil_encode_cmd_connect(buffer, &(p_aci_cmd->params.connect));
+      break;
+    case ACI_CMD_BOND:
+      acil_encode_cmd_bond(buffer, &(p_aci_cmd->params.bond));
+      break;
+    case ACI_CMD_DISCONNECT:
+      acil_encode_cmd_disconnect(buffer, &(p_aci_cmd->params.disconnect));
+      break;
+    case ACI_CMD_RADIO_RESET:
+      acil_encode_baseband_reset(buffer);
+      break;
+    case ACI_CMD_CHANGE_TIMING:
+      acil_encode_cmd_change_timing_req(buffer, &(p_aci_cmd->params.change_timing));
+      break;
+    case ACI_CMD_SETUP:
+      acil_encode_cmd_setup(buffer, &(p_aci_cmd->params.setup), (p_aci_cmd->len - MSG_SETUP_CMD_BASE_LEN));
+      break;
+    case ACI_CMD_DTM_CMD:
+      acil_encode_cmd_dtm_cmd(buffer, &(p_aci_cmd->params.dtm_cmd));
+      break;
+    case ACI_CMD_READ_DYNAMIC_DATA:
+      acil_encode_cmd_read_dynamic_data(buffer);
+      break;
+    case ACI_CMD_WRITE_DYNAMIC_DATA:
+      acil_encode_cmd_write_dynamic_data(buffer, p_aci_cmd->params.write_dynamic_data.seq_no, &(p_aci_cmd->params.write_dynamic_data.dynamic_data[0]), (p_aci_cmd->len - MSG_WRITE_DYNAMIC_DATA_BASE_LEN));
+      break;
+    case ACI_CMD_OPEN_REMOTE_PIPE:
+      acil_encode_cmd_open_remote_pipe(buffer, &(p_aci_cmd->params.open_remote_pipe));
+      break;
+    case ACI_CMD_SEND_DATA:
+      acil_encode_cmd_send_data(buffer, &(p_aci_cmd->params.send_data), (p_aci_cmd->len - MSG_SEND_DATA_BASE_LEN));
+      break;
+    case ACI_CMD_SEND_DATA_ACK:
+      acil_encode_cmd_send_data_ack(buffer, p_aci_cmd->params.send_data_ack.pipe_number );
+      break;
+    case ACI_CMD_REQUEST_DATA:
+      acil_encode_cmd_request_data(buffer, &(p_aci_cmd->params.request_data));
+      break;
+    case ACI_CMD_SET_LOCAL_DATA:
+      acil_encode_cmd_set_local_data(buffer, (aci_cmd_params_set_local_data_t *)(&(p_aci_cmd->params.send_data)), (p_aci_cmd->len - MSG_SET_LOCAL_DATA_BASE_LEN));
+      break;
+    case ACI_CMD_BOND_SECURITY_REQUEST:
+      acil_encode_cmd_bond_security_request(buffer);
+      break;
+    default:
+      break;
+  }
+  return ret_val;
+}
+
+void acil_decode_evt_command_response(uint8_t *buffer_in, aci_evt_params_cmd_rsp_t *p_evt_params_cmd_rsp)
+{
+  aci_evt_cmd_rsp_params_get_device_version_t *p_device_version;
+  aci_evt_cmd_rsp_params_get_device_address_t *p_device_address;
+  aci_evt_cmd_rsp_params_get_temperature_t    *p_temperature;
+  aci_evt_cmd_rsp_params_get_battery_level_t  *p_batt_lvl;
+  aci_evt_cmd_rsp_read_dynamic_data_t         *p_read_dyn_data;
+  aci_evt_cmd_rsp_params_dtm_cmd_t            *p_dtm_evt;
+
+  p_evt_params_cmd_rsp->cmd_opcode = (aci_cmd_opcode_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_CMD_OPCODE);
+  p_evt_params_cmd_rsp->cmd_status = (aci_status_code_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_CMD_STATUS);
+
+  switch ((aci_cmd_opcode_t)p_evt_params_cmd_rsp->cmd_opcode)
+  {
+    case ACI_CMD_GET_DEVICE_VERSION:
+      p_device_version = &(p_evt_params_cmd_rsp->params.get_device_version);
+      p_device_version->configuration_id  = (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_CONFIGURATION_ID_LSB);
+      p_device_version->configuration_id |= (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_CONFIGURATION_ID_MSB) << 8;
+      p_device_version->aci_version       = *(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_ACI_VERSION);
+      p_device_version->setup_format      = *(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_FORMAT);
+      p_device_version->setup_id          = (uint32_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_LSB0);
+      p_device_version->setup_id         |= (uint32_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_LSB1) << 8;
+      p_device_version->setup_id         |= (uint32_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_MSB0) << 16;
+      p_device_version->setup_id         |= (uint32_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_MSB1) << 24;
+      p_device_version->setup_status      = *(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_STATUS);
+      break;
+
+    case ACI_CMD_GET_DEVICE_ADDRESS:
+      p_device_address = &(p_evt_params_cmd_rsp->params.get_device_address);
+      memcpy((uint8_t *)(p_device_address->bd_addr_own), (buffer_in + OFFSET_ACI_EVT_T_CMD_RSP+OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_ADDRESS+OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_ADDRESS_T_BD_ADDR_OWN), BTLE_DEVICE_ADDRESS_SIZE);
+      p_device_address->bd_addr_type = (aci_bd_addr_type_t) *(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP+OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_ADDRESS+OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_ADDRESS_T_BD_ADDR_TYPE);
+      break;
+      
+    case ACI_CMD_GET_TEMPERATURE:
+      p_temperature = &(p_evt_params_cmd_rsp->params.get_temperature);
+      p_temperature->temperature_value =  (int16_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_TEMPERATURE + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_TEMPERATURE_T_TEMPERATURE_VALUE_LSB);
+      p_temperature->temperature_value |= (int16_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_TEMPERATURE + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_TEMPERATURE_T_TEMPERATURE_VALUE_MSB) << 8;
+      break;
+      
+    case ACI_CMD_GET_BATTERY_LEVEL:
+      p_batt_lvl = &(p_evt_params_cmd_rsp->params.get_battery_level);
+      p_batt_lvl->battery_level =  (int16_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_BATTERY_LEVEL + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_BATTERY_LEVEL_T_BATTERY_LEVEL_LSB);
+      p_batt_lvl->battery_level |= (int16_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_BATTERY_LEVEL + OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_BATTERY_LEVEL_T_BATTERY_LEVEL_MSB) << 8;
+      break;
+    
+    case ACI_CMD_READ_DYNAMIC_DATA:
+      p_read_dyn_data = &(p_evt_params_cmd_rsp->params.read_dynamic_data);
+      p_read_dyn_data->seq_no =  (uint8_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_READ_DYNAMIC_DATA + OFFSET_ACI_EVT_CMD_RSP_READ_DYNAMIC_DATA_T_SEQ_NO);
+      memcpy((uint8_t *)(p_read_dyn_data->dynamic_data), (buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_READ_DYNAMIC_DATA + OFFSET_ACI_CMD_PARAMS_WRITE_DYNAMIC_DATA_T_DYNAMIC_DATA), ACIL_DECODE_EVT_GET_LENGTH(buffer_in) - 3); // 3 bytes subtracted account for EventCode, CommandOpCode and Status bytes.
+      // Now that the p_read_dyn_data->dynamic_data will be pointing to memory location with enough space to accommodate upto 27 bytes of dynamic data received. This is because of the padding element in aci_evt_params_cmd_rsp_t
+      break;
+    
+    case ACI_CMD_DTM_CMD:
+      p_dtm_evt = &(p_evt_params_cmd_rsp->params.dtm_cmd);
+      p_dtm_evt->evt_msb = (uint8_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_DTM_CMD + OFFSET_ACI_EVT_CMD_RSP_PARAMS_DTM_CMD_T_EVT_MSB);
+      p_dtm_evt->evt_lsb = (uint8_t)*(buffer_in + OFFSET_ACI_EVT_T_CMD_RSP + OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_DTM_CMD + OFFSET_ACI_EVT_CMD_RSP_PARAMS_DTM_CMD_T_EVT_LSB);
+      break;
+    default:
+      break;
+  }
+}
+
+void acil_decode_evt_device_started(uint8_t *buffer_in, aci_evt_params_device_started_t *p_evt_params_device_started)
+{
+  p_evt_params_device_started->device_mode = (aci_device_operation_mode_t) *(buffer_in + OFFSET_ACI_EVT_T_DEVICE_STARTED+OFFSET_ACI_EVT_PARAMS_DEVICE_STARTED_T_DEVICE_MODE);
+  p_evt_params_device_started->hw_error = (aci_hw_error_t) *(buffer_in + OFFSET_ACI_EVT_T_DEVICE_STARTED+OFFSET_ACI_EVT_PARAMS_DEVICE_STARTED_T_HW_ERROR);
+  p_evt_params_device_started->credit_available = *(buffer_in + OFFSET_ACI_EVT_T_DEVICE_STARTED+OFFSET_ACI_EVT_PARAMS_DEVICE_STARTED_T_CREDIT_AVAILABLE); 
+}
+
+void acil_decode_evt_pipe_status(uint8_t *buffer_in, aci_evt_params_pipe_status_t *p_aci_evt_params_pipe_status)
+{
+  memcpy((uint8_t *)p_aci_evt_params_pipe_status->pipes_open_bitmap, (buffer_in + OFFSET_ACI_EVT_T_PIPE_STATUS + OFFSET_ACI_EVT_PARAMS_PIPE_STATUS_T_PIPES_OPEN_BITMAP), 8);
+  memcpy((uint8_t *)p_aci_evt_params_pipe_status->pipes_closed_bitmap, (buffer_in + OFFSET_ACI_EVT_T_PIPE_STATUS + OFFSET_ACI_EVT_PARAMS_PIPE_STATUS_T_PIPES_CLOSED_BITMAP), 8);
+}
+
+void acil_decode_evt_disconnected(uint8_t *buffer_in, aci_evt_params_disconnected_t *p_aci_evt_params_disconnected)
+{
+  p_aci_evt_params_disconnected->aci_status = (aci_status_code_t)*(buffer_in + OFFSET_ACI_EVT_T_DISCONNECTED + OFFSET_ACI_EVT_PARAMS_DISCONNECTED_T_ACI_STATUS);
+  p_aci_evt_params_disconnected->btle_status = *(buffer_in + OFFSET_ACI_EVT_T_DISCONNECTED + OFFSET_ACI_EVT_PARAMS_DISCONNECTED_T_BTLE_STATUS);
+}
+
+void acil_decode_evt_bond_status(uint8_t *buffer_in, aci_evt_params_bond_status_t *p_aci_evt_params_bond_status)
+{
+  p_aci_evt_params_bond_status->status_code = (aci_bond_status_code_t)*(buffer_in + OFFSET_ACI_EVT_T_BOND_STATUS + OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_STATUS_CODE);
+  p_aci_evt_params_bond_status->status_source = (aci_bond_status_source_t)*(buffer_in + OFFSET_ACI_EVT_T_BOND_STATUS + OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_STATUS_SOURCE);
+  p_aci_evt_params_bond_status->secmode1_bitmap = *(buffer_in + OFFSET_ACI_EVT_T_BOND_STATUS + OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_SECMODE1_BITMAP);
+  p_aci_evt_params_bond_status->secmode2_bitmap = *(buffer_in + OFFSET_ACI_EVT_T_BOND_STATUS + OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_SECMODE2_BITMAP);
+  p_aci_evt_params_bond_status->keys_exchanged_slave = *(buffer_in + OFFSET_ACI_EVT_T_BOND_STATUS + OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_KEYS_EXCHANGED_SLAVE);
+  p_aci_evt_params_bond_status->keys_exchanged_master = *(buffer_in + OFFSET_ACI_EVT_T_BOND_STATUS + OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_KEYS_EXCHANGED_MASTER);
+}
+
+uint8_t acil_decode_evt_data_received(uint8_t *buffer_in, aci_evt_params_data_received_t *p_evt_params_data_received)
+{
+  uint8_t size = *( buffer_in + OFFSET_ACI_EVT_T_LEN) - (OFFSET_ACI_EVT_T_DATA_RECEIVED + OFFSET_ACI_RX_DATA_T_ACI_DATA) + 1 ;
+  p_evt_params_data_received->rx_data.pipe_number = *(buffer_in + OFFSET_ACI_EVT_T_DATA_RECEIVED + OFFSET_ACI_RX_DATA_T_PIPE_NUMBER);
+  memcpy((uint8_t *)p_evt_params_data_received->rx_data.aci_data, (buffer_in + OFFSET_ACI_EVT_T_DATA_RECEIVED + OFFSET_ACI_RX_DATA_T_ACI_DATA), size);
+  return size;
+}
+
+void acil_decode_evt_data_ack(uint8_t *buffer_in, aci_evt_params_data_ack_t *p_evt_params_data_ack)
+{
+  p_evt_params_data_ack->pipe_number = *(buffer_in + OFFSET_ACI_EVT_T_DATA_ACK + OFFSET_ACI_EVT_PARAMS_DATA_ACK_T_PIPE_NUMBER);
+}
+
+uint8_t acil_decode_evt_hw_error(uint8_t *buffer_in, aci_evt_params_hw_error_t *p_aci_evt_params_hw_error)
+{
+  uint8_t size = *(buffer_in + OFFSET_ACI_EVT_T_LEN) - (OFFSET_ACI_EVT_T_HW_ERROR + OFFSET_ACI_EVT_PARAMS_HW_ERROR_T_FILE_NAME) + 1;
+  p_aci_evt_params_hw_error->line_num = (uint16_t)(*(buffer_in + OFFSET_ACI_EVT_T_HW_ERROR + OFFSET_ACI_EVT_PARAMS_HW_ERROR_T_LINE_NUM_MSB)) << 8;
+  p_aci_evt_params_hw_error->line_num |= (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_HW_ERROR + OFFSET_ACI_EVT_PARAMS_HW_ERROR_T_LINE_NUM_LSB);
+  memcpy((uint8_t *)p_aci_evt_params_hw_error->file_name, (buffer_in + OFFSET_ACI_EVT_T_HW_ERROR + OFFSET_ACI_EVT_PARAMS_HW_ERROR_T_FILE_NAME), size);
+  return size;
+}
+
+void acil_decode_evt_credit(uint8_t *buffer_in, aci_evt_params_data_credit_t *p_evt_params_data_credit)
+{
+  p_evt_params_data_credit->credit = *(buffer_in + OFFSET_ACI_EVT_T_DATA_CREDIT + OFFSET_ACI_EVT_PARAMS_DATA_CREDIT_T_CREDIT);
+}
+
+void acil_decode_evt_connected(uint8_t *buffer_in, aci_evt_params_connected_t *p_aci_evt_params_connected)
+{
+  p_aci_evt_params_connected->dev_addr_type = (aci_bd_addr_type_t)*(buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_DEV_ADDR_TYPE);
+  memcpy(&(p_aci_evt_params_connected->dev_addr[0]), (buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_DEV_ADDR), BTLE_DEVICE_ADDRESS_SIZE);
+  p_aci_evt_params_connected->conn_rf_interval       = (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_INTERVAL_MSB) << 8;
+  p_aci_evt_params_connected->conn_rf_interval      |= (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_INTERVAL_LSB);
+  p_aci_evt_params_connected->conn_slave_rf_latency  = (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_SLAVE_RF_LATENCY_MSB) << 8;
+  p_aci_evt_params_connected->conn_slave_rf_latency |= (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_SLAVE_RF_LATENCY_LSB);
+  p_aci_evt_params_connected->conn_rf_timeout        = (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_TIMEOUT_MSB) << 8;
+  p_aci_evt_params_connected->conn_rf_timeout       |= (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_TIMEOUT_LSB);
+  p_aci_evt_params_connected->master_clock_accuracy  = (aci_clock_accuracy_t)*(buffer_in + OFFSET_ACI_EVT_T_CONNECTED + OFFSET_ACI_EVT_PARAMS_CONNECTED_T_MASTER_CLOCK_ACCURACY);
+
+}
+
+void acil_decode_evt_timing(uint8_t *buffer_in, aci_evt_params_timing_t *p_evt_params_timing)
+{
+  p_evt_params_timing->conn_rf_interval       = *(buffer_in + OFFSET_ACI_EVT_T_TIMING + OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_INTERVAL_MSB) << 8;
+  p_evt_params_timing->conn_rf_interval      |= (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_TIMING + OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_INTERVAL_LSB);
+  p_evt_params_timing->conn_slave_rf_latency  = (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_TIMING + OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_SLAVE_RF_LATENCY_MSB) << 8;
+  p_evt_params_timing->conn_slave_rf_latency |= (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_TIMING + OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_SLAVE_RF_LATENCY_LSB);
+  p_evt_params_timing->conn_rf_timeout        = (uint16_t)*(buffer_in + OFFSET_ACI_EVT_T_TIMING + OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_TIMEOUT_MSB) << 8;
+  p_evt_params_timing->conn_rf_timeout       |= *(buffer_in + OFFSET_ACI_EVT_T_TIMING + OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_TIMEOUT_LSB);
+}
+
+void acil_decode_evt_pipe_error(uint8_t *buffer_in, aci_evt_params_pipe_error_t *p_evt_params_pipe_error)
+{
+  //volatile uint8_t size = *(buffer_in + OFFSET_ACI_EVT_T_LEN) - (OFFSET_ACI_EVT_T_PIPE_ERROR + OFFSET_ACI_EVT_PARAMS_PIPE_ERROR_T_ERROR_DATA) + 1;
+  p_evt_params_pipe_error->pipe_number = *(buffer_in + OFFSET_ACI_EVT_T_PIPE_ERROR + OFFSET_ACI_EVT_PARAMS_PIPE_ERROR_T_PIPE_NUMBER);
+  p_evt_params_pipe_error->error_code = *(buffer_in + OFFSET_ACI_EVT_T_PIPE_ERROR + OFFSET_ACI_EVT_PARAMS_PIPE_ERROR_T_ERROR_CODE);
+  p_evt_params_pipe_error->params.error_data.content[0] = *(buffer_in + OFFSET_ACI_EVT_T_PIPE_ERROR + OFFSET_ACI_EVT_PARAMS_PIPE_ERROR_T_ERROR_DATA + OFFSET_ERROR_DATA_T_CONTENT);
+}
+
+void acil_decode_evt_key_request(uint8_t *buffer_in, aci_evt_params_key_request_t *p_evt_params_key_request)
+{
+  p_evt_params_key_request->key_type = (aci_key_type_t)*(buffer_in + OFFSET_ACI_EVT_T_KEY_REQUEST + OFFSET_ACI_EVT_PARAMS_KEY_REQUEST_T_KEY_TYPE);
+}
+
+uint8_t acil_decode_evt_echo(uint8_t *buffer_in, aci_evt_params_echo_t *aci_evt_params_echo)
+{
+  uint8_t size = *(buffer_in + OFFSET_ACI_EVT_T_LEN) - 1;
+  memcpy(&aci_evt_params_echo->echo_data[0], (buffer_in + OFFSET_ACI_EVT_T_EVT_OPCODE + 1), size);
+  return size;
+}
+
+void acil_decode_evt_display_passkey(uint8_t *buffer_in, aci_evt_params_display_passkey_t *p_aci_evt_params_display_passkey)
+{
+  p_aci_evt_params_display_passkey->passkey[0] = *(buffer_in + OFFSET_ACI_EVT_T_DISPLAY_PASSKEY +  OFFSET_ACI_EVT_PARAMS_DISPLAY_PASSKEY_T_PASSKEY + 0);
+  p_aci_evt_params_display_passkey->passkey[1] = *(buffer_in + OFFSET_ACI_EVT_T_DISPLAY_PASSKEY +  OFFSET_ACI_EVT_PARAMS_DISPLAY_PASSKEY_T_PASSKEY + 1);
+  p_aci_evt_params_display_passkey->passkey[2] = *(buffer_in + OFFSET_ACI_EVT_T_DISPLAY_PASSKEY +  OFFSET_ACI_EVT_PARAMS_DISPLAY_PASSKEY_T_PASSKEY + 2);
+  p_aci_evt_params_display_passkey->passkey[3] = *(buffer_in + OFFSET_ACI_EVT_T_DISPLAY_PASSKEY +  OFFSET_ACI_EVT_PARAMS_DISPLAY_PASSKEY_T_PASSKEY + 3);
+  p_aci_evt_params_display_passkey->passkey[4] = *(buffer_in + OFFSET_ACI_EVT_T_DISPLAY_PASSKEY +  OFFSET_ACI_EVT_PARAMS_DISPLAY_PASSKEY_T_PASSKEY + 4);
+  p_aci_evt_params_display_passkey->passkey[5] = *(buffer_in + OFFSET_ACI_EVT_T_DISPLAY_PASSKEY +  OFFSET_ACI_EVT_PARAMS_DISPLAY_PASSKEY_T_PASSKEY + 5);
+}
+
+bool acil_decode_evt(uint8_t *buffer_in, aci_evt_t *p_aci_evt)
+{
+  bool ret_val = true;
+
+  p_aci_evt->len = ACIL_DECODE_EVT_GET_LENGTH(buffer_in);
+  p_aci_evt->evt_opcode = (aci_evt_opcode_t)ACIL_DECODE_EVT_GET_OPCODE(buffer_in);
+
+  switch(p_aci_evt->evt_opcode)
+  {
+    case ACI_EVT_DEVICE_STARTED:
+      acil_decode_evt_device_started(buffer_in, &(p_aci_evt->params.device_started));
+      break;
+    case ACI_EVT_HW_ERROR:
+      acil_decode_evt_hw_error(buffer_in, &(p_aci_evt->params.hw_error));
+      break;
+    case ACI_EVT_CMD_RSP:
+      acil_decode_evt_command_response(buffer_in, &(p_aci_evt->params.cmd_rsp));
+      break;
+    case ACI_EVT_DATA_CREDIT:
+      acil_decode_evt_credit(buffer_in, &(p_aci_evt->params.data_credit));
+      break;
+    case ACI_EVT_CONNECTED:
+      acil_decode_evt_connected(buffer_in, &(p_aci_evt->params.connected));
+      break;
+    case ACI_EVT_PIPE_STATUS:
+      acil_decode_evt_pipe_status(buffer_in, &(p_aci_evt->params.pipe_status));
+      break;
+    case ACI_EVT_DISCONNECTED:
+      acil_decode_evt_disconnected(buffer_in, &(p_aci_evt->params.disconnected));
+      break;
+    case ACI_EVT_BOND_STATUS:
+      acil_decode_evt_bond_status(buffer_in, &(p_aci_evt->params.bond_status));
+      break;
+    case ACI_EVT_TIMING:
+      acil_decode_evt_timing(buffer_in, &(p_aci_evt->params.timing));
+      break;
+    case ACI_EVT_DATA_ACK:
+      acil_decode_evt_data_ack(buffer_in, &(p_aci_evt->params.data_ack));
+      break;
+    case ACI_EVT_DATA_RECEIVED:
+      acil_decode_evt_data_received(buffer_in, &(p_aci_evt->params.data_received));
+      break;
+    case ACI_EVT_PIPE_ERROR:
+      acil_decode_evt_pipe_error(buffer_in, &(p_aci_evt->params.pipe_error));
+      break;
+    case ACI_EVT_KEY_REQUEST:
+      acil_decode_evt_key_request(buffer_in, &(p_aci_evt->params.key_request));
+      break;
+    case ACI_EVT_DISPLAY_PASSKEY:
+      acil_decode_evt_display_passkey(buffer_in, &(p_aci_evt->params.display_passkey));     
+      break;
+    default:
+      ret_val = false;
+      break;
+  }
+  return ret_val;
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/acilib.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/acilib.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/acilib.h	(revision 453)
@@ -0,0 +1,61 @@
+/* Copyright (c) 2014, Nordic Semiconductor ASA
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * @file
+ *
+ * @ingroup group_acilib
+ *
+ * @brief Internal prototype for acilib module.
+ */
+
+#ifndef _acilib_H_
+#define _acilib_H_
+
+#define MSG_SET_LOCAL_DATA_BASE_LEN              2
+#define MSG_CONNECT_LEN                          5
+#define MSG_BOND_LEN                             5
+#define MSG_DISCONNECT_LEN                       2
+#define MSG_BASEBAND_RESET_LEN                   1
+#define MSG_WAKEUP_LEN                           1
+#define MSG_SET_RADIO_TX_POWER_LEN               2
+#define MSG_GET_DEVICE_ADDR_LEN                  1
+#define MSG_SEND_DATA_BASE_LEN                   2
+#define MSG_DATA_REQUEST_LEN                     2
+#define MSG_OPEN_REMOTE_PIPE_LEN                 2
+#define MSG_CLOSE_REMOTE_PIPE_LEN                2
+#define MSG_DTM_CMD                              3
+#define MSG_WRITE_DYNAMIC_DATA_BASE_LEN          2
+#define MSG_SETUP_CMD_BASE_LEN                   1
+#define MSG_ECHO_MSG_CMD_BASE_LEN                1
+#define MSG_CHANGE_TIMING_LEN                    9
+#define MSG_SET_APP_LATENCY_LEN                  4
+#define MSG_CHANGE_TIMING_LEN_GAP_PPCP           1
+#define MSG_DIRECT_CONNECT_LEN                   1
+#define MSG_SET_KEY_REJECT_LEN                   2
+#define MSG_SET_KEY_PASSKEY_LEN                  8
+#define MSG_SET_KEY_OOB_LEN                      18
+#define MSG_ACK_LEN                              2
+#define MSG_NACK_LEN                             3
+#define MSG_BROADCAST_LEN                        5
+#define MSG_OPEN_ADV_PIPES_LEN                   9
+
+#endif /* _acilib_H_ */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/acilib_defs.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/acilib_defs.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/acilib_defs.h	(revision 453)
@@ -0,0 +1,37 @@
+/* Copyright (c) 2014, Nordic Semiconductor ASA
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * @file
+ *
+ * @ingroup group_acilib
+ *
+ * @brief Definitions for the acilib interfaces
+ */
+
+#ifndef _acilib_DEFS_H_
+#define _acilib_DEFS_H_
+
+#define ACIL_DECODE_EVT_GET_LENGTH(buffer_in) (*(buffer_in + OFFSET_ACI_EVT_T_LEN))
+
+#define ACIL_DECODE_EVT_GET_OPCODE(buffer_in) (*(buffer_in + OFFSET_ACI_EVT_T_EVT_OPCODE))
+
+#endif /* _acilib_DEFS_H_ */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/acilib_if.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/acilib_if.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/acilib_if.h	(revision 453)
@@ -0,0 +1,471 @@
+/* Copyright (c) 2014, Nordic Semiconductor ASA
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * @file
+ *
+ * @ingroup group_acilib
+ *
+ * @brief Prototypes for the acilib interfaces.
+ */
+
+#ifndef _acilib_IF_H_
+#define _acilib_IF_H_
+
+/** @brief Encode the ACI message for set test mode command
+ *
+ *  @param[in,out]  buffer      Pointer to ACI message buffer
+ *  @param[in]      test_mode   Pointer to the test mode in ::aci_cmd_params_test_t
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_set_test_mode(uint8_t *buffer, aci_cmd_params_test_t *p_aci_cmd_params_test);
+
+/** @brief Encode the ACI message for sleep command
+ *
+ *  @param[in,out]  buffer      Pointer to ACI message buffer
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_sleep(uint8_t *buffer);
+
+/** @brief Encode the ACI message for get device version
+ *
+ *  @param[in,out]  buffer      Pointer to ACI message buffer
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_get_device_version(uint8_t *buffer);
+
+/** @brief Encode the ACI message for set local data
+ *
+ *  @param[in,out]  buffer                           Pointer to ACI message buffer
+ *  @param[in]      p_aci_cmd_params_set_local_data  Pointer to the local data parameters in ::aci_cmd_params_set_local_data_t
+ *  @param[in]      data_size                        Size of data message
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_set_local_data(uint8_t *buffer, aci_cmd_params_set_local_data_t *p_aci_cmd_params_set_local_data, uint8_t data_size);
+
+/** @brief Encode the ACI message to connect
+ *
+ *  @param[in,out]  buffer                    Pointer to ACI message buffer
+ *  @param[in]      p_aci_cmd_params_connect  Pointer to the run parameters in ::aci_cmd_params_connect_t
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_connect(uint8_t *buffer, aci_cmd_params_connect_t *p_aci_cmd_params_connect);
+
+/** @brief Encode the ACI message to bond
+ *
+ *  @param[in,out]  buffer                 Pointer to ACI message buffer
+ *  @param[in]      p_aci_cmd_params_bond  Pointer to the run parameters in ::aci_cmd_params_bond_t
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_bond(uint8_t *buffer, aci_cmd_params_bond_t *p_aci_cmd_params_bond);
+
+/** @brief Encode the ACI message to disconnect
+ *
+ *  @param[in,out]  buffer                       Pointer to ACI message buffer
+ *  @param[in]      p_aci_cmd_params_disconnect  Pointer to the run parameters in ::aci_cmd_params_disconnect_t
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_disconnect(uint8_t *buffer, aci_cmd_params_disconnect_t *p_aci_cmd_params_disconnect);
+
+/** @brief Encode the ACI message to baseband reset
+ *
+ *  @param[in,out]  buffer        Pointer to ACI message buffer
+ *
+ *  @return         None
+ */
+ void acil_encode_baseband_reset(uint8_t *buffer);
+
+ /** @brief Encode the ACI message for Directed Advertising
+ *
+ *  @param[in,out]  buffer        Pointer to ACI message buffer
+ *
+ *  @return         None
+ */
+ void acil_encode_direct_connect(uint8_t *buffer);
+
+/** @brief Encode the ACI message to wakeup
+ *
+ *  @param[in,out]  buffer        Pointer to ACI message buffer
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_wakeup(uint8_t *buffer);
+
+/** @brief Encode the ACI message for set radio Tx power
+ *
+ *  @param[in,out]  buffer                         Pointer to ACI message buffer
+ *  @param[in]      p_aci_cmd_params_set_tx_power  Pointer to the set Tx power parameters in ::aci_cmd_params_set_tx_power_t
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_set_radio_tx_power(uint8_t *buffer, aci_cmd_params_set_tx_power_t *p_aci_cmd_params_set_tx_power);
+
+/** @brief Encode the ACI message for get device address
+ *
+ *  @param[in,out]  buffer            Pointer to ACI message buffer
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_get_address(uint8_t *buffer);
+
+/** @brief Encode the ACI message for send data
+ *
+ *  @param[in,out]  buffer                        Pointer to ACI message buffer
+ *  @param[in]      p_aci_cmd_params_send_data_t  Pointer to the data parameters in ::aci_cmd_params_send_data_t
+ *  @param[in]      data_size                     Size of data message
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_send_data(uint8_t *buffer, aci_cmd_params_send_data_t *p_aci_cmd_params_send_data_t, uint8_t data_size);
+
+/** @brief Encode the ACI message for request data
+ *
+ *  @param[in,out]  buffer                          Pointer to ACI message buffer
+ *  @param[in]      p_aci_cmd_params_request_data   Pointer to the request data parameters in ::aci_cmd_params_request_data_t
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_request_data(uint8_t *buffer, aci_cmd_params_request_data_t *p_aci_cmd_params_request_data);
+
+/** @brief Encode the ACI message for open remote pipe
+ *
+ *  @param[in,out]  buffer                              Pointer to ACI message buffer
+ *  @param[in]      p_aci_cmd_params_open_remote_pipe   Pointer to the dynamic data parameters in ::aci_cmd_params_open_remote_pipe_t
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_open_remote_pipe(uint8_t *buffer, aci_cmd_params_open_remote_pipe_t *p_aci_cmd_params_open_remote_pipe);
+
+/** @brief Encode the ACI message for close remote pipe
+ *
+ *  @param[in,out]  buffer                              Pointer to ACI message buffer
+ *  @param[in]      p_aci_cmd_params_close_remote_pipe   Pointer to the dynamic data parameters in ::aci_cmd_params_close_remote_pipe_t
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_close_remote_pipe(uint8_t *buffer, aci_cmd_params_close_remote_pipe_t *p_aci_cmd_params_close_remote_pipe);
+
+/** @brief Encode the ACI message for echo message
+ *
+ *  @param[in,out]  buffer             Pointer to ACI message buffer
+ *  @param[in]      p_cmd_params_echo  Pointer to the dynamic data parameters in ::aci_cmd_params_echo_t
+ *  @param[in]      msg_size           Size of the message
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_echo_msg(uint8_t *buffer, aci_cmd_params_echo_t *p_cmd_params_echo, uint8_t msg_size);
+
+/** @brief Encode the ACI message to battery level
+ *
+ *  @param[in,out]  buffer  Pointer to ACI message buffer
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_battery_level(uint8_t *buffer);
+
+/** @brief Encode the ACI message to temparature
+ *
+ *  @param[in,out]  buffer  Pointer to ACI message buffer
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_temparature(uint8_t *buffer);
+
+/** @brief Encode the ACI message to read dynamic data
+ *
+ *  @param[in,out]  buffer  Pointer to ACI message buffer
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_read_dynamic_data(uint8_t *buffer);
+
+/** @brief Encode the ACI message to change timing request
+ *
+ *  @param[in,out]  buffer  Pointer to ACI message buffer
+ *  @param[in]      p_aci_cmd_params_change_timing  Pointer to the change timing parameters in ::aci_cmd_params_change_timing_t
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_change_timing_req(uint8_t *buffer, aci_cmd_params_change_timing_t *p_aci_cmd_params_change_timing);
+
+/** @brief Encode the ACI message to change timing request using the timing parameters from GAP PPCP
+ *
+ *  @param[in,out]  buffer  Pointer to ACI message buffer
+ *  @param[in]      p_aci_cmd_params_change_timing  Pointer to the change timing parameters in ::aci_cmd_params_change_timing_t
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_change_timing_req_GAP_PPCP(uint8_t *buffer);
+
+
+/** @brief Encode the ACI message for write dynamic data
+ *
+ *  @param[in,out]  buffer                          Pointer to ACI message buffer
+ *  @param[in]      seq_no                          Sequence number of the dynamic data (as received in the response to @c Read Dynamic Data)
+ *  @param[in]      dynamic_data                    Pointer to the dynamic data
+ *  @param[in]      dynamic_data_size               Size of dynamic data
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_write_dynamic_data(uint8_t *buffer, uint8_t seq_no, uint8_t* dynamic_data, uint8_t dynamic_data_size);
+
+/** @brief Encode the ACI message to send data acknowledgement
+ *
+ *  @param[in,out]  buffer  Pointer to ACI message buffer
+ *  @param[in]      pipe_number Pipe number for which the ack is to be sent
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_send_data_ack(uint8_t *buffer, const uint8_t pipe_number);
+
+/** @brief Encode the ACI message to send negative acknowledgement
+ *
+ *  @param[in,out]  buffer  Pointer to ACI message buffer
+ *  @param[in]    pipe_number Pipe number for which the nack is to be sent
+ *  @param[in]    error_code Error code that has to be sent in the NACK
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_send_data_nack(uint8_t *buffer, const uint8_t pipe_number,const uint8_t error_code);
+
+/** @brief Encode the ACI message to set the application latency
+ *
+ *  @param[in,out]  buffer  Pointer to ACI message buffer
+ *  @param[in]      p_aci_cmd_params_set_app_latency  Pointer to the set_application_latency command parameters in ::aci_cmd_params_dtm_cmd_t
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_set_app_latency(uint8_t *buffer, aci_cmd_params_set_app_latency_t *p_aci_cmd_params_set_app_latency);
+
+/** @brief Encode the ACI message for setup
+ *
+ *  @param[in,out]  buffer                          Pointer to ACI message buffer
+ *  @param[in]      p_cmd_params_set_run_behaviour  Pointer to the setup data in ::aci_cmd_params_setup_t
+ *  @param[in]      setup_data_size                 Size of setup message
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_setup(uint8_t *buffer, aci_cmd_params_setup_t *p_aci_cmd_params_setup, uint8_t setup_data_size);
+
+/** @brief Encode the ACI message for DTM command
+ *
+ *  @param[in,out]  buffer                          Pointer to ACI message buffer
+ *  @param[in]      p_cmd_params_set_run_behaviour  Pointer to the DTM command parameters in ::aci_cmd_params_dtm_cmd_t
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_dtm_cmd(uint8_t *buffer, aci_cmd_params_dtm_cmd_t *p_aci_cmd_params_dtm_cmd);
+
+/** @brief Encode the ACI message for Set Key Request command
+ *
+ *  @param[in,out]  buffer      Pointer to ACI message buffer
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_set_key(uint8_t *buffer, aci_cmd_params_set_key_t *p_aci_cmd_params_set_key);
+
+/** @brief Encode the ACI message for Bond Security Request command
+ *
+ *  @param[in,out]  buffer      Pointer to ACI message buffer
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_bond_security_request(uint8_t *buffer);
+
+/** @brief Encode the ACI message
+ *
+ *  @param[in,out]  buffer      Pointer to ACI message buffer
+ *  @param[in]      p_aci_cmd   Pointer to ACI command data in ::aci_cmd_t
+ *  @param[in]      bool       
+ *
+ *  @return         bool         true, if succesful, else returns false
+ */
+bool acil_encode_cmd(uint8_t *buffer, aci_cmd_t *p_aci_cmd);
+
+/** @brief Encode the ACI message for Broadcast command
+ *
+ *  @param[in,out]  buffer      Pointer to ACI message buffer
+ *  @param[in]      p_aci_cmd   Pointer to ACI command data in ::aci_cmd_params_broadcast_t
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_broadcast(uint8_t *buffer,  aci_cmd_params_broadcast_t * p_aci_cmd_params_broadcast);
+
+/** @brief Encode the ACI message for Open Adv Pipes
+ *
+ *  @param[in,out]  buffer      Pointer to ACI message buffer
+ *  @param[in]      p_aci_cmd   Pointer to ACI command data in ::aci_cmd_params_open_adv_pipe_t
+ *
+ *  @return         None
+ */
+void acil_encode_cmd_open_adv_pipes(uint8_t *buffer, aci_cmd_params_open_adv_pipe_t * p_aci_cmd_params_set_adv_svc_data);
+
+/** @brief Decode the ACI event command response
+ *
+ *  @param[in]      buffer_in  Pointer to message received
+ *  @param[in,out]  buffer     Pointer to the decoded message in ::aci_evt_params_cmd_rsp_t
+ *
+ *  @return         None
+ */
+void acil_decode_evt_command_response(uint8_t *buffer_in, aci_evt_params_cmd_rsp_t *p_evt_params_cmd_rsp);
+
+/** @brief Decode the ACI event device started
+ *
+ *  @param[in]      buffer_in  Pointer to message received
+ *  @param[in,out]  p_aci_evt  Pointer to the decoded message in ::aci_evt_params_device_started_t
+ *
+ *  @return         None
+ */
+void acil_decode_evt_device_started(uint8_t *buffer_in, aci_evt_params_device_started_t *p_evt_params_device_started);
+
+/** @brief Decode the ACI event pipe status
+ *
+ *  @param[in]      buffer_in  Pointer to message received
+ *  @param[in,out]  p_aci_evt_params_pipe_status  Pointer to the decoded message in ::aci_evt_params_pipe_status_t
+ *
+ *  @return         None
+ */
+void acil_decode_evt_pipe_status(uint8_t *buffer_in, aci_evt_params_pipe_status_t *p_aci_evt_params_pipe_status);
+
+/** @brief Decode the ACI event for disconnected
+ *
+ *  @param[in]      buffer_in                      Pointer to message received
+ *  @param[in,out]  p_aci_evt_params_disconnected  Pointer to the decoded message in ::aci_evt_params_disconnected_t
+ *
+ *  @return         None
+ */
+void acil_decode_evt_disconnected(uint8_t *buffer_in, aci_evt_params_disconnected_t *p_aci_evt_params_disconnected);
+
+/** @brief Decode the ACI event for bond status
+ *
+ *  @param[in]      buffer_in                     Pointer to message received
+ *  @param[in,out]  p_aci_evt_params_bond_status  Pointer to the decoded message in ::aci_evt_params_bond_status_t
+ *
+ *  @return         None
+ */
+void acil_decode_evt_bond_status(uint8_t *buffer_in, aci_evt_params_bond_status_t *p_aci_evt_params_bond_status);
+
+/** @brief Decode the ACI event for data received
+ *
+ *  @param[in]      buffer_in                   Pointer to message received
+ *  @param[in,out]  p_evt_params_data_received  Pointer to the decoded message in ::aci_evt_params_data_received_t
+ *
+ *  @return         size                        Received data size
+ */
+uint8_t acil_decode_evt_data_received(uint8_t *buffer_in, aci_evt_params_data_received_t *p_evt_params_data_received);
+
+/** @brief Decode the ACI event data acknowledgement
+ *
+ *  @param[in]      buffer_in               Pointer to message received
+ *  @param[in,out]  p_evt_params_data_ack   Pointer to the decoded message in ::aci_evt_params_data_ack_t
+ *
+ *  @return         None
+ */
+void acil_decode_evt_data_ack(uint8_t *buffer_in, aci_evt_params_data_ack_t *p_evt_params_data_ack);
+
+/** @brief Decode the ACI event for hardware error
+ *
+ *  @param[in]      buffer_in                  Pointer to message received
+ *  @param[in,out]  p_aci_evt_params_hw_error  Pointer to the decoded message in ::aci_evt_params_hw_error_t
+ *
+ *  @return         size                     Size of debug information
+ */
+uint8_t acil_decode_evt_hw_error(uint8_t *buffer_in, aci_evt_params_hw_error_t *p_aci_evt_params_hw_error);
+
+/** @brief Decode the ACI event data credit
+ *
+ *  @param[in]      buffer_in                 Pointer to message received
+ *  @param[in,out]  p_evt_params_data_credit  Pointer to the decoded message in ::aci_evt_params_data_credit_t
+ *
+ *  @return         None
+ */
+void acil_decode_evt_credit(uint8_t *buffer_in, aci_evt_params_data_credit_t *p_evt_params_data_credit);
+
+/** @brief Decode the ACI event for connected
+ *
+ *  @param[in]      buffer_in                   Pointer to message received
+ *  @param[in,out]  p_aci_evt_params_connected  Pointer to the decoded message in ::aci_evt_params_connected_t
+ *
+ *  @return         None
+ */
+void acil_decode_evt_connected(uint8_t *buffer_in, aci_evt_params_connected_t *p_aci_evt_params_connected);
+
+/** @brief Decode the ACI event for timing
+ *
+ *  @param[in]      buffer_in             Pointer to message received
+ *  @param[in,out]  p_evt_params_timing   Pointer to the decoded message in ::aci_evt_params_timing_t
+ *
+ *  @return         None
+ */
+void acil_decode_evt_timing(uint8_t *buffer_in, aci_evt_params_timing_t *p_evt_params_timing);
+
+/** @brief Decode the ACI event for pipe error
+ *
+ *  @param[in]      buffer_in                 Pointer to message received
+ *  @param[in,out]  p_evt_params_pipe_error   Pointer to the decoded message in ::aci_evt_params_pipe_error_t
+ *
+ */
+void acil_decode_evt_pipe_error(uint8_t *buffer_in, aci_evt_params_pipe_error_t *p_evt_params_pipe_error);
+
+/** @brief Decode the ACI event for key request
+ *
+ *  @param[in]      buffer_in               Pointer to message received
+ *  @param[in,out]  p_evt_params_key_type   Pointer to the decoded message in ::aci_evt_params_key_type_t
+ *
+ *  @return         None
+ */
+void acil_decode_evt_key_request(uint8_t *buffer_in, aci_evt_params_key_request_t *p_evt_params_key_request);
+
+/** @brief Decode the ACI event for echo
+ *
+ *  @param[in]      buffer_in    Pointer to message received
+ *  @param[in,out]  buffer_out   Pointer to the echo message (max size of buffer ::ACI_ECHO_DATA_MAX_LEN)
+ *
+ *  @return         size         Received echo message size
+ */
+uint8_t acil_decode_evt_echo(uint8_t *buffer_in, aci_evt_params_echo_t *buffer_out);
+
+/** @brief Decode the ACI event
+ *
+ *  @param[in]      buffer_in   Pointer to message received
+ *  @param[in,out]  p_aci_evt   Pointer to the decoded message in ::aci_evt_t
+ *
+ *  @return         bool         true, if succesful, else returns false
+ */
+bool acil_decode_evt(uint8_t *buffer_in, aci_evt_t *p_aci_evt);
+
+/** @brief Decode the Display Key Event
+ *
+ *  @param[in]      buffer_in   Pointer to message received
+ *  @param[in,out]  p_aci_evt   Pointer to the decoded message in ::aci_evt_params_display_passkey_t
+ *
+ *  @return         None
+ */
+void acil_decode_evt_display_passkey(uint8_t *buffer_in, aci_evt_params_display_passkey_t *p_aci_evt_params_display_passkey);
+
+#endif /* _acilib_IF_H_ */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/acilib_types.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/acilib_types.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/acilib_types.h	(revision 453)
@@ -0,0 +1,33 @@
+/* Copyright (c) 2014, Nordic Semiconductor ASA
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * @file
+ *
+ * @ingroup group_acilib
+ *
+ * @brief Type used in the acilib interfaces
+ */
+
+#ifndef _acilib_TYPES_H_
+#define _acilib_TYPES_H_
+
+#endif /* _acilib_TYPES_H_ */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/ble_assert.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/ble_assert.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/ble_assert.h	(revision 453)
@@ -0,0 +1,36 @@
+/* Copyright (c) 2014, Nordic Semiconductor ASA
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+ 
+ /** @file
+ * @brief Declaration of assert()
+ */
+ 
+ #ifndef BLE_ASSERT_H__
+ #define BLE_ASSERT_H__
+
+extern void __ble_assert(const char *file, uint16_t line);
+
+#define ble_assert(expr)              \
+  ((expr)                             \
+  ? ((void) 0)                        \
+  : __ble_assert (__FILE__, __LINE__))
+
+#endif /* BLE_ASSERT_H__ */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/boards.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/boards.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/boards.h	(revision 453)
@@ -0,0 +1,34 @@
+/* Copyright (c) 2014, Nordic Semiconductor ASA
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */ 
+
+/** @file
+ * @brief Defines for the different Bluetooth low energy boards
+ */
+ 
+#ifndef _BLE_BOARDS_H_
+#define _BLE_BOARDS_H_
+
+#define BOARD_DEFAULT               0 //Use this if you do not know the board you are using or you are creating a new one
+#define REDBEARLAB_SHIELD_V1_1      1 //Redbearlab Bluetooth low energy shield v1.1
+#define REDBEARLAB_SHIELD_V2012_07  1 //Identical to Redbearlab v1.1 shield
+#define REDBEARLAB_SHIELD_V2        0 //Redbearlab Bluetooth low energy shield v2.x - No special handling required for pin reset same as default
+
+#endif
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/dfu.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/dfu.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/dfu.c	(revision 453)
@@ -0,0 +1,375 @@
+#include <lib_aci.h>
+#include <ble_assert.h>
+#include <dfu.h>
+
+static uint8_t state = ST_ANY;
+static uint32_t firmware_len;
+static uint16_t notify_every;
+static uint32_t bytes_received;
+static uint16_t packets_received;
+
+static void dfu_notify (aci_state_t *aci_state);
+static bool dfu_send (aci_state_t *aci_state, uint8_t *buffer, uint8_t buffer_len);
+
+static uint8_t dfu_data_pkt_handle (aci_state_t *aci_state, aci_evt_t *aci_evt);
+static uint8_t dfu_init_pkt_handle (aci_state_t *aci_state, aci_evt_t *aci_evt);
+static uint8_t dfu_image_activate  (aci_state_t *aci_state, aci_evt_t *aci_evt);
+static uint8_t dfu_image_size_set (aci_state_t *aci_state, aci_evt_t *aci_evt);
+static uint8_t dfu_image_validate  (aci_state_t *aci_state, aci_evt_t *aci_evt);
+
+#define DEBUG
+
+enum
+{
+    OP_CODE_START_DFU            = 1,                                               /**< Value of the Op code field for 'Start DFU' command.*/
+    OP_CODE_RECEIVE_INIT         = 2,                                               /**< Value of the Op code field for 'Initialize DFU parameters' command.*/
+    OP_CODE_RECEIVE_FW           = 3,                                               /**< Value of the Op code field for 'Receive firmware image' command.*/
+    OP_CODE_VALIDATE             = 4,                                               /**< Value of the Op code field for 'Validate firmware' command.*/
+    OP_CODE_ACTIVATE_N_RESET     = 5,                                               /**< Value of the Op code field for 'Activate & Reset' command.*/
+    OP_CODE_SYS_RESET            = 6,                                               /**< Value of the Op code field for 'Reset System' command.*/
+    OP_CODE_IMAGE_SIZE_REQ       = 7,                                               /**< Value of the Op code field for 'Report received image size' command.*/
+    OP_CODE_PKT_RCPT_NOTIF_REQ   = 8,                                               /**< Value of the Op code field for 'Request packet receipt notification.*/
+    OP_CODE_RESPONSE             = 16,                                              /**< Value of the Op code field for 'Response.*/
+    OP_CODE_PKT_RCPT_NOTIF       = 17                                               /**< Value of the Op code field for 'Packets Receipt Notification'.*/
+};
+
+/* State transitions */
+
+static uint8_t dfu_begin_init (aci_state_t *aci_state, aci_evt_t *aci_evt)
+{
+  ble_assert (aci_state != NULL);
+  ble_assert (aci_evt != NULL);
+  ble_assert (state == ST_RDY);
+
+  return ST_RX_INIT_PKT;
+}
+
+static uint8_t dfu_begin_transfer (aci_state_t *aci_state, aci_evt_t *aci_evt)
+{
+  ble_assert (aci_state != NULL);
+  ble_assert (aci_evt != NULL);
+  ble_assert ((state == ST_RDY) | (state == ST_RX_INIT_PKT));
+
+  return ST_RX_DATA_PKT;
+}
+
+static uint8_t dfu_data_pkt_handle (aci_state_t *aci_state, aci_evt_t *aci_evt)
+{
+  static uint8_t response[3] = {OP_CODE_RESPONSE, BLE_DFU_RECEIVE_APP_PROCEDURE, BLE_DFU_RESP_VAL_SUCCESS};
+
+  ble_assert (aci_state != NULL);
+  ble_assert (aci_evt != NULL);
+  ble_assert (state == ST_RX_DATA_PKT);
+
+  bytes_received += aci_evt->len-2;
+  packets_received++;
+
+  /* Send notification for every N packets */
+  if (0 == (packets_received % notify_every))
+  {
+      #ifdef DEBUG
+      Serial.println(F(" Writing notification"));
+      #endif DEBUG
+
+      dfu_notify (aci_state);
+  }
+
+  if (firmware_len == bytes_received)
+  {
+    #ifdef DEBUG
+    Serial.print(F(" All bytes received ("));
+    Serial.print(bytes_received, DEC);
+    Serial.println(F(")"));
+    #endif
+
+    dfu_send (aci_state, response, 3);
+  }
+
+  return ST_RX_DATA_PKT;
+}
+
+static uint8_t dfu_image_size_set(aci_state_t *aci_state, aci_evt_t *aci_evt)
+{
+  static uint8_t response[3] = {OP_CODE_RESPONSE, BLE_DFU_START_PROCEDURE, BLE_DFU_RESP_VAL_SUCCESS};
+
+  ble_assert (aci_state != NULL);
+  ble_assert (aci_evt != NULL);
+  ble_assert (state == ST_IDLE);
+
+  firmware_len = (uint32_t)aci_evt->params.data_received.rx_data.aci_data[3] << 24 |
+                 (uint32_t)aci_evt->params.data_received.rx_data.aci_data[2] << 16 |
+                 (uint32_t)aci_evt->params.data_received.rx_data.aci_data[1] << 8  |
+                 (uint32_t)aci_evt->params.data_received.rx_data.aci_data[0];
+
+  #ifdef DEBUG
+  Serial.print(F("Received length: "));
+  Serial.println(firmware_len, DEC);
+  #endif
+
+  /* Write response */
+  dfu_send (aci_state, response, 3);
+
+  return ST_RDY;
+}
+
+static uint8_t dfu_image_activate(aci_state_t *aci_state, aci_evt_t *aci_evt)
+{
+  ble_assert (aci_state != NULL);
+  ble_assert (aci_evt != NULL);
+  ble_assert (state == ST_FW_VALID);
+
+  lib_aci_disconnect(aci_state, ACI_REASON_TERMINATE);
+
+  return ST_FW_VALID;
+}
+
+static uint8_t dfu_init_pkt_handle (aci_state_t *aci_state, aci_evt_t *aci_evt)
+{
+  ble_assert (aci_state != NULL);
+  ble_assert (aci_evt != NULL);
+  ble_assert (state == ST_RX_INIT_PKT);
+
+  return ST_RX_INIT_PKT;
+}
+
+static uint8_t dfu_image_validate (aci_state_t *aci_state, aci_evt_t *aci_evt)
+{
+  uint8_t new_state;
+  uint8_t response[3] = {OP_CODE_RESPONSE, BLE_DFU_VALIDATE_PROCEDURE};
+
+  ble_assert (aci_state != NULL);
+  ble_assert (aci_evt != NULL);
+  ble_assert (state == ST_RX_DATA_PKT);
+
+  /* TODO: Implement CRC validation */
+  if (bytes_received == firmware_len)
+  {
+    #ifdef DEBUG
+    Serial.println(F(" Validation successful"));
+    #endif
+    /* Completed successfully */
+    response[3] = BLE_DFU_RESP_VAL_SUCCESS;
+    dfu_send(aci_state, response, 3);
+
+    state = ST_FW_VALID;
+  }
+  else
+  {
+    #ifdef DEBUG
+    Serial.println(F(" Validation failed"));
+    #endif
+
+    /* CRC error */
+    response[3] = BLE_DFU_RESP_VAL_CRC_ERROR;
+    dfu_send(aci_state, response, 3);
+
+    state = ST_FW_VALID;
+  }
+
+  return state;
+}
+
+static uint8_t dfu_notification_set (aci_state_t *aci_state, aci_evt_t *aci_evt)
+{
+  ble_assert (aci_state != NULL);
+  ble_assert (aci_evt != NULL);
+
+  notify_every = (uint16_t)aci_evt->params.data_received.rx_data.aci_data[2] << 8 |
+                 (uint16_t)aci_evt->params.data_received.rx_data.aci_data[1];
+
+
+
+  #ifdef DEBUG
+  Serial.print(F(" Remote device requested notification every "));
+  Serial.print(notify_every, DEC);
+  Serial.println(F(" packets"));
+  #endif
+
+  return state;
+}
+
+dfu_transition_t trans[] = {
+	{ ST_IDLE,		    BLE_DFU_PACKET_WRITE,            &dfu_image_size_set          },
+	{ ST_RDY,		      BLE_DFU_RECEIVE_INIT_DATA,       &dfu_begin_init              },
+	{ ST_RX_INIT_PKT, BLE_DFU_PACKET_WRITE,            &dfu_init_pkt_handle         },
+  { ST_RDY,		      BLE_DFU_RECEIVE_APP_DATA,        &dfu_begin_transfer          },
+  { ST_RX_INIT_PKT,	BLE_DFU_RECEIVE_APP_DATA,        &dfu_begin_transfer          },
+	{ ST_RX_DATA_PKT,	BLE_DFU_PACKET_WRITE,            &dfu_data_pkt_handle         },
+  { ST_RX_DATA_PKT,	BLE_DFU_VALIDATE,                &dfu_image_validate          },
+  { ST_FW_VALID,    BLE_DFU_SYS_RESET,               &dfu_image_activate          },
+  { ST_FW_VALID,    BLE_DFU_ACTIVATE_N_RESET,        &dfu_image_activate          },
+  { ST_ANY,         BLE_DFU_PKT_RCPT_NOTIF_ENABLED,  &dfu_notification_set        },
+  { ST_ANY,         BLE_DFU_PKT_RCPT_NOTIF_DISABLED, &dfu_notification_set        }
+};
+
+#define TRANS_COUNT (sizeof(trans)/sizeof(*trans))
+
+/* Write receive notification */
+static void dfu_notify (aci_state_t *aci_state)
+{
+  uint8_t response[6] = {OP_CODE_PKT_RCPT_NOTIF,
+                         0,
+                         (uint8_t) bytes_received,
+                         (uint8_t) (bytes_received >> 8),
+                         (uint8_t) (bytes_received >> 16),
+                         (uint8_t) (bytes_received >> 24)
+                         };
+
+  ble_assert (aci_state != NULL);
+
+  dfu_send (aci_state, response, 6);
+}
+
+static bool dfu_send (aci_state_t *aci_state, uint8_t *buffer, uint8_t buffer_len)
+{
+	bool status = false;
+
+  ble_assert (aci_state != NULL);
+  ble_assert (buffer != NULL);
+
+	if (lib_aci_is_pipe_available(aci_state,
+                                PIPE_DEVICE_FIRMWARE_UPDATE_BLE_SERVICE_DFU_CONTROL_POINT_TX) &&
+                                (aci_state->data_credit_available >= 1))
+	{
+		status = lib_aci_send_data(PIPE_DEVICE_FIRMWARE_UPDATE_BLE_SERVICE_DFU_CONTROL_POINT_TX,
+                               buffer,
+                               buffer_len);
+		if (status)
+		{
+			aci_state->data_credit_available--;
+		}
+	}
+
+	return status;
+}
+
+static uint8_t dfu_get_event (aci_state_t *aci_state, aci_evt_t *aci_evt)
+{
+  uint8_t event;
+
+  ble_assert (aci_state != NULL);
+  ble_assert (aci_evt != NULL);
+
+  switch (aci_evt->params.data_received.rx_data.pipe_number)
+  {
+    case PIPE_DEVICE_FIRMWARE_UPDATE_BLE_SERVICE_DFU_PACKET_RX:
+      event = BLE_DFU_PACKET_WRITE;
+      break;
+
+    case PIPE_DEVICE_FIRMWARE_UPDATE_BLE_SERVICE_DFU_CONTROL_POINT_RX_ACK_AUTO:
+      #ifdef DEBUG
+      Serial.print(F("PIPE_DEVICE_FIRMWARE_UPDATE_BLE_SERVICE_DFU_CONTROL_POINT_RX_ACK_AUTO. Opcode: "));
+      Serial.println(aci_evt->params.data_received.rx_data.aci_data[0], DEC);
+      #endif
+
+      switch (aci_evt->params.data_received.rx_data.aci_data[0])
+      {
+        /* Start DFU */
+        case OP_CODE_START_DFU:
+          event = BLE_DFU_START;
+          break;
+
+        /* Initialize DFU parameters */
+        case OP_CODE_RECEIVE_INIT:
+          event = BLE_DFU_RECEIVE_INIT_DATA;
+          break;
+
+        /* Receive firmware image */
+        case OP_CODE_RECEIVE_FW:
+          event = BLE_DFU_RECEIVE_APP_DATA;
+          break;
+
+        /* Validate firmware image */
+        case OP_CODE_VALIDATE:
+          event = BLE_DFU_VALIDATE;
+          break;
+
+        /* Activate image and reset */
+        case OP_CODE_ACTIVATE_N_RESET:
+          event = BLE_DFU_ACTIVATE_N_RESET;
+          break;
+
+        /* Reset system */
+        case OP_CODE_SYS_RESET:
+          event = BLE_DFU_SYS_RESET;
+          break;
+
+        /* Report received image size */
+        case OP_CODE_IMAGE_SIZE_REQ:
+          event = BLE_DFU_BYTES_RECEIVED_SEND;
+          break;
+
+        /* Packet receipt notification request */
+        case OP_CODE_PKT_RCPT_NOTIF_REQ:
+          if (aci_evt->params.data_received.rx_data.aci_data[1] == 0)
+          {
+            event = BLE_DFU_PKT_RCPT_NOTIF_DISABLED;
+          }
+          else
+          {
+            event = BLE_DFU_PKT_RCPT_NOTIF_ENABLED;
+          }
+          break;
+
+        default:
+          event = EV_ANY;
+          break;
+      }
+      break;
+
+    default:
+      event = EV_ANY;
+  }
+  return event;
+}
+
+void dfu_initialize (void)
+{
+  #ifdef DEBUG
+  Serial.println(F(" Initializing DFU state machine"));
+  #endif
+
+  if (true)
+  {
+    state = ST_IDLE;
+  }
+  else
+  {
+    state = ST_INIT_ERROR;
+  }
+}
+
+void dfu_update (aci_state_t *aci_state, aci_evt_t *aci_evt)
+{
+  hal_aci_evt_t aci_data;
+  uint8_t event;
+  uint8_t i;
+
+  ble_assert (aci_state != NULL);
+  ble_assert (aci_evt != NULL);
+
+  event = dfu_get_event(aci_state, aci_evt);
+
+  for (i = 0; i < TRANS_COUNT; i++)
+	{
+    if ((state == trans[i].st) || (ST_ANY == trans[i].st))
+		{
+		  if ((event == trans[i].ev) || (EV_ANY == trans[i].ev))
+			{
+        #ifdef DEBUG
+        Serial.print(F("Transition (state = "));
+        Serial.print(trans[i].st);
+        Serial.print(F(", event = "));
+        Serial.print(trans[i].ev);
+        Serial.println(F(")"));
+        #endif
+
+        state = (trans[i].fn)(aci_state, aci_evt);
+        return;
+      }
+    }
+  }
+
+  /* Unhandled event */
+  ble_assert(false);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/dfu.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/dfu.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/dfu.h	(revision 453)
@@ -0,0 +1,87 @@
+#ifndef DFU_H_
+#define DFU_H_
+
+#define ST_IDLE		          0
+#define ST_INIT_ERROR       1
+#define ST_RDY		          2
+#define ST_RX_INIT_PKT	    3
+#define ST_RX_DATA_PKT	    4
+#define ST_FW_VALID         5
+#define ST_FW_INVALID       6
+#define ST_ANY	  	        255
+
+#define EV_ANY              255
+
+#define PIPE_DEVICE_FIRMWARE_UPDATE_BLE_SERVICE_DFU_PACKET_RX                   8
+#define PIPE_DEVICE_FIRMWARE_UPDATE_BLE_SERVICE_DFU_CONTROL_POINT_TX            9
+#define PIPE_DEVICE_FIRMWARE_UPDATE_BLE_SERVICE_DFU_CONTROL_POINT_RX_ACK_AUTO   10
+
+/**@brief   DFU Event type.
+ *
+ * @details This enumeration contains the types of events that will be received from the DFU Service.
+ */
+typedef enum
+{
+    BLE_DFU_START                      = 1,                            /**< The event indicating that the peer wants the application to prepare for a new firmware update. */
+    BLE_DFU_RECEIVE_INIT_DATA          = 2,                            /**< The event indicating that the peer wants the application to prepare to receive init parameters. */
+    BLE_DFU_RECEIVE_APP_DATA           = 3,                            /**< The event indicating that the peer wants the application to prepare to receive the new firmware image. */
+    BLE_DFU_VALIDATE                   = 4,                            /**< The event indicating that the peer wants the application to validate the newly received firmware image. */
+    BLE_DFU_ACTIVATE_N_RESET           = 5,                            /**< The event indicating that the peer wants the application to undergo activate new firmware and restart with new valid application */
+    BLE_DFU_SYS_RESET                  = 6,                            /**< The event indicating that the peer wants the application to undergo a reset and start the currently valid application image.*/
+    BLE_DFU_PKT_RCPT_NOTIF_ENABLED     = 7,                            /**< The event indicating that the peer has enabled packet receipt notifications. It is the responsibility of the application to call @ref ble_dfu_pkts_rcpt_notify each time the number of packets indicated by num_of_pkts field in @ref ble_dfu_evt_t is received.*/
+    BLE_DFU_PKT_RCPT_NOTIF_DISABLED    = 8,                            /**< The event indicating that the peer has disabled the packet receipt notifications.*/
+    BLE_DFU_PACKET_WRITE               = 9,                            /**< The event indicating that the peer has written a value to the 'DFU Packet' characteristic. The data received from the peer will be present in the @ref ble_dfu_pkt_write element contained within @ref ble_dfu_evt_t.*/
+    BLE_DFU_BYTES_RECEIVED_SEND        = 10                            /**< The event indicating that the peer is requesting for the number of bytes of firmware data last received by the application. It is the responsibility of the application to call @ref ble_dfu_pkts_rcpt_notify in response to this event. */
+} ble_dfu_evt_type_t;
+
+/**@brief   DFU Procedure type.
+ *
+ * @details This enumeration contains the types of DFU procedures.
+ */
+typedef enum
+{
+    BLE_DFU_START_PROCEDURE        = 1,                                 /**< DFU Start procedure.*/
+    BLE_DFU_INIT_PROCEDURE         = 2,                                 /**< DFU Initialization procedure.*/
+    BLE_DFU_RECEIVE_APP_PROCEDURE  = 3,                                 /**< Firmware receiving procedure.*/
+    BLE_DFU_VALIDATE_PROCEDURE     = 4,                                 /**< Firmware image validation procedure .*/
+    BLE_DFU_PKT_RCPT_REQ_PROCEDURE = 8                                  /**< Packet receipt notification request procedure. */
+} ble_dfu_procedure_t;
+
+/**@brief   DFU Response value type.
+ */
+typedef enum
+{
+    BLE_DFU_RESP_VAL_SUCCESS        = 1,                                /**< Success.*/
+    BLE_DFU_RESP_VAL_INVALID_STATE  = 2,                                /**< Invalid state.*/
+    BLE_DFU_RESP_VAL_NOT_SUPPORTED  = 3,                                /**< Operation not supported.*/
+    BLE_DFU_RESP_VAL_DATA_SIZE      = 4,                                /**< Data size exceeds limit.*/
+    BLE_DFU_RESP_VAL_CRC_ERROR      = 5,                                /**< CRC Error.*/
+    BLE_DFU_RESP_VAL_OPER_FAILED    = 6,                                /**< Operation failed.*/
+} ble_dfu_resp_val_t;
+
+/**
+ *  @brief FSM transition
+ *
+ * Struct that describes a transition in the FSM.
+ */
+typedef struct
+{   /**
+	 * @brief State
+	 */
+	uint8_t st;
+
+    /**
+	 * @brief Event
+	 */
+	uint8_t ev;
+
+    /**
+	 * @brief Transition function
+	 */
+	uint8_t (*fn)(aci_state_t *aci_state, aci_evt_t *aci_evt);
+} dfu_transition_t;
+
+void dfu_initialize (void);
+void dfu_update (aci_state_t *aci_state, aci_evt_t *aci_evt);
+
+#endif /* DFU_H_ */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/dtm.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/dtm.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/dtm.h	(revision 453)
@@ -0,0 +1,63 @@
+/* Copyright (c) 2014, Nordic Semiconductor ASA
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * @file
+ *
+ * @ingroup group_acilib
+ *
+ * @brief Internal prototype for acilib module.
+ */
+
+#ifndef DTM_H__
+#define DTM_H__
+
+/** @brief DTM command codes (upper two bits in the DTM command), use a bitwise OR with the frequency N = 0x00 - 0x27: N = (F-2402)/2 Frequency Range 2402 MHz
+to 2480 MHz*/
+#define DTM_LE_CMD_RESET            0x00
+#define DTM_LE_CMD_RECEIVER_TEST    0x40
+#define DTM_LE_CMD_TRANSMITTER_TEST 0x80
+#define DTM_LE_CMD_TEST_END         0xC0
+
+
+/** @brief Defined packet types for DTM */
+#define DTM_LE_PKT_PRBS9      0x00       /**< Bit pattern PRBS9.    */
+#define DTM_LE_PKT_0X0F       0x01       /**< Bit pattern 11110000 (LSB is the leftmost bit). */
+#define DTM_LE_PKT_0X55       0x02       /**< Bit pattern 10101010 (LSB is the leftmost bit). */
+#define DTM_LE_PKT_VENDOR     0x03       /**< Vendor specific. Nordic: continous carrier test */
+
+/** @brief Defined bit fields for DTM responses. */
+#define LE_PACKET_REPORTING_EVENT_MSB_BIT   0x80
+#define LE_TEST_STATUS_EVENT_LSB_BIT        0x01
+
+/** @brief DTM response types. */
+#define LE_TEST_STATUS_EVENT                0x00
+#define LE_TEST_PACKET_REPORT_EVENT         0x80
+
+/** @brief DTM return values. */
+#define LE_TEST_STATUS_SUCCESS              0x00
+#define LE_TEST_STATUS_FAILURE              0x01
+
+
+
+#endif //DTM_H__
+
+/** @} */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/hal_aci_tl.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/hal_aci_tl.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/hal_aci_tl.c	(revision 453)
@@ -0,0 +1,525 @@
+/* Copyright (c) 2014, Nordic Semiconductor ASA
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/** @file
+@brief Implementation of the ACI transport layer module
+*/
+
+#include "hal_platform.h"
+#include "hal_aci_tl.h"
+#include "aci_queue.h"
+
+/*
+PIC32 supports only MSbit transfer on SPI and the nRF8001 uses LSBit
+Use the REVERSE_BITS macro to convert from MSBit to LSBit
+The outgoing command and the incoming event needs to be converted
+*/
+//Board dependent defines
+//For ChipKit as the transmission has to be reversed, the next definitions have to be added
+#ifdef __STM32__
+#define REVERSE_BITS(byte) (byte)
+#else
+#define REVERSE_BITS(byte) (((reverse_lookup[(byte & 0x0F)]) << 4) + reverse_lookup[((byte & 0xF0) >> 4)])
+static const uint8_t reverse_lookup[] = { 0, 8,  4, 12, 2, 10, 6, 14,1, 9, 5, 13,3, 11, 7, 15 };
+#endif
+
+static void m_aci_data_print(hal_aci_data_t *p_data);
+static void m_aci_event_check(void);
+static void m_aci_pins_set(aci_pins_t *a_pins_ptr);
+static inline void m_aci_reqn_disable (void);
+static inline void m_aci_reqn_enable (void);
+static void m_aci_q_flush(void);
+static bool m_aci_spi_transfer(hal_aci_data_t * data_to_send, hal_aci_data_t * received_data);
+
+static uint8_t        spi_readwrite(uint8_t aci_byte);
+
+
+static bool           aci_debug_print = false;
+
+aci_queue_t    aci_tx_q;
+aci_queue_t    aci_rx_q;
+
+static aci_pins_t	 *a_pins_local_ptr;
+
+static SPI_Handle_t *hspi;
+static int evt_taskid;
+static int aci_activate;
+
+/* Buffer used for transmission */
+uint8_t aTxBuffer[4];
+
+/* Buffer used for reception */
+uint8_t aRxBuffer[4];
+
+static uint8_t spi_transfer(uint8_t a)
+{
+  ER ercd;
+
+  aTxBuffer[0] = a;
+#if SPI_WAIT_TIME != 0
+  ercd = spi_transrecv(hspi, (uint8_t*)aTxBuffer, (uint8_t *)aRxBuffer, 1);
+#else
+  if((ercd = spi_transrecv(hspi, (uint8_t*)aTxBuffer, (uint8_t *)aRxBuffer, 1)) == E_OK)
+    ercd = spi_wait(hspi, 100);
+#endif
+  if(ercd != E_OK){
+    /* Transfer error in transmission process */
+    syslog_1(LOG_NOTICE, "## call Error_Handler(2)(%d) ##", ercd);
+  }
+  return aRxBuffer[0];
+}
+
+/*
+ *  GPIO設定関数
+ */
+static void pinMode(uint32_t no, int mode)
+{
+  Arduino_PortControlBlock *ppcb = getGpioTable(DIGITAL_PIN, no);
+  GPIO_Init_t GPIO_Init_Data;
+
+  syslog_2(LOG_NOTICE, "## pinMode(%d, %d) ##", no, mode);
+  syslog_2(LOG_NOTICE, "## [%08x](%d) ##", ppcb->giobase, ppcb->giopin);
+  if(ppcb == NULL)
+    return;
+  pinClock(no);
+  if(mode == OUTPUT){
+    GPIO_Init_Data.mode      = GPIO_MODE_OUTPUT;
+    GPIO_Init_Data.pull      = GPIO_PULLUP;
+    GPIO_Init_Data.otype     = GPIO_OTYPE_PP;
+#ifdef TOPPERS_BASE_PLATFORM_RV
+	GPIO_Init_Data.oxor  = GPIO_OUTPUT_NORMAL;
+	GPIO_Init_Data.iof   = GPIO_NOIOF;
+#else
+    GPIO_Init_Data.speed     = GPIO_SPEED_FAST;
+#endif
+    gpio_setup(ppcb->giobase, &GPIO_Init_Data, ppcb->giopin);
+  }
+  else{
+    GPIO_Init_Data.mode      = GPIO_MODE_IT_RISING_FALLING;
+    if(mode == INPUT_PULLUP)
+      GPIO_Init_Data.pull    = GPIO_PULLUP;
+    else
+      GPIO_Init_Data.pull    = GPIO_NOPULL;
+    gpio_setup(ppcb->giobase, &GPIO_Init_Data, ppcb->giopin);
+  }
+}
+
+void m_aci_data_print(hal_aci_data_t *p_data)
+{
+  const uint8_t length = p_data->buffer[0];
+  uint8_t i, j, len, data[5];
+
+  len = length % 5;
+  if(len == 0)
+    len = length;
+  else
+    len = length + 5 - len;
+  for (i=j=0; i< len; i++){
+    if(i < length)
+      data[j] = p_data->buffer[i+1];
+    else
+      data[j] = 0xff;
+    if(j == 4){
+       syslog_5(LOG_NOTICE, "%02x, %02x, %02x, %02x, %02x,", data[0], data[1], data[2], data[3], data[4]);
+       j = 0;
+    }
+    else
+       j++;
+  }
+}
+
+/*
+  Interrupt service routine called when the RDYN line goes low. Runs the SPI transfer.
+*/
+void
+m_aci_isr(void)
+{
+  if(aci_activate == 0){
+    if(evt_taskid != 0)
+      iact_tsk(evt_taskid);
+    else
+      aci_task(0);
+  }
+}
+
+void aci_task(int arg)
+{
+  hal_aci_data_t data_to_send;
+  hal_aci_data_t received_data;
+#ifdef NOACT_TASK	/* ROI DEBUG */
+	syslog_1(LOG_NOTICE, "## aci_task(%d) ##", arg);
+#endif	/* ROI DEBUG */
+
+  aci_activate = 1;
+  // Receive from queue
+  if (!aci_queue_dequeue/*_from_isr*/(&aci_tx_q, &data_to_send))
+  {
+    /* queue was empty, nothing to send */
+    data_to_send.status_byte = 0;
+    data_to_send.buffer[0] = 0;
+  }
+
+  // Receive and/or transmit data
+  if(!m_aci_spi_transfer(&data_to_send, &received_data)){
+    m_aci_reqn_enable();
+    aci_activate = 0;
+    return;
+  }
+
+  if (!aci_queue_is_full/*_from_isr*/(&aci_rx_q) && !aci_queue_is_empty/*_from_isr*/(&aci_tx_q))
+  {
+    m_aci_reqn_enable();
+  }
+
+  // Check if we received data
+  if (received_data.buffer[0] > 0)
+  {
+    if (!aci_queue_enqueue/*_from_isr*/(&aci_rx_q, &received_data))
+    {
+      /* Receive Buffer full.
+         Should never happen.
+         Spin in a while loop.
+      */
+      syslog_0(LOG_ERROR, "aci_task Buffer full !");
+      while(1);
+    }
+  }
+  aci_activate = 0;
+
+  return;
+}
+
+/*
+  Checks the RDYN line and runs the SPI transfer if required.
+*/
+static void m_aci_event_check(void)
+{
+  hal_aci_data_t data_to_send;
+  hal_aci_data_t received_data;
+
+  // No room to store incoming messages
+  if (aci_queue_is_full(&aci_rx_q))
+  {
+    return;
+  }
+
+  // If the ready line is disabled and we have pending messages outgoing we enable the request line
+  if (HIGH == digitalRead(a_pins_local_ptr->rdyn_pin))
+  {
+    if (!aci_queue_is_empty(&aci_tx_q))
+    {
+      m_aci_reqn_enable();
+    }
+
+    return;
+  }
+
+  // Receive from queue
+  if (!aci_queue_dequeue(&aci_tx_q, &data_to_send))
+  {
+    /* queue was empty, nothing to send */
+    data_to_send.status_byte = 0;
+    data_to_send.buffer[0] = 0;
+  }
+
+  // Receive and/or transmit data
+  m_aci_spi_transfer(&data_to_send, &received_data);
+
+  /* If there are messages to transmit, and we can store the reply, we request a new transfer */
+  if (!aci_queue_is_full(&aci_rx_q) && !aci_queue_is_empty(&aci_tx_q))
+  {
+    m_aci_reqn_enable();
+  }
+
+  // Check if we received data
+  if (received_data.buffer[0] > 0)
+  {
+    if (!aci_queue_enqueue(&aci_rx_q, &received_data))
+    {
+      /* Receive Buffer full.
+         Should never happen.
+         Spin in a while loop.
+      */
+      syslog_0(LOG_ERROR, "m_aci_event_check Buffer full !");
+      while(1);
+    }
+  }
+
+  return;
+}
+
+/** @brief Point the low level library at the ACI pins specified
+ *  @details
+ *  The ACI pins are specified in the application and a pointer is made available for
+ *  the low level library to use
+ */
+static void m_aci_pins_set(aci_pins_t *a_pins_ptr)
+{
+  a_pins_local_ptr = a_pins_ptr;
+}
+
+static inline void m_aci_reqn_disable (void)
+{
+  digitalWrite(a_pins_local_ptr->reqn_pin, 1);
+}
+
+static inline void m_aci_reqn_enable (void)
+{
+  digitalWrite(a_pins_local_ptr->reqn_pin, 0);
+}
+
+static void m_aci_q_flush(void)
+{
+  noInterrupts();
+  /* re-initialize aci cmd queue and aci event queue to flush them*/
+  aci_queue_init(&aci_tx_q);
+  aci_queue_init(&aci_rx_q);
+  interrupts();
+}
+
+static bool m_aci_spi_transfer(hal_aci_data_t * data_to_send, hal_aci_data_t * received_data)
+{
+  uint8_t byte_cnt;
+  uint8_t byte_sent_cnt;
+  uint8_t max_bytes;
+
+  m_aci_reqn_enable();
+
+  // Send length, receive header
+  byte_sent_cnt = 0;
+  received_data->status_byte = spi_readwrite(data_to_send->buffer[byte_sent_cnt++]);
+  // Send first byte, receive length from slave
+  received_data->buffer[0] = spi_readwrite(data_to_send->buffer[byte_sent_cnt++]);
+  if(received_data->buffer[0] == 0xff)
+    return false;
+  if (0 == data_to_send->buffer[0])
+  {
+    max_bytes = received_data->buffer[0];
+  }
+  else
+  {
+    // Set the maximum to the biggest size. One command byte is already sent
+    max_bytes = (received_data->buffer[0] > (data_to_send->buffer[0] - 1))
+                                          ? received_data->buffer[0]
+                                          : (data_to_send->buffer[0] - 1);
+  }
+
+  if (max_bytes > HAL_ACI_MAX_LENGTH)
+  {
+    max_bytes = HAL_ACI_MAX_LENGTH;
+  }
+
+  // Transmit/receive the rest of the packet
+  for (byte_cnt = 0; byte_cnt < max_bytes; byte_cnt++)
+  {
+    received_data->buffer[byte_cnt+1] =  spi_readwrite(data_to_send->buffer[byte_sent_cnt++]);
+  }
+
+  // RDYN should follow the REQN line in approx 100ns
+  m_aci_reqn_disable();
+
+  return (max_bytes > 0);
+}
+
+void hal_aci_tl_debug_print(bool enable)
+{
+	aci_debug_print = enable;
+}
+
+void hal_aci_tl_pin_reset(void)
+{
+    if (UNUSED != a_pins_local_ptr->reset_pin)
+    {
+        pinMode(a_pins_local_ptr->reset_pin, OUTPUT);
+
+        if ((REDBEARLAB_SHIELD_V1_1     == a_pins_local_ptr->board_name) ||
+            (REDBEARLAB_SHIELD_V2012_07 == a_pins_local_ptr->board_name))
+        {
+            //The reset for the Redbearlab v1.1 and v2012.07 boards are inverted and has a Power On Reset
+            //circuit that takes about 100ms to trigger the reset
+            digitalWrite(a_pins_local_ptr->reset_pin, 1);
+            delay(100);
+            digitalWrite(a_pins_local_ptr->reset_pin, 0);
+        }
+        else
+        {
+            digitalWrite(a_pins_local_ptr->reset_pin, 1);
+            digitalWrite(a_pins_local_ptr->reset_pin, 0);
+            digitalWrite(a_pins_local_ptr->reset_pin, 1);
+        }
+    }
+}
+
+bool hal_aci_tl_event_peek(hal_aci_data_t *p_aci_data)
+{
+  if (!a_pins_local_ptr->interface_is_interrupt)
+  {
+    m_aci_event_check();
+  }
+
+  if (aci_queue_peek(&aci_rx_q, p_aci_data))
+  {
+    return true;
+  }
+
+  return false;
+}
+
+bool hal_aci_tl_event_get(hal_aci_data_t *p_aci_data)
+{
+  bool was_full;
+
+  if (!a_pins_local_ptr->interface_is_interrupt && !aci_queue_is_full(&aci_rx_q))
+  {
+    m_aci_event_check();
+  }
+
+  was_full = aci_queue_is_full(&aci_rx_q);
+
+  if (aci_queue_dequeue(&aci_rx_q, p_aci_data))
+  {
+    if (aci_debug_print)
+    {
+      syslog_1(LOG_NOTICE, "EVT %d:", p_aci_data->buffer[0]);
+      m_aci_data_print(p_aci_data);
+    }
+
+    /* Attempt to pull REQN LOW since we've made room for new messages */
+    if (!aci_queue_is_full(&aci_rx_q) && !aci_queue_is_empty(&aci_tx_q))
+    {
+      m_aci_reqn_enable();
+    }
+
+    return true;
+  }
+
+  (void)(was_full);
+  return false;
+}
+
+void hal_aci_tl_init(aci_pins_t *a_pins, bool debug)
+{
+  aci_debug_print = debug;
+
+  /* Needs to be called as the first thing for proper intialization*/
+  m_aci_pins_set(a_pins);
+
+  /*
+  The SPI lines used are mapped directly to the hardware SPI
+  MISO MOSI and SCK
+  Change here if the pins are mapped differently
+
+  The SPI library assumes that the hardware pins are used
+  */
+  hspi = a_pins->spihandle;
+  evt_taskid = a_pins->event_taskid;
+
+  /* Initialize the ACI Command queue. This must be called after the delay above. */
+  aci_queue_init(&aci_tx_q);
+  aci_queue_init(&aci_rx_q);
+
+  //Configure the IO lines
+  pinMode(a_pins->rdyn_pin,		INPUT_PULLUP);
+  pinMode(a_pins->reqn_pin,		OUTPUT);
+
+  if (UNUSED != a_pins->active_pin)
+  {
+    pinMode(a_pins->active_pin,	INPUT);
+  }
+  /* Pin reset the nRF8001, required when the nRF8001 setup is being changed */
+  hal_aci_tl_pin_reset();
+
+  /* Set the nRF8001 to a known state as required by the datasheet*/
+  digitalWrite(a_pins->reqn_pin, 1);
+
+  dly_tsk(30); //Wait for the nRF8001 to get hold of its lines - the lines float for a few ms after the reset
+}
+
+bool hal_aci_tl_send(hal_aci_data_t *p_aci_cmd)
+{
+  const uint8_t length = p_aci_cmd->buffer[0];
+  bool ret_val = false;
+
+  if (length > HAL_ACI_MAX_LENGTH)
+  {
+    return false;
+  }
+
+  ret_val = aci_queue_enqueue(&aci_tx_q, p_aci_cmd);
+  if (ret_val)
+  {
+    if(!aci_queue_is_full(&aci_rx_q))
+    {
+      // Lower the REQN only when successfully enqueued
+      m_aci_reqn_enable();
+    }
+
+    if (aci_debug_print)
+    {
+      syslog_1(LOG_NOTICE, "CMD %d:", p_aci_cmd->buffer[0]);
+      m_aci_data_print(p_aci_cmd);
+    }
+  }
+
+  return ret_val;
+}
+
+static uint8_t spi_readwrite(const uint8_t aci_byte)
+{
+  //Board dependent defines
+  //For ChipKit the transmission has to be reversed
+  uint8_t tmp_bits;
+  tmp_bits = spi_transfer(REVERSE_BITS(aci_byte));
+#if 0	/* ROI DEBUG */
+	{
+		uint32_t tim;
+		get_tim(&tim);
+		syslog_5(LOG_NOTICE, "## spi_readwrite in1[%02x] in2[%02x] out1[%02x] out2[%02x] tim(%d) ##", aci_byte, REVERSE_BITS(aci_byte), tmp_bits, REVERSE_BITS(tmp_bits), tim);
+	}
+#endif	/* ROI DEBUG */
+  return REVERSE_BITS(tmp_bits);
+}
+
+bool hal_aci_tl_rx_q_empty (void)
+{
+  return aci_queue_is_empty(&aci_rx_q);
+}
+
+bool hal_aci_tl_rx_q_full (void)
+{
+  return aci_queue_is_full(&aci_rx_q);
+}
+
+bool hal_aci_tl_tx_q_empty (void)
+{
+  return aci_queue_is_empty(&aci_tx_q);
+}
+
+bool hal_aci_tl_tx_q_full (void)
+{
+  return aci_queue_is_full(&aci_tx_q);
+}
+
+void hal_aci_tl_q_flush (void)
+{
+  m_aci_q_flush();
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/hal_aci_tl.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/hal_aci_tl.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/hal_aci_tl.h	(revision 453)
@@ -0,0 +1,191 @@
+/* Copyright (c) 2014, Nordic Semiconductor ASA
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */ 
+
+/** @file
+ * @brief Interface for hal_aci_tl.
+ */
+ 
+/** @defgroup hal_aci_tl hal_aci_tl
+@{
+@ingroup hal
+ 
+@brief Module for the ACI Transport Layer interface
+@details This module is responsible for sending and receiving messages over the ACI interface of the nRF8001 chip.
+ The hal_aci_tl_send_cmd() can be called directly to send ACI commands.
+
+
+The RDYN line is hooked to an interrupt on the MCU when the level is low.
+The SPI master clocks in the interrupt context.
+The ACI Command is taken from the head of the command queue is sent over the SPI
+and the received ACI event is placed in the tail of the event queue.
+
+*/
+ 
+#ifndef HAL_ACI_TL_H__
+#define HAL_ACI_TL_H__
+
+#include "hal_platform.h"
+#include "aci.h"
+#include "boards.h"
+
+#ifndef HAL_ACI_MAX_LENGTH
+#define HAL_ACI_MAX_LENGTH 31
+#endif
+
+/************************************************************************/
+/* Unused nRF8001 pin                                                    */
+/************************************************************************/
+#define UNUSED		    255
+
+/** Data type for ACI commands and events */
+typedef struct {
+  uint8_t status_byte;
+  uint8_t buffer[HAL_ACI_MAX_LENGTH+1];
+} _aci_packed_ hal_aci_data_t;
+
+ACI_ASSERT_SIZE(hal_aci_data_t, HAL_ACI_MAX_LENGTH + 2);
+
+/** Datatype for ACI pins and interface (polling/interrupt)*/
+typedef struct aci_pins_t
+{
+	uint8_t board_name;             //Optional : Use BOARD_DEFAULT if you do not know. See boards.h
+	uint8_t	reqn_pin;				//Required
+	uint8_t	rdyn_pin;				//Required
+//	uint8_t	mosi_pin;				//Required
+//	uint8_t	miso_pin;				//Required
+//	uint8_t	sck_pin;				//Required
+	
+//	uint8_t spi_clock_divider;      //Required : Clock divider on the SPI clock : nRF8001 supports a maximum clock of 3MHz
+	void   *spihandle;				//Required
+	
+	uint8_t	reset_pin;				//Recommended but optional - Set it to UNUSED when not connected
+	uint8_t active_pin;				//Optional - Set it to UNUSED when not connected
+	uint8_t optional_chip_sel_pin;  //Optional - Used only when the reqn line is required to be separate from the SPI chip select. Eg. Arduino DUE
+	
+	bool	interface_is_interrupt;	//Required - true = Uses interrupt on RDYN pin. false - Uses polling on RDYN pin
+	
+//	uint8_t	interrupt_number;		//Required when using interrupts, otherwise ignored
+	int     event_taskid;			//Required event taskid
+} aci_pins_t;
+
+/** @brief ACI Transport Layer initialization.
+ *  @details
+ *  This function initializes the transport layer, including configuring the SPI, creating
+ *  message queues for Commands and Events and setting up interrupt if required.
+ *  @param a_pins Pins on the MCU used to connect to the nRF8001
+ *  @param bool True if debug printing should be enabled on the Serial.
+ */
+void hal_aci_tl_init(aci_pins_t *a_pins, bool debug);
+
+/** @brief Sends an ACI command to the radio.
+ *  @details
+ *  This function sends an ACI command to the radio. This queue up the message to send and 
+ *  lower the request line. When the device lowers the ready line, @ref m_aci_spi_transfer()
+ *  will send the data.
+ *  @param aci_buffer Pointer to the message to send.
+ *  @return True if the data was successfully queued for sending, 
+ *  false if there is no more space to store messages to send.
+ */
+bool hal_aci_tl_send(hal_aci_data_t *aci_buffer);
+
+/** @brief Process pending transactions.
+ *  @details 
+ *  The library code takes care of calling this function to check if the nRF8001 RDYN line indicates a
+ *  pending transaction. It will send a pending message if there is one and return any receive message
+ *  that was pending.
+ *  @return Points to data buffer for received data. Length byte in buffer is 0 if no data received.
+ */
+hal_aci_data_t * hal_aci_tl_poll_get(void);
+
+/** @brief Get an ACI event from the event queue
+ *  @details 
+ *  Call this function from the main context to get an event from the ACI event queue
+ *  This is called by lib_aci_event_get
+ */
+bool hal_aci_tl_event_get(hal_aci_data_t *p_aci_data);
+
+/** @brief Peek an ACI event from the event queue
+ *  @details
+ *  Call this function from the main context to peek an event from the ACI event queue.
+ *  This is called by lib_aci_event_peek
+ */
+bool hal_aci_tl_event_peek(hal_aci_data_t *p_aci_data);
+
+/** @brief Enable debug printing of all ACI commands sent and ACI events received
+ *  @details
+ *  when the enable parameter is true. The debug printing is enabled on the Serial.
+ *  When the enable parameter is false. The debug printing is disabled on the Serial.
+ *  By default the debug printing is disabled.
+ */
+void hal_aci_tl_debug_print(bool enable);
+
+
+/** @brief Pin reset the nRF8001
+ *  @details
+ *  The reset line of the nF8001 needs to kept low for 200 ns.
+ *  Redbearlab shield v1.1 and v2012.07 are exceptions as they
+ *  have a Power ON Reset circuit that works differently.
+ *  The function handles the exceptions based on the board_name in aci_pins_t
+ */
+void hal_aci_tl_pin_reset(void);
+
+/** @brief Return full status of transmit queue
+ *  @details
+ *
+ */
+bool hal_aci_tl_rx_q_full(void);
+ 
+ /** @brief Return empty status of receive queue
+ *  @details
+ *
+ */
+bool hal_aci_tl_rx_q_empty(void);
+
+/** @brief Return full status of receive queue
+ *  @details
+ *
+ */
+bool hal_aci_tl_tx_q_full(void);
+ 
+ /** @brief Return empty status of transmit queue
+ *  @details
+ *
+ */
+bool hal_aci_tl_tx_q_empty(void);
+
+/** @brief Flush the ACI command Queue and the ACI Event Queue
+ *  @details
+ *  Call this function in the main thread
+ */
+void hal_aci_tl_q_flush(void);
+
+/**
+ *  added aci interrupt function
+ */
+void m_aci_isr(void);
+
+/**
+ *  added aci task function
+ */
+void aci_task(int arg);
+
+#endif // HAL_ACI_TL_H__
+/** @} */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/hal_platform.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/hal_platform.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/hal_platform.h	(revision 453)
@@ -0,0 +1,106 @@
+/* Copyright (c) 2014, Nordic Semiconductor ASA
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef PLATFORM_H__
+#define PLATFORM_H__
+
+/** @file
+* @brief 
+*/
+
+//Board dependent defines
+#if defined (__AVR__)
+    //For Arduino this AVR specific library has to be used for reading from Flash memory
+    #include <avr/pgmspace.h>
+    #include "Arduino.h"
+    #ifdef PROGMEM
+        #undef PROGMEM
+        #define PROGMEM __attribute__(( section(".progmem.data") ))
+	    #endif
+#elif defined(__PIC32MX__)
+    //For Chipkit add the following libraries.
+    #include <stdint.h>
+    #include <stdbool.h>
+    #include <string.h>
+    #include <wiring.h>
+    #include <WProgram.h>
+#else	/* GCC */
+    #include <kernel.h>
+    #include <t_syslog.h>
+    #include <t_stdlib.h>
+    #include <stdbool.h>
+    #include <stdio.h>
+    #include <string.h>
+    #include <target_syssvc.h>
+    #include "syssvc/serial.h"
+    #include "syssvc/syslog.h"
+    #include "device.h"
+    #include "pinmode.h"
+    #include "spi.h"
+
+    #define delay           dly_tsk
+    #define noInterrupts    loc_cpu
+    #define interrupts      unl_cpu
+
+    #define sil_orw_mem(a, b) sil_wrw_mem((a), sil_rew_mem(a) | (b))
+
+#define PORT_HIGH      1
+#define PORT_LOW       0
+
+#define LOW     PORT_LOW
+#define HIGH    PORT_HIGH
+
+#define INPUT   0
+#define INPUT_PULLUP 1
+#define OUTPUT  2
+
+#endif
+	
+	//For making the Serial.Print compatible between Arduino and Chipkit
+	#define F(X) (X)
+	
+	//For ChipKit neither PROGMEM or PSTR are needed for PIC32
+    #define PROGMEM
+    #define PSTR(s) (s)	
+
+    #define pgm_read_byte(x)	        (*((char *)x))
+    #define pgm_read_byte_near(x)	(*((char *)x))
+    #define pgm_read_byte_far(x)	    (*((char *)x))
+    #define pgm_read_word(x)    	    (*((short *)x))
+    #define pgm_read_word_near(x)	(*((short *)x))
+    #define pgm_read_workd_far(x)	(*((short *)x))
+
+    #define	prog_void	    const void
+    #define	prog_char	    const char
+    #define	prog_uchar	    const unsigned char
+    #define	prog_int8_t	    const int8_t
+    #define	prog_uint8_t	const uint8_t
+    #define	prog_int16_t	const int16_t
+    #define	prog_uint16_t	const uint16_t
+    #define	prog_int32_t	const int32_t
+    #define	prog_uint32_t	const uint32_t
+    #define	prog_int64_t	const int64_t
+    #define	prog_uint64_t	const uint64_t
+	
+	//Redefine the function for reading from flash in ChipKit
+	#define memcpy_P        memcpy
+
+#endif /* PLATFORM_H__ */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/lib_aci.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/lib_aci.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/lib_aci.c	(revision 453)
@@ -0,0 +1,754 @@
+/* Copyright (c) 2014, Nordic Semiconductor ASA
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/** @file
+  @brief Implementation of the ACI library.
+ */
+
+#include "hal_platform.h"
+#include "aci.h"
+#include "aci_cmds.h"
+#include "aci_evts.h"
+#include "aci_protocol_defines.h"
+#include "acilib_defs.h"
+#include "acilib_if.h"
+#include "hal_aci_tl.h"
+#include "aci_queue.h"
+#include "lib_aci.h"
+
+
+#define LIB_ACI_DEFAULT_CREDIT_NUMBER   1
+
+/*
+Global additionally used used in aci_setup 
+*/
+hal_aci_data_t  msg_to_send;
+
+
+static services_pipe_type_mapping_t * p_services_pipe_type_map;
+static hal_aci_data_t *               p_setup_msgs;
+
+
+
+
+static bool is_request_operation_pending;
+static bool is_indicate_operation_pending;
+static bool is_open_remote_pipe_pending;
+static bool is_close_remote_pipe_pending;
+
+static uint8_t request_operation_pipe = 0;
+static uint8_t indicate_operation_pipe = 0;
+
+
+// The following structure (aci_cmd_params_open_adv_pipe) will be used to store the complete command 
+// including the pipes to be opened. 
+static aci_cmd_params_open_adv_pipe_t aci_cmd_params_open_adv_pipe; 
+
+
+
+extern aci_queue_t    aci_rx_q;
+extern aci_queue_t    aci_tx_q;
+
+bool lib_aci_is_pipe_available(aci_state_t *aci_stat, uint8_t pipe)
+{
+  uint8_t byte_idx;
+
+  byte_idx = pipe / 8;
+  if (aci_stat->pipes_open_bitmap[byte_idx] & (0x01 << (pipe % 8)))
+  {
+    return(true);
+  }
+  return(false);
+}
+
+
+bool lib_aci_is_pipe_closed(aci_state_t *aci_stat, uint8_t pipe)
+{
+  uint8_t byte_idx;
+
+  byte_idx = pipe / 8;
+  if (aci_stat->pipes_closed_bitmap[byte_idx] & (0x01 << (pipe % 8)))
+  {
+    return(true);
+  }
+  return(false);
+}
+
+
+bool lib_aci_is_discovery_finished(aci_state_t *aci_stat)
+{
+  return(aci_stat->pipes_open_bitmap[0]&0x01);
+}
+
+void lib_aci_board_init(aci_state_t *aci_stat)
+{
+	hal_aci_evt_t *aci_data = NULL;
+	aci_data = (hal_aci_evt_t *)&msg_to_send;
+					
+	if (REDBEARLAB_SHIELD_V1_1 == aci_stat->aci_pins.board_name)
+	{
+	  /*
+	  The Bluetooth low energy Arduino shield v1.1 requires about 100ms to reset.
+	  This is not required for the nRF2740, nRF2741 modules
+	  */
+	  delay(100);
+  
+	  /*
+	  Send the soft reset command to the nRF8001 to get the nRF8001 to a known state.
+	  */
+	  lib_aci_radio_reset();
+  
+	  while (1)
+	  {
+		/*Wait for the command response of the radio reset command.
+		as the nRF8001 will be in either SETUP or STANDBY after the ACI Reset Radio is processed
+		*/
+
+			
+		if (true == lib_aci_event_get(aci_stat, aci_data))
+		{
+		  aci_evt_t * aci_evt;      
+		  aci_evt = &(aci_data->evt);
+	  
+		  if (ACI_EVT_CMD_RSP == aci_evt->evt_opcode)
+		  {
+				if (ACI_STATUS_ERROR_DEVICE_STATE_INVALID == aci_evt->params.cmd_rsp.cmd_status) //in SETUP
+				{
+					//Inject a Device Started Event Setup to the ACI Event Queue
+					msg_to_send.buffer[0] = 4;    //Length
+					msg_to_send.buffer[1] = 0x81; //Device Started Event
+					msg_to_send.buffer[2] = 0x02; //Setup
+					msg_to_send.buffer[3] = 0;    //Hardware Error -> None
+					msg_to_send.buffer[4] = 2;    //Data Credit Available
+					aci_queue_enqueue(&aci_rx_q, &msg_to_send);
+				}
+				else if (ACI_STATUS_SUCCESS == aci_evt->params.cmd_rsp.cmd_status) //We are now in STANDBY
+				{
+					//Inject a Device Started Event Standby to the ACI Event Queue
+					msg_to_send.buffer[0] = 4;    //Length
+					msg_to_send.buffer[1] = 0x81; //Device Started Event
+					msg_to_send.buffer[2] = 0x03; //Standby
+					msg_to_send.buffer[3] = 0;    //Hardware Error -> None
+					msg_to_send.buffer[4] = 2;    //Data Credit Available
+					aci_queue_enqueue(&aci_rx_q, &msg_to_send);
+				}
+				else if (ACI_STATUS_ERROR_CMD_UNKNOWN == aci_evt->params.cmd_rsp.cmd_status) //We are now in TEST
+				{
+					//Inject a Device Started Event Test to the ACI Event Queue
+					msg_to_send.buffer[0] = 4;    //Length
+					msg_to_send.buffer[1] = 0x81; //Device Started Event
+					msg_to_send.buffer[2] = 0x01; //Test
+					msg_to_send.buffer[3] = 0;    //Hardware Error -> None
+					msg_to_send.buffer[4] = 0;    //Data Credit Available
+					aci_queue_enqueue(&aci_rx_q, &msg_to_send);
+				}
+				
+				//Break out of the while loop
+				break;
+		  }
+		  else
+		  {			
+			//Serial.println(F("Discard any other ACI Events"));
+		  }
+	  
+		}
+	  }		
+	}
+}
+
+
+void lib_aci_init(aci_state_t *aci_stat, bool debug)
+{
+  uint8_t i;
+
+  for (i = 0; i < PIPES_ARRAY_SIZE; i++)
+  {
+    aci_stat->pipes_open_bitmap[i]          = 0;
+    aci_stat->pipes_closed_bitmap[i]        = 0;
+    aci_cmd_params_open_adv_pipe.pipes[i]   = 0;
+  }
+  
+
+
+
+  is_request_operation_pending     = false;
+  is_indicate_operation_pending    = false; 
+  is_open_remote_pipe_pending      = false;
+  is_close_remote_pipe_pending     = false;
+
+
+
+  
+  
+  request_operation_pipe           = 0;
+  indicate_operation_pipe          = 0;
+  
+  
+  
+  p_services_pipe_type_map = aci_stat->aci_setup_info.services_pipe_type_mapping;
+  
+  p_setup_msgs             = aci_stat->aci_setup_info.setup_msgs;
+  
+  
+  hal_aci_tl_init(&aci_stat->aci_pins, debug);
+  
+  lib_aci_board_init(aci_stat);
+}
+
+
+uint8_t lib_aci_get_nb_available_credits(aci_state_t *aci_stat)
+{
+  return aci_stat->data_credit_available;
+}
+
+uint16_t lib_aci_get_cx_interval_ms(aci_state_t *aci_stat)
+{
+  uint32_t cx_rf_interval_ms_32bits;
+  uint16_t cx_rf_interval_ms;
+  
+  cx_rf_interval_ms_32bits  = aci_stat->connection_interval;
+  cx_rf_interval_ms_32bits *= 125;                      // the connection interval is given in multiples of 0.125 milliseconds
+  cx_rf_interval_ms         = cx_rf_interval_ms_32bits / 100;
+  
+  return cx_rf_interval_ms;
+}
+
+
+uint16_t lib_aci_get_cx_interval(aci_state_t *aci_stat)
+{
+  return aci_stat->connection_interval;
+}
+
+
+uint16_t lib_aci_get_slave_latency(aci_state_t *aci_stat)
+{
+  return aci_stat->slave_latency;
+}
+
+
+bool lib_aci_set_app_latency(uint16_t latency, aci_app_latency_mode_t latency_mode)
+{
+  aci_cmd_params_set_app_latency_t aci_set_app_latency;
+  
+  aci_set_app_latency.mode    = latency_mode;
+  aci_set_app_latency.latency = latency;  
+  acil_encode_cmd_set_app_latency(&(msg_to_send.buffer[0]), &aci_set_app_latency);
+  
+  return hal_aci_tl_send(&msg_to_send);
+}
+
+
+bool lib_aci_test(aci_test_mode_change_t enter_exit_test_mode)
+{
+  aci_cmd_params_test_t aci_cmd_params_test;
+  aci_cmd_params_test.test_mode_change = enter_exit_test_mode;
+  acil_encode_cmd_set_test_mode(&(msg_to_send.buffer[0]), &aci_cmd_params_test);
+  return hal_aci_tl_send(&msg_to_send);
+}
+
+
+bool lib_aci_sleep()
+{
+  acil_encode_cmd_sleep(&(msg_to_send.buffer[0]));
+  return hal_aci_tl_send(&msg_to_send);
+}
+
+
+bool lib_aci_radio_reset()
+{
+  acil_encode_baseband_reset(&(msg_to_send.buffer[0]));
+  return hal_aci_tl_send(&msg_to_send);
+}
+
+
+bool lib_aci_direct_connect()
+{
+  acil_encode_direct_connect(&(msg_to_send.buffer[0]));
+  return hal_aci_tl_send(&msg_to_send);
+}
+
+
+bool lib_aci_device_version()
+{
+  acil_encode_cmd_get_device_version(&(msg_to_send.buffer[0]));
+  return hal_aci_tl_send(&msg_to_send);
+}
+
+
+bool lib_aci_set_local_data(aci_state_t *aci_stat, uint8_t pipe, uint8_t *p_value, uint8_t size)
+{
+  aci_cmd_params_set_local_data_t aci_cmd_params_set_local_data;
+  
+  // if ((p_services_pipe_type_map[pipe-1].location != ACI_STORE_LOCAL)
+  //     ||
+  //     (size > ACI_PIPE_TX_DATA_MAX_LEN))
+  // {
+  //   return false;
+  // }
+
+  aci_cmd_params_set_local_data.tx_data.pipe_number = pipe;
+  memcpy(&(aci_cmd_params_set_local_data.tx_data.aci_data[0]), p_value, size);
+  acil_encode_cmd_set_local_data(&(msg_to_send.buffer[0]), &aci_cmd_params_set_local_data, size);
+  return hal_aci_tl_send(&msg_to_send);
+}
+
+bool lib_aci_connect(uint16_t run_timeout, uint16_t adv_interval)
+{
+  aci_cmd_params_connect_t aci_cmd_params_connect;
+  aci_cmd_params_connect.timeout      = run_timeout;
+  aci_cmd_params_connect.adv_interval = adv_interval;
+  acil_encode_cmd_connect(&(msg_to_send.buffer[0]), &aci_cmd_params_connect);
+  return hal_aci_tl_send(&msg_to_send);
+}
+
+
+bool lib_aci_disconnect(aci_state_t *aci_stat, aci_disconnect_reason_t reason)
+{
+  bool ret_val;
+  uint8_t i;
+  aci_cmd_params_disconnect_t aci_cmd_params_disconnect;
+  aci_cmd_params_disconnect.reason = reason;
+  acil_encode_cmd_disconnect(&(msg_to_send.buffer[0]), &aci_cmd_params_disconnect);
+  ret_val = hal_aci_tl_send(&msg_to_send);
+  // If we have actually sent the disconnect
+  if (ret_val)
+  {
+    // Update pipes immediately so that while the disconnect is happening,
+    // the application can't attempt sending another message
+    // If the application sends another message before we updated this
+    //    a ACI Pipe Error Event will be received from nRF8001
+    for (i=0; i < PIPES_ARRAY_SIZE; i++)
+    {
+      aci_stat->pipes_open_bitmap[i] = 0;
+      aci_stat->pipes_closed_bitmap[i] = 0;
+    }
+  }
+  return ret_val;
+}
+
+
+bool lib_aci_bond(uint16_t run_timeout, uint16_t adv_interval)
+{
+  aci_cmd_params_bond_t aci_cmd_params_bond;
+  aci_cmd_params_bond.timeout = run_timeout;
+  aci_cmd_params_bond.adv_interval = adv_interval;
+  acil_encode_cmd_bond(&(msg_to_send.buffer[0]), &aci_cmd_params_bond);
+  return hal_aci_tl_send(&msg_to_send);
+}
+
+
+bool lib_aci_wakeup()
+{
+  acil_encode_cmd_wakeup(&(msg_to_send.buffer[0]));
+  return hal_aci_tl_send(&msg_to_send);
+}
+
+
+bool lib_aci_set_tx_power(aci_device_output_power_t tx_power)
+{
+  aci_cmd_params_set_tx_power_t aci_cmd_params_set_tx_power;
+  aci_cmd_params_set_tx_power.device_power = tx_power;
+  acil_encode_cmd_set_radio_tx_power(&(msg_to_send.buffer[0]), &aci_cmd_params_set_tx_power);
+  return hal_aci_tl_send(&msg_to_send);
+}
+
+
+bool lib_aci_get_address()
+{
+  acil_encode_cmd_get_address(&(msg_to_send.buffer[0]));
+  return hal_aci_tl_send(&msg_to_send);
+}
+
+
+bool lib_aci_get_temperature()
+{
+  acil_encode_cmd_temparature(&(msg_to_send.buffer[0]));
+  return hal_aci_tl_send(&msg_to_send);
+}
+
+
+bool lib_aci_get_battery_level()
+{
+  acil_encode_cmd_battery_level(&(msg_to_send.buffer[0]));
+  return hal_aci_tl_send(&msg_to_send);
+}
+
+
+bool lib_aci_send_data(uint8_t pipe, uint8_t *p_value, uint8_t size)
+{
+  bool ret_val = false;
+  aci_cmd_params_send_data_t aci_cmd_params_send_data;
+
+  
+  // if(!((p_services_pipe_type_map[pipe-1].pipe_type == ACI_TX) ||
+  //     (p_services_pipe_type_map[pipe-1].pipe_type == ACI_TX_ACK)))
+  // {
+  //   return false;
+  // }
+
+  if (size > ACI_PIPE_TX_DATA_MAX_LEN)
+  {
+    return false;
+  }
+  {
+      aci_cmd_params_send_data.tx_data.pipe_number = pipe;
+      memcpy(&(aci_cmd_params_send_data.tx_data.aci_data[0]), p_value, size);
+      acil_encode_cmd_send_data(&(msg_to_send.buffer[0]), &aci_cmd_params_send_data, size);
+      
+      ret_val = hal_aci_tl_send(&msg_to_send);          
+  }
+  return ret_val;
+}
+
+
+bool lib_aci_request_data(aci_state_t *aci_stat, uint8_t pipe)
+{
+  bool ret_val = false;
+  aci_cmd_params_request_data_t aci_cmd_params_request_data;
+
+  if(!((p_services_pipe_type_map[pipe-1].location == ACI_STORE_REMOTE)&&(p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX_REQ)))
+  {
+    return false;
+  }
+
+
+  {
+
+    {
+
+
+
+      aci_cmd_params_request_data.pipe_number = pipe;
+      acil_encode_cmd_request_data(&(msg_to_send.buffer[0]), &aci_cmd_params_request_data);
+
+      ret_val = hal_aci_tl_send(&msg_to_send);
+    }
+  }
+  return ret_val;
+}
+
+
+bool lib_aci_change_timing(uint16_t minimun_cx_interval, uint16_t maximum_cx_interval, uint16_t slave_latency, uint16_t timeout)
+{
+  aci_cmd_params_change_timing_t aci_cmd_params_change_timing;
+  aci_cmd_params_change_timing.conn_params.min_conn_interval = minimun_cx_interval;
+  aci_cmd_params_change_timing.conn_params.max_conn_interval = maximum_cx_interval;
+  aci_cmd_params_change_timing.conn_params.slave_latency     = slave_latency;    
+  aci_cmd_params_change_timing.conn_params.timeout_mult      = timeout;     
+  acil_encode_cmd_change_timing_req(&(msg_to_send.buffer[0]), &aci_cmd_params_change_timing);
+  return hal_aci_tl_send(&msg_to_send);
+}
+
+
+bool lib_aci_change_timing_GAP_PPCP()
+{
+  acil_encode_cmd_change_timing_req_GAP_PPCP(&(msg_to_send.buffer[0]));
+  return hal_aci_tl_send(&msg_to_send);
+}
+
+
+bool lib_aci_open_remote_pipe(aci_state_t *aci_stat, uint8_t pipe)
+{
+  bool ret_val = false;
+  aci_cmd_params_open_remote_pipe_t aci_cmd_params_open_remote_pipe;
+
+  if(!((p_services_pipe_type_map[pipe-1].location == ACI_STORE_REMOTE)&&
+                ((p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX)||
+                (p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX_ACK_AUTO)||
+                (p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX_ACK))))
+  {
+    return false;
+  }
+
+  
+  {
+
+    is_request_operation_pending = true;
+    is_open_remote_pipe_pending = true;
+    request_operation_pipe = pipe;
+    aci_cmd_params_open_remote_pipe.pipe_number = pipe;
+    acil_encode_cmd_open_remote_pipe(&(msg_to_send.buffer[0]), &aci_cmd_params_open_remote_pipe);
+    ret_val = hal_aci_tl_send(&msg_to_send);
+  }
+  return ret_val;
+}
+
+
+bool lib_aci_close_remote_pipe(aci_state_t *aci_stat, uint8_t pipe)
+{
+  bool ret_val = false;
+  aci_cmd_params_close_remote_pipe_t aci_cmd_params_close_remote_pipe;
+
+  if(!((p_services_pipe_type_map[pipe-1].location == ACI_STORE_REMOTE)&&
+        ((p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX)||
+         (p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX_ACK_AUTO)||
+         (p_services_pipe_type_map[pipe-1].pipe_type == ACI_RX_ACK))))
+  {
+    return false;
+  }  
+
+
+  {
+
+    is_request_operation_pending = true;
+    is_close_remote_pipe_pending = true;
+    request_operation_pipe = pipe;
+    aci_cmd_params_close_remote_pipe.pipe_number = pipe;
+    acil_encode_cmd_close_remote_pipe(&(msg_to_send.buffer[0]), &aci_cmd_params_close_remote_pipe);
+    ret_val = hal_aci_tl_send(&msg_to_send);
+  }
+  return ret_val;
+}
+
+
+bool lib_aci_set_key(aci_key_type_t key_rsp_type, uint8_t *key, uint8_t len)
+{
+  aci_cmd_params_set_key_t aci_cmd_params_set_key;
+  aci_cmd_params_set_key.key_type = key_rsp_type;
+  memcpy((uint8_t*)&(aci_cmd_params_set_key.key), key, len);
+  acil_encode_cmd_set_key(&(msg_to_send.buffer[0]), &aci_cmd_params_set_key);
+  return hal_aci_tl_send(&msg_to_send);
+}
+
+
+bool lib_aci_echo_msg(uint8_t msg_size, uint8_t *p_msg_data)
+{
+  aci_cmd_params_echo_t aci_cmd_params_echo;
+  if(msg_size > (ACI_ECHO_DATA_MAX_LEN))
+  {
+    return false;
+  }
+
+  if (msg_size > (ACI_ECHO_DATA_MAX_LEN))
+  {
+    msg_size = ACI_ECHO_DATA_MAX_LEN;
+  }
+
+  memcpy(&(aci_cmd_params_echo.echo_data[0]), p_msg_data, msg_size);
+  acil_encode_cmd_echo_msg(&(msg_to_send.buffer[0]), &aci_cmd_params_echo, msg_size);
+
+  return hal_aci_tl_send(&msg_to_send);
+}
+
+
+bool lib_aci_bond_request()
+{
+  acil_encode_cmd_bond_security_request(&(msg_to_send.buffer[0]));
+  return hal_aci_tl_send(&msg_to_send);
+}
+
+bool lib_aci_event_peek(hal_aci_evt_t *p_aci_evt_data)
+{
+  return hal_aci_tl_event_peek((hal_aci_data_t *)p_aci_evt_data);
+}
+
+bool lib_aci_event_get(aci_state_t *aci_stat, hal_aci_evt_t *p_aci_evt_data)
+{
+  bool status = false;
+  
+  status = hal_aci_tl_event_get((hal_aci_data_t *)p_aci_evt_data);
+  
+  /**
+  Update the state of the ACI with the 
+  ACI Events -> Pipe Status, Disconnected, Connected, Bond Status, Pipe Error
+  */
+  if (true == status)
+  {
+    aci_evt_t * aci_evt;
+    
+    aci_evt = &p_aci_evt_data->evt;  
+    
+    switch(aci_evt->evt_opcode)
+    {
+        case ACI_EVT_PIPE_STATUS:
+            {
+                uint8_t i=0;
+                
+                for (i=0; i < PIPES_ARRAY_SIZE; i++)
+                {
+                  aci_stat->pipes_open_bitmap[i]   = aci_evt->params.pipe_status.pipes_open_bitmap[i];
+                  aci_stat->pipes_closed_bitmap[i] = aci_evt->params.pipe_status.pipes_closed_bitmap[i];
+                }
+            }
+            break;
+        
+        case ACI_EVT_DISCONNECTED:
+            {
+                uint8_t i=0;
+                
+                for (i=0; i < PIPES_ARRAY_SIZE; i++)
+                {
+                  aci_stat->pipes_open_bitmap[i] = 0;
+                  aci_stat->pipes_closed_bitmap[i] = 0;
+                }
+                aci_stat->confirmation_pending = false;
+                aci_stat->data_credit_available = aci_stat->data_credit_total;
+                
+            }
+            break;
+            
+        case ACI_EVT_TIMING:            
+                aci_stat->connection_interval = aci_evt->params.timing.conn_rf_interval;
+                aci_stat->slave_latency       = aci_evt->params.timing.conn_slave_rf_latency;
+                aci_stat->supervision_timeout = aci_evt->params.timing.conn_rf_timeout;
+            break;
+
+        default:
+            /* Need default case to avoid compiler warnings about missing enum
+             * values on some platforms.
+             */
+            break;
+
+			
+			
+    }
+  }
+  return status;
+}
+
+
+bool lib_aci_send_ack(aci_state_t *aci_stat, const uint8_t pipe)
+{
+  bool ret_val = false;
+  {
+    acil_encode_cmd_send_data_ack(&(msg_to_send.buffer[0]), pipe);
+    
+    ret_val = hal_aci_tl_send(&msg_to_send);
+  }
+  return ret_val;
+}
+
+
+bool lib_aci_send_nack(aci_state_t *aci_stat, const uint8_t pipe, const uint8_t error_code)
+{
+  bool ret_val = false;
+  
+  {
+    
+    acil_encode_cmd_send_data_nack(&(msg_to_send.buffer[0]), pipe, error_code);
+    ret_val = hal_aci_tl_send(&msg_to_send);
+  }
+  return ret_val;
+}
+
+
+bool lib_aci_broadcast(const uint16_t timeout, const uint16_t adv_interval)
+{
+  aci_cmd_params_broadcast_t aci_cmd_params_broadcast;
+  if (timeout > 16383)
+  {
+    return false;
+  }  
+  
+  // The adv_interval should be between 160 and 16384 (which translates to the advertisement 
+  // interval values 100 ms and 10.24 s.
+  if ((160 > adv_interval) || (adv_interval > 16384))
+  {
+    return false;
+  }
+
+  aci_cmd_params_broadcast.timeout = timeout;
+  aci_cmd_params_broadcast.adv_interval = adv_interval;
+  acil_encode_cmd_broadcast(&(msg_to_send.buffer[0]), &aci_cmd_params_broadcast);
+  return hal_aci_tl_send(&msg_to_send);
+}
+
+
+bool lib_aci_open_adv_pipes(const uint8_t * const adv_service_data_pipes)
+{
+  uint8_t i;
+    
+  for (i = 0; i < PIPES_ARRAY_SIZE; i++)
+  {
+    aci_cmd_params_open_adv_pipe.pipes[i] = adv_service_data_pipes[i];
+  }
+
+  acil_encode_cmd_open_adv_pipes(&(msg_to_send.buffer[0]), &aci_cmd_params_open_adv_pipe);
+  return hal_aci_tl_send(&msg_to_send);
+}
+
+bool lib_aci_open_adv_pipe(const uint8_t pipe)
+{
+  uint8_t byte_idx = pipe / 8;
+  
+  aci_cmd_params_open_adv_pipe.pipes[byte_idx] |= (0x01 << (pipe % 8));
+  acil_encode_cmd_open_adv_pipes(&(msg_to_send.buffer[0]), &aci_cmd_params_open_adv_pipe);
+  return hal_aci_tl_send(&msg_to_send);
+}
+
+
+bool lib_aci_read_dynamic_data()
+{
+  acil_encode_cmd_read_dynamic_data(&(msg_to_send.buffer[0]));
+  return hal_aci_tl_send(&msg_to_send);
+}
+
+
+bool lib_aci_write_dynamic_data(uint8_t sequence_number, uint8_t* dynamic_data, uint8_t length)
+{
+  acil_encode_cmd_write_dynamic_data(&(msg_to_send.buffer[0]), sequence_number, dynamic_data, length);
+  return hal_aci_tl_send(&msg_to_send);
+}
+
+bool lib_aci_dtm_command(uint8_t dtm_command_msbyte, uint8_t dtm_command_lsbyte)
+{
+  aci_cmd_params_dtm_cmd_t aci_cmd_params_dtm_cmd;
+  aci_cmd_params_dtm_cmd.cmd_msb = dtm_command_msbyte;
+  aci_cmd_params_dtm_cmd.cmd_lsb = dtm_command_lsbyte;
+  acil_encode_cmd_dtm_cmd(&(msg_to_send.buffer[0]), &aci_cmd_params_dtm_cmd);
+  return hal_aci_tl_send(&msg_to_send);
+}
+
+void lib_aci_flush(void)
+{
+  hal_aci_tl_q_flush();
+}
+
+void lib_aci_debug_print(bool enable)
+{
+  hal_aci_tl_debug_print(enable);
+
+}
+
+void lib_aci_pin_reset(void)
+{
+    hal_aci_tl_pin_reset();
+}
+
+bool lib_aci_event_queue_empty(void)
+{
+  return hal_aci_tl_rx_q_empty();
+}
+
+bool lib_aci_event_queue_full(void)
+{
+  return hal_aci_tl_rx_q_full();
+}
+
+bool lib_aci_command_queue_empty(void)
+{
+  return hal_aci_tl_tx_q_empty();
+}
+
+bool lib_aci_command_queue_full(void)
+{
+  return hal_aci_tl_tx_q_full();
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/lib_aci.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/lib_aci.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/ble_shield2.1/utility/lib_aci.h	(revision 453)
@@ -0,0 +1,557 @@
+/* Copyright (c) 2014, Nordic Semiconductor ASA
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef LIB_ACI_H__
+#define LIB_ACI_H__
+
+/** @file
+* @brief ACI library
+*/
+
+/** @addtogroup lib_aci
+@{
+@brief Library for the logical part of the Application Controller Interface (ACI)
+*/
+
+#include "hal_platform.h"
+#include "hal_aci_tl.h"
+#include "aci_queue.h"
+#include "aci.h"
+#include "aci_cmds.h"
+#include "aci_evts.h"
+
+
+#define EVT_CMD_RESPONSE_MIN_LENGTH              3
+
+#define PIPES_ARRAY_SIZE                ((ACI_DEVICE_MAX_PIPES + 7)/8)
+
+/* Same size as a hal_aci_data_t */
+typedef struct {
+  uint8_t   debug_byte;
+  aci_evt_t evt;
+} _aci_packed_ hal_aci_evt_t;
+
+ACI_ASSERT_SIZE(hal_aci_evt_t, 34);
+
+typedef struct
+{
+  uint8_t  location; /**< enum aci_pipe_store_t */
+  aci_pipe_type_t   pipe_type;
+} services_pipe_type_mapping_t;
+
+typedef struct aci_setup_info_t
+{
+  services_pipe_type_mapping_t *services_pipe_type_mapping;
+  uint8_t                       number_of_pipes;
+  hal_aci_data_t               *setup_msgs;
+  uint8_t                       num_setup_msgs;
+} aci_setup_info_t;
+
+
+
+// aci_struct that will contain 
+// total initial credits
+// current credit
+// current state of the aci (setup/standby/active/sleep)
+// open remote pipe pending
+// close remote pipe pending
+// Current pipe available bitmap
+// Current pipe closed bitmap
+// Current connection interval, slave latency and link supervision timeout
+// Current State of the the GATT client (Service Discovery status)
+// Relationship of bond to peer address
+typedef struct aci_state_t
+{
+  aci_pins_t                    aci_pins;                               /* Pins on the MCU used to connect to the nRF8001 */ 
+  aci_setup_info_t              aci_setup_info;                         /* Data structures that are created from nRFgo Studio */
+  uint8_t                       bonded;                                 /* ( aci_bond_status_code_t ) Is the nRF8001 bonded to a peer device */
+  uint8_t                       data_credit_total;                      /* Total data credit available for the specific version of the nRF8001, total equals available when a link is established */
+  aci_device_operation_mode_t   device_state;                           /* Operating mode of the nRF8001 */
+  
+  /* */
+  
+  /* Start : Variables that are valid only when in a connection */
+  uint8_t                       data_credit_available;                  /* Available data credits at a specific point of time, ACI_EVT_DATA_CREDIT updates the available credits */
+  
+  uint16_t                      connection_interval;                    /* Multiply by 1.25 to get the connection interval in milliseconds*/
+  uint16_t                      slave_latency;                          /* Number of consecutive connection intervals that the nRF8001 is not required to transmit. Use this to save power */
+  uint16_t                      supervision_timeout;                    /* Multiply by 10 to get the supervision timeout in milliseconds */
+  
+  uint8_t                       pipes_open_bitmap[PIPES_ARRAY_SIZE];    /* Bitmap -> pipes are open and can be used for sending data over the air */
+  uint8_t                       pipes_closed_bitmap[PIPES_ARRAY_SIZE];  /* Bitmap -> pipes are closed and cannot be used for sending data over the air */
+  bool                          confirmation_pending;                   /* Attribute protocol Handle Value confirmation is pending for a Handle Value Indication
+                                                                        (ACK is pending for a TX_ACK pipe) on local GATT Server*/
+  /* End : Variables that are valid only when in a connection */                                                                        
+  
+} aci_state_t;
+
+
+
+#define DISCONNECT_REASON_CX_TIMEOUT                 0x08
+#define DISCONNECT_REASON_CX_CLOSED_BY_PEER_DEVICE   0x13
+#define DISCONNECT_REASON_POWER_LOSS                 0x14
+#define DISCONNECT_REASON_CX_CLOSED_BY_LOCAL_DEVICE  0x16
+#define DISCONNECT_REASON_ADVERTISER_TIMEOUT         0x50
+
+
+/** @name Functions for library management */
+//@{
+
+/** @brief Function to enable printing of all ACI commands sent and ACI events received
+ *  @details This function shall be used to enable or disable the debug printing.
+              Debug printing is disabled by default.
+ */
+void lib_aci_debug_print(bool enable);
+
+/** @brief Function to pin reset the nRF8001
+ *  @details Pin resets the nRF8001 also handles differences between development boards
+ */
+void lib_aci_pin_reset(void);
+
+/** @brief Initialization function.
+ *  @details This function shall be used to initialize/reset ACI Library and also Resets the 
+ *           nRF8001 by togging the reset pin of the nRF8001. This function will reset 
+ *           all the variables locally used by ACI library to their respective default values.
+ *  @param bool True if the data was successfully queued for sending, 
+ *  false if there is no more space to store messages to send.
+ */
+void lib_aci_init(aci_state_t *aci_stat, bool debug);
+
+
+/** @brief Gets the number of currently available ACI credits.
+ *  @return Number of ACI credits.
+ */
+uint8_t lib_aci_get_nb_available_credits(aci_state_t *aci_stat);
+
+/** @brief Gets the connection interval in milliseconds.
+ *  @return Connection interval in milliseconds.
+ */
+uint16_t lib_aci_get_cx_interval_ms(aci_state_t *aci_stat);
+
+/** @brief Gets the connection interval in multiple of 1.25&nbsp;ms.
+ *  @return Connection interval in multiple of 1.25&nbsp;ms.
+ */
+uint16_t lib_aci_get_cx_interval(aci_state_t *aci_stat);
+
+/** @brief Gets the current slave latency.
+ *  @return Current slave latency.
+ */
+uint16_t lib_aci_get_slave_latency(aci_state_t *aci_stat);
+
+/** @brief Checks if a given pipe is available.
+ *  @param pipe Pipe to check.
+ *  @return True if the pipe is available, otherwise false.
+ */
+bool lib_aci_is_pipe_available(aci_state_t *aci_stat, uint8_t pipe);
+
+/** @brief Checks if a given pipe is closed.
+ *  @param pipe Pipe to check.
+ *  @return True if the pipe is closed, otherwise false.
+ */
+bool lib_aci_is_pipe_closed(aci_state_t *aci_stat, uint8_t pipe);
+
+/** @brief Checks if the discovery operation is finished.
+ *  @return True if the discovery is finished.
+ */
+bool lib_aci_is_discovery_finished(aci_state_t *aci_stat);
+
+
+
+//@}
+
+/** @name ACI Commands available in all modes */
+//@{
+
+/** @brief Sets the radio in sleep mode.
+ *  @details The function sends a @c sleep command to the radio.
+ *  If the radio is advertising or connected, it sends back an error, then use lib_aci_radio_reset 
+ *  if advertising or disconnect if in a connection.
+ *  @return True if the transaction is successfully initiated.
+ */
+bool lib_aci_sleep(void);
+
+/** @brief Resets the radio.
+ *  @details The function sends a @c BasebandReset command to the radio.  
+ *  @return True if the transaction is successfully initiated.
+ */
+bool lib_aci_radio_reset(void);
+
+/** @brief Radio starts directed advertising to bonded device.
+ *  @details The function sends a @c DirectedConnect command to the radio.  
+ *  @return True if the transaction is successfully initiated.
+ */
+bool lib_aci_direct_connect(void);
+
+/** @brief Gets the radio's version.
+ *  @details This function sends a @c GetDeviceVersion command.
+ *  @return True if the transaction is successfully initiated.
+ */
+bool lib_aci_device_version(void);
+
+/** @brief Gets the device address.
+ *  @details This function sends a @c GetDeviceAddress command.
+ *  @return True if the transaction is successfully initiated.
+ */
+bool lib_aci_get_address(void);
+
+/** @brief Gets the temperature.
+ *  @details This function sends a @c GetTemperature command. lib_aci
+ *  calls the @ref lib_aci_transaction_finished_hook() function when the temperature is received.
+ *  @return True if the transaction is successfully initiated.
+ */
+bool lib_aci_get_temperature(void);
+
+/** @brief Gets the battery level.
+ *  @details This function sends a @c GetBatteryLevel command. 
+ *  @return True if the transaction is successfully initiated.
+ */
+bool lib_aci_get_battery_level(void);
+
+//@}
+
+/** @name ACI commands available in Sleep mode */
+//@{
+
+/** @brief Wakes up the radio.
+ *  @details This function sends a @c Wakeup command to wake up the radio from
+ *  sleep mode. When woken up the radio sends a @c DeviceStartedEvent and
+ *  a @c CommandResponseEvent.
+ *  @return True if the transaction is successfully initiated.
+ */
+bool lib_aci_wakeup(void);
+
+//@}
+
+/** @name ACI commands available in Active mode */
+//@{
+
+/** @brief Sets the radio in test mode.
+ *  @details This function sends a @c Test command to the radio. There are two
+ *  Test modes available:
+ *  - UART: DTM commands are received over UART.
+ *  - ACI: DTM commands are received over ACI.
+ *  The same command is used to exit the test mode When receiving
+ *  a @c DeviceStartedEvent the radio has entered the new mode.
+ *  @param enter_exit_test_mode Enter a Test mode, or exit Test mode.
+ *  @return True if the transaction is successfully initiated.
+ */
+bool lib_aci_test(aci_test_mode_change_t enter_exit_test_mode);
+
+/** @brief Sets the radio's TX power.
+ *  @details This function sends a @c SetTxPower command.
+ *  @param tx_power TX power to be used by the radio.
+ *  @return True if the transaction is successfully initiated.
+ */
+bool lib_aci_set_tx_power(aci_device_output_power_t tx_power);
+
+/** @brief Tries to connect to a peer device.
+ *  @details This function sends a @c Connect command to the radio.
+ *  @param run_timeout Maximum advertising time in seconds (0 means infinite).
+ *  @param adv_interval Advertising interval (in multiple of 0.625&nbsp;ms).
+ *  @return True if the transaction is successfully initiated.
+ */
+bool lib_aci_connect(uint16_t run_timeout, uint16_t adv_interval);
+
+/** @brief Tries to bond with a peer device.
+ *  @details This function sends a @c Bond command to the radio.
+ *  @param run_timeout Maximum advertising time in seconds (0 means infinite).
+ *  @param adv_interval Advertising interval (in multiple of 0.625&nbsp;ms).
+ *  @return True if the transaction is successfully initiated.
+ */
+bool lib_aci_bond(uint16_t run_timeout, uint16_t adv_interval);
+
+/** @brief Disconnects from peer device.
+ *  @details This function sends a @c Disconnect command to the radio.
+ *  @param reason Reason for disconnecting.
+ *  @return True if the transaction is successfully initiated.
+ */
+bool lib_aci_disconnect(aci_state_t *aci_stat, aci_disconnect_reason_t reason);
+
+/**@brief Sets Local Data.
+ *  @details
+ *  This command updates the value of the characteristic value or the characteristic descriptor stored locally on the device.
+ *  Can be called for all types of pipes as long as the data is stored locally.
+ *  @param ACI state structure
+ *  @param pipe Pipe number on which the data should be set.
+ *  @param value Pointer to the data to set.
+ *  @param size Size of the data to set.
+ *  @return True if the transaction is successfully initiated.
+*/
+bool lib_aci_set_local_data(aci_state_t *aci_stat, uint8_t pipe, uint8_t *value, uint8_t size);
+
+/** @brief Sends Broadcast message to the radio.
+ *  @details The Broadcast message starts advertisement procedure 
+ *  using the given interval with the intention of broadcasting data to a peer device.
+ *  @param timeout Time, in seconds, to advertise before exiting to standby mode (0 means infinite).
+ *  Valid values: 0 to 16383.
+ *  @param adv_interval Advertising interval (in multiple of 0.625&nbsp;ms).
+ *  Valid values: 160 to 16384 (which corresponds to an interval from 100 ms to 10.24 s).
+ *  @return True if the broadcast message is sent successfully to the radio. 
+*/
+bool lib_aci_broadcast(const uint16_t timeout, const uint16_t adv_interval);
+
+/** @name Open Advertising Pipes.  */
+
+/** @brief Sends a command to the radio to set the input pipe to be placed in Advertisement Service Data.
+ *  @details This function sends a command to the radio that places the pipe in 
+ *  advertisement service data.  To start advertising service data, call this function before
+ *  Connecting, Broadcasting or Bonding to peer. The data that should be sent in the advertisement packets 
+ *  must be set using the @c lib_aci_set_local_data function. This function can be called during 
+ *  advertising to enable/disable broadcast pipes.  
+ *  @param pipe The pipe that has to be placed in advertising service data.
+ *  @return True if the Open Adv Pipe message is sent successfully to the radio. 
+*/
+bool lib_aci_open_adv_pipe(const uint8_t pipe);
+
+
+/** @name Open Advertising Pipes  */
+
+/** @brief Sends a command to the radio to set the pipes to be placed in Advertisement Service Data.
+ *  @details This function will send a command to the radio that will set the pipes to be placed in 
+ *  advertisement Service Data.  To start advertising service data, this function should be called before
+ *  Connecting, Broadcasting or Bonding to peer. This function can be called during 
+ *  advertising to enable/disable broadcast pipes. Use this as an alternative to @ref lib_aci_open_adv_pipe 
+ *  to avoid multiple function calls for placing multiple pipes in the adv data.
+ *  @param adv_service_data_pipes Pipe bitmap, where '1' indicates that the corresponding 
+ *  Valid Values: 0000000000000000 to FEFFFFFFFFFFFF7F (See the ACI Pipe Status Evt bitmap in the nRF8001 datasheet
+ *  TX_BROADCAST pipe data is to be placed in Advertising Service Data fields
+ *  @return true if the Open Adv Pipe message was sent successfully to the radio. 
+*/
+bool lib_aci_open_adv_pipes(const uint8_t * const adv_service_data_pipes);
+
+
+//@}
+
+/** @name ACI commands available in Connected mode */
+//@{
+
+
+/** @brief Sets a given application latency.
+ *  @details This function sends a @c setApplicationLatency command. 
+ *  @return True if the transaction is successfully initiated.
+ */
+bool lib_aci_set_app_latency(uint16_t latency, aci_app_latency_mode_t latency_mode);
+
+/** @brief Opens a remote pipe.
+ *  @details This function sends an @c OpenRemotePipe command.
+ *  @param pipe Number of the pipe to open.
+ *  @return True if the transaction is successfully initiated.
+ */
+bool lib_aci_open_remote_pipe(aci_state_t *aci_stat, uint8_t pipe);
+
+/** @brief Closes a remote pipe.
+ *  @details This function sends an @c CloseRemotePipe command.
+ *  @param pipe Pipe number to close.
+ *  @return True if the transaction is successfully initiated.
+ */
+bool lib_aci_close_remote_pipe(aci_state_t *aci_stat, uint8_t pipe);
+
+/** @brief Sends data on a given pipe.
+ *  @details This function sends a @c SendData command with application data to
+ *  the radio. This function memorizes credit use, and checks that
+ *  enough credits are available.
+ *  @param pipe Pipe number on which the data should be sent.
+ *  @param value Pointer to the data to send.
+ *  @param size Size of the data to send.
+ *  @return True if the transaction is successfully initiated.
+ */
+bool lib_aci_send_data(uint8_t pipe, uint8_t *value, uint8_t size);
+
+/** @brief Requests data from a given pipe.
+ *  @details This function sends a @c RequestData command to the radio. This
+ *  function memorizes credit uses, and check that enough credits are available.
+ *  After this command, the radio sends back either a @c DataReceivedEvent
+ *  or a @c PipeErrorEvent.
+ *  @param pipe Pipe number on which the data is requested.
+ *  @return True if the transaction is successfully initiated.
+ */
+bool lib_aci_request_data(aci_state_t *aci_stat, uint8_t pipe);
+
+/** @brief Sends a L2CAP change connection parameters request.
+ *  @details This function sends a @c ChangeTiming command to the radio.  This command triggers a "L2CAP change connection parameters" request 
+ *  to the master. If the master rejects or accepts but doesn't change the connection parameters within
+ *  30 seconds, a timing event with the unchanged connection parameters is sent by the radio.
+ *  If the request is accepted and the master changes connection parameters, a timing event with
+ *  the new connection parameters is sent by the radio.
+ *  If the master doesn't reply to the request within 60 seconds, the radio disconnects.
+ *  @param minimun_cx_interval Minimum connection interval requested, in multiple of 1.25&nbsp;ms.
+ *  @param maximum_cx_interval Maximum connection interval requested, in multiple of 1.25&nbsp;ms.
+ *  @param slave_latency requested slave latency.
+ *  @param timeout requested slave timeout, in multiple of 10&nbsp;ms.
+ *  @return True if the transaction is successfully initiated.
+ */
+bool lib_aci_change_timing(uint16_t minimun_cx_interval, uint16_t maximum_cx_interval, uint16_t slave_latency, uint16_t timeout);
+
+/** @brief Sends a L2CAP change connection parameters request with the connection predefined preffered connection parameters.
+ *  @details This function sends a @c ChangeTiming command to the radio. This command triggers a "L2CAP change connection parameters" request 
+ *  to the master. If the master rejects or accepts but doesn't change the connection parameters within
+ *  30 seconds, a timing event with the unchanged connection parameters is sent by the radio.
+ *  If the request is accepted and the master changes connection parameters, a timing event with
+ *  the new connection parameters is sent by the radio.
+ *  If the master doesn't reply to the request within 60 seconds, the radio disconnects.
+ *  The timing parameters used are the Timing parameters in the GAP settings in the nRFgo Studio.
+ *  The Timing parameters as stored as the GAP Preferred Peripheral Connection Parameters.
+ *  @return True if the transaction is successfully initiated.
+ */
+bool lib_aci_change_timing_GAP_PPCP(void);
+
+/** @brief Sends acknowledgement message to peer.
+ *  @details This function sends @c SendDataAck command to radio. The radio is expected 
+ *  to send either Handle Value Confirmation or Write response depending
+ *  on whether the data is stored remotely or locally.
+ *  @param pipe Pipe number for which the acknowledgement is to be sent.
+ *  @return True if the ack was sent successfully. False otherwise.
+*/
+bool lib_aci_send_ack(aci_state_t *aci_stat, const uint8_t pipe);
+
+/** @brief Sends negative acknowledgement message to peer.
+ *  @details This function sends @c SendDataNack command to radio. The radio is expected 
+ *  to send Error Response to the peer.
+ *  @param pipe Pipe number for which the nack is to be sent.
+ *  @param error_code Error code to be sent in the NACk.
+ *  @return True if the nack was sent successfully. False otherwise.
+*/
+bool lib_aci_send_nack(aci_state_t *aci_stat, const uint8_t pipe, const uint8_t error_code);
+
+/** @brief Sends ReadDynamicData command to the host. 
+ *  @details This function sends @c ReadDynamicData command to host. The host is expected 
+ *  to send @c CommandResponse back with the dynamic data. The application is expected to 
+ *  call this function in a loop until all the dynamic data is read out from the host. 
+ *  As long as there is dynamic data to be read from the host, the command response
+ *  for this message has its status field set to ACI_STATUS_TRANSACTION_CONTINUE (0x01).
+ *  The application may chose to store this read out data in a non-volatile memory location
+ *  and later chose to write it back using the function lib_aci_write_dynamic_data.
+ *  @return True if the command was sent successfully through the ACI. False otherwise.
+*/
+bool lib_aci_read_dynamic_data(void);
+
+/** @brief Sends WriteDynamicData command to the host.
+ *  @details This function sends @c WriteDynamicData command to host. The host is expected
+ *  to send @c CommandResponse with the status of this operation. As long as the status field 
+ *  in the @c CommandResponse is ACI_STATUS_TRANSACTION_CONTINUE (0x01), the hosts expects
+ *  more dynamic data to be written. This function should ideally be called in a cycle, 
+ *  until all the stored dynamic data is sent to the host. This function should be 
+ *  called with the dynamic data obtained from the response to a @c ReadDynamicData 
+ *  (see @c lib_aci_read_dynamic_data) command.
+ *  @param sequence_number Sequence number of the dynamic data to be sent.
+ *  @param dynamic_data Pointer to the dynamic data.
+ *  @param length Length of the dynamic data.
+ *  @return True if the command was sent successfully through the ACI. False otherwise.
+*/
+bool lib_aci_write_dynamic_data(uint8_t sequence_number, uint8_t* dynamic_data, uint8_t length);
+//@}
+
+/** @name ACI commands available while connected in Bond mode */
+//@{
+
+/** @brief Sends a SMP Security Request.
+ *  @details This function send a @c BondRequest command to the radio.
+ *  This command triggers a SMP Security Request to the master. If the
+ *  master rejects with a pairing failed or if the bond timer expires the connection is closed. 
+ *  @return True if the transaction is successfully initiated.
+ */
+bool lib_aci_bond_request(void);
+
+/** @brief Set the key requested by the 8001. 
+ *  @details This function sends an @c SetKey command to the radio. 
+ *  @param key_rsp_type Type of key.
+ *  @param key Pointer to the key to set.
+ *  @param len Length of the key.
+ *  @return True if the transaction is successfully initiated.
+*/
+bool lib_aci_set_key(aci_key_type_t key_rsp_type, uint8_t *key, uint8_t len);
+
+//@}
+
+
+
+/** @name ACI commands available in Test mode */
+//@{
+
+/** @brief Sends an echo message
+ *  @details This function sends an @c Echo command to the radio. lib_aci
+ *  places the Echp ACI command in the ACI command queue
+ *  @param message_size Length of the data to send.
+ *  @param message_data Pointer to the data to send.
+ *  @return True if the transaction is successfully initiated.
+*/
+bool lib_aci_echo_msg(uint8_t message_size, uint8_t *message_data);
+
+/** @brief Sends an DTM command
+ *  @details This function sends an @c DTM command to the radio. 
+ *  @param dtm_command_msbyte Most significant byte of the DTM command.
+ *  @param dtm_command_lsbyte Least significant byte of the DTM command.
+ *  @return True if the transaction is successfully initiated.
+*/
+bool lib_aci_dtm_command(uint8_t dtm_command_msbyte, uint8_t dtm_command_lsbyte);
+
+/** @brief Gets an ACI event from the ACI Event Queue
+ *  @details This function gets an ACI event from the ACI event queue. 
+ *  The queue is updated by the SPI driver for the ACI running in the interrupt context
+ *  @param aci_stat pointer to the state of the ACI.
+ *  @param p_aci_data pointer to the ACI Event. The ACI Event received will be copied into this pointer.
+ *  @return True if an ACI Event was copied to the pointer.
+*/
+bool lib_aci_event_get(aci_state_t *aci_stat, hal_aci_evt_t * aci_evt);
+
+/** @brief Peeks an ACI event from the ACI Event Queue
+ * @details This function peeks at the top event in the ACI event queue.
+ * In polling mode, this function will query the nRF8001 for pending events, but unlike
+ * lib_aci_event_get() it will not dequeue the event from the local queue, but will instead
+ * only peek at it.
+ * @return True if an ACI Event was copied to the pointer.
+*/
+bool lib_aci_event_peek(hal_aci_evt_t *p_aci_evt_data);
+
+/** @brief Flushes the events in the ACI command queues and ACI Event queue
+ *
+*/
+void lib_aci_flush(void);
+
+/** @brief Return full status of the Event queue
+ *  @details
+ *
+ */
+ bool lib_aci_event_queue_full(void);
+ 
+ /** @brief Return empty status of the Event queue
+ *  @details
+ *
+ */
+ bool lib_aci_event_queue_empty(void);
+
+/** @brief Return full status of Command queue
+ *  @details
+ *
+ */
+ bool lib_aci_command_queue_full(void);
+ 
+ /** @brief Return empty status of Command queue
+ *  @details
+ *
+ */
+ bool lib_aci_command_queue_empty(void);
+
+//@}
+
+/** @} */
+
+#endif /* LIB_ACI_H__ */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/flash_file/Makefile.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/flash_file/Makefile.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/flash_file/Makefile.config	(revision 453)
@@ -0,0 +1,55 @@
+#
+#   TOPPERS/ASP/FMP Kernel
+#       Toyohashi Open Platform for Embedded Real-Time Systems/
+#       Advanced Standard Profile Kernel
+#
+#   Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                               Toyohashi Univ. of Technology, JAPAN
+#   Copyright (C) 2003-2008 by Ryosuke Takeuchi
+#                Platform Development Center RICOH COMPANY,LTD. JAPAN
+#   Copyright (C) 2015-2017 by TOPPERS PROJECT Educational Working Group.
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+ 
+#
+#  Makefile のプロセッサ依存 (flash_file用)
+#
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/gdic/flash_file
+
+#
+#  SPI DRIVER(GDIC)に関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR):$(SRCDIR)/gdic/flash_file
+SYSSVC_COBJS := $(SYSSVC_COBJS) flash_file.o
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/flash_file/flash_file.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/flash_file/flash_file.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/flash_file/flash_file.c	(revision 453)
@@ -0,0 +1,344 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2018 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+ *  によって公表されている GNU General Public License の Version 2 に記
+ *  述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+ *  を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+ *  含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+ *  接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <target_syssvc.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#include "device.h"
+#include "qspi.h"
+#include <fcntl.h>
+#include "storagedevice.h"
+#include "flash_file.h"
+
+#define MIN(a, b) ((a) > (b) ? (b) : (a))
+
+#define QSPIBUFLENGTH    512
+
+static QSPI_Handle_t *hqspi;
+static int           num_files = 0;
+static int           dirreadcount;
+static fs_descrip_t  fs_descrip_table[MAX_DESCRIP];
+static uint32_t      qspibuff[(QSPIBUFLENGTH+8)/sizeof(uint32_t)];
+
+static void  *ffs_opendir(const char *pathname);
+static int   ffs_closedir(void *dir);
+static int   ffs_readdir(void *dir, void *pdirent);
+static int   ffs_open(int devno, const char *pathname, int flags);
+static int   ffs_close(int fd);
+static int   ffs_fstat(int fd, struct stat *buf);
+static off_t ffs_lseek(int fd, off_t offset, int whence, int *res);
+static long  ffs_read(int fd, void *buf, long count, int *res);
+
+static const StorageDeviceFileFunc_t romSDeviceFunc = {
+	ffs_opendir,
+	ffs_closedir,
+	ffs_readdir,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	ffs_open,
+	ffs_close,
+	ffs_fstat,
+	ffs_lseek,
+	ffs_read,
+	0,
+	0
+};
+
+
+/*
+ *  FLASH-ROMファイル関数郡の初期化
+ */
+ER
+flash_file_init(void *h)
+{
+	StorageDevice_t *psdev;
+	int result;
+
+	num_files = 0;
+	memset(fs_descrip_table, 0, sizeof(fs_descrip_table));
+	result = SDMSetupDevice(DEFAULT_DEVNO, &psdev);
+	if(result == E_OK){
+		psdev->pdevff           = (StorageDeviceFileFunc_t *)&romSDeviceFunc;
+		psdev->_sdev_attribute |= SDEV_EMPLOY;
+		hqspi = (QSPI_Handle_t *)h;
+		return MAX_DESCRIP;
+	}
+	else
+		return 0;
+}
+
+/*
+ *  FLASH-ROMファイルの生成
+ */
+int
+create_flash_file(const char *pathname, uint32_t start, uint32_t size)
+{
+	fs_descrip_t  *fdp;
+	int           cd = -1;
+	int           i, j;
+
+	dis_dsp();			/* disable dispatch */
+	for(i = 0 ; i < MAX_DESCRIP ; i++){
+		fdp = &fs_descrip_table[i];
+		if(fdp->create == 0){
+			fdp->create   = 1;
+			fdp->inuse    = 0;
+			fdp->fp       = 0;
+			fdp->addr     = start;
+			fdp->size     = size;
+			for(j = 0 ; j < ROMFILE_SIZE && pathname[j] != 0 ; j++)
+				fdp->filename[j] = (char)pathname[j];
+			fdp->filename[j] = 0;
+			cd = i;
+			num_files++;
+			break;
+		}
+	}
+	ena_dsp();			/* enable dispatch */
+	return cd;
+}
+
+/*
+ *  FLASH-ROMファイルディレクトリオープン
+ */
+static void *
+ffs_opendir(const char *pathname)
+{
+	dirreadcount = 0;
+	return (void *)&num_files;
+}
+
+/*
+ *  FLASH-ROMファイルディレクトリクローズ
+ */
+static int
+ffs_closedir(void *dir)
+{
+	return 0;
+}
+
+/*
+ *  FLASH-ROMファイルディレクトリ読み込み
+ */
+static int
+ffs_readdir(void *dir, void *pdirent)
+{
+	fs_descrip_t   *pf;
+	struct dirent2 *pd = pdirent;
+	unsigned int   i;
+
+	if(dirreadcount >= num_files)
+		return 0;
+	else{
+		pf = &fs_descrip_table[dirreadcount];
+		pd->d_fsize = pf->size;
+		pd->d_date  = 0;
+		pd->d_time  = 0;
+		pd->d_type  = AM_RDO;
+		for(i = 0 ; i < 255 && pf->filename[i] != 0 ; i++){
+			pd->d_name[i] = pf->filename[i];
+		}
+		pd->d_name[i] = 0;
+		dirreadcount++;
+		return dirreadcount;
+	}
+}
+
+/*
+ *  FLASH-ROMファイルオープン
+ */
+static int
+ffs_open(int devno, const char *pathname, int flags)
+{
+	fs_descrip_t  *fdp = 0;
+	int           fd;
+
+	SDMGetDeviceNo(&pathname);
+	if(*pathname == '/')
+		pathname++;
+	dis_dsp();			/* disable dispatch */
+	for(fd = 0 ; fd < num_files ; fd++){
+		fdp = &fs_descrip_table[fd];
+		if(fdp->create && strcmp(pathname, fdp->filename) == 0){
+			break;
+		}
+	}
+	if(fd < num_files && (flags & 0x0f) == O_RDONLY && fdp->inuse == 0){
+		fdp->inuse = 1;
+		fdp->fp = 0;
+		ena_dsp();			/* enable dispatch */
+		return fd;
+	}
+	else{
+		ena_dsp();			/* enable dispatch */
+		return -1;
+	}
+}
+
+/*
+ *  FLASH-ROMファイルクローズ
+ */
+static int
+ffs_close(int fd)
+{
+	fs_descrip_t  *fdp;
+
+	if(fd < 0 || num_files < fd)
+		return -1;
+	fdp = &fs_descrip_table[fd];
+	if(fdp->inuse == 1){
+		fdp->inuse = 0;
+		return 0;
+	}
+	else
+		return -1;
+}
+
+/*
+ *  FLASH-ROMファイルステート取得
+ */
+static int
+ffs_fstat(int fd, struct stat *buf)
+{
+	fs_descrip_t  *fdp;
+
+	if(fd < 0 || num_files < fd)
+		return -1;
+	fdp = &fs_descrip_table[fd];
+	if(fdp->create == 1){
+		memset(buf, 0, sizeof(struct stat));
+		buf->st_size = fdp->size;
+		return 0;
+	}
+	else
+		return -1;
+}
+
+/*
+ *  FLASH-ROMファイルシーク
+ */
+static off_t
+ffs_lseek(int fd, off_t offset, int whence, int *res)
+{
+	fs_descrip_t  *fdp;
+
+	*res = -1;
+	if(fd < 0 || num_files < fd)
+		return -1;
+	fdp = &fs_descrip_table[fd];
+	if(fdp->inuse == 1){
+		switch (whence) {
+		case SEEK_SET:
+			fdp->fp = offset;
+			break;
+		case SEEK_CUR:
+			fdp->fp += offset;
+			break;
+		case SEEK_END:
+			fdp->fp = fdp->size + offset;
+			break;
+		}
+		offset = fdp->fp;
+		*res = 0;
+		return offset;
+	}
+	else
+		return -1;
+}
+
+/*
+ *  FLASH-ROMファイル読みだし
+ */
+static long
+ffs_read(int fd, void *buf, long count, int *res)
+{
+	fs_descrip_t*fdp;
+	int         readsize, length;
+	uint32_t    fp, rcount, off;
+	ER          ercd = E_OK;
+
+	*res = -1;
+	if(fd < 0 || num_files < fd)
+		return -1;
+	fdp = &fs_descrip_table[fd];
+	if(fdp->inuse == 1){
+		if(fdp->fp < fdp->size){
+			if((fdp->fp + count) <= fdp->size)
+				readsize = count;	/* all counts can be read */
+			else
+				readsize = fdp->size - fdp->fp;	/* a part of counts can be read */
+			length = readsize;
+			fp     = fdp->fp;
+			while(length > 0){
+				off = ((unsigned int)fdp->addr + fp) & 3;
+				rcount = MIN(QSPIBUFLENGTH, length);
+				ercd = qspi_read(hqspi, (void *)qspibuff, (uint32_t)(fdp->addr + fp - off), ((rcount+off+3) & ~3));
+				if(ercd != E_OK){
+					syslog_4(LOG_ERROR, "ffs_read(%d, %08x, %d, %08x) ERROR !", fd, buf, count, res);
+					break;
+				}
+				memcpy(buf, ((uint8_t *)qspibuff)+off, rcount);
+				fp  += rcount;
+				buf += rcount;
+				length -= rcount;
+			}
+			fdp->fp += readsize;
+		}
+		else
+			readsize = 0;	/* no data can be read */
+		*res = 0;
+		if(ercd == E_OK)
+			return readsize;
+		else
+			return 0;
+	}
+	else
+		return -1;
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/flash_file/flash_file.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/flash_file/flash_file.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/flash_file/flash_file.h	(revision 453)
@@ -0,0 +1,76 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2018 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+ *  によって公表されている GNU General Public License の Version 2 に記
+ *  述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+ *  を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+ *  含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+ *  接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+#ifndef _FLASH_FILE_H_
+#define _FLASH_FILE_H_
+
+#include <kernel.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef MAX_DESCRIP
+#define	MAX_DESCRIP     16
+#endif
+#define ROMFILE_SIZE    27
+
+#ifndef TOPPERS_MACRO_ONLY
+
+typedef struct fs_descrip_s {
+  unsigned      create  : 1;
+  unsigned      inuse   : 1;
+  unsigned      size    : 30;
+  uint32_t      fp;
+  uint32_t      addr;
+  char          filename[ROMFILE_SIZE+1];
+} fs_descrip_t;
+
+
+extern ER  flash_file_init(void *h);
+extern int create_flash_file(const char *pathname, uint32_t start, uint32_t size);
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FLASHFILE_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/rom_file/Makefile.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/rom_file/Makefile.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/rom_file/Makefile.config	(revision 453)
@@ -0,0 +1,49 @@
+#
+#   TOPPERS BASE PLATFORM MIDDLEWARE
+#
+#   Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+ 
+#
+#  Makefile のプロセッサ依存 (rom_file用)
+#
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/gdic/rom_file
+
+#
+#  SPI DRIVER(GDIC)に関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR):$(SRCDIR)/gdic/rom_file
+SYSSVC_COBJS := $(SYSSVC_COBJS) rom_file.o
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/rom_file/rom_file.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/rom_file/rom_file.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/rom_file/rom_file.c	(revision 453)
@@ -0,0 +1,314 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+ *  によって公表されている GNU General Public License の Version 2 に記
+ *  述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+ *  を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+ *  含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+ *  接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <target_syssvc.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#include "device.h"
+#include <fcntl.h>
+#include "storagedevice.h"
+#include "rom_file.h"
+
+
+static int           num_files = 0;
+static int           dirreadcount;
+static fs_descrip_t  fs_descrip_table[MAX_DESCRIP];
+
+static void  *romf_opendir(const char *pathname);
+static int   romf_closedir(void *dir);
+static int   romf_readdir(void *dir, void *pdirent);
+static int   romf_open(int devno, const char *pathname, int flags);
+static int   romf_close(int fd);
+static int   romf_fstat(int fd, struct stat *buf);
+static off_t romf_lseek(int fd, off_t offset, int whence, int *res);
+static long  romf_read(int fd, void *buf, long count, int *res);
+
+static const StorageDeviceFileFunc_t romfSDeviceFunc = {
+	romf_opendir,
+	romf_closedir,
+	romf_readdir,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	romf_open,
+	romf_close,
+	romf_fstat,
+	romf_lseek,
+	romf_read,
+	0,
+	0
+};
+
+
+/*
+ *  FLASH-ROMファイル関数郡の初期化
+ */
+ER
+rom_file_init(void)
+{
+	StorageDevice_t *psdev;
+	int result;
+
+	num_files = 0;
+	memset(fs_descrip_table, 0, sizeof(fs_descrip_table));
+	result = SDMSetupDevice(DEFAULT_DEVNO, &psdev);
+	if(result == E_OK){
+		psdev->pdevff           = (StorageDeviceFileFunc_t *)&romfSDeviceFunc;
+		psdev->_sdev_attribute |= SDEV_EMPLOY;
+		return MAX_DESCRIP;
+	}
+	else
+		return 0;
+}
+
+/*
+ *  ROMファイルの生成
+ */
+int
+create_rom_file(const char *pathname, uintptr_t start, uint32_t size)
+{
+	fs_descrip_t  *fdp;
+	int           cd = -1;
+	int           i;
+
+	dis_dsp();			/* disable dispatch */
+	for(i = 0 ; i < MAX_DESCRIP ; i++){
+		fdp = &fs_descrip_table[i];
+		if(fdp->create == 0){
+			fdp->create   = 1;
+			fdp->inuse    = 0;
+			fdp->fp       = 0;
+			fdp->addr     = start;
+			fdp->size     = size;
+			fdp->filename = pathname;
+			cd = i;
+			num_files++;
+			break;
+		}
+	}
+	ena_dsp();			/* enable dispatch */
+	return cd;
+}
+
+/*
+ *  FLASH-ROMファイルディレクトリオープン
+ */
+static void *
+romf_opendir(const char *pathname)
+{
+	dirreadcount = 0;
+	return (void *)&num_files;
+}
+
+/*
+ *  ROMファイルディレクトリクローズ
+ */
+static int
+romf_closedir(void *dir)
+{
+	return 0;
+}
+
+/*
+ *  ROMファイルディレクトリ読み込み
+ */
+static int
+romf_readdir(void *dir, void *pdirent)
+{
+	fs_descrip_t   *pf;
+	struct dirent2 *pd = pdirent;
+	unsigned int   i;
+
+	if(dirreadcount >= num_files)
+		return 0;
+	else{
+		pf = &fs_descrip_table[dirreadcount];
+		pd->d_fsize = pf->size;
+		pd->d_date  = 0;
+		pd->d_time  = 0;
+		pd->d_type  = AM_RDO;
+		for(i = 0 ; i < 255 && pf->filename[i] != 0 ; i++){
+			pd->d_name[i] = pf->filename[i];
+		}
+		pd->d_name[i] = 0;
+		dirreadcount++;
+		return dirreadcount;
+	}
+}
+
+/*
+ *  ROMファイルオープン
+ */
+static int
+romf_open(int devno, const char *pathname, int flags)
+{
+	fs_descrip_t  *fdp = 0;
+	int           fd;
+
+	SDMGetDeviceNo(&pathname);
+	if(*pathname == '/')
+		pathname++;
+	dis_dsp();			/* disable dispatch */
+	for(fd = 0 ; fd < num_files ; fd++){
+		fdp = &fs_descrip_table[fd];
+		if(fdp->create && strcmp(pathname, fdp->filename) == 0){
+			break;
+		}
+	}
+	if(fd < num_files && (flags & 0x0f) == O_RDONLY && fdp->inuse == 0){
+		fdp->inuse = 1;
+		fdp->fp = 0;
+		ena_dsp();			/* enable dispatch */
+		return fd;
+	}
+	else{
+		ena_dsp();			/* enable dispatch */
+		return -1;
+	}
+}
+
+/*
+ *  ROMファイルクローズ
+ */
+static int
+romf_close(int fd)
+{
+	fs_descrip_t  *fdp;
+
+	if(fd < 0 || num_files < fd)
+		return -1;
+	fdp = &fs_descrip_table[fd];
+	if(fdp->inuse == 1){
+		fdp->inuse = 0;
+		return 0;
+	}
+	else
+		return -1;
+}
+
+/*
+ *  ROMファイルステート取得
+ */
+static int
+romf_fstat(int fd, struct stat *buf)
+{
+	fs_descrip_t  *fdp;
+
+	if(fd < 0 || num_files < fd)
+		return -1;
+	fdp = &fs_descrip_table[fd];
+	if(fdp->create == 1){
+		memset(buf, 0, sizeof(struct stat));
+		buf->st_size = fdp->size;
+		return 0;
+	}
+	else
+		return -1;
+}
+
+/*
+ *  ROMファイルシーク
+ */
+static off_t
+romf_lseek(int fd, off_t offset, int whence, int *res)
+{
+	fs_descrip_t  *fdp;
+
+	*res = -1;
+	if(fd < 0 || num_files < fd)
+		return -1;
+	fdp = &fs_descrip_table[fd];
+	if(fdp->inuse == 1){
+		switch (whence) {
+		case SEEK_SET:
+			fdp->fp = offset;
+			break;
+		case SEEK_CUR:
+			fdp->fp += offset;
+			break;
+		case SEEK_END:
+			fdp->fp = fdp->size + offset;
+			break;
+		}
+		offset = fdp->fp;
+		*res = 0;
+		return offset;
+	}
+	else
+		return -1;
+}
+
+/*
+ *  ROMファイル読みだし
+ */
+static long
+romf_read(int fd, void *buf, long count, int *res)
+{
+	fs_descrip_t*fdp;
+	int         readsize;
+
+	*res = -1;
+	if(fd < 0 || num_files < fd)
+		return -1;
+	fdp = &fs_descrip_table[fd];
+	if(fdp->inuse == 1){
+		if(fdp->fp < fdp->size){
+			if((fdp->fp + count) <= fdp->size)
+				readsize = count;	/* all counts can be read */
+			else
+				readsize = fdp->size - fdp->fp;	/* a part of counts can be read */
+			memcpy(buf, ((uint8_t *)fdp->addr + fdp->fp), readsize);
+			buf += readsize;
+			fdp->fp += readsize;
+		}
+		else
+			readsize = 0;	/* no data can be read */
+		*res = 0;
+		return readsize;
+	}
+	else
+		return -1;
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/rom_file/rom_file.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/rom_file/rom_file.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/rom_file/rom_file.h	(revision 453)
@@ -0,0 +1,72 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+ *  によって公表されている GNU General Public License の Version 2 に記
+ *  述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+ *  を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+ *  含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+ *  接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+#ifndef _ROM_FILE_H_
+#define _ROM_FILE_H_
+
+#include <kernel.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef MAX_DESCRIP
+#define	MAX_DESCRIP     16
+#endif
+
+#ifndef TOPPERS_MACRO_ONLY
+
+typedef struct fs_descrip_s {
+  unsigned      create  : 1;
+  unsigned      inuse   : 1;
+  unsigned      size    : 30;
+  uintptr_t     fp;
+  uintptr_t     addr;
+  const char    *filename;
+} fs_descrip_t;
+
+
+extern ER  rom_file_init(void);
+extern int create_rom_file(const char *pathname, uintptr_t start, uint32_t size);
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ROM_FILE_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/sipeed_ov2640/Makefile.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/sipeed_ov2640/Makefile.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/sipeed_ov2640/Makefile.config	(revision 453)
@@ -0,0 +1,55 @@
+#
+#   TOPPERS/ASP/FMP Kernel
+#       Toyohashi Open Platform for Embedded Real-Time Systems/
+#       Advanced Standard Profile Kernel
+#
+#   Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                               Toyohashi Univ. of Technology, JAPAN
+#   Copyright (C) 2003-2008 by Ryosuke Takeuchi
+#                Platform Development Center RICOH COMPANY,LTD. JAPAN
+#   Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+ 
+#
+#  Makefile のプロセッサ依存 (sipeed ov2640:CAMERA用)
+#
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/gdic/sipeed_ov2640
+
+#
+#  SIPEED OV2640 CAMERA DRIVER(GDIC)に関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR):$(SRCDIR)/gdic/sipeed_ov2640
+SYSSVC_COBJS := $(SYSSVC_COBJS) sipeed_ov2640.o 
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/sipeed_ov2640/ov2640_regs.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/sipeed_ov2640/ov2640_regs.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/sipeed_ov2640/ov2640_regs.h	(revision 453)
@@ -0,0 +1,212 @@
+/*
+ * This file is part of the OpenMV project.
+ * Copyright (c) 2013/2014 Ibrahim Abdelkader <i.abdalkader@gmail.com>
+ * This work is licensed under the MIT license, see the file LICENSE for details.
+ *
+ * OV2640 register definitions.
+ */
+
+#ifndef __REG_REGS_H__
+#define __REG_REGS_H__
+
+/* DSP register bank FF=0x00*/
+
+#define QS                      0x44
+#define HSIZE                   0x51
+#define VSIZE                   0x52
+#define XOFFL                   0x53
+#define YOFFL                   0x54
+#define VHYX                    0x55
+#define DPRP                    0x56
+#define TEST                    0x57
+#define ZMOW                    0x5A
+#define ZMOH                    0x5B
+#define ZMHH                    0x5C
+#define BPADDR                  0x7C
+#define BPDATA                  0x7D
+#define SIZEL                   0x8C
+#define HSIZE8                  0xC0
+#define VSIZE8                  0xC1
+#define CTRL1                   0xC3
+#define MS_SP                   0xF0
+#define SS_ID                   0xF7
+#define SS_CTRL                 0xF7
+#define MC_AL                   0xFA
+#define MC_AH                   0xFB
+#define MC_D                    0xFC
+#define P_CMD                   0xFD
+#define P_STATUS                0xFE
+
+#define CTRLI                   0x50
+#define CTRLI_LP_DP             0x80
+#define CTRLI_ROUND             0x40
+
+#define CTRL0                   0xC2
+#define CTRL0_AEC_EN            0x80
+#define CTRL0_AEC_SEL           0x40
+#define CTRL0_STAT_SEL          0x20
+#define CTRL0_VFIRST            0x10
+#define CTRL0_YUV422            0x08
+#define CTRL0_YUV_EN            0x04
+#define CTRL0_RGB_EN            0x02
+#define CTRL0_RAW_EN            0x01
+
+#define CTRL2                   0x86
+#define CTRL2_DCW_EN            0x20
+#define CTRL2_SDE_EN            0x10
+#define CTRL2_UV_ADJ_EN         0x08
+#define CTRL2_UV_AVG_EN         0x04
+#define CTRL2_CMX_EN            0x01
+
+#define CTRL3                   0x87
+#define CTRL3_BPC_EN            0x80
+#define CTRL3_WPC_EN            0x40
+#define R_DVP_SP                0xD3
+#define R_DVP_SP_AUTO_MODE      0x80
+
+#define R_BYPASS                0x05
+#define R_BYPASS_DSP_EN         0x00
+#define R_BYPASS_DSP_BYPAS      0x01
+
+#define IMAGE_MODE              0xDA
+#define IMAGE_MODE_Y8_DVP_EN    0x40
+#define IMAGE_MODE_JPEG_EN      0x10
+#define IMAGE_MODE_YUV422       0x00
+#define IMAGE_MODE_RAW10        0x04
+#define IMAGE_MODE_RGB565       0x08
+#define IMAGE_MODE_HREF_VSYNC   0x02
+#define IMAGE_MODE_LBYTE_FIRST  0x01
+#define IMAGE_MODE_GET_FMT(x)   ((x)&0xC)
+
+#define RESET                   0xE0
+#define RESET_MICROC            0x40
+#define RESET_SCCB              0x20
+#define RESET_JPEG              0x10
+#define RESET_DVP               0x04
+#define RESET_IPU               0x02
+#define RESET_CIF               0x01
+
+#define MC_BIST                 0xF9
+#define MC_BIST_RESET           0x80
+#define MC_BIST_BOOT_ROM_SEL    0x40
+#define MC_BIST_12KB_SEL        0x20
+#define MC_BIST_12KB_MASK       0x30
+#define MC_BIST_512KB_SEL       0x08
+#define MC_BIST_512KB_MASK      0x0C
+#define MC_BIST_BUSY_BIT_R      0x02
+#define MC_BIST_MC_RES_ONE_SH_W 0x02
+#define MC_BIST_LAUNCH          0x01
+
+#define BANK_SEL                0xFF
+#define BANK_SEL_DSP            0x00
+#define BANK_SEL_SENSOR         0x01
+
+/* Sensor register bank FF=0x01*/
+
+#define GAIN                0x00
+#define COM1                0x03
+#define REG_PID             0x0A
+#define REG_VER             0x0B
+#define COM4                0x0D
+#define AEC                 0x10
+
+#define CLKRC               0x11
+#define CLKRC_DOUBLE        0x80
+#define CLKRC_DIVIDER_MASK  0x3F
+
+#define COM10               0x15
+#define HSTART              0x17
+#define HSTOP               0x18
+#define VSTART              0x19
+#define VSTOP               0x1A
+#define MIDH                0x1C
+#define MIDL                0x1D
+#define AEW                 0x24
+#define AEB                 0x25
+#define REG2A               0x2A
+#define FRARL               0x2B
+#define ADDVSL              0x2D
+#define ADDVSH              0x2E
+#define YAVG                0x2F
+#define HSDY                0x30
+#define HEDY                0x31
+#define ARCOM2              0x34
+#define REG45               0x45
+#define FLL                 0x46
+#define FLH                 0x47
+#define COM19               0x48
+#define ZOOMS               0x49
+#define COM22               0x4B
+#define COM25               0x4E
+#define BD50                0x4F
+#define BD60                0x50
+#define REG5D               0x5D
+#define REG5E               0x5E
+#define REG5F               0x5F
+#define REG60               0x60
+#define HISTO_LOW           0x61
+#define HISTO_HIGH          0x62
+
+#define REG04               0x04
+#define REG04_DEFAULT       0x28
+#define REG04_HFLIP_IMG     0x80
+#define REG04_VFLIP_IMG     0x40
+#define REG04_VREF_EN       0x10
+#define REG04_HREF_EN       0x08
+#define REG04_SET(x)        (REG04_DEFAULT|x)
+
+#define REG08               0x08
+#define COM2                0x09
+#define COM2_STDBY          0x10
+#define COM2_OUT_DRIVE_1x   0x00
+#define COM2_OUT_DRIVE_2x   0x01
+#define COM2_OUT_DRIVE_3x   0x02
+#define COM2_OUT_DRIVE_4x   0x03
+
+#define COM3                0x0C
+#define COM3_DEFAULT        0x38
+#define COM3_BAND_50Hz      0x04
+#define COM3_BAND_60Hz      0x00
+#define COM3_BAND_AUTO      0x02
+#define COM3_BAND_SET(x)    (COM3_DEFAULT|x)
+
+#define COM7                0x12
+#define COM7_SRST           0x80
+#define COM7_RES_UXGA       0x00 /* UXGA */
+#define COM7_RES_SVGA       0x40 /* SVGA */
+#define COM7_RES_CIF        0x20 /* CIF  */
+#define COM7_ZOOM_EN        0x04 /* Enable Zoom */
+#define COM7_COLOR_BAR      0x02 /* Enable Color Bar Test */
+#define COM7_GET_RES(x)     ((x)&0x70)
+
+#define COM8                0x13
+#define COM8_DEFAULT        0xC0
+#define COM8_BNDF_EN        0x20 /* Enable Banding filter */
+#define COM8_AGC_EN         0x04 /* AGC Auto/Manual control selection */
+#define COM8_AEC_EN         0x01 /* Auto/Manual Exposure control */
+#define COM8_SET(x)         (COM8_DEFAULT|x)
+#define COM8_SET_AEC(r,x)   (((r)&0xFE)|((x)&1))
+
+#define COM9                0x14 /* AGC gain ceiling */
+#define COM9_DEFAULT        0x08
+#define COM9_AGC_GAIN_2x    0x00 /* AGC:    2x */
+#define COM9_AGC_GAIN_4x    0x01 /* AGC:    4x */
+#define COM9_AGC_GAIN_8x    0x02 /* AGC:    8x */
+#define COM9_AGC_GAIN_16x   0x03 /* AGC:   16x */
+#define COM9_AGC_GAIN_32x   0x04 /* AGC:   32x */
+#define COM9_AGC_GAIN_64x   0x05 /* AGC:   64x */
+#define COM9_AGC_GAIN_128x  0x06 /* AGC:  128x */
+#define COM9_AGC_SET(x)     (COM9_DEFAULT|(x<<5))
+
+#define CTRL1_AWB           0x08 /* Enable AWB */
+
+#define VV                  0x26
+#define VV_AGC_TH_SET(h,l)  ((h<<4)|(l&0x0F))
+
+#define REG32               0x32
+#define REG32_UXGA          0x36
+#define REG32_SVGA          0x09
+#define REG32_CIF           0x00
+
+#endif //__REG_REGS_H__
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/sipeed_ov2640/sipeed_ov2640.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/sipeed_ov2640/sipeed_ov2640.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/sipeed_ov2640/sipeed_ov2640.c	(revision 453)
@@ -0,0 +1,1102 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2012 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+/* 
+ *  SIPEED OV2640 CAMARA制御プログラムの本体
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <target_syssvc.h>
+#include "device.h"
+
+#include "dvp.h"
+#include "ov2640_regs.h"
+#include "stdlib.h"
+#include "math.h"
+#include "sipeed_ov2640.h"
+
+
+#define IM_MAX(a,b)     ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a > _b ? _a : _b; })
+#define IM_MIN(a,b)     ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a < _b ? _a : _b; })
+#define IM_DIV(a,b)     ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _b ? (_a / _b) : 0; })
+#define IM_MOD(a,b)     ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _b ? (_a % _b) : 0; })
+
+#ifndef SNAPSHOT_TIMEOUT
+#define SNAPDHOT_TIMEOUT    300
+#endif
+
+
+#define SVGA_HSIZE     (800)
+#define SVGA_VSIZE     (600)
+
+#define UXGA_HSIZE     (1600)
+#define UXGA_VSIZE     (1200)
+static const uint8_t ov2640_default[][2] = { //k210 
+	{0xff, 0x01},
+	{0x12, 0x80},
+	{0xff, 0x00},
+	{0x2c, 0xff},
+	{0x2e, 0xdf},
+	{0xff, 0x01},
+	{0x3c, 0x32},
+	{0x11, 0x00},
+	{0x09, 0x02},
+	{0x04, 0xa8},//v flip and h mirro
+	{0x13, 0xe5},
+	{0x14, 0x48},
+	{0x2c, 0x0c},
+	{0x33, 0x78},
+	{0x3a, 0x33},
+	{0x3b, 0xfb},
+	{0x3e, 0x00},
+	{0x43, 0x11},
+	{0x16, 0x10},
+	{0x39, 0x92},//test 92
+	{0x23, 0x00},
+	{0x36, 0x1a},
+	{0x07, 0xc0},
+	{0x4c, 0x00},
+	{0x48, 0x00},
+	{0x5b, 0x00},
+	{0x4a, 0x81},
+	{0x21, 0x99},
+	{0x24, 0x40},
+	{0x25, 0x38},
+	{0x26, 0x82},
+	{0x5c, 0x00},
+	{0x63, 0x00},
+	{0x46, 0x22},
+	{0x0c, 0x3c},
+	{0x61, 0x70},
+	{0x62, 0x80},
+	{0x7c, 0x05},
+	{0x20, 0x80},
+	{0x28, 0x30},
+	{0x6c, 0x00},
+	{0x6d, 0x80},
+	{0x6e, 0x00},
+	{0x70, 0x02},
+	{0x71, 0x94},
+	{0x73, 0xc1},
+	{0x5a, 0x57},
+	{0x37, 0xc0},
+	{0x4f, 0xca},
+	{0x50, 0xa8},
+	{0x5a, 0x23},
+	{0x6d, 0x00},
+	{0x3d, 0x38},
+	{0xff, 0x00},
+	{0xe5, 0x7f},
+	{0xf9, 0xc0},
+	{0x41, 0x24},
+	{0xe0, 0x14},
+	{0x76, 0xff},
+	{0x33, 0xa0},
+	{0x42, 0x20},
+	{0x43, 0x18},
+	{0x4c, 0x00},
+	{0x87, 0xd5},
+	{0x88, 0x3f},
+	{0xd7, 0x03},//[pixformat]:
+	{0xd9, 0x10},
+	{0xd3, 0x82},
+	{0xc8, 0x08},
+	{0xc9, 0x80},
+	{0x7c, 0x00},
+	{0x7d, 0x00},
+	{0x7c, 0x03},
+	{0x7d, 0x48},
+	{0x7d, 0x48},
+	{0x7c, 0x08},
+	{0x7d, 0x20},
+	{0x7d, 0x10},
+	{0x7d, 0x0e},
+	{0x90, 0x00},
+	{0x91, 0x0e},
+	{0x91, 0x1a},
+	{0x91, 0x31},
+	{0x91, 0x5a},
+	{0x91, 0x69},
+	{0x91, 0x75},
+	{0x91, 0x7e},
+	{0x91, 0x88},
+	{0x91, 0x8f},
+	{0x91, 0x96},
+	{0x91, 0xa3},
+	{0x91, 0xaf},
+	{0x91, 0xc4},
+	{0x91, 0xd7},
+	{0x91, 0xe8},
+	{0x91, 0x20},
+	{0x92, 0x00},
+	{0x93, 0x06},
+	{0x93, 0xe3},
+	{0x93, 0x05},
+	{0x93, 0x05},
+	{0x93, 0x00},
+	{0x93, 0x04},
+	{0x93, 0x00},
+	{0x93, 0x00},
+	{0x93, 0x00},
+	{0x93, 0x00},
+	{0x93, 0x00},
+	{0x93, 0x00},
+	{0x93, 0x00},
+	{0x96, 0x00},
+	{0x97, 0x08},
+	{0x97, 0x19},
+	{0x97, 0x02},
+	{0x97, 0x0c},
+	{0x97, 0x24},
+	{0x97, 0x30},
+	{0x97, 0x28},
+	{0x97, 0x26},
+	{0x97, 0x02},
+	{0x97, 0x98},
+	{0x97, 0x80},
+	{0x97, 0x00},
+	{0x97, 0x00},
+	{0xc3, 0xed},
+	{0xa4, 0x00},
+	{0xa8, 0x00},
+	{0xc5, 0x11},
+	{0xc6, 0x51},
+	{0xbf, 0x80},
+	{0xc7, 0x10},
+	{0xb6, 0x66},
+	{0xb8, 0xa5},
+	{0xb7, 0x64},
+	{0xb9, 0x7c},
+	{0xb3, 0xaf},
+	{0xb4, 0x97},
+	{0xb5, 0xff},
+	{0xb0, 0xc5},
+	{0xb1, 0x94},
+	{0xb2, 0x0f},
+	{0xc4, 0x5c},
+	{0x5a, 0xc8},
+	{0x5b, 0x96},
+	{0x5c, 0x00},
+	{0xc3, 0xed},
+	{0x7f, 0x00},
+	{0xda, 0x08},//pixformat
+	{0xe5, 0x1f},
+	{0xe1, 0x67},//pixformat
+	{0xe0, 0x00},
+	{0xdd, 0x7f},
+	{0x05, 0x00},
+#if 1	//color bar
+	{0xff, 0x01},
+	{0x12, 0x02},
+#endif
+	{0x00, 0x00}
+
+};
+static const uint8_t svga_config[][2] = { //k210 
+	{0xff, 0x01},//bank sel
+	{0x35, 0xda},//[SVGA]:
+	{0x22, 0x1a},//[SVGA]:
+	{0x37, 0xc3},//[SVGA]:
+	{0x34, 0xc0},//[SVGA]:
+	{0x06, 0x88},//[SVGA]:
+	{0x0d, 0x87},//[SVGA]:
+	{0x0e, 0x41},//[SVGA]:
+	{0x42, 0x03},//[SVGA]:
+	{0x3d, 0x34},//[SVGA]:
+	{0x12, 0x40},//[SVGA]:  COM7,COM7_RES_SVGA  SVGA
+	{0x03, 0x0f},//[SVGA]:  COM1,0x0F  
+	{0x17, 0x11},//[SVGA]:HSTART
+	{0x18, 0x43},//[SVGA]:HSTOP
+	{0x19, 0x00},//[SVGA]:VSTART
+	{0x1a, 0x4b},//[SVGA]:VSTOP
+	{0x32, 0x09},//[SVGA]:REG32
+	
+	{0xff, 0x00},//bank sel
+	{0xc0, 0x64},//[SVGA]:HSIZE8 SVGA_HSIZE>>3
+	{0xc1, 0x4b},//[SVGA]:VSIZE8 SVGA_VSIZE>>3
+	{0x8c, 0x00},//[SVGA]:SIZEL
+	{0x86, 0x3d},//[SVGA]:
+	{0x50, 0x00},//[SVGA]:CTRLI
+	{0x51, 0xc8},//[SVGA]:HSIZE
+	{0x52, 0x96},//[SVGA]:VSIZE
+	{0x53, 0x00},//[SVGA]:XOFFL
+	{0x54, 0x00},//[SVGA]:YOFFL
+	{0x55, 0x00},//[SVGA]:VHYX
+	{0xd3, 0x02},//[SVGA]:R_DVP_SP	
+};
+
+static const uint8_t uxga_regs[][2] = {
+        { BANK_SEL, BANK_SEL_SENSOR },
+        /* DSP input image resoultion and window size control */
+        { COM7,    COM7_RES_UXGA},
+        { COM1,    0x0F }, /* UXGA=0x0F, SVGA=0x0A, CIF=0x06 */
+        { REG32,   0x36 }, /* UXGA=0x36, SVGA/CIF=0x09 */
+
+        { HSTART,  0x11 }, /* UXGA=0x11, SVGA/CIF=0x11 */
+        { HSTOP,   0x75 }, /* UXGA=0x75, SVGA/CIF=0x43 */
+
+        { VSTART,  0x01 }, /* UXGA=0x01, SVGA/CIF=0x00 */
+        { VSTOP,   0x97 }, /* UXGA=0x97, SVGA/CIF=0x4b */
+        { 0x3d,    0x34 }, /* UXGA=0x34, SVGA/CIF=0x38 */
+
+        { 0x35,    0x88 },
+        { 0x22,    0x0a },
+        { 0x37,    0x40 },
+        { 0x34,    0xa0 },
+        { 0x06,    0x02 },
+        { 0x0d,    0xb7 },
+        { 0x0e,    0x01 },
+        { 0x42,    0x83 },
+
+        /* Set DSP input image size and offset.
+           The sensor output image can be scaled with OUTW/OUTH */
+        { BANK_SEL, BANK_SEL_DSP },
+        { R_BYPASS, R_BYPASS_DSP_BYPAS },
+
+        { RESET,   RESET_DVP },
+        { HSIZE8,  (UXGA_HSIZE>>3)}, /* Image Horizontal Size HSIZE[10:3] */
+        { VSIZE8,  (UXGA_VSIZE>>3)}, /* Image Vertiacl Size VSIZE[10:3] */
+
+        /* {HSIZE[11], HSIZE[2:0], VSIZE[2:0]} */
+        { SIZEL,   ((UXGA_HSIZE>>6)&0x40) | ((UXGA_HSIZE&0x7)<<3) | (UXGA_VSIZE&0x7)},
+
+        { XOFFL,   0x00 }, /* OFFSET_X[7:0] */
+        { YOFFL,   0x00 }, /* OFFSET_Y[7:0] */
+        { HSIZE,   ((UXGA_HSIZE>>2)&0xFF) }, /* H_SIZE[7:0] real/4 */
+        { VSIZE,   ((UXGA_VSIZE>>2)&0xFF) }, /* V_SIZE[7:0] real/4 */
+
+        /* V_SIZE[8]/OFFSET_Y[10:8]/H_SIZE[8]/OFFSET_X[10:8] */
+        { VHYX,    ((UXGA_VSIZE>>3)&0x80) | ((UXGA_HSIZE>>7)&0x08) },
+        { TEST,    (UXGA_HSIZE>>4)&0x80}, /* H_SIZE[9] */
+
+        { CTRL2,   CTRL2_DCW_EN | CTRL2_SDE_EN |
+            CTRL2_UV_AVG_EN | CTRL2_CMX_EN | CTRL2_UV_ADJ_EN },
+
+        /* H_DIVIDER/V_DIVIDER */
+        { CTRLI,   CTRLI_LP_DP | 0x00},
+        /* DVP prescalar */
+        { R_DVP_SP, R_DVP_SP_AUTO_MODE | 0x04},
+
+        { R_BYPASS, R_BYPASS_DSP_EN },
+        { RESET,    0x00 },
+        {0, 0},
+};
+
+static const uint8_t yuv422_regs[][2] = {
+        { BANK_SEL, BANK_SEL_DSP },
+        { RESET,   RESET_DVP},
+        { 0xD7,     0x01 },
+        { IMAGE_MODE, IMAGE_MODE_YUV422 },
+        { 0xE1,     0x67 },
+        { RESET,    0x00 },
+        {0, 0},
+};
+
+static const uint8_t rgb565_regs[][2] = {
+        { BANK_SEL,   BANK_SEL_DSP },
+        { RESET,      RESET_DVP},
+        { 0xD7,       0x03},
+        { IMAGE_MODE, IMAGE_MODE_RGB565 },
+        { 0xE1,       0x77 },
+        { RESET,      0x00 },
+        {0,           0},
+};
+
+static const uint8_t jpeg_regs[][2] = {
+        { BANK_SEL, BANK_SEL_DSP },
+        { RESET,   RESET_DVP},
+        { IMAGE_MODE, IMAGE_MODE_JPEG_EN|IMAGE_MODE_RGB565 },
+        { 0xD7,     0x03 },
+        { 0xE1,     0x77 },
+        { QS,       0x0C },
+        { RESET,    0x00 },
+        {0, 0},
+};
+
+#define NUM_BRIGHTNESS_LEVELS (5)
+static const uint8_t brightness_regs[NUM_BRIGHTNESS_LEVELS + 1][5] = {
+    { BPADDR, BPDATA, BPADDR, BPDATA, BPDATA },
+    { 0x00, 0x04, 0x09, 0x00, 0x00 }, /* -2 */
+    { 0x00, 0x04, 0x09, 0x10, 0x00 }, /* -1 */
+    { 0x00, 0x04, 0x09, 0x20, 0x00 }, /*  0 */
+    { 0x00, 0x04, 0x09, 0x30, 0x00 }, /* +1 */
+    { 0x00, 0x04, 0x09, 0x40, 0x00 }, /* +2 */
+};
+
+#define NUM_CONTRAST_LEVELS (5)
+static const uint8_t contrast_regs[NUM_CONTRAST_LEVELS + 1][7] = {
+    { BPADDR, BPDATA, BPADDR, BPDATA, BPDATA, BPDATA, BPDATA },
+    { 0x00, 0x04, 0x07, 0x20, 0x18, 0x34, 0x06 }, /* -2 */
+    { 0x00, 0x04, 0x07, 0x20, 0x1c, 0x2a, 0x06 }, /* -1 */
+    { 0x00, 0x04, 0x07, 0x20, 0x20, 0x20, 0x06 }, /*  0 */
+    { 0x00, 0x04, 0x07, 0x20, 0x24, 0x16, 0x06 }, /* +1 */
+    { 0x00, 0x04, 0x07, 0x20, 0x28, 0x0c, 0x06 }, /* +2 */
+};
+
+#define NUM_SATURATION_LEVELS (5)
+static const uint8_t saturation_regs[NUM_SATURATION_LEVELS + 1][5] = {
+    { BPADDR, BPDATA, BPADDR, BPDATA, BPDATA },
+    { 0x00, 0x02, 0x03, 0x28, 0x28 }, /* -2 */
+    { 0x00, 0x02, 0x03, 0x38, 0x38 }, /* -1 */
+    { 0x00, 0x02, 0x03, 0x48, 0x48 }, /*  0 */
+    { 0x00, 0x02, 0x03, 0x58, 0x58 }, /* +1 */
+    { 0x00, 0x02, 0x03, 0x58, 0x58 }, /* +2 */
+};
+
+static const int resolution[][2] = {
+    {0,    0   },
+    // C/SIF Resolutions
+    {88,   72  },    /* QQCIF     */
+    {176,  144 },    /* QCIF      */
+    {352,  288 },    /* CIF       */
+    {88,   60  },    /* QQSIF     */
+    {176,  120 },    /* QSIF      */
+    {352,  240 },    /* SIF       */
+    // VGA Resolutions
+    {40,   30  },    /* QQQQVGA   */
+    {80,   60  },    /* QQQVGA    */
+    {160,  120 },    /* QQVGA     */
+    {320,  240 },    /* QVGA      */
+    {640,  480 },    /* VGA       */
+    {60,   40  },    /* HQQQVGA   */
+    {120,  80  },    /* HQQVGA    */
+    {240,  160 },    /* HQVGA     */
+    // FFT Resolutions
+    {64,   32  },    /* 64x32     */
+    {64,   64  },    /* 64x64     */
+    {128,  64  },    /* 128x64    */
+    {128,  128 },    /* 128x64    */
+    // Other
+    {128,  160 },    /* LCD       */
+    {128,  160 },    /* QQVGA2    */
+    {720,  480 },    /* WVGA      */
+    {752,  480 },    /* WVGA2     */
+    {800,  600 },    /* SVGA      */
+    {1280, 1024},    /* SXGA      */
+    {1600, 1200},    /* UXGA      */
+};
+
+
+#define cambus_writeb(h, a, d)  dvp_sccb_send_data(((h)->hdvp), ((h)->_slaveAddr), (a), (d))
+
+int Sipeed_OV2640_cambus_scan_gc0328(OV2640_t *hcmr);
+int Sipeed_OV2640_dvpInitIrq(void);
+
+static int cambus_readb(OV2640_t *hcmr, uint8_t reg_addr, uint8_t *reg_data)
+{
+
+    int ret = 0;
+	*reg_data = dvp_sccb_receive_data(hcmr->hdvp, hcmr->_slaveAddr, reg_addr);
+	if(0xff == *reg_data)
+		ret = -1;
+    return ret;
+}
+
+static int reverse_u32pixel(uint32_t* addr, uint32_t length)
+{
+  if(NULL == addr)
+    return -1;
+
+  uint32_t data;
+  uint32_t* pend = addr+length;
+  for(;addr<pend;addr++)
+  {
+	  data = *(addr);
+	  *(addr) = ((data & 0x000000FF) << 24) | ((data & 0x0000FF00) << 8) | 
+                ((data & 0x00FF0000) >> 8) | ((data & 0xFF000000) >> 24) ;
+  }  //1.7ms
+  
+  
+  return 0;
+}
+
+static int cambus_read_id(OV2640_t *hcmr, uint8_t addr, uint16_t *manuf_id, uint16_t *device_id)
+{
+	dvp_sccb_send_data(hcmr->hdvp, addr, 0xFF, 0x01);
+	*manuf_id = (dvp_sccb_receive_data(hcmr->hdvp, addr, 0x1C) << 8) | dvp_sccb_receive_data(hcmr->hdvp, addr, 0x1D);
+	*device_id = (dvp_sccb_receive_data(hcmr->hdvp, addr, 0x0A) << 8) | dvp_sccb_receive_data(hcmr->hdvp, addr, 0x0B);
+	return 0;
+}
+
+static int cambus_scan(OV2640_t *hcmr)
+{
+
+	uint16_t manuf_id = 0;
+	uint16_t device_id = 0;
+    for (uint8_t addr=0x08; addr<=0x77; addr++) {
+		cambus_read_id(hcmr, addr ,&manuf_id,&device_id);
+		if(0xffff != device_id)
+		{
+			return addr ;
+		}
+    }
+    return 0;
+}
+
+
+void
+ov2640_getResolition(OV2640_t *hcmr, framesize_t frameSize)
+{
+	hcmr->_width    = resolution[frameSize][0];
+	hcmr->_height   = resolution[frameSize][1];
+}
+
+ER
+ov2640_sensor_ov_detect(OV2640_t *hcmr)
+{
+	DVP_Handle_t *hdvp = hcmr->hdvp;
+
+	/* Reset the sensor */
+	dvp_dcmi_reset(hdvp, true);
+	dly_tsk(10);
+
+	dvp_dcmi_reset(hdvp, false);
+	dly_tsk(10);
+
+	/* Probe the ov sensor */
+	hcmr->_slaveAddr = cambus_scan(hcmr);
+	if(hcmr->_slaveAddr == 0){
+		/* Sensor has been held in reset,
+		   so the reset line is active low */
+		hcmr->_resetPoliraty = ACTIVE_LOW;
+
+		/* Pull the sensor out of the reset state,systick_sleep() */
+		dvp_dcmi_reset(hdvp, true);
+		dly_tsk(10);
+
+		/* Probe again to set the slave addr */
+		hcmr->_slaveAddr = cambus_scan(hcmr);
+		if(hcmr->_slaveAddr == 0){
+			hcmr->_pwdnPoliraty = ACTIVE_LOW;
+			dvp_dcmi_powerdown(hdvp, false);
+			dly_tsk(10);
+
+			hcmr->_slaveAddr = cambus_scan(hcmr);
+			if(hcmr->_slaveAddr == 0){
+				hcmr->_resetPoliraty = ACTIVE_HIGH;
+				dvp_dcmi_reset(hdvp, false);
+				dly_tsk(10);
+
+				hcmr->_slaveAddr = cambus_scan(hcmr);
+				if(hcmr->_slaveAddr == 0){
+					//should do something?
+					return E_SYS;
+				}
+			}
+		}
+	}
+
+	// Clear sensor chip ID.
+	hcmr->_id = 0;
+
+	if(hcmr->_slaveAddr == LEPTON_ID){
+		hcmr->_id = LEPTON_ID;
+		/*set LEPTON xclk rate*/
+		/*lepton_init*/
+	}
+	else{
+		// Read ON semi sensor ID.
+		cambus_readb(hcmr, ON_CHIP_ID, &hcmr->_id);
+		if(hcmr->_id == MT9V034_ID){
+			/*set MT9V034 xclk rate*/
+			/*mt9v034_init*/
+		}
+		else{	// Read OV sensor ID.
+			cambus_readb(hcmr, OV_CHIP_ID, &hcmr->_id);
+			// Initialize sensor struct.
+			switch(hcmr->_id){
+			case OV9650_ID:
+				/*ov9650_init*/
+				break;
+			case OV2640_ID:
+				// printf("detect ov2640, id:%x\n", _slaveAddr);
+				break;
+			case OV7725_ID:
+				/*ov7725_init*/
+				break;
+			default:
+				// Sensor is not supported.
+				return E_SYS;
+			}
+		}
+	}
+	return E_OK;
+}
+
+ER
+ov2640_sensro_gc_detect(OV2640_t *hcmr)
+{
+	DVP_Handle_t *hdvp = hcmr->hdvp;
+	uint8_t id;
+
+	dvp_dcmi_powerdown(hdvp, false);//enable gc0328 要恢? normal 工作模式，需将 PWDN pin 接入低?平即可，同?写入初始化寄存器即可
+	dvp_dcmi_reset(hdvp, false);	//reset gc3028
+	dly_tsk(10);
+	dvp_dcmi_reset(hdvp, true);
+	dly_tsk(10);
+	id = ov2640_cambus_scan_gc0328(hcmr);
+	if(0 == id){
+		return E_SYS;
+	}
+	else{
+		// printf("[MAIXPY]: gc0328 id = %x\n",id); 
+		hcmr->_slaveAddr = GC0328_ADDR;
+		hcmr->_id = id;
+	}
+	return E_OK;
+}
+
+
+ER
+ov2640_reset(OV2640_t *hcmr)
+{
+	int i=0;
+	const uint8_t (*regs)[2];
+
+	/* Reset all registers */
+	cambus_writeb(hcmr, BANK_SEL, BANK_SEL_SENSOR);
+	cambus_writeb(hcmr, COM7, COM7_SRST);
+
+	/* delay n ms */
+	dly_tsk(10);
+
+	i = 0;
+	regs = ov2640_default;
+	/* Write initial regsiters */
+	while (regs[i][0]) {
+		cambus_writeb(hcmr, regs[i][0], regs[i][1]);
+		i++;
+	}
+	i = 0;
+	regs = svga_config;
+	/* Write DSP input regsiters */
+	while (regs[i][0]) {
+		cambus_writeb(hcmr, regs[i][0], regs[i][1]);
+		i++;
+	}
+	return E_OK;
+}
+
+ER
+ov2640_set_pixformat(OV2640_t *hcmr)
+{
+	int i=0;
+	const uint8_t (*regs)[2]=NULL;
+
+	/* read pixel format reg */
+	switch(hcmr->pixFormat){
+	case PIXFORMAT_RGB565:
+		regs = rgb565_regs;
+		break;
+	case PIXFORMAT_YUV422:
+	case PIXFORMAT_GRAYSCALE:
+		regs = yuv422_regs;
+		break;
+	case PIXFORMAT_JPEG:
+		regs = jpeg_regs;
+		break;
+	default:
+		return E_PAR;
+	}
+
+	/* Write initial regsiters */
+	while(regs[i][0]){
+		cambus_writeb(hcmr, regs[i][0], regs[i][1]);
+		i++;
+	}
+	switch(hcmr->pixFormat) {
+	case PIXFORMAT_RGB565:
+		hcmr->hdvp->Init.Format = DVP_FORMAT_RGB;
+		break;
+	case PIXFORMAT_YUV422:
+		hcmr->hdvp->Init.Format = DVP_FORMAT_YUY;
+		break;
+	case PIXFORMAT_GRAYSCALE:
+		hcmr->hdvp->Init.Format = DVP_FORMAT_Y;
+		break;
+	case PIXFORMAT_JPEG:
+		hcmr->hdvp->Init.Format = DVP_FORMAT_RGB;
+		break;
+	default:
+		return E_PAR;
+	}
+	dvp_set_image_format(hcmr->hdvp);
+	/* delay n ms */
+	dly_tsk(30);
+	return E_OK;
+}
+
+ER
+ov2640_set_framesize(OV2640_t *hcmr)
+{
+	uint8_t clkrc;
+	uint16_t w = hcmr->_width;
+	uint16_t h = hcmr->_height;
+	int i=0;
+	const uint8_t (*regs)[2];
+
+	if((w <= 800) && (h <= 600)){
+		clkrc =0x80;
+		regs = svga_config;
+//		regs = ov2640_config;
+	}
+	else{
+		clkrc =0x81;
+		regs = uxga_regs;
+	}
+
+	/* Disable DSP */
+	cambus_writeb(hcmr, BANK_SEL, BANK_SEL_DSP);
+	cambus_writeb(hcmr, R_BYPASS, R_BYPASS_DSP_BYPAS);
+
+	/* Set CLKRC */
+	if(clkrc == 0x81){
+		cambus_writeb(hcmr, BANK_SEL, BANK_SEL_SENSOR);
+		cambus_writeb(hcmr, CLKRC, clkrc);
+	}
+
+	/* Write DSP input regsiters */
+	while(regs[i][0]){
+		cambus_writeb(hcmr, regs[i][0], regs[i][1]);
+		i++;
+	}
+
+	 /* Write output width */
+	cambus_writeb(hcmr,0xe0,0x04 ); /* OUTH[8]/OUTW[9:8] */
+	cambus_writeb(hcmr, ZMOW, (w>>2)&0xFF); /* OUTW[7:0] (real/4) */
+	cambus_writeb(hcmr, ZMOH, (h>>2)&0xFF); /* OUTH[7:0] (real/4) */
+	cambus_writeb(hcmr, ZMHH, ((h>>8)&0x04)|((w>>10)&0x03)); /* OUTH[8]/OUTW[9:8] */
+	cambus_writeb(hcmr,0xe0,0x00 ); /* OUTH[8]/OUTW[9:8] */
+
+	/* Enable DSP */
+	cambus_writeb(hcmr, BANK_SEL, BANK_SEL_DSP);
+	cambus_writeb(hcmr, R_BYPASS, R_BYPASS_DSP_EN);
+
+	/* delay n ms */
+	dly_tsk(30);
+	hcmr->hdvp->Init.Width  = w;
+	hcmr->hdvp->Init.Height = h;
+	return dvp_set_image_size(hcmr->hdvp);
+}
+
+
+ER
+ov2640_activate(OV2640_t *hcmr, bool_t run)
+{
+	return dvp_activate(hcmr->hdvp, run);
+}
+
+int
+ov2640_id(OV2640_t *hcmr)
+{
+    return hcmr->_id;
+}
+
+ER
+ov2640_snapshot(OV2640_t *hcmr)
+{
+	DVP_Handle_t *hdvp = hcmr->hdvp;
+	int32_t timeout = SNAPDHOT_TIMEOUT;
+
+	//wait for new frame
+	hdvp->state = DVP_STATE_ACTIVATE;
+
+	while(hdvp->state != DVP_STATE_FINISH){
+		if(--timeout <= 0)
+			return E_TMOUT;
+		if(hdvp->semid != 0)
+			twai_sem(hdvp->semid, 1);
+		else
+			dly_tsk(1);
+	}
+	reverse_u32pixel((uint32_t*)hcmr->_dataBuffer, hcmr->_width * hcmr->_height/2);
+	return E_OK;
+}
+
+ER
+ov2640_cambus_scan_gc0328(OV2640_t *hcmr)
+{
+	uint8_t id;
+
+	dvp_sccb_send_data(hcmr->hdvp, GC0328_ADDR, 0xFE, 0x00);
+	id = dvp_sccb_receive_data(hcmr->hdvp, GC0328_ADDR, 0xf0);
+	if(id != 0x9d){
+		return 0;
+	}
+	return id;
+}
+
+
+ER
+ov2640_setInvert(OV2640_t *hcmr, bool_t invert)
+{
+	uint8_t reg;
+
+	cambus_readb(hcmr, BANK_SEL, &reg);
+	cambus_writeb(hcmr, BANK_SEL, reg | BANK_SEL_SENSOR);
+	cambus_readb(hcmr, REG04, &reg);
+
+	if(invert){
+		reg |= REG04_HFLIP_IMG;
+	}
+	else{
+		reg &= ~REG04_HFLIP_IMG;
+	}
+	cambus_writeb(hcmr, REG04, reg);
+    return E_OK;
+}
+
+ER
+ov2640_set_contrast(OV2640_t *hcmr, int level)
+{
+	int i;
+
+	level += (NUM_CONTRAST_LEVELS / 2 + 1);
+	if(level < 0 || level > NUM_CONTRAST_LEVELS){
+		return E_PAR;
+	}
+
+	/* Switch to DSP register bank */
+	cambus_writeb(hcmr, BANK_SEL, BANK_SEL_DSP);
+
+	/* Write contrast registers */
+    for(i = 0 ; i < sizeof(contrast_regs[0])/sizeof(contrast_regs[0][0]) ; i++){
+		cambus_writeb(hcmr, contrast_regs[0][i], contrast_regs[level][i]);
+	}
+	return E_OK;
+}
+
+ER
+ov2640_set_brightness(OV2640_t *hcmr, int level)
+{
+	int i;
+
+	level += (NUM_BRIGHTNESS_LEVELS / 2 + 1);
+	if(level < 0 || level > NUM_BRIGHTNESS_LEVELS){
+		return E_PAR;
+	}
+
+	/* Switch to DSP register bank */
+	cambus_writeb(hcmr, BANK_SEL, BANK_SEL_DSP);
+
+	/* Write brightness registers */
+	for(i = 0 ; i < sizeof(brightness_regs[0])/sizeof(brightness_regs[0][0]) ; i++){
+		cambus_writeb(hcmr, brightness_regs[0][i], brightness_regs[level][i]);
+	}
+	return E_OK;
+}
+
+ER
+ov2640_set_saturation(OV2640_t *hcmr, int level)
+{
+	int i;
+
+	level += (NUM_SATURATION_LEVELS / 2 + 1);
+	if(level < 0 || level > NUM_SATURATION_LEVELS){
+		return E_PAR;
+	}
+
+	/* Switch to DSP register bank */
+	cambus_writeb(hcmr, BANK_SEL, BANK_SEL_DSP);
+
+	/* Write contrast registers */
+	for(i = 0 ; i < sizeof(saturation_regs[0])/sizeof(saturation_regs[0][0]) ; i++){
+		cambus_writeb(hcmr, saturation_regs[0][i], saturation_regs[level][i]);
+	}
+	return E_OK;
+}
+
+ER
+ov2640_set_gainceiling(OV2640_t *hcmr, gainceiling_t gainceiling)
+{
+	/* Switch to SENSOR register bank */
+	cambus_writeb(hcmr, BANK_SEL, BANK_SEL_SENSOR);
+
+	/* Write gain ceiling register */
+	cambus_writeb(hcmr, COM9, COM9_AGC_SET(gainceiling));
+	return E_OK;
+}
+
+ER
+ov2640_set_quality(OV2640_t *hcmr, int qs)
+{
+	/* Switch to DSP register bank */
+	cambus_writeb(hcmr, BANK_SEL, BANK_SEL_DSP);
+
+	/* Write QS register */
+	cambus_writeb(hcmr, QS, qs);
+	return E_OK;
+}
+
+ER
+ov2640_set_colorbar(OV2640_t *hcmr, bool_t enable)
+{
+	uint8_t reg;
+
+    /* Switch to SENSOR register bank */
+	cambus_writeb(hcmr, BANK_SEL, BANK_SEL_SENSOR);
+
+	/* Update COM7 */
+	cambus_readb(hcmr, COM7, &reg);
+
+	if(enable){
+		reg |= COM7_COLOR_BAR;
+	}
+	else{
+		reg &= ~COM7_COLOR_BAR;
+	}
+	cambus_writeb(hcmr, COM7, reg);
+	return E_OK;
+}
+
+ER
+ov2640_set_auto_exposure(OV2640_t *hcmr, bool_t enable, int exposure_us)
+{
+	uint32_t freq = hcmr->hdvp->Init.Freq;
+	uint8_t reg;
+	int ret = 0;
+
+	cambus_readb(hcmr, BANK_SEL, &reg);
+	cambus_writeb(hcmr, BANK_SEL, reg | BANK_SEL_SENSOR);
+	cambus_readb(hcmr, COM8, &reg);
+	cambus_writeb(hcmr, COM8, COM8_SET_AEC(reg, enable));
+
+	if((!enable) && (exposure_us >= 0)){
+		int t_line = 0;
+		int pll_mult, clk_rc, exposure;
+		int t_pclk = 0;
+		cambus_readb(hcmr, COM7, &reg);
+
+		if (COM7_GET_RES(reg) == COM7_RES_UXGA) t_line = 1600 + 322;
+		if (COM7_GET_RES(reg) == COM7_RES_SVGA) t_line = 800 + 390;
+		if (COM7_GET_RES(reg) == COM7_RES_CIF) t_line = 400 + 195;
+
+		ret |= cambus_readb(hcmr, CLKRC, &reg);
+		pll_mult = (reg & CLKRC_DOUBLE) ? 2 : 1;
+		clk_rc = ((reg & CLKRC_DIVIDER_MASK) + 1) * 2;
+
+		ret |= cambus_readb(hcmr, BANK_SEL, &reg);
+		cambus_writeb(hcmr, BANK_SEL, reg & (~BANK_SEL_SENSOR));
+		ret |= cambus_readb(hcmr, IMAGE_MODE, &reg);
+
+		if (IMAGE_MODE_GET_FMT(reg) == IMAGE_MODE_YUV422) t_pclk = 2;
+		if (IMAGE_MODE_GET_FMT(reg) == IMAGE_MODE_RAW10) t_pclk = 1;
+		if (IMAGE_MODE_GET_FMT(reg) == IMAGE_MODE_RGB565) t_pclk = 2;
+
+		exposure = IM_MAX(IM_MIN(((exposure_us*(((freq/clk_rc)*pll_mult)/1000000))/t_pclk)/t_line,0xFFFF),0x0000);
+
+		ret |= cambus_readb(hcmr, BANK_SEL, &reg);
+		cambus_writeb(hcmr, BANK_SEL, reg | BANK_SEL_SENSOR);
+
+		ret |= cambus_readb(hcmr, REG04, &reg);
+		cambus_writeb(hcmr, REG04, (reg & 0xFC) | ((exposure >> 0) & 0x3));
+
+		ret |= cambus_readb(hcmr, AEC, &reg);
+		cambus_writeb(hcmr, AEC, (reg & 0x00) | ((exposure >> 2) & 0xFF));
+
+		ret |= cambus_readb(hcmr, REG04, &reg);
+		cambus_writeb(hcmr, REG04, (reg & 0xC0) | ((exposure >> 10) & 0x3F));
+	}
+	if(ret == 0)
+		return E_OK;
+	else
+		return E_SYS;
+}
+
+ER
+ov2640_get_exposure_us(OV2640_t *hcmr, int *exposure_us)
+{
+	uint32_t freq = hcmr->hdvp->Init.Freq;
+	uint8_t reg, aec_10, aec_92, aec_1510;
+	int t_line = 0;
+	int t_pclk = 0;
+	int pll_mult, clk_rc;
+	uint16_t exposure;
+	int ret = cambus_readb(hcmr, BANK_SEL, &reg);
+
+	cambus_writeb(hcmr, BANK_SEL, reg | BANK_SEL_SENSOR);
+	ret |= cambus_readb(hcmr, COM8, &reg);
+
+    // DISABLED
+    // if (reg & COM8_AEC_EN) {
+    //     ret |= cambus_writeb(_slaveAddr, COM8, reg & (~COM8_AEC_EN));
+    // }
+    // DISABLED
+
+	ret |= cambus_readb(hcmr, REG04, &aec_10);
+	ret |= cambus_readb(hcmr, AEC, &aec_92);
+	ret |= cambus_readb(hcmr, REG45, &aec_1510);
+
+    // DISABLED
+    // if (reg & COM8_AEC_EN) {
+    //     ret |= cambus_writeb(_slaveAddr, COM8, reg | COM8_AEC_EN);
+    // }
+    // DISABLED
+
+	ret |= cambus_readb(hcmr, COM7, &reg);
+
+	if (COM7_GET_RES(reg) == COM7_RES_UXGA) t_line = 1600 + 322;
+	if (COM7_GET_RES(reg) == COM7_RES_SVGA) t_line = 800 + 390;
+	if (COM7_GET_RES(reg) == COM7_RES_CIF) t_line = 400 + 195;
+
+	ret |= cambus_readb(hcmr, CLKRC, &reg);
+	pll_mult = (reg & CLKRC_DOUBLE) ? 2 : 1;
+	clk_rc = ((reg & CLKRC_DIVIDER_MASK) + 1) * 2;
+
+	ret |= cambus_readb(hcmr, BANK_SEL, &reg);
+	cambus_writeb(hcmr, BANK_SEL, reg & (~BANK_SEL_SENSOR));
+	ret |= cambus_readb(hcmr, IMAGE_MODE, &reg);
+
+	if (IMAGE_MODE_GET_FMT(reg) == IMAGE_MODE_YUV422) t_pclk = 2;
+	if (IMAGE_MODE_GET_FMT(reg) == IMAGE_MODE_RAW10) t_pclk = 1;
+	if (IMAGE_MODE_GET_FMT(reg) == IMAGE_MODE_RGB565) t_pclk = 2;
+
+	exposure = ((aec_1510 & 0x3F) << 10) + ((aec_92 & 0xFF) << 2) + ((aec_10 & 0x3) << 0);
+	*exposure_us = (exposure*t_line*t_pclk)/(((freq/clk_rc)*pll_mult)/1000000);
+	if(ret == 0)
+		return E_OK;
+	else
+		return E_SYS;
+}
+
+ER
+ov2640_set_auto_whitebal(OV2640_t *hcmr, bool_t enable, float r_gain_db, float g_gain_db, float b_gain_db)
+{
+	uint8_t reg;
+	int ret = cambus_readb(hcmr, BANK_SEL, &reg);
+	cambus_writeb(hcmr, BANK_SEL, reg & (~BANK_SEL_SENSOR));
+	ret |= cambus_readb(hcmr, CTRL1, &reg);
+	cambus_writeb(hcmr, CTRL1, (reg & (~CTRL1_AWB)) | (enable ? CTRL1_AWB : 0));
+
+	if((!enable) && (!isnanf(r_gain_db)) && (!isnanf(g_gain_db)) && (!isnanf(b_gain_db))
+                      && (!isinff(r_gain_db)) && (!isinff(g_gain_db)) && (!isinff(b_gain_db))) {
+    }
+	if(ret == 0)
+		return E_OK;
+	else
+		return E_SYS;
+}
+
+ER
+ov2640_set_vflip(OV2640_t *hcmr, bool_t enable)
+{
+	uint8_t reg;
+	int ret = cambus_readb(hcmr, BANK_SEL, &reg);
+	cambus_writeb(hcmr, BANK_SEL, reg | BANK_SEL_SENSOR);
+	ret |= cambus_readb(hcmr, REG04, &reg);
+
+	if(enable){
+		reg |= REG04_VFLIP_IMG;
+		reg |= REG04_VREF_EN;
+	}
+	else{
+		reg &= ~REG04_VFLIP_IMG;
+		reg &= ~REG04_VREF_EN;
+	}
+	cambus_writeb(hcmr, REG04, reg);
+	if(ret == 0)
+		return E_OK;
+	else
+		return E_SYS;
+}
+
+#ifdef USE_GAIN
+ER
+ov2640_set_auto_gain(OV2640_t *hcmr, bool_t enable, float gain_db, float gain_db_ceiling)
+{
+	uint8_t reg;
+
+	cambus_readb(hcmr, BANK_SEL, &reg);
+	cambus_writeb(hcmr, BANK_SEL, reg | BANK_SEL_SENSOR);
+	cambus_readb(hcmr, COM8, &reg);
+	cambus_writeb(hcmr, COM8, (reg & (~COM8_AGC_EN)) | ((enable != 0) ? COM8_AGC_EN : 0));
+
+	if((!enable) && (!isnanf(gain_db)) && (!isinff(gain_db))){
+		float gain = IM_MAX(IM_MIN(expf((gain_db / 20.0) * log(10.0)), 32.0), 1.0);
+		int gain_temp = roundf(log2(IM_MAX(gain / 2.0, 1.0)));
+		int gain_hi = 0xF >> (4 - gain_temp);
+		int gain_lo = IM_MIN(roundf(((gain / (1 << gain_temp)) - 1.0) * 16.0), 15);
+
+		cambus_writeb(hcmr, GAIN, (gain_hi << 4) | (gain_lo << 0));
+	}
+	else if(enable && (!isnanf(gain_db_ceiling)) && (!isinff(gain_db_ceiling))){
+		float gain_ceiling = IM_MAX(IM_MIN(expf((gain_db_ceiling / 20.0) * log(10.0)), 128.0), 2.0);
+
+		cambus_readb(hcmr, COM9, &reg);
+		cambus_writeb(hcmr, COM9, (reg & 0x1F) | (((int)ceilf(log2(gain_ceiling)) - 1) << 5));
+	}
+	return E_OK;
+}
+
+ER
+ov2640_get_gain_db(OV2640_t *hcmr, float *gain_db)
+{
+    uint8_t reg, gain;
+	int hi_gain;
+	float lo_gain;
+
+	cambus_readb(hcmr, BANK_SEL, &reg);
+	cambus_writeb(hcmr, BANK_SEL, reg | BANK_SEL_SENSOR);
+	cambus_readb(hcmr, COM8, &reg);
+
+    // DISABLED
+    // if (reg & COM8_AGC_EN) {
+    //     ret |= cambus_writeb(_slaveAddr, COM8, reg & (~COM8_AGC_EN));
+    // }
+    // DISABLED
+
+	cambus_readb(hcmr, GAIN, &gain);
+
+    // DISABLED
+    // if (reg & COM8_AGC_EN) {
+    //     ret |= cambus_writeb(_slaveAddr, COM8, reg | COM8_AGC_EN);
+    // }
+    // DISABLED
+
+	hi_gain = 1 << (((gain >> 7) & 1) + ((gain >> 6) & 1) + ((gain >> 5) & 1) + ((gain >> 4) & 1));
+	lo_gain = 1.0 + (((gain >> 0) & 0xF) / 16.0);
+	*gain_db = 20.0 * (log(hi_gain * lo_gain) / log(10.0));
+	return E_OK;
+}
+#endif	/* USE_GAIN */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/sipeed_ov2640/sipeed_ov2640.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/sipeed_ov2640/sipeed_ov2640.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/sipeed_ov2640/sipeed_ov2640.h	(revision 453)
@@ -0,0 +1,188 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ *
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+ *
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ *
+ *  $Id$
+ */
+/*
+ *  SIPEED OV2640 CAMARE制御プログラムのヘッダファイル
+ */
+
+#ifndef _SIPEED_OV2640_H_
+#define _SIPEED_OV2640_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include "kernel.h"
+#include "dvp.h"
+
+#define OV9650_ID       (0x96)
+#define OV2640_ID       (0x26)
+#define OV7725_ID       (0x77)
+#define MT9V034_ID      (0x13)
+#define LEPTON_ID       (0x54)
+#define OV_CHIP_ID      (0x0A)
+#define ON_CHIP_ID      (0x00)
+#define GC0328_ID       (0x9d)
+#define GC0328_ADDR     (0x42)
+
+#ifndef TOPPERS_MACRO_ONLY
+
+typedef enum {
+    FRAMESIZE_INVALID = 0,
+    // C/SIF Resolutions
+    FRAMESIZE_QQCIF,    // 88x72
+    FRAMESIZE_QCIF,     // 176x144
+    FRAMESIZE_CIF,      // 352x288
+    FRAMESIZE_QQSIF,    // 88x60
+    FRAMESIZE_QSIF,     // 176x120
+    FRAMESIZE_SIF,      // 352x240
+    // VGA Resolutions
+    FRAMESIZE_QQQQVGA,  // 40x30
+    FRAMESIZE_QQQVGA,   // 80x60
+    FRAMESIZE_QQVGA,    // 160x120
+    FRAMESIZE_QVGA,     // 320x240
+    FRAMESIZE_VGA,      // 640x480
+    FRAMESIZE_HQQQVGA,  // 60x40
+    FRAMESIZE_HQQVGA,   // 120x80
+    FRAMESIZE_HQVGA,    // 240x160
+    // FFT Resolutions
+    FRAMESIZE_64X32,    // 64x32
+    FRAMESIZE_64X64,    // 64x64
+    FRAMESIZE_128X64,   // 128x64
+    FRAMESIZE_128X128,  // 128x128
+    // Other
+    FRAMESIZE_LCD,      // 128x160
+    FRAMESIZE_QQVGA2,   // 128x160
+    FRAMESIZE_WVGA,     // 720x480
+    FRAMESIZE_WVGA2,    // 752x480
+    FRAMESIZE_SVGA,     // 800x600
+    FRAMESIZE_SXGA,     // 1280x1024
+    FRAMESIZE_UXGA,     // 1600x1200
+    FRAMESIZE_CUSTOM,
+} framesize_t;
+
+
+typedef enum {
+    PIXFORMAT_INVLAID = 0,
+    PIXFORMAT_BAYER,     // RAW
+    PIXFORMAT_RGB565,    // RGB565
+    PIXFORMAT_YUV422,    // YUV422
+    PIXFORMAT_GRAYSCALE, // GRAYSCALE
+    PIXFORMAT_JPEG,      // JPEG/COMPRESSED
+} pixformat_t;
+
+
+
+typedef enum {
+    GAINCEILING_2X,
+    GAINCEILING_4X,
+    GAINCEILING_8X,
+    GAINCEILING_16X,
+    GAINCEILING_32X,
+    GAINCEILING_64X,
+    GAINCEILING_128X,
+} gainceiling_t;
+
+typedef enum {
+    FRAMERATE_2FPS =0x9F,
+    FRAMERATE_8FPS =0x87,
+    FRAMERATE_15FPS=0x83,
+    FRAMERATE_30FPS=0x81,
+    FRAMERATE_60FPS=0x80,
+} framerate_t;
+
+typedef enum {
+    ACTIVE_LOW,
+    ACTIVE_HIGH,
+    ACTIVE_BINOCULAR,
+} polarity_t;
+
+typedef struct _OV2640_s {
+	DVP_Handle_t    *hdvp;
+	framesize_t     frameSize;
+	pixformat_t     pixFormat;
+
+	uint16_t        _width;
+	uint16_t        _height;
+	uint8_t         _id;
+	uint32_t        *_dataBuffer;
+	uint32_t        *_aiBuffer;
+	uint16_t        _resetPoliraty;
+	uint16_t        _pwdnPoliraty;
+	uint32_t        _slaveAddr;
+} OV2640_t;
+
+extern void ov2640_getResolition(OV2640_t *hcmr, framesize_t frameSize);
+extern ER ov2640_sensor_ov_detect(OV2640_t *hcmr);
+extern ER ov2640_sensro_gc_detect(OV2640_t *hcmr);
+extern ER ov2640_reset(OV2640_t *hcmr);
+extern ER ov2640_set_pixformat(OV2640_t *hcmr);
+extern ER ov2640_set_framesize(OV2640_t *hcmr);
+extern ER ov2640_activate(OV2640_t *hcmr, bool_t run);
+extern ER ov2640_snapshot(OV2640_t *hcmr);
+extern ER ov2640_cambus_scan_gc0328(OV2640_t *hcmr);
+extern int ov2640_id(OV2640_t *hcmr);
+
+extern ER ov2640_setInvert(OV2640_t *hcmr, bool_t invert);
+extern ER ov2640_set_contrast(OV2640_t *hcmr, int level);
+extern ER ov2640_set_brightness(OV2640_t *hcmr, int level);
+extern ER ov2640_set_saturation(OV2640_t *hcmr, int level);
+extern ER ov2640_set_gainceiling(OV2640_t *hcmr, gainceiling_t gainceiling);
+extern ER ov2640_set_quality(OV2640_t *hcmr, int qs);
+extern ER ov2640_set_colorbar(OV2640_t *hcmr, bool_t enable);
+extern ER ov2640_set_auto_exposure(OV2640_t *hcmr, bool_t enable, int exposure_us);
+extern ER ov2640_get_exposure_us(OV2640_t *hcmr, int *exposure_us);
+extern ER ov2640_set_auto_whitebal(OV2640_t *hcmr, bool_t enable, float r_gain_db, float g_gain_db, float b_gain_db);
+extern ER ov2640_set_vflip(OV2640_t *hcmr, bool_t enable);
+#ifdef USE_GAIN
+extern ER ov2640_set_auto_gain(OV2640_t *hcmr, bool_t enable, float gain_db, float gain_db_ceiling);
+extern ER ov2640_get_gain_db(OV2640_t *hcmr, float *gain_db);
+#endif	/* USE_GAIN */
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _SIPEED_OV2640_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/sipeed_st7789/Makefile.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/sipeed_st7789/Makefile.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/sipeed_st7789/Makefile.config	(revision 453)
@@ -0,0 +1,55 @@
+#
+#   TOPPERS/ASP/FMP Kernel
+#       Toyohashi Open Platform for Embedded Real-Time Systems/
+#       Advanced Standard Profile Kernel
+#
+#   Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                               Toyohashi Univ. of Technology, JAPAN
+#   Copyright (C) 2003-2008 by Ryosuke Takeuchi
+#                Platform Development Center RICOH COMPANY,LTD. JAPAN
+#   Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+ 
+#
+#  Makefile のプロセッサ依存 (sipeed st7789:LCD用)
+#
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/gdic/sipeed_st7789
+
+#
+#  SIPEED ST7789 LCD DRIVER(GDIC)に関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR):$(SRCDIR)/gdic/sipeed_st7789
+SYSSVC_COBJS := $(SYSSVC_COBJS) sipeed_st7789.o 
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/sipeed_st7789/glcd_core.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/sipeed_st7789/glcd_core.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/sipeed_st7789/glcd_core.h	(revision 453)
@@ -0,0 +1,45 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+#ifndef _LCD_CORE_H_
+#define _LCD_CORE_H_
+
+#include "sipeed_st7789.h"
+
+#endif /* _LCD_CORE_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/sipeed_st7789/sipeed_st7789.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/sipeed_st7789/sipeed_st7789.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/sipeed_st7789/sipeed_st7789.c	(revision 453)
@@ -0,0 +1,656 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2012 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+/* 
+ *  SIPEED ST7789 2.4"LCD制御プログラムの本体
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <target_syssvc.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#include "sipeed_st7789.h"
+
+/*
+ *  サービスコールのエラーのログ出力
+ */
+Inline void
+svc_perror(const char *file, int_t line, const char *expr, ER ercd)
+{
+	if (ercd < 0) {
+		t_perror(LOG_ERROR, file, line, expr, ercd);
+	}
+}
+
+#define	SVC_PERROR(expr)	svc_perror(__FILE__, __LINE__, #expr, (expr))
+#define ABS(X)  ((X) > 0 ? (X) : -(X))
+
+#ifndef SPI_CORE_WAIT_TIME
+#define SPI_CORE_WAIT_TIME  500
+#endif
+
+#define PORT_HIGH           1
+#define PORT_LOW            0
+
+#define MAX_BUFFER          8
+
+static uint32_t aTxBuffer[MAX_BUFFER];
+
+
+static void set_dcx_control(LCD_Handler_t *hlcd)
+{
+    gpio_set_pin(TADR_GPIO_BASE, hlcd->dcx_no, PORT_LOW);
+}
+
+static void set_dcx_data(LCD_Handler_t *hlcd)
+{
+    gpio_set_pin(TADR_GPIO_BASE, hlcd->dcx_no, PORT_HIGH);
+}
+
+/*
+ *  LCDへのコマンド送信関数
+ */
+ER
+lcd_writecommand(LCD_Handler_t *hlcd, uint8_t c)
+{
+	SPI_Handle_t *hspi = hlcd->hspi;
+	ER ercd = E_OK;
+
+	aTxBuffer[0] = c;
+    set_dcx_control(hlcd);
+	hspi->Init.DataSize = 8;
+	hspi->Init.InstLength = 8;
+	hspi->Init.AddrLength = 0;
+    ercd = spi_core_transmit(hspi, hlcd->cs_sel, (uint8_t *)(aTxBuffer), 1);
+#if SPI_WAIT_TIME == 0
+	if(ercd == E_OK)
+		ercd = spi_wait(hspi, SPI_CORE_WAIT_TIME);
+#endif
+	return ercd;
+}
+
+/*
+ *  LCDへのデータ送信関数
+ */
+ER
+lcd_writebyte(LCD_Handler_t *hlcd, uint8_t *buf, uint8_t len)
+{
+	SPI_Handle_t *hspi = hlcd->hspi;
+	uint32_t i;
+	ER ercd = E_OK;
+
+	if(len >= MAX_BUFFER)
+		return E_PAR;
+	for(i = 0 ; i < len ; i++)
+		aTxBuffer[i] = buf[i];
+
+    set_dcx_data(hlcd);
+	hspi->Init.DataSize = 8;
+	hspi->Init.InstLength = 8;
+	hspi->Init.AddrLength = 0;
+	ercd = spi_core_transmit(hspi, hlcd->cs_sel, (uint8_t *)aTxBuffer, len);
+#if SPI_WAIT_TIME == 0
+	if(ercd == E_OK)
+		ercd = spi_wait(hspi, SPI_CORE_WAIT_TIME);
+#endif
+	return ercd;
+}
+
+ER
+lcd_writebyte2(LCD_Handler_t *hlcd, uint8_t *buf, uint8_t len)
+{
+	SPI_Handle_t *hspi = hlcd->hspi;
+	ER ercd = E_OK;
+
+    set_dcx_data(hlcd);
+	hspi->Init.DataSize = 8;
+	hspi->Init.InstLength = 8;
+	hspi->Init.AddrLength = 0;
+	ercd = spi_core_transmit(hspi, hlcd->cs_sel, buf, len);
+#if SPI_WAIT_TIME == 0
+	if(ercd == E_OK)
+		ercd = spi_wait(hspi, SPI_CORE_WAIT_TIME);
+#endif
+	return ercd;
+}
+
+/*
+ *  LCDへの16ビットデータ転送
+ */
+ER
+lcd_writehalf(LCD_Handler_t *hlcd, uint32_t *buf, int cnt)
+{
+	SPI_Handle_t *hspi = hlcd->hspi;
+	ER ercd = E_OK;
+
+    set_dcx_data(hlcd);
+	hspi->Init.DataSize = 16;
+	hspi->Init.InstLength = 16;
+	hspi->Init.AddrLength = 0;
+	ercd = spi_core_transmit(hspi, hlcd->cs_sel, (uint8_t *)buf, cnt);
+#if SPI_WAIT_TIME == 0
+	if(ercd == E_OK)
+		ercd = spi_wait(hspi, SPI_CORE_WAIT_TIME);
+#endif
+	return ercd;
+}
+
+/*
+ *  LCD32ビットフィル
+ */
+ER
+lcd_filldata(LCD_Handler_t *hlcd, uint32_t *data_buf, uint32_t len)
+{
+	SPI_Handle_t *hspi = hlcd->hspi;
+	ER ercd = E_OK;
+
+    set_dcx_data(hlcd);
+	hspi->Init.DataSize = 32;
+	hspi->Init.InstLength = 0;
+	hspi->Init.AddrLength = 32;
+	ercd = spi_core_transmit_fill(hspi, hlcd->cs_sel, data_buf, len);
+#if SPI_WAIT_TIME == 0
+	if(ercd == E_OK)
+		spi_wait(hspi, SPI_CORE_WAIT_TIME);
+#endif
+	return ercd;
+}
+
+/*
+ *   SIPEED LCD初期化
+ */
+void lcd_init(LCD_Handler_t *hlcd)
+{
+	GPIO_Init_t init = {0};
+    uint8_t data = 0;
+
+	/*
+	 *  DCXピン初期化
+	 */
+	fpioa_set_function(hlcd->dcx_pin , FUNC_GPIO0 + hlcd->dcx_no);
+	init.mode = GPIO_MODE_OUTPUT;
+	init.pull = GPIO_PULLDOWN;
+    gpio_setup(TADR_GPIO_BASE, &init, hlcd->dcx_no);
+    gpio_set_pin(TADR_GPIO_BASE, hlcd->dcx_no, PORT_HIGH);
+
+	/*
+	 *  LCDリセット
+	 */
+	if(hlcd->rst_pin >= 0){
+		fpioa_set_function(hlcd->rst_pin , FUNC_GPIO0 + hlcd->rst_no);
+		init.mode = GPIO_MODE_OUTPUT;
+		init.pull = GPIO_PULLDOWN;
+		gpio_setup(TADR_GPIO_BASE, &init, hlcd->rst_no);
+		gpio_set_pin(TADR_GPIO_BASE, hlcd->rst_no, PORT_HIGH);
+
+	    gpio_set_pin(TADR_GPIO_BASE, hlcd->rst_no, 0);
+	    gpio_set_pin(TADR_GPIO_BASE, hlcd->rst_no, 1);
+	}
+
+	/*
+	 *  soft reset
+	 */
+	lcd_writecommand(hlcd, SOFTWARE_RESET);
+	dly_tsk(100);
+	/*
+	 *  exit sleep
+	 */
+	lcd_writecommand(hlcd, SLEEP_OFF);
+	dly_tsk(100);
+	/*
+	 *  pixel format
+	 */
+	lcd_writecommand(hlcd, PIXEL_FORMAT_SET);
+	data = 0x55;
+    lcd_writebyte(hlcd, &data, 1);
+	if(hlcd->dir & DIR_XY_MASK){
+		hlcd->_width = ST7789_TFTHEIGHT;
+		hlcd->_height = ST7789_TFTWIDTH;
+	}
+	else{
+		hlcd->_width = ST7789_TFTWIDTH;
+		hlcd->_height = ST7789_TFTHEIGHT;
+	}
+	hlcd->colstart = 0;
+	hlcd->rowstart = 0;
+
+	lcd_writecommand(hlcd, MEMORY_ACCESS_CTL);
+    lcd_writebyte(hlcd, (uint8_t *)&hlcd->dir, 1);
+
+	/*
+	 *  display on
+	 */
+	lcd_writecommand(hlcd, DISPALY_ON);
+	hlcd->mode = 1;
+}
+
+/*
+ *  表示ウィンドウ設定
+ */
+void
+lcd_setAddrWindow(LCD_Handler_t *hlcd,  uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
+{
+    uint8_t data[4] = {0};
+
+    data[0] = (uint8_t)(x0 >> 8);
+    data[1] = (uint8_t)(x0);
+    data[2] = (uint8_t)(x1 >> 8);
+    data[3] = (uint8_t)(x1);
+	lcd_writecommand(hlcd, HORIZONTAL_ADDRESS_SET);
+    lcd_writebyte(hlcd, data, 4);
+
+    data[0] = (uint8_t)(y0 >> 8);
+    data[1] = (uint8_t)(y0);
+    data[2] = (uint8_t)(y1 >> 8);
+    data[3] = (uint8_t)(y1);
+	lcd_writecommand(hlcd, VERTICAL_ADDRESS_SET);
+    lcd_writebyte(hlcd, data, 4);
+
+	SVC_PERROR(lcd_writecommand(hlcd, MEMORY_WRITE));
+}
+
+/*
+ *  RECTANGLEのフィル描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: start X position
+ *  param3  y: start Y position
+ *  param4  w: width
+ *  param5  h: height
+ *  param6  color: color value
+ */
+void
+lcd_fillRect(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t w, int16_t h, color_t color)
+{
+    uint32_t data = ((uint32_t)color << 16) | (uint32_t)color;
+	// rudimentary clipping (drawChar w/big text requires this)
+	if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
+	if((x + w - 1) >= hlcd->_width)  w = hlcd->_width  - x;
+	if((y + h - 1) >= hlcd->_height) h = hlcd->_height - y;
+
+	lcd_setAddrWindow(hlcd, x, y, x+w-1, y+h-1);
+    SVC_PERROR(lcd_filldata(hlcd, &data, (h*w+1)/2));
+}
+
+/*
+ *  PIXEL描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: X position
+ *  param3  y: Y position
+ *  param4  color: color value
+ */
+void
+lcd_drawPixel(LCD_Handler_t *hlcd, int16_t x, int16_t y, color_t color)
+{
+	uint32_t data = color;
+    lcd_setAddrWindow(hlcd, x, y, x, y);
+	SVC_PERROR(lcd_writehalf(hlcd, &data, 1));
+}
+
+/*
+ *  垂直方向LINEの高速描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: start X position
+ *  param3  y: start Y position
+ *  param4  h: height
+ *  param5  color: color value
+ */
+void
+lcd_drawFastVLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t h, color_t color)
+{
+    uint32_t data = ((uint32_t)color << 16) | (uint32_t)color;
+	// Rudimentary clipping
+	if(h == 0) return;
+	if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
+	if((y+h-1) >= hlcd->_height) h = hlcd->_height-y;
+	lcd_setAddrWindow(hlcd, x, y, x, y+h-1);
+    SVC_PERROR(lcd_filldata(hlcd, &data, (h+1)/2));
+}
+
+/*
+ *  水平方向LINEの高速描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: start X position
+ *  param3  y: start Y position
+ *  param4  w: width
+ *  param5  color: color value
+ */
+void lcd_drawFastHLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t w, color_t color)
+{
+    uint32_t data = ((uint32_t)color << 16) | (uint32_t)color;
+	// Rudimentary clipping
+	if(w == 0) return;
+	if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
+	if((x+w-1) >= hlcd->_width)  w = hlcd->_width-x;
+	lcd_setAddrWindow(hlcd, x, y, x+w-1, y);
+    SVC_PERROR(lcd_filldata(hlcd, &data, (w+1)/2));
+}
+
+/*
+ *  DRAW IMAGE LINE描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: X position
+ *  param3  y: Y position
+ *  param4  w: width
+ *  param5  pcolor: color value
+ */
+void
+lcd_drawImageHLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, uint16_t w, uint32_t *pcolor)
+{
+	if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
+	if((x+w-1) >= hlcd->_width)  w = hlcd->_width-x;
+	lcd_setAddrWindow(hlcd, x, y, x+w-1, y);
+	SVC_PERROR(lcd_writehalf(hlcd, pcolor, w));
+}
+
+/*
+ *  BITMAP描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x0: Bmp X position in the LCD
+ *  param3  y0: Bmp Y position in the LCD
+ *  param4  pbmp: Pointer to Bmp picture address in the internal Flash
+ */
+void
+lcd_drawBitmap(LCD_Handler_t *hlcd, uint16_t x0, uint16_t y0, uint8_t *pbmp)
+{
+	uint32_t index = 0, width = 0, height = 0, bit_pixel = 0;
+	uint32_t input_color_mode = 0;
+	uint32_t i;
+
+	/* Get bitmap data address offset */
+	index = *(uint16_t *) (pbmp + 10);
+	index |= (*(uint16_t *) (pbmp + 12)) << 16;
+
+	/* Read bitmap width */
+	width = *(uint16_t *) (pbmp + 18);
+	width |= (*(uint16_t *) (pbmp + 20)) << 16;
+
+	/* Read bitmap height */
+	height = *(uint16_t *) (pbmp + 22);
+	height |= (*(uint16_t *) (pbmp + 24)) << 16;
+
+	/* Read bit/pixel */
+	bit_pixel = *(uint16_t *) (pbmp + 28);
+
+	/* Get the layer pixel format */
+	if ((bit_pixel/8) == 4){
+		input_color_mode = CM_ARGB8888;
+	}
+	else if ((bit_pixel/8) == 2){
+		input_color_mode = CM_RGB565;
+	}
+	else{
+		input_color_mode = CM_RGB888;
+	}
+
+	/* Bypass the bitmap header */
+	pbmp += (index + (width * (height - 1) * (bit_pixel/8)));  
+	syslog_4(LOG_NOTICE, "## input_color_mode(%d) width(%d) height(%d) bit_pixel(%d) ##", input_color_mode, width, height, bit_pixel);
+	for(index=0; index < height; index++){
+		uint8_t *p = pbmp;
+		color_t color;
+		for (i = 0; i < width; i++){
+			color  = ((p[0] & 0xf8) | (p[1] >> 5)) << 8;
+			color  |= ((p[1] << 3) & 0xE0) | ((p[2] >> 3) & 0x1F);
+			lcd_drawPixel(hlcd, x0+i, y0+index, color);
+			p += 3;
+		}
+		pbmp -= width*3;
+	}
+}
+
+/*
+ *  PICTURE描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: Picture X position in the LCD
+ *  param3  y: Picture Y position in the LCD
+ *  param4  width:  Picture width
+ *  param5  height: Picture heigth
+ *  param6  pbmp: Pointer to picture address in the internal Flash
+ */
+void
+lcd_drawPicture(LCD_Handler_t *hlcd, uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t *pbmp)
+{
+	SPI_Handle_t *hspi = hlcd->hspi;
+	ER ercd = E_OK;
+
+	if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
+	if((x+width-1) > hlcd->_width)  return;
+	if((y+height-1) > hlcd->_height)  return;
+
+	lcd_setAddrWindow(hlcd, x, y, x+width-1, y+height-1);
+    set_dcx_data(hlcd);
+	hspi->Init.DataSize = 32;
+	hspi->Init.InstLength = 0;
+	hspi->Init.AddrLength = 32;
+	ercd = spi_core_transmit(hspi, hlcd->cs_sel, (uint8_t *)pbmp, width * height / 2);
+#if SPI_WAIT_TIME == 0
+	if(ercd == E_OK)
+		spi_wait(hspi, SPI_CORE_WAIT_TIME);
+#endif
+	(void)(ercd);
+}
+
+/*
+ *  INVERT DISPLAY
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  i: invert value
+ */
+void
+lcd_invertDisplay(LCD_Handler_t *hlcd, bool_t i)
+{
+	lcd_writecommand(hlcd, (i ? INVERSION_DISPALY_ON : INVERSION_DISPALY_OFF));
+}
+
+
+/*
+ *  スクリーンフィル
+ *  param1  pDrawProp: Pointer to Draw Prop
+ */
+void
+lcd_fillScreen(LCD_DrawProp_t *pDrawProp)
+{
+	lcd_fillRect(pDrawProp->hlcd, 0, 0,  pDrawProp->hlcd->_width, pDrawProp->hlcd->_height, pDrawProp->BackColor);
+}
+
+/*
+ *  RECTANGLE描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x: left X position
+ *  param3  y: top Y position
+ *  param4  w: width
+ *  param5  h: height
+ */
+void
+lcd_drawRect(LCD_DrawProp_t *pDrawProp, int16_t x, int16_t y, int16_t w, int16_t h)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	color_t color;
+
+	// rudimentary clipping (drawChar w/big text requires this)
+	if((x >= hlcd->_width) || (y >= hlcd->_height)) return;
+	if((x + w - 1) >= hlcd->_width)  w = hlcd->_width  - x;
+	if((y + h - 1) >= hlcd->_height) h = hlcd->_height - y;
+
+	color = pDrawProp->TextColor;
+	lcd_drawFastVLine(hlcd, x, y, h, color);
+	lcd_drawFastHLine(hlcd, x, y+h-1, w, color);
+	lcd_drawFastVLine(hlcd, x+w-1, y, h, color);
+	lcd_drawFastHLine(hlcd, x, y, w, color);
+}
+
+/*
+ *  円描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x0: X position
+ *  param3  y0: Y position
+ *  param4  Radius: Circle radius
+ */
+void
+lcd_DrawCircle(LCD_DrawProp_t *pDrawProp, uint16_t x0, uint16_t y0, uint16_t Radius)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+ 	int32_t   decision;    /* Decision Variable */ 
+	uint32_t  current_x;   /* Current X Value */
+	uint32_t  current_y;   /* Current Y Value */
+
+	decision = 3 - (Radius << 1);
+	current_x = 0;
+	current_y = Radius;
+
+	while(current_x <= current_y){
+		lcd_drawPixel(hlcd, (x0 + current_x), (y0 - current_y), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 - current_x), (y0 - current_y), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 + current_y), (y0 - current_x), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 - current_y), (y0 - current_x), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 + current_x), (y0 + current_y), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 - current_x), (y0 + current_y), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 + current_y), (y0 + current_x), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (x0 - current_y), (y0 + current_x), pDrawProp->TextColor);
+
+		if (decision < 0){
+			decision += (current_x << 2) + 6;
+		}
+		else{
+			decision += ((current_x - current_y) << 2) + 10;
+			current_y--;
+		}
+		current_x++;
+	}
+}
+
+/*
+ *  線描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x1: Point 1 X position
+ *  param3  y1: Point 1 Y position
+ *  param4  x2: Point 2 X position
+ *  param5  y2: Point 2 Y position
+ */
+void
+lcd_drawLine(LCD_DrawProp_t *pDrawProp, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0, 
+	yinc1 = 0, yinc2 = 0, den = 0, num = 0, num_add = 0, num_pixels = 0, 
+	curpixel = 0;
+
+	deltax = ABS(x2 - x1);		/* The difference between the x's */
+	deltay = ABS(y2 - y1);		/* The difference between the y's */
+	x = x1;						/* Start x off at the first pixel */
+	y = y1;						/* Start y off at the first pixel */
+
+	if(x2 >= x1){				/* The x-values are increasing */
+		xinc1 = 1;
+		xinc2 = 1;
+	}
+	else{						/* The x-values are decreasing */
+		xinc1 = -1;
+		xinc2 = -1;
+	}
+
+	if(y2 >= y1){				/* The y-values are increasing */
+		yinc1 = 1;
+		yinc2 = 1;
+	}
+	else{						/* The y-values are decreasing */
+		yinc1 = -1;
+		yinc2 = -1;
+	}
+
+	if(deltax >= deltay){		/* There is at least one x-value for every y-value */
+		xinc1 = 0;				/* Don't change the x when numerator >= denominator */
+		yinc2 = 0;				/* Don't change the y for every iteration */
+		den = deltax;
+		num = deltax / 2;
+		num_add = deltay;
+		num_pixels = deltax;	/* There are more x-values than y-values */
+	}
+	else{						/* There is at least one y-value for every x-value */
+		xinc2 = 0;				/* Don't change the x for every iteration */
+		yinc1 = 0;				/* Don't change the y when numerator >= denominator */
+		den = deltay;
+		num = deltay / 2;
+		num_add = deltax;
+		num_pixels = deltay;	/* There are more y-values than x-values */
+	}
+
+	for (curpixel = 0; curpixel <= num_pixels; curpixel++){
+		lcd_drawPixel(hlcd, x, y, pDrawProp->TextColor);	/* Draw the current pixel */
+		num += num_add;			/* Increase the numerator by the top of the fraction */
+		if(num >= den){			/* Check if numerator >= denominator */
+			num -= den;			/* Calculate the new numerator value */
+			x += xinc1;			/* Change the x as appropriate */
+			y += yinc1;			/* Change the y as appropriate */
+		}
+		x += xinc2;				/* Change the x as appropriate */
+		y += yinc2;				/* Change the y as appropriate */
+	}
+}
+
+/*
+ *  PLOY-LINE描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  Points: Pointer to the points array
+ *  param3  PointCount: Number of points
+ */
+void
+lcd_drawPolygon(LCD_DrawProp_t *pDrawProp, pPoint Points, uint16_t PointCount)
+{
+	int16_t x = 0, y = 0;
+
+	if(PointCount < 2){
+		return;
+	}
+
+	lcd_drawLine(pDrawProp, Points->X, Points->Y, (Points+PointCount-1)->X, (Points+PointCount-1)->Y);
+	while(--PointCount){
+		x = Points->X;
+		y = Points->Y;
+		Points++;
+		lcd_drawLine(pDrawProp, x, y, Points->X, Points->Y);
+	}
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/sipeed_st7789/sipeed_st7789.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/sipeed_st7789/sipeed_st7789.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/sipeed_st7789/sipeed_st7789.h	(revision 453)
@@ -0,0 +1,262 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ *
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+ *
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ *
+ *  $Id$
+ */
+/*
+ *  SIPEED ST7789 2.4"LCD制御プログラムのヘッダファイル
+ */
+
+#ifndef _SIPEED_ST7789_H_
+#define _SIPEED_ST7789_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include "device.h"
+#include "spi.h"
+
+/*
+ *  LCDカラーモード定義
+ */
+#define CM_ARGB8888         0x00000000			/* ARGB8888 color mode */
+#define CM_RGB888           0x00000001			/* RGB888 color mode */
+#define CM_RGB565           0x00000002			/* RGB565 color mode */
+
+#define ST7789_TFTWIDTH  240
+#define ST7789_TFTHEIGHT 320
+
+
+#define NO_OPERATION            0x00
+#define SOFTWARE_RESET          0x01
+#define READ_ID                 0x04
+#define READ_STATUS             0x09
+#define READ_POWER_MODE         0x0A
+#define READ_MADCTL             0x0B
+#define READ_PIXEL_FORMAT       0x0C
+#define READ_IMAGE_FORMAT       0x0D
+#define READ_SIGNAL_MODE        0x0E
+#define READ_SELT_DIAG_RESULT   0x0F
+#define SLEEP_ON                0x10
+#define SLEEP_OFF               0x11
+#define PARTIAL_DISPALY_ON      0x12
+#define NORMAL_DISPALY_ON       0x13
+#define INVERSION_DISPALY_OFF   0x20
+#define INVERSION_DISPALY_ON    0x21
+#define GAMMA_SET               0x26
+#define DISPALY_OFF             0x28
+#define DISPALY_ON              0x29
+#define HORIZONTAL_ADDRESS_SET  0x2A
+#define VERTICAL_ADDRESS_SET    0x2B
+#define MEMORY_WRITE            0x2C
+#define COLOR_SET               0x2D
+#define MEMORY_READ             0x2E
+#define PARTIAL_AREA            0x30
+#define VERTICAL_SCROL_DEFINE   0x33
+#define TEAR_EFFECT_LINE_OFF    0x34
+#define TEAR_EFFECT_LINE_ON     0x35
+#define MEMORY_ACCESS_CTL       0x36
+#define VERTICAL_SCROL_S_ADD    0x37
+#define IDLE_MODE_OFF           0x38
+#define IDLE_MODE_ON            0x39
+#define PIXEL_FORMAT_SET        0x3A
+#define WRITE_MEMORY_CONTINUE   0x3C
+#define READ_MEMORY_CONTINUE    0x3E
+#define SET_TEAR_SCANLINE       0x44
+#define GET_SCANLINE            0x45
+#define WRITE_BRIGHTNESS        0x51
+#define READ_BRIGHTNESS         0x52
+#define WRITE_CTRL_DISPALY      0x53
+#define READ_CTRL_DISPALY       0x54
+#define WRITE_BRIGHTNESS_CTL    0x55
+#define READ_BRIGHTNESS_CTL     0x56
+#define WRITE_MIN_BRIGHTNESS    0x5E
+#define READ_MIN_BRIGHTNESS     0x5F
+#define READ_ID1                0xDA
+#define READ_ID2                0xDB
+#define READ_ID3                0xDC
+#define RGB_IF_SIGNAL_CTL       0xB0
+#define NORMAL_FRAME_CTL        0xB1
+#define IDLE_FRAME_CTL          0xB2
+#define PARTIAL_FRAME_CTL       0xB3
+#define INVERSION_CTL           0xB4
+#define BLANK_PORCH_CTL         0xB5
+#define DISPALY_FUNCTION_CTL    0xB6
+#define ENTRY_MODE_SET          0xB7
+#define BACKLIGHT_CTL1          0xB8
+#define BACKLIGHT_CTL2          0xB9
+#define BACKLIGHT_CTL3          0xBA
+#define BACKLIGHT_CTL4          0xBB
+#define BACKLIGHT_CTL5          0xBC
+#define BACKLIGHT_CTL7          0xBE
+#define BACKLIGHT_CTL8          0xBF
+#define POWER_CTL1              0xC0
+#define POWER_CTL2              0xC1
+#define VCOM_CTL1               0xC5
+#define VCOM_CTL2               0xC7
+#define NV_MEMORY_WRITE         0xD0
+#define NV_MEMORY_PROTECT_KEY   0xD1
+#define NV_MEMORY_STATUS_READ   0xD2
+#define READ_ID4                0xD3
+#define POSITIVE_GAMMA_CORRECT  0xE0
+#define NEGATIVE_GAMMA_CORRECT  0xE1
+#define DIGITAL_GAMMA_CTL1      0xE2
+#define DIGITAL_GAMMA_CTL2      0xE3
+#define INTERFACE_CTL           0xF6
+
+/*
+ *  カラー定義
+ */
+#define ST7789_BLACK            0x0000
+#define ST7789_NAVY             0x000F
+#define ST7789_DARKGREEN        0x03E0
+#define ST7789_DARKCYAN         0x03EF
+#define ST7789_MAROON           0x7800
+#define ST7789_PURPLE           0x780F
+#define ST7789_OLIVE            0x7BE0
+#define ST7789_LIGHTGREY        0xC618
+#define ST7789_DARKGREY         0x7BEF
+#define ST7789_BLUE             0x001F
+#define ST7789_GREEN            0x07E0
+#define ST7789_CYAN             0x07FF
+#define ST7789_RED              0xF800
+#define ST7789_MAGENTA          0xF81F
+#define ST7789_YELLOW           0xFFE0
+#define ST7789_WHITE            0xFFFF
+#define ST7789_ORANGE           0xFD20
+#define ST7789_GREENYELLOW      0xAFE5
+#define ST7789_PINK             0xF81F
+
+/*
+ *  LCD DIRECTION
+ */
+#define DIR_XY_RLUD             0x00
+#define DIR_YX_RLUD             0x20
+#define DIR_XY_LRUD             0x40
+#define DIR_YX_LRUD             0x60
+#define DIR_XY_RLDU             0x80
+#define DIR_YX_RLDU             0xA0
+#define DIR_XY_LRDU             0xC0
+#define DIR_YX_LRDU             0xE0
+#define DIR_XY_MASK             0x20
+#define DIR_RL_MASK             0x40
+#define DIR_UD_MASK             0x80
+
+#define TRS_COLOR_T             uint32_t
+
+#ifndef TOPPERS_MACRO_ONLY
+
+
+/*
+ *  カラーの属性を定義
+ */
+typedef uint16_t   color_t;
+
+typedef struct
+{
+	SPI_Handle_t            *hspi;
+    uint16_t                _width;
+    uint16_t                _height;
+	uint16_t                colstart;
+	uint16_t                rowstart;
+	ID                      spi_lock;
+    uint8_t                 mode;
+    uint8_t                 dir;
+
+	int8_t                  dcx_pin;
+	int8_t                  rst_pin;
+	int8_t                  cs_sel;
+	uint8_t                 dcx_no;
+	uint8_t                 rst_no;
+} LCD_Handler_t;
+
+
+/*
+ *  描画構造体
+ */
+typedef struct
+{
+	LCD_Handler_t           *hlcd;
+	color_t                 TextColor;
+	color_t                 BackColor;
+	void                    *pFont;
+}LCD_DrawProp_t;
+
+typedef struct
+{
+	int16_t X;
+	int16_t Y;
+}Point, * pPoint;
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+extern ER lcd_writecommand(LCD_Handler_t *hlcd, uint8_t c);
+extern ER lcd_writebyte(LCD_Handler_t *hlcd, uint8_t *buf, uint8_t len);
+extern ER lcd_writehalf(LCD_Handler_t *hlcd, uint32_t *buf, int cnt);
+extern ER lcd_filldata(LCD_Handler_t *hlcd, uint32_t *data_buf, uint32_t len);
+
+extern void lcd_init(LCD_Handler_t *hlcd);
+extern void lcd_setAddrWindow(LCD_Handler_t *hlcd, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
+extern void lcd_fillRect(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t w, int16_t h, color_t color);
+extern void lcd_pushColor(LCD_Handler_t *hlcd, color_t color);
+extern void lcd_drawPixel(LCD_Handler_t *hlcd, int16_t x, int16_t y, color_t color);
+extern void lcd_drawFastVLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t h, color_t color);
+extern void lcd_drawFastHLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, int16_t w, color_t color);
+extern void lcd_drawImageHLine(LCD_Handler_t *hlcd, int16_t x, int16_t y, uint16_t w, TRS_COLOR_T *pcolor);
+extern void lcd_drawBitmap(LCD_Handler_t *hlcd, uint16_t x0, uint16_t y0, uint8_t *pbmp);
+extern void lcd_drawPicture(LCD_Handler_t *hlcd, uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t *pbmp);
+extern void lcd_invertDisplay(LCD_Handler_t *hlcd, bool_t i);
+
+extern void lcd_fillScreen(LCD_DrawProp_t *pDrawProp);
+extern void lcd_drawRect(LCD_DrawProp_t *pDrawProp, int16_t x, int16_t y, int16_t w, int16_t h);
+extern void lcd_DrawCircle(LCD_DrawProp_t *pDrawProp, uint16_t x0, uint16_t y0, uint16_t Radius);
+extern void lcd_drawLine(LCD_DrawProp_t *pDrawProp, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
+extern void lcd_drawPolygon(LCD_DrawProp_t *pDrawProp, pPoint Points, uint16_t PointCount);
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _SIPEED_ST7789_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/spi_driver/Makefile.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/spi_driver/Makefile.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/spi_driver/Makefile.config	(revision 453)
@@ -0,0 +1,55 @@
+#
+#   TOPPERS/ASP/FMP Kernel
+#       Toyohashi Open Platform for Embedded Real-Time Systems/
+#       Advanced Standard Profile Kernel
+#
+#   Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                               Toyohashi Univ. of Technology, JAPAN
+#   Copyright (C) 2003-2008 by Ryosuke Takeuchi
+#                Platform Development Center RICOH COMPANY,LTD. JAPAN
+#   Copyright (C) 2015-2017 by TOPPERS PROJECT Educational Working Group.
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+ 
+#
+#  Makefile のプロセッサ依存 (spi_driver:sdcard用)
+#
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/gdic/spi_driver
+
+#
+#  SPI DRIVER(GDIC)に関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR):$(SRCDIR)/gdic/spi_driver
+SYSSVC_COBJS := $(SYSSVC_COBJS) spi_driver.o
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/spi_driver/mcicmd.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/spi_driver/mcicmd.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/spi_driver/mcicmd.h	(revision 453)
@@ -0,0 +1,66 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2016 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+ *  によって公表されている GNU General Public License の Version 2 に記
+ *  述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+ *  を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+ *  含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+ *  接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+#ifndef _MCICMD_H_
+#define _MCICMD_H_
+
+#define MCIPCB              SDCARD_Handler_t
+#define MCIINFO             SDCARD_CardInfo_t
+
+#define SDDEV_BUS_WIDE_4B   SDMMC_BUS_WIDE_4B
+#define DMA_ALINE
+
+#define mci_ses_por         sdcard_init
+#define mci_opn_por         sdcard_open
+#define mci_cls_por         sdcard_close
+#define MciCheckCID         sdcard_checkCID
+#define MciSetAddress       sdcard_dummy
+#define MciSendCID          sdcard_sendCSD
+#define MciGetCardInfo      sdcard_getcardinfo
+#define MciSelectCard       sdcard_select_card
+#define MciConfiguration    sdcard_configuration
+#define MciSetWideBus       sdcard_dummy
+#define mci_red_blk         sdcard_blockread
+#define mci_wri_blk         sdcard_blockwrite
+#define mci_wai_trn         sdcard_wait_transfar
+
+#include "spi_driver.h"
+
+#endif
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/spi_driver/spi_driver.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/spi_driver/spi_driver.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/spi_driver/spi_driver.c	(revision 453)
@@ -0,0 +1,950 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2012 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *  SPI用デバイスドライバ
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <string.h>
+#include <target_syssvc.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#include "device.h"
+#include "spi.h"
+#include "pinmode.h"
+#include "spi_driver.h"
+
+#define sil_orw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) | (b))
+#define sil_andw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) & ~(b))
+#define sil_modw_mem(a, b, c)	sil_wrw_mem((a), (sil_rew_mem(a) & (~b)) | (c))
+
+#define INIT_RETRY_COUNT    32
+
+#define CRC16POLY           0x1021
+
+static const uint8_t CMD0[5]   = {0x40, 0x00, 0x00, 0x00, 0x00};
+static const uint8_t CMD8[5]   = {0x48, 0x00, 0x00, 0x01, 0xAA};
+static const uint8_t CMD9[5]   = {0x49, 0x00, 0x00, 0x00, 0x00};
+static const uint8_t CMD10[5]  = {0x4A, 0x00, 0x00, 0x00, 0x00};
+static const uint8_t CMD16[5]  = {0x50, 0x00, 0x00, 0x02, 0x00};
+static const uint8_t CMD55[5]  = {0x77, 0x00, 0x00, 0x00, 0x00};
+static const uint8_t ACMD41[5] = {0x69, 0x40, 0x00, 0x00, 0x00};
+static const uint8_t CMD58[5]  = {0x7A, 0x00, 0x00, 0x00, 0x00};
+
+static bool_t           sdcard_sense = true;
+static SDCARD_Handler_t SdHandle;
+
+/* Buffer used for transmission */
+uint8_t aTxBuffer[BUFFERSIZE];
+
+/* Buffer used for reception */
+uint8_t aRxBuffer[BUFFERSIZE];
+
+#ifndef SPI_DRIVER_NOSTART
+/*
+ *  GPIO設定関数
+ */
+static void
+pinMode(uint8_t no, uint32_t otype, uint32_t pullmode)
+{
+	Arduino_PortControlBlock *pgcb = getGpioTable(DIGITAL_PIN, no);
+	GPIO_Init_t GPIO_Init_Data;
+
+	if(pgcb == NULL)
+		return;
+	pinClock(no);
+	GPIO_Init_Data.mode  = GPIO_MODE_OUTPUT;
+	GPIO_Init_Data.pull  = pullmode;
+	GPIO_Init_Data.otype = otype;
+	GPIO_Init_Data.speed = GPIO_SPEED_FAST;
+	gpio_setup(pgcb->giobase, &GPIO_Init_Data, pgcb->giopin);
+}
+
+/*
+ *  SPI初期化関数
+ */
+SPI_Handle_t *
+spi_start(SPI_Setup_t *psps)
+{
+	SPI_Init_t spi_initd;
+	SPI_Handle_t  *hspi;
+
+	/*
+	 *  CS PORT(D10-PB6)
+	 */
+	pinMode(psps->cs_pin, psps->otype, psps->pullmode);
+	/*
+	 *  RS PORT(D8-PA9)
+	 */
+	pinMode(psps->rs_pin, psps->otype, psps->pullmode);
+	/*
+	 *  RST PORT(D9-PC7)
+	 */
+	pinMode(psps->rst_pin, psps->otype, psps->pullmode);
+	/*
+	 *  CS2 PORT(D4-PB5)
+	 */
+	pinMode(psps->cs2_pin, psps->otype, psps->pullmode);
+	SdHandle.cs2_port = psps->cs2_pin;
+
+	memset(&spi_initd, 0, sizeof(SPI_Init_t));
+	spi_initd.Prescaler     = psps->baud;
+	spi_initd.Direction     = SPI_DIRECTION_2LINES;
+	spi_initd.CLKPhase      = SPI_PHASE_1EDGE;
+	spi_initd.CLKPolarity   = SPI_POLARITY_LOW;
+	spi_initd.CRC           = SPI_CRC_DISABLE;
+	spi_initd.CRCPolynomial = 7;
+	spi_initd.DataSize      = SPI_DATASIZE_8BIT;
+	spi_initd.SignBit       = SPI_DATA_MSB;
+	spi_initd.NSS           = SPI_NSS_SOFT;
+	spi_initd.TIMode        = SPI_TIMODE_DISABLE;
+	spi_initd.Mode = SPI_MODE_MASTER;
+	spi_initd.semid   = psps->spi_sem;
+	spi_initd.semlock = 0;
+
+	if((hspi = spi_init(psps->port, &spi_initd)) == NULL){
+		syslog_0(LOG_ERROR, "spi_start initialize error !");
+	}
+	return hspi;
+}
+
+/*
+ *  SPI終了関数
+ */
+void
+spi_end(SPI_Handle_t *hspi)
+{
+	spi_deinit(hspi);
+}
+#endif	/* SPI_DRIVER_NOSTART */
+
+
+/*
+ *  CRC7計算関数
+ */
+static uint8_t
+calc_CRC7(const uint8_t *data, int len)
+{
+	uint_t  i, j;
+	uint8_t crc = 0, dt;
+
+	for(i = 0; i < len; i++){
+		dt = *data++;
+		for(j = 0; j < 8; j++){
+			crc <<=1;
+			if ((crc & 0x80) ^ (dt & 0x80))
+				crc ^= 0x09;
+			dt <<= 1;
+		}
+	}
+	return ((crc & 0x7f) << 1) | 1;
+}
+
+/*
+ *  CRC16-CCITT計算関数
+ */
+static uint16_t
+calc_CRC16(const uint8_t *data, int len)
+{
+	uint16_t crc = 0;
+	int i, j;
+
+	for(i = 0; i < len; i++){
+		crc ^= (data[i]<<8);
+		for(j = 0; j < 8; j++){
+			if(crc & 0x8000)
+				crc = (crc << 1) ^ CRC16POLY;
+			else
+				crc <<= 1;
+		}
+	}
+	return crc;
+}
+
+/*
+ *  SDCARDからのデータ読み込み
+ */
+static ER
+sdcard_read(SPI_Handle_t *hspi, uint8_t *pres, int size)
+{
+	ER ercd;
+
+#if SPI_WAIT_TIME != 0
+	ercd = spi_receive(hspi, (uint8_t*)pres, size);
+#else
+	if((ercd = spi_receive(hspi, (uint8_t*)pres, size)) == E_OK){
+		ercd = spi_wait(hspi, 50);
+	}
+#endif
+	if(ercd != E_OK)
+    	syslog_1(LOG_ERROR, "sdcard_read ERROR(%d) !", ercd);
+	return ercd;
+}
+
+/*
+ *  SDCARDへのデータ書き込み
+ */
+static ER
+sdcard_write(SPI_Handle_t *hspi, uint8_t *pres, int size)
+{
+	ER ercd;
+
+#if SPI_WAIT_TIME != 0
+	ercd = spi_transmit(hspi, (uint8_t*)pres, size);
+#else
+	if((ercd = spi_transmit(hspi, (uint8_t*)pres, size)) == E_OK){
+		ercd = spi_wait(hspi, 50);
+	}
+#endif
+	if(ercd != E_OK)
+    	syslog_1(LOG_ERROR, "sdcard_write ERROR(%d) !", ercd);
+	return ercd;
+}
+
+/*
+ *  SDCARDへのコマンド送信
+ */
+static ER
+sdcard_sendcommand(SPI_Handle_t *hspi, const uint8_t *cmd, int size)
+{
+	ER ercd = E_OK;
+	uint8_t crc;
+
+	crc = calc_CRC7(cmd, size);
+	memcpy(aTxBuffer, cmd, size);
+	aTxBuffer[size] = crc;
+#if SPI_WAIT_TIME != 0
+	ercd = spi_transmit(hspi, (uint8_t*)aTxBuffer, (size+1));
+#else
+	if((ercd = spi_transmit(hspi, (uint8_t*)aTxBuffer, (size+1))) == E_OK){
+		ercd = spi_wait(hspi, 50);
+	}
+#endif
+	return ercd;
+}
+
+/*
+ *  SDCARDへのダミー書き込み
+ */
+static ER
+sdcard_dummywrite(SPI_Handle_t *hspi)
+{
+	uint8_t dummy[2];
+	dummy[0] = 0xff;
+	return sdcard_write(hspi, dummy, 1);
+}
+
+/*
+ *  SDCARDからのレスポンス受信
+ */
+static ER
+sdcard_response(SPI_Handle_t *hspi, uint8_t *pres, int size, int timeout)
+{
+	int tick, i = 0;
+
+	timeout *= 100;
+	for(tick = 0 ; tick < timeout ; tick++){
+		if(sdcard_read(hspi, aRxBuffer, 1) == E_OK){
+			pres[i] = aRxBuffer[0];
+			if((aRxBuffer[0] & 0x80) == 0){
+				i++;
+				if(i >= size)
+					return E_OK;
+			}
+		}
+		sil_dly_nse(1000*10);
+	}
+	return E_TMOUT;
+}
+
+/*
+ *  SDCARDからのデータ受信
+ */
+static ER
+sdcard_receive(SPI_Handle_t *hspi, uint8_t *pdata, int size, uint16_t *crc, int timeout)
+{
+	ER  ercd = E_OK;
+	bool_t ff_count;
+	int tick, i = 0;
+
+	for(tick = 0 ; tick < (timeout*1000) ; tick++){
+		*crc = 0xffff;
+		if((ercd = sdcard_read(hspi, aRxBuffer, 1)) == E_OK){
+			if(aRxBuffer[0] == 0xfe){
+				if((ercd = sdcard_read(hspi, pdata, size)) != E_OK)
+					return ercd;
+				ercd = E_TMOUT;
+				for(i = 0, ff_count = 0 ; i < 24 ; i++){
+					sdcard_read(hspi, aRxBuffer, 1);
+					dly_tsk(2);
+					if(aRxBuffer[0] != 0xff){
+						if(ff_count == 0)
+							*crc = aRxBuffer[0]<<8;
+						else if(ff_count == 1)
+							*crc |= aRxBuffer[0];
+						ff_count++;
+					}
+					if(i >= 1 && aRxBuffer[0] == 0xff && ff_count > 0)
+						ercd = E_OK;
+				}
+				return ercd;
+			}
+			else if(aRxBuffer[0] != 0xff){
+				syslog_2(LOG_NOTICE, "## sdcard_receive i(%d) resp[%02x] ##", i, aRxBuffer[0]);
+			}
+		}
+		sil_dly_nse(1000);
+	}
+	return E_TMOUT;
+}
+
+/*
+ *  SDCARDへのデータ送信
+ */
+static ER
+sdcard_send(SPI_Handle_t *hspi, uint8_t *pdata, int size)
+{
+	ER  ercd = E_OK;
+	uint8_t  data[4];
+	uint16_t crc;
+	int   res_count = 0;
+	int i = 0;
+
+	crc = calc_CRC16((const uint8_t *)pdata, size);
+	data[0] = 0xff;
+	data[1] = 0xfe;
+	if((ercd = sdcard_write(hspi, data, 2)) != E_OK)
+		return ercd;
+	if((ercd = sdcard_write(hspi, pdata, size)) != E_OK)
+		return ercd;
+	data[0] = crc >> 8;
+	data[1] = crc & 0xff;
+	if((ercd = sdcard_write(hspi, data, 2)) != E_OK)
+		return ercd;
+	ercd = E_TMOUT;
+	for(i = 0 ; i < 24 ; i++){
+		sdcard_read(hspi, aRxBuffer, 1);
+		dly_tsk(1);
+		if(aRxBuffer[0] != 0xff){
+			if(res_count == 0){
+				if((aRxBuffer[0] & 0x1F) == 0x05)
+					ercd = E_OK;
+				else
+					ercd = E_SYS;
+				res_count++;
+			}
+			else if(aRxBuffer[0] == 0x00)
+				res_count++;
+		}
+		else if(res_count >= 2)
+			break;
+	}
+	return ercd;
+}
+/*
+ *  SDCARD通信ロック
+ */
+static ER
+sdcard_lock(SDCARD_Handler_t *hsd)
+{
+	ER ercd = E_OK;
+	if(hsd->spi_lock != 0)
+		ercd = wai_sem(hsd->spi_lock);
+	digitalWrite(hsd->cs2_port, PORT_LOW);
+	return ercd;
+}
+
+/*
+ *  SDCARD通信アンロック
+ */
+static ER
+sdcard_unlock(SDCARD_Handler_t *hsd)
+{
+	ER ercd = E_OK;
+	digitalWrite(hsd->cs2_port, PORT_HIGH);
+	if(hsd->spi_lock != 0)
+		ercd = sig_sem(hsd->spi_lock);
+	return ercd;
+}
+
+/*
+ *  SDCARDリセット
+ */
+static ER
+sdcard_reset(SDCARD_Handler_t *hsd)
+{
+	ER ercd = E_OK;
+	uint8_t resp[2];
+	int i = 0;
+
+	if((ercd = sdcard_lock(hsd)) != E_OK){
+		return ercd;
+	}
+	for(i = 0 ; i < 20 ; i++){
+		if((ercd = sdcard_sendcommand(hsd->hspi, CMD55, sizeof(CMD55))) != E_OK)
+			continue;
+		if((ercd = sdcard_response(hsd->hspi, resp, 1, 300)) != E_OK)
+			continue;
+		if((ercd = sdcard_sendcommand(hsd->hspi, ACMD41, sizeof(ACMD41))) != E_OK)
+			continue;
+		if((ercd = sdcard_response(hsd->hspi, resp, 1, 300)) != E_OK)
+			continue;
+		if(resp[0] == 0x00)
+			break;
+		dly_tsk(40);
+	}
+	sdcard_unlock(hsd);
+	return ercd;
+}
+
+
+/*
+ *  SDCARDのSPI設定
+ */
+void
+sdcard_setspi(ID portid, SPI_Handle_t *hspi)
+{
+	SdHandle.hspi = hspi;
+}
+
+/*
+ *  SDCARDのSPI設定:改良型
+ */
+void
+sdcard_setspi2(ID portid, SPI_Handle_t *hspi, uint8_t cs_port)
+{
+	SdHandle.hspi     = hspi;
+	SdHandle.cs2_port = cs_port;
+}
+
+/*
+ *  SDCARDの初期化関数、エラーならばカードなし
+ */
+bool_t
+sdcard_init(ID portid)
+{
+	SDCARD_Handler_t *hsd = &SdHandle;
+	SPI_Handle_t *hspi;
+	uint8_t resp[8];
+	uint8_t checkno = 0;
+	ER      ercd;
+	int     i;
+
+	if(!sdcard_sense)
+		return false;
+
+	sdcard_sense = false;
+	if((hspi = hsd->hspi) == NULL)
+		return false;
+	hsd->hspi = NULL;
+
+	if((ercd = sdcard_lock(hsd)) != E_OK)
+		return false;
+	if((ercd = sdcard_sendcommand(hspi, CMD0, sizeof(CMD0))) != E_OK){
+		sdcard_unlock(hsd);
+		return false;
+	}
+	if((ercd = sdcard_response(hspi, resp, 1, 500)) != E_OK){
+		sdcard_unlock(hsd);
+		return false;
+	}
+#if 1	/* ROI DEBUG */
+	syslog_4(LOG_NOTICE, "## resp 0[%02x] 1[%02x] 2[%02x] 3[%02x] ##", resp[0], resp[1], resp[2], resp[3]);
+#endif	/* ROI DEBUG */
+	sdcard_unlock(hsd);
+	sdcard_dummywrite(hspi);
+
+	if((ercd = sdcard_lock(hsd)) != E_OK)
+		return false;
+	if((ercd = sdcard_sendcommand(hspi, CMD8, sizeof(CMD8))) == E_OK){
+		sdcard_response(hspi, resp, 1, 500);
+	}
+	if(ercd == E_OK && (resp[0] & 0x04) == 0x00){
+		ercd = sdcard_read(hspi, resp, 4);
+		if(resp[2] != 0x01 || resp[3] != 0xAA){
+			syslog_4(LOG_ERROR, "CMD8(1) ERROR [%02x][%02x][%02x][%02x] !", resp[0], resp[1], resp[2], resp[3]);
+			sdcard_unlock(hsd);
+			return false;
+		}
+	}
+	else{
+		sdcard_unlock(hsd);
+		sdcard_dummywrite(hspi);
+
+		if((ercd = sdcard_lock(hsd)) != E_OK)
+			return false;
+		checkno = 1;
+		if((ercd = sdcard_sendcommand(hspi, CMD58, sizeof(CMD58))) == E_OK){
+			ercd = sdcard_response(hspi, resp, 1, 500);
+		}
+		if(ercd == E_OK && (resp[0] & 0x04) == 0x00){
+			ercd = sdcard_read(hspi, resp, 4);
+			if(resp[2] != 0x01){
+				syslog_4(LOG_ERROR, "CMD58 ERROR [%02x][%02x][%02x][%02x] !", resp[0], resp[1], resp[2], resp[3]);
+				sdcard_unlock(hsd);
+				return false;
+			}
+		}
+		else{
+			syslog_2(LOG_ERROR, "CMD58 ERROR(%d) [%02x] !", ercd, resp[0]);
+			sdcard_unlock(hsd);
+			return false;
+		}
+	}
+	sdcard_unlock(hsd);
+	sdcard_dummywrite(hspi);
+
+	for(i = 0 ; i < 50 ; i++){	/* 5sec */
+		do{
+			if((ercd = sdcard_lock(hsd)) != E_OK)
+				return false;
+			if((ercd = sdcard_sendcommand(hspi, CMD55, sizeof(CMD55))) == E_OK){
+				if((ercd = sdcard_response(hspi, resp, 1, 500)) == E_OK){
+					sdcard_unlock(hsd);
+					sdcard_dummywrite(hspi);
+
+					if((ercd = sdcard_lock(hsd)) != E_OK)
+						return false;
+					if((ercd = sdcard_sendcommand(hspi, ACMD41, sizeof(ACMD41))) == E_OK){
+						if((ercd = sdcard_response(hspi, resp, 1, 500)) == E_OK){
+							sdcard_unlock(hsd);
+							sdcard_dummywrite(hspi);
+							break;
+						}
+					}
+				}
+			}
+			sdcard_unlock(hsd);
+			sdcard_dummywrite(hspi);
+			dly_tsk(200);
+		}while(ercd != E_OK);
+		if(resp[0] == 0x00)
+			break;
+		dly_tsk(100);
+	}
+
+	if(checkno == 1){
+		sdcard_sense = true;
+		hsd->cardtype = SD_CARD_V20;
+		hsd->hspi = hspi;
+		return true;
+	}
+
+	if((ercd = sdcard_lock(hsd)) != E_OK)
+		return false;
+	if((ercd = sdcard_sendcommand(hspi, CMD58, sizeof(CMD58))) == E_OK){
+		ercd = sdcard_response(hspi, resp, 1, 500);
+	}
+	if(ercd == E_OK && resp[0] == 0x00){
+		sdcard_sense = true;
+		ercd = sdcard_read(hspi, resp, 4);
+		if((resp[0] & 0x40) == 0)
+			hsd->cardtype = SD_CARD_V20;
+		else
+			hsd->cardtype = SD_CARD_HC;
+		hsd->hspi = hspi;
+		sdcard_unlock(hsd);
+		sdcard_dummywrite(hspi);
+		return true;
+	}
+	sdcard_unlock(hsd);
+	return false;
+}
+
+/*
+ *  SDCARDオープン
+ */
+SDCARD_Handler_t*
+sdcard_open(ID portid)
+{
+	if(SdHandle.hspi != NULL){
+		SdHandle.spi_lock    = 0;
+		SdHandle.RetryCount  = INIT_RETRY_COUNT;
+		SdHandle.read_count  = 0;
+		SdHandle.write_count = 0;
+		SdHandle.read_retry_count  = 0;
+		SdHandle.write_retry_count = 0;
+		SdHandle.read_error  = 0;
+		SdHandle.write_error = 0;
+		return &SdHandle;
+	}
+	else
+		return NULL;
+}
+
+/*
+ *  SDCARDクローズ(未処理)
+ */
+ER
+sdcard_close(SDCARD_Handler_t *hsd)
+{
+	return E_OK;
+}
+
+/*
+ *  SDカードの情報を取り込む
+ *  parameter1  hsd: SDCARDハンドラ
+ *  parameter2  pCardInfo: カードインフォ構造体へのポインタ
+ *  return      ERコード
+ */
+ER
+sdcard_getcardinfo(SDCARD_Handler_t *hsd, SDCARD_CardInfo_t *pCardInfo)
+{
+	ER ercd = E_OK;
+	uint32_t devicesize;
+	uint8_t  blocklen, mul;
+
+	pCardInfo->cardtype = (uint8_t)(hsd->cardtype);
+	pCardInfo->RCA      = (uint16_t)(hsd->RCA);
+
+	if(hsd->cardtype == SD_CARD_V11 || hsd->cardtype == SD_CARD_V20){
+		/* ブロック長を取り込む */
+		blocklen       = (uint8_t)(hsd->CSD[5] & 0x0F);
+		devicesize = (hsd->CSD[6] & 0x03) << 10;
+		devicesize |= hsd->CSD[7] << 2;
+		devicesize |= (hsd->CSD[8] & 0xC0) >> 6;
+		mul = (hsd->CSD[9] & 0x03) << 1;
+		mul |= (hsd->CSD[10] & 0x80) >> 7;
+		pCardInfo->capacity  = (devicesize + 1) ;
+		pCardInfo->capacity *= (1 << (mul + 2));
+		pCardInfo->blocksize = 1 << (blocklen);
+		pCardInfo->capacity *= pCardInfo->blocksize;
+	}
+	else if(hsd->cardtype == SD_CARD_HC){
+		devicesize = (hsd->CSD[7] & 0x3F) << 16;
+		devicesize |= (hsd->CSD[8] & 0xFF) << 8;
+		devicesize |= (hsd->CSD[9] & 0xFF);
+		pCardInfo->capacity  = (uint64_t)(devicesize + 1) << 19 /* 512 * 1024*/;
+		pCardInfo->blocksize = 512;
+	}
+	else{
+		pCardInfo->capacity  = 0;
+		pCardInfo->blocksize = 512;
+		ercd = E_OBJ;
+	}
+	pCardInfo->maxsector = pCardInfo->capacity / 512;
+	pCardInfo->status    = (uint8_t)hsd->CSD[14];
+	return ercd;
+}
+
+/*
+ *  CIDの取得
+ *  SDカードCMD2,MMCカードCMD1送信後のレスポンス受信
+ *  parameter1  hsd: SDCARDハンドラ
+ *  return      ERコード
+ */
+ER
+sdcard_checkCID(SDCARD_Handler_t *hsd)
+{
+	ER  ercd = E_OK;
+	uint8_t resp[2];
+	uint16_t crc;
+	int i, timeout = 50;
+
+	if((ercd = sdcard_lock(hsd)) != E_OK)
+		return ercd;
+	for(i = 0 ; i < INIT_RETRY_COUNT ; i++, timeout = 1000){
+	    /*
+		 *  CMD10送信
+		 */
+		if((ercd = sdcard_sendcommand(hsd->hspi, CMD10, sizeof(CMD10))) != E_OK)
+			break;
+		if((ercd = sdcard_response(hsd->hspi, resp, 1, timeout)) != E_OK)
+			continue;
+		else if(resp[0] == 0x00){
+			sdcard_receive(hsd->hspi, &hsd->CID[0], 16, &crc, 5000);
+			sdcard_unlock(hsd);
+			return ercd;
+		}
+	}
+	sdcard_unlock(hsd);
+	if(i == INIT_RETRY_COUNT)
+		ercd = E_TMOUT;
+	return ercd;
+}
+
+/*
+ *  CSD(Card Specific DATA)の取得
+ *  parameter1  hsd: SDCARDハンドラ
+ *  return      ERコード
+ */
+ER
+sdcard_sendCSD(SDCARD_Handler_t *hsd)
+{
+	ER  ercd = E_OK;
+	uint8_t resp[2];
+	uint16_t crc;
+	int i, timeout = 50;
+
+	if((ercd = sdcard_lock(hsd)) != E_OK)
+		return ercd;
+	for(i = 0 ; i < INIT_RETRY_COUNT ; i++, timeout = 1000){
+	    /*
+		 *  CMD9送信
+		 */
+		if((ercd = sdcard_sendcommand(hsd->hspi, CMD9, sizeof(CMD9))) != E_OK)
+			break;
+		if((ercd = sdcard_response(hsd->hspi, resp, 1, timeout)) != E_OK)
+			continue;
+		else if(resp[0] == 0x00){
+			sdcard_receive(hsd->hspi, &hsd->CSD[0], 16, &crc, 5000);
+			sdcard_unlock(hsd);
+			return E_OK;
+		}
+		dly_tsk(100);
+	}
+	if(i == INIT_RETRY_COUNT)
+		ercd = E_TMOUT;
+	sdcard_unlock(hsd);
+	return ercd;
+}
+
+/*
+ *  SELECT_CARDコマンドの送信(未処理)
+ *  parameter1  hsd: SDMMCハンドラ
+ *  return      ERコード
+ */
+ER
+sdcard_select_card(SDCARD_Handler_t *hsd, uint64_t addr)
+{
+	return E_OK;
+}
+
+/*
+ *  SDCARDコンフィギュレーション
+ *  parameter1  hsd: SDMMCハンドラ
+ *  return      ERコード
+ */
+ER
+sdcard_configuration(SDCARD_Handler_t *hsd)
+{
+	ER  ercd = E_OK;
+	uint8_t resp[2];
+	int     i;
+
+	if((ercd = sdcard_lock(hsd)) != E_OK)
+		return ercd;
+	for(i = 0 ; i < INIT_RETRY_COUNT ; i++){
+		if((ercd = sdcard_sendcommand(hsd->hspi, CMD16, sizeof(CMD16))) != E_OK)
+			break;
+		ercd = sdcard_response(hsd->hspi, resp, 1, 2000);
+		if(ercd == E_OK && resp[0] == 0x00)
+			break;
+		dly_tsk(100);
+	}
+	sdcard_unlock(hsd);
+	if(i == INIT_RETRY_COUNT && resp[0] != 0x04)	/* SanDisk */
+		ercd = E_TMOUT;
+	return ercd;
+}
+
+/*
+ *  SDCARDブロックREAD
+ *  parameter1  hsd: SDCARDハンドラ
+ *  parameter2  pbuf: 読み出しデータ格納領域のポインタ(uint32_t型)
+ *  parameter3  ReadAddr: カード上の読み出し位置
+ *  parameter4  blocksize: ブロックサイズ
+ *  parameter5  num: 読み出しブロック数
+ *  return      ERコード
+ */
+ER
+sdcard_blockread(SDCARD_Handler_t *hsd, uint32_t *pbuf, uint64_t ReadAddr, uint32_t blocksize, uint32_t num)
+{
+	ER  ercd = E_OK;
+	static uint8_t cmd17[8];
+	uint8_t resp[2];
+	uint32_t incsec = blocksize;
+	uint16_t crc1, crc2;
+	uint16_t crc3 = 0xffff;
+	int     no, i = 0;
+
+	hsd->read_count++;
+	if(hsd->cardtype == SD_CARD_HC){
+		blocksize = 512;
+		incsec    = 1;
+		ReadAddr /= 512;
+	}
+	for(no = 0 ; no < num ; no++){
+		for(i = 0 ; i < hsd->RetryCount ; i++){
+			if((ercd = sdcard_lock(hsd)) != E_OK){
+				return ercd;
+			}
+
+			cmd17[0] = 0x51;
+			cmd17[1] = (ReadAddr >> 24) & 0xff;
+			cmd17[2] = (ReadAddr >> 16) & 0xff;
+			cmd17[3] = (ReadAddr >> 8) & 0xff;
+			cmd17[4] = ReadAddr & 0xff;
+		    /*
+			 *  CMD17送信
+			 */
+			if((ercd = sdcard_sendcommand(hsd->hspi, cmd17, 5)) == E_OK){
+				if((ercd = sdcard_response(hsd->hspi, resp, 1, 50)) == E_OK && resp[0] == 0x00){
+					ercd = sdcard_receive(hsd->hspi, (uint8_t *)pbuf, blocksize, &crc1, 5000);
+					if(ercd == E_OK){
+						dly_tsk(5);
+						crc2 = calc_CRC16((const uint8_t *)pbuf, blocksize);
+						if(crc1 == crc2){
+							sdcard_unlock(hsd);
+							break;
+						}
+						else if(crc3 == crc2){
+							hsd->read_error++;
+							if(i > 1)
+								syslog_4(LOG_ERROR, "sdcard_blockread crc[%04x][%04x] count(%d) error(%d)  !", crc1, crc2, i, hsd->read_error);
+							sdcard_unlock(hsd);
+							break;
+							dly_tsk(100);
+						}
+						crc3 = crc2;
+					}
+				}
+			}
+			hsd->read_retry_count++;
+			sdcard_unlock(hsd);
+			dly_tsk(10);
+			sdcard_reset(hsd);
+			dly_tsk(10);
+			sdcard_configuration(hsd);
+		}
+		if(i == hsd->RetryCount && ercd == E_OK){
+			ercd = E_TMOUT;
+			break;
+		}
+		ReadAddr += incsec;
+		pbuf += (blocksize/4);
+	}
+	return ercd;
+}
+
+/*
+ *  SDCARDブロックWRITE
+ *  parameter1  hsd: SDCARDハンドラ
+ *  parameter2  pbuf: 書込みデータ格納領域のポインタ(uint32_t型)
+ *  parameter3  WritedAddr: カード上の書き込み位置
+ *  parameter4  blocksize: ブロックサイズ
+ *  parameter5  num: 書込みブロック数
+ *  return      ERコード
+ */
+ER
+sdcard_blockwrite(SDCARD_Handler_t *hsd, uint32_t *pbuf, uint64_t WriteAddr, uint32_t blocksize, uint32_t num)
+{
+	ER  ercd = E_OK;
+	static uint8_t cmd24[8];
+	uint8_t resp[2];
+	uint32_t incsec = blocksize;
+	int     no, i = 0;
+
+	hsd->write_count++;
+	if(hsd->cardtype == SD_CARD_HC){
+		blocksize  = 512;
+		incsec     = 1;
+		WriteAddr /= 512;
+	}
+	for(no = 0 ; no < num ; no++){
+		for(i = 0 ; i < hsd->RetryCount ; i++){
+			if((ercd = sdcard_lock(hsd)) != E_OK){
+				return ercd;
+			}
+
+			cmd24[0] = 0x58;
+			cmd24[1] = (WriteAddr >> 24) & 0xff;
+			cmd24[2] = (WriteAddr >> 16) & 0xff;
+			cmd24[3] = (WriteAddr >> 8) & 0xff;
+			cmd24[4] = WriteAddr & 0xff;
+		    /*
+			 *  CMD24送信
+			 */
+			if((ercd = sdcard_sendcommand(hsd->hspi, cmd24, 5)) == E_OK){
+				if((ercd = sdcard_response(hsd->hspi, resp, 1, 50)) == E_OK && resp[0] == 0x00){
+					ercd = sdcard_send(hsd->hspi, (uint8_t *)pbuf, blocksize);
+					if(ercd == E_OK){
+						sdcard_unlock(hsd);
+						break;
+					}
+				}
+			}
+			hsd->read_retry_count++;
+			sdcard_unlock(hsd);
+			dly_tsk(10);
+			sdcard_reset(hsd);
+			dly_tsk(10);
+			sdcard_configuration(hsd);
+		}
+		if(i == hsd->RetryCount && ercd == E_OK){
+			ercd = E_TMOUT;
+			break;
+		}
+		WriteAddr += incsec;
+		pbuf += (blocksize/4);
+	}
+	return ercd;
+}
+
+/*
+ *  SDCARDブロック転送終了待ち
+ *  parameter1  hsd: SDCARDハンドラ
+ *  parameter2  Timeout: タイムアウト値(1msec)
+ *  return      ERコード
+ */
+ER
+sdcard_wait_transfar(SDCARD_Handler_t *hsd, uint32_t Timeout)
+{
+	return E_OK;
+}
+
+/*
+ *  SDカードダミー処理
+ *  parameter1  hsd: SDCARDハンドラ
+ *  return      ERコード
+ */
+ER
+sdcard_dummy(SDCARD_Handler_t *hsd)
+{
+	return E_OK;
+}
+
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/spi_driver/spi_driver.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/spi_driver/spi_driver.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/spi_driver/spi_driver.h	(revision 453)
@@ -0,0 +1,162 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ *
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2016 by TOPPERS PROJECT Educational Working Group.
+ *
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ *
+ *  $Id$
+ */
+
+/*
+ *	SPIドライバのヘッダファイル
+ */
+
+#ifndef _SPI_DRIVER_H_
+#define _SPI_DRIVER_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include "device.h"
+#include "spi.h"
+#include "pinmode.h"
+
+/*
+ *  SDカード種別定義
+ */
+#define SD_CARD_V11         0
+#define SD_CARD_V20         1
+#define SD_CARD_HC          2
+#define MMC_CARD			3
+#define SD_IO_CARD          4
+#define HS_MM_CARD          5
+#define SD_IO_COMBO_CARD    6
+#define MMC_CARD_HC         7
+
+#define PORT_HIGH           1
+#define PORT_LOW            0
+
+#define SDMODE_PROTECT      (1<<5)
+#define BUFFERSIZE          140
+
+
+#ifndef TOPPERS_MACRO_ONLY
+
+#ifndef SPI_DRIVER_NOSTART
+/*
+ *  SPI SETUP構造体定義
+ */
+typedef struct {
+	int                     port;
+	uint32_t                baud;
+	ID                      spi_sem;
+	uint8_t                 cs_pin;
+	uint8_t                 rs_pin;
+	uint8_t                 rst_pin;
+	uint8_t                 cs2_pin;
+	uint32_t                otype;
+	uint32_t                pullmode;
+} SPI_Setup_t;
+#endif	/* SPI_DRIVER_NOSTART */
+
+/*
+ *  SDCARDハンドラ構造体定義
+ */
+typedef struct {
+	SPI_Handle_t            *hspi;		/* spiハンドラ */
+	uint32_t                RetryCount;	/* リトライ回数 */
+	uint32_t                cardtype;	/* カードタイプ */
+	uint32_t                RCA;		/* RCA値 */
+	uint8_t                 CSD[16];	/* CSD値 */
+	uint8_t                 CID[16];	/* CID値 */
+	ID                      spi_lock;
+	uint32_t                cs2_port;	/* csポート */
+	volatile uint32_t       status;		/* 転送状態 */
+	uint32_t                read_count;
+	uint32_t                write_count;
+	uint32_t                read_retry_count;
+	uint32_t                write_retry_count;
+	uint32_t                read_error;
+	uint32_t                write_error;
+}SDCARD_Handler_t;
+
+/*
+ *  SDCARD情報構造体
+ */
+typedef struct {
+	uint64_t                capacity;	/* 容量(バイト) */
+	uint32_t                blocksize;	/* ブロックサイズ */
+	uint32_t                maxsector;	/* 最大セクタ数 */
+	uint16_t                RCA;		/* SD RCA */
+	uint8_t                 cardtype;	/* カード種類 */
+	uint8_t                 status;		/* ステータス */
+}SDCARD_CardInfo_t;
+
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+
+#ifndef SPI_DRIVER_NOSTART
+extern SPI_Handle_t *spi_start(SPI_Setup_t *psps);
+extern void spi_end(SPI_Handle_t *hspi);
+#endif
+
+extern void sdcard_setspi(ID portid, SPI_Handle_t *hspi);
+extern void sdcard_setspi2(ID portid, SPI_Handle_t *hspi, uint8_t cs_port);
+extern bool_t sdcard_init(ID portid);
+extern SDCARD_Handler_t *sdcard_open(int id);
+extern ER sdcard_close(SDCARD_Handler_t *hsd);
+extern ER sdcard_getcardinfo(SDCARD_Handler_t *hsd, SDCARD_CardInfo_t *pCardInfo);
+extern ER sdcard_checkCID(SDCARD_Handler_t *hsd);
+extern ER sdcard_sendCSD(SDCARD_Handler_t *hsd);
+extern ER sdcard_select_card(SDCARD_Handler_t *hsd, uint64_t addr);
+extern ER sdcard_configuration(SDCARD_Handler_t *hsd);
+extern ER sdcard_blockread(SDCARD_Handler_t *hsd, uint32_t *pbuf, uint64_t ReadAddr, uint32_t blocksize, uint32_t num);
+extern ER sdcard_blockwrite(SDCARD_Handler_t *hsd, uint32_t *pbuf, uint64_t WriteAddr, uint32_t blocksize, uint32_t num);
+extern ER sdcard_wait_transfar(SDCARD_Handler_t *hsd, uint32_t Timeout);
+extern ER sdcard_dummy(SDCARD_Handler_t *hsd);
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _SPI_DRIVER_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/staudio_wm8994/Makefile.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/staudio_wm8994/Makefile.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/staudio_wm8994/Makefile.config	(revision 453)
@@ -0,0 +1,55 @@
+#
+#   TOPPERS/ASP/FMP Kernel
+#       Toyohashi Open Platform for Embedded Real-Time Systems/
+#       Advanced Standard Profile Kernel
+#
+#   Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                               Toyohashi Univ. of Technology, JAPAN
+#   Copyright (C) 2003-2008 by Ryosuke Takeuchi
+#                Platform Development Center RICOH COMPANY,LTD. JAPAN
+#   Copyright (C) 2015-2018 by TOPPERS PROJECT Educational Working Group.
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+ 
+#
+#  Makefile のプロセッサ依存 (wm8994用)
+#
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/gdic/staudio_wm8994
+
+#
+#  USB DEVICE(GDIC)に関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR):$(SRCDIR)/gdic/staudio_wm8994
+SYSSVC_COBJS := $(SYSSVC_COBJS) staudio_wm8994.o
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/staudio_wm8994/staudio_wm8994.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/staudio_wm8994/staudio_wm8994.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/staudio_wm8994/staudio_wm8994.c	(revision 453)
@@ -0,0 +1,2471 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/**
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+#include "staudio_wm8994.h"
+#include <sil.h>
+#include <target_syssvc.h>
+#include <stdlib.h>
+
+/*
+ *  SIL関数のマクロ定義
+ */
+#define sil_orw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) | (b))
+#define sil_andw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) & ~(b))
+#define sil_modw_mem(a, b, c)	sil_wrw_mem((a), (sil_rew_mem(a) & (~b)) | (c))
+
+/* Uncomment this line to enable verifying data sent to codec after each write 
+   operation (for debug purpose) */
+#if !defined (VERIFY_WRITTENDATA)  
+/* #define VERIFY_WRITTENDATA */
+#endif /* VERIFY_WRITTENDATA */
+
+typedef struct
+{
+  uint16_t      *pRecBuf;       /* Pointer to record user buffer */
+  uint32_t      RecSize;        /* Size to record in mono, double size to record in stereo */
+}AUDIOIN_TypeDef;
+
+#define AUDIO_FREQUENCY_192K          ((uint32_t)192000)
+#define AUDIO_FREQUENCY_96K           ((uint32_t)96000)
+#define AUDIO_FREQUENCY_48K           ((uint32_t)48000)
+#define AUDIO_FREQUENCY_44K           ((uint32_t)44100)
+#define AUDIO_FREQUENCY_32K           ((uint32_t)32000)
+#define AUDIO_FREQUENCY_22K           ((uint32_t)22050)
+#define AUDIO_FREQUENCY_16K           ((uint32_t)16000)
+#define AUDIO_FREQUENCY_11K           ((uint32_t)11025)
+#define AUDIO_FREQUENCY_8K            ((uint32_t)8000)  
+
+/*### RECORD ###*/
+#define DFSDM_OVER_SAMPLING(__FREQUENCY__) \
+        (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 256 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 256 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 128 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 128 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 64 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 64  \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 40 : 20  \
+
+#define DFSDM_CLOCK_DIVIDER(__FREQUENCY__) \
+        (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 24 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 4 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 24 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 24 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 4  \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 25 : 25  \
+
+#define DFSDM_FILTER_ORDER(__FREQUENCY__) \
+        (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? DFSDM_FILTER_SINC3_ORDER \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? DFSDM_FILTER_SINC3_ORDER \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? DFSDM_FILTER_SINC3_ORDER \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? DFSDM_FILTER_SINC3_ORDER \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? DFSDM_FILTER_SINC4_ORDER \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? DFSDM_FILTER_SINC3_ORDER  \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? DFSDM_FILTER_SINC3_ORDER : DFSDM_FILTER_SINC5_ORDER  \
+
+#define DFSDM_RIGHT_BIT_SHIFT(__FREQUENCY__) \
+        (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 8 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 8 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 3 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 7 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 0  \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 0 : 4  \
+
+/* Saturate the record PCM sample */
+#define SaturaLH(N, L, H) (((N)<(L))?(L):(((N)>(H))?(H):(N)))
+
+
+#ifdef TOPPERS_STM32F769_DISCOVERY
+
+#define GPIO_AF3_DFSDM1         ((uint8_t)0x03U)  /* DFSDM1 Alternate Function mapping */
+
+#define AUDIO_DFSDMx_DMIC_DATIN_GPIO_CLK_ENABLE()       sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB1ENR), RCC_AHB1ENR_GPIOCEN)
+#define AUDIO_DFSDMx_CKOUT_DMIC_GPIO_CLK_ENABLE()       sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB1ENR), RCC_AHB1ENR_GPIODEN)
+
+#define AUDIO_DFSDMx_TOP_RIGHT_CHANNEL                  DFSDM_CHANNEL_0
+#define AUDIO_DFSDMx_TOP_LEFT_CHANNEL                   DFSDM_CHANNEL_1
+#define AUDIO_DFSDMx_BUTTOM_RIGHT_CHANNEL               DFSDM_CHANNEL_4
+#define AUDIO_DFSDMx_BUTTOM_LEFT_CHANNEL                DFSDM_CHANNEL_5
+
+#define AUDIO_DFSDMx_TOP_LEFT_FILTER                    TADR_DFSDM1_FILTER0_BASE
+#define AUDIO_DFSDMx_TOP_RIGHT_FILTER                   TADR_DFSDM1_FILTER1_BASE
+#define AUDIO_DFSDMx_BUTTOM_LEFT_FILTER                 TADR_DFSDM1_FILTER2_BASE
+#define AUDIO_DFSDMx_BUTTOM_RIGHT_FILTER                TADR_DFSDM1_FILTER3_BASE
+
+#define AUDIO_DFSDMx_CKOUT_DMIC_GPIO_PORT               TADR_GPIOD_BASE
+#define AUDIO_DFSDMx_CKOUT_PINNO                        3
+#define AUDIO_DFSDMx_DMIC_DATIN_GPIO_PORT               TADR_GPIOC_BASE
+#define AUDIO_DFSDMx_DMIC_DATIN1_PINNO                  3
+#define AUDIO_DFSDMx_DMIC_DATIN5_PINNO                  11
+#define AUDIO_DFSDMx_DMIC_DATIN_AF                      GPIO_AF3_DFSDM1
+#define AUDIO_DFSDMx_CKOUT_AF                           GPIO_AF3_DFSDM1
+
+#define AUDIO_DFSDMx_DMAx_BUTTOM_LEFT_STREAM            TADR_DMA2_STM6_BASE
+#define AUDIO_DFSDMx_DMAx_BUTTOM_RIGHT_STREAM           TADR_DMA2_STM7_BASE
+
+#define AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE              DMA_PDATAALIGN_WORD
+#define AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE                 DMA_MDATAALIGN_WORD
+
+#define AUDIO_DFSDMx_DMAx_CHANNEL                       DMA_CHANNEL_8
+
+
+/* RECORD */
+static STAUDIO_Handle_t     *hstaudio;
+AUDIOIN_TypeDef             hAudioIn;
+
+DFSDM_Channel_Handle_t      hAudioInTopLeftChannel;
+DFSDM_Channel_Handle_t      hAudioInTopRightChannel;
+DFSDM_Filter_Handle_t       hAudioInTopLeftFilter;
+DFSDM_Filter_Handle_t       hAudioInTopRightFilter;
+DMA_Handle_t                hDmaTopLeft;
+DMA_Handle_t                hDmaTopRight;
+
+DFSDM_Channel_Handle_t      hAudioInButtomLeftChannel;
+DFSDM_Channel_Handle_t      hAudioInButtomRightChannel;
+DFSDM_Filter_Handle_t       hAudioInButtomLeftFilter;
+DFSDM_Filter_Handle_t       hAudioInButtomRightFilter;
+DMA_Handle_t                hDmaButtomLeft;
+DMA_Handle_t                hDmaButtomRight;
+
+/* Buffers for right and left samples */
+static int32_t              *pScratchBuff[2*DEFAULT_AUDIO_IN_CHANNEL_NBR];
+static volatile int32_t     ScratchSize;
+/* Cannel number to be used: 2 channels by default */
+static uint8_t              AudioIn_ChannelNumber = DEFAULT_AUDIO_IN_CHANNEL_NBR;
+
+/* Buffers status flags */
+static uint32_t             DmaTopLeftRecHalfCplt  = 0;
+static uint32_t             DmaTopLeftRecCplt      = 0;
+static uint32_t             DmaTopRightRecHalfCplt = 0;
+static uint32_t             DmaTopRightRecCplt     = 0;
+static uint32_t             DmaButtomLeftRecHalfCplt  = 0;
+static uint32_t             DmaButtomLeftRecCplt      = 0;
+static uint32_t             DmaButtomRightRecHalfCplt = 0;
+static uint32_t             DmaButtomRightRecCplt     = 0;
+
+/* Application Buffer Trigger */
+static volatile uint32_t    AppBuffTrigger          = 0;
+static volatile uint32_t    AppBuffHalf             = 0;
+#endif
+
+
+/** @defgroup WM8994_Function_Prototypes
+  * @{
+  */
+static uint32_t wm8994_SetVolume(STAUDIO_Handle_t *haudio, uint8_t Volume);
+static uint32_t wm8994_SetMute(STAUDIO_Handle_t *haudio, uint32_t Cmd);
+
+
+/**
+  * @brief  Writes/Read a single data.
+  * @param  Addr: I2C address
+  * @param  Reg: Reg address 
+  * @param  Value: Data to be written
+  * @retval None
+  */
+static uint8_t
+CODEC_IO_Write(STAUDIO_Handle_t *haudio, uint16_t Reg, uint16_t Value)
+{
+	ER ercd;
+	uint8_t  buffer[4];
+	uint32_t result = 0;
+
+	buffer[0] = (uint8_t)(Value >> 8);
+	buffer[1] = (uint8_t)Value;
+	ercd = i2c_memwrite(haudio->hi2c, haudio->i2caddress, (uint16_t)Reg, I2C_MEMADD_SIZE_16BIT, buffer, 2, 1000);
+
+	/* Check the communication status */
+	if(ercd != E_OK){
+#if 1	/* ROI DEBUG */
+		syslog_2(LOG_NOTICE, "## I2Cx_Error(%08x, %02x) ##", haudio->hi2c, haudio->i2caddress);
+#endif	/* ROI DEBUG */
+		/* De-initialize the I2C communication bus */
+		i2c_deinit(haudio->hi2c);
+
+		/* Re-Initialize the I2C communication bus */
+		i2c_init(haudio->hi2c->i2cid, &haudio->hi2c->Init);
+	}
+
+#ifdef VERIFY_WRITTENDATA
+	{
+		uint16_t  value;
+		ercd = i2c_memread(haudio->hi2c, haudio->i2caddress, (uint16_t)Reg, I2C_MEMADD_SIZE_16BIT, buffer, 2, 1000);
+		value = (buffer[0] << 8) | buffer[1];
+		/* Verify that the data has been correctly written */
+		result = (value == Value)? 0:1;
+	}
+#endif /* VERIFY_WRITTENDATA */
+	return result;
+}
+
+/**
+  * @brief Initializes the audio codec and the control interface.
+  * @param DeviceAddr: Device address on communication Bus.   
+  * @param OutputInputDevice: can be OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
+  *  OUTPUT_DEVICE_BOTH, OUTPUT_DEVICE_AUTO, INPUT_DEVICE_DIGITAL_MICROPHONE_1,
+  *  INPUT_DEVICE_DIGITAL_MICROPHONE_2, INPUT_DEVICE_DIGITAL_MIC1_MIC2, 
+  *  INPUT_DEVICE_INPUT_LINE_1 or INPUT_DEVICE_INPUT_LINE_2.
+  * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max))
+  * @param AudioFreq: Audio Frequency 
+  * @retval 0 if correct communication, else wrong communication
+  */
+static uint32_t
+wm8994_Init(STAUDIO_Handle_t *haudio, uint16_t OutputInputDevice, uint8_t Volume, uint32_t AudioFreq)
+{
+	uint32_t counter = 0;
+	uint16_t output_device = OutputInputDevice & 0xFF;
+	uint16_t input_device = OutputInputDevice & 0xFF00;
+	uint16_t power_mgnt_reg_1 = 0;
+
+	/* wm8994 Errata Work-Arounds */
+	counter += CODEC_IO_Write(haudio, 0x102, 0x0003);
+	counter += CODEC_IO_Write(haudio, 0x817, 0x0000);
+	counter += CODEC_IO_Write(haudio, 0x102, 0x0000);
+
+	/* Enable VMID soft start (fast), Start-up Bias Current Enabled */
+	counter += CODEC_IO_Write(haudio, 0x39, 0x006C);
+
+	/* Enable bias generator, Enable VMID */
+	if(input_device > 0){
+		counter += CODEC_IO_Write(haudio, 0x01, 0x0013);
+	}
+	else{
+		counter += CODEC_IO_Write(haudio, 0x01, 0x0003);
+	}
+
+	/* Add Delay */
+	dly_tsk(50);
+
+	/* Path Configurations for output */
+	if(output_device > 0){
+		haudio->outputEnabled = 1;
+
+		switch(output_device){
+		case OUTPUT_DEVICE_SPEAKER:
+			/* Enable DAC1 (Left), Enable DAC1 (Right),
+			   Disable DAC2 (Left), Disable DAC2 (Right)*/
+			counter += CODEC_IO_Write(haudio, 0x05, 0x0C0C);
+
+			/* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */
+			counter += CODEC_IO_Write(haudio, 0x601, 0x0000);
+
+			/* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */
+			counter += CODEC_IO_Write(haudio, 0x602, 0x0000);
+
+			/* Disable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */
+			counter += CODEC_IO_Write(haudio, 0x604, 0x0002);
+
+			/* Disable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */
+			counter += CODEC_IO_Write(haudio, 0x605, 0x0002);
+			break;
+
+		case OUTPUT_DEVICE_HEADPHONE:
+			/* Disable DAC1 (Left), Disable DAC1 (Right),
+			   Enable DAC2 (Left), Enable DAC2 (Right)*/
+			counter += CODEC_IO_Write(haudio, 0x05, 0x0303);
+
+			/* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */
+			counter += CODEC_IO_Write(haudio, 0x601, 0x0001);
+
+			/* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */
+			counter += CODEC_IO_Write(haudio, 0x602, 0x0001);
+
+			/* Disable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */
+			counter += CODEC_IO_Write(haudio, 0x604, 0x0000);
+
+			/* Disable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */
+			counter += CODEC_IO_Write(haudio, 0x605, 0x0000);
+			break;
+
+		case OUTPUT_DEVICE_BOTH:
+			if(input_device == INPUT_DEVICE_DIGITAL_MIC1_MIC2){
+				/* Enable DAC1 (Left), Enable DAC1 (Right),
+				   also Enable DAC2 (Left), Enable DAC2 (Right)*/
+				counter += CODEC_IO_Write(haudio, 0x05, 0x0303 | 0x0C0C);
+
+				/* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path
+				  Enable the AIF1 Timeslot 1 (Left) to DAC 1 (Left) mixer path */
+				counter += CODEC_IO_Write(haudio, 0x601, 0x0003);
+
+				/* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path
+				   Enable the AIF1 Timeslot 1 (Right) to DAC 1 (Right) mixer path */
+				counter += CODEC_IO_Write(haudio, 0x602, 0x0003);
+
+				/* Enable the AIF1 Timeslot 0 (Left) to DAC 2 (Left) mixer path
+				   Enable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path  */
+				counter += CODEC_IO_Write(haudio, 0x604, 0x0003);
+
+				/* Enable the AIF1 Timeslot 0 (Right) to DAC 2 (Right) mixer path
+				   Enable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */
+				counter += CODEC_IO_Write(haudio, 0x605, 0x0003);
+			}
+			else{
+				/* Enable DAC1 (Left), Enable DAC1 (Right),
+				   also Enable DAC2 (Left), Enable DAC2 (Right)*/
+				counter += CODEC_IO_Write(haudio, 0x05, 0x0303 | 0x0C0C);
+
+				/* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */
+				counter += CODEC_IO_Write(haudio, 0x601, 0x0001);
+
+				/* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */
+				counter += CODEC_IO_Write(haudio, 0x602, 0x0001);
+
+				/* Enable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */
+				counter += CODEC_IO_Write(haudio, 0x604, 0x0002);
+
+				/* Enable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */
+				counter += CODEC_IO_Write(haudio, 0x605, 0x0002);      
+			}
+			break;
+
+		case OUTPUT_DEVICE_AUTO :
+		default:
+			/* Disable DAC1 (Left), Disable DAC1 (Right),
+			   Enable DAC2 (Left), Enable DAC2 (Right)*/
+			counter += CODEC_IO_Write(haudio, 0x05, 0x0303);
+
+			/* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */
+			counter += CODEC_IO_Write(haudio, 0x601, 0x0001);
+
+			/* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */
+			counter += CODEC_IO_Write(haudio, 0x602, 0x0001);
+
+			/* Disable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */
+			counter += CODEC_IO_Write(haudio, 0x604, 0x0000);
+
+			/* Disable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */
+			counter += CODEC_IO_Write(haudio, 0x605, 0x0000);
+			break;
+		}
+	}
+	else{
+		haudio->outputEnabled = 0;
+	}
+
+	/* Path Configurations for input */
+	if(input_device > 0){
+		haudio->inputEnabled = 1;
+		switch(input_device){
+		case INPUT_DEVICE_DIGITAL_MICROPHONE_2 :
+			/* Enable AIF1ADC2 (Left), Enable AIF1ADC2 (Right)
+			 * Enable DMICDAT2 (Left), Enable DMICDAT2 (Right)
+			 * Enable Left ADC, Enable Right ADC */
+			counter += CODEC_IO_Write(haudio, 0x04, 0x0C30);
+
+			/* Enable AIF1 DRC2 Signal Detect & DRC in AIF1ADC2 Left/Right Timeslot 1 */
+			counter += CODEC_IO_Write(haudio, 0x450, 0x00DB);
+
+			/* Disable IN1L, IN1R, IN2L, IN2R, Enable Thermal sensor & shutdown */
+			counter += CODEC_IO_Write(haudio, 0x02, 0x6000);
+
+			/* Enable the DMIC2(Left) to AIF1 Timeslot 1 (Left) mixer path */
+			counter += CODEC_IO_Write(haudio, 0x608, 0x0002);
+
+			/* Enable the DMIC2(Right) to AIF1 Timeslot 1 (Right) mixer path */
+			counter += CODEC_IO_Write(haudio, 0x609, 0x0002);
+
+			/* GPIO1 pin configuration GP1_DIR = output, GP1_FN = AIF1 DRC2 signal detect */
+			counter += CODEC_IO_Write(haudio, 0x700, 0x000E);
+			break;
+
+		case INPUT_DEVICE_INPUT_LINE_1 :
+			/* IN1LN_TO_IN1L, IN1LP_TO_VMID, IN1RN_TO_IN1R, IN1RP_TO_VMID */
+			counter += CODEC_IO_Write(haudio, 0x28, 0x0011);
+
+			/* Disable mute on IN1L_TO_MIXINL and +30dB on IN1L PGA output */
+			counter += CODEC_IO_Write(haudio, 0x29, 0x0035);
+
+			/* Disable mute on IN1R_TO_MIXINL, Gain = +30dB */
+			counter += CODEC_IO_Write(haudio, 0x2A, 0x0035);
+
+			/* Enable AIF1ADC1 (Left), Enable AIF1ADC1 (Right)
+			 * Enable Left ADC, Enable Right ADC */
+			counter += CODEC_IO_Write(haudio, 0x04, 0x0303);
+
+			/* Enable AIF1 DRC1 Signal Detect & DRC in AIF1ADC1 Left/Right Timeslot 0 */
+			counter += CODEC_IO_Write(haudio, 0x440, 0x00DB);
+
+			/* Enable IN1L and IN1R, Disable IN2L and IN2R, Enable Thermal sensor & shutdown */
+			counter += CODEC_IO_Write(haudio, 0x02, 0x6350);
+
+			/* Enable the ADCL(Left) to AIF1 Timeslot 0 (Left) mixer path */
+			counter += CODEC_IO_Write(haudio, 0x606, 0x0002);
+
+			/* Enable the ADCR(Right) to AIF1 Timeslot 0 (Right) mixer path */
+			counter += CODEC_IO_Write(haudio, 0x607, 0x0002);
+
+			/* GPIO1 pin configuration GP1_DIR = output, GP1_FN = AIF1 DRC1 signal detect */
+			counter += CODEC_IO_Write(haudio, 0x700, 0x000D);
+			break;
+
+		case INPUT_DEVICE_DIGITAL_MICROPHONE_1 :
+			/* Enable AIF1ADC1 (Left), Enable AIF1ADC1 (Right)
+			 * Enable DMICDAT1 (Left), Enable DMICDAT1 (Right)
+			 * Enable Left ADC, Enable Right ADC */
+			counter += CODEC_IO_Write(haudio, 0x04, 0x030C);
+
+			/* Enable AIF1 DRC2 Signal Detect & DRC in AIF1ADC1 Left/Right Timeslot 0 */
+			counter += CODEC_IO_Write(haudio, 0x440, 0x00DB);
+
+			/* Disable IN1L, IN1R, IN2L, IN2R, Enable Thermal sensor & shutdown */
+			counter += CODEC_IO_Write(haudio, 0x02, 0x6350);
+
+			/* Enable the DMIC2(Left) to AIF1 Timeslot 0 (Left) mixer path */
+			counter += CODEC_IO_Write(haudio, 0x606, 0x0002);
+
+			/* Enable the DMIC2(Right) to AIF1 Timeslot 0 (Right) mixer path */
+			counter += CODEC_IO_Write(haudio, 0x607, 0x0002);
+
+			/* GPIO1 pin configuration GP1_DIR = output, GP1_FN = AIF1 DRC1 signal detect */
+			counter += CODEC_IO_Write(haudio, 0x700, 0x000D);
+			break;
+		case INPUT_DEVICE_DIGITAL_MIC1_MIC2 :
+			/* Enable AIF1ADC1 (Left), Enable AIF1ADC1 (Right)
+			 * Enable DMICDAT1 (Left), Enable DMICDAT1 (Right)
+			 * Enable Left ADC, Enable Right ADC */
+			counter += CODEC_IO_Write(haudio, 0x04, 0x0F3C);
+
+			/* Enable AIF1 DRC2 Signal Detect & DRC in AIF1ADC2 Left/Right Timeslot 1 */
+			counter += CODEC_IO_Write(haudio, 0x450, 0x00DB);
+
+			/* Enable AIF1 DRC2 Signal Detect & DRC in AIF1ADC1 Left/Right Timeslot 0 */
+			counter += CODEC_IO_Write(haudio, 0x440, 0x00DB);
+
+			/* Disable IN1L, IN1R, Enable IN2L, IN2R, Thermal sensor & shutdown */
+			counter += CODEC_IO_Write(haudio, 0x02, 0x63A0);
+
+			/* Enable the DMIC2(Left) to AIF1 Timeslot 0 (Left) mixer path */
+			counter += CODEC_IO_Write(haudio, 0x606, 0x0002);
+
+			/* Enable the DMIC2(Right) to AIF1 Timeslot 0 (Right) mixer path */
+			counter += CODEC_IO_Write(haudio, 0x607, 0x0002);
+
+			/* Enable the DMIC2(Left) to AIF1 Timeslot 1 (Left) mixer path */
+			counter += CODEC_IO_Write(haudio, 0x608, 0x0002);
+
+			/* Enable the DMIC2(Right) to AIF1 Timeslot 1 (Right) mixer path */
+			counter += CODEC_IO_Write(haudio, 0x609, 0x0002);
+
+			/* GPIO1 pin configuration GP1_DIR = output, GP1_FN = AIF1 DRC1 signal detect */
+			counter += CODEC_IO_Write(haudio, 0x700, 0x000D);
+			break;
+		case INPUT_DEVICE_INPUT_LINE_2 :
+		default:
+			/* Actually, no other input devices supported */
+			counter++;
+			break;
+		}
+	}
+	else{
+		haudio->inputEnabled = 0;
+	}
+
+	/*  Clock Configurations */
+	switch (AudioFreq){
+	case  AUDIO_FREQUENCY_8K:
+		/* AIF1 Sample Rate = 8 (KHz), ratio=256 */ 
+		counter += CODEC_IO_Write(haudio, 0x210, 0x0003);
+		break;
+
+	case  AUDIO_FREQUENCY_16K:
+		/* AIF1 Sample Rate = 16 (KHz), ratio=256 */ 
+		counter += CODEC_IO_Write(haudio, 0x210, 0x0033);
+		break;
+
+	case  AUDIO_FREQUENCY_32K:
+		/* AIF1 Sample Rate = 32 (KHz), ratio=256 */ 
+		counter += CODEC_IO_Write(haudio, 0x210, 0x0063);
+		break;
+
+	case  AUDIO_FREQUENCY_48K:
+		/* AIF1 Sample Rate = 48 (KHz), ratio=256 */ 
+		counter += CODEC_IO_Write(haudio, 0x210, 0x0083);
+		break;
+
+	case  AUDIO_FREQUENCY_96K:
+		/* AIF1 Sample Rate = 96 (KHz), ratio=256 */ 
+		counter += CODEC_IO_Write(haudio, 0x210, 0x00A3);
+		break;
+
+	case  AUDIO_FREQUENCY_11K:
+		/* AIF1 Sample Rate = 11.025 (KHz), ratio=256 */ 
+		counter += CODEC_IO_Write(haudio, 0x210, 0x0013);
+		break;
+
+	case  AUDIO_FREQUENCY_22K:
+		/* AIF1 Sample Rate = 22.050 (KHz), ratio=256 */ 
+		counter += CODEC_IO_Write(haudio, 0x210, 0x0043);
+		break;
+
+	case  AUDIO_FREQUENCY_44K:
+		/* AIF1 Sample Rate = 44.1 (KHz), ratio=256 */ 
+		counter += CODEC_IO_Write(haudio, 0x210, 0x0073);
+		break;
+
+	default:
+		/* AIF1 Sample Rate = 48 (KHz), ratio=256 */ 
+		counter += CODEC_IO_Write(haudio, 0x210, 0x0083);
+		break;
+	}
+
+	if(input_device == INPUT_DEVICE_DIGITAL_MIC1_MIC2){
+		/* AIF1 Word Length = 16-bits, AIF1 Format = DSP mode */
+		counter += CODEC_IO_Write(haudio, 0x300, 0x4018);    
+	}
+	else{
+		/* AIF1 Word Length = 16-bits, AIF1 Format = I2S (Default Register Value) */
+		counter += CODEC_IO_Write(haudio, 0x300, 0x4010);
+	}
+
+	/* slave mode */
+	counter += CODEC_IO_Write(haudio, 0x302, 0x0000);
+
+	/* Enable the DSP processing clock for AIF1, Enable the core clock */
+	counter += CODEC_IO_Write(haudio, 0x208, 0x000A);
+
+	/* Enable AIF1 Clock, AIF1 Clock Source = MCLK1 pin */
+	counter += CODEC_IO_Write(haudio, 0x200, 0x0001);
+
+	if(output_device > 0){	/* Audio output selected */
+		if(output_device == OUTPUT_DEVICE_HEADPHONE){
+			/* Select DAC1 (Left) to Left Headphone Output PGA (HPOUT1LVOL) path */
+			counter += CODEC_IO_Write(haudio, 0x2D, 0x0100);
+
+			/* Select DAC1 (Right) to Right Headphone Output PGA (HPOUT1RVOL) path */
+			counter += CODEC_IO_Write(haudio, 0x2E, 0x0100);    
+
+			/* Startup sequence for Headphone */
+			if(haudio->ColdStartup){
+				counter += CODEC_IO_Write(haudio,0x110,0x8100);
+
+				haudio->ColdStartup = 0;
+				/* Add Delay */
+				dly_tsk(300);
+			}
+			else{	/* Headphone Warm Start-Up */
+				counter += CODEC_IO_Write(haudio,0x110,0x8108);
+				/* Add Delay */
+				dly_tsk(50);
+			}
+
+			/* Soft un-Mute the AIF1 Timeslot 0 DAC1 path L&R */
+			counter += CODEC_IO_Write(haudio, 0x420, 0x0000);
+		}
+		/* Analog Output Configuration */
+
+		/* Enable SPKRVOL PGA, Enable SPKMIXR, Enable SPKLVOL PGA, Enable SPKMIXL */
+		counter += CODEC_IO_Write(haudio, 0x03, 0x0300);
+
+		/* Left Speaker Mixer Volume = 0dB */
+		counter += CODEC_IO_Write(haudio, 0x22, 0x0000);
+
+		/* Speaker output mode = Class D, Right Speaker Mixer Volume = 0dB ((0x23, 0x0100) = class AB)*/
+		counter += CODEC_IO_Write(haudio, 0x23, 0x0000);
+
+		/* Unmute DAC2 (Left) to Left Speaker Mixer (SPKMIXL) path,
+		   Unmute DAC2 (Right) to Right Speaker Mixer (SPKMIXR) path */
+		counter += CODEC_IO_Write(haudio, 0x36, 0x0300);
+
+		/* Enable bias generator, Enable VMID, Enable SPKOUTL, Enable SPKOUTR */
+		counter += CODEC_IO_Write(haudio, 0x01, 0x3003);
+
+		/* Headphone/Speaker Enable */
+		if(input_device == INPUT_DEVICE_DIGITAL_MIC1_MIC2){
+			/* Enable Class W, Class W Envelope Tracking = AIF1 Timeslots 0 and 1 */
+			counter += CODEC_IO_Write(haudio, 0x51, 0x0205);
+		}
+		else{
+			/* Enable Class W, Class W Envelope Tracking = AIF1 Timeslot 0 */
+			counter += CODEC_IO_Write(haudio, 0x51, 0x0005);      
+		}
+
+		/* Enable bias generator, Enable VMID, Enable HPOUT1 (Left) and Enable HPOUT1 (Right) input stages */
+		/* idem for Speaker */
+		power_mgnt_reg_1 |= 0x0303 | 0x3003;
+		counter += CODEC_IO_Write(haudio, 0x01, power_mgnt_reg_1);
+
+		/* Enable HPOUT1 (Left) and HPOUT1 (Right) intermediate stages */
+		counter += CODEC_IO_Write(haudio, 0x60, 0x0022);
+
+		/* Enable Charge Pump */
+		counter += CODEC_IO_Write(haudio, 0x4C, 0x9F25);
+
+		/* Add Delay */
+		dly_tsk(15);
+
+		/* Select DAC1 (Left) to Left Headphone Output PGA (HPOUT1LVOL) path */
+		counter += CODEC_IO_Write(haudio, 0x2D, 0x0001);
+
+		/* Select DAC1 (Right) to Right Headphone Output PGA (HPOUT1RVOL) path */
+		counter += CODEC_IO_Write(haudio, 0x2E, 0x0001);
+
+		/* Enable Left Output Mixer (MIXOUTL), Enable Right Output Mixer (MIXOUTR) */
+		/* idem for SPKOUTL and SPKOUTR */
+		counter += CODEC_IO_Write(haudio, 0x03, 0x0030 | 0x0300);
+
+		/* Enable DC Servo and trigger start-up mode on left and right channels */
+		counter += CODEC_IO_Write(haudio, 0x54, 0x0033);
+
+		/* Add Delay */
+		dly_tsk(257);
+
+		/* Enable HPOUT1 (Left) and HPOUT1 (Right) intermediate and output stages. Remove clamps */
+		counter += CODEC_IO_Write(haudio, 0x60, 0x00EE);
+
+		/* Unmutes */
+
+		/* Unmute DAC 1 (Left) */
+		counter += CODEC_IO_Write(haudio, 0x610, 0x00C0);
+
+		/* Unmute DAC 1 (Right) */
+		counter += CODEC_IO_Write(haudio, 0x611, 0x00C0);
+
+		/* Unmute the AIF1 Timeslot 0 DAC path */
+		counter += CODEC_IO_Write(haudio, 0x420, 0x0010);
+
+		/* Unmute DAC 2 (Left) */
+		counter += CODEC_IO_Write(haudio, 0x612, 0x00C0);
+
+		/* Unmute DAC 2 (Right) */
+		counter += CODEC_IO_Write(haudio, 0x613, 0x00C0);
+
+		/* Unmute the AIF1 Timeslot 1 DAC2 path */
+		counter += CODEC_IO_Write(haudio, 0x422, 0x0010);
+
+		/* Volume Control */
+		wm8994_SetVolume(haudio, Volume);
+	}
+
+	if(input_device > 0){	/* Audio input selected */
+		if((input_device == INPUT_DEVICE_DIGITAL_MICROPHONE_1) || (input_device == INPUT_DEVICE_DIGITAL_MICROPHONE_2)){
+			/* Enable Microphone bias 1 generator, Enable VMID */
+			power_mgnt_reg_1 |= 0x0013;
+			counter += CODEC_IO_Write(haudio, 0x01, power_mgnt_reg_1);
+
+			/* ADC oversample enable */
+			counter += CODEC_IO_Write(haudio, 0x620, 0x0002);
+
+			/* AIF ADC2 HPF enable, HPF cut = voice mode 1 fc=127Hz at fs=8kHz */
+			counter += CODEC_IO_Write(haudio, 0x411, 0x3800);
+		}
+		else if(input_device == INPUT_DEVICE_DIGITAL_MIC1_MIC2){
+			/* Enable Microphone bias 1 generator, Enable VMID */
+			power_mgnt_reg_1 |= 0x0013;
+			counter += CODEC_IO_Write(haudio, 0x01, power_mgnt_reg_1);
+
+			/* ADC oversample enable */
+			counter += CODEC_IO_Write(haudio, 0x620, 0x0002);
+
+			/* AIF ADC1 HPF enable, HPF cut = voice mode 1 fc=127Hz at fs=8kHz */
+			counter += CODEC_IO_Write(haudio, 0x410, 0x1800);
+
+			/* AIF ADC2 HPF enable, HPF cut = voice mode 1 fc=127Hz at fs=8kHz */
+			counter += CODEC_IO_Write(haudio, 0x411, 0x1800);      
+		}
+		else if((input_device == INPUT_DEVICE_INPUT_LINE_1) || (input_device == INPUT_DEVICE_INPUT_LINE_2)){
+			/* Disable mute on IN1L, IN1L Volume = +0dB */
+			counter += CODEC_IO_Write(haudio, 0x18, 0x000B);
+
+			/* Disable mute on IN1R, IN1R Volume = +0dB */
+			counter += CODEC_IO_Write(haudio, 0x1A, 0x000B);
+
+			/* AIF ADC1 HPF enable, HPF cut = hifi mode fc=4Hz at fs=48kHz */
+			counter += CODEC_IO_Write(haudio, 0x410, 0x1800);
+		}
+		/* Volume Control */
+		wm8994_SetVolume(haudio, Volume);
+	}
+	/* Return communication control value */
+	return counter;
+}
+
+/**
+  * @brief Pauses playing on the audio codec.
+  * @param DeviceAddr: Device address on communication Bus. 
+  * @retval 0 if correct communication, else wrong communication
+  */
+static uint32_t
+wm8994_Pause(STAUDIO_Handle_t *haudio)
+{
+	uint32_t counter = 0;
+
+	/* Pause the audio file playing */
+	/* Mute the output first */
+	counter += wm8994_SetMute(haudio, AUDIO_MUTE_ON);
+
+	/* Put the Codec in Power save mode */
+	counter += CODEC_IO_Write(haudio, 0x02, 0x01);
+	return counter;
+}
+
+/**
+  * @brief Stops audio Codec playing. It powers down the codec.
+  * @param DeviceAddr: Device address on communication Bus. 
+  * @param CodecPdwnMode: selects the  power down mode.
+  *          - CODEC_PDWN_SW: only mutes the audio codec. When resuming from this 
+  *                           mode the codec keeps the previous initialization
+  *                           (no need to re-Initialize the codec registers).
+  *          - CODEC_PDWN_HW: Physically power down the codec. When resuming from this
+  *                           mode, the codec is set to default configuration 
+  *                           (user should re-Initialize the codec in order to 
+  *                            play again the audio stream).
+  * @retval 0 if correct communication, else wrong communication
+  */
+static uint32_t
+wm8994_Stop(STAUDIO_Handle_t *haudio, uint32_t CodecPdwnMode)
+{
+	uint32_t counter = 0;
+
+	if(haudio->outputEnabled != 0){
+		/* Mute the output first */
+		counter += wm8994_SetMute(haudio, AUDIO_MUTE_ON);
+
+		if(CodecPdwnMode == CODEC_PDWN_SW){
+			/* Only output mute required*/
+		}
+		else{	/* CODEC_PDWN_HW */
+			/* Mute the AIF1 Timeslot 0 DAC1 path */
+			counter += CODEC_IO_Write(haudio, 0x420, 0x0200);
+
+			/* Mute the AIF1 Timeslot 1 DAC2 path */
+			counter += CODEC_IO_Write(haudio, 0x422, 0x0200);
+
+			/* Disable DAC1L_TO_HPOUT1L */
+			counter += CODEC_IO_Write(haudio, 0x2D, 0x0000);
+
+			/* Disable DAC1R_TO_HPOUT1R */
+			counter += CODEC_IO_Write(haudio, 0x2E, 0x0000);
+
+			/* Disable DAC1 and DAC2 */
+			counter += CODEC_IO_Write(haudio, 0x05, 0x0000);
+
+			/* Reset Codec by writing in 0x0000 address register */
+			counter += CODEC_IO_Write(haudio, 0x0000, 0x0000);
+			haudio->outputEnabled = 0;
+		}
+	}
+	return counter;
+}
+
+/**
+  * @brief Sets higher or lower the codec volume level.
+  * @param DeviceAddr: Device address on communication Bus.
+  * @param Volume: a byte value from 0 to 255 (refer to codec registers 
+  *         description for more details).
+  * @retval 0 if correct communication, else wrong communication
+  */
+static uint32_t
+wm8994_SetVolume(STAUDIO_Handle_t *haudio, uint8_t Volume)
+{
+	uint32_t counter = 0;
+	uint8_t convertedvol = VOLUME_CONVERT(Volume);
+
+	/* Output volume */
+	if(haudio->outputEnabled != 0){
+		if(convertedvol > 0x3E){
+			/* Unmute audio codec */
+			counter += wm8994_SetMute(haudio, AUDIO_MUTE_OFF);
+
+			/* Left Headphone Volume */
+			counter += CODEC_IO_Write(haudio, 0x1C, 0x3F | 0x140);
+
+			/* Right Headphone Volume */
+			counter += CODEC_IO_Write(haudio, 0x1D, 0x3F | 0x140);
+
+			/* Left Speaker Volume */
+			counter += CODEC_IO_Write(haudio, 0x26, 0x3F | 0x140);
+
+			/* Right Speaker Volume */
+			counter += CODEC_IO_Write(haudio, 0x27, 0x3F | 0x140);
+		}
+		else if(Volume == 0){
+			/* Mute audio codec */
+			counter += wm8994_SetMute(haudio, AUDIO_MUTE_ON);
+		}
+		else{
+			/* Unmute audio codec */
+			counter += wm8994_SetMute(haudio, AUDIO_MUTE_OFF);
+
+			/* Left Headphone Volume */
+			counter += CODEC_IO_Write(haudio, 0x1C, convertedvol | 0x140);
+
+			/* Right Headphone Volume */
+			counter += CODEC_IO_Write(haudio, 0x1D, convertedvol | 0x140);
+
+			/* Left Speaker Volume */
+			counter += CODEC_IO_Write(haudio, 0x26, convertedvol | 0x140);
+
+			/* Right Speaker Volume */
+			counter += CODEC_IO_Write(haudio, 0x27, convertedvol | 0x140);
+		}
+	}
+
+	/* Input volume */
+	if(haudio->inputEnabled != 0){
+		convertedvol = VOLUME_IN_CONVERT(Volume);
+
+		/* Left AIF1 ADC1 volume */
+		counter += CODEC_IO_Write(haudio, 0x400, convertedvol | 0x100);
+
+		/* Right AIF1 ADC1 volume */
+		counter += CODEC_IO_Write(haudio, 0x401, convertedvol | 0x100);
+
+		/* Left AIF1 ADC2 volume */
+		counter += CODEC_IO_Write(haudio, 0x404, convertedvol | 0x100);
+
+		/* Right AIF1 ADC2 volume */
+		counter += CODEC_IO_Write(haudio, 0x405, convertedvol | 0x100);
+	}
+	return counter;
+}
+
+/**
+  * @brief Enables or disables the mute feature on the audio codec.
+  * @param DeviceAddr: Device address on communication Bus.   
+  * @param Cmd: AUDIO_MUTE_ON to enable the mute or AUDIO_MUTE_OFF to disable the
+  *             mute mode.
+  * @retval 0 if correct communication, else wrong communication
+  */
+static uint32_t
+wm8994_SetMute(STAUDIO_Handle_t *haudio, uint32_t Cmd)
+{
+	uint32_t counter = 0;
+
+	if(haudio->outputEnabled != 0){
+		/* Set the Mute mode */
+		if(Cmd == AUDIO_MUTE_ON){
+			/* Soft Mute the AIF1 Timeslot 0 DAC1 path L&R */
+			counter += CODEC_IO_Write(haudio, 0x420, 0x0200);
+
+			/* Soft Mute the AIF1 Timeslot 1 DAC2 path L&R */
+			counter += CODEC_IO_Write(haudio, 0x422, 0x0200);
+		}
+		else{	/* AUDIO_MUTE_OFF Disable the Mute */
+			/* Unmute the AIF1 Timeslot 0 DAC1 path L&R */
+			counter += CODEC_IO_Write(haudio, 0x420, 0x0010);
+
+			/* Unmute the AIF1 Timeslot 1 DAC2 path L&R */
+			counter += CODEC_IO_Write(haudio, 0x422, 0x0010);
+		}
+	}
+	return counter;
+}
+
+/**
+  * @brief Switch dynamically (while audio file is played) the output target 
+  *         (speaker or headphone).
+  * @param DeviceAddr: Device address on communication Bus.
+  * @param Output: specifies the audio output target: OUTPUT_DEVICE_SPEAKER,
+  *         OUTPUT_DEVICE_HEADPHONE, OUTPUT_DEVICE_BOTH or OUTPUT_DEVICE_AUTO 
+  * @retval 0 if correct communication, else wrong communication
+  */
+static uint32_t
+wm8994_SetOutputMode(STAUDIO_Handle_t *haudio, uint8_t Output)
+{
+	uint32_t counter = 0;
+
+	switch(Output){
+	case OUTPUT_DEVICE_SPEAKER:
+		/* Enable DAC1 (Left), Enable DAC1 (Right), 
+		  Disable DAC2 (Left), Disable DAC2 (Right)*/
+		counter += CODEC_IO_Write(haudio, 0x05, 0x0C0C);
+
+		/* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */
+		counter += CODEC_IO_Write(haudio, 0x601, 0x0000);
+
+		/* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */
+		counter += CODEC_IO_Write(haudio, 0x602, 0x0000);
+
+		/* Disable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */
+		counter += CODEC_IO_Write(haudio, 0x604, 0x0002);
+
+		/* Disable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */
+		counter += CODEC_IO_Write(haudio, 0x605, 0x0002);
+		break;
+
+	case OUTPUT_DEVICE_HEADPHONE:
+		/* Disable DAC1 (Left), Disable DAC1 (Right), 
+		  Enable DAC2 (Left), Enable DAC2 (Right)*/
+		counter += CODEC_IO_Write(haudio, 0x05, 0x0303);
+
+		/* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */
+		counter += CODEC_IO_Write(haudio, 0x601, 0x0001);
+
+		/* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */
+		counter += CODEC_IO_Write(haudio, 0x602, 0x0001);
+
+		/* Disable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */
+		counter += CODEC_IO_Write(haudio, 0x604, 0x0000);
+
+		/* Disable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */
+		counter += CODEC_IO_Write(haudio, 0x605, 0x0000);
+		break;
+
+	case OUTPUT_DEVICE_BOTH:
+		/* Enable DAC1 (Left), Enable DAC1 (Right), 
+		 also Enable DAC2 (Left), Enable DAC2 (Right)*/
+		counter += CODEC_IO_Write(haudio, 0x05, 0x0303 | 0x0C0C);
+
+		/* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */
+		counter += CODEC_IO_Write(haudio, 0x601, 0x0001);
+
+		/* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */
+		counter += CODEC_IO_Write(haudio, 0x602, 0x0001);
+
+		/* Enable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */
+		counter += CODEC_IO_Write(haudio, 0x604, 0x0002);
+
+		/* Enable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */
+		counter += CODEC_IO_Write(haudio, 0x605, 0x0002);
+		break;
+
+	default:
+		/* Disable DAC1 (Left), Disable DAC1 (Right), 
+		  Enable DAC2 (Left), Enable DAC2 (Right)*/
+		counter += CODEC_IO_Write(haudio, 0x05, 0x0303);
+
+		/* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */
+		counter += CODEC_IO_Write(haudio, 0x601, 0x0001);
+
+		/* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */
+		counter += CODEC_IO_Write(haudio, 0x602, 0x0001);
+
+		/* Disable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */
+		counter += CODEC_IO_Write(haudio, 0x604, 0x0000);
+
+		/* Disable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */
+		counter += CODEC_IO_Write(haudio, 0x605, 0x0000);
+		break;
+	}
+	return counter;
+}
+
+/**
+  * @brief Resets wm8994 registers.
+  * @param DeviceAddr: Device address on communication Bus. 
+  * @retval 0 if correct communication, else wrong communication
+  */
+static ER
+wm8994_Reset(STAUDIO_Handle_t *haudio)
+{
+	uint32_t deviceid = 0;
+	ER ercd;
+	uint8_t  buffer[4];
+
+	/* Get the WM8994 ID. */
+	ercd = i2c_memread(haudio->hi2c, haudio->i2caddress, (uint16_t)WM8994_CHIPID_ADDR, I2C_MEMADD_SIZE_16BIT, buffer, 2, 1000);
+	if(ercd != E_OK)
+		return ercd;
+	deviceid = (buffer[0] << 8) | buffer[1];
+
+	/* wm8994 codec initialization */
+#if 1	/* ROI DEBUG */
+	syslog_2(LOG_NOTICE, "## wm8994_Reset deviceid[%08x][%08x] ##", deviceid, WM8994_ID);
+#endif	/* ROI DEBUG */
+
+	if(deviceid != WM8994_ID)
+		return E_SYS;
+
+	/* Reset Codec by writing in 0x0000 address register */
+	CODEC_IO_Write(haudio, 0x0000, 0x0000);
+	haudio->outputEnabled = 0;
+	haudio->inputEnabled  = 0;
+	haudio->ColdStartup   = 1;
+	return E_OK;
+}
+
+
+static void SAIx_Out_Init(STAUDIO_Handle_t *haudio, uint32_t AudioFreq, uint16_t framesize)
+{
+	AUDIO_Handle_t *hsai = haudio->hsai;
+
+	/* Configure SAI_Block_x 
+	  LSBFirst: Disabled 
+	  DataSize: 16 */
+	hsai->OutInit.MonoStereoMode = SAI_STEREOMODE;
+	hsai->OutInit.AudioFrequency = AudioFreq;
+	hsai->OutInit.AudioMode = SAI_MODEMASTER_TX;
+	hsai->OutInit.NoDivider = SAI_MASTERDIVIDER_ENABLE;
+	hsai->OutInit.Protocol = SAI_FREE_PROTOCOL;
+	hsai->OutInit.DataSize = SAI_DATASIZE_16;
+	hsai->OutInit.FirstBit = SAI_FIRSTBIT_MSB;
+	hsai->OutInit.Synchro = SAI_ASYNCHRONOUS;
+#if defined(TOPPERS_STM32F769_DISCOVERY) || defined(TOPPERS_STM32F7_DISCOVERY)
+	hsai->OutInit.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
+	hsai->OutInit.OutputDrive = SAI_OUTPUTDRIVE_ENABLE;
+#else
+	hsai->OutInit.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
+	hsai->OutInit.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
+#endif
+	hsai->OutInit.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
+	hsai->OutInit.SynchroExt    = SAI_SYNCEXT_DISABLE;
+	hsai->OutInit.CompandingMode= SAI_NOCOMPANDING;
+	hsai->OutInit.TriState      = SAI_OUTPUT_NOTRELEASED;
+	hsai->OutInit.Mckdiv        = 0;
+
+	/* Configure SAI_Block_x Frame 
+	  Frame Length: 64
+	  Frame active Length: 32
+	  FS Definition: Start frame + Channel Side identification
+	  FS Polarity: FS active Low
+	  FS Offset: FS asserted one bit before the first bit of slot 0 */ 
+	hsai->OutInit.FrameLength = framesize;
+	hsai->OutInit.ActiveFrameLength = framesize / 2;
+	hsai->OutInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
+	hsai->OutInit.FSPolarity = SAI_FS_ACTIVE_LOW;
+	hsai->OutInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
+
+	/* Configure SAI Block_x Slot 
+	  Slot First Bit Offset: 0
+	  Slot Size  : 16
+	  Slot Number: 4
+	  Slot Active: All slot actives */
+	hsai->OutInit.FirstBitOffset = 0;
+	hsai->OutInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
+	hsai->OutInit.SlotNumber = 4; 
+	hsai->OutInit.SlotActive = CODEC_AUDIOFRAME_SLOT_0123;
+}
+
+
+/*
+ *  オーディオ出力初期化設定
+ *  param1: STAUDIOハンドラ
+ *  param2: 出力デバイス設定
+ *  param3: ボリューム設定値
+ *  param4: オーディオ周波数値
+ *  param5: フレームサイズ(バイト)
+ *  return: E_OKで正常設定
+ */
+ER
+staudio_out_init(STAUDIO_Handle_t *haudio, uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq, uint16_t framesize)
+{
+	AUDIO_Handle_t *hsai;
+	ER   ercd = E_OK;
+
+	/* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 
+	if(haudio->hsai == NULL){
+		haudio->hsai = audio_init(haudio->saiid);
+	}
+	else{
+		/* Disable SAI peripheral */
+		audio_disable(haudio->hsai, AUDIO_OUT_BLOCK);
+		audio_end(haudio->hsai, AUDIO_OUT_BLOCK);
+	}
+	hsai = haudio->hsai;
+	audio_clockconfig(hsai, AudioFreq, NULL);
+
+	/* SAI data transfer preparation:
+	  Prepare the Media to be used for the audio transfer from memory to SAI peripheral */
+	/* Disable SAI peripheral to allow access to SAI internal registers */
+	audio_disable(hsai, AUDIO_OUT_BLOCK);
+
+	SAIx_Out_Init(haudio, AudioFreq, framesize);
+
+	audio_start(hsai, AUDIO_OUT_BLOCK);
+
+	/* Enable SAI peripheral to generate MCLK */
+	audio_enable(hsai, AUDIO_OUT_BLOCK);
+
+	/* wm8994 codec initialization */
+	/* Reset the Codec Registers */
+	ercd = wm8994_Reset(haudio);
+	if(ercd == E_OK){
+		/* Initialize the codec internal registers */
+		wm8994_Init(haudio, OutputDevice, Volume, AudioFreq);
+	}
+	return ercd;
+}
+
+/*
+ *  オーディオ出力演奏
+ *  param1: STAUDIOハンドラ
+ *  param2: 出力バッファポインタ
+ *  param3: 出力バッファサイズ
+ *  return: E_OKで正常設定
+ */
+ER
+staudio_out_play(STAUDIO_Handle_t *haudio, uint16_t* pBuffer, uint32_t Size)
+{
+	AUDIO_Handle_t *hsai = haudio->hsai;
+
+	/* Call the audio Codec Play function */
+	if(wm8994_SetMute(haudio, AUDIO_MUTE_OFF) != 0){
+		return E_SYS;
+	}
+	else{
+		/* Update the Media layer and enable it for play */  
+		hsai->transcallback = haudio->audio_fullout_func;
+		hsai->transhalfcallback = haudio->audio_halfout_func;
+		hsai->errorcallback = haudio->audio_error_func;
+		audio_transmit(hsai, (uint8_t*) pBuffer, DMA_MAX(Size / AUDIODATA_SIZE));
+		return E_OK;
+	}
+}
+
+/*
+ *  オーディオPAUSE設定
+ *  param1: STAUDIOハンドラ
+ *  return: E_OKで正常設定
+ */
+ER
+staudio_out_pause(STAUDIO_Handle_t *haudio)
+{
+	/* Call the Audio Codec Pause/Resume function */
+	if(wm8994_Pause(haudio) != 0){
+		return E_SYS;
+	}
+	else{
+		/* Call the Media layer pause function */
+		audio_dmapause(haudio->hsai, AUDIO_OUT_BLOCK);
+		return E_OK;
+	}
+}
+
+/*
+ *  オーディオRESUME設定
+ *  param1: STAUDIOハンドラ
+ *  return: E_OKで正常設定
+ */
+ER
+staudio_out_resume(STAUDIO_Handle_t *haudio)
+{
+	/* Call the Audio Codec Pause/Resume function */
+	if(wm8994_SetMute(haudio, AUDIO_MUTE_OFF) != 0){
+		return E_SYS;
+	}
+	else{
+		/* Call the Media layer pause/resume function */
+		audio_dmaresume(haudio->hsai, AUDIO_OUT_BLOCK);
+		return E_OK;
+	}
+}
+
+/*
+ *  オーディオ出力停止設定
+ *  param1: STAUDIOハンドラ
+ *  param2: 停止設定条件
+ *  return: E_OKで正常設定
+ */
+ER
+staudio_out_stop(STAUDIO_Handle_t *haudio, uint32_t Option)
+{
+	/* Call the Media layer stop function */
+	audio_dmastop(haudio->hsai, AUDIO_OUT_BLOCK);
+
+	/* Call Audio Codec Stop function */
+	if(wm8994_Stop(haudio, Option) != 0){
+		return E_SYS;
+	}
+	else{
+		if(Option == CODEC_PDWN_HW){
+			/* Wait at least 100us */
+			dly_tsk(1);
+		}
+		return E_OK;
+	}
+}
+
+/*
+ *  オーディオボリューム設定
+ *  param1: STAUDIOハンドラ
+ *  param2: volumeパセンテージ(0%-100%)
+ *  return: E_OKで正常設定
+ */
+ER
+staudio_out_setvolume(STAUDIO_Handle_t *haudio, uint8_t Volume)
+{
+	/* Call the codec volume control function with converted volume value */
+	if(wm8994_SetVolume(haudio, Volume) != 0)
+		return E_SYS;
+	else
+		return E_OK;
+}
+
+/*
+ *  オーディオMUTE設定
+ *  param1: STAUDIOハンドラ
+ *  param2: MUTE設定コマンド(AUDIO_MUTE_ONまたはAUDIO_MUTE_OFF)
+ *  return: E_OKで正常設定
+ */
+ER
+staudio_out_setmute(STAUDIO_Handle_t *haudio, uint32_t Cmd)
+{
+	/* Call the Codec Mute function */
+	if(wm8994_SetMute(haudio, Cmd) != 0)
+		return E_SYS;
+	else
+		return E_OK;
+}
+
+/*
+ *  オーディオ出力モード設定
+ *  param1: STAUDIOハンドラ
+ *  param2: 出力モード(OUTPUT_DEVICE_SPEAKER,UTPUT_DEVICE_HEADPHONEまたはOUTPUT_DEVICE_BOTH)
+ *  return: E_OKで正常設定
+ */
+ER
+staudio_out_setoutputmode(STAUDIO_Handle_t *haudio, uint8_t Output)
+{
+	/* Call the Codec output device function */
+	if(wm8994_SetOutputMode(haudio, Output) != 0)
+		return E_SYS;
+	else
+		return E_OK;
+}
+
+/*
+ *  オーディオ周波数設定
+ *  param1: STAUDIOハンドラ
+ *  param2: 周波数値
+ *  return: E_OKで正常設定
+ */
+void
+staudio_out_setfrequency(STAUDIO_Handle_t *haudio, uint32_t AudioFreq)
+{
+	/* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 
+	audio_clockconfig(haudio->hsai, AudioFreq, NULL);
+
+	/* Disable SAI peripheral to allow access to SAI internal registers */
+	audio_disable(haudio->hsai, AUDIO_OUT_BLOCK);
+
+	/* Update the SAI audio frequency configuration */
+	haudio->hsai->OutInit.AudioFrequency = AudioFreq;
+	audio_start(haudio->hsai, AUDIO_OUT_BLOCK);
+
+	/* Enable SAI peripheral to generate MCLK */
+	audio_enable(haudio->hsai, AUDIO_OUT_BLOCK);
+}
+
+/*
+ *  オーディオフレームスロット設定
+ *  param1: STAUDIOハンドラ
+ *  param2: フレームスロット値
+ */
+void
+staudio_out_setframeslot(STAUDIO_Handle_t *haudio, uint32_t AudioFrameSlot)
+{
+	/* Disable SAI peripheral to allow access to SAI internal registers */
+	audio_disable(haudio->hsai, AUDIO_OUT_BLOCK);
+
+	/* Update the SAI audio frame slot configuration */
+	haudio->hsai->OutInit.SlotActive = AudioFrameSlot;
+	audio_start(haudio->hsai, AUDIO_OUT_BLOCK);
+
+	/* Enable SAI peripheral to generate MCLK */
+	audio_enable(haudio->hsai, AUDIO_OUT_BLOCK);
+}
+
+/*
+ *  オーディオ出力バッファ変更
+ *  param1: STAUDIOハンドラ
+ *  param2: 出力バッファポインタ
+ *  param3: バッファサイズ
+ */
+void
+staudio_out_changebuffer(STAUDIO_Handle_t *haudio, uint16_t *pData, uint16_t Size)
+{
+	haudio->hsai->transcallback = haudio->audio_fullout_func;
+	haudio->hsai->transhalfcallback = haudio->audio_halfout_func;
+	haudio->hsai->errorcallback = haudio->audio_error_func;
+	audio_transmit(haudio->hsai, (uint8_t*)pData, Size);
+}
+
+/*
+ *  オーディオ出力処理終了
+ *  param1: STAUDIOハンドラ
+ */
+void
+staudio_out_deinit(STAUDIO_Handle_t *haudio)
+{
+	if(haudio->hsai != NULL){
+		/* Disable SAI peripheral */
+		audio_disable(haudio->hsai, AUDIO_OUT_BLOCK);
+		audio_end(haudio->hsai, AUDIO_OUT_BLOCK);
+		if(audio_status(haudio->hsai, AUDIO_IN_BLOCK) == AUDIO_STATUS_RESET){
+			/* DeInit the SAI MSP : this __weak function can be rewritten by the application */
+			audio_deinit(haudio->hsai, AUDIO_OUT_BLOCK);
+			haudio->hsai = NULL;
+		}
+	}
+}
+
+/*******************************************************************************
+                            Static Functions
+*******************************************************************************/
+/**
+  * @brief  Initializes the input Audio Codec audio interface (SAI).
+  * @param  SaiOutMode: SAI_MODEMASTER_TX (for record and playback in parallel)
+  *                     or SAI_MODEMASTER_RX (for record only).
+  * @param  SlotActive: CODEC_AUDIOFRAME_SLOT_02, CODEC_AUDIOFRAME_SLOT_13 or
+  *                     CODEC_AUDIOFRAME_SLOT_0123
+  * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
+  * @retval None
+  */
+static void SAIx_In_Init(STAUDIO_Handle_t *haudio, uint32_t SaiOutMode, uint32_t SlotActive, uint32_t AudioFreq)
+{
+	/* Initialize the haudio_out_sai instance parameters */
+	AUDIO_Handle_t *hsai = haudio->hsai;
+
+	/* Disable SAI peripheral to allow access to SAI internal registers */
+	audio_disable(hsai, AUDIO_OUT_BLOCK);
+
+	/* Configure SAI_Block_x
+	LSBFirst: Disabled
+	DataSize: 16 */
+	hsai->OutInit.AudioFrequency = AudioFreq;
+#ifdef TOPPERS_STM32F769_DISCOVERY
+	hsai->OutInit.AudioMode = SAI_MODEMASTER_RX;
+#else
+	hsai->OutInit.AudioMode = SaiOutMode;
+#endif
+	hsai->OutInit.MonoStereoMode = SAI_STEREOMODE;
+	hsai->OutInit.NoDivider = SAI_MASTERDIVIDER_ENABLE;
+	hsai->OutInit.Protocol = SAI_FREE_PROTOCOL;
+	hsai->OutInit.DataSize = SAI_DATASIZE_16;
+	hsai->OutInit.FirstBit = SAI_FIRSTBIT_MSB;
+#if defined(TOPPERS_STM32F769_DISCOVERY) || defined(TOPPERS_STM32F7_DISCOVERY)
+	hsai->OutInit.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
+	hsai->OutInit.OutputDrive = SAI_OUTPUTDRIVE_ENABLE;
+#else
+	hsai->OutInit.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
+	hsai->OutInit.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
+#endif
+	hsai->OutInit.Synchro = SAI_ASYNCHRONOUS;
+	hsai->OutInit.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
+#if defined(TOPPERS_STM32F769_DISCOVERY)
+	hsai->OutInit.SynchroExt    = SAI_SYNCEXT_DISABLE;
+#endif
+#ifndef TOPPERS_STM32F7_DISCOVERY
+	hsai->OutInit.CompandingMode= SAI_NOCOMPANDING;
+	hsai->OutInit.TriState      = SAI_OUTPUT_NOTRELEASED;
+	hsai->OutInit.Mckdiv        = 0;
+#endif
+
+	/* Configure SAI_Block_x Frame
+	Frame Length: 64
+	Frame active Length: 32
+	FS Definition: Start frame + Channel Side identification
+	FS Polarity: FS active Low
+	FS Offset: FS asserted one bit before the first bit of slot 0 */
+	hsai->OutInit.FrameLength = 64;
+	hsai->OutInit.ActiveFrameLength = 32;
+	hsai->OutInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
+	hsai->OutInit.FSPolarity = SAI_FS_ACTIVE_LOW;
+	hsai->OutInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
+
+	/* Configure SAI Block_x Slot
+	Slot First Bit Offset: 0
+	Slot Size  : 16
+	Slot Number: 4
+	Slot Active: All slot actives */
+	hsai->OutInit.FirstBitOffset = 0;
+	hsai->OutInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
+	hsai->OutInit.SlotNumber = 4;
+	hsai->OutInit.SlotActive = SlotActive;
+
+	audio_start(hsai, AUDIO_OUT_BLOCK);
+
+	/* Initialize SAI2 block B in SLAVE RX synchronous from SAI2 block A */
+	/* Initialize the haudio_in_sai Instance parameter */
+
+	/* Disable SAI peripheral to allow access to SAI internal registers */
+	audio_disable(hsai, AUDIO_IN_BLOCK);
+
+	/* Configure SAI_Block_x
+	LSBFirst: Disabled
+	DataSize: 16 */
+	hsai->InInit.AudioFrequency = AudioFreq;
+	hsai->InInit.AudioMode = SAI_MODESLAVE_RX;
+	hsai->InInit.NoDivider = SAI_MASTERDIVIDER_ENABLE;
+	hsai->InInit.Protocol = SAI_FREE_PROTOCOL;
+	hsai->InInit.DataSize = SAI_DATASIZE_16;
+	hsai->InInit.FirstBit = SAI_FIRSTBIT_MSB;
+	hsai->InInit.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
+	hsai->InInit.Synchro = SAI_SYNCHRONOUS;
+	hsai->InInit.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
+	hsai->InInit.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
+#ifdef TOPPERS_STM32F7_DISCOVERY
+	hsai->InInit.SynchroExt    = SAI_SYNCEXT_DISABLE;
+#endif
+#ifndef TOPPERS_STM32F7_DISCOVERY
+	hsai->InInit.CompandingMode= SAI_NOCOMPANDING;
+	hsai->InInit.TriState      = SAI_OUTPUT_NOTRELEASED;
+	hsai->InInit.Mckdiv        = 0;
+#endif
+
+	/* Configure SAI_Block_x Frame
+	Frame Length: 64
+	Frame active Length: 32
+	FS Definition: Start frame + Channel Side identification
+	FS Polarity: FS active Low
+	FS Offset: FS asserted one bit before the first bit of slot 0 */
+	hsai->InInit.FrameLength = 64;
+	hsai->InInit.ActiveFrameLength = 32;
+	hsai->InInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
+	hsai->InInit.FSPolarity = SAI_FS_ACTIVE_LOW;
+	hsai->InInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
+
+	/* Configure SAI Block_x Slot
+	Slot First Bit Offset: 0
+	Slot Size  : 16
+	Slot Number: 4
+	Slot Active: All slot active */
+	hsai->InInit.FirstBitOffset = 0;
+	hsai->InInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
+	hsai->InInit.SlotNumber = 4;
+	hsai->InInit.SlotActive = SlotActive;
+
+	audio_start(hsai, AUDIO_IN_BLOCK);
+
+	/* Enable SAI peripheral to generate MCLK */
+	audio_enable(hsai, AUDIO_OUT_BLOCK);
+
+	/* Enable SAI peripheral */
+	audio_enable(hsai, AUDIO_IN_BLOCK);
+}
+
+
+/**
+  * @brief  Deinitializes the output Audio Codec audio interface (SAI).
+  * @retval None
+  */
+static void SAIx_In_DeInit(STAUDIO_Handle_t *haudio)
+{
+	if(haudio->hsai != NULL){
+		/* Disable SAI peripheral */
+		audio_disable(haudio->hsai, AUDIO_IN_BLOCK);
+		audio_end(haudio->hsai, AUDIO_IN_BLOCK);
+		if(audio_status(haudio->hsai, AUDIO_OUT_BLOCK) == AUDIO_STATUS_RESET){
+			/* DeInit the SAI MSP : this __weak function can be rewritten by the application */
+			audio_deinit(haudio->hsai, AUDIO_IN_BLOCK);
+			haudio->hsai = NULL;
+		}
+	}
+}
+
+
+#ifdef TOPPERS_STM32F769_DISCOVERY
+/**
+  * @brief  Regular conversion complete callback. 
+  * @note   In interrupt mode, user has to read conversion value in this function
+            using HAL_DFSDM_FilterGetRegularValue.
+  * @param  hdfsdm_filter : DFSDM filter handle.
+  * @retval None
+  */
+static void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_Handle_t *hdfsdm_filter)
+{
+	uint32_t index = 0;
+
+	if(hdfsdm_filter == &hAudioInTopLeftFilter){
+		DmaTopLeftRecCplt = 1;
+	}
+	else if(hdfsdm_filter == &hAudioInTopRightFilter){
+		DmaTopRightRecCplt = 1;
+	}
+	else if(hdfsdm_filter == &hAudioInButtomLeftFilter){
+		DmaButtomLeftRecCplt = 1;
+	}
+	else{
+		DmaButtomRightRecCplt = 1;
+	}
+
+	if(AudioIn_ChannelNumber > 2){
+		if((DmaTopLeftRecCplt == 1) && (DmaTopRightRecCplt == 1) && (DmaButtomLeftRecCplt == 1) && (DmaButtomRightRecCplt == 1)){
+			for(index = (ScratchSize/2) ; index < ScratchSize; index++){
+				hAudioIn.pRecBuf[AppBuffTrigger]     = (uint16_t)(SaturaLH((pScratchBuff[1][index] >> 8), -32760, 32760));
+				hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[0][index] >> 8), -32760, 32760));       
+				hAudioIn.pRecBuf[AppBuffTrigger + 2] = (uint16_t)(SaturaLH((pScratchBuff[3][index] >> 8), -32760, 32760));
+				hAudioIn.pRecBuf[AppBuffTrigger + 3] = (uint16_t)(SaturaLH((pScratchBuff[2][index] >> 8), -32760, 32760));      
+				AppBuffTrigger +=4;
+			}
+			DmaTopLeftRecCplt  = 0;
+			DmaTopRightRecCplt = 0;
+			DmaButtomLeftRecCplt  = 0;
+			DmaButtomRightRecCplt = 0;
+		}
+	}
+	else{
+		if((DmaTopLeftRecCplt == 1) && (DmaTopRightRecCplt == 1)){
+			for(index = (ScratchSize/2) ; index < ScratchSize; index++){
+				hAudioIn.pRecBuf[AppBuffTrigger]     = (uint16_t)(SaturaLH((pScratchBuff[1][index] >> 8), -32760, 32760));
+				hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[0][index] >> 8), -32760, 32760));
+				AppBuffTrigger +=2;
+			}
+			DmaTopLeftRecCplt  = 0;
+			DmaTopRightRecCplt = 0;  
+		}
+	}
+
+	/* Call Half Transfer Complete callback */
+	if((AppBuffTrigger == hAudioIn.RecSize/2) && (AppBuffHalf == 0)){
+		AppBuffHalf = 1;
+		if(hstaudio != NULL && hstaudio->audio_halfin_func)
+			hstaudio->audio_halfin_func(hdfsdm_filter);
+	}
+	/* Call Transfer Complete callback */
+	if(AppBuffTrigger == hAudioIn.RecSize){
+		/* Reset Application Buffer Trigger */
+		AppBuffTrigger = 0;
+		AppBuffHalf = 0; 
+		/* Call the record update function to get the next buffer to fill and its size (size is ignored) */
+		if(hstaudio != NULL && hstaudio->audio_fullin_func)
+			hstaudio->audio_fullin_func(hdfsdm_filter);
+	}
+}
+
+/**
+  * @brief  Half regular conversion complete callback. 
+  * @param  hdfsdm_filter : DFSDM filter handle.
+  * @retval None
+  */
+static void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_Handle_t *hdfsdm_filter)
+{
+	uint32_t index = 0;
+
+	if(hdfsdm_filter == &hAudioInTopLeftFilter){
+		DmaTopLeftRecHalfCplt = 1;
+	}
+	else if(hdfsdm_filter == &hAudioInTopRightFilter){
+		DmaTopRightRecHalfCplt = 1;
+	}
+	else if(hdfsdm_filter == &hAudioInButtomLeftFilter){
+		DmaButtomLeftRecHalfCplt = 1;
+	}
+	else{
+		DmaButtomRightRecHalfCplt = 1;
+	}
+
+	if(AudioIn_ChannelNumber > 2){
+		if((DmaTopLeftRecHalfCplt == 1) && (DmaTopRightRecHalfCplt == 1) && (DmaButtomLeftRecHalfCplt == 1) && (DmaButtomRightRecHalfCplt == 1)){
+			for(index = 0 ; index < ScratchSize/2; index++){
+				hAudioIn.pRecBuf[AppBuffTrigger]     = (uint16_t)(SaturaLH((pScratchBuff[1][index] >> 8), -32760, 32760));
+				hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[0][index] >> 8), -32760, 32760)); 
+				hAudioIn.pRecBuf[AppBuffTrigger + 2] = (uint16_t)(SaturaLH((pScratchBuff[3][index] >> 8), -32760, 32760));
+				hAudioIn.pRecBuf[AppBuffTrigger + 3] = (uint16_t)(SaturaLH((pScratchBuff[2][index] >> 8), -32760, 32760));      
+ 				AppBuffTrigger +=4;
+			}
+			DmaTopLeftRecHalfCplt  = 0;
+			DmaTopRightRecHalfCplt = 0;
+			DmaButtomLeftRecHalfCplt  = 0;
+			DmaButtomRightRecHalfCplt = 0;
+		}
+	}
+	else{
+		if((DmaTopLeftRecHalfCplt == 1) && (DmaTopRightRecHalfCplt == 1)){
+			for(index = 0 ; index < ScratchSize/2; index++){
+				hAudioIn.pRecBuf[AppBuffTrigger]     = (uint16_t)(SaturaLH((pScratchBuff[1][index] >> 8), -32760, 32760));
+				hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[0][index] >> 8), -32760, 32760));
+				AppBuffTrigger +=2;
+			}
+			DmaTopLeftRecHalfCplt  = 0;
+			DmaTopRightRecHalfCplt = 0;
+		}
+	}
+
+	/* Call Half Transfer Complete callback */
+	if((AppBuffTrigger == hAudioIn.RecSize/2) && (AppBuffHalf == 0)){
+		AppBuffHalf = 1;
+		if(hstaudio != NULL && hstaudio->audio_halfin_func)
+			hstaudio->audio_halfin_func(hdfsdm_filter);
+	}
+	/* Call Transfer Complete callback */
+	if(AppBuffTrigger == hAudioIn.RecSize){
+		/* Reset Application Buffer Trigger */
+		AppBuffTrigger = 0;
+		AppBuffHalf = 0;
+		/* Call the record update function to get the next buffer to fill and its size (size is ignored) */
+		if(hstaudio != NULL && hstaudio->audio_fullin_func)
+			hstaudio->audio_fullin_func(hdfsdm_filter);
+	}
+}
+
+/*******************************************************************************
+                            Static Functions
+*******************************************************************************/
+/**
+  * @brief  Initialize the Digital Filter for Sigma-Delta Modulators interface (DFSDM).
+  * @param  AudioFreq: Audio frequency to be used to set correctly the DFSDM peripheral.
+  * @note   Channel output Clock Divider and Filter Oversampling are calculated as follow: 
+  *         - Clock_Divider = CLK(input DFSDM)/CLK(micro) with
+  *           1MHZ < CLK(micro) < 3.2MHZ (TYP 2.4MHZ for MP34DT01TR)
+  *         - Oversampling = CLK(input DFSDM)/(Clock_Divider * AudioFreq)  
+  * @retval AUDIO_OK if correct communication, else wrong communication
+  */
+static ER DFSDMx_Init(uint32_t AudioFreq)
+{
+	ER ercd = E_OK;
+
+	/****************************************************************************/ 
+	/********************** Channels configuration  *****************************/
+	/****************************************************************************/ 
+	/* CHANNEL 1 configuration */
+	hAudioInTopLeftChannel.state                         = DFSDM_CHANNEL_STATE_RESET;
+	hAudioInTopLeftChannel.base                          = (uint32_t)TADR_DFSDM1_CHANNEL1_BASE;
+	hAudioInTopLeftChannel.Init.OutClockActivation       = 1 /* ENABLE */;
+	hAudioInTopLeftChannel.Init.OutClockSelection        = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO;
+	/* Set the DFSDM clock OUT audio frequency configuration */
+	hAudioInTopLeftChannel.Init.OutClockDivider          = DFSDM_CLOCK_DIVIDER(AudioFreq);
+	hAudioInTopLeftChannel.Init.InputMultiplexer         = DFSDM_CHANNEL_EXTERNAL_INPUTS;
+	hAudioInTopLeftChannel.Init.InputDataPacking         = DFSDM_CHANNEL_STANDARD_MODE;
+	hAudioInTopLeftChannel.Init.InputPins                = DFSDM_CHANNEL_SAME_CHANNEL_PINS;
+	/* Request to sample stable data for LEFT micro on Rising edge */
+	hAudioInTopLeftChannel.Init.SerialType               = DFSDM_CHANNEL_SPI_RISING;
+	hAudioInTopLeftChannel.Init.SerialSpiClock           = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
+	hAudioInTopLeftChannel.Init.AwdFilterOrder           = DFSDM_CHANNEL_FASTSINC_ORDER;
+	hAudioInTopLeftChannel.Init.AwdOversampling          = 10;
+	hAudioInTopLeftChannel.Init.Offset                   = 0;
+	hAudioInTopLeftChannel.Init.RightBitShift            = DFSDM_RIGHT_BIT_SHIFT(AudioFreq);
+	if(E_OK != (ercd = dfsdm_channel_init(&hAudioInTopLeftChannel))){
+		return ercd;
+	}
+
+	/* CHANNEL 0 configuration */
+	hAudioInTopRightChannel.state                         = DFSDM_CHANNEL_STATE_RESET;
+	hAudioInTopRightChannel.base                          = (uint32_t)TADR_DFSDM1_CHANNEL0_BASE;
+	hAudioInTopRightChannel.Init.OutClockActivation       = 1 /* ENABLE*/;
+	hAudioInTopRightChannel.Init.OutClockSelection        = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO;
+	/* Set the DFSDM clock OUT audio frequency configuration */
+	hAudioInTopRightChannel.Init.OutClockDivider          = DFSDM_CLOCK_DIVIDER(AudioFreq);
+	hAudioInTopRightChannel.Init.InputMultiplexer         = DFSDM_CHANNEL_EXTERNAL_INPUTS;
+	hAudioInTopRightChannel.Init.InputDataPacking         = DFSDM_CHANNEL_STANDARD_MODE;
+	hAudioInTopRightChannel.Init.InputPins                = DFSDM_CHANNEL_FOLLOWING_CHANNEL_PINS;
+	/* Request to sample stable data for RIGHT micro on Falling edge */
+	hAudioInTopRightChannel.Init.SerialType               = DFSDM_CHANNEL_SPI_FALLING;
+	hAudioInTopRightChannel.Init.SerialSpiClock           = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
+	hAudioInTopRightChannel.Init.AwdFilterOrder           = DFSDM_CHANNEL_FASTSINC_ORDER;
+	hAudioInTopRightChannel.Init.AwdOversampling          = 10;
+	hAudioInTopRightChannel.Init.Offset                   = 0;
+	hAudioInTopRightChannel.Init.RightBitShift            = DFSDM_RIGHT_BIT_SHIFT(AudioFreq);
+	if(E_OK != (ercd = dfsdm_channel_init(&hAudioInTopRightChannel))){
+		return ercd;
+	}
+
+	if(AudioIn_ChannelNumber > 2){
+		/* CHANNEL 5 configuration */
+		hAudioInButtomLeftChannel.state                         = DFSDM_CHANNEL_STATE_RESET;
+		hAudioInButtomLeftChannel.base                          = (uint32_t)TADR_DFSDM1_CHANNEL5_BASE;
+		hAudioInButtomLeftChannel.Init.OutClockActivation       = 1 /* ENABLE */;
+		hAudioInButtomLeftChannel.Init.OutClockSelection        = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO;
+		/* Set the DFSDM clock OUT audio frequency configuration */
+		hAudioInButtomLeftChannel.Init.OutClockDivider          = DFSDM_CLOCK_DIVIDER(AudioFreq);
+		hAudioInButtomLeftChannel.Init.InputMultiplexer         = DFSDM_CHANNEL_EXTERNAL_INPUTS;
+		hAudioInButtomLeftChannel.Init.InputDataPacking         = DFSDM_CHANNEL_STANDARD_MODE;
+		hAudioInButtomLeftChannel.Init.InputPins                = DFSDM_CHANNEL_SAME_CHANNEL_PINS;
+		/* Request to sample stable data for LEFT micro on Rising edge */
+		hAudioInButtomLeftChannel.Init.SerialType               = DFSDM_CHANNEL_SPI_RISING;
+		hAudioInButtomLeftChannel.Init.SerialSpiClock           = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
+		hAudioInButtomLeftChannel.Init.AwdFilterOrder           = DFSDM_CHANNEL_FASTSINC_ORDER;
+		hAudioInButtomLeftChannel.Init.AwdOversampling          = 10;
+		hAudioInButtomLeftChannel.Init.Offset                   = 0;
+		hAudioInButtomLeftChannel.Init.RightBitShift            = DFSDM_RIGHT_BIT_SHIFT(AudioFreq);
+		if(E_OK != (ercd = dfsdm_channel_init(&hAudioInButtomLeftChannel))){
+			return ercd;
+		}
+
+		/* CHANNEL 4 configuration */
+		hAudioInButtomRightChannel.state                         = DFSDM_CHANNEL_STATE_RESET;
+		hAudioInButtomRightChannel.base                          = (uint32_t)TADR_DFSDM1_CHANNEL4_BASE;
+		hAudioInButtomRightChannel.Init.OutClockActivation       = 1 /* ENABLE */;
+		hAudioInButtomRightChannel.Init.OutClockSelection        = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO;
+		/* Set the DFSDM clock OUT audio frequency configuration */
+		hAudioInButtomRightChannel.Init.OutClockDivider          = DFSDM_CLOCK_DIVIDER(AudioFreq);
+		hAudioInButtomRightChannel.Init.InputMultiplexer         = DFSDM_CHANNEL_EXTERNAL_INPUTS;
+		hAudioInButtomRightChannel.Init.InputDataPacking         = DFSDM_CHANNEL_STANDARD_MODE;
+		hAudioInButtomRightChannel.Init.InputPins                = DFSDM_CHANNEL_FOLLOWING_CHANNEL_PINS;
+		/* Request to sample stable data for RIGHT micro on Falling edge */
+		hAudioInButtomRightChannel.Init.SerialType               = DFSDM_CHANNEL_SPI_FALLING;
+		hAudioInButtomRightChannel.Init.SerialSpiClock           = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
+		hAudioInButtomRightChannel.Init.AwdFilterOrder           = DFSDM_CHANNEL_FASTSINC_ORDER;
+		hAudioInButtomRightChannel.Init.AwdOversampling          = 10;
+		hAudioInButtomRightChannel.Init.Offset                   = 0;
+		hAudioInButtomRightChannel.Init.RightBitShift            = DFSDM_RIGHT_BIT_SHIFT(AudioFreq);
+		if(E_OK != (ercd = dfsdm_channel_init(&hAudioInButtomRightChannel))){
+			return ercd;
+		}
+	}
+	/****************************************************************************/ 
+	/********************** Filters configuration  ******************************/
+	/****************************************************************************/
+	/* FILTER 0 configuration */
+	hAudioInTopLeftFilter.state                             = DFSDM_FILTER_STATE_RESET;
+	hAudioInTopLeftFilter.base                              = (uint32_t)AUDIO_DFSDMx_TOP_LEFT_FILTER;
+	hAudioInTopLeftFilter.regconvhalfcallback               = HAL_DFSDM_FilterRegConvHalfCpltCallback;
+	hAudioInTopLeftFilter.regconvcallback                   = HAL_DFSDM_FilterRegConvCpltCallback;
+	hAudioInTopLeftFilter.Init.RegTrigger                   = DFSDM_FILTER_SW_TRIGGER;
+	hAudioInTopLeftFilter.Init.RegFastMode                  = 1 /* ENABLE */;
+	hAudioInTopLeftFilter.Init.RegDmaMode                   = 1 /* ENABLE */;
+	hAudioInTopLeftFilter.Init.InjTrigger                   = DFSDM_FILTER_SW_TRIGGER;
+	hAudioInTopLeftFilter.Init.InjScanMode                  = 1 /* ENABLE */;
+	hAudioInTopLeftFilter.Init.InjDmaMode                   = 0 /* DISABLE */;
+	hAudioInTopLeftFilter.Init.InjExtTrigger                = DFSDM_FILTER_EXT_TRIG_TIM1_TRGO;
+	hAudioInTopLeftFilter.Init.InjExtTriggerEdge            = DFSDM_FILTER_EXT_TRIG_RISING_EDGE;
+	hAudioInTopLeftFilter.Init.FilterSincOrder              = DFSDM_FILTER_ORDER(AudioFreq);
+	/* Set the DFSDM Filters Oversampling to have correct sample rate */
+	hAudioInTopLeftFilter.Init.FilterOversampling           = DFSDM_OVER_SAMPLING(AudioFreq);
+	hAudioInTopLeftFilter.Init.FilterIntOversampling        = 1;
+	if(E_OK != (ercd = dfsdm_filter_init(&hAudioInTopLeftFilter))){
+		return ercd;
+	}
+
+	/* Configure injected channel */
+	if(E_OK != (ercd = dfsdm_filter_config_reg(&hAudioInTopLeftFilter, AUDIO_DFSDMx_TOP_LEFT_CHANNEL, DFSDM_CONTINUOUS_CONV_ON))){
+		return ercd;
+	}
+
+	/* FILTER 1 configuration */
+	hAudioInTopRightFilter.state                             = DFSDM_FILTER_STATE_RESET;
+	hAudioInTopRightFilter.base                              = (uint32_t)AUDIO_DFSDMx_TOP_RIGHT_FILTER;
+	hAudioInTopRightFilter.regconvhalfcallback               = HAL_DFSDM_FilterRegConvHalfCpltCallback;
+	hAudioInTopRightFilter.regconvcallback                   = HAL_DFSDM_FilterRegConvCpltCallback;
+	hAudioInTopRightFilter.Init.RegTrigger                   = DFSDM_FILTER_SYNC_TRIGGER;
+	hAudioInTopRightFilter.Init.RegFastMode                  = 1 /* ENABLE */;
+	hAudioInTopRightFilter.Init.RegDmaMode                   = 1 /* ENABLE */;
+	hAudioInTopRightFilter.Init.InjTrigger                   = DFSDM_FILTER_SW_TRIGGER;
+	hAudioInTopRightFilter.Init.InjScanMode                  = 0 /* DISABLE */;
+	hAudioInTopRightFilter.Init.InjDmaMode                   = 0 /* DISABLE */;
+	hAudioInTopRightFilter.Init.InjExtTrigger                = DFSDM_FILTER_EXT_TRIG_TIM1_TRGO;
+	hAudioInTopRightFilter.Init.InjExtTriggerEdge            = DFSDM_FILTER_EXT_TRIG_RISING_EDGE;
+	hAudioInTopRightFilter.Init.FilterSincOrder              = DFSDM_FILTER_ORDER(AudioFreq);
+	/* Set the DFSDM Filters Oversampling to have correct sample rate */
+	hAudioInTopRightFilter.Init.FilterOversampling           = DFSDM_OVER_SAMPLING(AudioFreq);
+	hAudioInTopRightFilter.Init.FilterIntOversampling        = 1;
+	if(E_OK != (ercd = dfsdm_filter_init(&hAudioInTopRightFilter))){
+		return ercd;
+	}
+	/* Configure injected channel */
+	if(E_OK != (ercd = dfsdm_filter_config_reg(&hAudioInTopRightFilter, AUDIO_DFSDMx_TOP_RIGHT_CHANNEL, DFSDM_CONTINUOUS_CONV_ON))){
+		return ercd;
+	}
+
+	if(AudioIn_ChannelNumber > 2){
+		/* FILTER 2 configuration */
+		hAudioInButtomLeftFilter.state                             = DFSDM_FILTER_STATE_RESET;
+		hAudioInButtomLeftFilter.base                              = (uint32_t)AUDIO_DFSDMx_BUTTOM_LEFT_FILTER;
+		hAudioInButtomLeftFilter.regconvhalfcallback               = HAL_DFSDM_FilterRegConvHalfCpltCallback;
+		hAudioInButtomLeftFilter.regconvcallback                   = HAL_DFSDM_FilterRegConvCpltCallback;
+		hAudioInButtomLeftFilter.Init.RegTrigger                   = DFSDM_FILTER_SYNC_TRIGGER;
+		hAudioInButtomLeftFilter.Init.RegFastMode                  = 1 /* ENABLE */;
+		hAudioInButtomLeftFilter.Init.RegDmaMode                   = 1 /* ENABLE */;
+		hAudioInButtomLeftFilter.Init.InjTrigger                   = DFSDM_FILTER_SW_TRIGGER;
+		hAudioInButtomLeftFilter.Init.InjScanMode                  = 1 /* ENABLE */;
+		hAudioInButtomLeftFilter.Init.InjDmaMode                   = 0 /* DISABLE */;
+		hAudioInButtomLeftFilter.Init.InjExtTrigger                = DFSDM_FILTER_EXT_TRIG_TIM1_TRGO;
+		hAudioInButtomLeftFilter.Init.InjExtTriggerEdge            = DFSDM_FILTER_EXT_TRIG_RISING_EDGE;
+		hAudioInButtomLeftFilter.Init.FilterSincOrder              = DFSDM_FILTER_ORDER(AudioFreq);
+		/* Set the DFSDM Filters Oversampling to have correct sample rate */
+		hAudioInButtomLeftFilter.Init.FilterOversampling           = DFSDM_OVER_SAMPLING(AudioFreq);
+		hAudioInButtomLeftFilter.Init.FilterIntOversampling        = 1;
+		if(E_OK != (ercd = dfsdm_filter_init(&hAudioInButtomLeftFilter))){
+			return ercd;
+		}
+
+		/* Configure injected channel */
+		if(E_OK != (ercd = dfsdm_filter_config_reg(&hAudioInButtomLeftFilter, AUDIO_DFSDMx_BUTTOM_LEFT_CHANNEL, DFSDM_CONTINUOUS_CONV_ON))){
+			return ercd;
+		}
+
+		/* FILTER 3 configuration */
+		hAudioInButtomRightFilter.state                             = DFSDM_FILTER_STATE_RESET;
+		hAudioInButtomRightFilter.base                              = (uint32_t)AUDIO_DFSDMx_BUTTOM_RIGHT_FILTER;
+		hAudioInButtomRightFilter.regconvhalfcallback               = HAL_DFSDM_FilterRegConvHalfCpltCallback;
+		hAudioInButtomRightFilter.regconvcallback                   = HAL_DFSDM_FilterRegConvCpltCallback;
+		hAudioInButtomRightFilter.Init.RegTrigger                   = DFSDM_FILTER_SYNC_TRIGGER;
+		hAudioInButtomRightFilter.Init.RegFastMode                  = 1 /* ENABLE */;
+		hAudioInButtomRightFilter.Init.RegDmaMode                   = 1 /* ENABLE */;
+		hAudioInButtomRightFilter.Init.InjTrigger                   = DFSDM_FILTER_SW_TRIGGER;
+		hAudioInButtomRightFilter.Init.InjScanMode                  = 0 /* DISABLE */;
+		hAudioInButtomRightFilter.Init.InjDmaMode                   = 0 /* DISABLE */;
+		hAudioInButtomRightFilter.Init.InjExtTrigger                = DFSDM_FILTER_EXT_TRIG_TIM1_TRGO;
+		hAudioInButtomRightFilter.Init.InjExtTriggerEdge            = DFSDM_FILTER_EXT_TRIG_RISING_EDGE;
+		hAudioInButtomRightFilter.Init.FilterSincOrder              = DFSDM_FILTER_ORDER(AudioFreq);
+		/* Set the DFSDM Filters Oversampling to have correct sample rate */
+		hAudioInButtomRightFilter.Init.FilterOversampling           = DFSDM_OVER_SAMPLING(AudioFreq);
+		hAudioInButtomRightFilter.Init.FilterIntOversampling        = 1;
+		if(E_OK != (ercd = dfsdm_filter_init(&hAudioInButtomRightFilter))){
+			return ercd;
+		}
+		/* Configure injected channel */
+		if(E_OK != (ercd = dfsdm_filter_config_reg(&hAudioInButtomRightFilter, AUDIO_DFSDMx_BUTTOM_RIGHT_CHANNEL, DFSDM_CONTINUOUS_CONV_ON))){
+			return ercd;
+		}
+	}
+	return ercd;
+}
+
+/**
+  * @brief  De-initialize the Digital Filter for Sigma-Delta Modulators interface (DFSDM).
+  * @retval AUDIO_OK if correct communication, else wrong communication
+  */
+static ER DFSDMx_DeInit(void)
+{
+	ER ercd = E_OK;
+
+	/* De-initializes the DFSDM filters to allow access to DFSDM internal registers */
+	if(E_OK != (ercd = dfsdm_filter_deinit(&hAudioInTopLeftFilter))){
+		return ercd;
+	}
+	if(E_OK != (ercd = dfsdm_filter_deinit(&hAudioInTopRightFilter))){
+		return ercd;
+	}
+
+	/* De-initializes the DFSDM channels to allow access to DFSDM internal registers */
+	if(E_OK != (ercd = dfsdm_channel_deinit(&hAudioInTopLeftChannel))){
+		return ercd;
+	}
+	if(E_OK != (ercd = dfsdm_channel_deinit(&hAudioInTopRightChannel))){
+		return ercd;
+  }
+
+	if(AudioIn_ChannelNumber > 2){
+		/* De-initializes the DFSDM filters to allow access to DFSDM internal registers */        
+		if(E_OK != (ercd = dfsdm_filter_deinit(&hAudioInButtomLeftFilter))){
+			return ercd;
+		}
+		if(E_OK != (ercd = dfsdm_filter_deinit(&hAudioInButtomRightFilter))){
+			return ercd;
+		}
+
+		/* De-initializes the DFSDM channels to allow access to DFSDM internal registers */  
+		if(E_OK != (ercd = dfsdm_channel_deinit(&hAudioInButtomLeftChannel))){
+			return ercd;
+		}
+		if(E_OK != (ercd = dfsdm_channel_deinit(&hAudioInButtomRightChannel))){
+			return ercd;
+		}
+	}
+	return ercd;
+}
+
+/**
+  * @brief  Initialize the DFSDM channel MSP.
+  * @param  hdfsdm_channel : DFSDM channel handle.
+  * @retval None
+  */
+static void DFSDMx_ChannelMspInit(void)
+{
+	GPIO_Init_t  GPIO_InitStruct;
+
+	/* Enable DFSDM clock */
+	sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_APB2ENR), RCC_APB2ENR_DFSDM1EN);
+
+	/* Enable GPIO clock */
+	AUDIO_DFSDMx_DMIC_DATIN_GPIO_CLK_ENABLE();
+	AUDIO_DFSDMx_CKOUT_DMIC_GPIO_CLK_ENABLE();
+
+	/* DFSDM pins configuration: DFSDM_CKOUT, DMIC_DATIN1 pins ------------------*/
+	GPIO_InitStruct.mode = GPIO_MODE_AF;
+	GPIO_InitStruct.pull = GPIO_NOPULL;
+	GPIO_InitStruct.otype = GPIO_OTYPE_PP;
+	GPIO_InitStruct.speed = GPIO_SPEED_HIGH;
+	GPIO_InitStruct.alternate = AUDIO_DFSDMx_CKOUT_AF;
+	gpio_setup((uint32_t)AUDIO_DFSDMx_CKOUT_DMIC_GPIO_PORT, &GPIO_InitStruct, AUDIO_DFSDMx_CKOUT_PINNO);
+
+	/* DFSDM pin configuration: DMIC_DATIN1 pin --------------------------------*/
+	GPIO_InitStruct.alternate = AUDIO_DFSDMx_DMIC_DATIN_AF;
+	gpio_setup((uint32_t)AUDIO_DFSDMx_DMIC_DATIN_GPIO_PORT, &GPIO_InitStruct, AUDIO_DFSDMx_DMIC_DATIN1_PINNO);
+
+	if(AudioIn_ChannelNumber > 2){
+		/* DFSDM pin configuration: DMIC_DATIN5 pin --------------------------------*/  
+		GPIO_InitStruct.alternate = AUDIO_DFSDMx_DMIC_DATIN_AF;
+		gpio_setup((uint32_t)AUDIO_DFSDMx_DMIC_DATIN_GPIO_PORT, &GPIO_InitStruct, AUDIO_DFSDMx_DMIC_DATIN5_PINNO);
+	}
+}
+
+/**
+  * @brief  Initialize the DFSDM filter MSP.
+  * @param  hdfsdm_filter : DFSDM filter handle.
+  * @retval None
+  */
+static void DFSDMx_FilterMspInit(void)
+{
+	/* Enable DFSDM clock */
+	sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_APB2ENR), RCC_APB2ENR_DFSDM1EN);
+
+	/* Enable the DMA clock */
+	sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB1ENR), RCC_AHB1ENR_DMA2EN);
+
+	/*********** Configure DMA stream for TOP LEFT microphone *******************/
+	hDmaTopLeft.Init.Direction           = DMA_PERIPH_TO_MEMORY;
+	hDmaTopLeft.Init.PeriphInc           = DMA_PINC_DISABLE;
+	hDmaTopLeft.Init.MemInc              = DMA_MINC_ENABLE;
+	hDmaTopLeft.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE;
+	hDmaTopLeft.Init.MemDataAlignment    = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE;
+	hDmaTopLeft.Init.Mode                = DMA_CIRCULAR;
+	hDmaTopLeft.Init.Priority            = DMA_PRIORITY_HIGH;
+	hDmaTopLeft.base                     = (uint32_t)TADR_DMA2_STM4_BASE;
+	hDmaTopLeft.Init.Channel             = AUDIO_DFSDMx_DMAx_CHANNEL; 
+
+	/* Associate the DMA handle */
+	hAudioInTopLeftFilter.hdmaReg = &hDmaTopLeft;
+	hDmaTopLeft.localdata = &hAudioInTopLeftFilter;
+
+	/* Reset DMA handle state */
+	hDmaTopLeft.status = 0;
+
+	/* Configure the DMA Channel */
+	dma_init(&hDmaTopLeft);
+
+	/*********** Configure DMA stream for TOP RIGHT microphone ******************/
+	hDmaTopRight.Init.Direction           = DMA_PERIPH_TO_MEMORY;
+	hDmaTopRight.Init.PeriphInc           = DMA_PINC_DISABLE;
+	hDmaTopRight.Init.MemInc              = DMA_MINC_ENABLE;
+	hDmaTopRight.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE;
+	hDmaTopRight.Init.MemDataAlignment    = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE;
+	hDmaTopRight.Init.Mode                = DMA_CIRCULAR;
+	hDmaTopRight.Init.Priority            = DMA_PRIORITY_HIGH;  
+	hDmaTopRight.base                     = (uint32_t)TADR_DMA2_STM1_BASE;
+	hDmaTopRight.Init.Channel             = AUDIO_DFSDMx_DMAx_CHANNEL;
+
+	/* Associate the DMA handle */
+	hAudioInTopRightFilter.hdmaReg        = &hDmaTopRight;
+	hDmaTopRight.localdata                = &hAudioInTopRightFilter;
+
+	/* Reset DMA handle state */
+	hDmaTopRight.status = 0;
+
+	/* Configure the DMA Channel */
+	dma_init(&hDmaTopRight);
+
+	if(AudioIn_ChannelNumber > 2){
+		/*********** Configure DMA stream for BUTTOM LEFT microphone ****************/
+		hDmaButtomLeft.Init.Direction           = DMA_PERIPH_TO_MEMORY;
+		hDmaButtomLeft.Init.PeriphInc           = DMA_PINC_DISABLE;
+		hDmaButtomLeft.Init.MemInc              = DMA_MINC_ENABLE;
+		hDmaButtomLeft.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE;
+		hDmaButtomLeft.Init.MemDataAlignment    = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE;
+		hDmaButtomLeft.Init.Mode                = DMA_CIRCULAR;
+		hDmaButtomLeft.Init.Priority            = DMA_PRIORITY_HIGH;
+		hDmaButtomLeft.base                     = (uint32_t)AUDIO_DFSDMx_DMAx_BUTTOM_LEFT_STREAM;
+		hDmaButtomLeft.Init.Channel             = AUDIO_DFSDMx_DMAx_CHANNEL; 
+
+		/* Associate the DMA handle */
+		hAudioInButtomLeftFilter.hdmaReg        = &hDmaButtomLeft;
+		hDmaButtomLeft.localdata                = &hAudioInButtomLeftFilter;
+
+		/* Reset DMA handle state */
+		hDmaButtomLeft.status = 0;
+
+		/* Configure the DMA Channel */
+		dma_init(&hDmaButtomLeft);
+
+		/*********** Configure DMA stream for BUTTOM RIGHT microphone ***************/
+		hDmaButtomRight.Init.Direction           = DMA_PERIPH_TO_MEMORY;
+		hDmaButtomRight.Init.PeriphInc           = DMA_PINC_DISABLE;
+		hDmaButtomRight.Init.MemInc              = DMA_MINC_ENABLE;
+		hDmaButtomRight.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE;
+		hDmaButtomRight.Init.MemDataAlignment    = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE;
+		hDmaButtomRight.Init.Mode                = DMA_CIRCULAR;
+		hDmaButtomRight.Init.Priority            = DMA_PRIORITY_HIGH;  
+		hDmaButtomRight.base                     = (uint32_t)AUDIO_DFSDMx_DMAx_BUTTOM_RIGHT_STREAM;
+		hDmaButtomRight.Init.Channel             = AUDIO_DFSDMx_DMAx_CHANNEL;
+
+		/* Associate the DMA handle */
+		hAudioInButtomRightFilter.hdmaReg        = &hDmaButtomRight;
+		hDmaButtomRight.localdata                = &hAudioInButtomRightFilter;
+
+		/* Reset DMA handle state */
+		hDmaButtomRight.status = 0;
+
+		/* Configure the DMA Channel */
+		dma_init(&hDmaButtomRight);
+	}
+}
+
+/**
+  * @brief  DeInitialize the DFSDM filter MSP.
+  * @param  hdfsdm_filter : DFSDM filter handle.
+  * @retval None
+  */
+static void DFSDMx_FilterMspDeInit(void)
+{
+	/* Configure the DMA Channel */
+	dma_deinit(&hDmaTopLeft);
+	dma_deinit(&hDmaTopRight);
+	if(AudioIn_ChannelNumber > 2){
+		dma_deinit(&hDmaButtomLeft);
+		dma_deinit(&hDmaButtomRight);
+	}
+}
+
+void dfsdm1fl0_handler(void)
+{
+	dfsdm_irqhandler(&hAudioInTopLeftFilter);
+}
+
+void dfsdm1fl1_handler(void)
+{
+	dfsdm_irqhandler(&hAudioInTopRightFilter);
+}
+
+void dfsdm1fl2_handler(void)
+{
+	dfsdm_irqhandler(&hAudioInButtomLeftFilter);
+}
+
+void dfsdm1fl3_handler(void)
+{
+	dfsdm_irqhandler(&hAudioInButtomRightFilter);
+}
+
+#endif
+
+/*
+ *  オーディオ入力初期化設定
+ *  param1: STAUDIOハンドラ
+ *  param2: 入力デバイス設定
+ *  param3: オーディオ周波数値
+ *  param4: BitRes
+ *  param5: チャネル番号
+ *  return: E_OKで正常設定
+ */
+ER
+staudio_in_init(STAUDIO_Handle_t *haudio, uint16_t InputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
+{
+	ER       ercd = E_OK;
+	uint32_t slot_active;
+
+	haudio->InputDevice = InputDevice;
+	if(InputDevice == INPUT_DEVICE_DIGITAL_MIC){
+#ifdef TOPPERS_STM32F769_DISCOVERY
+		AudioIn_ChannelNumber = ChnlNbr;
+		/* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 
+		dfsdm_clockconfig(AUDIO2_PORTID, AudioFreq);
+		sil_modw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_DCKCFGR1), RCC_DCKCFGR1_ADFSDM1SEL, (uint32_t)(RCC_DCKCFGR1_ADFSDM1SEL));
+
+		/* Init the SAI MSP: this __weak function can be redefined by the application*/
+		/* MSP channels initialization */
+		DFSDMx_ChannelMspInit();
+		/* MSP filters initialization */
+		DFSDMx_FilterMspInit();
+
+		/* Initializes DFSDM peripheral */
+		DFSDMx_Init(AudioFreq);
+		hstaudio = haudio;
+		ercd = E_OK;
+#else
+		ercd = E_PAR;
+#endif
+	}
+	/* Only INPUT_LINE_1, MICROPHONE_1, MICROPHONE_2 and MIC1&MIC2 inputs supported */
+	else if((InputDevice != INPUT_DEVICE_INPUT_LINE_1) &&       
+		(InputDevice != INPUT_DEVICE_DIGITAL_MICROPHONE_1) &&
+		(InputDevice != INPUT_DEVICE_DIGITAL_MICROPHONE_2) &&
+		(InputDevice != INPUT_DEVICE_DIGITAL_MIC1_MIC2)){
+		ercd = E_PAR;
+	}
+	else{
+		/* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */
+		if(haudio->hsai == NULL){
+			haudio->hsai = audio_init(haudio->saiid);
+		}
+		else{
+			/* Disable SAI peripheral */
+			audio_disable(haudio->hsai, AUDIO_IN_BLOCK);
+			audio_end(haudio->hsai, AUDIO_IN_BLOCK);
+		}
+		audio_clockconfig(haudio->hsai, AudioFreq, NULL); /* Clock config is shared between AUDIO IN and OUT */
+
+		/* Configure SAI in master RX mode :
+		 *   - SAI2_block_A in master RX mode
+		 *   - SAI2_block_B in slave RX mode synchronous from SAI2_block_A
+		 */
+		if(InputDevice == INPUT_DEVICE_DIGITAL_MICROPHONE_2){
+			slot_active = CODEC_AUDIOFRAME_SLOT_13;
+		}
+		else if(InputDevice == INPUT_DEVICE_DIGITAL_MIC1_MIC2){
+			slot_active = CODEC_AUDIOFRAME_SLOT_0123;
+		}
+		else{
+			slot_active = CODEC_AUDIOFRAME_SLOT_02;
+		}
+		SAIx_In_Init(haudio, SAI_MODEMASTER_RX, slot_active, AudioFreq);
+
+		/* wm8994 codec initialization */
+		ercd = wm8994_Reset(haudio);
+		if(ercd == E_OK){
+			/* Initialize the codec internal registers */
+			wm8994_Init(haudio, InputDevice, haudio->AudioInVolume, AudioFreq);
+		}
+	}
+	return ercd;
+}
+
+#ifndef TOPPERS_STM32F769_DISCOVERY
+/*
+ *  オーディオ入出力初期化設定
+ *  param1: STAUDIOハンドラ
+ *  param2: 入力デバイス設定
+ *  param3: 出力デバイス設定
+ *  param4: オーディオ周波数値
+ *  param5: BitRes
+ *  param6: チャネル番号
+ *  return: E_OKで正常設定
+ */
+ER
+staudio_in_out_init(STAUDIO_Handle_t *haudio, uint16_t InputDevice, uint16_t OutputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
+{
+	ER       ercd = E_OK;
+	uint32_t slot_active;
+
+	haudio->InputDevice = InputDevice;
+	/* Only INPUT_LINE_1, MICROPHONE_1, MICROPHONE_2 and MIC1&MIC2 inputs supported */
+	if ((InputDevice != INPUT_DEVICE_INPUT_LINE_1) &&       
+		(InputDevice != INPUT_DEVICE_DIGITAL_MICROPHONE_1) &&
+		(InputDevice != INPUT_DEVICE_DIGITAL_MICROPHONE_2) &&
+		(InputDevice != INPUT_DEVICE_DIGITAL_MIC1_MIC2)){
+		ercd = E_PAR;
+	}
+	else{
+		/* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */
+		if(haudio->hsai == NULL){
+			haudio->hsai = audio_init(haudio->saiid);
+		}
+		else{
+			/* Disable SAI peripheral */
+			audio_disable(haudio->hsai, AUDIO_IN_BLOCK);
+			audio_end(haudio->hsai, AUDIO_IN_BLOCK);
+		}
+		audio_clockconfig(haudio->hsai, AudioFreq, NULL); /* Clock config is shared between AUDIO IN and OUT */
+
+		/* Configure SAI in master RX mode :
+		 *   - SAI2_block_A in master RX mode
+		 *   - SAI2_block_B in slave RX mode synchronous from SAI2_block_A
+		 */
+		if(InputDevice == INPUT_DEVICE_DIGITAL_MICROPHONE_2){
+			slot_active = CODEC_AUDIOFRAME_SLOT_13;
+		}
+		else if(InputDevice == INPUT_DEVICE_DIGITAL_MIC1_MIC2){
+			slot_active = CODEC_AUDIOFRAME_SLOT_0123;
+		}
+		else{
+			slot_active = CODEC_AUDIOFRAME_SLOT_02;
+		}
+		SAIx_In_Init(haudio, SAI_MODEMASTER_RX, slot_active, AudioFreq);
+
+		/* wm8994 codec initialization */
+		ercd = wm8994_Reset(haudio);
+		if(ercd == E_OK){
+			/* Initialize the codec internal registers */
+			wm8994_Init(haudio, InputDevice | OutputDevice, haudio->AudioInVolume, AudioFreq);
+		}
+	}
+	return ercd;
+}
+#endif
+
+/*
+ *  オーディオ録音開始設定
+ *  param1: STAUDIOハンドラ
+ *  param2: 入力バッファポインタ
+ *  param3: 入力バッファサイズ
+ *  return: E_OKで正常設定
+ */
+ER
+staudio_in_record(STAUDIO_Handle_t *haudio, uint16_t* pbuf, uint32_t size)
+{
+	AUDIO_Handle_t  *hsai = haudio->hsai;
+	ER ercd = E_OK;
+
+#ifdef TOPPERS_STM32F769_DISCOVERY
+	if(haudio->InputDevice == INPUT_DEVICE_DIGITAL_MIC){
+		hAudioIn.pRecBuf = pbuf;
+		hAudioIn.RecSize = size;
+		/* Reset Application Buffer Trigger */
+		AppBuffTrigger = 0;
+		AppBuffHalf = 0;
+
+		if(AudioIn_ChannelNumber > 2){
+			/* Call the Media layer start function for buttom right channel */
+			if(E_OK != (ercd = dfsdm_filterRegularStart(&hAudioInButtomRightFilter, pScratchBuff[2], ScratchSize))){
+				return ercd;
+			}
+			/* Call the Media layer start function for buttom left channel */
+			if(E_OK != (ercd = dfsdm_filterRegularStart(&hAudioInButtomLeftFilter, pScratchBuff[3], ScratchSize))){
+				return ercd;
+			}
+		}
+		/* Call the Media layer start function for top right channel */
+		if(E_OK != (ercd = dfsdm_filterRegularStart(&hAudioInTopRightFilter, pScratchBuff[0], ScratchSize))){
+			return ercd;
+		}
+		/* Call the Media layer start function for top left channel */
+		if(E_OK != (ercd = dfsdm_filterRegularStart(&hAudioInTopLeftFilter, pScratchBuff[1], ScratchSize))){
+			return ercd;
+		}
+		return ercd;
+	}
+#endif
+	/* Start the process receive DMA */
+	hsai->recevcallback = (void (*)(AUDIO_Handle_t *hsai))haudio->audio_fullin_func;
+	hsai->recevhalfcallback = (void (*)(AUDIO_Handle_t *hsai))haudio->audio_halfin_func;
+	hsai->errorcallback = haudio->audio_error_func;
+	ercd = audio_receive(hsai, (uint8_t*)pbuf, size);
+	return ercd;
+}
+
+/*
+ *  オーディオ録音停止設定
+ *  param1: STAUDIOハンドラ
+ *  param2: 終了オプション
+ *  return: E_OKで正常設定
+ */
+ER
+staudio_in_stop(STAUDIO_Handle_t *haudio, uint32_t Option)
+{
+#ifdef TOPPERS_STM32F769_DISCOVERY
+	ER ercd = E_OK;
+	if(haudio->InputDevice == INPUT_DEVICE_DIGITAL_MIC){
+		AppBuffTrigger = 0;
+		AppBuffHalf    = 0;
+		if(AudioIn_ChannelNumber > 2){
+			/* Call the Media layer stop function for buttom right channel */
+			if(E_OK != (ercd = dfsdm_filterRegularStop(&hAudioInButtomRightFilter))){
+				return ercd;
+			}
+			/* Call the Media layer stop function for buttom left channel */
+			if(E_OK != (ercd = dfsdm_filterRegularStop(&hAudioInButtomLeftFilter))){
+				return ercd;
+			}
+		}
+		/* Call the Media layer stop function for top right channel */
+		if(E_OK != (ercd = dfsdm_filterRegularStop(&hAudioInTopRightFilter))){
+			return ercd;
+		}
+		/* Call the Media layer stop function for top left channel */
+		if(E_OK != (ercd = dfsdm_filterRegularStop(&hAudioInTopLeftFilter))){
+			return ercd;
+		}
+		return ercd;
+	}
+#endif
+	/* Call the Media layer stop function */
+	audio_dmastop(haudio->hsai, AUDIO_IN_BLOCK);
+
+	/* Call Audio Codec Stop function */
+	if(wm8994_Stop(haudio, Option) != 0){
+		return E_SYS;
+	}
+	else{
+		if(Option == CODEC_PDWN_HW){
+			/* Wait at least 100us */
+			dly_tsk(1);
+		}
+		/* Return AUDIO_OK when all operations are correctly done */
+		return E_OK;
+	}
+}
+
+/*
+ *  オーディオ録音PAUSE設定
+ *  param1: STAUDIOハンドラ
+ *  return: E_OKで正常設定
+ */
+ER
+staudio_in_pause(STAUDIO_Handle_t *haudio)
+{
+#ifdef TOPPERS_STM32F769_DISCOVERY
+	ER ercd = E_OK;
+	if(haudio->InputDevice == INPUT_DEVICE_DIGITAL_MIC){
+		if(AudioIn_ChannelNumber > 2){
+			/* Call the Media layer stop function */
+			if(E_OK != (ercd = dfsdm_filterRegularStop(&hAudioInButtomRightFilter))){
+				return ercd;
+			}
+			/* Call the Media layer stop function */
+			if(E_OK != (ercd = dfsdm_filterRegularStop(&hAudioInButtomLeftFilter))){
+				return ercd;
+			}
+		}
+		/* Call the Media layer stop function */
+		if(E_OK != (ercd = dfsdm_filterRegularStop(&hAudioInTopRightFilter))){
+			return ercd;
+		}
+		/* Call the Media layer stop function */
+		if(E_OK != (ercd = dfsdm_filterRegularStop(&hAudioInTopLeftFilter))){
+			return ercd;
+		}
+		/* Return AUDIO_OK when all operations are correctly done */
+		return ercd;
+	}
+#endif
+	/* Call the Media layer pause function */
+	return audio_dmapause(haudio->hsai, AUDIO_IN_BLOCK);
+}
+
+/*
+ *  オーディオ録音RESUME設定
+ *  param1: STAUDIOハンドラ
+ *  return: E_OKで正常設定
+ */
+ER
+staudio_in_resume(STAUDIO_Handle_t *haudio)
+{
+#ifdef TOPPERS_STM32F769_DISCOVERY
+	ER ercd = E_OK;
+	if(haudio->InputDevice == INPUT_DEVICE_DIGITAL_MIC){
+		if(AudioIn_ChannelNumber > 2){
+			/* Call the Media layer start function for buttom right channel */
+			if(E_OK != (ercd = dfsdm_filterRegularStart(&hAudioInButtomRightFilter, pScratchBuff[2], ScratchSize))){
+				return ercd;
+			}
+			/* Call the Media layer start function for buttom left channel */
+			if(E_OK != (ercd = dfsdm_filterRegularStart(&hAudioInButtomLeftFilter, pScratchBuff[3], ScratchSize))){
+				return ercd;
+			}
+		}
+		/* Call the Media layer start function for top right channel */
+		if(E_OK != (ercd = dfsdm_filterRegularStart(&hAudioInTopRightFilter, pScratchBuff[0], ScratchSize))){
+			return ercd;
+		}
+		/* Call the Media layer start function for top left channel */
+		if(E_OK != (ercd = dfsdm_filterRegularStart(&hAudioInTopLeftFilter, pScratchBuff[1], ScratchSize))){
+			return ercd;
+		}
+		/* Return AUDIO_OK when all operations are correctly done */
+		return ercd;
+	}
+#endif
+	/* Call the Media layer pause/resume function */
+	return audio_dmaresume(haudio->hsai, AUDIO_IN_BLOCK);
+}
+
+/*
+ *  オーディオ録音終了設定
+ *  param1: STAUDIOハンドラ
+ */
+void
+staudio_in_deinit(STAUDIO_Handle_t *haudio)
+{
+#ifdef TOPPERS_STM32F769_DISCOVERY
+	if(haudio->InputDevice == INPUT_DEVICE_DIGITAL_MIC){
+		/* MSP filters initialization */
+		DFSDMx_FilterMspDeInit();
+		DFSDMx_DeInit();
+	}
+	else
+#endif
+	SAIx_In_DeInit(haudio);
+}
+
+#ifndef TOPPERS_STM32F769_DISCOVERY
+/*
+ *  オーディオ録音ボリューム設定
+ *  param1: STAUDIOハンドラ
+ *  param2: ボリューム値(0..100)
+ *  return: E_OKで正常設定
+ */
+ER
+staudio_in_setvolume(STAUDIO_Handle_t *haudio, uint8_t Volume)
+{
+	/* Call the codec volume control function with converted volume value */
+	if(wm8994_SetVolume(haudio, Volume) != 0){
+		return E_SYS;
+	}
+	else{
+		/* Set the Global variable AudioInVolume  */
+		haudio->AudioInVolume = Volume;
+		/* Return AUDIO_OK when all operations are correctly done */
+		return E_OK;
+	}
+}
+
+
+#else	/* TOPPERS_STM32F769_DISCOVERY  */
+/*
+ *  オーディオ録音スクラッチ領域E設定
+ *  param1: スクラッチ領域へのポインタ
+ *  param2: スクラッチ領域サイズ
+ *  return: E_OKで正常設定
+ */
+ER
+BSP_AUDIO_IN_AllocScratch(int32_t *pScratch, uint32_t size)
+{
+	uint32_t idx;
+
+	ScratchSize = (size / AudioIn_ChannelNumber);
+
+	/* copy scratch pointers */
+	for (idx = 0; idx < AudioIn_ChannelNumber; idx++){
+		pScratchBuff[idx] = (int32_t *)(pScratch + (idx * ScratchSize));
+	}
+	/* Return AUDIO_OK */
+	return E_OK;
+}
+
+/*
+ *  オーディオチャネル番号取り出し
+ *  return: チャネル番号
+ */
+uint8_t BSP_AUDIO_IN_GetChannelNumber(void)
+{
+  return AudioIn_ChannelNumber;
+}
+
+#endif
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/staudio_wm8994/staudio_wm8994.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/staudio_wm8994/staudio_wm8994.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/staudio_wm8994/staudio_wm8994.h	(revision 453)
@@ -0,0 +1,277 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/**
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+#ifndef _STAUDIO_WM8994_H_
+#define _STAUDIO_WM8994_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif 
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include "device.h"
+#include "i2c.h"
+#include "sai.h"
+#ifdef TOPPERS_STM32F769_DISCOVERY
+#include "dfsdm.h"
+#endif
+
+/******************************************************************************/
+/***************************  Codec User defines ******************************/
+/******************************************************************************/
+/* Codec output DEVICE */
+#define OUTPUT_DEVICE_SPEAKER                 ((uint16_t)0x0001)
+#define OUTPUT_DEVICE_HEADPHONE               ((uint16_t)0x0002)
+#define OUTPUT_DEVICE_BOTH                    ((uint16_t)0x0003)
+#define OUTPUT_DEVICE_AUTO                    ((uint16_t)0x0004)
+#define INPUT_DEVICE_DIGITAL_MICROPHONE_1     ((uint16_t)0x0100)
+#define INPUT_DEVICE_DIGITAL_MICROPHONE_2     ((uint16_t)0x0200)
+#define INPUT_DEVICE_INPUT_LINE_1             ((uint16_t)0x0300)
+#define INPUT_DEVICE_INPUT_LINE_2             ((uint16_t)0x0400)
+#define INPUT_DEVICE_DIGITAL_MIC1_MIC2        ((uint16_t)0x0800)
+
+/* MP34DT01TR digital microphone on PCB top side */
+#define INPUT_DEVICE_DIGITAL_MIC       ((uint16_t)0)
+
+/* Volume Levels values */
+#define DEFAULT_VOLMIN                0x00
+#define DEFAULT_VOLMAX                0xFF
+#define DEFAULT_VOLSTEP               0x04
+
+#define AUDIO_PAUSE                   0
+#define AUDIO_RESUME                  1
+
+/* Codec POWER DOWN modes */
+#define CODEC_PDWN_HW                 1
+#define CODEC_PDWN_SW                 2
+
+/* MUTE commands */
+#define AUDIO_MUTE_ON                 1
+#define AUDIO_MUTE_OFF                0
+
+
+#define VOLUME_CONVERT(Volume)        (((Volume) > 100)? 100:((uint8_t)(((Volume) * 63) / 100)))
+#define VOLUME_IN_CONVERT(Volume)     (((Volume) >= 100)? 239:((uint8_t)(((Volume) * 240) / 100)))
+
+/******************************************************************************/
+/****************************** REGISTER MAPPING ******************************/
+/******************************************************************************/
+/** 
+  * @brief  WM8994 ID  
+  */  
+#define  WM8994_ID    0x08994
+
+/**
+  * @brief Device ID Register: Reading from this register will indicate device 
+  *                            family ID 8994h
+  */
+#define WM8994_CHIPID_ADDR                  0x00
+
+
+/*------------------------------------------------------------------------------
+                           Audio Codec functions 
+------------------------------------------------------------------------------*/
+/**
+  * @brief Audio I2C Slave address
+  */
+#define AUDIO_I2C_ADDRESS                ((uint16_t)0x34)
+
+
+/** @defgroup BSP_Audio_Out_Option BSP Audio Out Option
+  * @{
+  */
+#define BSP_AUDIO_OUT_CIRCULARMODE      ((uint32_t)0x00000001) /* BUFFER CIRCULAR MODE */
+#define BSP_AUDIO_OUT_NORMALMODE        ((uint32_t)0x00000002) /* BUFFER NORMAL MODE   */
+#define BSP_AUDIO_OUT_STEREOMODE        ((uint32_t)0x00000004) /* STEREO MODE          */
+#define BSP_AUDIO_OUT_MONOMODE          ((uint32_t)0x00000008) /* MONO MODE            */
+/**
+  * @}
+  */
+/** @defgroup BSP_Audio_Sample_Rate BSP Audio Sample Rate
+  * @{
+  */
+#define BSP_AUDIO_FREQUENCY_96K         ((uint32_t)192000U)
+#define BSP_AUDIO_FREQUENCY_48K         ((uint32_t)48000U)
+#define BSP_AUDIO_FREQUENCY_44K         ((uint32_t)44100U)
+#define BSP_AUDIO_FREQUENCY_32K         ((uint32_t)32000U)
+#define BSP_AUDIO_FREQUENCY_22K         ((uint32_t)22050U)
+#define BSP_AUDIO_FREQUENCY_16K         ((uint32_t)16000U)
+#define BSP_AUDIO_FREQUENCY_11K         ((uint32_t)11025U)
+#define BSP_AUDIO_FREQUENCY_8K          ((uint32_t)8000U)
+
+/*------------------------------------------------------------------------------
+                          USER SAI defines parameters
+ -----------------------------------------------------------------------------*/
+/** CODEC_AudioFrame_SLOT_TDMMode In W8994 codec the Audio frame contains 4 slots : TDM Mode
+  * TDM format :
+  * +------------------|------------------|--------------------|-------------------+ 
+  * | CODEC_SLOT0 Left | CODEC_SLOT1 Left | CODEC_SLOT0 Right  | CODEC_SLOT1 Right |
+  * +------------------------------------------------------------------------------+
+  */
+/* To have 2 separate audio stream in Both headphone and speaker the 4 slot must be activated */
+#define CODEC_AUDIOFRAME_SLOT_0123          (SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_1 | SAI_SLOTACTIVE_2 | SAI_SLOTACTIVE_3)
+
+/* To have an audio stream in headphone only SAI Slot 0 and Slot 2 must be activated */ 
+#define CODEC_AUDIOFRAME_SLOT_02            SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_2 
+/* To have an audio stream in speaker only SAI Slot 1 and Slot 3 must be activated */ 
+#define CODEC_AUDIOFRAME_SLOT_13            SAI_SLOTACTIVE_1 | SAI_SLOTACTIVE_3
+
+
+#define DMA_MAX_SZE                         0xFFFF
+
+/*------------------------------------------------------------------------------
+             CONFIGURATION: Audio Driver Configuration parameters
+------------------------------------------------------------------------------*/
+
+#define AUDIODATA_SIZE                      2   /* 16-bits audio data size */
+
+/* Audio status definition */
+#define AUDIO_OK                            E_OK
+
+/* AudioFreq * DataSize (2 bytes) * NumChannels (Stereo: 2) */
+#define DEFAULT_AUDIO_IN_FREQ               BSP_AUDIO_FREQUENCY_16K
+#define DEFAULT_AUDIO_IN_BIT_RESOLUTION     ((uint8_t)16)
+#define DEFAULT_AUDIO_IN_CHANNEL_NBR        ((uint8_t)2) /* Mono = 1, Stereo = 2 */
+#define DEFAULT_AUDIO_IN_VOLUME             ((uint16_t)100)
+   
+/*------------------------------------------------------------------------------
+                    OPTIONAL Configuration defines parameters
+------------------------------------------------------------------------------*/
+
+/* Delay for the Codec to be correctly reset */
+#define CODEC_RESET_DELAY                   ((uint8_t)5)
+   
+
+/*------------------------------------------------------------------------------
+                            OUTPUT DEVICES definition
+------------------------------------------------------------------------------*/
+/* Alias on existing output devices to adapt to headphones output */
+#define OUTPUT_DEVICE_HEADPHONE1 OUTPUT_DEVICE_HEADPHONE
+#define OUTPUT_DEVICE_HEADPHONE2 OUTPUT_DEVICE_SPEAKER 
+   
+#define DMA_MAX(x)           (((x) <= DMA_MAX_SZE)? (x):DMA_MAX_SZE)
+
+/*
+ *  STMAUDIOハンドラ定義
+ *
+ */
+typedef struct STAUDIO_Handle_s {
+	I2C_Handle_t    *hi2c;
+	AUDIO_Handle_t  *hsai;
+	ID              saiid;
+	uint8_t         i2caddress;
+	uint8_t         outputEnabled;
+	uint8_t         inputEnabled;
+	uint8_t         ColdStartup;
+	uint16_t        InputDevice;
+	uint16_t        AudioInVolume;
+	void   (*audio_fullout_func)(AUDIO_Handle_t *hsai);
+	void   (*audio_halfout_func)(AUDIO_Handle_t *hsai);
+	void   (*audio_fullin_func)(void *handle);
+	void   (*audio_halfin_func)(void *handle);
+	void   (*audio_error_func)(AUDIO_Handle_t *hsai);
+} STAUDIO_Handle_t;
+
+
+extern ER staudio_out_init(STAUDIO_Handle_t *haudio, uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq, uint16_t framesize);
+extern void staudio_out_deinit(STAUDIO_Handle_t *haudio);
+extern ER staudio_out_play(STAUDIO_Handle_t *haudio, uint16_t* pBuffer, uint32_t Size);
+extern ER staudio_out_pause(STAUDIO_Handle_t *haudio);
+extern ER staudio_out_resume(STAUDIO_Handle_t *haudio);
+extern ER staudio_out_stop(STAUDIO_Handle_t *haudio, uint32_t Option);
+extern ER staudio_out_setvolume(STAUDIO_Handle_t *haudio, uint8_t Volume);
+extern void staudio_out_setfrequency(STAUDIO_Handle_t *haudio, uint32_t AudioFreq);
+extern void staudio_out_setframeslot(STAUDIO_Handle_t *haudio, uint32_t AudioFrameSlot);
+extern ER staudio_out_setmute(STAUDIO_Handle_t *haudio, uint32_t Cmd);
+extern ER staudio_out_setoutputmode(STAUDIO_Handle_t *haudio, uint8_t Output);
+extern void staudio_out_changebuffer(STAUDIO_Handle_t *haudio, uint16_t *pData, uint16_t Size);
+
+
+extern ER staudio_in_init(STAUDIO_Handle_t *haudio, uint16_t InputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr);
+uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr);
+extern ER staudio_in_out_init(STAUDIO_Handle_t *haudio, uint16_t InputDevice, uint16_t OutputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr);
+extern void staudio_in_deinit(STAUDIO_Handle_t *haudio);
+extern ER staudio_in_record(STAUDIO_Handle_t *haudio, uint16_t* pbuf, uint32_t size);
+extern ER staudio_in_stop(STAUDIO_Handle_t *haudio, uint32_t Option);
+extern ER staudio_in_pause(STAUDIO_Handle_t *haudio);
+extern ER staudio_in_resume(STAUDIO_Handle_t *haudio);
+extern ER staudio_in_setvolume(STAUDIO_Handle_t *haudio, uint8_t Volume);
+
+#ifdef TOPPERS_STM32F769_DISCOVERY
+extern ER BSP_AUDIO_IN_AllocScratch(int32_t *pScratch, uint32_t size);
+extern uint8_t BSP_AUDIO_IN_GetChannelNumber(void);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _STAUDIO_WM8994_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_otm8009a/Makefile.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_otm8009a/Makefile.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_otm8009a/Makefile.config	(revision 453)
@@ -0,0 +1,55 @@
+#
+#   TOPPERS/ASP/FMP Kernel
+#       Toyohashi Open Platform for Embedded Real-Time Systems/
+#       Advanced Standard Profile Kernel
+#
+#   Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                               Toyohashi Univ. of Technology, JAPAN
+#   Copyright (C) 2003-2008 by Ryosuke Takeuchi
+#                Platform Development Center RICOH COMPANY,LTD. JAPAN
+#   Copyright (C) 2015-2018 by TOPPERS PROJECT Educational Working Group.
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+ 
+#
+#  Makefile のプロセッサ依存 (otm8009a用)
+#
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/gdic/stlcd_otm8009a
+
+#
+#  USB DEVICE(GDIC)に関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR):$(SRCDIR)/gdic/stlcd_otm8009a
+SYSSVC_COBJS := $(SYSSVC_COBJS) stlcd_otm8009a.o
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_otm8009a/glcd_core.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_otm8009a/glcd_core.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_otm8009a/glcd_core.h	(revision 453)
@@ -0,0 +1,45 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+#ifndef _LCD_CORE_H_
+#define _LCD_CORE_H_
+
+#include "stlcd_otm8009a.h"
+
+#endif /* _LCD_CORE_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_otm8009a/stlcd_otm8009a.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_otm8009a/stlcd_otm8009a.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_otm8009a/stlcd_otm8009a.c	(revision 453)
@@ -0,0 +1,1505 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/**
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+#include "stlcd_otm8009a.h"
+#include "kernel_cfg.h"
+
+#define sil_orw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) | (b))
+#define sil_andw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) & ~(b))
+#define sil_modw_mem(a, b, c)	sil_wrw_mem((a), (sil_rew_mem(a) & (~b)) | (c))
+
+
+
+/** @defgroup STM32F769I-DISCOVERY_LCD_Private_Macros LCD Private Macros
+  * @{
+  */
+#define ABS(X)                 ((X) > 0 ? (X) : -(X))
+
+#define POLY_X(Z)              ((int32_t)((Points + (Z))->X))
+#define POLY_Y(Z)              ((int32_t)((Points + (Z))->Y))
+
+/*
+ * @brief Constant tables of register settings used to transmit DSI
+ * command packets as power up initialization sequence of the KoD LCD (OTM8009A LCD Driver)
+ */
+static const uint8_t lcdRegData1[]  = {0x80,0x09,0x01,0xFF};
+static const uint8_t lcdRegData2[]  = {0x80,0x09,0xFF};
+static const uint8_t lcdRegData3[]  = {0x00,0x09,0x0F,0x0E,0x07,0x10,0x0B,0x0A,0x04,0x07,0x0B,0x08,0x0F,0x10,0x0A,0x01,0xE1};
+static const uint8_t lcdRegData4[]  = {0x00,0x09,0x0F,0x0E,0x07,0x10,0x0B,0x0A,0x04,0x07,0x0B,0x08,0x0F,0x10,0x0A,0x01,0xE2};
+static const uint8_t lcdRegData5[]  = {0x79,0x79,0xD8};
+static const uint8_t lcdRegData6[]  = {0x00,0x01,0xB3};
+static const uint8_t lcdRegData7[]  = {0x85,0x01,0x00,0x84,0x01,0x00,0xCE};
+static const uint8_t lcdRegData8[]  = {0x18,0x04,0x03,0x39,0x00,0x00,0x00,0x18,0x03,0x03,0x3A,0x00,0x00,0x00,0xCE};
+static const uint8_t lcdRegData9[]  = {0x18,0x02,0x03,0x3B,0x00,0x00,0x00,0x18,0x01,0x03,0x3C,0x00,0x00,0x00,0xCE};
+static const uint8_t lcdRegData10[] = {0x01,0x01,0x20,0x20,0x00,0x00,0x01,0x02,0x00,0x00,0xCF};
+static const uint8_t lcdRegData11[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCB};
+static const uint8_t lcdRegData12[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCB};
+static const uint8_t lcdRegData13[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCB};
+static const uint8_t lcdRegData14[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCB};
+static const uint8_t lcdRegData15[] = {0x00,0x04,0x04,0x04,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCB};
+static const uint8_t lcdRegData16[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x04,0x04,0x04,0x00,0x00,0x00,0x00,0xCB};
+static const uint8_t lcdRegData17[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCB};
+static const uint8_t lcdRegData18[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCB};
+static const uint8_t lcdRegData19[] = {0x00,0x26,0x09,0x0B,0x01,0x25,0x00,0x00,0x00,0x00,0xCC};
+static const uint8_t lcdRegData20[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x26,0x0A,0x0C,0x02,0xCC};
+static const uint8_t lcdRegData21[] = {0x25,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCC};
+static const uint8_t lcdRegData22[] = {0x00,0x25,0x0C,0x0A,0x02,0x26,0x00,0x00,0x00,0x00,0xCC};
+static const uint8_t lcdRegData23[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x0B,0x09,0x01,0xCC};
+static const uint8_t lcdRegData24[] = {0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCC};
+static const uint8_t lcdRegData25[] = {0xFF,0xFF,0xFF,0xFF};
+/*
+  * CASET value (Column Address Set) : X direction LCD GRAM boundaries
+  * depending on LCD orientation mode and PASET value (Page Address Set) : Y direction
+  * LCD GRAM boundaries depending on LCD orientation mode
+  * XS[15:0] = 0x000 = 0, XE[15:0] = 0x31F = 799 for landscape mode : apply to CASET
+  * YS[15:0] = 0x000 = 0, YE[15:0] = 0x31F = 799 for portrait mode : : apply to PASET
+  */
+static const uint8_t lcdRegData27[] = {0x00, 0x00, 0x03, 0x1F, OTM8009A_CMD_CASET};
+/*
+  * XS[15:0] = 0x000 = 0, XE[15:0] = 0x1DF = 479 for portrait mode : apply to CASET
+  * YS[15:0] = 0x000 = 0, YE[15:0] = 0x1DF = 479 for landscape mode : apply to PASET
+ */
+static const uint8_t lcdRegData28[] = {0x00, 0x00, 0x01, 0xDF, OTM8009A_CMD_PASET};
+
+
+static const uint8_t ShortRegData1[]  = {OTM8009A_CMD_NOP, 0x00};
+static const uint8_t ShortRegData2[]  = {OTM8009A_CMD_NOP, 0x80};
+static const uint8_t ShortRegData3[]  = {0xC4, 0x30};
+static const uint8_t ShortRegData4[]  = {OTM8009A_CMD_NOP, 0x8A};
+static const uint8_t ShortRegData5[]  = {0xC4, 0x40};
+static const uint8_t ShortRegData6[]  = {OTM8009A_CMD_NOP, 0xB1};
+static const uint8_t ShortRegData7[]  = {0xC5, 0xA9};
+static const uint8_t ShortRegData8[]  = {OTM8009A_CMD_NOP, 0x91};
+static const uint8_t ShortRegData9[]  = {0xC5, 0x34};
+static const uint8_t ShortRegData10[] = {OTM8009A_CMD_NOP, 0xB4};
+static const uint8_t ShortRegData11[] = {0xC0, 0x50};
+static const uint8_t ShortRegData12[] = {0xD9, 0x4E};
+static const uint8_t ShortRegData13[] = {OTM8009A_CMD_NOP, 0x81};
+static const uint8_t ShortRegData14[] = {0xC1, 0x66};
+static const uint8_t ShortRegData15[] = {OTM8009A_CMD_NOP, 0xA1};
+static const uint8_t ShortRegData16[] = {0xC1, 0x08};
+static const uint8_t ShortRegData17[] = {OTM8009A_CMD_NOP, 0x92};
+static const uint8_t ShortRegData18[] = {0xC5, 0x01};
+static const uint8_t ShortRegData19[] = {OTM8009A_CMD_NOP, 0x95};
+static const uint8_t ShortRegData20[] = {OTM8009A_CMD_NOP, 0x94};
+static const uint8_t ShortRegData21[] = {0xC5, 0x33};
+static const uint8_t ShortRegData22[] = {OTM8009A_CMD_NOP, 0xA3};
+static const uint8_t ShortRegData23[] = {0xC0, 0x1B};
+static const uint8_t ShortRegData24[] = {OTM8009A_CMD_NOP, 0x82};
+static const uint8_t ShortRegData25[] = {0xC5, 0x83};
+static const uint8_t ShortRegData26[] = {0xC4, 0x83};
+static const uint8_t ShortRegData27[] = {0xC1, 0x0E};
+static const uint8_t ShortRegData28[] = {OTM8009A_CMD_NOP, 0xA6};
+static const uint8_t ShortRegData29[] = {OTM8009A_CMD_NOP, 0xA0};
+static const uint8_t ShortRegData30[] = {OTM8009A_CMD_NOP, 0xB0};
+static const uint8_t ShortRegData31[] = {OTM8009A_CMD_NOP, 0xC0};
+static const uint8_t ShortRegData32[] = {OTM8009A_CMD_NOP, 0xD0};
+static const uint8_t ShortRegData33[] = {OTM8009A_CMD_NOP, 0x90};
+static const uint8_t ShortRegData34[] = {OTM8009A_CMD_NOP, 0xE0};
+static const uint8_t ShortRegData35[] = {OTM8009A_CMD_NOP, 0xF0};
+static const uint8_t ShortRegData36[] = {OTM8009A_CMD_SLPOUT, 0x00};
+static const uint8_t ShortRegData37[] = {OTM8009A_CMD_COLMOD, OTM8009A_COLMOD_RGB565};
+static const uint8_t ShortRegData38[] = {OTM8009A_CMD_COLMOD, OTM8009A_COLMOD_RGB888};
+static const uint8_t ShortRegData39[] = {OTM8009A_CMD_MADCTR, OTM8009A_MADCTR_MODE_LANDSCAPE};
+static const uint8_t ShortRegData40[] = {OTM8009A_CMD_WRDISBV, 0x7F};
+static const uint8_t ShortRegData41[] = {OTM8009A_CMD_WRCTRLD, 0x2C};
+static const uint8_t ShortRegData42[] = {OTM8009A_CMD_WRCABC, 0x02};
+static const uint8_t ShortRegData43[] = {OTM8009A_CMD_WRCABCMB, 0xFF};
+static const uint8_t ShortRegData44[] = {OTM8009A_CMD_DISPON, 0x00};
+static const uint8_t ShortRegData45[] = {OTM8009A_CMD_RAMWR, 0x00};
+static const uint8_t ShortRegData46[] = {0xCF, 0x00};
+static const uint8_t ShortRegData47[] = {0xC5, 0x66};
+static const uint8_t ShortRegData48[] = {OTM8009A_CMD_NOP, 0xB6};
+static const uint8_t ShortRegData49[] = {0xF5, 0x06};
+
+
+/** @defgroup STM32F769I-DISCOVERY_LCD_Exported_Variables STM32F769I DISCOVERY LCD Exported Variables
+  * @{
+  */
+static DMA2D_Handle_t hdma2d_discovery;
+static LTDC_Handle_t  hltdc_discovery;
+static DSI_Handle_t   hdsi_discovery;
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/** @defgroup STM32F769I-DISCOVERY_LCD_Private_FunctionPrototypes LCD Private FunctionPrototypes
+  * @{
+  */
+static void FillTriangle(LCD_DrawProp_t *pDrawProp, uint16_t x1, uint16_t x2, uint16_t x3, uint16_t y1, uint16_t y2, uint16_t y3);
+static void LL_FillBuffer(uint32_t LayerIndex, void *pDst, uint32_t xSize, uint32_t ySize, uint32_t OffLine, uint32_t ColorIndex);
+static void LL_ConvertLineToARGB8888(void * pSrc, void *pDst, uint32_t xSize, uint32_t ColorMode);
+/**
+  * @}
+  */
+/**
+  * @brief  DCS or Generic short/long write command
+  * @param  NbParams: Number of parameters. It indicates the write command mode:
+  *                 If inferior to 2, a long write command is performed else short.
+  * @param  pParams: Pointer to parameter values table.
+  * @retval HAL status
+  */
+static void
+DSI_IO_WriteCmd(DSI_Handle_t *hdsi, uint32_t NbrParams, uint8_t *pParams)
+{
+	if(NbrParams <= 1){
+		dsi_swrite(hdsi, LCD_OTM8009A_ID, DSI_DCS_SHORT_PKT_WRITE_P1, pParams[0], pParams[1]);
+	}
+	else{
+		dsi_lwrite(hdsi,  LCD_OTM8009A_ID, DSI_DCS_LONG_PKT_WRITE, NbrParams, pParams[NbrParams], pParams);
+	}
+}
+
+/**
+  * @brief  Initializes the LCD KoD display part by communication in DSI mode in Video Mode
+  *         with IC Display Driver OTM8009A (see IC Driver specification for more information).
+  * @param  hdsi_eval : pointer on DSI configuration structure
+  * @param  hdsivideo_handle : pointer on DSI video mode configuration structure
+  * @retval Status
+  */
+static uint8_t
+OTM8009A_Init(DSI_Handle_t *hdsi, uint32_t ColorCoding, uint32_t orientation)
+{
+	/* Enable CMD2 to access vendor specific commands                               */
+	/* Enter in command 2 mode and set EXTC to enable address shift function (0x00) */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData1);
+	DSI_IO_WriteCmd(hdsi,  3, (uint8_t *)lcdRegData1);
+
+	/* Enter ORISE Command 2 */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData2); /* Shift address to 0x80 */
+	DSI_IO_WriteCmd(hdsi,  2, (uint8_t *)lcdRegData2);
+
+	/////////////////////////////////////////////////////////////////////
+	/* SD_PCH_CTRL - 0xC480h - 129th parameter - Default 0x00          */
+	/* Set SD_PT                                                       */
+	/* -> Source output level during porch and non-display area to GND */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData2);
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData3);
+	dly_tsk(10);
+	/* Not documented */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData4);
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData5);
+	dly_tsk(10);
+	/////////////////////////////////////////////////////////////////////
+
+	/* PWR_CTRL4 - 0xC4B0h - 178th parameter - Default 0xA8 */
+	/* Set gvdd_en_test                                     */
+	/* -> enable GVDD test mode !!!                         */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData6);
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData7);
+
+	/* PWR_CTRL2 - 0xC590h - 146th parameter - Default 0x79      */
+	/* Set pump 4 vgh voltage                                    */
+	/* -> from 15.0v down to 13.0v                               */
+	/* Set pump 5 vgh voltage                                    */
+	/* -> from -12.0v downto -9.0v                               */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData8);
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData9);
+
+	/* P_DRV_M - 0xC0B4h - 181th parameter - Default 0x00 */
+	/* -> Column inversion                                */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData10);
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData11);
+
+	/* VCOMDC - 0xD900h - 1st parameter - Default 0x39h */
+	/* VCOM Voltage settings                            */
+	/* -> from -1.0000v downto -1.2625v                 */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData1);
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData12);
+
+	/* Oscillator adjustment for Idle/Normal mode (LPDT only) set to 65Hz (default is 60Hz) */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData13);
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData14);
+
+	/* Video mode internal */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData15);
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData16);
+
+	/* PWR_CTRL2 - 0xC590h - 147h parameter - Default 0x00 */
+	/* Set pump 4&5 x6                                     */
+	/* -> ONLY VALID when PUMP4_EN_ASDM_HV = "0"           */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData17);
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData18);
+
+	/* PWR_CTRL2 - 0xC590h - 150th parameter - Default 0x33h */
+	/* Change pump4 clock ratio                              */
+	/* -> from 1 line to 1/2 line                            */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData19);
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData9);
+
+	/* GVDD/NGVDD settings */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData1);
+	DSI_IO_WriteCmd(hdsi,  2, (uint8_t *)lcdRegData5);
+
+	/* PWR_CTRL2 - 0xC590h - 149th parameter - Default 0x33h */
+	/* Rewrite the default value !                           */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData20);
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData21);
+
+	/* Panel display timing Setting 3 */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData22);
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData23);
+
+	/* Power control 1 */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData24);
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData25);
+
+	/* Source driver precharge */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData13);
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData26);
+
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData15);
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData27);
+
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData28);
+	DSI_IO_WriteCmd(hdsi,  2, (uint8_t *)lcdRegData6);
+
+	/* GOAVST */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData2);
+	DSI_IO_WriteCmd(hdsi,  6, (uint8_t *)lcdRegData7);
+
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData29);
+	DSI_IO_WriteCmd(hdsi,  14, (uint8_t *)lcdRegData8);
+
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData30);
+	DSI_IO_WriteCmd(hdsi,  14, (uint8_t *)lcdRegData9);
+
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData31);
+	DSI_IO_WriteCmd(hdsi,  10, (uint8_t *)lcdRegData10);
+
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData32);
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData46);
+
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData2);
+	DSI_IO_WriteCmd(hdsi,  10, (uint8_t *)lcdRegData11);
+
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData33);
+	DSI_IO_WriteCmd(hdsi,  15, (uint8_t *)lcdRegData12);
+
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData29);
+	DSI_IO_WriteCmd(hdsi,  15, (uint8_t *)lcdRegData13);
+
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData30);
+	DSI_IO_WriteCmd(hdsi,  10, (uint8_t *)lcdRegData14);
+
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData31);
+	DSI_IO_WriteCmd(hdsi,  15, (uint8_t *)lcdRegData15);
+
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData32);
+	DSI_IO_WriteCmd(hdsi,  15, (uint8_t *)lcdRegData16);
+
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData34);
+	DSI_IO_WriteCmd(hdsi,  10, (uint8_t *)lcdRegData17);
+
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData35);
+	DSI_IO_WriteCmd(hdsi,  10, (uint8_t *)lcdRegData18);
+
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData2);
+	DSI_IO_WriteCmd(hdsi,  10, (uint8_t *)lcdRegData19);
+
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData33);
+	DSI_IO_WriteCmd(hdsi,  15, (uint8_t *)lcdRegData20);
+
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData29);
+	DSI_IO_WriteCmd(hdsi,  15, (uint8_t *)lcdRegData21);
+
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData30);
+	DSI_IO_WriteCmd(hdsi,  10, (uint8_t *)lcdRegData22);
+
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData31);
+	DSI_IO_WriteCmd(hdsi,  15, (uint8_t *)lcdRegData23);
+
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData32);
+	DSI_IO_WriteCmd(hdsi,  15, (uint8_t *)lcdRegData24);
+
+	/////////////////////////////////////////////////////////////////////////////
+	/* PWR_CTRL1 - 0xc580h - 130th parameter - default 0x00 */
+	/* Pump 1 min and max DM                                */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData13);
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData47);
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData48);
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData49);
+	/////////////////////////////////////////////////////////////////////////////
+
+	/* Exit CMD2 mode */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData1);
+	DSI_IO_WriteCmd(hdsi,  3, (uint8_t *)lcdRegData25);
+
+	/*************************************************************************** */
+	/* Standard DCS Initialization TO KEEP CAN BE DONE IN HSDT                   */
+	/*************************************************************************** */
+
+	/* NOP - goes back to DCS std command ? */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData1);
+
+	/* Gamma correction 2.2+ table (HSDT possible) */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData1);
+	DSI_IO_WriteCmd(hdsi,  16, (uint8_t *)lcdRegData3);
+
+	/* Gamma correction 2.2- table (HSDT possible) */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData1);
+	DSI_IO_WriteCmd(hdsi,  16, (uint8_t *)lcdRegData4);
+
+	/* Send Sleep Out command to display : no parameter */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData36);
+
+	/* Wait for sleep out exit */
+	dly_tsk(120);
+
+	switch(ColorCoding){
+	case OTM8009A_FORMAT_RBG565:
+		/* Set Pixel color format to RGB565 */
+		DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData37);
+		break;
+	case OTM8009A_FORMAT_RGB888:
+		/* Set Pixel color format to RGB888 */
+		DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData38);
+		break;
+	default:
+		break;
+	}
+
+	/* Send command to configure display in landscape orientation mode. By default
+      the orientation mode is portrait  */
+	if(orientation == OTM8009A_ORIENTATION_LANDSCAPE){
+		DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData39);
+		DSI_IO_WriteCmd(hdsi,  4, (uint8_t *)lcdRegData27);
+		DSI_IO_WriteCmd(hdsi,  4, (uint8_t *)lcdRegData28);
+	}
+
+	/** CABC : Content Adaptive Backlight Control section start >> */
+	/* Note : defaut is 0 (lowest Brightness), 0xFF is highest Brightness, try 0x7F : intermediate value */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData40);
+
+	/* defaut is 0, try 0x2C - Brightness Control Block, Display Dimming & BackLight on */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData41);
+
+	/* defaut is 0, try 0x02 - image Content based Adaptive Brightness [Still Picture] */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData42);
+
+	/* defaut is 0 (lowest Brightness), 0xFF is highest Brightness */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData43);
+
+	/** CABC : Content Adaptive Backlight Control section end << */
+
+	/* Send Command Display On */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData44);
+
+	/* NOP command */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData1);
+
+	/* Send Command GRAM memory write (no parameters) : this initiates frame write via other DSI commands sent by */
+	/* DSI host from LTDC incoming pixels in video mode */
+	DSI_IO_WriteCmd(hdsi, 0, (uint8_t *)ShortRegData45);
+	return 0;
+}
+
+
+/*
+ *  LTDC/DSI割込みハンドラ
+ */
+void ltdc_handler(void)
+{
+	ltdc_irqhandler(&hltdc_discovery);
+}
+
+void dsi_handler(void)
+{
+	dsi_irqhandler(&hdsi_discovery);
+}
+
+/*
+ *  DSI/OTM8009Aスクリーンの初期化関数
+ */
+ER
+lcd_init(LCD_Handler_t *hlcd, LCD_OrientationTypeDef orientation)
+{
+	LTDC_Handle_t *hldtc = &hltdc_discovery;
+	DSI_Handle_t  *hdsi  = &hdsi_discovery;
+	uint32_t LcdClock  = 27429; /*!< LcdClk = 27429 kHz */
+
+	uint32_t laneByteClk_kHz = 0;
+	uint32_t VSA;	/*!< Vertical start active time in units of lines */
+	uint32_t VBP;	/*!< Vertical Back Porch time in units of lines */
+	uint32_t VFP;	/*!< Vertical Front Porch time in units of lines */
+	uint32_t VACT;	/*!< Vertical Active time in units of lines = imageSize Y in pixels to display */
+	uint32_t HSA;	/*!< Horizontal start active time in units of lcdClk */
+	uint32_t HBP;	/*!< Horizontal Back Porch time in units of lcdClk */
+	uint32_t HFP;	/*!< Horizontal Front Porch time in units of lcdClk */
+	uint32_t HACT;	/*!< Horizontal Active time in units of lcdClk = imageSize X in pixels to display */
+
+	/* Toggle Hardware Reset of the DSI LCD using
+	 * its XRES signal (active low) */
+	lcd_reset(hlcd);
+	hlcd->layer = LTDC_ACTIVE_LAYER_BACKGROUND;
+
+  /* Call first MSP Initialize only in case of first initialization
+  * This will set IP blocks LTDC, DSI and DMA2D
+  * - out of reset
+  * - clocked
+  * - NVIC IRQ related to IP blocks enabled
+  */
+	/** @brief Enable the LTDC clock */
+	sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_APB2ENR), RCC_APB2ENR_LTDCEN);
+
+
+	/** @brief Toggle Sw reset of LTDC IP */
+	sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_APB2RSTR), RCC_APB2RSTR_LTDCRST);
+	sil_andw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_APB2RSTR), RCC_APB2RSTR_LTDCRST);
+
+	/** @brief Enable the DMA2D clock */
+	sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB1ENR), RCC_AHB1ENR_DMA2DEN);
+
+	/** @brief Toggle Sw reset of DMA2D IP */
+	sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB1RSTR), RCC_AHB1RSTR_DMA2DRST);
+	sil_andw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB1RSTR), RCC_AHB1RSTR_DMA2DRST);
+
+	/** @brief Enable DSI Host and wrapper clocks */
+	sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_APB2ENR), RCC_APB2ENR_DSIEN);
+
+	/** @brief Soft Reset the DSI Host and wrapper */
+	sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_APB2RSTR), RCC_APB2RSTR_DSIRST);
+	sil_andw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_APB2RSTR), RCC_APB2RSTR_DSIRST);
+
+/*************************DSI Initialization***********************************/  
+
+	/* Base address of DSI Host/Wrapper registers to be set before calling De-Init */
+	hlcd->hdsi = hdsi;
+	hdsi->base = TADR_DSI_BASE;
+
+	dsi_deinit(hlcd->hdsi);
+
+	hdsi->Init.pllndiv = 100;
+	hdsi->Init.pllidf  = DSI_PLL_IN_DIV5;
+	hdsi->Init.pllodf  = DSI_PLL_OUT_DIV1;
+	laneByteClk_kHz = 62500; /* 500 MHz / 8 = 62.5 MHz = 62500 kHz */
+
+	/* Set number of Lanes */
+	hdsi->Init.NumberOfLanes = DSI_TWO_DATA_LANES;
+
+	/* TXEscapeCkdiv = f(LaneByteClk)/15.62 = 4 */
+	hdsi->Init.TXEscapeCkdiv = laneByteClk_kHz/15620;
+
+	dsi_init(hlcd->hdsi);
+
+	/* Timing parameters for all Video modes
+	 * Set Timing parameters of LTDC depending on its chosen orientation
+	 */
+	if(orientation == LCD_ORIENTATION_PORTRAIT){
+		hlcd->_width  = OTM8009A_480X800_WIDTH;  /* 480 */
+		hlcd->_height = OTM8009A_480X800_HEIGHT; /* 800 */                                
+	}
+	else{
+		/* lcd_orientation == LCD_ORIENTATION_LANDSCAPE */
+		hlcd->_width  = OTM8009A_800X480_WIDTH;  /* 800 */
+		hlcd->_height = OTM8009A_800X480_HEIGHT; /* 480 */                                
+	}
+
+	HACT = hlcd->_width;
+	VACT = hlcd->_height;
+
+	/* The following values are same for portrait and landscape orientations */
+	VSA  = OTM8009A_480X800_VSYNC;        /* 12  */
+	VBP  = OTM8009A_480X800_VBP;          /* 12  */
+	VFP  = OTM8009A_480X800_VFP;          /* 12  */
+	HSA  = OTM8009A_480X800_HSYNC;        /* 63  */
+	HBP  = OTM8009A_480X800_HBP;          /* 120 */
+	HFP  = OTM8009A_480X800_HFP;          /* 120 */   
+
+	hlcd->dsivc.VirtualChannelID = LCD_OTM8009A_ID;
+	hlcd->dsivc.ColorCoding = LCD_DSI_PIXEL_DATA_FMT_RBG888;
+	hlcd->dsivc.VSPolarity = DSI_VSYNC_ACTIVE_HIGH;
+	hlcd->dsivc.HSPolarity = DSI_HSYNC_ACTIVE_HIGH;
+	hlcd->dsivc.DEPolarity = DSI_DATA_ENABLE_ACTIVE_HIGH;  
+	hlcd->dsivc.Mode = DSI_VID_MODE_BURST; /* Mode Video burst ie : one LgP per line */
+	hlcd->dsivc.NullPacketSize = 0xFFF;
+	hlcd->dsivc.NumberOfChunks = 0;
+	hlcd->dsivc.PacketSize                = HACT; /* Value depending on display orientation choice portrait/landscape */ 
+	hlcd->dsivc.HorizontalSyncActive      = (HSA * laneByteClk_kHz)/LcdClock;
+	hlcd->dsivc.HorizontalBackPorch       = (HBP * laneByteClk_kHz)/LcdClock;
+	hlcd->dsivc.HorizontalLine            = ((HACT + HSA + HBP + HFP) * laneByteClk_kHz)/LcdClock; /* Value depending on display orientation choice portrait/landscape */
+	hlcd->dsivc.VerticalSyncActive        = VSA;
+	hlcd->dsivc.VerticalBackPorch         = VBP;
+	hlcd->dsivc.VerticalFrontPorch        = VFP;
+	hlcd->dsivc.VerticalActive            = VACT; /* Value depending on display orientation choice portrait/landscape */
+
+	/* Enable or disable sending LP command while streaming is active in video mode */
+	hlcd->dsivc.LPCommandEnable = DSI_LP_COMMAND_ENABLE; /* Enable sending commands in mode LP (Low Power) */
+
+	/* Largest packet size possible to transmit in LP mode in VSA, VBP, VFP regions */
+	/* Only useful when sending LP packets is allowed while streaming is active in video mode */
+	hlcd->dsivc.LPLargestPacketSize = 16;
+
+	/* Largest packet size possible to transmit in LP mode in HFP region during VACT period */
+	/* Only useful when sending LP packets is allowed while streaming is active in video mode */
+	hlcd->dsivc.LPVACTLargestPacketSize = 0;
+
+	/* Specify for each region of the video frame, if the transmission of command in LP mode is allowed in this region */
+	/* while streaming is active in video mode                                                                         */
+	hlcd->dsivc.LPHorizontalFrontPorchEnable = DSI_LP_HFP_ENABLE;   /* Allow sending LP commands during HFP period */
+	hlcd->dsivc.LPHorizontalBackPorchEnable  = DSI_LP_HBP_ENABLE;   /* Allow sending LP commands during HBP period */
+	hlcd->dsivc.LPVerticalActiveEnable = DSI_LP_VACT_ENABLE;  /* Allow sending LP commands during VACT period */
+	hlcd->dsivc.LPVerticalFrontPorchEnable = DSI_LP_VFP_ENABLE;   /* Allow sending LP commands during VFP period */
+	hlcd->dsivc.LPVerticalBackPorchEnable = DSI_LP_VBP_ENABLE;   /* Allow sending LP commands during VBP period */
+	hlcd->dsivc.LPVerticalSyncActiveEnable = DSI_LP_VSYNC_ENABLE; /* Allow sending LP commands during VSync = VSA period */
+
+	/* Configure DSI Video mode timings with settings set above */
+	dsi_configvideo(hlcd->hdsi, &hlcd->dsivc);
+
+/*************************End DSI Initialization*******************************/ 
+
+
+/************************LTDC Initialization***********************************/  
+
+	/* Timing Configuration */
+	hldtc->Init.HorizontalSync = (HSA - 1);
+	hldtc->Init.AccumulatedHBP = (HSA + HBP - 1);
+	hldtc->Init.AccumulatedActiveW = (hlcd->_width + HSA + HBP - 1);
+	hldtc->Init.TotalWidth = (hlcd->_width + HSA + HBP + HFP - 1);
+
+	/* Initialize the LCD pixel width and pixel height */
+	hldtc->LayerCfg->ImageWidth  = hlcd->_width;
+	hldtc->LayerCfg->ImageHeight = hlcd->_height;
+
+	/** LCD clock configuration
+	 * Note: The following values should not be changed as the PLLSAI is also used 
+	 *      to clock the USB FS
+	 * PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz 
+	 * PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 384 Mhz 
+	 * PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 384 MHz / 7 = 54.85 MHz 
+	 * LTDC clock frequency = PLLLCDCLK / LTDC_PLLSAI_DIVR_2 = 54.85 MHz / 2 = 27.429 MHz 
+	 */
+	/* Background value */
+	hldtc->Init.Backcolor.Blue = 0;
+	hldtc->Init.Backcolor.Green = 0;
+	hldtc->Init.Backcolor.Red = 0;
+	hldtc->Init.PCPolarity = LTDC_PCPOLARITY_IPC;
+	hldtc->Init.pllsain = 384;
+	hldtc->Init.pllsair = 7;
+	hldtc->Init.saidivr = RCC_PLLSAIDIVR_2;
+	hldtc->base = TADR_LTDC_BASE;
+
+	/* Get LTDC Configuration from DSI Configuration */
+	dci_configltdc(hldtc, &hlcd->dsivc);
+
+	/* Initialize the LTDC */  
+	ltdc_init(hldtc);
+	hlcd->hltdc = hldtc;
+
+	/* Enable the DSI host and wrapper after the LTDC initialization
+	   To avoid any synchronization issue, the DSI shall be started after enabling the LTDC */
+	dsi_start(hlcd->hdsi);
+
+	/* Initialize the font */
+//	BSP_LCD_SetFont(&LCD_DEFAULT_FONT);
+
+/************************End LTDC Initialization*******************************/
+  
+  
+/***********************OTM8009A Initialization********************************/ 
+
+	/* Initialize the OTM8009A LCD Display IC Driver (KoD LCD IC Driver)
+	 *  depending on configuration set in 'hdsivideo_handle'.
+	 */
+	OTM8009A_Init(hlcd->hdsi, OTM8009A_FORMAT_RGB888, orientation);
+
+/***********************End OTM8009A Initialization****************************/ 
+	return E_OK;
+}
+
+/*
+ *  DSI/OTM8009Aスクリーンのリセット関数
+ */
+ER
+lcd_reset(LCD_Handler_t *hlcd)
+{
+	GPIO_Init_t  gpio_init_structure;
+	uint32_t base = TADR_GPIOJ_BASE;
+
+	sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB1ENR), RCC_AHB1ENR_GPIOJEN);
+
+    /* Configure the GPIO on PJ15 */
+    gpio_init_structure.mode  = GPIO_MODE_OUTPUT;
+    gpio_init_structure.pull  = GPIO_PULLUP;
+    gpio_init_structure.otype = GPIO_OTYPE_PP;
+    gpio_init_structure.speed = GPIO_SPEED_HIGH;
+	gpio_setup(base, &gpio_init_structure, PINPOSITION15);
+
+    sil_wrw_mem((uint32_t *)(base+TOFF_GPIO_BSRR), GPIO_PIN_15<<16);
+	sil_dly_nse(100);
+
+    dly_tsk(20); /* wait 20 ms */
+
+    /* Desactivate XRES */
+    sil_wrw_mem((uint32_t *)(base+TOFF_GPIO_BSRR), GPIO_PIN_15);
+
+    /* Wait for 10ms after releasing XRES before sending commands */
+    dly_tsk(10);
+	return E_OK;
+}
+
+
+/*
+ *  DSI/OTM8009Aスクリーンレイヤ初期化関数
+ */
+ER
+lcd_layerdefaultinit(LCD_Handler_t *hlcd, LCD_DrawProp_t *pDrawProp, uint16_t LayerIndex, uint32_t FB_Address)
+{
+    LTDC_LayerCfg_t  Layercfg;
+
+	/* Layer Init */
+	Layercfg.WindowX0 = 0;
+	Layercfg.WindowX1 = hlcd->_width;
+	Layercfg.WindowY0 = 0;
+	Layercfg.WindowY1 = hlcd->_height;
+	Layercfg.PixelFormat = LTDC_PIXEL_FORMAT_ARGB8888;
+	Layercfg.FBStartAdress = FB_Address;
+	Layercfg.Alpha = 255;
+	Layercfg.Alpha0 = 0;
+	Layercfg.Backcolor.Blue = 0;
+	Layercfg.Backcolor.Green = 0;
+	Layercfg.Backcolor.Red = 0;
+	Layercfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA;
+	Layercfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA;
+	Layercfg.ImageWidth = hlcd->_width;
+	Layercfg.ImageHeight = hlcd->_height;
+
+	ltdc_configlayer(hlcd->hltdc, &Layercfg, LayerIndex);
+
+	hlcd->layer = LayerIndex;
+	pDrawProp[LayerIndex].BackColor = LCD_COLOR_WHITE;
+	pDrawProp[LayerIndex].TextColor = LCD_COLOR_BLACK;
+	pDrawProp[LayerIndex].hlcd      = hlcd;
+	return E_OK;
+}
+
+/*
+ *  DSI/OTM8009Aスクリーンレイヤ表示設定関数
+ */
+void
+lcd_setlayervisible(LCD_Handler_t *hlcd, uint32_t LayerIndex, uint8_t State)
+{
+	uint32_t layer = (TADR_LTDC_LAYER1 + (LTDC_WINDOW_SIZE * LayerIndex));
+	if(State == 1){
+		sil_orw_mem((uint32_t *)(layer+TOFF_LTDCW_CR), LTDC_CR_LEN);
+	}
+	else{
+		sil_andw_mem((uint32_t *)(layer+TOFF_LTDCW_CR), LTDC_CR_LEN);
+	}
+	sil_orw_mem((uint32_t *)(TADR_LTDC_BASE+TOFF_LTDC_SRCR), LTDC_SRCR_IMR);
+}
+
+/*
+ *  DSI/OTM8009Aスクリーンレイヤ透過設定関数
+ */
+void
+lcd_settransparency(LCD_Handler_t *hlcd, uint32_t LayerIndex, uint8_t Transparency)
+{
+	ltdc_setalpha(hlcd->hltdc, Transparency, LayerIndex);
+}
+
+/*
+ *  DSI/OTM8009AスクリーンレイヤRAMアドレス設定関数
+ */
+void
+lcd_setlayeraddress(LCD_Handler_t *hlcd, uint32_t LayerIndex, uint32_t Address)
+{
+	ltdc_setaddress(hlcd->hltdc, Address, LayerIndex);
+}
+
+/*
+ *  DSI/OTM8009A表示ウィンドウ設定
+ */
+void
+lcd_setAddrWindow(LCD_Handler_t *hlcd, uint16_t LayerIndex, uint16_t Xpos, uint16_t Ypos, uint16_t Width, uint16_t Height)
+{
+	/* Reconfigure the layer size */
+	ltdc_setwindowsize(hlcd->hltdc, Width, Height, LayerIndex);
+
+	/* Reconfigure the layer position */
+	ltdc_setwindowposition(hlcd->hltdc, Xpos, Ypos, LayerIndex);
+}
+
+/**
+  * @brief  Configures and sets the color keying.
+  * @param  LayerIndex: Layer foreground or background
+  * @param  RGBValue: Color reference
+  */
+void
+lcd_setcolorkeying(LCD_Handler_t *hlcd, uint32_t LayerIndex, uint32_t RGBValue)
+{
+	/* Configure and Enable the color Keying for LCD Layer */
+	ltdc_configcolorkeying(hlcd->hltdc, RGBValue, LayerIndex);
+	ltdc_enablecolorkeying(hlcd->hltdc, LayerIndex);
+}
+
+/**
+  * @brief  Disables the color keying.
+  * @param  LayerIndex: Layer foreground or background
+  */
+void
+lcd_resetcolorkeying(LCD_Handler_t *hlcd, uint32_t LayerIndex)
+{
+	/* Disable the color Keying for LCD Layer */
+	ltdc_disablecolorkeying(hlcd->hltdc, LayerIndex);
+}
+
+/*
+ *  DSI/OTM8009Aスクリーンクリア
+ */
+void
+lcd_clear(LCD_Handler_t *hlcd, uint32_t Color)
+{
+	/* Clear the LCD */
+	LL_FillBuffer(hlcd->layer, (uint32_t *)(hlcd->hltdc->LayerCfg[hlcd->layer].FBStartAdress), hlcd->_width, hlcd->_height, 0, Color);
+}
+
+/*
+ *  PIXEL読み出し
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: X position
+ *  param3  y: Y position
+ */
+uint32_t
+lcd_readPixel(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos)
+{
+	LTDC_Handle_t  *hltdc = hlcd->hltdc;
+	uint32_t ret = 0;
+
+	if(hltdc->LayerCfg[hlcd->layer].PixelFormat == LTDC_PIXEL_FORMAT_ARGB8888){
+		/* Read data value from SDRAM memory */
+		ret = *(volatile uint32_t*)(hltdc->LayerCfg[hlcd->layer].FBStartAdress + (2*(Ypos*hlcd->_width + Xpos)));
+	}
+	else if(hltdc->LayerCfg[hlcd->layer].PixelFormat == LTDC_PIXEL_FORMAT_RGB888){
+		/* Read data value from SDRAM memory */
+		ret = (*(volatile uint32_t*) (hltdc->LayerCfg[hlcd->layer].FBStartAdress + (2*(Ypos*hlcd->_width + Xpos))) & 0x00FFFFFF);
+	}
+	else if((hltdc->LayerCfg[hlcd->layer].PixelFormat == LTDC_PIXEL_FORMAT_RGB565) || \
+          (hltdc->LayerCfg[hlcd->layer].PixelFormat == LTDC_PIXEL_FORMAT_ARGB4444) || \
+          (hltdc->LayerCfg[hlcd->layer].PixelFormat == LTDC_PIXEL_FORMAT_AL88)){
+		/* Read data value from SDRAM memory */
+		ret = *(volatile uint16_t*) (hltdc->LayerCfg[hlcd->layer].FBStartAdress + (2*(Ypos*hlcd->_width + Xpos)));
+	}
+	else{
+		/* Read data value from SDRAM memory */
+		ret = *(volatile uint8_t*) (hltdc->LayerCfg[hlcd->layer].FBStartAdress + (2*(Ypos*hlcd->_width + Xpos)));
+	}
+	return ret;
+}
+
+/*
+ *  PIXEL描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: X position
+ *  param3  y: Y position
+ *  param4  color: color value
+ */
+void
+lcd_drawPixel(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint32_t RGB_Code)
+{
+	/* Write data value to all SDRAM memory */
+	*(volatile uint32_t*) (hlcd->hltdc->LayerCfg[hlcd->layer].FBStartAdress + (4*(Ypos*hlcd->_width + Xpos))) = RGB_Code;
+}
+
+/*
+ *  垂直方向LINEの高速描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: start X position
+ *  param3  y: start Y position
+ *  param4  h: height
+ *  param5  color: color value
+ */
+void
+lcd_drawFastHLine(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint16_t Length, uint32_t color)
+{
+	uint32_t  Xaddress = 0;
+
+	/* Get the line address */
+	Xaddress = (hlcd->hltdc->LayerCfg[hlcd->layer].FBStartAdress) + 4*(hlcd->_width*Ypos + Xpos);
+
+	/* Write line */
+	LL_FillBuffer(hlcd->layer, (uint32_t *)Xaddress, Length, 1, 0, color);
+}
+
+/*
+ *  水平方向LINEの高速描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: start X position
+ *  param3  y: start Y position
+ *  param4  w: width
+ *  param5  color: color value
+ */
+void
+lcd_drawFastVLine(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint16_t Length, uint32_t color)
+{
+	uint32_t  Xaddress = 0;
+
+	/* Get the line address */
+	Xaddress = (hlcd->hltdc->LayerCfg[hlcd->layer].FBStartAdress) + 4*(hlcd->_width*Ypos + Xpos);
+
+	/* Write line */
+	LL_FillBuffer(hlcd->layer, (uint32_t *)Xaddress, 1, Length, (hlcd->_width - 1), color);
+}
+
+/*
+ *  BITMAP描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x0: Bmp X position in the LCD
+ *  param3  y0: Bmp Y position in the LCD
+ *  param4  pbmp: Pointer to Bmp picture address in the internal Flash
+ */
+void
+lcd_drawBitmap(LCD_Handler_t *hlcd, uint32_t Xpos, uint32_t Ypos, uint8_t *pbmp)
+{
+	uint32_t index = 0, width = 0, height = 0, bit_pixel = 0;
+	uint32_t Address;
+	uint32_t InputColorMode = 0;
+
+	/* Get bitmap data address offset */
+	index = *(volatile uint16_t *) (pbmp + 10);
+	index |= (*(volatile uint16_t *) (pbmp + 12)) << 16;
+
+	/* Read bitmap width */
+	width = *(volatile uint16_t *) (pbmp + 18);
+	width |= (*(volatile uint16_t *) (pbmp + 20)) << 16;
+
+	/* Read bitmap height */
+	height = *(volatile uint16_t *) (pbmp + 22);
+	height |= (*(volatile uint16_t *) (pbmp + 24)) << 16;
+
+	/* Read bit/pixel */
+	bit_pixel = *(uint16_t *) (pbmp + 28);
+
+	/* Set the address */
+	Address = hlcd->hltdc->LayerCfg[hlcd->layer].FBStartAdress + (((hlcd->_width*Ypos) + Xpos)*(4));
+
+	/* Get the layer pixel format */
+	if((bit_pixel/8) == 4){
+		InputColorMode = DMA2D_ARGB8888;
+	}
+	else if((bit_pixel/8) == 2){
+		InputColorMode = DMA2D_RGB565;
+	}
+	else{
+		InputColorMode = DMA2D_RGB888;
+	}
+
+	/* Bypass the bitmap header */
+	pbmp += (index + (width * (height - 1) * (bit_pixel/8)));
+
+	/* Convert picture to ARGB8888 pixel format */
+	for(index=0; index < height; index++){
+		/* Pixel format conversion */
+		LL_ConvertLineToARGB8888((uint32_t *)pbmp, (uint32_t *)Address, width, InputColorMode);
+
+		/* Increment the source and destination buffers */
+		Address+=  (hlcd->_width*4);
+		pbmp -= width*(bit_pixel/8);
+	}
+}
+
+/*
+ *  表示オン
+ *  param1  hlcd: Pointer to LCD Handler
+ */
+void
+lcd_displayOn(LCD_Handler_t *hlcd)
+{
+    /* Send Display on DCS command to display */
+    dsi_swrite(hlcd->hdsi, hlcd->dsivc.VirtualChannelID,
+                       DSI_DCS_SHORT_PKT_WRITE_P1,
+                       OTM8009A_CMD_DISPON,
+                       0x00);
+}
+
+/*
+ *  表示オフ
+ *  param1  hlcd: Pointer to LCD Handler
+ */
+void
+lcd_displayOff(LCD_Handler_t *hlcd)
+{
+    /* Send Display off DCS Command to display */
+    dsi_swrite(hlcd->hdsi, hlcd->dsivc.VirtualChannelID,
+                       DSI_DCS_SHORT_PKT_WRITE_P1,
+                       OTM8009A_CMD_DISPOFF,
+                       0x00);
+}
+
+/**
+  * @brief  Set the brightness value 
+  * @param  BrightnessValue: [00: Min (black), 100 Max]
+  */
+void
+lcd_setbrightness(LCD_Handler_t *hlcd, uint8_t BrightnessValue)
+{
+    /* Send Display on DCS command to display */
+    dsi_swrite(hlcd->hdsi, LCD_OTM8009A_ID, 
+                       DSI_DCS_SHORT_PKT_WRITE_P1, 
+                       OTM8009A_CMD_WRDISBV, (uint16_t)(BrightnessValue * 255)/100);
+}
+
+/*
+ *  RECTANGLE塗りつぶし描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: left X position
+ *  param3  y: top Y position
+ *  param4  w: width
+ *  param5  h: height
+ *  param6  color: color value
+ */
+void
+lcd_fillRect(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint16_t Width, uint16_t Height, uint32_t color)
+{
+	uint32_t  Xaddress = 0;
+
+	/* Get the rectangle start address */
+	Xaddress = (hlcd->hltdc->LayerCfg[hlcd->layer].FBStartAdress) + 4*(hlcd->_width*Ypos + Xpos);
+
+	/* Fill the rectangle */
+	LL_FillBuffer(hlcd->layer, (uint32_t *)Xaddress, Width, Height, (hlcd->_width - Width), color);
+}
+
+
+/*
+ *  線描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x1: Point 1 X position
+ *  param3  y1: Point 1 Y position
+ *  param4  x2: Point 2 X position
+ *  param5  y2: Point 2 Y position
+ */
+void
+lcd_drawLine(LCD_DrawProp_t *pDrawProp, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0,
+	yinc1 = 0, yinc2 = 0, den = 0, num = 0, numadd = 0, numpixels = 0,
+	curpixel = 0;
+
+	deltax = ABS(x2 - x1);        /* The difference between the x's */
+	deltay = ABS(y2 - y1);        /* The difference between the y's */
+	x = x1;                       /* Start x off at the first pixel */
+	y = y1;                       /* Start y off at the first pixel */
+
+	if(x2 >= x1){				/* The x-values are increasing */
+		xinc1 = 1;
+		xinc2 = 1;
+	}
+	else{						/* The x-values are decreasing */
+		xinc1 = -1;
+		xinc2 = -1;
+	}
+
+	if(y2 >= y1){				/* The y-values are increasing */
+		yinc1 = 1;
+		yinc2 = 1;
+	}
+	else{						/* The y-values are decreasing */
+		yinc1 = -1;
+		yinc2 = -1;
+	}
+
+	if(deltax >= deltay){		/* There is at least one x-value for every y-value */
+		xinc1 = 0;                  /* Don't change the x when numerator >= denominator */
+		yinc2 = 0;                  /* Don't change the y for every iteration */
+		den = deltax;
+		num = deltax / 2;
+		numadd = deltay;
+		numpixels = deltax;         /* There are more x-values than y-values */
+	}
+	else{							/* There is at least one y-value for every x-value */
+		xinc2 = 0;                  /* Don't change the x for every iteration */
+		yinc1 = 0;                  /* Don't change the y when numerator >= denominator */
+		den = deltay;
+		num = deltay / 2;
+		numadd = deltax;
+		numpixels = deltay;         /* There are more y-values than x-values */
+	}
+
+	for(curpixel = 0; curpixel <= numpixels; curpixel++){
+		lcd_drawPixel(hlcd, x, y, pDrawProp->TextColor);	/* Draw the current pixel */
+		num += numadd;				/* Increase the numerator by the top of the fraction */
+		if(num >= den){				/* Check if numerator >= denominator */
+			num -= den;				/* Calculate the new numerator value */
+			x += xinc1;				/* Change the x as appropriate */
+			y += yinc1;				/* Change the y as appropriate */
+		}
+		x += xinc2;					/* Change the x as appropriate */
+		y += yinc2;					/* Change the y as appropriate */
+	}
+}
+
+/*
+ *  RECTANGLE描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x: left X position
+ *  param3  y: top Y position
+ *  param4  w: width
+ *  param5  h: height
+ */
+void
+lcd_drawRect(LCD_DrawProp_t *pDrawProp, uint16_t Xpos, uint16_t Ypos, uint16_t Width, uint16_t Height)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	uint32_t      color = pDrawProp->TextColor;
+
+	/* Draw horizontal lines */
+	lcd_drawFastHLine(hlcd, Xpos, Ypos, Width, color);
+	lcd_drawFastHLine(hlcd, Xpos, (Ypos+ Height), Width, color);
+
+	/* Draw vertical lines */
+	lcd_drawFastVLine(hlcd, Xpos, Ypos, Height, color);
+	lcd_drawFastVLine(hlcd, (Xpos + Width), Ypos, Height, color);
+}
+
+/*
+ *  円描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x0: X position
+ *  param3  y0: Y position
+ *  param4  Radius: Circle radius
+ */
+void
+lcd_DrawCircle(LCD_DrawProp_t *pDrawProp, uint16_t Xpos, uint16_t Ypos, uint16_t Radius)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	uint32_t      color = pDrawProp->TextColor;
+	int32_t   D;    /* Decision Variable */
+	uint32_t  CurX; /* Current X Value */
+	uint32_t  CurY; /* Current Y Value */
+
+	D = 3 - (Radius << 1);
+	CurX = 0;
+	CurY = Radius;
+
+	while (CurX <= CurY){
+		lcd_drawPixel(hlcd, (Xpos + CurX), (Ypos - CurY), color);
+		lcd_drawPixel(hlcd, (Xpos - CurX), (Ypos - CurY), color);
+		lcd_drawPixel(hlcd, (Xpos + CurY), (Ypos - CurX), color);
+		lcd_drawPixel(hlcd, (Xpos - CurY), (Ypos - CurX), color);
+		lcd_drawPixel(hlcd, (Xpos + CurX), (Ypos + CurY), color);
+		lcd_drawPixel(hlcd, (Xpos - CurX), (Ypos + CurY), color);
+		lcd_drawPixel(hlcd, (Xpos + CurY), (Ypos + CurX), color);
+		lcd_drawPixel(hlcd, (Xpos - CurY), (Ypos + CurX), color);
+		if(D < 0){
+			D += (CurX << 2) + 6;
+		}
+		else{
+			D += ((CurX - CurY) << 2) + 10;
+			CurY--;
+		}
+		CurX++;
+	}
+}
+
+/*
+ *  楕円描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x0: X position
+ *  param3  y0: Y position
+ *  param4  XRadius: Ellipse X radius
+ *  param5  YRadius: Ellipse Y radius
+ */
+void
+lcd_DrawEllipse(LCD_DrawProp_t *pDrawProp, int Xpos, int Ypos, int XRadius, int YRadius)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	uint32_t      color = pDrawProp->TextColor;
+	int x = 0, y = -YRadius, err = 2-2*XRadius, e2;
+	float K = 0, rad1 = 0, rad2 = 0;
+
+	rad1 = XRadius;
+	rad2 = YRadius;
+
+	K = (float)(rad2/rad1);
+
+	do{
+		lcd_drawPixel(hlcd, (Xpos-(uint16_t)(x/K)), (Ypos+y), color);
+		lcd_drawPixel(hlcd, (Xpos+(uint16_t)(x/K)), (Ypos+y), color);
+		lcd_drawPixel(hlcd, (Xpos+(uint16_t)(x/K)), (Ypos-y), color);
+		lcd_drawPixel(hlcd, (Xpos-(uint16_t)(x/K)), (Ypos-y), color);
+
+		e2 = err;
+		if(e2 <= x){
+			err += ++x*2+1;
+			if (-y == x && e2 <= y)
+				e2 = 0;
+		}
+		if(e2 > y)
+			err += ++y*2+1;
+	}while (y <= 0);
+}
+
+/*
+ *  PLOY-LINE描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  Points: Pointer to the points array
+ *  param3  PointCount: Number of points
+ */
+void
+lcd_drawPolygon(LCD_DrawProp_t *pDrawProp, pPoint Points, uint16_t PointCount)
+{
+	int16_t X = 0, Y = 0;
+
+	if(PointCount < 2){
+		return;
+	}
+
+	lcd_drawLine(pDrawProp, Points->X, Points->Y, (Points+PointCount-1)->X, (Points+PointCount-1)->Y);
+
+	while(--PointCount){
+		X = Points->X;
+		Y = Points->Y;
+		Points++;
+		lcd_drawLine(pDrawProp, X, Y, Points->X, Points->Y);
+	}
+}
+
+/*
+ *  円塗りつぶし描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x0: X position
+ *  param3  y0: Y position
+ *  param4  Radius: Circle radius
+ */
+void
+lcd_fillCircle(LCD_DrawProp_t *pDrawProp, uint16_t Xpos, uint16_t Ypos, uint16_t Radius)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	uint32_t      color = pDrawProp->TextColor;
+	int32_t  D;     /* Decision Variable */
+	uint32_t  CurX; /* Current X Value */
+	uint32_t  CurY; /* Current Y Value */
+
+	D = 3 - (Radius << 1);
+
+	CurX = 0;
+	CurY = Radius;
+
+	while (CurX <= CurY){
+		if(CurY > 0){
+			lcd_drawFastHLine(hlcd, Xpos - CurY, Ypos + CurX, 2*CurY, color);
+			lcd_drawFastHLine(hlcd, Xpos - CurY, Ypos - CurX, 2*CurY, color);
+		}
+
+		if(CurX > 0){
+			lcd_drawFastHLine(hlcd, Xpos - CurX, Ypos - CurY, 2*CurX, color);
+			lcd_drawFastHLine(hlcd, Xpos - CurX, Ypos + CurY, 2*CurX, color);
+		}
+		if(D < 0){
+			D += (CurX << 2) + 6;
+		}
+		else{
+			D += ((CurX - CurY) << 2) + 10;
+			CurY--;
+		}
+		CurX++;
+	}
+
+	lcd_DrawCircle(pDrawProp, Xpos, Ypos, Radius);
+}
+
+/*
+ *  楕円塗りつぶし描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x0: X position
+ *  param3  y0: Y position
+ *  param4  XRadius: Ellipse X radius
+ *  param5  YRadius: Ellipse Y radius
+ */
+void
+lcd_fillEllipse(LCD_DrawProp_t *pDrawProp, int Xpos, int Ypos, int XRadius, int YRadius)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	int x = 0, y = -YRadius, err = 2-2*XRadius, e2;
+	float K = 0, rad1 = 0, rad2 = 0;
+
+	rad1 = XRadius;
+	rad2 = YRadius;
+
+	K = (float)(rad2/rad1);
+
+	do{
+		lcd_drawFastHLine(hlcd, (Xpos-(uint16_t)(x/K)), (Ypos+y), (2*(uint16_t)(x/K) + 1), pDrawProp->TextColor);
+		lcd_drawFastHLine(hlcd, (Xpos-(uint16_t)(x/K)), (Ypos-y), (2*(uint16_t)(x/K) + 1), pDrawProp->TextColor);
+
+		e2 = err;
+		if(e2 <= x){
+			err += ++x*2+1;
+			if (-y == x && e2 <= y)
+				e2 = 0;
+		}
+		if(e2 > y)
+			err += ++y*2+1;
+	}while (y <= 0);
+}
+
+/*
+ *  PLOY-LINE塗りつぶし描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  Points: Pointer to the points array
+ *  param3  PointCount: Number of points
+ */
+void
+lcd_fillPolygon(LCD_DrawProp_t *pDrawProp, pPoint Points, uint16_t PointCount)
+{
+	int16_t X = 0, Y = 0, X2 = 0, Y2 = 0, X_center = 0, Y_center = 0, X_first = 0, Y_first = 0, pixelX = 0, pixelY = 0, counter = 0;
+	uint16_t  IMAGE_LEFT = 0, IMAGE_RIGHT = 0, IMAGE_TOP = 0, IMAGE_BOTTOM = 0;
+
+	IMAGE_LEFT = IMAGE_RIGHT = Points->X;
+	IMAGE_TOP= IMAGE_BOTTOM = Points->Y;
+
+	for(counter = 1; counter < PointCount; counter++){
+		pixelX = POLY_X(counter);
+		if(pixelX < IMAGE_LEFT){
+			IMAGE_LEFT = pixelX;
+		}
+		if(pixelX > IMAGE_RIGHT){
+			IMAGE_RIGHT = pixelX;
+		}
+
+		pixelY = POLY_Y(counter);
+		if(pixelY < IMAGE_TOP){
+			IMAGE_TOP = pixelY;
+		}
+		if(pixelY > IMAGE_BOTTOM){
+			IMAGE_BOTTOM = pixelY;
+		}
+	}
+
+	if(PointCount < 2){
+		return;
+	}
+
+	X_center = (IMAGE_LEFT + IMAGE_RIGHT)/2;
+	Y_center = (IMAGE_BOTTOM + IMAGE_TOP)/2;
+
+	X_first = Points->X;
+	Y_first = Points->Y;
+
+	while(--PointCount){
+		X = Points->X;
+		Y = Points->Y;
+		Points++;
+		X2 = Points->X;
+		Y2 = Points->Y;
+
+		FillTriangle(pDrawProp, X, X2, X_center, Y, Y2, Y_center);
+		FillTriangle(pDrawProp, X, X_center, X2, Y, Y_center, Y2);
+		FillTriangle(pDrawProp, X_center, X2, X, Y_center, Y2, Y);
+	}
+
+	FillTriangle(pDrawProp, X_first, X2, X_center, Y_first, Y2, Y_center);
+	FillTriangle(pDrawProp, X_first, X_center, X2, Y_first, Y_center, Y2);
+	FillTriangle(pDrawProp, X_center, X2, X_first, Y_center, Y2, Y_first);
+}
+
+/*******************************************************************************
+                       LTDC, DMA2D and DSI BSP Routines
+*******************************************************************************/
+
+/*
+ *  トライアングルフィル
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x1: 点1 X座標始点
+ *  param3  y1: 点1 Y座標始点
+ *  param4  x2: 点2 X座標始点
+ *  param5  y2: 点2 Y座標始点
+ *  param6  x3: 点3 X座標始点
+ *  param7  y3: 点3 Y座標始点
+ */
+static void
+FillTriangle(LCD_DrawProp_t *pDrawProp, uint16_t x1, uint16_t x2, uint16_t x3, uint16_t y1, uint16_t y2, uint16_t y3)
+{
+	int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0,
+	yinc1 = 0, yinc2 = 0, den = 0, num = 0, numadd = 0, numpixels = 0,
+	curpixel = 0;
+
+	deltax = ABS(x2 - x1);        /* The difference between the x's */
+	deltay = ABS(y2 - y1);        /* The difference between the y's */
+	x = x1;                       /* Start x off at the first pixel */
+	y = y1;                       /* Start y off at the first pixel */
+
+	if(x2 >= x1){				/* The x-values are increasing */
+		xinc1 = 1;
+		xinc2 = 1;
+	}
+	else{						/* The x-values are decreasing */
+		xinc1 = -1;
+		xinc2 = -1;
+	}
+
+	if(y2 >= y1){				/* The y-values are increasing */
+		yinc1 = 1;
+		yinc2 = 1;
+	}
+	else{						/* The y-values are decreasing */
+		yinc1 = -1;
+		yinc2 = -1;
+	}
+
+	if(deltax >= deltay){		/* There is at least one x-value for every y-value */
+		xinc1 = 0;                  /* Don't change the x when numerator >= denominator */
+		yinc2 = 0;                  /* Don't change the y for every iteration */
+		den = deltax;
+		num = deltax / 2;
+		numadd = deltay;
+		numpixels = deltax;         /* There are more x-values than y-values */
+	}
+	else{						/* There is at least one y-value for every x-value */
+		xinc2 = 0;                  /* Don't change the x for every iteration */
+		yinc1 = 0;                  /* Don't change the y when numerator >= denominator */
+		den = deltay;
+		num = deltay / 2;
+		numadd = deltax;
+		numpixels = deltay;         /* There are more y-values than x-values */
+	}
+
+	for(curpixel = 0; curpixel <= numpixels; curpixel++){
+		lcd_drawLine(pDrawProp, x, y, x3, y3);
+
+		num += numadd;              /* Increase the numerator by the top of the fraction */
+		if(num >= den){				/* Check if numerator >= denominator */
+			num -= den;				/* Calculate the new numerator value */
+			x += xinc1;               /* Change the x as appropriate */
+			y += yinc1;               /* Change the y as appropriate */
+		}
+		x += xinc2;                 /* Change the x as appropriate */
+		y += yinc2;                 /* Change the y as appropriate */
+	}
+}
+
+/*
+ *  バッファフィル
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  pDst:バッファ先頭ポインタ
+ *  param3  xSize: バッファ幅
+ *  param3  ySize: バッファ高さ
+ *  param4  OffLine: 出力オフセット
+ *  param5  ColorIndex: フィルカラー
+ */
+static
+void LL_FillBuffer(uint32_t LayerIndex, void *pDst, uint32_t xSize, uint32_t ySize, uint32_t OffLine, uint32_t ColorIndex)
+{
+	/* Register to memory mode with ARGB8888 as color Mode */
+	hdma2d_discovery.Init.Mode         = DMA2D_R2M;
+	hdma2d_discovery.Init.ColorMode    = CM_ARGB8888;
+	hdma2d_discovery.Init.OutputOffset = OffLine;
+
+	hdma2d_discovery.base = TADR_DMA2D_BASE;
+
+	/* DMA2D Initialization */
+	if(dma2d_init(&hdma2d_discovery) == E_OK){
+		if(dma2d_configlayer(&hdma2d_discovery, LayerIndex) == E_OK){
+			if(dma2d_start(&hdma2d_discovery, ColorIndex, (uint32_t)pDst, xSize, ySize) == E_OK){
+				/* Polling For DMA transfer */
+				dma2d_waittransfar(&hdma2d_discovery, 10);
+			}
+		}
+	}
+}
+
+/**
+  * @brief  Converts a line to an ARGB8888 pixel format.
+  * @param  pSrc: Pointer to source buffer
+  * @param  pDst: Output color
+  * @param  xSize: Buffer width
+  * @param  ColorMode: Input color mode
+  */
+static
+void LL_ConvertLineToARGB8888(void *pSrc, void *pDst, uint32_t xSize, uint32_t ColorMode)
+{
+	/* Configure the DMA2D Mode, Color Mode and output offset */
+	hdma2d_discovery.Init.Mode         = DMA2D_M2M_PFC;
+	hdma2d_discovery.Init.ColorMode    = CM_ARGB8888;
+	hdma2d_discovery.Init.OutputOffset = 0;
+
+	/* Foreground Configuration */
+	hdma2d_discovery.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
+	hdma2d_discovery.LayerCfg[1].InputAlpha = 0xFF;
+	hdma2d_discovery.LayerCfg[1].InputColorMode = ColorMode;
+	hdma2d_discovery.LayerCfg[1].InputOffset = 0;
+
+	hdma2d_discovery.base = TADR_DMA2D_BASE;
+
+	/* DMA2D Initialization */
+	if(dma2d_init(&hdma2d_discovery) == E_OK){
+		if(dma2d_configlayer(&hdma2d_discovery, 1) == E_OK){
+			if(dma2d_start(&hdma2d_discovery, (uint32_t)pSrc, (uint32_t)pDst, xSize, 1) == E_OK){
+				/* Polling For DMA transfer */
+				dma2d_waittransfar(&hdma2d_discovery, 10);
+			}
+		}
+	}
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_otm8009a/stlcd_otm8009a.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_otm8009a/stlcd_otm8009a.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_otm8009a/stlcd_otm8009a.h	(revision 453)
@@ -0,0 +1,369 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/**
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+#ifndef _STLCD_OTM8009A_H_
+#define _STLCD_OTM8009A_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <sil.h>
+#include <target_syssvc.h>
+#include <string.h>
+
+#include "device.h"
+#include "i2c.h"
+#include "ltdc.h"
+#include "dsi.h"
+#include "dfsdm.h"
+
+
+/** @defgroup RCCEx_PLLSAI_DIVR RCCEx PLLSAI DIVR
+  * @{
+  */
+#define RCC_PLLSAIDIVR_2                ((uint32_t)0x00000000U)
+#define RCC_PLLSAIDIVR_4                RCC_DCKCFGR1_PLLSAIDIVR_0
+#define RCC_PLLSAIDIVR_8                RCC_DCKCFGR1_PLLSAIDIVR_1
+#define RCC_PLLSAIDIVR_16               RCC_DCKCFGR1_PLLSAIDIVR
+
+
+
+/**
+ *  @brief LCD_OrientationTypeDef
+ *  Possible values of Display Orientation
+ */
+#define OTM8009A_ORIENTATION_PORTRAIT    ((uint32_t)0x00) /* Portrait orientation choice of LCD screen  */
+#define OTM8009A_ORIENTATION_LANDSCAPE   ((uint32_t)0x01) /* Landscape orientation choice of LCD screen */
+
+/**
+ *  @brief  Possible values of
+ *  pixel data format (ie color coding) transmitted on DSI Data lane in DSI packets
+ */
+#define OTM8009A_FORMAT_RGB888    ((uint32_t)0x00) /* Pixel format chosen is RGB888 : 24 bpp */
+#define OTM8009A_FORMAT_RBG565    ((uint32_t)0x02) /* Pixel format chosen is RGB565 : 16 bpp */
+
+/**
+  * @brief  otm8009a_480x800 Size
+  */
+
+/* Width and Height in Portrait mode */
+#define OTM8009A_480X800_WIDTH             ((uint16_t)480)     /* LCD PIXEL WIDTH   */
+#define OTM8009A_480X800_HEIGHT            ((uint16_t)800)     /* LCD PIXEL HEIGHT  */
+
+/* Width and Height in Landscape mode */
+#define OTM8009A_800X480_WIDTH             ((uint16_t)800)     /* LCD PIXEL WIDTH   */
+#define OTM8009A_800X480_HEIGHT            ((uint16_t)480)     /* LCD PIXEL HEIGHT  */
+
+/**
+  * @brief  OTM8009A_480X800 Timing parameters for Portrait orientation mode
+  */
+#define OTM8009A_480X800_HSYNC             ((uint16_t)63)     /* Horizontal synchronization: This value is set to limit value mentionned 
+                                                                   in otm8009a spec to fit with USB functional clock configuration constraints */
+#define OTM8009A_480X800_HBP               ((uint16_t)120)     /* Horizontal back porch      */
+#define OTM8009A_480X800_HFP               ((uint16_t)120)     /* Horizontal front porch     */
+#define OTM8009A_480X800_VSYNC             ((uint16_t)12)      /* Vertical synchronization   */
+#define OTM8009A_480X800_VBP               ((uint16_t)12)      /* Vertical back porch        */
+#define OTM8009A_480X800_VFP               ((uint16_t)12)      /* Vertical front porch       */
+
+/**
+  * @brief  OTM8009A_800X480 Timing parameters for Landscape orientation mode
+  *         Same values as for Portrait mode in fact.
+  */
+#define OTM8009A_800X480_HSYNC             OTM8009A_480X800_HSYNC  /* Horizontal synchronization */
+#define OTM8009A_800X480_HBP               OTM8009A_480X800_HBP    /* Horizontal back porch      */
+#define OTM8009A_800X480_HFP               OTM8009A_480X800_HFP    /* Horizontal front porch     */
+#define OTM8009A_800X480_VSYNC             OTM8009A_480X800_VSYNC  /* Vertical synchronization   */
+#define OTM8009A_800X480_VBP               OTM8009A_480X800_VBP    /* Vertical back porch        */
+#define OTM8009A_800X480_VFP               OTM8009A_480X800_VFP    /* Vertical front porch       */
+
+
+/* List of OTM8009A used commands                                  */
+/* Detailed in OTM8009A Data Sheet 'DATA_SHEET_OTM8009A_V0 92.pdf' */
+/* Version of 14 June 2012                                         */
+#define OTM8009A_CMD_NOP                   0x00  /* NOP command      */
+#define OTM8009A_CMD_SWRESET               0x01  /* Sw reset command */
+#define OTM8009A_CMD_RDDMADCTL             0x0B  /* Read Display MADCTR command : read memory display access ctrl */
+#define OTM8009A_CMD_RDDCOLMOD             0x0C  /* Read Display pixel format */
+#define OTM8009A_CMD_SLPIN                 0x10  /* Sleep In command */
+#define OTM8009A_CMD_SLPOUT                0x11  /* Sleep Out command */
+#define OTM8009A_CMD_PTLON                 0x12  /* Partial mode On command */
+
+#define OTM8009A_CMD_DISPOFF               0x28  /* Display Off command */
+#define OTM8009A_CMD_DISPON                0x29  /* Display On command */
+
+#define OTM8009A_CMD_CASET                 0x2A  /* Column address set command */
+#define OTM8009A_CMD_PASET                 0x2B  /* Page address set command */
+
+#define OTM8009A_CMD_RAMWR                 0x2C  /* Memory (GRAM) write command */
+#define OTM8009A_CMD_RAMRD                 0x2E  /* Memory (GRAM) read command  */
+
+#define OTM8009A_CMD_PLTAR                 0x30  /* Partial area command (4 parameters) */
+
+#define OTM8009A_CMD_TEOFF                 0x34  /* Tearing Effect Line Off command : command with no parameter */
+
+#define OTM8009A_CMD_TEEON                 0x35  /* Tearing Effect Line On command : command with 1 parameter 'TELOM' */
+
+/* Parameter TELOM : Tearing Effect Line Output Mode : possible values */
+#define OTM8009A_TEEON_TELOM_VBLANKING_INFO_ONLY            0x00
+#define OTM8009A_TEEON_TELOM_VBLANKING_AND_HBLANKING_INFO   0x01
+
+#define OTM8009A_CMD_MADCTR                0x36  /* Memory Access write control command  */
+
+/* Possible used values of MADCTR */
+#define OTM8009A_MADCTR_MODE_PORTRAIT      0x00
+#define OTM8009A_MADCTR_MODE_LANDSCAPE     0x60  /* MY = 0, MX = 1, MV = 1, ML = 0, RGB = 0 */
+
+#define OTM8009A_CMD_IDMOFF                0x38  /* Idle mode Off command */
+#define OTM8009A_CMD_IDMON                 0x39  /* Idle mode On command  */
+
+#define OTM8009A_CMD_COLMOD                0x3A  /* Interface Pixel format command */
+
+/* Possible values of COLMOD parameter corresponding to used pixel formats */
+#define OTM8009A_COLMOD_RGB565             0x55
+#define OTM8009A_COLMOD_RGB888             0x77
+
+#define OTM8009A_CMD_RAMWRC                0x3C  /* Memory write continue command */
+#define OTM8009A_CMD_RAMRDC                0x3E  /* Memory read continue command  */
+
+#define OTM8009A_CMD_WRTESCN               0x44  /* Write Tearing Effect Scan line command */
+#define OTM8009A_CMD_RDSCNL                0x45  /* Read  Tearing Effect Scan line command */
+
+/* CABC Management : ie : Content Adaptive Back light Control in IC OTM8009a */
+#define OTM8009A_CMD_WRDISBV               0x51  /* Write Display Brightness command          */
+#define OTM8009A_CMD_WRCTRLD               0x53  /* Write CTRL Display command                */
+#define OTM8009A_CMD_WRCABC                0x55  /* Write Content Adaptive Brightness command */
+#define OTM8009A_CMD_WRCABCMB              0x5E  /* Write CABC Minimum Brightness command     */
+
+/**
+  * @brief  OTM8009A_480X800 frequency divider
+  */
+#define OTM8009A_480X800_FREQUENCY_DIVIDER  2   /* LCD Frequency divider      */
+
+/** 
+  * @brief  LCD FB_StartAddress
+  */
+#define LCD_FB_START_ADDRESS       ((uint32_t)0xC0000000)
+   
+/** @brief Maximum number of LTDC layers
+ */
+#define LTDC_MAX_LAYER_NUMBER             ((uint32_t) 2)
+
+/** @brief LTDC Background layer index
+ */
+#define LTDC_ACTIVE_LAYER_BACKGROUND      ((uint32_t) 0)
+
+/** @brief LTDC Foreground layer index
+ */
+#define LTDC_ACTIVE_LAYER_FOREGROUND      ((uint32_t) 1)
+
+/** @brief Number of LTDC layers
+ */
+#define LTDC_NB_OF_LAYERS                 ((uint32_t) 2)
+
+/** @brief LTDC Default used layer index
+ */
+#define LTDC_DEFAULT_ACTIVE_LAYER         LTDC_ACTIVE_LAYER_FOREGROUND
+
+/**
+  * @brief  LCD Display OTM8009A DSI Virtual Channel  ID
+  */
+#define LCD_OTM8009A_ID  ((uint32_t) 0)
+
+
+/** 
+  * @brief  LCD color  
+  */ 
+#define LCD_COLOR_BLUE          ((uint32_t)0xFF0000FF)
+#define LCD_COLOR_GREEN         ((uint32_t)0xFF00FF00)
+#define LCD_COLOR_RED           ((uint32_t)0xFFFF0000)
+#define LCD_COLOR_CYAN          ((uint32_t)0xFF00FFFF)
+#define LCD_COLOR_MAGENTA       ((uint32_t)0xFFFF00FF)
+#define LCD_COLOR_YELLOW        ((uint32_t)0xFFFFFF00)
+#define LCD_COLOR_LIGHTBLUE     ((uint32_t)0xFF8080FF)
+#define LCD_COLOR_LIGHTGREEN    ((uint32_t)0xFF80FF80)
+#define LCD_COLOR_LIGHTRED      ((uint32_t)0xFFFF8080)
+#define LCD_COLOR_LIGHTCYAN     ((uint32_t)0xFF80FFFF)
+#define LCD_COLOR_LIGHTMAGENTA  ((uint32_t)0xFFFF80FF)
+#define LCD_COLOR_LIGHTYELLOW   ((uint32_t)0xFFFFFF80)
+#define LCD_COLOR_DARKBLUE      ((uint32_t)0xFF000080)
+#define LCD_COLOR_DARKGREEN     ((uint32_t)0xFF008000)
+#define LCD_COLOR_DARKRED       ((uint32_t)0xFF800000)
+#define LCD_COLOR_DARKCYAN      ((uint32_t)0xFF008080)
+#define LCD_COLOR_DARKMAGENTA   ((uint32_t)0xFF800080)
+#define LCD_COLOR_DARKYELLOW    ((uint32_t)0xFF808000)
+#define LCD_COLOR_WHITE         ((uint32_t)0xFFFFFFFF)
+#define LCD_COLOR_LIGHTGRAY     ((uint32_t)0xFFD3D3D3)
+#define LCD_COLOR_GRAY          ((uint32_t)0xFF808080)
+#define LCD_COLOR_DARKGRAY      ((uint32_t)0xFF404040)
+#define LCD_COLOR_BLACK         ((uint32_t)0xFF000000)
+#define LCD_COLOR_BROWN         ((uint32_t)0xFFA52A2A)
+#define LCD_COLOR_ORANGE        ((uint32_t)0xFFFFA500)
+#define LCD_COLOR_TRANSPARENT   ((uint32_t)0xFF000000)
+
+/**
+ *  @brief  Possible values of
+ *  pixel data format (ie color coding) transmitted on DSI Data lane in DSI packets
+ */
+
+#define LCD_DSI_PIXEL_DATA_FMT_RBG888  DSI_RGB888 /*!< DSI packet pixel format chosen is RGB888 : 24 bpp */
+#define LCD_DSI_PIXEL_DATA_FMT_RBG565  DSI_RGB565 /*!< DSI packet pixel format chosen is RGB565 : 16 bpp */
+
+/*
+ *  LCDハンドラ構造体定義
+ */
+typedef struct
+{
+	LTDC_Handle_t           *hltdc;		/* LTDCハンドラ */
+	DSI_Handle_t            *hdsi;		/* DSIハンドラ */
+	DSI_VideoConfig_t       dsivc;		/* DSI video configハンドラ */
+	uint32_t                layer;
+	uint16_t                _width;		/* 幅ピクセル数 */
+	uint16_t				_height;	/* 高さピクセル数 */
+} LCD_Handler_t;
+
+/**
+* @brief  LCD Drawing main properties
+*/
+typedef struct
+{
+	LCD_Handler_t           *hlcd;
+	uint32_t TextColor;		/* Specifies the color of text */
+	uint32_t BackColor;		/* Specifies the background color below the text */
+	void     *pFont;		/* Specifies the font used for the text */
+
+} LCD_DrawProp_t;
+
+/**
+  * @brief  LCD Drawing point (pixel) geometric definition
+  */
+typedef struct
+{
+  int16_t X; /*!< geometric X position of drawing */
+  int16_t Y; /*!< geometric Y position of drawing */
+
+} Point;
+
+/**
+  * @brief  Pointer on LCD Drawing point (pixel) geometric definition
+  */
+typedef Point * pPoint;
+
+/**
+ *  @brief LCD_OrientationTypeDef
+ *  Possible values of Display Orientation
+ */
+typedef enum
+{
+	LCD_ORIENTATION_PORTRAIT  = 0x00, /*!< Portrait orientation choice of LCD screen  */
+	LCD_ORIENTATION_LANDSCAPE = 0x01, /*!< Landscape orientation choice of LCD screen */
+	LCD_ORIENTATION_INVALID   = 0x02  /*!< Invalid orientation choice of LCD screen   */
+} LCD_OrientationTypeDef;
+
+
+extern ER lcd_init(LCD_Handler_t *hlcd, LCD_OrientationTypeDef orientation);
+extern ER lcd_reset(LCD_Handler_t *hlcd);
+
+extern ER lcd_layerdefaultinit(LCD_Handler_t *hlcd, LCD_DrawProp_t *pDrawProp, uint16_t LayerIndex, uint32_t FB_Address);
+extern void lcd_setlayervisible(LCD_Handler_t *hlcd, uint32_t LayerIndex, uint8_t State);
+extern void lcd_settransparency(LCD_Handler_t *hlcd, uint32_t LayerIndex, uint8_t Transparency);
+extern void lcd_setlayeraddress(LCD_Handler_t *hlcd, uint32_t LayerIndex, uint32_t Address);
+extern void lcd_setcolorkeying(LCD_Handler_t *hlcd, uint32_t LayerIndex, uint32_t RGBValue);
+extern void lcd_resetcolorkeying(LCD_Handler_t *hlcd, uint32_t LayerIndex);
+
+extern void lcd_setAddrWindow(LCD_Handler_t *hlcd, uint16_t LayerIndex, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
+extern void lcd_clear(LCD_Handler_t *hlcd, uint32_t Color);
+extern uint32_t lcd_readPixel(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos);
+extern void lcd_drawPixel(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint32_t RGB_Code);
+extern void lcd_drawFastHLine(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint16_t Length, uint32_t color);
+extern void lcd_drawFastVLine(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint16_t Length, uint32_t color);
+extern void lcd_drawBitmap(LCD_Handler_t *hlcd, uint32_t Xpos, uint32_t Ypos, uint8_t *pbmp);
+extern void lcd_displayOn(LCD_Handler_t *hlcd);
+extern void lcd_displayOff(LCD_Handler_t *hlcd);
+extern void lcd_setbrightness(LCD_Handler_t *hlcd, uint8_t BrightnessValue);
+extern void lcd_fillRect(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint16_t Width, uint16_t Height, uint32_t color);
+
+extern void lcd_drawLine(LCD_DrawProp_t *pDrawProp, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
+extern void lcd_drawRect(LCD_DrawProp_t *pDrawProp, uint16_t Xpos, uint16_t Ypos, uint16_t Width, uint16_t Height);
+extern void lcd_DrawCircle(LCD_DrawProp_t *pDrawProp, uint16_t Xpos, uint16_t Ypos, uint16_t Radius);
+extern void lcd_DrawEllipse(LCD_DrawProp_t *pDrawProp, int Xpos, int Ypos, int XRadius, int YRadius);
+extern void lcd_drawPolygon(LCD_DrawProp_t *pDrawProp, pPoint Points, uint16_t PointCount);
+extern void lcd_fillCircle(LCD_DrawProp_t *pDrawProp, uint16_t Xpos, uint16_t Ypos, uint16_t Radius);
+extern void lcd_fillEllipse(LCD_DrawProp_t *pDrawProp, int Xpos, int Ypos, int XRadius, int YRadius);
+extern void lcd_fillPolygon(LCD_DrawProp_t *pDrawProp, pPoint Points, uint16_t PointCount);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _STLCD_OTM8009A_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_rk043fn48h/Makefile.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_rk043fn48h/Makefile.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_rk043fn48h/Makefile.config	(revision 453)
@@ -0,0 +1,55 @@
+#
+#   TOPPERS/ASP/FMP Kernel
+#       Toyohashi Open Platform for Embedded Real-Time Systems/
+#       Advanced Standard Profile Kernel
+#
+#   Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                               Toyohashi Univ. of Technology, JAPAN
+#   Copyright (C) 2003-2008 by Ryosuke Takeuchi
+#                Platform Development Center RICOH COMPANY,LTD. JAPAN
+#   Copyright (C) 2015-2018 by TOPPERS PROJECT Educational Working Group.
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+ 
+#
+#  Makefile のプロセッサ依存 (rk043fn48h用)
+#
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/gdic/stlcd_rk043fn48h
+
+#
+#  USB DEVICE(GDIC)に関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR):$(SRCDIR)/gdic/stlcd_rk043fn48h
+SYSSVC_COBJS := $(SYSSVC_COBJS) stlcd_rk043fn48h.o
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_rk043fn48h/glcd_core.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_rk043fn48h/glcd_core.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_rk043fn48h/glcd_core.h	(revision 453)
@@ -0,0 +1,45 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+#ifndef _LCD_CORE_H_
+#define _LCD_CORE_H_
+
+#include "stlcd_rk043fn48h.h"
+
+#endif /* _LCD_CORE_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_rk043fn48h/stlcd_rk043fn48h.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_rk043fn48h/stlcd_rk043fn48h.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_rk043fn48h/stlcd_rk043fn48h.c	(revision 453)
@@ -0,0 +1,982 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/**
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+#include "stlcd_rk043fn48h.h"
+#include <sil.h>
+#include <target_syssvc.h>
+
+#define sil_orw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) | (b))
+#define sil_andw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) & ~(b))
+#define sil_modw_mem(a, b, c)	sil_wrw_mem((a), (sil_rew_mem(a) & (~b)) | (c))
+
+#define POLY_X(Z)              ((int32_t)((Points + Z)->X))
+#define POLY_Y(Z)              ((int32_t)((Points + Z)->Y))
+#define ABS(X)                 ((X) > 0 ? (X) : -(X))
+
+#ifndef ENABLE
+#define ENABLE                 1
+#endif
+
+static LTDC_Handle_t  hLtdcHandler;
+static DMA2D_Handle_t hDma2dHandler;
+
+static void FillTriangle(LCD_DrawProp_t *pDrawProp, uint16_t x1, uint16_t x2, uint16_t x3, uint16_t y1, uint16_t y2, uint16_t y3);
+static void LL_FillBuffer(LCD_Handler_t *hlcd, void *pDst, uint32_t xSize, uint32_t ySize, uint32_t OffLine, uint32_t ColorIndex);
+static void LL_ConvertLineToARGB8888(void * pSrc, void *pDst, uint32_t xSize, uint32_t ColorMode);
+
+/*
+ *  LTDC/RK043FN48Hスクリーンの初期化関数
+ */
+ER
+lcd_init(LCD_Handler_t *hlcd, LCD_OrientationTypeDef orientation)
+{
+	/* The RK043FN48H LCD 480x272 is selected */
+	/* Timing Configuration */
+	hLtdcHandler.Init.HorizontalSync = (RK043FN48H_HSYNC - 1);
+	hLtdcHandler.Init.VerticalSync = (RK043FN48H_VSYNC - 1);
+	hLtdcHandler.Init.AccumulatedHBP = (RK043FN48H_HSYNC + RK043FN48H_HBP - 1);
+	hLtdcHandler.Init.AccumulatedVBP = (RK043FN48H_VSYNC + RK043FN48H_VBP - 1);
+	hLtdcHandler.Init.AccumulatedActiveH = (RK043FN48H_HEIGHT + RK043FN48H_VSYNC + RK043FN48H_VBP - 1);
+	hLtdcHandler.Init.AccumulatedActiveW = (RK043FN48H_WIDTH + RK043FN48H_HSYNC + RK043FN48H_HBP - 1);
+	hLtdcHandler.Init.TotalHeigh = (RK043FN48H_HEIGHT + RK043FN48H_VSYNC + RK043FN48H_VBP + RK043FN48H_VFP - 1);
+	hLtdcHandler.Init.TotalWidth = (RK043FN48H_WIDTH + RK043FN48H_HSYNC + RK043FN48H_HBP + RK043FN48H_HFP - 1);
+	hLtdcHandler.Init.pllsain = 192;
+	hLtdcHandler.Init.pllsair = 5;
+	hLtdcHandler.Init.saidivr = RCC_DCKCFGR1_PLLSAIDIVR_0;	/* DIV 4 */
+
+	/* Initialize the LCD pixel width and pixel height */
+	hLtdcHandler.LayerCfg[0].ImageWidth  = RK043FN48H_WIDTH;
+	hLtdcHandler.LayerCfg[0].ImageHeight = RK043FN48H_HEIGHT;
+#if MAX_LAYER_NUMBER >= 2
+	hLtdcHandler.LayerCfg[1].ImageWidth  = RK043FN48H_WIDTH;
+	hLtdcHandler.LayerCfg[1].ImageHeight = RK043FN48H_HEIGHT;
+#endif
+
+	/* Background value */
+	hLtdcHandler.Init.Backcolor.Blue = 0;
+	hLtdcHandler.Init.Backcolor.Green = 0;
+	hLtdcHandler.Init.Backcolor.Red = 0;
+
+	/* Polarity */
+	hLtdcHandler.Init.HSPolarity = LTDC_HSPOLARITY_AL;
+	hLtdcHandler.Init.VSPolarity = LTDC_VSPOLARITY_AL; 
+	hLtdcHandler.Init.DEPolarity = LTDC_DEPOLARITY_AL;  
+	hLtdcHandler.Init.PCPolarity = LTDC_PCPOLARITY_IPC;
+	hLtdcHandler.base = TADR_LTDC_BASE;
+	hlcd->_width  = RK043FN48H_WIDTH;
+	hlcd->_height = RK043FN48H_HEIGHT;
+	ltdc_init(&hLtdcHandler);
+	hlcd->hltdc = &hLtdcHandler;
+	return E_OK;
+}
+
+/*
+ *  LTDC/RK043FN48Hスクリーンレイヤ初期化関数
+ */
+ER
+lcd_layerdefaultinit(LCD_Handler_t *hlcd, LCD_DrawProp_t *pDrawProp, uint16_t LayerIndex, uint32_t FB_Address)
+{
+	LTDC_LayerCfg_t  layer_cfg;
+
+	if(LayerIndex >= MAX_LAYER_NUMBER)
+		return E_PAR;
+	/* Layer Init */
+	layer_cfg.WindowX0 = 0;
+	layer_cfg.WindowX1 = hlcd->hltdc->LayerCfg[LayerIndex].ImageWidth;
+	layer_cfg.WindowY0 = 0;
+	layer_cfg.WindowY1 = hlcd->hltdc->LayerCfg[LayerIndex].ImageHeight;
+	layer_cfg.PixelFormat = LTDC_PIXEL_FORMAT_ARGB8888;
+	layer_cfg.FBStartAdress = FB_Address;
+	layer_cfg.Alpha = 255;
+	layer_cfg.Alpha0 = 0;
+	layer_cfg.Backcolor.Blue = 0;
+	layer_cfg.Backcolor.Green = 0;
+	layer_cfg.Backcolor.Red = 0;
+	layer_cfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA;
+	layer_cfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA;
+	layer_cfg.ImageWidth = hlcd->hltdc->LayerCfg[LayerIndex].ImageWidth;
+	layer_cfg.ImageHeight = hlcd->hltdc->LayerCfg[LayerIndex].ImageHeight;
+
+	ltdc_configlayer(&hLtdcHandler, &layer_cfg, LayerIndex);
+
+	hlcd->layer = LayerIndex;
+	pDrawProp[LayerIndex].BackColor = LCD_COLOR_WHITE;
+	pDrawProp[LayerIndex].TextColor = LCD_COLOR_BLACK;
+	pDrawProp[LayerIndex].hlcd      = hlcd;
+	return E_OK;
+}
+
+/*
+ *  LTDC/RK043FN48HスクリーンRGB565レイヤ初期化関数
+ */
+ER
+lcd_layerRgb565init(LCD_Handler_t *hlcd, LCD_DrawProp_t *pDrawProp, uint16_t LayerIndex, uint32_t FB_Address)
+{
+	LTDC_LayerCfg_t  layer_cfg;
+
+	if(LayerIndex >= MAX_LAYER_NUMBER)
+		return E_PAR;
+	/* Layer Init */
+	layer_cfg.WindowX0 = 0;
+	layer_cfg.WindowX1 = hlcd->hltdc->LayerCfg[LayerIndex].ImageWidth;
+	layer_cfg.WindowY0 = 0;
+	layer_cfg.WindowY1 = hlcd->hltdc->LayerCfg[LayerIndex].ImageHeight;
+	layer_cfg.PixelFormat = LTDC_PIXEL_FORMAT_RGB565;
+	layer_cfg.FBStartAdress = FB_Address;
+	layer_cfg.Alpha = 255;
+	layer_cfg.Alpha0 = 0;
+	layer_cfg.Backcolor.Blue = 0;
+	layer_cfg.Backcolor.Green = 0;
+	layer_cfg.Backcolor.Red = 0;
+	layer_cfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA;
+	layer_cfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA;
+	layer_cfg.ImageWidth = hlcd->hltdc->LayerCfg[LayerIndex].ImageWidth;
+	layer_cfg.ImageHeight = hlcd->hltdc->LayerCfg[LayerIndex].ImageHeight;
+
+	ltdc_configlayer(&hLtdcHandler, &layer_cfg, LayerIndex);
+
+	hlcd->layer = LayerIndex;
+	pDrawProp[LayerIndex].BackColor = LCD_COLOR_WHITE;
+	pDrawProp[LayerIndex].TextColor = LCD_COLOR_BLACK;
+	pDrawProp[LayerIndex].hlcd      = hlcd;
+	return E_OK;
+}
+
+/*
+ *  LTDC/RK043FN48Hスクリーンレイヤ表示設定関数
+ */
+void
+lcd_setlayervisible(LCD_Handler_t *hlcd, uint32_t LayerIndex, uint8_t State)
+{
+	uint32_t layer_base = ((uint32_t)TADR_LTDC_BASE + 0x84 + (0x80 * LayerIndex));
+	if(State == ENABLE){
+		sil_orw_mem((uint32_t *)(layer_base+TOFF_LTDCW_CR), LTDC_CR_LEN);
+	}
+	else{
+		sil_andw_mem((uint32_t *)(layer_base+TOFF_LTDCW_CR), LTDC_CR_LEN);
+	}
+	sil_orw_mem((uint32_t *)(TADR_LTDC_BASE+TOFF_LTDC_SRCR), LTDC_SRCR_IMR);
+}
+
+/*
+ *  LTDC/RK043FN48Hスクリーンレイヤ透過設定関数
+*
+  * @brief  Configures the transparency.
+  * @param  LayerIndex: Layer foreground or background.
+  * @param  Transparency: Transparency
+  *           This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFF 
+  * @retval None
+  */
+void
+lcd_settransparency(LCD_Handler_t *hlcd, uint32_t LayerIndex, uint8_t Transparency)
+{
+	ltdc_setalpha(hlcd->hltdc, Transparency, LayerIndex);
+}
+
+/*
+ *  LTDC/RK043FN48HスクリーンレイヤRAMアドレス設定関数
+ */
+void
+lcd_setlayeraddress(LCD_Handler_t *hlcd, uint32_t LayerIndex, uint32_t Address)
+{
+	ltdc_setaddress(hlcd->hltdc, Address, LayerIndex);
+}
+
+/*
+ *  LTDC/RK043FN48H表示ウィンドウ設定
+ */
+void
+lcd_setAddrWindow(LCD_Handler_t *hlcd, uint16_t LayerIndex, uint16_t x0, uint16_t y0, uint16_t Width, uint16_t Height)
+{
+	/* Reconfigure the layer size */
+	ltdc_setwindowsize(hlcd->hltdc, Width, Height, LayerIndex);
+
+	/* Reconfigure the layer position */
+	ltdc_setwindowposition(hlcd->hltdc, x0, y0, LayerIndex);
+}
+
+/**
+  * @brief  Configures and sets the color keying.
+  * @param  LayerIndex: Layer foreground or background
+  * @param  RGBValue: Color reference
+  * @retval None
+  */
+void
+lcd_setcolorkeying(LCD_Handler_t *hlcd, uint32_t LayerIndex, uint32_t RGBValue)
+{
+	/* Configure and Enable the color Keying for LCD Layer */
+	ltdc_configcolorkeying(hlcd->hltdc, RGBValue, LayerIndex);
+	ltdc_enablecolorkeying(hlcd->hltdc, LayerIndex);
+}
+
+/**
+  * @brief  Disables the color keying.
+  * @param  LayerIndex: Layer foreground or background
+  * @retval None
+  */
+void
+lcd_resetcolorkeying(LCD_Handler_t *hlcd, uint32_t LayerIndex)
+{
+	/* Disable the color Keying for LCD Layer */
+	ltdc_disablecolorkeying(hlcd->hltdc, LayerIndex);
+}
+
+/*
+ *  LTDC/RK043FN48Hスクリーンクリア
+ */
+void
+lcd_clear(LCD_Handler_t *hlcd, uint32_t Color)
+{
+	LTDC_Handle_t *hltdc = hlcd->hltdc;
+	uint32_t layer = hlcd->layer;
+	uint32_t width, height;
+
+	width  = hltdc->LayerCfg[layer].ImageWidth;
+	height = hltdc->LayerCfg[layer].ImageHeight;
+ 	/* Clear the LCD */
+ 	LL_FillBuffer(hlcd, (uint32_t *)(hltdc->LayerCfg[layer].FBStartAdress), width, height, 0, Color);
+}
+
+/*
+ *  PIXEL読み出し
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: X position
+ *  param3  y: Y position
+ */
+uint32_t
+lcd_readPixel(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos)
+{
+	LTDC_Handle_t *hltdc = hlcd->hltdc;
+	uint32_t layer = hlcd->layer;
+	uint32_t ret = 0;
+	uint32_t width;
+
+	width = hltdc->LayerCfg[layer].ImageWidth;
+	if(hltdc->LayerCfg[layer].PixelFormat == LTDC_PIXEL_FORMAT_ARGB8888){
+		/* Read data value from SDRAM memory */
+		ret = *(volatile uint32_t*)(hltdc->LayerCfg[layer].FBStartAdress + (2*(Ypos * width + Xpos)));
+	}
+	else if(hltdc->LayerCfg[layer].PixelFormat == LTDC_PIXEL_FORMAT_RGB888){
+		/* Read data value from SDRAM memory */
+		ret = (*(volatile uint32_t*)(hltdc->LayerCfg[layer].FBStartAdress + (2*(Ypos * width + Xpos))) & 0x00FFFFFF);
+	}
+	else if((hltdc->LayerCfg[layer].PixelFormat == LTDC_PIXEL_FORMAT_RGB565)
+			|| (hltdc->LayerCfg[layer].PixelFormat == LTDC_PIXEL_FORMAT_ARGB4444)
+			|| (hltdc->LayerCfg[layer].PixelFormat == LTDC_PIXEL_FORMAT_AL88)){
+		/* Read data value from SDRAM memory */
+		ret = *(volatile uint16_t*)(hltdc->LayerCfg[layer].FBStartAdress + (2*(Ypos * width + Xpos)));
+	}
+	else{
+		/* Read data value from SDRAM memory */
+		ret = *(volatile uint8_t*)(hltdc->LayerCfg[layer].FBStartAdress + (2*(Ypos * width + Xpos)));
+	}
+	return ret;
+}
+
+/*
+ *  PIXEL描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: X position
+ *  param3  y: Y position
+ *  param4  color: color value
+ */
+void
+lcd_drawPixel(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint32_t RGB_Code)
+{
+	LTDC_Handle_t *hltdc = hlcd->hltdc;
+	uint32_t layer = hlcd->layer;
+
+	/* Write data value to all SDRAM memory */
+	if(hltdc->LayerCfg[layer].PixelFormat == LTDC_PIXEL_FORMAT_RGB565){ /* RGB565 format */
+		*(volatile uint16_t*)(hltdc->LayerCfg[layer].FBStartAdress + (2*(Ypos*hltdc->LayerCfg[layer].ImageWidth + Xpos))) = (uint16_t)RGB_Code;
+	}
+	else{	/* ARGB8888 format */
+		*(volatile uint32_t*)(hltdc->LayerCfg[layer].FBStartAdress + (4*(Ypos*hltdc->LayerCfg[layer].ImageWidth + Xpos))) = RGB_Code;
+	}
+}
+
+/*
+ *  垂直方向LINEの高速描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: start X position
+ *  param3  y: start Y position
+ *  param4  h: height
+ *  param5  color: color value
+ */
+void
+lcd_drawFastHLine(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint16_t Length, uint32_t color)
+{
+	LTDC_Handle_t *hltdc = hlcd->hltdc;
+	uint32_t layer = hlcd->layer;
+	uint32_t Xaddress = 0, width;
+
+	width = hltdc->LayerCfg[layer].ImageWidth;
+	/* Get the line address */
+	if(hltdc->LayerCfg[layer].PixelFormat == LTDC_PIXEL_FORMAT_RGB565){	/* RGB565 format */
+		Xaddress = (hltdc->LayerCfg[layer].FBStartAdress) + 2*(width * Ypos + Xpos);
+	}
+	else{	/* ARGB8888 format */
+		Xaddress = (hltdc->LayerCfg[layer].FBStartAdress) + 4*(width * Ypos + Xpos);
+	}
+	/* Write line */
+	LL_FillBuffer(hlcd, (uint32_t *)Xaddress, Length, 1, 0, color);
+}
+
+/*
+ *  水平方向LINEの高速描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: start X position
+ *  param3  y: start Y position
+ *  param4  w: width
+ *  param5  color: color value
+ */
+void
+lcd_drawFastVLine(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint16_t Length, uint32_t color)
+{
+	LTDC_Handle_t *hltdc = hlcd->hltdc;
+	uint32_t layer = hlcd->layer;
+	uint32_t  Xaddress = 0, width;
+
+	width = hltdc->LayerCfg[layer].ImageWidth;
+	/* Get the line address */
+	if(hltdc->LayerCfg[layer].PixelFormat == LTDC_PIXEL_FORMAT_RGB565){	/* RGB565 format */
+		Xaddress = (hltdc->LayerCfg[layer].FBStartAdress) + 2*(width * Ypos + Xpos);
+	}
+	else{	/* ARGB8888 format */
+		Xaddress = (hltdc->LayerCfg[layer].FBStartAdress) + 4*(width*Ypos + Xpos);
+	}
+
+	/* Write line */
+	LL_FillBuffer(hlcd, (uint32_t *)Xaddress, 1, Length, (width - 1), color);
+}
+
+/*
+ *  BITMAP描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x0: Bmp X position in the LCD
+ *  param3  y0: Bmp Y position in the LCD
+ *  param4  pbmp: Pointer to Bmp picture address in the internal Flash
+ */
+void
+lcd_drawBitmap(LCD_Handler_t *hlcd, uint32_t Xpos, uint32_t Ypos, uint8_t *pbmp)
+{
+	LTDC_Handle_t *hltdc = hlcd->hltdc;
+	uint32_t layer = hlcd->layer;
+	uint32_t index = 0, width = 0, height = 0, bit_pixel = 0;
+	uint32_t address, iwidth;
+	uint32_t input_color_mode = 0;
+
+	iwidth = hltdc->LayerCfg[hlcd->layer].ImageWidth;
+	/* Get bitmap data address offset */
+	index = *(volatile uint16_t *) (pbmp + 10);
+	index |= (*(volatile uint16_t *) (pbmp + 12)) << 16;
+
+	/* Read bitmap width */
+	width = *(volatile uint16_t *) (pbmp + 18);
+	width |= (*(volatile uint16_t *) (pbmp + 20)) << 16;
+
+	/* Read bitmap height */
+	height = *(volatile uint16_t *) (pbmp + 22);
+	height |= (*(volatile uint16_t *) (pbmp + 24)) << 16; 
+
+	/* Read bit/pixel */
+	bit_pixel = *(uint16_t *) (pbmp + 28);
+
+	/* Set the address */
+	address = hltdc->LayerCfg[layer].FBStartAdress + (((hltdc->LayerCfg[layer].ImageWidth*Ypos) + Xpos)*(4));
+
+	/* Get the layer pixel format */
+	if((bit_pixel/8) == 4){
+		input_color_mode = CM_ARGB8888;
+	}
+	else if ((bit_pixel/8) == 2){
+		input_color_mode = CM_RGB565;
+	}
+	else{
+		input_color_mode = CM_RGB888;
+	}
+
+	/* Bypass the bitmap header */
+	pbmp += (index + (width * (height - 1) * (bit_pixel/8)));  
+
+	/* Convert picture to ARGB8888 pixel format */
+	for(index=0; index < height; index++){
+		/* Pixel format conversion */
+		LL_ConvertLineToARGB8888((uint32_t *)pbmp, (uint32_t *)address, width, input_color_mode);
+
+		/* Increment the source and destination buffers */
+		address+=  (iwidth*4);
+		pbmp -= width*(bit_pixel/8);
+	}
+}
+
+/*
+ *  RECTANGLE塗りつぶし描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: left X position
+ *  param3  y: top Y position
+ *  param4  w: width
+ *  param5  h: height
+ *  param6  color: color value
+ */
+void
+lcd_fillRect(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint16_t Width, uint16_t Height, uint32_t color)
+{
+	LTDC_Handle_t *hltdc = hlcd->hltdc;
+	uint32_t  x_address = 0;
+	uint32_t width;
+
+	width = hltdc->LayerCfg[hlcd->layer].ImageWidth;
+
+	/* Get the rectangle start address */
+	if(hltdc->LayerCfg[hlcd->layer].PixelFormat == LTDC_PIXEL_FORMAT_RGB565){	/* RGB565 format */
+		x_address = (hltdc->LayerCfg[hlcd->layer].FBStartAdress) + 2*(width * Ypos + Xpos);
+	}
+	else{	/* ARGB8888 format */
+		x_address = (hltdc->LayerCfg[hlcd->layer].FBStartAdress) + 4*(width * Ypos + Xpos);
+	}
+	/* Fill the rectangle */
+	LL_FillBuffer(hlcd, (uint32_t *)x_address, Width, Height, (width - Width), color);
+}
+
+
+/*
+ *  線描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x1: Point 1 X position
+ *  param3  y1: Point 1 Y position
+ *  param4  x2: Point 2 X position
+ *  param5  y2: Point 2 Y position
+ */
+void
+lcd_drawLine(LCD_DrawProp_t *pDrawProp, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0, 
+	yinc1 = 0, yinc2 = 0, den = 0, num = 0, num_add = 0, num_pixels = 0, 
+	curpixel = 0;
+
+	deltax = ABS(x2 - x1);        /* The difference between the x's */
+	deltay = ABS(y2 - y1);        /* The difference between the y's */
+	x = x1;                       /* Start x off at the first pixel */
+	y = y1;                       /* Start y off at the first pixel */
+
+	if(x2 >= x1){				/* The x-values are increasing */
+		xinc1 = 1;
+		xinc2 = 1;
+	}
+	else{						/* The x-values are decreasing */
+		xinc1 = -1;
+		xinc2 = -1;
+	}
+
+	if(y2 >= y1){				/* The y-values are increasing */
+		yinc1 = 1;
+		yinc2 = 1;
+	}
+	else{						/* The y-values are decreasing */
+		yinc1 = -1;
+		yinc2 = -1;
+	}
+
+	if(deltax >= deltay){		/* There is at least one x-value for every y-value */
+		xinc1 = 0;				/* Don't change the x when numerator >= denominator */
+		yinc2 = 0;				/* Don't change the y for every iteration */
+		den = deltax;
+		num = deltax / 2;
+		num_add = deltay;
+		num_pixels = deltax;	/* There are more x-values than y-values */
+	}
+	else{						/* There is at least one y-value for every x-value */
+		xinc2 = 0;				/* Don't change the x for every iteration */
+		yinc1 = 0;				/* Don't change the y when numerator >= denominator */
+		den = deltay;
+		num = deltay / 2;
+		num_add = deltax;
+		num_pixels = deltay;	/* There are more y-values than x-values */
+	}
+
+	for(curpixel = 0; curpixel <= num_pixels; curpixel++){
+		lcd_drawPixel(hlcd, x, y, pDrawProp[hlcd->layer].TextColor);   /* Draw the current pixel */
+		num += num_add;			/* Increase the numerator by the top of the fraction */
+		if(num >= den){			/* Check if numerator >= denominator */
+			num -= den;			/* Calculate the new numerator value */
+			x += xinc1;			/* Change the x as appropriate */
+			y += yinc1;			/* Change the y as appropriate */
+		}
+		x += xinc2;				/* Change the x as appropriate */
+		y += yinc2;				/* Change the y as appropriate */
+	}
+}
+
+/*
+ *  RECTANGLE描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x: left X position
+ *  param3  y: top Y position
+ *  param4  w: width
+ *  param5  h: height
+ */
+void
+lcd_drawRect(LCD_DrawProp_t *pDrawProp, uint16_t Xpos, uint16_t Ypos, uint16_t Width, uint16_t Height)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	uint32_t      color = pDrawProp[hlcd->layer].TextColor;
+	/* Draw horizontal lines */
+	lcd_drawFastHLine(hlcd, Xpos, Ypos, Width, color);
+	lcd_drawFastHLine(hlcd, Xpos, (Ypos+ Height), Width, color);
+
+	/* Draw vertical lines */
+	lcd_drawFastVLine(hlcd, Xpos, Ypos, Height, color);
+	lcd_drawFastVLine(hlcd, (Xpos + Width), Ypos, Height, color);
+}
+
+/*
+ *  円描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x0: X position
+ *  param3  y0: Y position
+ *  param4  Radius: Circle radius
+ */
+void
+lcd_DrawCircle(LCD_DrawProp_t *pDrawProp, uint16_t Xpos, uint16_t Ypos, uint16_t Radius)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	uint32_t      color = pDrawProp[hlcd->layer].TextColor;
+	int32_t   decision;    /* Decision Variable */ 
+	uint32_t  current_x;   /* Current X Value */
+	uint32_t  current_y;   /* Current Y Value */
+
+	decision = 3 - (Radius << 1);
+	current_x = 0;
+	current_y = Radius;
+
+	while (current_x <= current_y){
+		lcd_drawPixel(hlcd, (Xpos + current_x), (Ypos - current_y), color);
+		lcd_drawPixel(hlcd, (Xpos - current_x), (Ypos - current_y), color);
+		lcd_drawPixel(hlcd, (Xpos + current_y), (Ypos - current_x), color);
+		lcd_drawPixel(hlcd, (Xpos - current_y), (Ypos - current_x), color);
+		lcd_drawPixel(hlcd, (Xpos + current_x), (Ypos + current_y), color);
+		lcd_drawPixel(hlcd, (Xpos - current_x), (Ypos + current_y), color);
+		lcd_drawPixel(hlcd, (Xpos + current_y), (Ypos + current_x), color);
+		lcd_drawPixel(hlcd, (Xpos - current_y), (Ypos + current_x), color);
+
+		if(decision < 0){
+			decision += (current_x << 2) + 6;
+		}
+		else{
+			decision += ((current_x - current_y) << 2) + 10;
+			current_y--;
+		}
+		current_x++;
+	}
+}
+
+/*
+ *  楕円描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x0: X position
+ *  param3  y0: Y position
+ *  param4  XRadius: Ellipse X radius
+ *  param5  YRadius: Ellipse Y radius
+ */
+void
+lcd_DrawEllipse(LCD_DrawProp_t *pDrawProp, int Xpos, int Ypos, int XRadius, int YRadius)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	uint32_t      color = pDrawProp[hlcd->layer].TextColor;
+	int x = 0, y = -YRadius, err = 2-2*XRadius, e2;
+	float k = 0, rad1 = 0, rad2 = 0;
+
+	rad1 = XRadius;
+	rad2 = YRadius;
+	k = (float)(rad2/rad1);
+
+	do{
+		lcd_drawPixel(hlcd, (Xpos-(uint16_t)(x/k)), (Ypos+y), color);
+		lcd_drawPixel(hlcd, (Xpos+(uint16_t)(x/k)), (Ypos+y), color);
+		lcd_drawPixel(hlcd, (Xpos+(uint16_t)(x/k)), (Ypos-y), color);
+		lcd_drawPixel(hlcd, (Xpos-(uint16_t)(x/k)), (Ypos-y), color);
+
+		e2 = err;
+		if(e2 <= x){
+			err += ++x*2+1;
+			if(-y == x && e2 <= y)
+				e2 = 0;
+		}
+		if(e2 > y)
+			err += ++y*2+1;
+	}
+	while (y <= 0);
+}
+
+/*
+ *  PLOY-LINE描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  Points: Pointer to the points array
+ *  param3  PointCount: Number of points
+ */
+void
+lcd_drawPolygon(LCD_DrawProp_t *pDrawProp, pPoint Points, uint16_t PointCount)
+{
+	int16_t x = 0, y = 0;
+
+	if(PointCount < 2){
+		return;
+	}
+
+	lcd_drawLine(pDrawProp, Points->X, Points->Y, (Points+PointCount-1)->X, (Points+PointCount-1)->Y);
+	while(--PointCount){
+		x = Points->X;
+		y = Points->Y;
+		Points++;
+		lcd_drawLine(pDrawProp, x, y, Points->X, Points->Y);
+	}
+}
+
+/*
+ *  円塗りつぶし描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x0: X position
+ *  param3  y0: Y position
+ *  param4  Radius: Circle radius
+ */
+void
+lcd_fillCircle(LCD_DrawProp_t *pDrawProp, uint16_t Xpos, uint16_t Ypos, uint16_t Radius)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	uint32_t  color = pDrawProp->TextColor;
+	int32_t   decision;     /* Decision Variable */ 
+	uint32_t  current_x;   /* Current X Value */
+	uint32_t  current_y;   /* Current Y Value */
+
+	decision = 3 - (Radius << 1);
+	current_x = 0;
+	current_y = Radius;
+
+	while (current_x <= current_y){
+		if(current_y > 0){
+			lcd_drawFastHLine(hlcd, Xpos - current_y, Ypos + current_x, 2*current_y, color);
+			lcd_drawFastHLine(hlcd, Xpos - current_y, Ypos - current_x, 2*current_y, color);
+		}
+		if(current_x > 0){
+			lcd_drawFastHLine(hlcd, Xpos - current_x, Ypos - current_y, 2*current_x, color);
+			lcd_drawFastHLine(hlcd, Xpos - current_x, Ypos + current_y, 2*current_x, color);
+		}
+		if(decision < 0){
+			decision += (current_x << 2) + 6;
+		}
+		else{
+			decision += ((current_x - current_y) << 2) + 10;
+			current_y--;
+		}
+		current_x++;
+	}
+	lcd_DrawCircle(pDrawProp, Xpos, Ypos, Radius);
+}
+
+/*
+ *  楕円塗りつぶし描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x0: X position
+ *  param3  y0: Y position
+ *  param4  XRadius: Ellipse X radius
+ *  param5  YRadius: Ellipse Y radius
+ */
+void
+lcd_fillEllipse(LCD_DrawProp_t *pDrawProp, int Xpos, int Ypos, int XRadius, int YRadius)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	uint32_t      color = pDrawProp[hlcd->layer].TextColor;
+	int x = 0, y = -YRadius, err = 2-2*XRadius, e2;
+	float k = 0, rad1 = 0, rad2 = 0;
+
+	rad1 = XRadius;
+	rad2 = YRadius;
+	k = (float)(rad2/rad1);
+
+	do{
+		lcd_drawFastHLine(hlcd, (Xpos-(uint16_t)(x/k)), (Ypos+y), (2*(uint16_t)(x/k) + 1), color);
+		lcd_drawFastHLine(hlcd, (Xpos-(uint16_t)(x/k)), (Ypos-y), (2*(uint16_t)(x/k) + 1), color);
+
+		e2 = err;
+		if(e2 <= x){
+			err += ++x*2+1;
+			if(-y == x && e2 <= y)
+				e2 = 0;
+		}
+		if(e2 > y)
+			err += ++y*2+1;
+	}while(y <= 0);
+}
+
+/*
+ *  PLOY-LINE塗りつぶし描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  Points: Pointer to the points array
+ *  param3  PointCount: Number of points
+ */
+void
+lcd_fillPolygon(LCD_DrawProp_t *pDrawProp, pPoint Points, uint16_t PointCount)
+{
+	int16_t X = 0, Y = 0, X2 = 0, Y2 = 0, X_center = 0, Y_center = 0, X_first = 0, Y_first = 0, pixelX = 0, pixelY = 0, counter = 0;
+	uint16_t  image_left = 0, image_right = 0, image_top = 0, image_bottom = 0;
+
+	image_left = image_right = Points->X;
+	image_top= image_bottom = Points->Y;
+
+	for(counter = 1; counter < PointCount; counter++){
+		pixelX = POLY_X(counter);
+		if(pixelX < image_left){
+			image_left = pixelX;
+		}
+		if(pixelX > image_right){
+			image_right = pixelX;
+		}
+
+		pixelY = POLY_Y(counter);
+		if(pixelY < image_top){
+			image_top = pixelY;
+		}
+		if(pixelY > image_bottom){
+			image_bottom = pixelY;
+		}
+	}
+
+	if(PointCount < 2){
+		return;
+	}
+
+	X_center = (image_left + image_right)/2;
+	Y_center = (image_bottom + image_top)/2;
+	X_first = Points->X;
+	Y_first = Points->Y;
+
+	while(--PointCount){
+		X = Points->X;
+		Y = Points->Y;
+		Points++;
+		X2 = Points->X;
+		Y2 = Points->Y;
+
+		FillTriangle(pDrawProp, X, X2, X_center, Y, Y2, Y_center);
+		FillTriangle(pDrawProp, X, X_center, X2, Y, Y_center, Y2);
+		FillTriangle(pDrawProp, X_center, X2, X, Y_center, Y2, Y);
+	}
+
+	FillTriangle(pDrawProp, X_first, X2, X_center, Y_first, Y2, Y_center);
+	FillTriangle(pDrawProp, X_first, X_center, X2, Y_first, Y_center, Y2);
+	FillTriangle(pDrawProp, X_center, X2, X_first, Y_center, Y2, Y_first);
+}
+
+
+/*******************************************************************************
+                            Static Functions
+*******************************************************************************/
+
+/*
+ *  トライアングルフィル
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x1: 点1 X座標始点
+ *  param3  y1: 点1 Y座標始点
+ *  param4  x2: 点2 X座標始点
+ *  param5  y2: 点2 Y座標始点
+ *  param6  x3: 点3 X座標始点
+ *  param7  y3: 点3 Y座標始点
+ */
+static void
+FillTriangle(LCD_DrawProp_t *pDrawProp, uint16_t x1, uint16_t x2, uint16_t x3, uint16_t y1, uint16_t y2, uint16_t y3)
+{
+	int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0, 
+	yinc1 = 0, yinc2 = 0, den = 0, num = 0, num_add = 0, num_pixels = 0,
+	curpixel = 0;
+
+	deltax = ABS(x2 - x1);        /* The difference between the x's */
+	deltay = ABS(y2 - y1);        /* The difference between the y's */
+	x = x1;                       /* Start x off at the first pixel */
+	y = y1;                       /* Start y off at the first pixel */
+
+	if(x2 >= x1){			/* The x-values are increasing */
+		xinc1 = 1;
+		xinc2 = 1;
+	}
+	else{					/* The x-values are decreasing */
+		xinc1 = -1;
+		xinc2 = -1;
+	}
+
+	if(y2 >= y1){			/* The y-values are increasing */
+		yinc1 = 1;
+		yinc2 = 1;
+	}
+	else{					/* The y-values are decreasing */
+		yinc1 = -1;
+		yinc2 = -1;
+	}
+
+	if(deltax >= deltay){	/* There is at least one x-value for every y-value */
+		xinc1 = 0;			/* Don't change the x when numerator >= denominator */
+		yinc2 = 0;			/* Don't change the y for every iteration */
+		den = deltax;
+		num = deltax / 2;
+		num_add = deltay;
+		num_pixels = deltax;	/* There are more x-values than y-values */
+	}
+	else{					/* There is at least one y-value for every x-value */
+		xinc2 = 0;			/* Don't change the x for every iteration */
+		yinc1 = 0;			/* Don't change the y when numerator >= denominator */
+		den = deltay;
+		num = deltay / 2;
+		num_add = deltax;
+		num_pixels = deltay;	/* There are more y-values than x-values */
+	}
+
+	for(curpixel = 0; curpixel <= num_pixels; curpixel++){
+		lcd_drawLine(pDrawProp, x, y, x3, y3);
+		num += num_add;		/* Increase the numerator by the top of the fraction */
+		if(num >= den){		/* Check if numerator >= denominator */
+			num -= den;		/* Calculate the new numerator value */
+			x += xinc1;		/* Change the x as appropriate */
+			y += yinc1;		/* Change the y as appropriate */
+		}
+		x += xinc2;			/* Change the x as appropriate */
+		y += yinc2;			/* Change the y as appropriate */
+	}
+}
+
+/*
+ *  バッファフィル
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  pDst:バッファ先頭ポインタ
+ *  param3  xSize: バッファ幅
+ *  param3  ySize: バッファ高さ
+ *  param4  OffLine: 出力オフセット
+ *  param5  ColorIndex: フィルカラー
+ */
+static void
+LL_FillBuffer(LCD_Handler_t *hlcd, void *pDst, uint32_t xSize, uint32_t ySize, uint32_t OffLine, uint32_t ColorIndex) 
+{
+	LTDC_Handle_t *hltdc = hlcd->hltdc;
+
+	/* Register to memory mode with ARGB8888 as color Mode */ 
+	hDma2dHandler.Init.Mode         = DMA2D_R2M;
+	if(hltdc->LayerCfg[hlcd->layer].PixelFormat == LTDC_PIXEL_FORMAT_RGB565){	/* RGB565 format */ 
+		hDma2dHandler.Init.ColorMode    = DMA2D_RGB565;
+	}
+	else{	/* ARGB8888 format */
+		hDma2dHandler.Init.ColorMode    = DMA2D_ARGB8888;
+	}
+	hDma2dHandler.Init.OutputOffset = OffLine;
+
+	hDma2dHandler.base = (uint32_t)TADR_DMA2D_BASE;
+
+	/* DMA2D Initialization */
+	if(dma2d_init(&hDma2dHandler) == E_OK){
+		if(dma2d_configlayer(&hDma2dHandler, hlcd->layer) == E_OK){
+			if(dma2d_start(&hDma2dHandler, ColorIndex, (uint32_t)pDst, xSize, ySize) == E_OK){
+				/* Polling For DMA transfer */
+				dma2d_waittransfar(&hDma2dHandler, 10);
+			}
+		}
+	}
+}
+
+/**
+  * @brief  Converts a line to an ARGB8888 pixel format.
+  * @param  pSrc: Pointer to source buffer
+  * @param  pDst: Output color
+  * @param  xSize: Buffer width
+  * @param  ColorMode: Input color mode   
+  * @retval None
+  */
+static void
+LL_ConvertLineToARGB8888(void *pSrc, void *pDst, uint32_t xSize, uint32_t ColorMode)
+{
+	/* Configure the DMA2D Mode, Color Mode and output offset */
+	hDma2dHandler.Init.Mode         = DMA2D_M2M_PFC;
+	hDma2dHandler.Init.ColorMode    = DMA2D_ARGB8888;
+	hDma2dHandler.Init.OutputOffset = 0;
+
+	/* Foreground Configuration */
+	hDma2dHandler.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
+	hDma2dHandler.LayerCfg[1].InputAlpha = 0xFF;
+	hDma2dHandler.LayerCfg[1].InputColorMode = ColorMode;
+	hDma2dHandler.LayerCfg[1].InputOffset = 0;
+	hDma2dHandler.base = (uint32_t)TADR_DMA2D_BASE;
+
+	/* DMA2D Initialization */
+	if(dma2d_init(&hDma2dHandler) == E_OK){
+		if(dma2d_configlayer(&hDma2dHandler, 1) == E_OK){
+			if(dma2d_start(&hDma2dHandler, (uint32_t)pSrc, (uint32_t)pDst, xSize, 1) == E_OK){
+				/* Polling For DMA transfer */
+				dma2d_waittransfar(&hDma2dHandler, 10);
+			}
+		}
+	}
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_rk043fn48h/stlcd_rk043fn48h.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_rk043fn48h/stlcd_rk043fn48h.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_rk043fn48h/stlcd_rk043fn48h.h	(revision 453)
@@ -0,0 +1,235 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/**
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+#ifndef _STLCD_RK043FN48H_H_
+#define _STLCD_RK043FN48H_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif 
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#include "device.h"
+#include "ltdc.h"
+
+
+
+/* Include LCD component Driver */
+/* LCD RK043FN48H-CT672B 4,3" 480x272 pixels */
+/**
+  * @brief  RK043FN48H Size
+  */
+#define  RK043FN48H_WIDTH    ((uint16_t)480)          /* LCD PIXEL WIDTH            */
+#define  RK043FN48H_HEIGHT   ((uint16_t)272)          /* LCD PIXEL HEIGHT           */
+
+/**
+  * @brief  RK043FN48H Timing
+  */
+#define  RK043FN48H_HSYNC            ((uint16_t)41)   /* Horizontal synchronization */
+#define  RK043FN48H_HBP              ((uint16_t)13)   /* Horizontal back porch      */
+#define  RK043FN48H_HFP              ((uint16_t)32)   /* Horizontal front porch     */
+#define  RK043FN48H_VSYNC            ((uint16_t)10)   /* Vertical synchronization   */
+#define  RK043FN48H_VBP              ((uint16_t)2)    /* Vertical back porch        */
+#define  RK043FN48H_VFP              ((uint16_t)2)    /* Vertical front porch       */
+
+/**
+  * @brief  RK043FN48H frequency divider
+  */
+#define  RK043FN48H_FREQUENCY_DIVIDER    5            /* LCD Frequency divider      */
+
+#define MAX_LAYER_NUMBER       2
+
+#define LTDC_ACTIVE_LAYER	     ((uint32_t)1) /* Layer 1 */
+
+/**
+  * @brief  LCD FB_StartAddress
+  */
+#define LCD_FB_START_ADDRESS       ((uint32_t)0xC0000000)
+
+/**
+  * @brief  LCD color
+  */
+#define LCD_COLOR_BLUE          ((uint32_t)0xFF0000FF)
+#define LCD_COLOR_GREEN         ((uint32_t)0xFF00FF00)
+#define LCD_COLOR_RED           ((uint32_t)0xFFFF0000)
+#define LCD_COLOR_CYAN          ((uint32_t)0xFF00FFFF)
+#define LCD_COLOR_MAGENTA       ((uint32_t)0xFFFF00FF)
+#define LCD_COLOR_YELLOW        ((uint32_t)0xFFFFFF00)
+#define LCD_COLOR_LIGHTBLUE     ((uint32_t)0xFF8080FF)
+#define LCD_COLOR_LIGHTGREEN    ((uint32_t)0xFF80FF80)
+#define LCD_COLOR_LIGHTRED      ((uint32_t)0xFFFF8080)
+#define LCD_COLOR_LIGHTCYAN     ((uint32_t)0xFF80FFFF)
+#define LCD_COLOR_LIGHTMAGENTA  ((uint32_t)0xFFFF80FF)
+#define LCD_COLOR_LIGHTYELLOW   ((uint32_t)0xFFFFFF80)
+#define LCD_COLOR_DARKBLUE      ((uint32_t)0xFF000080)
+#define LCD_COLOR_DARKGREEN     ((uint32_t)0xFF008000)
+#define LCD_COLOR_DARKRED       ((uint32_t)0xFF800000)
+#define LCD_COLOR_DARKCYAN      ((uint32_t)0xFF008080)
+#define LCD_COLOR_DARKMAGENTA   ((uint32_t)0xFF800080)
+#define LCD_COLOR_DARKYELLOW    ((uint32_t)0xFF808000)
+#define LCD_COLOR_WHITE         ((uint32_t)0xFFFFFFFF)
+#define LCD_COLOR_LIGHTGRAY     ((uint32_t)0xFFD3D3D3)
+#define LCD_COLOR_GRAY          ((uint32_t)0xFF808080)
+#define LCD_COLOR_DARKGRAY      ((uint32_t)0xFF404040)
+#define LCD_COLOR_BLACK         ((uint32_t)0xFF000000)
+#define LCD_COLOR_BROWN         ((uint32_t)0xFFA52A2A)
+#define LCD_COLOR_ORANGE        ((uint32_t)0xFFFFA500)
+#define LCD_COLOR_TRANSPARENT   ((uint32_t)0xFF000000)
+
+
+/*
+ *  LCDハンドラ構造体定義
+ */
+typedef struct
+{
+	LTDC_Handle_t           *hltdc;		/* LTDCハンドラ */
+	uint32_t                layer;
+	uint16_t                _width;		/* 幅ピクセル数 */
+	uint16_t				_height;	/* 高さピクセル数 */
+} LCD_Handler_t;
+
+/** @defgroup STM32746G_DISCOVERY_LCD_Exported_Types STM32746G_DISCOVERY_LCD Exported Types
+  * @{
+  */
+typedef struct
+{
+	LCD_Handler_t           *hlcd;
+	uint32_t TextColor;		/* Specifies the color of text */
+	uint32_t BackColor;		/* Specifies the background color below the text */
+	void     *pFont;		/* Specifies the font used for the text */
+
+} LCD_DrawProp_t;
+
+/**
+  * @brief  LCD Drawing point (pixel) geometric definition
+  */
+typedef struct
+{
+  int16_t X; /*!< geometric X position of drawing */
+  int16_t Y; /*!< geometric Y position of drawing */
+
+} Point;
+
+/**
+  * @brief  Pointer on LCD Drawing point (pixel) geometric definition
+  */
+typedef Point * pPoint;
+
+
+/**
+ *  @brief LCD_OrientationTypeDef
+ *  Possible values of Display Orientation
+ */
+typedef enum
+{
+	LCD_ORIENTATION_PORTRAIT  = 0x00, /*!< Portrait orientation choice of LCD screen  */
+	LCD_ORIENTATION_LANDSCAPE = 0x01, /*!< Landscape orientation choice of LCD screen */
+	LCD_ORIENTATION_INVALID   = 0x02  /*!< Invalid orientation choice of LCD screen   */
+} LCD_OrientationTypeDef;
+
+/** @addtogroup STM32746G_DISCOVERY_LCD_Exported_Functions
+  * @{
+  */
+extern ER lcd_init(LCD_Handler_t *hlcd, LCD_OrientationTypeDef orientation);
+extern ER lcd_layerdefaultinit(LCD_Handler_t *hlcd, LCD_DrawProp_t *pDrawProp, uint16_t LayerIndex, uint32_t FB_Address);
+extern ER lcd_layerRgb565init(LCD_Handler_t *hlcd, LCD_DrawProp_t *pDrawProp, uint16_t LayerIndex, uint32_t FB_Address);
+extern void lcd_setlayervisible(LCD_Handler_t *hlcd, uint32_t LayerIndex, uint8_t State);
+extern void lcd_settransparency(LCD_Handler_t *hlcd, uint32_t LayerIndex, uint8_t Transparency);
+extern void lcd_setlayeraddress(LCD_Handler_t *hlcd, uint32_t LayerIndex, uint32_t Address);
+extern void lcd_setcolorkeying(LCD_Handler_t *hlcd, uint32_t LayerIndex, uint32_t RGBValue);
+extern void lcd_resetcolorkeying(LCD_Handler_t *hlcd, uint32_t LayerIndex);
+
+extern void lcd_setAddrWindow(LCD_Handler_t *hlcd, uint16_t LayerIndex, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
+extern void lcd_clear(LCD_Handler_t *hlcd, uint32_t Color);
+extern uint32_t lcd_readPixel(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos);
+extern void lcd_drawPixel(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint32_t RGB_Code);
+extern void lcd_drawFastHLine(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint16_t Length, uint32_t color);
+extern void lcd_drawFastVLine(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint16_t Length, uint32_t color);
+extern void lcd_drawBitmap(LCD_Handler_t *hlcd, uint32_t Xpos, uint32_t Ypos, uint8_t *pbmp);
+extern void lcd_fillRect(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint16_t Width, uint16_t Height, uint32_t color);
+
+extern void lcd_drawLine(LCD_DrawProp_t *pDrawProp, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
+extern void lcd_drawRect(LCD_DrawProp_t *pDrawProp, uint16_t Xpos, uint16_t Ypos, uint16_t Width, uint16_t Height);
+extern void lcd_DrawCircle(LCD_DrawProp_t *pDrawProp, uint16_t Xpos, uint16_t Ypos, uint16_t Radius);
+extern void lcd_DrawEllipse(LCD_DrawProp_t *pDrawProp, int Xpos, int Ypos, int XRadius, int YRadius);
+extern void lcd_drawPolygon(LCD_DrawProp_t *pDrawProp, pPoint Points, uint16_t PointCount);
+extern void lcd_fillCircle(LCD_DrawProp_t *pDrawProp, uint16_t Xpos, uint16_t Ypos, uint16_t Radius);
+extern void lcd_fillEllipse(LCD_DrawProp_t *pDrawProp, int Xpos, int Ypos, int XRadius, int YRadius);
+extern void lcd_fillPolygon(LCD_DrawProp_t *pDrawProp, pPoint Points, uint16_t PointCount);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _STLCD_RK043FN48H_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_st7789h2/Makefile.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_st7789h2/Makefile.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_st7789h2/Makefile.config	(revision 453)
@@ -0,0 +1,55 @@
+#
+#   TOPPERS/ASP/FMP Kernel
+#       Toyohashi Open Platform for Embedded Real-Time Systems/
+#       Advanced Standard Profile Kernel
+#
+#   Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                               Toyohashi Univ. of Technology, JAPAN
+#   Copyright (C) 2003-2008 by Ryosuke Takeuchi
+#                Platform Development Center RICOH COMPANY,LTD. JAPAN
+#   Copyright (C) 2015-2018 by TOPPERS PROJECT Educational Working Group.
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+ 
+#
+#  Makefile のプロセッサ依存 (st7789h2用)
+#
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/gdic/stlcd_st7789h2
+
+#
+#  USB DEVICE(GDIC)に関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR):$(SRCDIR)/gdic/stlcd_st7789h2
+SYSSVC_COBJS := $(SYSSVC_COBJS) stlcd_st7789h2.o
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_st7789h2/glcd_core.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_st7789h2/glcd_core.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_st7789h2/glcd_core.h	(revision 453)
@@ -0,0 +1,45 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+#ifndef _LCD_CORE_H_
+#define _LCD_CORE_H_
+
+#include "stlcd_st7789h2.h"
+
+#endif /* _LCD_CORE_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_st7789h2/stlcd_st7789h2.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_st7789h2/stlcd_st7789h2.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_st7789h2/stlcd_st7789h2.c	(revision 453)
@@ -0,0 +1,1302 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/**
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+#include "stlcd_st7789h2.h"
+
+#define sil_orw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) | (b))
+#define sil_andw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) & ~(b))
+#define sil_modw_mem(a, b, c)	sil_wrw_mem((a), (sil_rew_mem(a) & (~b)) | (c))
+
+
+#define POLY_X(Z)              ((int32_t)((Points + Z)->X))
+#define POLY_Y(Z)              ((int32_t)((Points + Z)->Y))
+#define ABS(X)  ((X) > 0 ? (X) : -(X))      
+
+#define FMC_BANK2_BASE  ((uint32_t)(0x60000000 | 0x04000000))
+#define GPIO_AF12_FMC           ((uint8_t)0xCU)  /* FMC Alternate Function mapping                      */
+
+#define GIOD_PINMAP     (GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5  | GPIO_PIN_7 | GPIO_PIN_8 |\
+						 GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_14 | GPIO_PIN_15)
+#define GIOE_PINMAP     (GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 |GPIO_PIN_10 |\
+						 GPIO_PIN_11 | GPIO_PIN_12 |GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15)
+#define GIOF_PINMAP     (GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 |\
+						 GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15)
+#define GIOG_PINMAP     (GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_9)
+
+
+typedef struct  {
+  uint8_t red;
+  uint8_t green;
+  uint8_t blue;
+} ST7789H2_Rgb888;
+
+#define LCD_IO_WriteData(b, r) do { \
+								  sil_wrh_mem((uint16_t *)((b)->fmc_base+2), (r)); \
+								  asm ("dsb 0xF":::"memory"); \
+							   } while(0)
+
+#define LCD_IO_WriteReg(b, r)  do { \
+								  sil_wrh_mem((uint16_t *)((b)->fmc_base), (r)); \
+								  asm ("dsb 0xF":::"memory"); \
+							   } while(0)
+
+#define LCD_IO_ReadData(b)     (uint16_t)sil_reh_mem((uint16_t *)((b)->fmc_base+2))
+
+
+/** @defgroup STM32F723E_DISCOVERY_LCD_Private_FunctionPrototypes STM32F723E Discovery Lcd Private Prototypes
+  * @{
+  */
+
+static void FillTriangle(LCD_DrawProp_t *pDrawProp, uint16_t x1, uint16_t x2, uint16_t x3, uint16_t y1, uint16_t y2, uint16_t y3);
+
+
+/**
+  * @brief  Initializes LCD low level.
+  * @retval None
+  */
+static void LCD_IO_Init(void) 
+{
+	GPIO_Init_t GPIO_Init_Data;
+	uint32_t pin, i;
+	uint32_t tmpr = 0;
+
+	/* Enable FMC clock */
+	sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB3ENR), RCC_AHB3ENR_FMCEN);
+
+	/* Enable FSMC clock */
+	sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB3ENR), RCC_AHB3ENR_FMCEN);
+	sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB3RSTR), RCC_AHB3RSTR_FMCRST);
+	sil_andw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB3RSTR), RCC_AHB3RSTR_FMCRST);
+
+	/* Enable GPIOs clock */
+	sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB1ENR), RCC_AHB1ENR_GPIODEN);
+	sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB1ENR), RCC_AHB1ENR_GPIOEEN);
+	sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB1ENR), RCC_AHB1ENR_GPIOFEN);
+	sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB1ENR), RCC_AHB1ENR_GPIOGEN);
+
+	GPIO_Init_Data.mode      = GPIO_MODE_AF;
+	GPIO_Init_Data.pull      = GPIO_PULLUP;
+	GPIO_Init_Data.otype     = GPIO_OTYPE_PP;
+	GPIO_Init_Data.speed     = GPIO_SPEED_HIGH;
+	GPIO_Init_Data.alternate = GPIO_AF12_FMC;
+
+	/* GPIOD configuration */ 
+	/* LCD_PSRAM_D2, LCD_PSRAM_D3, LCD_PSRAM_NOE, LCD_PSRAM_NWE, PSRAM_NE1, LCD_PSRAM_D13, 
+	   LCD_PSRAM_D14, LCD_PSRAM_D15, PSRAM_A16, PSRAM_A17, LCD_PSRAM_D0, LCD_PSRAM_D1 */
+	pin = GIOD_PINMAP;
+	for(i = 0 ; i < 16 ; i++){
+		if((pin & (1<<i)) != 0)
+			gpio_setup(TADR_GPIOD_BASE, &GPIO_Init_Data, i);
+	}
+
+	/* GPIOE configuration */
+	/* PSRAM_NBL0, PSRAM_NBL1, LCD_PSRAM_D4, LCD_PSRAM_D5, LCD_PSRAM_D6, LCD_PSRAM_D7, 
+	   LCD_PSRAM_D8, LCD_PSRAM_D9, LCD_PSRAM_D10, LCD_PSRAM_D11, LCD_PSRAM_D12 */
+	pin = GIOE_PINMAP;
+	for(i = 0 ; i < 16 ; i++){
+		if((pin & (1<<i)) != 0)
+			gpio_setup(TADR_GPIOE_BASE, &GPIO_Init_Data, i);
+	}
+
+	/* GPIOF configuration */
+	/* PSRAM_A0, PSRAM_A1, PSRAM_A2, PSRAM_A3, PSRAM_A4, PSRAM_A5, 
+	   PSRAM_A6, PSRAM_A7, PSRAM_A8, PSRAM_A9 */
+	pin = GIOF_PINMAP;
+	for(i = 0 ; i < 16 ; i++){
+		if((pin & (1<<i)) != 0)
+			gpio_setup(TADR_GPIOF_BASE, &GPIO_Init_Data, i);
+	}
+
+	/* GPIOG configuration */
+	/* PSRAM_A10, PSRAM_A11, PSRAM_A12, PSRAM_A13, PSRAM_A14, PSRAM_A15, LCD_NE */
+	pin = GIOG_PINMAP;
+	for(i = 0 ; i < 16 ; i++){
+		if((pin & (1<<i)) != 0)
+			gpio_setup(TADR_GPIOG_BASE, &GPIO_Init_Data, i);
+	}
+
+	/* Initialize SRAM control Interface */
+	tmpr = sil_rew_mem((uint32_t *)(TADR_FMC_R_BASE+TOFF_FMC_R_BTCR2));
+
+	/* Clear MBKEN, MUXEN, MTYP, MWID, FACCEN, BURSTEN, WAITPOL, WAITCFG, WREN,
+           WAITEN, EXTMOD, ASYNCWAIT, CBURSTRW and CCLKEN bits */
+	tmpr &= ((uint32_t)~(FMC_BCR1_MBKEN     | FMC_BCR1_MUXEN    | FMC_BCR1_MTYP    | \
+                       FMC_BCR1_MWID      | FMC_BCR1_FACCEN   | FMC_BCR1_BURSTEN | \
+                       FMC_BCR1_WAITPOL   | FMC_BCR1_CPSIZE   | FMC_BCR1_WAITCFG | \
+                       FMC_BCR1_WREN      | FMC_BCR1_WAITEN   | FMC_BCR1_EXTMOD  | \
+                       FMC_BCR1_ASYNCWAIT | FMC_BCR1_CBURSTRW | FMC_BCR1_CCLKEN  | FMC_BCR1_WFDIS));
+
+	/* Set NORSRAM device control parameters */
+	tmpr |= (uint32_t)(FMC_BCR1_MWID_0 | FMC_BCR1_WREN | FMC_BCR1_WFDIS);
+
+	sil_wrw_mem((uint32_t *)(TADR_FMC_R_BASE+TOFF_FMC_R_BTCR2), tmpr);
+
+	/* Configure synchronous mode when Continuous clock is enabled for bank2..4 */
+	sil_orw_mem((uint32_t *)(TADR_FMC_R_BASE+TOFF_FMC_R_BTCR0), FMC_BCR1_WFDIS);
+
+	/* Get the BTCR register value */
+	tmpr = sil_rew_mem((uint32_t *)(TADR_FMC_R_BASE+TOFF_FMC_R_BTCR3));
+
+	/* Clear ADDSET, ADDHLD, DATAST, BUSTURN, CLKDIV, DATLAT and ACCMOD bits */
+	tmpr &= ((uint32_t)~(FMC_BTR1_ADDSET  | FMC_BTR1_ADDHLD | FMC_BTR1_DATAST | \
+                       FMC_BTR1_BUSTURN | FMC_BTR1_CLKDIV | FMC_BTR1_DATLAT | \
+                       FMC_BTR1_ACCMOD));
+
+	/* Set FMC_NORSRAM device timing parameters */  
+	tmpr |= (uint32_t)(9 /* AddressSetupTime */                 |\
+                   ((2 /* AddressHoldTime */ ) << 4)          |\
+                   ((6 /* DataSetupTime */ ) << 8)            |\
+                   ((1 /* BusTurnAroundDuration */ ) << 16)   |\
+                   (((2 /* CLKDivision */ )-1) << 20)         |\
+                   (((2 /* DataLatency */)-2) << 24));
+
+	sil_wrw_mem((uint32_t *)(TADR_FMC_R_BASE+TOFF_FMC_R_BTCR3), tmpr);
+
+	/* Configure Clock division value (in NORSRAM bank 1) when continuous clock is enabled */
+	if((sil_rew_mem((uint32_t *)(TADR_FMC_R_BASE+TOFF_FMC_R_BTCR1)) & FMC_BCR1_CCLKEN) != 0){
+		tmpr = sil_rew_mem((uint32_t *)(TADR_FMC_R_BASE+TOFF_FMC_R_BTCR1));
+		tmpr &= ~(((uint32_t)0x0F) << 20);
+		tmpr |= (uint32_t)(((2 /* CLKDivision */ )-1) << 20);
+		sil_wrw_mem((uint32_t *)(TADR_FMC_R_BASE+TOFF_FMC_R_BTCR1), tmpr);
+	}
+
+	/* Initialize SRAM extended mode timing Interface */
+	sil_wrw_mem((uint32_t *)(TADR_FMC_R_BASE+TOFF_FMC_R_BWTR2), 0xFFFFFFFF);
+
+	/* Enable the NORSRAM device */
+	sil_orw_mem((uint32_t *)(TADR_FMC_R_BASE+TOFF_FMC_R_BTCR2), FMC_BCR1_MBKEN);
+}
+
+
+/**
+  * @brief  Writes to the selected LCD register.
+  * @param  Command: command value (or register address as named in st7789h2 doc).
+  * @param  Parameters: pointer on parameters value (if command uses one or several parameters).
+  * @param  NbParameters: number of command parameters (0 if no parameter)
+  * @retval None
+  */
+static void
+ST7789H2_WriteReg(LCD_Handler_t *hlcd, uint8_t Command, uint8_t *Parameters, uint8_t NbParameters)
+{
+	uint8_t   i;
+
+	/* Send command */
+	LCD_IO_WriteReg(hlcd, Command);
+
+	/* Send command's parameters if any */
+	for(i = 0 ; i<NbParameters; i++){
+		LCD_IO_WriteData(hlcd, Parameters[i]);
+	}
+}
+
+/**
+  * @brief  Reads the selected LCD Register.
+  * @param  Command: command value (or register address as named in st7789h2 doc).
+  * @retval Register Value.
+  */
+static uint8_t
+ST7789H2_ReadReg(LCD_Handler_t *hlcd, uint8_t Command)
+{
+	/* Send command */
+	LCD_IO_WriteReg(hlcd, Command);
+
+	/* Read dummy data */
+	LCD_IO_ReadData(hlcd);
+
+	/* Read register value */
+	return (LCD_IO_ReadData(hlcd));
+}
+
+/**
+  * @brief  Initialize the st7789h2 LCD Component.
+  * @param  None
+  * @retval None
+  */
+static void
+ST7789H2_Init(LCD_Handler_t *hlcd)
+{
+	uint8_t   parameter[14];
+
+	/* Initialize st7789h2 low level bus layer ----------------------------------*/
+	/* Sleep In Command */ 
+	ST7789H2_WriteReg(hlcd, ST7789H2_SLEEP_IN, (uint8_t*)NULL, 0); 
+	/* Wait for 10ms */
+	dly_tsk(10);
+
+	/* SW Reset Command */
+	ST7789H2_WriteReg(hlcd, 0x01, (uint8_t*)NULL, 0); 
+	/* Wait for 200ms */
+	dly_tsk(200);
+
+	/* Sleep Out Command */
+	ST7789H2_WriteReg(hlcd, ST7789H2_SLEEP_OUT, (uint8_t*)NULL, 0); 
+	/* Wait for 120ms */
+	dly_tsk(120);
+
+	/* Normal display for Driver Down side */
+	parameter[0] = 0x00;
+	ST7789H2_WriteReg(hlcd, ST7789H2_NORMAL_DISPLAY, parameter, 1);
+
+	/* Color mode 16bits/pixel */
+	parameter[0] = 0x05;
+	ST7789H2_WriteReg(hlcd, ST7789H2_COLOR_MODE, parameter, 1);
+
+	/* Display inversion On */
+	ST7789H2_WriteReg(hlcd, ST7789H2_DISPLAY_INVERSION, (uint8_t*)NULL, 0);
+
+	/* Set Column address CASET */
+	parameter[0] = 0x00;
+	parameter[1] = 0x00;
+	parameter[2] = 0x00;
+	parameter[3] = 0xEF;
+	ST7789H2_WriteReg(hlcd, ST7789H2_CASET, parameter, 4);
+	/* Set Row address RASET */
+	parameter[0] = 0x00;
+	parameter[1] = 0x00;
+	parameter[2] = 0x00;
+	parameter[3] = 0xEF;
+	ST7789H2_WriteReg(hlcd, ST7789H2_RASET, parameter, 4);
+
+	/*--------------- ST7789H2 Frame rate setting -------------------------------*/
+	/* PORCH control setting */      
+	parameter[0] = 0x0C;
+	parameter[1] = 0x0C;
+	parameter[2] = 0x00;
+	parameter[3] = 0x33;
+	parameter[4] = 0x33; 
+	ST7789H2_WriteReg(hlcd, ST7789H2_PORCH_CTRL, parameter, 5);
+
+	/* GATE control setting */
+	parameter[0] = 0x35; 
+	ST7789H2_WriteReg(hlcd, ST7789H2_GATE_CTRL, parameter, 1);
+
+	/*--------------- ST7789H2 Power setting ------------------------------------*/
+	/* VCOM setting */ 
+	parameter[0] = 0x1F;
+	ST7789H2_WriteReg(hlcd, ST7789H2_VCOM_SET, parameter, 1); 
+
+	/* LCM Control setting */
+	parameter[0] = 0x2C; 
+	ST7789H2_WriteReg(hlcd, ST7789H2_LCM_CTRL, parameter, 1);
+
+	/* VDV and VRH Command Enable */
+	parameter[0] = 0x01;
+	parameter[1] = 0xC3;
+	ST7789H2_WriteReg(hlcd, ST7789H2_VDV_VRH_EN, parameter, 2);
+
+	/* VDV Set */ 
+	parameter[0] = 0x20;
+	ST7789H2_WriteReg(hlcd, ST7789H2_VDV_SET, parameter, 1);
+
+	/* Frame Rate Control in normal mode */
+	parameter[0] = 0x0F; 
+	ST7789H2_WriteReg(hlcd, ST7789H2_FR_CTRL, parameter, 1);
+
+	/* Power Control */
+	parameter[0] = 0xA4;
+	parameter[1] = 0xA1;
+	ST7789H2_WriteReg(hlcd, ST7789H2_POWER_CTRL, parameter, 1); 
+
+	/*--------------- ST7789H2 Gamma setting ------------------------------------*/
+	/* Positive Voltage Gamma Control */ 
+	parameter[0] = 0xD0;
+	parameter[1] = 0x08;
+	parameter[2] = 0x11;
+	parameter[3] = 0x08;
+	parameter[4] = 0x0C;
+	parameter[5] = 0x15;
+	parameter[6] = 0x39;
+	parameter[7] = 0x33;
+	parameter[8] = 0x50;
+	parameter[9] = 0x36;
+	parameter[10] = 0x13;
+	parameter[11] = 0x14;
+	parameter[12] = 0x29;
+	parameter[13] = 0x2D;
+	ST7789H2_WriteReg(hlcd, ST7789H2_PV_GAMMA_CTRL, parameter, 14); 
+
+	/* Negative Voltage Gamma Control */
+	parameter[0] = 0xD0;
+	parameter[1] = 0x08;
+	parameter[2] = 0x10;
+	parameter[3] = 0x08;
+	parameter[4] = 0x06;
+	parameter[5] = 0x06;
+	parameter[6] = 0x39;
+	parameter[7] = 0x44;
+	parameter[8] = 0x51;
+	parameter[9] = 0x0B;
+	parameter[10] = 0x16;
+	parameter[11] = 0x14;
+	parameter[12] = 0x2F;
+	parameter[13] = 0x31;
+	ST7789H2_WriteReg(hlcd, ST7789H2_NV_GAMMA_CTRL, parameter, 14); 
+
+	/* Display ON command */
+	lcd_displayOn(hlcd);
+
+	/* Tearing Effect Line On: Option (00h:VSYNC Interface OFF, 01h:VSYNC Interface ON) */
+	parameter[0] = 0x00;
+	ST7789H2_WriteReg(hlcd, ST7789H2_TEARING_EFFECT, parameter, 1);
+}
+
+/**
+  * @brief  Set the Display Orientation.
+  * @param  orientation: ST7789H2_ORIENTATION_PORTRAIT, ST7789H2_ORIENTATION_LANDSCAPE
+  *                      or ST7789H2_ORIENTATION_LANDSCAPE_ROT180  
+  * @retval None
+  */
+static void
+ST7789H2_SetOrientation(LCD_Handler_t *hlcd, uint32_t orientation)
+{
+	uint8_t   parameter[6];
+
+	if(orientation == ST7789H2_ORIENTATION_LANDSCAPE){
+		parameter[0] = 0x00;
+	}
+	else if(orientation == ST7789H2_ORIENTATION_LANDSCAPE_ROT180){
+		/* Vertical Scrolling Definition */
+		/* TFA describes the Top Fixed Area */
+		parameter[0] = 0x00;
+		parameter[1] = 0x00;
+		/* VSA describes the height of the Vertical Scrolling Area */
+		parameter[2] = 0x01;
+		parameter[3] = 0xF0;
+		/* BFA describes the Bottom Fixed Area */
+		parameter[4] = 0x00;
+		parameter[5] = 0x00; 
+		ST7789H2_WriteReg(hlcd, ST7789H2_VSCRDEF, parameter, 6);
+
+		/* Vertical Scroll Start Address of RAM */
+		/* GRAM row nbr (320) - Display row nbr (240) = 80 = 0x50 */
+		parameter[0] = 0x00;
+		parameter[1] = 0x50;
+		ST7789H2_WriteReg(hlcd, ST7789H2_VSCSAD, parameter, 2);
+
+		parameter[0] = 0xC0;
+	}
+	else{
+		parameter[0] = 0x60;
+	}
+	ST7789H2_WriteReg(hlcd, ST7789H2_NORMAL_DISPLAY, parameter, 1);
+}
+
+/**
+  * @brief  Set Cursor position.
+  * @param  Xpos: specifies the X position.
+  * @param  Ypos: specifies the Y position.
+  * @retval None
+  */
+static void
+ST7789H2_SetCursor(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos)
+{
+  uint8_t   parameter[4];
+  /* CASET: Comumn Addrses Set */
+  parameter[0] = 0x00;     
+  parameter[1] = 0x00 + Xpos;
+  parameter[2] = 0x00;
+  parameter[3] = 0xEF + Xpos;
+  ST7789H2_WriteReg(hlcd, ST7789H2_CASET, parameter, 4);
+  /* RASET: Row Addrses Set */  
+  parameter[0] = 0x00;
+  parameter[1] = 0x00 + Ypos;
+  parameter[2] = 0x00;
+  parameter[3] = 0xEF + Ypos;
+  ST7789H2_WriteReg(hlcd, ST7789H2_RASET, parameter, 4);
+}
+
+/**
+  * @brief  Read pixel from LCD RAM in RGB888 format
+  * @param  Xpos: specifies the X position.
+  * @param  Ypos: specifies the Y position.
+  * @retval Each RGB pixel color components in a structure
+  */
+static ST7789H2_Rgb888
+ST7789H2_ReadPixel_rgb888(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos)
+{
+	ST7789H2_Rgb888 rgb888;
+	uint16_t         rgb888_part1, rgb888_part2;
+
+  /* In LCD RAM, pixels are 24 bits packed and read with 16 bits access
+   * Here is the pixels components arrangement in memory :
+   *       bits:  15 14 13 12 11 10 09 08 | 07 06 05 04 03 02 01 00
+   * address 0 :     red pixel 0    X  X  |   green pixel 0   X  X
+   * address 1 :    blue pixel 0    X  X  |     red pixel 1   X  X
+   * address 2 :   green pixel 1    X  X  |    blue pixel 1   X  X
+   */
+
+	/* Set Cursor */
+	ST7789H2_SetCursor(hlcd, Xpos, Ypos);
+	/* Prepare to read LCD RAM */
+	ST7789H2_WriteReg(hlcd, ST7789H2_READ_RAM, (uint8_t*)NULL, 0);   /* RAM read data command */
+	/* Dummy read */
+	LCD_IO_ReadData(hlcd);
+	/* Read first part of the RGB888 data */
+	rgb888_part1 = LCD_IO_ReadData(hlcd);
+	/* Read first part of the RGB888 data */
+	rgb888_part2 = LCD_IO_ReadData(hlcd);
+
+	/* red component */
+	rgb888.red   = (rgb888_part1 & 0xFC00) >> 8;
+	/* green component */
+	rgb888.green = (rgb888_part1 & 0x00FC) >> 0;
+	/* blue component */
+	rgb888.blue  = (rgb888_part2 & 0xFC00) >> 8;
+	return rgb888;
+}
+
+/**
+  * @brief  Displays a single picture line.
+  * @param  pdata: picture address.
+  * @param  Xpos: Image X position in the LCD
+  * @param  Ypos: Image Y position in the LCD
+  * @param  Xsize: Image X size in the LCD
+  * @retval None
+  */
+static void
+ST7789H2_DrawRGBHLine(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint16_t Xsize, uint8_t *pdata)
+{
+	uint32_t i = 0;
+	uint32_t posX;
+	uint16_t *rgb565 = (uint16_t*)pdata;
+
+	/* Prepare to write to LCD RAM */
+	ST7789H2_WriteReg(hlcd, ST7789H2_WRITE_RAM, (uint8_t*)NULL, 0);   /* RAM write data command */
+
+	for(posX = Xpos ; posX < (Xsize + Xpos) ; posX++){
+		if((posX >= hlcd->winXstart) && (Ypos >= hlcd->winYstart) &&     /* Check we are in the defined window */
+			(posX <= hlcd->winXend) && (Ypos <= hlcd->winXend)){
+			if(posX != (Xsize + Xpos)){	/* When writing last pixel when size is odd, the third part is not written */
+				LCD_IO_WriteData(hlcd, rgb565[i]);
+			}
+			i++;
+		}
+	}
+}
+
+/*
+ *  ST7789H2スクリーンの初期化関数
+ */
+ER
+lcd_init(LCD_Handler_t *hlcd, uint32_t orientation)
+{ 
+	GPIO_Init_t GPIO_Init_Data;
+	uint16_t id;
+
+	hlcd->_width  = ST7789H2_LCD_PIXEL_WIDTH;
+	hlcd->_height = ST7789H2_LCD_PIXEL_HEIGHT;
+	hlcd->winXstart = 0;
+	hlcd->winYstart = 0;
+	hlcd->winXend = hlcd->_width - 1;
+	hlcd->winXend = hlcd->_height - 1;
+
+	/* Initialize LCD special pins GPIOs */
+	sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB1ENR), hlcd->rst_clk);
+	sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB1ENR), hlcd->te_clk);
+	sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB1ENR), hlcd->bl_clk);
+
+	GPIO_Init_Data.mode      = GPIO_MODE_OUTPUT;   /* LCD_RESET pin has to be manually controlled */
+	GPIO_Init_Data.speed     = hlcd->gpio_speed;
+	GPIO_Init_Data.pull      = hlcd->rst_pull;
+	GPIO_Init_Data.otype     = GPIO_OTYPE_PP;
+	gpio_setup(hlcd->rst_base, &GPIO_Init_Data, hlcd->rst_pin);
+	sil_wrw_mem((uint32_t *)(hlcd->rst_base+TOFF_GPIO_BSRR), (1<<hlcd->rst_pin) << 16);
+
+	/* LCD_TE GPIO configuration */
+	GPIO_Init_Data.mode      = GPIO_MODE_INPUT;        /* LCD_TE pin has to be manually managed */
+	gpio_setup(hlcd->te_base, &GPIO_Init_Data, hlcd->te_pin);
+
+	/* LCD_BL_CTRL GPIO configuration */
+	GPIO_Init_Data.mode      = GPIO_MODE_OUTPUT;   /* LCD_BL_CTRL pin has to be manually controlled */
+	GPIO_Init_Data.pull      = hlcd->bl_pull;
+	gpio_setup(hlcd->bl_base, &GPIO_Init_Data, hlcd->bl_pin);
+
+	/* Backlight control signal assertion */
+	if(hlcd->bl_active == 0)
+		sil_wrw_mem((uint32_t *)(hlcd->bl_base+TOFF_GPIO_BSRR), (1<<hlcd->bl_pin) << 16);
+	else
+		sil_wrw_mem((uint32_t *)(hlcd->bl_base+TOFF_GPIO_BSRR), (1<<hlcd->bl_pin));
+
+	/* Apply hardware reset according to procedure indicated in FRD154BP2901 documentation */
+	dly_tsk(5);   /* Reset signal asserted during 5ms  */
+	sil_wrw_mem((uint32_t *)(hlcd->rst_base+TOFF_GPIO_BSRR), (1<<hlcd->rst_pin));
+	dly_tsk(10);  /* Reset signal released during 10ms */
+	sil_wrw_mem((uint32_t *)(hlcd->rst_base+TOFF_GPIO_BSRR), (1<<hlcd->rst_pin) << 16);
+	dly_tsk(20);  /* Reset signal asserted during 20ms */
+	sil_wrw_mem((uint32_t *)(hlcd->rst_base+TOFF_GPIO_BSRR), (1<<hlcd->rst_pin));
+	dly_tsk(10);  /* Reset signal released during 10ms */
+
+	LCD_IO_Init();
+	id = ST7789H2_ReadReg(hlcd, ST7789H2_LCD_ID);
+	if(id  == ST7789H2_ID){
+		/* LCD Init */
+		ST7789H2_Init(hlcd);
+
+		if(orientation == LCD_ORIENTATION_PORTRAIT){
+			ST7789H2_SetOrientation(hlcd, LCD_ORIENTATION_PORTRAIT);
+		}
+		else if(orientation == LCD_ORIENTATION_LANDSCAPE_ROT180){
+			ST7789H2_SetOrientation(hlcd, LCD_ORIENTATION_LANDSCAPE_ROT180);
+		}
+		else{
+			/* Default landscape orientation is selected */
+		}
+		return E_OK;
+	}
+	else
+		return E_SYS;
+}
+
+/*
+ *  ST7789H2スクリーンの終了関数
+ */
+ER
+lcd_deinit(LCD_Handler_t *hlcd)
+{
+	/* Actually LcdDrv does not provide a DeInit function */
+	return E_OK;
+}
+
+/*
+ *  ST7789H2スクリーンレイヤ初期化関数
+ */
+ER
+lcd_layerdefaultinit(LCD_Handler_t *hlcd, LCD_DrawProp_t *pDrawProp, uint16_t LayerIndex, uint32_t FB_Address)
+{
+	pDrawProp->BackColor = 0xFFFF;
+	pDrawProp->TextColor = 0x0000;
+	pDrawProp->hlcd      = hlcd;
+	return E_OK;
+}
+
+/*
+ *  ST7789H2表示ウィンドウ設定
+ */
+void
+lcd_setAddrWindow(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint16_t Width, uint16_t Height)
+{
+	if(Xpos < hlcd->_width){
+		hlcd->winXstart = Xpos;
+	}
+	else{
+		hlcd->winXstart = 0;
+	}
+
+	if(Ypos < hlcd->_height){
+		hlcd->winYstart = Ypos;
+	}
+	else{
+		hlcd->winYstart = 0;
+	}
+
+	if(Width  + Xpos <= hlcd->_width){
+		hlcd->winXend = Width  + Xpos - 1;
+	}
+	else{
+		hlcd->winXend = hlcd->_width - 1;
+	}
+
+	if(Height + Ypos <= hlcd->_height){
+		hlcd->winXend = Height + Ypos - 1;
+	}
+	else{
+		hlcd->winXend = hlcd->_height-1;
+	}
+}
+
+/*
+ *  ST7789H2スクリーンクリア
+ */
+void
+lcd_clear(LCD_Handler_t *hlcd, uint16_t Color)
+{
+	uint32_t counter = 0;
+	uint32_t y_size = 0;
+
+	y_size =  hlcd->_height;
+
+	for(counter = 0; counter < y_size; counter++){
+		lcd_drawFastHLine(hlcd, 0, counter, hlcd->_width, Color);
+	}
+}
+
+/*
+ *  PIXEL読み出し
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: X position
+ *  param3  y: Y position
+ */
+uint16_t
+lcd_readPixel(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos)
+{
+	ST7789H2_Rgb888 rgb888;
+	uint8_t          r, g, b;
+	uint16_t         rgb565;
+
+	/* Set Cursor */
+	ST7789H2_SetCursor(hlcd, Xpos, Ypos);
+
+	/* Read RGB888 data from LCD RAM */
+	rgb888 = ST7789H2_ReadPixel_rgb888(hlcd, Xpos, Ypos);
+
+	/* Convert RGB888 to RGB565 */
+	r = ((rgb888.red & 0xF8) >> 3);    /* Extract the red component 5 most significant bits */
+	g = ((rgb888.green & 0xFC) >> 2);  /* Extract the green component 6 most significant bits */
+	b = ((rgb888.blue & 0xF8) >> 3);   /* Extract the blue component 5 most significant bits */
+
+	rgb565 = ((uint16_t)(r) << 11) + ((uint16_t)(g) << 5) + ((uint16_t)(b) << 0);
+	return (rgb565);
+}
+
+/*
+ *  PIXEL描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: X position
+ *  param3  y: Y position
+ *  param4  color: color value
+ */
+void
+lcd_drawPixel(LCD_Handler_t *hlcd, int16_t Xpos, int16_t Ypos, uint16_t RGB_Code)
+{
+	ST7789H2_SetCursor(hlcd, Xpos, Ypos);
+
+	/* Prepare to write to LCD RAM */
+	ST7789H2_WriteReg(hlcd, ST7789H2_WRITE_RAM, (uint8_t*)NULL, 0);   /* RAM write data command */
+
+	/* Write RAM data */
+	LCD_IO_WriteData(hlcd, RGB_Code);
+}
+
+/*
+ *  垂直方向LINEの高速描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: start X position
+ *  param3  y: start Y position
+ *  param4  h: height
+ *  param5  color: color value
+ */
+void
+lcd_drawFastHLine(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint16_t Length, uint32_t color)
+{
+	uint16_t counter = 0;
+
+	/* Set Cursor */
+	ST7789H2_SetCursor(hlcd, Xpos, Ypos);
+
+	/* Prepare to write to LCD RAM */
+	ST7789H2_WriteReg(hlcd, ST7789H2_WRITE_RAM, (uint8_t*)NULL, 0);   /* RAM write data command */
+
+	/* Sent a complete line */
+	for(counter = 0; counter < Length; counter++){
+		LCD_IO_WriteData(hlcd, color);
+	}
+}
+
+/*
+ *  水平方向LINEの高速描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: start X position
+ *  param3  y: start Y position
+ *  param4  w: width
+ *  param5  color: color value
+ */
+void
+lcd_drawFastVLine(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint16_t Length, uint32_t color)
+{
+	uint16_t counter = 0;
+
+	/* Set Cursor */
+	ST7789H2_SetCursor(hlcd, Xpos, Ypos);
+
+	/* Prepare to write to LCD RAM */
+	ST7789H2_WriteReg(hlcd, ST7789H2_WRITE_RAM, (uint8_t*)NULL, 0);   /* RAM write data command */
+
+	/* Fill a complete vertical line */
+	for(counter = 0; counter < Length; counter++){
+		lcd_drawPixel(hlcd, Xpos, Ypos + counter, color);
+	}
+}
+
+/*
+ *  BITMAP描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x0: Bmp X position in the LCD
+ *  param3  y0: Bmp Y position in the LCD
+ *  param4  pbmp: Pointer to Bmp picture address in the internal Flash
+ */
+void
+lcd_drawBitmap(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint8_t *pbmp)
+{
+	uint32_t height = 0;
+	uint32_t width  = 0;
+	uint32_t index = 0, size = 0;
+	uint32_t posY;
+	uint32_t nb_line = 0;
+	uint16_t Xsize = hlcd->winXend - hlcd->winXstart + 1;
+	uint16_t Ysize = hlcd->winXend - hlcd->winYstart + 1;
+
+	/* Read bitmap width */
+	width = pbmp[18] + (pbmp[19] << 8) + (pbmp[20] << 16)  + (pbmp[21] << 24);
+
+	/* Read bitmap height */
+	height = pbmp[22] + (pbmp[23] << 8) + (pbmp[24] << 16)  + (pbmp[25] << 24);
+
+	lcd_setAddrWindow(hlcd, Xpos, Ypos, width, height);
+
+	/* Read bitmap size */
+	size = *(volatile uint16_t *) (pbmp + 2);
+	size |= (*(volatile uint16_t *) (pbmp + 4)) << 16;
+	/* Get bitmap data address offset */
+	index = *(volatile uint16_t *) (pbmp + 10);
+	index |= (*(volatile uint16_t *) (pbmp + 12)) << 16;
+	size = (size - index)/2;
+	pbmp += index;
+
+	for (posY = (Ypos + Ysize); posY > Ypos; posY--){	/* In BMP files the line order is inverted */
+		/* Set Cursor */
+		ST7789H2_SetCursor(hlcd, Xpos, posY - 1);
+
+		/* Draw one line of the picture */
+		ST7789H2_DrawRGBHLine(hlcd, Xpos, posY - 1, Xsize, (pbmp + (nb_line * Xsize * 2)));
+		nb_line++;
+	}
+	lcd_setAddrWindow(hlcd, 0, 0, hlcd->_width, hlcd->_height);
+}
+
+/*
+ *  バッファコピー
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  Xpos: コピー先X座標
+ *  param3  Ypos: コピー先Y座標
+ *  param4  Xsize: バッファ幅
+ *  param5  Ysize: バッファ高さ
+ *  param6  pdata: コピー元バッファポインタ
+ */
+void
+lcd_drawRGBImage(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint16_t Xsize, uint16_t Ysize, uint8_t *pdata)
+{
+	uint32_t posY;
+	uint32_t nb_line = 0;
+
+	lcd_setAddrWindow(hlcd, Xpos, Ypos, Xsize, Ysize);
+
+	for(posY = Ypos ; posY < (Ypos + Ysize) ; posY++){
+		/* Set Cursor */
+		ST7789H2_SetCursor(hlcd, Xpos, posY);
+
+		/* Draw one line of the picture */
+		ST7789H2_DrawRGBHLine(hlcd, Xpos, posY, Xsize, (pdata + (nb_line * Xsize * 2)));
+		nb_line++;
+	}
+	lcd_setAddrWindow(hlcd, 0, 0, hlcd->_width, hlcd->_height);
+}
+
+/*
+ *  RECTANGLE塗りつぶし描画
+ *  param1  hlcd: Pointer to LCD Handler
+ *  param2  x: left X position
+ *  param3  y: top Y position
+ *  param4  w: width
+ *  param5  h: height
+ *  param6  color: color value
+ */
+void
+lcd_fillRect(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint16_t Width, uint16_t Height, uint32_t color)
+{
+	do{
+		lcd_drawFastHLine(hlcd, Xpos, Ypos++, Width, color);
+	}
+	while(Height--);
+}
+
+
+/*
+ *  線描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x1: Point 1 X position
+ *  param3  y1: Point 1 Y position
+ *  param4  x2: Point 2 X position
+ *  param5  y2: Point 2 Y position
+ */
+void
+lcd_drawLine(LCD_DrawProp_t *pDrawProp, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
+{
+	int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0, 
+	yinc1 = 0, yinc2 = 0, den = 0, num = 0, numadd = 0, numpixels = 0, 
+	curpixel = 0;
+
+	deltax = ABS(x2 - x1);		/* The difference between the x's */
+	deltay = ABS(y2 - y1);		/* The difference between the y's */
+	x = x1;						/* Start x off at the first pixel */
+	y = y1;						/* Start y off at the first pixel */
+
+	if(x2 >= x1){				/* The x-values are increasing */
+		xinc1 = 1;
+		xinc2 = 1;
+	}
+	else{						/* The x-values are decreasing */
+		xinc1 = -1;
+		xinc2 = -1;
+	}
+
+	if(y2 >= y1){				/* The y-values are increasing */
+		yinc1 = 1;
+		yinc2 = 1;
+	}
+	else{						/* The y-values are decreasing */
+		yinc1 = -1;
+		yinc2 = -1;
+	}
+
+	if(deltax >= deltay){		/* There is at least one x-value for every y-value */
+		xinc1 = 0;                  /* Don't change the x when numerator >= denominator */
+		yinc2 = 0;                  /* Don't change the y for every iteration */
+		den = deltax;
+		num = deltax / 2;
+		numadd = deltay;
+		numpixels = deltax;         /* There are more x-values than y-values */
+	}
+	else{						/* There is at least one y-value for every x-value */
+		xinc2 = 0;				/* Don't change the x for every iteration */
+		yinc1 = 0;				/* Don't change the y when numerator >= denominator */
+		den = deltay;
+		num = deltay / 2;
+		numadd = deltax;
+		numpixels = deltay;		/* There are more y-values than x-values */
+	}
+
+	for(curpixel = 0; curpixel <= numpixels; curpixel++){
+		lcd_drawPixel(pDrawProp->hlcd, x, y, pDrawProp->TextColor);  /* Draw the current pixel */
+		num += numadd;                            /* Increase the numerator by the top of the fraction */
+		if(num >= den){			/* Check if numerator >= denominator */
+			num -= den;			/* Calculate the new numerator value */
+			x += xinc1;			/* Change the x as appropriate */
+			y += yinc1;			/* Change the y as appropriate */
+		}
+		x += xinc2;				/* Change the x as appropriate */
+		y += yinc2;				/* Change the y as appropriate */
+	}
+}
+
+/*
+ *  RECTANGLE描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x: left X position
+ *  param3  y: top Y position
+ *  param4  w: width
+ *  param5  h: height
+ */
+void
+lcd_drawRect(LCD_DrawProp_t *pDrawProp, uint16_t Xpos, uint16_t Ypos, uint16_t Width, uint16_t Height)
+{
+	/* Draw horizontal lines */
+	lcd_drawFastHLine(pDrawProp->hlcd, Xpos, Ypos, Width, pDrawProp->TextColor);
+	lcd_drawFastHLine(pDrawProp->hlcd, Xpos, (Ypos+ Height), Width, pDrawProp->TextColor);
+
+	/* Draw vertical lines */
+	lcd_drawFastVLine(pDrawProp->hlcd, Xpos, Ypos, Height, pDrawProp->TextColor);
+	lcd_drawFastVLine(pDrawProp->hlcd, (Xpos + Width), Ypos, Height, pDrawProp->TextColor);
+}
+
+/*
+ *  円描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x0: X position
+ *  param3  y0: Y position
+ *  param4  Radius: Circle radius
+ */
+void
+lcd_DrawCircle(LCD_DrawProp_t *pDrawProp, uint16_t Xpos, uint16_t Ypos, uint16_t Radius)
+{
+	int32_t  decision;       /* Decision Variable */ 
+	uint32_t  current_x;   /* Current X Value */
+	uint32_t  current_y;   /* Current Y Value */ 
+
+	decision = 3 - (Radius << 1);
+	current_x = 0;
+	current_y = Radius;
+
+	while (current_x <= current_y){
+		lcd_drawPixel(pDrawProp->hlcd, (Xpos + current_x), (Ypos - current_y), pDrawProp->TextColor);
+		lcd_drawPixel(pDrawProp->hlcd, (Xpos - current_x), (Ypos - current_y), pDrawProp->TextColor);
+		lcd_drawPixel(pDrawProp->hlcd, (Xpos + current_y), (Ypos - current_x), pDrawProp->TextColor);
+		lcd_drawPixel(pDrawProp->hlcd, (Xpos - current_y), (Ypos - current_x), pDrawProp->TextColor);
+		lcd_drawPixel(pDrawProp->hlcd, (Xpos + current_x), (Ypos + current_y), pDrawProp->TextColor);
+		lcd_drawPixel(pDrawProp->hlcd, (Xpos - current_x), (Ypos + current_y), pDrawProp->TextColor);
+		lcd_drawPixel(pDrawProp->hlcd, (Xpos + current_y), (Ypos + current_x), pDrawProp->TextColor);
+		lcd_drawPixel(pDrawProp->hlcd, (Xpos - current_y), (Ypos + current_x), pDrawProp->TextColor);
+
+		if(decision < 0){
+			decision += (current_x << 2) + 6;
+		}
+		else{
+			decision += ((current_x - current_y) << 2) + 10;
+			current_y--;
+		}
+		current_x++;
+	}
+}
+
+/*
+ *  PLOY-LINE描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  Points: Pointer to the points array
+ *  param3  PointCount: Number of points
+ */
+void
+lcd_drawPolygon(LCD_DrawProp_t *pDrawProp, pPoint Points, uint16_t PointCount)
+{
+	int16_t x = 0, y = 0;
+
+	if(PointCount < 2)
+		return;
+
+	lcd_drawLine(pDrawProp, Points->X, Points->Y, (Points+PointCount-1)->X, (Points+PointCount-1)->Y);
+
+	while(--PointCount){
+		x = Points->X;
+		y = Points->Y;
+		Points++;
+		lcd_drawLine(pDrawProp, x, y, Points->X, Points->Y);
+	}
+}
+
+/*
+ *  楕円描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x0: X position
+ *  param3  y0: Y position
+ *  param4  XRadius: Ellipse X radius
+ *  param5  YRadius: Ellipse Y radius
+ */
+void
+lcd_DrawEllipse(LCD_DrawProp_t *pDrawProp, int Xpos, int Ypos, int XRadius, int YRadius)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	int x = 0, y = -YRadius, err = 2-2*XRadius, e2;
+	float k = 0, rad1 = 0, rad2 = 0;
+
+	rad1 = XRadius;
+	rad2 = YRadius;
+
+	k = (float)(rad2/rad1);
+
+	do{
+		lcd_drawPixel(hlcd, (Xpos-(uint16_t)(x/k)), (Ypos+y), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (Xpos+(uint16_t)(x/k)), (Ypos+y), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (Xpos+(uint16_t)(x/k)), (Ypos-y), pDrawProp->TextColor);
+		lcd_drawPixel(hlcd, (Xpos-(uint16_t)(x/k)), (Ypos-y), pDrawProp->TextColor);
+
+		e2 = err;
+		if(e2 <= x){
+			err += ++x*2+1;
+			if(-y == x && e2 <= y)
+				e2 = 0;
+		}
+		if(e2 > y)
+			err += ++y*2+1;
+	}while (y <= 0);
+}
+
+/*
+ *  円塗りつぶし描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x0: X position
+ *  param3  y0: Y position
+ *  param4  Radius: Circle radius
+ */
+void
+lcd_fillCircle(LCD_DrawProp_t *pDrawProp, uint16_t Xpos, uint16_t Ypos, uint16_t Radius)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	int32_t  decision;        /* Decision Variable */ 
+	uint32_t  current_x;    /* Current X Value */
+	uint32_t  current_y;    /* Current Y Value */ 
+
+	decision = 3 - (Radius << 1);
+	current_x = 0;
+	current_y = Radius;
+
+	while(current_x <= current_y){
+		if(current_y > 0){
+			lcd_drawFastHLine(hlcd, Xpos - current_y, Ypos + current_x, 2*current_y, pDrawProp->TextColor);
+			lcd_drawFastHLine(hlcd, Xpos - current_y, Ypos - current_x, 2*current_y, pDrawProp->TextColor);
+		}
+
+		if(current_x > 0){
+			lcd_drawFastHLine(hlcd, Xpos - current_x, Ypos - current_y, 2*current_x, pDrawProp->TextColor);
+			lcd_drawFastHLine(hlcd, Xpos - current_x, Ypos + current_y, 2*current_x, pDrawProp->TextColor);
+		}
+		if(decision < 0){
+			decision += (current_x << 2) + 6;
+		}
+		else{
+			decision += ((current_x - current_y) << 2) + 10;
+			current_y--;
+		}
+		current_x++;
+	}
+	lcd_DrawCircle(pDrawProp, Xpos, Ypos, Radius);
+}
+
+/*
+ *  楕円塗りつぶし描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x0: X position
+ *  param3  y0: Y position
+ *  param4  XRadius: Ellipse X radius
+ *  param5  YRadius: Ellipse Y radius
+ */
+void
+lcd_fillEllipse(LCD_DrawProp_t *pDrawProp, int Xpos, int Ypos, int XRadius, int YRadius)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	int x = 0, y = -YRadius, err = 2-2*XRadius, e2;
+	float k = 0, rad1 = 0, rad2 = 0;
+
+	rad1 = XRadius;
+	rad2 = YRadius;
+	k = (float)(rad2/rad1);
+
+	do{
+		lcd_drawFastHLine(hlcd, (Xpos-(uint16_t)(x/k)), (Ypos+y), (2*(uint16_t)(x/k) + 1), pDrawProp->TextColor);
+		lcd_drawFastHLine(hlcd, (Xpos-(uint16_t)(x/k)), (Ypos-y), (2*(uint16_t)(x/k) + 1), pDrawProp->TextColor);
+
+		e2 = err;
+		if(e2 <= x){
+			err += ++x*2+1;
+			if(-y == x && e2 <= y)
+				e2 = 0;
+		}
+		if(e2 > y)
+			err += ++y*2+1;
+	}
+	while(y <= 0);
+}
+
+/*
+ *  PLOY-LINE塗りつぶし描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  Points: Pointer to the points array
+ *  param3  PointCount: Number of points
+ */
+void
+lcd_fillPolygon(LCD_DrawProp_t *pDrawProp, pPoint Points, uint16_t PointCount)
+{
+	int16_t X = 0, Y = 0, X2 = 0, Y2 = 0, X_center = 0, Y_center = 0, X_first = 0, Y_first = 0, pixelX = 0, pixelY = 0, counter = 0;
+	uint16_t  IMAGE_LEFT = 0, IMAGE_RIGHT = 0, IMAGE_TOP = 0, IMAGE_BOTTOM = 0;  
+
+	IMAGE_LEFT = IMAGE_RIGHT = Points->X;
+	IMAGE_TOP= IMAGE_BOTTOM = Points->Y;
+
+	for(counter = 1; counter < PointCount; counter++){
+		pixelX = POLY_X(counter);
+		if(pixelX < IMAGE_LEFT){
+			IMAGE_LEFT = pixelX;
+		}
+		if(pixelX > IMAGE_RIGHT){
+			IMAGE_RIGHT = pixelX;
+		}
+
+		pixelY = POLY_Y(counter);
+		if(pixelY < IMAGE_TOP){
+			IMAGE_TOP = pixelY;
+		}
+		if(pixelY > IMAGE_BOTTOM){
+			IMAGE_BOTTOM = pixelY;
+		}
+	}
+
+	if(PointCount < 2){
+		return;
+	}
+
+	X_center = (IMAGE_LEFT + IMAGE_RIGHT)/2;
+	Y_center = (IMAGE_BOTTOM + IMAGE_TOP)/2;
+
+	X_first = Points->X;
+	Y_first = Points->Y;
+
+	while(--PointCount){
+		X = Points->X;
+		Y = Points->Y;
+		Points++;
+		X2 = Points->X;
+		Y2 = Points->Y;
+
+		FillTriangle(pDrawProp, X, X2, X_center, Y, Y2, Y_center);
+		FillTriangle(pDrawProp, X, X_center, X2, Y, Y_center, Y2);
+		FillTriangle(pDrawProp, X_center, X2, X, Y_center, Y2, Y);
+	}
+	FillTriangle(pDrawProp, X_first, X2, X_center, Y_first, Y2, Y_center);
+	FillTriangle(pDrawProp, X_first, X_center, X2, Y_first, Y_center, Y2);
+	FillTriangle(pDrawProp, X_center, X2, X_first, Y_center, Y2, Y_first);
+}
+
+/*
+ *  表示オン
+ *  param1  hlcd: Pointer to LCD Handler
+ */
+void
+lcd_displayOn(LCD_Handler_t *hlcd)
+{
+	/* Display ON command */
+	ST7789H2_WriteReg(hlcd, ST7789H2_DISPLAY_ON, (uint8_t*)NULL, 0);
+
+	/* Sleep Out command */
+	ST7789H2_WriteReg(hlcd, ST7789H2_SLEEP_OUT, (uint8_t*)NULL, 0);
+}
+
+/*
+ *  表示オフ
+ *  param1  hlcd: Pointer to LCD Handler
+ */
+void
+lcd_displayOff(LCD_Handler_t *hlcd)
+{
+	uint8_t   parameter[1];
+	parameter[0] = 0xFE;
+	/* Display OFF command */
+	ST7789H2_WriteReg(hlcd, ST7789H2_DISPLAY_OFF, parameter, 1);
+	/* Sleep In Command */
+	ST7789H2_WriteReg(hlcd, ST7789H2_SLEEP_IN, (uint8_t*)NULL, 0);
+	/* Wait for 10ms */
+	dly_tsk(10);
+}
+
+
+/*
+ *  トライアングルフィル
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x1: 点1 X座標始点
+ *  param3  y1: 点1 Y座標始点
+ *  param4  x2: 点2 X座標始点
+ *  param5  y2: 点2 Y座標始点
+ *  param6  x3: 点3 X座標始点
+ *  param7  y3: 点3 Y座標始点
+ */
+static void
+FillTriangle(LCD_DrawProp_t *pDrawProp, uint16_t x1, uint16_t x2, uint16_t x3, uint16_t y1, uint16_t y2, uint16_t y3)
+{
+	int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0, 
+	yinc1 = 0, yinc2 = 0, den = 0, num = 0, numadd = 0, numpixels = 0, 
+	curpixel = 0;
+
+	deltax = ABS(x2 - x1);	/* The difference between the x's */
+	deltay = ABS(y2 - y1);	/* The difference between the y's */
+	x = x1;					/* Start x off at the first pixel */
+	y = y1;					/* Start y off at the first pixel */
+
+	if(x2 >= x1){			/* The x-values are increasing */
+		xinc1 = 1;
+		xinc2 = 1;
+	}
+	else{					/* The x-values are decreasing */
+		xinc1 = -1;
+		xinc2 = -1;
+	}
+
+	if(y2 >= y1){			/* The y-values are increasing */
+		yinc1 = 1;
+		yinc2 = 1;
+	}
+	else{					/* The y-values are decreasing */
+		yinc1 = -1;
+		yinc2 = -1;
+	}
+
+	if(deltax >= deltay){	/* There is at least one x-value for every y-value */
+		xinc1 = 0;			/* Don't change the x when numerator >= denominator */
+		yinc2 = 0;			/* Don't change the y for every iteration */
+		den = deltax;
+		num = deltax / 2;
+		numadd = deltay;
+		numpixels = deltax;	/* There are more x-values than y-values */
+	}
+	else{					/* There is at least one y-value for every x-value */
+		xinc2 = 0;			/* Don't change the x for every iteration */
+		yinc1 = 0;			/* Don't change the y when numerator >= denominator */
+		den = deltay;
+		num = deltay / 2;
+		numadd = deltax;
+		numpixels = deltay;	/* There are more y-values than x-values */
+	}
+
+	for(curpixel = 0 ; curpixel <= numpixels ; curpixel++){
+		lcd_drawLine(pDrawProp, x, y, x3, y3);
+		num += numadd;		/* Increase the numerator by the top of the fraction */
+		if(num >= den){		/* Check if numerator >= denominator */
+			num -= den;		/* Calculate the new numerator value */
+			x += xinc1;		/* Change the x as appropriate */
+			y += yinc1;		/* Change the y as appropriate */
+		}
+		x += xinc2;			/* Change the x as appropriate */
+		y += yinc2;			/* Change the y as appropriate */
+	}
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_st7789h2/stlcd_st7789h2.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_st7789h2/stlcd_st7789h2.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stlcd_st7789h2/stlcd_st7789h2.h	(revision 453)
@@ -0,0 +1,252 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/**
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+#ifndef _STLCD_ST7789H2_H_
+#define _STLCD_ST7789H2_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif 
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <target_syssvc.h>
+#include "device.h"
+#include "ltdc.h"
+
+
+/**
+  * @brief  ST7789H2 ID
+  */
+#define  ST7789H2_ID    0x85
+
+/**
+  * @brief  ST7789H2 Size
+  */
+#define  ST7789H2_LCD_PIXEL_WIDTH    ((uint16_t)240)
+#define  ST7789H2_LCD_PIXEL_HEIGHT   ((uint16_t)240)
+
+/**
+ *  @brief LCD_OrientationTypeDef
+ *  Possible values of Display Orientation
+ */
+#define ST7789H2_ORIENTATION_PORTRAIT         ((uint32_t)0x00) /* Portrait orientation choice of LCD screen  */
+#define ST7789H2_ORIENTATION_LANDSCAPE        ((uint32_t)0x01) /* Landscape orientation choice of LCD screen */
+#define ST7789H2_ORIENTATION_LANDSCAPE_ROT180 ((uint32_t)0x02) /* Landscape rotated 180ｰ orientation choice of LCD screen */
+
+/**
+  * @brief  ST7789H2 Registers
+  */
+#define ST7789H2_LCD_ID             0x04
+#define ST7789H2_SLEEP_IN           0x10
+#define ST7789H2_SLEEP_OUT          0x11
+#define ST7789H2_PARTIAL_DISPLAY    0x12
+#define ST7789H2_DISPLAY_INVERSION  0x21
+#define ST7789H2_DISPLAY_ON         0x29
+#define ST7789H2_WRITE_RAM          0x2C
+#define ST7789H2_READ_RAM           0x2E
+#define ST7789H2_CASET              0x2A
+#define ST7789H2_RASET              0x2B
+#define ST7789H2_VSCRDEF            0x33 /* Vertical Scroll Definition */
+#define ST7789H2_VSCSAD             0x37 /* Vertical Scroll Start Address of RAM */
+#define ST7789H2_TEARING_EFFECT     0x35
+#define ST7789H2_NORMAL_DISPLAY     0x36
+#define ST7789H2_IDLE_MODE_OFF      0x38
+#define ST7789H2_IDLE_MODE_ON       0x39
+#define ST7789H2_COLOR_MODE         0x3A
+#define ST7789H2_PORCH_CTRL         0xB2
+#define ST7789H2_GATE_CTRL          0xB7
+#define ST7789H2_VCOM_SET           0xBB
+#define ST7789H2_DISPLAY_OFF        0xBD
+#define ST7789H2_LCM_CTRL           0xC0
+#define ST7789H2_VDV_VRH_EN         0xC2
+#define ST7789H2_VDV_SET            0xC4
+#define ST7789H2_VCOMH_OFFSET_SET   0xC5
+#define ST7789H2_FR_CTRL            0xC6
+#define ST7789H2_POWER_CTRL         0xD0
+#define ST7789H2_PV_GAMMA_CTRL      0xE0
+#define ST7789H2_NV_GAMMA_CTRL      0xE1
+
+
+/*
+ *  ポリゴンポイント定義
+ */
+typedef struct
+{
+	int16_t X;
+	int16_t Y;
+}Point, *pPoint;
+
+
+#define  LCD_ORIENTATION_PORTRAIT         ((uint8_t)0x00)  /*!< Portrait orientation choice of LCD screen  */
+#define  LCD_ORIENTATION_LANDSCAPE        ((uint8_t)0x01)  /*!< Landscape orientation choice of LCD screen */
+#define  LCD_ORIENTATION_LANDSCAPE_ROT180 ((uint32_t)0x02) /*!< Landscape rotated 180ｰ orientation choice of LCD screen */
+
+
+/**
+  * @brief  LCD color
+  */
+#define LCD_COLOR_BLUE          ((uint16_t)0x001F)
+#define LCD_COLOR_GREEN         ((uint16_t)0x07E0)
+#define LCD_COLOR_RED           ((uint16_t)0xF800)
+#define LCD_COLOR_CYAN          ((uint16_t)0x07FF)
+#define LCD_COLOR_MAGENTA       ((uint16_t)0xF81F)
+#define LCD_COLOR_YELLOW        ((uint16_t)0xFFE0)
+#define LCD_COLOR_LIGHTBLUE     ((uint16_t)0x841F)
+#define LCD_COLOR_LIGHTGREEN    ((uint16_t)0x87F0)
+#define LCD_COLOR_LIGHTRED      ((uint16_t)0xFC10)
+#define LCD_COLOR_LIGHTMAGENTA  ((uint16_t)0xFC1F)
+#define LCD_COLOR_LIGHTYELLOW   ((uint16_t)0xFFF0)
+#define LCD_COLOR_DARKBLUE      ((uint16_t)0x0010)
+#define LCD_COLOR_DARKGREEN     ((uint16_t)0x0400)
+#define LCD_COLOR_DARKRED       ((uint16_t)0x8000)
+#define LCD_COLOR_DARKCYAN      ((uint16_t)0x0410)
+#define LCD_COLOR_DARKMAGENTA   ((uint16_t)0x8010)
+#define LCD_COLOR_DARKYELLOW    ((uint16_t)0x8400)
+#define LCD_COLOR_WHITE         ((uint16_t)0xFFFF)
+#define LCD_COLOR_LIGHTGRAY     ((uint16_t)0xD69A)
+#define LCD_COLOR_GRAY          ((uint16_t)0x8410)
+#define LCD_COLOR_DARKGRAY      ((uint16_t)0x4208)
+#define LCD_COLOR_BLACK         ((uint16_t)0x0000)
+#define LCD_COLOR_BROWN         ((uint16_t)0xA145)
+#define LCD_COLOR_ORANGE        ((uint16_t)0xFD20)
+
+
+/*
+ *  LCDハンドラ構造体定義
+ */
+typedef struct
+{
+	uint32_t                fmc_base;	/* FMCベースアドレス */
+	uint16_t                _width;		/* 幅ピクセル数 */
+	uint16_t				_height;	/* 高さピクセル数 */
+	uint16_t                winXstart;	/* Windows X start */
+	uint16_t                winYstart;	/* Windows Y start */
+	uint16_t                winXend;	/* Windows X end */
+	uint16_t                winYend;	/* Windows Y end */
+
+	uint32_t                rst_clk;	/* RESET CLOCK BIT */
+	uint32_t                te_clk;		/* LCD tearing effect CLOCK BIT */
+	uint32_t                bl_clk;		/* LCD Backlight control CLOCK BIT */
+	uint32_t                rst_base;	/* RESET PORT */
+	uint32_t                te_base;	/* LCD tearing effect PORT */
+	uint32_t                bl_base;	/* LCD Backlight control PORT */
+	uint32_t                gpio_speed;	/* GPIO SPEED */
+	uint32_t                rst_pull;	/* RESET PULL TYPE */
+	uint32_t                bl_pull;	/* LCD Backlight control PULL TYPE */
+	uint8_t                 rst_pin;	/* RESET PIN */
+	uint8_t                 te_pin;		/* LCD tearing effect PIN */
+	uint8_t                 bl_pin;		/* LCD Backlight control PIN */
+	uint8_t                 bl_active;
+}LCD_Handler_t;
+
+/**
+  * @}
+  */
+typedef struct 
+{
+	LCD_Handler_t           *hlcd;
+	uint32_t                TextColor;
+	uint32_t                BackColor;
+	void                    *pFont;
+}LCD_DrawProp_t;
+
+
+extern ER lcd_init(LCD_Handler_t *hlcd, uint32_t orientation);
+extern ER lcd_deinit(LCD_Handler_t *hlcd);
+
+extern ER lcd_layerdefaultinit(LCD_Handler_t *hlcd, LCD_DrawProp_t *pDrawProp, uint16_t LayerIndex, uint32_t FB_Address);
+extern void lcd_setAddrWindow(LCD_Handler_t *hlcd, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
+extern void lcd_clear(LCD_Handler_t *hlcd, uint16_t Color);
+extern uint16_t lcd_readPixel(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos);
+extern void lcd_drawPixel(LCD_Handler_t *hlcd, int16_t x, int16_t y, uint16_t color);
+extern void lcd_drawFastHLine(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint16_t Length, uint32_t color);
+extern void lcd_drawFastVLine(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint16_t Length, uint32_t color);
+extern void lcd_drawBitmap(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint8_t *pbmp);
+extern void lcd_drawRGBImage(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint16_t Xsize, uint16_t Ysize, uint8_t *pdata);
+extern void lcd_displayOn(LCD_Handler_t *hlcd);
+extern void lcd_displayOff(LCD_Handler_t *hlcd);
+extern void lcd_fillRect(LCD_Handler_t *hlcd, uint16_t Xpos, uint16_t Ypos, uint16_t Width, uint16_t Height, uint32_t color);
+
+extern void lcd_drawLine(LCD_DrawProp_t *pDrawProp, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
+extern void lcd_drawRect(LCD_DrawProp_t *pDrawProp, uint16_t Xpos, uint16_t Ypos, uint16_t Width, uint16_t Height);
+extern void lcd_DrawCircle(LCD_DrawProp_t *pDrawProp, uint16_t Xpos, uint16_t Ypos, uint16_t Radius);
+extern void lcd_drawPolygon(LCD_DrawProp_t *pDrawProp, pPoint Points, uint16_t PointCount);
+extern void lcd_DrawEllipse(LCD_DrawProp_t *pDrawProp, int Xpos, int Ypos, int XRadius, int YRadius);
+extern void lcd_fillCircle(LCD_DrawProp_t *pDrawProp, uint16_t Xpos, uint16_t Ypos, uint16_t Radius);
+extern void lcd_fillEllipse(LCD_DrawProp_t *pDrawProp, int Xpos, int Ypos, int XRadius, int YRadius);
+extern void lcd_fillPolygon(LCD_DrawProp_t *pDrawProp, pPoint Points, uint16_t PointCount);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _STLCD_ST7789H2_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stts_ft06x06/Makefile.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stts_ft06x06/Makefile.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stts_ft06x06/Makefile.config	(revision 453)
@@ -0,0 +1,55 @@
+#
+#   TOPPERS/ASP/FMP Kernel
+#       Toyohashi Open Platform for Embedded Real-Time Systems/
+#       Advanced Standard Profile Kernel
+#
+#   Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                               Toyohashi Univ. of Technology, JAPAN
+#   Copyright (C) 2003-2008 by Ryosuke Takeuchi
+#                Platform Development Center RICOH COMPANY,LTD. JAPAN
+#   Copyright (C) 2015-2018 by TOPPERS PROJECT Educational Working Group.
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+ 
+#
+#  Makefile のプロセッサ依存 (stts_ft06x06用)
+#
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/gdic/stts_ft06x06
+
+#
+#  USB DEVICE(GDIC)に関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR):$(SRCDIR)/gdic/stts_ft06x06
+SYSSVC_COBJS := $(SYSSVC_COBJS) stts_ft06x06.o
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stts_ft06x06/stts_ft06x06.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stts_ft06x06/stts_ft06x06.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stts_ft06x06/stts_ft06x06.c	(revision 453)
@@ -0,0 +1,650 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/**
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+
+/* Includes ------------------------------------------------------------------*/
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <sil.h>
+#include <target_syssvc.h>
+#include "device.h"
+#include "i2c.h"
+#include "stts_ft06x06.h"
+
+#define sil_orw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) | (b))
+
+/**
+  * @brief TouchScreen FT6206 Slave I2C address
+  */
+#define TS_I2C_ADDRESS                   ((uint16_t)0x70)
+
+
+/* Table for touchscreen event information display on LCD : table indexed on enum @ref TS_TouchEventTypeDef information */
+char * ts_event_string_tab[TOUCH_EVENT_NB_MAX] = { "None",
+                                                   "Press down",
+                                                   "Lift up",
+                                                   "Contact"
+                                                  };
+
+/* Table for touchscreen gesture Id information display on LCD : table indexed on enum @ref TS_GestureIdTypeDef information */
+char * ts_gesture_id_string_tab[GEST_ID_NB_MAX] = { "None",
+                                                    "Move Up",
+                                                    "Move Right",
+                                                    "Move Down",
+                                                    "Move Left",
+                                                    "Zoom In",
+                                                    "Zoom Out"
+                                                  };
+
+
+
+
+/* Private functions prototypes-----------------------------------------------*/
+/**
+  * @}
+  */
+
+/** @defgroup ft6x06_Private_Functions ft6x06 Private Functions
+  * @{
+  */
+
+/**
+  * @brief  Read the ft6x06 device ID, pre initialize I2C in case of need to be
+  *         able to read the FT6206 device ID, and verify this is a FT6206.
+  * @param  DeviceAddr: I2C FT6x06 Slave address.
+  * @retval The Device ID (two bytes).
+  */
+static ER
+ft6x06_ReadID(TouchScreen_Handle_t *hts, uint8_t *ts_id)
+{
+	uint8_t read_value = 0;
+	ER ercd = E_OK;
+
+	ercd = i2c_memread(hts->hi2c, hts->I2C_Address, (uint16_t)FT6206_CHIP_ID_REG, I2C_MEMADD_SIZE_8BIT, (uint8_t*)&read_value, 1, 1000);
+	*ts_id = read_value;
+	return ercd;
+}
+
+/**
+  * @brief  Return if there is touches detected or not.
+  *         Try to detect new touches and forget the old ones (reset internal global
+  *         variables).
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @retval : Number of active touches detected (can be 0, 1 or 2).
+  */
+static ER_UINT
+ft6x06_TS_DetectTouch(TouchScreen_Handle_t *hts)
+{
+	ER ercd = E_OK;
+	volatile uint8_t nbTouch = 0;
+
+	/* Read register FT6206_TD_STAT_REG to check number of touches detection */
+	ercd = i2c_memread(hts->hi2c, hts->I2C_Address, (uint16_t)FT6206_TD_STAT_REG, I2C_MEMADD_SIZE_8BIT, (uint8_t*)&nbTouch, 1, 1000);
+	/* Check the communication status */
+	if(ercd != E_OK)
+		return ercd;
+
+	nbTouch &= FT6206_TD_STAT_MASK;
+
+	if(nbTouch > FT6206_MAX_DETECTABLE_TOUCH){
+		/* If invalid number of touch detected, set it to zero */
+		nbTouch = 0;
+	}
+
+	/* Update ft6x06 driver internal global : current number of active touches */
+	hts->currActiveTouchNb = nbTouch;
+
+	/* Reset current active touch index on which to work on */
+	hts->currActiveTouchIdx = 0;
+	return nbTouch;
+}
+
+/**
+  * @brief  Get the touch screen X and Y positions values
+  *         Manage multi touch thanks to touch Index global
+  *         variable 'ft6x06_handle.currActiveTouchIdx'.
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @param  X: Pointer to X position value
+  * @param  Y: Pointer to Y position value
+  * @retval None.
+  */
+static ER
+ft6x06_TS_GetXY(TouchScreen_Handle_t *hts, uint16_t *X, uint16_t *Y)
+{
+	uint8_t regAddress = 0;
+	uint8_t  dataxy[4];
+	ER ercd = E_OK;
+
+	if(hts->currActiveTouchIdx < hts->currActiveTouchNb){
+		switch(hts->currActiveTouchIdx){
+		case 0 :
+			regAddress = FT6206_P1_XH_REG;
+			break;
+		case 1 :
+			regAddress = FT6206_P2_XH_REG; 
+			break;
+
+		default :
+			break;
+ 		}
+
+		/* Read X and Y positions */
+		ercd = i2c_memread(hts->hi2c, hts->I2C_Address, (uint16_t)regAddress, I2C_MEMADD_SIZE_8BIT, dataxy, sizeof(dataxy), 1000);
+		if(ercd != E_OK)
+			return ercd;
+		/* Send back ready X position to caller */
+		*X = ((dataxy[0] & FT6206_MSB_MASK) << 8) | (dataxy[1] & FT6206_LSB_MASK);
+
+		/* Send back ready Y position to caller */
+		*Y = ((dataxy[2] & FT6206_MSB_MASK) << 8) | (dataxy[3] & FT6206_LSB_MASK);
+		hts->currActiveTouchIdx++;
+	}
+	return ercd;
+}
+
+/**** NEW FEATURES enabled when Multi-touch support is enabled ****/
+
+#if (TS_MULTI_TOUCH_SUPPORTED == 1)
+/**
+  * @brief  Get the touch detailed informations on touch number 'touchIdx' (0..1)
+  *         This touch detailed information contains :
+  *         - weight that was applied to this touch
+  *         - sub-area of the touch in the touch panel
+  *         - event of linked to the touch (press down, lift up, ...)
+  * @param  DeviceAddr: Device address on communication Bus (I2C slave address of FT6x06).
+  * @param  touchIdx : Passed index of the touch (0..1) on which we want to get the
+  *                    detailed information.
+  * @param  pWeight : Pointer to to get the weight information of 'touchIdx'.
+  * @param  pArea   : Pointer to to get the sub-area information of 'touchIdx'.
+  * @param  pEvent  : Pointer to to get the event information of 'touchIdx'.
+
+  * @retval None.
+  */
+static ER
+ft6x06_TS_GetTouchInfo(TouchScreen_Handle_t *hts,
+                            uint32_t   touchIdx,
+                            uint32_t * pWeight,
+                            uint32_t * pArea,
+                            uint32_t * pEvent)
+{
+	uint8_t regAddress = 0;
+	uint8_t dataxy[3];
+	ER ercd = E_OK;
+
+	if(touchIdx < hts->currActiveTouchNb){
+		switch(touchIdx){
+		case 0 :
+			regAddress = FT6206_P1_WEIGHT_REG;
+			break;
+		case 1 :
+			regAddress = FT6206_P2_WEIGHT_REG;
+			break;
+		default :
+			break;
+		} /* end switch(touchIdx) */
+
+		/* Read weight, area and Event Id of touch index */
+		ercd = i2c_memread(hts->hi2c, hts->I2C_Address, (uint16_t)regAddress, I2C_MEMADD_SIZE_8BIT, dataxy, sizeof(dataxy), 1000);
+
+		/* Return weight of touch index */
+		*pWeight = (dataxy[0] & FT6206_TOUCH_WEIGHT_MASK) >> FT6206_TOUCH_WEIGHT_SHIFT;
+		/* Return area of touch index */
+		*pArea = (dataxy[1] & FT6206_TOUCH_AREA_MASK) >> FT6206_TOUCH_AREA_SHIFT;
+		/* Return Event Id  of touch index */
+		*pEvent = (dataxy[2] & FT6206_TOUCH_EVT_FLAG_MASK) >> FT6206_TOUCH_EVT_FLAG_SHIFT;
+	} /* of if(touchIdx < ft6x06_handle.currActiveTouchNb) */
+	return ercd;
+}
+
+#endif /* TS_MULTI_TOUCH_SUPPORTED == 1 */
+
+#if (TS_AUTO_CALIBRATION_SUPPORTED == 1)
+/**
+  * @brief  Start TouchScreen calibration phase
+  * @param  DeviceAddr: FT6206 Device address for communication on I2C Bus.
+  * @retval Status FT6206_STATUS_OK or FT6206_STATUS_NOT_OK.
+  */
+static ER
+ft6x06_TS_Calibration(TouchScreen_Handle_t *hts)
+{
+	uint32_t nbAttempt = 0;
+	volatile uint8_t ucReadData;
+	volatile uint8_t regValue;
+	uint8_t bEndCalibration = 0;
+	ER ercd = E_OK;
+
+	/* >> Calibration sequence start */
+
+	/* Switch FT6206 back to factory mode to calibrate */
+	regValue = (FT6206_DEV_MODE_FACTORY & FT6206_DEV_MODE_MASK) << FT6206_DEV_MODE_SHIFT;
+	ercd = i2c_memwrite(hts->hi2c, hts->I2C_Address, (uint16_t)FT6206_DEV_MODE_REG, I2C_MEMADD_SIZE_8BIT, (uint8_t*)&regValue, 1, 1000);
+	if(ercd != E_OK)
+		return ercd;
+
+	/* Read back the same register FT6206_DEV_MODE_REG */
+	ercd = i2c_memread(hts->hi2c, hts->I2C_Address, (uint16_t)FT6206_GEST_ID_REG, I2C_MEMADD_SIZE_8BIT, (uint8_t*)&ucReadData, 1, 1000);
+	if(ercd != E_OK)
+		return ercd;
+
+	dly_tsk(300);	/* Wait 300 ms */
+
+	if(((ucReadData & (FT6206_DEV_MODE_MASK << FT6206_DEV_MODE_SHIFT)) >> FT6206_DEV_MODE_SHIFT) != FT6206_DEV_MODE_FACTORY ){
+		/* Return error to caller */
+		return E_OBJ;
+	}
+
+	/* Start calibration command */
+	regValue = 0x04;
+	ercd = i2c_memwrite(hts->hi2c, hts->I2C_Address, (uint16_t)FT6206_TD_STAT_REG, I2C_MEMADD_SIZE_8BIT, (uint8_t*)&regValue, 1, 1000);
+	if(ercd != E_OK)
+		return ercd;
+
+	dly_tsk(300);	/* Wait 300 ms */
+
+	/* 100 attempts to wait switch from factory mode (calibration) to working mode */
+	for (nbAttempt=0; ((nbAttempt < 100) && (!bEndCalibration)) ; nbAttempt++){
+		ercd = i2c_memread(hts->hi2c, hts->I2C_Address, (uint16_t)FT6206_DEV_MODE_REG, I2C_MEMADD_SIZE_8BIT, (uint8_t*)&ucReadData, 1, 1000);
+		if(ercd != E_OK)
+			return ercd;
+
+		ucReadData = (ucReadData & (FT6206_DEV_MODE_MASK << FT6206_DEV_MODE_SHIFT)) >> FT6206_DEV_MODE_SHIFT;
+		if(ucReadData == FT6206_DEV_MODE_WORKING){
+			/* Auto Switch to FT6206_DEV_MODE_WORKING : means calibration have ended */
+			bEndCalibration = 1; /* exit for loop */
+		}
+		dly_tsk(200);	/* Wait 200 ms */
+	}
+
+	/* Calibration sequence end << */
+	return ercd;
+}
+#endif /* TS_AUTO_CALIBRATION_SUPPORTED == 1 */
+
+/**
+  * @brief  Initializes and configures the touch screen functionalities and
+  *         configures all necessary hardware resources (GPIOs, I2C, clocks..)
+  *         with a given orientation
+  * @param  ts_SizeX : Maximum X size of the TS area on LCD
+  * @param  ts_SizeY : Maximum Y size of the TS area on LCD
+  * @param  orientation : TS_ORIENTATION_LANDSCAPE or TS_ORIENTATION_PORTRAIT
+  * @retval TS_OK if all initializations are OK. Other value if error.
+  */
+ER
+touchscreen_init(TouchScreen_Handle_t *hts, uint16_t ts_SizeX, uint16_t ts_SizeY, uint8_t orientation)
+{
+	GPIO_Init_t GPIO_Init_Data;
+	ER ercd = E_OK;
+	uint8_t ts_id = 0;
+
+	/* Note : I2C_Address is un-initialized here, but is not used at all in init function */
+	/* but the prototype of Init() is like that in template and should be respected       */
+
+	/* Initialize the communication channel to sensor (I2C) if necessary */
+	/* that is initialization is done only once after a power up         */
+	hts->tsOrientation = TS_SWAP_NONE;
+	if(hts->I2C_Address == 0)
+		hts->I2C_Address   = TS_I2C_ADDRESS;
+	hts->initialized   = false;
+	if(hts->pcb->reset_gpio_base){
+		sil_orw_mem((uint32_t *)(hts->pcb->reset_clk_base), hts->pcb->reset_clk_bit);
+		GPIO_Init_Data.mode  = hts->pcb->reset_gpio_mode;
+		GPIO_Init_Data.otype = hts->pcb->reset_gpio_otype;
+		GPIO_Init_Data.pull  = hts->pcb->reset_gpio_pull;
+		GPIO_Init_Data.speed = hts->pcb->reset_gpio_speed;
+		gpio_setup(hts->pcb->reset_gpio_base, &GPIO_Init_Data, hts->pcb->reset_gpio_pinno);
+		if(hts->pcb->reset_gpio_release == 0)
+			sil_wrw_mem((uint32_t *)(hts->pcb->reset_gpio_base+TOFF_GPIO_BSRR), (1<<hts->pcb->reset_gpio_pinno)<<16);
+		else
+			sil_wrw_mem((uint32_t *)(hts->pcb->reset_gpio_base+TOFF_GPIO_BSRR), (1<<hts->pcb->reset_gpio_pinno));
+	}
+
+	/* Scan FT6x36 TouchScreen IC controller ID register by I2C Read */
+	/* Verify this is a FT6x36, otherwise this is an error case      */
+	ercd = ft6x06_ReadID(hts, &ts_id);
+	if(ercd != E_OK)
+		return ercd;
+	if(ts_id == FT6x36_ID_VALUE){
+		/* Found FT6x36 : Initialize the TS driver structure */
+		/* Get LCD chosen orientation */
+		if(orientation == TS_ORIENTATION_PORTRAIT){
+			hts->tsOrientation = TS_SWAP_X | TS_SWAP_Y;               
+		}
+		else if(orientation == TS_ORIENTATION_LANDSCAPE_ROT180){
+			hts->tsOrientation = TS_SWAP_XY;
+		}
+		else{
+			hts->tsOrientation = TS_SWAP_XY | TS_SWAP_Y;                 
+		}
+		hts->max_width  = FT_6206_MAX_WIDTH_HEIGHT;
+		hts->max_height = FT_6206_MAX_WIDTH_HEIGHT;
+	}
+	/* Scan FT6xx6 TouchScreen IC controller ID register by I2C Read       */
+	/* Verify this is a FT6206 or FT6336G, otherwise this is an error case */
+	else if(ts_id == FT6206_ID_VALUE){
+		/* Found FT6206 : Initialize the TS driver structure */
+		/* Get LCD chosen orientation */
+		if(ts_SizeX < ts_SizeY){
+			hts->tsOrientation = TS_SWAP_NONE;
+		}
+		else{
+			hts->tsOrientation = TS_SWAP_XY | TS_SWAP_Y;
+		}
+		hts->max_width  = FT_6206_MAX_WIDTH;
+		hts->max_height = FT_6206_MAX_HEIGHT;
+	}
+
+	if(ercd == E_OK){
+		/* Software reset the TouchScreen */
+		/* Calibrate, Configure and Start the TouchScreen driver */
+#if (TS_AUTO_CALIBRATION_SUPPORTED == 1)
+		/* Hw Calibration sequence start : should be done once after each power up */
+		/* This is called internal calibration of the touch screen                 */
+		ft6x06_TS_Calibration(hts);
+#endif
+
+		/* By default set FT6206 IC in Polling mode : no INT generation on FT6206 for new touch available */
+		/* Note TS_INT is active low                                                                      */
+		ercd = touchscreen_disable_it(hts);
+			/* Configure Interrupt mode for TS_INT pin falling edge : when a new touch is available */
+			/* TS_INT pin is active on low level on new touch available */
+		if(ercd == E_OK && hts->pcb->int_gpio_base != 0){
+			exti_func[hts->pcb->int_gpio_pinno] = hts->ifunc;
+			sil_orw_mem((uint32_t *)hts->pcb->int_clk_base, hts->pcb->int_clk_bit);
+			GPIO_Init_Data.mode      = hts->pcb->int_gpio_mode;
+			GPIO_Init_Data.pull      = hts->pcb->int_gpio_pull;
+			GPIO_Init_Data.speed     = hts->pcb->int_gpio_speed;
+			gpio_setup(hts->pcb->int_gpio_base, &GPIO_Init_Data, hts->pcb->int_gpio_pinno);
+			if(hts->enable_it)
+				ercd = touchscreen_enable_it(hts);
+		}
+		if(ercd == E_OK)
+			hts->initialized = true;
+	}
+	return (ercd);
+}
+
+/**
+  * @brief  Returns status and positions of the touch screen.
+  * @param  TS_State: Pointer to touch screen current state structure
+  * @retval TS_OK if all initializations are OK. Other value if error.
+  */
+ER
+touchscreen_getstate(TouchScreen_Handle_t *hts, TS_StateTypeDef *TS_State)
+{
+	static uint32_t _x[TS_MAX_NB_TOUCH] = {0, 0};
+	static uint32_t _y[TS_MAX_NB_TOUCH] = {0, 0};
+	uint16_t tmp;
+	uint16_t Raw_x[TS_MAX_NB_TOUCH];
+	uint16_t Raw_y[TS_MAX_NB_TOUCH];
+	uint16_t xDiff;
+	uint16_t yDiff;
+	uint32_t index;
+#if (TS_MULTI_TOUCH_SUPPORTED == 1)
+	uint32_t weight = 0;
+	uint32_t area = 0;
+	uint32_t event = 0;
+#endif /* TS_MULTI_TOUCH_SUPPORTED == 1 */
+	ER ercd = E_OK;
+
+	/* Check and update the number of touches active detected */
+	ercd = ft6x06_TS_DetectTouch(hts);
+	if(ercd < 0)
+		return ercd;
+	if((TS_State->touchDetected = (uint8_t)ercd)){
+		for(index=0; index < TS_State->touchDetected; index++){
+			/* Get each touch coordinates */
+			ft6x06_TS_GetXY(hts, &(Raw_x[index]), &(Raw_y[index]));
+
+			if(hts->tsOrientation & TS_SWAP_XY){
+				tmp = Raw_x[index];
+				Raw_x[index] = Raw_y[index];
+				Raw_y[index] = tmp;
+			}
+			if(hts->tsOrientation & TS_SWAP_X){
+				Raw_x[index] = hts->max_width - 1 - Raw_x[index];
+			}
+			if(hts->tsOrientation & TS_SWAP_Y){
+				Raw_y[index] = hts->max_height - 1 - Raw_y[index];
+			}
+
+			xDiff = Raw_x[index] > _x[index]? (Raw_x[index] - _x[index]): (_x[index] - Raw_x[index]);
+			yDiff = Raw_y[index] > _y[index]? (Raw_y[index] - _y[index]): (_y[index] - Raw_y[index]);
+
+			if((xDiff + yDiff) > 5){
+				_x[index] = Raw_x[index];
+				_y[index] = Raw_y[index];
+			}
+
+			TS_State->touchX[index] = _x[index];
+			TS_State->touchY[index] = _y[index];
+
+#if (TS_MULTI_TOUCH_SUPPORTED == 1)
+
+			/* Get touch info related to the current touch */
+			ercd = ft6x06_TS_GetTouchInfo(hts, index, &weight, &area, &event);
+
+			/* Update TS_State structure */
+			TS_State->touchWeight[index] = weight;
+			TS_State->touchArea[index]   = area;
+
+			/* Remap touch event */
+			switch(event){
+			case FT6206_TOUCH_EVT_FLAG_PRESS_DOWN  :
+				TS_State->touchEventId[index] = TOUCH_EVENT_PRESS_DOWN;
+				break;
+			case FT6206_TOUCH_EVT_FLAG_LIFT_UP :
+				TS_State->touchEventId[index] = TOUCH_EVENT_LIFT_UP;
+				break;
+			case FT6206_TOUCH_EVT_FLAG_CONTACT :
+				TS_State->touchEventId[index] = TOUCH_EVENT_CONTACT;
+				break;
+			case FT6206_TOUCH_EVT_FLAG_NO_EVENT :
+				TS_State->touchEventId[index] = TOUCH_EVENT_NO_EVT;
+				break;
+			 default :
+				ercd = E_SYS;
+				break;
+			} /* of switch(event) */
+			if(ercd < 0)
+				return ercd;
+
+#endif /* TS_MULTI_TOUCH_SUPPORTED == 1 */
+
+		} /* of for(index=0; index < TS_State->touchDetected; index++) */
+
+#if (TS_MULTI_TOUCH_SUPPORTED == 1)
+		/* Get gesture Id */
+		ercd = touchscreen_get_gestureid(hts, TS_State);
+#endif /* TS_MULTI_TOUCH_SUPPORTED == 1 */
+
+	} /* end of if(TS_State->touchDetected != 0) */
+	return ercd;
+}
+
+/**
+  * @brief  Configure the FT6206 device to generate IT on given INT pin
+  *         connected to MCU as EXTI.
+  * @param  DeviceAddr: Device address on communication Bus (Slave I2C address of FT6206).
+  * @retval None
+  */
+ER
+touchscreen_enable_it(TouchScreen_Handle_t *hts)
+{
+	ER ercd;
+	uint8_t regValue = 0;
+	regValue = (FT6206_G_MODE_INTERRUPT_TRIGGER & (FT6206_G_MODE_INTERRUPT_MASK >> FT6206_G_MODE_INTERRUPT_SHIFT)) << FT6206_G_MODE_INTERRUPT_SHIFT;
+
+	/* Set interrupt trigger mode in FT6206_GMODE_REG */
+	ercd = i2c_memwrite(hts->hi2c, hts->I2C_Address, (uint16_t)FT6206_GMODE_REG, I2C_MEMADD_SIZE_8BIT, (uint8_t*)&regValue, 1, 1000);
+	return ercd;
+}
+
+/**
+  * @brief  Configure the FT6206 device to stop generating IT on the given INT pin
+  *         connected to MCU as EXTI.
+  * @param  DeviceAddr: Device address on communication Bus (Slave I2C address of FT6206).
+  * @retval None
+  */
+ER touchscreen_disable_it(TouchScreen_Handle_t *hts)
+{
+	ER  ercd;
+	uint8_t regValue = 0;
+	regValue = (FT6206_G_MODE_INTERRUPT_POLLING | (FT6206_G_MODE_INTERRUPT_MASK >> FT6206_G_MODE_INTERRUPT_SHIFT)) << FT6206_G_MODE_INTERRUPT_SHIFT;
+
+	/* Set interrupt polling mode in FT6206_GMODE_REG */
+	ercd = i2c_memwrite(hts->hi2c, hts->I2C_Address, (uint16_t)FT6206_GMODE_REG, I2C_MEMADD_SIZE_8BIT, (uint8_t*)&regValue, 1, 1000);
+	return ercd;
+}
+
+#if (TS_MULTI_TOUCH_SUPPORTED == 1)
+/**
+  * @brief  Update gesture Id following a touch detected.
+  * @param  TS_State: Pointer to touch screen current state structure
+  * @retval TS_OK if all initializations are OK. Other value if error.
+  */
+ER
+touchscreen_get_gestureid(TouchScreen_Handle_t *hts, TS_StateTypeDef *TS_State)
+{
+	uint32_t gestureId = 0;
+	volatile uint8_t ucReadData = 0;
+	ER ercd = E_OK;
+
+	/* Get gesture Id */
+	ercd = i2c_memread(hts->hi2c, hts->I2C_Address, (uint16_t)FT6206_GEST_ID_REG, I2C_MEMADD_SIZE_8BIT, (uint8_t*)&ucReadData, 1, 1000);
+	if(ercd != E_OK)
+		return ercd;
+
+	gestureId = hts->I2C_Address;
+
+	/* Remap gesture Id to a TS_GestureIdTypeDef value */
+	switch(gestureId){
+	case FT6206_GEST_ID_NO_GESTURE :
+		TS_State->gestureId = GEST_ID_NO_GESTURE;
+		break;
+	case FT6206_GEST_ID_MOVE_UP :
+		TS_State->gestureId = GEST_ID_MOVE_UP;
+		break;
+	case FT6206_GEST_ID_MOVE_RIGHT :
+		TS_State->gestureId = GEST_ID_MOVE_RIGHT;
+		break;
+	case FT6206_GEST_ID_MOVE_DOWN :
+		TS_State->gestureId = GEST_ID_MOVE_DOWN;
+		break;
+	case FT6206_GEST_ID_MOVE_LEFT :
+		TS_State->gestureId = GEST_ID_MOVE_LEFT;
+		break;
+	case FT6206_GEST_ID_ZOOM_IN :
+		TS_State->gestureId = GEST_ID_ZOOM_IN;
+		break;
+	case FT6206_GEST_ID_ZOOM_OUT :
+		TS_State->gestureId = GEST_ID_ZOOM_OUT;
+		break;
+	default :
+		ercd = E_OBJ;
+		break;
+	} /* of switch(gestureId) */
+	return ercd;
+}
+#endif /* TS_MULTI_TOUCH_SUPPORTED == 1 */
+
+
+/** @defgroup STM32F723E-DISCOVERY_TS_Private_Functions TS Private Functions
+  * @{
+  */
+
+#if (TS_MULTI_TOUCH_SUPPORTED == 1)
+/**
+  * @brief  Function used to reset all touch data before a new acquisition
+  *         of touch information.
+  * @param  TS_State: Pointer to touch screen current state structure
+  * @retval TS_OK if OK, TE_ERROR if problem found.
+  */
+ER
+touchscreen_reset_data(TS_StateTypeDef *TS_State)
+{
+	uint32_t index;
+
+	if(TS_State != (TS_StateTypeDef *)NULL){
+		TS_State->gestureId = GEST_ID_NO_GESTURE;
+		TS_State->touchDetected = 0;
+
+		for(index = 0; index < TS_MAX_NB_TOUCH; index++){
+			TS_State->touchX[index]       = 0;
+			TS_State->touchY[index]       = 0;
+			TS_State->touchArea[index]    = 0;
+			TS_State->touchEventId[index] = TOUCH_EVENT_NO_EVT;
+			TS_State->touchWeight[index]  = 0;
+		}
+		return E_OK;
+	}
+	else
+		return E_PAR;
+}
+#endif /* TS_MULTI_TOUCH_SUPPORTED == 1 */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stts_ft06x06/stts_ft06x06.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stts_ft06x06/stts_ft06x06.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stts_ft06x06/stts_ft06x06.h	(revision 453)
@@ -0,0 +1,400 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/**
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+#ifndef _STTS_FT06X06_H_
+#define _STTS_FT06X06_H_
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include "device.h"
+#include "i2c.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Set Multi-touch as non supported */
+#ifndef TS_MULTI_TOUCH_SUPPORTED
+  #define TS_MULTI_TOUCH_SUPPORTED 0
+#endif
+
+/* Set Auto-calibration as non supported */
+#ifndef TS_AUTO_CALIBRATION_SUPPORTED
+  #define TS_AUTO_CALIBRATION_SUPPORTED 0
+#endif
+
+  /* Maximum border values of the touchscreen pad */
+#define  FT_6206_MAX_WIDTH              ((uint16_t)800)     /* Touchscreen pad max width   */
+#define  FT_6206_MAX_HEIGHT             ((uint16_t)480)     /* Touchscreen pad max height  */
+
+  /* Touchscreen pad max width and height values for FT6x36 Touch*/
+#define  FT_6206_MAX_WIDTH_HEIGHT       ((uint16_t)240)     
+
+  /* Max detectable simultaneous touches */
+#define FT6206_MAX_DETECTABLE_TOUCH     2
+
+  /**
+   * @brief : Definitions for FT6206 I2C register addresses on 8 bit
+   **/
+
+  /* Current mode register of the FT6206 (R/W) */
+#define FT6206_DEV_MODE_REG             0x00
+
+  /* Possible values of FT6206_DEV_MODE_REG */
+#define FT6206_DEV_MODE_WORKING         0x00
+#define FT6206_DEV_MODE_FACTORY         0x04
+
+#define FT6206_DEV_MODE_MASK            0x7
+#define FT6206_DEV_MODE_SHIFT           4
+
+  /* Gesture ID register */
+#define FT6206_GEST_ID_REG              0x01
+
+  /* Possible values of FT6206_GEST_ID_REG */
+#define FT6206_GEST_ID_NO_GESTURE       0x00
+#define FT6206_GEST_ID_MOVE_UP          0x10
+#define FT6206_GEST_ID_MOVE_RIGHT       0x14
+#define FT6206_GEST_ID_MOVE_DOWN        0x18
+#define FT6206_GEST_ID_MOVE_LEFT        0x1C
+#define FT6206_GEST_ID_ZOOM_IN          0x48
+#define FT6206_GEST_ID_ZOOM_OUT         0x49
+
+  /* Touch Data Status register : gives number of active touch points (0..2) */
+#define FT6206_TD_STAT_REG              0x02
+
+  /* Values related to FT6206_TD_STAT_REG */
+#define FT6206_TD_STAT_MASK             0x0F
+#define FT6206_TD_STAT_SHIFT            0x00
+
+  /* Values Pn_XH and Pn_YH related */
+#define FT6206_TOUCH_EVT_FLAG_PRESS_DOWN 0x00
+#define FT6206_TOUCH_EVT_FLAG_LIFT_UP    0x01
+#define FT6206_TOUCH_EVT_FLAG_CONTACT    0x02
+#define FT6206_TOUCH_EVT_FLAG_NO_EVENT   0x03
+
+#define FT6206_TOUCH_EVT_FLAG_SHIFT     6
+#define FT6206_TOUCH_EVT_FLAG_MASK      (3 << FT6206_TOUCH_EVT_FLAG_SHIFT)
+
+#define FT6206_MSB_MASK                 0x0F
+#define FT6206_MSB_SHIFT                0
+
+  /* Values Pn_XL and Pn_YL related */
+#define FT6206_LSB_MASK                 0xFF
+#define FT6206_LSB_SHIFT                0
+
+#define FT6206_P1_XH_REG                0x03
+#define FT6206_P1_XL_REG                0x04
+#define FT6206_P1_YH_REG                0x05
+#define FT6206_P1_YL_REG                0x06
+
+  /* Touch Pressure register value (R) */
+#define FT6206_P1_WEIGHT_REG            0x07
+
+  /* Values Pn_WEIGHT related  */
+#define FT6206_TOUCH_WEIGHT_MASK        0xFF
+#define FT6206_TOUCH_WEIGHT_SHIFT       0
+
+  /* Touch area register */
+#define FT6206_P1_MISC_REG              0x08
+
+  /* Values related to FT6206_Pn_MISC_REG */
+#define FT6206_TOUCH_AREA_MASK         (0x04 << 4)
+#define FT6206_TOUCH_AREA_SHIFT        0x04
+
+#define FT6206_P2_XH_REG               0x09
+#define FT6206_P2_XL_REG               0x0A
+#define FT6206_P2_YH_REG               0x0B
+#define FT6206_P2_YL_REG               0x0C
+#define FT6206_P2_WEIGHT_REG           0x0D
+#define FT6206_P2_MISC_REG             0x0E
+
+  /* Threshold for touch detection */
+#define FT6206_TH_GROUP_REG            0x80
+
+  /* Values FT6206_TH_GROUP_REG : threshold related  */
+#define FT6206_THRESHOLD_MASK          0xFF
+#define FT6206_THRESHOLD_SHIFT         0
+
+  /* Filter function coefficients */
+#define FT6206_TH_DIFF_REG             0x85
+
+  /* Control register */
+#define FT6206_CTRL_REG                0x86
+
+  /* Values related to FT6206_CTRL_REG */
+
+  /* Will keep the Active mode when there is no touching */
+#define FT6206_CTRL_KEEP_ACTIVE_MODE    0x00
+
+  /* Switching from Active mode to Monitor mode automatically when there is no touching */
+#define FT6206_CTRL_KEEP_AUTO_SWITCH_MONITOR_MODE  0x01
+
+  /* The time period of switching from Active mode to Monitor mode when there is no touching */
+#define FT6206_TIMEENTERMONITOR_REG     0x87
+
+  /* Report rate in Active mode */
+#define FT6206_PERIODACTIVE_REG         0x88
+
+  /* Report rate in Monitor mode */
+#define FT6206_PERIODMONITOR_REG        0x89
+
+  /* The value of the minimum allowed angle while Rotating gesture mode */
+#define FT6206_RADIAN_VALUE_REG         0x91
+
+  /* Maximum offset while Moving Left and Moving Right gesture */
+#define FT6206_OFFSET_LEFT_RIGHT_REG    0x92
+
+  /* Maximum offset while Moving Up and Moving Down gesture */
+#define FT6206_OFFSET_UP_DOWN_REG       0x93
+
+  /* Minimum distance while Moving Left and Moving Right gesture */
+#define FT6206_DISTANCE_LEFT_RIGHT_REG  0x94
+
+  /* Minimum distance while Moving Up and Moving Down gesture */
+#define FT6206_DISTANCE_UP_DOWN_REG     0x95
+
+  /* Maximum distance while Zoom In and Zoom Out gesture */
+#define FT6206_DISTANCE_ZOOM_REG        0x96
+
+  /* High 8-bit of LIB Version info */
+#define FT6206_LIB_VER_H_REG            0xA1
+
+  /* Low 8-bit of LIB Version info */
+#define FT6206_LIB_VER_L_REG            0xA2
+
+  /* Chip Selecting */
+#define FT6206_CIPHER_REG               0xA3
+
+  /* Interrupt mode register (used when in interrupt mode) */
+#define FT6206_GMODE_REG                0xA4
+
+#define FT6206_G_MODE_INTERRUPT_MASK    0x03
+#define FT6206_G_MODE_INTERRUPT_SHIFT   0x00
+
+  /* Possible values of FT6206_GMODE_REG */
+#define FT6206_G_MODE_INTERRUPT_POLLING 0x00
+#define FT6206_G_MODE_INTERRUPT_TRIGGER 0x01
+
+  /* Current power mode the FT6206 system is in (R) */
+#define FT6206_PWR_MODE_REG             0xA5
+
+  /* FT6206 firmware version */
+#define FT6206_FIRMID_REG               0xA6
+
+  /* FT6206 Chip identification register */
+#define FT6206_CHIP_ID_REG              0xA8
+
+  /*  Possible values of FT6206_CHIP_ID_REG */
+#define FT6206_ID_VALUE                 0x11
+#define FT6x36_ID_VALUE                 0xCD
+
+  /* Release code version */
+#define FT6206_RELEASE_CODE_ID_REG      0xAF
+
+  /* Current operating mode the FT6206 system is in (R) */
+#define FT6206_STATE_REG                0xBC
+
+typedef struct _TouchScreen_PortControlBlock{
+	uint32_t        reset_clk_base;
+	uint32_t        reset_clk_bit;
+	uint32_t        reset_gpio_base;
+	uint32_t        reset_gpio_pinno;
+	uint32_t        reset_gpio_mode;
+	uint32_t        reset_gpio_otype;
+	uint32_t        reset_gpio_pull;
+	uint32_t        reset_gpio_speed;
+	uint32_t        reset_gpio_release;
+
+	uint32_t        int_clk_base;
+	uint32_t        int_clk_bit;
+	uint32_t        int_gpio_base;
+	uint32_t        int_gpio_pinno;
+	uint32_t        int_gpio_mode;
+	uint32_t        int_gpio_pull;
+	uint32_t        int_gpio_speed;
+} TS_PortControlBlock;
+
+/** @typedef TouchScreen_Handle_t
+ *  TouchScreen Handle definition.
+ */
+typedef struct
+{
+	I2C_Handle_t    *hi2c;
+	const TS_PortControlBlock *pcb;
+	void            (*ifunc)(void);
+	uint8_t         initialized;
+	uint8_t         enable_it;
+	uint16_t        max_width;
+	uint16_t        max_height;
+	uint8_t         I2C_Address;
+	uint8_t         tsOrientation;
+
+	/* field holding the current number of simultaneous active touches */
+	uint8_t         currActiveTouchNb;
+
+	/* field holding the touch index currently managed */
+	uint8_t         currActiveTouchIdx;
+} TouchScreen_Handle_t;
+
+
+
+/**** NEW FEATURES enabled when Multi-touch support is enabled ****/
+
+/** @brief With FT6206 : maximum 2 touches detected simultaneously
+  */
+#define TS_MAX_NB_TOUCH                 ((uint32_t) FT6206_MAX_DETECTABLE_TOUCH)
+
+#define TS_SWAP_NONE                    ((uint8_t) 0x01)
+#define TS_SWAP_X                       ((uint8_t) 0x02)
+#define TS_SWAP_Y                       ((uint8_t) 0x04)
+#define TS_SWAP_XY                      ((uint8_t) 0x08)
+
+#define TS_ORIENTATION_PORTRAIT         ((uint8_t) 0x00)
+#define TS_ORIENTATION_LANDSCAPE        ((uint8_t) 0x01)
+#define TS_ORIENTATION_LANDSCAPE_ROT180 ((uint8_t) 0x02)
+
+/**
+*  @brief TS_StateTypeDef
+*  Define TS State structure
+*/
+typedef struct
+{
+	uint8_t         touchDetected;				/* Total number of active touches detected at last scan */
+	uint16_t        touchX[TS_MAX_NB_TOUCH];	/* Touch X[0], X[1] coordinates on 12 bits */
+	uint16_t        touchY[TS_MAX_NB_TOUCH];	/* Touch Y[0], Y[1] coordinates on 12 bits */
+
+#if (TS_MULTI_TOUCH_SUPPORTED == 1)
+	uint8_t         touchWeight[TS_MAX_NB_TOUCH];	/* Touch_Weight[0], Touch_Weight[1] : weight property of touches */
+	uint8_t         touchEventId[TS_MAX_NB_TOUCH];	/* Touch_EventId[0], Touch_EventId[1] : take value of type @ref TS_TouchEventTypeDef */
+	uint8_t         touchArea[TS_MAX_NB_TOUCH];		/* Touch_Area[0], Touch_Area[1] : touch area of each touch */
+	uint32_t        gestureId; /*!< type of gesture detected : take value of type @ref TS_GestureIdTypeDef */
+#endif  /* TS_MULTI_TOUCH_SUPPORTED == 1 */
+} TS_StateTypeDef;
+
+/**
+ *  @brief TS_GestureIdTypeDef
+ *  Define Possible managed gesture identification values returned by touch screen
+ *  driver.
+ */
+typedef enum
+{
+  GEST_ID_NO_GESTURE = 0x00, /*!< Gesture not defined / recognized */
+  GEST_ID_MOVE_UP    = 0x01, /*!< Gesture Move Up */
+  GEST_ID_MOVE_RIGHT = 0x02, /*!< Gesture Move Right */
+  GEST_ID_MOVE_DOWN  = 0x03, /*!< Gesture Move Down */
+  GEST_ID_MOVE_LEFT  = 0x04, /*!< Gesture Move Left */
+  GEST_ID_ZOOM_IN    = 0x05, /*!< Gesture Zoom In */
+  GEST_ID_ZOOM_OUT   = 0x06, /*!< Gesture Zoom Out */
+  GEST_ID_NB_MAX     = 0x07 /*!< max number of gesture id */
+} TS_GestureIdTypeDef;
+
+/**
+ *  @brief TS_TouchEventTypeDef
+ *  Define Possible touch events kind as returned values
+ *  by touch screen IC Driver.
+ */
+typedef enum
+{
+  TOUCH_EVENT_NO_EVT        = 0x00, /*!< Touch Event : undetermined */
+  TOUCH_EVENT_PRESS_DOWN    = 0x01, /*!< Touch Event Press Down */
+  TOUCH_EVENT_LIFT_UP       = 0x02, /*!< Touch Event Lift Up */
+  TOUCH_EVENT_CONTACT       = 0x03, /*!< Touch Event Contact */
+  TOUCH_EVENT_NB_MAX        = 0x04  /*!< max number of touch events kind */
+} TS_TouchEventTypeDef;
+
+/**
+ *  @brief Table for touchscreen event information display on LCD :
+ *  table indexed on enum @ref TS_TouchEventTypeDef information
+ */
+extern char * ts_event_string_tab[TOUCH_EVENT_NB_MAX];
+
+/**
+ *  @brief Table for touchscreen gesture Id information display on LCD : table indexed
+ *  on enum @ref TS_GestureIdTypeDef information
+ */
+extern char * ts_gesture_id_string_tab[GEST_ID_NB_MAX];
+
+extern ER touchscreen_init(TouchScreen_Handle_t *hts, uint16_t ts_SizeX, uint16_t ts_SizeY, uint8_t orientation);
+extern ER touchscreen_getstate(TouchScreen_Handle_t *hts, TS_StateTypeDef *TS_State);
+extern ER touchscreen_enable_it(TouchScreen_Handle_t *hts);
+extern ER touchscreen_disable_it(TouchScreen_Handle_t *hts);
+
+#if (TS_MULTI_TOUCH_SUPPORTED == 1)
+extern ER touchscreen_get_gestureid(TouchScreen_Handle_t *hts, TS_StateTypeDef *TS_State);
+extern ER touchscreen_reset_data(TS_StateTypeDef *TS_State);
+#endif /* TS_MULTI_TOUCH_SUPPORTED == 1 */
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _STTS_FT06X06_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stts_ft5336/Makefile.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stts_ft5336/Makefile.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stts_ft5336/Makefile.config	(revision 453)
@@ -0,0 +1,55 @@
+#
+#   TOPPERS/ASP/FMP Kernel
+#       Toyohashi Open Platform for Embedded Real-Time Systems/
+#       Advanced Standard Profile Kernel
+#
+#   Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                               Toyohashi Univ. of Technology, JAPAN
+#   Copyright (C) 2003-2008 by Ryosuke Takeuchi
+#                Platform Development Center RICOH COMPANY,LTD. JAPAN
+#   Copyright (C) 2015-2018 by TOPPERS PROJECT Educational Working Group.
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+ 
+#
+#  Makefile のプロセッサ依存 (stts_ft5336用)
+#
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/gdic/stts_ft5336
+
+#
+#  USB DEVICE(GDIC)に関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR):$(SRCDIR)/gdic/stts_ft5336
+SYSSVC_COBJS := $(SYSSVC_COBJS) stts_ft5336.o
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stts_ft5336/stts_ft5336.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stts_ft5336/stts_ft5336.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stts_ft5336/stts_ft5336.c	(revision 453)
@@ -0,0 +1,574 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/**
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+#include <string.h>
+#include "stts_ft5336.h"
+
+/**
+  * @brief  Reads a single data.
+  * @param  Addr: I2C address
+  * @param  Reg: Reg address
+  * @retval Data to be read
+  */
+static uint8_t
+ft5336_IO_Read(TouchScreen_Handle_t *hts, uint8_t Reg)
+{
+	I2C_Init_t  Init;
+	uint8_t read_value = 0;
+	ER ercd = E_OK;
+
+	ercd = i2c_memread(hts->hi2c, hts->I2C_Address, (uint16_t)Reg, I2C_MEMADD_SIZE_8BIT, &read_value, 1, 1000);
+
+	/* Check the communication status */
+	if(ercd != E_OK){
+		/* De-initialize the I2C communication bus */
+		i2c_deinit(hts->hi2c);
+
+		/* Re-Initialize the I2C communication bus */
+		memcpy(&Init, &hts->hi2c->Init, sizeof(I2C_Init_t));
+		i2c_init(hts->hi2c->i2cid, &Init);
+	}
+	return read_value;
+}
+
+/**
+  * @brief  Read the ft5336 device ID, pre initialize I2C in case of need to be
+  *         able to read the FT5336 device ID, and verify this is a FT5336.
+  * @param  DeviceAddr: I2C FT5336 Slave address.
+  * @retval The Device ID (two bytes).
+  */
+static uint16_t
+ft5336_ReadID(TouchScreen_Handle_t *hts, uint16_t DeviceAddr)
+{
+	volatile uint8_t ucReadId = 0;
+	uint8_t nbReadAttempts = 0;
+	uint8_t bFoundDevice = 0; /* Device not found by default */
+
+	hts->I2C_Address = DeviceAddr;
+	/* At maximum 4 attempts to read ID : exit at first finding of the searched device ID */
+	for(nbReadAttempts = 0; ((nbReadAttempts < 3) && !(bFoundDevice)); nbReadAttempts++){
+		/* Read register FT5336_CHIP_ID_REG as DeviceID detection */
+		ucReadId = ft5336_IO_Read(hts, FT5336_CHIP_ID_REG);
+
+		/* Found the searched device ID ? */
+		if(ucReadId == FT5336_ID_VALUE){
+			/* Set device as found */
+			bFoundDevice = 1;
+		}
+	}
+	return (ucReadId);
+}
+
+/**
+  * @brief  Configure the FT5336 device to stop generating IT on the given INT pin
+  *         connected to MCU as EXTI.
+  * @param  DeviceAddr: Device address on communication Bus (Slave I2C address of FT5336).
+  * @retval None
+  */
+static void
+ft5336_TS_DisableIT(TouchScreen_Handle_t *hts)
+{
+	ER ercd = E_OK;
+	uint8_t regValue = 0;
+	regValue = (FT5336_G_MODE_INTERRUPT_POLLING & (FT5336_G_MODE_INTERRUPT_MASK >> FT5336_G_MODE_INTERRUPT_SHIFT)) << FT5336_G_MODE_INTERRUPT_SHIFT;
+
+	/* Set interrupt polling mode in FT5336_GMODE_REG */
+	ercd = i2c_memwrite(hts->hi2c, hts->I2C_Address, FT5336_GMODE_REG, I2C_MEMADD_SIZE_8BIT, &regValue, 1, 1000);
+	if(ercd != E_OK)
+		syslog_1(LOG_ERROR, "ft5336_TS_DisableIT I2C write error(%d) !", ercd);
+}
+
+/**
+  * @brief  Return if there is touches detected or not.
+  *         Try to detect new touches and forget the old ones (reset internal global
+  *         variables).
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @retval : Number of active touches detected (can be 0, 1 or 2).
+  */
+static uint8_t
+ft5336_TS_DetectTouch(TouchScreen_Handle_t *hts)
+{
+	volatile uint8_t nbTouch = 0;
+
+	/* Read register FT5336_TD_STAT_REG to check number of touches detection */
+	nbTouch = ft5336_IO_Read(hts, FT5336_TD_STAT_REG);
+	nbTouch &= FT5336_TD_STAT_MASK;
+
+	if(nbTouch > FT5336_MAX_DETECTABLE_TOUCH){
+		/* If invalid number of touch detected, set it to zero */
+		nbTouch = 0;
+	}
+
+	/* Update ft5336 driver internal global : current number of active touches */
+	hts->currActiveTouchNb = nbTouch;
+
+	/* Reset current active touch index on which to work on */
+	hts->currActiveTouchIdx = 0;
+	return(nbTouch);
+}
+
+/**
+  * @brief  Get the touch screen X and Y positions values
+  *         Manage multi touch thanks to touch Index global
+  *         variable 'TouchScreen_Handle.currActiveTouchIdx'.
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @param  X: Pointer to X position value
+  * @param  Y: Pointer to Y position value
+  * @retval None.
+  */
+static void
+ft5336_TS_GetXY(TouchScreen_Handle_t *hts, uint16_t *X, uint16_t *Y)
+{
+	volatile uint8_t ucReadData = 0;
+	static uint16_t coord;
+	uint8_t regAddressXLow = 0;
+	uint8_t regAddressXHigh = 0;
+	uint8_t regAddressYLow = 0;
+	uint8_t regAddressYHigh = 0;
+
+	if(hts->currActiveTouchIdx < hts->currActiveTouchNb){
+		switch(hts->currActiveTouchIdx){
+		case 0:
+			regAddressXLow  = FT5336_P1_XL_REG;
+			regAddressXHigh = FT5336_P1_XH_REG;
+			regAddressYLow  = FT5336_P1_YL_REG;
+			regAddressYHigh = FT5336_P1_YH_REG;
+			break;
+		case 1:
+			regAddressXLow  = FT5336_P2_XL_REG;
+			regAddressXHigh = FT5336_P2_XH_REG;
+			regAddressYLow  = FT5336_P2_YL_REG;
+			regAddressYHigh = FT5336_P2_YH_REG;
+			break;
+		case 2:
+			regAddressXLow  = FT5336_P3_XL_REG;
+			regAddressXHigh = FT5336_P3_XH_REG;
+			regAddressYLow  = FT5336_P3_YL_REG;
+			regAddressYHigh = FT5336_P3_YH_REG;
+			break;
+		case 3:
+			regAddressXLow  = FT5336_P4_XL_REG;
+			regAddressXHigh = FT5336_P4_XH_REG;
+			regAddressYLow  = FT5336_P4_YL_REG;
+			regAddressYHigh = FT5336_P4_YH_REG;
+			break;
+		case 4:
+			regAddressXLow  = FT5336_P5_XL_REG;
+			regAddressXHigh = FT5336_P5_XH_REG;
+			regAddressYLow  = FT5336_P5_YL_REG;
+			regAddressYHigh = FT5336_P5_YH_REG;
+			break;
+		case 5:
+			regAddressXLow  = FT5336_P6_XL_REG;
+			regAddressXHigh = FT5336_P6_XH_REG;
+			regAddressYLow  = FT5336_P6_YL_REG;
+			regAddressYHigh = FT5336_P6_YH_REG;
+			break;
+		case 6:
+			regAddressXLow  = FT5336_P7_XL_REG;
+			regAddressXHigh = FT5336_P7_XH_REG;
+			regAddressYLow  = FT5336_P7_YL_REG;
+			regAddressYHigh = FT5336_P7_YH_REG;
+			break;
+		case 7:
+			regAddressXLow  = FT5336_P8_XL_REG;
+			regAddressXHigh = FT5336_P8_XH_REG;
+			regAddressYLow  = FT5336_P8_YL_REG;
+			regAddressYHigh = FT5336_P8_YH_REG;
+			break;
+		case 8:
+			regAddressXLow  = FT5336_P9_XL_REG;
+			regAddressXHigh = FT5336_P9_XH_REG;
+			regAddressYLow  = FT5336_P9_YL_REG;
+			regAddressYHigh = FT5336_P9_YH_REG;
+			break;
+		case 9:
+			regAddressXLow  = FT5336_P10_XL_REG;
+			regAddressXHigh = FT5336_P10_XH_REG;
+			regAddressYLow  = FT5336_P10_YL_REG;
+			regAddressYHigh = FT5336_P10_YH_REG;
+			break;
+		default:
+			break;
+
+		} /* end switch(TouchScreen_Handle.currActiveTouchIdx) */
+
+		/* Read low part of X position */
+		ucReadData = ft5336_IO_Read(hts, regAddressXLow);
+		coord = (ucReadData & FT5336_TOUCH_POS_LSB_MASK) >> FT5336_TOUCH_POS_LSB_SHIFT;
+
+		/* Read high part of X position */
+		ucReadData = ft5336_IO_Read(hts, regAddressXHigh);
+		coord |= ((ucReadData & FT5336_TOUCH_POS_MSB_MASK) >> FT5336_TOUCH_POS_MSB_SHIFT) << 8;
+
+		/* Send back ready X position to caller */
+		*X = coord;
+
+		/* Read low part of Y position */
+		ucReadData = ft5336_IO_Read(hts, regAddressYLow);
+		coord = (ucReadData & FT5336_TOUCH_POS_LSB_MASK) >> FT5336_TOUCH_POS_LSB_SHIFT;
+
+		/* Read high part of Y position */
+		ucReadData = ft5336_IO_Read(hts, regAddressYHigh);
+		coord |= ((ucReadData & FT5336_TOUCH_POS_MSB_MASK) >> FT5336_TOUCH_POS_MSB_SHIFT) << 8;
+
+		/* Send back ready Y position to caller */
+		*Y = coord;
+
+		hts->currActiveTouchIdx++;	/* next call will work on next touch */
+	} /* of if(TouchScreen_Handle.currActiveTouchIdx < TouchScreen_Handle.currActiveTouchNb) */
+}
+
+
+/**** NEW FEATURES enabled when Multi-touch support is enabled ****/
+
+#if (TS_MULTI_TOUCH_SUPPORTED == 1)
+/**
+  * @brief  Get the touch detailed informations on touch number 'touchIdx' (0..1)
+  *         This touch detailed information contains :
+  *         - weight that was applied to this touch
+  *         - sub-area of the touch in the touch panel
+  *         - event of linked to the touch (press down, lift up, ...)
+  * @param  DeviceAddr: Device address on communication Bus (I2C slave address of FT5336).
+  * @param  touchIdx : Passed index of the touch (0..1) on which we want to get the
+  *                    detailed information.
+  * @param  pWeight : Pointer to to get the weight information of 'touchIdx'.
+  * @param  pArea   : Pointer to to get the sub-area information of 'touchIdx'.
+  * @param  pEvent  : Pointer to to get the event information of 'touchIdx'.
+
+  * @retval None.
+  */
+static void
+ft5336_TS_GetTouchInfo(TouchScreen_Handle_t *hts, uint32_t touchIdx, uint32_t *pWeight, uint32_t *pArea, uint32_t *pEvent)
+{
+	volatile uint8_t ucReadData = 0;
+	uint8_t regAddressXHigh = 0;
+	uint8_t regAddressPWeight = 0;
+	uint8_t regAddressPMisc = 0;
+
+	if(touchIdx < hts->currActiveTouchNb){
+		switch(touchIdx){
+		case 0:
+			regAddressXHigh   = FT5336_P1_XH_REG;
+			regAddressPWeight = FT5336_P1_WEIGHT_REG;
+			regAddressPMisc   = FT5336_P1_MISC_REG;
+			break;
+		case 1:
+			regAddressXHigh   = FT5336_P2_XH_REG;
+			regAddressPWeight = FT5336_P2_WEIGHT_REG;
+			regAddressPMisc   = FT5336_P2_MISC_REG;
+			break;
+		case 2:
+			regAddressXHigh   = FT5336_P3_XH_REG;
+			regAddressPWeight = FT5336_P3_WEIGHT_REG;
+			regAddressPMisc   = FT5336_P3_MISC_REG;
+			break;
+		case 3:
+			regAddressXHigh   = FT5336_P4_XH_REG;
+			regAddressPWeight = FT5336_P4_WEIGHT_REG;
+			regAddressPMisc   = FT5336_P4_MISC_REG;
+			break;
+		case 4:
+			regAddressXHigh   = FT5336_P5_XH_REG;
+			regAddressPWeight = FT5336_P5_WEIGHT_REG;
+			regAddressPMisc   = FT5336_P5_MISC_REG;
+			break;
+		case 5:
+			regAddressXHigh   = FT5336_P6_XH_REG;
+			regAddressPWeight = FT5336_P6_WEIGHT_REG;
+			regAddressPMisc   = FT5336_P6_MISC_REG;
+			break;
+		case 6:
+			regAddressXHigh   = FT5336_P7_XH_REG;
+			regAddressPWeight = FT5336_P7_WEIGHT_REG;
+			regAddressPMisc   = FT5336_P7_MISC_REG;
+			break;
+		case 7:
+			regAddressXHigh   = FT5336_P8_XH_REG;
+			regAddressPWeight = FT5336_P8_WEIGHT_REG;
+			regAddressPMisc   = FT5336_P8_MISC_REG;
+			break;
+		case 8:
+			regAddressXHigh   = FT5336_P9_XH_REG;
+			regAddressPWeight = FT5336_P9_WEIGHT_REG;
+			regAddressPMisc   = FT5336_P9_MISC_REG;
+			break;
+		case 9:
+			regAddressXHigh   = FT5336_P10_XH_REG;
+			regAddressPWeight = FT5336_P10_WEIGHT_REG;
+			regAddressPMisc   = FT5336_P10_MISC_REG;
+			break;
+		default:
+			break;
+		} /* end switch(touchIdx) */
+
+		/* Read Event Id of touch index */
+		ucReadData = ft5336_IO_Read(hts, regAddressXHigh);
+		*pEvent = (ucReadData & FT5336_TOUCH_EVT_FLAG_MASK) >> FT5336_TOUCH_EVT_FLAG_SHIFT;
+
+		/* Read weight of touch index */
+		ucReadData = ft5336_IO_Read(hts, regAddressPWeight);
+		*pWeight = (ucReadData & FT5336_TOUCH_WEIGHT_MASK) >> FT5336_TOUCH_WEIGHT_SHIFT;
+
+		/* Read area of touch index */
+		ucReadData = ft5336_IO_Read(hts, regAddressPMisc);
+		*pArea = (ucReadData & FT5336_TOUCH_AREA_MASK) >> FT5336_TOUCH_AREA_SHIFT;
+	} /* of if(touchIdx < TouchScreen_Handle.currActiveTouchNb) */
+}
+#endif /* TS_MULTI_TOUCH_SUPPORTED == 1 */
+
+
+/**
+  * @brief  Initializes and configures the touch screen functionalities and 
+  *         configures all necessary hardware resources (GPIOs, I2C, clocks..).
+  * @param  ts_SizeX: Maximum X size of the TS area on LCD
+  * @param  ts_SizeY: Maximum Y size of the TS area on LCD
+  * @param  orientation : TS_ORIENTATION_LANDSCAPE or TS_ORIENTATION_PORTRAIT
+  * @retval E_OK if all initializations are OK. Other value if error.
+  */
+ER
+touchscreen_init(TouchScreen_Handle_t *hts, uint16_t ts_SizeX, uint16_t ts_SizeY, uint8_t orientation)
+{
+	ER ercd  = E_OK;
+	hts->tsXBoundary = ts_SizeX;
+	hts->tsYBoundary = ts_SizeY;
+
+	/* Read ID and verify if the touch screen driver is ready */
+	if(ft5336_ReadID(hts, FT5336_I2C_SLAVE_ADDRESS) == FT5336_ID_VALUE){
+		/* Initialize the TS driver structure */
+		hts->I2C_Address = FT5336_I2C_SLAVE_ADDRESS;
+		hts->tsOrientation = TS_SWAP_XY;
+
+		/* Initialize the TS driver */
+		ft5336_TS_DisableIT(hts);
+	}
+	else
+		ercd = E_NOSPT;
+	return ercd;
+}
+
+/**
+  * @brief  Returns status and positions of the touch screen.
+  * @param  TS_State: Pointer to touch screen current state structure
+  * @retval E_OK if all initializations are OK. Other value if error.
+  */
+ER
+touchscreen_getstate(TouchScreen_Handle_t *hts, TS_StateTypeDef *TS_State)
+{
+	static uint32_t _x[TS_MAX_NB_TOUCH] = {0, 0};
+	static uint32_t _y[TS_MAX_NB_TOUCH] = {0, 0};
+	ER  ercd = E_OK;
+	uint16_t x[TS_MAX_NB_TOUCH];
+	uint16_t y[TS_MAX_NB_TOUCH];
+	uint16_t brute_x[TS_MAX_NB_TOUCH];
+	uint16_t brute_y[TS_MAX_NB_TOUCH];
+	uint16_t x_diff;
+	uint16_t y_diff;
+	uint32_t index;
+#if (TS_MULTI_TOUCH_SUPPORTED == 1)
+	uint32_t weight = 0;
+	uint32_t area = 0;
+	uint32_t event = 0;
+	uint32_t gestureId = 0;
+#endif /* TS_MULTI_TOUCH_SUPPORTED == 1 */
+
+	/* Check and update the number of touches active detected */
+	TS_State->touchDetected = ft5336_TS_DetectTouch(hts);
+
+	if(TS_State->touchDetected){
+		for(index=0; index < TS_State->touchDetected; index++){
+			/* Get each touch coordinates */
+			ft5336_TS_GetXY(hts, &(brute_x[index]), &(brute_y[index]));
+
+			if(hts->tsOrientation == TS_SWAP_NONE){
+				x[index] = brute_x[index];
+				y[index] = brute_y[index];
+			}
+			if(hts->tsOrientation & TS_SWAP_X){
+				x[index] = 4096 - brute_x[index];
+			}
+			if(hts->tsOrientation & TS_SWAP_Y){
+				y[index] = 4096 - brute_y[index];
+			}
+			if(hts->tsOrientation & TS_SWAP_XY){
+				y[index] = brute_x[index];
+				x[index] = brute_y[index];
+			}
+
+			x_diff = x[index] > _x[index]? (x[index] - _x[index]): (_x[index] - x[index]);
+			y_diff = y[index] > _y[index]? (y[index] - _y[index]): (_y[index] - y[index]);
+
+			if((x_diff + y_diff) > 5){
+				_x[index] = x[index];
+				_y[index] = y[index];
+			}
+			if(hts->I2C_Address == FT5336_I2C_SLAVE_ADDRESS){
+				TS_State->touchX[index] = x[index];
+				TS_State->touchY[index] = y[index];
+			}
+			else{
+				/* 2^12 = 4096 : indexes are expressed on a dynamic of 4096 */
+				TS_State->touchX[index] = (hts->tsXBoundary * _x[index]) >> 12;
+				TS_State->touchY[index] = (hts->tsYBoundary * _y[index]) >> 12;
+			}
+
+#if (TS_MULTI_TOUCH_SUPPORTED == 1)
+			/* Get touch info related to the current touch */
+			ft5336_TS_GetTouchInfo(hts, index, &weight, &area, &event);
+
+			/* Update TS_State structure */
+			TS_State->touchWeight[index] = weight;
+			TS_State->touchArea[index]   = area;
+
+			/* Remap touch event */
+			switch(event){
+			case FT5336_TOUCH_EVT_FLAG_PRESS_DOWN	:
+				TS_State->touchEventId[index] = TOUCH_EVENT_PRESS_DOWN;
+				break;
+			case FT5336_TOUCH_EVT_FLAG_LIFT_UP :
+				TS_State->touchEventId[index] = TOUCH_EVENT_LIFT_UP;
+				break;
+			case FT5336_TOUCH_EVT_FLAG_CONTACT :
+				TS_State->touchEventId[index] = TOUCH_EVENT_CONTACT;
+				break;
+			case FT5336_TOUCH_EVT_FLAG_NO_EVENT :
+				TS_State->touchEventId[index] = TOUCH_EVENT_NO_EVT;
+				break;
+			default:
+				ercd = E_SYS;
+				break;
+			} /* of switch(event) */
+#endif /* TS_MULTI_TOUCH_SUPPORTED == 1 */
+
+		} /* of for(index=0; index < TS_State->touchDetected; index++) */
+
+#if (TS_MULTI_TOUCH_SUPPORTED == 1)
+		/* Get gesture Id */
+		gestureId = ft5336_IO_Read(hts, FT5336_GEST_ID_REG);
+
+		/* Remap gesture Id to a TS_GestureIdTypeDef value */
+		switch(gestureId){
+		case FT5336_GEST_ID_NO_GESTURE :
+			TS_State->gestureId = GEST_ID_NO_GESTURE;
+			break;
+		case FT5336_GEST_ID_MOVE_UP :
+			TS_State->gestureId = GEST_ID_MOVE_UP;
+			break;
+		case FT5336_GEST_ID_MOVE_RIGHT :
+			TS_State->gestureId = GEST_ID_MOVE_RIGHT;
+			break;
+		case FT5336_GEST_ID_MOVE_DOWN :
+			TS_State->gestureId = GEST_ID_MOVE_DOWN;
+			break;
+		case FT5336_GEST_ID_MOVE_LEFT :
+			TS_State->gestureId = GEST_ID_MOVE_LEFT;
+			break;
+		case FT5336_GEST_ID_ZOOM_IN :
+			TS_State->gestureId = GEST_ID_ZOOM_IN;
+			break;
+		case FT5336_GEST_ID_ZOOM_OUT :
+			TS_State->gestureId = GEST_ID_ZOOM_OUT;
+			break;
+		default:
+			ercd = E_SYS;
+			break;
+		} /* of switch(gestureId) */
+#endif /* TS_MULTI_TOUCH_SUPPORTED == 1 */
+
+	} /* end of if(TS_State->touchDetected != 0) */
+	return ercd;
+}
+
+/**
+  * @brief  Function used to reset all touch data before a new acquisition
+  *         of touch information.
+  * @param  TS_State: Pointer to touch screen current state structure
+  * @retval E_OK if OK, TE_ERROR if problem found.
+  */
+ER
+touchscreen_reset_data(TS_StateTypeDef *TS_State)
+{
+	ER       ercd = E_PAR;
+	uint32_t index;
+
+	if(TS_State != (TS_StateTypeDef *)NULL){
+		TS_State->gestureId = GEST_ID_NO_GESTURE;
+		TS_State->touchDetected = 0;
+
+		for(index = 0; index < TS_MAX_NB_TOUCH; index++){
+			TS_State->touchX[index]       = 0;
+			TS_State->touchY[index]       = 0;
+			TS_State->touchArea[index]    = 0;
+			TS_State->touchEventId[index] = TOUCH_EVENT_NO_EVT;
+			TS_State->touchWeight[index]  = 0;
+		}
+		ercd = E_OK;
+	} /* of if (TS_State != (TS_StateTypeDef *)NULL) */
+	return ercd;
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stts_ft5336/stts_ft5336.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stts_ft5336/stts_ft5336.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/stts_ft5336/stts_ft5336.h	(revision 453)
@@ -0,0 +1,428 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/**
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+#ifndef _STTS_FT5336_H_
+#define _STTS_FT5336_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#include "device.h"
+#include "i2c.h"
+
+/* Set Multi-touch as supported */
+#if !defined(TS_MONO_TOUCH_SUPPORTED)
+#define TS_MULTI_TOUCH_SUPPORTED        1
+#endif /* TS_MONO_TOUCH_SUPPORTED */
+
+
+  /* I2C Slave address of touchscreen FocalTech FT5336 */
+#define FT5336_I2C_SLAVE_ADDRESS        0x70
+
+  /* Maximum border values of the touchscreen pad */
+#define FT5336_MAX_WIDTH                480	/* Touchscreen pad max width   */
+#define FT5336_MAX_HEIGHT               272	/* Touchscreen pad max height  */
+
+  /* Max detectable simultaneous touches */
+#define FT5336_MAX_DETECTABLE_TOUCH     0x05
+
+  /**
+   * @brief : Definitions for FT5336 I2C register addresses on 8 bit
+   **/
+
+  /* Current mode register of the FT5336 (R/W) */
+#define FT5336_DEV_MODE_REG             0x00
+
+  /* Possible values of FT5336_DEV_MODE_REG */
+#define FT5336_DEV_MODE_WORKING         0x00
+#define FT5336_DEV_MODE_FACTORY         0x04
+
+#define FT5336_DEV_MODE_MASK            0x07
+#define FT5336_DEV_MODE_SHIFT           0x04
+
+  /* Gesture ID register */
+#define FT5336_GEST_ID_REG              0x01
+
+  /* Possible values of FT5336_GEST_ID_REG */
+#define FT5336_GEST_ID_NO_GESTURE       0x00
+#define FT5336_GEST_ID_MOVE_UP          0x10
+#define FT5336_GEST_ID_MOVE_RIGHT       0x14
+#define FT5336_GEST_ID_MOVE_DOWN        0x18
+#define FT5336_GEST_ID_MOVE_LEFT        0x1C
+#define FT5336_GEST_ID_SINGLE_CLICK     0x20
+#define FT5336_GEST_ID_DOUBLE_CLICK     0x22
+#define FT5336_GEST_ID_ROTATE_CLOCKWISE 0x28
+#define FT5336_GEST_ID_ROTATE_C_CLOCKWISE 0x29
+#define FT5336_GEST_ID_ZOOM_IN          0x40
+#define FT5336_GEST_ID_ZOOM_OUT         0x49
+
+  /* Touch Data Status register : gives number of active touch points (0..5) */
+#define FT5336_TD_STAT_REG              0x02
+
+  /* Values related to FT5336_TD_STAT_REG */
+#define FT5336_TD_STAT_MASK             0x0F
+#define FT5336_TD_STAT_SHIFT            0x00
+
+  /* Values Pn_XH and Pn_YH related */
+#define FT5336_TOUCH_EVT_FLAG_PRESS_DOWN 0x00
+#define FT5336_TOUCH_EVT_FLAG_LIFT_UP   0x01
+#define FT5336_TOUCH_EVT_FLAG_CONTACT   0x02
+#define FT5336_TOUCH_EVT_FLAG_NO_EVENT  0x03
+
+#define FT5336_TOUCH_EVT_FLAG_SHIFT     0x06
+#define FT5336_TOUCH_EVT_FLAG_MASK      (3 << FT5336_TOUCH_EVT_FLAG_SHIFT)
+
+#define FT5336_TOUCH_POS_MSB_MASK       0x0F
+#define FT5336_TOUCH_POS_MSB_SHIFT      0x00
+
+  /* Values Pn_XL and Pn_YL related */
+#define FT5336_TOUCH_POS_LSB_MASK       0xFF
+#define FT5336_TOUCH_POS_LSB_SHIFT      0x00
+
+#define FT5336_P1_XH_REG                0x03
+#define FT5336_P1_XL_REG                0x04
+#define FT5336_P1_YH_REG                0x05
+#define FT5336_P1_YL_REG                0x06
+
+/* Touch Pressure register value (R) */
+#define FT5336_P1_WEIGHT_REG            0x07
+
+/* Values Pn_WEIGHT related  */
+#define FT5336_TOUCH_WEIGHT_MASK        0xFF
+#define FT5336_TOUCH_WEIGHT_SHIFT       0x00
+
+/* Touch area register */
+#define FT5336_P1_MISC_REG              0x08
+
+/* Values related to FT5336_Pn_MISC_REG */
+#define FT5336_TOUCH_AREA_MASK          (0x04 << 4)
+#define FT5336_TOUCH_AREA_SHIFT         0x04
+
+#define FT5336_P2_XH_REG                0x09
+#define FT5336_P2_XL_REG                0x0A
+#define FT5336_P2_YH_REG                0x0B
+#define FT5336_P2_YL_REG                0x0C
+#define FT5336_P2_WEIGHT_REG            0x0D
+#define FT5336_P2_MISC_REG              0x0E
+
+#define FT5336_P3_XH_REG                0x0F
+#define FT5336_P3_XL_REG                0x10
+#define FT5336_P3_YH_REG                0x11
+#define FT5336_P3_YL_REG                0x12
+#define FT5336_P3_WEIGHT_REG            0x13
+#define FT5336_P3_MISC_REG              0x14
+
+#define FT5336_P4_XH_REG                0x15
+#define FT5336_P4_XL_REG                0x16
+#define FT5336_P4_YH_REG                0x17
+#define FT5336_P4_YL_REG                0x18
+#define FT5336_P4_WEIGHT_REG            0x19
+#define FT5336_P4_MISC_REG              0x1A
+
+#define FT5336_P5_XH_REG                0x1B
+#define FT5336_P5_XL_REG                0x1C
+#define FT5336_P5_YH_REG                0x1D
+#define FT5336_P5_YL_REG                0x1E
+#define FT5336_P5_WEIGHT_REG            0x1F
+#define FT5336_P5_MISC_REG              0x20
+
+#define FT5336_P6_XH_REG                0x21
+#define FT5336_P6_XL_REG                0x22
+#define FT5336_P6_YH_REG                0x23
+#define FT5336_P6_YL_REG                0x24
+#define FT5336_P6_WEIGHT_REG            0x25
+#define FT5336_P6_MISC_REG              0x26
+
+#define FT5336_P7_XH_REG                0x27
+#define FT5336_P7_XL_REG                0x28
+#define FT5336_P7_YH_REG                0x29
+#define FT5336_P7_YL_REG                0x2A
+#define FT5336_P7_WEIGHT_REG            0x2B
+#define FT5336_P7_MISC_REG              0x2C
+
+#define FT5336_P8_XH_REG                0x2D
+#define FT5336_P8_XL_REG                0x2E
+#define FT5336_P8_YH_REG                0x2F
+#define FT5336_P8_YL_REG                0x30
+#define FT5336_P8_WEIGHT_REG            0x31
+#define FT5336_P8_MISC_REG              0x32
+
+#define FT5336_P9_XH_REG                0x33
+#define FT5336_P9_XL_REG                0x34
+#define FT5336_P9_YH_REG                0x35
+#define FT5336_P9_YL_REG                0x36
+#define FT5336_P9_WEIGHT_REG            0x37
+#define FT5336_P9_MISC_REG              0x38
+
+#define FT5336_P10_XH_REG               0x39
+#define FT5336_P10_XL_REG               0x3A
+#define FT5336_P10_YH_REG               0x3B
+#define FT5336_P10_YL_REG               0x3C
+#define FT5336_P10_WEIGHT_REG           0x3D
+#define FT5336_P10_MISC_REG             0x3E
+
+  /* Threshold for touch detection */
+#define FT5336_TH_GROUP_REG             0x80
+
+  /* Values FT5336_TH_GROUP_REG : threshold related  */
+#define FT5336_THRESHOLD_MASK           0xFF
+#define FT5336_THRESHOLD_SHIFT          0x00
+
+  /* Filter function coefficients */
+#define FT5336_TH_DIFF_REG              0x85
+
+  /* Control register */
+#define FT5336_CTRL_REG                 0x86
+
+  /* Values related to FT5336_CTRL_REG */
+
+  /* Will keep the Active mode when there is no touching */
+#define FT5336_CTRL_KEEP_ACTIVE_MODE    0x00
+
+  /* Switching from Active mode to Monitor mode automatically when there is no touching */
+#define FT5336_CTRL_KEEP_AUTO_SWITCH_MONITOR_MODE  0x01
+
+  /* The time period of switching from Active mode to Monitor mode when there is no touching */
+#define FT5336_TIMEENTERMONITOR_REG     0x87
+
+  /* Report rate in Active mode */
+#define FT5336_PERIODACTIVE_REG         0x88
+
+  /* Report rate in Monitor mode */
+#define FT5336_PERIODMONITOR_REG        0x89
+
+  /* The value of the minimum allowed angle while Rotating gesture mode */
+#define FT5336_RADIAN_VALUE_REG         0x91
+
+  /* Maximum offset while Moving Left and Moving Right gesture */
+#define FT5336_OFFSET_LEFT_RIGHT_REG    0x92
+
+  /* Maximum offset while Moving Up and Moving Down gesture */
+#define FT5336_OFFSET_UP_DOWN_REG       0x93
+
+  /* Minimum distance while Moving Left and Moving Right gesture */
+#define FT5336_DISTANCE_LEFT_RIGHT_REG  0x94
+
+  /* Minimum distance while Moving Up and Moving Down gesture */
+#define FT5336_DISTANCE_UP_DOWN_REG     0x95
+
+  /* Maximum distance while Zoom In and Zoom Out gesture */
+#define FT5336_DISTANCE_ZOOM_REG        0x96
+
+  /* High 8-bit of LIB Version info */
+#define FT5336_LIB_VER_H_REG            0xA1
+
+  /* Low 8-bit of LIB Version info */
+#define FT5336_LIB_VER_L_REG            0xA2
+
+  /* Chip Selecting */
+#define FT5336_CIPHER_REG               0xA3
+
+  /* Interrupt mode register (used when in interrupt mode) */
+#define FT5336_GMODE_REG                0xA4
+
+#define FT5336_G_MODE_INTERRUPT_MASK    0x03
+#define FT5336_G_MODE_INTERRUPT_SHIFT   0x00
+
+  /* Possible values of FT5336_GMODE_REG */
+#define FT5336_G_MODE_INTERRUPT_POLLING 0x00
+#define FT5336_G_MODE_INTERRUPT_TRIGGER 0x01
+
+  /* Current power mode the FT5336 system is in (R) */
+#define FT5336_PWR_MODE_REG             0xA5
+
+  /* FT5336 firmware version */
+#define FT5336_FIRMID_REG               0xA6
+
+  /* FT5336 Chip identification register */
+#define FT5336_CHIP_ID_REG              0xA8
+
+  /*  Possible values of FT5336_CHIP_ID_REG */
+#define FT5336_ID_VALUE                 0x51
+
+  /* Release code version */
+#define FT5336_RELEASE_CODE_ID_REG      0xAF
+
+  /* Current operating mode the FT5336 system is in (R) */
+#define FT5336_STATE_REG                0xBC
+
+
+/** @typedef TouchScreen_Handle_t
+ *  TouchScreen Handle definition.
+ */
+typedef struct
+{
+	I2C_Handle_t    *hi2c;
+	uint16_t        tsXBoundary;
+	uint16_t        tsYBoundary;
+	uint8_t         tsOrientation;
+	uint8_t         I2C_Address;
+
+	/* field holding the current number of simultaneous active touches */
+	uint8_t         currActiveTouchNb;
+
+	/* field holding the touch index currently managed */
+	uint8_t         currActiveTouchIdx;
+
+} TouchScreen_Handle_t;
+
+/** @brief With FT5336 : maximum 5 touches detected simultaneously
+  */
+#define TS_MAX_NB_TOUCH                 ((uint32_t) FT5336_MAX_DETECTABLE_TOUCH)
+
+#define TS_NO_IRQ_PENDING               ((uint8_t) 0)
+#define TS_IRQ_PENDING                  ((uint8_t) 1)
+
+#define TS_SWAP_NONE                    ((uint8_t) 0x01)
+#define TS_SWAP_X                       ((uint8_t) 0x02)
+#define TS_SWAP_Y                       ((uint8_t) 0x04)
+#define TS_SWAP_XY                      ((uint8_t) 0x08)
+
+#define TS_ORIENTATION_PORTRAIT         ((uint8_t) 0x00)
+#define TS_ORIENTATION_LANDSCAPE        ((uint8_t) 0x01)
+#define TS_ORIENTATION_LANDSCAPE_ROT180 ((uint8_t) 0x02)
+
+/**
+*  @brief TS_StateTypeDef
+*  Define TS State structure
+*/
+typedef struct
+{
+	uint8_t  touchDetected;				/* Total number of active touches detected at last scan */
+	uint16_t touchX[TS_MAX_NB_TOUCH];	/* Touch X[0], X[1] coordinates on 12 bits */
+	uint16_t touchY[TS_MAX_NB_TOUCH];	/* Touch Y[0], Y[1] coordinates on 12 bits */
+
+#if (TS_MULTI_TOUCH_SUPPORTED == 1)
+	uint8_t  touchWeight[TS_MAX_NB_TOUCH];	/* Touch_Weight[0], Touch_Weight[1] : weight property of touches */
+	uint8_t  touchEventId[TS_MAX_NB_TOUCH];	/* Touch_EventId[0], Touch_EventId[1] : take value of type @ref TS_TouchEventTypeDef */
+	uint8_t  touchArea[TS_MAX_NB_TOUCH];	/*!< Touch_Area[0], Touch_Area[1] : touch area of each touch */
+	uint32_t gestureId; /*!< type of gesture detected : take value of type @ref TS_GestureIdTypeDef */
+#endif  /* TS_MULTI_TOUCH_SUPPORTED == 1 */
+} TS_StateTypeDef;
+
+
+/**
+ *  @brief TS_GestureIdTypeDef
+ *  Define Possible managed gesture identification values returned by touch screen
+ *  driver.
+ */
+typedef enum
+{
+	GEST_ID_NO_GESTURE = 0x00, /*!< Gesture not defined / recognized */
+	GEST_ID_MOVE_UP    = 0x01, /*!< Gesture Move Up */
+	GEST_ID_MOVE_RIGHT = 0x02, /*!< Gesture Move Right */
+	GEST_ID_MOVE_DOWN  = 0x03, /*!< Gesture Move Down */
+	GEST_ID_MOVE_LEFT  = 0x04, /*!< Gesture Move Left */
+	GEST_ID_ZOOM_IN    = 0x05, /*!< Gesture Zoom In */
+	GEST_ID_ZOOM_OUT   = 0x06, /*!< Gesture Zoom Out */
+	GEST_ID_NB_MAX     = 0x07  /*!< max number of gesture id */
+} TS_GestureIdTypeDef;
+
+/**
+ *  @brief TS_TouchEventTypeDef
+ *  Define Possible touch events kind as returned values
+ *  by touch screen IC Driver.
+ */
+typedef enum
+{
+	TOUCH_EVENT_NO_EVT        = 0x00, /*!< Touch Event : undetermined */
+	TOUCH_EVENT_PRESS_DOWN    = 0x01, /*!< Touch Event Press Down */
+	TOUCH_EVENT_LIFT_UP       = 0x02, /*!< Touch Event Lift Up */
+	TOUCH_EVENT_CONTACT       = 0x03, /*!< Touch Event Contact */
+	TOUCH_EVENT_NB_MAX        = 0x04  /*!< max number of touch events kind */
+} TS_TouchEventTypeDef;
+
+/**
+ *  @brief Table for touchscreen event information display on LCD :
+ *  table indexed on enum @ref TS_TouchEventTypeDef information
+ */
+extern char * ts_event_string_tab[TOUCH_EVENT_NB_MAX];
+
+/**
+ *  @brief Table for touchscreen gesture Id information display on LCD : table indexed
+ *  on enum @ref TS_GestureIdTypeDef information
+ */
+extern char * ts_gesture_id_string_tab[GEST_ID_NB_MAX];
+
+extern ER touchscreen_init(TouchScreen_Handle_t *hts, uint16_t ts_SizeX, uint16_t ts_SizeY, uint8_t orientation);
+extern ER touchscreen_getstate(TouchScreen_Handle_t *hts, TS_StateTypeDef *TS_State);
+extern ER touchscreen_reset_data(TS_StateTypeDef *TS_State);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _STTS_FT5336_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_device/Makefile.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_device/Makefile.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_device/Makefile.config	(revision 453)
@@ -0,0 +1,55 @@
+#
+#   TOPPERS/ASP/FMP Kernel
+#       Toyohashi Open Platform for Embedded Real-Time Systems/
+#       Advanced Standard Profile Kernel
+#
+#   Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                               Toyohashi Univ. of Technology, JAPAN
+#   Copyright (C) 2003-2008 by Ryosuke Takeuchi
+#                Platform Development Center RICOH COMPANY,LTD. JAPAN
+#   Copyright (C) 2015-2017 by TOPPERS PROJECT Educational Working Group.
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+ 
+#
+#  Makefile のプロセッサ依存 (usb_device用)
+#
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/gdic/usb_device
+
+#
+#  USB DEVICE(GDIC)に関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR):$(SRCDIR)/gdic/usb_device
+SYSSVC_COBJS := $(SYSSVC_COBJS) usb_device_driver.o
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_device/tusbd_conf.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_device/tusbd_conf.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_device/tusbd_conf.h	(revision 453)
@@ -0,0 +1,94 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2017 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  TOPPERS USB DEVICE MODULE CONFIGURATION インクルードファイル
+ */
+
+#ifndef _TUSBD_CONF_H_
+#define _TUSBD_CONF_H_
+
+#include "usb_device_driver.h"
+
+#define TUSBD_MAX_NUM_INTERFACES              1
+#define TUSBD_MAX_NUM_CONFIGURATION           1
+#define TUSBD_NUM_ENDPOINT                    15
+#define TUSBD_CONFIG_SELF_POWERED             0x01
+
+#define USBD_StatusTypeDef   TUSBD_ERCODE
+#define USBD_HandleTypeDef   TUSBD_Handle_t
+#define USBD_Init            tusbdInit
+#define USBD_Start           tusbdStart
+
+extern uint8_t defaultDeviceDescriptor[];
+extern uint8_t defaultDeviceQualifierDescriptor[];
+extern uint8_t defaultLanguageIDDescriptor[];
+extern uint8_t defaultManufacturerString[];
+extern uint8_t defaultProductString[];
+extern uint8_t defaultSerialString[];
+extern uint8_t defaultConfigurationString[];
+extern uint8_t defaultInterfaceString[];
+
+#define TUSBD_DEVICE_DESCRIPTOR               defaultDeviceDescriptor
+#define TUSBD_DEVICE_QUALIFIER_DESCRIPTOR     defaultDeviceQualifierDescriptor
+#define TUSBD_LANGUAGEID_DESCRIPTOR           defaultLanguageIDDescriptor
+#define TUSBD_MANUFACTURER_STRING             defaultManufacturerString
+#define TUSBD_PRODUCT_STRING                  defaultProductString
+#define TUSBD_SERIAL_STRING                   defaultSerialString
+#define TUSBD_CONFIGURATION_STRING            defaultConfigurationString
+#define TUSBD_INTERFACE_STRING                defaultInterfaceString
+#define TUSBD_USER_STRING                     NULL
+
+#define tusbdDriverSetUSBAddress(d, a)  usbd_setDevAddress(((d)->pSysData), (a))
+#define tusbdDriverGetRxDataSize        usb_device_getrxdatasize
+
+#define tusbdDriverInit                 usb_device_init
+#define tusbdDriverDeInit               usb_device_deinit
+#define tusbdDriverStart                usb_device_start
+#define tusbdDriverStop                 usb_device_stop
+#define tusbdDriverOpenEp               usb_device_openep
+#define tusbdDriverCloseEp              usb_device_closeep
+#define tusbdDriverFlushEp              usb_device_flushep
+#define tusbdDriverStallEp              usb_device_stallep
+#define tusbdDriverClearStallEp         usb_device_clearep
+#define tusbdDriverStallConditionEp     usb_device_getstallcondition
+#define tusbdDriverStartTransmit        usb_device_transmitdata
+#define tusbdDriverSetupReceive         usb_device_startreceive
+#define tusbdDriverTestMode             usb_device_testmode
+
+#endif /* _TUSBD_CONF_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_device/usb_device_driver.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_device/usb_device_driver.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_device/usb_device_driver.c	(revision 453)
@@ -0,0 +1,498 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  USB DEVICE HIGH DRIVERS
+ */
+
+#include "kernel_impl.h"
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <sil.h>
+#include <target_syssvc.h>
+#include "device.h"
+
+#include "stdlib.h"
+#include "tusbd_base.h"
+#include "usb_device.h"
+
+
+#define sil_orw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) | (b))
+#define sil_andw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) & ~(b))
+#define sil_orh_mem(a, b)		sil_wrh_mem((a), sil_reh_mem(a) | (b))
+#define sil_andh_mem(a, b)		sil_wrh_mem((a), sil_reh_mem(a) & ~(b))
+
+#ifndef MAX_DEVICE_EPS
+#define MAX_DEVICE_EPS          (MAX_EPS_CHANNELS-1)
+#endif
+
+/*
+ *  SETUPSTAGE CALLBACK関数
+ */
+static void
+tusbdSetupStageCallback(USB_DEV_Handle_t *husb)
+{
+	tusbdSetupStage(husb->pDev, (uint8_t *)husb->Setup);
+}
+
+/*
+ *  DATAOUTSTAGE CALLBACK関数
+ */
+static void
+tusbdDataOutStageCallback(USB_DEV_Handle_t *husb, uint8_t epnum)
+{
+	tusbdDataOutStage(husb->pDev, epnum, husb->OUT_ep[epnum].xfer_buff);
+}
+
+/*
+ *  DATAINSTAGE CALLBACK関数
+ */
+static void
+tusbdDataInStageCallback(USB_DEV_Handle_t *husb, uint8_t epnum)
+{
+	tusbdDataInStage(husb->pDev, epnum, husb->IN_ep[epnum].xfer_buff);
+}
+
+/*
+ *  DEVICE RESET CALLBACK関数
+ */
+static void
+tusbdResetCallback(USB_DEV_Handle_t *husb)
+{
+	uint8_t speed = USB_DEVICE_SPEED_FULL;
+
+	/* Set USB Current Speed */
+	switch(husb->Init.speed){
+	case USB_SPEED_HIGH:
+		speed = USB_DEVICE_SPEED_HIGH;
+		break;
+	case USB_SPEED_FULL:
+		speed = USB_DEVICE_SPEED_FULL;
+		break;
+	default:
+		speed = USB_DEVICE_SPEED_FULL;
+		break;
+	}
+
+	/*
+	 *  DEVICEのリセット
+	 */
+	tusbdReset(husb->pDev);
+	tusbdSetSpeed(husb->pDev, speed);
+}
+
+/*
+ *  DEVICE SUSPEND CALLBACK関数
+ */
+static void
+tusbdSuspendCallback(USB_DEV_Handle_t *husb)
+{
+	tusbdSuspend(husb->pDev);
+#if 1	/* ROI DEBUG */
+	syslog_0(LOG_NOTICE, "## tusbdSuspendCallback ##");
+#endif
+  /*Enter in STOP mode */
+	if (husb->Init.low_power_enable){
+		/* Set SLEEPDEEP bit and SleepOnExit of Cortex System Control Register */
+		sil_orw_mem((uint32_t *)(TADR_SCB_BASE+TOFF_SCB_SCR), (SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk));
+	}
+}
+
+/*
+ *  DEVICE RESUME CALLBACK関数
+ */
+static void
+tusbdResumeCallback(USB_DEV_Handle_t *husb)
+{
+	TUSBD_Handle_t *pdevice = husb->pDev;
+	if(husb->Init.low_power_enable && pdevice->dev_state == TUSBD_STATE_SUSPENDED){
+		/* Reset SLEEPDEEP bit of Cortex System Control Register */
+		sil_andw_mem((uint32_t *)(TADR_SCB_BASE+TOFF_SCB_SCR), (SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk));
+		sysclock_config(1);
+	}
+	tusbdResume(husb->pDev);
+#if 1	/* ROI DEBUG */
+	syslog_0(LOG_NOTICE, "## tusbdResumeCallback ##");
+#endif
+}
+
+/*
+ *  DEVICE CONNECT CALLBACK関数
+ */
+static void
+tusbdConnectCallback(USB_DEV_Handle_t *husb)
+{
+	tusbdDeviceConnected(husb->pDev);
+}
+
+/*
+ *  DEVICE DISCONNECT CALLBACK関数
+ */
+static void
+tusbdDisconnectCallback(USB_DEV_Handle_t *husb)
+{
+	tusbdDeviceDisconnected(husb->pDev);
+}
+
+/*
+ *  ENDPOINT取得
+ */
+static USB_DEV_EPTypeDef *
+tusbdGetEndpoint(USB_DEV_Handle_t *husb, uint8_t addr)
+{
+	USB_DEV_EPTypeDef *ep;
+
+	if((addr & USB_DEVICE_TO_HOST) != 0){
+		ep = &husb->IN_ep[addr & 0x7F];
+	}
+	else{
+		ep = &husb->OUT_ep[addr & 0x7F];
+	}
+	ep->num   = addr & 0x7F;
+	ep->is_in = (USB_DEVICE_TO_HOST & addr) != 0;
+	return ep;
+}
+
+
+/*
+ *  USB_DEVICE HIGH DRIVER INITIALIZE
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+usb_device_init(TUSBD_Handle_t *pdevice)
+{
+	USB_DEV_Handle_t *husb = (USB_DEV_Handle_t *)(pdevice->pSysData);
+	uint32_t i = 0;
+
+	/*
+	 *  USBハンドラに、USBデバイスハンドラをセット
+	 */
+	husb->pDev = pdevice;
+
+	/*
+	 *  コールバック関数をセット
+	 */
+	husb->devsetupstagecallback   = tusbdSetupStageCallback;
+	husb->devdataoutstagecallback = tusbdDataOutStageCallback;
+	husb->devdatainstagecallback  = tusbdDataInStageCallback;
+	husb->devsofcallback          = NULL;
+	husb->devresetcallback        = tusbdResetCallback;
+	husb->devsuspendcallback      = tusbdSuspendCallback;
+	husb->devresumecallback       = tusbdResumeCallback;
+	husb->devconnectcallback      = tusbdConnectCallback;
+	husb->devdisconnectcallback   = tusbdDisconnectCallback;
+	husb->devlpmcallback          = NULL;
+
+	/*
+	 *  エンドポイントの初期化
+	 */
+	for(i = 0 ; i < MAX_DEVICE_EPS ; i++){
+		husb->IN_ep[i].is_in = 1;
+		husb->IN_ep[i].num = i;
+		husb->IN_ep[i].type = EP_TYPE_CTRL;
+		husb->IN_ep[i].maxpacket = 0;
+		husb->IN_ep[i].xfer_buff = 0;
+		husb->IN_ep[i].xfer_len = 0;
+
+		husb->OUT_ep[i].is_in = 0;
+		husb->OUT_ep[i].num = i;
+ 		husb->OUT_ep[i].type = EP_TYPE_CTRL;
+		husb->OUT_ep[i].maxpacket = 0;
+		husb->OUT_ep[i].xfer_buff = 0;
+		husb->OUT_ep[i].xfer_len = 0;
+	}
+
+	/*
+	 *  LPMの有効化
+	 */
+	usbd_init_lpm(husb);
+	usbd_init_BCD(husb);
+
+	usbd_setupPMA(husb , 0x00 , PCD_SNG_BUF, 0x18);
+	usbd_setupPMA(husb , 0x80 , PCD_SNG_BUF, 0x58);
+	usbd_setupPMA(husb , 0x81 , PCD_SNG_BUF, 0x98);
+	usbd_setupPMA(husb , 0x82 , PCD_SNG_BUF, 0xD8);
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB_DEVICE HIGH DRIVER DE-INITIALIZE
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  return     TUSBD_ERCODE
+  */
+TUSBD_ERCODE
+usb_device_deinit(TUSBD_Handle_t *pdevice)
+{
+	/*
+	 *  デバイス停止
+	 */
+	usb_device_stop(pdevice);
+
+	/*
+	 *  デバイスハードウェア終了
+	 */
+	usbd_deinit(pdevice->pSysData);
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB DEVICE HIGH DRIVER START
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  return     TUSBD_ERCODE
+  */
+TUSBD_ERCODE
+usb_device_start(TUSBD_Handle_t *pdevice)
+{
+	usbd_devconnect(pdevice->pSysData);
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB DEVICE HIGH DRIVER STOP
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  return     TUSBD_ERCODE
+  */
+TUSBD_ERCODE
+usb_device_stop(TUSBD_Handle_t *pdevice)
+{
+	usbd_devdisconnect(pdevice->pSysData);
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB DEVICE HIGH DRIVER OPEN ENDPOINT
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  parameter2 addr:  endpointアドレス
+ *  parameter3 type:  endpointタイプ
+ *  parameter4 mps:   MAX PACKET SIZE
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+usb_device_openep(TUSBD_Handle_t *pdevice, uint8_t addr, uint8_t type, uint16_t mps)
+{
+	USB_DEV_Handle_t  *husb = pdevice->pSysData;
+	USB_DEV_EPTypeDef *ep;
+
+	ep = tusbdGetEndpoint(husb, addr);
+	ep->maxpacket = mps;
+	ep->type = type;
+	usbd_activateEndpoint(husb, ep);
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB DEVICE HIGH DRIVER CLOSE ENDPOINT
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  parameter2 addr:  endpointアドレス
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+usb_device_closeep(TUSBD_Handle_t *pdevice, uint8_t addr)
+{
+	USB_DEV_Handle_t  *husb = pdevice->pSysData;
+	USB_DEV_EPTypeDef *ep;
+
+	ep = tusbdGetEndpoint(husb, addr);
+	usbd_deactivateEndpoint(husb, ep);
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB DEVICE HIGH DRIVER FLUSH ENDPOINT
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  parameter2 addr:  endpointアドレス
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+usb_device_flushep(TUSBD_Handle_t *pdevice, uint8_t addr)
+{
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB DEVICE HIGH DRIVER STALL ENDPOINT
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  parameter2 addr:  endpointアドレス
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+usb_device_stallep(TUSBD_Handle_t *pdevice, uint8_t addr)
+{
+	USB_DEV_Handle_t  *husb = pdevice->pSysData;
+	USB_DEV_EPTypeDef *ep;
+
+	ep = tusbdGetEndpoint(husb, addr);
+	ep->is_stall = 1;
+
+	usbd_epsetStall(husb, ep);
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB DEVICE HIGH DRIVER CLEAR STALL-ENDPOINT
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  parameter2 addr:  endpointアドレス
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+usb_device_clearep(TUSBD_Handle_t *pdevice, uint8_t addr)
+{
+	USB_DEV_Handle_t *husb = pdevice->pSysData;
+	USB_DEV_EPTypeDef *ep;
+
+	ep = tusbdGetEndpoint(husb, addr);
+	ep->is_stall = 0;
+
+	usbd_epclearStall(husb, ep);
+	return TUSBD_E_OK; 
+}
+
+/*
+ *  USB DEVICE HIGH DRIVER GET STALL CONDITION
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  parameter2 addr:  endpointアドレス
+ *  return     1:stall 0:not stall
+ */
+uint8_t
+usb_device_getstallcondition(TUSBD_Handle_t *pdevice, uint8_t addr)
+{
+	USB_DEV_Handle_t *husb = pdevice->pSysData;
+
+	if((addr & USB_DEVICE_TO_HOST) != 0)
+		return husb->IN_ep[addr & 0x7F].is_stall;
+	else
+		return husb->OUT_ep[addr & 0x7F].is_stall;
+}
+
+/*
+ *  USB DEVICE HIGH DRIVER TRANSMIT A DATA
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  parameter2 addr:  endpointアドレス
+ *  parameter3 pbuf:  送信データバッファ
+ *  parameter4 size:  送信サイズ
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+usb_device_transmitdata(TUSBD_Handle_t *pdevice, uint8_t addr, uint8_t *pbuf, uint16_t size)
+{
+	USB_DEV_Handle_t  *husb = pdevice->pSysData;
+	USB_DEV_EPTypeDef *ep;
+
+	ep = tusbdGetEndpoint(husb, (addr | USB_DEVICE_TO_HOST));
+
+	/*
+	 *  送信データ設定
+	 */
+	ep->xfer_buff = pbuf;
+	ep->xfer_len = size;
+	ep->xfer_count = 0;
+	usbd_epstartsend(husb, ep);
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB DEVICE HIGH DRIVER START to RECEIVE
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  parameter2 addr:  endpointアドレス
+ *  parameter3 pbuf:  受信データバッファ
+ *  parameter4 size:  受信サイズ
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+usb_device_startreceive(TUSBD_Handle_t *pdevice, uint8_t addr, uint8_t *pbuf, uint16_t size)
+{
+	USB_DEV_Handle_t  *husb = pdevice->pSysData;
+	USB_DEV_EPTypeDef *ep;
+
+	ep = tusbdGetEndpoint(husb, (addr & ~USB_DEVICE_TO_HOST));
+
+	/*
+	 *  受信データ設定
+	 */
+	ep->xfer_buff = pbuf;
+	ep->xfer_len = size;
+	ep->xfer_count = 0;
+	usbd_epstartreceive(husb, ep);
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB DEVICE HIGH DRIVER TEST MODE
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+usb_device_testmode(TUSBD_Handle_t *pdevice)
+{
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB DEVICE HIGH DRIVER REMOTE WAKEUP
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  return     TUSBD_ERCODE
+ */
+void
+usb_device_wakeup(USBD_HandleTypeDef *pdevice)
+{
+	USB_DEV_Handle_t *husb = pdevice->pSysData;
+
+	if(pdevice->dev_remote_wakeup == 1 && pdevice->dev_state == TUSBD_STATE_SUSPENDED){
+		if(husb->Init.low_power_enable){
+			/* Reset SLEEPDEEP bit of Cortex System Control Register */
+			sil_andw_mem((uint32_t *)(TADR_SCB_BASE+TOFF_SCB_SCR), (SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk));
+			sysclock_config(1);
+		}
+		/* Activate Remote wakeup */
+		if(husb->Init.lpm_enable == 1)	/* Apply L1 Resume */
+			sil_orh_mem((uint16_t *)(husb->base+TOFF_USB_CNTR), USB_CNTR_L1RESUME);
+		else	/* Apply L2 Resume */
+		sil_orh_mem((uint16_t *)(husb->base+TOFF_USB_CNTR), USB_CNTR_RESUME);
+
+		/* Remote wakeup delay */
+		sil_dly_nse(10*1000*1000);
+
+		if(husb->Init.lpm_enable == 1)	/* Release L1 Resume */
+			sil_andh_mem((uint16_t *)(husb->base+TOFF_USB_CNTR), USB_CNTR_L1RESUME);
+		else		/* Release L2 Resume */
+			sil_andh_mem((uint16_t *)(husb->base+TOFF_USB_CNTR), USB_CNTR_RESUME);
+		/* Change remote_wakeup feature to 0*/
+		pdevice->dev_remote_wakeup = 0;
+	}
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_device/usb_device_driver.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_device/usb_device_driver.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_device/usb_device_driver.h	(revision 453)
@@ -0,0 +1,78 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2017 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  STM USB DEVICE HIGH DRIVER インクルードファイル
+ */
+
+
+#ifndef _USB_DEVICE_DRIVER_H_
+#define _USB_DEVICE_DRIVER_H_
+
+#include "tusb_rtos.h"
+#include "usb_device.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#define usb_device_getrxdatasize(d, a)  (((USB_DEV_Handle_t *)((d)->pSysData))->OUT_ep[(a) & 0x7F].xfer_count)
+
+/*
+ *  STM USB DEVICE HIGH DRIVER関数プロトタイプ宣言
+ */
+extern TUSBD_ERCODE usb_device_init(TUSBD_Handle_t *pdevice);
+extern TUSBD_ERCODE usb_device_deinit(TUSBD_Handle_t *pdevice);
+extern TUSBD_ERCODE usb_device_start(TUSBD_Handle_t *pdevice);
+extern TUSBD_ERCODE usb_device_stop(TUSBD_Handle_t *pdevice);
+extern TUSBD_ERCODE usb_device_openep(TUSBD_Handle_t *pdevice, uint8_t addr, uint8_t type, uint16_t mps);
+extern TUSBD_ERCODE usb_device_closeep(TUSBD_Handle_t *pdevice, uint8_t addr);
+extern TUSBD_ERCODE usb_device_flushep(TUSBD_Handle_t *pdevice, uint8_t addr);
+extern TUSBD_ERCODE usb_device_stallep(TUSBD_Handle_t *pdevice, uint8_t addr);
+extern TUSBD_ERCODE usb_device_clearep(TUSBD_Handle_t *pdevice, uint8_t addr);
+extern uint8_t      usb_device_getstallcondition(TUSBD_Handle_t *pdevice, uint8_t addr);
+extern TUSBD_ERCODE usb_device_transmitdata(TUSBD_Handle_t *pdevice, uint8_t addr, uint8_t *pbuf, uint16_t size);
+extern TUSBD_ERCODE usb_device_startreceive(TUSBD_Handle_t *pdevice, uint8_t addr, uint8_t *pbuf, uint16_t size);
+extern TUSBD_ERCODE usb_device_testmode(TUSBD_Handle_t *pdevice);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _USB_DEVICE_DRIVER_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_otg/Makefile.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_otg/Makefile.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_otg/Makefile.config	(revision 453)
@@ -0,0 +1,63 @@
+#
+#   TOPPERS/ASP/FMP Kernel
+#       Toyohashi Open Platform for Embedded Real-Time Systems/
+#       Advanced Standard Profile Kernel
+#
+#   Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                               Toyohashi Univ. of Technology, JAPAN
+#   Copyright (C) 2003-2008 by Ryosuke Takeuchi
+#                Platform Development Center RICOH COMPANY,LTD. JAPAN
+#   Copyright (C) 2015-2017 by TOPPERS PROJECT Educational Working Group.
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+ 
+#
+#  Makefile のプロセッサ依存 (usb_otg:dwc2用)
+#
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/gdic/usb_otg
+
+#
+#  USB OTG(GDIC)に関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR):$(SRCDIR)/gdic/usb_otg
+ifneq ($(USB_OTG_MODE),USB_OTG_MODE_DEVICE)
+ifneq ($(USB_OTG_MODE),)
+SYSSVC_COBJS := $(SYSSVC_COBJS) dwc2_host_driver.o
+endif
+endif
+ifneq ($(USB_OTG_MODE),USB_OTG_MODE_HOST)
+SYSSVC_COBJS := $(SYSSVC_COBJS) dwc2_device_driver.o
+endif
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_otg/dwc2_device_driver.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_otg/dwc2_device_driver.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_otg/dwc2_device_driver.c	(revision 453)
@@ -0,0 +1,559 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  USB DEVICE HIGH DRIVERS
+ */
+
+#include "kernel_impl.h"
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <sil.h>
+#include <target_syssvc.h>
+#include "device.h"
+
+#include "stdlib.h"
+#include "tusbd_base.h"
+#include "usb_otg.h"
+
+#define sil_orw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) | (b))
+#define sil_andw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) & ~(b))
+
+#ifndef MAX_DEVICE_EPS
+#define MAX_DEVICE_EPS          (MAX_EPS_CHANNELS-1)
+#endif
+
+/*
+ *  SETUPSTAGE CALLBACK関数
+ */
+static void
+tusbdSetupStageCallback(USB_OTG_Handle_t *husb)
+{
+	tusbdSetSpeed(husb->pDev, usbo_getDevSpeed(husb));
+	tusbdSetupStage(husb->pDev, (uint8_t *)husb->Setup);
+}
+
+/*
+ *  DATAOUTSTAGE CALLBACK関数
+ */
+static void
+tusbdDataOutStageCallback(USB_OTG_Handle_t *husb, uint8_t epnum)
+{
+	tusbdDataOutStage(husb->pDev, epnum, husb->OUT_ep[epnum].xfer_buff);
+}
+
+/*
+ *  DATAINSTAGE CALLBACK関数
+ */
+static void
+tusbdDataInStageCallback(USB_OTG_Handle_t *husb, uint8_t epnum)
+{
+	tusbdDataInStage(husb->pDev, epnum, husb->IN_ep[epnum].xfer_buff);
+}
+
+/*
+ *  DEVICE RESET CALLBACK関数
+ */
+static void
+tusbdResetCallback(USB_OTG_Handle_t *husb)
+{
+	uint8_t speed = USB_DEVICE_SPEED_FULL;
+
+	/* Set USB Current Speed */
+	switch(husb->Init.speed){
+	case USB_SPEED_HIGH:
+		speed = USB_DEVICE_SPEED_HIGH;
+		break;
+	case USB_SPEED_FULL:
+		speed = USB_DEVICE_SPEED_FULL;
+		break;
+	default:
+		speed = USB_DEVICE_SPEED_FULL;
+		break;
+	}
+
+	/*
+	 *  DEVICEのリセット
+	 */
+	tusbdReset(husb->pDev);
+	tusbdSetSpeed(husb->pDev, speed);
+}
+
+/*
+ *  DEVICE SUSPEND CALLBACK関数
+ */
+static void
+tusbdSuspendCallback(USB_OTG_Handle_t *husb)
+{
+	tusbdSuspend(husb->pDev);
+#if 1	/* ROI DEBUG */
+	syslog_0(LOG_NOTICE, "## tusbdSuspendCallback ##");
+#endif
+}
+
+/*
+ *  DEVICE RESUME CALLBACK関数
+ */
+static void
+tusbdResumeCallback(USB_OTG_Handle_t *husb)
+{
+	tusbdResume(husb->pDev);
+#if 1	/* ROI DEBUG */
+	syslog_0(LOG_NOTICE, "## tusbdResumeCallback ##");
+#endif
+}
+
+/*
+ *  ISOOUTCOMPLETE CALLBACK関数
+ */
+static void
+tusbdISOOUTIncompleteCallback(USB_OTG_Handle_t *husb, uint8_t epnum)
+{
+	tusbdIsoOutIncomplete(husb->pDev, epnum);
+}
+
+/*
+ *  ISOINCOMPLETE CALLBACK関数
+ */
+static void
+tusbdISOINIncompleteCallback(USB_OTG_Handle_t *husb, uint8_t epnum)
+{
+	tusbdIsoInIncomplete(husb->pDev, epnum);
+}
+
+/*
+ *  DEVICE CONNECT CALLBACK関数
+ */
+static void
+tusbdConnectCallback(USB_OTG_Handle_t *husb)
+{
+	tusbdDeviceConnected(husb->pDev);
+}
+
+/*
+ *  DEVICE DISCONNECT CALLBACK関数
+ */
+static void
+tusbdDisconnectCallback(USB_OTG_Handle_t *husb)
+{
+	tusbdDeviceDisconnected(husb->pDev);
+}
+
+/*
+ *  ENDPOINT取得
+ */
+static USB_OTG_EPTypeDef *
+tusbdGetEndpoint(USB_OTG_Handle_t *husb, uint8_t addr)
+{
+	USB_OTG_EPTypeDef *ep;
+
+	if((addr & USB_DEVICE_TO_HOST) != 0){
+		ep = &husb->IN_ep[addr & 0x7F];
+	}
+	else{
+		ep = &husb->OUT_ep[addr & 0x7F];
+	}
+	ep->num   = addr & 0x7F;
+	ep->is_in = (USB_DEVICE_TO_HOST & addr) != 0;
+	return ep;
+}
+
+
+/*
+ *  USB_OTG DWC2 HIGH DRIVER INITIALIZE
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+dwc2_device_init(TUSBD_Handle_t *pdevice)
+{
+	USB_OTG_Handle_t *husb = (USB_OTG_Handle_t *)(pdevice->pSysData);
+	uint32_t i = 0;
+
+	/*
+	 *  USBハンドラに、USBデバイスハンドラをセット
+	 */
+	husb->pDev = pdevice;
+
+	/*
+	 *  コールバック関数をセット
+	 */
+	husb->devsetupstagecallback   = tusbdSetupStageCallback;
+	husb->devdataoutstagecallback = tusbdDataOutStageCallback;
+	husb->devdatainstagecallback  = tusbdDataInStageCallback;
+	husb->devsofcallback          = NULL;
+	husb->devresetcallback        = tusbdResetCallback;
+	husb->devsuspendcallback      = tusbdSuspendCallback;
+	husb->devresumecallback       = tusbdResumeCallback;
+	husb->devisooutcallback       = tusbdISOOUTIncompleteCallback;
+	husb->devisoincallback        = tusbdISOINIncompleteCallback;
+	husb->devconnectcallback      = tusbdConnectCallback;
+	husb->devdisconnectcallback   = tusbdDisconnectCallback;
+	husb->devlpmcallback          = NULL;
+
+	/*
+	 *  エンドポイントの初期化
+	 */
+	for(i = 0 ; i < MAX_DEVICE_EPS ; i++){
+		husb->IN_ep[i].is_in = 1;
+		husb->IN_ep[i].num = i;
+		husb->IN_ep[i].tx_fifo_num = i;
+		husb->IN_ep[i].type = EP_TYPE_CTRL;
+		husb->IN_ep[i].maxpacket = 0;
+		husb->IN_ep[i].xfer_buff = 0;
+		husb->IN_ep[i].xfer_len = 0;
+
+		husb->OUT_ep[i].is_in = 0;
+		husb->OUT_ep[i].num = i;
+		husb->OUT_ep[i].tx_fifo_num = 0;
+ 		husb->OUT_ep[i].type = EP_TYPE_CTRL;
+		husb->OUT_ep[i].maxpacket = 0;
+		husb->OUT_ep[i].xfer_buff = 0;
+		husb->OUT_ep[i].xfer_len = 0;
+	}
+
+	/*
+	 *  USBデバイスの初期化
+	 */
+	usbo_devinit(husb);
+
+	/*
+	 *  LPMの有効化
+	 */
+	usbo_init_lpm(husb);
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB_OTG DWC2 HIGH DRIVER DE-INITIALIZE
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  return     TUSBD_ERCODE
+  */
+TUSBD_ERCODE
+dwc2_device_deinit(TUSBD_Handle_t *pdevice)
+{
+	/*
+	 *  デバイス停止
+	 */
+	dwc2_device_stop(pdevice);
+
+	/*
+	 *  デバイスハードウェア終了
+	 */
+	usbo_deinit(pdevice->pSysData);
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB_OTG DWC2 HIGH DRIVER START
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  return     TUSBD_ERCODE
+  */
+TUSBD_ERCODE
+dwc2_device_start(TUSBD_Handle_t *pdevice)
+{
+	usbo_devconnect(pdevice->pSysData);
+	dly_tsk(3);
+	usbo_enableglobalint(pdevice->pSysData);
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB_OTG DWC2 HIGH DRIVER STOP
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  return     TUSBD_ERCODE
+  */
+TUSBD_ERCODE
+dwc2_device_stop(TUSBD_Handle_t *pdevice)
+{
+	usbo_disableglobalint(pdevice->pSysData);
+	usbo_stopdevice(pdevice->pSysData);
+	usbo_devdisconnect(pdevice->pSysData);
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB_OTG DWC2 HIGH DRIVER OPEN ENDPOINT
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  parameter2 addr:  endpointアドレス
+ *  parameter3 type:  endpointタイプ
+ *  parameter4 mps:   MAX PACKET SIZE
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+dwc2_device_openep(TUSBD_Handle_t *pdevice, uint8_t addr, uint8_t type, uint16_t mps)
+{
+	USB_OTG_Handle_t  *husb = pdevice->pSysData;
+	USB_OTG_EPTypeDef *ep;
+
+	ep = tusbdGetEndpoint(husb, addr);
+	ep->maxpacket = mps;
+	ep->type = type;
+	if(ep->is_in){
+		/* 送信FIFO設定 */
+		ep->tx_fifo_num = ep->num;
+	}
+
+	/*
+	 *  DATA PIDの初期化
+	 */
+	if (type == EP_TYPE_BULK){
+		ep->data_pid_start = 0;
+	}
+
+	usbo_activateEndpoint(husb, ep);
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB_OTG DWC2 HIGH DRIVER CLOSE ENDPOINT
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  parameter2 addr:  endpointアドレス
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+dwc2_device_closeep(TUSBD_Handle_t *pdevice, uint8_t addr)
+{
+	USB_OTG_Handle_t  *husb = pdevice->pSysData;
+	USB_OTG_EPTypeDef *ep;
+
+	ep = tusbdGetEndpoint(husb, addr);
+	usbo_deactivateEndpoint(husb, ep);
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB_OTG DWC2 HIGH DRIVER FLUSH ENDPOINT
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  parameter2 addr:  endpointアドレス
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+dwc2_device_flushep(TUSBD_Handle_t *pdevice, uint8_t addr)
+{
+	USB_OTG_Handle_t *husb = pdevice->pSysData;
+
+	if((addr & USB_DEVICE_TO_HOST) != 0){
+		usbo_flushTxFifo(husb, addr & 0x7F);
+	}
+	else{
+		usbo_flushRxFifo(husb);
+	}
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB_OTG DWC2 HIGH DRIVER STALL ENDPOINT
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  parameter2 addr:  endpointアドレス
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+dwc2_device_stallep(TUSBD_Handle_t *pdevice, uint8_t addr)
+{
+	USB_OTG_Handle_t  *husb = pdevice->pSysData;
+	USB_OTG_EPTypeDef *ep;
+
+	ep = tusbdGetEndpoint(husb, addr);
+	ep->is_stall = 1;
+
+	usbo_epsetStall(husb, ep);
+	if((addr & 0x7FU) == 0U){
+		usbo_ep0_outstart(husb, (uint8_t *)husb->Setup);
+	}
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB_OTG DWC2 HIGH DRIVER CLEAR STALL-ENDPOINT
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  parameter2 addr:  endpointアドレス
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+dwc2_device_clearep(TUSBD_Handle_t *pdevice, uint8_t addr)
+{
+	USB_OTG_Handle_t *husb = pdevice->pSysData;
+	USB_OTG_EPTypeDef *ep;
+
+	ep = tusbdGetEndpoint(husb, addr);
+	ep->is_stall = 0;
+
+	usbo_epclearStall(husb, ep);
+	return TUSBD_E_OK; 
+}
+
+/*
+ *  USB_OTG DWC2 HIGH DRIVER GET STALL CONDITION
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  parameter2 addr:  endpointアドレス
+ *  return     1:stall 0:not stall
+ */
+uint8_t
+dwc2_device_getstallcondition(TUSBD_Handle_t *pdevice, uint8_t addr)
+{
+	USB_OTG_Handle_t *husb = pdevice->pSysData;
+
+	if((addr & USB_DEVICE_TO_HOST) != 0)
+		return husb->IN_ep[addr & 0x7F].is_stall;
+	else
+		return husb->OUT_ep[addr & 0x7F].is_stall;
+}
+
+/*
+ *  USB_OTG DWC2 HIGH DRIVER TRANSMIT A DATA
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  parameter2 addr:  endpointアドレス
+ *  parameter3 pbuf:  送信データバッファ
+ *  parameter4 size:  送信サイズ
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+dwc2_device_transmitdata(TUSBD_Handle_t *pdevice, uint8_t addr, uint8_t *pbuf, uint16_t size)
+{
+	USB_OTG_Handle_t  *husb = pdevice->pSysData;
+	USB_OTG_EPTypeDef *ep;
+
+	ep = tusbdGetEndpoint(husb, (addr | USB_DEVICE_TO_HOST));
+
+	/*
+	 *  送信データ設定
+	 */
+	ep->xfer_buff = pbuf;
+	ep->xfer_len = size;
+	ep->xfer_count = 0;
+
+	if(husb->Init.dma_enable == 1)
+		ep->dma_addr = (uint32_t)pbuf;
+
+	if((addr & 0x7F) == 0U){
+		usbo_ep0startxfer(husb, ep);
+	}
+	else{
+		usbo_epstartxfer(husb, ep);
+	}
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB_OTG DWC2 HIGH DRIVER START to RECEIVE
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  parameter2 addr:  endpointアドレス
+ *  parameter3 pbuf:  受信データバッファ
+ *  parameter4 size:  受信サイズ
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+dwc2_device_startreceive(TUSBD_Handle_t *pdevice, uint8_t addr, uint8_t *pbuf, uint16_t size)
+{
+	USB_OTG_Handle_t  *husb = pdevice->pSysData;
+	USB_OTG_EPTypeDef *ep;
+
+	ep = tusbdGetEndpoint(husb, (addr & ~USB_DEVICE_TO_HOST));
+
+	/*
+	 *  受信データ設定
+	 */
+	ep->xfer_buff = pbuf;
+	ep->xfer_len = size;
+	ep->xfer_count = 0;
+
+	if(husb->Init.dma_enable == 1)
+		ep->dma_addr = (uint32_t)pbuf;
+
+	if((addr & 0x7F) == 0){
+		usbo_ep0startxfer(husb, ep);
+	}
+	else{
+		usbo_epstartxfer(husb, ep);
+	}
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB_OTG DWC2 HIGH DRIVER TEST MODE
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+dwc2_device_testmode(TUSBD_Handle_t *pdevice)
+{
+	return TUSBD_E_OK;
+}
+
+#ifndef TOPPERS_MPCORE
+/*
+ *  USB_OTG DWC2 HIGH DRIVER REMOTE WAKEUP
+ *  parameter1 pdevice:  USBデバイスハンドラ
+ *  return     TUSBD_ERCODE
+ */
+void
+dwc2_device_wakeup(USBD_HandleTypeDef *pdevice)
+{
+	USB_OTG_Handle_t *husb = pdevice->pSysData;
+
+	if(pdevice->dev_remote_wakeup == 1 && pdevice->dev_state == TUSBD_STATE_SUSPENDED){
+		if(husb->Init.low_power_enable){
+			/* Reset SLEEPDEEP bit of Cortex System Control Register */
+			sil_andw_mem((uint32_t *)(TADR_SCB_BASE+TOFF_SCB_SCR), (SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk));
+			sysclock_config(1);
+		}
+
+		/* Ungate PHY clock */
+		sil_andw_mem((uint32_t *)(USBPGC_BASE(husb->base)), USB_OTG_PCGCCTL_STOPCLK);
+
+		/* Activate Remote wakeup */
+		if((sil_rew_mem((uint32_t *)(USBD_BASE(husb->base)+TOFF_USBD_DSTS)) & USB_OTG_DSTS_SUSPSTS) != 0){
+			/* Activate Remote wakeup signaling */
+			sil_orw_mem((uint32_t *)(USBD_BASE(husb->base)+TOFF_USBD_DCTL), USB_OTG_DCTL_RWUSIG);
+		}
+
+		/* Remote wakeup delay */
+		sil_dly_nse(10*1000*1000);
+
+		/* Disable Remote wakeup */
+		sil_andw_mem((uint32_t *)(USBD_BASE(husb->base)+TOFF_USBD_DCTL), USB_OTG_DCTL_RWUSIG);
+
+		/* change state to configured */
+		pdevice->dev_state = TUSBD_STATE_CONFIGURED;
+
+		/* Change remote_wakeup feature to 0*/
+		pdevice->dev_remote_wakeup = 0;
+	}
+}
+#endif	/* TOPPERS_MPCORE */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_otg/dwc2_device_driver.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_otg/dwc2_device_driver.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_otg/dwc2_device_driver.h	(revision 453)
@@ -0,0 +1,78 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2017 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  DWC2 DEVICE HIGH DRIVER インクルードファイル
+ */
+
+
+#ifndef _DWC2_DEVICE_DRIVER_H_
+#define _DWC2_DEVICE_DRIVER_H_
+
+#include "tusb_rtos.h"
+#include "usb_otg.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#define dwc2_device_getrxdatasize(d, a)  (((USB_OTG_Handle_t *)((d)->pSysData))->OUT_ep[(a) & 0x7F].xfer_count)
+
+/*
+ *  DWC2 DEVICE HIGH DRIVER関数プロトタイプ宣言
+ */
+extern TUSBD_ERCODE dwc2_device_init(TUSBD_Handle_t *pdevice);
+extern TUSBD_ERCODE dwc2_device_deinit(TUSBD_Handle_t *pdevice);
+extern TUSBD_ERCODE dwc2_device_start(TUSBD_Handle_t *pdevice);
+extern TUSBD_ERCODE dwc2_device_stop(TUSBD_Handle_t *pdevice);
+extern TUSBD_ERCODE dwc2_device_openep(TUSBD_Handle_t *pdevice, uint8_t addr, uint8_t type, uint16_t mps);
+extern TUSBD_ERCODE dwc2_device_closeep(TUSBD_Handle_t *pdevice, uint8_t addr);
+extern TUSBD_ERCODE dwc2_device_flushep(TUSBD_Handle_t *pdevice, uint8_t addr);
+extern TUSBD_ERCODE dwc2_device_stallep(TUSBD_Handle_t *pdevice, uint8_t addr);
+extern TUSBD_ERCODE dwc2_device_clearep(TUSBD_Handle_t *pdevice, uint8_t addr);
+extern uint8_t      dwc2_device_getstallcondition(TUSBD_Handle_t *pdevice, uint8_t addr);
+extern TUSBD_ERCODE dwc2_device_transmitdata(TUSBD_Handle_t *pdevice, uint8_t addr, uint8_t *pbuf, uint16_t size);
+extern TUSBD_ERCODE dwc2_device_startreceive(TUSBD_Handle_t *pdevice, uint8_t addr, uint8_t *pbuf, uint16_t size);
+extern TUSBD_ERCODE dwc2_device_testmode(TUSBD_Handle_t *pdevice);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DWC2_DEVICE_DRIVER_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_otg/dwc2_host_driver.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_otg/dwc2_host_driver.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_otg/dwc2_host_driver.c	(revision 453)
@@ -0,0 +1,456 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  USB HOST HIGH DRIVERS
+ */
+
+#include "tusbh_base.h"
+#include "kernel_cfg.h"
+#include "usb_otg.h"
+
+/*
+ *  URBの変換テーブル
+ */
+static const uint8_t urb_table[8] = {
+	TUSBH_URB_IDLE,
+	TUSBH_URB_DONE,
+	TUSBH_URB_NOTREADY,
+	TUSBH_URB_NYET,
+	TUSBH_URB_ERROR,
+	TUSBH_URB_STALL,
+	TUSBH_URB_ERROR,
+	TUSBH_URB_ERROR
+};
+
+/*
+ *  USB HOST CLASS リンク関数
+ */
+__attribute__((weak)) void tusbhLinkHID(TUSBH_Handle_t *phost)
+{
+}
+
+__attribute__((weak)) void tusbhLinkMSC(TUSBH_Handle_t *phost)
+{
+}
+
+__attribute__((weak)) void tusbhLinkSERIAL(TUSBH_Handle_t *phost)
+{
+}
+
+__attribute__((weak)) void tusbhLinkPRT(TUSBH_Handle_t *phost)
+{
+}
+
+__attribute__((weak)) void tusbhLinkBLUETOOTH(TUSBH_Handle_t *phost)
+{
+}
+
+__attribute__((weak)) void tusbhLinkHUB(TUSBH_Handle_t *phost)
+{
+}
+
+
+
+#ifdef TOPPERS_MPCORE
+/*
+ *  IDCHANGE CALLBACK関数
+ */
+static void
+dwc2_host_idchangecallback(USB_OTG_Handle_t *hhcd)
+{
+	tusbiSendData(((TUSBH_Handle_t *)(hhcd->pHost))->connect_event, TUSBH_IDCHANGE_EVENT, 0, 1, 0);
+}
+#endif	/* TOPPERS_MPCORE */
+
+/*
+ *  CONNECT CALLBACK関数
+ */
+static void
+dwc2_host_connectcallback(USB_OTG_Handle_t *hhcd)
+{
+	tusbiSendData(((TUSBH_Handle_t *)(hhcd->pHost))->connect_event, TUSBH_CONNECT_EVENT, 0, 1, 0);
+}
+
+/*
+ *  DISCONNECT CALLBACK関数
+ */
+static void
+dwc2_host_disconnectcallback(USB_OTG_Handle_t *hhcd)
+{
+	tusbiSendData(((TUSBH_Handle_t *)(hhcd->pHost))->connect_event, TUSBH_DISCONNECT_EVENT, 0, 1, 0);
+}
+
+/*
+ *  URB CHANGE CALLBACK関数
+ */
+static void
+dwc2_host_changeurbcallback(USB_OTG_Handle_t *hhcd, uint8_t chnum, uint8_t urb_state)
+{
+	TUSBH_Handle_t *phost = hhcd->pHost;
+	uint8_t urb;
+
+	if(urb_state < 8)
+		urb = urb_table[urb_state];
+	else
+		urb = TUSBH_URB_ERROR;
+	tusbiSendData(phost->process_event, TUSBH_URB_EVENT, phost->pipes[chnum].index, chnum, urb);
+}
+
+
+/*
+ *  USB_OTG DWC2 HIGH DRIVER INITIALIZE
+ *  parameter1 phost:  USBホストハンドラ
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+dwc2_host_init(TUSBH_Handle_t *phost)
+{
+	USB_OTG_Handle_t *husb = (USB_OTG_Handle_t *)(phost->pSysData);
+
+	/*
+	 *  RTOSリソース設定
+	 */
+	phost->processTaskID = TUSBH_P_TASK;
+	phost->eventTaskID   = TUSBH_E_TASK;
+	phost->process_event = USBH_EVT1_DTQ;
+	phost->connect_event = USBH_EVT2_DTQ;
+	phost->numPipes = husb->Init.host_channels;
+
+	/*
+	 *  USB-OTGドライバ設定
+	 */
+	husb->pHost = phost;
+
+	/*
+	 *  コールバック関数設定
+	 */
+#ifdef TOPPERS_MPCORE
+	husb->otgidchangecallback    = dwc2_host_idchangecallback;
+#endif	/* TOPPERS_MPCORE */
+	husb->hostsofcallback        = NULL;
+	husb->hostconnectcallback    = dwc2_host_connectcallback;
+	husb->hostdisconnectcallback = dwc2_host_disconnectcallback;
+	husb->hostchangeurbcallback  = dwc2_host_changeurbcallback;
+
+	/*
+	 *  USB-OTG初期化
+	 */
+	usbo_hostinit(husb);
+
+	/*
+	 *  USBホストクラスのリンク
+	 */
+	tusbhLinkHID(phost);
+	tusbhLinkMSC(phost);
+	tusbhLinkSERIAL(phost);
+	tusbhLinkPRT(phost);
+	tusbhLinkBLUETOOTH(phost);
+	tusbhLinkHUB(phost);
+	return TUSBH_E_OK;
+}
+
+/*
+ *  USB_OTG DWC2 HIGH DRIVER DE-INITIALIZE
+ *  parameter1 phost:  USBホストハンドラ
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+dwc2_host_deinit(TUSBH_Handle_t *phost)
+{
+	USB_OTG_Handle_t *husb = phost->pSysData;
+
+	/*
+	 *  USB-OTG終了処理
+	 */
+	usbo_deinit(husb);
+
+#if 0	/* ROI DEBUG クロック停止なので意味がない */
+	usbo_disableglobalint(husb);
+#endif	/* ROI DEBUG */
+	return TUSBH_E_OK;
+}
+
+/*
+ *  USB_OTG DWC2 HIGH DRIVER START
+ *  parameter1 phost:  USBホストハンドラ
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+dwc2_host_start(TUSBH_Handle_t *phost)
+{
+	usbo_starthost(phost->pSysData);
+	usbo_enableglobalint(phost->pSysData);
+	return TUSBH_E_OK; 
+}
+
+/*
+ *  USB_OTG DWC2 HIGH DRIVER GET SPEED
+ *  parameter1 phost:  USBホストハンドラ
+ *  return     usb speed value
+ */
+uint8_t
+dwc2_host_getspeed(TUSBH_Handle_t *phost)
+{
+	uint8_t speed = USB_DEVICE_SPEED_FULL;
+
+	switch(usbo_gethostspeed(phost->pSysData)){
+	case 0:
+		speed = USB_DEVICE_SPEED_HIGH;
+		break;
+	case 2:
+		speed = USB_DEVICE_SPEED_LOW;
+		break;
+	case 1:
+	default:
+		speed = USB_DEVICE_SPEED_FULL;
+		break;
+	}
+	return speed;
+}
+
+/*
+ *  USB_OTG DWC2 HIGH DRIVER OPEN PIPE
+ *  parameter1 phost:   USBホストハンドラ
+ *  parameter2 pipe:    PIPE#
+ *  parameter3 epnum:   EP番号
+ *  parameter4 dev_addr:デバイスアドレス
+ *  parameter5 speed:   デバイススピード
+ *  parameter6 type:    エンドポイントタイプ
+ *  parameter7 eps:     MAXパケットサイズ
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+dwc2_host_openpipe(TUSBH_Handle_t *phost, uint8_t pipe, uint8_t epnum, uint8_t dev_addr,
+					uint8_t speed, uint8_t type, uint16_t mps)
+{
+	USB_OTG_Handle_t  *husb = (USB_OTG_Handle_t *)(phost->pSysData);
+	USB_OTG_HCTypeDef *phc = &husb->hc[pipe];
+
+	phc->dev_addr = dev_addr;
+	phc->max_packet = mps;
+	phc->ch_num = pipe;
+	phc->ep_type = type;
+	phc->ep_num = epnum & 0x7F;
+	phc->ep_is_in = ((epnum & 0x80) == 0x80);
+	phc->speed = speed;
+
+	if(usbo_hc_init(husb, pipe, epnum) == E_OK)
+		return TUSBH_E_OK;
+	else
+		return TUSBH_E_ERR;
+}
+
+/*
+ *  USB_OTG DWC2 HIGH DRIVER CLOSE PIPE
+ *  parameter1 phost:   USBホストハンドラ
+ *  parameter2 pipe:    PIPE#
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+dwc2_host_closepipe(TUSBH_Handle_t *phost, uint8_t pipe)
+{
+	loc_cpu();
+	usbo_hc_halt(phost->pSysData, pipe);
+	unl_cpu();
+	return TUSBH_E_OK;
+}
+
+/*
+ *  USB_OTG DWC2 HIGH DRIVER SUBMIT URB
+ *  parameter1 phost:   USBホストハンドラ
+ *  parameter2 pipe:    PIPE#
+ *  parameter3 dir:     接続方向:0Out/1:In
+ *  parameter4 token:   エンドポイント設定タイプ:0:SETUP/1:DATA
+ *  parameter5 pbuff:   通信領域へのポインタ
+ *  parameter6 length:  通信サイズ
+ *  parameter7 do_ping: DO PING設定
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+dwc2_host_submiturb(TUSBH_Handle_t *phost, uint8_t pipe, uint8_t dir,
+					uint8_t token, uint8_t* pbuff, uint16_t length, uint8_t do_ping)
+{
+	USB_OTG_Handle_t *husb = (USB_OTG_Handle_t *)phost->pSysData;
+
+#ifdef TOPPERS_MPCORE
+	usbo_dma_wait(husb, pipe);
+#endif	/* TOPPERS_MPCORE */
+	husb->hc[pipe].ep_is_in = dir;
+
+	if(token == 0)
+		husb->hc[pipe].data_pid = HC_PID_SETUP;
+	else
+		husb->hc[pipe].data_pid = HC_PID_DATA1;
+
+	/* Manage Data Toggle */
+	switch(husb->hc[pipe].ep_type){
+	case EP_TYPE_CTRL:
+		if(token == 1 && dir == 0){ /*send data */
+			if(length == 0){	/* For Status OUT stage, Length==0, Status Out PID = 1 */
+				husb->hc[pipe].toggle_out = 1;
+			}
+
+			/* Set the Data Toggle bit as per the Flag */
+			if(husb->hc[pipe].toggle_out == 0){	/* Put the PID 0 */
+				husb->hc[pipe].data_pid = HC_PID_DATA0;
+			}
+			else{	/* Put the PID 1 */
+				husb->hc[pipe].data_pid = HC_PID_DATA1;
+			}
+			if(husb->hc[pipe].urb_state != URB_NOTREADY){
+				husb->hc[pipe].do_ping = do_ping;
+			}
+		}
+		break;
+
+	case EP_TYPE_BULK:
+		if(dir == 0){
+			/* Set the Data Toggle bit as per the Flag */
+			if(husb->hc[pipe].toggle_out == 0){	/* Put the PID 0 */
+				husb->hc[pipe].data_pid = HC_PID_DATA0;
+			}
+			else{	/* Put the PID 1 */
+				husb->hc[pipe].data_pid = HC_PID_DATA1;
+			}
+			if(husb->hc[pipe].urb_state != URB_NOTREADY){
+				husb->hc[pipe].do_ping = do_ping;
+			}
+		}
+		else{
+			if(husb->hc[pipe].toggle_in == 0){
+				husb->hc[pipe].data_pid = HC_PID_DATA0;
+			}
+			else{
+				husb->hc[pipe].data_pid = HC_PID_DATA1;
+			}
+		}
+		break;
+	case EP_TYPE_INTR:
+		if(dir == 0){
+			/* Set the Data Toggle bit as per the Flag */
+			if(husb->hc[pipe].toggle_out == 0){	/* Put the PID 0 */
+				husb->hc[pipe].data_pid = HC_PID_DATA0;
+			}
+			else{	/* Put the PID 1 */
+				husb->hc[pipe].data_pid = HC_PID_DATA1;
+			}
+		}
+		else{
+			if(husb->hc[pipe].toggle_in == 0){
+				husb->hc[pipe].data_pid = HC_PID_DATA0;
+			}
+			else{
+				husb->hc[pipe].data_pid = HC_PID_DATA1;
+			}
+		}
+		break;
+	case EP_TYPE_ISOC: 
+		husb->hc[pipe].data_pid = HC_PID_DATA0;
+		break;
+	}
+
+	husb->hc[pipe].xfer_buff = pbuff;
+	husb->hc[pipe].xfer_len  = length;
+	husb->hc[pipe].urb_state = URB_IDLE;
+	husb->hc[pipe].xfer_count = 0;
+	husb->hc[pipe].ch_num = pipe;
+	husb->hc[pipe].state = USBO_HC_IDLE;
+
+	usbo_hc_startxfer(husb, pipe);
+	return TUSBH_E_OK;
+}
+
+/*
+ *  USB_OTG DWC2 HIGH DRIVER CHECK PIPE STATE
+ *  parameter1 phost:   USBホストハンドラ
+ *  parameter2 pipe:    PIPE#
+ *  return     TUSBH_ERCODE
+ */
+bool_t
+dwc2_host_checkpipe(TUSBH_Handle_t *phost, uint8_t pipe)
+{
+	USB_OTG_Handle_t *husb = (USB_OTG_Handle_t *)(phost->pSysData);
+
+	if(pipe < husb->Init.host_channels && husb->hc[pipe].state != USBO_HC_FAIL)
+		return true;
+	else
+		return false;
+}
+
+/*
+ *  USB_OTG DWC2 HIGH DRIVER SET PIPE TOGGLE VALUE
+ *  parameter1 phost:   USBホストハンドラ
+ *  parameter2 pipe:    PIPE#
+ *  parameter3 toggle:  トグル値
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+dwc2_host_settoggle(TUSBH_Handle_t *phost, uint8_t pipe, uint8_t toggle)
+{
+	USB_OTG_Handle_t *husb = (USB_OTG_Handle_t *)(phost->pSysData);
+
+	if(husb->hc[pipe].ep_is_in){
+		husb->hc[pipe].toggle_in = toggle;
+	}
+	else{
+		husb->hc[pipe].toggle_out = toggle;
+	}
+	return TUSBH_E_OK; 
+}
+
+/*
+ *  USB_OTG DWC2 HIGH DRIVER GET PIPE TOGGLE VALUE
+ *  parameter1 phost:   USBホストハンドラ
+ *  parameter2 pipe:    PIPE#
+ *  return    トグル値
+ */
+uint8_t
+dwc2_host_gettoggle(TUSBH_Handle_t *phost, uint8_t pipe)
+{
+	USB_OTG_Handle_t *husb = (USB_OTG_Handle_t *)(phost->pSysData);
+	uint8_t toggle = 0;
+
+	if(husb->hc[pipe].ep_is_in){
+		toggle = husb->hc[pipe].toggle_in;
+	}
+	else{
+		toggle = husb->hc[pipe].toggle_out;
+	}
+	return toggle;
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_otg/dwc2_host_driver.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_otg/dwc2_host_driver.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_otg/dwc2_host_driver.h	(revision 453)
@@ -0,0 +1,75 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2017 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  DWC2 HIGH DRIVER インクルードファイル
+ */
+
+
+#ifndef _DWC2_HOST_DRIVER_H_
+#define _DWC2_HOST_DRIVER_H_
+
+#include "tusb_rtos.h"
+#include "usb_otg.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#define dwc2_host_gettraslength(h, n)   (((USB_OTG_Handle_t *)((h)->pSysData))->hc[(n)].xfer_count)
+
+/*
+ *  DWC2 HOST HIGH DRIVER関数プロトタイプ宣言
+ */
+extern TUSBH_ERCODE dwc2_host_init(TUSBH_Handle_t *phost);
+extern TUSBH_ERCODE dwc2_host_deinit(TUSBH_Handle_t *phost);
+extern TUSBH_ERCODE dwc2_host_start(TUSBH_Handle_t *phost);
+extern uint8_t      dwc2_host_getspeed(TUSBH_Handle_t *phost);
+
+extern TUSBH_ERCODE dwc2_host_openpipe(TUSBH_Handle_t *phost, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint16_t);
+extern TUSBH_ERCODE dwc2_host_closepipe(TUSBH_Handle_t *phost, uint8_t);
+extern TUSBH_ERCODE dwc2_host_submiturb(TUSBH_Handle_t *phost, uint8_t, uint8_t,  uint8_t, uint8_t*, uint16_t, uint8_t);
+extern bool_t       dwc2_host_checkpipe(TUSBH_Handle_t *phost, uint8_t pipe);
+extern TUSBH_ERCODE dwc2_host_settoggle(TUSBH_Handle_t *phost, uint8_t , uint8_t);
+extern uint8_t      dwc2_host_gettoggle(TUSBH_Handle_t *phost, uint8_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DWC2_HOST_DRIVER_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_otg/tusbd_conf.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_otg/tusbd_conf.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_otg/tusbd_conf.h	(revision 453)
@@ -0,0 +1,94 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2017 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  TOPPERS USB DEVICE MODULE CONFIGURATION インクルードファイル
+ */
+
+#ifndef _TUSBD_CONF_H_
+#define _TUSBD_CONF_H_
+
+#include "dwc2_device_driver.h"
+
+#define TUSBD_MAX_NUM_INTERFACES              1
+#define TUSBD_MAX_NUM_CONFIGURATION           1
+#define TUSBD_NUM_ENDPOINT                    15
+#define TUSBD_CONFIG_SELF_POWERED             0x01
+
+#define USBD_StatusTypeDef   TUSBD_ERCODE
+#define USBD_HandleTypeDef   TUSBD_Handle_t
+#define USBD_Init            tusbdInit
+#define USBD_Start           tusbdStart
+
+extern uint8_t defaultDeviceDescriptor[];
+extern uint8_t defaultDeviceQualifierDescriptor[];
+extern uint8_t defaultLanguageIDDescriptor[];
+extern uint8_t defaultManufacturerString[];
+extern uint8_t defaultProductString[];
+extern uint8_t defaultSerialString[];
+extern uint8_t defaultConfigurationString[];
+extern uint8_t defaultInterfaceString[];
+
+#define TUSBD_DEVICE_DESCRIPTOR               defaultDeviceDescriptor
+#define TUSBD_DEVICE_QUALIFIER_DESCRIPTOR     defaultDeviceQualifierDescriptor
+#define TUSBD_LANGUAGEID_DESCRIPTOR           defaultLanguageIDDescriptor
+#define TUSBD_MANUFACTURER_STRING             defaultManufacturerString
+#define TUSBD_PRODUCT_STRING                  defaultProductString
+#define TUSBD_SERIAL_STRING                   defaultSerialString
+#define TUSBD_CONFIGURATION_STRING            defaultConfigurationString
+#define TUSBD_INTERFACE_STRING                defaultInterfaceString
+#define TUSBD_USER_STRING                     NULL
+
+#define tusbdDriverSetUSBAddress(d, a)  usbo_setDevAddress(((d)->pSysData), (a))
+#define tusbdDriverGetRxDataSize        dwc2_device_getrxdatasize
+
+#define tusbdDriverInit                 dwc2_device_init
+#define tusbdDriverDeInit               dwc2_device_deinit
+#define tusbdDriverStart                dwc2_device_start
+#define tusbdDriverStop                 dwc2_device_stop
+#define tusbdDriverOpenEp               dwc2_device_openep
+#define tusbdDriverCloseEp              dwc2_device_closeep
+#define tusbdDriverFlushEp              dwc2_device_flushep
+#define tusbdDriverStallEp              dwc2_device_stallep
+#define tusbdDriverClearStallEp         dwc2_device_clearep
+#define tusbdDriverStallConditionEp     dwc2_device_getstallcondition
+#define tusbdDriverStartTransmit        dwc2_device_transmitdata
+#define tusbdDriverSetupReceive         dwc2_device_startreceive
+#define tusbdDriverTestMode             dwc2_device_testmode
+
+#endif /* _TUSBD_CONF_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_otg/tusbh_conf.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_otg/tusbh_conf.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/gdic/usb_otg/tusbh_conf.h	(revision 453)
@@ -0,0 +1,63 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2017 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  TOPPERS USB HOST MODULE CONFIGURATION インクルードファイル
+ */
+
+#ifndef _TUSBH_CONF_H_
+#define _TUSBH_CONF_H_
+
+#include "dwc2_host_driver.h"
+
+#define tusbhHDStop(h)              usbo_stophost((h)->pSysData)
+#define tusbhHDResetPort(h)         usbo_resetport((h)->pSysData)
+#define tusbhHDTrasLength           dwc2_host_gettraslength
+#define tusbhHDControlVBUS(h, s)    usbo_driveextvbus((h)->pSysData, s)
+
+#define tusbhHDInit         dwc2_host_init
+#define tusbhHDStart        dwc2_host_start
+#define tusbhHDGetSpeed     dwc2_host_getspeed
+#define tusbhHDOpenPipe     dwc2_host_openpipe
+#define tusbhHDClosePipe    dwc2_host_closepipe
+#define tsubhHDSubmitURB    dwc2_host_submiturb
+#define tusbhHDCheckPipe    dwc2_host_checkpipe
+#define tusbhHDSetToggle    dwc2_host_settoggle
+#define tusbhHDGetToggle    dwc2_host_gettoggle
+
+#endif /* _TUSBH_CONF_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/include/histogram.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/include/histogram.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/include/histogram.h	(revision 453)
@@ -0,0 +1,75 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2006-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		実行時間分布集計モジュール
+ */
+
+#ifndef TOPPERS_HISTOGRAM_H
+#define TOPPERS_HISTOGRAM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ *  実行時間分布計測の初期化
+ */
+extern void	init_hist(ID histid, uint_t maxval, uint_t histarea[]);
+
+/*
+ *  実行時間計測の開始
+ */
+extern void	begin_measure(ID histid);
+
+/*
+ *  実行時間計測の終了
+ */
+extern void	end_measure(ID histid);
+
+/*
+ *  実行時間分布計測の表示
+ */
+extern void	print_hist(ID histid);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TOPPERS_HISTOGRAM_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/include/itron.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/include/itron.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/include/itron.h	(revision 453)
@@ -0,0 +1,137 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		ITRON仕様共通規定のデータ型・定数・マクロ
+ *
+ *  このヘッダファイルは，ITRON仕様共通規定のデータ型・定数・マクロの中
+ *  で，TOPPERS共通ヘッダファイルに含まれないものの定義を含む．ITRON仕
+ *  様との互換性を必要とするアプリケーションがインクルードすることを想
+ *  定している．
+ *
+ *  アセンブリ言語のソースファイルからこのファイルをインクルードする時
+ *  は，TOPPERS_MACRO_ONLYを定義しておく．これにより，マクロ定義以外を
+ *  除くようになっている．
+ */
+
+#ifndef TOPPERS_ITRON_H
+#define TOPPERS_ITRON_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ *  TOPPERS共通ヘッダファイル
+ */
+#include "t_stddef.h"
+
+/*
+ *  ITRON仕様共通データ型
+ */
+#ifndef TOPPERS_MACRO_ONLY
+
+#ifdef INT8_MAX
+typedef	int8_t			B;			/* 符号付き8ビット整数 */
+#endif /* INT8_MAX */
+
+#ifdef UINT8_MAX
+typedef	uint8_t			UB;			/* 符号無し8ビット整数 */
+typedef	uint8_t			VB;			/* 型が定まらない8ビットの値 */
+#endif /* UINT8_MAX */
+
+typedef	int16_t			H;			/* 符号付き16ビット整数 */
+typedef	uint16_t		UH;			/* 符号無し16ビット整数 */
+typedef	uint16_t		VH;			/* 型が定まらない16ビットの値 */
+
+typedef	int32_t			W;			/* 符号付き32ビット整数 */
+typedef	uint32_t		UW;			/* 符号無し32ビット整数 */
+typedef	uint32_t		VW;			/* 型が定まらない32ビットの値 */
+
+#ifdef INT64_MAX
+typedef	int64_t			D;			/* 符号付き64ビット整数 */
+#endif /* INT64_MAX */
+
+#ifdef UINT64_MAX
+typedef	uint64_t		UD;			/* 符号無し64ビット整数 */
+typedef	uint64_t		VD;			/* 型が定まらない64ビットの値 */
+#endif /* UINT64_MAX */
+
+typedef	void			*VP;		/* 型が定まらないものへのポインタ */
+
+typedef int_t			INT;		/* 自然なサイズの符号付き整数 */
+typedef uint_t			UINT;		/* 自然なサイズの符号無し整数 */
+
+typedef bool_t			BOOL;		/* 真偽値 */
+
+typedef	intptr_t		VP_INT;		/* ポインタまたは符号付き整数 */
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+/*
+ *  ITRON仕様共通定数
+ */
+#define	TRUE		true			/* 真 */
+#define	FALSE		false			/* 偽 */
+
+/*
+ *  オブジェクト属性の定義
+ */
+#define TA_HLNG			UINT_C(0x00)	/* 高級言語用インタフェース */
+#define TA_TFIFO		UINT_C(0x00)	/* タスクの待ち行列をFIFO順に */
+#define TA_MFIFO		UINT_C(0x00)	/* メッセージキューをFIFO順に */
+#define TA_WSGL			UINT_C(0x00)	/* 待ちタスクは1つのみ */
+
+/*
+ *  ネスト回数の最大値
+ */
+#define TMAX_SUSCNT		UINT_C(1)		/* 強制待ち要求ネスト数の最大値 */
+
+/*
+ *  強制待ち状態からの強制再開
+ */
+#define frsm_tsk(tskid)		rsm_tsk(tskid)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TOPPERS_ITRON_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/include/kernel.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/include/kernel.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/include/kernel.h	(revision 453)
@@ -0,0 +1,635 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2014 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		TOPPERS/ASPカーネル 標準ヘッダファイル
+ *
+ *  TOPPERS/ASPカーネルがサポートするサービスコールの宣言と，必要なデー
+ *  タ型，定数，マクロの定義を含むヘッダファイル．
+ *
+ *  アセンブリ言語のソースファイルからこのファイルをインクルードする時
+ *  は，TOPPERS_MACRO_ONLYを定義しておく．これにより，マクロ定義以外を
+ *  除くようになっている．
+ *
+ *  このファイルをインクルードする前にインクルードしておくべきファイル
+ *  はない．
+ */
+
+#ifndef TOPPERS_KERNEL_H
+#define TOPPERS_KERNEL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ *	TOPPERS共通のデータ型・定数・マクロ
+ */
+#include <t_stddef.h>
+
+/*
+ *  ターゲット依存部
+ */
+#include "target_kernel.h"
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  データ型の定義
+ */
+
+/*
+ *  ビットパターンやオブジェクト番号の型定義
+ */
+typedef	uint_t		TEXPTN;		/* タスク例外要因のビットパターン */
+typedef	uint_t		FLGPTN;		/* イベントフラグのビットパターン */
+typedef	uint_t		INTNO;		/* 割込み番号 */
+typedef	uint_t		INHNO;		/* 割込みハンドラ番号 */
+typedef	uint_t		EXCNO;		/* CPU例外ハンドラ番号 */
+
+/*
+ *  処理単位の型定義
+ */
+typedef void	(*TASK)(intptr_t exinf);
+typedef void	(*TEXRTN)(TEXPTN texptn, intptr_t exinf);
+typedef void	(*CYCHDR)(intptr_t exinf);
+typedef void	(*ALMHDR)(intptr_t exinf);
+typedef void	(*ISR)(intptr_t exinf);
+typedef void	(*INTHDR)(void);
+typedef void	(*EXCHDR)(void *p_excinf);
+typedef void	(*INIRTN)(intptr_t exinf);
+typedef void	(*TERRTN)(intptr_t exinf);
+
+/*
+ *  メモリ領域確保のための型定義
+ */
+#ifndef TOPPERS_STK_T
+#define TOPPERS_STK_T	intptr_t
+#endif /* TOPPERS_STK_T */
+typedef	TOPPERS_STK_T	STK_T;	/* スタック領域を確保するための型 */
+
+#ifndef TOPPERS_MPF_T
+#define TOPPERS_MPF_T	intptr_t
+#endif /* TOPPERS_MPF_T */
+typedef	TOPPERS_MPF_T	MPF_T;	/* 固定長メモリプール領域を確保するための型 */
+
+/*
+ *  メッセージヘッダの型定義
+ */
+typedef	struct t_msg {			/* メールボックスのメッセージヘッダ */
+	struct t_msg	*pk_next;
+} T_MSG;
+
+typedef	struct t_msg_pri {		/* 優先度付きメッセージヘッダ */
+	T_MSG	msgque;				/* メッセージヘッダ */
+	PRI		msgpri;				/* メッセージ優先度 */
+} T_MSG_PRI;
+
+/*
+ *  パケット形式の定義
+ */
+typedef struct t_ctsk {
+	ATR			tskatr;		/* タスク属性 */
+	intptr_t	exinf;		/* タスクの拡張情報 */
+	TASK		task;		/* タスクのメインルーチンの先頭番地 */
+	PRI			itskpri;	/* タスクの起動時優先度 */
+	SIZE		stksz;		/* タスクのスタック領域のサイズ */
+	STK_T 		*stk;		/* タスクのスタック領域の先頭番地 */
+} T_CTSK;
+
+typedef struct t_rtsk {
+	STAT	tskstat;	/* タスク状態 */
+	PRI		tskpri;		/* タスクの現在優先度 */
+	PRI		tskbpri;	/* タスクのベース優先度 */
+	STAT	tskwait;	/* 待ち要因 */
+	ID		wobjid;		/* 待ち対象のオブジェクトのID */
+	TMO		lefttmo;	/* タイムアウトするまでの時間 */
+	uint_t	actcnt;		/* 起動要求キューイング数 */
+	uint_t	wupcnt;		/* 起床要求キューイング数 */
+} T_RTSK;
+
+typedef struct t_dtex {
+	ATR		texatr;		/* タスク例外処理ルーチン属性 */
+	TEXRTN	texrtn;		/* タスク例外処理ルーチンの先頭番地 */
+} T_DTEX;
+
+typedef struct t_rtex {
+	STAT	texstat;	/* タスク例外処理の状態 */
+	TEXPTN	pndptn;		/* 保留例外要因 */
+} T_RTEX;
+
+typedef struct t_csem {
+	ATR		sematr;		/* セマフォ属性 */
+	uint_t	isemcnt;	/* セマフォの初期資源数 */
+	uint_t	maxsem;		/* セマフォの最大資源数 */
+} T_CSEM;
+
+typedef struct t_rsem {
+	ID		wtskid;		/* セマフォの待ち行列の先頭のタスクのID番号 */
+	uint_t	semcnt;		/* セマフォの現在の資源数 */
+} T_RSEM;
+
+typedef struct t_cflg {
+	ATR		flgatr;		/* イベントフラグ属性 */
+	FLGPTN	iflgptn;	/* イベントフラグの初期ビットパターン */
+} T_CFLG;
+
+typedef struct t_rflg {
+	ID		wtskid;		/* イベントフラグの待ち行列の先頭のタスクのID番号 */
+	FLGPTN	flgptn;		/* イベントフラグの現在のビットパターン */
+} T_RFLG;
+
+typedef struct t_cdtq {
+	ATR		dtqatr;		/* データキュー属性 */
+	uint_t	dtqcnt;		/* データキュー管理領域に格納できるデータ数 */
+	void 	*dtqmb;		/* データキュー管理領域の先頭番地 */
+} T_CDTQ;
+
+typedef struct t_rdtq {
+	ID		stskid;		/* データキューの送信待ち行列の先頭のタスクのID番号 */
+	ID		rtskid;		/* データキューの受信待ち行列の先頭のタスクのID番号 */
+	uint_t	sdtqcnt;	/* データキュー管理領域に格納されているデータの数 */
+} T_RDTQ;
+
+typedef struct t_cpdq {
+	ATR		pdqatr;		/* 優先度データキュー属性 */
+	uint_t	pdqcnt;		/* 優先度データキュー管理領域に格納できるデータ数 */
+	PRI		maxdpri;	/* 優先度データキューに送信できるデータ優先度の最
+						   大値 */
+	void 	*pdqmb;		/* 優先度データキュー管理領域の先頭番地 */
+} T_CPDQ;
+
+typedef struct t_rpdq {
+	ID		stskid;		/* 優先度データキューの送信待ち行列の先頭のタスク
+						   のID番号 */
+	ID		rtskid;		/* 優先度データキューの受信待ち行列の先頭のタスク
+						   のID番号 */
+	uint_t	spdqcnt;	/* 優先度データキュー管理領域に格納されているデー
+						   タの数 */
+} T_RPDQ;
+
+typedef struct t_cmbx {
+	ATR		mbxatr;		/* メールボックス属性 */
+	PRI		maxmpri;	/* 優先度メールボックスに送信できるメッセージ優先
+						   度の最大値 */
+	void 	*mprihd;	/* 優先度別のメッセージキューヘッダ領域の先頭番地 */
+} T_CMBX;
+
+typedef struct t_rmbx {
+	ID		wtskid;		/* メールボックスの待ち行列の先頭のタスクのID番号 */
+	T_MSG	*pk_msg;	/* メッセージキューの先頭につながれたメッセージ
+						   の先頭番地 */
+} T_RMBX;
+
+typedef struct t_cmtx {
+	ATR		mtxatr;		/* ミューテックス属性 */
+	PRI		ceilpri;	/* 優先度ミューテックスに送信できるメッセージ優先
+						   度の最大値 */
+	void 	*mprihd;	/* 優先度別のメッセージキューヘッダ領域の先頭番地 */
+} T_CMTX;
+
+typedef struct t_rmtx {
+	ID		htskid;		/* ミューテックスをロックしているタスクのID番号 */
+	ID		wtskid;		/* ミューテックスの待ち行列の先頭のタスクのID番号 */
+} T_RMTX;
+
+typedef struct t_cmpf {
+	ATR		mpfatr;		/* 固定長メモリプール属性 */
+	uint_t	blkcnt;		/* 獲得できる固定長メモリブロックの数 */
+	uint_t	blksz;		/* 固定長メモリブロックのサイズ */
+	MPF_T 	*mpf;		/* 固定長メモリプール領域の先頭番地 */
+	void 	*mpfmb;		/* 固定長メモリプール管理領域の先頭番地 */
+} T_CMPF;
+
+typedef struct t_rmpf {
+	ID		wtskid;		/* 固定長メモリプールの待ち行列の先頭のタスクの
+						   ID番号 */
+	uint_t	fblkcnt;	/* 固定長メモリプール領域の空きメモリ領域に割り
+						   付けることができる固定長メモリブロックの数 */
+} T_RMPF;
+
+typedef struct t_ccyc {
+	ATR			cycatr;		/* 周期ハンドラ属性 */
+	intptr_t	exinf;		/* 周期ハンドラの拡張情報 */
+	CYCHDR		cychdr;		/* 周期ハンドラの先頭番地 */
+	RELTIM		cyctim;		/* 周期ハンドラの起動周期 */
+	RELTIM		cycphs;		/* 周期ハンドラの起動位相 */
+} T_CCYC;
+
+typedef struct t_rcyc {
+	STAT	cycstat;	/* 周期ハンドラの動作状態 */
+	RELTIM	lefttim;	/* 次に周期ハンドラを起動する時刻までの相対時間 */
+} T_RCYC;
+
+typedef struct t_calm {
+	ATR			almatr;		/* アラームハンドラ属性 */
+	intptr_t	exinf;		/* アラームハンドラの拡張情報 */
+	ALMHDR		almhdr;		/* アラームハンドラの先頭番地 */
+} T_CALM;
+
+typedef struct t_ralm {
+	STAT	almstat;	/* アラームハンドラの動作状態 */
+	RELTIM	lefttim;	/* アラームハンドラを起動する時刻までの相対時間 */
+} T_RALM;
+
+typedef struct t_cisr {
+	ATR			isratr;		/* 割込みサービスルーチン属性 */
+	intptr_t	exinf;		/* 割込みサービスルーチンの拡張情報 */
+	INTNO		intno;		/* 割込みサービスルーチンを登録する割込み番号 */
+	ISR			isr;		/* 割込みサービスルーチンの先頭番地 */
+	PRI			isrpri;		/* 割込みサービスルーチン優先度 */
+} T_CISR;
+
+/*
+ *  サービスコールの宣言
+ */
+
+/*
+ *  タスク管理機能
+ */
+extern ER_ID	acre_tsk(const T_CTSK *pk_ctsk) throw();
+extern ER		del_tsk(ID tskid) throw();
+extern ER		act_tsk(ID tskid) throw();
+extern ER		iact_tsk(ID tskid) throw();
+extern ER_UINT	can_act(ID tskid) throw();
+extern ER		ext_tsk(void) throw();
+extern ER		ter_tsk(ID tskid) throw();
+extern ER		chg_pri(ID tskid, PRI tskpri) throw();
+extern ER		get_pri(ID tskid, PRI *p_tskpri) throw();
+extern ER		get_inf(intptr_t *p_exinf) throw();
+extern ER		ref_tsk(ID tskid, T_RTSK *pk_rtsk) throw();
+
+/*
+ *  タスク付属同期機能
+ */
+extern ER		slp_tsk(void) throw();
+extern ER		tslp_tsk(TMO tmout) throw();
+extern ER		wup_tsk(ID tskid) throw();
+extern ER		iwup_tsk(ID tskid) throw();
+extern ER_UINT	can_wup(ID tskid) throw();
+extern ER		rel_wai(ID tskid) throw();
+extern ER		irel_wai(ID tskid) throw();
+extern ER		sus_tsk(ID tskid) throw();
+extern ER		rsm_tsk(ID tskid) throw();
+extern ER		dly_tsk(RELTIM dlytim) throw();
+
+/*
+ *  タスク例外処理機能
+ */
+extern ER		def_tex(ID tskid, const T_DTEX *pk_dtex) throw();
+extern ER		ras_tex(ID tskid, TEXPTN rasptn) throw();
+extern ER		iras_tex(ID tskid, TEXPTN rasptn) throw();
+extern ER		dis_tex(void) throw();
+extern ER		ena_tex(void) throw();
+extern bool_t	sns_tex(void) throw();
+extern ER		ref_tex(ID tskid, T_RTEX *pk_rtex) throw();
+
+/*
+ *  同期・通信機能
+ */
+extern ER_ID	acre_sem(const T_CSEM *pk_csem) throw();
+extern ER		del_sem(ID semid) throw();
+extern ER		sig_sem(ID semid) throw();
+extern ER		isig_sem(ID semid) throw();
+extern ER		wai_sem(ID semid) throw();
+extern ER		pol_sem(ID semid) throw();
+extern ER		twai_sem(ID semid, TMO tmout) throw();
+extern ER		ini_sem(ID semid) throw();
+extern ER		ref_sem(ID semid, T_RSEM *pk_rsem) throw();
+
+extern ER_ID	acre_flg(const T_CFLG *pk_cflg) throw();
+extern ER		del_flg(ID flgid) throw();
+extern ER		set_flg(ID flgid, FLGPTN setptn) throw();
+extern ER		iset_flg(ID flgid, FLGPTN setptn) throw();
+extern ER		clr_flg(ID flgid, FLGPTN clrptn) throw();
+extern ER		wai_flg(ID flgid, FLGPTN waiptn,
+						MODE wfmode, FLGPTN *p_flgptn) throw();
+extern ER		pol_flg(ID flgid, FLGPTN waiptn,
+						MODE wfmode, FLGPTN *p_flgptn) throw();
+extern ER		twai_flg(ID flgid, FLGPTN waiptn,
+						MODE wfmode, FLGPTN *p_flgptn, TMO tmout) throw();
+extern ER		ini_flg(ID flgid) throw();
+extern ER		ref_flg(ID flgid, T_RFLG *pk_rflg) throw();
+
+extern ER_ID	acre_dtq(const T_CDTQ *pk_cdtq) throw();
+extern ER		del_dtq(ID dtqid) throw();
+extern ER		snd_dtq(ID dtqid, intptr_t data) throw();
+extern ER		psnd_dtq(ID dtqid, intptr_t data) throw();
+extern ER		ipsnd_dtq(ID dtqid, intptr_t data) throw();
+extern ER		tsnd_dtq(ID dtqid, intptr_t data, TMO tmout) throw();
+extern ER		fsnd_dtq(ID dtqid, intptr_t data) throw();
+extern ER		ifsnd_dtq(ID dtqid, intptr_t data) throw();
+extern ER		rcv_dtq(ID dtqid, intptr_t *p_data) throw();
+extern ER		prcv_dtq(ID dtqid, intptr_t *p_data) throw();
+extern ER		trcv_dtq(ID dtqid, intptr_t *p_data, TMO tmout) throw();
+extern ER		ini_dtq(ID dtqid) throw();
+extern ER		ref_dtq(ID dtqid, T_RDTQ *pk_rdtq) throw();
+
+extern ER_ID	acre_pdq(const T_CPDQ *pk_cpdq) throw();
+extern ER		del_pdq(ID pdqid) throw();
+extern ER		snd_pdq(ID pdqid, intptr_t data, PRI datapri) throw();
+extern ER		psnd_pdq(ID pdqid, intptr_t data, PRI datapri) throw();
+extern ER		ipsnd_pdq(ID pdqid, intptr_t data, PRI datapri) throw();
+extern ER		tsnd_pdq(ID pdqid, intptr_t data,
+										PRI datapri, TMO tmout) throw();
+extern ER		rcv_pdq(ID pdqid, intptr_t *p_data, PRI *p_datapri) throw();
+extern ER		prcv_pdq(ID pdqid, intptr_t *p_data, PRI *p_datapri) throw();
+extern ER		trcv_pdq(ID pdqid, intptr_t *p_data,
+										PRI *p_datapri, TMO tmout) throw();
+extern ER		ini_pdq(ID pdqid) throw();
+extern ER		ref_pdq(ID pdqid, T_RPDQ *pk_rpdq) throw();
+
+extern ER_ID	acre_mbx(const T_CMBX *pk_cmbx) throw();
+extern ER		del_mbx(ID mbxid) throw();
+extern ER		snd_mbx(ID mbxid, T_MSG *pk_msg) throw();
+extern ER		rcv_mbx(ID mbxid, T_MSG **ppk_msg) throw();
+extern ER		prcv_mbx(ID mbxid, T_MSG **ppk_msg) throw();
+extern ER		trcv_mbx(ID mbxid, T_MSG **ppk_msg, TMO tmout) throw();
+extern ER		ini_mbx(ID mbxid) throw();
+extern ER		ref_mbx(ID mbxid, T_RMBX *pk_rmbx) throw();
+
+extern ER_ID	acre_mtx(const T_CMTX *pk_cmtx) throw();
+extern ER		del_mtx(ID mtxid) throw();
+extern ER		loc_mtx(ID mtxid) throw();
+extern ER		ploc_mtx(ID mtxid) throw();
+extern ER		tloc_mtx(ID mtxid, TMO tmout) throw();
+extern ER		unl_mtx(ID mtxid) throw();
+extern ER		ini_mtx(ID mtxid) throw();
+extern ER		ref_mtx(ID mtxid, T_RMTX *pk_rmtx) throw();
+
+/*
+ *  メモリプール管理機能
+ */
+extern ER_ID	acre_mpf(const T_CMPF *pk_cmpf) throw();
+extern ER		del_mpf(ID mpfid) throw();
+extern ER		get_mpf(ID mpfid, void **p_blk) throw();
+extern ER		pget_mpf(ID mpfid, void **p_blk) throw();
+extern ER		tget_mpf(ID mpfid, void **p_blk, TMO tmout) throw();
+extern ER		rel_mpf(ID mpfid, void *blk) throw();
+extern ER		ini_mpf(ID mpfid) throw();
+extern ER		ref_mpf(ID mpfid, T_RMPF *pk_rmpf) throw();
+
+/*
+ *  時間管理機能
+ */
+extern ER		get_tim(SYSTIM *p_systim) throw();
+extern ER		get_utm(SYSUTM *p_sysutm) throw();
+
+extern ER_ID	acre_cyc(const T_CCYC *pk_ccyc) throw();
+extern ER		del_cyc(ID cycid) throw();
+extern ER		sta_cyc(ID cycid) throw();
+extern ER		stp_cyc(ID cycid) throw();
+extern ER		ref_cyc(ID cycid, T_RCYC *pk_rcyc) throw();
+
+extern ER_ID	acre_alm(const T_CALM *pk_calm) throw();
+extern ER		del_alm(ID almid) throw();
+extern ER		sta_alm(ID almid, RELTIM almtim) throw();
+extern ER		ista_alm(ID almid, RELTIM almtim) throw();
+extern ER		stp_alm(ID almid) throw();
+extern ER		istp_alm(ID almid) throw();
+extern ER		ref_alm(ID almid, T_RALM *pk_ralm) throw();
+
+/*
+ *  システム状態管理機能
+ */
+extern ER		rot_rdq(PRI tskpri) throw();
+extern ER		irot_rdq(PRI tskpri) throw();
+extern ER		get_tid(ID *p_tskid) throw();
+extern ER		iget_tid(ID *p_tskid) throw();
+extern ER		loc_cpu(void) throw();
+extern ER		iloc_cpu(void) throw();
+extern ER		unl_cpu(void) throw();
+extern ER		iunl_cpu(void) throw();
+extern ER		dis_dsp(void) throw();
+extern ER		ena_dsp(void) throw();
+extern bool_t	sns_ctx(void) throw();
+extern bool_t	sns_loc(void) throw();
+extern bool_t	sns_dsp(void) throw();
+extern bool_t	sns_dpn(void) throw();
+extern bool_t	sns_ker(void) throw();
+extern ER		ext_ker(void) throw();
+
+/*
+ *  割込み管理機能
+ */
+extern ER_ID	acre_isr(const T_CISR *pk_cisr) throw();
+extern ER		del_isr(ID isrid) throw();
+extern ER		dis_int(INTNO intno) throw();
+extern ER		ena_int(INTNO intno) throw();
+extern ER		chg_ipm(PRI intpri) throw();
+extern ER		get_ipm(PRI *p_intpri) throw();
+
+/*
+ *  CPU例外管理機能
+ */
+extern bool_t	xsns_dpn(void *p_excinf) throw();
+extern bool_t	xsns_xpn(void *p_excinf) throw();
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+/*
+ *  オブジェクト属性の定義
+ */
+#define TA_ACT			UINT_C(0x02)	/* タスクを起動された状態で生成 */
+
+#define TA_TPRI			UINT_C(0x01)	/* タスクの待ち行列を優先度順に */
+#define TA_MPRI			UINT_C(0x02)	/* メッセージキューを優先度順に */
+
+#define TA_WMUL			UINT_C(0x02)	/* 複数の待ちタスク */
+#define TA_CLR			UINT_C(0x04)	/* イベントフラグのクリア指定 */
+
+#define TA_CEILING		UINT_C(0x03)	/* 優先度上限プロトコル */
+
+#define TA_STA			UINT_C(0x02)	/* 周期ハンドラを動作状態で生成 */
+
+#define TA_NONKERNEL	UINT_C(0x02)	/* カーネル管理外の割込み */
+
+#define TA_ENAINT		UINT_C(0x01)	/* 割込み要求禁止フラグをクリア */
+#define TA_EDGE			UINT_C(0x02)	/* エッジトリガ */
+
+/*
+ *  サービスコールの動作モードの定義
+ */
+#define TWF_ORW			UINT_C(0x01)	/* イベントフラグのOR待ち */
+#define TWF_ANDW		UINT_C(0x02)	/* イベントフラグのAND待ち */
+
+/*
+ *  オブジェクトの状態の定義
+ */
+#define TTS_RUN			UINT_C(0x01)	/* 実行状態 */
+#define TTS_RDY			UINT_C(0x02)	/* 実行可能状態 */
+#define TTS_WAI			UINT_C(0x04)	/* 待ち状態 */
+#define TTS_SUS			UINT_C(0x08)	/* 強制待ち状態 */
+#define TTS_WAS			UINT_C(0x0c)	/* 二重待ち状態 */
+#define TTS_DMT			UINT_C(0x10)	/* 休止状態 */
+
+#define TTW_SLP			UINT_C(0x0001)	/* 起床待ち */
+#define TTW_DLY			UINT_C(0x0002)	/* 時間経過待ち */
+#define TTW_SEM			UINT_C(0x0004)	/* セマフォの資源獲得待ち */
+#define TTW_FLG			UINT_C(0x0008)	/* イベントフラグ待ち */
+#define TTW_SDTQ		UINT_C(0x0010)	/* データキューへの送信待ち */
+#define TTW_RDTQ		UINT_C(0x0020)	/* データキューからの受信待ち */
+#define TTW_SPDQ		UINT_C(0x0100)	/* 優先度データキューへの送信待ち */
+#define TTW_RPDQ		UINT_C(0x0200)	/* 優先度データキューからの受信待ち */
+#define TTW_MBX			UINT_C(0x0040)	/* メールボックスからの受信待ち */
+#define TTW_MTX			UINT_C(0x0080)	/* ミューテックスのロック待ち状態 */
+#define TTW_MPF			UINT_C(0x2000)	/* 固定長メモリブロックの獲得待ち */
+
+#define TTEX_ENA		UINT_C(0x01)	/* タスク例外処理許可状態 */
+#define TTEX_DIS		UINT_C(0x02)	/* タスク例外処理禁止状態 */
+
+#define TCYC_STP		UINT_C(0x01)	/* 周期ハンドラが動作していない */
+#define TCYC_STA		UINT_C(0x02)	/* 周期ハンドラが動作している */
+
+#define TALM_STP		UINT_C(0x01)	/* アラームハンドラが動作していない */
+#define TALM_STA		UINT_C(0x02)	/* アラームハンドラが動作している */
+
+/*
+ *  その他の定数の定義
+ */
+#define TSK_SELF		0			/* 自タスク指定 */
+#define TSK_NONE		0			/* 該当するタスクがない */
+
+#define TPRI_SELF		0			/* 自タスクのベース優先度 */
+#define TPRI_INI		0			/* タスクの起動時優先度 */
+
+#define TIPM_ENAALL		0			/* 割込み優先度マスク全解除 */
+
+/*
+ *  構成定数とマクロ
+ */
+
+/*
+ *  サポートする機能
+ */
+#ifdef TOPPERS_TARGET_SUPPORT_DIS_INT
+#define TOPPERS_SUPPORT_DIS_INT			/* dis_intがサポートされている */
+#endif /* TOPPERS_TARGET_SUPPORT_DIS_INT */
+
+#ifdef TOPPERS_TARGET_SUPPORT_ENA_INT
+#define TOPPERS_SUPPORT_ENA_INT			/* ena_intがサポートされている */
+#endif /* TOPPERS_TARGET_SUPPORT_ENA_INT */
+
+#ifdef TOPPERS_TARGET_SUPPORT_GET_UTM
+#define TOPPERS_SUPPORT_GET_UTM			/* get_utmがサポートされている */
+#endif /* TOPPERS_TARGET_SUPPORT_GET_UTM */
+
+#define TOPPERS_SUPPORT_MUTEX			/* ミューテックス機能拡張 */
+#define TOPPERS_SUPPORT_DYNAMIC_CRE		/* 動的生成機能拡張 */
+
+/*
+ *  優先度の範囲
+ */
+#define TMIN_TPRI		1			/* タスク優先度の最小値（最高値）*/
+#define TMAX_TPRI		16			/* タスク優先度の最大値（最低値）*/
+#define TMIN_DPRI		1			/* データ優先度の最小値（最高値）*/
+#define TMAX_DPRI		16			/* データ優先度の最大値（最低値）*/
+#define TMIN_MPRI		1			/* メッセージ優先度の最小値（最高値）*/
+#define TMAX_MPRI		16			/* メッセージ優先度の最大値（最低値）*/
+#define TMIN_ISRPRI		1			/* 割込みサービスルーチン優先度の最小値 */
+#define TMAX_ISRPRI		16			/* 割込みサービスルーチン優先度の最大値 */
+
+/*
+ *  バージョン情報
+ */
+#define TKERNEL_MAKER	UINT_C(0x0118)	/* カーネルのメーカーコード */
+#define TKERNEL_PRID	UINT_C(0x0007)	/* カーネルの識別番号 */
+#define TKERNEL_SPVER	UINT_C(0xf517)	/* カーネル仕様のバージョン番号 */
+#define TKERNEL_PRVER	UINT_C(0x1093)	/* カーネルのバージョン番号 */
+
+/*
+ *  キューイング回数の最大値
+ */
+#define TMAX_ACTCNT		UINT_C(1)		/* 起動要求キューイング数の最大値 */
+#define TMAX_WUPCNT		UINT_C(1)		/* 起床要求キューイング数の最大値 */
+
+/*
+ *  ビットパターンのビット数
+ */
+#ifndef TBIT_TEXPTN					/* タスク例外要因のビット数 */
+#define TBIT_TEXPTN		(sizeof(TEXPTN) * CHAR_BIT)
+#endif /* TBIT_TEXPTN */
+
+#ifndef TBIT_FLGPTN					/* イベントフラグのビット数 */
+#define TBIT_FLGPTN		(sizeof(FLGPTN) * CHAR_BIT)
+#endif /* TBIT_FLGPTN */
+
+/*
+ *  メモリ領域確保のためのマクロ
+ *
+ *  以下のTOPPERS_COUNT_SZとTOPPERS_ROUND_SZの定義は，unitが2の巾乗であ
+ *  ることを仮定している．
+ */
+#ifndef TOPPERS_COUNT_SZ
+#define TOPPERS_COUNT_SZ(sz, unit)	(((sz) + (unit) - 1) / (unit))
+#endif /* TOPPERS_COUNT_SZ */
+#ifndef TOPPERS_ROUND_SZ
+#define TOPPERS_ROUND_SZ(sz, unit)	(((sz) + (unit) - 1) & ~((unit) - 1))
+#endif /* TOPPERS_ROUND_SZ */
+
+#define COUNT_STK_T(sz)		TOPPERS_COUNT_SZ(sz, sizeof(STK_T))
+#define ROUND_STK_T(sz)		TOPPERS_ROUND_SZ(sz, sizeof(STK_T))
+
+#define COUNT_MPF_T(blksz)	TOPPERS_COUNT_SZ(blksz, sizeof(MPF_T))
+#define ROUND_MPF_T(blksz)	TOPPERS_ROUND_SZ(blksz, sizeof(MPF_T))
+
+#define TSZ_DTQMB(dtqcnt)	(sizeof(intptr_t) * (dtqcnt))
+#define TCNT_DTQMB(dtqcnt)	TOPPERS_COUNT_SZ(TSZ_DTQMB(dtqcnt), sizeof(MB_T))
+
+#ifndef TSZ_PDQMB
+#define TSZ_PDQMB(pdqcnt)	(sizeof(intptr_t) * 3 * (pdqcnt))
+#endif /* TSZ_PDQMB */
+#define TCNT_PDQMB(pdqcnt)	TOPPERS_COUNT_SZ(TSZ_PDQMB(pdqcnt), sizeof(MB_T))
+
+#define TSZ_MPFMB(blkcnt)	(sizeof(uint_t) * (blkcnt))
+#define TCNT_MPFMB(blkcnt)	TOPPERS_COUNT_SZ(TSZ_MPFMB(blkcnt), sizeof(MB_T))
+
+/*
+ *  その他の構成定数
+ */
+#define TMAX_MAXSEM		UINT_MAX	/* セマフォの最大資源数の最大値 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TOPPERS_KERNEL_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/include/log_output.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/include/log_output.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/include/log_output.h	(revision 453)
@@ -0,0 +1,84 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		システムログのフォーマット出力
+ */
+
+#ifndef TOPPERS_LOG_OUTPUT_H
+#define TOPPERS_LOG_OUTPUT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <t_syslog.h>
+
+/*
+ *  文字列整形出力
+ *
+ *  formatで指定されるフォーマット記述とp_argsで指定される引数列から作
+ *  成したメッセージを，1文字出力関数putcを用いて出力する．
+ */
+extern void	syslog_printf(const char *format, const intptr_t *p_args,
+										void (*putc)(char)) throw();
+
+/*
+ *  ログ情報の出力
+ *
+ *  p_syslogで指定されるログ情報を文字列に整形し，1文字出力関数putcを用
+ *  いて出力する．
+ */
+extern void	syslog_print(const SYSLOG *p_syslog, void (*putc)(char)) throw();
+
+/*
+ *  ログ情報喪失メッセージ文字列
+ *
+ *  lostlog個のログ情報が失われた旨のメッセージを，1文字出力関数putcを
+ *  用いて出力する．
+ */
+extern void	syslog_lostmsg(uint_t lostlog, void (*putc)(char)) throw();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TOPPERS_LOG_OUTPUT_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/include/queue.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/include/queue.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/include/queue.h	(revision 453)
@@ -0,0 +1,161 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2000 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2006-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		キュー操作ライブラリ
+ *
+ *  このキュー操作ライブラリでは，キューヘッダを含むリング構造のダブル
+ *  リンクキューを扱う．具体的には，キューヘッダの次エントリはキューの
+ *  先頭のエントリ，前エントリはキューの末尾のエントリとする．また，キ
+ *  ューの先頭のエントリの前エントリと，キューの末尾のエントリの次エン
+ *  トリは，キューヘッダとする．空のキューは，次エントリ，前エントリと
+ *  も自分自身を指すキューヘッダであらわす．
+ */
+
+#ifndef	TOPPERS_QUEUE_H
+#define	TOPPERS_QUEUE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ *  キューのデータ構造の定義
+ */
+typedef struct queue {
+	struct queue *p_next;		/* 次エントリへのポインタ */
+	struct queue *p_prev;		/* 前エントリへのポインタ */
+} QUEUE;
+
+/*
+ *  キューの初期化
+ *
+ *  p_queueにはキューヘッダを指定する．
+ */
+Inline void
+queue_initialize(QUEUE *p_queue)
+{
+	p_queue->p_prev = p_queue;
+	p_queue->p_next = p_queue;
+}
+
+/*
+ *  キューの前エントリへの挿入
+ *
+ *  p_queueの前にp_entryを挿入する．p_queueにキューヘッダを指定した場
+ *  合には，キューの末尾にp_entryを挿入することになる．
+ */
+Inline void
+queue_insert_prev(QUEUE *p_queue, QUEUE *p_entry)
+{
+	p_entry->p_prev = p_queue->p_prev;
+	p_entry->p_next = p_queue;
+	p_queue->p_prev->p_next = p_entry;
+	p_queue->p_prev = p_entry;
+}
+
+/*
+ *  キューの次エントリへの挿入
+ *
+ *  p_queueの次にp_entryを挿入する．p_queueにキューヘッダを指定した場
+ *  合には，キューの先頭にp_entryを挿入することになる．
+ */
+Inline void
+queue_insert_next(QUEUE *p_queue, QUEUE *p_entry)
+{
+	p_entry->p_prev = p_queue;
+	p_entry->p_next = p_queue->p_next;
+	p_queue->p_next->p_prev = p_entry;
+	p_queue->p_next = p_entry;
+}
+
+/*
+ *  エントリの削除
+ *
+ *  p_entryをキューから削除する．
+ */
+Inline void
+queue_delete(QUEUE *p_entry)
+{
+	p_entry->p_prev->p_next = p_entry->p_next;
+	p_entry->p_next->p_prev = p_entry->p_prev;
+}
+
+/*
+ *  キューの次エントリの取出し
+ *
+ *  p_queueの次エントリをキューから削除し，削除したエントリを返す．
+ *  p_queueにキューヘッダを指定した場合には，キューの先頭のエントリを
+ *  取り出すことになる．p_queueに空のキューを指定して呼び出してはなら
+ *  ない．
+ */
+Inline QUEUE *
+queue_delete_next(QUEUE *p_queue)
+{
+	QUEUE	*p_entry;
+
+	assert(p_queue->p_next != p_queue);
+	p_entry = p_queue->p_next;
+	p_queue->p_next = p_entry->p_next;
+	p_entry->p_next->p_prev = p_queue;
+	return(p_entry);
+}
+
+/*
+ *  キューが空かどうかのチェック
+ *
+ *  p_queueにはキューヘッダを指定する．
+ */
+Inline bool_t
+queue_empty(QUEUE *p_queue)
+{
+	if (p_queue->p_next == p_queue) {
+		assert(p_queue->p_prev == p_queue);
+		return(true);
+	}
+	return(false);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TOPPERS_QUEUE_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/include/sil.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/include/sil.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/include/sil.h	(revision 453)
@@ -0,0 +1,287 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		システムインタフェースレイヤ
+ *
+ *  システムインタフェースレイヤのサービスコールの定義・宣言とマクロな
+ *  どの定義を含むヘッダファイル．
+ *
+ *  アセンブリ言語のソースファイルからこのファイルをインクルードする時
+ *  は，TOPPERS_MACRO_ONLYを定義しておくことで，マクロ定義以外の記述を
+ *  除くことができる．
+ *
+ *  このファイルをインクルードする前にインクルードしておくべきファイル
+ *  はない．
+ */
+
+#ifndef TOPPERS_SIL_H
+#define TOPPERS_SIL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ *	TOPPERS共通のデータ型・定数・マクロ
+ */
+#include <t_stddef.h>
+
+/*
+ *  ターゲット依存部
+ */
+#include "target_sil.h"
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  全割込みロック状態の制御
+ *
+ *  SIL_PRE_LOC，SIL_LOC_INT()，SIL_UNL_INT()は，ターゲット依存部で用
+ *  意する．デフォルトの定義は用意していない．
+ */
+
+/*
+ *  微少時間待ち
+ */
+extern void	sil_dly_nse(ulong_t dlytim) throw();
+
+/*
+ *  エンディアンの反転
+ */
+#ifndef TOPPERS_SIL_REV_ENDIAN_UINT16
+#define	TOPPERS_SIL_REV_ENDIAN_UINT16(data) \
+				((((data) & 0xffU) << 8) | (((data) >> 8) & 0xffU))
+#endif /* TOPPERS_SIL_REV_ENDIAN_UINT16 */
+
+#ifndef TOPPERS_SIL_REV_ENDIAN_UINT32
+#define	TOPPERS_SIL_REV_ENDIAN_UINT32(data) \
+				((((data) & 0xffU) << 24) | (((data) & 0xff00U) << 8) \
+					| (((data) >> 8) & 0xff00U) | (((data) >> 24) & 0xffU))
+#endif /* TOPPERS_SIL_REV_ENDIAN_UINT32 */
+
+/*
+ *  メモリ空間アクセス関数
+ */
+#ifndef TOPPERS_OMIT_SIL_ACCESS
+
+/*
+ *  8ビット単位の読出し／書込み
+ */
+#ifdef UINT8_MAX
+
+Inline uint8_t
+sil_reb_mem(const uint8_t *mem)
+{
+	uint8_t	data;
+
+	data = *((const volatile uint8_t *) mem);
+	return(data);
+}
+
+Inline void
+sil_wrb_mem(uint8_t *mem, uint8_t data)
+{
+	*((volatile uint8_t *) mem) = data;
+}
+
+#endif /* UINT8_MAX */
+
+/*
+ *  16ビット単位の読出し／書込み
+ */
+
+Inline uint16_t
+sil_reh_mem(const uint16_t *mem)
+{
+	uint16_t	data;
+
+	data = *((const volatile uint16_t *) mem);
+	return(data);
+}
+
+Inline void
+sil_wrh_mem(uint16_t *mem, uint16_t data)
+{
+	*((volatile uint16_t *) mem) = data;
+}
+
+#ifdef SIL_ENDIAN_BIG			/* ビッグエンディアンプロセッサ */
+
+#define	sil_reh_bem(mem)		sil_reh_mem(mem)
+#define	sil_wrh_bem(mem, data)	sil_wrh_mem(mem, data)
+
+#ifndef TOPPERS_OMIT_SIL_REH_LEM
+
+Inline uint16_t
+sil_reh_lem(const uint16_t *mem)
+{
+	uint16_t	data;
+
+	data = *((const volatile uint16_t *) mem);
+	return(TOPPERS_SIL_REV_ENDIAN_UINT16(data));
+}
+
+#endif /* TOPPERS_OMIT_SIL_REH_LEM */
+#ifndef TOPPERS_OMIT_SIL_WRH_LEM
+
+Inline void
+sil_wrh_lem(uint16_t *mem, uint16_t data)
+{
+	*((volatile uint16_t *) mem) = TOPPERS_SIL_REV_ENDIAN_UINT16(data);
+}
+
+#endif /* TOPPERS_OMIT_SIL_WRH_LEM */
+#else /* SIL_ENDIAN_BIG */
+#ifdef SIL_ENDIAN_LITTLE		/* リトルエンディアンプロセッサ */
+
+#define	sil_reh_lem(mem)		sil_reh_mem(mem)
+#define	sil_wrh_lem(mem, data)	sil_wrh_mem(mem, data)
+
+#ifndef TOPPERS_OMIT_SIL_REH_BEM
+
+Inline uint16_t
+sil_reh_bem(const uint16_t *mem)
+{
+	uint16_t	data;
+
+	data = *((const volatile uint16_t *) mem);
+	return(TOPPERS_SIL_REV_ENDIAN_UINT16(data));
+}
+
+#endif /* TOPPERS_OMIT_SIL_REH_BEM */
+#ifndef TOPPERS_OMIT_SIL_WRH_BEM
+
+Inline void
+sil_wrh_bem(uint16_t *mem, uint16_t data)
+{
+	*((volatile uint16_t *) mem) = TOPPERS_SIL_REV_ENDIAN_UINT16(data);
+}
+
+#endif /* TOPPERS_OMIT_SIL_WRH_BEM */
+#else /* SIL_ENDIAN_LITTLE */
+
+#error Neither SIL_ENDIAN_BIG nor SIL_ENDIAN_LITTLE is defined.
+
+#endif /* SIL_ENDIAN_LITTLE */
+#endif /* SIL_ENDIAN_BIG */
+
+/*
+ *  32ビット単位の読出し／書込み
+ */
+
+Inline uint32_t
+sil_rew_mem(const uint32_t *mem)
+{
+	uint32_t	data;
+
+	data = *((const volatile uint32_t *) mem);
+	return(data);
+}
+
+Inline void
+sil_wrw_mem(uint32_t *mem, uint32_t data)
+{
+	*((volatile uint32_t *) mem) = data;
+}
+
+#ifdef SIL_ENDIAN_BIG			/* ビッグエンディアンプロセッサ */
+
+#define	sil_rew_bem(mem)		sil_rew_mem(mem)
+#define	sil_wrw_bem(mem, data)	sil_wrw_mem(mem, data)
+
+#ifndef TOPPERS_OMIT_SIL_REW_LEM
+
+Inline uint32_t
+sil_rew_lem(const uint32_t *mem)
+{
+	uint32_t	data;
+
+	data = *((const volatile uint32_t *) mem);
+	return(TOPPERS_SIL_REV_ENDIAN_UINT32(data));
+}
+
+#endif /* TOPPERS_OMIT_SIL_REW_LEM */
+#ifndef TOPPERS_OMIT_SIL_WRW_LEM
+
+Inline void
+sil_wrw_lem(uint32_t *mem, uint32_t data)
+{
+	*((volatile uint32_t *) mem) = TOPPERS_SIL_REV_ENDIAN_UINT32(data);
+}
+
+#endif /* TOPPERS_OMIT_SIL_WRW_LEM */
+#else /* SIL_ENDIAN_BIG */		/* リトルエンディアンプロセッサ */
+
+#define	sil_rew_lem(mem)		sil_rew_mem(mem)
+#define	sil_wrw_lem(mem, data)	sil_wrw_mem(mem, data)
+
+#ifndef TOPPERS_OMIT_SIL_REW_BEM
+
+Inline uint32_t
+sil_rew_bem(const uint32_t *mem)
+{
+	uint32_t	data;
+
+	data = *((const volatile uint32_t *) mem);
+	return(TOPPERS_SIL_REV_ENDIAN_UINT32(data));
+}
+
+#endif /* TOPPERS_OMIT_SIL_REW_BEM */
+#ifndef TOPPERS_OMIT_SIL_WRW_BEM
+
+Inline void
+sil_wrw_bem(uint32_t *mem, uint32_t data)
+{
+	*((volatile uint32_t *) mem) = TOPPERS_SIL_REV_ENDIAN_UINT32(data);
+}
+
+#endif /* TOPPERS_OMIT_SIL_WRW_BEM */
+#endif /* SIL_ENDIAN_BIG */
+#endif /* TOPPERS_OMIT_SIL_ACCESS */
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TOPPERS_SIL_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/include/t_stddef.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/include/t_stddef.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/include/t_stddef.h	(revision 453)
@@ -0,0 +1,286 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2012 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		TOPPERS共通ヘッダファイル
+ *
+ *  TOPPERS関連のすべてのソースファイルでインクルードすべきヘッダファイ
+ *  ル．各種のカーネルやソフトウェア部品で共通に用いることを想定してい
+ *  る．TOPPERSの各種のカーネルやソフトウェア部品で共通に用いるデータ型，
+ *  定数，マクロの定義などを含む．
+ *
+ *  アセンブリ言語のソースファイルからこのファイルをインクルードする時
+ *  は，TOPPERS_MACRO_ONLYを定義しておく．これにより，マクロ定義以外を
+ *  除くようになっている．
+ *
+ *  このファイルをインクルードする前にインクルードしておくべきファイル
+ *  はない．
+ */
+
+#ifndef TOPPERS_T_STDDEF_H
+#define TOPPERS_T_STDDEF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ *  ターゲット依存部
+ */
+#include "target_stddef.h"
+
+/*
+ *  C言語/EC++でthrow()に対処するための定義
+ */
+#if !defined(__cplusplus) || defined(__embedded_cplusplus)
+#define throw()
+#endif
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  ターゲット依存のデータ型のマクロのデフォルト定義
+ */
+#ifndef TOPPERS_bool
+#define TOPPERS_bool	int				/* ブール型 */
+#endif /* TOPPERS_bool */
+
+#ifndef TOPPERS_size
+#define TOPPERS_size	uintptr_t		/* サイズ型 */
+#endif /* TOPPERS_size */
+
+#ifndef TOPPERS_fp
+struct TOPPERS_dummy_t { int TOPPERS_dummy_field; };
+typedef	void			(*TOPPERS_fp_t)(struct TOPPERS_dummy_t);
+#define TOPPERS_fp		TOPPERS_fp_t	/* プログラムの起動番地 */
+#endif /* TOPPERS_fp */
+
+/*
+ *  共通データ型
+ */
+typedef TOPPERS_bool	bool_t;		/* 真偽値 */
+
+typedef signed int		int_t;		/* 自然なサイズの符号付き整数 */
+typedef unsigned int	uint_t;		/* 自然なサイズの符号無し整数 */
+
+typedef signed long		long_t;		/* 長めのサイズの符号付き整数 */
+typedef unsigned long	ulong_t;	/* 長めのサイズの符号無し整数 */
+
+typedef int_t			FN;			/* 機能コード */
+typedef	int_t			ER;			/* エラーコード */
+typedef	int_t			ID;			/* オブジェクトのID番号 */
+typedef	uint_t			ATR;		/* オブジェクトの属性 */
+typedef	uint_t			STAT;		/* オブジェクトの状態 */
+typedef	uint_t			MODE;		/* サービスコールの動作モード */
+typedef	int_t			PRI;		/* 優先度 */
+typedef	TOPPERS_size	SIZE;		/* メモリ領域のサイズ */
+
+typedef	int_t			TMO;		/* タイムアウト指定 */
+typedef	uint_t			RELTIM;		/* 相対時間 */
+typedef	ulong_t			SYSTIM;		/* システム時刻 */
+typedef	ulong_t			SYSUTM;		/* 性能評価用システム時刻 */
+
+typedef	TOPPERS_fp		FP;			/* プログラムの起動番地 */
+
+typedef	int_t			ER_BOOL;	/* エラーコードまたは真偽値 */
+typedef	int_t			ER_ID;		/* エラーコードまたはID番号 */
+typedef	int_t			ER_UINT;	/* エラーコードまたは符号無し整数 */
+
+typedef uintptr_t		MB_T;		/* 管理領域を確保するためのデータ型 */
+
+typedef	uint32_t		ACPTN;		/* アクセス許可パターン */
+typedef	struct acvct {				/* アクセス許可ベクタ */
+	ACPTN		acptn1;				/* 通常操作1のアクセス許可パターン */
+	ACPTN		acptn2;				/* 通常操作2のアクセス許可パターン */
+	ACPTN		acptn3;				/* 管理操作のアクセス許可パターン */
+	ACPTN		acptn4;				/* 参照操作のアクセス許可パターン */
+} ACVCT;
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+/*
+ *  整数定数を作るマクロ
+ */
+#ifndef UINT_C
+#define UINT_C(val)		(val ## U)		/* uint_t型の定数を作るマクロ */
+#endif /* UINT_C */
+
+#ifndef ULONG_C
+#define ULONG_C(val)	(val ## UL)		/* ulong_t型の定数を作るマクロ */
+#endif /* ULONG_C */
+
+/*
+ *  一般定数
+ */
+#ifndef NULL
+#define NULL		0			/* 無効ポインタ */
+#endif /* NULL */
+
+#ifndef true
+#define true		1			/* 真 */
+#endif /* true */
+
+#ifndef false
+#define false		0			/* 偽 */
+#endif /* false */
+
+#define E_OK		0			/* 正常終了 */
+
+/*
+ *  メインエラーコード
+ */
+#define E_SYS		(-5)		/* システムエラー */
+#define E_NOSPT		(-9)		/* 未サポート機能 */
+#define E_RSFN		(-10)		/* 予約機能コード */
+#define E_RSATR		(-11)		/* 予約属性 */
+#define E_PAR		(-17)		/* パラメータエラー */
+#define E_ID		(-18)		/* 不正ID番号 */
+#define E_CTX		(-25)		/* コンテキストエラー */
+#define E_MACV		(-26)		/* メモリアクセス違反 */
+#define E_OACV		(-27)		/* オブジェクトアクセス違反 */
+#define E_ILUSE		(-28)		/* サービスコール不正使用 */
+#define E_NOMEM		(-33)		/* メモリ不足 */
+#define E_NOID		(-34)		/* ID番号不足 */
+#define E_NORES		(-35)		/* 資源不足 */
+#define E_OBJ		(-41)		/* オブジェクト状態エラー */
+#define E_NOEXS		(-42)		/* オブジェクト未生成 */
+#define E_QOVR		(-43)		/* キューイングオーバーフロー */
+#define E_RLWAI		(-49)		/* 待ち状態の強制解除 */
+#define E_TMOUT		(-50)		/* ポーリング失敗またはタイムアウト */
+#define E_DLT		(-51)		/* 待ちオブジェクトの削除 */
+#define E_CLS		(-52)		/* 待ちオブジェクトの状態変化 */
+#define E_WBLK		(-57)		/* ノンブロッキング受付け */
+#define E_BOVR		(-58)		/* バッファオーバーフロー */
+
+/*
+ *  オブジェクト属性
+ */
+#define TA_NULL		UINT_C(0)	/* オブジェクト属性を指定しない */
+
+/*
+ *  タイムアウト指定
+ */
+#define TMO_POL		0			/* ポーリング */
+#define TMO_FEVR	(-1)		/* 永久待ち */
+#define TMO_NBLK	(-2)		/* ノンブロッキング */
+
+/*
+ *  アクセス許可パターン
+ */
+#define TACP_KERNEL		(0U)	/* カーネルドメインだけにアクセスを許可 */
+#define TACP_SHARED		(~0U)	/* すべてのドメインからアクセスを許可 */
+
+/*
+ *  型に関する情報を取り出すためのマクロ
+ *
+ *  以下のALIGN_TYPEの定義は，アラインメントの単位が2の巾乗であることを
+ *  仮定している．
+ */
+#ifndef offsetof
+#define	offsetof(structure, field)	((uintptr_t) &(((structure *) 0)->field))
+#endif /* offsetof */
+
+#ifndef alignof
+#define alignof(type)	offsetof(struct { char field1; type field2; }, field2)
+#endif /* alignof */
+
+#ifndef ALIGN_TYPE				/* アラインメントのチェック */
+#define ALIGN_TYPE(addr, type) \
+						((((uintptr_t)(addr)) & (alignof(type) - 1)) == 0U)
+#endif /* ALIGN_TYPE */
+
+/*
+ *  assertマクロ
+ */
+#undef assert
+#ifndef NDEBUG
+#define assert(exp)		((void)((exp) ? 0 : (TOPPERS_assert_fail(#exp, \
+							__FILE__, __LINE__), TOPPERS_assert_abort(), 0)))
+#else /* NDEBUG */
+#define assert(exp)		((void) 0)
+#endif /* NDEBUG */
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+ *  エラーコード生成・分解マクロ
+ *
+ *  以下のマクロ定義は，符号付き整数が2の補数で表現されており，右シフト
+ *  演算子（>>）が算術シフトされることを仮定している．そうでない開発環
+ *  境では，target_stddef.hでこれらの定義を上書きしなければならない．
+ *
+ *  MERCDマクロの定義は，メインエラーコードが負であることを仮定している．
+ *  そうでない場合，2つの定義が一致しなくなる．
+ */
+#ifndef ERCD
+#define ERCD(mercd, sercd) \
+				((ER)((((uint_t)(sercd)) << 8) | (((uint_t)(mercd)) & 0xffU)))
+#endif /* ERCD */
+
+#ifndef MERCD
+#ifdef INT8_MAX
+#define MERCD(ercd)		((ER)((int8_t)(ercd)))
+#else /* INT8_MAX */
+#define MERCD(ercd)		((ER)(((uint_t) ercd) | ~0xffU))
+#endif /* INT8_MAX */
+#endif /* MERCD */
+
+#ifndef SERCD
+#define SERCD(ercd)		((ER)((ercd) >> 8))
+#endif /* SERCD */
+
+/*
+ *  アクセス許可パターン生成マクロ
+ */
+#define TACP(domid)		(1U << ((domid) - 1))	/* domidだけにアクセスを許可 */
+
+/*
+ *  相対時間（RELTIM）に指定できる最大値
+ */
+#if UINT_MAX < LONG_MAX
+#define TMAX_RELTIM		((RELTIM) UINT_MAX)
+#else /* UINT_MAX < LONG_MAX */
+#define TMAX_RELTIM		((RELTIM) LONG_MAX)
+#endif /* UINT_MAX < LONG_MAX */
+
+#endif /* TOPPERS_T_STDDEF_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/include/t_stdlib.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/include/t_stdlib.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/include/t_stdlib.h	(revision 453)
@@ -0,0 +1,74 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2006 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		基本的なライブラリ関数
+ */
+
+#ifndef TOPPERS_T_STDLIB_H
+#define TOPPERS_T_STDLIB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ *  エラーメッセージ文字列を返す関数
+ *
+ *  ercdで指定されたエラーコードのメインエラーコードの名称（E_PAR，
+ *  E_OBJなど）の文字列を返す関数．
+ */
+extern const char	*itron_strerror(ER ercd) throw();
+
+/*
+ *  エラーメッセージのログ出力
+ *
+ *  サービスコールがエラーを返した場合に，そのファイル名，行番号，メイ
+ *  ンエラーコード等を表示するための関数．
+ */
+extern void		t_perror(uint_t prio, const char *file, int_t line,
+									const char *expr, ER ercd) throw();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TOPPERS_T_STDLIB_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/include/t_syslog.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/include/t_syslog.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/include/t_syslog.h	(revision 453)
@@ -0,0 +1,335 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		システムログ出力を行うための定義
+ *
+ *  システムログサービスは，システムのログ情報を出力するためのサービス
+ *  である．カーネルからのログ情報の出力にも用いるため，内部で待ち状態
+ *  にはいることはない．
+ *
+ *  ログ情報は，カーネル内のログバッファに書き込むか，低レベルの文字出
+ *  力関数を用いて出力する．どちらを使うかは，拡張サービスコールで切り
+ *  換えることができる．
+ *
+ *  ログバッファ領域がオーバフローした場合には，古いログ情報を消して上
+ *  書きする．
+ *
+ *  アセンブリ言語のソースファイルからこのファイルをインクルードする時
+ *  は，TOPPERS_MACRO_ONLYを定義しておくことで，マクロ定義以外の記述を
+ *  除くことができる．
+ *
+ *  このファイルをインクルードする前に，t_stddef.hをインクルードしてお
+ *  くことが必要である．
+ */
+
+#ifndef TOPPERS_T_SYSLOG_H
+#define TOPPERS_T_SYSLOG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ *  ログ情報の種別の定義
+ */
+#define LOG_TYPE_COMMENT	UINT_C(0x01)	/* コメント */
+#define LOG_TYPE_ASSERT		UINT_C(0x02)	/* アサーションの失敗 */
+
+#define LOG_TYPE_INH		UINT_C(0x11)	/* 割込みハンドラ */
+#define LOG_TYPE_ISR		UINT_C(0x12)	/* 割込みサービスルーチン */
+#define LOG_TYPE_CYC		UINT_C(0x13)	/* 周期ハンドラ */
+#define LOG_TYPE_ALM		UINT_C(0x14)	/* アラームハンドラ */
+#define LOG_TYPE_OVR		UINT_C(0x15)	/* オーバランハンドラ */
+#define LOG_TYPE_EXC		UINT_C(0x16)	/* CPU例外ハンドラ */
+#define LOG_TYPE_TEX		UINT_C(0x17)	/* タスク例外処理ルーチン */
+#define LOG_TYPE_TSKSTAT	UINT_C(0x18)	/* タスク状態変化 */
+#define LOG_TYPE_DSP		UINT_C(0x19)	/* ディスパッチャ */
+#define LOG_TYPE_SVC		UINT_C(0x1a)	/* サービスコール */
+
+#define LOG_ENTER			UINT_C(0x00)	/* 入口／開始 */
+#define LOG_LEAVE			UINT_C(0x80)	/* 出口／終了 */
+
+/*
+ *  ログ情報の重要度の定義
+ */
+#define LOG_EMERG			UINT_C(0)		/* シャットダウンに値するエラー */
+#define LOG_ALERT			UINT_C(1)
+#define LOG_CRIT			UINT_C(2)
+#define LOG_ERROR			UINT_C(3)		/* システムエラー */
+#define LOG_WARNING			UINT_C(4)		/* 警告メッセージ */
+#define LOG_NOTICE			UINT_C(5)
+#define LOG_INFO			UINT_C(6)
+#define LOG_DEBUG			UINT_C(7)		/* デバッグ用メッセージ */
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  ログ情報のデータ構造
+ */
+
+#define TMAX_LOGINFO	6
+
+typedef struct {
+	uint_t		logtype;				/* ログ情報の種別 */
+	SYSTIM		logtim;					/* ログ時刻 */
+	intptr_t	loginfo[TMAX_LOGINFO];	/* その他のログ情報 */
+} SYSLOG;
+
+/*
+ *  ログ情報の重要度のビットマップを作るためのマクロ
+ */
+#define LOG_MASK(prio)		(1U << (prio))
+#define LOG_UPTO(prio)		((1U << ((prio) + 1)) - 1)
+
+/*
+ *  パケット形式の定義
+ */
+typedef struct t_syslog_rlog {
+	uint_t	count;		/* ログバッファ中のログの数 */
+	uint_t	lost;		/* 失われたログの数 */
+	uint_t	logmask;	/* ログバッファに記録すべき重要度 */
+	uint_t	lowmask;	/* 低レベル出力すべき重要度 */
+} T_SYSLOG_RLOG;
+
+/*
+ *  ログ情報を出力するためのライブラリ関数
+ */
+
+#ifndef TOPPERS_OMIT_SYSLOG
+
+extern ER	syslog_wri_log(uint_t prio, const SYSLOG *p_syslog) throw();
+
+Inline void
+_syslog_0(uint_t prio, uint_t type)
+{
+	SYSLOG	logbuf;
+
+	logbuf.logtype = type;
+	(void) syslog_wri_log(prio, &logbuf);
+}
+
+Inline void
+_syslog_1(uint_t prio, uint_t type, intptr_t arg1)
+{
+	SYSLOG	logbuf;
+
+	logbuf.logtype = type;
+	logbuf.loginfo[0] = arg1;
+	(void) syslog_wri_log(prio, &logbuf);
+}
+
+Inline void
+_syslog_2(uint_t prio, uint_t type, intptr_t arg1, intptr_t arg2)
+{
+	SYSLOG	logbuf;
+
+	logbuf.logtype = type;
+	logbuf.loginfo[0] = arg1;
+	logbuf.loginfo[1] = arg2;
+	(void) syslog_wri_log(prio, &logbuf);
+}
+
+Inline void
+_syslog_3(uint_t prio, uint_t type, intptr_t arg1, intptr_t arg2,
+														intptr_t arg3)
+{
+	SYSLOG	logbuf;
+
+	logbuf.logtype = type;
+	logbuf.loginfo[0] = arg1;
+	logbuf.loginfo[1] = arg2;
+	logbuf.loginfo[2] = arg3;
+	(void) syslog_wri_log(prio, &logbuf);
+}
+
+Inline void
+_syslog_4(uint_t prio, uint_t type, intptr_t arg1, intptr_t arg2,
+										intptr_t arg3, intptr_t arg4)
+{
+	SYSLOG	logbuf;
+
+	logbuf.logtype = type;
+	logbuf.loginfo[0] = arg1;
+	logbuf.loginfo[1] = arg2;
+	logbuf.loginfo[2] = arg3;
+	logbuf.loginfo[3] = arg4;
+	(void) syslog_wri_log(prio, &logbuf);
+}
+
+Inline void
+_syslog_5(uint_t prio, uint_t type, intptr_t arg1, intptr_t arg2,
+							intptr_t arg3, intptr_t arg4, intptr_t arg5)
+{
+	SYSLOG	logbuf;
+
+	logbuf.logtype = type;
+	logbuf.loginfo[0] = arg1;
+	logbuf.loginfo[1] = arg2;
+	logbuf.loginfo[2] = arg3;
+	logbuf.loginfo[3] = arg4;
+	logbuf.loginfo[4] = arg5;
+	(void) syslog_wri_log(prio, &logbuf);
+}
+
+Inline void
+_syslog_6(uint_t prio, uint_t type, intptr_t arg1, intptr_t arg2,
+				intptr_t arg3, intptr_t arg4, intptr_t arg5, intptr_t arg6)
+{
+	SYSLOG	logbuf;
+
+	logbuf.logtype = type;
+	logbuf.loginfo[0] = arg1;
+	logbuf.loginfo[1] = arg2;
+	logbuf.loginfo[2] = arg3;
+	logbuf.loginfo[3] = arg4;
+	logbuf.loginfo[4] = arg5;
+	logbuf.loginfo[5] = arg6;
+	(void) syslog_wri_log(prio, &logbuf);
+}
+
+/*
+ *  ログ情報（コメント）を出力するためのライブラリ関数（vasyslog.c）
+ */
+extern void	syslog(uint_t prio, const char *format, ...) throw();
+
+#else /* TOPPERS_OMIT_SYSLOG */
+
+/*
+ *  システムログ出力を抑止する場合
+ */
+
+Inline void
+_syslog_0(uint_t prio, uint_t type)
+{
+}
+
+Inline void
+_syslog_1(uint_t prio, uint_t type, intptr_t arg1)
+{
+}
+
+Inline void
+_syslog_2(uint_t prio, uint_t type, intptr_t arg1, intptr_t arg2)
+{
+}
+
+Inline void
+_syslog_3(uint_t prio, uint_t type, intptr_t arg1, intptr_t arg2,
+														intptr_t arg3)
+{
+}
+
+Inline void
+_syslog_4(uint_t prio, uint_t type, intptr_t arg1, intptr_t arg2,
+										intptr_t arg3, intptr_t arg4)
+{
+}
+
+Inline void
+_syslog_5(uint_t prio, uint_t type, intptr_t arg1, intptr_t arg2,
+							intptr_t arg3, intptr_t arg4, intptr_t arg5)
+{
+}
+
+Inline void
+_syslog_6(uint_t prio, uint_t type, intptr_t arg1, intptr_t arg2,
+				intptr_t arg3, intptr_t arg4, intptr_t arg5, intptr_t arg6)
+{
+}
+
+Inline void
+syslog(uint_t prio, const char *format, ...)
+{
+}
+
+#endif /* TOPPERS_OMIT_SYSLOG */
+
+/*
+ *  ログ情報（コメント）を出力するためのマクロ
+ *
+ *  formatおよび後続の引数から作成したメッセージを，重大度prioでログ情
+ *  報として出力するためのマクロ．arg1～argnはintptr_t型にキャストする
+ *  ため，intptr_t型に型変換できる任意の型でよい．
+ */
+
+#define syslog_0(prio, format) \
+				_syslog_1(prio, LOG_TYPE_COMMENT, (intptr_t)(format))
+
+#define syslog_1(prio, format, arg1) \
+				_syslog_2(prio, LOG_TYPE_COMMENT, (intptr_t)(format), \
+														(intptr_t)(arg1))
+
+#define syslog_2(prio, format, arg1, arg2) \
+				_syslog_3(prio, LOG_TYPE_COMMENT, (intptr_t)(format), \
+										(intptr_t)(arg1), (intptr_t)(arg2))
+
+#define syslog_3(prio, format, arg1, arg2, arg3) \
+				_syslog_4(prio, LOG_TYPE_COMMENT, (intptr_t)(format), \
+						(intptr_t)(arg1), (intptr_t)(arg2), (intptr_t)(arg3))
+
+#define syslog_4(prio, format, arg1, arg2, arg3, arg4) \
+				_syslog_5(prio, LOG_TYPE_COMMENT, (intptr_t)(format), \
+						(intptr_t)(arg1), (intptr_t)(arg2), (intptr_t)(arg3), \
+														(intptr_t)(arg4))
+
+#define syslog_5(prio, format, arg1, arg2, arg3, arg4, arg5) \
+				_syslog_6(prio, LOG_TYPE_COMMENT, (intptr_t)(format), \
+						(intptr_t)(arg1), (intptr_t)(arg2), (intptr_t)(arg3), \
+										(intptr_t)(arg4), (intptr_t)(arg5))
+
+/*
+ *  ログ情報（アサーションの失敗）を出力するためのマクロ
+ */
+#ifndef TOPPERS_assert_fail
+#define TOPPERS_assert_fail(exp, file, line) \
+				_syslog_3(LOG_EMERG, LOG_TYPE_ASSERT, (intptr_t)(file), \
+										(intptr_t)(line), (intptr_t)(exp))
+#endif /* TOPPERS_assert_fail */
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TOPPERS_T_SYSLOG_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/include/test_lib.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/include/test_lib.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/include/test_lib.h	(revision 453)
@@ -0,0 +1,150 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2005-2013 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *		テストプログラム用ライブラリ
+ */
+
+#ifndef TOPPERS_TEST_LIB_H
+#define TOPPERS_TEST_LIB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <t_stddef.h>
+
+/*
+ *  ターゲット依存の定義
+ */
+#include "target_test.h"
+
+/*
+ *	自己診断関数の型
+ */
+typedef ER (*BIT_FUNC)(void);
+
+/*
+ *	自己診断関数の設定
+ */
+extern void	set_bit_func(BIT_FUNC bit_func);
+
+/*
+ *  テストプログラムの開始
+ */
+extern void	test_start(char *progname);
+
+/*
+ *  システムログの出力処理
+ */
+extern void	syslog_flush(void);
+
+/*
+ *	テストプログラムの終了
+ */
+extern void	test_finish(void);
+
+/*
+ *	チェックポイント
+ */
+extern void	check_point(uint_t count);
+
+/*
+ *	完了チェックポイント
+ */
+extern void	check_finish(uint_t count);
+
+/*
+ *	条件チェック
+ */
+extern void	_check_assert(const char *expr, const char *file, int_t line);
+#define check_assert(exp) \
+	((void)(!(exp) ? (_check_assert(#exp, __FILE__, __LINE__), 0) : 0))
+
+/*
+ *	エラーコードチェック
+ */
+extern void	_check_ercd(ER ercd, const char *file, int_t line);
+#define check_ercd(ercd, expected_ercd) \
+	((void)((ercd) != (expected_ercd) ? \
+					(_check_ercd(ercd, __FILE__, __LINE__), 0) : 0))
+
+/*
+ *	システム状態のチェック
+ */
+Inline void
+check_state(bool_t ctx, bool_t loc, PRI ipm, bool_t dsp,
+										bool_t dpn, bool_t tex)
+{
+	PRI		intpri;
+	ER		ercd;
+
+	check_assert(sns_ctx() == ctx);
+	check_assert(sns_loc() == loc);
+	if (!loc) {
+		/*
+		 *  IPMのチェックは，CPUロック解除状態の場合にのみ行う．
+		 */
+		ercd = get_ipm(&intpri);
+		check_ercd(ercd, E_OK);
+		check_assert(intpri == ipm);
+	}
+	check_assert(sns_dsp() == dsp);
+	check_assert(sns_dpn() == dpn);
+	check_assert(sns_tex() == tex);
+}
+
+/*
+ *	システム状態のチェック（非タスクコンテキスト用）
+ */
+Inline void
+check_state_i(bool_t ctx, bool_t loc, bool_t dsp, bool_t dpn, bool_t tex)
+{
+	check_assert(sns_ctx() == ctx);
+	check_assert(sns_loc() == loc);
+	check_assert(sns_dsp() == dsp);
+	check_assert(sns_dpn() == dpn);
+	check_assert(sns_tex() == tex);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TOPPERS_TEST_LIB_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/Makefile.kernel
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/Makefile.kernel	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/Makefile.kernel	(revision 453)
@@ -0,0 +1,144 @@
+#
+#  TOPPERS/ASP Kernel
+#      Toyohashi Open Platform for Embedded Real-Time Systems/
+#      Advanced Standard Profile Kernel
+# 
+#  Copyright (C) 2003 by Embedded and Real-Time Systems Laboratory
+#                              Toyohashi Univ. of Technology, JAPAN
+#  Copyright (C) 2005-2010 by Embedded and Real-Time Systems Laboratory
+#              Graduate School of Information Science, Nagoya Univ., JAPAN
+# 
+#  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+#  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+#  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+#  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#      スコード中に含まれていること．
+#  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#      の無保証規定を掲載すること．
+#  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#      と．
+#    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#        作権表示，この利用条件および下記の無保証規定を掲載すること．
+#    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#        報告すること．
+#  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+#      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+#      免責すること．
+# 
+#  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+#  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+#  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+#  の責任を負わない．
+# 
+#  @(#) $Id$
+# 
+
+#
+#		カーネルのファイル構成の定義
+#
+
+#
+#  1つのソースファイルから複数のオブジェクトファイルを生成するように作
+#  成されたソースファイルのリスト
+#
+KERNEL_FCSRCS = startup.c task.c wait.c time_event.c \
+				task_manage.c task_refer.c task_sync.c task_except.c \
+				semaphore.c eventflag.c dataqueue.c pridataq.c mailbox.c \
+				mutex.c mempfix.c time_manage.c cyclic.c alarm.c \
+				sys_manage.c interrupt.c exception.c
+
+#
+#  各ソースファイルから生成されるオブジェクトファイルのリスト
+#
+startup = sta_ker.o ext_ker.o kermem.o
+
+task = tskini.o tsksched.o tskrun.o tsknrun.o \
+		tskdmt.o tskact.o tskpri.o tskrot.o tsktex.o
+
+wait = waimake.o waicmp.o waitmo.o waitmook.o \
+		wairel.o wobjwai.o wobjwaitmo.o iniwque.o
+
+time_event = tmeini.o tmeup.o tmedown.o tmeins.o tmedel.o tmeltim.o sigtim.o
+
+task_manage = acre_tsk.o del_tsk.o act_tsk.o iact_tsk.o can_act.o \
+		ext_tsk.o ter_tsk.o chg_pri.o get_pri.o get_inf.o
+
+task_refer = ref_tsk.o
+
+task_sync = slp_tsk.o tslp_tsk.o wup_tsk.o iwup_tsk.o can_wup.o \
+		rel_wai.o irel_wai.o sus_tsk.o rsm_tsk.o dly_tsk.o
+
+task_except = def_tex.o ras_tex.o iras_tex.o dis_tex.o ena_tex.o \
+		sns_tex.o ref_tex.o
+
+semaphore = semini.o acre_sem.o del_sem.o sig_sem.o isig_sem.o \
+		wai_sem.o pol_sem.o twai_sem.o ini_sem.o ref_sem.o
+
+eventflag = flgini.o flgcnd.o acre_flg.o del_flg.o set_flg.o iset_flg.o \
+		clr_flg.o wai_flg.o pol_flg.o twai_flg.o ini_flg.o ref_flg.o
+
+dataqueue = dtqini.o dtqenq.o dtqfenq.o dtqdeq.o dtqsnd.o dtqfsnd.o dtqrcv.o \
+		acre_dtq.o del_dtq.o snd_dtq.o psnd_dtq.o ipsnd_dtq.o tsnd_dtq.o \
+		fsnd_dtq.o ifsnd_dtq.o rcv_dtq.o prcv_dtq.o trcv_dtq.o ini_dtq.o \
+		ref_dtq.o
+
+pridataq = pdqini.o pdqenq.o pdqdeq.o pdqsnd.o pdqrcv.o \
+		acre_pdq.o del_pdq.o snd_pdq.o psnd_pdq.o ipsnd_pdq.o tsnd_pdq.o \
+		rcv_pdq.o prcv_pdq.o trcv_pdq.o ini_pdq.o ref_pdq.o
+
+mailbox = mbxini.o acre_mbx.o del_mbx.o snd_mbx.o rcv_mbx.o \
+		prcv_mbx.o trcv_mbx.o ini_mbx.o ref_mbx.o
+
+mutex = mtxhook.o mtxini.o mtxchk.o mtxscan.o mtxcalc.o mtxrel.o mtxrela.o \
+		acre_mtx.o del_mtx.o loc_mtx.o ploc_mtx.o tloc_mtx.o unl_mtx.o ini_mtx.o ref_mtx.o
+
+mempfix = mpfini.o mpfget.o acre_mpf.o del_mpf.o get_mpf.o \
+		pget_mpf.o tget_mpf.o rel_mpf.o ini_mpf.o ref_mpf.o
+
+time_manage = get_tim.o get_utm.o
+
+cyclic = cycini.o acre_cyc.o del_cyc.o sta_cyc.o stp_cyc.o ref_cyc.o cyccal.o
+
+alarm = almini.o acre_alm.o del_alm.o sta_alm.o ista_alm.o stp_alm.o \
+		istp_alm.o ref_alm.o almcal.o
+
+sys_manage = rot_rdq.o irot_rdq.o get_tid.o iget_tid.o \
+		loc_cpu.o iloc_cpu.o unl_cpu.o iunl_cpu.o dis_dsp.o ena_dsp.o \
+		sns_ctx.o sns_loc.o sns_dsp.o sns_dpn.o sns_ker.o
+
+interrupt = isrini.o isrcal.o acre_isr.o del_isr.o \
+		intini.o dis_int.o ena_int.o chg_ipm.o get_ipm.o
+
+exception = excini.o xsns_dpn.o xsns_xpn.o
+
+#
+#  生成されるオブジェクトファイルの依存関係の定義
+#
+$(startup) $(startup:.o=.s) $(startup:.o=.d): startup.c
+$(task) $(task:.o=.s) $(task:.o=.d): task.c
+$(wait) $(wait:.o=.s) $(wait:.o=.d): wait.c
+$(time_event) $(time_event:.o=.s) $(time_event:.o=.d): time_event.c
+$(task_manage) $(task_manage:.o=.s) $(task_manage:.o=.d): task_manage.c
+$(task_refer) $(task_refer:.o=.s) $(task_refer:.o=.d): task_refer.c
+$(task_sync) $(task_sync:.o=.s) $(task_sync:.o=.d): task_sync.c
+$(task_except) $(task_except:.o=.s) $(task_except:.o=.d): task_except.c
+$(semaphore) $(semaphore:.o=.s) $(semaphore:.o=.d): semaphore.c
+$(eventflag) $(eventflag:.o=.s) $(eventflag:.o=.d): eventflag.c
+$(dataqueue) $(dataqueue:.o=.s) $(dataqueue:.o=.d): dataqueue.c
+$(pridataq) $(pridataq:.o=.s) $(pridataq:.o=.d): pridataq.c
+$(mailbox) $(mailbox:.o=.s) $(mailbox:.o=.d): mailbox.c
+$(mutex) $(mutex:.o=.s) $(mutex:.o=.d): mutex.c
+$(mempfix) $(mempfix:.o=.s) $(mempfix:.o=.d): mempfix.c
+$(time_manage) $(time_manage:.o=.s) $(time_manage:.o=.d): time_manage.c
+$(cyclic) $(cyclic:.o=.s) $(cyclic:.o=.d): cyclic.c
+$(alarm) $(alarm:.o=.s) $(alarm:.o=.d): alarm.c
+$(sys_manage) $(sys_manage:.o=.s) $(sys_manage:.o=.d): sys_manage.c
+$(interrupt) $(interrupt:.o=.s) $(interrupt:.o=.d): interrupt.c
+$(exception) $(exception:.o=.s) $(exception:.o=.d): exception.c
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/alarm.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/alarm.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/alarm.c	(revision 453)
@@ -0,0 +1,477 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2014 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		アラームハンドラ機能
+ */
+
+#include "kernel_impl.h"
+#include "check.h"
+#include "alarm.h"
+
+/*
+ *  トレースログマクロのデフォルト定義
+ */
+#ifndef LOG_ALM_ENTER
+#define LOG_ALM_ENTER(p_almcb)
+#endif /* LOG_ALM_ENTER */
+
+#ifndef LOG_ALM_LEAVE
+#define LOG_ALM_LEAVE(p_almcb)
+#endif /* LOG_ALM_LEAVE */
+
+#ifndef LOG_ACRE_ALM_ENTER
+#define LOG_ACRE_ALM_ENTER(pk_calm)
+#endif /* LOG_ACRE_ALM_ENTER */
+
+#ifndef LOG_ACRE_ALM_LEAVE
+#define LOG_ACRE_ALM_LEAVE(ercd)
+#endif /* LOG_ACRE_ALM_LEAVE */
+
+#ifndef LOG_DEL_ALM_ENTER
+#define LOG_DEL_ALM_ENTER(almid)
+#endif /* LOG_DEL_ALM_ENTER */
+
+#ifndef LOG_DEL_ALM_LEAVE
+#define LOG_DEL_ALM_LEAVE(ercd)
+#endif /* LOG_DEL_ALM_LEAVE */
+
+#ifndef LOG_STA_ALM_ENTER
+#define LOG_STA_ALM_ENTER(almid, almtim)
+#endif /* LOG_STA_ALM_ENTER */
+
+#ifndef LOG_STA_ALM_LEAVE
+#define LOG_STA_ALM_LEAVE(ercd)
+#endif /* LOG_STA_ALM_LEAVE */
+
+#ifndef LOG_ISTA_ALM_ENTER
+#define LOG_ISTA_ALM_ENTER(almid, almtim)
+#endif /* LOG_ISTA_ALM_ENTER */
+
+#ifndef LOG_ISTA_ALM_LEAVE
+#define LOG_ISTA_ALM_LEAVE(ercd)
+#endif /* LOG_ISTA_ALM_LEAVE */
+
+#ifndef LOG_STP_ALM_ENTER
+#define LOG_STP_ALM_ENTER(almid)
+#endif /* LOG_STP_ALM_ENTER */
+
+#ifndef LOG_STP_ALM_LEAVE
+#define LOG_STP_ALM_LEAVE(ercd)
+#endif /* LOG_STP_ALM_LEAVE */
+
+#ifndef LOG_ISTP_ALM_ENTER
+#define LOG_ISTP_ALM_ENTER(almid)
+#endif /* LOG_ISTP_ALM_ENTER */
+
+#ifndef LOG_ISTP_ALM_LEAVE
+#define LOG_ISTP_ALM_LEAVE(ercd)
+#endif /* LOG_ISTP_ALM_LEAVE */
+
+#ifndef LOG_REF_ALM_ENTER
+#define LOG_REF_ALM_ENTER(almid, pk_ralm)
+#endif /* LOG_REF_ALM_ENTER */
+
+#ifndef LOG_REF_ALM_LEAVE
+#define LOG_REF_ALM_LEAVE(ercd, pk_ralm)
+#endif /* LOG_REF_ALM_LEAVE */
+
+/*
+ *  アラームハンドラの数
+ */
+#define tnum_alm	((uint_t)(tmax_almid - TMIN_ALMID + 1))
+#define tnum_salm	((uint_t)(tmax_salmid - TMIN_ALMID + 1))
+
+/*
+ *  アラームハンドラIDからアラームハンドラ管理ブロックを取り出すためのマクロ
+ */
+#define INDEX_ALM(almid)	((uint_t)((almid) - TMIN_ALMID))
+#define get_almcb(almid)	(&(almcb_table[INDEX_ALM(almid)]))
+
+#ifdef TOPPERS_almini
+
+/*
+ *  使用していないアラームハンドラ管理ブロックのリスト
+ *
+ *  アラームハンドラ管理ブロックの先頭にはキューにつなぐための領域がな
+ *  いため，タイムイベントブロック（tmevtb）の領域を用いる．
+ */
+QUEUE	free_almcb;
+
+/*
+ *  アラームハンドラ機能の初期化
+ */
+void
+initialize_alarm(void)
+{
+	uint_t	i, j;
+	ALMCB	*p_almcb;
+	ALMINIB	*p_alminib;
+
+	for (i = 0; i < tnum_salm; i++) {
+		p_almcb = &(almcb_table[i]);
+		p_almcb->p_alminib = &(alminib_table[i]);
+		p_almcb->almsta = false;
+	}
+	queue_initialize(&free_almcb);
+	for (j = 0; i < tnum_alm; i++, j++) {
+		p_almcb = &(almcb_table[i]);
+		p_alminib = &(aalminib_table[j]);
+		p_alminib->almatr = TA_NOEXS;
+		p_almcb->p_alminib = ((const ALMINIB *) p_alminib);
+		queue_insert_prev(&free_almcb, ((QUEUE *) &(p_almcb->tmevtb)));
+	}
+}
+
+#endif /* TOPPERS_almini */
+
+/*
+ *  アラームハンドラの生成
+ */
+#ifdef TOPPERS_acre_alm
+
+ER_UINT
+acre_alm(const T_CALM *pk_calm)
+{
+	ALMCB	*p_almcb;
+	ALMINIB	*p_alminib;
+	ER		ercd;
+
+	LOG_ACRE_ALM_ENTER(pk_calm);
+	CHECK_TSKCTX_UNL();
+	CHECK_RSATR(pk_calm->almatr, TA_NULL);
+	CHECK_ALIGN_FUNC(pk_calm->almhdr);
+	CHECK_NONNULL_FUNC(pk_calm->almhdr);
+
+	t_lock_cpu();
+	if (tnum_alm == 0 || queue_empty(&free_almcb)) {
+		ercd = E_NOID;
+	}
+	else {
+		p_almcb = ((ALMCB *)(((char *) queue_delete_next(&free_almcb))
+												- offsetof(ALMCB, tmevtb)));
+		p_alminib = (ALMINIB *)(p_almcb->p_alminib);
+		p_alminib->almatr = pk_calm->almatr;
+		p_alminib->exinf = pk_calm->exinf;
+		p_alminib->almhdr = pk_calm->almhdr;
+
+		p_almcb->almsta = false;
+		ercd = ALMID(p_almcb);
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_ACRE_ALM_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_acre_alm */
+
+/*
+ *  アラームハンドラの削除
+ */
+#ifdef TOPPERS_del_alm
+
+ER
+del_alm(ID almid)
+{
+	ALMCB	*p_almcb;
+	ALMINIB	*p_alminib;
+	ER		ercd;
+
+	LOG_DEL_ALM_ENTER(almid);
+	CHECK_TSKCTX_UNL();
+	CHECK_ALMID(almid);
+	p_almcb = get_almcb(almid);
+
+	t_lock_cpu();
+	if (p_almcb->p_alminib->almatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (ALMID(p_almcb) > tmax_salmid) {
+		if (p_almcb->almsta) {
+			p_almcb->almsta = false;
+			tmevtb_dequeue(&(p_almcb->tmevtb));
+		}
+
+		p_alminib = (ALMINIB *)(p_almcb->p_alminib);
+		p_alminib->almatr = TA_NOEXS;
+		queue_insert_prev(&free_almcb, ((QUEUE *) &(p_almcb->tmevtb)));
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_OBJ;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_DEL_ALM_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_del_alm */
+
+/*
+ *  アラームハンドラの動作開始
+ */
+#ifdef TOPPERS_sta_alm
+
+ER
+sta_alm(ID almid, RELTIM almtim)
+{
+	ALMCB	*p_almcb;
+	ER		ercd;
+
+	LOG_STA_ALM_ENTER(almid, almtim);
+	CHECK_TSKCTX_UNL();
+	CHECK_ALMID(almid);
+	CHECK_PAR(almtim <= TMAX_RELTIM);
+	p_almcb = get_almcb(almid);
+
+	t_lock_cpu();
+	if (p_almcb->p_alminib->almatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		if (p_almcb->almsta) {
+			tmevtb_dequeue(&(p_almcb->tmevtb));
+		}
+		else {
+			p_almcb->almsta = true;
+		}
+		tmevtb_enqueue(&(p_almcb->tmevtb), almtim,
+									(CBACK) call_almhdr, (void *) p_almcb);
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_STA_ALM_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_sta_alm */
+
+/*
+ *  アラームハンドラの動作開始（非タスクコンテキスト用）
+ */
+#ifdef TOPPERS_ista_alm
+
+ER
+ista_alm(ID almid, RELTIM almtim)
+{
+	ALMCB	*p_almcb;
+	ER		ercd;
+
+	LOG_ISTA_ALM_ENTER(almid, almtim);
+	CHECK_INTCTX_UNL();
+	CHECK_ALMID(almid);
+	CHECK_PAR(almtim <= TMAX_RELTIM);
+	p_almcb = get_almcb(almid);
+
+	i_lock_cpu();
+	if (p_almcb->p_alminib->almatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		if (p_almcb->almsta) {
+			tmevtb_dequeue(&(p_almcb->tmevtb));
+		}
+		else {
+			p_almcb->almsta = true;
+		}
+		tmevtb_enqueue(&(p_almcb->tmevtb), almtim,
+									(CBACK) call_almhdr, (void *) p_almcb);
+		ercd = E_OK;
+	}
+	i_unlock_cpu();
+
+  error_exit:
+	LOG_ISTA_ALM_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ista_alm */
+
+/*
+ *  アラームハンドラの動作停止
+ */
+#ifdef TOPPERS_stp_alm
+
+ER
+stp_alm(ID almid)
+{
+	ALMCB	*p_almcb;
+	ER		ercd;
+
+	LOG_STP_ALM_ENTER(almid);
+	CHECK_TSKCTX_UNL();
+	CHECK_ALMID(almid);
+	p_almcb = get_almcb(almid);
+
+	t_lock_cpu();
+	if (p_almcb->p_alminib->almatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		if (p_almcb->almsta) {
+			p_almcb->almsta = false;
+			tmevtb_dequeue(&(p_almcb->tmevtb));
+		}
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_STP_ALM_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_stp_alm */
+
+/*
+ *  アラームハンドラの動作停止（非タスクコンテキスト用）
+ */
+#ifdef TOPPERS_istp_alm
+
+ER
+istp_alm(ID almid)
+{
+	ALMCB	*p_almcb;
+	ER		ercd;
+
+	LOG_ISTP_ALM_ENTER(almid);
+	CHECK_INTCTX_UNL();
+	CHECK_ALMID(almid);
+	p_almcb = get_almcb(almid);
+
+	i_lock_cpu();
+	if (p_almcb->p_alminib->almatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		if (p_almcb->almsta) {
+			p_almcb->almsta = false;
+			tmevtb_dequeue(&(p_almcb->tmevtb));
+		}
+		ercd = E_OK;
+	}
+	i_unlock_cpu();
+
+  error_exit:
+	LOG_ISTP_ALM_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_istp_alm */
+
+/*
+ *  アラームハンドラの状態参照
+ */
+#ifdef TOPPERS_ref_alm
+
+ER
+ref_alm(ID almid, T_RALM *pk_ralm)
+{
+	ALMCB	*p_almcb;
+	ER		ercd;
+    
+	LOG_REF_ALM_ENTER(almid, pk_ralm);
+	CHECK_TSKCTX_UNL();
+	CHECK_ALMID(almid);
+	p_almcb = get_almcb(almid);
+
+	t_lock_cpu();
+	if (p_almcb->p_alminib->almatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		if (p_almcb->almsta) {
+			pk_ralm->almstat = TALM_STA;
+			pk_ralm->lefttim = tmevt_lefttim(&(p_almcb->tmevtb));
+		}
+		else {
+			pk_ralm->almstat = TALM_STP;
+		}
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_REF_ALM_LEAVE(ercd, pk_ralm);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ref_alm */
+
+/*
+ *  アラームハンドラ起動ルーチン
+ */
+#ifdef TOPPERS_almcal
+
+void
+call_almhdr(ALMCB *p_almcb)
+{
+	PRI		saved_ipm;
+
+	/*
+	 *  アラームハンドラを停止状態にする．
+	 */
+	p_almcb->almsta = false;
+
+	/*
+	 *  アラームハンドラを，CPUロック解除状態で呼び出す．
+	 */
+	saved_ipm = i_get_ipm();
+	i_unlock_cpu();
+
+	LOG_ALM_ENTER(p_almcb);
+	(*((ALMHDR)(p_almcb->p_alminib->almhdr)))(p_almcb->p_alminib->exinf);
+	LOG_ALM_LEAVE(p_almcb);
+
+	if (!i_sense_lock()) {
+		i_lock_cpu();
+	}
+	i_set_ipm(saved_ipm);
+}
+
+#endif /* TOPPERS_almcal */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/alarm.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/alarm.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/alarm.h	(revision 453)
@@ -0,0 +1,109 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		アラームハンドラ機能
+ */
+
+#ifndef TOPPERS_ALARM_H
+#define TOPPERS_ALARM_H
+
+#include <queue.h>
+#include "time_event.h"
+
+/*
+ *  アラームハンドラ初期化ブロック
+ */
+typedef struct alarm_handler_initialization_block {
+	ATR			almatr;			/* アラームハンドラ属性 */
+	intptr_t	exinf;			/* アラームハンドラの拡張情報 */
+	ALMHDR		almhdr;			/* アラームハンドラの起動番地 */
+} ALMINIB;
+
+/*
+ *  アラームハンドラ管理ブロック
+ */
+typedef struct alarm_handler_control_block {
+	const ALMINIB *p_alminib;	/* 初期化ブロックへのポインタ */
+	bool_t		almsta;			/* アラームハンドラの動作状態 */
+	TMEVTB		tmevtb;			/* タイムイベントブロック */
+} ALMCB;
+
+/*
+ *  使用していないアラームハンドラ管理ブロックのリスト
+ */
+extern QUEUE	free_almcb;
+
+/*
+ *  アラームハンドラIDの最大値（kernel_cfg.c）
+ */
+extern const ID	tmax_almid;
+extern const ID	tmax_salmid;
+
+/*
+ *  アラームハンドラ初期化ブロックのエリア（kernel_cfg.c）
+ */
+extern const ALMINIB	alminib_table[];
+extern ALMINIB			aalminib_table[];
+
+/*
+ *  アラームハンドラ管理ブロックのエリア（kernel_cfg.c）
+ */
+extern ALMCB	almcb_table[];
+
+/*
+ *  アラームハンドラ管理ブロックからアラームハンドラIDを取り出すための
+ *  マクロ
+ */
+#define	ALMID(p_almcb)	((ID)(((p_almcb) - almcb_table) + TMIN_ALMID))
+
+/*
+ *  アラームハンドラ機能の初期化
+ */
+extern void	initialize_alarm(void);
+
+/*
+ *  アラームハンドラ起動ルーチン
+ */
+extern void	call_almhdr(ALMCB *p_almcb);
+
+#endif /* TOPPERS_ALARM_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/allfunc.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/allfunc.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/allfunc.h	(revision 453)
@@ -0,0 +1,282 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2005-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		すべての関数をコンパイルするための定義
+ */
+
+#ifndef TOPPERS_ALLFUNC_H
+#define TOPPERS_ALLFUNC_H
+
+/* startup.c */
+#define TOPPERS_sta_ker
+#define TOPPERS_ext_ker
+#define TOPPERS_kermem
+
+/* task.c */
+#define TOPPERS_tskini
+#define TOPPERS_tsksched
+#define TOPPERS_tskrun
+#define TOPPERS_tsknrun
+#define TOPPERS_tskdmt
+#define TOPPERS_tskact
+#define TOPPERS_tskpri
+#define TOPPERS_tskrot
+#define TOPPERS_tsktex
+
+/* wait.c */
+#define TOPPERS_waimake
+#define TOPPERS_waicmp
+#define TOPPERS_waitmo
+#define TOPPERS_waitmook
+#define TOPPERS_wairel
+#define TOPPERS_wobjwai
+#define TOPPERS_wobjwaitmo
+#define TOPPERS_iniwque
+
+/* time_event.c */
+#define TOPPERS_tmeini
+#define TOPPERS_tmeup
+#define TOPPERS_tmedown
+#define TOPPERS_tmeins
+#define TOPPERS_tmedel
+#define TOPPERS_tmeltim
+#define TOPPERS_sigtim
+
+/* task_manage.c */
+#define TOPPERS_acre_tsk
+#define TOPPERS_del_tsk
+#define TOPPERS_act_tsk
+#define TOPPERS_iact_tsk
+#define TOPPERS_can_act
+#define TOPPERS_ext_tsk
+#define TOPPERS_ter_tsk
+#define TOPPERS_chg_pri
+#define TOPPERS_get_pri
+#define TOPPERS_get_inf
+
+/* task_refer.c */
+#define TOPPERS_ref_tsk
+
+/* task_sync.c */
+#define TOPPERS_slp_tsk
+#define TOPPERS_tslp_tsk
+#define TOPPERS_wup_tsk
+#define TOPPERS_iwup_tsk
+#define TOPPERS_can_wup
+#define TOPPERS_rel_wai
+#define TOPPERS_irel_wai
+#define TOPPERS_sus_tsk
+#define TOPPERS_rsm_tsk
+#define TOPPERS_dly_tsk
+
+/* task_except.c */
+#define TOPPERS_def_tex
+#define TOPPERS_ras_tex
+#define TOPPERS_iras_tex
+#define TOPPERS_dis_tex
+#define TOPPERS_ena_tex
+#define TOPPERS_sns_tex
+#define TOPPERS_ref_tex
+
+/* semaphore.c */
+#define TOPPERS_semini
+#define TOPPERS_acre_sem
+#define TOPPERS_del_sem
+#define TOPPERS_sig_sem
+#define TOPPERS_isig_sem
+#define TOPPERS_wai_sem
+#define TOPPERS_pol_sem
+#define TOPPERS_twai_sem
+#define TOPPERS_ini_sem
+#define TOPPERS_ref_sem
+
+/* eventflag.c */
+#define TOPPERS_flgini
+#define TOPPERS_flgcnd
+#define TOPPERS_acre_flg
+#define TOPPERS_del_flg
+#define TOPPERS_set_flg
+#define TOPPERS_iset_flg
+#define TOPPERS_clr_flg
+#define TOPPERS_wai_flg
+#define TOPPERS_pol_flg
+#define TOPPERS_twai_flg
+#define TOPPERS_ini_flg
+#define TOPPERS_ref_flg
+
+/* dataqueue.c */
+#define TOPPERS_dtqini
+#define TOPPERS_dtqenq
+#define TOPPERS_dtqfenq
+#define TOPPERS_dtqdeq
+#define TOPPERS_dtqsnd
+#define TOPPERS_dtqfsnd
+#define TOPPERS_dtqrcv
+#define TOPPERS_acre_dtq
+#define TOPPERS_del_dtq
+#define TOPPERS_snd_dtq
+#define TOPPERS_psnd_dtq
+#define TOPPERS_ipsnd_dtq
+#define TOPPERS_tsnd_dtq
+#define TOPPERS_fsnd_dtq
+#define TOPPERS_ifsnd_dtq
+#define TOPPERS_rcv_dtq
+#define TOPPERS_prcv_dtq
+#define TOPPERS_trcv_dtq
+#define TOPPERS_ini_dtq
+#define TOPPERS_ref_dtq
+
+/* pridataq.c */
+#define TOPPERS_pdqini
+#define TOPPERS_pdqenq
+#define TOPPERS_pdqdeq
+#define TOPPERS_pdqsnd
+#define TOPPERS_pdqrcv
+#define TOPPERS_acre_pdq
+#define TOPPERS_del_pdq
+#define TOPPERS_snd_pdq
+#define TOPPERS_psnd_pdq
+#define TOPPERS_ipsnd_pdq
+#define TOPPERS_tsnd_pdq
+#define TOPPERS_rcv_pdq
+#define TOPPERS_prcv_pdq
+#define TOPPERS_trcv_pdq
+#define TOPPERS_ini_pdq
+#define TOPPERS_ref_pdq
+
+/* mailbox.c */
+#define TOPPERS_mbxini
+#define TOPPERS_acre_mbx
+#define TOPPERS_del_mbx
+#define TOPPERS_snd_mbx
+#define TOPPERS_rcv_mbx
+#define TOPPERS_prcv_mbx
+#define TOPPERS_trcv_mbx
+#define TOPPERS_ini_mbx
+#define TOPPERS_ref_mbx
+
+/* mutex.c */
+#define TOPPERS_mtxhook
+#define TOPPERS_mtxini
+#define TOPPERS_mtxchk
+#define TOPPERS_mtxscan
+#define TOPPERS_mtxcalc
+#define TOPPERS_mtxrel
+#define TOPPERS_mtxrela
+#define TOPPERS_acre_mtx
+#define TOPPERS_del_mtx
+#define TOPPERS_loc_mtx
+#define TOPPERS_ploc_mtx
+#define TOPPERS_tloc_mtx
+#define TOPPERS_unl_mtx
+#define TOPPERS_ini_mtx
+#define TOPPERS_ref_mtx
+
+/* mempfix.c */
+#define TOPPERS_mpfini
+#define TOPPERS_mpfget
+#define TOPPERS_acre_mpf
+#define TOPPERS_del_mpf
+#define TOPPERS_get_mpf
+#define TOPPERS_pget_mpf
+#define TOPPERS_tget_mpf
+#define TOPPERS_rel_mpf
+#define TOPPERS_ini_mpf
+#define TOPPERS_ref_mpf
+
+/* time_manage.c */
+#define TOPPERS_get_tim
+#define TOPPERS_get_utm
+
+/* cyclic.c */
+#define TOPPERS_cycini
+#define TOPPERS_acre_cyc
+#define TOPPERS_del_cyc
+#define TOPPERS_sta_cyc
+#define TOPPERS_stp_cyc
+#define TOPPERS_ref_cyc
+#define TOPPERS_cyccal
+
+/* alarm.c */
+#define TOPPERS_almini
+#define TOPPERS_acre_alm
+#define TOPPERS_del_alm
+#define TOPPERS_sta_alm
+#define TOPPERS_ista_alm
+#define TOPPERS_stp_alm
+#define TOPPERS_istp_alm
+#define TOPPERS_ref_alm
+#define TOPPERS_almcal
+
+/* sys_manage.c */
+#define TOPPERS_rot_rdq
+#define TOPPERS_irot_rdq
+#define TOPPERS_get_tid
+#define TOPPERS_iget_tid
+#define TOPPERS_loc_cpu
+#define TOPPERS_iloc_cpu
+#define TOPPERS_unl_cpu
+#define TOPPERS_iunl_cpu
+#define TOPPERS_dis_dsp
+#define TOPPERS_ena_dsp
+#define TOPPERS_sns_ctx
+#define TOPPERS_sns_loc
+#define TOPPERS_sns_dsp
+#define TOPPERS_sns_dpn
+#define TOPPERS_sns_ker
+
+/* interrupt.c */
+#define TOPPERS_isrini
+#define TOPPERS_isrcal
+#define TOPPERS_acre_isr
+#define TOPPERS_del_isr
+#define TOPPERS_intini
+#define TOPPERS_dis_int
+#define TOPPERS_ena_int
+#define TOPPERS_chg_ipm
+#define TOPPERS_get_ipm
+
+/* exception.c */
+#define TOPPERS_excini
+#define TOPPERS_xsns_dpn
+#define TOPPERS_xsns_xpn
+
+#endif /* TOPPERS_ALLFUNC_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/check.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/check.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/check.h	(revision 453)
@@ -0,0 +1,475 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2014 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		エラーチェック用マクロ
+ */
+
+#ifndef TOPPERS_CHECK_H
+#define TOPPERS_CHECK_H
+
+/*
+ *  予約属性エラーのチェック（E_PAR）
+ */
+#define CHECK_RSATR(atr, valid_atr) do {					\
+	if (((atr) & ~(valid_atr)) != 0U) {						\
+		ercd = E_RSATR;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+/*
+ *  優先度の範囲の判定
+ */
+#define VALID_TPRI(tpri)	(TMIN_TPRI <= (tpri) && (tpri) <= TMAX_TPRI)
+
+#define VALID_DPRI(dpri)	(TMIN_DPRI <= (dpri) && (dpri) <= TMAX_DPRI)
+
+#define VALID_MPRI(mpri)	(TMIN_MPRI <= (mpri) && (mpri) <= TMAX_MPRI)
+
+#define VALID_ISRPRI(isrpri) \
+				(TMIN_ISRPRI <= (isrpri) && (isrpri) <= TMAX_ISRPRI)
+
+#ifndef VALID_INTPRI_CHGIPM
+#define VALID_INTPRI_CHGIPM(intpri) \
+				(TMIN_INTPRI <= (intpri) && (intpri) <= TIPM_ENAALL)
+#endif /* VALID_INTPRI_CHGIPM */
+
+/*
+ *  タスク優先度のチェック（E_PAR）
+ */
+#define CHECK_TPRI(tpri) do {								\
+	if (!VALID_TPRI(tpri)) {								\
+		ercd = E_PAR;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+#define CHECK_TPRI_INI(tpri) do {							\
+	if (!(VALID_TPRI(tpri) || (tpri) == TPRI_INI)) {		\
+		ercd = E_PAR;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+#define CHECK_TPRI_SELF(tpri) do {							\
+	if (!(VALID_TPRI(tpri) || (tpri) == TPRI_SELF)) {		\
+		ercd = E_PAR;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+/*
+ *  データ優先度のチェック（E_PAR）
+ */
+#define CHECK_DPRI(dpri) do {								\
+	if (!VALID_DPRI(dpri)) {								\
+		ercd = E_PAR;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+/*
+ *  メッセージ優先度のチェック（E_PAR）
+ */
+#define CHECK_MPRI(mpri) do {								\
+	if (!VALID_MPRI(mpri)) {								\
+		ercd = E_PAR;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+/*
+ *  割込みサービスルーチン優先度のチェック（E_PAR）
+ */
+#define CHECK_ISRPRI(isrpri) do {							\
+	if (!VALID_ISRPRI(isrpri)) {							\
+		ercd = E_PAR;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+/*
+ *  タイムアウト指定値のチェック（E_PAR）
+ */
+#define CHECK_TMOUT(tmout) do {								\
+	if (!(TMO_FEVR <= (tmout))) {							\
+		ercd = E_PAR;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+/*
+ *  割込み優先度のチェック（E_PAR）
+ */
+#define CHECK_INTPRI_CHGIPM(intpri) do {					\
+	if (!VALID_INTPRI_CHGIPM(intpri)) {						\
+		ercd = E_PAR;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+/*
+ *  割込み番号のチェック（E_PAR）
+ */
+#define CHECK_INTNO_CREISR(intno) do {						\
+	if (!VALID_INTNO_CREISR(intno)) {						\
+		ercd = E_PAR;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+#define CHECK_INTNO_DISINT(intno) do {						\
+	if (!VALID_INTNO_DISINT(intno)) {						\
+		ercd = E_PAR;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+/*
+ *  アラインしているかの判定
+ */
+#define ALIGNED(val, align)		((((uintptr_t)(val)) & ((align) - 1U)) == 0U)
+
+#ifdef CHECK_FUNC_ALIGN
+#define FUNC_ALIGNED(func)		ALIGNED(func, CHECK_FUNC_ALIGN)
+#else /* CHECK_FUNC_ALIGN */
+#define FUNC_ALIGNED(func)		true
+#endif /* CHECK_FUNC_ALIGN */
+
+#ifdef CHECK_STKSZ_ALIGN
+#define STKSZ_ALIGNED(stksz)	ALIGNED(stksz, CHECK_STKSZ_ALIGN)
+#else /* CHECK_STKSZ_ALIGN */
+#define STKSZ_ALIGNED(stksz)	true
+#endif /* CHECK_STKSZ_ALIGN */
+
+#ifdef CHECK_STACK_ALIGN
+#define STACK_ALIGNED(stack)	ALIGNED(stack, CHECK_STACK_ALIGN)
+#else /* CHECK_STACK_ALIGN */
+#define STACK_ALIGNED(stack)	true
+#endif /* CHECK_STACK_ALIGN */
+
+#ifdef CHECK_MPF_ALIGN
+#define MPF_ALIGNED(mpf)		ALIGNED(mpf, CHECK_MPF_ALIGN)
+#else /* CHECK_MPF_ALIGN */
+#define MPF_ALIGNED(mpf)		true
+#endif /* CHECK_MPF_ALIGN */
+
+#ifdef CHECK_MB_ALIGN
+#define MB_ALIGNED(mb)			ALIGNED(mb, CHECK_MB_ALIGN)
+#else /* CHECK_MB_ALIGN */
+#define MB_ALIGNED(mb)			true
+#endif /* CHECK_MB_ALIGN */
+
+/*
+ *  NULLでないことのチェック
+ */
+#ifdef CHECK_FUNC_NONNULL
+#define FUNC_NONNULL(func)		((func) != NULL)
+#else /* CHECK_FUNC_NONNULL */
+#define FUNC_NONNULL(func)		true
+#endif /* CHECK_FUNC_NONNULL */
+
+/*
+ *  関数の先頭番地のチェック（E_PAR）
+ */
+#define CHECK_ALIGN_FUNC(func) do {							\
+	if (!FUNC_ALIGNED(func)) {								\
+		ercd = E_PAR;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+#define CHECK_NONNULL_FUNC(func) do {						\
+	if (!FUNC_NONNULL(func)) {								\
+		ercd = E_PAR;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+/*
+ *  スタックサイズのチェック（E_PAR）
+ */
+#define CHECK_ALIGN_STKSZ(stksz) do {						\
+	if (!STKSZ_ALIGNED(stksz)) {							\
+		ercd = E_PAR;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+/*
+ *  スタックの先頭番地のチェック（E_PAR）
+ */
+#define CHECK_ALIGN_STACK(stack) do {						\
+	if (!STACK_ALIGNED(stack)) {							\
+		ercd = E_PAR;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+/*
+ *  固定長メモリプール領域の先頭番地のチェック（E_PAR）
+ */
+#define CHECK_ALIGN_MPF(mpf) do {							\
+	if (!MPF_ALIGNED(mpf)) {								\
+		ercd = E_PAR;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+/*
+ *  管理領域の先頭番地のチェック（E_PAR）
+ */
+#define CHECK_ALIGN_MB(mb) do {								\
+	if (!MB_ALIGNED(mb)) {									\
+		ercd = E_PAR;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+/*
+ *  その他のパラメータエラーのチェック（E_PAR）
+ */
+#define CHECK_PAR(exp) do {									\
+	if (!(exp)) {											\
+		ercd = E_PAR;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+/*
+ *  オブジェクトIDの範囲の判定
+ */
+#define VALID_TSKID(tskid)	(TMIN_TSKID <= (tskid) && (tskid) <= tmax_tskid)
+#define VALID_SEMID(semid)	(TMIN_SEMID <= (semid) && (semid) <= tmax_semid)
+#define VALID_FLGID(flgid)	(TMIN_FLGID <= (flgid) && (flgid) <= tmax_flgid)
+#define VALID_DTQID(dtqid)	(TMIN_DTQID <= (dtqid) && (dtqid) <= tmax_dtqid)
+#define VALID_PDQID(pdqid)	(TMIN_PDQID <= (pdqid) && (pdqid) <= tmax_pdqid)
+#define VALID_MBXID(mbxid)	(TMIN_MBXID <= (mbxid) && (mbxid) <= tmax_mbxid)
+#define VALID_MTXID(mtxid)	(TMIN_MTXID <= (mtxid) && (mtxid) <= tmax_mtxid)
+#define VALID_MPFID(mpfid)	(TMIN_MPFID <= (mpfid) && (mpfid) <= tmax_mpfid)
+#define VALID_CYCID(cycid)	(TMIN_CYCID <= (cycid) && (cycid) <= tmax_cycid)
+#define VALID_ALMID(almid)	(TMIN_ALMID <= (almid) && (almid) <= tmax_almid)
+#define VALID_ISRID(isrid)	(TMIN_ISRID <= (isrid) && (isrid) <= tmax_isrid)
+
+/*
+ *  オブジェクトIDのチェック（E_ID）
+ */
+#define CHECK_TSKID(tskid) do {								\
+	if (!VALID_TSKID(tskid)) {								\
+		ercd = E_ID;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+#define CHECK_TSKID_SELF(tskid) do {						\
+	if (!(VALID_TSKID(tskid) || (tskid) == TSK_SELF)) {		\
+		ercd = E_ID;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+#define CHECK_SEMID(semid) do {								\
+	if (!VALID_SEMID(semid)) {								\
+		ercd = E_ID;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+#define CHECK_FLGID(flgid) do {								\
+	if (!VALID_FLGID(flgid)) {								\
+		ercd = E_ID;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+#define CHECK_DTQID(dtqid) do {								\
+	if (!VALID_DTQID(dtqid)) {								\
+		ercd = E_ID;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+#define CHECK_PDQID(pdqid) do {								\
+	if (!VALID_PDQID(pdqid)) {								\
+		ercd = E_ID;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+#define CHECK_MBXID(mbxid) do {								\
+	if (!VALID_MBXID(mbxid)) {								\
+		ercd = E_ID;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+#define CHECK_MTXID(mtxid) do {								\
+	if (!VALID_MTXID(mtxid)) {								\
+		ercd = E_ID;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+#define CHECK_MPFID(mpfid) do {								\
+	if (!VALID_MPFID(mpfid)) {								\
+		ercd = E_ID;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+#define CHECK_CYCID(cycid) do {								\
+	if (!VALID_CYCID(cycid)) {								\
+		ercd = E_ID;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+#define CHECK_ALMID(almid) do {								\
+	if (!VALID_ALMID(almid)) {								\
+		ercd = E_ID;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+#define CHECK_ISRID(isrid) do {								\
+	if (!VALID_ISRID(isrid)) {								\
+		ercd = E_ID;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+/*
+ *  呼出しコンテキストのチェック（E_CTX）
+ */
+#define CHECK_TSKCTX() do {									\
+	if (sense_context()) {									\
+		ercd = E_CTX;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+#define CHECK_INTCTX() do {									\
+	if (!sense_context()) {									\
+		ercd = E_CTX;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+/*
+ *  呼出しコンテキストとCPUロック状態のチェック（E_CTX）
+ */
+#define CHECK_TSKCTX_UNL() do {								\
+	if (sense_context() || t_sense_lock()) {				\
+		ercd = E_CTX;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+#define CHECK_INTCTX_UNL() do {								\
+	if (!sense_context() || i_sense_lock()) {				\
+		ercd = E_CTX;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+/*
+ *  ディスパッチ保留状態でないかのチェック（E_CTX）
+ */
+#define CHECK_DISPATCH() do {								\
+	if (sense_context() || t_sense_lock() || !dspflg) {		\
+		ercd = E_CTX;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+/*
+ *  その他のコンテキストエラーのチェック（E_CTX）
+ */
+#define CHECK_CTX(exp) do {									\
+	if (!(exp)) {											\
+		ercd = E_CTX;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+/*
+ *  自タスクを指定していないかのチェック（E_ILUSE）
+ */
+#define CHECK_NONSELF(p_tcb) do {							\
+	if ((p_tcb) == p_runtsk) {								\
+		ercd = E_ILUSE;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+/*
+ *  その他の不正使用エラーのチェック（E_ILUSE）
+ */
+#define CHECK_ILUSE(exp) do {								\
+	if (!(exp)) {											\
+		ercd = E_ILUSE;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+/*
+ *  未サポート機能エラーのチェック（E_NOSPT）
+ */
+#define CHECK_NOSPT(exp) do {								\
+	if (!(exp)) {											\
+		ercd = E_NOSPT;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+/*
+ *  静的なオブジェクト状態エラーのチェック（E_OBJ）
+ */
+#define CHECK_OBJ(exp) do {									\
+	if (!(exp)) {											\
+		ercd = E_OBJ;										\
+		goto error_exit;									\
+	}														\
+} while (false)
+
+#endif /* TOPPERS_CHECK_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/cyclic.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/cyclic.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/cyclic.c	(revision 453)
@@ -0,0 +1,414 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2014 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		周期ハンドラ機能
+ */
+
+#include "kernel_impl.h"
+#include "check.h"
+#include "cyclic.h"
+
+/*
+ *  トレースログマクロのデフォルト定義
+ */
+#ifndef LOG_CYC_ENTER
+#define LOG_CYC_ENTER(p_cyccb)
+#endif /* LOG_CYC_ENTER */
+
+#ifndef LOG_CYC_LEAVE
+#define LOG_CYC_LEAVE(p_cyccb)
+#endif /* LOG_CYC_LEAVE */
+
+#ifndef LOG_ACRE_CYC_ENTER
+#define LOG_ACRE_CYC_ENTER(pk_ccyc)
+#endif /* LOG_ACRE_CYC_ENTER */
+
+#ifndef LOG_ACRE_CYC_LEAVE
+#define LOG_ACRE_CYC_LEAVE(ercd)
+#endif /* LOG_ACRE_CYC_LEAVE */
+
+#ifndef LOG_DEL_CYC_ENTER
+#define LOG_DEL_CYC_ENTER(cycid)
+#endif /* LOG_DEL_CYC_ENTER */
+
+#ifndef LOG_DEL_CYC_LEAVE
+#define LOG_DEL_CYC_LEAVE(ercd)
+#endif /* LOG_DEL_CYC_LEAVE */
+
+#ifndef LOG_STA_CYC_ENTER
+#define LOG_STA_CYC_ENTER(cycid)
+#endif /* LOG_STA_CYC_ENTER */
+
+#ifndef LOG_STA_CYC_LEAVE
+#define LOG_STA_CYC_LEAVE(ercd)
+#endif /* LOG_STA_CYC_LEAVE */
+
+#ifndef LOG_STP_CYC_ENTER
+#define LOG_STP_CYC_ENTER(cycid)
+#endif /* LOG_STP_CYC_ENTER */
+
+#ifndef LOG_STP_CYC_LEAVE
+#define LOG_STP_CYC_LEAVE(ercd)
+#endif /* LOG_STP_CYC_LEAVE */
+
+#ifndef LOG_REF_CYC_ENTER
+#define LOG_REF_CYC_ENTER(cycid, pk_rcyc)
+#endif /* LOG_REF_CYC_ENTER */
+
+#ifndef LOG_REF_CYC_LEAVE
+#define LOG_REF_CYC_LEAVE(ercd, pk_rcyc)
+#endif /* LOG_REF_CYC_LEAVE */
+
+/*
+ *  周期ハンドラの数
+ */
+#define tnum_cyc	((uint_t)(tmax_cycid - TMIN_CYCID + 1))
+#define tnum_scyc	((uint_t)(tmax_scycid - TMIN_CYCID + 1))
+
+/*
+ *  周期ハンドラIDから周期ハンドラ管理ブロックを取り出すためのマクロ
+ */
+#define INDEX_CYC(cycid)	((uint_t)((cycid) - TMIN_CYCID))
+#define get_cyccb(cycid)	(&(cyccb_table[INDEX_CYC(cycid)]))
+
+/*
+ *  周期ハンドラ起動のためのタイムイベントブロックの登録
+ */
+Inline void
+tmevtb_enqueue_cyc(CYCCB *p_cyccb, EVTTIM evttim)
+{
+	tmevtb_enqueue_evttim(&(p_cyccb->tmevtb), evttim,
+								(CBACK) call_cychdr, (void *) p_cyccb);
+	p_cyccb->evttim = evttim;
+}
+
+#ifdef TOPPERS_cycini
+
+/*
+ *  使用していない周期ハンドラ管理ブロックのリスト
+ *
+ *  周期ハンドラ管理ブロックの先頭にはキューにつなぐための領域がないた
+ *  め，タイムイベントブロック（tmevtb）の領域を用いる．
+ */
+QUEUE	free_cyccb;
+
+/*
+ *  周期ハンドラ機能の初期化
+ */
+void
+initialize_cyclic(void)
+{
+	uint_t	i, j;
+	CYCCB	*p_cyccb;
+	CYCINIB	*p_cycinib;
+
+	for (i = 0; i < tnum_scyc; i++) {
+		p_cyccb = &(cyccb_table[i]);
+		p_cyccb->p_cycinib = &(cycinib_table[i]);
+		if ((p_cyccb->p_cycinib->cycatr & TA_STA) != 0U) {
+			p_cyccb->cycsta = true;
+			tmevtb_enqueue_cyc(p_cyccb, (EVTTIM)(p_cyccb->p_cycinib->cycphs));
+		}
+		else {
+			p_cyccb->cycsta = false;
+		}
+	}
+	queue_initialize(&free_cyccb);
+	for (j = 0; i < tnum_cyc; i++, j++) {
+		p_cyccb = &(cyccb_table[i]);
+		p_cycinib = &(acycinib_table[j]);
+		p_cycinib->cycatr = TA_NOEXS;
+		p_cyccb->p_cycinib = ((const CYCINIB *) p_cycinib);
+		queue_insert_prev(&free_cyccb, ((QUEUE *) &(p_cyccb->tmevtb)));
+	}
+}
+
+#endif /* TOPPERS_cycini */
+
+/*
+ *  周期ハンドラの生成
+ */
+#ifdef TOPPERS_acre_cyc
+
+ER_UINT
+acre_cyc(const T_CCYC *pk_ccyc)
+{
+	CYCCB	*p_cyccb;
+	CYCINIB	*p_cycinib;
+	ER		ercd;
+
+	LOG_ACRE_CYC_ENTER(pk_ccyc);
+	CHECK_TSKCTX_UNL();
+	CHECK_RSATR(pk_ccyc->cycatr, TA_STA);
+	CHECK_ALIGN_FUNC(pk_ccyc->cychdr);
+	CHECK_NONNULL_FUNC(pk_ccyc->cychdr);
+	CHECK_PAR(0 < pk_ccyc->cyctim && pk_ccyc->cyctim <= TMAX_RELTIM);
+	CHECK_PAR(0 <= pk_ccyc->cycphs && pk_ccyc->cycphs <= TMAX_RELTIM);
+
+	t_lock_cpu();
+	if (tnum_cyc == 0 || queue_empty(&free_cyccb)) {
+		ercd = E_NOID;
+	}
+	else {
+		p_cyccb = ((CYCCB *)(((char *) queue_delete_next(&free_cyccb))
+												- offsetof(CYCCB, tmevtb)));
+		p_cycinib = (CYCINIB *)(p_cyccb->p_cycinib);
+		p_cycinib->cycatr = pk_ccyc->cycatr;
+		p_cycinib->exinf = pk_ccyc->exinf;
+		p_cycinib->cychdr = pk_ccyc->cychdr;
+		p_cycinib->cyctim = pk_ccyc->cyctim;
+		p_cycinib->cycphs = pk_ccyc->cycphs;
+
+		if ((p_cyccb->p_cycinib->cycatr & TA_STA) != 0U) {
+			p_cyccb->cycsta = true;
+			tmevtb_enqueue_cyc(p_cyccb,
+								base_time + p_cyccb->p_cycinib->cycphs);
+		}
+		else {
+			p_cyccb->cycsta = false;
+		}
+		ercd = CYCID(p_cyccb);
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_ACRE_CYC_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_acre_cyc */
+
+/*
+ *  周期ハンドラの削除
+ */
+#ifdef TOPPERS_del_cyc
+
+ER
+del_cyc(ID cycid)
+{
+	CYCCB	*p_cyccb;
+	CYCINIB	*p_cycinib;
+	ER		ercd;
+
+	LOG_DEL_CYC_ENTER(cycid);
+	CHECK_TSKCTX_UNL();
+	CHECK_CYCID(cycid);
+	p_cyccb = get_cyccb(cycid);
+
+	t_lock_cpu();
+	if (p_cyccb->p_cycinib->cycatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (CYCID(p_cyccb) > tmax_scycid) {
+		if (p_cyccb->cycsta) {
+			p_cyccb->cycsta = false;
+			tmevtb_dequeue(&(p_cyccb->tmevtb));
+		}
+
+		p_cycinib = (CYCINIB *)(p_cyccb->p_cycinib);
+		p_cycinib->cycatr = TA_NOEXS;
+		queue_insert_prev(&free_cyccb, ((QUEUE *) &(p_cyccb->tmevtb)));
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_OBJ;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_DEL_CYC_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_del_cyc */
+
+/*
+ *  周期ハンドラの動作開始
+ */
+#ifdef TOPPERS_sta_cyc
+
+ER
+sta_cyc(ID cycid)
+{
+	CYCCB	*p_cyccb;
+	ER		ercd;
+
+	LOG_STA_CYC_ENTER(cycid);
+	CHECK_TSKCTX_UNL();
+	CHECK_CYCID(cycid);
+	p_cyccb = get_cyccb(cycid);
+
+	t_lock_cpu();
+	if (p_cyccb->p_cycinib->cycatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		if (p_cyccb->cycsta) {
+			tmevtb_dequeue(&(p_cyccb->tmevtb));
+		}
+		else {
+			p_cyccb->cycsta = true;
+		}
+		tmevtb_enqueue_cyc(p_cyccb, base_time + p_cyccb->p_cycinib->cycphs);
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_STA_CYC_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_sta_cyc */
+
+/*
+ *  周期ハンドラの動作停止
+ */
+#ifdef TOPPERS_stp_cyc
+
+ER
+stp_cyc(ID cycid)
+{
+	CYCCB	*p_cyccb;
+	ER		ercd;
+
+	LOG_STP_CYC_ENTER(cycid);
+	CHECK_TSKCTX_UNL();
+	CHECK_CYCID(cycid);
+	p_cyccb = get_cyccb(cycid);
+
+	t_lock_cpu();
+	if (p_cyccb->p_cycinib->cycatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		if (p_cyccb->cycsta) {
+			p_cyccb->cycsta = false;
+			tmevtb_dequeue(&(p_cyccb->tmevtb));
+		}
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_STP_CYC_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_stp_cyc */
+
+/*
+ *  周期ハンドラの状態参照
+ */
+#ifdef TOPPERS_ref_cyc
+
+ER
+ref_cyc(ID cycid, T_RCYC *pk_rcyc)
+{
+	CYCCB	*p_cyccb;
+	ER		ercd;
+    
+	LOG_REF_CYC_ENTER(cycid, pk_rcyc);
+	CHECK_TSKCTX_UNL();
+	CHECK_CYCID(cycid);
+	p_cyccb = get_cyccb(cycid);
+
+	t_lock_cpu();
+	if (p_cyccb->p_cycinib->cycatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		if (p_cyccb->cycsta) {
+			pk_rcyc->cycstat = TCYC_STA;
+			pk_rcyc->lefttim = tmevt_lefttim(&(p_cyccb->tmevtb));
+		}
+		else {
+			pk_rcyc->cycstat = TCYC_STP;
+		}
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_REF_CYC_LEAVE(ercd, pk_rcyc);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ref_cyc */
+
+/*
+ *  周期ハンドラ起動ルーチン
+ */
+#ifdef TOPPERS_cyccal
+
+void
+call_cychdr(CYCCB *p_cyccb)
+{
+	PRI		saved_ipm;
+
+	/*
+	 *  次回の起動のためのタイムイベントブロックを登録する．
+	 *
+	 *  同じタイムティックで周期ハンドラを再度起動すべき場合には，この
+	 *  関数からsignal_timeに戻った後に，再度この関数が呼ばれることにな
+	 *  る．
+	 */
+	tmevtb_enqueue_cyc(p_cyccb, p_cyccb->evttim + p_cyccb->p_cycinib->cyctim);
+
+	/*
+	 *  周期ハンドラを，CPUロック解除状態で呼び出す．
+	 */
+	saved_ipm = i_get_ipm();
+	i_unlock_cpu();
+
+	LOG_CYC_ENTER(p_cyccb);
+	(*((CYCHDR)(p_cyccb->p_cycinib->cychdr)))(p_cyccb->p_cycinib->exinf);
+	LOG_CYC_LEAVE(p_cyccb);
+
+	if (!i_sense_lock()) {
+		i_lock_cpu();
+	}
+	i_set_ipm(saved_ipm);
+}
+
+#endif /* TOPPERS_cyccal */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/cyclic.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/cyclic.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/cyclic.h	(revision 453)
@@ -0,0 +1,111 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		周期ハンドラ機能
+ */
+
+#ifndef TOPPERS_CYCLIC_H
+#define TOPPERS_CYCLIC_H
+
+#include <queue.h>
+#include "time_event.h"
+
+/*
+ *  周期ハンドラ初期化ブロック
+ */
+typedef struct cyclic_handler_initialization_block {
+	ATR			cycatr;			/* 周期ハンドラ属性 */
+	intptr_t	exinf;			/* 周期ハンドラの拡張情報 */
+	CYCHDR		cychdr;			/* 周期ハンドラの起動番地 */
+	RELTIM		cyctim;			/* 周期ハンドラの起動周期 */
+	RELTIM		cycphs;			/* 周期ハンドラの起動位相 */
+} CYCINIB;
+
+/*
+ *  周期ハンドラ管理ブロック
+ */
+typedef struct cyclic_handler_control_block {
+	const CYCINIB *p_cycinib;	/* 初期化ブロックへのポインタ */
+	bool_t		cycsta;			/* 周期ハンドラの動作状態 */
+	EVTTIM		evttim;			/* 次に周期ハンドラを起動する時刻 */
+	TMEVTB		tmevtb;			/* タイムイベントブロック */
+} CYCCB;
+
+/*
+ *  使用していない周期ハンドラ管理ブロックのリスト
+ */
+extern QUEUE	free_cyccb;
+
+/*
+ *  周期ハンドラIDの最大値（kernel_cfg.c）
+ */
+extern const ID	tmax_cycid;
+extern const ID	tmax_scycid;
+
+/*
+ *  周期ハンドラ初期化ブロックのエリア（kernel_cfg.c）
+ */
+extern const CYCINIB	cycinib_table[];
+extern CYCINIB			acycinib_table[];
+
+/*
+ *  周期ハンドラ管理ブロックのエリア（kernel_cfg.c）
+ */
+extern CYCCB	cyccb_table[];
+
+/*
+ *  周期ハンドラ管理ブロックから周期ハンドラIDを取り出すためのマクロ
+ */
+#define	CYCID(p_cyccb)	((ID)(((p_cyccb) - cyccb_table) + TMIN_CYCID))
+
+/*
+ *  周期ハンドラ機能の初期化
+ */
+extern void	initialize_cyclic(void);
+
+/*
+ *  周期ハンドラ起動ルーチン
+ */
+extern void	call_cychdr(CYCCB *p_cyccb);
+
+#endif /* TOPPERS_CYCLIC_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/dataqueue.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/dataqueue.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/dataqueue.c	(revision 453)
@@ -0,0 +1,932 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2017 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		データキュー機能
+ */
+
+#include "kernel_impl.h"
+#include "check.h"
+#include "task.h"
+#include "wait.h"
+#include "dataqueue.h"
+
+/*
+ *  トレースログマクロのデフォルト定義
+ */
+#ifndef LOG_ACRE_DTQ_ENTER
+#define LOG_ACRE_DTQ_ENTER(pk_cdtq)
+#endif /* LOG_ACRE_DTQ_ENTER */
+
+#ifndef LOG_ACRE_DTQ_LEAVE
+#define LOG_ACRE_DTQ_LEAVE(ercd)
+#endif /* LOG_ACRE_DTQ_LEAVE */
+
+#ifndef LOG_DEL_DTQ_ENTER
+#define LOG_DEL_DTQ_ENTER(dtqid)
+#endif /* LOG_DEL_DTQ_ENTER */
+
+#ifndef LOG_DEL_DTQ_LEAVE
+#define LOG_DEL_DTQ_LEAVE(ercd)
+#endif /* LOG_DEL_DTQ_LEAVE */
+
+#ifndef LOG_SND_DTQ_ENTER
+#define LOG_SND_DTQ_ENTER(dtqid, data)
+#endif /* LOG_SND_DTQ_ENTER */
+
+#ifndef LOG_SND_DTQ_LEAVE
+#define LOG_SND_DTQ_LEAVE(ercd)
+#endif /* LOG_SND_DTQ_LEAVE */
+
+#ifndef LOG_PSND_DTQ_ENTER
+#define LOG_PSND_DTQ_ENTER(dtqid, data)
+#endif /* LOG_PSND_DTQ_ENTER */
+
+#ifndef LOG_PSND_DTQ_LEAVE
+#define LOG_PSND_DTQ_LEAVE(ercd)
+#endif /* LOG_PSND_DTQ_LEAVE */
+
+#ifndef LOG_IPSND_DTQ_ENTER
+#define LOG_IPSND_DTQ_ENTER(dtqid, data)
+#endif /* LOG_IPSND_DTQ_ENTER */
+
+#ifndef LOG_IPSND_DTQ_LEAVE
+#define LOG_IPSND_DTQ_LEAVE(ercd)
+#endif /* LOG_IPSND_DTQ_LEAVE */
+
+#ifndef LOG_TSND_DTQ_ENTER
+#define LOG_TSND_DTQ_ENTER(dtqid, data, tmout)
+#endif /* LOG_TSND_DTQ_ENTER */
+
+#ifndef LOG_TSND_DTQ_LEAVE
+#define LOG_TSND_DTQ_LEAVE(ercd)
+#endif /* LOG_TSND_DTQ_LEAVE */
+
+#ifndef LOG_FSND_DTQ_ENTER
+#define LOG_FSND_DTQ_ENTER(dtqid, data)
+#endif /* LOG_FSND_DTQ_ENTER */
+
+#ifndef LOG_FSND_DTQ_LEAVE
+#define LOG_FSND_DTQ_LEAVE(ercd)
+#endif /* LOG_FSND_DTQ_LEAVE */
+
+#ifndef LOG_IFSND_DTQ_ENTER
+#define LOG_IFSND_DTQ_ENTER(dtqid, data)
+#endif /* LOG_IFSND_DTQ_ENTER */
+
+#ifndef LOG_IFSND_DTQ_LEAVE
+#define LOG_IFSND_DTQ_LEAVE(ercd)
+#endif /* LOG_IFSND_DTQ_LEAVE */
+
+#ifndef LOG_RCV_DTQ_ENTER
+#define LOG_RCV_DTQ_ENTER(dtqid, p_data)
+#endif /* LOG_RCV_DTQ_ENTER */
+
+#ifndef LOG_RCV_DTQ_LEAVE
+#define LOG_RCV_DTQ_LEAVE(ercd, data)
+#endif /* LOG_RCV_DTQ_LEAVE */
+
+#ifndef LOG_PRCV_DTQ_ENTER
+#define LOG_PRCV_DTQ_ENTER(dtqid, p_data)
+#endif /* LOG_PRCV_DTQ_ENTER */
+
+#ifndef LOG_PRCV_DTQ_LEAVE
+#define LOG_PRCV_DTQ_LEAVE(ercd, data)
+#endif /* LOG_PRCV_DTQ_LEAVE */
+
+#ifndef LOG_TRCV_DTQ_ENTER
+#define LOG_TRCV_DTQ_ENTER(dtqid, p_data, tmout)
+#endif /* LOG_TRCV_DTQ_ENTER */
+
+#ifndef LOG_TRCV_DTQ_LEAVE
+#define LOG_TRCV_DTQ_LEAVE(ercd, data)
+#endif /* LOG_TRCV_DTQ_LEAVE */
+
+#ifndef LOG_INI_DTQ_ENTER
+#define LOG_INI_DTQ_ENTER(dtqid)
+#endif /* LOG_INI_DTQ_ENTER */
+
+#ifndef LOG_INI_DTQ_LEAVE
+#define LOG_INI_DTQ_LEAVE(ercd)
+#endif /* LOG_INI_DTQ_LEAVE */
+
+#ifndef LOG_REF_DTQ_ENTER
+#define LOG_REF_DTQ_ENTER(dtqid, pk_rdtq)
+#endif /* LOG_REF_DTQ_ENTER */
+
+#ifndef LOG_REF_DTQ_LEAVE
+#define LOG_REF_DTQ_LEAVE(ercd, pk_rdtq)
+#endif /* LOG_REF_DTQ_LEAVE */
+
+/*
+ *  データキューの数
+ */
+#define tnum_dtq	((uint_t)(tmax_dtqid - TMIN_DTQID + 1))
+#define tnum_sdtq	((uint_t)(tmax_sdtqid - TMIN_DTQID + 1))
+
+/*
+ *  データキューIDからデータキュー管理ブロックを取り出すためのマクロ
+ */
+#define INDEX_DTQ(dtqid)	((uint_t)((dtqid) - TMIN_DTQID))
+#define get_dtqcb(dtqid)	(&(dtqcb_table[INDEX_DTQ(dtqid)]))
+
+#ifdef TOPPERS_dtqini
+
+/*
+ *  使用していないデータキュー管理ブロックのリスト
+ */
+QUEUE	free_dtqcb;
+
+/*
+ *  データキュー機能の初期化
+ */
+void
+initialize_dataqueue(void)
+{
+	uint_t	i, j;
+	DTQCB	*p_dtqcb;
+	DTQINIB	*p_dtqinib;
+
+	for (i = 0; i < tnum_sdtq; i++) {
+		p_dtqcb = &(dtqcb_table[i]);
+		queue_initialize(&(p_dtqcb->swait_queue));
+		p_dtqcb->p_dtqinib = &(dtqinib_table[i]);
+		queue_initialize(&(p_dtqcb->rwait_queue));
+		p_dtqcb->count = 0U;
+		p_dtqcb->head = 0U;
+		p_dtqcb->tail = 0U;
+	}
+	queue_initialize(&free_dtqcb);
+	for (j = 0; i < tnum_dtq; i++, j++) {
+		p_dtqcb = &(dtqcb_table[i]);
+		p_dtqinib = &(adtqinib_table[j]);
+		p_dtqinib->dtqatr = TA_NOEXS;
+		p_dtqcb->p_dtqinib = ((const DTQINIB *) p_dtqinib);
+		queue_insert_prev(&free_dtqcb, &(p_dtqcb->swait_queue));
+	}
+}
+
+#endif /* TOPPERS_dtqini */
+
+/*
+ *  データキュー管理領域へのデータの格納
+ */
+#ifdef TOPPERS_dtqenq
+
+void
+enqueue_data(DTQCB *p_dtqcb, intptr_t data)
+{
+	(p_dtqcb->p_dtqinib->p_dtqmb + p_dtqcb->tail)->data = data;
+	p_dtqcb->count++;
+	p_dtqcb->tail++;
+	if (p_dtqcb->tail >= p_dtqcb->p_dtqinib->dtqcnt) {
+		p_dtqcb->tail = 0U;
+	}
+}
+
+#endif /* TOPPERS_dtqenq */
+
+/*
+ *  データキュー管理領域へのデータの強制格納
+ */
+#ifdef TOPPERS_dtqfenq
+
+void
+force_enqueue_data(DTQCB *p_dtqcb, intptr_t data)
+{
+	(p_dtqcb->p_dtqinib->p_dtqmb + p_dtqcb->tail)->data = data;
+	p_dtqcb->tail++;
+	if (p_dtqcb->tail >= p_dtqcb->p_dtqinib->dtqcnt) {
+		p_dtqcb->tail = 0U;
+	}
+	if (p_dtqcb->count < p_dtqcb->p_dtqinib->dtqcnt) {
+		p_dtqcb->count++;
+	}
+	else {
+		p_dtqcb->head = p_dtqcb->tail;
+	}
+}
+
+#endif /* TOPPERS_dtqfenq */
+
+/*
+ *  データキュー管理領域からのデータの取出し
+ */
+#ifdef TOPPERS_dtqdeq
+
+void
+dequeue_data(DTQCB *p_dtqcb, intptr_t *p_data)
+{
+	*p_data = (p_dtqcb->p_dtqinib->p_dtqmb + p_dtqcb->head)->data;
+	p_dtqcb->count--;
+	p_dtqcb->head++;
+	if (p_dtqcb->head >= p_dtqcb->p_dtqinib->dtqcnt) {
+		p_dtqcb->head = 0U;
+	}
+}
+
+#endif /* TOPPERS_dtqdeq */
+
+/*
+ *  データキューへのデータ送信
+ */
+#ifdef TOPPERS_dtqsnd
+
+bool_t
+send_data(DTQCB *p_dtqcb, intptr_t data, bool_t *p_dspreq)
+{
+	TCB		*p_tcb;
+
+	if (!queue_empty(&(p_dtqcb->rwait_queue))) {
+		p_tcb = (TCB *) queue_delete_next(&(p_dtqcb->rwait_queue));
+		((WINFO_DTQ *)(p_tcb->p_winfo))->data = data;
+		*p_dspreq = wait_complete(p_tcb);
+		return(true);
+	}
+	else if (p_dtqcb->count < p_dtqcb->p_dtqinib->dtqcnt) {
+		enqueue_data(p_dtqcb, data);
+		*p_dspreq = false;
+		return(true);
+	}
+	else {
+		return(false);
+	}
+}
+
+#endif /* TOPPERS_dtqsnd */
+
+/*
+ *  データキューへのデータ強制送信
+ */
+#ifdef TOPPERS_dtqfsnd
+
+bool_t
+force_send_data(DTQCB *p_dtqcb, intptr_t data)
+{
+	TCB		*p_tcb;
+
+	if (!queue_empty(&(p_dtqcb->rwait_queue))) {
+		p_tcb = (TCB *) queue_delete_next(&(p_dtqcb->rwait_queue));
+		((WINFO_DTQ *)(p_tcb->p_winfo))->data = data;
+		return(wait_complete(p_tcb));
+	}
+	else {
+		force_enqueue_data(p_dtqcb, data);
+		return(false);
+	}
+}
+
+#endif /* TOPPERS_dtqfsnd */
+
+/*
+ *  データキューからのデータ受信
+ */
+#ifdef TOPPERS_dtqrcv
+
+bool_t
+receive_data(DTQCB *p_dtqcb, intptr_t *p_data, bool_t *p_dspreq)
+{
+	TCB		*p_tcb;
+	intptr_t data;
+
+	if (p_dtqcb->count > 0U) {
+		dequeue_data(p_dtqcb, p_data);
+		if (!queue_empty(&(p_dtqcb->swait_queue))) {
+			p_tcb = (TCB *) queue_delete_next(&(p_dtqcb->swait_queue));
+			data = ((WINFO_DTQ *)(p_tcb->p_winfo))->data;
+			enqueue_data(p_dtqcb, data);
+			*p_dspreq = wait_complete(p_tcb);
+		}
+		else {
+			*p_dspreq = false;
+		}
+		return(true);
+	}
+	else if (!queue_empty(&(p_dtqcb->swait_queue))) {
+		p_tcb = (TCB *) queue_delete_next(&(p_dtqcb->swait_queue));
+		*p_data = ((WINFO_DTQ *)(p_tcb->p_winfo))->data;
+		*p_dspreq = wait_complete(p_tcb);
+		return(true);
+	}
+	else {
+		return(false);
+	}
+}
+
+#endif /* TOPPERS_dtqrcv */
+
+/*
+ *  データキューの生成
+ */
+#ifdef TOPPERS_acre_dtq
+
+ER_UINT
+acre_dtq(const T_CDTQ *pk_cdtq)
+{
+	DTQCB	*p_dtqcb;
+	DTQINIB	*p_dtqinib;
+	ATR		dtqatr;
+	DTQMB	*p_dtqmb;
+	ER		ercd;
+
+	LOG_ACRE_DTQ_ENTER(pk_cdtq);
+	CHECK_TSKCTX_UNL();
+	CHECK_RSATR(pk_cdtq->dtqatr, TA_TPRI);
+	if (pk_cdtq->dtqmb != NULL) {
+		CHECK_ALIGN_MB(pk_cdtq->dtqmb);
+	}
+	dtqatr = pk_cdtq->dtqatr;
+	p_dtqmb = pk_cdtq->dtqmb;
+
+	t_lock_cpu();
+	if (tnum_dtq == 0 || queue_empty(&free_dtqcb)) {
+		ercd = E_NOID;
+	}
+	else {
+		if (pk_cdtq->dtqcnt != 0 && p_dtqmb == NULL) {
+			p_dtqmb = kernel_malloc(sizeof(DTQMB) * pk_cdtq->dtqcnt);
+			dtqatr |= TA_MBALLOC;
+		}
+		if (pk_cdtq->dtqcnt != 0 && p_dtqmb == NULL) {
+			ercd = E_NOMEM;
+		}
+		else {
+			p_dtqcb = ((DTQCB *) queue_delete_next(&free_dtqcb));
+			p_dtqinib = (DTQINIB *)(p_dtqcb->p_dtqinib);
+			p_dtqinib->dtqatr = dtqatr;
+			p_dtqinib->dtqcnt = pk_cdtq->dtqcnt;
+			p_dtqinib->p_dtqmb = p_dtqmb;
+
+			queue_initialize(&(p_dtqcb->swait_queue));
+			queue_initialize(&(p_dtqcb->rwait_queue));
+			p_dtqcb->count = 0U;
+			p_dtqcb->head = 0U;
+			p_dtqcb->tail = 0U;
+			ercd = DTQID(p_dtqcb);
+		}
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_ACRE_DTQ_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_acre_dtq */
+
+/*
+ *  データキューの削除
+ */
+#ifdef TOPPERS_del_dtq
+
+ER
+del_dtq(ID dtqid)
+{
+	DTQCB	*p_dtqcb;
+	DTQINIB	*p_dtqinib;
+	bool_t	dspreq;
+	ER		ercd;
+
+	LOG_DEL_DTQ_ENTER(dtqid);
+	CHECK_TSKCTX_UNL();
+	CHECK_DTQID(dtqid);
+	p_dtqcb = get_dtqcb(dtqid);
+
+	t_lock_cpu();
+	if (p_dtqcb->p_dtqinib->dtqatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (DTQID(p_dtqcb) > tmax_sdtqid) {
+		dspreq = init_wait_queue(&(p_dtqcb->swait_queue));
+		if (init_wait_queue(&(p_dtqcb->rwait_queue))) {
+			dspreq = true;
+		}
+		p_dtqinib = (DTQINIB *)(p_dtqcb->p_dtqinib);
+		if ((p_dtqinib->dtqatr & TA_MBALLOC) != 0U) {
+			kernel_free(p_dtqinib->p_dtqmb);
+		}
+		p_dtqinib->dtqatr = TA_NOEXS;
+		queue_insert_prev(&free_dtqcb, &(p_dtqcb->swait_queue));
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_OBJ;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_DEL_DTQ_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_del_dtq */
+
+/*
+ *  データキューへの送信
+ */
+#ifdef TOPPERS_snd_dtq
+
+ER
+snd_dtq(ID dtqid, intptr_t data)
+{
+	DTQCB	*p_dtqcb;
+	WINFO_DTQ winfo_dtq;
+	bool_t	dspreq;
+	ER		ercd;
+
+	LOG_SND_DTQ_ENTER(dtqid, data);
+	CHECK_DISPATCH();
+	CHECK_DTQID(dtqid);
+	p_dtqcb = get_dtqcb(dtqid);
+
+	t_lock_cpu();
+	if (p_dtqcb->p_dtqinib->dtqatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (send_data(p_dtqcb, data, &dspreq)) {
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	else {
+		winfo_dtq.data = data;
+		p_runtsk->tstat = (TS_WAITING | TS_WAIT_SDTQ);
+		wobj_make_wait((WOBJCB *) p_dtqcb, (WINFO_WOBJ *) &winfo_dtq);
+		dispatch();
+		ercd = winfo_dtq.winfo.wercd;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_SND_DTQ_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_snd_dtq */
+
+/*
+ *  データキューへの送信（ポーリング）
+ */
+#ifdef TOPPERS_psnd_dtq
+
+ER
+psnd_dtq(ID dtqid, intptr_t data)
+{
+	DTQCB	*p_dtqcb;
+	bool_t	dspreq;
+	ER		ercd;
+
+	LOG_PSND_DTQ_ENTER(dtqid, data);
+	CHECK_TSKCTX_UNL();
+	CHECK_DTQID(dtqid);
+	p_dtqcb = get_dtqcb(dtqid);
+
+	t_lock_cpu();
+	if (p_dtqcb->p_dtqinib->dtqatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (send_data(p_dtqcb, data, &dspreq)) {
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_TMOUT;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_PSND_DTQ_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_psnd_dtq */
+
+/*
+ *  データキューへの送信（ポーリング，非タスクコンテキスト用）
+ */
+#ifdef TOPPERS_ipsnd_dtq
+
+ER
+ipsnd_dtq(ID dtqid, intptr_t data)
+{
+	DTQCB	*p_dtqcb;
+	bool_t	dspreq;
+	ER		ercd;
+
+	LOG_IPSND_DTQ_ENTER(dtqid, data);
+	CHECK_INTCTX_UNL();
+	CHECK_DTQID(dtqid);
+	p_dtqcb = get_dtqcb(dtqid);
+
+	i_lock_cpu();
+	if (p_dtqcb->p_dtqinib->dtqatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (send_data(p_dtqcb, data, &dspreq)) {
+		if (dspreq) {
+			reqflg = true;
+		}
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_TMOUT;
+	}
+	i_unlock_cpu();
+
+  error_exit:
+	LOG_IPSND_DTQ_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ipsnd_dtq */
+
+/*
+ *  データキューへの送信（タイムアウトあり）
+ */
+#ifdef TOPPERS_tsnd_dtq
+
+ER
+tsnd_dtq(ID dtqid, intptr_t data, TMO tmout)
+{
+	DTQCB	*p_dtqcb;
+	WINFO_DTQ winfo_dtq;
+	TMEVTB	tmevtb;
+	bool_t	dspreq;
+	ER		ercd;
+
+	LOG_TSND_DTQ_ENTER(dtqid, data, tmout);
+	CHECK_DISPATCH();
+	CHECK_DTQID(dtqid);
+	CHECK_TMOUT(tmout);
+	p_dtqcb = get_dtqcb(dtqid);
+
+	t_lock_cpu();
+	if (p_dtqcb->p_dtqinib->dtqatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (send_data(p_dtqcb, data, &dspreq)) {
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	else if (tmout == TMO_POL) {
+		ercd = E_TMOUT;
+	}
+	else {
+		winfo_dtq.data = data;
+		p_runtsk->tstat = (TS_WAITING | TS_WAIT_SDTQ);
+		wobj_make_wait_tmout((WOBJCB *) p_dtqcb, (WINFO_WOBJ *) &winfo_dtq,
+														&tmevtb, tmout);
+		dispatch();
+		ercd = winfo_dtq.winfo.wercd;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_TSND_DTQ_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_tsnd_dtq */
+
+/*
+ *  データキューへの強制送信
+ */
+#ifdef TOPPERS_fsnd_dtq
+
+ER
+fsnd_dtq(ID dtqid, intptr_t data)
+{
+	DTQCB	*p_dtqcb;	
+	ER		ercd;
+
+	LOG_FSND_DTQ_ENTER(dtqid, data);
+	CHECK_TSKCTX_UNL();
+	CHECK_DTQID(dtqid);
+	p_dtqcb = get_dtqcb(dtqid);
+
+	t_lock_cpu();
+	if (p_dtqcb->p_dtqinib->dtqatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (!(p_dtqcb->p_dtqinib->dtqcnt > 0U)) {
+		ercd = E_ILUSE;
+	}
+	else {
+		if (force_send_data(p_dtqcb, data)) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_FSND_DTQ_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_fsnd_dtq */
+
+/*
+ *  データキューへの強制送信（非タスクコンテキスト用）
+ */
+#ifdef TOPPERS_ifsnd_dtq
+
+ER
+ifsnd_dtq(ID dtqid, intptr_t data)
+{
+	DTQCB	*p_dtqcb;
+	ER		ercd;
+
+	LOG_IFSND_DTQ_ENTER(dtqid, data);
+	CHECK_INTCTX_UNL();
+	CHECK_DTQID(dtqid);
+	p_dtqcb = get_dtqcb(dtqid);
+
+	i_lock_cpu();
+	if (p_dtqcb->p_dtqinib->dtqatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (!(p_dtqcb->p_dtqinib->dtqcnt > 0U)) {
+		ercd = E_ILUSE;
+	}
+	else {
+		if (force_send_data(p_dtqcb, data)) {
+			reqflg = true;
+		}
+		ercd = E_OK;
+	}
+	i_unlock_cpu();
+
+  error_exit:
+	LOG_IFSND_DTQ_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ifsnd_dtq */
+
+/*
+ *  データキューからの受信
+ */
+#ifdef TOPPERS_rcv_dtq
+
+ER
+rcv_dtq(ID dtqid, intptr_t *p_data)
+{
+	DTQCB	*p_dtqcb;
+	WINFO_DTQ winfo_dtq;
+	bool_t	dspreq;
+	ER		ercd;
+
+	LOG_RCV_DTQ_ENTER(dtqid, p_data);
+	CHECK_DISPATCH();
+	CHECK_DTQID(dtqid);
+	p_dtqcb = get_dtqcb(dtqid);
+
+	t_lock_cpu();
+	if (p_dtqcb->p_dtqinib->dtqatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (receive_data(p_dtqcb, p_data, &dspreq)) {
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	else {
+		p_runtsk->tstat = (TS_WAITING | TS_WAIT_RDTQ);
+		make_wait(&(winfo_dtq.winfo));
+		queue_insert_prev(&(p_dtqcb->rwait_queue), &(p_runtsk->task_queue));
+		winfo_dtq.p_dtqcb = p_dtqcb;
+		LOG_TSKSTAT(p_runtsk);
+		dispatch();
+		ercd = winfo_dtq.winfo.wercd;
+		if (ercd == E_OK) {
+			*p_data = winfo_dtq.data;
+		}
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_RCV_DTQ_LEAVE(ercd, *p_data);
+	return(ercd);
+}
+
+#endif /* TOPPERS_rcv_dtq */
+
+/*
+ *  データキューからの受信（ポーリング）
+ */
+#ifdef TOPPERS_prcv_dtq
+
+ER
+prcv_dtq(ID dtqid, intptr_t *p_data)
+{
+	DTQCB	*p_dtqcb;
+	bool_t	dspreq;
+	ER		ercd;
+
+	LOG_PRCV_DTQ_ENTER(dtqid, p_data);
+	CHECK_TSKCTX_UNL();
+	CHECK_DTQID(dtqid);
+	p_dtqcb = get_dtqcb(dtqid);
+
+	t_lock_cpu();
+	if (p_dtqcb->p_dtqinib->dtqatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (receive_data(p_dtqcb, p_data, &dspreq)) {
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_TMOUT;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_PRCV_DTQ_LEAVE(ercd, *p_data);
+	return(ercd);
+}
+
+#endif /* TOPPERS_prcv_dtq */
+
+/*
+ *  データキューからの受信（タイムアウトあり）
+ */
+#ifdef TOPPERS_trcv_dtq
+
+ER
+trcv_dtq(ID dtqid, intptr_t *p_data, TMO tmout)
+{
+	DTQCB	*p_dtqcb;
+	WINFO_DTQ winfo_dtq;
+	TMEVTB	tmevtb;
+	bool_t	dspreq;
+	ER		ercd;
+
+	LOG_TRCV_DTQ_ENTER(dtqid, p_data, tmout);
+	CHECK_DISPATCH();
+	CHECK_DTQID(dtqid);
+	CHECK_TMOUT(tmout);
+	p_dtqcb = get_dtqcb(dtqid);
+
+	t_lock_cpu();
+	if (p_dtqcb->p_dtqinib->dtqatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (receive_data(p_dtqcb, p_data, &dspreq)) {
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	else if (tmout == TMO_POL) {
+		ercd = E_TMOUT;
+	}
+	else {
+		p_runtsk->tstat = (TS_WAITING | TS_WAIT_RDTQ);
+		make_wait_tmout(&(winfo_dtq.winfo), &tmevtb, tmout);
+		queue_insert_prev(&(p_dtqcb->rwait_queue), &(p_runtsk->task_queue));
+		winfo_dtq.p_dtqcb = p_dtqcb;
+		LOG_TSKSTAT(p_runtsk);
+		dispatch();
+		ercd = winfo_dtq.winfo.wercd;
+		if (ercd == E_OK) {
+			*p_data = winfo_dtq.data;
+		}
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_TRCV_DTQ_LEAVE(ercd, *p_data);
+	return(ercd);
+}
+
+#endif /* TOPPERS_trcv_dtq */
+
+/*
+ *  データキューの再初期化
+ */
+#ifdef TOPPERS_ini_dtq
+
+ER
+ini_dtq(ID dtqid)
+{
+	DTQCB	*p_dtqcb;
+	bool_t	dspreq;
+	ER		ercd;
+    
+	LOG_INI_DTQ_ENTER(dtqid);
+	CHECK_TSKCTX_UNL();
+	CHECK_DTQID(dtqid);
+	p_dtqcb = get_dtqcb(dtqid);
+
+	t_lock_cpu();
+	if (p_dtqcb->p_dtqinib->dtqatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		dspreq = init_wait_queue(&(p_dtqcb->swait_queue));
+		if (init_wait_queue(&(p_dtqcb->rwait_queue))) {
+			dspreq = true;
+		}
+		p_dtqcb->count = 0U;
+		p_dtqcb->head = 0U;
+		p_dtqcb->tail = 0U;
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_INI_DTQ_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ini_dtq */
+
+/*
+ *  データキューの状態参照
+ */
+#ifdef TOPPERS_ref_dtq
+
+ER
+ref_dtq(ID dtqid, T_RDTQ *pk_rdtq)
+{
+	DTQCB	*p_dtqcb;
+	ER		ercd;
+    
+	LOG_REF_DTQ_ENTER(dtqid, pk_rdtq);
+	CHECK_TSKCTX_UNL();
+	CHECK_DTQID(dtqid);
+	p_dtqcb = get_dtqcb(dtqid);
+
+	t_lock_cpu();
+	if (p_dtqcb->p_dtqinib->dtqatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		pk_rdtq->stskid = wait_tskid(&(p_dtqcb->swait_queue));
+		pk_rdtq->rtskid = wait_tskid(&(p_dtqcb->rwait_queue));
+		pk_rdtq->sdtqcnt = p_dtqcb->count;
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_REF_DTQ_LEAVE(ercd, pk_rdtq);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ref_dtq */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/dataqueue.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/dataqueue.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/dataqueue.h	(revision 453)
@@ -0,0 +1,166 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2013 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		データキュー機能
+ */
+
+#ifndef TOPPERS_DATAQUEUE_H
+#define TOPPERS_DATAQUEUE_H
+
+#include "wait.h"
+
+/*
+ *  データ管理ブロック
+ */
+typedef struct data_management_block {
+	intptr_t	data;			/* データ本体 */
+} DTQMB;
+
+/*
+ *  データキュー初期化ブロック
+ *
+ *  この構造体は，同期・通信オブジェクトの初期化ブロックの共通部分
+ *  （WOBJINIB）を拡張（オブジェクト指向言語の継承に相当）したもので，
+ *  最初のフィールドが共通になっている．
+ */
+typedef struct dataqueue_initialization_block {
+	ATR			dtqatr;			/* データキュー属性 */
+	uint_t		dtqcnt;			/* データキューの容量 */
+	DTQMB		*p_dtqmb;		/* データキュー管理領域の先頭番地 */
+} DTQINIB;
+
+/*
+ *  データキュー管理ブロック
+ *
+ *  この構造体は，同期・通信オブジェクトの管理ブロックの共通部分（WOBJCB）
+ *  を拡張（オブジェクト指向言語の継承に相当）したもので，最初の2つの
+ *  フィールドが共通になっている．
+ */
+typedef struct dataqueue_control_block {
+	QUEUE		swait_queue;	/* データキュー送信待ちキュー */
+	const DTQINIB *p_dtqinib;	/* 初期化ブロックへのポインタ */
+	QUEUE		rwait_queue;	/* データキュー受信待ちキュー */
+	uint_t		count;			/* データキュー中のデータの数 */
+	uint_t		head;			/* 最初のデータの格納場所 */
+	uint_t		tail;			/* 最後のデータの格納場所の次 */
+} DTQCB;
+
+/*
+ *  データキュー待ち情報ブロックの定義
+ *
+ *  この構造体は，同期・通信オブジェクトの待ち情報ブロックの共通部分
+ *  （WINFO_WOBJ）を拡張（オブジェクト指向言語の継承に相当）したもので，
+ *  最初の2つのフィールドが共通になっている．
+ *  データキューへの送信待ちとデータキューからの受信待ちで，同じ待ち情
+ *  報ブロックを使う．
+ */
+typedef struct dataqueue_waiting_information {
+	WINFO		winfo;			/* 標準の待ち情報ブロック */
+	DTQCB		*p_dtqcb;		/* 待っているデータキューの管理ブロック */
+	intptr_t	data;			/* 送受信データ */
+} WINFO_DTQ;
+
+/*
+ *  使用していないデータキュー管理ブロックのリスト
+ */
+extern QUEUE	free_dtqcb;
+
+/*
+ *  データキューIDの最大値（kernel_cfg.c）
+ */
+extern const ID	tmax_dtqid;
+extern const ID	tmax_sdtqid;
+
+/*
+ *  データキュー初期化ブロックのエリア（kernel_cfg.c）
+ */
+extern const DTQINIB	dtqinib_table[];
+extern DTQINIB			adtqinib_table[];
+
+/*
+ *  データキュー管理ブロックのエリア（kernel_cfg.c）
+ */
+extern DTQCB	dtqcb_table[];
+
+/*
+ *  データキュー管理ブロックからデータキューIDを取り出すためのマクロ
+ */
+#define	DTQID(p_dtqcb)	((ID)(((p_dtqcb) - dtqcb_table) + TMIN_DTQID))
+
+/*
+ *  データキュー機能の初期化
+ */
+extern void	initialize_dataqueue(void);
+
+/*
+ *  データキュー管理領域へのデータの格納
+ */
+extern void	enqueue_data(DTQCB *p_dtqcb, intptr_t data);
+
+/*
+ *  データキュー管理領域へのデータの強制格納
+ */
+extern void	force_enqueue_data(DTQCB *p_dtqcb, intptr_t data);
+
+/*
+ *  データキュー管理領域からのデータの取出し
+ */
+extern void	dequeue_data(DTQCB *p_dtqcb, intptr_t *p_data);
+
+/*
+ *  データキューへのデータ送信
+ */
+extern bool_t	send_data(DTQCB *p_dtqcb, intptr_t data, bool_t *p_dspreq);
+
+/*
+ *  データキューへのデータ強制送信
+ */
+extern bool_t	force_send_data(DTQCB *p_dtqcb, intptr_t data);
+
+/*
+ *  データキューからのデータ受信
+ */
+extern bool_t	receive_data(DTQCB *p_dtqcb, intptr_t *p_data,
+													bool_t *p_dspreq);
+
+#endif /* TOPPERS_DATAQUEUE_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/eventflag.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/eventflag.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/eventflag.c	(revision 453)
@@ -0,0 +1,645 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2014 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		イベントフラグ機能
+ */
+
+#include "kernel_impl.h"
+#include "check.h"
+#include "task.h"
+#include "wait.h"
+#include "eventflag.h"
+
+/*
+ *  トレースログマクロのデフォルト定義
+ */
+#ifndef LOG_ACRE_FLG_ENTER
+#define LOG_ACRE_FLG_ENTER(pk_cflg)
+#endif /* LOG_ACRE_FLG_ENTER */
+
+#ifndef LOG_ACRE_FLG_LEAVE
+#define LOG_ACRE_FLG_LEAVE(ercd)
+#endif /* LOG_ACRE_FLG_LEAVE */
+
+#ifndef LOG_DEL_FLG_ENTER
+#define LOG_DEL_FLG_ENTER(flgid)
+#endif /* LOG_DEL_FLG_ENTER */
+
+#ifndef LOG_DEL_FLG_LEAVE
+#define LOG_DEL_FLG_LEAVE(ercd)
+#endif /* LOG_DEL_FLG_LEAVE */
+
+#ifndef LOG_SET_FLG_ENTER
+#define LOG_SET_FLG_ENTER(flgid, setptn)
+#endif /* LOG_SET_FLG_ENTER */
+
+#ifndef LOG_SET_FLG_LEAVE
+#define LOG_SET_FLG_LEAVE(ercd)
+#endif /* LOG_SET_FLG_LEAVE */
+
+#ifndef LOG_ISET_FLG_ENTER
+#define LOG_ISET_FLG_ENTER(flgid, setptn)
+#endif /* LOG_ISET_FLG_ENTER */
+
+#ifndef LOG_ISET_FLG_LEAVE
+#define LOG_ISET_FLG_LEAVE(ercd)
+#endif /* LOG_ISET_FLG_LEAVE */
+
+#ifndef LOG_CLR_FLG_ENTER
+#define LOG_CLR_FLG_ENTER(flgid, clrptn)
+#endif /* LOG_CLR_FLG_ENTER */
+
+#ifndef LOG_CLR_FLG_LEAVE
+#define LOG_CLR_FLG_LEAVE(ercd)
+#endif /* LOG_CLR_FLG_LEAVE */
+
+#ifndef LOG_WAI_FLG_ENTER
+#define LOG_WAI_FLG_ENTER(flgid, waiptn, wfmode, p_flgptn)
+#endif /* LOG_WAI_FLG_ENTER */
+
+#ifndef LOG_WAI_FLG_LEAVE
+#define LOG_WAI_FLG_LEAVE(ercd, flgptn)
+#endif /* LOG_WAI_FLG_LEAVE */
+
+#ifndef LOG_POL_FLG_ENTER
+#define LOG_POL_FLG_ENTER(flgid, waiptn, wfmode, p_flgptn)
+#endif /* LOG_POL_FLG_ENTER */
+
+#ifndef LOG_POL_FLG_LEAVE
+#define LOG_POL_FLG_LEAVE(ercd, flgptn)
+#endif /* LOG_POL_FLG_LEAVE */
+
+#ifndef LOG_TWAI_FLG_ENTER
+#define LOG_TWAI_FLG_ENTER(flgid, waiptn, wfmode, p_flgptn, tmout)
+#endif /* LOG_TWAI_FLG_ENTER */
+
+#ifndef LOG_TWAI_FLG_LEAVE
+#define LOG_TWAI_FLG_LEAVE(ercd, flgptn)
+#endif /* LOG_TWAI_FLG_LEAVE */
+
+#ifndef LOG_INI_FLG_ENTER
+#define LOG_INI_FLG_ENTER(flgid)
+#endif /* LOG_INI_FLG_ENTER */
+
+#ifndef LOG_INI_FLG_LEAVE
+#define LOG_INI_FLG_LEAVE(ercd)
+#endif /* LOG_INI_FLG_LEAVE */
+
+#ifndef LOG_REF_FLG_ENTER
+#define LOG_REF_FLG_ENTER(flgid, pk_rflg)
+#endif /* LOG_REF_FLG_ENTER */
+
+#ifndef LOG_REF_FLG_LEAVE
+#define LOG_REF_FLG_LEAVE(ercd, pk_rflg)
+#endif /* LOG_REF_FLG_LEAVE */
+
+/*
+ *  イベントフラグの数
+ */
+#define tnum_flg	((uint_t)(tmax_flgid - TMIN_FLGID + 1))
+#define tnum_sflg	((uint_t)(tmax_sflgid - TMIN_FLGID + 1))
+
+/*
+ *  イベントフラグIDからイベントフラグ管理ブロックを取り出すためのマクロ
+ */
+#define INDEX_FLG(flgid)	((uint_t)((flgid) - TMIN_FLGID))
+#define get_flgcb(flgid)	(&(flgcb_table[INDEX_FLG(flgid)]))
+
+#ifdef TOPPERS_flgini
+
+/*
+ *  使用していないイベントフラグ管理ブロックのリスト
+ */
+QUEUE	free_flgcb;
+
+/*
+ *  イベントフラグ機能の初期化
+ */
+void
+initialize_eventflag(void)
+{
+	uint_t	i, j;
+	FLGCB	*p_flgcb;
+	FLGINIB	*p_flginib;
+
+	for (i = 0; i < tnum_sflg; i++) {
+		p_flgcb = &(flgcb_table[i]);
+		queue_initialize(&(p_flgcb->wait_queue));
+		p_flgcb->p_flginib = &(flginib_table[i]);
+		p_flgcb->flgptn = p_flgcb->p_flginib->iflgptn;
+	}
+	queue_initialize(&free_flgcb);
+	for (j = 0; i < tnum_flg; i++, j++) {
+		p_flgcb = &(flgcb_table[i]);
+		p_flginib = &(aflginib_table[j]);
+		p_flginib->flgatr = TA_NOEXS;
+		p_flgcb->p_flginib = ((const FLGINIB *) p_flginib);
+		queue_insert_prev(&free_flgcb, &(p_flgcb->wait_queue));
+	}
+}
+
+#endif /* TOPPERS_flgini */
+
+/*
+ *  イベントフラグ待ち解除条件のチェック
+ */
+#ifdef TOPPERS_flgcnd
+
+bool_t
+check_flg_cond(FLGCB *p_flgcb, FLGPTN waiptn, MODE wfmode, FLGPTN *p_flgptn)
+{
+	if ((wfmode & TWF_ORW) != 0U ? (p_flgcb->flgptn & waiptn) != 0U
+									: (p_flgcb->flgptn & waiptn) == waiptn) {
+		*p_flgptn = p_flgcb->flgptn;
+		if ((p_flgcb->p_flginib->flgatr & TA_CLR) != 0U) {
+			p_flgcb->flgptn = 0U;
+		}
+		return(true);
+	}
+	return(false);
+}
+
+#endif /* TOPPERS_flgcnd */
+
+/*
+ *  イベントフラグの生成
+ */
+#ifdef TOPPERS_acre_flg
+
+ER_UINT
+acre_flg(const T_CFLG *pk_cflg)
+{
+	FLGCB	*p_flgcb;
+	FLGINIB	*p_flginib;
+	ER		ercd;
+
+	LOG_ACRE_FLG_ENTER(pk_cflg);
+	CHECK_TSKCTX_UNL();
+	CHECK_RSATR(pk_cflg->flgatr, TA_TPRI|TA_WMUL|TA_CLR);
+
+	t_lock_cpu();
+	if (tnum_flg == 0 || queue_empty(&free_flgcb)) {
+		ercd = E_NOID;
+	}
+	else {
+		p_flgcb = ((FLGCB *) queue_delete_next(&free_flgcb));
+		p_flginib = (FLGINIB *)(p_flgcb->p_flginib);
+		p_flginib->flgatr = pk_cflg->flgatr;
+		p_flginib->iflgptn = pk_cflg->iflgptn;
+
+		queue_initialize(&(p_flgcb->wait_queue));
+		p_flgcb->flgptn = p_flgcb->p_flginib->iflgptn;
+		ercd = FLGID(p_flgcb);
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_ACRE_FLG_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_acre_flg */
+
+/*
+ *  イベントフラグの削除
+ */
+#ifdef TOPPERS_del_flg
+
+ER
+del_flg(ID flgid)
+{
+	FLGCB	*p_flgcb;
+	FLGINIB	*p_flginib;
+	bool_t	dspreq;
+	ER		ercd;
+
+	LOG_DEL_FLG_ENTER(flgid);
+	CHECK_TSKCTX_UNL();
+	CHECK_FLGID(flgid);
+	p_flgcb = get_flgcb(flgid);
+
+	t_lock_cpu();
+	if (p_flgcb->p_flginib->flgatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (FLGID(p_flgcb) > tmax_sflgid) {
+		dspreq = init_wait_queue(&(p_flgcb->wait_queue));
+		p_flginib = (FLGINIB *)(p_flgcb->p_flginib);
+		p_flginib->flgatr = TA_NOEXS;
+		queue_insert_prev(&free_flgcb, &(p_flgcb->wait_queue));
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_OBJ;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_DEL_FLG_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_del_flg */
+
+/*
+ *  イベントフラグのセット
+ */
+#ifdef TOPPERS_set_flg
+
+ER
+set_flg(ID flgid, FLGPTN setptn)
+{
+	FLGCB	*p_flgcb;
+	QUEUE	*p_queue;
+	TCB		*p_tcb;
+	WINFO_FLG *p_winfo_flg;
+	bool_t	dspreq = false;
+	ER		ercd;
+
+	LOG_SET_FLG_ENTER(flgid, setptn);
+	CHECK_TSKCTX_UNL();
+	CHECK_FLGID(flgid);
+	p_flgcb = get_flgcb(flgid);
+
+	t_lock_cpu();
+	if (p_flgcb->p_flginib->flgatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		p_flgcb->flgptn |= setptn;
+		p_queue = p_flgcb->wait_queue.p_next;
+		while (p_queue != &(p_flgcb->wait_queue)) {
+			p_tcb = (TCB *) p_queue;
+			p_queue = p_queue->p_next;
+			p_winfo_flg = (WINFO_FLG *)(p_tcb->p_winfo);
+			if (check_flg_cond(p_flgcb, p_winfo_flg->waiptn,
+							p_winfo_flg->wfmode, &(p_winfo_flg->flgptn))) {
+				queue_delete(&(p_tcb->task_queue));
+				if (wait_complete(p_tcb)) {
+					dspreq = true;
+				}
+				if ((p_flgcb->p_flginib->flgatr & TA_CLR) != 0U) {
+					break;
+				}
+			}
+		}
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_SET_FLG_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_set_flg */
+
+/*
+ *  イベントフラグのセット（非タスクコンテキスト用）
+ */
+#ifdef TOPPERS_iset_flg
+
+ER
+iset_flg(ID flgid, FLGPTN setptn)
+{
+	FLGCB	*p_flgcb;
+	QUEUE	*p_queue;
+	TCB		*p_tcb;
+	WINFO_FLG *p_winfo_flg;
+	ER		ercd;
+
+	LOG_ISET_FLG_ENTER(flgid, setptn);
+	CHECK_INTCTX_UNL();
+	CHECK_FLGID(flgid);
+	p_flgcb = get_flgcb(flgid);
+
+	i_lock_cpu();
+	if (p_flgcb->p_flginib->flgatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		p_flgcb->flgptn |= setptn;
+		p_queue = p_flgcb->wait_queue.p_next;
+		while (p_queue != &(p_flgcb->wait_queue)) {
+			p_tcb = (TCB *) p_queue;
+			p_queue = p_queue->p_next;
+			p_winfo_flg = (WINFO_FLG *)(p_tcb->p_winfo);
+			if (check_flg_cond(p_flgcb, p_winfo_flg->waiptn,
+							p_winfo_flg->wfmode, &(p_winfo_flg->flgptn))) {
+				queue_delete(&(p_tcb->task_queue));
+				if (wait_complete(p_tcb)) {
+					reqflg = true;
+				}
+				if ((p_flgcb->p_flginib->flgatr & TA_CLR) != 0U) {
+					break;
+				}
+			}
+		}
+		ercd = E_OK;
+	}
+	i_unlock_cpu();
+
+  error_exit:
+	LOG_ISET_FLG_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_iset_flg */
+
+/*
+ *  イベントフラグのクリア
+ */
+#ifdef TOPPERS_clr_flg
+
+ER
+clr_flg(ID flgid, FLGPTN clrptn)
+{
+	FLGCB	*p_flgcb;
+	ER		ercd;
+
+	LOG_CLR_FLG_ENTER(flgid, clrptn);
+	CHECK_TSKCTX_UNL();
+	CHECK_FLGID(flgid);
+	p_flgcb = get_flgcb(flgid);
+
+	t_lock_cpu();
+	if (p_flgcb->p_flginib->flgatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		p_flgcb->flgptn &= clrptn; 
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_CLR_FLG_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_clr_flg */
+
+/*
+ *  イベントフラグ待ち
+ */
+#ifdef TOPPERS_wai_flg
+
+ER
+wai_flg(ID flgid, FLGPTN waiptn, MODE wfmode, FLGPTN *p_flgptn)
+{
+	FLGCB	*p_flgcb;
+	WINFO_FLG winfo_flg;
+	ER		ercd;
+
+	LOG_WAI_FLG_ENTER(flgid, waiptn, wfmode, p_flgptn);
+	CHECK_DISPATCH();
+	CHECK_FLGID(flgid);
+	CHECK_PAR(waiptn != 0U);
+	CHECK_PAR(wfmode == TWF_ORW || wfmode == TWF_ANDW);
+	p_flgcb = get_flgcb(flgid);
+
+	t_lock_cpu();
+	if (p_flgcb->p_flginib->flgatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if ((p_flgcb->p_flginib->flgatr & TA_WMUL) == 0U
+					&& !queue_empty(&(p_flgcb->wait_queue))) {
+		ercd = E_ILUSE;
+	}
+	else if (check_flg_cond(p_flgcb, waiptn, wfmode, p_flgptn)) {
+		ercd = E_OK;
+	}
+	else {
+		winfo_flg.waiptn = waiptn;
+		winfo_flg.wfmode = wfmode;
+		p_runtsk->tstat = (TS_WAITING | TS_WAIT_FLG);
+		wobj_make_wait((WOBJCB *) p_flgcb, (WINFO_WOBJ *) &winfo_flg);
+		dispatch();
+		ercd = winfo_flg.winfo.wercd;
+		if (ercd == E_OK) {
+			*p_flgptn = winfo_flg.flgptn;
+		}
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_WAI_FLG_LEAVE(ercd, *p_flgptn);
+	return(ercd);
+}
+
+#endif /* TOPPERS_wai_flg */
+
+/*
+ *  イベントフラグ待ち（ポーリング）
+ */
+#ifdef TOPPERS_pol_flg
+
+ER
+pol_flg(ID flgid, FLGPTN waiptn, MODE wfmode, FLGPTN *p_flgptn)
+{
+	FLGCB	*p_flgcb;
+	ER		ercd;
+
+	LOG_POL_FLG_ENTER(flgid, waiptn, wfmode, p_flgptn);
+	CHECK_TSKCTX_UNL();
+	CHECK_FLGID(flgid);
+	CHECK_PAR(waiptn != 0U);
+	CHECK_PAR(wfmode == TWF_ORW || wfmode == TWF_ANDW);
+	p_flgcb = get_flgcb(flgid);
+
+	t_lock_cpu();
+	if (p_flgcb->p_flginib->flgatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if ((p_flgcb->p_flginib->flgatr & TA_WMUL) == 0U
+					&& !queue_empty(&(p_flgcb->wait_queue))) {
+		ercd = E_ILUSE;
+	}
+	else if (check_flg_cond(p_flgcb, waiptn, wfmode, p_flgptn)) {
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_TMOUT;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_POL_FLG_LEAVE(ercd, *p_flgptn);
+	return(ercd);
+}
+
+#endif /* TOPPERS_pol_flg */
+
+/*
+ *  イベントフラグ待ち（タイムアウトあり）
+ */
+#ifdef TOPPERS_twai_flg
+
+ER
+twai_flg(ID flgid, FLGPTN waiptn, MODE wfmode, FLGPTN *p_flgptn, TMO tmout)
+{
+	FLGCB	*p_flgcb;
+	WINFO_FLG winfo_flg;
+	TMEVTB	tmevtb;
+	ER		ercd;
+
+	LOG_TWAI_FLG_ENTER(flgid, waiptn, wfmode, p_flgptn, tmout);
+	CHECK_DISPATCH();
+	CHECK_FLGID(flgid);
+	CHECK_PAR(waiptn != 0U);
+	CHECK_PAR(wfmode == TWF_ORW || wfmode == TWF_ANDW);
+	CHECK_TMOUT(tmout);
+	p_flgcb = get_flgcb(flgid);
+
+	t_lock_cpu();
+	if (p_flgcb->p_flginib->flgatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if ((p_flgcb->p_flginib->flgatr & TA_WMUL) == 0U
+					&& !queue_empty(&(p_flgcb->wait_queue))) {
+		ercd = E_ILUSE;
+	}
+	else if (check_flg_cond(p_flgcb, waiptn, wfmode, p_flgptn)) {
+		ercd = E_OK;
+	}
+	else if (tmout == TMO_POL) {
+		ercd = E_TMOUT;
+	}
+	else {
+		winfo_flg.waiptn = waiptn;
+		winfo_flg.wfmode = wfmode;
+		p_runtsk->tstat = (TS_WAITING | TS_WAIT_FLG);
+		wobj_make_wait_tmout((WOBJCB *) p_flgcb, (WINFO_WOBJ *) &winfo_flg,
+														&tmevtb, tmout);
+		dispatch();
+		ercd = winfo_flg.winfo.wercd;
+		if (ercd == E_OK) {
+			*p_flgptn = winfo_flg.flgptn;
+		}
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_TWAI_FLG_LEAVE(ercd, *p_flgptn);
+	return(ercd);
+}
+
+#endif /* TOPPERS_twai_flg */
+
+/*
+ *  イベントフラグの再初期化
+ */
+#ifdef TOPPERS_ini_flg
+
+ER
+ini_flg(ID flgid)
+{
+	FLGCB	*p_flgcb;
+	bool_t	dspreq;
+	ER		ercd;
+    
+	LOG_INI_FLG_ENTER(flgid);
+	CHECK_TSKCTX_UNL();
+	CHECK_FLGID(flgid);
+	p_flgcb = get_flgcb(flgid);
+
+	t_lock_cpu();
+	if (p_flgcb->p_flginib->flgatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		dspreq = init_wait_queue(&(p_flgcb->wait_queue));
+		p_flgcb->flgptn = p_flgcb->p_flginib->iflgptn;
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_INI_FLG_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ini_flg */
+
+/*
+ *  イベントフラグの状態参照
+ */
+#ifdef TOPPERS_ref_flg
+
+ER
+ref_flg(ID flgid, T_RFLG *pk_rflg)
+{
+	FLGCB	*p_flgcb;
+	ER		ercd;
+    
+	LOG_REF_FLG_ENTER(flgid, pk_rflg);
+	CHECK_TSKCTX_UNL();
+	CHECK_FLGID(flgid);
+	p_flgcb = get_flgcb(flgid);
+
+	t_lock_cpu();
+	if (p_flgcb->p_flginib->flgatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		pk_rflg->wtskid = wait_tskid(&(p_flgcb->wait_queue));
+		pk_rflg->flgptn = p_flgcb->flgptn;
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_REF_FLG_LEAVE(ercd, pk_rflg);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ref_flg */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/eventflag.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/eventflag.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/eventflag.h	(revision 453)
@@ -0,0 +1,133 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2012 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		イベントフラグ機能
+ */
+
+#ifndef TOPPERS_EVENTFLAG_H
+#define TOPPERS_EVENTFLAG_H
+
+#include "wait.h"
+
+/*
+ *  イベントフラグ初期化ブロック
+ *
+ *  この構造体は，同期・通信オブジェクトの初期化ブロックの共通部分
+ *  （WOBJINIB）を拡張（オブジェクト指向言語の継承に相当）したもので，
+ *  最初のフィールドが共通になっている．
+ */
+typedef struct eventflag_initialization_block {
+	ATR			flgatr;			/* イベントフラグ属性 */
+	FLGPTN		iflgptn;		/* イベントフラグのビットパターンの初期値 */
+} FLGINIB;
+
+/*
+ *  イベントフラグ管理ブロック
+ *
+ *  この構造体は，同期・通信オブジェクトの管理ブロックの共通部分（WOBJCB）
+ *  を拡張（オブジェクト指向言語の継承に相当）したもので，最初の2つの
+ *  フィールドが共通になっている．
+ */
+typedef struct eventflag_control_block {
+	QUEUE		wait_queue;		/* イベントフラグ待ちキュー */
+	const FLGINIB *p_flginib;	/* 初期化ブロックへのポインタ */
+	FLGPTN		flgptn;			/* イベントフラグ現在パターン */
+} FLGCB;
+
+/*
+ *  イベントフラグ待ち情報ブロックの定義
+ *
+ *  この構造体は，同期・通信オブジェクトの待ち情報ブロックの共通部分
+ *  （WINFO_WOBJ）を拡張（オブジェクト指向言語の継承に相当）したもので，
+ *  最初の2つのフィールドが共通になっている．
+ *
+ *  flgptnは，waiptnおよびwfmodeと同時に使うことはないため，共用体を使
+ *  えばメモリを節約することが可能である．
+ */
+typedef struct eventflag_waiting_information {
+	WINFO		winfo;			/* 標準の待ち情報ブロック */
+	FLGCB		*p_flgcb;		/* 待っているイベントフラグの管理ブロック */
+	FLGPTN		waiptn;			/* 待ちパターン */
+	MODE		wfmode;			/* 待ちモード */
+	FLGPTN		flgptn;			/* 待ち解除時のパターン */
+} WINFO_FLG;
+
+/*
+ *  使用していないイベントフラグ管理ブロックのリスト
+ */
+extern QUEUE	free_flgcb;
+
+/*
+ *  イベントフラグIDの最大値（kernel_cfg.c）
+ */
+extern const ID	tmax_flgid;
+extern const ID	tmax_sflgid;
+
+/*
+ *  イベントフラグ初期化ブロックのエリア（kernel_cfg.c）
+ */
+extern const FLGINIB	flginib_table[];
+extern FLGINIB			aflginib_table[];
+
+/*
+ *  イベントフラグ管理ブロックのエリア（kernel_cfg.c）
+ */
+extern FLGCB	flgcb_table[];
+
+/*
+ *  イベントフラグ管理ブロックからイベントフラグIDを取り出すためのマクロ
+ */
+#define	FLGID(p_flgcb)	((ID)(((p_flgcb) - flgcb_table) + TMIN_FLGID))
+
+/*
+ *  イベントフラグ機能の初期化
+ */
+extern void	initialize_eventflag(void);
+
+/*
+ *  イベントフラグ待ち解除条件のチェック
+ */
+extern bool_t	check_flg_cond(FLGCB *p_flgcb, FLGPTN waiptn,
+								MODE wfmode, FLGPTN *p_flgptn);
+
+#endif /* TOPPERS_EVENTFLAG_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/exception.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/exception.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/exception.c	(revision 453)
@@ -0,0 +1,138 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		CPU例外管理機能
+ */
+
+#include "kernel_impl.h"
+#include "task.h"
+#include "exception.h"
+
+/*
+ *  トレースログマクロのデフォルト定義
+ */
+#ifndef LOG_XSNS_DPN_ENTER
+#define LOG_XSNS_DPN_ENTER(p_excinf)
+#endif /* LOG_XSNS_DPN_ENTER */
+
+#ifndef LOG_XSNS_DPN_LEAVE
+#define LOG_XSNS_DPN_LEAVE(state)
+#endif /* LOG_XSNS_DPN_LEAVE */
+
+#ifndef LOG_XSNS_XPN_ENTER
+#define LOG_XSNS_XPN_ENTER(p_excinf)
+#endif /* LOG_XSNS_XPN_ENTER */
+
+#ifndef LOG_XSNS_XPN_LEAVE
+#define LOG_XSNS_XPN_LEAVE(state)
+#endif /* LOG_XSNS_XPN_LEAVE */
+
+/* 
+ *  CPU例外ハンドラ管理機能の初期化
+ */
+#ifdef TOPPERS_excini
+#ifndef OMIT_INITIALIZE_EXCEPTION
+
+void
+initialize_exception(void)
+{
+	uint_t			i;
+	const EXCINIB	*p_excinib;
+
+	for (i = 0; i < tnum_excno; i++) {
+		p_excinib = &(excinib_table[i]);
+		x_define_exc(p_excinib->excno, p_excinib->exc_entry);
+	}
+}
+
+#endif /* OMIT_INITIALIZE_EXCEPTION */
+#endif /* TOPPERS_excini */
+
+/*
+ *  CPU例外の発生したコンテキストの参照
+ */
+
+/*
+ *  CPU例外発生時のディスパッチ保留状態の参照
+ *
+ *  CPU例外ハンドラ中でdisdspが変化することはないため，CPU例外が発生し
+ *  た時のdisdspを保存しておく必要はない．
+ */
+#ifdef TOPPERS_xsns_dpn
+
+bool_t
+xsns_dpn(void *p_excinf)
+{
+	bool_t	state;
+
+	LOG_XSNS_DPN_ENTER(p_excinf);
+	state = (kerflg && exc_sense_intmask(p_excinf)
+									&& !disdsp) ? false : true;
+	LOG_XSNS_DPN_LEAVE(state);
+	return(state);
+}
+
+#endif /* TOPPERS_xsns_dpn */
+
+/*
+ *  CPU例外発生時のタスク例外処理保留状態の参照
+ *
+ *  CPU例外ハンドラ中でp_runtskとp_runtsk->enatexが変化することはない
+ *  ため，CPU例外が発生した時のp_runtsk->enatexを保存しておく必要はな
+ *  い．
+ */
+#ifdef TOPPERS_xsns_xpn
+
+bool_t
+xsns_xpn(void *p_excinf)
+{
+	bool_t	state;
+
+	LOG_XSNS_XPN_ENTER(p_excinf);
+	state = (kerflg && exc_sense_intmask(p_excinf)
+									&& p_runtsk->enatex) ? false : true;
+	LOG_XSNS_XPN_LEAVE(state);
+	return(state);
+}
+
+#endif /* TOPPERS_xsns_xpn */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/exception.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/exception.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/exception.h	(revision 453)
@@ -0,0 +1,78 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2007 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		CPU例外管理機能
+ */
+
+#ifndef TOPPERS_EXCEPTION_H
+#define TOPPERS_EXCEPTION_H
+
+#ifndef OMIT_INITIALIZE_EXCEPTION
+
+/*
+ *  CPU例外ハンドラ初期化ブロック
+ */
+typedef struct cpu_exception_handler_initialization_block {
+	EXCNO		excno;			/* CPU例外ハンドラ番号 */
+	ATR			excatr;			/* CPU例外ハンドラ属性 */
+	FP			exc_entry;		/* CPU例外ハンドラの出入口処理の番地 */
+} EXCINIB;
+
+/*
+ *  CPU例外ハンドラ番号の数（kernel_cfg.c）
+ */
+extern const uint_t	tnum_excno;
+
+/*
+ *  CPU例外ハンドラ初期化ブロックのエリア（kernel_cfg.c）
+ */
+extern const EXCINIB	excinib_table[];
+
+#endif /* OMIT_INITIALIZE_EXCEPTION */
+
+/*
+ *  CPU例外ハンドラ管理機能の初期化
+ */
+extern void	initialize_exception(void);
+
+#endif /* TOPPERS_EXCEPTION_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/genoffset.tf
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/genoffset.tf	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/genoffset.tf	(revision 453)
@@ -0,0 +1,158 @@
+$ ======================================================================
+$ 
+$   TOPPERS/ASP Kernel
+$       Toyohashi Open Platform for Embedded Real-Time Systems/
+$       Advanced Standard Profile Kernel
+$ 
+$   Copyright (C) 2011-2017 by Embedded and Real-Time Systems Laboratory
+$               Graduate School of Information Science, Nagoya Univ., JAPAN
+$  
+$   上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+$   ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+$   変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+$   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+$       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+$       スコード中に含まれていること．
+$   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+$       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+$       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+$       の無保証規定を掲載すること．
+$   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+$       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+$       と．
+$     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+$         作権表示，この利用条件および下記の無保証規定を掲載すること．
+$     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+$         報告すること．
+$   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+$       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+$       また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+$       由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+$       免責すること．
+$  
+$   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+$   よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+$   に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+$   アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+$   の責任を負わない．
+$ 
+$   $Id$
+$ 
+$ =====================================================================
+
+$ 
+$  SIL_ENDIANの誤定義の検出
+$ 
+$IF SIL_ENDIAN_BIG && SIL_ENDIAN_LITTLE$
+	$ERROR$Both SIL_ENDIAN_BIG and SIL_ENDIAN_LITTLE are defined.$END$
+	$DIE()$
+$END$
+$IF !SIL_ENDIAN_BIG && !SIL_ENDIAN_LITTLE$
+	$ERROR$Neither SIL_ENDIAN_BIG nor SIL_ENDIAN_LITTLE is defined.$END$
+	$DIE()$
+$END$
+
+$ 
+$  #defineディレクティブの生成
+$ 
+$FUNCTION DEFINE$
+	#define $ARGV[1]$$TAB$$FORMAT("%d", +ARGV[2])$$NL$
+$END$
+
+$ 
+$  ビットのサーチ
+$ 
+$FUNCTION SEARCH_BIT$
+	$_val = ARGV[1]$
+	$FOREACH _val_bit RANGE(0,7)$
+		$IF (_val & 1) != 0$
+			$RESULT = _val_bit$
+		$END$
+		$_val = _val >> 1$
+	$END$
+$END$
+
+$ 
+$  ビットフィールドのオフセットとビット位置の定義の生成
+$ 
+$FUNCTION DEFINE_BIT$
+	$label = ARGV[1]$
+	$struct_size = ARGV[2]$
+	$output_size = ARGV[3]$
+
+	$top = SYMBOL(label)$
+	$IF !LENGTH(top)$
+		$ERROR$$FORMAT("label %1% not found", label)$$END$
+	$ELSE$
+		$val = 0$
+		$FOREACH i RANGE(0,struct_size-1)$
+			$tmp_val = PEEK(top + i, 1)$
+			$IF val == 0 && tmp_val != 0$
+				$val = tmp_val$
+				$offset = i$
+			$END$
+		$END$
+
+		$IF val == 0$
+			$ERROR$$FORMAT("bit not found in %1%", ARGV[1])$$END$
+		$ELSE$
+			$val_bit = SEARCH_BIT(val)$
+			$RESULT = {}$
+			$IF EQ(output_size, "W")$
+				$IF SIL_ENDIAN_BIG$
+					$val_bit = val_bit + 24 - ((offset & 0x03) << 3)$
+				$ELSE$
+					$val_bit = val_bit + ((offset & 0x03) << 3)$
+				$END$
+				$offset = offset & ~0x03$
+			$ELSE$$IF EQ(output_size, "H")$
+				$IF SIL_ENDIAN_BIG$
+					$val_bit = val_bit + 8 - ((offset & 0x01) << 3)$
+				$ELSE$
+					$val_bit = val_bit + ((offset & 0x01) << 3)$
+				$END$
+				$offset = offset & ~0x01$
+			$END$$END$
+		$END$
+
+		#define $label$$TAB$$FORMAT("%d", +offset)$$NL$
+		#define $label$_bit$TAB$$FORMAT("%d", +val_bit)$$NL$
+		#define $label$_mask$TAB$$FORMAT("0x%x", 1 << val_bit)$$NL$
+	$END$
+$END$
+
+$ 
+$  バイト配置のチェック
+$ 
+$FUNCTION MAGIC_CHECK$
+	$size = ARGV[1]$
+	$check = ARGV[2]$
+
+	$label = FORMAT("MAGIC_%d", +size)$
+	$top = SYMBOL(label)$
+	$IF !LENGTH(top)$
+		$ERROR$$FORMAT("label %1% not found", label)$$END$
+	$ELSE$
+		$FOREACH offset RANGE(1,size)$
+			$IF SIL_ENDIAN_BIG$
+				$val = PEEK(top + offset - 1, 1)$
+			$ELSE$
+				$val = PEEK(top + size - offset, 1)$
+			$END$
+			$IF val != AT(check, offset - 1)$
+				$ERROR$$FORMAT("value check of %1% failed", label)$$END$
+			$END$
+		$END$
+	$END$
+$END$
+
+$MAGIC_CHECK(1, { 0x12 })$
+$MAGIC_CHECK(2, { 0x12, 0x34 })$
+$MAGIC_CHECK(4, { 0x12, 0x34, 0x56, 0x78 })$
+
+$ 
+$  ファイルヘッダの生成
+$ 
+$FILE "offset.h"$
+/* offset.h */$NL$
+$NL$
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/interrupt.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/interrupt.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/interrupt.c	(revision 453)
@@ -0,0 +1,494 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2012 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		割込み管理機能
+ */
+
+#include "kernel_impl.h"
+#include "check.h"
+#include "task.h"
+#include "interrupt.h"
+
+/*
+ *  トレースログマクロのデフォルト定義
+ */
+#ifndef LOG_ISR_ENTER
+#define LOG_ISR_ENTER(intno)
+#endif /* LOG_ISR_ENTER */
+
+#ifndef LOG_ISR_LEAVE
+#define LOG_ISR_LEAVE(intno)
+#endif /* LOG_ISR_LEAVE */
+
+#ifndef LOG_ACRE_ISR_ENTER
+#define LOG_ACRE_ISR_ENTER(pk_cisr)
+#endif /* LOG_ACRE_ISR_ENTER */
+
+#ifndef LOG_ACRE_ISR_LEAVE
+#define LOG_ACRE_ISR_LEAVE(ercd)
+#endif /* LOG_ACRE_ISR_LEAVE */
+
+#ifndef LOG_DEL_ISR_ENTER
+#define LOG_DEL_ISR_ENTER(isrid)
+#endif /* LOG_DEL_ISR_ENTER */
+
+#ifndef LOG_DEL_ISR_LEAVE
+#define LOG_DEL_ISR_LEAVE(ercd)
+#endif /* LOG_DEL_ISR_LEAVE */
+
+#ifndef LOG_DIS_INT_ENTER
+#define LOG_DIS_INT_ENTER(intno)
+#endif /* LOG_DIS_INT_ENTER */
+
+#ifndef LOG_DIS_INT_LEAVE
+#define LOG_DIS_INT_LEAVE(ercd)
+#endif /* LOG_DIS_INT_LEAVE */
+
+#ifndef LOG_ENA_INT_ENTER
+#define LOG_ENA_INT_ENTER(intno)
+#endif /* LOG_ENA_INT_ENTER */
+
+#ifndef LOG_ENA_INT_LEAVE
+#define LOG_ENA_INT_LEAVE(ercd)
+#endif /* LOG_ENA_INT_LEAVE */
+
+#ifndef LOG_CHG_IPM_ENTER
+#define LOG_CHG_IPM_ENTER(intpri)
+#endif /* LOG_CHG_IPM_ENTER */
+
+#ifndef LOG_CHG_IPM_LEAVE
+#define LOG_CHG_IPM_LEAVE(ercd)
+#endif /* LOG_CHG_IPM_LEAVE */
+
+#ifndef LOG_GET_IPM_ENTER
+#define LOG_GET_IPM_ENTER(p_intpri)
+#endif /* LOG_GET_IPM_ENTER */
+
+#ifndef LOG_GET_IPM_LEAVE
+#define LOG_GET_IPM_LEAVE(ercd, intpri)
+#endif /* LOG_GET_IPM_LEAVE */
+
+/*
+ *  割込みサービスルーチンの数
+ */
+#define tnum_isr	((uint_t)(tmax_isrid - TMIN_ISRID + 1) + tnum_sisr)
+
+/*
+ *  割込みサービスルーチンIDから割込みサービスルーチン管理ブロックを取
+ *  り出すためのマクロ
+ */
+#define INDEX_ISR(isrid)	((uint_t)((isrid) - TMIN_ISRID) + tnum_sisr)
+#define get_isrcb(isrid)	(&(isrcb_table[INDEX_ISR(isrid)]))
+
+/*
+ *  割込みサービスルーチンキューへの登録
+ */
+Inline void
+enqueue_isr(QUEUE *p_isr_queue, ISRCB *p_isrcb)
+{
+	QUEUE	*p_entry;
+	PRI		isrpri = p_isrcb->p_isrinib->isrpri;
+
+	for (p_entry = p_isr_queue->p_next; p_entry != p_isr_queue;
+											p_entry = p_entry->p_next) {
+		if (isrpri < ((ISRCB *) p_entry)->p_isrinib->isrpri) {
+			break;
+		}
+	}
+	queue_insert_prev(p_entry, &(p_isrcb->isr_queue));
+}
+
+#ifdef TOPPERS_isrini
+
+/*
+ *  使用していない割込みサービスルーチン管理ブロックのリスト
+ */
+QUEUE	free_isrcb;
+
+/* 
+ *  割込みサービスルーチン機能の初期化
+ */
+void
+initialize_isr(void)
+{
+	uint_t	i, j;
+	ISRCB	*p_isrcb;
+	ISRINIB	*p_isrinib;
+
+	for (i = 0; i < tnum_isr_queue; i++) {
+		queue_initialize(&(isr_queue_table[i]));
+	}
+	for (i = 0; i < tnum_sisr; i++) {
+		p_isrcb = &(isrcb_table[i]);
+		p_isrcb->p_isrinib = &(sisrinib_table[i]);
+		enqueue_isr(p_isrcb->p_isrinib->p_isr_queue, p_isrcb);
+	}
+	queue_initialize(&free_isrcb);
+	for (j = 0; i < tnum_isr; i++, j++) {
+		p_isrcb = &(isrcb_table[i]);
+		p_isrinib = &(aisrinib_table[j]);
+		p_isrinib->isratr = TA_NOEXS;
+		p_isrcb->p_isrinib = ((const ISRINIB *) p_isrinib);
+		queue_insert_prev(&free_isrcb, &(p_isrcb->isr_queue));
+	}
+}
+
+#endif /* TOPPERS_isrini */
+
+/*
+ *  割込みサービスルーチンの呼出し
+ */
+#ifdef TOPPERS_isrcal
+
+void
+call_isr(QUEUE *p_isr_queue)
+{
+	QUEUE	*p_queue;
+	ISRINIB	*p_isrinib;
+	PRI		saved_ipm;
+
+	saved_ipm = i_get_ipm();
+	for (p_queue = p_isr_queue->p_next; p_queue != p_isr_queue;
+											p_queue = p_queue->p_next) {
+		p_isrinib = (ISRINIB *)(((ISRCB *) p_queue)->p_isrinib);
+		LOG_ISR_ENTER(p_isrinib->intno);
+		(*(p_isrinib->isr))(p_isrinib->exinf);
+		LOG_ISR_LEAVE(p_isrinib->intno);
+
+		if (p_queue->p_next != p_isr_queue) {
+			/* ISRの呼出し前の状態に戻す */
+			if (i_sense_lock()) {
+				i_unlock_cpu();
+			}
+			i_set_ipm(saved_ipm);
+		}
+	}
+}
+
+#endif /* TOPPERS_isrcal */
+
+/*
+ *  割込みサービスルーチン呼出しキューの検索
+ */
+Inline QUEUE *
+search_isr_queue(INTNO intno)
+{
+	int_t	left, right, i;
+
+	if (tnum_isr_queue == 0) {
+		return(NULL);
+	}
+
+	left = 0;
+	right = tnum_isr_queue - 1;
+	while (left < right) {
+		i = (left + right + 1) / 2;
+		if (intno < isr_queue_list[i].intno) {
+			right = i - 1;
+		}
+		else {
+			left = i;
+		}
+	}
+	if (isr_queue_list[left].intno == intno) {
+		return(isr_queue_list[left].p_isr_queue);
+	}
+	else {
+		return(NULL);
+	}
+}
+
+/*
+ *  割込みサービスルーチンの生成
+ */
+#ifdef TOPPERS_acre_isr
+
+ER_UINT
+acre_isr(const T_CISR *pk_cisr)
+{
+	ISRCB	*p_isrcb;
+	ISRINIB	*p_isrinib;
+	QUEUE	*p_isr_queue;
+	ER		ercd;
+
+	LOG_ACRE_ISR_ENTER(pk_cisr);
+	CHECK_TSKCTX_UNL();
+	CHECK_RSATR(pk_cisr->isratr, TARGET_ISRATR);
+	CHECK_INTNO_CREISR(pk_cisr->intno);
+	CHECK_ALIGN_FUNC(pk_cisr->isr);
+	CHECK_NONNULL_FUNC(pk_cisr->isr);
+	CHECK_ISRPRI(pk_cisr->isrpri);
+
+	p_isr_queue = search_isr_queue(pk_cisr->intno);
+	CHECK_OBJ(p_isr_queue != NULL);
+
+	t_lock_cpu();
+	if (tnum_isr == 0 || queue_empty(&free_isrcb)) {
+		ercd = E_NOID;
+	}
+	else {
+		p_isrcb = ((ISRCB *) queue_delete_next(&free_isrcb));
+		p_isrinib = (ISRINIB *)(p_isrcb->p_isrinib);
+		p_isrinib->isratr = pk_cisr->isratr;
+		p_isrinib->exinf = pk_cisr->exinf;
+		p_isrinib->intno = pk_cisr->intno;
+		p_isrinib->p_isr_queue = p_isr_queue;
+		p_isrinib->isr = pk_cisr->isr;
+		p_isrinib->isrpri = pk_cisr->isrpri;
+		enqueue_isr(p_isr_queue, p_isrcb);
+		ercd = ISRID(p_isrcb);
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_ACRE_ISR_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_acre_isr */
+
+/*
+ *  割込みサービスルーチンの削除
+ */
+#ifdef TOPPERS_del_isr
+
+ER
+del_isr(ID isrid)
+{
+	ISRCB	*p_isrcb;
+	ISRINIB	*p_isrinib;
+	ER		ercd;
+
+	LOG_DEL_ISR_ENTER(isrid);
+	CHECK_TSKCTX_UNL();
+	CHECK_ISRID(isrid);
+	p_isrcb = get_isrcb(isrid);
+
+	t_lock_cpu();
+	if (p_isrcb->p_isrinib->isratr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		queue_delete(&(p_isrcb->isr_queue));
+		p_isrinib = (ISRINIB *)(p_isrcb->p_isrinib);
+		p_isrinib->isratr = TA_NOEXS;
+		queue_insert_prev(&free_isrcb, &(p_isrcb->isr_queue));
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_DEL_ISR_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_del_isr */
+
+/* 
+ *  割込み管理機能の初期化
+ */
+#ifdef TOPPERS_intini
+#ifndef OMIT_INITIALIZE_INTERRUPT
+
+void
+initialize_interrupt(void)
+{
+	uint_t			i;
+	const INHINIB	*p_inhinib;
+	const INTINIB	*p_intinib;
+
+	for (i = 0; i < tnum_inhno; i++) {
+		p_inhinib = &(inhinib_table[i]);
+		x_define_inh(p_inhinib->inhno, p_inhinib->int_entry);
+	}
+	for (i = 0; i < tnum_intno; i++) {
+		p_intinib = &(intinib_table[i]);
+		x_config_int(p_intinib->intno, p_intinib->intatr, p_intinib->intpri);
+	}
+}
+
+#endif /* OMIT_INITIALIZE_INTERRUPT */
+#endif /* TOPPERS_intini */
+
+/*
+ *  割込みの禁止
+ */
+#ifdef TOPPERS_dis_int
+#ifdef TOPPERS_SUPPORT_DIS_INT
+
+ER
+dis_int(INTNO intno)
+{
+	bool_t	locked;
+	ER		ercd;
+
+	LOG_DIS_INT_ENTER(intno);
+	CHECK_TSKCTX();
+	CHECK_INTNO_DISINT(intno);
+
+	locked = t_sense_lock();
+	if (!locked) {
+		t_lock_cpu();
+	}
+	if (t_disable_int(intno)) {
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_OBJ;
+	}
+	if (!locked) {
+		t_unlock_cpu();
+	}
+
+  error_exit:
+	LOG_DIS_INT_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_SUPPORT_DIS_INT */
+#endif /* TOPPERS_dis_int */
+
+/*
+ *  割込みの許可
+ */
+#ifdef TOPPERS_ena_int
+#ifdef TOPPERS_SUPPORT_ENA_INT
+
+ER
+ena_int(INTNO intno)
+{
+	bool_t	locked;
+	ER		ercd;
+
+	LOG_ENA_INT_ENTER(intno);
+	CHECK_TSKCTX();
+	CHECK_INTNO_DISINT(intno);
+
+	locked = t_sense_lock();
+	if (!locked) {
+		t_lock_cpu();
+	}
+	if (t_enable_int(intno)) {
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_OBJ;
+	}
+	if (!locked) {
+		t_unlock_cpu();
+	}
+
+  error_exit:
+	LOG_ENA_INT_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_SUPPORT_ENA_INT */
+#endif /* TOPPERS_ena_int */
+
+/*
+ *  割込み優先度マスクの変更
+ */
+#ifdef TOPPERS_chg_ipm
+
+ER
+chg_ipm(PRI intpri)
+{
+	ER		ercd;
+
+	LOG_CHG_IPM_ENTER(intpri);
+	CHECK_TSKCTX_UNL();
+	CHECK_INTPRI_CHGIPM(intpri);
+
+	t_lock_cpu();
+	t_set_ipm(intpri);
+	if (intpri == TIPM_ENAALL) {
+		ipmflg = true;
+		if (!disdsp) {
+			dspflg = true;
+			if (p_runtsk != p_schedtsk) {
+				dispatch();
+			}
+		}
+		if (p_runtsk->enatex && p_runtsk->texptn != 0U) {
+			call_texrtn();
+		}
+	}
+	else {
+		ipmflg = false;
+		dspflg = false;
+	}
+	ercd = E_OK;
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_CHG_IPM_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_chg_ipm */
+
+/*
+ *  割込み優先度マスクの参照
+ */
+#ifdef TOPPERS_get_ipm
+
+ER
+get_ipm(PRI *p_intpri)
+{
+	ER		ercd;
+
+	LOG_GET_IPM_ENTER(p_intpri);
+	CHECK_TSKCTX_UNL();
+
+	t_lock_cpu();
+	*p_intpri = t_get_ipm();
+	ercd = E_OK;
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_GET_IPM_LEAVE(ercd, *p_intpri);
+	return(ercd);
+}
+
+#endif /* TOPPERS_get_ipm */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/interrupt.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/interrupt.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/interrupt.h	(revision 453)
@@ -0,0 +1,186 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		割込み管理機能
+ */
+
+#ifndef TOPPERS_INTERRUPT_H
+#define TOPPERS_INTERRUPT_H
+
+#include <queue.h>
+
+/*
+ *  割込みサービスルーチン初期化ブロック
+ */
+typedef struct isr_initialization_block {
+	ATR			isratr;			/* 割込みサービスルーチン属性 */
+	intptr_t	exinf;			/* 割込みサービスルーチンの拡張情報 */
+	INTNO		intno;			/* 割込みサービスルーチンを登録する割込み番号 */
+	QUEUE		*p_isr_queue;	/* 登録先割込みサービスルーチンキューの番地 */
+	ISR			isr;			/* 割込みサービスルーチンの先頭番地 */
+	PRI			isrpri;			/* 割込みサービスルーチン優先度 */
+} ISRINIB;
+
+/*
+ *  割込みサービスルーチン管理ブロック
+ */
+typedef struct isr_control_block {
+	QUEUE		isr_queue;		/* 割込みサービスルーチン呼出しキュー */
+	const ISRINIB *p_isrinib;	/* 初期化ブロックへのポインタ */
+} ISRCB;
+
+/*
+ *  割込みサービスルーチン呼出しキューを検索するためのデータ構造
+ */
+typedef struct {
+	INTNO		intno;			/* 割込み番号 */
+	QUEUE		*p_isr_queue;	/* 割込みサービスルーチン呼出しキュー */
+} ISR_ENTRY;
+
+/*
+ *  割込みサービスルーチンキューのエントリ数（kernel_cfg.c）
+ */
+extern const uint_t tnum_isr_queue;
+
+/*
+ *  割込みサービスルーチンキューリスト（kernel_cfg.c）
+ */
+extern const ISR_ENTRY isr_queue_list[];
+
+/*
+ *  割込みサービスルーチンキューのエリア（kernel_cfg.c）
+ */
+extern QUEUE isr_queue_table[];
+
+/*
+ *  使用していない割込みサービスルーチン管理ブロックのリスト
+ */
+extern QUEUE	free_isrcb;
+
+/*
+ *  割込みサービスルーチンIDの最大値（kernel_cfg.c）
+ *
+ *  静的に生成される割込みサービスルーチンはID番号を持たないため，
+ *  tmax_isridは動的に生成される割込みサービスルーチンのID番号の最大値
+ *  である．静的に生成される割込みサービスルーチンの数は，tnum_sisrに保
+ *  持する．
+ */
+extern const ID		tmax_isrid;
+extern const uint_t	tnum_sisr;
+
+/*
+ *  割込みサービスルーチン初期化ブロックのエリア（kernel_cfg.c）
+ */
+extern const ISRINIB	sisrinib_table[];
+extern ISRINIB			aisrinib_table[];
+
+/*
+ *  割込みサービスルーチン管理ブロックのエリア（kernel_cfg.c）
+ */
+extern ISRCB	isrcb_table[];
+
+/*
+ *  割込みサービスルーチン管理ブロックから割込みサービスルーチンIDを取
+ *  り出すためのマクロ
+ */
+#define	ISRID(p_isrcb)	((ID)(((p_isrcb) - isrcb_table) \
+										- tnum_sisr + TMIN_ISRID))
+
+/*
+ *  割込みサービスルーチン機能の初期化
+ */
+extern void initialize_isr(void);
+
+/*
+ *  割込みサービスルーチンの呼出し
+ */
+extern void call_isr(QUEUE *p_isr_queue);
+
+#ifndef OMIT_INITIALIZE_INTERRUPT
+
+/*
+ *  割込みハンドラ初期化ブロック
+ */
+typedef struct interrupt_handler_initialization_block {
+	INHNO		inhno;			/* 割込みハンドラ番号 */
+	ATR			inhatr;			/* 割込みハンドラ属性 */
+	FP			int_entry;		/* 割込みハンドラの出入口処理の番地 */
+} INHINIB;
+
+/*
+ *  割込み要求ライン初期化ブロック
+ */
+typedef struct interrupt_request_initialization_block {
+	INTNO		intno;			/* 割込み番号 */
+	ATR			intatr;			/* 割込み属性 */
+	PRI			intpri;			/* 割込み優先度 */
+} INTINIB;
+
+/*
+ *  割込みハンドラ番号の数（kernel_cfg.c）
+ */
+extern const uint_t	tnum_inhno;
+
+/*
+ *  割込みハンドラ初期化ブロックのエリア（kernel_cfg.c）
+ */
+extern const INHINIB	inhinib_table[];
+
+/*
+ *  割込み要求ラインの数（kernel_cfg.c）
+ */
+extern const uint_t	tnum_intno;
+
+/*
+ *  割込み要求ライン初期化ブロックのエリア（kernel_cfg.c）
+ */
+extern const INTINIB	intinib_table[];
+
+#endif /* OMIT_INITIALIZE_INTERRUPT */
+
+/*
+ *  割込み管理機能の初期化
+ */
+extern void	initialize_interrupt(void);
+
+#endif /* TOPPERS_INTERRUPT_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/kernel.tf
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/kernel.tf	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/kernel.tf	(revision 453)
@@ -0,0 +1,1500 @@
+$ ======================================================================
+$ 
+$   TOPPERS/ASP Kernel
+$       Toyohashi Open Platform for Embedded Real-Time Systems/
+$       Advanced Standard Profile Kernel
+$ 
+$   Copyright (C) 2007 by TAKAGI Nobuhisa
+$   Copyright (C) 2007-2015 by Embedded and Real-Time Systems Laboratory
+$               Graduate School of Information Science, Nagoya Univ., JAPAN
+$  
+$   上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+$   ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+$   変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+$   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+$       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+$       スコード中に含まれていること．
+$   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+$       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+$       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+$       の無保証規定を掲載すること．
+$   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+$       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+$       と．
+$     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+$         作権表示，この利用条件および下記の無保証規定を掲載すること．
+$     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+$         報告すること．
+$   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+$       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+$       また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+$       由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+$       免責すること．
+$  
+$   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+$   よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+$   に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+$   アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+$   の責任を負わない．
+$ 
+$   $Id$
+$  
+$ =====================================================================
+
+$ =====================================================================
+$ AID_YYYの処理
+$ =====================================================================
+
+$num_atskid = 0$
+$FOREACH i ATSK.ORDER_LIST$
+$	// notskが負の場合（E_PAR）
+	$IF ATSK.NOTSK[i] < 0$
+		$ERROR ATSK.TEXT_LINE[i]$E_PAR: $FORMAT(_("illegal %1% `%2%\' in %3%"), "notsk", ATSK.NOTSK[i], "AID_TSK")$$END$
+	$END$
+	$num_atskid = num_atskid + ATSK.NOTSK[i]$
+$END$
+$num_tskid = LENGTH(TSK.ID_LIST) + num_atskid$
+
+$num_asemid = 0$
+$FOREACH i ASEM.ORDER_LIST$
+$	// nosemが負の場合（E_PAR）
+	$IF ASEM.NOSEM[i] < 0$
+		$ERROR ASEM.TEXT_LINE[i]$E_PAR: $FORMAT(_("illegal %1% `%2%\' in %3%"), "nosem", ASEM.NOSEM[i], "AID_SEM")$$END$
+	$END$
+	$num_asemid = num_asemid + ASEM.NOSEM[i]$
+$END$
+$num_semid = LENGTH(SEM.ID_LIST) + num_asemid$
+
+$num_aflgid = 0$
+$FOREACH i AFLG.ORDER_LIST$
+$	// noflgが負の場合（E_PAR）
+	$IF AFLG.NOFLG[i] < 0$
+		$ERROR AFLG.TEXT_LINE[i]$E_PAR: $FORMAT(_("illegal %1% `%2%\' in %3%"), "noflg", AFLG.NOFLG[i], "AID_FLG")$$END$
+	$END$
+	$num_aflgid = num_aflgid + AFLG.NOFLG[i]$
+$END$
+$num_flgid = LENGTH(FLG.ID_LIST) + num_aflgid$
+
+$num_adtqid = 0$
+$FOREACH i ADTQ.ORDER_LIST$
+$	// nodtqが負の場合（E_PAR）
+	$IF ADTQ.NODTQ[i] < 0$
+		$ERROR ADTQ.TEXT_LINE[i]$E_PAR: $FORMAT(_("illegal %1% `%2%\' in %3%"), "nodtq", ADTQ.NODTQ[i], "AID_DTQ")$$END$
+	$END$
+	$num_adtqid = num_adtqid + ADTQ.NODTQ[i]$
+$END$
+$num_dtqid = LENGTH(DTQ.ID_LIST) + num_adtqid$
+
+$num_apdqid = 0$
+$FOREACH i APDQ.ORDER_LIST$
+$	// nopdqが負の場合（E_PAR）
+	$IF APDQ.NOPDQ[i] < 0$
+		$ERROR APDQ.TEXT_LINE[i]$E_PAR: $FORMAT(_("illegal %1% `%2%\' in %3%"), "nopdq", APDQ.NOPDQ[i], "AID_PDQ")$$END$
+	$END$
+	$num_apdqid = num_apdqid + APDQ.NOPDQ[i]$
+$END$
+$num_pdqid = LENGTH(PDQ.ID_LIST) + num_apdqid$
+
+$num_ambxid = 0$
+$FOREACH i AMBX.ORDER_LIST$
+$	// nombxが負の場合（E_PAR）
+	$IF AMBX.NOMBX[i] < 0$
+		$ERROR AMBX.TEXT_LINE[i]$E_PAR: $FORMAT(_("illegal %1% `%2%\' in %3%"), "nombx", AMBX.NOMBX[i], "AID_MBX")$$END$
+	$END$
+	$num_ambxid = num_ambxid + AMBX.NOMBX[i]$
+$END$
+$num_mbxid = LENGTH(MBX.ID_LIST) + num_ambxid$
+
+$num_amtxid = 0$
+$FOREACH i AMTX.ORDER_LIST$
+$	// nomtxが負の場合（E_PAR）
+	$IF AMTX.NOMTX[i] < 0$
+		$ERROR AMTX.TEXT_LINE[i]$E_PAR: $FORMAT(_("illegal %1% `%2%\' in %3%"), "nomtx", AMTX.NOMTX[i], "AID_MTX")$$END$
+	$END$
+	$num_amtxid = num_amtxid + AMTX.NOMTX[i]$
+$END$
+$num_mtxid = LENGTH(MTX.ID_LIST) + num_amtxid$
+
+$num_ampfid = 0$
+$FOREACH i AMPF.ORDER_LIST$
+$	// nompfが負の場合（E_PAR）
+	$IF AMPF.NOMPF[i] < 0$
+		$ERROR AMPF.TEXT_LINE[i]$E_PAR: $FORMAT(_("illegal %1% `%2%\' in %3%"), "nompf", AMPF.NOMPF[i], "AID_MPF")$$END$
+	$END$
+	$num_ampfid = num_ampfid + AMPF.NOMPF[i]$
+$END$
+$num_mpfid = LENGTH(MPF.ID_LIST) + num_ampfid$
+
+$num_acycid = 0$
+$FOREACH i ACYC.ORDER_LIST$
+$	// nocycが負の場合（E_PAR）
+	$IF ACYC.NOCYC[i] < 0$
+		$ERROR ACYC.TEXT_LINE[i]$E_PAR: $FORMAT(_("illegal %1% `%2%\' in %3%"), "nocyc", ACYC.NOCYC[i], "AID_CYC")$$END$
+	$END$
+	$num_acycid = num_acycid + ACYC.NOCYC[i]$
+$END$
+$num_cycid = LENGTH(CYC.ID_LIST) + num_acycid$
+
+$num_aalmid = 0$
+$FOREACH i AALM.ORDER_LIST$
+$	// noalmが負の場合（E_PAR）
+	$IF AALM.NOALM[i] < 0$
+		$ERROR AALM.TEXT_LINE[i]$E_PAR: $FORMAT(_("illegal %1% `%2%\' in %3%"), "noalm", AALM.NOALM[i], "AID_ALM")$$END$
+	$END$
+	$num_aalmid = num_aalmid + AALM.NOALM[i]$
+$END$
+$num_almid = LENGTH(ALM.ID_LIST) + num_aalmid$
+
+$num_aisrid = 0$
+$FOREACH i AISR.ORDER_LIST$
+$	// noisrが負の場合（E_PAR）
+	$IF AISR.NOISR[i] < 0$
+		$ERROR AISR.TEXT_LINE[i]$E_PAR: $FORMAT(_("illegal %1% `%2%\' in %3%"), "noisr", AISR.NOISR[i], "AID_ISR")$$END$
+	$END$
+	$num_aisrid = num_aisrid + AISR.NOISR[i]$
+$END$
+$num_isrid = num_aisrid$
+$num_isr = LENGTH(ISR.ORDER_LIST) + num_aisrid$
+
+$ =====================================================================
+$ kernel_cfg.hの生成
+$ =====================================================================
+
+$FILE "kernel_cfg.h"$
+/* kernel_cfg.h */$NL$
+#ifndef TOPPERS_KERNEL_CFG_H$NL$
+#define TOPPERS_KERNEL_CFG_H$NL$
+$NL$
+#define TNUM_TSKID	$num_tskid$$NL$
+#define TNUM_SEMID	$num_semid$$NL$
+#define TNUM_FLGID	$num_flgid$$NL$
+#define TNUM_DTQID	$num_dtqid$$NL$
+#define TNUM_PDQID	$num_pdqid$$NL$
+#define TNUM_MBXID	$num_mbxid$$NL$
+#define TNUM_MTXID	$num_mtxid$$NL$
+#define TNUM_MPFID	$num_mpfid$$NL$
+#define TNUM_CYCID	$num_cycid$$NL$
+#define TNUM_ALMID	$num_almid$$NL$
+#define TNUM_ISRID	$num_isrid$$NL$
+$NL$
+$FOREACH id TSK.ID_LIST$
+	#define $id$	$+id$$NL$
+$END$
+$FOREACH id SEM.ID_LIST$
+	#define $id$	$+id$$NL$
+$END$
+$FOREACH id FLG.ID_LIST$
+	#define $id$	$+id$$NL$
+$END$
+$FOREACH id DTQ.ID_LIST$
+	#define $id$	$+id$$NL$
+$END$
+$FOREACH id PDQ.ID_LIST$
+	#define $id$	$+id$$NL$
+$END$
+$FOREACH id MBX.ID_LIST$
+	#define $id$	$+id$$NL$
+$END$
+$FOREACH id MTX.ID_LIST$
+	#define $id$	$+id$$NL$
+$END$
+$FOREACH id MPF.ID_LIST$
+	#define $id$	$+id$$NL$
+$END$
+$FOREACH id CYC.ID_LIST$
+	#define $id$	$+id$$NL$
+$END$
+$FOREACH id ALM.ID_LIST$
+	#define $id$	$+id$$NL$
+$END$
+$NL$
+#endif /* TOPPERS_KERNEL_CFG_H */$NL$
+
+$ =====================================================================
+$ kernel_cfg.cの生成
+$ =====================================================================
+
+$FILE "kernel_cfg.c"$
+/* kernel_cfg.c */$NL$
+#include "kernel/kernel_int.h"$NL$
+#include "kernel_cfg.h"$NL$
+$NL$
+#if TKERNEL_PRID != 0x07u$NL$
+#error The kernel does not match this configuration file.$NL$
+#endif$NL$
+$NL$
+
+$ 
+$  インクルードディレクティブ（#include）
+$ 
+/*$NL$
+$SPC$*  Include Directives (#include)$NL$
+$SPC$*/$NL$
+$NL$
+$INCLUDES$
+$NL$
+
+$ 
+$  オブジェクトのID番号を保持する変数
+$ 
+$IF USE_EXTERNAL_ID$
+	/*$NL$
+	$SPC$*  Variables for Object ID$NL$
+	$SPC$*/$NL$
+	$NL$
+	$FOREACH id TSK.ID_LIST$
+		const ID $id$_id$SPC$=$SPC$$+id$;$NL$
+	$END$
+	$FOREACH id SEM.ID_LIST$
+		const ID $id$_id$SPC$=$SPC$$+id$;$NL$
+	$END$
+	$FOREACH id FLG.ID_LIST$
+		const ID $id$_id$SPC$=$SPC$$+id$;$NL$
+	$END$
+	$FOREACH id DTQ.ID_LIST$
+		const ID $id$_id$SPC$=$SPC$$+id$;$NL$
+	$END$
+	$FOREACH id PDQ.ID_LIST$
+		const ID $id$_id$SPC$=$SPC$$+id$;$NL$
+	$END$
+	$FOREACH id MBX.ID_LIST$
+		const ID $id$_id$SPC$=$SPC$$+id$;$NL$
+	$END$
+	$FOREACH id MTX.ID_LIST$
+		const ID $id$_id$SPC$=$SPC$$+id$;$NL$
+	$END$
+	$FOREACH id MPF.ID_LIST$
+		const ID $id$_id$SPC$=$SPC$$+id$;$NL$
+	$END$
+	$FOREACH id CYC.ID_LIST$
+		const ID $id$_id$SPC$=$SPC$$+id$;$NL$
+	$END$
+	$FOREACH id ALM.ID_LIST$
+		const ID $id$_id$SPC$=$SPC$$+id$;$NL$
+	$END$
+$END$
+
+$
+$  スタック領域の確保関数
+$
+$IF !ISFUNCTION("ALLOC_STACK")$
+$FUNCTION ALLOC_STACK$
+$	// 大きい方に丸めたサイズで確保する
+	/*static*/ STK_T $ARGV[1]$[COUNT_STK_T($ARGV[2]$)] __attribute__((section(".stack"),aligned(16)));$NL$
+	$RESULT = FORMAT("ROUND_STK_T(%1%)", ARGV[2])$
+$END$
+$END$
+
+$ 
+$  タスク
+$ 
+/*$NL$
+$SPC$*  Task Management Functions$NL$
+$SPC$*/$NL$
+$NL$
+
+$ 静的に生成されたタスクが1個以上存在することのチェック
+$IF !LENGTH(TSK.ID_LIST)$
+	$ERROR$$FORMAT(_("no task is registered"))$$END$
+$END$
+
+$ 静的に生成されたタスクの数
+#define TNUM_STSKID	$LENGTH(TSK.ID_LIST)$$NL$
+$NL$
+
+$ タスクID番号の最大値
+const ID _kernel_tmax_tskid = (TMIN_TSKID + TNUM_TSKID - 1);$NL$
+const ID _kernel_tmax_stskid = (TMIN_TSKID + TNUM_STSKID - 1);$NL$
+$NL$
+
+$ エラーチェック
+$FOREACH tskid TSK.ID_LIST$
+$	// tskatrが（［TA_ACT］）でない場合（E_RSATR）
+	$IF (TSK.TSKATR[tskid] & ~(TA_ACT|TARGET_TSKATR)) != 0$
+		$ERROR TSK.TEXT_LINE[tskid]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "tskatr", TSK.TSKATR[tskid], tskid, "CRE_TSK")$$END$
+	$END$
+
+$	// (TMIN_TPRI <= itskpri && itskpri <= TMAX_TPRI)でない場合（E_PAR）
+	$IF !(TMIN_TPRI <= TSK.ITSKPRI[tskid] && TSK.ITSKPRI[tskid] <= TMAX_TPRI)$
+		$ERROR TSK.TEXT_LINE[tskid]$E_PAR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "itskpri", TSK.ITSKPRI[tskid], tskid, "CRE_TSK")$$END$
+	$END$
+
+$ 	// texatrが（TA_NULL）でない場合（E_RSATR）
+	$IF LENGTH(TSK.TEXATR[tskid]) && TSK.TEXATR[tskid] != 0$
+		$ERROR DEF_TEX.TEXT_LINE[tskid]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "texatr", TSK.TEXATR[tskid], tskid, "DEF_TEX")$$END$
+	$END$
+$END$
+
+$ スタック領域の生成とそれに関するエラーチェック
+$FOREACH tskid TSK.ID_LIST$
+$	// stkszが0以下か，ターゲット定義の最小値（TARGET_MIN_STKSZ）よりも
+$	// 小さい場合（E_PAR）
+	$IF TSK.STKSZ[tskid] <= 0 || (TARGET_MIN_STKSZ
+									&& TSK.STKSZ[tskid] < TARGET_MIN_STKSZ)$
+		$ERROR TSK.TEXT_LINE[tskid]$E_PAR: $FORMAT(_("too small %1% `%2%\' of `%3%\' in %4%"), "stksz", TSK.STKSZ[tskid], tskid, "CRE_TSK")$$END$
+	$END$
+
+$ 	// stkszがスタック領域のサイズとして正しくない場合（E_PAR）
+	$IF !EQ(TSK.STK[tskid], "NULL") && CHECK_STKSZ_ALIGN
+							&& (TSK.STKSZ[tskid] & (CHECK_STKSZ_ALIGN - 1))$
+		$ERROR TSK.TEXT_LINE[tskid]$E_PAR: $FORMAT(_("%1% `%2%\' of `%3%\' in %4% is not aligned"), "stksz", TSK.STKSZ[tskid], tskid, "CRE_TSK")$$END$
+	$END$
+
+	$IF EQ(TSK.STK[tskid],"NULL")$
+		$TSK.TINIB_STKSZ[tskid] = ALLOC_STACK(CONCAT("_kernel_stack_",
+												tskid), TSK.STKSZ[tskid])$
+		$TSK.TINIB_STK[tskid] = CONCAT("_kernel_stack_", tskid)$
+	$ELSE$
+		$TSK.TINIB_STKSZ[tskid] = FORMAT("(%1%)", TSK.STKSZ[tskid])$
+		$TSK.TINIB_STK[tskid] = FORMAT("(void *)(%1%)", TSK.STK[tskid])$
+	$END$
+$END$
+$NL$
+
+$ タスク初期化ブロックの生成（タスクは1個以上存在する）
+const TINIB _kernel_tinib_table[TNUM_STSKID] = {$NL$
+$JOINEACH tskid TSK.ID_LIST ",\n"$
+$	// タスク属性，拡張情報，起動番地，起動時優先度
+	$TAB${
+	$SPC$($TSK.TSKATR[tskid]$), (intptr_t)($TSK.EXINF[tskid]$),
+	$SPC$((TASK)($TSK.TASK[tskid]$)), INT_PRIORITY($TSK.ITSKPRI[tskid]$),
+
+$	// タスク初期化コンテキストブロック，スタック領域
+	$IF USE_TSKINICTXB$
+		$GENERATE_TSKINICTXB(tskid)$
+	$ELSE$
+		$SPC$$TSK.TINIB_STKSZ[tskid]$, $TSK.TINIB_STK[tskid]$,
+	$END$
+
+$	// タスク例外処理ルーチンの属性と起動番地
+	$SPC$($ALT(TSK.TEXATR[tskid],"TA_NULL")$), ($ALT(TSK.TEXRTN[tskid],"NULL")$) }
+$END$$NL$
+};$NL$
+$NL$
+
+$ 動的生成タスク用のタスク初期化ブロックの生成
+$IF num_atskid > 0$
+	TINIB _kernel_atinib_table[$num_atskid$];$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(TINIB, _kernel_atinib_table);$NL$
+$END$$NL$
+
+$ タスク管理ブロックの生成
+TCB _kernel_tcb_table[TNUM_TSKID];$NL$
+$NL$
+
+$ タスク生成順序テーブルの生成
+const ID _kernel_torder_table[TNUM_STSKID] = {$NL$
+$TAB$$JOINEACH tskid TSK.ORDER_LIST ", "$$tskid$$END$$NL$
+};$NL$
+$NL$
+
+$ 
+$  セマフォ
+$ 
+/*$NL$
+$SPC$*  Semaphore Functions$NL$
+$SPC$*/$NL$
+$NL$
+
+$ 静的に生成されたセマフォの数
+#define TNUM_SSEMID	$LENGTH(SEM.ID_LIST)$$NL$
+$NL$
+
+$ セマフォID番号の最大値
+const ID _kernel_tmax_semid = (TMIN_SEMID + TNUM_SEMID - 1);$NL$
+const ID _kernel_tmax_ssemid = (TMIN_SEMID + TNUM_SSEMID - 1);$NL$
+$NL$
+
+$ セマフォ初期化ブロックの生成
+$IF LENGTH(SEM.ID_LIST)$
+	const SEMINIB _kernel_seminib_table[TNUM_SSEMID] = {$NL$
+	$JOINEACH semid SEM.ID_LIST ",\n"$
+$		// sematrが（［TA_TPRI］）でない場合（E_RSATR）
+		$IF (SEM.SEMATR[semid] & ~TA_TPRI) != 0$
+			$ERROR SEM.TEXT_LINE[semid]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "sematr", SEM.SEMATR[semid], semid, "CRE_SEM")$$END$
+		$END$
+
+$		// (0 <= isemcnt && isemcnt <= maxsem)でない場合（E_PAR）
+		$IF !(0 <= SEM.ISEMCNT[semid] && SEM.ISEMCNT[semid] <= SEM.MAXSEM[semid])$
+			$ERROR SEM.TEXT_LINE[semid]$E_PAR: $FORMAT(_("too large %1% `%2%\' of `%3%\' in %4%"), "isemcnt", SEM.ISEMCNT[semid], semid, "CRE_SEM")$$END$
+		$END$
+
+$		// (1 <= maxsem && maxsem <= TMAX_MAXSEM)でない場合（E_PAR）
+		$IF !(1 <= SEM.MAXSEM[semid] && SEM.MAXSEM[semid] <= TMAX_MAXSEM)$
+			$ERROR SEM.TEXT_LINE[semid]$E_PAR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "maxsem", SEM.MAXSEM[semid], semid, "CRE_SEM")$$END$
+		$END$
+
+$		// セマフォ初期化ブロック
+		$TAB${ ($SEM.SEMATR[semid]$), ($SEM.ISEMCNT[semid]$), ($SEM.MAXSEM[semid]$) }
+	$END$$NL$
+	};$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(const SEMINIB, _kernel_seminib_table);$NL$
+$END$$NL$
+
+$ 動的生成セマフォ用のセマフォ初期化ブロックの生成
+$IF num_asemid > 0$
+	SEMINIB _kernel_aseminib_table[$num_asemid$];$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(SEMINIB, _kernel_aseminib_table);$NL$
+$END$$NL$
+
+$ セマフォ管理ブロックの生成
+$IF num_semid > 0$
+	SEMCB _kernel_semcb_table[TNUM_SEMID];$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(SEMCB, _kernel_semcb_table);$NL$
+$END$$NL$
+
+$ 
+$  イベントフラグ
+$ 
+/*$NL$
+$SPC$*  Eventflag Functions$NL$
+$SPC$*/$NL$
+$NL$
+
+$ 静的に生成されたイベントフラグの数
+#define TNUM_SFLGID	$LENGTH(FLG.ID_LIST)$$NL$
+$NL$
+
+$ イベントフラグID番号の最大値
+const ID _kernel_tmax_flgid = (TMIN_FLGID + TNUM_FLGID - 1);$NL$
+const ID _kernel_tmax_sflgid = (TMIN_FLGID + TNUM_SFLGID - 1);$NL$
+$NL$
+
+$ イベントフラグ初期化ブロックの生成
+$IF LENGTH(FLG.ID_LIST)$
+	const FLGINIB _kernel_flginib_table[TNUM_SFLGID] = {$NL$
+	$JOINEACH flgid FLG.ID_LIST ",\n"$
+$		// flgatrが（［TA_TPRI］｜［TA_WMUL］｜［TA_CLR］）でない場合（E_RSATR）
+		$IF (FLG.FLGATR[flgid] & ~(TA_TPRI|TA_WMUL|TA_CLR)) != 0$
+			$ERROR FLG.TEXT_LINE[flgid]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "flgatr", FLG.FLGATR[flgid], flgid, "CRE_FLG")$$END$
+		$END$
+
+$		// iflgptnがFLGPTNに格納できない場合（E_PAR）
+		$IF (FLG.IFLGPTN[flgid] & ~((1 << TBIT_FLGPTN) - 1)) != 0$
+			$ERROR FLG.TEXT_LINE[flgid]$E_PAR: $FORMAT(_("too large %1% `%2%\' of `%3%\' in %4%"), "iflgptn", FLG.IFLGPTN[flgid], flgid, "CRE_FLG")$$END$
+		$END$
+
+$		// イベントフラグ初期化ブロック
+		$TAB${ ($FLG.FLGATR[flgid]$), ($FLG.IFLGPTN[flgid]$) }
+	$END$$NL$
+	};$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(const FLGINIB, _kernel_flginib_table);$NL$
+$END$$NL$
+
+$ 動的生成イベントフラグ用のイベントフラグ初期化ブロックの生成
+$IF num_aflgid > 0$
+	FLGINIB _kernel_aflginib_table[$num_aflgid$];$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(FLGINIB, _kernel_aflginib_table);$NL$
+$END$$NL$
+
+$ イベントフラグ管理ブロックの生成
+$IF num_flgid > 0$
+	FLGCB _kernel_flgcb_table[TNUM_FLGID];$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(FLGCB, _kernel_flgcb_table);$NL$
+$END$$NL$
+
+$ 
+$  データキュー
+$ 
+/*$NL$
+$SPC$*  Dataqueue Functions$NL$
+$SPC$*/$NL$
+$NL$
+
+$ 静的に生成されたデータキューの数
+#define TNUM_SDTQID	$LENGTH(DTQ.ID_LIST)$$NL$
+$NL$
+
+$ データキューID番号の最大値
+const ID _kernel_tmax_dtqid = (TMIN_DTQID + TNUM_DTQID - 1);$NL$
+const ID _kernel_tmax_sdtqid = (TMIN_DTQID + TNUM_SDTQID - 1);$NL$
+$NL$
+
+$IF LENGTH(DTQ.ID_LIST)$
+	$FOREACH dtqid DTQ.ID_LIST$
+$		// dtqatrが（［TA_TPRI］）でない場合（E_RSATR）
+		$IF (DTQ.DTQATR[dtqid] & ~TA_TPRI) != 0$
+			$ERROR DTQ.TEXT_LINE[dtqid]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "dtqatr", DTQ.DTQATR[dtqid], dtqid, "CRE_DTQ")$$END$
+		$END$
+
+$		// dtqcntが負の場合（E_PAR）
+		$IF DTQ.DTQCNT[dtqid] < 0$
+			$ERROR DTQ.TEXT_LINE[dtqid]$E_PAR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "dtqcnt", DTQ.DTQCNT[dtqid], dtqid, "CRE_DTQ")$$END$
+		$END$
+
+$		// dtqmbがNULLでない場合（E_NOSPT）
+		$IF !EQ(DTQ.DTQMB[dtqid], "NULL")$
+			$ERROR DTQ.TEXT_LINE[dtqid]$E_NOSPT: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "dtqmb", DTQ.DTQMB[dtqid], dtqid, "CRE_DTQ")$$END$
+		$END$
+
+$		// データキュー管理領域
+		$IF DTQ.DTQCNT[dtqid]$
+			static DTQMB _kernel_dtqmb_$dtqid$[$DTQ.DTQCNT[dtqid]$];$NL$
+		$END$
+	$END$
+
+$	// データキュー初期化ブロックの生成
+	const DTQINIB _kernel_dtqinib_table[TNUM_SDTQID] = {$NL$
+	$JOINEACH dtqid DTQ.ID_LIST ",\n"$
+		$TAB${ ($DTQ.DTQATR[dtqid]$), ($DTQ.DTQCNT[dtqid]$), $IF DTQ.DTQCNT[dtqid]$(_kernel_dtqmb_$dtqid$)$ELSE$NULL$END$ }
+	$END$$NL$
+	};$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(const DTQINIB, _kernel_dtqinib_table);$NL$
+$END$$NL$
+
+$ 動的生成データキュー用のデータキュー初期化ブロックの生成
+$IF num_adtqid > 0$
+	DTQINIB _kernel_adtqinib_table[$num_adtqid$];$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(DTQINIB, _kernel_adtqinib_table);$NL$
+$END$$NL$
+
+$ データキュー管理ブロックの生成
+$IF num_dtqid > 0$
+	DTQCB _kernel_dtqcb_table[TNUM_DTQID];$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(DTQCB, _kernel_dtqcb_table);$NL$
+$END$$NL$
+
+$ 
+$  優先度データキュー
+$ 
+/*$NL$
+$SPC$*  Priority Dataqueue Functions$NL$
+$SPC$*/$NL$
+$NL$
+
+$ 静的に生成された優先度データキューの数
+#define TNUM_SPDQID	$LENGTH(PDQ.ID_LIST)$$NL$
+$NL$
+
+$ 優先度データキューID番号の最大値
+const ID _kernel_tmax_pdqid = (TMIN_PDQID + TNUM_PDQID - 1);$NL$
+const ID _kernel_tmax_spdqid = (TMIN_PDQID + TNUM_SPDQID - 1);$NL$
+$NL$
+
+$IF LENGTH(PDQ.ID_LIST)$
+	$FOREACH pdqid PDQ.ID_LIST$
+$		// pdqatrが（［TA_TPRI］）でない場合（E_RSATR）
+		$IF (PDQ.PDQATR[pdqid] & ~TA_TPRI) != 0$
+			$ERROR PDQ.TEXT_LINE[pdqid]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "pdqatr", PDQ.PDQATR[pdqid], pdqid, "CRE_PDQ")$$END$
+		$END$
+
+$		// pdqcntが負の場合（E_PAR）
+		$IF PDQ.PDQCNT[pdqid] < 0$
+			$ERROR PDQ.TEXT_LINE[pdqid]$E_PAR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "pdqcnt", PDQ.PDQCNT[pdqid], pdqid, "CRE_PDQ")$$END$
+		$END$
+
+$		// (TMIN_DPRI <= maxdpri && maxdpri <= TMAX_DPRI)でない場合（E_PAR）
+		$IF !(TMIN_DPRI <= PDQ.MAXDPRI[pdqid] && PDQ.MAXDPRI[pdqid] <= TMAX_DPRI)$
+			$ERROR PDQ.TEXT_LINE[pdqid]$E_PAR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "maxdpri", PDQ.MAXDPRI[pdqid], pdqid, "CRE_PDQ")$$END$
+		$END$
+
+$		// pdqmbがNULLでない場合（E_NOSPT）
+		$IF !EQ(PDQ.PDQMB[pdqid], "NULL")$
+			$ERROR PDQ.TEXT_LINE[pdqid]$E_NOSPT: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "pdqmb", PDQ.PDQMB[pdqid], pdqid, "CRE_PDQ")$$END$
+		$END$
+
+$		// 優先度データキュー管理領域
+		$IF PDQ.PDQCNT[pdqid]$
+			static PDQMB _kernel_pdqmb_$pdqid$[$PDQ.PDQCNT[pdqid]$];$NL$
+		$END$
+	$END$
+
+$	// 優先度データキュー初期化ブロックの生成
+	const PDQINIB _kernel_pdqinib_table[TNUM_SPDQID] = {$NL$
+	$JOINEACH pdqid PDQ.ID_LIST ",\n"$
+		$TAB${ ($PDQ.PDQATR[pdqid]$), ($PDQ.PDQCNT[pdqid]$), ($PDQ.MAXDPRI[pdqid]$), $IF PDQ.PDQCNT[pdqid]$(_kernel_pdqmb_$pdqid$)$ELSE$NULL$END$ }
+	$END$$NL$
+	};$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(const PDQINIB, _kernel_pdqinib_table);$NL$
+$END$$NL$
+
+$ 動的生成優先度データキュー用の優先度データキュー初期化ブロックの生成
+$IF num_apdqid > 0$
+	PDQINIB _kernel_apdqinib_table[$num_apdqid$];$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(PDQINIB, _kernel_apdqinib_table);$NL$
+$END$$NL$
+
+$ 優先度データキュー管理ブロックの生成
+$IF num_pdqid > 0$
+	PDQCB _kernel_pdqcb_table[TNUM_PDQID];$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(PDQCB, _kernel_pdqcb_table);$NL$
+$END$$NL$
+
+$ 
+$  メールボックス
+$ 
+/*$NL$
+$SPC$*  Mailbox Functions$NL$
+$SPC$*/$NL$
+$NL$
+
+$ 静的に生成されたメールボックスの数
+#define TNUM_SMBXID	$LENGTH(MBX.ID_LIST)$$NL$
+$NL$
+
+$ メールボックスID番号の最大値
+const ID _kernel_tmax_mbxid = (TMIN_MBXID + TNUM_MBXID - 1);$NL$
+const ID _kernel_tmax_smbxid = (TMIN_MBXID + TNUM_SMBXID - 1);$NL$
+$NL$
+
+$ メールボックス初期化ブロックの生成
+$IF LENGTH(MBX.ID_LIST)$
+	const MBXINIB _kernel_mbxinib_table[TNUM_SMBXID] = {$NL$
+	$JOINEACH mbxid MBX.ID_LIST ",\n"$
+$		// mbxatrが（［TA_TPRI］｜［TA_MPRI］）でない場合（E_RSATR）
+		$IF (MBX.MBXATR[mbxid] & ~(TA_TPRI|TA_MPRI)) != 0$
+			$ERROR MBX.TEXT_LINE[mbxid]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "mbxatr", MBX.MBXATR[mbxid], mbxid, "CRE_MBX")$$END$
+		$END$
+
+$		// (TMIN_MPRI <= maxmpri && maxmpri <= TMAX_MPRI)でない場合（E_PAR）
+		$IF !(TMIN_MPRI <= MBX.MAXMPRI[mbxid] && MBX.MAXMPRI[mbxid] <= TMAX_MPRI)$
+			$ERROR MBX.TEXT_LINE[mbxid]$E_PAR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "maxmpri", MBX.MAXMPRI[mbxid], mbxid, "CRE_MBX")$$END$
+		$END$
+
+$		// mprihdがNULLでない場合（E_NOSPT）
+		$IF !EQ(MBX.MPRIHD[mbxid], "NULL")$
+			$ERROR MBX.TEXT_LINE[mbxid]$E_NOSPT: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "mprihd", MBX.MPRIHD[mbxid], mbxid, "CRE_MBX")$$END$
+		$END$
+
+$		// メールボックス初期化ブロック
+		$TAB${ ($MBX.MBXATR[mbxid]$), ($MBX.MAXMPRI[mbxid]$) }
+	$END$$NL$
+	};$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(const MBXINIB, _kernel_mbxinib_table);$NL$
+$END$$NL$
+
+$ 動的生成メールボックス用のメールボックス初期化ブロックの生成
+$IF num_ambxid > 0$
+	MBXINIB _kernel_ambxinib_table[$num_ambxid$];$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(MBXINIB, _kernel_ambxinib_table);$NL$
+$END$$NL$
+
+$ メールボックス管理ブロックの生成
+$IF num_mbxid > 0$
+	MBXCB _kernel_mbxcb_table[TNUM_MBXID];$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(MBXCB, _kernel_mbxcb_table);$NL$
+$END$$NL$
+
+$ 
+$  ミューテックス
+$ 
+/*$NL$
+$SPC$*  Mutex Functions$NL$
+$SPC$*/$NL$
+$NL$
+
+$ 静的に生成されたミューテックスの数
+#define TNUM_SMTXID	$LENGTH(MTX.ID_LIST)$$NL$
+$NL$
+
+$ ミューテックスID番号の最大値
+const ID _kernel_tmax_mtxid = (TMIN_MTXID + TNUM_MTXID - 1);$NL$
+const ID _kernel_tmax_smtxid = (TMIN_MTXID + TNUM_SMTXID - 1);$NL$
+$NL$
+
+$ ミューテックス初期化ブロックの生成
+$IF LENGTH(MTX.ID_LIST)$
+	const MTXINIB _kernel_mtxinib_table[TNUM_SMTXID] = {$NL$
+	$JOINEACH mtxid MTX.ID_LIST ",\n"$
+$		// mtxatrが（［TA_TPRI｜TA_CEILING］）でない場合（E_RSATR）
+		$IF !(MTX.MTXATR[mtxid] == 0 || MTX.MTXATR[mtxid] == TA_TPRI || MTX.MTXATR[mtxid] == TA_CEILING)$
+			$ERROR MTX.TEXT_LINE[mtxid]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "mtxatr", MTX.MTXATR[mtxid], mtxid, "CRE_MTX")$$END$
+		$END$
+
+$		// ceilpriが未指定の場合は0と見なす
+		$IF !LENGTH(MTX.CEILPRI[mtxid])$
+			$MTX.CEILPRI[mtxid] = 0$
+		$END$
+$		// (TMIN_TPRI <= ceilpri && ceilpri <= TMAX_TPRI)でない場合（E_PAR）
+		$IF MTX.MTXATR[mtxid] == TA_CEILING && (MTX.CEILPRI[mtxid] < TMIN_TPRI || TMAX_TPRI < MTX.CEILPRI[mtxid])$
+			$ERROR MTX.TEXT_LINE[mtxid]$E_PAR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "ceilpri", MTX.CEILPRI[mtxid], mtxid, "CRE_MTX")$$END$
+		$END$
+
+$		// ミューテックス初期化ブロック
+		$TAB${ ($MTX.MTXATR[mtxid]$), INT_PRIORITY($MTX.CEILPRI[mtxid]$) }
+	$END$$NL$
+	};$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(const MTXINIB, _kernel_mtxinib_table);$NL$
+$END$$NL$
+
+$ 動的生成ミューテックス用のミューテックス初期化ブロックの生成
+$IF num_amtxid > 0$
+	MTXINIB _kernel_amtxinib_table[$num_amtxid$];$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(MTXINIB, _kernel_amtxinib_table);$NL$
+$END$$NL$
+
+$ ミューテックス管理ブロックの生成
+$IF num_mtxid > 0$
+	MTXCB _kernel_mtxcb_table[TNUM_MTXID];$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(MTXCB, _kernel_mtxcb_table);$NL$
+$END$$NL$
+
+$ 
+$  固定長メモリプール
+$ 
+/*$NL$
+$SPC$*  Fixed-sized Memorypool Functions$NL$
+$SPC$*/$NL$
+$NL$
+
+$ 静的に生成された固定長メモリプールの数
+#define TNUM_SMPFID	$LENGTH(MPF.ID_LIST)$$NL$
+$NL$
+
+$ 固定長メモリプールID番号の最大値
+const ID _kernel_tmax_mpfid = (TMIN_MPFID + TNUM_MPFID - 1);$NL$
+const ID _kernel_tmax_smpfid = (TMIN_MPFID + TNUM_SMPFID - 1);$NL$
+$NL$
+
+$IF LENGTH(MPF.ID_LIST)$
+	$FOREACH mpfid MPF.ID_LIST$
+$		// mpfatrが（［TA_TPRI］）でない場合（E_RSATR）
+		$IF (MPF.MPFATR[mpfid] & ~TA_TPRI) != 0$
+			$ERROR MPF.TEXT_LINE[mpfid]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "mpfatr", MPF.MPFATR[mpfid], mpfid, "CRE_MPF")$$END$
+		$END$
+
+$		// blkcntが0以下の場合（E_PAR）
+		$IF MPF.BLKCNT[mpfid] <= 0$
+			$ERROR MPF.TEXT_LINE[mpfid]$E_PAR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "blkcnt", MPF.BLKCNT[mpfid], mpfid, "CRE_MPF")$$END$
+		$END$
+
+$		// blkszが0以下の場合（E_PAR）
+		$IF MPF.BLKSZ[mpfid] <= 0$
+			$ERROR MPF.TEXT_LINE[mpfid]$E_PAR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "blksz", MPF.BLKSZ[mpfid], mpfid, "CRE_MPF")$$END$
+		$END$
+
+$		// 固定長メモリプール領域
+		$IF EQ(MPF.MPF[mpfid], "NULL")$
+			static MPF_T _kernel_mpf_$mpfid$[($MPF.BLKCNT[mpfid]$) * COUNT_MPF_T($MPF.BLKSZ[mpfid]$)];$NL$
+		$END$
+
+$		// mpfmbがNULLでない場合（E_NOSPT）
+		$IF !EQ(MPF.MPFMB[mpfid], "NULL")$
+			$ERROR MPF.TEXT_LINE[mpfid]$E_NOSPT: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "mpfmb", MPF.MPFMB[mpfid], mpfid, "CRE_MPF")$$END$
+		$END$
+
+$		// 固定長メモリプール管理領域
+		static MPFMB _kernel_mpfmb_$mpfid$[$MPF.BLKCNT[mpfid]$];$NL$
+	$END$
+
+$	// 固定長メモリプール初期化ブロックの生成
+	const MPFINIB _kernel_mpfinib_table[TNUM_SMPFID] = {$NL$
+	$JOINEACH mpfid MPF.ID_LIST ",\n"$
+		$TAB${ ($MPF.MPFATR[mpfid]$), ($MPF.BLKCNT[mpfid]$), ROUND_MPF_T($MPF.BLKSZ[mpfid]$), $IF EQ(MPF.MPF[mpfid],"NULL")$(_kernel_mpf_$mpfid$)$ELSE$(void *)($MPF.MPF[mpfid]$)$END$, (_kernel_mpfmb_$mpfid$) }
+	$END$$NL$
+	};$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(const MPFINIB, _kernel_mpfinib_table);$NL$
+$END$$NL$
+
+$ 動的生成固定長メモリプール用の固定長メモリプール初期化ブロックの生成
+$IF num_ampfid > 0$
+	MPFINIB _kernel_ampfinib_table[$num_ampfid$];$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(MPFINIB, _kernel_ampfinib_table);$NL$
+$END$$NL$
+
+$ 固定長メモリプール管理ブロックの生成
+$IF num_mpfid > 0$
+	MPFCB _kernel_mpfcb_table[TNUM_MPFID];$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(MPFCB, _kernel_mpfcb_table);$NL$
+$END$$NL$
+
+$ 
+$  周期ハンドラ
+$ 
+/*$NL$
+$SPC$*  Cyclic Handler Functions$NL$
+$SPC$*/$NL$
+$NL$
+
+$ 静的に生成された周期ハンドラの数
+#define TNUM_SCYCID	$LENGTH(CYC.ID_LIST)$$NL$
+$NL$
+
+$ 周期ハンドラID番号の最大値
+const ID _kernel_tmax_cycid = (TMIN_CYCID + TNUM_CYCID - 1);$NL$
+const ID _kernel_tmax_scycid = (TMIN_CYCID + TNUM_SCYCID - 1);$NL$
+$NL$
+
+$ 周期ハンドラ初期化ブロックの生成
+$IF LENGTH(CYC.ID_LIST)$
+	const CYCINIB _kernel_cycinib_table[TNUM_SCYCID] = {$NL$
+	$JOINEACH cycid CYC.ID_LIST ",\n"$
+$		// cycatrが（［TA_STA］）でない場合（E_RSATR）
+		$IF (CYC.CYCATR[cycid] & ~TA_STA) != 0$
+			$ERROR CYC.TEXT_LINE[cycid]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "cycatr", CYC.CYCATR[cycid], cycid, "CRE_CYC")$$END$
+		$END$
+
+$		// (0 < cyctim && cyctim <= TMAX_RELTIM)でない場合（E_PAR）
+		$IF !(0 < CYC.CYCTIM[cycid] && CYC.CYCTIM[cycid] <= TMAX_RELTIM)$
+			$ERROR CYC.TEXT_LINE[cycid]$E_PAR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "cyctim", CYC.CYCTIM[cycid], cycid, "CRE_CYC")$$END$
+		$END$
+
+$		// (0 <= cycphs && cycphs <= TMAX_RELTIM)でない場合（E_PAR）
+		$IF !(0 <= CYC.CYCPHS[cycid] && CYC.CYCPHS[cycid] <= TMAX_RELTIM)$
+			$ERROR CYC.TEXT_LINE[cycid]$E_PAR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "cycphs", CYC.CYCPHS[cycid], cycid, "CRE_CYC")$$END$
+		$END$
+
+$		// 警告：cycatrにTA_STAが設定されていて，(cycphs == 0)の場合
+		$IF (CYC.CYCATR[cycid] & TA_STA) != 0 && CYC.CYCPHS[cycid] == 0$
+			$WARNING CYC.TEXT_LINE[cycid]$$FORMAT(_("%1% is not recommended when %2% is set to %3% in %4%"), "cycphs==0", "TA_STA", "cycatr", "CRE_CYC")$$END$
+		$END$
+
+$		// 周期ハンドラ初期化ブロック
+		$TAB${ ($CYC.CYCATR[cycid]$), (intptr_t)($CYC.EXINF[cycid]$), ($CYC.CYCHDR[cycid]$), ($CYC.CYCTIM[cycid]$), ($CYC.CYCPHS[cycid]$) }
+	$END$$NL$
+	};$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(const CYCINIB, _kernel_cycinib_table);$NL$
+$END$$NL$
+
+$ 動的生成周期ハンドラ用の周期ハンドラ初期化ブロックの生成
+$IF num_acycid > 0$
+	CYCINIB _kernel_acycinib_table[$num_acycid$];$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(CYCINIB, _kernel_acycinib_table);$NL$
+$END$$NL$
+
+$ 周期ハンドラ管理ブロックの生成
+$IF num_cycid > 0$
+	CYCCB _kernel_cyccb_table[TNUM_CYCID];$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(CYCCB, _kernel_cyccb_table);$NL$
+$END$$NL$
+
+$ 
+$  アラームハンドラ
+$ 
+/*$NL$
+$SPC$*  Alarm Handler Functions$NL$
+$SPC$*/$NL$
+$NL$
+
+$ 静的に生成されたアラームハンドラの数
+#define TNUM_SALMID	$LENGTH(ALM.ID_LIST)$$NL$
+$NL$
+
+$ アラームハンドラID番号の最大値
+const ID _kernel_tmax_almid = (TMIN_ALMID + TNUM_ALMID - 1);$NL$
+const ID _kernel_tmax_salmid = (TMIN_ALMID + TNUM_SALMID - 1);$NL$
+$NL$
+
+$ アラームハンドラ初期化ブロックの生成
+$IF LENGTH(ALM.ID_LIST)$
+	const ALMINIB _kernel_alminib_table[TNUM_SALMID] = {$NL$
+	$JOINEACH almid ALM.ID_LIST ",\n"$
+$		// almatrが（TA_NULL）でない場合（E_RSATR）
+		$IF ALM.ALMATR[almid] != 0$
+			$ERROR ALM.TEXT_LINE[almid]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "almatr", ALM.ALMATR[almid], almid, "CRE_ALM")$$END$
+		$END$
+
+$		// アラームハンドラ初期化ブロック
+		$TAB${ ($ALM.ALMATR[almid]$), (intptr_t)($ALM.EXINF[almid]$), ($ALM.ALMHDR[almid]$) }
+	$END$$NL$
+	};$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(const ALMINIB, _kernel_alminib_table);$NL$
+$END$$NL$
+
+$ 動的生成アラームハンドラ用のアラームハンドラ初期化ブロックの生成
+$IF num_aalmid > 0$
+	ALMINIB _kernel_aalminib_table[$num_aalmid$];$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(ALMINIB, _kernel_aalminib_table);$NL$
+$END$$NL$
+
+$ アラームハンドラ管理ブロックの生成
+$IF num_almid > 0$
+	ALMCB _kernel_almcb_table[TNUM_ALMID];$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(ALMCB, _kernel_almcb_table);$NL$
+$END$$NL$
+
+$ 
+$  割込み管理機能
+$ 
+/*$NL$
+$SPC$*  Interrupt Management Functions$NL$
+$SPC$*/$NL$
+$NL$
+
+$ 割込み番号と割込みハンドラ番号の変換テーブルの作成
+$IF LENGTH(INTNO_ATTISR_VALID) != LENGTH(INHNO_ATTISR_VALID)$
+	$ERROR$length of `INTNO_ATTISR_VALID' is different from length of `INHNO_ATTISR_VALID'$END$
+$END$
+$i = 0$
+$FOREACH intno INTNO_ATTISR_VALID$
+	$inhno = AT(INHNO_ATTISR_VALID, i)$
+	$INHNO[intno] = inhno$
+	$INTNO[inhno] = intno$
+	$i = i + 1$
+$END$
+
+$ 割込み要求ラインに関するエラーチェック
+$i = 0$
+$FOREACH intno INT.ORDER_LIST$
+$	// intnoがCFG_INTに対する割込み番号として正しくない場合（E_PAR）
+	$IF !LENGTH(FIND(INTNO_CFGINT_VALID, INT.INTNO[intno]))$
+		$ERROR INT.TEXT_LINE[intno]$E_PAR: $FORMAT(_("illegal %1% `%2%\' in %3%"), "intno", INT.INTNO[intno], "CFG_INT")$$END$
+	$END$
+
+$	// intnoがCFG_INTによって設定済みの場合（E_OBJ）
+	$j = 0$
+	$FOREACH intno2 INT.ORDER_LIST$
+		$IF j < i && INT.INTNO[intno] == INT.INTNO[intno2]$
+			$ERROR INT.TEXT_LINE[intno]$E_OBJ: $FORMAT(_("%1% `%2%\' in %3% is duplicated"), "intno", INT.INTNO[intno], "CFG_INT")$$END$
+		$END$
+		$j = j + 1$
+	$END$
+
+$	// intatrが（［TA_ENAINT］｜［TA_EDGE］）でない場合（E_RSATR）
+	$IF (INT.INTATR[intno] & ~(TA_ENAINT|TA_EDGE|TARGET_INTATR)) != 0$
+		$ERROR INT.TEXT_LINE[intno]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of %3% `%4%\' in %5%"), "intatr", INT.INTATR[intno], "intno", INT.INTNO[intno], "CFG_INT")$$END$
+	$END$
+
+$	// intpriがCFG_INTに対する割込み優先度として正しくない場合（E_PAR）
+	$IF !LENGTH(FIND(INTPRI_CFGINT_VALID, INT.INTPRI[intno]))$
+		$ERROR INT.TEXT_LINE[intno]$E_PAR: $FORMAT(_("illegal %1% `%2%\' in %3%"), "intpri", INT.INTPRI[intno], "CFG_INT")$$END$
+	$END$
+
+$	// カーネル管理に固定されているintnoに対して，intpriにTMIN_INTPRI
+$	// よりも小さい値が指定された場合（E_OBJ）
+	$IF LENGTH(FIND(INTNO_FIX_KERNEL, intno))$
+		$IF INT.INTPRI[intno] < TMIN_INTPRI$
+			$ERROR INT.TEXT_LINE[intno]$E_OBJ: $FORMAT(_("%1% `%2%\' must not have higher priority than %3%"), "intno", INT.INTNO[intno], "TMIN_INTPRI")$$END$
+		$END$
+	$END$
+
+$	// カーネル管理外に固定されているintnoに対して，intpriにTMIN_INTPRI
+$	// よりも小さい値が指定されなかった場合（E_OBJ）
+	$IF LENGTH(FIND(INTNO_FIX_NONKERNEL, intno))$
+		$IF INT.INTPRI[intno] >= TMIN_INTPRI$
+			$ERROR INT.TEXT_LINE[intno]$E_OBJ: $FORMAT(_("%1% `%2%\' must have higher priority than %3%"), "intno", INT.INTNO[intno], "TMIN_INTPRI")$$END$
+		$END$
+	$END$
+	$i = i + 1$
+$END$
+
+$ 割込みハンドラに関するエラーチェック
+$i = 0$
+$FOREACH inhno INH.ORDER_LIST$
+$	// inhnoがDEF_INHに対する割込みハンドラ番号として正しくない場合（E_PAR）
+	$IF !LENGTH(FIND(INHNO_DEFINH_VALID, INH.INHNO[inhno]))$
+		$ERROR INH.TEXT_LINE[inhno]$E_PAR: $FORMAT(_("illegal %1% `%2%\' in %3%"), "inhno", INH.INHNO[inhno], "DEF_INH")$$END$
+	$END$
+
+$	// inhnoがDEF_INHによって設定済みの場合（E_OBJ）
+	$j = 0$
+	$FOREACH inhno2 INH.ORDER_LIST$
+		$IF j < i && INH.INHNO[inhno] == INH.INHNO[inhno2]$
+			$ERROR INH.TEXT_LINE[inhno]$E_OBJ: $FORMAT(_("%1% `%2%\' in %3% is duplicated"), "inhno", INH.INHNO[inhno], "DEF_INH")$$END$
+		$END$
+		$j = j + 1$
+	$END$
+
+$	// inhatrが（TA_NULL）でない場合（E_RSATR）
+	$IF (INH.INHATR[inhno] & ~TARGET_INHATR) != 0$
+		$ERROR INH.TEXT_LINE[inhno]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of %3% `%4%\' in %5%"), "inhatr", INH.INHATR[inhno], "inhno", INH.INHNO[inhno], "DEF_INH")$$END$
+	$END$
+
+$	// カーネル管理に固定されているinhnoに対して，inhatrにTA_NONKERNEL
+$	//　が指定されている場合（E_RSATR）
+	$IF LENGTH(FIND(INHNO_FIX_KERNEL, inhno))$
+		$IF (INH.INHATR[inhno] & TA_NONKERNEL) != 0$
+			$ERROR INH.TEXT_LINE[inhno]$E_RSATR: $FORMAT(_("%1% `%2%\' must not be non-kernel interrupt"), "inhno", INH.INHNO[inhno])$$END$
+		$END$
+	$END$
+
+$	// カーネル管理外に固定されているinhnoに対して，inhatrにTA_NONKERNEL
+$	// が指定されていない場合（E_RSATR）
+	$IF LENGTH(FIND(INHNO_FIX_NONKERNEL, inhno))$
+		$IF (INH.INHATR[inhno] & TA_NONKERNEL) == 0$
+			$ERROR INH.TEXT_LINE[inhno]$E_RSATR: $FORMAT(_("%1% `%2%\' must be non-kernel interrupt"), "inhno", INH.INHNO[inhno])$$END$
+		$END$
+	$END$
+
+	$IF LENGTH(INTNO[INH.INHNO[inhno]])$
+		$intno = INTNO[INH.INHNO[inhno]]$
+$		// inhnoに対応するintnoに対するCFG_INTがない場合（E_OBJ）
+		$IF !LENGTH(INT.INTNO[intno])$
+			$ERROR INH.TEXT_LINE[inhno]$E_OBJ: $FORMAT(_("%1% `%2%\' corresponding to %3% `%4%\' is not configured with %5%"), "intno", intno, "inhno", INH.INHNO[inhno], "CFG_INT")$$END$
+		$ELSE$
+			$IF (INH.INHATR[inhno] & TA_NONKERNEL) == 0$
+$				// inhatrにTA_NONKERNELが指定されておらず，inhnoに対応
+$				// するintnoに対してCFG_INTで設定された割込み優先度が
+$				// TMIN_INTPRIよりも小さい場合（E_OBJ）
+				$IF INT.INTPRI[intno] < TMIN_INTPRI$
+					$ERROR INT.TEXT_LINE[intno]$E_OBJ: $FORMAT(_("%1% `%2%\' configured for %3% `%4%\' is higher than %5%"), "intpri", INT.INTPRI[intno], "inhno", INH.INHNO[inhno], "TMIN_INTPRI")$$END$
+				$END$
+			$ELSE$
+$				// inhatrにTA_NONKERNELが指定されており，inhnoに対応
+$				// するintnoに対してCFG_INTで設定された割込み優先度が
+$				// TMIN_INTPRI以上である場合（E_OBJ）
+				$IF INT.INTPRI[intno] >= TMIN_INTPRI$
+					$ERROR INT.TEXT_LINE[intno]$E_OBJ: $FORMAT(_("%1% `%2%\' configured for %3% `%4%\' is lower than or equal to %5%"), "intpri", INT.INTPRI[intno], "inhno", INH.INHNO[inhno], "TMIN_INTPRI")$$END$
+				$END$
+			$END$
+		$END$
+	$END$
+	$i = i + 1$
+$END$
+
+$ 割込みサービスルーチン（ISR）に関するエラーチェック
+$FOREACH order ISR.ORDER_LIST$
+$	// isratrが（TA_NULL）でない場合（E_RSATR）
+	$IF (ISR.ISRATR[order] & ~TARGET_ISRATR) != 0$
+		$ERROR ISR.TEXT_LINE[order]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' in %3%"), "isratr", ISR.ISRATR[order], "ATT_ISR")$$END$
+	$END$
+
+$	// intnoがATT_ISRに対する割込み番号として正しくない場合（E_PAR）
+	$IF !LENGTH(FIND(INTNO_ATTISR_VALID, ISR.INTNO[order]))$
+		$ERROR ISR.TEXT_LINE[order]$E_PAR: $FORMAT(_("illegal %1% `%2%\' in %3%"), "intno", ISR.INTNO[order], "ATT_ISR")$$END$
+	$END$
+
+$	// (TMIN_ISRPRI <= isrpri && isrpri <= TMAX_ISRPRI)でない場合（E_PAR）
+	$IF !(TMIN_ISRPRI <= ISR.ISRPRI[order] && ISR.ISRPRI[order] <= TMAX_ISRPRI)$
+		$ERROR ISR.TEXT_LINE[order]$E_PAR: $FORMAT(_("illegal %1% `%2%\' in %3%"), "isrpri", ISR.ISRPRI[order], "ATT_ISR")$$END$
+	$END$
+$END$
+
+$FOREACH intno INTNO_ATTISR_VALID$
+	$inhno = INHNO[intno]$
+
+$	// 割込み番号intnoに対して登録されたISRのリストの作成
+	$isr_order_list = {}$
+	$FOREACH order ISR.ORDER_LIST$
+		$IF ISR.INTNO[order] == intno$
+			$isr_order_list = APPEND(isr_order_list, order)$
+			$order_for_error = order$
+		$END$
+	$END$
+
+$	// 割込み番号intnoに対して登録されたISRが存在する場合
+	$IF LENGTH(isr_order_list) > 0$
+$		// intnoに対応するinhnoに対してDEF_INHがある場合（E_OBJ）
+		$IF LENGTH(INH.INHNO[inhno])$
+			$ERROR ISR.TEXT_LINE[order_for_error]$E_OBJ: $FORMAT(_("%1% `%2%\' in %3% is duplicated with %4% `%5%\'"), "intno", ISR.INTNO[order_for_error], "ATT_ISR", "inhno", INH.INHNO[inhno])$$END$
+		$END$
+
+$		// intnoに対するCFG_INTがない場合（E_OBJ）
+		$IF !LENGTH(INT.INTNO[intno])$
+			$ERROR ISR.TEXT_LINE[order_for_error]$E_OBJ: $FORMAT(_("%1% `%2%\' is not configured with %3%"), "intno", ISR.INTNO[order_for_error], "CFG_INT")$$END$
+		$ELSE$
+$			// intnoに対してCFG_INTで設定された割込み優先度がTMIN_INTPRI
+$			// よりも小さい場合（E_OBJ）
+			$IF INT.INTPRI[intno] < TMIN_INTPRI$
+				$ERROR INT.TEXT_LINE[intno]$E_OBJ: $FORMAT(_("%1% `%2%\' configured for %3% `%4%\' is higher than %5%"), "intpri", INT.INTPRI[intno], "intno", ISR.INTNO[order_for_error], "TMIN_INTPRI")$$END$
+			$END$
+		$END$
+	$END$
+$END$
+
+$ 割込みサービスルーチン（ISR）管理のデータ構造
+$intno_isr_list = {}$
+$FOREACH intno INTNO_ATTISR_VALID$
+	$inhno = INHNO[intno]$
+	$IF LENGTH(INT.INTNO[intno]) && !LENGTH(INH.INHNO[inhno])$
+		$intno_isr_list = APPEND(intno_isr_list, intno)$
+	$END$
+$END$
+
+$INTNO_ISR = {}$
+$i = 0$
+$FOREACH intno SORT(intno_isr_list, "INT.INTNO")$
+	$INTNO_ISR = APPEND(INTNO_ISR, intno)$
+	$ISR_QUEUE_HEADER[intno] = FORMAT("&(_kernel_isr_queue_table[%d])", i)$
+	$i = i + 1$
+$END$
+
+const uint_t _kernel_tnum_isr_queue = $LENGTH(INTNO_ISR)$;$NL$
+$NL$
+
+$IF LENGTH(INTNO_ISR)$
+	const ISR_ENTRY _kernel_isr_queue_list[$LENGTH(INTNO_ISR)$] = {$NL$
+	$JOINEACH intno INTNO_ISR ",\n"$
+		$TAB${ $intno$, $ISR_QUEUE_HEADER[intno]$ }
+	$END$$NL$
+	};$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(QUEUE, _kernel_isr_queue_table);$NL$
+$END$$NL$
+
+$IF LENGTH(INTNO_ISR)$
+	QUEUE _kernel_isr_queue_table[$LENGTH(INTNO_ISR)$];$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(QUEUE, _kernel_isr_queue_table);$NL$
+$END$$NL$
+
+$ 割込みサービスルーチン（ISR）呼出しのための割込みハンドラの生成
+$FOREACH intno INTNO_ISR$
+	$inhno = INHNO[intno]$
+
+$	// DEF_INH(inhno, { TA_NULL, _kernel_inthdr_<intno> } );
+	$INH.INHNO[inhno] = inhno$
+	$INH.INHATR[inhno] = VALUE("TA_NULL", 0)$
+	$INH.INTHDR[inhno] = CONCAT("_kernel_inthdr_", intno)$
+	$INH.ORDER_LIST = APPEND(INH.ORDER_LIST, inhno)$
+
+$	// ISR用の割込みハンドラ
+	void$NL$
+	_kernel_inthdr_$intno$(void)$NL$
+	{$NL$
+	$TAB$i_begin_int($intno$);$NL$
+	$TAB$_kernel_call_isr($ISR_QUEUE_HEADER[intno]$);$NL$
+	$TAB$i_end_int($intno$);$NL$
+	}$NL$
+	$NL$
+$END$
+
+$ 割込みサービスルーチンの数
+#define TNUM_SISR	$LENGTH(ISR.ORDER_LIST)$$NL$
+#define TNUM_ISR	$LENGTH(ISR.ORDER_LIST) + num_aisrid$$NL$
+$NL$
+
+$ 割込みサービスルーチンID番号の最大値
+const ID _kernel_tmax_isrid = (TMIN_ISRID + TNUM_ISRID - 1);$NL$
+const uint_t _kernel_tnum_sisr = TNUM_SISR;$NL$
+$NL$
+
+$ 割込みサービスルーチン初期化ブロックの生成
+$IF LENGTH(ISR.ORDER_LIST)$
+	const ISRINIB _kernel_sisrinib_table[TNUM_SISR] = {$NL$
+	$JOINEACH order ISR.ORDER_LIST ",\n"$
+		$TAB${ ($ISR.ISRATR[order]$), (intptr_t)($ISR.EXINF[order]$), ($ISR.INTNO[order]$), ($ISR_QUEUE_HEADER[ISR.INTNO[order]]$), ($ISR.ISR[order]$), ($ISR.ISRPRI[order]$) }
+	$END$$NL$
+	};$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(const ISRINIB, _kernel_sisrinib_table);$NL$
+$END$
+$NL$
+
+$ 動的生成割込みサービスルーチン用の割込みサービスルーチン初期化ブロッ
+$ クの生成
+$IF num_aisrid > 0$
+	ISRINIB _kernel_aisrinib_table[$num_aisrid$];$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(ISRINIB, _kernel_aisrinib_table);$NL$
+$END$
+$NL$
+
+$ 割込みサービスルーチン管理ブロックの生成
+$IF num_isr > 0$
+	ISRCB _kernel_isrcb_table[TNUM_ISR];$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(ISRCB, _kernel_isrcb_table);$NL$
+$END$
+$NL$
+
+$ 
+$  割込み管理機能のための標準的な初期化情報の生成
+$ 
+$ 割込みハンドラの初期化に必要な情報
+$IF !OMIT_INITIALIZE_INTERRUPT || ALT(USE_INHINIB_TABLE,0)$
+
+$ 割込みハンドラ数
+#define TNUM_INHNO	$LENGTH(INH.ORDER_LIST)$$NL$
+const uint_t _kernel_tnum_inhno = TNUM_INHNO;$NL$
+$NL$
+$FOREACH inhno INH.ORDER_LIST$
+	$IF (INH.INHATR[inhno] & TA_NONKERNEL) == 0$
+		INTHDR_ENTRY($INH.INHNO[inhno]$, $+INH.INHNO[inhno]$, $INH.INTHDR[inhno]$)$NL$
+	$END$
+$END$
+$NL$
+
+$ 割込みハンドラ初期化ブロック
+$IF LENGTH(INH.ORDER_LIST)$
+	const INHINIB _kernel_inhinib_table[TNUM_INHNO] = {$NL$
+	$JOINEACH inhno INH.ORDER_LIST ",\n"$
+		$IF (INH.INHATR[inhno] & TA_NONKERNEL) == 0$
+			$TAB${ ($INH.INHNO[inhno]$), ($INH.INHATR[inhno]$), (FP)(INT_ENTRY($INH.INHNO[inhno]$, $INH.INTHDR[inhno]$)) }
+		$ELSE$
+			$TAB${ ($INH.INHNO[inhno]$), ($INH.INHATR[inhno]$), (FP)($INH.INTHDR[inhno]$) }
+		$END$
+	$END$$NL$
+	};$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(const INHINIB, _kernel_inhinib_table);$NL$
+$END$$NL$
+$END$
+
+$ 割込み要求ラインの初期化に必要な情報
+$IF !OMIT_INITIALIZE_INTERRUPT || ALT(USE_INTINIB_TABLE,0)$
+
+$ 割込み要求ライン数
+#define TNUM_INTNO	$LENGTH(INT.ORDER_LIST)$$NL$
+const uint_t _kernel_tnum_intno = TNUM_INTNO;$NL$
+$NL$
+
+$ 割込み要求ライン初期化ブロック
+$IF LENGTH(INT.ORDER_LIST)$
+	const INTINIB _kernel_intinib_table[TNUM_INTNO] = {$NL$
+	$JOINEACH intno INT.ORDER_LIST ",\n"$
+		$TAB${ ($INT.INTNO[intno]$), ($INT.INTATR[intno]$), ($INT.INTPRI[intno]$) }
+	$END$$NL$
+	};$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(const INTINIB, _kernel_intinib_table);$NL$
+$END$$NL$
+$END$
+
+$ 
+$  CPU例外管理機能
+$ 
+/*$NL$
+$SPC$*  CPU Exception Management Functions$NL$
+$SPC$*/$NL$
+$NL$
+
+$ CPU例外ハンドラに関するエラーチェック
+$i = 0$
+$FOREACH excno EXC.ORDER_LIST$
+$	// excnoがDEF_EXCに対するCPU例外ハンドラ番号として正しくない場合（E_PAR）
+	$IF !LENGTH(FIND(EXCNO_DEFEXC_VALID, EXC.EXCNO[excno]))$
+		$ERROR EXC.TEXT_LINE[excno]$E_PAR: $FORMAT(_("illegal %1% `%2%\' in %3%"), "excno", EXC.EXCNO[excno], "DEF_EXC")$$END$
+	$END$
+
+$	// excnoがDEF_EXCによって設定済みの場合（E_OBJ）
+	$j = 0$
+	$FOREACH excno2 EXC.ORDER_LIST$
+		$IF j < i && EXC.EXCNO[excno] == EXC.EXCNO[excno2]$
+			$ERROR EXC.TEXT_LINE[excno]$E_OBJ: $FORMAT(_("%1% `%2%\' in %3% is duplicated"), "excno", EXC.EXCNO[excno], "DEF_EXC")$$END$
+		$END$
+		$j = j + 1$
+	$END$
+
+$	// excatrが（TA_NULL）でない場合（E_RSATR）
+	$IF (EXC.EXCATR[excno] & ~TARGET_EXCATR) != 0$
+		$ERROR EXC.TEXT_LINE[excno]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of %3% `%4%\' in %5%"), "excatr", EXC.EXCATR[excno], "excno", EXC.EXCNO[excno], "DEF_EXC")$$END$
+	$END$
+	$i = i + 1$
+$END$
+
+$ CPU例外ハンドラのための標準的な初期化情報の生成
+$IF !OMIT_INITIALIZE_EXCEPTION$
+
+$ CPU例外ハンドラ数
+#define TNUM_EXCNO	$LENGTH(EXC.ORDER_LIST)$$NL$
+const uint_t _kernel_tnum_excno = TNUM_EXCNO;$NL$
+$NL$
+$FOREACH excno EXC.ORDER_LIST$
+	EXCHDR_ENTRY($EXC.EXCNO[excno]$, $+EXC.EXCNO[excno]$, $EXC.EXCHDR[excno]$)$NL$
+$END$
+$NL$
+
+$ CPU例外ハンドラ初期化ブロック
+$IF LENGTH(EXC.ORDER_LIST)$
+	const EXCINIB _kernel_excinib_table[TNUM_EXCNO] = {$NL$
+	$JOINEACH excno EXC.ORDER_LIST ",\n"$
+		$TAB${ ($EXC.EXCNO[excno]$), ($EXC.EXCATR[excno]$), (FP)(EXC_ENTRY($EXC.EXCNO[excno]$, $EXC.EXCHDR[excno]$)) }
+	$END$$NL$
+	};$NL$
+$ELSE$
+	TOPPERS_EMPTY_LABEL(const EXCINIB, _kernel_excinib_table);$NL$
+$END$$NL$
+$END$
+
+$ 
+$  非タスクコンテキスト用のスタック領域
+$ 
+/*$NL$
+$SPC$*  Stack Area for Non-task Context$NL$
+$SPC$*/$NL$
+$NL$
+
+$IF !LENGTH(ICS.ORDER_LIST)$
+$	// DEF_ICSがない場合のデフォルト値の設定
+	#ifdef DEFAULT_ISTK$NL$
+	$NL$
+	#define TOPPERS_ISTKSZ		DEFAULT_ISTKSZ$NL$
+	#define TOPPERS_ISTK		DEFAULT_ISTK$NL$
+	$NL$
+	#else /* DEAULT_ISTK */$NL$
+	$NL$
+	$istksz = ALLOC_STACK("_kernel_istack", "DEFAULT_ISTKSZ")$$NL$
+	#define TOPPERS_ISTKSZ		$istksz$$NL$
+	#define TOPPERS_ISTK		_kernel_istack$NL$
+	$NL$
+	#endif /* DEAULT_ISTK */$NL$
+$ELSE$
+
+$	// 静的API「DEF_ICS」が複数ある（E_OBJ）
+	$IF LENGTH(ICS.ORDER_LIST) > 1$
+		$ERROR$E_OBJ: $FORMAT(_("too many %1%"), "DEF_ICS")$$END$
+	$END$
+
+$	// istkszが0以下か，ターゲット定義の最小値（TARGET_MIN_ISTKSZ）よりも
+$	// 小さい場合（E_PAR）
+	$IF ICS.ISTKSZ[1] <= 0 || (TARGET_MIN_ISTKSZ
+									&& ICS.ISTKSZ[1] < TARGET_MIN_ISTKSZ)$
+		$ERROR ICS.TEXT_LINE[1]$E_PAR: $FORMAT(_("too small %1% `%2%\' in %3%"), "istksz", ICS.ISTKSZ[1], "DEF_ICS")$$END$
+	$END$
+
+$ 	// istkszがスタック領域のサイズとして正しくない場合（E_PAR）
+	$IF !EQ(ICS.ISTK[1], "NULL") && CHECK_STKSZ_ALIGN
+							&& (ICS.ISTKSZ[1] & (CHECK_STKSZ_ALIGN - 1))$
+		$ERROR ICS.TEXT_LINE[1]$E_PAR: $FORMAT(_("%1% `%2%\' in %3% is not aligned"), "istksz", ICS.ISTKSZ[1], "DEF_ICS")$$END$
+	$END$
+
+	$IF EQ(ICS.ISTK[1], "NULL")$
+$		// スタック領域の自動割付け
+		$istksz = ALLOC_STACK("_kernel_istack", ICS.ISTKSZ[1])$$NL$
+		#define TOPPERS_ISTKSZ		$istksz$$NL$
+		#define TOPPERS_ISTK		_kernel_istack$NL$
+	$ELSE$
+		#define TOPPERS_ISTKSZ		($ICS.ISTKSZ[1]$)$NL$
+		#define TOPPERS_ISTK		(void *)($ICS.ISTK[1]$)$NL$
+	$END$
+$END$
+$NL$
+
+$ 非タスクコンテキスト用のスタック領域
+const SIZE		_kernel_istksz = TOPPERS_ISTKSZ;$NL$
+STK_T *const	_kernel_istk = TOPPERS_ISTK;$NL$
+$NL$
+#ifdef TOPPERS_ISTKPT$NL$
+STK_T *const	_kernel_istkpt = TOPPERS_ISTKPT(TOPPERS_ISTK, TOPPERS_ISTKSZ);$NL$
+#endif /* TOPPERS_ISTKPT */$NL$
+$NL$
+
+$ 
+$  カーネルが割り付けるメモリ領域
+$ 
+/*$NL$
+$SPC$*  Memory Area Allocated by Kernel$NL$
+$SPC$*/$NL$
+$NL$
+
+$IF !LENGTH(KMM.ORDER_LIST)$
+$	// DEF_KMMがない場合のデフォルト値の設定
+	#define TOPPERS_KMMSZ		0$NL$
+	#define TOPPERS_KMM			NULL$NL$
+$ELSE$
+$	// 静的API「DEF_KMM」が複数ある（E_OBJ）
+	$IF LENGTH(KMM.ORDER_LIST) > 1$
+		$ERROR$E_OBJ: $FORMAT(_("too many %1%"), "DEF_KMM")$$END$
+	$END$
+
+$	// kmmszが0以下の場合（E_PAR）
+	$IF KMM.KMMSZ[1] <= 0$
+		$ERROR KMM.TEXT_LINE[1]$E_PAR: $FORMAT(_("%1% `%2%\' is zero in %3%"), "kmmsz", KMM.KMMSZ[1], "DEF_KMM")$$END$
+	$END$
+
+$ 	// kmmszがカーネルが割り付けるメモリ領域のサイズとして正しくない場合（E_PAR）
+	$IF !EQ(KMM.KMM[1], "NULL") && CHECK_MB_ALIGN
+							&& (KMM.KMMSZ[1] & (CHECK_MB_ALIGN - 1))$
+		$ERROR KMM.TEXT_LINE[1]$E_PAR: $FORMAT(_("%1% `%2%\' in %3% is not aligned"), "kmmsz", KMM.KMMSZ[1], "DEF_KMM")$$END$
+	$END$
+
+	$IF EQ(KMM.KMM[1], "NULL")$
+$		// カーネルが割り付けるメモリ領域の自動割付け
+		static MB_T					_kernel_memory[TOPPERS_COUNT_SZ($KMM.KMMSZ[1]$, sizeof(MB_T))];$NL$
+		#define TOPPERS_KMMSZ		TOPPERS_ROUND_SZ($KMM.KMMSZ[1]$, sizeof(MB_T))$NL$
+		#define TOPPERS_KMM			_kernel_memory$NL$
+	$ELSE$
+		#define TOPPERS_KMMSZ		($KMM.KMMSZ[1]$)$NL$
+		#define TOPPERS_KMM			(void *)($KMM.KMM[1]$)$NL$
+	$END$
+$END$
+$NL$
+
+$ カーネルが割り付けるメモリ領域
+const SIZE		_kernel_kmmsz = TOPPERS_KMMSZ;$NL$
+MB_T *const		_kernel_kmm = TOPPERS_KMM;$NL$
+$NL$
+
+$ 
+$  タイムイベント管理
+$ 
+/*$NL$
+$SPC$*  Time Event Management$NL$
+$SPC$*/$NL$
+$NL$
+TMEVTN   _kernel_tmevt_heap[TNUM_TSKID + TNUM_CYCID + TNUM_ALMID];$NL$
+$NL$
+
+$ 
+$  各モジュールの初期化関数
+$ 
+/*$NL$
+$SPC$*  Module Initialization Function$NL$
+$SPC$*/$NL$
+$NL$
+void$NL$
+_kernel_initialize_object(void)$NL$
+{$NL$
+$TAB$_kernel_initialize_task();$NL$
+$IF num_semid$$TAB$_kernel_initialize_semaphore();$NL$$END$
+$IF num_flgid$$TAB$_kernel_initialize_eventflag();$NL$$END$
+$IF num_dtqid$$TAB$_kernel_initialize_dataqueue();$NL$$END$
+$IF num_pdqid$$TAB$_kernel_initialize_pridataq();$NL$$END$
+$IF num_mbxid$$TAB$_kernel_initialize_mailbox();$NL$$END$
+$IF num_mpfid$$TAB$_kernel_initialize_mempfix();$NL$$END$
+$IF num_cycid$$TAB$_kernel_initialize_cyclic();$NL$$END$
+$IF num_almid$$TAB$_kernel_initialize_alarm();$NL$$END$
+$TAB$_kernel_initialize_interrupt();$NL$
+$IF num_isr$$TAB$_kernel_initialize_isr();$NL$$END$
+$TAB$_kernel_initialize_exception();$NL$
+}$NL$
+$NL$
+
+$ 
+$  初期化ルーチンの実行関数
+$ 
+/*$NL$
+$SPC$*  Initialization Routine$NL$
+$SPC$*/$NL$
+$NL$
+void$NL$
+_kernel_call_inirtn(void)$NL$
+{$NL$
+$FOREACH order INI.ORDER_LIST$
+$ 	// iniatrが（TA_NULL）でない場合（E_RSATR）
+	$IF INI.INIATR[order] != 0$
+		$ERROR INI.TEXT_LINE[order]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of %3% `%4%\' in %5%"), "iniatr", INI.INIATR[order], "inirtn", INI.INIRTN[order], "ATT_INI")$$END$
+	$END$
+	$TAB$((INIRTN)($INI.INIRTN[order]$))((intptr_t)($INI.EXINF[order]$));$NL$
+$END$
+}$NL$
+$NL$
+
+$ 
+$  終了処理ルーチンの実行関数
+$ 
+/*$NL$
+$SPC$*  Termination Routine$NL$
+$SPC$*/$NL$
+$NL$
+void$NL$
+_kernel_call_terrtn(void)$NL$
+{$NL$
+$FOREACH rorder TER.RORDER_LIST$
+$ 	// teratrが（TA_NULL）でない場合（E_RSATR）
+	$IF TER.TERATR[rorder] != 0$
+		$ERROR TER.TEXT_LINE[rorder]$E_RSATR: $FORMAT(_("illegal %1% `%2%\' of %3% `%4%\' in %5%"), "teratr", TER.TERATR[rorder], "terrtn", TER.TERRTN[rorder], "ATT_TER")$$END$
+	$END$
+	$TAB$((TERRTN)($TER.TERRTN[rorder]$))((intptr_t)($TER.EXINF[rorder]$));$NL$
+$END$
+}$NL$
+$NL$
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/kernel_api.csv
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/kernel_api.csv	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/kernel_api.csv	(revision 453)
@@ -0,0 +1,30 @@
+tsk,CRE_TSK,#tskid { .tskatr &exinf &task +itskpri .stksz &stk },,
+tsk,DEF_TEX,%tskid { .texatr &texrtn },0,1
+atsk,AID_TSK,.notsk,,
+sem,CRE_SEM,#semid { .sematr .isemcnt .maxsem },,
+asem,AID_SEM,.nosem,,
+flg,CRE_FLG,#flgid { .flgatr .iflgptn },,
+aflg,AID_FLG,.nosem,,
+dtq,CRE_DTQ,#dtqid { .dtqatr .dtqcnt &dtqmb },,
+adtq,AID_DTQ,.nodtq,,
+pdq,CRE_PDQ,#pdqid { .pdqatr .pdqcnt +maxdpri &pdqmb },,
+apdq,AID_PDQ,.nopdq,,
+mbx,CRE_MBX,#mbxid { .mbxatr +maxmpri &mprihd },,
+ambx,AID_MBX,.nombx,,
+mtx,CRE_MTX,#mtxid { .mtxatr +ceilpri? },,
+amtx,AID_MTX,.nomtx,,
+mpf,CRE_MPF,#mpfid { .mpfatr .blkcnt .blksz &mpf &mpfmb },,
+ampf,AID_MPF,.nompf,,
+cyc,CRE_CYC,#cycid { .cycatr &exinf &cychdr .cyctim .cycphs },,
+acyc,AID_CYC,.nocyc,,
+alm,CRE_ALM,#almid { .almatr &exinf &almhdr },,
+aalm,AID_ALM,.noalm,,
+int,CFG_INT,.intno { .intatr +intpri },,
+isr,ATT_ISR,{ .isratr &exinf .intno &isr +isrpri },-1,
+aisr,AID_ISR,.noisr,,
+inh,DEF_INH,.inhno { .inhatr &inthdr },,
+exc,DEF_EXC,.excno { .excatr &exchdr },,
+ics,DEF_ICS,{ .istksz &istk },-1,
+kmm,DEF_KMM,{ .kmmsz &kmm },-1,
+ini,ATT_INI,{ .iniatr &exinf &inirtn },-1,
+ter,ATT_TER,{ .teratr &exinf &terrtn },-1,
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/kernel_check.tf
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/kernel_check.tf	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/kernel_check.tf	(revision 453)
@@ -0,0 +1,212 @@
+$ ======================================================================
+$ 
+$   TOPPERS/ASP Kernel
+$       Toyohashi Open Platform for Embedded Real-Time Systems/
+$       Advanced Standard Profile Kernel
+$ 
+$   Copyright (C) 2008-2010 by Embedded and Real-Time Systems Laboratory
+$               Graduate School of Information Science, Nagoya Univ., JAPAN
+$  
+$   上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+$   ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+$   変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+$   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+$       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+$       スコード中に含まれていること．
+$   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+$       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+$       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+$       の無保証規定を掲載すること．
+$   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+$       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+$       と．
+$     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+$         作権表示，この利用条件および下記の無保証規定を掲載すること．
+$     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+$         報告すること．
+$   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+$       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+$       また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+$       由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+$       免責すること．
+$  
+$   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+$   よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+$   に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+$   アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+$   の責任を負わない．
+$ 
+$   @(#) $Id$
+$  
+$ =====================================================================
+
+$
+$  データセクションのLMAからVMAへのコピー
+$
+$FOREACH lma LMA.ORDER_LIST$
+	$start_data = SYMBOL(LMA.START_DATA[lma])$
+	$end_data = SYMBOL(LMA.END_DATA[lma])$
+	$start_idata = SYMBOL(LMA.START_IDATA[lma])$
+	$IF !LENGTH(start_data)$
+		$ERROR$$FORMAT(_("symbol '%1%' not found"), LMA.START_DATA[lma])$$END$
+	$ELIF !LENGTH(end_data)$
+		$ERROR$$FORMAT(_("symbol '%1%' not found"), LMA.END_DATA[lma])$$END$
+	$ELIF !LENGTH(start_idata)$
+		$ERROR$$FORMAT(_("symbol '%1%' not found"), LMA.START_IDATA[lma])$$END$
+	$ELSE$
+		$BCOPY(start_idata, start_data, end_data - start_data)$
+	$END$
+$END$
+
+$ 
+$  関数の先頭番地のチェック
+$ 
+$IF CHECK_FUNC_ALIGN || CHECK_FUNC_NONNULL$
+$	// タスクとタスク例外処理ルーチンの先頭番地のチェック
+	$tinib = SYMBOL("_kernel_tinib_table")$
+	$FOREACH tskid TSK.ID_LIST$
+		$task = PEEK(tinib + offsetof_TINIB_task, sizeof_FP)$
+		$IF CHECK_FUNC_ALIGN && (task & (CHECK_FUNC_ALIGN - 1)) != 0$
+			$ERROR TSK.TEXT_LINE[tskid]$E_PAR: 
+				$FORMAT(_("%1% `%2%\' of `%3%\' in %4% is not aligned"),
+				"task", TSK.TASK[tskid], tskid, "CRE_TSK")$$END$
+		$END$
+		$IF CHECK_FUNC_NONNULL && task == 0$
+			$ERROR TSK.TEXT_LINE[tskid]$E_PAR: 
+				$FORMAT(_("%1% `%2%\' of `%3%\' in %4% is null"),
+				"task", TSK.TASK[tskid], tskid, "CRE_TSK")$$END$
+		$END$
+		$texrtn = PEEK(tinib + offsetof_TINIB_texrtn, sizeof_FP)$
+		$IF CHECK_FUNC_ALIGN && (texrtn & (CHECK_FUNC_ALIGN - 1)) != 0$
+			$ERROR DEF_TEX.TEXT_LINE[tskid]$E_PAR: 
+				$FORMAT(_("%1% `%2%\' of `%3%\' in %4% is not aligned"),
+				"texrtn", TSK.TEXRTN[tskid], tskid, "DEF_TEX")$$END$
+		$END$
+		$tinib = tinib + sizeof_TINIB$
+	$END$
+
+$	// 周期ハンドラの先頭番地のチェック
+	$cycinib = SYMBOL("_kernel_cycinib_table")$
+	$FOREACH cycid CYC.ID_LIST$
+		$cychdr = PEEK(cycinib + offsetof_CYCINIB_cychdr, sizeof_FP)$
+		$IF CHECK_FUNC_ALIGN && (cychdr & (CHECK_FUNC_ALIGN - 1)) != 0$
+			$ERROR CYC.TEXT_LINE[cycid]$E_PAR: 
+				$FORMAT(_("%1% `%2%\' of `%3%\' in %4% is not aligned"),
+				"cychdr", CYC.CYCHDR[cycid], cycid, "CRE_CYC")$$END$
+		$END$
+		$IF CHECK_FUNC_NONNULL && cychdr == 0$
+			$ERROR CYC.TEXT_LINE[cycid]$E_PAR: 
+				$FORMAT(_("%1% `%2%\' of `%3%\' in %4% is null"),
+				"cychdr", CYC.CYCHDR[cycid], cycid, "CRE_CYC")$$END$
+		$END$
+		$cycinib = cycinib + sizeof_CYCINIB$
+	$END$
+
+$	// アラームハンドラの先頭番地のチェック
+	$alminib = SYMBOL("_kernel_alminib_table")$
+	$FOREACH almid ALM.ID_LIST$
+		$almhdr = PEEK(alminib + offsetof_ALMINIB_almhdr, sizeof_FP)$
+		$IF CHECK_FUNC_ALIGN && (almhdr & (CHECK_FUNC_ALIGN - 1)) != 0$
+			$ERROR ALM.TEXT_LINE[almid]$E_PAR: 
+				$FORMAT(_("%1% `%2%\' of `%3%\' in %4% is not aligned"),
+				"almhdr", ALM.ALMHDR[almid], almid, "CRE_ALM")$$END$
+		$END$
+		$IF CHECK_FUNC_NONNULL && almhdr == 0$
+			$ERROR ALM.TEXT_LINE[almid]$E_PAR: 
+				$FORMAT(_("%1% `%2%\' of `%3%\' in %4% is null"),
+				"almhdr", ALM.ALMHDR[almid], almid, "CRE_ALM")$$END$
+		$END$
+		$alminib = alminib + sizeof_ALMINIB$
+	$END$
+
+$	// 割込みサービスルーチンの先頭番地のチェック
+	$isrinib = SYMBOL("_kernel_sisrinib_table")$
+	$FOREACH order ISR.ORDER_LIST$
+		$isr = PEEK(isrinib + offsetof_ISRINIB_isr, sizeof_FP)$
+		$IF CHECK_FUNC_ALIGN && (isr & (CHECK_FUNC_ALIGN - 1)) != 0$
+			$ERROR ISR.TEXT_LINE[order]$E_PAR: 
+				$FORMAT(_("%1% `%2%\' in %4% is not aligned"),
+				"isr", ISR.ISR[order], "ATT_ISR")$$END$
+		$END$
+		$IF CHECK_FUNC_NONNULL && isr == 0$
+			$ERROR ISR.TEXT_LINE[order]$E_PAR: 
+				$FORMAT(_("%1% `%2%\' in %4% is null"),
+				"isr", ISR.ISR[order], "ATT_ISR")$$END$
+		$END$
+		$isrinib = isrinib + sizeof_ISRINIB$
+	$END$
+$END$
+
+$ 
+$  スタック領域の先頭番地のチェック
+$ 
+$IF CHECK_STACK_ALIGN || CHECK_STACK_NONNULL$
+$	// タスクのスタック領域の先頭番地のチェック
+	$tinib = SYMBOL("_kernel_tinib_table")$
+	$FOREACH tskid TSK.ID_LIST$
+		$IF USE_TSKINICTXB$
+			$stk = GET_STK_TSKINICTXB(tinib)$
+		$ELSE$
+			$stk = PEEK(tinib + offsetof_TINIB_stk, sizeof_void_ptr)$
+		$END$
+		$IF CHECK_STACK_ALIGN && (stk & (CHECK_STACK_ALIGN - 1)) != 0$
+			$ERROR TSK.TEXT_LINE[tskid]$E_PAR: 
+				$FORMAT(_("%1% `%2%\' of `%3%\' in %4% is not aligned"),
+				"stk", TSK.STK[tskid], tskid, "CRE_TSK")$$END$
+		$END$
+		$IF CHECK_STACK_NONNULL && stk == 0$
+			$ERROR TSK.TEXT_LINE[tskid]$E_PAR: 
+				$FORMAT(_("%1% `%2%\' of `%3%\' in %4% is null"),
+				"stk", TSK.STK[tskid], tskid, "CRE_TSK")$$END$
+		$END$
+		$tinib = tinib + sizeof_TINIB$
+	$END$
+
+$	// 非タスクコンテキスト用のスタック領域の先頭番地のチェック
+	$istk = PEEK(SYMBOL("_kernel_istk"), sizeof_void_ptr)$
+	$IF CHECK_STACK_ALIGN && (istk & (CHECK_STACK_ALIGN - 1)) != 0$
+		$ERROR ICS.TEXT_LINE[1]$E_PAR: 
+			$FORMAT(_("%1% `%2%\' in %3% is not aligned"),
+			"istk", ICS.ISTK[1], "DEF_ICS")$$END$
+	$END$
+	$IF CHECK_STACK_NONNULL && istk == 0$
+		$ERROR ICS.TEXT_LINE[1]$E_PAR: 
+			$FORMAT(_("%1% `%2%\' in %3% is null"),
+			"istk", ICS.ISTK[1], "DEF_ICS")$$END$
+	$END$
+$END$
+
+$ 
+$  固定長メモリプール領域の先頭番地のチェック
+$ 
+$IF CHECK_MPF_ALIGN || CHECK_MPF_NONNULL$
+$	// 固定長メモリプール領域の先頭番地のチェック
+	$mpfinib = SYMBOL("_kernel_mpfinib_table")$
+	$FOREACH mpfid MPF.ID_LIST$
+		$mpf = PEEK(mpfinib + offsetof_MPFINIB_mpf, sizeof_void_ptr)$
+		$IF CHECK_MPF_ALIGN && (mpf & (CHECK_MPF_ALIGN - 1)) != 0$
+			$ERROR MPF.TEXT_LINE[mpfid]$E_PAR: 
+				$FORMAT(_("%1% `%2%\' of `%3%\' in %4% is not aligned"),
+				"mpf", MPF.MPF[mpfid], mpfid, "CRE_MPF")$$END$
+		$END$
+		$IF CHECK_MPF_NONNULL && mpf == 0$
+			$ERROR MPF.TEXT_LINE[mpfid]$E_PAR: 
+				$FORMAT(_("%1% `%2%\' of `%3%\' in %4% is null"),
+				"mpf", MPF.MPF[mpfid], mpfid, "CRE_MPF")$$END$
+		$END$
+		$mpfinib = mpfinib + sizeof_MPFINIB$
+	$END$
+$END$
+
+$ 
+$  カーネルが割り付けるメモリ領域の先頭番地のチェック
+$ 
+$IF CHECK_MB_ALIGN$
+$	// カーネルが割り付けるメモリ領域の先頭番地のチェック
+	$kmm = PEEK(SYMBOL("_kernel_kmm"), sizeof_void_ptr)$
+	$IF CHECK_MB_ALIGN && (kmm & (CHECK_MB_ALIGN - 1)) != 0$
+		$ERROR KMM.TEXT_LINE[1]$E_PAR: 
+			$FORMAT(_("%1% `%2%\' in %3% is not aligned"),
+			"kmm", KMM.KMM[1], "DEF_KMM")$$END$
+	$END$
+$END$
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/kernel_def.csv
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/kernel_def.csv	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/kernel_def.csv	(revision 453)
@@ -0,0 +1,123 @@
+SIL_ENDIAN_BIG,#defined(SIL_ENDIAN_BIG)
+SIL_ENDIAN_LITTLE,#defined(SIL_ENDIAN_LITTLE)
+TA_NULL,TA_NULL
+TA_ACT,TA_ACT
+TA_TPRI,TA_TPRI
+TA_MPRI,TA_MPRI
+TA_WMUL,TA_WMUL
+TA_CLR,TA_CLR
+TA_CEILING,TA_CEILING
+TA_STA,TA_STA
+TA_NONKERNEL,TA_NONKERNEL
+TA_ENAINT,TA_ENAINT
+TA_EDGE,TA_EDGE
+TMIN_TPRI,TMIN_TPRI,signed
+TMAX_TPRI,TMAX_TPRI,signed
+TMIN_DPRI,TMIN_DPRI,signed
+TMAX_DPRI,TMAX_DPRI,signed
+TMIN_MPRI,TMIN_MPRI,signed
+TMAX_MPRI,TMAX_MPRI,signed
+TMIN_ISRPRI,TMIN_ISRPRI,signed
+TMAX_ISRPRI,TMAX_ISRPRI,signed
+TBIT_TEXPTN,TBIT_TEXPTN
+TBIT_FLGPTN,TBIT_FLGPTN
+TMAX_MAXSEM,TMAX_MAXSEM
+TMAX_RELTIM,TMAX_RELTIM
+TMIN_INTPRI,TMIN_INTPRI,signed
+OMIT_INITIALIZE_INTERRUPT,#defined(OMIT_INITIALIZE_INTERRUPT)
+OMIT_INITIALIZE_EXCEPTION,#defined(OMIT_INITIALIZE_EXCEPTION)
+USE_TSKINICTXB,#defined(USE_TSKINICTXB)
+TARGET_TSKATR,#defined(TARGET_TSKATR),,TARGET_TSKATR
+TARGET_INTATR,#defined(TARGET_INTATR),,TARGET_INTATR
+TARGET_INHATR,#defined(TARGET_INHATR),,TARGET_INHATR
+TARGET_ISRATR,#defined(TARGET_ISRATR),,TARGET_ISRATR
+TARGET_EXCATR,#defined(TARGET_EXCATR),,TARGET_EXCATR
+TARGET_MIN_STKSZ,#defined(TARGET_MIN_STKSZ),,TARGET_MIN_STKSZ
+TARGET_MIN_ISTKSZ,#defined(TARGET_MIN_ISTKSZ),,TARGET_MIN_ISTKSZ
+CHECK_STKSZ_ALIGN,#defined(CHECK_STKSZ_ALIGN),,CHECK_STKSZ_ALIGN
+CHECK_FUNC_ALIGN,#defined(CHECK_FUNC_ALIGN),,CHECK_FUNC_ALIGN
+CHECK_FUNC_NONNULL,#defined(CHECK_FUNC_NONNULL)
+CHECK_STACK_ALIGN,#defined(CHECK_STACK_ALIGN),,CHECK_STACK_ALIGN
+CHECK_STACK_NONNULL,#defined(CHECK_STACK_NONNULL)
+CHECK_MPF_ALIGN,#defined(CHECK_MPF_ALIGN),,CHECK_MPF_ALIGN
+CHECK_MPF_NONNULL,#defined(CHECK_MPF_NONNULL)
+CHECK_MB_ALIGN,#defined(CHECK_MB_ALIGN),,CHECK_MB_ALIGN
+sizeof_ID,sizeof(ID)
+sizeof_uint_t,sizeof(uint_t)
+sizeof_SIZE,sizeof(SIZE)
+sizeof_ATR,sizeof(ATR)
+sizeof_PRI,sizeof(PRI)
+sizeof_void_ptr,sizeof(void*)
+sizeof_VP,sizeof(void*)
+sizeof_intptr_t,sizeof(intptr_t)
+sizeof_FP,sizeof(FP)
+sizeof_INHNO,sizeof(INHNO)
+sizeof_INTNO,sizeof(INTNO)
+sizeof_EXCNO,sizeof(EXCNO)
+sizeof_TINIB,sizeof(TINIB)
+offsetof_TINIB_tskatr,"offsetof(TINIB,tskatr)"
+offsetof_TINIB_exinf,"offsetof(TINIB,exinf)"
+offsetof_TINIB_task,"offsetof(TINIB,task)"
+offsetof_TINIB_ipriority,"offsetof(TINIB,ipriority)"
+offsetof_TINIB_stksz,#!defined(USE_TSKINICTXB),,"offsetof(TINIB,stksz)"
+offsetof_TINIB_stk,#!defined(USE_TSKINICTXB),,"offsetof(TINIB,stk)"
+offsetof_TINIB_texatr,"offsetof(TINIB,texatr)"
+offsetof_TINIB_texrtn,"offsetof(TINIB,texrtn)"
+sizeof_SEMINIB,sizeof(SEMINIB)
+offsetof_SEMINIB_sematr,"offsetof(SEMINIB,sematr)"
+offsetof_SEMINIB_isemcnt,"offsetof(SEMINIB,isemcnt)"
+offsetof_SEMINIB_maxsem,"offsetof(SEMINIB,maxsem)"
+sizeof_FLGPTN,sizeof(FLGPTN)
+sizeof_FLGINIB,sizeof(FLGINIB)
+offsetof_FLGINIB_flgatr,"offsetof(FLGINIB,flgatr)"
+offsetof_FLGINIB_iflgptn,"offsetof(FLGINIB,iflgptn)"
+sizeof_DTQINIB,sizeof(DTQINIB)
+offsetof_DTQINIB_dtqatr,"offsetof(DTQINIB,dtqatr)"
+offsetof_DTQINIB_dtqcnt,"offsetof(DTQINIB,dtqcnt)"
+offsetof_DTQINIB_p_dtqmb,"offsetof(DTQINIB,p_dtqmb)"
+sizeof_PDQINIB,sizeof(PDQINIB)
+offsetof_PDQINIB_pdqatr,"offsetof(PDQINIB,pdqatr)"
+offsetof_PDQINIB_pdqcnt,"offsetof(PDQINIB,pdqcnt)"
+offsetof_PDQINIB_maxdpri,"offsetof(PDQINIB,maxdpri)"
+offsetof_PDQINIB_p_pdqmb,"offsetof(PDQINIB,p_pdqmb)"
+sizeof_MBXINIB,sizeof(MBXINIB)
+offsetof_MBXINIB_mbxatr,"offsetof(MBXINIB,mbxatr)"
+offsetof_MBXINIB_maxmpri,"offsetof(MBXINIB,maxmpri)"
+sizeof_MTXINIB,sizeof(MTXINIB)
+offsetof_MTXINIB_mtxatr,"offsetof(MTXINIB,mtxatr)"
+offsetof_MTXINIB_ceilpri,"offsetof(MTXINIB,ceilpri)"
+sizeof_MPFINIB,sizeof(MPFINIB)
+offsetof_MPFINIB_mpfatr,"offsetof(MPFINIB,mpfatr)"
+offsetof_MPFINIB_blkcnt,"offsetof(MPFINIB,blkcnt)"
+offsetof_MPFINIB_blksz,"offsetof(MPFINIB,blksz)"
+offsetof_MPFINIB_mpf,"offsetof(MPFINIB,mpf)"
+offsetof_MPFINIB_p_mpfmb,"offsetof(MPFINIB,p_mpfmb)"
+sizeof_CYCINIB,sizeof(CYCINIB)
+offsetof_CYCINIB_cycatr,"offsetof(CYCINIB,cycatr)"
+offsetof_CYCINIB_exinf,"offsetof(CYCINIB,exinf)"
+offsetof_CYCINIB_cychdr,"offsetof(CYCINIB,cychdr)"
+offsetof_CYCINIB_cyctim,"offsetof(CYCINIB,cyctim)"
+offsetof_CYCINIB_cycphs,"offsetof(CYCINIB,cycphs)"
+sizeof_ALMINIB,sizeof(ALMINIB)
+offsetof_ALMINIB_almatr,"offsetof(ALMINIB,almatr)"
+offsetof_ALMINIB_exinf,"offsetof(ALMINIB,exinf)"
+offsetof_ALMINIB_almhdr,"offsetof(ALMINIB,almhdr)"
+sizeof_ISRINIB,sizeof(ISRINIB)
+offsetof_ISRINIB_isratr,"offsetof(ISRINIB,isratr)"
+offsetof_ISRINIB_exinf,"offsetof(ISRINIB,exinf)"
+offsetof_ISRINIB_intno,"offsetof(ISRINIB,intno)"
+offsetof_ISRINIB_p_isr_queue,"offsetof(ISRINIB,p_isr_queue)"
+offsetof_ISRINIB_isr,"offsetof(ISRINIB,isr)"
+offsetof_ISRINIB_isrpri,"offsetof(ISRINIB,isrpri)"
+sizeof_INHINIB,#!defined(OMIT_INITIALIZE_INTERRUPT),,sizeof(INHINIB)
+offset_INHINIB_inhno,#!defined(OMIT_INITIALIZE_INTERRUPT),,"offsetof(INHINIB,inhno)"
+offset_INHINIB_inhatr,#!defined(OMIT_INITIALIZE_INTERRUPT),,"offsetof(INHINIB,inhatr)"
+offset_INHINIB_int_entry,#!defined(OMIT_INITIALIZE_INTERRUPT),,"offsetof(INHINIB,int_entry)"
+sizeof_INTINIB,#!defined(OMIT_INITIALIZE_INTERRUPT),,sizeof(INTINIB)
+offset_INTINIB_intno,#!defined(OMIT_INITIALIZE_INTERRUPT),,"offsetof(INTINIB,intno)"
+offset_INTINIB_intatr,#!defined(OMIT_INITIALIZE_INTERRUPT),,"offsetof(INTINIB,intatr)"
+offset_INTINIB_intpri,#!defined(OMIT_INITIALIZE_INTERRUPT),,"offsetof(INTINIB,intpri)"
+sizeof_EXCINIB,#!defined(OMIT_INITIALIZE_EXCEPTION),,sizeof(EXCINIB)
+offset_EXCINIB_excno,#!defined(OMIT_INITIALIZE_EXCEPTION),,"offsetof(EXCINIB,excno)"
+offset_EXCINIB_excatr,#!defined(OMIT_INITIALIZE_EXCEPTION),,"offsetof(EXCINIB,excatr)"
+offset_EXCINIB_exc_entry,#!defined(OMIT_INITIALIZE_EXCEPTION),,"offsetof(EXCINIB,exc_entry)"
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/kernel_impl.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/kernel_impl.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/kernel_impl.h	(revision 453)
@@ -0,0 +1,218 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		TOPPERS/ASPカーネル内部向け標準ヘッダファイル
+ *
+ *  このヘッダファイルは，カーネルを構成するプログラムのソースファイル
+ *  で必ずインクルードするべき標準ヘッダファイルである．
+ *
+ *  アセンブリ言語のソースファイルからこのファイルをインクルードする時
+ *  は，TOPPERS_MACRO_ONLYを定義しておく．これにより，マクロ定義以外を
+ *  除くようになっている．
+ */
+
+#ifndef TOPPERS_KERNEL_IMPL_H
+#define TOPPERS_KERNEL_IMPL_H
+
+/*
+ *  カーネルの内部識別名のリネーム
+ */
+#include "kernel_rename.h"
+
+/*
+ *  アプリケーションと共通のヘッダファイル
+ */
+#include <kernel.h>
+
+/*
+ *  システムログ機能のための定義
+ */
+#include <t_syslog.h>
+
+/*
+ *  型キャストを行うマクロの定義
+ */
+#ifndef CAST
+#define CAST(type, val)		((type)(val))
+#endif /* CAST */
+
+/*
+ *  ターゲット依存情報の定義
+ */
+#include "target_config.h"
+
+/*
+ *  すべての関数をコンパイルするための定義
+ */
+#ifdef ALLFUNC
+#include "allfunc.h"
+#endif /* ALLFUNC */
+
+/*
+ *  ビットフィールドでの符号無し整数型
+ *
+ *  8ビット以下の幅のビットフィールドで，符号無し整数値を保持したい場合
+ *  に用いるべきデータ型．ANSI Cでは，ビットフィールドのデータ型には
+ *  intとunsigned intしか許されないため，デフォルトの定義はunsigned
+ *  intとしているが，ターゲットおよびツール依存で，unsigned charまたは
+ *  unsigned shortに定義した方が効率が良い場合がある．
+ */
+#ifndef BIT_FIELD_UINT
+#define BIT_FIELD_UINT		unsigned int
+#endif /* BIT_FIELD_UINT */
+
+/*
+ *  ビットフィールドでのブール型
+ *
+ *  1ビット幅のビットフィールドで，ブール値を保持したい場合に用いるべき
+ *  データ型．デフォルトではBIT_FIELD_UINTと同一に定義しているが，ブー
+ *  ル値を保持することを明示するために別の名称としている．
+ */
+#ifndef BIT_FIELD_BOOL
+#define BIT_FIELD_BOOL		BIT_FIELD_UINT
+#endif /* BIT_FIELD_BOOL */
+
+/*
+ *  オブジェクトIDの最小値の定義
+ */
+#define TMIN_TSKID		1		/* タスクIDの最小値 */
+#define TMIN_SEMID		1		/* セマフォIDの最小値 */
+#define TMIN_FLGID		1		/* フラグIDの最小値 */
+#define TMIN_DTQID		1		/* データキューIDの最小値 */
+#define TMIN_PDQID		1		/* 優先度データキューIDの最小値 */
+#define TMIN_MBXID		1		/* メールボックスIDの最小値 */
+#define TMIN_MTXID		1		/* ミューテックスIDの最小値 */
+#define TMIN_MPFID		1		/* 固定長メモリプールIDの最小値 */
+#define TMIN_CYCID		1		/* 周期ハンドラIDの最小値 */
+#define TMIN_ALMID		1		/* アラームハンドラIDの最小値 */
+#define TMIN_ISRID		1		/* 割込みサービスルーチンIDの最小値 */
+
+/*
+ *  優先度の段階数の定義
+ */
+#define TNUM_TPRI		(TMAX_TPRI - TMIN_TPRI + 1)
+#define TNUM_MPRI		(TMAX_MPRI - TMIN_MPRI + 1)
+#define TNUM_INTPRI		(TMAX_INTPRI - TMIN_INTPRI + 1)
+
+/*
+ *  カーネル内部で使用する属性の定義
+ */
+#define TA_NOEXS		((ATR)(-1))			/* 未登録状態 */
+
+#ifndef TA_MEMALLOC
+#define TA_MEMALLOC		UINT_C(0x8000)		/* メモリ領域をカーネルで確保 */
+#endif /* TA_MEMALLOC */
+#ifndef TA_MBALLOC
+#define TA_MBALLOC		UINT_C(0x4000)		/* 管理領域をカーネルで確保 */
+#endif /* TA_MBALLOC */
+
+/*
+ *  ターゲット定義のエラーチェックマクロのデフォルト値の定義
+ */
+#ifndef TARGET_TSKATR
+#define TARGET_TSKATR		0U		/* ターゲット定義のタスク属性 */
+#endif /* TARGET_TSKATR */
+
+#ifndef TARGET_ISRATR
+#define TARGET_ISRATR		0U		/* ターゲット定義のISR属性 */
+#endif /* TARGET_ISRATR */
+
+/*
+ *  ヘッダファイルを持たないモジュールの関数・変数の宣言
+ */
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  各モジュールの初期化（kernel_cfg.c）
+ */
+extern void	initialize_object(void);
+
+/*
+ *  初期化ルーチンの実行（kernel_cfg.c）
+ */
+extern void	call_inirtn(void);
+
+/*
+ *  終了処理ルーチンの実行（kernel_cfg.c）
+ */
+extern void	call_terrtn(void);
+
+/*
+ *  非タスクコンテキスト用のスタック領域（kernel_cfg.c）
+ */
+extern const SIZE	istksz;		/* スタック領域のサイズ（丸めた値） */
+extern STK_T *const	istk;		/* スタック領域の先頭番地 */
+#ifdef TOPPERS_ISTKPT
+extern STK_T *const	istkpt;		/* スタックポインタの初期値 */
+#endif /* TOPPERS_ISTKPT */
+
+/*
+ *  カーネルが割り付けるメモリ領域（kernel_cfg.c）
+ */
+extern const SIZE	kmmsz;		/* カーネルが割り付けるメモリ領域のサイズ */
+extern MB_T *const	kmm;		/* カーネルが割り付けるメモリ領域の先頭番地 */
+
+/*
+ *  カーネル動作状態フラグ（startup.c）
+ */
+extern bool_t	kerflg;
+
+/*
+ *  カーネルの起動（startup.c）
+ */
+extern void	sta_ker(void);
+
+/*
+ *  カーネルの終了処理（startup.c）
+ */
+extern void	exit_kernel(void);
+
+/*
+ *  カーネルの割り付けるメモリ領域の管理（startup.c）
+ */
+extern void initialize_kmm(void);
+extern void *kernel_malloc(SIZE size);
+extern void kernel_free(void *ptr);
+
+#endif /* TOPPERS_MACRO_ONLY */
+#endif /* TOPPERS_KERNEL_IMPL_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/kernel_int.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/kernel_int.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/kernel_int.h	(revision 453)
@@ -0,0 +1,84 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2012 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		kernel_cfg.c（およびcfg1_out.c）用ヘッダファイル
+ */
+
+#ifndef TOPPERS_KERNEL_INT_H
+#define TOPPERS_KERNEL_INT_H
+
+/*
+ *  カーネル標準ヘッダファイル
+ */
+#include "kernel_impl.h"
+
+/*
+ *  カーネルの各ヘッダファイル
+ */
+#include "task.h"
+#include "semaphore.h"
+#include "eventflag.h"
+#include "dataqueue.h"
+#include "pridataq.h"
+#include "mailbox.h"
+#include "mutex.h"
+#include "mempfix.h"
+#include "cyclic.h"
+#include "alarm.h"
+#include "interrupt.h"
+#include "exception.h"
+#include "time_event.h"
+
+/*
+ *  リネームしたシンボルを元に戻すためのヘッダファイル
+ */
+#include "kernel_unrename.h"
+
+/*
+ *  内容が空の配列を生成するためのマクロ
+ */
+#ifndef TOPPERS_EMPTY_LABEL
+#define TOPPERS_EMPTY_LABEL(type, var)		type var[0]
+#endif
+
+#endif /* TOPPERS_KERNEL_INT_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/kernel_rename.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/kernel_rename.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/kernel_rename.h	(revision 453)
@@ -0,0 +1,468 @@
+/* This file is generated from kernel_rename.def by genrename. */
+
+#ifndef TOPPERS_KERNEL_RENAME_H
+#define TOPPERS_KERNEL_RENAME_H
+
+/*
+ *  startup.c
+ */
+#define kerflg						_kernel_kerflg
+#define exit_kernel					_kernel_exit_kernel
+#define initialize_kmm				_kernel_initialize_kmm
+#define kernel_malloc				_kernel_kernel_malloc
+#define kernel_free					_kernel_kernel_free
+
+/*
+ *  task.c
+ */
+#define p_runtsk					_kernel_p_runtsk
+#define p_schedtsk					_kernel_p_schedtsk
+#define reqflg						_kernel_reqflg
+#define ipmflg						_kernel_ipmflg
+#define disdsp						_kernel_disdsp
+#define dspflg						_kernel_dspflg
+#define ready_queue					_kernel_ready_queue
+#define ready_primap				_kernel_ready_primap
+#define free_tcb					_kernel_free_tcb
+#define initialize_task				_kernel_initialize_task
+#define search_schedtsk				_kernel_search_schedtsk
+#define make_runnable				_kernel_make_runnable
+#define make_non_runnable			_kernel_make_non_runnable
+#define make_dormant				_kernel_make_dormant
+#define make_active					_kernel_make_active
+#define change_priority				_kernel_change_priority
+#define rotate_ready_queue			_kernel_rotate_ready_queue
+#define call_texrtn					_kernel_call_texrtn
+#define calltex						_kernel_calltex
+
+/*
+ *  wait.c
+ */
+#define make_wait_tmout				_kernel_make_wait_tmout
+#define wait_complete				_kernel_wait_complete
+#define wait_tmout					_kernel_wait_tmout
+#define wait_tmout_ok				_kernel_wait_tmout_ok
+#define wait_release				_kernel_wait_release
+#define wobj_make_wait				_kernel_wobj_make_wait
+#define wobj_make_wait_tmout		_kernel_wobj_make_wait_tmout
+#define init_wait_queue				_kernel_init_wait_queue
+
+/*
+ *  time_event.c
+ */
+#define current_time				_kernel_current_time
+#define min_time					_kernel_min_time
+#define next_time					_kernel_next_time
+#define next_subtime				_kernel_next_subtime
+#define last_index					_kernel_last_index
+#define initialize_tmevt			_kernel_initialize_tmevt
+#define tmevt_up					_kernel_tmevt_up
+#define tmevt_down					_kernel_tmevt_down
+#define tmevtb_insert				_kernel_tmevtb_insert
+#define tmevtb_delete				_kernel_tmevtb_delete
+#define tmevt_lefttim				_kernel_tmevt_lefttim
+#define signal_time					_kernel_signal_time
+
+/*
+ *  semaphore.c
+ */
+#define free_semcb					_kernel_free_semcb
+#define initialize_semaphore		_kernel_initialize_semaphore
+
+/*
+ *  eventflag.c
+ */
+#define free_flgcb					_kernel_free_flgcb
+#define initialize_eventflag		_kernel_initialize_eventflag
+#define check_flg_cond				_kernel_check_flg_cond
+
+/*
+ *  dataqueue.c
+ */
+#define free_dtqcb					_kernel_free_dtqcb
+#define initialize_dataqueue		_kernel_initialize_dataqueue
+#define enqueue_data				_kernel_enqueue_data
+#define force_enqueue_data			_kernel_force_enqueue_data
+#define dequeue_data				_kernel_dequeue_data
+#define send_data					_kernel_send_data
+#define force_send_data				_kernel_force_send_data
+#define receive_data				_kernel_receive_data
+
+/*
+ *  pridataq.c
+ */
+#define free_pdqcb					_kernel_free_pdqcb
+#define initialize_pridataq			_kernel_initialize_pridataq
+#define enqueue_pridata				_kernel_enqueue_pridata
+#define dequeue_pridata				_kernel_dequeue_pridata
+#define send_pridata				_kernel_send_pridata
+#define receive_pridata				_kernel_receive_pridata
+
+/*
+ *  mailbox.c
+ */
+#define free_mbxcb					_kernel_free_mbxcb
+#define initialize_mailbox			_kernel_initialize_mailbox
+
+/*
+ *  mutex.c
+ */
+#define free_mtxcb					_kernel_free_mtxcb
+#define mtxhook_check_ceilpri		_kernel_mtxhook_check_ceilpri
+#define mtxhook_scan_ceilmtx		_kernel_mtxhook_scan_ceilmtx
+#define mtxhook_release_all			_kernel_mtxhook_release_all
+#define initialize_mutex			_kernel_initialize_mutex
+#define mutex_check_ceilpri			_kernel_mutex_check_ceilpri
+#define mutex_scan_ceilmtx			_kernel_mutex_scan_ceilmtx
+#define mutex_calc_priority			_kernel_mutex_calc_priority
+#define mutex_release				_kernel_mutex_release
+#define mutex_release_all			_kernel_mutex_release_all
+
+/*
+ *  mempfix.c
+ */
+#define free_mpfcb					_kernel_free_mpfcb
+#define initialize_mempfix			_kernel_initialize_mempfix
+#define get_mpf_block				_kernel_get_mpf_block
+
+/*
+ *  cyclic.c
+ */
+#define free_cyccb					_kernel_free_cyccb
+#define initialize_cyclic			_kernel_initialize_cyclic
+#define call_cychdr					_kernel_call_cychdr
+
+/*
+ *  alarm.c
+ */
+#define free_almcb					_kernel_free_almcb
+#define initialize_alarm			_kernel_initialize_alarm
+#define call_almhdr					_kernel_call_almhdr
+
+/*
+ *  interrupt.c
+ */
+#define free_isrcb					_kernel_free_isrcb
+#define initialize_isr				_kernel_initialize_isr
+#define call_isr					_kernel_call_isr
+#define initialize_interrupt		_kernel_initialize_interrupt
+
+/*
+ *  exception.c
+ */
+#define initialize_exception		_kernel_initialize_exception
+
+/*
+ *  kernel_cfg.c
+ */
+#define initialize_object			_kernel_initialize_object
+#define call_inirtn					_kernel_call_inirtn
+#define call_terrtn					_kernel_call_terrtn
+#define tmax_tskid					_kernel_tmax_tskid
+#define tmax_stskid					_kernel_tmax_stskid
+#define tinib_table					_kernel_tinib_table
+#define atinib_table				_kernel_atinib_table
+#define tcb_table					_kernel_tcb_table
+#define torder_table				_kernel_torder_table
+#define tmax_semid					_kernel_tmax_semid
+#define tmax_ssemid					_kernel_tmax_ssemid
+#define seminib_table				_kernel_seminib_table
+#define aseminib_table				_kernel_aseminib_table
+#define semcb_table					_kernel_semcb_table
+#define tmax_flgid					_kernel_tmax_flgid
+#define tmax_sflgid					_kernel_tmax_sflgid
+#define flginib_table				_kernel_flginib_table
+#define aflginib_table				_kernel_aflginib_table
+#define flgcb_table					_kernel_flgcb_table
+#define tmax_dtqid					_kernel_tmax_dtqid
+#define tmax_sdtqid					_kernel_tmax_sdtqid
+#define dtqinib_table				_kernel_dtqinib_table
+#define adtqinib_table				_kernel_adtqinib_table
+#define dtqcb_table					_kernel_dtqcb_table
+#define tmax_pdqid					_kernel_tmax_pdqid
+#define tmax_spdqid					_kernel_tmax_spdqid
+#define pdqinib_table				_kernel_pdqinib_table
+#define apdqinib_table				_kernel_apdqinib_table
+#define pdqcb_table					_kernel_pdqcb_table
+#define tmax_mbxid					_kernel_tmax_mbxid
+#define tmax_smbxid					_kernel_tmax_smbxid
+#define mbxinib_table				_kernel_mbxinib_table
+#define ambxinib_table				_kernel_ambxinib_table
+#define mbxcb_table					_kernel_mbxcb_table
+#define tmax_mtxid					_kernel_tmax_mtxid
+#define tmax_smtxid					_kernel_tmax_smtxid
+#define mtxinib_table				_kernel_mtxinib_table
+#define amtxinib_table				_kernel_amtxinib_table
+#define mtxcb_table					_kernel_mtxcb_table
+#define tmax_mpfid					_kernel_tmax_mpfid
+#define tmax_smpfid					_kernel_tmax_smpfid
+#define mpfinib_table				_kernel_mpfinib_table
+#define ampfinib_table				_kernel_ampfinib_table
+#define mpfcb_table					_kernel_mpfcb_table
+#define tmax_cycid					_kernel_tmax_cycid
+#define tmax_scycid					_kernel_tmax_scycid
+#define cycinib_table				_kernel_cycinib_table
+#define acycinib_table				_kernel_acycinib_table
+#define cyccb_table					_kernel_cyccb_table
+#define tmax_almid					_kernel_tmax_almid
+#define tmax_salmid					_kernel_tmax_salmid
+#define alminib_table				_kernel_alminib_table
+#define aalminib_table				_kernel_aalminib_table
+#define almcb_table					_kernel_almcb_table
+#define tnum_isr_queue				_kernel_tnum_isr_queue
+#define isr_queue_table				_kernel_isr_queue_table
+#define isr_queue_list				_kernel_isr_queue_list
+#define tmax_isrid					_kernel_tmax_isrid
+#define tnum_sisr					_kernel_tnum_sisr
+#define sisrinib_table				_kernel_sisrinib_table
+#define aisrinib_table				_kernel_aisrinib_table
+#define isrcb_table					_kernel_isrcb_table
+#define tnum_inhno					_kernel_tnum_inhno
+#define inhinib_table				_kernel_inhinib_table
+#define tnum_intno					_kernel_tnum_intno
+#define intinib_table				_kernel_intinib_table
+#define tnum_excno					_kernel_tnum_excno
+#define excinib_table				_kernel_excinib_table
+#define tmevt_heap					_kernel_tmevt_heap
+#define istksz						_kernel_istksz
+#define istk						_kernel_istk
+#define istkpt						_kernel_istkpt
+#define kmmsz						_kernel_kmmsz
+#define kmm							_kernel_kmm
+
+
+#ifdef TOPPERS_LABEL_ASM
+
+/*
+ *  startup.c
+ */
+#define _kerflg						__kernel_kerflg
+#define _exit_kernel				__kernel_exit_kernel
+#define _initialize_kmm				__kernel_initialize_kmm
+#define _kernel_malloc				__kernel_kernel_malloc
+#define _kernel_free				__kernel_kernel_free
+
+/*
+ *  task.c
+ */
+#define _p_runtsk					__kernel_p_runtsk
+#define _p_schedtsk					__kernel_p_schedtsk
+#define _reqflg						__kernel_reqflg
+#define _ipmflg						__kernel_ipmflg
+#define _disdsp						__kernel_disdsp
+#define _dspflg						__kernel_dspflg
+#define _ready_queue				__kernel_ready_queue
+#define _ready_primap				__kernel_ready_primap
+#define _free_tcb					__kernel_free_tcb
+#define _initialize_task			__kernel_initialize_task
+#define _search_schedtsk			__kernel_search_schedtsk
+#define _make_runnable				__kernel_make_runnable
+#define _make_non_runnable			__kernel_make_non_runnable
+#define _make_dormant				__kernel_make_dormant
+#define _make_active				__kernel_make_active
+#define _change_priority			__kernel_change_priority
+#define _rotate_ready_queue			__kernel_rotate_ready_queue
+#define _call_texrtn				__kernel_call_texrtn
+#define _calltex					__kernel_calltex
+
+/*
+ *  wait.c
+ */
+#define _make_wait_tmout			__kernel_make_wait_tmout
+#define _wait_complete				__kernel_wait_complete
+#define _wait_tmout					__kernel_wait_tmout
+#define _wait_tmout_ok				__kernel_wait_tmout_ok
+#define _wait_release				__kernel_wait_release
+#define _wobj_make_wait				__kernel_wobj_make_wait
+#define _wobj_make_wait_tmout		__kernel_wobj_make_wait_tmout
+#define _init_wait_queue			__kernel_init_wait_queue
+
+/*
+ *  time_event.c
+ */
+#define _current_time				__kernel_current_time
+#define _min_time					__kernel_min_time
+#define _next_time					__kernel_next_time
+#define _next_subtime				__kernel_next_subtime
+#define _last_index					__kernel_last_index
+#define _initialize_tmevt			__kernel_initialize_tmevt
+#define _tmevt_up					__kernel_tmevt_up
+#define _tmevt_down					__kernel_tmevt_down
+#define _tmevtb_insert				__kernel_tmevtb_insert
+#define _tmevtb_delete				__kernel_tmevtb_delete
+#define _tmevt_lefttim				__kernel_tmevt_lefttim
+#define _signal_time				__kernel_signal_time
+
+/*
+ *  semaphore.c
+ */
+#define _free_semcb					__kernel_free_semcb
+#define _initialize_semaphore		__kernel_initialize_semaphore
+
+/*
+ *  eventflag.c
+ */
+#define _free_flgcb					__kernel_free_flgcb
+#define _initialize_eventflag		__kernel_initialize_eventflag
+#define _check_flg_cond				__kernel_check_flg_cond
+
+/*
+ *  dataqueue.c
+ */
+#define _free_dtqcb					__kernel_free_dtqcb
+#define _initialize_dataqueue		__kernel_initialize_dataqueue
+#define _enqueue_data				__kernel_enqueue_data
+#define _force_enqueue_data			__kernel_force_enqueue_data
+#define _dequeue_data				__kernel_dequeue_data
+#define _send_data					__kernel_send_data
+#define _force_send_data			__kernel_force_send_data
+#define _receive_data				__kernel_receive_data
+
+/*
+ *  pridataq.c
+ */
+#define _free_pdqcb					__kernel_free_pdqcb
+#define _initialize_pridataq		__kernel_initialize_pridataq
+#define _enqueue_pridata			__kernel_enqueue_pridata
+#define _dequeue_pridata			__kernel_dequeue_pridata
+#define _send_pridata				__kernel_send_pridata
+#define _receive_pridata			__kernel_receive_pridata
+
+/*
+ *  mailbox.c
+ */
+#define _free_mbxcb					__kernel_free_mbxcb
+#define _initialize_mailbox			__kernel_initialize_mailbox
+
+/*
+ *  mutex.c
+ */
+#define _free_mtxcb					__kernel_free_mtxcb
+#define _mtxhook_check_ceilpri		__kernel_mtxhook_check_ceilpri
+#define _mtxhook_scan_ceilmtx		__kernel_mtxhook_scan_ceilmtx
+#define _mtxhook_release_all		__kernel_mtxhook_release_all
+#define _initialize_mutex			__kernel_initialize_mutex
+#define _mutex_check_ceilpri		__kernel_mutex_check_ceilpri
+#define _mutex_scan_ceilmtx			__kernel_mutex_scan_ceilmtx
+#define _mutex_calc_priority		__kernel_mutex_calc_priority
+#define _mutex_release				__kernel_mutex_release
+#define _mutex_release_all			__kernel_mutex_release_all
+
+/*
+ *  mempfix.c
+ */
+#define _free_mpfcb					__kernel_free_mpfcb
+#define _initialize_mempfix			__kernel_initialize_mempfix
+#define _get_mpf_block				__kernel_get_mpf_block
+
+/*
+ *  cyclic.c
+ */
+#define _free_cyccb					__kernel_free_cyccb
+#define _initialize_cyclic			__kernel_initialize_cyclic
+#define _call_cychdr				__kernel_call_cychdr
+
+/*
+ *  alarm.c
+ */
+#define _free_almcb					__kernel_free_almcb
+#define _initialize_alarm			__kernel_initialize_alarm
+#define _call_almhdr				__kernel_call_almhdr
+
+/*
+ *  interrupt.c
+ */
+#define _free_isrcb					__kernel_free_isrcb
+#define _initialize_isr				__kernel_initialize_isr
+#define _call_isr					__kernel_call_isr
+#define _initialize_interrupt		__kernel_initialize_interrupt
+
+/*
+ *  exception.c
+ */
+#define _initialize_exception		__kernel_initialize_exception
+
+/*
+ *  kernel_cfg.c
+ */
+#define _initialize_object			__kernel_initialize_object
+#define _call_inirtn				__kernel_call_inirtn
+#define _call_terrtn				__kernel_call_terrtn
+#define _tmax_tskid					__kernel_tmax_tskid
+#define _tmax_stskid				__kernel_tmax_stskid
+#define _tinib_table				__kernel_tinib_table
+#define _atinib_table				__kernel_atinib_table
+#define _tcb_table					__kernel_tcb_table
+#define _torder_table				__kernel_torder_table
+#define _tmax_semid					__kernel_tmax_semid
+#define _tmax_ssemid				__kernel_tmax_ssemid
+#define _seminib_table				__kernel_seminib_table
+#define _aseminib_table				__kernel_aseminib_table
+#define _semcb_table				__kernel_semcb_table
+#define _tmax_flgid					__kernel_tmax_flgid
+#define _tmax_sflgid				__kernel_tmax_sflgid
+#define _flginib_table				__kernel_flginib_table
+#define _aflginib_table				__kernel_aflginib_table
+#define _flgcb_table				__kernel_flgcb_table
+#define _tmax_dtqid					__kernel_tmax_dtqid
+#define _tmax_sdtqid				__kernel_tmax_sdtqid
+#define _dtqinib_table				__kernel_dtqinib_table
+#define _adtqinib_table				__kernel_adtqinib_table
+#define _dtqcb_table				__kernel_dtqcb_table
+#define _tmax_pdqid					__kernel_tmax_pdqid
+#define _tmax_spdqid				__kernel_tmax_spdqid
+#define _pdqinib_table				__kernel_pdqinib_table
+#define _apdqinib_table				__kernel_apdqinib_table
+#define _pdqcb_table				__kernel_pdqcb_table
+#define _tmax_mbxid					__kernel_tmax_mbxid
+#define _tmax_smbxid				__kernel_tmax_smbxid
+#define _mbxinib_table				__kernel_mbxinib_table
+#define _ambxinib_table				__kernel_ambxinib_table
+#define _mbxcb_table				__kernel_mbxcb_table
+#define _tmax_mtxid					__kernel_tmax_mtxid
+#define _tmax_smtxid				__kernel_tmax_smtxid
+#define _mtxinib_table				__kernel_mtxinib_table
+#define _amtxinib_table				__kernel_amtxinib_table
+#define _mtxcb_table				__kernel_mtxcb_table
+#define _tmax_mpfid					__kernel_tmax_mpfid
+#define _tmax_smpfid				__kernel_tmax_smpfid
+#define _mpfinib_table				__kernel_mpfinib_table
+#define _ampfinib_table				__kernel_ampfinib_table
+#define _mpfcb_table				__kernel_mpfcb_table
+#define _tmax_cycid					__kernel_tmax_cycid
+#define _tmax_scycid				__kernel_tmax_scycid
+#define _cycinib_table				__kernel_cycinib_table
+#define _acycinib_table				__kernel_acycinib_table
+#define _cyccb_table				__kernel_cyccb_table
+#define _tmax_almid					__kernel_tmax_almid
+#define _tmax_salmid				__kernel_tmax_salmid
+#define _alminib_table				__kernel_alminib_table
+#define _aalminib_table				__kernel_aalminib_table
+#define _almcb_table				__kernel_almcb_table
+#define _tnum_isr_queue				__kernel_tnum_isr_queue
+#define _isr_queue_table			__kernel_isr_queue_table
+#define _isr_queue_list				__kernel_isr_queue_list
+#define _tmax_isrid					__kernel_tmax_isrid
+#define _tnum_sisr					__kernel_tnum_sisr
+#define _sisrinib_table				__kernel_sisrinib_table
+#define _aisrinib_table				__kernel_aisrinib_table
+#define _isrcb_table				__kernel_isrcb_table
+#define _tnum_inhno					__kernel_tnum_inhno
+#define _inhinib_table				__kernel_inhinib_table
+#define _tnum_intno					__kernel_tnum_intno
+#define _intinib_table				__kernel_intinib_table
+#define _tnum_excno					__kernel_tnum_excno
+#define _excinib_table				__kernel_excinib_table
+#define _tmevt_heap					__kernel_tmevt_heap
+#define _istksz						__kernel_istksz
+#define _istk						__kernel_istk
+#define _istkpt						__kernel_istkpt
+#define _kmmsz						__kernel_kmmsz
+#define _kmm						__kernel_kmm
+
+
+#endif /* TOPPERS_LABEL_ASM */
+
+#include "target_rename.h"
+
+#endif /* TOPPERS_KERNEL_RENAME_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/kernel_unrename.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/kernel_unrename.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/kernel_unrename.h	(revision 453)
@@ -0,0 +1,469 @@
+/* This file is generated from kernel_rename.def by genrename. */
+
+/* This file is included only when kernel_rename.h has been included. */
+#ifdef TOPPERS_KERNEL_RENAME_H
+#undef TOPPERS_KERNEL_RENAME_H
+
+/*
+ *  startup.c
+ */
+#undef kerflg
+#undef exit_kernel
+#undef initialize_kmm
+#undef kernel_malloc
+#undef kernel_free
+
+/*
+ *  task.c
+ */
+#undef p_runtsk
+#undef p_schedtsk
+#undef reqflg
+#undef ipmflg
+#undef disdsp
+#undef dspflg
+#undef ready_queue
+#undef ready_primap
+#undef free_tcb
+#undef initialize_task
+#undef search_schedtsk
+#undef make_runnable
+#undef make_non_runnable
+#undef make_dormant
+#undef make_active
+#undef change_priority
+#undef rotate_ready_queue
+#undef call_texrtn
+#undef calltex
+
+/*
+ *  wait.c
+ */
+#undef make_wait_tmout
+#undef wait_complete
+#undef wait_tmout
+#undef wait_tmout_ok
+#undef wait_release
+#undef wobj_make_wait
+#undef wobj_make_wait_tmout
+#undef init_wait_queue
+
+/*
+ *  time_event.c
+ */
+#undef current_time
+#undef min_time
+#undef next_time
+#undef next_subtime
+#undef last_index
+#undef initialize_tmevt
+#undef tmevt_up
+#undef tmevt_down
+#undef tmevtb_insert
+#undef tmevtb_delete
+#undef tmevt_lefttim
+#undef signal_time
+
+/*
+ *  semaphore.c
+ */
+#undef free_semcb
+#undef initialize_semaphore
+
+/*
+ *  eventflag.c
+ */
+#undef free_flgcb
+#undef initialize_eventflag
+#undef check_flg_cond
+
+/*
+ *  dataqueue.c
+ */
+#undef free_dtqcb
+#undef initialize_dataqueue
+#undef enqueue_data
+#undef force_enqueue_data
+#undef dequeue_data
+#undef send_data
+#undef force_send_data
+#undef receive_data
+
+/*
+ *  pridataq.c
+ */
+#undef free_pdqcb
+#undef initialize_pridataq
+#undef enqueue_pridata
+#undef dequeue_pridata
+#undef send_pridata
+#undef receive_pridata
+
+/*
+ *  mailbox.c
+ */
+#undef free_mbxcb
+#undef initialize_mailbox
+
+/*
+ *  mutex.c
+ */
+#undef free_mtxcb
+#undef mtxhook_check_ceilpri
+#undef mtxhook_scan_ceilmtx
+#undef mtxhook_release_all
+#undef initialize_mutex
+#undef mutex_check_ceilpri
+#undef mutex_scan_ceilmtx
+#undef mutex_calc_priority
+#undef mutex_release
+#undef mutex_release_all
+
+/*
+ *  mempfix.c
+ */
+#undef free_mpfcb
+#undef initialize_mempfix
+#undef get_mpf_block
+
+/*
+ *  cyclic.c
+ */
+#undef free_cyccb
+#undef initialize_cyclic
+#undef call_cychdr
+
+/*
+ *  alarm.c
+ */
+#undef free_almcb
+#undef initialize_alarm
+#undef call_almhdr
+
+/*
+ *  interrupt.c
+ */
+#undef free_isrcb
+#undef initialize_isr
+#undef call_isr
+#undef initialize_interrupt
+
+/*
+ *  exception.c
+ */
+#undef initialize_exception
+
+/*
+ *  kernel_cfg.c
+ */
+#undef initialize_object
+#undef call_inirtn
+#undef call_terrtn
+#undef tmax_tskid
+#undef tmax_stskid
+#undef tinib_table
+#undef atinib_table
+#undef tcb_table
+#undef torder_table
+#undef tmax_semid
+#undef tmax_ssemid
+#undef seminib_table
+#undef aseminib_table
+#undef semcb_table
+#undef tmax_flgid
+#undef tmax_sflgid
+#undef flginib_table
+#undef aflginib_table
+#undef flgcb_table
+#undef tmax_dtqid
+#undef tmax_sdtqid
+#undef dtqinib_table
+#undef adtqinib_table
+#undef dtqcb_table
+#undef tmax_pdqid
+#undef tmax_spdqid
+#undef pdqinib_table
+#undef apdqinib_table
+#undef pdqcb_table
+#undef tmax_mbxid
+#undef tmax_smbxid
+#undef mbxinib_table
+#undef ambxinib_table
+#undef mbxcb_table
+#undef tmax_mtxid
+#undef tmax_smtxid
+#undef mtxinib_table
+#undef amtxinib_table
+#undef mtxcb_table
+#undef tmax_mpfid
+#undef tmax_smpfid
+#undef mpfinib_table
+#undef ampfinib_table
+#undef mpfcb_table
+#undef tmax_cycid
+#undef tmax_scycid
+#undef cycinib_table
+#undef acycinib_table
+#undef cyccb_table
+#undef tmax_almid
+#undef tmax_salmid
+#undef alminib_table
+#undef aalminib_table
+#undef almcb_table
+#undef tnum_isr_queue
+#undef isr_queue_table
+#undef isr_queue_list
+#undef tmax_isrid
+#undef tnum_sisr
+#undef sisrinib_table
+#undef aisrinib_table
+#undef isrcb_table
+#undef tnum_inhno
+#undef inhinib_table
+#undef tnum_intno
+#undef intinib_table
+#undef tnum_excno
+#undef excinib_table
+#undef tmevt_heap
+#undef istksz
+#undef istk
+#undef istkpt
+#undef kmmsz
+#undef kmm
+
+
+#ifdef TOPPERS_LABEL_ASM
+
+/*
+ *  startup.c
+ */
+#undef _kerflg
+#undef _exit_kernel
+#undef _initialize_kmm
+#undef _kernel_malloc
+#undef _kernel_free
+
+/*
+ *  task.c
+ */
+#undef _p_runtsk
+#undef _p_schedtsk
+#undef _reqflg
+#undef _ipmflg
+#undef _disdsp
+#undef _dspflg
+#undef _ready_queue
+#undef _ready_primap
+#undef _free_tcb
+#undef _initialize_task
+#undef _search_schedtsk
+#undef _make_runnable
+#undef _make_non_runnable
+#undef _make_dormant
+#undef _make_active
+#undef _change_priority
+#undef _rotate_ready_queue
+#undef _call_texrtn
+#undef _calltex
+
+/*
+ *  wait.c
+ */
+#undef _make_wait_tmout
+#undef _wait_complete
+#undef _wait_tmout
+#undef _wait_tmout_ok
+#undef _wait_release
+#undef _wobj_make_wait
+#undef _wobj_make_wait_tmout
+#undef _init_wait_queue
+
+/*
+ *  time_event.c
+ */
+#undef _current_time
+#undef _min_time
+#undef _next_time
+#undef _next_subtime
+#undef _last_index
+#undef _initialize_tmevt
+#undef _tmevt_up
+#undef _tmevt_down
+#undef _tmevtb_insert
+#undef _tmevtb_delete
+#undef _tmevt_lefttim
+#undef _signal_time
+
+/*
+ *  semaphore.c
+ */
+#undef _free_semcb
+#undef _initialize_semaphore
+
+/*
+ *  eventflag.c
+ */
+#undef _free_flgcb
+#undef _initialize_eventflag
+#undef _check_flg_cond
+
+/*
+ *  dataqueue.c
+ */
+#undef _free_dtqcb
+#undef _initialize_dataqueue
+#undef _enqueue_data
+#undef _force_enqueue_data
+#undef _dequeue_data
+#undef _send_data
+#undef _force_send_data
+#undef _receive_data
+
+/*
+ *  pridataq.c
+ */
+#undef _free_pdqcb
+#undef _initialize_pridataq
+#undef _enqueue_pridata
+#undef _dequeue_pridata
+#undef _send_pridata
+#undef _receive_pridata
+
+/*
+ *  mailbox.c
+ */
+#undef _free_mbxcb
+#undef _initialize_mailbox
+
+/*
+ *  mutex.c
+ */
+#undef _free_mtxcb
+#undef _mtxhook_check_ceilpri
+#undef _mtxhook_scan_ceilmtx
+#undef _mtxhook_release_all
+#undef _initialize_mutex
+#undef _mutex_check_ceilpri
+#undef _mutex_scan_ceilmtx
+#undef _mutex_calc_priority
+#undef _mutex_release
+#undef _mutex_release_all
+
+/*
+ *  mempfix.c
+ */
+#undef _free_mpfcb
+#undef _initialize_mempfix
+#undef _get_mpf_block
+
+/*
+ *  cyclic.c
+ */
+#undef _free_cyccb
+#undef _initialize_cyclic
+#undef _call_cychdr
+
+/*
+ *  alarm.c
+ */
+#undef _free_almcb
+#undef _initialize_alarm
+#undef _call_almhdr
+
+/*
+ *  interrupt.c
+ */
+#undef _free_isrcb
+#undef _initialize_isr
+#undef _call_isr
+#undef _initialize_interrupt
+
+/*
+ *  exception.c
+ */
+#undef _initialize_exception
+
+/*
+ *  kernel_cfg.c
+ */
+#undef _initialize_object
+#undef _call_inirtn
+#undef _call_terrtn
+#undef _tmax_tskid
+#undef _tmax_stskid
+#undef _tinib_table
+#undef _atinib_table
+#undef _tcb_table
+#undef _torder_table
+#undef _tmax_semid
+#undef _tmax_ssemid
+#undef _seminib_table
+#undef _aseminib_table
+#undef _semcb_table
+#undef _tmax_flgid
+#undef _tmax_sflgid
+#undef _flginib_table
+#undef _aflginib_table
+#undef _flgcb_table
+#undef _tmax_dtqid
+#undef _tmax_sdtqid
+#undef _dtqinib_table
+#undef _adtqinib_table
+#undef _dtqcb_table
+#undef _tmax_pdqid
+#undef _tmax_spdqid
+#undef _pdqinib_table
+#undef _apdqinib_table
+#undef _pdqcb_table
+#undef _tmax_mbxid
+#undef _tmax_smbxid
+#undef _mbxinib_table
+#undef _ambxinib_table
+#undef _mbxcb_table
+#undef _tmax_mtxid
+#undef _tmax_smtxid
+#undef _mtxinib_table
+#undef _amtxinib_table
+#undef _mtxcb_table
+#undef _tmax_mpfid
+#undef _tmax_smpfid
+#undef _mpfinib_table
+#undef _ampfinib_table
+#undef _mpfcb_table
+#undef _tmax_cycid
+#undef _tmax_scycid
+#undef _cycinib_table
+#undef _acycinib_table
+#undef _cyccb_table
+#undef _tmax_almid
+#undef _tmax_salmid
+#undef _alminib_table
+#undef _aalminib_table
+#undef _almcb_table
+#undef _tnum_isr_queue
+#undef _isr_queue_table
+#undef _isr_queue_list
+#undef _tmax_isrid
+#undef _tnum_sisr
+#undef _sisrinib_table
+#undef _aisrinib_table
+#undef _isrcb_table
+#undef _tnum_inhno
+#undef _inhinib_table
+#undef _tnum_intno
+#undef _intinib_table
+#undef _tnum_excno
+#undef _excinib_table
+#undef _tmevt_heap
+#undef _istksz
+#undef _istk
+#undef _istkpt
+#undef _kmmsz
+#undef _kmm
+
+
+#endif /* TOPPERS_LABEL_ASM */
+
+#include "target_unrename.h"
+
+#endif /* TOPPERS_KERNEL_RENAME_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/mailbox.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/mailbox.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/mailbox.c	(revision 453)
@@ -0,0 +1,534 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2014 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		メールボックス機能
+ */
+
+#include "kernel_impl.h"
+#include "check.h"
+#include "task.h"
+#include "wait.h"
+#include "mailbox.h"
+
+/*
+ *  トレースログマクロのデフォルト定義
+ */
+#ifndef LOG_ACRE_MBX_ENTER
+#define LOG_ACRE_MBX_ENTER(pk_cmbx)
+#endif /* LOG_ACRE_MBX_ENTER */
+
+#ifndef LOG_ACRE_MBX_LEAVE
+#define LOG_ACRE_MBX_LEAVE(ercd)
+#endif /* LOG_ACRE_MBX_LEAVE */
+
+#ifndef LOG_DEL_MBX_ENTER
+#define LOG_DEL_MBX_ENTER(mbxid)
+#endif /* LOG_DEL_MBX_ENTER */
+
+#ifndef LOG_DEL_MBX_LEAVE
+#define LOG_DEL_MBX_LEAVE(ercd)
+#endif /* LOG_DEL_MBX_LEAVE */
+
+#ifndef LOG_SND_MBX_ENTER
+#define LOG_SND_MBX_ENTER(mbxid, pk_msg)
+#endif /* LOG_SND_MBX_ENTER */
+
+#ifndef LOG_SND_MBX_LEAVE
+#define LOG_SND_MBX_LEAVE(ercd)
+#endif /* LOG_SND_MBX_LEAVE */
+
+#ifndef LOG_RCV_MBX_ENTER
+#define LOG_RCV_MBX_ENTER(mbxid, ppk_msg)
+#endif /* LOG_RCV_MBX_ENTER */
+
+#ifndef LOG_RCV_MBX_LEAVE
+#define LOG_RCV_MBX_LEAVE(ercd, pk_msg)
+#endif /* LOG_RCV_MBX_LEAVE */
+
+#ifndef LOG_PRCV_MBX_ENTER
+#define LOG_PRCV_MBX_ENTER(mbxid, ppk_msg)
+#endif /* LOG_PRCV_MBX_ENTER */
+
+#ifndef LOG_PRCV_MBX_LEAVE
+#define LOG_PRCV_MBX_LEAVE(ercd, pk_msg)
+#endif /* LOG_PRCV_MBX_LEAVE */
+
+#ifndef LOG_TRCV_MBX_ENTER
+#define LOG_TRCV_MBX_ENTER(mbxid, ppk_msg, tmout)
+#endif /* LOG_TRCV_MBX_ENTER */
+
+#ifndef LOG_TRCV_MBX_LEAVE
+#define LOG_TRCV_MBX_LEAVE(ercd, pk_msg)
+#endif /* LOG_TRCV_MBX_LEAVE */
+
+#ifndef LOG_INI_MBX_ENTER
+#define LOG_INI_MBX_ENTER(mbxid)
+#endif /* LOG_INI_MBX_ENTER */
+
+#ifndef LOG_INI_MBX_LEAVE
+#define LOG_INI_MBX_LEAVE(ercd)
+#endif /* LOG_INI_MBX_LEAVE */
+
+#ifndef LOG_REF_MBX_ENTER
+#define LOG_REF_MBX_ENTER(mbxid, pk_rmbx)
+#endif /* LOG_REF_MBX_ENTER */
+
+#ifndef LOG_REF_MBX_LEAVE
+#define LOG_REF_MBX_LEAVE(ercd, pk_rmbx)
+#endif /* LOG_REF_MBX_LEAVE */
+
+/*
+ *  メールボックスの数
+ */
+#define tnum_mbx	((uint_t)(tmax_mbxid - TMIN_MBXID + 1))
+#define tnum_smbx	((uint_t)(tmax_smbxid - TMIN_MBXID + 1))
+
+/*
+ *  メールボックスIDからメールボックス管理ブロックを取り出すためのマクロ
+ */
+#define INDEX_MBX(mbxid)	((uint_t)((mbxid) - TMIN_MBXID))
+#define get_mbxcb(mbxid)	(&(mbxcb_table[INDEX_MBX(mbxid)]))
+
+#ifdef TOPPERS_mbxini
+
+/*
+ *  使用していないメールボックス管理ブロックのリスト
+ */
+QUEUE	free_mbxcb;
+
+/* 
+ *  メールボックス機能の初期化
+ */
+void
+initialize_mailbox(void)
+{
+	uint_t	i, j;
+	MBXCB	*p_mbxcb;
+	MBXINIB	*p_mbxinib;
+
+	for (i = 0; i < tnum_smbx; i++) {
+		p_mbxcb = &(mbxcb_table[i]);
+		queue_initialize(&(p_mbxcb->wait_queue));
+		p_mbxcb->p_mbxinib = &(mbxinib_table[i]);
+		p_mbxcb->pk_head = NULL;
+	}
+	queue_initialize(&free_mbxcb);
+	for (j = 0; i < tnum_mbx; i++, j++) {
+		p_mbxcb = &(mbxcb_table[i]);
+		p_mbxinib = &(ambxinib_table[j]);
+		p_mbxinib->mbxatr = TA_NOEXS;
+		p_mbxcb->p_mbxinib = ((const MBXINIB *) p_mbxinib);
+		queue_insert_prev(&free_mbxcb, &(p_mbxcb->wait_queue));
+	}
+}
+
+#endif /* TOPPERS_mbxini */
+
+/*
+ *  メッセージ優先度の取出し
+ */
+#define	MSGPRI(pk_msg)	(((T_MSG_PRI *)(pk_msg))->msgpri)
+
+/*
+ *  優先度順メッセージキューへの挿入
+ */
+Inline void
+enqueue_msg_pri(T_MSG **ppk_prevmsg_next, T_MSG *pk_msg)
+{
+	T_MSG	*pk_nextmsg;
+
+	while ((pk_nextmsg = *ppk_prevmsg_next) != NULL) {
+		if (MSGPRI(pk_nextmsg) > MSGPRI(pk_msg)) {
+			break;
+		}
+		ppk_prevmsg_next = &(pk_nextmsg->pk_next);
+	}
+	pk_msg->pk_next = pk_nextmsg;
+	*ppk_prevmsg_next = pk_msg;
+}
+
+/*
+ *  メールボックスの生成
+ */
+#ifdef TOPPERS_acre_mbx
+
+ER_UINT
+acre_mbx(const T_CMBX *pk_cmbx)
+{
+	MBXCB	*p_mbxcb;
+	MBXINIB	*p_mbxinib;
+	ER		ercd;
+
+	LOG_ACRE_MBX_ENTER(pk_cmbx);
+	CHECK_TSKCTX_UNL();
+	CHECK_RSATR(pk_cmbx->mbxatr, TA_TPRI|TA_MPRI);
+	CHECK_MPRI(pk_cmbx->maxmpri);
+	CHECK_NOSPT(pk_cmbx->mprihd == NULL);
+
+	t_lock_cpu();
+	if (tnum_mbx == 0 || queue_empty(&free_mbxcb)) {
+		ercd = E_NOID;
+	}
+	else {
+		p_mbxcb = ((MBXCB *) queue_delete_next(&free_mbxcb));
+		p_mbxinib = (MBXINIB *)(p_mbxcb->p_mbxinib);
+		p_mbxinib->mbxatr = pk_cmbx->mbxatr;
+		p_mbxinib->maxmpri = pk_cmbx->maxmpri;
+
+		queue_initialize(&(p_mbxcb->wait_queue));
+		p_mbxcb->pk_head = NULL;
+		ercd = MBXID(p_mbxcb);
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_ACRE_MBX_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_acre_mbx */
+
+/*
+ *  メールボックスの削除
+ */
+#ifdef TOPPERS_del_mbx
+
+ER
+del_mbx(ID mbxid)
+{
+	MBXCB	*p_mbxcb;
+	MBXINIB	*p_mbxinib;
+	bool_t	dspreq;
+	ER		ercd;
+
+	LOG_DEL_MBX_ENTER(mbxid);
+	CHECK_TSKCTX_UNL();
+	CHECK_MBXID(mbxid);
+	p_mbxcb = get_mbxcb(mbxid);
+
+	t_lock_cpu();
+	if (p_mbxcb->p_mbxinib->mbxatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (MBXID(p_mbxcb) > tmax_smbxid) {
+		dspreq = init_wait_queue(&(p_mbxcb->wait_queue));
+		p_mbxinib = (MBXINIB *)(p_mbxcb->p_mbxinib);
+		p_mbxinib->mbxatr = TA_NOEXS;
+		queue_insert_prev(&free_mbxcb, &(p_mbxcb->wait_queue));
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_OBJ;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_DEL_MBX_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_del_mbx */
+
+/*
+ *  メールボックスへの送信
+ */
+#ifdef TOPPERS_snd_mbx
+
+ER
+snd_mbx(ID mbxid, T_MSG *pk_msg)
+{
+	MBXCB	*p_mbxcb;
+	TCB		*p_tcb;
+	ER		ercd;
+    
+	LOG_SND_MBX_ENTER(mbxid, pk_msg);
+	CHECK_TSKCTX_UNL();
+	CHECK_MBXID(mbxid);
+	p_mbxcb = get_mbxcb(mbxid);
+
+	t_lock_cpu();
+	if (p_mbxcb->p_mbxinib->mbxatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (!((p_mbxcb->p_mbxinib->mbxatr & TA_MPRI) == 0U
+				|| (TMIN_MPRI <= MSGPRI(pk_msg)
+					&& MSGPRI(pk_msg) <= p_mbxcb->p_mbxinib->maxmpri))) {
+		ercd = E_PAR;
+	}
+	else if (!queue_empty(&(p_mbxcb->wait_queue))) {
+		p_tcb = (TCB *) queue_delete_next(&(p_mbxcb->wait_queue));
+		((WINFO_MBX *)(p_tcb->p_winfo))->pk_msg = pk_msg;
+		if (wait_complete(p_tcb)) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	else if ((p_mbxcb->p_mbxinib->mbxatr & TA_MPRI) != 0U) {
+		enqueue_msg_pri(&(p_mbxcb->pk_head), pk_msg);
+		ercd = E_OK;
+	}
+	else {
+		pk_msg->pk_next = NULL;
+		if (p_mbxcb->pk_head != NULL) {
+			p_mbxcb->pk_last->pk_next = pk_msg;
+		}
+		else {
+			p_mbxcb->pk_head = pk_msg;
+		}
+		p_mbxcb->pk_last = pk_msg;
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_SND_MBX_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_snd_mbx */
+
+/*
+ *  メールボックスからの受信
+ */
+#ifdef TOPPERS_rcv_mbx
+
+ER
+rcv_mbx(ID mbxid, T_MSG **ppk_msg)
+{
+	MBXCB	*p_mbxcb;
+	WINFO_MBX winfo_mbx;
+	ER		ercd;
+    
+	LOG_RCV_MBX_ENTER(mbxid, ppk_msg);
+	CHECK_DISPATCH();
+	CHECK_MBXID(mbxid);
+	p_mbxcb = get_mbxcb(mbxid);
+    
+	t_lock_cpu();
+	if (p_mbxcb->p_mbxinib->mbxatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (p_mbxcb->pk_head != NULL) {
+		*ppk_msg = p_mbxcb->pk_head;
+		p_mbxcb->pk_head = (*ppk_msg)->pk_next;
+		ercd = E_OK;
+	}
+	else {
+		p_runtsk->tstat = (TS_WAITING | TS_WAIT_MBX);
+		wobj_make_wait((WOBJCB *) p_mbxcb, (WINFO_WOBJ *) &winfo_mbx);
+		dispatch();
+		ercd = winfo_mbx.winfo.wercd;
+		if (ercd == E_OK) {
+			*ppk_msg = winfo_mbx.pk_msg;
+		}
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_RCV_MBX_LEAVE(ercd, *ppk_msg);
+	return(ercd);
+}
+
+#endif /* TOPPERS_rcv_mbx */
+
+/*
+ *  メールボックスからの受信（ポーリング）
+ */
+#ifdef TOPPERS_prcv_mbx
+
+ER
+prcv_mbx(ID mbxid, T_MSG **ppk_msg)
+{
+	MBXCB	*p_mbxcb;
+	ER		ercd;
+    
+	LOG_PRCV_MBX_ENTER(mbxid, ppk_msg);
+	CHECK_TSKCTX_UNL();
+	CHECK_MBXID(mbxid);
+	p_mbxcb = get_mbxcb(mbxid);
+    
+	t_lock_cpu();
+	if (p_mbxcb->p_mbxinib->mbxatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (p_mbxcb->pk_head != NULL) {
+		*ppk_msg = p_mbxcb->pk_head;
+		p_mbxcb->pk_head = (*ppk_msg)->pk_next;
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_TMOUT;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_PRCV_MBX_LEAVE(ercd, *ppk_msg);
+	return(ercd);
+}
+
+#endif /* TOPPERS_prcv_mbx */
+
+/*
+ *  メールボックスからの受信（タイムアウトあり）
+ */
+#ifdef TOPPERS_trcv_mbx
+
+ER
+trcv_mbx(ID mbxid, T_MSG **ppk_msg, TMO tmout)
+{
+	MBXCB	*p_mbxcb;
+	WINFO_MBX winfo_mbx;
+	TMEVTB	tmevtb;
+	ER		ercd;
+    
+	LOG_TRCV_MBX_ENTER(mbxid, ppk_msg, tmout);
+	CHECK_DISPATCH();
+	CHECK_MBXID(mbxid);
+	CHECK_TMOUT(tmout);
+	p_mbxcb = get_mbxcb(mbxid);
+    
+	t_lock_cpu();
+	if (p_mbxcb->p_mbxinib->mbxatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (p_mbxcb->pk_head != NULL) {
+		*ppk_msg = p_mbxcb->pk_head;
+		p_mbxcb->pk_head = (*ppk_msg)->pk_next;
+		ercd = E_OK;
+	}
+	else if (tmout == TMO_POL) {
+		ercd = E_TMOUT;
+	}
+	else {
+		p_runtsk->tstat = (TS_WAITING | TS_WAIT_MBX);
+		wobj_make_wait_tmout((WOBJCB *) p_mbxcb, (WINFO_WOBJ *) &winfo_mbx,
+														&tmevtb, tmout);
+		dispatch();
+		ercd = winfo_mbx.winfo.wercd;
+		if (ercd == E_OK) {
+			*ppk_msg = winfo_mbx.pk_msg;
+		}
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_TRCV_MBX_LEAVE(ercd, *ppk_msg);
+	return(ercd);
+}
+
+#endif /* TOPPERS_trcv_mbx */
+
+/*
+ *  メールボックスの再初期化
+ */
+#ifdef TOPPERS_ini_mbx
+
+ER
+ini_mbx(ID mbxid)
+{
+	MBXCB	*p_mbxcb;
+	bool_t	dspreq;
+	ER		ercd;
+    
+	LOG_INI_MBX_ENTER(mbxid);
+	CHECK_TSKCTX_UNL();
+	CHECK_MBXID(mbxid);
+	p_mbxcb = get_mbxcb(mbxid);
+
+	t_lock_cpu();
+	if (p_mbxcb->p_mbxinib->mbxatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		dspreq = init_wait_queue(&(p_mbxcb->wait_queue));
+		p_mbxcb->pk_head = NULL;
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_INI_MBX_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ini_mbx */
+
+/*
+ *  メールボックスの状態参照
+ */
+#ifdef TOPPERS_ref_mbx
+
+ER
+ref_mbx(ID mbxid, T_RMBX *pk_rmbx)
+{
+	MBXCB	*p_mbxcb;
+	ER		ercd;
+    
+	LOG_REF_MBX_ENTER(mbxid, pk_rmbx);
+	CHECK_TSKCTX_UNL();
+	CHECK_MBXID(mbxid);
+	p_mbxcb = get_mbxcb(mbxid);
+
+	t_lock_cpu();
+	if (p_mbxcb->p_mbxinib->mbxatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		pk_rmbx->wtskid = wait_tskid(&(p_mbxcb->wait_queue));
+		pk_rmbx->pk_msg = p_mbxcb->pk_head;
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_REF_MBX_LEAVE(ercd, pk_rmbx);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ref_mbx */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/mailbox.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/mailbox.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/mailbox.h	(revision 453)
@@ -0,0 +1,127 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2012 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		メールボックス機能
+ */
+
+#ifndef TOPPERS_MAILBOX_H
+#define TOPPERS_MAILBOX_H
+
+#include "wait.h"
+
+/*
+ *  メールボックス初期化ブロック
+ *
+ *  この構造体は，同期・通信オブジェクトの初期化ブロックの共通部分
+ *  （WOBJINIB）を拡張（オブジェクト指向言語の継承に相当）したもので，
+ *  最初のフィールドが共通になっている．
+ */
+typedef struct mailbox_initialization_block {
+	ATR			mbxatr;			/* メールボックス属性 */
+	PRI			maxmpri;		/* メッセージ優先度の最大値 */
+} MBXINIB;
+
+/*
+ *  メールボックス管理ブロック
+ *
+ *  この構造体は，同期・通信オブジェクトの管理ブロックの共通部分（WOBJCB）
+ *  を拡張（オブジェクト指向言語の継承に相当）したもので，最初の2つの
+ *  フィールドが共通になっている．
+ *
+ *  メッセージキューがメッセージの優先度順の場合には，pk_lastは使わな
+ *  い．また，メッセージキューが空の場合（pk_headがNULLの場合）にも，
+ *  pk_lastは無効である．
+ */
+typedef struct mailbox_control_block {
+	QUEUE		wait_queue;		/* メールボックス待ちキュー */
+	const MBXINIB *p_mbxinib;	/* 初期化ブロックへのポインタ */
+	T_MSG		*pk_head;		/* 先頭のメッセージ */
+	T_MSG		*pk_last;		/* 末尾のメッセージ */
+} MBXCB;
+
+/*
+ *  メールボックス待ち情報ブロックの定義
+ *
+ *  この構造体は，同期・通信オブジェクトの待ち情報ブロックの共通部分
+ *  （WINFO_WOBJ）を拡張（オブジェクト指向言語の継承に相当）したもので，
+ *  最初の2つのフィールドが共通になっている．
+ */
+typedef struct mailbox_waiting_information {
+	WINFO		winfo;			/* 標準の待ち情報ブロック */
+	MBXCB		*p_mbxcb;		/* 待っているメールボックスの管理ブロック */
+	T_MSG		*pk_msg;		/* 受信したメッセージ */
+} WINFO_MBX;
+
+/*
+ *  使用していないメールボックス管理ブロックのリスト
+ */
+extern QUEUE	free_mbxcb;
+
+/*
+ *  メールボックスIDの最大値（kernel_cfg.c）
+ */
+extern const ID	tmax_mbxid;
+extern const ID	tmax_smbxid;
+
+/*
+ *  メールボックス初期化ブロックのエリア（kernel_cfg.c）
+ */
+extern const MBXINIB	mbxinib_table[];
+extern MBXINIB			ambxinib_table[];
+
+/*
+ *  メールボックス管理ブロックのエリア（kernel_cfg.c）
+ */
+extern MBXCB	mbxcb_table[];
+
+/*
+ *  メールボックス管理ブロックからメールボックスIDを取り出すためのマクロ
+ */
+#define	MBXID(p_mbxcb)	((ID)(((p_mbxcb) - mbxcb_table) + TMIN_MBXID))
+
+/*
+ *  メールボックス機能の初期化
+ */
+extern void	initialize_mailbox(void);
+
+#endif /* TOPPERS_MAILBOX_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/mempfix.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/mempfix.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/mempfix.c	(revision 453)
@@ -0,0 +1,588 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2014 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		固定長メモリプール機能
+ */
+
+#include "kernel_impl.h"
+#include "check.h"
+#include "task.h"
+#include "wait.h"
+#include "mempfix.h"
+
+/*
+ *  トレースログマクロのデフォルト定義
+ */
+#ifndef LOG_ACRE_MPF_ENTER
+#define LOG_ACRE_MPF_ENTER(pk_cmpf)
+#endif /* LOG_ACRE_MPF_ENTER */
+
+#ifndef LOG_ACRE_MPF_LEAVE
+#define LOG_ACRE_MPF_LEAVE(ercd)
+#endif /* LOG_ACRE_MPF_LEAVE */
+
+#ifndef LOG_DEL_MPF_ENTER
+#define LOG_DEL_MPF_ENTER(mpfid)
+#endif /* LOG_DEL_MPF_ENTER */
+
+#ifndef LOG_DEL_MPF_LEAVE
+#define LOG_DEL_MPF_LEAVE(ercd)
+#endif /* LOG_DEL_MPF_LEAVE */
+
+#ifndef LOG_GET_MPF_ENTER
+#define LOG_GET_MPF_ENTER(mpfid, p_blk)
+#endif /* LOG_GET_MPF_ENTER */
+
+#ifndef LOG_GET_MPF_LEAVE
+#define LOG_GET_MPF_LEAVE(ercd, blk)
+#endif /* LOG_GET_MPF_LEAVE */
+
+#ifndef LOG_PGET_MPF_ENTER
+#define LOG_PGET_MPF_ENTER(mpfid, p_blk)
+#endif /* LOG_PGET_MPF_ENTER */
+
+#ifndef LOG_PGET_MPF_LEAVE
+#define LOG_PGET_MPF_LEAVE(ercd, blk)
+#endif /* LOG_PGET_MPF_LEAVE */
+
+#ifndef LOG_TGET_MPF_ENTER
+#define LOG_TGET_MPF_ENTER(mpfid, p_blk, tmout)
+#endif /* LOG_TGET_MPF_ENTER */
+
+#ifndef LOG_TGET_MPF_LEAVE
+#define LOG_TGET_MPF_LEAVE(ercd, blk)
+#endif /* LOG_TGET_MPF_LEAVE */
+
+#ifndef LOG_REL_MPF_ENTER
+#define LOG_REL_MPF_ENTER(mpfid, blk)
+#endif /* LOG_REL_MPF_ENTER */
+
+#ifndef LOG_REL_MPF_LEAVE
+#define LOG_REL_MPF_LEAVE(ercd)
+#endif /* LOG_REL_MPF_LEAVE */
+
+#ifndef LOG_INI_MPF_ENTER
+#define LOG_INI_MPF_ENTER(mpfid)
+#endif /* LOG_INI_MPF_ENTER */
+
+#ifndef LOG_INI_MPF_LEAVE
+#define LOG_INI_MPF_LEAVE(ercd)
+#endif /* LOG_INI_MPF_LEAVE */
+
+#ifndef LOG_REF_MPF_ENTER
+#define LOG_REF_MPF_ENTER(mpfid, pk_rmpf)
+#endif /* LOG_REF_MPF_ENTER */
+
+#ifndef LOG_REF_MPF_LEAVE
+#define LOG_REF_MPF_LEAVE(ercd, pk_rmpf)
+#endif /* LOG_REF_MPF_LEAVE */
+
+/*
+ *  固定長メモリプールの数
+ */
+#define tnum_mpf	((uint_t)(tmax_mpfid - TMIN_MPFID + 1))
+#define tnum_smpf	((uint_t)(tmax_smpfid - TMIN_MPFID + 1))
+
+/*
+ *  固定長メモリプールIDから固定長メモリプール管理ブロックを取り出すた
+ *  めのマクロ
+ */
+#define INDEX_MPF(mpfid)	((uint_t)((mpfid) - TMIN_MPFID))
+#define get_mpfcb(mpfid)	(&(mpfcb_table[INDEX_MPF(mpfid)]))
+
+/*
+ *  特殊なインデックス値の定義
+ */
+#define INDEX_NULL		(~0U)		/* 空きブロックリストの最後 */
+#define INDEX_ALLOC		(~1U)		/* 割当て済みのブロック */
+
+#ifdef TOPPERS_mpfini
+
+/*
+ *  使用していない固定長メモリプール管理ブロックのリスト
+ */
+QUEUE	free_mpfcb;
+
+/*
+ *  固定長メモリプール機能の初期化
+ */
+void
+initialize_mempfix(void)
+{
+	uint_t	i, j;
+	MPFCB	*p_mpfcb;
+	MPFINIB	*p_mpfinib;
+
+	for (i = 0; i < tnum_smpf; i++) {
+		p_mpfcb = &(mpfcb_table[i]);
+		queue_initialize(&(p_mpfcb->wait_queue));
+		p_mpfcb->p_mpfinib = &(mpfinib_table[i]);
+		p_mpfcb->fblkcnt = p_mpfcb->p_mpfinib->blkcnt;
+		p_mpfcb->unused = 0U;
+		p_mpfcb->freelist = INDEX_NULL;
+	}
+	queue_initialize(&free_mpfcb);
+	for (j = 0; i < tnum_mpf; i++, j++) {
+		p_mpfcb = &(mpfcb_table[i]);
+		p_mpfinib = &(ampfinib_table[j]);
+		p_mpfinib->mpfatr = TA_NOEXS;
+		p_mpfcb->p_mpfinib = ((const MPFINIB *) p_mpfinib);
+		queue_insert_prev(&free_mpfcb, &(p_mpfcb->wait_queue));
+	}
+}
+
+#endif /* TOPPERS_mpfini */
+
+/*
+ *  固定長メモリプールからブロックを獲得
+ */
+#ifdef TOPPERS_mpfget
+
+void
+get_mpf_block(MPFCB *p_mpfcb, void **p_blk)
+{
+	uint_t	blkidx;
+
+	if (p_mpfcb->freelist != INDEX_NULL) {
+		blkidx = p_mpfcb->freelist;
+		p_mpfcb->freelist = (p_mpfcb->p_mpfinib->p_mpfmb + blkidx)->next;
+	}
+	else {
+		blkidx = p_mpfcb->unused;
+		p_mpfcb->unused++;
+	}
+	*p_blk = (void *)((char *)(p_mpfcb->p_mpfinib->mpf)
+								+ p_mpfcb->p_mpfinib->blksz * blkidx);
+	p_mpfcb->fblkcnt--;
+	(p_mpfcb->p_mpfinib->p_mpfmb + blkidx)->next = INDEX_ALLOC;
+}
+
+#endif /* TOPPERS_mpfget */
+
+/*
+ *  固定長メモリプールの生成
+ */
+#ifdef TOPPERS_acre_mpf
+
+ER_UINT
+acre_mpf(const T_CMPF *pk_cmpf)
+{
+	MPFCB	*p_mpfcb;
+	MPFINIB	*p_mpfinib;
+	ATR		mpfatr;
+	void	*mpf;
+	MPFMB	*p_mpfmb;
+	ER		ercd;
+
+	LOG_ACRE_MPF_ENTER(pk_cmpf);
+	CHECK_TSKCTX_UNL();
+	CHECK_RSATR(pk_cmpf->mpfatr, TA_TPRI);
+	CHECK_PAR(pk_cmpf->blkcnt != 0);
+	CHECK_PAR(pk_cmpf->blksz != 0);
+	if (pk_cmpf->mpf != NULL) {
+		CHECK_ALIGN_MPF(pk_cmpf->mpf);
+	}
+	if (pk_cmpf->mpfmb != NULL) {
+		CHECK_ALIGN_MB(pk_cmpf->mpfmb);
+	}
+	mpfatr = pk_cmpf->mpfatr;
+	mpf = pk_cmpf->mpf;
+	p_mpfmb = pk_cmpf->mpfmb;
+
+	t_lock_cpu();
+	if (tnum_mpf == 0 || queue_empty(&free_mpfcb)) {
+		ercd = E_NOID;
+	}
+	else {
+		if (mpf == NULL) {
+			mpf = kernel_malloc(ROUND_MPF_T(pk_cmpf->blksz) * pk_cmpf->blkcnt);
+			mpfatr |= TA_MEMALLOC;
+		}
+		if (mpf == NULL) {
+			ercd = E_NOMEM;
+		}
+		else {
+			if (p_mpfmb == NULL) {
+				p_mpfmb = kernel_malloc(sizeof(MPFMB) * pk_cmpf->blkcnt);
+				mpfatr |= TA_MBALLOC;
+			}
+			if (p_mpfmb == NULL) {
+				if (pk_cmpf->mpf == NULL) {
+					kernel_free(mpf);
+				}
+				ercd = E_NOMEM;
+			}
+			else {
+				p_mpfcb = ((MPFCB *) queue_delete_next(&free_mpfcb));
+				p_mpfinib = (MPFINIB *)(p_mpfcb->p_mpfinib);
+				p_mpfinib->mpfatr = mpfatr;
+				p_mpfinib->blkcnt = pk_cmpf->blkcnt;
+				p_mpfinib->blksz = ROUND_MPF_T(pk_cmpf->blksz);
+				p_mpfinib->mpf = mpf;
+				p_mpfinib->p_mpfmb = p_mpfmb;
+
+				queue_initialize(&(p_mpfcb->wait_queue));
+				p_mpfcb->fblkcnt = p_mpfcb->p_mpfinib->blkcnt;
+				p_mpfcb->unused = 0U;
+				p_mpfcb->freelist = INDEX_NULL;
+				ercd = MPFID(p_mpfcb);
+			}
+		}
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_ACRE_MPF_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_acre_mpf */
+
+/*
+ *  固定長メモリプールの削除
+ */
+#ifdef TOPPERS_del_mpf
+
+ER
+del_mpf(ID mpfid)
+{
+	MPFCB	*p_mpfcb;
+	MPFINIB	*p_mpfinib;
+	bool_t	dspreq;
+	ER		ercd;
+
+	LOG_DEL_MPF_ENTER(mpfid);
+	CHECK_TSKCTX_UNL();
+	CHECK_MPFID(mpfid);
+	p_mpfcb = get_mpfcb(mpfid);
+
+	t_lock_cpu();
+	if (p_mpfcb->p_mpfinib->mpfatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (MPFID(p_mpfcb) > tmax_smpfid) {
+		dspreq = init_wait_queue(&(p_mpfcb->wait_queue));
+		p_mpfinib = (MPFINIB *)(p_mpfcb->p_mpfinib);
+		if ((p_mpfinib->mpfatr & TA_MEMALLOC) != 0U) {
+			kernel_free(p_mpfinib->mpf);
+		}
+		if ((p_mpfinib->mpfatr & TA_MBALLOC) != 0U) {
+			kernel_free(p_mpfinib->p_mpfmb);
+		}
+		p_mpfinib->mpfatr = TA_NOEXS;
+		queue_insert_prev(&free_mpfcb, &(p_mpfcb->wait_queue));
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_OBJ;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_DEL_MPF_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_del_mpf */
+
+/*
+ *  固定長メモリブロックの獲得
+ */
+#ifdef TOPPERS_get_mpf
+
+ER
+get_mpf(ID mpfid, void **p_blk)
+{
+	MPFCB	*p_mpfcb;
+	WINFO_MPF winfo_mpf;
+	ER		ercd;
+
+	LOG_GET_MPF_ENTER(mpfid, p_blk);
+	CHECK_DISPATCH();
+	CHECK_MPFID(mpfid);
+	p_mpfcb = get_mpfcb(mpfid);
+
+	t_lock_cpu();
+	if (p_mpfcb->p_mpfinib->mpfatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (p_mpfcb->fblkcnt > 0) {
+		get_mpf_block(p_mpfcb, p_blk);
+		ercd = E_OK;
+	}
+	else {
+		p_runtsk->tstat = (TS_WAITING | TS_WAIT_MPF);
+		wobj_make_wait((WOBJCB *) p_mpfcb, (WINFO_WOBJ *) &winfo_mpf);
+		dispatch();
+		ercd = winfo_mpf.winfo.wercd;
+		if (ercd == E_OK) {
+			*p_blk = winfo_mpf.blk;
+		}
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_GET_MPF_LEAVE(ercd, *p_blk);
+	return(ercd);
+}
+
+#endif /* TOPPERS_get_mpf */
+
+/*
+ *  固定長メモリブロックの獲得（ポーリング）
+ */
+#ifdef TOPPERS_pget_mpf
+
+ER
+pget_mpf(ID mpfid, void **p_blk)
+{
+	MPFCB	*p_mpfcb;
+	ER		ercd;
+
+	LOG_PGET_MPF_ENTER(mpfid, p_blk);
+	CHECK_TSKCTX_UNL();
+	CHECK_MPFID(mpfid);
+	p_mpfcb = get_mpfcb(mpfid);
+
+	t_lock_cpu();
+	if (p_mpfcb->p_mpfinib->mpfatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (p_mpfcb->fblkcnt > 0) {
+		get_mpf_block(p_mpfcb, p_blk);
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_TMOUT;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_PGET_MPF_LEAVE(ercd, *p_blk);
+	return(ercd);
+}
+
+#endif /* TOPPERS_pget_mpf */
+
+/*
+ *  固定長メモリブロックの獲得（タイムアウトあり）
+ */
+#ifdef TOPPERS_tget_mpf
+
+ER
+tget_mpf(ID mpfid, void **p_blk, TMO tmout)
+{
+	MPFCB	*p_mpfcb;
+	WINFO_MPF winfo_mpf;
+	TMEVTB	tmevtb;
+	ER		ercd;
+
+	LOG_TGET_MPF_ENTER(mpfid, p_blk, tmout);
+	CHECK_DISPATCH();
+	CHECK_MPFID(mpfid);
+	CHECK_TMOUT(tmout);
+	p_mpfcb = get_mpfcb(mpfid);
+
+	t_lock_cpu();
+	if (p_mpfcb->p_mpfinib->mpfatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (p_mpfcb->fblkcnt > 0) {
+		get_mpf_block(p_mpfcb, p_blk);
+		ercd = E_OK;
+	}
+	else if (tmout == TMO_POL) {
+		ercd = E_TMOUT;
+	}
+	else {
+		p_runtsk->tstat = (TS_WAITING | TS_WAIT_MPF);
+		wobj_make_wait_tmout((WOBJCB *) p_mpfcb, (WINFO_WOBJ *) &winfo_mpf,
+														&tmevtb, tmout);
+		dispatch();
+		ercd = winfo_mpf.winfo.wercd;
+		if (ercd == E_OK) {
+			*p_blk = winfo_mpf.blk;
+		}
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_TGET_MPF_LEAVE(ercd, *p_blk);
+	return(ercd);
+}
+
+#endif /* TOPPERS_tget_mpf */
+
+/*
+ *  固定長メモリブロックの返却
+ */
+#ifdef TOPPERS_rel_mpf
+
+ER
+rel_mpf(ID mpfid, void *blk)
+{
+	MPFCB	*p_mpfcb;
+	SIZE	blkoffset;
+	uint_t	blkidx;
+	TCB		*p_tcb;
+	ER		ercd;
+    
+	LOG_REL_MPF_ENTER(mpfid, blk);
+	CHECK_TSKCTX_UNL();
+	CHECK_MPFID(mpfid);
+	p_mpfcb = get_mpfcb(mpfid);
+
+	t_lock_cpu();
+	if (p_mpfcb->p_mpfinib->mpfatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		blkoffset = ((char *) blk) - (char *)(p_mpfcb->p_mpfinib->mpf);
+		blkidx = (uint_t)(blkoffset / p_mpfcb->p_mpfinib->blksz);
+		if (!(p_mpfcb->p_mpfinib->mpf <= blk)
+				|| !(blkoffset % p_mpfcb->p_mpfinib->blksz == 0U)
+				|| !(blkoffset / p_mpfcb->p_mpfinib->blksz < p_mpfcb->unused)
+				|| !((p_mpfcb->p_mpfinib->p_mpfmb + blkidx)->next
+															== INDEX_ALLOC)) {
+			ercd = E_PAR;
+		}
+		else if (!queue_empty(&(p_mpfcb->wait_queue))) {
+			p_tcb = (TCB *) queue_delete_next(&(p_mpfcb->wait_queue));
+			((WINFO_MPF *)(p_tcb->p_winfo))->blk = blk;
+			if (wait_complete(p_tcb)) {
+				dispatch();
+			}
+			ercd = E_OK;
+		}
+		else {
+			p_mpfcb->fblkcnt++;
+			(p_mpfcb->p_mpfinib->p_mpfmb + blkidx)->next = p_mpfcb->freelist;
+			p_mpfcb->freelist = blkidx;
+			ercd = E_OK;
+		}
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_REL_MPF_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_rel_mpf */
+
+/*
+ *  固定長メモリプールの再初期化
+ */
+#ifdef TOPPERS_ini_mpf
+
+ER
+ini_mpf(ID mpfid)
+{
+	MPFCB	*p_mpfcb;
+	bool_t	dspreq;
+	ER		ercd;
+    
+	LOG_INI_MPF_ENTER(mpfid);
+	CHECK_TSKCTX_UNL();
+	CHECK_MPFID(mpfid);
+	p_mpfcb = get_mpfcb(mpfid);
+
+	t_lock_cpu();
+	if (p_mpfcb->p_mpfinib->mpfatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		dspreq = init_wait_queue(&(p_mpfcb->wait_queue));
+		p_mpfcb->fblkcnt = p_mpfcb->p_mpfinib->blkcnt;
+		p_mpfcb->unused = 0U;
+		p_mpfcb->freelist = INDEX_NULL;
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_INI_MPF_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ini_mpf */
+
+/*
+ *  固定長メモリプールの状態参照
+ */
+#ifdef TOPPERS_ref_mpf
+
+ER
+ref_mpf(ID mpfid, T_RMPF *pk_rmpf)
+{
+	MPFCB	*p_mpfcb;
+	ER		ercd;
+    
+	LOG_REF_MPF_ENTER(mpfid, pk_rmpf);
+	CHECK_TSKCTX_UNL();
+	CHECK_MPFID(mpfid);
+	p_mpfcb = get_mpfcb(mpfid);
+
+	t_lock_cpu();
+	if (p_mpfcb->p_mpfinib->mpfatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		pk_rmpf->wtskid = wait_tskid(&(p_mpfcb->wait_queue));
+		pk_rmpf->fblkcnt = p_mpfcb->fblkcnt;
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_REF_MPF_LEAVE(ercd, pk_rmpf);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ref_mpf */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/mempfix.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/mempfix.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/mempfix.h	(revision 453)
@@ -0,0 +1,144 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2012 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		固定長メモリプール機能
+ */
+
+#ifndef TOPPERS_MEMPFIX_H
+#define TOPPERS_MEMPFIX_H
+
+#include "wait.h"
+
+/*
+ *  固定長メモリブロック管理ブロック
+ *
+ *  nextフィールドには，メモリブロックが割当て済みの場合はINDEX_ALLOCを，
+ *  未割当ての場合は次の未割当てブロックのインデックス番号を格納する．
+ *  最後の未割当てブロックの場合には，INDEX_NULLを格納する．
+ */
+typedef struct fixed_memoryblock_management_block {
+	uint_t		next;			/* 次の未割当てブロック */
+} MPFMB;
+
+/*
+ *  固定長メモリプール初期化ブロック
+ *
+ *  この構造体は，同期・通信オブジェクトの初期化ブロックの共通部分
+ *  （WOBJINIB）を拡張（オブジェクト指向言語の継承に相当）したもので，
+ *  最初のフィールドが共通になっている．
+ */
+typedef struct fixed_memorypool_initialization_block {
+	ATR			mpfatr;			/* 固定長メモリプール属性 */
+	uint_t		blkcnt;			/* メモリブロック数 */
+	uint_t		blksz;			/* メモリブロックのサイズ（丸めた値） */
+	void		*mpf;			/* 固定長メモリプール領域の先頭番地 */
+	MPFMB		*p_mpfmb;		/* 固定長メモリプール管理領域の先頭番地 */
+} MPFINIB;
+
+/*
+ *  固定長メモリプール管理ブロック
+ *
+ *  この構造体は，同期・通信オブジェクトの管理ブロックの共通部分（WOBJCB）
+ *  を拡張（オブジェクト指向言語の継承に相当）したもので，最初の2つの
+ *  フィールドが共通になっている．
+ */
+typedef struct fixed_memorypool_control_block {
+	QUEUE		wait_queue;		/* 固定長メモリプール待ちキュー */
+	const MPFINIB *p_mpfinib;	/* 初期化ブロックへのポインタ */
+	uint_t		fblkcnt;		/* 未割当てブロック数 */
+	uint_t		unused;			/* 未使用ブロックの先頭 */
+	uint_t		freelist;		/* 未割当てブロックのリスト */
+} MPFCB;
+
+/*
+ *  固定長メモリプール待ち情報ブロックの定義
+ *
+ *  この構造体は，同期・通信オブジェクトの待ち情報ブロックの共通部分
+ *  （WINFO_WOBJ）を拡張（オブジェクト指向言語の継承に相当）したもので，
+ *  最初の2つのフィールドが共通になっている．
+ */
+typedef struct fixed_memorypool_waiting_information {
+	WINFO		winfo;			/* 標準の待ち情報ブロック */
+	MPFCB		*p_mpfcb;		/* 待っている固定長メモリプールの管理ブロック*/
+	void		*blk;			/* 獲得したメモリブロック */
+} WINFO_MPF;
+
+/*
+ *  使用していない固定長メモリプール管理ブロックのリスト
+ */
+extern QUEUE	free_mpfcb;
+
+/*
+ *  固定長メモリプールIDの最大値（kernel_cfg.c）
+ */
+extern const ID	tmax_mpfid;
+extern const ID	tmax_smpfid;
+
+/*
+ *  固定長メモリプール初期化ブロックのエリア（kernel_cfg.c）
+ */
+extern const MPFINIB	mpfinib_table[];
+extern MPFINIB			ampfinib_table[];
+
+/*
+ *  固定長メモリプール管理ブロックのエリア（kernel_cfg.c）
+ */
+extern MPFCB	mpfcb_table[];
+
+/*
+ *  固定長メモリプール管理ブロックから固定長メモリプールIDを取り出すた
+ *  めのマクロ
+ */
+#define	MPFID(p_mpfcb)	((ID)(((p_mpfcb) - mpfcb_table) + TMIN_MPFID))
+
+/*
+ *  固定長メモリプール機能の初期化
+ */
+extern void	initialize_mempfix(void);
+
+/*
+ *  固定長メモリプールからブロックを獲得
+ */
+extern void	get_mpf_block(MPFCB *p_mpfcb, void **p_blk);
+
+#endif /* TOPPERS_MEMPFIX_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/mutex.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/mutex.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/mutex.c	(revision 453)
@@ -0,0 +1,781 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2005-2014 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		ミューテックス機能
+ */
+
+#include "kernel_impl.h"
+#include "check.h"
+#include "task.h"
+#include "wait.h"
+#include "mutex.h"
+
+/*
+ *  トレースログマクロのデフォルト定義
+ */
+#ifndef LOG_ACRE_MTX_ENTER
+#define LOG_ACRE_MTX_ENTER(mtxid)
+#endif /* LOG_ACRE_MTX_ENTER */
+
+#ifndef LOG_ACRE_MTX_LEAVE
+#define LOG_ACRE_MTX_LEAVE(ercd)
+#endif /* LOG_ACRE_MTX_LEAVE */
+
+#ifndef LOG_DEL_MTX_ENTER
+#define LOG_DEL_MTX_ENTER(mtxid)
+#endif /* LOG_DEL_MTX_ENTER */
+
+#ifndef LOG_DEL_MTX_LEAVE
+#define LOG_DEL_MTX_LEAVE(ercd)
+#endif /* LOG_DEL_MTX_LEAVE */
+
+#ifndef LOG_LOC_MTX_ENTER
+#define LOG_LOC_MTX_ENTER(mtxid)
+#endif /* LOG_LOC_MTX_ENTER */
+
+#ifndef LOG_LOC_MTX_LEAVE
+#define LOG_LOC_MTX_LEAVE(ercd)
+#endif /* LOG_LOC_MTX_LEAVE */
+
+#ifndef LOG_PLOC_MTX_ENTER
+#define LOG_PLOC_MTX_ENTER(mtxid)
+#endif /* LOG_PLOC_MTX_ENTER */
+
+#ifndef LOG_PLOC_MTX_LEAVE
+#define LOG_PLOC_MTX_LEAVE(ercd)
+#endif /* LOG_PLOC_MTX_LEAVE */
+
+#ifndef LOG_TLOC_MTX_ENTER
+#define LOG_TLOC_MTX_ENTER(mtxid, tmout)
+#endif /* LOG_TLOC_MTX_ENTER */
+
+#ifndef LOG_TLOC_MTX_LEAVE
+#define LOG_TLOC_MTX_LEAVE(ercd)
+#endif /* LOG_TLOC_MTX_LEAVE */
+
+#ifndef LOG_UNL_MTX_ENTER
+#define LOG_UNL_MTX_ENTER(mtxid)
+#endif /* LOG_UNL_MTX_ENTER */
+
+#ifndef LOG_UNL_MTX_LEAVE
+#define LOG_UNL_MTX_LEAVE(ercd)
+#endif /* LOG_UNL_MTX_LEAVE */
+
+#ifndef LOG_INI_MTX_ENTER
+#define LOG_INI_MTX_ENTER(mtxid)
+#endif /* LOG_INI_MTX_ENTER */
+
+#ifndef LOG_INI_MTX_LEAVE
+#define LOG_INI_MTX_LEAVE(ercd)
+#endif /* LOG_INI_MTX_LEAVE */
+
+#ifndef LOG_REF_MTX_ENTER
+#define LOG_REF_MTX_ENTER(mtxid, pk_rmtx)
+#endif /* LOG_REF_MTX_ENTER */
+
+#ifndef LOG_REF_MTX_LEAVE
+#define LOG_REF_MTX_LEAVE(ercd, pk_rmtx)
+#endif /* LOG_REF_MTX_LEAVE */
+
+/*
+ *  ミューテックスの数
+ */
+#define tnum_mtx	((uint_t)(tmax_mtxid - TMIN_MTXID + 1))
+#define tnum_smtx	((uint_t)(tmax_smtxid - TMIN_MTXID + 1))
+
+/*
+ *  ミューテックスIDからミューテックス管理ブロックを取り出すためのマクロ
+ */
+#define INDEX_MTX(mtxid)	((uint_t)((mtxid) - TMIN_MTXID))
+#define get_mtxcb(mtxid)	(&(mtxcb_table[INDEX_MTX(mtxid)]))
+
+/*
+ *  ミューテックス管理ブロック中のmutex_queueへのポインタから，ミューテッ
+ *  クス管理ブロックへのポインタを取り出すためのマクロ
+ */
+#define MTXCB_QUEUE(p_queue) \
+			((MTXCB *)(((char *) p_queue) - offsetof(MTXCB, mutex_queue)))
+
+/*
+ *  ミューテックスのプロトコルを判断するマクロ
+ */
+#define MTXPROTO_MASK			0x03U
+#define MTXPROTO(p_mtxcb)		((p_mtxcb)->p_mtxinib->mtxatr & MTXPROTO_MASK)
+#define MTX_CEILING(p_mtxcb)	(MTXPROTO(p_mtxcb) == TA_CEILING)
+
+/*
+ *  フックルーチン呼出し用の変数
+ */
+#ifdef TOPPERS_mtxhook
+
+bool_t	(*mtxhook_check_ceilpri)(TCB *p_tcb, uint_t bpriority) = NULL;
+bool_t	(*mtxhook_scan_ceilmtx)(TCB *p_tcb) = NULL;
+bool_t	(*mtxhook_release_all)(TCB *p_tcb) = NULL;
+
+#endif /* TOPPERS_mtxhook */
+
+/*
+ *  使用していないミューテックス管理ブロックのリスト
+ */
+QUEUE	free_mtxcb;
+
+/* 
+ *  ミューテックス機能の初期化
+ */
+#ifdef TOPPERS_mtxini
+
+void
+initialize_mutex(void)
+{
+	uint_t	i, j;
+	MTXCB	*p_mtxcb;
+	MTXINIB	*p_mtxinib;
+
+	mtxhook_check_ceilpri = mutex_check_ceilpri;
+	mtxhook_scan_ceilmtx = mutex_scan_ceilmtx;
+	mtxhook_release_all = mutex_release_all;
+
+	for (i = 0; i < tnum_smtx; i++) {
+		p_mtxcb = &(mtxcb_table[i]);
+		queue_initialize(&(p_mtxcb->wait_queue));
+		p_mtxcb->p_mtxinib = &(mtxinib_table[i]);
+		p_mtxcb->p_loctsk = NULL;
+	}
+	queue_initialize(&free_mtxcb);
+	for (j = 0; i < tnum_mtx; i++, j++) {
+		p_mtxcb = &(mtxcb_table[i]);
+		p_mtxinib = &(amtxinib_table[j]);
+		p_mtxinib->mtxatr = TA_NOEXS;
+		p_mtxcb->p_mtxinib = ((const MTXINIB *) p_mtxinib);
+		queue_insert_prev(&free_mtxcb, &(p_mtxcb->wait_queue));
+	}
+}
+
+#endif /* TOPPERS_mtxini */
+
+/* 
+ *  上限優先度違反のチェック
+ */
+#ifdef TOPPERS_mtxchk
+
+bool_t
+mutex_check_ceilpri(TCB *p_tcb, uint_t bpriority)
+{
+	QUEUE	*p_queue;
+	MTXCB	*p_mtxcb;
+
+	/*
+	 *  タスクがロックしている優先度上限ミューテックスの中で，上限優先
+	 *  度がbpriorityよりも低いものがあれば，falseを返す．
+	 */
+	p_queue = p_tcb->mutex_queue.p_next;
+	while (p_queue != &(p_tcb->mutex_queue)) {
+		p_mtxcb = MTXCB_QUEUE(p_queue);
+		if (MTX_CEILING(p_mtxcb) && bpriority < p_mtxcb->p_mtxinib->ceilpri) {
+			return(false);
+		}
+		p_queue = p_queue->p_next;
+	}
+
+	/*
+	 *  タスクが優先度上限ミューテックスのロックを待っている場合に，そ
+	 *  の上限優先度がbpriorityよりも低くければ，falseを返す．
+	 */
+	if (TSTAT_WAIT_MTX(p_tcb->tstat)) {
+		p_mtxcb = ((WINFO_MTX *)(p_tcb->p_winfo))->p_mtxcb;
+		if (MTX_CEILING(p_mtxcb) && bpriority < p_mtxcb->p_mtxinib->ceilpri) {
+			return(false);
+		}
+	}
+
+	/*
+	 *  いずれの条件にも当てはまらなければtrueを返す．
+	 */
+	return(true);
+}
+
+#endif /* TOPPERS_mtxchk */
+
+/* 
+ *  優先度上限ミューテックスをロックしているかのチェック
+ */
+#ifdef TOPPERS_mtxscan
+
+bool_t
+mutex_scan_ceilmtx(TCB *p_tcb)
+{
+	QUEUE	*p_queue;
+	MTXCB	*p_mtxcb;
+
+	p_queue = p_tcb->mutex_queue.p_next;
+	while (p_queue != &(p_tcb->mutex_queue)) {
+		p_mtxcb = MTXCB_QUEUE(p_queue);
+		if (MTX_CEILING(p_mtxcb)) {
+			return(true);
+		}
+		p_queue = p_queue->p_next;
+	}
+	return(false);
+}
+
+#endif /* TOPPERS_mtxscan */
+
+/* 
+ *  タスクの現在優先度の計算
+ */
+#ifdef TOPPERS_mtxcalc
+
+uint_t
+mutex_calc_priority(TCB *p_tcb)
+{
+	uint_t	priority;
+	QUEUE	*p_queue;
+	MTXCB	*p_mtxcb;
+
+	priority = p_tcb->bpriority;
+	p_queue = p_tcb->mutex_queue.p_next;
+	while (p_queue != &(p_tcb->mutex_queue)) {
+		p_mtxcb = MTXCB_QUEUE(p_queue);
+		if (MTX_CEILING(p_mtxcb) && p_mtxcb->p_mtxinib->ceilpri < priority) {
+			priority = p_mtxcb->p_mtxinib->ceilpri;
+		}
+		p_queue = p_queue->p_next;
+	}
+	return(priority);
+}
+
+#endif /* TOPPERS_mtxcalc */
+
+/*
+ *  要素優先度が上がる（または増える）場合の現在優先度変更処理
+ */
+Inline bool_t
+mutex_raise_priority(TCB *p_tcb, uint_t newpri)
+{
+	if (newpri < p_tcb->priority) {
+		return(change_priority(p_tcb, newpri, true));
+	}
+	return(false);
+}
+
+/*
+ *  要素優先度が下がる（または減る）場合の現在優先度変更処理
+ */
+Inline bool_t
+mutex_drop_priority(TCB *p_tcb, uint_t oldpri)
+{
+	uint_t	newpri;
+
+	if (oldpri == p_tcb->priority) {
+		newpri = mutex_calc_priority(p_tcb);
+		if (newpri != p_tcb->priority) {
+			return(change_priority(p_tcb, newpri, true));
+		}
+	}
+	return(false);
+}
+
+/*
+ *  ミューテックスをロックした場合の処理
+ */
+Inline bool_t
+mutex_acquire(TCB *p_loctsk, MTXCB *p_mtxcb)
+{
+	p_mtxcb->p_loctsk = p_loctsk;
+	queue_insert_next(&(p_loctsk->mutex_queue), &(p_mtxcb->mutex_queue));
+	if (MTX_CEILING(p_mtxcb)) {
+		return(mutex_raise_priority(p_loctsk, p_mtxcb->p_mtxinib->ceilpri));
+	}
+	return(false);
+}
+
+/*
+ *  ミューテックスのロック解除
+ */
+#ifdef TOPPERS_mtxrel
+
+bool_t
+mutex_release(MTXCB *p_mtxcb)
+{
+	TCB		*p_tcb;
+
+	if (queue_empty(&(p_mtxcb->wait_queue))) {
+		p_mtxcb->p_loctsk = NULL;
+		return(false);
+	}
+	else {
+		/*
+		 *  ミューテックス待ちキューの先頭タスク（p_tcb）に，ミューテッ
+		 *  クスをロックさせる．
+		 */
+		p_tcb = (TCB *) queue_delete_next(&(p_mtxcb->wait_queue));
+		wait_dequeue_tmevtb(p_tcb);
+		p_tcb->p_winfo->wercd = E_OK;
+
+		p_mtxcb->p_loctsk = p_tcb;
+		queue_insert_prev(&(p_tcb->mutex_queue), &(p_mtxcb->mutex_queue));
+		if (MTX_CEILING(p_mtxcb)) {
+			if (p_mtxcb->p_mtxinib->ceilpri < p_tcb->priority) {
+				p_tcb->priority = p_mtxcb->p_mtxinib->ceilpri;
+			}
+		}
+		return(make_non_wait(p_tcb));
+	}
+}
+
+#endif /* TOPPERS_mtxrel */
+
+/*
+ *  タスクがロックしているすべてのミューテックスのロック解除
+ */
+#ifdef TOPPERS_mtxrela
+
+bool_t
+mutex_release_all(TCB *p_tcb)
+{
+	MTXCB	*p_mtxcb;
+	bool_t	dspreq = false;
+
+	while (!queue_empty(&(p_tcb->mutex_queue))) {
+		p_mtxcb = MTXCB_QUEUE(p_tcb->mutex_queue.p_next);
+		queue_delete(&(p_mtxcb->mutex_queue));
+		if (mutex_release(p_mtxcb)) {
+			dspreq = true;
+		}
+	}
+	return(dspreq);
+}
+
+#endif /* TOPPERS_mtxrela */
+
+/*
+ *  ミューテックスの生成
+ */
+#ifdef TOPPERS_acre_mtx
+
+ER_UINT
+acre_mtx(const T_CMTX *pk_cmtx)
+{
+	MTXCB	*p_mtxcb;
+	MTXINIB	*p_mtxinib;
+	ATR		mtxatr;
+	PRI		ceilpri;
+	ER		ercd;
+
+	LOG_ACRE_MTX_ENTER(pk_cmtx);
+	CHECK_TSKCTX_UNL();
+
+	mtxatr = pk_cmtx->mtxatr;
+	ceilpri = pk_cmtx->ceilpri;
+
+	if (mtxatr == TA_CEILING) {
+		CHECK_PAR(VALID_TPRI(ceilpri));
+	}
+	else {
+		CHECK_RSATR(mtxatr, TA_TPRI);
+	}
+
+	t_lock_cpu();
+	if (tnum_mtx == 0 || queue_empty(&free_mtxcb)) {
+		ercd = E_NOID;
+	}
+	else {
+		p_mtxcb = ((MTXCB *) queue_delete_next(&free_mtxcb));
+		p_mtxinib = (MTXINIB *)(p_mtxcb->p_mtxinib);
+		p_mtxinib->mtxatr = mtxatr;
+		p_mtxinib->ceilpri = INT_PRIORITY(ceilpri);
+
+		queue_initialize(&(p_mtxcb->wait_queue));
+		queue_initialize(&(p_mtxcb->mutex_queue));
+		ercd = MTXID(p_mtxcb);
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_ACRE_MTX_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_acre_mtx */
+
+/*
+ *  ミューテックスの削除
+ */
+#ifdef TOPPERS_del_mtx
+
+ER
+del_mtx(ID mtxid)
+{
+	MTXCB	*p_mtxcb;
+	bool_t	dspreq = false;
+	MTXINIB	*p_mtxinib;
+	TCB		*p_loctsk;
+	ER		ercd;
+
+	LOG_DEL_MTX_ENTER(mtxid);
+	CHECK_TSKCTX_UNL();
+	CHECK_MTXID(mtxid);
+	p_mtxcb = get_mtxcb(mtxid);
+
+	t_lock_cpu();
+	if (p_mtxcb->p_mtxinib->mtxatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (MTXID(p_mtxcb) > tmax_smtxid) {
+		dspreq = init_wait_queue(&(p_mtxcb->wait_queue));
+		p_loctsk = p_mtxcb->p_loctsk;
+		if (p_loctsk != NULL) {
+			queue_delete(&(p_mtxcb->mutex_queue));
+			p_mtxcb->p_loctsk = NULL;
+			if (MTX_CEILING(p_mtxcb)) {
+				if (mutex_drop_priority(p_loctsk, p_mtxcb->p_mtxinib->ceilpri)) {
+					dspreq = true;
+				}
+			}
+		}
+		p_mtxinib = (MTXINIB *)(p_mtxcb->p_mtxinib);
+		p_mtxinib->mtxatr = TA_NOEXS;
+		queue_insert_prev(&free_mtxcb, &(p_mtxcb->wait_queue));
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_OBJ;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_DEL_MTX_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_del_mtx */
+
+/*
+ *  ミューテックスのロック
+ */
+#ifdef TOPPERS_loc_mtx
+
+ER
+loc_mtx(ID mtxid)
+{
+	MTXCB	*p_mtxcb;
+	WINFO_MTX winfo_mtx;
+	ER		ercd;
+
+	LOG_LOC_MTX_ENTER(mtxid);
+	CHECK_DISPATCH();
+	CHECK_MTXID(mtxid);
+	p_mtxcb = get_mtxcb(mtxid);
+
+	t_lock_cpu();
+	if (p_mtxcb->p_mtxinib->mtxatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (MTX_CEILING(p_mtxcb)
+				&& p_runtsk->bpriority < p_mtxcb->p_mtxinib->ceilpri) {
+		ercd = E_ILUSE;
+	}
+	else if (p_mtxcb->p_loctsk == NULL) {
+		(void) mutex_acquire(p_runtsk, p_mtxcb);
+		/*
+		 *  優先度上限ミューテックスをロックした場合，p_runtskの優先度
+		 *  が上がる可能性があるが，ディスパッチが必要になることはない．
+		 */
+		assert(!(p_runtsk != p_schedtsk && dspflg));
+		ercd = E_OK;
+	}
+	else if (p_mtxcb->p_loctsk == p_runtsk) {
+		ercd = E_OBJ;
+	}
+	else {
+		p_runtsk->tstat = (TS_WAITING | TS_WAIT_MTX);
+		wobj_make_wait((WOBJCB *) p_mtxcb, (WINFO_WOBJ *) &winfo_mtx);
+		dispatch();
+		ercd = winfo_mtx.winfo.wercd;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_LOC_MTX_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_loc_mtx */
+
+/*
+ *  ミューテックスのロック（ポーリング）
+ */
+#ifdef TOPPERS_ploc_mtx
+
+ER
+ploc_mtx(ID mtxid)
+{
+	MTXCB	*p_mtxcb;
+	ER		ercd;
+
+	LOG_PLOC_MTX_ENTER(mtxid);
+	CHECK_TSKCTX_UNL();
+	CHECK_MTXID(mtxid);
+	p_mtxcb = get_mtxcb(mtxid);
+
+	t_lock_cpu();
+	if (p_mtxcb->p_mtxinib->mtxatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (MTX_CEILING(p_mtxcb)
+				&& p_runtsk->bpriority < p_mtxcb->p_mtxinib->ceilpri) {
+		ercd = E_ILUSE;
+	}
+	else if (p_mtxcb->p_loctsk == NULL) {
+		(void) mutex_acquire(p_runtsk, p_mtxcb);
+		/*
+		 *  優先度上限ミューテックスをロックした場合，p_runtskの優先度
+		 *  が上がる可能性があるが，ディスパッチが必要になることはない．
+		 */
+		assert(!(p_runtsk != p_schedtsk && dspflg));
+		ercd = E_OK;
+	}
+	else if (p_mtxcb->p_loctsk == p_runtsk) {
+		ercd = E_OBJ;
+	}
+	else {
+		ercd = E_TMOUT;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_PLOC_MTX_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ploc_mtx */
+
+/*
+ *  ミューテックスのロック（タイムアウトあり）
+ */
+#ifdef TOPPERS_tloc_mtx
+
+ER
+tloc_mtx(ID mtxid, TMO tmout)
+{
+	MTXCB	*p_mtxcb;
+	WINFO_MTX winfo_mtx;
+	TMEVTB	tmevtb;
+	ER		ercd;
+
+	LOG_TLOC_MTX_ENTER(mtxid, tmout);
+	CHECK_DISPATCH();
+	CHECK_MTXID(mtxid);
+	CHECK_TMOUT(tmout);
+	p_mtxcb = get_mtxcb(mtxid);
+
+	t_lock_cpu();
+	if (p_mtxcb->p_mtxinib->mtxatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (MTX_CEILING(p_mtxcb)
+				&& p_runtsk->bpriority < p_mtxcb->p_mtxinib->ceilpri) {
+		ercd = E_ILUSE;
+	}
+	else if (p_mtxcb->p_loctsk == NULL) {
+		(void) mutex_acquire(p_runtsk, p_mtxcb);
+		/*
+		 *  優先度上限ミューテックスをロックした場合，p_runtskの優先度
+		 *  が上がる可能性があるが，ディスパッチが必要になることはない．
+		 */
+		assert(!(p_runtsk != p_schedtsk && dspflg));
+		ercd = E_OK;
+	}
+	else if (p_mtxcb->p_loctsk == p_runtsk) {
+		ercd = E_OBJ;
+	}
+	else if (tmout == TMO_POL) {
+		ercd = E_TMOUT;
+	}
+	else {
+		p_runtsk->tstat = (TS_WAITING | TS_WAIT_MTX);
+		wobj_make_wait_tmout((WOBJCB *) p_mtxcb, (WINFO_WOBJ *) &winfo_mtx,
+														&tmevtb, tmout);
+		dispatch();
+		ercd = winfo_mtx.winfo.wercd;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_TLOC_MTX_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_tloc_mtx */
+
+/*
+ *  ミューテックスのロック解除
+ */
+#ifdef TOPPERS_unl_mtx
+
+ER
+unl_mtx(ID mtxid)
+{
+	MTXCB	*p_mtxcb;
+	bool_t	dspreq = false;
+	ER		ercd;
+    
+	LOG_UNL_MTX_ENTER(mtxid);
+	CHECK_TSKCTX_UNL();
+	CHECK_MTXID(mtxid);
+	p_mtxcb = get_mtxcb(mtxid);
+
+	t_lock_cpu();
+	if (p_mtxcb->p_mtxinib->mtxatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (p_mtxcb->p_loctsk != p_runtsk) {
+		ercd = E_OBJ;
+	}
+	else {
+		queue_delete(&(p_mtxcb->mutex_queue));
+		if (MTX_CEILING(p_mtxcb)) {
+			if (mutex_drop_priority(p_runtsk, p_mtxcb->p_mtxinib->ceilpri)) {
+				dspreq = true;
+			}
+		}
+		if (mutex_release(p_mtxcb)) {
+			dspreq = true;
+		}
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_UNL_MTX_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_unl_mtx */
+
+/*
+ *  ミューテックスの初期化
+ */
+#ifdef TOPPERS_ini_mtx
+
+ER
+ini_mtx(ID mtxid)
+{
+	MTXCB	*p_mtxcb;
+	TCB		*p_loctsk;
+	bool_t	dspreq;
+	ER		ercd;
+    
+	LOG_INI_MTX_ENTER(mtxid);
+	CHECK_TSKCTX_UNL();
+	CHECK_MTXID(mtxid);
+	p_mtxcb = get_mtxcb(mtxid);
+
+	t_lock_cpu();
+	if (p_mtxcb->p_mtxinib->mtxatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		dspreq = init_wait_queue(&(p_mtxcb->wait_queue));
+		p_loctsk = p_mtxcb->p_loctsk;
+		if (p_loctsk != NULL) {
+			queue_delete(&(p_mtxcb->mutex_queue));
+			p_mtxcb->p_loctsk = NULL;
+			if (MTX_CEILING(p_mtxcb)) {
+				if (mutex_drop_priority(p_loctsk, p_mtxcb->p_mtxinib->ceilpri)) {
+					dspreq = true;
+				}
+			}
+		}
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_INI_MTX_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ini_mtx */
+
+/*
+ *  ミューテックスの状態参照
+ */
+#ifdef TOPPERS_ref_mtx
+
+ER
+ref_mtx(ID mtxid, T_RMTX *pk_rmtx)
+{
+	MTXCB	*p_mtxcb;
+	ER		ercd;
+    
+	LOG_REF_MTX_ENTER(mtxid, pk_rmtx);
+	CHECK_TSKCTX_UNL();
+	CHECK_MTXID(mtxid);
+	p_mtxcb = get_mtxcb(mtxid);
+
+	t_lock_cpu();
+	if (p_mtxcb->p_mtxinib->mtxatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		pk_rmtx->htskid = (p_mtxcb->p_loctsk != NULL) ? TSKID(p_mtxcb->p_loctsk)
+														: TSK_NONE;
+		pk_rmtx->wtskid = wait_tskid(&(p_mtxcb->wait_queue));
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_REF_MTX_LEAVE(ercd, pk_rmtx);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ref_mtx */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/mutex.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/mutex.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/mutex.h	(revision 453)
@@ -0,0 +1,174 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2012 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		ミューテックス機能
+ */
+
+#ifndef TOPPERS_MUTEX_H
+#define TOPPERS_MUTEX_H
+
+#include "wait.h"
+
+/*
+ *  ミューテックス初期化ブロック
+ *
+ *  この構造体は，同期・通信オブジェクトの初期化ブロックの共通部分
+ *  （WOBJINIB）を拡張（オブジェクト指向言語の継承に相当）したもので，
+ *  最初のフィールドが共通になっている．
+ */
+typedef struct mutex_initialization_block {
+	ATR			mtxatr;			/* ミューテックス属性 */
+	uint_t		ceilpri;		/* ミューテックスの上限優先度（内部表現）*/
+} MTXINIB;
+
+/*
+ *  ミューテックス管理ブロック
+ *
+ *  この構造体は，同期・通信オブジェクトの管理ブロックの共通部分（WOBJCB）
+ *  を拡張（オブジェクト指向言語の継承に相当）したもので，最初の2つの
+ *  フィールドが共通になっている．
+ */
+typedef struct mutex_control_block {
+	QUEUE		wait_queue;		/* ミューテックス待ちキュー */
+	const MTXINIB *p_mtxinib;	/* 初期化ブロックへのポインタ */
+	TCB			*p_loctsk;		/* ミューテックスをロックしているタスク */
+	QUEUE		mutex_queue;	/* ロックしているミューテックスのキュー */
+} MTXCB;
+
+/*
+ *  ミューテックス待ち情報ブロックの定義
+ *
+ *  この構造体は，同期・通信オブジェクトの待ち情報ブロックの共通部分
+ *  （WINFO_WOBJ）を拡張（オブジェクト指向言語の継承に相当）したもので，
+ *  すべてのフィールドが共通になっている．
+ */
+typedef struct mutex_waiting_information {
+	WINFO	winfo;			/* 標準の待ち情報ブロック */
+	MTXCB	*p_mtxcb;		/* 待っているミューテックスの管理ブロック */
+} WINFO_MTX;
+
+/*
+ *  使用していないミューテックス管理ブロックのリスト
+ */
+extern QUEUE	free_mtxcb;
+
+/*
+ *  ミューテックスIDの最大値（kernel_cfg.c）
+ */
+extern const ID	tmax_mtxid;
+extern const ID	tmax_smtxid;
+
+/*
+ *  ミューテックス初期化ブロックのエリア（kernel_cfg.c）
+ */
+extern const MTXINIB	mtxinib_table[];
+extern MTXINIB			amtxinib_table[];
+
+/*
+ *  ミューテックス管理ブロックのエリア（kernel_cfg.c）
+ */
+extern MTXCB	mtxcb_table[];
+
+/*
+ *  ミューテックス管理ブロックからミューテックスIDを取り出すためのマクロ
+ */
+#define	MTXID(p_mtxcb)	((ID)(((p_mtxcb) - mtxcb_table) + TMIN_MTXID))
+
+/*
+ *  ミューテックス機能の初期化
+ */
+extern void	initialize_mutex(void);
+
+/*
+ *  上限優先度違反のチェック
+ *
+ *  chg_priの中で上限優先度違反のチェックを行うために用いる関数であり，
+ *  p_tcbで指定されるタスクがロックしている優先度上限ミューテックスと，
+ *  ロックを待っている優先度上限ミューテックスの中で，上限優先度が
+ *  bpriorityよりも低いものがあればfalseを，そうでなければtrueを返す．
+ */
+extern bool_t	(*mtxhook_check_ceilpri)(TCB *p_tcb, uint_t bpriority);
+extern bool_t	mutex_check_ceilpri(TCB *p_tcb, uint_t bpriority);
+
+/* 
+ *  優先度上限ミューテックスをロックしているかのチェック
+ *
+ *  p_tcbで指定されるタスクが優先度上限ミューテックスをロックしていれば
+ *  true，そうでなければfalseを返す．
+ */
+extern bool_t	(*mtxhook_scan_ceilmtx)(TCB *p_tcb);
+extern bool_t	mutex_scan_ceilmtx(TCB *p_tcb);
+
+/* 
+ *  タスクの現在優先度の計算
+ *
+ *  p_tcbで指定されるタスクの現在優先度（に設定すべき値）を計算する．
+ */
+extern uint_t	mutex_calc_priority(TCB *p_tcb);
+
+/*
+ *  ミューテックスのロック解除
+ *
+ *  p_mtxcbで指定されるミューテックスをロック解除する．ロック解除した
+ *  ミューテックスに，ロック待ち状態のタスクがある場合には，そのタスク
+ *  にミューテックスをロックさせる．
+ */
+extern bool_t	mutex_release(MTXCB *p_mtxcb);
+
+/*
+ *  タスクがロックしているすべてのミューテックスのロック解除
+ *
+ *  p_tcbで指定されるタスクに，それがロックしているすべてのミューテック
+ *  スをロック解除させる．ロック解除したミューテックスに，ロック待ち状
+ *  態のタスクがある場合には，そのタスクにミューテックスをロックさせる．
+ *
+ *  この関数は，タスクの終了時に使われるものであるため，p_tcbで指定され
+ *  るタスクの優先度を変更する処理は行わない．ただし，この関数の中で他
+ *  のタスクの優先度が変化し，実行すべきタスクが変わることがある．その
+ *  ため，この関数から戻った後に，ディスパッチが必要か判別して，必要な
+ *  場合にはディスパッチを行わなければならない．
+ */
+extern bool_t	(*mtxhook_release_all)(TCB *p_tcb);
+extern bool_t	mutex_release_all(TCB *p_tcb);
+
+#endif /* TOPPERS_MUTEX_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/pridataq.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/pridataq.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/pridataq.c	(revision 453)
@@ -0,0 +1,849 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2014 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		優先度データキュー機能
+ */
+
+#include "kernel_impl.h"
+#include "check.h"
+#include "task.h"
+#include "wait.h"
+#include "pridataq.h"
+
+/*
+ *  トレースログマクロのデフォルト定義
+ */
+#ifndef LOG_ACRE_PDQ_ENTER
+#define LOG_ACRE_PDQ_ENTER(pk_cpdq)
+#endif /* LOG_ACRE_PDQ_ENTER */
+
+#ifndef LOG_ACRE_PDQ_LEAVE
+#define LOG_ACRE_PDQ_LEAVE(ercd)
+#endif /* LOG_ACRE_PDQ_LEAVE */
+
+#ifndef LOG_DEL_PDQ_ENTER
+#define LOG_DEL_PDQ_ENTER(pdqid)
+#endif /* LOG_DEL_PDQ_ENTER */
+
+#ifndef LOG_DEL_PDQ_LEAVE
+#define LOG_DEL_PDQ_LEAVE(ercd)
+#endif /* LOG_DEL_PDQ_LEAVE */
+
+#ifndef LOG_SND_PDQ_ENTER
+#define LOG_SND_PDQ_ENTER(pdqid, data, datapri)
+#endif /* LOG_SND_PDQ_ENTER */
+
+#ifndef LOG_SND_PDQ_LEAVE
+#define LOG_SND_PDQ_LEAVE(ercd)
+#endif /* LOG_SND_PDQ_LEAVE */
+
+#ifndef LOG_PSND_PDQ_ENTER
+#define LOG_PSND_PDQ_ENTER(pdqid, data, datapri)
+#endif /* LOG_PSND_PDQ_ENTER */
+
+#ifndef LOG_PSND_PDQ_LEAVE
+#define LOG_PSND_PDQ_LEAVE(ercd)
+#endif /* LOG_PSND_PDQ_LEAVE */
+
+#ifndef LOG_IPSND_PDQ_ENTER
+#define LOG_IPSND_PDQ_ENTER(pdqid, data, datapri)
+#endif /* LOG_IPSND_PDQ_ENTER */
+
+#ifndef LOG_IPSND_PDQ_LEAVE
+#define LOG_IPSND_PDQ_LEAVE(ercd)
+#endif /* LOG_IPSND_PDQ_LEAVE */
+
+#ifndef LOG_TSND_PDQ_ENTER
+#define LOG_TSND_PDQ_ENTER(pdqid, data, datapri, tmout)
+#endif /* LOG_TSND_PDQ_ENTER */
+
+#ifndef LOG_TSND_PDQ_LEAVE
+#define LOG_TSND_PDQ_LEAVE(ercd)
+#endif /* LOG_TSND_PDQ_LEAVE */
+
+#ifndef LOG_RCV_PDQ_ENTER
+#define LOG_RCV_PDQ_ENTER(pdqid, p_data, p_datapri)
+#endif /* LOG_RCV_PDQ_ENTER */
+
+#ifndef LOG_RCV_PDQ_LEAVE
+#define LOG_RCV_PDQ_LEAVE(ercd, data, datapri)
+#endif /* LOG_RCV_PDQ_LEAVE */
+
+#ifndef LOG_PRCV_PDQ_ENTER
+#define LOG_PRCV_PDQ_ENTER(pdqid, p_data, p_datapri)
+#endif /* LOG_PRCV_PDQ_ENTER */
+
+#ifndef LOG_PRCV_PDQ_LEAVE
+#define LOG_PRCV_PDQ_LEAVE(ercd, data, datapri)
+#endif /* LOG_PRCV_PDQ_LEAVE */
+
+#ifndef LOG_TRCV_PDQ_ENTER
+#define LOG_TRCV_PDQ_ENTER(pdqid, p_data, p_datapri, tmout)
+#endif /* LOG_TRCV_PDQ_ENTER */
+
+#ifndef LOG_TRCV_PDQ_LEAVE
+#define LOG_TRCV_PDQ_LEAVE(ercd, data, datapri)
+#endif /* LOG_TRCV_PDQ_LEAVE */
+
+#ifndef LOG_INI_PDQ_ENTER
+#define LOG_INI_PDQ_ENTER(pdqid)
+#endif /* LOG_INI_PDQ_ENTER */
+
+#ifndef LOG_INI_PDQ_LEAVE
+#define LOG_INI_PDQ_LEAVE(ercd)
+#endif /* LOG_INI_PDQ_LEAVE */
+
+#ifndef LOG_REF_PDQ_ENTER
+#define LOG_REF_PDQ_ENTER(pdqid, pk_rpdq)
+#endif /* LOG_REF_PDQ_ENTER */
+
+#ifndef LOG_REF_PDQ_LEAVE
+#define LOG_REF_PDQ_LEAVE(ercd, pk_rpdq)
+#endif /* LOG_REF_PDQ_LEAVE */
+
+/*
+ *  優先度データキューの数
+ */
+#define tnum_pdq	((uint_t)(tmax_pdqid - TMIN_PDQID + 1))
+#define tnum_spdq	((uint_t)(tmax_spdqid - TMIN_PDQID + 1))
+
+/*
+ *  優先度データキューIDから優先度データキュー管理ブロックを取り出すた
+ *  めのマクロ
+ */
+#define INDEX_PDQ(pdqid)	((uint_t)((pdqid) - TMIN_PDQID))
+#define get_pdqcb(pdqid)	(&(pdqcb_table[INDEX_PDQ(pdqid)]))
+
+#ifdef TOPPERS_pdqini
+
+/*
+ *  使用していない優先度データキュー管理ブロックのリスト
+ */
+QUEUE	free_pdqcb;
+
+/*
+ *  優先度データキュー機能の初期化
+ */
+void
+initialize_pridataq(void)
+{
+	uint_t	i, j;
+	PDQCB	*p_pdqcb;
+	PDQINIB	*p_pdqinib;
+
+	for (i = 0; i < tnum_spdq; i++) {
+		p_pdqcb = &(pdqcb_table[i]);
+		queue_initialize(&(p_pdqcb->swait_queue));
+		p_pdqcb->p_pdqinib = &(pdqinib_table[i]);
+		queue_initialize(&(p_pdqcb->rwait_queue));
+		p_pdqcb->count = 0U;
+		p_pdqcb->p_head = NULL;
+		p_pdqcb->unused = 0U;
+		p_pdqcb->p_freelist = NULL;
+	}
+	queue_initialize(&free_pdqcb);
+	for (j = 0; i < tnum_pdq; i++, j++) {
+		p_pdqcb = &(pdqcb_table[i]);
+		p_pdqinib = &(apdqinib_table[j]);
+		p_pdqinib->pdqatr = TA_NOEXS;
+		p_pdqcb->p_pdqinib = ((const PDQINIB *) p_pdqinib);
+		queue_insert_prev(&free_pdqcb, &(p_pdqcb->swait_queue));
+	}
+}
+
+#endif /* TOPPERS_pdqini */
+
+/*
+ *  優先度データキュー管理領域へのデータの格納
+ */
+#ifdef TOPPERS_pdqenq
+
+void
+enqueue_pridata(PDQCB *p_pdqcb, intptr_t data, PRI datapri)
+{
+	PDQMB	*p_pdqmb;
+	PDQMB	**pp_prev_next, *p_next;
+
+	if (p_pdqcb->p_freelist != NULL) {
+		p_pdqmb = p_pdqcb->p_freelist;
+		p_pdqcb->p_freelist = p_pdqmb->p_next;
+	}
+	else {
+		p_pdqmb = p_pdqcb->p_pdqinib->p_pdqmb + p_pdqcb->unused;
+		p_pdqcb->unused++;
+	}
+
+	p_pdqmb->data = data;
+	p_pdqmb->datapri = datapri;
+
+	pp_prev_next = &(p_pdqcb->p_head);
+	while ((p_next = *pp_prev_next) != NULL) {
+		if (p_next->datapri > datapri) {
+			break;
+		}
+		pp_prev_next = &(p_next->p_next);
+	}
+	p_pdqmb->p_next = p_next;
+	*pp_prev_next = p_pdqmb;
+	p_pdqcb->count++;
+}
+
+#endif /* TOPPERS_pdqenq */
+
+/*
+ *  優先度データキュー管理領域からのデータの取出し
+ */
+#ifdef TOPPERS_pdqdeq
+
+void
+dequeue_pridata(PDQCB *p_pdqcb, intptr_t *p_data, PRI *p_datapri)
+{
+	PDQMB	*p_pdqmb;
+
+	p_pdqmb = p_pdqcb->p_head;
+	p_pdqcb->p_head = p_pdqmb->p_next;
+	p_pdqcb->count--;
+
+	*p_data = p_pdqmb->data;
+	*p_datapri = p_pdqmb->datapri;
+
+	p_pdqmb->p_next = p_pdqcb->p_freelist;
+	p_pdqcb->p_freelist = p_pdqmb;
+}
+
+#endif /* TOPPERS_pdqdeq */
+
+/*
+ *  優先度データキューへのデータ送信
+ */
+#ifdef TOPPERS_pdqsnd
+
+bool_t
+send_pridata(PDQCB *p_pdqcb, intptr_t data, PRI datapri, bool_t *p_dspreq)
+{
+	TCB		*p_tcb;
+
+	if (!queue_empty(&(p_pdqcb->rwait_queue))) {
+		p_tcb = (TCB *) queue_delete_next(&(p_pdqcb->rwait_queue));
+		((WINFO_PDQ *)(p_tcb->p_winfo))->data = data;
+		((WINFO_PDQ *)(p_tcb->p_winfo))->datapri = datapri;
+		*p_dspreq = wait_complete(p_tcb);
+		return(true);
+	}
+	else if (p_pdqcb->count < p_pdqcb->p_pdqinib->pdqcnt) {
+		enqueue_pridata(p_pdqcb, data, datapri);
+		*p_dspreq = false;
+		return(true);
+	}
+	else {
+		return(false);
+	}
+}
+
+#endif /* TOPPERS_pdqsnd */
+
+/*
+ *  優先度データキューからのデータ受信
+ */
+#ifdef TOPPERS_pdqrcv
+
+bool_t
+receive_pridata(PDQCB *p_pdqcb, intptr_t *p_data,
+									PRI *p_datapri, bool_t *p_dspreq)
+{
+	TCB		*p_tcb;
+	intptr_t data;
+	PRI		datapri;
+
+	if (p_pdqcb->count > 0U) {
+		dequeue_pridata(p_pdqcb, p_data, p_datapri);
+		if (!queue_empty(&(p_pdqcb->swait_queue))) {
+			p_tcb = (TCB *) queue_delete_next(&(p_pdqcb->swait_queue));
+			data = ((WINFO_PDQ *)(p_tcb->p_winfo))->data;
+			datapri = ((WINFO_PDQ *)(p_tcb->p_winfo))->datapri;
+			enqueue_pridata(p_pdqcb, data, datapri);
+			*p_dspreq = wait_complete(p_tcb);
+		}
+		else {
+			*p_dspreq = false;
+		}
+		return(true);
+	}
+	else if (!queue_empty(&(p_pdqcb->swait_queue))) {
+		p_tcb = (TCB *) queue_delete_next(&(p_pdqcb->swait_queue));
+		*p_data = ((WINFO_PDQ *)(p_tcb->p_winfo))->data;
+		*p_datapri = ((WINFO_PDQ *)(p_tcb->p_winfo))->datapri;
+		*p_dspreq = wait_complete(p_tcb);
+		return(true);
+	}
+	else {
+		return(false);
+	}
+}
+
+#endif /* TOPPERS_pdqrcv */
+
+/*
+ *  優先度データキューの生成
+ */
+#ifdef TOPPERS_acre_pdq
+
+ER_UINT
+acre_pdq(const T_CPDQ *pk_cpdq)
+{
+	PDQCB	*p_pdqcb;
+	PDQINIB	*p_pdqinib;
+	ATR		pdqatr;
+	PDQMB	*p_pdqmb;
+	ER		ercd;
+
+	LOG_ACRE_PDQ_ENTER(pk_cpdq);
+	CHECK_TSKCTX_UNL();
+	CHECK_RSATR(pk_cpdq->pdqatr, TA_TPRI);
+	CHECK_DPRI(pk_cpdq->maxdpri);
+	if (pk_cpdq->pdqmb != NULL) {
+		CHECK_ALIGN_MB(pk_cpdq->pdqmb);
+	}
+	pdqatr = pk_cpdq->pdqatr;
+	p_pdqmb = pk_cpdq->pdqmb;
+
+	t_lock_cpu();
+	if (tnum_pdq == 0 || queue_empty(&free_pdqcb)) {
+		ercd = E_NOID;
+	}
+	else {
+		if (pk_cpdq->pdqcnt != 0 && p_pdqmb == NULL) {
+			p_pdqmb = kernel_malloc(sizeof(PDQMB) * pk_cpdq->pdqcnt);
+			pdqatr |= TA_MBALLOC;
+		}
+		if (pk_cpdq->pdqcnt != 0 && p_pdqmb == NULL) {
+			ercd = E_NOMEM;
+		}
+		else {
+			p_pdqcb = ((PDQCB *) queue_delete_next(&free_pdqcb));
+			p_pdqinib = (PDQINIB *)(p_pdqcb->p_pdqinib);
+			p_pdqinib->pdqatr = pdqatr;
+			p_pdqinib->pdqcnt = pk_cpdq->pdqcnt;
+			p_pdqinib->maxdpri = pk_cpdq->maxdpri;
+			p_pdqinib->p_pdqmb = p_pdqmb;
+
+			queue_initialize(&(p_pdqcb->swait_queue));
+			queue_initialize(&(p_pdqcb->rwait_queue));
+			p_pdqcb->count = 0U;
+			p_pdqcb->p_head = NULL;
+			p_pdqcb->unused = 0U;
+			p_pdqcb->p_freelist = NULL;
+			ercd = PDQID(p_pdqcb);
+		}
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_ACRE_PDQ_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_acre_pdq */
+
+/*
+ *  優先度データキューの削除
+ */
+#ifdef TOPPERS_del_pdq
+
+ER
+del_pdq(ID pdqid)
+{
+	PDQCB	*p_pdqcb;
+	PDQINIB	*p_pdqinib;
+	bool_t	dspreq;
+	ER		ercd;
+
+	LOG_DEL_PDQ_ENTER(pdqid);
+	CHECK_TSKCTX_UNL();
+	CHECK_PDQID(pdqid);
+	p_pdqcb = get_pdqcb(pdqid);
+
+	t_lock_cpu();
+	if (p_pdqcb->p_pdqinib->pdqatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (PDQID(p_pdqcb) > tmax_spdqid) {
+		dspreq = init_wait_queue(&(p_pdqcb->swait_queue));
+		if (init_wait_queue(&(p_pdqcb->rwait_queue))) {
+			dspreq = true;
+		}
+		p_pdqinib = (PDQINIB *)(p_pdqcb->p_pdqinib);
+		if ((p_pdqinib->pdqatr & TA_MBALLOC) != 0U) {
+			kernel_free(p_pdqinib->p_pdqmb);
+		}
+		p_pdqinib->pdqatr = TA_NOEXS;
+		queue_insert_prev(&free_pdqcb, &(p_pdqcb->swait_queue));
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_OBJ;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_DEL_PDQ_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_del_pdq */
+
+/*
+ *  優先度データキューへの送信
+ */
+#ifdef TOPPERS_snd_pdq
+
+ER
+snd_pdq(ID pdqid, intptr_t data, PRI datapri)
+{
+	PDQCB	*p_pdqcb;
+	WINFO_PDQ winfo_pdq;
+	bool_t	dspreq;
+	ER		ercd;
+
+	LOG_SND_PDQ_ENTER(pdqid, data, datapri);
+	CHECK_DISPATCH();
+	CHECK_PDQID(pdqid);
+	p_pdqcb = get_pdqcb(pdqid);
+	CHECK_PAR(TMIN_DPRI <= datapri);
+
+	t_lock_cpu();
+	if (p_pdqcb->p_pdqinib->pdqatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (!(datapri <= p_pdqcb->p_pdqinib->maxdpri)) {
+		ercd = E_PAR;
+	}
+	else if (send_pridata(p_pdqcb, data, datapri, &dspreq)) {
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	else {
+		winfo_pdq.data = data;
+		winfo_pdq.datapri = datapri;
+		p_runtsk->tstat = (TS_WAITING | TS_WAIT_SPDQ);
+		wobj_make_wait((WOBJCB *) p_pdqcb, (WINFO_WOBJ *) &winfo_pdq);
+		dispatch();
+		ercd = winfo_pdq.winfo.wercd;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_SND_PDQ_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_snd_pdq */
+
+/*
+ *  優先度データキューへの送信（ポーリング）
+ */
+#ifdef TOPPERS_psnd_pdq
+
+ER
+psnd_pdq(ID pdqid, intptr_t data, PRI datapri)
+{
+	PDQCB	*p_pdqcb;
+	bool_t	dspreq;
+	ER		ercd;
+
+	LOG_PSND_PDQ_ENTER(pdqid, data, datapri);
+	CHECK_TSKCTX_UNL();
+	CHECK_PDQID(pdqid);
+	p_pdqcb = get_pdqcb(pdqid);
+	CHECK_PAR(TMIN_DPRI <= datapri);
+
+	t_lock_cpu();
+	if (p_pdqcb->p_pdqinib->pdqatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (!(datapri <= p_pdqcb->p_pdqinib->maxdpri)) {
+		ercd = E_PAR;
+	}
+	else if (send_pridata(p_pdqcb, data, datapri, &dspreq)) {
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_TMOUT;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_PSND_PDQ_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_psnd_pdq */
+
+/*
+ *  優先度データキューへの送信（ポーリング，非タスクコンテキスト用）
+ */
+#ifdef TOPPERS_ipsnd_pdq
+
+ER
+ipsnd_pdq(ID pdqid, intptr_t data, PRI datapri)
+{
+	PDQCB	*p_pdqcb;
+	bool_t	dspreq;
+	ER		ercd;
+
+	LOG_IPSND_PDQ_ENTER(pdqid, data, datapri);
+	CHECK_INTCTX_UNL();
+	CHECK_PDQID(pdqid);
+	p_pdqcb = get_pdqcb(pdqid);
+	CHECK_PAR(TMIN_DPRI <= datapri);
+
+	i_lock_cpu();
+	if (p_pdqcb->p_pdqinib->pdqatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (!(datapri <= p_pdqcb->p_pdqinib->maxdpri)) {
+		ercd = E_PAR;
+	}
+	else if (send_pridata(p_pdqcb, data, datapri, &dspreq)) {
+		if (dspreq) {
+			reqflg = true;
+		}
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_TMOUT;
+	}
+	i_unlock_cpu();
+
+  error_exit:
+	LOG_IPSND_PDQ_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ipsnd_pdq */
+
+/*
+ *  優先度データキューへの送信（タイムアウトあり）
+ */
+#ifdef TOPPERS_tsnd_pdq
+
+ER
+tsnd_pdq(ID pdqid, intptr_t data, PRI datapri, TMO tmout)
+{
+	PDQCB	*p_pdqcb;
+	WINFO_PDQ winfo_pdq;
+	TMEVTB	tmevtb;
+	bool_t	dspreq;
+	ER		ercd;
+
+	LOG_TSND_PDQ_ENTER(pdqid, data, datapri, tmout);
+	CHECK_DISPATCH();
+	CHECK_PDQID(pdqid);
+	CHECK_TMOUT(tmout);
+	p_pdqcb = get_pdqcb(pdqid);
+	CHECK_PAR(TMIN_DPRI <= datapri);
+
+	t_lock_cpu();
+	if (p_pdqcb->p_pdqinib->pdqatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (!(datapri <= p_pdqcb->p_pdqinib->maxdpri)) {
+		ercd = E_PAR;
+	}
+	else if (send_pridata(p_pdqcb, data, datapri, &dspreq)) {
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	else if (tmout == TMO_POL) {
+		ercd = E_TMOUT;
+	}
+	else {
+		winfo_pdq.data = data;
+		winfo_pdq.datapri = datapri;
+		p_runtsk->tstat = (TS_WAITING | TS_WAIT_SPDQ);
+		wobj_make_wait_tmout((WOBJCB *) p_pdqcb, (WINFO_WOBJ *) &winfo_pdq,
+														&tmevtb, tmout);
+		dispatch();
+		ercd = winfo_pdq.winfo.wercd;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_TSND_PDQ_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_tsnd_pdq */
+
+/*
+ *  優先度データキューからの受信
+ */
+#ifdef TOPPERS_rcv_pdq
+
+ER
+rcv_pdq(ID pdqid, intptr_t *p_data, PRI *p_datapri)
+{
+	PDQCB	*p_pdqcb;
+	WINFO_PDQ winfo_pdq;
+	bool_t	dspreq;
+	ER		ercd;
+
+	LOG_RCV_PDQ_ENTER(pdqid, p_data, p_datapri);
+	CHECK_DISPATCH();
+	CHECK_PDQID(pdqid);
+	p_pdqcb = get_pdqcb(pdqid);
+
+	t_lock_cpu();
+	if (p_pdqcb->p_pdqinib->pdqatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (receive_pridata(p_pdqcb, p_data, p_datapri, &dspreq)) {
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	else {
+		p_runtsk->tstat = (TS_WAITING | TS_WAIT_RPDQ);
+		make_wait(&(winfo_pdq.winfo));
+		queue_insert_prev(&(p_pdqcb->rwait_queue), &(p_runtsk->task_queue));
+		winfo_pdq.p_pdqcb = p_pdqcb;
+		LOG_TSKSTAT(p_runtsk);
+		dispatch();
+		ercd = winfo_pdq.winfo.wercd;
+		if (ercd == E_OK) {
+			*p_data = winfo_pdq.data;
+			*p_datapri = winfo_pdq.datapri;
+		}
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_RCV_PDQ_LEAVE(ercd, *p_data, *p_datapri);
+	return(ercd);
+}
+
+#endif /* TOPPERS_rcv_pdq */
+
+/*
+ *  優先度データキューからの受信（ポーリング）
+ */
+#ifdef TOPPERS_prcv_pdq
+
+ER
+prcv_pdq(ID pdqid, intptr_t *p_data, PRI *p_datapri)
+{
+	PDQCB	*p_pdqcb;
+	bool_t	dspreq;
+	ER		ercd;
+
+	LOG_PRCV_PDQ_ENTER(pdqid, p_data, p_datapri);
+	CHECK_TSKCTX_UNL();
+	CHECK_PDQID(pdqid);
+	p_pdqcb = get_pdqcb(pdqid);
+
+	t_lock_cpu();
+	if (p_pdqcb->p_pdqinib->pdqatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (receive_pridata(p_pdqcb, p_data, p_datapri, &dspreq)) {
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_TMOUT;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_PRCV_PDQ_LEAVE(ercd, *p_data, *p_datapri);
+	return(ercd);
+}
+
+#endif /* TOPPERS_prcv_pdq */
+
+/*
+ *  優先度データキューからの受信（タイムアウトあり）
+ */
+#ifdef TOPPERS_trcv_pdq
+
+ER
+trcv_pdq(ID pdqid, intptr_t *p_data, PRI *p_datapri, TMO tmout)
+{
+	PDQCB	*p_pdqcb;
+	WINFO_PDQ winfo_pdq;
+	TMEVTB	tmevtb;
+	bool_t	dspreq;
+	ER		ercd;
+
+	LOG_TRCV_PDQ_ENTER(pdqid, p_data, p_datapri, tmout);
+	CHECK_DISPATCH();
+	CHECK_PDQID(pdqid);
+	CHECK_TMOUT(tmout);
+	p_pdqcb = get_pdqcb(pdqid);
+
+	t_lock_cpu();
+	if (p_pdqcb->p_pdqinib->pdqatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (receive_pridata(p_pdqcb, p_data, p_datapri, &dspreq)) {
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	else if (tmout == TMO_POL) {
+		ercd = E_TMOUT;
+	}
+	else {
+		p_runtsk->tstat = (TS_WAITING | TS_WAIT_RPDQ);
+		make_wait_tmout(&(winfo_pdq.winfo), &tmevtb, tmout);
+		queue_insert_prev(&(p_pdqcb->rwait_queue), &(p_runtsk->task_queue));
+		winfo_pdq.p_pdqcb = p_pdqcb;
+		LOG_TSKSTAT(p_runtsk);
+		dispatch();
+		ercd = winfo_pdq.winfo.wercd;
+		if (ercd == E_OK) {
+			*p_data = winfo_pdq.data;
+			*p_datapri = winfo_pdq.datapri;
+		}
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_TRCV_PDQ_LEAVE(ercd, *p_data, *p_datapri);
+	return(ercd);
+}
+
+#endif /* TOPPERS_trcv_pdq */
+
+/*
+ *  優先度データキューの再初期化
+ */
+#ifdef TOPPERS_ini_pdq
+
+ER
+ini_pdq(ID pdqid)
+{
+	PDQCB	*p_pdqcb;
+	bool_t	dspreq;
+	ER		ercd;
+    
+	LOG_INI_PDQ_ENTER(pdqid);
+	CHECK_TSKCTX_UNL();
+	CHECK_PDQID(pdqid);
+	p_pdqcb = get_pdqcb(pdqid);
+
+	t_lock_cpu();
+	if (p_pdqcb->p_pdqinib->pdqatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		dspreq = init_wait_queue(&(p_pdqcb->swait_queue));
+		if (init_wait_queue(&(p_pdqcb->rwait_queue))) {
+			dspreq = true;
+		}
+		p_pdqcb->count = 0U;
+		p_pdqcb->p_head = NULL;
+		p_pdqcb->unused = 0U;
+		p_pdqcb->p_freelist = NULL;
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_INI_PDQ_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ini_pdq */
+
+/*
+ *  優先度データキューの状態参照
+ */
+#ifdef TOPPERS_ref_pdq
+
+ER
+ref_pdq(ID pdqid, T_RPDQ *pk_rpdq)
+{
+	PDQCB	*p_pdqcb;
+	ER		ercd;
+    
+	LOG_REF_PDQ_ENTER(pdqid, pk_rpdq);
+	CHECK_TSKCTX_UNL();
+	CHECK_PDQID(pdqid);
+	p_pdqcb = get_pdqcb(pdqid);
+
+	t_lock_cpu();
+	if (p_pdqcb->p_pdqinib->pdqatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		pk_rpdq->stskid = wait_tskid(&(p_pdqcb->swait_queue));
+		pk_rpdq->rtskid = wait_tskid(&(p_pdqcb->rwait_queue));
+		pk_rpdq->spdqcnt = p_pdqcb->count;
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_REF_PDQ_LEAVE(ercd, pk_rpdq);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ref_pdq */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/pridataq.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/pridataq.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/pridataq.h	(revision 453)
@@ -0,0 +1,165 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2013 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		優先度データキュー機能
+ */
+
+#ifndef TOPPERS_PRIDATAQ_H
+#define TOPPERS_PRIDATAQ_H
+
+#include "wait.h"
+
+/*
+ *  優先度データ管理ブロック
+ */
+typedef struct pridata_management_block PDQMB;
+
+struct pridata_management_block {
+	PDQMB		*p_next;		/* 次のデータ */
+	intptr_t	data;			/* データ本体 */
+	PRI			datapri;		/* データ優先度 */
+};
+
+/*
+ *  優先度データキュー初期化ブロック
+ *
+ *  この構造体は，同期・通信オブジェクトの初期化ブロックの共通部分
+ *  （WOBJINIB）を拡張（オブジェクト指向言語の継承に相当）したもので，
+ *  最初のフィールドが共通になっている．
+ */
+typedef struct pridataq_initialization_block {
+	ATR			pdqatr;			/* 優先度データキュー属性 */
+	uint_t		pdqcnt;			/* 優先度データキューの容量 */
+	PRI			maxdpri;		/* データ優先度の最大値 */
+	PDQMB		*p_pdqmb;		/* 優先度データキュー管理領域の先頭番地 */
+} PDQINIB;
+
+/*
+ *  優先度データキュー管理ブロック
+ *
+ *  この構造体は，同期・通信オブジェクトの管理ブロックの共通部分（WOBJCB）
+ *  を拡張（オブジェクト指向言語の継承に相当）したもので，最初の2つの
+ *  フィールドが共通になっている．
+ */
+typedef struct pridataq_control_block {
+	QUEUE		swait_queue;	/* 優先度データキュー送信待ちキュー */
+	const PDQINIB *p_pdqinib;	/* 初期化ブロックへのポインタ */
+	QUEUE		rwait_queue;	/* 優先度データキュー受信待ちキュー */
+	uint_t		count;			/* 優先度データキュー中のデータの数 */
+	PDQMB		*p_head;		/* 最初のデータ */
+	uint_t		unused;			/* 未使用データ管理ブロックの先頭 */
+	PDQMB		*p_freelist;	/* 未割当てデータ管理ブロックのリスト */
+} PDQCB;
+
+/*
+ *  優先度データキュー待ち情報ブロックの定義
+ *
+ *  この構造体は，同期・通信オブジェクトの待ち情報ブロックの共通部分
+ *  （WINFO_WOBJ）を拡張（オブジェクト指向言語の継承に相当）したもので，
+ *  最初の2つのフィールドが共通になっている．
+ *  優先度データキューへの送信待ちと優先度データキューからの受信待ちで，
+ *  同じ待ち情報ブロックを使う．
+ */
+typedef struct pridataq_waiting_information {
+	WINFO		winfo;			/* 標準の待ち情報ブロック */
+	PDQCB		*p_pdqcb;		/* 待っている優先度データキューの管理ブロック*/
+	intptr_t	data;			/* 送受信データ */
+	PRI			datapri;		/* データ優先度 */
+} WINFO_PDQ;
+
+/*
+ *  使用していない優先度データキュー管理ブロックのリスト
+ */
+extern QUEUE	free_pdqcb;
+
+/*
+ *  優先度データキューIDの最大値（kernel_cfg.c）
+ */
+extern const ID	tmax_pdqid;
+extern const ID	tmax_spdqid;
+
+/*
+ *  優先度データキュー初期化ブロックのエリア（kernel_cfg.c）
+ */
+extern const PDQINIB	pdqinib_table[];
+extern PDQINIB			apdqinib_table[];
+
+/*
+ *  優先度データキュー管理ブロックのエリア（kernel_cfg.c）
+ */
+extern PDQCB	pdqcb_table[];
+
+/*
+ *  優先度データキュー管理ブロックから優先度データキューIDを取り出すた
+ *  めのマクロ
+ */
+#define	PDQID(p_pdqcb)	((ID)(((p_pdqcb) - pdqcb_table) + TMIN_PDQID))
+
+/*
+ *  優先度データキュー機能の初期化
+ */
+extern void	initialize_pridataq(void);
+
+/*
+ *  優先度データキュー管理領域へのデータの格納
+ */
+extern void	enqueue_pridata(PDQCB *p_pdqcb, intptr_t data, PRI datapri);
+
+/*
+ *  優先度データキュー管理領域からのデータの取出し
+ */
+extern void	dequeue_pridata(PDQCB *p_pdqcb, intptr_t *p_data, PRI *p_datapri);
+
+/*
+ *  優先度データキューへのデータ送信
+ */
+extern bool_t	send_pridata(PDQCB *p_pdqcb, intptr_t data,
+											PRI datapri, bool_t *p_dspreq);
+
+/*
+ *  優先度データキューからのデータ受信
+ */
+extern bool_t	receive_pridata(PDQCB *p_pdqcb, intptr_t *p_data,
+											PRI *p_datapri, bool_t *p_dspreq);
+
+#endif /* TOPPERS_PRIDATAQ_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/semaphore.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/semaphore.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/semaphore.c	(revision 453)
@@ -0,0 +1,541 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2012 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		セマフォ機能
+ */
+
+#include "kernel_impl.h"
+#include "check.h"
+#include "task.h"
+#include "wait.h"
+#include "semaphore.h"
+
+/*
+ *  トレースログマクロのデフォルト定義
+ */
+#ifndef LOG_ACRE_SEM_ENTER
+#define LOG_ACRE_SEM_ENTER(pk_csem)
+#endif /* LOG_ACRE_SEM_ENTER */
+
+#ifndef LOG_ACRE_SEM_LEAVE
+#define LOG_ACRE_SEM_LEAVE(ercd)
+#endif /* LOG_ACRE_SEM_LEAVE */
+
+#ifndef LOG_DEL_SEM_ENTER
+#define LOG_DEL_SEM_ENTER(semid)
+#endif /* LOG_DEL_SEM_ENTER */
+
+#ifndef LOG_DEL_SEM_LEAVE
+#define LOG_DEL_SEM_LEAVE(ercd)
+#endif /* LOG_DEL_SEM_LEAVE */
+
+#ifndef LOG_SIG_SEM_ENTER
+#define LOG_SIG_SEM_ENTER(semid)
+#endif /* LOG_SIG_SEM_ENTER */
+
+#ifndef LOG_SIG_SEM_LEAVE
+#define LOG_SIG_SEM_LEAVE(ercd)
+#endif /* LOG_SIG_SEM_LEAVE */
+
+#ifndef LOG_ISIG_SEM_ENTER
+#define LOG_ISIG_SEM_ENTER(semid)
+#endif /* LOG_ISIG_SEM_ENTER */
+
+#ifndef LOG_ISIG_SEM_LEAVE
+#define LOG_ISIG_SEM_LEAVE(ercd)
+#endif /* LOG_ISIG_SEM_LEAVE */
+
+#ifndef LOG_WAI_SEM_ENTER
+#define LOG_WAI_SEM_ENTER(semid)
+#endif /* LOG_WAI_SEM_ENTER */
+
+#ifndef LOG_WAI_SEM_LEAVE
+#define LOG_WAI_SEM_LEAVE(ercd)
+#endif /* LOG_WAI_SEM_LEAVE */
+
+#ifndef LOG_POL_SEM_ENTER
+#define LOG_POL_SEM_ENTER(semid)
+#endif /* LOG_POL_SEM_ENTER */
+
+#ifndef LOG_POL_SEM_LEAVE
+#define LOG_POL_SEM_LEAVE(ercd)
+#endif /* LOG_POL_SEM_LEAVE */
+
+#ifndef LOG_TWAI_SEM_ENTER
+#define LOG_TWAI_SEM_ENTER(semid, tmout)
+#endif /* LOG_TWAI_SEM_ENTER */
+
+#ifndef LOG_TWAI_SEM_LEAVE
+#define LOG_TWAI_SEM_LEAVE(ercd)
+#endif /* LOG_TWAI_SEM_LEAVE */
+
+#ifndef LOG_INI_SEM_ENTER
+#define LOG_INI_SEM_ENTER(semid)
+#endif /* LOG_INI_SEM_ENTER */
+
+#ifndef LOG_INI_SEM_LEAVE
+#define LOG_INI_SEM_LEAVE(ercd)
+#endif /* LOG_INI_SEM_LEAVE */
+
+#ifndef LOG_REF_SEM_ENTER
+#define LOG_REF_SEM_ENTER(semid, pk_rsem)
+#endif /* LOG_REF_SEM_ENTER */
+
+#ifndef LOG_REF_SEM_LEAVE
+#define LOG_REF_SEM_LEAVE(ercd, pk_rsem)
+#endif /* LOG_REF_SEM_LEAVE */
+
+/*
+ *  セマフォの数
+ */
+#define tnum_sem	((uint_t)(tmax_semid - TMIN_SEMID + 1))
+#define tnum_ssem	((uint_t)(tmax_ssemid - TMIN_SEMID + 1))
+
+/*
+ *  セマフォIDからセマフォ管理ブロックを取り出すためのマクロ
+ */
+#define INDEX_SEM(semid)	((uint_t)((semid) - TMIN_SEMID))
+#define get_semcb(semid)	(&(semcb_table[INDEX_SEM(semid)]))
+
+#ifdef TOPPERS_semini
+
+/*
+ *  使用していないセマフォ管理ブロックのリスト
+ */
+QUEUE	free_semcb;
+
+/* 
+ *  セマフォ機能の初期化
+ */
+void
+initialize_semaphore(void)
+{
+	uint_t	i, j;
+	SEMCB	*p_semcb;
+	SEMINIB	*p_seminib;
+
+	for (i = 0; i < tnum_ssem; i++) {
+		p_semcb = &(semcb_table[i]);
+		queue_initialize(&(p_semcb->wait_queue));
+		p_semcb->p_seminib = &(seminib_table[i]);
+		p_semcb->semcnt = p_semcb->p_seminib->isemcnt;
+	}
+	queue_initialize(&free_semcb);
+	for (j = 0; i < tnum_sem; i++, j++) {
+		p_semcb = &(semcb_table[i]);
+		p_seminib = &(aseminib_table[j]);
+		p_seminib->sematr = TA_NOEXS;
+		p_semcb->p_seminib = ((const SEMINIB *) p_seminib);
+		queue_insert_prev(&free_semcb, &(p_semcb->wait_queue));
+	}
+}
+
+#endif /* TOPPERS_semini */
+
+/*
+ *  セマフォの生成
+ */
+#ifdef TOPPERS_acre_sem
+
+ER_UINT
+acre_sem(const T_CSEM *pk_csem)
+{
+	SEMCB	*p_semcb;
+	SEMINIB	*p_seminib;
+	ER		ercd;
+
+	LOG_ACRE_SEM_ENTER(pk_csem);
+	CHECK_TSKCTX_UNL();
+	CHECK_RSATR(pk_csem->sematr, TA_TPRI);
+	CHECK_PAR(0 <= pk_csem->isemcnt && pk_csem->isemcnt <= pk_csem->maxsem);
+	CHECK_PAR(1 <= pk_csem->maxsem && pk_csem->maxsem <= TMAX_MAXSEM);
+
+	t_lock_cpu();
+	if (tnum_sem == 0 || queue_empty(&free_semcb)) {
+		ercd = E_NOID;
+	}
+	else {
+		p_semcb = ((SEMCB *) queue_delete_next(&free_semcb));
+		p_seminib = (SEMINIB *)(p_semcb->p_seminib);
+		p_seminib->sematr = pk_csem->sematr;
+		p_seminib->isemcnt = pk_csem->isemcnt;
+		p_seminib->maxsem = pk_csem->maxsem;
+
+		queue_initialize(&(p_semcb->wait_queue));
+		p_semcb->semcnt = p_semcb->p_seminib->isemcnt;
+		ercd = SEMID(p_semcb);
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_ACRE_SEM_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_acre_sem */
+
+/*
+ *  セマフォの削除
+ */
+#ifdef TOPPERS_del_sem
+
+ER
+del_sem(ID semid)
+{
+	SEMCB	*p_semcb;
+	SEMINIB	*p_seminib;
+	bool_t	dspreq;
+	ER		ercd;
+
+	LOG_DEL_SEM_ENTER(semid);
+	CHECK_TSKCTX_UNL();
+	CHECK_SEMID(semid);
+	p_semcb = get_semcb(semid);
+
+	t_lock_cpu();
+	if (p_semcb->p_seminib->sematr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (SEMID(p_semcb) > tmax_ssemid) {
+		dspreq = init_wait_queue(&(p_semcb->wait_queue));
+		p_seminib = (SEMINIB *)(p_semcb->p_seminib);
+		p_seminib->sematr = TA_NOEXS;
+		queue_insert_prev(&free_semcb, &(p_semcb->wait_queue));
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_OBJ;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_DEL_SEM_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_del_sem */
+
+/*
+ *  セマフォ資源の返却
+ */
+#ifdef TOPPERS_sig_sem
+
+ER
+sig_sem(ID semid)
+{
+	SEMCB	*p_semcb;
+	TCB		*p_tcb;
+	ER		ercd;
+    
+	LOG_SIG_SEM_ENTER(semid);
+	CHECK_TSKCTX_UNL();
+	CHECK_SEMID(semid);
+	p_semcb = get_semcb(semid);
+
+	t_lock_cpu();
+	if (p_semcb->p_seminib->sematr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (!queue_empty(&(p_semcb->wait_queue))) {
+		p_tcb = (TCB *) queue_delete_next(&(p_semcb->wait_queue));
+		if (wait_complete(p_tcb)) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	else if (p_semcb->semcnt < p_semcb->p_seminib->maxsem) {
+		p_semcb->semcnt += 1;
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_QOVR;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_SIG_SEM_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_sig_sem */
+
+/*
+ *  セマフォ資源の返却（非タスクコンテキスト用）
+ */
+#ifdef TOPPERS_isig_sem
+
+ER
+isig_sem(ID semid)
+{
+	SEMCB	*p_semcb;
+	TCB		*p_tcb;
+	ER		ercd;
+    
+	LOG_ISIG_SEM_ENTER(semid);
+	CHECK_INTCTX_UNL();
+	CHECK_SEMID(semid);
+	p_semcb = get_semcb(semid);
+
+	i_lock_cpu();
+	if (p_semcb->p_seminib->sematr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (!queue_empty(&(p_semcb->wait_queue))) {
+		p_tcb = (TCB *) queue_delete_next(&(p_semcb->wait_queue));
+		if (wait_complete(p_tcb)) {
+			reqflg = true;
+		}
+		ercd = E_OK;
+	}
+	else if (p_semcb->semcnt < p_semcb->p_seminib->maxsem) {
+		p_semcb->semcnt += 1;
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_QOVR;
+	}
+	i_unlock_cpu();
+
+  error_exit:
+	LOG_ISIG_SEM_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_isig_sem */
+
+/*
+ *  セマフォ資源の獲得
+ */
+#ifdef TOPPERS_wai_sem
+
+ER
+wai_sem(ID semid)
+{
+	SEMCB	*p_semcb;
+	WINFO_SEM winfo_sem;
+	ER		ercd;
+
+	LOG_WAI_SEM_ENTER(semid);
+	CHECK_DISPATCH();
+	CHECK_SEMID(semid);
+	p_semcb = get_semcb(semid);
+
+	t_lock_cpu();
+	if (p_semcb->p_seminib->sematr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (p_semcb->semcnt >= 1) {
+		p_semcb->semcnt -= 1;
+		ercd = E_OK;
+	}
+	else {
+		p_runtsk->tstat = (TS_WAITING | TS_WAIT_SEM);
+		wobj_make_wait((WOBJCB *) p_semcb, (WINFO_WOBJ *) &winfo_sem);
+		dispatch();
+		ercd = winfo_sem.winfo.wercd;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_WAI_SEM_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_wai_sem */
+
+/*
+ *  セマフォ資源の獲得（ポーリング）
+ */
+#ifdef TOPPERS_pol_sem
+
+ER
+pol_sem(ID semid)
+{
+	SEMCB	*p_semcb;
+	ER		ercd;
+
+	LOG_POL_SEM_ENTER(semid);
+	CHECK_TSKCTX_UNL();
+	CHECK_SEMID(semid);
+	p_semcb = get_semcb(semid);
+
+	t_lock_cpu();
+	if (p_semcb->p_seminib->sematr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (p_semcb->semcnt >= 1) {
+		p_semcb->semcnt -= 1;
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_TMOUT;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_POL_SEM_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_pol_sem */
+
+/*
+ *  セマフォ資源の獲得（タイムアウトあり）
+ */
+#ifdef TOPPERS_twai_sem
+
+ER
+twai_sem(ID semid, TMO tmout)
+{
+	SEMCB	*p_semcb;
+	WINFO_SEM winfo_sem;
+	TMEVTB	tmevtb;
+	ER		ercd;
+
+	LOG_TWAI_SEM_ENTER(semid, tmout);
+	CHECK_DISPATCH();
+	CHECK_SEMID(semid);
+	CHECK_TMOUT(tmout);
+	p_semcb = get_semcb(semid);
+
+	t_lock_cpu();
+	if (p_semcb->p_seminib->sematr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (p_semcb->semcnt >= 1) {
+		p_semcb->semcnt -= 1;
+		ercd = E_OK;
+	}
+	else if (tmout == TMO_POL) {
+		ercd = E_TMOUT;
+	}
+	else {
+		p_runtsk->tstat = (TS_WAITING | TS_WAIT_SEM);
+		wobj_make_wait_tmout((WOBJCB *) p_semcb, (WINFO_WOBJ *) &winfo_sem,
+														&tmevtb, tmout);
+		dispatch();
+		ercd = winfo_sem.winfo.wercd;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_TWAI_SEM_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_twai_sem */
+
+/*
+ *  セマフォの再初期化
+ */
+#ifdef TOPPERS_ini_sem
+
+ER
+ini_sem(ID semid)
+{
+	SEMCB	*p_semcb;
+	bool_t	dspreq;
+	ER		ercd;
+    
+	LOG_INI_SEM_ENTER(semid);
+	CHECK_TSKCTX_UNL();
+	CHECK_SEMID(semid);
+	p_semcb = get_semcb(semid);
+
+	t_lock_cpu();
+	if (p_semcb->p_seminib->sematr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		dspreq = init_wait_queue(&(p_semcb->wait_queue));
+		p_semcb->semcnt = p_semcb->p_seminib->isemcnt;
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_INI_SEM_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ini_sem */
+
+/*
+ *  セマフォの状態参照
+ */
+#ifdef TOPPERS_ref_sem
+
+ER
+ref_sem(ID semid, T_RSEM *pk_rsem)
+{
+	SEMCB	*p_semcb;
+	ER		ercd;
+    
+	LOG_REF_SEM_ENTER(semid, pk_rsem);
+	CHECK_TSKCTX_UNL();
+	CHECK_SEMID(semid);
+	p_semcb = get_semcb(semid);
+
+	t_lock_cpu();
+	if (p_semcb->p_seminib->sematr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		pk_rsem->wtskid = wait_tskid(&(p_semcb->wait_queue));
+		pk_rsem->semcnt = p_semcb->semcnt;
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_REF_SEM_LEAVE(ercd, pk_rsem);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ref_sem */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/semaphore.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/semaphore.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/semaphore.h	(revision 453)
@@ -0,0 +1,122 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2012 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		セマフォ機能
+ */
+
+#ifndef TOPPERS_SEMAPHORE_H
+#define TOPPERS_SEMAPHORE_H
+
+#include "wait.h"
+
+/*
+ *  セマフォ初期化ブロック
+ *
+ *  この構造体は，同期・通信オブジェクトの初期化ブロックの共通部分
+ *  （WOBJINIB）を拡張（オブジェクト指向言語の継承に相当）したもので，
+ *  最初のフィールドが共通になっている．
+ */
+typedef struct semaphore_initialization_block {
+	ATR			sematr;			/* セマフォ属性 */
+	uint_t		isemcnt;		/* セマフォの資源数の初期値 */
+	uint_t		maxsem;			/* セマフォの最大資源数 */
+} SEMINIB;
+
+/*
+ *  セマフォ管理ブロック
+ *
+ *  この構造体は，同期・通信オブジェクトの管理ブロックの共通部分（WOBJCB）
+ *  を拡張（オブジェクト指向言語の継承に相当）したもので，最初の2つの
+ *  フィールドが共通になっている．
+ */
+typedef struct semaphore_control_block {
+	QUEUE		wait_queue;		/* セマフォ待ちキュー */
+	const SEMINIB *p_seminib;	/* 初期化ブロックへのポインタ */
+	uint_t		semcnt;			/* セマフォ現在カウント値 */
+} SEMCB;
+
+/*
+ *  セマフォ待ち情報ブロックの定義
+ *
+ *  この構造体は，同期・通信オブジェクトの待ち情報ブロックの共通部分
+ *  （WINFO_WOBJ）を拡張（オブジェクト指向言語の継承に相当）したもので，
+ *  すべてのフィールドが共通になっている．
+ */
+typedef struct semaphore_waiting_information {
+	WINFO	winfo;			/* 標準の待ち情報ブロック */
+	SEMCB	*p_semcb;		/* 待っているセマフォの管理ブロック */
+} WINFO_SEM;
+
+/*
+ *  使用していないセマフォ管理ブロックのリスト
+ */
+extern QUEUE	free_semcb;
+
+/*
+ *  セマフォIDの最大値（kernel_cfg.c）
+ */
+extern const ID	tmax_semid;
+extern const ID	tmax_ssemid;
+
+/*
+ *  セマフォ初期化ブロックのエリア（kernel_cfg.c）
+ */
+extern const SEMINIB	seminib_table[];
+extern SEMINIB			aseminib_table[];
+
+/*
+ *  セマフォ管理ブロックのエリア（kernel_cfg.c）
+ */
+extern SEMCB	semcb_table[];
+
+/*
+ *  セマフォ管理ブロックからセマフォIDを取り出すためのマクロ
+ */
+#define	SEMID(p_semcb)	((ID)(((p_semcb) - semcb_table) + TMIN_SEMID))
+
+/*
+ *  セマフォ機能の初期化
+ */
+extern void	initialize_semaphore(void);
+
+#endif /* TOPPERS_SEMAPHORE_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/startup.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/startup.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/startup.c	(revision 453)
@@ -0,0 +1,210 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		カーネルの初期化と終了処理
+ */
+
+#include "kernel_impl.h"
+#include "time_event.h"
+#include <sil.h>
+
+/*
+ *  トレースログマクロのデフォルト定義
+ */
+#ifndef LOG_KER_ENTER
+#define LOG_KER_ENTER()
+#endif /* LOG_KER_ENTER */
+
+#ifndef LOG_KER_LEAVE
+#define LOG_KER_LEAVE()
+#endif /* LOG_KER_LEAVE */
+
+#ifndef LOG_EXT_KER_ENTER
+#define LOG_EXT_KER_ENTER()
+#endif /* LOG_EXT_KER_ENTER */
+
+#ifndef LOG_EXT_KER_LEAVE
+#define LOG_EXT_KER_LEAVE(ercd)
+#endif /* LOG_EXT_KER_LEAVE */
+
+#ifdef TOPPERS_sta_ker
+
+/*
+ *  カーネル動作状態フラグ
+ *
+ *  スタートアップルーチンで，false（＝0）に初期化されることを期待して
+ *  いる．
+ */
+bool_t	kerflg = false;
+
+/*
+ *  カーネルの起動
+ */
+void
+sta_ker(void)
+{
+	/*
+	 *  ターゲット依存の初期化
+	 */
+	target_initialize();
+
+	/*
+	 *  各モジュールの初期化
+	 *
+	 *  タイムイベント管理モジュールは他のモジュールより先に初期化
+	 *  する必要がある．
+	 */
+	initialize_kmm();
+	initialize_tmevt();
+	initialize_object();
+
+	/*
+	 *  初期化ルーチンの実行
+	 */ 
+	call_inirtn();
+
+	/*
+	 *  カーネル動作の開始
+	 */
+	kerflg = true;
+	LOG_KER_ENTER();
+	start_dispatch();
+	assert(0);
+}
+
+#endif /* TOPPERS_sta_ker */
+
+/*
+ *  カーネルの終了
+ */
+#ifdef TOPPERS_ext_ker
+
+ER
+ext_ker(void)
+{
+	SIL_PRE_LOC;
+
+	LOG_EXT_KER_ENTER();
+
+	/*
+	 *  割込みロック状態に移行
+	 */
+	SIL_LOC_INT();
+
+	/*
+	 *  カーネル動作の終了
+	 */
+	LOG_KER_LEAVE();
+	kerflg = false;
+
+	/*
+	 *  カーネルの終了処理の呼出し
+	 *
+	 *  非タスクコンテキストに切り換えて，exit_kernelを呼び出す．
+	 */
+	call_exit_kernel();
+
+	/*
+	 *  コンパイラの警告対策（ここへ来ることはないはず）
+	 */
+	SIL_UNL_INT();
+	LOG_EXT_KER_LEAVE(E_SYS);
+	return(E_SYS);
+}
+
+/*
+ *  カーネルの終了処理
+ */
+void
+exit_kernel(void)
+{
+	/*
+	 *  終了処理ルーチンの実行
+	 */
+	call_terrtn();
+
+	/*
+	 *  ターゲット依存の終了処理
+	 */
+	target_exit();
+	assert(0);
+}
+
+#endif /* TOPPERS_ext_ker */
+
+/*
+ *  カーネルの割り付けるメモリ領域の管理
+ *
+ *  メモリ領域を先頭から順に割り当て，解放されたメモリ領域を再利用しな
+ *  いメモリ管理モジュール．
+ */
+#ifdef TOPPERS_kermem
+#ifndef OMIT_KMM_ALLOCONLY
+
+static void	*kmm_brk;
+
+void
+initialize_kmm(void)
+{
+	kmm_brk = ((char *) kmm) + kmmsz;
+}
+
+void *
+kernel_malloc(SIZE size)
+{
+	if (((char *) kmm_brk) - ((char *) kmm) >= size) {
+		kmm_brk = ((char *) kmm_brk) - size;
+		return(kmm_brk);
+	}
+	else {
+		return(NULL);
+	}
+}
+
+void
+kernel_free(void *ptr)
+{
+}
+
+#endif /* OMIT_KMM_ALLOCONLY */
+#endif /* TOPPERS_kermem */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/sys_manage.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/sys_manage.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/sys_manage.c	(revision 453)
@@ -0,0 +1,535 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		システム状態管理機能
+ */
+
+#include "kernel_impl.h"
+#include "check.h"
+#include "task.h"
+
+/*
+ *  トレースログマクロのデフォルト定義
+ */
+#ifndef LOG_ROT_RDQ_ENTER
+#define LOG_ROT_RDQ_ENTER(tskpri)
+#endif /* LOG_ROT_RDQ_ENTER */
+
+#ifndef LOG_ROT_RDQ_LEAVE
+#define LOG_ROT_RDQ_LEAVE(ercd)
+#endif /* LOG_ROT_RDQ_LEAVE */
+
+#ifndef LOG_IROT_RDQ_ENTER
+#define LOG_IROT_RDQ_ENTER(tskpri)
+#endif /* LOG_IROT_RDQ_ENTER */
+
+#ifndef LOG_IROT_RDQ_LEAVE
+#define LOG_IROT_RDQ_LEAVE(ercd)
+#endif /* LOG_IROT_RDQ_LEAVE */
+
+#ifndef LOG_GET_TID_ENTER
+#define LOG_GET_TID_ENTER(p_tskid)
+#endif /* LOG_GET_TID_ENTER */
+
+#ifndef LOG_GET_TID_LEAVE
+#define LOG_GET_TID_LEAVE(ercd, tskid)
+#endif /* LOG_GET_TID_LEAVE */
+
+#ifndef LOG_IGET_TID_ENTER
+#define LOG_IGET_TID_ENTER(p_tskid)
+#endif /* LOG_IGET_TID_ENTER */
+
+#ifndef LOG_IGET_TID_LEAVE
+#define LOG_IGET_TID_LEAVE(ercd, tskid)
+#endif /* LOG_IGET_TID_LEAVE */
+
+#ifndef LOG_LOC_CPU_ENTER
+#define LOG_LOC_CPU_ENTER()
+#endif /* LOG_LOC_CPU_ENTER */
+
+#ifndef LOG_LOC_CPU_LEAVE
+#define LOG_LOC_CPU_LEAVE(ercd)
+#endif /* LOG_LOC_CPU_LEAVE */
+
+#ifndef LOG_ILOC_CPU_ENTER
+#define LOG_ILOC_CPU_ENTER()
+#endif /* LOG_ILOC_CPU_ENTER */
+
+#ifndef LOG_ILOC_CPU_LEAVE
+#define LOG_ILOC_CPU_LEAVE(ercd)
+#endif /* LOG_ILOC_CPU_LEAVE */
+
+#ifndef LOG_UNL_CPU_ENTER
+#define LOG_UNL_CPU_ENTER()
+#endif /* LOG_UNL_CPU_ENTER */
+
+#ifndef LOG_UNL_CPU_LEAVE
+#define LOG_UNL_CPU_LEAVE(ercd)
+#endif /* LOG_UNL_CPU_LEAVE */
+
+#ifndef LOG_IUNL_CPU_ENTER
+#define LOG_IUNL_CPU_ENTER()
+#endif /* LOG_IUNL_CPU_ENTER */
+
+#ifndef LOG_IUNL_CPU_LEAVE
+#define LOG_IUNL_CPU_LEAVE(ercd)
+#endif /* LOG_IUNL_CPU_LEAVE */
+
+#ifndef LOG_DIS_DSP_ENTER
+#define LOG_DIS_DSP_ENTER()
+#endif /* LOG_DIS_DSP_ENTER */
+
+#ifndef LOG_DIS_DSP_LEAVE
+#define LOG_DIS_DSP_LEAVE(ercd)
+#endif /* LOG_DIS_DSP_LEAVE */
+
+#ifndef LOG_ENA_DSP_ENTER
+#define LOG_ENA_DSP_ENTER()
+#endif /* LOG_ENA_DSP_ENTER */
+
+#ifndef LOG_ENA_DSP_LEAVE
+#define LOG_ENA_DSP_LEAVE(ercd)
+#endif /* LOG_ENA_DSP_LEAVE */
+
+#ifndef LOG_SNS_CTX_ENTER
+#define LOG_SNS_CTX_ENTER()
+#endif /* LOG_SNS_CTX_ENTER */
+
+#ifndef LOG_SNS_CTX_LEAVE
+#define LOG_SNS_CTX_LEAVE(state)
+#endif /* LOG_SNS_CTX_LEAVE */
+
+#ifndef LOG_SNS_LOC_ENTER
+#define LOG_SNS_LOC_ENTER()
+#endif /* LOG_SNS_LOC_ENTER */
+
+#ifndef LOG_SNS_LOC_LEAVE
+#define LOG_SNS_LOC_LEAVE(state)
+#endif /* LOG_SNS_LOC_LEAVE */
+
+#ifndef LOG_SNS_DSP_ENTER
+#define LOG_SNS_DSP_ENTER()
+#endif /* LOG_SNS_DSP_ENTER */
+
+#ifndef LOG_SNS_DSP_LEAVE
+#define LOG_SNS_DSP_LEAVE(state)
+#endif /* LOG_SNS_DSP_LEAVE */
+
+#ifndef LOG_SNS_DPN_ENTER
+#define LOG_SNS_DPN_ENTER()
+#endif /* LOG_SNS_DPN_ENTER */
+
+#ifndef LOG_SNS_DPN_LEAVE
+#define LOG_SNS_DPN_LEAVE(state)
+#endif /* LOG_SNS_DPN_LEAVE */
+
+#ifndef LOG_SNS_KER_ENTER
+#define LOG_SNS_KER_ENTER()
+#endif /* LOG_SNS_KER_ENTER */
+
+#ifndef LOG_SNS_KER_LEAVE
+#define LOG_SNS_KER_LEAVE(state)
+#endif /* LOG_SNS_KER_LEAVE */
+
+/*
+ *  タスクの優先順位の回転
+ */
+#ifdef TOPPERS_rot_rdq
+
+ER
+rot_rdq(PRI tskpri)
+{
+	uint_t	pri;
+	ER		ercd;
+
+	LOG_ROT_RDQ_ENTER(tskpri);
+	CHECK_TSKCTX_UNL();
+	CHECK_TPRI_SELF(tskpri);
+
+	t_lock_cpu();
+	pri = (tskpri == TPRI_SELF) ? p_runtsk->bpriority : INT_PRIORITY(tskpri);
+	if (rotate_ready_queue(pri)) {
+		dispatch();
+	}
+	ercd = E_OK;
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_ROT_RDQ_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_rot_rdq */
+
+/*
+ *  タスクの優先順位の回転（非タスクコンテキスト用）
+ */
+#ifdef TOPPERS_irot_rdq
+
+ER
+irot_rdq(PRI tskpri)
+{
+	ER		ercd;
+
+	LOG_IROT_RDQ_ENTER(tskpri);
+	CHECK_INTCTX_UNL();
+	CHECK_TPRI(tskpri);
+
+	i_lock_cpu();
+	if (rotate_ready_queue(INT_PRIORITY(tskpri))) {
+		reqflg = true;
+	}
+	ercd = E_OK;
+	i_unlock_cpu();
+
+  error_exit:
+	LOG_IROT_RDQ_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_irot_rdq */
+
+/*
+ *  実行状態のタスクIDの参照
+ */
+#ifdef TOPPERS_get_tid
+
+ER
+get_tid(ID *p_tskid)
+{
+	ER		ercd;
+
+	LOG_GET_TID_ENTER(p_tskid);
+	CHECK_TSKCTX_UNL();
+
+	t_lock_cpu();
+	*p_tskid = TSKID(p_runtsk);
+	ercd = E_OK;
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_GET_TID_LEAVE(ercd, *p_tskid);
+	return(ercd);
+}
+
+#endif /* TOPPERS_get_tid */
+
+/*
+ *  実行状態のタスクIDの参照（非タスクコンテキスト用）
+ */
+#ifdef TOPPERS_iget_tid
+
+ER
+iget_tid(ID *p_tskid)
+{
+	ER		ercd;
+
+	LOG_IGET_TID_ENTER(p_tskid);
+	CHECK_INTCTX_UNL();
+
+	i_lock_cpu();
+	*p_tskid = (p_runtsk == NULL) ? TSK_NONE : TSKID(p_runtsk);
+	ercd = E_OK;
+	i_unlock_cpu();
+
+  error_exit:
+	LOG_IGET_TID_LEAVE(ercd, *p_tskid);
+	return(ercd);
+}
+
+#endif /* TOPPERS_iget_tid */
+
+/*
+ *  CPUロック状態への移行
+ */
+#ifdef TOPPERS_loc_cpu
+
+ER
+loc_cpu(void)
+{
+	ER		ercd;
+
+	LOG_LOC_CPU_ENTER();
+	CHECK_TSKCTX();
+
+	if (!t_sense_lock()) {
+		t_lock_cpu();
+	}
+	ercd = E_OK;
+
+  error_exit:
+	LOG_LOC_CPU_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_loc_cpu */
+
+/*
+ *  CPUロック状態への移行（非タスクコンテキスト用）
+ */
+#ifdef TOPPERS_iloc_cpu
+
+ER
+iloc_cpu(void)
+{
+	ER		ercd;
+
+	LOG_ILOC_CPU_ENTER();
+	CHECK_INTCTX();
+
+	if (!i_sense_lock()) {
+		i_lock_cpu();
+	}
+	ercd = E_OK;
+
+  error_exit:
+	LOG_ILOC_CPU_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_iloc_cpu */
+
+/*
+ *  CPUロック状態の解除
+ *
+ *  CPUロック中は，ディスパッチが必要となるサービスコールを呼び出すこ
+ *  とはできないため，CPUロック状態の解除時にディスパッチャを起動する
+ *  必要はない．
+ */
+#ifdef TOPPERS_unl_cpu
+
+ER
+unl_cpu(void)
+{
+	ER		ercd;
+
+	LOG_UNL_CPU_ENTER();
+	CHECK_TSKCTX();
+
+	if (t_sense_lock()) {
+		t_unlock_cpu();
+	}
+	ercd = E_OK;
+
+  error_exit:
+	LOG_UNL_CPU_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_unl_cpu */
+
+/*
+ *  CPUロック状態の解除（非タスクコンテキスト用）
+ *
+ *  CPUロック中は，ディスパッチが必要となるサービスコールを呼び出すこ
+ *  とはできないため，CPUロック状態の解除時にディスパッチャの起動を要
+ *  求する必要はない．
+ */
+#ifdef TOPPERS_iunl_cpu
+
+ER
+iunl_cpu(void)
+{
+	ER		ercd;
+
+	LOG_IUNL_CPU_ENTER();
+	CHECK_INTCTX();
+
+	if (i_sense_lock()) {
+		i_unlock_cpu();
+	}
+	ercd = E_OK;
+
+  error_exit:
+	LOG_IUNL_CPU_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_iunl_cpu */
+
+/*
+ *  ディスパッチの禁止
+ */
+#ifdef TOPPERS_dis_dsp
+
+ER
+dis_dsp(void)
+{
+	ER		ercd;
+
+	LOG_DIS_DSP_ENTER();
+	CHECK_TSKCTX_UNL();
+
+	t_lock_cpu();
+	disdsp = true;
+	dspflg = false;
+	ercd = E_OK;
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_DIS_DSP_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_dis_dsp */
+
+/*
+ *  ディスパッチの許可
+ */
+#ifdef TOPPERS_ena_dsp
+
+ER
+ena_dsp(void)
+{
+	ER		ercd;
+
+	LOG_ENA_DSP_ENTER();
+	CHECK_TSKCTX_UNL();
+
+	t_lock_cpu();
+	disdsp = false;
+	if (ipmflg) {
+		dspflg = true;
+		if (p_runtsk != p_schedtsk) {
+			dispatch();
+		}
+	}
+	ercd = E_OK;
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_ENA_DSP_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ena_dsp */
+
+/*
+ *  コンテキストの参照
+ */
+#ifdef TOPPERS_sns_ctx
+
+bool_t
+sns_ctx(void)
+{
+	bool_t	state;
+
+	LOG_SNS_CTX_ENTER();
+	state = sense_context() ? true : false;
+	LOG_SNS_CTX_LEAVE(state);
+	return(state);
+}
+
+#endif /* TOPPERS_sns_ctx */
+
+/*
+ *  CPUロック状態の参照
+ */
+#ifdef TOPPERS_sns_loc
+
+bool_t
+sns_loc(void)
+{
+	bool_t	state;
+
+	LOG_SNS_LOC_ENTER();
+	state = x_sense_lock() ? true : false;
+	LOG_SNS_LOC_LEAVE(state);
+	return(state);
+}
+
+#endif /* TOPPERS_sns_loc */
+
+/*
+ *  ディスパッチ禁止状態の参照
+ */
+#ifdef TOPPERS_sns_dsp
+
+bool_t
+sns_dsp(void)
+{
+	bool_t	state;
+
+	LOG_SNS_DSP_ENTER();
+	state = disdsp;
+	LOG_SNS_DSP_LEAVE(state);
+	return(state);
+}
+
+#endif /* TOPPERS_sns_dsp */
+
+/*
+ *  ディスパッチ保留状態の参照
+ */
+#ifdef TOPPERS_sns_dpn
+
+bool_t
+sns_dpn(void)
+{
+	bool_t	state;
+
+	LOG_SNS_DPN_ENTER();
+	state = (sense_context() || t_sense_lock() || !dspflg) ? true : false;
+	LOG_SNS_DPN_LEAVE(state);
+	return(state);
+}
+
+#endif /* TOPPERS_sns_dpn */
+
+/*
+ *  カーネル非動作状態の参照
+ */
+#ifdef TOPPERS_sns_ker
+
+bool_t
+sns_ker(void)
+{
+	bool_t	state;
+
+	LOG_SNS_KER_ENTER();
+	state = kerflg ? false : true;
+	LOG_SNS_KER_LEAVE(state);
+	return(state);
+}
+
+#endif /* TOPPERS_sns_ker */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/task.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/task.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/task.c	(revision 453)
@@ -0,0 +1,505 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		タスク管理モジュール
+ */
+
+#include "kernel_impl.h"
+#include "wait.h"
+#include "task.h"
+
+/*
+ *  トレースログマクロのデフォルト定義
+ */
+#ifndef LOG_TEX_ENTER
+#define LOG_TEX_ENTER(p_tcb, texptn)
+#endif /* LOG_TEX_ENTER */
+
+#ifndef LOG_TEX_LEAVE
+#define LOG_TEX_LEAVE(p_tcb)
+#endif /* LOG_TEX_LEAVE */
+
+#ifdef TOPPERS_tskini
+
+/*
+ *  実行状態のタスク
+ */
+TCB		*p_runtsk;
+
+/*
+ *  最高優先順位のタスク
+ */
+TCB		*p_schedtsk;
+
+/*
+ *  タスクディスパッチ／タスク例外処理ルーチン起動要求フラグ
+ */
+bool_t	reqflg;
+
+/*
+ *  割込み優先度マスク全解除状態
+ */
+bool_t	ipmflg;
+
+/*
+ *  ディスパッチ禁止状態
+ */
+bool_t	disdsp;
+
+/*
+ *  タスクディスパッチ可能状態
+ */
+bool_t	dspflg;
+
+/*
+ *  レディキュー
+ */
+QUEUE	ready_queue[TNUM_TPRI];
+
+/*
+ *  レディキューサーチのためのビットマップ
+ */
+uint16_t	ready_primap;
+
+/*
+ *  使用していないTCBのリスト
+ */
+QUEUE	free_tcb;
+
+/*
+ *  タスク管理モジュールの初期化
+ */
+void
+initialize_task(void)
+{
+	uint_t	i, j;
+	TCB		*p_tcb;
+	TINIB	*p_tinib;
+
+	p_runtsk = NULL;
+	p_schedtsk = NULL;
+	reqflg = false;
+	ipmflg = true;
+	disdsp = false;
+	dspflg = true;
+
+	for (i = 0; i < TNUM_TPRI; i++) {
+		queue_initialize(&(ready_queue[i]));
+	}
+	ready_primap = 0U;
+
+	for (i = 0; i < tnum_stsk; i++) {
+		j = INDEX_TSK(torder_table[i]);
+		p_tcb = &(tcb_table[j]);
+		p_tcb->p_tinib = &(tinib_table[j]);
+		p_tcb->actque = false;
+		make_dormant(p_tcb);
+		queue_initialize(&(p_tcb->mutex_queue));
+		if ((p_tcb->p_tinib->tskatr & TA_ACT) != 0U) {
+			(void) make_active(p_tcb);
+		}
+	}
+	queue_initialize(&free_tcb);
+	for (j = 0; i < tnum_tsk; i++, j++) {
+		p_tcb = &(tcb_table[i]);
+		p_tinib = &(atinib_table[j]);
+		p_tinib->tskatr = TA_NOEXS;
+		p_tcb->p_tinib = ((const TINIB *) p_tinib);
+		queue_insert_prev(&free_tcb, &(p_tcb->task_queue));
+	}
+}
+
+#endif /* TOPPERS_tskini */
+
+/*
+ *  ビットマップサーチ関数
+ *
+ *  bitmap内の1のビットの内，最も下位（右）のものをサーチし，そのビッ
+ *  ト番号を返す．ビット番号は，最下位ビットを0とする．bitmapに0を指定
+ *  してはならない．この関数では，bitmapが16ビットであることを仮定し，
+ *  uint16_t型としている．
+ *
+ *  ビットサーチ命令を持つプロセッサでは，ビットサーチ命令を使うように
+ *  書き直した方が効率が良い場合がある．このような場合には，ターゲット
+ *  依存部でビットサーチ命令を使ったbitmap_searchを定義し，
+ *  OMIT_BITMAP_SEARCHをマクロ定義すればよい．また，ビットサーチ命令の
+ *  サーチ方向が逆などの理由で優先度とビットとの対応を変更したい場合に
+ *  は，PRIMAP_BITをマクロ定義すればよい．
+ *
+ *  また，ライブラリにffsがあるなら，次のように定義してライブラリ関数を
+ *  使った方が効率が良い可能性もある．
+ *		#define	bitmap_search(bitmap) (ffs(bitmap) - 1)
+ */
+#ifndef PRIMAP_BIT
+#define	PRIMAP_BIT(pri)		(1U << (pri))
+#endif /* PRIMAP_BIT */
+
+#ifndef OMIT_BITMAP_SEARCH
+
+static const unsigned char bitmap_search_table[] = { 0, 1, 0, 2, 0, 1, 0,
+												3, 0, 1, 0, 2, 0, 1, 0 };
+
+Inline uint_t
+bitmap_search(uint16_t bitmap)
+{
+	uint_t	n = 0U;
+
+	assert(bitmap != 0U);
+	if ((bitmap & 0x00ffU) == 0U) {
+		bitmap >>= 8;
+		n += 8;
+	}
+	if ((bitmap & 0x0fU) == 0U) {
+		bitmap >>= 4;
+		n += 4;
+	}
+	return(n + bitmap_search_table[(bitmap & 0x0fU) - 1]);
+}
+
+#endif /* OMIT_BITMAP_SEARCH */
+
+/*
+ *  優先度ビットマップが空かのチェック
+ */
+Inline bool_t
+primap_empty(void)
+{
+	return(ready_primap == 0U);
+}
+
+/*
+ *  優先度ビットマップのサーチ
+ */
+Inline uint_t
+primap_search(void)
+{
+	return(bitmap_search(ready_primap));
+}
+
+/*
+ *  優先度ビットマップのセット
+ */
+Inline void
+primap_set(uint_t pri)
+{
+	ready_primap |= PRIMAP_BIT(pri);
+}
+
+/*
+ *  優先度ビットマップのクリア
+ */
+Inline void
+primap_clear(uint_t pri)
+{
+	ready_primap &= ~PRIMAP_BIT(pri);
+}
+
+/*
+ *  最高優先順位タスクのサーチ
+ */
+#ifdef TOPPERS_tsksched
+
+TCB *
+search_schedtsk(void)
+{
+	uint_t	schedpri;
+
+	schedpri = primap_search();
+	return((TCB *)(ready_queue[schedpri].p_next));
+}
+
+#endif /* TOPPERS_tsksched */
+
+/*
+ *  実行できる状態への遷移
+ *
+ *  最高優先順位のタスクを更新するのは，実行できるタスクがなかった場合
+ *  と，p_tcbの優先度が最高優先順位のタスクの優先度よりも高い場合であ
+ *  る．
+ */
+#ifdef TOPPERS_tskrun
+
+bool_t
+make_runnable(TCB *p_tcb)
+{
+	uint_t	pri = p_tcb->priority;
+
+	queue_insert_prev(&(ready_queue[pri]), &(p_tcb->task_queue));
+	primap_set(pri);
+
+	if (p_schedtsk == (TCB *) NULL || pri < p_schedtsk->priority) {
+		p_schedtsk = p_tcb;
+		return(dspflg);
+	}
+	return(false);
+}
+
+#endif /* TOPPERS_tskrun */
+
+/*
+ *  実行できる状態から他の状態への遷移
+ *
+ *  最高優先順位のタスクを更新するのは，p_tcbが最高優先順位のタスクで
+ *  あった場合である．p_tcbと同じ優先度のタスクが他にある場合は，p_tcb
+ *  の次のタスクが最高優先順位になる．そうでない場合は，レディキューを
+ *  サーチする必要がある．
+ */
+#ifdef TOPPERS_tsknrun
+
+bool_t
+make_non_runnable(TCB *p_tcb)
+{
+	uint_t	pri = p_tcb->priority;
+	QUEUE	*p_queue = &(ready_queue[pri]);
+
+	queue_delete(&(p_tcb->task_queue));
+	if (queue_empty(p_queue)) {
+		primap_clear(pri);
+		if (p_schedtsk == p_tcb) {
+			p_schedtsk = primap_empty() ? (TCB *) NULL : search_schedtsk();
+			return(dspflg);
+		}
+	}
+	else {
+		if (p_schedtsk == p_tcb) {
+			p_schedtsk = (TCB *)(p_queue->p_next);
+			return(dspflg);
+		}
+	}
+	return(false);
+}
+
+#endif /* TOPPERS_tsknrun */
+
+/*
+ *  休止状態への遷移
+ */
+#ifdef TOPPERS_tskdmt
+
+void
+make_dormant(TCB *p_tcb)
+{
+	p_tcb->tstat = TS_DORMANT;
+	p_tcb->bpriority = p_tcb->p_tinib->ipriority;
+	p_tcb->priority = p_tcb->p_tinib->ipriority;
+	p_tcb->wupque = false;
+	p_tcb->enatex = false;
+	p_tcb->texptn = 0U;
+	LOG_TSKSTAT(p_tcb);
+}
+
+#endif /* TOPPERS_tskdmt */
+
+/*
+ *  休止状態から実行できる状態への遷移
+ */
+#ifdef TOPPERS_tskact
+
+bool_t
+make_active(TCB *p_tcb)
+{
+	activate_context(p_tcb);
+	p_tcb->tstat = TS_RUNNABLE;
+	LOG_TSKSTAT(p_tcb);
+	return(make_runnable(p_tcb));
+}
+
+#endif /* TOPPERS_tskact */
+
+/*
+ *  タスクの優先度の変更
+ *
+ *  タスクが実行できる状態の場合には，レディキューの中での位置を変更す
+ *  る．オブジェクトの待ちキューの中で待ち状態になっている場合には，待
+ *  ちキューの中での位置を変更する．
+ *
+ *  最高優先順位のタスクを更新するのは，(1) p_tcbが最高優先順位のタス
+ *  クであって，その優先度を下げた場合，(2) p_tcbが最高優先順位のタス
+ *  クではなく，変更後の優先度が最高優先順位のタスクの優先度よりも高い
+ *  場合である．(1)の場合には，レディキューをサーチする必要がある．
+ */
+#ifdef TOPPERS_tskpri
+
+bool_t
+change_priority(TCB *p_tcb, uint_t newpri, bool_t mtxmode)
+{
+	uint_t	oldpri;
+
+	oldpri = p_tcb->priority;
+	p_tcb->priority = newpri;
+
+	if (TSTAT_RUNNABLE(p_tcb->tstat)) {
+		/*
+		 *  タスクが実行できる状態の場合
+		 */
+		queue_delete(&(p_tcb->task_queue));
+		if (queue_empty(&(ready_queue[oldpri]))) {
+			primap_clear(oldpri);
+		}
+		if (mtxmode) {
+			queue_insert_next(&(ready_queue[newpri]), &(p_tcb->task_queue));
+		}
+		else {
+			queue_insert_prev(&(ready_queue[newpri]), &(p_tcb->task_queue));
+		}
+		primap_set(newpri);
+
+		if (p_schedtsk == p_tcb) {
+			if (newpri >= oldpri) {
+				p_schedtsk = search_schedtsk();
+				return(p_schedtsk != p_tcb && dspflg);
+			}
+		}
+		else {
+			if (mtxmode ? newpri <= p_schedtsk->priority
+						: newpri < p_schedtsk->priority) {
+				p_schedtsk = p_tcb;
+				return(dspflg);
+			}
+		}
+	}
+	else {
+		if (TSTAT_WAIT_WOBJCB(p_tcb->tstat)) {
+			/*
+			 *  タスクが，同期・通信オブジェクトの管理ブロックの共通部
+			 *  分（WOBJCB）の待ちキューにつながれている場合
+			 */
+			wobj_change_priority(((WINFO_WOBJ *)(p_tcb->p_winfo))->p_wobjcb,
+																	p_tcb);
+		}
+	}
+	return(false);
+}
+
+#endif /* TOPPERS_tskpri */
+
+/*
+ *  レディキューの回転
+ *
+ *  最高優先順位のタスクを更新するのは，最高優先順位のタスクがタスクキ
+ *  ューの末尾に移動した場合である．
+ */
+#ifdef TOPPERS_tskrot
+
+bool_t
+rotate_ready_queue(uint_t pri)
+{
+	QUEUE	*p_queue = &(ready_queue[pri]);
+	QUEUE	*p_entry;
+
+	if (!queue_empty(p_queue) && p_queue->p_next->p_next != p_queue) {
+		p_entry = queue_delete_next(p_queue);
+		queue_insert_prev(p_queue, p_entry);
+		if (p_schedtsk == (TCB *) p_entry) {
+			p_schedtsk = (TCB *)(p_queue->p_next);
+			return(dspflg);
+		}
+	}
+	return(false);
+}
+
+#endif /* TOPPERS_tskrot */
+
+/*
+ *  タスク例外処理ルーチンの呼出し
+ *
+ *  ASPカーネルでは，タスク例外処理ルーチン内でCPUロック状態に遷移し，
+ *  元の状態に戻さずにリターンした場合，カーネルが元の状態に戻す．
+ */
+#ifdef TOPPERS_tsktex
+
+void
+call_texrtn(void)
+{
+	TEXPTN	texptn;
+	bool_t	saved_disdsp;
+
+	saved_disdsp = disdsp;
+	p_runtsk->enatex = false;
+	do {
+		texptn = p_runtsk->texptn;
+		p_runtsk->texptn = 0U;
+
+		t_unlock_cpu();
+		LOG_TEX_ENTER(p_runtsk, texptn);
+		(*((TEXRTN)(p_runtsk->p_tinib->texrtn)))(texptn,
+												p_runtsk->p_tinib->exinf);
+		LOG_TEX_LEAVE(p_runtsk);
+		if (!t_sense_lock()) {
+			t_lock_cpu();
+		}
+		if (!ipmflg) {
+			t_set_ipm(TIPM_ENAALL);
+			ipmflg = true;
+		}
+		disdsp = saved_disdsp;
+		dspflg = !disdsp;
+		p_runtsk->enatex = false;
+		if (p_runtsk != p_schedtsk && dspflg) {
+			/*
+			 *  ここでdispatchを呼び出す処理は，相互再帰呼出しになって
+			 *  いるが，dispatchを呼ぶ前にp_runtsk->enatexをfalseにして
+			 *  おけば支障がない．その理由については，「TOPPERS/ASP カー
+			 *  ネル 設計メモ」を参照のこと．
+			 */
+			dispatch();
+		}
+	} while (p_runtsk->texptn != 0U);
+	p_runtsk->enatex = true;
+}
+
+/*
+ *  タスク例外処理ルーチンの起動
+ */
+#ifndef OMIT_CALLTEX
+
+void
+calltex(void)
+{
+	if (p_runtsk->enatex && p_runtsk->texptn != 0U && ipmflg) {
+		call_texrtn();
+	}
+}
+
+#endif /* OMIT_CALLTEX */
+#endif /* TOPPERS_tsktex */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/task.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/task.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/task.h	(revision 453)
@@ -0,0 +1,498 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		タスク管理モジュール
+ */
+
+#ifndef TOPPERS_TASK_H
+#define TOPPERS_TASK_H
+
+#include <queue.h>
+#include "time_event.h"
+
+/*
+ *  トレースログマクロのデフォルト定義
+ */
+#ifndef LOG_TSKSTAT
+#define LOG_TSKSTAT(p_tcb)
+#endif /* LOG_TSKSTAT */
+
+/*
+ *  タスク優先度の内部表現・外部表現変換マクロ
+ */
+#define INT_PRIORITY(x)		((uint_t)((x) - TMIN_TPRI))
+#define EXT_TSKPRI(x)		((PRI)(x) + TMIN_TPRI)
+
+/*
+ *  タスク状態の内部表現
+ *
+ *  TCB中のタスク状態では，実行状態（RUNNING）と実行可能状態（READY）
+ *  は区別しない．両状態を総称して，実行できる状態（RUNNABLE）と呼ぶ．
+ *  二重待ち状態は，(TS_WAITING | TS_SUSPENDED)で表す．TS_WAIT_???は待
+ *  ち要因を表し，待ち状態（二重待ち状態を含む）の場合にのみ設定する．
+ */
+#define TS_DORMANT		0x00U			/* 休止状態 */
+#define TS_RUNNABLE		0x01U			/* 実行できる状態 */
+#define TS_WAITING		0x02U			/* 待ち状態 */
+#define TS_SUSPENDED	0x04U			/* 強制待ち状態 */
+
+#define TS_WAIT_DLY		(0x00U << 3)	/* 時間経過待ち */
+#define TS_WAIT_SLP		(0x01U << 3)	/* 起床待ち */
+#define TS_WAIT_RDTQ	(0x02U << 3)	/* データキューからの受信待ち */
+#define TS_WAIT_RPDQ	(0x03U << 3)	/* 優先度データキューからの受信待ち */
+#define TS_WAIT_SEM		(0x04U << 3)	/* セマフォ資源の獲得待ち */
+#define TS_WAIT_FLG		(0x05U << 3)	/* イベントフラグ待ち */
+#define TS_WAIT_SDTQ	(0x06U << 3)	/* データキューへの送信待ち */
+#define TS_WAIT_SPDQ	(0x07U << 3)	/* 優先度データキューへの送信待ち */
+#define TS_WAIT_MBX		(0x08U << 3)	/* メールボックスからの受信待ち */
+#define TS_WAIT_MPF		(0x09U << 3)	/* 固定長メモリブロックの獲得待ち */
+#define TS_WAIT_MTX		(0x0aU << 3)	/* ミューテックスのロック待ち */
+
+/*
+ *  タスク状態判別マクロ
+ *
+ *  TSTAT_DORMANTはタスクが休止状態であるかどうかを，TSTAT_RUNNABLEは
+ *  タスクが実行できる状態であるかどうかを判別する．TSTAT_WAITINGは待
+ *  ち状態と二重待ち状態のいずれかであるかどうかを，TSTAT_SUSPENDEDは
+ *  強制待ち状態と二重待ち状態のいずれかであるかどうかを判別する．
+ */
+#define TSTAT_DORMANT(tstat)	((tstat) == TS_DORMANT)
+#define TSTAT_RUNNABLE(tstat)	(((tstat) & TS_RUNNABLE) != 0U)
+#define TSTAT_WAITING(tstat)	(((tstat) & TS_WAITING) != 0U)
+#define TSTAT_SUSPENDED(tstat)	(((tstat) & TS_SUSPENDED) != 0U)
+
+/*
+ *  タスク待ち要因判別マクロ
+ *
+ *  TSTAT_WAIT_SLPはタスクが起床待ちであるかどうかを，TSTAT_WAIT_WOBJ
+ *  はタスクが同期・通信オブジェクトに対する待ちであるか（言い換えると，
+ *  同期通信オブジェクトの待ちキューにつながれているか）どうかを判別す
+ *  る．また，TSTAT_WAIT_WOBJCBはタスクが同期・通信オブジェクトの管理
+ *  ブロックの共通部分（WOBJCB）の待ちキューにつながれているかどうかを
+ *  判別する．
+ *
+ *  TSTAT_WAIT_SLPは，任意のタスク状態の中から，タスクが起床待ちである
+ *  ことを判別できる．すなわち，TSTAT_WAITINGにより待ち状態であることを
+ *  判別せずに，TSTAT_SLPだけを用いて起床待ち状態であることを判別できる．
+ *  これを効率的に実現するために，TS_WAIT_SLPの値を，(0x00U << 3)ではな
+ *  く(0x01U << 3)としている．そのため，タスクが時間経過待ち状態である
+ *  ことを判別するためのTSTAT_WAIT_DLYを，TSTAT_WAIT_SLPと同様の方法で
+ *  実現することはできない．
+ */
+#define TS_WAIT_MASK	(0x0fU << 3)	/* 待ち要因の取出しマスク */
+
+#define TSTAT_WAIT_SLP(tstat)		(((tstat) & TS_WAIT_MASK) == TS_WAIT_SLP)
+#define TSTAT_WAIT_WOBJ(tstat)		(((tstat) & TS_WAIT_MASK) >= TS_WAIT_RDTQ)
+#define TSTAT_WAIT_WOBJCB(tstat)	(((tstat) & TS_WAIT_MASK) >= TS_WAIT_SEM)
+#define TSTAT_WAIT_MTX(tstat)		(((tstat) & TS_WAIT_MASK) == TS_WAIT_MTX)
+
+/*
+ *  待ち情報ブロック（WINFO）の定義
+ *
+ *  タスクが待ち状態の間は，TCBおよびそのp_winfoで指されるWINFOを次の
+ *  ように設定しなければならない．
+ *
+ *  (a) TCBのタスク状態を待ち状態（TS_WAITING）にする．その際に，待ち
+ *  要因（TS_WAIT_???）も設定する．
+ *
+ *  (b) タイムアウトを監視するために，タイムイベントブロックを登録する．
+ *  登録するタイムイベントブロックは，待ちに入るサービスコール処理関数
+ *  のローカル変数として確保し，それへのポインタをWINFOのp_tmevtbに記
+ *  憶する．タイムアウトの監視が必要ない場合（永久待ちの場合）には，
+ *  p_tmevtbをNULLにする．
+ *
+ *  同期・通信オブジェクトに対する待ち状態の場合には，標準のWINFOに
+ *  p_wobjcbフィールドを追加した構造体（WINFO_WOBJ，wait.hで定義）を使
+ *  う．また，以下の(c)～(e)の設定を行う必要がある．同期・通信オブジェ
+ *  クトに関係しない待ち（起床待ち，時間経過待ち）の場合には，(c)～(e)
+ *  は必要ない．
+ *
+ *  (c) TCBを待ち対象の同期・通信オブジェクトの待ちキューにつなぐ．待
+ *  ちキューにつなぐために，task_queueを使う．
+ *
+ *  (d) 待ち対象の同期・通信オブジェクトの管理ブロックへのポインタを，
+ *  WINFO_WOBJのp_wobjcbに記憶する．
+ *
+ *  (e) 待ち対象の同期・通信オブジェクトに依存して記憶することが必要な
+ *  情報がある場合には，WINFO_WOBJに必要な情報のためのフィールドを追加
+ *  した構造体を定義し，WINFO_WOBJの代わりに用いる．
+ *
+ *  待ち状態を解除する際には，待ち解除したタスクに対する返値をWINFOの
+ *  wercdに設定する．wercdが必要なのは待ち解除以降であるのに対して，
+ *  p_tmevtbは待ち解除後は必要ないため，メモリ節約のために共用体を使っ
+ *  ている．そのため，wercdへエラーコードを設定するのは，タイムイベント
+ *  ブロックを登録解除した後にしなければならない．
+ */
+typedef union waiting_information {
+	ER		wercd;			/* 待ち解除時のエラーコード */
+	TMEVTB	*p_tmevtb;		/* 待ち状態用のタイムイベントブロック */
+} WINFO;
+
+/*
+ *  タスク初期化ブロック
+ *
+ *  タスクに関する情報を，値が変わらないためにROMに置ける部分（タスク
+ *  初期化ブロック）と，値が変化するためにRAMに置かなければならない部
+ *  分（タスク管理ブロック，TCB）に分離し，TCB内に対応するタスク初期化
+ *  ブロックを指すポインタを入れる．タスク初期化ブロック内に対応する
+ *  TCBを指すポインタを入れる方法の方が，RAMの節約の観点からは望ましい
+ *  が，実行効率が悪くなるために採用していない．他のオブジェクトについ
+ *  ても同様に扱う．
+ *
+ *  タスク初期化ブロックには，DEF_TEXで定義されるタスク例外処理ルーチ
+ *  ンに関する情報も含む．
+ */
+typedef struct task_initialization_block {
+	ATR			tskatr;			/* タスク属性 */
+	intptr_t	exinf;			/* タスクの拡張情報 */
+	TASK		task;			/* タスクの起動番地 */
+	uint_t		ipriority;		/* タスクの起動時優先度（内部表現） */
+
+#ifdef USE_TSKINICTXB
+	TSKINICTXB	tskinictxb;		/* タスク初期化コンテキストブロック */
+#else /* USE_TSKINICTXB */
+	SIZE		stksz;			/* スタック領域のサイズ（丸めた値） */
+	void		*stk;			/* スタック領域の先頭番地 */
+#endif /* USE_TSKINICTXB */
+
+	ATR			texatr;			/* タスク例外処理ルーチン属性 */
+	TEXRTN		texrtn;			/* タスク例外処理ルーチンの起動番地 */
+} TINIB;
+
+/*
+ *  TCB中のフィールドのビット幅の定義
+ *
+ *  プロセッサによっては，TCB中のフィールドのビット幅でメモリ使用量と
+ *  性能がトレードオフになるため，ターゲット依存にフィールドのビット幅
+ *  を変更することを許している．
+ */
+#ifndef TBIT_TCB_PRIORITY
+#define	TBIT_TCB_PRIORITY		8		/* priorityフィールドのビット幅 */
+#endif /* TBIT_TCB_PRIORITY */
+
+/*
+ *  タスク管理ブロック（TCB）
+ *
+ *  ASPカーネルでは，タスクの起動要求キューイング数の最大値（TMAX_ACTCNT）
+ *  と起床要求キューイング数の最大値（TMAX_WUPCNT）は1に固定されている
+ *  ため，キューイングされているかどうかの真偽値で表現することができる．
+ *  また，強制待ち要求ネスト数の最大値（TMAX_SUSCNT）が1に固定されてい
+ *  るので，強制待ち要求ネスト数（suscnt）は必要ない．
+ *
+ *  TCBのいくつかのフィールドは，特定のタスク状態でのみ有効な値を保持し，
+ *  それ以外の場合は値が保証されない（よって，参照してはならない）．各
+ *  フィールドが有効な値を保持する条件は次の通り．
+ *
+ *  ・初期化後は常に有効：
+ *  		p_tinib，tstat，actque
+ *  ・休止状態以外で有効（休止状態では初期値になっている）：
+ *  		bpriority，priority，wupque，enatex，texptn，mutex_queue
+ *  ・待ち状態（二重待ち状態を含む）で有効：
+ *  		p_winfo
+ *  ・実行できる状態と同期・通信オブジェクトに対する待ち状態で有効：
+ *  		task_queue
+ *  ・実行可能状態，待ち状態，強制待ち状態，二重待ち状態で有効：
+ *  		tskctxb
+ */
+typedef struct task_control_block {
+	QUEUE			task_queue;		/* タスクキュー */
+	const TINIB		*p_tinib;		/* 初期化ブロックへのポインタ */
+
+#ifdef UINT8_MAX
+	uint8_t			tstat;			/* タスク状態（内部表現）*/
+#else /* UINT8_MAX */
+	BIT_FIELD_UINT	tstat : 8;		/* タスク状態（内部表現）*/
+#endif /* UINT8_MAX */
+#if defined(UINT8_MAX) && (TBIT_TCB_PRIORITY == 8)
+	uint8_t			bpriority;		/* ベース優先度（内部表現）*/
+	uint8_t			priority;		/* 現在の優先度（内部表現）*/
+#else /* defined(UINT8_MAX) && (TBIT_TCB_PRIORITY == 8) */
+	BIT_FIELD_UINT	bpriority : TBIT_TCB_PRIORITY;
+									/* ベース優先度（内部表現）*/
+	BIT_FIELD_UINT	priority : TBIT_TCB_PRIORITY;
+									/* 現在の優先度（内部表現）*/
+#endif /* defined(UINT8_MAX) && (TBIT_TCB_PRIORITY == 8) */
+	BIT_FIELD_BOOL	actque : 1;		/* 起動要求キューイング */
+	BIT_FIELD_BOOL	wupque : 1;		/* 起床要求キューイング */
+	BIT_FIELD_BOOL	enatex : 1;		/* タスク例外処理許可状態 */
+
+	TEXPTN			texptn;			/* 保留例外要因 */
+	WINFO			*p_winfo;		/* 待ち情報ブロックへのポインタ */
+	QUEUE			mutex_queue;	/* ロックしているミューテックスのキュー */
+	TSKCTXB			tskctxb;		/* タスクコンテキストブロック */
+} TCB;
+
+/*
+ *  実行状態のタスク
+ *
+ *  実行状態のタスク（＝プロセッサがコンテキストを持っているタスク）の
+ *  TCBを指すポインタ．実行状態のタスクがない場合はNULLにする．
+ *
+ *  サービスコールの処理中で，自タスク（サービスコールを呼び出したタス
+ *  ク）に関する情報を参照する場合はp_runtskを使う．p_runtskを書き換え
+ *  るのは，ディスパッチャ（と初期化処理）のみである．
+ */
+extern TCB	*p_runtsk;
+
+/*
+ *  最高優先順位のタスク
+ *
+ *  実行できるタスクの中で最高優先順位のタスクのTCBを指すポインタ．実
+ *  行できるタスクがない場合はNULLにする．
+ *
+ *  ディスパッチ禁止状態など，ディスパッチが保留されている間はp_runtsk
+ *  と一致しているとは限らない．
+ */
+extern TCB	*p_schedtsk;
+
+/*
+ *  ディスパッチ／タスク例外処理ルーチン起動要求フラグ
+ *
+ *  割込みハンドラ／CPU例外ハンドラの出口処理に，ディスパッチまたは
+ *  タスク例外処理ルーチンの起動を要求することを示すフラグ．
+ */
+extern bool_t	reqflg;
+
+/*
+ *  割込み優先度マスク全解除状態
+ *
+ *  割込み優先度マスク全解除状態であることを示すフラグ．
+ */
+extern bool_t	ipmflg;
+
+/*
+ *  ディスパッチ禁止状態
+ *
+ *  ディスパッチ禁止状態であることを示すフラグ．
+ */
+extern bool_t	disdsp;
+
+/*
+ *  タスクディスパッチ可能状態
+ *
+ *  割込み優先度マスク全解除状態であり，ディスパッチ許可状態である（ディ
+ *  スパッチ禁止状態でない）ことを示すフラグ．
+ */
+extern bool_t	dspflg;
+
+/*
+ *  レディキュー
+ *
+ *  レディキューは，実行できる状態のタスクを管理するためのキューである．
+ *  実行状態のタスクも管理しているため，レディ（実行可能）キューという
+ *  名称は正確ではないが，レディキューという名称が定着しているため，こ
+ *  の名称で呼ぶことにする．
+ *
+ *  レディキューは，優先度ごとのタスクキューで構成されている．タスクの
+ *  TCBは，該当する優先度のキューに登録される．
+ */
+extern QUEUE	ready_queue[TNUM_TPRI];
+
+/*
+ *  レディキューサーチのためのビットマップ
+ *
+ *  レディキューのサーチを効率よく行うために，優先度ごとのタスクキュー
+ *  にタスクが入っているかどうかを示すビットマップを用意している．ビッ
+ *  トマップを使うことで，メモリアクセスの回数を減らすことができるが，
+ *  ビット操作命令が充実していないプロセッサで，優先度の段階数が少ない
+ *  場合には，ビットマップ操作のオーバーヘッドのために，逆に効率が落ち
+ *  る可能性もある．
+ *
+ *  優先度が16段階であることを仮定しているため，uint16_t型としている．
+ */
+extern uint16_t	ready_primap;
+
+/*
+ *  使用していないTCBのリスト
+ */
+extern QUEUE	free_tcb;
+
+/*
+ *  タスクIDの最大値（kernel_cfg.c）
+ */
+extern const ID	tmax_tskid;
+extern const ID	tmax_stskid;
+
+/*
+ *  タスク初期化ブロックのエリア（kernel_cfg.c）
+ */
+extern const TINIB	tinib_table[];
+extern TINIB		atinib_table[];
+
+/*
+ *  タスク生成順序テーブル（kernel_cfg.c）
+ */
+extern const ID	torder_table[];
+
+/*
+ *  TCBのエリア（kernel_cfg.c）
+ */
+extern TCB	tcb_table[];
+
+/*
+ *  タスクの数
+ */
+#define tnum_tsk	((uint_t)(tmax_tskid - TMIN_TSKID + 1))
+#define tnum_stsk	((uint_t)(tmax_stskid - TMIN_TSKID + 1))
+
+/*
+ *  タスクIDからTCBを取り出すためのマクロ
+ */
+#define INDEX_TSK(tskid)	((uint_t)((tskid) - TMIN_TSKID))
+#define get_tcb(tskid)		(&(tcb_table[INDEX_TSK(tskid)]))
+#define get_tcb_self(tskid)	((tskid) == TSK_SELF ? p_runtsk : get_tcb(tskid))
+
+/*
+ *  TCBからタスクIDを取り出すためのマクロ
+ */
+#define	TSKID(p_tcb)	((ID)(((p_tcb) - tcb_table) + TMIN_TSKID))
+
+/*
+ *  タスク管理モジュールの初期化
+ */
+extern void	initialize_task(void);
+
+/*
+ *  最高優先順位タスクのサーチ
+ *
+ *  レディキュー中の最高優先順位のタスクをサーチし，そのTCBへのポインタ
+ *  を返す．レディキューが空の場合には，この関数を呼び出してはならない．
+ */
+extern TCB	*search_schedtsk(void);
+
+/*
+ *  実行できる状態への遷移
+ *
+ *  p_tcbで指定されるタスクをレディキューに挿入する．レディキューに挿入
+ *  したタスクの優先度が，最高優先順位のタスクの優先度よりも高い場合は，
+ *  最高優先順位のタスクを更新し，ディスパッチ許可状態であればtrueを返
+ *  す．そうでない場合はfalseを返す．
+ */
+extern bool_t	make_runnable(TCB *p_tcb);
+
+/*
+ *  実行できる状態から他の状態への遷移
+ *
+ *  p_tcbで指定されるタスクをレディキューから削除する．p_tcbで指定した
+ *  タスクが最高優先順位のタスクであった場合には，最高優先順位のタスク
+ *  を設定しなおし，ディスパッチ許可状態であればtrueを返す．そうでない
+ *  場合はfalseを返す．タスクの状態は更新しない．
+ */
+extern bool_t	make_non_runnable(TCB *p_tcb);
+
+/*
+ *  休止状態への遷移
+ *
+ *  p_tcbで指定されるタスクの状態を休止状態とする．また，タスクの起動
+ *  時に初期化すべき変数の初期化と，タスク起動のためのコンテキストを設
+ *  定する．
+ */
+extern void	make_dormant(TCB *p_tcb);
+
+/*
+ *  休止状態から実行できる状態への遷移
+ *
+ *  p_tcbで指定されるタスクの状態を休止状態から実行できる状態とする．
+ *  実行できる状態に遷移したタスクへのディスパッチが必要な場合はtrue，
+ *  そうでない場合はfalseを返す．
+ */
+extern bool_t	make_active(TCB *p_tcb);
+
+/*
+ *  タスクの優先度の変更
+ *
+ *  p_tcbで指定されるタスクの優先度をnewpri（内部表現）に変更する．また，
+ *  必要な場合には最高優先順位のタスクを更新し，ディスパッチ許可状態で
+ *  あればtrueを返す．そうでない場合はfalseを返す．
+ *
+ *  p_tcbで指定されるタスクの優先順位は，mtxmodeがfalseの時は同じ優先度
+ *  のタスクの中で最低，mtxmodeがtrueの時は同じ優先度のタスクの中で最高
+ *  とする．
+ */
+extern bool_t	change_priority(TCB *p_tcb, uint_t newpri, bool_t mtxmode);
+
+/*
+ *  レディキューの回転
+ *
+ *  レディキュー中の，priで指定される優先度のタスクキューを回転させる．
+ *  また，必要な場合には最高優先順位のタスクを変更し，ディスパッチが保
+ *  留されていなければtrueを返す．そうでない場合はfalseを返す．
+ */
+extern bool_t	rotate_ready_queue(uint_t pri);
+
+/*
+ *  タスク例外処理ルーチンの呼出し
+ *
+ *  タスク例外処理ルーチンを呼び出す．呼び出す前に，実行状態のタスクの
+ *  保留例外要因をクリアし，タスク例外処理禁止状態にし，CPUロックを解
+ *  除する．
+ *
+ *  タスク例外処理ルーチンから戻ると，まずCPUロック状態に戻し，その間
+ *  に保留例外要因が0でなくなっていれば，再びタスク例外処理ルーチンを
+ *  呼び出す．保留例外要因が0の場合には，例外処理許可状態にして関数か
+ *  らリターンする．
+ *
+ *  この関数は，実行状態のタスクが，タスク例外処理許可状態（enatexが
+ *  true）で，保留例外要因が0でない（texptnが0でない）場合に呼び出すこ
+ *  とを想定している．この関数は，CPUロック状態で呼び出さなければなら
+ *  ない．
+ */
+extern void	call_texrtn(void);
+
+/*
+ *  タスク例外処理ルーチンの起動
+ *
+ *  実行状態のタスクがタスク例外処理ルーチンの起動条件を満たしていれば，
+ *  タスク例外処理ルーチンを呼び出す．CPU例外処理ルーチンを呼び出す時
+ *  は，一時的にCPUロックを解除する．
+ *
+ *  この関数は，ディスパッチャや割込みハンドラ／CPU例外ハンドラの出口
+ *  処理から呼び出されることを想定している．この関数は，CPUロック状態
+ *  で呼び出さなければならない．
+ *
+ *  実行効率を上げるために，この関数をターゲット依存部で記述してもよい．
+ *  その場合には，OMIT_CALLTEXをマクロ定義する．
+ */
+extern void	calltex(void);
+
+#endif /* TOPPERS_TASK_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/task_except.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/task_except.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/task_except.c	(revision 453)
@@ -0,0 +1,368 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2014 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		タスク例外処理機能
+ */
+
+#include "kernel_impl.h"
+#include "check.h"
+#include "task.h"
+
+/*
+ *  トレースログマクロのデフォルト定義
+ */
+#ifndef LOG_DEF_TEX_ENTER
+#define LOG_DEF_TEX_ENTER(tskid, pk_dtex)
+#endif /* LOG_DEF_TEX_ENTER */
+
+#ifndef LOG_DEF_TEX_LEAVE
+#define LOG_DEF_TEX_LEAVE(ercd)
+#endif /* LOG_DEF_TEX_LEAVE */
+
+#ifndef LOG_RAS_TEX_ENTER
+#define LOG_RAS_TEX_ENTER(tskid, rasptn)
+#endif /* LOG_RAS_TEX_ENTER */
+
+#ifndef LOG_RAS_TEX_LEAVE
+#define LOG_RAS_TEX_LEAVE(ercd)
+#endif /* LOG_RAS_TEX_LEAVE */
+
+#ifndef LOG_IRAS_TEX_ENTER
+#define LOG_IRAS_TEX_ENTER(tskid, rasptn)
+#endif /* LOG_IRAS_TEX_ENTER */
+
+#ifndef LOG_IRAS_TEX_LEAVE
+#define LOG_IRAS_TEX_LEAVE(ercd)
+#endif /* LOG_IRAS_TEX_LEAVE */
+
+#ifndef LOG_DIS_TEX_ENTER
+#define LOG_DIS_TEX_ENTER()
+#endif /* LOG_DIS_TEX_ENTER */
+
+#ifndef LOG_DIS_TEX_LEAVE
+#define LOG_DIS_TEX_LEAVE(ercd)
+#endif /* LOG_DIS_TEX_LEAVE */
+
+#ifndef LOG_ENA_TEX_ENTER
+#define LOG_ENA_TEX_ENTER()
+#endif /* LOG_ENA_TEX_ENTER */
+
+#ifndef LOG_ENA_TEX_LEAVE
+#define LOG_ENA_TEX_LEAVE(ercd)
+#endif /* LOG_ENA_TEX_LEAVE */
+
+#ifndef LOG_SNS_TEX_ENTER
+#define LOG_SNS_TEX_ENTER()
+#endif /* LOG_SNS_TEX_ENTER */
+
+#ifndef LOG_SNS_TEX_LEAVE
+#define LOG_SNS_TEX_LEAVE(state)
+#endif /* LOG_SNS_TEX_LEAVE */
+
+#ifndef LOG_REF_TEX_ENTER
+#define LOG_REF_TEX_ENTER(tskid, pk_rtex)
+#endif /* LOG_REF_TEX_ENTER */
+
+#ifndef LOG_REF_TEX_LEAVE
+#define LOG_REF_TEX_LEAVE(ercd, pk_rtex)
+#endif /* LOG_REF_TEX_LEAVE */
+
+/*
+ *  タスク例外処理ルーチンの定義
+ */
+#ifdef TOPPERS_def_tex
+
+ER_UINT
+def_tex(ID tskid, const T_DTEX *pk_dtex)
+{
+	TCB		*p_tcb;
+	TINIB	*p_tinib;
+	ER		ercd;
+
+	LOG_DEF_TEX_ENTER(tskid, pk_dtex);
+	CHECK_TSKCTX_UNL();
+	CHECK_TSKID_SELF(tskid);
+	CHECK_RSATR(pk_dtex->texatr, TA_NULL);
+	if (pk_dtex->texrtn != NULL) {
+		CHECK_ALIGN_FUNC(pk_dtex->texrtn);
+		CHECK_NONNULL_FUNC(pk_dtex->texrtn);
+	}
+	p_tcb = get_tcb_self(tskid);
+	p_tinib = (TINIB *)(p_tcb->p_tinib);
+
+	t_lock_cpu();
+	if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (TSKID(p_tcb) > tmax_stskid) {
+		if (pk_dtex->texrtn != NULL) {
+			if (p_tinib->texrtn != NULL) {
+				ercd = E_OBJ;
+			}
+			else {
+				p_tinib->texatr = pk_dtex->texatr;
+				p_tinib->texrtn = pk_dtex->texrtn;
+				ercd = E_OK;
+			}
+		}
+		else {
+			if (p_tinib->texrtn != NULL) {
+				p_tinib->texrtn = NULL;
+				p_tcb->enatex = false;
+				p_tcb->texptn = 0U;
+				ercd = E_OK;
+			}
+			else {
+				ercd = E_OBJ;
+			}
+		}
+	}
+	else {
+		ercd = E_OBJ;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_DEF_TEX_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_def_tex */
+
+/*
+ *  タスク例外処理の要求
+ */
+#ifdef TOPPERS_ras_tex
+
+ER
+ras_tex(ID tskid, TEXPTN rasptn)
+{
+	TCB		*p_tcb;
+	ER		ercd;
+
+	LOG_RAS_TEX_ENTER(tskid, rasptn);
+	CHECK_TSKCTX_UNL();
+	CHECK_TSKID_SELF(tskid);
+	CHECK_PAR(rasptn != 0U);
+	p_tcb = get_tcb_self(tskid);
+
+	t_lock_cpu();
+	if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (TSTAT_DORMANT(p_tcb->tstat) || p_tcb->p_tinib->texrtn == NULL) {
+		ercd = E_OBJ;
+	}
+	else {
+		p_tcb->texptn |= rasptn;
+		if (p_tcb == p_runtsk && p_runtsk->enatex && ipmflg) {
+			call_texrtn();
+		}
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_RAS_TEX_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ras_tex */
+
+/*
+ *  タスク例外処理の要求（非タスクコンテキスト用）
+ */
+#ifdef TOPPERS_iras_tex
+
+ER
+iras_tex(ID tskid, TEXPTN rasptn)
+{
+	TCB		*p_tcb;
+	ER		ercd;
+
+	LOG_IRAS_TEX_ENTER(tskid, rasptn);
+	CHECK_INTCTX_UNL();
+	CHECK_TSKID(tskid);
+	CHECK_PAR(rasptn != 0U);
+	p_tcb = get_tcb(tskid);
+
+	i_lock_cpu();
+	if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (TSTAT_DORMANT(p_tcb->tstat) || p_tcb->p_tinib->texrtn == NULL) {
+		ercd = E_OBJ;
+	}
+	else {
+		p_tcb->texptn |= rasptn;
+		if (p_tcb == p_runtsk && p_runtsk->enatex && ipmflg) {
+			reqflg = true;
+		}
+		ercd = E_OK;
+	}
+	i_unlock_cpu();
+
+  error_exit:
+	LOG_IRAS_TEX_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_iras_tex */
+
+/*
+ *  タスク例外処理の禁止
+ */
+#ifdef TOPPERS_dis_tex
+
+ER
+dis_tex(void)
+{
+	ER		ercd;
+
+	LOG_DIS_TEX_ENTER();
+	CHECK_TSKCTX_UNL();
+
+	t_lock_cpu();
+	if (p_runtsk->p_tinib->texrtn == NULL) {
+		ercd = E_OBJ;
+	}
+	else {
+		p_runtsk->enatex = false;
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_DIS_TEX_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_dis_tex */
+
+/*
+ *  タスク例外処理の許可
+ */
+#ifdef TOPPERS_ena_tex
+
+ER
+ena_tex(void)
+{
+	ER		ercd;
+
+	LOG_ENA_TEX_ENTER();
+	CHECK_TSKCTX_UNL();
+
+	t_lock_cpu();
+	if (p_runtsk->p_tinib->texrtn == NULL) {
+		ercd = E_OBJ;
+	}
+	else {
+		p_runtsk->enatex = true;
+		if (p_runtsk->texptn != 0U && ipmflg) {
+			call_texrtn();
+		}
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_ENA_TEX_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ena_tex */
+
+/*
+ *  タスク例外処理禁止状態の参照
+ */
+#ifdef TOPPERS_sns_tex
+
+bool_t
+sns_tex(void)
+{
+	bool_t	state;
+
+	LOG_SNS_TEX_ENTER();
+	state = (p_runtsk != NULL && p_runtsk->enatex) ? false : true;
+	LOG_SNS_TEX_LEAVE(state);
+	return(state);
+}
+
+#endif /* TOPPERS_sns_tex */
+
+/*
+ *  タスク例外処理の状態参照
+ */
+#ifdef TOPPERS_ref_tex
+
+ER
+ref_tex(ID tskid, T_RTEX *pk_rtex)
+{
+	TCB		*p_tcb;
+	ER		ercd;
+
+	LOG_REF_TEX_ENTER(tskid, pk_rtex);
+	CHECK_TSKCTX_UNL();
+	CHECK_TSKID_SELF(tskid);
+	p_tcb = get_tcb_self(tskid);
+
+	t_lock_cpu();
+	if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (TSTAT_DORMANT(p_tcb->tstat) || p_tcb->p_tinib->texrtn == NULL) {
+		ercd = E_OBJ;
+	}
+	else {
+		pk_rtex->texstat = (p_tcb->enatex) ? TTEX_ENA : TTEX_DIS;
+		pk_rtex->pndptn = p_tcb->texptn;
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_REF_TEX_LEAVE(ercd, pk_rtex);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ref_tex */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/task_manage.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/task_manage.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/task_manage.c	(revision 453)
@@ -0,0 +1,615 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2017 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		タスク管理機能
+ */
+
+#include "kernel_impl.h"
+#include "check.h"
+#include "task.h"
+#include "wait.h"
+#include "mutex.h"
+
+/*
+ *  トレースログマクロのデフォルト定義
+ */
+#ifndef LOG_ACRE_TSK_ENTER
+#define LOG_ACRE_TSK_ENTER(pk_ctsk)
+#endif /* LOG_ACRE_TSK_ENTER */
+
+#ifndef LOG_ACRE_TSK_LEAVE
+#define LOG_ACRE_TSK_LEAVE(ercd)
+#endif /* LOG_ACRE_TSK_LEAVE */
+
+#ifndef LOG_DEL_TSK_ENTER
+#define LOG_DEL_TSK_ENTER(tskid)
+#endif /* LOG_DEL_TSK_ENTER */
+
+#ifndef LOG_DEL_TSK_LEAVE
+#define LOG_DEL_TSK_LEAVE(ercd)
+#endif /* LOG_DEL_TSK_LEAVE */
+
+#ifndef LOG_ACT_TSK_ENTER
+#define LOG_ACT_TSK_ENTER(tskid)
+#endif /* LOG_ACT_TSK_ENTER */
+
+#ifndef LOG_ACT_TSK_LEAVE
+#define LOG_ACT_TSK_LEAVE(ercd)
+#endif /* LOG_ACT_TSK_LEAVE */
+
+#ifndef LOG_IACT_TSK_ENTER
+#define LOG_IACT_TSK_ENTER(tskid)
+#endif /* LOG_IACT_TSK_ENTER */
+
+#ifndef LOG_IACT_TSK_LEAVE
+#define LOG_IACT_TSK_LEAVE(ercd)
+#endif /* LOG_IACT_TSK_LEAVE */
+
+#ifndef LOG_CAN_ACT_ENTER
+#define LOG_CAN_ACT_ENTER(tskid)
+#endif /* LOG_CAN_ACT_ENTER */
+
+#ifndef LOG_CAN_ACT_LEAVE
+#define LOG_CAN_ACT_LEAVE(ercd)
+#endif /* LOG_CAN_ACT_LEAVE */
+
+#ifndef LOG_EXT_TSK_ENTER
+#define LOG_EXT_TSK_ENTER()
+#endif /* LOG_EXT_TSK_ENTER */
+
+#ifndef LOG_EXT_TSK_LEAVE
+#define LOG_EXT_TSK_LEAVE(ercd)
+#endif /* LOG_EXT_TSK_LEAVE */
+
+#ifndef LOG_TER_TSK_ENTER
+#define LOG_TER_TSK_ENTER(tskid)
+#endif /* LOG_TER_TSK_ENTER */
+
+#ifndef LOG_TER_TSK_LEAVE
+#define LOG_TER_TSK_LEAVE(ercd)
+#endif /* LOG_TER_TSK_LEAVE */
+
+#ifndef LOG_CHG_PRI_ENTER
+#define LOG_CHG_PRI_ENTER(tskid, tskpri)
+#endif /* LOG_CHG_PRI_ENTER */
+
+#ifndef LOG_CHG_PRI_LEAVE
+#define LOG_CHG_PRI_LEAVE(ercd)
+#endif /* LOG_CHG_PRI_LEAVE */
+
+#ifndef LOG_GET_PRI_ENTER
+#define LOG_GET_PRI_ENTER(tskid, p_tskpri)
+#endif /* LOG_GET_PRI_ENTER */
+
+#ifndef LOG_GET_PRI_LEAVE
+#define LOG_GET_PRI_LEAVE(ercd, tskpri)
+#endif /* LOG_GET_PRI_LEAVE */
+
+#ifndef LOG_GET_INF_ENTER
+#define LOG_GET_INF_ENTER(p_exinf)
+#endif /* LOG_GET_INF_ENTER */
+
+#ifndef LOG_GET_INF_LEAVE
+#define LOG_GET_INF_LEAVE(ercd, exinf)
+#endif /* LOG_GET_INF_LEAVE */
+
+/*
+ *  タスクの生成
+ */
+#ifdef TOPPERS_acre_tsk
+
+#ifndef TARGET_MIN_STKSZ
+#define TARGET_MIN_STKSZ	1U		/* 未定義の場合は0でないことをチェック */
+#endif /* TARGET_MIN_STKSZ */
+
+ER_UINT
+acre_tsk(const T_CTSK *pk_ctsk)
+{
+	TCB		*p_tcb;
+	TINIB	*p_tinib;
+	ATR		tskatr;
+	SIZE	stksz;
+	void	*stk;
+	ER		ercd;
+
+	LOG_ACRE_TSK_ENTER(pk_ctsk);
+	CHECK_TSKCTX_UNL();
+	CHECK_RSATR(pk_ctsk->tskatr, TA_ACT|TARGET_TSKATR);
+	CHECK_ALIGN_FUNC(pk_ctsk->task);
+	CHECK_NONNULL_FUNC(pk_ctsk->task);
+	CHECK_TPRI(pk_ctsk->itskpri);
+	CHECK_PAR(pk_ctsk->stksz >= TARGET_MIN_STKSZ);
+	if (pk_ctsk->stk != NULL) {
+		CHECK_ALIGN_STKSZ(pk_ctsk->stksz);
+		CHECK_ALIGN_STACK(pk_ctsk->stk);
+	}
+	tskatr = pk_ctsk->tskatr;
+	stksz = pk_ctsk->stksz;
+	stk = pk_ctsk->stk;
+
+	t_lock_cpu();
+	if (queue_empty(&free_tcb)) {
+		ercd = E_NOID;
+	}
+	else {
+		if (stk == NULL) {
+			stksz = ROUND_STK_T(stksz);
+			stk = kernel_malloc(stksz);
+			tskatr |= TA_MEMALLOC;
+		}
+		if (stk == NULL) {
+			ercd = E_NOMEM;
+		}
+		else {
+			p_tcb = ((TCB *) queue_delete_next(&free_tcb));
+			p_tinib = (TINIB *)(p_tcb->p_tinib);
+			p_tinib->tskatr = tskatr;
+			p_tinib->exinf = pk_ctsk->exinf;
+			p_tinib->task = pk_ctsk->task;
+			p_tinib->ipriority = INT_PRIORITY(pk_ctsk->itskpri);
+#ifdef USE_TSKINICTXB
+			init_tskinictxb(&(p_tinib->tskinictxb), stk, pk_ctsk);
+#else /* USE_TSKINICTXB */
+			p_tinib->stksz = stksz;
+			p_tinib->stk = stk;
+#endif /* USE_TSKINICTXB */
+			p_tinib->texatr = TA_NULL;
+			p_tinib->texrtn = NULL;
+
+			p_tcb->actque = false;
+			make_dormant(p_tcb);
+			if ((p_tcb->p_tinib->tskatr & TA_ACT) != 0U) {
+				if (make_active(p_tcb)) {
+					dispatch();
+				}
+			}
+			ercd = TSKID(p_tcb);
+		}
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_ACRE_TSK_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_acre_tsk */
+
+/*
+ *  タスクの削除
+ */
+#ifdef TOPPERS_del_tsk
+
+ER
+del_tsk(ID tskid)
+{
+	TCB		*p_tcb;
+	TINIB	*p_tinib;
+	ER		ercd;
+
+	LOG_DEL_TSK_ENTER(tskid);
+	CHECK_TSKCTX_UNL();
+	CHECK_TSKID(tskid);
+	p_tcb = get_tcb(tskid);
+
+	t_lock_cpu();
+	if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (TSKID(p_tcb) > tmax_stskid && TSTAT_DORMANT(p_tcb->tstat)) {
+		p_tinib = (TINIB *)(p_tcb->p_tinib);
+#ifdef USE_TSKINICTXB
+		term_tskinictxb(&(p_tinib->tskinictxb));
+#else /* USE_TSKINICTXB */
+		if ((p_tinib->tskatr & TA_MEMALLOC) != 0U) {
+			kernel_free(p_tinib->stk);
+		}
+#endif /* USE_TSKINICTXB */
+		p_tinib->tskatr = TA_NOEXS;
+		queue_insert_prev(&free_tcb, &(p_tcb->task_queue));
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_OBJ;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_DEL_TSK_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_del_tsk */
+
+/*
+ *  タスクの起動
+ */
+#ifdef TOPPERS_act_tsk
+
+ER
+act_tsk(ID tskid)
+{
+	TCB		*p_tcb;
+	ER		ercd;
+
+	LOG_ACT_TSK_ENTER(tskid);
+	CHECK_TSKCTX_UNL();
+	CHECK_TSKID_SELF(tskid);
+	p_tcb = get_tcb_self(tskid);
+
+	t_lock_cpu();
+	if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (TSTAT_DORMANT(p_tcb->tstat)) {
+		if (make_active(p_tcb)) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	else if (!(p_tcb->actque)) {
+		p_tcb->actque = true;
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_QOVR;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_ACT_TSK_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_act_tsk */
+
+/*
+ *  タスクの起動（非タスクコンテキスト用）
+ */
+#ifdef TOPPERS_iact_tsk
+
+ER
+iact_tsk(ID tskid)
+{
+	TCB		*p_tcb;
+	ER		ercd;
+
+	LOG_IACT_TSK_ENTER(tskid);
+	CHECK_INTCTX_UNL();
+	CHECK_TSKID(tskid);
+	p_tcb = get_tcb(tskid);
+
+	i_lock_cpu();
+	if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (TSTAT_DORMANT(p_tcb->tstat)) {
+		if (make_active(p_tcb)) {
+			reqflg = true;
+		}
+		ercd = E_OK;
+	}
+	else if (!(p_tcb->actque)) {
+		p_tcb->actque = true;
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_QOVR;
+	}
+	i_unlock_cpu();
+
+  error_exit:
+	LOG_IACT_TSK_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_iact_tsk */
+
+/*
+ *  タスク起動要求のキャンセル
+ */
+#ifdef TOPPERS_can_act
+
+ER_UINT
+can_act(ID tskid)
+{
+	TCB		*p_tcb;
+	ER_UINT	ercd;
+
+	LOG_CAN_ACT_ENTER(tskid);
+	CHECK_TSKCTX_UNL();
+	CHECK_TSKID_SELF(tskid);
+	p_tcb = get_tcb_self(tskid);
+
+	t_lock_cpu();
+	if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		ercd = p_tcb->actque ? 1 : 0;
+		p_tcb->actque = false;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_CAN_ACT_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_can_act */
+
+/*
+ *  自タスクの終了
+ */
+#ifdef TOPPERS_ext_tsk
+
+ER
+ext_tsk(void)
+{
+	ER		ercd;
+
+	LOG_EXT_TSK_ENTER();
+	CHECK_TSKCTX();
+
+	if (t_sense_lock()) {
+		/*
+		 *  CPUロック状態でext_tskが呼ばれた場合は，CPUロックを解除し
+		 *  てからタスクを終了する．実装上は，サービスコール内でのCPU
+		 *  ロックを省略すればよいだけ．
+		 */
+	}
+	else {
+		t_lock_cpu();
+	}
+	if (disdsp) {
+		/*
+		 *  ディスパッチ禁止状態でext_tskが呼ばれた場合は，ディスパッ
+		 *  チ許可状態にしてからタスクを終了する．
+		 */
+		disdsp = false;
+	}
+	if (!ipmflg) {
+		/*
+		 *  割込み優先度マスク（IPM）がTIPM_ENAALL以外の状態でext_tsk
+		 *  が呼ばれた場合は，IPMをTIPM_ENAALLにしてからタスクを終了す
+		 *  る．
+		 */
+		t_set_ipm(TIPM_ENAALL);
+		ipmflg = true;
+	}
+	dspflg = true;
+
+	(void) make_non_runnable(p_runtsk);
+	if (!queue_empty(&(p_runtsk->mutex_queue))) {
+		(void) (*mtxhook_release_all)(p_runtsk);
+	}
+	make_dormant(p_runtsk);
+	if (p_runtsk->actque) {
+		p_runtsk->actque = false;
+		(void) make_active(p_runtsk);
+	}
+	exit_and_dispatch();
+	ercd = E_SYS;
+
+  error_exit:
+	LOG_EXT_TSK_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ext_tsk */
+
+/*
+ *  タスクの強制終了
+ */
+#ifdef TOPPERS_ter_tsk
+
+ER
+ter_tsk(ID tskid)
+{
+	TCB		*p_tcb;
+	bool_t	dspreq = false;
+	ER		ercd;
+
+	LOG_TER_TSK_ENTER(tskid);
+	CHECK_TSKCTX_UNL();
+	CHECK_TSKID(tskid);
+	p_tcb = get_tcb(tskid);
+	CHECK_NONSELF(p_tcb);
+
+	t_lock_cpu();
+	if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (TSTAT_DORMANT(p_tcb->tstat)) {
+		ercd = E_OBJ;
+	}
+	else {
+		if (TSTAT_RUNNABLE(p_tcb->tstat)) {
+			/*
+			 *  p_tcbは自タスクでないため，（シングルプロセッサでは）実
+			 *  行状態でなく，make_non_runnable(p_tcb)でタスクディスパッ
+			 *  チが必要になることはない．
+			 */
+			(void) make_non_runnable(p_tcb);
+		}
+		else if (TSTAT_WAITING(p_tcb->tstat)) {
+			wait_dequeue_wobj(p_tcb);
+			wait_dequeue_tmevtb(p_tcb);
+		}
+		if (!queue_empty(&(p_tcb->mutex_queue))) {
+			if ((*mtxhook_release_all)(p_tcb)) {
+				dspreq = true;
+			}
+		}
+		make_dormant(p_tcb);
+		if (p_tcb->actque) {
+			p_tcb->actque = false;
+			if (make_active(p_tcb)) {
+				dspreq = true;
+			}
+		}
+		if (dspreq) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_TER_TSK_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ter_tsk */
+
+/*
+ *  タスクのベース優先度の変更
+ */
+#ifdef TOPPERS_chg_pri
+
+ER
+chg_pri(ID tskid, PRI tskpri)
+{
+	TCB		*p_tcb;
+	uint_t	newbpri;
+	ER		ercd;
+
+	LOG_CHG_PRI_ENTER(tskid, tskpri);
+	CHECK_TSKCTX_UNL();
+	CHECK_TSKID_SELF(tskid);
+	CHECK_TPRI_INI(tskpri);
+	p_tcb = get_tcb_self(tskid);
+
+	t_lock_cpu();
+	if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (TSTAT_DORMANT(p_tcb->tstat)) {
+		ercd = E_OBJ;
+	}
+	else if ((!queue_empty(&(p_tcb->mutex_queue))
+										|| TSTAT_WAIT_MTX(p_tcb->tstat))
+						&& !((*mtxhook_check_ceilpri)(p_tcb, newbpri))) {
+		ercd = E_ILUSE;
+	}
+	else {
+		newbpri = (tskpri == TPRI_INI) ? p_tcb->p_tinib->ipriority
+											: INT_PRIORITY(tskpri);
+		p_tcb->bpriority = newbpri;
+		if (queue_empty(&(p_tcb->mutex_queue))
+								|| !((*mtxhook_scan_ceilmtx)(p_tcb))) {
+			if (change_priority(p_tcb, newbpri, false)) {
+				dispatch();
+			}
+		}
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_CHG_PRI_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_chg_pri */
+
+/*
+ *  タスク優先度の参照
+ */
+#ifdef TOPPERS_get_pri
+
+ER
+get_pri(ID tskid, PRI *p_tskpri)
+{
+	TCB		*p_tcb;
+	ER		ercd;
+
+	LOG_GET_PRI_ENTER(tskid, p_tskpri);
+	CHECK_TSKCTX_UNL();
+	CHECK_TSKID_SELF(tskid);
+	p_tcb = get_tcb_self(tskid);
+
+	t_lock_cpu();
+	if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (TSTAT_DORMANT(p_tcb->tstat)) {
+		ercd = E_OBJ;
+	}
+	else {
+		*p_tskpri = EXT_TSKPRI(p_tcb->priority);
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_GET_PRI_LEAVE(ercd, *p_tskpri);
+	return(ercd);
+}
+
+#endif /* TOPPERS_get_pri */
+
+/*
+ *  自タスクの拡張情報の参照
+ */
+#ifdef TOPPERS_get_inf
+
+ER
+get_inf(intptr_t *p_exinf)
+{
+	ER		ercd;
+
+	LOG_GET_INF_ENTER(p_exinf);
+	CHECK_TSKCTX_UNL();
+
+	t_lock_cpu();
+	*p_exinf = p_runtsk->p_tinib->exinf;
+	ercd = E_OK;
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_GET_INF_LEAVE(ercd, *p_exinf);
+	return(ercd);
+}
+
+#endif /* TOPPERS_get_inf */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/task_refer.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/task_refer.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/task_refer.c	(revision 453)
@@ -0,0 +1,215 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2005-2014 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		タスクの状態参照機能
+ */
+
+#include "kernel_impl.h"
+#include "check.h"
+#include "task.h"
+#include "wait.h"
+#include "semaphore.h"
+#include "eventflag.h"
+#include "dataqueue.h"
+#include "pridataq.h"
+#include "mailbox.h"
+#include "mutex.h"
+#include "mempfix.h"
+#include "time_event.h"
+
+/*
+ *  トレースログマクロのデフォルト定義
+ */
+#ifndef LOG_REF_TSK_ENTER
+#define LOG_REF_TSK_ENTER(tskid, pk_rtsk)
+#endif /* LOG_REF_TSK_ENTER */
+
+#ifndef LOG_REF_TSK_LEAVE
+#define LOG_REF_TSK_LEAVE(ercd, pk_rtsk)
+#endif /* LOG_REF_TSK_LEAVE */
+
+/*
+ *  タスクの状態参照
+ */
+#ifdef TOPPERS_ref_tsk
+
+ER
+ref_tsk(ID tskid, T_RTSK *pk_rtsk)
+{
+	TCB		*p_tcb;
+	uint_t	tstat;
+	ER		ercd;
+
+	LOG_REF_TSK_ENTER(tskid, pk_rtsk);
+	CHECK_TSKCTX_UNL();
+	CHECK_TSKID_SELF(tskid);
+	p_tcb = get_tcb_self(tskid);
+
+	t_lock_cpu();
+	if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else {
+		tstat = p_tcb->tstat;
+		if (TSTAT_DORMANT(tstat)) {
+			/*
+	 		 *  対象タスクが休止状態の場合
+			 */
+			pk_rtsk->tskstat = TTS_DMT;
+		}
+		else {
+			/*
+	 		 *  タスク状態の取出し
+			 */
+			if (TSTAT_SUSPENDED(tstat)) {
+				if (TSTAT_WAITING(tstat)) {
+					pk_rtsk->tskstat = TTS_WAS;
+				}
+				else {
+					pk_rtsk->tskstat = TTS_SUS;
+				}
+			}
+			else if (TSTAT_WAITING(tstat)) {
+				pk_rtsk->tskstat = TTS_WAI;
+			}
+			else if (p_tcb == p_runtsk) {
+				pk_rtsk->tskstat = TTS_RUN;
+			}
+			else {
+				pk_rtsk->tskstat = TTS_RDY;
+			}
+
+			/*
+	 		 *  現在優先度とベース優先度の取出し
+			 */
+			pk_rtsk->tskpri = EXT_TSKPRI(p_tcb->priority);
+			pk_rtsk->tskbpri = EXT_TSKPRI(p_tcb->bpriority);
+
+			if (TSTAT_WAITING(tstat)) {
+				/*
+		 		 *  待ち要因と待ち対象のオブジェクトのIDの取出し
+				 */
+				switch (tstat & TS_WAIT_MASK) {
+				case TS_WAIT_SLP:
+					pk_rtsk->tskwait = TTW_SLP;
+					break;
+				case TS_WAIT_DLY:
+					pk_rtsk->tskwait = TTW_DLY;
+					break;
+				case TS_WAIT_SEM:
+					pk_rtsk->tskwait = TTW_SEM;
+					pk_rtsk->wobjid = SEMID(((WINFO_SEM *)(p_tcb->p_winfo))
+																->p_semcb);
+					break;
+				case TS_WAIT_FLG:
+					pk_rtsk->tskwait = TTW_FLG;
+					pk_rtsk->wobjid = FLGID(((WINFO_FLG *)(p_tcb->p_winfo))
+																->p_flgcb);
+					break;
+				case TS_WAIT_SDTQ:
+					pk_rtsk->tskwait = TTW_SDTQ;
+					pk_rtsk->wobjid = DTQID(((WINFO_DTQ *)(p_tcb->p_winfo))
+																->p_dtqcb);
+					break;
+				case TS_WAIT_RDTQ:
+					pk_rtsk->tskwait = TTW_RDTQ;
+					pk_rtsk->wobjid = DTQID(((WINFO_DTQ *)(p_tcb->p_winfo))
+																->p_dtqcb);
+					break;
+				case TS_WAIT_SPDQ:
+					pk_rtsk->tskwait = TTW_SPDQ;
+					pk_rtsk->wobjid = PDQID(((WINFO_PDQ *)(p_tcb->p_winfo))
+																->p_pdqcb);
+					break;
+				case TS_WAIT_RPDQ:
+					pk_rtsk->tskwait = TTW_RPDQ;
+					pk_rtsk->wobjid = PDQID(((WINFO_PDQ *)(p_tcb->p_winfo))
+																->p_pdqcb);
+					break;
+				case TS_WAIT_MBX:
+					pk_rtsk->tskwait = TTW_MBX;
+					pk_rtsk->wobjid = MBXID(((WINFO_MBX *)(p_tcb->p_winfo))
+																->p_mbxcb);
+					break;
+				case TS_WAIT_MTX:
+					pk_rtsk->tskwait = TTW_MTX;
+					pk_rtsk->wobjid = MTXID(((WINFO_MTX *)(p_tcb->p_winfo))
+																	->p_mtxcb);
+					break;
+				case TS_WAIT_MPF:
+					pk_rtsk->tskwait = TTW_MPF;
+					pk_rtsk->wobjid = MPFID(((WINFO_MPF *)(p_tcb->p_winfo))
+																->p_mpfcb);
+					break;
+				}
+
+				/*
+				 *  タイムアウトするまでの時間の取出し
+				 */
+				if (p_tcb->p_winfo->p_tmevtb != NULL) {
+					pk_rtsk->lefttmo
+							= (TMO) tmevt_lefttim(p_tcb->p_winfo->p_tmevtb);
+				}
+				else {
+					pk_rtsk->lefttmo = TMO_FEVR;
+				}
+			}
+
+			/*
+			 *  起床要求キューイング数の取出し
+			 */
+			pk_rtsk->wupcnt = p_tcb->wupque ? 1U : 0U;
+		}
+
+		/*
+		 *  起動要求キューイング数の取出し
+		 */
+		pk_rtsk->actcnt = p_tcb->actque ? 1U : 0U;
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_REF_TSK_LEAVE(ercd, pk_rtsk);
+	return(ercd);
+}
+
+#endif /* TOPPERS_ref_tsk */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/task_sync.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/task_sync.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/task_sync.c	(revision 453)
@@ -0,0 +1,552 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		タスク付属同期機能
+ */
+
+#include "kernel_impl.h"
+#include "check.h"
+#include "task.h"
+#include "wait.h"
+
+/*
+ *  トレースログマクロのデフォルト定義
+ */
+#ifndef LOG_SLP_TSK_ENTER
+#define LOG_SLP_TSK_ENTER()
+#endif /* LOG_SLP_TSK_ENTER */
+
+#ifndef LOG_SLP_TSK_LEAVE
+#define LOG_SLP_TSK_LEAVE(ercd)
+#endif /* LOG_SLP_TSK_LEAVE */
+
+#ifndef LOG_TSLP_TSK_ENTER
+#define LOG_TSLP_TSK_ENTER(tmout)
+#endif /* LOG_TSLP_TSK_ENTER */
+
+#ifndef LOG_TSLP_TSK_LEAVE
+#define LOG_TSLP_TSK_LEAVE(ercd)
+#endif /* LOG_TSLP_TSK_LEAVE */
+
+#ifndef LOG_WUP_TSK_ENTER
+#define LOG_WUP_TSK_ENTER(tskid)
+#endif /* LOG_WUP_TSK_ENTER */
+
+#ifndef LOG_WUP_TSK_LEAVE
+#define LOG_WUP_TSK_LEAVE(ercd)
+#endif /* LOG_WUP_TSK_LEAVE */
+
+#ifndef LOG_IWUP_TSK_ENTER
+#define LOG_IWUP_TSK_ENTER(tskid)
+#endif /* LOG_IWUP_TSK_ENTER */
+
+#ifndef LOG_IWUP_TSK_LEAVE
+#define LOG_IWUP_TSK_LEAVE(ercd)
+#endif /* LOG_IWUP_TSK_LEAVE */
+
+#ifndef LOG_CAN_WUP_ENTER
+#define LOG_CAN_WUP_ENTER(tskid)
+#endif /* LOG_CAN_WUP_ENTER */
+
+#ifndef LOG_CAN_WUP_LEAVE
+#define LOG_CAN_WUP_LEAVE(ercd)
+#endif /* LOG_CAN_WUP_LEAVE */
+
+#ifndef LOG_REL_WAI_ENTER
+#define LOG_REL_WAI_ENTER(tskid)
+#endif /* LOG_REL_WAI_ENTER */
+
+#ifndef LOG_REL_WAI_LEAVE
+#define LOG_REL_WAI_LEAVE(ercd)
+#endif /* LOG_REL_WAI_LEAVE */
+
+#ifndef LOG_IREL_WAI_ENTER
+#define LOG_IREL_WAI_ENTER(tskid)
+#endif /* LOG_IREL_WAI_ENTER */
+
+#ifndef LOG_IREL_WAI_LEAVE
+#define LOG_IREL_WAI_LEAVE(ercd)
+#endif /* LOG_IREL_WAI_LEAVE */
+
+#ifndef LOG_SUS_TSK_ENTER
+#define LOG_SUS_TSK_ENTER(tskid)
+#endif /* LOG_SUS_TSK_ENTER */
+
+#ifndef LOG_SUS_TSK_LEAVE
+#define LOG_SUS_TSK_LEAVE(ercd)
+#endif /* LOG_SUS_TSK_LEAVE */
+
+#ifndef LOG_RSM_TSK_ENTER
+#define LOG_RSM_TSK_ENTER(tskid)
+#endif /* LOG_RSM_TSK_ENTER */
+
+#ifndef LOG_RSM_TSK_LEAVE
+#define LOG_RSM_TSK_LEAVE(ercd)
+#endif /* LOG_RSM_TSK_LEAVE */
+
+#ifndef LOG_DLY_TSK_ENTER
+#define LOG_DLY_TSK_ENTER(dlytim)
+#endif /* LOG_DLY_TSK_ENTER */
+
+#ifndef LOG_DLY_TSK_LEAVE
+#define LOG_DLY_TSK_LEAVE(ercd)
+#endif /* LOG_DLY_TSK_LEAVE */
+
+/*
+ *  起床待ち
+ */
+#ifdef TOPPERS_slp_tsk
+
+ER
+slp_tsk(void)
+{
+	WINFO	winfo;
+	ER		ercd;
+
+	LOG_SLP_TSK_ENTER();
+	CHECK_DISPATCH();
+
+	t_lock_cpu();
+	if (p_runtsk->wupque) {
+		p_runtsk->wupque = false;
+		ercd = E_OK;
+	}
+	else {
+		p_runtsk->tstat = (TS_WAITING | TS_WAIT_SLP);
+		make_wait(&winfo);
+		LOG_TSKSTAT(p_runtsk);
+		dispatch();
+		ercd = winfo.wercd;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_SLP_TSK_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_slp_tsk */
+
+/*
+ *  起床待ち（タイムアウトあり）
+ */
+#ifdef TOPPERS_tslp_tsk
+
+ER
+tslp_tsk(TMO tmout)
+{
+	WINFO	winfo;
+	TMEVTB	tmevtb;
+	ER		ercd;
+
+	LOG_TSLP_TSK_ENTER(tmout);
+	CHECK_DISPATCH();
+	CHECK_TMOUT(tmout);
+
+	t_lock_cpu();
+	if (p_runtsk->wupque) {
+		p_runtsk->wupque = false;
+		ercd = E_OK;
+	}
+	else if (tmout == TMO_POL) {
+		ercd = E_TMOUT;
+	}
+	else {
+		p_runtsk->tstat = (TS_WAITING | TS_WAIT_SLP);
+		make_wait_tmout(&winfo, &tmevtb, tmout);
+		LOG_TSKSTAT(p_runtsk);
+		dispatch();
+		ercd = winfo.wercd;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_TSLP_TSK_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_tslp_tsk */
+
+/*
+ *  タスクの起床
+ */
+#ifdef TOPPERS_wup_tsk
+
+ER
+wup_tsk(ID tskid)
+{
+	TCB		*p_tcb;
+	ER		ercd;
+
+	LOG_WUP_TSK_ENTER(tskid);
+	CHECK_TSKCTX_UNL();
+	CHECK_TSKID_SELF(tskid);
+	p_tcb = get_tcb_self(tskid);
+
+	t_lock_cpu();
+	if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (TSTAT_DORMANT(p_tcb->tstat)) {
+		ercd = E_OBJ;
+	}
+	else if (TSTAT_WAIT_SLP(p_tcb->tstat)) {
+		if (wait_complete(p_tcb)) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	else if (!(p_tcb->wupque)) {
+		p_tcb->wupque = true;
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_QOVR;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_WUP_TSK_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_wup_tsk */
+
+/*
+ *  タスクの起床（非タスクコンテキスト用）
+ */
+#ifdef TOPPERS_iwup_tsk
+
+ER
+iwup_tsk(ID tskid)
+{
+	TCB		*p_tcb;
+	ER		ercd;
+
+	LOG_IWUP_TSK_ENTER(tskid);
+	CHECK_INTCTX_UNL();
+	CHECK_TSKID(tskid);
+	p_tcb = get_tcb(tskid);
+
+	i_lock_cpu();
+	if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (TSTAT_DORMANT(p_tcb->tstat)) {
+		ercd = E_OBJ;
+	}
+	else if (TSTAT_WAIT_SLP(p_tcb->tstat)) {
+		if (wait_complete(p_tcb)) {
+			reqflg = true;
+		}
+		ercd = E_OK;
+	}
+	else if (!(p_tcb->wupque)) {
+		p_tcb->wupque = true;
+		ercd = E_OK;
+	}
+	else {
+		ercd = E_QOVR;
+	}
+	i_unlock_cpu();
+
+  error_exit:
+	LOG_IWUP_TSK_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_iwup_tsk */
+
+/*
+ *  タスク起床要求のキャンセル
+ */
+#ifdef TOPPERS_can_wup
+
+ER_UINT
+can_wup(ID tskid)
+{
+	TCB		*p_tcb;
+	ER_UINT	ercd;
+
+	LOG_CAN_WUP_ENTER(tskid);
+	CHECK_TSKCTX_UNL();
+	CHECK_TSKID_SELF(tskid);
+	p_tcb = get_tcb_self(tskid);
+
+	t_lock_cpu();
+	if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (TSTAT_DORMANT(p_tcb->tstat)) {
+		ercd = E_OBJ;
+	}
+	else {
+		ercd = p_tcb->wupque ? 1 : 0;
+		p_tcb->wupque = false;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_CAN_WUP_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_can_wup */
+
+/*
+ *  待ち状態の強制解除
+ */
+#ifdef TOPPERS_rel_wai
+
+ER
+rel_wai(ID tskid)
+{
+	TCB		*p_tcb;
+	ER		ercd;
+
+	LOG_REL_WAI_ENTER(tskid);
+	CHECK_TSKCTX_UNL();
+	CHECK_TSKID(tskid);
+	p_tcb = get_tcb(tskid);
+
+	t_lock_cpu();
+	if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (!TSTAT_WAITING(p_tcb->tstat)) {
+		ercd = E_OBJ;
+	}
+	else {
+		if (wait_release(p_tcb)) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_REL_WAI_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_rel_wai */
+
+/*
+ *  待ち状態の強制解除（非タスクコンテキスト用）
+ */
+#ifdef TOPPERS_irel_wai
+
+ER
+irel_wai(ID tskid)
+{
+	TCB		*p_tcb;
+	ER		ercd;
+
+	LOG_IREL_WAI_ENTER(tskid);
+	CHECK_INTCTX_UNL();
+	CHECK_TSKID(tskid);
+	p_tcb = get_tcb(tskid);
+
+	i_lock_cpu();
+	if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (!TSTAT_WAITING(p_tcb->tstat)) {
+		ercd = E_OBJ;
+	}
+	else {
+		if (wait_release(p_tcb)) {
+			reqflg = true;
+		}
+		ercd = E_OK;
+	}
+	i_unlock_cpu();
+
+  error_exit:
+	LOG_IREL_WAI_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_irel_wai */
+
+/*
+ *  強制待ち状態への移行
+ */
+#ifdef TOPPERS_sus_tsk
+
+ER
+sus_tsk(ID tskid)
+{
+	TCB		*p_tcb;
+	ER		ercd;
+
+	LOG_SUS_TSK_ENTER(tskid);
+	CHECK_TSKCTX_UNL();
+	CHECK_TSKID_SELF(tskid);
+	p_tcb = get_tcb_self(tskid);
+
+	t_lock_cpu();
+	if (p_tcb == p_runtsk && !dspflg) {
+		ercd = E_CTX;
+	}
+	else if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (TSTAT_DORMANT(p_tcb->tstat)) {
+		ercd = E_OBJ;
+	}
+	else if (TSTAT_RUNNABLE(p_tcb->tstat)) {
+		/*
+		 *  実行できる状態から強制待ち状態への遷移
+		 */
+		p_tcb->tstat = TS_SUSPENDED;
+		LOG_TSKSTAT(p_tcb);
+		if (make_non_runnable(p_tcb)) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	else if (TSTAT_SUSPENDED(p_tcb->tstat)) {
+		ercd = E_QOVR;
+	}
+	else {
+		/*
+		 *  待ち状態から二重待ち状態への遷移
+		 */
+		p_tcb->tstat |= TS_SUSPENDED;
+		LOG_TSKSTAT(p_tcb);
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_SUS_TSK_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_sus_tsk */
+
+/*
+ *  強制待ち状態からの再開
+ */
+#ifdef TOPPERS_rsm_tsk
+
+ER
+rsm_tsk(ID tskid)
+{
+	TCB		*p_tcb;
+	ER		ercd;
+
+	LOG_RSM_TSK_ENTER(tskid);
+	CHECK_TSKCTX_UNL();
+	CHECK_TSKID(tskid);
+	p_tcb = get_tcb(tskid);
+
+	t_lock_cpu();
+	if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
+		ercd = E_NOEXS;
+	}
+	else if (!TSTAT_SUSPENDED(p_tcb->tstat)) {
+		ercd = E_OBJ;
+	}
+	else if (!TSTAT_WAITING(p_tcb->tstat)) {
+		/*
+		 *  強制待ち状態から実行できる状態への遷移
+		 */
+		p_tcb->tstat = TS_RUNNABLE;
+		LOG_TSKSTAT(p_tcb);
+		if (make_runnable(p_tcb)) {
+			dispatch();
+		}
+		ercd = E_OK;
+	}
+	else {
+		/*
+		 *  二重待ち状態から待ち状態への遷移
+		 */
+		p_tcb->tstat &= ~TS_SUSPENDED;
+		LOG_TSKSTAT(p_tcb);
+		ercd = E_OK;
+	}
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_RSM_TSK_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_rsm_tsk */
+
+/*
+ *  自タスクの遅延
+ */
+#ifdef TOPPERS_dly_tsk
+
+ER
+dly_tsk(RELTIM dlytim)
+{
+	WINFO	winfo;
+	TMEVTB	tmevtb;
+	ER		ercd;
+
+	LOG_DLY_TSK_ENTER(dlytim);
+	CHECK_DISPATCH();
+	CHECK_PAR(dlytim <= TMAX_RELTIM);
+
+	t_lock_cpu();
+	p_runtsk->tstat = (TS_WAITING | TS_WAIT_DLY);
+	(void) make_non_runnable(p_runtsk);
+	p_runtsk->p_winfo = &winfo;
+	winfo.p_tmevtb = &tmevtb;
+	tmevtb_enqueue(&tmevtb, dlytim, (CBACK) wait_tmout_ok, (void *) p_runtsk);
+	LOG_TSKSTAT(p_runtsk);
+	dispatch();
+	ercd = winfo.wercd;
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_DLY_TSK_LEAVE(ercd);
+	return(ercd);
+}
+
+#endif /* TOPPERS_dly_tsk */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/time_event.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/time_event.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/time_event.c	(revision 453)
@@ -0,0 +1,399 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2013 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		タイムイベント管理モジュール
+ */
+
+#include "kernel_impl.h"
+#include "time_event.h"
+
+/*
+ *  タイムイベントヒープ操作マクロ
+ */
+#define	PARENT(index)		((index) >> 1)		/* 親ノードを求める */
+#define	LCHILD(index)		((index) << 1)		/* 左の子ノードを求める */
+#define	TMEVT_NODE(index)	(tmevt_heap[(index) - 1])
+
+/*
+ *  イベント発生時刻比較マクロ
+ *
+ *  イベント発生時刻は，min_timeからの相対値で比較する．すなわち，
+ *  min_timeを最小値（最も近い時刻），mit_time-1が最大値（最も遠い時刻）
+ *  とみなして比較する．
+ */
+#define	EVTTIM_LT(t1, t2) (((t1) - min_time) < ((t2) - min_time))
+#define	EVTTIM_LE(t1, t2) (((t1) - min_time) <= ((t2) - min_time))
+
+#ifdef TOPPERS_tmeini
+
+/*
+ *  現在のシステム時刻（単位: 1ミリ秒）
+ *
+ *  厳密には，前のタイムティックのシステム時刻．
+ */
+EVTTIM	current_time;
+
+/*
+ *  タイムイベントヒープ中で有効な最小のシステム時刻（単位: 1ミリ秒）
+ */
+EVTTIM	min_time;
+
+/*
+ *  次のタイムティックのシステム時刻（単位: 1ミリ秒）
+ */
+EVTTIM	next_time;
+
+/*
+ *  システム時刻積算用変数（単位: 1/TIC_DENOミリ秒）
+ */
+#if TIC_DENO != 1U
+uint_t	next_subtime;
+#endif /* TIC_DENO != 1U */
+
+/*
+ *  タイムイベントヒープの最後の使用領域のインデックス
+ */
+uint_t	last_index;
+
+/*
+ *  タイマモジュールの初期化
+ */
+void
+initialize_tmevt(void)
+{
+	current_time = 0U;
+	min_time = 0U;
+	next_time = current_time + TIC_NUME / TIC_DENO;
+#if TIC_DENO != 1U
+	next_subtime = TIC_NUME % TIC_DENO;
+#endif /* TIC_DENO != 1U */
+	last_index = 0U;
+}
+
+#endif /* TOPPERS_tmeini */
+
+/*
+ *  タイムイベントの挿入位置を上向きに探索
+ *
+ *  時刻timeに発生するタイムイベントを挿入するノードを空けるために，
+ *  ヒープの上に向かって空ノードを移動させる．移動前の空ノードの位置を
+ *  indexに渡すと，移動後の空ノードの位置（すなわち挿入位置）を返す．
+ */
+#ifdef TOPPERS_tmeup
+
+uint_t
+tmevt_up(uint_t index, EVTTIM time)
+{
+	uint_t	parent;
+
+	while (index > 1) {
+		/*
+		 *  親ノードのイベント発生時刻の方が早い（または同じ）ならば，
+		 *  indexが挿入位置なのでループを抜ける．
+		 */
+		parent = PARENT(index);
+		if (EVTTIM_LE(TMEVT_NODE(parent).time, time)) {
+			break;
+		}
+
+		/*
+		 *  親ノードをindexの位置に移動させる．
+		 */
+		TMEVT_NODE(index) = TMEVT_NODE(parent);
+		TMEVT_NODE(index).p_tmevtb->index = index;
+
+		/*
+		 *  indexを親ノードの位置に更新．
+		 */
+		index = parent;
+	}
+	return(index);
+}
+
+#endif /* TOPPERS_tmeup */
+
+/*
+ *  タイムイベントの挿入位置を下向きに探索
+ *
+ *  時刻timeに発生するタイムイベントを挿入するノードを空けるために，
+ *  ヒープの下に向かって空ノードを移動させる．移動前の空ノードの位置を 
+ *  indexに渡すと，移動後の空ノードの位置（すなわち挿入位置）を返す．
+ */
+#ifdef TOPPERS_tmedown
+
+uint_t
+tmevt_down(uint_t index, EVTTIM time)
+{
+	uint_t	child;
+
+	while ((child = LCHILD(index)) <= last_index) {
+		/*
+		 *  左右の子ノードのイベント発生時刻を比較し，早い方の子ノード
+		 *  の位置をchildに設定する．以下の子ノードは，ここで選ばれた方
+		 *  の子ノードのこと．
+		 */
+		if (child + 1 <= last_index
+						&& EVTTIM_LT(TMEVT_NODE(child + 1).time,
+										TMEVT_NODE(child).time)) {
+			child = child + 1;
+		}
+
+		/*
+		 *  子ノードのイベント発生時刻の方が遅い（または同じ）ならば，
+		 *  indexが挿入位置なのでループを抜ける．
+		 */
+		if (EVTTIM_LE(time, TMEVT_NODE(child).time)) {
+			break;
+		}
+
+		/*
+		 *  子ノードをindexの位置に移動させる．
+		 */
+		TMEVT_NODE(index) = TMEVT_NODE(child);
+		TMEVT_NODE(index).p_tmevtb->index = index;
+
+		/*
+		 *  indexを子ノードの位置に更新．
+		 */
+		index = child;
+	}
+	return(index);
+}
+
+#endif /* TOPPERS_tmedown */
+
+/*
+ *  タイムイベントヒープへの登録
+ *
+ *  p_tmevtbで指定したタイムイベントブロックを，timeで指定した時間が経
+ *  過後にイベントが発生するように，タイムイベントヒープに登録する．
+ */
+#ifdef TOPPERS_tmeins
+
+void
+tmevtb_insert(TMEVTB *p_tmevtb, EVTTIM time)
+{
+	uint_t	index;
+
+	/*
+	 *  last_indexをインクリメントし，そこから上に挿入位置を探す．
+	 */
+	index = tmevt_up(++last_index, time);
+
+	/*
+	 *  タイムイベントをindexの位置に挿入する．
+	 */ 
+	TMEVT_NODE(index).time = time;
+	TMEVT_NODE(index).p_tmevtb = p_tmevtb;
+	p_tmevtb->index = index;
+}
+
+#endif /* TOPPERS_tmeins */
+
+/*
+ *  タイムイベントヒープからの削除
+ */
+#ifdef TOPPERS_tmedel
+
+void
+tmevtb_delete(TMEVTB *p_tmevtb)
+{
+	uint_t	index = p_tmevtb->index;
+	uint_t	parent;
+	EVTTIM	event_time = TMEVT_NODE(last_index).time;
+
+	/*
+	 *  削除によりタイムイベントヒープが空になる場合は何もしない．
+	 */
+	if (--last_index == 0) {
+		return;
+	}
+
+	/*
+	 *  削除したノードの位置に最後のノード（last_index+1の位置のノード）
+	 *  を挿入し，それを適切な位置へ移動させる．実際には，最後のノード
+	 *  を実際に挿入するのではなく，削除したノードの位置が空ノードにな
+	 *  るので，最後のノードを挿入すべき位置へ向けて空ノードを移動させ
+	 *  る．
+	 *  最後のノードのイベント発生時刻が，削除したノードの親ノードのイ
+	 *  ベント発生時刻より前の場合には，上に向かって挿入位置を探す．そ
+	 *  うでない場合には，下に向かって探す．
+	 */
+	if (index > 1 && EVTTIM_LT(event_time,
+								TMEVT_NODE(parent = PARENT(index)).time)) {
+		/*
+		 *  親ノードをindexの位置に移動させる．
+		 */
+		TMEVT_NODE(index) = TMEVT_NODE(parent);
+		TMEVT_NODE(index).p_tmevtb->index = index;
+
+		/*
+		 *  削除したノードの親ノードから上に向かって挿入位置を探す．
+		 */
+		index = tmevt_up(parent, event_time);
+	}
+	else {
+		/*
+		 *  削除したノードから下に向かって挿入位置を探す．
+		 */
+		index = tmevt_down(index, event_time);
+	}
+
+	/*
+	 *  最後のノードをindexの位置に挿入する．
+	 */ 
+	TMEVT_NODE(index) = TMEVT_NODE(last_index + 1);
+	TMEVT_NODE(index).p_tmevtb->index = index;
+}
+
+#endif /* TOPPERS_tmedel */
+
+/*
+ *  タイムイベントヒープの先頭のノードの削除
+ */
+Inline void
+tmevtb_delete_top(void)
+{
+	uint_t	index;
+	EVTTIM	event_time = TMEVT_NODE(last_index).time;
+
+	/*
+	 *  削除によりタイムイベントヒープが空になる場合は何もしない．
+	 */
+	if (--last_index == 0) {
+		return;
+	}
+
+	/*
+	 *  ルートノードに最後のノード（last_index + 1 の位置のノード）を
+	 *  挿入し，それを適切な位置へ移動させる．実際には，最後のノードを
+	 *  実際に挿入するのではなく，ルートノードが空ノードになるので，最
+	 *  後のノードを挿入すべき位置へ向けて空ノードを移動させる．
+	 */
+	index = tmevt_down(1, event_time);
+
+	/*
+	 *  最後のノードをindexの位置に挿入する．
+	 */ 
+	TMEVT_NODE(index) = TMEVT_NODE(last_index + 1);
+	TMEVT_NODE(index).p_tmevtb->index = index;
+}
+
+/*
+ *  タイムイベントまでの残り時間の計算
+ */
+#ifdef TOPPERS_tmeltim
+
+RELTIM
+tmevt_lefttim(TMEVTB *p_tmevtb)
+{
+	EVTTIM	time;
+
+	time = TMEVT_NODE(p_tmevtb->index).time;
+	if (EVTTIM_LE(time, next_time)) {
+		/*
+		 *  次のタイムティックで処理される場合には0を返す．
+		 */
+		return(0U);
+	}
+	else {
+		return((RELTIM)(time - base_time));
+	}
+}
+
+#endif /* TOPPERS_tmeltim */
+
+/*
+ *  タイムティックの供給
+ */
+#ifdef TOPPERS_sigtim
+
+void
+signal_time(void)
+{
+	TMEVTB	*p_tmevtb;
+
+	assert(sense_context());
+	assert(!i_sense_lock());
+
+	i_lock_cpu();
+
+	/*
+	 *  current_timeを更新する．
+	 */
+	current_time = next_time;
+
+	/*
+	 *  next_time，next_subtimeを更新する．
+	 */
+#if TIC_DENO == 1U
+	next_time = current_time + TIC_NUME;
+#else /* TIC_DENO == 1U */
+	next_subtime += TIC_NUME % TIC_DENO;
+	next_time = current_time + TIC_NUME / TIC_DENO;
+	if (next_subtime >= TIC_DENO) {
+		next_subtime -= TIC_DENO;
+		next_time += 1U;
+	}
+#endif /* TIC_DENO == 1U */
+
+	/*
+	 *  current_timeよりイベント発生時刻の早い（または同じ）タイムイベ
+	 *  ントを，タイムイベントヒープから削除し，コールバック関数を呼び
+	 *  出す．
+	 */
+	while (last_index > 0 && EVTTIM_LE(TMEVT_NODE(1).time, current_time)) {
+		p_tmevtb = TMEVT_NODE(1).p_tmevtb;
+		tmevtb_delete_top();
+		(*(p_tmevtb->callback))(p_tmevtb->arg);
+	}
+
+	/*
+	 *  min_timeを更新する．
+	 */
+	min_time = current_time;
+
+	i_unlock_cpu();
+}
+
+#endif /* TOPPERS_sigtim */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/time_event.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/time_event.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/time_event.h	(revision 453)
@@ -0,0 +1,200 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		タイムイベント管理モジュール
+ */
+
+#ifndef TOPPERS_TIME_EVENT_H
+#define TOPPERS_TIME_EVENT_H
+
+/*
+ *  イベント発生時刻のデータ型の定義
+ *
+ *  EVTTIMは，RELTIMとして指定できる範囲よりも広い範囲を表現できる必要
+ *  がある．μITRON4.0仕様のスタンダードプロファイルでは，RELTIMが16ビッ
+ *  ト以上でなければならないため，EVTTIMは17ビット以上であることが必要
+ *  である．そのため，16ビットになる場合があるuint_tではなく，ulong_tに
+ *  定義している．
+ */
+typedef ulong_t	EVTTIM;
+
+/* 
+ *  タイムイベントブロックのデータ型の定義
+ */
+typedef void	(*CBACK)(void *);	/* コールバック関数の型 */
+
+typedef struct time_event_block {
+	uint_t	index;			/* タイムイベントヒープ中での位置 */
+	CBACK	callback;		/* コールバック関数 */
+	void	*arg;			/* コールバック関数へ渡す引数 */
+} TMEVTB;
+
+/*
+ *  タイムイベントヒープ中のノードのデータ型の定義
+ */
+typedef struct time_event_node {
+	EVTTIM	time;			/* イベント発生時刻 */
+	TMEVTB	*p_tmevtb;		/* 対応するタイムイベントブロック */
+} TMEVTN;
+
+/*
+ *  タイムイベントヒープ（kernel_cfg.c）
+ */
+extern TMEVTN	tmevt_heap[];
+
+/*
+ *  現在のシステム時刻（単位: 1ミリ秒）
+ *
+ *  システム起動時に0に初期化され，以降，タイムティックが供給される度に
+ *  単調に増加する．
+ */
+extern EVTTIM	current_time;
+
+/*
+ *  タイムイベントヒープ中で有効な最小のシステム時刻（単位: 1ミリ秒）
+ */
+extern EVTTIM	min_time;
+
+/*
+ *  次のタイムティックのシステム時刻（単位: 1ミリ秒）
+ */
+extern EVTTIM	next_time;
+
+/*
+ *  システム時刻積算用変数（単位: 1/TIC_DENOミリ秒）
+ *
+ *  次のタイムティックのシステム時刻の下位桁を示す（上位桁はnext_time）．
+ *  TIC_DENOが1の時は，下位桁は常に0であるため，この変数は必要ない．
+ */
+#if TIC_DENO != 1U
+extern uint_t	next_subtime;
+#endif /* TIC_DENO != 1U */
+
+/*
+ *  相対時間の基準時刻（単位: 1ミリ秒）
+ *
+ *  次のタイムティックのシステム時刻を切り上げた時刻．TIC_DENOが1の時
+ *  は，next_timeに一致する．
+ */
+#if TIC_DENO == 1U
+#define	base_time	(next_time)
+#else /* TIC_DENO == 1U */
+#define	base_time	(next_time + (next_subtime > 0U ? 1U : 0U))
+#endif /* TIC_DENO == 1U */
+
+/*
+ *  タイムイベントヒープの最後の使用領域のインデックス
+ *
+ *  タイムイベントヒープに登録されているタイムイベントの数に一致する．
+ */
+extern uint_t	last_index;
+
+/*
+ *  タイムイベント管理モジュールの初期化
+ */
+extern void	initialize_tmevt(void);
+
+/*
+ *  タイムイベントの挿入位置の探索
+ */
+extern uint_t	tmevt_up(uint_t index, EVTTIM time);
+extern uint_t	tmevt_down(uint_t index, EVTTIM time);
+
+/*
+ *  タイムイベントヒープへの登録と削除
+ */
+extern void	tmevtb_insert(TMEVTB *p_tmevtb, EVTTIM time);
+extern void	tmevtb_delete(TMEVTB *p_tmevtb);
+
+/*
+ *  タイムイベントブロックの登録（相対時間指定）
+ *
+ *  timeで指定した相対時間が経過した後に，argを引数としてcallbackが呼
+ *  び出されるように，p_tmevtbで指定したタイムイベントブロックを登録す
+ *  る．
+ *  
+ */
+Inline void
+tmevtb_enqueue(TMEVTB *p_tmevtb, RELTIM time, CBACK callback, void *arg)
+{
+	assert(time <= TMAX_RELTIM);
+
+	p_tmevtb->callback = callback;
+	p_tmevtb->arg = arg;
+	tmevtb_insert(p_tmevtb, base_time + time);
+}
+
+/*
+ *  タイムイベントブロックの登録（イベント発生時刻指定）
+ *
+ *  timeで指定したイベント発生時刻に，argを引数としてcallbackが呼び出
+ *  されるように，p_tmevtbで指定したタイムイベントブロックを登録する．
+ */
+Inline void
+tmevtb_enqueue_evttim(TMEVTB *p_tmevtb, EVTTIM time, CBACK callback, void *arg)
+{
+	p_tmevtb->callback = callback;
+	p_tmevtb->arg = arg;
+	tmevtb_insert(p_tmevtb, time);
+}
+
+/*
+ *  タイムイベントブロックの登録解除
+ */
+Inline void
+tmevtb_dequeue(TMEVTB *p_tmevtb)
+{
+	tmevtb_delete(p_tmevtb);
+}
+
+/*
+ *  タイムイベントまでの残り時間の計算
+ */
+extern RELTIM	tmevt_lefttim(TMEVTB *p_tmevtb);
+
+/*
+ *  タイムティックの供給
+ */
+extern void	signal_time(void);
+
+#endif /* TOPPERS_TIME_EVENT_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/time_manage.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/time_manage.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/time_manage.c	(revision 453)
@@ -0,0 +1,144 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		システム時刻管理機能
+ */
+
+#include "kernel_impl.h"
+#include "check.h"
+#include "time_event.h"
+
+/*
+ *  トレースログマクロのデフォルト定義
+ */
+#ifndef LOG_GET_TIM_ENTER
+#define LOG_GET_TIM_ENTER(p_systim)
+#endif /* LOG_GET_TIM_ENTER */
+
+#ifndef LOG_GET_TIM_LEAVE
+#define LOG_GET_TIM_LEAVE(ercd, systim)
+#endif /* LOG_GET_TIM_LEAVE */
+
+#ifndef LOG_GET_UTM_ENTER
+#define LOG_GET_UTM_ENTER(p_sysutm)
+#endif /* LOG_GET_UTM_ENTER */
+
+#ifndef LOG_GET_UTM_LEAVE
+#define LOG_GET_UTM_LEAVE(ercd, sysutm)
+#endif /* LOG_GET_UTM_LEAVE */
+
+/*
+ *  システム時刻の参照
+ */
+#ifdef TOPPERS_get_tim
+
+ER
+get_tim(SYSTIM *p_systim)
+{
+	ER		ercd;
+
+	LOG_GET_TIM_ENTER(p_systim);
+	CHECK_TSKCTX_UNL();
+
+	t_lock_cpu();
+	*p_systim = current_time;
+	ercd = E_OK;
+	t_unlock_cpu();
+
+  error_exit:
+	LOG_GET_TIM_LEAVE(ercd, *p_systim);
+	return(ercd);
+}
+
+#endif /* TOPPERS_get_tim */
+
+/*
+ *  性能評価用システム時刻の参照
+ */
+#ifdef TOPPERS_get_utm
+#ifdef TOPPERS_SUPPORT_GET_UTM
+#ifndef OMIT_GET_UTM
+#include "target_timer.h"
+
+ER
+get_utm(SYSUTM *p_sysutm)
+{
+	SYSUTM	utime;
+	SYSTIM	time;
+#if TIC_DENO != 1
+	uint_t	subtime;
+#endif /* TIC_DENO != 1 */
+	CLOCK	clock1, clock2;
+	bool_t	ireq;
+	SIL_PRE_LOC;
+
+	LOG_GET_UTM_ENTER(p_sysutm);
+
+	SIL_LOC_INT();
+	time = next_time;
+#if TIC_DENO != 1
+	subtime = next_subtime;
+#endif /* TIC_DENO != 1 */
+	clock1 = target_timer_get_current();
+	ireq = target_timer_probe_int();
+	clock2 = target_timer_get_current();
+	SIL_UNL_INT();
+
+	utime = ((SYSUTM) time) * 1000U;
+#if TIC_DENO != 1
+	utime += subtime * 1000U / TIC_DENO;
+#endif /* TIC_DENO != 1 */
+
+	if (!ireq || clock1 > clock2) {
+		utime -= TIC_NUME * 1000U / TIC_DENO;
+	}
+	utime += TO_USEC(clock1);
+	*p_sysutm = utime;
+
+	LOG_GET_UTM_LEAVE(E_OK, *p_sysutm);
+	return(E_OK);
+}
+
+#endif /* OMIT_GET_UTM */
+#endif /* TOPPERS_SUPPORT_GET_UTM */
+#endif /* TOPPERS_get_utm */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/wait.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/wait.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/wait.c	(revision 453)
@@ -0,0 +1,213 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		待ち状態管理モジュール
+ */
+
+#include "kernel_impl.h"
+#include "wait.h"
+
+/*
+ *  待ち状態への遷移（タイムアウト指定）
+ */
+#ifdef TOPPERS_waimake
+
+void
+make_wait_tmout(WINFO *p_winfo, TMEVTB *p_tmevtb, TMO tmout)
+{
+	(void) make_non_runnable(p_runtsk);
+	p_runtsk->p_winfo = p_winfo;
+	if (tmout > 0) {
+		p_winfo->p_tmevtb = p_tmevtb;
+		tmevtb_enqueue(p_tmevtb, (RELTIM) tmout,
+						(CBACK) wait_tmout, (void *) p_runtsk);
+	}
+	else {
+		assert(tmout == TMO_FEVR);
+		p_winfo->p_tmevtb = NULL;
+	}
+}
+
+#endif /* TOPPERS_waimake */
+
+/*
+ *  待ち解除
+ */
+#ifdef TOPPERS_waicmp
+
+bool_t
+wait_complete(TCB *p_tcb)
+{
+	wait_dequeue_tmevtb(p_tcb);
+	p_tcb->p_winfo->wercd = E_OK;
+	return(make_non_wait(p_tcb));
+}
+
+#endif /* TOPPERS_waicmp */
+
+/*
+ *  タイムアウトに伴う待ち解除
+ */
+#ifdef TOPPERS_waitmo
+
+void
+wait_tmout(TCB *p_tcb)
+{
+	wait_dequeue_wobj(p_tcb);
+	p_tcb->p_winfo->wercd = E_TMOUT;
+	if (make_non_wait(p_tcb)) {
+		reqflg = true;
+	}
+
+	/*
+	 *  ここで優先度の高い割込みを受け付ける．
+	 */
+	i_unlock_cpu();
+	i_lock_cpu();
+}
+
+#endif /* TOPPERS_waitmo */
+#ifdef TOPPERS_waitmook
+
+void
+wait_tmout_ok(TCB *p_tcb)
+{
+	p_tcb->p_winfo->wercd = E_OK;
+	if (make_non_wait(p_tcb)) {
+		reqflg = true;
+	}
+
+	/*
+	 *  ここで優先度の高い割込みを受け付ける．
+	 */
+	i_unlock_cpu();
+	i_lock_cpu();
+}
+
+#endif /* TOPPERS_waitmook */
+
+/*
+ *  待ち状態の強制解除
+ */
+#ifdef TOPPERS_wairel
+
+bool_t
+wait_release(TCB *p_tcb)
+{
+	wait_dequeue_wobj(p_tcb);
+	wait_dequeue_tmevtb(p_tcb);
+	p_tcb->p_winfo->wercd = E_RLWAI;
+	return(make_non_wait(p_tcb));
+}
+
+#endif /* TOPPERS_wairel */
+
+/*
+ *  実行中のタスクの同期・通信オブジェクトの待ちキューへの挿入
+ *
+ *  実行中のタスクを，同期・通信オブジェクトの待ちキューへ挿入する．オ
+ *  ブジェクトの属性に応じて，FIFO順またはタスク優先度順で挿入する．
+ */
+Inline void
+wobj_queue_insert(WOBJCB *p_wobjcb)
+{
+	if ((p_wobjcb->p_wobjinib->wobjatr & TA_TPRI) != 0U) {
+		queue_insert_tpri(&(p_wobjcb->wait_queue), p_runtsk);
+	}
+	else {
+		queue_insert_prev(&(p_wobjcb->wait_queue), &(p_runtsk->task_queue));
+	}
+}
+
+/*
+ *  同期・通信オブジェクトに対する待ち状態への遷移
+ */
+#ifdef TOPPERS_wobjwai
+
+void
+wobj_make_wait(WOBJCB *p_wobjcb, WINFO_WOBJ *p_winfo_wobj)
+{
+	make_wait(&(p_winfo_wobj->winfo));
+	wobj_queue_insert(p_wobjcb);
+	p_winfo_wobj->p_wobjcb = p_wobjcb;
+	LOG_TSKSTAT(p_runtsk);
+}
+
+#endif /* TOPPERS_wobjwai */
+#ifdef TOPPERS_wobjwaitmo
+
+void
+wobj_make_wait_tmout(WOBJCB *p_wobjcb, WINFO_WOBJ *p_winfo_wobj,
+								TMEVTB *p_tmevtb, TMO tmout)
+{
+	make_wait_tmout(&(p_winfo_wobj->winfo), p_tmevtb, tmout);
+	wobj_queue_insert(p_wobjcb);
+	p_winfo_wobj->p_wobjcb = p_wobjcb;
+	LOG_TSKSTAT(p_runtsk);
+}
+
+#endif /* TOPPERS_wobjwaitmo */
+
+/*
+ *  待ちキューの初期化
+ */
+#ifdef TOPPERS_iniwque
+
+bool_t
+init_wait_queue(QUEUE *p_wait_queue)
+{
+	TCB		*p_tcb;
+	bool_t	dspreq = false;
+
+	while (!queue_empty(p_wait_queue)) {
+		p_tcb = (TCB *) queue_delete_next(p_wait_queue);
+		wait_dequeue_tmevtb(p_tcb);
+		p_tcb->p_winfo->wercd = E_DLT;
+		if (make_non_wait(p_tcb)) {
+			dspreq = true;
+		}
+	}
+	return(dspreq);
+}
+
+#endif /* TOPPERS_iniwque */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/wait.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/wait.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/kernel/wait.h	(revision 453)
@@ -0,0 +1,288 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		待ち状態管理モジュール
+ */
+
+#ifndef TOPPERS_WAIT_H
+#define TOPPERS_WAIT_H
+
+#include "task.h"
+#include "time_event.h"
+
+/*
+ *  タスクの優先度順の待ちキューへの挿入
+ *
+ *  p_tcbで指定されるタスクを，タスク優先度順のキューp_queueに挿入する．
+ *  キューの中に同じ優先度のタスクがある場合には，その最後に挿入する．
+ */
+Inline void
+queue_insert_tpri(QUEUE *p_queue, TCB *p_tcb)
+{
+	QUEUE	*p_entry;
+	uint_t	pri = p_tcb->priority;
+
+	for (p_entry = p_queue->p_next; p_entry != p_queue;
+										p_entry = p_entry->p_next) {
+		if (pri < ((TCB *) p_entry)->priority) {
+			break;
+		}
+	}
+	queue_insert_prev(p_entry, &(p_tcb->task_queue));
+}
+
+/*
+ *  待ち状態への遷移
+ *
+ *  実行中のタスクを待ち状態に遷移させる．具体的には，実行中のタスクを
+ *  レディキューから削除し，TCBのp_winfoフィールド，WINFOのp_tmevtbフィー
+ *  ルドを設定する．
+ */
+Inline void
+make_wait(WINFO *p_winfo)
+{
+	(void) make_non_runnable(p_runtsk);
+	p_runtsk->p_winfo = p_winfo;
+	p_winfo->p_tmevtb = NULL;
+}
+
+/*
+ *  待ち状態への遷移（タイムアウト指定）
+ *
+ *  実行中のタスクを，タイムアウト指定付きで待ち状態に遷移させる．具体
+ *  的には，実行中のタスクをレディキューから削除し，TCBのp_winfoフィー
+ *  ルド，WINFOのp_tmevtbフィールドを設定する．また，タイムイベントブ
+ *  ロックを登録する．
+ */
+extern void	make_wait_tmout(WINFO *p_winfo, TMEVTB *p_tmevtb, TMO tmout);
+
+/*
+ *  待ち解除のためのタスク状態の更新
+ *
+ *  p_tcbで指定されるタスクを，待ち解除するようタスク状態を更新する．
+ *  待ち解除するタスクが実行できる状態になる場合は，レディキューにつな
+ *  ぐ．また，ディスパッチが必要な場合にはtrueを返す．
+ */
+Inline bool_t
+make_non_wait(TCB *p_tcb)
+{
+	assert(TSTAT_WAITING(p_tcb->tstat));
+
+	if (!TSTAT_SUSPENDED(p_tcb->tstat)) {
+		/*
+		 *  待ち状態から実行できる状態への遷移
+		 */
+		p_tcb->tstat = TS_RUNNABLE;
+		LOG_TSKSTAT(p_tcb);
+		return(make_runnable(p_tcb));
+	}
+	else {
+		/*
+		 *  二重待ち状態から強制待ち状態への遷移
+		 */
+		p_tcb->tstat = TS_SUSPENDED;
+		LOG_TSKSTAT(p_tcb);
+		return(false);
+	}
+}
+
+/*
+ *  オブジェクト待ちキューからの削除
+ *
+ *  p_tcbで指定されるタスクが，同期・通信オブジェクトの待ちキューにつ
+ *  ながれていれば，待ちキューから削除する．
+ */
+Inline void
+wait_dequeue_wobj(TCB *p_tcb)
+{
+	if (TSTAT_WAIT_WOBJ(p_tcb->tstat)) {
+		queue_delete(&(p_tcb->task_queue));
+	}
+}
+
+/*
+ *  時間待ちのためのタイムイベントブロックの登録解除
+ *
+ *  p_tcbで指定されるタスクに対して，時間待ちのためのタイムイベントブ
+ *  ロックが登録されていれば，それを登録解除する．
+ */
+Inline void
+wait_dequeue_tmevtb(TCB *p_tcb)
+{
+	if (p_tcb->p_winfo->p_tmevtb != NULL) {
+		tmevtb_dequeue(p_tcb->p_winfo->p_tmevtb);
+	}
+}
+
+/*
+ *  待ち解除
+ *
+ *  p_tcbで指定されるタスクの待ち状態を解除する．具体的には，タイムイ
+ *  ベントブロックが登録されていれば，それを登録解除する．また，タスク
+ *  状態を更新し，待ち解除したタスクからの返値をE_OKとする．待ちキュー
+ *  からの削除は行わない．待ち解除したタスクへのディスパッチが必要な場
+ *  合にはtrueを返す．
+ */
+extern bool_t	wait_complete(TCB *p_tcb);
+
+/*
+ *  タイムアウトに伴う待ち解除
+ *
+ *  p_tcbで指定されるタスクが，待ちキューにつながれていれば待ちキュー
+ *  から削除し，タスク状態を更新する．また，待ち解除したタスクからの返
+ *  値を，wait_tmoutではE_TMOUT，wait_tmout_okではE_OKとする．待ち解除
+ *  したタスクへのディスパッチが必要な時は，reqflgをtrueにする．
+ *
+ *  wait_tmout_okは，dly_tskで使うためのもので，待ちキューから削除する
+ *  処理を行わない．
+ *
+ *  いずれの関数も，タイムイベントのコールバック関数として用いるための
+ *  もので，割込みハンドラから呼び出されることを想定している．
+ */
+extern void	wait_tmout(TCB *p_tcb);
+extern void	wait_tmout_ok(TCB *p_tcb);
+
+/*
+ *  待ち状態の強制解除
+ *
+ *  p_tcbで指定されるタスクの待ち状態を強制的に解除する．具体的には，
+ *  タスクが待ちキューにつながれていれば待ちキューから削除し，タイムイ
+ *  ベントブロックが登録されていればそれを登録解除する．また，タスクの
+ *  状態を更新し，待ち解除したタスクからの返値をE_RLWAIとする．また，
+ *  待ち解除したタスクへのディスパッチが必要な場合にはtrueを返す．
+ */
+extern bool_t	wait_release(TCB *p_tcb);
+
+/*
+ *  待ちキューの先頭のタスクID
+ *
+ *  p_wait_queueで指定した待ちキューの先頭のタスクIDを返す．待ちキュー
+ *  が空の場合には，TSK_NONEを返す．
+ */
+Inline ID
+wait_tskid(QUEUE *p_wait_queue)
+{
+	if (!queue_empty(p_wait_queue)) {
+		return(TSKID((TCB *) p_wait_queue->p_next));
+	}
+	else {
+		return(TSK_NONE);
+	}
+}
+
+/*
+ *  同期・通信オブジェクトの管理ブロックの共通部分操作ルーチン
+ *
+ *  同期・通信オブジェクトの初期化ブロックと管理ブロックの先頭部分は共
+ *  通になっている．以下は，その共通部分を扱うための型およびルーチン群
+ *  である．
+ *
+ *  複数の待ちキューを持つ同期・通信オブジェクトの場合，先頭以外の待ち
+ *  キューを操作する場合には，これらのルーチンは使えない．また，オブジェ
+ *  クト属性のTA_TPRIビットを参照するので，このビットを他の目的に使って
+ *  いる場合も，これらのルーチンは使えない．
+ */
+
+/*
+ *  同期・通信オブジェクトの初期化ブロックの共通部分
+ */
+typedef struct wait_object_initialization_block {
+	ATR			wobjatr;		/* オブジェクト属性 */
+} WOBJINIB;
+
+/*
+ *  同期・通信オブジェクトの管理ブロックの共通部分
+ */
+typedef struct wait_object_control_block {
+	QUEUE		wait_queue;		/* 待ちキュー */
+	const WOBJINIB *p_wobjinib;	/* 初期化ブロックへのポインタ */
+} WOBJCB;
+
+/*
+ *  同期・通信オブジェクトの待ち情報ブロックの共通部分
+ *
+ *  この構造体は，待ち情報ブロック（WINFO）を拡張（オブジェクト指向言
+ *  語の継承に相当）したものであるが，WINFOが共用体で定義されているた
+ *  めに，1つのフィールドとして含めている．
+ */
+typedef struct wait_object_waiting_information {
+	WINFO	winfo;			/* 標準の待ち情報ブロック */
+	WOBJCB	*p_wobjcb;		/* 待ちオブジェクトの管理ブロック */
+} WINFO_WOBJ;
+
+/*
+ *  同期・通信オブジェクトに対する待ち状態への遷移
+ *  
+ *  実行中のタスクを待ち状態に遷移させ，同期・通信オブジェクトの待ちキュー
+ *  につなぐ．また，待ち情報ブロック（WINFO）のp_wobjcbを設定する．
+ *  wobj_make_wait_tmoutは，タイムイベントブロックの登録も行う．
+ */
+extern void	wobj_make_wait(WOBJCB *p_wobjcb, WINFO_WOBJ *p_winfo);
+extern void	wobj_make_wait_tmout(WOBJCB *p_wobjcb, WINFO_WOBJ *p_winfo,
+											TMEVTB *p_tmevtb, TMO tmout);
+
+/*
+ *  タスク優先度変更時の処理
+ *
+ *  同期・通信オブジェクトに対する待ち状態にあるタスクの優先度が変更さ
+ *  れた場合に，待ちキューの中でのタスクの位置を修正する．
+ */
+Inline void
+wobj_change_priority(WOBJCB *p_wobjcb, TCB *p_tcb)
+{
+	if ((p_wobjcb->p_wobjinib->wobjatr & TA_TPRI) != 0U) {
+		queue_delete(&(p_tcb->task_queue));
+		queue_insert_tpri(&(p_wobjcb->wait_queue), p_tcb);
+	}
+}
+
+/*
+ *  待ちキューの初期化
+ *
+ *  待ちキューにつながれているタスクをすべて待ち解除する．待ち解除した
+ *  タスクからの返値は，E_DLTとする．待ち解除したタスクへのディスパッチ
+ *  が必要な場合はtrue，そうでない場合はfalseを返す．
+ */
+extern bool_t	init_wait_queue(QUEUE *p_wait_queue);
+
+#endif /* TOPPERS_WAIT_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/library/histogram.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/library/histogram.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/library/histogram.c	(revision 453)
@@ -0,0 +1,189 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2006-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		実行時間分布集計モジュール
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <test_lib.h>
+#include <histogram.h>
+#include "target_test.h"
+
+/*
+ *  実行時間分布計測の数
+ */
+#ifndef TNUM_HIST
+#define TNUM_HIST		10
+#endif /* TNUM_HIST */
+
+/*
+ *  ターゲット依存部で設定変更するためのマクロ
+ */
+#ifndef HISTTIM						/* 実行時間計測用の時刻のデータ型 */
+#define HISTTIM			SYSUTM
+#endif /* HISTTIM */
+
+#ifndef HIST_GET_TIM				/* 実行時間計測用の現在時刻の取得 */
+#ifndef TOPPERS_SUPPORT_GET_UTM
+#error get_utm is not supported.
+#endif /* TOPPERS_SUPPORT_GET_UTM */
+#define HIST_GET_TIM(p_time)	((void) get_utm(p_time))
+#endif /* HIST_GET_TIM */
+
+#ifndef HIST_CONV_TIM				/* 時刻の差から実行時間への変換 */
+#define HIST_CONV_TIM(time)		((uint_t)(time))
+#endif /* HIST_CONV_TIM */
+
+#ifndef HIST_BM_HOOK				/* 実行時間計測直前に行うべき処理 */
+#define HIST_BM_HOOK()			((void) 0)
+#endif
+
+/*
+ *  実行時間分布計測管理ブロック
+ */
+typedef struct histogram_control_block {
+	HISTTIM		begin_time;			/* 計測開始時刻 */
+	uint_t		maxval;				/* 分布を記録する最大時間 */
+	uint_t		*histarea;			/* 分布を記録するメモリ領域 */
+	uint_t		over;				/* 最大時間を超えた度数 */
+	uint_t		under;				/* 時間の逆転が疑われる度数 */
+} HISTCB;
+
+/*
+ *  実行時間分布計測管理ブロックのエリア
+ */
+static HISTCB	histcb_table[TNUM_HIST];
+
+/*
+ *  実行時間分布計測IDの最小値と最大値
+ */
+#define TMIN_HISTID		1
+#define TMAX_HISTID		(TMIN_HISTID + TNUM_HIST - 1)
+
+/*
+ *  実行時間分布計測の初期化
+ */
+void
+init_hist(ID histid, uint_t maxval, uint_t histarea[])
+{
+	HISTCB	*p_histcb;
+	uint_t	i;
+
+	assert(TMIN_HISTID <= histid && histid <= TMAX_HISTID);
+	p_histcb = &(histcb_table[histid - TMIN_HISTID]);
+
+	for (i = 0; i <= maxval; i++) {
+		histarea[i] = 0U;
+	}
+	p_histcb->maxval = maxval;
+	p_histcb->histarea = histarea;
+	p_histcb->over = 0U;
+	p_histcb->under = 0U;
+}
+
+/*
+ *  実行時間計測の開始
+ */
+void
+begin_measure(ID histid)
+{
+	HISTCB	*p_histcb;
+
+	assert(TMIN_HISTID <= histid && histid <= TMAX_HISTID);
+	p_histcb = &(histcb_table[histid - TMIN_HISTID]);
+
+	HIST_BM_HOOK();
+	HIST_GET_TIM(&(p_histcb->begin_time));
+}
+
+/*
+ *  実行時間計測の終了
+ */
+void
+end_measure(ID histid)
+{
+	HISTCB	*p_histcb;
+	HISTTIM	end_time;
+	uint_t	val;
+
+	HIST_GET_TIM(&end_time);
+
+	assert(TMIN_HISTID <= histid && histid <= TMAX_HISTID);
+	p_histcb = &(histcb_table[histid - TMIN_HISTID]);
+
+	val = HIST_CONV_TIM(end_time - p_histcb->begin_time);
+	if (val <= p_histcb->maxval) {
+		p_histcb->histarea[val]++;
+	}
+	else if (val <= ((uint_t) INT_MAX)) {
+		p_histcb->over++;
+	}
+	else {
+		p_histcb->under++;
+	}
+}
+
+/*
+ *  実行時間分布計測の表示
+ */
+void
+print_hist(ID histid)
+{
+	HISTCB	*p_histcb;
+	uint_t	i;
+
+	assert(TMIN_HISTID <= histid && histid <= TMAX_HISTID);
+	p_histcb = &(histcb_table[histid - TMIN_HISTID]);
+
+	for (i = 0; i <= p_histcb->maxval; i++) {
+		if (p_histcb->histarea[i] > 0) {
+			syslog_2(LOG_NOTICE, "%d : %d", i, p_histcb->histarea[i]);
+			syslog_flush();
+		}
+	}
+	if (p_histcb->over > 0) {
+		syslog_2(LOG_NOTICE, "> %d : %d", p_histcb->maxval, p_histcb->over);
+	}
+	if (p_histcb->under > 0) {
+		syslog_1(LOG_NOTICE, "> INT_MAX : %d", p_histcb->under);
+	}
+	syslog_flush();
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/library/log_output.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/library/log_output.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/library/log_output.c	(revision 453)
@@ -0,0 +1,200 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		システムログのフォーマット出力
+ */
+
+#include <t_stddef.h>
+#include <t_syslog.h>
+#include <log_output.h>
+
+/*
+ *  数値を文字列に変換
+ */
+#define CONVERT_BUFLEN	((sizeof(uintptr_t) * CHAR_BIT + 2) / 3)
+										/* uintptr_t型の数値の最大文字数 */
+static void
+convert(uintptr_t val, uint_t radix, const char *radchar,
+			uint_t width, bool_t minus, bool_t padzero, void (*putc)(char))
+{
+	char	buf[CONVERT_BUFLEN];
+	uint_t	i, j;
+
+	i = 0U;
+	do {
+		buf[i++] = radchar[val % radix];
+		val /= radix;
+	} while (i < CONVERT_BUFLEN && val != 0);
+
+	if (minus && width > 0) {
+		width -= 1;
+	}
+	if (minus && padzero) {
+		(*putc)('-');
+	}
+	for (j = i; j < width; j++) {
+		(*putc)(padzero ? '0' : ' ');
+	}
+	if (minus && !padzero) {
+		(*putc)('-');
+	}
+	while (i > 0U) {
+		(*putc)(buf[--i]);
+	}
+}
+
+/*
+ *  文字列整形出力
+ */
+static const char raddec[] = "0123456789";
+static const char radhex[] = "0123456789abcdef";
+static const char radHEX[] = "0123456789ABCDEF";
+
+void
+syslog_printf(const char *format, const intptr_t *p_args, void (*putc)(char))
+{
+	char		c;
+	uint_t		width;
+	bool_t		padzero;
+	intptr_t	val;
+	const char	*str;
+
+	while ((c = *format++) != '\0') {
+		if (c != '%') {
+			(*putc)(c);
+			continue;
+		}
+
+		width = 0U;
+		padzero = false;
+		if ((c = *format++) == '0') {
+			padzero = true;
+			c = *format++;
+		}
+		while ('0' <= c && c <= '9') {
+			width = width * 10U + c - '0';
+			c = *format++;
+		}
+		if (c == 'l') {
+			c = *format++;
+		}
+		switch (c) {
+		case 'd':
+			val = (intptr_t)(*p_args++);
+			if (val >= 0) {
+				convert((uintptr_t) val, 10U, raddec,
+										width, false, padzero, putc);
+			}
+			else {
+				convert((uintptr_t)(-val), 10U, raddec,
+										width, true, padzero, putc);
+			}
+			break;
+		case 'u':
+			val = (intptr_t)(*p_args++);
+			convert((uintptr_t) val, 10U, raddec, width, false, padzero, putc);
+			break;
+		case 'x':
+		case 'p':
+			val = (intptr_t)(*p_args++);
+			convert((uintptr_t) val, 16U, radhex, width, false, padzero, putc);
+			break;
+		case 'X':
+			val = (intptr_t)(*p_args++);
+			convert((uintptr_t) val, 16U, radHEX, width, false, padzero, putc);
+			break;
+		case 'c':
+			(*putc)((char)(intptr_t)(*p_args++));
+			break;
+		case 's':
+			str = (const char *)(*p_args++);
+			while ((c = *str++) != '\0') {
+				(*putc)(c);
+			}
+			break;
+		case '%':
+			(*putc)('%');
+			break;
+		case '\0':
+			format--;
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+/*
+ *  ログ情報の出力
+ */
+void
+syslog_print(const SYSLOG *p_syslog, void (*putc)(char))
+{
+	switch (p_syslog->logtype) {
+	case LOG_TYPE_COMMENT:
+		syslog_printf((const char *)(p_syslog->loginfo[0]),
+								&(p_syslog->loginfo[1]), putc);
+		break;
+	case LOG_TYPE_ASSERT:
+		syslog_printf("%s:%u: Assertion `%s' failed.",
+								&(p_syslog->loginfo[0]), putc);
+		break;
+	default:
+		/*
+		 *  他の種別のログ情報には対応していない．
+		 */
+		break;
+	}
+}
+
+/*
+ *  ログ情報喪失メッセージの出力
+ */
+void
+syslog_lostmsg(uint_t lostlog, void (*putc)(char))
+{
+	intptr_t	lostinfo[1];
+
+	lostinfo[0] = (intptr_t) lostlog;
+	syslog_printf("%d messages are lost.", lostinfo, putc);
+	(*putc)('\n');
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/library/strerror.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/library/strerror.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/library/strerror.c	(revision 453)
@@ -0,0 +1,110 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		エラーメッセージ文字列を返す関数
+ */
+
+#include <t_stddef.h>
+#include <t_stdlib.h>
+
+const char *
+itron_strerror(ER ercd)
+{
+	switch (MERCD(ercd)) {
+	case E_OK:
+		return("E_OK");
+
+	case E_SYS:
+		return("E_SYS");
+	case E_NOSPT:
+		return("E_NOSPT");
+	case E_RSFN:
+		return("E_RSFN");
+	case E_RSATR:
+		return("E_RSATR");
+
+	case E_PAR:
+		return("E_PAR");
+	case E_ID:
+		return("E_ID");
+
+	case E_CTX:
+		return("E_CTX");
+	case E_MACV:
+		return("E_MACV");
+	case E_OACV:
+		return("E_OACV");
+	case E_ILUSE:
+		return("E_ILUSE");
+
+	case E_NOMEM:
+		return("E_NOMEM");
+	case E_NOID:
+		return("E_NOID");
+	case E_NORES:
+		return("E_NORES");
+
+	case E_OBJ:
+		return("E_OBJ");
+	case E_NOEXS:
+		return("E_NOEXS");
+	case E_QOVR:
+		return("E_QOVR");
+
+	case E_RLWAI:
+		return("E_RLWAI");
+	case E_TMOUT:
+		return("E_TMOUT");
+	case E_DLT:
+		return("E_DLT");
+	case E_CLS:
+		return("E_CLS");
+
+	case E_WBLK:
+		return("E_WBLK");
+	case E_BOVR:
+		return("E_BOVR");
+
+	default:
+		return("unknown error");
+	}
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/library/t_perror.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/library/t_perror.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/library/t_perror.c	(revision 453)
@@ -0,0 +1,56 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2006 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		エラーメッセージの出力
+ */
+
+#include <t_stddef.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+
+void
+t_perror(uint_t prio, const char *file, int_t line, const char *expr, ER ercd)
+{
+	syslog_5(prio, "%s (%d) reported by `%s' in line %d of `%s'.",
+						itron_strerror(ercd), SERCD(ercd), expr, line, file);
+
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/library/test_lib.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/library/test_lib.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/library/test_lib.c	(revision 453)
@@ -0,0 +1,203 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2005-2013 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *		テストプログラム用ライブラリ
+ */
+
+#include <kernel.h>
+#include <sil.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <log_output.h>
+#include "syssvc/syslog.h"
+#include "target_syssvc.h"
+#include <test_lib.h>
+
+/*
+ *	チェックポイント
+ */
+static uint_t	check_count = 0u;
+
+/*
+ *	自己診断関数
+ */
+static BIT_FUNC	check_bit_func = NULL;
+
+/*
+ *	自己診断関数の設定
+ */
+void
+set_bit_func(BIT_FUNC bit_func)
+{
+	check_bit_func = bit_func;
+}
+
+/*
+ *  テストプログラムの開始
+ */
+void
+test_start(char *progname)
+{
+	syslog_1(LOG_NOTICE, "Test program: %s", progname);
+}
+
+/*
+ *  システムログの出力処理
+ */
+void
+syslog_flush(void)
+{
+	SYSLOG	logbuf;
+	ER_UINT	rercd;
+
+	/*
+	 *  ログバッファに記録されたログ情報を，低レベル出力機能を用いて出
+	 *  力する．
+	 */
+	while ((rercd = syslog_rea_log(&logbuf)) >= 0) {
+		if (rercd > 0) {
+			syslog_lostmsg((uint_t) rercd, target_fput_log);
+		}
+		if (logbuf.logtype >= LOG_TYPE_COMMENT) {
+			syslog_print(&logbuf, target_fput_log);
+			target_fput_log('\n');
+		}
+	}
+}
+
+/*
+ *	テストプログラムの終了
+ */
+void
+test_finish(void)
+{
+	SIL_PRE_LOC;
+
+	SIL_LOC_INT();
+	syslog_flush();
+	(void) ext_ker();
+
+	/* ここへ来ることはないはず */
+	SIL_UNL_INT();
+}
+
+/*
+ *	チェックポイント
+ */
+void
+check_point(uint_t count)
+{
+	bool_t	errorflag = false;
+	ER		rercd;
+	SIL_PRE_LOC;
+
+	/*
+	 *  割込みロック状態に
+	 */
+	SIL_LOC_INT();
+
+	/*
+	 *  シーケンスチェック
+	 */
+	if (++check_count == count) {
+		syslog_1(LOG_NOTICE, "Check point %d passed.", count);
+	}
+	else {
+		syslog_1(LOG_ERROR, "## Unexpected check point %d.", count);
+		errorflag = true;
+	}
+
+	/*
+	 *  カーネルの内部状態の検査
+	 */
+	if (check_bit_func != NULL) {
+		rercd = (*check_bit_func)();
+		if (rercd < 0) {
+			syslog_2(LOG_ERROR, "## Internal inconsistency detected (%s, %d).",
+								itron_strerror(rercd), SERCD(rercd));
+			errorflag = true;
+		}
+	}
+
+	/*
+	 *  エラーが検出された場合は，テストプログラムを終了する．
+	 */
+	if (errorflag) {
+		test_finish();
+	}
+
+	/*
+	 *  割込みロック状態を解除
+	 */
+	SIL_UNL_INT();
+}
+
+/*
+ *	完了チェックポイント
+ */
+void
+check_finish(uint_t count)
+{
+	check_point(count);
+	syslog_0(LOG_NOTICE, "All check points passed.");
+	test_finish();
+}
+
+/*
+ *	条件チェックのエラー処理
+ */
+void
+_check_assert(const char *expr, const char *file, int_t line)
+{
+	syslog_3(LOG_ERROR, "## Assertion `%s' failed at %s:%u.",
+								expr, file, line);
+	test_finish();
+}
+
+/*
+ *	エラーコードチェックのエラー処理
+ */
+void
+_check_ercd(ER ercd, const char *file, int_t line)
+{
+	syslog_3(LOG_ERROR, "## Unexpected error %s detected at %s:%u.",
+								itron_strerror(ercd), file, line);
+	test_finish();
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/library/vasyslog.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/library/vasyslog.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/library/vasyslog.c	(revision 453)
@@ -0,0 +1,111 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		可変数引数のシステムログライブラリ
+ */
+
+#include <t_stddef.h>
+#include <t_syslog.h>
+#include <stdarg.h>
+
+#ifndef TOPPERS_OMIT_SYSLOG
+
+void
+syslog(uint_t prio, const char *format, ...)
+{
+	SYSLOG	logbuf;
+	va_list	ap;
+	uint_t	i;
+	char	c;
+	bool_t	lflag;
+
+	logbuf.logtype = LOG_TYPE_COMMENT;
+	logbuf.loginfo[0] = (intptr_t) format;
+	i = 1U;
+	va_start(ap, format);
+
+	while ((c = *format++) != '\0' && i < TMAX_LOGINFO) {
+		if (c != '%') {
+			continue;
+		}
+
+		lflag = false;
+		c = *format++;
+		while ('0' <= c && c <= '9') {
+			c = *format++;
+		}
+		if (c == 'l') {
+			lflag = true;
+			c = *format++;
+		}
+		switch (c) {
+		case 'd':
+			logbuf.loginfo[i++] = lflag ? (intptr_t) va_arg(ap, long_t)
+										: (intptr_t) va_arg(ap, int_t);
+			break;
+		case 'u':
+		case 'x':
+		case 'X':
+			logbuf.loginfo[i++] = lflag ? (intptr_t) va_arg(ap, ulong_t)
+										: (intptr_t) va_arg(ap, uint_t);
+			break;
+		case 'p':
+			logbuf.loginfo[i++] = (intptr_t) va_arg(ap, void *);
+			break;
+		case 'c':
+			logbuf.loginfo[i++] = (intptr_t) va_arg(ap, int);
+			break;
+		case 's':
+			logbuf.loginfo[i++] = (intptr_t) va_arg(ap, const char *);
+			break;
+		case '\0':
+			format--;
+			break;
+		default:
+			break;
+		}
+	}
+	va_end(ap);
+	(void) syslog_wri_log(prio, &logbuf);
+}
+
+#endif /* TOPPERS_OMIT_SYSLOG */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/Makefile
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/Makefile	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/Makefile	(revision 453)
@@ -0,0 +1,593 @@
+#
+#  TOPPERS/ASP Kernel
+#      Toyohashi Open Platform for Embedded Real-Time Systems/
+#      Advanced Standard Profile Kernel
+# 
+#  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                              Toyohashi Univ. of Technology, JAPAN
+#  Copyright (C) 2006-2014 by Embedded and Real-Time Systems Laboratory
+#              Graduate School of Information Science, Nagoya Univ., JAPAN
+# 
+#  ä¸è¨èä½æ¨©è
+ã¯ï¼ä»¥ä¸ã®(1)ï½(4)ã®æ¡ä»¶ãæºããå ´åã«éãï¼æ¬ã½ããã¦ã§
+#  ã¢ï¼æ¬ã½ããã¦ã§ã¢ãæ¹å¤ãããã®ãå«ãï¼ä»¥ä¸åãï¼ãä½¿ç¨ã»è¤è£½ã»æ¹
+#  å¤ã»åé
+å¸ï¼ä»¥ä¸ï¼å©ç¨ã¨å¼ã¶ï¼ãããã¨ãç¡åã§è¨±è«¾ããï¼
+#  (1) æ¬ã½ããã¦ã§ã¢ãã½ã¼ã¹ã³ã¼ãã®å½¢ã§å©ç¨ããå ´åã«ã¯ï¼ä¸è¨ã®èä½
+#      æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãï¼ãã®ã¾ã¾ã®å½¢ã§ã½ã¼
+#      ã¹ã³ã¼ãä¸­ã«å«ã¾ãã¦ãããã¨ï¼
+#  (2) æ¬ã½ããã¦ã§ã¢ãï¼ã©ã¤ãã©ãªå½¢å¼ãªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨
+#      è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®èä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨
+#      ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#  (3) æ¬ã½ããã¦ã§ã¢ãï¼æ©å¨ã«çµã¿è¾¼ããªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããªãå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼æ¬¡ã®ããããã®æ¡ä»¶ãæºããã
+#      ã¨ï¼
+#    (a) åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®è
+#        ä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#    (b) åé
+å¸ã®å½¢æ
+ãï¼å¥ã«å®ããæ¹æ³ã«ãã£ã¦ï¼TOPPERSãã­ã¸ã§ã¯ãã«
+#        å ±åãããã¨ï¼
+#  (4) æ¬ã½ããã¦ã§ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæ
+#      å®³ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ããå
+è²¬ãããã¨ï¼
+#      ã¾ãï¼æ¬ã½ããã¦ã§ã¢ã®ã¦ã¼ã¶ã¾ãã¯ã¨ã³ãã¦ã¼ã¶ããã®ãããªãç
+#      ç±ã«åºã¥ãè«æ±ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ãã
+#      å
+è²¬ãããã¨ï¼
+# 
+#  æ¬ã½ããã¦ã§ã¢ã¯ï¼ç¡ä¿è¨¼ã§æä¾ããã¦ãããã®ã§ããï¼ä¸è¨èä½æ¨©è
+ã
+#  ãã³TOPPERSãã­ã¸ã§ã¯ãã¯ï¼æ¬ã½ããã¦ã§ã¢ã«é¢ãã¦ï¼ç¹å®ã®ä½¿ç¨ç®ç
+#  ã«å¯¾ããé©åæ§ãå«ãã¦ï¼ãããªãä¿è¨¼ãè¡ããªãï¼ã¾ãï¼æ¬ã½ããã¦ã§
+#  ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæå®³ã«é¢ãã¦ãï¼ã
+#  ã®è²¬ä»»ãè² ããªãï¼
+# 
+#  $Id$
+# 
+
+#
+#  ã¿ã¼ã²ããã®æå®ï¼Makefile.targetã§ä¸æ¸ããããã®ãé²ãããï¼
+#
+all:
+
+#
+#  ã¿ã¼ã²ããç¥ç§°ã®å®ç¾©
+#
+TARGET = @(TARGET)
+
+#
+#  ãã­ã°ã©ãã³ã°è¨èªã®å®ç¾©
+#
+SRCLANG = @(SRCLANG)
+ifeq ($(SRCLANG),c)
+  LIBS = -lc
+endif
+ifeq ($(SRCLANG),c++)
+  USE_CXX = true
+  CXXLIBS = -lstdc++ -lm -lc
+  CXXRTS = cxxrt.o newlibrt.o
+endif
+
+#
+#  ã½ã¼ã¹ãã¡ã¤ã«ã®ãã£ã¬ã¯ããªã®å®ç¾©
+#
+SRCDIR = @(SRCDIR)
+
+#
+#  ãªãã¸ã§ã¯ããã¡ã¤ã«åã®æ¡å¼µå­ã®è¨­å®
+#
+OBJEXT = @(OBJEXT)
+
+#
+#  å®è¡ç°å¢ã®å®ç¾©ï¼ã¿ã¼ã²ããä¾å­ã«ä¸æ¸ããããå ´åãããï¼
+#
+DBGENV := @(DBGENV)
+
+#
+#  ã«ã¼ãã«ã©ã¤ãã©ãªï¼libkernel.aï¼ã®ãã£ã¬ã¯ããªå
+#  ï¼ã«ã¼ãã«ã©ã¤ãã©ãªãmakeå¯¾è±¡ã«ããæã¯ï¼ç©ºã«å®ç¾©ããï¼
+#
+KERNEL_LIB = @(KERNEL_LIB)
+
+#
+#  ã«ã¼ãã«ãé¢æ°åä½ã§ã³ã³ãã¤ã«ãããã©ããã®å®ç¾©
+#
+KERNEL_FUNCOBJS = @(KERNEL_FUNCOBJS)
+
+#
+#  ãã¬ã¼ã¹ã­ã°ãåå¾ãããã©ããã®å®ç¾©
+#
+ENABLE_TRACE = @(ENABLE_TRACE)
+
+#
+#  ã¦ã¼ãã£ãªãã£ãã­ã°ã©ã ã®åç§°
+#
+PERL = @(PERL)
+CFG = @(CFG)
+
+#
+#  ãªãã¸ã§ã¯ããã¡ã¤ã«åã®å®ç¾©
+#
+OBJNAME = asp
+ifdef OBJEXT
+  OBJFILE = $(OBJNAME).$(OBJEXT)
+  CFG1_OUT = cfg1_out.$(OBJEXT)
+else
+  OBJFILE = $(OBJNAME)
+  CFG1_OUT = cfg1_out
+endif
+
+#
+#  ã¿ã¼ã²ããä¾å­é¨ã®ãã£ã¬ã¯ããªã®å®ç¾©
+#
+TARGETDIR = $(SRCDIR)/target/$(TARGET)
+
+#
+#  ã¿ã¼ã²ããä¾å­ã®å®ç¾©ã®ã¤ã³ã¯ã«ã¼ã
+#
+include $(TARGETDIR)/Makefile.target
+
+#
+#  ã³ã³ãã£ã®ã¥ã¬ã¼ã¿é¢ä¿ã®å¤æ°ã®å®ç¾©
+#
+CFG_TABS := --api-table $(SRCDIR)/kernel/kernel_api.csv \
+			--cfg1-def-table $(SRCDIR)/kernel/kernel_def.csv $(CFG_TABS)
+
+CFG_ASMOBJS := $(CFG_ASMOBJS)
+CFG_COBJS := kernel_cfg.o $(CFG_COBJS)
+CFG_OBJS := $(CFG_ASMOBJS) $(CFG_COBJS)
+CFG2_OUT_SRCS := kernel_cfg.h kernel_cfg.c $(CFG2_OUT_SRCS)
+
+#
+#  å
+±éã³ã³ãã¤ã«ãªãã·ã§ã³ã®å®ç¾©
+#
+COPTS := $(COPTS) -g @(COPTS)
+ifndef OMIT_WARNING_ALL
+  COPTS := $(COPTS) -Wall
+endif
+ifndef OMIT_OPTIMIZATION
+  COPTS := $(COPTS) -O2
+endif
+CDEFS := $(CDEFS) @(CDEFS)
+INCLUDES := -I. -I$(SRCDIR)/include -I$(SRCDIR)/arch -I$(SRCDIR) $(INCLUDES)
+LDFLAGS := $(LDFLAGS) @(LDFLAGS)
+CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) @(LDFLAGS)
+LIBS := $(LIBS) $(CXXLIBS)
+CFLAGS = $(COPTS) $(CDEFS) $(INCLUDES)
+
+#
+#  ã¢ããªã±ã¼ã·ã§ã³ãã­ã°ã©ã ã«é¢ããå®ç¾©
+#
+APPLNAME = @(APPLNAME)
+APPLDIR = @(APPLDIR)
+APPL_CFG = $(APPLNAME).cfg
+
+APPL_DIR = $(APPLDIR) $(SRCDIR)/library
+APPL_ASMOBJS =
+ifdef USE_CXX
+  APPL_CXXOBJS = $(APPLNAME).o @(APPLOBJS)
+  APPL_COBJS =
+else
+  APPL_COBJS = $(APPLNAME).o @(APPLOBJS)
+endif
+APPL_COBJS := $(APPL_COBJS) log_output.o vasyslog.o t_perror.o strerror.o
+APPL_CFLAGS =
+APPL_LIBS =
+ifdef APPLDIR
+  INCLUDES := $(INCLUDES) $(foreach dir,$(APPLDIR),-I$(dir))
+endif
+
+#  ããã«ã¦ã§ã¢ã® Makefile ã®ã¤ã³ã¯ã«ã¼ã
+#
+include @(SRCDIR)/monitor/Makefile.config
+
+#
+#  ã·ã¹ãã ãµã¼ãã¹ã«é¢ããå®ç¾©
+#
+SYSSVC_DIR := $(SYSSVC_DIR) $(SRCDIR)/syssvc $(SRCDIR)/library
+SYSSVC_ASMOBJS := $(SYSSVC_ASMOBJS)
+SYSSVC_COBJS := $(SYSSVC_COBJS) banner.o syslog.o serial.o logtask.o armv7m.o \
+				@(SYSSVCOBJS) $(CXXRTS)
+SYSSVC_CFLAGS := $(SYSSVC_CFLAGS)
+SYSSVC_LIBS := $(SYSSVC_LIBS)
+INCLUDES := $(INCLUDES)
+
+#
+#  ã«ã¼ãã«ã«é¢ããå®ç¾©
+#
+#  KERNEL_ASMOBJS: ã«ã¼ãã«ã©ã¤ãã©ãªã«å«ããï¼ã½ã¼ã¹ãã¢ã»ã³ããªè¨èªã®
+#				   ãªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#  KERNEL_COBJS: ã«ã¼ãã«ã®ã©ã¤ãã©ãªã«å«ããï¼ã½ã¼ã¹ãCè¨èªã§ï¼ã½ã¼ã¹
+#				 ãã¡ã¤ã«ã¨1å¯¾1ã«å¯¾å¿ãããªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#  KERNEL_LCSRCS: ã«ã¼ãã«ã®ã©ã¤ãã©ãªã«å«ããCè¨èªã®ã½ã¼ã¹ãã¡ã¤ã«ã§ï¼
+#				  1ã¤ã®ã½ã¼ã¹ãã¡ã¤ã«ããè¤æ°ã®ãªãã¸ã§ã¯ããã¡ã¤ã«ãç
+#				  æãããã®ï¼
+#  KERNEL_LCOBJS: ä¸ã®ã½ã¼ã¹ãã¡ã¤ã«ããçæããããªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#  KERNEL_AUX_COBJS: ã­ã¼ãã¢ã¸ã¥ã¼ã«ã«å«ããªããï¼ã«ã¼ãã«ã®ã½ã¼ã¹ãã¡
+#					 ã¤ã«ã¨åããªãã·ã§ã³ãé©ç¨ãã¦ã³ã³ãã¤ã«ãã¹ãï¼ã½ã¼
+#					 ã¹ãCè¨èªã®ãªãã¸ã§ã¯ããã¡ã¤ã«ï¼
+#
+KERNEL_DIR := $(KERNEL_DIR) $(SRCDIR)/kernel
+KERNEL_ASMOBJS := $(KERNEL_ASMOBJS)
+KERNEL_COBJS := $(KERNEL_COBJS)
+KERNEL_CFLAGS := $(KERNEL_CFLAGS) -I$(SRCDIR)/kernel
+ifdef OMIT_MAKEOFFSET
+  OFFSET_H =
+else
+  OFFSET_H = offset.h
+ifndef OFFSET_TF
+  KERNEL_AUX_COBJS := $(KERNEL_AUX_COBJS) makeoffset.o
+endif
+endif
+
+#
+#  ã¿ã¼ã²ãããã¡ã¤ã«ï¼è¤æ°ãåæã«é¸æãã¦ã¯ãªããªãï¼
+#
+all: $(OBJFILE)
+#all: $(OBJNAME).bin
+#all: $(OBJNAME).srec
+
+##### ä»¥ä¸ã¯ç·¨éããªããã¨ #####
+
+#
+#  ç°å¢ã«ä¾å­ããã³ã³ãã¤ã«ãªãã·ã§ã³ã®å®ç¾©
+#
+ifdef DBGENV
+  CDEFS := $(CDEFS) -D$(DBGENV)
+endif
+
+#
+#  ã«ã¼ãã«ã®ãã¡ã¤ã«æ§æã®å®ç¾©
+#
+include $(SRCDIR)/kernel/Makefile.kernel
+ifdef KERNEL_FUNCOBJS
+  KERNEL_LCSRCS := $(KERNEL_FCSRCS)
+  KERNEL_LCOBJS := $(foreach file,$(KERNEL_FCSRCS),$($(file:.c=)))
+else
+  KERNEL_CFLAGS := -DALLFUNC $(KERNEL_CFLAGS)
+  KERNEL_COBJS := $(KERNEL_COBJS) \
+					$(foreach file,$(KERNEL_FCSRCS),$(file:.c=.o))
+endif
+
+#
+#  ã½ã¼ã¹ãã¡ã¤ã«ã®ãããã£ã¬ã¯ããªã«é¢ããå®ç¾©
+#
+vpath %.c $(KERNEL_DIR) $(SYSSVC_DIR) $(APPL_DIR)
+vpath %.S $(KERNEL_DIR) $(SYSSVC_DIR) $(APPL_DIR)
+vpath %.cfg $(APPL_DIR)
+
+#
+#  ã³ã³ãã¤ã«ã®ããã®å¤æ°ã®å®ç¾©
+#
+KERNEL_LIB_OBJS = $(KERNEL_ASMOBJS) $(KERNEL_COBJS) $(KERNEL_LCOBJS)
+SYSSVC_OBJS = $(SYSSVC_ASMOBJS) $(SYSSVC_COBJS)
+APPL_OBJS = $(APPL_ASMOBJS) $(APPL_COBJS) $(APPL_CXXOBJS)
+ALL_OBJS = $(START_OBJS) $(APPL_OBJS) $(SYSSVC_OBJS) $(CFG_OBJS) \
+											$(END_OBJS) $(HIDDEN_OBJS)
+ifdef KERNEL_LIB
+  ALL_LIBS = $(APPL_LIBS) $(SYSSVC_LIBS) -lkernel $(LIBS)
+  LIBS_DEP = $(filter %.a,$(ALL_LIBS)) $(KERNEL_LIB)/libkernel.a
+  LDFLAGS := $(LDFLAGS) -L$(KERNEL_LIB)
+  REALCLEAN_FILES := libkernel.a $(REALCLEAN_FILES)
+else
+  ALL_LIBS = $(APPL_LIBS) $(SYSSVC_LIBS) libkernel.a $(LIBS)
+  LIBS_DEP = $(filter %.a,$(ALL_LIBS))
+endif
+
+ifdef TEXT_START_ADDRESS
+  LDFLAGS := $(LDFLAGS) -Wl,-Ttext,$(TEXT_START_ADDRESS)
+  CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) -Wl,-Ttext,$(TEXT_START_ADDRESS)
+endif
+ifdef DATA_START_ADDRESS
+  LDFLAGS := $(LDFLAGS) -Wl,-Tdata,$(DATA_START_ADDRESS)
+  CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) -Wl,-Tdata,$(DATA_START_ADDRESS)
+endif
+ifdef LDSCRIPT
+  LDFLAGS := $(LDFLAGS) -Wl,-T,$(LDSCRIPT)
+  CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) -Wl,-T,$(LDSCRIPT)
+endif
+
+#
+#  ãªãã»ãããã¡ã¤ã«ï¼offset.hï¼ã®çæè¦å
+#
+ifdef OFFSET_TF
+offset.h: $(APPL_CFG) kernel_cfg.timestamp
+	$(CFG) --pass 3 --kernel asp $(INCLUDES) \
+				--rom-image cfg1_out.srec --symbol-table cfg1_out.syms \
+				-T $(OFFSET_TF) $(CFG_TABS) $<
+else
+offset.h: makeoffset.s $(SRCDIR)/utils/genoffset
+	$(PERL) $(SRCDIR)/utils/genoffset makeoffset.s > offset.h
+endif
+
+#
+#  ã«ã¼ãã«ã®ã³ã³ãã£ã®ã¥ã¬ã¼ã·ã§ã³ãã¡ã¤ã«ã®çæ
+#
+cfg1_out.c: $(APPL_CFG)
+	$(CFG) --pass 1 --kernel asp $(INCLUDES) $(CFG_TABS) $<
+
+$(CFG2_OUT_SRCS): kernel_cfg.timestamp
+kernel_cfg.timestamp: $(APPL_CFG) \
+						$(START_OBJS) cfg1_out.o $(END_OBJS) $(HIDDEN_OBJS)
+	$(LINK) $(CFLAGS) $(CFG1_OUT_LDFLAGS) -o $(CFG1_OUT) \
+						$(START_OBJS) cfg1_out.o $(END_OBJS)
+	$(NM) -n $(CFG1_OUT) > cfg1_out.syms
+	$(OBJCOPY) -O srec -S $(CFG1_OUT) cfg1_out.srec
+	$(CFG) --pass 2 --kernel asp $(INCLUDES) \
+				-T $(TARGETDIR)/target.tf $(CFG_TABS) $<
+	touch -r kernel_cfg.c kernel_cfg.timestamp
+
+#
+#  ã«ã¼ãã«ã©ã¤ãã©ãªãã¡ã¤ã«ã®çæ
+#
+libkernel.a: $(OFFSET_H) $(KERNEL_LIB_OBJS)
+	rm -f libkernel.a
+	$(AR) -rcs libkernel.a $(KERNEL_LIB_OBJS)
+	$(RANLIB) libkernel.a
+
+#
+#  ç¹å¥ãªä¾å­é¢ä¿ã®å®ç¾©
+#
+banner.o: kernel_cfg.timestamp $(filter-out banner.o,$(ALL_OBJS)) $(LIBS_DEP)
+
+#
+#  å
+¨ä½ã®ãªã³ã¯
+#
+$(OBJFILE): $(APPL_CFG) kernel_cfg.timestamp $(ALL_OBJS) $(LIBS_DEP)
+	$(LINK) $(CFLAGS) $(LDFLAGS) -o $(OBJFILE) $(START_OBJS) \
+			$(APPL_OBJS) $(SYSSVC_OBJS) $(CFG_OBJS) $(ALL_LIBS) $(END_OBJS)
+	$(NM) -n $(OBJFILE) > $(OBJNAME).syms
+	$(OBJCOPY) -O srec -S $(OBJFILE) $(OBJNAME).srec
+	$(CFG) --pass 3 --kernel asp $(INCLUDES) \
+				--rom-image $(OBJNAME).srec --symbol-table $(OBJNAME).syms \
+				-T $(TARGETDIR)/target_check.tf $(CFG_TABS) $<
+
+#
+#  ãã¤ããªãã¡ã¤ã«ã®çæ
+#
+$(OBJNAME).bin: $(OBJFILE)
+	$(OBJCOPY) -O binary -S $(OBJFILE) $(OBJNAME).bin
+
+#
+#  Sã¬ã³ã¼ããã¡ã¤ã«ã®çæ
+#
+$(OBJNAME).srec: $(OBJFILE)
+	$(OBJCOPY) -O srec -S $(OBJFILE) $(OBJNAME).srec
+
+#
+#  ã³ã³ãã¤ã«çµæã®æ¶å»
+#
+.PHONY: clean
+clean:
+	rm -f \#* *~ *.o $(CLEAN_FILES)
+	rm -f $(OBJFILE) $(OBJNAME).syms $(OBJNAME).srec $(OBJNAME).bin
+	rm -f kernel_cfg.timestamp $(CFG2_OUT_SRCS)
+	rm -f cfg1_out.c $(CFG1_OUT) cfg1_out.syms cfg1_out.srec
+ifndef KERNEL_LIB
+	rm -f libkernel.a
+endif
+	rm -f makeoffset.s offset.h
+
+.PHONY: cleankernel
+cleankernel:
+	rm -rf $(KERNEL_LIB_OBJS)
+	rm -f makeoffset.s offset.h
+
+.PHONY: cleandep
+cleandep:
+	if ! [ -f Makefile.depend ]; then \
+		rm -f kernel_cfg.timestamp $(CFG2_OUT_SRCS); \
+		rm -f cfg1_out.c cfg1_out.o $(CFG1_OUT) cfg1_out.syms cfg1_out.srec; \
+		rm -f makeoffset.s offset.h; \
+	fi
+	rm -f Makefile.depend
+
+.PHONY: realclean
+realclean: cleandep clean
+	rm -f $(REALCLEAN_FILES)
+
+#
+#  ã³ã³ãã£ã®ã¥ã¬ã¼ã¿ãçæãããã¡ã¤ã«ã®ã³ã³ãã¤ã«ã«ã¼ã«ã¨ä¾å­é¢ä¿ä½æ
+#  ã«ã¼ã«ã®å®ç¾©
+#
+#  ã³ã³ãã£ã®ã¥ã¬ã¼ã¿ãçæãããã¡ã¤ã«ã¯ï¼ã¢ããªã±ã¼ã·ã§ã³ãã­ã°ã©ã ç¨ï¼
+#  ã·ã¹ãã ãµã¼ãã¹ç¨ï¼ã«ã¼ãã«ç¨ã®ãã¹ã¦ã®ãªãã·ã§ã³ãä»ãã¦ã³ã³ãã¤ã«
+#  ããï¼
+#
+ALL_CFG_COBJS = $(CFG_COBJS) cfg1_out.o
+ALL_CFG_ASMOBJS = $(CFG_ASMOBJS)
+CFG_CFLAGS = $(APPL_CFLAGS) $(SYSSVC_CFLAGS) $(KERNEL_CFLAGS)
+
+$(ALL_CFG_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(CFG_CFLAGS) $<
+
+$(ALL_CFG_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(CFG_CFLAGS) $<
+
+$(ALL_CFG_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(CFG_CFLAGS)" $< >> Makefile.depend
+
+$(ALL_CFG_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(CFG_CFLAGS) $<
+
+$(ALL_CFG_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(CFG_CFLAGS)" $< >> Makefile.depend
+
+#
+#  ç¹æ®ãªä¾å­é¢ä¿ä½æã«ã¼ã«ã®å®ç¾©
+#
+cfg1_out.depend: $(APPL_CFG)
+	@$(CFG) -M cfg1_out.c $(INCLUDES) $< >> Makefile.depend
+
+makeoffset.d: makeoffset.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-T "makeoffset.s" -O "$(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+#
+#  ä¾å­é¢ä¿ãã¡ã¤ã«ã®çæ
+#
+.PHONY: gendepend
+gendepend:
+	@echo "Generating Makefile.depend."
+
+.PHONY: depend
+ifdef KERNEL_LIB
+depend: cleandep kernel_cfg.timestamp gendepend \
+		cfg1_out.depend cfg1_out.d \
+		$(ALL_OBJS:.o=.d)
+else
+depend: cleandep $(OFFSET_H) kernel_cfg.timestamp gendepend \
+		cfg1_out.depend cfg1_out.d \
+		$(KERNEL_AUX_COBJS:.o=.d) $(KERNEL_ASMOBJS:.o=.d) \
+		$(KERNEL_COBJS:.o=.d) $(KERNEL_LCSRCS:.c=.d) $(ALL_OBJS:.o=.d)
+endif
+
+#
+#  ä¾å­é¢ä¿ãã¡ã¤ã«ãã¤ã³ã¯ã«ã¼ã
+#
+-include Makefile.depend
+
+#
+#  éçºãã¼ã«ã®ã³ãã³ãåã®å®ç¾©
+#
+ifeq ($(TOOL),gcc)
+  #
+  #  GNUéçºç°å¢ç¨
+  #
+  ifdef GCC_TARGET
+    GCC_TARGET_PREFIX = $(GCC_TARGET)-
+  else
+    GCC_TARGET_PREFIX =
+  endif
+  CC = $(GCC_TARGET_PREFIX)gcc
+  CXX = $(GCC_TARGET_PREFIX)g++
+  AS = $(GCC_TARGET_PREFIX)as
+  LD = $(GCC_TARGET_PREFIX)ld
+  AR = $(GCC_TARGET_PREFIX)ar
+  NM = $(GCC_TARGET_PREFIX)nm
+  RANLIB = $(GCC_TARGET_PREFIX)ranlib
+  OBJCOPY = $(GCC_TARGET_PREFIX)objcopy
+  OBJDUMP = $(GCC_TARGET_PREFIX)objdump
+endif
+
+ifdef USE_CXX
+  LINK = $(CXX)
+else
+  LINK = $(CC)
+endif
+
+#
+#  ã³ã³ãã¤ã«ã«ã¼ã«ã®å®ç¾©
+#
+KERNEL_ALL_COBJS = $(KERNEL_COBJS) $(KERNEL_AUX_COBJS)
+
+$(KERNEL_ALL_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_ALL_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_LCOBJS): %.o:
+	$(CC) -DTOPPERS_$(*F) -o $@ -c $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_LCOBJS:.o=.s): %.s:
+	$(CC) -DTOPPERS_$(*F) -o $@ -S $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(SYSSVC_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(SYSSVC_CFLAGS) $<
+
+$(SYSSVC_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(SYSSVC_CFLAGS) $<
+
+$(SYSSVC_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(SYSSVC_CFLAGS) $<
+
+$(APPL_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_CXXOBJS): %.o: %.cpp
+	$(CXX) -c $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_CXXOBJS:.o=.s): %.s: %.cpp
+	$(CXX) -S $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(APPL_CFLAGS) $<
+
+#
+#  ä¾å­é¢ä¿ä½æã«ã¼ã«ã®å®ç¾©
+#
+$(KERNEL_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+$(KERNEL_LCSRCS:.c=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) -T "$($*)" \
+		-O "-DALLFUNC $(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+$(KERNEL_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+$(SYSSVC_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(SYSSVC_CFLAGS)" $< >> Makefile.depend
+
+$(SYSSVC_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(SYSSVC_CFLAGS)" $< >> Makefile.depend
+
+$(APPL_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(APPL_CFLAGS)" $< >> Makefile.depend
+
+$(APPL_CXXOBJS:.o=.d): %.d: %.cpp
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CXX) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(APPL_CFLAGS)" $< >> Makefile.depend
+
+$(APPL_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(APPL_CFLAGS)" $< >> Makefile.depend
+
+#
+#  ããã©ã«ãã³ã³ãã¤ã«ã«ã¼ã«ãä¸æ¸ã
+#
+%.o: %.c
+	@echo "*** Default compile rules should not be used."
+	$(CC) -c $(CFLAGS) $<
+
+%.s: %.c
+	@echo "*** Default compile rules should not be used."
+	$(CC) -S $(CFLAGS) $<
+
+%.o: %.cpp
+	@echo "*** Default compile rules should not be used."
+	$(CXX) -c $(CFLAGS) $<
+
+%.s: %.cpp
+	@echo "*** Default compile rules should not be used."
+	$(CXX) -S $(CFLAGS) $<
+
+%.o: %.S
+	@echo "*** Default compile rules should not be used."
+	$(CC) -c $(CFLAGS) $<
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/Makefile.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/Makefile.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/Makefile.config	(revision 453)
@@ -0,0 +1,57 @@
+#
+#   TOPPERS/ASP Kernel
+#       Toyohashi Open Platform for Embedded Real-Time Systems/
+#       Advanced Standard Profile Kernel
+#
+#   Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                               Toyohashi Univ. of Technology, JAPAN
+#   Copyright (C) 2003-2008 by Ryosuke Takeuchi
+#                Platform Development Center RICOH COMPANY,LTD. JAPAN
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+ 
+#
+#  Makefile のプロセッサ依存 (monitor用)
+#
+
+#
+#  コンパイルオプション
+#
+INCLUDES	:= $(INCLUDES) -I$(SRCDIR)/monitor -I$(SRCDIR)/kernel
+LDFLAGS := $(LDFLAGS) -Wl,--wrap=fflush
+
+#
+#  モニターに関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR):$(SRCDIR)/monitor:$(SRCDIR)/monitor/arch:$(SRCDIR)/monitor/stdio
+SYSSVC_COBJS := $(SYSSVC_COBJS) task_expansion.o monitor.o stddev.o \
+	      printf.o sprintf.o fprintf.o scanf.o sscanf.o
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/README.txt
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/README.txt	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/README.txt	(revision 453)
@@ -0,0 +1,374 @@
+
+        ＝ TOPPERS/JSPカーネル ユーザズマニュアル ＝
+      （monitor、netDeviceの説明、newlib標準入出力の対応）
+
+        （Release 1.4.3 対応，最終更新: 11-27-2010）
+
+------------------------------------------------------------------------
+ TOPPERS/JSP Kernel
+     Toyohashi Open Platform for Embedded Real-Time Systems/
+     Just Standard Profile Kernel
+
+ Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+                             Toyohashi Univ. of Technology, JAPAN
+ Copyright (C) 2003-2004 by Takagi Nobuhisa
+ Copyright (C) 2003-2010 by Ryosuke Takeuchi
+                     GJ Business Division RICOH COMPANY,LTD. JAPAN
+
+ 上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+ によって公表されている GNU General Public License の Version 2 に記
+ 述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+ を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ 利用と呼ぶ）することを無償で許諾する．
+ (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+     権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+     スコード中に含まれていること．
+ (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+     用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+     者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+     の無保証規定を掲載すること．
+ (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+     用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+     と．
+   (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+       作権表示，この利用条件および下記の無保証規定を掲載すること．
+   (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+       報告すること．
+ (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+     害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+
+ 本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+ 含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+ 接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+------------------------------------------------------------------------
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+１．monitorについて
+
+１－１．解説
+本モニタは、TOPPERSプロジェクト教育ＷＧの実装教育用に作成されたプログラム
+です。TOPPERS/JSP1.4.1上でタスクとして実行します。実行確認は以下の４つの
+環境環境で実行確認を行っています。
+１）m16c(OAKS16-miniとOAKS16)   ルネサステクノロジ製TM
+２）h8(AKIH8-3048,AKIH8-3069F)  PizzaFactory2+GNU(h8300-hms)
+                                cygwin+GNU(h8300-hms)
+３）sh2(hsb7616it)              cygwin+GNU(sh-hitachi-elf)
+
+１－２．コンソールの指定
+タスクモニタのコンソールは通常はシリアルデバイスを対象としています。
+MONTSK(タスクモニタのタスク)の起動の引数で渡されるexinfの値をモニタの
+通信出力デバイスとしています。但し、netDeviceのサーバとして起動する場合
+コンソールはWindows上のnetTermとなります。
+
+１－３．コンパイルスイッチ
+タスクモニタのビルドで実行機能を指定するコンパイルスイッチについて説明します。
+
+１）MONITOR_PORTID
+モニタのデフォルトポートはシリアルコンソール（CONSOLE_PORTID）ですが、
+モニタの起動コンソールを変更したい場合、コンパイルスイッチに
+-DMONITOR_PORTID=nを指定すると変更が可能です。このとき、指定ポートのオープンは
+モニタの起動時に行います。(Ver1.1.0のNEED_OPENのスイッチは削除します)
+
+２）SUPPORT_PIPE
+このスイッチを定義すると、外付けのコマンドを拡張します。
+外付けコマンドは第1コマンド"PIPE"で起動します。
+外付けコマンドの連絡関数はpipe_command(B *command);で設定してください。
+
+３）SUPPORT_ETHER
+TINETのコマンドサービス及びnetDeviceのコマンド拡張を行います。
+このコマンドは第1コマンド"NET"で起動します。
+
+４）START_TASKID
+netDEviceの接続時、自動実行するタスク番号を指定します。
+-DSTART_TASKID=1
+のように指定すると、netDeviceの接続後、教材のプログラムが自動的に実行します。
+
+５）NEED_MONITOR
+このコンパイルスイッチを指定すると、モニタの起動時にneed_monitor()関数を呼び
+出します。この関数の戻り値がFALSEの場合、モニタタスクを終了します。
+
+６）MONITOR_DELAY
+このコンパイルスイッチが指定された場合、モニタの起動時、コンソールの出力を
+MONITOR_DELAY(ms)待ちを行った後で行います。
+
+１－４．TOPPERS/JSPの実装拡張について
+タスクモニタの以下の機能を実現するためにTOPPERS/JSPの実装依存configに
+いくつかの改造が必要です。
+
+１）_kernel_break_waitの定義の追加(必須)
+JSPカーネルのサービスコールでの待ち状態の判定のために、_kernel_break_wait
+ラベルをサービスコールの待ちプログラム位置に定義する必要があります。
+サービスコールの待ちプログラム位置は通常各ＣＰＵのcpu_support.Sの何れかの
+位置にあります。
+
+２）iana_tskのリンクポイントの設定（必須ではない）
+タスクモニタでは各タスクの実行履歴をdispatchのタスク切り替え時にiana_tsk
+関数を呼び出すことで情報収集を行っています。そのためiana_tskの呼び出しに
+より、スイッチング時間が大きく低下します。しかし、"log task"コマンドによる
+タスク情報はリアルタイムシステムの検証には有用な手段です。
+通常はコンパイルスイッチMONにより、取り外し可能とし、必要のない場合は
+取り外して、使用してください。
+dispatch関数は通常各ＣＰＵのcpu_support.S中にあります。
+
+１－５．タスクモニタのマニュアル
+１）displayコマンド
+display byte [<start address> [<end address>]]
+        <start address>から<end address>までのメモリまたはポート領域を
+        １バイト単位に表示する。<end address>を省略した場合は128バイトの
+        表示を行う。<start adress>を省略した場合は、前回表示を行った次の
+        アドレスから表示を行う。
+
+display half [<start address> [<end address>]]
+        <start address>から<end address>までのメモリまたはポート領域を
+        ２バイト単位に表示する。<end address>を省略した場合は128バイトの
+        表示を行う。<start adress>を省略した場合は、前回表示を行った次の
+        アドレスから表示を行う。
+
+display word [<start address> [<end address>]]
+        <start address>から<end address>までのメモリまたはポート領域を
+        ４バイト単位に表示する。<end address>を省略した場合は128バイトの
+        表示を行う。<start adress>を省略した場合は、前回表示を行った次の
+        アドレスから表示を行う。
+
+display task
+        登録されたタスクの内容を表示する。表示内容は以下の通り。
+        cur     	カレントタスクに*、モニタタスクはmonを表示する。
+        id          タスクIDを表示する。
+        pri         初期値のタスク優先度
+        state       タスクの状態
+        pc          RUN状態以外なら、現在のプログラムカウンタ値
+        stack       現在のスタックアドレス
+        inistack    初期値スタックの先頭アドレス
+        inisize     初期値スタックのバイトサイズ
+
+diaplay register
+        カレントタスクが待ち状態となった場合、待ち状態のレジスタの内容を
+        表示する。サービスコール中の待ちではレジスタの保存を行わない為、
+        レジスタの表示は行わない。レジスタの内容はCPUによって異なる。
+
+２）setコマンド
+set byte [<start address>]
+        <start address>の内容を１バイト表示し入力待ちとなる。１６進数入力後
+        <RETURN>にてバイト値を入力すると<start address>に値を書込み後、
+        <start address>の内容を再表示し<start address>+1の内容の入力待ちとなる
+        .<RETURN>にてsetコマンドを終了しプロンプト表示に戻る。<start address>
+        を省略した場合、最後に書込んだ次のアドレスの書込みを行う。
+
+set half [<start address>]
+        <start address>の内容を２バイト表示し入力待ちとなる。１６進数入力後
+        <RETURN>にてバイト値を入力すると<start address>に値を書込み後、
+        <start address>の内容を再表示し<start address>+2の内容の入力待ちとなる
+        .<RETURN>にてsetコマンドを終了しプロンプト表示に戻る。<start address>
+        を省略した場合、最後に書込んだ次のアドレスの書込みを行う。
+
+set ward [<start address>]
+        <start address>の内容を２バイト表示し入力待ちとなる。１６進数入力後
+        <RETURN>にてバイト値を入力すると<start address>に値を書込み後、
+        <start address>の内容を再表示し<start address>+2の内容の入力待ちとなる
+        .<RETURN>にてsetコマンドを終了しプロンプト表示に戻る。<start address>
+        を省略した場合、最後に書込んだ次のアドレスの書込みを行う。
+
+set command [<mode>]
+        コマンドモードを設定する。モードは１(1コマンド)、２(2コマンド)モードで
+        デフォルトは２コマンドモード(例：displayとbyteの２つのコマンドで
+        コマンド設定を行う)である。１コマンドは２コマンドの先頭の1文字を組み合
+        わせた１つのコマンドでコマンド設定を行う。(例：display byteではdb)
+        <mode>を省略すると現在のコマンドモードの表示を行う。
+        ２コマンドモードでも、コマンドの最初の1文字の入力で実行可能である。
+        (例：display byteでは d b)
+
+set serial [<portid>]
+        タスクモニタの入出力対応のシリアルのポート番号を<porid>で変更する
+        <portid>を省略すると現在のポート番号を表示する。
+
+set task [<task id>]
+        <task id>で指定したタスクにカレントタスクを変更する。
+        <task id>を省略するとモニタタスクをカレントタスクに設定する。
+
+３）taskコマンド
+task activate
+        カレントタスクにact_tsk(<カレントタスクID>)サービスコールを発行する。
+
+task terminate
+        カレントタスクにter_tsk(<カレントタスクID>)サービスコールを発行する。
+
+task suspend
+        カレントタスクにsus_tsk(<カレントタスクID>)サービスコールを発行する。
+
+task resume
+        カレントタスクにrsm_tsk(<カレントタスクID>)サービスコールを発行する。
+
+task priority [pir]
+        カレントタスクにchg_tsk(<カレントタスクID>, <pri>)サービスコールを
+        発行する。
+
+４）logコマンド
+log mode [<logmask> [<lowmask>]]
+        syslogの表示モードを変更する。<logmask>と<lowmask>を省略した場合
+        現在の<logmask>と<lowmask>を表示する。設定値のマスクの対応は
+        以下の通りである。
+        <マスク>   <設定値>
+        LOG_EMERG     0     シャットダウンに値するエラー:lowmask default
+        LOG_ALERT     1
+        LOG_CRIT      2
+        LOG_ERROR     3     システムエラー
+        LOG_WARNING   4     警告メッセージ
+        LOG_NOTICE    5                                 :logmask default
+        LOG_INFO      6
+        LOG_DEBUG     7     デバッグ用メッセージ
+        logmask defaultとlowmask defaultは電源RTOS起動後のデフォルト値
+
+log task [<cycle time>]
+        <cycle time>ms周期に各タスクの前周期からのタスクの実行時間を表示する。
+        <cycle time>を省略した場合、前回のlog task表示からの各タスクの
+        実行時間を表示する。
+
+log port [<no> <logno> [<portaddress>]]
+        ポートモニタ機能の設定。<portaddress>を設定した場合<portaddress>が
+        アクセスされるたびに<logno>にてアクセスデータをsyslogにてログ表示
+        する。
+         <no> <logno> <portaddress>の設定にて<portaddress>を<no>にlogmaskを
+         <logno>にてポートモニタの設定を行う。但し、<logno>は1以上7までの値。
+         <no> <0>の設定にてポートモニタの解除を行う。
+         引数を省略すると、ポートモニタの登録状態の表示を行う。
+
+５）volumeコマンド
+TINETが有効であり、SUPPORT_VOLUMEコンパイルスイッチが有効の場合のみ使用可能な
+コマンドである。
+volume format <drive>
+         <drive>に対してフォーマットを行う。
+
+volume dir  [<path>]
+         <path>のディレクトリを表示する。<path>を省略した場合、デフォルト
+         deriveのディレクトリを表示する。
+
+volume mkdir <path>
+         <path>で指定したディレクトリを作成する。
+
+volume rmdir <path>
+         <path>で指定したディレクトリを削除する。
+
+volume erase <path>
+         <path>で指定したファイルを削除する。
+
+６）pipeコマンド
+SUPPORT_PIPEコンパイルスイッチが有効で、拡張コマンドが用意されている場合のみ
+有効なコマンドであり、コマンド仕様は拡張されたユーザ設定コマンドの仕様に
+従う、セカンドコマンドがユーザ設定コマンドとなる。
+
+７）helpコマンド
+モニタコマンドのヘルプ情報を表示する。
+
+２．モニタの入出力に関して
+モニタのデータ取り込みは、(FILE*)mon_infileに対するデータ取り込みを行う
+モニタのデータ送信は、標準入出力の出力ファイル(stdout)に対して行う。
+
+
+３．標準入出力の対応
+
+３－１．解説
+標準入出力はnewlib版と簡易版を選択できます。
+newlib版は簡易版に比べ、H8のサイズで32KBほど大きくなります。
+状況に応じて、選択してください。
+newlib版はh8の環境のみ実行確認を行っています。他の環境では
+実行確認を行っていません。
+
+
+３－２．簡易版標準入出力
+monitorデレクトリィ中の以下のファイルを使用します
+　stdio.h　　（newlib中のstdio.hに優先して参照する）
+  printf.c　　(printf文)
+  sprintf.c   (sprintf文)
+サポートしている標準入出力関数はstdio.hを参照してください
+また、printf関数やsprintf関数がlibc.aに優先してリンクされるように
+ライブラリィより前に、printf.oとsprintf.oを取り込むようにしてください。
+また、OAKS16用の開発環境TMで使用する場合はstdio.hを削除しMTOOLの
+stdio.hを使用するようにしてください。
+
+３－３．newlib版標準入出力
+monitorデレクトリィ中のstdio.h、stddev.c、printf.c、sprintf.cを参照しない
+ように、これらのファイルを削除してください。
+また、monitor/Makefile.config中からstddev.o、printf.o、sprintf.oをビルド時
+にリンクしないように削除してください。
+newlib中の標準入出力は、putcharやputcのような一文字出力関数は\n(改行)コードが
+ないと表示を行いません。また、printfやputsのような文字列出力関数は\nコードが
+付けられて出力されます。
+putcharやputcの対応を行うには、初期化としてバッファのない指定を行えば
+解決できます。この教材ではnewlibrc.cを改造し、タスクモニタの初期化時、
+setbuf(stdio, 0);関数にて、出力バッファなしの指定を行っています。
+タスクモニタを使用しない場合は、setbufの設定を自分で行ってください。
+printfやputsのような文字列の出力関数に関しては、newlib中のputs.cを
+修正することにより、これを回避することが出来ます。
+詳細は３．newlibの改造を参照してください。
+
+ライブラリィのビルド手順は以下の通りです。
+/home/roi/gnuにnewlibの凍結ファイルをコピーし
+gnu>tar zxvf newlib-1.11.0.tar.gz
+gnu>mkdir /usr/local/h8300-hms
+gnu>mkdir newlib-objdir
+gnu>cd newlib-objdir
+gnu>export TARGET_CFLAGS=-DREENTRANT_SYSCALLS_PROVIDED
+gnu>/home/roi/gnu/newlib-1.11.0/configure --target=h8300-hms --prefix=/usr/local/h8300-hms
+gnu>make
+gnu>make install
+
+アプリケーションのビルド時、標準入出力用の実装部として改造した
+systask/newlibrt.cをリンクする必要があります。
+
+
+３－４．newlibの改造(newlib-1.11.0/newlib/libc/stdio/)
+puts.cの修正部
+/*
+ * Write the given string to stdout, appending a newline.
+ */
+
+int
+_DEFUN (_puts_r, (ptr, s),
+	struct _reent *ptr _AND
+	_CONST char * s)
+{
+  size_t c = strlen (s);
+  struct __suio uio;
+  struct __siov iov[2];
+
+  iov[0].iov_base = s;
+  iov[0].iov_len = c;
+#if 0	/* TOPPERS.JSP */
+  iov[1].iov_base = "\n";
+#else	/* TOPPERS.JSP */
+  iov[1].iov_base = "\0";
+#endif	/* TOPPERS.JSP */
+  iov[1].iov_len = 1;
+  uio.uio_resid = c + 1;
+  uio.uio_iov = &iov[0];
+  uio.uio_iovcnt = 2;
+
+  _REENT_SMALL_CHECK_INIT(_stdout_r (ptr));
+  return (__sfvwrite (_stdout_r (ptr), &uio) ? EOF : '\n');
+}
+
+
+また、標準入出力用のローレベル関数はsystask/newlibrt.cに記載してあります。
+既存のnewlibrt.cはnewlib用のC言語ライブラリィとC++言語ライブラリィと
+初期化プログラムがいっしょに記述してありましたので以下の２つのソースに
+分けました。newlibの標準入出力を使用する場合は新しいnewlibrt.cを
+プログラムのビルド時にリンクするようにしてください。
+・新しいnewlibrt.c：C言語用のnewlibライブラリィのTOPPERSとのI/F部
+・cpplibrt.c：C++言語用の関数と初期化プログラム
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/arch/armv4.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/arch/armv4.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/arch/armv4.c	(revision 453)
@@ -0,0 +1,311 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2003-2008 by Ryosuke Takeuchi
+ *                     GJ Business Division RICOH COMPANY,LTD. JAPAN
+ * 
+ *  上記著作権者は，Free Software Foundation によって公表されている 
+ *  GNU General Public License の Version 2 に記述されている条件か，以
+ *  下の(1)～(4)の条件を満たす場合に限り，本ソフトウェア（本ソフトウェ
+ *  アを改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを再利用可能なバイナリコード（リロケータブルオブ
+ *      ジェクトファイルやライブラリなど）の形で利用する場合には，利用
+ *      に伴うドキュメント（利用者マニュアルなど）に，上記の著作権表示，
+ *      この利用条件および下記の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを再利用不可能なバイナリコードの形または機器に組
+ *      み込んだ形で利用する場合には，次のいずれかの条件を満たすこと．
+ *    (a) 利用に伴うドキュメント（利用者マニュアルなど）に，上記の著作
+ *        権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 利用の形態を，別に定める方法によって，上記著作権者に報告する
+ *        こと．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者を免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者は，
+ *  本ソフトウェアに関して，その適用可能性も含めて，いかなる保証も行わ
+ *  ない．また，本ソフトウェアの利用により直接的または間接的に生じたい
+ *  かなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/* 
+ *  TOPPERS/ASP用タスクモニタCPU依存プログラム．
+ *
+ */
+
+#include <itron.h>
+#include <sil.h>
+#include <stdio.h>
+#include "kernel_impl.h"
+#include "task.h"
+#include "task_expansion.h"
+#include "monitor.h"
+
+extern void _kernel_break_wait();
+
+#define set_align(a, b)	((ulong_t)a & ~(b-1))
+
+/*
+ * レジスタの構造体
+ */
+typedef struct t_reg{
+	uint32_t r4;
+	uint32_t r5;
+	uint32_t r6;
+	uint32_t r7;
+	uint32_t r8;
+	uint32_t r9;
+	uint32_t r10;
+	uint32_t r11;
+	uint32_t spsr;
+	uint32_t r0;
+	uint32_t r1;
+	uint32_t r2;
+	uint32_t r3;
+	uint32_t ip;
+	uint32_t lr;
+	uint32_t pc;
+}T_REG;
+
+/*
+ * メモリのマッピング定義構造体
+ */
+
+typedef struct t_memdef{
+	uint32_t mstart;
+	uint32_t mend;
+	uint8_t  mtype;
+	uint8_t  mstate;
+}T_MEMDEF;
+
+/*
+ * ARM4のメモリマッピング
+ */
+
+static T_MEMDEF const memdefine[] = {
+#if defined(__AT91SAM7S128__)
+	{0x00000000, 0x0001FFFF,           MEMORY_AREA, MREAD_ONLY },
+	{RAM_START,  RAM_START+RAM_SIZE-1, MEMORY_AREA, MREAD_WRITE},
+	{0xFFFF0000, 0xFFFFFFFF,           PORT_AREA,   MREAD_WRITE}
+#elif defined(MINDSTORMSNXT)
+	{0x00000000, RAM_SIZE-1,           MEMORY_AREA, MREAD_ONLY },
+	{0x001C0000, 0x001FFFFF,           MEMORY_AREA, MREAD_ONLY },
+	{RAM_START,  RAM_START+RAM_SIZE-1, MEMORY_AREA, MREAD_WRITE},
+	{0xFFFF0000, 0xFFFFFFFF,           PORT_AREA,   MREAD_WRITE}
+#elif defined(__LPC2388__)
+	{0x00000000, 0x0007FFFF,           MEMORY_AREA, MREAD_ONLY },
+	{0x3FFFC000, 0x3FFFFFFF,           PORT_AREA,   MREAD_WRITE},
+	{RAM_START,  RAM_START+RAM_SIZE-1, MEMORY_AREA, MREAD_WRITE},
+	{0x80000000, 0x8000FFFF,           MEMORY_AREA, MREAD_ONLY },
+	{0x81000000, 0x8100FFFF,           MEMORY_AREA, MREAD_ONLY },
+	{0xE0000000, 0xE008FFFF,           PORT_AREA,   MREAD_WRITE},
+	{0xE01FC000, 0xE01FFFFF,           PORT_AREA,   MREAD_WRITE},
+	{0xFFEF0000, 0xFFFFFFFF,           PORT_AREA,   MREAD_WRITE}
+#elif (__TARGET_ARCH_ARM == 5)
+	{0x01BC0000, 0x01BC0FFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x01BC1000, 0x01BC17FF,           PORT_AREA,   MREAD_WRITE},
+	{0x01C00000, 0x01C07FFF,           PORT_AREA,   MREAD_WRITE},
+	{0x01C08000, 0x01C087FF,           PORT_AREA,   MREAD_WRITE},
+	{0x01C10000, 0x01C11FFF,           PORT_AREA,   MREAD_WRITE},
+	{0x01C14000, 0x01C14FFF,           PORT_AREA,   MREAD_WRITE},
+	{0x01C20000, 0x01C23FFF,           PORT_AREA,   MREAD_WRITE},
+	{0x01C40000, 0x01C42FFF,           PORT_AREA,   MREAD_WRITE},
+	{0x01D00000, 0x01D02FFF,           PORT_AREA,   MREAD_WRITE},
+	{0x01D0C000, 0x01D0DFFF,           PORT_AREA,   MREAD_WRITE},
+	{0x01D10000, 0x01D11FFF,           PORT_AREA,   MREAD_WRITE},
+	{0x01E00000, 0x01E0FFFF,           PORT_AREA,   MREAD_WRITE},
+	{0x01E10000, 0x01E10FFF,           PORT_AREA,   MREAD_WRITE},
+	{0x01E13000, 0x01E1BFFF,           PORT_AREA,   MREAD_WRITE},
+	{0x01E20000, 0x01E28FFF,           PORT_AREA,   MREAD_WRITE},
+	{0x01E2C000, 0x01E2CFFF,           PORT_AREA,   MREAD_WRITE},
+	{0x01E30000, 0x01E383FF,           PORT_AREA,   MREAD_WRITE},
+	{0x01F00000, 0x01F03FFF,           PORT_AREA,   MREAD_WRITE},
+	{0x01F06000, 0x01F08FFF,           PORT_AREA,   MREAD_WRITE},
+	{0x01F0C000, 0x01F0EFFF,           PORT_AREA,   MREAD_WRITE},
+	{0x01F10000, 0x01F11FFF,           PORT_AREA,   MREAD_WRITE},
+	{0x01C40000, 0x01C42FFF,           PORT_AREA,   MREAD_WRITE},
+	{0xC0000000, 0xC3FFFFFF,           MEMORY_AREA, MREAD_WRITE},
+	{0xFFFD0000, 0xFFFDFFFF,           MEMORY_AREA, MREAD_ONLY },
+	{0xFFFEE000, 0xFFFEFFFF,           PORT_AREA,   MREAD_WRITE},
+	{0xFFFF0000, 0xFFFF1FFF,           MEMORY_AREA, MREAD_WRITE}
+#else
+#error "No board type in ARMV4 groups."
+#endif
+};
+
+static T_REG  sreg;
+
+/******************************************************************************
+ * ハードウェアポート属性参照関数
+ ******************************************************************************/
+/*
+ *  アドレスからメモリ領域属性を取り出す
+ *  mode=0:領域の型
+ *  mode=1:読み取り書き込み属性
+ */
+
+char
+getMemoryType(ulong_t address, int_t mode)
+{
+	int_t count = sizeof(memdefine) / sizeof(T_MEMDEF);
+	int_t i;
+
+	for(i = 0 ; i < count ; i++){
+		if(address >= memdefine[i].mstart && address <= memdefine[i].mend){
+			if(mode == 0)
+				return memdefine[i].mtype;
+			else
+				return memdefine[i].mstate;
+		}
+	}
+	return NONE_AREA;
+}
+
+/*
+ *  アドレスからアライン後のアドレスを取り出す
+ */
+
+ulong_t
+MonAlignAddress(ulong_t address)
+{
+	return address;
+}
+
+/******************************************************************************
+ * メモリアクセス用関数
+ ******************************************************************************/
+/*
+ *  メモリ領域に対する読み出し関数
+ *  領域のチェックを行い、エラーならゼロを返す
+ */
+int_t
+MemoryRead(ulong_t address, intptr_t p, int_t type)
+{
+	int_t len;
+
+	switch(getMemoryType(address, 0)){
+	case PORT_AREA:
+		if(type == 2){
+			len = 2;
+			*((UH *)p) = sil_reh_mem((VP)address);
+		}
+		else if(type == 4){
+			len = 4;
+			*((UW *)p) = sil_rew_mem((VP)address);
+		}
+		else{
+			len = 1;
+			*((UB *)p) = sil_reb_mem((VP)address);
+		}
+		break;
+	case MEMORY_AREA:
+		if(type == 2){
+			len = 2;
+			*((UH *)p) = *((UH *)set_align(address, len));
+		}
+		else if(type == 4){
+			len = 4;
+			*((UW *)p) = *((UW *)set_align(address, len));
+		}
+		else{
+			len = 1;
+			*((UB *)p) = *((UB *)address);
+		}
+		break;
+	default:
+		len = 0;
+		break;
+	}
+	return len;
+}
+
+/*
+ *  メモリ領域に対する書き込み関数
+ *  領域のチェックを行い、エラーならゼロを返す
+ */
+int_t
+MemoryWrite(ulong_t address, intptr_t p, int_t type)
+{
+	int_t len;
+
+	switch(getMemoryType(address, 0)){
+	case PORT_AREA:
+		if(type == 2){
+			len = 2;
+			address = set_align(address, len);
+			sil_wrh_mem((VP)address, *((UH *)p));
+		}
+		else if(type == 4){
+			len = 4;
+			address = set_align(address, len);
+			sil_wrw_mem((VP)address, *((UW *)p));
+		}
+		else{
+			len = 1;
+			sil_wrb_mem((VP)address, *((UB *)p));
+		}
+		break;
+	case MEMORY_AREA:
+		if(getMemoryType(address, 1) == MREAD_ONLY){
+			len = 0;
+		}
+		else if(type == 2){
+			len = 2;
+			*((UH *)address) = *((UH *)set_align(p, len));
+		}
+		else if(type == 4){
+			len = 4;
+			*((UW *)address) = *((UW *)set_align(p, len));
+		}
+		else{
+			len = 1;
+			*((UB *)address) = *((UB *)p);
+		}
+		break;
+	default:
+		len = 0;
+		break;
+	}
+	return len;
+}
+
+/******************************************************************************
+ * モニタ用関数
+ ******************************************************************************/
+/*
+ *  レジスタ内容の表示
+ */
+void
+display_registers(ID tskid)
+{
+	ER     ercd;
+	T_RTST rtst;
+
+	ercd = ref_tst(tskid, &rtst);
+	if(ercd == E_OK){
+		if(rtst.tskpc == (FP)_kernel_break_wait){
+			sreg = *((T_REG *)rtst.tsksp);
+			printf(" PC =%08lx SP =%08x IR =%08x", (long)sreg.pc, (UW)((long)rtst.tsksp+sizeof(T_REG)), sreg.lr);
+			printf(" IP =%08x SR=%08x\n", sreg.ip, sreg.spsr);
+			printf(" R0 =%08x R1 =%08x R2 =%08x", sreg.r0, sreg.r1, sreg.r2);
+			printf(" R3 =%08x R4 =%08x R5 =%08x\n", sreg.r3, sreg.r4, sreg.r5);
+			printf(" R6 =%08x R7 =%08x R8 =%08x", sreg.r6, sreg.r7, sreg.r8);
+			printf(" R9 =%08x R10=%08x R11=%08x\n", sreg.r9, sreg.r10, sreg.r11);
+			printf("     %08lx    %08x\n", (long)sreg.pc, *((UW*)((sreg.pc+3) & ~3)));
+			return;
+		}
+		else if(rtst.tskstat == TTS_DMT){
+			printf("  wait in activate_r() !!\n");
+			return;
+		}
+	}
+	printf("  wait in dispatch() !!\n");
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/arch/armv7m.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/arch/armv7m.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/arch/armv7m.c	(revision 453)
@@ -0,0 +1,365 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2003-2016 by Ryosuke Takeuchi
+ *                     GJ Business Division RICOH COMPANY,LTD. JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，Free Software Foundation によって公表されている 
+ *  GNU General Public License の Version 2 に記述されている条件か，以
+ *  下の(1)～(4)の条件を満たす場合に限り，本ソフトウェア（本ソフトウェ
+ *  アを改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを再利用可能なバイナリコード（リロケータブルオブ
+ *      ジェクトファイルやライブラリなど）の形で利用する場合には，利用
+ *      に伴うドキュメント（利用者マニュアルなど）に，上記の著作権表示，
+ *      この利用条件および下記の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを再利用不可能なバイナリコードの形または機器に組
+ *      み込んだ形で利用する場合には，次のいずれかの条件を満たすこと．
+ *    (a) 利用に伴うドキュメント（利用者マニュアルなど）に，上記の著作
+ *        権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 利用の形態を，別に定める方法によって，上記著作権者に報告する
+ *        こと．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者を免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者は，
+ *  本ソフトウェアに関して，その適用可能性も含めて，いかなる保証も行わ
+ *  ない．また，本ソフトウェアの利用により直接的または間接的に生じたい
+ *  かなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/* 
+ *  TOPPERS/ASP用タスクモニタCPU依存プログラム．
+ *
+ */
+
+#include <itron.h>
+#include <sil.h>
+#include <stdio.h>
+#include "kernel_impl.h"
+#include "task.h"
+#include "task_expansion.h"
+#include "monitor.h"
+
+extern void dispatch_r(void);
+
+#define set_align(a, b)	((ulong_t)a & ~(b-1))
+
+/*
+ * レジスタの構造体
+ */
+typedef struct t_reg{
+	uint32_t r4;
+	uint32_t r5;
+	uint32_t r6;
+	uint32_t r7;
+	uint32_t r8;
+	uint32_t r9;
+	uint32_t r10;
+	uint32_t r11;
+	uint32_t pc;
+}T_REG;
+
+/*
+ * メモリのマッピング定義構造体
+ */
+
+typedef struct t_memdef{
+	uint32_t mstart;
+	uint32_t mend;
+	uint8_t  mtype;
+	uint8_t  mstate;
+}T_MEMDEF;
+
+/*
+ * ARMv7のメモリマッピング
+ */
+
+static T_MEMDEF const memdefine[] = {
+#if defined(TOPPERS_CQ_FRK_FM3)
+	{0x00000000, 0x000FFFFF,           MEMORY_AREA, MREAD_ONLY },
+	{0x1FFF0000, 0x201EFFFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x40000000, 0x400FFFFF,           PORT_AREA,   MREAD_WRITE},
+#elif defined(TOPPERS_STM32F091_NUCLEO64)	/* ARMV6m */
+	{0x08000000, 0x0803FFFF,           MEMORY_AREA, MREAD_ONLY },
+	{0x20000000, 0x20007FFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x40000000, 0x50060FFF,           PORT_AREA,   MREAD_WRITE},
+	{0xA0000000, 0xBFFFFFFF,           PORT_AREA,   MREAD_WRITE},
+#elif defined(TOPPERS_STM32L073_NUCLEO64) || defined(TOPPERS_STM32LORA_DISCOVERY)	/* ARMV6m */
+	{0x08000000, 0x0802FFFF,           MEMORY_AREA, MREAD_ONLY },
+	{0x20000000, 0x20004FFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x40000000, 0x50060FFF,           PORT_AREA,   MREAD_WRITE},
+	{0xA0000000, 0xBFFFFFFF,           PORT_AREA,   MREAD_WRITE},
+#elif defined(TOPPERS_STM32G071_NUCLEO64)	/* ARMV6m */
+	{0x08000000, 0x0801FFFF,           MEMORY_AREA, MREAD_ONLY },
+	{0x20000000, 0x20008FFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x40000000, 0x50060FFF,           PORT_AREA,   MREAD_WRITE},
+	{0xA0000000, 0xBFFFFFFF,           PORT_AREA,   MREAD_WRITE},
+#elif defined(TOPPERS_STM32L476_NUCLEO64) || defined(TOPPERS_STM32L476_DISCOVERY)
+	{0x08000000, 0x080FFFFF,           MEMORY_AREA, MREAD_ONLY },
+	{0x10000000, 0x10007FFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x20000000, 0x20017FFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x40000000, 0x50060FFF,           PORT_AREA,   MREAD_WRITE},
+	{0x90000000, 0xBFFFFFFF,           PORT_AREA,   MREAD_WRITE},
+#elif defined(TOPPERS_STM32L4R5_NUCLEO144)
+	{0x08000000, 0x080FFFFF,           MEMORY_AREA, MREAD_ONLY },
+	{0x10000000, 0x10007FFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x20000000, 0x2009FFFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x40000000, 0x6FFFFFFF,           PORT_AREA,   MREAD_WRITE},
+	{0x80000000, 0xBFFFFFFF,           PORT_AREA,   MREAD_WRITE},
+#elif defined(TOPPERS_STM32WB55_NUCLEO)
+	{0x08000000, 0x080CBFFF,           MEMORY_AREA, MREAD_ONLY },
+	{0x20000000, 0x2003FFFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x40000000, 0x6FFFFFFF,           PORT_AREA,   MREAD_WRITE},
+	{0x80000000, 0xBFFFFFFF,           PORT_AREA,   MREAD_WRITE},
+#elif defined(TOPPERS_STM32F4_DISCOVERY) || defined(TOPPERS_STM32_E407)
+	{0x08000000, 0x080FFFFF,           MEMORY_AREA, MREAD_ONLY },
+	{0x20000000, 0x2001FFFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x40000000, 0x50060FFF,           PORT_AREA,   MREAD_WRITE},
+	{0xA0000000, 0xBFFFFFFF,           PORT_AREA,   MREAD_WRITE},
+#elif defined(TOPPERS_STM32F401_NUCLEO)
+	{0x08000000, 0x0807FFFF,           MEMORY_AREA, MREAD_ONLY },
+	{0x20000000, 0x20017FFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x40000000, 0x50060FFF,           PORT_AREA,   MREAD_WRITE},
+	{0xA0000000, 0xBFFFFFFF,           PORT_AREA,   MREAD_WRITE},
+#elif defined(TOPPERS_STM32F446_NUCLEO64) || defined(TOPPERS_STM32F446_NUCLEO144)
+	{0x08000000, 0x0807FFFF,           MEMORY_AREA, MREAD_ONLY },
+	{0x20000000, 0x2001FFFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x40000000, 0x50060FFF,           PORT_AREA,   MREAD_WRITE},
+	{0xA0000000, 0xBFFFFFFF,           PORT_AREA,   MREAD_WRITE},
+#elif defined(TOPPERS_STM32F429_BOARD)
+	{0x08000000, 0x080FFFFF,           MEMORY_AREA, MREAD_ONLY },
+	{0x20000000, 0x2002FFFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x40000000, 0x50060FFF,           PORT_AREA,   MREAD_WRITE},
+	{0xA0000000, 0xBFFFFFFF,           PORT_AREA,   MREAD_WRITE},
+#elif defined(TOPPERS_STM32G474_NUCLEO64)
+	{0x08000000, 0x0807FFFF,           MEMORY_AREA, MREAD_ONLY },
+	{0x10000000, 0x10007FFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x20000000, 0x20017FFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x40000000, 0xAFFFFFFF,           PORT_AREA,   MREAD_WRITE},
+#elif defined(TOPPERS_STM32G431_NUCLEO64)
+	{0x08000000, 0x0801FFFF,           MEMORY_AREA, MREAD_ONLY },
+	{0x10000000, 0x10002FFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x20000000, 0x200057FF,           MEMORY_AREA, MREAD_WRITE},
+	{0x40000000, 0xAFFFFFFF,           PORT_AREA,   MREAD_WRITE},
+#elif defined(TOPPERS_STM32F723_DISCOVERY)
+	{0x00000000, 0x0003FFFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x08000000, 0x0807FFFF,           MEMORY_AREA, MREAD_ONLY },
+	{0x20000000, 0x2003FFFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x40000000, 0x50060FFF,           PORT_AREA,   MREAD_WRITE},
+	{0x90000000, 0xBFFFFFFF,           PORT_AREA,   MREAD_WRITE},
+	{0xC0000000, 0xC07FFFFF,           MEMORY_AREA, MREAD_WRITE},
+#elif defined(TOPPERS_STM32F7_DISCOVERY) ||defined(TOPPERS_STM32F746_NUCLEO144)
+	{0x00000000, 0x0003FFFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x08000000, 0x080FFFFF,           MEMORY_AREA, MREAD_ONLY },
+	{0x20000000, 0x2004FFFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x40000000, 0x50060FFF,           PORT_AREA,   MREAD_WRITE},
+	{0x90000000, 0xBFFFFFFF,           PORT_AREA,   MREAD_WRITE},
+	{0xC0000000, 0xC07FFFFF,           MEMORY_AREA, MREAD_WRITE},
+#elif defined(TOPPERS_STM32F769_DISCOVERY) || defined(TOPPERS_STM32F767_NUCLEO144)
+	{0x00000000, 0x0003FFFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x08000000, 0x081FFFFF,           MEMORY_AREA, MREAD_ONLY },
+	{0x20000000, 0x2007FFFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x40000000, 0x50060FFF,           PORT_AREA,   MREAD_WRITE},
+	{0x90000000, 0xBFFFFFFF,           PORT_AREA,   MREAD_WRITE},
+	{0xC0000000, 0xC07FFFFF,           MEMORY_AREA, MREAD_WRITE},
+#elif defined(TOPPERS_STM32H743_NUCLEO144)
+	{0x08000000, 0x081FFFFF,           MEMORY_AREA, MREAD_ONLY },
+	{0x20000000, 0x0001FFFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x24000000, 0x2407FFFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x30000000, 0x30047FFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x38000000, 0x3800FFFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x40000000, 0x5802FFFF,           PORT_AREA,   MREAD_WRITE},
+	{0x90000000, 0xBFFFFFFF,           PORT_AREA,   MREAD_WRITE},
+#elif defined(NRF52832)
+	{0x00000000, 0x0007FFFF,           MEMORY_AREA, MREAD_ONLY },
+	{0x10000000, 0x1FFFFFFF,           PORT_AREA,   MREAD_WRITE},
+	{0x20000000, 0x2000FFFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x40000000, 0x5007FFFF,           PORT_AREA,   MREAD_WRITE},
+	{0xF0000000, 0xF1FFFFFF,           PORT_AREA,   MREAD_WRITE},
+#elif defined(NRF52810)
+	{0x00000000, 0x0002FFFF,           MEMORY_AREA, MREAD_ONLY },
+	{0x10000000, 0x1FFFFFFF,           PORT_AREA,   MREAD_WRITE},
+	{0x20000000, 0x20005FFF,           MEMORY_AREA, MREAD_WRITE},
+	{0x40000000, 0x5007FFFF,           PORT_AREA,   MREAD_WRITE},
+	{0xF0000000, 0xF1FFFFFF,           PORT_AREA,   MREAD_WRITE},
+#else
+#error "No support board type in ARMV7-M groups."
+#endif
+	{0xE0000000, 0xFFFFFFFF,           PORT_AREA,   MREAD_WRITE}
+};
+
+static T_REG  sreg;
+
+/******************************************************************************
+ * ハードウェアポート属性参照関数
+ ******************************************************************************/
+/*
+ *  アドレスからメモリ領域属性を取り出す
+ *  mode=0:領域の型
+ *  mode=1:読み取り書き込み属性
+ */
+
+char
+getMemoryType(ulong_t address, int_t mode)
+{
+	int_t count = sizeof(memdefine) / sizeof(T_MEMDEF);
+	int_t i;
+
+	for(i = 0 ; i < count ; i++){
+		if(address >= memdefine[i].mstart && address <= memdefine[i].mend){
+			if(mode == 0)
+				return memdefine[i].mtype;
+			else
+				return memdefine[i].mstate;
+		}
+	}
+	return NONE_AREA;
+}
+
+/*
+ *  アドレスからアライン後のアドレスを取り出す
+ */
+
+ulong_t
+MonAlignAddress(ulong_t address)
+{
+	return address;
+}
+
+/******************************************************************************
+ * メモリアクセス用関数
+ ******************************************************************************/
+/*
+ *  メモリ領域に対する読み出し関数
+ *  領域のチェックを行い、エラーならゼロを返す
+ */
+int_t
+MemoryRead(ulong_t address, intptr_t p, int_t type)
+{
+	int_t len;
+
+	switch(getMemoryType(address, 0)){
+	case PORT_AREA:
+		if(type == 2){
+			len = 2;
+			*((UH *)p) = sil_reh_mem((VP)address);
+		}
+		else if(type == 4){
+			len = 4;
+			*((UW *)p) = sil_rew_mem((VP)address);
+		}
+		else{
+			len = 1;
+			*((UB *)p) = sil_reb_mem((VP)address);
+		}
+		break;
+	case MEMORY_AREA:
+		if(type == 2){
+			len = 2;
+			*((UH *)p) = *((UH *)set_align(address, len));
+		}
+		else if(type == 4){
+			len = 4;
+			*((UW *)p) = *((UW *)set_align(address, len));
+		}
+		else{
+			len = 1;
+			*((UB *)p) = *((UB *)address);
+		}
+		break;
+	default:
+		len = 0;
+		break;
+	}
+	return len;
+}
+
+/*
+ *  メモリ領域に対する書き込み関数
+ *  領域のチェックを行い、エラーならゼロを返す
+ */
+int_t
+MemoryWrite(ulong_t address, intptr_t p, int_t type)
+{
+	int_t len;
+
+	switch(getMemoryType(address, 0)){
+	case PORT_AREA:
+		if(type == 2){
+			len = 2;
+			address = set_align(address, len);
+			sil_wrh_mem((VP)address, *((UH *)p));
+		}
+		else if(type == 4){
+			len = 4;
+			address = set_align(address, len);
+			sil_wrw_mem((VP)address, *((UW *)p));
+		}
+		else{
+			len = 1;
+			sil_wrb_mem((VP)address, *((UB *)p));
+		}
+		break;
+	case MEMORY_AREA:
+		if(getMemoryType(address, 1) == MREAD_ONLY){
+			len = 0;
+		}
+		else if(type == 2){
+			len = 2;
+			*((UH *)address) = *((UH *)set_align(p, len));
+		}
+		else if(type == 4){
+			len = 4;
+			*((UW *)address) = *((UW *)set_align(p, len));
+		}
+		else{
+			len = 1;
+			*((UB *)address) = *((UB *)p);
+		}
+		break;
+	default:
+		len = 0;
+		break;
+	}
+	return len;
+}
+
+/******************************************************************************
+ * モニタ用関数
+ ******************************************************************************/
+/*
+ *  レジスタ内容の表示
+ */
+void
+display_registers(ID tskid)
+{
+	ER     ercd;
+	T_RTST rtst;
+
+	ercd = ref_tst(tskid, &rtst);
+	if(ercd == E_OK){
+		if(rtst.tskpc == (FP)dispatch_r){
+			sreg = *((T_REG *)rtst.tsksp);
+			printf(" PC  =%08lx SP =%08x\n", (long)sreg.pc, (UW)((long)rtst.tsksp+sizeof(T_REG)));
+			printf(" R4  =%08x R5 =%08x R6  =%08x R7  =%08x\n", sreg.r4, sreg.r5, sreg.r6, sreg.r7);
+			printf(" R8  =%08x R9 =%08x R10 =%08x R11 =%08x\n", sreg.r8, sreg.r9, sreg.r10, sreg.r11);
+			printf("     %08lx    %04x\n", (long)sreg.pc, *((UH*)(sreg.pc & ~1)));
+			return;
+		}
+		else if(rtst.tskstat == TTS_DMT){
+			printf("  wait in activate_r() !!\n");
+			return;
+		}
+	}
+	printf("  wait in dispatch() !!\n");
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/arch/h8300h.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/arch/h8300h.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/arch/h8300h.c	(revision 453)
@@ -0,0 +1,357 @@
+/*
+ *  TOPPERS/ASP Educative Program
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Just Standard Profile Kernel
+ * 
+ *  Copyright (C) 2003-2008 by Ryosuke Takeuchi
+ *               Platform Development Center RICOH COMPANY,LTD. JAPAN
+ * 
+ *  上記著作権者は，Free Software Foundation によって公表されている 
+ *  GNU General Public License の Version 2 に記述されている条件か，以
+ *  下の(1)～(4)の条件を満たす場合に限り，本ソフトウェア（本ソフトウェ
+ *  アを改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを再利用可能なバイナリコード（リロケータブルオブ
+ *      ジェクトファイルやライブラリなど）の形で利用する場合には，利用
+ *      に伴うドキュメント（利用者マニュアルなど）に，上記の著作権表示，
+ *      この利用条件および下記の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを再利用不可能なバイナリコードの形または機器に組
+ *      み込んだ形で利用する場合には，次のいずれかの条件を満たすこと．
+ *    (a) 利用に伴うドキュメント（利用者マニュアルなど）に，上記の著作
+ *        権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 利用の形態を，別に定める方法によって，上記著作権者に報告する
+ *        こと．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者を免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者は，
+ *  本ソフトウェアに関して，その適用可能性も含めて，いかなる保証も行わ
+ *  ない．また，本ソフトウェアの利用により直接的または間接的に生じたい
+ *  かなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/* 
+ *  TOPPERS/ASP用タスクモニタCPU依存プログラム．
+ *
+ */
+
+#include <itron.h>
+#include <sil.h>
+#include <stdio.h>
+#include "kernel_impl.h"
+#include "task.h"
+#include "task_expansion.h"
+#ifdef SUPPORT_NETDEV
+#include "netdevice.h"
+#endif
+#include "monitor.h"
+
+extern void _kernel_break_wait();
+#ifdef SUPPORT_NETDEV
+static UB save_ier;
+extern unsigned long vector[];
+#endif
+
+/*
+ * レジスタの構造体
+ */
+typedef struct t_reg{
+	uint32_t er6;
+	uint32_t er5;
+	uint32_t er4;
+	uint32_t er3;
+	uint32_t er2;
+	uint32_t er1;
+	uint32_t er0;
+	uint32_t pc;
+}T_REG;
+
+/*
+ * メモリのマッピング定義構造体
+ */
+
+typedef struct t_memdef{
+	uint32_t mstart;
+	uint32_t mend;
+	uint8_t  mtype;
+	uint8_t  mstate;
+}T_MEMDEF;
+
+/*
+ * AKIH8のメモリマッピング
+ */
+
+static T_MEMDEF const memdefine[] = {
+	0x00000000, 0x000000FF, MEMORY_AREA, MREAD_ONLY,
+#if defined(__H8_3048F__)
+	0x00000100,	0x0001FFFF, MEMORY_AREA, MREAD_ONLY,
+	0x000FEF10, 0x000FFF0F, MEMORY_AREA, MREAD_WRITE,
+	0x00FFFF1C, 0x00FFFFFF, PORT_AREA,   MREAD_WRITE
+#elif defined(__H8_3069F__)
+	0x00000100,	0x0007FFFF, MEMORY_AREA, MREAD_ONLY,
+	0x00400000, 0x005FFFFF, MEMORY_AREA, MREAD_WRITE,
+	0x00FEE000, 0x00FEEFFF, PORT_AREA,   MREAD_WRITE,
+	0x00FFBF20, 0x00FFFF1F, MEMORY_AREA, MREAD_WRITE,
+	0x00FFFF20, 0x00FFFFFF, PORT_AREA,   MREAD_WRITE
+#else
+#error "No board type in H8300H groups."
+#endif
+};
+
+/******************************************************************************
+ * ハードウェアポート属性参照関数
+ ******************************************************************************/
+/*
+ *  アドレスからメモリ領域属性を取り出す
+ *  mode=0:領域の型
+ *  mode=1:読み取り書き込み属性
+ */
+
+char
+getMemoryType(ulong_t address, int_t mode)
+{
+	int_t count = sizeof(memdefine) / sizeof(T_MEMDEF);
+	int_t i;
+
+	for(i = 0 ; i < count ; i++){
+		if(address >= memdefine[i].mstart && address <= memdefine[i].mend){
+			if(mode == 0)
+				return memdefine[i].mtype;
+			else
+				return memdefine[i].mstate;
+		}
+	}
+	return NONE_AREA;
+}
+
+/*
+ *  アドレスからアライン後のアドレスを取り出す
+ */
+
+ulong_t
+MonAlignAddress(ulong_t address)
+{
+	return address;
+}
+
+/******************************************************************************
+ * メモリアクセス用関数
+ ******************************************************************************/
+/*
+ *  メモリ領域に対する読み出し関数
+ *  領域のチェックを行い、エラーならゼロを返す
+ */
+int_t
+MemoryRead(ulong_t address, intptr_t p, int_t type)
+{
+	int_t len;
+
+	switch(getMemoryType(address, 0)){
+	case PORT_AREA:
+		if(type == 2){
+			len = 2;
+#ifdef SUPPORT_NETDEV
+            if(!NetDeviceRead((unsigned long)address, len, (void *)p))
+#endif
+			*((UH *)p) = sil_reh_mem((VP)address);
+		}
+		else if(type == 4){
+			len = 4;
+#ifdef SUPPORT_NETDEV
+            if(!NetDeviceRead((unsigned long)address, len, (void *)p))
+#endif
+			*((UW *)p) = sil_rew_mem((VP)address);
+		}
+		else{
+#ifdef SUPPORT_NETDEV
+			len = 1;
+			if(NetDeviceActive() && address == H8IER)
+				*((UB *)p) = save_ier;
+			else if(address == H8IPRA || address == H8IPRB)
+				*((UB *)p) = sil_reb_mem((VP)address);
+            else if(!NetDeviceRead((unsigned long)address, len, (void *)p))
+				*((UB *)p) = sil_reb_mem((VP)address);
+#else
+			len = 1;
+			*((UB *)p) = sil_reb_mem((VP)address);
+#endif
+		}
+		break;
+	case MEMORY_AREA:
+		if(type == 2){
+			len = 2;
+			*((UH *)p) = *((UH *)address);
+		}
+		else if(type == 4){
+			len = 4;
+			*((UW *)p) = *((UW *)address);
+		}
+		else{
+			len = 1;
+			*((UB *)p) = *((UB *)address);
+		}
+		break;
+	default:
+		len = 0;
+		break;
+	}
+	return len;
+}
+
+/*
+ *  メモリ領域に対する書き込み関数
+ *  領域のチェックを行い、エラーならゼロを返す
+ */
+int_t
+MemoryWrite(ulong_t address, intptr_t p, int_t type)
+{
+	int_t len;
+
+	switch(getMemoryType(address, 0)){
+	case PORT_AREA:
+		if(type == 2){
+			len = 2;
+#ifdef SUPPORT_NETDEV
+            if(!NetDeviceWrite((unsigned long)address, len, (void *)p))
+#endif
+			sil_wrh_mem((VP)address, *((UH *)p));
+		}
+		else if(type == 4){
+			len = 4;
+#ifdef SUPPORT_NETDEV
+            if(!NetDeviceWrite((unsigned long)address, len, (void *)p))
+#endif
+			sil_wrw_mem((VP)address, *((UW *)p));
+		}
+		else{
+#ifdef SUPPORT_NETDEV
+			len = 1;
+			if(NetDeviceActive() && address == H8IER){
+				save_ier = *((UB *)p);
+				if(save_ier & (1<<H8IER_IRQ1E_BIT))
+					NetDeviceSetInt(IRQ_EXT1, (void (*)(VP))vector[IRQ_EXT1]);
+				else
+					NetDeviceSetInt(IRQ_EXT1, 0);
+				if(save_ier & (1<<H8IER_IRQ2E_BIT))
+					NetDeviceSetInt(IRQ_EXT2, (void (*)(VP))vector[IRQ_EXT2]);
+				else
+					NetDeviceSetInt(IRQ_EXT2, 0);
+			}
+			else if(address == H8IPRA || address == H8IPRB)
+				sil_wrb_mem((VP)address, *((UB *)p));
+            else if(!NetDeviceWrite((unsigned long)address, len, (void *)p))
+				sil_wrb_mem((VP)address, *((UB *)p));
+#else
+			len = 1;
+			sil_wrb_mem((VP)address, *((UB *)p));
+#endif
+		}
+		break;
+	case MEMORY_AREA:
+		if(getMemoryType(address, 1) == MREAD_ONLY){
+			len = 0;
+		}
+		else if(type == 2){
+			len = 2;
+			*((UH *)address) = *((UH *)p);
+		}
+		else if(type == 4){
+			len = 4;
+			*((UW *)address) = *((UW *)p);
+		}
+		else{
+			len = 1;
+			*((UB *)address) = *((UB *)p);
+		}
+		break;
+	default:
+		len = 0;
+		break;
+	}
+	return len;
+}
+
+/******************************************************************************
+ * モニタ用関数
+ ******************************************************************************/
+/*
+ *  エクセプションの引数よりpcを取り出す関数
+ */
+ulong_t
+get_exception_pc(void * p_excinf)
+{
+	ulong_t pc;
+
+	pc = *(ulong_t*)((char*)p_excinf+16) & 0xffffff;
+	return pc;
+}
+
+/*
+ *  レジスタ内容の表示
+ */
+void
+display_registers(ID tskid)
+{
+	ER       ercd;
+	T_RTST   rtst;
+	T_REG    reg;
+	uint32_t pc;
+	uint8_t  ccr;
+
+	ercd = ref_tst(tskid, &rtst);
+	printf("tskid=%d ercd=%d rtst.tskpc=0x%x rtst.tsksp=0x%x\n", tskid, ercd, (int)rtst.tskpc, (int)rtst.tsksp);
+
+	if(ercd == E_OK){
+		if(rtst.tskpc == (FP)_kernel_break_wait){
+			reg = *((T_REG *)rtst.tsksp);
+			pc  = reg.pc & 0xffffff;
+			ccr = reg.pc >> 24;
+			printf("  PC=%08lx SP=%08lx", (unsigned long)pc, (unsigned long)rtst.tsksp+sizeof(T_REG));
+			printf(" I=%1x UI=%1x H=%1x", (ccr>>7) & 1, (ccr>>6) & 1, (ccr>>5) & 1);
+			printf(" U=%1x N=%1x Z=%1x", (ccr>>4) & 1, (ccr>>3) & 1, (ccr>>2) & 1);
+			printf(" V=%1x C=%1x    R6=%08x\n", (ccr>>1) & 1, ccr & 1, reg.er6);
+			printf("  R0=%08x R1=%08x R2=%08x", reg.er0, reg.er1, reg.er2);
+			printf(" R3=%08x R4=%08x R5=%08x\n", reg.er3, reg.er4, reg.er5);
+			printf("     %08lx    %02x %02x\n", (unsigned long)pc, *((UB*)pc), *((UB*)(pc+1)));
+			return;
+		}
+		else if(rtst.tskstat == TTS_DMT){
+			printf("  wait in activate_r() !!\n");
+			return;
+		}
+	}
+	printf("  wait in dispatch() !!\n");
+}
+
+/******************************************************************************
+ * エラー通知用関数
+ ******************************************************************************/
+/*
+ * イレギュラーエクセプション
+ */
+void
+irregular_ext_handler(void * p_excinf)
+{
+	uint32_t pc = get_exception_pc(p_excinf);
+
+	if(p_runtsk){
+		if(_kernel_intnest > 1){
+			syslog_2(LOG_EMERG, "Irregular Exception occured in not task Context pc=0x%x p_excinf=0x%x !", pc, p_excinf);
+			target_exit();
+		}
+		else{
+			syslog_3(LOG_ERROR, "Irregular Exception occured in tskid=%d pc=0x%x p_excinf=0x%x !", TSKID(p_runtsk), pc, p_excinf);
+			isus_tsk(TSKID(p_runtsk));
+		}
+	}
+	else{
+		syslog_2(LOG_EMERG, "Irregular Exception occured in Idle pc=0x%x p_excinf=0x%x !", pc, p_excinf);
+		target_exit();
+	}
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/arch/m16c.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/arch/m16c.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/arch/m16c.c	(revision 453)
@@ -0,0 +1,330 @@
+/*
+ *  TOPPERS/ASP Educative Program
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Just Standard Profile Kernel
+ * 
+ *  Copyright (C) 2003-2009 by Ryosuke Takeuchi
+ *               Platform Development Center RICOH COMPANY,LTD. JAPAN
+ * 
+ *  上記著作権者は，Free Software Foundation によって公表されている 
+ *  GNU General Public License の Version 2 に記述されている条件か，以
+ *  下の(1)～(4)の条件を満たす場合に限り，本ソフトウェア（本ソフトウェ
+ *  アを改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを再利用可能なバイナリコード（リロケータブルオブ
+ *      ジェクトファイルやライブラリなど）の形で利用する場合には，利用
+ *      に伴うドキュメント（利用者マニュアルなど）に，上記の著作権表示，
+ *      この利用条件および下記の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを再利用不可能なバイナリコードの形または機器に組
+ *      み込んだ形で利用する場合には，次のいずれかの条件を満たすこと．
+ *    (a) 利用に伴うドキュメント（利用者マニュアルなど）に，上記の著作
+ *        権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 利用の形態を，別に定める方法によって，上記著作権者に報告する
+ *        こと．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者を免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者は，
+ *  本ソフトウェアに関して，その適用可能性も含めて，いかなる保証も行わ
+ *  ない．また，本ソフトウェアの利用により直接的または間接的に生じたい
+ *  かなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/* 
+ *  TOPPERS/ASP用タスクモニタCPU依存プログラム．
+ *
+ */
+
+#include <itron.h>
+#include <sil.h>
+#include <stdio.h>
+#include "kernel_impl.h"
+#include "task.h"
+#include "task_expansion.h"
+#include "monitor.h"
+
+extern void _kernel_break_wait();
+
+/*
+ * レジスタの構造体
+ */
+typedef struct t_reg{
+	uint16_t r0;
+	uint16_t r1;
+	uint16_t r2;
+	uint16_t r3;
+	uint16_t a0;
+	uint16_t a1;
+	uint16_t sb;
+	uint16_t fb;
+	uint16_t lpc;
+	uint8_t  lflg;
+	uint8_t  hpc;
+}T_REG;
+
+/*
+ * メモリのマッピング定義構造体
+ */
+
+typedef struct t_memdef{
+	uint32_t mstart;
+	uint32_t mend;
+	uint8_t  mtype;
+	uint8_t  mstate;
+}T_MEMDEF;
+
+/*
+ * M16Cのメモリマッピング
+ */
+
+static T_MEMDEF const memdefine[] = {
+	0x00000000,	0x000003FF, PORT_AREA,   MREAD_WRITE,
+#if defined(OAKS16)
+	0x00000400, 0x00002BFF, MEMORY_AREA, MREAD_WRITE,
+	0x000E0000, 0x000FFFFF, MEMORY_AREA, MREAD_ONLY
+#elif defined(OAKS16_MINI)
+	0x00000400, 0x00000BFF, MEMORY_AREA, MREAD_WRITE,
+	0x000F0000, 0x000FFFFF, MEMORY_AREA, MREAD_ONLY
+#else
+	0x00000400, 0x000033FF, MEMORY_AREA, MREAD_WRITE,
+	0x000E0000, 0x000FFFFF, MEMORY_AREA, MREAD_ONLY
+#endif
+};
+
+/******************************************************************************
+ * ハードウェアポート属性参照関数
+ ******************************************************************************/
+/*
+ *  アドレスからメモリ領域属性を取り出す
+ *  mode=0:領域の型
+ *  mode=1:読み取り書き込み属性
+ */
+
+char
+getMemoryType(ulong_t address, int_t mode)
+{
+	int_t count = sizeof(memdefine) / sizeof(T_MEMDEF);
+	int_t i;
+
+	for(i = 0 ; i < count ; i++){
+		if(address >= memdefine[i].mstart && address <= memdefine[i].mend){
+			if(mode == 0)
+				return memdefine[i].mtype;
+			else
+				return memdefine[i].mstate;
+		}
+	}
+	return NONE_AREA;
+}
+
+/*
+ *  アドレスからアライン後のアドレスを取り出す
+ */
+
+ulong_t
+MonAlignAddress(ulong_t address)
+{
+	return address;
+}
+
+/******************************************************************************
+ * メモリアクセス用関数
+ ******************************************************************************/
+/*
+ *  メモリ領域に対する読み出し関数
+ *  領域のチェックを行い、エラーならゼロを返す
+ */
+int_t
+MemoryRead(ulong_t address, intptr_t p, int_t type)
+{
+	int_t len;
+
+	switch(getMemoryType(address, 0)){
+	case PORT_AREA:
+		if(type == 2){
+			len = 2;
+			*((UH _far *)p) = sil_reh_mem((VP)address);
+		}
+		else if(type == 4){
+			len = 4;
+			*((UW _far *)p) = sil_rew_mem((VP)address);
+		}
+		else{
+			len = 1;
+			*((UB _far *)p) = sil_reb_mem((VP)address);
+		}
+		break;
+	case MEMORY_AREA:
+		if(type == 2){
+			len = 2;
+			*((UH _far *)p) = *((UH _far *)address);
+		}
+		else if(type == 4){
+			len = 4;
+			*((UW _far *)p) = *((UW _far *)address);
+		}
+		else{
+			len = 1;
+			*((UB _far *)p) = *((UB _far *)address);
+		}
+		break;
+	default:
+		len = 0;
+		break;
+	}
+	return len;
+}
+
+/*
+ *  メモリ領域に対する書き込み関数
+ *  領域のチェックを行い、エラーならゼロを返す
+ */
+int_t
+MemoryWrite(ulong_t address, intptr_t p, int_t type)
+{
+	int_t len;
+
+	switch(getMemoryType(address, 0)){
+	case PORT_AREA:
+		if(type == 2){
+			len = 2;
+			sil_wrh_mem((VP)address, *((UH _far *)p));
+		}
+		else if(type == 4){
+			len = 4;
+			sil_wrw_mem((VP)address, *((UW _far *)p));
+		}
+		else{
+			len = 1;
+			sil_wrb_mem((VP)address, *((UB _far *)p));
+		}
+		break;
+	case MEMORY_AREA:
+		if(getMemoryType(address, 1) == MREAD_ONLY){
+			len = 0;
+		}
+		else if(type == 2){
+			len = 2;
+			*((UH _far *)address) = *((UH _far *)p);
+		}
+		else if(type == 4){
+			len = 4;
+			*((UW _far *)address) = *((UW _far *)p);
+		}
+		else{
+			len = 1;
+			*((UB _far *)address) = *((UB _far *)p);
+		}
+		break;
+	default:
+		len = 0;
+		break;
+	}
+	return len;
+}
+
+/******************************************************************************
+ * モニタ用関数
+ ******************************************************************************/
+/*
+ *  エクセプションの引数よりpcを取り出す関数
+ */
+ulong_t
+get_exception_pc(void * p_excinf)
+{
+	ulong_t pc;
+
+	pc = *(uint16_t*)((char*)p_excinf+16) | ((ulong_t)(*((char*)p_excinf+19) & 0xf) << 16);
+	return pc;
+}
+
+/*
+ *  レジスタ内容の表示
+ */
+void
+display_registers(ID tskid)
+{
+	ER       ercd;
+	T_RTST   rtst;
+	T_REG    reg;
+	uint32_t pc;
+
+	ercd = ref_tst(tskid, &rtst);
+	if(ercd == E_OK){
+		if(rtst.tskpc == (FP)_kernel_break_wait){
+			reg = *((T_REG *)rtst.tsksp);
+			pc = reg.lpc | (((UW)reg.hpc & 0xf)<<16);
+			printf("  PC=%06lx SP=%04x", (unsigned long)pc, (UW)rtst.tsksp+sizeof(T_REG));
+			printf("       IPL=%1x U=%1x I=%1x", (reg.hpc>>4) & 0x7, (reg.lflg>>7) & 1, (reg.lflg>>6) & 1);
+			printf(" O=%1x B=%1x S=%1x", (reg.lflg>>5) & 1, (reg.lflg>>4) & 1, (reg.lflg>>3) & 1);
+			printf(" Z=%1x D=%1x C=%1x\n", (reg.lflg>>2) & 1, (reg.lflg>>1) & 1, reg.lflg & 1);
+			printf("  R0=%04x R1=%04x R2=%04x", reg.r0, reg.r1, reg.r2);
+			printf(" R3=%04x A0=%04x A1=%04x", reg.r3, reg.a0, reg.a1);
+			printf(" SB=%04x FB=%04x\n", reg.sb, reg.fb);
+			printf("     %06lx    %02x %02x\n", (unsigned long)pc, *((UB*)pc), *((UB*)(pc+1)));
+			return;
+		}
+		else if(rtst.tskstat == TTS_DMT){
+			printf("  wait in activate_r() !!\n");
+			return;
+		}
+	}
+	printf("  wait in dispatch() !!\n");
+}
+
+#if 0
+/******************************************************************************
+ * エラー通知用関数
+ ******************************************************************************/
+/*
+ * イレギュラー割込みハンドラー
+ */
+void
+irregular_int_handler(void)
+{
+	if(runtsk){
+		if(intnest > 1){
+			syslog_1(LOG_EMERG, "Irregular Interrupt occured in tskid=%d !", TSKID(runtsk));
+			kernel_exit();
+		}
+		else{
+			syslog_1(LOG_ERROR, "Irregular Interrupt occured in tskid=%d  !", TSKID(runtsk));
+			isus_tsk(TSKID(runtsk));
+		}
+	}
+	else{
+		syslog_0(LOG_EMERG, "Irregular Interrupt occured in Idle!");
+		kernel_exit();
+	}
+}
+
+/*
+ * イレギュラーエクセプション
+ */
+void
+irregular_ext_handler(VP p_excinf)
+{
+	UW pc = get_exception_pc(p_excinf);
+
+	if(runtsk){
+		if(exc_sense_context(p_excinf)){
+			syslog_1(LOG_EMERG, "Irregular Exception occured in not task Context pc=0x%x !", pc);
+			kernel_exit();
+		}
+		else{
+			syslog_2(LOG_ERROR, "Irregular Exception occured in tskid=%d pc=0x%x !", TSKID(runtsk), pc);
+			isus_tsk(TSKID(runtsk));
+		}
+	}
+	else{
+		syslog_1(LOG_EMERG, "Irregular Exception occured in Idle pc=0x%x !", pc);
+		kernel_exit();
+	}
+}
+#endif
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/arch/powerpc32.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/arch/powerpc32.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/arch/powerpc32.c	(revision 453)
@@ -0,0 +1,351 @@
+/*
+ *  TOPPERS/ASP Educative Program
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Just Standard Profile Kernel
+ * 
+ *  Copyright (C) 2003-2009 by Ryosuke Takeuchi
+ *                     GJ Business Division RICOH COMPANY,LTD. JAPAN
+ * 
+ *  上記著作権者は，Free Software Foundation によって公表されている 
+ *  GNU General Public License の Version 2 に記述されている条件か，以
+ *  下の(1)～(4)の条件を満たす場合に限り，本ソフトウェア（本ソフトウェ
+ *  アを改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを再利用可能なバイナリコード（リロケータブルオブ
+ *      ジェクトファイルやライブラリなど）の形で利用する場合には，利用
+ *      に伴うドキュメント（利用者マニュアルなど）に，上記の著作権表示，
+ *      この利用条件および下記の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを再利用不可能なバイナリコードの形または機器に組
+ *      み込んだ形で利用する場合には，次のいずれかの条件を満たすこと．
+ *    (a) 利用に伴うドキュメント（利用者マニュアルなど）に，上記の著作
+ *        権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 利用の形態を，別に定める方法によって，上記著作権者に報告する
+ *        こと．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者を免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者は，
+ *  本ソフトウェアに関して，その適用可能性も含めて，いかなる保証も行わ
+ *  ない．また，本ソフトウェアの利用により直接的または間接的に生じたい
+ *  かなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/* 
+ *  TOPPERS/JSP用タスクモニタCPU依存プログラム．
+ *
+ */
+
+#include <itron.h>
+#include <sil.h>
+#include <stdio.h>
+#include "kernel_impl.h"
+#include "task.h"
+#include "task_expansion.h"
+#ifdef SUPPORT_ETHER
+#include "netdevice.h"
+#endif
+#include "monitor.h"
+
+extern void _kernel_break_wait();
+
+#define set_align(a, b)	((UW)a & ~(b-1))
+
+/*
+ * レジスタの構造体
+ */
+typedef struct t_reg{
+#ifdef SUPPORT_FLOATING_POINT_REG
+	UW  memo_msr;
+	UW  memo_off;
+	UW  fps[33*2+1];
+#endif	/* SUPPORT_FLOATING_POINT_REG */
+	UW  r13;
+	UW  r14;
+	UW  r15;
+	UW  r16;
+	UW  r17;
+	UW  r18;
+	UW  r19;
+	UW  r20;
+	UW  r21;
+	UW  r22;
+	UW  r23;
+	UW  r24;
+	UW  r25;
+	UW  r26;
+	UW  r27;
+	UW  r28;
+	UW  r29;
+	UW  r30;
+	UW  r31;
+	UW  lr2;
+
+	UW	r0;
+	UW	r3;
+	UW	r4;
+	UW	r5;
+	UW	r6;
+	UW	r7;
+	UW	r8;
+	UW	r9;
+	UW	r10;
+	UW	r11;
+	UW	r12;
+	UW	srr0;
+	UW	srr1;
+	UW  lr;
+	UW	ctr;
+	UW	cr;
+	UW	xer;
+	UW  dummy;
+}T_REG;
+
+/*
+ * メモリのマッピング定義構造体
+ */
+
+typedef struct t_memdef{
+	UW	mstart;
+	UW	mend;
+	UB	mtype;
+	UB	mstate;
+}T_MEMDEF;
+
+/*
+ * POWERPC32のメモリマッピング
+ */
+
+static T_MEMDEF const memdefine[] = {
+	{0x00000000, 0x0FFFFFFF, MEMORY_AREA, MREAD_WRITE},
+#ifdef SUPPORT_MIRROR_MEMORY
+	{0x20000000, 0x2FFFFFFF, MEMORY_AREA, MREAD_WRITE},
+#endif
+#if defined(SANTAMARIA)
+	{0xEC000000, 0xEC7FFFFF, MEMORY_AREA, MREAD_ONLY },
+	{0xFF400000, 0xFF4FFFFF, PORT_AREA,   MREAD_WRITE},
+	{0xFFF00000, 0xFFFFFFFF, MEMORY_AREA, MREAD_ONLY }
+#elif defined(EP440XC)
+	{0xE0000000, 0xE00004FF, PORT_AREA,   MREAD_ONLY },
+	{0xE0010000, 0xE0013FFF, MEMORY_AREA, MREAD_WRITE},
+	{0xEF600000, 0xEF6011FF, PORT_AREA,   MREAD_WRITE},
+	{0xFFF00000, 0xFFFFFFFF, MEMORY_AREA, MREAD_ONLY }
+#elif defined(EP460XC)
+	{0xD8000000, 0xD8FFFFFF, PORT_AREA,   MREAD_WRITE},
+	{0xE2000000, 0xE20FFFFF, PORT_AREA,   MREAD_WRITE},
+	{0xEF600000, 0xEF6011FF, PORT_AREA,   MREAD_WRITE},
+	{0xFFF00000, 0xFFFFFFFF, MEMORY_AREA, MREAD_ONLY }
+#else
+#error "No board type in POWERPC32 groups."
+#endif
+};
+
+static T_REG  sreg;
+
+/******************************************************************************
+ * ハードウェアポート属性参照関数
+ ******************************************************************************/
+/*
+ *  アドレスからメモリ領域属性を取り出す
+ *  mode=0:領域の型
+ *  mode=1:読み取り書き込み属性
+ */
+
+UB
+getMemoryType(UW address, INT mode)
+{
+	INT count = sizeof(memdefine) / sizeof(T_MEMDEF);
+	INT i;
+
+	for(i = 0 ; i < count ; i++){
+		if(address >= memdefine[i].mstart && address <= memdefine[i].mend){
+			if(mode == 0)
+				return memdefine[i].mtype;
+			else
+				return memdefine[i].mstate;
+		}
+	}
+	return NONE_AREA;
+}
+
+/*
+ *  アドレスからアライン後のアドレスを取り出す
+ */
+
+UW
+MonAlignAddress(UW address)
+{
+	return address;
+}
+
+/******************************************************************************
+ * メモリアクセス用関数
+ ******************************************************************************/
+/*
+ *  メモリ領域に対する読み出し関数
+ *  領域のチェックを行い、エラーならゼロを返す
+ */
+INT
+MemoryRead(UW address, VP_INT p, INT type)
+{
+	INT  len;
+
+	switch(getMemoryType(address, 0)){
+	case PORT_AREA:
+		if(type == 2){
+			len = 2;
+#ifdef PANEL_SIMULATION
+            if(!NetDeviceRead((unsigned long)address, len, (void *)p))
+#endif
+			asm("eieio");
+			*((UH *)p) = sil_reh_mem((VP)address);
+		}
+		else if(type == 4){
+			len = 4;
+#ifdef PANEL_SIMULATION
+            if(!NetDeviceRead((unsigned long)address, len, (void *)p))
+#endif
+			*((UW *)p) = sil_rew_mem_ppc((VP)address);
+		}
+		else{
+#ifdef PANEL_SIMULATION
+			len = 1;
+            if(!NetDeviceRead((unsigned long)address, len, (void *)p))
+				*((UB *)p) = sil_reb_mem_ppc((VP)address);
+#else
+			len = 1;
+			*((UB *)p) = sil_reb_mem_ppc((VP)address);
+#endif
+		}
+		break;
+	case MEMORY_AREA:
+		if(type == 2){
+			len = 2;
+			*((UH *)p) = *((UH *)set_align(address, len));
+		}
+		else if(type == 4){
+			len = 4;
+			*((UW *)p) = *((UW *)set_align(address, len));
+		}
+		else{
+			len = 1;
+			*((UB *)p) = *((UB *)address);
+		}
+		break;
+	default:
+		len = 0;
+		break;
+	}
+	return len;
+}
+
+/*
+ *  メモリ領域に対する書き込み関数
+ *  領域のチェックを行い、エラーならゼロを返す
+ */
+INT
+MemoryWrite(UW address, VP_INT p, INT type)
+{
+	INT  len;
+
+	switch(getMemoryType(address, 0)){
+	case PORT_AREA:
+		if(type == 2){
+			len = 2;
+			address = set_align(address, len);
+#ifdef PANEL_SIMULATION
+            if(!NetDeviceWrite((unsigned long)address, len, (void *)p))
+#endif
+			sil_wrh_mem((VP)address, *((UH *)p));
+		}
+		else if(type == 4){
+			len = 4;
+			address = set_align(address, len);
+#ifdef PANEL_SIMULATION
+            if(!NetDeviceWrite((unsigned long)address, len, (void *)p))
+#endif
+			sil_wrw_mem((VP)address, *((UW *)p));
+		}
+		else{
+#ifdef PANEL_SIMULATION
+			len = 1;
+            if(!NetDeviceWrite((unsigned long)address, len, (void *)p))
+				sil_wrb_mem((VP)address, *((UB *)p));
+#else
+			len = 1;
+			sil_wrb_mem((VP)address, *((UB *)p));
+#endif
+		}
+		break;
+	case MEMORY_AREA:
+		if(getMemoryType(address, 1) == MREAD_ONLY){
+			len = 0;
+		}
+		else if(type == 2){
+			len = 2;
+			*((UH *)address) = *((UH *)set_align(p, len));
+		}
+		else if(type == 4){
+			len = 4;
+			*((UW *)address) = *((UW *)set_align(p, len));
+		}
+		else{
+			len = 1;
+			*((UB *)address) = *((UB *)p);
+		}
+		break;
+	default:
+		len = 0;
+		break;
+	}
+	return len;
+}
+
+/******************************************************************************
+ * モニタ用関数
+ ******************************************************************************/
+/*
+ *  レジスタ内容の表示
+ */
+void
+display_registers(ID tskid)
+{
+	ER     ercd;
+	T_RTST rtst;
+
+	ercd = ref_tst(tskid, &rtst);
+	if(ercd == E_OK){
+		if(rtst.tskpc == (FP)_kernel_break_wait){
+			sreg = *((T_REG *)(rtst.tsksp-4));
+			printf(" PC =%08lx SP =%08x MSR =%08x", (long)sreg.srr0, (UW)((long)rtst.tsksp+sizeof(T_REG)), sreg.srr1);
+			printf(" LR =%08x CTR=%08x CR=%08x\n", sreg.lr, sreg.ctr, sreg.cr);
+			printf(" R0 =%08x R3 =%08x R4 =%08x", sreg.r0, sreg.r3, sreg.r4);
+			printf(" R5 =%08x R6 =%08x R7 =%08x\n", sreg.r5, sreg.r6, sreg.r7);
+			printf(" R8 =%08x R9 =%08x R10=%08x", sreg.r8, sreg.r9, sreg.r10);
+			printf(" R11=%08x R12=%08x R13=%08x\n", sreg.r11, sreg.r12, sreg.r13);
+			printf(" R14=%08x R15=%08x R16=%08x\n", sreg.r14, sreg.r15, sreg.r16);
+			printf(" R17=%08x R18=%08x R19=%08x\n", sreg.r17, sreg.r18, sreg.r19);
+			printf(" R20=%08x R21=%08x R22=%08x\n", sreg.r20, sreg.r21, sreg.r22);
+			printf(" R23=%08x R24=%08x R25=%08x\n", sreg.r23, sreg.r24, sreg.r25);
+			printf(" R26=%08x R27=%08x R28=%08x\n", sreg.r26, sreg.r27, sreg.r28);
+			printf(" R29=%08x R30=%08x R31=%08x\n", sreg.r29, sreg.r30, sreg.r31);
+			printf(" XER=%08x\n", sreg.xer);
+			printf("     %08lx    %08x\n", (long)sreg.srr0, *((UW*)sreg.srr0));
+			return;
+		}
+		else if(rtst.tskstat == TTS_DMT){
+			printf("  wait in activate_r() !!\n");
+			return;
+		}
+	}
+	printf("  wait in dispatch() !!\n");
+}
+
+
+void __va_arg_type_violation(void)
+{}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/arch/riscv32.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/arch/riscv32.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/arch/riscv32.c	(revision 453)
@@ -0,0 +1,261 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2003-2016 by Ryosuke Takeuchi
+ *                     GJ Business Division RICOH COMPANY,LTD. JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，Free Software Foundation によって公表されている 
+ *  GNU General Public License の Version 2 に記述されている条件か，以
+ *  下の(1)～(4)の条件を満たす場合に限り，本ソフトウェア（本ソフトウェ
+ *  アを改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを再利用可能なバイナリコード（リロケータブルオブ
+ *      ジェクトファイルやライブラリなど）の形で利用する場合には，利用
+ *      に伴うドキュメント（利用者マニュアルなど）に，上記の著作権表示，
+ *      この利用条件および下記の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを再利用不可能なバイナリコードの形または機器に組
+ *      み込んだ形で利用する場合には，次のいずれかの条件を満たすこと．
+ *    (a) 利用に伴うドキュメント（利用者マニュアルなど）に，上記の著作
+ *        権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 利用の形態を，別に定める方法によって，上記著作権者に報告する
+ *        こと．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者を免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者は，
+ *  本ソフトウェアに関して，その適用可能性も含めて，いかなる保証も行わ
+ *  ない．また，本ソフトウェアの利用により直接的または間接的に生じたい
+ *  かなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/* 
+ *  TOPPERS/ASP用タスクモニタCPU依存プログラム．
+ *
+ */
+
+#include <itron.h>
+#include <sil.h>
+#include <stdio.h>
+#include "kernel_impl.h"
+#include "task.h"
+#include "task_expansion.h"
+#include "monitor.h"
+
+extern void dispatch_r(void);
+
+#define set_align(a, b)	((ulong_t)a & ~(b-1))
+
+/*
+ * レジスタの構造体
+ */
+typedef struct t_reg{
+	uint32_t ra;
+	uint32_t gp;
+	uint32_t tp;
+	uint32_t s0;
+	uint32_t s1;
+	uint32_t s2;
+	uint32_t s3;
+	uint32_t s4;
+	uint32_t s5;
+}T_REG;
+
+/*
+ * メモリのマッピング定義構造体
+ */
+
+typedef struct t_memdef{
+	uint32_t mstart;
+	uint32_t mend;
+	uint8_t  mtype;
+	uint8_t  mstate;
+}T_MEMDEF;
+
+/*
+ * RISC-V/32のメモリマッピング
+ */
+
+static T_MEMDEF const memdefine[] = {
+	{0x00000000, 0x1FFFFFFF,           PORT_AREA,   MREAD_WRITE},
+#if defined(TOPPERS_HIFIVE1)
+	{0x20000000, 0x3FFFFFFF,           MEMORY_AREA, MREAD_ONLY },
+	{0x80000000, 0x80003FFF,           MEMORY_AREA, MREAD_WRITE},
+#else
+#error "No support board type in RISC-V/32 groups."
+#endif
+};
+
+static T_REG  sreg;
+
+/******************************************************************************
+ * ハードウェアポート属性参照関数
+ ******************************************************************************/
+/*
+ *  アドレスからメモリ領域属性を取り出す
+ *  mode=0:領域の型
+ *  mode=1:読み取り書き込み属性
+ */
+
+char
+getMemoryType(ulong_t address, int_t mode)
+{
+	int_t count = sizeof(memdefine) / sizeof(T_MEMDEF);
+	int_t i;
+
+	for(i = 0 ; i < count ; i++){
+		if(address >= memdefine[i].mstart && address <= memdefine[i].mend){
+			if(mode == 0)
+				return memdefine[i].mtype;
+			else
+				return memdefine[i].mstate;
+		}
+	}
+	return NONE_AREA;
+}
+
+/*
+ *  アドレスからアライン後のアドレスを取り出す
+ */
+
+ulong_t
+MonAlignAddress(ulong_t address)
+{
+	return address;
+}
+
+/******************************************************************************
+ * メモリアクセス用関数
+ ******************************************************************************/
+/*
+ *  メモリ領域に対する読み出し関数
+ *  領域のチェックを行い、エラーならゼロを返す
+ */
+int_t
+MemoryRead(ulong_t address, intptr_t p, int_t type)
+{
+	int_t len;
+
+	switch(getMemoryType(address, 0)){
+	case PORT_AREA:
+		if(type == 2){
+			len = 2;
+			*((UH *)p) = sil_reh_mem((VP)address);
+		}
+		else if(type == 4){
+			len = 4;
+			*((UW *)p) = sil_rew_mem((VP)address);
+		}
+		else{
+			len = 1;
+			*((UB *)p) = sil_reb_mem((VP)address);
+		}
+		break;
+	case MEMORY_AREA:
+		if(type == 2){
+			len = 2;
+			*((UH *)p) = *((UH *)set_align(address, len));
+		}
+		else if(type == 4){
+			len = 4;
+			*((UW *)p) = *((UW *)set_align(address, len));
+		}
+		else{
+			len = 1;
+			*((UB *)p) = *((UB *)address);
+		}
+		break;
+	default:
+		len = 0;
+		break;
+	}
+	return len;
+}
+
+/*
+ *  メモリ領域に対する書き込み関数
+ *  領域のチェックを行い、エラーならゼロを返す
+ */
+int_t
+MemoryWrite(ulong_t address, intptr_t p, int_t type)
+{
+	int_t len;
+
+	switch(getMemoryType(address, 0)){
+	case PORT_AREA:
+		if(type == 2){
+			len = 2;
+			address = set_align(address, len);
+			sil_wrh_mem((VP)address, *((UH *)p));
+		}
+		else if(type == 4){
+			len = 4;
+			address = set_align(address, len);
+			sil_wrw_mem((VP)address, *((UW *)p));
+		}
+		else{
+			len = 1;
+			sil_wrb_mem((VP)address, *((UB *)p));
+		}
+		break;
+	case MEMORY_AREA:
+		if(getMemoryType(address, 1) == MREAD_ONLY){
+			len = 0;
+		}
+		else if(type == 2){
+			len = 2;
+			*((UH *)address) = *((UH *)set_align(p, len));
+		}
+		else if(type == 4){
+			len = 4;
+			*((UW *)address) = *((UW *)set_align(p, len));
+		}
+		else{
+			len = 1;
+			*((UB *)address) = *((UB *)p);
+		}
+		break;
+	default:
+		len = 0;
+		break;
+	}
+	return len;
+}
+
+/******************************************************************************
+ * モニタ用関数
+ ******************************************************************************/
+/*
+ *  レジスタ内容の表示
+ */
+void
+display_registers(ID tskid)
+{
+	ER     ercd;
+	T_RTST rtst;
+
+	ercd = ref_tst(tskid, &rtst);
+	if(ercd == E_OK){
+		if(rtst.tskpc == (FP)dispatch_r){
+			sreg = *((T_REG *)rtst.tsksp);
+			printf(" RA  =%08lx SP =%08x\n", (long)sreg.ra, (UW)((long)rtst.tsksp+sizeof(T_REG)));
+			printf(" GP  =%08x TP =%08x S0 =%08x S1 =%08x\n", sreg.gp, sreg.tp, sreg.s0, sreg.s1);
+			printf(" S2  =%08x S3 =%08x S4 =%08x S5 =%08x\n", sreg.s2, sreg.s3, sreg.s4, sreg.s5);
+			printf("     %08lx    %04x\n", (long)sreg.ra, *((UH*)(sreg.ra & ~1)));
+			return;
+		}
+		else if(rtst.tskstat == TTS_DMT){
+			printf("  wait in activate_r() !!\n");
+			return;
+		}
+	}
+	printf("  wait in dispatch() !!\n");
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/arch/riscv64.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/arch/riscv64.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/arch/riscv64.c	(revision 453)
@@ -0,0 +1,265 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2003-2016 by Ryosuke Takeuchi
+ *                     GJ Business Division RICOH COMPANY,LTD. JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，Free Software Foundation によって公表されている 
+ *  GNU General Public License の Version 2 に記述されている条件か，以
+ *  下の(1)～(4)の条件を満たす場合に限り，本ソフトウェア（本ソフトウェ
+ *  アを改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを再利用可能なバイナリコード（リロケータブルオブ
+ *      ジェクトファイルやライブラリなど）の形で利用する場合には，利用
+ *      に伴うドキュメント（利用者マニュアルなど）に，上記の著作権表示，
+ *      この利用条件および下記の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを再利用不可能なバイナリコードの形または機器に組
+ *      み込んだ形で利用する場合には，次のいずれかの条件を満たすこと．
+ *    (a) 利用に伴うドキュメント（利用者マニュアルなど）に，上記の著作
+ *        権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 利用の形態を，別に定める方法によって，上記著作権者に報告する
+ *        こと．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者を免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者は，
+ *  本ソフトウェアに関して，その適用可能性も含めて，いかなる保証も行わ
+ *  ない．また，本ソフトウェアの利用により直接的または間接的に生じたい
+ *  かなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/* 
+ *  TOPPERS/ASP用タスクモニタCPU依存プログラム．
+ *
+ */
+
+#include <itron.h>
+#include <sil.h>
+#include <stdio.h>
+#include "kernel_impl.h"
+#include "task.h"
+#include "task_expansion.h"
+#include "monitor.h"
+
+extern void dispatch_r(void);
+
+#define set_align(a, b)	((ulong_t)a & ~(b-1))
+
+/*
+ * レジスタの構造体
+ */
+typedef struct t_reg{
+	unsigned long ra;
+	unsigned long gp;
+	unsigned long tp;
+	unsigned long s0;
+	unsigned long s1;
+	unsigned long s2;
+	unsigned long s3;
+	unsigned long s4;
+	unsigned long s5;
+}T_REG;
+
+/*
+ * メモリのマッピング定義構造体
+ */
+
+typedef struct t_memdef{
+	uintptr_t mstart;
+	uint32_t  mend;
+	uint8_t   mtype;
+	uint8_t   mstate;
+}T_MEMDEF;
+
+/*
+ * RISC-V/64のメモリマッピング
+ */
+
+static T_MEMDEF const memdefine[] = {
+	{0x02000000L, 0x02FFFFFFL,         PORT_AREA,   MREAD_WRITE},
+	{0x0C000000L, 0x0CFFFFFFL,         PORT_AREA,   MREAD_WRITE},
+	{0x38000000L, 0x3807FFFFL,         PORT_AREA,   MREAD_WRITE},
+	{0x40000000L, 0x413FFFFFL,         PORT_AREA,   MREAD_WRITE},
+	{0x50000000L, 0x543FFFFFL,         PORT_AREA,   MREAD_WRITE},
+#if defined(TOPPERS_K210)
+	{0x80000000L, 0x807FFFFFL,         MEMORY_AREA, MREAD_WRITE},
+	{0x88000000L, 0x881FFFFFL,         MEMORY_AREA, MREAD_ONLY },
+#else
+#error "No support board type in RISC-V/64 groups."
+#endif
+};
+
+static T_REG  sreg;
+
+/******************************************************************************
+ * ハードウェアポート属性参照関数
+ ******************************************************************************/
+/*
+ *  アドレスからメモリ領域属性を取り出す
+ *  mode=0:領域の型
+ *  mode=1:読み取り書き込み属性
+ */
+
+char
+getMemoryType(ulong_t address, int_t mode)
+{
+	int_t count = sizeof(memdefine) / sizeof(T_MEMDEF);
+	int_t i;
+
+	for(i = 0 ; i < count ; i++){
+		if(address >= memdefine[i].mstart && address <= memdefine[i].mend){
+			if(mode == 0)
+				return memdefine[i].mtype;
+			else
+				return memdefine[i].mstate;
+		}
+	}
+	return NONE_AREA;
+}
+
+/*
+ *  アドレスからアライン後のアドレスを取り出す
+ */
+
+ulong_t
+MonAlignAddress(ulong_t address)
+{
+	return address;
+}
+
+/******************************************************************************
+ * メモリアクセス用関数
+ ******************************************************************************/
+/*
+ *  メモリ領域に対する読み出し関数
+ *  領域のチェックを行い、エラーならゼロを返す
+ */
+int_t
+MemoryRead(ulong_t address, intptr_t p, int_t type)
+{
+	int_t len;
+
+	switch(getMemoryType(address, 0)){
+	case PORT_AREA:
+		if(type == 2){
+			len = 2;
+			*((UH *)p) = sil_reh_mem((VP)address);
+		}
+		else if(type == 4){
+			len = 4;
+			*((UW *)p) = sil_rew_mem((VP)address);
+		}
+		else{
+			len = 1;
+			*((UB *)p) = sil_reb_mem((VP)address);
+		}
+		break;
+	case MEMORY_AREA:
+		if(type == 2){
+			len = 2;
+			*((UH *)p) = *((UH *)set_align(address, len));
+		}
+		else if(type == 4){
+			len = 4;
+			*((UW *)p) = *((UW *)set_align(address, len));
+		}
+		else{
+			len = 1;
+			*((UB *)p) = *((UB *)address);
+		}
+		break;
+	default:
+		len = 0;
+		break;
+	}
+	return len;
+}
+
+/*
+ *  メモリ領域に対する書き込み関数
+ *  領域のチェックを行い、エラーならゼロを返す
+ */
+int_t
+MemoryWrite(ulong_t address, intptr_t p, int_t type)
+{
+	int_t len;
+
+	switch(getMemoryType(address, 0)){
+	case PORT_AREA:
+		if(type == 2){
+			len = 2;
+			address = set_align(address, len);
+			sil_wrh_mem((VP)address, *((UH *)p));
+		}
+		else if(type == 4){
+			len = 4;
+			address = set_align(address, len);
+			sil_wrw_mem((VP)address, *((UW *)p));
+		}
+		else{
+			len = 1;
+			sil_wrb_mem((VP)address, *((UB *)p));
+		}
+		break;
+	case MEMORY_AREA:
+		if(getMemoryType(address, 1) == MREAD_ONLY){
+			len = 0;
+		}
+		else if(type == 2){
+			len = 2;
+			*((UH *)address) = *((UH *)set_align(p, len));
+		}
+		else if(type == 4){
+			len = 4;
+			*((UW *)address) = *((UW *)set_align(p, len));
+		}
+		else{
+			len = 1;
+			*((UB *)address) = *((UB *)p);
+		}
+		break;
+	default:
+		len = 0;
+		break;
+	}
+	return len;
+}
+
+/******************************************************************************
+ * モニタ用関数
+ ******************************************************************************/
+/*
+ *  レジスタ内容の表示
+ */
+void
+display_registers(ID tskid)
+{
+	ER     ercd;
+	T_RTST rtst;
+
+	ercd = ref_tst(tskid, &rtst);
+	if(ercd == E_OK){
+		if(rtst.tskpc == (FP)dispatch_r){
+			sreg = *((T_REG *)rtst.tsksp);
+			printf(" RA  =%lx SP =%lx\n", (long)sreg.ra, (long)((long)rtst.tsksp+sizeof(T_REG)));
+			printf(" GP  =%lx TP =%lx S0 =%lx S1 =%lx\n", sreg.gp, sreg.tp, sreg.s0, sreg.s1);
+			printf(" S2  =%lx S3 =%lx S4 =%lx S5 =%lx\n", sreg.s2, sreg.s3, sreg.s4, sreg.s5);
+			printf("     %lx    %04x\n", (long)sreg.ra, *((UH*)(sreg.ra & ~1)));
+			return;
+		}
+		else if(rtst.tskstat == TTS_DMT){
+			printf("  wait in activate_r() !!\n");
+			return;
+		}
+	}
+	printf("  wait in dispatch() !!\n");
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/arch/sh2.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/arch/sh2.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/arch/sh2.c	(revision 453)
@@ -0,0 +1,396 @@
+/*
+ *  TOPPERS/ASP Educative Program
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Just Standard Profile Kernel
+ * 
+ *  Copyright (C) 2003-2008 by Ryosuke Takeuchi
+ *                     GJ Business Division RICOH COMPANY,LTD. JAPAN
+ * 
+ *  上記著作権者は，Free Software Foundation によって公表されている 
+ *  GNU General Public License の Version 2 に記述されている条件か，以
+ *  下の(1)～(4)の条件を満たす場合に限り，本ソフトウェア（本ソフトウェ
+ *  アを改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを再利用可能なバイナリコード（リロケータブルオブ
+ *      ジェクトファイルやライブラリなど）の形で利用する場合には，利用
+ *      に伴うドキュメント（利用者マニュアルなど）に，上記の著作権表示，
+ *      この利用条件および下記の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを再利用不可能なバイナリコードの形または機器に組
+ *      み込んだ形で利用する場合には，次のいずれかの条件を満たすこと．
+ *    (a) 利用に伴うドキュメント（利用者マニュアルなど）に，上記の著作
+ *        権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 利用の形態を，別に定める方法によって，上記著作権者に報告する
+ *        こと．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者を免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者は，
+ *  本ソフトウェアに関して，その適用可能性も含めて，いかなる保証も行わ
+ *  ない．また，本ソフトウェアの利用により直接的または間接的に生じたい
+ *  かなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/* 
+ *  TOPPERS/ASP用タスクモニタCPU依存プログラム．
+ *
+ */
+
+#include <itron.h>
+#include <sil.h>
+#include <stdio.h>
+#include "kernel_impl.h"
+#include "task.h"
+#include "task_expansion.h"
+#ifdef SUPPORT_ETHER
+#include "netdevice.h"
+#endif
+#include "monitor.h"
+
+extern void _kernel_break_wait();
+#ifdef SUPPORT_ETHER
+extern unsigned long vectors[];
+#endif
+
+#define set_align(a, b)	((UW)a & ~(b-1))
+
+/*
+ * レジスタの構造体
+ */
+typedef struct t_reg{
+	uint32_t gbr;
+	uint32_t macl;
+	uint32_t mach;
+	uint32_t r14;
+	uint32_t r13;
+	uint32_t r12;
+	uint32_t r11;
+	uint32_t r10;
+	uint32_t r9;
+	uint32_t r8;
+	uint32_t pr;
+	uint32_t r7;
+	uint32_t r6;
+	uint32_t r5;
+	uint32_t r4;
+	uint32_t r3;
+	uint32_t r2;
+	uint32_t r1;
+	uint32_t r0;
+	uint32_t pc;
+	uint32_t sr;
+}T_REG;
+
+/*
+ * メモリのマッピング定義構造体
+ */
+
+typedef struct t_memdef{
+	uint32_t mstart;
+	uint32_t mend;
+	uint8_t  mtype;
+	uint8_t  mstate;
+}T_MEMDEF;
+
+/*
+ * SH2のメモリマッピング
+ */
+
+static T_MEMDEF const memdefine[] = {
+#if defined(HSB7616IT)
+	{0x00000000, 0x0001FFFF, MEMORY_AREA, MREAD_ONLY },
+	{0x02000000, 0x021FFFFF, MEMORY_AREA, MREAD_ONLY },
+	{0x04000000, 0x040FFFFF, MEMORY_AREA, MREAD_WRITE},
+	{0xFFFFE000, 0xFFFFFFFF, PORT_AREA,   MREAD_WRITE}
+#elif defined(MS72060SEP01)
+	{0x00000000, 0x001FFFFF, MEMORY_AREA, MREAD_ONLY },
+	{0x01000000, 0x01FFFFFF, MEMORY_AREA, MREAD_ONLY },
+	{0x0C000000, 0x0FFFFFFF, MEMORY_AREA, MREAD_WRITE},
+	{0x10000000, 0xFFF7FFFF, PORT_AREA,   MREAD_WRITE},
+	{0xFFF80000, 0xFFF9FFFF, MEMORY_AREA, MREAD_WRITE},
+	{0xFFFA0000, 0xFFFFFFFF, PORT_AREA,   MREAD_WRITE}
+#elif defined(CRB_H3)
+	{0x00000000, 0x0003FFFF, MEMORY_AREA, MREAD_ONLY },
+	{0x00200000, 0x0021FFFF, MEMORY_AREA, MREAD_WRITE},
+	{0x00220000, 0x0022FFFF, MEMORY_AREA, MREAD_ONLY },
+	{0x00230000, 0x0023FFFF, PORT_AREA,   MREAD_WRITE},
+	{0xFFF00000, 0xFFFCFFFF, PORT_AREA,   MREAD_WRITE},
+	{0xFFFD0000, 0xFFFFFFFF, MEMORY_AREA, MREAD_WRITE}
+#else
+#error "No board type in SH2 groups."
+#endif
+};
+
+static T_REG  sreg;
+
+/******************************************************************************
+ * ハードウェアポート属性参照関数
+ ******************************************************************************/
+/*
+ *  アドレスからメモリ領域属性を取り出す
+ *  mode=0:領域の型
+ *  mode=1:読み取り書き込み属性
+ */
+
+char
+getMemoryType(ulong_t address, int_t mode)
+{
+	int_t count = sizeof(memdefine) / sizeof(T_MEMDEF);
+	int_t i;
+
+	for(i = 0 ; i < count ; i++){
+		if(address >= memdefine[i].mstart && address <= memdefine[i].mend){
+			if(mode == 0)
+				return memdefine[i].mtype;
+			else
+				return memdefine[i].mstate;
+		}
+	}
+	return NONE_AREA;
+}
+
+/*
+ *  アドレスからアライン後のアドレスを取り出す
+ */
+
+ulong_t
+MonAlignAddress(ulong_t address)
+{
+	return address;
+}
+
+/******************************************************************************
+ * メモリアクセス用関数
+ ******************************************************************************/
+/*
+ *  メモリ領域に対する読み出し関数
+ *  領域のチェックを行い、エラーならゼロを返す
+ */
+int_t
+MemoryRead(ulong_t address, intptr_t p, int_t type)
+{
+	int_t len;
+
+	switch(getMemoryType(address, 0)){
+	case PORT_AREA:
+		if(type == 2){
+			len = 2;
+#ifdef SUPPORT_ETHER
+            if(!NetDeviceRead((unsigned long)address, len, (void *)p))
+#endif
+			*((UH *)p) = sil_reh_mem((VP)address);
+		}
+		else if(type == 4){
+			len = 4;
+#ifdef SUPPORT_ETHER
+            if(!NetDeviceRead((unsigned long)address, len, (void *)p))
+#endif
+			*((UW *)p) = sil_rew_mem((VP)address);
+		}
+		else{
+#ifdef SUPPORT_ETHER
+			len = 1;
+            if(!NetDeviceRead((unsigned long)address, len, (void *)p))
+				*((UB *)p) = sil_reb_mem((VP)address);
+#else
+			len = 1;
+			*((UB *)p) = sil_reb_mem((VP)address);
+#endif
+		}
+		break;
+	case MEMORY_AREA:
+		if(type == 2){
+			len = 2;
+			*((UH *)p) = *((UH *)set_align(address, len));
+		}
+		else if(type == 4){
+			len = 4;
+			*((UW *)p) = *((UW *)set_align(address, len));
+		}
+		else{
+			len = 1;
+			*((UB *)p) = *((UB *)address);
+		}
+		break;
+	default:
+		len = 0;
+		break;
+	}
+	return len;
+}
+
+/*
+ *  メモリ領域に対する書き込み関数
+ *  領域のチェックを行い、エラーならゼロを返す
+ */
+int_t
+MemoryWrite(ulong_t address, intptr_t p, int_t type)
+{
+	int_t len;
+
+	switch(getMemoryType(address, 0)){
+	case PORT_AREA:
+		if(type == 2){
+			len = 2;
+			address = set_align(address, len);
+#ifdef SUPPORT_ETHER
+            if(!NetDeviceWrite((unsigned long)address, len, (void *)p))
+#endif
+			sil_wrh_mem((VP)address, *((UH *)p));
+		}
+		else if(type == 4){
+			len = 4;
+			address = set_align(address, len);
+#ifdef SUPPORT_ETHER
+            if(!NetDeviceWrite((unsigned long)address, len, (void *)p))
+#endif
+			sil_wrw_mem((VP)address, *((UW *)p));
+		}
+		else{
+#ifdef SUPPORT_ETHER
+			len = 1;
+            if(!NetDeviceWrite((unsigned long)address, len, (void *)p))
+				sil_wrb_mem((VP)address, *((UB *)p));
+#else
+			len = 1;
+			sil_wrb_mem((VP)address, *((UB *)p));
+#endif
+		}
+		break;
+	case MEMORY_AREA:
+		if(getMemoryType(address, 1) == MREAD_ONLY){
+			len = 0;
+		}
+		else if(type == 2){
+			len = 2;
+			*((UH *)address) = *((UH *)set_align(p, len));
+		}
+		else if(type == 4){
+			len = 4;
+			*((UW *)address) = *((UW *)set_align(p, len));
+		}
+		else{
+			len = 1;
+			*((UB *)address) = *((UB *)p);
+		}
+		break;
+	default:
+		len = 0;
+		break;
+	}
+	return len;
+}
+
+/******************************************************************************
+ * モニタ用関数
+ ******************************************************************************/
+/*
+ *  エクセプションの引数よりpcを取り出す関数
+ */
+ulong_t
+get_exception_pc(void * p_excinf)
+{
+	ulong_t pc;
+
+	pc = *(ulong_t*)((char*)p_excinf-4);
+	return pc;
+}
+
+/*
+ *  レジスタ内容の表示
+ */
+void
+display_registers(ID tskid)
+{
+	ER     ercd;
+	T_RTST rtst;
+
+	ercd = ref_tst(tskid, &rtst);
+	if(ercd == E_OK){
+		if(rtst.tskpc == (FP)_kernel_break_wait){
+			sreg = *((T_REG *)rtst.tsksp);
+			printf(" PC =%08lx SP =%08x PR =%08x", (long)sreg.pc, (UW)((long)rtst.tsksp+sizeof(T_REG)), sreg.pr);
+			printf(" SR =%08x MBH=%08x MBL=%08x\n", sreg.sr, sreg.mach, sreg.macl);
+			printf(" R0 =%08x R1 =%08x R2 =%08x", sreg.r0, sreg.r1, sreg.r2);
+			printf(" R3 =%08x R4 =%08x R5 =%08x\n", sreg.r3, sreg.r4, sreg.r5);
+			printf(" R6 =%08x R7 =%08x R8 =%08x", sreg.r6, sreg.r7, sreg.r8);
+			printf(" R9 =%08x R10=%08x R11=%08x\n", sreg.r9, sreg.r10, sreg.r11);
+			printf(" R12=%08x R13=%08x R14=%08x\n", sreg.r12, sreg.r13, sreg.r14);
+			printf("     %08lx    %02x %02x\n", (long)sreg.pc, *((UB*)sreg.pc), *((UB*)(sreg.pc+1)));
+			return;
+		}
+		else if(rtst.tskstat == TTS_DMT){
+			printf("  wait in activate_r() !!\n");
+			return;
+		}
+	}
+	printf("  wait in dispatch() !!\n");
+}
+
+/******************************************************************************
+ * エラー通知用関数
+ ******************************************************************************/
+/*
+ * イレギュラーエクセプション
+ */
+static void
+irregular_ext_handler(void *p_excinf, const char *s)
+{
+	uint32_t pc = get_exception_pc(p_excinf);
+
+	if(runtsk){
+		if(exc_sense_context(p_excinf)){
+			syslog_3(LOG_EMERG, "Irregular Exception(%s) occured in not task Context pc=0x%x p_excinf=0x%x !", s, pc, p_excinf);
+			kernel_exit();
+		}
+		else{
+			syslog_4(LOG_ERROR, "Irregular Exception(%s) occured in tskid=%d pc=0x%x p_excinf=0x%x !", s, TSKID(runtsk), pc, p_excinf);
+			isus_tsk(TSKID(runtsk));
+		}
+	}
+	else{
+		syslog_3(LOG_EMERG, "Irregular Exception(%s) occured in Idle pc=0x%x p_excinf=0x%x !", s, pc, p_excinf);
+		kernel_exit();
+	}
+}
+
+/*
+ *  一般不当命令:General Illegal Instruction
+ */
+void
+irregular_extgii_handler(void * p_excinf)
+{
+	irregular_ext_handler(p_excinf, "GII");
+}
+
+/*
+ *  スロット不当命令:Slot Illegal Instruction
+ */
+void
+irregular_extsii_handler(void * p_excinf)
+{
+	irregular_ext_handler(p_excinf, "SII");
+}
+
+/*
+ *  CPUアドレスエラー:CPU Address Error
+ */
+void
+irregular_extcae_handler(void * p_excinf)
+{
+	irregular_ext_handler(p_excinf, "CAE");
+}
+
+/*
+ *  DMAアドレスエラー:DMA Address Error
+ */
+void
+irregular_extdae_handler(void * p_excinf)
+{
+	irregular_ext_handler(p_excinf, "DAE");
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/monitor.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/monitor.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/monitor.c	(revision 453)
@@ -0,0 +1,1091 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2003-2015 by Ryosuke Takeuchi
+ *                     GJ Business Division RICOH COMPANY,LTD. JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，Free Software Foundation によって公表されている 
+ *  GNU General Public License の Version 2 に記述されている条件か，以
+ *  下の(1)～(4)の条件を満たす場合に限り，本ソフトウェア（本ソフトウェ
+ *  アを改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを再利用可能なバイナリコード（リロケータブルオブ
+ *      ジェクトファイルやライブラリなど）の形で利用する場合には，利用
+ *      に伴うドキュメント（利用者マニュアルなど）に，上記の著作権表示，
+ *      この利用条件および下記の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを再利用不可能なバイナリコードの形または機器に組
+ *      み込んだ形で利用する場合には，次のいずれかの条件を満たすこと．
+ *    (a) 利用に伴うドキュメント（利用者マニュアルなど）に，上記の著作
+ *        権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 利用の形態を，別に定める方法によって，上記著作権者に報告する
+ *        こと．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者を免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者は，
+ *  本ソフトウェアに関して，その適用可能性も含めて，いかなる保証も行わ
+ *  ない．また，本ソフトウェアの利用により直接的または間接的に生じたい
+ *  かなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/* 
+ *  TOPPERS/ASP用タスクモニタプログラム．
+ *
+ */
+
+#include <kernel.h>
+#include <stdio.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <string.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#include "task_expansion.h"
+#include "task.h"
+#include "kernel_cfg.h"
+#include "monitor.h"
+
+#ifndef NUM_ARGC
+#define NUM_ARGC    16
+#endif
+
+/*
+ *  サービスコールのエラーのログ出力
+ */
+Inline void
+svc_perror(const char *file, int_t line, const char *expr, ER ercd)
+{
+	if (ercd < 0) {
+		t_perror(LOG_ERROR, file, line, expr, ercd);
+	}
+}
+
+#define	SVC_PERROR(expr)	svc_perror(__FILE__, __LINE__, #expr, (expr))
+
+/*
+ *  モニタ内定義
+ */
+#define	HEX_VALUE			16			/* 16進指定 */
+#define	DEC_VALUE			10			/* 10進指定 */
+
+#define	MONDISPLAY_BYTE	DATA_BYTE	/* バイト単位メモリ表示 */
+#define	MONDISPLAY_HALF	DATA_HALF	/* ハーフ単位メモリ表示 */
+#define	MONDISPLAY_WORD	DATA_WORD	/* ワード単位メモリ表示 */
+#define	MONDISPLAY_TASK	3			/* タスク状態表示 */
+#define	MONDISPLAY_REG	5			/* レジスタの表示 */
+#define	MONDISPLAY_ASM	6
+
+#define	MONSET_BYTE		DATA_BYTE	/* バイト単位メモリ設定 */
+#define	MONSET_HALF		DATA_HALF	/* ハーフ単位メモリ設定 */
+#define	MONSET_WORD		DATA_WORD	/* ワード単位メモリ設定 */
+#define	MONSET_COMMAND	3			/* コマンドモード設定 */
+#define	MONSET_SERIAL	5			/* シリアル設定 */
+#define	MONSET_TASK		6			/* タスク設定 */
+#define MONSET_IN       7			/* 入力設定 */
+
+struct SUBCOMMAND_TABLE {
+	const char *subcommand;			/* サブコマンド文 */
+	const char type;				/* 実行タイプ */
+};
+
+/*
+ *  プロトタイプ宣言
+ *
+ *  このモジュール内で使用している関数
+ */
+static void    prompt(ID tskid);
+static int_t   dispatch_command(int argc, char **argv);
+static int_t   display_command(int argc, char **argv);
+static int_t   set_command(int argc, char **argv);
+static int_t   help_command(int argc, char **argv);
+static int_t   task_activate(int argc, char **argv);
+static int_t   task_terminate(int argc, char **argv);
+static int_t   task_suspend(int argc, char **argv);
+static int_t   task_resume(int argc, char **argv);
+static int_t   task_release(int argc, char **argv);
+static int_t   task_wakeup(int argc, char **argv);
+static int_t   task_priority(int argc, char **argv);
+static int_t   log_mode(int argc, char **argv);
+static int_t   log_task(int argc, char **argv);
+static int_t   log_port(int argc, char **argv);
+static uint_t  get_taskstate(STAT tskstat);
+static char    monitor_getstring(char *s, int *len);
+
+extern const char	*itron_strerror(ER ercd);
+
+/*
+ *  モニタバナー表示
+ */
+static char const banner[] = "\n"
+"ASP TASK Monitor Release %d.%d.%d for " TARGET_NAME
+" (" __DATE__ ", " __TIME__ ")\n"
+"Copyright (C) 2016-2019 by TOPPERS PROJECT Educational Working Group\n";
+
+/*
+ *  ヘルプメッセージ
+ */
+static char const display_help[] =
+"  Display BYTE     [start address] [end address]\n"
+"          HALF     [start address] [end address]\n"
+"          WORD     [start address] [end address]\n"
+"          TASK\n"
+"          REGISTER\n";
+
+static char const set_help[] =
+"  Set     BYTE     [start address]\n"
+"          HALF     [start address]\n"
+"          WORD     [start address]\n"
+"          COMMAND  [mode]  mode=1 or (2)\n"
+"          SERIAL   [port id]\n"
+"          TASK     [task id]\n";
+
+static char const task_help[] =
+"  Task    ACTIVATE          (act_tsk)\n"
+"          TERMINATE         (ter_tsk)\n"
+"          SUSPEND           (sus_tsk)\n"
+"          RESUME            (rsm_tsk)\n"
+"          RELEASE           (rel_tsk)\n"
+"          WAKEUP            (wup_tsk)\n"
+"          PRIORITY [pri]    (chg_pri)\n";
+
+static char const log_help[] =
+"  Log     MODE     [logmask] [lowmask]\n"
+"          TASK     [cycle time(ms)] [count]\n"
+"          PORT     [no] [logno] [portaddress]\n";
+
+static char const help_help[] =
+"  Help    [arg1]\n";
+
+/*
+ *  タスクコマンドサブテーブル
+ */
+static const COMMAND_INFO task_command_info[] = {
+	{"ACTIVATE",	task_activate},
+	{"TERMINATE",	task_terminate},
+	{"SUSPEND",		task_suspend},
+	{"RESUME",		task_resume},
+	{"RELEASE",		task_release},
+	{"WAKEUP",		task_wakeup},
+	{"PRIORITY",	task_priority}
+};
+
+/*
+ *  ログコマンドサブテーブル
+ */
+static const COMMAND_INFO log_command_info[] = {
+	{"MODE",		log_mode},
+	{"TASK",		log_task},
+	{"PORT",		log_port}
+};
+
+/*
+ *  メインコマンドテーブル
+ */
+static COMMAND_LINK const standard_command[] = {
+	{NULL,	0,	"DISPLAY",	display_command,	display_help,	NULL },
+	{NULL,	0,	"SET",		set_command,		set_help,		NULL },
+	{NULL,	7,	"TASK",		NULL,				task_help,		task_command_info },
+	{NULL,	3,	"LOG",		NULL,				log_help,		log_command_info },
+	{NULL,	0,	"HELP",		help_command,		help_help,		NULL }
+};
+
+/*
+ *  表示コマンドテーブル
+ */
+static struct SUBCOMMAND_TABLE const mon_display[] = {
+	{"BYTE",		MONDISPLAY_BYTE },	/* バイト単位メモリ表示 */
+	{"HALF",		MONDISPLAY_HALF },	/* ハーフ単位メモリ表示 */
+	{"WORD",		MONDISPLAY_WORD },	/* ワード単位メモリ表示 */
+	{"TASK",		MONDISPLAY_TASK },	/* タスク状態表示 */
+	{"REGISTER",	MONDISPLAY_REG  },	/* タスクレジスター表示 */
+	{"ASSEMBLER",	MONDISPLAY_ASM  }	/* アセンブラー表示 */
+};
+
+/*
+ *  設定コマンドテーブル
+ */
+static struct SUBCOMMAND_TABLE const mon_set[] = {
+	{"BYTE",		MONSET_BYTE     },	/* バイト単位メモリ設定 */
+	{"HALF",		MONSET_HALF     },	/* ハーフ単位メモリ設定 */
+	{"WORD",		MONSET_WORD     },	/* ワード単位メモリ設定 */
+	{"COMMAND",		MONSET_COMMAND  },	/* コマンドモード設定 */
+	{"SERIAL",		MONSET_SERIAL   },	/* シリアル設定 */
+	{"TASK",		MONSET_TASK     },	/* タスク選択 */
+	{"IN",			MONSET_IN       }	/* 入力設定 */
+};
+
+/*
+ *  バックスペース
+ */
+static const char backspace[] = "\b \b";
+
+/*
+ *  タスクモード表示テーブル
+ */
+#define	TSTATE_LEN		11
+
+static char const task_state[6][TSTATE_LEN] = {
+	"RUNNING",						/* 実行中 */
+	"RUNNABLE",						/* 実行できる状態 */
+	"WAITING",						/* 待ち状態 */
+	"SUSPENDED",					/* 強制待ち状態 */
+	"WSUSPENDED",					/* 二重待ち状態 */
+	"DORMANT"						/* 休止状態 */
+};
+
+/*
+ *  ロギングモード表示テーブル
+ */
+static char const log_mode_name[8][12] = {
+	"LOG_EMERG",					/* シャットダウンに値するエラー */
+	"LOG_ALERT",
+	"LOG_CRIT",
+	"LOG_ERROR",					/* システムエラー */
+	"LOG_WARNING",					/* 警告メッセージ */
+	"LOG_NOTICE",
+	"LOG_INFO",
+	"LOG_DEBUG"						/* デバッグ用メッセージ */
+};
+
+/*
+ * モニタで使用されるデータ領域
+ */
+static ID      current_tskid;			/* モニタが対象とするタスク */
+static char    mon_command[MAX_COMMAND_LENGTH+1];
+static char    mon_datatype;			/* モニタが指定するデータタイプのデフォルト値 */
+static ulong_t mon_address;				/* モニタが指定するアドレスのデフォルト値 */
+static int_t   mon_mode;				/* モニタが指定するコマンドモード */
+static uint_t  mon_logmask;				/* モニタが指定する記録／出力すべき重要度 */
+static uint_t  mon_lowmask;				/* モニタが指定する低レベル出力すべき重要度 */
+static ID      mon_default_portid;		/* モニタのデフォルトポートID */
+static FILE    *mon_infile;				/* モニタの入力ファイル */
+static COMMAND_LINK *pheadcmd;
+
+ID             mon_portid;				/* モニタのデバイスポートID */
+
+/*
+ *  モニタタスク
+ */
+void monitor(intptr_t exinf)
+{
+	int    no, argc, cno, len;
+	char   *argv[NUM_ARGC], c;
+
+	/* モニタで使用するデータの初期化 */
+
+	mon_portid   = mon_default_portid = (ID)exinf;
+	mon_datatype = DATA_BYTE;
+	mon_logmask  = LOG_NOTICE;
+	mon_lowmask  = LOG_EMERG;
+	current_tskid = MONTASK;
+	mon_infile   = stdin;
+
+	if(mon_portid != CONSOLE_PORTID)
+		SVC_PERROR(serial_opn_por(mon_portid));
+#ifdef NEED_MONITOR
+	if(!need_monitor())
+		ext_tsk();
+#endif	/* NEED_MONITOR */
+#ifndef NOINIT_STDIO_MONITOR
+	_setup_stdio(&mon_portid);
+#endif	/* NOTSET_STDIO_MONITOR */
+#ifdef MONITOR_DELAY
+	dly_tsk(MONITOR_DELAY);
+#endif	/* MONITOR_DELAY */
+	printf(banner,
+		(TMONITOR_PRVER >> 12) & 0x0f,
+		(TMONITOR_PRVER >> 4) & 0xff,
+		TMONITOR_PRVER & 0x0f);
+	SVC_PERROR(syslog_msk_log(LOG_UPTO(mon_logmask), LOG_UPTO(mon_lowmask)));
+	SVC_PERROR(serial_ctl_por(mon_portid, (IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV)));
+
+	/* モニタのメインのデスパッチ */
+
+	do{
+		prompt(current_tskid);
+		c = monitor_getstring(mon_command, &len);
+		/*
+		 *  引数の設定
+		 */
+		for(no = argc = cno = 0 ; argc < 16 && no < len ; no++){
+			if(test_next_char(mon_command[no])){
+				mon_command[no] = 0;
+				cno = 0;
+			}
+			else if(no < len){
+				if(cno == 0)
+					argv[argc++] = &mon_command[no];
+				cno++;
+			}
+		}
+		mon_command[no] = 0;
+
+		putecho('\n');
+		no = dispatch_command(argc, argv);
+		fflush(NULL);
+	}while(c != KEY_EXT);
+	printf("exit monitor !!\n");
+}
+
+/*
+ *  モニタのプロンプトの表示
+ *
+ *  指定のタスクIDがモニタ以外の場合は
+ *  タスクの状態によってプロンプトの表示内容を変更する．
+ */
+static void
+prompt(ID tskid)
+{
+	T_RTSK rtsk;
+
+	if(tskid == MONTASK)
+		printf("mon");
+	else{
+		ref_tsk(tskid, &rtsk);
+		printf("%03d(%s)", tskid, task_state[get_taskstate(rtsk.tskstat)]);
+	}
+	putchar('>');
+	fflush(NULL);
+}
+
+/*
+ *  コマンドのデスパッチ
+ */
+static int_t
+dispatch_command(int argc, char **argv)
+{
+	COMMAND_LINK *pcmd = (COMMAND_LINK *)standard_command;
+	const COMMAND_INFO *pscmd;
+	int no, sno, count;
+
+	if(argc > 0){
+		count = sizeof(standard_command) / sizeof(COMMAND_LINK);
+		for(no = 0 ; no < count ; no++, pcmd++){
+			if(compare_word(pcmd->command, argv[0], mon_mode)){
+				if(pcmd->num_command == 0){
+					if(pcmd->func != NULL){
+						pcmd->func(argc-1, &argv[1]);
+						return no;
+					}
+					else
+						return -1;
+				}
+				for(sno = 0, pscmd = pcmd->pcinfo ; sno < pcmd->num_command; sno++, pscmd++){
+					if(compare_word(pscmd->command, argv[1], mon_mode)){
+						pscmd->func(argc-1, &argv[1]);
+						return sno;
+					}
+				}
+			}
+		}
+		pcmd = pheadcmd;
+		while(pcmd){
+			if(compare_word(pcmd->command, argv[0], mon_mode)){
+				for(sno = 0, pscmd = pcmd->pcinfo ; sno < pcmd->num_command; sno++, pscmd++){
+					if(compare_word(pscmd->command, argv[1], mon_mode)){
+						pscmd->func(argc-1, &argv[1]);
+						return sno;
+					}
+				}
+			}
+			pcmd = pcmd->pcnext;
+		}
+	}
+	return -1;
+}
+
+/*
+ *  コマンドセットアップ
+ */
+int
+setup_command(COMMAND_LINK *pcmd)
+{
+	COMMAND_LINK *pbcmd = pheadcmd;
+
+	if(pcmd == NULL)
+		return -1;
+	pcmd->pcnext = NULL;
+	if(pbcmd == NULL){
+		pheadcmd = pcmd;
+		return 0;
+	}
+	while(pbcmd != NULL){
+		if(pbcmd == pcmd)
+			return -1;
+		else if(pbcmd->pcnext == NULL)
+			break;
+		pbcmd = pbcmd->pcnext;
+	}
+	pbcmd->pcnext = pcmd;
+	return 0;
+}
+
+/*
+ *  表示コマンド
+ */
+static int_t
+display_command(int argc, char **argv)
+{
+	char     cmd=0;
+	T_RTST   rtst;
+	char     b;
+	uint16_t h;
+	ulong_t  w, value1, value2;
+	int      no, count;
+
+	count = sizeof(mon_display) / sizeof(struct SUBCOMMAND_TABLE);
+	if(argc > 0){
+		for(no = 0 ; no < count ; no++){
+			if(compare_word(mon_display[no].subcommand, argv[0], 0)){
+				cmd = mon_display[no].type;
+				break;
+			}
+		}
+	}
+	switch(cmd){
+	default:						/* デフォルト */
+		cmd = mon_datatype;
+	case MONDISPLAY_BYTE:			/* バイト単位メモリ表示 */
+	case MONDISPLAY_HALF:			/* ハーフ単位メモリ表示 */
+	case MONDISPLAY_WORD:			/* ワード単位メモリ表示 */
+		value2 = 128;
+		if(argc < 2 || !get_value(argv[1], &value1, HEX_VALUE))
+			value1 = mon_address;
+		value1 = MonAlignAddress(value1);
+		if(argc > 2){
+			if(*argv[2] == '+'){
+				if(!get_value(argv[2]+1, &value2, HEX_VALUE))
+					value2 = 128;
+			}
+			else{
+				if(!get_value(argv[2], &value2, HEX_VALUE))
+					value2 = value1 + 128;
+				value2 -= value1;
+			}
+		}
+		mon_datatype = cmd;
+		while((W)value2 > 0){
+			printf("%08lx  ", (long)value1);
+			for(no = 0 ; no < 16 ; no += mon_datatype){
+				if(no == 8)
+					putchar(' ');
+				switch(mon_datatype){
+				case DATA_HALF:
+					if(MemoryRead(value1+no, (intptr_t)&h, 2) == 0)
+						h = -1;
+					printf("%04x  ", h);
+					break;
+				case DATA_WORD:
+					if(MemoryRead(value1+no, (intptr_t)&w, 4) == 0)
+						w = -1;
+					printf("%08lx    ", (long)w);
+					break;
+				default:
+					if(MemoryRead(value1+no, (intptr_t)&b, 1) == 0)
+						b = -1;
+					printf("%02x ", b);
+					break;
+				}
+			}
+			if(getMemoryType(value1+no, 0) == MEMORY_AREA){
+				for(no = 0 ; no < 16 ; no++){
+					if(MemoryRead(value1+no, (intptr_t)&b, 1)){
+						if(b < ' ' || b >= 0xE0)
+							b = '.';
+						else if(b >= 127 && b < 0xA0)
+							b = '.';
+					}
+					else
+						b = '.';
+					putchar(b);
+				}
+			}
+			putchar('\n');
+			value1 += 16;
+			value2 -= 16;
+			tslp_tsk(50);
+			if(monitor_break())
+				value2 = 0;
+		}
+		mon_address = value1;
+		break;
+	case MONDISPLAY_TASK:			/* タスク状態表示 */
+		printf("cur id  pri state      pc       stack    inistack inisize\n");
+		for(no = 0 ; no < tmax_tskid ; no++){
+			ref_tst(no+TMIN_TSKID, &rtst);
+			if(current_tskid == (no+TMIN_TSKID))
+				printf(" * ");
+			else
+				printf("   ");
+			if(MONTASK == (no+TMIN_TSKID))
+				printf(" mon");
+			else
+				printf(" %03d", no+TMIN_TSKID);
+			printf(" %3d ", rtst.tskpri);
+			value1 = get_taskstate(rtst.tskstat);
+			for(count = 0 ; count < TSTATE_LEN-1 ; count++){
+				if(task_state[value1][count] == 0)
+					putchar(' ');
+				else
+					putchar(task_state[value1][count]);
+			}
+			if(rtst.tskstat == TTS_RUN)
+				printf("         ");
+			else
+				printf(" %08lx", (unsigned long)rtst.tskpc);
+			printf(" %08lx %08lx %5ld\n", (unsigned long)rtst.tsksp, (unsigned long)rtst.inistk, (unsigned long)rtst.inistksz);
+		}
+		putchar('\n');
+		break;
+	case MONDISPLAY_REG:			/* レジスタの表示 */
+		if(current_tskid != MONTASK)
+			display_registers(current_tskid);
+		break;
+	}
+	return 0;
+}
+
+/*
+ *  設定コマンド
+ */
+static int_t
+set_command(int argc, char **argv)
+{
+	char     cmd=0;
+	char     b;
+	uint16_t h;
+	ulong_t  w, value1, value2;
+	int      no, count;
+	bool_t   cont;
+
+	count = sizeof(mon_set) / sizeof(struct SUBCOMMAND_TABLE);
+	if(argc > 0){
+		for(no = 0 ; no < count ; no++){
+			if(compare_word(mon_set[no].subcommand, argv[0], 0)){
+				cmd = mon_set[no].type;
+				break;
+			}
+		}
+	}
+	switch(cmd){
+	default:						/* デフォルト */
+		cmd = mon_datatype;
+	case MONSET_BYTE:				/* バイト単位メモリ設定 */
+	case MONSET_HALF:				/* ハーフ単位メモリ設定 */
+	case MONSET_WORD:				/* ワード単位メモリ設定 */
+		if(argc < 2 || !get_value(argv[1], &value1, HEX_VALUE))
+			value1 = mon_address;
+		value1 = MonAlignAddress(value1);
+		mon_datatype = cmd;
+		do{
+			printf("  %08lx", (unsigned long)value1);
+			switch(mon_datatype){
+			case DATA_HALF:
+				if(MemoryRead(value1, (intptr_t)&h, 2) == 0)
+					h = -1;
+				printf(" %04x =", h);
+				break;
+			case DATA_WORD:
+				if(MemoryRead(value1, (intptr_t)&w, 4) == 0)
+					w = -1;
+				printf(" %08lx =", (unsigned long)w);
+				break;
+			default:
+				if(MemoryRead(value1, (intptr_t)&b, 1) == 0)
+					b = -1;
+				printf(" %02x =", b);
+				break;
+			}
+			monitor_getstring(mon_command, &count);
+			if(get_value(mon_command, &value2, HEX_VALUE)){
+				switch(mon_datatype){
+				case DATA_HALF:
+					h = value2;
+					MemoryWrite(value1, (intptr_t)&h, 2);
+					if(MemoryRead(value1, (intptr_t)&h, 2) == 0)
+						h = -1;
+					printf(" %04x\n", h);
+					break;
+				case DATA_WORD:
+					w = value2;
+					MemoryWrite(value1, (intptr_t)&w, 4);
+					if(MemoryRead(value1, (intptr_t)&w, 4) == 0)
+						w = -1;
+					printf(" %08lx\n", (unsigned long)w);
+					break;
+				default:
+					b = value2;
+					MemoryWrite(value1, (intptr_t)&b, 1);
+					if(MemoryRead(value1, (intptr_t)&b, 1) == 0)
+						b = -1;
+					printf(" %02x\n", b);
+					break;
+				}
+				value1 += mon_datatype;
+				cont = true;
+			}
+			else
+				cont = false;
+		}while(cont);
+		putchar('\n');
+		mon_address = value1;
+		break;
+	case MONSET_COMMAND:			/* コマンドモード設定 */
+		if(argc > 1 && get_value(argv[1], &value1, DEC_VALUE)){
+			if(value1 == 1 || value1 == 2){
+				printf("  set %d command(s) mode !\n", (int)value1);
+				mon_mode = value1;
+			}
+		}
+		printf("  set command mode=%d word(s) !\n", mon_mode);
+		break;
+	case MONSET_SERIAL:				/* シリアル設定 */
+		if(argc > 1 && get_value(argv[1], &value1, DEC_VALUE)){
+			if(value1 > 0 && mon_portid != value1){
+				if(mon_portid != mon_default_portid && mon_portid != CONSOLE_PORTID)
+					SVC_PERROR(serial_cls_por(mon_portid));
+				mon_portid = value1;
+				if(mon_portid != mon_default_portid && mon_portid != CONSOLE_PORTID)
+					SVC_PERROR(serial_opn_por(mon_portid));
+				SVC_PERROR(serial_ctl_por(mon_portid, (IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV)));
+				printf(banner,
+					(TMONITOR_PRVER >> 12) & 0x0f,
+					(TMONITOR_PRVER >> 4) & 0xff,
+					TMONITOR_PRVER & 0x0f);
+			}
+		}
+		printf("  set serial port id=%d !\n", mon_portid);
+		break;
+	case MONSET_TASK:				/* タスク選択 */
+		if(argc > 1 && get_value(argv[1], &value1, DEC_VALUE)){
+			if(value1 >= TMIN_TSKID && value1 < (TMIN_TSKID+tmax_tskid))
+				current_tskid = value1;
+			else
+				current_tskid = MONTASK;
+		}
+		else
+			current_tskid = MONTASK;
+		break;
+	case MONSET_IN:					/* 入力設定 */
+		value1 = 0;
+		if(argc > 1)
+			get_value(argv[1], &value1, DEC_VALUE);
+		if(value1 == 1)
+			mon_infile = stdout;
+		else if(value1 == 2)
+			mon_infile = stderr;
+		else
+			mon_infile = stdin;
+		break;
+	}
+	return 0;
+}
+
+/*
+ *  ヘルプコマンド
+ */
+static int_t
+help_command(int argc, char **argv)
+{
+	COMMAND_LINK *pcmd = (COMMAND_LINK *)standard_command;
+	int no, count;
+
+	count = sizeof(standard_command) / sizeof(COMMAND_LINK);
+	for(no = 0 ; no < count ; no++, pcmd++){
+		if(argc > 0){
+			if(compare_word(pcmd->command, argv[0], 0)){
+				printf(pcmd->help);
+				return no;
+			}
+		}
+		else
+			printf(pcmd->help);
+	}
+	pcmd = pheadcmd;
+	while(pcmd){
+		if(argc > 0){
+			if(compare_word(pcmd->command, argv[0], 0)){
+				printf(pcmd->help);
+				return no;
+			}
+		}
+		else
+			printf(pcmd->help);
+		pcmd = pcmd->pcnext;
+	}
+	return 0;
+}
+
+/*
+ *  タスクコマンド、起動要求(act_tsk)
+ */
+static int_t
+task_activate(int argc, char **argv)
+{
+	ER      ercd = E_OK;
+
+	if(current_tskid == MONTASK){	/* モニタ自体の制御はできない */
+		printf(" Can't control the monitor!!\n");
+		return 0;
+	}
+	ercd = act_tsk(current_tskid);
+	printf("  execute act_tsk(%d) :: result = %s !\n", current_tskid, itron_strerror(ercd));
+	tslp_tsk(100);				/* スイッチング */
+	return 0;
+}
+
+/*
+ *  タスクコマンド、強制終了(ter_tsk)
+ */
+static int_t
+task_terminate(int argc, char **argv)
+{
+	ER      ercd = E_OK;
+
+	if(current_tskid == MONTASK){	/* モニタ自体の制御はできない */
+		printf(" Can't control the monitor!!\n");
+		return 0;
+	}
+	ercd = ter_tsk(current_tskid);
+	printf("  execute ter_tsk(%d) :: result = %s !\n", current_tskid, itron_strerror(ercd));
+	tslp_tsk(100);				/* スイッチング */
+	return 0;
+}
+
+/*
+ *  タスクコマンド、待ち要求(sus_tsk)
+ */
+static int_t
+task_suspend(int argc, char **argv)
+{
+	ER      ercd = E_OK;
+
+	if(current_tskid == MONTASK){	/* モニタ自体の制御はできない */
+		printf(" Can't control the monitor!!\n");
+		return 0;
+	}
+	ercd = sus_tsk(current_tskid);
+	printf("  execute sus_tsk(%d) :: result = %s !\n", current_tskid, itron_strerror(ercd));
+	tslp_tsk(100);				/* スイッチング */
+	return 0;
+}
+
+/*
+ *  タスクコマンド、待ち再開(rsm_tsk)
+ */
+static int_t
+task_resume(int argc, char **argv)
+{
+	ER      ercd = E_OK;
+
+	if(current_tskid == MONTASK){	/* モニタ自体の制御はできない */
+		printf(" Can't control the monitor!!\n");
+		return 0;
+	}
+	ercd = rsm_tsk(current_tskid);
+	printf("  execute rsm_tsk(%d) :: result = %s !\n", current_tskid, itron_strerror(ercd));
+	tslp_tsk(100);				/* スイッチング */
+	return 0;
+}
+
+/*
+ *  タスクコマンド、待ち解除(rel_wai)
+ */
+static int_t
+task_release(int argc, char **argv)
+{
+	ER      ercd = E_OK;
+
+	if(current_tskid == MONTASK){	/* モニタ自体の制御はできない */
+		printf(" Can't control the monitor!!\n");
+		return 0;
+	}
+	ercd = rel_wai(current_tskid);
+	printf("  execute rel_wai(%d) :: result = %s !\n", current_tskid, itron_strerror(ercd));
+	tslp_tsk(100);				/* スイッチング */
+	return 0;
+}
+
+/*
+ *  タスクコマンド、タスク起床(wup_tsk)
+ */
+static int_t
+task_wakeup(int argc, char **argv)
+{
+	ER      ercd = E_OK;
+
+	if(current_tskid == MONTASK){	/* モニタ自体の制御はできない */
+		printf(" Can't control the monitor!!\n");
+		return 0;
+	}
+	ercd = wup_tsk(current_tskid);
+	printf("  execute wup_tsk(%d) :: result = %s !\n", current_tskid, itron_strerror(ercd));
+	tslp_tsk(100);				/* スイッチング */
+	return 0;
+}
+
+/*
+ *  タスクコマンド、優先度変更(chg_pri)
+ */
+static int_t
+task_priority(int argc, char **argv)
+{
+	ER      ercd = E_OK;
+	ulong_t w;
+
+	if(current_tskid == MONTASK){	/* モニタ自体の制御はできない */
+		printf(" Can't control the monitor!!\n");
+		return 0;
+	}
+	if(argc > 1 && get_value(argv[1], &w, DEC_VALUE)){
+		ercd = chg_pri(current_tskid, w);
+		printf("  execute chg_pri(%d, %d) :: result = %s !\n", current_tskid, (int)w, itron_strerror(ercd));
+		tslp_tsk(100);				/* スイッチング */
+		return 0;
+	}
+	return -1;
+}
+
+/*
+ * ログコマンド、ロギングモード設定
+ */
+static int_t
+log_mode(int argc, char **argv)
+{
+	ulong_t	value1, value2;
+
+	if(argc < 2 || !get_value(argv[1], &value1, DEC_VALUE))
+		value1 = mon_logmask;
+	if(argc < 3 || !get_value(argv[2], &value2, DEC_VALUE))
+		value2 = mon_lowmask;
+	if(value1 <= LOG_DEBUG)
+		mon_logmask = value1;
+	if(value2 <= LOG_DEBUG)
+		mon_lowmask = value2;
+	syslog_msk_log(LOG_UPTO(mon_logmask), LOG_UPTO(mon_lowmask));
+	printf("  set logmask=%s lowmask=%s !\n", log_mode_name[mon_logmask], log_mode_name[mon_lowmask]);
+	return 0;
+}
+
+/*
+ * ログコマンド、タスクモニタ設定
+ */
+static int_t
+log_task(int argc, char **argv)
+{
+	T_TPRM  loglist;
+	ulong_t value1, value2, value3 = 0;
+	ulong_t tcount, ttime;
+	ulong_t sno = MONTASK;
+	ulong_t xno = MONTASK+NUM_LOG_DISP;
+	int     no, count;
+
+	if(argc < 2 || !get_value(argv[1], &value1, DEC_VALUE))
+		value1 = 0;
+	else if(argc < 3 || !get_value(argv[2], &value3, DEC_VALUE))
+		value3 = 0;
+	if(value1 < 100)
+		value1 = 0;
+	value2 = 0;
+	do{
+		count = get_tsklog(&loglist);
+		if(value2 == 0){		/* はじめの１回 */
+			value2 =loglist.currtime;
+			if(xno > count){
+				int i = xno - count;
+				if(i > MONTASK)
+					i = MONTASK;
+				sno -= xno - count;
+				xno -= xno - count;
+			}
+			printf("-- time --");
+			for(no = 1 ; no <= xno ; no++){
+				if(no > sno)
+					printf(" --id=%04u --", no);
+			}
+			printf(" -- others --  -vacancy-\n");
+		}
+		value2 += value1;
+		if(value1 == 0)
+			printf("%010lu\n", (unsigned long)loglist.pervtime);
+		printf("%010lu", (unsigned long)loglist.currtime);
+		tcount = ttime = 0;
+		for(no = 1 ; no <= count ; no++){
+			if(no > sno && no <= xno){
+				printf(" %04u %05lu.%01u", loglist.tlog[no].runcount, (unsigned long)(loglist.tlog[no].runtimes/10),
+						(int)(loglist.tlog[no].runtimes%10));
+			}
+			else{
+				tcount += loglist.tlog[no].runcount;
+				ttime += loglist.tlog[no].runtimes;
+			}
+		}
+		printf(" %04u %05lu.%01u", (int)tcount, (unsigned long)(ttime/10), (int)(ttime%10));
+		printf("  %07lu.%01u\n", (unsigned long)(loglist.tlog[0].runtimes/10), (int)(loglist.tlog[0].runtimes%10));
+		if(value1){
+			tslp_tsk(value2 - loglist.currtime);
+			if(monitor_break())
+				value1 = 0;
+		}
+		value3--;
+	}while(value1 && value3 != 0);
+	return 0;
+}
+
+/*
+ * ログコマンド、ポートモニタ設定
+ */
+static int_t
+log_port(int argc, char **argv)
+{
+	T_PCHK  *p;
+	ulong_t type, address;
+	ulong_t value1, value2;
+
+	value2 = NUM_PCHK-1;
+	if(argc > 1 && get_value(argv[1], &value1, DEC_VALUE)){
+		if((p = get_device_log(value1)) != 0){
+			value2 = value1;
+			if(argc < 3 || !get_value(argv[2], &type, DEC_VALUE)){
+				type = p->logtype;
+			}
+			if(type >= LOG_DEBUG)
+				type = 0;
+			p->logtype = type;
+			if(argc < 4 || !get_value(argv[4], &address, HEX_VALUE)){
+				address = p->portaddress;
+			}
+			p->portaddress = address;
+		}
+	}
+	else
+		value1 = 0;
+	while(value1 <= value2){
+		if((p = get_device_log(value1)) != 0){
+			if(p->logtype > 0)
+				printf("  %02d   %s port=%08lx\n", (int)value1, log_mode_name[p->logtype], (unsigned long)p->portaddress);
+			else
+				printf("  %02d   OFF      port=%08lx\n", (int)value1, (unsigned long)p->portaddress);
+		}
+		else
+			break;
+		value1++;
+	}
+	return 0;
+}
+
+
+/*
+ *  キャラクタの比較
+ */
+bool_t
+compare_word(const char *s, char *d, int_t mode)
+{
+	char c1, c2;
+
+	if(*d == 0)
+		return false;
+	while(*s != 0 && *d != 0 && *d != ' ' && *d != ','){
+		c2 = *d++;
+		if(c2 >= 'a' && c2 <= 'z')
+			c2 -= 0x20;
+		c1 = *s++;
+		if(c1 >= 'a' && c1 <= 'z')
+			c1 -= 0x20;
+		if(c1 != c2)
+			return false;
+		if(mode == 1)
+			break;
+	}
+	return true;
+}
+
+/*
+ *  タスク状態番号を取り出す
+ */
+static uint_t
+get_taskstate(STAT tskstat)
+{
+	uint_t no;
+
+	if(tskstat == TTS_RUN)
+		no = 0;
+	else if(tskstat == TTS_RDY)
+		no = 1;
+	else if(tskstat == TTS_WAI)
+		no = 2;
+	else if(tskstat == TTS_SUS)
+		no = 3;
+	else if(tskstat == TTS_DMT)
+		no = 5;
+	else
+		no = 4;
+	return no;
+}
+
+/*
+ *  モニタのコマンド読み込み文
+ */
+char
+monitor_getstring(char *s, int *len)
+{
+	char c;
+	int  no = 0;
+
+	*len = 0;
+	do{
+		c = getc(mon_infile);
+		if(c >= ' ' && no < MAX_COMMAND_LENGTH){
+			putecho((int)c);
+			s[no++] = c;
+		}
+		else if((c == KEY_BS || c == KEY_DEL) && no > 0){
+			printecho(backspace);
+			no--;
+		}
+	}while(c != KEY_NL && c != KEY_CR && c != KEY_EXT);
+	s[no] = 0;
+	*len = no;
+	return c;
+}
+
+/*
+ *  モニタコマンドブレークの判定
+ */
+bool_t
+monitor_break(void)
+{
+	T_SERIAL_RPOR k_rpor;
+
+	if(mon_infile != stdin)
+		return false;
+	serial_ref_por(mon_portid, &k_rpor);
+	if(k_rpor.reacnt > 0){
+		getc(mon_infile);
+		return true;
+	}
+	else
+		return false;
+}
+
+/*
+ *  モニタ入力ファイルの切り替え
+ */
+void *
+monitor_infile(void *file)
+{
+	void *ofile = mon_infile;
+
+	if(file != NULL)
+		mon_infile = file;
+	return ofile;
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/monitor.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/monitor.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/monitor.cfg	(revision 453)
@@ -0,0 +1,11 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *  モニタタスクのコンフィギュレーション
+ */
+
+#include "monitor.h"
+CRE_TSK(MONTASK, { TA_ACT, MONITOR_PORTID, monitor,
+			MONITOR_PRIORITY, MONITOR_STACK_SIZE, NULL });
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/monitor.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/monitor.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/monitor.h	(revision 453)
@@ -0,0 +1,215 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2003-2015 by Ryosuke Takeuchi
+ *                     GJ Business Division RICOH COMPANY,LTD. JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，Free Software Foundation によって公表されている 
+ *  GNU General Public License の Version 2 に記述されている条件か，以
+ *  下の(1)～(4)の条件を満たす場合に限り，本ソフトウェア（本ソフトウェ
+ *  アを改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを再利用可能なバイナリコード（リロケータブルオブ
+ *      ジェクトファイルやライブラリなど）の形で利用する場合には，利用
+ *      に伴うドキュメント（利用者マニュアルなど）に，上記の著作権表示，
+ *      この利用条件および下記の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを再利用不可能なバイナリコードの形または機器に組
+ *      み込んだ形で利用する場合には，次のいずれかの条件を満たすこと．
+ *    (a) 利用に伴うドキュメント（利用者マニュアルなど）に，上記の著作
+ *        権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 利用の形態を，別に定める方法によって，上記著作権者に報告する
+ *        こと．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者を免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者は，
+ *  本ソフトウェアに関して，その適用可能性も含めて，いかなる保証も行わ
+ *  ない．また，本ソフトウェアの利用により直接的または間接的に生じたい
+ *  かなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+#ifndef _MONITOR_H_
+#define	_MONITOR_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 
+ *  モニタ・サンプルプログラムのヘッダファイル
+ */
+#include <kernel.h>
+#include "syssvc/logtask.h"
+
+/*
+ *  タスク優先度の設定
+ */
+#define MONITOR_PRIORITY	4
+
+/*
+ *  ターゲットに依存する可能性のある定数の定義
+ */
+
+#ifndef CONSOLE_PORTID
+#if defined(LOGTASK_PORTID) && defined(SIO_PORTID)
+#define	CONSOLE_PORTID		LOGTASK_PORTID	/* 文字入力するシリアルポートID */
+#else  /* LOGTASK_PORTID */
+#define	CONSOLE_PORTID		1				/* 文字入力するシリアルポートID */
+#endif /* LOGTASK_PORTID */
+#endif /* TASK_PORTID */
+
+/*
+ *  モニタのサイズの設定
+ */
+#if defined(TOPPERS_CORTEX_M0PLUS) || defined(TOPPERS_HIFIVE1)
+#define	MONITOR_STACK_SIZE	1536	/* タスクのスタックサイズ */
+#else
+#define	MONITOR_STACK_SIZE	2046	/* タスクのスタックサイズ */
+#endif
+#define	MAX_COMMAND_LENGTH	200		/* モニタの最大コマンド長 */
+#define	NUM_LOG_DISP		3		/* 最大表示アイテム数 */
+#ifndef MONITOR_PORTID
+#define MONITOR_PORTID      CONSOLE_PORTID
+#endif
+
+/*
+ *  バージョン情報
+ */
+#define	TMONITOR_PRVER	0x1020		/* カーネルのバージョン番号 */
+
+/*
+ *  キー割り当ての定義
+ */
+#define	KEY_BS			(8)			/* バックスペース */
+#define	KEY_DEL			(127)		/* 削除 */
+#define KEY_NL			(10)		/* 改行1 */
+#define	KEY_CR			(13)		/* 改行2 */
+#define	KEY_EXT			(1)			/* 終了 */
+
+/*
+ *  データタイプ定義
+ */
+#define	DATA_BYTE		1			/* バイトデータ（１バイト）*/
+#define	DATA_HALF		2			/* ハーフデータ（２バイト）*/
+#define	DATA_WORD		4			/* ワードデータ（４バイト）*/
+
+/*
+ *  領域属性の定義
+ */
+#define	NONE_AREA		0			/* 領域の割り当てのない領域 */
+#define	PORT_AREA		1			/* ハードウェアのポート領域 */
+#define	MEMORY_AREA		2			/* メモリ領域　*/
+
+#define	MREAD_ONLY		1			/* 読み込み専用 */
+#define	MWRITE_ONLY		2			/* 書き込み専用 */
+#define	MREAD_WRITE		(MREAD_ONLY+MWRITE_ONLY)
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  コマンドデスパッチ用の構造体定義
+ */
+typedef struct _COMMAND_INFO {
+	const char   *command;			/* コマンド文 */
+	int_t        (*func)(int argc, char **argv);	/* 実行関数 */
+} COMMAND_INFO;
+
+typedef struct _COMMAND_LINK COMMAND_LINK;
+struct _COMMAND_LINK {
+	COMMAND_LINK *pcnext;
+	int          num_command;
+	const char   *command;			/* 主コマンド文 */
+	int_t        (*func)(int argc, char **argv);	/* 実行関数 */
+	const char   *help;				/* ヘルプ文 */
+    const COMMAND_INFO *pcinfo;
+};
+
+/*
+ *  エコーの設定
+ */
+#define putecho(a)      putchar(a)
+#define printecho(a)    printf(a)
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+
+extern bool_t  need_monitor(void);
+extern void	   monitor(intptr_t exinf);
+extern int     setup_command(COMMAND_LINK *pcmd);
+extern bool_t  monitor_break(void);
+extern bool_t  compare_word(const char *s, char *d, int_t mode);
+extern char    getMemoryType(ulong_t address, int_t mode);
+extern int_t   MemoryRead(ulong_t address, intptr_t p, int_t type);
+extern int_t   MemoryWrite(ulong_t address, intptr_t p, int_t type);
+extern ulong_t MonAlignAddress(ulong_t address);
+extern int_t   MemoryRead(ulong_t address, intptr_t p, int_t type);
+extern int_t   MemoryWrite(ulong_t address, intptr_t p, int_t type);
+extern ulong_t get_exception_pc(void * p_excinf);
+extern void    display_registers(ID tskid);
+extern ulong_t display_assembler(ulong_t pc);
+
+/*
+ *  次のキャラクタの判定
+ */
+Inline bool_t
+test_next_char(char c)
+{
+	if(c == ' ' || c == '\t')
+		return true;
+	else
+		return false;
+}
+
+/*
+ *  文字列から数字を取り出す
+ *  戻り値がFALSEなら値が未設定であることを示す
+ */
+Inline bool_t
+get_value(char *s, ulong_t *v, int_t card)
+{
+	char c;
+	int  no = 0;
+
+	*v = 0;
+	if(s[no] == 0)
+		return false;
+	else if(s[no] == ' ' || s[no] == '\t'
+               || s[no] == ',' || s[no] == '.'){
+		no++;
+		return false;
+	}
+	else{
+		while(s[no]){
+			c = s[no];
+			no++;
+			if(c >= '0' && c <= '9')
+				c -= '0';
+			else if(c >= 'A' && c <= 'Z')
+				c -= 'A' - 10;
+			else if(c >= 'a' && c <= 'z')
+				c -= 'a' - 10;
+			else
+				break;
+			*v = *v * card + c;
+		}
+		return true;
+	}
+}
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MONITOR_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/monsil.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/monsil.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/monsil.h	(revision 453)
@@ -0,0 +1,329 @@
+/*
+ *  TOPPERS/JSP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Just Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2003-2004 by Ryosuke Takeuchi
+ *               Platform Development Center RICOH COMPANY,LTD. JAPAN
+ * 
+ *  上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+ *  によって公表されている GNU General Public License の Version 2 に記
+ *  述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+ *  を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+ *  含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+ *  接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *	システムインタフェースレイヤ（ターゲット共通部）
+ *
+ *  アセンブリ言語のソースファイルやシステムコンフィギュレーションファ
+ *  イルからこのファイルをインクルードする時は，_MACRO_ONLY を定義して
+ *  おくことで，マクロ定義以外の記述を除くことができる．
+ *
+ *  このインクルードファイルは，標準インクルードファイル（s_services.h）
+ *  でインクルードされる．また，カーネルから呼ばれるデバイスドライバの
+ *  インクルードファイルで，インライン関数などでシステムインタフェース
+ *  レイヤを用いている場合にも，このファイルがインクルードされる．この
+ *  例外を除いて，他のファイルから直接インクルードされることはない．
+ *
+ *  この中でインクルードしているファイルを除いて，他のインクルードファ
+ *  イルに依存していない．
+ */
+
+#ifndef _MONSIL_H_
+#define _MONSIL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ *  カーネル・アプリケーション 共通インクルードファイル
+ */
+#include <t_stddef.h>
+
+/*
+ *  ITRON仕様共通規定のデータ型・定数・マクロ
+ */
+#include <itron.h>
+
+/*
+ *  システムやプロセッサに依存する定義
+ */
+#include <sys_defs.h>
+#include <cpu_defs.h>
+
+/*
+ *  システムログサービスのための定義
+ */
+#include <t_syslog.h>
+
+/*
+ *  ポートログ設定の定義
+ */
+#include <task_expansion.h>
+
+/*
+ *  エンディアン定数の定義
+ */
+#define	SIL_ENDIAN_LITTLE	0	/* リトルエンディアン */
+#define	SIL_ENDIAN_BIG		1	/* ビッグエンディアン */
+
+#ifndef _MACRO_ONLY
+
+/*
+ *  割込みロック状態の制御
+ */
+#ifndef SIL_PRE_LOC
+#define	SIL_PRE_LOC	BOOL _sil_loc_ = sns_loc()
+#define	SIL_LOC_INT()	((void)(!(_sil_loc_) \
+				&& (sns_ctx() ? iloc_cpu() : loc_cpu())))
+#define	SIL_UNL_INT()	((void)(!(_sil_loc_) \
+				&& (sns_ctx() ? iunl_cpu() : unl_cpu())))
+#endif /* SIL_PRE_LOC */
+
+/*
+ *  微少時間待ち
+ */
+extern void	sil_dly_nse(UINT dlytim) throw();
+
+/*
+ *  エンディアンの反転
+ */
+#ifndef SIL_REV_ENDIAN_H
+#define	SIL_REV_ENDIAN_H(data) \
+	((VH)((((UH)(data) & 0xff) << 8) | (((UH)(data) >> 8) & 0xff)))
+#endif /* SIL_REV_ENDIAN_H */
+
+#ifndef SIL_REV_ENDIAN_W
+#define	SIL_REV_ENDIAN_W(data) \
+	((VW)((((UW)(data) & 0xff) << 24) | (((UW)(data) & 0xff00) << 8) \
+		| (((UW)(data)>> 8) & 0xff00) | (((UW)(data) >> 24) & 0xff)))
+#endif /* SIL_REV_ENDIAN_H */
+
+/*
+ *  メモリ空間アクセス関数
+ */
+#ifndef OMIT_SIL_ACCESS
+
+/*
+ *  8ビット単位の読出し／書込み
+ */
+#ifdef _int8_
+
+Inline VB
+sil_reb_mem(VP mem)
+{
+	VB data;
+
+    MemoryRead((unsigned long)mem, (void *)&data, sizeof(VB));
+	ana_rdv((UW)mem, (UW)data, 1);
+	return(data);
+}
+
+Inline void
+sil_wrb_mem(VP mem, VB data)
+{
+	ana_wdv((UW)mem, (UW)data, 1);
+    MemoryWrite((unsigned long)mem, (void *)&data, sizeof(VB));
+}
+
+#endif /* _int8_ */
+
+/*
+ *  16ビット単位の読出し／書込み
+ */
+#ifdef _int16_
+
+Inline VH
+sil_reh_mem(VP mem)
+{
+	VH data;
+
+    MemoryRead((unsigned long)mem,  (void *)&data, sizeof(VH));
+	ana_rdv((UW)mem, (UW)data, 2);
+	return(data);
+}
+
+Inline void
+sil_wrh_mem(VP mem, VH data)
+{
+	ana_wdv((UW)mem, (UW)data, 2);
+    MemoryWrite((unsigned long)mem, (void *)&data, sizeof(VH));
+}
+
+#if SIL_ENDIAN == SIL_ENDIAN_BIG	/* ビッグエンディアンプロセッサ */
+
+#define	sil_reh_bem(mem)	sil_reh_mem(mem)
+#define	sil_wrh_bem(mem, data)	sil_wrh_mem(mem, data)
+
+#ifndef OMIT_SIL_REH_LEM
+
+Inline VH
+sil_reh_lem(VP mem)
+{
+	VH	data;
+
+	data = *((volatile VH *) mem);
+	data = (SIL_REV_ENDIAN_H(data));
+	ana_rdv((UW)mem, (UW)data, 2);
+	return(data);
+}
+
+#endif /* OMIT_SIL_REH_LEM */
+#ifndef OMIT_SIL_WRH_LEM
+
+Inline void
+sil_wrh_lem(VP mem, VH data)
+{
+	ana_wdv((UW)mem, (UW)data, 2);
+	*((volatile VH *) mem) = SIL_REV_ENDIAN_H(data);
+}
+
+#endif /* OMIT_SIL_WRH_LEM */
+#else /* SIL_ENDIAN == SIL_ENDIAN_BIG *//* リトルエンディアンプロセッサ */
+
+#define	sil_reh_lem(mem)	sil_reh_mem(mem)
+#define	sil_wrh_lem(mem, data)	sil_wrh_mem(mem, data)
+
+#ifndef OMIT_SIL_REH_BEM
+
+Inline VH
+sil_reh_bem(VP mem)
+{
+	VH	data;
+
+	data = *((volatile VH *) mem);
+	data = (SIL_REV_ENDIAN_H(data));
+	ana_rdv((UW)mem, (UW)data, 2);
+	return(data);
+}
+
+#endif /* OMIT_SIL_REH_BEM */
+#ifndef OMIT_SIL_WRH_BEM
+
+Inline void
+sil_wrh_bem(VP mem, VH data)
+{
+	ana_wdv((UW)mem, (UW)data, 2);
+	*((volatile VH *) mem) = SIL_REV_ENDIAN_H(data);
+}
+
+#endif /* OMIT_SIL_WRH_BEM */
+#endif /* SIL_ENDIAN == SIL_ENDIAN_BIG */
+#endif /* _int16_ */
+
+/*
+ *  32ビット単位の読出し／書込み
+ */
+
+Inline VW
+sil_rew_mem(VP mem)
+{
+	VW data;
+
+    MemoryRead((unsigned long)mem, (void *)&data,  sizeof(VW));
+	ana_rdv((UW)mem, (UW)data, 4);
+	return(data);
+}
+
+Inline void
+sil_wrw_mem(VP mem, VW data)
+{
+	ana_wdv((UW)mem, (UW)data, 4);
+    MemoryWrite((unsigned long)mem, (void *)&data, sizeof(VW));
+}
+
+#if SIL_ENDIAN == SIL_ENDIAN_BIG	/* ビッグエンディアンプロセッサ */
+
+#define	sil_rew_bem(mem)	sil_rew_mem(mem)
+#define	sil_wrw_bem(mem, data)	sil_wrw_mem(mem, data)
+
+#ifndef OMIT_SIL_REW_LEM
+
+Inline VW
+sil_rew_lem(VP mem)
+{
+	VW	data;
+
+	data = *((volatile VW *) mem);
+	data = (SIL_REV_ENDIAN_W(data));
+	ana_rdv((UW)mem, (UW)data, 4);
+	return(data);
+}
+
+#endif /* OMIT_SIL_REW_LEM */
+#ifndef OMIT_SIL_WRW_LEM
+
+Inline void
+sil_wrw_lem(VP mem, VW data)
+{
+	ana_wdv((UW)mem, (UW)data, 4);
+	*((volatile VW *) mem) = SIL_REV_ENDIAN_W(data);
+}
+
+#endif /* OMIT_SIL_WRW_LEM */
+#else /* SIL_ENDIAN == SIL_ENDIAN_BIG *//* リトルエンディアンプロセッサ */
+
+#define	sil_rew_lem(mem)	sil_rew_mem(mem)
+#define	sil_wrw_lem(mem, data)	sil_wrw_mem(mem, data)
+
+#ifndef OMIT_SIL_REW_BEM
+
+Inline VW
+sil_rew_bem(VP mem)
+{
+	VW	data;
+
+	data = *((volatile VW *) mem);
+	data = (SIL_REV_ENDIAN_W(data));
+	ana_rdv((UW)mem, (UW)data, 4);
+	return(data);
+}
+
+#endif /* OMIT_SIL_REW_BEM */
+#ifndef OMIT_SIL_WRW_BEM
+
+Inline void
+sil_wrw_bem(VP mem, VW data)
+{
+	ana_wdv((UW)mem, (UW)data, 4);
+	*((volatile VW *) mem) = SIL_REV_ENDIAN_W(data);
+}
+
+#endif /* OMIT_SIL_WRW_BEM */
+#endif /* SIL_ENDIAN == SIL_ENDIAN_BIG */
+#endif /* OMIT_SIL_ACCESS */
+
+#endif /* _MACRO_ONLY */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MONSIL_H_ */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/sample1.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/sample1.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/sample1.c	(revision 453)
@@ -0,0 +1,541 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2012 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *  サンプルプログラム(1)の本体
+ *
+ *  ASPカーネルの基本的な動作を確認するためのサンプルプログラム．
+ *
+ *  プログラムの概要:
+ *
+ *  ユーザインタフェースを受け持つメインタスク（タスクID: MAIN_TASK，優
+ *  先度: MAIN_PRIORITY）と，3つの並行実行されるタスク（タスクID:
+ *  TASK1～TASK3，初期優先度: MID_PRIORITY）で構成される．また，起動周
+ *  期が2秒の周期ハンドラ（周期ハンドラID: CYCHDR1）を用いる．
+ *
+ *  並行実行されるタスクは，task_loop回空ループを実行する度に，タスクが
+ *  実行中であることをあらわすメッセージを表示する．空ループを実行する
+ *  のは，空ループなしでメッセージを出力すると，多量のメッセージが出力
+ *  され，プログラムの動作が確認しずらくなるためである．また，低速なシ
+ *  リアルポートを用いてメッセージを出力する場合に，すべてのメッセージ
+ *  が出力できるように，メッセージの量を制限するという理由もある．
+ *
+ *  周期ハンドラは，三つの優先度（HIGH_PRIORITY，MID_PRIORITY，
+ *  LOW_PRIORITY）のレディキューを回転させる．プログラムの起動直後は，
+ *  周期ハンドラは停止状態になっている．
+ *
+ *  メインタスクは，シリアルI/Oポートからの文字入力を行い（文字入力を
+ *  待っている間は，並行実行されるタスクが実行されている），入力された
+ *  文字に対応した処理を実行する．入力された文字と処理の関係は次の通り．
+ *  Control-Cまたは'Q'が入力されると，プログラムを終了する．
+ *
+ *  '1' : 対象タスクをTASK1に切り換える（初期設定）．
+ *  '2' : 対象タスクをTASK2に切り換える．
+ *  '3' : 対象タスクをTASK3に切り換える．
+ *  'a' : 対象タスクをact_tskにより起動する．
+ *  'A' : 対象タスクに対する起動要求をcan_actによりキャンセルする．
+ *  'e' : 対象タスクにext_tskを呼び出させ，終了させる．
+ *  't' : 対象タスクをter_tskにより強制終了する．
+ *  '>' : 対象タスクの優先度をHIGH_PRIORITYにする．
+ *  '=' : 対象タスクの優先度をMID_PRIORITYにする．
+ *  '<' : 対象タスクの優先度をLOW_PRIORITYにする．
+ *  'G' : 対象タスクの優先度をget_priで読み出す．
+ *  's' : 対象タスクにslp_tskを呼び出させ，起床待ちにさせる．
+ *  'S' : 対象タスクにtslp_tsk(10秒)を呼び出させ，起床待ちにさせる．
+ *  'w' : 対象タスクをwup_tskにより起床する．
+ *  'W' : 対象タスクに対する起床要求をcan_wupによりキャンセルする．
+ *  'l' : 対象タスクをrel_waiにより強制的に待ち解除にする．
+ *  'u' : 対象タスクをsus_tskにより強制待ち状態にする．
+ *  'm' : 対象タスクの強制待ち状態をrsm_tskにより解除する．
+ *  'd' : 対象タスクにdly_tsk(10秒)を呼び出させ，時間経過待ちにさせる．
+ *  'x' : 対象タスクに例外パターン0x0001の例外処理を要求する．
+ *  'X' : 対象タスクに例外パターン0x0002の例外処理を要求する．
+ *  'y' : 対象タスクにdis_texを呼び出させ，タスク例外を禁止する．
+ *  'Y' : 対象タスクにena_texを呼び出させ，タスク例外を許可する．
+ *  'r' : 3つの優先度（HIGH_PRIORITY，MID_PRIORITY，LOW_PRIORITY）のレ
+ *        ディキューを回転させる．
+ *  'c' : 周期ハンドラを動作開始させる．
+ *  'C' : 周期ハンドラを動作停止させる．
+ *  'b' : アラームハンドラを5秒後に起動するよう動作開始させる．
+ *  'B' : アラームハンドラを動作停止させる．
+ *  'z' : 対象タスクにCPU例外を発生させる（タスクを終了させる）．
+ *  'Z' : 対象タスクにCPUロック状態でCPU例外を発生させる（プログラムを
+ *        終了する）．
+ *  'V' : get_utmで性能評価用システム時刻を2回読む．
+ *  'v' : 発行したシステムコールを表示する（デフォルト）．
+ *  'q' : 発行したシステムコールを表示しない．
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#include "kernel_cfg.h"
+#include "sample1.h"
+
+/*
+ *  サービスコールのエラーのログ出力
+ */
+Inline void
+svc_perror(const char *file, int_t line, const char *expr, ER ercd)
+{
+	if (ercd < 0) {
+		t_perror(LOG_ERROR, file, line, expr, ercd);
+	}
+}
+
+#define	SVC_PERROR(expr)	svc_perror(__FILE__, __LINE__, #expr, (expr))
+
+/*
+ *  並行実行されるタスクへのメッセージ領域
+ */
+char	message[3];
+
+/*
+ *  ループ回数
+ */
+ulong_t	task_loop;		/* タスク内でのループ回数 */
+ulong_t	tex_loop;		/* 例外処理ルーチン内でのループ回数 */
+
+/*
+ *  並行実行されるタスク
+ */
+void task(intptr_t exinf)
+{
+	volatile ulong_t	i;
+	int_t		n = 0;
+	int_t		tskno = (int_t) exinf;
+	const char	*graph[] = { "|", "  +", "    *" };
+	char		c;
+
+	SVC_PERROR(ena_tex());
+	while (true) {
+		syslog(LOG_NOTICE, "task%d is running (%03d).   %s",
+										tskno, ++n, graph[tskno-1]);
+		for (i = 0; i < task_loop; i++);
+		c = message[tskno-1];
+		message[tskno-1] = 0;
+		switch (c) {
+		case 'e':
+			syslog(LOG_INFO, "#%d#ext_tsk()", tskno);
+			SVC_PERROR(ext_tsk());
+			assert(0);
+		case 's':
+			syslog(LOG_INFO, "#%d#slp_tsk()", tskno);
+			SVC_PERROR(slp_tsk());
+			break;
+		case 'S':
+			syslog(LOG_INFO, "#%d#tslp_tsk(10000)", tskno);
+			SVC_PERROR(tslp_tsk(10000));
+			break;
+		case 'd':
+			syslog(LOG_INFO, "#%d#dly_tsk(10000)", tskno);
+			SVC_PERROR(dly_tsk(10000));
+			break;
+		case 'y':
+			syslog(LOG_INFO, "#%d#dis_tex()", tskno);
+			SVC_PERROR(dis_tex());
+			break;
+		case 'Y':
+			syslog(LOG_INFO, "#%d#ena_tex()", tskno);
+			SVC_PERROR(ena_tex());
+			break;
+#ifdef CPUEXC1
+		case 'z':
+			syslog(LOG_NOTICE, "#%d#raise CPU exception", tskno);
+			RAISE_CPU_EXCEPTION;
+			break;
+		case 'Z':
+			SVC_PERROR(loc_cpu());
+			syslog(LOG_NOTICE, "#%d#raise CPU exception", tskno);
+			RAISE_CPU_EXCEPTION;
+			SVC_PERROR(unl_cpu());
+			break;
+#endif /* CPUEXC1 */
+		default:
+			break;
+		}
+	}
+}
+
+/*
+ *  並行して実行されるタスク用のタスク例外処理ルーチン
+ */
+void tex_routine(TEXPTN texptn, intptr_t exinf)
+{
+	volatile ulong_t	i;
+	int_t	tskno = (int_t) exinf;
+
+	syslog(LOG_NOTICE, "task%d receives exception 0x%04x.", tskno, texptn);
+	for (i = 0; i < tex_loop; i++);
+
+	if ((texptn & 0x8000U) != 0U) {
+		syslog(LOG_INFO, "#%d#ext_tsk()", tskno);
+		SVC_PERROR(ext_tsk());
+		assert(0);
+	}
+}
+
+/*
+ *  CPU例外ハンドラ
+ */
+#ifdef CPUEXC1
+
+void
+cpuexc_handler(void *p_excinf)
+{
+	ID		tskid;
+
+	syslog(LOG_NOTICE, "CPU exception handler (p_excinf = %08p).", p_excinf);
+	if (sns_ctx() != true) {
+		syslog(LOG_WARNING,
+					"sns_ctx() is not true in CPU exception handler.");
+	}
+	if (sns_dpn() != true) {
+		syslog(LOG_WARNING,
+					"sns_dpn() is not true in CPU exception handler.");
+	}
+	syslog(LOG_INFO, "sns_loc = %d sns_dsp = %d sns_tex = %d",
+									sns_loc(), sns_dsp(), sns_tex());
+	syslog(LOG_INFO, "xsns_dpn = %d xsns_xpn = %d",
+									xsns_dpn(p_excinf), xsns_xpn(p_excinf));
+
+	if (xsns_xpn(p_excinf)) {
+		syslog(LOG_NOTICE, "Sample program ends with exception.");
+		SVC_PERROR(ext_ker());
+		assert(0);
+	}
+
+	SVC_PERROR(iget_tid(&tskid));
+	SVC_PERROR(iras_tex(tskid, 0x8000U));
+}
+
+#endif /* CPUEXC1 */
+
+/*
+ *  周期ハンドラ
+ *
+ *  HIGH_PRIORITY，MID_PRIORITY，LOW_PRIORITY の各優先度のレディキュー
+ *  を回転させる．
+ */
+void cyclic_handler(intptr_t exinf)
+{
+	SVC_PERROR(irot_rdq(HIGH_PRIORITY));
+	SVC_PERROR(irot_rdq(MID_PRIORITY));
+	SVC_PERROR(irot_rdq(LOW_PRIORITY));
+}
+
+/*
+ *  アラームハンドラ
+ *
+ *  HIGH_PRIORITY，MID_PRIORITY，LOW_PRIORITY の各優先度のレディキュー
+ *  を回転させる．
+ */
+void alarm_handler(intptr_t exinf)
+{
+	SVC_PERROR(irot_rdq(HIGH_PRIORITY));
+	SVC_PERROR(irot_rdq(MID_PRIORITY));
+	SVC_PERROR(irot_rdq(LOW_PRIORITY));
+}
+
+/*
+ *  メインタスク
+ */
+void main_task(intptr_t exinf)
+{
+	char	c;
+	ID		tskid = TASK1;
+	int_t	tskno = 1;
+	ER_UINT	ercd;
+	PRI		tskpri;
+#ifndef TASK_LOOP
+	volatile ulong_t	i;
+	SYSTIM	stime1, stime2;
+#endif /* TASK_LOOP */
+#ifdef TOPPERS_SUPPORT_GET_UTM
+	SYSUTM	utime1, utime2;
+#endif /* TOPPERS_SUPPORT_GET_UTM */
+
+	SVC_PERROR(syslog_msk_log(LOG_UPTO(LOG_INFO), LOG_UPTO(LOG_EMERG)));
+	syslog(LOG_NOTICE, "Sample program starts (exinf = %d).", (int_t) exinf);
+
+	/*
+	 *  シリアルポートの初期化
+	 *
+	 *  システムログタスクと同じシリアルポートを使う場合など，シリアル
+	 *  ポートがオープン済みの場合にはここでE_OBJエラーになるが，支障は
+	 *  ない．
+	 */
+	ercd = serial_opn_por(TASK_PORTID);
+	if (ercd < 0 && MERCD(ercd) != E_OBJ) {
+		syslog(LOG_ERROR, "%s (%d) reported by `serial_opn_por'.",
+									itron_strerror(ercd), SERCD(ercd));
+	}
+	SVC_PERROR(serial_ctl_por(TASK_PORTID,
+							(IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV)));
+
+	/*
+ 	 *  ループ回数の設定
+	 *
+	 *  並行実行されるタスク内での空ループの回数（task_loop）は，空ルー
+	 *  プの実行時間が約0.4秒になるように設定する．この設定のために，
+	 *  LOOP_REF回の空ループの実行時間を，その前後でget_timを呼ぶことで
+	 *  測定し，その測定結果から空ループの実行時間が0.4秒になるループ回
+	 *  数を求め，task_loopに設定する．
+	 *
+	 *  LOOP_REFは，デフォルトでは1,000,000に設定しているが，想定したよ
+	 *  り遅いプロセッサでは，サンプルプログラムの実行開始に時間がかか
+	 *  りすぎるという問題を生じる．逆に想定したより速いプロセッサでは，
+	 *  LOOP_REF回の空ループの実行時間が短くなり，task_loopに設定する値
+	 *  の誤差が大きくなるという問題がある．
+	 *
+	 *  そこで，そのようなターゲットでは，target_test.hで，LOOP_REFを適
+	 *  切な値に定義するのが望ましい．
+	 *
+	 *  また，task_loopの値を固定したい場合には，その値をTASK_LOOPにマ
+	 *  クロ定義する．TASK_LOOPがマクロ定義されている場合，上記の測定を
+	 *  行わずに，TASK_LOOPに定義された値を空ループの回数とする．
+	 *
+	 * ターゲットによっては，空ループの実行時間の1回目の測定で，本来よ
+	 * りも長めになるものがある．このようなターゲットでは，MEASURE_TWICE
+	 * をマクロ定義することで，1回目の測定結果を捨てて，2回目の測定結果
+	 * を使う．
+	 *
+	 *  タスク例外処理ルーチン内での空ループの回数（tex_loop）は，
+	 *  task_loopの4分の1の値（空ループの実行時間が0.1秒になるループ回
+	 *  数）に設定する．
+	 */
+#ifdef TASK_LOOP
+	task_loop = TASK_LOOP;
+#else /* TASK_LOOP */
+
+#ifdef MEASURE_TWICE
+	task_loop = LOOP_REF;
+	SVC_PERROR(get_tim(&stime1));
+	for (i = 0; i < task_loop; i++);
+	SVC_PERROR(get_tim(&stime2));
+#endif /* MEASURE_TWICE */
+
+	task_loop = LOOP_REF;
+	SVC_PERROR(get_tim(&stime1));
+	for (i = 0; i < task_loop; i++);
+	SVC_PERROR(get_tim(&stime2));
+	task_loop = LOOP_REF * 400UL / (stime2 - stime1);
+
+#endif /* TASK_LOOP */
+	tex_loop = task_loop / 4;
+
+	/*
+ 	 *  タスクの起動
+	 */
+	SVC_PERROR(act_tsk(TASK1));
+	SVC_PERROR(act_tsk(TASK2));
+	SVC_PERROR(act_tsk(TASK3));
+
+	/*
+ 	 *  メインループ
+	 */
+	do {
+#ifndef USE_CUPCOMMAND
+		SVC_PERROR(serial_rea_dat(TASK_PORTID, &c, 1));
+#else
+		do{
+			c = get_cup_command();
+			dly_tsk(10);
+		}while(c == 0);
+#endif
+		switch (c) {
+		case 'e':
+		case 's':
+		case 'S':
+		case 'd':
+		case 'y':
+		case 'Y':
+		case 'z':
+		case 'Z':
+			message[tskno-1] = c;
+			break;
+		case '1':
+			tskno = 1;
+			tskid = TASK1;
+			break;
+		case '2':
+			tskno = 2;
+			tskid = TASK2;
+			break;
+		case '3':
+			tskno = 3;
+			tskid = TASK3;
+			break;
+		case 'a':
+			syslog(LOG_INFO, "#act_tsk(%d)", tskno);
+			SVC_PERROR(act_tsk(tskid));
+			break;
+		case 'A':
+			syslog(LOG_INFO, "#can_act(%d)", tskno);
+			SVC_PERROR(ercd = can_act(tskid));
+			if (ercd >= 0) {
+				syslog(LOG_NOTICE, "can_act(%d) returns %d", tskno, ercd);
+			}
+			break;
+		case 't':
+			syslog(LOG_INFO, "#ter_tsk(%d)", tskno);
+			SVC_PERROR(ter_tsk(tskid));
+			break;
+		case '>':
+			syslog(LOG_INFO, "#chg_pri(%d, HIGH_PRIORITY)", tskno);
+			SVC_PERROR(chg_pri(tskid, HIGH_PRIORITY));
+			break;
+		case '=':
+			syslog(LOG_INFO, "#chg_pri(%d, MID_PRIORITY)", tskno);
+			SVC_PERROR(chg_pri(tskid, MID_PRIORITY));
+			break;
+		case '<':
+			syslog(LOG_INFO, "#chg_pri(%d, LOW_PRIORITY)", tskno);
+			SVC_PERROR(chg_pri(tskid, LOW_PRIORITY));
+			break;
+		case 'G':
+			syslog(LOG_INFO, "#get_pri(%d, &tskpri)", tskno);
+			SVC_PERROR(ercd = get_pri(tskid, &tskpri));
+			if (ercd >= 0) {
+				syslog(LOG_NOTICE, "priority of task %d is %d", tskno, tskpri);
+			}
+			break;
+		case 'w':
+			syslog(LOG_INFO, "#wup_tsk(%d)", tskno);
+			SVC_PERROR(wup_tsk(tskid));
+			break;
+		case 'W':
+			syslog(LOG_INFO, "#can_wup(%d)", tskno);
+			SVC_PERROR(ercd = can_wup(tskid));
+			if (ercd >= 0) {
+				syslog(LOG_NOTICE, "can_wup(%d) returns %d", tskno, ercd);
+			}
+			break;
+		case 'l':
+			syslog(LOG_INFO, "#rel_wai(%d)", tskno);
+			SVC_PERROR(rel_wai(tskid));
+			break;
+		case 'u':
+			syslog(LOG_INFO, "#sus_tsk(%d)", tskno);
+			SVC_PERROR(sus_tsk(tskid));
+			break;
+		case 'm':
+			syslog(LOG_INFO, "#rsm_tsk(%d)", tskno);
+			SVC_PERROR(rsm_tsk(tskid));
+			break;
+		case 'x':
+			syslog(LOG_INFO, "#ras_tex(%d, 0x0001U)", tskno);
+			SVC_PERROR(ras_tex(tskid, 0x0001U));
+			break;
+		case 'X':
+			syslog(LOG_INFO, "#ras_tex(%d, 0x0002U)", tskno);
+			SVC_PERROR(ras_tex(tskid, 0x0002U));
+			break;
+		case 'r':
+			syslog(LOG_INFO, "#rot_rdq(three priorities)");
+			SVC_PERROR(rot_rdq(HIGH_PRIORITY));
+			SVC_PERROR(rot_rdq(MID_PRIORITY));
+			SVC_PERROR(rot_rdq(LOW_PRIORITY));
+			break;
+		case 'c':
+			syslog(LOG_INFO, "#sta_cyc(1)");
+			SVC_PERROR(sta_cyc(CYCHDR1));
+			break;
+		case 'C':
+			syslog(LOG_INFO, "#stp_cyc(1)");
+			SVC_PERROR(stp_cyc(CYCHDR1));
+			break;
+		case 'b':
+			syslog(LOG_INFO, "#sta_alm(1, 5000)");
+			SVC_PERROR(sta_alm(ALMHDR1, 5000));
+			break;
+		case 'B':
+			syslog(LOG_INFO, "#stp_alm(1)");
+			SVC_PERROR(stp_alm(ALMHDR1));
+			break;
+
+		case 'V':
+#ifdef TOPPERS_SUPPORT_GET_UTM
+			SVC_PERROR(get_utm(&utime1));
+			SVC_PERROR(get_utm(&utime2));
+			syslog(LOG_NOTICE, "utime1 = %ld, utime2 = %ld",
+										(ulong_t) utime1, (ulong_t) utime2);
+#else /* TOPPERS_SUPPORT_GET_UTM */
+			syslog(LOG_NOTICE, "get_utm is not supported.");
+#endif /* TOPPERS_SUPPORT_GET_UTM */
+			break;
+
+		case 'v':
+			SVC_PERROR(syslog_msk_log(LOG_UPTO(LOG_INFO),
+										LOG_UPTO(LOG_EMERG)));
+			break;
+		case 'q':
+			SVC_PERROR(syslog_msk_log(LOG_UPTO(LOG_NOTICE),
+										LOG_UPTO(LOG_EMERG)));
+			break;
+
+#ifdef BIT_KERNEL
+		case ' ':
+			SVC_PERROR(loc_cpu());
+			{
+				extern ER	bit_kernel(void);
+
+				SVC_PERROR(ercd = bit_kernel());
+				if (ercd >= 0) {
+					syslog(LOG_NOTICE, "bit_kernel passed.");
+				}
+			}
+			SVC_PERROR(unl_cpu());
+			break;
+#endif /* BIT_KERNEL */
+
+		default:
+			break;
+		}
+	} while (c != '\003' && c != 'Q');
+
+	syslog(LOG_NOTICE, "Sample program ends.");
+	SVC_PERROR(ext_ker());
+	assert(0);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/sample1.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/sample1.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/sample1.cfg	(revision 453)
@@ -0,0 +1,27 @@
+/*
+ *  $Id$
+ */
+
+/*
+ *  サンプルプログラム(1)のシステムコンフィギュレーションファイル
+ */
+INCLUDE("target_timer.cfg");
+INCLUDE("syssvc/syslog.cfg");
+INCLUDE("syssvc/banner.cfg");
+INCLUDE("syssvc/serial.cfg");
+INCLUDE("syssvc/logtask.cfg");
+INCLUDE("monitor/monitor.cfg");
+
+#include "sample1.h"
+CRE_TSK(TASK1, { TA_NULL, 1, task, MID_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK2, { TA_NULL, 2, task, MID_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK3, { TA_NULL, 3, task, MID_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(MAIN_TASK, { TA_NULL, 0, main_task, MAIN_PRIORITY, STACK_SIZE, NULL });
+DEF_TEX(TASK1, { TA_NULL, tex_routine });
+DEF_TEX(TASK2, { TA_NULL, tex_routine });
+DEF_TEX(TASK3, { TA_NULL, tex_routine });
+CRE_CYC(CYCHDR1, { TA_NULL, 0, cyclic_handler, 2000, 0 });
+CRE_ALM(ALMHDR1, { TA_NULL, 0, alarm_handler });
+#ifdef CPUEXC1
+DEF_EXC(CPUEXC1, { TA_NULL, cpuexc_handler });
+#endif /* CPUEXC1 */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/sample1.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/sample1.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/sample1.h	(revision 453)
@@ -0,0 +1,94 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ *
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ *
+ *  $Id$
+ */
+
+/*
+ *		サンプルプログラム(1)のヘッダファイル
+ */
+
+/*
+ *  ターゲット依存の定義
+ */
+#include "target_test.h"
+
+/*
+ *  各タスクの優先度の定義
+ */
+
+#define MAIN_PRIORITY	5		/* メインタスクの優先度 */
+								/* HIGH_PRIORITYより高くすること */
+
+#define HIGH_PRIORITY	9		/* 並行実行されるタスクの優先度 */
+#define MID_PRIORITY	10
+#define LOW_PRIORITY	11
+
+/*
+ *  ターゲットに依存する可能性のある定数の定義
+ */
+
+#ifndef TASK_PORTID
+#define	TASK_PORTID		1			/* 文字入力するシリアルポートID */
+#endif /* TASK_PORTID */
+
+#ifndef STACK_SIZE
+#define	STACK_SIZE		4096		/* タスクのスタックサイズ */
+#endif /* STACK_SIZE */
+
+#ifndef LOOP_REF
+#define LOOP_REF		ULONG_C(1000000)	/* 速度計測用のループ回数 */
+#endif /* LOOP_REF */
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+#ifndef TOPPERS_MACRO_ONLY
+
+extern void	task(intptr_t exinf);
+extern void	main_task(intptr_t exinf);
+extern void	tex_routine(TEXPTN texptn, intptr_t exinf);
+#ifdef CPUEXC1
+extern void	cpuexc_handler(void *p_excinf);
+#endif /* CPUEXC1 */
+extern void	cyclic_handler(intptr_t exinf);
+extern void	alarm_handler(intptr_t exinf);
+extern int8_t get_cup_command(void);
+
+#endif /* TOPPERS_MACRO_ONLY */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/stdio.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/stdio.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/stdio.h	(revision 453)
@@ -0,0 +1,186 @@
+/*
+ *  TOPPERS/ASP/FMP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile/Flexible MultiProcessor Kernel
+ * 
+ *  Copyright (C) 2003-2005 by 
+ *                     GJ Business Division RICOH COMPANY,LTD. JAPAN
+ *  Copyright (C) 2015-2017 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，Free Software Foundation によって公表されている 
+ *  GNU General Public License の Version 2 に記述されている条件か，以
+ *  下の(1)～(4)の条件を満たす場合に限り，本ソフトウェア（本ソフトウェ
+ *  アを改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを再利用可能なバイナリコード（リロケータブルオブ
+ *      ジェクトファイルやライブラリなど）の形で利用する場合には，利用
+ *      に伴うドキュメント（利用者マニュアルなど）に，上記の著作権表示，
+ *      この利用条件および下記の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを再利用不可能なバイナリコードの形または機器に組
+ *      み込んだ形で利用する場合には，次のいずれかの条件を満たすこと．
+ *    (a) 利用に伴うドキュメント（利用者マニュアルなど）に，上記の著作
+ *        権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 利用の形態を，別に定める方法によって，上記著作権者に報告する
+ *        こと．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者を免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者は，
+ *  本ソフトウェアに関して，その適用可能性も含めて，いかなる保証も行わ
+ *  ない．また，本ソフトウェアの利用により直接的または間接的に生じたい
+ *  かなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *	@(#)stdio.h	5.3 (Berkeley) 3/15/86
+ */
+
+/*
+ * NB: to fit things in six character monocase externals, the
+ * stdio code uses the prefix `__ms' for embedded stdio objects, typically
+ * followed by a three-character attempt at a mnemonic.
+ */
+#ifndef _STDIO_H_
+#define	_STDIO_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//#define __need___va_list
+#include <stdarg.h>
+
+#define	_SMALL_STDIO_
+
+#include <target_stddef.h>
+
+typedef struct __msFILE {
+  int	_flags;				/* flags, below; this FILE is free if 0 */
+  int	_file;				/* fileno, if Unix descriptor, else -1 */
+  int  (* _func_in)(void*);	/* pointer to a character input function */
+							/* pointer to a character input string function */
+  int  (* _func_ins)(void*, unsigned int, char *);
+  void (* _func_out)(void*, int);	/* pointer to a character output function */
+							/* pointer to a character output string function */
+  int  (* _func_outs)(void*, unsigned int, char *);
+							/* pointer to a character output flush function */
+  int  (* _func_flush)(struct __msFILE *);
+  void * _dev;				/* pointer to local device structure */
+} FILE;
+
+#define	__SLBF	0x0001		/* line buffered */
+#define	__SNBF	0x0002		/* unbuffered */
+#define	__SRD	0x0004		/* OK to read */
+#define	__SWR	0x0008		/* OK to write */
+	/* RD and WR are never simultaneously asserted */
+#define	__SRW	0x0010		/* open for reading & writing */
+#define	__SEOF	0x0020		/* found EOF */
+#define	__SERR	0x0040		/* found error */
+#define	__SMBF	0x0080		/* _buf is from malloc */
+#define	__SAPP	0x0100		/* fdopen()ed in append mode - so must  write to end */
+#define	__SSTR	0x0200		/* this is an sprintf/snprintf string */
+#define	__SOPT	0x0400		/* do fseek() optimisation */
+#define	__SNPT	0x0800		/* do not do fseek() optimisation */
+#define	__SOFF	0x1000		/* set iff _offset is in fact correct */
+#define	__SMOD	0x2000		/* true => fgetline modified _p text */
+
+/*
+ * The following three definitions are for ANSI C, which took them
+ * from System V, which stupidly took internal interface macros and
+ * made them official arguments to setvbuf(), without renaming them.
+ * Hence, these ugly _IOxxx names are *supposed* to appear in user code.
+ *
+ * Although these happen to match their counterparts above, the
+ * implementation does not rely on that (so these could be renumbered).
+ */
+#define	_IOFBF	0		/* setvbuf should set fully buffered */
+#define	_IOLBF	1		/* setvbuf should set line buffered */
+#define	_IONBF	2		/* setvbuf should set unbuffered */
+
+#ifndef NULL
+#define	NULL	0
+#endif
+
+#define	BUFSIZ	1024
+#define	EOF	(-1)
+
+extern FILE _iob[];
+#define  stdin   (&_iob[0])	/* FILE input */
+#define  stdout  (&_iob[1])	/* FILE output */
+#define  stderr  (&_iob[2])	/* FILE error input output */
+
+/*
+ * Functions defined in ANSI C standard.
+ */
+
+#ifdef __GNUC__
+#define __VALIST __gnuc_va_list
+#else
+#define __VALIST char*
+#endif
+
+int fgetc(FILE *);
+int fgets(char *, int, FILE *);
+int fputc(int, FILE *);
+int fputs(const char *, FILE *);
+int putchar(int);
+int puts(const char *);
+int printf(const char *, ...);
+int vprintf(const char *, va_list args);
+int sprintf(char *, const char *, ...);
+int vsprintf(char *, const char *, va_list args);
+int snprintf(char *, size_t, const char *, ...);
+int scanf(const char *, ...);
+int sscanf(char *, const char *, ...);
+int fflush(FILE *);
+FILE *fopen(const char *, const char *);
+int fclose(FILE *);
+size_t fread(void *, size_t, size_t, FILE *);
+size_t fwrite(const void *, size_t, size_t, FILE *);
+int fseek(FILE *, long, int);
+long ftell(FILE *);
+int fprintf(FILE *, const char *, ...);
+int vfprintf(FILE *, const char *, va_list args);
+
+#define	feof(p)     (((p)->_flags & __SEOF) != 0)
+#define	ferror(p)   (((p)->_flags & __SERR) != 0)
+#define	clearerr(p) ((void)((p)->_flags &= ~(__SERR|__SEOF)))
+#define putc(c,fp)  fputc(c,fp)
+#define getchar()   fgetc(stdin)
+#define getc(fp)    fgetc(fp)
+
+/*
+ * NOT SUPPORT stdio functions
+ */
+#define gets(s)                         puts("NOT SUPPORT gets !\n")
+#define ungetc(c, st)                   puts("NOT SUPPORT ungetc !\n")
+#if !defined(__cplusplus) && defined(__GNUC__)
+#define fscanf(st, format, ...)         puts("NOT SUPPORT fscanf !\n")
+#endif
+
+extern void _setup_stdio(signed int *pport);
+extern FILE *_get_stdio(int no);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _STDIO_H_ */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/stdio/fprintf.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/stdio/fprintf.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/stdio/fprintf.c	(revision 453)
@@ -0,0 +1,66 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2016 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ * 
+ *	fprintf代用プログラム
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+extern int _setformat(int (*)(int, FILE *), FILE *st, const char *, va_list);
+
+int
+fprintf(FILE *st, const char *format, ...)
+{
+    va_list args;
+    va_start(args, format);
+
+    return _setformat(fputc, st, format, args);
+}
+
+int
+vfprintf(FILE *st, const char *format, va_list args)
+{
+    return _setformat(fputc, st, format, args);
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/stdio/printf.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/stdio/printf.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/stdio/printf.c	(revision 453)
@@ -0,0 +1,280 @@
+/*
+ *  TOPPERS/JSP/ASP/FMP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Just Standard Profile Kernel
+ * 
+ *  Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+ *  によって公表されている GNU General Public License の Version 2 に記
+ *  述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+ *  を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *	printf代用プログラム
+ */
+
+#include <itron.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+/*
+ *  long型から変換される文字列の最大サイズを計算
+ */
+#define CONVERT_BUFLEN	((sizeof(unsigned long) * CHAR_BIT + 4) / 3)
+
+/*
+ *  数値を文字列に変換
+ */
+static int
+convert(unsigned long val, int radix, const char *radchar, int width, int minus, int padzero,
+        void (*putsub)(char c, char **p), char ** putbuf)
+{
+	char	buf[CONVERT_BUFLEN];
+	int	i, j;
+	int count = 0;
+
+	i = 0;
+	do {
+		buf[i++] = radchar[val % radix];
+		val /= radix;
+	} while (i < CONVERT_BUFLEN && val != 0);
+
+	width -= minus;
+	if (minus > 0 && padzero > 0) {
+		putsub('-', putbuf);
+		count++;
+	}
+	for (j = i; j < width; j++) {
+		putsub((char)(padzero > 0 ? '0' : ' '), putbuf);
+		count++;
+	}
+	if (minus > 0 && padzero <= 0) {
+		putsub('-', putbuf);
+		count++;
+	}
+	while (i > 0) {
+		putsub(buf[--i], putbuf);
+		count++;
+	}
+	return count;
+}
+
+/*
+ *  ログ情報フォーマット用ライブラリ関数
+ */
+static char const raddec[] = "0123456789";
+static char const radhex[] = "0123456789abcdef";
+static char const radHEX[] = "0123456789ABCDEF";
+
+int _setformat (void (*putsub)(char c, char **p), char ** putbuf, const char * format, va_list ap)
+{
+	int	c;
+	int count = 0;
+	int	width;
+	int	padzero;
+	int precision;
+	long	val;
+	char const	*str;
+
+	while ((c = *format++) != '\0') {
+		if (c != '%') {
+			putsub((char) c, putbuf);
+			count++;
+			continue;
+		}
+
+		width = padzero = precision = 0;
+		if ((c = *format++) == '0') {
+			padzero = 1;
+			c = *format++;
+		}
+		else if (c == '.') {
+			precision = 1;
+			c = *format++;
+		}
+		while ('0' <= c && c <= '9') {
+			width = width*10 + c - '0';
+			c = *format++;
+		}
+		switch (c) {
+		case 'l':						/* long */
+			c = *format++;
+			switch (c) {
+			case 'd':					/* long 10進整数 */
+			case 'i':					/* long 8,10,16進整数 */
+				val = (long) va_arg(ap, long);
+				if (val >= 0)
+					count += convert(val, 10, raddec, width, 0, padzero, putsub, putbuf);
+				else
+					count += convert(-val, 10, raddec, width, 1, padzero, putsub, putbuf);
+				break;
+			case 'u':					/* unsigned long 10進整数 */
+				val = (long) va_arg(ap, unsigned long);
+				count += convert(val, 10, raddec, width, 0, padzero, putsub, putbuf);
+				break;
+			case 'o':					/* unsigned long 8進整数 */
+				val = (long) va_arg(ap, unsigned long);
+				count += convert(val, 8, raddec, width, 0, padzero, putsub, putbuf);
+				break;
+			case 'x':					/* unsigned long 16進整数 */
+				val = (long) va_arg(ap, unsigned long);
+				count += convert(val, 16, radhex, width, 0, padzero, putsub, putbuf);
+				break;
+			case 'X':					/* unsigned long 大文字16進整数 */
+				val = (long) va_arg(ap, unsigned long);
+				count += convert(val, 16, radHEX, width, 0, padzero, putsub, putbuf);
+				break;
+			case '\0':
+				format--;
+				break;
+			}
+			break;
+
+		case 'h':						/* short */
+			c = *format++;
+			switch (c) {
+			case 'd':					/* short 8進整数 */
+			case 'i':					/* short 8,10,16進整数 */
+				val = (long) ((short)va_arg(ap, int));
+				if (val >= 0)
+					count += convert(val, 10, raddec, width, 0, padzero, putsub, putbuf);
+				else
+					count += convert(-val, 10, raddec, width, 1, padzero, putsub, putbuf);
+				break;
+			case 'u':					/* unsigned short 10進整数 */
+				val = (long) ((unsigned short)va_arg(ap, unsigned int));
+				count += convert(val, 10, raddec, width, 0, padzero, putsub, putbuf);
+				break;
+			case 'o':					/* unsigned short 8進整数 */
+				val = (long) ((unsigned short)va_arg(ap, unsigned int));
+				count += convert(val, 8, raddec, width, 0, padzero, putsub, putbuf);
+				break;
+			case 'x':					/* unsigned short 16進整数 */
+				val = (long) ((unsigned short)va_arg(ap, unsigned int));
+				count += convert(val, 16, radhex, width, 0, padzero, putsub, putbuf);
+				break;
+			case 'X':					/* unsigned short 大文字16進整数 */
+				val = (long) ((unsigned short)va_arg(ap, unsigned int));
+				count += convert(val, 16, radHEX, width, 0, padzero, putsub, putbuf);
+				break;
+			case '\0':
+				format--;
+				break;
+			}
+			break;
+		case 'd':						/* int 10進整数 */
+		case 'i':						/* int 8,10,16進整数 */
+			val = (long) va_arg(ap, int);
+			if (val >= 0)
+				count += convert(val, 10, raddec, width, 0, padzero, putsub, putbuf);
+			else
+				count += convert(-val, 10, raddec, width, 1, padzero, putsub, putbuf);
+			break;
+		case 'u':						/* unsigned int 10進整数 */
+			val = (long) va_arg(ap, unsigned int);
+			count += convert(val, 10, raddec, width, 0, padzero, putsub, putbuf);
+			break;
+		case 'o':						/* unsigned int 8進整数 */
+			val = (long) va_arg(ap, unsigned int);
+			count += convert(val, 8, raddec, width, 0, padzero, putsub, putbuf);
+			break;
+		case 'p':
+		case 'x':						/* unsigned int 16進整数 */
+			val = (long) va_arg(ap, unsigned int);
+			count += convert(val, 16, radhex, width, 0, padzero, putsub, putbuf);
+			break;
+		case 'X':						/* unsigned int 大文字16進整数 */
+			val = (long) va_arg(ap, unsigned int);
+			count += convert(val, 16, radHEX, width, 0, padzero, putsub, putbuf);
+			break;
+
+		case 'c':						/* 1バイト文字 */
+			c = (int) va_arg(ap, unsigned int);
+			putsub((char)(int)c, putbuf);
+			count++;
+			break;
+		case 's':						/* 文字列 */
+			str = (char const *) va_arg(ap, VP_INT);
+			if (width > 0) {
+				while (((c = *str++) != '\0') && (width > 0)) {
+					putsub((char) c, putbuf);
+					count++;
+					width--;
+				}
+				while (width > 0) {
+					putsub(' ', putbuf);
+					count++;
+					width--;
+				}
+			}
+			else {
+				while ((c = *str++) != '\0') {
+					putsub((char) c, putbuf);
+					count++;
+				}
+			}
+			break;
+		case '%':
+			putsub('%', putbuf);
+			count++;
+			break;
+		case '\0':
+			format--;
+			break;
+		}
+	}
+	return count;
+}
+
+static void putzi (char c, char ** p)
+{
+    putchar(c);
+}
+
+int printf (const char * format, ...)
+{
+	va_list args;
+	va_start(args, format);
+	int ret = (_setformat(putzi, NULL, format, args));
+	va_end(args);
+	return ret;
+}
+
+
+int vprintf (const char * format, va_list args)
+{
+	return (_setformat(putzi, NULL, format, args));
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/stdio/scanf.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/stdio/scanf.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/stdio/scanf.c	(revision 453)
@@ -0,0 +1,297 @@
+/*
+ *  TOPPERS/JSP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Just Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2003-2006 by Ryosuke Takeuchi
+  *                     GJ Business Division RICOH COMPANY,LTD. JAPAN
+ * 
+ *  上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+ *  によって公表されている GNU General Public License の Version 2 に記
+ *  述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+ *  を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+ *  含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+ *  接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *	scanf代用プログラム
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+
+typedef	void		*VP;		/* 型が定まらないものへのポインタ */
+typedef	VP		VP_INT;		/* VP または INT */
+
+#define	BOOL	int
+#define TRUE	1
+#define FALSE	0
+#define FHALF   0
+#define FINT    1
+#define FLONG   2
+
+static BOOL is_terminator(char c)
+{
+	if(c == '\0')
+		return TRUE;
+	else if(c == '\r' || c == '\n' || c == 0xc)
+		return TRUE;
+	else
+		return FALSE;
+}
+
+/*
+ *  文字列を数値に変換
+ */
+static int
+convert(VP_INT p, int radix, int padzero, int width, int minus, int (*getsub)(char **p), char ** getbuf, int type)
+{
+	char	c;
+	int		i;
+	unsigned long val = 0;
+	int count = 0;
+	int csign = 0;
+
+	if(width <= 0)
+		width = 64;
+	c = getsub(getbuf);				/* get first character */
+	if(is_terminator((char)c))
+		return count;
+	if(c < '0' || (c > '9' && c < 'A')
+			   || (c > 'Z' && c < 'a') || c > 'z'){
+		c = getsub(getbuf);
+		if(is_terminator((char)c))
+			return count;
+	}
+
+	while(c == ' ' || c == '\t'){	/* skip white space */
+		c = getsub(getbuf);
+		if(is_terminator((char)c))
+			return count;
+	}
+
+	if(padzero && c == '0'){		/* skip pad zero */
+		do{
+			c = getsub(getbuf);
+			if(is_terminator((char)c))
+				return count;
+		}while(c == '0');
+	}
+	for( ; !is_terminator((char)c) ; c = getsub(getbuf), width--){
+		if(c == '\t' || c == ' ' || c == ',')
+			break;
+		i = 0;
+		if(c == '-' && minus){
+			csign = 1;
+			width++;
+		}
+		else if(c >= '0' && c <= '9')
+			i = c - '0';
+		else if(c >= 'A' && c <= 'Z')
+			i = c - 'A' + 10;
+		else if(c >= 'a' && c <= 'z')
+			i = c - 'a' + 10;
+		else
+			continue;
+
+		if(i >= radix)
+			i = radix - 1;
+		val = val * radix + i;
+		count = 1;
+		if(width <= 1)
+			break;
+	}
+	if(csign)
+		val = (unsigned long)((long)val * -1);
+
+	switch(type){
+	case FHALF:
+		*((unsigned short *)p) = (unsigned short)val;
+		break;
+	case FLONG:
+		*((unsigned long *)p) = (unsigned long)val;
+		break;
+	default:
+		*((unsigned int *)p) = (unsigned int)val;
+		break;
+	}
+	return count;
+}
+
+
+/*
+ *  データ取り込みライブラリ関数
+ */
+
+int _getformat (int (*getsub)(char **p), char ** getbuf, const char * format, va_list ap)
+{
+	int c;
+	int count = 0;
+	int	width;
+	int	padzero;
+	VP_INT	val;
+	char *str;
+
+	while ((c = *format++) != '\0') {
+		if (c != '%') {
+			continue;
+		}
+
+		width = padzero = 0;
+		c = *format++;
+		if (c >= '1' && c <= '9') {
+			padzero = 1;
+		}
+		while (c >= '0' && c <= '9') {
+			width = width*10 + c - '0';
+			c = *format++;
+		}
+		switch (c) {
+		case 'l':						/* long */
+			c = *format++;
+			switch (c) {
+			case 'd':					/* long 10進整数 */
+			case 'i':					/* long 8,10,16進整数 */
+				val = (VP_INT) va_arg(ap, VP_INT);
+				count += convert(val, 10, padzero, width, 1, getsub, getbuf, FLONG);
+				break;
+			case 'u':					/* unsigned long 10進整数 */
+				val = (VP_INT) va_arg(ap, VP_INT);
+				count += convert(val, 10, padzero, width, 0, getsub, getbuf, FLONG);
+				break;
+			case 'o':					/* unsigned long 8進整数 */
+				val = (VP_INT) va_arg(ap, VP_INT);
+				count += convert(val, 8, padzero, width, 0, getsub, getbuf, FLONG);
+				break;
+			case 'x':					/* unsigned long 16進整数 */
+				val = (VP_INT) va_arg(ap, VP_INT);
+				count += convert(val, 16, padzero, width, 0, getsub, getbuf, FLONG);
+				break;
+			case 'X':					/* unsigned long 大文字16進整数 */
+				val = (VP_INT) va_arg(ap, VP_INT);
+				count += convert(val, 16, padzero, width, 0, getsub, getbuf, FLONG);
+				break;
+			case '\0':
+				format--;
+				break;
+			}
+			break;
+		case 'h':						/* short */
+			c = *format++;
+			switch (c) {
+			case 'd':					/* short 8進整数 */
+			case 'i':					/* short 8,10,16進整数 */
+				val = (VP_INT) va_arg(ap, VP_INT);
+				count += convert(val, 10, padzero, width, 1, getsub, getbuf, FHALF);
+				break;
+			case 'u':					/* unsigned short 10進整数 */
+				val = (VP_INT) va_arg(ap, VP_INT);
+				count += convert(val, 10, padzero, width, 0, getsub, getbuf, FHALF);
+				break;
+			case 'o':					/* unsigned short 8進整数 */
+				val = (VP_INT) va_arg(ap, VP_INT);
+				count += convert(val, 8, padzero, width, 0, getsub, getbuf, FHALF);
+				break;
+			case 'x':					/* unsigned short 16進整数 */
+				val = (VP_INT) va_arg(ap, VP_INT);
+				count += convert(val, 16, padzero, width, 0, getsub, getbuf, FHALF);
+				break;
+			case 'X':					/* unsigned short 大文字16進整数 */
+				val = (VP_INT) va_arg(ap, VP_INT);
+				count += convert(val, 16, padzero, width, 0, getsub, getbuf, FHALF);
+				break;
+			case '\0':
+				format--;
+				break;
+			}
+			break;
+		case 'd':						/* int 10進整数 */
+		case 'i':						/* int 8,10,16進整数 */
+			val = (VP_INT) va_arg(ap, VP_INT);
+			count += convert(val, 10, padzero, width, 1, getsub, getbuf, FINT);
+			break;
+		case 'u':						/* unsigned int 10進整数 */
+			val = (VP_INT) va_arg(ap, VP_INT);
+			count += convert(val, 10, padzero, width, 0, getsub, getbuf, FINT);
+			break;
+		case 'o':						/* unsigned int 8進整数 */
+			val = (VP_INT) va_arg(ap, VP_INT);
+			count += convert(val, 8, padzero, width, 0, getsub, getbuf, FINT);
+			break;
+		case 'x':						/* unsigned int 16進整数 */
+			val = (VP_INT) va_arg(ap, VP_INT);
+			count += convert(val, 16, padzero, width, 0, getsub, getbuf, FINT);
+			break;
+		case 'X':						/* unsigned int 大文字16進整数 */
+			val = (VP_INT) va_arg(ap, VP_INT);
+			count += convert(val, 16, padzero, width, 0, getsub, getbuf, FINT);
+			break;
+
+		case 'c':						/* 1バイト文字 */
+			str = (char *) va_arg(ap, VP_INT);
+			*str = getsub(getbuf);
+			count++;
+			break;
+		case 's':						/* 文字列 */
+			str = (char *) va_arg(ap, VP_INT);
+			do{
+				c = getsub(getbuf);
+				if(c == ' ' || c == '\t')
+					break;
+				if(is_terminator((char)c))
+					break;
+				if(width > 0)
+					*str++ = c;
+				width--;
+			}while(c != '\0');
+			*str = '\0';
+			count++;
+			break;
+		case '\0':
+			format--;
+			break;
+		default:
+			break;
+		}
+	}
+	return count;
+}
+
+static int getzi (char ** p)
+{
+	return getchar();
+}
+
+int scanf (const char * format, ...)
+{
+    va_list args;
+    va_start(args, format);
+    return (_getformat(getzi, NULL, format, args));
+}
+
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/stdio/sprintf.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/stdio/sprintf.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/stdio/sprintf.c	(revision 453)
@@ -0,0 +1,81 @@
+/*
+ *  TOPPERS/JSP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Just Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2003-2004 by Ryosuke Takeuchi
+ *               GW Development Center RICOH COMPANY,LTD. JAPAN
+ * 
+ *  上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+ *  によって公表されている GNU General Public License の Version 2 に記
+ *  述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+ *  を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+ *  含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+ *  接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *	sprintf代用プログラム
+ */
+
+#include <stdarg.h>
+
+extern int _setformat(void (*)(char c, char **p), char **, const char *, va_list);
+
+static void putz (char c, char ** p)
+{
+    *(*p)++ = c;
+}
+
+/*  sprintf() takes an unlimited number of arguments,
+ *  which the caller has thoughtfully pushed onto the stack.
+ *  It returns a count of bytes moved to the output buffer.
+ */
+int
+sprintf(char * buffer, const char * format, ...)
+{
+    int count;
+    char * pbuffer = buffer;
+    va_list args;
+    va_start(args, format);
+
+    count = _setformat(putz, &pbuffer, format, args);
+    *pbuffer = 0;
+    return count;
+}
+
+int
+vsprintf(char * buffer, const char * format, va_list args)
+{
+    int count;
+    char * pbuffer = buffer;
+
+    count = _setformat(putz, &pbuffer, format, args);
+    *pbuffer = 0;
+    return count;
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/stdio/sscanf.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/stdio/sscanf.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/stdio/sscanf.c	(revision 453)
@@ -0,0 +1,66 @@
+/*
+ *  TOPPERS/JSP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Just Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2003-2006 by Ryosuke Takeuchi
+  *                     GJ Business Division RICOH COMPANY,LTD. JAPAN
+ * 
+ *  上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+ *  によって公表されている GNU General Public License の Version 2 に記
+ *  述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+ *  を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+ *  含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+ *  接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *	sprintf代用プログラム
+ */
+
+#include <stdarg.h>
+
+extern int _getformat(int (*)(char **p), char **, const char *, va_list);
+
+static int getz (char ** p)
+{
+	int c;
+
+	c = *(*p)++;
+	return c;
+}
+
+
+int sscanf(char * buffer, const char * format, ...)
+{
+    char * gbuffer = buffer;
+    va_list args;
+    va_start(args, format);
+
+    return _getformat(getz, &gbuffer, format, args);
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/stdio/stddev.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/stdio/stddev.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/stdio/stddev.c	(revision 453)
@@ -0,0 +1,271 @@
+/*
+ *  TOPPERS/JSP/ASP/FMP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Just Standard Profile Kernel
+ * 
+ *  Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2017 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/* 
+ *  TOPPERS用タスクモニタCPU依存プログラム．
+ *
+ */
+
+#include <itron.h> 
+#include <stdio.h>
+#include <string.h>
+#include "syssvc/serial.h"
+#include "monitor.h"
+
+
+#ifdef _SMALL_STDIO_
+/******************************************************************************
+ * 縮小版標準入出力の設定
+ ******************************************************************************/
+
+FILE _iob[4];
+static ID   dummyid = CONSOLE_PORTID;
+static ID * stdport = &dummyid;
+
+/*
+ *  モニタの１文字入力文
+ */
+static int
+local_getc(FILE *st)
+{
+	char buf[2];
+
+	serial_rea_dat(*stdport, buf, 1);
+	return (int)buf[0];
+}
+
+/*
+ *  モニタの文字列入力文
+ */
+static int
+local_gets(FILE *st, unsigned int len, char *s)
+{
+	return serial_rea_dat(*stdport, s, len);
+}
+
+/*
+ *  モニタの１文字出力文
+ */
+static void
+local_putc(FILE *st, int c)
+{
+	char buf[2];
+
+	buf[0] = c;
+	serial_wri_dat(*stdport, buf, 1);
+	if(c == '\n'){
+		buf[0] = '\r';
+		serial_wri_dat(*stdport, buf, 1);
+	}
+}
+
+/*
+ *  モニタの文字列出力文
+ */
+static int
+local_puts(FILE *st, unsigned int len, char *s)
+{
+	return serial_wri_dat(*stdport, s, len);
+}
+
+/*
+ *  モニタのデータフラッシュ文
+ */
+static int
+local_flush(FILE *st)
+{
+	return 0;
+}
+
+/*
+ *  ローカルなstrlen
+ */
+static int
+local_datacount(const char *s)
+{
+	int i;
+
+	for(i = 0 ; *s != 0 ; i++)
+		s++;
+	return i;
+}
+
+/*
+ *  標準出力関数
+ */
+int fputc(int c, FILE *st)
+{
+	if(st == NULL)
+		st = stdout;
+	st->_func_out(st, c);
+	return 1;
+}
+
+/*
+ *  標準文字列出力関数
+ */
+int fputs(const char *s, FILE *st)
+{
+	int status;
+
+	if(st == NULL)
+		st = stdout;
+	status = st->_func_outs(st, local_datacount(s), (char *)s);
+	st->_func_out(st, '\n');
+	return status;
+}
+
+/*
+ *  標準入力関数
+ */
+int fgetc(FILE *st)
+{
+	if(st == NULL)
+		st = stdin;
+	return st->_func_in(st);
+}
+
+/*
+ *  標準文字列入力関数
+ */
+int fgets(char *buf, int size, FILE *st)
+{
+	if(st == NULL)
+		st = stdin;
+	return st->_func_ins(st, size, buf);
+}
+
+/*
+ *  標準データ読み出し関数
+ */
+size_t fread(void *buf, size_t size, size_t count, FILE *st)
+{
+	int result;
+	if(st == NULL)
+		st = stdin;
+	result = st->_func_ins(st, size*count, buf);
+	return result / size;
+}
+
+/*
+ *  標準データ書き込み関数
+ */
+size_t fwrite(const void *buf, size_t size, size_t count, FILE *st)
+{
+	int result;
+	if(st == NULL)
+		st = stdout;
+	result = st->_func_outs(st, size*count, (char *)buf);
+	return result / size;
+}
+
+/*
+ *  標準文字列出力関数
+ */
+int puts(const char *s)
+{
+	int status;
+
+	status = stdout->_func_outs(stdout, local_datacount(s), (char *)s);
+	stdout->_func_out(stdout, '\n');
+	return status;
+}
+
+/*
+ *  一文字出力プログラム
+ */
+int putchar(int c)
+{
+	return fputc(c,stdout);
+}
+
+/*
+ *  バッファのフラッシュ関数
+ */
+int __wrap_fflush(FILE *st)
+{
+	if(st == NULL)
+		st = stdout;
+	return st->_func_flush(st);
+}
+
+/*
+ *  標準入出力用ストリーム取り出し関数
+ */
+FILE *_get_stdio(int no)
+{
+	return &_iob[no];
+}
+
+/*
+ *  標準入出力ストリーム初期化関数
+ */
+int _set_stdio(int no)
+{
+	if(no >= 0 && no < 3){
+		_iob[no]._file       = -1;
+		_iob[no]._func_in    = (int (*)(void*))local_getc;
+		_iob[no]._func_ins   = (int (*)(void*, unsigned int, char *))local_gets;
+		_iob[no]._func_out   = (void (*)(void*, int))local_putc;
+		_iob[no]._func_outs  = (int  (*)(void*, unsigned int, char *))local_puts;
+		_iob[no]._func_flush = local_flush;
+		_iob[no]._dev        = 0;
+		return no;
+	}
+	else
+		return -1;
+}
+
+/*
+ *  標準入出力初期化関数
+ */
+void _setup_stdio(signed int *pport)
+{
+	int i;
+
+	stdport = pport;
+	for(i = 0 ; i < 3 ; i++){
+		_set_stdio(i);
+	}
+}
+
+#endif /* _SMALL_STDIO_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/task_expansion.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/task_expansion.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/task_expansion.c	(revision 453)
@@ -0,0 +1,393 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2003-2012 by Ryosuke Takeuchi
+ *                     GJ Business Division RICOH COMPANY,LTD. JAPAN
+ * 
+ *  上記著作権者は，Free Software Foundation によって公表されている 
+ *  GNU General Public License の Version 2 に記述されている条件か，以
+ *  下の(1)～(4)の条件を満たす場合に限り，本ソフトウェア（本ソフトウェ
+ *  アを改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを再利用可能なバイナリコード（リロケータブルオブ
+ *      ジェクトファイルやライブラリなど）の形で利用する場合には，利用
+ *      に伴うドキュメント（利用者マニュアルなど）に，上記の著作権表示，
+ *      この利用条件および下記の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを再利用不可能なバイナリコードの形または機器に組
+ *      み込んだ形で利用する場合には，次のいずれかの条件を満たすこと．
+ *    (a) 利用に伴うドキュメント（利用者マニュアルなど）に，上記の著作
+ *        権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 利用の形態を，別に定める方法によって，上記著作権者に報告する
+ *        こと．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者を免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者は，
+ *  本ソフトウェアに関して，その適用可能性も含めて，いかなる保証も行わ
+ *  ない．また，本ソフトウェアの利用により直接的または間接的に生じたい
+ *  かなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *	TOPPERS/ASP用タスク管理拡張機能
+ */
+
+#include "kernel_impl.h"
+#include "check.h"
+#include "task.h"
+#include "task_expansion.h"
+#include "kernel_cfg.h"
+#include "target_timer.h"
+
+/*
+ *  コンテクスト中からの強制待ち状態への移行
+ */
+ER
+isus_tsk(ID tskid)
+{
+	TCB	*tcb;
+	UINT	tstat;
+	ER	ercd;
+
+	CHECK_INTCTX_UNL();
+	CHECK_TSKID(tskid);
+	tcb = get_tcb(tskid);
+
+	i_lock_cpu();
+	if (TSTAT_DORMANT(tstat = tcb->tstat)) {
+		ercd = E_OBJ;
+	}
+	else if (TSTAT_RUNNABLE(tstat)) {
+		/*
+		 *  実行できる状態から強制待ち状態への遷移
+		 */
+		tcb->tstat = TS_SUSPENDED;
+		if (make_non_runnable(tcb)) {
+			reqflg = TRUE;
+		}
+		ercd = E_OK;
+	}
+	else if (TSTAT_SUSPENDED(tstat)) {
+		ercd = E_QOVR;
+	}
+	else {
+		/*
+		 *  待ち状態から二重待ち状態への遷移
+		 */
+		tcb->tstat |= TS_SUSPENDED;
+		ercd = E_OK;
+	}
+	i_unlock_cpu();
+
+    error_exit:
+	return(ercd);
+}
+
+/*
+ *  タスク状態参照（簡易版）
+ */
+ER
+ref_tst(ID tskid, T_RTST *pk_rtst)
+{
+	TCB	*tcb;
+	UB	tstat;
+	ER	ercd;
+
+	CHECK_TSKCTX_UNL();
+	CHECK_TSKID_SELF(tskid);
+	tcb = get_tcb_self(tskid);
+
+	t_lock_cpu();
+	pk_rtst->tskwait  = 0;
+	pk_rtst->tskpri   = EXT_TSKPRI(tcb->priority);
+#ifdef USE_TSKINICTXB
+	pk_rtst->inistk   = (VP)tcb->p_tinib->tskinictxb.stk_bottom;
+	pk_rtst->inistksz = tcb->p_tinib->tskinictxb.stksz;
+#else
+	pk_rtst->inistk   = (VP)tcb->p_tinib->stk;
+	pk_rtst->inistksz = tcb->p_tinib->stksz;
+#endif
+
+	tstat = tcb->tstat;
+	if (TSTAT_RUNNABLE(tstat)) {
+		if (tcb == p_runtsk) {
+			pk_rtst->tskstat = TTS_RUN;
+		}
+		else {
+			pk_rtst->tskstat = TTS_RDY;
+		}
+	}
+	else if (TSTAT_WAITING(tstat)) {
+		if (TSTAT_SUSPENDED(tstat)) {
+			pk_rtst->tskstat = TTS_WAS;
+		}
+		else {
+			pk_rtst->tskstat = TTS_WAI;
+		}
+		if ((tstat & TS_WAIT_MASK) == TS_WAIT_DLY) {
+			pk_rtst->tskwait = TTW_DLY;
+		}
+		else if ((tstat & TS_WAIT_MASK) == TS_WAIT_SLP) {
+			pk_rtst->tskwait = TTW_SLP;
+		}
+		else if ((tstat & TS_WAIT_MASK) == TS_WAIT_RDTQ) {
+			pk_rtst->tskwait = TTW_RDTQ;
+		}
+		else {
+			pk_rtst->tskwait = TTW_OTHR;
+		}
+	}
+	else if (TSTAT_SUSPENDED(tstat)) {
+		pk_rtst->tskstat = TTS_SUS;
+	}
+	else {
+		pk_rtst->tskstat = TTS_DMT;
+	}
+	if (pk_rtst->tskstat == TTS_DMT)
+		pk_rtst->tskpc = (FP)tcb->p_tinib->task;
+	else
+		pk_rtst->tskpc = (FP)tcb->tskctxb.pc;
+	pk_rtst->tsksp   = (VP)tcb->tskctxb.sp;
+	ercd = E_OK;
+	t_unlock_cpu();
+
+    error_exit:
+	return(ercd);
+}
+
+/*
+ *  タスク状態のロギング格納領域
+ */
+static T_TLOG   tsk_log[MAX_TASK_LOG+1];
+static uint32_t check_tskid;
+static SYSTIM   check_time;
+static SYSTIM   pervious_time;
+
+/*
+ *  システム時間取り出し関数
+ *  割込み中でも使用でき、共通化できるように
+ *  インライン関数とする．
+ */
+Inline SYSTIM get_systime(void)
+{
+	return next_time;
+}
+
+/*
+ *  タスクの実測時間測定用の時間
+ *  取り出し関数、CPUロック状態で呼び出す．
+ */
+Inline SYSTIM get_anatime(void)
+{
+	SYSTIM  time;
+#if TIC_DENO != 1
+	INT     subtime;
+#endif /* TIC_DENO != 1 */
+	CLOCK   clock1, clock2;
+	BOOL    ireq;
+
+	/*
+	 * 時間の取り出しはコンテキスト中でも行われるので
+	 * get_utmと同等の記述をここにおく。
+	 */
+#if TIC_DENO != 1
+	subtime = (INT) next_subtime;
+#endif /* TIC_DENO != 1 */
+	clock1 = target_timer_get_current();
+	ireq = target_timer_probe_int();
+	clock2 = target_timer_get_current();
+
+	time = get_systime() * ANA_STIC;
+#if TIC_DENO != 1
+	time += subtime * ANA_STIC / TIC_DENO;
+#endif /* TIC_DENO != 1 */
+	if (!(ireq) || clock1 > clock2) {
+		time -= TIC_NUME * ANA_STIC / TIC_DENO;
+	}
+	time += clock1 * ANA_STIC / TIMER_CLOCK;
+	return time;
+}
+
+/*
+ *  タスク実行領域設定関数
+ *  この関数はdispatchの開始時、CPUロック状態で呼び出す．
+ *  STM32F746はこの関数を複雑にするとハングアップ時間の方はあきらめる．
+ */
+void log_dsp_enter(TCB *runtsk)
+{
+#if !defined(TOPPERS_ARM_M) || defined(TOPPERS_STM32F4_DISCOVERY)
+	SYSTIM time = get_systime();
+#endif	/* ROI DEBUG */
+	T_TLOG  *t;
+
+	if(check_tskid < MAX_TASK_LOG)
+		t = &tsk_log[check_tskid];
+	else
+		t = &tsk_log[MAX_TASK_LOG];
+#if !defined(TOPPERS_ARM_M) || defined(TOPPERS_STM32F4_DISCOVERY)
+	t->runtimes += time - check_time;
+	check_time = time;
+#endif
+	if(p_schedtsk == 0){
+		check_tskid = 0;
+#if defined(TOPPERS_ARM_M) && !defined(TOPPERS_STM32F4_DISCOVERY)
+		t->runtimes += 2;
+//		check_time  += 2;
+#endif
+	}
+}
+
+/*
+ *  タスク実行領域設定関数
+ *  この関数はdispatchの終了時時、CPUロック状態で呼び出す．
+ */
+void log_dsp_leave(TCB *runtsk)
+{
+	SYSTIM time = get_anatime();
+	T_TLOG  *t;
+
+	if(check_tskid < MAX_TASK_LOG)
+		t = &tsk_log[check_tskid];
+	else
+		t = &tsk_log[MAX_TASK_LOG];
+	t->runtimes += time - check_time;
+
+	if(runtsk){
+		check_tskid = TSKID(runtsk);
+		t = &tsk_log[check_tskid];
+		t->runcount++;
+	}
+	else
+		check_tskid = 0;
+	check_time = time;
+}
+
+/*
+ *  タスクログ状態取り出し関数
+ */
+int_t get_tsklog(T_TPRM * pprm)
+{
+	INT no;
+	INT num_item=0;
+
+	get_tim(&pprm->currtime);
+	t_lock_cpu();
+	pprm->pervtime = pervious_time;
+	pervious_time  = pprm->currtime;
+	for(no = 0 ; no <= tmax_tskid && no <= MAX_TASK_LOG ; no++){
+		if(no < NUM_LDSP){
+			pprm->tlog[no] = tsk_log[no];
+			num_item = no;
+		}
+		else{
+			pprm->tlog[1].runcount += tsk_log[no].runcount;
+			pprm->tlog[1].runtimes += tsk_log[no].runtimes;
+			num_item = NUM_LDSP-1;
+		}
+		tsk_log[no].runcount = 0;
+		tsk_log[no].runtimes = 0;
+	}
+	t_unlock_cpu();
+	return num_item;
+}
+
+
+/*
+ *  デバイス・ポートのログアウト要求判定用データ領域
+ */
+
+static T_PCHK port_log[NUM_PCHK];
+
+/*
+ *  デバイスログを行うかどうかの判定
+ */
+static uint_t check_device_log(ulong_t address, ulong_t size)
+{
+	int    i;
+	T_PCHK *p;
+
+	for(i = 0 ; i < NUM_PCHK ; i++){
+		p = &port_log[i];
+		if(p->portaddress >= address && p->portaddress < (address+size) && p->logtype)
+			return (UINT)p->logtype;
+	}
+	return 0;
+}
+
+/*
+ *  デバイス・ポートのログ判定データの取り出し
+ */
+T_PCHK *get_device_log(ulong_t no){
+	if(no < NUM_PCHK)
+		return &port_log[no];
+	else
+		return 0;
+}
+
+/*
+ *  デバイス読み出し表示判定とログアウト関数
+ */
+void
+ana_rdv(ulong_t address, ulong_t data, int_t size)
+{
+	SYSTIM time = get_systime();
+	ID     id;
+	uint_t logtype = check_device_log(address, size);
+
+	if(logtype == 0)
+		return;
+	if(sense_context() || !p_runtsk)
+		syslog_3(logtype, "Device Read  time=%09d interrupt port=%08x data=0x%x", time, address, data);
+	else{
+		id = TSKID(p_runtsk);
+		switch(size){
+		case 4:
+			syslog_4(logtype, "Device Read  time=%09d task=%04d port=%08x data=%08x", time, id, address, data);
+			break;
+		case 2:
+			syslog_4(logtype, "Device Read  time=%09d task=%04d port=%08x data=%04x", time, id, address, data);
+			break;
+		default:
+			syslog_4(logtype, "Device Read  time=%09d task=%04d port=%08x data=%02x", time, id, address, data);
+			break;
+		}
+	}
+}
+
+/*
+ *  デバイス書き込み表示判定とログアウト関数
+ */
+void
+ana_wdv(ulong_t address, ulong_t data, int_t size)
+{
+	SYSTIM time = get_systime();
+	ID     id;
+	uint_t logtype = check_device_log(address, size);
+
+	if(logtype == 0)
+		return;
+	if(sense_context() || !p_runtsk)
+		syslog_3(logtype, "Device Write  time=%09d interrupt port=%08x data=0x%x", time, address, data);
+	else{
+		id = TSKID(p_runtsk);
+		switch(size){
+		case 4:
+			syslog_4(logtype, "Device Write time=%09d task=%04d port=%08x data=%08x", time, id, address, data);
+			break;
+		case 2:
+			syslog_4(logtype, "Device Write time=%09d task=%04d port=%08x data=%04x", time, id, address, data);
+			break;
+		default:
+			syslog_4(logtype, "Device Write time=%09d task=%04d port=%08x data=%02x", time, id, address, data);
+			break;
+		}
+	}
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/task_expansion.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/task_expansion.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/monitor/task_expansion.h	(revision 453)
@@ -0,0 +1,123 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2003-2008 by Ryosuke Takeuchi
+ *                     GJ Business Division RICOH COMPANY,LTD. JAPAN
+ * 
+ *  上記著作権者は，Free Software Foundation によって公表されている 
+ *  GNU General Public License の Version 2 に記述されている条件か，以
+ *  下の(1)～(4)の条件を満たす場合に限り，本ソフトウェア（本ソフトウェ
+ *  アを改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを再利用可能なバイナリコード（リロケータブルオブ
+ *      ジェクトファイルやライブラリなど）の形で利用する場合には，利用
+ *      に伴うドキュメント（利用者マニュアルなど）に，上記の著作権表示，
+ *      この利用条件および下記の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを再利用不可能なバイナリコードの形または機器に組
+ *      み込んだ形で利用する場合には，次のいずれかの条件を満たすこと．
+ *    (a) 利用に伴うドキュメント（利用者マニュアルなど）に，上記の著作
+ *        権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 利用の形態を，別に定める方法によって，上記著作権者に報告する
+ *        こと．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者を免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者は，
+ *  本ソフトウェアに関して，その適用可能性も含めて，いかなる保証も行わ
+ *  ない．また，本ソフトウェアの利用により直接的または間接的に生じたい
+ *  かなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *	TOPPERS/ASPモニタ用タスク用拡張定義
+ */
+
+#ifndef _TASK_EXPANSION_H_
+#define _TASK_EXPANSION_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "itron.h"
+#include "kernel_impl.h"
+
+/*
+ *  タスク状態（簡易版）のパケット形式
+ */
+
+typedef struct t_rtst{
+	STAT    tskstat;			/* タスク状態 */
+	STAT    tskwait;			/* 待ち要因 */
+	PRI     tskpri;				/* タスクの現在の優先度 */
+	FP      tskpc;				/* タスクの現在のプログラムカウンタ */
+	VP      tsksp;				/* タスクの現在のスタックポインタ */
+	VP      inistk;				/* 初期設定のスタックアドレス */
+	SIZE    inistksz;			/* 初期設定のスタックサイズ */
+}T_RTST;
+
+#define	TTW_OTHR	0x0040		/* その他の待ち状態 */
+					/* TOPPERS待ち状態TTW_SEM,TTW_FLG, TTW_SDTQ */
+					/* TTW_MBX, TTW_MPFの待ち状態区別ではない */
+
+/*
+ *  タスクの実行状態構造体定義
+ */
+#define	MAX_TASK_LOG	8		/* タスクログテーブルの数 */
+#define	ANA_STIC		10		/* サブチック値 */
+
+typedef struct t_tlog{
+	int_t   runcount;			/* タスクの実行回数 */
+	SYSTIM	runtimes;			/* タスクの実行時間(MS) */
+}T_TLOG;
+
+/*
+ *  タスクのログ情報取り出し構造体定義
+ */
+
+#define	NUM_LDSP		6		/* 表示用のログ情報取り出し領域の最大数 */
+
+typedef struct t_tprm{
+	SYSTIM  pervtime;			/* 過去の参照時間 */
+	SYSTIM  currtime;			/* 今回の参照時間 */
+	T_TLOG	tlog[NUM_LDSP];		/* 取り出したログ情報 */
+}T_TPRM;
+
+/*
+ *  デバイスポート判定テーブルの構造体定義
+ */
+
+#define	NUM_PCHK		4		/* デバイスポート判定テーブルのアイテム数 */
+
+typedef struct t_pchk{
+	char    logtype;			/* ログ表示判定情報 */
+	ulong_t portaddress;		/* ポートアドレス */
+}T_PCHK;
+
+/*
+ *  プロトタイプ宣言
+ */
+
+extern ER isus_tsk(ID tskid);
+extern ER ref_tst(ID tskid, T_RTST *pk_rtst);
+extern void iana_tsk(void);
+extern void ana_rdv(ulong_t address, ulong_t data, int_t size);
+extern void ana_wdv(ulong_t address, ulong_t data, int_t size);
+extern int_t get_tsklog(T_TPRM *pprm);
+extern T_PCHK *get_device_log(ulong_t no);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TASK_EXPANSION_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/clock.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/clock.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/clock.c	(revision 453)
@@ -0,0 +1,333 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ *
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2012-2015 by GT Development Center RICOH COMPANY,LTD. JAPAN
+ *  Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+ *  によって公表されている GNU General Public License の Version 2 に記
+ *  述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+ *  を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+ *  含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+ *  接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <stdio.h>
+#define _SYS__STDINT_H
+#define clock_t int
+#include <time.h>
+#include "kernel_cfg.h"
+#include "device.h"
+#include "monitor.h"
+
+#define RTC_CLOCK   32768	/* LSE_VALUE */
+
+static int_t date_func(int argc, char **argv);
+static int_t time_func(int argc, char **argv);
+static int_t intmode_func(int argc, char **argv);
+static int_t wakeup_func(int argc, char **argv);
+static int_t clock_func(int argc, char **argv);
+
+/*
+ *  ＲＴＣコマンドテーブル
+ */
+static const COMMAND_INFO rtc_command_info[] = {
+	{"DATE",	date_func    },	/* 日にち設定 */
+	{"TIME",	time_func    },	/* 時間設定 */
+	{"INTM",	intmode_func },	/* INTMODE設定 */
+	{"WAKEUP",	wakeup_func  },	/* WAKEUP設定 */
+	{"CLOCK",	clock_func   }	/* 時計 */
+};
+
+#define NUM_RTC_CMD     (sizeof(rtc_command_info)/sizeof(COMMAND_INFO))
+
+static const char rtc_name[] = "RTC";
+static const char rtc_help[] =
+"  Rtc     DATE  (year #) (month #) (day #)\n"
+"          TIME  (hour #) (min   #) (sec #)\n"
+"          INTM  mode(0-4)\n"
+"          WAKEUP time(sec)\n"
+"          CLOCK DATE:TIME\n";
+
+static const char monthday[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+static COMMAND_LINK rtc_command_link = {
+	NULL,
+	NUM_RTC_CMD,
+	rtc_name,
+	NULL,
+	rtc_help,
+	&rtc_command_info[0]
+};
+
+/*
+ *  ローカルatox
+ */
+static int atoix(char *s)
+{
+	int c, val = 0;
+
+	while((c = *s++) != 0){
+		if(c >= '0' && c <= '9')
+			val = val * 10 + (c - '0');
+	}
+	return val;
+}
+
+/*
+ *  TICK EVENT
+ */
+static void tick_event(int mode)
+{
+	syslog_1(LOG_NOTICE, "rtc tick event(%d) !", mode);
+}
+
+/*
+ *  WAKUP EVENT
+ */
+static void wakeup_event(int reg)
+{
+	syslog_1(LOG_NOTICE, "rtc wakeup event[%08x] !", reg);
+}
+#ifndef NOT_USE_TBP_MKTIME_GMTIME
+/*
+ *  mktime関数
+ */
+time_t mktime(struct tm *ptm)
+{
+	int day = ptm->tm_year *365;
+	int yday, i; 
+
+	day += (ptm->tm_year+2) / 4;
+	for(i = 1, yday = 0 ; i < ptm->tm_mon ; i++)
+		yday += monthday[i-1];
+	if(ptm->tm_mon > 2 && ((ptm->tm_year+2) % 4) == 0)
+		yday++;
+	yday += ptm->tm_mday - 1;
+	day  += yday;
+	ptm->tm_wday = (day+4) % 7;
+	ptm->tm_yday = yday+1;
+	syslog_3(LOG_INFO, "yday[%d] wday[%d] day[%d]", yday+1, ptm->tm_wday, ptm->tm_yday);
+	return day * (24*60*60) + ptm->tm_hour * 60*60 + ptm->tm_min * 60 + ptm->tm_sec;
+}
+
+/*
+ * gmtime_r関数
+ */
+struct tm *gmtime_r(const time_t *pt, struct tm *ptm)
+{
+	int day = *pt / (24*60*60);
+	int time, i, yday, mday;
+
+	time = *pt - day * 24 * 60 * 60;
+	ptm->tm_wday = (day+4) % 7;
+	for(i = 365, ptm->tm_year = 0 ; i < day ; i += 365){
+		if(((ptm->tm_year+2) % 4) == 0)
+			i++;
+		ptm->tm_year++;
+	}
+
+	ptm->tm_yday = yday = day - i + 365 + 1;
+	for(ptm->tm_mon = 1 ; ptm->tm_mon <= 12 && yday > 0 ; ptm->tm_mon++){
+		mday = monthday[ptm->tm_mon-1];
+		if(ptm->tm_mon == 2 && ((ptm->tm_year+2) % 4) == 0)
+			mday++;
+		if(yday < mday){
+			ptm->tm_mday = yday;
+			break;
+		}
+		yday -= mday;
+	}
+	ptm->tm_hour = time / (60*60);
+	time -= ptm->tm_hour * 60 * 60;
+	ptm->tm_min  = time / 60;
+	ptm->tm_sec = time % 60;
+	return ptm;
+}
+#endif
+int
+_gettimeofday (struct timeval * tp, void * tzvp)
+{
+	struct tm timedate;
+	if (!tp) return 0;
+	rtc_get_time((struct tm2 *)&timedate);
+	uint64_t time = (uint64_t)mktime(&timedate) * (uint64_t)1000000;
+	tp->tv_sec = time / 1000000;
+	tp->tv_usec = time - (tp->tv_sec * 1000000);
+	return 0;
+}
+
+/*
+ *  RTCコマンド設定関数
+ */
+void rtc_info_init(intptr_t exinf)
+{
+	setup_command(&rtc_command_link);
+}
+
+/*
+ *  日付設定コマンド関数
+ */
+static int_t date_func(int argc, char **argv)
+{
+	struct tm timedate;
+	int arg1 = 2016;
+
+	ER ret = rtc_get_time((struct tm2 *)&timedate);
+	if (ret != E_OK){
+		printf("rtc_get_time %s\n", itron_strerror(ret));
+	}
+	if(argc > 1)
+		arg1 = atoix(argv[1]);
+	if(argc > 2)
+		timedate.tm_mon = atoix(argv[2]) - 1;
+	else
+		timedate.tm_mon = 0;
+	if(argc > 3)
+		timedate.tm_mday = atoix(argv[3]);
+	else
+		timedate.tm_mday = 1;
+	printf("%04d/%02d/%02d\n", arg1, timedate.tm_mon + 1, timedate.tm_mday);
+	timedate.tm_year = arg1-1900;
+	timedate.tm_isdst = 0;
+	mktime((struct tm *)&timedate);
+	ret = rtc_set_time((struct tm2 *)&timedate);
+	if (ret != E_OK){
+		printf("rtc_set_time %s\n", itron_strerror(ret));
+	}
+	return 0;
+}
+
+/*
+ *  時間設定コマンド関数
+ */
+static int_t time_func(int argc, char **argv)
+{
+	struct tm2 timedate;
+
+	ER ret = rtc_get_time(&timedate);
+	if (ret != E_OK){
+		printf("rtc_get_time %s\n", itron_strerror(ret));
+	}
+	if(argc > 1)
+		timedate.tm_hour = atoix(argv[1]);
+	else
+		timedate.tm_hour = 0;
+	if(argc > 2)
+		timedate.tm_min = atoix(argv[2]);
+	else
+		timedate.tm_min = 0;
+	if(argc > 3)
+		timedate.tm_sec = atoix(argv[3]);
+	else
+		timedate.tm_sec = 0;
+	printf("%02d:%02d:%02d\n", timedate.tm_hour, timedate.tm_min, timedate.tm_sec);
+	timedate.tm_isdst = 0;
+	mktime((struct tm *)&timedate);
+	ret = rtc_set_time(&timedate);
+	if (ret != E_OK){
+		printf("rtc_set_time %s\n", itron_strerror(ret));
+	}
+	return 0;
+}
+
+/*
+ *  TICK割込み設定
+ */
+static int_t intmode_func(int argc, char **argv)
+{
+	int8_t mode = -1;
+	if(argc > 1){
+		mode = atoix(argv[1]);
+		if(mode > 3)
+			printf("reset intmode(%d)\n", rtc_intmode(mode, NULL));
+		else
+			printf("setup intmode(%d)\n", rtc_intmode(mode, tick_event));
+	}
+	else
+		printf("current intmode(%d)\n", rtc_intmode(mode, NULL));
+	return 0;
+}
+
+/*
+ *  WAKEUPイベント設定関数
+ */
+static int_t wakeup_func(int argc, char **argv)
+{
+	uint32_t count = 0;
+	struct tm2 timedate;
+	RTC_Alarm_t alarm_param;
+
+	rtc_get_time(&timedate);
+	if(argc > 1){
+		count = atoix(argv[1]);
+		alarm_param.alarmmask = RTC_ALARM_SECOND | RTC_ALARM_MINUTE | RTC_ALARM_HOUR;
+		alarm_param.callback  = wakeup_event;
+		timedate.tm_sec += count;
+		while(timedate.tm_sec >= 60){
+			timedate.tm_sec -= 60;
+			if(++timedate.tm_min >= 60){
+				timedate.tm_min -= 60;
+				if(++timedate.tm_hour >= 24)
+					timedate.tm_hour = 0;
+			}
+		}
+		rtc_setalarm(&alarm_param, &timedate);
+		printf("wakeup %02d:%02d:%02d !\n", timedate.tm_hour, timedate.tm_min, timedate.tm_sec);
+	}
+	else{
+		alarm_param.alarmmask = 0;
+		rtc_setalarm(&alarm_param, &timedate);
+		printf("stop wakeup event !\n");
+	}
+	return 0;
+}
+
+/*
+ *  時刻取出しコマンド関数
+ */
+static int_t clock_func(int argc, char **argv)
+{
+	struct tm2 timedate;
+
+	ER ret = rtc_get_time(&timedate);
+	if (ret != E_OK){
+		printf("rtc_get_time %s\n", itron_strerror(ret));
+	}
+	mktime((struct tm *)&timedate);
+	printf("  %04d/%02d/%02d yday[%d]\n", timedate.tm_year+1900, timedate.tm_mon+1, timedate.tm_mday, timedate.tm_yday);
+	printf("    %02d:%02d:%02d wday[%d]\n", timedate.tm_hour, timedate.tm_min, timedate.tm_sec, timedate.tm_wday);
+	return 0;
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/device.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/device.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/device.c	(revision 453)
@@ -0,0 +1,1182 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  K210用デバイスドライバ
+ */
+#include "kernel_impl.h"
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <sil.h>
+#include <target_syssvc.h>
+#include "kernel_cfg.h"
+#include "device.h"
+
+
+Inline uint64_t
+sil_rel_mem(const uint64_t *mem)
+{
+	uint64_t	data;
+
+	data = *((const volatile uint64_t *) mem);
+	return(data);
+}
+
+Inline void
+sil_wrl_mem(uint64_t *mem, uint64_t data)
+{
+	*((volatile uint64_t *) mem) = data;
+}
+
+/*
+ *  SIL関数のマクロ定義
+ */
+#define sil_orw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) | (b))
+#define sil_andw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) & ~(b))
+#define sil_modw_mem(a, b, c)	sil_wrw_mem((a), (sil_rew_mem(a) & (~b)) | (c))
+#define sil_orl_mem(a, b)		sil_wrl_mem((a), sil_rel_mem(a) | (b))
+#define sil_andl_mem(a, b)		sil_wrl_mem((a), sil_rel_mem(a) & ~(b))
+#define sil_modl_mem(a, b, c)	sil_wrl_mem((a), (sil_rel_mem(a) & (~b)) | (c))
+
+/*
+ *  サービスコールのエラーのログ出力
+ */
+Inline void
+svc_perror(const char *file, int_t line, const char *expr, ER ercd)
+{
+	if (ercd < 0) {
+		t_perror(LOG_ERROR, file, line, expr, ercd);
+	}
+}
+
+#define	SVC_PERROR(expr)	svc_perror(__FILE__, __LINE__, #expr, (expr))
+
+
+/*
+ *  GPIOモードの内部定義
+ */
+#define GPIO_MODE               0x00000001
+#define GPIO_MODE_IT            0x00010000
+#define RISING_EDGE             0x00100000
+#define FALLING_EDGE            0x00200000
+#define HIGH_LEVEL              0x00400000
+#define LOW_LEVEL               0x00800000
+#define GPIO_OUTPUT_TYPE        0x00000010
+
+#define GPIO_ID                 0
+#define GPIOHS_ID               1
+
+#ifndef NON_INT_GPIOHS_IO
+#define NON_INT_GPIOHS_IO       4
+#endif
+
+typedef struct {
+	uint8_t  maxpin;
+	uint8_t  funcbase;
+	uint16_t diroff;
+	uint16_t outoff;
+	uint16_t inoff;
+} gpio_pcb_type;
+
+static const gpio_pcb_type pcb_table[2] = {
+	{GPIO_MAX_PINNO,   FUNC_GPIO0,
+	 TOFF_GPIO_DIRECTION,   TOFF_GPIO_DATA_OUTOUT,  TOFF_GPIO_DATA_INPUT},
+	{GPIOHS_MAX_PINNO, FUNC_GPIOHS0,
+	 TOFF_GPIOHS_OUTPUT_EN, TOFF_GPIOHS_OUTPUT_VAL, TOFF_GPIOHS_INPUT_VAL}
+};
+
+int8_t arduino_gpio_table[ARDUINO_GPIO_PORT];
+
+/*
+ *  GPIOの種別IDを取り出す
+ */
+static int gpio_get_no(unsigned long base)
+{
+	if(base == TADR_GPIO_BASE)
+		return 0;
+	else if(base == TADR_GPIOHS_BASE)
+		return 1;
+	else
+		return -1;
+}
+
+/*
+ *  GPIOの初期設定関数
+ */
+void
+gpio_setup(unsigned long base, GPIO_Init_t *init, uint32_t pin)
+{
+	const gpio_pcb_type *pt;
+	uint32_t dir, io_number, off;
+	uint8_t  ch_sel;
+	int no = gpio_get_no(base);
+
+	if(no < 0 || init == NULL)
+		return;
+
+	pt  = &pcb_table[no];
+	if(pin >= pt->maxpin || init->pull >= GPIO_PULLMAX)
+		return;
+	dir = init->mode & GPIO_MODE;
+
+    for(io_number = 0, off = TOFF_FPIOA_IO ; io_number < FPIOA_NUM_IO ; io_number++, off += 4){
+		ch_sel = sil_rew_mem((uint32_t *)(TADR_FPIOA_BASE+off)) & FPIOA_CH_SEL;
+        if(ch_sel == (pt->funcbase + pin))
+            break;
+    }
+	if(io_number >= FPIOA_NUM_IO)
+		return;
+
+	switch(init->pull){
+	case GPIO_NOPULL:
+		sil_andw_mem((uint32_t *)(TADR_FPIOA_BASE+off), (FPIOA_PU | FPIOA_PD));
+		break;
+	case GPIO_PULLDOWN:
+		sil_andw_mem((uint32_t *)(TADR_FPIOA_BASE+off), FPIOA_PU);
+		sil_orw_mem((uint32_t *)(TADR_FPIOA_BASE+off), FPIOA_PD);
+		break;
+	case GPIO_PULLUP:
+		sil_orw_mem((uint32_t *)(TADR_FPIOA_BASE+off), FPIOA_PU);
+		sil_andw_mem((uint32_t *)(TADR_FPIOA_BASE+off), FPIOA_PD);
+		break;
+	default:
+		break;
+    }
+
+	if(no == GPIO_ID){	/* GPIO */
+		sil_modw_mem((uint32_t *)(base+TOFF_GPIO_DIRECTION), (1<<pin), (dir<<pin));
+	}
+	else{				/* GPIOHS */
+		uint32_t off, off_d;
+		off = dir ? TOFF_GPIOHS_OUTPUT_EN : TOFF_GPIOHS_INPUT_EN;
+		off_d = !dir ? TOFF_GPIOHS_OUTPUT_EN : TOFF_GPIOHS_INPUT_EN;
+		sil_andw_mem((uint32_t *)(base+off_d), 1<<pin);
+		sil_orw_mem((uint32_t *)(base+off), 1<<pin);
+
+		sil_andw_mem((uint32_t *)(base+TOFF_GPIOHS_RISE_IE), (1<<pin));
+		sil_orw_mem((uint32_t *)(base+TOFF_GPIOHS_RISE_IP), (1<<pin));
+		sil_andw_mem((uint32_t *)(base+TOFF_GPIOHS_FALL_IE), (1<<pin));
+		sil_orw_mem((uint32_t *)(base+TOFF_GPIOHS_FALL_IP), (1<<pin));
+		sil_andw_mem((uint32_t *)(base+TOFF_GPIOHS_LOW_IE), (1<<pin));
+		sil_orw_mem((uint32_t *)(base+TOFF_GPIOHS_LOW_IP), (1<<pin));
+		sil_andw_mem((uint32_t *)(base+TOFF_GPIOHS_HIGH_IE), (1<<pin));
+		sil_orw_mem((uint32_t *)(base+TOFF_GPIOHS_HIGH_IP), (1<<pin));
+		if((init->mode & GPIO_MODE_IT) != 0){
+			if((init->mode & FALLING_EDGE) != 0)
+				sil_orw_mem((uint32_t *)(base+TOFF_GPIOHS_FALL_IE), (1<<pin));
+			if((init->mode & RISING_EDGE) != 0)
+				sil_orw_mem((uint32_t *)(base+TOFF_GPIOHS_RISE_IE), (1<<pin));
+			if((init->mode & LOW_LEVEL) != 0)
+				sil_orw_mem((uint32_t *)(base+TOFF_GPIOHS_LOW_IE), (1<<pin));
+			if((init->mode & HIGH_LEVEL) != 0)
+				sil_orw_mem((uint32_t *)(base+TOFF_GPIOHS_HIGH_IE), (1<<pin));
+		}
+	}
+}
+
+/*
+ *  GPIOピン設定
+ */
+void
+gpio_set_pin(unsigned long base, uint8_t pin, uint8_t value)
+{
+	const gpio_pcb_type *pt;
+	int no = gpio_get_no(base);
+	uint32_t dir;
+
+	if(no < 0)
+		return;
+	pt  = &pcb_table[no];
+	if(pin >= pt->maxpin)
+		return;
+	dir = (sil_rew_mem((uint32_t *)(base+pt->diroff)) >> pin) & 1;
+	if(dir == 0)
+		return;
+	value &= 1;
+	sil_modw_mem((uint32_t *)(base+pt->outoff), (1<<pin), (value<<pin));
+}
+
+/*
+ *  GPIOピンデータ取得
+ */
+uint8_t
+gpio_get_pin(unsigned long base, uint8_t pin)
+{
+	const gpio_pcb_type *pt;
+	int no = gpio_get_no(base);
+	uint32_t dir, off;
+
+	if(no < 0)
+		return 0;
+	pt  = &pcb_table[no];
+	if(pin >= pt->maxpin)
+		return 0;
+	dir = (sil_rew_mem((uint32_t *)(base+pt->diroff)) >> pin) & 1;
+	off = dir ? pt->outoff : pt->inoff;
+	return (sil_rew_mem((uint32_t *)(base+off)) >> pin) & 1;
+}
+
+/*
+ *  GPIOHSの空きファンクション番号を返す
+ */
+int
+gpio_get_gpiohno(uint8_t fpio_pin, bool_t intreq)
+{
+#if NON_INT_GPIOHS_IO > 0
+	static uint8_t io0 = 0;
+#endif
+	static uint8_t io1 = NON_INT_GPIOHS_IO;
+	int io = -1;
+
+	if(arduino_gpio_table[fpio_pin] >= 0)
+		return (int)arduino_gpio_table[fpio_pin];
+#if NON_INT_GPIOHS_IO > 0
+	else if(intreq && io0 < (NON_INT_GPIOHS_IO-1)){
+		io = (int)io0++;
+		arduino_gpio_table[fpio_pin] = io;
+	}
+#endif
+	else{
+		if(io1 <= (FUNC_GPIOHS31-FUNC_GPIOHS0)){
+			io = (int)io1++;
+			arduino_gpio_table[fpio_pin] = io;
+		}
+    }
+	return io;
+}
+
+
+/*
+ *  DMACの設定関数
+ */
+#define DMAC_COM_INTVALUE     (DMAC_COM_INTSTATUS_SLVIF_DEC_ERR   | DMAC_COM_INTSTATUS_SLVIF_WR2RO_ERR |\
+                               DMAC_COM_INTSTATUS_SLVIF_RD2WO_ERR | DMAC_COM_INTSTATUS_SLVIF_WRONHOLD_ERR |\
+                               DMAC_COM_INTSTATUS_SLVIF_UNDEFREG_ERR)
+
+#define DMAC_CH_CFG_DEFAULT   (DMACCH_CFG_SRC_MULTBLKTYPE | DMACCH_CFG_DST_MULTBLKTYPE |\
+                               DMACCH_CFG_TT_FC | DMACCH_CFG_HS_SEL_SRC | DMACCH_CFG_HS_SEL_DST |\
+                               DMACCH_CFG_SRC_PER | DMACCH_CFG_DST_PER)
+
+#define DMAC_CH_CTL_SRC       (DMACCH_CTL_SMS | DMACCH_CTL_SINC | DMACCH_CTL_SRC_TR_WIDTH | DMACCH_CTL_SRC_MSIZE)
+#define DMAC_CH_CTL_DST       (DMACCH_CTL_DMS | DMACCH_CTL_DINC | DMACCH_CTL_DST_TR_WIDTH | DMACCH_CTL_DST_MSIZE)
+#define DMAC_CH_CTL_DEFAULT   (DMAC_CH_CTL_SRC | DMAC_CH_CTL_DST)
+
+#define DMAC_CH_INT_ERROR     (DMACCH_ENABLE_SRC_DEC_ERR_INSTAT   | DMACCH_ENABLE_DST_DEC_ERR_INSTAT    |\
+                               DMACCH_ENABLE_SRC_SLV_ERR_INSTAT   | DMACCH_ENABLE_DST_SLV_ERR_INSTAT)
+#define DMAC_CH_INT_DEFAULT   (DMACCH_ENABLE_DMA_TFR_DONE_INTSTAT | DMACCH_ENABLE_SRC_TRANSCOMP_INTSTAT |\
+                               DMACCH_ENABLE_DST_TRANSCOMP_INSTAT | DMAC_CH_INT_ERROR)
+
+#define DMAC_CHANNEL_ENABLE   (DMAC_CHEN_CH1_EN | DMAC_CHEN_CH2_EN | DMAC_CHEN_CH3_EN |\
+                               DMAC_CHEN_CH4_EN | DMAC_CHEN_CH5_EN | DMAC_CHEN_CH6_EN)
+
+static DMA_Handle_t *pDmaHandler[NUM_DMA_CHANNEL];
+
+/*
+ *  DMACの初期化
+ */
+static void
+dmac_init(void)
+{
+    uint64_t tmp;
+
+	sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_PERI), SYSCTL_CLK_EN_PERI_DMA_CLK_EN);
+
+	/*
+	 *  DMACリセット
+	 */
+	sil_orl_mem((uint64_t *)(TADR_DMAC_BASE+TOFF_DMAC_RESET), DMAC_RESET_RST);
+	while((sil_rel_mem((uint64_t *)(TADR_DMAC_BASE+TOFF_DMAC_RESET)) & DMAC_RESET_RST) != 0);
+
+    /*
+	 *  COMMON割込みクリア
+	 */
+	sil_wrl_mem((uint64_t *)(TADR_DMAC_BASE+TOFF_DMAC_COM_INTCLEAR), DMAC_COM_INTVALUE);
+
+	/*
+	 *  DMAC無効化
+	 */
+	sil_wrl_mem((uint64_t *)(TADR_DMAC_BASE+TOFF_DMAC_CFG), 0);
+	while(sil_rel_mem((uint64_t *)(TADR_DMAC_BASE+TOFF_DMAC_CFG)) != 0);
+
+	/*
+	 *  チャネル無効化
+	 */
+	tmp = sil_rel_mem((uint64_t *)(TADR_DMAC_BASE+TOFF_DMAC_CHEN));
+    tmp &= ~DMAC_CHANNEL_ENABLE;
+	sil_wrl_mem((uint64_t *)(TADR_DMAC_BASE+TOFF_DMAC_CHEN), tmp);
+
+	/*
+	 *  DMAC有効化
+	 */
+	sil_wrl_mem((uint64_t *)(TADR_DMAC_BASE+TOFF_DMAC_CFG), (DMAC_CFG_DMAC_EN | DMAC_CFG_INT_EN));
+}
+
+/*
+ *  チャンネルCFG/CTLレジスタ設定
+ */
+static void
+dma_config(DMA_Handle_t *hdma)
+{
+	uint64_t cfg, ctl;
+
+	/* DMA-CFGレジスタ設定 */
+    cfg = sil_rel_mem((uint64_t *)(hdma->cbase+TOFF_DMAC_CH_CFG));
+	cfg &= ~(DMAC_CH_CFG_DEFAULT | DMACCH_CFG_SRC_HWHS_POL | DMACCH_CFG_DST_HWHS_POL | DMACCH_CFG_CH_PRIOR);
+	cfg |= (hdma->Init.SrcMultBlock << 0) | (hdma->Init.DrcMultBlock << 2);
+	cfg |= (uint64_t)hdma->Init.Direction << 32;
+	cfg |= ((uint64_t)hdma->Init.SrcHandShake << 35) | ((uint64_t)hdma->Init.DrcHandShake << 36);
+	cfg |= ((uint64_t)hdma->Init.SrcHwhsPol << 37)   | ((uint64_t)hdma->Init.DrcHwhsPol << 38);
+	cfg |= ((uint64_t)hdma->chnum << 39)    | ((uint64_t)hdma->chnum << 44);
+	cfg |= (uint64_t)hdma->Init.Priority << 49;
+	sil_wrl_mem((uint64_t *)(hdma->cbase+TOFF_DMAC_CH_CFG), cfg);
+
+	/* DMA-CTLレジスタ設定 */
+    ctl = sil_rel_mem((uint64_t *)(hdma->cbase+TOFF_DMAC_CH_CTL));
+	ctl &= ~(DMAC_CH_CTL_DEFAULT | DMACCH_CTL_IOC_BLKTFR);
+	ctl |= (hdma->Init.SrcMaster << 0) | (hdma->Init.DstMaster << 2);
+	ctl |= (hdma->Init.SrcInc << 4)    | (hdma->Init.DstInc << 6);
+	ctl |= (hdma->Init.SrcTransWidth << 8) | (hdma->Init.DstTransWidth << 11);
+	ctl |= (hdma->Init.SrcBurstSize << 14) | (hdma->Init.DstBurstSize << 18);
+	ctl |= (uint64_t)hdma->Init.IocBlkTrans << 58;
+	sil_wrl_mem((uint64_t *)(hdma->cbase+TOFF_DMAC_CH_CTL), ctl);
+}
+
+/*
+ *  CHANNEL DMA初期化関数
+ *  parameter1  hdma: DMAハンドラへのポインタ
+ *  return ER値
+ */
+ER
+dma_init(DMA_Handle_t *hdma)
+{
+	/* パラメータチェック */
+	if(hdma == NULL || hdma->chnum >= NUM_DMA_CHANNEL)
+		return E_PAR;
+	if(pDmaHandler[hdma->chnum] != NULL)
+		return E_OBJ;
+
+	hdma->base  = TADR_DMAC_BASE;
+	hdma->cbase = hdma->base + TOFF_DMAC_CHANNEL + hdma->chnum * DMAC_CHANNEL_WINDOW_SIZE;
+	select_dma_channel(hdma->chnum, hdma->Init.Request);
+	pDmaHandler[hdma->chnum] = hdma;
+
+	/* DMA-CFG/CTLレジスタ設定 */
+	dma_config(hdma);
+
+	/* エラー状態をクリア */
+	hdma->status    = DMA_STATUS_READY;
+	hdma->ErrorCode = DMA_ERROR_NONE;
+	return E_OK;
+}
+
+/*
+ *  チャネルDMA終了関数
+ *  parameter1  hdma: DMAハンドラへのポインタ
+ *  return ER値
+ */
+ER
+dma_deinit(DMA_Handle_t *hdma)
+{
+	/* パラメータチェック */
+	if(hdma == NULL || hdma->chnum >= NUM_DMA_CHANNEL)
+		return E_PAR;
+
+	/*
+	 *  チャンネルの無効化
+	 */
+	dma_end(hdma);
+	pDmaHandler[hdma->chnum] = NULL;
+
+	/* エラー状態をクリア */
+	hdma->ErrorCode = DMA_ERROR_NONE;
+	return E_OK;
+}
+
+/*
+ *  CHANNEL DMAリセット関数
+ *  parameter1  hdma: DMAハンドラへのポインタ
+ *  return ER値
+ */
+ER
+dma_reset(DMA_Handle_t *hdma)
+{
+	uint32_t tick = 0;
+
+	/* パラメータチェック */
+	if(hdma == NULL || hdma->chnum >= NUM_DMA_CHANNEL)
+		return E_PAR;
+
+	while((sil_rel_mem((uint64_t *)(hdma->base+TOFF_DMAC_CHEN)) & (1 << hdma->chnum)) != 0){
+		dly_tsk(1);
+		if(tick++ >= DMA_TRS_TIMEOUT)
+			return E_TMOUT;
+	}
+
+	/* DMA-CFGレジスタ設定 */
+	dma_config(hdma);
+	return E_OK;
+}
+
+/*
+ *  チャネルDMA開始関数
+ *  parameter1  hdma:       DMAハンドラへのポインタ
+ *  parameter2  SrcAddress: ソースアドレス
+ *  parameter3  DstAddress: デスティネーションアドレス
+ *  parameter4  DataLength: 転送長
+ *  return ER値
+ */
+ER
+dma_start(DMA_Handle_t *hdma, uintptr_t SrcAddress, uintptr_t DstAddress, uint32_t DataLength)
+{
+	uint64_t tmp;
+
+	/* パラメータチェック */
+	if(hdma == NULL || hdma->chnum >= NUM_DMA_CHANNEL)
+		return E_PAR;
+
+	hdma->status = DMA_STATUS_BUSY;
+	hdma->ErrorCode = DMA_ERROR_NONE;
+
+	/*
+	 *  割込み要因クリア
+	 */
+	sil_wrl_mem((uint64_t *)(hdma->cbase+TOFF_DMAC_CH_INTCLEAR), 0xFFFFFFFF);
+
+	/*
+	 *  転送設定
+	 */
+	sil_wrl_mem((uint64_t *)(hdma->cbase+TOFF_DMAC_CH_SAR), (uint64_t)SrcAddress);
+	sil_wrl_mem((uint64_t *)(hdma->cbase+TOFF_DMAC_CH_DAR), (uint64_t)DstAddress);
+	sil_wrl_mem((uint64_t *)(hdma->cbase+TOFF_DMAC_CH_BLOCK_TS), DataLength - 1);
+
+	/*
+	 *  DMAC有効化
+	 */
+	sil_wrl_mem((uint64_t *)(hdma->base+TOFF_DMAC_CFG), (DMAC_CFG_DMAC_EN | DMAC_CFG_INT_EN));
+	sil_wrl_mem((uint64_t *)(hdma->cbase+TOFF_DMAC_CH_INTSTATUS_EN), DMAC_CH_INT_DEFAULT);
+
+	/* DMA開始 */
+	tmp = sil_rel_mem((uint64_t *)(hdma->base+TOFF_DMAC_CHEN));
+	tmp |= (DMAC_CHEN_CH1_EN | DMAC_CHEN_CH1_EN_WE) << hdma->chnum;
+	sil_wrl_mem((uint64_t *)(hdma->base+TOFF_DMAC_CHEN), tmp);
+	return E_OK;
+}
+
+/*
+ *  チャネルDMA停止関数
+ *  parameter1  hdma  : DMAハンドラへのポインタ
+ *  return ER値
+ */
+ER
+dma_end(DMA_Handle_t *hdma)
+{
+	uint64_t tmp;
+
+	if(hdma == NULL || hdma->chnum >= NUM_DMA_CHANNEL)
+		return E_PAR;
+
+	/* DMA停止 */
+	tmp = sil_rel_mem((uint64_t *)(hdma->base+TOFF_DMAC_CHEN));
+	tmp &= ~DMAC_CHEN_CH1_EN << hdma->chnum;
+	tmp |= DMAC_CHEN_CH1_EN_WE << hdma->chnum;
+	sil_wrl_mem((uint64_t *)(hdma->base+TOFF_DMAC_CHEN), tmp);
+
+	hdma->status    = DMA_STATUS_READY;
+	return E_OK;
+}
+
+/*
+ *  チャネルDMA割込み処理関数
+ *  parameter1  hdma: DMAハンドラへのポインタ
+ */
+void
+dma_inthandler(DMA_Handle_t *hdma)
+{
+	uint64_t intstatus, intstatus_en;
+
+	intstatus    = sil_rel_mem((uint64_t *)(hdma->cbase+TOFF_DMAC_CH_INTSTATUS));
+	intstatus_en = sil_rel_mem((uint64_t *)(hdma->cbase+TOFF_DMAC_CH_INTSTATUS_EN));
+	syslog_2(LOG_DEBUG, "dma_inthandler instatus[%08x][%08x]", (int)intstatus, (int)intstatus_en);
+	if((intstatus & intstatus_en & DMACCH_ENABLE_DMA_TFR_DONE_INTSTAT) != 0){
+		hdma->status = DMA_STATUS_READY_TRN1;
+		if(hdma->xfercallback != NULL)
+			hdma->xfercallback(hdma);
+	}
+	else if((intstatus & intstatus_en & DMACCH_ENABLE_SRC_TRANSCOMP_INTSTAT) != 0){
+		hdma->status = DMA_STATUS_READY_TRN2;
+		if(hdma->xfercallback != NULL)
+			hdma->xfercallback(hdma);
+	}
+	else if((intstatus & intstatus_en & DMACCH_ENABLE_DST_TRANSCOMP_INSTAT) != 0){
+		hdma->status = DMA_STATUS_READY_TRN3;
+		if(hdma->xfercallback != NULL)
+			hdma->xfercallback(hdma);
+	}
+	if((intstatus & intstatus_en & DMAC_CH_INT_ERROR) != 0){
+		hdma->ErrorCode |= intstatus & intstatus_en & DMAC_CH_INT_ERROR;
+		if(hdma->errorcallback != NULL)
+			hdma->errorcallback(hdma);
+	}
+	sil_wrl_mem((uint64_t *)(hdma->cbase+TOFF_DMAC_CH_INTCLEAR), intstatus);
+}
+
+/*
+ *  チャネルDMA 割込みサービスルーチン
+ */
+void
+channel_dmac_isr(intptr_t exinf)
+{
+	dma_inthandler(pDmaHandler[(uint32_t)exinf]);
+}
+
+ER
+select_dma_channel(uint8_t channel, uint8_t select)
+{
+	uint32_t dma_sel;
+
+	if(select >= NUM_DMA_SELECT)
+		return E_PAR;
+	if(channel < DMA_CHANNEL5){
+		dma_sel  = sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_DMA_SEL0));
+		dma_sel &= ~(0x3F << (channel * 6));
+		dma_sel |= select << (channel * 6);
+		sil_wrw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_DMA_SEL0), dma_sel);
+		return E_OK;
+	}
+	else if(channel == DMA_CHANNEL5){
+		dma_sel  = sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_DMA_SEL1));
+		dma_sel &= ~0x3F;
+		dma_sel |= select;
+		sil_wrw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_DMA_SEL1), dma_sel);
+		return E_OK;
+	}
+	else
+	    return E_PAR;
+}
+
+
+/*
+ *  WDOGドライバ
+ */
+/*
+ *  SPIOポートIDから管理ブロックを取り出すためのマクロ
+ */
+#define INDEX_WDOG(wdogid)        ((uint_t)((wdogid) - 1))
+
+typedef struct {
+	unsigned long   base;
+	uint32_t        reset;
+	uint32_t        threshold;
+	uint32_t        thshift;
+	uint32_t        bus_en;
+	uint32_t        peri_en;
+} WDT_PortControlBlock;
+
+static const WDT_PortControlBlock wdt_table[2] = {
+	{TADR_WDT0_BASE, SYSCTL_PERI_RESET_WDT0_RESET, SYSCTL_CLK_TH6_WD0_CLK_THHD,
+	 0, SYSCTL_CLK_EN_CENT_APB1_CLK_EN, SYSCTL_CLK_EN_PERI_WDT0_CLK_EN},
+	{TADR_WDT1_BASE, SYSCTL_PERI_RESET_WDT1_RESET, SYSCTL_CLK_TH6_WD1_CLK_THHD,
+	 8, SYSCTL_CLK_EN_CENT_APB1_CLK_EN, SYSCTL_CLK_EN_PERI_WDT1_CLK_EN}
+};
+
+static WDT_Handle_t WdtHandle[NUM_WDOGPORT];
+
+
+/*
+ *  WDT無効化
+ */
+static void
+wdt_disable(WDT_Handle_t *hwdt)
+{
+	sil_wrw_mem((uint32_t *)(hwdt->base+TOFF_WDT_CRR), WDT_CRR_MASK);
+	sil_andw_mem((uint32_t *)(hwdt->base+TOFF_WDT_CR), WDT_CR_ENABLE);
+}
+
+/*
+ *  WINDOW WATCH-DOG初期化
+ *  parameter1  port: WDOGポート番号
+ *  return WDTハンドラへのポインタ
+ */
+WDT_Handle_t *
+wdt_init(ID port)
+{
+	const WDT_PortControlBlock *pcb;
+	WDT_Handle_t *hwdt;
+	uint8_t  no;
+	uint32_t source = SYSCTRL_CLOCK_FREQ_IN0;
+	uint32_t threshold;
+
+	if(port < WDOG1_PORTID || port >= NUM_WDOGPORT)
+		return NULL;
+
+	no = INDEX_WDOG(port);
+	pcb = &wdt_table[no];
+	hwdt = &WdtHandle[no];
+
+	hwdt->base  = pcb->base;
+	hwdt->wdtno = no;
+	hwdt->callback = NULL;
+
+	/*
+	 *  WDTリセット
+	 */
+	sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_PERI_RESET), pcb->reset);
+	sil_dly_nse(10*1000);
+	sil_andw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_PERI_RESET), pcb->reset);
+
+	/*
+	 *  WDT初期化
+	 */
+	sil_andw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_TH6), pcb->threshold);
+	sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_CENT), pcb->bus_en);
+	sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_PERI), pcb->peri_en);
+
+	sil_modw_mem((uint32_t *)(hwdt->base+TOFF_WDT_CR), WDT_CR_RMOD_MASK, WDT_CR_RMOD_INTERRUPT);
+
+	threshold = sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_TH6)) & pcb->threshold;
+	threshold >>= pcb->thshift;
+
+	hwdt->pclk = source / ((threshold + 1) * 2);
+
+    wdt_disable(hwdt);
+    return hwdt;
+}
+
+/*
+ *  WINDOW WATCH-DOG終了設定
+ *  parameter1  hwdt: WDOGハンドラ
+ *  return ERコード
+ */
+ER
+wdt_deinit(WDT_Handle_t *hwdt)
+{
+	const WDT_PortControlBlock *pcb;
+
+	if(hwdt == NULL)
+		return E_PAR;
+	pcb = &wdt_table[hwdt->wdtno];
+    wdt_disable(hwdt);
+	sil_andw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_PERI), pcb->peri_en);
+	hwdt->base = 0;
+	return E_OK;
+}
+
+/*
+ *  WDOGタイマー開始
+ *  parameter1  hwdt: WDOGハンドラ
+ *  parameter2  mode: タイムアウトモード
+ *  parameter3  tmout: タイムアウト時間(ms)
+ *  return ERコード
+ */
+ER_UINT
+wdt_start(WDT_Handle_t *hwdt, uint32_t mode, uint32_t timeout_ms)
+{
+	uint8_t  m_top;
+    uint64_t clk;
+	uint32_t torr;
+
+	if(hwdt == NULL)
+		return E_PAR;
+	clk = ((uint64_t)timeout_ms * hwdt->pclk / 1000) >> 16;
+	for(m_top = 0, clk >>=1 ; m_top < 16 && clk > 0  ; m_top++){
+		clk >>= 1;
+	}
+	if(m_top > 0xf)
+        m_top = 0xf;
+
+	sil_modw_mem((uint32_t *)(hwdt->base+TOFF_WDT_CR), WDT_CR_RMOD_MASK, mode);
+
+	/*
+	 *  WDTタイムアウト設定
+	 */
+	torr = (m_top << 4) | m_top;
+	sil_wrw_mem((uint32_t *)(hwdt->base+TOFF_WDT_TORR), torr);
+
+	/*
+	 *  WDT有効化
+	 */
+	sil_wrw_mem((uint32_t *)(hwdt->base+TOFF_WDT_CRR), WDT_CRR_MASK);
+	sil_orw_mem((uint32_t *)(hwdt->base+TOFF_WDT_CR), WDT_CR_ENABLE);
+    return (1UL << (m_top + 16 + 1)) * 1000UL / hwdt->pclk;
+}
+
+/*
+ *  WDOGタイマー停止
+ *  parameter1  hwdt: WDOGハンドラ
+ *  return ERコード
+ */
+ER
+wdt_stop(WDT_Handle_t *hwdt)
+{
+	if(hwdt == NULL)
+		return E_PAR;
+    wdt_disable(hwdt);
+	return E_OK;
+}
+
+/*
+ *  WDOG割込サービスコール
+ */
+void
+wdog_isr(intptr_t exinf)
+{
+	WDT_Handle_t *hwdt = &WdtHandle[INDEX_WDOG(exinf)];
+	uint32_t eoi;
+
+	eoi = sil_rew_mem((uint32_t *)(hwdt->base+TOFF_WDT_EOI));
+	sil_wrw_mem((uint32_t *)(hwdt->base+TOFF_WDT_EOI), eoi);
+	if(hwdt->callback != NULL)
+		hwdt->callback(hwdt);
+}
+
+
+/*
+ *  RTCデバイス
+ */
+
+#define RTC_MASK_VALUE  (RTC_RCTL_TIMER_MASK   | RTC_RCTL_ALARAM_MASK |\
+                         RTC_RCTL_INT_CNT_MASK | RTC_RCTL_INT_REG_MASK)
+
+static const int days[2][13] = {
+        {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
+        {0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}};
+
+
+uint8_t rtc_timer_mode;
+static void (*tick_func)(int);
+static void (*alarm_func)(int);
+
+Inline bool_t
+rtc_in_range(int value, int min, int max)
+{
+    return ((value >= min) && (value <= max));
+}
+
+static int
+rtc_get_wday(int year, int month, int day)
+{
+    /* Magic method to get weekday */
+    int weekday = (day += month < 3 ? year-- : year - 2, 23 * month / 9 + day + 4 + year / 4 - year / 100 + year / 400) % 7;
+    return weekday;
+}
+
+static int
+rtc_year_is_leap(int year)
+{
+    return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
+}
+
+static int
+rtc_get_yday(int year, int month, int day)
+{
+    int leap = rtc_year_is_leap(year);
+
+    return days[leap][month] + day;
+}
+
+/*
+ *  RTCプロテクション設定
+ */
+static void
+rtc_protect_set(int enable)
+{
+	if(enable){
+		sil_andw_mem((uint32_t *)(TADR_RTC_BASE+TOFF_REGISTER_CTRL), RTC_MASK_VALUE);
+	}
+	else{
+		sil_orw_mem((uint32_t *)(TADR_RTC_BASE+TOFF_REGISTER_CTRL), RTC_MASK_VALUE);
+	}
+}
+
+ER
+rtc_timer_set_mode(uint8_t timer_mode)
+{
+	uint32_t regctl = sil_rew_mem((uint32_t *)(TADR_RTC_BASE+TOFF_REGISTER_CTRL));
+    unsigned long freq = (unsigned long)SYS_CLOCK / 26000000;
+    unsigned long start_cycle;
+
+	switch(timer_mode){
+	case RTC_TIMER_RUNNING:
+		regctl |= RTC_RCTL_READ_ENABLE;
+		regctl &= ~RTC_RCTL_WRITE_ENABLE;
+		break;
+	case RTC_TIMER_SETTING:
+		regctl &= ~RTC_RCTL_READ_ENABLE;
+		regctl |= RTC_RCTL_WRITE_ENABLE;
+		break;
+	case RTC_TIMER_PAUSE:
+	default:
+		regctl &= ~(RTC_RCTL_READ_ENABLE | RTC_RCTL_WRITE_ENABLE);
+		break;
+    }
+
+    /* Wait for 1/26000000 s to sync data */
+	start_cycle = read_csr(mcycle);
+    while((read_csr(mcycle) - start_cycle) < freq){
+        continue;
+	}
+
+	sil_wrw_mem((uint32_t *)(TADR_RTC_BASE+TOFF_REGISTER_CTRL), regctl);
+	rtc_timer_mode = timer_mode;
+    return E_OK;
+}
+
+/*
+ *  RTC初期化関数
+ */
+void rtc_init(intptr_t exinf)
+{
+    /* Reset RTC */
+	sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_PERI_RESET), SYSCTL_PERI_RESET_RTC_RESET);
+    sil_dly_nse(10*1000);
+	sil_andw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_PERI_RESET), SYSCTL_PERI_RESET_RTC_RESET);
+
+    /* Enable RTC */
+	sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_CENT), SYSCTL_CLK_EN_CENT_APB1_CLK_EN);
+	sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_PERI), SYSCTL_CLK_EN_PERI_RTC_CLK_EN);
+
+    /* Unprotect RTC */
+    rtc_protect_set(0);
+    rtc_timer_set_mode(RTC_TIMER_SETTING);
+    /* Set RTC clock frequency */
+	sil_wrw_mem((uint32_t *)(TADR_RTC_BASE+TOFF_INITIAL_COUNT), SYSCTRL_CLOCK_FREQ_IN0);
+
+	sil_wrw_mem((uint32_t *)(TADR_RTC_BASE+TOFF_COURRNT_COUNT), 1);
+    /* Set RTC mode to timer running mode */
+    rtc_timer_set_mode(RTC_TIMER_RUNNING);
+
+	tick_func = NULL;
+	alarm_func = NULL;
+}
+
+/*
+ *  RTCの時刻設定関数
+ *
+ *  時刻の設定はPONIXのtm構造体を使用する
+ *  PONIXのインクルードがない場合を考慮し、同一項目のtm2をドライバとして定義する。
+ */
+ER
+rtc_set_time(struct tm2 *pt)
+{
+	uint32_t tm_wday = rtc_get_wday(pt->tm_year + 1900, pt->tm_mon, pt->tm_mday);
+	uint32_t extend  = sil_rew_mem((uint32_t *)(TADR_RTC_BASE+TOFF_RTC_EXTENDED));
+	int human_year = pt->tm_year + 1900;
+	int rtc_year = human_year % 100;
+	int rtc_century = human_year / 100;
+
+	if(!rtc_in_range(pt->tm_sec, 0, 59))
+		return E_PAR;
+	if(!rtc_in_range(pt->tm_min, 0, 59))
+		return E_PAR;
+	if(!rtc_in_range(pt->tm_hour, 0, 23))
+		return E_PAR;
+	if(!rtc_in_range(pt->tm_mday, 1, 31))
+		return E_PAR;
+	if(!rtc_in_range(pt->tm_mon, 1, 12))
+		return E_PAR;
+	if(!rtc_in_range(rtc_year, 0, 99) || !rtc_in_range(rtc_century, 0, 31))
+		return E_PAR;
+
+	/*
+	 *  RTC日時をセットアップ
+	 */
+	rtc_timer_set_mode(RTC_TIMER_SETTING);
+	sil_wrw_mem((uint32_t *)(TADR_RTC_BASE+TOFF_RTC_DATE),
+		tm_wday | (pt->tm_mday << 8) | (pt->tm_mon << 16) | (rtc_year << 20));
+	sil_wrw_mem((uint32_t *)(TADR_RTC_BASE+TOFF_RTC_TIME),
+		(pt->tm_sec << 10) | (pt->tm_min << 16) | (pt->tm_hour << 24));
+	extend &= ~RTC_EXTENDED_CENTURY;
+	extend |= rtc_century;
+	sil_wrw_mem((uint32_t *)(TADR_RTC_BASE+TOFF_RTC_EXTENDED), extend);
+	rtc_timer_set_mode(RTC_TIMER_RUNNING);
+	return E_OK;
+}
+
+/*
+ *  RTCの時刻取り出し関数
+ *
+ *  時刻の設定はPONIXのtm構造体を使用する
+ *  PONIXのインクルードがない場合を考慮し、同一項目のtm2をドライバとして定義する。
+ */
+ER rtc_get_time(struct tm2 *pt)
+{
+	uint32_t date = sil_rew_mem((uint32_t *)(TADR_RTC_BASE+TOFF_RTC_DATE));
+	uint32_t time = sil_rew_mem((uint32_t *)(TADR_RTC_BASE+TOFF_RTC_TIME));
+	uint32_t century = sil_rew_mem((uint32_t *)(TADR_RTC_BASE+TOFF_RTC_EXTENDED)) & RTC_EXTENDED_CENTURY;
+
+    if(rtc_timer_mode != RTC_TIMER_RUNNING)
+        return E_OBJ;
+
+    pt->tm_sec = (time & RTC_TIME_SECOND) >> 10;	/* 0-60, follow C99 */
+    pt->tm_min = (time & RTC_TIME_MINUTE) >> 16;	/* 0-59 */
+    pt->tm_hour = (time & RTC_TIME_HOUR) >> 24;	/* 0-23 */
+    pt->tm_mday = (date & RTC_DATE_DAY) >> 8;		/* 1-31 */
+    pt->tm_mon  = (date & RTC_DATE_MONTH) >> 16;	/* 1-12 */
+    pt->tm_year = (((date & RTC_DATE_YEAR) >> 20) % 100) + (century * 100) - 1900;
+    pt->tm_wday = date & RTC_DATE_WEEK;                                                 /* 0-6 */
+    pt->tm_yday = rtc_get_yday(pt->tm_year + 1900, pt->tm_mon + 1, pt->tm_mday) % 366; /* 0-365 */
+    pt->tm_isdst = 0;
+	return E_OK;
+}
+
+/*
+ *  RTC TICK割込み設定
+ */
+ER_UINT
+rtc_intmode(int8_t mode, void *func)
+{
+	uint32_t intctl = sil_rew_mem((uint32_t *)(TADR_RTC_BASE+TOFF_INTERRUPT_CTRL));
+	uint_t cmode;
+	if(mode >= 0){
+	    rtc_timer_set_mode(RTC_TIMER_SETTING);
+		if(func == NULL){
+			if(alarm_func == NULL)
+				intctl &= ~RTC_INT_TICK_ENABLE;
+			tick_func = NULL;
+		}
+		else{
+			intctl &= ~RTC_INT_TICK_INT_MODE;
+			intctl |= ((mode & 3) << 2) | RTC_INT_TICK_ENABLE;
+			tick_func = (void (*)(int))func;
+		}
+		sil_wrw_mem((uint32_t *)(TADR_RTC_BASE+TOFF_INTERRUPT_CTRL), intctl);
+	    rtc_timer_set_mode(RTC_TIMER_RUNNING);
+	}
+	cmode  = ((intctl & RTC_INT_TICK_ENABLE) ^ 1) << 2;
+	cmode |= (intctl & RTC_INT_TICK_INT_MODE) >> 2;
+	return cmode;
+}
+
+/*
+ *  RTCアラーム設定
+ *  parameter1 : parm: Pointer to Alarm structure
+ *  parameter2 : ptm: Pointer to struct tm2
+ *  return ERコード
+ */
+ER
+rtc_setalarm(RTC_Alarm_t *parm, struct tm2 *ptm)
+{
+	uint32_t intctl = sil_rew_mem((uint32_t *)(TADR_RTC_BASE+TOFF_INTERRUPT_CTRL));
+	int human_year = ptm->tm_year + 1900;
+	int rtc_year = human_year % 100;
+	int rtc_century = human_year / 100;
+	uint32_t alarmmask;
+
+	if(parm == NULL || ptm == NULL)
+		return E_PAR;
+	alarmmask = parm->alarmmask & RTC_INT_ARARM_C_MASK;
+	if(alarmmask != 0 && parm->callback == NULL)
+		return E_PAR;
+
+	if(!rtc_in_range(ptm->tm_sec, 0, 59)){
+		if((alarmmask & RTC_ALARM_SECOND) != 0)
+			return E_PAR;
+		ptm->tm_sec = 0;
+	}
+	if(!rtc_in_range(ptm->tm_min, 0, 59)){
+		if((alarmmask & RTC_ALARM_MINUTE) != 0)
+			return E_PAR;
+		ptm->tm_min = 0;
+	}
+	if(!rtc_in_range(ptm->tm_hour, 0, 23)){
+		if((alarmmask & RTC_ALARM_HOUR) != 0)
+			return E_PAR;
+		ptm->tm_hour = 0;
+	}
+	if(!rtc_in_range(ptm->tm_mday, 1, 31)){
+		if((alarmmask & RTC_ALARM_DAY) != 0)
+			return E_PAR;
+		ptm->tm_mday = 1;
+	}
+	if(rtc_in_range(ptm->tm_wday, 0, 6)){
+		if((alarmmask & RTC_ALARM_WEEK) != 0)
+			return E_PAR;
+		ptm->tm_wday = 0;
+	}
+	if(!rtc_in_range(ptm->tm_mon, 1, 12)){
+		if((alarmmask & RTC_ALARM_MONTH) != 0)
+			return E_PAR;
+		ptm->tm_mon = 1;
+	}
+	if(!rtc_in_range(rtc_year, 0, 99) || !rtc_in_range(rtc_century, 0, 31)){
+		if((alarmmask & RTC_ALARM_YEAR) != 0)
+			return E_PAR;
+		ptm->tm_year = 0;
+	}
+
+	/*
+	 *  RTC日時、割込みをセットアップ
+	 */
+	rtc_timer_set_mode(RTC_TIMER_SETTING);
+	sil_wrw_mem((uint32_t *)(TADR_RTC_BASE+TOFF_ALARM_DATE),
+		ptm->tm_wday | (ptm->tm_mday << 8) | (ptm->tm_mon << 16) | (rtc_year << 20));
+	sil_wrw_mem((uint32_t *)(TADR_RTC_BASE+TOFF_ALARM_TIME),
+		(ptm->tm_sec << 10) | (ptm->tm_min << 16) | (ptm->tm_hour << 24));
+
+	if(tick_func == NULL)
+		intctl &= ~RTC_INT_TICK_ENABLE;
+	intctl &= ~(RTC_INT_ALARM_ENABLE | RTC_INT_ARARM_C_MASK);
+	alarm_func = NULL;
+	if(alarmmask != 0){
+		intctl |= alarmmask | RTC_INT_TICK_ENABLE | RTC_INT_ALARM_ENABLE;
+		alarm_func = (void (*)(int))parm->callback;
+	}
+	sil_wrw_mem((uint32_t *)(TADR_RTC_BASE+TOFF_INTERRUPT_CTRL), intctl);
+	rtc_timer_set_mode(RTC_TIMER_RUNNING);
+	return E_OK;
+}
+
+/*
+ *  RTC割込みハンドラ
+ */
+void
+rtc_int_handler(void)
+{
+	uint32_t intctl = sil_rew_mem((uint32_t *)(TADR_RTC_BASE+TOFF_INTERRUPT_CTRL));
+	uint32_t cdate  = sil_rew_mem((uint32_t *)(TADR_RTC_BASE+TOFF_RTC_DATE));
+	uint32_t ctime  = sil_rew_mem((uint32_t *)(TADR_RTC_BASE+TOFF_RTC_TIME));
+
+	if((intctl & RTC_INT_TICK_ENABLE) != 0 && tick_func != NULL){
+		int    mode = (intctl & RTC_INT_TICK_INT_MODE) >> 2;
+		bool_t tickact = true;
+		switch(mode){
+		case RTC_INT_MINUTE:
+			if((ctime & RTC_TIME_SECOND) != 0)
+				tickact = false;
+			break;
+		case RTC_INT_HOUR:
+			if((ctime & (RTC_TIME_SECOND | RTC_TIME_MINUTE)) != 0)
+				tickact = false;
+			break;
+		default:
+			break;
+		}
+		if(tickact)
+			tick_func(mode);
+	}
+
+	if((intctl & RTC_INT_ALARM_ENABLE) != 0 && alarm_func != NULL){
+		uint32_t adate = sil_rew_mem((uint32_t *)(TADR_RTC_BASE+TOFF_ALARM_DATE));
+		uint32_t atime = sil_rew_mem((uint32_t *)(TADR_RTC_BASE+TOFF_ALARM_TIME));
+		uint32_t tdate = cdate;
+		uint32_t ttime = ctime;
+
+		if((intctl & RTC_ALARM_YEAR) == 0){
+			tdate &= ~RTC_DATE_YEAR;
+			adate &= ~RTC_ALARM_DATE_YEAR;
+		}
+		if((intctl & RTC_ALARM_MONTH) == 0){
+			tdate &= ~RTC_DATE_MONTH;
+			adate &= ~RTC_ALARM_DATE_MONTH;
+		}
+		if((intctl & RTC_ALARM_DAY) == 0){
+			tdate &= ~RTC_DATE_DAY;
+			adate &= ~RTC_ALARM_DATE_DAY;
+		}
+		if((intctl & RTC_ALARM_WEEK) == 0){
+			tdate &= ~RTC_DATE_WEEK;
+			adate &= ~RTC_ALARM_DATE_WEEK;
+		}
+		if((intctl & RTC_ALARM_HOUR) == 0){
+			ttime &= ~RTC_TIME_HOUR;
+			atime &= ~RTC_ALARM_TIME_HOUR;
+		}
+		if((intctl & RTC_ALARM_MINUTE) == 0){
+			ttime &= ~RTC_TIME_MINUTE;
+			atime &= ~RTC_ALARM_TIME_MINUTE;
+		}
+		if((intctl & RTC_ALARM_SECOND) == 0){
+			ttime &= ~RTC_TIME_SECOND;
+			atime &= ~RTC_ALARM_TIME_SECOND;
+		}
+		if(tdate == adate && ttime == atime)
+			alarm_func(intctl);
+    }
+}
+
+
+/*
+ *  デバイス初期化
+ */
+void
+device_init(intptr_t exinf)
+{
+	unsigned long sbase = TADR_SYSCTL_BASE;
+	uint32_t i;
+
+	/*
+	 *  GPIOクロック設定
+	 */
+	sil_orw_mem((uint32_t *)(sbase+TOFF_SYSCTL_CLK_EN_CENT), SYSCTL_CLK_EN_CENT_APB0_CLK_EN);
+	sil_orw_mem((uint32_t *)(sbase+TOFF_SYSCTL_CLK_EN_PERI), SYSCTL_CLK_EN_PERI_GPIO_CLK_EN);
+
+	/*
+	 *  Arduino用GPIOテーブル初期化
+	 */
+	for(i = 0 ; i < ARDUINO_GPIO_PORT ; i++){
+		arduino_gpio_table[i] = -1;
+	}
+
+	/*
+	 *  DMAC初期化
+	 */
+	dmac_init();
+}
+
+/*
+ *  SPI0-DVPモード設定
+ *  parameter1  en: 有効(1)、無効(0)
+ *  return ERコード
+ */
+ER
+select_spi0_dvp_mode(uint8_t en)
+{
+	if(en == 0){
+		sil_andw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_MISC), SYSCTL_MISC_SPI_DVP_DATA_ENABLE);
+		return E_OK;
+	}
+	else if(en == 1){
+		sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_MISC), SYSCTL_MISC_SPI_DVP_DATA_ENABLE);
+		return E_OK;
+	}
+	else
+	    return E_PAR;
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/device.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/device.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/device.cfg	(revision 453)
@@ -0,0 +1,20 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *  K210 Deviceのシステムコンフィギュレーションファイル
+ */
+
+#include "device.h"
+
+ATT_INI({ TA_NULL, 0, device_init });
+
+ATT_ISR({TA_NULL, WDOG1_PORTID, INTNO_WDOG1, wdog_isr, 1 });
+CFG_INT(INTNO_WDOG1, { TA_ENAINT | INTATR_WDOG, INTPRI_WDOG });
+ATT_ISR({TA_NULL, WDOG2_PORTID, INTNO_WDOG2, wdog_isr, 1 });
+CFG_INT(INTNO_WDOG2, { TA_ENAINT | INTATR_WDOG, INTPRI_WDOG });
+
+DEF_INH(INHNO_RTC, { TA_NULL, rtc_int_handler });
+CFG_INT(INTNO_RTC, { TA_ENAINT | INTATR_RTC, INTPRI_RTC });
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/device.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/device.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/device.h	(revision 453)
@@ -0,0 +1,532 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ * K210用デバイスドライバの外部宣言
+ */
+
+#ifndef _DEVICE_H_
+#define _DEVICE_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*
+ *  TOPPERS BASE PLATFORM情報
+ */
+#define TOPPERS_BASE_PLATFORM_K210
+#define SPI_DRIVER_NOSTART
+
+/*
+ *  バージョン情報
+ */
+#define	TPLATFORM_PRVER 0x0012		/* プラットフォームのバージョン番号 */
+
+/*
+ * ピン設定
+ */
+
+#define PINPOSITION0    0
+#define PINPOSITION1    1
+#define PINPOSITION2    2
+#define PINPOSITION3    3
+#define PINPOSITION4    4
+#define PINPOSITION5    5
+#define PINPOSITION6    6
+#define PINPOSITION7    7
+#define PINPOSITION8    8
+#define PINPOSITION9    9
+#define PINPOSITION10   10
+#define PINPOSITION11   11
+#define PINPOSITION12   12
+#define PINPOSITION13	13
+#define PINPOSITION14	14
+#define PINPOSITION15	15
+#define PINPOSITION16	16
+#define PINPOSITION17	17
+#define PINPOSITION18	18
+#define PINPOSITION19	19
+#define PINPOSITION20	20
+#define PINPOSITION21	21
+#define PINPOSITION22	22
+#define PINPOSITION23	23
+#define PINPOSITION24	24
+#define PINPOSITION25	25
+#define PINPOSITION26	26
+#define PINPOSITION27	27
+#define PINPOSITION28	28
+#define PINPOSITION29	29
+#define PINPOSITION30	30
+#define PINPOSITION31	31
+
+#define GPIO_PIN_0      (1<<PINPOSITION0)
+#define GPIO_PIN_1      (1<<PINPOSITION1)
+#define GPIO_PIN_2      (1<<PINPOSITION2)
+#define GPIO_PIN_3      (1<<PINPOSITION3)
+#define GPIO_PIN_4      (1<<PINPOSITION4)
+#define GPIO_PIN_5      (1<<PINPOSITION5)
+#define GPIO_PIN_6      (1<<PINPOSITION6)
+#define GPIO_PIN_7      (1<<PINPOSITION7)
+#define GPIO_PIN_8      (1<<PINPOSITION8)
+#define GPIO_PIN_9      (1<<PINPOSITION9)
+#define GPIO_PIN_10     (1<<PINPOSITION10)
+#define GPIO_PIN_11     (1<<PINPOSITION11)
+#define GPIO_PIN_12     (1<<PINPOSITION12)
+#define GPIO_PIN_13     (1<<PINPOSITION13)
+#define GPIO_PIN_14     (1<<PINPOSITION14)
+#define GPIO_PIN_15     (1<<PINPOSITION15)
+#define GPIO_PIN_16     (1<<PINPOSITION16)
+#define GPIO_PIN_17     (1<<PINPOSITION17)
+#define GPIO_PIN_18     (1<<PINPOSITION18)
+#define GPIO_PIN_19     (1<<PINPOSITION19)
+#define GPIO_PIN_20     (1<<PINPOSITION20)
+#define GPIO_PIN_21     (1<<PINPOSITION21)
+#define GPIO_PIN_22     (1<<PINPOSITION22)
+#define GPIO_PIN_23     (1<<PINPOSITION23)
+#define GPIO_PIN_24     (1<<PINPOSITION24)
+#define GPIO_PIN_25     (1<<PINPOSITION25)
+#define GPIO_PIN_26     (1<<PINPOSITION26)
+#define GPIO_PIN_27     (1<<PINPOSITION27)
+#define GPIO_PIN_28     (1<<PINPOSITION28)
+#define GPIO_PIN_29     (1<<PINPOSITION29)
+#define GPIO_PIN_30     (1<<PINPOSITION30)
+#define GPIO_PIN_31     (1<<PINPOSITION31)
+
+#define ARDUINO_GPIO_PORT   48
+
+/*
+ *  GPIOモードパラメータ
+ */
+#define GPIO_MODE_INPUT     0x00000000	/* Input Floating Mode */
+#define GPIO_MODE_OUTPUT    0x00000001	/* Output Mode */
+
+/*
+ *  GPIO-割込みモードパラメータ
+ */
+#define GPIO_MODE_IT_RISING             0x00110000	/* Interrupt Mode with Rising edge trigger detection */
+#define GPIO_MODE_IT_FALLING            0x00210000	/* Interrupt Mode with Falling edge trigger detection */
+#define GPIO_MODE_IT_HIGH               0x00410000	/* Interrupt Mode High Level */
+#define GPIO_MODE_IT_LOW                0x00810000	/* Interrupt Mode Low Level */
+
+/*
+ *  GPIOプルアップダウンパラメータ
+ */
+#define GPIO_NOPULL         0x00000000	/* No Pull-up or Pull-down activation  */
+#define GPIO_PULLUP         0x00000001	/* Pull-up activation                  */
+#define GPIO_PULLDOWN       0x00000002	/* Pull-down activation                */
+#define GPIO_PULLMAX        (GPIO_PULLDOWN+1)
+
+/*
+ *  GPIO初期化設定
+ */
+typedef struct
+{
+    uint32_t    mode;		/* specifies the operating mode for the selected pins. */
+	uint32_t    pull;		/* specifies the Pull-up or Pull-Down */
+}GPIO_Init_t;
+
+extern void gpio_setup(unsigned long base, GPIO_Init_t *init, uint32_t pin);
+extern void gpio_set_pin(unsigned long base, uint8_t pin, uint8_t value);
+extern uint8_t gpio_get_pin(unsigned long base, uint8_t pin);
+extern int  gpio_get_gpiohno(uint8_t fpio_pin, bool_t intreq);
+
+
+/*
+ *  DMAチャンネル定義
+ */
+#define DMA_CHANNEL0         0
+#define DMA_CHANNEL1         1
+#define DMA_CHANNEL2         2
+#define DMA_CHANNEL3         3
+#define DMA_CHANNEL4         4
+#define DMA_CHANNEL5         5
+#define NUM_DMA_CHANNEL      (NUM_DMAC_CHANNEL)
+
+/*
+ *  DMA選択定義
+ */
+#define DMA_SELECT_SSI0_RX_REQ  0
+#define DMA_SELECT_SSI0_TX_REQ  1
+#define DMA_SELECT_SSI1_RX_REQ  2
+#define DMA_SELECT_SSI1_TX_REQ  3
+#define DMA_SELECT_SSI2_RX_REQ  4
+#define DMA_SELECT_SSI2_TX_REQ  5
+#define DMA_SELECT_SSI3_RX_REQ  6
+#define DMA_SELECT_SSI3_TX_REQ  7
+#define DMA_SELECT_I2C0_RX_REQ  8
+#define DMA_SELECT_I2C0_TX_REQ  9
+#define DMA_SELECT_I2C1_RX_REQ  10
+#define DMA_SELECT_I2C1_TX_REQ  11
+#define DMA_SELECT_I2C2_RX_REQ  12
+#define DMA_SELECT_I2C2_TX_REQ  13
+#define DMA_SELECT_UART1_RX_REQ 14
+#define DMA_SELECT_UART1_TX_REQ 15
+#define DMA_SELECT_UART2_RX_REQ 16
+#define DMA_SELECT_UART2_TX_REQ 17
+#define DMA_SELECT_UART3_RX_REQ 18
+#define DMA_SELECT_UART3_TX_REQ 19
+#define DMA_SELECT_AES_REQ      20
+#define DMA_SELECT_SHA_RX_REQ   21
+#define DMA_SELECT_AI_RX_REQ    22
+#define DMA_SELECT_FFT_RX_REQ   23
+#define DMA_SELECT_FFT_TX_REQ   24
+#define DMA_SELECT_I2S0_TX_REQ  25
+#define DMA_SELECT_I2S0_RX_REQ  26
+#define DMA_SELECT_I2S1_TX_REQ  27
+#define DMA_SELECT_I2S1_RX_REQ  28
+#define DMA_SELECT_I2S2_TX_REQ  29
+#define DMA_SELECT_I2S2_RX_REQ  30
+#define DMA_SELECT_I2S0_BF_DIR_REQ    31
+#define DMA_SELECT_I2S0_BF_VOICE_REQ  32
+#define NUM_DMA_SELECT          33
+
+/*
+ *  DMAステータス定義
+ */
+#define DMA_STATUS_BUSY         0x0001		/* BUSY */
+#define DMA_STATUS_READY_HMEM0  0x0002		/* DMA Mem0 Half process success */
+#define DMA_STATUS_READY_HMEM1  0x0004		/* DMA Mem1 Half process success */
+#define DMA_STATUS_READY_MEM0   0x0008		/* DMA Mem0 process success      */
+#define DMA_STATUS_READY_ERROR  0x0100		/* DMA Error end */
+
+/*
+ *  DMA転送方向定義
+ */
+#define DMA_MEMORY_TO_MEMORY    0x0000		/* Memory to memory direction(DMAC)     */
+#define DMA_MEMORY_TO_PERIPH    0x0001		/* Memory to peripheral direction(DMAC) */
+#define DMA_PERIPH_TO_MEMORY    0x0002		/* Peripheral to memory direction(DMAC) */
+#define DMA_PERIPH_TO_PERIPH    0x0003		/* Peripheral to peripheral direction(DMAC) */
+#define PRF_PERIPH_TO_MEMORY1   0x0004		/* Peripheral to memory direction(PRF-SRC) */
+#define PRF_PERIPH_TO_PERIPH    0x0005		/* Peripheral to peripheral direction(PRF) */
+#define PRF_MEMORY_TO_PERIPH    0x0006		/* Memory to peripheral direction(PRF) */
+#define PRF_PERIPH_TO_MEMORY2   0x0007		/* Peripheral to memory direction(PRF-DST) */
+
+/*
+ *  DMAマルチブロックタイプ
+ */
+#define DMAC_MULTBLOCK_CONT     0x0000		/* Continuous multiblock type */
+#define DMAC_MULTBLOCK_RELOAD   0x0001		/* Reload multiblock type */
+#define DMAC_MULTBLOCK_SHADOW   0x0002		/* Shadow register based multiblock type */
+#define DMAC_MULTBLOCK_LINKED   0x0003		/* Linked lisr bases multiblock type */
+
+/*
+ *  DMAソフトウェア-ハードウェアハンドシェイク
+ */
+#define DMAC_HS_HARDWARE        0x0000		/* Hardware handshaking */
+#define DMAC_HS_SOFTWARE        0x0001		/* Software handshaking */
+
+/*
+ *  DMAハードウェアハンドシェイク極性
+ */
+#define DMAC_HWHS_POLARITY_LOW  0x0000		/* polarity low */
+#define DMAC_HWHS_POLARITY_HIGH 0x00001		/* polarity high */
+
+/*
+ *  DMA優先度定義
+ */
+#define DMAC_PRIORITY_0         0x0000
+#define DMAC_PRIORITY_1         0x0001
+#define DMAC_PRIORITY_2         0x0002
+#define DMAC_PRIORITY_3         0x0003
+#define DMAC_PRIORITY_4         0x0004
+#define DMAC_PRIORITY_5         0x0005
+#define DMAC_PRIORITY_6         0x0006
+#define DMAC_PRIORITY_7         0x0007
+
+
+/*
+ *  DMAマスター定義
+ */
+#define DMAC_MASTER1            0x0000		/* Master #1 */
+#define DMAC_MASTER2            0x0001		/* Master #2 */
+
+/*
+ *  DMAインクリメントモード
+ */
+#define DMAC_ADDR_INCREMENT     0x0000		/* インクリメント */
+#define DMAC_ADDR_NOCHANGE      0x0001		/* 未変更 */
+
+/*
+ *  DMA転送幅定義
+ */
+#define DMAC_TRANS_WIDTH_8      0x0000		/* 8ビット */
+#define DMAC_TRANS_WIDTH_16     0x0001		/* 16ビット */
+#define DMAC_TRANS_WIDTH_32     0x0002		/* 32ビット */
+#define DMAC_TRANS_WIDTH_64     0x0003		/* 64ビット */
+#define DMAC_TRANS_WIDTH_128    0x0004		/* 128ビット */
+#define DMAC_TRANS_WIDTH_256    0x0005		/* 256ビット */
+
+/*
+ *  DMAブースト転送サイズ定義
+ */
+#define DMAC_MSIZE_1            0x0000		/* 1バイト */
+#define DMAC_MSIZE_4            0x0001		/* 4バイト */
+#define DMAC_MSIZE_8            0x0002		/* 8バイト */
+#define DMAC_MSIZE_16           0x0003		/* 16バイト */
+#define DMAC_MSIZE_32           0x0004		/* 32バイト */
+#define DMAC_MSIZE_64           0x0005		/* 64バイト */
+#define DMAC_MSIZE_128          0x0006		/* 128バイト */
+#define DMAC_MSIZE_256          0x0007		/* 256バイト */
+
+#define DMA_TRS_TIMEOUT         2000	/* 2秒 */
+
+/*
+ *  DMA初期化構造体定義
+ */
+typedef struct
+{
+	uint16_t              Request;		/* DMA選択 */
+	uint16_t              Direction;	/* DMA転送方向 */
+	uint16_t              SrcMultBlock;	/* ソースマルチブロックタイプ */
+	uint16_t              DrcMultBlock;	/* デスティネーションマルチブロックタイプ */
+	uint16_t              SrcHandShake;	/* ソースハンドシェイク */
+	uint16_t              DrcHandShake;	/* デスティネーションハンドシェイク */
+	uint16_t              SrcHwhsPol;	/* ソースハードウェアハンドシェイク極性 */
+	uint16_t              DrcHwhsPol;	/* デスティネーションハードウェアハンドシェイク極性 */
+	uint16_t              Priority;		/* 優先度 */
+	uint16_t              SrcMaster;	/* ソースマスター設定 */
+	uint16_t              DstMaster;	/* デスティネーションマスター設定 */
+	uint16_t              SrcInc;		/* ソースインクリメント設定 */
+	uint16_t              DstInc;		/* デスティネーションインクリメント設定 */
+	uint16_t              SrcTransWidth;/* ソース転送幅 */
+	uint16_t              DstTransWidth;/* デスティネーション転送幅 */
+	uint16_t              SrcBurstSize;	/* ソースバーストサイズ */
+	uint16_t              DstBurstSize;	/* デスティネーションバーストサイズ */
+	uint16_t              IocBlkTrans;	/* IOCブロック転送 */
+}DMA_Init_t;
+
+/*
+ *  DMAハンドラ構造体定義
+ */
+typedef struct __DMA_Handle_t DMA_Handle_t;
+struct __DMA_Handle_t
+{
+	unsigned long         base;			/* DMA Port base address */
+	unsigned long         cbase;		/* DMA Channel Port address */
+	DMA_Init_t            Init;			/* DMA communication parameters */
+	uint16_t              chnum;		/* channel number */
+	volatile uint16_t     status;		/* DMA status */
+	volatile uint16_t     ErrorCode;	/* DMA Error code */
+	uint16_t              dummy;
+	void                  (*xfercallback)(DMA_Handle_t * hdma);		/* DMA transfer complete callback */
+	void                  (*errorcallback)(DMA_Handle_t * hdma);	/* DMA transfer error callback */
+	void                  *localdata;	/* DMA local data */
+};
+
+/*
+ *  DMAステータス定義
+ */
+#define DMA_STATUS_READY        0x0000	/* READY */
+#define DMA_STATUS_BUSY         0x0001	/* BUSY */
+#define DMA_STATUS_READY_TRN1   0x0008	/* DMA Mem process success      */
+#define DMA_STATUS_READY_TRN2   0x0010	/* DMA SRC process success      */
+#define DMA_STATUS_READY_TRN3   0x0020	/* DMA DST process success      */
+#define DMA_STATUS_READY_ERROR  0x0100	/* DMA Error end */
+
+/*
+ *  DMAエラー定義
+ */ 
+#define DMA_ERROR_NONE          0x0000	/* No error */
+#define DMA_ERROR_SRC_DODE      0x0020	/* Source Decode error */
+#define DMA_ERROR_DST_DECODE    0x0040	/* Destination Decode error */
+#define DMA_ERROR_SRC_SLV       0x0080	/* Source Slave Error Status Enable */
+#define DMA_ERROR_DST_SLV       0x0100	/* Destination Slave Error Status Enable */
+#define DMA_ERROR_LLI_RD_DEC    0x0200	/* LLI Read Decode Error Status */
+#define DMA_ERROR_LLI_WR_DEC    0x0400	/* LLI Write Decode Error Status */
+#define DMA_ERROR_LLI_RD_SLV    0x0800	/* LLI Read Slave Error Status Enable */
+#define DMA_ERROR_LLI_WR_SLV    0x1000	/* LLI Write Slave Error Status Enable */
+#define DMA_ERROR_TIMEOUT       0x0001	/* Timeout error */
+
+extern ER dma_init(DMA_Handle_t *hdma);
+extern ER dma_deinit(DMA_Handle_t *hdma);
+extern ER dma_reset(DMA_Handle_t *hdma);
+extern ER dma_start(DMA_Handle_t *hdma, uintptr_t SrcAddress, uintptr_t DstAddress, uint32_t DataLength);
+extern ER dma_end(DMA_Handle_t *hdma);
+extern void channel_dmac_isr(intptr_t exinf);
+extern ER select_dma_channel(uint8_t channel, uint8_t select);
+
+
+/*
+ *  WDOGドライバ
+ */
+#define WDOG1_PORTID        1
+#define WDOG2_PORTID        2
+#define NUM_WDOGPORT        2
+
+/*
+ *  WDOGモード定義
+ */
+#define WDT_MODE_REST       WDT_CR_RMOD_RESET
+#define WDT_MODE_INTERRUPT  WDT_CR_RMOD_INTERRUPT
+
+/*
+ *  WDOGハンドラ定義
+ */
+typedef struct __WDT_Handle_t WDT_Handle_t;
+struct __WDT_Handle_t
+{
+	unsigned long       base;
+	uint32_t            wdtno;
+	uint32_t            pclk;
+	void                (*callback)(WDT_Handle_t *hwdt);
+};
+
+#define INHNO_WDOG1   IRQ_VECTOR_WDT0	/* 割込みハンドラ番号 */
+#define INTNO_WDOG1   IRQ_VECTOR_WDT0	/* 割込み番号 */
+#define INHNO_WDOG2   IRQ_VECTOR_WDT1	/* 割込みハンドラ番号 */
+#define INTNO_WDOG2   IRQ_VECTOR_WDT1	/* 割込み番号 */
+#define INTPRI_WDOG   -1		/* 割込み優先度 */
+#define INTATR_WDOG   0			/* 割込み属性 */
+
+extern WDT_Handle_t *wdt_init(ID port);
+extern ER wdt_deinit(WDT_Handle_t *hwdt);
+extern ER_UINT wdt_start(WDT_Handle_t *hwdt, uint32_t mode, uint32_t timeout_ms);
+extern ER wdt_stop(WDT_Handle_t *hwdt);
+extern void wdog_isr(intptr_t exinf);
+
+
+/*
+ *  RTCドライバ
+ */
+
+/*
+ *  RTCモード定義
+ */
+#define RTC_TIMER_PAUSE         0	/* Timer pause */
+#define RTC_TIMER_RUNNING       1	/* Timer time running */
+#define RTC_TIMER_SETTING       2	/* Timer time setting */
+#define RTC_TIMER_MAX           3	/* Max count of this enum*/
+
+/*
+ *  RTC TICK割込みモード
+ */
+#define RTC_INT_SECOND          0	/* 秒単位 */
+#define RTC_INT_MINUTE          1	/* 分単位 */
+#define RTC_INT_HOUR            2	/* 時間単位 */
+#define RTC_INT_DAY             3	/* 日単位 */
+
+/*
+ *  RTC ALARMマスク
+ */
+#define RTC_ALARM_SECOND        0x02000000	/* 秒マスク */
+#define RTC_ALARM_MINUTE        0x04000000	/* 分マスク */
+#define RTC_ALARM_HOUR          0x08000000	/* 時マスク */
+#define RTC_ALARM_WEEK          0x10000000	/* 週マスク */
+#define RTC_ALARM_DAY           0x20000000	/* 日マスク */
+#define RTC_ALARM_MONTH         0x40000000	/* 月マスク */
+#define RTC_ALARM_YEAR          0x80000000	/* 年マスク */
+
+/*
+ *  RTC割込み設定
+ */
+#define INHNO_RTC     IRQ_VECTOR_RTC	/* 割込みハンドラ番号 */
+#define INTNO_RTC     IRQ_VECTOR_RTC	/* 割込み番号 */
+#define INTPRI_RTC    -7		/* 割込み優先度 */
+#define INTATR_RTC    0			/* 割込み属性 */
+
+/*
+ *  日時設定用の構造体を定義
+ */
+struct tm2 {
+  int	tm_sec;			/* 秒 */
+  int	tm_min;			/* 分 */
+  int	tm_hour;		/* 時 */
+  int	tm_mday;		/* 月中の日 */
+  int	tm_mon;			/* 月 */
+  int	tm_year;		/* 年 */
+  int	tm_wday;		/* 曜日 */
+  int	tm_yday;		/* 年中の日 */
+  int	tm_isdst;
+};
+
+/*
+ *  RTCアラーム構造体
+ */
+typedef struct
+{
+	uint32_t            alarmmask;			/* アラームマスク設定 */
+	void                (*callback)(int);	/* アラームコールバック */
+}RTC_Alarm_t;
+
+extern void rtc_init(intptr_t exinf);
+extern void rtc_info_init(intptr_t exinf);
+extern ER rtc_timer_set_mode(uint8_t timer_mode);
+extern ER rtc_set_time(struct tm2 *pt);
+extern ER rtc_get_time(struct tm2 *pt);
+extern ER_UINT rtc_intmode(int8_t mode, void *func);
+extern ER rtc_setalarm(RTC_Alarm_t *parm, struct tm2 *ptm);
+extern void rtc_int_handler(void);
+
+extern uint8_t rtc_timer_mode;
+
+/*
+ *  デバイス初期化
+ */
+extern void device_init(intptr_t exinf);
+
+/*
+ *  SPI0/DVPのモード設定
+ */
+extern ER select_spi0_dvp_mode(uint8_t en);
+
+
+/*
+ *  FPIOAにファンクションを設定する
+ *  param1  number      The IO number
+ *  param2  function    The function enum number
+ *  return  0-OK
+ */
+extern ER fpioa_set_function(int number, uint8_t function);
+
+
+/*
+ *  PLLクロック取得
+ */
+extern uint32_t get_pll_clock(uint8_t no);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/dvp.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/dvp.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/dvp.c	(revision 453)
@@ -0,0 +1,482 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ * 
+ *  K210 DVPドライバ関数群
+ *
+ */
+#include <stddef.h>
+#include <kernel.h>
+#include <sil.h>
+#include <t_syslog.h>
+#include <target_syssvc.h>
+#include <kernel_cfg.h>
+#include "device.h"
+#include "dvp.h"
+
+/*
+ *  SIL関数のマクロ定義
+ */
+#define sil_orw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) | (b))
+#define sil_andw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) & ~(b))
+#define sil_modw_mem(a, b, c)	sil_wrw_mem((a), (sil_rew_mem(a) & (~b)) | (c))
+
+#define DVP_CLOCK_REQ           0
+#define APB1_CLOCK_REQ          1
+
+#define RESET_DELAY_TIME        200
+
+#define DEAFULT_CLEAR_INT       (DVP_STS_FRAME_START  | DVP_STS_FRAME_START_WE | \
+                                 DVP_STS_FRAME_FINISH | DVP_STS_FRAME_FINISH_WE)
+
+
+static DVP_Handle_t *phdvp;
+
+static uint32_t
+dvp_clock_get_freq(uint8_t clock)
+{
+	uint32_t clk_sel0 = sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_CLK_SEL0));
+    uint32_t source = 0;
+    uint32_t result = 0;
+	uint32_t threshold = 0;
+
+	/*
+	 *  ACLKの取り出し
+	 */
+	if((clk_sel0 & SYSCTL_CLK_SEL0_ACLK_SEL) == 0)
+		source = SYSCTRL_CLOCK_FREQ_IN0;
+	else{
+		threshold = (clk_sel0 & SYSCTL_CLK_SEL0_ACLK_SDIVISER) >> 1;
+		source = get_pll_clock(0) / (2ULL << threshold);
+	}
+
+	if(clock == DVP_CLOCK_REQ){
+		threshold = sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_TH0)) & SYSCTL_CLK_TH0_DVP_GCLK_THHD;
+		threshold >>= 12;
+	}
+	else	/* APB1 request */
+		threshold = (clk_sel0 & SYSCTL_CLK_SEL0_APB1_CLK_SEL) >> 6;
+	result = source / (threshold + 1);
+	syslog_2(LOG_NOTICE, "## dvp_clock_get_freq req(%d) result(%d) ##", clock, result);
+    return result;
+}
+
+static void
+dvp_sccb_start_transfer(DVP_Handle_t *hdvp)
+{
+	while(sil_rew_mem((uint32_t *)(hdvp->base+TOFF_DVP_STS)) & DVP_STS_SCCB_EN)
+        ;
+	sil_wrw_mem((uint32_t *)(hdvp->base+TOFF_DVP_STS), (DVP_STS_SCCB_EN | DVP_STS_SCCB_EN_WE));
+    while (sil_rew_mem((uint32_t *)(hdvp->base+TOFF_DVP_STS)) & DVP_STS_SCCB_EN)
+        ;
+}
+
+
+/*
+ *  SCCBレジスタ書込み
+ *  parameter1  hdvp: DVPハンドラへのポインタ
+ *  parameter2  addr: デバイスアドレス
+ *  parameter3  reg_addr: レジスタアドレス
+ *  parameter4  reg_data: レジスタデータ
+ */
+void
+dvp_sccb_send_data(DVP_Handle_t *hdvp, uint8_t addr, uint16_t reg_addr, uint8_t reg_data)
+{
+	uint32_t tmp;
+
+	tmp = sil_rew_mem((uint32_t *)(hdvp->base+TOFF_DVP_SCCB_CFG)) & (~DVP_SCCB_BYTE_NUM_MASK);
+
+	(hdvp->Init.num_sccb_reg == 8) ? (tmp |= DVP_SCCB_BYTE_NUM_3) : (tmp |= DVP_SCCB_BYTE_NUM_4);
+
+	sil_wrw_mem((uint32_t *)(hdvp->base+TOFF_DVP_SCCB_CFG), tmp);
+
+	if (hdvp->Init.num_sccb_reg == 8)
+		tmp = DVP_SCCB_WRITE_DATA_ENABLE | addr | (reg_addr << 8) | (reg_data << 16);
+	else
+		tmp = DVP_SCCB_WRITE_DATA_ENABLE | addr | ((reg_addr >> 8) << 8) | ((reg_addr & 0xff) << 16) | (reg_data << 24);
+	sil_wrw_mem((uint32_t *)(hdvp->base+TOFF_DVP_SCCB_CTL), tmp);
+	dvp_sccb_start_transfer(hdvp);
+}
+
+/*
+ *  SCCBレジスタ読み込み
+ *  parameter1  hdvp: DVPハンドラへのポインタ
+ *  parameter2  addr: デバイスアドレス
+ *  parameter3  reg_addr: レジスタアドレス
+ *  return      読み込みデータ
+ */
+uint8_t dvp_sccb_receive_data(DVP_Handle_t *hdvp, uint8_t addr, uint16_t reg_addr)
+{
+	uint32_t tmp;
+
+	tmp = sil_rew_mem((uint32_t *)(hdvp->base+TOFF_DVP_SCCB_CFG)) & (~DVP_SCCB_BYTE_NUM_MASK);
+
+    if (hdvp->Init.num_sccb_reg == 8)
+		tmp |= DVP_SCCB_BYTE_NUM_2;
+	else
+		tmp |= DVP_SCCB_BYTE_NUM_3;
+
+	sil_wrw_mem((uint32_t *)(hdvp->base+TOFF_DVP_SCCB_CFG), tmp);
+
+	if(hdvp->Init.num_sccb_reg == 8)
+		tmp = DVP_SCCB_WRITE_DATA_ENABLE | addr | (reg_addr << 8);
+	else
+		tmp = DVP_SCCB_WRITE_DATA_ENABLE | addr | ((reg_addr >> 8) << 8) | ((reg_addr & 0xff) << 16);
+
+	sil_wrw_mem((uint32_t *)(hdvp->base+TOFF_DVP_SCCB_CTL), tmp);
+
+    dvp_sccb_start_transfer(hdvp);
+
+	sil_wrw_mem((uint32_t *)(hdvp->base+TOFF_DVP_SCCB_CTL), addr);
+
+    dvp_sccb_start_transfer(hdvp);
+
+	tmp = sil_rew_mem((uint32_t *)(hdvp->base+TOFF_DVP_SCCB_CFG));
+	return (uint8_t) (tmp >> 24);
+}
+
+/*
+ *  DVP初期設定
+ *  parameter1  hdvp: DVPハンドラへのポインタ
+ *  return      ERコード
+ */
+ER
+dvp_init(DVP_Handle_t *hdvp)
+{
+    uint32_t v_apb1_clk, v_period;
+
+	if(hdvp == NULL)
+		return E_PAR;
+
+	if(hdvp->Init.GMMlen > DVP_AXI_GM_MLEN_MASK || hdvp->Init.GMMlen == 0)
+		return E_PAR;
+
+	hdvp->base  = DVP_BASE_ADDR;
+	hdvp->semid = DVP_SEM;
+	fpioa_set_function(hdvp->Init.CMosPClkPin, FUNC_CMOS_PCLK);
+	fpioa_set_function(hdvp->Init.CMosXClkPin, FUNC_CMOS_XCLK);
+	fpioa_set_function(hdvp->Init.CMosHRefPin, FUNC_CMOS_HREF);
+	fpioa_set_function(hdvp->Init.CMosPwDnPin, FUNC_CMOS_PWDN);
+	fpioa_set_function(hdvp->Init.CMosVSyncPin, FUNC_CMOS_VSYNC);
+	fpioa_set_function(hdvp->Init.CMosRstPin, FUNC_CMOS_RST);
+	fpioa_set_function(hdvp->Init.SccbSClkPin, FUNC_SCCB_SCLK);
+	fpioa_set_function(hdvp->Init.SccbSdaPin, FUNC_SCCB_SDA);
+
+    /* Do a power cycle */
+    dvp_dcmi_powerdown(hdvp, false);
+    dly_tsk(10);
+
+    dvp_dcmi_powerdown(hdvp, true);
+    dly_tsk(100);
+
+	/*
+	 *  DVPクロック有効化
+	 */
+	sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_CENT), SYSCTL_CLK_EN_CENT_APB1_CLK_EN);
+	sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_PERI), SYSCTL_CLK_EN_PERI_DVP_CLK_EN);
+
+	phdvp = hdvp;
+
+	/*
+	 *  DVPリセット
+	 */
+	sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_PERI_RESET), SYSCTL_PERI_RESET_DVP_RESET);
+	dly_tsk(10);
+	sil_andw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_PERI_RESET), SYSCTL_PERI_RESET_DVP_RESET);
+	dly_tsk(1);
+
+	/*
+	 *  SCCBクロック初期化
+	 */
+	sil_orw_mem((uint32_t *)(hdvp->base+TOFF_DVP_SCCB_CFG), (DVP_SCCB_SCL_LCNT_MASK | DVP_SCCB_SCL_HCNT_MASK));
+
+	 // Initialize dvp interface
+	v_apb1_clk = dvp_clock_get_freq(APB1_CLOCK_REQ);
+	if(v_apb1_clk > (hdvp->Init.Freq * 2))
+		v_period = ((v_apb1_clk + hdvp->Init.Freq) / (hdvp->Init.Freq * 2)) - 1;
+	else
+		v_period = 0;
+	if(v_period > 255)
+		v_period = 255;
+
+	/*
+	 *  DVPリセット
+	 */
+	sil_andw_mem((uint32_t *)(hdvp->base+TOFF_DVP_CMOS_CFG), DVP_CMOS_CLK_DIV_MASK);
+	sil_orw_mem((uint32_t *)(hdvp->base+TOFF_DVP_CMOS_CFG), (DVP_CMOS_CLK_ENABLE | v_period));
+	/* First power down */
+	sil_orw_mem((uint32_t *)(hdvp->base+TOFF_DVP_CMOS_CFG), DVP_CMOS_POWER_DOWN);
+	sil_dly_nse(RESET_DELAY_TIME*1000);
+	sil_andw_mem((uint32_t *)(hdvp->base+TOFF_DVP_CMOS_CFG), DVP_CMOS_POWER_DOWN);
+	sil_dly_nse(RESET_DELAY_TIME*1000);
+
+	/* Second reset */
+	sil_andw_mem((uint32_t *)(hdvp->base+TOFF_DVP_CMOS_CFG), DVP_CMOS_RESET);
+	sil_dly_nse(RESET_DELAY_TIME*1000);
+	sil_orw_mem((uint32_t *)(hdvp->base+TOFF_DVP_CMOS_CFG), DVP_CMOS_RESET);
+	sil_dly_nse(RESET_DELAY_TIME*1000);
+
+	/*
+	 *  バーストモード設定
+	 */
+	sil_modw_mem((uint32_t *)(hdvp->base+TOFF_DVP_CFG), DVP_CFG_BURST_SIZE_4BEATS, hdvp->Init.BurstMode);
+	sil_modw_mem((uint32_t *)(hdvp->base+TOFF_DVP_AXI), DVP_AXI_GM_MLEN_MASK, hdvp->Init.GMMlen-1);
+
+	/*
+	 *  オートモード設定
+	 */
+	sil_modw_mem((uint32_t *)(hdvp->base+TOFF_DVP_CFG), DVP_CFG_AUTO_ENABLE, hdvp->Init.AutoMode);
+
+	/*
+	 *  出力有効化
+	 */
+	sil_orw_mem((uint32_t *)(hdvp->base+TOFF_DVP_CFG), DVP_CFG_AI_OUTPUT_ENABLE);
+	sil_orw_mem((uint32_t *)(hdvp->base+TOFF_DVP_CFG), DVP_CFG_DISPLAY_OUTPUT_ENABLE);
+
+	/*
+	 *  イメージフォーマット、サイズ設定
+	 */
+	dvp_set_image_format(hdvp);
+	dvp_set_image_size(hdvp);	//set QVGA default
+
+	sil_wrw_mem((uint32_t *)(hdvp->base+TOFF_DVP_R_ADDR), hdvp->Init.RedAddr);
+	sil_wrw_mem((uint32_t *)(hdvp->base+TOFF_DVP_G_ADDR), hdvp->Init.GreenAddr);
+	sil_wrw_mem((uint32_t *)(hdvp->base+TOFF_DVP_B_ADDR), hdvp->Init.BlueAddr);
+	sil_wrw_mem((uint32_t *)(hdvp->base+TOFF_DVP_RGB_ADDR), hdvp->Init.RGBAddr);
+
+	/*
+	 *  割込み設定
+	 */
+	sil_andw_mem((uint32_t *)(hdvp->base+TOFF_DVP_CFG), (DVP_CFG_START_INT_ENABLE | DVP_CFG_FINISH_INT_ENABLE));
+	dis_int(hdvp->Init.IntNo);
+	sil_orw_mem((uint32_t *)(hdvp->base+TOFF_DVP_STS), DEAFULT_CLEAR_INT);
+	sil_orw_mem((uint32_t *)(hdvp->base+TOFF_DVP_CFG), (DVP_CFG_START_INT_ENABLE | DVP_CFG_FINISH_INT_ENABLE));
+	hdvp->state = DVP_STATE_INIT;
+	return E_OK;
+}
+
+/*
+ *  DVP終了設定
+ *  parameter1  hspi: SPIハンドラへのポインタ
+ *  return ERコード
+ */
+ER
+dvp_deinit(DVP_Handle_t *hdvp)
+{
+	if(hdvp == NULL)
+		return E_PAR;
+
+	dis_int(hdvp->Init.IntNo);
+	sil_andw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_PERI), SYSCTL_CLK_EN_PERI_DVP_CLK_EN);
+
+	phdvp = NULL;
+	hdvp->state = DVP_STATE_INIT;
+	return E_OK;
+}
+
+/*
+ *  DVP有効化処理
+ *  parameter1  hspi: SPIハンドラへのポインタ
+ *  parameter2  run:  1:有効化、0:無効化
+ *  return ERコード
+ */
+ER
+dvp_activate(DVP_Handle_t *hdvp, bool_t run)
+{
+	if(hdvp == NULL)
+		return E_PAR;
+	if(run){
+		hdvp->state = DVP_STATE_READY;
+		sil_orw_mem((uint32_t *)(hdvp->base+TOFF_DVP_STS), DEAFULT_CLEAR_INT);
+		ena_int(hdvp->Init.IntNo);
+		sil_orw_mem((uint32_t *)(hdvp->base+TOFF_DVP_CFG), (DVP_CFG_START_INT_ENABLE | DVP_CFG_FINISH_INT_ENABLE));
+	}
+	else{
+		hdvp->state = DVP_STATE_INIT;
+		dis_int(hdvp->Init.IntNo);
+		sil_orw_mem((uint32_t *)(hdvp->base+TOFF_DVP_STS), DEAFULT_CLEAR_INT);
+		sil_andw_mem((uint32_t *)(hdvp->base+TOFF_DVP_CFG), (DVP_CFG_START_INT_ENABLE | DVP_CFG_FINISH_INT_ENABLE));
+	}
+	return E_OK;
+}
+
+/*
+ *  DVPイメージフォーマット再設定
+ *  parameter1  hdvp:  DVPハンドラへのポインタ
+ *              Init.Formatに再設定値
+ *  return ERコード
+ */
+ER
+dvp_set_image_format(DVP_Handle_t *hdvp)
+{
+	if(hdvp == NULL)
+		return E_PAR;
+	if((hdvp->Init.Format & ~DVP_CFG_FORMAT_MASK) != 0)
+		return E_PAR;
+
+	sil_modw_mem((uint32_t *)(hdvp->base+TOFF_DVP_CFG), DVP_CFG_FORMAT_MASK, hdvp->Init.Format);
+	return E_OK;
+}
+
+/*
+ *  DVPイメージサイズ再設定
+ *  parameter1  hdvp:  DVPハンドラへのポインタ
+ *              Init.Width, Init.Heightに再設定値
+ *  return ERコード
+ */
+ER
+dvp_set_image_size(DVP_Handle_t *hdvp)
+{
+	uint32_t cfg, divw;
+
+	if(hdvp == NULL)
+		return E_PAR;
+	cfg  = sil_rew_mem((uint32_t *)(hdvp->base+TOFF_DVP_CFG));
+	cfg &= ~(DVP_CFG_HREF_BURST_NUM_MASK | DVP_CFG_LINE_NUM_MASK);
+    cfg |= hdvp->Init.Height << 20;
+
+    if((cfg & DVP_CFG_BURST_SIZE_4BEATS) != 0)
+		divw = 4;
+	else
+		divw = 1;
+	cfg |= (hdvp->Init.Width / 8 / divw) << 12;
+    sil_wrw_mem((uint32_t *)(hdvp->base+TOFF_DVP_CFG), cfg);
+	return E_OK;
+}
+
+/*
+ *  SCCBクロック再設定
+ *  parameter1  hdvp:  DVPハンドラへのポインタ
+ *  parameter2  clk_rate:設定クロック値
+ *  return      設定値、0で未設定
+ */
+uint32_t
+dvp_sccb_set_clk_rate(DVP_Handle_t *hdvp, uint32_t clk_rate)
+{
+	uint32_t sccb_cfg;
+	uint32_t v_sccb_freq = dvp_clock_get_freq(APB1_CLOCK_REQ);
+	uint16_t v_period_clk_cnt = ((v_sccb_freq+(clk_rate/2)) / clk_rate / 2);
+
+	if(hdvp == NULL)
+		return 0;
+	if(v_period_clk_cnt > 255){
+		return 0;
+	}
+
+	sccb_cfg  = sil_rew_mem((uint32_t *)(hdvp->base+TOFF_DVP_SCCB_CFG));
+    sccb_cfg &= ~(DVP_SCCB_SCL_LCNT_MASK | DVP_SCCB_SCL_HCNT_MASK);
+    sccb_cfg |= (v_period_clk_cnt << 8) | (v_period_clk_cnt << 16);
+	sil_wrw_mem((uint32_t *)(hdvp->base+TOFF_DVP_SCCB_CFG), sccb_cfg);
+	return dvp_clock_get_freq(DVP_CLOCK_REQ) / (v_period_clk_cnt * 2);
+}
+
+/*
+ *  DVP-DCMIリセット設定
+ *  parameter1  hdvp:  DVPハンドラへのポインタ
+ *  parameter2  reset: 1:reset, 0:relase
+ *  return ERコード
+ */
+ER
+dvp_dcmi_reset(DVP_Handle_t *hdvp, bool_t reset)
+{
+	if(hdvp == NULL)
+		return E_PAR;
+	if(reset)
+		sil_orw_mem((uint32_t *)(hdvp->base+TOFF_DVP_CMOS_CFG), DVP_CMOS_RESET);
+	else
+		sil_andw_mem((uint32_t *)(hdvp->base+TOFF_DVP_CMOS_CFG), DVP_CMOS_RESET);
+	return E_OK;
+}
+
+/*
+ *  DVP-DCMIパワーダウン設定
+ *  parameter1  hdvp:  DVPハンドラへのポインタ
+ *  parameter2  down: 1:down, 0:up
+ *  return ERコード
+ */
+ER
+dvp_dcmi_powerdown(DVP_Handle_t *hdvp, bool_t down)
+{
+	if(hdvp == NULL)
+		return E_PAR;
+	if(down)
+		sil_orw_mem((uint32_t *)(hdvp->base+TOFF_DVP_CMOS_CFG), DVP_CMOS_POWER_DOWN);
+	else
+		sil_andw_mem((uint32_t *)(hdvp->base+TOFF_DVP_CMOS_CFG), DVP_CMOS_POWER_DOWN);
+	return E_OK;
+}
+
+/*
+ *  DVP割込みハンドラ
+ */
+void
+dvp_handler(void)
+{
+	DVP_Handle_t *hdvp = phdvp;
+	uint32_t istatus, estatus;
+
+	if(hdvp == NULL)
+		return;
+	istatus = sil_rew_mem((uint32_t *)(hdvp->base+TOFF_DVP_STS));
+	if(istatus == 0)
+		return;
+	estatus = istatus;
+	syslog_2(LOG_DEBUG, "sensor_irq istatus[%08x] hdvp->state(%d)", istatus, hdvp->state);
+	if((istatus & DVP_STS_FRAME_FINISH) != 0){	//frame end
+		estatus |= DVP_STS_FRAME_FINISH_WE;
+		hdvp->state = DVP_STATE_FINISH;
+		if(hdvp->semid != 0)
+			isig_sem(hdvp->semid);
+	}
+	if((istatus & DVP_STS_FRAME_START) != 0){	//frame start
+		estatus |= DVP_STS_FRAME_START_WE;
+        if(hdvp->state == DVP_STATE_ACTIVATE){  //only we finish the convert, do transmit again
+			/*
+			 *  コンバートスタート
+			 */
+			sil_wrw_mem((uint32_t *)(hdvp->base+TOFF_DVP_STS), DVP_STS_DVP_EN | DVP_STS_DVP_EN_WE);
+			hdvp->state = DVP_STATE_STARTED;
+		}
+	}
+	sil_orw_mem((uint32_t *)(hdvp->base+TOFF_DVP_STS), estatus);
+}
+
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/dvp.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/dvp.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/dvp.cfg	(revision 453)
@@ -0,0 +1,16 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *  DVPドライバのコンフィギュレーションファイル
+ */
+
+#include "device.h"
+#include "dvp.h"
+
+CRE_SEM(DVP_SEM, { TA_TPRI, 0, 1 });
+
+DEF_INH(INHNO_DVP, { TA_NULL, dvp_handler });
+CFG_INT(INTNO_DVP, { TA_NULL | INTATR_DVP, INTPRI_DVP });
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/dvp.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/dvp.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/dvp.h	(revision 453)
@@ -0,0 +1,209 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ * 
+ *  K210 DVPデバイスドライバの外部宣言
+ *
+ */
+
+#ifndef _DVP_H_
+#define _DVP_H_
+
+#include <kernel.h>
+#include <target_syssvc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TADR_DVP_BASE       (DVP_BASE_ADDR)
+#define TOFF_DVP_CFG            0x0000	/* (RW) DVP Config Register */
+  #define DVP_CFG_START_INT_ENABLE      0x00000001
+  #define DVP_CFG_FINISH_INT_ENABLE     0x00000002
+  #define DVP_CFG_AI_OUTPUT_ENABLE      0x00000004
+  #define DVP_CFG_DISPLAY_OUTPUT_ENABLE 0x00000008
+  #define DVP_CFG_AUTO_ENABLE           0x00000010
+  #define DVP_CFG_BURST_SIZE_4BEATS     0x00000100
+  #define DVP_CFG_FORMAT_MASK           0x00000600
+  #define DVP_CFG_RGB_FORMAT            0x00000000
+  #define DVP_CFG_YUV_FORMAT            0x00000200
+  #define DVP_CFG_Y_FORMAT              0x00000600
+  #define DVP_CFG_HREF_BURST_NUM_MASK   0x000FF000
+  #define DVP_CFG_LINE_NUM_MASK         0x3FF00000
+#define TOFF_DVP_R_ADDR         0x0004	/* (RW) RED ADDRESS */
+#define TOFF_DVP_G_ADDR         0x0008	/* (RW) GREEN ADDRESS */
+#define TOFF_DVP_B_ADDR         0x000C	/* (RW) BLUE ADDRESS */
+#define TOFF_DVP_CMOS_CFG       0x0010	/* (RW) DVP CMOS Config Register */
+  #define DVP_CMOS_CLK_DIV_MASK         0x000000FF
+  #define DVP_CMOS_CLK_DIV(x)           ((x) << 0)
+  #define DVP_CMOS_CLK_ENABLE           0x00000100
+  #define DVP_CMOS_RESET                0x00010000
+  #define DVP_CMOS_POWER_DOWN           0x01000000
+#define TOFF_DVP_SCCB_CFG       0x0014	/* (RW) DVP SCCB Config Register */
+  #define DVP_SCCB_BYTE_NUM_MASK        0x00000003
+  #define DVP_SCCB_BYTE_NUM_2           0x00000001
+  #define DVP_SCCB_BYTE_NUM_3           0x00000002
+  #define DVP_SCCB_BYTE_NUM_4           0x00000003
+  #define DVP_SCCB_SCL_LCNT_MASK        0x0000FF00
+  #define DVP_SCCB_SCL_HCNT_MASK        0x00FF0000
+  #define DVP_SCCB_RDATA_BYTE_MASK      0xFF000000
+#define TOFF_DVP_SCCB_CTL       0x0018	/* (RW) DVP SCCB Control Register */
+  #define DVP_SCCB_WRITE_DATA_ENABLE    0x00000001
+  #define DVP_SCCB_DEVICE_ADDRESS       0x000000FF
+  #define DVP_SCCB_REG_ADDRESS          0x0000FF00
+  #define DVP_SCCB_WDATA_BYTE0          0x00FF0000
+  #define DVP_SCCB_WDATA_BYTE1          0xFF000000
+#define TOFF_DVP_AXI            0x001C	/* (RW) DVP AXI Register */
+  #define DVP_AXI_GM_MLEN_MASK          0x000000FF
+  #define DVP_AXI_GM_MLEN_1BYTE         0x00000000
+  #define DVP_AXI_GM_MLEN_4BYTE         0x00000003
+#define TOFF_DVP_STS            0x0020	/* (RW) DVP STS Register */
+  #define DVP_STS_FRAME_START           0x00000001
+  #define DVP_STS_FRAME_START_WE        0x00000002
+  #define DVP_STS_FRAME_FINISH          0x00000100
+  #define DVP_STS_FRAME_FINISH_WE       0x00000200
+  #define DVP_STS_DVP_EN                0x00010000
+  #define DVP_STS_DVP_EN_WE             0x00020000
+  #define DVP_STS_SCCB_EN               0x01000000
+  #define DVP_STS_SCCB_EN_WE            0x02000000
+#define TOFF_DVP_RGB_ADDR       0x0028	/* (RW) DVP RGB ADDRESS */
+
+
+/*
+ *  BURSTモード設定
+ */
+#define DVP_BURST_ENABLE        DVP_CFG_BURST_SIZE_4BEATS
+#define DVP_BURST_DISABLE       0
+
+/*
+ *  AUTOモード設定
+ */
+#define DVP_AUTOMODE_ENABLE     DVP_CFG_AUTO_ENABLE
+#define DVP_AUTOMODE_DISABLE    0
+
+/*
+ *  DVPイメージフォーマット設定
+ */
+#define DVP_FORMAT_RGB          DVP_CFG_RGB_FORMAT
+#define DVP_FORMAT_YUY          DVP_CFG_YUV_FORMAT
+#define DVP_FORMAT_Y            DVP_CFG_Y_FORMAT
+
+/*
+ *  DVP状態定義
+ */
+#define DVP_STATE_INIT          0
+#define DVP_STATE_READY         1
+#define DVP_STATE_ACTIVATE      2
+#define DVP_STATE_STARTED       3
+#define DVP_STATE_FINISH        4
+
+
+#define INHNO_DVP     IRQ_VECTOR_DVP	/* 割込みハンドラ番号 */
+#define INTNO_DVP     IRQ_VECTOR_DVP	/* 割込み番号 */
+#define INTPRI_DVP    -3		/* 割込み優先度 */
+#define INTATR_DVP    0			/* 割込み属性 */
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  DVP 設定初期設定構造体
+ */
+typedef struct
+{
+	uint32_t              Freq;				/* DVP 周波数設定 */
+	uint32_t              RedAddr;			/* DVP Readアドレス設定 */
+	uint32_t              GreenAddr;		/* DVP Greenアドレス設定 */
+    uint32_t              BlueAddr;			/* DVP Blueアドレス設定 */
+	uint32_t              RGBAddr;			/* DVP RGBアドレス設定 */
+
+	uint32_t              Format;			/* DVP イメージフォーマット */
+	uint32_t              BurstMode;		/* DVP ブーストモード設定 */
+	uint32_t              AutoMode;			/* DVP オートモード設定 */
+	uint32_t              GMMlen;			/* DVP GM MLEN設定 */
+	uint16_t              Width;			/* DVP 幅設定 */
+	uint16_t              Height;			/* DVP 高さ設定 */
+	uint8_t               num_sccb_reg;		/* DVP SCCBレジスタ長 */
+	int8_t                CMosPClkPin;		/* DVP PCLKピン設定 */
+	int8_t                CMosXClkPin;		/* DVP XCLKピン設定 */
+	int8_t                CMosHRefPin;		/* DVP HREFピン設定 */
+	int8_t                CMosPwDnPin;		/* DVP パワーダウン設定 */
+	int8_t                CMosVSyncPin;		/* DVP VSYNCピン設定 */
+	int8_t                CMosRstPin;		/* DVP リセットピン設定 */
+	int8_t                SccbSClkPin;		/* DVP SCCB SCLKピン設定 */
+	int8_t                SccbSdaPin;		/* DVP SCCB SDAピン設定 */
+	uint8_t               dummy;
+	uint16_t              IntNo;			/* DVP 割込み番号 */
+	int                   semlock;			/* SPI ロックセマフォ値 */
+}DVP_Init_t;
+
+/*
+ *  SPIハンドラ
+ */
+typedef struct _DVP_Handle_t
+{
+	unsigned long         base;				/* DVP registers base address */
+	DVP_Init_t            Init;				/* DVP communication parameters */
+	ID                    semid;			/* DVP semaphore id */
+	volatile uint16_t     state;			/* DVP state */
+	volatile uint16_t     ErrorCode;		/* DVP Error code */
+}DVP_Handle_t;
+
+
+extern ER dvp_init(DVP_Handle_t *hdvp);
+extern ER dvp_deinit(DVP_Handle_t *hdvp);
+extern ER dvp_activate(DVP_Handle_t *hdvp, bool_t run);
+extern ER dvp_set_image_format(DVP_Handle_t *hdvp);
+extern ER dvp_set_image_size(DVP_Handle_t *hdvp);
+extern uint32_t dvp_sccb_set_clk_rate(DVP_Handle_t *hdvp, uint32_t clk_rate);
+extern ER dvp_dcmi_reset(DVP_Handle_t *hdvp, bool_t reset);
+extern ER dvp_dcmi_powerdown(DVP_Handle_t *hdvp, bool_t down);
+extern void dvp_sccb_send_data(DVP_Handle_t *hdvp, uint8_t dev_addr, uint16_t reg_addr, uint8_t reg_data);
+extern uint8_t dvp_sccb_receive_data(DVP_Handle_t *hdvp, uint8_t dev_addr, uint16_t reg_addr);
+extern void dvp_handler(void);
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _DVP_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/i2c.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/i2c.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/i2c.c	(revision 453)
@@ -0,0 +1,597 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ * 
+ *  K210 I2Cドライバ関数群
+ *
+ */
+#include "kernel_impl.h"
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <string.h>
+#include <sil.h>
+#include <target_syssvc.h>
+#include "device.h"
+#include "i2c.h"
+
+/*
+ *  SIL関数のマクロ定義
+ */
+#define sil_orw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) | (b))
+#define sil_andw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) & ~(b))
+#define sil_modw_mem(a, b, c)	sil_wrw_mem((a), (sil_rew_mem(a) & (~b)) | (c))
+
+/*
+ *  I2CポートIDから管理ブロックを取り出すためのマクロ
+ */
+#define INDEX_I2C(i2cid)        ((uint_t)((i2cid) - 1))
+
+#ifndef I2C_TIMEOUT
+#define I2C_TIMEOUT             500				/* 500ms */
+#endif
+
+#define I2C_CON_SPEED_STANDARD  0x00000020		/* <=100Kbit/s */
+#define I2C_CON_SPEED_FAST      0x00000040		/* <=400Kbit/s or <=1000Kbit/s */
+#define I2C_CON_SPEED_HIGH      0x00000060		/* <=3.4Mbit/s */
+
+#define DEFAULT_THRESHOLD       3
+#define DEFAULT_MASTER          (I2C_CON_MASTER_MODE | I2C_CON_SLAVE_DISABLE | I2C_CON_RESTART_EN)
+#define DEFAULT_SLAVE           (I2C_CON_STOP_DET_IFADDRESSED)
+#define DEFAULT_INTRM           (I2C_INTR_MASK_START_DET | I2C_INTR_MASK_STOP_DET | I2C_INTR_MASK_RD_REQ)
+
+/*
+ *  I2Cポート設定テーブル
+ */
+static const I2C_PortControlBlock i2c_pcb[NUM_I2CPORT] = {
+  {	TADR_I2C0_BASE, SYSCTL_CLK_EN_PERI_I2C0_CLK_EN, 8,  FUNC_I2C0_SCLK, FUNC_I2C0_SDA },
+  {	TADR_I2C1_BASE, SYSCTL_CLK_EN_PERI_I2C1_CLK_EN, 16, FUNC_I2C1_SCLK, FUNC_I2C1_SDA },
+  {	TADR_I2C2_BASE, SYSCTL_CLK_EN_PERI_I2C2_CLK_EN, 24, FUNC_I2C2_SCLK, FUNC_I2C2_SDA }
+};
+
+static I2C_Handle_t i2cHandle[3];
+
+
+/*
+ *  I2C転送待ち
+ *  parameter1 hi2c:   I2Cハンドラへのポインタ
+ *  parameter2 Timeout:タイムアウト時間(ms)
+ */
+static ER
+i2c_transwait(I2C_Handle_t *hi2c, uint32_t Timeout)
+{
+	uint32_t tick = 0;
+
+	while(hi2c->status != I2C_STATUS_READY){
+		if(tick >= Timeout)
+			return E_TMOUT;
+		if(hi2c->Init.semid != 0)
+			twai_sem(hi2c->Init.semid, 1);
+		else
+			dly_tsk(1);
+		tick++;
+	}
+	if(hi2c->ErrorCode != 0)
+		return E_SYS;
+	else
+		return E_OK;
+}
+
+/*
+ *  I2Cデータ送信モジュール
+ */
+static void
+i2c_send_data(I2C_Handle_t *hi2c)
+{
+    uint32_t fifo_len, i,  tmp;
+
+	if(hi2c->tXferCount > 0){
+		uint8_t  *send_buf;
+		int  addr_len = hi2c->aXferSize - hi2c->aXferCount;
+        fifo_len = 8 - sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_TXFLR));
+		if(addr_len > 0){
+	        fifo_len = addr_len < fifo_len ? addr_len : fifo_len;
+			send_buf = &hi2c->aBuffer[hi2c->aXferCount];
+		}
+		else{
+			fifo_len = hi2c->tXferCount < fifo_len ? hi2c->tXferCount : fifo_len;
+			send_buf = hi2c->pBuffPtr;
+		}
+        for(i = 0 ; i < fifo_len ; i++)
+			sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_DATA_CMD), *send_buf++);
+		if(addr_len > 0)
+			hi2c->aXferCount += fifo_len;
+		else{
+			hi2c->pBuffPtr  += fifo_len;
+			hi2c->XferCount += fifo_len;
+		}
+        hi2c->tXferCount -= fifo_len;
+    }
+	(void)(tmp);
+}
+
+/*
+ *  I2Cデータ受信モジュール
+ */
+static void
+i2c_recv_data(I2C_Handle_t *hi2c)
+{
+	uint32_t fifo_len, i, tmp;
+	int rx_len = hi2c->XferSize - hi2c->XferCount;
+
+	if(hi2c->tXferCount > 0 || rx_len > 0){
+		fifo_len = sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_RXFLR));
+		fifo_len = rx_len < fifo_len ? rx_len : fifo_len;
+		for(i = 0 ; i < fifo_len ; i++){
+			tmp = (uint8_t)sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_DATA_CMD));
+			*hi2c->pBuffPtr++ = (uint8_t)tmp;
+		}
+		hi2c->XferCount += fifo_len;
+		fifo_len = 8 - sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_TXFLR));
+		fifo_len = hi2c->tXferCount < fifo_len ? hi2c->tXferCount : fifo_len;
+		for(i = 0 ; i < fifo_len ; i++)
+			sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_DATA_CMD), I2C_DATA_CMD_CMD);
+		hi2c->tXferCount -= fifo_len;
+	}
+}
+
+
+/*
+ *  I2Cデバイスの初期化
+ *  parameter1 hi2c  I2Cハンドラへのポインタ
+ *  return           正常終了時、E_OK
+ */
+I2C_Handle_t *
+i2c_init(ID portid, I2C_Init_t *ii2c)
+{
+	I2C_Handle_t *hi2c;
+	const I2C_PortControlBlock *pcb;
+    uint32_t v_i2c_freq = 0;
+	uint32_t threshold = 0;
+    int32_t v_period_clk_cnt2 = 0;
+	uint16_t v_period_clk_cnt;
+	uint8_t  no;
+    uint32_t speed_mode = I2C_CON_SPEED_STANDARD;
+
+	if(portid < I2C1_PORTID || portid >= NUM_I2CPORT)
+		return NULL;
+
+	no = INDEX_I2C(portid);
+	hi2c = &i2cHandle[no];
+	hi2c->i2cid = portid;
+	pcb = &i2c_pcb[no];
+	hi2c->base  = pcb->base;
+	memcpy(&hi2c->Init, ii2c, sizeof(I2C_Init_t));
+
+	/*
+	 *  ファンクションピン設定
+	 */
+	if(ii2c->SdaPin >= 0)
+		fpioa_set_function(ii2c->SdaPin, pcb->sdafunc);
+	if(ii2c->SclPin >= 0)
+		fpioa_set_function(ii2c->SclPin, pcb->sclfunc);
+
+	/*
+	 *  クロック設定
+	 */
+	sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_CENT), SYSCTL_CLK_SEL0_APB0_CLK_SEL);
+	sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_PERI), (SYSCTL_CLK_EN_PERI_I2C0_CLK_EN<<no));
+	threshold  = sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_TH5));
+	threshold &= ~(0xff << pcb->thresholdshift);
+	threshold |= (DEFAULT_THRESHOLD << pcb->thresholdshift);
+	sil_wrw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_TH5), threshold);
+
+	sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_CENT), SYSCTL_CLK_SEL0_APB0_CLK_SEL);
+	sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_PERI), (SYSCTL_CLK_EN_PERI_I2C0_CLK_EN<<no));
+	threshold  = sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_TH5));
+	threshold &= ~(0xff << pcb->thresholdshift);
+	threshold |= (DEFAULT_THRESHOLD << pcb->thresholdshift);
+	sil_wrw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_TH5), threshold);
+
+	threshold = sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_TH5));
+	threshold = (threshold >> pcb->thresholdshift) & 0xff;
+    v_i2c_freq = get_pll_clock(0) / ((threshold + 1) * 2);
+	v_period_clk_cnt2 = (((int64_t)v_i2c_freq * 1000L) / ii2c->ClockSpeed / 2) + 500;
+	v_period_clk_cnt  = v_period_clk_cnt2 / 1000;
+
+    if(v_period_clk_cnt <= 6)
+        v_period_clk_cnt = 6;
+    if(v_period_clk_cnt >= 65525)
+        v_period_clk_cnt = 65525;
+    if((ii2c->ClockSpeed > 100000) && (ii2c->ClockSpeed <= 1000000))
+        speed_mode = I2C_CON_SPEED_FAST;
+    else if(ii2c->ClockSpeed > 1000000)
+        speed_mode = I2C_CON_SPEED_HIGH;
+	else
+        speed_mode = I2C_CON_SPEED_STANDARD;
+
+	sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_ENABLE), 0);
+	if(ii2c->OwnAddress1 == 0)	/* master */
+		sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_CON), (DEFAULT_MASTER | ii2c->AddressingMode | speed_mode));
+	else						/* slave */
+		sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_CON), (DEFAULT_SLAVE | ii2c->AddressingMode | speed_mode));
+	sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_SS_SCL_HCNT), v_period_clk_cnt);
+	sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_SS_SCL_LCNT), v_period_clk_cnt);
+
+	sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_TAR), ii2c->OwnAddress1/2);
+	sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_RX_TL), 0);
+	sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_TX_TL), 0);
+	sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_INTR_MASK), DEFAULT_INTRM);
+	sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_DMA_CR), (I2C_DMA_CR_RDMAE | I2C_DMA_CR_TDMAE));
+	sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_DMA_RDLR), 0);
+	sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_DMA_TDLR), 4);
+	sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_ENABLE), I2C_ENABLE_ENABLE);
+	hi2c->status = I2C_STATUS_READY;
+	syslog_3(LOG_NOTICE, "## abrt[%08x] dmacr[%08x] intrm[%08x] ##", sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_TX_ABRT_SOURCE)), sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_DMA_CR)), sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_INTR_MASK)));
+	return hi2c;
+}
+
+/*
+ *  I2Cデバイスの無効化
+ *  parameter1 hi2c  I2Cハンドラへのポインタ
+ *  return           正常終了時、E_OK
+ */
+ER
+i2c_deinit(I2C_Handle_t *hi2c)
+{
+	uint8_t no;
+
+	if(hi2c == NULL)
+		return E_PAR;
+	sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_ENABLE), 0);
+	no = INDEX_I2C(hi2c->i2cid);
+	hi2c->status = I2C_STATUS_RESET;
+	sil_andw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_PERI), (SYSCTL_CLK_EN_PERI_I2C0_CLK_EN<<no));
+	return E_OK;
+}
+
+/*
+ *  I2Cスレーブ受信
+ *  parameter1 hi2c:   I2Cハンドラへのポインタ
+ *  parameter2 pData:  読み出しバッファへのポインタ
+ *  parameter3 Size:   読み出しサイズ
+ *  return             正常終了ならE_OK
+ */
+ER
+i2c_slaveread(I2C_Handle_t *hi2c, uint8_t *pData, uint16_t Size)
+{
+	ER ercd = E_OK;
+	uint32_t tmp;
+
+	if(hi2c == NULL || pData == NULL || Size == 0)
+		return E_PAR;
+	if(hi2c->status != I2C_STATUS_READY)
+		return E_OBJ;
+
+	/*
+	 *  読み出しロック
+	 */
+	if(hi2c->Init.semlock != 0)
+		wai_sem(hi2c->Init.semlock);
+
+	tmp = sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_CLR_TX_ABRT));
+	sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_CLR_TX_ABRT), tmp);
+
+	hi2c->aXferSize  = 0;
+	hi2c->aXferCount = 0;
+	hi2c->pBuffPtr   = pData;
+	hi2c->XferSize   = Size;
+	hi2c->XferCount  = 0;
+	hi2c->tXferCount = Size;
+	hi2c->status     = I2C_STATUS_BUSY_RX;
+	sil_orw_mem((uint32_t *)(hi2c->base+TOFF_I2C_INTR_MASK), I2C_INTR_MASK_RX_FULL);
+
+	i2c_recv_data(hi2c);
+	ercd = i2c_transwait(hi2c, I2C_TIMEOUT);
+
+	/*
+	 *  読み出しロック解除
+	 */
+	if(hi2c->Init.semlock != 0)
+		sig_sem(hi2c->Init.semlock);
+	return ercd;
+}
+
+/*
+ *  I2Cスレーブ送信
+ *  parameter1 hi2c:   I2Cハンドラへのポインタ
+ *  parameter2 pData:  読み出しバッファへのポインタ
+ *  parameter3 Size:   読み出しサイズ
+ *  return             正常終了ならE_OK
+ */
+ER
+i2c_slavewrite(I2C_Handle_t *hi2c, uint8_t *pData, uint16_t Size)
+{
+	ER ercd = E_OK;
+	uint32_t tmp;
+
+	if(hi2c == NULL || pData == NULL || Size == 0)
+		return E_PAR;
+	if(hi2c->status != I2C_STATUS_READY)
+		return E_OBJ;
+
+	/*
+	 *  書き込みロック
+	 */
+	if(hi2c->Init.semlock != 0)
+		wai_sem(hi2c->Init.semlock);
+
+	tmp = sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_CLR_TX_ABRT));
+	sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_CLR_TX_ABRT), tmp);
+
+	hi2c->aXferSize  = 0;
+	hi2c->aXferCount = 0;
+	hi2c->pBuffPtr   = pData;
+	hi2c->XferSize   = Size;
+	hi2c->XferCount  = 0;
+	hi2c->tXferCount = Size;
+	hi2c->status     = I2C_STATUS_BUSY_TX;
+
+	i2c_send_data(hi2c);
+	sil_orw_mem((uint32_t *)(hi2c->base+TOFF_I2C_INTR_MASK), I2C_INTR_MASK_TX_EMPTY);
+	ercd = i2c_transwait(hi2c, I2C_TIMEOUT);
+
+	while((sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_STATUS)) & I2C_STATUS_TFE) == 0){
+		syslog_2(LOG_ERROR, "i2c_slavewrite status[%08x] abrt[%08x]", sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_STATUS)), sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_TX_ABRT_SOURCE)));
+		dly_tsk(50);
+	}
+
+	/*
+	 *  書き込みロック解除
+	 */
+	if(hi2c->Init.semlock != 0)
+		sig_sem(hi2c->Init.semlock);
+	return ercd;
+}
+
+/*
+ *  I2Cデータリード
+ *  parameter1 hi2c:       I2Cハンドラへのポインタ
+ *  parameter2 DevAddress: スレーブアドレス
+ *  parameter3 MemAddress: メモリアドレス
+ *  parameter4 MemAddSize: メモリアドレスサイズ
+ *  parameter5 pData:      読み出しバッファへのポインタ
+ *  parameter6 Size:       読み出しサイズ
+ *  return                 正常終了ならE_OK
+ */
+ER
+i2c_memread(I2C_Handle_t *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
+{
+	ER ercd = E_OK;
+	int32_t  send_buf_len, timeout = I2C_TIMEOUT;
+	uint32_t fifo_len, abrt, i, tmp;
+
+	if(hi2c == NULL || pData == NULL || Size == 0)
+		return E_PAR;
+	if(hi2c->status != I2C_STATUS_READY)
+		return E_OBJ;
+
+	/*
+	 *  読み出しロック
+	 */
+	if(hi2c->Init.semlock != 0)
+		wai_sem(hi2c->Init.semlock);
+
+	tmp = sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_CLR_TX_ABRT));
+	sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_CLR_TX_ABRT), tmp);
+
+	if(MemAddSize == 2){
+		hi2c->aBuffer[0] = (uint8_t)(MemAddress >> 8);
+		hi2c->aBuffer[1] = (uint8_t)MemAddress;
+	}
+	else if(MemAddSize == 1)
+		hi2c->aBuffer[0] = (uint8_t)MemAddress;
+	hi2c->aXferSize  = MemAddSize;
+	hi2c->aXferCount = 0;
+	hi2c->pBuffPtr   = pData;
+	hi2c->XferSize   = Size;
+	hi2c->XferCount  = 0;
+	hi2c->tXferCount = Size;
+	hi2c->status     = I2C_STATUS_BUSY_RX;
+
+	sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_TAR), DevAddress/2);
+	while(hi2c->aXferSize > hi2c->aXferCount){
+		send_buf_len = hi2c->aXferSize - hi2c->aXferCount;
+        fifo_len = 8 - sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_TXFLR));
+        fifo_len = send_buf_len < fifo_len ? send_buf_len : fifo_len;
+		if(fifo_len == 0){
+			dly_tsk(1);
+			if(--timeout == 0){
+				hi2c->ErrorCode = I2C_ERROR_TIMEOUT;
+				if(hi2c->Init.semlock != 0)
+					sig_sem(hi2c->Init.semlock);
+				return E_TMOUT;
+			}
+		}
+        for(i = 0 ; i < fifo_len; i++)
+			sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_DATA_CMD), hi2c->aBuffer[hi2c->aXferCount++]);
+		if((abrt = sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_TX_ABRT_SOURCE))) != 0){
+			hi2c->ErrorCode = abrt;
+			if(hi2c->Init.semlock != 0)
+				sig_sem(hi2c->Init.semlock);
+			return E_SYS;
+		}
+        hi2c->aXferCount += fifo_len;
+    }
+	sil_orw_mem((uint32_t *)(hi2c->base+TOFF_I2C_INTR_MASK), I2C_INTR_MASK_RX_FULL);
+
+	i2c_recv_data(hi2c);
+	ercd = i2c_transwait(hi2c, I2C_TIMEOUT);
+
+	/*
+	 *  読み出しロック解除
+	 */
+	if(hi2c->Init.semlock != 0)
+		sig_sem(hi2c->Init.semlock);
+	return ercd;
+}
+
+/*
+ *  I2Cデータライト
+ *  parameter1 hi2c:       I2Cハンドラへのポインタ
+ *  parameter2 DevAddress: スレーブアドレス
+ *  parameter3 MemAddress: メモリアドレス
+ *  parameter4 MemAddSize: メモリアドレスサイズ
+ *  parameter5 pData:      書込みバッファへのポインタ
+ *  parameter6 Size:       書込みサイズ
+ *  return                 正常終了ならE_OK
+ */
+ER
+i2c_memwrite(I2C_Handle_t *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
+{
+	ER ercd;
+	uint32_t tmp;
+
+	if(hi2c == NULL || pData == NULL || Size == 0)
+		return E_PAR;
+	if(hi2c->status != I2C_STATUS_READY)
+		return E_OBJ;
+
+	/*
+	 *  書き込みロック
+	 */
+	if(hi2c->Init.semlock != 0)
+		wai_sem(hi2c->Init.semlock);
+
+	tmp = sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_CLR_TX_ABRT));
+	sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_CLR_TX_ABRT), tmp);
+
+	if(MemAddSize == 2){
+		hi2c->aBuffer[0] = (uint8_t)(MemAddress >> 8);
+		hi2c->aBuffer[1] = (uint8_t)MemAddress;
+	}
+	else if(MemAddSize == 1)
+		hi2c->aBuffer[0] = (uint8_t)MemAddress;
+	hi2c->aXferSize  = MemAddSize;
+	hi2c->aXferCount = 0;
+	hi2c->pBuffPtr   = pData;
+	hi2c->XferSize   = Size;
+	hi2c->XferCount  = 0;
+	hi2c->tXferCount = MemAddSize + Size;
+	hi2c->status     = I2C_STATUS_BUSY_TX;
+
+	sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_TAR), DevAddress/2);
+	i2c_send_data(hi2c);
+	sil_orw_mem((uint32_t *)(hi2c->base+TOFF_I2C_INTR_MASK), I2C_INTR_MASK_TX_EMPTY);
+	ercd = i2c_transwait(hi2c, I2C_TIMEOUT);
+
+	while((sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_STATUS)) & I2C_STATUS_TFE) == 0){
+		syslog_2(LOG_NOTICE, "i2c_memwrite status[%08x] abrt[%08x]", sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_STATUS)), sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_TX_ABRT_SOURCE)));
+		dly_tsk(100);
+	}
+
+	/*
+	 *  書き込みロック解除
+	 */
+	if(hi2c->Init.semlock != 0)
+		sig_sem(hi2c->Init.semlock);
+	return ercd;
+}
+
+/*
+ *  I2C割込みハンドラ
+ */
+void
+i2c_isr(intptr_t exinf)
+{
+	I2C_Handle_t *hi2c = &i2cHandle[INDEX_I2C(exinf)];
+	uint32_t istatus = sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_INTR_STAT));
+	uint32_t abrt   = sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_TX_ABRT_SOURCE));
+	uint32_t status  = sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_STATUS));
+	uint32_t tmp;
+	syslog_3(LOG_DEBUG, "i2c_isr[%08x] abrt[%08x] status[%08x]", istatus, abrt, status);
+	if(istatus & I2C_INTR_STAT_START_DET){
+		tmp = sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_CLR_START_DET));
+	}
+	if(istatus & I2C_INTR_STAT_STOP_DET){
+		tmp = sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_CLR_STOP_DET));
+		if((status & I2C_STATUS_ACTIVITY) == 0){
+			hi2c->status = I2C_STATUS_READY;
+			hi2c->ErrorCode = abrt;
+			if(abrt != 0 && hi2c->errorcallback != NULL)
+				hi2c->errorcallback(hi2c);
+			if(hi2c->Init.semid != 0)
+				isig_sem(hi2c->Init.semid);
+		}
+	}
+	if(istatus & I2C_INTR_STAT_TX_EMPTY){
+		tmp = sil_rew_mem((uint32_t *)(hi2c->base+I2C_INTR_STAT_TX_EMPTY));
+		if(abrt != 0){
+			hi2c->status = I2C_STATUS_READY;
+			hi2c->ErrorCode = abrt;
+			if(hi2c->errorcallback != NULL)
+				hi2c->errorcallback(hi2c);
+			hi2c->tXferCount = 0;
+		}
+		else if(hi2c->status == I2C_STATUS_BUSY_TX){
+			if(hi2c->tXferCount > 0)
+				i2c_send_data(hi2c);
+		}
+		if(hi2c->tXferCount == 0){
+			sil_andw_mem((uint32_t *)(hi2c->base+TOFF_I2C_INTR_MASK), I2C_INTR_MASK_TX_EMPTY);
+			if(hi2c->writecallback != NULL)
+				hi2c->writecallback(hi2c);
+		}
+	}
+	if(istatus & I2C_INTR_STAT_RX_FULL){
+		if(abrt != 0){
+			hi2c->status = I2C_STATUS_READY;
+			hi2c->ErrorCode = abrt;
+			if(hi2c->errorcallback != NULL)
+				hi2c->errorcallback(hi2c);
+			hi2c->tXferCount = 0;
+			hi2c->XferCount  = hi2c->XferSize;
+		}
+		else if(hi2c->status == I2C_STATUS_BUSY_RX){
+			if(hi2c->XferSize > hi2c->XferCount)
+				i2c_recv_data(hi2c);
+		}
+		if(hi2c->XferSize <= hi2c->XferCount){
+			sil_andw_mem((uint32_t *)(hi2c->base+TOFF_I2C_INTR_MASK), I2C_INTR_MASK_RX_FULL);
+			if(hi2c->readcallback != NULL)
+				hi2c->readcallback(hi2c);
+		}
+	}
+	if(istatus & I2C_INTR_STAT_RD_REQ){
+		tmp = sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_CLR_RD_REQ));
+    }
+	(void)(tmp);
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/i2c.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/i2c.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/i2c.h	(revision 453)
@@ -0,0 +1,159 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ * 
+ *  K210 I2Cデバイスドライバの外部宣言
+ *
+ */
+
+#ifndef _I2C_H_
+#define _I2C_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+/*
+ *  I2Cポート定義
+ */
+#define I2C1_PORTID             1
+#define I2C2_PORTID             2
+#define I2C3_PORTID             3
+#define NUM_I2CPORT             3
+
+#define I2C_MAX_NUM NUM_I2CPORT
+
+/*
+ *  I2Cアドレッシングモード
+ */
+#define I2C_ADDRESSINGMODE_7BIT  0
+#define I2C_ADDRESSINGMODE_10BIT I2C_CON_10BITADDR_SLAVE
+
+/*
+ *  I2Cメモリアドレスモード
+ */
+#define I2C_MEMADD_SIZE_NONE    0x00000000
+#define I2C_MEMADD_SIZE_8BIT    0x00000001
+#define I2C_MEMADD_SIZE_16BIT   0x00000002
+
+/*
+ *  I2C状態定義
+ */
+#define I2C_STATUS_RESET    0x00			/* I2C リセット状態 */
+#define I2C_STATUS_READY    0x01			/* I2C レディ状態 */
+#define I2C_STATUS_BUSY     0x02			/* I2C ビジィ状態 */
+#define I2C_STATUS_BUSY_TX  0x52			/* I2C 送信中 */
+#define I2C_STATUS_BUSY_RX  0x62			/* I2C 受信中 */
+#define I2C_STATUS_TIMEOUT  0x80
+
+/*
+ *  I2Cエラー定義
+ */
+#define I2C_ERROR_NONE      0x00000000		/* No error              */
+#define I2C_ERROR_TIMEOUT   0x02000000		/* Timeout error         */
+
+
+/*
+ *  SPIハードウェア設定構造体
+ */
+
+typedef struct _I2C_PortControlBlock{
+	unsigned long         base;
+	uint32_t              clkenable;
+	uint8_t               thresholdshift;
+	uint8_t               sclfunc;
+	uint8_t               sdafunc;
+	uint8_t               dummy;
+} I2C_PortControlBlock;
+
+/*
+ *  I2Cコンフュギュレーション構造体定義
+ */
+typedef struct
+{
+	uint32_t              ClockSpeed;		/* I2C クロック設定 */
+	uint32_t              OwnAddress1;		/* I2C 最初のデバイスの自分のアドレス */
+	uint32_t              AddressingMode;	/* I2C アドレッシングモード */
+	int32_t               SclPin;			/* I2C SCL PINNO */
+	int32_t               SdaPin;			/* I2C SDA PINNO*/
+	int                   semid;			/* I2C 通信用セマフォ値 */
+	int                   semlock;			/* I2C ロックセマフォ値 */
+}I2C_Init_t;
+
+
+/*
+ *  I2Cハンドラ定義
+ */
+typedef struct __I2C_Handle_t I2C_Handle_t;
+struct __I2C_Handle_t {
+	unsigned long              base;
+	I2C_Init_t                 Init;		/* I2C初期設定パラメータ */
+	uint8_t                    aBuffer[4];	/* I2C 通信アドレス領域 */
+	uint16_t                   aXferSize;	/* I2C 通信アドレスサイズ */
+	uint16_t                   aXferCount;	/* I2C 通信アドレスカウンタ */
+	uint8_t                    *pBuffPtr;	/* I2C 通信バッファへのポインタ */
+	uint16_t                   XferSize;	/* I2C 通信サイズ */
+	volatile uint16_t          XferCount;	/* I2C 通信カウンタ */
+	void                  (*writecallback)(I2C_Handle_t * hi2c);	/* 送信終了コールバック関数 */
+	void                  (*readcallback)(I2C_Handle_t * hi2c);		/* 受信終了コールバック関数 */
+	void                  (*errorcallback)(I2C_Handle_t * hi2c);	/* エラーコールバック関数 */
+	volatile uint32_t          tXferCount;	/* I2C 合計転送カウンタ */
+	ID                         i2cid;		/* I2C ID値 */
+	volatile uint32_t          status;		/* I2C 実行状態 */
+	volatile uint32_t          ErrorCode;	/* I2C Error code */
+};
+
+extern I2C_Handle_t *i2c_init(ID port, I2C_Init_t *ii2c);
+extern ER i2c_deinit (I2C_Handle_t *hi2c);
+extern ER i2c_slavewrite(I2C_Handle_t *hi2c, uint8_t *pData, uint16_t Size);
+extern ER i2c_slaveread(I2C_Handle_t *hi2c, uint8_t *pData, uint16_t Size);
+extern ER i2c_memwrite(I2C_Handle_t *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size);
+extern ER i2c_memread(I2C_Handle_t *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size);
+extern void i2c_isr(intptr_t exinf);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _I2C_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/pinmode.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/pinmode.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/pinmode.c	(revision 453)
@@ -0,0 +1,134 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2012 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *  ARDUNO-PIN(K410)ドライバ
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <string.h>
+#include <target_syssvc.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#include "kernel_cfg.h"
+#include "device.h"
+#include "pinmode.h"
+
+#define MD_PIN_MAP(fpio) _maixduino_pin_map[(fpio)]
+
+static const uint8_t _maixduino_pin_map[17] = {4, 5, 21, 22, 23, 24, 32, 15, 14, 13, 12, 11, 10, 3, 31, 30, 16};
+
+
+/*
+ *  Arduinoピンモード設定
+ */
+void
+pinMode(uint8_t dwPin, uint8_t dwMode){ 
+    int gpionumx = gpio_get_gpiohno(MD_PIN_MAP(dwPin), false);
+	GPIO_Init_t init = {0};
+	int gpionum;
+
+	gpionum = gpionumx;
+    if(gpionum >= 0){
+        uint8_t function = FUNC_GPIOHS0 + gpionum;
+        fpioa_set_function(MD_PIN_MAP(dwPin), function);
+		switch(dwMode){
+		case INPUT:
+			init.mode = GPIO_MODE_INPUT;
+			init.pull = GPIO_NOPULL;
+			break;
+		case INPUT_PULLDOWN:
+			init.mode = GPIO_MODE_INPUT;
+			init.pull = GPIO_PULLDOWN;
+			break;
+		case INPUT_PULLUP:
+			init.mode = GPIO_MODE_INPUT;
+			init.pull = GPIO_PULLUP;
+			break;
+		case OUTPUT:
+		default:
+			init.mode = GPIO_MODE_OUTPUT;
+			init.pull = GPIO_PULLDOWN;
+			break;
+		}
+        gpio_setup(TADR_GPIOHS_BASE, &init, (uint8_t)gpionum);
+    }
+    return ;
+}
+
+/*
+ *  Arduinoデジタルピン出力
+ */
+void
+digitalWrite(uint8_t dwPin, int dwVal){
+    int8_t gpio_pin = gpio_get_gpiohno(MD_PIN_MAP(dwPin), false);
+    if( gpio_pin >= 0){
+        gpio_set_pin(TADR_GPIOHS_BASE, (uint8_t)gpio_pin, dwVal);
+    }
+    return ;
+}
+
+/*
+ *  Arduinoデジタルピン入力
+ */
+int
+digitalRead(uint8_t dwPin){
+    int8_t gpio_pin = gpio_get_gpiohno(MD_PIN_MAP(dwPin), false);
+    if(gpio_pin >= 0){
+        return (int)gpio_get_pin(TADR_GPIOHS_BASE, (uint8_t)gpio_pin);
+    }
+    return -1;
+}
+
+/*
+ *  Arduionピン、IOピン変換
+ */
+uint8_t
+getGpioPin(uint8_t no)
+{
+	return _maixduino_pin_map[no];
+}
+
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/pinmode.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/pinmode.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/pinmode.h	(revision 453)
@@ -0,0 +1,85 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ *
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+ *
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ *
+ *  $Id$
+ */
+
+/*
+ *	ARDUNO-PINドライバのヘッダファイル
+ */
+
+#ifndef _PINMODE_H_
+#define _PINMODE_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include "device.h"
+
+
+#define HIGH 0x1
+#define LOW  0x0
+
+#define INPUT           0x0
+#define OUTPUT          0x3
+#define INPUT_PULLUP    0x2
+#define INPUT_PULLDOWN  0X1
+
+
+#ifndef TOPPERS_MACRO_ONLY
+/*
+ *  関数のプロトタイプ宣言
+ */
+
+extern void pinMode( uint8_t dwPin, uint8_t dwMode);
+extern int  digitalRead(uint8_t no);
+extern void digitalWrite(uint8_t no, int sw);
+extern uint8_t getGpioPin(uint8_t no);
+
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _PINMODE_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/spi.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/spi.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/spi.c	(revision 453)
@@ -0,0 +1,799 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ * 
+ *  SPIドライバ関数群
+ *
+ */
+#include "kernel_impl.h"
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <string.h>
+#include <sil.h>
+#include <target_syssvc.h>
+#include "device.h"
+#include "spi.h"
+
+Inline uint64_t
+sil_rel_mem(const uint64_t *mem)
+{
+	uint64_t	data;
+
+	data = *((const volatile uint64_t *) mem);
+	return(data);
+}
+
+#define sil_orw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) | (b))
+#define sil_andw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) & ~(b))
+#define sil_modw_mem(a, b, c)	sil_wrw_mem((a), (sil_rew_mem(a) & (~b)) | (c))
+
+/*
+ *  SPIOポートIDから管理ブロックを取り出すためのマクロ
+ */
+#define INDEX_SPI(spiid)        ((uint_t)((spiid) - 1))
+
+#define get_framewidth(l)       (((l)+7)/8)
+
+#define SPI_SSIENR_DISABLE      0x00000000
+#define SPI_SSIENR_ENABLE       0x00000001
+
+#define SPI_DMACR_RXENABLE      0x00000001
+#define SPI_DMACR_TXENABLE      0x00000002
+
+/*
+ *  SPIハードウェア設定構造体
+ */
+
+typedef struct _SPI_PortControlBlock{
+	unsigned long         base;
+	int16_t               func_data;
+	int16_t               func_ss;
+	int16_t               func_arb;
+	int16_t               func_sclk;
+} SPI_PortControlBlock;
+
+static const SPI_PortControlBlock spi_pcb[NUM_SPIPORT] = {
+	{TADR_SPI0_BASE, FUNC_SPI0_D0,      FUNC_SPI0_SS0,     FUNC_SPI0_ARB, FUNC_SPI0_SCLK     },
+	{TADR_SPI1_BASE, FUNC_SPI1_D0,      FUNC_SPI1_SS0,     FUNC_SPI1_ARB, FUNC_SPI1_SCLK     },
+	{TADR_SPIS_BASE, FUNC_SPI_SLAVE_D0, FUNC_SPI_SLAVE_SS, -1,            FUNC_SPI_SLAVE_SCLK},
+	{TADR_SPI2_BASE, -1,                -1,                -1,            -1                 }
+};
+
+SPI_Handle_t SpiHandle[NUM_SPIPORT];
+DMA_Handle_t spi_dma_handle[NUM_SPIPORT][2];
+
+
+/*
+ *  転送モード設定
+ */
+static ER
+spi_set_tmod(SPI_Handle_t *hspi, uint32_t tmod)
+{
+	SPI_Init_t *init;
+    uint32_t inst_l = 4;
+    uint32_t addr_l;
+
+	init = &hspi->Init;
+    switch (init->InstLength){
+	case 0:
+		inst_l = 0;
+		break;
+	case 4:
+		inst_l = 1;
+		break;
+	case 8:
+		inst_l = 2;
+		break;
+	case 16:
+		inst_l = 3;
+		break;
+	default:
+		break;
+    }
+	if(inst_l == 4)
+		return E_PAR;
+
+	addr_l = init->AddrLength / 4;
+	sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_CTRLR0), (init->WorkMode << hspi->work_mode_offset) | \
+		(init->FrameFormat << hspi->frf_offset) | ((init->DataSize - 1) << hspi->dfs_offset));
+	sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SPI_CTRLR0),
+		((init->WaitCycles << 11) | (inst_l << 8) | (addr_l << 2) | init->IATransMode));
+	sil_modw_mem((uint32_t *)(hspi->base+TOFF_SPI_CTRLR0), (3 << hspi->tmod_offset), (tmod << hspi->tmod_offset));
+	return E_OK;
+}
+
+/*
+ *  DMAコールバック関数
+ */
+static void
+spi_dma_comp(DMA_Handle_t *hdma)
+{
+	SPI_Handle_t *hspi = (SPI_Handle_t *)hdma->localdata;
+	if(hspi != NULL && hspi->Init.semdmaid != 0){
+		isig_sem(hspi->Init.semdmaid);
+	}
+}
+
+/*
+ *  DMA転送開始関数
+ */
+DMA_Handle_t *
+spi_dmac_set_single_mode(SPI_Handle_t *hspi, uint8_t rtx,
+						  int8_t  ss_no, const void *src, void *dest,
+						  uint8_t src_inc, uint8_t dest_inc,
+                          uint8_t dmac_burst_size, uint8_t dmac_trans_width,
+                          size_t block_size)
+{
+	DMA_Handle_t *hdma;
+    int mem_type_src, mem_type_dest;
+    uint8_t flow_control;
+
+	if(rtx == 0){
+		hdma = hspi->hdmatx;
+        flow_control = DMA_MEMORY_TO_PERIPH;
+		mem_type_src = 1;
+		mem_type_dest = 0;
+	}
+	else{
+		hdma = hspi->hdmarx;
+        flow_control = DMA_PERIPH_TO_MEMORY;
+		mem_type_src = 0;
+		mem_type_dest = 1;
+	}
+	if(ss_no < 0)
+		ss_no = 0;
+
+	hdma->Init.Direction    = flow_control;	/* DMA転送方向 */
+	hdma->Init.SrcHandShake = (mem_type_src ? DMAC_HS_SOFTWARE : DMAC_HS_HARDWARE);	/* ソースハンドシェイク */
+	hdma->Init.DrcHandShake = (mem_type_dest ? DMAC_HS_SOFTWARE : DMAC_HS_HARDWARE);	/* デスティネーションハンドシェイク */
+	hdma->Init.SrcInc       = src_inc;	/* ソースインクリメント設定 */
+	hdma->Init.DstInc       = dest_inc;	/* デスティネーションインクリメント設定 */
+	hdma->Init.SrcTransWidth = dmac_trans_width;	/* ソース転送幅 */
+	hdma->Init.DstTransWidth = dmac_trans_width;	/* デスティネーション転送幅 */
+	hdma->Init.SrcBurstSize = dmac_burst_size;	/* ソースバーストサイズ */
+	hdma->Init.DstBurstSize = dmac_burst_size;	/* デスティネーションバーストサイズ */
+	dma_reset(hdma);
+	sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SER), (1 << ss_no));
+	dma_start(hdma, (uintptr_t)src, (uintptr_t)dest, block_size);
+	return hdma;
+}
+
+/*
+ *  SPI-DMA転送終了待ち
+ */
+ER
+spi_dmac_wait_done(DMA_Handle_t * hdma)
+{
+	SPI_Handle_t *hspi = (SPI_Handle_t *)hdma->localdata;
+	ER ercd = E_OK;
+	int tick = DMA_TRS_TIMEOUT;
+
+	while((hdma->status == DMA_STATUS_BUSY) && tick > 0){
+		if(hspi != NULL && hspi->Init.semdmaid != 0){
+	 		ercd = twai_sem(hspi->Init.semdmaid, 5);
+		}
+		else
+			dly_tsk(1);
+		tick--;
+	}
+	dma_end(hdma);
+	if(hdma->ErrorCode != 0)
+		ercd = E_OBJ;
+	else if(tick == 0)
+		ercd = E_TMOUT;
+	return ercd;
+}
+
+/*
+ *  SPI内部転送終了待ち
+ */
+ER
+spi_inwait(SPI_Handle_t *hspi, uint32_t timeout)
+{
+	ER ercd = E_OK;
+	int tick = timeout;
+
+	sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_IMR), 0x0011);
+    while((sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_SR)) & 0x05) != 0x04 && tick > 0){
+		if(hspi->Init.semid != 0)
+			twai_sem(hspi->Init.semid, 5);
+		else
+			dly_tsk(1);
+		tick--;
+	}
+	sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SER), 0x00000000);
+	sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SSIENR), SPI_SSIENR_DISABLE);
+
+	if(hspi->ErrorCode != 0)
+		ercd = E_OBJ;
+	else if(tick == 0)
+		ercd = E_TMOUT;
+	hspi->TxXferCount = 0;
+	hspi->RxXferCount = 0;
+	return ercd;
+}
+
+
+/*
+ *  SPI初期設定
+ *  parameter1  port: SPIポート番号
+ *  parameter2  spii: SPI初期設定構造体へのポインタ
+ *  return SPIハンドラへのポインタ、NULLでエラー
+ */
+SPI_Handle_t *
+spi_init(ID port, const SPI_Init_t *init)
+{
+	SPI_Handle_t *hspi;
+	DMA_Handle_t *hdma;
+	const SPI_PortControlBlock *spcb;
+	unsigned long base;
+	uint8_t  spi_num;
+	uint32_t spi_baudr, clk_th1, threshold;
+    uint8_t  dfs_offset, frf_offset, work_mode_offset, tmod_offset;
+	uint32_t dsize_err = 0;
+    uint32_t inst_l = 4;
+    uint32_t addr_l;
+
+	if(port < SPI1_PORTID || port > NUM_SPIPORT)
+		return NULL;
+	spi_num = INDEX_SPI(port);
+	if(init == NULL)
+		return NULL;
+	if(init->DataSize < 4 && init->DataSize > 32)
+		return NULL;
+	if(init->AddrLength % 4 != 0 && init->AddrLength > 60)
+		return NULL;
+
+	/*
+	 *  クロック設定
+	 */
+    if(spi_num == 3){
+		sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_CLK_SEL0), SYSCTL_CLK_SEL0_SPI3_CLK_SEL);
+	}
+	if(spi_num < 2)
+		sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_CENT), SYSCTL_CLK_EN_CENT_APB2_CLK_EN);
+	else if(spi_num == 2)
+		sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_CENT), SYSCTL_CLK_EN_CENT_APB0_CLK_EN);
+	sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_PERI), (SYSCTL_CLK_EN_PERI_SPI0_CLK_EN<<spi_num));
+	sil_andw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_TH1), 0xFF << (spi_num*8));
+
+	/*
+	 *  ピンファンクション設定
+	 */
+	spcb = &spi_pcb[spi_num];
+	if(spcb->func_ss >= 0 && init->SsPin >= 0)
+		fpioa_set_function(init->SsPin, (uint8_t)(spcb->func_ss + init->SsNo));
+	if(spcb->func_sclk >= 0 && init->SclkPin >= 0)
+		fpioa_set_function(init->SclkPin, (uint8_t)(spcb->func_sclk));
+	if(spcb->func_data >= 0){
+		if(init->MosiPin >= 0)
+			fpioa_set_function(init->MosiPin, (uint8_t)(spcb->func_data));
+		if(init->MisoPin >= 0)
+			fpioa_set_function(init->MisoPin, (uint8_t)(spcb->func_data+1));
+
+	}
+	hspi = &SpiHandle[spi_num];
+	base = spcb->base;
+
+    switch(spi_num){
+	case 0:
+	case 1:
+		dfs_offset = 16;
+		frf_offset = 21;
+		work_mode_offset = 6;
+		tmod_offset = 8;
+		break;
+	case 3:
+	default:
+		dfs_offset = 0;
+		frf_offset = 22;
+		work_mode_offset = 8;
+		tmod_offset = 10;
+		break;
+	}
+
+	switch(init->FrameFormat){
+	case SPI_FF_DUAL:
+		if(init->DataSize % 2 != 0)
+			dsize_err = 1;
+		break;
+	case SPI_FF_QUAD:
+		if(init->DataSize % 4 != 0)
+			dsize_err = 1;
+		break;
+	case SPI_FF_OCTAL:
+		if(init->DataSize % 8 != 0)
+			dsize_err = 1;
+		break;
+	default:
+		break;
+	}
+
+	switch(init->InstLength){
+	case 0:
+		inst_l = 0;
+		break;
+	case 4:
+		inst_l = 1;
+		break;
+	case 8:
+		inst_l = 2;
+		break;
+	case 16:
+		inst_l = 3;
+		break;
+	default:
+		break;
+	}
+	if(inst_l == 4 || dsize_err){
+		syslog_0(LOG_ERROR, "Invalid instruction length");
+		return NULL;
+	}
+	addr_l = init->AddrLength / 4;
+
+	memcpy(&hspi->Init, init, sizeof(SPI_Init_t));
+
+    if(sil_rew_mem((uint32_t *)(base+TOFF_SPI_BAUDR)) == 0)
+		sil_wrw_mem((uint32_t *)(base+TOFF_SPI_BAUDR), 0x14);
+	/*
+	 *  割込み不許可
+	 */
+	sil_wrw_mem((uint32_t *)(base+TOFF_SPI_IMR), 0x00000000);
+
+	sil_wrw_mem((uint32_t *)(base+TOFF_SPI_DMACR), 0x00000000);
+	sil_wrw_mem((uint32_t *)(base+TOFF_SPI_DMATDLR), 0x00000010);
+	sil_wrw_mem((uint32_t *)(base+TOFF_SPI_DMARDLR), 0x00000000);
+	sil_wrw_mem((uint32_t *)(base+TOFF_SPI_SER), 0x00000000);
+	sil_wrw_mem((uint32_t *)(base+TOFF_SPI_SSIENR), SPI_SSIENR_DISABLE);
+	sil_wrw_mem((uint32_t *)(base+TOFF_SPI_CTRLR0), (init->WorkMode << work_mode_offset) | \
+		(init->FrameFormat << frf_offset) | ((init->DataSize - 1) << dfs_offset));
+	sil_wrw_mem((uint32_t *)(base+TOFF_SPI_SPI_CTRLR0),
+		((init->WaitCycles << 11) | (inst_l << 8) | (addr_l << 2) | init->IATransMode));
+	sil_wrw_mem((uint32_t *)(base+TOFF_SPI_ENDIAN), init->SignBit);
+
+	/*
+	 *  転送クロック設定
+	 */
+	clk_th1 = sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_TH1));
+	threshold = (clk_th1 >> (spi_num * 8)) & 0xff;
+	spi_baudr = (get_pll_clock(0) / ((threshold + 1) * 2)) / init->Prescaler;
+
+
+	if(spi_baudr < 2 ){
+		spi_baudr = 2;
+	}
+	else if(spi_baudr > 65534){
+		spi_baudr = 65534;
+	}
+	sil_wrw_mem((uint32_t *)(base+TOFF_SPI_BAUDR), spi_baudr);
+
+	/*
+	 *  ハンドラ初期化
+	 */
+	hspi->base = base;
+	hspi->spi_num = spi_num;
+	hspi->dfs_offset  = dfs_offset;
+	hspi->frf_offset  = frf_offset;
+	hspi->work_mode_offset = work_mode_offset;
+	hspi->tmod_offset = tmod_offset;
+	hspi->hdmatx = NULL;
+	hspi->hdmarx = NULL;
+	if(init->TxDMAChannel >= 0){
+		hdma = &spi_dma_handle[init->TxDMAChannel][0];
+		hdma->chnum = init->TxDMAChannel;
+		if(init->RxDMAChannel >= 0)
+			hdma->xfercallback      = NULL;
+		else
+			hdma->xfercallback      = spi_dma_comp;
+		hdma->errorcallback     = NULL;
+		hdma->Init.Request      = DMA_SELECT_SSI0_TX_REQ + spi_num * 2;	/* DMA選択 */
+		hdma->Init.Direction    = DMA_MEMORY_TO_PERIPH;	/* DMA転送方向 */
+		hdma->Init.SrcMultBlock = DMAC_MULTBLOCK_CONT;	/* ソースマルチブロックタイプ */
+		hdma->Init.DrcMultBlock = DMAC_MULTBLOCK_CONT;	/* デスティネーションマルチブロックタイプ */
+		hdma->Init.SrcHandShake = DMAC_HS_SOFTWARE;	/* ソースハンドシェイク */
+		hdma->Init.DrcHandShake = DMAC_HS_HARDWARE;	/* デスティネーションハンドシェイク */
+		hdma->Init.SrcHwhsPol   = DMAC_HWHS_POLARITY_LOW;	/* ソースハードウェアハンドシェイク極性 */
+		hdma->Init.DrcHwhsPol   = DMAC_HWHS_POLARITY_LOW;	/* デスティネーションハードウェアハンドシェイク極性 */
+		hdma->Init.Priority     = 4;	/* 優先度 */
+		hdma->Init.SrcMaster    = DMAC_MASTER1;	/* ソースマスター設定 */
+		hdma->Init.DstMaster    = DMAC_MASTER2;	/* デスティネーションマスター設定 */
+		hdma->Init.SrcInc       = DMAC_ADDR_INCREMENT;	/* ソースインクリメント設定 */
+		hdma->Init.DstInc       = DMAC_ADDR_NOCHANGE;	/* デスティネーションインクリメント設定 */
+		hdma->Init.SrcTransWidth = DMAC_TRANS_WIDTH_32;	/* ソース転送幅 */
+		hdma->Init.DstTransWidth = DMAC_TRANS_WIDTH_32;	/* デスティネーション転送幅 */
+		hdma->Init.SrcBurstSize = DMAC_MSIZE_4;	/* ソースバーストサイズ */
+		hdma->Init.DstBurstSize = DMAC_MSIZE_4;	/* デスティネーションバーストサイズ */
+		hdma->Init.IocBlkTrans  = 0;	/* IOCブロック転送 */
+		hdma->localdata         = (void *)hspi;
+		dma_init(hdma);
+		hspi->hdmatx = hdma;
+	}
+	if(init->RxDMAChannel >= 0){
+		hdma = &spi_dma_handle[init->RxDMAChannel][1];
+		hdma->chnum = init->RxDMAChannel;
+		hdma->xfercallback      = spi_dma_comp;
+		hdma->errorcallback     = NULL;
+		hdma->Init.Request      = DMA_SELECT_SSI0_RX_REQ + spi_num * 2;	/* DMA選択 */
+		hdma->Init.Direction    = DMA_PERIPH_TO_MEMORY;	/* DMA転送方向 */
+		hdma->Init.SrcMultBlock = DMAC_MULTBLOCK_CONT;	/* ソースマルチブロックタイプ */
+		hdma->Init.DrcMultBlock = DMAC_MULTBLOCK_CONT;	/* デスティネーションマルチブロックタイプ */
+		hdma->Init.SrcHandShake = DMAC_HS_HARDWARE;	/* ソースハンドシェイク */
+		hdma->Init.DrcHandShake = DMAC_HS_SOFTWARE;	/* デスティネーションハンドシェイク */
+		hdma->Init.SrcHwhsPol   = DMAC_HWHS_POLARITY_LOW;	/* ソースハードウェアハンドシェイク極性 */
+		hdma->Init.DrcHwhsPol   = DMAC_HWHS_POLARITY_LOW;	/* デスティネーションハードウェアハンドシェイク極性 */
+		hdma->Init.Priority     = 4;	/* 優先度 */
+		hdma->Init.SrcMaster    = DMAC_MASTER1;	/* ソースマスター設定 */
+		hdma->Init.DstMaster    = DMAC_MASTER2;	/* デスティネーションマスター設定 */
+		hdma->Init.SrcInc       = DMAC_ADDR_NOCHANGE;	/* ソースインクリメント設定 */
+		hdma->Init.DstInc       = DMAC_ADDR_INCREMENT;	/* デスティネーションインクリメント設定 */
+		hdma->Init.SrcTransWidth = DMAC_TRANS_WIDTH_32;	/* ソース転送幅 */
+		hdma->Init.DstTransWidth = DMAC_TRANS_WIDTH_32;	/* デスティネーション転送幅 */
+		hdma->Init.SrcBurstSize = DMAC_MSIZE_4;	/* ソースバーストサイズ */
+		hdma->Init.DstBurstSize = DMAC_MSIZE_4;	/* デスティネーションバーストサイズ */
+		hdma->Init.IocBlkTrans  = 0;	/* IOCブロック転送 */
+		hdma->localdata         = (void *)hspi;
+		dma_init(hdma);
+		hspi->hdmarx = hdma;
+	}
+	hspi->status = SPI_STATUS_READY;
+	hspi->xmode  = 0;
+	return hspi;
+}
+
+/*
+ *  SPI終了設定
+ *  parameter1  hspi: SPIハンドラへのポインタ
+ *  return ERコード
+ */
+ER
+spi_deinit(SPI_Handle_t *hspi)
+{
+	if(hspi == NULL)
+		return E_PAR;
+
+	if(hspi->hdmatx != NULL){
+		dma_deinit(hspi->hdmatx);
+		hspi->hdmatx = NULL;
+	}
+	if(hspi->hdmarx != NULL){
+		dma_deinit(hspi->hdmarx);
+		hspi->hdmarx = NULL;
+	}
+	sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SSIENR), SPI_SSIENR_DISABLE);
+
+	hspi->ErrorCode = SPI_ERROR_NONE;
+	hspi->status = SPI_STATUS_RESET;
+	return E_OK;
+}
+
+/*
+ *  ポーリングデータ送信
+ */
+static void
+spi_send_data_normal2(SPI_Handle_t *hspi, int8_t ss_no, const uint8_t *tx_buff, size_t tx_len)
+{
+	size_t index, fifo_len;
+	uint8_t frame_width = get_framewidth(hspi->Init.DataSize);
+	uint8_t v_misalign_flag = 0;
+	uint32_t v_send_data;
+	uint32_t i = 0;
+
+	if((uintptr_t)tx_buff % frame_width){
+		v_misalign_flag = 1;
+	}
+	if(ss_no < 0)
+		ss_no = 0;
+
+	sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SSIENR), SPI_SSIENR_ENABLE);
+	sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SER), (1 << ss_no));
+	while(tx_len > 0){
+		fifo_len = 32 - sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_TXFLR));
+		fifo_len = fifo_len < tx_len ? fifo_len : tx_len;
+		switch(frame_width){
+		case SPI_TRANS_INT:
+			fifo_len = fifo_len / 4 * 4;
+			if(v_misalign_flag){
+				for(index = 0; index < fifo_len; index +=4){
+					memcpy(&v_send_data, tx_buff + i , 4);
+					sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_DR), v_send_data);
+					i += 4;
+				}
+			}
+			else{
+				for(index = 0; index < fifo_len / 4; index++)
+					sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_DR), ((uint32_t *)tx_buff)[i++]);
+			}
+			break;
+		case SPI_TRANS_SHORT:
+			fifo_len = fifo_len / 2 * 2;
+			if(v_misalign_flag){
+				for(index = 0; index < fifo_len; index +=2){
+					memcpy(&v_send_data, tx_buff + i, 2);
+					sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_DR), v_send_data);
+					i += 2;
+				}
+			}
+			else{
+				for(index = 0; index < fifo_len / 2; index++)
+					sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_DR), ((uint16_t *)tx_buff)[i++]);
+			}
+			break;
+		default:
+			for(index = 0; index < fifo_len; index++)
+				sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_DR), tx_buff[i++]);
+			break;
+ 		}
+		tx_len -= fifo_len;
+	}
+}
+
+/*
+ *  SPI送信実行関数
+ *  parameter1  hspi: SPIハンドラへのポインタ
+ *  parameter2  ss_no: SS番号
+ *  parameter3  pdata: 送信バッファへのポインタ
+ *  parameter4  length: 送信サイズ
+ *  return ERコード
+ */
+ER
+spi_core_transmit(SPI_Handle_t *hspi, int8_t ss_no, uint8_t *pdata, uint16_t length)
+{
+	DMA_Handle_t *hdma;
+	ER ercd = E_OK;
+
+	if(hspi == NULL)
+		return E_PAR;
+
+	if(hspi->Init.semlock != 0)
+		wai_sem(hspi->Init.semlock);
+	hspi->xmode = SPI_XMODE_TX;
+    spi_set_tmod(hspi, SPI_TMOD_TRANS);
+	if(hspi->hdmatx != NULL){
+		sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_DMACR), SPI_DMACR_TXENABLE);
+		sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SSIENR), SPI_SSIENR_ENABLE);
+		hdma = spi_dmac_set_single_mode(hspi, 0, ss_no, (const void *)pdata, 
+							(void *)(hspi->base+TOFF_SPI_DR), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE,
+							DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, length);
+		spi_dmac_wait_done(hdma);
+	}
+	else{
+		spi_send_data_normal2(hspi, ss_no, (const void *)pdata, length);
+	}
+
+#if SPI_WAIT_TIME != 0
+	ercd = spi_inwait(hspi, SPI_WAIT_TIME * length);
+
+	if(hspi->Init.semlock != 0)
+		sig_sem(hspi->Init.semlock);
+#endif
+	return ercd;
+}
+
+/*
+ *  SPIフィル送信実行関数
+ *  parameter1  hspi: SPIハンドラへのポインタ
+ *  parameter2  ss_no: SS番号
+ *  parameter3  pdata: 送信バッファへのポインタ
+ *  parameter4  length: 送信サイズ
+ *  return ERコード
+ */
+ER
+spi_core_transmit_fill(SPI_Handle_t *hspi, int8_t ss_no, const uint32_t *tx_buff, size_t tx_len)
+{
+	DMA_Handle_t *hdmatx;
+	ER ercd = E_OK;
+
+	if(hspi == NULL)
+		return E_PAR;
+
+	if(hspi->Init.semlock != 0)
+		wai_sem(hspi->Init.semlock);
+
+	hspi->xmode = SPI_XMODE_TX;
+	spi_set_tmod(hspi, SPI_TMOD_TRANS);
+	sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_DMACR), SPI_DMACR_TXENABLE);
+	sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SSIENR), SPI_SSIENR_ENABLE);
+
+    hdmatx = spi_dmac_set_single_mode(hspi, 0, ss_no, tx_buff, (void *)(hspi->base+TOFF_SPI_DR), DMAC_ADDR_NOCHANGE, DMAC_ADDR_NOCHANGE,
+                                DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, tx_len);
+    spi_dmac_wait_done(hdmatx);
+
+#if SPI_WAIT_TIME != 0
+	ercd = spi_inwait(hspi, SPI_WAIT_TIME * tx_len);
+
+	if(hspi->Init.semlock != 0)
+		sig_sem(hspi->Init.semlock);
+#endif
+	return ercd;
+}
+
+/*
+ *  SPI受信実行関数
+ *  parameter1  hspi: SPIハンドラへのポインタ
+ *  parameter2  ss_no: SS番号
+ *  parameter3  pdata: 受信バッファへのポインタ
+ *  parameter4  length: 受信サイズ
+ *  return ERコード
+ */
+ER
+spi_core_receive(SPI_Handle_t *hspi, int8_t ss_no, void *rx_buff, size_t rx_len)
+{
+	DMA_Handle_t * hdmarx;
+	ER ercd = E_OK;
+
+	if(hspi == NULL || hspi->spi_num == 2)
+		return E_PAR;
+
+	if(hspi->Init.semlock != 0)
+		wai_sem(hspi->Init.semlock);
+
+	hspi->xmode = SPI_XMODE_RX;
+	spi_set_tmod(hspi, SPI_TMOD_RECV);
+
+	sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_CTRLR1), (rx_len - 1));
+	sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_DMACR), SPI_DMACR_RXENABLE);
+	sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SSIENR), SPI_SSIENR_ENABLE);
+
+    hdmarx = spi_dmac_set_single_mode(hspi, 1, ss_no, (void *)(hspi->base+TOFF_SPI_DR), rx_buff, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
+                           DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, rx_len);
+    if(hspi->Init.FrameFormat == SPI_FF_STANDARD)
+		sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_DR), 0xFFFFFFFF);
+    spi_dmac_wait_done(hdmarx);
+
+	sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SER), 0x00000000);
+	sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SSIENR), SPI_SSIENR_DISABLE);
+
+#if SPI_WAIT_TIME != 0
+	ercd = spi_inwait(hspi, SPI_WAIT_TIME * rx_len);
+
+	if(hspi->Init.semlock != 0)
+		sig_sem(hspi->Init.semlock);
+#endif
+	return ercd;
+}
+
+/*
+ *  SPI送受信実行関数
+ *  parameter1  hspi: SPIハンドラへのポインタ
+ *  parameter2  ss_no: SS番号
+ *  parameter3  ptxdata: 送信バッファへのポインタ
+ *  parameter4  prxdata: 受信バッファへのポインタ
+ *  parameter5  length: 送受信サイズ
+ *  return ERコード
+ */
+ER
+spi_core_transrecv(SPI_Handle_t *hspi, int8_t ss_no, const uint8_t *tx_buf, uint8_t *rx_buf, size_t len)
+{
+	DMA_Handle_t * hdmarx, *hdmatx;
+    uint8_t frame_width = get_framewidth(hspi->Init.DataSize);
+    size_t v_len = len / frame_width;
+	ER ercd = E_OK;
+
+	if(hspi == NULL)
+		return E_PAR;
+
+	if(hspi->Init.semlock != 0)
+		wai_sem(hspi->Init.semlock);
+
+	hspi->xmode = SPI_XMODE_TXRX;
+    spi_set_tmod(hspi, SPI_TMOD_TRANS_RECV);
+
+
+	if(hspi->hdmatx != NULL){
+		sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_DMACR), (SPI_DMACR_TXENABLE | SPI_DMACR_RXENABLE));
+		sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SSIENR), SPI_SSIENR_ENABLE);
+
+	    hdmarx = spi_dmac_set_single_mode(hspi, 1, ss_no, (void *)(hspi->base+TOFF_SPI_DR), rx_buf, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
+                           DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, v_len);
+	    hdmatx = spi_dmac_set_single_mode(hspi, 0, -1, tx_buf, (void *)(hspi->base+TOFF_SPI_DR), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE,
+                           DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, v_len);
+
+	    spi_dmac_wait_done(hdmatx);
+	}
+	else{
+		sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_DMACR), SPI_DMACR_RXENABLE);
+		sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SSIENR), SPI_SSIENR_ENABLE);
+
+	    hdmarx = spi_dmac_set_single_mode(hspi, 1, ss_no, (void *)(hspi->base+TOFF_SPI_DR), rx_buf, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
+                           DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, v_len);
+		spi_send_data_normal2(hspi, -1, (const void *)tx_buf, len);
+	}
+	spi_dmac_wait_done(hdmarx);
+
+	sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SER), 0x00000000);
+	sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_SSIENR), SPI_SSIENR_DISABLE);
+
+#if SPI_WAIT_TIME != 0
+	ercd = spi_inwait(hspi, SPI_WAIT_TIME * len);
+
+	if(hspi->Init.semlock != 0)
+		sig_sem(hspi->Init.semlock);
+#endif
+	return ercd;
+}
+
+/*
+ *  SPI転送終了待ち
+ */
+ER
+spi_wait(SPI_Handle_t *hspi, uint32_t timeout)
+{
+	ER ercd = E_OK;
+
+#if SPI_WAIT_TIME == 0
+	if(hspi == NULL)
+		return E_PAR;
+	ercd = spi_inwait(hspi, timeout);
+	if(hspi->Init.semlock != 0)
+		sig_sem(hspi->Init.semlock);
+#endif
+	return ercd;
+}
+
+
+/*
+ *  SPI割込みサービスルーチン
+ */
+void
+spi_handler(SPI_Handle_t *hspi)
+{
+	volatile uint32_t imr, isr, tmp;
+
+	imr = sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_IMR));
+	isr = sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_ISR));
+	sil_wrw_mem((uint32_t *)(hspi->base+TOFF_SPI_IMR), 0);
+
+	syslog_2(LOG_DEBUG, "spi_handler imr[%08x] isr[%08x]", imr, isr);
+	tmp = sil_rew_mem((uint32_t *)(hspi->base+TOFF_SPI_ICR));
+	if(hspi->Init.semid != 0)
+		isig_sem(hspi->Init.semid);
+	(void)(tmp);
+}
+
+/*
+ *  SPI割込みサービスルーチン
+ */
+void spi_isr(intptr_t exinf)
+{
+  spi_handler(&SpiHandle[INDEX_SPI((uint32_t)exinf)]);
+}
+
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/spi.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/spi.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/spi.h	(revision 453)
@@ -0,0 +1,219 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ * 
+ *  K210 SPIデバイスドライバの外部宣言
+ *
+ */
+
+#ifndef _SPI_H_
+#define _SPI_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*
+ *  SPIポート定義
+ */
+#define SPI1_PORTID             1
+#define SPI2_PORTID             2
+#define SPI3_PORTID             3
+#define SPI4_PORTID             3
+#define NUM_SPIPORT             4
+
+
+/*
+ *  SPI状態定義
+ */
+#define SPI_STATUS_RESET        0x0000	/* SPI未使用状態 */
+#define SPI_STATUS_READY        0x0001	/* SPIレディ状態 */
+#define SPI_STATUS_ERROR        0x0002	/* SPIエラー状態 */
+#define SPI_STATUS_BUSY         0x0004	/* SPI処理中 */
+
+/*
+ *  SPI転送モード
+ */
+#define SPI_XMODE_TX            0x0000	/* 送信モード */
+#define SPI_XMODE_RX            0x0001	/* 受信モード */
+#define SPI_XMODE_TXRX          0x0002	/* 送受信モード */
+
+/*
+ *  SPIエラー定義
+ */
+#define SPI_ERROR_NONE          0x00000000	/* No error */
+#define SPI_ERROR_MODF          0x00000001	/* MODF error */
+#define SPI_ERROR_CRC           0x00000002	/* CRC error */
+#define SPI_ERROR_OVR           0x00000004	/* OVR error */
+#define SPI_ERROR_FRE           0x00000008	/* FRE error */
+#define SPI_ERROR_DMA           0x00000010	/* DMA transfer error */
+#define SPI_ERROR_TIMEOUT       0x00000020
+
+/*
+ *  SPIワークモード定義
+ */
+#define SPI_WORK_MODE_0         0x00000000
+#define SPI_WORK_MODE_1         0x00000001
+#define SPI_WORK_MODE_2         0x00000002
+#define SPI_WORK_MODE_3         0x00000003
+
+/*
+ *  SPIフレームフォーマット定義
+ */
+#define SPI_FF_STANDARD         0x00000000
+#define SPI_FF_DUAL             0x00000001
+#define SPI_FF_QUAD             0x00000002
+#define SPI_FF_OCTAL            0x00000003
+
+/*
+ *  SPIインストラクションアドレスモード
+ */
+#define SPI_AITM_STANDARD        0x00000000
+#define SPI_AITM_ADDR_STANDARD   0x00000001
+#define SPI_AITM_AS_FRAME_FORMAT 0x00000002
+
+
+/*
+ *  SPI転送モード定義
+ */
+#define SPI_TMOD_TRANS_RECV     0x00000000
+#define SPI_TMOD_TRANS          0x00000001
+#define SPI_TMOD_RECV           0x00000002
+#define SPI_TMOD_EEROM          0x00000003
+
+/*
+ *  SPI転送データ長定義
+ */
+#define SPI_TRANS_CHAR          0x01
+#define SPI_TRANS_SHORT         0x02
+#define SPI_TRANS_INT           0x04
+
+/*
+ *  SPI CS選択定義
+ */
+#define SPI_CHIP_SELECT_0       0x00
+#define SPI_CHIP_SELECT_1       0x01
+#define SPI_CHIP_SELECT_2       0x02
+#define SPI_CHIP_SELECT_3       0x03
+#define SPI_CHIP_SELECT_MAX     4
+
+/*
+ *  SPI 設定初期設定構造体
+ */
+typedef struct
+{
+	uint32_t              WorkMode;
+	uint32_t              FrameFormat;
+    uint32_t              DataSize;			/* SPI転送データサイズ */
+	uint32_t              Prescaler;		/* SPIクロック分周設定 */
+	uint32_t              SignBit;			/* SPI MSB/LSB設定 */
+	uint32_t              InstLength;		/* SPI Instraction Length */
+	uint32_t              AddrLength;		/* SPI Address Length */
+	uint32_t              WaitCycles;		/* SPI WaitCycles */
+	uint32_t              IATransMode;		/* SPI 転送モード */
+	int32_t               SclkPin;			/* SPI SCLK-PIN */
+	int32_t               MosiPin;			/* SPI MOSI-PIN */
+	int32_t               MisoPin;			/* SPI MISO-PIN */
+	int32_t               SsPin;			/* SPI Slave Select-PIN */
+	int32_t               SsNo;				/* SPI Slave Select-Number */
+	int32_t               TxDMAChannel;		/* SPI TxDMAチャンネル */
+	int32_t               RxDMAChannel;		/* SPI RxDMAチャンネル */
+	int                   semid;			/* SPI 通信用セマフォ値 */
+	int                   semlock;			/* SPI ロックセマフォ値 */
+	int                   semdmaid;			/* SPI DMA通信用セマフォ値 */
+}SPI_Init_t;
+
+/*
+ *  SPIハンドラ
+ */
+typedef struct _SPI_Handle_t
+{
+	unsigned long         base;				/* SPI registers base address */
+	SPI_Init_t            Init;				/* SPI communication parameters */
+	uint8_t               spi_num;
+	uint8_t               dfs_offset;
+	uint8_t               frf_offset;
+	uint8_t               work_mode_offset;
+	uint8_t               tmod_offset;
+	uint8_t               dummy[3];
+	uint8_t               *pTxBuffPtr;		/* Pointer to SPI Tx transfer Buffer */
+	uint32_t              TxXferSize;		/* SPI Tx transfer size */
+	uint32_t              TxXferCount;		/* SPI Tx Transfer Counter */
+	uint8_t               *pRxBuffPtr;		/* Pointer to SPI Rx transfer Buffer */
+	uint32_t              RxXferSize;		/* SPI Rx transfer size */
+	uint32_t              RxXferCount;		/* SPI Rx Transfer Counter */
+	DMA_Handle_t          *hdmatx;			/* SPI Tx DMA handle parameters */
+	DMA_Handle_t          *hdmarx;			/* SPI Rx DMA handle parameters */
+	uint16_t              xmode;			/* SPI Transfar mode */
+	volatile uint16_t     status;			/* SPI communication state */
+	volatile uint32_t     ErrorCode;		/* SPI Error code */
+}SPI_Handle_t;
+
+
+extern SPI_Handle_t *spi_init(ID port, const SPI_Init_t *init);
+extern ER spi_deinit(SPI_Handle_t *hspi);
+extern ER spi_core_transmit(SPI_Handle_t *hspi, int8_t ss_no, uint8_t *pdata, uint16_t length);
+extern ER spi_core_transmit_fill(SPI_Handle_t *hspi, int8_t ss_no, const uint32_t *tx_buff, size_t tx_len);
+extern ER spi_core_receive(SPI_Handle_t *hspi, int8_t ss_no, void *rx_buff, size_t rx_len);
+extern ER spi_core_transrecv(SPI_Handle_t *hspi, int8_t ss_no, const uint8_t *tx_buf, uint8_t *rx_buf, size_t len);
+extern ER spi_transmit(SPI_Handle_t *hspi, uint8_t *pdata, uint16_t length);
+extern ER spi_receive(SPI_Handle_t *hspi, uint8_t *pdata, uint16_t length);
+extern ER spi_transrecv(SPI_Handle_t *hspi, uint8_t *ptxData, uint8_t *prxData, uint16_t length);
+extern ER spi_wait(SPI_Handle_t *hspi, uint32_t timeout);
+extern void spi_handler(SPI_Handle_t *hspi);
+extern void spi_isr(intptr_t exinf);
+extern DMA_Handle_t *spi_dmac_set_single_mode(SPI_Handle_t *hspi, 
+                          uint8_t rtx,
+						  int8_t  ss_no,
+                          const void *src, void *dest, uint8_t src_inc,
+                          uint8_t dest_inc,
+                          uint8_t dmac_burst_size,
+                          uint8_t dmac_trans_width,
+                          size_t block_size);
+extern ER spi_dmac_wait_done(DMA_Handle_t * hdma);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _SPI_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/spi_reg.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/spi_reg.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/spi_reg.c	(revision 453)
@@ -0,0 +1,171 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ * 
+ *  SPIレガシードライバ関数群
+ *
+ */
+#include "kernel.h"
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <stdlib.h>
+#include <string.h>
+#include "device.h"
+#include "spi.h"
+
+/*
+ *  SPI受信実行関数
+ *  parameter1  hspi: SPIハンドラへのポインタ
+ *  parameter2  pdata: 受信バッファへのポインタ
+ *  parameter3  length: 受信サイズ
+ *  return ERコード
+ */
+ER
+spi_transmit(SPI_Handle_t *hspi, uint8_t *ptxData, uint16_t length)
+{
+	uint32_t *pTx;
+	int32_t  ss;
+	uint32_t i;
+	ER ercd = E_OK;
+
+	if(hspi == NULL)
+		return E_PAR;
+	ss = hspi->Init.SsNo;
+	if(hspi->hdmatx != NULL){
+		pTx = malloc(length * sizeof(uint32_t));
+		if(pTx == NULL)
+			return E_OBJ;
+		for(i = 0 ; i < length ; i++)
+			pTx[i] = ptxData[i];
+	}
+	else
+		pTx = (uint32_t *)ptxData;
+
+#if SPI_WAIT_TIME != 0
+	ercd = spi_core_transmit(hspi, ss, (uint8_t*)pTx, length);
+#else
+	if((ercd = spi_core_transmit(hspi, ss, (uint8_t*)pTx, length)) == E_OK){
+		ercd = spi_wait(hspi, 50);
+	}
+#endif
+	if(hspi->hdmatx != NULL)
+		free(pTx);
+	return ercd;
+}
+
+/*
+ *  SPI送信実行関数
+ *  parameter1  hspi: SPIハンドラへのポインタ
+ *  parameter2  pdata: 送信バッファへのポインタ
+ *  parameter3  length: 送信サイズ
+ *  return ERコード
+ */
+ER
+spi_receive(SPI_Handle_t *hspi, uint8_t *pdata, uint16_t length)
+{
+	uint32_t *pRx;
+	int32_t  ss;
+	uint32_t i;
+	ER  ercd = E_OK;
+
+	if(hspi == NULL)
+		return E_PAR;
+	ss = hspi->Init.SsNo;
+	pRx = malloc(length * sizeof(uint32_t));
+	if(pRx == NULL)
+		return E_OBJ;
+#if SPI_WAIT_TIME != 0
+	ercd = spi_core_receive(hspi, ss, pRx, length);
+#else
+	if((ercd = spi_core_receive(hspi, ss, pRx, length)) == E_OK)
+		ercd = spi_wait(hspi, 50);
+#endif
+	for(i = 0 ; i < length ; i++)
+		pdata[i] = pRx[i];
+	free(pRx);
+	return ercd;
+}
+
+/*
+ *  SPI送受信実行関数
+ *  parameter1  hspi: SPIハンドラへのポインタ
+ *  parameter2  ptxdata: 送信バッファへのポインタ
+ *  parameter3  prxdata: 受信バッファへのポインタ
+ *  parameter4  length: 送受信サイズ
+ *  return ERコード
+ */
+ER
+spi_transrecvx(SPI_Handle_t *hspi, uint8_t *ptxdata, uint8_t *prxdata, uint16_t length)
+{
+	uint32_t *pTx, *pRx;
+	int32_t  ss;
+	uint32_t i;
+	ER  ercd = E_OK;
+
+	if(hspi == NULL)
+		return E_PAR;
+	ss = hspi->Init.SsNo;
+	if(hspi->hdmatx != NULL){
+		pRx = malloc(length * sizeof(uint32_t) * 2);
+		if(pRx == NULL)
+			return E_OBJ;
+		pTx = pRx + length;
+		for(i = 0 ; i < length ; i++)
+			pTx[i] = ptxdata[i];
+	}
+	else{
+		pRx = malloc(length * sizeof(uint32_t));
+		if(pRx == NULL)
+			return E_OBJ;
+		pTx = (uint32_t *)ptxdata;
+	}
+#if SPI_WAIT_TIME != 0
+	ercd = spi_core_transrecv(hspi, ss, (uint8_t *)pTx, (uint8_t *)pRx, length);
+#else
+	if((ercd = spi_core_transrecv(hspi, ss, (uint8_t *)pTx, (uint8_t *)pRx, length)) == E_OK)
+		ercd = spi_wait(hspi, 50);
+#endif
+	for(i = 0 ; i < length ; i++)
+		prxdata[i] = pRx[i];
+	free(pRx);
+	return ercd;
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/sys/_stdint.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/sys/_stdint.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/sys/_stdint.h	(revision 453)
@@ -0,0 +1,2 @@
+#include <kernel.h>
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/sample/Makefile
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/sample/Makefile	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/sample/Makefile	(revision 453)
@@ -0,0 +1,572 @@
+#
+#  TOPPERS/ASP Kernel
+#      Toyohashi Open Platform for Embedded Real-Time Systems/
+#      Advanced Standard Profile Kernel
+# 
+#  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                              Toyohashi Univ. of Technology, JAPAN
+#  Copyright (C) 2006-2014 by Embedded and Real-Time Systems Laboratory
+#              Graduate School of Information Science, Nagoya Univ., JAPAN
+# 
+#  上記著作権者は，以下の(1)〜(4)の条件を満たす場合に限り，本ソフトウェ
+#  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+#  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+#  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#      スコード中に含まれていること．
+#  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#      の無保証規定を掲載すること．
+#  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#      と．
+#    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#        作権表示，この利用条件および下記の無保証規定を掲載すること．
+#    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#        報告すること．
+#  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+#      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+#      免責すること．
+# 
+#  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+#  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+#  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+#  の責任を負わない．
+# 
+#  $Id$
+# 
+
+#
+#  ターゲットの指定（Makefile.targetで上書きされるのを防ぐため）
+#
+all:
+
+#
+#  ターゲット略称の定義
+#
+TARGET = @(TARGET)
+
+#
+#  プログラミング言語の定義
+#
+SRCLANG = @(SRCLANG)
+ifeq ($(SRCLANG),c)
+  LIBS = -lc
+endif
+ifeq ($(SRCLANG),c++)
+  USE_CXX = true
+  CXXLIBS = -lstdc++ -lm -lc
+  CXXRTS = cxxrt.o newlibrt.o
+endif
+
+#
+#  ソースファイルのディレクトリの定義
+#
+SRCDIR = @(SRCDIR)
+
+#
+#  オブジェクトファイル名の拡張子の設定
+#
+OBJEXT = @(OBJEXT)
+
+#
+#  実行環境の定義（ターゲット依存に上書きされる場合がある）
+#
+DBGENV := @(DBGENV)
+
+#
+#  カーネルライブラリ（libkernel.a）のディレクトリ名
+#  （カーネルライブラリもmake対象にする時は，空に定義する）
+#
+KERNEL_LIB = @(KERNEL_LIB)
+
+#
+#  カーネルを関数単位でコンパイルするかどうかの定義
+#
+KERNEL_FUNCOBJS = @(KERNEL_FUNCOBJS)
+
+#
+#  トレースログを取得するかどうかの定義
+#
+ENABLE_TRACE = @(ENABLE_TRACE)
+
+#
+#  ユーティリティプログラムの名称
+#
+PERL = @(PERL)
+CFG = @(CFG)
+
+#
+#  オブジェクトファイル名の定義
+#
+OBJNAME = asp
+ifdef OBJEXT
+  OBJFILE = $(OBJNAME).$(OBJEXT)
+  CFG1_OUT = cfg1_out.$(OBJEXT)
+else
+  OBJFILE = $(OBJNAME)
+  CFG1_OUT = cfg1_out
+endif
+
+#
+#  ターゲット依存部のディレクトリの定義
+#
+TARGETDIR = $(SRCDIR)/target/$(TARGET)
+
+#
+#  ターゲット依存の定義のインクルード
+#
+include $(TARGETDIR)/Makefile.target
+
+#
+#  コンフィギュレータ関係の変数の定義
+#
+CFG_TABS := --api-table $(SRCDIR)/kernel/kernel_api.csv \
+			--cfg1-def-table $(SRCDIR)/kernel/kernel_def.csv $(CFG_TABS)
+
+CFG_ASMOBJS := $(CFG_ASMOBJS)
+CFG_COBJS := kernel_cfg.o $(CFG_COBJS)
+CFG_OBJS := $(CFG_ASMOBJS) $(CFG_COBJS)
+CFG2_OUT_SRCS := kernel_cfg.h kernel_cfg.c $(CFG2_OUT_SRCS)
+
+#
+#  共通コンパイルオプションの定義
+#
+COPTS := $(COPTS) -g @(COPTS)
+ifndef OMIT_WARNING_ALL
+  COPTS := $(COPTS) -Wall
+endif
+ifndef OMIT_OPTIMIZATION
+  COPTS := $(COPTS) -O2
+endif
+CDEFS := $(CDEFS) @(CDEFS)
+INCLUDES := -I. -I$(SRCDIR)/include -I$(SRCDIR)/arch -I$(SRCDIR) $(INCLUDES)
+LDFLAGS := $(LDFLAGS) @(LDFLAGS)
+CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) @(LDFLAGS)
+LIBS := $(LIBS) $(CXXLIBS)
+CFLAGS = $(COPTS) $(CDEFS) $(INCLUDES)
+
+#
+#  アプリケーションプログラムに関する定義
+#
+APPLNAME = @(APPLNAME)
+APPLDIR = @(APPLDIR)
+APPL_CFG = $(APPLNAME).cfg
+
+APPL_DIR = $(APPLDIR) $(SRCDIR)/library
+APPL_ASMOBJS =
+ifdef USE_CXX
+  APPL_CXXOBJS = $(APPLNAME).o @(APPLOBJS)
+  APPL_COBJS =
+else
+  APPL_COBJS = $(APPLNAME).o @(APPLOBJS)
+endif
+APPL_COBJS := $(APPL_COBJS) log_output.o vasyslog.o t_perror.o strerror.o
+APPL_CFLAGS =
+APPL_LIBS =
+ifdef APPLDIR
+  INCLUDES := $(INCLUDES) $(foreach dir,$(APPLDIR),-I$(dir))
+endif
+
+#
+#  システムサービスに関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR) $(SRCDIR)/syssvc $(SRCDIR)/library
+SYSSVC_ASMOBJS := $(SYSSVC_ASMOBJS)
+SYSSVC_COBJS := $(SYSSVC_COBJS) banner.o syslog.o serial.o logtask.o \
+				@(SYSSVCOBJS) $(CXXRTS)
+SYSSVC_CFLAGS := $(SYSSVC_CFLAGS)
+SYSSVC_LIBS := $(SYSSVC_LIBS)
+INCLUDES := $(INCLUDES)
+
+#
+#  カーネルに関する定義
+#
+#  KERNEL_ASMOBJS: カーネルライブラリに含める，ソースがアセンブリ言語の
+#				   オブジェクトファイル．
+#  KERNEL_COBJS: カーネルのライブラリに含める，ソースがC言語で，ソース
+#				 ファイルと1対1に対応するオブジェクトファイル．
+#  KERNEL_LCSRCS: カーネルのライブラリに含めるC言語のソースファイルで，
+#				  1つのソースファイルから複数のオブジェクトファイルを生
+#				  成するもの．
+#  KERNEL_LCOBJS: 上のソースファイルから生成されるオブジェクトファイル．
+#  KERNEL_AUX_COBJS: ロードモジュールに含めないが，カーネルのソースファ
+#					 イルと同じオプションを適用してコンパイルすべき，ソー
+#					 スがC言語のオブジェクトファイル．
+#
+KERNEL_DIR := $(KERNEL_DIR) $(SRCDIR)/kernel
+KERNEL_ASMOBJS := $(KERNEL_ASMOBJS)
+KERNEL_COBJS := $(KERNEL_COBJS)
+KERNEL_CFLAGS := $(KERNEL_CFLAGS) -I$(SRCDIR)/kernel
+ifdef OMIT_MAKEOFFSET
+  OFFSET_H =
+else
+  OFFSET_H = offset.h
+ifndef OFFSET_TF
+  KERNEL_AUX_COBJS := $(KERNEL_AUX_COBJS) makeoffset.o
+endif
+endif
+
+#
+#  ターゲットファイル（複数を同時に選択してはならない）
+#
+all: $(OBJFILE)
+#all: $(OBJNAME).bin
+#all: $(OBJNAME).srec
+
+##### 以下は編集しないこと #####
+
+#
+#  環境に依存するコンパイルオプションの定義
+#
+ifdef DBGENV
+  CDEFS := $(CDEFS) -D$(DBGENV)
+endif
+
+#
+#  カーネルのファイル構成の定義
+#
+include $(SRCDIR)/kernel/Makefile.kernel
+ifdef KERNEL_FUNCOBJS
+  KERNEL_LCSRCS := $(KERNEL_FCSRCS)
+  KERNEL_LCOBJS := $(foreach file,$(KERNEL_FCSRCS),$($(file:.c=)))
+else
+  KERNEL_CFLAGS := -DALLFUNC $(KERNEL_CFLAGS)
+  KERNEL_COBJS := $(KERNEL_COBJS) \
+					$(foreach file,$(KERNEL_FCSRCS),$(file:.c=.o))
+endif
+
+#
+#  ソースファイルのあるディレクトリに関する定義
+#
+vpath %.c $(KERNEL_DIR) $(SYSSVC_DIR) $(APPL_DIR)
+vpath %.S $(KERNEL_DIR) $(SYSSVC_DIR) $(APPL_DIR)
+vpath %.cfg $(APPL_DIR)
+
+#
+#  コンパイルのための変数の定義
+#
+KERNEL_LIB_OBJS = $(KERNEL_ASMOBJS) $(KERNEL_COBJS) $(KERNEL_LCOBJS)
+SYSSVC_OBJS = $(SYSSVC_ASMOBJS) $(SYSSVC_COBJS)
+APPL_OBJS = $(APPL_ASMOBJS) $(APPL_COBJS) $(APPL_CXXOBJS)
+ALL_OBJS = $(START_OBJS) $(APPL_OBJS) $(SYSSVC_OBJS) $(CFG_OBJS) \
+											$(END_OBJS) $(HIDDEN_OBJS)
+ifdef KERNEL_LIB
+  ALL_LIBS = $(APPL_LIBS) $(SYSSVC_LIBS) -lkernel $(LIBS)
+  LIBS_DEP = $(filter %.a,$(ALL_LIBS)) $(KERNEL_LIB)/libkernel.a
+  LDFLAGS := $(LDFLAGS) -L$(KERNEL_LIB)
+  REALCLEAN_FILES := libkernel.a $(REALCLEAN_FILES)
+else
+  ALL_LIBS = $(APPL_LIBS) $(SYSSVC_LIBS) libkernel.a $(LIBS)
+  LIBS_DEP = $(filter %.a,$(ALL_LIBS))
+endif
+
+ifdef TEXT_START_ADDRESS
+  LDFLAGS := $(LDFLAGS) -Wl,-Ttext,$(TEXT_START_ADDRESS)
+  CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) -Wl,-Ttext,$(TEXT_START_ADDRESS)
+endif
+ifdef DATA_START_ADDRESS
+  LDFLAGS := $(LDFLAGS) -Wl,-Tdata,$(DATA_START_ADDRESS)
+  CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) -Wl,-Tdata,$(DATA_START_ADDRESS)
+endif
+ifdef LDSCRIPT
+  LDFLAGS := $(LDFLAGS) -Wl,-T,$(LDSCRIPT)
+  CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS) -Wl,-T,$(LDSCRIPT)
+endif
+
+#
+#  オフセットファイル（offset.h）の生成規則
+#
+ifdef OFFSET_TF
+offset.h: $(APPL_CFG) kernel_cfg.timestamp
+	$(CFG) --pass 3 --kernel asp $(INCLUDES) \
+				--rom-image cfg1_out.srec --symbol-table cfg1_out.syms \
+				-T $(OFFSET_TF) $(CFG_TABS) $<
+else
+offset.h: makeoffset.s $(SRCDIR)/utils/genoffset
+	$(PERL) $(SRCDIR)/utils/genoffset makeoffset.s > offset.h
+endif
+
+#
+#  カーネルのコンフィギュレーションファイルの生成
+#
+cfg1_out.c: $(APPL_CFG)
+	$(CFG) --pass 1 --kernel asp $(INCLUDES) $(CFG_TABS) $<
+
+$(CFG2_OUT_SRCS): kernel_cfg.timestamp
+kernel_cfg.timestamp: $(APPL_CFG) \
+						$(START_OBJS) cfg1_out.o $(END_OBJS) $(HIDDEN_OBJS)
+	$(LINK) $(CFLAGS) $(CFG1_OUT_LDFLAGS) -o $(CFG1_OUT) \
+						$(START_OBJS) cfg1_out.o $(END_OBJS)
+	$(NM) -n $(CFG1_OUT) > cfg1_out.syms
+	$(OBJCOPY) -O srec -S $(CFG1_OUT) cfg1_out.srec
+	$(CFG) --pass 2 --kernel asp $(INCLUDES) \
+				-T $(TARGETDIR)/target.tf $(CFG_TABS) $<
+	touch -r kernel_cfg.c kernel_cfg.timestamp
+
+#
+#  カーネルライブラリファイルの生成
+#
+libkernel.a: $(OFFSET_H) $(KERNEL_LIB_OBJS)
+	rm -f libkernel.a
+	$(AR) -rcs libkernel.a $(KERNEL_LIB_OBJS)
+	$(RANLIB) libkernel.a
+
+#
+#  特別な依存関係の定義
+#
+banner.o: kernel_cfg.timestamp $(filter-out banner.o,$(ALL_OBJS)) $(LIBS_DEP)
+
+#
+#  全体のリンク
+#
+$(OBJFILE): $(APPL_CFG) kernel_cfg.timestamp $(ALL_OBJS) $(LIBS_DEP)
+	$(LINK) $(CFLAGS) $(LDFLAGS) -o $(OBJFILE) $(START_OBJS) \
+			$(APPL_OBJS) $(SYSSVC_OBJS) $(CFG_OBJS) $(ALL_LIBS) $(END_OBJS)
+	$(NM) -n $(OBJFILE) > $(OBJNAME).syms
+	$(OBJCOPY) -O srec -S $(OBJFILE) $(OBJNAME).srec
+	$(CFG) --pass 3 --kernel asp $(INCLUDES) \
+				--rom-image $(OBJNAME).srec --symbol-table $(OBJNAME).syms \
+				-T $(TARGETDIR)/target_check.tf $(CFG_TABS) $<
+
+#
+#  バイナリファイルの生成
+#
+$(OBJNAME).bin: $(OBJFILE)
+	$(OBJCOPY) -O binary -S $(OBJFILE) $(OBJNAME).bin
+
+#
+#  Sレコードファイルの生成
+#
+$(OBJNAME).srec: $(OBJFILE)
+	$(OBJCOPY) -O srec -S $(OBJFILE) $(OBJNAME).srec
+
+#
+#  コンパイル結果の消去
+#
+.PHONY: clean
+clean:
+	rm -f \#* *~ *.o $(CLEAN_FILES)
+	rm -f $(OBJFILE) $(OBJNAME).syms $(OBJNAME).srec $(OBJNAME).bin
+	rm -f kernel_cfg.timestamp $(CFG2_OUT_SRCS)
+	rm -f cfg1_out.c $(CFG1_OUT) cfg1_out.syms cfg1_out.srec
+ifndef KERNEL_LIB
+	rm -f libkernel.a
+endif
+	rm -f makeoffset.s offset.h
+
+.PHONY: cleankernel
+cleankernel:
+	rm -rf $(KERNEL_LIB_OBJS)
+	rm -f makeoffset.s offset.h
+
+.PHONY: cleandep
+cleandep:
+	if ! [ -f Makefile.depend ]; then \
+		rm -f kernel_cfg.timestamp $(CFG2_OUT_SRCS); \
+		rm -f cfg1_out.c cfg1_out.o $(CFG1_OUT) cfg1_out.syms cfg1_out.srec; \
+		rm -f makeoffset.s offset.h; \
+	fi
+	rm -f Makefile.depend
+
+.PHONY: realclean
+realclean: cleandep clean
+	rm -f $(REALCLEAN_FILES)
+
+#
+#  コンフィギュレータが生成したファイルのコンパイルルールと依存関係作成
+#  ルールの定義
+#
+#  コンフィギュレータが生成したファイルは，アプリケーションプログラム用，
+#  システムサービス用，カーネル用のすべてのオプションを付けてコンパイル
+#  する．
+#
+ALL_CFG_COBJS = $(CFG_COBJS) cfg1_out.o
+ALL_CFG_ASMOBJS = $(CFG_ASMOBJS)
+CFG_CFLAGS = $(APPL_CFLAGS) $(SYSSVC_CFLAGS) $(KERNEL_CFLAGS)
+
+$(ALL_CFG_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(CFG_CFLAGS) $<
+
+$(ALL_CFG_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(CFG_CFLAGS) $<
+
+$(ALL_CFG_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(CFG_CFLAGS)" $< >> Makefile.depend
+
+$(ALL_CFG_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(CFG_CFLAGS) $<
+
+$(ALL_CFG_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(CFG_CFLAGS)" $< >> Makefile.depend
+
+#
+#  特殊な依存関係作成ルールの定義
+#
+cfg1_out.depend: $(APPL_CFG)
+	@$(CFG) -M cfg1_out.c $(INCLUDES) $< >> Makefile.depend
+
+makeoffset.d: makeoffset.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-T "makeoffset.s" -O "$(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+#
+#  依存関係ファイルの生成
+#
+.PHONY: gendepend
+gendepend:
+	@echo "Generating Makefile.depend."
+
+.PHONY: depend
+ifdef KERNEL_LIB
+depend: cleandep kernel_cfg.timestamp gendepend \
+		cfg1_out.depend cfg1_out.d \
+		$(ALL_OBJS:.o=.d)
+else
+depend: cleandep $(OFFSET_H) kernel_cfg.timestamp gendepend \
+		cfg1_out.depend cfg1_out.d \
+		$(KERNEL_AUX_COBJS:.o=.d) $(KERNEL_ASMOBJS:.o=.d) \
+		$(KERNEL_COBJS:.o=.d) $(KERNEL_LCSRCS:.c=.d) $(ALL_OBJS:.o=.d)
+endif
+
+#
+#  依存関係ファイルをインクルード
+#
+-include Makefile.depend
+
+#
+#  開発ツールのコマンド名の定義
+#
+ifeq ($(TOOL),gcc)
+  #
+  #  GNU開発環境用
+  #
+  ifdef GCC_TARGET
+    GCC_TARGET_PREFIX = $(GCC_TARGET)-
+  else
+    GCC_TARGET_PREFIX =
+  endif
+  CC = $(GCC_TARGET_PREFIX)gcc
+  CXX = $(GCC_TARGET_PREFIX)g++
+  AS = $(GCC_TARGET_PREFIX)as
+  LD = $(GCC_TARGET_PREFIX)ld
+  AR = $(GCC_TARGET_PREFIX)ar
+  NM = $(GCC_TARGET_PREFIX)nm
+  RANLIB = $(GCC_TARGET_PREFIX)ranlib
+  OBJCOPY = $(GCC_TARGET_PREFIX)objcopy
+  OBJDUMP = $(GCC_TARGET_PREFIX)objdump
+endif
+
+ifdef USE_CXX
+  LINK = $(CXX)
+else
+  LINK = $(CC)
+endif
+
+#
+#  コンパイルルールの定義
+#
+KERNEL_ALL_COBJS = $(KERNEL_COBJS) $(KERNEL_AUX_COBJS)
+
+$(KERNEL_ALL_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_ALL_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_LCOBJS): %.o:
+	$(CC) -DTOPPERS_$(*F) -o $@ -c $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_LCOBJS:.o=.s): %.s:
+	$(CC) -DTOPPERS_$(*F) -o $@ -S $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(KERNEL_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(SYSSVC_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(SYSSVC_CFLAGS) $<
+
+$(SYSSVC_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(SYSSVC_CFLAGS) $<
+
+$(SYSSVC_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(SYSSVC_CFLAGS) $<
+
+$(APPL_COBJS): %.o: %.c
+	$(CC) -c $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_COBJS:.o=.s): %.s: %.c
+	$(CC) -S $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_CXXOBJS): %.o: %.cpp
+	$(CXX) -c $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_CXXOBJS:.o=.s): %.s: %.cpp
+	$(CXX) -S $(CFLAGS) $(APPL_CFLAGS) $<
+
+$(APPL_ASMOBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(APPL_CFLAGS) $<
+
+#
+#  依存関係作成ルールの定義
+#
+$(KERNEL_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+$(KERNEL_LCSRCS:.c=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) -T "$($*)" \
+		-O "-DALLFUNC $(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+$(KERNEL_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+$(SYSSVC_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(SYSSVC_CFLAGS)" $< >> Makefile.depend
+
+$(SYSSVC_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(SYSSVC_CFLAGS)" $< >> Makefile.depend
+
+$(APPL_COBJS:.o=.d): %.d: %.c
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(APPL_CFLAGS)" $< >> Makefile.depend
+
+$(APPL_CXXOBJS:.o=.d): %.d: %.cpp
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CXX) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(APPL_CFLAGS)" $< >> Makefile.depend
+
+$(APPL_ASMOBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(APPL_CFLAGS)" $< >> Makefile.depend
+
+#
+#  デフォルトコンパイルルールを上書き
+#
+%.o: %.c
+	@echo "*** Default compile rules should not be used."
+	$(CC) -c $(CFLAGS) $<
+
+%.s: %.c
+	@echo "*** Default compile rules should not be used."
+	$(CC) -S $(CFLAGS) $<
+
+%.o: %.cpp
+	@echo "*** Default compile rules should not be used."
+	$(CXX) -c $(CFLAGS) $<
+
+%.s: %.cpp
+	@echo "*** Default compile rules should not be used."
+	$(CXX) -S $(CFLAGS) $<
+
+%.o: %.S
+	@echo "*** Default compile rules should not be used."
+	$(CC) -c $(CFLAGS) $<
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/sample/sample1.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/sample/sample1.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/sample/sample1.c	(revision 453)
@@ -0,0 +1,559 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2012 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *  サンプルプログラム(1)の本体
+ *
+ *  ASPカーネルの基本的な動作を確認するためのサンプルプログラム．
+ *
+ *  プログラムの概要:
+ *
+ *  ユーザインタフェースを受け持つメインタスク（タスクID: MAIN_TASK，優
+ *  先度: MAIN_PRIORITY）と，3つの並行実行されるタスク（タスクID:
+ *  TASK1～TASK3，初期優先度: MID_PRIORITY）で構成される．また，起動周
+ *  期が2秒の周期ハンドラ（周期ハンドラID: CYCHDR1）を用いる．
+ *
+ *  並行実行されるタスクは，task_loop回空ループを実行する度に，タスクが
+ *  実行中であることをあらわすメッセージを表示する．空ループを実行する
+ *  のは，空ループなしでメッセージを出力すると，多量のメッセージが出力
+ *  され，プログラムの動作が確認しずらくなるためである．また，低速なシ
+ *  リアルポートを用いてメッセージを出力する場合に，すべてのメッセージ
+ *  が出力できるように，メッセージの量を制限するという理由もある．
+ *
+ *  周期ハンドラは，三つの優先度（HIGH_PRIORITY，MID_PRIORITY，
+ *  LOW_PRIORITY）のレディキューを回転させる．プログラムの起動直後は，
+ *  周期ハンドラは停止状態になっている．
+ *
+ *  メインタスクは，シリアルI/Oポートからの文字入力を行い（文字入力を
+ *  待っている間は，並行実行されるタスクが実行されている），入力された
+ *  文字に対応した処理を実行する．入力された文字と処理の関係は次の通り．
+ *  Control-Cまたは'Q'が入力されると，プログラムを終了する．
+ *
+ *  '1' : 対象タスクをTASK1に切り換える（初期設定）．
+ *  '2' : 対象タスクをTASK2に切り換える．
+ *  '3' : 対象タスクをTASK3に切り換える．
+ *  'a' : 対象タスクをact_tskにより起動する．
+ *  'A' : 対象タスクに対する起動要求をcan_actによりキャンセルする．
+ *  'e' : 対象タスクにext_tskを呼び出させ，終了させる．
+ *  't' : 対象タスクをter_tskにより強制終了する．
+ *  '>' : 対象タスクの優先度をHIGH_PRIORITYにする．
+ *  '=' : 対象タスクの優先度をMID_PRIORITYにする．
+ *  '<' : 対象タスクの優先度をLOW_PRIORITYにする．
+ *  'G' : 対象タスクの優先度をget_priで読み出す．
+ *  's' : 対象タスクにslp_tskを呼び出させ，起床待ちにさせる．
+ *  'S' : 対象タスクにtslp_tsk(10秒)を呼び出させ，起床待ちにさせる．
+ *  'w' : 対象タスクをwup_tskにより起床する．
+ *  'W' : 対象タスクに対する起床要求をcan_wupによりキャンセルする．
+ *  'l' : 対象タスクをrel_waiにより強制的に待ち解除にする．
+ *  'u' : 対象タスクをsus_tskにより強制待ち状態にする．
+ *  'm' : 対象タスクの強制待ち状態をrsm_tskにより解除する．
+ *  'd' : 対象タスクにdly_tsk(10秒)を呼び出させ，時間経過待ちにさせる．
+ *  'x' : 対象タスクに例外パターン0x0001の例外処理を要求する．
+ *  'X' : 対象タスクに例外パターン0x0002の例外処理を要求する．
+ *  'y' : 対象タスクにdis_texを呼び出させ，タスク例外を禁止する．
+ *  'Y' : 対象タスクにena_texを呼び出させ，タスク例外を許可する．
+ *  'r' : 3つの優先度（HIGH_PRIORITY，MID_PRIORITY，LOW_PRIORITY）のレ
+ *        ディキューを回転させる．
+ *  'c' : 周期ハンドラを動作開始させる．
+ *  'C' : 周期ハンドラを動作停止させる．
+ *  'b' : アラームハンドラを5秒後に起動するよう動作開始させる．
+ *  'B' : アラームハンドラを動作停止させる．
+ *  'z' : 対象タスクにCPU例外を発生させる（タスクを終了させる）．
+ *  'Z' : 対象タスクにCPUロック状態でCPU例外を発生させる（プログラムを
+ *        終了する）．
+ *  '@' : タスク3をacre_tskにより生成し，def_texによりタスク例外処理
+ *        ルーチンを設定する．
+ *  '!' : 対象タスクをdel_tskにより削除する．
+ *  'V' : get_utmで性能評価用システム時刻を2回読む．
+ *  'v' : 発行したシステムコールを表示する（デフォルト）．
+ *  'q' : 発行したシステムコールを表示しない．
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#include "kernel_cfg.h"
+#include "sample1.h"
+
+/*
+ *  サービスコールのエラーのログ出力
+ */
+Inline void
+svc_perror(const char *file, int_t line, const char *expr, ER ercd)
+{
+	if (ercd < 0) {
+		t_perror(LOG_ERROR, file, line, expr, ercd);
+	}
+}
+
+#define	SVC_PERROR(expr)	svc_perror(__FILE__, __LINE__, #expr, (expr))
+
+/*
+ *  並行実行されるタスクへのメッセージ領域
+ */
+char	message[3];
+
+/*
+ *  ループ回数
+ */
+ulong_t	task_loop;		/* タスク内でのループ回数 */
+ulong_t	tex_loop;		/* 例外処理ルーチン内でのループ回数 */
+
+/*
+ *  並行実行されるタスク
+ */
+void task(intptr_t exinf)
+{
+	volatile ulong_t	i;
+	int_t		n = 0;
+	int_t		tskno = (int_t) exinf;
+	const char	*graph[] = { "|", "  +", "    *" };
+	char		c;
+
+	SVC_PERROR(ena_tex());
+	while (true) {
+		syslog(LOG_NOTICE, "task%d is running (%03d).   %s",
+										tskno, ++n, graph[tskno-1]);
+		for (i = 0; i < task_loop; i++);
+		c = message[tskno-1];
+		message[tskno-1] = 0;
+		switch (c) {
+		case 'e':
+			syslog(LOG_INFO, "#%d#ext_tsk()", tskno);
+			SVC_PERROR(ext_tsk());
+			assert(0);
+		case 's':
+			syslog(LOG_INFO, "#%d#slp_tsk()", tskno);
+			SVC_PERROR(slp_tsk());
+			break;
+		case 'S':
+			syslog(LOG_INFO, "#%d#tslp_tsk(10000)", tskno);
+			SVC_PERROR(tslp_tsk(10000));
+			break;
+		case 'd':
+			syslog(LOG_INFO, "#%d#dly_tsk(10000)", tskno);
+			SVC_PERROR(dly_tsk(10000));
+			break;
+		case 'y':
+			syslog(LOG_INFO, "#%d#dis_tex()", tskno);
+			SVC_PERROR(dis_tex());
+			break;
+		case 'Y':
+			syslog(LOG_INFO, "#%d#ena_tex()", tskno);
+			SVC_PERROR(ena_tex());
+			break;
+#ifdef CPUEXC1
+		case 'z':
+			syslog(LOG_NOTICE, "#%d#raise CPU exception", tskno);
+			RAISE_CPU_EXCEPTION;
+			break;
+		case 'Z':
+			SVC_PERROR(loc_cpu());
+			syslog(LOG_NOTICE, "#%d#raise CPU exception", tskno);
+			RAISE_CPU_EXCEPTION;
+			SVC_PERROR(unl_cpu());
+			break;
+#endif /* CPUEXC1 */
+		default:
+			break;
+		}
+	}
+}
+
+/*
+ *  並行して実行されるタスク用のタスク例外処理ルーチン
+ */
+void tex_routine(TEXPTN texptn, intptr_t exinf)
+{
+	volatile ulong_t	i;
+	int_t	tskno = (int_t) exinf;
+
+	syslog(LOG_NOTICE, "task%d receives exception 0x%04x.", tskno, texptn);
+	for (i = 0; i < tex_loop; i++);
+
+	if ((texptn & 0x8000U) != 0U) {
+		syslog(LOG_INFO, "#%d#ext_tsk()", tskno);
+		SVC_PERROR(ext_tsk());
+		assert(0);
+	}
+}
+
+/*
+ *  CPU例外ハンドラ
+ */
+#ifdef CPUEXC1
+
+void
+cpuexc_handler(void *p_excinf)
+{
+	ID		tskid;
+
+	syslog(LOG_NOTICE, "CPU exception handler (p_excinf = %08p).", p_excinf);
+	if (sns_ctx() != true) {
+		syslog(LOG_WARNING,
+					"sns_ctx() is not true in CPU exception handler.");
+	}
+	if (sns_dpn() != true) {
+		syslog(LOG_WARNING,
+					"sns_dpn() is not true in CPU exception handler.");
+	}
+	syslog(LOG_INFO, "sns_loc = %d sns_dsp = %d sns_tex = %d",
+									sns_loc(), sns_dsp(), sns_tex());
+	syslog(LOG_INFO, "xsns_dpn = %d xsns_xpn = %d",
+									xsns_dpn(p_excinf), xsns_xpn(p_excinf));
+
+	if (xsns_xpn(p_excinf)) {
+		syslog(LOG_NOTICE, "Sample program ends with exception.");
+		SVC_PERROR(ext_ker());
+		assert(0);
+	}
+
+	SVC_PERROR(iget_tid(&tskid));
+	SVC_PERROR(iras_tex(tskid, 0x8000U));
+}
+
+#endif /* CPUEXC1 */
+
+/*
+ *  周期ハンドラ
+ *
+ *  HIGH_PRIORITY，MID_PRIORITY，LOW_PRIORITY の各優先度のレディキュー
+ *  を回転させる．
+ */
+void cyclic_handler(intptr_t exinf)
+{
+	SVC_PERROR(irot_rdq(HIGH_PRIORITY));
+	SVC_PERROR(irot_rdq(MID_PRIORITY));
+	SVC_PERROR(irot_rdq(LOW_PRIORITY));
+}
+
+/*
+ *  アラームハンドラ
+ *
+ *  HIGH_PRIORITY，MID_PRIORITY，LOW_PRIORITY の各優先度のレディキュー
+ *  を回転させる．
+ */
+void alarm_handler(intptr_t exinf)
+{
+	SVC_PERROR(irot_rdq(HIGH_PRIORITY));
+	SVC_PERROR(irot_rdq(MID_PRIORITY));
+	SVC_PERROR(irot_rdq(LOW_PRIORITY));
+}
+
+/*
+ *  メインタスク
+ */
+void main_task(intptr_t exinf)
+{
+	char	c;
+	ID		tskid = TASK1;
+	int_t	tskno = 1;
+	ER_UINT	ercd;
+	PRI		tskpri;
+#ifndef TASK_LOOP
+	volatile ulong_t	i;
+	SYSTIM	stime1, stime2;
+#endif /* TASK_LOOP */
+#ifdef TOPPERS_SUPPORT_GET_UTM
+	SYSUTM	utime1, utime2;
+#endif /* TOPPERS_SUPPORT_GET_UTM */
+	T_CTSK	ctsk;
+	T_DTEX	dtex;
+	ID		TASK3 = -1;
+
+	SVC_PERROR(syslog_msk_log(LOG_UPTO(LOG_INFO), LOG_UPTO(LOG_EMERG)));
+	syslog(LOG_NOTICE, "Sample program starts (exinf = %d).", (int_t) exinf);
+
+	/*
+	 *  シリアルポートの初期化
+	 *
+	 *  システムログタスクと同じシリアルポートを使う場合など，シリアル
+	 *  ポートがオープン済みの場合にはここでE_OBJエラーになるが，支障は
+	 *  ない．
+	 */
+	ercd = serial_opn_por(TASK_PORTID);
+	if (ercd < 0 && MERCD(ercd) != E_OBJ) {
+		syslog(LOG_ERROR, "%s (%d) reported by `serial_opn_por'.",
+									itron_strerror(ercd), SERCD(ercd));
+	}
+	SVC_PERROR(serial_ctl_por(TASK_PORTID,
+							(IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV)));
+
+	/*
+ 	 *  ループ回数の設定
+	 *
+	 *  並行実行されるタスク内での空ループの回数（task_loop）は，空ルー
+	 *  プの実行時間が約0.4秒になるように設定する．この設定のために，
+	 *  LOOP_REF回の空ループの実行時間を，その前後でget_timを呼ぶことで
+	 *  測定し，その測定結果から空ループの実行時間が0.4秒になるループ回
+	 *  数を求め，task_loopに設定する．
+	 *
+	 *  LOOP_REFは，デフォルトでは1,000,000に設定しているが，想定したよ
+	 *  り遅いプロセッサでは，サンプルプログラムの実行開始に時間がかか
+	 *  りすぎるという問題を生じる．逆に想定したより速いプロセッサでは，
+	 *  LOOP_REF回の空ループの実行時間が短くなり，task_loopに設定する値
+	 *  の誤差が大きくなるという問題がある．
+	 *
+	 *  そこで，そのようなターゲットでは，target_test.hで，LOOP_REFを適
+	 *  切な値に定義するのが望ましい．
+	 *
+	 *  また，task_loopの値を固定したい場合には，その値をTASK_LOOPにマ
+	 *  クロ定義する．TASK_LOOPがマクロ定義されている場合，上記の測定を
+	 *  行わずに，TASK_LOOPに定義された値を空ループの回数とする．
+	 *
+	 * ターゲットによっては，空ループの実行時間の1回目の測定で，本来よ
+	 * りも長めになるものがある．このようなターゲットでは，MEASURE_TWICE
+	 * をマクロ定義することで，1回目の測定結果を捨てて，2回目の測定結果
+	 * を使う．
+	 *
+	 *  タスク例外処理ルーチン内での空ループの回数（tex_loop）は，
+	 *  task_loopの4分の1の値（空ループの実行時間が0.1秒になるループ回
+	 *  数）に設定する．
+	 */
+#ifdef TASK_LOOP
+	task_loop = TASK_LOOP;
+#else /* TASK_LOOP */
+
+#ifdef MEASURE_TWICE
+	task_loop = LOOP_REF;
+	SVC_PERROR(get_tim(&stime1));
+	for (i = 0; i < task_loop; i++);
+	SVC_PERROR(get_tim(&stime2));
+#endif /* MEASURE_TWICE */
+
+	task_loop = LOOP_REF;
+	SVC_PERROR(get_tim(&stime1));
+	for (i = 0; i < task_loop; i++);
+	SVC_PERROR(get_tim(&stime2));
+	task_loop = LOOP_REF * 400UL / (stime2 - stime1);
+
+#endif /* TASK_LOOP */
+	tex_loop = task_loop / 4;
+
+	/*
+ 	 *  タスクの起動
+	 */
+	SVC_PERROR(act_tsk(TASK1));
+	SVC_PERROR(act_tsk(TASK2));
+
+	/*
+ 	 *  メインループ
+	 */
+	do {
+		SVC_PERROR(serial_rea_dat(TASK_PORTID, &c, 1));
+		switch (c) {
+		case 'e':
+		case 's':
+		case 'S':
+		case 'd':
+		case 'y':
+		case 'Y':
+		case 'z':
+		case 'Z':
+			message[tskno-1] = c;
+			break;
+		case '1':
+			tskno = 1;
+			tskid = TASK1;
+			break;
+		case '2':
+			tskno = 2;
+			tskid = TASK2;
+			break;
+		case '3':
+			tskno = 3;
+			tskid = TASK3;
+			break;
+		case 'a':
+			syslog(LOG_INFO, "#act_tsk(%d)", tskno);
+			SVC_PERROR(act_tsk(tskid));
+			break;
+		case 'A':
+			syslog(LOG_INFO, "#can_act(%d)", tskno);
+			SVC_PERROR(ercd = can_act(tskid));
+			if (ercd >= 0) {
+				syslog(LOG_NOTICE, "can_act(%d) returns %d", tskno, ercd);
+			}
+			break;
+		case 't':
+			syslog(LOG_INFO, "#ter_tsk(%d)", tskno);
+			SVC_PERROR(ter_tsk(tskid));
+			break;
+		case '>':
+			syslog(LOG_INFO, "#chg_pri(%d, HIGH_PRIORITY)", tskno);
+			SVC_PERROR(chg_pri(tskid, HIGH_PRIORITY));
+			break;
+		case '=':
+			syslog(LOG_INFO, "#chg_pri(%d, MID_PRIORITY)", tskno);
+			SVC_PERROR(chg_pri(tskid, MID_PRIORITY));
+			break;
+		case '<':
+			syslog(LOG_INFO, "#chg_pri(%d, LOW_PRIORITY)", tskno);
+			SVC_PERROR(chg_pri(tskid, LOW_PRIORITY));
+			break;
+		case 'G':
+			syslog(LOG_INFO, "#get_pri(%d, &tskpri)", tskno);
+			SVC_PERROR(ercd = get_pri(tskid, &tskpri));
+			if (ercd >= 0) {
+				syslog(LOG_NOTICE, "priority of task %d is %d", tskno, tskpri);
+			}
+			break;
+		case 'w':
+			syslog(LOG_INFO, "#wup_tsk(%d)", tskno);
+			SVC_PERROR(wup_tsk(tskid));
+			break;
+		case 'W':
+			syslog(LOG_INFO, "#can_wup(%d)", tskno);
+			SVC_PERROR(ercd = can_wup(tskid));
+			if (ercd >= 0) {
+				syslog(LOG_NOTICE, "can_wup(%d) returns %d", tskno, ercd);
+			}
+			break;
+		case 'l':
+			syslog(LOG_INFO, "#rel_wai(%d)", tskno);
+			SVC_PERROR(rel_wai(tskid));
+			break;
+		case 'u':
+			syslog(LOG_INFO, "#sus_tsk(%d)", tskno);
+			SVC_PERROR(sus_tsk(tskid));
+			break;
+		case 'm':
+			syslog(LOG_INFO, "#rsm_tsk(%d)", tskno);
+			SVC_PERROR(rsm_tsk(tskid));
+			break;
+		case 'x':
+			syslog(LOG_INFO, "#ras_tex(%d, 0x0001U)", tskno);
+			SVC_PERROR(ras_tex(tskid, 0x0001U));
+			break;
+		case 'X':
+			syslog(LOG_INFO, "#ras_tex(%d, 0x0002U)", tskno);
+			SVC_PERROR(ras_tex(tskid, 0x0002U));
+			break;
+		case 'r':
+			syslog(LOG_INFO, "#rot_rdq(three priorities)");
+			SVC_PERROR(rot_rdq(HIGH_PRIORITY));
+			SVC_PERROR(rot_rdq(MID_PRIORITY));
+			SVC_PERROR(rot_rdq(LOW_PRIORITY));
+			break;
+		case 'c':
+			syslog(LOG_INFO, "#sta_cyc(1)");
+			SVC_PERROR(sta_cyc(CYCHDR1));
+			break;
+		case 'C':
+			syslog(LOG_INFO, "#stp_cyc(1)");
+			SVC_PERROR(stp_cyc(CYCHDR1));
+			break;
+		case 'b':
+			syslog(LOG_INFO, "#sta_alm(1, 5000)");
+			SVC_PERROR(sta_alm(ALMHDR1, 5000));
+			break;
+		case 'B':
+			syslog(LOG_INFO, "#stp_alm(1)");
+			SVC_PERROR(stp_alm(ALMHDR1));
+			break;
+		case '@':
+			ctsk.tskatr = TA_NULL;
+			ctsk.exinf = 3;
+			ctsk.task = task;
+			ctsk.itskpri = MID_PRIORITY;
+			ctsk.stksz = STACK_SIZE;
+			ctsk.stk = NULL;
+			SVC_PERROR(TASK3 = acre_tsk(&ctsk));
+
+			dtex.texatr = TA_NULL;
+			dtex.texrtn = tex_routine;
+			SVC_PERROR(def_tex(TASK3, &dtex));
+
+			syslog(LOG_NOTICE, "task3 is created with tskid = %d.",
+														(int_t) TASK3);
+			break;
+		case '!':
+			syslog(LOG_INFO, "#del_tsk(%d)", tskno);
+			SVC_PERROR(del_tsk(tskid));
+			break;
+
+		case 'V':
+#ifdef TOPPERS_SUPPORT_GET_UTM
+			SVC_PERROR(get_utm(&utime1));
+			SVC_PERROR(get_utm(&utime2));
+			syslog(LOG_NOTICE, "utime1 = %ld, utime2 = %ld",
+										(ulong_t) utime1, (ulong_t) utime2);
+#else /* TOPPERS_SUPPORT_GET_UTM */
+			syslog(LOG_NOTICE, "get_utm is not supported.");
+#endif /* TOPPERS_SUPPORT_GET_UTM */
+			break;
+
+		case 'v':
+			SVC_PERROR(syslog_msk_log(LOG_UPTO(LOG_INFO),
+										LOG_UPTO(LOG_EMERG)));
+			break;
+		case 'q':
+			SVC_PERROR(syslog_msk_log(LOG_UPTO(LOG_NOTICE),
+										LOG_UPTO(LOG_EMERG)));
+			break;
+
+#ifdef BIT_KERNEL
+		case ' ':
+			SVC_PERROR(loc_cpu());
+			{
+				extern ER	bit_kernel(void);
+
+				SVC_PERROR(ercd = bit_kernel());
+				if (ercd >= 0) {
+					syslog(LOG_NOTICE, "bit_kernel passed.");
+				}
+			}
+			SVC_PERROR(unl_cpu());
+			break;
+#endif /* BIT_KERNEL */
+
+		default:
+			break;
+		}
+	} while (c != '\003' && c != 'Q');
+
+	syslog(LOG_NOTICE, "Sample program ends.");
+	SVC_PERROR(ext_ker());
+	assert(0);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/sample/sample1.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/sample/sample1.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/sample/sample1.cfg	(revision 453)
@@ -0,0 +1,26 @@
+/*
+ *  $Id$
+ */
+
+/*
+ *  サンプルプログラム(1)のシステムコンフィギュレーションファイル
+ */
+INCLUDE("target_timer.cfg");
+INCLUDE("syssvc/syslog.cfg");
+INCLUDE("syssvc/banner.cfg");
+INCLUDE("syssvc/serial.cfg");
+INCLUDE("syssvc/logtask.cfg");
+
+#include "sample1.h"
+CRE_TSK(TASK1, { TA_NULL, 1, task, MID_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK2, { TA_NULL, 2, task, MID_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(MAIN_TASK, { TA_ACT, 0, main_task, MAIN_PRIORITY, STACK_SIZE, NULL });
+AID_TSK(3);
+DEF_TEX(TASK1, { TA_NULL, tex_routine });
+DEF_TEX(TASK2, { TA_NULL, tex_routine });
+CRE_CYC(CYCHDR1, { TA_NULL, 0, cyclic_handler, 2000, 0 });
+CRE_ALM(ALMHDR1, { TA_NULL, 0, alarm_handler });
+#ifdef CPUEXC1
+DEF_EXC(CPUEXC1, { TA_NULL, cpuexc_handler });
+#endif /* CPUEXC1 */
+DEF_KMM({ KMM_SIZE, NULL });
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/sample/sample1.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/sample/sample1.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/sample/sample1.h	(revision 453)
@@ -0,0 +1,97 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ *
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ *
+ *  $Id$
+ */
+
+/*
+ *		サンプルプログラム(1)のヘッダファイル
+ */
+
+/*
+ *  ターゲット依存の定義
+ */
+#include "target_test.h"
+
+/*
+ *  各タスクの優先度の定義
+ */
+
+#define MAIN_PRIORITY	5		/* メインタスクの優先度 */
+								/* HIGH_PRIORITYより高くすること */
+
+#define HIGH_PRIORITY	9		/* 並行実行されるタスクの優先度 */
+#define MID_PRIORITY	10
+#define LOW_PRIORITY	11
+
+/*
+ *  ターゲットに依存する可能性のある定数の定義
+ */
+
+#ifndef TASK_PORTID
+#define	TASK_PORTID		1			/* 文字入力するシリアルポートID */
+#endif /* TASK_PORTID */
+
+#ifndef STACK_SIZE
+#define	STACK_SIZE		4096		/* タスクのスタックサイズ */
+#endif /* STACK_SIZE */
+
+#ifndef KMM_SIZE
+#define	KMM_SIZE		(STACK_SIZE * 16)	/* カーネルが割り付ける   */
+#endif /* KMM_SIZE */						/*     メモリ領域のサイズ */
+
+#ifndef LOOP_REF
+#define LOOP_REF		ULONG_C(1000000)	/* 速度計測用のループ回数 */
+#endif /* LOOP_REF */
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+#ifndef TOPPERS_MACRO_ONLY
+
+extern void	task(intptr_t exinf);
+extern void	main_task(intptr_t exinf);
+extern void	tex_routine(TEXPTN texptn, intptr_t exinf);
+#ifdef CPUEXC1
+extern void	cpuexc_handler(void *p_excinf);
+#endif /* CPUEXC1 */
+extern void	cyclic_handler(intptr_t exinf);
+extern void	alarm_handler(intptr_t exinf);
+
+#endif /* TOPPERS_MACRO_ONLY */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/stmcube/Utilities/Fonts/font12.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/stmcube/Utilities/Fonts/font12.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/stmcube/Utilities/Fonts/font12.c	(revision 453)
@@ -0,0 +1,1464 @@
+/**
+  ******************************************************************************
+  * @file    Font12.c
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    18-February-2014
+  * @brief   This file provides text Font12 for STM32xx-EVAL's LCD driver. 
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "fonts.h"
+
+/** @addtogroup Utilities
+  * @{
+  */
+  
+/** @addtogroup STM32_EVAL
+  * @{
+  */ 
+
+/** @addtogroup Common
+  * @{
+  */
+
+/** @addtogroup FONTS
+  * @brief      This file provides text Font12 for STM32xx-EVAL's LCD driver.
+  * @{
+  */  
+
+/** @defgroup FONTS_Private_Types
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+
+
+/** @defgroup FONTS_Private_Defines
+  * @{
+  */
+/**
+  * @}
+  */ 
+
+
+/** @defgroup FONTS_Private_Macros
+  * @{
+  */
+/**
+  * @}
+  */ 
+  
+
+/** @defgroup FONTS_Private_Variables
+  * @{
+  */
+// 
+//  Font data for Courier New 12pt
+// 
+
+const uint8_t Font12_Table[] = 
+{
+	// @0 ' ' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @12 '!' (7 pixels wide)
+	0x00, //        
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x00, //        
+	0x00, //        
+	0x10, //    #   
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @24 '"' (7 pixels wide)
+	0x00, //        
+	0x6C, //  ## ## 
+	0x48, //  #  #  
+	0x48, //  #  #  
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @36 '#' (7 pixels wide)
+	0x00, //        
+	0x14, //    # # 
+	0x14, //    # # 
+	0x28, //   # #  
+	0x7C, //  ##### 
+	0x28, //   # #  
+	0x7C, //  ##### 
+	0x28, //   # #  
+	0x50, //  # #   
+	0x50, //  # #   
+	0x00, //        
+	0x00, //        
+
+	// @48 '$' (7 pixels wide)
+	0x00, //        
+	0x10, //    #   
+	0x38, //   ###  
+	0x40, //  #     
+	0x40, //  #     
+	0x38, //   ###  
+	0x48, //  #  #  
+	0x70, //  ###   
+	0x10, //    #   
+	0x10, //    #   
+	0x00, //        
+	0x00, //        
+
+	// @60 '%' (7 pixels wide)
+	0x00, //        
+	0x20, //   #    
+	0x50, //  # #   
+	0x20, //   #    
+	0x0C, //     ## 
+	0x70, //  ###   
+	0x08, //     #  
+	0x14, //    # # 
+	0x08, //     #  
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @72 '&' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x18, //    ##  
+	0x20, //   #    
+	0x20, //   #    
+	0x54, //  # # # 
+	0x48, //  #  #  
+	0x34, //   ## # 
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @84 ''' (7 pixels wide)
+	0x00, //        
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @96 '(' (7 pixels wide)
+	0x00, //        
+	0x08, //     #  
+	0x08, //     #  
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x08, //     #  
+	0x08, //     #  
+	0x00, //        
+
+	// @108 ')' (7 pixels wide)
+	0x00, //        
+	0x20, //   #    
+	0x20, //   #    
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x20, //   #    
+	0x20, //   #    
+	0x00, //        
+
+	// @120 '*' (7 pixels wide)
+	0x00, //        
+	0x10, //    #   
+	0x7C, //  ##### 
+	0x10, //    #   
+	0x28, //   # #  
+	0x28, //   # #  
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @132 '+' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0xFE, // #######
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @144 ',' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x18, //    ##  
+	0x10, //    #   
+	0x30, //   ##   
+	0x20, //   #    
+	0x00, //        
+
+	// @156 '-' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x7C, //  ##### 
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @168 '.' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x30, //   ##   
+	0x30, //   ##   
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @180 '/' (7 pixels wide)
+	0x00, //        
+	0x04, //      # 
+	0x04, //      # 
+	0x08, //     #  
+	0x08, //     #  
+	0x10, //    #   
+	0x10, //    #   
+	0x20, //   #    
+	0x20, //   #    
+	0x40, //  #     
+	0x00, //        
+	0x00, //        
+
+	// @192 '0' (7 pixels wide)
+	0x00, //        
+	0x38, //   ###  
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x38, //   ###  
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @204 '1' (7 pixels wide)
+	0x00, //        
+	0x30, //   ##   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x7C, //  ##### 
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @216 '2' (7 pixels wide)
+	0x00, //        
+	0x38, //   ###  
+	0x44, //  #   # 
+	0x04, //      # 
+	0x08, //     #  
+	0x10, //    #   
+	0x20, //   #    
+	0x44, //  #   # 
+	0x7C, //  ##### 
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @228 '3' (7 pixels wide)
+	0x00, //        
+	0x38, //   ###  
+	0x44, //  #   # 
+	0x04, //      # 
+	0x18, //    ##  
+	0x04, //      # 
+	0x04, //      # 
+	0x44, //  #   # 
+	0x38, //   ###  
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @240 '4' (7 pixels wide)
+	0x00, //        
+	0x0C, //     ## 
+	0x14, //    # # 
+	0x14, //    # # 
+	0x24, //   #  # 
+	0x44, //  #   # 
+	0x7E, //  ######
+	0x04, //      # 
+	0x0E, //     ###
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @252 '5' (7 pixels wide)
+	0x00, //        
+	0x3C, //   #### 
+	0x20, //   #    
+	0x20, //   #    
+	0x38, //   ###  
+	0x04, //      # 
+	0x04, //      # 
+	0x44, //  #   # 
+	0x38, //   ###  
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @264 '6' (7 pixels wide)
+	0x00, //        
+	0x1C, //    ### 
+	0x20, //   #    
+	0x40, //  #     
+	0x78, //  ####  
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x38, //   ###  
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @276 '7' (7 pixels wide)
+	0x00, //        
+	0x7C, //  ##### 
+	0x44, //  #   # 
+	0x04, //      # 
+	0x08, //     #  
+	0x08, //     #  
+	0x08, //     #  
+	0x10, //    #   
+	0x10, //    #   
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @288 '8' (7 pixels wide)
+	0x00, //        
+	0x38, //   ###  
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x38, //   ###  
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x38, //   ###  
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @300 '9' (7 pixels wide)
+	0x00, //        
+	0x38, //   ###  
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x3C, //   #### 
+	0x04, //      # 
+	0x08, //     #  
+	0x70, //  ###   
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @312 ':' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x30, //   ##   
+	0x30, //   ##   
+	0x00, //        
+	0x00, //        
+	0x30, //   ##   
+	0x30, //   ##   
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @324 ';' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x18, //    ##  
+	0x18, //    ##  
+	0x00, //        
+	0x00, //        
+	0x18, //    ##  
+	0x30, //   ##   
+	0x20, //   #    
+	0x00, //        
+	0x00, //        
+
+	// @336 '<' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x0C, //     ## 
+	0x10, //    #   
+	0x60, //  ##    
+	0x80, // #      
+	0x60, //  ##    
+	0x10, //    #   
+	0x0C, //     ## 
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @348 '=' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x7C, //  ##### 
+	0x00, //        
+	0x7C, //  ##### 
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @360 '>' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0xC0, // ##     
+	0x20, //   #    
+	0x18, //    ##  
+	0x04, //      # 
+	0x18, //    ##  
+	0x20, //   #    
+	0xC0, // ##     
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @372 '?' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x18, //    ##  
+	0x24, //   #  # 
+	0x04, //      # 
+	0x08, //     #  
+	0x10, //    #   
+	0x00, //        
+	0x30, //   ##   
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @384 '@' (7 pixels wide)
+	0x38, //   ###  
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x4C, //  #  ## 
+	0x54, //  # # # 
+	0x54, //  # # # 
+	0x4C, //  #  ## 
+	0x40, //  #     
+	0x44, //  #   # 
+	0x38, //   ###  
+	0x00, //        
+	0x00, //        
+
+	// @396 'A' (7 pixels wide)
+	0x00, //        
+	0x30, //   ##   
+	0x10, //    #   
+	0x28, //   # #  
+	0x28, //   # #  
+	0x28, //   # #  
+	0x7C, //  ##### 
+	0x44, //  #   # 
+	0xEE, // ### ###
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @408 'B' (7 pixels wide)
+	0x00, //        
+	0xF8, // #####  
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x78, //  ####  
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0xF8, // #####  
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @420 'C' (7 pixels wide)
+	0x00, //        
+	0x3C, //   #### 
+	0x44, //  #   # 
+	0x40, //  #     
+	0x40, //  #     
+	0x40, //  #     
+	0x40, //  #     
+	0x44, //  #   # 
+	0x38, //   ###  
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @432 'D' (7 pixels wide)
+	0x00, //        
+	0xF0, // ####   
+	0x48, //  #  #  
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x48, //  #  #  
+	0xF0, // ####   
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @444 'E' (7 pixels wide)
+	0x00, //        
+	0xFC, // ###### 
+	0x44, //  #   # 
+	0x50, //  # #   
+	0x70, //  ###   
+	0x50, //  # #   
+	0x40, //  #     
+	0x44, //  #   # 
+	0xFC, // ###### 
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @456 'F' (7 pixels wide)
+	0x00, //        
+	0x7E, //  ######
+	0x22, //   #   #
+	0x28, //   # #  
+	0x38, //   ###  
+	0x28, //   # #  
+	0x20, //   #    
+	0x20, //   #    
+	0x70, //  ###   
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @468 'G' (7 pixels wide)
+	0x00, //        
+	0x3C, //   #### 
+	0x44, //  #   # 
+	0x40, //  #     
+	0x40, //  #     
+	0x4E, //  #  ###
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x38, //   ###  
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @480 'H' (7 pixels wide)
+	0x00, //        
+	0xEE, // ### ###
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x7C, //  ##### 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0xEE, // ### ###
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @492 'I' (7 pixels wide)
+	0x00, //        
+	0x7C, //  ##### 
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x7C, //  ##### 
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @504 'J' (7 pixels wide)
+	0x00, //        
+	0x3C, //   #### 
+	0x08, //     #  
+	0x08, //     #  
+	0x08, //     #  
+	0x48, //  #  #  
+	0x48, //  #  #  
+	0x48, //  #  #  
+	0x30, //   ##   
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @516 'K' (7 pixels wide)
+	0x00, //        
+	0xEE, // ### ###
+	0x44, //  #   # 
+	0x48, //  #  #  
+	0x50, //  # #   
+	0x70, //  ###   
+	0x48, //  #  #  
+	0x44, //  #   # 
+	0xE6, // ###  ##
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @528 'L' (7 pixels wide)
+	0x00, //        
+	0x70, //  ###   
+	0x20, //   #    
+	0x20, //   #    
+	0x20, //   #    
+	0x20, //   #    
+	0x24, //   #  # 
+	0x24, //   #  # 
+	0x7C, //  ##### 
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @540 'M' (7 pixels wide)
+	0x00, //        
+	0xEE, // ### ###
+	0x6C, //  ## ## 
+	0x6C, //  ## ## 
+	0x54, //  # # # 
+	0x54, //  # # # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0xEE, // ### ###
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @552 'N' (7 pixels wide)
+	0x00, //        
+	0xEE, // ### ###
+	0x64, //  ##  # 
+	0x64, //  ##  # 
+	0x54, //  # # # 
+	0x54, //  # # # 
+	0x54, //  # # # 
+	0x4C, //  #  ## 
+	0xEC, // ### ## 
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @564 'O' (7 pixels wide)
+	0x00, //        
+	0x38, //   ###  
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x38, //   ###  
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @576 'P' (7 pixels wide)
+	0x00, //        
+	0x78, //  ####  
+	0x24, //   #  # 
+	0x24, //   #  # 
+	0x24, //   #  # 
+	0x38, //   ###  
+	0x20, //   #    
+	0x20, //   #    
+	0x70, //  ###   
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @588 'Q' (7 pixels wide)
+	0x00, //        
+	0x38, //   ###  
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x38, //   ###  
+	0x1C, //    ### 
+	0x00, //        
+	0x00, //        
+
+	// @600 'R' (7 pixels wide)
+	0x00, //        
+	0xF8, // #####  
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x78, //  ####  
+	0x48, //  #  #  
+	0x44, //  #   # 
+	0xE2, // ###   #
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @612 'S' (7 pixels wide)
+	0x00, //        
+	0x34, //   ## # 
+	0x4C, //  #  ## 
+	0x40, //  #     
+	0x38, //   ###  
+	0x04, //      # 
+	0x04, //      # 
+	0x64, //  ##  # 
+	0x58, //  # ##  
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @624 'T' (7 pixels wide)
+	0x00, //        
+	0xFE, // #######
+	0x92, // #  #  #
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x38, //   ###  
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @636 'U' (7 pixels wide)
+	0x00, //        
+	0xEE, // ### ###
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x38, //   ###  
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @648 'V' (7 pixels wide)
+	0x00, //        
+	0xEE, // ### ###
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x28, //   # #  
+	0x28, //   # #  
+	0x28, //   # #  
+	0x10, //    #   
+	0x10, //    #   
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @660 'W' (7 pixels wide)
+	0x00, //        
+	0xEE, // ### ###
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x54, //  # # # 
+	0x54, //  # # # 
+	0x54, //  # # # 
+	0x54, //  # # # 
+	0x28, //   # #  
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @672 'X' (7 pixels wide)
+	0x00, //        
+	0xC6, // ##   ##
+	0x44, //  #   # 
+	0x28, //   # #  
+	0x10, //    #   
+	0x10, //    #   
+	0x28, //   # #  
+	0x44, //  #   # 
+	0xC6, // ##   ##
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @684 'Y' (7 pixels wide)
+	0x00, //        
+	0xEE, // ### ###
+	0x44, //  #   # 
+	0x28, //   # #  
+	0x28, //   # #  
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x38, //   ###  
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @696 'Z' (7 pixels wide)
+	0x00, //        
+	0x7C, //  ##### 
+	0x44, //  #   # 
+	0x08, //     #  
+	0x10, //    #   
+	0x10, //    #   
+	0x20, //   #    
+	0x44, //  #   # 
+	0x7C, //  ##### 
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @708 '[' (7 pixels wide)
+	0x00, //        
+	0x38, //   ###  
+	0x20, //   #    
+	0x20, //   #    
+	0x20, //   #    
+	0x20, //   #    
+	0x20, //   #    
+	0x20, //   #    
+	0x20, //   #    
+	0x20, //   #    
+	0x38, //   ###  
+	0x00, //        
+
+	// @720 '\' (7 pixels wide)
+	0x00, //        
+	0x40, //  #     
+	0x20, //   #    
+	0x20, //   #    
+	0x20, //   #    
+	0x10, //    #   
+	0x10, //    #   
+	0x08, //     #  
+	0x08, //     #  
+	0x08, //     #  
+	0x00, //        
+	0x00, //        
+
+	// @732 ']' (7 pixels wide)
+	0x00, //        
+	0x38, //   ###  
+	0x08, //     #  
+	0x08, //     #  
+	0x08, //     #  
+	0x08, //     #  
+	0x08, //     #  
+	0x08, //     #  
+	0x08, //     #  
+	0x08, //     #  
+	0x38, //   ###  
+	0x00, //        
+
+	// @744 '^' (7 pixels wide)
+	0x00, //        
+	0x10, //    #   
+	0x10, //    #   
+	0x28, //   # #  
+	0x44, //  #   # 
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @756 '_' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0xFE, // #######
+
+	// @768 '`' (7 pixels wide)
+	0x00, //        
+	0x10, //    #   
+	0x08, //     #  
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @780 'a' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x38, //   ###  
+	0x44, //  #   # 
+	0x3C, //   #### 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x3E, //   #####
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @792 'b' (7 pixels wide)
+	0x00, //        
+	0xC0, // ##     
+	0x40, //  #     
+	0x58, //  # ##  
+	0x64, //  ##  # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0xF8, // #####  
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @804 'c' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x3C, //   #### 
+	0x44, //  #   # 
+	0x40, //  #     
+	0x40, //  #     
+	0x44, //  #   # 
+	0x38, //   ###  
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @816 'd' (7 pixels wide)
+	0x00, //        
+	0x0C, //     ## 
+	0x04, //      # 
+	0x34, //   ## # 
+	0x4C, //  #  ## 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x3E, //   #####
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @828 'e' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x38, //   ###  
+	0x44, //  #   # 
+	0x7C, //  ##### 
+	0x40, //  #     
+	0x40, //  #     
+	0x3C, //   #### 
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @840 'f' (7 pixels wide)
+	0x00, //        
+	0x1C, //    ### 
+	0x20, //   #    
+	0x7C, //  ##### 
+	0x20, //   #    
+	0x20, //   #    
+	0x20, //   #    
+	0x20, //   #    
+	0x7C, //  ##### 
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @852 'g' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x36, //   ## ##
+	0x4C, //  #  ## 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x3C, //   #### 
+	0x04, //      # 
+	0x38, //   ###  
+	0x00, //        
+
+	// @864 'h' (7 pixels wide)
+	0x00, //        
+	0xC0, // ##     
+	0x40, //  #     
+	0x58, //  # ##  
+	0x64, //  ##  # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0xEE, // ### ###
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @876 'i' (7 pixels wide)
+	0x00, //        
+	0x10, //    #   
+	0x00, //        
+	0x70, //  ###   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x7C, //  ##### 
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @888 'j' (7 pixels wide)
+	0x00, //        
+	0x10, //    #   
+	0x00, //        
+	0x78, //  ####  
+	0x08, //     #  
+	0x08, //     #  
+	0x08, //     #  
+	0x08, //     #  
+	0x08, //     #  
+	0x08, //     #  
+	0x70, //  ###   
+	0x00, //        
+
+	// @900 'k' (7 pixels wide)
+	0x00, //        
+	0xC0, // ##     
+	0x40, //  #     
+	0x5C, //  # ### 
+	0x48, //  #  #  
+	0x70, //  ###   
+	0x50, //  # #   
+	0x48, //  #  #  
+	0xDC, // ## ### 
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @912 'l' (7 pixels wide)
+	0x00, //        
+	0x30, //   ##   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x7C, //  ##### 
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @924 'm' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0xE8, // ### #  
+	0x54, //  # # # 
+	0x54, //  # # # 
+	0x54, //  # # # 
+	0x54, //  # # # 
+	0xFE, // #######
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @936 'n' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0xD8, // ## ##  
+	0x64, //  ##  # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0xEE, // ### ###
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @948 'o' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x38, //   ###  
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x38, //   ###  
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @960 'p' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0xD8, // ## ##  
+	0x64, //  ##  # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x78, //  ####  
+	0x40, //  #     
+	0xE0, // ###    
+	0x00, //        
+
+	// @972 'q' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x36, //   ## ##
+	0x4C, //  #  ## 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x3C, //   #### 
+	0x04, //      # 
+	0x0E, //     ###
+	0x00, //        
+
+	// @984 'r' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x6C, //  ## ## 
+	0x30, //   ##   
+	0x20, //   #    
+	0x20, //   #    
+	0x20, //   #    
+	0x7C, //  ##### 
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @996 's' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x3C, //   #### 
+	0x44, //  #   # 
+	0x38, //   ###  
+	0x04, //      # 
+	0x44, //  #   # 
+	0x78, //  ####  
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @1008 't' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x20, //   #    
+	0x7C, //  ##### 
+	0x20, //   #    
+	0x20, //   #    
+	0x20, //   #    
+	0x22, //   #   #
+	0x1C, //    ### 
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @1020 'u' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0xCC, // ##  ## 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x4C, //  #  ## 
+	0x36, //   ## ##
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @1032 'v' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0xEE, // ### ###
+	0x44, //  #   # 
+	0x44, //  #   # 
+	0x28, //   # #  
+	0x28, //   # #  
+	0x10, //    #   
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @1044 'w' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0xEE, // ### ###
+	0x44, //  #   # 
+	0x54, //  # # # 
+	0x54, //  # # # 
+	0x54, //  # # # 
+	0x28, //   # #  
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @1056 'x' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0xCC, // ##  ## 
+	0x48, //  #  #  
+	0x30, //   ##   
+	0x30, //   ##   
+	0x48, //  #  #  
+	0xCC, // ##  ## 
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @1068 'y' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0xEE, // ### ###
+	0x44, //  #   # 
+	0x24, //   #  # 
+	0x28, //   # #  
+	0x18, //    ##  
+	0x10, //    #   
+	0x10, //    #   
+	0x78, //  ####  
+	0x00, //        
+
+	// @1080 'z' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x7C, //  ##### 
+	0x48, //  #  #  
+	0x10, //    #   
+	0x20, //   #    
+	0x44, //  #   # 
+	0x7C, //  ##### 
+	0x00, //        
+	0x00, //        
+	0x00, //        
+
+	// @1092 '{' (7 pixels wide)
+	0x00, //        
+	0x08, //     #  
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x20, //   #    
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x08, //     #  
+	0x00, //        
+
+	// @1104 '|' (7 pixels wide)
+	0x00, //        
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x00, //        
+	0x00, //        
+
+	// @1116 '}' (7 pixels wide)
+	0x00, //        
+	0x20, //   #    
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x08, //     #  
+	0x10, //    #   
+	0x10, //    #   
+	0x10, //    #   
+	0x20, //   #    
+	0x00, //        
+
+	// @1128 '~' (7 pixels wide)
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x24, //   #  # 
+	0x58, //  # ##  
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+	0x00, //        
+};
+
+sFONT Font12 = {
+  Font12_Table,
+  7, /* Width */
+  12, /* Height */
+};
+
+/**
+  * @}
+  */ 
+
+
+/** @defgroup FONTS_Private_Function_Prototypes
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+
+
+/** @defgroup FONTS_Private_Functions
+  * @{
+  */
+    
+/**
+  * @}
+  */
+  
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */  
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/stmcube/Utilities/Fonts/font16.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/stmcube/Utilities/Fonts/font16.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/stmcube/Utilities/Fonts/font16.c	(revision 453)
@@ -0,0 +1,1844 @@
+/**
+  ******************************************************************************
+  * @file    font16.c
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    18-February-2014
+  * @brief   This file provides text font16 for STM32xx-EVAL's LCD driver. 
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "fonts.h"
+
+/** @addtogroup Utilities
+  * @{
+  */
+  
+/** @addtogroup STM32_EVAL
+  * @{
+  */ 
+
+/** @addtogroup Common
+  * @{
+  */
+
+/** @addtogroup FONTS
+  * @brief      This file provides text font16 for STM32xx-EVAL's LCD driver.
+  * @{
+  */  
+
+/** @defgroup FONTS_Private_Types
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+
+
+/** @defgroup FONTS_Private_Defines
+  * @{
+  */
+/**
+  * @}
+  */ 
+
+
+/** @defgroup FONTS_Private_Macros
+  * @{
+  */
+/**
+  * @}
+  */ 
+  
+
+/** @defgroup FONTS_Private_Variables
+  * @{
+  */
+// 
+//  Font data for Courier New 12pt
+// 
+
+const uint8_t Font16_Table[] = 
+{
+	// @0 ' ' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @32 '!' (11 pixels wide)
+	0x00, 0x00, //            
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x00, 0x00, //            
+	0x0C, 0x00, //     ##     
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @64 '"' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x1D, 0xC0, //    ### ### 
+	0x1D, 0xC0, //    ### ### 
+	0x08, 0x80, //     #   #  
+	0x08, 0x80, //     #   #  
+	0x08, 0x80, //     #   #  
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @96 '#' (11 pixels wide)
+	0x00, 0x00, //            
+	0x0D, 0x80, //     ## ##  
+	0x0D, 0x80, //     ## ##  
+	0x0D, 0x80, //     ## ##  
+	0x0D, 0x80, //     ## ##  
+	0x3F, 0xC0, //   ######## 
+	0x1B, 0x00, //    ## ##   
+	0x3F, 0xC0, //   ######## 
+	0x1B, 0x00, //    ## ##   
+	0x1B, 0x00, //    ## ##   
+	0x1B, 0x00, //    ## ##   
+	0x1B, 0x00, //    ## ##   
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @128 '$' (11 pixels wide)
+	0x04, 0x00, //      #     
+	0x1F, 0x80, //    ######  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x38, 0x00, //   ###      
+	0x1E, 0x00, //    ####    
+	0x0F, 0x00, //     ####   
+	0x03, 0x80, //       ###  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x3F, 0x00, //   ######   
+	0x04, 0x00, //      #     
+	0x04, 0x00, //      #     
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @160 '%' (11 pixels wide)
+	0x00, 0x00, //            
+	0x18, 0x00, //    ##      
+	0x24, 0x00, //   #  #     
+	0x24, 0x00, //   #  #     
+	0x18, 0xC0, //    ##   ## 
+	0x07, 0x80, //      ####  
+	0x1E, 0x00, //    ####    
+	0x31, 0x80, //   ##   ##  
+	0x02, 0x40, //       #  # 
+	0x02, 0x40, //       #  # 
+	0x01, 0x80, //        ##  
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @192 '&' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x0F, 0x00, //     ####   
+	0x18, 0x00, //    ##      
+	0x18, 0x00, //    ##      
+	0x18, 0x00, //    ##      
+	0x0C, 0x00, //     ##     
+	0x1D, 0x80, //    ### ##  
+	0x37, 0x00, //   ## ###   
+	0x33, 0x00, //   ##  ##   
+	0x1D, 0x80, //    ### ##  
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @224 ''' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x07, 0x00, //      ###   
+	0x07, 0x00, //      ###   
+	0x02, 0x00, //       #    
+	0x02, 0x00, //       #    
+	0x02, 0x00, //       #    
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @256 '(' (11 pixels wide)
+	0x00, 0x00, //            
+	0x03, 0x00, //       ##   
+	0x03, 0x00, //       ##   
+	0x06, 0x00, //      ##    
+	0x0E, 0x00, //     ###    
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x0E, 0x00, //     ###    
+	0x06, 0x00, //      ##    
+	0x03, 0x00, //       ##   
+	0x03, 0x00, //       ##   
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @288 ')' (11 pixels wide)
+	0x00, 0x00, //            
+	0x18, 0x00, //    ##      
+	0x18, 0x00, //    ##      
+	0x0C, 0x00, //     ##     
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x0C, 0x00, //     ##     
+	0x1C, 0x00, //    ###     
+	0x18, 0x00, //    ##      
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @320 '*' (11 pixels wide)
+	0x00, 0x00, //            
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x3F, 0xC0, //   ######## 
+	0x3F, 0xC0, //   ######## 
+	0x0F, 0x00, //     ####   
+	0x1F, 0x80, //    ######  
+	0x19, 0x80, //    ##  ##  
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @352 '+' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x04, 0x00, //      #     
+	0x04, 0x00, //      #     
+	0x04, 0x00, //      #     
+	0x3F, 0x80, //   #######  
+	0x04, 0x00, //      #     
+	0x04, 0x00, //      #     
+	0x04, 0x00, //      #     
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @384 ',' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x06, 0x00, //      ##    
+	0x04, 0x00, //      #     
+	0x0C, 0x00, //     ##     
+	0x08, 0x00, //     #      
+	0x08, 0x00, //     #      
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @416 '-' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x3F, 0x80, //   #######  
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @448 '.' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @480 '/' (11 pixels wide)
+	0x00, 0xC0, //         ## 
+	0x00, 0xC0, //         ## 
+	0x01, 0x80, //        ##  
+	0x01, 0x80, //        ##  
+	0x03, 0x00, //       ##   
+	0x03, 0x00, //       ##   
+	0x06, 0x00, //      ##    
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x18, 0x00, //    ##      
+	0x18, 0x00, //    ##      
+	0x30, 0x00, //   ##       
+	0x30, 0x00, //   ##       
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @512 '0' (11 pixels wide)
+	0x00, 0x00, //            
+	0x0E, 0x00, //     ###    
+	0x1B, 0x00, //    ## ##   
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x1B, 0x00, //    ## ##   
+	0x0E, 0x00, //     ###    
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @544 '1' (11 pixels wide)
+	0x00, 0x00, //            
+	0x06, 0x00, //      ##    
+	0x3E, 0x00, //   #####    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x3F, 0xC0, //   ######## 
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @576 '2' (11 pixels wide)
+	0x00, 0x00, //            
+	0x0F, 0x00, //     ####   
+	0x19, 0x80, //    ##  ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x03, 0x00, //       ##   
+	0x06, 0x00, //      ##    
+	0x0C, 0x00, //     ##     
+	0x18, 0x00, //    ##      
+	0x30, 0x00, //   ##       
+	0x3F, 0x80, //   #######  
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @608 '3' (11 pixels wide)
+	0x00, 0x00, //            
+	0x3F, 0x00, //   ######   
+	0x61, 0x80, //  ##    ##  
+	0x01, 0x80, //        ##  
+	0x03, 0x00, //       ##   
+	0x1F, 0x00, //    #####   
+	0x03, 0x80, //       ###  
+	0x01, 0x80, //        ##  
+	0x01, 0x80, //        ##  
+	0x61, 0x80, //  ##    ##  
+	0x3F, 0x00, //   ######   
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @640 '4' (11 pixels wide)
+	0x00, 0x00, //            
+	0x07, 0x00, //      ###   
+	0x07, 0x00, //      ###   
+	0x0F, 0x00, //     ####   
+	0x0B, 0x00, //     # ##   
+	0x1B, 0x00, //    ## ##   
+	0x13, 0x00, //    #  ##   
+	0x33, 0x00, //   ##  ##   
+	0x3F, 0x80, //   #######  
+	0x03, 0x00, //       ##   
+	0x0F, 0x80, //     #####  
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @672 '5' (11 pixels wide)
+	0x00, 0x00, //            
+	0x1F, 0x80, //    ######  
+	0x18, 0x00, //    ##      
+	0x18, 0x00, //    ##      
+	0x18, 0x00, //    ##      
+	0x1F, 0x00, //    #####   
+	0x11, 0x80, //    #   ##  
+	0x01, 0x80, //        ##  
+	0x01, 0x80, //        ##  
+	0x21, 0x80, //   #    ##  
+	0x1F, 0x00, //    #####   
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @704 '6' (11 pixels wide)
+	0x00, 0x00, //            
+	0x07, 0x80, //      ####  
+	0x1C, 0x00, //    ###     
+	0x18, 0x00, //    ##      
+	0x30, 0x00, //   ##       
+	0x37, 0x00, //   ## ###   
+	0x39, 0x80, //   ###  ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x19, 0x80, //    ##  ##  
+	0x0F, 0x00, //     ####   
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @736 '7' (11 pixels wide)
+	0x00, 0x00, //            
+	0x7F, 0x00, //  #######   
+	0x43, 0x00, //  #    ##   
+	0x03, 0x00, //       ##   
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @768 '8' (11 pixels wide)
+	0x00, 0x00, //            
+	0x1F, 0x00, //    #####   
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x1F, 0x00, //    #####   
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x1F, 0x00, //    #####   
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @800 '9' (11 pixels wide)
+	0x00, 0x00, //            
+	0x1E, 0x00, //    ####    
+	0x33, 0x00, //   ##  ##   
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x33, 0x80, //   ##  ###  
+	0x1D, 0x80, //    ### ##  
+	0x01, 0x80, //        ##  
+	0x03, 0x00, //       ##   
+	0x07, 0x00, //      ###   
+	0x3C, 0x00, //   ####     
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @832 ':' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @864 ';' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x03, 0x00, //       ##   
+	0x03, 0x00, //       ##   
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x06, 0x00, //      ##    
+	0x04, 0x00, //      #     
+	0x08, 0x00, //     #      
+	0x08, 0x00, //     #      
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @896 '<' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0xC0, //         ## 
+	0x03, 0x00, //       ##   
+	0x04, 0x00, //      #     
+	0x18, 0x00, //    ##      
+	0x60, 0x00, //  ##        
+	0x18, 0x00, //    ##      
+	0x04, 0x00, //      #     
+	0x03, 0x00, //       ##   
+	0x00, 0xC0, //         ## 
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @928 '=' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x7F, 0xC0, //  ######### 
+	0x00, 0x00, //            
+	0x7F, 0xC0, //  ######### 
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @960 '>' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x60, 0x00, //  ##        
+	0x18, 0x00, //    ##      
+	0x04, 0x00, //      #     
+	0x03, 0x00, //       ##   
+	0x00, 0xC0, //         ## 
+	0x03, 0x00, //       ##   
+	0x04, 0x00, //      #     
+	0x18, 0x00, //    ##      
+	0x60, 0x00, //  ##        
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @992 '?' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x1F, 0x00, //    #####   
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x01, 0x80, //        ##  
+	0x07, 0x00, //      ###   
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x00, 0x00, //            
+	0x0C, 0x00, //     ##     
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1024 '@' (11 pixels wide)
+	0x00, 0x00, //            
+	0x0E, 0x00, //     ###    
+	0x11, 0x00, //    #   #   
+	0x21, 0x00, //   #    #   
+	0x21, 0x00, //   #    #   
+	0x27, 0x00, //   #  ###   
+	0x29, 0x00, //   # #  #   
+	0x29, 0x00, //   # #  #   
+	0x27, 0x00, //   #  ###   
+	0x20, 0x00, //   #        
+	0x11, 0x00, //    #   #   
+	0x0E, 0x00, //     ###    
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1056 'A' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x3F, 0x00, //   ######   
+	0x0F, 0x00, //     ####   
+	0x09, 0x00, //     #  #   
+	0x19, 0x80, //    ##  ##  
+	0x19, 0x80, //    ##  ##  
+	0x1F, 0x80, //    ######  
+	0x30, 0xC0, //   ##    ## 
+	0x30, 0xC0, //   ##    ## 
+	0x79, 0xE0, //  ####  ####
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1088 'B' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x7F, 0x00, //  #######   
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x3F, 0x00, //   ######   
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x7F, 0x00, //  #######   
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1120 'C' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x1F, 0x40, //    ##### # 
+	0x30, 0xC0, //   ##    ## 
+	0x60, 0x40, //  ##      # 
+	0x60, 0x00, //  ##        
+	0x60, 0x00, //  ##        
+	0x60, 0x00, //  ##        
+	0x60, 0x40, //  ##      # 
+	0x30, 0x80, //   ##    #  
+	0x1F, 0x00, //    #####   
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1152 'D' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x7F, 0x00, //  #######   
+	0x31, 0x80, //   ##   ##  
+	0x30, 0xC0, //   ##    ## 
+	0x30, 0xC0, //   ##    ## 
+	0x30, 0xC0, //   ##    ## 
+	0x30, 0xC0, //   ##    ## 
+	0x30, 0xC0, //   ##    ## 
+	0x31, 0x80, //   ##   ##  
+	0x7F, 0x00, //  #######   
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1184 'E' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x7F, 0x80, //  ########  
+	0x30, 0x80, //   ##    #  
+	0x30, 0x80, //   ##    #  
+	0x32, 0x00, //   ##  #    
+	0x3E, 0x00, //   #####    
+	0x32, 0x00, //   ##  #    
+	0x30, 0x80, //   ##    #  
+	0x30, 0x80, //   ##    #  
+	0x7F, 0x80, //  ########  
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1216 'F' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x7F, 0xC0, //  ######### 
+	0x30, 0x40, //   ##     # 
+	0x30, 0x40, //   ##     # 
+	0x32, 0x00, //   ##  #    
+	0x3E, 0x00, //   #####    
+	0x32, 0x00, //   ##  #    
+	0x30, 0x00, //   ##       
+	0x30, 0x00, //   ##       
+	0x7C, 0x00, //  #####     
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1248 'G' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x1E, 0x80, //    #### #  
+	0x31, 0x80, //   ##   ##  
+	0x60, 0x80, //  ##     #  
+	0x60, 0x00, //  ##        
+	0x60, 0x00, //  ##        
+	0x67, 0xC0, //  ##  ##### 
+	0x61, 0x80, //  ##    ##  
+	0x31, 0x80, //   ##   ##  
+	0x1F, 0x00, //    #####   
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1280 'H' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x7B, 0xC0, //  #### #### 
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x3F, 0x80, //   #######  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x7B, 0xC0, //  #### #### 
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1312 'I' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x3F, 0xC0, //   ######## 
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x3F, 0xC0, //   ######## 
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1344 'J' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x1F, 0xC0, //    ####### 
+	0x03, 0x00, //       ##   
+	0x03, 0x00, //       ##   
+	0x03, 0x00, //       ##   
+	0x03, 0x00, //       ##   
+	0x63, 0x00, //  ##   ##   
+	0x63, 0x00, //  ##   ##   
+	0x63, 0x00, //  ##   ##   
+	0x3E, 0x00, //   #####    
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1376 'K' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x7B, 0xC0, //  #### #### 
+	0x31, 0x80, //   ##   ##  
+	0x33, 0x00, //   ##  ##   
+	0x36, 0x00, //   ## ##    
+	0x3C, 0x00, //   ####     
+	0x3E, 0x00, //   #####    
+	0x33, 0x00, //   ##  ##   
+	0x31, 0x80, //   ##   ##  
+	0x79, 0xC0, //  ####  ### 
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1408 'L' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x7E, 0x00, //  ######    
+	0x18, 0x00, //    ##      
+	0x18, 0x00, //    ##      
+	0x18, 0x00, //    ##      
+	0x18, 0x00, //    ##      
+	0x18, 0x40, //    ##    # 
+	0x18, 0x40, //    ##    # 
+	0x18, 0x40, //    ##    # 
+	0x7F, 0xC0, //  ######### 
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1440 'M' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0xE0, 0xE0, // ###     ###
+	0x60, 0xC0, //  ##     ## 
+	0x71, 0xC0, //  ###   ### 
+	0x7B, 0xC0, //  #### #### 
+	0x6A, 0xC0, //  ## # # ## 
+	0x6E, 0xC0, //  ## ### ## 
+	0x64, 0xC0, //  ##  #  ## 
+	0x60, 0xC0, //  ##     ## 
+	0xFB, 0xE0, // ##### #####
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1472 'N' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x73, 0xC0, //  ###  #### 
+	0x31, 0x80, //   ##   ##  
+	0x39, 0x80, //   ###  ##  
+	0x3D, 0x80, //   #### ##  
+	0x35, 0x80, //   ## # ##  
+	0x37, 0x80, //   ## ####  
+	0x33, 0x80, //   ##  ###  
+	0x31, 0x80, //   ##   ##  
+	0x79, 0x80, //  ####  ##  
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1504 'O' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x1F, 0x00, //    #####   
+	0x31, 0x80, //   ##   ##  
+	0x60, 0xC0, //  ##     ## 
+	0x60, 0xC0, //  ##     ## 
+	0x60, 0xC0, //  ##     ## 
+	0x60, 0xC0, //  ##     ## 
+	0x60, 0xC0, //  ##     ## 
+	0x31, 0x80, //   ##   ##  
+	0x1F, 0x00, //    #####   
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1536 'P' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x7F, 0x00, //  #######   
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x3F, 0x00, //   ######   
+	0x30, 0x00, //   ##       
+	0x30, 0x00, //   ##       
+	0x7E, 0x00, //  ######    
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1568 'Q' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x1F, 0x00, //    #####   
+	0x31, 0x80, //   ##   ##  
+	0x60, 0xC0, //  ##     ## 
+	0x60, 0xC0, //  ##     ## 
+	0x60, 0xC0, //  ##     ## 
+	0x60, 0xC0, //  ##     ## 
+	0x60, 0xC0, //  ##     ## 
+	0x31, 0x80, //   ##   ##  
+	0x1F, 0x00, //    #####   
+	0x0C, 0xC0, //     ##  ## 
+	0x1F, 0x80, //    ######  
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1600 'R' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x7F, 0x00, //  #######   
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x3E, 0x00, //   #####    
+	0x33, 0x00, //   ##  ##   
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x7C, 0xE0, //  #####  ###
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1632 'S' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x1F, 0x80, //    ######  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x38, 0x00, //   ###      
+	0x1F, 0x00, //    #####   
+	0x03, 0x80, //       ###  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x3F, 0x00, //   ######   
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1664 'T' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x7F, 0x80, //  ########  
+	0x4C, 0x80, //  #  ##  #  
+	0x4C, 0x80, //  #  ##  #  
+	0x4C, 0x80, //  #  ##  #  
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x3F, 0x00, //   ######   
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1696 'U' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x7B, 0xC0, //  #### #### 
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x1F, 0x00, //    #####   
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1728 'V' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x7B, 0xC0, //  #### #### 
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x1B, 0x00, //    ## ##   
+	0x1B, 0x00, //    ## ##   
+	0x1B, 0x00, //    ## ##   
+	0x0A, 0x00, //     # #    
+	0x0E, 0x00, //     ###    
+	0x0E, 0x00, //     ###    
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1760 'W' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0xFB, 0xE0, // ##### #####
+	0x60, 0xC0, //  ##     ## 
+	0x64, 0xC0, //  ##  #  ## 
+	0x6E, 0xC0, //  ## ### ## 
+	0x6E, 0xC0, //  ## ### ## 
+	0x2A, 0x80, //   # # # #  
+	0x3B, 0x80, //   ### ###  
+	0x3B, 0x80, //   ### ###  
+	0x31, 0x80, //   ##   ##  
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1792 'X' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x7B, 0xC0, //  #### #### 
+	0x31, 0x80, //   ##   ##  
+	0x1B, 0x00, //    ## ##   
+	0x0E, 0x00, //     ###    
+	0x0E, 0x00, //     ###    
+	0x0E, 0x00, //     ###    
+	0x1B, 0x00, //    ## ##   
+	0x31, 0x80, //   ##   ##  
+	0x7B, 0xC0, //  #### #### 
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1824 'Y' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x79, 0xE0, //  ####  ####
+	0x30, 0xC0, //   ##    ## 
+	0x19, 0x80, //    ##  ##  
+	0x0F, 0x00, //     ####   
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x1F, 0x80, //    ######  
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1856 'Z' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x3F, 0x80, //   #######  
+	0x21, 0x80, //   #    ##  
+	0x23, 0x00, //   #   ##   
+	0x06, 0x00, //      ##    
+	0x04, 0x00, //      #     
+	0x0C, 0x00, //     ##     
+	0x18, 0x80, //    ##   #  
+	0x30, 0x80, //   ##    #  
+	0x3F, 0x80, //   #######  
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1888 '[' (11 pixels wide)
+	0x00, 0x00, //            
+	0x07, 0x80, //      ####  
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x07, 0x80, //      ####  
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1920 '\' (11 pixels wide)
+	0x30, 0x00, //   ##       
+	0x30, 0x00, //   ##       
+	0x18, 0x00, //    ##      
+	0x18, 0x00, //    ##      
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x06, 0x00, //      ##    
+	0x03, 0x00, //       ##   
+	0x03, 0x00, //       ##   
+	0x01, 0x80, //        ##  
+	0x01, 0x80, //        ##  
+	0x00, 0xC0, //         ## 
+	0x00, 0xC0, //         ## 
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1952 ']' (11 pixels wide)
+	0x00, 0x00, //            
+	0x1E, 0x00, //    ####    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x1E, 0x00, //    ####    
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @1984 '^' (11 pixels wide)
+	0x04, 0x00, //      #     
+	0x0A, 0x00, //     # #    
+	0x0A, 0x00, //     # #    
+	0x11, 0x00, //    #   #   
+	0x20, 0x80, //   #     #  
+	0x20, 0x80, //   #     #  
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2016 '_' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0xFF, 0xE0, // ###########
+
+	// @2048 '`' (11 pixels wide)
+	0x08, 0x00, //     #      
+	0x04, 0x00, //      #     
+	0x02, 0x00, //       #    
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2080 'a' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x1F, 0x00, //    #####   
+	0x01, 0x80, //        ##  
+	0x01, 0x80, //        ##  
+	0x1F, 0x80, //    ######  
+	0x31, 0x80, //   ##   ##  
+	0x33, 0x80, //   ##  ###  
+	0x1D, 0xC0, //    ### ### 
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2112 'b' (11 pixels wide)
+	0x00, 0x00, //            
+	0x70, 0x00, //  ###       
+	0x30, 0x00, //   ##       
+	0x30, 0x00, //   ##       
+	0x37, 0x00, //   ## ###   
+	0x39, 0x80, //   ###  ##  
+	0x30, 0xC0, //   ##    ## 
+	0x30, 0xC0, //   ##    ## 
+	0x30, 0xC0, //   ##    ## 
+	0x39, 0x80, //   ###  ##  
+	0x77, 0x00, //  ### ###   
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2144 'c' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x1E, 0x80, //    #### #  
+	0x31, 0x80, //   ##   ##  
+	0x60, 0x80, //  ##     #  
+	0x60, 0x00, //  ##        
+	0x60, 0x80, //  ##     #  
+	0x31, 0x80, //   ##   ##  
+	0x1F, 0x00, //    #####   
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2176 'd' (11 pixels wide)
+	0x00, 0x00, //            
+	0x03, 0x80, //       ###  
+	0x01, 0x80, //        ##  
+	0x01, 0x80, //        ##  
+	0x1D, 0x80, //    ### ##  
+	0x33, 0x80, //   ##  ###  
+	0x61, 0x80, //  ##    ##  
+	0x61, 0x80, //  ##    ##  
+	0x61, 0x80, //  ##    ##  
+	0x33, 0x80, //   ##  ###  
+	0x1D, 0xC0, //    ### ### 
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2208 'e' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x1F, 0x00, //    #####   
+	0x31, 0x80, //   ##   ##  
+	0x60, 0xC0, //  ##     ## 
+	0x7F, 0xC0, //  ######### 
+	0x60, 0x00, //  ##        
+	0x30, 0xC0, //   ##    ## 
+	0x1F, 0x80, //    ######  
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2240 'f' (11 pixels wide)
+	0x00, 0x00, //            
+	0x07, 0xE0, //      ######
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x3F, 0x80, //   #######  
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x3F, 0x80, //   #######  
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2272 'g' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x1D, 0xC0, //    ### ### 
+	0x33, 0x80, //   ##  ###  
+	0x61, 0x80, //  ##    ##  
+	0x61, 0x80, //  ##    ##  
+	0x61, 0x80, //  ##    ##  
+	0x33, 0x80, //   ##  ###  
+	0x1D, 0x80, //    ### ##  
+	0x01, 0x80, //        ##  
+	0x01, 0x80, //        ##  
+	0x1F, 0x00, //    #####   
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2304 'h' (11 pixels wide)
+	0x00, 0x00, //            
+	0x70, 0x00, //  ###       
+	0x30, 0x00, //   ##       
+	0x30, 0x00, //   ##       
+	0x37, 0x00, //   ## ###   
+	0x39, 0x80, //   ###  ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x7B, 0xC0, //  #### #### 
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2336 'i' (11 pixels wide)
+	0x00, 0x00, //            
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x00, 0x00, //            
+	0x1E, 0x00, //    ####    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x3F, 0xC0, //   ######## 
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2368 'j' (11 pixels wide)
+	0x00, 0x00, //            
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x00, 0x00, //            
+	0x3F, 0x00, //   ######   
+	0x03, 0x00, //       ##   
+	0x03, 0x00, //       ##   
+	0x03, 0x00, //       ##   
+	0x03, 0x00, //       ##   
+	0x03, 0x00, //       ##   
+	0x03, 0x00, //       ##   
+	0x03, 0x00, //       ##   
+	0x03, 0x00, //       ##   
+	0x3E, 0x00, //   #####    
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2400 'k' (11 pixels wide)
+	0x00, 0x00, //            
+	0x70, 0x00, //  ###       
+	0x30, 0x00, //   ##       
+	0x30, 0x00, //   ##       
+	0x37, 0x80, //   ## ####  
+	0x36, 0x00, //   ## ##    
+	0x3C, 0x00, //   ####     
+	0x3C, 0x00, //   ####     
+	0x36, 0x00, //   ## ##    
+	0x33, 0x00, //   ##  ##   
+	0x77, 0xC0, //  ### ##### 
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2432 'l' (11 pixels wide)
+	0x00, 0x00, //            
+	0x1E, 0x00, //    ####    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x3F, 0xC0, //   ######## 
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2464 'm' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x7F, 0x80, //  ########  
+	0x36, 0xC0, //   ## ## ## 
+	0x36, 0xC0, //   ## ## ## 
+	0x36, 0xC0, //   ## ## ## 
+	0x36, 0xC0, //   ## ## ## 
+	0x36, 0xC0, //   ## ## ## 
+	0x76, 0xE0, //  ### ## ###
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2496 'n' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x77, 0x00, //  ### ###   
+	0x39, 0x80, //   ###  ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x7B, 0xC0, //  #### #### 
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2528 'o' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x1F, 0x00, //    #####   
+	0x31, 0x80, //   ##   ##  
+	0x60, 0xC0, //  ##     ## 
+	0x60, 0xC0, //  ##     ## 
+	0x60, 0xC0, //  ##     ## 
+	0x31, 0x80, //   ##   ##  
+	0x1F, 0x00, //    #####   
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2560 'p' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x77, 0x00, //  ### ###   
+	0x39, 0x80, //   ###  ##  
+	0x30, 0xC0, //   ##    ## 
+	0x30, 0xC0, //   ##    ## 
+	0x30, 0xC0, //   ##    ## 
+	0x39, 0x80, //   ###  ##  
+	0x37, 0x00, //   ## ###   
+	0x30, 0x00, //   ##       
+	0x30, 0x00, //   ##       
+	0x7C, 0x00, //  #####     
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2592 'q' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x1D, 0xC0, //    ### ### 
+	0x33, 0x80, //   ##  ###  
+	0x61, 0x80, //  ##    ##  
+	0x61, 0x80, //  ##    ##  
+	0x61, 0x80, //  ##    ##  
+	0x33, 0x80, //   ##  ###  
+	0x1D, 0x80, //    ### ##  
+	0x01, 0x80, //        ##  
+	0x01, 0x80, //        ##  
+	0x07, 0xC0, //      ##### 
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2624 'r' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x7B, 0x80, //  #### ###  
+	0x1C, 0xC0, //    ###  ## 
+	0x18, 0x00, //    ##      
+	0x18, 0x00, //    ##      
+	0x18, 0x00, //    ##      
+	0x18, 0x00, //    ##      
+	0x7F, 0x00, //  #######   
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2656 's' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x1F, 0x80, //    ######  
+	0x31, 0x80, //   ##   ##  
+	0x3C, 0x00, //   ####     
+	0x1F, 0x00, //    #####   
+	0x03, 0x80, //       ###  
+	0x31, 0x80, //   ##   ##  
+	0x3F, 0x00, //   ######   
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2688 't' (11 pixels wide)
+	0x00, 0x00, //            
+	0x18, 0x00, //    ##      
+	0x18, 0x00, //    ##      
+	0x18, 0x00, //    ##      
+	0x7F, 0x00, //  #######   
+	0x18, 0x00, //    ##      
+	0x18, 0x00, //    ##      
+	0x18, 0x00, //    ##      
+	0x18, 0x00, //    ##      
+	0x18, 0x80, //    ##   #  
+	0x0F, 0x00, //     ####   
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2720 'u' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x73, 0x80, //  ###  ###  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x33, 0x80, //   ##  ###  
+	0x1D, 0xC0, //    ### ### 
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2752 'v' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x7B, 0xC0, //  #### #### 
+	0x31, 0x80, //   ##   ##  
+	0x31, 0x80, //   ##   ##  
+	0x1B, 0x00, //    ## ##   
+	0x1B, 0x00, //    ## ##   
+	0x0E, 0x00, //     ###    
+	0x0E, 0x00, //     ###    
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2784 'w' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0xF1, 0xE0, // ####   ####
+	0x60, 0xC0, //  ##     ## 
+	0x64, 0xC0, //  ##  #  ## 
+	0x6E, 0xC0, //  ## ### ## 
+	0x3B, 0x80, //   ### ###  
+	0x3B, 0x80, //   ### ###  
+	0x31, 0x80, //   ##   ##  
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2816 'x' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x7B, 0xC0, //  #### #### 
+	0x1B, 0x00, //    ## ##   
+	0x0E, 0x00, //     ###    
+	0x0E, 0x00, //     ###    
+	0x0E, 0x00, //     ###    
+	0x1B, 0x00, //    ## ##   
+	0x7B, 0xC0, //  #### #### 
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2848 'y' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x79, 0xE0, //  ####  ####
+	0x30, 0xC0, //   ##    ## 
+	0x19, 0x80, //    ##  ##  
+	0x19, 0x80, //    ##  ##  
+	0x0B, 0x00, //     # ##   
+	0x0F, 0x00, //     ####   
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x0C, 0x00, //     ##     
+	0x3E, 0x00, //   #####    
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2880 'z' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x3F, 0x80, //   #######  
+	0x21, 0x80, //   #    ##  
+	0x03, 0x00, //       ##   
+	0x0E, 0x00, //     ###    
+	0x18, 0x00, //    ##      
+	0x30, 0x80, //   ##    #  
+	0x3F, 0x80, //   #######  
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2912 '{' (11 pixels wide)
+	0x00, 0x00, //            
+	0x06, 0x00, //      ##    
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x18, 0x00, //    ##      
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x0C, 0x00, //     ##     
+	0x06, 0x00, //      ##    
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2944 '|' (11 pixels wide)
+	0x00, 0x00, //            
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @2976 '}' (11 pixels wide)
+	0x00, 0x00, //            
+	0x0C, 0x00, //     ##     
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x03, 0x00, //       ##   
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x06, 0x00, //      ##    
+	0x0C, 0x00, //     ##     
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+
+	// @3008 '~' (11 pixels wide)
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x18, 0x00, //    ##      
+	0x24, 0x80, //   #  #  #  
+	0x03, 0x00, //       ##   
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+	0x00, 0x00, //            
+};
+
+sFONT Font16 = {
+  Font16_Table,
+  11, /* Width */
+  16, /* Height */
+};
+
+/**
+  * @}
+  */ 
+
+
+/** @defgroup FONTS_Private_Function_Prototypes
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+
+
+/** @defgroup FONTS_Private_Functions
+  * @{
+  */
+    
+/**
+  * @}
+  */
+  
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */  
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/stmcube/Utilities/Fonts/font20.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/stmcube/Utilities/Fonts/font20.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/stmcube/Utilities/Fonts/font20.c	(revision 453)
@@ -0,0 +1,2223 @@
+/**
+  ******************************************************************************
+  * @file    font20.c
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    18-February-2014
+  * @brief   This file provides text font20 for STM32xx-EVAL's LCD driver. 
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "fonts.h"
+
+/** @addtogroup Utilities
+  * @{
+  */
+  
+/** @addtogroup STM32_EVAL
+  * @{
+  */ 
+
+/** @addtogroup Common
+  * @{
+  */
+
+/** @addtogroup FONTS
+  * @brief      This file provides text font20 for STM32xx-EVAL's LCD driver.
+  * @{
+  */  
+
+/** @defgroup FONTS_Private_Types
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+
+
+/** @defgroup FONTS_Private_Defines
+  * @{
+  */
+/**
+  * @}
+  */ 
+
+
+/** @defgroup FONTS_Private_Macros
+  * @{
+  */
+/**
+  * @}
+  */ 
+  
+
+/** @defgroup FONTS_Private_Variables
+  * @{
+  */
+
+// Character bitmaps for Courier New 15pt
+const uint8_t Font20_Table[] = 
+{
+	// @0 ' ' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @40 '!' (14 pixels wide)
+	0x00, 0x00, //               
+	0x07, 0x00, //      ###      
+	0x07, 0x00, //      ###      
+	0x07, 0x00, //      ###      
+	0x07, 0x00, //      ###      
+	0x07, 0x00, //      ###      
+	0x07, 0x00, //      ###      
+	0x07, 0x00, //      ###      
+	0x02, 0x00, //       #       
+	0x02, 0x00, //       #       
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x07, 0x00, //      ###      
+	0x07, 0x00, //      ###      
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @80 '"' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x1C, 0xE0, //    ###  ###   
+	0x1C, 0xE0, //    ###  ###   
+	0x1C, 0xE0, //    ###  ###   
+	0x08, 0x40, //     #    #    
+	0x08, 0x40, //     #    #    
+	0x08, 0x40, //     #    #    
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @120 '#' (14 pixels wide)
+	0x0C, 0xC0, //     ##  ##    
+	0x0C, 0xC0, //     ##  ##    
+	0x0C, 0xC0, //     ##  ##    
+	0x0C, 0xC0, //     ##  ##    
+	0x0C, 0xC0, //     ##  ##    
+	0x3F, 0xF0, //   ##########  
+	0x3F, 0xF0, //   ##########  
+	0x0C, 0xC0, //     ##  ##    
+	0x0C, 0xC0, //     ##  ##    
+	0x3F, 0xF0, //   ##########  
+	0x3F, 0xF0, //   ##########  
+	0x0C, 0xC0, //     ##  ##    
+	0x0C, 0xC0, //     ##  ##    
+	0x0C, 0xC0, //     ##  ##    
+	0x0C, 0xC0, //     ##  ##    
+	0x0C, 0xC0, //     ##  ##    
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @160 '$' (14 pixels wide)
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x07, 0xE0, //      ######   
+	0x0F, 0xE0, //     #######   
+	0x18, 0x60, //    ##    ##   
+	0x18, 0x00, //    ##         
+	0x1F, 0x00, //    #####      
+	0x0F, 0xC0, //     ######    
+	0x00, 0xE0, //         ###   
+	0x18, 0x60, //    ##    ##   
+	0x18, 0x60, //    ##    ##   
+	0x1F, 0xC0, //    #######    
+	0x1F, 0x80, //    ######     
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @200 '%' (14 pixels wide)
+	0x00, 0x00, //               
+	0x1C, 0x00, //    ###        
+	0x22, 0x00, //   #   #       
+	0x22, 0x00, //   #   #       
+	0x22, 0x00, //   #   #       
+	0x1C, 0x60, //    ###   ##   
+	0x01, 0xE0, //        ####   
+	0x0F, 0x80, //     #####     
+	0x3C, 0x00, //   ####        
+	0x31, 0xC0, //   ##   ###    
+	0x02, 0x20, //       #   #   
+	0x02, 0x20, //       #   #   
+	0x02, 0x20, //       #   #   
+	0x01, 0xC0, //        ###    
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @240 '&' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x03, 0xE0, //       #####   
+	0x0F, 0xE0, //     #######   
+	0x0C, 0x00, //     ##        
+	0x0C, 0x00, //     ##        
+	0x06, 0x00, //      ##       
+	0x0F, 0x30, //     ####  ##  
+	0x1F, 0xF0, //    #########  
+	0x19, 0xE0, //    ##  ####   
+	0x18, 0xC0, //    ##   ##    
+	0x1F, 0xF0, //    #########  
+	0x07, 0xB0, //      #### ##  
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @280 ''' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x03, 0x80, //       ###     
+	0x03, 0x80, //       ###     
+	0x03, 0x80, //       ###     
+	0x01, 0x00, //        #      
+	0x01, 0x00, //        #      
+	0x01, 0x00, //        #      
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @320 '(' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0xC0, //         ##    
+	0x00, 0xC0, //         ##    
+	0x01, 0x80, //        ##     
+	0x01, 0x80, //        ##     
+	0x01, 0x80, //        ##     
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x01, 0x80, //        ##     
+	0x01, 0x80, //        ##     
+	0x01, 0x80, //        ##     
+	0x00, 0xC0, //         ##    
+	0x00, 0xC0, //         ##    
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @360 ')' (14 pixels wide)
+	0x00, 0x00, //               
+	0x0C, 0x00, //     ##        
+	0x0C, 0x00, //     ##        
+	0x06, 0x00, //      ##       
+	0x06, 0x00, //      ##       
+	0x06, 0x00, //      ##       
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x06, 0x00, //      ##       
+	0x06, 0x00, //      ##       
+	0x06, 0x00, //      ##       
+	0x0C, 0x00, //     ##        
+	0x0C, 0x00, //     ##        
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @400 '*' (14 pixels wide)
+	0x00, 0x00, //               
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x1B, 0x60, //    ## ## ##   
+	0x1F, 0xE0, //    ########   
+	0x07, 0x80, //      ####     
+	0x07, 0x80, //      ####     
+	0x0F, 0xC0, //     ######    
+	0x0C, 0xC0, //     ##  ##    
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @440 '+' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x3F, 0xF0, //   ##########  
+	0x3F, 0xF0, //   ##########  
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @480 ',' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x03, 0x80, //       ###     
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x06, 0x00, //      ##       
+	0x06, 0x00, //      ##       
+	0x04, 0x00, //      #        
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @520 '-' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x3F, 0xE0, //   #########   
+	0x3F, 0xE0, //   #########   
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @560 '.' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x03, 0x80, //       ###     
+	0x03, 0x80, //       ###     
+	0x03, 0x80, //       ###     
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @600 '/' (14 pixels wide)
+	0x00, 0x60, //          ##   
+	0x00, 0x60, //          ##   
+	0x00, 0xC0, //         ##    
+	0x00, 0xC0, //         ##    
+	0x00, 0xC0, //         ##    
+	0x01, 0x80, //        ##     
+	0x01, 0x80, //        ##     
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x06, 0x00, //      ##       
+	0x06, 0x00, //      ##       
+	0x0C, 0x00, //     ##        
+	0x0C, 0x00, //     ##        
+	0x0C, 0x00, //     ##        
+	0x18, 0x00, //    ##         
+	0x18, 0x00, //    ##         
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @640 '0' (14 pixels wide)
+	0x00, 0x00, //               
+	0x0F, 0x80, //     #####     
+	0x1F, 0xC0, //    #######    
+	0x18, 0xC0, //    ##   ##    
+	0x30, 0x60, //   ##     ##   
+	0x30, 0x60, //   ##     ##   
+	0x30, 0x60, //   ##     ##   
+	0x30, 0x60, //   ##     ##   
+	0x30, 0x60, //   ##     ##   
+	0x30, 0x60, //   ##     ##   
+	0x30, 0x60, //   ##     ##   
+	0x18, 0xC0, //    ##   ##    
+	0x1F, 0xC0, //    #######    
+	0x0F, 0x80, //     #####     
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @680 '1' (14 pixels wide)
+	0x00, 0x00, //               
+	0x03, 0x00, //       ##      
+	0x1F, 0x00, //    #####      
+	0x1F, 0x00, //    #####      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x1F, 0xE0, //    ########   
+	0x1F, 0xE0, //    ########   
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @720 '2' (14 pixels wide)
+	0x00, 0x00, //               
+	0x0F, 0x80, //     #####     
+	0x1F, 0xC0, //    #######    
+	0x38, 0xE0, //   ###   ###   
+	0x30, 0x60, //   ##     ##   
+	0x00, 0x60, //          ##   
+	0x00, 0xC0, //         ##    
+	0x01, 0x80, //        ##     
+	0x03, 0x00, //       ##      
+	0x06, 0x00, //      ##       
+	0x0C, 0x00, //     ##        
+	0x18, 0x00, //    ##         
+	0x3F, 0xE0, //   #########   
+	0x3F, 0xE0, //   #########   
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @760 '3' (14 pixels wide)
+	0x00, 0x00, //               
+	0x0F, 0x80, //     #####     
+	0x3F, 0xC0, //   ########    
+	0x30, 0xE0, //   ##    ###   
+	0x00, 0x60, //          ##   
+	0x00, 0xE0, //         ###   
+	0x07, 0xC0, //      #####    
+	0x07, 0xC0, //      #####    
+	0x00, 0xE0, //         ###   
+	0x00, 0x60, //          ##   
+	0x00, 0x60, //          ##   
+	0x60, 0xE0, //  ##     ###   
+	0x7F, 0xC0, //  #########    
+	0x3F, 0x80, //   #######     
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @800 '4' (14 pixels wide)
+	0x00, 0x00, //               
+	0x01, 0xC0, //        ###    
+	0x03, 0xC0, //       ####    
+	0x03, 0xC0, //       ####    
+	0x06, 0xC0, //      ## ##    
+	0x0C, 0xC0, //     ##  ##    
+	0x0C, 0xC0, //     ##  ##    
+	0x18, 0xC0, //    ##   ##    
+	0x30, 0xC0, //   ##    ##    
+	0x3F, 0xE0, //   #########   
+	0x3F, 0xE0, //   #########   
+	0x00, 0xC0, //         ##    
+	0x03, 0xE0, //       #####   
+	0x03, 0xE0, //       #####   
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @840 '5' (14 pixels wide)
+	0x00, 0x00, //               
+	0x1F, 0xC0, //    #######    
+	0x1F, 0xC0, //    #######    
+	0x18, 0x00, //    ##         
+	0x18, 0x00, //    ##         
+	0x1F, 0x80, //    ######     
+	0x1F, 0xC0, //    #######    
+	0x18, 0xE0, //    ##   ###   
+	0x00, 0x60, //          ##   
+	0x00, 0x60, //          ##   
+	0x00, 0x60, //          ##   
+	0x30, 0xE0, //   ##    ###   
+	0x3F, 0xC0, //   ########    
+	0x1F, 0x80, //    ######     
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @880 '6' (14 pixels wide)
+	0x00, 0x00, //               
+	0x03, 0xE0, //       #####   
+	0x0F, 0xE0, //     #######   
+	0x1E, 0x00, //    ####       
+	0x18, 0x00, //    ##         
+	0x38, 0x00, //   ###         
+	0x37, 0x80, //   ## ####     
+	0x3F, 0xC0, //   ########    
+	0x38, 0xE0, //   ###   ###   
+	0x30, 0x60, //   ##     ##   
+	0x30, 0x60, //   ##     ##   
+	0x18, 0xE0, //    ##   ###   
+	0x1F, 0xC0, //    #######    
+	0x07, 0x80, //      ####     
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @920 '7' (14 pixels wide)
+	0x00, 0x00, //               
+	0x3F, 0xE0, //   #########   
+	0x3F, 0xE0, //   #########   
+	0x30, 0x60, //   ##     ##   
+	0x00, 0x60, //          ##   
+	0x00, 0xC0, //         ##    
+	0x00, 0xC0, //         ##    
+	0x00, 0xC0, //         ##    
+	0x01, 0x80, //        ##     
+	0x01, 0x80, //        ##     
+	0x01, 0x80, //        ##     
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @960 '8' (14 pixels wide)
+	0x00, 0x00, //               
+	0x0F, 0x80, //     #####     
+	0x1F, 0xC0, //    #######    
+	0x38, 0xE0, //   ###   ###   
+	0x30, 0x60, //   ##     ##   
+	0x38, 0xE0, //   ###   ###   
+	0x1F, 0xC0, //    #######    
+	0x1F, 0xC0, //    #######    
+	0x38, 0xE0, //   ###   ###   
+	0x30, 0x60, //   ##     ##   
+	0x30, 0x60, //   ##     ##   
+	0x38, 0xE0, //   ###   ###   
+	0x1F, 0xC0, //    #######    
+	0x0F, 0x80, //     #####     
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @1000 '9' (14 pixels wide)
+	0x00, 0x00, //               
+	0x0F, 0x00, //     ####      
+	0x1F, 0xC0, //    #######    
+	0x38, 0xC0, //   ###   ##    
+	0x30, 0x60, //   ##     ##   
+	0x30, 0x60, //   ##     ##   
+	0x38, 0xE0, //   ###   ###   
+	0x1F, 0xE0, //    ########   
+	0x0F, 0x60, //     #### ##   
+	0x00, 0xE0, //         ###   
+	0x00, 0xC0, //         ##    
+	0x03, 0xC0, //       ####    
+	0x3F, 0x80, //   #######     
+	0x3E, 0x00, //   #####       
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @1040 ':' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x03, 0x80, //       ###     
+	0x03, 0x80, //       ###     
+	0x03, 0x80, //       ###     
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x03, 0x80, //       ###     
+	0x03, 0x80, //       ###     
+	0x03, 0x80, //       ###     
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @1080 ';' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x01, 0xC0, //        ###    
+	0x01, 0xC0, //        ###    
+	0x01, 0xC0, //        ###    
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x03, 0x80, //       ###     
+	0x03, 0x00, //       ##      
+	0x06, 0x00, //      ##       
+	0x06, 0x00, //      ##       
+	0x04, 0x00, //      #        
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @1120 '<' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x30, //           ##  
+	0x00, 0xF0, //         ####  
+	0x03, 0xC0, //       ####    
+	0x07, 0x00, //      ###      
+	0x1C, 0x00, //    ###        
+	0x78, 0x00, //  ####         
+	0x1C, 0x00, //    ###        
+	0x07, 0x00, //      ###      
+	0x03, 0xC0, //       ####    
+	0x00, 0xF0, //         ####  
+	0x00, 0x30, //           ##  
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @1160 '=' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x7F, 0xF0, //  ###########  
+	0x7F, 0xF0, //  ###########  
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x7F, 0xF0, //  ###########  
+	0x7F, 0xF0, //  ###########  
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @1200 '>' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x30, 0x00, //   ##          
+	0x3C, 0x00, //   ####        
+	0x0F, 0x00, //     ####      
+	0x03, 0x80, //       ###     
+	0x00, 0xE0, //         ###   
+	0x00, 0x78, //          #### 
+	0x00, 0xE0, //         ###   
+	0x03, 0x80, //       ###     
+	0x0F, 0x00, //     ####      
+	0x3C, 0x00, //   ####        
+	0x30, 0x00, //   ##          
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @1240 '?' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x0F, 0x80, //     #####     
+	0x1F, 0xC0, //    #######    
+	0x18, 0x60, //    ##    ##   
+	0x18, 0x60, //    ##    ##   
+	0x00, 0x60, //          ##   
+	0x01, 0xC0, //        ###    
+	0x03, 0x80, //       ###     
+	0x03, 0x00, //       ##      
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x07, 0x00, //      ###      
+	0x07, 0x00, //      ###      
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @1280 '@' (14 pixels wide)
+	0x00, 0x00, //               
+	0x03, 0x80, //       ###     
+	0x0C, 0x80, //     ##  #     
+	0x08, 0x40, //     #    #    
+	0x10, 0x40, //    #     #    
+	0x10, 0x40, //    #     #    
+	0x11, 0xC0, //    #   ###    
+	0x12, 0x40, //    #  #  #    
+	0x12, 0x40, //    #  #  #    
+	0x12, 0x40, //    #  #  #    
+	0x11, 0xC0, //    #   ###    
+	0x10, 0x00, //    #          
+	0x08, 0x00, //     #         
+	0x08, 0x40, //     #    #    
+	0x07, 0x80, //      ####     
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @1320 'A' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x1F, 0x80, //    ######     
+	0x1F, 0x80, //    ######     
+	0x03, 0x80, //       ###     
+	0x06, 0xC0, //      ## ##    
+	0x06, 0xC0, //      ## ##    
+	0x0C, 0xC0, //     ##  ##    
+	0x0C, 0x60, //     ##   ##   
+	0x1F, 0xE0, //    ########   
+	0x1F, 0xE0, //    ########   
+	0x30, 0x30, //   ##      ##  
+	0x78, 0x78, //  ####    #### 
+	0x78, 0x78, //  ####    #### 
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @1360 'B' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x3F, 0x80, //   #######     
+	0x3F, 0xC0, //   ########    
+	0x18, 0x60, //    ##    ##   
+	0x18, 0x60, //    ##    ##   
+	0x18, 0xE0, //    ##   ###   
+	0x1F, 0xC0, //    #######    
+	0x1F, 0xE0, //    ########   
+	0x18, 0x70, //    ##    ###  
+	0x18, 0x30, //    ##     ##  
+	0x18, 0x30, //    ##     ##  
+	0x3F, 0xF0, //   ##########  
+	0x3F, 0xE0, //   #########   
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @1400 'C' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x07, 0xB0, //      #### ##  
+	0x0F, 0xF0, //     ########  
+	0x1C, 0x70, //    ###   ###  
+	0x38, 0x30, //   ###     ##  
+	0x30, 0x00, //   ##          
+	0x30, 0x00, //   ##          
+	0x30, 0x00, //   ##          
+	0x30, 0x00, //   ##          
+	0x38, 0x30, //   ###     ##  
+	0x1C, 0x70, //    ###   ###  
+	0x0F, 0xE0, //     #######   
+	0x07, 0xC0, //      #####    
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @1440 'D' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x7F, 0x80, //  ########     
+	0x7F, 0xC0, //  #########    
+	0x30, 0xE0, //   ##    ###   
+	0x30, 0x70, //   ##     ###  
+	0x30, 0x30, //   ##      ##  
+	0x30, 0x30, //   ##      ##  
+	0x30, 0x30, //   ##      ##  
+	0x30, 0x30, //   ##      ##  
+	0x30, 0x70, //   ##     ###  
+	0x30, 0xE0, //   ##    ###   
+	0x7F, 0xC0, //  #########    
+	0x7F, 0x80, //  ########     
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @1480 'E' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x3F, 0xF0, //   ##########  
+	0x3F, 0xF0, //   ##########  
+	0x18, 0x30, //    ##     ##  
+	0x18, 0x30, //    ##     ##  
+	0x19, 0x80, //    ##  ##     
+	0x1F, 0x80, //    ######     
+	0x1F, 0x80, //    ######     
+	0x19, 0x80, //    ##  ##     
+	0x18, 0x30, //    ##     ##  
+	0x18, 0x30, //    ##     ##  
+	0x3F, 0xF0, //   ##########  
+	0x3F, 0xF0, //   ##########  
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @1520 'F' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x3F, 0xF0, //   ##########  
+	0x3F, 0xF0, //   ##########  
+	0x18, 0x30, //    ##     ##  
+	0x18, 0x30, //    ##     ##  
+	0x19, 0x80, //    ##  ##     
+	0x1F, 0x80, //    ######     
+	0x1F, 0x80, //    ######     
+	0x19, 0x80, //    ##  ##     
+	0x18, 0x00, //    ##         
+	0x18, 0x00, //    ##         
+	0x3F, 0x00, //   ######      
+	0x3F, 0x00, //   ######      
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @1560 'G' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x07, 0xB0, //      #### ##  
+	0x1F, 0xF0, //    #########  
+	0x18, 0x70, //    ##    ###  
+	0x30, 0x30, //   ##      ##  
+	0x30, 0x00, //   ##          
+	0x30, 0x00, //   ##          
+	0x31, 0xF8, //   ##   ###### 
+	0x31, 0xF8, //   ##   ###### 
+	0x30, 0x30, //   ##      ##  
+	0x18, 0x30, //    ##     ##  
+	0x1F, 0xF0, //    #########  
+	0x07, 0xC0, //      #####    
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @1600 'H' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x3C, 0xF0, //   ####  ####  
+	0x3C, 0xF0, //   ####  ####  
+	0x18, 0x60, //    ##    ##   
+	0x18, 0x60, //    ##    ##   
+	0x18, 0x60, //    ##    ##   
+	0x1F, 0xE0, //    ########   
+	0x1F, 0xE0, //    ########   
+	0x18, 0x60, //    ##    ##   
+	0x18, 0x60, //    ##    ##   
+	0x18, 0x60, //    ##    ##   
+	0x3C, 0xF0, //   ####  ####  
+	0x3C, 0xF0, //   ####  ####  
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @1640 'I' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x1F, 0xE0, //    ########   
+	0x1F, 0xE0, //    ########   
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x1F, 0xE0, //    ########   
+	0x1F, 0xE0, //    ########   
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @1680 'J' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x03, 0xF8, //       ####### 
+	0x03, 0xF8, //       ####### 
+	0x00, 0x60, //          ##   
+	0x00, 0x60, //          ##   
+	0x00, 0x60, //          ##   
+	0x00, 0x60, //          ##   
+	0x30, 0x60, //   ##     ##   
+	0x30, 0x60, //   ##     ##   
+	0x30, 0x60, //   ##     ##   
+	0x30, 0xE0, //   ##    ###   
+	0x3F, 0xC0, //   ########    
+	0x0F, 0x80, //     #####     
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @1720 'K' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x3E, 0xF8, //   ##### ##### 
+	0x3E, 0xF8, //   ##### ##### 
+	0x18, 0xE0, //    ##   ###   
+	0x19, 0x80, //    ##  ##     
+	0x1B, 0x00, //    ## ##      
+	0x1F, 0x00, //    #####      
+	0x1D, 0x80, //    ### ##     
+	0x18, 0xC0, //    ##   ##    
+	0x18, 0xC0, //    ##   ##    
+	0x18, 0x60, //    ##    ##   
+	0x3E, 0x78, //   #####  #### 
+	0x3E, 0x38, //   #####   ### 
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @1760 'L' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x3F, 0x00, //   ######      
+	0x3F, 0x00, //   ######      
+	0x0C, 0x00, //     ##        
+	0x0C, 0x00, //     ##        
+	0x0C, 0x00, //     ##        
+	0x0C, 0x00, //     ##        
+	0x0C, 0x00, //     ##        
+	0x0C, 0x30, //     ##    ##  
+	0x0C, 0x30, //     ##    ##  
+	0x0C, 0x30, //     ##    ##  
+	0x3F, 0xF0, //   ##########  
+	0x3F, 0xF0, //   ##########  
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @1800 'M' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x78, 0x78, //  ####    #### 
+	0x78, 0x78, //  ####    #### 
+	0x38, 0x70, //   ###    ###  
+	0x3C, 0xF0, //   ####  ####  
+	0x34, 0xB0, //   ## #  # ##  
+	0x37, 0xB0, //   ## #### ##  
+	0x37, 0xB0, //   ## #### ##  
+	0x33, 0x30, //   ##  ##  ##  
+	0x33, 0x30, //   ##  ##  ##  
+	0x30, 0x30, //   ##      ##  
+	0x7C, 0xF8, //  #####  ##### 
+	0x7C, 0xF8, //  #####  ##### 
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @1840 'N' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x39, 0xF0, //   ###  #####  
+	0x3D, 0xF0, //   #### #####  
+	0x1C, 0x60, //    ###   ##   
+	0x1E, 0x60, //    ####  ##   
+	0x1E, 0x60, //    ####  ##   
+	0x1B, 0x60, //    ## ## ##   
+	0x1B, 0x60, //    ## ## ##   
+	0x19, 0xE0, //    ##  ####   
+	0x19, 0xE0, //    ##  ####   
+	0x18, 0xE0, //    ##   ###   
+	0x3E, 0xE0, //   ##### ###   
+	0x3E, 0x60, //   #####  ##   
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @1880 'O' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x07, 0x80, //      ####     
+	0x0F, 0xC0, //     ######    
+	0x1C, 0xE0, //    ###  ###   
+	0x38, 0x70, //   ###    ###  
+	0x30, 0x30, //   ##      ##  
+	0x30, 0x30, //   ##      ##  
+	0x30, 0x30, //   ##      ##  
+	0x30, 0x30, //   ##      ##  
+	0x38, 0x70, //   ###    ###  
+	0x1C, 0xE0, //    ###  ###   
+	0x0F, 0xC0, //     ######    
+	0x07, 0x80, //      ####     
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @1920 'P' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x3F, 0xC0, //   ########    
+	0x3F, 0xE0, //   #########   
+	0x18, 0x70, //    ##    ###  
+	0x18, 0x30, //    ##     ##  
+	0x18, 0x30, //    ##     ##  
+	0x18, 0x70, //    ##    ###  
+	0x1F, 0xE0, //    ########   
+	0x1F, 0xC0, //    #######    
+	0x18, 0x00, //    ##         
+	0x18, 0x00, //    ##         
+	0x3F, 0x00, //   ######      
+	0x3F, 0x00, //   ######      
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @1960 'Q' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x07, 0x80, //      ####     
+	0x0F, 0xC0, //     ######    
+	0x1C, 0xE0, //    ###  ###   
+	0x38, 0x70, //   ###    ###  
+	0x30, 0x30, //   ##      ##  
+	0x30, 0x30, //   ##      ##  
+	0x30, 0x30, //   ##      ##  
+	0x30, 0x30, //   ##      ##  
+	0x38, 0x70, //   ###    ###  
+	0x1C, 0xE0, //    ###  ###   
+	0x0F, 0xC0, //     ######    
+	0x07, 0x80, //      ####     
+	0x07, 0xB0, //      #### ##  
+	0x0F, 0xF0, //     ########  
+	0x0C, 0xE0, //     ##  ###   
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @2000 'R' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x3F, 0xC0, //   ########    
+	0x3F, 0xE0, //   #########   
+	0x18, 0x70, //    ##    ###  
+	0x18, 0x30, //    ##     ##  
+	0x18, 0x70, //    ##    ###  
+	0x1F, 0xE0, //    ########   
+	0x1F, 0xC0, //    #######    
+	0x18, 0xE0, //    ##   ###   
+	0x18, 0x60, //    ##    ##   
+	0x18, 0x70, //    ##    ###  
+	0x3E, 0x38, //   #####   ### 
+	0x3E, 0x18, //   #####    ## 
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @2040 'S' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x0F, 0xB0, //     ##### ##  
+	0x1F, 0xF0, //    #########  
+	0x38, 0x70, //   ###    ###  
+	0x30, 0x30, //   ##      ##  
+	0x38, 0x00, //   ###         
+	0x1F, 0x80, //    ######     
+	0x07, 0xE0, //      ######   
+	0x00, 0x70, //          ###  
+	0x30, 0x30, //   ##      ##  
+	0x38, 0x70, //   ###    ###  
+	0x3F, 0xE0, //   #########   
+	0x37, 0xC0, //   ## #####    
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @2080 'T' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x3F, 0xF0, //   ##########  
+	0x3F, 0xF0, //   ##########  
+	0x33, 0x30, //   ##  ##  ##  
+	0x33, 0x30, //   ##  ##  ##  
+	0x33, 0x30, //   ##  ##  ##  
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x0F, 0xC0, //     ######    
+	0x0F, 0xC0, //     ######    
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @2120 'U' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x3C, 0xF0, //   ####  ####  
+	0x3C, 0xF0, //   ####  ####  
+	0x18, 0x60, //    ##    ##   
+	0x18, 0x60, //    ##    ##   
+	0x18, 0x60, //    ##    ##   
+	0x18, 0x60, //    ##    ##   
+	0x18, 0x60, //    ##    ##   
+	0x18, 0x60, //    ##    ##   
+	0x18, 0x60, //    ##    ##   
+	0x1C, 0xE0, //    ###  ###   
+	0x0F, 0xC0, //     ######    
+	0x07, 0x80, //      ####     
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @2160 'V' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x78, 0xF0, //  ####   ####  
+	0x78, 0xF0, //  ####   ####  
+	0x30, 0x60, //   ##     ##   
+	0x30, 0x60, //   ##     ##   
+	0x18, 0xC0, //    ##   ##    
+	0x18, 0xC0, //    ##   ##    
+	0x0D, 0x80, //     ## ##     
+	0x0D, 0x80, //     ## ##     
+	0x0D, 0x80, //     ## ##     
+	0x07, 0x00, //      ###      
+	0x07, 0x00, //      ###      
+	0x07, 0x00, //      ###      
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @2200 'W' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x7C, 0x7C, //  #####   #####
+	0x7C, 0x7C, //  #####   #####
+	0x30, 0x18, //   ##       ## 
+	0x33, 0x98, //   ##  ###  ## 
+	0x33, 0x98, //   ##  ###  ## 
+	0x33, 0x98, //   ##  ###  ## 
+	0x36, 0xD8, //   ## ## ## ## 
+	0x16, 0xD0, //    # ## ## #  
+	0x1C, 0x70, //    ###   ###  
+	0x1C, 0x70, //    ###   ###  
+	0x1C, 0x70, //    ###   ###  
+	0x18, 0x30, //    ##     ##  
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @2240 'X' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x78, 0xF0, //  ####   ####  
+	0x78, 0xF0, //  ####   ####  
+	0x30, 0x60, //   ##     ##   
+	0x18, 0xC0, //    ##   ##    
+	0x0D, 0x80, //     ## ##     
+	0x07, 0x00, //      ###      
+	0x07, 0x00, //      ###      
+	0x0D, 0x80, //     ## ##     
+	0x18, 0xC0, //    ##   ##    
+	0x30, 0x60, //   ##     ##   
+	0x78, 0xF0, //  ####   ####  
+	0x78, 0xF0, //  ####   ####  
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @2280 'Y' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x3C, 0xF0, //   ####  ####  
+	0x3C, 0xF0, //   ####  ####  
+	0x18, 0x60, //    ##    ##   
+	0x0C, 0xC0, //     ##  ##    
+	0x07, 0x80, //      ####     
+	0x07, 0x80, //      ####     
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x0F, 0xC0, //     ######    
+	0x0F, 0xC0, //     ######    
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @2320 'Z' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x1F, 0xE0, //    ########   
+	0x1F, 0xE0, //    ########   
+	0x18, 0x60, //    ##    ##   
+	0x18, 0xC0, //    ##   ##    
+	0x01, 0x80, //        ##     
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x06, 0x00, //      ##       
+	0x0C, 0x60, //     ##   ##   
+	0x18, 0x60, //    ##    ##   
+	0x1F, 0xE0, //    ########   
+	0x1F, 0xE0, //    ########   
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @2360 '[' (14 pixels wide)
+	0x00, 0x00, //               
+	0x03, 0xC0, //       ####    
+	0x03, 0xC0, //       ####    
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0xC0, //       ####    
+	0x03, 0xC0, //       ####    
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @2400 '\' (14 pixels wide)
+	0x18, 0x00, //    ##         
+	0x18, 0x00, //    ##         
+	0x0C, 0x00, //     ##        
+	0x0C, 0x00, //     ##        
+	0x0C, 0x00, //     ##        
+	0x06, 0x00, //      ##       
+	0x06, 0x00, //      ##       
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x01, 0x80, //        ##     
+	0x01, 0x80, //        ##     
+	0x00, 0xC0, //         ##    
+	0x00, 0xC0, //         ##    
+	0x00, 0xC0, //         ##    
+	0x00, 0x60, //          ##   
+	0x00, 0x60, //          ##   
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @2440 ']' (14 pixels wide)
+	0x00, 0x00, //               
+	0x0F, 0x00, //     ####      
+	0x0F, 0x00, //     ####      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x0F, 0x00, //     ####      
+	0x0F, 0x00, //     ####      
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @2480 '^' (14 pixels wide)
+	0x00, 0x00, //               
+	0x02, 0x00, //       #       
+	0x07, 0x00, //      ###      
+	0x0D, 0x80, //     ## ##     
+	0x18, 0xC0, //    ##   ##    
+	0x30, 0x60, //   ##     ##   
+	0x20, 0x20, //   #       #   
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @2520 '_' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0xFF, 0xFC, // ##############
+	0xFF, 0xFC, // ##############
+
+	// @2560 '`' (14 pixels wide)
+	0x00, 0x00, //               
+	0x04, 0x00, //      #        
+	0x03, 0x00, //       ##      
+	0x00, 0x80, //         #     
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @2600 'a' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x0F, 0xC0, //     ######    
+	0x1F, 0xE0, //    ########   
+	0x00, 0x60, //          ##   
+	0x0F, 0xE0, //     #######   
+	0x1F, 0xE0, //    ########   
+	0x38, 0x60, //   ###    ##   
+	0x30, 0xE0, //   ##    ###   
+	0x3F, 0xF0, //   ##########  
+	0x1F, 0x70, //    ##### ###  
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @2640 'b' (14 pixels wide)
+	0x00, 0x00, //               
+	0x70, 0x00, //  ###          
+	0x70, 0x00, //  ###          
+	0x30, 0x00, //   ##          
+	0x30, 0x00, //   ##          
+	0x37, 0x80, //   ## ####     
+	0x3F, 0xE0, //   #########   
+	0x38, 0x60, //   ###    ##   
+	0x30, 0x30, //   ##      ##  
+	0x30, 0x30, //   ##      ##  
+	0x30, 0x30, //   ##      ##  
+	0x38, 0x60, //   ###    ##   
+	0x7F, 0xE0, //  ##########   
+	0x77, 0x80, //  ### ####     
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @2680 'c' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x07, 0xB0, //      #### ##  
+	0x1F, 0xF0, //    #########  
+	0x18, 0x30, //    ##     ##  
+	0x30, 0x30, //   ##      ##  
+	0x30, 0x00, //   ##          
+	0x30, 0x00, //   ##          
+	0x38, 0x30, //   ###     ##  
+	0x1F, 0xF0, //    #########  
+	0x0F, 0xC0, //     ######    
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @2720 'd' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x70, //          ###  
+	0x00, 0x70, //          ###  
+	0x00, 0x30, //           ##  
+	0x00, 0x30, //           ##  
+	0x07, 0xB0, //      #### ##  
+	0x1F, 0xF0, //    #########  
+	0x18, 0x70, //    ##    ###  
+	0x30, 0x30, //   ##      ##  
+	0x30, 0x30, //   ##      ##  
+	0x30, 0x30, //   ##      ##  
+	0x38, 0x70, //   ###    ###  
+	0x1F, 0xF8, //    ########## 
+	0x07, 0xB8, //      #### ### 
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @2760 'e' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x07, 0x80, //      ####     
+	0x1F, 0xE0, //    ########   
+	0x18, 0x60, //    ##    ##   
+	0x3F, 0xF0, //   ##########  
+	0x3F, 0xF0, //   ##########  
+	0x30, 0x00, //   ##          
+	0x18, 0x30, //    ##     ##  
+	0x1F, 0xF0, //    #########  
+	0x07, 0xC0, //      #####    
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @2800 'f' (14 pixels wide)
+	0x00, 0x00, //               
+	0x03, 0xF0, //       ######  
+	0x07, 0xF0, //      #######  
+	0x06, 0x00, //      ##       
+	0x06, 0x00, //      ##       
+	0x1F, 0xE0, //    ########   
+	0x1F, 0xE0, //    ########   
+	0x06, 0x00, //      ##       
+	0x06, 0x00, //      ##       
+	0x06, 0x00, //      ##       
+	0x06, 0x00, //      ##       
+	0x06, 0x00, //      ##       
+	0x1F, 0xE0, //    ########   
+	0x1F, 0xE0, //    ########   
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @2840 'g' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x07, 0xB8, //      #### ### 
+	0x1F, 0xF8, //    ########## 
+	0x18, 0x70, //    ##    ###  
+	0x30, 0x30, //   ##      ##  
+	0x30, 0x30, //   ##      ##  
+	0x30, 0x30, //   ##      ##  
+	0x18, 0x70, //    ##    ###  
+	0x1F, 0xF0, //    #########  
+	0x07, 0xB0, //      #### ##  
+	0x00, 0x30, //           ##  
+	0x00, 0x70, //          ###  
+	0x0F, 0xE0, //     #######   
+	0x0F, 0xC0, //     ######    
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @2880 'h' (14 pixels wide)
+	0x00, 0x00, //               
+	0x38, 0x00, //   ###         
+	0x38, 0x00, //   ###         
+	0x18, 0x00, //    ##         
+	0x18, 0x00, //    ##         
+	0x1B, 0xC0, //    ## ####    
+	0x1F, 0xE0, //    ########   
+	0x1C, 0x60, //    ###   ##   
+	0x18, 0x60, //    ##    ##   
+	0x18, 0x60, //    ##    ##   
+	0x18, 0x60, //    ##    ##   
+	0x18, 0x60, //    ##    ##   
+	0x3C, 0xF0, //   ####  ####  
+	0x3C, 0xF0, //   ####  ####  
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @2920 'i' (14 pixels wide)
+	0x00, 0x00, //               
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x1F, 0x00, //    #####      
+	0x1F, 0x00, //    #####      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x1F, 0xE0, //    ########   
+	0x1F, 0xE0, //    ########   
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @2960 'j' (14 pixels wide)
+	0x00, 0x00, //               
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x1F, 0xC0, //    #######    
+	0x1F, 0xC0, //    #######    
+	0x00, 0xC0, //         ##    
+	0x00, 0xC0, //         ##    
+	0x00, 0xC0, //         ##    
+	0x00, 0xC0, //         ##    
+	0x00, 0xC0, //         ##    
+	0x00, 0xC0, //         ##    
+	0x00, 0xC0, //         ##    
+	0x00, 0xC0, //         ##    
+	0x01, 0xC0, //        ###    
+	0x3F, 0x80, //   #######     
+	0x3F, 0x00, //   ######      
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @3000 'k' (14 pixels wide)
+	0x00, 0x00, //               
+	0x38, 0x00, //   ###         
+	0x38, 0x00, //   ###         
+	0x18, 0x00, //    ##         
+	0x18, 0x00, //    ##         
+	0x1B, 0xE0, //    ## #####   
+	0x1B, 0xE0, //    ## #####   
+	0x1B, 0x00, //    ## ##      
+	0x1E, 0x00, //    ####       
+	0x1E, 0x00, //    ####       
+	0x1B, 0x00, //    ## ##      
+	0x19, 0x80, //    ##  ##     
+	0x39, 0xF0, //   ###  #####  
+	0x39, 0xF0, //   ###  #####  
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @3040 'l' (14 pixels wide)
+	0x00, 0x00, //               
+	0x1F, 0x00, //    #####      
+	0x1F, 0x00, //    #####      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x1F, 0xE0, //    ########   
+	0x1F, 0xE0, //    ########   
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @3080 'm' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x7E, 0xE0, //  ###### ###   
+	0x7F, 0xF0, //  ###########  
+	0x33, 0x30, //   ##  ##  ##  
+	0x33, 0x30, //   ##  ##  ##  
+	0x33, 0x30, //   ##  ##  ##  
+	0x33, 0x30, //   ##  ##  ##  
+	0x33, 0x30, //   ##  ##  ##  
+	0x7B, 0xB8, //  #### ### ### 
+	0x7B, 0xB8, //  #### ### ### 
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @3120 'n' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x3B, 0xC0, //   ### ####    
+	0x3F, 0xE0, //   #########   
+	0x1C, 0x60, //    ###   ##   
+	0x18, 0x60, //    ##    ##   
+	0x18, 0x60, //    ##    ##   
+	0x18, 0x60, //    ##    ##   
+	0x18, 0x60, //    ##    ##   
+	0x3C, 0xF0, //   ####  ####  
+	0x3C, 0xF0, //   ####  ####  
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @3160 'o' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x07, 0x80, //      ####     
+	0x1F, 0xE0, //    ########   
+	0x18, 0x60, //    ##    ##   
+	0x30, 0x30, //   ##      ##  
+	0x30, 0x30, //   ##      ##  
+	0x30, 0x30, //   ##      ##  
+	0x18, 0x60, //    ##    ##   
+	0x1F, 0xE0, //    ########   
+	0x07, 0x80, //      ####     
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @3200 'p' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x77, 0x80, //  ### ####     
+	0x7F, 0xE0, //  ##########   
+	0x38, 0x60, //   ###    ##   
+	0x30, 0x30, //   ##      ##  
+	0x30, 0x30, //   ##      ##  
+	0x30, 0x30, //   ##      ##  
+	0x38, 0x60, //   ###    ##   
+	0x3F, 0xE0, //   #########   
+	0x37, 0x80, //   ## ####     
+	0x30, 0x00, //   ##          
+	0x30, 0x00, //   ##          
+	0x7C, 0x00, //  #####        
+	0x7C, 0x00, //  #####        
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @3240 'q' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x07, 0xB8, //      #### ### 
+	0x1F, 0xF8, //    ########## 
+	0x18, 0x70, //    ##    ###  
+	0x30, 0x30, //   ##      ##  
+	0x30, 0x30, //   ##      ##  
+	0x30, 0x30, //   ##      ##  
+	0x18, 0x70, //    ##    ###  
+	0x1F, 0xF0, //    #########  
+	0x07, 0xB0, //      #### ##  
+	0x00, 0x30, //           ##  
+	0x00, 0x30, //           ##  
+	0x00, 0xF8, //         ##### 
+	0x00, 0xF8, //         ##### 
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @3280 'r' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x3C, 0xE0, //   ####  ###   
+	0x3D, 0xF0, //   #### #####  
+	0x0F, 0x30, //     ####  ##  
+	0x0E, 0x00, //     ###       
+	0x0C, 0x00, //     ##        
+	0x0C, 0x00, //     ##        
+	0x0C, 0x00, //     ##        
+	0x3F, 0xC0, //   ########    
+	0x3F, 0xC0, //   ########    
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @3320 's' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x07, 0xE0, //      ######   
+	0x1F, 0xE0, //    ########   
+	0x18, 0x60, //    ##    ##   
+	0x1E, 0x00, //    ####       
+	0x0F, 0xC0, //     ######    
+	0x01, 0xE0, //        ####   
+	0x18, 0x60, //    ##    ##   
+	0x1F, 0xE0, //    ########   
+	0x1F, 0x80, //    ######     
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @3360 't' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x0C, 0x00, //     ##        
+	0x0C, 0x00, //     ##        
+	0x0C, 0x00, //     ##        
+	0x3F, 0xE0, //   #########   
+	0x3F, 0xE0, //   #########   
+	0x0C, 0x00, //     ##        
+	0x0C, 0x00, //     ##        
+	0x0C, 0x00, //     ##        
+	0x0C, 0x00, //     ##        
+	0x0C, 0x30, //     ##    ##  
+	0x0F, 0xF0, //     ########  
+	0x07, 0xC0, //      #####    
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @3400 'u' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x38, 0xE0, //   ###   ###   
+	0x38, 0xE0, //   ###   ###   
+	0x18, 0x60, //    ##    ##   
+	0x18, 0x60, //    ##    ##   
+	0x18, 0x60, //    ##    ##   
+	0x18, 0x60, //    ##    ##   
+	0x18, 0xE0, //    ##   ###   
+	0x1F, 0xF0, //    #########  
+	0x0F, 0x70, //     #### ###  
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @3440 'v' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x78, 0xF0, //  ####   ####  
+	0x78, 0xF0, //  ####   ####  
+	0x30, 0x60, //   ##     ##   
+	0x18, 0xC0, //    ##   ##    
+	0x18, 0xC0, //    ##   ##    
+	0x0D, 0x80, //     ## ##     
+	0x0D, 0x80, //     ## ##     
+	0x07, 0x00, //      ###      
+	0x07, 0x00, //      ###      
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @3480 'w' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x78, 0xF0, //  ####   ####  
+	0x78, 0xF0, //  ####   ####  
+	0x32, 0x60, //   ##  #  ##   
+	0x32, 0x60, //   ##  #  ##   
+	0x37, 0xE0, //   ## ######   
+	0x1D, 0xC0, //    ### ###    
+	0x1D, 0xC0, //    ### ###    
+	0x18, 0xC0, //    ##   ##    
+	0x18, 0xC0, //    ##   ##    
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @3520 'x' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x3C, 0xF0, //   ####  ####  
+	0x3C, 0xF0, //   ####  ####  
+	0x0C, 0xC0, //     ##  ##    
+	0x07, 0x80, //      ####     
+	0x03, 0x00, //       ##      
+	0x07, 0x80, //      ####     
+	0x0C, 0xC0, //     ##  ##    
+	0x3C, 0xF0, //   ####  ####  
+	0x3C, 0xF0, //   ####  ####  
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @3560 'y' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x78, 0xF0, //  ####   ####  
+	0x78, 0xF0, //  ####   ####  
+	0x30, 0x60, //   ##     ##   
+	0x18, 0xC0, //    ##   ##    
+	0x18, 0xC0, //    ##   ##    
+	0x0D, 0x80, //     ## ##     
+	0x0F, 0x80, //     #####     
+	0x07, 0x00, //      ###      
+	0x06, 0x00, //      ##       
+	0x06, 0x00, //      ##       
+	0x0C, 0x00, //     ##        
+	0x7F, 0x00, //  #######      
+	0x7F, 0x00, //  #######      
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @3600 'z' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x1F, 0xE0, //    ########   
+	0x1F, 0xE0, //    ########   
+	0x18, 0xC0, //    ##   ##    
+	0x01, 0x80, //        ##     
+	0x03, 0x00, //       ##      
+	0x06, 0x00, //      ##       
+	0x0C, 0x60, //     ##   ##   
+	0x1F, 0xE0, //    ########   
+	0x1F, 0xE0, //    ########   
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @3640 '{' (14 pixels wide)
+	0x00, 0x00, //               
+	0x01, 0xC0, //        ###    
+	0x03, 0xC0, //       ####    
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x07, 0x00, //      ###      
+	0x0E, 0x00, //     ###       
+	0x07, 0x00, //      ###      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0xC0, //       ####    
+	0x01, 0xC0, //        ###    
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @3680 '|' (14 pixels wide)
+	0x00, 0x00, //               
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x03, 0x00, //       ##      
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @3720 '}' (14 pixels wide)
+	0x00, 0x00, //               
+	0x1C, 0x00, //    ###        
+	0x1E, 0x00, //    ####       
+	0x06, 0x00, //      ##       
+	0x06, 0x00, //      ##       
+	0x06, 0x00, //      ##       
+	0x06, 0x00, //      ##       
+	0x06, 0x00, //      ##       
+	0x07, 0x00, //      ###      
+	0x03, 0x80, //       ###     
+	0x07, 0x00, //      ###      
+	0x06, 0x00, //      ##       
+	0x06, 0x00, //      ##       
+	0x06, 0x00, //      ##       
+	0x06, 0x00, //      ##       
+	0x1E, 0x00, //    ####       
+	0x1C, 0x00, //    ###        
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+
+	// @3760 '~' (14 pixels wide)
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x0E, 0x00, //     ###       
+	0x3F, 0x30, //   ######  ##  
+	0x33, 0xF0, //   ##  ######  
+	0x01, 0xE0, //        ####   
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+	0x00, 0x00, //               
+};
+
+
+sFONT Font20 = {
+  Font20_Table,
+  14, /* Width */
+  20, /* Height */
+};
+
+/**
+  * @}
+  */ 
+
+
+/** @defgroup FONTS_Private_Function_Prototypes
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+
+
+/** @defgroup FONTS_Private_Functions
+  * @{
+  */
+    
+/**
+  * @}
+  */
+  
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */  
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/stmcube/Utilities/Fonts/font24.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/stmcube/Utilities/Fonts/font24.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/stmcube/Utilities/Fonts/font24.c	(revision 453)
@@ -0,0 +1,2600 @@
+/**
+  ******************************************************************************
+  * @file    font24.c
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    18-February-2014
+  * @brief   This file provides text font24 for STM32xx-EVAL's LCD driver. 
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "fonts.h"
+
+/** @addtogroup Utilities
+  * @{
+  */
+  
+/** @addtogroup STM32_EVAL
+  * @{
+  */ 
+
+/** @addtogroup Common
+  * @{
+  */
+
+/** @addtogroup FONTS
+  * @brief      This file provides text font24 for STM32xx-EVAL's LCD driver.
+  * @{
+  */  
+
+/** @defgroup FONTS_Private_Types
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+
+
+/** @defgroup FONTS_Private_Defines
+  * @{
+  */
+/**
+  * @}
+  */ 
+
+
+/** @defgroup FONTS_Private_Macros
+  * @{
+  */
+/**
+  * @}
+  */ 
+  
+
+/** @defgroup FONTS_Private_Variables
+  * @{
+  */
+const uint8_t Font24_Table [] = 
+{
+	// @0 ' ' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @72 '!' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x03, 0x80, 0x00, //       ###        
+	0x03, 0x80, 0x00, //       ###        
+	0x03, 0x80, 0x00, //       ###        
+	0x03, 0x80, 0x00, //       ###        
+	0x03, 0x80, 0x00, //       ###        
+	0x03, 0x80, 0x00, //       ###        
+	0x03, 0x80, 0x00, //       ###        
+	0x03, 0x80, 0x00, //       ###        
+	0x03, 0x80, 0x00, //       ###        
+	0x01, 0x00, 0x00, //        #         
+	0x01, 0x00, 0x00, //        #         
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x03, 0x80, 0x00, //       ###        
+	0x03, 0x80, 0x00, //       ###        
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @144 '"' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x0E, 0x70, 0x00, //     ###  ###     
+	0x0E, 0x70, 0x00, //     ###  ###     
+	0x0E, 0x70, 0x00, //     ###  ###     
+	0x04, 0x20, 0x00, //      #    #      
+	0x04, 0x20, 0x00, //      #    #      
+	0x04, 0x20, 0x00, //      #    #      
+	0x04, 0x20, 0x00, //      #    #      
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @216 '#' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x06, 0x60, 0x00, //      ##  ##      
+	0x06, 0x60, 0x00, //      ##  ##      
+	0x06, 0x60, 0x00, //      ##  ##      
+	0x06, 0x60, 0x00, //      ##  ##      
+	0x06, 0x60, 0x00, //      ##  ##      
+	0x3F, 0xF8, 0x00, //   ###########    
+	0x3F, 0xF8, 0x00, //   ###########    
+	0x06, 0x60, 0x00, //      ##  ##      
+	0x0C, 0xC0, 0x00, //     ##  ##       
+	0x3F, 0xF8, 0x00, //   ###########    
+	0x3F, 0xF8, 0x00, //   ###########    
+	0x0C, 0xC0, 0x00, //     ##  ##       
+	0x0C, 0xC0, 0x00, //     ##  ##       
+	0x0C, 0xC0, 0x00, //     ##  ##       
+	0x0C, 0xC0, 0x00, //     ##  ##       
+	0x0C, 0xC0, 0x00, //     ##  ##       
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @288 '$' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x07, 0xB0, 0x00, //      #### ##     
+	0x0F, 0xF0, 0x00, //     ########     
+	0x18, 0x70, 0x00, //    ##    ###     
+	0x18, 0x70, 0x00, //    ##    ###     
+	0x1C, 0x00, 0x00, //    ###           
+	0x0F, 0x80, 0x00, //     #####        
+	0x07, 0xE0, 0x00, //      ######      
+	0x00, 0xF0, 0x00, //         ####     
+	0x18, 0x30, 0x00, //    ##     ##     
+	0x1C, 0x30, 0x00, //    ###    ##     
+	0x1C, 0x70, 0x00, //    ###   ###     
+	0x1F, 0xE0, 0x00, //    ########      
+	0x1B, 0xC0, 0x00, //    ## ####       
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @360 '%' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x07, 0x80, 0x00, //      ####        
+	0x0F, 0xC0, 0x00, //     ######       
+	0x1C, 0xE0, 0x00, //    ###  ###      
+	0x18, 0x60, 0x00, //    ##    ##      
+	0x18, 0x60, 0x00, //    ##    ##      
+	0x1C, 0xE0, 0x00, //    ###  ###      
+	0x0F, 0xF8, 0x00, //     #########    
+	0x07, 0xE0, 0x00, //      ######      
+	0x1F, 0xF0, 0x00, //    #########     
+	0x07, 0x38, 0x00, //      ###  ###    
+	0x06, 0x18, 0x00, //      ##    ##    
+	0x06, 0x18, 0x00, //      ##    ##    
+	0x07, 0x38, 0x00, //      ###  ###    
+	0x03, 0xF0, 0x00, //       ######     
+	0x01, 0xE0, 0x00, //        ####      
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @432 '&' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x03, 0xF0, 0x00, //       ######     
+	0x07, 0xF0, 0x00, //      #######     
+	0x0C, 0x60, 0x00, //     ##   ##      
+	0x0C, 0x00, 0x00, //     ##           
+	0x0C, 0x00, 0x00, //     ##           
+	0x06, 0x00, 0x00, //      ##          
+	0x07, 0x00, 0x00, //      ###         
+	0x0F, 0x9C, 0x00, //     #####  ###   
+	0x1D, 0xFC, 0x00, //    ### #######   
+	0x18, 0xF0, 0x00, //    ##   ####     
+	0x18, 0x70, 0x00, //    ##    ###     
+	0x0F, 0xFC, 0x00, //     ##########   
+	0x07, 0xDC, 0x00, //      ##### ###   
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @504 ''' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x03, 0x80, 0x00, //       ###        
+	0x03, 0x80, 0x00, //       ###        
+	0x03, 0x80, 0x00, //       ###        
+	0x01, 0x00, 0x00, //        #         
+	0x01, 0x00, 0x00, //        #         
+	0x01, 0x00, 0x00, //        #         
+	0x01, 0x00, 0x00, //        #         
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @576 '(' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x18, 0x00, //            ##    
+	0x00, 0x38, 0x00, //           ###    
+	0x00, 0x70, 0x00, //          ###     
+	0x00, 0xF0, 0x00, //         ####     
+	0x00, 0xE0, 0x00, //         ###      
+	0x00, 0xE0, 0x00, //         ###      
+	0x01, 0xC0, 0x00, //        ###       
+	0x01, 0xC0, 0x00, //        ###       
+	0x01, 0xC0, 0x00, //        ###       
+	0x01, 0xC0, 0x00, //        ###       
+	0x01, 0xC0, 0x00, //        ###       
+	0x01, 0xC0, 0x00, //        ###       
+	0x00, 0xE0, 0x00, //         ###      
+	0x00, 0xE0, 0x00, //         ###      
+	0x00, 0x70, 0x00, //          ###     
+	0x00, 0x70, 0x00, //          ###     
+	0x00, 0x38, 0x00, //           ###    
+	0x00, 0x18, 0x00, //            ##    
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @648 ')' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x18, 0x00, 0x00, //    ##            
+	0x1C, 0x00, 0x00, //    ###           
+	0x0E, 0x00, 0x00, //     ###          
+	0x0E, 0x00, 0x00, //     ###          
+	0x07, 0x00, 0x00, //      ###         
+	0x07, 0x00, 0x00, //      ###         
+	0x03, 0x80, 0x00, //       ###        
+	0x03, 0x80, 0x00, //       ###        
+	0x03, 0x80, 0x00, //       ###        
+	0x03, 0x80, 0x00, //       ###        
+	0x03, 0x80, 0x00, //       ###        
+	0x03, 0x80, 0x00, //       ###        
+	0x07, 0x00, 0x00, //      ###         
+	0x07, 0x00, 0x00, //      ###         
+	0x0F, 0x00, 0x00, //     ####         
+	0x0E, 0x00, 0x00, //     ###          
+	0x1C, 0x00, 0x00, //    ###           
+	0x18, 0x00, 0x00, //    ##            
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @720 '*' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x1D, 0xB8, 0x00, //    ### ## ###    
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x07, 0xE0, 0x00, //      ######      
+	0x03, 0xC0, 0x00, //       ####       
+	0x03, 0xC0, 0x00, //       ####       
+	0x06, 0x60, 0x00, //      ##  ##      
+	0x06, 0x60, 0x00, //      ##  ##      
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @792 '+' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x3F, 0xFC, 0x00, //   ############   
+	0x3F, 0xFC, 0x00, //   ############   
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @864 ',' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0xE0, 0x00, //         ###      
+	0x00, 0xC0, 0x00, //         ##       
+	0x01, 0xC0, 0x00, //        ###       
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x03, 0x00, 0x00, //       ##         
+	0x03, 0x00, 0x00, //       ##         
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @936 '-' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @1008 '.' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x03, 0xC0, 0x00, //       ####       
+	0x03, 0xC0, 0x00, //       ####       
+	0x03, 0xC0, 0x00, //       ####       
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @1080 '/' (17 pixels wide)
+	0x00, 0x18, 0x00, //            ##    
+	0x00, 0x18, 0x00, //            ##    
+	0x00, 0x38, 0x00, //           ###    
+	0x00, 0x30, 0x00, //           ##     
+	0x00, 0x70, 0x00, //          ###     
+	0x00, 0x60, 0x00, //          ##      
+	0x00, 0x60, 0x00, //          ##      
+	0x00, 0xC0, 0x00, //         ##       
+	0x00, 0xC0, 0x00, //         ##       
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x03, 0x00, 0x00, //       ##         
+	0x03, 0x00, 0x00, //       ##         
+	0x06, 0x00, 0x00, //      ##          
+	0x06, 0x00, 0x00, //      ##          
+	0x0E, 0x00, 0x00, //     ###          
+	0x0C, 0x00, 0x00, //     ##           
+	0x1C, 0x00, 0x00, //    ###           
+	0x18, 0x00, 0x00, //    ##            
+	0x18, 0x00, 0x00, //    ##            
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @1152 '0' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x03, 0xC0, 0x00, //       ####       
+	0x07, 0xE0, 0x00, //      ######      
+	0x0C, 0x30, 0x00, //     ##    ##     
+	0x0C, 0x30, 0x00, //     ##    ##     
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x0C, 0x30, 0x00, //     ##    ##     
+	0x0C, 0x30, 0x00, //     ##    ##     
+	0x07, 0xE0, 0x00, //      ######      
+	0x03, 0xC0, 0x00, //       ####       
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @1224 '1' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x80, 0x00, //         #        
+	0x07, 0x80, 0x00, //      ####        
+	0x1F, 0x80, 0x00, //    ######        
+	0x1D, 0x80, 0x00, //    ### ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @1296 '2' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x07, 0xC0, 0x00, //      #####       
+	0x1F, 0xF0, 0x00, //    #########     
+	0x38, 0x30, 0x00, //   ###     ##     
+	0x30, 0x18, 0x00, //   ##       ##    
+	0x30, 0x18, 0x00, //   ##       ##    
+	0x00, 0x18, 0x00, //            ##    
+	0x00, 0x30, 0x00, //           ##     
+	0x00, 0x60, 0x00, //          ##      
+	0x01, 0xC0, 0x00, //        ###       
+	0x03, 0x80, 0x00, //       ###        
+	0x06, 0x00, 0x00, //      ##          
+	0x0C, 0x00, 0x00, //     ##           
+	0x18, 0x00, 0x00, //    ##            
+	0x3F, 0xF8, 0x00, //   ###########    
+	0x3F, 0xF8, 0x00, //   ###########    
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @1368 '3' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x03, 0xC0, 0x00, //       ####       
+	0x0F, 0xE0, 0x00, //     #######      
+	0x0C, 0x70, 0x00, //     ##   ###     
+	0x00, 0x30, 0x00, //           ##     
+	0x00, 0x30, 0x00, //           ##     
+	0x00, 0x60, 0x00, //          ##      
+	0x03, 0xC0, 0x00, //       ####       
+	0x03, 0xE0, 0x00, //       #####      
+	0x00, 0x70, 0x00, //          ###     
+	0x00, 0x18, 0x00, //            ##    
+	0x00, 0x18, 0x00, //            ##    
+	0x00, 0x18, 0x00, //            ##    
+	0x18, 0x38, 0x00, //    ##     ###    
+	0x1F, 0xF0, 0x00, //    #########     
+	0x0F, 0xC0, 0x00, //     ######       
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @1440 '4' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0xE0, 0x00, //         ###      
+	0x01, 0xE0, 0x00, //        ####      
+	0x01, 0xE0, 0x00, //        ####      
+	0x03, 0x60, 0x00, //       ## ##      
+	0x06, 0x60, 0x00, //      ##  ##      
+	0x06, 0x60, 0x00, //      ##  ##      
+	0x0C, 0x60, 0x00, //     ##   ##      
+	0x0C, 0x60, 0x00, //     ##   ##      
+	0x18, 0x60, 0x00, //    ##    ##      
+	0x30, 0x60, 0x00, //   ##     ##      
+	0x3F, 0xF8, 0x00, //   ###########    
+	0x3F, 0xF8, 0x00, //   ###########    
+	0x00, 0x60, 0x00, //          ##      
+	0x03, 0xF8, 0x00, //       #######    
+	0x03, 0xF8, 0x00, //       #######    
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @1512 '5' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x1F, 0xF0, 0x00, //    #########     
+	0x1F, 0xF0, 0x00, //    #########     
+	0x18, 0x00, 0x00, //    ##            
+	0x18, 0x00, 0x00, //    ##            
+	0x18, 0x00, 0x00, //    ##            
+	0x1B, 0xC0, 0x00, //    ## ####       
+	0x1F, 0xF0, 0x00, //    #########     
+	0x1C, 0x30, 0x00, //    ###    ##     
+	0x00, 0x18, 0x00, //            ##    
+	0x00, 0x18, 0x00, //            ##    
+	0x00, 0x18, 0x00, //            ##    
+	0x00, 0x18, 0x00, //            ##    
+	0x30, 0x30, 0x00, //   ##      ##     
+	0x3F, 0xF0, 0x00, //   ##########     
+	0x0F, 0xC0, 0x00, //     ######       
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @1584 '6' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0xF8, 0x00, //         #####    
+	0x03, 0xF8, 0x00, //       #######    
+	0x07, 0x00, 0x00, //      ###         
+	0x0E, 0x00, 0x00, //     ###          
+	0x0C, 0x00, 0x00, //     ##           
+	0x18, 0x00, 0x00, //    ##            
+	0x1B, 0xC0, 0x00, //    ## ####       
+	0x1F, 0xF0, 0x00, //    #########     
+	0x1C, 0x30, 0x00, //    ###    ##     
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x0C, 0x38, 0x00, //     ##    ###    
+	0x0F, 0xF0, 0x00, //     ########     
+	0x03, 0xE0, 0x00, //       #####      
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @1656 '7' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x38, 0x00, //    ##     ###    
+	0x00, 0x30, 0x00, //           ##     
+	0x00, 0x30, 0x00, //           ##     
+	0x00, 0x70, 0x00, //          ###     
+	0x00, 0x60, 0x00, //          ##      
+	0x00, 0x60, 0x00, //          ##      
+	0x00, 0xE0, 0x00, //         ###      
+	0x00, 0xC0, 0x00, //         ##       
+	0x00, 0xC0, 0x00, //         ##       
+	0x01, 0xC0, 0x00, //        ###       
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @1728 '8' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x07, 0xE0, 0x00, //      ######      
+	0x0F, 0xF0, 0x00, //     ########     
+	0x1C, 0x38, 0x00, //    ###    ###    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x0C, 0x30, 0x00, //     ##    ##     
+	0x07, 0xE0, 0x00, //      ######      
+	0x07, 0xE0, 0x00, //      ######      
+	0x0C, 0x30, 0x00, //     ##    ##     
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x1C, 0x38, 0x00, //    ###    ###    
+	0x0F, 0xF0, 0x00, //     ########     
+	0x07, 0xE0, 0x00, //      ######      
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @1800 '9' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x07, 0xC0, 0x00, //      #####       
+	0x0F, 0xF0, 0x00, //     ########     
+	0x1C, 0x30, 0x00, //    ###    ##     
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x0C, 0x38, 0x00, //     ##    ###    
+	0x0F, 0xF8, 0x00, //     #########    
+	0x03, 0xD8, 0x00, //       #### ##    
+	0x00, 0x18, 0x00, //            ##    
+	0x00, 0x30, 0x00, //           ##     
+	0x00, 0x70, 0x00, //          ###     
+	0x00, 0xE0, 0x00, //         ###      
+	0x1F, 0xC0, 0x00, //    #######       
+	0x1F, 0x00, 0x00, //    #####         
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @1872 ':' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x03, 0xC0, 0x00, //       ####       
+	0x03, 0xC0, 0x00, //       ####       
+	0x03, 0xC0, 0x00, //       ####       
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x03, 0xC0, 0x00, //       ####       
+	0x03, 0xC0, 0x00, //       ####       
+	0x03, 0xC0, 0x00, //       ####       
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @1944 ';' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0xF0, 0x00, //         ####     
+	0x00, 0xF0, 0x00, //         ####     
+	0x00, 0xF0, 0x00, //         ####     
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0xE0, 0x00, //         ###      
+	0x01, 0xC0, 0x00, //        ###       
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x03, 0x00, 0x00, //       ##         
+	0x02, 0x00, 0x00, //       #          
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @2016 '<' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x1C, 0x00, //            ###   
+	0x00, 0x3C, 0x00, //           ####   
+	0x00, 0xF0, 0x00, //         ####     
+	0x03, 0xC0, 0x00, //       ####       
+	0x0F, 0x00, 0x00, //     ####         
+	0x3C, 0x00, 0x00, //   ####           
+	0xF0, 0x00, 0x00, // ####             
+	0x3C, 0x00, 0x00, //   ####           
+	0x0F, 0x00, 0x00, //     ####         
+	0x03, 0xC0, 0x00, //       ####       
+	0x00, 0xF0, 0x00, //         ####     
+	0x00, 0x3C, 0x00, //           ####   
+	0x00, 0x1C, 0x00, //            ###   
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @2088 '=' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x7F, 0xFC, 0x00, //  #############   
+	0x7F, 0xFC, 0x00, //  #############   
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x7F, 0xFC, 0x00, //  #############   
+	0x7F, 0xFC, 0x00, //  #############   
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @2160 '>' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x70, 0x00, 0x00, //  ###             
+	0x78, 0x00, 0x00, //  ####            
+	0x1E, 0x00, 0x00, //    ####          
+	0x07, 0x80, 0x00, //      ####        
+	0x01, 0xE0, 0x00, //        ####      
+	0x00, 0x78, 0x00, //          ####    
+	0x00, 0x1E, 0x00, //            ####  
+	0x00, 0x78, 0x00, //          ####    
+	0x01, 0xE0, 0x00, //        ####      
+	0x07, 0x80, 0x00, //      ####        
+	0x1E, 0x00, 0x00, //    ####          
+	0x78, 0x00, 0x00, //  ####            
+	0x70, 0x00, 0x00, //  ###             
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @2232 '?' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x07, 0xC0, 0x00, //      #####       
+	0x0F, 0xE0, 0x00, //     #######      
+	0x18, 0x70, 0x00, //    ##    ###     
+	0x18, 0x30, 0x00, //    ##     ##     
+	0x18, 0x30, 0x00, //    ##     ##     
+	0x00, 0x70, 0x00, //          ###     
+	0x00, 0xE0, 0x00, //         ###      
+	0x03, 0xC0, 0x00, //       ####       
+	0x03, 0x80, 0x00, //       ###        
+	0x03, 0x00, 0x00, //       ##         
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x07, 0x00, 0x00, //      ###         
+	0x07, 0x00, 0x00, //      ###         
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @2304 '@' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x03, 0xE0, 0x00, //       #####      
+	0x07, 0xF0, 0x00, //      #######     
+	0x0E, 0x38, 0x00, //     ###   ###    
+	0x0C, 0x18, 0x00, //     ##     ##    
+	0x18, 0x78, 0x00, //    ##    ####    
+	0x18, 0xF8, 0x00, //    ##   #####    
+	0x19, 0xD8, 0x00, //    ##  ### ##    
+	0x19, 0x98, 0x00, //    ##  ##  ##    
+	0x19, 0x98, 0x00, //    ##  ##  ##    
+	0x19, 0x98, 0x00, //    ##  ##  ##    
+	0x18, 0xF8, 0x00, //    ##   #####    
+	0x18, 0x78, 0x00, //    ##    ####    
+	0x18, 0x00, 0x00, //    ##            
+	0x0C, 0x00, 0x00, //     ##           
+	0x0E, 0x18, 0x00, //     ###    ##    
+	0x07, 0xF8, 0x00, //      ########    
+	0x03, 0xE0, 0x00, //       #####      
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @2376 'A' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x1F, 0x80, 0x00, //    ######        
+	0x1F, 0xC0, 0x00, //    #######       
+	0x01, 0xC0, 0x00, //        ###       
+	0x03, 0x60, 0x00, //       ## ##      
+	0x03, 0x60, 0x00, //       ## ##      
+	0x06, 0x30, 0x00, //      ##   ##     
+	0x06, 0x30, 0x00, //      ##   ##     
+	0x0C, 0x30, 0x00, //     ##    ##     
+	0x0F, 0xF8, 0x00, //     #########    
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x30, 0x0C, 0x00, //   ##        ##   
+	0xFC, 0x7F, 0x00, // ######   ####### 
+	0xFC, 0x7F, 0x00, // ######   ####### 
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @2448 'B' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x7F, 0xE0, 0x00, //  ##########      
+	0x7F, 0xF0, 0x00, //  ###########     
+	0x18, 0x38, 0x00, //    ##     ###    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x38, 0x00, //    ##     ###    
+	0x1F, 0xF0, 0x00, //    #########     
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x18, 0x1C, 0x00, //    ##      ###   
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x7F, 0xF8, 0x00, //  ############    
+	0x7F, 0xF0, 0x00, //  ###########     
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @2520 'C' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x03, 0xEC, 0x00, //       ##### ##   
+	0x0F, 0xFC, 0x00, //     ##########   
+	0x1C, 0x1C, 0x00, //    ###     ###   
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x30, 0x0C, 0x00, //   ##        ##   
+	0x30, 0x00, 0x00, //   ##             
+	0x30, 0x00, 0x00, //   ##             
+	0x30, 0x00, 0x00, //   ##             
+	0x30, 0x00, 0x00, //   ##             
+	0x30, 0x00, 0x00, //   ##             
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x1C, 0x1C, 0x00, //    ###     ###   
+	0x0F, 0xF8, 0x00, //     #########    
+	0x03, 0xF0, 0x00, //       ######     
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @2592 'D' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x7F, 0xC0, 0x00, //  #########       
+	0x7F, 0xF0, 0x00, //  ###########     
+	0x18, 0x38, 0x00, //    ##     ###    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x38, 0x00, //    ##     ###    
+	0x7F, 0xF0, 0x00, //  ###########     
+	0x7F, 0xE0, 0x00, //  ##########      
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @2664 'E' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x7F, 0xF8, 0x00, //  ############    
+	0x7F, 0xF8, 0x00, //  ############    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x19, 0x98, 0x00, //    ##  ##  ##    
+	0x19, 0x80, 0x00, //    ##  ##        
+	0x1F, 0x80, 0x00, //    ######        
+	0x1F, 0x80, 0x00, //    ######        
+	0x19, 0x80, 0x00, //    ##  ##        
+	0x19, 0x98, 0x00, //    ##  ##  ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x7F, 0xF8, 0x00, //  ############    
+	0x7F, 0xF8, 0x00, //  ############    
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @2736 'F' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x3F, 0xFC, 0x00, //   ############   
+	0x3F, 0xFC, 0x00, //   ############   
+	0x0C, 0x0C, 0x00, //     ##      ##   
+	0x0C, 0x0C, 0x00, //     ##      ##   
+	0x0C, 0xCC, 0x00, //     ##  ##  ##   
+	0x0C, 0xC0, 0x00, //     ##  ##       
+	0x0F, 0xC0, 0x00, //     ######       
+	0x0F, 0xC0, 0x00, //     ######       
+	0x0C, 0xC0, 0x00, //     ##  ##       
+	0x0C, 0xC0, 0x00, //     ##  ##       
+	0x0C, 0x00, 0x00, //     ##           
+	0x0C, 0x00, 0x00, //     ##           
+	0x3F, 0xC0, 0x00, //   ########       
+	0x3F, 0xC0, 0x00, //   ########       
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @2808 'G' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x03, 0xEC, 0x00, //       ##### ##   
+	0x0F, 0xFC, 0x00, //     ##########   
+	0x1C, 0x1C, 0x00, //    ###     ###   
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x30, 0x0C, 0x00, //   ##        ##   
+	0x30, 0x00, 0x00, //   ##             
+	0x30, 0x00, 0x00, //   ##             
+	0x30, 0xFE, 0x00, //   ##    #######  
+	0x30, 0xFE, 0x00, //   ##    #######  
+	0x30, 0x0C, 0x00, //   ##        ##   
+	0x38, 0x0C, 0x00, //   ###       ##   
+	0x1C, 0x1C, 0x00, //    ###     ###   
+	0x0F, 0xFC, 0x00, //     ##########   
+	0x03, 0xF0, 0x00, //       ######     
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @2880 'H' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x7E, 0x7E, 0x00, //  ######  ######  
+	0x7E, 0x7E, 0x00, //  ######  ######  
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x7E, 0x7E, 0x00, //  ######  ######  
+	0x7E, 0x7E, 0x00, //  ######  ######  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @2952 'I' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @3024 'J' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x07, 0xFE, 0x00, //      ##########  
+	0x07, 0xFE, 0x00, //      ##########  
+	0x00, 0x30, 0x00, //           ##     
+	0x00, 0x30, 0x00, //           ##     
+	0x00, 0x30, 0x00, //           ##     
+	0x00, 0x30, 0x00, //           ##     
+	0x00, 0x30, 0x00, //           ##     
+	0x30, 0x30, 0x00, //   ##      ##     
+	0x30, 0x30, 0x00, //   ##      ##     
+	0x30, 0x30, 0x00, //   ##      ##     
+	0x30, 0x30, 0x00, //   ##      ##     
+	0x30, 0x60, 0x00, //   ##     ##      
+	0x3F, 0xE0, 0x00, //   #########      
+	0x0F, 0x80, 0x00, //     #####        
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @3096 'K' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x7F, 0x3E, 0x00, //  #######  #####  
+	0x7F, 0x3E, 0x00, //  #######  #####  
+	0x18, 0x30, 0x00, //    ##     ##     
+	0x18, 0x60, 0x00, //    ##    ##      
+	0x18, 0xC0, 0x00, //    ##   ##       
+	0x19, 0x80, 0x00, //    ##  ##        
+	0x1B, 0x80, 0x00, //    ## ###        
+	0x1F, 0xC0, 0x00, //    #######       
+	0x1C, 0xE0, 0x00, //    ###  ###      
+	0x18, 0x70, 0x00, //    ##    ###     
+	0x18, 0x30, 0x00, //    ##     ##     
+	0x18, 0x38, 0x00, //    ##     ###    
+	0x7F, 0x1F, 0x00, //  #######   ##### 
+	0x7F, 0x1F, 0x00, //  #######   ##### 
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @3168 'L' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x7F, 0x80, 0x00, //  ########        
+	0x7F, 0x80, 0x00, //  ########        
+	0x0C, 0x00, 0x00, //     ##           
+	0x0C, 0x00, 0x00, //     ##           
+	0x0C, 0x00, 0x00, //     ##           
+	0x0C, 0x00, 0x00, //     ##           
+	0x0C, 0x00, 0x00, //     ##           
+	0x0C, 0x00, 0x00, //     ##           
+	0x0C, 0x0C, 0x00, //     ##      ##   
+	0x0C, 0x0C, 0x00, //     ##      ##   
+	0x0C, 0x0C, 0x00, //     ##      ##   
+	0x0C, 0x0C, 0x00, //     ##      ##   
+	0x7F, 0xFC, 0x00, //  #############   
+	0x7F, 0xFC, 0x00, //  #############   
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @3240 'M' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0xF0, 0x0F, 0x00, // ####        #### 
+	0xF8, 0x1F, 0x00, // #####      ##### 
+	0x38, 0x1C, 0x00, //   ###      ###   
+	0x3C, 0x3C, 0x00, //   ####    ####   
+	0x3C, 0x3C, 0x00, //   ####    ####   
+	0x36, 0x6C, 0x00, //   ## ##  ## ##   
+	0x36, 0x6C, 0x00, //   ## ##  ## ##   
+	0x33, 0xCC, 0x00, //   ##  ####  ##   
+	0x33, 0xCC, 0x00, //   ##  ####  ##   
+	0x31, 0x8C, 0x00, //   ##   ##   ##   
+	0x30, 0x0C, 0x00, //   ##        ##   
+	0x30, 0x0C, 0x00, //   ##        ##   
+	0xFE, 0x7F, 0x00, // #######  ####### 
+	0xFE, 0x7F, 0x00, // #######  ####### 
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @3312 'N' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x78, 0xFE, 0x00, //  ####   #######  
+	0x78, 0xFE, 0x00, //  ####   #######  
+	0x1C, 0x18, 0x00, //    ###     ##    
+	0x1E, 0x18, 0x00, //    ####    ##    
+	0x1F, 0x18, 0x00, //    #####   ##    
+	0x1B, 0x18, 0x00, //    ## ##   ##    
+	0x1B, 0x98, 0x00, //    ## ###  ##    
+	0x19, 0xD8, 0x00, //    ##  ### ##    
+	0x18, 0xD8, 0x00, //    ##   ## ##    
+	0x18, 0xF8, 0x00, //    ##   #####    
+	0x18, 0x78, 0x00, //    ##    ####    
+	0x18, 0x38, 0x00, //    ##     ###    
+	0x7F, 0x18, 0x00, //  #######   ##    
+	0x7F, 0x18, 0x00, //  #######   ##    
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @3384 'O' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x03, 0xC0, 0x00, //       ####       
+	0x0F, 0xF0, 0x00, //     ########     
+	0x1C, 0x38, 0x00, //    ###    ###    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x38, 0x1C, 0x00, //   ###      ###   
+	0x30, 0x0C, 0x00, //   ##        ##   
+	0x30, 0x0C, 0x00, //   ##        ##   
+	0x30, 0x0C, 0x00, //   ##        ##   
+	0x30, 0x0C, 0x00, //   ##        ##   
+	0x38, 0x1C, 0x00, //   ###      ###   
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x1C, 0x38, 0x00, //    ###    ###    
+	0x0F, 0xF0, 0x00, //     ########     
+	0x03, 0xC0, 0x00, //       ####       
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @3456 'P' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x3F, 0xF0, 0x00, //   ##########     
+	0x3F, 0xF8, 0x00, //   ###########    
+	0x0C, 0x1C, 0x00, //     ##     ###   
+	0x0C, 0x0C, 0x00, //     ##      ##   
+	0x0C, 0x0C, 0x00, //     ##      ##   
+	0x0C, 0x0C, 0x00, //     ##      ##   
+	0x0C, 0x18, 0x00, //     ##     ##    
+	0x0F, 0xF8, 0x00, //     #########    
+	0x0F, 0xE0, 0x00, //     #######      
+	0x0C, 0x00, 0x00, //     ##           
+	0x0C, 0x00, 0x00, //     ##           
+	0x0C, 0x00, 0x00, //     ##           
+	0x3F, 0xC0, 0x00, //   ########       
+	0x3F, 0xC0, 0x00, //   ########       
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @3528 'Q' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x03, 0xC0, 0x00, //       ####       
+	0x0F, 0xF0, 0x00, //     ########     
+	0x1C, 0x38, 0x00, //    ###    ###    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x38, 0x1C, 0x00, //   ###      ###   
+	0x30, 0x0C, 0x00, //   ##        ##   
+	0x30, 0x0C, 0x00, //   ##        ##   
+	0x30, 0x0C, 0x00, //   ##        ##   
+	0x30, 0x0C, 0x00, //   ##        ##   
+	0x38, 0x1C, 0x00, //   ###      ###   
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x1C, 0x38, 0x00, //    ###    ###    
+	0x0F, 0xF0, 0x00, //     ########     
+	0x07, 0xC0, 0x00, //      #####       
+	0x07, 0xCC, 0x00, //      #####  ##   
+	0x0F, 0xFC, 0x00, //     ##########   
+	0x0C, 0x38, 0x00, //     ##    ###    
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @3600 'R' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x7F, 0xE0, 0x00, //  ##########      
+	0x7F, 0xF0, 0x00, //  ###########     
+	0x18, 0x38, 0x00, //    ##     ###    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x38, 0x00, //    ##     ###    
+	0x1F, 0xF0, 0x00, //    #########     
+	0x1F, 0xC0, 0x00, //    #######       
+	0x18, 0xE0, 0x00, //    ##   ###      
+	0x18, 0x70, 0x00, //    ##    ###     
+	0x18, 0x30, 0x00, //    ##     ##     
+	0x18, 0x38, 0x00, //    ##     ###    
+	0x7F, 0x1E, 0x00, //  #######   ####  
+	0x7F, 0x0E, 0x00, //  #######    ###  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @3672 'S' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x07, 0xD8, 0x00, //      ##### ##    
+	0x0F, 0xF8, 0x00, //     #########    
+	0x1C, 0x38, 0x00, //    ###    ###    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x1E, 0x00, 0x00, //    ####          
+	0x0F, 0xC0, 0x00, //     ######       
+	0x03, 0xF0, 0x00, //       ######     
+	0x00, 0x78, 0x00, //          ####    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x1C, 0x38, 0x00, //    ###    ###    
+	0x1F, 0xF0, 0x00, //    #########     
+	0x1B, 0xE0, 0x00, //    ## #####      
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @3744 'T' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x3F, 0xFC, 0x00, //   ############   
+	0x3F, 0xFC, 0x00, //   ############   
+	0x31, 0x8C, 0x00, //   ##   ##   ##   
+	0x31, 0x8C, 0x00, //   ##   ##   ##   
+	0x31, 0x8C, 0x00, //   ##   ##   ##   
+	0x31, 0x8C, 0x00, //   ##   ##   ##   
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x0F, 0xF0, 0x00, //     ########     
+	0x0F, 0xF0, 0x00, //     ########     
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @3816 'U' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x7E, 0x7E, 0x00, //  ######  ######  
+	0x7E, 0x7E, 0x00, //  ######  ######  
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x0C, 0x30, 0x00, //     ##    ##     
+	0x0F, 0xF0, 0x00, //     ########     
+	0x03, 0xC0, 0x00, //       ####       
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @3888 'V' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x7F, 0x7F, 0x00, //  ####### ####### 
+	0x7F, 0x7F, 0x00, //  ####### ####### 
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x0C, 0x18, 0x00, //     ##     ##    
+	0x0C, 0x18, 0x00, //     ##     ##    
+	0x0C, 0x18, 0x00, //     ##     ##    
+	0x06, 0x30, 0x00, //      ##   ##     
+	0x06, 0x30, 0x00, //      ##   ##     
+	0x03, 0x60, 0x00, //       ## ##      
+	0x03, 0x60, 0x00, //       ## ##      
+	0x03, 0x60, 0x00, //       ## ##      
+	0x01, 0xC0, 0x00, //        ###       
+	0x01, 0xC0, 0x00, //        ###       
+	0x00, 0x80, 0x00, //         #        
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @3960 'W' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0xFE, 0x3F, 0x80, // #######   #######
+	0xFE, 0x3F, 0x80, // #######   #######
+	0x30, 0x06, 0x00, //   ##         ##  
+	0x30, 0x06, 0x00, //   ##         ##  
+	0x30, 0x86, 0x00, //   ##    #    ##  
+	0x19, 0xCC, 0x00, //    ##  ###  ##   
+	0x19, 0xCC, 0x00, //    ##  ###  ##   
+	0x1B, 0x6C, 0x00, //    ## ## ## ##   
+	0x1B, 0x6C, 0x00, //    ## ## ## ##   
+	0x1E, 0x7C, 0x00, //    ####  #####   
+	0x0E, 0x38, 0x00, //     ###   ###    
+	0x0E, 0x38, 0x00, //     ###   ###    
+	0x0C, 0x18, 0x00, //     ##     ##    
+	0x0C, 0x18, 0x00, //     ##     ##    
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @4032 'X' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x7E, 0x7E, 0x00, //  ######  ######  
+	0x7E, 0x7E, 0x00, //  ######  ######  
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x0C, 0x30, 0x00, //     ##    ##     
+	0x06, 0x60, 0x00, //      ##  ##      
+	0x03, 0xC0, 0x00, //       ####       
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x03, 0xC0, 0x00, //       ####       
+	0x06, 0x60, 0x00, //      ##  ##      
+	0x0C, 0x30, 0x00, //     ##    ##     
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x7E, 0x7E, 0x00, //  ######  ######  
+	0x7E, 0x7E, 0x00, //  ######  ######  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @4104 'Y' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x7C, 0x7E, 0x00, //  #####   ######  
+	0x7C, 0x7E, 0x00, //  #####   ######  
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x0C, 0x30, 0x00, //     ##    ##     
+	0x06, 0x60, 0x00, //      ##  ##      
+	0x06, 0x60, 0x00, //      ##  ##      
+	0x03, 0xC0, 0x00, //       ####       
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x0F, 0xF0, 0x00, //     ########     
+	0x0F, 0xF0, 0x00, //     ########     
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @4176 'Z' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x30, 0x00, //    ##     ##     
+	0x18, 0x60, 0x00, //    ##    ##      
+	0x18, 0xC0, 0x00, //    ##   ##       
+	0x01, 0x80, 0x00, //        ##        
+	0x03, 0x00, 0x00, //       ##         
+	0x06, 0x18, 0x00, //      ##    ##    
+	0x0C, 0x18, 0x00, //     ##     ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x30, 0x18, 0x00, //   ##       ##    
+	0x3F, 0xF8, 0x00, //   ###########    
+	0x3F, 0xF8, 0x00, //   ###########    
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @4248 '[' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x01, 0xF0, 0x00, //        #####     
+	0x01, 0xF0, 0x00, //        #####     
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0xF0, 0x00, //        #####     
+	0x01, 0xF0, 0x00, //        #####     
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @4320 '\' (17 pixels wide)
+	0x18, 0x00, 0x00, //    ##            
+	0x18, 0x00, 0x00, //    ##            
+	0x1C, 0x00, 0x00, //    ###           
+	0x0C, 0x00, 0x00, //     ##           
+	0x0E, 0x00, 0x00, //     ###          
+	0x06, 0x00, 0x00, //      ##          
+	0x06, 0x00, 0x00, //      ##          
+	0x03, 0x00, 0x00, //       ##         
+	0x03, 0x00, 0x00, //       ##         
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x00, 0xC0, 0x00, //         ##       
+	0x00, 0xC0, 0x00, //         ##       
+	0x00, 0x60, 0x00, //          ##      
+	0x00, 0x60, 0x00, //          ##      
+	0x00, 0x70, 0x00, //          ###     
+	0x00, 0x30, 0x00, //           ##     
+	0x00, 0x38, 0x00, //           ###    
+	0x00, 0x18, 0x00, //            ##    
+	0x00, 0x18, 0x00, //            ##    
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @4392 ']' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x0F, 0x80, 0x00, //     #####        
+	0x0F, 0x80, 0x00, //     #####        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x0F, 0x80, 0x00, //     #####        
+	0x0F, 0x80, 0x00, //     #####        
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @4464 '^' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x80, 0x00, //         #        
+	0x01, 0xC0, 0x00, //        ###       
+	0x03, 0xE0, 0x00, //       #####      
+	0x07, 0x70, 0x00, //      ### ###     
+	0x06, 0x30, 0x00, //      ##   ##     
+	0x0C, 0x18, 0x00, //     ##     ##    
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x10, 0x04, 0x00, //    #         #   
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @4536 '_' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0xFF, 0xFF, 0x00, // ################ 
+	0xFF, 0xFF, 0x00, // ################ 
+
+	// @4608 '`' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x03, 0x00, 0x00, //       ##         
+	0x03, 0x80, 0x00, //       ###        
+	0x00, 0xE0, 0x00, //         ###      
+	0x00, 0x60, 0x00, //          ##      
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @4680 'a' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x0F, 0xC0, 0x00, //     ######       
+	0x1F, 0xE0, 0x00, //    ########      
+	0x00, 0x30, 0x00, //           ##     
+	0x00, 0x30, 0x00, //           ##     
+	0x07, 0xF0, 0x00, //      #######     
+	0x1F, 0xF0, 0x00, //    #########     
+	0x38, 0x30, 0x00, //   ###     ##     
+	0x30, 0x30, 0x00, //   ##      ##     
+	0x30, 0x70, 0x00, //   ##     ###     
+	0x1F, 0xFC, 0x00, //    ###########   
+	0x0F, 0xBC, 0x00, //     ##### ####   
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @4752 'b' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x78, 0x00, 0x00, //  ####            
+	0x78, 0x00, 0x00, //  ####            
+	0x18, 0x00, 0x00, //    ##            
+	0x18, 0x00, 0x00, //    ##            
+	0x1B, 0xE0, 0x00, //    ## #####      
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x1C, 0x18, 0x00, //    ###     ##    
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x1C, 0x18, 0x00, //    ###     ##    
+	0x7F, 0xF8, 0x00, //  ############    
+	0x7B, 0xE0, 0x00, //  #### #####      
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @4824 'c' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x03, 0xEC, 0x00, //       ##### ##   
+	0x0F, 0xFC, 0x00, //     ##########   
+	0x1C, 0x1C, 0x00, //    ###     ###   
+	0x38, 0x0C, 0x00, //   ###       ##   
+	0x30, 0x0C, 0x00, //   ##        ##   
+	0x30, 0x00, 0x00, //   ##             
+	0x30, 0x00, 0x00, //   ##             
+	0x38, 0x0C, 0x00, //   ###       ##   
+	0x1C, 0x1C, 0x00, //    ###     ###   
+	0x0F, 0xF8, 0x00, //     #########    
+	0x03, 0xF0, 0x00, //       ######     
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @4896 'd' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x78, 0x00, //          ####    
+	0x00, 0x78, 0x00, //          ####    
+	0x00, 0x18, 0x00, //            ##    
+	0x00, 0x18, 0x00, //            ##    
+	0x07, 0xD8, 0x00, //      ##### ##    
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x18, 0x38, 0x00, //    ##     ###    
+	0x30, 0x18, 0x00, //   ##       ##    
+	0x30, 0x18, 0x00, //   ##       ##    
+	0x30, 0x18, 0x00, //   ##       ##    
+	0x30, 0x18, 0x00, //   ##       ##    
+	0x30, 0x18, 0x00, //   ##       ##    
+	0x18, 0x38, 0x00, //    ##     ###    
+	0x1F, 0xFE, 0x00, //    ############  
+	0x07, 0xDE, 0x00, //      ##### ####  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @4968 'e' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x07, 0xE0, 0x00, //      ######      
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x30, 0x0C, 0x00, //   ##        ##   
+	0x3F, 0xFC, 0x00, //   ############   
+	0x3F, 0xFC, 0x00, //   ############   
+	0x30, 0x00, 0x00, //   ##             
+	0x30, 0x00, 0x00, //   ##             
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x1F, 0xFC, 0x00, //    ###########   
+	0x07, 0xF0, 0x00, //      #######     
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @5040 'f' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x01, 0xFC, 0x00, //        #######   
+	0x03, 0xFC, 0x00, //       ########   
+	0x06, 0x00, 0x00, //      ##          
+	0x06, 0x00, 0x00, //      ##          
+	0x3F, 0xF8, 0x00, //   ###########    
+	0x3F, 0xF8, 0x00, //   ###########    
+	0x06, 0x00, 0x00, //      ##          
+	0x06, 0x00, 0x00, //      ##          
+	0x06, 0x00, 0x00, //      ##          
+	0x06, 0x00, 0x00, //      ##          
+	0x06, 0x00, 0x00, //      ##          
+	0x06, 0x00, 0x00, //      ##          
+	0x06, 0x00, 0x00, //      ##          
+	0x3F, 0xF0, 0x00, //   ##########     
+	0x3F, 0xF0, 0x00, //   ##########     
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @5112 'g' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x07, 0xDE, 0x00, //      ##### ####  
+	0x1F, 0xFE, 0x00, //    ############  
+	0x18, 0x38, 0x00, //    ##     ###    
+	0x30, 0x18, 0x00, //   ##       ##    
+	0x30, 0x18, 0x00, //   ##       ##    
+	0x30, 0x18, 0x00, //   ##       ##    
+	0x30, 0x18, 0x00, //   ##       ##    
+	0x30, 0x18, 0x00, //   ##       ##    
+	0x18, 0x38, 0x00, //    ##     ###    
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x07, 0xD8, 0x00, //      ##### ##    
+	0x00, 0x18, 0x00, //            ##    
+	0x00, 0x18, 0x00, //            ##    
+	0x00, 0x38, 0x00, //           ###    
+	0x0F, 0xF0, 0x00, //     ########     
+	0x0F, 0xC0, 0x00, //     ######       
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @5184 'h' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x78, 0x00, 0x00, //  ####            
+	0x78, 0x00, 0x00, //  ####            
+	0x18, 0x00, 0x00, //    ##            
+	0x18, 0x00, 0x00, //    ##            
+	0x1B, 0xE0, 0x00, //    ## #####      
+	0x1F, 0xF0, 0x00, //    #########     
+	0x1C, 0x38, 0x00, //    ###    ###    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x7E, 0x7E, 0x00, //  ######  ######  
+	0x7E, 0x7E, 0x00, //  ######  ######  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @5256 'i' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x1F, 0x80, 0x00, //    ######        
+	0x1F, 0x80, 0x00, //    ######        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x3F, 0xFC, 0x00, //   ############   
+	0x3F, 0xFC, 0x00, //   ############   
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @5328 'j' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0xC0, 0x00, //         ##       
+	0x00, 0xC0, 0x00, //         ##       
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x1F, 0xF0, 0x00, //    #########     
+	0x1F, 0xF0, 0x00, //    #########     
+	0x00, 0x30, 0x00, //           ##     
+	0x00, 0x30, 0x00, //           ##     
+	0x00, 0x30, 0x00, //           ##     
+	0x00, 0x30, 0x00, //           ##     
+	0x00, 0x30, 0x00, //           ##     
+	0x00, 0x30, 0x00, //           ##     
+	0x00, 0x30, 0x00, //           ##     
+	0x00, 0x30, 0x00, //           ##     
+	0x00, 0x30, 0x00, //           ##     
+	0x00, 0x30, 0x00, //           ##     
+	0x00, 0x30, 0x00, //           ##     
+	0x00, 0x70, 0x00, //          ###     
+	0x1F, 0xE0, 0x00, //    ########      
+	0x1F, 0x80, 0x00, //    ######        
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @5400 'k' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x3C, 0x00, 0x00, //   ####           
+	0x3C, 0x00, 0x00, //   ####           
+	0x0C, 0x00, 0x00, //     ##           
+	0x0C, 0x00, 0x00, //     ##           
+	0x0C, 0xF8, 0x00, //     ##  #####    
+	0x0C, 0xF8, 0x00, //     ##  #####    
+	0x0C, 0xC0, 0x00, //     ##  ##       
+	0x0D, 0x80, 0x00, //     ## ##        
+	0x0F, 0x80, 0x00, //     #####        
+	0x0F, 0x00, 0x00, //     ####         
+	0x0F, 0x80, 0x00, //     #####        
+	0x0D, 0xC0, 0x00, //     ## ###       
+	0x0C, 0xE0, 0x00, //     ##  ###      
+	0x3C, 0x7C, 0x00, //   ####   #####   
+	0x3C, 0x7C, 0x00, //   ####   #####   
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @5472 'l' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x1F, 0x80, 0x00, //    ######        
+	0x1F, 0x80, 0x00, //    ######        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x3F, 0xFC, 0x00, //   ############   
+	0x3F, 0xFC, 0x00, //   ############   
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @5544 'm' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0xF7, 0x78, 0x00, // #### ### ####    
+	0xFF, 0xFC, 0x00, // ##############   
+	0x39, 0xCC, 0x00, //   ###  ###  ##   
+	0x31, 0x8C, 0x00, //   ##   ##   ##   
+	0x31, 0x8C, 0x00, //   ##   ##   ##   
+	0x31, 0x8C, 0x00, //   ##   ##   ##   
+	0x31, 0x8C, 0x00, //   ##   ##   ##   
+	0x31, 0x8C, 0x00, //   ##   ##   ##   
+	0x31, 0x8C, 0x00, //   ##   ##   ##   
+	0xFD, 0xEF, 0x00, // ###### #### #### 
+	0xFD, 0xEF, 0x00, // ###### #### #### 
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @5616 'n' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x7B, 0xE0, 0x00, //  #### #####      
+	0x7F, 0xF0, 0x00, //  ###########     
+	0x1C, 0x38, 0x00, //    ###    ###    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x7E, 0x7E, 0x00, //  ######  ######  
+	0x7E, 0x7E, 0x00, //  ######  ######  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @5688 'o' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x03, 0xC0, 0x00, //       ####       
+	0x0F, 0xF0, 0x00, //     ########     
+	0x1C, 0x38, 0x00, //    ###    ###    
+	0x38, 0x1C, 0x00, //   ###      ###   
+	0x30, 0x0C, 0x00, //   ##        ##   
+	0x30, 0x0C, 0x00, //   ##        ##   
+	0x30, 0x0C, 0x00, //   ##        ##   
+	0x38, 0x1C, 0x00, //   ###      ###   
+	0x1C, 0x38, 0x00, //    ###    ###    
+	0x0F, 0xF0, 0x00, //     ########     
+	0x03, 0xC0, 0x00, //       ####       
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @5760 'p' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x7B, 0xE0, 0x00, //  #### #####      
+	0x7F, 0xF8, 0x00, //  ############    
+	0x1C, 0x18, 0x00, //    ###     ##    
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x1C, 0x18, 0x00, //    ###     ##    
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x1B, 0xE0, 0x00, //    ## #####      
+	0x18, 0x00, 0x00, //    ##            
+	0x18, 0x00, 0x00, //    ##            
+	0x18, 0x00, 0x00, //    ##            
+	0x7F, 0x00, 0x00, //  #######         
+	0x7F, 0x00, 0x00, //  #######         
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @5832 'q' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x07, 0xDE, 0x00, //      ##### ####  
+	0x1F, 0xFE, 0x00, //    ############  
+	0x18, 0x38, 0x00, //    ##     ###    
+	0x30, 0x18, 0x00, //   ##       ##    
+	0x30, 0x18, 0x00, //   ##       ##    
+	0x30, 0x18, 0x00, //   ##       ##    
+	0x30, 0x18, 0x00, //   ##       ##    
+	0x30, 0x18, 0x00, //   ##       ##    
+	0x18, 0x38, 0x00, //    ##     ###    
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x07, 0xD8, 0x00, //      ##### ##    
+	0x00, 0x18, 0x00, //            ##    
+	0x00, 0x18, 0x00, //            ##    
+	0x00, 0x18, 0x00, //            ##    
+	0x00, 0xFE, 0x00, //         #######  
+	0x00, 0xFE, 0x00, //         #######  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @5904 'r' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x3E, 0x78, 0x00, //   #####  ####    
+	0x3E, 0xFC, 0x00, //   ##### ######   
+	0x07, 0xCC, 0x00, //      #####  ##   
+	0x07, 0x00, 0x00, //      ###         
+	0x06, 0x00, 0x00, //      ##          
+	0x06, 0x00, 0x00, //      ##          
+	0x06, 0x00, 0x00, //      ##          
+	0x06, 0x00, 0x00, //      ##          
+	0x06, 0x00, 0x00, //      ##          
+	0x3F, 0xF0, 0x00, //   ##########     
+	0x3F, 0xF0, 0x00, //   ##########     
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @5976 's' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x07, 0xF8, 0x00, //      ########    
+	0x0F, 0xF8, 0x00, //     #########    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x1F, 0x80, 0x00, //    ######        
+	0x0F, 0xF0, 0x00, //     ########     
+	0x00, 0xF8, 0x00, //         #####    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x38, 0x00, //    ##     ###    
+	0x1F, 0xF0, 0x00, //    #########     
+	0x1F, 0xE0, 0x00, //    ########      
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @6048 't' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x0C, 0x00, 0x00, //     ##           
+	0x0C, 0x00, 0x00, //     ##           
+	0x0C, 0x00, 0x00, //     ##           
+	0x0C, 0x00, 0x00, //     ##           
+	0x3F, 0xF0, 0x00, //   ##########     
+	0x3F, 0xF0, 0x00, //   ##########     
+	0x0C, 0x00, 0x00, //     ##           
+	0x0C, 0x00, 0x00, //     ##           
+	0x0C, 0x00, 0x00, //     ##           
+	0x0C, 0x00, 0x00, //     ##           
+	0x0C, 0x00, 0x00, //     ##           
+	0x0C, 0x00, 0x00, //     ##           
+	0x0C, 0x1C, 0x00, //     ##     ###   
+	0x07, 0xFC, 0x00, //      #########   
+	0x03, 0xF0, 0x00, //       ######     
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @6120 'u' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x78, 0x78, 0x00, //  ####    ####    
+	0x78, 0x78, 0x00, //  ####    ####    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x38, 0x00, //    ##     ###    
+	0x0F, 0xFE, 0x00, //     ###########  
+	0x07, 0xDE, 0x00, //      ##### ####  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @6192 'v' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x7C, 0x3E, 0x00, //  #####    #####  
+	0x7C, 0x3E, 0x00, //  #####    #####  
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x18, 0x18, 0x00, //    ##      ##    
+	0x0C, 0x30, 0x00, //     ##    ##     
+	0x0C, 0x30, 0x00, //     ##    ##     
+	0x06, 0x60, 0x00, //      ##  ##      
+	0x06, 0x60, 0x00, //      ##  ##      
+	0x07, 0xE0, 0x00, //      ######      
+	0x03, 0xC0, 0x00, //       ####       
+	0x03, 0xC0, 0x00, //       ####       
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @6264 'w' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x78, 0x3C, 0x00, //  ####     ####   
+	0x78, 0x3C, 0x00, //  ####     ####   
+	0x31, 0x18, 0x00, //   ##   #   ##    
+	0x33, 0x98, 0x00, //   ##  ###  ##    
+	0x33, 0x98, 0x00, //   ##  ###  ##    
+	0x1A, 0xB0, 0x00, //    ## # # ##     
+	0x1E, 0xF0, 0x00, //    #### ####     
+	0x1E, 0xF0, 0x00, //    #### ####     
+	0x1C, 0x60, 0x00, //    ###   ##      
+	0x0C, 0x60, 0x00, //     ##   ##      
+	0x0C, 0x60, 0x00, //     ##   ##      
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @6336 'x' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x3E, 0x7C, 0x00, //   #####  #####   
+	0x3E, 0x7C, 0x00, //   #####  #####   
+	0x0C, 0x30, 0x00, //     ##    ##     
+	0x06, 0x60, 0x00, //      ##  ##      
+	0x03, 0xC0, 0x00, //       ####       
+	0x01, 0x80, 0x00, //        ##        
+	0x03, 0xC0, 0x00, //       ####       
+	0x06, 0x60, 0x00, //      ##  ##      
+	0x0C, 0x30, 0x00, //     ##    ##     
+	0x3E, 0x7C, 0x00, //   #####  #####   
+	0x3E, 0x7C, 0x00, //   #####  #####   
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @6408 'y' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x7E, 0x1F, 0x00, //  ######    ##### 
+	0x7E, 0x1F, 0x00, //  ######    ##### 
+	0x18, 0x0C, 0x00, //    ##       ##   
+	0x0C, 0x18, 0x00, //     ##     ##    
+	0x0C, 0x18, 0x00, //     ##     ##    
+	0x06, 0x30, 0x00, //      ##   ##     
+	0x06, 0x30, 0x00, //      ##   ##     
+	0x03, 0x60, 0x00, //       ## ##      
+	0x03, 0xE0, 0x00, //       #####      
+	0x01, 0xC0, 0x00, //        ###       
+	0x00, 0xC0, 0x00, //         ##       
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x03, 0x00, 0x00, //       ##         
+	0x3F, 0xC0, 0x00, //   ########       
+	0x3F, 0xC0, 0x00, //   ########       
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @6480 'z' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x18, 0x30, 0x00, //    ##     ##     
+	0x18, 0x60, 0x00, //    ##    ##      
+	0x00, 0xC0, 0x00, //         ##       
+	0x01, 0x80, 0x00, //        ##        
+	0x03, 0x00, 0x00, //       ##         
+	0x06, 0x18, 0x00, //      ##    ##    
+	0x0C, 0x18, 0x00, //     ##     ##    
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x1F, 0xF8, 0x00, //    ##########    
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @6552 '{' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0xE0, 0x00, //         ###      
+	0x01, 0xE0, 0x00, //        ####      
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x03, 0x80, 0x00, //       ###        
+	0x07, 0x00, 0x00, //      ###         
+	0x03, 0x80, 0x00, //       ###        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0xE0, 0x00, //        ####      
+	0x00, 0xE0, 0x00, //         ###      
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @6624 '|' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @6696 '}' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x07, 0x00, 0x00, //      ###         
+	0x07, 0x80, 0x00, //      ####        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0xC0, 0x00, //        ###       
+	0x00, 0xE0, 0x00, //         ###      
+	0x01, 0xC0, 0x00, //        ###       
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x01, 0x80, 0x00, //        ##        
+	0x07, 0x80, 0x00, //      ####        
+	0x07, 0x00, 0x00, //      ###         
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+
+	// @6768 '~' (17 pixels wide)
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x0E, 0x00, 0x00, //     ###          
+	0x1F, 0x18, 0x00, //    #####   ##    
+	0x3B, 0xB8, 0x00, //   ### ### ###    
+	0x31, 0xF0, 0x00, //   ##   #####     
+	0x00, 0xE0, 0x00, //         ###      
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+	0x00, 0x00, 0x00, //                  
+};
+
+sFONT Font24 = {
+  Font24_Table,
+  17, /* Width */
+  24, /* Height */
+};
+
+/**
+  * @}
+  */ 
+
+
+/** @defgroup FONTS_Private_Function_Prototypes
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+
+
+/** @defgroup FONTS_Private_Functions
+  * @{
+  */
+    
+/**
+  * @}
+  */
+  
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */  
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/stmcube/Utilities/Fonts/font8.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/stmcube/Utilities/Fonts/font8.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/stmcube/Utilities/Fonts/font8.c	(revision 453)
@@ -0,0 +1,1084 @@
+/**
+  ******************************************************************************
+  * @file    Font8.c
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    18-February-2014
+  * @brief   This file provides text Font8 for STM32xx-EVAL's LCD driver. 
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "fonts.h"
+
+/** @addtogroup Utilities
+  * @{
+  */
+  
+/** @addtogroup STM32_EVAL
+  * @{
+  */ 
+
+/** @addtogroup Common
+  * @{
+  */
+
+/** @addtogroup FONTS
+  * @brief      This file provides text Font8 for STM32xx-EVAL's LCD driver. 
+  * @{
+  */  
+
+/** @defgroup FONTS_Private_Types
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+
+
+/** @defgroup FONTS_Private_Defines
+  * @{
+  */
+/**
+  * @}
+  */ 
+
+
+/** @defgroup FONTS_Private_Macros
+  * @{
+  */
+/**
+  * @}
+  */ 
+  
+
+/** @defgroup FONTS_Private_Variables
+  * @{
+  */
+// 
+//  Font data for Courier New 12pt
+// 
+
+const uint8_t Font8_Table[] = 
+{
+	// @0 ' ' (5 pixels wide)
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+
+	// @8 '!' (5 pixels wide)
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x00, //      
+	0x20, //   #  
+	0x00, //      
+	0x00, //      
+
+	// @16 '"' (5 pixels wide)
+	0x50, //  # # 
+	0x50, //  # # 
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+
+	// @24 '#' (5 pixels wide)
+	0x28, //   # #
+	0x50, //  # # 
+	0xF8, // #####
+	0x50, //  # # 
+	0xF8, // #####
+	0x50, //  # # 
+	0xA0, // # #  
+	0x00, //      
+
+	// @32 '$' (5 pixels wide)
+	0x20, //   #  
+	0x30, //   ## 
+	0x60, //  ##  
+	0x30, //   ## 
+	0x10, //    # 
+	0x60, //  ##  
+	0x20, //   #  
+	0x00, //      
+
+	// @40 '%' (5 pixels wide)
+	0x20, //   #  
+	0x20, //   #  
+	0x18, //    ##
+	0x60, //  ##  
+	0x10, //    # 
+	0x10, //    # 
+	0x00, //      
+	0x00, //      
+
+	// @48 '&' (5 pixels wide)
+	0x00, //      
+	0x38, //   ###
+	0x20, //   #  
+	0x60, //  ##  
+	0x50, //  # # 
+	0x78, //  ####
+	0x00, //      
+	0x00, //      
+
+	// @56 ''' (5 pixels wide)
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+
+	// @64 '(' (5 pixels wide)
+	0x10, //    # 
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x10, //    # 
+	0x00, //      
+
+	// @72 ')' (5 pixels wide)
+	0x40, //  #   
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x40, //  #   
+	0x00, //      
+
+	// @80 '*' (5 pixels wide)
+	0x20, //   #  
+	0x70, //  ### 
+	0x20, //   #  
+	0x50, //  # # 
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+
+	// @88 '+' (5 pixels wide)
+	0x00, //      
+	0x20, //   #  
+	0x20, //   #  
+	0xF8, // #####
+	0x20, //   #  
+	0x20, //   #  
+	0x00, //      
+	0x00, //      
+
+	// @96 ',' (5 pixels wide)
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x10, //    # 
+	0x20, //   #  
+	0x20, //   #  
+	0x00, //      
+
+	// @104 '-' (5 pixels wide)
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x70, //  ### 
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+
+	// @112 '.' (5 pixels wide)
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x20, //   #  
+	0x00, //      
+	0x00, //      
+
+	// @120 '/' (5 pixels wide)
+	0x10, //    # 
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x40, //  #   
+	0x40, //  #   
+	0x80, // #    
+	0x00, //      
+
+	// @128 '0' (5 pixels wide)
+	0x20, //   #  
+	0x50, //  # # 
+	0x50, //  # # 
+	0x50, //  # # 
+	0x50, //  # # 
+	0x20, //   #  
+	0x00, //      
+	0x00, //      
+
+	// @136 '1' (5 pixels wide)
+	0x60, //  ##  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0xF8, // #####
+	0x00, //      
+	0x00, //      
+
+	// @144 '2' (5 pixels wide)
+	0x20, //   #  
+	0x50, //  # # 
+	0x20, //   #  
+	0x20, //   #  
+	0x40, //  #   
+	0x70, //  ### 
+	0x00, //      
+	0x00, //      
+
+	// @152 '3' (5 pixels wide)
+	0x20, //   #  
+	0x50, //  # # 
+	0x10, //    # 
+	0x20, //   #  
+	0x10, //    # 
+	0x60, //  ##  
+	0x00, //      
+	0x00, //      
+
+	// @160 '4' (5 pixels wide)
+	0x10, //    # 
+	0x30, //   ## 
+	0x50, //  # # 
+	0x78, //  ####
+	0x10, //    # 
+	0x38, //   ###
+	0x00, //      
+	0x00, //      
+
+	// @168 '5' (5 pixels wide)
+	0x70, //  ### 
+	0x40, //  #   
+	0x60, //  ##  
+	0x10, //    # 
+	0x50, //  # # 
+	0x20, //   #  
+	0x00, //      
+	0x00, //      
+
+	// @176 '6' (5 pixels wide)
+	0x30, //   ## 
+	0x40, //  #   
+	0x60, //  ##  
+	0x50, //  # # 
+	0x50, //  # # 
+	0x60, //  ##  
+	0x00, //      
+	0x00, //      
+
+	// @184 '7' (5 pixels wide)
+	0x70, //  ### 
+	0x50, //  # # 
+	0x10, //    # 
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x00, //      
+	0x00, //      
+
+	// @192 '8' (5 pixels wide)
+	0x20, //   #  
+	0x50, //  # # 
+	0x20, //   #  
+	0x50, //  # # 
+	0x50, //  # # 
+	0x20, //   #  
+	0x00, //      
+	0x00, //      
+
+	// @200 '9' (5 pixels wide)
+	0x30, //   ## 
+	0x50, //  # # 
+	0x50, //  # # 
+	0x30, //   ## 
+	0x10, //    # 
+	0x60, //  ##  
+	0x00, //      
+	0x00, //      
+
+	// @208 ':' (5 pixels wide)
+	0x00, //      
+	0x00, //      
+	0x20, //   #  
+	0x00, //      
+	0x00, //      
+	0x20, //   #  
+	0x00, //      
+	0x00, //      
+
+	// @216 ';' (5 pixels wide)
+	0x00, //      
+	0x00, //      
+	0x10, //    # 
+	0x00, //      
+	0x10, //    # 
+	0x20, //   #  
+	0x00, //      
+	0x00, //      
+
+	// @224 '<' (5 pixels wide)
+	0x00, //      
+	0x10, //    # 
+	0x20, //   #  
+	0xC0, // ##   
+	0x20, //   #  
+	0x10, //    # 
+	0x00, //      
+	0x00, //      
+
+	// @232 '=' (5 pixels wide)
+	0x00, //      
+	0x70, //  ### 
+	0x00, //      
+	0x70, //  ### 
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+
+	// @240 '>' (5 pixels wide)
+	0x00, //      
+	0x40, //  #   
+	0x20, //   #  
+	0x18, //    ##
+	0x20, //   #  
+	0x40, //  #   
+	0x00, //      
+	0x00, //      
+
+	// @248 '?' (5 pixels wide)
+	0x20, //   #  
+	0x50, //  # # 
+	0x10, //    # 
+	0x20, //   #  
+	0x00, //      
+	0x20, //   #  
+	0x00, //      
+	0x00, //      
+
+	// @256 '@' (5 pixels wide)
+	0x30, //   ## 
+	0x48, //  #  #
+	0x48, //  #  #
+	0x58, //  # ##
+	0x48, //  #  #
+	0x40, //  #   
+	0x38, //   ###
+	0x00, //      
+
+	// @264 'A' (5 pixels wide)
+	0x60, //  ##  
+	0x20, //   #  
+	0x50, //  # # 
+	0x70, //  ### 
+	0x88, // #   #
+	0xD8, // ## ##
+	0x00, //      
+	0x00, //      
+
+	// @272 'B' (5 pixels wide)
+	0xF0, // #### 
+	0x48, //  #  #
+	0x70, //  ### 
+	0x48, //  #  #
+	0x48, //  #  #
+	0xF0, // #### 
+	0x00, //      
+	0x00, //      
+
+	// @280 'C' (5 pixels wide)
+	0x70, //  ### 
+	0x50, //  # # 
+	0x40, //  #   
+	0x40, //  #   
+	0x40, //  #   
+	0x30, //   ## 
+	0x00, //      
+	0x00, //      
+
+	// @288 'D' (5 pixels wide)
+	0xF0, // #### 
+	0x48, //  #  #
+	0x48, //  #  #
+	0x48, //  #  #
+	0x48, //  #  #
+	0xF0, // #### 
+	0x00, //      
+	0x00, //      
+
+	// @296 'E' (5 pixels wide)
+	0xF8, // #####
+	0x48, //  #  #
+	0x60, //  ##  
+	0x40, //  #   
+	0x48, //  #  #
+	0xF8, // #####
+	0x00, //      
+	0x00, //      
+
+	// @304 'F' (5 pixels wide)
+	0xF8, // #####
+	0x48, //  #  #
+	0x60, //  ##  
+	0x40, //  #   
+	0x40, //  #   
+	0xE0, // ###  
+	0x00, //      
+	0x00, //      
+
+	// @312 'G' (5 pixels wide)
+	0x70, //  ### 
+	0x40, //  #   
+	0x40, //  #   
+	0x58, //  # ##
+	0x50, //  # # 
+	0x30, //   ## 
+	0x00, //      
+	0x00, //      
+
+	// @320 'H' (5 pixels wide)
+	0xE8, // ### #
+	0x48, //  #  #
+	0x78, //  ####
+	0x48, //  #  #
+	0x48, //  #  #
+	0xE8, // ### #
+	0x00, //      
+	0x00, //      
+
+	// @328 'I' (5 pixels wide)
+	0x70, //  ### 
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x70, //  ### 
+	0x00, //      
+	0x00, //      
+
+	// @336 'J' (5 pixels wide)
+	0x38, //   ###
+	0x10, //    # 
+	0x10, //    # 
+	0x50, //  # # 
+	0x50, //  # # 
+	0x20, //   #  
+	0x00, //      
+	0x00, //      
+
+	// @344 'K' (5 pixels wide)
+	0xD8, // ## ##
+	0x50, //  # # 
+	0x60, //  ##  
+	0x70, //  ### 
+	0x50, //  # # 
+	0xD8, // ## ##
+	0x00, //      
+	0x00, //      
+
+	// @352 'L' (5 pixels wide)
+	0xE0, // ###  
+	0x40, //  #   
+	0x40, //  #   
+	0x40, //  #   
+	0x48, //  #  #
+	0xF8, // #####
+	0x00, //      
+	0x00, //      
+
+	// @360 'M' (5 pixels wide)
+	0xD8, // ## ##
+	0xD8, // ## ##
+	0xD8, // ## ##
+	0xA8, // # # #
+	0x88, // #   #
+	0xD8, // ## ##
+	0x00, //      
+	0x00, //      
+
+	// @368 'N' (5 pixels wide)
+	0xD8, // ## ##
+	0x68, //  ## #
+	0x68, //  ## #
+	0x58, //  # ##
+	0x58, //  # ##
+	0xE8, // ### #
+	0x00, //      
+	0x00, //      
+
+	// @376 'O' (5 pixels wide)
+	0x30, //   ## 
+	0x48, //  #  #
+	0x48, //  #  #
+	0x48, //  #  #
+	0x48, //  #  #
+	0x30, //   ## 
+	0x00, //      
+	0x00, //      
+
+	// @384 'P' (5 pixels wide)
+	0xF0, // #### 
+	0x48, //  #  #
+	0x48, //  #  #
+	0x70, //  ### 
+	0x40, //  #   
+	0xE0, // ###  
+	0x00, //      
+	0x00, //      
+
+	// @392 'Q' (5 pixels wide)
+	0x30, //   ## 
+	0x48, //  #  #
+	0x48, //  #  #
+	0x48, //  #  #
+	0x48, //  #  #
+	0x30, //   ## 
+	0x18, //    ##
+	0x00, //      
+
+	// @400 'R' (5 pixels wide)
+	0xF0, // #### 
+	0x48, //  #  #
+	0x48, //  #  #
+	0x70, //  ### 
+	0x48, //  #  #
+	0xE8, // ### #
+	0x00, //      
+	0x00, //      
+
+	// @408 'S' (5 pixels wide)
+	0x70, //  ### 
+	0x50, //  # # 
+	0x20, //   #  
+	0x10, //    # 
+	0x50, //  # # 
+	0x70, //  ### 
+	0x00, //      
+	0x00, //      
+
+	// @416 'T' (5 pixels wide)
+	0xF8, // #####
+	0xA8, // # # #
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x70, //  ### 
+	0x00, //      
+	0x00, //      
+
+	// @424 'U' (5 pixels wide)
+	0xD8, // ## ##
+	0x48, //  #  #
+	0x48, //  #  #
+	0x48, //  #  #
+	0x48, //  #  #
+	0x30, //   ## 
+	0x00, //      
+	0x00, //      
+
+	// @432 'V' (5 pixels wide)
+	0xD8, // ## ##
+	0x88, // #   #
+	0x48, //  #  #
+	0x50, //  # # 
+	0x50, //  # # 
+	0x30, //   ## 
+	0x00, //      
+	0x00, //      
+
+	// @440 'W' (5 pixels wide)
+	0xD8, // ## ##
+	0x88, // #   #
+	0xA8, // # # #
+	0xA8, // # # #
+	0xA8, // # # #
+	0x50, //  # # 
+	0x00, //      
+	0x00, //      
+
+	// @448 'X' (5 pixels wide)
+	0xD8, // ## ##
+	0x50, //  # # 
+	0x20, //   #  
+	0x20, //   #  
+	0x50, //  # # 
+	0xD8, // ## ##
+	0x00, //      
+	0x00, //      
+
+	// @456 'Y' (5 pixels wide)
+	0xD8, // ## ##
+	0x88, // #   #
+	0x50, //  # # 
+	0x20, //   #  
+	0x20, //   #  
+	0x70, //  ### 
+	0x00, //      
+	0x00, //      
+
+	// @464 'Z' (5 pixels wide)
+	0x78, //  ####
+	0x48, //  #  #
+	0x10, //    # 
+	0x20, //   #  
+	0x48, //  #  #
+	0x78, //  ####
+	0x00, //      
+	0x00, //      
+
+	// @472 '[' (5 pixels wide)
+	0x30, //   ## 
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x30, //   ## 
+	0x00, //      
+
+	// @480 '\' (5 pixels wide)
+	0x80, // #    
+	0x40, //  #   
+	0x40, //  #   
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x10, //    # 
+	0x00, //      
+
+	// @488 ']' (5 pixels wide)
+	0x60, //  ##  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x60, //  ##  
+	0x00, //      
+
+	// @496 '^' (5 pixels wide)
+	0x20, //   #  
+	0x20, //   #  
+	0x50, //  # # 
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+
+	// @504 '_' (5 pixels wide)
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0xF8, // #####
+
+	// @512 '`' (5 pixels wide)
+	0x20, //   #  
+	0x10, //    # 
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+
+	// @520 'a' (5 pixels wide)
+	0x00, //      
+	0x00, //      
+	0x30, //   ## 
+	0x10, //    # 
+	0x70, //  ### 
+	0x78, //  ####
+	0x00, //      
+	0x00, //      
+
+	// @528 'b' (5 pixels wide)
+	0xC0, // ##   
+	0x40, //  #   
+	0x70, //  ### 
+	0x48, //  #  #
+	0x48, //  #  #
+	0xF0, // #### 
+	0x00, //      
+	0x00, //      
+
+	// @536 'c' (5 pixels wide)
+	0x00, //      
+	0x00, //      
+	0x70, //  ### 
+	0x40, //  #   
+	0x40, //  #   
+	0x70, //  ### 
+	0x00, //      
+	0x00, //      
+
+	// @544 'd' (5 pixels wide)
+	0x18, //    ##
+	0x08, //     #
+	0x38, //   ###
+	0x48, //  #  #
+	0x48, //  #  #
+	0x38, //   ###
+	0x00, //      
+	0x00, //      
+
+	// @552 'e' (5 pixels wide)
+	0x00, //      
+	0x00, //      
+	0x70, //  ### 
+	0x70, //  ### 
+	0x40, //  #   
+	0x30, //   ## 
+	0x00, //      
+	0x00, //      
+
+	// @560 'f' (5 pixels wide)
+	0x10, //    # 
+	0x20, //   #  
+	0x70, //  ### 
+	0x20, //   #  
+	0x20, //   #  
+	0x70, //  ### 
+	0x00, //      
+	0x00, //      
+
+	// @568 'g' (5 pixels wide)
+	0x00, //      
+	0x00, //      
+	0x38, //   ###
+	0x48, //  #  #
+	0x48, //  #  #
+	0x38, //   ###
+	0x08, //     #
+	0x30, //   ## 
+
+	// @576 'h' (5 pixels wide)
+	0xC0, // ##   
+	0x40, //  #   
+	0x70, //  ### 
+	0x48, //  #  #
+	0x48, //  #  #
+	0xE8, // ### #
+	0x00, //      
+	0x00, //      
+
+	// @584 'i' (5 pixels wide)
+	0x20, //   #  
+	0x00, //      
+	0x60, //  ##  
+	0x20, //   #  
+	0x20, //   #  
+	0x70, //  ### 
+	0x00, //      
+	0x00, //      
+
+	// @592 'j' (5 pixels wide)
+	0x20, //   #  
+	0x00, //      
+	0x70, //  ### 
+	0x10, //    # 
+	0x10, //    # 
+	0x10, //    # 
+	0x10, //    # 
+	0x70, //  ### 
+
+	// @600 'k' (5 pixels wide)
+	0xC0, // ##   
+	0x40, //  #   
+	0x58, //  # ##
+	0x70, //  ### 
+	0x50, //  # # 
+	0xD8, // ## ##
+	0x00, //      
+	0x00, //      
+
+	// @608 'l' (5 pixels wide)
+	0x60, //  ##  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x70, //  ### 
+	0x00, //      
+	0x00, //      
+
+	// @616 'm' (5 pixels wide)
+	0x00, //      
+	0x00, //      
+	0xD0, // ## # 
+	0xA8, // # # #
+	0xA8, // # # #
+	0xA8, // # # #
+	0x00, //      
+	0x00, //      
+
+	// @624 'n' (5 pixels wide)
+	0x00, //      
+	0x00, //      
+	0xF0, // #### 
+	0x48, //  #  #
+	0x48, //  #  #
+	0xC8, // ##  #
+	0x00, //      
+	0x00, //      
+
+	// @632 'o' (5 pixels wide)
+	0x00, //      
+	0x00, //      
+	0x30, //   ## 
+	0x48, //  #  #
+	0x48, //  #  #
+	0x30, //   ## 
+	0x00, //      
+	0x00, //      
+
+	// @640 'p' (5 pixels wide)
+	0x00, //      
+	0x00, //      
+	0xF0, // #### 
+	0x48, //  #  #
+	0x48, //  #  #
+	0x70, //  ### 
+	0x40, //  #   
+	0xE0, // ###  
+
+	// @648 'q' (5 pixels wide)
+	0x00, //      
+	0x00, //      
+	0x38, //   ###
+	0x48, //  #  #
+	0x48, //  #  #
+	0x38, //   ###
+	0x08, //     #
+	0x18, //    ##
+
+	// @656 'r' (5 pixels wide)
+	0x00, //      
+	0x00, //      
+	0x78, //  ####
+	0x20, //   #  
+	0x20, //   #  
+	0x70, //  ### 
+	0x00, //      
+	0x00, //      
+
+	// @664 's' (5 pixels wide)
+	0x00, //      
+	0x00, //      
+	0x30, //   ## 
+	0x20, //   #  
+	0x10, //    # 
+	0x60, //  ##  
+	0x00, //      
+	0x00, //      
+
+	// @672 't' (5 pixels wide)
+	0x00, //      
+	0x40, //  #   
+	0xF0, // #### 
+	0x40, //  #   
+	0x48, //  #  #
+	0x30, //   ## 
+	0x00, //      
+	0x00, //      
+
+	// @680 'u' (5 pixels wide)
+	0x00, //      
+	0x00, //      
+	0xD8, // ## ##
+	0x48, //  #  #
+	0x48, //  #  #
+	0x38, //   ###
+	0x00, //      
+	0x00, //      
+
+	// @688 'v' (5 pixels wide)
+	0x00, //      
+	0x00, //      
+	0xC8, // ##  #
+	0x48, //  #  #
+	0x30, //   ## 
+	0x30, //   ## 
+	0x00, //      
+	0x00, //      
+
+	// @696 'w' (5 pixels wide)
+	0x00, //      
+	0x00, //      
+	0xD8, // ## ##
+	0xA8, // # # #
+	0xA8, // # # #
+	0x50, //  # # 
+	0x00, //      
+	0x00, //      
+
+	// @704 'x' (5 pixels wide)
+	0x00, //      
+	0x00, //      
+	0x48, //  #  #
+	0x30, //   ## 
+	0x30, //   ## 
+	0x48, //  #  #
+	0x00, //      
+	0x00, //      
+
+	// @712 'y' (5 pixels wide)
+	0x00, //      
+	0x00, //      
+	0xD8, // ## ##
+	0x50, //  # # 
+	0x50, //  # # 
+	0x20, //   #  
+	0x20, //   #  
+	0x60, //  ##  
+
+	// @720 'z' (5 pixels wide)
+	0x00, //      
+	0x00, //      
+	0x78, //  ####
+	0x50, //  # # 
+	0x28, //   # #
+	0x78, //  ####
+	0x00, //      
+	0x00, //      
+
+	// @728 '{' (5 pixels wide)
+	0x10, //    # 
+	0x20, //   #  
+	0x20, //   #  
+	0x60, //  ##  
+	0x20, //   #  
+	0x20, //   #  
+	0x10, //    # 
+	0x00, //      
+
+	// @736 '|' (5 pixels wide)
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x00, //      
+
+	// @744 '}' (5 pixels wide)
+	0x40, //  #   
+	0x20, //   #  
+	0x20, //   #  
+	0x30, //   ## 
+	0x20, //   #  
+	0x20, //   #  
+	0x40, //  #   
+	0x00, //      
+
+	// @752 '~' (5 pixels wide)
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x28, //   # #
+	0x50, //  # # 
+	0x00, //      
+	0x00, //      
+	0x00, //      
+};
+
+sFONT Font8 = {
+  Font8_Table,
+  5, /* Width */
+  8, /* Height */
+};
+
+/**
+  * @}
+  */ 
+
+
+/** @defgroup FONTS_Private_Function_Prototypes
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+
+
+/** @defgroup FONTS_Private_Functions
+  * @{
+  */
+    
+/**
+  * @}
+  */
+  
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */  
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/stmcube/Utilities/Fonts/fonts.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/stmcube/Utilities/Fonts/fonts.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/stmcube/Utilities/Fonts/fonts.h	(revision 453)
@@ -0,0 +1,134 @@
+/**
+  ******************************************************************************
+  * @file    fonts.h
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    18-February-2014
+  * @brief   Header for fonts.c file
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __FONTS_H
+#define __FONTS_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include <stdint.h>
+
+/** @addtogroup Utilities
+  * @{
+  */
+  
+/** @addtogroup STM32_EVAL
+  * @{
+  */ 
+
+/** @addtogroup Common
+  * @{
+  */
+
+/** @addtogroup FONTS
+  * @{
+  */ 
+
+/** @defgroup FONTS_Exported_Types
+  * @{
+  */ 
+typedef struct _tFont
+{    
+  const uint8_t *table;
+  uint16_t Width;
+  uint16_t Height;
+  
+} sFONT;
+
+extern sFONT Font24;
+extern sFONT Font20;
+extern sFONT Font16;
+extern sFONT Font12;
+extern sFONT Font8;
+/**
+  * @}
+  */ 
+
+/** @defgroup FONTS_Exported_Constants
+  * @{
+  */ 
+#define LINE(x) ((x) * (((sFONT *)BSP_LCD_GetFont())->Height))
+
+/**
+  * @}
+  */ 
+
+/** @defgroup FONTS_Exported_Macros
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+
+/** @defgroup FONTS_Exported_Functions
+  * @{
+  */ 
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+  
+#endif /* __FONTS_H */
+ 
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */      
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/banner.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/banner.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/banner.c	(revision 453)
@@ -0,0 +1,72 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2014 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		カーネル起動メッセージの出力
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include "target_syssvc.h"
+#include "banner.h"
+
+#ifndef TARGET_COPYRIGHT
+#define TARGET_COPYRIGHT
+#endif /* TARGET_COPYRIGHT */
+
+static const char banner[] = "\n"
+"TOPPERS/ASP Kernel Release %d.%X.%d for " TARGET_NAME
+" (" __DATE__ ", " __TIME__ ")\n"
+"Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory\n"
+"                            Toyohashi Univ. of Technology, JAPAN\n"
+"Copyright (C) 2004-2014 by Embedded and Real-Time Systems Laboratory\n"
+"            Graduate School of Information Science, Nagoya Univ., JAPAN\n"
+TARGET_COPYRIGHT;
+
+void
+print_banner(intptr_t exinf)
+{
+	syslog_3(LOG_NOTICE, banner,
+				(TKERNEL_PRVER >> 12) & 0x0fU,
+				(TKERNEL_PRVER >> 4) & 0xffU,
+				TKERNEL_PRVER & 0x0fU);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/banner.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/banner.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/banner.cfg	(revision 453)
@@ -0,0 +1,10 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *		カーネル起動メッセージの出力のコンフィギュレーションファイル
+ */
+
+#include "syssvc/banner.h"
+ATT_INI({ TA_NULL, 0, print_banner });
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/banner.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/banner.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/banner.h	(revision 453)
@@ -0,0 +1,53 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2008 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		カーネル起動メッセージの出力
+ */
+
+#ifndef TOPPERS_BANNER_H
+#define TOPPERS_BANNER_H
+
+/*
+ *  カーネル起動メッセージの出力
+ */
+extern void	print_banner(intptr_t exinf) throw();
+
+#endif /* TOPPERS_BANNER_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/logtask.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/logtask.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/logtask.c	(revision 453)
@@ -0,0 +1,198 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		システムログタスク
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <log_output.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#include "logtask.h"
+
+/*
+ *  システムログタスクの出力先のポートID
+ */
+static ID	logtask_portid;
+
+/*
+ *  シリアルインタフェースへの1文字出力
+ */
+static void
+logtask_putc(char c)
+{
+	(void) serial_wri_dat(logtask_portid, &c, 1);
+}
+
+/*
+ *  システムログ出力の待ち合わせ
+ */
+ER
+logtask_flush(uint_t count)
+{
+	T_SYSLOG_RLOG	rlog;
+	T_SERIAL_RPOR	rpor;
+	ER				ercd, rercd;
+
+	if (sns_dpn()) {
+		ercd = E_CTX;
+	}
+	else {
+		for (;;) {
+			if (syslog_ref_log(&rlog) < 0) {
+				ercd = E_SYS;
+				goto error_exit;
+			}
+			if (rlog.count <= count) {
+				if (count == 0U) {
+					/*
+					 *  countが0の場合には，シリアルバッファが空かを確
+					 *  認する．
+					 */
+					if (serial_ref_por(logtask_portid, &rpor) < 0) {
+						ercd = E_SYS;
+						goto error_exit;
+					}
+					if (rpor.wricnt == 0U) {
+						ercd = E_OK;
+						goto error_exit;
+					}
+				}
+				else {
+					ercd = E_OK;
+					goto error_exit;
+				}
+			}
+
+			/*
+			 *  LOGTASK_FLUSH_WAITミリ秒待つ．
+			 */
+			rercd = dly_tsk(LOGTASK_FLUSH_WAIT);
+			if (rercd < 0) {
+				ercd = (rercd == E_RLWAI) ? rercd : E_SYS;
+				goto error_exit;
+			}
+		}
+	}
+
+  error_exit:
+	return(ercd);
+}
+
+/*
+ *  システムログタスクの本体
+ */
+void
+logtask_main(intptr_t exinf)
+{
+	SYSLOG	logbuf;
+	uint_t	lostlog;
+	ER_UINT	rercd;
+
+	logtask_portid = (ID) exinf;
+	(void) serial_opn_por(logtask_portid);
+	(void) syslog_msk_log(LOG_UPTO(LOG_NOTICE), LOG_UPTO(LOG_EMERG));
+	syslog_1(LOG_NOTICE, "System logging task is started on port %d.",
+													logtask_portid);
+	for (;;) {
+		lostlog = 0U;
+		while ((rercd = syslog_rea_log(&logbuf)) >= 0) {
+			lostlog += (uint_t) rercd;
+			if (logbuf.logtype >= LOG_TYPE_COMMENT) {
+				if (lostlog > 0U) {
+					syslog_lostmsg(lostlog, logtask_putc);
+					lostlog = 0U;
+				}
+				syslog_print(&logbuf, logtask_putc);
+				logtask_putc('\n');
+			}
+		}
+		if (lostlog > 0U) {
+			syslog_lostmsg(lostlog, logtask_putc);
+		}
+		(void) dly_tsk(LOGTASK_INTERVAL);
+	}
+}
+
+/*
+ *  システムログタスクの終了処理
+ */
+void
+logtask_terminate(intptr_t exinf)
+{
+	char	c;
+	SYSLOG	logbuf;
+	bool_t	msgflg = false;
+	ER_UINT	rercd;
+
+	/*
+	 *  シリアルインタフェースドライバの送信バッファに蓄積されたデータ
+	 *  を，低レベル出力機能を用いて出力する．
+	 */
+	while (serial_get_chr(logtask_portid, &c)) {
+		target_fput_log(c);
+	}
+
+	/*
+	 *  ログバッファに記録されたログ情報を，低レベル出力機能を用いて出
+	 *  力する．
+	 */
+	while ((rercd = syslog_rea_log(&logbuf)) >= 0) {
+		if (!msgflg) {
+			/*
+			 *  ログバッファに残ったログ情報であることを示す文字列を出
+			 *  力する．
+			 */
+			syslog_printf("-- buffered messages --\n", NULL, target_fput_log);
+			msgflg = true;
+		}
+		if (rercd > 0) {
+			syslog_lostmsg((uint_t) rercd, target_fput_log);
+		}
+		if (logbuf.logtype >= LOG_TYPE_COMMENT) {
+			syslog_print(&logbuf, target_fput_log);
+			target_fput_log('\n');
+		}
+	}
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/logtask.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/logtask.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/logtask.cfg	(revision 453)
@@ -0,0 +1,12 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *		システムログタスクのコンフィギュレーションファイル
+ */
+
+#include "syssvc/logtask.h"
+CRE_TSK(LOGTASK, { TA_ACT, LOGTASK_PORTID, logtask_main,
+						LOGTASK_PRIORITY, LOGTASK_STACK_SIZE, NULL });
+ATT_TER({ TA_NULL, 0, logtask_terminate });
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/logtask.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/logtask.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/logtask.h	(revision 453)
@@ -0,0 +1,101 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2008 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		システムログタスク
+ */
+
+#ifndef TOPPERS_LOGTASK_H
+#define TOPPERS_LOGTASK_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "target_syssvc.h"
+
+/*
+ *  システムログタスク関連の定数のデフォルト値の定義
+ */ 
+#ifndef LOGTASK_PRIORITY
+#define LOGTASK_PRIORITY	3		/* 初期優先度 */
+#endif /* LOGTASK_PRIORITY */
+
+#ifndef LOGTASK_STACK_SIZE
+#define LOGTASK_STACK_SIZE	1024	/* スタック領域のサイズ */
+#endif /* LOGTASK_STACK_SIZE */
+
+#ifndef LOGTASK_PORTID
+#define LOGTASK_PORTID		1		/* システムログ用のシリアルポート番号 */
+#endif /* LOGTASK_PORTID */
+
+#ifndef LOGTASK_INTERVAL
+#define LOGTASK_INTERVAL	10U		/* システムログタスクの動作間隔（ミリ秒）*/
+#endif /* LOGTASK_INTERVAL */
+
+#ifndef LOGTASK_FLUSH_WAIT
+#define LOGTASK_FLUSH_WAIT	1U		/* フラッシュ待ちの単位時間（ミリ秒）*/
+#endif /* LOGTASK_FLUSH_WAIT */
+
+/*
+ *  システムログ出力の待ち合わせ
+ *
+ *  ログバッファ中のログの数がcount以下になるまで待つ．countが0の場合に
+ *  は，シリアルバッファが空になるのも待つ．
+ */
+extern ER	logtask_flush(uint_t count) throw();
+
+/*
+ *  システムログタスクの本体
+ */
+extern void	logtask_main(intptr_t exinf) throw();
+
+/*
+ *  システムログタスクの終了処理
+ */
+extern void	logtask_terminate(intptr_t exinf) throw();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TOPPERS_LOGTASK_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/malloc.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/malloc.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/malloc.c	(revision 453)
@@ -0,0 +1,395 @@
+/*
+ *  TOPPERS/ASP/FMP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2020 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ * 
+ *  メモリアロケーション機能
+ *
+ */
+#include <kernel.h>
+#include <t_syslog.h>
+#include <stdlib.h>
+#include <string.h>
+#include "kernel_cfg.h"
+
+#ifndef CACHE_LINE_SIZE
+#define CACHE_LINE_SIZE	    32	/* default cacle line size */
+#endif
+
+#if defined(TLSF_SEM)	/* TLSF */
+#include "tlsf.h"
+
+/*
+ *  TLSF2.4.6には、アロケート、フリーを何度も繰り返すと
+ *  アロケート領域の先頭８バイトが破壊される問題がある.
+ *  TLSF側の修正は品質保証できないため、malloc/free関数で
+ *  対応を行う.
+ */
+#define TLSF_PTR_AREA_SIZE  8
+
+static void *memory_pool;
+
+/*
+ *  プール初期化
+ */
+void
+heap_init(intptr_t exinf)
+{
+	intptr_t *param = (intptr_t *)exinf;
+	uint32_t *p;
+	int i, size;
+	memory_pool = (void*)param[0];
+	p = (uint32_t *)param[0];
+	size = param[1] / sizeof(uint32_t);
+	for(i = 0 ; i < size ; i++)
+		*p++ = 0;
+	init_memory_pool(param[1], (void*)memory_pool);
+}
+
+/*
+ *  MALLOC
+ */
+void *
+__wrap__malloc_r(struct _reent *reent, size_t __size)
+{
+	void *mempool, *addr;
+	mempool = (void *)memory_pool;
+	if(mempool == NULL)
+		return NULL;
+	wai_sem(TLSF_SEM);
+	addr = (void*)malloc_ex(__size+TLSF_PTR_AREA_SIZE, mempool);
+	sig_sem(TLSF_SEM);
+	if(addr != NULL)
+		return addr+TLSF_PTR_AREA_SIZE;
+	else
+		return addr;
+}
+
+/*
+ *  CALLOC
+ */
+void *
+__wrap__calloc_r(struct _reent *reent, size_t __nmemb, size_t __size)
+{
+	void *mempool, *addr;
+	mempool = (void *)memory_pool;
+	if(mempool == NULL)
+		return NULL;
+	wai_sem(TLSF_SEM);
+	addr = (void*)malloc_ex((__nmemb * __size)+TLSF_PTR_AREA_SIZE, mempool);
+	sig_sem(TLSF_SEM);
+	if(addr != NULL){
+		memset(addr+TLSF_PTR_AREA_SIZE, 0, __nmemb * __size);
+		return addr+TLSF_PTR_AREA_SIZE;
+	}
+	else
+		return addr;
+}
+
+/*
+ *  REALLOC
+ */
+void *__wrap__realloc_r(struct _reent *reent, void *ptr, size_t __size)
+{
+	void *mempool, *addr;
+	mempool = (void *)memory_pool;
+	if(mempool == NULL)
+		return NULL;
+	wai_sem(TLSF_SEM);
+	addr = (void*)realloc_ex(ptr, __size+TLSF_PTR_AREA_SIZE, mempool);
+	sig_sem(TLSF_SEM);
+	if(addr != NULL)
+		return addr+TLSF_PTR_AREA_SIZE;
+	else
+		return addr;
+}
+
+/*
+ *  FREE
+ */
+void
+__wrap__free_r(struct _reent *reent, void *ptr)
+{
+	void *mempool = memory_pool;
+	if(ptr == NULL)
+		return;
+	if(mempool != NULL){
+		wai_sem(TLSF_SEM);
+		free_ex(ptr-TLSF_PTR_AREA_SIZE, mempool);
+		sig_sem(TLSF_SEM);
+	}
+}
+
+#elif(LOCAL_MALLOC)		/* LOCAL MALLOC */
+
+typedef struct _LMAP LMAP_t;
+struct _LMAP {
+  unsigned long lsize;		/* メモリサイズ */
+  LMAP_t *      laddr;		/* メモリスタートポインタ */
+};
+
+static LMAP_t lmap;
+
+/*
+ *  ローカルアロケータ初期化
+ */
+void
+heap_init(intptr_t exinf)
+{
+	intptr_t *param = (intptr_t *)exinf;
+	LMAP_t *plmap;
+
+	plmap = (LMAP_t *)param[0];
+	plmap->lsize = (unsigned long)param[1];
+	plmap->laddr = NULL;
+	lmap.lsize   = plmap->lsize;
+	lmap.laddr   = plmap;
+}
+
+/*
+ *  MALLOC
+ */
+void *
+__wrap__malloc_r(struct _reent *reent, size_t __size)
+{
+	LMAP_t *ph = &lmap;
+	LMAP_t *p;
+
+	__size = (__size+3+sizeof(unsigned int)) & ~3;
+	if(__size < sizeof(LMAP_t))
+		__size = sizeof(LMAP_t);
+
+	loc_cpu();
+	while((p = ph->laddr) != 0){
+		if(p->lsize >= __size && p->lsize < (__size+sizeof(LMAP_t))){
+			ph->laddr = p->laddr;
+			unl_cpu();
+			return (void *)(&p->laddr);
+		}
+		else if(p->lsize >= (__size+sizeof(LMAP_t))){
+			LMAP_t *pw = (LMAP_t *)((char *)p+__size);
+			pw->lsize = p->lsize-__size;
+			pw->laddr = p->laddr;
+			ph->laddr = pw;
+			p->lsize  = __size;
+			unl_cpu();
+			return (void *)(&p->laddr);
+		}
+		ph = p;
+	}
+	unl_cpu();
+	return NULL;
+}
+
+/*
+ *  CALLOC
+ */
+void *
+__wrap__calloc_r(struct _reent *reent, size_t __nmemb, size_t __size)
+{
+	return __wrap__malloc_r(reent, __nmemb * __size);
+}
+
+/*
+ *  FREE
+ */
+void
+__wrap__free_r(struct _reent *reent, void *ptr)
+{
+	LMAP_t *ph = &lmap;
+	LMAP_t *p;
+	char   *t, *pf;
+
+	if(ptr == NULL)
+		return;
+	p  = (LMAP_t *)((char *)ptr-sizeof(unsigned long));
+	t  = (char *)p+p->lsize;
+	loc_cpu();
+	for(;;){
+		if(ph->laddr == NULL){		/* 空きメモリなし */
+			p->laddr  = NULL;
+			ph->laddr = p;
+			break;
+		}
+		else if(t == (char *)ph->laddr){
+			p->lsize += (ph->laddr)->lsize;
+			p->laddr  = (ph->laddr)->laddr;
+			ph->laddr = p;
+			break;
+		}
+		else if(t < (char *)ph->laddr){
+			p->laddr = ph->laddr;
+			ph->laddr = p;
+			break;
+		}
+		ph = ph->laddr;
+		pf = (char *)ph+ph->lsize;
+		if(pf > (char *)p){			/* 領域オーバーラップ */
+			unl_cpu();
+			syslog_0(LOG_EMERG, "free:FATAL:irrguler free memory !");
+			return;
+		}
+		else if(pf == (char *)p){
+			ph->lsize += p->lsize;
+			if(t > (char *)ph->laddr){	/* 領域オーバーラップ */
+				unl_cpu();
+				syslog_0(LOG_EMERG, "free:FATAL:irrguler free memory !");
+				return;
+			}
+			else if(t == (char *)ph->laddr){
+				ph->lsize += (ph->laddr)->lsize;
+				ph->laddr  = (ph->laddr)->laddr;
+			}
+			break;
+		}
+	}
+	unl_cpu();
+}
+
+#else		/* LIBC MALLOC */
+#include <kernel_impl.h>
+
+static uintptr_t *heap_param;
+static int malloc_lock_count;
+
+/*
+ *  LIBCアロケータ初期化
+ */
+void
+heap_init(intptr_t exinf)
+{
+	heap_param = (uintptr_t *)exinf;
+	malloc_lock_count = 0;
+}
+
+void
+__malloc_lock(void * reent)
+{
+	malloc_lock_count++;
+	if (malloc_lock_count == 1){
+		ER ret;
+		if (sense_context())
+			ret = iloc_cpu();
+		else
+			ret = loc_cpu();
+		if (ret != E_OK)
+			syslog_1(LOG_ERROR, "__malloc_unlock: count[%d] loc_cpu", malloc_lock_count);
+	}
+}
+
+void
+__malloc_unlock(void * reent)
+{
+	malloc_lock_count--;
+	if (malloc_lock_count == 0){
+		ER ret;
+		if (sense_context())
+			ret = iunl_cpu();
+		else
+			ret = unl_cpu();
+		if (ret != E_OK)
+			syslog_1(LOG_ERROR, "__malloc_unlock: count[%d] unl_cpu error !", malloc_lock_count);
+	}
+}
+
+void *
+_sbrk(int incr)
+{ 
+	static char *heap_end = NULL;
+	char        *prev_heap_end;
+
+	if(incr < 0 || incr > heap_param[1]){
+		syslog_2(LOG_ERROR, "_sbrk: incr[%d] parameter error ! %d", incr, malloc_lock_count);
+		return (void *)-1;
+	}
+
+	if(heap_end == NULL)
+		heap_end = (char *)heap_param[0];
+
+	prev_heap_end  = heap_end;
+	heap_end      += incr;
+
+	if(heap_end < (char *)(heap_param[0]+heap_param[1]))
+		return (void *) prev_heap_end;
+	else{
+		heap_end = prev_heap_end;
+		syslog_2(LOG_ERROR, "_sbrk: incr[%d] allocation error ! %d", incr, malloc_lock_count);
+		return (void *)-1;
+	}
+}
+
+#endif
+
+/*
+ *  CACHE ALINE MALLOC
+ */
+void *
+malloc_cache(uint32_t len)
+{
+	void * addr = malloc(len+CACHE_LINE_SIZE);
+	uint32_t *p;
+	intptr_t uaddr;
+
+	if(addr == NULL)
+		return addr;
+	p = addr;
+	uaddr = (intptr_t)addr;
+	if((uaddr & (CACHE_LINE_SIZE-1)) != 0)
+		uaddr &= ~(CACHE_LINE_SIZE-1);
+	uaddr += CACHE_LINE_SIZE;
+	p = (uint32_t *)uaddr;
+	*(p-1) = (intptr_t)addr;
+	return p;
+}
+
+/*
+ *  CACHE ALINE FREE
+ */
+void
+free_cache(void *addr)
+{
+	intptr_t *p = addr;
+
+	if(addr == NULL)
+		return;
+	addr = (void*)(*(p-1));
+	free(addr);
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/serial.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/serial.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/serial.c	(revision 453)
@@ -0,0 +1,786 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2006-2013 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		シリアルインタフェースドライバ
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include "target_syssvc.h"
+#include "target_serial.h"
+#include "serial.h"
+#include "kernel_cfg.h"
+
+/*
+ *  バッファサイズのデフォルト値とバッファの定義
+ */
+#ifndef SERIAL_RCV_BUFSZ1
+#define	SERIAL_RCV_BUFSZ1	256			/* ポート1の受信バッファサイズ */
+#endif /* SERIAL_RCV_BUFSZ1 */
+
+#ifndef SERIAL_SND_BUFSZ1
+#define	SERIAL_SND_BUFSZ1	256			/* ポート1の送信バッファサイズ */
+#endif /* SERIAL_SND_BUFSZ1 */
+
+static char	rcv_buffer1[SERIAL_RCV_BUFSZ1];
+static char	snd_buffer1[SERIAL_SND_BUFSZ1];
+
+#if TNUM_PORT >= 2						/* ポート2に関する定義 */
+
+#ifndef SERIAL_RCV_BUFSZ2
+#define	SERIAL_RCV_BUFSZ2	256			/* ポート2の受信バッファサイズ */
+#endif /* SERIAL_RCV_BUFSZ2 */
+
+#ifndef SERIAL_SND_BUFSZ2
+#define	SERIAL_SND_BUFSZ2	256			/* ポート2の送信バッファサイズ */
+#endif /* SERIAL_SND_BUFSZ2 */
+
+static char	rcv_buffer2[SERIAL_RCV_BUFSZ2];
+static char	snd_buffer2[SERIAL_SND_BUFSZ2];
+
+#endif /* TNUM_PORT >= 2 */
+
+#if TNUM_PORT >= 3						/* ポート3に関する定義 */
+
+#ifndef SERIAL_RCV_BUFSZ3
+#define	SERIAL_RCV_BUFSZ3	256			/* ポート3の受信バッファサイズ */
+#endif /* SERIAL_RCV_BUFSZ3 */
+
+#ifndef SERIAL_SND_BUFSZ3
+#define	SERIAL_SND_BUFSZ3	256			/* ポート3の送信バッファサイズ */
+#endif /* SERIAL_SND_BUFSZ3 */
+
+static char	rcv_buffer3[SERIAL_RCV_BUFSZ3];
+static char	snd_buffer3[SERIAL_SND_BUFSZ3];
+
+#endif /* TNUM_PORT >= 3 */
+
+#if TNUM_PORT >= 4						/* ポート4に関する定義 */
+
+#ifndef SERIAL_RCV_BUFSZ4
+#define	SERIAL_RCV_BUFSZ4	256			/* ポート4の受信バッファサイズ */
+#endif /* SERIAL_RCV_BUFSZ4 */
+
+#ifndef SERIAL_SND_BUFSZ4
+#define	SERIAL_SND_BUFSZ4	256			/* ポート4の送信バッファサイズ */
+#endif /* SERIAL_SND_BUFSZ4 */
+
+static char	rcv_buffer4[SERIAL_RCV_BUFSZ4];
+static char	snd_buffer4[SERIAL_SND_BUFSZ4];
+
+#endif /* TNUM_PORT >= 4 */
+
+#if TNUM_PORT >= 5
+#error Serial interface driver supports up to 4 ports.
+#endif /* TNUM_PORT >= 5 */
+
+/*
+ *  フロー制御に関連する定数とマクロ
+ */
+#define	FC_STOP			'\023'		/* コントロール-S */
+#define	FC_START		'\021'		/* コントロール-Q */
+
+#define BUFCNT_STOP(bufsz)		((bufsz) * 3 / 4)	/* STOPを送る基準文字数 */
+#define BUFCNT_START(bufsz)		((bufsz) / 2)		/* STARTを送る基準文字数 */
+
+/*
+ *  シリアルポート初期化ブロック
+ */
+typedef struct serial_port_initialization_block {
+	ID		rcv_semid;		/* 受信バッファ管理用セマフォのID */
+	ID		snd_semid;		/* 送信バッファ管理用セマフォのID */
+	uint_t	rcv_bufsz;		/* 受信バッファサイズ */
+	char	*rcv_buffer;	/* 受信バッファ */
+	uint_t	snd_bufsz;		/* 送信バッファサイズ */
+	char	*snd_buffer;	/* 送信バッファ */
+} SPINIB;
+
+static const SPINIB spinib_table[TNUM_PORT] = {
+	{ SERIAL_RCV_SEM1, SERIAL_SND_SEM1,
+	  SERIAL_RCV_BUFSZ1, rcv_buffer1,
+	  SERIAL_SND_BUFSZ1, snd_buffer1 },
+#if TNUM_PORT >= 2
+	{ SERIAL_RCV_SEM2, SERIAL_SND_SEM2,
+	  SERIAL_RCV_BUFSZ2, rcv_buffer2,
+	  SERIAL_SND_BUFSZ2, snd_buffer2 },
+#endif /* TNUM_PORT >= 2 */
+#if TNUM_PORT >= 3
+	{ SERIAL_RCV_SEM3, SERIAL_SND_SEM3,
+	  SERIAL_RCV_BUFSZ3, rcv_buffer3,
+	  SERIAL_SND_BUFSZ3, snd_buffer3 },
+#endif /* TNUM_PORT >= 3 */
+#if TNUM_PORT >= 4
+	{ SERIAL_RCV_SEM4, SERIAL_SND_SEM4,
+	  SERIAL_RCV_BUFSZ4, rcv_buffer4,
+	  SERIAL_SND_BUFSZ4, snd_buffer4 },
+#endif /* TNUM_PORT >= 4 */
+};
+
+/*
+ *  シリアルポート管理ブロック
+ */
+typedef struct serial_port_control_block {
+	const SPINIB *p_spinib;		/* シリアルポート初期化ブロック */
+	SIOPCB	*p_siopcb;			/* シリアルI/Oポート管理ブロック */
+	bool_t	openflag;			/* オープン済みフラグ */
+	bool_t	errorflag;			/* エラーフラグ */
+	uint_t	ioctl;				/* 動作制御の設定値 */
+
+	uint_t	rcv_read_ptr;		/* 受信バッファ読出しポインタ */
+	uint_t	rcv_write_ptr;		/* 受信バッファ書込みポインタ */
+	uint_t	rcv_count;			/* 受信バッファ中の文字数 */
+	char	rcv_fc_chr;			/* 送るべきSTART/STOP */
+	bool_t	rcv_stopped;		/* STOPを送った状態か？ */
+
+	uint_t	snd_read_ptr;		/* 送信バッファ読出しポインタ */
+	uint_t	snd_write_ptr;		/* 送信バッファ書込みポインタ */
+	uint_t	snd_count;			/* 送信バッファ中の文字数 */
+	bool_t	snd_stopped;		/* STOPを受け取った状態か？ */
+} SPCB;
+
+static SPCB	spcb_table[TNUM_PORT];
+
+/*
+ *  シリアルポートIDからシリアルポート管理ブロックを取り出すためのマクロ
+ */
+#define INDEX_PORT(portid)	((uint_t)((portid) - 1))
+#define get_spcb(portid)	(&(spcb_table[INDEX_PORT(portid)]))
+
+/*
+ *  ポインタのインクリメント
+ */
+#define INC_PTR(ptr, bufsz) do {	\
+	if (++(ptr) == (bufsz)) {		\
+		(ptr) = 0;					\
+	 }								\
+} while (false)
+
+/*
+ *  サービスコール呼出しマクロ
+ *
+ *  サービスコール呼出しを含む式expを評価し，返値がエラー（負の値）の場
+ *  合には，ercにercd_expを評価した値を代入し，error_exitにgotoする．
+ */
+#define SVC(exp, ercd_exp) do {		\
+	if ((exp) < 0) {				\
+		ercd = (ercd_exp);			\
+		goto error_exit;			\
+	}								\
+} while (false)
+
+/*
+ *  E_SYSエラーの生成
+ */
+static ER
+gen_ercd_sys(SPCB *p_spcb)
+{
+	p_spcb->errorflag = true;
+	return(E_SYS);
+}
+
+/*
+ *  待ちに入るサービスコールからのエラーの変換
+ */
+static ER
+gen_ercd_wait(ER rercd, SPCB *p_spcb)
+{
+	switch (MERCD(rercd)) {
+	case E_RLWAI:
+	case E_DLT:
+		return(rercd);
+	default:
+		p_spcb->errorflag = true;
+		return(E_SYS);
+	}
+}
+
+/*
+ *  シリアルインタフェースドライバの初期化ルーチン
+ */
+void
+serial_initialize(intptr_t exinf)
+{
+	uint_t	i;
+	SPCB	*p_spcb;
+
+	for (i = 0; i < TNUM_PORT; i++) {
+		p_spcb = &(spcb_table[i]);
+		p_spcb->p_spinib = &(spinib_table[i]);
+		p_spcb->openflag = false;
+	}
+}
+
+/*
+ *  シリアルポートのオープン（サービスコール）
+ */
+ER
+serial_opn_por(ID portid)
+{
+	SPCB	*p_spcb;
+	ER		ercd;
+
+	if (sns_dpn()) {				/* コンテキストのチェック */
+		return(E_CTX);
+	}
+	if (!(1 <= portid && portid <= TNUM_PORT)) {
+		return(E_ID);				/* ポート番号のチェック */
+	}
+	p_spcb = get_spcb(portid);
+
+	SVC(dis_dsp(), gen_ercd_sys(p_spcb));
+	if (p_spcb->openflag) {			/* オープン済みかのチェック */
+		ercd = E_OBJ;
+	}
+	else {
+		/*
+		 *  変数の初期化
+		 */
+		p_spcb->ioctl = (IOCTL_ECHO | IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV);
+
+		p_spcb->rcv_read_ptr = 0U;
+		p_spcb->rcv_write_ptr = 0U;
+		p_spcb->rcv_count = 0U;
+		p_spcb->rcv_fc_chr = '\0';
+		p_spcb->rcv_stopped = false;
+
+		p_spcb->snd_read_ptr = 0U;
+		p_spcb->snd_write_ptr = 0U;
+		p_spcb->snd_count = 0U;
+		p_spcb->snd_stopped = false;
+
+		/*
+		 *  これ以降，割込みを禁止する．
+		 */
+		if (loc_cpu() < 0) {
+			ercd = E_SYS;
+			goto error_exit_enadsp;
+		}
+
+		/*
+		 *  ハードウェア依存のオープン処理
+		 */
+		p_spcb->p_siopcb = sio_opn_por(portid, (intptr_t) p_spcb);
+
+		/*
+		 *  受信通知コールバックを許可する．
+		 */
+		sio_ena_cbr(p_spcb->p_siopcb, SIO_RDY_RCV);
+		p_spcb->openflag = true;
+		p_spcb->errorflag = false;
+
+		if (unl_cpu() < 0) {
+			p_spcb->errorflag = true;
+			ercd = E_SYS;
+			goto error_exit_enadsp;
+		}
+		ercd = E_OK;
+	}
+
+  error_exit_enadsp:
+	SVC(ena_dsp(), gen_ercd_sys(p_spcb));
+
+  error_exit:
+	return(ercd);
+}
+
+/*
+ *  シリアルポートのクローズ（サービスコール）
+ */
+ER
+serial_cls_por(ID portid)
+{
+	SPCB	*p_spcb;
+	ER		ercd;
+	bool_t	eflag = false;
+
+	if (sns_dpn()) {				/* コンテキストのチェック */
+		return(E_CTX);
+	}
+	if (!(1 <= portid && portid <= TNUM_PORT)) {
+		return(E_ID);				/* ポート番号のチェック */
+	}
+	p_spcb = get_spcb(portid);
+
+	SVC(dis_dsp(), gen_ercd_sys(p_spcb));
+	if (!(p_spcb->openflag)) {		/* オープン済みかのチェック */
+		ercd = E_OBJ;
+	}
+	else {
+		/*
+		 *  ハードウェア依存のクローズ処理
+		 */
+		if (loc_cpu() < 0) {
+			eflag = true;
+		}
+		sio_cls_por(p_spcb->p_siopcb);
+		p_spcb->openflag = false;
+		if (unl_cpu() < 0) {
+			eflag = true;
+		}
+
+		/*
+		 *  セマフォの初期化
+		 */
+		if (ini_sem(p_spcb->p_spinib->snd_semid) < 0) {
+			eflag = true;
+		}
+		if (ini_sem(p_spcb->p_spinib->rcv_semid) < 0) {
+			eflag = true;
+		}
+
+		/*
+		 *  エラーコードの設定
+		 */
+		if (eflag) {
+			ercd = gen_ercd_sys(p_spcb);
+		}
+		else {
+			ercd = E_OK;
+		}
+	}
+	SVC(ena_dsp(), gen_ercd_sys(p_spcb));
+
+  error_exit:
+	return(ercd);
+}
+
+/*
+ *  シリアルポートへの文字送信
+ *
+ *  p_spcbで指定されるシリアルI/Oポートに対して，文字cを送信する．文字
+ *  を送信レジスタにいれた場合にはtrueを返す．そうでない場合には，送信
+ *  レジスタが空いたことを通知するコールバック関数を許可し，falseを返す．
+ *  この関数は，CPUロック状態で呼び出される．
+ */
+Inline bool_t
+serial_snd_chr(SPCB *p_spcb, char c)
+{
+	if (sio_snd_chr(p_spcb->p_siopcb, c)) {
+		return(true);
+	}
+	else {
+		sio_ena_cbr(p_spcb->p_siopcb, SIO_RDY_SND);
+		return(false);
+	}
+}
+
+/*
+ *  シリアルポートへの1文字送信
+ */
+static ER_BOOL
+serial_wri_chr(SPCB *p_spcb, char c)
+{
+	bool_t	buffer_full;
+	ER		ercd, rercd;
+
+	/*
+	 *  LFの前にCRを送信する．
+	 */
+	if (c == '\n' && (p_spcb->ioctl & IOCTL_CRLF) != 0U) {
+		/*
+		 *  以下のコードは再帰呼出しになっているが，引数cが'\n'の場合に
+		 *  引数cを'\r'として呼び出すことから，この再帰呼出しは2回目の
+		 *  呼び出しで必ず止まる．
+		 */
+		SVC(rercd = serial_wri_chr(p_spcb, '\r'), rercd);
+		if ((bool_t) rercd) {
+			SVC(rercd = wai_sem(p_spcb->p_spinib->snd_semid),
+										gen_ercd_wait(rercd, p_spcb));
+		}
+	}
+
+	SVC(loc_cpu(), gen_ercd_sys(p_spcb));
+	if (p_spcb->snd_count == 0U && !(p_spcb->snd_stopped)
+								&& serial_snd_chr(p_spcb, c)) {
+		/*
+		 *  シリアルI/Oデバイスの送信レジスタに文字を入れることに成功し
+		 *  た場合．
+		 */
+		buffer_full = false;
+	}
+	else {
+		/*
+		 *  送信バッファに文字を入れる．
+		 */
+		p_spcb->p_spinib->snd_buffer[p_spcb->snd_write_ptr] = c;
+		INC_PTR(p_spcb->snd_write_ptr, p_spcb->p_spinib->snd_bufsz);
+		p_spcb->snd_count++;
+		buffer_full = (p_spcb->snd_count == p_spcb->p_spinib->snd_bufsz);
+	}
+
+	SVC(unl_cpu(), gen_ercd_sys(p_spcb));
+	ercd = (ER_BOOL) buffer_full;
+
+  error_exit:
+	return(ercd);
+}
+
+/*
+ *  シリアルポートへの文字列送信（サービスコール）
+ */
+ER_UINT
+serial_wri_dat(ID portid, const char *buf, uint_t len)
+{
+	SPCB	*p_spcb;
+	bool_t	buffer_full;
+	uint_t	wricnt = 0U;
+	ER		ercd, rercd;
+
+	if (sns_dpn()) {				/* コンテキストのチェック */
+		return(E_CTX);
+	}
+	if (!(1 <= portid && portid <= TNUM_PORT)) {
+		return(E_ID);				/* ポート番号のチェック */
+	}
+
+	p_spcb = get_spcb(portid);
+	if (!(p_spcb->openflag)) {		/* オープン済みかのチェック */
+		return(E_OBJ);
+	}
+	if (p_spcb->errorflag) {		/* エラー状態かのチェック */
+		return(E_SYS);
+	}
+
+	buffer_full = true;				/* ループの1回めはwai_semする */
+	while (wricnt < len) {
+		if (buffer_full) {
+			SVC(rercd = wai_sem(p_spcb->p_spinib->snd_semid),
+										gen_ercd_wait(rercd, p_spcb));
+		}
+		SVC(rercd = serial_wri_chr(p_spcb, *buf++), rercd);
+		wricnt++;
+		buffer_full = (bool_t) rercd;
+	}
+	if (!buffer_full) {
+		SVC(sig_sem(p_spcb->p_spinib->snd_semid), gen_ercd_sys(p_spcb));
+	}
+	ercd = E_OK;
+
+  error_exit:
+	return(wricnt > 0U ? (ER_UINT) wricnt : ercd);
+}
+
+/*
+ *  シリアルポートからの1文字受信
+ */
+static bool_t
+serial_rea_chr(SPCB *p_spcb, char *p_c)
+{
+	bool_t	buffer_empty;
+	ER		ercd;
+
+	SVC(loc_cpu(), gen_ercd_sys(p_spcb));
+
+	/*
+	 *  受信バッファから文字を取り出す．
+	 */
+	*p_c = p_spcb->p_spinib->rcv_buffer[p_spcb->rcv_read_ptr];
+	INC_PTR(p_spcb->rcv_read_ptr, p_spcb->p_spinib->rcv_bufsz);
+	p_spcb->rcv_count--;
+	buffer_empty = (p_spcb->rcv_count == 0U);
+
+	/*
+	 *  STARTを送信する．
+	 */
+	if (p_spcb->rcv_stopped && p_spcb->rcv_count
+								<= BUFCNT_START(p_spcb->p_spinib->rcv_bufsz)) {
+		if (!serial_snd_chr(p_spcb, FC_START)) {
+			p_spcb->rcv_fc_chr = FC_START;
+		}
+		p_spcb->rcv_stopped = false;
+	}
+
+	SVC(unl_cpu(), gen_ercd_sys(p_spcb));
+	ercd = (ER_BOOL) buffer_empty;
+
+  error_exit:
+	return(ercd);
+}
+
+/*
+ *  シリアルポートからの文字列受信（サービスコール）
+ */
+ER_UINT
+serial_rea_dat(ID portid, char *buf, uint_t len)
+{
+	SPCB	*p_spcb;
+	bool_t	buffer_empty;
+	uint_t	reacnt = 0U;
+	char	c = '\0';		/* コンパイラの警告を抑止するために初期化する */
+	ER		ercd, rercd;
+
+	if (sns_dpn()) {				/* コンテキストのチェック */
+		return(E_CTX);
+	}
+	if (!(1 <= portid && portid <= TNUM_PORT)) {
+		return(E_ID);				/* ポート番号のチェック */
+	}
+
+	p_spcb = get_spcb(portid);
+	if (!(p_spcb->openflag)) {		/* オープン済みかのチェック */
+		return(E_OBJ);
+	}
+	if (p_spcb->errorflag) {		/* エラー状態かのチェック */
+		return(E_SYS);
+	}
+
+	buffer_empty = true;			/* ループの1回めはwai_semする */
+	while (reacnt < len) {
+		if (buffer_empty) {
+			SVC(rercd = wai_sem(p_spcb->p_spinib->rcv_semid),
+										gen_ercd_wait(rercd, p_spcb));
+		}
+		SVC(rercd = serial_rea_chr(p_spcb, &c), rercd);
+		*buf++ = c;
+		reacnt++;
+		buffer_empty = (bool_t) rercd;
+
+		/*
+		 *  エコーバック処理．
+		 */
+		if ((p_spcb->ioctl & IOCTL_ECHO) != 0U) {
+			SVC(rercd = wai_sem(p_spcb->p_spinib->snd_semid),
+										gen_ercd_wait(rercd, p_spcb));
+			SVC(rercd = serial_wri_chr(p_spcb, c), rercd);
+			if (!((bool_t) rercd)) {
+				SVC(sig_sem(p_spcb->p_spinib->snd_semid),
+										gen_ercd_sys(p_spcb));
+			}
+		}
+	}
+	if (!buffer_empty) {
+		SVC(sig_sem(p_spcb->p_spinib->rcv_semid), gen_ercd_sys(p_spcb));
+	}
+	ercd = E_OK;
+
+  error_exit:
+	return(reacnt > 0U ? (ER_UINT) reacnt : ercd);
+}
+
+/*
+ *  シリアルポートの制御（サービスコール）
+ */
+ER
+serial_ctl_por(ID portid, uint_t ioctl)
+{
+	SPCB	*p_spcb;
+
+	if (sns_dpn()) {				/* コンテキストのチェック */
+		return(E_CTX);
+	}
+	if (!(1 <= portid && portid <= TNUM_PORT)) {
+		return(E_ID);				/* ポート番号のチェック */
+	}
+
+	p_spcb = get_spcb(portid);
+	if (!(p_spcb->openflag)) {		/* オープン済みかのチェック */
+		return(E_OBJ);
+	}
+	if (p_spcb->errorflag) {		/* エラー状態かのチェック */
+		return(E_SYS);
+	}
+
+	p_spcb->ioctl = ioctl;
+	return(E_OK);
+}
+
+/*
+ *  シリアルポート状態の参照（サービスコール）
+ */
+ER
+serial_ref_por(ID portid, T_SERIAL_RPOR *pk_rpor)
+{
+	SPCB	*p_spcb;
+
+	if (sns_dpn()) {				/* コンテキストのチェック */
+		return(E_CTX);
+	}
+	if (!(1 <= portid && portid <= TNUM_PORT)) {
+		return(E_ID);				/* ポート番号のチェック */
+	}
+
+	p_spcb = get_spcb(portid);
+	if (!(p_spcb->openflag)) {		/* オープン済みかのチェック */
+		return(E_OBJ);
+	}
+	if (p_spcb->errorflag) {		/* エラー状態かのチェック */
+		return(E_SYS);
+	}
+
+	pk_rpor->reacnt = p_spcb->rcv_count;
+	pk_rpor->wricnt = p_spcb->snd_count;
+	return(E_OK);
+}
+
+/*
+ *  シリアルポートからの送信可能コールバック
+ */
+void
+sio_irdy_snd(intptr_t exinf)
+{
+	SPCB	*p_spcb;
+
+	p_spcb = (SPCB *) exinf;
+	if (p_spcb->rcv_fc_chr != '\0') {
+		/*
+		 *  START/STOP を送信する．
+		 */
+		(void) sio_snd_chr(p_spcb->p_siopcb, p_spcb->rcv_fc_chr);
+		p_spcb->rcv_fc_chr = '\0';
+	}
+	else if (!(p_spcb->snd_stopped) && p_spcb->snd_count > 0U) {
+		/*
+		 *  送信バッファ中から文字を取り出して送信する．
+		 */
+		(void) sio_snd_chr(p_spcb->p_siopcb,
+					p_spcb->p_spinib->snd_buffer[p_spcb->snd_read_ptr]);
+		INC_PTR(p_spcb->snd_read_ptr, p_spcb->p_spinib->snd_bufsz);
+		if (p_spcb->snd_count == p_spcb->p_spinib->snd_bufsz) {
+			if (isig_sem(p_spcb->p_spinib->snd_semid) < 0) {
+				p_spcb->errorflag = true;
+			}
+		}
+		p_spcb->snd_count--;
+	}
+	else {
+		/*
+		 *  送信すべき文字がない場合は，送信可能コールバックを禁止する．
+		 */
+		sio_dis_cbr(p_spcb->p_siopcb, SIO_RDY_SND);
+	}
+}
+
+/*
+ *  シリアルポートからの受信通知コールバック
+ */
+void
+sio_irdy_rcv(intptr_t exinf)
+{
+	SPCB	*p_spcb;
+	char	c;
+
+	p_spcb = (SPCB *) exinf;
+	c = (char) sio_rcv_chr(p_spcb->p_siopcb);
+	if ((p_spcb->ioctl & IOCTL_FCSND) != 0U && c == FC_STOP) {
+		/*
+		 *  送信を一時停止する．送信中の文字はそのまま送信する．
+		 */
+		p_spcb->snd_stopped = true;
+	}
+	else if (p_spcb->snd_stopped && (c == FC_START
+				|| (p_spcb->ioctl & IOCTL_FCANY) != 0U)) {
+		/*
+		 *  送信を再開する．
+		 */
+		p_spcb->snd_stopped = false;
+		if (p_spcb->snd_count > 0U) {
+			c = p_spcb->p_spinib->snd_buffer[p_spcb->snd_read_ptr];
+			if (serial_snd_chr(p_spcb, c)) {
+				INC_PTR(p_spcb->snd_read_ptr, p_spcb->p_spinib->snd_bufsz);
+				if (p_spcb->snd_count == p_spcb->p_spinib->snd_bufsz) {
+					if (isig_sem(p_spcb->p_spinib->snd_semid) < 0) {
+						p_spcb->errorflag = true;
+					}
+				}
+				p_spcb->snd_count--;
+			}
+		}
+	}
+	else if ((p_spcb->ioctl & IOCTL_FCSND) != 0U && c == FC_START) {
+		/*
+		 *  送信に対してフロー制御している場合，START は捨てる．
+		 */
+	}
+	else if (p_spcb->rcv_count == p_spcb->p_spinib->rcv_bufsz) {
+		/*
+		 *  バッファフルの場合，受信した文字を捨てる．
+		 */
+	}
+	else {
+		/*
+		 *  受信した文字を受信バッファに入れる．
+		 */
+		p_spcb->p_spinib->rcv_buffer[p_spcb->rcv_write_ptr] = c;
+		INC_PTR(p_spcb->rcv_write_ptr, p_spcb->p_spinib->rcv_bufsz);
+		if (p_spcb->rcv_count == 0U) {
+			if (isig_sem(p_spcb->p_spinib->rcv_semid) < 0) {
+				p_spcb->errorflag = true;
+			}
+		}
+		p_spcb->rcv_count++;
+
+		/*
+		 *  STOPを送信する．
+		 */
+		if ((p_spcb->ioctl & IOCTL_FCRCV) != 0U && !(p_spcb->rcv_stopped)
+						&& p_spcb->rcv_count
+							>= BUFCNT_STOP(p_spcb->p_spinib->rcv_bufsz)) {
+			if (!serial_snd_chr(p_spcb, FC_STOP)) {
+				p_spcb->rcv_fc_chr = FC_STOP;
+			}
+			p_spcb->rcv_stopped = true;
+		}
+	}
+}
+
+/*
+ *  シリアルインタフェースドライバからの未送信文字の取出し
+ */
+bool_t
+serial_get_chr(ID portid, char *p_c)
+{
+	SPCB	*p_spcb;
+
+	if (1 <= portid && portid <= TNUM_PORT) {	/* ポート番号のチェック */
+		p_spcb = get_spcb(portid);
+		if (p_spcb->openflag) {					/* オープン済みかのチェック */
+			if (p_spcb->snd_count > 0U) {
+				*p_c = p_spcb->p_spinib->snd_buffer[p_spcb->snd_read_ptr];
+				INC_PTR(p_spcb->snd_read_ptr, p_spcb->p_spinib->snd_bufsz);
+				p_spcb->snd_count--;
+				return(true);
+			}
+		}
+	}
+	return(false);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/serial.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/serial.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/serial.cfg	(revision 453)
@@ -0,0 +1,28 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *  シリアルインタフェースドライバのコンフィギュレーションファイル
+ */
+
+#include "target_syssvc.h"
+INCLUDE("target_serial.cfg");
+
+#include "syssvc/serial.h"
+ATT_INI({ TA_NULL, 0, serial_initialize });
+
+CRE_SEM(SERIAL_RCV_SEM1, { TA_TPRI, 0, 1 });
+CRE_SEM(SERIAL_SND_SEM1, { TA_TPRI, 1, 1 });
+#if TNUM_PORT >= 2
+CRE_SEM(SERIAL_RCV_SEM2, { TA_TPRI, 0, 1 });
+CRE_SEM(SERIAL_SND_SEM2, { TA_TPRI, 1, 1 });
+#endif /* TNUM_PORT >= 2 */
+#if TNUM_PORT >= 3
+CRE_SEM(SERIAL_RCV_SEM3, { TA_TPRI, 0, 1 });
+CRE_SEM(SERIAL_SND_SEM3, { TA_TPRI, 1, 1 });
+#endif /* TNUM_PORT >= 3 */
+#if TNUM_PORT >= 4
+CRE_SEM(SERIAL_RCV_SEM4, { TA_TPRI, 0, 1 });
+CRE_SEM(SERIAL_SND_SEM4, { TA_TPRI, 1, 1 });
+#endif /* TNUM_PORT >= 4 */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/serial.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/serial.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/serial.h	(revision 453)
@@ -0,0 +1,98 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		シリアルインタフェースドライバ
+ */
+
+#ifndef TOPPERS_SERIAL_H
+#define TOPPERS_SERIAL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ *  シリアルインタフェースドライバの用いるパケット
+ */
+typedef struct {
+	uint_t		reacnt;			/* 受信バッファ中の文字数 */
+	uint_t		wricnt;			/* 送信バッファ中の文字数 */
+} T_SERIAL_RPOR;
+
+/*
+ *  シリアルインタフェースドライバの初期化ルーチン
+ */
+extern void		serial_initialize(intptr_t exinf) throw();
+
+/*
+ *  シリアルインタフェースドライバからの未送信文字の取出し
+ */
+extern bool_t	serial_get_chr(ID portid, char *p_c) throw();
+
+/*
+ *  シリアルインタフェースドライバのサービスコール
+ */
+extern ER		serial_opn_por(ID portid) throw();
+extern ER		serial_cls_por(ID portid) throw();
+extern ER_UINT	serial_rea_dat(ID portid, char *buf, uint_t len) throw();
+extern ER_UINT	serial_wri_dat(ID portid, const char *buf, uint_t len) throw();
+extern ER		serial_ctl_por(ID portid, uint_t ioctl) throw();
+extern ER		serial_ref_por(ID portid, T_SERIAL_RPOR *pk_rpor) throw();
+
+/*
+ *  シリアルインタフェースドライバの動作制御用のための定数
+ *
+ *  以下の定数は，ビット毎に論理和をとって用いる．
+ */
+#define	IOCTL_NULL	0U			/* 指定なし */
+#define	IOCTL_ECHO	0x0001U		/* 受信した文字をエコーバック */
+#define	IOCTL_CRLF	0x0010U		/* LFを送信する前にCRを付加 */
+#define	IOCTL_FCSND	0x0100U		/* 送信に対してフロー制御を行う */
+#define	IOCTL_FCANY	0x0200U		/* どのような文字でも送信再開 */
+#define	IOCTL_FCRCV	0x0400U		/* 受信に対してフロー制御を行う */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TOPPERS_SERIAL_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/syslog.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/syslog.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/syslog.c	(revision 453)
@@ -0,0 +1,243 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2015 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		システムログ機能
+ */
+
+#include <sil.h>
+#undef TOPPERS_OMIT_SYSLOG
+#include <t_syslog.h>
+#include <log_output.h>
+#include "target_syssvc.h"
+#include "syslog.h"
+
+/*
+ *  トレースログマクロのデフォルト定義
+ */
+#ifndef LOG_SYSLOG_WRI_LOG_ENTER
+#define LOG_SYSLOG_WRI_LOG_ENTER(prio, p_syslog)
+#endif /* LOG_SYSLOG_WRI_LOG_ENTER */
+
+#ifndef LOG_SYSLOG_WRI_LOG_LEAVE
+#define LOG_SYSLOG_WRI_LOG_LEAVE(ercd)
+#endif /* LOG_SYSLOG_WRI_LOG_LEAVE */
+
+#ifndef LOG_SYSLOG_REA_LOG_ENTER
+#define LOG_SYSLOG_REA_LOG_ENTER(p_syslog)
+#endif /* LOG_SYSLOG_REA_LOG_ENTER */
+
+#ifndef LOG_SYSLOG_REA_LOG_LEAVE
+#define LOG_SYSLOG_REA_LOG_LEAVE(ercd, p_syslog)
+#endif /* LOG_SYSLOG_REA_LOG_LEAVE */
+
+#ifndef LOG_SYSLOG_MSK_LOG_ENTER
+#define LOG_SYSLOG_MSK_LOG_ENTER(logmask, lowmask)
+#endif /* LOG_SYSLOG_MSK_LOG_ENTER */
+
+#ifndef LOG_SYSLOG_MSK_LOG_LEAVE
+#define LOG_SYSLOG_MSK_LOG_LEAVE(ercd)
+#endif /* LOG_SYSLOG_MSK_LOG_LEAVE */
+
+#ifndef LOG_SYSLOG_REF_LOG_ENTER
+#define LOG_SYSLOG_REF_LOG_ENTER(pk_rlog)
+#endif /* LOG_SYSLOG_REF_LOG_ENTER */
+
+#ifndef LOG_SYSLOG_REF_LOG_LEAVE
+#define LOG_SYSLOG_REF_LOG_LEAVE(ercd, pk_rlog)
+#endif /* LOG_SYSLOG_REF_LOG_LEAVE */
+
+/*
+ *  現在のシステム時刻
+ *
+ *  ログ時刻を取り出すために，やむなく，カーネルの内部変数を参照してい
+ *  る．
+ */
+extern ulong_t	_kernel_current_time;
+
+/*
+ *  ログバッファとそれにアクセスするためのポインタ
+ */
+static SYSLOG	syslog_buffer[TCNT_SYSLOG_BUFFER];	/* ログバッファ */
+static uint_t	syslog_count;			/* ログバッファ中のログの数 */
+static uint_t	syslog_head;			/* 先頭のログの格納位置 */
+static uint_t	syslog_tail;			/* 次のログの格納位置 */
+static uint_t	syslog_lost;			/* 失われたログの数 */
+
+/*
+ *  出力すべきログ情報の重要度（ビットマップ）
+ */
+static uint_t	syslog_logmask;			/* ログバッファに記録すべき重要度 */
+static uint_t	syslog_lowmask_not;		/* 低レベル出力すべき重要度（反転）*/
+
+/*
+ *  システムログ機能の初期化
+ */
+void
+syslog_initialize(intptr_t exinf)
+{
+	syslog_count = 0U;
+	syslog_head = 0U;
+	syslog_tail = 0U;
+	syslog_lost = 0U;
+	syslog_logmask = 0U;
+	syslog_lowmask_not = 0U;
+}     
+
+/* 
+ *  ログ情報の出力
+ *
+ *  CPUロック状態や実行コンテキストによらず動作できるように実装してある．
+ */
+ER
+syslog_wri_log(uint_t prio, const SYSLOG *p_syslog)
+{
+	SIL_PRE_LOC;
+
+	LOG_SYSLOG_WRI_LOG_ENTER(prio, p_syslog);
+	SIL_LOC_INT();
+
+	/*
+	 *  ログ時刻の設定
+	 */
+	((SYSLOG *) p_syslog)->logtim = _kernel_current_time;
+
+	/*
+	 *  ログバッファに記録
+	 */
+	if ((syslog_logmask & LOG_MASK(prio)) != 0U) {
+		syslog_buffer[syslog_tail] = *p_syslog;
+		syslog_tail++;
+		if (syslog_tail >= TCNT_SYSLOG_BUFFER) {
+			syslog_tail = 0U;
+		}
+		if (syslog_count < TCNT_SYSLOG_BUFFER) {
+			syslog_count++;
+		}
+		else {
+			syslog_head = syslog_tail;
+			syslog_lost++;
+		}
+	}
+
+	/*
+	 *  低レベル出力
+	 */
+	if (((~syslog_lowmask_not) & LOG_MASK(prio)) != 0U) {
+		syslog_print(p_syslog, target_fput_log);
+		target_fput_log('\n');
+	}
+
+	SIL_UNL_INT();
+	LOG_SYSLOG_WRI_LOG_LEAVE(E_OK);
+	return(E_OK);
+}
+
+/*
+ *  ログバッファからの読出し
+ *
+ *  CPUロック状態や実行コンテキストによらず動作できるように実装してある．
+ */
+ER_UINT
+syslog_rea_log(SYSLOG *p_syslog)
+{
+	ER_UINT	ercd;
+	SIL_PRE_LOC;
+
+	LOG_SYSLOG_REA_LOG_ENTER(p_syslog);
+	SIL_LOC_INT();
+
+	/*
+	 *  ログバッファからの取出し
+	 */
+	if (syslog_count > 0U) {
+		*p_syslog = syslog_buffer[syslog_head];
+		syslog_count--;
+		syslog_head++;
+		if (syslog_head >= TCNT_SYSLOG_BUFFER) {
+			syslog_head = 0U;
+		}
+		ercd = (ER_UINT) syslog_lost;
+		syslog_lost = 0U;
+	}
+	else {
+		ercd = E_OBJ;
+	}
+
+	SIL_UNL_INT();
+	LOG_SYSLOG_REA_LOG_LEAVE(ercd, p_syslog);
+	return(ercd);
+}
+
+/* 
+ *  出力すべきログ情報の重要度の設定
+ */
+ER
+syslog_msk_log(uint_t logmask, uint_t lowmask)
+{
+	LOG_SYSLOG_MSK_LOG_ENTER(logmask, lowmask);
+	syslog_logmask = logmask;
+	syslog_lowmask_not = ~lowmask;
+	LOG_SYSLOG_MSK_LOG_LEAVE(E_OK);
+	return(E_OK);
+}
+
+/*
+ *  ログバッファの状態参照
+ */
+ER
+syslog_ref_log(T_SYSLOG_RLOG *pk_rlog)
+{
+	SIL_PRE_LOC;
+
+	LOG_SYSLOG_REF_LOG_ENTER(pk_rlog);
+	SIL_LOC_INT();
+
+	pk_rlog->count = syslog_count;
+	pk_rlog->lost = syslog_lost;
+	pk_rlog->logmask = syslog_logmask;
+	pk_rlog->lowmask = ~syslog_lowmask_not;
+
+	SIL_UNL_INT();
+	LOG_SYSLOG_REF_LOG_LEAVE(E_OK, pk_rlog);
+	return(E_OK);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/syslog.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/syslog.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/syslog.cfg	(revision 453)
@@ -0,0 +1,10 @@
+/*
+ *  $Id$
+ */
+
+/*
+ *		システムログ機能のコンフィギュレーションファイル
+ */
+
+#include "syssvc/syslog.h"
+ATT_INI({ TA_NULL, 0, syslog_initialize });
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/syslog.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/syslog.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/syslog.h	(revision 453)
@@ -0,0 +1,95 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2008 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		システムログ機能
+ */
+
+#ifndef TOPPERS_SYSLOG_H
+#define TOPPERS_SYSLOG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ *  システムログ出力を行うための定義
+ */
+#include <t_syslog.h>
+
+/*
+ *  ログバッファとそれにアクセスするためのポインタ
+ */
+#ifndef TCNT_SYSLOG_BUFFER
+#define TCNT_SYSLOG_BUFFER	32		/* ログバッファのサイズ */
+#endif /* TCNT_SYSLOG_BUFFER */
+
+/*
+ *  システムログ機能の初期化
+ */
+extern void	syslog_initialize(intptr_t exinf) throw();
+
+/*
+ *  ログ情報の出力
+ */
+extern ER	syslog_wri_log(uint_t prio, const SYSLOG *p_syslog) throw();
+
+/*
+ *  ログバッファからのログ情報の読出し
+ */
+extern ER_UINT	syslog_rea_log(SYSLOG *p_syslog) throw();
+
+/* 
+ *  出力すべきログ情報の重要度の設定
+ */
+extern ER	syslog_msk_log(uint_t logmask, uint_t lowmask) throw();
+
+/* 
+ *  ログバッファの状態参照
+ */
+extern ER	syslog_ref_log(T_SYSLOG_RLOG *pk_rlog) throw();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TOPPERS_SYSLOG_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/tlsf.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/tlsf.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/tlsf.c	(revision 453)
@@ -0,0 +1,1023 @@
+/* 
+ * Two Levels Segregate Fit memory allocator (TLSF)
+ * Version 2.4.6
+ *
+ * Written by Miguel Masmano Tello <mimastel@doctor.upv.es>
+ *
+ * Thanks to Ismael Ripoll for his suggestions and reviews
+ *
+ * Copyright (C) 2008, 2007, 2006, 2005, 2004
+ *
+ * This code is released using a dual license strategy: GPL/LGPL
+ * You can choose the licence that better fits your requirements.
+ *
+ * Released under the terms of the GNU General Public License Version 2.0
+ * Released under the terms of the GNU Lesser General Public License Version 2.1
+ *
+ */
+
+/*
+ * Code contributions:
+ *
+ * (Jul 28 2007)  Herman ten Brugge <hermantenbrugge@home.nl>:
+ *
+ * - Add 64 bit support. It now runs on x86_64 and solaris64.
+ * - I also tested this on vxworks/32and solaris/32 and i386/32 processors.
+ * - Remove assembly code. I could not measure any performance difference 
+ *   on my core2 processor. This also makes the code more portable.
+ * - Moved defines/typedefs from tlsf.h to tlsf.c
+ * - Changed MIN_BLOCK_SIZE to sizeof (free_ptr_t) and BHDR_OVERHEAD to 
+ *   (sizeof (bhdr_t) - MIN_BLOCK_SIZE). This does not change the fact 
+ *    that the minumum size is still sizeof 
+ *   (bhdr_t).
+ * - Changed all C++ comment style to C style. (// -> /.* ... *./)
+ * - Used ls_bit instead of ffs and ms_bit instead of fls. I did this to 
+ *   avoid confusion with the standard ffs function which returns 
+ *   different values.
+ * - Created set_bit/clear_bit fuctions because they are not present 
+ *   on x86_64.
+ * - Added locking support + extra file target.h to show how to use it.
+ * - Added get_used_size function (REMOVED in 2.4)
+ * - Added rtl_realloc and rtl_calloc function
+ * - Implemented realloc clever support.
+ * - Added some test code in the example directory.
+ * - Bug fixed (discovered by the rockbox project: www.rockbox.org).       
+ *
+ * (Oct 23 2006) Adam Scislowicz: 
+ *
+ * - Support for ARMv5 implemented
+ *
+ */
+
+/*#define USE_SBRK        (0) */
+/*#define USE_MMAP        (0) */
+
+#ifndef USE_PRINTF
+#define USE_PRINTF      (1)
+#endif
+
+#include <string.h>
+
+#ifndef TLSF_USE_LOCKS
+#define	TLSF_USE_LOCKS 	(0)
+#endif
+
+#ifndef TLSF_STATISTIC
+#define	TLSF_STATISTIC 	(0)
+#endif
+
+#ifndef USE_MMAP
+#define	USE_MMAP 	(0)
+#endif
+
+#ifndef USE_SBRK
+#define	USE_SBRK 	(0)
+#endif
+
+
+#if TLSF_USE_LOCKS
+#include "kernel.h"
+#include "kernel_cfg.h"
+#define TLSF_MLOCK_T ID
+#define TLSF_CREATE_LOCK(lock) (*lock = TLSF_SEM)
+#define TLSF_DESTROY_LOCK(lock) ini_sem(*lock)
+#define TLSF_ACQUIRE_LOCK(lock) wai_sem(*lock)
+#define TLSF_RELEASE_LOCK(lock) sig_sem(*lock)
+#else
+#define TLSF_CREATE_LOCK(_unused_)   do{}while(0)
+#define TLSF_DESTROY_LOCK(_unused_)  do{}while(0) 
+#define TLSF_ACQUIRE_LOCK(_unused_)  do{}while(0)
+#define TLSF_RELEASE_LOCK(_unused_)  do{}while(0)
+#endif
+
+#if TLSF_STATISTIC
+#define	TLSF_ADD_SIZE(tlsf, b) do {									\
+		tlsf->used_size += (b->size & BLOCK_SIZE) + BHDR_OVERHEAD;	\
+		if (tlsf->used_size > tlsf->max_size) 						\
+			tlsf->max_size = tlsf->used_size;						\
+		} while(0)
+
+#define	TLSF_REMOVE_SIZE(tlsf, b) do {								\
+		tlsf->used_size -= (b->size & BLOCK_SIZE) + BHDR_OVERHEAD;	\
+	} while(0)
+#else
+#define	TLSF_ADD_SIZE(tlsf, b)	     do{}while(0)
+#define	TLSF_REMOVE_SIZE(tlsf, b)    do{}while(0)
+#endif
+
+#if USE_MMAP || USE_SBRK
+#include <unistd.h>
+#endif
+
+#if USE_MMAP
+#include <sys/mman.h>
+#endif
+
+#include "tlsf.h"
+
+#if !defined(__GNUC__)
+#ifndef __inline__
+#define __inline__
+#endif
+#endif
+
+/* The  debug functions  only can  be used  when _DEBUG_TLSF_  is set. */
+#ifndef _DEBUG_TLSF_
+#define _DEBUG_TLSF_  (0)
+#endif
+
+/*************************************************************************/
+/* Definition of the structures used by TLSF */
+
+
+/* Some IMPORTANT TLSF parameters */
+/* Unlike the preview TLSF versions, now they are statics */
+#define BLOCK_ALIGN (sizeof(void *) * 2)
+
+#define MAX_FLI		(30)
+#define MAX_LOG2_SLI	(5)
+#define MAX_SLI		(1 << MAX_LOG2_SLI)     /* MAX_SLI = 2^MAX_LOG2_SLI */
+
+#define FLI_OFFSET	(6)     /* tlsf structure just will manage blocks bigger */
+/* than 128 bytes */
+#define SMALL_BLOCK	(128)
+#define REAL_FLI	(MAX_FLI - FLI_OFFSET)
+#define MIN_BLOCK_SIZE	(sizeof (free_ptr_t))
+#define BHDR_OVERHEAD	(sizeof (bhdr_t) - MIN_BLOCK_SIZE)
+#define TLSF_SIGNATURE	(0x2A59FA59)
+
+#define	PTR_MASK	(sizeof(void *) - 1)
+#define BLOCK_SIZE	(0xFFFFFFFF - PTR_MASK)
+
+#define GET_NEXT_BLOCK(_addr, _r) ((bhdr_t *) ((char *) (_addr) + (_r)))
+#define	MEM_ALIGN		  ((BLOCK_ALIGN) - 1)
+#define ROUNDUP_SIZE(_r)          (((_r) + MEM_ALIGN) & ~MEM_ALIGN)
+#define ROUNDDOWN_SIZE(_r)        ((_r) & ~MEM_ALIGN)
+#define ROUNDUP(_x, _v)           ((((~(_x)) + 1) & ((_v)-1)) + (_x))
+
+#define BLOCK_STATE	(0x1)
+#define PREV_STATE	(0x2)
+
+/* bit 0 of the block size */
+#define FREE_BLOCK	(0x1)
+#define USED_BLOCK	(0x0)
+
+/* bit 1 of the block size */
+#define PREV_FREE	(0x2)
+#define PREV_USED	(0x0)
+
+
+#define DEFAULT_AREA_SIZE (1024*10)
+
+#ifdef USE_MMAP
+#define PAGE_SIZE (getpagesize())
+#endif
+
+#ifdef USE_PRINTF
+#include <stdio.h>
+#include <t_stddef.h>
+#include <t_syslog.h>
+#define PRINT_MSG(fmt, args...) syslog(LOG_ERROR, fmt, ## args)
+#define ERROR_MSG(fmt, args...) syslog(LOG_ERROR, fmt, ## args)
+#else
+# if !defined(PRINT_MSG)
+#  define PRINT_MSG(fmt, args...)
+# endif
+# if !defined(ERROR_MSG)
+#  define ERROR_MSG(fmt, args...)
+# endif
+#endif
+
+typedef unsigned int u32_t;     /* NOTE: Make sure that this type is 4 bytes long on your computer */
+typedef unsigned char u8_t;     /* NOTE: Make sure that this type is 1 byte on your computer */
+
+typedef struct free_ptr_struct {
+    struct bhdr_struct *prev;
+    struct bhdr_struct *next;
+} free_ptr_t;
+
+typedef struct bhdr_struct {
+    /* This pointer is just valid if the first bit of size is set */
+    struct bhdr_struct *prev_hdr;
+    /* The size is stored in bytes */
+    size_t size;                /* bit 0 indicates whether the block is used and */
+    /* bit 1 allows to know whether the previous block is free */
+    union {
+        struct free_ptr_struct free_ptr;
+        u8_t buffer[1];         /*sizeof(struct free_ptr_struct)]; */
+    } ptr;
+} bhdr_t;
+
+/* This structure is embedded at the beginning of each area, giving us
+ * enough information to cope with a set of areas */
+
+typedef struct area_info_struct {
+    bhdr_t *end;
+    struct area_info_struct *next;
+} area_info_t;
+
+typedef struct TLSF_struct {
+    /* the TLSF's structure signature */
+    u32_t tlsf_signature;
+
+#if TLSF_USE_LOCKS
+    TLSF_MLOCK_T lock;
+#endif
+
+#if TLSF_STATISTIC
+    /* These can not be calculated outside tlsf because we
+     * do not know the sizes when freeing/reallocing memory. */
+    size_t used_size;
+    size_t max_size;
+#endif
+
+    /* A linked list holding all the existing areas */
+    area_info_t *area_head;
+
+    /* the first-level bitmap */
+    /* This array should have a size of REAL_FLI bits */
+    u32_t fl_bitmap;
+
+    /* the second-level bitmap */
+    u32_t sl_bitmap[REAL_FLI];
+
+    bhdr_t *matrix[REAL_FLI][MAX_SLI];
+} tlsf_t;
+
+
+/******************************************************************/
+/**************     Helping functions    **************************/
+/******************************************************************/
+static __inline__ void set_bit(int nr, u32_t * addr);
+static __inline__ void clear_bit(int nr, u32_t * addr);
+static __inline__ int ls_bit(int x);
+static __inline__ int ms_bit(int x);
+static __inline__ void MAPPING_SEARCH(size_t * _r, int *_fl, int *_sl);
+static __inline__ void MAPPING_INSERT(size_t _r, int *_fl, int *_sl);
+static __inline__ bhdr_t *FIND_SUITABLE_BLOCK(tlsf_t * _tlsf, int *_fl, int *_sl);
+static __inline__ bhdr_t *process_area(void *area, size_t size);
+#if USE_SBRK || USE_MMAP
+static __inline__ void *get_new_area(size_t * size);
+#endif
+
+static const int table[] = {
+    -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4,
+    4, 4,
+    4, 4, 4, 4, 4, 4, 4,
+    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+    5,
+    5, 5, 5, 5, 5, 5, 5,
+    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+    6,
+    6, 6, 6, 6, 6, 6, 6,
+    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+    6,
+    6, 6, 6, 6, 6, 6, 6,
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+    7,
+    7, 7, 7, 7, 7, 7, 7,
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+    7,
+    7, 7, 7, 7, 7, 7, 7,
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+    7,
+    7, 7, 7, 7, 7, 7, 7,
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+    7,
+    7, 7, 7, 7, 7, 7, 7
+};
+
+static __inline__ int ls_bit(int i)
+{
+    unsigned int a;
+    unsigned int x = i & -i;
+
+    a = x <= 0xffff ? (x <= 0xff ? 0 : 8) : (x <= 0xffffff ? 16 : 24);
+    return table[x >> a] + a;
+}
+
+static __inline__ int ms_bit(int i)
+{
+    unsigned int a;
+    unsigned int x = (unsigned int) i;
+
+    a = x <= 0xffff ? (x <= 0xff ? 0 : 8) : (x <= 0xffffff ? 16 : 24);
+    return table[x >> a] + a;
+}
+
+static __inline__ void set_bit(int nr, u32_t * addr)
+{
+    addr[nr >> 5] |= 1 << (nr & 0x1f);
+}
+
+static __inline__ void clear_bit(int nr, u32_t * addr)
+{
+    addr[nr >> 5] &= ~(1 << (nr & 0x1f));
+}
+
+static __inline__ void MAPPING_SEARCH(size_t * _r, int *_fl, int *_sl)
+{
+    int _t;
+
+    if (*_r < SMALL_BLOCK) {
+        *_fl = 0;
+        *_sl = *_r / (SMALL_BLOCK / MAX_SLI);
+    } else {
+        _t = (1 << (ms_bit(*_r) - MAX_LOG2_SLI)) - 1;
+        *_r = *_r + _t;
+        *_fl = ms_bit(*_r);
+        *_sl = (*_r >> (*_fl - MAX_LOG2_SLI)) - MAX_SLI;
+        *_fl -= FLI_OFFSET;
+        /*if ((*_fl -= FLI_OFFSET) < 0) // FL wil be always >0!
+         *_fl = *_sl = 0;
+         */
+        *_r &= ~_t;
+    }
+}
+
+static __inline__ void MAPPING_INSERT(size_t _r, int *_fl, int *_sl)
+{
+    if (_r < SMALL_BLOCK) {
+        *_fl = 0;
+        *_sl = _r / (SMALL_BLOCK / MAX_SLI);
+    } else {
+        *_fl = ms_bit(_r);
+        *_sl = (_r >> (*_fl - MAX_LOG2_SLI)) - MAX_SLI;
+        *_fl -= FLI_OFFSET;
+    }
+}
+
+
+static __inline__ bhdr_t *FIND_SUITABLE_BLOCK(tlsf_t * _tlsf, int *_fl, int *_sl)
+{
+    u32_t _tmp = _tlsf->sl_bitmap[*_fl] & (~0 << *_sl);
+    bhdr_t *_b = NULL;
+
+    if (_tmp) {
+        *_sl = ls_bit(_tmp);
+        _b = _tlsf->matrix[*_fl][*_sl];
+    } else {
+        *_fl = ls_bit(_tlsf->fl_bitmap & (~0 << (*_fl + 1)));
+        if (*_fl > 0) {         /* likely */
+            *_sl = ls_bit(_tlsf->sl_bitmap[*_fl]);
+            _b = _tlsf->matrix[*_fl][*_sl];
+        }
+    }
+    return _b;
+}
+
+
+#define EXTRACT_BLOCK_HDR(_b, _tlsf, _fl, _sl) do {					\
+		_tlsf -> matrix [_fl] [_sl] = _b -> ptr.free_ptr.next;		\
+		if (_tlsf -> matrix[_fl][_sl])								\
+			_tlsf -> matrix[_fl][_sl] -> ptr.free_ptr.prev = NULL;	\
+		else {														\
+			clear_bit (_sl, &_tlsf -> sl_bitmap [_fl]);				\
+			if (!_tlsf -> sl_bitmap [_fl])							\
+				clear_bit (_fl, &_tlsf -> fl_bitmap);				\
+		}															\
+		_b -> ptr.free_ptr.prev =  NULL;				\
+		_b -> ptr.free_ptr.next =  NULL;				\
+	}while(0)
+
+
+#define EXTRACT_BLOCK(_b, _tlsf, _fl, _sl) do {							\
+		if (_b -> ptr.free_ptr.next)									\
+			_b -> ptr.free_ptr.next -> ptr.free_ptr.prev = _b -> ptr.free_ptr.prev; \
+		if (_b -> ptr.free_ptr.prev)									\
+			_b -> ptr.free_ptr.prev -> ptr.free_ptr.next = _b -> ptr.free_ptr.next; \
+		if (_tlsf -> matrix [_fl][_sl] == _b) {							\
+			_tlsf -> matrix [_fl][_sl] = _b -> ptr.free_ptr.next;		\
+			if (!_tlsf -> matrix [_fl][_sl]) {							\
+				clear_bit (_sl, &_tlsf -> sl_bitmap[_fl]);				\
+				if (!_tlsf -> sl_bitmap [_fl])							\
+					clear_bit (_fl, &_tlsf -> fl_bitmap);				\
+			}															\
+		}																\
+		_b -> ptr.free_ptr.prev = NULL;					\
+		_b -> ptr.free_ptr.next = NULL;					\
+	} while(0)
+
+#define INSERT_BLOCK(_b, _tlsf, _fl, _sl) do {							\
+		_b -> ptr.free_ptr.prev = NULL; \
+		_b -> ptr.free_ptr.next = _tlsf -> matrix [_fl][_sl]; \
+		if (_tlsf -> matrix [_fl][_sl])									\
+			_tlsf -> matrix [_fl][_sl] -> ptr.free_ptr.prev = _b;		\
+		_tlsf -> matrix [_fl][_sl] = _b;								\
+		set_bit (_sl, &_tlsf -> sl_bitmap [_fl]);						\
+		set_bit (_fl, &_tlsf -> fl_bitmap);								\
+	} while(0)
+
+#if USE_SBRK || USE_MMAP
+static __inline__ void *get_new_area(size_t * size) 
+{
+    void *area;
+
+#if USE_SBRK
+    area = (void *)sbrk(0);
+    if (((void *)sbrk(*size)) != ((void *) -1))
+        return area;
+#endif
+
+#ifndef MAP_ANONYMOUS
+/* https://dev.openwrt.org/ticket/322 */
+# define MAP_ANONYMOUS MAP_ANON
+#endif
+
+
+#if USE_MMAP
+    *size = ROUNDUP(*size, PAGE_SIZE);
+    if ((area = mmap(0, *size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) != MAP_FAILED)
+        return area;
+#endif
+    return ((void *) ~0);
+}
+#endif
+
+static __inline__ bhdr_t *process_area(void *area, size_t size)
+{
+    bhdr_t *b, *lb, *ib;
+    area_info_t *ai;
+
+    ib = (bhdr_t *) area;
+    ib->size =
+        (sizeof(area_info_t) <
+         MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : ROUNDUP_SIZE(sizeof(area_info_t)) | USED_BLOCK | PREV_USED;
+    b = (bhdr_t *) GET_NEXT_BLOCK(ib->ptr.buffer, ib->size & BLOCK_SIZE);
+    b->size = ROUNDDOWN_SIZE(size - 3 * BHDR_OVERHEAD - (ib->size & BLOCK_SIZE)) | USED_BLOCK | PREV_USED;
+    b->ptr.free_ptr.prev = b->ptr.free_ptr.next = 0;
+    lb = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
+    lb->prev_hdr = b;
+    lb->size = 0 | USED_BLOCK | PREV_FREE;
+    ai = (area_info_t *) ib->ptr.buffer;
+    ai->next = 0;
+    ai->end = lb;
+    return ib;
+}
+
+/******************************************************************/
+/******************** Begin of the allocator code *****************/
+/******************************************************************/
+
+static char *mp = NULL;         /* Default memory pool. */
+
+/******************************************************************/
+size_t init_memory_pool(size_t mem_pool_size, void *mem_pool)
+{
+/******************************************************************/
+    tlsf_t *tlsf;
+    bhdr_t *b, *ib;
+
+    if (!mem_pool || !mem_pool_size || mem_pool_size < sizeof(tlsf_t) + BHDR_OVERHEAD * 8) {
+        ERROR_MSG("init_memory_pool (): memory_pool invalid\n");
+        return -1;
+    }
+
+    if (((unsigned long) mem_pool & PTR_MASK)) {
+        ERROR_MSG("init_memory_pool (): mem_pool must be aligned to a word\n");
+        return -1;
+    }
+    tlsf = (tlsf_t *) mem_pool;
+    /* Check if already initialised */
+    if (tlsf->tlsf_signature == TLSF_SIGNATURE) {
+        mp = mem_pool;
+        b = GET_NEXT_BLOCK(mp, ROUNDUP_SIZE(sizeof(tlsf_t)));
+        return b->size & BLOCK_SIZE;
+    }
+
+    mp = mem_pool;
+
+    /* Zeroing the memory pool */
+    memset(mem_pool, 0, sizeof(tlsf_t));
+
+    tlsf->tlsf_signature = TLSF_SIGNATURE;
+
+    TLSF_CREATE_LOCK(&tlsf->lock);
+
+    ib = process_area(GET_NEXT_BLOCK
+                      (mem_pool, ROUNDUP_SIZE(sizeof(tlsf_t))), ROUNDDOWN_SIZE(mem_pool_size - sizeof(tlsf_t)));
+    b = GET_NEXT_BLOCK(ib->ptr.buffer, ib->size & BLOCK_SIZE);
+    free_ex(b->ptr.buffer, tlsf);
+    tlsf->area_head = (area_info_t *) ib->ptr.buffer;
+
+#if TLSF_STATISTIC
+    tlsf->used_size = mem_pool_size - (b->size & BLOCK_SIZE);
+    tlsf->max_size = tlsf->used_size;
+#endif
+
+    return (b->size & BLOCK_SIZE);
+}
+
+/******************************************************************/
+size_t add_new_area(void *area, size_t area_size, void *mem_pool)
+{
+/******************************************************************/
+    tlsf_t *tlsf = (tlsf_t *) mem_pool;
+    area_info_t *ptr, *ptr_prev, *ai;
+    bhdr_t *ib0, *b0, *lb0, *ib1, *b1, *lb1, *next_b;
+
+    memset(area, 0, area_size);
+    ptr = tlsf->area_head;
+    ptr_prev = 0;
+
+    ib0 = process_area(area, area_size);
+    b0 = GET_NEXT_BLOCK(ib0->ptr.buffer, ib0->size & BLOCK_SIZE);
+    lb0 = GET_NEXT_BLOCK(b0->ptr.buffer, b0->size & BLOCK_SIZE);
+
+    /* Before inserting the new area, we have to merge this area with the
+       already existing ones */
+
+    while (ptr) {
+        ib1 = (bhdr_t *) ((char *) ptr - BHDR_OVERHEAD);
+        b1 = GET_NEXT_BLOCK(ib1->ptr.buffer, ib1->size & BLOCK_SIZE);
+        lb1 = ptr->end;
+
+        /* Merging the new area with the next physically contigous one */
+        if ((unsigned long) ib1 == (unsigned long) lb0 + BHDR_OVERHEAD) {
+            if (tlsf->area_head == ptr) {
+                tlsf->area_head = ptr->next;
+                ptr = ptr->next;
+            } else {
+                ptr_prev->next = ptr->next;
+                ptr = ptr->next;
+            }
+
+            b0->size =
+                ROUNDDOWN_SIZE((b0->size & BLOCK_SIZE) +
+                               (ib1->size & BLOCK_SIZE) + 2 * BHDR_OVERHEAD) | USED_BLOCK | PREV_USED;
+
+            b1->prev_hdr = b0;
+            lb0 = lb1;
+
+            continue;
+        }
+
+        /* Merging the new area with the previous physically contigous
+           one */
+        if ((unsigned long) lb1->ptr.buffer == (unsigned long) ib0) {
+            if (tlsf->area_head == ptr) {
+                tlsf->area_head = ptr->next;
+                ptr = ptr->next;
+            } else {
+                ptr_prev->next = ptr->next;
+                ptr = ptr->next;
+            }
+
+            lb1->size =
+                ROUNDDOWN_SIZE((b0->size & BLOCK_SIZE) +
+                               (ib0->size & BLOCK_SIZE) + 2 * BHDR_OVERHEAD) | USED_BLOCK | (lb1->size & PREV_STATE);
+            next_b = GET_NEXT_BLOCK(lb1->ptr.buffer, lb1->size & BLOCK_SIZE);
+            next_b->prev_hdr = lb1;
+            b0 = lb1;
+            ib0 = ib1;
+
+            continue;
+        }
+        ptr_prev = ptr;
+        ptr = ptr->next;
+    }
+
+    /* Inserting the area in the list of linked areas */
+    ai = (area_info_t *) ib0->ptr.buffer;
+    ai->next = tlsf->area_head;
+    ai->end = lb0;
+    tlsf->area_head = ai;
+    free_ex(b0->ptr.buffer, mem_pool);
+    return (b0->size & BLOCK_SIZE);
+}
+
+
+/******************************************************************/
+size_t get_used_size(void *mem_pool)
+{
+/******************************************************************/
+#if TLSF_STATISTIC
+    return ((tlsf_t *) mem_pool)->used_size;
+#else
+    return 0;
+#endif
+}
+
+/******************************************************************/
+size_t get_max_size(void *mem_pool)
+{
+/******************************************************************/
+#if TLSF_STATISTIC
+    return ((tlsf_t *) mem_pool)->max_size;
+#else
+    return 0;
+#endif
+}
+
+/******************************************************************/
+void destroy_memory_pool(void *mem_pool)
+{
+/******************************************************************/
+    tlsf_t *tlsf = (tlsf_t *) mem_pool;
+
+    tlsf->tlsf_signature = 0;
+
+    TLSF_DESTROY_LOCK(&tlsf->lock);
+
+}
+
+
+/******************************************************************/
+void *tlsf_malloc(size_t size)
+{
+/******************************************************************/
+    void *ret;
+
+#if USE_MMAP || USE_SBRK
+    if (!mp) {
+        size_t area_size;
+        void *area;
+
+        area_size = sizeof(tlsf_t) + BHDR_OVERHEAD * 8; /* Just a safety constant */
+        area_size = (area_size > DEFAULT_AREA_SIZE) ? area_size : DEFAULT_AREA_SIZE;
+        area = get_new_area(&area_size);
+        if (area == ((void *) ~0))
+            return NULL;        /* Not enough system memory */
+        init_memory_pool(area_size, area);
+    }
+#endif
+
+    TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock);
+
+    ret = malloc_ex(size, mp);
+
+    TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock);
+
+    return ret;
+}
+
+/******************************************************************/
+void tlsf_free(void *ptr)
+{
+/******************************************************************/
+
+    TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock);
+
+    free_ex(ptr, mp);
+
+    TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock);
+
+}
+
+/******************************************************************/
+void *tlsf_realloc(void *ptr, size_t size)
+{
+/******************************************************************/
+    void *ret;
+
+#if USE_MMAP || USE_SBRK
+	if (!mp) {
+		return tlsf_malloc(size);
+	}
+#endif
+
+    TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock);
+
+    ret = realloc_ex(ptr, size, mp);
+
+    TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock);
+
+    return ret;
+}
+
+/******************************************************************/
+void *tlsf_calloc(size_t nelem, size_t elem_size)
+{
+/******************************************************************/
+    void *ret;
+
+    TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock);
+
+    ret = calloc_ex(nelem, elem_size, mp);
+
+    TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock);
+
+    return ret;
+}
+
+/******************************************************************/
+void *malloc_ex(size_t size, void *mem_pool)
+{
+/******************************************************************/
+    tlsf_t *tlsf = (tlsf_t *) mem_pool;
+    bhdr_t *b, *b2, *next_b;
+    int fl, sl;
+    size_t tmp_size;
+
+    size = (size < MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : ROUNDUP_SIZE(size);
+
+    /* Rounding up the requested size and calculating fl and sl */
+    MAPPING_SEARCH(&size, &fl, &sl);
+
+    /* Searching a free block, recall that this function changes the values of fl and sl,
+       so they are not longer valid when the function fails */
+    b = FIND_SUITABLE_BLOCK(tlsf, &fl, &sl);
+#if USE_MMAP || USE_SBRK
+    if (!b) {
+        size_t area_size;
+        void *area;
+        /* Growing the pool size when needed */
+        area_size = size + BHDR_OVERHEAD * 8;   /* size plus enough room for the requered headers. */
+        area_size = (area_size > DEFAULT_AREA_SIZE) ? area_size : DEFAULT_AREA_SIZE;
+        area = get_new_area(&area_size);        /* Call sbrk or mmap */
+        if (area == ((void *) ~0))
+            return NULL;        /* Not enough system memory */
+        add_new_area(area, area_size, mem_pool);
+        /* Rounding up the requested size and calculating fl and sl */
+        MAPPING_SEARCH(&size, &fl, &sl);
+        /* Searching a free block */
+        b = FIND_SUITABLE_BLOCK(tlsf, &fl, &sl);
+    }
+#endif
+    if (!b)
+        return NULL;            /* Not found */
+
+    EXTRACT_BLOCK_HDR(b, tlsf, fl, sl);
+
+    /*-- found: */
+    next_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
+    /* Should the block be split? */
+    tmp_size = (b->size & BLOCK_SIZE) - size;
+    if (tmp_size >= sizeof(bhdr_t)) {
+        tmp_size -= BHDR_OVERHEAD;
+        b2 = GET_NEXT_BLOCK(b->ptr.buffer, size);
+        b2->size = tmp_size | FREE_BLOCK | PREV_USED;
+        next_b->prev_hdr = b2;
+        MAPPING_INSERT(tmp_size, &fl, &sl);
+        INSERT_BLOCK(b2, tlsf, fl, sl);
+
+        b->size = size | (b->size & PREV_STATE);
+    } else {
+        next_b->size &= (~PREV_FREE);
+        b->size &= (~FREE_BLOCK);       /* Now it's used */
+    }
+
+    TLSF_ADD_SIZE(tlsf, b);
+
+    return (void *) b->ptr.buffer;
+}
+
+/******************************************************************/
+void free_ex(void *ptr, void *mem_pool)
+{
+/******************************************************************/
+    tlsf_t *tlsf = (tlsf_t *) mem_pool;
+    bhdr_t *b, *tmp_b;
+    int fl = 0, sl = 0;
+
+    if (!ptr) {
+        return;
+    }
+    b = (bhdr_t *) ((char *) ptr - BHDR_OVERHEAD);
+    b->size |= FREE_BLOCK;
+
+    TLSF_REMOVE_SIZE(tlsf, b);
+
+    b->ptr.free_ptr.prev = NULL;
+    b->ptr.free_ptr.next = NULL;
+    tmp_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
+    if (tmp_b->size & FREE_BLOCK) {
+        MAPPING_INSERT(tmp_b->size & BLOCK_SIZE, &fl, &sl);
+        EXTRACT_BLOCK(tmp_b, tlsf, fl, sl);
+        b->size += (tmp_b->size & BLOCK_SIZE) + BHDR_OVERHEAD;
+    }
+    if (b->size & PREV_FREE) {
+        tmp_b = b->prev_hdr;
+        MAPPING_INSERT(tmp_b->size & BLOCK_SIZE, &fl, &sl);
+        EXTRACT_BLOCK(tmp_b, tlsf, fl, sl);
+        tmp_b->size += (b->size & BLOCK_SIZE) + BHDR_OVERHEAD;
+        b = tmp_b;
+    }
+    MAPPING_INSERT(b->size & BLOCK_SIZE, &fl, &sl);
+    INSERT_BLOCK(b, tlsf, fl, sl);
+
+    tmp_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
+    tmp_b->size |= PREV_FREE;
+    tmp_b->prev_hdr = b;
+}
+
+/******************************************************************/
+void *realloc_ex(void *ptr, size_t new_size, void *mem_pool)
+{
+/******************************************************************/
+    tlsf_t *tlsf = (tlsf_t *) mem_pool;
+    void *ptr_aux;
+    unsigned int cpsize;
+    bhdr_t *b, *tmp_b, *next_b;
+    int fl, sl;
+    size_t tmp_size;
+
+    if (!ptr) {
+        if (new_size)
+            return (void *) malloc_ex(new_size, mem_pool);
+        if (!new_size)
+            return NULL;
+    } else if (!new_size) {
+        free_ex(ptr, mem_pool);
+        return NULL;
+    }
+
+    b = (bhdr_t *) ((char *) ptr - BHDR_OVERHEAD);
+    next_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
+    new_size = (new_size < MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : ROUNDUP_SIZE(new_size);
+    tmp_size = (b->size & BLOCK_SIZE);
+    if (new_size <= tmp_size) {
+	TLSF_REMOVE_SIZE(tlsf, b);
+        if (next_b->size & FREE_BLOCK) {
+            MAPPING_INSERT(next_b->size & BLOCK_SIZE, &fl, &sl);
+            EXTRACT_BLOCK(next_b, tlsf, fl, sl);
+            tmp_size += (next_b->size & BLOCK_SIZE) + BHDR_OVERHEAD;
+            next_b = GET_NEXT_BLOCK(next_b->ptr.buffer, next_b->size & BLOCK_SIZE);
+            /* We allways reenter this free block because tmp_size will
+               be greater then sizeof (bhdr_t) */
+        }
+        tmp_size -= new_size;
+        if (tmp_size >= sizeof(bhdr_t)) {
+            tmp_size -= BHDR_OVERHEAD;
+            tmp_b = GET_NEXT_BLOCK(b->ptr.buffer, new_size);
+            tmp_b->size = tmp_size | FREE_BLOCK | PREV_USED;
+            next_b->prev_hdr = tmp_b;
+            next_b->size |= PREV_FREE;
+            MAPPING_INSERT(tmp_size, &fl, &sl);
+            INSERT_BLOCK(tmp_b, tlsf, fl, sl);
+            b->size = new_size | (b->size & PREV_STATE);
+        }
+	TLSF_ADD_SIZE(tlsf, b);
+        return (void *) b->ptr.buffer;
+    }
+    if ((next_b->size & FREE_BLOCK)) {
+        if (new_size <= (tmp_size + (next_b->size & BLOCK_SIZE))) {
+			TLSF_REMOVE_SIZE(tlsf, b);
+            MAPPING_INSERT(next_b->size & BLOCK_SIZE, &fl, &sl);
+            EXTRACT_BLOCK(next_b, tlsf, fl, sl);
+            b->size += (next_b->size & BLOCK_SIZE) + BHDR_OVERHEAD;
+            next_b = GET_NEXT_BLOCK(b->ptr.buffer, b->size & BLOCK_SIZE);
+            next_b->prev_hdr = b;
+            next_b->size &= ~PREV_FREE;
+            tmp_size = (b->size & BLOCK_SIZE) - new_size;
+            if (tmp_size >= sizeof(bhdr_t)) {
+                tmp_size -= BHDR_OVERHEAD;
+                tmp_b = GET_NEXT_BLOCK(b->ptr.buffer, new_size);
+                tmp_b->size = tmp_size | FREE_BLOCK | PREV_USED;
+                next_b->prev_hdr = tmp_b;
+                next_b->size |= PREV_FREE;
+                MAPPING_INSERT(tmp_size, &fl, &sl);
+                INSERT_BLOCK(tmp_b, tlsf, fl, sl);
+                b->size = new_size | (b->size & PREV_STATE);
+            }
+			TLSF_ADD_SIZE(tlsf, b);
+            return (void *) b->ptr.buffer;
+        }
+    }
+
+    if (!(ptr_aux = malloc_ex(new_size, mem_pool))){
+        return NULL;
+    }      
+    
+    cpsize = ((b->size & BLOCK_SIZE) > new_size) ? new_size : (b->size & BLOCK_SIZE);
+
+    memcpy(ptr_aux, ptr, cpsize);
+
+    free_ex(ptr, mem_pool);
+    return ptr_aux;
+}
+
+
+/******************************************************************/
+void *calloc_ex(size_t nelem, size_t elem_size, void *mem_pool)
+{
+/******************************************************************/
+    void *ptr;
+
+    if (nelem <= 0 || elem_size <= 0)
+        return NULL;
+
+    if (!(ptr = malloc_ex(nelem * elem_size, mem_pool)))
+        return NULL;
+    memset(ptr, 0, nelem * elem_size);
+
+    return ptr;
+}
+
+
+
+#if _DEBUG_TLSF_
+
+/***************  DEBUG FUNCTIONS   **************/
+
+/* The following functions have been designed to ease the debugging of */
+/* the TLSF  structure.  For non-developing  purposes, it may  be they */
+/* haven't too much worth.  To enable them, _DEBUG_TLSF_ must be set.  */
+
+extern void dump_memory_region(unsigned char *mem_ptr, unsigned int size);
+extern void print_block(bhdr_t * b);
+extern void print_tlsf(tlsf_t * tlsf);
+void print_all_blocks(tlsf_t * tlsf);
+
+void dump_memory_region(unsigned char *mem_ptr, unsigned int size)
+{
+
+    unsigned long begin = (unsigned long) mem_ptr;
+    unsigned long end = (unsigned long) mem_ptr + size;
+    int column = 0;
+
+    begin >>= 2;
+    begin <<= 2;
+
+    end >>= 2;
+    end++;
+    end <<= 2;
+
+    PRINT_MSG("\nMemory region dumped: 0x%lx - 0x%lx\n\n", begin, end);
+
+    column = 0;
+    PRINT_MSG("0x%lx ", begin);
+
+    while (begin < end) {
+        if (((unsigned char *) begin)[0] == 0)
+            PRINT_MSG("00");
+        else
+            PRINT_MSG("%02x", ((unsigned char *) begin)[0]);
+        if (((unsigned char *) begin)[1] == 0)
+            PRINT_MSG("00 ");
+        else
+            PRINT_MSG("%02x ", ((unsigned char *) begin)[1]);
+        begin += 2;
+        column++;
+        if (column == 8) {
+            PRINT_MSG("\n0x%lx ", begin);
+            column = 0;
+        }
+
+    }
+    PRINT_MSG("\n\n");
+}
+
+void print_block(bhdr_t * b)
+{
+    if (!b)
+        return;
+    PRINT_MSG(">> [%p] (", b);
+    if ((b->size & BLOCK_SIZE))
+        PRINT_MSG("%lu bytes, ", (unsigned long) (b->size & BLOCK_SIZE));
+    else
+        PRINT_MSG("sentinel, ");
+    if ((b->size & BLOCK_STATE) == FREE_BLOCK)
+        PRINT_MSG("free [%p, %p], ", b->ptr.free_ptr.prev, b->ptr.free_ptr.next);
+    else
+        PRINT_MSG("used, ");
+    if ((b->size & PREV_STATE) == PREV_FREE)
+        PRINT_MSG("prev. free [%p])\n", b->prev_hdr);
+    else
+        PRINT_MSG("prev used)\n");
+}
+
+void print_tlsf(tlsf_t * tlsf)
+{
+    bhdr_t *next;
+    int i, j;
+
+    PRINT_MSG("\nTLSF at %p\n", tlsf);
+
+    PRINT_MSG("FL bitmap: 0x%x\n\n", (unsigned) tlsf->fl_bitmap);
+
+    for (i = 0; i < REAL_FLI; i++) {
+        if (tlsf->sl_bitmap[i])
+            PRINT_MSG("SL bitmap 0x%x\n", (unsigned) tlsf->sl_bitmap[i]);
+        for (j = 0; j < MAX_SLI; j++) {
+            next = tlsf->matrix[i][j];
+            if (next)
+                PRINT_MSG("-> [%d][%d]\n", i, j);
+            while (next) {
+                print_block(next);
+                next = next->ptr.free_ptr.next;
+            }
+        }
+    }
+}
+
+void print_all_blocks(tlsf_t * tlsf)
+{
+    area_info_t *ai;
+    bhdr_t *next;
+    PRINT_MSG("\nTLSF at %p\nALL BLOCKS\n\n", tlsf);
+    ai = tlsf->area_head;
+    while (ai) {
+        next = (bhdr_t *) ((char *) ai - BHDR_OVERHEAD);
+        while (next) {
+            print_block(next);
+            if ((next->size & BLOCK_SIZE))
+                next = GET_NEXT_BLOCK(next->ptr.buffer, next->size & BLOCK_SIZE);
+            else
+                next = NULL;
+        }
+        ai = ai->next;
+    }
+}
+
+#endif
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/tlsf.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/tlsf.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/tlsf.cfg	(revision 453)
@@ -0,0 +1,5 @@
+/*
+ *  $Id$
+ */
+CRE_SEM(TLSF_SEM, { TA_NULL, 1, 1 });
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/tlsf.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/tlsf.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/syssvc/tlsf.h	(revision 453)
@@ -0,0 +1,39 @@
+/*
+ * Two Levels Segregate Fit memory allocator (TLSF)
+ * Version 2.4.6
+ *
+ * Written by Miguel Masmano Tello <mimastel@doctor.upv.es>
+ *
+ * Thanks to Ismael Ripoll for his suggestions and reviews
+ *
+ * Copyright (C) 2008, 2007, 2006, 2005, 2004
+ *
+ * This code is released using a dual license strategy: GPL/LGPL
+ * You can choose the licence that better fits your requirements.
+ *
+ * Released under the terms of the GNU General Public License Version 2.0
+ * Released under the terms of the GNU Lesser General Public License Version 2.1
+ *
+ */
+
+#ifndef _TLSF_H_
+#define _TLSF_H_
+
+//#include <sys/types.h>
+
+extern size_t init_memory_pool(size_t, void *);
+extern size_t get_used_size(void *);
+extern size_t get_max_size(void *);
+extern void destroy_memory_pool(void *);
+extern size_t add_new_area(void *, size_t, void *);
+extern void *malloc_ex(size_t, void *);
+extern void free_ex(void *, void *);
+extern void *realloc_ex(void *, size_t, void *);
+extern void *calloc_ex(size_t, size_t, void *);
+
+extern void *tlsf_malloc(size_t size);
+extern void tlsf_free(void *ptr);
+extern void *tlsf_realloc(void *ptr, size_t size);
+extern void *tlsf_calloc(size_t nelem, size_t elem_size);
+
+#endif
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/MANIFEST
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/MANIFEST	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/MANIFEST	(revision 453)
@@ -0,0 +1,25 @@
+PACKAGE asp
+
+MANIFEST
+Makefile.target
+kendryte-k210.h
+target.tf
+target_cfg1_out.h
+target_check.tf
+target_config.c
+target_config.h
+target_inithook.c
+target_kernel.h
+target_rename.def
+target_rename.h
+target_serial.c
+target_serial.cfg
+target_serial.h
+target_sil.h
+target_stddef.h
+target_support.S
+target_syssvc.h
+target_test.h
+target_timer.cfg
+target_timer.h
+target_unrename.h
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/Makefile.target
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/Makefile.target	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/Makefile.target	(revision 453)
@@ -0,0 +1,88 @@
+#
+#		Makefileのターゲット依存部（RISCV64/K210用）
+#
+
+#
+#  ボード名，プロセッサ名，開発環境名の定義
+#
+BOARD = k210
+PRC = riscv
+TOOL = gcc
+
+#
+#  COMポートピン0設定
+#
+COM0 = 0
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(TARGETDIR)
+COPTS := $(COPTS) -march=rv64imafdc -mabi=lp64d -mcmodel=medany -nostdlib -fstrict-volatile-bitfields
+CDEFS := $(CDEFS) -D__riscv64 -DUSE_FPU -DCOM0=$(COM0)
+
+#
+#  カーネルに関する定義
+#
+KERNEL_DIR := $(KERNEL_DIR) $(TARGETDIR)
+KERNEL_ASMOBJS := $(KERNEL_ASMOBJS) 
+KERNEL_COBJS := $(KERNEL_COBJS) target_config.o 
+
+#
+#  システムサービスに関する定義
+#
+SYSSVC_COBJS := $(SYSSVC_COBJS) target_serial.o target_inithook.o
+
+#
+#  GNU開発環境のターゲットアーキテクチャの定義
+#
+GCC_TARGET = riscv-none-embed
+
+#
+#  トレースログ記録のサンプルコードに関する定義
+#
+ifeq ($(ENABLE_TRACE),true)
+	COPTS := $(COPTS) -DTOPPERS_ENABLE_TRACE
+	KERNEL_DIR := $(KERNEL_DIR) $(SRCDIR)/arch/logtrace
+	KERNEL_COBJS := $(KERNEL_COBJS) trace_config.o trace_dump.o
+endif
+
+#
+#  各セグメントの開始アドレスの定義
+#
+TEXT_START_ADDRESS = 80000000
+
+#
+#  リンカスクリプトの定義
+#
+LDSCRIPT = $(SRCDIR)/arch/$(PRC)_$(TOOL)/riscv64elf.ld
+
+#
+#  スタートアップモジュールに関する定義
+#
+#  m68kelf.ldに「STARTUP(start.o)」を記述したため，スタートアップモジュー
+#  ルの名前をHIDDEN_OBJSに定義する．また，LDFLAGSに-nostdlibを追加している．
+#
+HIDDEN_OBJS = start.o
+
+$(HIDDEN_OBJS): %.o: %.S
+	$(CC) -c $(CFLAGS) $(KERNEL_CFLAGS) $<
+
+$(HIDDEN_OBJS:.o=.d): %.d: %.S
+	@$(PERL) $(SRCDIR)/utils/makedep -C $(CC) $(MAKEDEP_OPTS) \
+		-O "$(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
+
+LDFLAGS := -nostdlib $(LDFLAGS)
+CFG1_OUT_LDFLAGS := -nostdlib $(CFG1_OUT_LDFLAGS)
+LIBS := $(LIBS) -lgcc
+
+#
+#  依存関係の定義
+#
+kernel_cfg.timestamp: $(TARGETDIR)/target.tf
+$(OBJFILE): $(TARGETDIR)/target_check.tf
+
+#
+#  プロセッサ依存部のインクルード
+#
+include $(SRCDIR)/arch/$(PRC)_$(TOOL)/Makefile.prc
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/kendryte-k210.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/kendryte-k210.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/kendryte-k210.h	(revision 453)
@@ -0,0 +1,1528 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ *
+ *  上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+ *  によって公表されている GNU General Public License の Version 2 に記
+ *  述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+ *  を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (3) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+ *  含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+ *  接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+#ifndef _KENDRYTE_K210_H_
+#define _KENDRYTE_K210_H_
+
+#include <sil.h>
+#include "encoding.h"
+
+#define TMAX_INTNO          66
+#define TMAX_PRIORITY       8
+
+/*
+ *  割込み優先度設定のための定義
+ */
+#define TIRQ_NMI           (-8)		/* ノンマスカブル割込み */
+#define TIRQ_LEVEL7        (-7)		/* 割込みレベル7 */
+#define TIRQ_LEVEL6        (-6)		/* 割込みレベル6 */
+#define TIRQ_LEVEL5        (-5)		/* 割込みレベル5 */
+#define TIRQ_LEVEL4        (-4)		/* 割込みレベル4 */
+#define TIRQ_LEVEL3        (-3)		/* 割込みレベル3 */
+#define TIRQ_LEVEL2        (-2)		/* 割込みレベル2 */
+#define TIRQ_LEVEL1        (-1)		/* 割込みレベル1 */
+
+/*
+ *  MACHINE EXCEPTION NUMBER
+ */
+#define EXC_INSTRUCTION_ADDRESS_MISALIGNED  0
+#define EXC_INSTRUCTION_ADDRESS_FAULT       1
+#define EXC_ILLEGAL_INSTRUCTION             2
+#define EXC_BREAKPOINT                      3
+#define EXC_LOAD_ADDRESS_MISALIGNED         4
+#define EXC_LOAD_ADDRESS_FAULT              5
+#define EXC_STORE_AMO_ADDRESS_MISALIGNED    6
+#define EXC_STORE_AMO_ACCESS_FAUT           7
+#define EXC_ENVIRONMENT_CALL_FROM_MMODE     11
+
+/*
+ *  MACHINE INTERRUPT NUMBER
+ */
+#define IRQ_MACHINE_SOFTWARE                3
+#define IRQ_MACHIE_TIMER                    7
+#define IRQ_MACHINE_EXTERNAL                11
+
+/*
+ *  GLOBAL INTERRUPT NUMBER
+ */
+#define IRQ_VECTOR_RESERVED                 0
+#define IRQ_VECTOR_SPI0                     1	/* SPI0 interrupt */
+#define IRQ_VECTOR_SPI1                     2	/* SPI1 interrupt */
+#define IRQ_VECTOR_SPI_SLAVE                3	/* SPI_SLAVE interrupt */
+#define IRQ_VECTOR_SPI3                     4	/* SPI3 interrupt */
+#define IRQ_VECTOR_I2S0                     5	/* I2S0 interrupt */
+#define IRQ_VECTOR_I2S1                     6	/* I2S1 interrupt */
+#define IRQ_VECTOR_I2S2                     7	/* I2S2 interrupt */
+#define IRQ_VECTOR_I2C0                     8	/* I2C0 interrupt */
+#define IRQ_VECTOR_I2C1                     9	/* I2C1 interrupt */
+#define IRQ_VECTOR_I2C2                     10	/* I2C2 interrupt */
+#define IRQ_VECTOR_UART1                    11	/* UART1 interrupt */
+#define IRQ_VECTOR_UART2                    12	/* UART2 interrupt */
+#define IRQ_VECTOR_UART3                    13	/* UART3 interrupt */
+#define IRQ_VECTOR_TIMER0A                  14	/* TIMER0 channel 0 or 1 interrupt */
+#define IRQ_VECTOR_TIMER0B                  15	/* TIMER0 channel 2 or 3 interrupt */
+#define IRQ_VECTOR_TIMER1A                  16	/* TIMER1 channel 0 or 1 interrupt */
+#define IRQ_VECTOR_TIMER1B                  17	/* TIMER1 channel 2 or 3 interrupt */
+#define IRQ_VECTOR_TIMER2A                  18	/* TIMER2 channel 0 or 1 interrupt */
+#define IRQ_VECTOR_TIMER2B                  19	/* TIMER2 channel 2 or 3 interrupt */
+#define IRQ_VECTOR_RTC                      20	/* RTC tick and alarm interrupt */
+#define IRQ_VECTOR_WDT0                     21	/* Watching dog timer0 interrupt */
+#define IRQ_VECTOR_WDT1                     22	/* Watching dog timer1 interrupt */
+#define IRQ_VECTOR_APB_GPIO                 23	/* APB GPIO interrupt */
+#define IRQ_VECTOR_DVP                      24	/* Digital video port interrupt */
+#define IRQ_VECTOR_AI                       25	/* AI accelerator interrupt */
+#define IRQ_VECTOR_FFT                      26	/* FFT accelerator interrupt */
+#define IRQ_VECTOR_DMA0                     27	/* DMA channel0 interrupt */
+#define IRQ_VECTOR_DMA1                     28	/* DMA channel1 interrupt */
+#define IRQ_VECTOR_DMA2                     29	/* DMA channel2 interrupt */
+#define IRQ_VECTOR_DMA3                     30	/* DMA channel3 interrupt */
+#define IRQ_VECTOR_DMA4                     31	/* DMA channel4 interrupt */
+#define IRQ_VECTOR_DMA5                     32	/* DMA channel5 interrupt */
+#define IRQ_VECTOR_UARTHS                   33	/* Hi-speed UART0 interrupt */
+#define IRQ_VECTOR_GPIOHS0                  34	/* Hi-speed GPIO0 interrupt */
+#define IRQ_VECTOR_GPIOHS1                  35	/* Hi-speed GPIO1 interrupt */
+#define IRQ_VECTOR_GPIOHS2                  36	/* Hi-speed GPIO2 interrupt */
+#define IRQ_VECTOR_GPIOHS3                  37	/* Hi-speed GPIO3 interrupt */
+#define IRQ_VECTOR_GPIOHS4                  38	/* Hi-speed GPIO4 interrupt */
+#define IRQ_VECTOR_GPIOHS5                  39	/* Hi-speed GPIO5 interrupt */
+#define IRQ_VECTOR_GPIOHS6                  40	/* Hi-speed GPIO6 interrupt */
+#define IRQ_VECTOR_GPIOHS7                  41	/* Hi-speed GPIO7 interrupt */
+#define IRQ_VECTOR_GPIOHS8                  42	/* Hi-speed GPIO8 interrupt */
+#define IRQ_VECTOR_GPIOHS9                  43	/* Hi-speed GPIO9 interrupt */
+#define IRQ_VECTOR_GPIOHS10                 44	/* Hi-speed GPIO10 interrupt */
+#define IRQ_VECTOR_GPIOHS11                 45	/* Hi-speed GPIO11 interrupt */
+#define IRQ_VECTOR_GPIOHS12                 46	/* Hi-speed GPIO12 interrupt */
+#define IRQ_VECTOR_GPIOHS13                 47	/* Hi-speed GPIO13 interrupt */
+#define IRQ_VECTOR_GPIOHS14                 48	/* Hi-speed GPIO14 interrupt */
+#define IRQ_VECTOR_GPIOHS15                 49	/* Hi-speed GPIO15 interrupt */
+#define IRQ_VECTOR_GPIOHS16                 50	/* Hi-speed GPIO16 interrupt */
+#define IRQ_VECTOR_GPIOHS17                 51	/* Hi-speed GPIO17 interrupt */
+#define IRQ_VECTOR_GPIOHS18                 52	/* Hi-speed GPIO18 interrupt */
+#define IRQ_VECTOR_GPIOHS19                 53	/* Hi-speed GPIO19 interrupt */
+#define IRQ_VECTOR_GPIOHS20                 54	/* Hi-speed GPIO20 interrupt */
+#define IRQ_VECTOR_GPIOHS21                 55	/* Hi-speed GPIO21 interrupt */
+#define IRQ_VECTOR_GPIOHS22                 56	/* Hi-speed GPIO22 interrupt */
+#define IRQ_VECTOR_GPIOHS23                 57	/* Hi-speed GPIO23 interrupt */
+#define IRQ_VECTOR_GPIOHS24                 58	/* Hi-speed GPIO24 interrupt */
+#define IRQ_VECTOR_GPIOHS25                 59	/* Hi-speed GPIO25 interrupt */
+#define IRQ_VECTOR_GPIOHS26                 60	/* Hi-speed GPIO26 interrupt */
+#define IRQ_VECTOR_GPIOHS27                 61	/* Hi-speed GPIO27 interrupt */
+#define IRQ_VECTOR_GPIOHS28                 62	/* Hi-speed GPIO28 interrupt */
+#define IRQ_VECTOR_GPIOHS29                 63	/* Hi-speed GPIO29 interrupt */
+#define IRQ_VECTOR_GPIOHS30                 64	/* Hi-speed GPIO30 interrupt */
+#define IRQ_VECTOR_GPIOHS31                 65	/* Hi-speed GPIO31 interrupt */
+
+
+/*
+ *  FPIOAファンクション定義
+ */
+#define FUNC_JTAG_TCLK                      0	/* JTAG Test Clock */
+#define FUNC_JTAG_TDI                       1	/* JTAG Test Data In */
+#define FUNC_JTAG_TMS                       2	/* JTAG Test Mode Select */
+#define FUNC_JTAG_TDO                       3	/* JTAG Test Data Out */
+#define FUNC_SPI0_D0                        4	/* SPI0 Data 0 */
+#define FUNC_SPI0_D1                        5	/* SPI0 Data 1 */
+#define FUNC_SPI0_D2                        6	/* SPI0 Data 2 */
+#define FUNC_SPI0_D3                        7	/* SPI0 Data 3 */
+#define FUNC_SPI0_D4                        8	/* SPI0 Data 4 */
+#define FUNC_SPI0_D5                        9	/* SPI0 Data 5 */
+#define FUNC_SPI0_D6                        10	/* SPI0 Data 6 */
+#define FUNC_SPI0_D7                        11	/* SPI0 Data 7 */
+#define FUNC_SPI0_SS0                       12	/* SPI0 Chip Select 0 */
+#define FUNC_SPI0_SS1                       13	/* SPI0 Chip Select 1 */
+#define FUNC_SPI0_SS2                       14	/* SPI0 Chip Select 2 */
+#define FUNC_SPI0_SS3                       15	/* SPI0 Chip Select 3 */
+#define FUNC_SPI0_ARB                       16	/* SPI0 Arbitration */
+#define FUNC_SPI0_SCLK                      17	/* SPI0 Serial Clock */
+#define FUNC_UARTHS_RX                      18	/* UART High speed Receiver */
+#define FUNC_UARTHS_TX                      19	/* UART High speed Transmitter */
+#define FUNC_RESV6                          20	/* Reserved function */
+#define FUNC_RESV7                          21	/* Reserved function */
+#define FUNC_CLK_SPI1                       22	/* Clock SPI1 */
+#define FUNC_CLK_I2C1                       23	/* Clock I2C1 */
+#define FUNC_GPIOHS0                        24	/* GPIO High speed 0 */
+#define FUNC_GPIOHS1                        25	/* GPIO High speed 1 */
+#define FUNC_GPIOHS2                        26	/* GPIO High speed 2 */
+#define FUNC_GPIOHS3                        27	/* GPIO High speed 3 */
+#define FUNC_GPIOHS4                        28	/* GPIO High speed 4 */
+#define FUNC_GPIOHS5                        29	/* GPIO High speed 5 */
+#define FUNC_GPIOHS6                        30	/* GPIO High speed 6 */
+#define FUNC_GPIOHS7                        31	/* GPIO High speed 7 */
+#define FUNC_GPIOHS8                        32	/* GPIO High speed 8 */
+#define FUNC_GPIOHS9                        33	/* GPIO High speed 9 */
+#define FUNC_GPIOHS10                       34	/* GPIO High speed 10 */
+#define FUNC_GPIOHS11                       35	/* GPIO High speed 11 */
+#define FUNC_GPIOHS12                       36	/* GPIO High speed 12 */
+#define FUNC_GPIOHS13                       37	/* GPIO High speed 13 */
+#define FUNC_GPIOHS14                       38	/* GPIO High speed 14 */
+#define FUNC_GPIOHS15                       39	/* GPIO High speed 15 */
+#define FUNC_GPIOHS16                       40	/* GPIO High speed 16 */
+#define FUNC_GPIOHS17                       41	/* GPIO High speed 17 */
+#define FUNC_GPIOHS18                       42	/* GPIO High speed 18 */
+#define FUNC_GPIOHS19                       43	/* GPIO High speed 19 */
+#define FUNC_GPIOHS20                       44	/* GPIO High speed 20 */
+#define FUNC_GPIOHS21                       45	/* GPIO High speed 21 */
+#define FUNC_GPIOHS22                       46	/* GPIO High speed 22 */
+#define FUNC_GPIOHS23                       47	/* GPIO High speed 23 */
+#define FUNC_GPIOHS24                       48	/* GPIO High speed 24 */
+#define FUNC_GPIOHS25                       49	/* GPIO High speed 25 */
+#define FUNC_GPIOHS26                       50	/* GPIO High speed 26 */
+#define FUNC_GPIOHS27                       51	/* GPIO High speed 27 */
+#define FUNC_GPIOHS28                       52	/* GPIO High speed 28 */
+#define FUNC_GPIOHS29                       53	/* GPIO High speed 29 */
+#define FUNC_GPIOHS30                       54	/* GPIO High speed 30 */
+#define FUNC_GPIOHS31                       55	/* GPIO High speed 31 */
+#define FUNC_GPIO0                          56	/* GPIO pin 0 */
+#define FUNC_GPIO1                          57	/* GPIO pin 1 */
+#define FUNC_GPIO2                          58	/* GPIO pin 2 */
+#define FUNC_GPIO3                          59	/* GPIO pin 3 */
+#define FUNC_GPIO4                          60	/* GPIO pin 4 */
+#define FUNC_GPIO5                          61	/* GPIO pin 5 */
+#define FUNC_GPIO6                          62	/* GPIO pin 6 */
+#define FUNC_GPIO7                          63	/* GPIO pin 7 */
+#define FUNC_UART1_RX                       64	/* UART1 Receiver */
+#define FUNC_UART1_TX                       65	/* UART1 Transmitter */
+#define FUNC_UART2_RX                       66	/* UART2 Receiver */
+#define FUNC_UART2_TX                       67	/* UART2 Transmitter */
+#define FUNC_UART3_RX                       68	/* UART3 Receiver */
+#define FUNC_UART3_TX                       69	/* UART3 Transmitter */
+#define FUNC_SPI1_D0                        70	/* SPI1 Data 0 */
+#define FUNC_SPI1_D1                        71	/* SPI1 Data 1 */
+#define FUNC_SPI1_D2                        72	/* SPI1 Data 2 */
+#define FUNC_SPI1_D3                        73	/* SPI1 Data 3 */
+#define FUNC_SPI1_D4                        74	/* SPI1 Data 4 */
+#define FUNC_SPI1_D5                        75	/* SPI1 Data 5 */
+#define FUNC_SPI1_D6                        76	/* SPI1 Data 6 */
+#define FUNC_SPI1_D7                        77	/* SPI1 Data 7 */
+#define FUNC_SPI1_SS0                       78	/* SPI1 Chip Select 0 */
+#define FUNC_SPI1_SS1                       79	/* SPI1 Chip Select 1 */
+#define FUNC_SPI1_SS2                       80	/* SPI1 Chip Select 2 */
+#define FUNC_SPI1_SS3                       81	/* SPI1 Chip Select 3 */
+#define FUNC_SPI1_ARB                       82	/* SPI1 Arbitration */
+#define FUNC_SPI1_SCLK                      83	/* SPI1 Serial Clock */
+#define FUNC_SPI_SLAVE_D0                   84	/* SPI Slave Data 0 */
+#define FUNC_SPI_SLAVE_SS                   85	/* SPI Slave Select */
+#define FUNC_SPI_SLAVE_SCLK                 86	/* SPI Slave Serial Clock */
+#define FUNC_I2S0_MCLK                      87	/* I2S0 Master Clock */
+#define FUNC_I2S0_SCLK                      88	/* I2S0 Serial Clock(BCLK) */
+#define FUNC_I2S0_WS                        89	/* I2S0 Word Select(LRCLK) */
+#define FUNC_I2S0_IN_D0                     90	/* I2S0 Serial Data Input 0 */
+#define FUNC_I2S0_IN_D1                     91	/* I2S0 Serial Data Input 1 */
+#define FUNC_I2S0_IN_D2                     92	/* I2S0 Serial Data Input 2 */
+#define FUNC_I2S0_IN_D3                     93	/* I2S0 Serial Data Input 3 */
+#define FUNC_I2S0_OUT_D0                    94	/* I2S0 Serial Data Output 0 */
+#define FUNC_I2S0_OUT_D1                    95	/* I2S0 Serial Data Output 1 */
+#define FUNC_I2S0_OUT_D2                    96	/* I2S0 Serial Data Output 2 */
+#define FUNC_I2S0_OUT_D3                    97	/* I2S0 Serial Data Output 3 */
+#define FUNC_I2S1_MCLK                      98	/* I2S1 Master Clock */
+#define FUNC_I2S1_SCLK                      99	/* I2S1 Serial Clock(BCLK) */
+#define FUNC_I2S1_WS                        100	/* I2S1 Word Select(LRCLK) */
+#define FUNC_I2S1_IN_D0                     101	/* I2S1 Serial Data Input 0 */
+#define FUNC_I2S1_IN_D1                     102	/* I2S1 Serial Data Input 1 */
+#define FUNC_I2S1_IN_D2                     103	/* I2S1 Serial Data Input 2 */
+#define FUNC_I2S1_IN_D3                     104	/* I2S1 Serial Data Input 3 */
+#define FUNC_I2S1_OUT_D0                    105	/* I2S1 Serial Data Output 0 */
+#define FUNC_I2S1_OUT_D1                    106	/* I2S1 Serial Data Output 1 */
+#define FUNC_I2S1_OUT_D2                    107	/* I2S1 Serial Data Output 2 */
+#define FUNC_I2S1_OUT_D3                    108	/* I2S1 Serial Data Output 3 */
+#define FUNC_I2S2_MCLK                      109	/* I2S2 Master Clock */
+#define FUNC_I2S2_SCLK                      110	/* I2S2 Serial Clock(BCLK) */
+#define FUNC_I2S2_WS                        111	/* I2S2 Word Select(LRCLK) */
+#define FUNC_I2S2_IN_D0                     112	/* I2S2 Serial Data Input 0 */
+#define FUNC_I2S2_IN_D1                     113	/* I2S2 Serial Data Input 1 */
+#define FUNC_I2S2_IN_D2                     114	/* I2S2 Serial Data Input 2 */
+#define FUNC_I2S2_IN_D3                     115	/* I2S2 Serial Data Input 3 */
+#define FUNC_I2S2_OUT_D0                    116	/* I2S2 Serial Data Output 0 */
+#define FUNC_I2S2_OUT_D1                    117	/* I2S2 Serial Data Output 1 */
+#define FUNC_I2S2_OUT_D2                    118	/* I2S2 Serial Data Output 2 */
+#define FUNC_I2S2_OUT_D3                    119	/* I2S2 Serial Data Output 3 */
+#define FUNC_RESV0                          120	/* Reserved function */
+#define FUNC_RESV1                          121	/* Reserved function */
+#define FUNC_RESV2                          122	/* Reserved function */
+#define FUNC_RESV3                          123	/* Reserved function */
+#define FUNC_RESV4                          124	/* Reserved function */
+#define FUNC_RESV5                          125	/* Reserved function */
+#define FUNC_I2C0_SCLK                      126	/* I2C0 Serial Clock */
+#define FUNC_I2C0_SDA                       127	/* I2C0 Serial Data */
+#define FUNC_I2C1_SCLK                      128	/* I2C1 Serial Clock */
+#define FUNC_I2C1_SDA                       129	/* I2C1 Serial Data */
+#define FUNC_I2C2_SCLK                      130	/* I2C2 Serial Clock */
+#define FUNC_I2C2_SDA                       131	/* I2C2 Serial Data */
+#define FUNC_CMOS_XCLK                      132	/* DVP System Clock */
+#define FUNC_CMOS_RST                       133	/* DVP System Reset */
+#define FUNC_CMOS_PWDN                      134	/* DVP Power Down Mode */
+#define FUNC_CMOS_VSYNC                     135	/* DVP Vertical Sync */
+#define FUNC_CMOS_HREF                      136	/* DVP Horizontal Reference output */
+#define FUNC_CMOS_PCLK                      137	/* Pixel Clock */
+#define FUNC_CMOS_D0                        138	/* Data Bit 0 */
+#define FUNC_CMOS_D1                        139	/* Data Bit 1 */
+#define FUNC_CMOS_D2                        140	/* Data Bit 2 */
+#define FUNC_CMOS_D3                        141	/* Data Bit 3 */
+#define FUNC_CMOS_D4                        142	/* Data Bit 4 */
+#define FUNC_CMOS_D5                        143	/* Data Bit 5 */
+#define FUNC_CMOS_D6                        144	/* Data Bit 6 */
+#define FUNC_CMOS_D7                        145	/* Data Bit 7 */
+#define FUNC_SCCB_SCLK                      146	/* SCCB Serial Clock */
+#define FUNC_SCCB_SDA                       147	/* SCCB Serial Data */
+#define FUNC_UART1_CTS                      148	/* UART1 Clear To Send */
+#define FUNC_UART1_DSR                      149	/* UART1 Data Set Ready */
+#define FUNC_UART1_DCD                      150	/* UART1 Data Carrier Detect */
+#define FUNC_UART1_RI                       151	/* UART1 Ring Indicator */
+#define FUNC_UART1_SIR_IN                   152	/* UART1 Serial Infrared Input */
+#define FUNC_UART1_DTR                      153	/* UART1 Data Terminal Ready */
+#define FUNC_UART1_RTS                      154	/* UART1 Request To Send */
+#define FUNC_UART1_OUT2                     155	/* UART1 User-designated Output 2 */
+#define FUNC_UART1_OUT1                     156	/* UART1 User-designated Output 1 */
+#define FUNC_UART1_SIR_OUT                  157	/* UART1 Serial Infrared Output */
+#define FUNC_UART1_BAUD                     158	/* UART1 Transmit Clock Output */
+#define FUNC_UART1_RE                       159	/* UART1 Receiver Output Enable */
+#define FUNC_UART1_DE                       160	/* UART1 Driver Output Enable */
+#define FUNC_UART1_RS485_EN                 161	/* UART1 RS485 Enable */
+#define FUNC_UART2_CTS                      162	/* UART2 Clear To Send */
+#define FUNC_UART2_DSR                      163	/* UART2 Data Set Ready */
+#define FUNC_UART2_DCD                      164	/* UART2 Data Carrier Detect */
+#define FUNC_UART2_RI                       165	/* UART2 Ring Indicator */
+#define FUNC_UART2_SIR_IN                   166	/* UART2 Serial Infrared Input */
+#define FUNC_UART2_DTR                      167	/* UART2 Data Terminal Ready */
+#define FUNC_UART2_RTS                      168	/* UART2 Request To Send */
+#define FUNC_UART2_OUT2                     169	/* UART2 User-designated Output 2 */
+#define FUNC_UART2_OUT1                     170	/* UART2 User-designated Output 1 */
+#define FUNC_UART2_SIR_OUT                  171	/* UART2 Serial Infrared Output */
+#define FUNC_UART2_BAUD                     172	/* UART2 Transmit Clock Output */
+#define FUNC_UART2_RE                       173	/* UART2 Receiver Output Enable */
+#define FUNC_UART2_DE                       174	/* UART2 Driver Output Enable */
+#define FUNC_UART2_RS485_EN                 175	/* UART2 RS485 Enable */
+#define FUNC_UART3_CTS                      176	/* UART3 Clear To Send */
+#define FUNC_UART3_DSR                      177	/* UART3 Data Set Ready */
+#define FUNC_UART3_DCD                      178	/* UART3 Data Carrier Detect */
+#define FUNC_UART3_RI                       179	/* UART3 Ring Indicator */
+#define FUNC_UART3_SIR_IN                   180	/* UART3 Serial Infrared Input */
+#define FUNC_UART3_DTR                      181	/* UART3 Data Terminal Ready */
+#define FUNC_UART3_RTS                      182	/* UART3 Request To Send */
+#define FUNC_UART3_OUT2                     183	/* UART3 User-designated Output 2 */
+#define FUNC_UART3_OUT1                     184	/* UART3 User-designated Output 1 */
+#define FUNC_UART3_SIR_OUT                  185	/* UART3 Serial Infrared Output */
+#define FUNC_UART3_BAUD                     186	/* UART3 Transmit Clock Output */
+#define FUNC_UART3_RE                       187	/* UART3 Receiver Output Enable */
+#define FUNC_UART3_DE                       188	/* UART3 Driver Output Enable */
+#define FUNC_UART3_RS485_EN                 189	/* UART3 RS485 Enable */
+#define FUNC_TIMER0_TOGGLE1                 190	/* TIMER0 Toggle Output 1 */
+#define FUNC_TIMER0_TOGGLE2                 191	/* TIMER0 Toggle Output 2 */
+#define FUNC_TIMER0_TOGGLE3                 192	/* TIMER0 Toggle Output 3 */
+#define FUNC_TIMER0_TOGGLE4                 193	/* TIMER0 Toggle Output 4 */
+#define FUNC_TIMER1_TOGGLE1                 194	/* TIMER1 Toggle Output 1 */
+#define FUNC_TIMER1_TOGGLE2                 195	/* TIMER1 Toggle Output 2 */
+#define FUNC_TIMER1_TOGGLE3                 196	/* TIMER1 Toggle Output 3 */
+#define FUNC_TIMER1_TOGGLE4                 197	/* TIMER1 Toggle Output 4 */
+#define FUNC_TIMER2_TOGGLE1                 198	/* TIMER2 Toggle Output 1 */
+#define FUNC_TIMER2_TOGGLE2                 199	/* TIMER2 Toggle Output 2 */
+#define FUNC_TIMER2_TOGGLE3                 200	/* TIMER2 Toggle Output 3 */
+#define FUNC_TIMER2_TOGGLE4                 201	/* TIMER2 Toggle Output 4 */
+#define FUNC_CLK_SPI2                       202	/* Clock SPI2 */
+#define FUNC_CLK_I2C2                       203	/* Clock I2C2 */
+#define FUNC_INTERNAL0                      204	/* Internal function signal 0 */
+#define FUNC_INTERNAL1                      205	/* Internal function signal 1 */
+#define FUNC_INTERNAL2                      206	/* Internal function signal 2 */
+#define FUNC_INTERNAL3                      207	/* Internal function signal 3 */
+#define FUNC_INTERNAL4                      208	/* Internal function signal 4 */
+#define FUNC_INTERNAL5                      209	/* Internal function signal 5 */
+#define FUNC_INTERNAL6                      210	/* Internal function signal 6 */
+#define FUNC_INTERNAL7                      211	/* Internal function signal 7 */
+#define FUNC_INTERNAL8                      212	/* Internal function signal 8 */
+#define FUNC_INTERNAL9                      213	/* Internal function signal 9 */
+#define FUNC_INTERNAL10                     214	/* Internal function signal 10 */
+#define FUNC_INTERNAL11                     215	/* Internal function signal 11 */
+#define FUNC_INTERNAL12                     216	/* Internal function signal 12 */
+#define FUNC_INTERNAL13                     217	/* Internal function signal 13 */
+#define FUNC_INTERNAL14                     218	/* Internal function signal 14 */
+#define FUNC_INTERNAL15                     219	/* Internal function signal 15 */
+#define FUNC_INTERNAL16                     220	/* Internal function signal 16 */
+#define FUNC_INTERNAL17                     221	/* Internal function signal 17 */
+#define FUNC_CONSTANT                       222	/* Constant function */
+#define FUNC_INTERNAL18                     223	/* Internal function signal 18 */
+#define FUNC_DEBUG0                         224	/* Debug function 0 */
+#define FUNC_DEBUG1                         225	/* Debug function 1 */
+#define FUNC_DEBUG2                         226	/* Debug function 2 */
+#define FUNC_DEBUG3                         227	/* Debug function 3 */
+#define FUNC_DEBUG4                         228	/* Debug function 4 */
+#define FUNC_DEBUG5                         229	/* Debug function 5 */
+#define FUNC_DEBUG6                         230	/* Debug function 6 */
+#define FUNC_DEBUG7                         231	/* Debug function 7 */
+#define FUNC_DEBUG8                         232	/* Debug function 8 */
+#define FUNC_DEBUG9                         233	/* Debug function 9 */
+#define FUNC_DEBUG10                        234	/* Debug function 10 */
+#define FUNC_DEBUG11                        235	/* Debug function 11 */
+#define FUNC_DEBUG12                        236	/* Debug function 12 */
+#define FUNC_DEBUG13                        237	/* Debug function 13 */
+#define FUNC_DEBUG14                        238	/* Debug function 14 */
+#define FUNC_DEBUG15                        239	/* Debug function 15 */
+#define FUNC_DEBUG16                        240	/* Debug function 16 */
+#define FUNC_DEBUG17                        241	/* Debug function 17 */
+#define FUNC_DEBUG18                        242	/* Debug function 18 */
+#define FUNC_DEBUG19                        243	/* Debug function 19 */
+#define FUNC_DEBUG20                        244	/* Debug function 20 */
+#define FUNC_DEBUG21                        245	/* Debug function 21 */
+#define FUNC_DEBUG22                        246	/* Debug function 22 */
+#define FUNC_DEBUG23                        247	/* Debug function 23 */
+#define FUNC_DEBUG24                        248	/* Debug function 24 */
+#define FUNC_DEBUG25                        249	/* Debug function 25 */
+#define FUNC_DEBUG26                        250	/* Debug function 26 */
+#define FUNC_DEBUG27                        251	/* Debug function 27 */
+#define FUNC_DEBUG28                        252	/* Debug function 28 */
+#define FUNC_DEBUG29                        253	/* Debug function 29 */
+#define FUNC_DEBUG30                        254	/* Debug function 30 */
+#define FUNC_DEBUG31                        255	/* Debug function 31 */
+#define FUNC_MAX                            256	/* Function numbers */
+
+
+#define CLINT_BASE_ADDR         0x02000000UL
+#define PLIC_BASE_ADDR          0x0C000000UL
+
+/* Under TileLink */
+#define UARTHS_BASE_ADDR        0x38000000UL
+#define GPIOHS_BASE_ADDR        0x38001000UL
+
+/* Under AXI 64 bit */
+#define RAM_BASE_ADDR           0x80000000UL
+#define RAM_SIZE                (6 * 1024 * 1024U)
+#define AI_RAM_BASE_ADDR        (RAM_BASE_ADDR + RAM_SIZE)
+#define AI_RAM_SIZE             (2 * 1024 * 1024U)
+
+#define IO_BASE_ADDR            0x40000000UL
+#define IO_SIZE                 (6 * 1024 * 1024U)
+#define AI_IO_BASE_ADDR         (IO_BASE_ADDR + IO_SIZE)
+#define AI_IO_SIZE              (2 * 1024 * 1024U)
+#define AI_BASE_ADDR            (AI_IO_BASE_ADDR + AI_IO_SIZE)
+#define AI_SIZE                 (12 * 1024 * 1024U)
+
+#define FFT_BASE_ADDR           0x42000000UL
+#define FFT_SIZE                (4 * 1024 * 1024U)
+
+#define ROM_BASE_ADDR           0x88000000UL
+#define ROM_SIZE                (128 * 1024U)
+
+/* Under AHB 32 bit */
+#define DMAC_BASE_ADDR          0x50000000UL
+
+/* Under APB1 32 bit */
+#define GPIO_BASE_ADDR          0x50200000UL
+#define UART1_BASE_ADDR         0x50210000UL
+#define SPI_SLAVE_BASE_ADDR     0x50240000UL
+#define I2S0_BASE_ADDR          0x50250000UL
+#define I2S1_BASE_ADDR          0x50260000UL
+#define I2S2_BASE_ADDR          0x50270000UL
+#define I2C0_BASE_ADDR          0x50280000UL
+#define I2C1_BASE_ADDR          0x50290000UL
+#define I2C2_BASE_ADDR          0x502A0000UL
+#define FPIOA_BASE_ADDR         0x502B0000UL
+#define SHA256_BASE_ADDR        0x502C0000UL
+#define TIMER0_BASE_ADDR        0x502D0000UL
+#define TIMER1_BASE_ADDR        0x502E0000UL
+#define TIMER2_BASE_ADDR        0x502F0000UL
+
+/* Under APB2 32 bit */
+#define WDT0_BASE_ADDR          0x50400000UL
+#define WDT1_BASE_ADDR          0x50410000UL
+#define OTP_BASE_ADDR           0x50420000UL
+#define DVP_BASE_ADDR           0x50430000UL
+#define SYSCTL_BASE_ADDR        0x50440000UL
+#define AES_BASE_ADDR           0x50450000UL
+#define RTC_BASE_ADDR           0x50460000UL
+
+
+/* Under APB3 32 bit */
+#define SPI0_BASE_ADDR          0x52000000UL
+#define SPI1_BASE_ADDR          0x53000000UL
+#define SPI3_BASE_ADDR          0x54000000UL
+
+
+/*
+ *  CLINT (64bits registers)
+ */
+#define TADR_CLIC_BASE      (CLINT_BASE_ADDR)
+#define TOFF_CLINT_MSIP     0x0000			/* (RW) MSIP Registers 4bytes */
+  #define CLINT_MSOFTIP       0x000000001	/* Machine-mode software interrupt */
+#define TOFF_CLINT_MTIMECMP 0x4000			/* (RW) Timer compare Registers Machine-mode timer interrupts 8bytes */
+#define TOFF_CLINT_MTIME    0xBFF8			/* (R)  Timer Registers 8bytes */
+
+#define CLINT_MAX_CORES     (4095)
+
+
+/*
+ *  PLIC
+ */
+#define TADR_PLIC_BASE      (PLIC_BASE_ADDR)
+#define TOFF_PLIC_PRIORITY  0x00000000
+#define TOFF_PLIC_PENDING   0x00001000
+#define TOFF_PLIC_ENABLE    0x00002000
+#define NUM_PLIC_ENABLE     1024
+#define TOFF_PLIC_THRESHOLD 0x00200000
+#define NUM_PLIC_THRESHOLD  4096
+#define TOFF_PLIC_CLAIM     0x00200004
+
+
+/*
+ *  DMAC (64bits registers)
+ */
+#define TADR_DMAC_BASE      (DMAC_BASE_ADDR)
+#define TOFF_DMAC_ID                0x0000	/* (R)  DMAC ID Rgister */
+#define TOFF_DMAC_COMPVER           0x0008	/* (R)  DMAC COMPVER Register */
+#define TOFF_DMAC_CFG               0x0010	/* (RW) DMAC Configure Register */
+  #define DMAC_CFG_DMAC_EN              0x00000001L	/* enable dmac(dmac_en) */
+  #define DMAC_CFG_INT_EN               0x00000002L	/* glabally enable interrupt generation(int_en) */
+#define TOFF_DMAC_CHEN              0x0018	/* (RW) Channel Enable Register */
+  #define DMAC_CHEN_CH1_EN              0x0000000000000001	 /* enable channel 1(ch1_en) */
+  #define DMAC_CHEN_CH2_EN              0x0000000000000002	 /* enable channel 2(ch2_en) */
+  #define DMAC_CHEN_CH3_EN              0x0000000000000004	 /* enable channel 3(ch3_en) */
+  #define DMAC_CHEN_CH4_EN              0x0000000000000008	 /* enable channel 4(ch4_en) */
+  #define DMAC_CHEN_CH5_EN              0x0000000000000010	 /* enable channel 5(ch5_en) */
+  #define DMAC_CHEN_CH6_EN              0x0000000000000020	 /* enable channel 6(ch6_en) */
+  #define DMAC_CHEN_CH1_EN_WE           0x0000000000000100	 /* write enable bit channel 1(ch1_en_we) */
+  #define DMAC_CHEN_CH2_EN_WE           0x0000000000000200	 /* write enable bit channel 2(ch2_en_we) */
+  #define DMAC_CHEN_CH3_EN_WE           0x0000000000000400	 /* write enable bit channel 3(ch3_en_we) */
+  #define DMAC_CHEN_CH4_EN_WE           0x0000000000000800	 /* write enable bit channel 4(ch4_en_we) */
+  #define DMAC_CHEN_CH5_EN_WE           0x0000000000001000	 /* write enable bit channel 5(ch5_en_we) */
+  #define DMAC_CHEN_CH6_EN_WE           0x0000000000002000	 /* write enable bit channel 6(ch6_en_we) */
+  #define DMAC_CHEN_CH1_SUSP            0x0000000000010000	 /* susped reuest channel 1(ch1_susp) */
+  #define DMAC_CHEN_CH2_SUSP            0x0000000000020000	 /* susped reuest channel 2(ch2_susp) */
+  #define DMAC_CHEN_CH3_SUSP            0x0000000000040000	 /* susped reuest channel 3(ch3_susp) */
+  #define DMAC_CHEN_CH4_SUSP            0x0000000000080000	 /* susped reuest channel 4(ch4_susp) */
+  #define DMAC_CHEN_CH5_SUSP            0x0000000000100000	 /* susped reuest channel 5(ch5_susp) */
+  #define DMAC_CHEN_CH6_SUSP            0x0000000000200000	 /* susped reuest channel 6(ch6_susp) */
+  #define DMAC_CHEN_CH1_SUSP_WE         0x0000000001000000	 /* swrite enable to the channel 1 suspend(ch1_susp_we) */
+  #define DMAC_CHEN_CH2_SUSP_WE         0x0000000002000000	 /* swrite enable to the channel 2 suspend(ch2_susp_we) */
+  #define DMAC_CHEN_CH3_SUSP_WE         0x0000000004000000	 /* swrite enable to the channel 3 suspend(ch3_susp_we) */
+  #define DMAC_CHEN_CH4_SUSP_WE         0x0000000008000000	 /* swrite enable to the channel 4 suspend(ch4_susp_we) */
+  #define DMAC_CHEN_CH5_SUSP_WE         0x0000000010000000	 /* swrite enable to the channel 5 suspend(ch5_susp_we) */
+  #define DMAC_CHEN_CH6_SUSP_WE         0x0000000020000000	 /* swrite enable to the channel 6 suspend(ch6_susp_we) */
+  #define DMAC_CHEN_CH1_ABOUT           0x0000000100000000	 /* channel-1 abort requst bit(ch1_abort) */
+  #define DMAC_CHEN_CH2_ABOUT           0x0000000200000000	 /* channel-2 abort requst bit(ch2_abort) */
+  #define DMAC_CHEN_CH3_ABOUT           0x0000000400000000	 /* channel-3 abort requst bit(ch3_abort) */
+  #define DMAC_CHEN_CH4_ABOUT           0x0000000800000000	 /* channel-4 abort requst bit(ch4_abort) */
+  #define DMAC_CHEN_CH5_ABOUT           0x0000001000000000	 /* channel-5 abort requst bit(ch5_abort) */
+  #define DMAC_CHEN_CH6_ABOUT           0x0000002000000000	 /* channel-6 abort requst bit(ch6_abort) */
+  #define DMAC_CHEN_CH1_ABOUT_WE        0x0000010000000000	 /* write enable  channel-1 abort bit(ch1_abort_we) */
+  #define DMAC_CHEN_CH2_ABOUT_WE        0x0000020000000000	 /* write enable  channel-2 abort bit(ch2_abort_we) */
+  #define DMAC_CHEN_CH3_ABOUT_WE        0x0000040000000000	 /* write enable  channel-3 abort bit(ch3_abort_we) */
+  #define DMAC_CHEN_CH4_ABOUT_WE        0x0000080000000000	 /* write enable  channel-4 abort bit(ch4_abort_we) */
+  #define DMAC_CHEN_CH5_ABOUT_WE        0x0000100000000000	 /* write enable  channel-5 abort bit(ch5_abort_we) */
+  #define DMAC_CHEN_CH6_ABOUT_WE        0x0000200000000000	 /* write enable  channel-6 abort bit(ch6_abort_we) */
+#define TOFF_DMAC_INTSTATUS         0x0030	/* (RW) DMAC Interrupt Status Register */
+  #define DMAC_INTSTATUS_CH1            0x00000001L	 /* channel 1 interrupt bit(ch1_intstat) */
+  #define DMAC_INTSTATUS_CH2            0x00000002L	 /* channel 2 interrupt bit(ch2_intstat) */
+  #define DMAC_INTSTATUS_CH3            0x00000004L	 /* channel 3 interrupt bit(ch3_intstat) */
+  #define DMAC_INTSTATUS_CH4            0x00000008L	 /* channel 4 interrupt bit(ch4_intstat) */
+  #define DMAC_INTSTATUS_CH5            0x00000010L	 /* channel 5 interrupt bit(ch5_intstat) */
+  #define DMAC_INTSTATUS_CH6            0x00000020L	 /* channel 6 interrupt bit(ch6_intstat) */
+#define TOFF_DMAC_COM_INTCLEAR      0x0038	/* (RW) DMAC Common register Interrupt Status Register */
+  #define DMAC_COM_INTCLEAR_SLVIF_DEC_ERR           0x00000001L	/* Slave Interface Common Register Decode Error Interrupt Status clear(clear_slvif_dec_err_intstat) */
+  #define DMAC_COM_INTCLEAR_SLVIF_WR2RO_ERR         0x00000002L	/* Slave Interface Common Register Write to Read only Error Interrupt Status clear(clear_slvif_wr2ro_err_intstat) */
+  #define DMAC_COM_INTCLEAR_SLVIF_RD2WO_ERR         0x00000004L	/* Slave Interface Common Register Read to Write only Error Interrupt Status clear(clear_slvif_rd2wo_err_intstat) */
+  #define DMAC_COM_INTCLEAR_SLVIF_WRONHOLD_ERR      0x00000008L	/* Slave Interface Common Register Write On Hold Error Interrupt Status clear(clear_slvif_wronhold_err_intstat) */
+  #define DMAC_COM_INTCLEAR_SLVIF_UNDEFREG_ERR      0x00000100L	/* Slave Interface Undefined register Decode Error Interrupt Status clear(clear_slvif_undefinedreg_dec_err_intstat) */
+#define TOFF_DMAC_COM_INTSTATUS_EN  0x0040	/* (RW) DMAC Common Interrupt Enable Register */
+  #define DMAC_COM_INTSTATUS_EN_SLVIF_DEC_ERR       0x00000001L	/* Slave Interface Common Register Decode Error Interrupt Status Enable(enable_slvif_dec_err_intstat) */
+  #define DMAC_COM_INTSTATUS_EN_SLVIF_WR2RO_ERR     0x00000002L	/* Slave Interface Common Register Write to Read only Error Interrupt Status Enable(enable_slvif_wr2ro_err_intstat) */
+  #define DMAC_COM_INTSTATUS_EN_SLVIF_RD2WO_ERR     0x00000004L	/* Slave Interface Common Register Read to Write only Error Interrupt Status Enable(enable_slvif_rd2wo_err_intstat) */
+  #define DMAC_COM_INTSTATUS_EN_SLVIF_WRONHOLD_ERR  0x00000008L	/* Slave Interface Common Register Write On Hold Error Interrupt Status Enable(enable_slvif_wronhold_err_intstat) */
+  #define DMAC_COM_INTSTATUS_EN_SLVIF_UNDEFREG_ERR  0x00000100L	/* Slave Interface Undefined register Decode Error Interrupt Status Enable(enable_slvif_undefinedreg_dec_err_intstat) */
+#define TOFF_DMAC_COM_INTSIGNAL_EN  0x0048	/* (RW) DMAC Common Interrupt Signal Enable Register */
+  #define DMAC_COM_INTSIGNAL_EN_SLVIF_DEC_ERR       0x00000001L	/* Slave Interface Common Register Decode Error Interrupt Signal Enable(enable_slvif_dec_err_intsignal) */
+  #define DMAC_COM_INTSIGNAL_EN_SLVIF_WR2RO_ERR     0x00000002L	/* Slave Interface Common Register Write to Read only Error Interrupt Signal Enable(enable_slvif_wr2ro_err_intsignal) */
+  #define DMAC_COM_INTSIGNAL_EN_SLVIF_RD2WO_ERR     0x00000004L	/* Slave Interface Common Register Read to Write only Error Interrupt Signal Enable(enable_slvif_rd2wo_err_intsignal) */
+  #define DMAC_COM_INTSIGNAL_EN_SLVIF_WRONHOLD_ERR  0x00000008L	/* Slave Interface Common Register Write On Hold Error Interrupt Signal Enable(enable_slvif_wronhold_err_intsignal) */
+  #define DMAC_COM_INTSIGNAL_EN_SLVIF_UNDEFREG_ERR  0x00000100L	/* Slave Interface Undefined register Decode Error Interrupt Signal Enable(enable_slvif_undefinedreg_dec_err_intsignal) */
+#define TOFF_DMAC_COM_INTSTATUS     0x0050	/* (RW) DMAC Common Interrupt Status */
+  #define DMAC_COM_INTSTATUS_SLVIF_DEC_ERR          0x00000001L	/* Slave Interface Common Register Decode(slvif_dec_err_intstat) */
+  #define DMAC_COM_INTSTATUS_SLVIF_WR2RO_ERR        0x00000002L	/* Slave Interface Common Register Write to Read Only(slvif_wr2ro_err_intstat */
+  #define DMAC_COM_INTSTATUS_SLVIF_RD2WO_ERR        0x00000004L	/* Slave Interface Common Register Read to Write(slvif_rd2wo_err_intstat) */
+  #define DMAC_COM_INTSTATUS_SLVIF_WRONHOLD_ERR     0x00000008L	/*Slave Interface Common Register Write On(slvif_wronhold_err_intstat) */
+  #define DMAC_COM_INTSTATUS_SLVIF_UNDEFREG_ERR     0x00000100L	/*Slave Interface Undefined register Decode Error(slvif_undefinedreg_dec_err_intstat) */
+#define TOFF_DMAC_RESET             0x0058	/* (RW) DMAC Reset register */
+  #define DMAC_RESET_RST                0x00000001L	/* DMAC reset request bit */
+#define TOFF_DMAC_CHANNEL           0x0100	/* (RW) DMAC channel registers */
+
+/*
+ *  DMAC CHANNEL WINDOW
+ */
+#define TOFF_DMAC_CH_SAR            0x0000	/* (RW) SAR Address Register */
+#define TOFF_DMAC_CH_DAR            0x0008	/* (RW) DAR Address Register */
+#define TOFF_DMAC_CH_BLOCK_TS       0x0010	/* (RW) Block Transfer Size Register */
+  #define DMACCH_BLOCK_TS               0x03FFFFFFL	/* block transfer size(block_ts) */
+#define TOFF_DMAC_CH_CTL            0x0018	/* (RW) Control Register */
+  #define DMACCH_CTL_SMS                0x0000000000000001	/* source master select(sms) */
+  #define DMACCH_CTL_DMS                0x0000000000000004	/* destination master select(dms) */
+  #define DMACCH_CTL_SINC               0x0000000000000010	/* source address increment(sinc) */
+  #define DMACCH_CTL_DINC               0x0000000000000040	/* destination address incremnet(dinc) */
+  #define DMACCH_CTL_SRC_TR_WIDTH       0x0000000000000700	/* source transfer width(src_tr_width) */
+  /* * 0x0 for source transfer width is 8 bits
+     * 0x1 for source transfer width is 16 bits
+     * 0x2 for source transfer width is 32 bits
+     * 0x3 for source transfer width is 64 bits
+     * 0x4 for source transfer width is 128 bits
+     * 0x5  for source transfer width is 256 bits
+     * 0x6 for source transfer width is 512 bits
+     */
+  #define DMACCH_CTL_DST_TR_WIDTH       0x0000000000003800	/* detination transfer width(dst_tr_width) */
+  /* * 0x0 for detination transfer width is 8 bits
+     * 0x1 for detination transfer width is 16 bits
+     * 0x2 for detination transfer width is 32 bits
+     * 0x3 for detination transfer width is 64 bits
+     * 0x4 for detination transfer width is 128 bits
+     * 0x5  for detination transfer width is 256 bits
+     * 0x6 for detination transfer width is 512 bits
+     */
+  #define DMACCH_CTL_SRC_MSIZE          0x000000000003C000	/* source burst transaction length(src_msize) */
+  /* * 0x0 for 1 data item read from rource in the burst transaction
+     * 0x1 for 4 data item read from rource in the burst transaction
+     * 0x2 for 8 data item read from rource in the burst transaction
+     * 0x3 for 16 data item read from rource in the burst transaction
+     * 0x4 for 32 data item read from rource in the burst transaction
+     * 0x5 for 64 data item read from rource in the burst transaction
+     * 0x6 for 128 data item read from rource in the burst transaction
+     * 0x7 for 256 data item read from rource in the burst transaction
+     * 0x8 for 512 data item read from rource in the burst transaction
+     * 0x9 for 1024 data item read from rource in the burst transaction
+     */
+  #define DMACCH_CTL_DST_MSIZE          0x00000000003C0000	/* destination burst transaction length(dst_msize) */
+  /* * 0x0 for 1 data item read from rource in the burst transaction
+     * 0x1 for 4 data item read from rource in the burst transaction
+     * 0x2 for 8 data item read from rource in the burst transaction
+     * 0x3 for 16 data item read from rource in the burst transaction
+     * 0x4 for 32 data item read from rource in the burst transaction
+     * 0x5 for 64 data item read from rource in the burst transaction
+     * 0x6 for 128 data item read from rource in the burst transaction
+     * 0x7 for 256 data item read from rource in the burst transaction
+     * 0x8 for 512 data item read from rource in the burst transaction
+     * 0x9 for 1024 data item read from rource in the burst transaction
+     */
+  #define DMACCH_CTL_NONP_LASTWRITE_EN  0x0000000040000000	/* Non Posted Last Write Enable(nonposted_lastwrite_en) */
+  #define DMACCH_CTL_ARLEN_EN           0x0000004000000000	/* source burst length enable(arlen_en) */
+  #define DMACCH_CTL_ARLEN              0x00007F1000000000	/* source burst length(arlen) */
+  #define DMACCH_CTL_AWLEN_EN           0x0000800000000000	/* destination burst length enable(awlen_en) */
+  #define DMACCH_CTL_AWLEN              0x00FF000000000000	/* destination burst length(awlen) */
+  #define DMACCH_CTL_SRC_STAT_EN        0x0100000000000000	/* source status enable(src_stat_en) */
+  #define DMACCH_CTL_DST_STAT_EN        0x0200000000000000	/* destination status enable(dst_stat_en) */
+  #define DMACCH_CTL_IOC_BLKTFR         0x0400000000000000	/* interrupt completion of block transfer(ioc_blktfr) */
+  #define DMACCH_CTL_SHREG_OR_LLI_LAST  0x4000000000000000	/* last shadow linked list item(shadowreg_or_lli_last) */
+  #define DMACCH_CTL_SHREG_OR_LLI_VALID 0x8000000000000000	/* last shadow linked list item valid(shadowreg_or_lli_valid) */
+#define TOFF_DMAC_CH_CFG            0x0020	/* (RW) Configure Register */
+  #define DMACCH_CFG_SRC_MULTBLKTYPE    0x0000000000000003	/* source multi block transfer type(src_multblk_type) */
+  /* * 0x0 for continuous multiblock type
+     * 0x1 for reload multiblock type
+     * 0x2 for shadow register based multiblock type
+     * 0x3 for linked lisr bases multiblock type
+     */
+  #define DMACCH_CFG_DST_MULTBLKTYPE    0x000000000000000C	/* destination multi block transfer type(dst_multblk_type) */
+  /* * 0x0 for continuous multiblock type
+     * 0x1 for reload multiblock type
+     * 0x2 for shadow register based multiblock type
+     * 0x3 for linked lisr bases multiblock type
+     */
+  #define DMACCH_CFG_TT_FC              0x0000000700000000	/* transfer type and flow control(tt_fc) */
+  /* * 0x0  transfer memory to memory and flow controler is dmac
+     * 0x1  transfer memory to peripheral and flow controler is dmac
+     * 0x2  transfer peripheral to memory and flow controler is dmac
+     * 0x3  transfer peripheral to peripheral and flow controler is dmac
+     * 0x4  transfer peripheral to memory and flow controler is
+     * source peripheral
+     * 0x5  transfer peripheral to peripheral and flow controler
+     * is source peripheral
+     * 0x6  transfer memory to peripheral and flow controler is
+     * destination peripheral
+     * 0x7  transfer peripheral to peripheral and flow controler
+     * is destination peripheral
+     */
+  #define DMACCH_CFG_HS_SEL_SRC         0x0000000800000000	/* source software or hardware handshaking select(hs_sel_src) */
+  #define DMACCH_CFG_HS_SEL_DST         0x0000001000000000	/* destination software or hardware handshaking select(hs_sel_dst) */
+  #define DMACCH_CFG_SRC_HWHS_POL       0x0000002000000000	/* sorce hardware handshaking interface polarity(src_hwhs_pol) */
+  #define DMACCH_CFG_DST_HWHS_POL       0x0000004000000000	/* destination hardware handshaking interface polarity(dst_hwhs_pol) */
+  #define DMACCH_CFG_SRC_PER            0x0000078000000000	/* assign a hardware handshaking interfaceto source of channel x(src_per) */
+  #define DMACCH_CFG_DST_PER            0x0000F00000000000	/* assign a hardware handshaking interfaceto destination of channel x(dst_per) */
+  #define DMACCH_CFG_CH_PRIOR           0x000E000000000000	/* channel priority,7 is highest, 0 is lowest(ch_prior) */
+  #define DMACCH_CFG_LOCK_CH            0x0010000000000000	/* channel lock bit(lock_ch) */
+  #define DMACCH_CFG_LOCK_CH_L          0x0060000000000000	/* channel lock level(lock_ch_l) */
+  #define DMACCH_CFG_SRC_OSR_LMT        0x0780000000000000	/* source outstanding request limit(src_osr_lmt) */
+  #define DMACCH_CFG_DST_OSR_LMT        0x7800000000000000	/* destination outstanding request limit(dst_osr_lmt) */
+#define TOFF_DMAC_CH_LLP            0x0028	/* (RW) Linked List Pointer register */
+  #define DMACCH_LLP_LMS                0x0000000000000001	/* LLI master select(lms) */
+  #define DMACCH_LLP_LOC                0xFFFFFFFFFFFFFFC0	/* starting address memeory of LLI block(loc) */
+#define TOFF_DMAC_CH_STATUS         0x0030	/* (RW) Channelx Status Register */
+  #define DMACCH_CMPLTD_BLK_SIZE        0x03FFFFFFL	/* completed block transfer size(cmpltd_blk_size) */
+#define TOFF_DMAC_CH_SWHSSRC        0x0038	/* (RW) Channelx Software handshake Source Register */
+  #define DMACCH_SWHS_REQ_SRC           0x00000001L	/* software handshake request for channel source(swhs_req_src) */
+  #define DMACCH_SWHS_REQ_SRC_WE        0x00000002L	/* write enable bit for software handshake request(swhs_req_src_we) */
+  #define DMACCH_SWHS_SGLREQ_SRC        0x00000004L	/* software handshake single request for channel source(swhs_sglreq_src) */
+  #define DMACCH_SWHS_SGLREQ_SRC_WE     0x00000008L	/* write enable bit for software handshake single request for channle source(swhs_sglreq_src_we) */
+  #define DMACCH_SWHS_LST_SRC           0x00000010L	/* software handshake last request for channel source(swhs_lst_src) */
+  #define DMACCH_SWHS_LST_SRC_WE        0x00000020L	/* write enable bit for software handshake last request(swhs_lst_src_we) */
+#define TOFF_DMAC_CH_SWHSDST        0x0040	/* (RW) Channelx Software handshake Destination Register */
+  #define DMACCH_SWHS_REQ_DST           0x00000001L	/* software handshake request for channel destination(swhs_req_dst) */
+  #define DMACCH_SWHS_REQ_DST_WE        0x00000002L	/* write enable bit for software handshake request(swhs_req_dst_we) */
+  #define DMACCH_SWHS_SGLREQ_DST        0x00000004L	/* software handshake single request for channel destination(swhs_sglreq_dst) */
+  #define DMACCH_SWHS_SGLREQ_DST_WE     0x00000008L	/* write enable bit for software handshake single request for channle destination(swhs_sglreq_dst_we) */
+  #define DMACCH_SWHS_LST_DST           0x00000010L	/* software handshake last request for channel destination(swhs_lst_dst) */
+  #define DMACCH_SWHS_LST_DST_WE        0x00000020L	/* write enable bit for software handshake last request(swhs_lst_dst_we) */
+#define TOFF_DMAC_CH_BLK_TFR        0x0048	/* (RW) Channelx Block Transfer Resume Request Register */
+  #define DMACCH_BLK_TFR_RESUMEREQ      0x00000001L	/* block transfer resume request bit */
+#define TOFF_DMAC_CH_AXI_ID         0x0050	/* (R)  Channelx AXI ID Register */
+#define TOFF_DMAC_CH_AXI_QOS        0x0058	/* (RW) Channelx AXI QOS Register */
+#define TOFF_DMAC_CH_INTSTATUS_EN   0x0080	/* (RW) Interrupt Status Enable Register */
+  #define DMACCH_ENABLE_BLOCK_TFR_DONE_INTSTAT 0x00000001L	/* block transfer done interrupt status enable(enable_block_tfr_done_intstatus) */
+  #define DMACCH_ENABLE_DMA_TFR_DONE_INTSTAT   0x00000002L	/* DMA transfer done interrupt status enable(enable_dma_tfr_done_intstat) */
+  #define DMACCH_ENABLE_SRC_TRANSCOMP_INTSTAT  0x00000008L	/* source transaction complete status enable(enable_src_transcomp_intstat) */
+  #define DMACCH_ENABLE_DST_TRANSCOMP_INSTAT   0x00000010L	/* destination transaction complete(enable_dst_transcomp_intstat) */
+  #define DMACCH_ENABLE_SRC_DEC_ERR_INSTAT     0x00000020L	/* Source Decode Error Status Enable(enable_src_dec_err_intstat) */
+  #define DMACCH_ENABLE_DST_DEC_ERR_INSTAT     0x00000040L	/* Destination Decode Error Status Enable(enable_dst_dec_err_intstat) */
+  #define DMACCH_ENABLE_SRC_SLV_ERR_INSTAT     0x00000080L	/* Source Slave Error Status Enable(enable_src_slv_err_intstat) */
+  #define DMACCH_ENABLE_DST_SLV_ERR_INSTAT     0x00000100L	/* Destination Slave Error Status Enable(enable_dst_slv_err_intstat) */
+  #define DMACCH_ENABLE_LLI_RD_DEC_ERR_INSTAT  0x00000200L	/* LLI Read Decode Error Status Enable(enable_lli_rd_dec_err_intstat) */
+  #define DMACCH_ENABLE_LLI_WR_DEC_ERR_INSTAT  0x00000400L	/* LLI WRITE Decode Error Status Enable(enable_lli_wr_dec_err_intstat) */
+  #define DMACCH_ENABLE_LLI_RD_SLV_ERR_INSTAT  0x00000800L	/* LLI Read Slave Error Status Enable(enable_lli_rd_slv_err_intstat) */
+  #define DMACCH_ENABLE_LLI_WR_SLV_ERR_INSTAT  0x00001000L	/* LLI WRITE Slave Error Status Enable(enable_lli_wr_slv_err_intstat) */
+#define TOFF_DMAC_CH_INTSTATUS      0x0088	/* (RW) Channelx Interrupt Status Register */
+#define TOFF_DMAC_CH_INTSIGNAL_EN   0x0090	/* (RW) Interrupt  Siganl Enable Register */
+#define TOFF_DMAC_CH_INTCLEAR       0x0098	/* (W)  Interrupt Clear Register */
+  #define DMACCH_BLK_TFR_DONE_INSTAT    0x00000001L	/* block transfer done interrupt clear bit(blk_tfr_done_intstat) */
+  #define DMACCH_DMA_TFR_DONE_INSTAT    0x00000002L	/* DMA transfer done interrupt clear bit(dma_tfr_done_intstat) */
+
+#define DMAC_CHANNEL_WINDOW_SIZE    0x0100
+#define NUM_DMAC_CHANNEL            6
+
+/*
+ *  GPIOHS
+ */
+#define TADR_GPIOHS_BASE    (GPIOHS_BASE_ADDR)
+#define TOFF_GPIOHS_INPUT_VAL   0x0000	/* (RW) Input Values */
+#define TOFF_GPIOHS_INPUT_EN    0x0004	/* (RW) Input enable */
+#define TOFF_GPIOHS_OUTPUT_EN   0x0008	/* (RW) Output enable */
+#define TOFF_GPIOHS_OUTPUT_VAL  0x000C	/* (RW) Onput Values */
+#define TOFF_GPIOHS_PULLUP_EN   0x0010	/* (RW) Internal Pull-Ups enable */
+#define TOFF_GPIOHS_DRIVE       0x0014	/* (RW) Drive Strength */
+#define TOFF_GPIOHS_RISE_IE     0x0018	/* (RW) Rise interrupt enable */
+#define TOFF_GPIOHS_RISE_IP     0x001C	/* (RW) Rise interrupt pending */
+#define TOFF_GPIOHS_FALL_IE     0x0020	/* (RW) Fall interrupt enable */
+#define TOFF_GPIOHS_FALL_IP     0x0024	/* (RW) Fall interrupt pending */
+#define TOFF_GPIOHS_HIGH_IE     0x0028	/* (RW) High interrupt enable */
+#define TOFF_GPIOHS_HIGH_IP     0x002C	/* (RW) High interrupt pending */
+#define TOFF_GPIOHS_LOW_IE      0x0030	/* (RW) Low interrupt enable */
+#define TOFF_GPIOHS_LOW_IP      0x0034	/* (RW) Low interrupt pending */
+#define TOFF_GPIOHS_IOF_EN      0x0038	/* (RW) HW I/O Function enable */
+#define TOFF_GPIOHS_IOF_SEL     0x003C	/* (RW) HW I/O Function select */
+#define TOFF_GPIOHS_OUTPOT_XOR  0x0040	/* (RW) Output XOR (invert) */
+
+#define GPIOHS_MAX_PINNO        32
+
+
+/*
+ *  GPIO
+ */
+#define TADR_GPIO_BASE      (GPIO_BASE_ADDR)
+#define TOFF_GPIO_DATA_OUTOUT     0x0000	/* (RW) Data (output) registers */
+#define TOFF_GPIO_DIRECTION       0x0004	/* (RW) Data direction registers */
+#define TOFF_GPIO_SOURCE          0x0008	/* (RW) Data source registers */
+#define TOFF_GPIO_INT_ENABLE      0x0030	/* (RW) Interrupt enable/disable registers */
+#define TOFF_GPIO_INT_MASK        0x0034	/* (RW) Interrupt mask registers */
+#define TOFF_GPIO_INT_LEVEL       0x0038	/* (RW) Interrupt level registers */
+#define TOFF_GPIO_INT_POLARITY    0x003C	/* (RW) Interrupt polarity registers */
+#define TOFF_GPIO_INT_STATUS      0x0040	/* (RW) Interrupt status registers */
+#define TOFF_GPIO_INT_STATUS_RAW  0x0044	/* (RW) Raw interrupt status registers */
+#define TOFF_GPIO_INT_DEBOUNCE    0x0048	/* (RW) Interrupt debounce registers */
+#define TOFF_GPIO_INT_CLEAR       0x004C	/* (RW) Registers for clearing interrupts */
+#define TOFF_GPIO_DATA_INPUT      0x0050	/* (RW) External port (data input) registers */
+#define TOFF_GPIO_SYNC_LEVEL      0x0060	/* (RW) Sync level registers */
+#define TOFF_GPIO_ID_CODE         0x0064	/* (R)  ID code */
+#define TOFF_GPIO_INT_BOTHEDGE    0x0068	/* (RW) Interrupt both edge type */
+
+#define GPIO_MAX_PINNO            8
+
+
+/*
+ *  UART
+ */
+#define TADR_UART1_BASE     (UART1_BASE_ADDR)
+#define TADR_UART2_BASE     (UART1_BASE_ADDR + 0x10000)
+#define TADR_UART3_BASE     (UART1_BASE_ADDR + 0x20000)
+#define TOFF_UART_RBR       0x0000
+#define TOFF_UART_DLL       0x0000
+#define TOFF_UART_THR       0x0000
+#define TOFF_UART_DLH       0x0004
+#define TOFF_UART_IER       0x0004
+  #define UART_IER_RIE        0x000000001
+  #define UART_IER_TIE        0x000000002
+  #define UART_IER_THRE       0x000000080
+#define TOFF_UART_FCR       0x0008
+#define TOFF_UART_IIR       0x0008
+  #define UART_IIR_SEND       0x000000002
+  #define UART_IIR_RECEIVE    0x000000004
+  #define UART_IIR_CTIMEOUT   0x00000000C
+#define TOFF_UART_LCR       0x000C
+  #define UART_LCR_DLN        0x000000003
+  #define UART_LCR_STB        0x000000004
+  #define UART_LCR_PARITY     0x000000008
+  #define UART_LCR_PEVEN      0x000000010
+  #define UART_LCR_DMD        0x000000080
+#define TOFF_UART_MCR       0x0010
+#define TOFF_UART_LSR       0x0014
+  #define UART_LSR_RFL        0x000000001
+  #define UART_LSR_TFL        0x000000020
+#define TOFF_UART_MSR       0x0018
+#define TOFF_UART_SCR       0x001C
+#define TOFF_UART_LPDLL     0x0020
+#define TOFF_UART_LPDLH     0x0024
+
+#define TOFF_UART_SRBR      0x0030
+#define TOFF_UART_STHR      0x0030
+
+#define TOFF_UART_FAR       0x0070
+#define TOFF_UART_TFR       0x0074
+#define TOFF_UART_RFW       0x0078
+#define TOFF_UART_USR       0x007C
+#define TOFF_UART_TFL       0x0080
+#define TOFF_UART_RFL       0x0084
+#define TOFF_UART_SRR       0x0088
+#define TOFF_UART_SRTS      0x008C
+#define TOFF_UART_SBCR      0x0090
+#define TOFF_UART_SDMAM     0x0094
+#define TOFF_UART_SFE       0x0098
+#define TOFF_UART_SRT       0x009C
+#define TOFF_UART_STET      0x00A0
+#define TOFF_UART_HTX       0x00A4
+#define TOFF_UART_DMASA     0x00A8
+#define TOFF_UART_TCR       0x00AC
+#define TOFF_UART_DE_EN     0x00B0
+#define TOFF_UART_RE_EN     0x00B4
+#define TOFF_UART_DET       0x00B8
+#define TOFF_UART_TAT       0x00BC
+#define TOFF_UART_DLF       0x00C0
+#define TOFF_UART_RAR       0x00C4
+#define TOFF_UART_TAR       0x00C8
+#define TOFF_UART_LCR_EXT   0x00CC
+#define TOFF_UART_CPR       0x00F4
+#define TOFF_UART_UCV       0x00F8
+#define TOFF_UART_CTR       0x00FC
+
+
+/*
+ *  I2S
+ */
+#define TADR_I2S0_BASE      (I2S0_BASE_ADDR)
+#define TADR_I2S1_BASE      (I2S0_BASE_ADDR+0x10000)
+#define TADR_I2S2_BASE      (I2S0_BASE_ADDR+0x20000)
+#define TOFF_I2S_IER            0x0000		/* (RW) I2S Enable Register */
+#define TOFF_I2S_IRER           0x0004		/* (RW) I2S Receiver Block Enable Register */
+#define TOFF_I2S_ITER           0x0008		/* (RW) I2S Transmitter Block Enable Register */
+#define TOFF_I2S_CER            0x000C		/* (RW) Clock Enable Register */
+  #define I2S_CER_CLKEN             0x00000001	/* clock generation enable/disable */
+#define TOFF_I2S_CCR            0x0010		/* (RW) Clock Configuration Register */
+  #define I2S_CCR_CLK_GATE          0x00000007	/* program  the gating of sclk */
+  /* * 0x0 for clock gating is diable,
+     * 0x1 for gating after 12 sclk cycles
+     * 0x2 for gating after 16 sclk cycles
+     * 0x3 for gating after 20 sclk cycles
+     * 0x4 for gating after 24 sclk cycles
+     */
+  #define I2S_CCR_CLK_WORD_SIZE     0x00000018	/* the number of sclk cycles for which the word select line stayd in the left aligned or right aligned mode. */
+  #define I2S_CCR_ALIGN_MODE        0x000000E0	/* alignment mode setting. */
+  /* * 0x1 for standard i2s format
+     * 0x2 for right aligned format
+     * 0x4 for left aligned format
+     */
+  #define I2S_CCR_DMA_TX_EN         0x00000100	/* DMA transmit enable control */
+  #define I2S_CCR_DMA_RX_EN         0x00000200	/* DMA receive enable control */
+  #define I2S_CCR_DMA_DIVIED_16     0x00000400	/* split 32bit data to two 16 bit data and filled in left and right channel. Used with dma_tx_en or dma_rx_en */
+  #define I2S_CCR_SIGN_EXPAND_EN    0x00000800
+#define TOFF_I2S_RXFFR          0x0014		/* (RW) Receiver Block FIFO Reset Register */
+#define TOFF_I2S_TXFFR          0x0018		/* (RW) Transmitter Block FIFO Reset Register */
+#define TOFF_I2S_CHANNEL        0x0020		/* (RW) channel 0x40 * 4 */
+#define TOFF_I2S_RXDMA          0x01C0		/* (RW) Receiver Block DMA Register */
+#define TOFF_I2S_RRXDMA         0x01C4		/* (RW) Reset Receiver Block DMA Register */
+#define TOFF_I2S_TXDMA          0x01C8		/* (RW) Transmitter Block DMA Register */
+#define TOFF_I2S_RTXDMA         0x01CC		/* (RW) Reset Transmitter Block DMA Register */
+#define TOFF_I2S_COMP_PARAM_2   0x01F0		/* (RW) Component Parameter Register 2 */
+#define TOFF_I2S_COMP_PARAM_1   0x01F4		/* (RW) Component Parameter Register 1 */
+#define TOFF_I2S_COMP_VERSION   0x01F8		/* (RW) I2S Component Version Register */
+#define TOFF_I2S_COMP_TYPE      0x01FC		/* (RW) I2S Component Type Register */
+
+/*
+ *  I2S CHANNEL WINDOW
+ */
+#define TOFF_I2SC_LEFT_RXTX     0x0000		/* (RW) Left  Receive or Left Transmit Register */
+#define TOFF_I2SC_RIGHT_RXTX    0x0004		/* (RW) Right Receive or Right Transmit Register */
+#define TOFF_I2SC_RER           0x0008		/* (RW) Receive Enable Register */
+  #define I2SC_RER_RXCHENX          0x00000001	/* receive channel enable/disable */
+#define TOFF_I2SC_TER           0x000C		/* (RW) Transmit Enable Register */
+  #define I2SC_TER_TXCHENX          0x00000001	/* transmit channel enable/disable */
+#define TOFF_I2SC_RCR           0x0010		/* (RW) Receive Configuration Register */
+  #define I2SC_RCR_WLEN             0x00000007	/* program desired data resolution of receiver */
+#define TOFF_I2SC_TCR           0x0014		/* (RW) Transmit Configuration Register */
+  #define I2SC_TCR_WLEN             0x00000007	/* program desired data resolution of transmitter */
+  /* * 0x0 for ignore the word length
+     * 0x1 for 12-bit data resolution of the receiver/transmitter,
+     * 0x2 for 16-bit data resolution of the receiver/transmitter,
+     * 0x3 for 20-bit data resolution of the receiver/transmitter,
+     * 0x4 for 24-bit data resolution of the receiver/transmitter,
+     * 0x5 for 32-bit data resolution of the receiver/transmitter
+     */
+#define TOFF_I2SC_ISR           0x0018		/* (RW) Interrupt Status Register */
+  #define I2SC_ISR_RXDA             0x00000001	/* status of receiver data avaliable interrupt */
+  #define I2SC_ISR_RXFO             0x00000002	/* status of data overrun interrupt for rx channel */
+  #define I2SC_ISR_TXFE             0x00000010	/* status of transmit empty triger interrupt */
+  #define I2SC_ISR_TXFO             0x00000020	/* status of data overrun interrupt for the TX channel */
+#define TOFF_I2SC_IMR           0x001C		/* (RW) Interrupt Mask Register */
+  #define I2SC_IMR_RXDAM            0x00000001	/* mask RX FIFO data available interrupt */
+  #define I2SC_IMR_RXFOM            0x00000002	/* mask RX FIFO overrun interrupt */
+  #define I2SC_IMR_TXFEM            0x00000010	/* mask TX FIFO empty interrupt */
+  #define I2SC_IMR_TXFOM            0x00000020	/* mask TX FIFO overrun interrupt */
+#define TOFF_I2SC_ROR           0x0020		/* (RW) Receive Overrun Register */
+  #define I2CS_ROR_RXCHO            0x00000001	/* read this bit to clear RX FIFO data overrun interrupt */
+#define TOFF_I2SC_TOR           0x0024		/* (RW) Transmit Overrun Register */
+  #define I2CS_TOR_TXCHO            0x00000001	/* read this bit to clear TX FIFO data overrun interrupt */
+#define TOFF_I2SC_RFCR          0x0028		/* (RW) Receive FIFO Configuration Register */
+  #define I2SC_RFCR_RXCHDT          0x0000000F	/* program the trigger level in the RX FIFO at which the receiver data available interrupt generate */
+  /* * 0x0 for interrupt trigger when FIFO level is 1,
+     * 0x2 for interrupt trigger when FIFO level is 2,
+     * 0x3 for interrupt trigger when FIFO level is 4,
+     * 0x4 for interrupt trigger when FIFO level is 5,
+     * 0x5 for interrupt trigger when FIFO level is 6,
+     * 0x6 for interrupt trigger when FIFO level is 7,
+     * 0x7 for interrupt trigger when FIFO level is 8,
+     * 0x8 for interrupt trigger when FIFO level is 9,
+     * 0x9 for interrupt trigger when FIFO level is 10,
+     * 0xa for interrupt trigger when FIFO level is 11,
+     * 0xb for interrupt trigger when FIFO level is 12,
+     * 0xc for interrupt trigger when FIFO level is 13,
+     * 0xd for interrupt trigger when FIFO level is 14,
+     * 0xe for interrupt trigger when FIFO level is 15,
+     * 0xf for interrupt trigger when FIFO level is 16
+     */
+#define TOFF_I2SC_TFCR          0x002C		/* (RW) Transmit FIFO Configuration Register */
+  #define I2CS_TFCR_TXCHET          0x0000000F	/* program the trigger level in the TX FIFO at which the receiver data available interrupt generate */
+  /* * 0x0 for interrupt trigger when FIFO level is 1,
+     * 0x2 for interrupt trigger when FIFO level is 2,
+     * 0x3 for interrupt trigger when FIFO level is 4,
+     * 0x4 for interrupt trigger when FIFO level is 5,
+     * 0x5 for interrupt trigger when FIFO level is 6,
+     * 0x6 for interrupt trigger when FIFO level is 7,
+     * 0x7 for interrupt trigger when FIFO level is 8,
+     * 0x8 for interrupt trigger when FIFO level is 9,
+     * 0x9 for interrupt trigger when FIFO level is 10,
+     * 0xa for interrupt trigger when FIFO level is 11,
+     * 0xb for interrupt trigger when FIFO level is 12,
+     * 0xc for interrupt trigger when FIFO level is 13,
+     * 0xd for interrupt trigger when FIFO level is 14,
+     * 0xe for interrupt trigger when FIFO level is 15,
+     * 0xf for interrupt trigger when FIFO level is 16
+     */
+#define TOFF_I2SC_RFF           0x0030		/* (RW) Receive FIFO Flush Register */
+  #define I2SC_RFF_RXCHFR           0x00000001	/* receiver channel FIFO reset */
+#define TOFF_I2SC_TFF           0x0034		/* (RW) Transmit FIFO Flush Register */
+  #define I2SC_TFF_RTXCHFR          0x00000001	/* transmit channel FIFO reset */
+
+#define I2S_CHANNEL_WINDOW_SIZE 0x0040
+#define NUM_I2S_CHANNEL         4
+
+
+/*
+ *  I2C
+ */
+#define TADR_I2C0_BASE      (I2C0_BASE_ADDR)
+#define TADR_I2C1_BASE      (I2C0_BASE_ADDR+0x10000)
+#define TADR_I2C2_BASE      (I2C0_BASE_ADDR+0x20000)
+#define TOFF_I2C_CON            0x0000		/* (RW) I2C Control Register */
+  #define I2C_CON_MASTER_MODE           0x00000001
+  #define I2C_CON_SPEED_MASK            0x00000006
+  #define I2C_CON_10BITADDR_SLAVE       0x00000008
+  #define I2C_CON_RESTART_EN            0x00000020
+  #define I2C_CON_SLAVE_DISABLE         0x00000040
+  #define I2C_CON_STOP_DET_IFADDRESSED  0x00000080
+  #define I2C_CON_TX_EMPTY_CTRL         0x00000100
+#define TOFF_I2C_TAR            0x0004		/* (RW) I2C Target Address Register */
+  #define I2C_TAR_ADDRESS_MASK          0x000003FF
+  #define I2C_TAR_GC_OR_START           0x00000400
+  #define I2C_TAR_SPECIAL               0x00000800
+  #define I2C_TAR_10BITADDR_MASTER      0x00001000
+#define TOFF_I2C_SAR            0x0008		/* (RW) I2C Slave Address Register */
+  #define I2C_SAR_ADDRESS_MASK          0x000003FF
+#define TOFF_I2C_DATA_CMD       0x0010		/* (RW) I2C Data Buffer and Command Register */
+  #define I2C_DATA_CMD_CMD              0x00000100
+  #define I2C_DATA_CMD_DATA_MASK        0x000000FF
+#define TOFF_I2C_SS_SCL_HCNT    0x0014		/* (RW) I2C Standard Speed Clock SCL High Count Register */
+#define TOFF_I2C_SS_SCL_LCNT    0x0018		/* (RW) I2C Standard Speed Clock SCL Low Count Register */
+#define TOFF_I2C_INTR_STAT      0x002C		/* (RW) I2C Interrupt Status Register */
+  #define I2C_INTR_STAT_RX_UNDER        0x00000001
+  #define I2C_INTR_STAT_RX_OVER         0x00000002
+  #define I2C_INTR_STAT_RX_FULL         0x00000004
+  #define I2C_INTR_STAT_TX_OVER         0x00000008
+  #define I2C_INTR_STAT_TX_EMPTY        0x00000010
+  #define I2C_INTR_STAT_RD_REQ          0x00000020
+  #define I2C_INTR_STAT_TX_ABRT         0x00000040
+  #define I2C_INTR_STAT_RX_DONE         0x00000080
+  #define I2C_INTR_STAT_ACTIVITY        0x00000100
+  #define I2C_INTR_STAT_STOP_DET        0x00000200
+  #define I2C_INTR_STAT_START_DET       0x00000400
+  #define I2C_INTR_STAT_GEN_CALL        0x00000800
+#define TOFF_I2C_INTR_MASK      0x0030		/* (RW) I2C Interrupt Mask Register */
+  #define I2C_INTR_MASK_RX_UNDER        0x00000001
+  #define I2C_INTR_MASK_RX_OVER         0x00000002
+  #define I2C_INTR_MASK_RX_FULL         0x00000004
+  #define I2C_INTR_MASK_TX_OVER         0x00000008
+  #define I2C_INTR_MASK_TX_EMPTY        0x00000010
+  #define I2C_INTR_MASK_RD_REQ          0x00000020
+  #define I2C_INTR_MASK_TX_ABRT         0x00000040
+  #define I2C_INTR_MASK_RX_DONE         0x00000080
+  #define I2C_INTR_MASK_ACTIVITY        0x00000100
+  #define I2C_INTR_MASK_STOP_DET        0x00000200
+  #define I2C_INTR_MASK_START_DET       0x00000400
+  #define I2C_INTR_MASK_GEN_CALL        0x00000800
+#define TOFF_I2C_RAW_INTR_STAT  0x0034		/* (RW) I2C Raw Interrupt Status Register */
+  #define I2C_RAW_INTR_MASK_RX_UNDER    0x00000001
+  #define I2C_RAW_INTR_MASK_RX_OVER     0x00000002
+  #define I2C_RAW_INTR_MASK_RX_FULL     0x00000004
+  #define I2C_RAW_INTR_MASK_TX_OVER     0x00000008
+  #define I2C_RAW_INTR_MASK_TX_EMPTY    0x00000010
+  #define I2C_RAW_INTR_MASK_RD_REQ      0x00000020
+  #define I2C_RAW_INTR_MASK_TX_ABRT     0x00000040
+  #define I2C_RAW_INTR_MASK_RX_DONE     0x00000080
+  #define I2C_RAW_INTR_MASK_ACTIVITY    0x00000100
+  #define I2C_RAW_INTR_MASK_STOP_DET    0x00000200
+  #define I2C_RAW_INTR_MASK_START_DET   0x00000400
+  #define I2C_RAW_INTR_MASK_GEN_CALL    0x00000800
+#define TOFF_I2C_RX_TL          0x0038		/* (RW) I2C Receive FIFO Threshold Register */
+  #define I2C_RX_TL_VALUE_MASK          0x00000007
+#define TOFF_I2C_TX_TL          0x003C		/* (RW) I2C Transmit FIFO Threshold Register */
+  #define I2C_TX_TL_VALUE_MASK          0x00000007
+#define TOFF_I2C_CLR_INTR       0x0040		/* (RW) I2C Clear Combined and Individual Interrupt Register */
+  #define I2C_CLR_INTR_CLR              0x00000001
+#define TOFF_I2C_CLR_RX_UNDER   0x0044		/* (RW) I2C Clear RX_UNDER Interrupt Register */
+  #define I2C_CLR_RX_UNDER_CLR          0x00000001
+#define TOFF_I2C_CLR_RX_OVER    0x0048		/* (RW) I2C Clear RX_OVER Interrupt Register */
+  #define I2C_CLR_RX_OVER_CLR           0x00000001
+#define TOFF_I2C_CLR_TX_OVER    0x004C		/* (RW) I2C Clear TX_OVER Interrupt Register */
+  #define I2C_CLR_TX_OVER_CLR           0x00000001
+#define TOFF_I2C_CLR_RD_REQ     0x0050		/* (RW) I2C Clear RD_REQ Interrupt Register */
+  #define I2C_CLR_RD_REQ_CLR            0x00000001
+#define TOFF_I2C_CLR_TX_ABRT    0x0054		/* (RW) I2C Clear TX_ABRT Interrupt Register */
+  #define I2C_CLR_TX_ABRT_CLR           0x00000001
+#define TOFF_I2C_CLR_RX_DONE    0x0058		/* (RW) I2C Clear RX_DONE Interrupt Register */
+  #define I2C_CLR_RX_DONE_CLR           0x00000001
+#define TOFF_I2C_CLR_ACTIVITY   0x005C		/* (RW) I2C Clear ACTIVITY Interrupt Register */
+  #define I2C_CLR_ACTIVITY_CLR          0x00000001
+#define TOFF_I2C_CLR_STOP_DET   0x0060		/* (RW) I2C Clear STOP_DET Interrupt Register */
+  #define I2C_CLR_STOP_DET_CLR          0x00000001
+#define TOFF_I2C_CLR_START_DET  0x0064		/* (RW) I2C Clear START_DET Interrupt Register */
+  #define I2C_CLR_START_DET_CLR         0x00000001
+#define TOFF_I2C_CLR_GEN_CALL   0x0068		/* (RW) I2C Clear GEN_CALL Interrupt Register */
+  #define I2C_CLR_GEN_CALL_CLR          0x00000001
+#define TOFF_I2C_ENABLE         0x006C		/* (RW) I2C Enable Register */
+  #define I2C_ENABLE_ENABLE             0x00000001
+  #define I2C_ENABLE_ABORT              0x00000002
+  #define I2C_ENABLE_TX_CMD_BLOCK       0x00000004
+#define TOFF_I2C_STATUS         0x0070		/* (RW) I2C Status Register */
+  #define I2C_STATUS_ACTIVITY           0x00000001
+  #define I2C_STATUS_TFNF               0x00000002
+  #define I2C_STATUS_TFE                0x00000004
+  #define I2C_STATUS_RFNE               0x00000008
+  #define I2C_STATUS_RFF                0x00000010
+  #define I2C_STATUS_MST_ACTIVITY       0x00000020
+  #define I2C_STATUS_SLV_ACTIVITY       0x00000040
+#define TOFF_I2C_TXFLR          0x0074		/* (RW) I2C Transmit FIFO Level Register */
+  #define I2C_TXFLR_VALUE_MASK          0x00000007
+#define TOFF_I2C_RXFLR          0x0078		/* (RW) I2C Receive FIFO Level Register */
+  #define I2C_RXFLR_VALUE_MASK          0x00000007
+#define TOFF_I2C_SDA_HOLD       0x007C		/* (RW) I2C SDA Hold Time Length Register */
+  #define I2C_SDA_HOLD_TX_MASK          0x0000FFFF
+  #define I2C_SDA_HOLD_RX_MASK          0x00FF0000
+#define TOFF_I2C_TX_ABRT_SOURCE 0x0080		/* (RW) I2C Transmit Abort Source Register */
+  #define I2C_TX_ABRT_SOURCE_7B_ADDR_NOACK   0x00000001
+  #define I2C_TX_ABRT_SOURCE_10B_ADDR1_NOACK 0x00000002
+  #define I2C_TX_ABRT_SOURCE_10B_ADDR2_NOACK 0x00000004
+  #define I2C_TX_ABRT_SOURCE_TXDATA_NOACK    0x00000008
+  #define I2C_TX_ABRT_SOURCE_GCALL_NOACK     0x00000010
+  #define I2C_TX_ABRT_SOURCE_GCALL_READ      0x00000020
+  #define I2C_TX_ABRT_SOURCE_HS_ACKDET       0x00000040
+  #define I2C_TX_ABRT_SOURCE_SBYTE_ACKDET    0x00000080
+  #define I2C_TX_ABRT_SOURCE_HS_NORSTRT      0x00000100
+  #define I2C_TX_ABRT_SOURCE_SBYTE_NORSTRT   0x00000200
+  #define I2C_TX_ABRT_SOURCE_10B_RD_NORSTRT  0x00000400
+  #define I2C_TX_ABRT_SOURCE_MASTER_DIS      0x00000800
+  #define I2C_TX_ABRT_SOURCE_MST_ARBLOST     0x00001000
+  #define I2C_TX_ABRT_SOURCE_SLVFLUSH_TXFIFO 0x00002000
+  #define I2C_TX_ABRT_SOURCE_SLV_ARBLOST     0x00004000
+  #define I2C_TX_ABRT_SOURCE_SLVRD_INTX      0x00008000
+  #define I2C_TX_ABRT_SOURCE_USER_ABRT       0x00010000
+#define TOFF_I2C_DMA_CR         0x0088		/* (RW) I2C DMA Control Register */
+  #define I2C_DMA_CR_RDMAE              0x00000001
+  #define I2C_DMA_CR_TDMAE              0x00000002
+#define TOFF_I2C_DMA_TDLR       0x008C		/* (RW) I2C DMA Transmit Data Level Register */
+  #define I2C_DMA_TDLR_VALUE_MASK       0x00000007
+#define TOFF_I2C_DMA_RDLR       0x0090		/* (RW) I2C DMA Receive Data Level Register */
+  #define I2C_DMA_RDLR_VALUE_MASK       0x00000007
+#define TOFF_I2C_SDA_SETUP      0x0094		/* (RW) I2C SDA Setup Register */
+  #define I2C_SDA_SETUP_VALUE_MASK      0x000000FF
+#define TOFF_I2C_GENERAL_CALL   0x0098		/* (RW) I2C ACK General Call Register */
+  #define I2C_ACK_GENERAL_CALL_ENABLE   0x00000001
+#define TOFF_I2C_ENABLE_STATUS  0x009C		/* (RW) I2C Enable Status Register */
+  #define I2C_ENABLE_STATUS_IC_ENABLE        0x00000001
+  #define I2C_ENABLE_STATUS_SLV_DIS_BUSY     0x00000002
+  #define I2C_ENABLE_STATUS_SLV_RX_DATA_LOST 0x00000004
+#define TOFF_I2C_FS_SPKLEN      0x00A0		/* (RW) I2C SS, FS or FM+ spike suppression limit */
+  #define I2C_FS_SPKLEN_VALUE_MASK      0x000000FF
+#define TOFF_I2C_COMP_PARAM_1   0x00F4		/* (RW) I2C Component Parameter Register 1 */
+  #define I2C_COMP_PARAM1_APB_DATA_WIDTH     0x00000003
+  #define I2C_COMP_PARAM1_MAX_SPEED_MODE     0x0000000C
+  #define I2C_COMP_PARAM1_HC_COUNT_VALUES    0x00000010
+  #define I2C_COMP_PARAM1_INTR_IO            0x00000020
+  #define I2C_COMP_PARAM1_HAS_DMA            0x00000040
+  #define I2C_COMP_PARAM1_ENCODED_PARAMS     0x00000080
+  #define I2C_COMP_PARAM1_RX_BUFFER_DEPTH    0x0000FF00
+  #define I2C_COMP_PARAM1_TX_BUFFER_DEPTH    0x00FF0000
+#define TOFF_I2C_COMP_VERSION   0x00F8		/* (RW) I2C Component Version Register */
+#define TOFF_I2C_COMP_TYPE      0x00FC		/* (RW) I2C Component Type Register */
+
+
+/*
+ *  FPIOA
+ */
+#define TADR_FPIOA_BASE     (FPIOA_BASE_ADDR)
+#define FPIOA_NUM_IO        (48)
+#define TOFF_FPIOA_IO       0x0000
+  #define FPIOA_CH_SEL        0x000000FF	/* Channel select from 256 input. */
+  #define FPIOA_DS            0x00000F00	/* Driving selector. */
+  #define FPIOA_OE_EN         0x00001000	/* Static output enable, will AND with OE_INV. */
+  #define FPIOA_OE_INV        0x00002000	/* Invert output enable. */
+  #define FPIOA_DO_SEL        0x00004000	/* Data output select: 0 for DO, 1 for OE. */
+  #define FPIOA_DO_INV        0x00008000	/* Invert the result of data output select (DO_SEL). */
+  #define FPIOA_PU            0x00010000	/* Pull up enable. 0 for nothing, 1 for pull up. */
+  #define FPIOA_PD            0x00020000	/* Pull down enable. 0 for nothing, 1 for pull down. */
+  #define FPIOA_SL            0x00080000	/* Slew rate control enable. */
+  #define FPIOA_IE_EN         0x00100000	/* Static input enable, will AND with IE_INV. */
+  #define FPIOA_IE_INV        0x00200000	/* Invert input enable. */
+  #define FPIOA_DI_INV        0x00400000	/* Invert Data input. */
+  #define FPIOA_ST            0x00800000	/* Schmitt trigger. */
+  #define FPIOA_PAD_DI        0x80000000	/* Read current IO's data input. */
+#define TOFF_FPIOA_TIE_EN   (FPIOA_NUM_IO*4)
+#define TOFF_FPIOA_TIE_VAL  (TOFF_FPIOA_TIE_EN+(FUNC_MAX/8))
+
+
+/*
+ *  TIMER
+ */
+#define TADR_TIMER0_BASE    (TIMER0_BASE_ADDR)
+#define TADR_TIMER1_BASE    (TIMER0_BASE_ADDR+0x10000)
+#define TADR_TIMER2_BASE    (TIMER0_BASE_ADDR+0x20000)
+#define TOFF_TIMER_CHANNEL        0x0000	/* (RW) TIMER_N Register 20bytes * 4 */
+#define TOFF_TIMER_INT_STATR      0x00A0	/* (RW) TIMER Interrupt Status Register */
+#define TOFF_TIMER_EOI            0x00A4	/* (RW) TIMER Interrupt Clear Register */
+#define TOFF_TIMER_RAW_INTR_STAT  0x00A8	/* (RW) TIMER Raw Interrupt Status Register */
+#define TOFF_TIMER_COMP_VERSION   0x00AC	/* (RW) TIMER Component Version Register */
+#define TOFF_TIMER_LOAD_COUNT2    0x00B0	/* (RW) TIMER_N Load Count2 Register 4 *4 */
+
+/*
+ *  TIMER CHANNEL WINDOW
+ */
+#define TOFF_TIMERC_LOAD_COUNT    0x0000	/* (RW) TIMER_N Load Count Register */
+#define TOFF_TIMERC_CURRENT_VALUE 0x0004	/* (RW) TIMER_N Current Value Register */
+#define TOFF_TIMERC_CONTROL       0x0008	/* (RW) TIMER_N Control Register */
+  #define TIMERC_CR_ENABLE          0x00000001
+  #define TIMERC_CR_MODE_MASK       0x00000002
+  #define TIMERC_CR_FREE_MODE       0x00000000
+  #define TIMERC_CR_USER_MODE       0x00000002
+  #define TIMERC_CR_INTERRUPT_MASK  0x00000004
+  #define TIMERC_CR_PWM_ENABLE      0x00000008
+#define TOFF_TIMERC_EOI           0x000C	/* (RW) TIMER_N Interrupt Clear Register */
+#define TOFF_TIMERC_INTR_STAT     0x0010	/* (RW) TIMER_N Interrupt Status Register */
+
+#define TIMER_CHANNEL_WINDOW_SIZE 0x0014
+#define NUM_TIMER_CHANNEL         4
+
+
+/*
+ *  WDT
+ */
+#define TADR_WDT0_BASE      (WDT0_BASE_ADDR)
+#define TADR_WDT1_BASE      (WDT0_BASE_ADDR+0x10000)
+#define TOFF_WDT_CR         0x0000		/* (RW) WDT Control Register */
+  #define WDT_CR_ENABLE         0x00000001
+  #define WDT_CR_RMOD_MASK      0x00000002
+  #define WDT_CR_RMOD_RESET     0x00000000
+  #define WDT_CR_RMOD_INTERRUPT 0x00000002
+  #define WDT_CR_RPL_MASK       0x0000001C
+#define TOFF_WDT_TORR       0x0004		/* (RW) WDT Timeout Range Register */
+  #define WDT_TORR_TOP_MASK     0x000000FF
+#define TOFF_WDT_CCVR       0x0008		/* (RW) WDT Current Counter Value Register */
+#define TOFF_WDT_CRR        0x000C		/* (RW) WDT Counter Restart Register */
+  #define WDT_CRR_MASK          0x00000076
+#define TOFF_WDT_STAT       0x0010		/* (RW) WDT Interrupt Status Register */
+#define TOFF_WDT_EOI        0x0014		/* (RW) WDT Interrupt Clear Register */
+#define TOFF_WDT_PROT_LEVEL 0x001C		/* (RW) WDT Protection level Register */
+  #define WDT_PROT_LEVEL_MASK   0x00000007
+#define TOFF_WDT_CMP_PARAM5 0x00E4		/* (RW) WDT Component Parameters Register 5 */
+#define TOFF_WDT_CMP_PARAM4 0x00E8		/* (RW) WDT Component Parameters Register 4 */
+#define TOFF_WDT_CMP_PARAM3 0x00EC		/* (RW) WDT Component Parameters Register 3 */
+#define TOFF_WDT_CMP_PARAM2 0x00F0		/* (RW) WDT Component Parameters Register 2 */
+#define TOFF_WDT_CMP_PARAM1 0x00F4		/* (RW) WDT Component Parameters Register 1 */
+  #define WDT_COMP_PARAM_1_WDT_ALWAYS_EN_MASK      0x00000001
+  #define WDT_COMP_PARAM_1_WDT_DFLT_RMOD_MASK      0x00000002
+  #define WDT_COMP_PARAM_1_WDT_DUAL_TOP_MASK       0x00000004
+  #define WDT_COMP_PARAM_1_WDT_HC_RMOD_MASK        0x00000008
+  #define WDT_COMP_PARAM_1_WDT_HC_RPL_MASK         0x00000010
+  #define WDT_COMP_PARAM_1_WDT_HC_TOP_MASK         0x00000020
+  #define WDT_COMP_PARAM_1_WDT_USE_FIX_TOP_MASK    0x00000040
+  #define WDT_COMP_PARAM_1_WDT_PAUSE_MASK          0x00000080
+  #define WDT_COMP_PARAM_1_APB_DATA_WIDTH_MASK     0x00000300
+  #define WDT_COMP_PARAM_1_WDT_DFLT_RPL_MASK       0x00001C00
+  #define WDT_COMP_PARAM_1_WDT_DFLT_TOP_MASK       0x000F0000
+  #define WDT_COMP_PARAM_1_WDT_DFLT_TOP_INIT_MASK  0x00F00000
+  #define WDT_COMP_PARAM_1_WDT_CNT_WIDTH_MASK      0x1F000000
+#define TOFF_WDT_CMP_VER    0x00F8		/* (RW) WDT Component Version Register */
+#define TOFF_WDT_CMP_TYPE   0x00FC		/* (RW) WDT Component Type Register */
+
+
+/*
+ *  SYSCTL
+ */
+#define TADR_SYSCTL_BASE    (SYSCTL_BASE_ADDR)
+#define TOFF_SYSCTL_GIT_ID      0x0000			/* (RW) No. 0: Git short commit id */
+#define TOFF_SYSCTL_CLK_FREQ    0x0004			/* (RW) No. 1: System clock base frequency */
+#define TOFF_SYSCTL_PLL0        0x0008			/* (RW) No. 2: PLL0 controller */
+  #define SYSCTL_PLL_CLKR0              0x0000000F	/* clkr0 : 4 */
+  #define SYSCTL_PLL_CLKF0              0x000003F0	/* clkf0 : 6 */
+  #define SYSCTL_PLL_CLKOD0             0x00003C00	/* clkod0 : 4 */
+  #define SYSCTL_PLL_BWADJ0             0x000FC000	/* bwadj0 : 6 */
+  #define SYSCTL_PLL_RESET0             0x00100000	/* pll_reset0 : 1 */
+  #define SYSCTL_PLL_PWRD0              0x00200000	/* pll_pwrd0 : 1 */
+  #define SYSCTL_PLL_INTFB0             0x00400000	/* pll_intfb0 : 1 */
+  #define SYSCTL_PLL_BYPASS0            0x00800000	/* pll_bypass0 : 1 */
+  #define SYSCTL_PLL_TEST0              0x01000000	/* pll_test0 : 1 */
+  #define SYSCTL_PLL_OUT_EN0            0x02000000	/* pll_out_en0 : 1 */
+  #define SYSCTL_PLL_TEST_EN            0x04000000	/* pll_test_en : 1 */
+#define TOFF_SYSCTL_PLL1        0x000C			/* (RW) No. 3: PLL1 controller */
+  #define SYSCTL_PLL_CLKR1              0x0000000F	/* clkr1 : 4 */
+  #define SYSCTL_PLL_CLKF1              0x000003F0	/* clkf1 : 6 */
+  #define SYSCTL_PLL_CLKOD1             0x00003C00	/* clkod1 : 4 */
+  #define SYSCTL_PLL_BWADJ1             0x000FC000	/* bwadj1 : 6 */
+  #define SYSCTL_PLL_RESET1             0x00100000	/* pll_reset1 : 1 */
+  #define SYSCTL_PLL_PWRD1              0x00200000	/* pll_pwrd1 : 1 */
+  #define SYSCTL_PLL_INTFB1             0x00400000	/* pll_intfb1 : 1 */
+  #define SYSCTL_PLL_BYPASS1            0x00800000	/* pll_bypass1 : 1 */
+  #define SYSCTL_PLL_TEST1              0x01000000	/* pll_test1 : 1 */
+  #define SYSCTL_PLL_OUT_EN1            0x02000000	/* pll_out_en1 : 1 */
+#define TOFF_SYSCTL_PLL2        0x0010			/* (RW) No. 4: PLL2 controller */
+  #define SYSCTL_PLL_CLKR2              0x0000000F	/* clkr2 : 4 */
+  #define SYSCTL_PLL_CLKF2              0x000003F0	/* clkf2 : 6 */
+  #define SYSCTL_PLL_CLKOD2             0x00003C00	/* clkod2 : 4 */
+  #define SYSCTL_PLL_BWADJ2             0x000FC000	/* bwadj2 : 6 */
+  #define SYSCTL_PLL_RESET2             0x00100000	/* pll_reset2 : 1 */
+  #define SYSCTL_PLL_PWRD2              0x00200000	/* pll_pwrd2 : 1 */
+  #define SYSCTL_PLL_INTFB2             0x00400000	/* pll_intfb2 : 1 */
+  #define SYSCTL_PLL_BYPASS2            0x00800000	/* pll_bypass2 : 1 */
+  #define SYSCTL_PLL_TEST2              0x01000000	/* pll_test2 : 1 */
+  #define SYSCTL_PLL_OUT_EN2            0x02000000	/* pll_out_en2 : 1 */
+  #define SYSCTL_PLL_CKIN_SEL2          0x0C000000	/* pll_ckin_sel2 : 2 */
+#define TOFF_SYSCTL_PLL_LOCK    0x0018			/* (RW) No. 6: PLL lock tester */
+  #define SYSCTL_PLL_LOCK_LOCK0         0x00000003	/* pll_lock0 : 2 */
+  #define SYSCTL_PLL_LOCK_SLIP_CLEAR0   0x00000004	/* pll_slip_clear0 : 1 */
+  #define SYSCTL_PLL_LOCK_TEST_CLK_OUT0 0x00000008	/* test_clk_out0 : 1 */
+  #define SYSCTL_PLL_LOCK_LOCK1         0x00000300	/* pll_lock1 : 2 */
+  #define SYSCTL_PLL_LOCK_SLIP_CLEAR1   0x00000400	/* pll_slip_clear1 : 1 */
+  #define SYSCTL_PLL_LOCK_TEST_CLK_OUT1 0x00000800	/* test_clk_out1 : 1 */
+  #define SYSCTL_PLL_LOCK_LOCK2         0x00030000  /* pll_lock2 : 2 */
+  #define SYSCTL_PLL_LOCK_SLIP_CLEAR2   0x00040000	/* pll_slip_clear2 : 1 */
+  #define SYSCTL_PLL_LOCK_TEST_CLK_OUT2 0x00080000	/* test_clk_out2 : 1 */
+#define TOFF_SYSCTL_ROM_ERROR   0x001C			/* (RW) No. 7: AXI ROM detector */
+  #define SYSCTL_ROM_ERROR_NUL_ERROR    0x00000001	/* rom_mul_error : 1 */
+  #define SYSCTL_ROM_ERROR_ONE_ERROR    0x00000002	/* rom_one_error : 1 */
+#define TOFF_CLK_SEL0           0x0020			/* (RW) No. 8: Clock select controller0 */
+  #define SYSCTL_CLK_SEL0_ACLK_SEL      0x00000001	/* aclk_sel : 1 */
+  #define SYSCTL_CLK_SEL0_SOURCE_IN0    0x00000000
+  #define SYSCTL_CLK_SEL0_SOURCE_PLL0   0x00000001
+  #define SYSCTL_CLK_SEL0_ACLK_SDIVISER 0x00000006	/* aclk_divider_sel : 2 */
+  #define SYSCTL_CLK_SEL0_APB0_CLK_SEL  0x00000038	/* apb0_clk_sel : 3 */
+  #define SYSCTL_CLK_SEL0_APB1_CLK_SEL  0x000001C0	/* apb1_clk_sel : 3 */
+  #define SYSCTL_CLK_SEL0_APB2_CLK_SEL  0x00000E00	/* apb2_clk_sel : 3 */
+  #define SYSCTL_CLK_SEL0_SPI3_CLK_SEL  0x00001000	/* spi3_clk_sel : 1 */
+  #define SYSCTL_CLK_SEL0_TIM0_CLK_SEL  0x00002000	/* timer0_clk_sel : 1 */
+  #define SYSCTL_CLK_SEL0_TIM1_CLK_SEL  0x00004000	/* timer1_clk_sel : 1 */
+  #define SYSCTL_CLK_SEL0_TIM2_CLK_SEL  0x00008000	/* timer2_clk_sel : 1 */
+#define TOFF_CLK_SEL1           0x0024			/* (RW) No. 9: Clock select controller1 */
+  #define SYSCTL_CLK_SEL1_SPI3S_CLK_SEL 0x00000001	/* spi3_sample_clk_sel : 1 */
+#define TOFF_SYSCTL_CLK_EN_CENT 0x0028			/* (RW) No. 10: Central clock enable */
+  #define SYSCTL_CLK_EN_CENT_CPU_CLK_EN   0x00000001	/* cpu_clk_en : 1 */
+  #define SYSCTL_CLK_EN_CENT_SRAM0_CLK_EN 0x00000002	/* sram0_clk_en : 1 */
+  #define SYSCTL_CLK_EN_CENT_SRAM1_CLK_EN 0x00000004	/* sram1_clk_en : 1 */
+  #define SYSCTL_CLK_EN_CENT_APB0_CLK_EN  0x00000008	/* apb0_clk_en : 1 */
+  #define SYSCTL_CLK_EN_CENT_APB1_CLK_EN  0x00000010	/* apb1_clk_en : 1 */
+  #define SYSCTL_CLK_EN_CENT_APB2_CLK_EN  0x00000020	/* apb2_clk_en : 1 */
+#define TOFF_SYSCTL_CLK_EN_PERI 0x002C			/* (RW) No. 11: Peripheral clock enable */
+  #define SYSCTL_CLK_EN_PERI_ROM_CLK_EN   0x00000001	/* rom_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_DMA_CLK_EN   0x00000002	/* dma_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_AI_CLK_EN    0x00000004	/* ai_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_DVP_CLK_EN   0x00000008	/* dvp_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_FFT_CLK_EN   0x00000010	/* fft_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_GPIO_CLK_EN  0x00000020	/* gpio_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_SPI0_CLK_EN  0x00000040	/* spi0_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_SPI1_CLK_EN  0x00000080	/* spi1_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_SPI2_CLK_EN  0x00000100	/* spi2_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_SPI3_CLK_EN  0x00000200	/* spi3_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_I2S0_CLK_EN  0x00000400	/* i2s0_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_I2S1_CLK_EN  0x00000800	/* i2s1_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_I2S2_CLK_EN  0x00001000	/* i2s2_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_I2C0_CLK_EN  0x00002000	/* i2c0_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_I2C1_CLK_EN  0x00004000	/* i2c1_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_I2C2_CLK_EN  0x00008000	/* i2c2_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_UART1_CLK_EN 0x00010000	/* uart1_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_UART2_CLK_EN 0x00020000	/* uart2_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_UART3_CLK_EN 0x00040000	/* uart3_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_AES_CLK_EN   0x00080000	/* aes_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_FPIOA_CLK_EN 0x00100000	/* fpioa_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_TIM0_CLK_EN  0x00200000	/* timer0_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_TIM1_CLK_EN  0x00400000	/* timer1_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_TIM2_CLK_EN  0x00800000	/* timer2_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_WDT0_CLK_EN  0x01000000	/* wdt0_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_WDT1_CLK_EN  0x02000000	/* wdt1_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_SHA_CLK_EN   0x04000000	/* sha_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_OTP_CLK_EN   0x08000000	/* otp_clk_en : 1 */
+  #define SYSCTL_CLK_EN_PERI_RTC_CLK_EN   0x20000000	/* rtc_clk_en : 1 */
+#define TOFF_SYSCTL_SOFT_RESET  0x0030			/* (RW) No. 12: Soft reset ctrl */
+  #define SYSCTL_SOFT_RESET_RESET         0x00000001	/* soft_reset : 1 */
+#define TOFF_SYSCTL_PERI_RESET  0x0034			/* (RW) No. 13: Peripheral reset controller */
+  #define SYSCTL_PERI_RESET_ROM_RESET     0x00000001	/* rom_reset : 1 */
+  #define SYSCTL_PERI_RESET_DMA_RESET     0x00000002	/* dma_reset : 1 */
+  #define SYSCTL_PERI_RESET_AI_RESET      0x00000004	/* ai_reset : 1 */
+  #define SYSCTL_PERI_RESET_DVP_RESET     0x00000008	/* dvp_reset : 1 */
+  #define SYSCTL_PERI_RESET_FFT_RESET     0x00000010	/* fft_reset : 1 */
+  #define SYSCTL_PERI_RESET_GPIO_RESET    0x00000020	/* gpio_reset : 1 */
+  #define SYSCTL_PERI_RESET_SPI0_RESET    0x00000040	/* spi0_reset : 1 */
+  #define SYSCTL_PERI_RESET_SPI1_RESET    0x00000080	/* spi1_reset : 1 */
+  #define SYSCTL_PERI_RESET_SPI2_RESET    0x00000100	/* spi2_reset : 1 */
+  #define SYSCTL_PERI_RESET_SPI3_RESET    0x00000200	/* spi3_reset : 1 */
+  #define SYSCTL_PERI_RESET_I2S0_RESET    0x00000400	/* i2s0_reset : 1 */
+  #define SYSCTL_PERI_RESET_I2S1_RESET    0x00000800	/* i2s1_reset : 1 */
+  #define SYSCTL_PERI_RESET_I2S2_RESET    0x00001000	/* i2s2_reset : 1 */
+  #define SYSCTL_PERI_RESET_I2C0_RESET    0x00002000	/* i2c0_reset : 1 */
+  #define SYSCTL_PERI_RESET_I2C1_RESET    0x00004000	/* i2c1_reset : 1 */
+  #define SYSCTL_PERI_RESET_I2C2_RESET    0x00008000	/* i2c2_reset : 1 */
+  #define SYSCTL_PERI_RESET_UART1_RESET   0x00010000	/* uart1_reset : 1 */
+  #define SYSCTL_PERI_RESET_UART2_RESET   0x00020000	/* uart2_reset : 1 */
+  #define SYSCTL_PERI_RESET_UART3_RESET   0x00040000	/* uart3_reset : 1 */
+  #define SYSCTL_PERI_RESET_AES_RESET     0x00080000	/* aes_reset : 1 */
+  #define SYSCTL_PERI_RESET_FPIOA_RESET   0x00100000	/* fpioa_reset : 1 */
+  #define SYSCTL_PERI_RESET_TIM0_RESET    0x00200000	/* timer0_reset : 1 */
+  #define SYSCTL_PERI_RESET_TIM1_RESET    0x00400000	/* timer1_reset : 1 */
+  #define SYSCTL_PERI_RESET_TIM2_RESET    0x00800000	/* timer2_reset : 1 */
+  #define SYSCTL_PERI_RESET_WDT0_RESET    0x01000000	/* wdt0_reset : 1 */
+  #define SYSCTL_PERI_RESET_WDT1_RESET    0x02000000	/* wdt1_reset : 1 */
+  #define SYSCTL_PERI_RESET_SHA_RESET     0x04000000	/* sha_reset : 1 */
+  #define SYSCTL_PERI_RESET_RTC_RESET     0x20000000	/* rtc_reset : 1 */
+#define TOFF_SYSCTL_CLK_TH0     0x0038			/* (RW) No. 14: Clock threshold controller 0 */
+  #define SYSCTL_CLK_TH0_SRAM0_GCLK_THHD  0x0000000F	/* sram0_gclk_threshold : 4 */
+  #define SYSCTL_CLK_TH0_SRAM1_GCLK_THHD  0x000000F0	/* sram1_gclk_threshold : 4 */
+  #define SYSCTL_CLK_TH0_AI_GCLK_THHD     0x00000F00	/* ai_gclk_threshold : 4 */
+  #define SYSCTL_CLK_TH0_DVP_GCLK_THHD    0x0000F000	/* dvp_gclk_threshold : 4 */
+  #define SYSCTL_CLK_TH0_ROM_GCLK_THHD    0x000F0000	/* rom_gclk_threshold : 4 */
+#define TOFF_SYSCTL_CLK_TH1     0x003C			/* (RW) No. 15: Clock threshold controller 1 */
+  #define SYSCTL_CLK_TH1_SPI0_CLK_THHD    0x000000FF	/* spi0_clk_threshold : 8 */
+  #define SYSCTL_CLK_TH1_SPI1_CLK_THHD    0x0000FF00	/* spi1_clk_threshold : 8 */
+  #define SYSCTL_CLK_TH1_SPI2_CLK_THHD    0x00FF0000	/* spi2_clk_threshold : 8 */
+  #define SYSCTL_CLK_TH1_SPI3_CLK_THHD    0xFF000000	/* spi3_clk_threshold : 8 */
+#define TOFF_SYSCTL_CLK_TH2     0x0040			/* (RW) No. 16: Clock threshold controller 2 */
+  #define SYSCTL_CLK_TH2_TM0_CLK_THHD     0x000000FF	/* timer0_clk_threshold : 8 */
+  #define SYSCTL_CLK_TH2_TM1_CLK_THHD     0x0000FF00	/* timer1_clk_threshold : 8 */
+  #define SYSCTL_CLK_TH2_TM2_CLK_THHD     0x00FF0000	/* timer2_clk_threshold : 8 */
+#define TOFF_SYSCTL_CLK_TH3     0x0044			/* (RW) No. 17: Clock threshold controller 3 */
+  #define SYSCTL_CLK_TH3_I2S0_CLK_THHD    0x0000FFFF	/* i2s0_clk_threshold : 16 */
+  #define SYSCTL_CLK_TH3_I2S1_CLK_THHD    0xFFFF0000	/* i2s1_clk_threshold : 16 */
+#define TOFF_SYSCTL_CLK_TH4     0x0048			/* (RW) No. 18: Clock threshold controller 4 */
+  #define SYSCTL_CLK_TH4_I2S2_CLK_THHD    0x0000FFFF	/* i2s2_clk_threshold : 16 */
+  #define SYSCTL_CLK_TH4_I2S0_MCLK_THHD   0x00FF0000	/* i2s0_mclk_threshold : 8 */
+  #define SYSCTL_CLK_TH4_I2S1_MCLK_THHD   0xFF000000	/* i2s1_mclk_threshold : 8 */
+#define TOFF_SYSCTL_CLK_TH5     0x004C			/* (RW) No. 19: Clock threshold controller 5 */
+  #define SYSCTL_CLK_TH5_I2S2_MCLK_THHD   0x000000FF	/* i2s2_mclk_threshold : 8 */
+  #define SYSCTL_CLK_TH5_I2C0_CLK_THHD    0x0000FF00	/* i2c0_clk_threshold : 8 */
+  #define SYSCTL_CLK_TH5_I2C1_CLK_THHD    0x00FF0000	/* i2c1_clk_threshold : 8 */
+  #define SYSCTL_CLK_TH5_I2C2_CLK_THHD    0xFF000000	/* i2c2_clk_threshold : 8 */
+#define TOFF_SYSCTL_CLK_TH6     0x0050			/* (RW) No. 20: Clock threshold controller 6 */
+  #define SYSCTL_CLK_TH6_WD0_CLK_THHD     0x000000FF	/* wdt0_clk_threshold : 8 */
+  #define SYSCTL_CLK_TH6_WD1_CLK_THHD     0x0000FF00	/* wdt1_clk_threshold : 8 */
+#define TOFF_SYSCTL_MISC        0x0054			/* (RW) No. 21: Miscellaneous controller */
+  #define SYSCTL_MISC_DEBUG_SEL           0x0000003F	/* debug_sel : 6 */
+  #define SYSCTL_MISC_SPI_DVP_DATA_ENABLE 0x00000400	/* spi_dvp_data_enable: 1 */
+#define TOFF_SYSCTL_PERI        0x0058			/* (RW) No. 22: Peripheral controller */
+  #define SYSCTL_PERI_TIMER0_PAUSE        0x00000001	/* timer0_pause : 1 */
+  #define SYSCTL_PERI_TIMER1_PAUSE        0x00000002	/* timer1_pause : 1 */
+  #define SYSCTL_PERI_TIMER2_PAUSE        0x00000004	/* timer2_pause : 1 */
+  #define SYSCTL_PERI_TIMER3_PAUSE        0x00000008	/* timer3_pause : 1 */
+  #define SYSCTL_PERI_TIMER4_PAUSE        0x00000010	/* timer4_pause : 1 */
+  #define SYSCTL_PERI_TIMER5_PAUSE        0x00000020	/* timer5_pause : 1 */
+  #define SYSCTL_PERI_TIMER6_PAUSE        0x00000040	/* timer6_pause : 1 */
+  #define SYSCTL_PERI_TIMER7_PAUSE        0x00000080	/* timer7_pause : 1 */
+  #define SYSCTL_PERI_TIMER8_PAUSE        0x00000100	/* timer8_pause : 1 */
+  #define SYSCTL_PERI_TIMER9_PAUSE        0x00000200	/* timer9_pause : 1 */
+  #define SYSCTL_PERI_TIMER10_PAUSE       0x00000400	/* timer10_pause : 1 */
+  #define SYSCTL_PERI_TIMER11_PAUSE       0x00000800	/* timer11_pause : 1 */
+  #define SYSCTL_PERI_SPI0_XIP_EN         0x00001000	/* spi0_xip_en : 1 */
+  #define SYSCTL_PERI_SPI1_XIP_EN         0x00002000	/* spi1_xip_en : 1 */
+  #define SYSCTL_PERI_SPI2_XIP_EN         0x00004000	/* spi2_xip_en : 1 */
+  #define SYSCTL_PERI_SPI3_XIP_EN         0x00008000	/* spi3_xip_en : 1 */
+  #define SYSCTL_PERI_SPI0_CLK_BYPASS     0x00010000	/* spi0_clk_bypass : 1 */
+  #define SYSCTL_PERI_SPI1_CLK_BYPASS     0x00020000	/* spi1_clk_bypass : 1 */
+  #define SYSCTL_PERI_SPI2_CLK_BYPASS     0x00040000	/* spi2_clk_bypass : 1 */
+  #define SYSCTL_PERI_I2S0_CLK_BYPASS     0x00080000	/* i2s0_clk_bypass : 1 */
+  #define SYSCTL_PERI_I2S1_CLK_BYPASS     0x00100000	/* i2s1_clk_bypass : 1 */
+  #define SYSCTL_PERI_I2S2_CLK_BYPASS     0x00200000	/* i2s2_clk_bypass : 1 */
+  #define SYSCTL_PERI_JTAG_CLK_BYPASS     0x00400000	/* jtag_clk_bypass : 1 */
+  #define SYSCTL_PERI_DVP_CLK_BYPASS      0x00800000	/* dvp_clk_bypass : 1 */
+  #define SYSCTL_PERI_DEBUG_CLK_BYPASS    0x01000000	/* debug_clk_bypass : 1 */
+#define TOFF_SYSCTL_SPI_SLEEP   0x005C			/* (RW) No. 23: SPI sleep controller */
+  #define SYSCTL_SPI_SLEEP_SSI0_SLEEP     0x00000001	/* ssi0_sleep : 1 */
+  #define SYSCTL_SPI_SLEEP_SSI1_SLEEP     0x00000002	/* ssi1_sleep : 1 */
+  #define SYSCTL_SPI_SLEEP_SSI2_SLEEP     0x00000004	/* ssi2_sleep : 1 */
+  #define SYSCTL_SPI_SLEEP_SSI3_SLEEP     0x00000008	/* ssi3_sleep : 1 */
+#define TOFF_SYSCTL_RST_STATUS  0x0060			/* (RW) No. 24: Reset source status */
+  #define SYSCTL_RST_STATUS_RESET_STS_CLR 0x00000001	/* reset_sts_clr : 1 */
+  #define SYSCTL_RST_STATUS_PIN_RESET_STS 0x00000002	/* pin_reset_sts : 1 */
+  #define SYSCTL_RST_STATUS_WDT0_RESET_STS 0x00000004	/* wdt0_reset_sts : 1 */
+  #define SYSCTL_RST_STATUS_WDT1_RESET_STS 0x00000008	/* wdt1_reset_sts : 1 */
+  #define SYSCTL_RST_STATUS_SOFT_RESET_STS 0x00000010	/* soft_reset_sts : 1 */
+#define TOFF_SYSCTL_DMA_SEL0    0x0064			/* (RW) No. 25: DMA handshake selector */
+  #define SYSCTL_DMA_SEL0_DMA_SEL0        0x0000003F	/* dma_sel0 : 6 */
+  #define SYSCTL_DMA_SEL0_DMA_SEL1        0x00000FC0	/* dma_sel1 : 6 */
+  #define SYSCTL_DMA_SEL0_DMA_SEL2        0x0003F000	/* dma_sel2 : 6 */
+  #define SYSCTL_DMA_SEL0_DMA_SEL3        0x00FC0000	/* dma_sel3 : 6 */
+  #define SYSCTL_DMA_SEL0_DMA_SEL4        0x3F000000	/* dma_sel4 : 6 */
+#define TOFF_SYSCTL_DMA_SEL1    0x0068			/* (RW) No. 26: DMA handshake selector */
+  #define SYSCTL_DMA_SEL0_DMA_SEL5        0x0000003F	/* dma_sel5 : 6 */
+#define TOFF_SYSCTL_POWER_SEL   0x006C			/* (RW) No. 27: IO Power Mode Select controller */
+  #define SYSCTL_POWER_SEL_POWER_MODE_0   0x00000001	/* power_mode_sel0 : 1 */
+  #define SYSCTL_POWER_SEL_POWER_MODE_1   0x00000002	/* power_mode_sel1 : 1 */
+  #define SYSCTL_POWER_SEL_POWER_MODE_2   0x00000004	/* power_mode_sel2 : 1 */
+  #define SYSCTL_POWER_SEL_POWER_MODE_3   0x00000008	/* power_mode_sel3 : 1 */
+  #define SYSCTL_POWER_SEL_POWER_MODE_4   0x00000010	/* power_mode_sel4 : 1 */
+  #define SYSCTL_POWER_SEL_POWER_MODE_5   0x00000020	/* power_mode_sel5 : 1 */
+  #define SYSCTL_POWER_SEL_POWER_MODE_6   0x00000040	/* power_mode_sel6 : 1 */
+  #define SYSCTL_POWER_SEL_POWER_MODE_7   0x00000080	/* power_mode_sel7 : 1 */
+
+/*
+ *  RTC
+ */
+#define TADR_RTC_BASE       (RTC_BASE_ADDR)
+#define TOFF_RTC_DATE       0x0000		/* (RW) Timer date information */
+  #define RTC_DATE_WEEK         0x00000007	/* Week. Range [0,6]. 0 is Sunday. */
+  #define RTC_DATE_DAY          0x00001F00	/* Day. Range [1,31] or [1,30] or [1,29] or [1,28] */
+  #define RTC_DATE_MONTH        0x000F0000	/* Month. Range [1,12] */
+  #define RTC_DATE_YEAR         0x3FF00000	/* Year. Range [0,99] */
+#define TOFF_RTC_TIME       0x0004		/* (RW) Timer time information */
+  #define RTC_TIME_SECOND       0x0000FC00	/* Second. Range [0,59] */
+  #define RTC_TIME_MINUTE       0x003F0000	/* Minute. Range [0,59] */
+  #define RTC_TIME_HOUR         0x1F000000	/* Hour. Range [0,23] */
+#define TOFF_ALARM_DATE     0x0008		/* (RW) Alarm date information */
+  #define RTC_ALARM_DATE_WEEK   0x00000003	/* Alarm Week. Range [0,6]. 0 is Sunday. */
+  #define RTC_ALARM_DATE_DAY    0x00001F00	/* Alarm Day. Range [1,31] or [1,30] or [1,29] or [1,28] */
+  #define RTC_ALARM_DATE_MONTH  0x000F0000	/* Alarm Month. Range [1,12] */
+  #define RTC_ALARM_DATE_YEAR   0x3FF00000	/* Alarm Year. Range [0,99] */
+#define TOFF_ALARM_TIME     0x000C		/* (RW) Alarm time information */
+  #define RTC_ALARM_TIME_SECOND 0x0000FC00	/* Alarm Second. Range [0,59] */
+  #define RTC_ALARM_TIME_MINUTE 0x003F0000	/* Alarm Minute. Range [0,59] */
+  #define RTC_ALARM_TIME_HOUR   0x1F000000	/* Alarm Hour. Range [0,23] */
+#define TOFF_INITIAL_COUNT  0x0010		/* (RW) Timer counter initial value */
+#define TOFF_COURRNT_COUNT  0x0014		/* (RW) Timer counter current value */
+#define TOFF_INTERRUPT_CTRL 0x0018		/* (RW) RTC interrupt settings */
+  #define RTC_INT_TICK_ENABLE   0x00000001	/* Reserved */
+  #define RTC_INT_ALARM_ENABLE  0x00000002	/* Alarm interrupt enable */
+  #define RTC_INT_TICK_INT_MODE 0x0000000C	/* Tick interrupt enable */
+  #define RTC_INT_ARARM_C_MASK  0xFF000000	/* Alarm compare mask for interrupt */
+#define TOFF_REGISTER_CTRL  0x001C		/* (RW) RTC register settings */
+  #define RTC_RCTL_READ_ENABLE  0x00000001	/* RTC timer read enable */
+  #define RTC_RCTL_WRITE_ENABLE 0x00000002	/* RTC timer write enable */
+  #define RTC_RCTL_TIMER_MASK   0x001FE000	/* RTC timer mask */
+  #define RTC_RCTL_ALARAM_MASK  0x1FE00000	/* RTC alarm mask */
+  #define RTC_RCTL_INT_CNT_MASK 0x20000000	/* RTC counter initial count value mask */
+  #define RTC_RCTL_INT_REG_MASK 0x40000000	/* RTC interrupt register mask */
+#define TOFF_RTC_EXTENDED   0x0028			/* (RW) Timer extended information */
+  #define RTC_EXTENDED_CENTURY  0x0000001F	/* Century. Range [0,31] */
+  #define RTC_EXTENDED_YEAR     0x00000020	/* Is leap year. 1 is leap year, 0 is not leap year */
+
+
+/*
+ *  SPI
+ */
+#define TADR_SPI0_BASE      (SPI0_BASE_ADDR)
+#define TADR_SPI1_BASE      (SPI1_BASE_ADDR)
+#define TADR_SPIS_BASE      (SPI_SLAVE_BASE_ADDR)
+#define TADR_SPI2_BASE      (SPI3_BASE_ADDR)
+#define TOFF_SPI_CTRLR0         0x0000		/* (RW) SPI Control Register 0 */
+#define TOFF_SPI_CTRLR1         0x0004		/* (RW) SPI Control Register 1 */
+#define TOFF_SPI_SSIENR         0x0008		/* (RW) SPI Enable Register */
+#define TOFF_SPI_MWCR           0x000C		/* (RW) SPI Microwire Control Register */
+#define TOFF_SPI_SER            0x0010		/* (RW) SPI Slave Enable Register */
+#define TOFF_SPI_BAUDR          0x0014		/* (RW) SPI Baud Rate Select */
+#define TOFF_SPI_TXFTLR         0x0018		/* (RW) SPI Transmit FIFO Threshold Level */
+#define TOFF_SPI_RXFTLR         0x001C		/* (RW) SPI Receive FIFO Threshold Level */
+#define TOFF_SPI_TXFLR          0x0020		/* (RW) SPI Transmit FIFO Level Register */
+#define TOFF_SPI_RXFLR          0x0024		/* (RW) SPI Receive FIFO Level Register */
+#define TOFF_SPI_SR             0x0028		/* (RW) SPI Status Register */
+#define TOFF_SPI_IMR            0x002C		/* (RW) SPI Interrupt Mask Register */
+#define TOFF_SPI_ISR            0x0030		/* (RW) SPI Interrupt Status Register */
+#define TOFF_SPI_RISR           0x0034		/* (RW) SPI Raw Interrupt Status Register */
+#define TOFF_SPI_TXOICR         0x0038		/* (RW) SPI Transmit FIFO Overflow Interrupt Clear Register */
+#define TOFF_SPI_RXOICR         0x003C		/* (RW) SPI Receive FIFO Overflow Interrupt Clear Register */
+#define TOFF_SPI_RXUICR         0x0040		/* (RW) SPI Receive FIFO Underflow Interrupt Clear Register */
+#define TOFF_SPI_MSTICR         0x0044		/* (RW) SPI Multi-Master Interrupt Clear Register */
+#define TOFF_SPI_ICR            0x0048		/* (RW) SPI Interrupt Clear Register */
+#define TOFF_SPI_DMACR          0x004C		/* (RW) SPI DMA Control Register */
+#define TOFF_SPI_DMATDLR        0x0050		/* (RW) SPI DMA Transmit Data Level */
+#define TOFF_SPI_DMARDLR        0x0054		/* (RW) SPI DMA Receive Data Level */
+#define TOFF_SPI_IDR            0x0058		/* (RW) SPI Identification Register */
+#define TOFF_SPI_SSIC_VER_ID    0x005C		/* (RW) SPI DWC_ssi component version */
+#define TOFF_SPI_DR             0x0060		/* (RW) SPI Data Register 0-35 */
+#define TOFF_SPI_RX_SAMPL_DELAY 0x00F0		/* (RW) SPI RX Sample Delay Register */
+#define TOFF_SPI_SPI_CTRLR0     0x00F4		/* (RW) SPI SPI Control Register */
+#define TOFF_SPI_XIP_MODE_BITS  0x00FC		/* (RW) SPI XIP Mode bits */
+#define TOFF_SPI_XIP_INCR_INST  0x0100		/* (RW) SPI XIP INCR transfer opcode */
+#define TOFF_SPI_XIP_WRAP_INST  0x0104		/* (RW) SPI XIP WRAP transfer opcode */
+#define TOFF_SPI_XIP_CTRL       0x0108		/* (RW) SPI XIP Control Register */
+#define TOFF_SPI_XIP_SER        0x010C		/* (RW) SPI XIP Slave Enable Register */
+#define TOFF_SPI_XRXOICR        0x0110		/* (RW) SPI XIP Receive FIFO Overflow Interrupt Clear Register */
+#define TOFF_SPI_XIP_CNT_TIMOUT 0x0114		/* (RW) SPI XIP time out register for continuous transfers */
+#define TOFF_SPI_ENDIAN         0x0118
+
+#endif /* _KENDRYTE_K210_H_ */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target.tf
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target.tf	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target.tf	(revision 453)
@@ -0,0 +1,90 @@
+$ 
+$ 		パス2のターゲット依存テンプレート（K210用）
+$ 
+
+$ 
+$  有効な割込み番号，割込みハンドラ番号
+$ 
+$INTNO_VALID = RANGE(0, (TMAX_INTNO-1))$
+$INHNO_VALID = INTNO_VALID$
+
+$ 
+$  ATT_ISRで使用できる割込み番号とそれに対応する割込みハンドラ番号
+$ 
+$INTNO_ATTISR_VALID = INTNO_VALID$
+$INHNO_ATTISR_VALID = INHNO_VALID$
+
+$ 
+$  DEF_INT／DEF_EXCで使用できる割込みハンドラ番号／CPU例外ハンドラ番号
+$ 
+$INHNO_DEFINH_VALID = INTNO_VALID$
+$EXCNO_DEFEXC_VALID = INHNO_VALID$
+
+$ 
+$  CFG_INTで使用できる割込み番号と割込み優先度
+$ 
+$INTNO_CFGINT_VALID = INTNO_VALID$
+$INTPRI_CFGINT_VALID = { -7,-6,...,-1 }$
+
+$ 
+$  標準テンプレートファイルのインクルード
+$ 
+$INCLUDE "kernel/kernel.tf"$
+
+/*$NL$
+$SPC$*  Target-dependent Definitions (HIFIVE1)$NL$
+$SPC$*/$NL$
+$NL$
+
+$ 
+$  ベクターテーブル
+$ 
+$NL$
+$cfgint_num = TMAX_INTNO$
+
+const FP _kernel_vector_table[
+	$cfgint_num$
+] = {$NL$ 
+
+$FOREACH inhno INTNO_VALID$
+	$IF LENGTH(INH.INHNO[inhno])$
+		$TAB$(FP)(_kernel_
+		$INH.INTHDR[inhno]$_
+		$INH.INHNO[inhno]$),
+	$ELSE$
+		$TAB$(FP)(_kernel_default_plic_handler),
+	$END$
+	$SPC$$FORMAT("/* %d */", +inhno)$$NL$
+$END$
+
+$NL$};$NL$
+$NL$
+
+$ 
+$   CFG_INTのターゲット依存のエラーチェックと_kernel_bitpat_cfgintの生成
+$ 
+$bitpat_cfgint_num = 0$
+$bitpat_cfgint = 0$
+
+const uint32_t	_kernel_bitpat_cfgint[
+$IF (TMAX_INTNO & 0x0f) == 0x00 $
+	$bitpat_cfgint_num = (TMAX_INTNO >> 5)$
+$ELSE$
+	$bitpat_cfgint_num = (TMAX_INTNO >> 5) + 1$
+$END$
+	$bitpat_cfgint_num$
+] = {$NL$
+$FOREACH num RANGE(0,(bitpat_cfgint_num-1))$
+$   //boost のバージョンによって挙動が変わるための対策
+$   //http://www.toppers.jp/TOPPERS-USERS/201004/msg00034.html
+	$bitpat_cfgint = 1-1$
+	$FOREACH inhno RANGE(num*32, (num*32)+31)$
+		$IF LENGTH(INH.INHNO[inhno])$
+			$bitpat_cfgint = bitpat_cfgint | (1 << (inhno & 0x01f))$
+		$END$
+	$END$
+	$TAB$UINT32_C($FORMAT("0x%08x", bitpat_cfgint)$), $NL$
+$END$
+
+$NL$};$NL$
+$NL$
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_cfg1_out.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_cfg1_out.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_cfg1_out.h	(revision 453)
@@ -0,0 +1,9 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *		cfg1_out.cのリンクに必要なスタブの定義
+ */
+
+#include "riscv_gcc/prc_cfg1_out.h"
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_check.tf
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_check.tf	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_check.tf	(revision 453)
@@ -0,0 +1,8 @@
+$ 
+$ 		パス3のターゲット依存テンプレート（K210用）
+$ 
+
+$ 
+$  標準テンプレートファイルのインクルード
+$ 
+$INCLUDE "kernel/kernel_check.tf"$
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_config.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_config.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_config.c	(revision 453)
@@ -0,0 +1,243 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		ターゲット依存モジュール（K210用）
+ */
+
+#include "kernel_impl.h"
+#include <sil.h>
+
+#include "target_syssvc.h"
+#include "target_serial.h"
+
+/*
+ *  MACHINE割込みから割込みハンドラを呼び出す
+ */
+static void
+machine_interrupt(unsigned long mcause, void *p_excinf)
+{
+	uint32_t hart_id = read_csr(mhartid);
+	uint32_t int_num = sil_rew_mem((uint32_t *)(TADR_PLIC_BASE+TOFF_PLIC_CLAIM+(hart_id * NUM_PLIC_THRESHOLD)));
+	uint8_t  threshold = (uint8_t)current_ithreshold();
+	void (*volatile handler)(void);
+	uint8_t  priority;
+
+	if(int_num < TMAX_INTNO){
+		if((handler = (void (*volatile)(void))vector_table[int_num]) != NULL){
+			priority = current_ipriority(int_num);
+			set_ithreshold((uint32_t)priority);
+			set_csr(mie, kernel_mie);
+			sil_wrw_mem((uint32_t *)(TADR_PLIC_BASE+TOFF_PLIC_CLAIM+(hart_id * NUM_PLIC_THRESHOLD)), int_num);
+			handler();
+			clear_csr(mie, KERNEL_MIE);
+			set_ithreshold((uint32_t)threshold);
+		}
+	}
+	else{
+		syslog(LOG_EMERG, "Illegal global interrupt NO = %d", int_num);
+		sil_wrw_mem((uint32_t *)(TADR_PLIC_BASE+TOFF_PLIC_CLAIM+(hart_id * NUM_PLIC_THRESHOLD)), int_num);
+	}
+}
+
+/*
+ *  ターゲット依存の初期化
+ */
+void
+target_initialize(void)
+{
+	extern void	hardware_init_hook(void);
+	void (*volatile fp)(void) = hardware_init_hook;
+	unsigned long hart_id = read_csr(mhartid);
+	uint32_t i, off, len;
+
+	if(hart_id == 0){
+		/*
+		 *  hardware_init_hookへのポインタを，一旦volatile指定のあるfpに代
+		 *  入してから使うのは，0との比較が最適化で削除されないようにするた
+		 *  めである．
+		 */
+		if (fp != 0) {
+			(*fp)();
+		}
+
+		/*
+		 *  プロセッサ依存の初期化
+		 */
+		prc_initialize();
+
+		/*
+		 *  バナー出力用のシリアル初期化
+		 */
+		target_uart_init(SIO_PORTID);
+	}
+
+	/*
+	 *  割込み関連の初期化
+	 *
+	 *  割込みレベルテーブルをHIに設定する．
+	 *  PLICに対して割込み禁止、レベルを0、スレシュホールドを0に設定する．
+	 */
+	off = TOFF_PLIC_ENABLE + (hart_id * (NUM_PLIC_ENABLE / 8));
+	len = (TMAX_INTNO + 8) / 8;
+	for(i = 0 ; i < len ; i += 4){
+		sil_wrw_mem((uint32_t *)(TADR_PLIC_BASE + off + i), 0);
+	}
+
+	/*
+	 *  割込みスレシュホールドを0に設定
+	 */
+	off = (TOFF_PLIC_THRESHOLD + (hart_id * NUM_PLIC_THRESHOLD));
+	sil_wrw_mem((uint32_t *)(TADR_PLIC_BASE+off), 0);
+
+	if(hart_id == 0){
+		/*
+		 *  割込み優先度を0に設定
+		 */
+		len = (TMAX_INTNO + 1) * sizeof(uint32_t);
+		for(i = 0 ; i < len ; i += sizeof(uint32_t)){
+			sil_wrw_mem((uint32_t *)(TADR_PLIC_BASE + TOFF_PLIC_PRIORITY + i), 0);
+		}
+	}
+	else{
+		for(;;){
+			Asm("wfi":::"memory");
+		}
+	}
+
+	/*
+	 *  MACHINE割込み設定
+	 */
+	x_machine_inh(IRQ_MACHINE_EXTERNAL, (FP)machine_interrupt);
+}
+
+/*
+ *  ターゲット依存の終了処理
+ */
+void
+target_exit(void)
+{
+	unsigned long hart_id = read_csr(mhartid);
+	uint32_t i, off, len;
+
+	/*
+	 *  プロセッサ依存の終了処理
+	 */
+	prc_terminate();
+
+	/*
+	 *  すべての割込みをマスクする．
+	 */
+	off = TOFF_PLIC_ENABLE + (hart_id * (NUM_PLIC_ENABLE / 8));
+	len = (TMAX_INTNO + 8) / 8;
+	for(i = 0 ; i < len ; i += 4){
+		sil_wrw_mem((uint32_t *)(TADR_PLIC_BASE + off + i), 0);
+	}
+
+	/*
+	 *  開発環境依存の終了処理
+	 */
+	while(1);
+}
+
+/*
+ *  イレギュラーなPDIC割込み処理
+ */
+void
+default_plic_handler(void)
+{
+	syslog(LOG_EMERG, "\nUnregistered plic Interrupt occurs.");
+
+	target_exit();
+}
+
+/*
+ *  システムログの低レベル出力のための文字出力
+ */
+void
+target_fput_log(char c)
+{
+	if (c == '\n') {
+		sio_pol_snd_chr('\r', SIO_PORTID);
+	}
+	sio_pol_snd_chr(c, SIO_PORTID);
+}
+
+/*
+ *  割込み要求ラインの属性の設定
+ *
+ *  ASPカーネルでの利用を想定して，パラメータエラーはアサーションでチェッ
+ *  クしている．cfg_intサービスコールを設ける場合には，エラーを返すよう
+ *  にすべきであろう．
+ */
+void
+x_config_int(INTNO intno, ATR intatr, PRI intpri)
+{
+	uint32_t	priority;
+
+	assert(VALID_INTNO_CFGINT(intno));
+	assert(TIRQ_NMI <= intpri && intpri <= TIRQ_LEVEL1);
+	priority = intpri - TIRQ_NMI;
+
+	/*
+	 *  割込みのマスク
+	 *
+	 *  割込みを受け付けたまま，レベルトリガ／エッジトリガの設定や，割
+	 *  込み優先度の設定を行うのは危険なため，割込み属性にかかわらず，
+	 *  一旦マスクする．
+	 */
+	(void) x_disable_int(intno);
+
+	/*
+	 *  割込み優先度の設定
+	 */
+	set_ipriority(intno, priority);
+
+	/*
+	 *  割込みのマスク解除（必要な場合）
+ 	 */
+	if ((intatr & TA_ENAINT) != 0U) {
+		(void) x_enable_int(intno);
+	}
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_config.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_config.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_config.h	(revision 453)
@@ -0,0 +1,394 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		ターゲット依存モジュール（K210用）
+ *
+ *  カーネルのターゲット依存部のインクルードファイル．kernel_impl.hの
+ *  ターゲット依存部の位置付けとなる．
+ */
+
+#ifndef TOPPERS_TARGET_CONFIG_H
+#define TOPPERS_TARGET_CONFIG_H
+
+/*
+ *  ターゲットシステムのハードウェア資源の定義
+ */
+#include "kendryte-k210.h"
+
+/*
+ *  ターゲット定義のオブジェクト属性
+ */
+#define TARGET_INHATR	TA_NONKERNEL	/* カーネル管理外の割込み */
+
+/*
+ *  エラーチェック方法の指定
+ */
+#define CHECK_STKSZ_ALIGN	8	/* スタックサイズのアライン単位 */
+#define CHECK_FUNC_ALIGN	2	/* 関数のアライン単位 */
+#define CHECK_FUNC_NONNULL		/* 関数の非NULLチェック */
+#define CHECK_STACK_ALIGN	8	/* スタック領域のアライン単位 */
+#define CHECK_STACK_NONNULL		/* スタック領域の非NULLチェック */
+#define CHECK_MPF_ALIGN		4	/* 固定長メモリプール領域のアライン単位 */
+#define CHECK_MPF_NONNULL		/* 固定長メモリプール領域の非NULLチェック */
+#define CHECK_MB_ALIGN		4	/* 管理領域のアライン単位 */
+
+/*
+ *  トレースログに関する設定
+ */
+#ifdef TOPPERS_ENABLE_TRACE
+#include "logtrace/trace_config.h"
+#endif /* TOPPERS_ENABLE_TRACE */
+
+/*
+ *  デフォルトの非タスクコンテキスト用のスタック領域の定義
+ */
+#define DEFAULT_ISTKSZ		0x4000U
+//#define DEFAULT_ISTK		(void *)(RAM_BASE_ADDR + RAM_SIZE - DEFAULT_ISTKSZ * 2)
+
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  割込み番号の範囲の判定
+ */
+#define VALID_INTNO(intno)          ((1 <= (intno)) && ((intno) <= TMAX_INTNO))
+#define	VALID_INTNO_CREISR(intno)	VALID_INTNO(intno)
+#define VALID_INTNO_DISINT(intno)	VALID_INTNO(intno)
+#define VALID_INTNO_CFGINT(intno)	VALID_INTNO(intno)
+
+/*
+ *  PLIC THRESHOLD（ハードウェアの割込み優先度マスク，内部表現）の現在値の読出し
+ */
+Inline uint32_t
+current_ithreshold(void)
+{
+	uint32_t hard_id = read_csr(mhartid);
+	uint32_t off = TOFF_PLIC_THRESHOLD + (hard_id * NUM_PLIC_THRESHOLD);
+	return sil_rew_mem((uint32_t *)(TADR_PLIC_BASE+off));
+}
+
+/*
+ *  PLIC THRESHOLD（ハードウェアの割込み優先度マスク，内部表現）の現在値の設定
+ */
+Inline void
+set_ithreshold(uint32_t threshold)
+{
+	uint32_t hard_id = read_csr(mhartid);
+	uint32_t off = TOFF_PLIC_THRESHOLD + (hard_id * NUM_PLIC_THRESHOLD);
+	sil_wrw_mem((uint32_t *)(TADR_PLIC_BASE+off), threshold);
+}
+
+/*
+ *  PLIC 割込み優先度（ハードウェアの割込み優先度マスク，内部表現）の現在値の読出し
+ */
+Inline uint32_t
+current_ipriority(INTNO intno)
+{
+	uint32_t off = TOFF_PLIC_PRIORITY + (intno * sizeof(uint32_t));
+	return sil_rew_mem((uint32_t *)(TADR_PLIC_BASE+off));
+}
+
+/*
+ *  PLIC 割込み優先度（ハードウェアの割込み優先度マスク，内部表現）の現在値の設定
+ */
+Inline void
+set_ipriority(INTNO intno, uint32_t priority)
+{
+	uint32_t off = TOFF_PLIC_PRIORITY + (intno * sizeof(uint32_t));
+	sil_wrw_mem((uint32_t *)(TADR_PLIC_BASE+off), (uint32_t)priority);
+}
+
+/*
+ *  PLIC割込みハンドラテーブル
+ */
+extern const FP vector_table[];
+
+/*
+ *  割込み属性が設定されているかを判別するための変数（kernel_cfg.c）
+ */
+extern const uint32_t	bitpat_cfgint[];
+
+/*
+ *  割込み要求禁止フラグのセット
+ *
+ *  割込み属性が設定されていない割込み要求ラインに対して割込み要求禁止
+ *  フラグをセットしようとした場合には，falseを返す．
+ */
+Inline bool_t
+x_disable_int(INTNO intno)
+{
+	unsigned long hart_id = read_csr(mhartid);
+	uint32_t	bitpat = 1 << (intno & 0x1f);
+	uint32_t    bitpno = intno >> 5;
+	uint32_t	off = TOFF_PLIC_ENABLE + (hart_id * NUM_PLIC_ENABLE) + ((intno / 32) * 4);
+
+	if ((bitpat_cfgint[bitpno] & bitpat) == 0U) {
+		return(false);
+	}
+	sil_wrw_mem((uint32_t *)(TADR_PLIC_BASE+off),
+		(sil_rew_mem((uint32_t *)(TADR_PLIC_BASE+off)) & ~(1 << (intno % 32))));
+	return(true);
+}
+
+
+#define t_disable_int(intno)	x_disable_int(intno)
+#define i_disable_int(intno)	x_disable_int(intno)
+
+/*
+ *  割込み要求禁止フラグのクリア
+ *
+ *  割込み属性が設定されていない割込み要求ラインに対して割込み要求禁止
+ *  フラグをクリアしようとした場合には，falseを返す．
+ */
+Inline bool_t
+x_enable_int(INTNO intno)
+{
+	unsigned long hart_id = read_csr(mhartid);
+	uint32_t	bitpat = 1 << (intno & 0x1f);
+	uint32_t    bitpno = intno >> 5;
+	uint32_t	off = TOFF_PLIC_ENABLE + (hart_id * (NUM_PLIC_ENABLE / 8)) + ((intno / 32) * 4);
+
+	if ((bitpat_cfgint[bitpno] & bitpat) == 0U) {
+		return(false);
+	}
+
+	sil_wrw_mem((uint32_t *)(TADR_PLIC_BASE+off),
+		(sil_rew_mem((uint32_t *)(TADR_PLIC_BASE+off)) | (1 << (intno % 32))));
+	return(true);
+}
+
+#define t_enable_int(intno)		x_enable_int(intno)
+#define i_enable_int(intno)		x_enable_int(intno)
+
+/*
+ *  割込み要求のクリア
+ */
+Inline void
+x_clear_int(INTNO intno)
+{
+}
+
+#define t_clear_int(intno)		x_clear_int(intno)
+#define i_clear_int(intno)		x_clear_int(intno)
+
+/*
+ *  割込み要求のチェック
+ */
+Inline bool_t
+x_probe_int(INTNO intno)
+{
+	unsigned long hart_id = read_csr(mhartid);
+	uint32_t off = TOFF_PLIC_ENABLE + (hart_id * NUM_PLIC_ENABLE) + (intno >> 3);
+
+	return((sil_reb_mem((uint8_t *)(TADR_PLIC_BASE+off)) & (1 << (intno & 7))) != 0);
+}
+
+#define t_probe_int(intno)		x_probe_int(intno)
+#define i_probe_int(intno)		x_probe_int(intno)
+
+/*
+ *  割込みハンドラの設定
+ *
+ *  ベクトル番号inhnoの割込みハンドラの出入口処理の番地をint_entryに設
+ *  定する．
+ */
+Inline void
+x_define_inh(INHNO inhno, FP int_entry)
+{
+}
+
+
+/*
+ *  割込み要求ラインの属性の設定
+ *
+ *  DVE-68K/40のIRCでは，割込み要求ラインの割込み優先度にNMIを指定する
+ *  ことができため，-7を与えるとNMIに設定されることとする（ターゲット定
+ *  義の拡張）．
+ */
+extern void	x_config_int(INTNO intno, ATR intatr, PRI intpri);
+
+/*
+ *  割込みハンドラの入口で必要なIRC操作
+ *
+ *  エッジトリガの場合には，割込み要求をクリアする．エッジトリガかレベ
+ *  ルトリガかが設定できる場合も，現在の設定値を見ずにクリアしている．
+ *  レベルトリガの場合もクリア処理をして差し支えないが，最適化で消える
+ *  ことを期待して，クリアしないこととしている．
+ */
+Inline void
+i_begin_int(INTNO intno)
+{
+}
+
+/*
+ *  割込みハンドラの出口で必要なIRC操作
+ *
+ *  K210では必要なIRC操作はない．
+ */
+Inline void
+i_end_int(INTNO intno)
+{
+}
+
+/*
+ *  割込みハンドラの出入口処理の生成
+ */
+
+/*
+ *  割込みハンドラの出入口処理のラベルを作るマクロ
+ */
+#define INT_ENTRY(inhno, inthdr)	_kernel_##inthdr##_##inhno
+
+/*
+ *  LOG_INH_ENTERがマクロ定義されている場合に，CALL_LOG_INH_ENTERを，
+ *  inhno_numをパラメータとしてlog_inh_enterを呼び出すアセンブリ言語コー
+ *  ドにマクロ定義する．
+ */
+#ifdef LOG_INH_ENTER
+
+#define CALL_LOG_INH_ENTER(inhno_num) \
+"	li a0," #inhno_num "			\n"  /* inhno_numをパラメータに */ \
+"	jal _kernel_log_inh_enter		\n"  /* log_inh_enterを呼び出す */
+
+#else /* LOG_INH_ENTER */
+#define CALL_LOG_INH_ENTER(inhno_num)
+#endif /* LOG_INH_ENTER */
+
+#ifdef LOG_INH_LEAVE
+
+/*
+ *  CALL_LOG_INH_LEAVEを，inhno_numをパラメータとしてlog_inh_leaveを呼
+ *  び出すアセンブリ言語コードにマクロ定義する．
+ */
+#define CALL_LOG_INH_LEAVE(inhno_num) \
+"	li a0," #inhno_num "			\n"  /* inhno_numをパラメータに */ \
+"	jal _kernel_log_inh_leave		\n"  /* log_inh_leaveを呼び出す */
+
+/*
+ *  LOG_INH_LEAVEがマクロ定義されている場合の割込みハンドラの出入口処理．
+ *  割込みハンドラをサブルーチンコールし，戻ってきたら，トレースログの
+ *  取得後，呼び出し先に分岐する．
+ */
+#define INTHDR_ENTRY(inhno, inhno_num, inthdr) \
+extern void _kernel_##inthdr##_##inhno(void); \
+asm(".text							\n" \
+"_kernel_" #inthdr "_" #inhno ":	\n" \
+"	addi sp, sp, -32				\n"	 /* 保存領域を確保 */ \
+"	sd ra, 24(sp)					\n"	 /* return addressをセーブ */ \
+	CALL_LOG_INH_ENTER(inhno_num) \
+"	jal " #inthdr "				\n"  /* 割込みハンドラを呼び出す */ \
+	CALL_LOG_INH_LEAVE(inhno_num) \
+"	ld ra, 24(sp)					\n"	 /* return addressをリストア */ \
+"	addi sp, sp, 32					\n"	 /* 保存領域を開放 */ \
+"	ret								\n");/* リターン */
+
+
+#elif defined(LOG_INH_ENTER)
+
+/*
+ *  LOG_INH_LEAVEがマクロ定義されていなくてLOG_INH_ENTERが定義されている
+ *  場合の割込みハンドラの出入口処理．log_inh_enterを実行後、
+ *  ハンドラを呼び出し、呼び出し先に分岐する．
+ */
+#define INTHDR_ENTRY(inhno, inhno_num, inthdr) \
+extern void _kernel_##inthdr##_##inhno(void); \
+asm(".text							\n" \
+"_kernel_" #inthdr "_" #inhno ":	\n" \
+"	addi sp, sp, -32				\n"	 /* 保存領域を確保 */ \
+"	sd ra, 24(sp)					\n"	 /* return addressをセーブ */ \
+	CALL_LOG_INH_ENTER(inhno_num) \
+"	jal " #inthdr "					\n"	 /* 割込みハンドラへ分岐 */ \
+"	ld ra, 24(sp)					\n"	 /* return addressをリストア */ \
+"	addi sp, sp, 32					\n"	 /* 保存領域を開放 */ \
+"	ret								\n");/* リターン */
+
+#else
+
+/*
+ *  LOG_INH_ENTER/LOG_INH_LEAVEがマクロ定義されていない場合、raを保持したまま
+ *  ハンドラにジャンプする．
+ */
+#define INTHDR_ENTRY(inhno, inhno_num, inthdr) \
+extern void _kernel_##inthdr##_##inhno(void); \
+asm(".text							\n" \
+"_kernel_" #inthdr "_" #inhno ":	\n" \
+"	j " #inthdr "					\n");	 /* 割込みハンドラへ分岐 */ \
+
+#endif /* LOG_INH_LEAVE */
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  ターゲットシステム依存の初期化
+ */
+extern void	target_initialize(void);
+
+/*
+ *  ターゲットシステムの終了
+ *
+ *  システムを終了する時に使う．
+ */
+extern void	target_exit(void) NoReturn;
+
+/*
+ *  イレギュラーなPDIC割込み処理
+ */
+extern void default_plic_handler(void);
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+/*
+ *  微少時間待ちのための定義（本来はSILのターゲット依存部）
+ */
+#define SIL_DLY_TIM1    1
+#define SIL_DLY_TIM2    5
+
+/*
+ *  プロセッサ依存モジュール（RISC-V用）
+ */
+#include "riscv_gcc/prc_config.h"
+
+#endif /* TOPPERS_TARGET_CONFIG_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_inithook.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_inithook.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_inithook.c	(revision 453)
@@ -0,0 +1,614 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015      by 3rd Designing Center
+ *              Imageing System Development Division RICOH COMPANY, LTD.
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/* Copyright 2018 Canaan Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string.h>
+#include "kendryte-k210.h"
+#include "target_syssvc.h"
+
+/*
+ *  SIL関数のマクロ定義
+ */
+#define sil_orw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) | (b))
+#define sil_andw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) & ~(b))
+#define sil_modw_mem(a, b, c)	sil_wrw_mem((a), (sil_rew_mem(a) & (~b)) | (c))
+
+/*
+ *  PLL定義
+ */
+#define SYSCTL_PLL0             0
+#define SYSCTL_PLL1             1
+#define SYSCTL_PLL2             2
+
+/*
+ *  初期化プログラム（K210用）
+ */
+#define FPIOA_TIE_EN            0x01000000
+#define FPIOA_TIE_VAL           0x02000000
+
+
+static const uint32_t function_config[FUNC_MAX] = {
+	(0x00900000+FUNC_JTAG_TCLK),
+	(0x00900000+FUNC_JTAG_TDI),
+	(0x00900000+FUNC_JTAG_TMS),
+	(0x00001f00+FUNC_JTAG_TDO),
+	(0x00b03f00+FUNC_SPI0_D0),
+	(0x00b03f00+FUNC_SPI0_D1),
+	(0x00b03f00+FUNC_SPI0_D2),
+	(0x00b03f00+FUNC_SPI0_D3),
+	(0x00b03f00+FUNC_SPI0_D4),
+	(0x00b03f00+FUNC_SPI0_D5),
+	(0x00b03f00+FUNC_SPI0_D6),
+	(0x00b03f00+FUNC_SPI0_D7),
+	(0x00001f00+FUNC_SPI0_SS0),
+	(0x00001f00+FUNC_SPI0_SS1),
+	(0x00001f00+FUNC_SPI0_SS2),
+	(0x00001f00+FUNC_SPI0_SS3),
+	(0x03900000+FUNC_SPI0_ARB),
+	(0x00001f00+FUNC_SPI0_SCLK),
+	(0x00900000+FUNC_UARTHS_RX),
+	(0x00001f00+FUNC_UARTHS_TX),
+	(0x00900000+FUNC_RESV6),
+	(0x00900000+FUNC_RESV7),
+	(0x00001f00+FUNC_CLK_SPI1),
+	(0x00001f00+FUNC_CLK_I2C1),
+	(0x00901f00+FUNC_GPIOHS0),
+	(0x00901f00+FUNC_GPIOHS1),
+	(0x00901f00+FUNC_GPIOHS2),
+	(0x00901f00+FUNC_GPIOHS3),
+	(0x00901f00+FUNC_GPIOHS4),
+	(0x00901f00+FUNC_GPIOHS5),
+	(0x00901f00+FUNC_GPIOHS6),
+	(0x00901f00+FUNC_GPIOHS7),
+
+	(0x00901f00+FUNC_GPIOHS8),
+	(0x00901f00+FUNC_GPIOHS9),
+	(0x00901f00+FUNC_GPIOHS10),
+	(0x00901f00+FUNC_GPIOHS11),
+	(0x00901f00+FUNC_GPIOHS12),
+	(0x00901f00+FUNC_GPIOHS13),
+	(0x00901f00+FUNC_GPIOHS14),
+	(0x00901f00+FUNC_GPIOHS15),
+	(0x00901f00+FUNC_GPIOHS16),
+	(0x00901f00+FUNC_GPIOHS17),
+	(0x00901f00+FUNC_GPIOHS18),
+	(0x00901f00+FUNC_GPIOHS19),
+	(0x00901f00+FUNC_GPIOHS20),
+	(0x00901f00+FUNC_GPIOHS21),
+	(0x00901f00+FUNC_GPIOHS22),
+	(0x00901f00+FUNC_GPIOHS23),
+	(0x00901f00+FUNC_GPIOHS24),
+	(0x00901f00+FUNC_GPIOHS25),
+	(0x00901f00+FUNC_GPIOHS26),
+	(0x00901f00+FUNC_GPIOHS27),
+	(0x00901f00+FUNC_GPIOHS28),
+	(0x00901f00+FUNC_GPIOHS29),
+	(0x00901f00+FUNC_GPIOHS30),
+	(0x00901f00+FUNC_GPIOHS31),
+	(0x00901f00+FUNC_GPIO0),
+	(0x00901f00+FUNC_GPIO1),
+	(0x00901f00+FUNC_GPIO2),
+	(0x00901f00+FUNC_GPIO3),
+	(0x00901f00+FUNC_GPIO4),
+	(0x00901f00+FUNC_GPIO5),
+	(0x00901f00+FUNC_GPIO6),
+	(0x00901f00+FUNC_GPIO7),
+
+	(0x00900000+FUNC_UART1_RX),
+	(0x00001f00+FUNC_UART1_TX),
+	(0x00900000+FUNC_UART2_RX),
+	(0x00001f00+FUNC_UART2_TX),
+	(0x00900000+FUNC_UART3_RX),
+	(0x00001f00+FUNC_UART3_TX),
+	(0x00b03f00+FUNC_SPI1_D0),
+	(0x00b03f00+FUNC_SPI1_D1),
+	(0x00b03f00+FUNC_SPI1_D2),
+	(0x00b03f00+FUNC_SPI1_D3),
+	(0x00b03f00+FUNC_SPI1_D4),
+	(0x00b03f00+FUNC_SPI1_D5),
+	(0x00b03f00+FUNC_SPI1_D6),
+	(0x00b03f00+FUNC_SPI1_D7),
+	(0x00001f00+FUNC_SPI1_SS0),
+	(0x00001f00+FUNC_SPI1_SS1),
+	(0x00001f00+FUNC_SPI1_SS2),
+	(0x00001f00+FUNC_SPI1_SS3),
+	(0x03900000+FUNC_SPI1_ARB),
+	(0x00001f00+FUNC_SPI1_SCLK),
+	(0x00b03f00+FUNC_SPI_SLAVE_D0),
+	(0x00900000+FUNC_SPI_SLAVE_SS),
+	(0x00900000+FUNC_SPI_SLAVE_SCLK),
+	(0x00001f00+FUNC_I2S0_MCLK),
+	(0x00001f00+FUNC_I2S0_SCLK),
+	(0x00001f00+FUNC_I2S0_WS),
+	(0x00900000+FUNC_I2S0_IN_D0),
+	(0x00900000+FUNC_I2S0_IN_D1),
+	(0x00900000+FUNC_I2S0_IN_D2),
+	(0x00900000+FUNC_I2S0_IN_D3),
+	(0x00001f00+FUNC_I2S0_OUT_D0),
+	(0x00001f00+FUNC_I2S0_OUT_D1),
+
+	(0x00001f00+FUNC_I2S0_OUT_D2),
+	(0x00001f00+FUNC_I2S0_OUT_D3),
+	(0x00001f00+FUNC_I2S1_MCLK),
+	(0x00001f00+FUNC_I2S1_SCLK),
+	(0x00001f00+FUNC_I2S1_WS),
+	(0x00900000+FUNC_I2S1_IN_D0),
+	(0x00900000+FUNC_I2S1_IN_D1),
+	(0x00900000+FUNC_I2S1_IN_D2),
+	(0x00900000+FUNC_I2S1_IN_D3),
+	(0x00001f00+FUNC_I2S1_OUT_D0),
+	(0x00001f00+FUNC_I2S1_OUT_D1),
+	(0x00001f00+FUNC_I2S1_OUT_D2),
+	(0x00001f00+FUNC_I2S1_OUT_D3),
+	(0x00001f00+FUNC_I2S2_MCLK),
+	(0x00001f00+FUNC_I2S2_SCLK),
+	(0x00001f00+FUNC_I2S2_WS),
+	(0x00900000+FUNC_I2S2_IN_D0),
+	(0x00900000+FUNC_I2S2_IN_D1),
+	(0x00900000+FUNC_I2S2_IN_D2),
+	(0x00900000+FUNC_I2S2_IN_D3),
+	(0x00001f00+FUNC_I2S2_OUT_D0),
+	(0x00001f00+FUNC_I2S2_OUT_D1),
+	(0x00001f00+FUNC_I2S2_OUT_D2),
+	(0x00001f00+FUNC_I2S2_OUT_D3),
+	(0x00000000+FUNC_RESV0),
+	(0x00000000+FUNC_RESV1),
+	(0x00000000+FUNC_RESV2),
+	(0x00000000+FUNC_RESV3),
+	(0x00000000+FUNC_RESV4),
+	(0x00000000+FUNC_RESV5),
+	(0x00991000+FUNC_I2C0_SCLK),
+	(0x00991000+FUNC_I2C0_SDA),
+
+	(0x00991000+FUNC_I2C1_SCLK),
+	(0x00991000+FUNC_I2C1_SDA),
+	(0x00991000+FUNC_I2C2_SCLK),
+	(0x00991000+FUNC_I2C2_SDA),
+	(0x00001f00+FUNC_CMOS_XCLK),
+	(0x00001f00+FUNC_CMOS_RST),
+	(0x00001f00+FUNC_CMOS_PWDN),
+	(0x00900000+FUNC_CMOS_VSYNC),
+	(0x00900000+FUNC_CMOS_HREF),
+	(0x00900000+FUNC_CMOS_PCLK),
+	(0x00900000+FUNC_CMOS_D0),
+	(0x00900000+FUNC_CMOS_D1),
+	(0x00900000+FUNC_CMOS_D2),
+	(0x00900000+FUNC_CMOS_D3),
+	(0x00900000+FUNC_CMOS_D4),
+	(0x00900000+FUNC_CMOS_D5),
+	(0x00900000+FUNC_CMOS_D6),
+	(0x00900000+FUNC_CMOS_D7),
+	(0x00993000+FUNC_SCCB_SCLK),
+	(0x00993000+FUNC_SCCB_SDA),
+	(0x00900000+FUNC_UART1_CTS),
+	(0x00900000+FUNC_UART1_DSR),
+	(0x00900000+FUNC_UART1_DCD),
+	(0x00900000+FUNC_UART1_RI),
+	(0x00900000+FUNC_UART1_SIR_IN),
+	(0x00001f00+FUNC_UART1_DTR),
+	(0x00001f00+FUNC_UART1_RTS),
+	(0x00001f00+FUNC_UART1_OUT2),
+	(0x00001f00+FUNC_UART1_OUT1),
+	(0x00001f00+FUNC_UART1_SIR_OUT),
+	(0x00001f00+FUNC_UART1_BAUD),
+	(0x00001f00+FUNC_UART1_RE),
+
+	(0x00001f00+FUNC_UART1_DE),
+	(0x00001f00+FUNC_UART1_RS485_EN),
+	(0x00900000+FUNC_UART2_CTS),
+	(0x00900000+FUNC_UART2_DSR),
+	(0x00900000+FUNC_UART2_DCD),
+	(0x00900000+FUNC_UART2_RI),
+	(0x00900000+FUNC_UART2_SIR_IN),
+	(0x00001f00+FUNC_UART2_DTR),
+	(0x00001f00+FUNC_UART2_RTS),
+	(0x00001f00+FUNC_UART2_OUT2),
+	(0x00001f00+FUNC_UART2_OUT1),
+	(0x00001f00+FUNC_UART2_SIR_OUT),
+	(0x00001f00+FUNC_UART2_BAUD),
+	(0x00001f00+FUNC_UART2_RE),
+	(0x00001f00+FUNC_UART2_DE),
+	(0x00001f00+FUNC_UART2_RS485_EN),
+	(0x00900000+FUNC_UART3_CTS),
+	(0x00900000+FUNC_UART3_DSR),
+	(0x00900000+FUNC_UART3_DCD),
+	(0x00900000+FUNC_UART3_RI),
+	(0x00900000+FUNC_UART3_SIR_IN),
+	(0x00001f00+FUNC_UART3_DTR),
+	(0x00001f00+FUNC_UART3_RTS),
+	(0x00001f00+FUNC_UART3_OUT2),
+	(0x00001f00+FUNC_UART3_OUT1),
+	(0x00001f00+FUNC_UART3_SIR_OUT),
+	(0x00001f00+FUNC_UART3_BAUD),
+	(0x00001f00+FUNC_UART3_RE),
+	(0x00001f00+FUNC_UART3_DE),
+	(0x00001f00+FUNC_UART3_RS485_EN),
+	(0x00001f00+FUNC_TIMER0_TOGGLE1),
+	(0x00001f00+FUNC_TIMER0_TOGGLE2),
+
+	(0x00001f00+FUNC_TIMER0_TOGGLE3),
+	(0x00001f00+FUNC_TIMER0_TOGGLE4),
+	(0x00001f00+FUNC_TIMER1_TOGGLE1),
+	(0x00001f00+FUNC_TIMER1_TOGGLE2),
+	(0x00001f00+FUNC_TIMER1_TOGGLE3),
+	(0x00001f00+FUNC_TIMER1_TOGGLE4),
+	(0x00001f00+FUNC_TIMER2_TOGGLE1),
+	(0x00001f00+FUNC_TIMER2_TOGGLE2),
+	(0x00001f00+FUNC_TIMER2_TOGGLE3),
+	(0x00001f00+FUNC_TIMER2_TOGGLE4),
+	(0x00001f00+FUNC_CLK_SPI2),
+	(0x00001f00+FUNC_CLK_I2C2),
+	(0x00001f00+FUNC_INTERNAL0),
+	(0x00001f00+FUNC_INTERNAL1),
+	(0x00001f00+FUNC_INTERNAL2),
+	(0x00001f00+FUNC_INTERNAL3),
+	(0x00001f00+FUNC_INTERNAL4),
+	(0x00001f00+FUNC_INTERNAL5),
+	(0x00001f00+FUNC_INTERNAL6),
+	(0x00001f00+FUNC_INTERNAL7),
+	(0x00001f00+FUNC_INTERNAL8),
+	(0x00900000+FUNC_INTERNAL9),
+	(0x00900000+FUNC_INTERNAL10),
+	(0x00900000+FUNC_INTERNAL11),
+	(0x00900000+FUNC_INTERNAL12),
+	(0x00910000+FUNC_INTERNAL13),
+	(0x00991f00+FUNC_INTERNAL14),
+	(0x00900000+FUNC_INTERNAL15),
+	(0x00900000+FUNC_INTERNAL16),
+	(0x00900000+FUNC_INTERNAL17),
+	(0x00000000+FUNC_CONSTANT),
+	(0x00900000+FUNC_INTERNAL18),
+
+	(0x00001f00+FUNC_DEBUG0),
+	(0x00001f00+FUNC_DEBUG1),
+	(0x00001f00+FUNC_DEBUG2),
+	(0x00001f00+FUNC_DEBUG3),
+	(0x00001f00+FUNC_DEBUG4),
+	(0x00001f00+FUNC_DEBUG5),
+	(0x00001f00+FUNC_DEBUG6),
+	(0x00001f00+FUNC_DEBUG7),
+	(0x00001f00+FUNC_DEBUG8),
+	(0x00001f00+FUNC_DEBUG9),
+	(0x00001f00+FUNC_DEBUG10),
+	(0x00001f00+FUNC_DEBUG11),
+	(0x00001f00+FUNC_DEBUG12),
+	(0x00001f00+FUNC_DEBUG13),
+	(0x00001f00+FUNC_DEBUG14),
+	(0x00001f00+FUNC_DEBUG15),
+	(0x00001f00+FUNC_DEBUG16),
+	(0x00001f00+FUNC_DEBUG17),
+	(0x00001f00+FUNC_DEBUG18),
+	(0x00001f00+FUNC_DEBUG19),
+	(0x00001f00+FUNC_DEBUG20),
+	(0x00001f00+FUNC_DEBUG21),
+	(0x00001f00+FUNC_DEBUG22),
+	(0x00001f00+FUNC_DEBUG23),
+	(0x00001f00+FUNC_DEBUG24),
+	(0x00001f00+FUNC_DEBUG25),
+	(0x00001f00+FUNC_DEBUG26),
+	(0x00001f00+FUNC_DEBUG27),
+	(0x00001f00+FUNC_DEBUG28),
+	(0x00001f00+FUNC_DEBUG29),
+	(0x00001f00+FUNC_DEBUG30),
+	(0x00001f00+FUNC_DEBUG31),
+};
+
+static const uint8_t pll_table[3][4] = {
+	{1, 62,  2, 62},	/* PLL 0 */
+	{1, 46,  4, 46},	/* PLL 1 */
+	{1, 26, 15, 26},	/* PLL 0 */
+};
+
+/*
+ *  FPIOA初期化
+ */
+static ER
+fpioa_init(void)
+{
+    int i = 0;
+	uint32_t en[FUNC_MAX / 32];
+	uint32_t val[FUNC_MAX / 32];
+
+	/* Enable fpioa clock in system controller */
+	sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_CENT), SYSCTL_CLK_EN_CENT_APB0_CLK_EN);
+	sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_PERI), SYSCTL_CLK_EN_PERI_FPIOA_CLK_EN);
+
+	/* Initialize tie */
+	memset(en, 0, FUNC_MAX/8);
+	memset(val, 0, FUNC_MAX/8);
+
+	/* Set tie enable and tie value */
+	for(i = 0; i < FUNC_MAX; i++){
+		if((function_config[i] & FPIOA_TIE_EN) != 0)
+			en[i / 32] |= 1 << (i % 32);
+		if((function_config[i] & FPIOA_TIE_VAL) != 0)
+			val[i / 32] |= 1 << (i % 32);
+	}
+
+	/* Atomic write every 32bit register to fpioa function */
+	for(i = 0; i < FUNC_MAX / 32; i++){
+		/* Set value before enable */
+		sil_wrw_mem((uint32_t *)(TADR_FPIOA_BASE+TOFF_FPIOA_TIE_EN+i*4), en[i]);
+		sil_wrw_mem((uint32_t *)(TADR_FPIOA_BASE+TOFF_FPIOA_TIE_VAL+i*4), val[i]);
+	}
+    return E_OK;
+}
+
+/*
+ *  FPIOAハードウェア設定
+ */
+static ER
+fpioa_set_function_raw(int number, uint8_t function)
+{
+	uint32_t *p  = (uint32_t *)&function_config[function];
+	uint32_t off = TOFF_FPIOA_IO + number * sizeof(uint32_t);
+
+	/* Check parameters */
+	if(number < 0 || number >= FPIOA_NUM_IO || function >= FUNC_MAX)
+		return E_PAR;
+	sil_modw_mem((uint32_t *)(TADR_FPIOA_BASE+off), 0x00FFFFFF, (*p & 0x00FFFFFF));
+    return E_OK;
+}
+
+/*
+ *  FPIOAにファンクションを設定する
+ *  param1  number      The IO number
+ *  param2  function    The function enum number
+ *  return  0-OK
+ */
+ER
+fpioa_set_function(int number, uint8_t function)
+{
+	uint8_t i = 0;
+	/* Check parameters */
+	if(number < 0 || number >= FPIOA_NUM_IO || function >= FUNC_MAX)
+		return E_PAR;
+	if(function == FUNC_RESV0){
+		return fpioa_set_function_raw(number, FUNC_RESV0);
+	}
+	/* Compare all IO */
+	for(i = 0 ; i < FPIOA_NUM_IO ; i++){
+		if(((sil_rew_mem((uint32_t *)(TADR_FPIOA_BASE+TOFF_FPIOA_IO+i*4)) & FPIOA_CH_SEL) == function) && (i != number))
+			fpioa_set_function_raw(i, FUNC_RESV0);
+	}
+	return fpioa_set_function_raw(number, function);
+}
+
+/*
+ *  PLLクロック取得
+ */
+uint32_t
+get_pll_clock(uint8_t no)
+{
+	uint32_t pll, freq_in = 0, freq_out = 0;
+	uint32_t nr = 0, nf = 0, od = 0;
+	uint32_t select = 0;
+
+	switch(no){
+	case 0:		/* PLL0 */
+		pll     = sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_PLL0));
+		freq_in = SYSCTRL_CLOCK_FREQ_IN0;
+		nr      = (pll & SYSCTL_PLL_CLKR0) + 1;
+		nf      = ((pll & SYSCTL_PLL_CLKF0) >> 4) + 1;
+		od      = ((pll & SYSCTL_PLL_CLKOD0) >> 10) + 1;
+		break;
+	case 1:		/* PLL1 */
+		pll     = sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_PLL1));
+		freq_in = SYSCTRL_CLOCK_FREQ_IN0;
+		nr      = (pll & SYSCTL_PLL_CLKR1) + 1;
+		nf      = ((pll & SYSCTL_PLL_CLKF1) >> 4) + 1;
+		od      = ((pll & SYSCTL_PLL_CLKOD1) >> 10) + 1;
+		break;
+	case 2:		/* PLL2 */
+		pll     = sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_PLL2));
+		select  = (pll & SYSCTL_PLL_CKIN_SEL2) >> 26;
+		if(select == 0)
+			freq_in = SYSCTRL_CLOCK_FREQ_IN0;
+		else if(select == 1)
+			freq_in = get_pll_clock(0);
+		else if(select == 2)
+			freq_in = get_pll_clock(1);
+		nr      = (pll & SYSCTL_PLL_CLKR2) + 1;
+		nf      = ((pll & SYSCTL_PLL_CLKF2) >> 4) + 1;
+		od      = ((pll & SYSCTL_PLL_CLKOD2) >> 10) + 1;
+		break;
+	default:
+		break;
+	}
+	freq_out = (uint64_t)freq_in * nf / nr / od;
+	return freq_out;
+}
+
+/*
+ *  PLLロック判定
+ */
+static int
+pll_is_lock(uint8_t pll)
+{
+	uint32_t pll_lock = sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_PLL_LOCK));
+	if(pll == SYSCTL_PLL0)
+		return (pll_lock & SYSCTL_PLL_LOCK_LOCK0) == 3;
+	else if(pll == SYSCTL_PLL1)
+		return (pll_lock >> 8) & 1;
+	else if(pll == SYSCTL_PLL2)
+		return (pll_lock >> 16) & 1;
+	else
+	    return 0;
+}
+
+/*
+ *  PLL設定
+ */
+static uint32_t
+pll_set_freq(uint8_t pll, const uint8_t *conf)
+{
+	unsigned long base = TADR_SYSCTL_BASE;
+	uint32_t voff = TOFF_SYSCTL_PLL0;
+	uint32_t pll_value;
+
+	switch(pll){
+	case SYSCTL_PLL0:
+		voff = TOFF_SYSCTL_PLL0;
+		break;
+	case SYSCTL_PLL1:
+		voff = TOFF_SYSCTL_PLL1;
+		break;
+	case SYSCTL_PLL2:
+		voff = TOFF_SYSCTL_PLL2;
+		break;
+	default:
+		return 0;
+		break;
+    }
+
+    /*
+	 *  PLL0設定ならば、ACLKをINOに変更
+	 */
+    if(pll == SYSCTL_PLL0)
+		sil_modw_mem((uint32_t *)(base+TOFF_CLK_SEL0), SYSCTL_CLK_SEL0_ACLK_SEL, SYSCTL_CLK_SEL0_SOURCE_IN0);
+
+    /*
+	 *  PLL出力停止
+	 */
+	sil_andw_mem((uint32_t *)(base+voff), SYSCTL_PLL_OUT_EN0);
+
+    /*
+	 *  PLLパワーオフ
+	 */
+	sil_andw_mem((uint32_t *)(base+voff), SYSCTL_PLL_PWRD0);
+
+    /*
+	 *  PLL設定変更
+	 */
+	pll_value = sil_rew_mem((uint32_t *)(base+TOFF_SYSCTL_PLL0+pll*4));
+	if(pll == SYSCTL_PLL2){
+		pll_value &= SYSCTL_PLL_CKIN_SEL2;
+		pll_value |= SYSCTL_CLK_SEL0_SOURCE_IN0 << 22;
+	}
+	pll_value &= ~(SYSCTL_PLL_CLKR0 | SYSCTL_PLL_CLKF0 | SYSCTL_PLL_CLKOD0 | SYSCTL_PLL_BWADJ0);
+	pll_value |= conf[0] - 1;
+	pll_value |= (conf[1] - 1) << 4;
+	pll_value |= (conf[2] - 1) << 10;
+	pll_value |= (conf[3] - 1) << 14;
+	sil_wrw_mem((uint32_t *)(base+TOFF_SYSCTL_PLL0+pll*4), pll_value);
+
+    /*
+	 *  PLLパワーオン
+	 */
+	sil_orw_mem((uint32_t *)(base+voff), SYSCTL_PLL_PWRD0);
+	sil_dly_nse(1000);
+
+    /*
+	 *  PLLリセット
+	 */
+	sil_andw_mem((uint32_t *)(base+voff), SYSCTL_PLL_RESET0);
+	sil_orw_mem((uint32_t *)(base+voff), SYSCTL_PLL_RESET0);
+	sil_dly_nse(1000);
+	sil_andw_mem((uint32_t *)(base+voff), SYSCTL_PLL_RESET0);
+
+    /*
+	 *  PLLロック解除
+	 */
+    while (pll_is_lock(pll) == 0){
+		sil_orw_mem((uint32_t *)(base+TOFF_SYSCTL_PLL_LOCK), (SYSCTL_PLL_LOCK_SLIP_CLEAR0 << (pll*8)));
+	}
+
+    /*
+	 *  PLL出力開始
+	 */
+	sil_orw_mem((uint32_t *)(base+voff), SYSCTL_PLL_OUT_EN0);
+
+    /*
+	 *  PLL0設定ならば、ACLKをPLL0に変更
+	 */
+    if(pll == SYSCTL_PLL0)
+		sil_modw_mem((uint32_t *)(base+TOFF_CLK_SEL0), SYSCTL_CLK_SEL0_ACLK_SEL, SYSCTL_CLK_SEL0_SOURCE_PLL0);
+
+    return get_pll_clock(pll);
+}
+
+
+/*
+ *  低レベルのターゲット依存の初期化
+ *
+ *  スタートアップモジュールの中で，メモリの初期化の前に呼び出される．
+ */
+void hardware_init_hook(void)
+{
+	/*
+	 *  PLL設定
+	 */
+	pll_set_freq(SYSCTL_PLL0, &pll_table[SYSCTL_PLL0][0]);	/* 800000000 */
+	pll_set_freq(SYSCTL_PLL1, &pll_table[SYSCTL_PLL1][0]);	/* 300000000 */
+	pll_set_freq(SYSCTL_PLL2, &pll_table[SYSCTL_PLL2][0]);	/* 45158400 */
+
+	/*
+	 *  BANK6,7を1.8Vに設定
+	 */
+	sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_POWER_SEL),
+		SYSCTL_POWER_SEL_POWER_MODE_6);
+	sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_POWER_SEL),
+		SYSCTL_POWER_SEL_POWER_MODE_7);
+	/* Init FPIOA */
+	fpioa_init();
+	/*
+	 *  SYSCTLステータスをリセット
+	 */
+	sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_RST_STATUS),
+		 SYSCTL_RST_STATUS_RESET_STS_CLR);
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_kernel.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_kernel.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_kernel.h	(revision 453)
@@ -0,0 +1,74 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		kernel.hのターゲット依存部（K210用）
+ *
+ *  このインクルードファイルは，kernel.hでインクルードされる．他のファ
+ *  イルから直接インクルードすることはない．このファイルをインクルード
+ *  する前に，t_stddef.hがインクルードされるので，それらに依存してもよ
+ *  い．
+ */
+
+#ifndef TOPPERS_TARGET_KERNEL_H
+#define TOPPERS_TARGET_KERNEL_H
+
+/*
+ *  プロセッサで共通な定義
+ */
+#include "riscv_gcc/prc_kernel.h"
+
+/*
+ *  ターゲット依存部でサポートできる機能
+ */
+#define TOPPERS_TARGET_SUPPORT_GET_UTM		/* get_utm */
+
+/*
+ *  タイムティックの定義
+ */
+#ifndef TIC_NUME
+#define	TIC_NUME		1U			/* タイムティックの周期の分子 */
+#define	TIC_DENO		1U			/* タイムティックの周期の分母 */
+#endif /* TIC_NUME */
+
+#endif /* TOPPERS_TARGET_KERNEL_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_rename.def
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_rename.def	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_rename.def	(revision 453)
@@ -0,0 +1,19 @@
+# kernel_cfg.c
+vector_table
+bitpat_cfgint
+
+# target_config.c
+target_initialize
+target_exit
+default_plic_handler
+x_config_int
+
+# trace_config.c
+log_dsp_enter
+log_dsp_leave
+log_inh_enter
+log_inh_leave
+log_exc_enter
+log_exc_leave
+
+INCLUDE "riscv32_gcc/prc"
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_rename.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_rename.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_rename.h	(revision 453)
@@ -0,0 +1,62 @@
+/* This file is generated from target_rename.def by genrename. */
+
+#ifndef TOPPERS_TARGET_RENAME_H
+#define TOPPERS_TARGET_RENAME_H
+
+/*
+ *  kernel_cfg.c
+ */
+#define vector_table				_kernel_vector_table
+#define bitpat_cfgint				_kernel_bitpat_cfgint
+
+/*
+ *  target_config.c
+ */
+#define target_initialize			_kernel_target_initialize
+#define target_exit					_kernel_target_exit
+#define default_plic_handler		_kernel_default_plic_handler
+#define x_config_int				_kernel_x_config_int
+
+/*
+ *  trace_config.c
+ */
+#define log_dsp_enter				_kernel_log_dsp_enter
+#define log_dsp_leave				_kernel_log_dsp_leave
+#define log_inh_enter				_kernel_log_inh_enter
+#define log_inh_leave				_kernel_log_inh_leave
+#define log_exc_enter				_kernel_log_exc_enter
+#define log_exc_leave				_kernel_log_exc_leave
+
+
+#ifdef TOPPERS_LABEL_ASM
+
+/*
+ *  kernel_cfg.c
+ */
+#define _vector_table				__kernel_vector_table
+#define _bitpat_cfgint				__kernel_bitpat_cfgint
+
+/*
+ *  target_config.c
+ */
+#define _target_initialize			__kernel_target_initialize
+#define _target_exit				__kernel_target_exit
+#define _default_plic_handler		__kernel_default_plic_handler
+#define _x_config_int				__kernel_x_config_int
+
+/*
+ *  trace_config.c
+ */
+#define _log_dsp_enter				__kernel_log_dsp_enter
+#define _log_dsp_leave				__kernel_log_dsp_leave
+#define _log_inh_enter				__kernel_log_inh_enter
+#define _log_inh_leave				__kernel_log_inh_leave
+#define _log_exc_enter				__kernel_log_exc_enter
+#define _log_exc_leave				__kernel_log_exc_leave
+
+
+#endif /* TOPPERS_LABEL_ASM */
+
+#include "riscv_gcc/prc_rename.h"
+
+#endif /* TOPPERS_TARGET_RENAME_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_serial.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_serial.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_serial.c	(revision 453)
@@ -0,0 +1,463 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		シリアルI/Oデバイス（SIO）ドライバ（K210用）
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include "target_stddef.h"
+#include "target_serial.h"
+#include "target_syssvc.h"
+
+/*
+ *  SIL関数のマクロ定義
+ */
+#define sil_orw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) | (b))
+#define sil_andw_mem(a, b)		sil_wrw_mem((a), sil_rew_mem(a) & ~(b))
+
+/*
+ * レジスタ設定値
+ */
+#define INDEX_PORT(x)	((x) - 1)
+#define GET_SIOPCB(x)	(&siopcb_table[INDEX_PORT(x)])
+
+#define __UART_BRATE_CONST  16
+
+#ifndef COM0
+#define COM0                0
+#endif
+
+/*
+ *  ビット長パラメータ
+ */
+#define UART_WordLength_5B  0x00000000
+#define UART_WordLength_6B  0x00000001
+#define UART_WordLength_7B  0x00000002
+#define UART_WordLength_8b  0x00000003
+
+/*
+ *  ストップビットパラメータ
+ */ 
+#define UART_StopBits_1     0x00000000
+#define UART_StopBits_1_5   UART_LCR_STB
+
+/*
+ *  パリティパラメータ
+ */
+#define UART_Parity_No      0x00000000
+#define UART_Parity_Odd     UART_LCR_PARITY
+#define UART_Parity_Even    (UART_LCR_PARITY | UART_LCR_PEVEN)
+
+/*
+ *  送信FIFO
+ */
+#define UART_SEND_FIFO0     0
+#define UART_SEND_FIFO2     1
+#define UART_SEND_FIFO4     2
+#define UART_SEND_FIFO8     3
+
+/*
+ *  受信FIFO
+ */
+#define UART_RECEIVE_FIFO1  0
+#define UART_RECEIVE_FIFO4  1
+#define UART_RECEIVE_FIFO8  2
+#define UART_RECEIVE_FIFO14 3
+
+/*
+ *  シリアルI/Oポート初期化ブロックの定義
+ */
+typedef struct sio_port_initialization_block {
+	uint64_t base;
+	INTNO    intno_usart;
+	uint32_t clk;
+	uint8_t  txfunc;
+	uint8_t  rxfunc;
+	uint8_t  com;
+} SIOPINIB;
+
+/*
+ *  シリアルI/Oポート管理ブロックの定義
+ */
+struct sio_port_control_block {
+	const SIOPINIB  *p_siopinib;  /* シリアルI/Oポート初期化ブロック */
+	intptr_t        exinf;        /* 拡張情報 */
+	bool_t          opnflg;       /* オープン済みフラグ */
+};
+
+/*
+ * シリアルI/Oポート初期化ブロック
+ */
+const SIOPINIB siopinib_table[TNUM_SIOP] = {
+	{(uint32_t)TADR_UART1_BASE, (INTNO)IRQ_VECTOR_UART1, SYSCTL_CLK_EN_PERI_UART1_CLK_EN, FUNC_UART1_TX, FUNC_UART1_RX, COM0},
+#if TNUM_SIOP >= 2
+	{(uint32_t)TADR_UART3_BASE, (INTNO)IRQ_VECTOR_UART3, SYSCTL_CLK_EN_PERI_UART3_CLK_EN, FUNC_UART3_TX, FUNC_UART3_RX, COM0^1}
+#endif
+};
+
+/*
+ *  FPIOA番号テーブル
+ */
+static uint8_t uartpin[2][2] = {
+	{5, 4},		/* com0 tx, rx */
+	{6, 7},		/* com1 tx, rx */
+};
+
+/*
+ *  シリアルI/Oポート管理ブロックのエリア
+ */
+SIOPCB	siopcb_table[TNUM_SIOP];
+
+/*
+ *  シリアルI/OポートIDから管理ブロックを取り出すためのマクロ
+ */
+#define INDEX_SIOP(siopid)	((uint_t)((siopid) - 1))
+#define get_siopcb(siopid)	(&(siopcb_table[INDEX_SIOP(siopid)]))
+
+extern uint32_t get_pll_clock(uint8_t no);
+extern ER fpioa_set_function(int number, uint8_t function);
+
+/*
+ *  PLL0クロックを取得
+ */
+static uint32_t
+get_clock_aclk(void)
+{
+	uint32_t clk_sel0 = sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_CLK_SEL0));
+	uint32_t select = clk_sel0 & SYSCTL_CLK_SEL0_ACLK_SEL;
+	uint32_t source = 0;
+
+	if(select == 0)
+		source = SYSCTRL_CLOCK_FREQ_IN0;
+	else if(select == 1)
+		source = get_pll_clock(0) / (2UL << ((clk_sel0 & SYSCTL_CLK_SEL0_ACLK_SDIVISER)>>1));
+	return source;
+}
+
+
+void put_hex(char a, int val)
+{
+	int i, j;
+	target_fput_log(a);
+	target_fput_log(' ');
+	for(i = 28 ; i >= 0 ; i-= 4){
+		j = (val >> i) & 0xf;;
+		if(j > 9)
+			j += ('A'-10);
+		else
+			j += '0';
+		target_fput_log(j);
+	}
+	target_fput_log('\n');
+}
+
+/*
+ *  SIOドライバの初期化
+ */
+void
+sio_initialize(intptr_t exinf)
+{
+	SIOPCB	*p_siopcb;
+	uint_t	i;
+
+	/*
+	 *  シリアルI/Oポート管理ブロックの初期化
+	 */
+	for (p_siopcb = siopcb_table, i = 0; i < TNUM_SIOP; p_siopcb++, i++) {
+		p_siopcb->p_siopinib = &(siopinib_table[i]);
+		p_siopcb->opnflg = false;
+	}
+}
+
+
+/*
+ *  シリアルI/Oポートのオープン
+ */
+SIOPCB *
+sio_opn_por(ID siopid, intptr_t exinf)
+{
+	SIOPCB          *p_siopcb;
+	const SIOPINIB  *p_siopinib;
+	bool_t   opnflg;
+	ER       ercd;
+	unsigned long base;
+	uint32_t divisor, threshold, tmp;
+	uint8_t  dlh, dll, dlf;
+
+	p_siopcb = get_siopcb(siopid);
+	p_siopinib = p_siopcb->p_siopinib;
+
+	/*
+	 *  オープンしたポートがあるかをopnflgに読んでおく．
+	 */
+	opnflg = p_siopcb->opnflg;
+
+	p_siopcb->exinf = exinf;
+	base = p_siopinib->base;
+	if(base == 0)				/* no uart port */
+		goto sio_opn_exit;
+
+	/*
+	 *  ハードウェアの初期化
+	 */
+	sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_PERI), p_siopinib->clk);
+
+	sil_wrw_mem((uint32_t *)(base+TOFF_UART_IER), 0x00000000);
+	sil_dly_nse(10000);
+
+	threshold = (sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_CLK_SEL0)) & SYSCTL_CLK_SEL0_APB0_CLK_SEL) >> 3;
+    divisor = (get_clock_aclk() / (threshold+1)) / BPS_SETTING;
+    dlh = divisor >> 12;
+    dll = (divisor - (dlh << 12)) / __UART_BRATE_CONST;
+    dlf = divisor - (dlh << 12) - dll * __UART_BRATE_CONST;
+
+    /* Set UART registers */
+	sil_orw_mem((uint32_t *)(base+TOFF_UART_LCR), UART_LCR_DMD);
+	sil_wrw_mem((uint32_t *)(base+TOFF_UART_DLH), dlh);
+	sil_wrw_mem((uint32_t *)(base+TOFF_UART_DLL), dll);
+	sil_wrw_mem((uint32_t *)(base+TOFF_UART_DLF), dlf);
+	sil_wrw_mem((uint32_t *)(base+TOFF_UART_LCR), 0x00);
+	sil_wrw_mem((uint32_t *)(base+TOFF_UART_LCR), (UART_WordLength_8b | UART_StopBits_1 | UART_Parity_No));
+	sil_andw_mem((uint32_t *)(base+TOFF_UART_LCR), UART_LCR_DMD);
+	sil_orw_mem((uint32_t *)(base+TOFF_UART_IER), UART_IER_THRE);
+	sil_wrw_mem((uint32_t *)(base+TOFF_UART_FCR),
+			(UART_RECEIVE_FIFO1 << 6 | UART_SEND_FIFO8 << 4 | 0x1 << 3 | 0x1));
+
+	fpioa_set_function(uartpin[p_siopinib->com][1], p_siopinib->rxfunc);
+	fpioa_set_function(uartpin[p_siopinib->com][0], p_siopinib->txfunc);
+	sil_orw_mem((uint32_t *)(base+TOFF_UART_IER), UART_IER_RIE);
+	tmp = sil_rew_mem((uint32_t *)(p_siopcb->p_siopinib->base+TOFF_UART_RBR));
+	p_siopcb->opnflg = true;
+	(void)(tmp);
+
+	/*
+	 *  シリアルI/O割込みのマスクを解除する．
+	 */
+	if (!opnflg) {
+		ercd = ena_int(p_siopinib->intno_usart);
+		assert(ercd == E_OK);
+	}
+	sil_dly_nse(20000);
+
+sio_opn_exit:;
+	return(p_siopcb);
+}
+
+/*
+ *  シリアルI/Oポートのクローズ
+ */
+void
+sio_cls_por(SIOPCB *p_siopcb)
+{
+	const SIOPINIB  *p_siopinib;
+
+	p_siopinib = p_siopcb->p_siopinib;
+	/*
+	 *  シリアルI/O割込みをマスクする．
+	 */
+	if ((p_siopcb->opnflg)) {
+		dis_int(p_siopinib->intno_usart);
+	}
+
+	/*
+	 *  シリアル停止
+	 */
+	sil_wrw_mem((uint32_t *)(p_siopinib->base+TOFF_UART_IER), 0x00000000);
+	sil_andw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_PERI), p_siopinib->clk);
+	p_siopcb->opnflg = false;
+}
+
+/*
+ *  SIOの割込みサービスルーチン
+ */
+void
+sio_isr(intptr_t exinf)
+{
+	SIOPCB *p_siopcb = get_siopcb(exinf);
+	unsigned long base = p_siopcb->p_siopinib->base;
+	uint32_t ip = sil_rew_mem((uint32_t *)(base+TOFF_UART_IIR)) & 0x0F;
+	uint32_t tmp;
+
+	if(ip == UART_IIR_RECEIVE || ip == UART_IIR_CTIMEOUT){
+		sio_irdy_rcv(p_siopcb->exinf);
+	}
+	else if(ip == UART_IIR_SEND){
+		sio_irdy_snd(p_siopcb->exinf);
+	}
+	else{
+		tmp = sil_rew_mem((uint32_t *)(base+TOFF_UART_LSR));
+		tmp = sil_rew_mem((uint32_t *)(base+TOFF_UART_USR));
+		tmp = sil_rew_mem((uint32_t *)(base+TOFF_UART_MSR));
+	}
+	(void)(tmp);
+}
+
+/*
+ *  シリアルI/Oポートへの文字送信
+ */
+Inline bool_t
+sio_putready(SIOPCB* p_siopcb)
+{
+	uint32_t lsr = sil_rew_mem((uint32_t *)(p_siopcb->p_siopinib->base+TOFF_UART_LSR));
+
+	if((lsr & UART_LSR_TFL) == 0){
+		return 1;
+	}
+	return 0;
+}
+
+bool_t
+sio_snd_chr(SIOPCB *p_siopcb, char c)
+{
+	if(sio_putready(p_siopcb)){
+		sil_wrw_mem((uint32_t *)(p_siopcb->p_siopinib->base+TOFF_UART_THR), (uint32_t)c);
+		return true;
+	}
+	return false;
+}
+
+/*
+ *  シリアルI/Oポートからの文字受信
+ */
+int_t
+sio_rcv_chr(SIOPCB *p_siopcb)
+{
+	int_t c = -1;
+
+	if((sil_rew_mem((uint32_t *)(p_siopcb->p_siopinib->base+TOFF_UART_LSR)) & UART_LSR_RFL) != 0){
+		c = sil_rew_mem((uint32_t *)(p_siopcb->p_siopinib->base+TOFF_UART_RBR)) & 0xFF;
+	}
+	return c;
+}
+
+/*
+ *  シリアルI/Oポートからのコールバックの許可
+ */
+void
+sio_ena_cbr(SIOPCB *p_siopcb, uint_t cbrtn)
+{
+	switch (cbrtn) {
+	case SIO_RDY_SND:
+		sil_orw_mem((uint32_t *)(p_siopcb->p_siopinib->base+TOFF_UART_IER), UART_IER_TIE);
+		break;
+	case SIO_RDY_RCV:
+		sil_orw_mem((uint32_t *)(p_siopcb->p_siopinib->base+TOFF_UART_IER), UART_IER_RIE);
+		break;
+	}
+}
+
+/*
+ *  シリアルI/Oポートからのコールバックの禁止
+ */
+void
+sio_dis_cbr(SIOPCB *p_siopcb, uint_t cbrtn)
+{
+	switch (cbrtn) {
+	case SIO_RDY_SND:
+		sil_andw_mem((uint32_t *)(p_siopcb->p_siopinib->base+TOFF_UART_IER), UART_IER_TIE);
+		break;
+	case SIO_RDY_RCV:
+		sil_andw_mem((uint32_t *)(p_siopcb->p_siopinib->base+TOFF_UART_IER), UART_IER_RIE);
+		break;
+	}
+}
+
+/*
+ *  1文字出力（ポーリングでの出力）
+ */
+void sio_pol_snd_chr(int8_t c, ID siopid)
+{
+	unsigned long base = siopinib_table[INDEX_PORT(siopid)].base;
+
+	sil_wrw_mem((uint32_t *)(base+TOFF_UART_THR), (uint32_t)c);
+	while(0 != (sil_rew_mem((uint32_t *)(base+TOFF_UART_LSR)) & UART_LSR_TFL));
+
+	/*
+	 *  出力が完全に終わるまで待つ
+	 */
+	volatile int n = SYS_CLOCK/BPS_SETTING;
+	while(n--);
+}
+
+/*
+ *  ターゲットのシリアル初期化
+ */
+void target_uart_init(ID siopid)
+{
+	const SIOPINIB  *p_siopinib;
+	unsigned long base;
+	uint32_t divisor, threshold;
+	uint8_t  dlh, dll, dlf;
+
+	p_siopinib = &siopinib_table[INDEX_PORT(siopid)];
+	base = p_siopinib->base;
+
+	/*
+	 *  ハードウェアの初期化
+	 */
+	sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_PERI), p_siopinib->clk);
+
+	threshold = (sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_CLK_SEL0)) & SYSCTL_CLK_SEL0_APB0_CLK_SEL) >> 3;
+    divisor = (get_clock_aclk() / (threshold+1)) / BPS_SETTING;
+    dlh = divisor >> 12;
+    dll = (divisor - (dlh << 12)) / __UART_BRATE_CONST;
+    dlf = divisor - (dlh << 12) - dll * __UART_BRATE_CONST;
+
+    /* Set UART registers */
+	sil_orw_mem((uint32_t *)(base+TOFF_UART_LCR), UART_LCR_DMD);
+	sil_wrw_mem((uint32_t *)(base+TOFF_UART_DLH), dlh);
+	sil_wrw_mem((uint32_t *)(base+TOFF_UART_DLL), dll);
+	sil_wrw_mem((uint32_t *)(base+TOFF_UART_DLF), dlf);
+	sil_wrw_mem((uint32_t *)(base+TOFF_UART_LCR), 0x00);
+	sil_wrw_mem((uint32_t *)(base+TOFF_UART_LCR), (UART_WordLength_8b | UART_StopBits_1 | UART_Parity_No));
+	sil_andw_mem((uint32_t *)(base+TOFF_UART_LCR), UART_LCR_DMD);
+	sil_orw_mem((uint32_t *)(base+TOFF_UART_IER), UART_IER_THRE);
+	sil_wrw_mem((uint32_t *)(base+TOFF_UART_FCR),
+			(UART_RECEIVE_FIFO1 << 6 | UART_SEND_FIFO8 << 4 | 0x1 << 3 | 0x1));
+
+	fpioa_set_function(uartpin[p_siopinib->com][1], p_siopinib->rxfunc);
+	fpioa_set_function(uartpin[p_siopinib->com][0], p_siopinib->txfunc);
+	sil_dly_nse(10000);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_serial.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_serial.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_serial.cfg	(revision 453)
@@ -0,0 +1,16 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *		SIOドライバ（K210用）のコンフィギュレーションファイル
+ */
+
+#include "target_serial.h"
+ATT_INI({ TA_NULL, 0, sio_initialize });
+ATT_ISR({ TA_NULL, 1, INTNO_SIO1, sio_isr, 1 });
+CFG_INT(INTNO_SIO1, { INTATR_SIO, INTPRI_SIO });
+#if TNUM_SIOP >= 2
+ATT_ISR({ TA_NULL, 2, INTNO_SIO2, sio_isr, 1 });
+CFG_INT(INTNO_SIO2, { TA_ENAINT|INTATR_SIO, INTPRI_SIO });
+#endif /* TNUM_SIOP >= 2 */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_serial.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_serial.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_serial.h	(revision 453)
@@ -0,0 +1,146 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		シリアルI/Oデバイス（SIO）ドライバ（K210用）
+ */
+
+#ifndef TOPPERS_TARGET_SERIAL_H
+#define TOPPERS_TARGET_SERIAL_H
+
+#include "kendryte-k210.h"
+
+/*
+ *  シリアルI/Oポート数の定義
+ */
+#ifndef TNUM_SIOP
+#define TNUM_SIOP       2       /* サポートするシリアルI/Oポートの数 */
+#endif
+
+/*
+ *  SIOの割込みハンドラのベクタ番号
+ */
+#define INHNO_SIO1      IRQ_VECTOR_UART1
+#define INTNO_SIO1      IRQ_VECTOR_UART1
+#define INHNO_SIO2      IRQ_VECTOR_UART3
+#define INTNO_SIO2      IRQ_VECTOR_UART3
+
+#define INTPRI_SIO       -5        /* 割込み優先度 */
+#define INTATR_SIO       0         /* 割込み属性 */
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  シリアルI/Oポート管理ブロックの定義
+ */
+typedef struct sio_port_control_block    SIOPCB;
+
+/*
+ *  コールバックルーチンの識別番号
+ */
+#define SIO_RDY_SND    1U        /* 送信可能コールバック */
+#define SIO_RDY_RCV    2U        /* 受信通知コールバック */
+
+/*
+ *  SIOドライバの初期化
+ */
+extern void		sio_initialize(intptr_t exinf);
+
+/*
+ *  シリアルI/Oポートのオープン
+ */
+extern SIOPCB	*sio_opn_por(ID siopid, intptr_t exinf);
+
+/*
+ *  シリアルI/Oポートのクローズ
+ */
+extern void		sio_cls_por(SIOPCB *p_siopcb);
+
+/*
+ *  SIOの割込みサービスルーチン
+ */
+extern void		sio_isr(intptr_t exinf);
+
+/*
+ *  シリアルI/Oポートへの文字送信
+ */
+extern bool_t	sio_snd_chr(SIOPCB *siopcb, char c);
+
+/*
+ *  シリアルI/Oポートからの文字受信
+ */
+extern int_t	sio_rcv_chr(SIOPCB *siopcb);
+
+/*
+ *  シリアルI/Oポートからのコールバックの許可
+ */
+extern void		sio_ena_cbr(SIOPCB *siopcb, uint_t cbrtn);
+
+/*
+ *  シリアルI/Oポートからのコールバックの禁止
+ */
+extern void		sio_dis_cbr(SIOPCB *siopcb, uint_t cbrtn);
+
+/*
+ *  シリアルI/Oポートからの送信可能コールバック
+ */
+extern void		sio_irdy_snd(intptr_t exinf);
+
+/*
+ *  シリアルI/Oポートからの受信通知コールバック
+ */
+extern void		sio_irdy_rcv(intptr_t exinf);
+
+/*
+ *  1文字送信（ポーリングでの出力）
+ */
+extern void sio_pol_snd_chr(int8_t c, ID siopid);
+
+/*
+ *  ターゲットのシリアル初期化
+ */
+extern void target_uart_init(ID siopid);
+
+
+#endif /* TOPPERS_MACRO_ONLY */
+#endif /* TOPPERS_TARGET_SERIAL_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_sil.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_sil.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_sil.h	(revision 453)
@@ -0,0 +1,60 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2006 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		sil.hのターゲット依存部（K210用）
+ *
+ *  このインクルードファイルは，sil.hの先頭でインクルードされる．他のファ
+ *  イルからは直接インクルードすることはない．このファイルをインクルー
+ *  ドする前に，t_stddef.hがインクルードされるので，それらに依存しても
+ *  よい．
+ */
+
+#ifndef TOPPERS_TARGET_SIL_H
+#define TOPPERS_TARGET_SIL_H
+
+/*
+ *  プロセッサで共通な定義
+ */
+#include "riscv_gcc/prc_sil.h"
+
+#endif /* TOPPERS_TARGET_SIL_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_stddef.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_stddef.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_stddef.h	(revision 453)
@@ -0,0 +1,87 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2008 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		t_stddef.hのターゲット依存部（K210用）
+ *
+ *  このインクルードファイルは，t_stddef.hの先頭でインクルードされる．
+ *  他のファイルからは直接インクルードすることはない．他のインクルード
+ *  ファイルに先立って処理されるため，他のインクルードファイルに依存し
+ *  てはならない．
+ */
+
+#ifndef TOPPERS_TARGET_STDDEF_H
+#define TOPPERS_TARGET_STDDEF_H
+
+/*
+ *  ターゲットを識別するためのマクロの定義
+ */
+#define TOPPERS_K210				/* システム略称 */
+
+/*
+ *  開発環境で共通な定義
+ *
+ *  開発環境でstdint.hが用意されている場合には，TOPPERS_STDINT_TYPE1の
+ *  マクロ定義を削除し，stdint.hをインクルードすればよい．
+ */
+#define TOPPERS_STDINT_TYPE1
+#define TOPPERS_STDFLOAT_TYPE1
+#include "gcc/tool_stddef.h"
+
+/*
+ *  プロセッサで共通な定義
+ */
+#include "riscv_gcc/prc_stddef.h"
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  アサーションの失敗時の実行中断処理（T.B.D）
+ */
+Inline void
+TOPPERS_assert_abort(void)
+{
+    
+}
+
+#endif /* TOPPERS_MACRO_ONLY */
+#endif /* TOPPERS_TARGET_STDDEF_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_syssvc.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_syssvc.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_syssvc.h	(revision 453)
@@ -0,0 +1,112 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		システムサービスのターゲット依存部（K210用）
+ *
+ *  システムサービスのターゲット依存部のインクルードファイル．このファ
+ *  イルの内容は，コンポーネント記述ファイルに記述され，このファイルは
+ *  無くなる見込み．
+ */
+
+#ifndef TOPPERS_TARGET_SYSSVC_H
+#define TOPPERS_TARGET_SYSSVC_H
+
+/*
+ *  ターゲットシステムのハードウェア資源の定義
+ */
+#include "kendryte-k210.h"
+
+/*
+ *  システムクロックの定義
+ */
+#define SYS_CLOCK		        390000000
+#define SYSCTRL_CLOCK_FREQ_IN0  26000000
+
+/*
+ *  トレースログに関する設定
+ */
+#ifdef TOPPERS_ENABLE_TRACE
+#include "logtrace/trace_config.h"
+#endif /* TOPPERS_ENABLE_TRACE */
+
+/*
+ *  起動メッセージのターゲットシステム名
+ */
+#define TARGET_NAME	"K210"
+
+/*
+ *  起動メッセージの著作権表示
+ */
+#define TARGET_COPYRIGHT \
+"Copyright (C) 2017-2019 by Education Working Group TOPPERS PROJECT\n" \
+
+/*
+ *  システムログの低レベル出力のための文字出力
+ *
+ *  ターゲット依存の方法で，文字cを表示/出力/保存する．
+ */
+extern void	target_fput_log(char c);
+
+/*
+ *  サポートするシリアルポートの数
+ */
+#define TNUM_PORT        TNUM_SIOP
+
+/*
+ *  ログタスクが使用するポートID
+ */
+#define LOGTASK_PORTID   SIO_PORTID
+
+/*
+ *  ボーレート
+ */
+#define BPS_SETTING		(115200)
+
+/*
+ *  システムログタスク関連の定数の定義
+ *
+ *  デフォルト値の通り．
+ */
+
+#endif /* TOPPERS_TARGET_SYSSVC_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_test.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_test.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_test.h	(revision 453)
@@ -0,0 +1,54 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2006,2007 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		テストプログラムのターゲット依存定義（K210用）
+ */
+
+#ifndef TOPPERS_TARGET_TEST_H
+#define TOPPERS_TARGET_TEST_H
+
+/*
+ *  プロセッサで共通な定義
+ */
+#include "riscv_gcc/prc_test.h"
+
+#endif /* TOPPERS_TARGET_TEST_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_timer.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_timer.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_timer.cfg	(revision 453)
@@ -0,0 +1,8 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *		タイマドライバのコンフィギュレーションファイル
+ */
+INCLUDE("riscv_gcc/prc_timer.cfg");
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_timer.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_timer.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_timer.h	(revision 453)
@@ -0,0 +1,114 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2005-2008 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		タイマドライバ（K210用）
+ */
+
+#ifndef TOPPERS_TARGET_TIMER_H
+#define TOPPERS_TARGET_TIMER_H
+
+/*
+ *  ターゲット依存定義
+ */
+#include "target_syssvc.h"
+
+/*
+ *  タイマ割込みハンドラ登録のための定数
+ */
+#define INTPRI_TIMER	TIRQ_LEVEL4		/* 割込み優先度 */
+
+/*
+ *  CLINT周波数定義
+ */
+#define CLINT_FREQ      (SYS_CLOCK / 50)
+
+/*
+ *  プロセッサ依存定義
+ */
+#include "riscv_gcc/prc_timer.h"
+
+/*
+ *  累積値の読み出し
+ */
+Inline CLOCK
+target_current_timer_value(void)
+{
+	return *((volatile CLOCK *)(TADR_CLIC_BASE+TOFF_CLINT_MTIME));
+}
+
+/*
+ *  ターゲット値の読み出し
+ */
+Inline CLOCK
+target_get_target_timer_value(void)
+{
+    uint32_t core_id = read_csr(mhartid);
+	return *((volatile CLOCK *)(TADR_CLIC_BASE+TOFF_CLINT_MTIMECMP + core_id * sizeof(CLOCK)));
+}
+
+/*
+ *  ターゲット値の書き込み
+ */
+Inline void
+target_set_target_timer_value(CLOCK mtimecmp)
+{
+    uint32_t core_id = read_csr(mhartid);
+	*((volatile CLOCK *)(TADR_CLIC_BASE+TOFF_CLINT_MTIMECMP + core_id * sizeof(CLOCK))) = mtimecmp;
+}
+
+/*
+ *  タイマの現在値の読出し
+ */
+Inline CLOCK
+target_timer_get_current(void)
+{
+	CLOCK	clk;
+
+	clk = target_current_timer_value() - (target_get_target_timer_value() - TO_CLOCK(TIC_NUME, TIC_DENO));
+	return(clk);
+}
+
+#define target_timer_probe_int		prc_timer_probe_int
+
+#endif /* TOPPERS_TARGET_TIMER_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_unrename.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_unrename.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_unrename.h	(revision 453)
@@ -0,0 +1,63 @@
+/* This file is generated from target_rename.def by genrename. */
+
+/* This file is included only when target_rename.h has been included. */
+#ifdef TOPPERS_TARGET_RENAME_H
+#undef TOPPERS_TARGET_RENAME_H
+
+/*
+ *  kernel_cfg.c
+ */
+#undef vector_table
+#undef bitpat_cfgint
+
+/*
+ *  target_config.c
+ */
+#undef target_initialize
+#undef target_exit
+#undef default_plic_handler
+#undef x_config_int
+
+/*
+ *  trace_config.c
+ */
+#undef log_dsp_enter
+#undef log_dsp_leave
+#undef log_inh_enter
+#undef log_inh_leave
+#undef log_exc_enter
+#undef log_exc_leave
+
+
+#ifdef TOPPERS_LABEL_ASM
+
+/*
+ *  kernel_cfg.c
+ */
+#undef _vector_table
+#undef _bitpat_cfgint
+
+/*
+ *  target_config.c
+ */
+#undef _target_initialize
+#undef _target_exit
+#undef _default_plic_handler
+#undef _x_config_int
+
+/*
+ *  trace_config.c
+ */
+#undef _log_dsp_enter
+#undef _log_dsp_leave
+#undef _log_inh_enter
+#undef _log_inh_leave
+#undef _log_exc_enter
+#undef _log_exc_leave
+
+
+#endif /* TOPPERS_LABEL_ASM */
+
+#include "riscv_gcc/prc_unrename.h"
+
+#endif /* TOPPERS_TARGET_RENAME_H */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_user.txt
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_user.txt	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/target/k210_gcc/target_user.txt	(revision 453)
@@ -0,0 +1,96 @@
+=====================================================================
+                          MAixDUino依存部
+=====================================================================
+
+(1) 対応しているターゲットシステムの種類・構成
+
+hifive1依存部は，SiPEED社MAixDUinoボードをサポートしている．
+搭載しているチップはKendryte:K210(RISC-V RV32IMAC)である．
+
+(2) 使用する開発環境と動作検証した条件（バージョン，オプション等）
+
+コンパイラはGCCを用いる．動作確認に用いたコンパイラは以下の通りである．
+
+  gcc version 8.2(GNU MCU Eclipse:riscv-none-embed
+    8.2.0-2.1-20190425-1021)
+
+(3) ターゲット定義事項の規定
+
+(3-1) 割込み優先度
+
+CFG_INTで使用可能な割込み優先度の範囲は，-7 ～ -1 である．タイマー割
+込みはMIP_MTIPを使用する．タイマ割込みに優先度はtarget_timer.h中に
+INTPRI_TIMERとして定義しており，変更可能である．
+カーネル管理割込み制御としてmieを使用し，カーネル管理外割込みとして，
+mstatusのmieを使用する．
+
+(3-2) 割込み属性
+
+カーネルの割込み属性設定は意味を持たない．なぜなら，本SoCではピン設定
+はGPIOに対応しており，割込み属性はGPIOの設定，または，IPの仕様に従う．
+
+(4) メモリマップ
+
+プログラムはFLASHへデータはRAMへ配置する．
+リセット後、K210のブートローダがSDRAMに配置、実行を行う．
+
+(5) シリアルインタフェースドライバの情報
+
+シリアルインタフェースドライバでは，UART1とUART3を用いる．
+通信フォーマットは，115200bps, 8bit, non-parity, 1stopbitである．
+UART1(SIO1)はUSBシリアルで設定される最初のCOMポート及びArduinoの
+D0,D1のシリアル出力に設定される．UART3(SIO2)はUSBシリアルで設定さ
+れる二番目のCOMポートに設定される．
+
+(6) システムログ機能の情報
+
+システムログの低レベル出力は，UART1を用いる．通信フォーマットは，
+115200bps, 8bit, non-parity, 1stopbitである．
+
+(7) システムクロックの変更設定
+
+システムクロックは390MHzに固定である．
+
+(8) FPUの設定
+
+FPUを有効にするために、以下のコンパイルオプションを指定する必要が
+ある．この設定により、非タスク、タスク状態のFPUの使用が有効となる．
+　-march=rv64imafdc -mabi=lp64d -DUSE_FPU
+
+FPUを無効とし、ソフトウェアによるフロート処理を行うには、以下の
+コンパイルオプションを指定する必要がある．
+　-march=rv64imac -mabi=lp64
+
+(9)コア２の対応
+
+コア２の設定ドキュメントがないため、コア２はサポートしない．
+
+(10) ディレクトリ構成・ファイル構成
+ ./hifive1_gcc 
+   ./Makefile.target
+   ./kendryte-k210.h
+   ./target.tf
+   ./target_cfg1_out.h
+   ./target_check.tf
+   ./target_config.h
+   ./target_inithook.c
+   ./target_kernel.h
+   ./target_rename.def
+   ./target_rename.h
+   ./target_serial.c
+   ./target_serial.cfg
+   ./target_serial.h
+   ./target_sil.h
+   ./target_stddef.h
+   ./target_syssvc.h
+   ./target_test.h
+   ./target_timer.cfg
+   ./target_timer.h
+   ./target_unrename.h
+   ./target_user.txt
+
+(9) バージョン履歴
+2019/10/11
+・最初のリリース
+
+以上．
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/MANIFEST
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/MANIFEST	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/MANIFEST	(revision 453)
@@ -0,0 +1,59 @@
+PACKAGE asp
+
+MANIFEST
+bit_kernel.c
+perf0.c
+perf0.cfg
+perf0.h
+perf1.c
+perf1.cfg
+perf1.h
+perf2.c
+perf2.cfg
+perf2.h
+perf3.c
+perf3.cfg
+perf3.h
+perf4.c
+perf4.cfg
+perf4.h
+test_cpuexc.cfg
+test_cpuexc.h
+test_cpuexc.txt
+test_cpuexc1.c
+test_cpuexc2.c
+test_cpuexc3.c
+test_cpuexc4.c
+test_cpuexc5.c
+test_cpuexc6.c
+test_cpuexc7.c
+test_cpuexc8.c
+test_cpuexc9.c
+test_cpuexc10.c
+test_cpuexc11.c
+test_cpuexc12.c
+test_cpuexc13.c
+test_dlynse.c
+test_dlynse.cfg
+test_dlynse.h
+test_sem1.c
+test_sem1.cfg
+test_sem1.h
+test_sem2.c
+test_sem2.cfg
+test_sem2.h
+test_sysstat1.c
+test_sysstat1.cfg
+test_sysstat1.h
+test_task1.c
+test_task1.cfg
+test_task1.h
+test_tex1.c
+test_tex1.cfg
+test_tex1.h
+test_tex2.c
+test_tex2.cfg
+test_tex2.h
+test_utm1.c
+test_utm1.cfg
+test_utm1.h
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/bit_kernel.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/bit_kernel.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/bit_kernel.c	(revision 453)
@@ -0,0 +1,484 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2005-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		カーネルの整合性検査
+ */
+
+#include "kernel/kernel_impl.h"
+#include "kernel/task.h"
+#include "kernel/wait.h"
+#include "kernel/semaphore.h"
+#include "kernel/eventflag.h"
+#include "kernel/dataqueue.h"
+#include "kernel/pridataq.h"
+#include "kernel/mailbox.h"
+#include "kernel/mutex.h"
+#include "kernel/mempfix.h"
+#include "kernel/time_event.h"
+
+/*
+ *   エラーコードの定義
+ */
+#define E_SYS_LINENO	ERCD(E_SYS, -(__LINE__))
+
+/*
+ *  管理ブロックのアドレスの正当性のチェック
+ */
+#define VALID_TCB(p_tcb) \
+		((((char *) p_tcb) - ((char *) tcb_table)) % sizeof(TCB) == 0 \
+			&& TMIN_TSKID <= TSKID(p_tcb) && TSKID(p_tcb) <= tmax_tskid)
+
+#define VALID_SEMCB(p_semcb) \
+		((((char *) p_semcb) - ((char *) semcb_table)) % sizeof(SEMCB) == 0 \
+			&& TMIN_SEMID <= SEMID(p_semcb) && SEMID(p_semcb) <= tmax_semid)
+				
+#define VALID_FLGCB(p_flgcb) \
+		((((char *) p_flgcb) - ((char *) flgcb_table)) % sizeof(FLGCB) == 0 \
+			&& TMIN_FLGID <= FLGID(p_flgcb) && FLGID(p_flgcb) <= tmax_flgid)
+
+#define VALID_DTQCB(p_dtqcb) \
+		((((char *) p_dtqcb) - ((char *) dtqcb_table)) % sizeof(DTQCB) == 0 \
+			&& TMIN_DTQID <= DTQID(p_dtqcb) && DTQID(p_dtqcb) <= tmax_dtqid)
+
+#define VALID_PDQCB(p_pdqcb) \
+		((((char *) p_pdqcb) - ((char *) pdqcb_table)) % sizeof(PDQCB) == 0 \
+			&& TMIN_PDQID <= PDQID(p_pdqcb) && PDQID(p_pdqcb) <= tmax_pdqid)
+
+#define VALID_MBXCB(p_mbxcb) \
+		((((char *) p_mbxcb) - ((char *) mbxcb_table)) % sizeof(MBXCB) == 0 \
+			&& TMIN_MBXID <= MBXID(p_mbxcb) && MBXID(p_mbxcb) <= tmax_mbxid)
+
+#define VALID_MTXCB(p_mtxcb) \
+		((((char *) p_mtxcb) - ((char *) mtxcb_table)) % sizeof(MTXCB) == 0 \
+			&& TMIN_MTXID <= MTXID(p_mtxcb) && MTXID(p_mtxcb) <= tmax_mtxid)
+
+#define VALID_MPFCB(p_mpfcb) \
+		((((char *) p_mpfcb) - ((char *) mpfcb_table)) % sizeof(MPFCB) == 0 \
+			&& TMIN_MPFID <= MPFID(p_mpfcb) && MPFID(p_mpfcb) <= tmax_mpfid)
+
+/*
+ *  キューのチェックのための関数
+ *
+ *  p_queueにp_entryが含まれているかを調べる．含まれていればtrue，含ま
+ *  れていない場合にはfalseを返す．ダブルリンクの不整合の場合にも，
+ *  falseを返す．
+ */
+static bool_t
+in_queue(QUEUE *p_queue, QUEUE *p_entry)
+{
+	QUEUE	*p_current, *p_next;
+
+	p_current = p_queue->p_next;
+	if (p_current->p_prev != p_queue) {
+		return(false);					/* ダブルリンクの不整合 */
+	}
+	while (p_current != p_queue) {
+		if (p_current == p_entry) {
+			return(true);				/* p_entryが含まれていた */
+		}
+
+		/*
+		 *  キューの次の要素に進む
+		 */
+		p_next = p_current->p_next;
+		if (p_next->p_prev != p_current) {
+			return(false);				 /* ダブルリンクの不整合 */
+		}
+		p_current = p_next;
+	}
+	return(false);
+}
+
+/*
+ *  スタック上を指しているかの検査
+ */
+static bool_t
+on_stack(void *addr, const TINIB *p_tinib)
+{
+	if (p_tinib->stk <= addr
+				&& addr < (void *)((char *)(p_tinib->stk) + p_tinib->stksz)) {
+		return(true);
+	}
+	return(false);
+}
+
+/*
+ *  タスク毎の整合性検査
+ */
+static ER
+bit_task(ID tskid)
+{
+	TCB			*p_tcb;
+	const TINIB	*p_tinib;
+	uint_t		tstat, tstat_wait, pri;
+	TMEVTB		*p_tmevtb;
+	SEMCB		*p_semcb;
+	FLGCB		*p_flgcb;
+	DTQCB		*p_dtqcb;
+	PDQCB		*p_pdqcb;
+	MBXCB		*p_mbxcb;
+	MTXCB		*p_mtxcb;
+	MPFCB		*p_mpfcb;
+
+	if (!(TMIN_TSKID <= (tskid) && (tskid) <= tmax_tskid)) {
+		return(E_ID);
+	}
+	p_tcb = get_tcb(tskid);
+	p_tinib = p_tcb->p_tinib;
+	tstat = p_tcb->tstat;
+	tstat_wait = (tstat & TS_WAIT_MASK);
+	pri = p_tcb->priority;
+
+	/*
+	 *  初期化ブロックへのポインタの検査
+	 */
+	if (p_tinib != &(tinib_table[INDEX_TSK(tskid)])) {
+		return(E_SYS_LINENO);
+	}
+
+	/*
+	 *  tstatの検査
+	 */
+	switch (tstat & (TS_RUNNABLE | TS_WAITING | TS_SUSPENDED)) {
+	case TS_DORMANT:
+		if (tstat != TS_DORMANT) {
+			return(E_SYS_LINENO);
+		}
+		break;
+	case TS_RUNNABLE:
+		if (tstat != TS_RUNNABLE) {
+			return(E_SYS_LINENO);
+		}
+		break;
+	case TS_WAITING:
+	case (TS_WAITING | TS_SUSPENDED):
+		if (!(TS_WAIT_DLY <= tstat_wait && tstat_wait <= TS_WAIT_MTX)) {
+			return(E_SYS_LINENO);
+		}
+		if ((tstat & ~(TS_WAIT_MASK | TS_RUNNABLE | TS_WAITING | TS_SUSPENDED))
+																	!= 0U) {
+			return(E_SYS_LINENO);
+		}
+		break;
+	case TS_SUSPENDED:
+		if (tstat != TS_SUSPENDED) {
+			return(E_SYS_LINENO);
+		}
+		break;
+	default:
+		return(E_SYS_LINENO);
+	}
+
+	/*
+	 *  actqueの検査
+	 */
+	if (TSTAT_DORMANT(tstat) && p_tcb->actque) {
+		return(E_SYS_LINENO);
+	}
+
+	/*
+	 *  タスク優先度の検査
+	 */
+	if (pri >= TNUM_TPRI) {
+		return(E_SYS_LINENO);
+	}
+
+	/*
+	 *  texptnの検査
+	 */
+	if (p_tcb->p_tinib->texrtn == NULL && p_tcb->texptn != 0U) {
+		return(E_SYS_LINENO);
+	}
+
+	/*
+	 *  休止状態におけるチェック
+	 */
+	if (TSTAT_DORMANT(tstat)) {
+		if (!(pri == p_tinib->ipriority)
+					&& (p_tcb->wupque == false)
+					&& (p_tcb->enatex == false)
+					&& (p_tcb->texptn == 0U)) {
+			return(E_SYS_LINENO);
+		}
+	}
+
+	/*
+	 *  実行できる状態におけるチェック
+	 */
+	if (TSTAT_RUNNABLE(tstat)) {
+		if (!in_queue(&ready_queue[pri], &(p_tcb->task_queue))) {
+			return(E_SYS_LINENO);
+		}
+	}
+
+	/*
+	 *  待ち状態におけるチェック
+	 */
+	if (TSTAT_WAITING(tstat)) {
+		if (!on_stack(p_tcb->p_winfo, p_tinib)) {
+			return(E_SYS_LINENO);
+		}
+		p_tmevtb = p_tcb->p_winfo->p_tmevtb;
+		if (p_tmevtb != NULL) {
+			if (!on_stack(p_tmevtb, p_tinib)) {
+				return(E_SYS_LINENO);
+			}
+			/*
+			 *  (*p_tmevtb)の検査（未完成）
+			 */
+		}
+
+		switch (tstat & TS_WAIT_MASK) {
+			case TS_WAIT_SLP:
+				if (p_tcb->wupque == true) {
+					return(E_SYS_LINENO);
+				}
+				break;
+
+			case TS_WAIT_DLY:
+				if (p_tmevtb == NULL) {
+					return(E_SYS_LINENO);
+				}
+				break;
+
+			case TS_WAIT_SEM:
+				p_semcb = ((WINFO_SEM *)(p_tcb->p_winfo))->p_semcb;
+				if (!VALID_SEMCB(p_semcb)) {
+					return(E_SYS_LINENO);
+				}
+				if (!in_queue(&(p_semcb->wait_queue), &(p_tcb->task_queue))) {
+					return(E_SYS_LINENO);
+				}
+				break;
+
+			case TS_WAIT_FLG:
+				p_flgcb = ((WINFO_FLG *)(p_tcb->p_winfo))->p_flgcb;
+				if (!VALID_FLGCB(p_flgcb)) {
+					return(E_SYS_LINENO);
+				}
+				if (!in_queue(&(p_flgcb->wait_queue), &(p_tcb->task_queue))) {
+					return(E_SYS_LINENO);
+				}
+				break;
+
+			case TS_WAIT_SDTQ:
+				p_dtqcb = ((WINFO_DTQ *)(p_tcb->p_winfo))->p_dtqcb;
+				if (!VALID_DTQCB(p_dtqcb)) {
+					return(E_SYS_LINENO);
+				}
+				if (!in_queue(&(p_dtqcb->swait_queue), &(p_tcb->task_queue))) {
+					return(E_SYS_LINENO);
+				}
+				break;
+
+			case TS_WAIT_RDTQ:
+				p_dtqcb = ((WINFO_DTQ *)(p_tcb->p_winfo))->p_dtqcb;
+				if (!VALID_DTQCB(p_dtqcb)) {
+					return(E_SYS_LINENO);
+				}
+				if (!in_queue(&(p_dtqcb->rwait_queue), &(p_tcb->task_queue))) {
+					return(E_SYS_LINENO);
+				}
+				break;
+
+			case TS_WAIT_SPDQ:
+				p_pdqcb = ((WINFO_PDQ *)(p_tcb->p_winfo))->p_pdqcb;
+				if (!VALID_PDQCB(p_pdqcb)) {
+					return(E_SYS_LINENO);
+				}
+				if (!in_queue(&(p_pdqcb->swait_queue), &(p_tcb->task_queue))) {
+					return(E_SYS_LINENO);
+				}
+				break;
+
+			case TS_WAIT_RPDQ:
+				p_pdqcb = ((WINFO_PDQ *)(p_tcb->p_winfo))->p_pdqcb;
+				if (!VALID_PDQCB(p_pdqcb)) {
+					return(E_SYS_LINENO);
+				}
+				if (!in_queue(&(p_pdqcb->rwait_queue), &(p_tcb->task_queue))) {
+					return(E_SYS_LINENO);
+				}
+				break;
+
+			case TS_WAIT_MBX:
+				p_mbxcb = ((WINFO_MBX *)(p_tcb->p_winfo))->p_mbxcb;
+				if (!VALID_MBXCB(p_mbxcb)) {
+					return(E_SYS_LINENO);
+				}
+				if (!in_queue(&(p_mbxcb->wait_queue), &(p_tcb->task_queue))) {
+					return(E_SYS_LINENO);
+				}
+				break;
+
+			case TS_WAIT_MTX:
+				p_mtxcb = ((WINFO_MTX *)(p_tcb->p_winfo))->p_mtxcb;
+				if (!VALID_MTXCB(p_mtxcb)) {
+					return(E_SYS_LINENO);
+				}
+				if (!in_queue(&(p_mtxcb->wait_queue), &(p_tcb->task_queue))) {
+					return(E_SYS_LINENO);
+				}
+				break;
+
+			case TS_WAIT_MPF:
+				p_mpfcb = ((WINFO_MPF *)(p_tcb->p_winfo))->p_mpfcb;
+				if (!VALID_MPFCB(p_mpfcb)) {
+					return(E_SYS_LINENO);
+				}
+				if (!in_queue(&(p_mpfcb->wait_queue), &(p_tcb->task_queue))) {
+					return(E_SYS_LINENO);
+				}
+				break;
+		}
+	}
+
+	/*
+	 *  tskctxbの検査
+	 */
+	if (!TSTAT_DORMANT(tstat) && p_tcb != p_runtsk) {
+		/*
+		 *  ターゲット依存の検査
+		 */
+#if 0
+		if (bit_tskctxb(&(p_tcb->tskctxb))) {
+			return(E_SYS_LINENO);
+		}
+#endif
+	}
+	return(E_OK);
+}
+
+/*
+ *  セマフォ毎の整合性検査
+ */
+#define INDEX_SEM(semid)	((uint_t)((semid) - TMIN_SEMID))
+#define get_semcb(semid)	(&(semcb_table[INDEX_SEM(semid)]))
+
+static ER
+bit_semaphore(ID semid)
+{
+	SEMCB			*p_semcb;
+	const SEMINIB	*p_seminib;
+	uint_t			semcnt;
+	QUEUE			*p_queue;
+	TCB				*p_tcb;
+
+	if (!(TMIN_SEMID <= (semid) && (semid) <= tmax_semid)) {
+		return(E_ID);
+	}
+	p_semcb = get_semcb(semid);
+	p_seminib = p_semcb->p_seminib;
+	semcnt = p_semcb->semcnt;
+
+	/*
+	 *  初期化ブロックへのポインタの検査
+	 */
+	if (p_seminib != &(seminib_table[INDEX_SEM(semid)])) {
+		return(E_SYS_LINENO);
+	}
+
+	/*
+	 *  semcntの検査
+	 */
+	if (semcnt > p_seminib->maxsem) {
+		return(E_SYS_LINENO);
+	}
+
+	/*
+	 *  wait_queueの検査
+	 */
+	if (semcnt == 0) {
+		p_queue = p_semcb->wait_queue.p_next;
+		while (p_queue != &(p_semcb->wait_queue)) {
+			p_tcb = (TCB *) p_queue;
+			p_queue = p_queue->p_next;
+			if (!VALID_TCB(p_tcb)) {
+				return(E_SYS_LINENO);
+			}
+			if (p_tcb->tstat != (TS_WAITING | TS_WAIT_SEM)) {
+				return(E_SYS_LINENO);
+			}
+			if (p_semcb != ((WINFO_SEM *)(p_tcb->p_winfo))->p_semcb) {
+				return(E_SYS_LINENO);
+			}
+		}
+	}
+	else {
+		if (!queue_empty(&(p_semcb->wait_queue))) {
+			return(E_SYS_LINENO);
+		}
+	}
+	return(E_OK);
+}
+
+/*
+ *  整合性検査ルーチン本体
+ */
+ER
+bit_kernel(void)
+{
+	ID		tskid;
+	ID		semid;
+	ER		ercd;
+
+	/*
+	 *  タスク毎の検査
+	 */
+	for (tskid = TMIN_TSKID; tskid <= tmax_tskid; tskid++) {
+		ercd = bit_task(tskid);
+		if (ercd != E_OK) {
+			return(ercd);
+		}
+	}
+
+	/*
+	 *  セマフォ毎の検査
+	 */
+	for (semid = TMIN_SEMID; semid <= tmax_semid; semid++) {
+		ercd = bit_semaphore(semid);
+		if (ercd != E_OK) {
+			return(ercd);
+		}
+	}
+
+	return(E_OK);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf0.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf0.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf0.c	(revision 453)
@@ -0,0 +1,83 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2006-2009 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		カーネル性能評価プログラム(0)
+ *
+ *  時間計測のオーバヘッドを計測するためのプログラム．
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <test_lib.h>
+#include <histogram.h>
+#include "kernel_cfg.h"
+#include "perf0.h"
+
+/*
+ *  計測回数と実行時間分布を記録する最大時間
+ */
+#define NO_MEASURE	10000U			/* 計測回数 */
+#define MAX_TIME	1000U			/* 実行時間分布を記録する最大時間 */
+
+/*
+ *  実行時間分布を記録するメモリ領域
+ */
+static uint_t	histarea1[MAX_TIME + 1];
+
+/*
+ *  メインタスク
+ */
+void main_task(intptr_t exinf)
+{
+	uint_t	i;
+
+	syslog_0(LOG_NOTICE, "Performance evaluation program (0)");
+	init_hist(1, MAX_TIME, histarea1);
+	syslog_flush();
+
+	for (i = 0; i < NO_MEASURE; i++) {
+		begin_measure(1);
+		end_measure(1);
+	}
+
+	syslog_0(LOG_NOTICE, "Measurement overhead");
+	print_hist(1);
+	test_finish();
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf0.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf0.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf0.cfg	(revision 453)
@@ -0,0 +1,14 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *  カーネル性能評価プログラム(0)のシステムコンフィギュレーションファイル
+ */
+INCLUDE("target_timer.cfg");
+INCLUDE("syssvc/syslog.cfg");
+INCLUDE("syssvc/banner.cfg");
+INCLUDE("syssvc/serial.cfg");
+
+#include "perf0.h"
+CRE_TSK(MAIN_TASK, { TA_ACT, 0, main_task, MAIN_PRIORITY, STACK_SIZE, NULL });
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf0.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf0.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf0.h	(revision 453)
@@ -0,0 +1,64 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2006,2007 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		カーネル性能評価プログラム(0)
+ */
+
+/*
+ *  ターゲット依存の定義
+ */
+#include "target_test.h"
+
+/*
+ *  各タスクの優先度の定義
+ */
+#define MAIN_PRIORITY	11		/* メインタスクの優先度 */
+
+/*
+ *  ターゲットに依存する可能性のある定数の定義
+ */
+#ifndef STACK_SIZE
+#define	STACK_SIZE		4096		/* タスクのスタックサイズ */
+#endif /* STACK_SIZE */
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+extern void	main_task(intptr_t exinf);
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf1.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf1.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf1.c	(revision 453)
@@ -0,0 +1,116 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2006-2009 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		カーネル性能評価プログラム(1)
+ *
+ *  slp_tsk，wup_tskによるタスク切換え時間を計測するためのプログラム．
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <test_lib.h>
+#include <histogram.h>
+#include "kernel_cfg.h"
+#include "perf1.h"
+
+/*
+ *  計測回数と実行時間分布を記録する最大時間
+ */
+#define NO_MEASURE	10000U			/* 計測回数 */
+#define MAX_TIME	1000U			/* 実行時間分布を記録する最大時間 */
+
+/*
+ *  実行時間分布を記録するメモリ領域
+ */
+static uint_t	histarea1[MAX_TIME + 1];
+static uint_t	histarea2[MAX_TIME + 1];
+
+/*
+ *  計測タスク1（高優先度）
+ */
+void task1(intptr_t exinf)
+{
+	uint_t	i;
+
+	slp_tsk();
+	end_measure(1);
+	for (i = 1; i < NO_MEASURE; i++) {
+		begin_measure(2);
+		slp_tsk();
+		end_measure(1);
+	}
+	begin_measure(2);
+	slp_tsk();
+}
+
+/*
+ *  計測タスク2（中優先度）
+ */
+void task2(intptr_t exinf)
+{
+	uint_t	i;
+
+	for (i = 0; i < NO_MEASURE; i++) {
+		begin_measure(1);
+		wup_tsk(TASK1);
+		end_measure(2);
+	}
+	wup_tsk(TASK1);
+}
+
+/*
+ *  メインタスク（低優先度）
+ */
+void main_task(intptr_t exinf)
+{
+	syslog_0(LOG_NOTICE, "Performance evaluation program (1)");
+	init_hist(1, MAX_TIME, histarea1);
+	init_hist(2, MAX_TIME, histarea2);
+	syslog_flush();
+
+	act_tsk(TASK1);
+	act_tsk(TASK2);
+
+	syslog_0(LOG_NOTICE, "Execution times of wup_tsk -> slp_tsk");
+	print_hist(1);
+	syslog_0(LOG_NOTICE, "Execution times of slp_tsk -> wup_tsk");
+	print_hist(2);
+	test_finish();
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf1.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf1.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf1.cfg	(revision 453)
@@ -0,0 +1,16 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *  カーネル性能評価プログラム(1)のシステムコンフィギュレーションファイル
+ */
+INCLUDE("target_timer.cfg");
+INCLUDE("syssvc/syslog.cfg");
+INCLUDE("syssvc/banner.cfg");
+INCLUDE("syssvc/serial.cfg");
+
+#include "perf1.h"
+CRE_TSK(TASK1, { TA_NULL, 1, task1, TASK1_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK2, { TA_NULL, 2, task2, TASK2_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(MAIN_TASK, { TA_ACT, 0, main_task, MAIN_PRIORITY, STACK_SIZE, NULL });
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf1.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf1.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf1.h	(revision 453)
@@ -0,0 +1,68 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2006,2007 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		カーネル性能評価プログラム(1)
+ */
+
+/*
+ *  ターゲット依存の定義
+ */
+#include "target_test.h"
+
+/*
+ *  各タスクの優先度の定義
+ */
+#define TASK1_PRIORITY	9		/* 計測タスク1の優先度 */
+#define TASK2_PRIORITY	10		/* 計測タスク2の優先度 */
+#define MAIN_PRIORITY	11		/* メインタスクの優先度 */
+
+/*
+ *  ターゲットに依存する可能性のある定数の定義
+ */
+#ifndef STACK_SIZE
+#define	STACK_SIZE		4096		/* タスクのスタックサイズ */
+#endif /* STACK_SIZE */
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+extern void	task1(intptr_t exinf);
+extern void	task2(intptr_t exinf);
+extern void	main_task(intptr_t exinf);
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf2.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf2.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf2.c	(revision 453)
@@ -0,0 +1,115 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2007-2009 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		カーネル性能評価プログラム(2)
+ *
+ *  優先度データキューに蓄積されているデータの数により，snd_pdqの処理時
+ *  間がどのように変化するかを計測するためのプログラム．
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <test_lib.h>
+#include <histogram.h>
+#include "kernel_cfg.h"
+#include "perf2.h"
+
+/*
+ *  計測回数と実行時間分布を記録する最大時間
+ */
+#define NO_MEASURE	10000U			/* 計測回数 */
+#define MAX_TIME	1000U			/* 実行時間分布を記録する最大時間 */
+
+/*
+ *  実行時間分布を記録するメモリ領域
+ */
+static uint_t	histarea1[MAX_TIME + 1];
+
+/*
+ *  計測ルーチン
+ */
+void
+perf_eval(uint_t n)
+{
+	uint_t		i;
+	intptr_t	data;
+	PRI			pri;
+
+	ini_pdq(PDQ1);
+	init_hist(1, MAX_TIME, histarea1);
+
+	for (i = 0; i < n; i++) {
+		data = i;
+		snd_pdq(PDQ1, data, 1);
+	}
+
+	for (i = 0; i < NO_MEASURE; i++) {
+		data = i;
+		begin_measure(1);
+		snd_pdq(PDQ1, data, 2);
+		end_measure(1);
+		rcv_pdq(PDQ1, &data, &pri);
+	}
+
+	syslog_1(LOG_NOTICE, "Execution times of snd_pdq"
+								" when %d data are queued.", n);
+	print_hist(1);
+	syslog_flush();
+}
+
+/*
+ *  メインタスク（低優先度）
+ */
+void main_task(intptr_t exinf)
+{
+	syslog_0(LOG_NOTICE, "Performance evaluation program (2)");
+	syslog_flush();
+
+	perf_eval(0);
+	perf_eval(10);
+	perf_eval(20);
+	perf_eval(30);
+	perf_eval(40);
+	perf_eval(50);
+	perf_eval(100);
+	perf_eval(200);
+	perf_eval(300);
+	test_finish();
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf2.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf2.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf2.cfg	(revision 453)
@@ -0,0 +1,15 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *  カーネル性能評価プログラム(2)のシステムコンフィギュレーションファイル
+ */
+INCLUDE("target_timer.cfg");
+INCLUDE("syssvc/syslog.cfg");
+INCLUDE("syssvc/banner.cfg");
+INCLUDE("syssvc/serial.cfg");
+
+#include "perf2.h"
+CRE_TSK(MAIN_TASK, { TA_ACT, 0, main_task, MAIN_PRIORITY, STACK_SIZE, NULL });
+CRE_PDQ(PDQ1, { TA_NULL, 301, 16, NULL });
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf2.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf2.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf2.h	(revision 453)
@@ -0,0 +1,64 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2007 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		カーネル性能評価プログラム(2)
+ */
+
+/*
+ *  ターゲット依存の定義
+ */
+#include "target_test.h"
+
+/*
+ *  各タスクの優先度の定義
+ */
+#define MAIN_PRIORITY	11		/* メインタスクの優先度 */
+
+/*
+ *  ターゲットに依存する可能性のある定数の定義
+ */
+#ifndef STACK_SIZE
+#define	STACK_SIZE		4096		/* タスクのスタックサイズ */
+#endif /* STACK_SIZE */
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+extern void	main_task(intptr_t exinf);
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf3.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf3.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf3.c	(revision 453)
@@ -0,0 +1,136 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2007-2009 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		カーネル性能評価プログラム(3)
+ *
+ *  待ち解除するタスクの数により，set_flgの処理時間がどのように変化する
+ *  かを計測するためのプログラム．
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <test_lib.h>
+#include <histogram.h>
+#include "kernel_cfg.h"
+#include "perf3.h"
+
+/*
+ *  計測回数と実行時間分布を記録する最大時間
+ */
+#define NO_MEASURE	10000U			/* 計測回数 */
+#define MAX_TIME	1000U			/* 実行時間分布を記録する最大時間 */
+
+/*
+ *  実行時間分布を記録するメモリ領域
+ */
+static uint_t	histarea1[MAX_TIME + 1];
+
+/*
+ *  計測タスクのリスト
+ */
+static ID task_list[20] = {
+	TASK1, TASK2, TASK3, TASK4, TASK5,
+	TASK6, TASK7, TASK8, TASK9, TASK10,
+	TASK11, TASK12, TASK13, TASK14, TASK15,
+	TASK16, TASK17, TASK18, TASK19, TASK20
+};
+
+/*
+ *  計測タスク（中優先度）
+ */
+void task(intptr_t exinf)
+{
+	FLGPTN	flgptn;
+
+	wai_flg(FLG1, 0x01U, TWF_ORW, &flgptn);
+}
+
+/*
+ *  計測ルーチン
+ */
+void
+perf_eval(uint_t n)
+{
+	uint_t		i, j;
+
+	init_hist(1, MAX_TIME, histarea1);
+
+	for (i = 0; i < NO_MEASURE; i++) {
+		ini_flg(FLG1);
+		for (j = 0; j < n; j++) {
+			act_tsk(task_list[j]);
+		}
+		chg_pri(TSK_SELF, MAIN_PRIORITY_LOW);
+		/* タスクが待ち状態に入るのを待つ */
+		chg_pri(TSK_SELF, TPRI_INI);
+
+		begin_measure(1);
+		set_flg(FLG1, 0x01U);
+		end_measure(1);
+
+		chg_pri(TSK_SELF, MAIN_PRIORITY_LOW);
+		/* タスクが終了するのを待つ */
+		chg_pri(TSK_SELF, TPRI_INI);
+	}
+
+	syslog_1(LOG_NOTICE, "Execution times of set_flg"
+							" when %d tasks are released from waiting.", n);
+	print_hist(1);
+	syslog_flush();
+}
+
+/*
+ *  メインタスク（高優先度）
+ */
+void main_task(intptr_t exinf)
+{
+	syslog_0(LOG_NOTICE, "Performance evaluation program (3)");
+	syslog_flush();
+
+	perf_eval(0);
+	perf_eval(1);
+	perf_eval(2);
+	perf_eval(3);
+	perf_eval(4);
+	perf_eval(5);
+	perf_eval(10);
+	perf_eval(20);
+	test_finish();
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf3.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf3.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf3.cfg	(revision 453)
@@ -0,0 +1,35 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *  カーネル性能評価プログラム(3)のシステムコンフィギュレーションファイル
+ */
+INCLUDE("target_timer.cfg");
+INCLUDE("syssvc/syslog.cfg");
+INCLUDE("syssvc/banner.cfg");
+INCLUDE("syssvc/serial.cfg");
+
+#include "perf3.h"
+CRE_TSK(TASK1, { TA_NULL, 1, task, TASK_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK2, { TA_NULL, 2, task, TASK_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK3, { TA_NULL, 3, task, TASK_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK4, { TA_NULL, 4, task, TASK_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK5, { TA_NULL, 5, task, TASK_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK6, { TA_NULL, 6, task, TASK_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK7, { TA_NULL, 7, task, TASK_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK8, { TA_NULL, 8, task, TASK_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK9, { TA_NULL, 9, task, TASK_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK10, { TA_NULL, 10, task, TASK_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK11, { TA_NULL, 11, task, TASK_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK12, { TA_NULL, 12, task, TASK_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK13, { TA_NULL, 13, task, TASK_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK14, { TA_NULL, 14, task, TASK_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK15, { TA_NULL, 15, task, TASK_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK16, { TA_NULL, 16, task, TASK_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK17, { TA_NULL, 17, task, TASK_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK18, { TA_NULL, 18, task, TASK_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK19, { TA_NULL, 19, task, TASK_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK20, { TA_NULL, 20, task, TASK_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(MAIN_TASK, { TA_ACT, 0, main_task, MAIN_PRIORITY, STACK_SIZE, NULL });
+CRE_FLG(FLG1, { TA_WMUL, 0x00U });
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf3.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf3.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf3.h	(revision 453)
@@ -0,0 +1,67 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2007 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		カーネル性能評価プログラム(3)
+ */
+
+/*
+ *  ターゲット依存の定義
+ */
+#include "target_test.h"
+
+/*
+ *  各タスクの優先度の定義
+ */
+#define TASK_PRIORITY		10		/* タスクの優先度 */
+#define MAIN_PRIORITY		9		/* メインタスクの優先度 */
+#define MAIN_PRIORITY_LOW	11		/* メインタスクの低優先度 */
+
+/*
+ *  ターゲットに依存する可能性のある定数の定義
+ */
+#ifndef STACK_SIZE
+#define	STACK_SIZE		4096		/* タスクのスタックサイズ */
+#endif /* STACK_SIZE */
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+extern void	task(intptr_t exinf);
+extern void	main_task(intptr_t exinf);
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf4.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf4.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf4.c	(revision 453)
@@ -0,0 +1,179 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2006-2009 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		カーネル性能評価プログラム(4)
+ *
+ *  act_tsk，iact_tskの処理時間とタスク切換え時間を計測するためのプログ
+ *  ラム．以下の3つの時間を測定する．
+ *
+ *  (1) タスク切換えを起こさないact_tskの処理時間．自タスクよりも優先度
+ *      の低いタスクに対してact_tskを発行し，休止状態から実行できる状態
+ *      に遷移させる処理の時間．
+ *
+ *  (2) タスク切換えを起こすact_tskの処理時間．自タスクよりも優先度の高
+ *      いタスクに対してact_tskを発行し，休止状態から実行できる状態に遷
+ *      移させ，タスク切換えを起こして，高い優先度のタスクの実行が始ま
+ *      るまでの時間．
+ *
+ *  (3) タスク切換えを起こすiact_tskの処理時間．周期ハンドラから，実行
+ *      状態のタスクよりも高い優先度のタスクに対してact_tskを発行し，休
+ *      止状態から実行できる状態に遷移させたあとに周期ハンドラからリター
+ *      ンし，タスク切換えを起こして，高い優先度のタスクの実行が始まる
+ *      までの時間．
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <test_lib.h>
+#include <histogram.h>
+#include "kernel_cfg.h"
+#include "perf4.h"
+
+/*
+ *  計測回数と実行時間分布を記録する最大時間
+ */
+#define NO_MEASURE	10000U			/* 計測回数 */
+#define MAX_TIME	1000U			/* 実行時間分布を記録する最大時間 */
+
+/*
+ *  実行時間分布を記録するメモリ領域
+ */
+static uint_t	histarea1[MAX_TIME + 1];
+static uint_t	histarea2[MAX_TIME + 1];
+static uint_t	histarea3[MAX_TIME + 1];
+
+/*
+ *  計測タスク1（高優先度）
+ */
+void task1(intptr_t exinf)
+{
+	end_measure(2);
+	ext_tsk();
+}
+
+/*
+ *  計測タスク2とメインタスクの共有変数
+ */
+volatile uint_t		task2_count;
+
+/*
+ *  計測タスク2（高優先度）
+ */
+void task2(intptr_t exinf)
+{
+	end_measure(3);
+	task2_count++;
+	ext_tsk();
+}
+
+/*
+ *  計測タスク3（低優先度）
+ */
+void task3(intptr_t exinf)
+{
+	ext_tsk();
+}
+
+/*
+ *  計測タスク4（最低優先度）
+ */
+void task4(intptr_t exinf)
+{
+	while (true) {
+		wup_tsk(MAIN_TASK);
+	}
+}
+
+/*
+ *  周期ハンドラ
+ */
+void cyclic_handler(intptr_t exinf)
+{
+	begin_measure(3);
+	iact_tsk(TASK2);
+}
+
+/*
+ *  メインタスク（中優先度）
+ */
+void main_task(intptr_t exinf)
+{
+	uint_t	i;
+
+	syslog_0(LOG_NOTICE, "Performance evaluation program (4)");
+	init_hist(1, MAX_TIME, histarea1);
+	init_hist(2, MAX_TIME, histarea2);
+	init_hist(3, MAX_TIME, histarea3);
+	syslog_flush();
+
+	/*
+	 *  タスク切換えを起こさないact_tskの処理時間の測定
+	 */
+	for (i = 0; i < NO_MEASURE; i++) {
+		begin_measure(1);
+		act_tsk(TASK3);
+		end_measure(1);
+		slp_tsk();
+	}
+
+	/*
+	 *  タスク切換えを起こすact_tskの処理時間の測定
+	 */
+	for (i = 0; i < NO_MEASURE; i++) {
+		begin_measure(2);
+		act_tsk(TASK1);
+	}
+
+	/*
+	 *  タスク切換えを起こすiact_tskの処理時間の測定（測定回数は10分の1）
+	 */
+	task2_count = 0;
+	sta_cyc(CYC1);
+	while (task2_count < NO_MEASURE / 10) ;
+	stp_cyc(CYC1);
+
+	syslog_0(LOG_NOTICE, "Execution times of act_tsk without task switch");
+	print_hist(1);
+	syslog_0(LOG_NOTICE, "Execution times of act_tsk with task switch");
+	print_hist(2);
+	syslog_0(LOG_NOTICE, "Execution times of iact_tsk with task switch");
+	print_hist(3);
+	test_finish();
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf4.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf4.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf4.cfg	(revision 453)
@@ -0,0 +1,21 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *  カーネル性能評価プログラム(4)のシステムコンフィギュレーションファイル
+ */
+INCLUDE("target_timer.cfg");
+INCLUDE("syssvc/syslog.cfg");
+INCLUDE("syssvc/banner.cfg");
+INCLUDE("syssvc/serial.cfg");
+
+#include "perf4.h"
+CRE_TSK(TASK1, { TA_NULL, 1, task1, TASK1_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK2, { TA_NULL, 2, task2, TASK2_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK3, { TA_NULL, 3, task3, TASK3_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK4, { TA_ACT, 4, task4, TASK4_PRIORITY, STACK_SIZE, NULL });
+CRE_CYC(CYC1, { TA_NULL, 0, cyclic_handler,
+					(TIC_NUME + TIC_DENO - 1) / TIC_DENO,
+					(TIC_NUME + TIC_DENO - 1) / TIC_DENO });
+CRE_TSK(MAIN_TASK, { TA_ACT, 0, main_task, MAIN_PRIORITY, STACK_SIZE, NULL });
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf4.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf4.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/perf4.h	(revision 453)
@@ -0,0 +1,73 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2006-2009 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		カーネル性能評価プログラム(4)
+ */
+
+/*
+ *  ターゲット依存の定義
+ */
+#include "target_test.h"
+
+/*
+ *  各タスクの優先度の定義
+ */
+#define TASK1_PRIORITY	9		/* 計測タスク1の優先度 */
+#define TASK2_PRIORITY	9		/* 計測タスク2の優先度 */
+#define TASK3_PRIORITY	11		/* 計測タスク3の優先度 */
+#define TASK4_PRIORITY	12		/* 計測タスク4の優先度 */
+#define MAIN_PRIORITY	10		/* メインタスクの優先度 */
+
+/*
+ *  ターゲットに依存する可能性のある定数の定義
+ */
+#ifndef STACK_SIZE
+#define	STACK_SIZE		4096		/* タスクのスタックサイズ */
+#endif /* STACK_SIZE */
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+extern void	task1(intptr_t exinf);
+extern void	task2(intptr_t exinf);
+extern void	task3(intptr_t exinf);
+extern void	task4(intptr_t exinf);
+extern void	cyclic_handler(intptr_t exinf);
+extern void	main_task(intptr_t exinf);
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc.cfg	(revision 453)
@@ -0,0 +1,22 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *  CPU例外処理のテスト(1)～(13)のシステムコンフィギュレーションファイル
+ */
+INCLUDE("target_timer.cfg");
+INCLUDE("syssvc/syslog.cfg");
+INCLUDE("syssvc/banner.cfg");
+INCLUDE("syssvc/serial.cfg");
+
+#include "test_cpuexc.h"
+
+CRE_TSK(TASK1, { TA_ACT, 1, task1, MID_PRIORITY, STACK_SIZE, NULL });
+DEF_TEX(TASK1, { TA_NULL, tex_task1 });
+
+CRE_TSK(TASK2, { TA_NULL, 2, task2, HIGH_PRIORITY, STACK_SIZE, NULL });
+
+CRE_ALM(ALM1, { TA_NULL, 1, alarm1_handler });
+
+DEF_EXC(CPUEXC1, { TA_NULL, cpuexc_handler });
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc.h	(revision 453)
@@ -0,0 +1,76 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2007 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/* 
+ *		CPU例外処理のテスト(1)～(13)
+ */
+
+/*
+ *  ターゲット依存の定義
+ */
+#include "target_test.h"
+
+/*
+ *  各タスクの優先度の定義
+ */
+#define HIGH_PRIORITY	9		/* 高優先度 */
+#define MID_PRIORITY	10		/* 中優先度 */
+
+/*
+ *  ターゲットに依存する可能性のある定数の定義
+ */
+#ifndef STACK_SIZE
+#define	STACK_SIZE		4096		/* タスクのスタックサイズ */
+#endif /* STACK_SIZE */
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+#ifndef TOPPERS_MACRO_ONLY
+
+extern void	task1(intptr_t exinf);
+extern void	tex_task1(TEXPTN texptn, intptr_t exinf);
+
+extern void	task2(intptr_t exinf);
+
+extern void	alarm1_handler(intptr_t exinf);
+
+extern void	cpuexc_handler(void *p_excinf);
+
+#endif /* TOPPERS_MACRO_ONLY */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc.txt
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc.txt	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc.txt	(revision 453)
@@ -0,0 +1,127 @@
+
+		CPU例外処理のテスト
+
+【テストの目的】
+
+CPU例外ハンドラの実行開始／リターン時のシステム状態と，CPU例外ハンドラ
+中でのxsns_dpnとxsns_xpnの動作を網羅的にテストする．
+
+【テスト項目】
+
+(A) CPU例外ハンドラ実行開始時にCPUロックフラグが変化しないこと
+
+(B) CPU例外ハンドラ実行開始時に割込み優先度マスクが変化しないこと
+	！CPU例外ハンドラ中で割込み優先度マスクを読めないため，テストできな
+	　い．
+
+(C) CPU例外ハンドラ実行開始時にディスパッチ禁止フラグが変化しないこと
+
+(D) CPU例外ハンドラ実行開始時にタスク例外処理禁止フラグが変化しないこと
+
+(E) CPU例外ハンドラリターン時にCPUロックフラグが元に戻ること
+
+(F) CPU例外ハンドラリターン時に割込み優先度マスクが元に戻ること
+
+(G) CPU例外ハンドラリターン時にディスパッチ禁止フラグが変化しないこと
+
+(H) CPU例外ハンドラリターン時にタスク例外処理禁止フラグが変化しないこと
+
+(I) xsns_xpnが正しい値を返すこと
+
+xsns_xpnは，CPU例外が発生した状況が次の条件をすべて満たす場合にfalse，
+そうでない場合にtrueを返す．
+　・タスクコンテキスト
+　・割込みロック解除状態
+　・CPUロック解除状態
+　・割込み優先度マスク全解除状態
+　・タスク例外許可状態
+
+(J) xsns_dpnが正しい値を返すこと
+
+xsns_dpnは，CPU例外が発生した状況が次の条件をすべて満たす場合にfalse，
+そうでない場合にtrueを返す．
+　・タスクコンテキスト
+　・割込みロック解除状態
+　・CPUロック解除状態
+　・割込み優先度マスク全解除状態
+　・ディスパッチ許可状態
+
+(K) タスク切換えによるリカバリーができること
+
+(L) タスク例外によるリカバリーができること
+
+【テストを実施する状況】
+
+CPU例外の発生する状況は，次のように分類することができる．これらの状況毎
+にテストプログラムを用意する．
+
+(a-1) 非タスクコンテキスト
+(a-2) タスクコンテキスト
+
+(b-1) 割込みロック状態
+(b-2) 割込みロック解除状態
+
+(c-1) CPUロック状態
+(c-2) CPUロック解除状態
+
+(d-1) 割込み優先度マスク＝TIPM_ENAALL
+(d-2) 割込み優先度マスク＝TMAX_INTPRI
+	 ！TMAX_INTPRI＝TMIN_INTPRIの場合は(d-3)と同じになるので実施しない．
+(d-3) 割込み優先度マスク＝TMIN_INTPRI
+(d-4) 割込み優先度マスク＝TMIN_INTPRI-1
+	 ！TMIN_INTPRI-1が設定できるかはターゲットに依存する．
+
+(e-1) ディスパッチ禁止状態
+(e-2) ディスパッチ許可状態
+
+(f-1) タスク例外禁止状態
+(f-2) タスク例外許可状態
+
+この組み合わせをすべてテストすることは現実的でないため，代表的なパター
+ンに絞り込む．
+
+まず，(a)～(c)の組み合わせで，次の5つのパターンをテストする．これらのテ
+ストをする際には，(d)～(f)については，(d-1)(e-1)(f-2)の組み合わせに固定
+する．
+
+(1) (a-1)(b-1)(c-2) → リカバリー不可
+	！(a-1)(b-1)(c-1)のテストは省く．
+(2) (a-1)(b-2)(c-1) → リカバリー不可
+(3) (a-1)(b-2)(c-2) → リカバリー不可
+
+(4) (a-2)(b-1)(c-2) → リカバリー不可
+	！(a-2)(b-1)(c-1)のテストは省く．
+(5) (a-2)(b-2)(c-1) → リカバリー不可
+
+次に，(a)～(c)を(a-2)(b-2)(c-2)に固定して，(d)～(f)の組み合わせで，次の
+8つのパターンをテストする．
+
+(6) (d-1)(e-2)(f-1) → タスク切換えによるリカバリー可能
+
+(7) (d-1)(e-1)(f-2) → タスク例外によるリカバリー可能
+
+(8) (d-2)(e-2)(f-2) → リカバリー不可
+	！(d-2)(e-1)(f-2)のテストは省く．
+
+(9) (d-3)(e-2)(f-2) → リカバリー不可
+	！(d-3)(e-1)(f-2)のテストは省く．
+
+(10) (d-4)(e-2)(f-2) → リカバリー不可
+	！(d-4)(e-1)(f-2)のテストは省く．
+
+(11) (d-1)(e-2)(f-2) → 両方法によるリカバリー可能
+
+(12) (d-1)(e-1)(f-1) → リカバリー不可
+		(d-2)～(d-4)×(e-1)×(f-1) のテスト（3パターン）は省く．
+
+(13) (d-3)(e-2)(f-1) → リカバリー不可
+		(d-2),(d-4)×(e-2)×(f-1) のテスト（2パターン）は省く．
+
+【使用リソース】
+
+TASK1: TA_ACT，中優先度，タスク例外処理ルーチン登録
+TASK2: TA_NULL，高優先度
+CPUEXC1: TA_NULL
+ALM1: TA_NULL
+
+以上
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc1.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc1.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc1.c	(revision 453)
@@ -0,0 +1,188 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2007-2013 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *		CPU例外処理のテスト(1)
+ *
+ * 【テストの目的】
+ *
+ *  非タスクコンテキスト，割込ロック状態で発生したCPU例外におけるシステ
+ *  ム状態のテスト．割込み優先度マスク＝TIPM_ENAALL，ディスパッチ禁止状
+ *  態，タスク例外許可状態でテストする．
+ *
+ * 【テスト項目】
+ *
+ *  いずれも，非タスクコンテキスト，割込ロック状態で発生したCPU例外にお
+ *  いて，
+ *
+ *	(A) CPU例外ハンドラ実行開始時にCPUロックフラグが変化しないこと
+ *		！割込みロック状態で発生したCPU例外では，システム状態を正しく読
+ *		めることが保証されないため，テストできない．
+ *	(B) CPU例外ハンドラ実行開始時に割込み優先度マスクが変化しないこと
+ *		！割込みロック状態で発生したCPU例外では，システム状態を正しく読
+ *		めることが保証されないため，テストできない．
+ *	(C) CPU例外ハンドラ実行開始時にディスパッチ禁止フラグが変化しないこと
+ *		！割込みロック状態で発生したCPU例外では，システム状態を正しく読
+ *		めることが保証されないため，テストできない．
+ *	(D) CPU例外ハンドラ実行開始時にタスク例外処理禁止フラグが変化しないこと
+ *		！割込みロック状態で発生したCPU例外では，システム状態を正しく読
+ *		めることが保証されないため，テストできない．
+ *	(E) CPU例外ハンドラリターン時にCPUロックフラグが元に戻ること
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(F) CPU例外ハンドラリターン時に割込み優先度マスクが元に戻ること
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(G) CPU例外ハンドラリターン時にディスパッチ禁止フラグが変化しないこと
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(H) CPU例外ハンドラリターン時にタスク例外処理禁止フラグが変化しないこと
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(I) xsns_xpnがtrueを返すこと
+ *	(J) xsns_dpnがtrueを返すこと
+ *
+ * 【使用リソース】
+ *
+ *	TASK1: TA_ACT，中優先度，タスク例外処理ルーチン登録
+ *	CPUEXC1: TA_NULL
+ *	ALM1: TA_NULL
+ *
+ * 【テストシーケンス】
+ *
+ *	== TASK1（中優先度）==
+ *	1:	状態のチェック
+ *		dis_dsp()
+ *		ena_tex()
+ *	2:	状態のチェック
+ *		sta_alm(ALM1, 1U)
+ *		アラームハンドラ1の実行を待つ
+ *	== ALM1 ==
+ *	3:	状態のチェック
+ *		SIL_LOC_INT()
+ *		RAISE_CPU_EXCEPTION
+ *	== CPUEXC1 ==
+ *	4:	xsns_xpn() == true			... (I)
+ *		xsns_dpn() == true			... (J)
+ *	5:	CPU例外ハンドラからリターンできない場合は，ここで終了
+ *	5:	リターン
+ *	== ALM1（続き）==
+ *	6:	SIL_UNL_LOC()
+ *	7:	状態のチェック				... (E)(G)(H)
+ *		リターン
+ *	== TASK1（続き）==
+ *	8:	状態のチェック				... (F)
+ *	9:	テスト終了
+ */
+
+#include <sil.h>
+#include <kernel.h>
+#include <t_syslog.h>
+#include <test_lib.h>
+#include "kernel_cfg.h"
+#include "test_cpuexc.h"
+
+volatile bool_t	alm1_flag = false;
+
+void
+task1(intptr_t exinf)
+{
+	ER		ercd;
+
+	test_start(__FILE__);
+
+	check_point(1);
+	check_state(false, false, TIPM_ENAALL, false, false, true);
+	ercd = dis_dsp();
+	check_ercd(ercd, E_OK);
+	ercd = ena_tex();
+	check_ercd(ercd, E_OK);
+
+	check_point(2);
+	check_state(false, false, TIPM_ENAALL, true, true, false);
+	ercd = sta_alm(ALM1, 1U);
+	check_ercd(ercd, E_OK);
+
+	while (!(alm1_flag));
+
+	check_point(8);
+	check_state(false, false, TIPM_ENAALL, true, true, false);
+
+	check_finish(9);
+}
+
+void
+tex_task1(TEXPTN texptn, intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+task2(intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+alarm1_handler(intptr_t exinf)
+{
+	SIL_PRE_LOC;
+
+	check_point(3);
+	check_state_i(true, false, true, true, false);
+	SIL_LOC_INT();
+	RAISE_CPU_EXCEPTION;
+
+	check_point(6);
+	SIL_UNL_INT();
+
+	check_point(7);
+	check_state_i(true, false, true, true, false);
+	alm1_flag = true;
+}
+
+void
+cpuexc_handler(void *p_excinf)
+{
+	check_point(4);
+	check_assert(xsns_xpn(p_excinf) == true);
+	check_assert(xsns_dpn(p_excinf) == true);
+
+#ifdef CANNOT_RETURN_CPUEXC
+	check_finish(5);
+#endif /* CANNOT_RETURN_CPUEXC */
+
+	check_point(5);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc10.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc10.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc10.c	(revision 453)
@@ -0,0 +1,162 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2007-2015 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *		CPU例外処理のテスト(10)
+ *
+ * 【テストの目的】
+ *
+ *  割込み優先度マスク＝TMIN_INTPRI-1，ディスパッチ許可状態，タスク例外
+ *  許可状態で発生したCPU例外におけるシステム状態のテスト．
+ *
+ *  このテストは，割込み優先度マスクをTMIN_INTPRI-1に設定できる場合のみ
+ *  実施する．
+ *
+ * 【テスト項目】
+ *
+ *  いずれも，割込み優先度マスク＝TMIN_INTPRI-1，ディスパッチ許可状態，
+ *  タスク例外許可状態で発生したCPU例外において，
+ *
+ *	(A) CPU例外ハンドラ実行開始時にCPUロックフラグが変化しないこと
+ *	(B) CPU例外ハンドラ実行開始時に割込み優先度マスクが変化しないこと
+ *		！CPU例外ハンドラ中で割込み優先度マスクを読めないため，テストで
+ *		きない．
+ *	(C) CPU例外ハンドラ実行開始時にディスパッチ禁止フラグが変化しないこと
+ *	(D) CPU例外ハンドラ実行開始時にタスク例外処理禁止フラグが変化しないこと
+ *	(E) CPU例外ハンドラリターン時にCPUロックフラグが元に戻ること
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(F) CPU例外ハンドラリターン時に割込み優先度マスクが元に戻ること
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(G) CPU例外ハンドラリターン時にディスパッチ禁止フラグが変化しないこと
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(H) CPU例外ハンドラリターン時にタスク例外処理禁止フラグが変化しないこと
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(I) xsns_xpnがtrueを返すこと
+ *	(J) xsns_dpnがtrueを返すこと
+ *
+ * 【使用リソース】
+ *
+ *	TASK1: TA_ACT，中優先度，タスク例外処理ルーチン登録
+ *	CPUEXC1: TA_NULL
+ *
+ * 【テストシーケンス】
+ *
+ *	== TASK1（中優先度）==
+ *	1:	状態のチェック
+ *		chg_ipm(TMIN_INTPRI-1)
+ *		ena_tex()
+ *	2:	状態のチェック
+ *		RAISE_CPU_EXCEPTION
+ *	== CPUEXC1 ==
+ *	3:	状態のチェック				... (A)(C)(D)
+ *		xsns_xpn() == true			... (I)
+ *		xsns_dpn() == true			... (J)
+ *	4:	CPU例外ハンドラからリターンできない場合は，ここで終了
+ *	4:	リターン
+ *	== TASK1（続き）==
+ *	5:	状態のチェック				... (E)(F)(G)(H)
+ *	6:	テスト終了
+ */
+
+#include <kernel.h>
+#include <test_lib.h>
+#include <t_syslog.h>
+#include "kernel_cfg.h"
+#include "test_cpuexc.h"
+
+void
+task1(intptr_t exinf)
+{
+	ER		ercd;
+
+	test_start(__FILE__);
+
+	check_point(1);
+	check_state(false, false, TIPM_ENAALL, false, false, true);
+	ercd = chg_ipm(TMIN_INTPRI - 1);
+	if (ercd == E_PAR) {
+		syslog_0(LOG_NOTICE, "This test program is not necessary.");
+		ext_ker();
+	}
+	check_ercd(ercd, E_OK);
+	ercd = ena_tex();
+	check_ercd(ercd, E_OK);
+
+	check_point(2);
+	check_state(false, false, TMIN_INTPRI - 1, false, true, false);
+	RAISE_CPU_EXCEPTION;
+
+	check_point(5);
+	check_state(false, false, TMIN_INTPRI - 1, false, true, false);
+
+	check_finish(6);
+}
+
+void
+tex_task1(TEXPTN texptn, intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+task2(intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+alarm1_handler(intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+cpuexc_handler(void *p_excinf)
+{
+	check_point(3);
+	check_state_i(true, false, false, true, false);
+	check_assert(xsns_xpn(p_excinf) == true);
+	check_assert(xsns_dpn(p_excinf) == true);
+
+#ifdef CANNOT_RETURN_CPUEXC
+	check_finish(4);
+#endif /* CANNOT_RETURN_CPUEXC */
+
+	check_point(4);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc11.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc11.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc11.c	(revision 453)
@@ -0,0 +1,256 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2007-2013 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *		CPU例外処理のテスト(11)
+ *
+ * 【テストの目的】
+ *
+ *  割込み優先度マスク＝TIPM_ENAALL，ディスパッチ許可状態，タスク例外許
+ *  可状態で発生したCPU例外におけるシステム状態のテスト．タスク切換えに
+ *  よりリカバリーできることもテストする．
+ *
+ * 【テスト項目】
+ *
+ *  いずれも，割込み優先度マスク＝TIPM_ENAALL，ディスパッチ許可状態，タ
+ *  スク例外許可状態で発生したCPU例外において，
+ *
+ *	(A) CPU例外ハンドラ実行開始時にCPUロックフラグが変化しないこと
+ *	(B) CPU例外ハンドラ実行開始時に割込み優先度マスクが変化しないこと
+ *		！CPU例外ハンドラ中で割込み優先度マスクを読めないため，テストで
+ *		きない．
+ *	(C) CPU例外ハンドラ実行開始時にディスパッチ禁止フラグが変化しないこと
+ *	(D) CPU例外ハンドラ実行開始時にタスク例外処理禁止フラグが変化しないこと
+ *	(E) CPU例外ハンドラリターン時にCPUロックフラグが元に戻ること
+ *	(F) CPU例外ハンドラリターン時に割込み優先度マスクが元に戻ること
+ *	(G) CPU例外ハンドラリターン時にディスパッチ禁止フラグが変化しないこと
+ *	(H) CPU例外ハンドラリターン時にタスク例外処理禁止フラグが変化しないこと
+ *	(I) xsns_xpnがfalseを返すこと
+ *	(J) xsns_dpnがfalseを返すこと
+ *	(K) タスク切換えによるリカバリーができること
+ *	(L) タスク例外によるリカバリーができること
+ *
+ * 【使用リソース】
+ *
+ *	TASK1: TA_ACT，中優先度，タスク例外処理ルーチン登録
+ *	TASK2: TA_NULL，高優先度
+ *	CPUEXC1: TA_NULL
+ *
+ * 【テストシーケンス】
+ *
+ *	== TASK1（中優先度，1回目）==
+ *	1:	状態のチェック
+ *		ena_tex()
+ *	2:	状態のチェック
+ *		RAISE_CPU_EXCEPTION
+ *	== CPUEXC1（1回目）==
+ *	3:	状態のチェック				... (A)(C)(D)
+ *		xsns_xpn() == false			... (I)
+ *		xsns_dpn() == false			... (J)
+ *	4:	iact_tsk(TASK2)
+ *		iloc_cpu()
+ *		リターン
+ *	== TASK2（高優先度）==
+ *	5:	状態のチェック				... (E)(F)(G)(H)
+ *	6:	ter_tsk(TASK1)				... (K)
+ *	7:	act_tsk(TASK1)				... (K)
+ *	8:	ext_tsk()
+ *	== TASK1（中優先度，2回目）==
+ *	9:	状態のチェック				... (K)
+ *		ena_tex()
+ *	10:	状態のチェック
+ *		RAISE_CPU_EXCEPTION
+ *	== CPUEXC1（2回目）==
+ *	11:	状態のチェック				... (A)(C)(D)
+ *		xsns_xpn() == false			... (I)
+ *		xsns_dpn() == false			... (J)
+ *	12:	iras_tex(TASK1, 1U)
+ *		iloc_cpu()
+ *		リターン
+ *	== TASK1のタスク例外処理ルーチン ==
+ *	13:	状態のチェック				... (E)(F)(G)(H)
+ *	14:	act_tsk(TASK1)				... (L)
+ *	15:	ext_tsk()					... (L)
+ *	== TASK1（中優先度，3回目）==
+ *	16:	状態のチェック				... (L)
+ *	17:	テスト終了
+ */
+
+#include <kernel.h>
+#include <test_lib.h>
+#include <t_syslog.h>
+#include "kernel_cfg.h"
+#include "test_cpuexc.h"
+
+int_t	task1_count = 0;
+
+void
+task1(intptr_t exinf)
+{
+	ER		ercd;
+
+	switch (++task1_count) {
+	case 1:
+		test_start(__FILE__);
+
+		check_point(1);
+		check_state(false, false, TIPM_ENAALL, false, false, true);
+		ercd = ena_tex();
+		check_ercd(ercd, E_OK);
+
+		check_point(2);
+		check_state(false, false, TIPM_ENAALL, false, false, false);
+		RAISE_CPU_EXCEPTION;
+
+		check_point(0);
+		break;
+
+	case 2:
+		check_point(9);
+		check_state(false, false, TIPM_ENAALL, false, false, true);
+		ercd = ena_tex();
+		check_ercd(ercd, E_OK);
+
+		check_point(10);
+		check_state(false, false, TIPM_ENAALL, false, false, false);
+		RAISE_CPU_EXCEPTION;
+
+		check_point(0);
+		break;
+
+	case 3:
+		check_point(16);
+		check_state(false, false, TIPM_ENAALL, false, false, true);
+
+		check_finish(17);
+		break;
+
+	default:
+		check_point(0);
+		break;
+	}
+}
+
+void
+tex_task1(TEXPTN texptn, intptr_t exinf)
+{
+	ER		ercd;
+
+	check_point(13);
+	check_state(false, false, TIPM_ENAALL, false, false, true);
+
+	check_point(14);
+	ercd = act_tsk(TASK1);
+	check_ercd(ercd, E_OK);
+
+	check_point(15);
+	ercd = ext_tsk();
+	check_ercd(ercd, E_OK);
+
+	check_point(0);
+}
+
+void
+task2(intptr_t exinf)
+{
+	ER		ercd;
+
+	check_point(5);
+	check_state(false, false, TIPM_ENAALL, false, false, true);
+
+	check_point(6);
+	ercd = ter_tsk(TASK1);
+	check_ercd(ercd, E_OK);
+
+	check_point(7);
+	ercd = act_tsk(TASK1);
+	check_ercd(ercd, E_OK);
+
+	check_point(8);
+	ercd = ext_tsk();
+	check_ercd(ercd, E_OK);
+
+	check_point(0);
+}
+
+void
+alarm1_handler(intptr_t exinf)
+{
+	check_point(0);
+}
+
+int_t	cpuexc_count = 0;
+
+void
+cpuexc_handler(void *p_excinf)
+{
+	ER		ercd;
+
+	switch (++cpuexc_count) {
+	case 1:
+		check_point(3);
+		check_state_i(true, false, false, true, false);
+		check_assert(xsns_xpn(p_excinf) == false);
+		check_assert(xsns_dpn(p_excinf) == false);
+
+		check_point(4);
+		ercd = iact_tsk(TASK2);
+		check_ercd(ercd, E_OK);
+		ercd = iloc_cpu();
+		check_ercd(ercd, E_OK);
+		break;
+
+	case 2:
+		check_point(11);
+		check_state_i(true, false, false, true, false);
+		check_assert(xsns_xpn(p_excinf) == false);
+		check_assert(xsns_dpn(p_excinf) == false);
+
+		check_point(12);
+		ercd = iras_tex(TASK1, 1U);
+		check_ercd(ercd, E_OK);
+		ercd = iloc_cpu();
+		check_ercd(ercd, E_OK);
+		break;
+
+	default:
+		check_point(0);
+		break;
+	}
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc12.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc12.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc12.c	(revision 453)
@@ -0,0 +1,152 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2007-2013 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *		CPU例外処理のテスト(12)
+ *
+ * 【テストの目的】
+ *
+ *  割込み優先度マスク＝TIPM_ENAALL，ディスパッチ禁止状態，タスク例外禁
+ *  止状態で発生したCPU例外におけるシステム状態のテスト．
+ *
+ * 【テスト項目】
+ *
+ *  いずれも，割込み優先度マスク＝TIPM_ENAALL，ディスパッチ禁止状態，タ
+ *  スク例外禁止状態で発生したCPU例外において，
+ *
+ *	(A) CPU例外ハンドラ実行開始時にCPUロックフラグが変化しないこと
+ *	(B) CPU例外ハンドラ実行開始時に割込み優先度マスクが変化しないこと
+ *		！CPU例外ハンドラ中で割込み優先度マスクを読めないため，テストで
+ *		きない．
+ *	(C) CPU例外ハンドラ実行開始時にディスパッチ禁止フラグが変化しないこと
+ *	(D) CPU例外ハンドラ実行開始時にタスク例外処理禁止フラグが変化しないこと
+ *	(E) CPU例外ハンドラリターン時にCPUロックフラグが元に戻ること
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(F) CPU例外ハンドラリターン時に割込み優先度マスクが元に戻ること
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(G) CPU例外ハンドラリターン時にディスパッチ禁止フラグが変化しないこと
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(H) CPU例外ハンドラリターン時にタスク例外処理禁止フラグが変化しないこと
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(I) xsns_xpnがtrueを返すこと
+ *	(J) xsns_dpnがtrueを返すこと
+ *
+ * 【使用リソース】
+ *
+ *	TASK1: TA_ACT，中優先度，タスク例外処理ルーチン登録
+ *	CPUEXC1: TA_NULL
+ *
+ * 【テストシーケンス】
+ *
+ *	== TASK1（中優先度）==
+ *	1:	状態のチェック
+ *		dis_dsp()
+ *	2:	状態のチェック
+ *		RAISE_CPU_EXCEPTION
+ *	== CPUEXC1 ==
+ *	3:	状態のチェック				... (A)(C)(D)
+ *		xsns_xpn() == true			... (I)
+ *		xsns_dpn() == true			... (J)
+ *	4:	CPU例外ハンドラからリターンできない場合は，ここで終了
+ *	4:	リターン
+ *	== TASK1（続き）==
+ *	5:	状態のチェック				... (E)(F)(G)(H)
+ *	6:	テスト終了
+ */
+
+#include <kernel.h>
+#include <test_lib.h>
+#include <t_syslog.h>
+#include "kernel_cfg.h"
+#include "test_cpuexc.h"
+
+void
+task1(intptr_t exinf)
+{
+	ER		ercd;
+
+	test_start(__FILE__);
+
+	check_point(1);
+	check_state(false, false, TIPM_ENAALL, false, false, true);
+	ercd = dis_dsp();
+	check_ercd(ercd, E_OK);
+
+	check_point(2);
+	check_state(false, false, TIPM_ENAALL, true, true, true);
+	RAISE_CPU_EXCEPTION;
+
+	check_point(5);
+	check_state(false, false, TIPM_ENAALL, true, true, true);
+
+	check_finish(6);
+}
+
+void
+tex_task1(TEXPTN texptn, intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+task2(intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+alarm1_handler(intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+cpuexc_handler(void *p_excinf)
+{
+	check_point(3);
+	check_state_i(true, false, true, true, true);
+	check_assert(xsns_xpn(p_excinf) == true);
+	check_assert(xsns_dpn(p_excinf) == true);
+
+#ifdef CANNOT_RETURN_CPUEXC
+	check_finish(4);
+#endif /* CANNOT_RETURN_CPUEXC */
+
+	check_point(4);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc13.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc13.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc13.c	(revision 453)
@@ -0,0 +1,152 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2007-2013 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *		CPU例外処理のテスト(13)
+ *
+ * 【テストの目的】
+ *
+ *  割込み優先度マスク＝TMIN_INTPRI，ディスパッチ許可状態，タスク例外禁
+ *  止状態で発生したCPU例外におけるシステム状態のテスト．
+ *
+ * 【テスト項目】
+ *
+ *  いずれも，割込み優先度マスク＝TMIN_INTPRI，ディスパッチ許可状態，タ
+ *  スク例外禁止状態で発生したCPU例外において，
+ *
+ *	(A) CPU例外ハンドラ実行開始時にCPUロックフラグが変化しないこと
+ *	(B) CPU例外ハンドラ実行開始時に割込み優先度マスクが変化しないこと
+ *		！CPU例外ハンドラ中で割込み優先度マスクを読めないため，テストで
+ *		きない．
+ *	(C) CPU例外ハンドラ実行開始時にディスパッチ禁止フラグが変化しないこと
+ *	(D) CPU例外ハンドラ実行開始時にタスク例外処理禁止フラグが変化しないこと
+ *	(E) CPU例外ハンドラリターン時にCPUロックフラグが元に戻ること
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(F) CPU例外ハンドラリターン時に割込み優先度マスクが元に戻ること
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(G) CPU例外ハンドラリターン時にディスパッチ禁止フラグが変化しないこと
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(H) CPU例外ハンドラリターン時にタスク例外処理禁止フラグが変化しないこと
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(I) xsns_xpnがtrueを返すこと
+ *	(J) xsns_dpnがtrueを返すこと
+ *
+ * 【使用リソース】
+ *
+ *	TASK1: TA_ACT，中優先度，タスク例外処理ルーチン登録
+ *	CPUEXC1: TA_NULL
+ *
+ * 【テストシーケンス】
+ *
+ *	== TASK1（中優先度）==
+ *	1:	状態のチェック
+ *		chg_ipm(TMIN_INTPRI)
+ *	2:	状態のチェック
+ *		RAISE_CPU_EXCEPTION
+ *	== CPUEXC1 ==
+ *	3:	状態のチェック				... (A)(C)(D)
+ *		xsns_xpn() == true			... (I)
+ *		xsns_dpn() == true			... (J)
+ *	4:	CPU例外ハンドラからリターンできない場合は，ここで終了
+ *	4:	リターン
+ *	== TASK1（続き）==
+ *	5:	状態のチェック				... (E)(F)(G)(H)
+ *	6:	テスト終了
+ */
+
+#include <kernel.h>
+#include <test_lib.h>
+#include <t_syslog.h>
+#include "kernel_cfg.h"
+#include "test_cpuexc.h"
+
+void
+task1(intptr_t exinf)
+{
+	ER		ercd;
+
+	test_start(__FILE__);
+
+	check_point(1);
+	check_state(false, false, TIPM_ENAALL, false, false, true);
+	ercd = chg_ipm(TMIN_INTPRI);
+	check_ercd(ercd, E_OK);
+
+	check_point(2);
+	check_state(false, false, TMIN_INTPRI, false, true, true);
+	RAISE_CPU_EXCEPTION;
+
+	check_point(5);
+	check_state(false, false, TMIN_INTPRI, false, true, true);
+
+	check_finish(6);
+}
+
+void
+tex_task1(TEXPTN texptn, intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+task2(intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+alarm1_handler(intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+cpuexc_handler(void *p_excinf)
+{
+	check_point(3);
+	check_state_i(true, false, false, true, true);
+	check_assert(xsns_xpn(p_excinf) == true);
+	check_assert(xsns_dpn(p_excinf) == true);
+
+#ifdef CANNOT_RETURN_CPUEXC
+	check_finish(4);
+#endif /* CANNOT_RETURN_CPUEXC */
+
+	check_point(4);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc2.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc2.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc2.c	(revision 453)
@@ -0,0 +1,180 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2007-2013 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *		CPU例外処理のテスト(2)
+ *
+ * 【テストの目的】
+ *
+ *  非タスクコンテキスト，割込ロック解除，CPUロック状態で発生したCPU例
+ *  外におけるシステム状態のテスト．割込み優先度マスク＝TIPM_ENAALL，ディ
+ *  スパッチ禁止状態，タスク例外許可状態でテストする．
+ *
+ * 【テスト項目】
+ *
+ *  いずれも，非タスクコンテキスト，割込ロック解除，CPUロック状態で発生
+ *  したCPU例外において，
+ *
+ *	(A) CPU例外ハンドラ実行開始時にCPUロックフラグが変化しないこと
+ *	(B) CPU例外ハンドラ実行開始時に割込み優先度マスクが変化しないこと
+ *		！CPU例外ハンドラ中で割込み優先度マスクを読めないため，テストで
+ *		きない．
+ *	(C) CPU例外ハンドラ実行開始時にディスパッチ禁止フラグが変化しないこと
+ *	(D) CPU例外ハンドラ実行開始時にタスク例外処理禁止フラグが変化しないこと
+ *	(E) CPU例外ハンドラリターン時にCPUロックフラグが元に戻ること
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(F) CPU例外ハンドラリターン時に割込み優先度マスクが元に戻ること
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(G) CPU例外ハンドラリターン時にディスパッチ禁止フラグが変化しないこと
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(H) CPU例外ハンドラリターン時にタスク例外処理禁止フラグが変化しないこと
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(I) xsns_xpnがtrueを返すこと
+ *	(J) xsns_dpnがtrueを返すこと
+ *
+ * 【使用リソース】
+ *
+ *	TASK1: TA_ACT，中優先度，タスク例外処理ルーチン登録
+ *	CPUEXC1: TA_NULL
+ *	ALM1: TA_NULL
+ *
+ * 【テストシーケンス】
+ *
+ *	== TASK1（中優先度）==
+ *	1:	状態のチェック
+ *		dis_dsp()
+ *		ena_tex()
+ *	2:	状態のチェック
+ *		sta_alm(ALM1, 1U)
+ *		アラームハンドラ1の実行を待つ
+ *	== ALM1 ==
+ *	3:	状態のチェック
+ *		iloc_cpu()
+ *		RAISE_CPU_EXCEPTION
+ *	== CPUEXC1 ==
+ *	4:	状態のチェック				... (A)(C)(D)
+ *		xsns_xpn() == true			... (I)
+ *		xsns_dpn() == true			... (J)
+ *	5:	CPU例外ハンドラからリターンできない場合は，ここで終了
+ *	5:	リターン
+ *	== ALM1（続き）==
+ *	6:	状態のチェック				... (E)(G)(H)
+ *		リターン
+ *	== TASK1（続き）==
+ *	7:	状態のチェック				... (F)
+ *	8:	テスト終了
+ */
+
+#include <kernel.h>
+#include <test_lib.h>
+#include <t_syslog.h>
+#include "kernel_cfg.h"
+#include "test_cpuexc.h"
+
+volatile bool_t	alm1_flag = false;
+
+void
+task1(intptr_t exinf)
+{
+	ER		ercd;
+
+	test_start(__FILE__);
+
+	check_point(1);
+	check_state(false, false, TIPM_ENAALL, false, false, true);
+	ercd = dis_dsp();
+	check_ercd(ercd, E_OK);
+	ercd = ena_tex();
+	check_ercd(ercd, E_OK);
+
+	check_point(2);
+	check_state(false, false, TIPM_ENAALL, true, true, false);
+	ercd = sta_alm(ALM1, 1U);
+	check_ercd(ercd, E_OK);
+
+	while (!(alm1_flag));
+
+	check_point(7);
+	check_state(false, false, TIPM_ENAALL, true, true, false);
+
+	check_finish(8);
+}
+
+void
+tex_task1(TEXPTN texptn, intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+task2(intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+alarm1_handler(intptr_t exinf)
+{
+	ER		ercd;
+
+	check_point(3);
+	check_state_i(true, false, true, true, false);
+	ercd = iloc_cpu();
+	check_ercd(ercd, E_OK);
+	RAISE_CPU_EXCEPTION;
+
+	check_point(6);
+	check_state_i(true, true, true, true, false);
+	alm1_flag = true;
+}
+
+void
+cpuexc_handler(void *p_excinf)
+{
+	check_point(4);
+	check_state_i(true, true, true, true, false);
+	check_assert(xsns_xpn(p_excinf) == true);
+	check_assert(xsns_dpn(p_excinf) == true);
+
+#ifdef CANNOT_RETURN_CPUEXC
+	check_finish(5);
+#endif /* CANNOT_RETURN_CPUEXC */
+
+	check_point(5);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc3.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc3.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc3.c	(revision 453)
@@ -0,0 +1,175 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2007-2013 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *		CPU例外処理のテスト(3)
+ *
+ * 【テストの目的】
+ *
+ *  非タスクコンテキスト，割込ロック解除，CPUロック解除で発生したCPU例
+ *  外におけるシステム状態のテスト．割込み優先度マスク＝TIPM_ENAALL，ディ
+ *  スパッチ禁止状態，タスク例外許可状態でテストする．
+ *
+ * 【テスト項目】
+ *
+ *  いずれも，非タスクコンテキスト，割込ロック解除，CPUロック解除で発生
+ *  したCPU例外において，
+ *
+ *	(A) CPU例外ハンドラ実行開始時にCPUロックフラグが変化しないこと
+ *	(B) CPU例外ハンドラ実行開始時に割込み優先度マスクが変化しないこと
+ *		！CPU例外ハンドラ中で割込み優先度マスクを読めないため，テストで
+ *		きない．
+ *	(C) CPU例外ハンドラ実行開始時にディスパッチ禁止フラグが変化しないこと
+ *	(D) CPU例外ハンドラ実行開始時にタスク例外処理禁止フラグが変化しないこと
+ *	(E) CPU例外ハンドラリターン時にCPUロックフラグが元に戻ること
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(F) CPU例外ハンドラリターン時に割込み優先度マスクが元に戻ること
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(G) CPU例外ハンドラリターン時にディスパッチ禁止フラグが変化しないこと
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(H) CPU例外ハンドラリターン時にタスク例外処理禁止フラグが変化しないこと
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(I) xsns_xpnがtrueを返すこと
+ *	(J) xsns_dpnがtrueを返すこと
+ *
+ * 【使用リソース】
+ *
+ *	TASK1: TA_ACT，中優先度，タスク例外処理ルーチン登録
+ *	CPUEXC1: TA_NULL
+ *	ALM1: TA_NULL
+ *
+ * 【テストシーケンス】
+ *
+ *	== TASK1（中優先度）==
+ *	1:	状態のチェック
+ *		dis_dsp()
+ *		ena_tex()
+ *	2:	状態のチェック
+ *		sta_alm(ALM1, 1U)
+ *		アラームハンドラ1の実行を待つ
+ *	== ALM1 ==
+ *	3:	状態のチェック
+ *		RAISE_CPU_EXCEPTION
+ *	== CPUEXC1 ==
+ *	4:	状態のチェック				... (A)(C)(D)
+ *		xsns_xpn() == true			... (I)
+ *		xsns_dpn() == true			... (J)
+ *	5:	CPU例外ハンドラからリターンできない場合は，ここで終了
+ *	5:	リターン
+ *	== ALM1（続き）==
+ *	6:	状態のチェック				... (E)(G)(H)
+ *		リターン
+ *	== TASK1（続き）==
+ *	7:	状態のチェック				... (F)
+ *	8:	テスト終了
+ */
+
+#include <kernel.h>
+#include <test_lib.h>
+#include <t_syslog.h>
+#include "kernel_cfg.h"
+#include "test_cpuexc.h"
+
+volatile bool_t	alm1_flag = false;
+
+void
+task1(intptr_t exinf)
+{
+	ER		ercd;
+
+	test_start(__FILE__);
+
+	check_point(1);
+	check_state(false, false, TIPM_ENAALL, false, false, true);
+	ercd = dis_dsp();
+	check_ercd(ercd, E_OK);
+	ercd = ena_tex();
+	check_ercd(ercd, E_OK);
+
+	check_point(2);
+	check_state(false, false, TIPM_ENAALL, true, true, false);
+	ercd = sta_alm(ALM1, 1U);
+	check_ercd(ercd, E_OK);
+
+	while (!(alm1_flag));
+
+	check_point(7);
+	check_state(false, false, TIPM_ENAALL, true, true, false);
+
+	check_finish(8);
+}
+
+void
+tex_task1(TEXPTN texptn, intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+task2(intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+alarm1_handler(intptr_t exinf)
+{
+	check_point(3);
+	check_state_i(true, false, true, true, false);
+	RAISE_CPU_EXCEPTION;
+
+	check_point(6);
+	check_state_i(true, false, true, true, false);
+	alm1_flag = true;
+}
+
+void
+cpuexc_handler(void *p_excinf)
+{
+	check_point(4);
+	check_state_i(true, false, true, true, false);
+	check_assert(xsns_xpn(p_excinf) == true);
+	check_assert(xsns_dpn(p_excinf) == true);
+
+#ifdef CANNOT_RETURN_CPUEXC
+	check_finish(5);
+#endif /* CANNOT_RETURN_CPUEXC */
+
+	check_point(5);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc4.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc4.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc4.c	(revision 453)
@@ -0,0 +1,168 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2007-2013 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *		CPU例外処理のテスト(4)
+ *
+ * 【テストの目的】
+ *
+ *  タスクコンテキスト，割込ロック状態で発生したCPU例外におけるシステム
+ *  状態のテスト．割込み優先度マスク＝TIPM_ENAALL，ディスパッチ禁止状態，
+ *  タスク例外許可状態でテストする．
+ *
+ * 【テスト項目】
+ *
+ *  いずれも，タスクコンテキスト，割込ロック状態で発生したCPU例外におい
+ *  て，
+ *
+ *	(A) CPU例外ハンドラ実行開始時にCPUロックフラグが変化しないこと
+ *		！割込みロック状態で発生したCPU例外では，システム状態を正しく読
+ *		めることが保証されないため，テストできない．
+ *	(B) CPU例外ハンドラ実行開始時に割込み優先度マスクが変化しないこと
+ *		！割込みロック状態で発生したCPU例外では，システム状態を正しく読
+ *		めることが保証されないため，テストできない．
+ *	(C) CPU例外ハンドラ実行開始時にディスパッチ禁止フラグが変化しないこと
+ *		！割込みロック状態で発生したCPU例外では，システム状態を正しく読
+ *		めることが保証されないため，テストできない．
+ *	(D) CPU例外ハンドラ実行開始時にタスク例外処理禁止フラグが変化しないこと
+ *		！割込みロック状態で発生したCPU例外では，システム状態を正しく読
+ *		めることが保証されないため，テストできない．
+ *	(E) CPU例外ハンドラリターン時にCPUロックフラグが元に戻ること
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(F) CPU例外ハンドラリターン時に割込み優先度マスクが元に戻ること
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(G) CPU例外ハンドラリターン時にディスパッチ禁止フラグが変化しないこと
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(H) CPU例外ハンドラリターン時にタスク例外処理禁止フラグが変化しないこと
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(I) xsns_xpnがtrueを返すこと
+ *	(J) xsns_dpnがtrueを返すこと
+ *
+ * 【使用リソース】
+ *
+ *	TASK1: TA_ACT，中優先度，タスク例外処理ルーチン登録
+ *	CPUEXC1: TA_NULL
+ *
+ * 【テストシーケンス】
+ *
+ *	== TASK1（中優先度）==
+ *	1:	状態のチェック
+ *		dis_dsp()
+ *		ena_tex()
+ *	2:	状態のチェック
+ *		SIL_LOC_INT()
+ *		RAISE_CPU_EXCEPTION
+ *	== CPUEXC1 ==
+ *	3:	xsns_xpn() == true			... (I)
+ *		xsns_dpn() == true			... (J)
+ *	4:	CPU例外ハンドラからリターンできない場合は，ここで終了
+ *	4:	リターン
+ *	== TASK1（続き）==
+ *	5:	SIL_UNL_LOC()
+ *	6:	状態のチェック				... (E)(F)(G)(H)
+ *	7:	テスト終了
+ */
+
+#include <sil.h>
+#include <kernel.h>
+#include <test_lib.h>
+#include <t_syslog.h>
+#include "kernel_cfg.h"
+#include "test_cpuexc.h"
+
+void
+task1(intptr_t exinf)
+{
+	ER		ercd;
+	SIL_PRE_LOC;
+
+	test_start(__FILE__);
+
+	check_point(1);
+	check_state(false, false, TIPM_ENAALL, false, false, true);
+	ercd = dis_dsp();
+	check_ercd(ercd, E_OK);
+	ercd = ena_tex();
+	check_ercd(ercd, E_OK);
+
+	check_point(2);
+	check_state(false, false, TIPM_ENAALL, true, true, false);
+	SIL_LOC_INT();
+	RAISE_CPU_EXCEPTION;
+
+	check_point(5);
+	SIL_UNL_INT();
+
+	check_point(6);
+	check_state(false, false, TIPM_ENAALL, true, true, false);
+
+	check_finish(7);
+}
+
+void
+tex_task1(TEXPTN texptn, intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+task2(intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+alarm1_handler(intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+cpuexc_handler(void *p_excinf)
+{
+	check_point(3);
+	check_assert(xsns_xpn(p_excinf) == true);
+	check_assert(xsns_dpn(p_excinf) == true);
+
+#ifdef CANNOT_RETURN_CPUEXC
+	check_finish(4);
+#endif /* CANNOT_RETURN_CPUEXC */
+
+	check_point(4);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc5.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc5.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc5.c	(revision 453)
@@ -0,0 +1,159 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2007-2013 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *		CPU例外処理のテスト(5)
+ *
+ * 【テストの目的】
+ *
+ *  タスクコンテキスト，割込ロック解除，CPUロック状態で発生したCPU例外
+ *  におけるシステム状態のテスト．割込み優先度マスク＝TIPM_ENAALL，ディ
+ *  スパッチ禁止状態，タスク例外許可状態でテストする．
+ *
+ * 【テスト項目】
+ *
+ *  いずれも，タスクコンテキスト，割込ロック解除，CPUロック状態で発生し
+ *  たCPU例外において，
+ *
+ *	(A) CPU例外ハンドラ実行開始時にCPUロックフラグが変化しないこと
+ *	(B) CPU例外ハンドラ実行開始時に割込み優先度マスクが変化しないこと
+ *		！CPU例外ハンドラ中で割込み優先度マスクを読めないため，テストで
+ *		きない．
+ *	(C) CPU例外ハンドラ実行開始時にディスパッチ禁止フラグが変化しないこと
+ *	(D) CPU例外ハンドラ実行開始時にタスク例外処理禁止フラグが変化しないこと
+ *	(E) CPU例外ハンドラリターン時にCPUロックフラグが元に戻ること
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(F) CPU例外ハンドラリターン時に割込み優先度マスクが元に戻ること
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(G) CPU例外ハンドラリターン時にディスパッチ禁止フラグが変化しないこと
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(H) CPU例外ハンドラリターン時にタスク例外処理禁止フラグが変化しないこと
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(I) xsns_xpnがtrueを返すこと
+ *	(J) xsns_dpnがtrueを返すこと
+ *
+ * 【使用リソース】
+ *
+ *	TASK1: TA_ACT，中優先度，タスク例外処理ルーチン登録
+ *	CPUEXC1: TA_NULL
+ *
+ * 【テストシーケンス】
+ *
+ *	== TASK1（中優先度）==
+ *	1:	状態のチェック
+ *		dis_dsp()
+ *		ena_tex()
+ *		loc_cpu()
+ *	2:	状態のチェック
+ *		RAISE_CPU_EXCEPTION
+ *	== CPUEXC1 ==
+ *	3:	状態のチェック				... (A)(C)(D)
+ *		xsns_xpn() == true			... (I)
+ *		xsns_dpn() == true			... (J)
+ *	4:	CPU例外ハンドラからリターンできない場合は，ここで終了
+ *	4:	リターン
+ *	== TASK1（続き）==
+ *	5:	状態のチェック				... (E)(F)(G)(H)
+ *	6:	テスト終了
+ */
+
+#include <kernel.h>
+#include <test_lib.h>
+#include <t_syslog.h>
+#include "kernel_cfg.h"
+#include "test_cpuexc.h"
+
+void
+task1(intptr_t exinf)
+{
+	ER		ercd;
+
+	test_start(__FILE__);
+
+	check_point(1);
+	check_state(false, false, TIPM_ENAALL, false, false, true);
+	ercd = dis_dsp();
+	check_ercd(ercd, E_OK);
+	ercd = ena_tex();
+	check_ercd(ercd, E_OK);
+	ercd = loc_cpu();
+	check_ercd(ercd, E_OK);
+
+	check_point(2);
+	check_state(false, true, TIPM_ENAALL, true, true, false);
+	RAISE_CPU_EXCEPTION;
+
+	check_point(5);
+	check_state(false, true, TIPM_ENAALL, true, true, false);
+
+	check_finish(6);
+}
+
+void
+tex_task1(TEXPTN texptn, intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+task2(intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+alarm1_handler(intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+cpuexc_handler(void *p_excinf)
+{
+	check_point(3);
+	check_state_i(true, true, true, true, false);
+	check_assert(xsns_xpn(p_excinf) == true);
+	check_assert(xsns_dpn(p_excinf) == true);
+
+#ifdef CANNOT_RETURN_CPUEXC
+	check_finish(4);
+#endif /* CANNOT_RETURN_CPUEXC */
+
+	check_point(4);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc6.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc6.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc6.c	(revision 453)
@@ -0,0 +1,183 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2007-2013 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *		CPU例外処理のテスト(6)
+ *
+ * 【テストの目的】
+ *
+ *  割込み優先度マスク＝TIPM_ENAALL，ディスパッチ許可状態，タスク例外禁
+ *  止状態で発生したCPU例外におけるシステム状態のテスト．タスク切換えに
+ *  よりリカバリーできることもテストする．
+ *
+ * 【テスト項目】
+ *
+ *  いずれも，割込み優先度マスク＝TIPM_ENAALL，ディスパッチ許可状態，タ
+ *  スク例外禁止状態で発生したCPU例外において，
+ *
+ *	(A) CPU例外ハンドラ実行開始時にCPUロックフラグが変化しないこと
+ *	(B) CPU例外ハンドラ実行開始時に割込み優先度マスクが変化しないこと
+ *		！CPU例外ハンドラ中で割込み優先度マスクを読めないため，テストで
+ *		きない．
+ *	(C) CPU例外ハンドラ実行開始時にディスパッチ禁止フラグが変化しないこと
+ *	(D) CPU例外ハンドラ実行開始時にタスク例外処理禁止フラグが変化しないこと
+ *	(E) CPU例外ハンドラリターン時にCPUロックフラグが元に戻ること
+ *	(F) CPU例外ハンドラリターン時に割込み優先度マスクが元に戻ること
+ *	(G) CPU例外ハンドラリターン時にディスパッチ禁止フラグが変化しないこと
+ *	(H) CPU例外ハンドラリターン時にタスク例外処理禁止フラグが変化しないこと
+ *	(I) xsns_xpnがtrueを返すこと
+ *	(J) xsns_dpnがfalseを返すこと
+ *	(K) タスク切換えによるリカバリーができること
+ *
+ * 【使用リソース】
+ *
+ *	TASK1: TA_ACT，中優先度，タスク例外処理ルーチン登録
+ *	TASK2: TA_NULL，高優先度
+ *	CPUEXC1: TA_NULL
+ *
+ * 【テストシーケンス】
+ *
+ *	== TASK1（中優先度，1回目）==
+ *	1:	状態のチェック
+ *	2:	RAISE_CPU_EXCEPTION
+ *	== CPUEXC1 ==
+ *	3:	状態のチェック				... (A),(C),(D)
+ *		xsns_xpn() == true			... (I)
+ *		xsns_dpn() == false			... (J)
+ *  4:	iact_tsk(TASK2)
+ *		iloc_cpu()
+ *  	リターン
+ *	== TASK2（高優先度）==
+ *	5:	状態のチェック				... (E),(F),(G),(H)
+ *	6:	ter_tsk(TASK1)				... (K)
+ *	7:	act_tsk(TASK1)				... (K)
+ *	8:	ext_tsk()
+ *	== TASK1（中優先度，2回目）==
+ *	9:	状態のチェック				... (K)
+ *	10:	テスト終了
+ */
+
+#include <kernel.h>
+#include <test_lib.h>
+#include <t_syslog.h>
+#include "kernel_cfg.h"
+#include "test_cpuexc.h"
+
+int_t	task1_count = 0;
+
+void
+task1(intptr_t exinf)
+{
+	switch (++task1_count) {
+	case 1:
+		test_start(__FILE__);
+
+		check_point(1);
+		check_state(false, false, TIPM_ENAALL, false, false, true);
+
+		check_point(2);
+		RAISE_CPU_EXCEPTION;
+
+		check_point(0);
+		break;
+
+	case 2:
+		check_point(9);
+		check_state(false, false, TIPM_ENAALL, false, false, true);
+
+		check_finish(10);
+		break;
+
+	default:
+		check_point(0);
+		break;
+	}
+}
+
+void
+tex_task1(TEXPTN texptn, intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+task2(intptr_t exinf)
+{
+	ER		ercd;
+
+	check_point(5);
+	check_state(false, false, TIPM_ENAALL, false, false, true);
+
+	check_point(6);
+	ercd = ter_tsk(TASK1);
+	check_ercd(ercd, E_OK);
+
+	check_point(7);
+	ercd = act_tsk(TASK1);
+	check_ercd(ercd, E_OK);
+
+	check_point(8);
+	ercd = ext_tsk();
+	check_ercd(ercd, E_OK);
+
+	check_point(0);
+}
+
+void
+alarm1_handler(intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+cpuexc_handler(void *p_excinf)
+{
+	ER		ercd;
+
+	check_point(3);
+	check_state_i(true, false, false, true, true);
+	check_assert(xsns_xpn(p_excinf) == true);
+	check_assert(xsns_dpn(p_excinf) == false);
+
+	check_point(4);
+	ercd = iact_tsk(TASK2);
+	check_ercd(ercd, E_OK);
+	ercd = iloc_cpu();
+	check_ercd(ercd, E_OK);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc7.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc7.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc7.c	(revision 453)
@@ -0,0 +1,187 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2007-2013 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *		CPU例外処理のテスト(7)
+ *
+ * 【テストの目的】
+ *
+ *  割込み優先度マスク＝TIPM_ENAALL，ディスパッチ禁止状態，タスク例外許
+ *  可状態で発生したCPU例外におけるシステム状態のテスト．タスク例外によ
+ *  りリカバリーできることもテストする．
+ *
+ * 【テスト項目】
+ *
+ *  いずれも，割込み優先度マスク＝TIPM_ENAALL，ディスパッチ禁止状態，タ
+ *  スク例外許可状態で発生したCPU例外において，
+ *
+ *	(A) CPU例外ハンドラ実行開始時にCPUロックフラグが変化しないこと
+ *	(B) CPU例外ハンドラ実行開始時に割込み優先度マスクが変化しないこと
+ *		！CPU例外ハンドラ中で割込み優先度マスクを読めないため，テストで
+ *		きない．
+ *	(C) CPU例外ハンドラ実行開始時にディスパッチ禁止フラグが変化しないこと
+ *	(D) CPU例外ハンドラ実行開始時にタスク例外処理禁止フラグが変化しないこと
+ *	(E) CPU例外ハンドラリターン時にCPUロックフラグが元に戻ること
+ *	(F) CPU例外ハンドラリターン時に割込み優先度マスクが元に戻ること
+ *	(G) CPU例外ハンドラリターン時にディスパッチ禁止フラグが変化しないこと
+ *	(H) CPU例外ハンドラリターン時にタスク例外処理禁止フラグが変化しないこと
+ *	(I) xsns_xpnがfalseを返すこと
+ *	(J) xsns_dpnがtrueを返すこと
+ *	(L) タスク例外によるリカバリーができること
+ *
+ * 【使用リソース】
+ *
+ *	TASK1: TA_ACT，中優先度，タスク例外処理ルーチン登録
+ *	CPUEXC1: TA_NULL
+ *
+ * 【テストシーケンス】
+ *
+ *	== TASK1（中優先度，1回目）==
+ *	1:	状態のチェック
+ *		dis_dsp()
+ *		ena_tex()
+ *	2:	状態のチェック
+ *		RAISE_CPU_EXCEPTION
+ *	== CPUEXC1 ==
+ *	3:	状態のチェック				... (A),(C),(D)
+ *		xsns_xpn() == false			... (I)
+ *		xsns_dpn() == true			... (J)
+ *	4:	iras_tex(TASK1, 1U)
+ *		iloc_cpu()
+ *		リターン
+ *	== TASK1のタスク例外処理ルーチン ==
+ *	5:	状態のチェック				... (E),(F),(G),(H)
+ *	6:	act_tsk(TASK1)				... (L)
+ *	7:	ext_tsk()					... (L)
+ *	== TASK1（中優先度，2回目）==
+ *	8:	状態のチェック				... (L)
+ *	9:	テスト終了
+ */
+
+#include <kernel.h>
+#include <test_lib.h>
+#include <t_syslog.h>
+#include "kernel_cfg.h"
+#include "test_cpuexc.h"
+
+int_t	task1_count = 0;
+
+void
+task1(intptr_t exinf)
+{
+	ER		ercd;
+
+	switch (++task1_count) {
+	case 1:
+		test_start(__FILE__);
+
+		check_point(1);
+		check_state(false, false, TIPM_ENAALL, false, false, true);
+		ercd = dis_dsp();
+		check_ercd(ercd, E_OK);
+		ercd = ena_tex();
+		check_ercd(ercd, E_OK);
+
+		check_point(2);
+		check_state(false, false, TIPM_ENAALL, true, true, false);
+		RAISE_CPU_EXCEPTION;
+
+		check_point(0);
+		break;
+
+	case 2:
+		check_point(8);
+		check_state(false, false, TIPM_ENAALL, false, false, true);
+
+		check_finish(9);
+		break;
+
+	default:
+		check_point(0);
+		break;
+	}
+}
+
+void
+tex_task1(TEXPTN texptn, intptr_t exinf)
+{
+	ER		ercd;
+
+	check_point(5);
+	check_state(false, false, TIPM_ENAALL, true, true, true);
+
+	check_point(6);
+	ercd = act_tsk(TASK1);
+	check_ercd(ercd, E_OK);
+
+	check_point(7);
+	ercd = ext_tsk();
+	check_ercd(ercd, E_OK);
+
+	check_point(0);
+}
+
+void
+task2(intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+alarm1_handler(intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+cpuexc_handler(void *p_excinf)
+{
+	ER		ercd;
+
+	check_point(3);
+	check_state_i(true, false, true, true, false);
+	check_assert(xsns_xpn(p_excinf) == false);
+	check_assert(xsns_dpn(p_excinf) == true);
+
+	check_point(4);
+	ercd = iras_tex(TASK1, 1U);
+	check_ercd(ercd, E_OK);
+	ercd = iloc_cpu();
+	check_ercd(ercd, E_OK);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc8.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc8.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc8.c	(revision 453)
@@ -0,0 +1,162 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2007-2013 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *		CPU例外処理のテスト(8)
+ *
+ * 【テストの目的】
+ *
+ *  割込み優先度マスク＝TMAX_INTPRI，ディスパッチ許可状態，タスク例外許
+ *  可状態で発生したCPU例外におけるシステム状態のテスト．
+ *
+ *  このテストは，TMAX_INTPRIとTMIN_INTPRIが異なる場合のみ実施する．
+ *
+ * 【テスト項目】
+ *
+ *  いずれも，割込み優先度マスク＝TMAX_INTPRI，ディスパッチ許可状態，タ
+ *  スク例外許可状態で発生したCPU例外において，
+ *
+ *	(A) CPU例外ハンドラ実行開始時にCPUロックフラグが変化しないこと
+ *	(B) CPU例外ハンドラ実行開始時に割込み優先度マスクが変化しないこと
+ *		！CPU例外ハンドラ中で割込み優先度マスクを読めないため，テストで
+ *		きない．
+ *	(C) CPU例外ハンドラ実行開始時にディスパッチ禁止フラグが変化しないこと
+ *	(D) CPU例外ハンドラ実行開始時にタスク例外処理禁止フラグが変化しないこと
+ *	(E) CPU例外ハンドラリターン時にCPUロックフラグが元に戻ること
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(F) CPU例外ハンドラリターン時に割込み優先度マスクが元に戻ること
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(G) CPU例外ハンドラリターン時にディスパッチ禁止フラグが変化しないこと
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(H) CPU例外ハンドラリターン時にタスク例外処理禁止フラグが変化しないこと
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(I) xsns_xpnがtrueを返すこと
+ *	(J) xsns_dpnがtrueを返すこと
+ *
+ * 【使用リソース】
+ *
+ *	TASK1: TA_ACT，中優先度，タスク例外処理ルーチン登録
+ *	CPUEXC1: TA_NULL
+ *
+ * 【テストシーケンス】
+ *
+ *	== TASK1（中優先度）==
+ *	1:	状態のチェック
+ *		chg_ipm(TMAX_INTPRI)
+ *		ena_tex()
+ *	2:	状態のチェック
+ *		RAISE_CPU_EXCEPTION
+ *	== CPUEXC1 ==
+ *	3:	状態のチェック				... (A)(C)(D)
+ *		xsns_xpn() == true			... (I)
+ *		xsns_dpn() == true			... (J)
+ *	4:	CPU例外ハンドラからリターンできない場合は，ここで終了
+ *	4:	リターン
+ *	== TASK1（続き）==
+ *	5:	状態のチェック				... (E)(F)(G)(H)
+ *	6:	テスト終了
+ */
+
+#include <kernel.h>
+#include <test_lib.h>
+#include <t_syslog.h>
+#include "kernel_cfg.h"
+#include "test_cpuexc.h"
+
+void
+task1(intptr_t exinf)
+{
+	ER		ercd;
+
+	test_start(__FILE__);
+
+	if (TMAX_INTPRI == TMIN_INTPRI) {
+		syslog_0(LOG_NOTICE, "This test program is not necessary.");
+		ext_ker();
+	}
+
+	check_point(1);
+	check_state(false, false, TIPM_ENAALL, false, false, true);
+	ercd = chg_ipm(TMAX_INTPRI);
+	check_ercd(ercd, E_OK);
+	ercd = ena_tex();
+	check_ercd(ercd, E_OK);
+
+	check_point(2);
+	check_state(false, false, TMAX_INTPRI, false, true, false);
+	RAISE_CPU_EXCEPTION;
+
+	check_point(5);
+	check_state(false, false, TMAX_INTPRI, false, true, false);
+
+	check_finish(6);
+}
+
+void
+tex_task1(TEXPTN texptn, intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+task2(intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+alarm1_handler(intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+cpuexc_handler(void *p_excinf)
+{
+	check_point(3);
+	check_state_i(true, false, false, true, false);
+	check_assert(xsns_xpn(p_excinf) == true);
+	check_assert(xsns_dpn(p_excinf) == true);
+
+#ifdef CANNOT_RETURN_CPUEXC
+	check_finish(4);
+#endif /* CANNOT_RETURN_CPUEXC */
+
+	check_point(4);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc9.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc9.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_cpuexc9.c	(revision 453)
@@ -0,0 +1,155 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2007-2013 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *		CPU例外処理のテスト(9)
+ *
+ * 【テストの目的】
+ *
+ *  割込み優先度マスク＝TMIN_INTPRI，ディスパッチ許可状態，タスク例外許
+ *  可状態で発生したCPU例外におけるシステム状態のテスト．
+ *
+ * 【テスト項目】
+ *
+ *  いずれも，割込み優先度マスク＝TMIN_INTPRI，ディスパッチ許可状態，タ
+ *  スク例外許可状態で発生したCPU例外において，
+ *
+ *	(A) CPU例外ハンドラ実行開始時にCPUロックフラグが変化しないこと
+ *	(B) CPU例外ハンドラ実行開始時に割込み優先度マスクが変化しないこと
+ *		！CPU例外ハンドラ中で割込み優先度マスクを読めないため，テストで
+ *		きない．
+ *	(C) CPU例外ハンドラ実行開始時にディスパッチ禁止フラグが変化しないこと
+ *	(D) CPU例外ハンドラ実行開始時にタスク例外処理禁止フラグが変化しないこと
+ *	(E) CPU例外ハンドラリターン時にCPUロックフラグが元に戻ること
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(F) CPU例外ハンドラリターン時に割込み優先度マスクが元に戻ること
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(G) CPU例外ハンドラリターン時にディスパッチ禁止フラグが変化しないこと
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(H) CPU例外ハンドラリターン時にタスク例外処理禁止フラグが変化しないこと
+ *		！CPU例外ハンドラからリターンできる場合のみテストする．
+ *	(I) xsns_xpnがtrueを返すこと
+ *	(J) xsns_dpnがtrueを返すこと
+ *
+ * 【使用リソース】
+ *
+ *	TASK1: TA_ACT，中優先度，タスク例外処理ルーチン登録
+ *	CPUEXC1: TA_NULL
+ *
+ * 【テストシーケンス】
+ *
+ *	== TASK1（中優先度）==
+ *	1:	状態のチェック
+ *		chg_ipm(TMIN_INTPRI)
+ *		ena_tex()
+ *	2:	状態のチェック
+ *		RAISE_CPU_EXCEPTION
+ *	== CPUEXC1 ==
+ *	3:	状態のチェック				... (A)(C)(D)
+ *		xsns_xpn() == true			... (I)
+ *		xsns_dpn() == true			... (J)
+ *	4:	CPU例外ハンドラからリターンできない場合は，ここで終了
+ *	4:	リターン
+ *	== TASK1（続き）==
+ *	5:	状態のチェック				... (E)(F)(G)(H)
+ *	6:	テスト終了
+ */
+
+#include <kernel.h>
+#include <test_lib.h>
+#include <t_syslog.h>
+#include "kernel_cfg.h"
+#include "test_cpuexc.h"
+
+void
+task1(intptr_t exinf)
+{
+	ER		ercd;
+
+	test_start(__FILE__);
+
+	check_point(1);
+	check_state(false, false, TIPM_ENAALL, false, false, true);
+	ercd = chg_ipm(TMIN_INTPRI);
+	check_ercd(ercd, E_OK);
+	ercd = ena_tex();
+	check_ercd(ercd, E_OK);
+
+	check_point(2);
+	check_state(false, false, TMIN_INTPRI, false, true, false);
+	RAISE_CPU_EXCEPTION;
+
+	check_point(5);
+	check_state(false, false, TMIN_INTPRI, false, true, false);
+
+	check_finish(6);
+}
+
+void
+tex_task1(TEXPTN texptn, intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+task2(intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+alarm1_handler(intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+cpuexc_handler(void *p_excinf)
+{
+	check_point(3);
+	check_state_i(true, false, false, true, false);
+	check_assert(xsns_xpn(p_excinf) == true);
+	check_assert(xsns_dpn(p_excinf) == true);
+
+#ifdef CANNOT_RETURN_CPUEXC
+	check_finish(4);
+#endif /* CANNOT_RETURN_CPUEXC */
+
+	check_point(4);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_dlynse.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_dlynse.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_dlynse.c	(revision 453)
@@ -0,0 +1,120 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2007-2013 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		sil_dly_nseに関するテスト
+ */
+
+#include <kernel.h>
+#include <sil.h>
+#include <test_lib.h>
+#include <t_syslog.h>
+#include "kernel_cfg.h"
+#include "test_dlynse.h"
+
+/*
+ *  SIL_DLY_TIM1とSIL_DLY_TIM2を参照するために，カーネル用のヘッダファ
+ *  イルをインクルードする．
+ */
+#include "kernel/kernel_impl.h"
+
+#define	NO_LOOP		ULONG_C(1000000)
+
+SYSTIM	empty_time;
+
+static void
+test_empty(void)
+{
+	SYSTIM	stime, etime;
+	volatile ulong_t	i;
+
+	get_tim(&stime);
+	for (i = 0; i < NO_LOOP; i++) {
+	}
+	get_tim(&etime);
+	empty_time = etime - stime;
+	syslog(LOG_NOTICE, "empty loop: %u", empty_time);
+	syslog_flush();
+}
+
+static void
+test_dly_nse(ulong_t dlytim)
+{
+	SYSTIM	stime, etime, delay_time;
+	volatile ulong_t	i;
+
+	get_tim(&stime);
+	for (i = 0; i < NO_LOOP; i++) {
+		sil_dly_nse(dlytim);
+	}
+	get_tim(&etime);
+	delay_time = (etime - stime) - empty_time;
+	syslog(LOG_NOTICE, "sil_dly_nse(%u): %u %s", (uint_t)(dlytim),
+				(uint_t)(delay_time), delay_time > dlytim ? "OK" : "NG");
+	syslog_flush();
+}
+
+void
+main_task(intptr_t exinf)
+{
+	test_start(__FILE__);
+
+	test_empty();
+
+	syslog(LOG_NOTICE, "-- for fitting parameters --");
+	test_dly_nse(0);
+	test_dly_nse(SIL_DLY_TIM1);
+	test_dly_nse(SIL_DLY_TIM1 + SIL_DLY_TIM2 * 1);
+	test_dly_nse(SIL_DLY_TIM1 + SIL_DLY_TIM2 * 2);
+	test_dly_nse(SIL_DLY_TIM1 + SIL_DLY_TIM2 * 3);
+	test_dly_nse(SIL_DLY_TIM1 + SIL_DLY_TIM2 * 4);
+	test_dly_nse(SIL_DLY_TIM1 + SIL_DLY_TIM2 * 5);
+	test_dly_nse(SIL_DLY_TIM1 + SIL_DLY_TIM2 * 10);
+	test_dly_nse(SIL_DLY_TIM1 + SIL_DLY_TIM2 * 20);
+	test_dly_nse(SIL_DLY_TIM1 + SIL_DLY_TIM2 * 50);
+
+	syslog(LOG_NOTICE, "-- for checking boundary conditions --");
+	test_dly_nse(SIL_DLY_TIM1 + 1);
+	test_dly_nse(SIL_DLY_TIM1 + SIL_DLY_TIM2 * 1 + 1);
+	test_dly_nse(SIL_DLY_TIM1 + SIL_DLY_TIM2 * 2 + 1);
+
+	test_finish();
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_dlynse.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_dlynse.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_dlynse.cfg	(revision 453)
@@ -0,0 +1,14 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *  sil_dly_nseに関するテストのシステムコンフィギュレーションファイル
+ */
+INCLUDE("target_timer.cfg");
+INCLUDE("syssvc/syslog.cfg");
+INCLUDE("syssvc/banner.cfg");
+INCLUDE("syssvc/serial.cfg");
+
+#include "test_dlynse.h"
+CRE_TSK(MAIN_TASK, { TA_ACT, 0, main_task, MAIN_PRIORITY, STACK_SIZE, NULL });
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_dlynse.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_dlynse.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_dlynse.h	(revision 453)
@@ -0,0 +1,68 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2006,2007 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ *		sil_dly_nseに関するテスト
+ */
+
+/*
+ *  ターゲット依存の定義
+ */
+#include "target_test.h"
+
+/*
+ *  各タスクの優先度の定義
+ */
+#define MAIN_PRIORITY	10
+
+/*
+ *  ターゲットに依存する可能性のある定数の定義
+ */
+#ifndef STACK_SIZE
+#define	STACK_SIZE		4096		/* タスクのスタックサイズ */
+#endif /* STACK_SIZE */
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+#ifndef TOPPERS_MACRO_ONLY
+
+extern void	main_task(intptr_t exinf);
+
+#endif /* TOPPERS_MACRO_ONLY */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sem1.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sem1.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sem1.c	(revision 453)
@@ -0,0 +1,615 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2008-2014 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *		セマフォ機能のテスト(1)
+ *
+ * 【テストの目的】
+ *
+ *  sig_sem，wai_sem，CRE_SEMを網羅的にテストする．
+ *  ただし，CRE_SEMのエラーのテストは除く．
+ *
+ * 【テスト項目】
+ *
+ *	(A) sig_semの静的エラーのテスト
+ *		(A-1) 非タスクコンテキストからの呼出し
+ *		(A-2) CPUロック状態からの呼出し
+ *		(A-3) semidが不正（小さすぎる）
+ *		(A-4) semidが不正（大きすぎる）
+ *	(B) sig_semによりセマフォ待ち状態のタスクが待ち解除される
+ *		(B-1) 待ち解除されたタスクに切り換わる
+ *		(B-2) ディスパッチ保留状態で，切り換わらない
+ *		(B-3) 待ち解除されたタスクが強制待ち状態で，切り換わらない
+ *		(B-4) 待ち解除されたタスクが優先度が低く，切り換わらない
+ *	(C) sig_semによりセマフォの資源数が1増える
+ *		(C-1) セマフォの資源数が0から1になる
+ *		(C-2) セマフォの資源数が1から2になる
+ *	(D) sig_semがE_QOVRエラーとなる
+ *		(D-1) セマフォの最大資源数が1の時
+ *		(D-2) セマフォの最大資源数が2の時
+ *	(E) wai_semの静的エラーのテスト
+ *		(E-1) 非タスクコンテキストからの呼出し
+ *		(E-2) CPUロック状態からの呼出し
+ *		(E-3) ディスパッチ禁止状態からの呼出し
+ *		(E-4) 割込み優先度マスク全解除でない状態からの呼出し
+ *		(E-5) semidが不正（小さすぎる）
+ *		(E-6) semidが不正（大きすぎる）
+ *	(F) wai_semによりセマフォの資源数が1減る
+ *		(F-1) セマフォの資源数が1から0になる
+ *		(F-2) セマフォの資源数が2から1になる
+ *	(G) wai_semによりセマフォ待ち状態になる
+ *		(G-1) TA_TNULL属性のセマフォで，待っているタスクがなかった場合
+ *		(G-2) TA_TNULL属性のセマフォで，待っているタスクがあった場合
+ *		(G-3) TA_TPRI属性のセマフォで，待っているタスクがなかった場合
+ *		(G-4) TA_TPRI属性のセマフォで，優先度が高いタスクが待っている場合
+ *		(G-5) TA_TPRI属性のセマフォで，優先度が同じタスクが待っている場合
+ *		(G-6) TA_TPRI属性のセマフォで，優先度が低いタスクが待っている場合
+ *	(H) セマフォ待ち状態が強制解除される
+ *	(I) セマフォ待ち状態の間にセマフォが初期化される
+ *	(J) セマフォの資源数の初期値が正しく設定される
+ *		(J-1) セマフォの資源数の初期値が0
+ *		(J-2) セマフォの資源数の初期値が1
+ *		(J-3) セマフォの資源数の初期値が2
+ *
+ * 【使用リソース】
+ *
+ *	TASK1: 中優先度タスク，TA_ACT属性
+ *	TASK2: 高優先度タスク
+ *	TASK3: 低優先度タスク
+ *	TASK4: 中優先度タスク
+ *	TASK5: 中優先度タスク
+ *	ALM1:  アラームハンドラ
+ *  SEM1:  TA_NULL属性，初期資源数1，最大資源数1
+ *  SEM2:  TA_NULL属性，初期資源数2，最大資源数2
+ *  SEM3:  TA_TPRI属性，初期資源数0，最大資源数1
+ *
+ * 【テストシーケンス】
+ *
+ *	== TASK1（優先度：中）==
+ *  1:	ref_sem(SEM1, &rsem)
+ *		assert(rsem.wtskid == TSK_NONE)
+ *		assert(rsem.semcnt == 1)			... (J-2)
+ *  	ref_sem(SEM2, &rsem)
+ *		assert(rsem.wtskid == TSK_NONE)
+ *		assert(rsem.semcnt == 2)			... (J-3)
+ *  	ref_sem(SEM3, &rsem)
+ *		assert(rsem.wtskid == TSK_NONE)
+ *		assert(rsem.semcnt == 0)			... (J-1)
+ *	2:	loc_cpu()
+ *		sig_sem(SEM1) -> E_CTX				... (A-2)
+ *		wai_sem(SEM1) -> E_CTX				... (E-2)
+ *		unl_cpu()
+ *		dis_dsp()
+ *		wai_sem(SEM1) -> E_CTX				... (E-3)
+ *		ena_dsp()
+ *		chg_ipm(TMAX_INTPRI)
+ *		wai_sem(SEM1) -> E_CTX				... (E-4)
+ *		chg_ipm(TIPM_ENAALL)
+ *		sig_sem(0) -> E_ID					... (A-3)
+ *		wai_sem(0) -> E_ID					... (E-5)
+ *		sig_sem(TNUM_SEMID+1) -> E_ID		... (A-4)
+ *		wai_sem(TNUM_SEMID+1) -> E_ID		... (E-6)
+ *	3:	act_tsk(TASK3)
+ *	4:	slp_tsk()
+ *	== TASK3（優先度：低）==
+ *	5:	wai_sem(SEM1)						... (F-1)
+ *  6:	ref_sem(SEM1, &rsem)
+ *		assert(rsem.wtskid == TSK_NONE)
+ *		assert(rsem.semcnt == 0)
+ *	7:	sta_alm(ALM1, 10)
+ *	8:	wai_sem(SEM1)						... (G-1)
+ *	== ALM1 ==
+ *	9:	sig_sem(SEM1) -> E_CTX				... (A-1)
+ *		wai_sem(SEM1) -> E_CTX				... (E-1)
+ *	10:	iwup_tsk(TASK1)
+ *	11:	RETURN
+ *	== TASK1（続き）==
+ *	12:	act_tsk(TASK2)
+ *	== TASK2（優先度：高）==
+ *	13:	wai_sem(SEM1)						... (G-2)
+ *	== TASK1（続き）==
+ *  14:	ref_sem(SEM1, &rsem)
+ *		assert(rsem.wtskid == TASK3)
+ *		assert(rsem.semcnt == 0)
+ *	15:	sig_sem(SEM1)						... (B-4)
+ *	16:	sig_sem(SEM1)						... (B-1)
+ *	== TASK2（続き）==
+ *	17:	wai_sem(SEM1)						... (G-1)
+ *	== TASK1（続き）==
+ *	18: dis_dsp()
+ *	19:	sig_sem(SEM1)						... (B-2)
+ *	20:	ena_dsp()
+ *	== TASK2（続き）==
+ *	21:	wai_sem(SEM1)						... (G-1)
+ *	== TASK1（続き）==
+ *	22: sus_tsk(TASK2)
+ *	23:	sig_sem(SEM1)						... (B-3)
+ *	24: sig_sem(SEM1)						... (C-1)
+ *	25: sig_sem(SEM1) -> E_QOVR				... (D-1)
+ *  26:	ref_sem(SEM1, &rsem)
+ *		assert(rsem.wtskid == TSK_NONE)
+ *		assert(rsem.semcnt == 1)
+ *	27:	rsm_tsk(TASK2)
+ *	== TASK2（続き）==
+ *	28:	wai_sem(SEM2)						... (F-2)
+ *  29:	ref_sem(SEM2, &rsem)
+ *		assert(rsem.wtskid == TSK_NONE)
+ *		assert(rsem.semcnt == 1)
+ *	30:	wai_sem(SEM2)						... (F-1)
+ *	31: wai_sem(SEM2)						... (G-1)
+ *	== TASK1（続き）==
+ *	32:	sig_sem(SEM2)						... (B-1)
+ *	== TASK2（続き）==
+ *	33:	wai_sem(SEM3)						... (G-3)
+ *	== TASK1（続き）==
+ *	34:	sig_sem(SEM2)						... (C-1)
+ *	35:	sig_sem(SEM2)						... (C-2)
+ *  36:	ref_sem(SEM2, &rsem)
+ *		assert(rsem.wtskid == TSK_NONE)
+ *		assert(rsem.semcnt == 2)
+ *	37:	sig_sem(SEM2) -> E_QOVR				... (D-2)
+ *  38:	ref_sem(SEM2, &rsem)
+ *		assert(rsem.wtskid == TSK_NONE)
+ *		assert(rsem.semcnt == 2)
+ *	39:	tslp_tsk(10) -> E_TMOUT
+ *	== TASK3（続き）==
+ *	40:	wai_sem(SEM3)						... (G-4)
+ *	== TASK1（続き）==
+ *	41:	act_tsk(TASK4)
+ *	42:	act_tsk(TASK5)
+ *	43:	rot_rdq(TPRI_SELF)
+ *	== TASK4（優先度：中）==
+ *	44:	wai_sem(SEM3)						... (G-6)
+ *	== TASK5（優先度：中）==
+ *	45:	wai_sem(SEM3)						... (G-5)
+ *	== TASK1（続き）==
+ *	46:	sig_sem(SEM3)						... (B-1)
+ *	== TASK2（続き）==
+ *	47:	wai_sem(SEM1)
+ *		wai_sem(SEM1) -> E_RLWAI
+ *	== TASK1（続き）==
+ *	48:	sig_sem(SEM3)						... (B-4)
+ *	49:	tslp_tsk(10) -> E_TMOUT
+ *	== TASK4（続き）==
+ *	50:	ext_tsk() -> noreturn
+ *	== TASK1（続き）==
+ *	51:	sig_sem(SEM3)						... (B-4)
+ *	52:	tslp_tsk(10) -> E_TMOUT
+ *	== TASK5（続き）==
+ *	53:	ext_tsk() -> noreturn
+ *	== TASK1（続き）==
+ *	54:	sig_sem(SEM3)						... (B-4)
+ *	55:	tslp_tsk(10) -> E_TMOUT
+ *	== TASK3（続き）==
+ *	56:	ext_tsk() -> noreturn
+ *	== TASK1（続き）==
+ *	57: rel_wai(TASK2)						... (H)
+ *	== TASK2（続き）==
+ *	58:	wai_sem(SEM1) -> E_DLT
+ *	== TASK1（続き）==
+ *	59: ini_sem(SEM1)						... (I)
+ *	== TASK2（続き）==
+ *	60: ext_tsk() -> noreturn
+ *	== TASK1（続き）==
+ *	61: END
+ */
+
+#include <kernel.h>
+#include <test_lib.h>
+#include <t_syslog.h>
+#include "kernel_cfg.h"
+#include "test_sem1.h"
+
+/* DO NOT DELETE THIS LINE -- gentest depends on it. */
+
+void
+alarm1_handler(intptr_t exinf)
+{
+	ER_UINT	ercd;
+
+	check_point(9);
+	ercd = sig_sem(SEM1);
+	check_ercd(ercd, E_CTX);
+
+	ercd = wai_sem(SEM1);
+	check_ercd(ercd, E_CTX);
+
+	check_point(10);
+	ercd = iwup_tsk(TASK1);
+	check_ercd(ercd, E_OK);
+
+	check_point(11);
+	return;
+
+	check_point(0);
+}
+
+void
+task1(intptr_t exinf)
+{
+	ER_UINT	ercd;
+	T_RSEM	rsem;
+
+	test_start(__FILE__);
+
+	check_point(1);
+	ercd = ref_sem(SEM1, &rsem);
+	check_ercd(ercd, E_OK);
+
+	check_assert(rsem.wtskid == TSK_NONE);
+
+	check_assert(rsem.semcnt == 1);
+
+	ercd = ref_sem(SEM2, &rsem);
+	check_ercd(ercd, E_OK);
+
+	check_assert(rsem.wtskid == TSK_NONE);
+
+	check_assert(rsem.semcnt == 2);
+
+	ercd = ref_sem(SEM3, &rsem);
+	check_ercd(ercd, E_OK);
+
+	check_assert(rsem.wtskid == TSK_NONE);
+
+	check_assert(rsem.semcnt == 0);
+
+	check_point(2);
+	ercd = loc_cpu();
+	check_ercd(ercd, E_OK);
+
+	ercd = sig_sem(SEM1);
+	check_ercd(ercd, E_CTX);
+
+	ercd = wai_sem(SEM1);
+	check_ercd(ercd, E_CTX);
+
+	ercd = unl_cpu();
+	check_ercd(ercd, E_OK);
+
+	ercd = dis_dsp();
+	check_ercd(ercd, E_OK);
+
+	ercd = wai_sem(SEM1);
+	check_ercd(ercd, E_CTX);
+
+	ercd = ena_dsp();
+	check_ercd(ercd, E_OK);
+
+	ercd = chg_ipm(TMAX_INTPRI);
+	check_ercd(ercd, E_OK);
+
+	ercd = wai_sem(SEM1);
+	check_ercd(ercd, E_CTX);
+
+	ercd = chg_ipm(TIPM_ENAALL);
+	check_ercd(ercd, E_OK);
+
+	ercd = sig_sem(0);
+	check_ercd(ercd, E_ID);
+
+	ercd = wai_sem(0);
+	check_ercd(ercd, E_ID);
+
+	ercd = sig_sem(TNUM_SEMID+1);
+	check_ercd(ercd, E_ID);
+
+	ercd = wai_sem(TNUM_SEMID+1);
+	check_ercd(ercd, E_ID);
+
+	check_point(3);
+	ercd = act_tsk(TASK3);
+	check_ercd(ercd, E_OK);
+
+	check_point(4);
+	ercd = slp_tsk();
+	check_ercd(ercd, E_OK);
+
+	check_point(12);
+	ercd = act_tsk(TASK2);
+	check_ercd(ercd, E_OK);
+
+	check_point(14);
+	ercd = ref_sem(SEM1, &rsem);
+	check_ercd(ercd, E_OK);
+
+	check_assert(rsem.wtskid == TASK3);
+
+	check_assert(rsem.semcnt == 0);
+
+	check_point(15);
+	ercd = sig_sem(SEM1);
+	check_ercd(ercd, E_OK);
+
+	check_point(16);
+	ercd = sig_sem(SEM1);
+	check_ercd(ercd, E_OK);
+
+	check_point(18);
+	ercd = dis_dsp();
+	check_ercd(ercd, E_OK);
+
+	check_point(19);
+	ercd = sig_sem(SEM1);
+	check_ercd(ercd, E_OK);
+
+	check_point(20);
+	ercd = ena_dsp();
+	check_ercd(ercd, E_OK);
+
+	check_point(22);
+	ercd = sus_tsk(TASK2);
+	check_ercd(ercd, E_OK);
+
+	check_point(23);
+	ercd = sig_sem(SEM1);
+	check_ercd(ercd, E_OK);
+
+	check_point(24);
+	ercd = sig_sem(SEM1);
+	check_ercd(ercd, E_OK);
+
+	check_point(25);
+	ercd = sig_sem(SEM1);
+	check_ercd(ercd, E_QOVR);
+
+	check_point(26);
+	ercd = ref_sem(SEM1, &rsem);
+	check_ercd(ercd, E_OK);
+
+	check_assert(rsem.wtskid == TSK_NONE);
+
+	check_assert(rsem.semcnt == 1);
+
+	check_point(27);
+	ercd = rsm_tsk(TASK2);
+	check_ercd(ercd, E_OK);
+
+	check_point(32);
+	ercd = sig_sem(SEM2);
+	check_ercd(ercd, E_OK);
+
+	check_point(34);
+	ercd = sig_sem(SEM2);
+	check_ercd(ercd, E_OK);
+
+	check_point(35);
+	ercd = sig_sem(SEM2);
+	check_ercd(ercd, E_OK);
+
+	check_point(36);
+	ercd = ref_sem(SEM2, &rsem);
+	check_ercd(ercd, E_OK);
+
+	check_assert(rsem.wtskid == TSK_NONE);
+
+	check_assert(rsem.semcnt == 2);
+
+	check_point(37);
+	ercd = sig_sem(SEM2);
+	check_ercd(ercd, E_QOVR);
+
+	check_point(38);
+	ercd = ref_sem(SEM2, &rsem);
+	check_ercd(ercd, E_OK);
+
+	check_assert(rsem.wtskid == TSK_NONE);
+
+	check_assert(rsem.semcnt == 2);
+
+	check_point(39);
+	ercd = tslp_tsk(10);
+	check_ercd(ercd, E_TMOUT);
+
+	check_point(41);
+	ercd = act_tsk(TASK4);
+	check_ercd(ercd, E_OK);
+
+	check_point(42);
+	ercd = act_tsk(TASK5);
+	check_ercd(ercd, E_OK);
+
+	check_point(43);
+	ercd = rot_rdq(TPRI_SELF);
+	check_ercd(ercd, E_OK);
+
+	check_point(46);
+	ercd = sig_sem(SEM3);
+	check_ercd(ercd, E_OK);
+
+	check_point(48);
+	ercd = sig_sem(SEM3);
+	check_ercd(ercd, E_OK);
+
+	check_point(49);
+	ercd = tslp_tsk(10);
+	check_ercd(ercd, E_TMOUT);
+
+	check_point(51);
+	ercd = sig_sem(SEM3);
+	check_ercd(ercd, E_OK);
+
+	check_point(52);
+	ercd = tslp_tsk(10);
+	check_ercd(ercd, E_TMOUT);
+
+	check_point(54);
+	ercd = sig_sem(SEM3);
+	check_ercd(ercd, E_OK);
+
+	check_point(55);
+	ercd = tslp_tsk(10);
+	check_ercd(ercd, E_TMOUT);
+
+	check_point(57);
+	ercd = rel_wai(TASK2);
+	check_ercd(ercd, E_OK);
+
+	check_point(59);
+	ercd = ini_sem(SEM1);
+	check_ercd(ercd, E_OK);
+
+	check_finish(61);
+	check_point(0);
+}
+
+void
+task2(intptr_t exinf)
+{
+	ER_UINT	ercd;
+	T_RSEM	rsem;
+
+	check_point(13);
+	ercd = wai_sem(SEM1);
+	check_ercd(ercd, E_OK);
+
+	check_point(17);
+	ercd = wai_sem(SEM1);
+	check_ercd(ercd, E_OK);
+
+	check_point(21);
+	ercd = wai_sem(SEM1);
+	check_ercd(ercd, E_OK);
+
+	check_point(28);
+	ercd = wai_sem(SEM2);
+	check_ercd(ercd, E_OK);
+
+	check_point(29);
+	ercd = ref_sem(SEM2, &rsem);
+	check_ercd(ercd, E_OK);
+
+	check_assert(rsem.wtskid == TSK_NONE);
+
+	check_assert(rsem.semcnt == 1);
+
+	check_point(30);
+	ercd = wai_sem(SEM2);
+	check_ercd(ercd, E_OK);
+
+	check_point(31);
+	ercd = wai_sem(SEM2);
+	check_ercd(ercd, E_OK);
+
+	check_point(33);
+	ercd = wai_sem(SEM3);
+	check_ercd(ercd, E_OK);
+
+	check_point(47);
+	ercd = wai_sem(SEM1);
+	check_ercd(ercd, E_OK);
+
+	ercd = wai_sem(SEM1);
+	check_ercd(ercd, E_RLWAI);
+
+	check_point(58);
+	ercd = wai_sem(SEM1);
+	check_ercd(ercd, E_DLT);
+
+	check_point(60);
+	ercd = ext_tsk();
+
+	check_point(0);
+}
+
+void
+task3(intptr_t exinf)
+{
+	ER_UINT	ercd;
+	T_RSEM	rsem;
+
+	check_point(5);
+	ercd = wai_sem(SEM1);
+	check_ercd(ercd, E_OK);
+
+	check_point(6);
+	ercd = ref_sem(SEM1, &rsem);
+	check_ercd(ercd, E_OK);
+
+	check_assert(rsem.wtskid == TSK_NONE);
+
+	check_assert(rsem.semcnt == 0);
+
+	check_point(7);
+	ercd = sta_alm(ALM1, 10);
+	check_ercd(ercd, E_OK);
+
+	check_point(8);
+	ercd = wai_sem(SEM1);
+	check_ercd(ercd, E_OK);
+
+	check_point(40);
+	ercd = wai_sem(SEM3);
+	check_ercd(ercd, E_OK);
+
+	check_point(56);
+	ercd = ext_tsk();
+
+	check_point(0);
+}
+
+void
+task4(intptr_t exinf)
+{
+	ER_UINT	ercd;
+
+	check_point(44);
+	ercd = wai_sem(SEM3);
+	check_ercd(ercd, E_OK);
+
+	check_point(50);
+	ercd = ext_tsk();
+
+	check_point(0);
+}
+
+void
+task5(intptr_t exinf)
+{
+	ER_UINT	ercd;
+
+	check_point(45);
+	ercd = wai_sem(SEM3);
+	check_ercd(ercd, E_OK);
+
+	check_point(53);
+	ercd = ext_tsk();
+
+	check_point(0);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sem1.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sem1.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sem1.cfg	(revision 453)
@@ -0,0 +1,23 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *  セマフォ機能のテスト(1)のシステムコンフィギュレーションファイル
+ */
+INCLUDE("target_timer.cfg");
+INCLUDE("syssvc/syslog.cfg");
+INCLUDE("syssvc/banner.cfg");
+INCLUDE("syssvc/serial.cfg");
+
+#include "test_sem1.h"
+
+CRE_TSK(TASK1, { TA_ACT, 1, task1, MID_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK2, { TA_NULL, 2, task2, HIGH_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK3, { TA_NULL, 3, task3, LOW_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK4, { TA_NULL, 4, task4, MID_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK5, { TA_NULL, 5, task5, MID_PRIORITY, STACK_SIZE, NULL });
+CRE_ALM(ALM1, { TA_NULL, 1, alarm1_handler });
+CRE_SEM(SEM1, { TA_NULL, 1, 1 });
+CRE_SEM(SEM2, { TA_NULL, 2, 2 });
+CRE_SEM(SEM3, { TA_TPRI, 0, 1 });
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sem1.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sem1.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sem1.h	(revision 453)
@@ -0,0 +1,75 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2008 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/* 
+ *		セマフォ機能のテスト(1)
+ */
+
+/*
+ *  ターゲット依存の定義
+ */
+#include "target_test.h"
+
+/*
+ *  優先度の定義
+ */
+#define HIGH_PRIORITY	9		/* 高優先度 */
+#define MID_PRIORITY	10		/* 中優先度 */
+#define LOW_PRIORITY	11		/* 低優先度 */
+
+/*
+ *  ターゲットに依存する可能性のある定数の定義
+ */
+#ifndef STACK_SIZE
+#define	STACK_SIZE		4096		/* タスクのスタックサイズ */
+#endif /* STACK_SIZE */
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+#ifndef TOPPERS_MACRO_ONLY
+
+extern void	task1(intptr_t exinf);
+extern void	task2(intptr_t exinf);
+extern void	task3(intptr_t exinf);
+extern void	task4(intptr_t exinf);
+extern void	task5(intptr_t exinf);
+extern void	alarm1_handler(intptr_t exinf);
+
+#endif /* TOPPERS_MACRO_ONLY */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sem2.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sem2.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sem2.c	(revision 453)
@@ -0,0 +1,470 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2008-2013 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *		セマフォ機能のテスト(2)
+ *
+ * 【テストの目的】
+ *
+ *  isig_semを，sig_semとの違いを中心にテストする．
+ *  pol_sem，twai_semを，wai_semとの違いを中心にテストする．
+ *
+ * 【テスト項目】
+ *
+ *	(A) isig_semの静的エラーのテスト
+ *		(A-1) タスクコンテキストからの呼出し
+ *		(A-2) CPUロック状態からの呼出し
+ *	(B) isig_semによりセマフォ待ち状態のタスクが待ち解除される
+ *		(B-1) アイドル状態から，待ち解除されたタスクに切り換わる
+ *		(B-2) 実行状態のタスクから，待ち解除されたタスクに切り換わる
+ *		(B-3) ディスパッチ保留状態で，切り換わらない
+ *		(B-4) 待ち解除されたタスクが強制待ち状態で，切り換わらない
+ *		(B-5) 待ち解除されたタスクが優先度が低く，切り換わらない
+ *	(C) pol_semの静的エラーのテスト
+ *		(C-1) 非タスクコンテキストからの呼出し
+ *		(C-2) CPUロック状態からの呼出し
+ *		(C-3) ディスパッチ禁止状態からの呼出し（E_CTXエラーにならない）
+ *		(C-4) 割込み優先度マスク全解除でない状態からの呼出し（E_CTXエラー
+ *		      にならない）
+ *	(D) pol_semでポーリング失敗する
+ *	(E) twai_semの静的エラーのテスト
+ *		(E-1) 非タスクコンテキストからの呼出し
+ *		(E-2) CPUロック状態からの呼出し
+ *		(E-3) ディスパッチ禁止状態からの呼出し
+ *		(E-4) 割込み優先度マスク全解除でない状態からの呼出し
+ *		(E-5) tmoutが不正
+ *	(F) twai_semでtmout=TMO_POLの時にポーリング失敗する
+ *	(G) twai_semでtmout=TMO_FEVRの時にセマフォ待ち状態になる
+ *	(H) twai_semでtmoutにタイムアウトを設定した時に，タイムアウト付きの
+ *		セマフォ待ち状態になる
+ *
+ * 【使用リソース】
+ *
+ *	TASK1: 中優先度タスク，TA_ACT属性
+ *	TASK2: 高優先度タスク
+ *	TASK3: 低優先度タスク
+ *	TASK4: 中優先度タスク
+ *	TASK5: 中優先度タスク
+ *	ALM1:  アラームハンドラ
+ *  SEM1:  TA_NULL属性，初期資源数1，最大資源数1
+ *
+ * 【テストシーケンス】
+ *
+ *	== TASK1（優先度：中）==
+ *  1:	isig_sem(SEM1) -> E_CTX				... (A-1)
+ *	2:	loc_cpu()
+ *		pol_sem(SEM1) -> E_CTX				... (C-2)
+ *		twai_sem(SEM1, TMO_POL) -> E_CTX	... (E-2)
+ *		unl_cpu()
+ *	3:	dis_dsp()
+ *		pol_sem(SEM1)						... (C-3)
+ *		twai_sem(SEM1, TMO_POL) -> E_CTX	... (E-3)
+ *		ena_dsp()
+ *	4:	chg_ipm(TMAX_INTPRI)
+ *		pol_sem(SEM1) -> E_TMOUT			... (C-4)(D)
+ *		twai_sem(SEM1, TMO_POL) -> E_CTX	... (E-4)
+ *		chg_ipm(TIPM_ENAALL)
+ *	5:	twai_sem(SEM1, -2) -> E_PAR			... (E-5)
+ *		twai_sem(SEM1, TMO_POL) -> E_TMOUT	... (F)
+ *	6:	sta_alm(ALM1, 10)
+ *	7:	twai_sem(SEM1, TMO_FEVR)			... (G)
+ *	== ALM1-1 ==
+ *	8:	pol_sem(SEM1) -> E_CTX				... (C-1)
+ *		twai_sem(SEM1, TMO_POL) -> E_CTX	... (E-1)
+ *	9:	iloc_cpu()
+ *		isig_sem(SEM1) -> E_CTX				... (A-2)
+ *		iunl_cpu()
+ *	10:	isig_sem(SEM1)						... (B-1)
+ *		RETURN
+ *	== TASK1（続き）==
+ *	11:	act_tsk(TASK3)
+ *	12:	wai_sem(SEM1)
+ *	== TASK3（優先度：低）==
+ *	13:	sta_alm(ALM1, 10)
+ *		call(wait_var())
+ *	== ALM1-2 ==
+ *	14:	isig_sem(SEM1)						... (B-2)
+ *		call(signal_var())
+ *		RETURN
+ *	== TASK1（続き）==
+ *	15:	wai_sem(SEM1)
+ *	== TASK3（続き）==
+ *	16:	sta_alm(ALM1, 10)
+ *		dis_dsp()
+ *		call(wait_var())
+ *	== ALM1-3 ==
+ *	17:	isig_sem(SEM1)						... (B-3)
+ *		call(signal_var())
+ *		RETURN
+ *	== TASK3（続き）==
+ *	18:	ena_dsp()
+ *	== TASK1（続き）==
+ *	19:	wai_sem(SEM1)
+ *	== TASK3（続き）==
+ *	20:	sta_alm(ALM1, 10)
+ *		sus_tsk(TASK1)
+ *		call(wait_var())
+ *	== ALM1-4 ==
+ *	21:	isig_sem(SEM1)						... (B-4)
+ *		call(signal_var())
+ *		RETURN
+ *	== TASK3（続き）==
+ *	22:	rsm_tsk(TASK1)
+ *	== TASK1（続き）==
+ *	23:	act_tsk(TASK2)
+ *	== TASK2（優先度：高）==
+ *	24:	tslp_tsk(10) -> E_TMOUT
+ *	== TASK1（続き）==
+ *	25:	wai_sem(SEM1)
+ *	== TASK3（続き）==
+ *	26:	ext_tsk() -> noreturn
+ *	== TASK2（続き）==
+ *	27:	sta_alm(ALM1, 10)
+ *		call(wait_var())
+ *	== ALM1-5 ==
+ *	28:	isig_sem(SEM1)						... (B-5)
+ *		call(signal_var())
+ *		RETURN
+ *	== TASK2（続き）==
+ *	29:	ext_tsk() -> noreturn
+ *	== TASK1（続き）==
+ *	30:	sta_alm(ALM1, 10)
+ *	31:	twai_sem(SEM1, 100) -> E_RLWAI
+ *	== ALM1-6 ==
+ *	32:	irel_wai(TASK1)
+ *		RETURN
+ *	== TASK1（続き）==
+ *	33:	sta_alm(ALM1, 100)
+ *	34:	twai_sem(SEM1, 10) -> E_TMOUT		... (H)
+ *	35:	stp_alm(ALM1)
+ *	36:	END
+ */
+
+#include <kernel.h>
+#include <test_lib.h>
+#include <t_syslog.h>
+#include "kernel_cfg.h"
+#include "test_sem2.h"
+
+static volatile bool_t	flagvar;
+
+static void
+wait_var(void)
+{
+	flagvar = false;
+	while (!flagvar);
+}
+
+static void
+signal_var(void)
+{
+	flagvar = true;
+}
+
+/* DO NOT DELETE THIS LINE -- gentest depends on it. */
+
+static uint_t	alarm1_count = 0;
+
+void
+alarm1_handler(intptr_t exinf)
+{
+	ER_UINT	ercd;
+
+	switch (++alarm1_count) {
+	case 1:
+		check_point(8);
+		ercd = pol_sem(SEM1);
+		check_ercd(ercd, E_CTX);
+
+		ercd = twai_sem(SEM1, TMO_POL);
+		check_ercd(ercd, E_CTX);
+
+		check_point(9);
+		ercd = iloc_cpu();
+		check_ercd(ercd, E_OK);
+
+		ercd = isig_sem(SEM1);
+		check_ercd(ercd, E_CTX);
+
+		ercd = iunl_cpu();
+		check_ercd(ercd, E_OK);
+
+		check_point(10);
+		ercd = isig_sem(SEM1);
+		check_ercd(ercd, E_OK);
+
+		return;
+
+		check_point(0);
+
+	case 2:
+		check_point(14);
+		ercd = isig_sem(SEM1);
+		check_ercd(ercd, E_OK);
+
+		signal_var();
+
+		return;
+
+		check_point(0);
+
+	case 3:
+		check_point(17);
+		ercd = isig_sem(SEM1);
+		check_ercd(ercd, E_OK);
+
+		signal_var();
+
+		return;
+
+		check_point(0);
+
+	case 4:
+		check_point(21);
+		ercd = isig_sem(SEM1);
+		check_ercd(ercd, E_OK);
+
+		signal_var();
+
+		return;
+
+		check_point(0);
+
+	case 5:
+		check_point(28);
+		ercd = isig_sem(SEM1);
+		check_ercd(ercd, E_OK);
+
+		signal_var();
+
+		return;
+
+		check_point(0);
+
+	case 6:
+		check_point(32);
+		ercd = irel_wai(TASK1);
+		check_ercd(ercd, E_OK);
+
+		return;
+
+		check_point(0);
+
+	default:
+		check_point(0);
+	}
+	check_point(0);
+}
+
+void
+task1(intptr_t exinf)
+{
+	ER_UINT	ercd;
+
+	test_start(__FILE__);
+
+	check_point(1);
+	ercd = isig_sem(SEM1);
+	check_ercd(ercd, E_CTX);
+
+	check_point(2);
+	ercd = loc_cpu();
+	check_ercd(ercd, E_OK);
+
+	ercd = pol_sem(SEM1);
+	check_ercd(ercd, E_CTX);
+
+	ercd = twai_sem(SEM1, TMO_POL);
+	check_ercd(ercd, E_CTX);
+
+	ercd = unl_cpu();
+	check_ercd(ercd, E_OK);
+
+	check_point(3);
+	ercd = dis_dsp();
+	check_ercd(ercd, E_OK);
+
+	ercd = pol_sem(SEM1);
+	check_ercd(ercd, E_OK);
+
+	ercd = twai_sem(SEM1, TMO_POL);
+	check_ercd(ercd, E_CTX);
+
+	ercd = ena_dsp();
+	check_ercd(ercd, E_OK);
+
+	check_point(4);
+	ercd = chg_ipm(TMAX_INTPRI);
+	check_ercd(ercd, E_OK);
+
+	ercd = pol_sem(SEM1);
+	check_ercd(ercd, E_TMOUT);
+
+	ercd = twai_sem(SEM1, TMO_POL);
+	check_ercd(ercd, E_CTX);
+
+	ercd = chg_ipm(TIPM_ENAALL);
+	check_ercd(ercd, E_OK);
+
+	check_point(5);
+	ercd = twai_sem(SEM1, -2);
+	check_ercd(ercd, E_PAR);
+
+	ercd = twai_sem(SEM1, TMO_POL);
+	check_ercd(ercd, E_TMOUT);
+
+	check_point(6);
+	ercd = sta_alm(ALM1, 10);
+	check_ercd(ercd, E_OK);
+
+	check_point(7);
+	ercd = twai_sem(SEM1, TMO_FEVR);
+	check_ercd(ercd, E_OK);
+
+	check_point(11);
+	ercd = act_tsk(TASK3);
+	check_ercd(ercd, E_OK);
+
+	check_point(12);
+	ercd = wai_sem(SEM1);
+	check_ercd(ercd, E_OK);
+
+	check_point(15);
+	ercd = wai_sem(SEM1);
+	check_ercd(ercd, E_OK);
+
+	check_point(19);
+	ercd = wai_sem(SEM1);
+	check_ercd(ercd, E_OK);
+
+	check_point(23);
+	ercd = act_tsk(TASK2);
+	check_ercd(ercd, E_OK);
+
+	check_point(25);
+	ercd = wai_sem(SEM1);
+	check_ercd(ercd, E_OK);
+
+	check_point(30);
+	ercd = sta_alm(ALM1, 10);
+	check_ercd(ercd, E_OK);
+
+	check_point(31);
+	ercd = twai_sem(SEM1, 100);
+	check_ercd(ercd, E_RLWAI);
+
+	check_point(33);
+	ercd = sta_alm(ALM1, 100);
+	check_ercd(ercd, E_OK);
+
+	check_point(34);
+	ercd = twai_sem(SEM1, 10);
+	check_ercd(ercd, E_TMOUT);
+
+	check_point(35);
+	ercd = stp_alm(ALM1);
+	check_ercd(ercd, E_OK);
+
+	check_finish(36);
+	check_point(0);
+}
+
+void
+task2(intptr_t exinf)
+{
+	ER_UINT	ercd;
+
+	check_point(24);
+	ercd = tslp_tsk(10);
+	check_ercd(ercd, E_TMOUT);
+
+	check_point(27);
+	ercd = sta_alm(ALM1, 10);
+	check_ercd(ercd, E_OK);
+
+	wait_var();
+
+	check_point(29);
+	ercd = ext_tsk();
+
+	check_point(0);
+}
+
+void
+task3(intptr_t exinf)
+{
+	ER_UINT	ercd;
+
+	check_point(13);
+	ercd = sta_alm(ALM1, 10);
+	check_ercd(ercd, E_OK);
+
+	wait_var();
+
+	check_point(16);
+	ercd = sta_alm(ALM1, 10);
+	check_ercd(ercd, E_OK);
+
+	ercd = dis_dsp();
+	check_ercd(ercd, E_OK);
+
+	wait_var();
+
+	check_point(18);
+	ercd = ena_dsp();
+	check_ercd(ercd, E_OK);
+
+	check_point(20);
+	ercd = sta_alm(ALM1, 10);
+	check_ercd(ercd, E_OK);
+
+	ercd = sus_tsk(TASK1);
+	check_ercd(ercd, E_OK);
+
+	wait_var();
+
+	check_point(22);
+	ercd = rsm_tsk(TASK1);
+	check_ercd(ercd, E_OK);
+
+	check_point(26);
+	ercd = ext_tsk();
+
+	check_point(0);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sem2.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sem2.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sem2.cfg	(revision 453)
@@ -0,0 +1,20 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *  セマフォ機能のテスト(2)のシステムコンフィギュレーションファイル
+ */
+INCLUDE("target_timer.cfg");
+INCLUDE("syssvc/syslog.cfg");
+INCLUDE("syssvc/banner.cfg");
+INCLUDE("syssvc/serial.cfg");
+
+#include "test_sem2.h"
+
+CRE_TSK(TASK1, { TA_ACT, 1, task1, MID_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK2, { TA_NULL, 2, task2, HIGH_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK3, { TA_NULL, 3, task3, LOW_PRIORITY, STACK_SIZE, NULL });
+CRE_ALM(ALM1, { TA_NULL, 1, alarm1_handler });
+CRE_SEM(SEM1, { TA_NULL, 1, 1 });
+CRE_SEM(SEM2, { TA_TPRI, 0, 1 });
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sem2.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sem2.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sem2.h	(revision 453)
@@ -0,0 +1,73 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2008 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/* 
+ *		セマフォ機能のテスト(2)
+ */
+
+/*
+ *  ターゲット依存の定義
+ */
+#include "target_test.h"
+
+/*
+ *  優先度の定義
+ */
+#define HIGH_PRIORITY	9		/* 高優先度 */
+#define MID_PRIORITY	10		/* 中優先度 */
+#define LOW_PRIORITY	11		/* 低優先度 */
+
+/*
+ *  ターゲットに依存する可能性のある定数の定義
+ */
+#ifndef STACK_SIZE
+#define	STACK_SIZE		4096		/* タスクのスタックサイズ */
+#endif /* STACK_SIZE */
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+#ifndef TOPPERS_MACRO_ONLY
+
+extern void	task1(intptr_t exinf);
+extern void	task2(intptr_t exinf);
+extern void	task3(intptr_t exinf);
+extern void	alarm1_handler(intptr_t exinf);
+
+#endif /* TOPPERS_MACRO_ONLY */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sysstat1.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sysstat1.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sysstat1.c	(revision 453)
@@ -0,0 +1,241 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2006-2013 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *		システム状態に関するテスト(1)
+ *
+ *  テストシーケンス：
+ *
+ *	== TASK1（優先度：10）==
+ *	1:	初期状態のチェック
+ *	2:	loc_cpu() ... システム状態をランダムに変化させる
+ *		chg_ipm(TMAX_INTPRI) -> E_CTX
+ *	3:	unl_cpu()
+ *	4:	chg_ipm(TMAX_INTPRI)
+ *	5:	dis_dsp()
+ *	6:	ena_tex()
+ *	7:	chg_ipm(TIPM_ENAALL)
+ *	8:	ena_dsp()
+ *	9:	dis_tex()
+ *	10:	dis_dsp() ... タスク例外処理ルーチンを呼び出す準備
+ *		ena_tex()
+ *	11:	ras_tex(TSK_SELF, 0x0001)
+ *	== TASK1タスク例外処理ルーチン（1回目）==
+ *	12:	初期状態のチェック
+ *	13:	ena_dsp() ... 3つの状態を変化させ，リターンで元にもどるか調べる
+ *		chg_ipm(TMIN_INTPRI)
+ *		ena_tex()
+ *		リターン
+ *	== TASK1（続き）==
+ *	14:	戻ってきた状態のチェック
+ *	15:	loc_cpu() ... CPUロック状態のままタスクを終了させる
+ *	16:	リターン（＝タスク終了）
+ *	== TASK2（優先度：10）	==
+ *	17:	初期状態のチェック
+ *	18:	終了
+ */
+
+#include <kernel.h>
+#include <test_lib.h>
+#include <t_syslog.h>
+#include "kernel_cfg.h"
+#include "test_sysstat1.h"
+
+void
+tex_task1(TEXPTN texptn, intptr_t exinf)
+{
+	ER		ercd;
+
+	switch (texptn) {
+	case 0x0001:
+		check_point(12);
+		check_state(false, false, TIPM_ENAALL, true, true, true);
+
+		/*
+		 *  ディスパッチ許可，割込み優先度マスク変更，タスク例外処理許可
+		 */
+		check_point(13);
+		ercd = ena_dsp();
+		check_ercd(ercd, E_OK);
+		ercd = chg_ipm(TMIN_INTPRI);
+		check_ercd(ercd, E_OK);
+		ercd = ena_tex();
+		check_ercd(ercd, E_OK);
+		check_state(false, false, TMIN_INTPRI, false, true, false);
+		break;
+
+	default:
+		check_point(0);
+		break;
+	}
+}
+
+void
+task1(intptr_t exinf)
+{
+	ER		ercd;
+
+	test_start(__FILE__);
+
+	/*
+	 *  初期状態のチェック
+	 */
+	check_point(1);
+	check_state(false, false, TIPM_ENAALL, false, false, true);
+
+	/*
+	 *  CPUロック状態のチェック
+	 */
+	check_point(2);
+	ercd = loc_cpu();
+	check_ercd(ercd, E_OK);
+	check_state(false, true, TIPM_ENAALL, false, true, true);
+
+	/*
+	 *  割込み優先度マスク変更のチェック
+	 */
+	ercd = chg_ipm(TMAX_INTPRI);
+	check_ercd(ercd, E_CTX);
+	check_state(false, true, TIPM_ENAALL, false, true, true);
+
+	/*
+	 *  CPUロック解除のチェック
+	 */
+	check_point(3);
+	ercd = unl_cpu();
+	check_ercd(ercd, E_OK);
+	check_state(false, false, TIPM_ENAALL, false, false, true);
+
+	/*
+	 *  割込み優先度マスク変更のチェック
+	 */
+	check_point(4);
+	ercd = chg_ipm(TMAX_INTPRI);
+	check_ercd(ercd, E_OK);
+	check_state(false, false, TMAX_INTPRI, false, true, true);
+
+	/*
+	 *  ディスパッチ禁止のチェック
+	 */
+	check_point(5);
+	ercd = dis_dsp();
+	check_ercd(ercd, E_OK);
+	check_state(false, false, TMAX_INTPRI, true, true, true);
+
+	/*
+	 *  タスク例外処理許可のチェック
+	 */
+	check_point(6);
+	ercd = ena_tex();
+	check_ercd(ercd, E_OK);
+	check_state(false, false, TMAX_INTPRI, true, true, false);
+
+	/*
+	 *  割込み優先度マスク全解除のチェック
+	 */
+	check_point(7);
+	ercd = chg_ipm(TIPM_ENAALL);
+	check_ercd(ercd, E_OK);
+	check_state(false, false, TIPM_ENAALL, true, true, false);
+
+	/*
+	 *  ディスパッチ許可のチェック
+	 */
+	check_point(8);
+	ercd = ena_dsp();
+	check_ercd(ercd, E_OK);
+	check_state(false, false, TIPM_ENAALL, false, false, false);
+
+	/*
+	 *  タスク例外処理禁止のチェック
+	 */
+	check_point(9);
+	ercd = dis_tex();
+	check_ercd(ercd, E_OK);
+	check_state(false, false, TIPM_ENAALL, false, false, true);
+
+	/*
+	 *  ディスパッチ禁止，タスク例外処理許可
+	 */
+	check_point(10);
+	ercd = dis_dsp();
+	check_ercd(ercd, E_OK);
+	ercd = ena_tex();
+	check_ercd(ercd, E_OK);
+	check_state(false, false, TIPM_ENAALL, true, true, false);
+
+	/*
+	 *  タスク例外処理を要求
+	 */
+	check_point(11);
+	ercd = ras_tex(TSK_SELF, 0x0001);
+	/* ここでタスク例外処理ルーチンが動作する */
+	check_ercd(ercd, E_OK);
+
+	/*
+	 *  タスク例外処理からのリターンにより元の状態に戻っていることを
+	 *  チェック
+	 */
+	check_point(14);
+	check_state(false, false, TIPM_ENAALL, true, true, false);
+
+	/*
+	 *  CPUロック状態に
+	 */
+	check_point(15);
+	ercd = loc_cpu();
+	check_ercd(ercd, E_OK);
+
+	/*
+	 *  そのままタスク終了
+	 */
+	check_point(16);
+}
+
+void
+task2(intptr_t exinf)
+{
+	/*
+	 *  初期状態のチェック
+	 */
+	check_point(17);
+	check_state(false, false, TIPM_ENAALL, false, false, true);
+
+	check_finish(18);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sysstat1.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sysstat1.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sysstat1.cfg	(revision 453)
@@ -0,0 +1,18 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *  システム状態に関するテスト(1)のシステムコンフィギュレーションファイル
+ */
+INCLUDE("target_timer.cfg");
+INCLUDE("syssvc/syslog.cfg");
+INCLUDE("syssvc/banner.cfg");
+INCLUDE("syssvc/serial.cfg");
+
+#include "test_sysstat1.h"
+
+CRE_TSK(TASK1, { TA_ACT, 1, task1, TASK1_PRIORITY, STACK_SIZE, NULL });
+DEF_TEX(TASK1, { TA_NULL, tex_task1 });
+
+CRE_TSK(TASK2, { TA_ACT, 2, task2, TASK2_PRIORITY, STACK_SIZE, NULL });
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sysstat1.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sysstat1.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_sysstat1.h	(revision 453)
@@ -0,0 +1,72 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2006,2007 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/* 
+ *		システム状態に関するテスト(1)
+ */
+
+/*
+ *  ターゲット依存の定義
+ */
+#include "target_test.h"
+
+/*
+ *  各タスクの優先度の定義
+ */
+#define TASK1_PRIORITY	10		/* タスク1の優先度 */
+#define TASK2_PRIORITY	10		/* タスク2の優先度 */
+
+/*
+ *  ターゲットに依存する可能性のある定数の定義
+ */
+#ifndef STACK_SIZE
+#define	STACK_SIZE		4096		/* タスクのスタックサイズ */
+#endif /* STACK_SIZE */
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+#ifndef TOPPERS_MACRO_ONLY
+
+extern void	tex_task1(TEXPTN texptn, intptr_t exinf);
+extern void	task1(intptr_t exinf);
+
+extern void	task2(intptr_t exinf);
+
+#endif /* TOPPERS_MACRO_ONLY */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_task1.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_task1.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_task1.c	(revision 453)
@@ -0,0 +1,364 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2007-2013 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *		タスク管理モジュールのテスト(1)
+ *
+ * 【テストの目的】
+ *
+ *  make_runnableとmake_non_runnableを網羅的にテストする．
+ *
+ * 【テスト項目】
+ *
+ *	(A) 実行状態のタスクよりも高い優先度のタスクを実行できる状態にする
+ *		(A-1) ディスパッチ保留状態ではない場合
+ *		(A-2) ディスパッチ保留状態の場合
+ *	(B) 実行状態のタスクと同じ優先度のタスクを実行できる状態にする
+ *		！同じ優先度のタスクの中の末尾に入ることを確認する
+ *	(C) 実行状態のタスクよりも低い優先度のタスクを実行できる状態にする
+ *		！同じ優先度のタスクの中の末尾に入ることを確認する
+ *	(D) 実行できる状態のタスクがない状態で，タスクを実行できる状態にする
+ *		！この場合は，ディスパッチ保留状態ではない
+ *	(E) ディスパッチ保留状態で，実行状態になるべきだが実行可能状態タス
+ *		クよりも高い優先度のタスクを，実行できる状態にする
+ *	(F) ディスパッチ保留状態で，実行状態になるべきだが実行可能状態タス
+ *		クと同じ優先度のタスクを，実行できる状態にする
+ *	(G) ディスパッチ保留状態で，実行状態になるべきだが実行可能状態タス
+ *		クよりも低い優先度のタスクを，実行できる状態にする
+ *	(H) 実行状態のタスクを，実行できる状態でなくす
+ *		(H-1) 実行できる状態のタスクがなくなる場合
+ *		(H-2) 同一優先度のタスクがなくなる場合
+ *		(H-3) 同一優先度のタスクがなくならない場合
+ *	(I) 実行可能状態のタスクを，実行できる状態でなくす
+ *		(I-1) 同一優先度のタスクがなくなる場合
+ *		(I-2) 同一優先度のタスクがなくならない場合
+ *	(J) ディスパッチ保留状態で，実行状態になるべきだが実行可能状態となっ
+ *		ているタスクを，実行できる状態でなくす
+ *		(J-1) 同一優先度のタスクがなくなる場合
+ *		(J-2) 同一優先度のタスクがなくならない場合
+ *	(K) ディスパッチ保留状態で，実行可能状態になるべきだが実行状態のタ
+ *		スクを，実行できる状態でなくす
+ *		！ディスパッチ保留では，実行状態のタスクが実行できる状態でなく
+ *		なるような遷移を起こすことができないため，この状況は起こらない．
+ *
+ * 【使用リソース】
+ *
+ *	TASK1: 中優先度タスク，メインタスク，最初から起動
+ *	TASK2: 高優先度タスク
+ *	TASK3: 中優先度タスク
+ *	TASK4: 中優先度タスク
+ *	TASK5: 低優先度タスク
+ *	TASK6: 低優先度タスク
+ *	ALM1:  アラームハンドラ
+ *
+ * 【テストシーケンス】
+ *
+ *	== TASK1（優先度：中）==
+ *	1:	act_tsk(TASK2)					... (A-1)
+ *	== TASK2（優先度：高）==
+ *	2:	slp_tsk()						... (H-2)
+ *	== TASK1（続き）==
+ *	3:	act_tsk(TASK3)					... (B)
+ *	4:	act_tsk(TASK4)					... (B)
+ *	5:	slp_tsk()						... (H-3)
+ *	== TASK3（優先度：中）==
+ *	6:	slp_tsk()						... (H-3)
+ *	== TASK4（優先度：中）==
+ *	7:	wup_tsk(TASK1)
+ *	8:	slp_tsk()						... (H-3)
+ *	== TASK1（続き）==
+ *	9:	act_tsk(TASK5)					... (C)
+ *	10:	act_tsk(TASK6)					... (C)
+ *	11:	sus_tsk(TASK6)					... (I-2)
+ *	12:	sus_tsk(TASK5)					... (I-1)
+ *	13:	rsm_tsk(TASK5)					... (C)
+ *	14:	rsm_tsk(TASK6)					... (C)
+ *	15:	slp_tsk()						... (H-2)
+ *	== TASK5（優先度：低）==
+ *	16:	slp_tsk()						... (H-3)
+ *	== TASK6（優先度：低）==
+ *	17:	dis_dsp()
+ *	18:	wup_tsk(TASK1)					... (A-2)
+ *	19:	wup_tsk(TASK2)					... (E)
+ *	20:	sus_tsk(TASK2)					... (J-1)
+ *	21:	wup_tsk(TASK3)					... (F)
+ *	22:	wup_tsk(TASK4)					... (F)
+ *	23:	sus_tsk(TASK1)					... (J-2)
+ *	24:	ena_dsp()
+ *	== TASK3（続き）==
+ *	25:	slp_tsk()						... (H-3)
+ *	== TASK4（続き）==
+ *	26:	slp_tsk()						... (H-2)
+ *	== TASK6（続き）==
+ *	27:	dis_dsp()
+ *	28:	rsm_tsk(TASK1)					... (A-2)
+ *	29:	wup_tsk(TASK5)					... (G)
+ *	30:	ena_dsp()
+ *	== TASK1（続き）==
+ *	31:	slp_tsk()						... (H-2)
+ *	== TASK6（続き）==
+ *	32:	slp_tsk()						... (H-3)
+ *	== TASK5（続き）==
+ *	33:	sta_alm(ALM1, 10)
+ *	34:	slp_tsk()						... (H-1)
+ *	== ALM1 ==
+ *	35:	iget_tid(&tskid)
+ *		assert(tskid == TSK_NONE)
+ *	36:	iwup_tsk(TASK1)					... (D)
+ *	37:	RETURN
+ *	== TASK1（続き）==
+ *	38: END
+ */
+
+#include <kernel.h>
+#include <test_lib.h>
+#include <t_syslog.h>
+#include "kernel_cfg.h"
+#include "test_task1.h"
+
+/* DO NOT DELETE THIS LINE -- gentest depends on it. */
+
+void
+alarm1_handler(intptr_t exinf)
+{
+	ID		tskid;
+	ER_UINT	ercd;
+
+	check_point(35);
+	ercd = iget_tid(&tskid);
+	check_ercd(ercd, E_OK);
+
+	check_assert(tskid == TSK_NONE);
+
+	check_point(36);
+	ercd = iwup_tsk(TASK1);
+	check_ercd(ercd, E_OK);
+
+	check_point(37);
+	return;
+
+	check_point(0);
+}
+
+void
+task1(intptr_t exinf)
+{
+	ER_UINT	ercd;
+
+	test_start(__FILE__);
+
+	check_point(1);
+	ercd = act_tsk(TASK2);
+	check_ercd(ercd, E_OK);
+
+	check_point(3);
+	ercd = act_tsk(TASK3);
+	check_ercd(ercd, E_OK);
+
+	check_point(4);
+	ercd = act_tsk(TASK4);
+	check_ercd(ercd, E_OK);
+
+	check_point(5);
+	ercd = slp_tsk();
+	check_ercd(ercd, E_OK);
+
+	check_point(9);
+	ercd = act_tsk(TASK5);
+	check_ercd(ercd, E_OK);
+
+	check_point(10);
+	ercd = act_tsk(TASK6);
+	check_ercd(ercd, E_OK);
+
+	check_point(11);
+	ercd = sus_tsk(TASK6);
+	check_ercd(ercd, E_OK);
+
+	check_point(12);
+	ercd = sus_tsk(TASK5);
+	check_ercd(ercd, E_OK);
+
+	check_point(13);
+	ercd = rsm_tsk(TASK5);
+	check_ercd(ercd, E_OK);
+
+	check_point(14);
+	ercd = rsm_tsk(TASK6);
+	check_ercd(ercd, E_OK);
+
+	check_point(15);
+	ercd = slp_tsk();
+	check_ercd(ercd, E_OK);
+
+	check_point(31);
+	ercd = slp_tsk();
+	check_ercd(ercd, E_OK);
+
+	check_finish(38);
+	check_point(0);
+}
+
+void
+task2(intptr_t exinf)
+{
+	ER_UINT	ercd;
+
+	check_point(2);
+	ercd = slp_tsk();
+	check_ercd(ercd, E_OK);
+
+	check_point(0);
+}
+
+void
+task3(intptr_t exinf)
+{
+	ER_UINT	ercd;
+
+	check_point(6);
+	ercd = slp_tsk();
+	check_ercd(ercd, E_OK);
+
+	check_point(25);
+	ercd = slp_tsk();
+	check_ercd(ercd, E_OK);
+
+	check_point(0);
+}
+
+void
+task4(intptr_t exinf)
+{
+	ER_UINT	ercd;
+
+	check_point(7);
+	ercd = wup_tsk(TASK1);
+	check_ercd(ercd, E_OK);
+
+	check_point(8);
+	ercd = slp_tsk();
+	check_ercd(ercd, E_OK);
+
+	check_point(26);
+	ercd = slp_tsk();
+	check_ercd(ercd, E_OK);
+
+	check_point(0);
+}
+
+void
+task5(intptr_t exinf)
+{
+	ER_UINT	ercd;
+
+	check_point(16);
+	ercd = slp_tsk();
+	check_ercd(ercd, E_OK);
+
+	check_point(33);
+	ercd = sta_alm(ALM1, 10);
+	check_ercd(ercd, E_OK);
+
+	check_point(34);
+	ercd = slp_tsk();
+	check_ercd(ercd, E_OK);
+
+	check_point(0);
+}
+
+void
+task6(intptr_t exinf)
+{
+	ER_UINT	ercd;
+
+	check_point(17);
+	ercd = dis_dsp();
+	check_ercd(ercd, E_OK);
+
+	check_point(18);
+	ercd = wup_tsk(TASK1);
+	check_ercd(ercd, E_OK);
+
+	check_point(19);
+	ercd = wup_tsk(TASK2);
+	check_ercd(ercd, E_OK);
+
+	check_point(20);
+	ercd = sus_tsk(TASK2);
+	check_ercd(ercd, E_OK);
+
+	check_point(21);
+	ercd = wup_tsk(TASK3);
+	check_ercd(ercd, E_OK);
+
+	check_point(22);
+	ercd = wup_tsk(TASK4);
+	check_ercd(ercd, E_OK);
+
+	check_point(23);
+	ercd = sus_tsk(TASK1);
+	check_ercd(ercd, E_OK);
+
+	check_point(24);
+	ercd = ena_dsp();
+	check_ercd(ercd, E_OK);
+
+	check_point(27);
+	ercd = dis_dsp();
+	check_ercd(ercd, E_OK);
+
+	check_point(28);
+	ercd = rsm_tsk(TASK1);
+	check_ercd(ercd, E_OK);
+
+	check_point(29);
+	ercd = wup_tsk(TASK5);
+	check_ercd(ercd, E_OK);
+
+	check_point(30);
+	ercd = ena_dsp();
+	check_ercd(ercd, E_OK);
+
+	check_point(32);
+	ercd = slp_tsk();
+	check_ercd(ercd, E_OK);
+
+	check_point(0);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_task1.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_task1.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_task1.cfg	(revision 453)
@@ -0,0 +1,21 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *  タスク管理モジュールのテスト(1)のシステムコンフィギュレーションファイル
+ */
+INCLUDE("target_timer.cfg");
+INCLUDE("syssvc/syslog.cfg");
+INCLUDE("syssvc/banner.cfg");
+INCLUDE("syssvc/serial.cfg");
+
+#include "test_task1.h"
+
+CRE_TSK(TASK1, { TA_ACT, 1, task1, MID_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK2, { TA_NULL, 2, task2, HIGH_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK3, { TA_NULL, 3, task3, MID_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK4, { TA_NULL, 4, task4, MID_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK5, { TA_NULL, 5, task5, LOW_PRIORITY, STACK_SIZE, NULL });
+CRE_TSK(TASK6, { TA_NULL, 6, task6, LOW_PRIORITY, STACK_SIZE, NULL });
+CRE_ALM(ALM1, { TA_NULL, 1, alarm1_handler });
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_task1.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_task1.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_task1.h	(revision 453)
@@ -0,0 +1,76 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2007 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/* 
+ *		タスク管理モジュールのテスト(1)
+ */
+
+/*
+ *  ターゲット依存の定義
+ */
+#include "target_test.h"
+
+/*
+ *  優先度の定義
+ */
+#define HIGH_PRIORITY	4		/* 高優先度 */
+#define MID_PRIORITY	9		/* 中優先度 */
+#define LOW_PRIORITY	14		/* 低優先度 */
+
+/*
+ *  ターゲットに依存する可能性のある定数の定義
+ */
+#ifndef STACK_SIZE
+#define	STACK_SIZE		4096		/* タスクのスタックサイズ */
+#endif /* STACK_SIZE */
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+#ifndef TOPPERS_MACRO_ONLY
+
+extern void	task1(intptr_t exinf);
+extern void	task2(intptr_t exinf);
+extern void	task3(intptr_t exinf);
+extern void	task4(intptr_t exinf);
+extern void	task5(intptr_t exinf);
+extern void	task6(intptr_t exinf);
+extern void	alarm1_handler(intptr_t exinf);
+
+#endif /* TOPPERS_MACRO_ONLY */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_tex1.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_tex1.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_tex1.c	(revision 453)
@@ -0,0 +1,567 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2006-2013 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *		タスク例外処理に関するテスト(1)
+ *
+ * 【テストの目的】
+ *
+ *  タスクからタスク例外処理ルーチンを起動する処理を網羅的にテストする．
+ *
+ * 【テスト項目】
+ *
+ *	(A) ras_texのエラー検出
+ *		(A-1) 対象タスクが休止状態［NGKI1413］
+ *		(A-2) 対象タスクのタスク例外処理ルーチンが定義されていない［NGKI1414］
+ *	(B) dis_texのエラー検出
+ *		(B-1) 自タスクのタスク例外処理ルーチンが定義されていない［NGKI1421］
+ *	(C) ena_texのエラー検出
+ *		(C-1) 自タスクのタスク例外処理ルーチンが定義されていない［NGKI1426］
+ *	(D) ref_texのエラー検出
+ *		(D-1) 対象タスクが休止状態［NGKI1439］
+ *		(D-2) 対象タスクのタスク例外処理ルーチンが定義されていない［NGKI1440］
+ *	(E) ras_texの正常処理［NGKI1415］
+ *		(E-1) 対象タスクが自タスク，タスク例外処理許可，かつ割込み優先
+ *			  度マスク全解除状態で，すぐに実行開始
+ *		(E-2) 対象タスクが自タスクでない
+ *		(E-3) 対象タスクが自タスクだが，タスク例外処理禁止
+ *		(E-4) 対象タスクが自タスクでタスク例外処理許可だが，割込み優先
+ *			  度マスクが全解除でない
+ *	(F) ena_texの正常処理［NGKI1427］
+ *		(F-1) タスク例外処理要求があり，かつ割込み優先度マスク全解除状
+ *			  態で，すぐに実行開始
+ *		(F-2) タスク例外処理要求がない
+ *		(F-3) タスク例外処理要求があるが，割込み優先度マスクが全解除で
+ *			  ない
+ *	(G) chg_ipmの正常処理
+ *		(G-1) タスク例外処理要求があり，かつタスク例外処理許可で，すぐ
+ *			  に実行開始
+ *		(G-2) タスク例外処理要求がない
+ *		(G-3) タスク例外処理要求があるが，タスク例外処理禁止
+ *		(G-4) タスク例外処理要求があるが，割込み優先度マスクが全解除で
+ *			  ない
+ *	(H) タスクディスパッチャによる起動
+ *		(H-1) ディスパッチ後のタスクがタスク例外許可でタスク例外処理要
+ *			  求あり
+ *	(I) タスク例外処理ルーチンからのリターンによる起動（連続起動）
+ *	(J) タスク例外処理ルーチンからの戻り時による状態復帰
+ *		(J-1) タスクに戻ってくる時
+ *		(J-2) タスク例外処理ルーチンが連続起動される時
+ *	(K) タスク例外処理ルーチンの多重起動
+ *	(L) タスク例外処理ルーチンからの戻り時のタスク切換え
+ *
+ * 【使用リソース】
+ *
+ *	TASK1: メインのタスク．自タスクに対してタスク例外処理を要求する
+ *	TASK2: 他タスクに対してタスク例外処理を要求する対象タスク
+ *	TASK3: タスク例外処理ルーチンが定義されていないタスク
+ *	TASK4: 休止状態のタスク
+ *
+ * 【テストシーケンス】
+ *
+ *	== TASK1（優先度：10）==
+ *	1:	state(false, false, TIPM_ENAALL, false, false, true)
+ *		ref_tex(TSK_SELF, &rtex)
+ *		assert((rtex.texstat & TTEX_DIS) != 0U)
+ *		assert(rtex.pndptn == 0U)
+ *		ras_tex(TASK3, 0x0001) -> E_OBJ		... (A-2)
+ *		ras_tex(TASK4, 0x0001) -> E_OBJ		... (A-1)
+ *		ref_tex(TASK3, &rtex) -> E_OBJ		... (D-2)
+ *		ref_tex(TASK4, &rtex) -> E_OBJ		... (D-1)
+ *	2:	ena_tex()							... (F-2)
+ *		state(false, false, TIPM_ENAALL, false, false, false)
+ *		ref_tex(TSK_SELF, &rtex)
+ *		assert((rtex.texstat & TTEX_ENA) != 0U)
+ *		assert(rtex.pndptn == 0U)
+ *	3:	ras_tex(TSK_SELF, 0x0001)			... (E-1)
+ *	== TASK1-TEX-1（1回目）==
+ *	4:	assert(texptn == 0x0001)
+ *		state(false, false, TIPM_ENAALL, false, false, true)
+ *	5:	dis_dsp() ... 4つの状態をそれぞれ変化させる
+ *		chg_ipm(TMAX_INTPRI)
+ *		ena_tex()
+ *		loc_cpu()
+ *		state(false, true, TMAX_INTPRI, true, true, false)
+ *		RETURN
+ *	== TASK1（続き）==
+ *	6:	state(false, false, TIPM_ENAALL, false, false, false)	... (J-1)
+ *	7:	dis_dsp() ... ディスパッチ禁止，タスク例外処理禁止
+ *		dis_tex()
+ *		state(false, false, TIPM_ENAALL, true, true, true)
+ *	8:	ras_tex(TASK1, 0x0002)				... (E-3)
+ *		ref_tex(TSK_SELF, &rtex)
+ *		assert((rtex.texstat & TTEX_DIS) != 0)
+ *		assert(rtex.pndptn == 0x0002)
+ *	9:	ena_tex()							... (F-1)
+ *	== TASK1-TEX-2（2回目）==
+ *	10:	assert(texptn == 0x0002)
+ *		state(false, false, TIPM_ENAALL, true, true, true)
+ *	11:	ras_tex(TASK1, 0x0001)				... (E-3)
+ *		ras_tex(TASK1, 0x0002)				... (E-3)
+ *	12:	ena_dsp() ... 3つの状態をそれぞれ変化させる
+ *		chg_ipm(TMAX_INTPRI)
+ *		loc_cpu()
+ *		state(false, true, TMAX_INTPRI, false, true, true)
+ *		RETURN								... (I)
+ *	== TASK1-TEX-3（3回目）==
+ *	13:	assert(texptn == 0x0003)
+ *		state(false, false, TIPM_ENAALL, true, true, true)	... (J-2)
+ *	14:	ena_dsp() ... ディスパッチ許可，タスク例外許可
+ *		chg_ipm(TMAX_INTPRI)
+ *		ena_tex()
+ *		state(false, false, TMAX_INTPRI, false, true, false)
+ *		chg_ipm(TIPM_ENAALL)				... (G-2)
+ *		chg_ipm(TMAX_INTPRI)
+ *	15: ras_tex(TSK_SELF, 0x0004)			... (E-4)
+ *		chg_ipm(TMAX_INTPRI)				... (G-4)
+ *		dis_tex()
+ *		chg_ipm(TIPM_ENAALL)				... (G-3)
+ *		chg_ipm(TMAX_INTPRI)
+ *		ena_tex()							... (F-3)
+ *	16:	chg_ipm(TIPM_ENAALL)				... (G-1)(K)
+ *	== TASK1-TEX-4（4回目）==
+ *	17:	assert(texptn == 0x0004)
+ *		state(false, false, TIPM_ENAALL, false, false, true)
+ *	18:	dis_dsp() ... 3つの状態をそれぞれ変化させる
+ *		chg_ipm(TMAX_INTPRI)
+ *		loc_cpu()
+ *		state(false, true, TMAX_INTPRI, true, true, true)
+ *		RETURN
+ *	== TASK1-TEX-3（3回目続き）==
+ *	19:	state(false, false, TIPM_ENAALL, false, false, false)
+ *		RETURN
+ *	== TASK1（続き）==
+ *	20:	state(false, false, TIPM_ENAALL, true, true, false)	... (J-1)
+ *	21: ena_dsp()
+ *		rot_rdq(TPRI_SELF)
+ *	== TASK2（優先度：10）	==
+ *	22:	state(false, false, TIPM_ENAALL, false, false, true)
+ *	23:	ena_tex()
+ *		state(false, false, TIPM_ENAALL, false, false, false)
+ *		rot_rdq(TPRI_SELF)
+ *	== TASK3（優先度：10）	==
+ *	24:	state(false, false, TIPM_ENAALL, false, false, true)
+ *	25:	ena_tex() -> E_OBJ					... (C-1)
+ *		state(false, false, TIPM_ENAALL, false, false, true)
+ *	26:	dis_tex() -> E_OBJ					... (B-1)
+ *		state(false, false, TIPM_ENAALL, false, false, true)
+ *		ext_tsk()
+ *	== TASK1（続き）==
+ *	27: ras_tex(TASK2, 0x0001)				... (E-2)
+ *		ref_tex(TASK2, &rtex)
+ *	28:	rot_rdq(TPRI_SELF)					... (H-1)
+ *	== TASK2-TEX-1（1回目）==
+ *	29:	assert(texptn == 0x0001)
+ *		state(false, false, TIPM_ENAALL, false, false, true)
+ *		RETURN
+ *	== TASK2（続き）==
+ *	30: ras_tex(TSK_SELF, 0x0002)
+ *	== TASK2-TEX-2（2回目）==
+ *	31:	assert(texptn == 0x0002)
+ *		state(false, false, TIPM_ENAALL, false, false, true)
+ *	32:	dis_dsp()
+ *		rot_rdq(TPRI_SELF)
+ *	33:	RETURN
+ *	== TASK1（続き）==
+ *	34:	RETURN
+ *	== TASK2（続き）==
+ *	35:	END
+ */
+
+#include <kernel.h>
+#include <test_lib.h>
+#include <t_syslog.h>
+#include "kernel_cfg.h"
+#include "test_tex1.h"
+
+/*
+ *  task4とtex_task4は生成されない
+ */
+
+void
+task4(intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+tex_task4(TEXPTN texptn, intptr_t exinf)
+{
+	check_point(0);
+}
+
+/* DO NOT DELETE THIS LINE -- gentest depends on it. */
+
+void
+task1(intptr_t exinf)
+{
+	ER_UINT	ercd;
+	T_RTEX	rtex;
+
+	test_start(__FILE__);
+
+	check_point(1);
+	check_state(false, false, TIPM_ENAALL, false, false, true);
+
+	ercd = ref_tex(TSK_SELF, &rtex);
+	check_ercd(ercd, E_OK);
+
+	check_assert((rtex.texstat & TTEX_DIS) != 0U);
+
+	check_assert(rtex.pndptn == 0U);
+
+	ercd = ras_tex(TASK3, 0x0001);
+	check_ercd(ercd, E_OBJ);
+
+	ercd = ras_tex(TASK4, 0x0001);
+	check_ercd(ercd, E_OBJ);
+
+	ercd = ref_tex(TASK3, &rtex);
+	check_ercd(ercd, E_OBJ);
+
+	ercd = ref_tex(TASK4, &rtex);
+	check_ercd(ercd, E_OBJ);
+
+	check_point(2);
+	ercd = ena_tex();
+	check_ercd(ercd, E_OK);
+
+	check_state(false, false, TIPM_ENAALL, false, false, false);
+
+	ercd = ref_tex(TSK_SELF, &rtex);
+	check_ercd(ercd, E_OK);
+
+	check_assert((rtex.texstat & TTEX_ENA) != 0U);
+
+	check_assert(rtex.pndptn == 0U);
+
+	check_point(3);
+	ercd = ras_tex(TSK_SELF, 0x0001);
+	check_ercd(ercd, E_OK);
+
+	check_point(6);
+	check_state(false, false, TIPM_ENAALL, false, false, false);
+
+	check_point(7);
+	ercd = dis_dsp();
+	check_ercd(ercd, E_OK);
+
+	ercd = dis_tex();
+	check_ercd(ercd, E_OK);
+
+	check_state(false, false, TIPM_ENAALL, true, true, true);
+
+	check_point(8);
+	ercd = ras_tex(TASK1, 0x0002);
+	check_ercd(ercd, E_OK);
+
+	ercd = ref_tex(TSK_SELF, &rtex);
+	check_ercd(ercd, E_OK);
+
+	check_assert((rtex.texstat & TTEX_DIS) != 0);
+
+	check_assert(rtex.pndptn == 0x0002);
+
+	check_point(9);
+	ercd = ena_tex();
+	check_ercd(ercd, E_OK);
+
+	check_point(20);
+	check_state(false, false, TIPM_ENAALL, true, true, false);
+
+	check_point(21);
+	ercd = ena_dsp();
+	check_ercd(ercd, E_OK);
+
+	ercd = rot_rdq(TPRI_SELF);
+	check_ercd(ercd, E_OK);
+
+	check_point(27);
+	ercd = ras_tex(TASK2, 0x0001);
+	check_ercd(ercd, E_OK);
+
+	ercd = ref_tex(TASK2, &rtex);
+	check_ercd(ercd, E_OK);
+
+	check_point(28);
+	ercd = rot_rdq(TPRI_SELF);
+	check_ercd(ercd, E_OK);
+
+	check_point(34);
+	return;
+
+	check_point(0);
+}
+
+static uint_t	tex_task1_count = 0;
+
+void
+tex_task1(TEXPTN texptn, intptr_t exinf)
+{
+	ER_UINT	ercd;
+
+	switch (++tex_task1_count) {
+	case 1:
+		check_point(4);
+		check_assert(texptn == 0x0001);
+
+		check_state(false, false, TIPM_ENAALL, false, false, true);
+
+		check_point(5);
+		ercd = dis_dsp();
+		check_ercd(ercd, E_OK);
+
+		ercd = chg_ipm(TMAX_INTPRI);
+		check_ercd(ercd, E_OK);
+
+		ercd = ena_tex();
+		check_ercd(ercd, E_OK);
+
+		ercd = loc_cpu();
+		check_ercd(ercd, E_OK);
+
+		check_state(false, true, TMAX_INTPRI, true, true, false);
+
+		return;
+
+		check_point(0);
+
+	case 2:
+		check_point(10);
+		check_assert(texptn == 0x0002);
+
+		check_state(false, false, TIPM_ENAALL, true, true, true);
+
+		check_point(11);
+		ercd = ras_tex(TASK1, 0x0001);
+		check_ercd(ercd, E_OK);
+
+		ercd = ras_tex(TASK1, 0x0002);
+		check_ercd(ercd, E_OK);
+
+		check_point(12);
+		ercd = ena_dsp();
+		check_ercd(ercd, E_OK);
+
+		ercd = chg_ipm(TMAX_INTPRI);
+		check_ercd(ercd, E_OK);
+
+		ercd = loc_cpu();
+		check_ercd(ercd, E_OK);
+
+		check_state(false, true, TMAX_INTPRI, false, true, true);
+
+		return;
+
+		check_point(0);
+
+	case 3:
+		check_point(13);
+		check_assert(texptn == 0x0003);
+
+		check_state(false, false, TIPM_ENAALL, true, true, true);
+
+		check_point(14);
+		ercd = ena_dsp();
+		check_ercd(ercd, E_OK);
+
+		ercd = chg_ipm(TMAX_INTPRI);
+		check_ercd(ercd, E_OK);
+
+		ercd = ena_tex();
+		check_ercd(ercd, E_OK);
+
+		check_state(false, false, TMAX_INTPRI, false, true, false);
+
+		ercd = chg_ipm(TIPM_ENAALL);
+		check_ercd(ercd, E_OK);
+
+		ercd = chg_ipm(TMAX_INTPRI);
+		check_ercd(ercd, E_OK);
+
+		check_point(15);
+		ercd = ras_tex(TSK_SELF, 0x0004);
+		check_ercd(ercd, E_OK);
+
+		ercd = chg_ipm(TMAX_INTPRI);
+		check_ercd(ercd, E_OK);
+
+		ercd = dis_tex();
+		check_ercd(ercd, E_OK);
+
+		ercd = chg_ipm(TIPM_ENAALL);
+		check_ercd(ercd, E_OK);
+
+		ercd = chg_ipm(TMAX_INTPRI);
+		check_ercd(ercd, E_OK);
+
+		ercd = ena_tex();
+		check_ercd(ercd, E_OK);
+
+		check_point(16);
+		ercd = chg_ipm(TIPM_ENAALL);
+		check_ercd(ercd, E_OK);
+
+		check_point(19);
+		check_state(false, false, TIPM_ENAALL, false, false, false);
+
+		return;
+
+		check_point(0);
+
+	case 4:
+		check_point(17);
+		check_assert(texptn == 0x0004);
+
+		check_state(false, false, TIPM_ENAALL, false, false, true);
+
+		check_point(18);
+		ercd = dis_dsp();
+		check_ercd(ercd, E_OK);
+
+		ercd = chg_ipm(TMAX_INTPRI);
+		check_ercd(ercd, E_OK);
+
+		ercd = loc_cpu();
+		check_ercd(ercd, E_OK);
+
+		check_state(false, true, TMAX_INTPRI, true, true, true);
+
+		return;
+
+		check_point(0);
+
+	default:
+		check_point(0);
+	}
+	check_point(0);
+}
+
+void
+task2(intptr_t exinf)
+{
+	ER_UINT	ercd;
+
+	check_point(22);
+	check_state(false, false, TIPM_ENAALL, false, false, true);
+
+	check_point(23);
+	ercd = ena_tex();
+	check_ercd(ercd, E_OK);
+
+	check_state(false, false, TIPM_ENAALL, false, false, false);
+
+	ercd = rot_rdq(TPRI_SELF);
+	check_ercd(ercd, E_OK);
+
+	check_point(30);
+	ercd = ras_tex(TSK_SELF, 0x0002);
+	check_ercd(ercd, E_OK);
+
+	check_finish(35);
+	check_point(0);
+}
+
+static uint_t	tex_task2_count = 0;
+
+void
+tex_task2(TEXPTN texptn, intptr_t exinf)
+{
+	ER_UINT	ercd;
+
+	switch (++tex_task2_count) {
+	case 1:
+		check_point(29);
+		check_assert(texptn == 0x0001);
+
+		check_state(false, false, TIPM_ENAALL, false, false, true);
+
+		return;
+
+		check_point(0);
+
+	case 2:
+		check_point(31);
+		check_assert(texptn == 0x0002);
+
+		check_state(false, false, TIPM_ENAALL, false, false, true);
+
+		check_point(32);
+		ercd = dis_dsp();
+		check_ercd(ercd, E_OK);
+
+		ercd = rot_rdq(TPRI_SELF);
+		check_ercd(ercd, E_OK);
+
+		check_point(33);
+		return;
+
+		check_point(0);
+
+	default:
+		check_point(0);
+	}
+	check_point(0);
+}
+
+void
+task3(intptr_t exinf)
+{
+	ER_UINT	ercd;
+
+	check_point(24);
+	check_state(false, false, TIPM_ENAALL, false, false, true);
+
+	check_point(25);
+	ercd = ena_tex();
+	check_ercd(ercd, E_OBJ);
+
+	check_state(false, false, TIPM_ENAALL, false, false, true);
+
+	check_point(26);
+	ercd = dis_tex();
+	check_ercd(ercd, E_OBJ);
+
+	check_state(false, false, TIPM_ENAALL, false, false, true);
+
+	ercd = ext_tsk();
+	check_ercd(ercd, E_OK);
+
+	check_point(0);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_tex1.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_tex1.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_tex1.cfg	(revision 453)
@@ -0,0 +1,24 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *  タスク例外処理に関するテスト(1)のシステムコンフィギュレーションファイル
+ */
+INCLUDE("target_timer.cfg");
+INCLUDE("syssvc/syslog.cfg");
+INCLUDE("syssvc/banner.cfg");
+INCLUDE("syssvc/serial.cfg");
+
+#include "test_tex1.h"
+
+CRE_TSK(TASK1, { TA_ACT, 1, task1, TASK1_PRIORITY, STACK_SIZE, NULL });
+DEF_TEX(TASK1, { TA_NULL, tex_task1 });
+
+CRE_TSK(TASK2, { TA_ACT, 2, task2, TASK2_PRIORITY, STACK_SIZE, NULL });
+DEF_TEX(TASK2, { TA_NULL, tex_task2 });
+
+CRE_TSK(TASK3, { TA_ACT, 3, task3, TASK3_PRIORITY, STACK_SIZE, NULL });
+
+CRE_TSK(TASK4, { TA_NULL, 4, task4, TASK4_PRIORITY, STACK_SIZE, NULL });
+DEF_TEX(TASK4, { TA_NULL, tex_task4 });
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_tex1.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_tex1.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_tex1.h	(revision 453)
@@ -0,0 +1,80 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2006,2007 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/* 
+ *		タスク例外処理に関するテスト(1)
+ */
+
+/*
+ *  ターゲット依存の定義
+ */
+#include "target_test.h"
+
+/*
+ *  各タスクの優先度の定義
+ */
+#define TASK1_PRIORITY	10		/* タスク1の優先度 */
+#define TASK2_PRIORITY	10		/* タスク2の優先度 */
+#define TASK3_PRIORITY	10		/* タスク3の優先度 */
+#define TASK4_PRIORITY	10		/* タスク4の優先度 */
+
+/*
+ *  ターゲットに依存する可能性のある定数の定義
+ */
+#ifndef STACK_SIZE
+#define	STACK_SIZE		4096		/* タスクのスタックサイズ */
+#endif /* STACK_SIZE */
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+#ifndef TOPPERS_MACRO_ONLY
+
+extern void	tex_task1(TEXPTN texptn, intptr_t exinf);
+extern void	task1(intptr_t exinf);
+
+extern void	tex_task2(TEXPTN texptn, intptr_t exinf);
+extern void	task2(intptr_t exinf);
+
+extern void	task3(intptr_t exinf);
+
+extern void	tex_task4(TEXPTN texptn, intptr_t exinf);
+extern void	task4(intptr_t exinf);
+
+#endif /* TOPPERS_MACRO_ONLY */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_tex2.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_tex2.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_tex2.c	(revision 453)
@@ -0,0 +1,479 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2007-2013 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *		タスク例外処理に関するテスト(2)
+ *
+ * 【テストの目的】
+ *
+ *  割込みハンドラ（アラームハンドラ）およびCPU例外ハンドラからタスク例
+ *  外処理ルーチンを起動する処理を網羅的にテストする．
+ *
+ * 【テスト項目】
+ *
+ *	(A) iras_texのエラー検出
+ *		(A-1) 対象タスクが休止状態
+ *		(A-2) 対象タスクのタスク例外処理ルーチンが定義されていない
+ *	(B) 割込みハンドラから呼ばれたiras_texの正常処理
+ *		(B-1) 対象タスクが実行状態のタスクかつタスク例外処理許可
+ *		(B-2) 対象タスクが実行状態のタスクでない
+ *		(B-3) 対象タスクが実行状態のタスクだがタスク例外処理禁止
+ *	(C) CPU例外ハンドラから呼ばれたiras_texの正常処理
+ *		(C-1) 対象タスクが実行状態のタスクかつタスク例外処理許可
+ *		(C-2) 対象タスクが実行状態のタスクでない
+ *		(C-3) 対象タスクが実行状態のタスクだがタスク例外処理禁止
+ *				→ 実施しない（ターゲット非依存に実現できない）
+ *	(D) 割込みハンドラの出口処理による起動
+ *		(D-1) ディスパッチ後のタスクがタスク例外許可でタスク例外処理要
+ *			  求あり
+ *	(E) CPU例外ハンドラの出口処理による起動
+ *		(E-1) ディスパッチ後のタスクがタスク例外許可でタスク例外処理要
+ *			  求あり
+ *	(F) sns_texで実行状態のタスクがない
+ *
+ * 【使用リソース】
+ *
+ *	TASK1: メインのタスク．実行状態のタスクに対してタスク例外処理を要求す
+ *		   る対象タスク
+ *	TASK2: 実行状態でないタスクに対してタスク例外処理を要求する対象タスク
+ *	TASK3: タスク例外処理ルーチンが定義されていないタスク
+ *	TASK4: 休止状態のタスク
+ *	ALM1:  アラームハンドラ1
+ *	ALM2:  アラームハンドラ2
+ *	ALM3:  アラームハンドラ3
+ *	CPUEXC: CPU例外ハンドラ
+ *
+ * 【テストシーケンス】
+ *
+ *	== TASK1（優先度：10）==
+ *	1:	state(false, false, TIPM_ENAALL, false, false, true)
+ *		ref_tex(TSK_SELF, &rtex)
+ *		assert((rtex.texstat & TTEX_DIS) != 0U)
+ *		assert(rtex.pndptn == 0U)
+ *	2:	sta_alm(ALM1, 1U)
+ *		DO(while (!(alm1_flag)))	... アラームハンドラ1の実行を待つ
+ *	== ALM1 ==
+ *	3:	state_i(true, false, false, true, true)
+ *		iras_tex(TASK3, 0x0001) -> E_OBJ		... (A-2)
+ *		iras_tex(TASK4, 0x0001) -> E_OBJ		... (A-1)
+ *		iras_tex(TASK2, 0x0001)					... (B-2)
+ *		iras_tex(TASK1, 0x0001)					... (B-3)
+ *		DO(alm1_flag = true)
+ *		RETURN
+ *	== TASK1（続き）==
+ *	4:	ena_tex()
+ *	== TASK1-TEX-1（1回目）==
+ *	5:	assert(texptn == 0x0001)
+ *		state(false, false, TIPM_ENAALL, false, false, true)
+ *	6:	dis_dsp() ... 4つの状態をそれぞれ変化させる
+ *		chg_ipm(TMAX_INTPRI)
+ *		ena_tex()
+ *		loc_cpu()
+ *		state(false, true, TMAX_INTPRI, true, true, false)
+ *		RETURN
+ *	== TASK1（続き）==
+ *	7:	state(false, false, TIPM_ENAALL, false, false, false)
+ *		ref_tex(TSK_SELF, &rtex)
+ *		assert((rtex.texstat & TTEX_ENA) != 0U)
+ *		assert(rtex.pndptn == 0U)
+ *	8:	sta_alm(ALM2, 1U)
+ *		DO(while (!(alm2_flag)))
+ *	== ALM2 ==
+ *	9:	state_i(true, false, false, true, false)
+ *		iras_tex(TASK1, 0x0002)					... (B-1)
+ *		DO(alm2_flag = true)
+ *		RETURN									... (D-1)
+ *	== TASK1-TEX-2（2回目）==
+ *	10:	assert(texptn == 0x0002)
+ *		state(false, false, TIPM_ENAALL, false, false, true)
+ *		RETURN
+ *	== TASK1（続き）==
+ *	11:	sus_tsk(TASK2)
+ *		sus_tsk(TASK3)
+ *	12:	sta_alm(ALM3, 10U)
+ *	13:	dly_tsk(50U)
+ *	== ALM3 ==
+ *	14:	state_i(true, false, false, true, true)	... (F)［sns_tex()を含む］
+ *		iget_tid(&tskid)
+ *		assert(tskid == TSK_NONE)
+ *		iras_tex(TASK1, 0x0004)
+ *		DO(alm3_flag = true)
+ *		RETURN
+ *	== TASK1-TEX-3（3回目）==
+ *	15:	assert(texptn == 0x0004)
+ *		state(false, false, TIPM_ENAALL, false, false, true)
+ *		RETURN
+ *	== TASK1（続き）==
+ *	16:	rsm_tsk(TASK2)
+ *		rsm_tsk(TASK3)
+ *		dis_dsp()
+ *	17:	DO(RAISE_CPU_EXCEPTION)
+ *	== CPUEXC ==
+ *	18:	state_i(true, false, true, true, false)
+ *		assert(xsns_xpn(p_excinf) == false)
+ *		iras_tex(TASK3, 0x0010) -> E_OBJ		... (A-2)
+ *		iras_tex(TASK4, 0x0010) -> E_OBJ		... (A-1)
+ *		iras_tex(TASK2, 0x0010)					... (C-2)
+ *		iras_tex(TASK1, 0x0010)					... (C-1)
+ *		RETURN									... (E-1)
+ *	== TASK1-TEX-4（4回目）==
+ *	19:	assert(texptn == 0x0010)
+ *		state(false, false, TIPM_ENAALL, true, true, true)
+ *	20:	ext_tsk()
+ *	== TASK2（優先度：10）==
+ *	21:	state(false, false, TIPM_ENAALL, false, false, true)
+ *	22:	ena_tex()
+ *	== TASK2-TEX ==
+ *	23:	assert(texptn == 0x0011)
+ *		state(false, false, TIPM_ENAALL, false, false, true)
+ *		RETURN
+ *	== TASK2（続き）==
+ *	24:	sus_tsk(TASK3)
+ *	25:	END
+ */
+
+#include <kernel.h>
+#include <test_lib.h>
+#include <t_syslog.h>
+#include "kernel_cfg.h"
+#include "test_tex2.h"
+
+volatile bool_t	alm1_flag = false;
+volatile bool_t	alm2_flag = false;
+volatile bool_t	alm3_flag = false;
+
+/*
+ *  task3，task4とtex_task4は生成されない
+ */
+
+void
+task3(intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+task4(intptr_t exinf)
+{
+	check_point(0);
+}
+
+void
+tex_task4(TEXPTN texptn, intptr_t exinf)
+{
+	check_point(0);
+}
+
+/* DO NOT DELETE THIS LINE -- gentest depends on it. */
+
+void
+alarm1_handler(intptr_t exinf)
+{
+	ER_UINT	ercd;
+
+	check_point(3);
+	check_state_i(true, false, false, true, true);
+
+	ercd = iras_tex(TASK3, 0x0001);
+	check_ercd(ercd, E_OBJ);
+
+	ercd = iras_tex(TASK4, 0x0001);
+	check_ercd(ercd, E_OBJ);
+
+	ercd = iras_tex(TASK2, 0x0001);
+	check_ercd(ercd, E_OK);
+
+	ercd = iras_tex(TASK1, 0x0001);
+	check_ercd(ercd, E_OK);
+
+	alm1_flag = true;
+
+	return;
+
+	check_point(0);
+}
+
+void
+alarm2_handler(intptr_t exinf)
+{
+	ER_UINT	ercd;
+
+	check_point(9);
+	check_state_i(true, false, false, true, false);
+
+	ercd = iras_tex(TASK1, 0x0002);
+	check_ercd(ercd, E_OK);
+
+	alm2_flag = true;
+
+	return;
+
+	check_point(0);
+}
+
+void
+alarm3_handler(intptr_t exinf)
+{
+	ID		tskid;
+	ER_UINT	ercd;
+
+	check_point(14);
+	check_state_i(true, false, false, true, true);
+
+	ercd = iget_tid(&tskid);
+	check_ercd(ercd, E_OK);
+
+	check_assert(tskid == TSK_NONE);
+
+	ercd = iras_tex(TASK1, 0x0004);
+	check_ercd(ercd, E_OK);
+
+	alm3_flag = true;
+
+	return;
+
+	check_point(0);
+}
+
+void
+cpuexc_handler(void *p_excinf)
+{
+	ER_UINT	ercd;
+
+	check_point(18);
+	check_state_i(true, false, true, true, false);
+
+	check_assert(xsns_xpn(p_excinf) == false);
+
+	ercd = iras_tex(TASK3, 0x0010);
+	check_ercd(ercd, E_OBJ);
+
+	ercd = iras_tex(TASK4, 0x0010);
+	check_ercd(ercd, E_OBJ);
+
+	ercd = iras_tex(TASK2, 0x0010);
+	check_ercd(ercd, E_OK);
+
+	ercd = iras_tex(TASK1, 0x0010);
+	check_ercd(ercd, E_OK);
+
+	return;
+
+	check_point(0);
+}
+
+void
+task1(intptr_t exinf)
+{
+	ER_UINT	ercd;
+	T_RTEX	rtex;
+
+	test_start(__FILE__);
+
+	check_point(1);
+	check_state(false, false, TIPM_ENAALL, false, false, true);
+
+	ercd = ref_tex(TSK_SELF, &rtex);
+	check_ercd(ercd, E_OK);
+
+	check_assert((rtex.texstat & TTEX_DIS) != 0U);
+
+	check_assert(rtex.pndptn == 0U);
+
+	check_point(2);
+	ercd = sta_alm(ALM1, 1U);
+	check_ercd(ercd, E_OK);
+
+	while (!(alm1_flag));
+
+	check_point(4);
+	ercd = ena_tex();
+	check_ercd(ercd, E_OK);
+
+	check_point(7);
+	check_state(false, false, TIPM_ENAALL, false, false, false);
+
+	ercd = ref_tex(TSK_SELF, &rtex);
+	check_ercd(ercd, E_OK);
+
+	check_assert((rtex.texstat & TTEX_ENA) != 0U);
+
+	check_assert(rtex.pndptn == 0U);
+
+	check_point(8);
+	ercd = sta_alm(ALM2, 1U);
+	check_ercd(ercd, E_OK);
+
+	while (!(alm2_flag));
+
+	check_point(11);
+	ercd = sus_tsk(TASK2);
+	check_ercd(ercd, E_OK);
+
+	ercd = sus_tsk(TASK3);
+	check_ercd(ercd, E_OK);
+
+	check_point(12);
+	ercd = sta_alm(ALM3, 10U);
+	check_ercd(ercd, E_OK);
+
+	check_point(13);
+	ercd = dly_tsk(50U);
+	check_ercd(ercd, E_OK);
+
+	check_point(16);
+	ercd = rsm_tsk(TASK2);
+	check_ercd(ercd, E_OK);
+
+	ercd = rsm_tsk(TASK3);
+	check_ercd(ercd, E_OK);
+
+	ercd = dis_dsp();
+	check_ercd(ercd, E_OK);
+
+	check_point(17);
+	RAISE_CPU_EXCEPTION;
+
+	check_point(0);
+}
+
+static uint_t	tex_task1_count = 0;
+
+void
+tex_task1(TEXPTN texptn, intptr_t exinf)
+{
+	ER_UINT	ercd;
+
+	switch (++tex_task1_count) {
+	case 1:
+		check_point(5);
+		check_assert(texptn == 0x0001);
+
+		check_state(false, false, TIPM_ENAALL, false, false, true);
+
+		check_point(6);
+		ercd = dis_dsp();
+		check_ercd(ercd, E_OK);
+
+		ercd = chg_ipm(TMAX_INTPRI);
+		check_ercd(ercd, E_OK);
+
+		ercd = ena_tex();
+		check_ercd(ercd, E_OK);
+
+		ercd = loc_cpu();
+		check_ercd(ercd, E_OK);
+
+		check_state(false, true, TMAX_INTPRI, true, true, false);
+
+		return;
+
+		check_point(0);
+
+	case 2:
+		check_point(10);
+		check_assert(texptn == 0x0002);
+
+		check_state(false, false, TIPM_ENAALL, false, false, true);
+
+		return;
+
+		check_point(0);
+
+	case 3:
+		check_point(15);
+		check_assert(texptn == 0x0004);
+
+		check_state(false, false, TIPM_ENAALL, false, false, true);
+
+		return;
+
+		check_point(0);
+
+	case 4:
+		check_point(19);
+		check_assert(texptn == 0x0010);
+
+		check_state(false, false, TIPM_ENAALL, true, true, true);
+
+		check_point(20);
+		ercd = ext_tsk();
+		check_ercd(ercd, E_OK);
+
+		check_point(0);
+
+	default:
+		check_point(0);
+	}
+	check_point(0);
+}
+
+void
+task2(intptr_t exinf)
+{
+	ER_UINT	ercd;
+
+	check_point(21);
+	check_state(false, false, TIPM_ENAALL, false, false, true);
+
+	check_point(22);
+	ercd = ena_tex();
+	check_ercd(ercd, E_OK);
+
+	check_point(24);
+	ercd = sus_tsk(TASK3);
+	check_ercd(ercd, E_OK);
+
+	check_finish(25);
+	check_point(0);
+}
+
+void
+tex_task2(TEXPTN texptn, intptr_t exinf)
+{
+
+	check_point(23);
+	check_assert(texptn == 0x0011);
+
+	check_state(false, false, TIPM_ENAALL, false, false, true);
+
+	return;
+
+	check_point(0);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_tex2.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_tex2.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_tex2.cfg	(revision 453)
@@ -0,0 +1,30 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *  タスク例外処理に関するテスト(2)のシステムコンフィギュレーションファイル
+ */
+INCLUDE("target_timer.cfg");
+INCLUDE("syssvc/syslog.cfg");
+INCLUDE("syssvc/banner.cfg");
+INCLUDE("syssvc/serial.cfg");
+
+#include "test_tex2.h"
+
+CRE_TSK(TASK1, { TA_ACT, 1, task1, TASK1_PRIORITY, STACK_SIZE, NULL });
+DEF_TEX(TASK1, { TA_NULL, tex_task1 });
+
+CRE_TSK(TASK2, { TA_ACT, 2, task2, TASK2_PRIORITY, STACK_SIZE, NULL });
+DEF_TEX(TASK2, { TA_NULL, tex_task2 });
+
+CRE_TSK(TASK3, { TA_ACT, 3, task3, TASK3_PRIORITY, STACK_SIZE, NULL });
+
+CRE_TSK(TASK4, { TA_NULL, 4, task4, TASK4_PRIORITY, STACK_SIZE, NULL });
+DEF_TEX(TASK4, { TA_NULL, tex_task4 });
+
+CRE_ALM(ALM1, { TA_NULL, 1, alarm1_handler });
+CRE_ALM(ALM2, { TA_NULL, 2, alarm2_handler });
+CRE_ALM(ALM3, { TA_NULL, 3, alarm3_handler });
+
+DEF_EXC(CPUEXC1, { TA_NULL, cpuexc_handler });
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_tex2.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_tex2.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_tex2.h	(revision 453)
@@ -0,0 +1,85 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2007 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/* 
+ *		タスク例外処理に関するテスト(2)
+ */
+
+/*
+ *  ターゲット依存の定義
+ */
+#include "target_test.h"
+
+/*
+ *  各タスクの優先度の定義
+ */
+#define TASK1_PRIORITY	10		/* タスク1の優先度 */
+#define TASK2_PRIORITY	10		/* タスク2の優先度 */
+#define TASK3_PRIORITY	10		/* タスク3の優先度 */
+#define TASK4_PRIORITY	10		/* タスク4の優先度 */
+
+/*
+ *  ターゲットに依存する可能性のある定数の定義
+ */
+#ifndef STACK_SIZE
+#define	STACK_SIZE		4096		/* タスクのスタックサイズ */
+#endif /* STACK_SIZE */
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+#ifndef TOPPERS_MACRO_ONLY
+
+extern void	tex_task1(TEXPTN texptn, intptr_t exinf);
+extern void	task1(intptr_t exinf);
+
+extern void	tex_task2(TEXPTN texptn, intptr_t exinf);
+extern void	task2(intptr_t exinf);
+
+extern void	task3(intptr_t exinf);
+
+extern void	tex_task4(TEXPTN texptn, intptr_t exinf);
+extern void	task4(intptr_t exinf);
+
+extern void	alarm1_handler(intptr_t exinf);
+extern void	alarm2_handler(intptr_t exinf);
+extern void	alarm3_handler(intptr_t exinf);
+extern void	cpuexc_handler(void *p_excinf);
+
+#endif /* TOPPERS_MACRO_ONLY */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_utm1.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_utm1.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_utm1.c	(revision 453)
@@ -0,0 +1,124 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2007-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		get_utmに関するテスト(1)
+ *
+ * 【テストの目的】
+ *
+ *  性能評価用システム時刻が逆行することがないことをテストする．
+ *
+ * 【テストの内容】
+ *
+ *  メインタスクでは，性能評価用システム時刻を繰り返し取得し，時刻が小
+ *  さくならないかをチェックする．それと並行して，周期ハンドラを1ミリ秒
+ *  周期で実行し，その中でも性能評価用システム時刻を取得して，時刻が小
+ *  さくならないかをチェックする．
+ *
+ *  なお，性能評価用システム時刻が最大値を超えて0に戻る状況は考慮してい
+ *  ない．
+ */
+
+#include <kernel.h>
+#include <test_lib.h>
+#include <t_syslog.h>
+#include "kernel_cfg.h"
+#include "test_utm1.h"
+
+#define	NO_LOOP		ULONG_C(100000)
+
+SYSUTM	recent_sysutm;
+char	*recent_sysutm_pos;
+uint_t	cyclic_count;
+
+void
+cyclic_handler(intptr_t exinf)
+{
+	SYSUTM		sysutm, prev_sysutm;
+	char		*prev_sysutm_pos;
+
+	iloc_cpu();
+	get_utm(&sysutm);
+	prev_sysutm = recent_sysutm;
+	prev_sysutm_pos = recent_sysutm_pos;
+	recent_sysutm = sysutm;
+	recent_sysutm_pos = "CYC";
+	iunl_cpu();
+
+	if (prev_sysutm > sysutm) {
+		syslog(LOG_NOTICE,
+				"system performance time goes back: %ld(%s) %ld(CYC)",
+				((long_t) prev_sysutm), prev_sysutm_pos, ((ulong_t) sysutm));
+	}
+	cyclic_count += 1;
+}
+
+void
+main_task(intptr_t exinf)
+{
+	SYSUTM		sysutm, prev_sysutm;
+	char		*prev_sysutm_pos;
+	ulong_t		i;
+
+	cyclic_count = 0U;
+	get_utm(&recent_sysutm);
+	syslog(LOG_NOTICE, "system performance time test starts.");
+
+	for (i = 0; i < NO_LOOP; i++) {
+		loc_cpu();
+		get_utm(&sysutm);
+		prev_sysutm = recent_sysutm;
+		prev_sysutm_pos = recent_sysutm_pos;
+		recent_sysutm = sysutm;
+		recent_sysutm_pos = "TSK";
+		unl_cpu();
+
+		if (prev_sysutm > sysutm) {
+			syslog(LOG_NOTICE,
+				"system performance time goes back: %ld(%s) %ld(TSK)",
+				((long_t) prev_sysutm), prev_sysutm_pos, ((ulong_t) sysutm));
+		}
+	}
+
+	syslog(LOG_NOTICE, "system performance time test finishes.");
+	syslog(LOG_NOTICE, "number of cyclic handler execution: %d", cyclic_count);
+	test_finish();
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_utm1.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_utm1.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_utm1.cfg	(revision 453)
@@ -0,0 +1,16 @@
+/*
+ *  $Id$
+ */
+
+/*
+ *  get_utmに関するテスト(1)のシステムコンフィギュレーションファイル
+ */
+INCLUDE("target_timer.cfg");
+INCLUDE("syssvc/syslog.cfg");
+INCLUDE("syssvc/banner.cfg");
+INCLUDE("syssvc/serial.cfg");
+
+#include "test_utm1.h"
+
+CRE_CYC(CYC1, { TA_STA, 0, cyclic_handler, 2, 1 });
+CRE_TSK(MAIN_TASK, { TA_ACT, 0, main_task, MAIN_PRIORITY, STACK_SIZE, NULL });
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_utm1.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_utm1.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/test/test_utm1.h	(revision 453)
@@ -0,0 +1,69 @@
+/*
+ *  TOPPERS Software
+ *      Toyohashi Open Platform for Embedded Real-Time Systems
+ * 
+ *  Copyright (C) 2006-2010 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *		get_utmに関するテスト(1)
+ */
+
+/*
+ *  ターゲット依存の定義
+ */
+#include "target_test.h"
+
+/*
+ *  各タスクの優先度の定義
+ */
+#define MAIN_PRIORITY	10
+
+/*
+ *  ターゲットに依存する可能性のある定数の定義
+ */
+#ifndef STACK_SIZE
+#define	STACK_SIZE		4096		/* タスクのスタックサイズ */
+#endif /* STACK_SIZE */
+
+/*
+ *  関数のプロトタイプ宣言
+ */
+#ifndef TOPPERS_MACRO_ONLY
+
+extern void	cyclic_handler(intptr_t exinf);
+extern void	main_task(intptr_t exinf);
+
+#endif /* TOPPERS_MACRO_ONLY */
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/ui/snfont_disp/Makefile.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/ui/snfont_disp/Makefile.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/ui/snfont_disp/Makefile.config	(revision 453)
@@ -0,0 +1,57 @@
+#
+#   TOPPERS/ASP/FMP Kernel
+#       Toyohashi Open Platform for Embedded Real-Time Systems/
+#       Advanced Standard Profile Kernel
+#
+#   Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                               Toyohashi Univ. of Technology, JAPAN
+#   Copyright (C) 2003-2008 by Ryosuke Takeuchi
+#                Platform Development Center RICOH COMPANY,LTD. JAPAN
+#   Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+
+#
+#  Makefile のプロセッサ依存 (snfont_disp用)
+#
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/ui/snfont_disp
+
+#
+#  プログラムに関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR):$(SRCDIR)/ui/snfont_disp
+SYSSVC_COBJS := $(SYSSVC_COBJS) glcd_disp.o font9.o font12.o font16.o \
+	shinonome_font.o
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/ui/snfont_disp/font12.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/ui/snfont_disp/font12.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/ui/snfont_disp/font12.c	(revision 453)
@@ -0,0 +1,4577 @@
+/*
+ *  TOPPERS ECHONET Lite Communication Middleware
+ * 
+ *  Copyright (C) 2018 Cores Co., Ltd. Japan
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ * 東雲フォント
+ * http://openlab.ring.gr.jp/efont/shinonome/
+ * Licence
+ * Public Domain
+ */
+
+
+#include "fonts.h"
+
+/*
+ *  001
+ */
+static const uint8_t Font12_01[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x20, //   #   
+	0x20, //   #   
+	0x70, //  ###  
+	0x70, //  ###  
+	0xF8, // ##### 
+	0xF8, // ##### 
+	0x70, //  ###  
+	0x70, //  ###  
+	0x20, //   #   
+	0x20, //   #   
+	0x00  //       
+};
+
+/*
+ *  002
+ */
+static const uint8_t Font12_02[] = {
+	6, 12,
+	1, 12,
+	0x54, //  # # #
+	0xA8, // # # # 
+	0x54, //  # # #
+	0xA8, // # # # 
+	0x54, //  # # #
+	0xA8, // # # # 
+	0x54, //  # # #
+	0xA8, // # # # 
+	0x54, //  # # #
+	0xA8, // # # # 
+	0x54, //  # # #
+	0xA8  // # # # 
+};
+
+/*
+ *  003
+ */
+static const uint8_t Font12_03[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0xA0, // # #   
+	0xA0, // # #   
+	0xE0, // ###   
+	0xA0, // # #   
+	0xA0, // # #   
+	0x38, //   ### 
+	0x10, //    #  
+	0x10, //    #  
+	0x10, //    #  
+	0x10, //    #  
+	0x00  //       
+};
+
+/*
+ *  004
+ */
+static const uint8_t Font12_04[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0xE0, // ###   
+	0x80, // #     
+	0xE0, // ###   
+	0x80, // #     
+	0x80, // #     
+	0x38, //   ### 
+	0x20, //   #   
+	0x38, //   ### 
+	0x20, //   #   
+	0x20, //   #   
+	0x00  //       
+};
+
+/*
+ *  005
+ */
+static const uint8_t Font12_05[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x60, //  ##   
+	0x80, // #     
+	0x80, // #     
+	0x80, // #     
+	0x60, //  ##   
+	0x30, //   ##  
+	0x28, //   # # 
+	0x30, //   ##  
+	0x28, //   # # 
+	0x28, //   # # 
+	0x00  //       
+};
+
+/*
+ *  006
+ */
+static const uint8_t Font12_06[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x80, // #     
+	0x80, // #     
+	0x80, // #     
+	0x80, // #     
+	0xE0, // ###   
+	0x38, //   ### 
+	0x20, //   #   
+	0x38, //   ### 
+	0x20, //   #   
+	0x20, //   #   
+	0x00  //       
+};
+
+/*
+ *  007
+ */
+static const uint8_t Font12_07[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x60, //  ##   
+	0x90, // #  #  
+	0x60, //  ##   
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  008
+ */
+static const uint8_t Font12_08[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0xF8, // ##### 
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x00, //       
+	0xF8, // ##### 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  009
+ */
+static const uint8_t Font12_09[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0xC0, // ##    
+	0xA0, // # #   
+	0xA0, // # #   
+	0xA0, // # #   
+	0xA0, // # #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x38, //   ### 
+	0x00  //       
+};
+
+/*
+ *  010
+ */
+static const uint8_t Font12_10[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0xA0, // # #   
+	0xA0, // # #   
+	0xA0, // # #   
+	0xA0, // # #   
+	0x40, //  #    
+	0x30, //   ##  
+	0x28, //   # # 
+	0x30, //   ##  
+	0x28, //   # # 
+	0x28, //   # # 
+	0x00  //       
+};
+
+/*
+ *  011
+ */
+static const uint8_t Font12_11[] = {
+	6, 12,
+	1, 12,
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0xE0, // ###   
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  012
+ */
+static const uint8_t Font12_12[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0xE0, // ###   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20  //   #   
+};
+
+/*
+ *  013
+ */
+static const uint8_t Font12_13[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x3C, //   ####
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20  //   #   
+};
+
+/*
+ *  014
+ */
+static const uint8_t Font12_14[] = {
+	6, 12,
+	1, 12,
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x3C, //   ####
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  015
+ */
+static const uint8_t Font12_15[] = {
+	6, 12,
+	1, 12,
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0xFC, // ######
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20  //   #   
+};
+
+/*
+ *  016
+ */
+static const uint8_t Font12_16[] = {
+	6, 12,
+	1, 12,
+	0xFC, // ######
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  017
+ */
+static const uint8_t Font12_17[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0xFC, // ######
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  018
+ */
+static const uint8_t Font12_18[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0xFC, // ######
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  019
+ */
+static const uint8_t Font12_19[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0xFC, // ######
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  020
+ */
+static const uint8_t Font12_20[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0xFC  // ######
+};
+
+/*
+ *  021
+ */
+static const uint8_t Font12_21[] = {
+	6, 12,
+	1, 12,
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x3C, //   ####
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20  //   #   
+};
+
+/*
+ *  022
+ */
+static const uint8_t Font12_22[] = {
+	6, 12,
+	1, 12,
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0xE0, // ###   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20  //   #   
+};
+
+/*
+ *  023
+ */
+static const uint8_t Font12_23[] = {
+	6, 12,
+	1, 12,
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0xFC, // ######
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  024
+ */
+static const uint8_t Font12_24[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0xFC, // ######
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20  //   #   
+};
+
+/*
+ *  025
+ */
+static const uint8_t Font12_25[] = {
+	6, 12,
+	1, 12,
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20  //   #   
+};
+
+/*
+ *  026
+ */
+static const uint8_t Font12_26[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x18, //    ## 
+	0x60, //  ##   
+	0x80, // #     
+	0x60, //  ##   
+	0x18, //    ## 
+	0xF8, // ##### 
+	0x00, //       
+	0xF8, // ##### 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  027
+ */
+static const uint8_t Font12_27[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0xC0, // ##    
+	0x30, //   ##  
+	0x08, //     # 
+	0x30, //   ##  
+	0xC0, // ##    
+	0xF8, // ##### 
+	0x00, //       
+	0xF8, // ##### 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  028
+ */
+static const uint8_t Font12_28[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0xF8, // ##### 
+	0x50, //  # #  
+	0x50, //  # #  
+	0x50, //  # #  
+	0x50, //  # #  
+	0x58, //  # ## 
+	0x80, // #     
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  029
+ */
+static const uint8_t Font12_29[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x08, //     # 
+	0x08, //     # 
+	0x10, //    #  
+	0xF8, // ##### 
+	0x20, //   #   
+	0xF8, // ##### 
+	0x40, //  #    
+	0x80, // #     
+	0x80, // #     
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  030
+ */
+static const uint8_t Font12_30[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x18, //    ## 
+	0x20, //   #   
+	0x20, //   #   
+	0xF8, // ##### 
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x60, //  ##   
+	0xA4, // # #  #
+	0x58, //  # ## 
+	0x00  //       
+};
+
+/*
+ *  031
+ */
+static const uint8_t Font12_31[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x20, //   #   
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  SPACE
+ */
+static const uint8_t Font12_32[] = {
+	6, 12,
+	0, 0
+};
+
+/*
+ *  !
+ */
+static const uint8_t Font12_33[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x00, //       
+	0x20, //   #   
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '!'
+ */
+static const uint8_t Font12_34[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x50, //  # #  
+	0x50, //  # #  
+	0x50, //  # #  
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '#'
+ */
+static const uint8_t Font12_35[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x50, //  # #  
+	0x50, //  # #  
+	0xF8, // ##### 
+	0x50, //  # #  
+	0x50, //  # #  
+	0x50, //  # #  
+	0xF8, // ##### 
+	0x50, //  # #  
+	0x50, //  # #  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '$'
+ */
+static const uint8_t Font12_36[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x20, //   #   
+	0x70, //  ###  
+	0xA8, // # # # 
+	0xA8, // # # # 
+	0x60, //  ##   
+	0x30, //   ##  
+	0x28, //   # # 
+	0xA8, // # # # 
+	0x70, //  ###  
+	0x20, //   #   
+	0x00  //       
+};
+
+/*
+ *  '%'
+ */
+static const uint8_t Font12_37[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x48, //  #  # 
+	0xA8, // # # # 
+	0x50, //  # #  
+	0x10, //    #  
+	0x20, //   #   
+	0x20, //   #   
+	0x50, //  # #  
+	0x68, //  ## # 
+	0x90, // #  #  
+	0x80, // #     
+	0x00  //       
+};
+
+/*
+ *  '&'
+ */
+static const uint8_t Font12_38[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x60, //  ##   
+	0x90, // #  #  
+	0x90, // #  #  
+	0x60, //  ##   
+	0x40, //  #    
+	0xA8, // # # # 
+	0x90, // #  #  
+	0x90, // #  #  
+	0x68, //  ## # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '''
+ */
+static const uint8_t Font12_39[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x30, //   ##  
+	0x10, //    #  
+	0x20, //   #   
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '('
+ */
+static const uint8_t Font12_40[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x08, //     # 
+	0x10, //    #  
+	0x10, //    #  
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x10, //    #  
+	0x10, //    #  
+	0x08, //     # 
+	0x00  //       
+};
+
+/*
+ *  ')'
+ */
+static const uint8_t Font12_41[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x80, // #     
+	0x40, //  #    
+	0x40, //  #    
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x40, //  #    
+	0x40, //  #    
+	0x80, // #     
+	0x00  //       
+};
+
+/*
+ *  '*'
+ */
+static const uint8_t Font12_42[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x20, //   #   
+	0xA8, // # # # 
+	0x70, //  ###  
+	0xA8, // # # # 
+	0x20, //   #   
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '+'
+ */
+static const uint8_t Font12_43[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x20, //   #   
+	0x20, //   #   
+	0xF8, // ##### 
+	0x20, //   #   
+	0x20, //   #   
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  ','
+ */
+static const uint8_t Font12_44[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x20, //   #   
+	0x20, //   #   
+	0x40, //  #    
+	0x00  //       
+};
+
+/*
+ *  '-'
+ */
+static const uint8_t Font12_45[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0xF8, // ##### 
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '.'
+ */
+static const uint8_t Font12_46[] = {
+	5, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x20, //   #   
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '/'
+ */
+static const uint8_t Font12_47[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x08, //     # 
+	0x08, //     # 
+	0x10, //    #  
+	0x10, //    #  
+	0x20, //   #   
+	0x20, //   #   
+	0x40, //  #    
+	0x40, //  #    
+	0x80, // #     
+	0x80, // #     
+	0x00  //       
+};
+
+/*
+ *  '0'
+ */
+static const uint8_t Font12_48[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x30, //   ##  
+	0x48, //  #  # 
+	0x48, //  #  # 
+	0x48, //  #  # 
+	0x48, //  #  # 
+	0x48, //  #  # 
+	0x48, //  #  # 
+	0x48, //  #  # 
+	0x30, //   ##  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '1'
+ */
+static const uint8_t Font12_49[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x20, //   #   
+	0xE0, // ###   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '2'
+ */
+static const uint8_t Font12_50[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x08, //     # 
+	0x10, //    #  
+	0x20, //   #   
+	0x40, //  #    
+	0x80, // #     
+	0xF8, // ##### 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '3'
+ */
+static const uint8_t Font12_51[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x08, //     # 
+	0x30, //   ##  
+	0x08, //     # 
+	0x08, //     # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '4'
+ */
+static const uint8_t Font12_52[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x10, //    #  
+	0x30, //   ##  
+	0x30, //   ##  
+	0x50, //  # #  
+	0x50, //  # #  
+	0x90, // #  #  
+	0xF8, // ##### 
+	0x10, //    #  
+	0x10, //    #  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '5'
+ */
+static const uint8_t Font12_53[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0xF0, // ####  
+	0x80, // #     
+	0x80, // #     
+	0xF0, // ####  
+	0x88, // #   # 
+	0x08, //     # 
+	0x08, //     # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '6'
+ */
+static const uint8_t Font12_54[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x30, //   ##  
+	0x40, //  #    
+	0x80, // #     
+	0xF0, // ####  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '7'
+ */
+static const uint8_t Font12_55[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0xF8, // ##### 
+	0x08, //     # 
+	0x10, //    #  
+	0x10, //    #  
+	0x10, //    #  
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '8'
+ */
+static const uint8_t Font12_56[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '9'
+ */
+static const uint8_t Font12_57[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x78, //  #### 
+	0x08, //     # 
+	0x08, //     # 
+	0x10, //    #  
+	0x60, //  ##   
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  ':'
+ */
+static const uint8_t Font12_58[] = {
+	5, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x20, //   #   
+	0x00, //       
+	0x00, //       
+	0x20, //   #   
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  ';'
+ */
+static const uint8_t Font12_59[] = {
+	5, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x20, //   #   
+	0x00, //       
+	0x00, //       
+	0x20, //   #   
+	0x20, //   #   
+	0x40, //  #    
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '<'
+ */
+static const uint8_t Font12_60[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x08, //     # 
+	0x10, //    #  
+	0x20, //   #   
+	0x40, //  #    
+	0x20, //   #   
+	0x10, //    #  
+	0x08, //     # 
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '='
+ */
+static const uint8_t Font12_61[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0xF8, // ##### 
+	0x00, //       
+	0xF8, // ##### 
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '>'
+ */
+static const uint8_t Font12_62[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x40, //  #    
+	0x20, //   #   
+	0x10, //    #  
+	0x08, //     # 
+	0x10, //    #  
+	0x20, //   #   
+	0x40, //  #    
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '?'
+ */
+static const uint8_t Font12_63[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x10, //    #  
+	0x10, //    #  
+	0x20, //   #   
+	0x20, //   #   
+	0x00, //       
+	0x20, //   #   
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '@'
+ */
+static const uint8_t Font12_64[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x98, // #  ## 
+	0xA8, // # # # 
+	0xA8, // # # # 
+	0xA8, // # # # 
+	0x90, // #  #  
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'A'
+ */
+static const uint8_t Font12_65[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x20, //   #   
+	0x20, //   #   
+	0x50, //  # #  
+	0x50, //  # #  
+	0x50, //  # #  
+	0xF8, // ##### 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'B'
+ */
+static const uint8_t Font12_66[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0xF0, // ####  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x90, // #  #  
+	0xF0, // ####  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0xF0, // ####  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'C'
+ */
+static const uint8_t Font12_67[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x30, //   ##  
+	0x48, //  #  # 
+	0x88, // #   # 
+	0x80, // #     
+	0x80, // #     
+	0x80, // #     
+	0x88, // #   # 
+	0x48, //  #  # 
+	0x30, //   ##  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'D'
+ */
+static const uint8_t Font12_68[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0xE0, // ###   
+	0x90, // #  #  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x90, // #  #  
+	0xE0, // ###   
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'E'
+ */
+static const uint8_t Font12_69[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0xF8, // ##### 
+	0x80, // #     
+	0x80, // #     
+	0x80, // #     
+	0xF0, // ####  
+	0x80, // #     
+	0x80, // #     
+	0x80, // #     
+	0xF8, // ##### 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'F'
+ */
+static const uint8_t Font12_70[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0xF8, // ##### 
+	0x80, // #     
+	0x80, // #     
+	0x80, // #     
+	0xF0, // ####  
+	0x80, // #     
+	0x80, // #     
+	0x80, // #     
+	0x80, // #     
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'G'
+ */
+static const uint8_t Font12_71[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x30, //   ##  
+	0x48, //  #  # 
+	0x80, // #     
+	0x80, // #     
+	0xB8, // # ### 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x48, //  #  # 
+	0x38, //   ### 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'H'
+ */
+static const uint8_t Font12_72[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0xF8, // ##### 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'I'
+ */
+static const uint8_t Font12_73[] = {
+	5, 12,
+	1, 12,
+	0x00, //       
+	0x70, //  ###  
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'J'
+ */
+static const uint8_t Font12_74[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x10, //    #  
+	0x10, //    #  
+	0x10, //    #  
+	0x10, //    #  
+	0x10, //    #  
+	0x10, //    #  
+	0x90, // #  #  
+	0x90, // #  #  
+	0x60, //  ##   
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'K'
+ */
+static const uint8_t Font12_75[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x88, // #   # 
+	0x90, // #  #  
+	0xA0, // # #   
+	0xC0, // ##    
+	0xA0, // # #   
+	0xA0, // # #   
+	0x90, // #  #  
+	0x90, // #  #  
+	0x88, // #   # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'L'
+ */
+static const uint8_t Font12_76[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x80, // #     
+	0x80, // #     
+	0x80, // #     
+	0x80, // #     
+	0x80, // #     
+	0x80, // #     
+	0x80, // #     
+	0x80, // #     
+	0xF8, // ##### 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'M'
+ */
+static const uint8_t Font12_77[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x88, // #   # 
+	0x88, // #   # 
+	0xD8, // ## ## 
+	0xD8, // ## ## 
+	0xD8, // ## ## 
+	0xA8, // # # # 
+	0xA8, // # # # 
+	0xA8, // # # # 
+	0x88, // #   # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'N'
+ */
+static const uint8_t Font12_78[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x88, // #   # 
+	0xC8, // ##  # 
+	0xC8, // ##  # 
+	0xA8, // # # # 
+	0xA8, // # # # 
+	0x98, // #  ## 
+	0x98, // #  ## 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'O'
+ */
+static const uint8_t Font12_79[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'P'
+ */
+static const uint8_t Font12_80[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0xF0, // ####  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0xF0, // ####  
+	0x80, // #     
+	0x80, // #     
+	0x80, // #     
+	0x80, // #     
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'Q'
+ */
+static const uint8_t Font12_81[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0xA8, // # # # 
+	0x90, // #  #  
+	0x68, //  ## # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'R'
+ */
+static const uint8_t Font12_82[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0xF0, // ####  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0xF0, // ####  
+	0x90, // #  #  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'S'
+ */
+static const uint8_t Font12_83[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x80, // #     
+	0x60, //  ##   
+	0x10, //    #  
+	0x08, //     # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'T'
+ */
+static const uint8_t Font12_84[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0xF8, // ##### 
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'U'
+ */
+static const uint8_t Font12_85[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'V'
+ */
+static const uint8_t Font12_86[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x50, //  # #  
+	0x50, //  # #  
+	0x50, //  # #  
+	0x20, //   #   
+	0x20, //   #   
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'W'
+ */
+static const uint8_t Font12_87[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0xA8, // # # # 
+	0xA8, // # # # 
+	0xA8, // # # # 
+	0xA8, // # # # 
+	0xA8, // # # # 
+	0xA8, // # # # 
+	0x50, //  # #  
+	0x50, //  # #  
+	0x50, //  # #  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'X'
+ */
+static const uint8_t Font12_88[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x88, // #   # 
+	0x88, // #   # 
+	0x50, //  # #  
+	0x50, //  # #  
+	0x20, //   #   
+	0x50, //  # #  
+	0x50, //  # #  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'Y'
+ */
+static const uint8_t Font12_89[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x88, // #   # 
+	0x88, // #   # 
+	0x50, //  # #  
+	0x50, //  # #  
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'Z'
+ */
+static const uint8_t Font12_90[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0xF8, // ##### 
+	0x08, //     # 
+	0x10, //    #  
+	0x10, //    #  
+	0x20, //   #   
+	0x40, //  #    
+	0x40, //  #    
+	0x80, // #     
+	0xF8, // ##### 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '['
+ */
+static const uint8_t Font12_91[] = {
+	5, 12,
+	1, 12,
+	0x00, //       
+	0x38, //   ### 
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x38  //   ### 
+};
+
+/*
+ *  '\'
+ */
+static const uint8_t Font12_92[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x80, // #     
+	0x80, // #     
+	0x40, //  #    
+	0x40, //  #    
+	0x20, //   #   
+	0x20, //   #   
+	0x10, //    #  
+	0x10, //    #  
+	0x08, //     # 
+	0x08, //     # 
+	0x00  //       
+};
+
+/*
+ *  ']'
+ */
+static const uint8_t Font12_93[] = {
+	5, 12,
+	1, 12,
+	0x00, //       
+	0x70, //  ###  
+	0x10, //    #  
+	0x10, //    #  
+	0x10, //    #  
+	0x10, //    #  
+	0x10, //    #  
+	0x10, //    #  
+	0x10, //    #  
+	0x10, //    #  
+	0x10, //    #  
+	0x70  //  ###  
+};
+
+/*
+ *  '^'
+ */
+static const uint8_t Font12_94[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x20, //   #   
+	0x50, //  # #  
+	0x88, // #   # 
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '_'
+ */
+static const uint8_t Font12_95[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0xF8, // ##### 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '''
+ */
+static const uint8_t Font12_96[] = {
+	5, 12,
+	1, 12,
+	0x00, //       
+	0x30, //   ##  
+	0x20, //   #   
+	0x10, //    #  
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'a'
+ */
+static const uint8_t Font12_97[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x18, //    ## 
+	0x68, //  ## # 
+	0x88, // #   # 
+	0x98, // #  ## 
+	0x68, //  ## # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'b'
+ */
+static const uint8_t Font12_98[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x80, // #     
+	0x80, // #     
+	0xB0, // # ##  
+	0xC8, // ##  # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0xC8, // ##  # 
+	0xB0, // # ##  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'c'
+ */
+static const uint8_t Font12_99[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x80, // #     
+	0x80, // #     
+	0x80, // #     
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'd'
+ */
+static const uint8_t Font12_100[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x08, //     # 
+	0x08, //     # 
+	0x68, //  ## # 
+	0x98, // #  ## 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x98, // #  ## 
+	0x68, //  ## # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'e'
+ */
+static const uint8_t Font12_101[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x88, // #   # 
+	0xF8, // ##### 
+	0x80, // #     
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'f'
+ */
+static const uint8_t Font12_102[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x18, //    ## 
+	0x20, //   #   
+	0x70, //  ###  
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'g'
+ */
+static const uint8_t Font12_103[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x78, //  #### 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x98, // #  ## 
+	0x68, //  ## # 
+	0x08, //     # 
+	0x88, // #   # 
+	0x70  //  ###  
+};
+
+/*
+ *  'h'
+ */
+static const uint8_t Font12_104[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x80, // #     
+	0x80, // #     
+	0xB0, // # ##  
+	0xC8, // ##  # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'i'
+ */
+static const uint8_t Font12_105[] = {
+	5, 12,
+	1, 12,
+	0x00, //       
+	0x20, //   #   
+	0x00, //       
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'j'
+ */
+static const uint8_t Font12_106[] = {
+	5, 12,
+	1, 12,
+	0x00, //       
+	0x20, //   #   
+	0x00, //       
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x40  //  #    
+};
+
+/*
+ *  'k'
+ */
+static const uint8_t Font12_107[] = {
+	5, 12,
+	1, 12,
+	0x00, //       
+	0x80, // #     
+	0x80, // #     
+	0x80, // #     
+	0x90, // #  #  
+	0xA0, // # #   
+	0xC0, // ##    
+	0xA0, // # #   
+	0x90, // #  #  
+	0x88, // #   # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'l'
+ */
+static const uint8_t Font12_108[] = {
+	5, 12,
+	1, 12,
+	0x00, //       
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'm'
+ */
+static const uint8_t Font12_109[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0xF0, // ####  
+	0xA8, // # # # 
+	0xA8, // # # # 
+	0xA8, // # # # 
+	0xA8, // # # # 
+	0xA8, // # # # 
+	0xA8, // # # # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'n'
+ */
+static const uint8_t Font12_110[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0xB0, // # ##  
+	0xC8, // ##  # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'o'
+ */
+static const uint8_t Font12_111[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'p'
+ */
+static const uint8_t Font12_112[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0xB0, // # ##  
+	0xC8, // ##  # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0xC8, // ##  # 
+	0xB0, // # ##  
+	0x80, // #     
+	0x80  // #     
+};
+
+/*
+ *  'q'
+ */
+static const uint8_t Font12_113[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x68, //  ## # 
+	0x98, // #  ## 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x98, // #  ## 
+	0x68, //  ## # 
+	0x08, //     # 
+	0x08  //     # 
+};
+
+/*
+ *  'r'
+ */
+static const uint8_t Font12_114[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x58, //  # ## 
+	0x60, //  ##   
+	0x40, //  #    
+	0x40, //  #    
+	0x40, //  #    
+	0x40, //  #    
+	0x40, //  #    
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  's'
+ */
+static const uint8_t Font12_115[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x40, //  #    
+	0x30, //   ##  
+	0x08, //     # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  't'
+ */
+static const uint8_t Font12_116[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x40, //  #    
+	0x40, //  #    
+	0xF0, // ####  
+	0x40, //  #    
+	0x40, //  #    
+	0x40, //  #    
+	0x40, //  #    
+	0x40, //  #    
+	0x60, //  ##   
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'u'
+ */
+static const uint8_t Font12_117[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x98, // #  ## 
+	0x68, //  ## # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'v'
+ */
+static const uint8_t Font12_118[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x50, //  # #  
+	0x50, //  # #  
+	0x20, //   #   
+	0x20, //   #   
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'w'
+ */
+static const uint8_t Font12_119[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x88, // #   # 
+	0xA8, // # # # 
+	0xA8, // # # # 
+	0xA8, // # # # 
+	0xA8, // # # # 
+	0xA8, // # # # 
+	0x50, //  # #  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'x'
+ */
+static const uint8_t Font12_120[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x88, // #   # 
+	0x50, //  # #  
+	0x50, //  # #  
+	0x20, //   #   
+	0x50, //  # #  
+	0x50, //  # #  
+	0x88, // #   # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'y'
+ */
+static const uint8_t Font12_121[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x88, // #   # 
+	0x88, // #   # 
+	0x48, //  #  # 
+	0x50, //  # #  
+	0x50, //  # #  
+	0x20, //   #   
+	0x20, //   #   
+	0x40, //  #    
+	0x80  // #     
+};
+
+/*
+ *  'z'
+ */
+static const uint8_t Font12_122[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0xF8, // ##### 
+	0x10, //    #  
+	0x10, //    #  
+	0x20, //   #   
+	0x40, //  #    
+	0x40, //  #    
+	0xF8, // ##### 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '{'
+ */
+static const uint8_t Font12_123[] = {
+	5, 12,
+	1, 12,
+	0x00, //       
+	0x08, //     # 
+	0x10, //    #  
+	0x10, //    #  
+	0x10, //    #  
+	0x10, //    #  
+	0x20, //   #   
+	0x10, //    #  
+	0x10, //    #  
+	0x10, //    #  
+	0x10, //    #  
+	0x08  //     # 
+};
+
+/*
+ *  '|'
+ */
+static const uint8_t Font12_124[] = {
+	5, 12,
+	1, 12,
+	0x00, //       
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20  //   #   
+};
+
+/*
+ *  '}'
+ */
+static const uint8_t Font12_125[] = {
+	5, 12,
+	1, 12,
+	0x00, //       
+	0x40, //  #    
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x10, //    #  
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x40  //  #    
+};
+
+/*
+ *  '->'
+ */
+static const uint8_t Font12_126[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x48, //  #  # 
+	0xB0, // # ##  
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  DEL
+ */
+static const uint8_t Font12_127[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  yohaku
+ */
+static const uint8_t Font12_160[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  syuryou
+ */
+static const uint8_t Font12_161[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x20, //   #   
+	0x00, //       
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  kakko
+ */
+static const uint8_t Font12_162[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x10, //    #  
+	0x70, //  ###  
+	0x98, // #  ## 
+	0xA0, // # #   
+	0xA0, // # #   
+	0xA0, // # #   
+	0xC8, // ##  # 
+	0x70, //  ###  
+	0x40, //  #    
+	0x00  //       
+};
+
+/*
+ *  kakko tojiru
+ */
+static const uint8_t Font12_163[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x10, //    #  
+	0x28, //   # # 
+	0x20, //   #   
+	0x78, //  #### 
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x68, //  ## # 
+	0xA8, // # # # 
+	0x50, //  # #  
+	0x00  //       
+};
+
+/*
+ *  kutouten
+ */
+static const uint8_t Font12_164[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x88, // #   # 
+	0x70, //  ###  
+	0x50, //  # #  
+	0x70, //  ###  
+	0x88, // #   # 
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  cyuten
+ */
+static const uint8_t Font12_165[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x88, // #   # 
+	0x88, // #   # 
+	0x50, //  # #  
+	0xF8, // ##### 
+	0x20, //   #   
+	0xF8, // ##### 
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'WO'
+ */
+static const uint8_t Font12_166[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x00, //       
+	0x00, //       
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x00  //       
+};
+
+/*
+ *  'aa'
+ */
+static const uint8_t Font12_167[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x30, //   ##  
+	0x48, //  #  # 
+	0x40, //  #    
+	0x30, //   ##  
+	0x48, //  #  # 
+	0x30, //   ##  
+	0x08, //     # 
+	0x48, //  #  # 
+	0x48, //  #  # 
+	0x30, //   ##  
+	0x00  //       
+};
+
+/*
+ *  'ii'
+ */
+static const uint8_t Font12_168[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x50, //  # #  
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'uu'
+ */
+static const uint8_t Font12_169[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0xB8, // # ### 
+	0xC8, // ##  # 
+	0xC8, // ##  # 
+	0xB8, // # ### 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'ee'
+ */
+static const uint8_t Font12_170[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x60, //  ##   
+	0xA0, // # #   
+	0xA0, // # #   
+	0x50, //  # #  
+	0x00, //       
+	0xF0, // ####  
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'oo'
+ */
+static const uint8_t Font12_171[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x28, //   # # 
+	0x50, //  # #  
+	0xA0, // # #   
+	0x50, //  # #  
+	0x28, //   # # 
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'ya'
+ */
+static const uint8_t Font12_172[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0xF8, // ##### 
+	0x08, //     # 
+	0x08, //     # 
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'yu'
+ */
+static const uint8_t Font12_173[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x70, //  ###  
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+};
+
+/*
+ *  'yo'
+ */
+static const uint8_t Font12_174[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x78, //  #### 
+	0x84, // #    #
+	0xB4, // # ## #
+	0xAC, // # # ##
+	0xB4, // # ## #
+	0xAC, // # # ##
+	0xAC, // # # ##
+	0x78, //  #### 
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+
+/*
+ *  'tu'
+ */
+static const uint8_t Font12_175[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x70, //  ###  
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  '-'
+ */
+static const uint8_t Font12_176[] = {
+	6, 12,
+	1, 12,
+	0x30, //   ##  
+	0x48, //  #  # 
+	0x30, //   ##  
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'AA'
+ */
+static const uint8_t Font12_177[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x20, //   #   
+	0x20, //   #   
+	0xF8, // ##### 
+	0x20, //   #   
+	0x20, //   #   
+	0xF8, // ##### 
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'II'
+ */
+static const uint8_t Font12_178[] = {
+	6, 12,
+	1, 12,
+	0x40, //  #    
+	0xA0, // # #   
+	0x20, //   #   
+	0x40, //  #    
+	0xE0, // ###   
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'UU'
+ */
+static const uint8_t Font12_179[] = {
+	6, 12,
+	1, 12,
+	0xC0, // ##    
+	0x20, //   #   
+	0xC0, // ##    
+	0x20, //   #   
+	0xC0, // ##    
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'EE'
+ */
+static const uint8_t Font12_180[] = {
+	6, 12,
+	1, 12,
+	0x30, //   ##  
+	0x40, //  #    
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'OO'
+ */
+static const uint8_t Font12_181[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x48, //  #  # 
+	0x48, //  #  # 
+	0x48, //  #  # 
+	0x48, //  #  # 
+	0x74, //  ### #
+	0x40, //  #    
+	0x40, //  #    
+	0x80  // #     
+};
+
+/*
+ *  'KA'
+ */
+static const uint8_t Font12_182[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x38, //   ### 
+	0x68, //  ## # 
+	0x68, //  ## # 
+	0x28, //   # # 
+	0x28, //   # # 
+	0x28, //   # # 
+	0x28, //   # # 
+	0x28, //   # # 
+	0x28, //   # # 
+	0x28, //   # # 
+	0x00  //       
+};
+
+/*
+ *  'KI'
+ */
+static const uint8_t Font12_183[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x30, //   ##  
+	0x30, //   ##  
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'KU'
+ */
+static const uint8_t Font12_184[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x40, //  #    
+	0x60, //  ##   
+	0x10, //    #  
+	0x60  //  ##   
+};
+
+/*
+ *  'KE'
+ */
+static const uint8_t Font12_185[] = {
+	6, 12,
+	1, 12,
+	0x40, //  #    
+	0xC0, // ##    
+	0x40, //  #    
+	0x40, //  #    
+	0x40, //  #    
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'KO'
+ */
+static const uint8_t Font12_186[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x60, //  ##   
+	0x90, // #  #  
+	0x90, // #  #  
+	0x60, //  ##   
+	0x00, //       
+	0xF0, // ####  
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'SA'
+ */
+static const uint8_t Font12_187[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0xA0, // # #   
+	0x50, //  # #  
+	0x28, //   # # 
+	0x50, //  # #  
+	0xA0, // # #   
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'SI'
+ */
+static const uint8_t Font12_188[] = {
+	6, 12,
+	1, 12,
+	0x80, // #     
+	0x90, // #  #  
+	0xA0, // # #   
+	0x50, //  # #  
+	0xB0, // # ##  
+	0x38, //   ### 
+	0x10, //    #  
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'SU'
+ */
+static const uint8_t Font12_189[] = {
+	6, 12,
+	1, 12,
+	0x80, // #     
+	0x90, // #  #  
+	0xA0, // # #   
+	0x58, //  # ## 
+	0x88, // #   # 
+	0x10, //    #  
+	0x38, //   ### 
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'SE'
+ */
+static const uint8_t Font12_190[] = {
+	6, 12,
+	1, 12,
+	0xC0, // ##    
+	0x20, //   #   
+	0xE0, // ###   
+	0x28, //   # # 
+	0xD8, // ## ## 
+	0x28, //   # # 
+	0x3C, //   ####
+	0x08, //     # 
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'SO'
+ */
+static const uint8_t Font12_191[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x20, //   #   
+	0x00, //       
+	0x20, //   #   
+	0x20, //   #   
+	0x40, //  #    
+	0x40, //  #    
+	0x88, // #   # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'TA'
+ */
+static const uint8_t Font12_192[] = {
+	6, 12,
+	1, 12,
+	0x20, //   #   
+	0x10, //    #  
+	0x20, //   #   
+	0x20, //   #   
+	0x50, //  # #  
+	0x50, //  # #  
+	0x88, // #   # 
+	0xF8, // ##### 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'TI'
+ */
+static const uint8_t Font12_193[] = {
+	6, 12,
+	1, 12,
+	0x20, //   #   
+	0x40, //  #    
+	0x20, //   #   
+	0x20, //   #   
+	0x50, //  # #  
+	0x50, //  # #  
+	0x88, // #   # 
+	0xF8, // ##### 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'TU'
+ */
+static const uint8_t Font12_194[] = {
+	6, 12,
+	1, 12,
+	0x20, //   #   
+	0x50, //  # #  
+	0x20, //   #   
+	0x20, //   #   
+	0x50, //  # #  
+	0x50, //  # #  
+	0x88, // #   # 
+	0xF8, // ##### 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'TE'
+ */
+static const uint8_t Font12_195[] = {
+	6, 12,
+	1, 12,
+	0x50, //  # #  
+	0xA0, // # #   
+	0x20, //   #   
+	0x20, //   #   
+	0x50, //  # #  
+	0x50, //  # #  
+	0x88, // #   # 
+	0xF8, // ##### 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'TO'
+ */
+static const uint8_t Font12_196[] = {
+	6, 12,
+	1, 12,
+	0x50, //  # #  
+	0x00, //       
+	0x20, //   #   
+	0x20, //   #   
+	0x50, //  # #  
+	0x50, //  # #  
+	0x88, // #   # 
+	0xF8, // ##### 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'NA'
+ */
+static const uint8_t Font12_197[] = {
+	6, 12,
+	1, 12,
+	0x20, //   #   
+	0x50, //  # #  
+	0x20, //   #   
+	0x20, //   #   
+	0x50, //  # #  
+	0x50, //  # #  
+	0x88, // #   # 
+	0xF8, // ##### 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'NI'
+ */
+static const uint8_t Font12_198[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x78, //  #### 
+	0x60, //  ##   
+	0xA0, // # #   
+	0xA0, // # #   
+	0xF8, // ##### 
+	0xA0, // # #   
+	0xA0, // # #   
+	0xA0, // # #   
+	0xB8, // # ### 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'NU'
+ */
+static const uint8_t Font12_199[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x30, //   ##  
+	0x48, //  #  # 
+	0x80, // #     
+	0x80, // #     
+	0x80, // #     
+	0x80, // #     
+	0x48, //  #  # 
+	0x30, //   ##  
+	0x10, //    #  
+	0x60, //  ##   
+	0x00  //       
+};
+
+/*
+ *  'NE'
+ */
+static const uint8_t Font12_200[] = {
+	6, 12,
+	1, 12,
+	0x40, //  #    
+	0x20, //   #   
+	0xF8, // ##### 
+	0x80, // #     
+	0x80, // #     
+	0xF0, // ####  
+	0x80, // #     
+	0x80, // #     
+	0x80, // #     
+	0xF8, // ##### 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'NO'
+ */
+static const uint8_t Font12_201[] = {
+	6, 12,
+	1, 12,
+	0x10, //    #  
+	0x20, //   #   
+	0xF8, // ##### 
+	0x80, // #     
+	0x80, // #     
+	0xF0, // ####  
+	0x80, // #     
+	0x80, // #     
+	0x80, // #     
+	0xF8, // ##### 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'HA'
+ */
+static const uint8_t Font12_202[] = {
+	6, 12,
+	1, 12,
+	0x20, //   #   
+	0x50, //  # #  
+	0xF8, // ##### 
+	0x80, // #     
+	0x80, // #     
+	0xF0, // ####  
+	0x80, // #     
+	0x80, // #     
+	0x80, // #     
+	0xF8, // ##### 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'HI'
+ */
+static const uint8_t Font12_203[] = {
+	6, 12,
+	1, 12,
+	0x50, //  # #  
+	0x00, //       
+	0xF8, // ##### 
+	0x80, // #     
+	0x80, // #     
+	0xF0, // ####  
+	0x80, // #     
+	0x80, // #     
+	0x80, // #     
+	0xF8, // ##### 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'HU'
+ */
+static const uint8_t Font12_204[] = {
+	6, 12,
+	1, 12,
+	0x40, //  #    
+	0x20, //   #   
+	0x70, //  ###  
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'HE'
+ */
+static const uint8_t Font12_205[] = {
+	6, 12,
+	1, 12,
+	0x10, //    #  
+	0x20, //   #   
+	0x70, //  ###  
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'HO'
+ */
+static const uint8_t Font12_206[] = {
+	6, 12,
+	1, 12,
+	0x20, //   #   
+	0x50, //  # #  
+	0x00, //       
+	0x70, //  ###  
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'MA'
+ */
+static const uint8_t Font12_207[] = {
+	6, 12,
+	1, 12,
+	0x50, //  # #  
+	0x00, //       
+	0x70, //  ###  
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'MI'
+ */
+static const uint8_t Font12_208[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0xE0, // ###   
+	0x90, // #  #  
+	0x88, // #   # 
+	0x88, // #   # 
+	0xC8, // ##  # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x90, // #  #  
+	0xE0, // ###   
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'MU'
+ */
+static const uint8_t Font12_209[] = {
+	6, 12,
+	1, 12,
+	0x50, //  # #  
+	0xA0, // # #   
+	0x88, // #   # 
+	0xC8, // ##  # 
+	0xA8, // # # # 
+	0xA8, // # # # 
+	0x98, // #  ## 
+	0x98, // #  ## 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'ME'
+ */
+static const uint8_t Font12_210[] = {
+	6, 12,
+	1, 12,
+	0x40, //  #    
+	0x20, //   #   
+	0x70, //  ###  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'MO'
+ */
+static const uint8_t Font12_211[] = {
+	6, 12,
+	1, 12,
+	0x10, //    #  
+	0x20, //   #   
+	0x70, //  ###  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'YA'
+ */
+static const uint8_t Font12_212[] = {
+	6, 12,
+	1, 12,
+	0x20, //   #   
+	0x50, //  # #  
+	0x70, //  ###  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'YU'
+ */
+static const uint8_t Font12_213[] = {
+	6, 12,
+	1, 12,
+	0x28, //   # # 
+	0x50, //  # #  
+	0x70, //  ###  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'YO'
+ */
+static const uint8_t Font12_214[] = {
+	6, 12,
+	1, 12,
+	0x50, //  # #  
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'RA'
+ */
+static const uint8_t Font12_215[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x88, // #   # 
+	0x50, //  # #  
+	0x20, //   #   
+	0x50, //  # #  
+	0x88, // #   # 
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'RI'
+ */
+static const uint8_t Font12_216[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x34, //   ## #
+	0x4C, //  #  ##
+	0x48, //  #  # 
+	0x58, //  # ## 
+	0x68, //  ## # 
+	0x68, //  ## # 
+	0x48, //  #  # 
+	0xC8, // ##  # 
+	0xB0, // # ##  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'RU'
+ */
+static const uint8_t Font12_217[] = {
+	6, 12,
+	1, 12,
+	0x40, //  #    
+	0x20, //   #   
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'RE'
+ */
+static const uint8_t Font12_218[] = {
+	6, 12,
+	1, 12,
+	0x10, //    #  
+	0x20, //   #   
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'RO'
+ */
+static const uint8_t Font12_219[] = {
+	6, 12,
+	1, 12,
+	0x20, //   #   
+	0x50, //  # #  
+	0x00, //       
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'WA'
+ */
+static const uint8_t Font12_220[] = {
+	6, 12,
+	1, 12,
+	0x50, //  # #  
+	0xA0, // # #   
+	0x00, //       
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  'NN'
+ */
+static const uint8_t Font12_221[] = {
+	6, 12,
+	1, 12,
+	0x10, //    #  
+	0x20, //   #   
+	0x88, // #   # 
+	0x88, // #   # 
+	0x50, //  # #  
+	0x50, //  # #  
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  dakuten
+ */
+static const uint8_t Font12_222[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x40, //  #    
+	0x40, //  #    
+	0x70, //  ###  
+	0x48, //  #  # 
+	0x48, //  #  # 
+	0x48, //  #  # 
+	0x48, //  #  # 
+	0x70, //  ###  
+	0x40, //  #    
+	0x40, //  #    
+	0x00  //       
+};
+
+/*
+ *  maru
+ */
+static const uint8_t Font12_223[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x30, //   ##  
+	0x48, //  #  # 
+	0x48, //  #  # 
+	0x48, //  #  # 
+	0x70, //  ###  
+	0x48, //  #  # 
+	0x48, //  #  # 
+	0x48, //  #  # 
+	0x50, //  # #  
+	0x40, //  #    
+	0x40  //  #    
+};
+
+/*
+ *  224
+ */
+static const uint8_t Font12_224[] = {
+	6, 12,
+	1, 12,
+	0x40, //  #    
+	0x20, //   #   
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x18, //    ## 
+	0x68, //  ## # 
+	0x88, // #   # 
+	0x98, // #  ## 
+	0x68, //  ## # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  225
+ */
+static const uint8_t Font12_225[] = {
+	6, 12,
+	1, 12,
+	0x10, //    #  
+	0x20, //   #   
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x18, //    ## 
+	0x68, //  ## # 
+	0x88, // #   # 
+	0x98, // #  ## 
+	0x68, //  ## # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  226
+ */
+static const uint8_t Font12_226[] = {
+	6, 12,
+	1, 12,
+	0x20, //   #   
+	0x50, //  # #  
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x18, //    ## 
+	0x68, //  ## # 
+	0x88, // #   # 
+	0x98, // #  ## 
+	0x68, //  ## # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  227
+ */
+static const uint8_t Font12_227[] = {
+	6, 12,
+	1, 12,
+	0x50, //  # #  
+	0xA0, // # #   
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x18, //    ## 
+	0x68, //  ## # 
+	0x88, // #   # 
+	0x98, // #  ## 
+	0x68, //  ## # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  228
+ */
+static const uint8_t Font12_228[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x50, //  # #  
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x18, //    ## 
+	0x68, //  ## # 
+	0x88, // #   # 
+	0x98, // #  ## 
+	0x68, //  ## # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  229
+ */
+static const uint8_t Font12_229[] = {
+	6, 12,
+	1, 12,
+	0x20, //   #   
+	0x50, //  # #  
+	0x20, //   #   
+	0x70, //  ###  
+	0x88, // #   # 
+	0x18, //    ## 
+	0x68, //  ## # 
+	0x88, // #   # 
+	0x98, // #  ## 
+	0x68, //  ## # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  230
+ */
+static const uint8_t Font12_230[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x50, //  # #  
+	0xA8, // # # # 
+	0x28, //   # # 
+	0x78, //  #### 
+	0xA0, // # #   
+	0xA8, // # # # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  231
+ */
+static const uint8_t Font12_231[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x80, // #     
+	0x80, // #     
+	0x88, // #   # 
+	0x70, //  ###  
+	0x10, //    #  
+	0x60, //  ##   
+	0x00  //       
+};
+
+/*
+ *  232
+ */
+static const uint8_t Font12_232[] = {
+	6, 12,
+	1, 12,
+	0x40, //  #    
+	0x20, //   #   
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x88, // #   # 
+	0xF8, // ##### 
+	0x80, // #     
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  233
+ */
+static const uint8_t Font12_233[] = {
+	6, 12,
+	1, 12,
+	0x10, //    #  
+	0x20, //   #   
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x88, // #   # 
+	0xF8, // ##### 
+	0x80, // #     
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  234
+ */
+static const uint8_t Font12_234[] = {
+	6, 12,
+	1, 12,
+	0x20, //   #   
+	0x50, //  # #  
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x88, // #   # 
+	0xF8, // ##### 
+	0x80, // #     
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  235
+ */
+static const uint8_t Font12_235[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x50, //  # #  
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x88, // #   # 
+	0xF8, // ##### 
+	0x80, // #     
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  236
+ */
+static const uint8_t Font12_236[] = {
+	6, 12,
+	1, 12,
+	0x40, //  #    
+	0x20, //   #   
+	0x00, //       
+	0x00, //       
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  237
+ */
+static const uint8_t Font12_237[] = {
+	6, 12,
+	1, 12,
+	0x10, //    #  
+	0x20, //   #   
+	0x00, //       
+	0x00, //       
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  238
+ */
+static const uint8_t Font12_238[] = {
+	6, 12,
+	1, 12,
+	0x20, //   #   
+	0x50, //  # #  
+	0x00, //       
+	0x00, //       
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  239
+ */
+static const uint8_t Font12_239[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x50, //  # #  
+	0x00, //       
+	0x00, //       
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  240
+ */
+static const uint8_t Font12_240[] = {
+	6, 12,
+	1, 12,
+	0xA0, // # #   
+	0x40, //  #    
+	0xA0, // # #   
+	0x10, //    #  
+	0x70, //  ###  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  241
+ */
+static const uint8_t Font12_241[] = {
+	6, 12,
+	1, 12,
+	0x50, //  # #  
+	0xA0, // # #   
+	0x00, //       
+	0x00, //       
+	0xB0, // # ##  
+	0xC8, // ##  # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  242
+ */
+static const uint8_t Font12_242[] = {
+	6, 12,
+	1, 12,
+	0x40, //  #    
+	0x20, //   #   
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  243
+ */
+static const uint8_t Font12_243[] = {
+	6, 12,
+	1, 12,
+	0x10, //    #  
+	0x20, //   #   
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  244
+ */
+static const uint8_t Font12_244[] = {
+	6, 12,
+	1, 12,
+	0x20, //   #   
+	0x50, //  # #  
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  245
+ */
+static const uint8_t Font12_245[] = {
+	6, 12,
+	1, 12,
+	0x50, //  # #  
+	0xA0, // # #   
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  246
+ */
+static const uint8_t Font12_246[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x50, //  # #  
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  247
+ */
+static const uint8_t Font12_247[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x20, //   #   
+	0x00, //       
+	0xF8, // ##### 
+	0x00, //       
+	0x20, //   #   
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  248
+ */
+static const uint8_t Font12_248[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x34, //   ## #
+	0x48, //  #  # 
+	0x58, //  # ## 
+	0x68, //  ## # 
+	0x48, //  #  # 
+	0xC8, // ##  # 
+	0x30, //   ##  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  249
+ */
+static const uint8_t Font12_249[] = {
+	6, 12,
+	1, 12,
+	0x40, //  #    
+	0x20, //   #   
+	0x00, //       
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x98, // #  ## 
+	0x68, //  ## # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  250
+ */
+static const uint8_t Font12_250[] = {
+	6, 12,
+	1, 12,
+	0x10, //    #  
+	0x20, //   #   
+	0x00, //       
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x98, // #  ## 
+	0x68, //  ## # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  251
+ */
+static const uint8_t Font12_251[] = {
+	6, 12,
+	1, 12,
+	0x20, //   #   
+	0x50, //  # #  
+	0x00, //       
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x98, // #  ## 
+	0x68, //  ## # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  252
+ */
+static const uint8_t Font12_252[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x50, //  # #  
+	0x00, //       
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x98, // #  ## 
+	0x68, //  ## # 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  253
+ */
+static const uint8_t Font12_253[] = {
+	6, 12,
+	1, 12,
+	0x10, //    #  
+	0x20, //   #   
+	0x00, //       
+	0x88, // #   # 
+	0x88, // #   # 
+	0x48, //  #  # 
+	0x50, //  # #  
+	0x50, //  # #  
+	0x20, //   #   
+	0x20, //   #   
+	0x40, //  #    
+	0x80  // #     
+};
+
+/*
+ *  254
+ */
+static const uint8_t Font12_254[] = {
+	6, 12,
+	1, 12,
+	/* 253 */
+	0x00, //       
+	0x00, //       
+	0x40, //  #    
+	0x40, //  #    
+	0x70, //  ###  
+	0x48, //  #  # 
+	0x48, //  #  # 
+	0x48, //  #  # 
+	0x48, //  #  # 
+	0x70, //  ###  
+	0x40, //  #    
+	0x40  //  #    
+};
+
+/*
+ *  255
+ */
+static const uint8_t Font12_255[] = {
+	6, 12,
+	1, 12,
+	0x00, //       
+	0x50, //  # #  
+	0x00, //       
+	0x88, // #   # 
+	0x88, // #   # 
+	0x48, //  #  # 
+	0x50, //  # #  
+	0x50, //  # #  
+	0x20, //   #   
+	0x20, //   #   
+	0x40, //  #    
+	0x80  // #     
+};
+
+
+const font_t *Font12[] = {
+	(font_t *)Font12_32,  (font_t *)Font12_01,  (font_t *)Font12_02,  (font_t *)Font12_03,
+	(font_t *)Font12_04,  (font_t *)Font12_05,  (font_t *)Font12_06,  (font_t *)Font12_07,
+	(font_t *)Font12_08,  (font_t *)Font12_09,  (font_t *)Font12_10,  (font_t *)Font12_11,
+	(font_t *)Font12_12,  (font_t *)Font12_13,  (font_t *)Font12_14,  (font_t *)Font12_15,
+	(font_t *)Font12_16,  (font_t *)Font12_17,  (font_t *)Font12_18,  (font_t *)Font12_19,
+	(font_t *)Font12_20,  (font_t *)Font12_21,  (font_t *)Font12_22,  (font_t *)Font12_23,
+	(font_t *)Font12_24,  (font_t *)Font12_25,  (font_t *)Font12_26,  (font_t *)Font12_27,
+	(font_t *)Font12_28,  (font_t *)Font12_29,  (font_t *)Font12_30,  (font_t *)Font12_31,
+	(font_t *)Font12_32,  (font_t *)Font12_33,  (font_t *)Font12_34,  (font_t *)Font12_35,
+	(font_t *)Font12_36,  (font_t *)Font12_37,  (font_t *)Font12_38,  (font_t *)Font12_39,
+	(font_t *)Font12_40,  (font_t *)Font12_41,  (font_t *)Font12_42,  (font_t *)Font12_43,
+	(font_t *)Font12_44,  (font_t *)Font12_45,  (font_t *)Font12_46,  (font_t *)Font12_47,
+	(font_t *)Font12_48,  (font_t *)Font12_49,  (font_t *)Font12_50,  (font_t *)Font12_51,
+	(font_t *)Font12_52,  (font_t *)Font12_53,  (font_t *)Font12_54,  (font_t *)Font12_55,
+	(font_t *)Font12_56,  (font_t *)Font12_57,  (font_t *)Font12_58,  (font_t *)Font12_59,
+	(font_t *)Font12_60,  (font_t *)Font12_61,  (font_t *)Font12_62,  (font_t *)Font12_63,
+	(font_t *)Font12_64,  (font_t *)Font12_65,  (font_t *)Font12_66,  (font_t *)Font12_67,
+	(font_t *)Font12_68,  (font_t *)Font12_69,  (font_t *)Font12_70,  (font_t *)Font12_71,
+	(font_t *)Font12_72,  (font_t *)Font12_73,  (font_t *)Font12_74,  (font_t *)Font12_75,
+	(font_t *)Font12_76,  (font_t *)Font12_77,  (font_t *)Font12_78,  (font_t *)Font12_79,
+	(font_t *)Font12_80,  (font_t *)Font12_81,  (font_t *)Font12_82,  (font_t *)Font12_83,
+	(font_t *)Font12_84,  (font_t *)Font12_85,  (font_t *)Font12_86,  (font_t *)Font12_87,
+	(font_t *)Font12_88,  (font_t *)Font12_89,  (font_t *)Font12_90,  (font_t *)Font12_91,
+	(font_t *)Font12_92,  (font_t *)Font12_93,  (font_t *)Font12_94,  (font_t *)Font12_95,
+	(font_t *)Font12_96,  (font_t *)Font12_97,  (font_t *)Font12_98,  (font_t *)Font12_99,
+	(font_t *)Font12_100, (font_t *)Font12_101, (font_t *)Font12_102, (font_t *)Font12_103,
+	(font_t *)Font12_104, (font_t *)Font12_105, (font_t *)Font12_106, (font_t *)Font12_107,
+	(font_t *)Font12_108, (font_t *)Font12_109, (font_t *)Font12_110, (font_t *)Font12_111,
+	(font_t *)Font12_112, (font_t *)Font12_113, (font_t *)Font12_114, (font_t *)Font12_115,
+	(font_t *)Font12_116, (font_t *)Font12_117, (font_t *)Font12_118, (font_t *)Font12_119,
+	(font_t *)Font12_120, (font_t *)Font12_121, (font_t *)Font12_122, (font_t *)Font12_123,
+	(font_t *)Font12_124, (font_t *)Font12_125, (font_t *)Font12_126, (font_t *)Font12_127,
+
+	0,                    0,                    0,                    0,
+	0,                    0,                    0,                    0,
+	0,                    0,                    0,                    0,
+	0,                    0,                    0,                    0,
+	0,                    0,                    0,                    0,
+	0,                    0,                    0,                    0,
+	0,                    0,                    0,                    0,
+	0,                    0,                    0,                    0,
+	(font_t *)Font12_160, (font_t *)Font12_161, (font_t *)Font12_162, (font_t *)Font12_163,
+	(font_t *)Font12_164, (font_t *)Font12_165, (font_t *)Font12_166, (font_t *)Font12_167,
+	(font_t *)Font12_168, (font_t *)Font12_169, (font_t *)Font12_170, (font_t *)Font12_171,
+	(font_t *)Font12_172, (font_t *)Font12_173, (font_t *)Font12_174, (font_t *)Font12_175,
+	(font_t *)Font12_176, (font_t *)Font12_177, (font_t *)Font12_178, (font_t *)Font12_179,
+	(font_t *)Font12_180, (font_t *)Font12_181, (font_t *)Font12_182, (font_t *)Font12_183,
+	(font_t *)Font12_184, (font_t *)Font12_185, (font_t *)Font12_186, (font_t *)Font12_187,
+	(font_t *)Font12_188, (font_t *)Font12_189, (font_t *)Font12_190, (font_t *)Font12_191,
+	(font_t *)Font12_192, (font_t *)Font12_193, (font_t *)Font12_194, (font_t *)Font12_195,
+	(font_t *)Font12_196, (font_t *)Font12_197, (font_t *)Font12_198, (font_t *)Font12_199,
+	(font_t *)Font12_200, (font_t *)Font12_201, (font_t *)Font12_202, (font_t *)Font12_203,
+	(font_t *)Font12_204, (font_t *)Font12_205, (font_t *)Font12_206, (font_t *)Font12_207,
+	(font_t *)Font12_208, (font_t *)Font12_209, (font_t *)Font12_210, (font_t *)Font12_211,
+	(font_t *)Font12_212, (font_t *)Font12_213, (font_t *)Font12_214, (font_t *)Font12_215,
+	(font_t *)Font12_216, (font_t *)Font12_217, (font_t *)Font12_218, (font_t *)Font12_219,
+	(font_t *)Font12_220, (font_t *)Font12_221, (font_t *)Font12_222, (font_t *)Font12_223,
+	(font_t *)Font12_224, (font_t *)Font12_225, (font_t *)Font12_226, (font_t *)Font12_227,
+	(font_t *)Font12_228, (font_t *)Font12_229, (font_t *)Font12_230, (font_t *)Font12_231,
+	(font_t *)Font12_232, (font_t *)Font12_233, (font_t *)Font12_234, (font_t *)Font12_235,
+	(font_t *)Font12_236, (font_t *)Font12_237, (font_t *)Font12_238, (font_t *)Font12_239,
+	(font_t *)Font12_240, (font_t *)Font12_241, (font_t *)Font12_242, (font_t *)Font12_243,
+	(font_t *)Font12_244, (font_t *)Font12_245, (font_t *)Font12_246, (font_t *)Font12_247,
+	(font_t *)Font12_248, (font_t *)Font12_249, (font_t *)Font12_250, (font_t *)Font12_251,
+	(font_t *)Font12_252, (font_t *)Font12_253, (font_t *)Font12_254, (font_t *)Font12_255
+};
+
+font_head_t Shinonome_Font12 = {
+	"shinonome_font12",
+	0x80,
+	0x00,
+	12,
+	12,
+	Font12,
+	NULL
+};
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/ui/snfont_disp/font16.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/ui/snfont_disp/font16.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/ui/snfont_disp/font16.c	(revision 453)
@@ -0,0 +1,5460 @@
+/*
+ *  TOPPERS ECHONET Lite Communication Middleware
+ * 
+ *  Copyright (C) 2018-2019 Cores Co., Ltd. Japan
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ * 東雲フォント
+ * http://openlab.ring.gr.jp/efont/shinonome/
+ * Licence
+ * Public Domain
+ */
+
+
+#include "fonts.h"
+
+/*
+ *  001
+ */
+static const uint8_t Font16_01[] = {
+	8, 16,
+	1, 16,
+	0x10, //    #    
+	0x10, //    #    
+	0x38, //   ###   
+	0x38, //   ###   
+	0x7C, //  #####  
+	0x7C, //  #####  
+	0xFE, // ####### 
+	0xFE, // ####### 
+	0x7C, //  #####  
+	0x7C, //  #####  
+	0x38, //   ###   
+	0x38, //   ###   
+	0x10, //    #    
+	0x10, //    #    
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  002
+ */
+static const uint8_t Font16_02[] = {
+	8, 16,
+	1, 16,
+	0x55, //  # # # #
+	0xAA, // # # # # 
+	0x55, //  # # # #
+	0xAA, // # # # # 
+	0x55, //  # # # #
+	0xAA, // # # # # 
+	0x55, //  # # # #
+	0xAA, // # # # # 
+	0x55, //  # # # #
+	0xAA, // # # # # 
+	0x55, //  # # # #
+	0xAA, // # # # # 
+	0x55, //  # # # #
+	0xAA, // # # # # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  003
+ */
+static const uint8_t Font16_03[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x88, // #   #   
+	0x88, // #   #   
+	0x88, // #   #   
+	0xF8, // #####   
+	0x88, // #   #   
+	0x88, // #   #   
+	0x88, // #   #   
+	0x00, //         
+	0x3E, //   ##### 
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x08  //     #   
+};
+
+/*
+ *  004
+ */
+static const uint8_t Font16_04[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0xF8, // #####   
+	0x80, // #       
+	0x80, // #       
+	0xF0, // ####    
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x3E, //   ##### 
+	0x20, //   #     
+	0x20, //   #     
+	0x3C, //   ####  
+	0x20, //   #     
+	0x20, //   #     
+	0x20, //   #     
+	0x00  //         
+};
+
+/*
+ *  005
+ */
+static const uint8_t Font16_05[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x70, //  ###    
+	0x88, // #   #   
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x88, // #   #   
+	0x70, //  ###    
+	0x00, //         
+	0x3C, //   ####  
+	0x22, //   #   # 
+	0x22, //   #   # 
+	0x3C, //   ####  
+	0x28, //   # #   
+	0x24, //   #  #  
+	0x22  //   #   # 
+};
+
+/*
+ *  006
+ */
+static const uint8_t Font16_06[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0xF8, // #####   
+	0x00, //         
+	0x3E, //   ##### 
+	0x20, //   #     
+	0x20, //   #     
+	0x3C, //   ####  
+	0x20, //   #     
+	0x20, //   #     
+	0x20  //   #     
+};
+
+/*
+ *  007
+ */
+static const uint8_t Font16_07[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  008
+ */
+static const uint8_t Font16_08[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0xFE, // ####### 
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x00, //         
+	0xFE, // ####### 
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  009
+ */
+static const uint8_t Font16_09[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x84, // #    #  
+	0xC4, // ##   #  
+	0xA4, // # #  #  
+	0xA4, // # #  #  
+	0x94, // #  # #  
+	0x94, // #  # #  
+	0x8C, // #   ##  
+	0x84, // #    #  
+	0x20, //   #     
+	0x20, //   #     
+	0x20, //   #     
+	0x20, //   #     
+	0x20, //   #     
+	0x20, //   #     
+	0x3E  //   ##### 
+};
+
+/*
+ *  010
+ */
+static const uint8_t Font16_10[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x88, // #   #   
+	0x88, // #   #   
+	0x88, // #   #   
+	0x50, //  # #    
+	0x50, //  # #    
+	0x20, //   #     
+	0x00, //         
+	0x3E, //   ##### 
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x00  //         
+};
+
+/*
+ *  011
+ */
+static const uint8_t Font16_11[] = {
+	8, 16,
+	1, 16,
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0xF0, // ####    
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  012
+ */
+static const uint8_t Font16_12[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0xF0, // ####    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10  //    #    
+};
+
+/*
+ *  013
+ */
+static const uint8_t Font16_13[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x1F, //    #####
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10  //    #    
+};
+
+/*
+ *  014
+ */
+static const uint8_t Font16_14[] = {
+	8, 16,
+	1, 16,
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x1F, //    #####
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  015
+ */
+static const uint8_t Font16_15[] = {
+	8, 16,
+	1, 16,
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0xFF, // ########
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10  //    #    
+};
+
+/*
+ *  016
+ */
+static const uint8_t Font16_16[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0xFF, // ########
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  017
+ */
+static const uint8_t Font16_17[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0xFF, // ########
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //       
+};
+
+/*
+ *  018
+ */
+static const uint8_t Font16_18[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0xFF, // ########
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //       
+};
+
+/*
+ *  019
+ */
+static const uint8_t Font16_19[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0xFF, // ########
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //       
+};
+
+/*
+ *  020
+ */
+static const uint8_t Font16_20[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0xFF, // ########
+	0x00  //         
+};
+
+/*
+ *  021
+ */
+static const uint8_t Font16_21[] = {
+	8, 16,
+	1, 16,
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x1F, //    #####
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10  //    #    
+};
+
+/*
+ *  022
+ */
+static const uint8_t Font16_22[] = {
+	8, 16,
+	1, 16,
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0xF0, // ####    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10  //    #    
+};
+
+/*
+ *  023
+ */
+static const uint8_t Font16_23[] = {
+	8, 16,
+	1, 16,
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0xFF, // ########
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  024
+ */
+static const uint8_t Font16_24[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0xFF, // ########
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10  //    #    
+};
+
+/*
+ *  025
+ */
+static const uint8_t Font16_25[] = {
+	8, 16,
+	1, 16,
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10  //    #    
+};
+
+/*
+ *  026
+ */
+static const uint8_t Font16_26[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x02, //       # 
+	0x0C, //     ##  
+	0x30, //   ##    
+	0xC0, // ##      
+	0x30, //   ##    
+	0x0C, //     ##  
+	0x02, //       # 
+	0x00, //         
+	0xFE, // ####### 
+	0x00, //         
+	0xFE, // ####### 
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  027
+ */
+static const uint8_t Font16_27[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x80, // #       
+	0x60, //  ##     
+	0x18, //    ##   
+	0x06, //      ## 
+	0x18, //    ##   
+	0x60, //  ##     
+	0x80, // #       
+	0xFE, // ####### 
+	0x00, //         
+	0xFE, // ####### 
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  028
+ */
+static const uint8_t Font16_28[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0xFE, // ####### 
+	0x24, //   #  #  
+	0x24, //   #  #  
+	0x24, //   #  #  
+	0x24, //   #  #  
+	0x44, //  #   #  
+	0x84, // #    #  
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  029
+ */
+static const uint8_t Font16_29[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x02, //       # 
+	0x04, //      #  
+	0x08, //     #   
+	0xFE, // ####### 
+	0x10, //    #    
+	0xFE, // ####### 
+	0x20, //   #     
+	0x40, //  #      
+	0x80, // #       
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  030
+ */
+static const uint8_t Font16_30[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x0C, //     ##  
+	0x12, //    #  # 
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x7C, //  #####  
+	0x10, //    #    
+	0x10, //    #    
+	0x3C, //   ####  
+	0x52, //  # #  # 
+	0x20, //   #     
+	0x00  //         
+};
+
+/*
+ *  031
+ */
+static const uint8_t Font16_31[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x10, //    #    
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  SPACE
+ */
+static const uint8_t Font16_32[] = {
+	8, 16,
+	0, 0
+};
+
+/*
+ *  !
+ */
+static const uint8_t Font16_33[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x18, //    ##   
+	0x18, //    ##   
+	0x18, //    ##   
+	0x18, //    ##   
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x00, //         
+	0x00, //         
+	0x10, //    #    
+	0x10, //    #    
+	0x00  //         
+};
+
+/*
+ *  '!'
+ */
+static const uint8_t Font16_34[] = {
+	8, 16,
+	1, 16,
+	0x6C, //  ## ##  
+	0x24, //   #  #  
+	0x24, //   #  #  
+	0x48, //  #  #   
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  '#'
+ */
+static const uint8_t Font16_35[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x12, //    #  # 
+	0x12, //    #  # 
+	0x12, //    #  # 
+	0x7F, //  #######
+	0x24, //   #  #  
+	0x24, //   #  #  
+	0x24, //   #  #  
+	0x24, //   #  #  
+	0x24, //   #  #  
+	0xFE, // ####### 
+	0x48, //  #  #   
+	0x48, //  #  #   
+	0x48, //  #  #   
+	0x48, //  #  #   
+	0x00  //         
+};
+
+/*
+ *  '$'
+ */
+static const uint8_t Font16_36[] = {
+	8, 16,
+	1, 16,
+	0x10, //    #    
+	0x38, //   ###   
+	0x54, //  # # #  
+	0x92, // #  #  # 
+	0x92, // #  #  # 
+	0x90, // #  #    
+	0x50, //  # #    
+	0x38, //   ###   
+	0x14, //    # #  
+	0x12, //    #  # 
+	0x92, // #  #  # 
+	0x92, // #  #  # 
+	0x54, //  # # #  
+	0x38, //   ###   
+	0x10, //    #    
+	0x10  //    #    
+};
+
+/*
+ *  '%'
+ */
+static const uint8_t Font16_37[] = {
+	8, 16,
+	1, 16,
+	0x01, //        #
+	0x61, //  ##    #
+	0x92, // #  #  # 
+	0x92, // #  #  # 
+	0x94, // #  # #  
+	0x94, // #  # #  
+	0x68, //  ## #   
+	0x08, //     #   
+	0x10, //    #    
+	0x16, //    # ## 
+	0x29, //   # #  #
+	0x29, //   # #  #
+	0x49, //  #  #  #
+	0x49, //  #  #  #
+	0x86, // #    ## 
+	0x80  // #       
+};
+
+/*
+ *  '&'
+ */
+static const uint8_t Font16_38[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x28, //   # #   
+	0x10, //    #    
+	0x30, //   ##    
+	0x4A, //  #  # # 
+	0x8A, // #   # # 
+	0x84, // #    #  
+	0x84, // #    #  
+	0x4A, //  #  # # 
+	0x31, //   ##   #
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  '''
+ */
+static const uint8_t Font16_39[] = {
+	8, 16,
+	1, 16,
+	0x60, //  ##     
+	0x20, //   #     
+	0x20, //   #     
+	0x40, //  #      
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  '('
+ */
+static const uint8_t Font16_40[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x02, //       # 
+	0x04, //      #  
+	0x08, //     #   
+	0x08, //     #   
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x08, //     #   
+	0x08, //     #   
+	0x04, //      #  
+	0x02  //       # 
+};
+
+/*
+ *  ')'
+ */
+static const uint8_t Font16_41[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x40, //  #      
+	0x20, //   #     
+	0x10, //    #    
+	0x10, //    #    
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x10, //    #    
+	0x10, //    #    
+	0x20, //   #     
+	0x40  //  #      
+};
+
+/*
+ *  '*'
+ */
+static const uint8_t Font16_42[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x10, //    #    
+	0x92, // #  #  # 
+	0x54, //  # # #  
+	0x38, //   ###   
+	0x54, //  # # #  
+	0x92, // #  #  # 
+	0x10, //    #    
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  '+'
+ */
+static const uint8_t Font16_43[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0xFE, // ####### 
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  ','
+ */
+static const uint8_t Font16_44[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x60, //  ##     
+	0x20, //   #     
+	0x20, //   #     
+	0x40  //  #      
+};
+
+/*
+ *  '-'
+ */
+static const uint8_t Font16_45[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0xFE, // ####### 
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  '.'
+ */
+static const uint8_t Font16_46[] = {
+	5, 12,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x60, //  ##     
+	0x60, //  ##     
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  '/'
+ */
+static const uint8_t Font16_47[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x02, //       # 
+	0x02, //       # 
+	0x04, //      #  
+	0x04, //      #  
+	0x08, //     #   
+	0x08, //     #   
+	0x10, //    #    
+	0x10, //    #    
+	0x20, //   #     
+	0x20, //   #     
+	0x40, //  #      
+	0x40, //  #      
+	0x80, // #       
+	0x80, // #       
+	0x00  //         
+};
+
+/*
+ *  '0'
+ */
+static const uint8_t Font16_48[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x18, //    ##   
+	0x24, //   #  #  
+	0x24, //   #  #  
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x24, //   #  #  
+	0x24, //   #  #  
+	0x18, //    ##   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  '1'
+ */
+static const uint8_t Font16_49[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x10, //    #    
+	0x10, //    #    
+	0x30, //   ##    
+	0x50, //  # #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  '2'
+ */
+static const uint8_t Font16_50[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x18, //    ##   
+	0x24, //   #  #  
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x02, //       # 
+	0x04, //      #  
+	0x08, //     #   
+	0x10, //    #    
+	0x20, //   #     
+	0x20, //   #     
+	0x40, //  #      
+	0x40, //  #      
+	0x7E, //  ###### 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  '3'
+ */
+static const uint8_t Font16_51[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x02, //       # 
+	0x04, //      #  
+	0x38, //   ###   
+	0x04, //      #  
+	0x02, //       # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  '4'
+ */
+static const uint8_t Font16_52[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x08, //     #   
+	0x18, //    ##   
+	0x18, //    ##   
+	0x28, //   # #   
+	0x28, //   # #   
+	0x48, //  #  #   
+	0x48, //  #  #   
+	0x88, // #   #   
+	0xFE, // ####### 
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  '5'
+ */
+static const uint8_t Font16_53[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x7C, //  #####  
+	0x40, //  #      
+	0x40, //  #      
+	0x40, //  #      
+	0xB8, // # ###   
+	0xC4, // ##   #  
+	0x82, // #     # 
+	0x02, //       # 
+	0x02, //       # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  '6'
+ */
+static const uint8_t Font16_54[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x40, //  #      
+	0x80, // #       
+	0x80, // #       
+	0xB8, // # ###   
+	0xC4, // ##   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  '7'
+ */
+static const uint8_t Font16_55[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0xFE, // ####### 
+	0x02, //       # 
+	0x04, //      #  
+	0x04, //      #  
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x00  //         
+};
+
+/*
+ *  '8'
+ */
+static const uint8_t Font16_56[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  '9'
+ */
+static const uint8_t Font16_57[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x46, //  #   ## 
+	0x3A, //   ### # 
+	0x02, //       # 
+	0x02, //       # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  ':'
+ */
+static const uint8_t Font16_58[] = {
+	5, 12,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x18, //    ##   
+	0x18, //    ##   
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x18, //    ##   
+	0x18, //    ##   
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  ';'
+ */
+static const uint8_t Font16_59[] = {
+	5, 12,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x18, //    ##   
+	0x18, //    ##   
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x18, //    ##   
+	0x08, //     #   
+	0x08, //     #   
+	0x10, //    #    
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  '<'
+ */
+static const uint8_t Font16_60[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x02, //       # 
+	0x04, //      #  
+	0x08, //     #   
+	0x10, //    #    
+	0x20, //   #     
+	0x20, //   #     
+	0x10, //    #    
+	0x08, //     #   
+	0x04, //      #  
+	0x02, //       # 
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  '='
+ */
+static const uint8_t Font16_61[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0xFE, // ####### 
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0xFE, // ####### 
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  '>'
+ */
+static const uint8_t Font16_62[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x40, //  #      
+	0x20, //   #     
+	0x10, //    #    
+	0x08, //     #   
+	0x04, //      #  
+	0x04, //      #  
+	0x08, //     #   
+	0x10, //    #    
+	0x20, //   #     
+	0x40, //  #      
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  '?'
+ */
+static const uint8_t Font16_63[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x04, //      #  
+	0x08, //     #   
+	0x08, //     #   
+	0x10, //    #    
+	0x10, //    #    
+	0x00, //         
+	0x00, //         
+	0x10, //    #    
+	0x10, //    #    
+	0x00  //         
+};
+
+/*
+ *  '@'
+ */
+static const uint8_t Font16_64[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x18, //    ##   
+	0x24, //   #  #  
+	0x42, //  #    # 
+	0x5A, //  # ## # 
+	0xB5, // # ## # #
+	0xA5, // # #  # #
+	0xA5, // # #  # #
+	0xA5, // # #  # #
+	0x9A, // #  ## # 
+	0x40, //  #      
+	0x40, //  #      
+	0x22, //   #   # 
+	0x1C, //    ###  
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'A'
+ */
+static const uint8_t Font16_65[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x10, //    #    
+	0x10, //    #    
+	0x28, //   # #   
+	0x28, //   # #   
+	0x28, //   # #   
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x7C, //  #####  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'B'
+ */
+static const uint8_t Font16_66[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0xF0, // ####    
+	0x88, // #   #   
+	0x84, // #    #  
+	0x84, // #    #  
+	0x84, // #    #  
+	0x88, // #   #   
+	0xF8, // #####   
+	0x84, // #    #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x84, // #    #  
+	0xF8, // #####   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'C'
+ */
+static const uint8_t Font16_67[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x42, //  #    # 
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x42, //  #    # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'D'
+ */
+static const uint8_t Font16_68[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0xF0, // ####    
+	0x88, // #   #   
+	0x84, // #    #  
+	0x84, // #    #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x84, // #    #  
+	0x84, // #    #  
+	0x88, // #   #   
+	0xF0, // ####    
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'E'
+ */
+static const uint8_t Font16_69[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0xFE, // ####### 
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0xFC, // ######  
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0xFE, // ####### 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'F'
+ */
+static const uint8_t Font16_70[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0xFE, // ####### 
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0xFC, // ######  
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'G'
+ */
+static const uint8_t Font16_71[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x18, //    ##   
+	0x24, //   #  #  
+	0x42, //  #    # 
+	0x40, //  #      
+	0x80, // #       
+	0x80, // #       
+	0x8E, // #   ### 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x42, //  #    # 
+	0x66, //  ##  ## 
+	0x1A, //    ## # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'H'
+ */
+static const uint8_t Font16_72[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0xFE, // ####### 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'I'
+ */
+static const uint8_t Font16_73[] = {
+	5, 12,
+	1, 16,
+	0x00, //         
+	0x38, //   ###   
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'J'
+ */
+static const uint8_t Font16_74[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x02, //       # 
+	0x02, //       # 
+	0x02, //       # 
+	0x02, //       # 
+	0x02, //       # 
+	0x02, //       # 
+	0x02, //       # 
+	0x02, //       # 
+	0x02, //       # 
+	0x02, //       # 
+	0x42, //  #    # 
+	0x24, //   #  #  
+	0x18, //    ##   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'K'
+ */
+static const uint8_t Font16_75[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x48, //  #  #   
+	0x58, //  # ##   
+	0x68, //  ## #   
+	0x64, //  ##  #  
+	0x44, //  #   #  
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x41, //  #     #
+	0x41, //  #     #
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'L'
+ */
+static const uint8_t Font16_76[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x40, //  #      
+	0x40, //  #      
+	0x40, //  #      
+	0x40, //  #      
+	0x40, //  #      
+	0x40, //  #      
+	0x40, //  #      
+	0x40, //  #      
+	0x40, //  #      
+	0x40, //  #      
+	0x40, //  #      
+	0x40, //  #      
+	0x7E, //  ###### 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'M'
+ */
+static const uint8_t Font16_77[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x82, // #     # 
+	0x82, // #     # 
+	0xC6, // ##   ## 
+	0xC6, // ##   ## 
+	0xC6, // ##   ## 
+	0xAA, // # # # # 
+	0xAA, // # # # # 
+	0xAA, // # # # # 
+	0x92, // #  #  # 
+	0x92, // #  #  # 
+	0x92, // #  #  # 
+	0x92, // #  #  # 
+	0x82, // #     # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'N'
+ */
+static const uint8_t Font16_78[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x82, // #     # 
+	0xC2, // ##    # 
+	0xC2, // ##    # 
+	0xA2, // # #   # 
+	0xA2, // # #   # 
+	0x92, // #  #  # 
+	0x92, // #  #  # 
+	0x92, // #  #  # 
+	0x8A, // #   # # 
+	0x8A, // #   # # 
+	0x86, // #    ## 
+	0x86, // #    ## 
+	0x82, // #     # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'O'
+ */
+static const uint8_t Font16_79[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'P'
+ */
+static const uint8_t Font16_80[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0xF8, // #####   
+	0x84, // #    #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x84, // #    #  
+	0xF8, // #####   
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'Q'
+ */
+static const uint8_t Font16_81[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0xBA, // # ### # 
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x08, //     #   
+	0x06  //      ## 
+};
+
+/*
+ *  'R'
+ */
+static const uint8_t Font16_82[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0xF8, // #####   
+	0x84, // #    #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x84, // #    #  
+	0xF8, // #####   
+	0x88, // #   #   
+	0x84, // #    #  
+	0x84, // #    #  
+	0x84, // #    #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'S'
+ */
+static const uint8_t Font16_83[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x80, // #       
+	0x60, //  ##     
+	0x18, //    ##   
+	0x04, //      #  
+	0x02, //       # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'T'
+ */
+static const uint8_t Font16_84[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0xFE, // ####### 
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'U'
+ */
+static const uint8_t Font16_85[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'V'
+ */
+static const uint8_t Font16_86[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x28, //   # #   
+	0x28, //   # #   
+	0x28, //   # #   
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'W'
+ */
+static const uint8_t Font16_87[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x92, // #  #  # 
+	0x92, // #  #  # 
+	0x92, // #  #  # 
+	0x92, // #  #  # 
+	0x92, // #  #  # 
+	0x92, // #  #  # 
+	0xAA, // # # # # 
+	0xAA, // # # # # 
+	0x6C, //  ## ##  
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'X'
+ */
+static const uint8_t Font16_88[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x28, //   # #   
+	0x28, //   # #   
+	0x10, //    #    
+	0x28, //   # #   
+	0x28, //   # #   
+	0x28, //   # #   
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'Y'
+ */
+static const uint8_t Font16_89[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x28, //   # #   
+	0x28, //   # #   
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'Z'
+ */
+static const uint8_t Font16_90[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0xFE, // ####### 
+	0x04, //      #  
+	0x04, //      #  
+	0x08, //     #   
+	0x08, //     #   
+	0x10, //    #    
+	0x10, //    #    
+	0x20, //   #     
+	0x20, //   #     
+	0x40, //  #      
+	0x40, //  #      
+	0x80, // #       
+	0xFE, // ####### 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  '['
+ */
+static const uint8_t Font16_91[] = {
+	5, 12,
+	1, 16,
+	0x1E, //    #### 
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x1E  //    #### 
+};
+
+/*
+ *  '\'
+ */
+static const uint8_t Font16_92[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x80, // #       
+	0x80, // #       
+	0x40, //  #      
+	0x40, //  #      
+	0x20, //   #     
+	0x20, //   #     
+	0x10, //    #    
+	0x10, //    #    
+	0x08, //     #   
+	0x08, //     #   
+	0x04, //      #  
+	0x04, //      #  
+	0x02, //       # 
+	0x02, //       # 
+	0x00  //         
+};
+
+/*
+ *  ']'
+ */
+static const uint8_t Font16_93[] = {
+	5, 12,
+	1, 16,
+	0xF0, // ####    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0xF0  // ####    
+};
+
+/*
+ *  '^'
+ */
+static const uint8_t Font16_94[] = {
+	8, 16,
+	1, 16,
+	0x10, //    #    
+	0x28, //   # #   
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  '_'
+ */
+static const uint8_t Font16_95[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0xFE, // ####### 
+	0x00  //         
+};
+
+/*
+ *  '''
+ */
+static const uint8_t Font16_96[] = {
+	5, 12,
+	1, 16,
+	0x30, //   ##    
+	0x20, //   #     
+	0x20, //   #     
+	0x10, //    #    
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'a'
+ */
+static const uint8_t Font16_97[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x3C, //   ####  
+	0x42, //  #    # 
+	0x02, //       # 
+	0x3E, //   ##### 
+	0x42, //  #    # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x86, // #    ## 
+	0x7A, //  #### # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'b'
+ */
+static const uint8_t Font16_98[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0xB8, // # ###   
+	0xC4, // ##   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0xC4, // ##   #  
+	0xB8, // # ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'c'
+ */
+static const uint8_t Font16_99[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'd'
+ */
+static const uint8_t Font16_100[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x02, //       # 
+	0x02, //       # 
+	0x02, //       # 
+	0x02, //       # 
+	0x3A, //   ### # 
+	0x46, //  #   ## 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x46, //  #   ## 
+	0x3A, //   ### # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'e'
+ */
+static const uint8_t Font16_101[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0xFE, // ####### 
+	0x80, // #       
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'f'
+ */
+static const uint8_t Font16_102[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x0C, //     ##  
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x7C, //  #####  
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'g'
+ */
+static const uint8_t Font16_103[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x3B, //   ### ##
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x40, //  #      
+	0x78, //  ####   
+	0x84, // #    #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x7C  //  #####  
+};
+
+/*
+ *  'h'
+ */
+static const uint8_t Font16_104[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x40, //  #      
+	0x40, //  #      
+	0x40, //  #      
+	0x40, //  #      
+	0x5C, //  # ###  
+	0x62, //  ##   # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'i'
+ */
+static const uint8_t Font16_105[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x10, //    #    
+	0x10, //    #    
+	0x00, //         
+	0x00, //         
+	0x30, //   ##    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'j'
+ */
+static const uint8_t Font16_106[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x08, //     #   
+	0x08, //     #   
+	0x00, //         
+	0x00, //         
+	0x18, //    ##   
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x10, //    #    
+	0x60  //  ##     
+};
+
+/*
+ *  'k'
+ */
+static const uint8_t Font16_107[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x40, //  #      
+	0x40, //  #      
+	0x40, //  #      
+	0x40, //  #      
+	0x42, //  #    # 
+	0x44, //  #   #  
+	0x48, //  #  #   
+	0x50, //  # #    
+	0x68, //  ## #   
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'l'
+ */
+static const uint8_t Font16_108[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x30, //   ##    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'm'
+ */
+static const uint8_t Font16_109[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0xEC, // ### ##  
+	0x92, // #  #  # 
+	0x92, // #  #  # 
+	0x92, // #  #  # 
+	0x92, // #  #  # 
+	0x92, // #  #  # 
+	0x92, // #  #  # 
+	0x92, // #  #  # 
+	0x92, // #  #  # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'n'
+ */
+static const uint8_t Font16_110[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x5C, //  # ###  
+	0x62, //  ##   # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'o'
+ */
+static const uint8_t Font16_111[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'p'
+ */
+static const uint8_t Font16_112[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0xB8, // # ###   
+	0xC4, // ##   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0xC4, // ##   #  
+	0xB8, // # ###   
+	0x80, // #       
+	0x80, // #       
+	0x80  // #       
+};
+
+/*
+ *  'q'
+ */
+static const uint8_t Font16_113[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x3A, //   ### # 
+	0x46, //  #   ## 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x46, //  #   ## 
+	0x3A, //   ### # 
+	0x02, //       # 
+	0x02, //       # 
+	0x02  //       # 
+};
+
+/*
+ *  'r'
+ */
+static const uint8_t Font16_114[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x2C, //   # ##  
+	0x30, //   ##    
+	0x20, //   #     
+	0x20, //   #     
+	0x20, //   #     
+	0x20, //   #     
+	0x20, //   #     
+	0x20, //   #     
+	0x20, //   #     
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  's'
+ */
+static const uint8_t Font16_115[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x3C, //   ####  
+	0x42, //  #    # 
+	0x40, //  #      
+	0x60, //  ##     
+	0x18, //    ##   
+	0x06, //      ## 
+	0x02, //       # 
+	0x42, //  #    # 
+	0x3C, //   ####  
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  't'
+ */
+static const uint8_t Font16_116[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x7C, //  #####  
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x0C, //     ##  
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'u'
+ */
+static const uint8_t Font16_117[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x46, //  #   ## 
+	0x3A, //   ### # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'v'
+ */
+static const uint8_t Font16_118[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x28, //   # #   
+	0x28, //   # #   
+	0x10, //    #    
+	0x10, //    #    
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'w'
+ */
+static const uint8_t Font16_119[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x92, // #  #  # 
+	0x92, // #  #  # 
+	0x92, // #  #  # 
+	0x92, // #  #  # 
+	0xAA, // # # # # 
+	0xAA, // # # # # 
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'x'
+ */
+static const uint8_t Font16_120[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x28, //   # #   
+	0x28, //   # #   
+	0x10, //    #    
+	0x28, //   # #   
+	0x28, //   # #   
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'y'
+ */
+static const uint8_t Font16_121[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x28, //   # #   
+	0x28, //   # #   
+	0x18, //    ##   
+	0x10, //    #    
+	0x10, //    #    
+	0x20, //   #     
+	0xC0  // ##      
+};
+
+/*
+ *  'z'
+ */
+static const uint8_t Font16_122[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x7E, //  ###### 
+	0x04, //      #  
+	0x08, //     #   
+	0x08, //     #   
+	0x10, //    #    
+	0x10, //    #    
+	0x20, //   #     
+	0x40, //  #      
+	0xFE, // ####### 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  '{'
+ */
+static const uint8_t Font16_123[] = {
+	5, 12,
+	1, 16,
+	0x04, //      #  
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x10, //    #    
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x04  //      #  
+};
+
+/*
+ *  '|'
+ */
+static const uint8_t Font16_124[] = {
+	5, 12,
+	1, 16,
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10  //    #    
+};
+
+/*
+ *  '}'
+ */
+static const uint8_t Font16_125[] = {
+	5, 12,
+	1, 16,
+	0x40, //  #      
+	0x20, //   #     
+	0x20, //   #     
+	0x20, //   #     
+	0x20, //   #     
+	0x20, //   #     
+	0x20, //   #     
+	0x10, //    #    
+	0x20, //   #     
+	0x20, //   #     
+	0x20, //   #     
+	0x20, //   #     
+	0x20, //   #     
+	0x20, //   #     
+	0x20, //   #     
+	0x40  //  #      
+};
+
+/*
+ *  '->'
+ */
+static const uint8_t Font16_126[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x60, //  ##     
+	0x92, // #  #  # 
+	0x0C, //     ##  
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  DEL
+ */
+static const uint8_t Font16_127[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  yohaku
+ */
+static const uint8_t Font16_160[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  syuryou
+ */
+static const uint8_t Font16_161[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x10, //    #    
+	0x10, //    #    
+	0x00, //         
+	0x00, //         
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x30, //   ##    
+	0x30, //   ##    
+	0x30, //   ##    
+	0x30  //   ##    
+};
+
+/*
+ *  kakko
+ */
+static const uint8_t Font16_162[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x10, //    #    
+	0x3C, //   ####  
+	0x52, //  # #  # 
+	0x92, // #  #  # 
+	0x90, // #  #    
+	0x90, // #  #    
+	0x90, // #  #    
+	0x90, // #  #    
+	0x90, // #  #    
+	0x92, // #  #  # 
+	0x52, //  # #  # 
+	0x3C, //   ####  
+	0x10, //    #    
+	0x00  //         
+};
+
+/*
+ *  kakko tojiru
+ */
+static const uint8_t Font16_163[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x0C, //     ##  
+	0x12, //    #  # 
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x7C, //  #####  
+	0x10, //    #    
+	0x10, //    #    
+	0x3C, //   ####  
+	0x52, //  # #  # 
+	0x20, //   #     
+	0x00  //         
+};
+
+/*
+ *  kutouten
+ */
+static const uint8_t Font16_164[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x42, //  #    # 
+	0x3C, //   ####  
+	0x24, //   #  #  
+	0x24, //   #  #  
+	0x3C, //   ####  
+	0x42, //  #    # 
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  cyuten
+ */
+static const uint8_t Font16_165[] = {
+	8, 16,
+	1, 16,
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x28, //   # #   
+	0x28, //   # #   
+	0xFE, // ####### 
+	0x10, //    #    
+	0xFE, // ####### 
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'WO'
+ */
+static const uint8_t Font16_166[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'aa'
+ */
+static const uint8_t Font16_167[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x3C, //   ####  
+	0x42, //  #    # 
+	0x40, //  #      
+	0x20, //   #     
+	0x3C, //   ####  
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x3C, //   ####  
+	0x04, //      #  
+	0x02, //       # 
+	0x42, //  #    # 
+	0x3C, //   ####  
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'ii'
+ */
+static const uint8_t Font16_168[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x24, //   #  #  
+	0x24, //   #  #  
+	0x24, //   #  #  
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'uu'
+ */
+static const uint8_t Font16_169[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x3C, //   ####  
+	0x42, //  #    # 
+	0x99, // #  ##  #
+	0xA5, // # #  # #
+	0xA1, // # #    #
+	0xA1, // # #    #
+	0xA1, // # #    #
+	0xA5, // # #  # #
+	0xA5, // # #  # #
+	0x9B, // #  ## ##
+	0x42, //  #    # 
+	0x3C, //   ####  
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'ee'
+ */
+static const uint8_t Font16_170[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x1C, //    ###  
+	0x22, //   #   # 
+	0x1E, //    #### 
+	0x22, //   #   # 
+	0x26, //   #  ## 
+	0x1A, //    ## # 
+	0x00, //         
+	0x3E, //   ##### 
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'oo'
+ */
+static const uint8_t Font16_171[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x09, //     #  #
+	0x12, //    #  # 
+	0x24, //   #  #  
+	0x48, //  #  #   
+	0x90, // #  #    
+	0x90, // #  #    
+	0x48, //  #  #   
+	0x24, //   #  #  
+	0x12, //    #  # 
+	0x09, //     #  #
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'ya'
+ */
+static const uint8_t Font16_172[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0xFE, // ####### 
+	0xFE, // ####### 
+	0x06, //      ## 
+	0x06, //      ## 
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'yu'
+ */
+static const uint8_t Font16_173[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0xFE, // ####### 
+	0xFE, // ####### 
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'yo'
+ */
+static const uint8_t Font16_174[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x3C, //   ####  
+	0x42, //  #    # 
+	0xB9, // # ###  #
+	0xA5, // # #  # #
+	0xA5, // # #  # #
+	0xB9, // # ###  #
+	0xA9, // # # #  #
+	0xA5, // # #  # #
+	0xA5, // # #  # #
+	0xA3, // # #   ##
+	0x42, //  #    # 
+	0x3C, //   ####  
+	0x00, //         
+	0x00  //         
+};
+
+
+/*
+ *  'tu'
+ */
+static const uint8_t Font16_175[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0xFE, // ####### 
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  '-'
+ */
+static const uint8_t Font16_176[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'AA'
+ */
+static const uint8_t Font16_177[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0xFE, // ####### 
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x00, //         
+	0xFE, // ####### 
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'II'
+ */
+static const uint8_t Font16_178[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x18, //    ##   
+	0x24, //   #  #  
+	0x04, //      #  
+	0x08, //     #   
+	0x10, //    #    
+	0x20, //   #     
+	0x3C, //   ####  
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'UU'
+ */
+static const uint8_t Font16_179[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x18, //    ##   
+	0x24, //   #  #  
+	0x04, //      #  
+	0x18, //    ##   
+	0x04, //      #  
+	0x24, //   #  #  
+	0x18, //    ##   
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'EE'
+ */
+static const uint8_t Font16_180[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x0C, //     ##  
+	0x18, //    ##   
+	0x30, //   ##    
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'OO'
+ */
+static const uint8_t Font16_181[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x22, //   #   # 
+	0x22, //   #   # 
+	0x22, //   #   # 
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x6C, //  ## ##  
+	0x54, //  # # #  
+	0x82, // #     # 
+	0x80  // #       
+};
+
+/*
+ *  'KA'
+ */
+static const uint8_t Font16_182[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x3C, //   ####  
+	0x74, //  ### #  
+	0x74, //  ### #  
+	0x74, //  ### #  
+	0x74, //  ### #  
+	0x34, //   ## #  
+	0x14, //    # #  
+	0x14, //    # #  
+	0x14, //    # #  
+	0x14, //    # #  
+	0x14, //    # #  
+	0x14, //    # #  
+	0x14, //    # #  
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'KI'
+ */
+static const uint8_t Font16_183[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x18, //    ##   
+	0x18, //    ##   
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'KU'
+ */
+static const uint8_t Font16_184[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x0C, //     ##  
+	0x08, //     #   
+	0x10  //    #    
+};
+
+/*
+ *  'KE'
+ */
+static const uint8_t Font16_185[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x08, //     #   
+	0x18, //    ##   
+	0x28, //   # #   
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'KO'
+ */
+static const uint8_t Font16_186[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x18, //    ##   
+	0x24, //   #  #  
+	0x24, //   #  #  
+	0x24, //   #  #  
+	0x24, //   #  #  
+	0x18, //    ##   
+	0x00, //         
+	0x3C, //   ####  
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'SA'
+ */
+static const uint8_t Font16_187[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x90, // #  #    
+	0x48, //  #  #   
+	0x24, //   #  #  
+	0x12, //    #  # 
+	0x09, //     #  #
+	0x09, //     #  #
+	0x12, //    #  # 
+	0x24, //   #  #  
+	0x48, //  #  #   
+	0x90, // #  #    
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'SI'
+ */
+static const uint8_t Font16_188[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x40, //  #      
+	0xC4, // ##   #  
+	0x44, //  #   #  
+	0x48, //  #  #   
+	0x48, //  #  #   
+	0x50, //  # #    
+	0x12, //    #  # 
+	0x22, //   #   # 
+	0x26, //   #  ## 
+	0x4A, //  #  # # 
+	0x5F, //  # #####
+	0x82, // #     # 
+	0x82, // #     # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'SU'
+ */
+static const uint8_t Font16_189[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x40, //  #      
+	0xC4, // ##   #  
+	0x44, //  #   #  
+	0x48, //  #  #   
+	0x48, //  #  #   
+	0x50, //  # #    
+	0x1C, //    ###  
+	0x32, //   ##  # 
+	0x22, //   #   # 
+	0x44, //  #   #  
+	0x48, //  #  #   
+	0x88, // #   #   
+	0x9E, // #  #### 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'SE'
+ */
+static const uint8_t Font16_190[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x60, //  ##     
+	0x92, // #  #  # 
+	0x12, //    #  # 
+	0x64, //  ##  #  
+	0x14, //    # #  
+	0x98, // #  ##   
+	0x6A, //  ## # # 
+	0x12, //    #  # 
+	0x16, //    # ## 
+	0x2A, //   # # # 
+	0x3F, //   ######
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x00, //         
+	0x00, //         
+};
+
+/*
+ *  'SO'
+ */
+static const uint8_t Font16_191[] = {
+	8, 16,
+	1, 16,
+	0x08, //     #   
+	0x08, //     #   
+	0x00, //         
+	0x00, //         
+	0x08, //     #   
+	0x08, //     #   
+	0x08, //     #   
+	0x10, //    #    
+	0x20, //   #     
+	0x20, //   #     
+	0x41, //  #     #
+	0x41, //  #     #
+	0x41, //  #     #
+	0x22, //   #   # 
+	0x1C, //    ###  
+	0x00  //         
+};
+
+/*
+ *  'TA'
+ */
+static const uint8_t Font16_192[] = {
+	8, 16,
+	1, 16,
+	0x30, //   ##    
+	0x10, //    #    
+	0x08, //     #   
+	0x10, //    #    
+	0x10, //    #    
+	0x28, //   # #   
+	0x28, //   # #   
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x7C, //  #####  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'TI'
+ */
+static const uint8_t Font16_193[] = {
+	8, 16,
+	1, 16,
+	0x18, //    ##   
+	0x10, //    #    
+	0x20, //   #     
+	0x10, //    #    
+	0x10, //    #    
+	0x28, //   # #   
+	0x28, //   # #   
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x7C, //  #####  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'TU'
+ */
+static const uint8_t Font16_194[] = {
+	8, 16,
+	1, 16,
+	0x10, //    #    
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x10, //    #    
+	0x10, //    #    
+	0x28, //   # #   
+	0x28, //   # #   
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x7C, //  #####  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'TE'
+ */
+static const uint8_t Font16_195[] = {
+	8, 16,
+	1, 16,
+	0x34, //   ## #  
+	0x58, //  # ##   
+	0x00, //         
+	0x10, //    #    
+	0x10, //    #    
+	0x28, //   # #   
+	0x28, //   # #   
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x7C, //  #####  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'TO'
+ */
+static const uint8_t Font16_196[] = {
+	8, 16,
+	1, 16,
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x00, //         
+	0x10, //    #    
+	0x10, //    #    
+	0x28, //   # #   
+	0x28, //   # #   
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x7C, //  #####  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'NA'
+ */
+static const uint8_t Font16_197[] = {
+	8, 16,
+	1, 16,
+	0x10, //    #    
+	0x28, //   # #   
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x28, //   # #   
+	0x28, //   # #   
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x7C, //  #####  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'NI'
+ */
+static const uint8_t Font16_198[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x1F, //    #####
+	0x28, //   # #   
+	0x28, //   # #   
+	0x28, //   # #   
+	0x2E, //   # ### 
+	0x48, //  #  #   
+	0x48, //  #  #   
+	0x78, //  ####   
+	0x88, // #   #   
+	0x88, // #   #   
+	0x88, // #   #   
+	0x8F, // #   ####
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'NU'
+ */
+static const uint8_t Font16_199[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x42, //  #    # 
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x42, //  #    # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x08, //     #   
+	0x08, //     #   
+	0x10  //    #    
+};
+
+/*
+ *  'NE'
+ */
+static const uint8_t Font16_200[] = {
+	8, 16,
+	1, 16,
+	0x30, //   ##    
+	0x10, //    #    
+	0x08, //     #   
+	0xFE, // ####### 
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0xFC, // ######  
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0xFE, // ####### 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'NO'
+ */
+static const uint8_t Font16_201[] = {
+	8, 16,
+	1, 16,
+	0x18, //    ##   
+	0x10, //    #    
+	0x20, //   #     
+	0xFE, // ####### 
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0xFC, // ######  
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0xFE, // ####### 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'HA'
+ */
+static const uint8_t Font16_202[] = {
+	8, 16,
+	1, 16,
+	0x10, //    #    
+	0x38, //   ###   
+	0x44, //  #   #  
+	0xFE, // ####### 
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0xFC, // ######  
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0xFE, // ####### 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'HI'
+ */
+static const uint8_t Font16_203[] = {
+	8, 16,
+	1, 16,
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x00, //         
+	0xFE, // ####### 
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0xFC, // ######  
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0xFE, // ####### 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'HU'
+ */
+static const uint8_t Font16_204[] = {
+	8, 16,
+	1, 16,
+	0x30, //   ##    
+	0x10, //    #    
+	0x08, //     #   
+	0x38, //   ###   
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'HE'
+ */
+static const uint8_t Font16_205[] = {
+	8, 16,
+	1, 16,
+	0x18, //    ##   
+	0x10, //    #    
+	0x20, //   #     
+	0x38, //   ###   
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'HO'
+ */
+static const uint8_t Font16_206[] = {
+	8, 16,
+	1, 16,
+	0x10, //    #    
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'MA'
+ */
+static const uint8_t Font16_207[] = {
+	8, 16,
+	1, 16,
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x00, //         
+	0x38, //   ###   
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'MI'
+ */
+static const uint8_t Font16_208[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x70, //  ###    
+	0x48, //  #  #   
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0xF2, // ####  # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x48, //  #  #   
+	0x70, //  ###    
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'MU'
+ */
+static const uint8_t Font16_209[] = {
+	8, 16,
+	1, 16,
+	0x34, //   ## #  
+	0x58, //  # ##   
+	0x82, // #     # 
+	0x82, // #     # 
+	0xC2, // ##    # 
+	0xC2, // ##    # 
+	0xA2, // # #   # 
+	0xA2, // # #   # 
+	0x92, // #  #  # 
+	0x8A, // #   # # 
+	0x8A, // #   # # 
+	0x86, // #    ## 
+	0x86, // #    ## 
+	0x82, // #     # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'ME'
+ */
+static const uint8_t Font16_210[] = {
+	8, 16,
+	1, 16,
+	0x30, //   ##    
+	0x10, //    #    
+	0x08, //     #   
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'MO'
+ */
+static const uint8_t Font16_211[] = {
+	8, 16,
+	1, 16,
+	0x18, //    ##   
+	0x10, //    #    
+	0x20, //   #     
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'YA'
+ */
+static const uint8_t Font16_212[] = {
+	8, 16,
+	1, 16,
+	0x10, //    #    
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'YU'
+ */
+static const uint8_t Font16_213[] = {
+	8, 16,
+	1, 16,
+	0x34, //   ## #  
+	0x58, //  # ##   
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'YO'
+ */
+static const uint8_t Font16_214[] = {
+	8, 16,
+	1, 16,
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'RA'
+ */
+static const uint8_t Font16_215[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x81, // #      #
+	0x42, //  #    # 
+	0x24, //   #  #  
+	0x18, //    ##   
+	0x18, //    ##   
+	0x24, //   #  #  
+	0x42, //  #    # 
+	0x81, // #      #
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'RI'
+ */
+static const uint8_t Font16_216[] = {
+	8, 16,
+	1, 16,
+	0x02, //       # 
+	0x02, //       # 
+	0x3C, //   ####  
+	0x44, //  #   #  
+	0x86, // #    ## 
+	0x8A, // #   # # 
+	0x8A, // #   # # 
+	0x92, // #  #  # 
+	0x92, // #  #  # 
+	0xA2, // # #   # 
+	0xA2, // # #   # 
+	0xC2, // ##    # 
+	0x44, //  #   #  
+	0x78, //  ####   
+	0x80, // #       
+	0x80  // #       
+};
+
+/*
+ *  'RU'
+ */
+static const uint8_t Font16_217[] = {
+	8, 16,
+	1, 16,
+	0x30, //   ##    
+	0x10, //    #    
+	0x08, //     #   
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'RE'
+ */
+static const uint8_t Font16_218[] = {
+	8, 16,
+	1, 16,
+	0x18, //    ##   
+	0x10, //    #    
+	0x20, //   #     
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'RO'
+ */
+static const uint8_t Font16_219[] = {
+	8, 16,
+	1, 16,
+	0x10, //    #    
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x00, //         
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  'WA'
+ */
+static const uint8_t Font16_220[] = {
+	8, 16,
+	1, 16,
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x00, //         
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00, //         
+};
+
+/*
+ *  'NN'
+ */
+static const uint8_t Font16_221[] = {
+	8, 16,
+	1, 16,
+	0x18, //    ##   
+	0x10, //    #    
+	0xA2, // # #   # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x28, //   # #   
+	0x28, //   # #   
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  dakuten
+ */
+static const uint8_t Font16_222[] = {
+	8, 16,
+	1, 16,
+	0x80, // #       
+	0x80, // #       
+	0xF8, // #####   
+	0x84, // #    #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x84, // #    #  
+	0xF8, // #####   
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  maru
+ */
+static const uint8_t Font16_223[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x78, //  ####   
+	0x84, // #    #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x84, // #    #  
+	0xB8, // # ###   
+	0x84, // #    #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x84, // #    #  
+	0xB8, // # ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  224
+ */
+static const uint8_t Font16_224[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x30, //   ##    
+	0x10, //    #    
+	0x08, //     #   
+	0x00, //         
+	0x3C, //   ####  
+	0x42, //  #    # 
+	0x02, //       # 
+	0x3E, //   ##### 
+	0x42, //  #    # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x86, // #    ## 
+	0x7A, //  #### # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  225
+ */
+static const uint8_t Font16_225[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x18, //    ##   
+	0x10, //    #    
+	0x20, //   #     
+	0x00, //         
+	0x3C, //   ####  
+	0x42, //  #    # 
+	0x02, //       # 
+	0x3E, //   ##### 
+	0x42, //  #    # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x86, // #    ## 
+	0x7A, //  #### # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  226
+ */
+static const uint8_t Font16_226[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x10, //    #    
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x00, //         
+	0x3C, //   ####  
+	0x42, //  #    # 
+	0x02, //       # 
+	0x3E, //   ##### 
+	0x42, //  #    # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x86, // #    ## 
+	0x7A, //  #### # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  227
+ */
+static const uint8_t Font16_227[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x34, //   ## #  
+	0x58, //  # ##   
+	0x00, //         
+	0x00, //         
+	0x3C, //   ####  
+	0x42, //  #    # 
+	0x02, //       # 
+	0x3E, //   ##### 
+	0x42, //  #    # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x86, // #    ## 
+	0x7A, //  #### # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  228
+ */
+static const uint8_t Font16_228[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x24, //   #  #  
+	0x24, //   #  #  
+	0x00, //         
+	0x3C, //   ####  
+	0x42, //  #    # 
+	0x02, //       # 
+	0x3E, //   ##### 
+	0x42, //  #    # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x86, // #    ## 
+	0x7A, //  #### # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  229
+ */
+static const uint8_t Font16_229[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x10, //    #    
+	0x28, //   # #   
+	0x10, //    #    
+	0x00, //         
+	0x3C, //   ####  
+	0x42, //  #    # 
+	0x02, //       # 
+	0x3E, //   ##### 
+	0x42, //  #    # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x86, // #    ## 
+	0x7A, //  #### # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  230
+ */
+static const uint8_t Font16_230[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x6C, //  ## ##  
+	0x92, // #  #  # 
+	0x12, //    #  # 
+	0x3E, //   ##### 
+	0x50, //  # #    
+	0x90, // #  #    
+	0x92, // #  #  # 
+	0x92, // #  #  # 
+	0x6C, //  ## ##  
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  231
+ */
+static const uint8_t Font16_231[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x80, // #       
+	0x80, // #       
+	0x80, // #       
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x10, //    #    
+	0x10, //    #    
+	0x20  //   #     
+};
+
+/*
+ *  232
+ */
+static const uint8_t Font16_232[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x30, //   ##    
+	0x10, //    #    
+	0x08, //     #   
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0xFE, // ####### 
+	0x80, // #       
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  233
+ */
+static const uint8_t Font16_233[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x18, //    ##   
+	0x10, //    #    
+	0x20, //   #     
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0xFE, // ####### 
+	0x80, // #       
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  234
+ */
+static const uint8_t Font16_234[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x10, //    #    
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0xFE, // ####### 
+	0x80, // #       
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  235
+ */
+static const uint8_t Font16_235[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x00, //         
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0xFE, // ####### 
+	0x80, // #       
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  236
+ */
+static const uint8_t Font16_236[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x30, //   ##    
+	0x10, //    #    
+	0x08, //     #   
+	0x00, //         
+	0x30, //   ##    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  237
+ */
+static const uint8_t Font16_237[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x18, //    ##   
+	0x10, //    #    
+	0x20, //   #     
+	0x00, //         
+	0x30, //   ##    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  238
+ */
+static const uint8_t Font16_238[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x10, //    #    
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x00, //         
+	0x30, //   ##    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  239
+ */
+static const uint8_t Font16_239[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x44, //  #   #  
+	0x44, //  #   #  
+	0x00, //         
+	0x00, //         
+	0x30, //   ##    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x10, //    #    
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  240
+ */
+static const uint8_t Font16_240[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x64, //  ##  #  
+	0x18, //    ##   
+	0x30, //   ##    
+	0x48, //  #  #   
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  241
+ */
+static const uint8_t Font16_241[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x34, //   ## #  
+	0x58, //  # ##   
+	0x00, //         
+	0x00, //         
+	0x5C, //  # ###  
+	0x62, //  ##   # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  242
+ */
+static const uint8_t Font16_242[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x30, //   ##    
+	0x10, //    #    
+	0x08, //     #   
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  243
+ */
+static const uint8_t Font16_243[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x18, //    ##   
+	0x10, //    #    
+	0x20, //   #     
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  244
+ */
+static const uint8_t Font16_244[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x10, //    #    
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  245
+ */
+static const uint8_t Font16_245[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x34, //   ## #  
+	0x58, //  # ##   
+	0x00, //         
+	0x00, //         
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x82, // #     # 
+	0x44, //  #   #  
+	0x38, //   ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  246
+ */
+static const uint8_t Font16_246[] = {
+	8, 16,
+	1, 16,
+	0x00, //       
+	0x50, //  # #  
+	0x00, //       
+	0x70, //  ###  
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x88, // #   # 
+	0x70, //  ###  
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  247
+ */
+static const uint8_t Font16_247[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x10, //    #    
+	0x10, //    #    
+	0x00, //         
+	0xFE, // ####### 
+	0x00, //         
+	0x10, //    #    
+	0x10, //    #    
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  248
+ */
+static const uint8_t Font16_248[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x00, //         
+	0x3A, //   ### # 
+	0x44, //  #   #  
+	0x8A, // #   # # 
+	0x8A, // #   # # 
+	0x92, // #  #  # 
+	0xA2, // # #   # 
+	0xA2, // # #   # 
+	0x44, //  #   #  
+	0xB8, // # ###   
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  249
+ */
+static const uint8_t Font16_249[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x30, //   ##    
+	0x10, //    #    
+	0x08, //     #   
+	0x00, //         
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x46, //  #   ## 
+	0x3A, //   ### # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  250
+ */
+static const uint8_t Font16_250[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x18, //    ##   
+	0x10, //    #    
+	0x20, //   #     
+	0x00, //         
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x46, //  #   ## 
+	0x3A, //   ### # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  251
+ */
+static const uint8_t Font16_251[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x10, //    #    
+	0x38, //   ###   
+	0x44, //  #   #  
+	0x00, //         
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x46, //  #   ## 
+	0x3A, //   ### # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  252
+ */
+static const uint8_t Font16_252[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x24, //   #  #  
+	0x24, //   #  #  
+	0x00, //         
+	0x00, //         
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x46, //  #   ## 
+	0x3A, //   ### # 
+	0x00, //         
+	0x00  //         
+};
+
+/*
+ *  253
+ */
+static const uint8_t Font16_253[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x0C, //     ##  
+	0x08, //     #   
+	0x10, //    #    
+	0x00, //         
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x22, //   #   # 
+	0x24, //   #  #  
+	0x14, //    # #  
+	0x08, //     #   
+	0x08, //     #   
+	0x10, //    #    
+	0x10, //    #    
+	0x20, //   #     
+	0x40  //  #      
+};
+
+/*
+ *  254
+ */
+static const uint8_t Font16_254[] = {
+	8, 16,
+	1, 16,
+	/* 253 */
+	0x00, //         
+	0x00, //         
+	0x40, //  #      
+	0x40, //  #      
+	0x40, //  #      
+	0x78, //  ####   
+	0x44, //  #   #  
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x44, //  #   #  
+	0x78, //  ####   
+	0x40, //  #      
+	0x40, //  #      
+	0x40, //  #      
+	0x40  //  #      
+};
+
+/*
+ *  255
+ */
+static const uint8_t Font16_255[] = {
+	8, 16,
+	1, 16,
+	0x00, //         
+	0x24, //   #  #  
+	0x24, //   #  #  
+	0x00, //         
+	0x00, //         
+	0x42, //  #    # 
+	0x42, //  #    # 
+	0x22, //   #   # 
+	0x24, //   #  #  
+	0x14, //    # #  
+	0x08, //     #   
+	0x08, //     #   
+	0x10, //    #    
+	0x10, //    #    
+	0x20, //   #     
+	0x40  //  #      
+};
+
+
+const font_t *Font16[] = {
+	(font_t *)Font16_32,  (font_t *)Font16_01,  (font_t *)Font16_02,  (font_t *)Font16_03,
+	(font_t *)Font16_04,  (font_t *)Font16_05,  (font_t *)Font16_06,  (font_t *)Font16_07,
+	(font_t *)Font16_08,  (font_t *)Font16_09,  (font_t *)Font16_10,  (font_t *)Font16_11,
+	(font_t *)Font16_12,  (font_t *)Font16_13,  (font_t *)Font16_14,  (font_t *)Font16_15,
+	(font_t *)Font16_16,  (font_t *)Font16_17,  (font_t *)Font16_18,  (font_t *)Font16_19,
+	(font_t *)Font16_20,  (font_t *)Font16_21,  (font_t *)Font16_22,  (font_t *)Font16_23,
+	(font_t *)Font16_24,  (font_t *)Font16_25,  (font_t *)Font16_26,  (font_t *)Font16_27,
+	(font_t *)Font16_28,  (font_t *)Font16_29,  (font_t *)Font16_30,  (font_t *)Font16_31,
+	(font_t *)Font16_32,  (font_t *)Font16_33,  (font_t *)Font16_34,  (font_t *)Font16_35,
+	(font_t *)Font16_36,  (font_t *)Font16_37,  (font_t *)Font16_38,  (font_t *)Font16_39,
+	(font_t *)Font16_40,  (font_t *)Font16_41,  (font_t *)Font16_42,  (font_t *)Font16_43,
+	(font_t *)Font16_44,  (font_t *)Font16_45,  (font_t *)Font16_46,  (font_t *)Font16_47,
+	(font_t *)Font16_48,  (font_t *)Font16_49,  (font_t *)Font16_50,  (font_t *)Font16_51,
+	(font_t *)Font16_52,  (font_t *)Font16_53,  (font_t *)Font16_54,  (font_t *)Font16_55,
+	(font_t *)Font16_56,  (font_t *)Font16_57,  (font_t *)Font16_58,  (font_t *)Font16_59,
+	(font_t *)Font16_60,  (font_t *)Font16_61,  (font_t *)Font16_62,  (font_t *)Font16_63,
+	(font_t *)Font16_64,  (font_t *)Font16_65,  (font_t *)Font16_66,  (font_t *)Font16_67,
+	(font_t *)Font16_68,  (font_t *)Font16_69,  (font_t *)Font16_70,  (font_t *)Font16_71,
+	(font_t *)Font16_72,  (font_t *)Font16_73,  (font_t *)Font16_74,  (font_t *)Font16_75,
+	(font_t *)Font16_76,  (font_t *)Font16_77,  (font_t *)Font16_78,  (font_t *)Font16_79,
+	(font_t *)Font16_80,  (font_t *)Font16_81,  (font_t *)Font16_82,  (font_t *)Font16_83,
+	(font_t *)Font16_84,  (font_t *)Font16_85,  (font_t *)Font16_86,  (font_t *)Font16_87,
+	(font_t *)Font16_88,  (font_t *)Font16_89,  (font_t *)Font16_90,  (font_t *)Font16_91,
+	(font_t *)Font16_92,  (font_t *)Font16_93,  (font_t *)Font16_94,  (font_t *)Font16_95,
+	(font_t *)Font16_96,  (font_t *)Font16_97,  (font_t *)Font16_98,  (font_t *)Font16_99,
+	(font_t *)Font16_100, (font_t *)Font16_101, (font_t *)Font16_102, (font_t *)Font16_103,
+	(font_t *)Font16_104, (font_t *)Font16_105, (font_t *)Font16_106, (font_t *)Font16_107,
+	(font_t *)Font16_108, (font_t *)Font16_109, (font_t *)Font16_110, (font_t *)Font16_111,
+	(font_t *)Font16_112, (font_t *)Font16_113, (font_t *)Font16_114, (font_t *)Font16_115,
+	(font_t *)Font16_116, (font_t *)Font16_117, (font_t *)Font16_118, (font_t *)Font16_119,
+	(font_t *)Font16_120, (font_t *)Font16_121, (font_t *)Font16_122, (font_t *)Font16_123,
+	(font_t *)Font16_124, (font_t *)Font16_125, (font_t *)Font16_126, (font_t *)Font16_127,
+
+	0,                    0,                    0,                    0,
+	0,                    0,                    0,                    0,
+	0,                    0,                    0,                    0,
+	0,                    0,                    0,                    0,
+	0,                    0,                    0,                    0,
+	0,                    0,                    0,                    0,
+	0,                    0,                    0,                    0,
+	0,                    0,                    0,                    0,
+	(font_t *)Font16_160, (font_t *)Font16_161, (font_t *)Font16_162, (font_t *)Font16_163,
+	(font_t *)Font16_164, (font_t *)Font16_165, (font_t *)Font16_166, (font_t *)Font16_167,
+	(font_t *)Font16_168, (font_t *)Font16_169, (font_t *)Font16_170, (font_t *)Font16_171,
+	(font_t *)Font16_172, (font_t *)Font16_173, (font_t *)Font16_174, (font_t *)Font16_175,
+	(font_t *)Font16_176, (font_t *)Font16_177, (font_t *)Font16_178, (font_t *)Font16_179,
+	(font_t *)Font16_180, (font_t *)Font16_181, (font_t *)Font16_182, (font_t *)Font16_183,
+	(font_t *)Font16_184, (font_t *)Font16_185, (font_t *)Font16_186, (font_t *)Font16_187,
+	(font_t *)Font16_188, (font_t *)Font16_189, (font_t *)Font16_190, (font_t *)Font16_191,
+	(font_t *)Font16_192, (font_t *)Font16_193, (font_t *)Font16_194, (font_t *)Font16_195,
+	(font_t *)Font16_196, (font_t *)Font16_197, (font_t *)Font16_198, (font_t *)Font16_199,
+	(font_t *)Font16_200, (font_t *)Font16_201, (font_t *)Font16_202, (font_t *)Font16_203,
+	(font_t *)Font16_204, (font_t *)Font16_205, (font_t *)Font16_206, (font_t *)Font16_207,
+	(font_t *)Font16_208, (font_t *)Font16_209, (font_t *)Font16_210, (font_t *)Font16_211,
+	(font_t *)Font16_212, (font_t *)Font16_213, (font_t *)Font16_214, (font_t *)Font16_215,
+	(font_t *)Font16_216, (font_t *)Font16_217, (font_t *)Font16_218, (font_t *)Font16_219,
+	(font_t *)Font16_220, (font_t *)Font16_221, (font_t *)Font16_222, (font_t *)Font16_223,
+	(font_t *)Font16_224, (font_t *)Font16_225, (font_t *)Font16_226, (font_t *)Font16_227,
+	(font_t *)Font16_228, (font_t *)Font16_229, (font_t *)Font16_230, (font_t *)Font16_231,
+	(font_t *)Font16_232, (font_t *)Font16_233, (font_t *)Font16_234, (font_t *)Font16_235,
+	(font_t *)Font16_236, (font_t *)Font16_237, (font_t *)Font16_238, (font_t *)Font16_239,
+	(font_t *)Font16_240, (font_t *)Font16_241, (font_t *)Font16_242, (font_t *)Font16_243,
+	(font_t *)Font16_244, (font_t *)Font16_245, (font_t *)Font16_246, (font_t *)Font16_247,
+	(font_t *)Font16_248, (font_t *)Font16_249, (font_t *)Font16_250, (font_t *)Font16_251,
+	(font_t *)Font16_252, (font_t *)Font16_253, (font_t *)Font16_254, (font_t *)Font16_255
+};
+
+font_head_t Shinonome_Font16 = {
+	"shinonome_font16",
+	0x80,
+	0x00,
+	16,
+	16,
+	Font16,
+	NULL
+};
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/ui/snfont_disp/font9.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/ui/snfont_disp/font9.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/ui/snfont_disp/font9.c	(revision 453)
@@ -0,0 +1,3316 @@
+
+
+#include "fonts.h"
+
+/*
+ *  001
+ */
+static const uint8_t Font9_01[] = {
+	6, 9,
+	1, 9,
+	0x00, //       
+	0x20, //   #   
+	0x20, //   #   
+	0x70, //  ###  
+	0xF8, // ##### 
+	0x70, //  ###  
+	0x20, //   #   
+	0x20, //   #   
+	0x00  //       
+};
+
+/*
+ *  002
+ */
+static const uint8_t Font9_02[] = {
+	6, 9,
+	1, 9,
+	0x54, //  # # #
+	0xA8, // # # # 
+	0x54, //  # # #
+	0xA8, // # # # 
+	0x54, //  # # #
+	0xA8, // # # # 
+	0x54, //  # # #
+	0xA8, // # # # 
+	0x54  //  # # #
+};
+
+/*
+ *  003
+ */
+static const uint8_t Font9_03[] = {
+	6, 9,
+	1, 9,
+	0x00, //       
+	0xA0, // # #   
+	0xE0, // ###   
+	0xA0, // # #   
+	0x38, //   ### 
+	0x10, //    #  
+	0x10, //    #  
+	0x10, //    #  
+	0x00  //       
+};
+
+/*
+ *  004
+ */
+static const uint8_t Font9_04[] = {
+	6, 9,
+	1, 9,
+	0x00, //       
+	0xE0, // ###   
+	0xE0, // ###   
+	0x80, // #     
+	0x38, //   ### 
+	0x38, //   ### 
+	0x20, //   #   
+	0x20, //   #   
+	0x00  //       
+};
+
+/*
+ *  005
+ */
+static const uint8_t Font9_05[] = {
+	6, 9,
+	1, 9,
+	0x00, //       
+	0x60, //  ##   
+	0x80, // #     
+	0x60, //  ##   
+	0x30, //   ##  
+	0x28, //   # # 
+	0x30, //   ##  
+	0x28, //   # # 
+	0x00  //       
+};
+
+/*
+ *  006
+ */
+static const uint8_t Font9_06[] = {
+	6, 9,
+	1, 9,
+	0x00, //       
+	0x80, // #     
+	0x80, // #     
+	0xE0, // ###   
+	0x38, //   ### 
+	0x20, //   #   
+	0x38, //   ### 
+	0x20, //   #   
+	0x00  //       
+};
+
+/*
+ *  007
+ */
+static const uint8_t Font9_07[] = {
+	6, 9,
+	1, 9,
+	0x00, //       
+	0x60, //  ##   
+	0x90, // #  #  
+	0x60, //  ##   
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  008
+ */
+static const uint8_t Font9_08[] = {
+	6, 9,
+	1, 9,
+	0x00, //       
+	0x20, //   #   
+	0x20, //   #   
+	0xF8, // ##### 
+	0x20, //   #   
+	0x20, //   #   
+	0x00, //       
+	0xF8, // ##### 
+	0x00  //       
+};
+
+/*
+ *  009
+ */
+static const uint8_t Font9_09[] = {
+	6, 9,
+	1, 9,
+	0x00, //       
+	0xC0, // ##    
+	0xA0, // # #   
+	0xA0, // # #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x38, //   ### 
+	0x00  //       
+};
+
+/*
+ *  010
+ */
+static const uint8_t Font9_10[] = {
+	6, 9,
+	1, 9,
+	0x00, //       
+	0xA0, // # #   
+	0xA0, // # #   
+	0x40, //  #    
+	0x30, //   ##  
+	0x28, //   # # 
+	0x30, //   ##  
+	0x28, //   # # 
+	0x00  //       
+};
+
+/*
+ *  011
+ */
+static const uint8_t Font9_11[] = {
+	6, 9,
+	1, 9,
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0xE0, // ###   
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  012
+ */
+static const uint8_t Font9_12[] = {
+	6, 9,
+	1, 9,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0xE0, // ###   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20  //   #   
+};
+
+/*
+ *  013
+ */
+static const uint8_t Font9_13[] = {
+	6, 9,
+	1, 9,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x3C, //   ####
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20  //   #   
+};
+
+/*
+ *  014
+ */
+static const uint8_t Font9_14[] = {
+	6, 9,
+	1, 9,
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x3C, //   ####
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+};
+
+/*
+ *  015
+ */
+static const uint8_t Font9_15[] = {
+	6, 9,
+	1, 9,
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0xFC, // ######
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20  //   #   
+};
+
+/*
+ *  016
+ */
+static const uint8_t Font9_16[] = {
+	6, 9,
+	1, 9,
+	0xFC, // ######
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  017
+ */
+static const uint8_t Font9_17[] = {
+	6, 9,
+	1, 9,
+	0x00, //       
+	0x00, //       
+	0xFC, // ######
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  018
+ */
+static const uint8_t Font9_18[] = {
+	6, 9,
+	1, 9,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0xFC, // ######
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  019
+ */
+static const uint8_t Font9_19[] = {
+	6, 9,
+	1, 9,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0xFC, // ######
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  020
+ */
+static const uint8_t Font9_20[] = {
+	6, 9,
+	1, 9,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0xFC  // ######
+};
+
+/*
+ *  021
+ */
+static const uint8_t Font9_21[] = {
+	6, 9,
+	1, 9,
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x3C, //   ####
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20  //   #   
+};
+
+/*
+ *  022
+ */
+static const uint8_t Font9_22[] = {
+	6, 9,
+	1, 9,
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0xE0, // ###   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20  //   #   
+};
+
+/*
+ *  023
+ */
+static const uint8_t Font9_23[] = {
+	6, 9,
+	1, 9,
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0xFC, // ######
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  024
+ */
+static const uint8_t Font9_24[] = {
+	6, 9,
+	1, 9,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0xFC, // ######
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20  //   #   
+};
+
+/*
+ *  025
+ */
+static const uint8_t Font9_25[] = {
+	6, 9,
+	1, 9,
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20, //   #   
+	0x20  //   #   
+};
+
+/*
+ *  026
+ */
+static const uint8_t Font9_26[] = {
+	6, 9,
+	1, 9,
+	0x00, //       
+	0x38, //   ### 
+	0xC0, // ##    
+	0x38, //   ### 
+	0xF8, // ##### 
+	0x00, //       
+	0xF8, // ##### 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  027
+ */
+static const uint8_t Font9_27[] = {
+	6, 9,
+	1, 9,
+	0x00, //       
+	0xE0, // ###   
+	0x18, //    ## 
+	0xE0, // ###   
+	0xF8, // ##### 
+	0x00, //       
+	0xF8, // ##### 
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  028
+ */
+static const uint8_t Font9_28[] = {
+	6, 9,
+	1, 9,
+	0x00, //       
+	0xF8, // ##### 
+	0x50, //  # #  
+	0x50, //  # #  
+	0x50, //  # #  
+	0x58, //  # ## 
+	0x80, // #     
+	0x00, //       
+	0x00  //       
+};
+
+/*
+ *  029
+ */
+static const uint8_t Font9_29[] = {
+	6, 9,
+	1, 9,
+	0x00, //       
+	0x08, //     # 
+	0x10, //    #  
+	0xF8, // ##### 
+	0x20, //   #   
+	0xF8, // ##### 
+	0x40, //  #    
+	0x80, // #     
+	0x00  //       
+};
+
+/*
+ *  030
+ */
+static const uint8_t Font9_30[] = {
+	6, 9,
+	1, 9,
+	0x00, //       
+	0x18, //    ## 
+	0x20, //   #   
+	0xF8, // ##### 
+	0x20, //   #   
+	0x60, //  ##   
+	0xA4, // # #  #
+	0x58, //  # ## 
+	0x00, //       
+};
+
+/*
+ *  031
+ */
+static const uint8_t Font9_31[] = {
+	6, 9,
+	1, 9,
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x20, //   #   
+	0x00, //       
+	0x00, //       
+	0x00, //       
+	0x00  //       
+};
+
+
+/*
+ *  SPACE
+ */
+static const uint8_t Font9_32[] = {
+	5, 9,
+	0, 0
+};
+
+/*
+ *  !
+ */
+static const uint8_t Font9_33[] = {
+	5, 9,
+	1, 9,
+	0x40, //  #   
+	0x40, //  #   
+	0x40, //  #   
+	0x00, //      
+	0x00, //      
+	0x40, //  #   
+	0x00, //      
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '!'
+ */
+static const uint8_t Font9_34[] = {
+	6, 9,
+	1, 9,
+	0x50, //  # # 
+	0x50, //  # # 
+	0x50, //  # # 
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '#'
+ */
+static const uint8_t Font9_35[] = {
+	6, 9,
+	1, 9,
+	0x50, //  # # 
+	0x50, //  # # 
+	0xF8, // #####
+	0x50, //  # # 
+	0xF8, // #####
+	0x50, //  # # 
+	0x50, //  # # 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '$'
+ */
+static const uint8_t Font9_36[] = {
+	6, 9,
+	1, 9,
+	0x20, //   #  
+	0x78, //  ####
+	0xA0, // # #  
+	0x70, //  ### 
+	0x28, //   # #
+	0xF0, // #### 
+	0x20, //   #  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '%'
+ */
+static const uint8_t Font9_37[] = {
+	6, 9,
+	1, 9,
+	0xC0, // ##   
+	0xC8, // ##  #
+	0x10, //    # 
+	0x20, //   #  
+	0x40, //  #   
+	0x98, // #  ##
+	0x18, //    ##
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '&'
+ */
+static const uint8_t Font9_38[] = {
+	6, 9,
+	1, 9,
+	0x60, //  ##  
+	0x90, // #  # 
+	0xA0, // # #  
+	0x20, //  #   
+	0xA8, // # # #
+	0x90, // #  # 
+	0x68, //  ## #
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '''
+ */
+static const uint8_t Font9_39[] = {
+	5, 9,
+	1, 9,
+	0x60, //  ##  
+	0x20, //   #  
+	0x40, //  #   
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '('
+ */
+static const uint8_t Font9_40[] = {
+	5, 9,
+	1, 9,
+	0x10, //    # 
+	0x20, //   #  
+	0x40, //  #   
+	0x40, //  #   
+	0x40, //  #   
+	0x20, //   #  
+	0x10, //    # 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  ')'
+ */
+static const uint8_t Font9_41[] = {
+	5, 9,
+	1, 9,
+	0x40, //  #   
+	0x20, //   #  
+	0x10, //    # 
+	0x10, //    # 
+	0x10, //    # 
+	0x20, //   #  
+	0x40, //  #   
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '*'
+ */
+static const uint8_t Font9_42[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x20, //   #  
+	0xA8, // # # #
+	0x70, //  ### 
+	0xA8, // # # #
+	0x20, //   #  
+	0x00, //      
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '+'
+ */
+static const uint8_t Font9_43[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x20, //   #  
+	0x20, //   #  
+	0xF8, // #####
+	0x20, //   #  
+	0x20, //   #  
+	0x00, //      
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  ','
+ */
+static const uint8_t Font9_44[] = {
+	5, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x60, //  ##  
+	0x20, //   #  
+	0x40, //  #   
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '-'
+ */
+static const uint8_t Font9_45[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0xF8, // #####
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '.'
+ */
+static const uint8_t Font9_46[] = {
+	5, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x60, //  ##  
+	0x60, //  ##  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '/'
+ */
+static const uint8_t Font9_47[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x08, //     #
+	0x10, //    # 
+	0x20, //   #  
+	0x40, //  #   
+	0x80, // #    
+	0x00, //      
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '0'
+ */
+static const uint8_t Font9_48[] = {
+	6, 9,
+	1, 9,
+	0x70, //  ### 
+	0x88, // #   #
+	0x98, // #  ##
+	0xA8, // # # #
+	0xC8, // ##  #
+	0x88, // #   #
+	0x70, //  ### 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '1'
+ */
+static const uint8_t Font9_49[] = {
+	6, 9,
+	1, 9,
+	0x20, //   #  
+	0x60, //  ##  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x70, //  ### 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '2'
+ */
+static const uint8_t Font9_50[] = {
+	6, 9,
+	1, 9,
+	0x70, //  ### 
+	0x88, // #   #
+	0x08, //     #
+	0x10, //    # 
+	0x20, //   #  
+	0x40, //  #   
+	0xF8, // #####
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '3'
+ */
+static const uint8_t Font9_51[] = {
+	6, 9,
+	1, 9,
+	0xF8, // #####
+	0x10, //    # 
+	0x20, //   #  
+	0x10, //    # 
+	0x08, //     #
+	0x88, // #   #
+	0x70, //  ### 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '4'
+ */
+static const uint8_t Font9_52[] = {
+	6, 9,
+	1, 9,
+	0x10, //    # 
+	0x30, //   ## 
+	0x50, //  # # 
+	0x90, // #  # 
+	0xF8, // #####
+	0x10, //    # 
+	0x10, //    # 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '5'
+ */
+static const uint8_t Font9_53[] = {
+	6, 9,
+	1, 9,
+	0xF8, // #####
+	0x80, // #    
+	0xF0, // #### 
+	0x08, //     #
+	0x08, //     #
+	0x88, // #   #
+	0x70, //  ### 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '6'
+ */
+static const uint8_t Font9_54[] = {
+	6, 9,
+	1, 9,
+	0x30, //   ## 
+	0x40, //  #   
+	0x80, // #    
+	0xF0, // #### 
+	0x88, // #   #
+	0x88, // #   #
+	0x70, //  ### 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '7'
+ */
+static const uint8_t Font9_55[] = {
+	6, 9,
+	1, 9,
+	0xF8, // #####
+	0x08, //     #
+	0x10, //    # 
+	0x20, //   #  
+	0x40, //  #   
+	0x40, //  #   
+	0x40, //  #   
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '8'
+ */
+static const uint8_t Font9_56[] = {
+	6, 9,
+	1, 9,
+	0x70, //  ### 
+	0x88, // #   #
+	0x88, // #   #
+	0x70, //  ### 
+	0x88, // #   #
+	0x88, // #   #
+	0x70, //  ### 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '9'
+ */
+static const uint8_t Font9_57[] = {
+	6, 9,
+	1, 9,
+	0x70, //  ### 
+	0x88, // #   #
+	0x88, // #   #
+	0x78, //  ####
+	0x08, //     #
+	0x10, //    # 
+	0x60, //  ##  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  ':'
+ */
+static const uint8_t Font9_58[] = {
+	5, 9,
+	1, 9,
+	0x00, //      
+	0x60, //  ##  
+	0x60, //  ##  
+	0x00, //      
+	0x60, //  ##  
+	0x60, //  ##  
+	0x00, //      
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  ';'
+ */
+static const uint8_t Font9_59[] = {
+	5, 9,
+	1, 9,
+	0x00, //      
+	0x60, //  ##  
+	0x60, //  ##  
+	0x00, //      
+	0x60, //  ##  
+	0x20, //   #  
+	0x40, //  #   
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '<'
+ */
+static const uint8_t Font9_60[] = {
+	6, 9,
+	1, 9,
+	0x10, //    # 
+	0x20, //   #  
+	0x40, //  #   
+	0x80, // #    
+	0x40, //  #   
+	0x20, //   #  
+	0x10, //    # 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '='
+ */
+static const uint8_t Font9_61[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0xF8, // #####
+	0x00, //      
+	0xF8, // #####
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '>'
+ */
+static const uint8_t Font9_62[] = {
+	6, 9,
+	1, 9,
+	0x40, //  #   
+	0x20, //   #  
+	0x10, //    # 
+	0x08, //     #
+	0x10, //    # 
+	0x20, //   #  
+	0x40, //  #   
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '?'
+ */
+static const uint8_t Font9_63[] = {
+	6, 9,
+	1, 9,
+	0x70, //  ### 
+	0x88, // #   #
+	0x08, //     #
+	0x10, //    # 
+	0x20, //   #  
+	0x00, //      
+	0x20, //   #  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '@'
+ */
+static const uint8_t Font9_64[] = {
+	6, 9,
+	1, 9,
+	0x70, //  ### 
+	0x88, // #   #
+	0x08, //     #
+	0x68, //  ## #
+	0xA8, // # # #
+	0xA8, // # # #
+	0x70, //  ### 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'A'
+ */
+static const uint8_t Font9_65[] = {
+	6, 9,
+	1, 9,
+	0x70, //  ### 
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0xF8, // #####
+	0x88, // #   #
+	0x88, // #   #
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'B'
+ */
+static const uint8_t Font9_66[] = {
+	6, 9,
+	1, 9,
+	0xF0, // #### 
+	0x88, // #   #
+	0x88, // #   #
+	0xF0, // #### 
+	0x88, // #   #
+	0x88, // #   #
+	0xF0, // #### 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'C'
+ */
+static const uint8_t Font9_67[] = {
+	6, 9,
+	1, 9,
+	0x70, //  ### 
+	0x88, // #   #
+	0x80, // #    
+	0x80, // #    
+	0x80, // #    
+	0x88, // #   #
+	0x70, //  ### 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'D'
+ */
+static const uint8_t Font9_68[] = {
+	6, 9,
+	1, 9,
+	0xE0, // ###  
+	0x90, // #  # 
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0x90, // #  # 
+	0xE0, // ###  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'E'
+ */
+static const uint8_t Font9_69[] = {
+	6, 9,
+	1, 9,
+	0xF8, // #####
+	0x80, // #    
+	0x80, // #    
+	0xF0, // #### 
+	0x80, // #    
+	0x80, // #    
+	0xF8, // #####
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'F'
+ */
+static const uint8_t Font9_70[] = {
+	6, 9,
+	1, 9,
+	0xF8, // #####
+	0x80, // #    
+	0x80, // #    
+	0xF0, // #### 
+	0x80, // #    
+	0x80, // #    
+	0x80, // #    
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'G'
+ */
+static const uint8_t Font9_71[] = {
+	6, 9,
+	1, 9,
+	0x70, //  ### 
+	0x88, // #   #
+	0x80, // #    
+	0xB8, // # ###
+	0x88, // #   #
+	0x88, // #   #
+	0x78, //  ####
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'H'
+ */
+static const uint8_t Font9_72[] = {
+	6, 9,
+	1, 9,
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0xF8, // #####
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'I'
+ */
+static const uint8_t Font9_73[] = {
+	5, 9,
+	1, 9,
+	0x70, //  ### 
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x70, //  ### 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'J'
+ */
+static const uint8_t Font9_74[] = {
+	6, 9,
+	1, 9,
+	0x38, //   ###
+	0x10, //    # 
+	0x10, //    # 
+	0x10, //    # 
+	0x10, //    # 
+	0x90, // #  # 
+	0x60, //  ##  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'K'
+ */
+static const uint8_t Font9_75[] = {
+	6, 9,
+	1, 9,
+	0x88, // #   #
+	0x90, // #  # 
+	0xA0, // # #  
+	0xC0, // ##   
+	0xA0, // # #  
+	0x98, // #  # 
+	0x88, // #   #
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'L'
+ */
+static const uint8_t Font9_76[] = {
+	6, 9,
+	1, 9,
+	0x80, // #    
+	0x80, // #    
+	0x80, // #    
+	0x80, // #    
+	0x80, // #    
+	0x80, // #    
+	0xF8, // #####
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'M'
+ */
+static const uint8_t Font9_77[] = {
+	6, 9,
+	1, 9,
+	0x88, // #   #
+	0xD8, // ## ##
+	0xA8, // # # #
+	0xA8, // # # #
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'N'
+ */
+static const uint8_t Font9_78[] = {
+	6, 9,
+	1, 9,
+	0x88, // #   #
+	0x88, // #   #
+	0xC8, // ##  #
+	0xA8, // # # #
+	0x98, // #  ##
+	0x88, // #   #
+	0x88, // #   #
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'O'
+ */
+static const uint8_t Font9_79[] = {
+	6, 9,
+	1, 9,
+	0x70, //  ### 
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0x70, //  ### 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'P'
+ */
+static const uint8_t Font9_80[] = {
+	6, 9,
+	1, 9,
+	0xF0, // #### 
+	0x88, // #   #
+	0x88, // #   #
+	0xF0, // #### 
+	0x80, // #    
+	0x80, // #    
+	0x80, // #    
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'Q'
+ */
+static const uint8_t Font9_81[] = {
+	6, 9,
+	1, 9,
+	0x70, //  ### 
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0xA8, // # # #
+	0x90, // #  # 
+	0x68, //  ## #
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'R'
+ */
+static const uint8_t Font9_82[] = {
+	6, 9,
+	1, 9,
+	0xF0, // #### 
+	0x88, // #   #
+	0x88, // #   #
+	0xF0, // #### 
+	0xA0, // # #  
+	0x90, // #  # 
+	0x88, // #   #
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'S'
+ */
+static const uint8_t Font9_83[] = {
+	6, 9,
+	1, 9,
+	0x78, //  ####
+	0x80, // #    
+	0x80, // #    
+	0x70, //  ### 
+	0x08, //     #
+	0x08, //     #
+	0xF0, // #### 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'T'
+ */
+static const uint8_t Font9_84[] = {
+	6, 9,
+	1, 9,
+	0xF8, // #####
+	0x20, //   # 
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'U'
+ */
+static const uint8_t Font9_85[] = {
+	6, 9,
+	1, 9,
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0x70, //  ### 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'V'
+ */
+static const uint8_t Font9_86[] = {
+	6, 9,
+	1, 9,
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0x48, //  # # 
+	0x20, //   #  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'W'
+ */
+static const uint8_t Font9_87[] = {
+	6, 9,
+	1, 9,
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0xA8, // # # #
+	0xA8, // # # #
+	0xA8, // # # #
+	0x50, //  # # 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'X'
+ */
+static const uint8_t Font9_88[] = {
+	6, 9,
+	1, 9,
+	0x88, // #   #
+	0x88, // #   #
+	0x50, //  # # 
+	0x20, //   #  
+	0x50, //  # # 
+	0x88, // #   #
+	0x88, // #   #
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'Y'
+ */
+static const uint8_t Font9_89[] = {
+	6, 9,
+	1, 9,
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0x50, //  # # 
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'Z'
+ */
+static const uint8_t Font9_90[] = {
+	6, 9,
+	1, 9,
+	0xF8, // #####
+	0x08, //     #
+	0x10, //    # 
+	0x20, //   #  
+	0x40, //  #   
+	0x80, // #    
+	0xF8, // #####
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '['
+ */
+static const uint8_t Font9_91[] = {
+	5, 9,
+	1, 9,
+	0x70, //  ### 
+	0x40, //  #   
+	0x40, //  #   
+	0x40, //  #   
+	0x40, //  #   
+	0x40, //  #   
+	0x70, //  ### 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '\'
+ */
+static const uint8_t Font9_92[] = {
+	6, 9,
+	1, 9,
+	0x88, // #   #
+	0x50, //  # # 
+	0xF8, // #####
+	0x20, //   #  
+	0xF8, // #####
+	0x20, //   #  
+	0x20, //   #  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  ']'
+ */
+static const uint8_t Font9_93[] = {
+	5, 9,
+	1, 9,
+	0x70, //  ### 
+	0x10, //    # 
+	0x10, //    # 
+	0x10, //    # 
+	0x10, //    # 
+	0x10, //    # 
+	0x70, //  ### 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '^'
+ */
+static const uint8_t Font9_94[] = {
+	6, 9,
+	1, 9,
+	0x20, //   #  
+	0x50, //  # # 
+	0x88, // #   #
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '_'
+ */
+static const uint8_t Font9_95[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0xF8  // #####
+};
+
+/*
+ *  '''
+ */
+static const uint8_t Font9_96[] = {
+	5, 9,
+	1, 9,
+	0x40, //  #   
+	0x20, //   #  
+	0x10, //    # 
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'a'
+ */
+static const uint8_t Font9_97[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x70, //  ### 
+	0x08, //     #
+	0x78, //  ####
+	0x88, // #   #
+	0x78, //  ####
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'b'
+ */
+static const uint8_t Font9_98[] = {
+	6, 9,
+	1, 9,
+	0x80, // #    
+	0x80, // #    
+	0xB0, // # ## 
+	0xC8, // ##  #
+	0x88, // #   #
+	0x88, // #   #
+	0xF0, // #### 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'c'
+ */
+static const uint8_t Font9_99[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x70, //  ### 
+	0x80, // #    
+	0x80, // #    
+	0x88, // #   #
+	0x70, //  ### 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'd'
+ */
+static const uint8_t Font9_100[] = {
+	6, 9,
+	1, 9,
+	0x08, //     #
+	0x08, //     #
+	0x68, //  ## #
+	0x98, // #  ##
+	0x88, // #   #
+	0x88, // #   #
+	0x78, //  ####
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'e'
+ */
+static const uint8_t Font9_101[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x70, //  ### 
+	0x88, // #   #
+	0xF8, // #####
+	0x80, // #    
+	0x70, //  ### 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'f'
+ */
+static const uint8_t Font9_102[] = {
+	6, 9,
+	1, 9,
+	0x30, //   ## 
+	0x48, //  #  #
+	0x40, //  #   
+	0xE0, // ### 
+	0x40, //  #   
+	0x40, //  #   
+	0x40, //  #   
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'g'
+ */
+static const uint8_t Font9_103[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x78, //  ####
+	0x88, // #   #
+	0x88, // #   #
+	0x78, //  ####
+	0x08, //     #
+	0x08, //     #
+	0x70, //  ### 
+	0x00  //      
+};
+
+/*
+ *  'h'
+ */
+static const uint8_t Font9_104[] = {
+	6, 9,
+	1, 9,
+	0x80, // #    
+	0x80, // #    
+	0xB0, // # ## 
+	0xC8, // ##  #
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'i'
+ */
+static const uint8_t Font9_105[] = {
+	5, 9,
+	1, 9,
+	0x20, //   #  
+	0x00, //      
+	0x60, //  ##  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x70, //  ### 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'j'
+ */
+static const uint8_t Font9_106[] = {
+	5, 9,
+	1, 9,
+	0x20, //   #  
+	0x00, //      
+	0x30, //   ## 
+	0x10, //    # 
+	0x10, //    # 
+	0x10, //    # 
+	0x90, // #  # 
+	0x60, //  ##  
+	0x00  //      
+};
+
+/*
+ *  'k'
+ */
+static const uint8_t Font9_107[] = {
+	5, 9,
+	1, 9,
+	0x80, // #    
+	0x80, // #    
+	0x90, // #  # 
+	0xA0, // # #  
+	0xC0, // ##   
+	0xA0, // # #  
+	0x90, // #  # 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'l'
+ */
+static const uint8_t Font9_108[] = {
+	5, 9,
+	1, 9,
+	0x60, //  ##  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x70, //  ### 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'm'
+ */
+static const uint8_t Font9_109[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0xD0, // ## # 
+	0xA8, // # # #
+	0xA8, // # # #
+	0x98, // #   #
+	0x98, // #   #
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'n'
+ */
+static const uint8_t Font9_110[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0xB0, // # ## 
+	0xC8, // ##  #
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'o'
+ */
+static const uint8_t Font9_111[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x70, //  ### 
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0x70, //  ### 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'p'
+ */
+static const uint8_t Font9_112[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0xF0, // #### 
+	0x88, // #   #
+	0xF0, // #### 
+	0x80, // #    
+	0x80, // #    
+	0x80, // #    
+	0x00  //      
+};
+
+/*
+ *  'q'
+ */
+static const uint8_t Font9_113[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x68, //  ## #
+	0x98, // #  ##
+	0x78, //  ####
+	0x08, //     #
+	0x08, //     #
+	0x08, //     #
+	0x00  //      
+};
+
+/*
+ *  'r'
+ */
+static const uint8_t Font9_114[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0xB0, // # ##
+	0xC8, // ##  #
+	0x80, // #    
+	0x80, // #    
+	0x80, // #    
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  's'
+ */
+static const uint8_t Font9_115[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x70, //  ### 
+	0x80, // #    
+	0x70, //  ### 
+	0x08, //     #
+	0xF0, // #### 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  't'
+ */
+static const uint8_t Font9_116[] = {
+	6, 9,
+	1, 9,
+	0x40, //  #   
+	0x40, //  #   
+	0xE0, // ###  
+	0x40, //  #   
+	0x40, //  #   
+	0x48, //  #  #
+	0x30, //   ## 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'u'
+ */
+static const uint8_t Font9_117[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0x98, // #  ##
+	0x68, //  ## #
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'v'
+ */
+static const uint8_t Font9_118[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0x50, //  # # 
+	0x20, //   #  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'w'
+ */
+static const uint8_t Font9_119[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x88, // #   #
+	0x88, // #   #
+	0xA8, // # # #
+	0xA8, // # # #
+	0x50, //  # # 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'x'
+ */
+static const uint8_t Font9_120[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x88, // #   #
+	0x50, //  # # 
+	0x20, //   #  
+	0x50, //  # # 
+	0x88, // #   #
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'y'
+ */
+static const uint8_t Font9_121[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x88, // #   #
+	0x88, // #   #
+	0x78, //  ####
+	0x08, //     #
+	0x08, //     #
+	0x70, //  ### 
+	0x00  //      
+};
+
+/*
+ *  'z'
+ */
+static const uint8_t Font9_122[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0xF8, // #####
+	0x10, //    # 
+	0x20, //   #  
+	0x40, //  #   
+	0xF8, // #####
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '{'
+ */
+static const uint8_t Font9_123[] = {
+	5, 9,
+	1, 9,
+	0x10, //    # 
+	0x20, //   #  
+	0x20, //   #  
+	0x40, //  #   
+	0x20, //   #  
+	0x20, //   #  
+	0x10, //    # 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '|'
+ */
+static const uint8_t Font9_124[] = {
+	5, 9,
+	1, 9,
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '}'
+ */
+static const uint8_t Font9_125[] = {
+	5, 9,
+	1, 9,
+	0x40, //  #   
+	0x20, //   #  
+	0x20, //   #  
+	0x10, //    # 
+	0x20, //   #  
+	0x20, //   #  
+	0x40, //  #   
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '->'
+ */
+static const uint8_t Font9_126[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x20, //   #  
+	0x10, //    # 
+	0xF8, // #####
+	0x10, //    # 
+	0x20, //   #  
+	0x00, //      
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '<-'
+ */
+static const uint8_t Font9_127[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x20, //   #  
+	0x40, //  #   
+	0xF8, // #####
+	0x40, //  #   
+	0x20, //   #  
+	0x00, //      
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  yohaku
+ */
+static const uint8_t Font9_160[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  syuryou
+ */
+static const uint8_t Font9_161[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0xE0, // ###  
+	0xA0, // # #  
+	0xE0, // ###  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  kakko
+ */
+static const uint8_t Font9_162[] = {
+	6, 9,
+	1, 9,
+	0x38, //   ###
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  kakko tojiru
+ */
+static const uint8_t Font9_163[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0xE0, // ###  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  kutouten
+ */
+static const uint8_t Font9_164[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x80, // #    
+	0x40, //  #   
+	0x20, //   #  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  cyuten
+ */
+static const uint8_t Font9_165[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x60, //  ##  
+	0x60, //  ##  
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'WO'
+ */
+static const uint8_t Font9_166[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0xF8, // #####
+	0x08, //     #
+	0xF8, // #####
+	0x08, //     #
+	0x10, //    # 
+	0x20, //   #  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'aa'
+ */
+static const uint8_t Font9_167[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0xF8, // #####
+	0x08, //     #
+	0x30, //   ## 
+	0x20, //   #  
+	0x40, //  #   
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'ii'
+ */
+static const uint8_t Font9_168[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x10, //    # 
+	0x20, //   #  
+	0x60, //  ##  
+	0xA0, // # #  
+	0x20, //   #  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'uu'
+ */
+static const uint8_t Font9_169[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x20, //   #  
+	0xF8, // #####
+	0x88, // #   #
+	0x08, //     #
+	0x30, //   ## 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'ee'
+ */
+static const uint8_t Font9_170[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0xF8, // #####
+	0x20, //   #  
+	0x20, //   #  
+	0xF8, // #####
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'oo'
+ */
+static const uint8_t Font9_171[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x10, //    # 
+	0xF8, // #####
+	0x30, //   ## 
+	0xA0, //  # # 
+	0x90, // #  # 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'ya'
+ */
+static const uint8_t Font9_172[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x40, //  #   
+	0xF8, // #####
+	0x48, //  #  #
+	0x50, //  # # 
+	0x40, //  #   
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'yu'
+ */
+static const uint8_t Font9_173[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x70, //  ### 
+	0x10, //    # 
+	0x10, //    # 
+	0xF8, // #####
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'yo'
+ */
+static const uint8_t Font9_174[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0xF0, // #### 
+	0x10, //    # 
+	0xF0, // #### 
+	0x10, //    # 
+	0xF0, // #### 
+	0x00, //      
+	0x00  //      
+};
+
+
+/*
+ *  'tu'
+ */
+static const uint8_t Font9_175[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0xA8, // # # #
+	0xA8, // # # #
+	0x08, //     #
+	0x30, //   ## 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  '-'
+ */
+static const uint8_t Font9_176[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0xF8, // #####
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'AA'
+ */
+static const uint8_t Font9_177[] = {
+	6, 9,
+	1, 9,
+	0xF8, // #####
+	0x08, //     #
+	0x28, //   # #
+	0x30, //   ## 
+	0x20, //   #  
+	0x20, //   #  
+	0x40, //  #   
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'II'
+ */
+static const uint8_t Font9_178[] = {
+	6, 9,
+	1, 9,
+	0x08, //     #
+	0x10, //    # 
+	0x20, //   #  
+	0x60, //  ##  
+	0xA0, // # #  
+	0x20, //   #  
+	0x20, //   #  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'UU'
+ */
+static const uint8_t Font9_179[] = {
+	6, 9,
+	1, 9,
+	0x20, //   #  
+	0xF8, // #####
+	0x88, // #   #
+	0x88, // #   #
+	0x08, //     #
+	0x10, //    # 
+	0x20, //   #  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'EE'
+ */
+static const uint8_t Font9_180[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0xF8, // #####
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0xF8, // #####
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'OO'
+ */
+static const uint8_t Font9_181[] = {
+	6, 9,
+	1, 9,
+	0x10, //    # 
+	0xF8, // #####
+	0x10, //    # 
+	0x30, //   ## 
+	0x50, //  # # 
+	0x90, // #  # 
+	0x10, //    # 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'KA'
+ */
+static const uint8_t Font9_182[] = {
+	6, 9,
+	1, 9,
+	0x40, //  #   
+	0xF8, // #####
+	0x48, //  #  #
+	0x48, //  #  #
+	0x48, //  #  #
+	0x48, //  #  #
+	0x90, // #  # 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'KI'
+ */
+static const uint8_t Font9_183[] = {
+	6, 9,
+	1, 9,
+	0x20, //   #  
+	0xF8, // #####
+	0x20, //   #  
+	0xF8, // #####
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'KU'
+ */
+static const uint8_t Font9_184[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x78, //  ####
+	0x48, //  #  #
+	0x88, // #   #
+	0x08, //     #
+	0x10, //    # 
+	0x60, //  ##  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'KE'
+ */
+static const uint8_t Font9_185[] = {
+	6, 9,
+	1, 9,
+	0x40, //  #   
+	0x78, //  ####
+	0x90, // #  # 
+	0x10, //    # 
+	0x10, //    # 
+	0x10, //    # 
+	0x20, //   #  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'KO'
+ */
+static const uint8_t Font9_186[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0xF8, // #####
+	0x08, //     #
+	0x08, //     #
+	0x08, //     #
+	0x08, //     #
+	0xF8, // #####
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'SA'
+ */
+static const uint8_t Font9_187[] = {
+	6, 9,
+	1, 9,
+	0x50, //  # # 
+	0xF8, // #####
+	0x50, //  # # 
+	0x50, //  # # 
+	0x10, //    # 
+	0x20, //   #  
+	0x40, //  #   
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'SI'
+ */
+static const uint8_t Font9_188[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0xC0, // ##   
+	0x08, //     #
+	0xC8, // ##  #
+	0x08, //     #
+	0x10, //    # 
+	0xE0, // ###  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'SU'
+ */
+static const uint8_t Font9_189[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0xF8, // #####
+	0x08, //     #
+	0x10, //    # 
+	0x20, //   #  
+	0x50, //  # # 
+	0x88, // #   #
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'SE'
+ */
+static const uint8_t Font9_190[] = {
+	6, 9,
+	1, 9,
+	0x40, //  #   
+	0xF8, // #####
+	0x48, //  #  #
+	0x50, //  # # 
+	0x40, //  #   
+	0x40, //  #   
+	0x38, //   ###
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'SO'
+ */
+static const uint8_t Font9_191[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x88, // #   #
+	0x88, // #   #
+	0x48, //  #  #
+	0x08, //     #
+	0x10, //    # 
+	0x60, //  ##  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'TA'
+ */
+static const uint8_t Font9_192[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x78, //  ####
+	0x48, //  #  #
+	0xA8, // # # #
+	0x18, //    ##
+	0x10, //    # 
+	0x60, //  ##  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'TI'
+ */
+static const uint8_t Font9_193[] = {
+	6, 9,
+	1, 9,
+	0x10, //    # 
+	0xE0, // ###  
+	0x20, //   #  
+	0xF8, // #####
+	0x20, //   #  
+	0x20, //   #  
+	0x40, //  #   
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'TU'
+ */
+static const uint8_t Font9_194[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0xA8, // # # #
+	0xA8, // # # #
+	0xA8, // # # #
+	0x08, //     #
+	0x10, //    # 
+	0x20, //   #  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'TE'
+ */
+static const uint8_t Font9_195[] = {
+	6, 9,
+	1, 9,
+	0x70, //  ### 
+	0x00, //      
+	0xF8, // #####
+	0x20, //   #  
+	0x20, //   #  
+	0x20, //   #  
+	0x40, //  #   
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'TO'
+ */
+static const uint8_t Font9_196[] = {
+	6, 9,
+	1, 9,
+	0x40, //  #   
+	0x40, //  #   
+	0x40, //  #   
+	0x60, //  ##  
+	0x50, //  # # 
+	0x40, //  #   
+	0x40, //  #   
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'NA'
+ */
+static const uint8_t Font9_197[] = {
+	6, 9,
+	1, 9,
+	0x20, //   #  
+	0x20, //   #  
+	0xF8, // #####
+	0x20, //   #  
+	0x20, //   #  
+	0x40, //  #   
+	0x80, // #    
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'NI'
+ */
+static const uint8_t Font9_198[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x70, //  ### 
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0xF8, // #####
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'NU'
+ */
+static const uint8_t Font9_199[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0xF8, // #####
+	0x08, //     #
+	0x50, //  # # 
+	0x40, //   #  
+	0x50, //  # # 
+	0x80, // #    
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'NE'
+ */
+static const uint8_t Font9_200[] = {
+	6, 9,
+	1, 9,
+	0x20, //   #  
+	0xF8, // #####
+	0x10, //    # 
+	0x20, //   #  
+	0x70, //  ### 
+	0xA8, // # # #
+	0x20, //   #  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'NO'
+ */
+static const uint8_t Font9_201[] = {
+	6, 9,
+	1, 9,
+	0x10, //    # 
+	0x10, //    # 
+	0x10, //    # 
+	0x10, //    # 
+	0x10, //    # 
+	0x20, //   #  
+	0x40, //  #   
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'HA'
+ */
+static const uint8_t Font9_202[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x20, //   #  
+	0x10, //    # 
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'HI'
+ */
+static const uint8_t Font9_203[] = {
+	6, 9,
+	1, 9,
+	0x80, // #    
+	0x80, // #    
+	0xF8, // #####
+	0x80, // #    
+	0x80, // #    
+	0x80, // #    
+	0x78, //  ####
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'HU'
+ */
+static const uint8_t Font9_204[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0xF8, // #####
+	0x08, //     #
+	0x08, //     #
+	0x08, //     #
+	0x10, //    # 
+	0x60, //  ##  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'HE'
+ */
+static const uint8_t Font9_205[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x40, //  #   
+	0xA0, // # #  
+	0x10, //    # 
+	0x08, //     #
+	0x08, //     #
+	0x00, //      
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'HO'
+ */
+static const uint8_t Font9_206[] = {
+	6, 9,
+	1, 9,
+	0x20, //   #  
+	0xF8, // #####
+	0x20, //   #  
+	0x20, //   #  
+	0xA8, // # # #
+	0xA8, // # # #
+	0x20, //   #  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'MA'
+ */
+static const uint8_t Font9_207[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0xF8, // #####
+	0x08, //     #
+	0x08, //     #
+	0x50, //  # # 
+	0x20, //   #  
+	0x10, //    # 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'MI'
+ */
+static const uint8_t Font9_208[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x70, //  ### 
+	0x00, //      
+	0x70, //  ### 
+	0x00, //      
+	0x70, //  ### 
+	0x08, //     #
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'MU'
+ */
+static const uint8_t Font9_209[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x20, //   #  
+	0x40, //  #   
+	0x80, // #    
+	0x88, // #   #
+	0xF8, // #####
+	0x08, //     #
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'ME'
+ */
+static const uint8_t Font9_210[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x08, //     #
+	0x08, //     #
+	0x50, //  # # 
+	0x20, //   #  
+	0x50, //  # # 
+	0x80, // #    
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'MO'
+ */
+static const uint8_t Font9_211[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0xF8, // #####
+	0x40, //  #   
+	0xF8, // #####
+	0x40, //  #   
+	0x40, //  #   
+	0x38, //   ###
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'YA'
+ */
+static const uint8_t Font9_212[] = {
+	6, 9,
+	1, 9,
+	0x40, //  #   
+	0x40, //  #   
+	0xF8, // #####
+	0x48, //  #  #
+	0x50, //  # # 
+	0x40, //  #   
+	0x40, //  #   
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'YU'
+ */
+static const uint8_t Font9_213[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x70, //  ### 
+	0x10, //    # 
+	0x10, //    # 
+	0x10, //    # 
+	0x10, //    # 
+	0xF8, // #####
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'YO'
+ */
+static const uint8_t Font9_214[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0xF8, // ######
+	0x08, //      #
+	0xF8, // ######
+	0x08, //      #
+	0x08, //      #
+	0xF8, // ######
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'RA'
+ */
+static const uint8_t Font9_215[] = {
+	6, 9,
+	1, 9,
+	0x70, //  ### 
+	0x00, //      
+	0xF8, // #####
+	0x08, //     #
+	0x08, //     #
+	0x10, //    # 
+	0x20, //   #  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'RI'
+ */
+static const uint8_t Font9_216[] = {
+	6, 9,
+	1, 9,
+	0x90, // #  # 
+	0x90, // #  # 
+	0x90, // #  # 
+	0x90, // #  # 
+	0x10, //    # 
+	0x20, //   #  
+	0x40, //  #   
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'RU'
+ */
+static const uint8_t Font9_217[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x20, //   #  
+	0xA0, // # #  
+	0xA0, // # #  
+	0xA8, // # # #
+	0xA8, // # # #
+	0xB0, // # ## 
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'RE'
+ */
+static const uint8_t Font9_218[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0x80, // #    
+	0x80, // #    
+	0x88, // #   #
+	0x90, // #  # 
+	0xA0, // # #  
+	0xC0, // ##   
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'RO'
+ */
+static const uint8_t Font9_219[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0xF8, // #####
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0x88, // #   #
+	0xF8, // #####
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'WA'
+ */
+static const uint8_t Font9_220[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0xF8, // #####
+	0x88, // #   #
+	0x88, // #   #
+	0x08, //     #
+	0x10, //    # 
+	0x20, //   #  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  'NN'
+ */
+static const uint8_t Font9_221[] = {
+	6, 9,
+	1, 9,
+	0x00, //      
+	0xC0, // ##   
+	0x00, //      
+	0x08, //     #
+	0x08, //     #
+	0x10, //    # 
+	0xE0, // ###  
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  dakuten
+ */
+static const uint8_t Font9_222[] = {
+	6, 9,
+	1, 9,
+	0x20, //   #  
+	0x90, // #  # 
+	0x40, //  #   
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00  //      
+};
+
+/*
+ *  maru
+ */
+static const uint8_t Font9_223[] = {
+	6, 9,
+	1, 9,
+	0xE0, // ###  
+	0xA0, // # #  
+	0xE0, // ###  
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00, //      
+	0x00  //      
+};
+
+
+
+static const font_t *Font9[] = {
+	(font_t *)Font9_32,  (font_t *)Font9_01,  (font_t *)Font9_02,  (font_t *)Font9_03,
+	(font_t *)Font9_04,  (font_t *)Font9_05,  (font_t *)Font9_06,  (font_t *)Font9_07,
+	(font_t *)Font9_08,  (font_t *)Font9_09,  (font_t *)Font9_10,  (font_t *)Font9_11,
+	(font_t *)Font9_12,  (font_t *)Font9_13,  (font_t *)Font9_14,  (font_t *)Font9_15,
+	(font_t *)Font9_16,  (font_t *)Font9_17,  (font_t *)Font9_18,  (font_t *)Font9_19,
+	(font_t *)Font9_20,  (font_t *)Font9_21,  (font_t *)Font9_22,  (font_t *)Font9_23,
+	(font_t *)Font9_24,  (font_t *)Font9_25,  (font_t *)Font9_26,  (font_t *)Font9_27,
+	(font_t *)Font9_28,  (font_t *)Font9_29,  (font_t *)Font9_30,  (font_t *)Font9_31,
+	(font_t *)Font9_32,  (font_t *)Font9_33,  (font_t *)Font9_34,  (font_t *)Font9_35,
+	(font_t *)Font9_36,  (font_t *)Font9_37,  (font_t *)Font9_38,  (font_t *)Font9_39,
+	(font_t *)Font9_40,  (font_t *)Font9_41,  (font_t *)Font9_42,  (font_t *)Font9_43,
+	(font_t *)Font9_44,  (font_t *)Font9_45,  (font_t *)Font9_46,  (font_t *)Font9_47,
+	(font_t *)Font9_48,  (font_t *)Font9_49,  (font_t *)Font9_50,  (font_t *)Font9_51,
+	(font_t *)Font9_52,  (font_t *)Font9_53,  (font_t *)Font9_54,  (font_t *)Font9_55,
+	(font_t *)Font9_56,  (font_t *)Font9_57,  (font_t *)Font9_58,  (font_t *)Font9_59,
+	(font_t *)Font9_60,  (font_t *)Font9_61,  (font_t *)Font9_62,  (font_t *)Font9_63,
+	(font_t *)Font9_64,  (font_t *)Font9_65,  (font_t *)Font9_66,  (font_t *)Font9_67,
+	(font_t *)Font9_68,  (font_t *)Font9_69,  (font_t *)Font9_70,  (font_t *)Font9_71,
+	(font_t *)Font9_72,  (font_t *)Font9_73,  (font_t *)Font9_74,  (font_t *)Font9_75,
+	(font_t *)Font9_76,  (font_t *)Font9_77,  (font_t *)Font9_78,  (font_t *)Font9_79,
+	(font_t *)Font9_80,  (font_t *)Font9_81,  (font_t *)Font9_82,  (font_t *)Font9_83,
+	(font_t *)Font9_84,  (font_t *)Font9_85,  (font_t *)Font9_86,  (font_t *)Font9_87,
+	(font_t *)Font9_88,  (font_t *)Font9_89,  (font_t *)Font9_90,  (font_t *)Font9_91,
+	(font_t *)Font9_92,  (font_t *)Font9_93,  (font_t *)Font9_94,  (font_t *)Font9_95,
+	(font_t *)Font9_96,  (font_t *)Font9_97,  (font_t *)Font9_98,  (font_t *)Font9_99,
+	(font_t *)Font9_100, (font_t *)Font9_101, (font_t *)Font9_102, (font_t *)Font9_103,
+	(font_t *)Font9_104, (font_t *)Font9_105, (font_t *)Font9_106, (font_t *)Font9_107,
+	(font_t *)Font9_108, (font_t *)Font9_109, (font_t *)Font9_110, (font_t *)Font9_111,
+	(font_t *)Font9_112, (font_t *)Font9_113, (font_t *)Font9_114, (font_t *)Font9_115,
+	(font_t *)Font9_116, (font_t *)Font9_117, (font_t *)Font9_118, (font_t *)Font9_119,
+	(font_t *)Font9_120, (font_t *)Font9_121, (font_t *)Font9_122, (font_t *)Font9_123,
+	(font_t *)Font9_124, (font_t *)Font9_125, (font_t *)Font9_126, (font_t *)Font9_127,
+
+	0,                    0,                    0,                    0,
+	0,                    0,                    0,                    0,
+	0,                    0,                    0,                    0,
+	0,                    0,                    0,                    0,
+	0,                    0,                    0,                    0,
+	0,                    0,                    0,                    0,
+	0,                    0,                    0,                    0,
+	0,                    0,                    0,                    0,
+	(font_t *)Font9_160, (font_t *)Font9_161, (font_t *)Font9_162, (font_t *)Font9_163,
+	(font_t *)Font9_164, (font_t *)Font9_165, (font_t *)Font9_166, (font_t *)Font9_167,
+	(font_t *)Font9_168, (font_t *)Font9_169, (font_t *)Font9_170, (font_t *)Font9_171,
+	(font_t *)Font9_172, (font_t *)Font9_173, (font_t *)Font9_174, (font_t *)Font9_175,
+	(font_t *)Font9_176, (font_t *)Font9_177, (font_t *)Font9_178, (font_t *)Font9_179,
+	(font_t *)Font9_180, (font_t *)Font9_181, (font_t *)Font9_182, (font_t *)Font9_183,
+	(font_t *)Font9_184, (font_t *)Font9_185, (font_t *)Font9_186, (font_t *)Font9_187,
+	(font_t *)Font9_188, (font_t *)Font9_189, (font_t *)Font9_190, (font_t *)Font9_191,
+	(font_t *)Font9_192, (font_t *)Font9_193, (font_t *)Font9_194, (font_t *)Font9_195,
+	(font_t *)Font9_196, (font_t *)Font9_197, (font_t *)Font9_198, (font_t *)Font9_199,
+	(font_t *)Font9_200, (font_t *)Font9_201, (font_t *)Font9_202, (font_t *)Font9_203,
+	(font_t *)Font9_204, (font_t *)Font9_205, (font_t *)Font9_206, (font_t *)Font9_207,
+	(font_t *)Font9_208, (font_t *)Font9_209, (font_t *)Font9_210, (font_t *)Font9_211,
+	(font_t *)Font9_212, (font_t *)Font9_213, (font_t *)Font9_214, (font_t *)Font9_215,
+	(font_t *)Font9_216, (font_t *)Font9_217, (font_t *)Font9_218, (font_t *)Font9_219,
+	(font_t *)Font9_220, (font_t *)Font9_221, (font_t *)Font9_222, (font_t *)Font9_223,
+};
+
+font_head_t Embedded_Font9 = {
+	"embedded_font9",
+	0x00,
+	0x00,
+	6,
+	9,
+	Font9,
+	NULL
+};
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/ui/snfont_disp/fonts.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/ui/snfont_disp/fonts.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/ui/snfont_disp/fonts.h	(revision 453)
@@ -0,0 +1,110 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/*
+ *  FONTのヘッダファイル
+ */
+
+#ifndef _FONTS_H_
+#define _FONTS_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include <t_stddef.h>
+
+#define NUM_FONTS   224
+
+#ifndef TOPPERS_MACRO_ONLY
+
+/*
+ *  FONT構造体定義
+ */
+typedef struct _font_s {
+	uint8_t     width;
+	uint8_t     height;
+	uint8_t     stride;
+	uint8_t     iheight;
+	uint8_t     image[8];
+} font_t;
+
+/*
+ *  FONTヘッダ構造体定義
+ */
+typedef struct _font_head_s {
+	const char  font_name[32];
+	uint8_t     file_attribute;
+	uint8_t     font_attribute;
+	uint8_t     font_width;
+	uint8_t     font_height;
+	const font_t **font_table;
+	void        *pdata;
+} font_head_t;
+
+typedef struct font_file_head_s {
+	char           magic[4];
+	char           name[32];
+	unsigned int   fsize;
+	unsigned int   csize;
+	unsigned int   isize;
+	unsigned int   off_cnv_table1;
+	unsigned int   siz_cnv_table1;
+	unsigned int   off_cnv_table2;
+	unsigned int   siz_cnv_table2;
+	unsigned int   off_cnv_table3;
+	unsigned int   siz_cnv_table3;
+	unsigned int   off_2byte_font;
+	unsigned int   siz_2byte_font;
+	unsigned int   off_3byte_font;
+	unsigned int   siz_3byte_font;
+} font_file_head_t;
+
+extern font_head_t Embedded_Font9;
+extern font_head_t Shinonome_Font12;
+extern font_head_t Shinonome_Font16;
+
+
+#endif /* TOPPERS_MACRO_ONLY */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/ui/snfont_disp/glcd_disp.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/ui/snfont_disp/glcd_disp.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/ui/snfont_disp/glcd_disp.c	(revision 453)
@@ -0,0 +1,1276 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+/* 
+ *  GRAPHIC-LCDテキスト表示プログラムの本体
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <target_syssvc.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#ifndef NOT_USEFILFONT
+#include "fcntl.h"
+#endif
+#include "glcd_disp.h"
+
+/*
+ *  東雲漢字のイメージデータは以下のファイルにある
+ *  東雲フォントを使用する場合は、以下のフォントデータを
+ *  デフォルトドライブのrootに置いてください
+ *  shinonome_font12.fnt(12x12)
+ *  shinonome_font16.fnt(16x16)
+ */
+
+
+#define NUM_FONT_WORK   2
+
+typedef struct font_work_s {
+	FILE     *pffont;
+	uint8_t  arrtibute;
+	uint8_t  image_size;
+	uint16_t num_table2B;
+	uint32_t num_table3B;
+	uint32_t offset_image_2B;
+	uint32_t offset_image_3B;
+	uint8_t  table[256];
+} font_work_t;
+
+#ifndef NOT_USEFILFONT
+/*
+ *  2バイトコード　1バイト目
+ */
+static const uint8_t Utf8CodeTable_2B_1st[][2] = {
+	{0xC2, 0x06},
+	{0xC3, 0x02},
+	{0xCE, 0x27},
+	{0xCF, 0x09},
+	{0xD0, 0x31},
+	{0xD1, 0x11}
+};
+
+/*
+ *  3バイトコード 1バイト目
+ */
+static const uint8_t Utf8CodeTable_3B_1st[][2] = {
+	{0xE2, 0x0E},
+	{0xE3, 0x04},
+	{0xE4, 0x08},
+	{0xE5, 0x40},
+	{0xE6, 0x40},
+	{0xE7, 0x3F},
+	{0xE8, 0x3F},
+	{0xE9, 0x3C},
+	{0xEF, 0x03}
+};
+
+/*
+ *  3バイトコード 2バイト目
+ */
+static const uint8_t Utf8CodeTable_3B_2nd[][2] = {
+	{0x80, 0x0E},
+	{0x84, 0x02},
+	{0x86, 0x04},
+	{0x87, 0x02},
+	{0x88, 0x14},
+	{0x89, 0x07},
+	{0x8A, 0x05},
+	{0x8C, 0x01},
+	{0x94, 0x1E},
+	{0x95, 0x02},
+	{0x96, 0x06},
+	{0x97, 0x06},
+	{0x98, 0x02},
+	{0x99, 0x05},
+	{0x80, 0x15},
+	{0x81, 0x3F},
+	{0x82, 0x37},
+	{0x83, 0x3B},
+	{0xB8, 0x1F},
+	{0xB9, 0x13},
+	{0xBA, 0x23},
+	{0xBB, 0x1E},
+	{0xBC, 0x13},
+	{0xBD, 0x1A},
+	{0xBE, 0x14},
+	{0xBF, 0x1A},
+	{0x80, 0x1A},
+	{0x81, 0x12},
+	{0x82, 0x0F},
+	{0x83, 0x13},
+	{0x84, 0x14},
+	{0x85, 0x21},
+	{0x86, 0x24},
+	{0x87, 0x1B},
+	{0x88, 0x1B},
+	{0x89, 0x1A},
+	{0x8A, 0x17},
+	{0x8B, 0x1C},
+	{0x8C, 0x1A},
+	{0x8D, 0x21},
+	{0x8E, 0x11},
+	{0x8F, 0x24},
+	{0x90, 0x1E},
+	{0x91, 0x14},
+	{0x92, 0x16},
+	{0x93, 0x13},
+	{0x94, 0x0E},
+	{0x95, 0x0F},
+	{0x96, 0x17},
+	{0x97, 0x0D},
+	{0x98, 0x0E},
+	{0x99, 0x0D},
+	{0x9A, 0x0D},
+	{0x9B, 0x17},
+	{0x9C, 0x16},
+	{0x9D, 0x0E},
+	{0x9E, 0x0C},
+	{0x9F, 0x12},
+	{0xA0, 0x13},
+	{0xA1, 0x14},
+	{0xA2, 0x0F},
+	{0xA3, 0x1D},
+	{0xA4, 0x1A},
+	{0xA5, 0x1A},
+	{0xA6, 0x13},
+	{0xA7, 0x12},
+	{0xA8, 0x0F},
+	{0xA9, 0x0A},
+	{0xAA, 0x06},
+	{0xAB, 0x0E},
+	{0xAC, 0x0B},
+	{0xAD, 0x1A},
+	{0xAE, 0x21},
+	{0xAF, 0x22},
+	{0xB0, 0x1F},
+	{0xB1, 0x19},
+	{0xB2, 0x11},
+	{0xB3, 0x0F},
+	{0xB4, 0x0F},
+	{0xB5, 0x0B},
+	{0xB6, 0x0E},
+	{0xB7, 0x1A},
+	{0xB8, 0x15},
+	{0xB9, 0x1C},
+	{0xBA, 0x14},
+	{0xBB, 0x21},
+	{0xBC, 0x1F},
+	{0xBD, 0x1B},
+	{0xBE, 0x1F},
+	{0xBF, 0x14},
+	{0x80, 0x16},
+	{0x81, 0x1C},
+	{0x82, 0x1C},
+	{0x83, 0x17},
+	{0x84, 0x16},
+	{0x85, 0x20},
+	{0x86, 0x14},
+	{0x87, 0x16},
+	{0x88, 0x1D},
+	{0x89, 0x17},
+	{0x8A, 0x19},
+	{0x8B, 0x22},
+	{0x8C, 0x11},
+	{0x8D, 0x12},
+	{0x8E, 0x1C},
+	{0x8F, 0x12},
+	{0x90, 0x0F},
+	{0x91, 0x09},
+	{0x92, 0x12},
+	{0x93, 0x18},
+	{0x94, 0x14},
+	{0x95, 0x16},
+	{0x96, 0x1B},
+	{0x97, 0x19},
+	{0x98, 0x17},
+	{0x99, 0x17},
+	{0x9A, 0x15},
+	{0x9B, 0x18},
+	{0x9C, 0x1F},
+	{0x9D, 0x1F},
+	{0x9E, 0x17},
+	{0x9F, 0x1C},
+	{0xA0, 0x12},
+	{0xA1, 0x17},
+	{0xA2, 0x1A},
+	{0xA3, 0x16},
+	{0xA4, 0x1C},
+	{0xA5, 0x1A},
+	{0xA6, 0x12},
+	{0xA7, 0x17},
+	{0xA8, 0x1A},
+	{0xA9, 0x0D},
+	{0xAA, 0x10},
+	{0xAB, 0x0D},
+	{0xAC, 0x12},
+	{0xAD, 0x19},
+	{0xAE, 0x1A},
+	{0xAF, 0x10},
+	{0xB0, 0x0D},
+	{0xB1, 0x15},
+	{0xB2, 0x1B},
+	{0xB3, 0x16},
+	{0xB4, 0x14},
+	{0xB5, 0x11},
+	{0xB6, 0x0E},
+	{0xB7, 0x1B},
+	{0xB8, 0x1C},
+	{0xB9, 0x10},
+	{0xBA, 0x13},
+	{0xBB, 0x14},
+	{0xBC, 0x13},
+	{0xBD, 0x11},
+	{0xBE, 0x0F},
+	{0xBF, 0x16},
+	{0x80, 0x12},
+	{0x81, 0x0A},
+	{0x82, 0x0D},
+	{0x83, 0x09},
+	{0x84, 0x09},
+	{0x85, 0x0F},
+	{0x86, 0x0D},
+	{0x87, 0x16},
+	{0x88, 0x12},
+	{0x89, 0x15},
+	{0x8A, 0x0E},
+	{0x8B, 0x15},
+	{0x8C, 0x12},
+	{0x8D, 0x0E},
+	{0x8E, 0x09},
+	{0x8F, 0x0F},
+	{0x90, 0x0D},
+	{0x91, 0x12},
+	{0x92, 0x07},
+	{0x93, 0x11},
+	{0x94, 0x1D},
+	{0x95, 0x20},
+	{0x96, 0x18},
+	{0x97, 0x18},
+	{0x98, 0x0D},
+	{0x99, 0x19},
+	{0x9A, 0x15},
+	{0x9B, 0x19},
+	{0x9C, 0x13},
+	{0x9D, 0x0D},
+	{0x9E, 0x10},
+	{0x9F, 0x10},
+	{0xA0, 0x0D},
+	{0xA1, 0x08},
+	{0xA2, 0x14},
+	{0xA3, 0x0F},
+	{0xA4, 0x0D},
+	{0xA5, 0x16},
+	{0xA6, 0x14},
+	{0xA7, 0x12},
+	{0xA8, 0x16},
+	{0xA9, 0x16},
+	{0xAA, 0x13},
+	{0xAB, 0x20},
+	{0xAC, 0x15},
+	{0xAD, 0x17},
+	{0xAE, 0x15},
+	{0xAF, 0x13},
+	{0xB0, 0x13},
+	{0xB1, 0x11},
+	{0xB2, 0x1C},
+	{0xB3, 0x16},
+	{0xB4, 0x1F},
+	{0xB5, 0x1A},
+	{0xB6, 0x1A},
+	{0xB7, 0x16},
+	{0xB8, 0x19},
+	{0xB9, 0x18},
+	{0xBA, 0x0E},
+	{0xBC, 0x03},
+	{0xBD, 0x17},
+	{0xBE, 0x18},
+	{0xBF, 0x12},
+	{0x80, 0x16},
+	{0x81, 0x16},
+	{0x82, 0x19},
+	{0x83, 0x14},
+	{0x84, 0x10},
+	{0x85, 0x14},
+	{0x86, 0x18},
+	{0x87, 0x19},
+	{0x88, 0x1E},
+	{0x89, 0x15},
+	{0x8A, 0x12},
+	{0x8B, 0x17},
+	{0x8C, 0x16},
+	{0x8D, 0x0D},
+	{0x8E, 0x12},
+	{0x8F, 0x15},
+	{0x90, 0x12},
+	{0x91, 0x14},
+	{0x92, 0x10},
+	{0x93, 0x11},
+	{0x94, 0x10},
+	{0x95, 0x13},
+	{0x96, 0x17},
+	{0x97, 0x11},
+	{0x98, 0x0E},
+	{0x99, 0x0E},
+	{0x9A, 0x0D},
+	{0x9B, 0x16},
+	{0x9C, 0x13},
+	{0x9D, 0x13},
+	{0x9E, 0x0A},
+	{0x9F, 0x0F},
+	{0xA0, 0x0F},
+	{0xA1, 0x19},
+	{0xA2, 0x14},
+	{0xA3, 0x17},
+	{0xA4, 0x10},
+	{0xA5, 0x13},
+	{0xA6, 0x19},
+	{0xA7, 0x0A},
+	{0xA8, 0x1A},
+	{0xA9, 0x18},
+	{0xAA, 0x1B},
+	{0xAB, 0x1C},
+	{0xAC, 0x18},
+	{0xAD, 0x15},
+	{0xAE, 0x0B},
+	{0xB0, 0x03},
+	{0xB1, 0x12},
+	{0xB2, 0x22},
+	{0xB3, 0x1B},
+	{0xB4, 0x0C},
+	{0xB5, 0x0A},
+	{0xB6, 0x09},
+	{0xB7, 0x13},
+	{0xB8, 0x0C},
+	{0xB9, 0x12},
+	{0xBA, 0x13},
+	{0xBB, 0x12},
+	{0xBC, 0x18},
+	{0xBD, 0x0F},
+	{0xBE, 0x12},
+	{0xBF, 0x16},
+	{0x80, 0x23},
+	{0x81, 0x27},
+	{0x82, 0x12},
+	{0x83, 0x0C},
+	{0x84, 0x06},
+	{0x85, 0x15},
+	{0x86, 0x12},
+	{0x87, 0x1B},
+	{0x88, 0x0B},
+	{0x89, 0x0F},
+	{0x8A, 0x0E},
+	{0x8B, 0x0B},
+	{0x8C, 0x13},
+	{0x8D, 0x0D},
+	{0x8E, 0x0B},
+	{0x8F, 0x0C},
+	{0x90, 0x0E},
+	{0x91, 0x12},
+	{0x92, 0x01},
+	{0x95, 0x01},
+	{0x96, 0x1B},
+	{0x97, 0x0D},
+	{0x98, 0x09},
+	{0x99, 0x1D},
+	{0x9A, 0x1E},
+	{0x9B, 0x1C},
+	{0x9C, 0x18},
+	{0x9D, 0x18},
+	{0x9E, 0x12},
+	{0x9F, 0x0E},
+	{0xA0, 0x19},
+	{0xA1, 0x12},
+	{0xA2, 0x05},
+	{0xA3, 0x11},
+	{0xA4, 0x14},
+	{0xA5, 0x0A},
+	{0xA6, 0x0C},
+	{0xA7, 0x15},
+	{0xA8, 0x0C},
+	{0xA9, 0x10},
+	{0xAA, 0x05},
+	{0xAB, 0x15},
+	{0xAC, 0x11},
+	{0xAD, 0x0E},
+	{0xAE, 0x10},
+	{0xAF, 0x13},
+	{0xB0, 0x19},
+	{0xB1, 0x0A},
+	{0xB3, 0x09},
+	{0xB4, 0x13},
+	{0xB5, 0x11},
+	{0xB6, 0x0D},
+	{0xB7, 0x0F},
+	{0xB8, 0x03},
+	{0xB9, 0x05},
+	{0xBA, 0x17},
+	{0xBB, 0x19},
+	{0xBC, 0x0A},
+	{0xBD, 0x12},
+	{0xBE, 0x05},
+	{0xBC, 0x3D},
+	{0xBD, 0x1F},
+	{0xBF, 0x05}
+};
+
+/*
+ *  2バイトコード 2バイト目
+ */
+static const uint8_t Utf8CodeTable_2B_2nd[] = {
+	0xA7, 0xA8, 0xB0, 0xB1, 0xB4, 0xB6, 0x97, 0xB7, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, /* 0000-0015 */
+	0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9,	/* 0016-0031 */
+	0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x80,	/* 0032-0047 */
+	0x81, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x81, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,	/* 0048-0063 */
+	0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,	/* 0064-0079 */
+	0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,	/* 0080-0095 */
+	0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86,	/* 0096-0111 */
+	0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x91                                      /* 0112-0121 */
+};
+
+// 3バイトコード 3バイト目 bitmapデータ
+static const uint8_t Utf8CodeTable_3B_3rd[] = {
+	0x90, 0x95, 0x98, 0x99, 0x9C, 0x9D, 0xA0, 0xA1, 0xA5, 0xA6, 0xB0, 0xB2, 0xB3, 0xBB, 0x83, 0xAB,	/* 0000-0015 */
+	0x90, 0x91, 0x92, 0x93, 0x92, 0x94, 0x80, 0x82, 0x83, 0x87, 0x88, 0x8B, 0x9A, 0x9D, 0x9E, 0xA0,	/* 0016-0031 */
+	0xA5, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xB4, 0xB5, 0xBD, 0x92, 0xA0, 0xA1, 0xA6, 0xA7, 0xAA,	/* 0032-0047 */
+	0xAB, 0x82, 0x83, 0x86, 0x87, 0xA5, 0x92, 0x80, 0x81, 0x82, 0x83, 0x8C, 0x8F, 0x90, 0x93, 0x94,	/* 0048-0063 */
+	0x97, 0x98, 0x9B, 0x9C, 0x9D, 0xA0, 0xA3, 0xA4, 0xA5, 0xA8, 0xAB, 0xAC, 0xAF, 0xB0, 0xB3, 0xB4,	/* 0064-0079 */
+	0xB7, 0xB8, 0xBB, 0xBC, 0xBF, 0x82, 0x8B, 0xA0, 0xA1, 0xB2, 0xB3, 0xBC, 0xBD, 0x86, 0x87, 0x8B,	/* 0080-0095 */
+	0x8E, 0x8F, 0xAF, 0x85, 0x86, 0x80, 0x82, 0xAA, 0xAD, 0xAF, 0x80, 0x81, 0x82, 0x83, 0x85, 0x86,	/* 0096-0111 */
+	0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x81,	/* 0112-0127 */
+	0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, /* 0128-0143 */
+	0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, /* 0144-0159 */
+	0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, /* 0160-0175 */
+	0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x80, 0x81, /* 0176-0191 */
+	0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, /* 0192-0207 */
+	0x92, 0x93, 0x9B, 0x9C, 0x9D, 0x9E, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, /* 0208-0223 */
+	0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, /* 0224-0239 */
+	0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, /* 0240-0255 */
+	0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, /* 0256-0271 */
+	0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, /* 0272-0287 */
+	0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xBB, 0xBC, 0xBD, 0xBE, /* 0288-0303 */
+	0x80, 0x81, 0x83, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8D, 0x8E, 0x90, 0x91, 0x94, 0x95, 0x96, 0x97, /* 0304-0319 */
+	0x98, 0x99, 0x9E, 0xA1, 0xA6, 0xAA, 0xAD, 0xB1, 0xB2, 0xB6, 0xB8, 0xB9, 0xBB, 0xBC, 0xBF, 0x82, /* 0320-0335 */
+	0x83, 0x85, 0x8B, 0x8D, 0x8E, 0x8F, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9D, 0x9E, 0x9F, 0xA2, 0xB1, /* 0336-0351 */
+	0xB3, 0xBE, 0x80, 0x82, 0x85, 0x86, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8E, 0x91, 0x92, 0x94, 0x95, /* 0352-0367 */
+	0x98, 0x99, 0x9B, 0x9C, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA4, 0xA5, 0xA6, 0xA8, 0xAB, 0xAC, 0xAD, /* 0368-0383 */
+	0xAE, 0xB0, 0xB3, 0xB6, 0xBA, 0x80, 0x81, 0x82, 0x84, 0x86, 0x87, 0x8A, 0x8B, 0x8D, 0x8E, 0x8F, /* 0384-0399 */
+	0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9D, 0x9E, 0x9F, 0xA3, 0xA4, 0xA5, 0xAD, 0xAE, 0xB0, 0xB2, /* 0400-0415 */
+	0xB6, 0xB7, 0xBB, 0x81, 0x89, 0x8A, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x9A, 0x9C, 0x9D, 0xAF, 0xB0, /* 0416-0431 */
+	0xB4, 0xB6, 0xB8, 0xBA, 0xBC, 0xBD, 0x83, 0x86, 0x87, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x93, 0x95, /* 0432-0447 */
+	0x97, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0xA9, 0xAF, 0xB0, 0xB3, 0xB5, 0xB6, 0xBB, 0xBC, 0xBF, /* 0448-0463 */
+	0x83, 0x86, 0x88, 0x8B, 0x8D, 0x8F, 0x91, 0x96, 0x98, 0x9B, 0x9D, 0xA0, 0xA1, 0xAB, 0xAD, 0xAE, /* 0464-0479 */
+	0xAF, 0xB5, 0xB6, 0xBF, 0x82, 0x83, 0x84, 0x8A, 0x8E, 0x90, 0x91, 0x94, 0x97, 0x98, 0x9A, 0x9B, /* 0480-0495 */
+	0x9D, 0x9F, 0xA1, 0xA3, 0xA4, 0xA5, 0xAE, 0xAF, 0xB3, 0xB5, 0xB6, 0xB8, 0xBA, 0xBE, 0x85, 0x86, /* 0496-0511 */
+	0x89, 0x8B, 0x8D, 0x8F, 0x91, 0x92, 0x94, 0x96, 0x99, 0x9A, 0x9F, 0xA1, 0xA3, 0xA4, 0xA5, 0xA6, /* 0512-0527 */
+	0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xB6, 0xB9, 0x83, 0x87, 0x88, 0x89, 0x8F, 0x90, 0x95, 0x96, /* 0528-0543 */
+	0x9A, 0x9C, 0xA5, 0xAC, 0xB2, 0xB4, 0xB5, 0xB6, 0xB8, 0xBD, 0x80, 0x85, 0x8D, 0x91, 0x98, 0x99, /* 0544-0559 */
+	0x9A, 0xAC, 0xAD, 0xB2, 0xB3, 0xB4, 0xB5, 0xB7, 0xBE, 0x82, 0x85, 0x89, 0x8A, 0x8D, 0x8F, 0x91, /* 0560-0575 */
+	0x95, 0x96, 0x9A, 0x9E, 0xA3, 0xA5, 0xA7, 0xAD, 0xAE, 0xB5, 0xB9, 0xBB, 0x80, 0x81, 0x82, 0x84, /* 0576-0591 */
+	0x89, 0x92, 0x94, 0x95, 0x96, 0x98, 0x9A, 0x9F, 0xA1, 0xAA, 0xB2, 0xB7, 0xBA, 0xBB, 0xBC, 0xBF, /* 0592-0607 */
+	0x80, 0x81, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8B, 0x8C, 0x8D, 0x8E, 0x90, 0x92, 0x94, /* 0608-0623 */
+	0x9A, 0x9C, 0xA2, 0xA5, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xB1, 0xB5, 0xB6, 0xB7, 0xB8, /* 0624-0639 */
+	0xBC, 0x80, 0x82, 0x85, 0x86, 0x89, 0x8A, 0x8C, 0x8D, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x95, 0x96, /* 0640-0655 */
+	0x97, 0x99, 0xA0, 0xA2, 0xA4, 0xA5, 0xA6, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xB0, 0xB1, 0xB2, 0xB3, /* 0656-0671 */
+	0xB4, 0xB5, 0xB6, 0xB7, 0xBD, 0x84, 0x85, 0x86, 0x89, 0x8B, 0x8C, 0x8D, 0x96, 0x9B, 0x9C, 0x9D, /* 0672-0687 */
+	0xA0, 0xA1, 0xA6, 0xA7, 0xA9, 0xAA, 0xAD, 0xB0, 0xB1, 0xB5, 0xB6, 0xB8, 0xB9, 0xBA, 0xBD, 0xBE, /* 0688-0703 */
+	0x80, 0x83, 0x84, 0x86, 0x87, 0x88, 0x8A, 0x8B, 0x8E, 0x91, 0x94, 0x97, 0x9D, 0xA4, 0xA5, 0xA7, /* 0704-0719 */
+	0xA9, 0xAA, 0xAE, 0xB0, 0xB3, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0x83, 0x84, 0x87, 0x8A, 0x8B, /* 0720-0735 */
+	0x8C, 0x8D, 0x8F, 0x94, 0x96, 0x9B, 0x9E, 0xA3, 0xA4, 0xA5, 0xA9, 0xAA, 0xAF, 0xB0, 0xB1, 0xB2, /* 0736-0751 */
+	0xB3, 0xB4, 0xB5, 0xBD, 0xBF, 0x83, 0x87, 0x88, 0x89, 0x8D, 0x91, 0x92, 0x94, 0x9B, 0x9F, 0xA0, /* 0752-0767 */
+	0xA3, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xB1, 0xB4, 0xB5, 0xB9, 0xBC, 0xBE, 0x81, 0x83, 0x85, 0x87, /* 0768-0783 */
+	0x89, 0x8D, 0x92, 0x95, 0x97, 0x98, 0x99, 0x9D, 0x9E, 0x9F, 0xA0, 0xA2, 0xA3, 0xA4, 0xA6, 0xA7, /* 0784-0799 */
+	0xB2, 0xB3, 0xB5, 0xB8, 0xB9, 0xBA, 0xBE, 0xBF, 0x81, 0x82, 0x85, 0x86, 0x88, 0x8D, 0x8F, 0x90, /* 0800-0815 */
+	0x95, 0x96, 0x97, 0x99, 0x9A, 0x9D, 0xA0, 0xA1, 0xA3, 0xAA, 0xAF, 0xB1, 0xB3, 0xB8, 0xB9, 0xBA, /* 0816-0831 */
+	0xBB, 0xBF, 0x80, 0x81, 0x83, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8D, 0x91, 0x92, 0x93, 0x94, /* 0832-0847 */
+	0x97, 0x98, 0x9A, 0x9C, 0x9E, 0xA0, 0xA6, 0xA9, 0xAE, 0xAF, 0xB0, 0xB1, 0xB3, 0xB4, 0xB5, 0xB7, /* 0848-0863 */
+	0xB8, 0xBB, 0xBF, 0x82, 0x84, 0x96, 0x98, 0x9A, 0x9F, 0xA0, 0xA5, 0xA6, 0xA8, 0xA9, 0xAD, 0xAE, /* 0864-0879 */
+	0xB0, 0xB3, 0xB6, 0xBB, 0x82, 0x83, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x94, 0x96, 0x97, /* 0880-0895 */
+	0x99, 0x9B, 0x9F, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, /* 0896-0911 */
+	0xB0, 0xB1, 0xB2, 0xB3, 0xB6, 0xB7, 0xB8, 0xBA, 0x81, 0x83, 0x84, 0x88, 0x89, 0x8A, 0x8B, 0x8C, /* 0912-0927 */
+	0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x9B, 0x9D, 0x9F, 0xA0, 0xA6, 0xA9, 0xAB, 0xAC, 0xAD, 0xAE, 0xB6, /* 0928-0943 */
+	0xB8, 0xB9, 0xBB, 0xBC, 0xBD, 0xBE, 0x80, 0x82, 0x86, 0x88, 0x89, 0x8A, 0x8E, 0x91, 0x9F, 0xA8, /* 0944-0959 */
+	0xAA, 0xB0, 0xB1, 0xB3, 0xB5, 0xB6, 0xB7, 0xBB, 0xBC, 0xBD, 0x80, 0x84, 0x86, 0x8B, 0x8C, 0x8E, /* 0960-0975 */
+	0x8F, 0x90, 0x92, 0xA2, 0xA4, 0xA5, 0xA8, 0xAB, 0xAC, 0xAF, 0xB2, 0xB3, 0xB8, 0xBC, 0xBD, 0xBE, /* 0976-0991 */
+	0x80, 0x81, 0x82, 0x84, 0x87, 0x88, 0x89, 0x98, 0xA1, 0xA2, 0xA5, 0xA6, 0xA8, 0xA9, 0xAD, 0xAE, /* 0992-1007 */
+	0xB2, 0xBA, 0xBD, 0x84, 0x86, 0x87, 0x8F, 0x90, 0x94, 0x96, 0xAE, 0xAF, 0xB1, 0xB3, 0xB8, 0xB9, /* 1008-1023 */
+	0xBE, 0x80, 0x84, 0x85, 0x86, 0x8C, 0x8F, 0x93, 0x96, 0x97, 0x9C, 0x9D, 0xA3, 0xBB, 0xBC, 0xBE, 
+	0x80, 0x83, 0x84, 0x87, 0x89, 0x8A, 0x8B, 0x98, 0x99, 0x9A, 0x9C, 0x9D, 0x9E, 0x9F, 0xA7, 0xA8, 
+	0xA9, 0xAA, 0xAB, 0xAC, 0xAE, 0xB0, 0xB6, 0x84, 0x85, 0x87, 0x94, 0x9A, 0x9C, 0x9F, 0xA3, 0xA4, 
+	0xB7, 0xB9, 0xBD, 0xBE, 0x86, 0x89, 0x94, 0x96, 0x97, 0x98, 0x9B, 0xA9, 0xAF, 0xB1, 0xB2, 0xB4, 
+	0xB6, 0xB8, 0x82, 0x8C, 0x8E, 0x90, 0x9B, 0xA4, 0xA8, 0xAA, 0xAB, 0xAC, 0xB4, 0xB8, 0xBA, 0x80, 
+	0x86, 0x87, 0x8A, 0x8F, 0x94, 0xA0, 0xA2, 0xA5, 0xAE, 0xB4, 0xB6, 0xBC, 0x80, 0x81, 0x82, 0x83, 
+	0x88, 0x8E, 0x91, 0x93, 0x97, 0x98, 0x9A, 0x9B, 0x9E, 0xA0, 0xA3, 0xAE, 0xB0, 0xB2, 0xB3, 0xB9, 
+	0xBA, 0xBD, 0xBF, 0x80, 0x83, 0x84, 0x88, 0x89, 0x8B, 0x8D, 0x8F, 0x92, 0x93, 0x96, 0x98, 0x9C, 
+	0x9F, 0xA6, 0xA7, 0xA8, 0xAD, 0xB0, 0xB7, 0xB8, 0xBB, 0x80, 0x82, 0x87, 0x8A, 0x8E, 0x8F, 0x90, 
+	0x91, 0xA1, 0xA4, 0xA6, 0xA9, 0xAA, 0xBF, 0x82, 0x88, 0x89, 0x8B, 0x93, 0xA0, 0xA2, 0xA3, 0xA4, 
+	0xAA, 0xB0, 0xB3, 0x80, 0x83, 0x86, 0x8B, 0x8E, 0x92, 0x93, 0x94, 0x96, 0x9C, 0x9F, 0xA0, 0xA3, 
+	0xB4, 0xB7, 0xB9, 0xBA, 0xBC, 0x80, 0x82, 0x85, 0x86, 0x8A, 0x8B, 0x95, 0x99, 0x9D, 0xA1, 0xA4, 
+	0xAA, 0xAF, 0xB0, 0xB1, 0xB4, 0xB5, 0xBA, 0xBD, 0x80, 0x81, 0x8A, 0x8B, 0x91, 0x92, 0x94, 0x97, 
+	0x98, 0x99, 0x9A, 0x9E, 0xA2, 0xA9, 0xAB, 0xB0, 0xB2, 0xB5, 0xB9, 0xBE, 0x83, 0x85, 0x93, 0x97, 
+	0x9C, 0x9F, 0xA8, 0xAB, 0xAE, 0xB3, 0xB8, 0xB9, 0xBA, 0xBB, 0xBE, 0x81, 0x85, 0x87, 0x8A, 0x8C, 
+	0x91, 0x93, 0x95, 0x97, 0x98, 0x99, 0x9C, 0x9E, 0x9F, 0xA4, 0xA5, 0xAB, 0xAC, 0xAE, 0xAF, 0xB0, 
+	0xB1, 0xB2, 0xB7, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0x82, 0x89, 0x8A, 0x8F, 0x90, 0x95, 0x96, 0x98, 
+	0x99, 0x9A, 0x9B, 0x9C, 0xA2, 0xA5, 0xA7, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xB1, 0xB2, 0xB7, 
+	0xB8, 0xBE, 0x84, 0x87, 0x88, 0x89, 0x8E, 0x8F, 0x90, 0x91, 0x94, 0x95, 0x97, 0x98, 0x9A, 0xA0, 
+	0xA2, 0xA5, 0xA7, 0xA8, 0xA9, 0xAA, 0xAC, 0xAE, 0xB3, 0xB4, 0xB8, 0xBD, 0x81, 0x82, 0x83, 0x84, 
+	0x8A, 0x8D, 0x93, 0x96, 0x99, 0x9B, 0x9D, 0xA3, 0xA5, 0xA8, 0xAC, 0xB2, 0xB9, 0xBB, 0xBE, 0x86, 
+	0x89, 0x8B, 0x90, 0x91, 0x93, 0x94, 0x99, 0x9A, 0x9C, 0xA5, 0xA6, 0xA8, 0xAA, 0xAB, 0xB6, 0xBB, 
+	0xBF, 0x81, 0x83, 0x89, 0x91, 0x98, 0x9A, 0x9C, 0x9F, 0xA0, 0xA5, 0xA9, 0xAF, 0xB5, 0xB6, 0xBC, 
+	0x80, 0x81, 0x86, 0x89, 0x9A, 0xA2, 0xA6, 0xAA, 0xAC, 0xBF, 0x92, 0x9A, 0x9B, 0xBC, 0xBD, 0xBE, 
+	0x81, 0x82, 0x89, 0x8B, 0x8C, 0x90, 0x96, 0x97, 0xA1, 0xA3, 0xA6, 0xA9, 0xBA, 0xBB, 0x89, 0x8B, 
+	0x8C, 0x96, 0xA2, 0xAA, 0xAC, 0xB0, 0xB2, 0xB6, 0xBE, 0x80, 0x83, 0x85, 0x90, 0x91, 0x94, 0x95, 
+	0x97, 0x98, 0x9A, 0x9B, 0x9C, 0x9D, 0x9F, 0xA3, 0xA4, 0xA5, 0xA6, 0xA9, 0xAB, 0xB0, 0xB1, 0xB3, 
+	0xB5, 0xB8, 0xBA, 0x80, 0x83, 0x85, 0x87, 0x88, 0x89, 0x8B, 0x8C, 0x8D, 0x8F, 0x95, 0x97, 0x98, 
+	0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9F, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xAE, 0xB0, 0xB3, 0xB4, 0xB5, 
+	0xB6, 0xB8, 0xB9, 0xBF, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x89, 0x8C, 0x90, 0x92, 0x93, 0x94, 
+	0x9B, 0x9D, 0x9E, 0x9F, 0xA1, 0xA2, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAB, 0xAE, 0xB0, 0xB3, 
+	0xB5, 0xB6, 0xB8, 0xBA, 0xBE, 0xBF, 0x81, 0x82, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 
+	0x8D, 0x8E, 0x8F, 0x91, 0x93, 0x96, 0x9A, 0xA0, 0xA2, 0xA4, 0xA8, 0xAD, 0xB1, 0xB8, 0xB9, 0xBA, 
+	0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x80, 0x81, 0x85, 0x86, 0x88, 0x8A, 0x8B, 0x8D, 0x8E, 0x8F, 0x90, 
+	0x91, 0x93, 0x95, 0x9E, 0xA0, 0xA1, 0xA4, 0xA5, 0xAC, 0xAE, 0xAF, 0xB1, 0xB6, 0xB9, 0x8C, 0x90, 
+	0x91, 0x94, 0xA1, 0xA8, 0xA9, 0xAB, 0xAC, 0xB1, 0xB3, 0xB6, 0xB7, 0xB8, 0xBB, 0xBC, 0xBE, 0x85, 
+	0x87, 0x99, 0xA0, 0xA1, 0xA8, 0xA9, 0xAA, 0xAD, 0xAF, 0xB0, 0xB6, 0xBA, 0xBB, 0xBD, 0x87, 0x8B, 
+	0x8E, 0x91, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9F, 0xA2, 0xA9, 0x8B, 0x8C, 0x8E, 
+	0x90, 0x92, 0x9C, 0xA9, 0xAC, 0xAF, 0xB3, 0xB6, 0x82, 0x84, 0x87, 0x8B, 0x8C, 0x90, 0x9D, 0xA2, 
+	0xAC, 0xAE, 0xB7, 0xBA, 0xBC, 0xBD, 0x89, 0x8C, 0x8D, 0x92, 0x93, 0x96, 0x9B, 0x9D, 0x9E, 0xA1, 
+	0xA3, 0xA5, 0xA6, 0xA7, 0xA8, 0xAB, 0xAE, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB7, 0xBB, 0xBD, 0xBE, 
+	0x82, 0x83, 0x86, 0x8B, 0x8C, 0x91, 0x96, 0x99, 0x9A, 0x9B, 0x9D, 0xA5, 0xAB, 0xAD, 0xAF, 0xB0, 
+	0xB3, 0xB6, 0xB7, 0xB8, 0xBD, 0x80, 0x83, 0x84, 0x85, 0x87, 0x8C, 0x8E, 0x94, 0x95, 0x97, 0x9F, 
+	0xA1, 0xA2, 0xA3, 0xA4, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 
+	0xBF, 0x81, 0x83, 0x84, 0x87, 0x8A, 0x8F, 0x95, 0x96, 0x97, 0x9A, 0x9C, 0xA0, 0xA6, 0xA7, 0xAB, 
+	0xAD, 0xB5, 0xB6, 0xB7, 0xB8, 0x81, 0x82, 0x83, 0x88, 0x89, 0x8A, 0x8F, 0x90, 0x93, 0x96, 0x9A, 
+	0x9B, 0x9D, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA8, 0xA9, 0xAC, 0xB0, 0xB1, 0xB3, 0xB4, 0xB6, 0xB7, 
+	0xB8, 0xBA, 0xBB, 0xBC, 0xBE, 0xBF, 0x81, 0x83, 0x84, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8F, 0x90, 
+	0x91, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x9B, 0x9F, 0xA5, 0xA6, 0xA7, 0xA9, 0xAD, 0xAF, 0xB1, 
+	0xB5, 0xB7, 0xB8, 0xBC, 0xBE, 0x81, 0x88, 0x8A, 0x8C, 0x8E, 0x91, 0x93, 0x96, 0x97, 0x99, 0x9C, 
+	0x9D, 0xA1, 0xA2, 0xA6, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xB0, 0xB1, 0xB3, 0xB7, 0xB9, 0xBC, 0xBF, 
+	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x87, 0x88, 0x8A, 0x8B, 0x8C, 0x90, 0x91, 0x92, 0x93, 0x97, 
+	0x98, 0x99, 0x9E, 0xA0, 0xA1, 0xA8, 0xA9, 0xAA, 0xAD, 0xAE, 0xB3, 0xB4, 0xB9, 0xBC, 0xBD, 0x83, 
+	0x85, 0x8C, 0x8D, 0x96, 0x97, 0x98, 0x99, 0x9C, 0x9D, 0xA0, 0xA4, 0xAB, 0xB0, 0xB1, 0xB5, 0xB8, 
+	0xBB, 0xBD, 0xBF, 0x8E, 0x8F, 0x90, 0x92, 0x95, 0x96, 0x99, 0x9B, 0x9C, 0x9D, 0xA0, 0xA1, 0xA5, 
+	0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAF, 0xB1, 0xBA, 0x81, 0x82, 0x83, 0x86, 0x8A, 0x8B, 0x8D, 
+	0x90, 0x92, 0x95, 0x99, 0x9A, 0x9F, 0xA0, 0xA2, 0xA3, 0xA4, 0xA5, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 
+	0xAD, 0xAF, 0xB0, 0xB5, 0xB7, 0x81, 0x83, 0x84, 0x89, 0x8B, 0x8C, 0x8D, 0x92, 0x94, 0x96, 0x97, 
+	0x9A, 0x9B, 0x9F, 0xA0, 0xA3, 0xA6, 0xA7, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB8, 0xBC, 
+	0xBD, 0x85, 0x86, 0x87, 0x91, 0x93, 0x98, 0x9A, 0x9C, 0x9F, 0xA0, 0xA1, 0xA3, 0xA7, 0xA8, 0xB0, 
+	0xB1, 0xB3, 0xB4, 0xB6, 0xB7, 0xB9, 0xBA, 0xBB, 0x80, 0x81, 0x83, 0x86, 0x88, 0x89, 0x8D, 0x8E, 
+	0x8F, 0x95, 0x9A, 0x9B, 0x9F, 0xA1, 0xA7, 0xA8, 0xAC, 0xB4, 0xBC, 0xBD, 0xBE, 0xBF, 0x82, 0x84, 
+	0x87, 0x88, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x93, 0x95, 0x98, 0x99, 0x9A, 0x9D, 0x9F, 0xA2, 0xA3, 
+	0xA5, 0xA7, 0xA8, 0xAB, 0xAE, 0xAF, 0xB0, 0xB1, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xBE, 0x82, 0x87, 
+	0x8A, 0x8E, 0x90, 0x91, 0x94, 0x96, 0x99, 0x9A, 0xA4, 0xA7, 0xA9, 0xAB, 0xAC, 0xAE, 0xB2, 0xB6, 
+	0xBA, 0xBE, 0x83, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x90, 0xA3, 0xA6, 0xB2, 0xB4, 
+	0xB6, 0xB7, 0xB8, 0xBA, 0xBC, 0xBD, 0xBE, 0xBF, 0x80, 0x88, 0x89, 0x8A, 0x8C, 0x8D, 0x8E, 0x90, 
+	0x91, 0x92, 0x94, 0x96, 0x9A, 0x9B, 0x9D, 0x9E, 0x9F, 0xA1, 0xA6, 0xAA, 0xAE, 0xAF, 0xB0, 0xB2, 
+	0xB3, 0xB4, 0xB8, 0xBB, 0xBF, 0x80, 0x81, 0x87, 0x88, 0x89, 0x8B, 0x8D, 0x8E, 0x93, 0x95, 0x98, 
+	0x9B, 0x9E, 0xA0, 0xA3, 0xA8, 0xAE, 0xB1, 0xB6, 0xB9, 0xBC, 0xBE, 0xBF, 0x80, 0x82, 0x83, 0x84, 
+	0x89, 0x8A, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x9B, 0x9C, 0x9E, 0xAB, 0xAC, 0xB1, 
+	0xB5, 0xB9, 0xBB, 0xBC, 0xBD, 0x82, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8C, 0x8D, 0x8F, 0x90, 
+	0x91, 0x92, 0x93, 0x94, 0x97, 0x98, 0x99, 0x9B, 0x9C, 0x9D, 0xA0, 0xA1, 0xAC, 0xAD, 0xAE, 0xAF, 
+	0xB1, 0xB3, 0xB5, 0xB6, 0xB7, 0xBE, 0xBF, 0x81, 0x82, 0x87, 0x88, 0x89, 0x8C, 0x91, 0x99, 0x9F, 
+	0xA7, 0xA8, 0xAB, 0xAF, 0xBA, 0xBD, 0xBE, 0xBF, 0x89, 0x8C, 0x8D, 0x8F, 0x90, 0x95, 0x97, 0x9C, 
+	0xA7, 0xA8, 0xA9, 0xAB, 0xAE, 0xB2, 0xB6, 0xB7, 0xBA, 0xBB, 0x80, 0x83, 0x88, 0x89, 0x8C, 0x8E, 
+	0x8F, 0x92, 0x96, 0x98, 0x9B, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA5, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 
+	0xAC, 0xB2, 0xB4, 0xB5, 0xBB, 0xBE, 0x80, 0x83, 0x84, 0x86, 0x89, 0x8F, 0x90, 0x92, 0x96, 0x9A, 
+	0x9B, 0xA1, 0xA3, 0xA9, 0xAE, 0xB4, 0xB6, 0xBA, 0x86, 0x8D, 0x8F, 0x93, 0x96, 0x97, 0x9C, 0xA6, 
+	0xA8, 0xAC, 0xAD, 0xB4, 0xB6, 0xBA, 0xBE, 0x82, 0x8E, 0x98, 0xA7, 0xA9, 0xAF, 0xB6, 0xB8, 0xBA, 
+	0x83, 0x88, 0x92, 0x93, 0x95, 0x9A, 0x9E, 0xA4, 0xA5, 0xA9, 0xAB, 0xAD, 0xAE, 0xB0, 0xB2, 0xB9, 
+	0xBB, 0xBC, 0x81, 0x82, 0x85, 0x87, 0x8D, 0x92, 0x94, 0x98, 0x9A, 0xA0, 0xA1, 0xA2, 0xA3, 0xA6, 
+	0xA7, 0xAC, 0xAF, 0xB1, 0xB2, 0xB4, 0xB6, 0xBA, 0xBD, 0xBE, 0x80, 0x85, 0x98, 0x9C, 0x9D, 0xA3, 
+	0xA4, 0xAA, 0xAB, 0xAC, 0xAF, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBB, 0xBE, 0xBF, 0x85, 0x88, 
+	0x8D, 0x8F, 0x91, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9D, 0x9E, 0xA2, 0xA3, 0xA6, 0xAC, 0xB0, 0xB2, 
+	0xB4, 0xB5, 0xB7, 0xB8, 0x82, 0x83, 0x87, 0x88, 0x89, 0x8C, 0x8E, 0x90, 0x91, 0x97, 0x99, 0x9B, 
+	0x9C, 0x9F, 0xA1, 0xA4, 0xA5, 0xA7, 0xAB, 0xAC, 0xAD, 0xAF, 0xB0, 0xB7, 0xB9, 0xBC, 0xBD, 0x81, 
+	0x83, 0x84, 0x85, 0x86, 0x8B, 0x8C, 0x8F, 0x92, 0x97, 0x99, 0x9B, 0xA0, 0xA1, 0xA2, 0xA5, 0xA6, 
+	0xA7, 0xA8, 0xA9, 0xAC, 0xAD, 0xB1, 0xBA, 0xBB, 0x82, 0x83, 0x86, 0x87, 0x8A, 0x8C, 0x8E, 0x8F, 
+	0x93, 0x94, 0x9C, 0x9F, 0xA0, 0xA5, 0xA7, 0xA8, 0xAD, 0xAF, 0xB4, 0xB5, 0xB6, 0xBC, 0xBF, 0x81, 
+	0x82, 0x83, 0x84, 0x89, 0x8B, 0x8F, 0x92, 0x9D, 0x9E, 0x9F, 0xA2, 0xA4, 0xA6, 0xA7, 0xA8, 0xA9, 
+	0xAE, 0xAF, 0xB0, 0xB4, 0xB6, 0xBA, 0x81, 0x83, 0x84, 0x87, 0x88, 0x89, 0x8E, 0x91, 0x96, 0x97, 
+	0x98, 0x9D, 0xA2, 0xA6, 0xAB, 0xAE, 0xB4, 0xB8, 0xB9, 0xBC, 0xBE, 0x81, 0x84, 0x87, 0x89, 0x96, 
+	0x99, 0x9A, 0x9C, 0x9D, 0xA0, 0xA6, 0xA9, 0xB0, 0xB2, 0xB3, 0xB4, 0xB5, 0xB7, 0xB8, 0xB9, 0xBC, 
+	0xBD, 0xBE, 0xBF, 0x80, 0x83, 0x88, 0x89, 0x8B, 0x8D, 0x8F, 0x94, 0x95, 0x96, 0x97, 0x9B, 0x9D, 
+	0x9E, 0x9F, 0xA6, 0xA7, 0xA8, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xB1, 0xB4, 0xB6, 0xB7, 0xB8, 0xBA, 
+	0xBD, 0xBF, 0x81, 0x86, 0x89, 0x8E, 0x8F, 0x90, 0x91, 0x93, 0x96, 0x99, 0x9C, 0x9E, 0x9F, 0xA0, 
+	0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xAA, 0xAD, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB5, 0xB7, 0xBC, 0xBE, 
+	0xBF, 0x85, 0x87, 0x89, 0x8B, 0x8C, 0x90, 0x95, 0x97, 0x9A, 0x9C, 0x9D, 0xA0, 0xA1, 0xA2, 0xA6, 
+	0xA9, 0xAF, 0xB3, 0xB4, 0xB6, 0xB7, 0xB8, 0xB9, 0x81, 0x84, 0x86, 0x8A, 0x8E, 0x8F, 0x90, 0x91, 
+	0x93, 0x94, 0x98, 0x9A, 0x9D, 0x9E, 0xA2, 0xA4, 0xA7, 0xA9, 0xAC, 0xAE, 0xAF, 0xB1, 0xB3, 0xB4, 
+	0xB5, 0xBB, 0xBE, 0xBF, 0x82, 0x83, 0x84, 0x93, 0x96, 0x97, 0x9E, 0xA1, 0xA2, 0xA9, 0xAA, 0xAB, 
+	0xB2, 0xB4, 0xB8, 0xB9, 0xBC, 0xBD, 0x80, 0x81, 0x82, 0x83, 0x86, 0x88, 0x8D, 0x8E, 0x90, 0x91, 
+	0x93, 0x94, 0x99, 0x9C, 0x9D, 0x9F, 0xA3, 0xA7, 0xB4, 0xB6, 0xB7, 0xBE, 0xBF, 0x81, 0x83, 0x85, 
+	0x8D, 0x8F, 0x93, 0x94, 0x97, 0x9B, 0x9D, 0x9F, 0xA0, 0xA2, 0xA6, 0xA7, 0xA8, 0xAD, 0xAF, 0xB0, 
+	0xB1, 0xB3, 0xB5, 0xB6, 0xB9, 0xBA, 0xBC, 0x84, 0x86, 0x89, 0x8A, 0x8B, 0x8D, 0x92, 0x94, 0x95, 
+	0x97, 0x98, 0x9A, 0x9F, 0xA0, 0xA1, 0xA3, 0xA7, 0xAE, 0xAF, 0xB2, 0xB9, 0xBA, 0x80, 0x81, 0x84, 
+	0x85, 0x88, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x92, 0x99, 0x9A, 0x9B, 0x9C, 0xA1, 0xA2, 0xA3, 0xA5, 
+	0xA6, 0xA8, 0xAA, 0xB0, 0xB4, 0xB6, 0xB9, 0xBD, 0xBF, 0x8A, 0x93, 0x94, 0x95, 0x99, 0x9A, 0x9C, 
+	0x9D, 0x9E, 0xA0, 0xA1, 0xA2, 0xAA, 0xAB, 0xAD, 0xAE, 0xAF, 0xB3, 0xB4, 0xB5, 0xB7, 0xB8, 0xB9, 
+	0xBC, 0xBD, 0xBE, 0x81, 0x82, 0x8A, 0x8E, 0x91, 0x94, 0x95, 0x9B, 0x9C, 0xA0, 0xA7, 0xAE, 0xB1, 
+	0xB2, 0xB4, 0xBB, 0xBE, 0xBF, 0x81, 0x83, 0x87, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x90, 0x93, 0x98, 
+	0x99, 0x9D, 0x9E, 0xA7, 0xA8, 0xAB, 0xAD, 0xB2, 0xB9, 0xBB, 0xBD, 0xBF, 0x82, 0x85, 0x8A, 0x8B, 
+	0x8C, 0x92, 0x93, 0x94, 0x97, 0x99, 0x9B, 0x9E, 0x9F, 0xA1, 0xA2, 0xA3, 0xA9, 0xAA, 0xAB, 0xAE, 
+	0xB5, 0xB6, 0xB8, 0xB9, 0xBA, 0xBD, 0x84, 0x87, 0x88, 0x8B, 0x98, 0x99, 0x9F, 0xA1, 0xA2, 0xA6, 
+	0xB2, 0xB8, 0xBF, 0x80, 0x84, 0x8D, 0x8E, 0x90, 0x97, 0x9C, 0xA0, 0xA2, 0xA3, 0xAA, 0xAC, 0xAE, 
+	0xB3, 0xB8, 0xBB, 0x81, 0x82, 0x83, 0x91, 0x93, 0x9A, 0x9B, 0x9E, 0x9F, 0xA8, 0xAA, 0xBA, 0xBB, 
+	0x84, 0x85, 0x8A, 0x92, 0x96, 0x9D, 0x9F, 0xA0, 0xA1, 0xA3, 0xA7, 0xB2, 0xB7, 0xB8, 0xB9, 0xBA, 
+	0xBD, 0xBE, 0x83, 0x87, 0x89, 0x8C, 0x8E, 0x90, 0x93, 0x94, 0x99, 0x9B, 0x9F, 0xA1, 0xA2, 0xA3, 
+	0xA4, 0xA6, 0xA9, 0xAA, 0xAF, 0xB3, 0xB4, 0xB8, 0xB9, 0xBB, 0xBF, 0x80, 0x83, 0x84, 0x86, 0x89, 
+	0x8A, 0x8B, 0x8D, 0x95, 0x96, 0x98, 0x9E, 0xA4, 0xAA, 0xAB, 0xAF, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 
+	0xB7, 0xBA, 0xBB, 0xBC, 0xBF, 0x80, 0x85, 0x86, 0x8B, 0x8D, 0x8E, 0x92, 0x93, 0x94, 0x98, 0x9B, 
+	0x9F, 0xAB, 0xAC, 0xAF, 0xB3, 0x88, 0x8F, 0x91, 0x93, 0x94, 0x97, 0x9B, 0xA3, 0xA4, 0xB4, 0xB7, 
+	0xB8, 0xBE, 0x80, 0x81, 0x82, 0x8E, 0x90, 0x95, 0x97, 0x9A, 0x9D, 0x9E, 0x9F, 0xA0, 0xA2, 0xA8, 
+	0xAA, 0xB0, 0xB2, 0xB3, 0xBA, 0xBD, 0xBE, 0x81, 0x82, 0x83, 0x88, 0x8C, 0x8D, 0x90, 0x92, 0x93, 
+	0x96, 0x99, 0x9A, 0x9B, 0xA1, 0xA2, 0xAB, 0xAE, 0xB1, 0xB3, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 
+	0xBE, 0xBF, 0x81, 0x84, 0x85, 0x89, 0x8A, 0x8C, 0x93, 0x95, 0x97, 0x99, 0x9B, 0x9D, 0xA1, 0xA2, 
+	0xA3, 0xA5, 0xA8, 0xAA, 0xAF, 0xB0, 0xB1, 0xB3, 0x8B, 0x8C, 0x92, 0x97, 0x99, 0x9B, 0x9E, 0x9F, 
+	0xA5, 0xA9, 0xAA, 0xAB, 0xB2, 0xB3, 0xB5, 0xB6, 0xB8, 0xBB, 0xBD, 0xBE, 0x81, 0x84, 0x85, 0x99, 
+	0x9A, 0x9C, 0xA3, 0xA4, 0xA6, 0xA9, 0xAA, 0xAC, 0xAE, 0xB4, 0xB7, 0xB8, 0xB9, 0x85, 0x88, 0x8C, 
+	0x8E, 0x93, 0x95, 0x99, 0x9B, 0x9C, 0xAF, 0xB2, 0xB5, 0xB8, 0xBC, 0x80, 0x85, 0x86, 0x87, 0x8B, 
+	0x8C, 0x91, 0x92, 0x95, 0x98, 0x99, 0x9E, 0xA1, 0xA4, 0xA6, 0xA8, 0xAA, 0xAB, 0xAC, 0xAE, 0xB1, 
+	0xB3, 0xB5, 0xB7, 0xB9, 0xBA, 0xBB, 0x85, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x93, 0x95, 0x99, 0x9A, 
+	0x9B, 0x9D, 0x9F, 0xA0, 0xA1, 0xA3, 0xA4, 0xA5, 0xA6, 0xA9, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB8, 
+	0xBA, 0xBE, 0x83, 0x8A, 0x8D, 0x8E, 0x96, 0x98, 0x9B, 0x9F, 0xA7, 0xAB, 0xAE, 0xAF, 0xB2, 0xB6, 
+	0xBE, 0xBF, 0x80, 0x82, 0x8C, 0x8F, 0x90, 0x96, 0x98, 0x9C, 0x9D, 0x9F, 0xA2, 0xA5, 0xAA, 0xAF, 
+	0xB2, 0xB6, 0xB7, 0xBA, 0xBD, 0x82, 0x84, 0x85, 0x89, 0x8B, 0x8C, 0x91, 0x93, 0x94, 0x95, 0x9D, 
+	0x9E, 0xAC, 0xAF, 0xB2, 0xB4, 0xB7, 0xB8, 0xBE, 0xBF, 0x81, 0x82, 0x86, 0x89, 0x8F, 0x91, 0x93, 
+	0x94, 0x95, 0xA0, 0xA2, 0xA3, 0xAB, 0xAC, 0xB1, 0xB2, 0xB8, 0xBE, 0xBF, 0x81, 0x85, 0x94, 0x98, 
+	0x9B, 0x9C, 0x9F, 0xA4, 0xA6, 0xAD, 0xAE, 0xAF, 0xB0, 0xB4, 0xB8, 0xBA, 0xBC, 0x80, 0x81, 0x82,
+	0x84, 0x86, 0x8E, 0x91, 0x97, 0xA1, 0xA3, 0xA4, 0xAA, 0xB1, 0xB3, 0xB9, 0x80, 0x81, 0x82, 0x83, 
+	0x86, 0x94, 0x95, 0x98, 0x9B, 0x9F, 0xA0, 0xA1, 0xA4, 0xAB, 0xAC, 0xAE, 0xAF, 0xB1, 0xB3, 0xB6, 
+	0xBA, 0xBE, 0x81, 0x89, 0x8B, 0x8F, 0x91, 0x95, 0x98, 0x9A, 0x9B, 0x9D, 0x9E, 0x9F, 0xA6, 0xA7, 
+	0xAC, 0xB0, 0xB2, 0xBE, 0x8C, 0x91, 0x98, 0xA3, 0xAB, 0xAF, 0xB0, 0xB8, 0xBC, 0xBD, 0x89, 0x8A, 
+	0x8E, 0x92, 0x99, 0xAC, 0xAD, 0xAE, 0xAF, 0xB3, 0xB8, 0xB9, 0xBA, 0x88, 0x8B, 0x8F, 0x99, 0x9D, 
+	0x9F, 0xB1, 0xB9, 0xBD, 0x89, 0x94, 0x99, 0x9A, 0x9C, 0xA1, 0xA6, 0xB6, 0xBC, 0x89, 0x8C, 0x8E, 
+	0x95, 0x96, 0x99, 0xA2, 0xA4, 0xA5, 0xA6, 0xA7, 0xA9, 0xAC, 0xAE, 0xBD, 0x84, 0x88, 0x8A, 0x8F, 
+	0x94, 0x95, 0x99, 0x9F, 0xA8, 0xAC, 0xB1, 0xB9, 0xBE, 0x83, 0x88, 0x89, 0x8E, 0x90, 0x92, 0x94, 
+	0x95, 0x97, 0x9F, 0xA0, 0xA5, 0xA6, 0xA7, 0xAC, 0xAD, 0xAE, 0xB5, 0xB9, 0xBB, 0xBC, 0xBF, 0x86, 
+	0x8D, 0x90, 0x9B, 0xA8, 0xAA, 0xAC, 0xAD, 0xB0, 0xB2, 0xB5, 0xB6, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 
+	0xBF, 0x80, 0x86, 0x87, 0x88, 0x8B, 0x8C, 0x92, 0x98, 0x99, 0x9B, 0x9D, 0x9F, 0xA1, 0xA2, 0xA7, 
+	0xA9, 0xB2, 0xB4, 0xB9, 0xBD, 0xBE, 0x80, 0x81, 0x82, 0x87, 0x92, 0x96, 0xA0, 0xA2, 0xA7, 0xAC, 
+	0xAF, 0xB2, 0xB6, 0xB9, 0x82, 0x83, 0x84, 0x86, 0x8E, 0x90, 0x92, 0x97, 0x99, 0x9B, 0xA0, 0xA1, 
+	0xA2, 0xA9, 0xAC, 0xAD, 0xB7, 0xB8, 0xB9, 0xBC, 0xBD, 0x8A, 0x96, 0x97, 0x9B, 0x9C, 0x9D, 0x9F, 
+	0xA5, 0xA9, 0xAA, 0xAB, 0xAE, 0xAF, 0xB4, 0xB6, 0xB7, 0xBE, 0xBF, 0x84, 0x85, 0x8E, 0x8F, 0x97, 
+	0xA3, 0xA8, 0xAA, 0xB0, 0xB2, 0xB5, 0xB8, 0xBA, 0xBB, 0x84, 0x87, 0x89, 0x8B, 0x96, 0xA9, 0xB2, 
+	0xB3, 0xBB, 0x80, 0x82, 0x88, 0x8A, 0x8D, 0x8E, 0x9E, 0xA0, 0xA5, 0xAA, 0xAD, 0xAE, 0xB1, 0xB8, 
+	0xBE, 0x83, 0x85, 0x86, 0x89, 0xA2, 0xA5, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xBA, 0xBF, 0x81, 0x95, 
+	0x99, 0x9A, 0x9B, 0x9C, 0x9E, 0x9F, 0xA0, 0xA3, 0xA4, 0xA9, 0xAA, 0xAF, 0xB0, 0xB3, 0xB6, 0xBE, 
+	0x83, 0x8B, 0x9E, 0xA2, 0xA7, 0xB0, 0xBD, 0x8A, 0x8F, 0x94, 0x9C, 0xA0, 0xA2, 0xA3, 0xA6, 0xA7, 
+	0xA9, 0xAE, 0xB0, 0xB1, 0xB2, 0xB6, 0xB7, 0xB8, 0x83, 0x84, 0x85, 0x8C, 0x8D, 0x8E, 0x91, 0x93, 
+	0x95, 0x98, 0x9A, 0x9C, 0x9E, 0x9F, 0xA3, 0xA5, 0xA6, 0xA8, 0xAB, 0xAC, 0xB0, 0xB1, 0xB2, 0xB3, 
+	0xB7, 0xB8, 0xBA, 0xBB, 0xBC, 0x84, 0x86, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8F, 0x91, 0x94, 0x99, 
+	0x9A, 0x9B, 0x9C, 0x9D, 0xA0, 0xA2, 0xA4, 0xA5, 0xA6, 0xA7, 0xA9, 0xAA, 0xAB, 0xAD, 0xB0, 0xB3, 
+	0xB4, 0xB6, 0xB7, 0xB8, 0xBF, 0x82, 0x86, 0x87, 0x89, 0x8A, 0x8B, 0x8E, 0x8F, 0x91, 0x94, 0x9A, 
+	0x9D, 0xA3, 0xA5, 0xAB, 0xB1, 0xB2, 0xB3, 0xB5, 0xB8, 0xB9, 0xBC, 0xBD, 0xBE, 0x82, 0x83, 0x85, 
+	0x87, 0x8A, 0x8D, 0x92, 0x94, 0x95, 0x98, 0x99, 0x9B, 0x9E, 0xA2, 0xA3, 0xA9, 0xB0, 0xB2, 0xB3, 
+	0xB4, 0xBA, 0xBC, 0xBE, 0xBF, 0x81, 0x89, 0x8B, 0x8D, 0x9F, 0xA0, 0xA1, 0xA2, 0xA4, 0xA7, 0xB0, 
+	0xB4, 0xBB, 0x82, 0x86, 0x87, 0x88, 0x8C, 0x92, 0x96, 0x98, 0x9C, 0xA1, 0xA2, 0xA7, 0xA8, 0xA9, 
+	0xAA, 0xAC, 0xB0, 0xB2, 0xB6, 0xB8, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0x80, 0x83, 0x84, 0x86, 0x87, 
+	0x88, 0x8B, 0x8E, 0x90, 0x93, 0x96, 0x99, 0x9A, 0xAE, 0xB0, 0xB4, 0xB7, 0xB8, 0xB9, 0xBA, 0xBF, 
+	0x82, 0x83, 0x86, 0x88, 0x8A, 0x8D, 0x92, 0x96, 0x97, 0x9B, 0x9C, 0x9E, 0x9F, 0xA1, 0xA3, 0xA4, 
+	0xA5, 0xA7, 0xAA, 0xAE, 0xB2, 0xB4, 0xB8, 0xBB, 0xBE, 0x81, 0x84, 0x87, 0x88, 0x89, 0x8B, 0x8C, 
+	0x9B, 0x9E, 0x9F, 0xA0, 0xA4, 0xA5, 0xA6, 0xA9, 0xB7, 0xB8, 0xBA, 0xBC, 0x80, 0x87, 0x9A, 0x9B, 
+	0xA1, 0xA3, 0xA5, 0xA6, 0xA8, 0xAB, 0xB9, 0xBE, 0xBF, 0x8B, 0x8E, 0x91, 0x9E, 0xA0, 0xA5, 0xAC, 
+	0xAD, 0xB0, 0xB3, 0xB6, 0xB9, 0xBB, 0xBC, 0xBD, 0xBF, 0x87, 0x8D, 0x97, 0x9A, 0x9B, 0x9C, 0xA2, 
+	0xA3, 0xA5, 0xA7, 0xA9, 0xAD, 0xAE, 0xAF, 0xB3, 0xBC, 0x82, 0x8C, 0x92, 0x94, 0x95, 0xA0, 0xA5, 
+	0xA6, 0xA7, 0xB2, 0xB4, 0xBA, 0xBF, 0x85, 0x9D, 0xAB, 0xAC, 0xAF, 0xB2, 0xB4, 0xBC, 0x81, 0x86, 
+	0x87, 0x8C, 0x8D, 0x8E, 0x91, 0x93, 0x95, 0x97, 0x9A, 0xA3, 0xA7, 0xA9, 0xAA, 0xAF, 0xB5, 0xBA, 
+	0xBC, 0xBE, 0x81, 0x85, 0x86, 0x8A, 0x8B, 0x90, 0x91, 0x94, 0x9A, 0xA7, 0xA8, 0xAC, 0xAF, 0xB4, 
+	0xBD, 0x81, 0x87, 0x8E, 0x91, 0x92, 0x99, 0xA6, 0xAA, 0xAB, 0xAC, 0xBA, 0xBC, 0xBE, 0x80, 0x81, 
+	0x87, 0x88, 0x89, 0x90, 0x93, 0x95, 0x96, 0x97, 0x9A, 0x9D, 0x9E, 0x9F, 0xA0, 0xA2, 0xA5, 0xA8, 
+	0xAD, 0xB7, 0xBA, 0xBF, 0x80, 0x81, 0x84, 0x85, 0x8A, 0x8D, 0x8E, 0x8F, 0x9D, 0xA6, 0xA7, 0xAA, 
+	0xAE, 0xB0, 0xB3, 0xB9, 0xBA, 0xBD, 0xBE, 0xBF, 0x80, 0x81, 0x89, 0x8B, 0x91, 0x92, 0x95, 0x98, 
+	0x9F, 0xA1, 0xA3, 0xA4, 0xA6, 0xA7, 0xA9, 0xAC, 0xB0, 0xBB, 0x80, 0x88, 0x8B, 0x8D, 0x8E, 0x94, 
+	0x97, 0x98, 0x99, 0x9A, 0x9C, 0x9F, 0xA0, 0xAE, 0xB1, 0xB2, 0xB7, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 
+	0x80, 0x82, 0x83, 0x86, 0x89, 0x8D, 0x8E, 0x8F, 0x90, 0x97, 0xA1, 0xA2, 0xA3, 0xA9, 0xAB, 0xB0, 
+	0xB4, 0xB6, 0xB9, 0xBA, 0xBD, 0xBF, 0x81, 0x83, 0x84, 0x88, 0x92, 0x93, 0x95, 0x96, 0x97, 0x98, 
+	0x9F, 0xA9, 0xAA, 0xAE, 0xAF, 0xB0, 0xB6, 0xBA, 0xBF, 0x83, 0x84, 0x85, 0x87, 0x88, 0x8A, 0x8B, 
+	0x8D, 0x8F, 0x92, 0x93, 0x95, 0x99, 0x9A, 0x9C, 0x9D, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA5, 0xA6, 
+	0xAA, 0xAD, 0xAF, 0xB0, 0xB6, 0xB8, 0xB9, 0xBA, 0xBF, 0x82, 0x84, 0x86, 0x88, 0x8A, 0x8B, 0x8F, 
+	0x91, 0x98, 0x99, 0x9B, 0x9E, 0xA0, 0xA5, 0xA6, 0xA8, 0xAC, 0xB3, 0xB5, 0xB6, 0xB9, 0x85, 0x86, 
+	0x88, 0x89, 0x8B, 0x8C, 0x8D, 0x8F, 0x90, 0x91, 0x92, 0x94, 0x96, 0x9D, 0xA5, 0xA7, 0xAC, 0xAE, 
+	0xB0, 0xB1, 0xB4, 0xB5, 0xBA, 0x86, 0x87, 0x8B, 0x8D, 0x8F, 0x92, 0x94, 0x95, 0x97, 0x98, 0x99, 
+	0x9A, 0x9C, 0x9D, 0x9F, 0xA1, 0xAA, 0xAD, 0xB1, 0xB4, 0xB8, 0x80, 0x81, 0x84, 0x86, 0x87, 0x89, 
+	0x8B, 0x8C, 0x8F, 0x9D, 0xA0, 0xA4, 0xA5, 0xA6, 0xA9, 0xAD, 0xB3, 0xB6, 0xB7, 0x80, 0x87, 0x8D, 
+	0x91, 0x92, 0x93, 0x94, 0x97, 0x9F, 0xA1, 0xA3, 0xA7, 0xAA, 0xAB, 0xB7, 0xB8, 0xBD, 0xBE, 0xBF, 
+	0x80, 0x83, 0x8C, 0x8D, 0x8F, 0x90, 0x94, 0x96, 0x98, 0x9F, 0xA0, 0xA4, 0xA5, 0xAC, 0xB3, 0xB5, 
+	0xBE, 0x81, 0x82, 0x83, 0x89, 0x8B, 0x8D, 0x90, 0x92, 0x95, 0x97, 0x98, 0x9B, 0x9F, 0xA1, 0xA2, 
+	0xA4, 0xA5, 0xA7, 0xA8, 0xAB, 0xAD, 0xAE, 0xB1, 0xB2, 0xB3, 0xB9, 0xBD, 0xBE, 0x80, 0x82, 0x85, 
+	0x8A, 0x8E, 0x92, 0x96, 0x98, 0x9C, 0x9E, 0x9F, 0xA0, 0xA2, 0xA7, 0xAF, 0xB2, 0xB4, 0xB6, 0xB8, 
+	0xBA, 0xBB, 0xBE, 0x80, 0x82, 0x84, 0x85, 0x86, 0x8A, 0x8B, 0x8D, 0x90, 0x94, 0x95, 0x97, 0x98, 
+	0x99, 0x9A, 0x9B, 0x9C, 0xA0, 0xA1, 0xA2, 0xAB, 0xAC, 0xAE, 0xAF, 0xB0, 0xB2, 0xB3, 0xB5, 0xB9, 
+	0xBA, 0xBF, 0x82, 0x83, 0x84, 0x85, 0x86, 0x8B, 0x8C, 0x8E, 0x8F, 0x90, 0x96, 0x9B, 0x9E, 0xA1, 
+	0xA2, 0xA3, 0xA6, 0xA8, 0xAE, 0xB1, 0xB2, 0xB3, 0xB5, 0xB6, 0xB9, 0xBD, 0x89, 0x8F, 0x93, 0x99, 
+	0x9A, 0x9B, 0x9C, 0x9F, 0xA2, 0xA3, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB4, 0xB5, 
+	0xB8, 0xBA, 0xBB, 0xBD, 0xBE, 0xBF, 0x87, 0x8A, 0x8B, 0x8F, 0x91, 0x92, 0x95, 0x98, 0x9A, 0x9C, 
+	0x9D, 0x9E, 0xA0, 0xA1, 0xA4, 0xA8, 0xA9, 0xAC, 0xAF, 0xB2, 0xB4, 0xBB, 0x81, 0x84, 0x85, 0x89, 
+	0x8A, 0x8B, 0x92, 0x9B, 0x9E, 0x9F, 0xA1, 0xA2, 0xA3, 0xA6, 0xAB, 0xAE, 0xB1, 0xB2, 0xB5, 0xB7, 
+	0xB9, 0xBA, 0xBB, 0xBD, 0xBE, 0x81, 0x83, 0x86, 0x8A, 0x8B, 0x8D, 0x94, 0x95, 0x96, 0x99, 0x9A, 
+	0x9D, 0x9E, 0xA6, 0xA7, 0xA9, 0xAA, 0xAD, 0xB0, 0xB9, 0xBB, 0xBC, 0xBD, 0xBF, 0x82, 0x83, 0x88, 
+	0x89, 0x8C, 0x8E, 0x8F, 0x90, 0x92, 0x93, 0x94, 0x96, 0x9B, 0x9C, 0xB6, 0xB8, 0xBA, 0x85, 0x8C, 
+	0x8D, 0x8E, 0x90, 0x91, 0x94, 0x95, 0x98, 0x9F, 0xA0, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAE, 0xB0, 
+	0xB2, 0xB5, 0xB7, 0xB8, 0xB9, 0x82, 0x83, 0x85, 0x86, 0x87, 0x88, 0x8A, 0x8C, 0x8E, 0x94, 0x9A, 
+	0x9D, 0x9E, 0xA3, 0xA4, 0xA8, 0xA9, 0xAE, 0xAF, 0xB2, 0xB6, 0xB8, 0xB9, 0xBD, 0x81, 0x85, 0x86, 
+	0x8A, 0x8C, 0x92, 0x94, 0x95, 0xA0, 0xA1, 0xA6, 0xA9, 0xAB, 0xB0, 0xB3, 0xB9, 0xBB, 0xBC, 0x80, 
+	0x81, 0x83, 0x84, 0x85, 0x86, 0x8B, 0x8C, 0x90, 0x92, 0x95, 0x97, 0x98, 0x99, 0x9C, 0xA1, 0xA8, 
+	0xB3, 0xB6, 0xBB, 0xBD, 0xBF, 0x86, 0x8A, 0x92, 0x96, 0x98, 0x9A, 0x9E, 0x9F, 0xA1, 0xA2, 0xA8, 
+	0xAF, 0xB0, 0xB2, 0xB3, 0xB4, 0xB6, 0xB7, 0xB9, 0xBD, 0xBE, 0xBF, 0x84, 0x85, 0x86, 0x87, 0x89, 
+	0x8B, 0x8C, 0x93, 0x96, 0x98, 0x9A, 0x9B, 0x9D, 0xA1, 0xA2, 0xA5, 0xA9, 0xAA, 0xAC, 0xAD, 0xAF, 
+	0xB1, 0xB2, 0xB4, 0xBA, 0x83, 0x84, 0x86, 0x8C, 0x8E, 0x96, 0x99, 0x9A, 0x9B, 0x9D, 0x9E, 0xA1, 
+	0xA4, 0xA5, 0xAF, 0xB1, 0xB4, 0xB8, 0xBC, 0xBD, 0x82, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x9A, 
+	0x9B, 0xA3, 0xA9, 0xAF, 0xB1, 0xB3, 0xB9, 0xBE, 0x86, 0x8B, 0x8E, 0x90, 0x91, 0x93, 0x94, 0x95, 
+	0x9F, 0xA5, 0xA6, 0xAB, 0xAE, 0xB0, 0xB1, 0xB4, 0xB8, 0xB9, 0xBA, 0xBF, 0x80, 0x82, 0x83, 0x88, 
+	0x8A, 0x8F, 0x93, 0x95, 0x9A, 0x9C, 0x9D, 0xA0, 0xA3, 0xA4, 0xA8, 0xA9, 0xB0, 0xB3, 0xB5, 0xB8, 
+	0xBA, 0xBD, 0xBE, 0xBF, 0x80, 0x82, 0x86, 0x88, 0x89, 0x8D, 0x91, 0x93, 0x98, 0x99, 0x9A, 0x9F, 
+	0xA0, 0xA3, 0xA5, 0xA7, 0xA8, 0xAA, 0xAD, 0xB3, 0xB4, 0xBA, 0xBB, 0xBC, 0xBE, 0x81, 0x82, 0x85, 
+	0x87, 0x88, 0x89, 0x8A, 0x8C, 0x8D, 0x8E, 0x90, 0x92, 0x96, 0x97, 0x98, 0x9B, 0x9C, 0x9E, 0x9F, 
+	0xA9, 0xAA, 0xAB, 0xAC, 0xAE, 0xB3, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0x80, 0x87, 0x98, 0x99, 0x9A, 
+	0x9D, 0x9F, 0xA2, 0xA4, 0xA6, 0xA8, 0xAA, 0xAB, 0xAE, 0xAF, 0xB1, 0xB2, 0xB6, 0xB7, 0xB8, 0xBE, 
+	0x8B, 0x8D, 0x92, 0x99, 0x9D, 0x9F, 0xA5, 0xA6, 0xAB, 0xAC, 0xAD, 0xAF, 0xB1, 0xB3, 0xB8, 0xB9, 
+	0xBB, 0xBD, 0x85, 0x91, 0x92, 0x93, 0x94, 0x97, 0x99, 0x9B, 0x9C, 0x9E, 0x9F, 0xA1, 0xA3, 0xA5, 
+	0xA6, 0xA7, 0xAB, 0xB1, 0xB3, 0xB4, 0xB9, 0xBA, 0xBB, 0x82, 0x83, 0x84, 0x85, 0x86, 0x89, 0x8E, 
+	0x96, 0x97, 0x98, 0x9C, 0xA3, 0xA8, 0xAB, 0xAF, 0xB1, 0xB2, 0xB4, 0xB5, 0xB6, 0xB8, 0xB9, 0x80, 
+	0x85, 0x89, 0x8A, 0x8F, 0x90, 0x92, 0x98, 0xB3, 0xB5, 0xB7, 0xBB, 0xBC, 0x85, 0x87, 0x89, 0x8A, 
+	0x8E, 0x93, 0x96, 0x9A, 0x9E, 0x9F, 0xA0, 0xA2, 0xA8, 0xAA, 0xAB, 0xB1, 0xB5, 0xBD, 0x81, 0x85, 
+	0x8A, 0x8C, 0x8E, 0x93, 0x96, 0x98, 0x9C, 0x9F, 0xA0, 0xA9, 0xAB, 0xAF, 0xB0, 0xB1, 0xB2, 0xB4, 
+	0xB7, 0xBB, 0xBD, 0x83, 0x84, 0x87, 0x8B, 0x8C, 0x8D, 0x8E, 0x93, 0xA0, 0xA2, 0xA9, 0xAA, 0xAC, 
+	0xB1, 0xB5, 0xB8, 0xBC, 0xBD, 0x86, 0x89, 0x8E, 0x97, 0x9B, 0xA1, 0xA2, 0xA3, 0xA6, 0xA9, 0xAB, 
+	0xAC, 0xAD, 0xAE, 0xAF, 0xB1, 0xB5, 0xB7, 0xB9, 0xBA, 0x82, 0x84, 0x8B, 0x90, 0x94, 0x99, 0x9C, 
+	0x9F, 0xA1, 0xAD, 0xB2, 0xB8, 0xB9, 0xBB, 0xBC, 0xBF, 0x81, 0x84, 0x86, 0x89, 0x8A, 0x8B, 0x8D, 
+	0x90, 0x91, 0x96, 0x99, 0x9A, 0xAC, 0xAE, 0xB4, 0xBC, 0xBF, 0x80, 0x86, 0x91, 0x93, 0x94, 0x95, 
+	0x97, 0x98, 0x9A, 0x9F, 0xA1, 0xA6, 0xAC, 0xAD, 0xB5, 0xBD, 0x80, 0x81, 0x83, 0x88, 0x89, 0x8A, 
+	0x8B, 0x8E, 0x95, 0x97, 0x98, 0x9A, 0xA3, 0xA8, 0xA9, 0xAA, 0xAD, 0xB7, 0xBE, 0x80, 0x84, 0x87, 
+	0x88, 0x8A, 0x90, 0x91, 0x94, 0x97, 0x99, 0x9B, 0x9C, 0xA4, 0xA6, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 
+	0xAE, 0xAF, 0xB9, 0xBA, 0x81, 0x89, 0x8D, 0x8F, 0x90, 0x95, 0x9C, 0x9D, 0xA4, 0xA5, 0xA9, 0xAA, 
+	0xB7, 0xB9, 0xBA, 0xBB, 0xBE, 0x82, 0x86, 0x87, 0x8A, 0x8B, 0x93, 0x96, 0x97, 0x9A, 0xA2, 0xAD, 
+	0xAF, 0xB0, 0xBF, 0x8D, 0x8E, 0x90, 0x94, 0x95, 0x9A, 0x9C, 0x9E, 0x9F, 0xA7, 0xAB, 0xB1, 0xB9, 
+	0xBB, 0x8A, 0x8B, 0x8C, 0x93, 0x95, 0xA3, 0xA4, 0xA9, 0xAA, 0xAB, 0xAF, 0xB0, 0xB6, 0x84, 0x86, 
+	0x87, 0x89, 0x8B, 0x8D, 0x8E, 0x94, 0x99, 0x9B, 0x9E, 0x9F, 0xA4, 0xA9, 0xAC, 0xAD, 0xAE, 0xAF, 
+	0xB8, 0xB9, 0xBB, 0xBE, 0x80, 0x82, 0x83, 0x86, 0x88, 0x89, 0x8A, 0x8D, 0x91, 0x92, 0x98, 0x9A, 
+	0x9C, 0xA5, 0xA9, 0xB4, 0xB7, 0xBB, 0xBF, 0x89, 0x8B, 0x8C, 0x8E, 0x93, 0x95, 0x97, 0x99, 0x9F, 
+	0xA0, 0xA3, 0xA6, 0xA8, 0xAA, 0xAE, 0xB4, 0xB6, 0xB8, 0xBF, 0x82, 0x8D, 0x9F, 0xA2, 0xAB, 0xAF, 
+	0xB3, 0xBA, 0xBB, 0xBD, 0x80, 0x84, 0x86, 0x87, 0x8B, 0x90, 0x92, 0xA0, 0xAF, 0xB2, 0xB6, 0xB7, 
+	0xB9, 0xBB, 0xBE, 0x85, 0x8D, 0x8E, 0x8F, 0x91, 0x95, 0x96, 0xA1, 0xA2, 0xA3, 0xA7, 0xB1, 0xB6, 
+	0xB9, 0xBB, 0x80, 0x82, 0x84, 0x86, 0x8C, 0x8D, 0x92, 0x93, 0x97, 0x99, 0x9B, 0x9D, 0x9E, 0xA1, 
+	0xA2, 0xA3, 0xA8, 0xAB, 0xB0, 0xB2, 0xB5, 0xB7, 0xBD, 0xBE, 0xBF, 0x81, 0x82, 0x88, 0x8B, 0x8D, 
+	0x92, 0x96, 0x97, 0x99, 0x9E, 0xA2, 0xA4, 0xAB, 0xAE, 0xB0, 0xB1, 0xB4, 0xB5, 0xB7, 0xBF, 0x81, 
+	0x82, 0x83, 0x84, 0x85, 0x8F, 0x94, 0x95, 0x98, 0x99, 0x9C, 0x9D, 0x9F, 0xA1, 0xA8, 0xB2, 0xB3, 
+	0xB4, 0xB8, 0xB9, 0xBC, 0xBD, 0xBE, 0x82, 0x84, 0x87, 0x8A, 0x8C, 0x90, 0x92, 0x93, 0x9D, 0x9E, 
+	0xA5, 0xAA, 0xAB, 0xB6, 0xB8, 0xBB, 0x81, 0x83, 0x84, 0x8C, 0x8D, 0x96, 0x9E, 0x9F, 0xA0, 0xA4, 
+	0xA6, 0xAA, 0xAD, 0xAF, 0xB2, 0xB4, 0xB7, 0xBE, 0xBF, 0x81, 0x83, 0x86, 0x87, 0x88, 0x8A, 0x8B, 
+	0x8F, 0x93, 0x96, 0x97, 0x98, 0x9A, 0xA1, 0xA6, 0xA7, 0xA9, 0xAA, 0xAC, 0xAF, 0xB2, 0xB3, 0xBA, 
+	0xBD, 0xBF, 0x80, 0x92, 0x9A, 0x9C, 0x9D, 0xA3, 0xA6, 0xA7, 0xB4, 0xB8, 0x80, 0x82, 0x83, 0x88, 
+	0x8A, 0x8C, 0x8E, 0x90, 0x93, 0x96, 0x97, 0x98, 0x9B, 0x9D, 0x9F, 0xA3, 0xA5, 0xAA, 0xAD, 0xB1, 
+	0xB3, 0xB4, 0xB6, 0xBA, 0xBB, 0xBC, 0x81, 0x86, 0x88, 0x90, 0x91, 0x92, 0x94, 0x95, 0x9B, 0x9E, 
+	0xA0, 0xA2, 0xA3, 0xA6, 0xA9, 0xAB, 0xAC, 0xAD, 0xAE, 0xB0, 0xB1, 0xB2, 0xB3, 0xBC, 0x82, 0x84, 
+	0x85, 0x87, 0x89, 0x8C, 0x8D, 0x91, 0x93, 0x95, 0x98, 0x9A, 0x9E, 0xA0, 0xA1, 0xA3, 0xA4, 0xA5, 
+	0xA6, 0xA8, 0xAC, 0xAD, 0xB0, 0xB2, 0xB9, 0xBC, 0xBF, 0x82, 0x84, 0x87, 0x8B, 0x8C, 0x8D, 0x8F, 
+	0x92, 0x96, 0x9A, 0x9B, 0x9C, 0x9E, 0xA0, 0xA1, 0xA2, 0xA4, 0xA6, 0xA7, 0xAB, 0xAD, 0xAE, 0xB1, 
+	0xB3, 0xB7, 0xB8, 0xBA, 0xBE, 0x80, 0x81, 0x82, 0x84, 0x87, 0x8C, 0x8E, 0x90, 0x94, 0x96, 0x97, 
+	0x99, 0x9A, 0x9B, 0x9D, 0xA0, 0xA1, 0xA6, 0xA8, 0xAB, 0xAC, 0xB3, 0xB9, 0xBE, 0x81, 0x89, 0x8C, 
+	0x8E, 0x8F, 0x96, 0x98, 0x9A, 0x9B, 0x9C, 0x9F, 0xA6, 0xAB, 0xAC, 0xAF, 0xB0, 0xB1, 0xB2, 0xB4, 
+	0xB7, 0xBD, 0x80, 0x83, 0x8A, 0x8C, 0x8E, 0x90, 0x92, 0x93, 0x96, 0x99, 0x9A, 0xB7, 0xBA, 0xBF, 
+	0x81, 0x86, 0x88, 0x8A, 0x8C, 0x8E, 0x90, 0x95, 0x9A, 0xA1, 0xA2, 0xAA, 0xAB, 0xAC, 0xB8, 0xB9, 
+	0xBA, 0xBC, 0x82, 0x85, 0x89, 0x8A, 0x8C, 0x8D, 0x8E, 0x94, 0x98, 0x9D, 0x9E, 0xA0, 0xA1, 0xA2, 
+	0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB2, 0xB3, 0xB4, 0xB6, 0xB7, 0xB8, 
+	0xBB, 0xBC, 0xBD, 0xBF, 0x80, 0x81, 0x82, 0x83, 0x84, 0x87, 0x88, 0x8A, 0x8D, 0x8E, 0x91, 0x93, 
+	0x9A, 0x9B, 0x9C, 0x9E, 0xA0, 0xA2, 0xA3, 0xA4, 0xA6, 0xAA, 0xAD, 0xBA, 0xBB, 0xBC, 0xBD, 0x84, 
+	0x85, 0x87, 0x88, 0x8A, 0x8B, 0x8D, 0x8F, 0x90, 0x93, 0x94, 0x96, 0xA4, 0xA6, 0xA7, 0xAB, 0xAD, 
+	0xB0, 0xB1, 0xB3, 0xB4, 0xB7, 0x81, 0x85, 0x8A, 0x99, 0xA3, 0xA8, 0xB3, 0xBA, 0xBE, 0x82, 0x8B, 
+	0x8C, 0x8F, 0x96, 0x9A, 0x9B, 0x9D, 0x9F, 0xA1, 0xA3, 0xA8, 0xAA, 0xAB, 0xAF, 0xB3, 0xB5, 0xBC, 
+	0xBF, 0x88, 0x89, 0x8A, 0x8F, 0x90, 0x9D, 0x9E, 0x9F, 0xAA, 0xB0, 0xB4, 0xB5, 0x82, 0x84, 0x87, 
+	0x88, 0x89, 0x8A, 0x8C, 0x90, 0x95, 0x99, 0x9F, 0xA0, 0xA3, 0xA4, 0xB2, 0xB4, 0xB6, 0xBC, 0x81, 
+	0x84, 0x85, 0x87, 0x8A, 0x8B, 0x8D, 0x91, 0x93, 0x94, 0x99, 0xA1, 0xAA, 0xAB, 0xAC, 0xAF, 0xB0, 
+	0xB1, 0xBE, 0x85, 0x86, 0x88, 0x8A, 0x8B, 0x8C, 0x8D, 0x92, 0x9B, 0x9F, 0xA2, 0xA3, 0xAB, 0xB8, 
+	0xBB, 0xBC, 0xBD, 0xBE, 0x83, 0x85, 0x89, 0x8A, 0x8C, 0x92, 0x93, 0x94, 0x95, 0x99, 0x9B, 0x9C, 
+	0x9D, 0x9F, 0xA6, 0xA9, 0xAA, 0xAF, 0xB3, 0xB8, 0xB9, 0xBB, 0xBE, 0xBF, 0x82, 0x84, 0x85, 0x86, 
+	0x89, 0x8C, 0x8D, 0x8E, 0x97, 0x9C, 0x9F, 0xA1, 0xA2, 0xA3, 0xA4, 0x9B, 0x9C, 0x9E, 0x9F, 0xA3, 
+	0xA7, 0xA8, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB7, 0xBA, 0xBB, 0xBC, 0xBF, 0x82, 0x84, 0x85, 
+	0x8E, 0x91, 0x94, 0x9A, 0xA2, 0xA5, 0xA6, 0xA9, 0xAA, 0xAB, 0xAD, 0xAF, 0xB0, 0xB4, 0xB7, 0xB8, 
+	0xB9, 0xBA, 0xBD, 0x80, 0x81, 0x83, 0x85, 0x86, 0x8B, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x93, 0x94, 
+	0x95, 0x96, 0x97, 0x99, 0x9A, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA7, 0xAE, 0xB1, 0xB2, 
+	0xB5, 0xB6, 0xB8, 0xB9, 0xBC, 0xBE, 0x81, 0x82, 0x85, 0x87, 0x89, 0x8A, 0x8B, 0x8D, 0x8E, 0x8F, 
+	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x98, 0x99, 0x9C, 0x9E, 0xA0, 0xA1, 0xA3, 0xA5, 0xA8, 
+	0xA9, 0xAD, 0xAE, 0xAF, 0xB2, 0xB5, 0xB6, 0xB7, 0xB8, 0xBA, 0xBC, 0xBD, 0xBF, 0x80, 0x81, 0x82, 
+	0x83, 0x84, 0x87, 0x89, 0x8A, 0x8F, 0x91, 0xA3, 0xA6, 0xA8, 0xAA, 0xAF, 0xB1, 0xB5, 0xB8, 0x81, 
+	0x8A, 0x8E, 0x9B, 0xA1, 0xA2, 0xA4, 0xA8, 0xAD, 0xB5, 0xB7, 0xBD, 0x82, 0x92, 0x99, 0xAD, 0xB0, 
+	0xB2, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x92, 0x94, 0x96, 0x98, 0xA2, 0xA3, 0xA5, 0xA9, 0xAA, 
+	0xAC, 0xB2, 0xB3, 0xB5, 0xB7, 0xB8, 0x82, 0x87, 0x89, 0x8B, 0x8D, 0x90, 0x92, 0x97, 0x9C, 0xA2, 
+	0xA4, 0xAA, 0xAB, 0xAF, 0xB4, 0xB5, 0xB8, 0xBA, 0x80, 0x81, 0x86, 0x87, 0x88, 0x89, 0x8B, 0x8C, 
+	0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x96, 0x98, 0x9B, 0x9C, 0x9D, 0x9F, 0xA1, 0xA3, 0xA6, 0xA7, 0xB5, 
+	0xB6, 0xBC, 0xBF, 0x8D, 0x8E, 0x91, 0x94, 0x95, 0x9E, 0xA9, 0xAC, 0xB4, 0xB7, 0xBF, 0x84, 0x85, 
+	0x88, 0x89, 0x8B, 0x90, 0x97, 0x9A, 0x9B, 0x9E, 0xA2, 0xA4, 0xA6, 0xB1, 0xBE, 0x80, 0x83, 0x85, 
+	0x91, 0x93, 0x95, 0x96, 0x98, 0x9A, 0x9B, 0x9C, 0xAD, 0xB7, 0xB9, 0x8F, 0x92, 0xA4, 0xA9, 0xAA, 
+	0xAD, 0xB2, 0xB3, 0xB8, 0xBA, 0xBC, 0x86, 0x8F, 0x90, 0x98, 0x99, 0x9A, 0xA0, 0xA2, 0xA3, 0xA6, 
+	0xA8, 0xAB, 0xAC, 0xAE, 0xAF, 0xB2, 0xB5, 0xBA, 0xBB, 0x84, 0x8B, 0x8D, 0x94, 0x96, 0x9B, 0x9C, 
+	0xA0, 0xAC, 0xAE, 0xB5, 0xBC, 0xBE, 0x8C, 0x94, 0x96, 0x97, 0x9A, 0xA7, 0xAC, 0xAD, 0xAE, 0xB0, 
+	0xB9, 0x83, 0x88, 0x90, 0x91, 0x96, 0x97, 0x98, 0x9D, 0xA1, 0xA4, 0xA5, 0xA8, 0x83, 0x87, 0x90, 
+	0x93, 0x94, 0x98, 0x99, 0x9A, 0xA1, 0xAB, 0xB5, 0xB6, 0xB8, 0xBA, 0x81, 0x84, 0x91, 0x92, 0x93, 
+	0x9A, 0x9B, 0x9E, 0xA0, 0xA2, 0xAA, 0xB0, 0xB5, 0xB7, 0xBC, 0xBD, 0xBE, 0xBF, 0x81, 0xB7, 0x80, 
+	0x82, 0x83, 0x87, 0x89, 0x8A, 0x8B, 0x8F, 0x91, 0x93, 0x94, 0x96, 0x98, 0x99, 0xA0, 0xA2, 0xA3, 
+	0xA4, 0xA5, 0xA7, 0xA8, 0xAD, 0xB2, 0xB9, 0xBB, 0xBC, 0xBE, 0x83, 0x87, 0x8A, 0x8C, 0x8D, 0x94, 
+	0x95, 0x96, 0x98, 0x9C, 0xA1, 0xA2, 0xA5, 0x9C, 0xA1, 0xA8, 0xAA, 0xAE, 0xAF, 0xB2, 0xBB, 0xBF, 
+	0x80, 0x82, 0x84, 0x8B, 0x8C, 0x8D, 0x8F, 0x90, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA2, 0xA3, 0xA4, 
+	0xA5, 0xA6, 0xAA, 0xAC, 0xB0, 0xB2, 0xB3, 0xB5, 0xB6, 0xB7, 0xB8, 0xBA, 0xBD, 0x85, 0x86, 0x88, 
+	0x8A, 0x8B, 0x8D, 0x8E, 0x8F, 0x94, 0x95, 0x97, 0x98, 0x99, 0x9B, 0x9C, 0xA0, 0xA3, 0xA7, 0xA8, 
+	0xAA, 0xB0, 0xB1, 0xB2, 0xB4, 0xB6, 0xB7, 0xB8, 0xB9, 0xBB, 0xBC, 0x80, 0x81, 0x84, 0x85, 0x86, 
+	0x87, 0x89, 0x8B, 0x8C, 0x8D, 0x8E, 0x91, 0x95, 0x96, 0x99, 0x9B, 0x9C, 0xA2, 0xA3, 0xA8, 0xAA, 
+	0xAB, 0xB0, 0xB2, 0xB6, 0xB7, 0xB9, 0xBB, 0x80, 0x84, 0x86, 0x87, 0x88, 0x8A, 0x8D, 0x8E, 0x8F, 
+	0x91, 0x93, 0x96, 0x99, 0x9C, 0x9E, 0xA4, 0xA7, 0xAA, 0xB0, 0xB2, 0xB8, 0xB9, 0xBD, 0xBE, 0x82, 
+	0x84, 0x86, 0x88, 0x89, 0x92, 0x96, 0x99, 0x9C, 0x9E, 0xA0, 0xA1, 0xA2, 0xA4, 0xA6, 0xA8, 0xA9, 
+	0xAB, 0xAD, 0xB1, 0xB4, 0xB9, 0xBA, 0xBC, 0x81, 0x84, 0x85, 0x86, 0x8B, 0x8D, 0x8F, 0x90, 0x98, 
+	0x9C, 0xA0, 0xA3, 0xA6, 0xA8, 0xAB, 0xAD, 0xB3, 0xB4, 0x83, 0x86, 0x88, 0x8B, 0x93, 0x9C, 0xAD, 
+	0xAE, 0xB2, 0xB3, 0xB5, 0xB6, 0xBB, 0xBF, 0x81, 0x82, 0x83, 0x85, 0x86, 0x88, 0x8C, 0x8F, 0x90, 
+	0x91, 0x92, 0x93, 0x97, 0x98, 0x9A, 0xA1, 0xA4, 0xAC, 0xAD, 0xB4, 0xB7, 0xB8, 0xBB, 0xBC, 0xBD, 
+	0x86, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x94, 0x95, 0x98, 0x9B, 0x9E, 0xA7, 0xAB, 0xAF, 0xB0, 0xB1, 
+	0xB3, 0xB4, 0xA8, 0xAA, 0xAF, 0xB1, 0xB6, 0x83, 0x84, 0x86, 0x9B, 0x9C, 0x9F, 0xA2, 0xA9, 0xAB, 
+	0xAD, 0xAE, 0xAF, 0xB2, 0xB4, 0xBC, 0xBD, 0xBE, 0x83, 0x85, 0x89, 0x8A, 0x8C, 0x90, 0x92, 0x93, 
+	0x94, 0x98, 0x9D, 0x9E, 0xA0, 0xA1, 0xA4, 0xA8, 0xAC, 0xAE, 0xBD, 0xBE, 0x82, 0x85, 0x89, 0x8B, 
+	0x8C, 0x90, 0x91, 0x92, 0x95, 0x97, 0x96, 0x97, 0x98, 0x99, 0xA5, 0xA8, 0xAC, 0xAD, 0xAE, 0xB3, 
+	0xB4, 0xBC, 0x81, 0x84, 0x85, 0x86, 0x88, 0x90, 0x91, 0x92, 0x95, 0x98, 0x9B, 0x9D, 0x9F, 0xA2, 
+	0xAD, 0xAE, 0xB1, 0xB2, 0xB8, 0xBB, 0xBF, 0x81, 0x85, 0x8E, 0x8F, 0x92, 0x93, 0x99, 0xA8, 0xAB, 
+	0xB0, 0xB7, 0xBE, 0x80, 0x82, 0x83, 0x85, 0x8D, 0x95, 0x97, 0x9A, 0x9B, 0x9F, 0xA2, 0xA4, 0xA5, 
+	0xA9, 0xAA, 0xAB, 0xA8, 0xAD, 0xB0, 0xB8, 0xBC, 0x80, 0x84, 0x8F, 0x91, 0x93, 0x94, 0x98, 0x9E, 
+	0x9F, 0xA2, 0xA3, 0xA6, 0xAA, 0xAB, 0xAD, 0xAE, 0xAF, 0xB1, 0xB4, 0xB7, 0xBB, 0x86, 0x98, 0x9A, 
+	0x9F, 0xA2, 0xA3, 0xA5, 0xA7, 0xA8, 0xA9, 0xAA, 0xAE, 0xAF, 0xB1, 0xB2, 0xBB, 0xBC, 0x81, 0x82, 
+	0x83, 0x84, 0x85, 0x8D, 0x8E, 0x8F, 0x91, 0x94, 0x98, 0x9A, 0xAF, 0xB4, 0x83, 0x8E, 0x91, 0x92, 
+	0x93, 0x96, 0x97, 0x9F, 0xA0, 0xA8, 0xAA, 0xAB, 0xAD, 0xAE, 0xB4, 0xB9, 0x80, 0x86, 0x89, 0x8A, 
+	0x8F, 0x91, 0x92, 0x94, 0x96, 0x9B, 0xA1, 0xA2, 0xA3, 0xA4, 0xA8, 0xB0, 0xB1, 0xB2, 0xB5, 0x84, 
+	0x86, 0x88, 0x89, 0x8A, 0x8C, 0x8D, 0x90, 0x92, 0x93, 0x94, 0x95, 0x9B, 0xA1, 0xA4, 0xA5, 0xAD, 
+	0xAE, 0xAF, 0xB0, 0xB2, 0xB9, 0xBA, 0xBB, 0xBE, 0x86, 0x87, 0x88, 0x92, 0x97, 0x9A, 0xA0, 0xA7, 
+	0xB6, 0xB8, 0xA5, 0xA7, 0xA9, 0xAB, 0xAC, 0xB0, 0xB3, 0xB4, 0xB6, 0x83, 0x86, 0x87, 0x88, 0x89, 
+	0x8E, 0x92, 0x95, 0x9B, 0x9F, 0xA3, 0xA6, 0xA8, 0xAA, 0xAB, 0xAC, 0xBB, 0xBE, 0xBF, 0x81, 0x84, 
+	0x86, 0x88, 0x90, 0x91, 0x99, 0x9C, 0x9D, 0x9E, 0xA0, 0xA1, 0xA4, 0xAC, 0xAF, 0xB2, 0xBA, 0x87, 
+	0x89, 0x8F, 0x9A, 0xA4, 0xA9, 0xAB, 0xAF, 0xB2, 0xB4, 0xB8, 0xBA, 0xBB, 0x81, 0x82, 0x84, 0x86, 
+	0x8F, 0x93, 0x99, 0xA6, 0xAD, 0xAF, 0xB2, 0xB8, 0xB9, 0xBA, 0xBD, 0x9A, 0x9B, 0x9E, 0xB5, 0xB8, 
+	0xB9, 0xBD, 0xBF, 0x81, 0x88, 0x8B, 0x8C, 0x91, 0x92, 0x93, 0x95, 0x97, 0x9D, 0x9F, 0xA5, 0xA6, 
+	0xA9, 0xAA, 0xAD, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBE, 0xBF, 0x84, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 
+	0x92, 0x94, 0x98, 0x99, 0x9B, 0x9C, 0x9D, 0x9E, 0xA0, 0xA5, 0xA8, 0xAF, 0xB4, 0xB6, 0xB7, 0xB9, 
+	0xBB, 0xBC, 0xBD, 0x87, 0x88, 0x8E, 0x93, 0x95, 0xA0, 0xA1, 0xAC, 0xBB, 0xBE, 0x8A, 0x8B, 0x8E, 
+	0x8F, 0x92, 0x94, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA6, 0xA7, 0xAA, 0xAC, 0xB2, 0xB6, 0xB7, 0x8D, 
+	0x95, 0x9C, 0x9D, 0xA0, 0x81, 0x83, 0x84, 0x85, 0x86, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 
+	0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 
+	0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 
+	0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 
+	0xBF, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 
+	0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 
+	0xA0, 0xA1, 0xA2, 0xA3, 0xA5
+};
+
+
+#define UTF8_CODE_2B_1_NUM  (sizeof(Utf8CodeTable_2B_1st)/2)
+#define UTF8_CODE_3B_1_NUM  (sizeof(Utf8CodeTable_3B_1st)/2)
+#define UTF8_CODE_3B_2_NUM  (sizeof(Utf8CodeTable_3B_2nd)/2)
+#define UTF8_CODE_2B_2_NUM  sizeof(Utf8CodeTable_2B_2nd)
+#define UTF8_CODE_3B_3_NUM  sizeof(Utf8CodeTable_3B_3rd)
+
+static font_work_t FontWork[NUM_FONT_WORK];
+static uint8_t     font_data[256];
+#endif
+
+/*
+ *  フォントの幅を取得する
+ *  param1  phead: フォントヘッダ
+ *  param2  c: キャラクタ
+ *  param3  len:キャラクタの長さ領域へのポインタ
+ *  return  フォント幅
+ */
+static int
+GetFontWidth(font_head_t *phead, uint8_t c, int *len)
+{
+	const font_t  **pf = phead->font_table;
+	int   width;
+
+	width = phead->font_width;
+	*len = 1;
+	if(phead->file_attribute == 0){
+		if(c < 0x80 || c >= 0xA0)
+			width = pf[c]->width;
+	}
+	else if((c & 0xE0) == 0xC0)
+		*len = 2;
+	else if((c & 0xF0) == 0xE0)
+		*len = 3;
+	else if((c & 0xF8) == 0xF0)
+		*len = 4;
+	else if(c < 0x80 || c >= 0xA0)
+		width = pf[c]->width;
+	return width;
+}
+
+#ifndef NOT_USEFILFONT
+/*
+ *  2バイトコードビットマップ番号
+ */
+static int
+GetFont2BNo(font_work_t *pft, uint8_t *ptr)
+{
+	int      totalk = 0;
+	uint32_t i, j;
+
+	for(i = 0 ; i < UTF8_CODE_2B_1_NUM; i++){
+		if(Utf8CodeTable_2B_1st[i][0] == ptr[0]) {
+			for(j = 0 ; j < Utf8CodeTable_2B_1st[i][1] ; j++) {
+				if(Utf8CodeTable_2B_2nd[totalk] == ptr[1])
+					return totalk;
+				totalk++;
+			}
+		}
+		else
+			totalk += Utf8CodeTable_2B_1st[i][1];
+	}
+	return -1;
+}
+
+/*
+ *  3バイトコードビットマップ番号
+ */
+static int
+GetFont3BNo(font_work_t *pft, uint8_t *ptr)
+{
+	int      totalk = 0;
+	int      totalj = 0;
+	uint32_t i, j, k;
+
+	for(i = 0 ; i < UTF8_CODE_3B_1_NUM ; i++){
+		if(Utf8CodeTable_3B_1st[i][0] == ptr[0]){
+			for(j = 0 ; j < Utf8CodeTable_3B_1st[i][1]; j++){
+				if(Utf8CodeTable_3B_2nd[totalj][0] == ptr[1]){
+					for(k = 0 ; k < Utf8CodeTable_3B_2nd[totalj][1]; k++) {
+						if(Utf8CodeTable_3B_3rd[totalk] == ptr[2])
+							return totalk;
+						totalk++;
+					}
+					return -1;
+				}
+				else	/*読み飛ばすbitmap個数を蓄積*/
+					totalk += Utf8CodeTable_3B_2nd[totalj][1];
+				totalj++;
+			}
+		}
+		else{	/*読み飛ばすbitmap個数を蓄積*/
+			for(j = 0 ; j < Utf8CodeTable_3B_1st[i][1] ; j++){
+				totalk += Utf8CodeTable_3B_2nd[totalj][1];
+				totalj++;
+			}
+		}
+	}
+	return -1;
+}
+#endif
+
+/*
+ *  文字描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x0: 文字描画 X座標始点
+ *  param3  y0: 文字描画 Y座標始点
+ *  param4  c:  文字イメージへのポインタ
+ */
+#ifndef MAX_FONT_IMAGE
+static void
+DrawChar(LCD_DrawProp_t *pDrawProp, uint16_t x0, uint16_t y0, const font_t *pf)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	uint32_t h, w;
+	const uint8_t  *pchar;
+
+	for(h = 0 ; h < pf->height ; h++){
+		pchar = (pf->image + pf->stride * h);
+		for(w = 0; w < pf->width ; w++){
+			if(pf->stride != 0 && (pchar[w/8] & (1 << (7 - (w % 8)))) != 0){
+				lcd_drawPixel(hlcd, (x0 + w), (y0 + h), pDrawProp->TextColor);
+			}
+			else{
+				lcd_drawPixel(hlcd, (x0 + w), (y0 + h), pDrawProp->BackColor);
+			}
+		}
+	}
+}
+#else
+static void
+DrawChar(LCD_DrawProp_t *pDrawProp, uint16_t x0, uint16_t y0, const font_t *pf)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	uint32_t h, w;
+	const uint8_t *pchar;
+#ifdef TRS_COLOR_T
+	TRS_COLOR_T image[MAX_FONT_IMAGE];
+#else
+	color_t     image[MAX_FONT_IMAGE];
+#endif
+
+	for(h = 0 ; h < pf->height ; h++){
+		pchar = (pf->image + pf->stride * h);
+		for(w = 0; w < pf->width ; w++){
+			if(pf->stride != 0 && (pchar[w/8] & (1 << (7 - (w % 8)))) != 0){
+				image[w] = pDrawProp->TextColor;
+			}
+			else{
+				image[w] = pDrawProp->BackColor;
+			}
+		}
+		lcd_drawImageHLine(hlcd, x0, (y0 + h), pf->width, image);
+	}
+}
+#endif
+
+/*
+ *  一文字描画(UTF8)
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x0: 文字描画 X座標始点
+ *  param3  y0: 文字描画 Y座標始点
+ *  param4  描画コードへのポインタ
+ */
+static void
+lcd_DisplayData(LCD_DrawProp_t *pDrawProp, uint16_t x0, uint16_t y0, uint8_t *ptr)
+{
+	font_head_t  *phead = (font_head_t *)pDrawProp->pFont;
+	DrawChar(pDrawProp, x0, y0, lcd_getFontTable(phead, ptr));
+}
+
+/*
+ *  フォントデータからフォントテーブルを取り出す
+ *  param1  phead: フォントヘッダ
+ *  param2  ptr: フォントデータへのポインタ
+ *  return  フォントテーブルへのポインタ
+ */
+const font_t *
+lcd_getFontTable(font_head_t *phead, uint8_t *ptr)
+{
+	const font_t **pf = phead->font_table;
+	int len;
+#ifndef NOT_USEFILFONT
+	char  fname[32+4];
+	font_t *pwf = (font_t *)font_data;
+	font_file_head_t *pffh;
+	font_work_t  *pft = NULL;
+	int no, i, k, off = 0;
+#endif
+
+	GetFontWidth(phead, *ptr, &len);
+	if(len == 1)
+		return pf[*ptr];
+	else if(phead->file_attribute == 0)
+		return pf[*ptr];
+	else{
+#ifndef NOT_USEFILFONT
+		pwf->width   = phead->font_width;
+		pwf->height  = phead->font_height;
+		pwf->stride  = (phead->font_width + 7) >> 3;
+		pwf->iheight = phead->font_height;
+		memset(pwf->image, 0, pwf->height * pwf->stride);
+
+		if(phead->pdata == NULL){
+			for(i = 0 ; i < NUM_FONT_WORK ; i++){
+				if(FontWork[i].pffont == NULL){
+					pft = &FontWork[i];
+					break;
+				}
+			}
+			if(pft != NULL){
+				sprintf(fname, "%s.fnt", phead->font_name);
+				pft->pffont = fopen(fname, "rb");
+				if(pft->pffont != NULL){
+					if(fread(pft->table, sizeof(font_file_head_t), 1, pft->pffont) != 1){
+						phead->file_attribute = 0x00;
+						fclose(pft->pffont);
+						pft->pffont = NULL;
+					}
+					else{
+						pffh = (font_file_head_t *)pft->table;
+						pft->offset_image_2B = pffh->off_2byte_font;
+						pft->offset_image_3B = pffh->off_3byte_font;
+						pft->num_table2B = pffh->siz_2byte_font;
+						pft->num_table3B = pffh->siz_3byte_font;
+						pft->image_size  = pffh->csize + pffh->isize;
+						phead->pdata = pft;
+					}
+				}
+				else
+					phead->file_attribute = 0x00;
+			}
+			else
+				phead->file_attribute = 0x00;
+		}
+		if((pft = phead->pdata) != NULL){
+			no = -1;
+			if(len == 2){
+				no = GetFont2BNo(pft, ptr);
+				off = pft->offset_image_2B;
+			}
+			else if(len == 3){
+				no = GetFont3BNo(pft, ptr);
+				off = pft->offset_image_3B;
+			}
+			if(no >= 0){
+				uint32_t length = 0;
+				uint32_t data = 0, j, c;
+				fseek(pft->pffont, (no * pft->image_size + off), SEEK_SET);
+				fread(pft->table, pft->image_size, 1, pft->pffont);
+
+				for(i = j = k = no = 0 ; i < phead->font_height ; i++){
+					while(length < phead->font_width){
+						data <<= 8;
+						data |= pft->table[no+1];
+						length += 8;
+						no++;
+					}
+					j = phead->font_width;
+					while(j >= 8){
+						c = data >> (length - 8);
+						j -= 8;
+						length -= 8;
+						pwf->image[k++] = c;
+					}
+					if(j > 0){
+						c = data << (8-j);
+						length -= j;
+						pwf->image[k++] = c;
+					}
+				}
+			}
+		}
+		return pwf;
+#else
+		return pf[*ptr];
+#endif
+	}
+}
+
+/*
+ *  文字列表示ラインクリア
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  ライン番号
+ */
+void
+lcd_clearStringLine(LCD_DrawProp_t *pDrawProp, uint16_t Line)
+{
+	font_head_t *phead = (font_head_t *)pDrawProp->pFont;
+	lcd_fillRect(pDrawProp->hlcd, 0, (Line * phead->font_height), pDrawProp->hlcd->_width, phead->font_height, pDrawProp->BackColor);
+}
+
+/*
+ *  一文字描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x0: 文字描画 X座標始点
+ *  param3  y0: 文字描画 Y座標始点
+ *  param4  描画アスキーコード(範囲は0x20から0x7Eまで)
+ */
+void
+lcd_DisplayChar(LCD_DrawProp_t *pDrawProp, uint16_t x0, uint16_t y0, uint8_t Ascii)
+{
+	font_head_t  *phead = (font_head_t *)pDrawProp->pFont;
+	const font_t **pf   = phead->font_table;
+
+	DrawChar(pDrawProp, x0, y0, pf[Ascii]);
+}
+
+/*
+ *  文字列描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param1  x0: 文字列描画 X座標始点
+ *  param2  y0: 文字列描画 Y座標始点
+ *  param3  Text: 描画文字列へのポインタ
+ *  param4  Mode: 表示モード
+ */
+void
+lcd_DisplayStringAt(LCD_DrawProp_t *pDrawProp, uint16_t x0, uint16_t y0, uint8_t *Text, Line_ModeTypdef Mode)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	font_head_t   *phead = (font_head_t *)pDrawProp->pFont;
+	const font_t  **pf = phead->font_table;
+	uint16_t ref_column = 1;
+	uint32_t size = 0;
+	uint8_t  *ptr = (uint8_t *)Text, c;
+	int      wid, len  = 1;
+
+	/* Get the text size */
+	while(*ptr){
+		size += GetFontWidth(phead, *ptr, &len);
+		ptr  += len;
+	}
+
+	switch (Mode){
+	case CENTER_MODE:
+		ref_column = x0 + (hlcd->_width - size) / 2;
+		break;
+	case LEFT_MODE:
+		ref_column = x0;
+		break;
+	case RIGHT_MODE:
+		ref_column = - x0 + (hlcd->_width - size);
+		break;
+	default:
+		ref_column = x0;
+		break;
+	}
+
+	/*
+	 *  開始カラム位置をスクリーン内に収める
+	 */
+	if((ref_column < 1) || (ref_column >= 0x8000)){
+		ref_column = 1;
+	}
+
+	/*
+	 *  一文字描画を使って文字列を描画する
+	 */
+	while (((c = *Text) != 0) && pf[c] != 0 && (ref_column + (wid = GetFontWidth(phead, c, &len))) <= hlcd->_width){
+		lcd_DisplayData(pDrawProp, ref_column, y0, Text);
+		ref_column += wid;	/* 次のカラムに移動 */
+		Text += len;		/* 次の文字に移動 */
+	}
+}
+
+/*
+ *  文字列描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x0: 文字列描画 X座標始点
+ *  param3  y0: 文字列描画 Y座標始点
+ *  param4  Text: 描画文字列へのポインタ
+ */
+void
+lcd_DisplayStringAtLine(LCD_DrawProp_t *pDrawProp, uint16_t Line, uint8_t *ptr)
+{
+	font_head_t  *phead = (font_head_t *)pDrawProp->pFont;
+	const font_t *pf;
+
+	pf = phead->font_table[' '];
+	lcd_DisplayStringAt(pDrawProp, 0, Line * pf->height, ptr, LEFT_MODE);
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/ui/snfont_disp/glcd_disp.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/ui/snfont_disp/glcd_disp.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/ui/snfont_disp/glcd_disp.h	(revision 453)
@@ -0,0 +1,123 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+#ifndef _GLCD_DISP_H_
+#define _GLCD_DISP_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif 
+
+#include "glcd_core.h"
+#include "fonts.h"
+
+/*
+ *  テキスト表示ラインモード定義
+ */
+typedef enum
+{
+	CENTER_MODE = 0x01,	/* Center mode */
+	RIGHT_MODE,			/* Right mode  */
+	LEFT_MODE			/* Left mode   */
+}Line_ModeTypdef;
+
+
+#define Font8   Embedded_Font9
+#define Font12  Shinonome_Font12
+#define Font16  Shinonome_Font16
+
+/*
+ *  BSP表示関数変換定義
+ */
+#define BSP_LCD_Init()                  lcd_init(pHLCD, LCD_ORIENTATION_LANDSCAPE)
+#define BSP_LCD_DeInit()                lcd_deinit(pHLCD)
+#define BSP_LCD_LayerDefaultInit(a, b)  lcd_layerdefaultinit(pHLCD, pDRAWPROP, (a), (b))
+#define BSP_LCD_SetLayerWindow(i, x, y, w, h) lcd_setAddrWindow(pHLCD, (i), (x), (y), (w), (h))
+
+#define BSP_LCD_Clear(c)                lcd_clear(pHLCD, (c))
+#define BSP_LCD_ReadPixel(x, y)         lcd_readPixel(pHLCD, (x), (y))
+#define BSP_LCD_DrawPixel(x, y, c)      lcd_drawPixel(pHLCD, (x), (y), (c))
+#define BSP_LCD_DrawHLine(x, y, w)      lcd_drawFastHLine(pHLCD, (x), (y), (w), pDRAWPROP->TextColor)
+#define BSP_LCD_DrawVLine(x, y, h)      lcd_drawFastVLine(pHLCD, (x), (y), (h), pDRAWPROP->TextColor)
+#define BSP_LCD_DrawBitmap(x, y, p)     lcd_drawBitmap(pHLCD, (x), (y), (p))
+#define BSP_LCD_DrawRGBImage(x, y, xs, ys, p) lcd_drawRGBImage(pHLCD, (x), (y), (xs), (xy), (p))
+#define BSP_LCD_DisplayOn()             lcd_displayOn(pHLCD)
+#define BSP_LCD_DisplayOff()            lcd_displayOff(pHLCD)
+#define BSP_LCD_FillRect(x, y, w,h)     lcd_fillRect(pHLCD, (x), (y), (w), (h), pDRAWPROP->TextColor)
+
+#define BSP_LCD_DrawLine(x, y, x2, y2)  lcd_drawLine(pDRAWPROP, (x), (y), (x2), (y2))
+#define BSP_LCD_DrawRect(x, y, w, h)    lcd_drawRect(pDRAWPROP, (x), (y), (w), (h))
+#define BSP_LCD_DrawCircle(x, y, r)     lcd_DrawCircle(pDRAWPROP, (x), (y), (r))
+#define BSP_LCD_DrawEllipse(x, y, xr, yr) lcd_DrawEllipse(pDRAWPROP, (x), (y), (xr), (yr))
+#define BSP_LCD_DrawPolygon(a, b)       lcd_drawPolygon(pDRAWPROP, (a), (b))
+#define BSP_LCD_FillCircle(x, y, r)     lcd_fillCircle(pDRAWPROP, (x), (y), (r))
+#define BSP_LCD_FillEllipse(x, y, xr, yr) lcd_fillEllipse(pDRAWPROP, (x), (y), (xr), (yr))
+#define BSP_LCD_FillPolygon(a, b)       lcd_fillPolygon(pDRAWPROP, (a), (b))
+
+#define BSP_LCD_ClearStringLine(l)      lcd_clearStringLine(pDRAWPROP, (l))
+#define BSP_LCD_DisplayChar(x, y, a)    lcd_DisplayChar(pDRAWPROP, (x), (y), (a))
+#define BSP_LCD_DisplayStringAt(x, y, t, m) lcd_DisplayStringAt(pDRAWPROP, (x), (y), (t), (m))
+#define BSP_LCD_DisplayStringAtLine(l, p) lcd_DisplayStringAtLine(pDRAWPROP, (l), (p))
+
+#define BSP_LCD_SelectLayer(a)          pHLCD->layer = (a)
+#define BSP_LCD_GetXSize()              pHLCD->_width
+#define BSP_LCD_GetYSize()              pHLCD->_height
+#define BSP_LCD_SetTextColor(c)         pDRAWPROP->TextColor = (c)
+#define BSP_LCD_GetTextColor()          pDRAWPROP->TextColor
+#define BSP_LCD_SetBackColor(c)         pDRAWPROP->BackColor = (c)
+#define BSP_LCD_GetBackColor()          pDRAWPROP->BackColor
+#define BSP_LCD_SetFont(f)              pDRAWPROP->pFont = (f)
+#define BSP_LCD_GetFont()               ((sFONT *)pDRAWPROP->pFont)
+
+
+extern const font_t *lcd_getFontTable(font_head_t *phead, uint8_t *ptr);
+extern void lcd_clearStringLine(LCD_DrawProp_t *pDrawProp, uint16_t Line);
+extern void lcd_DisplayChar(LCD_DrawProp_t *pDrawProp, uint16_t Xpos, uint16_t Ypos, uint8_t Ascii);
+extern void lcd_DisplayStringAt(LCD_DrawProp_t *pDrawProp, uint16_t Xpos, uint16_t Ypos, uint8_t *Text, Line_ModeTypdef Mode);
+extern void lcd_DisplayStringAtLine(LCD_DrawProp_t *pDrawProp, uint16_t Line, uint8_t *ptr);
+
+#ifdef USE_ROMFONT
+extern const uint8_t romfont[];
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GLCD_DISP_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/ui/snfont_disp/shinonome_font.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/ui/snfont_disp/shinonome_font.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/ui/snfont_disp/shinonome_font.c	(revision 453)
@@ -0,0 +1,22472 @@
+
+#ifdef USE_ROMFONT
+
+#include "kernel.h"
+
+const uint8_t romfont[] = {
+	0x00,  0x02,  0x01,  0xD4,  's',   'h',   'i',   'n',   'o',   'n',   'o',   'm',   'e',   '_',   'f',   'o', 	/* 00000 */
+	'n',   't',   '1',   '2',   '.',   'f',   'n',   't',   0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 00010 */
+	'F',   'O',   'N',   'T',   's',   'h',   'i',   'n',   'o',   'n',   'o',   'm',   'e',   '_',   'f',   'o', 	/* 00020 */
+	'n',   't',   '1',   '2',   0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 00030 */
+	0x00,  0x00,  0x00,  0x00,  0xB1,  0x01,  0x02,  0x00,  0x01,  0x00,  0x00,  0x00,  0x12,  0x00,  0x00,  0x00, 	/* 00040 */
+	0x58,  0x00,  0x00,  0x00,  0x06,  0x00,  0x00,  0x00,  0x64,  0x00,  0x00,  0x00,  0x09,  0x00,  0x00,  0x00, 	/* 00050 */
+	0x76,  0x00,  0x00,  0x00,  0x57,  0x01,  0x00,  0x00,  0x24,  0x03,  0x00,  0x00,  0x7A,  0x00,  0x00,  0x00, 	/* 00060 */
+	0x32,  0x0C,  0x00,  0x00,  0x65,  0x1A,  0x00,  0x00,  0xC2,  0x06,  0xC3,  0x02,  0xCE,  0x27,  0xCF,  0x09, 	/* 00070 */
+	0xD0,  0x31,  0xD1,  0x11,  0xE2,  0x0E,  0xE3,  0x04,  0xE4,  0x08,  0xE5,  0x40,  0xE6,  0x40,  0xE7,  0x3F, 	/* 00080 */
+	0xE8,  0x3F,  0xE9,  0x3C,  0xEF,  0x03,  0x80,  0x0E,  0x84,  0x02,  0x86,  0x04,  0x87,  0x02,  0x88,  0x14, 	/* 00090 */
+	0x89,  0x07,  0x8A,  0x05,  0x8C,  0x01,  0x94,  0x1E,  0x95,  0x02,  0x96,  0x06,  0x97,  0x06,  0x98,  0x02, 	/* 000A0 */
+	0x99,  0x05,  0x80,  0x15,  0x81,  0x3F,  0x82,  0x37,  0x83,  0x3B,  0xB8,  0x1F,  0xB9,  0x13,  0xBA,  0x23, 	/* 000B0 */
+	0xBB,  0x1E,  0xBC,  0x13,  0xBD,  0x1A,  0xBE,  0x14,  0xBF,  0x1A,  0x80,  0x1A,  0x81,  0x12,  0x82,  0x0F, 	/* 000C0 */
+	0x83,  0x13,  0x84,  0x14,  0x85,  0x21,  0x86,  0x24,  0x87,  0x1B,  0x88,  0x1B,  0x89,  0x1A,  0x8A,  0x17, 	/* 000D0 */
+	0x8B,  0x1C,  0x8C,  0x1A,  0x8D,  0x21,  0x8E,  0x11,  0x8F,  0x24,  0x90,  0x1E,  0x91,  0x14,  0x92,  0x16, 	/* 000E0 */
+	0x93,  0x13,  0x94,  0x0E,  0x95,  0x0F,  0x96,  0x17,  0x97,  0x0D,  0x98,  0x0E,  0x99,  0x0D,  0x9A,  0x0D, 	/* 000F0 */
+	0x9B,  0x17,  0x9C,  0x16,  0x9D,  0x0E,  0x9E,  0x0C,  0x9F,  0x12,  0xA0,  0x13,  0xA1,  0x14,  0xA2,  0x0F, 	/* 00100 */
+	0xA3,  0x1D,  0xA4,  0x1A,  0xA5,  0x1A,  0xA6,  0x13,  0xA7,  0x12,  0xA8,  0x0F,  0xA9,  0x0A,  0xAA,  0x06, 	/* 00110 */
+	0xAB,  0x0E,  0xAC,  0x0B,  0xAD,  0x1A,  0xAE,  0x21,  0xAF,  0x22,  0xB0,  0x1F,  0xB1,  0x19,  0xB2,  0x11, 	/* 00120 */
+	0xB3,  0x0F,  0xB4,  0x0F,  0xB5,  0x0B,  0xB6,  0x0E,  0xB7,  0x1A,  0xB8,  0x15,  0xB9,  0x1C,  0xBA,  0x14, 	/* 00130 */
+	0xBB,  0x21,  0xBC,  0x1F,  0xBD,  0x1B,  0xBE,  0x1F,  0xBF,  0x14,  0x80,  0x16,  0x81,  0x1C,  0x82,  0x1C, 	/* 00140 */
+	0x83,  0x17,  0x84,  0x16,  0x85,  0x20,  0x86,  0x14,  0x87,  0x16,  0x88,  0x1D,  0x89,  0x17,  0x8A,  0x19, 	/* 00150 */
+	0x8B,  0x22,  0x8C,  0x11,  0x8D,  0x12,  0x8E,  0x1C,  0x8F,  0x12,  0x90,  0x0F,  0x91,  0x09,  0x92,  0x12, 	/* 00160 */
+	0x93,  0x18,  0x94,  0x14,  0x95,  0x16,  0x96,  0x1B,  0x97,  0x19,  0x98,  0x17,  0x99,  0x17,  0x9A,  0x15, 	/* 00170 */
+	0x9B,  0x18,  0x9C,  0x1F,  0x9D,  0x1F,  0x9E,  0x17,  0x9F,  0x1C,  0xA0,  0x12,  0xA1,  0x17,  0xA2,  0x1A, 	/* 00180 */
+	0xA3,  0x16,  0xA4,  0x1C,  0xA5,  0x1A,  0xA6,  0x12,  0xA7,  0x17,  0xA8,  0x1A,  0xA9,  0x0D,  0xAA,  0x10, 	/* 00190 */
+	0xAB,  0x0D,  0xAC,  0x12,  0xAD,  0x19,  0xAE,  0x1A,  0xAF,  0x10,  0xB0,  0x0D,  0xB1,  0x15,  0xB2,  0x1B, 	/* 001A0 */
+	0xB3,  0x16,  0xB4,  0x14,  0xB5,  0x11,  0xB6,  0x0E,  0xB7,  0x1B,  0xB8,  0x1C,  0xB9,  0x10,  0xBA,  0x13, 	/* 001B0 */
+	0xBB,  0x14,  0xBC,  0x13,  0xBD,  0x11,  0xBE,  0x0F,  0xBF,  0x16,  0x80,  0x12,  0x81,  0x0A,  0x82,  0x0D, 	/* 001C0 */
+	0x83,  0x09,  0x84,  0x09,  0x85,  0x0F,  0x86,  0x0D,  0x87,  0x16,  0x88,  0x12,  0x89,  0x15,  0x8A,  0x0E, 	/* 001D0 */
+	0x8B,  0x15,  0x8C,  0x12,  0x8D,  0x0E,  0x8E,  0x09,  0x8F,  0x0F,  0x90,  0x0D,  0x91,  0x12,  0x92,  0x07, 	/* 001E0 */
+	0x93,  0x11,  0x94,  0x1D,  0x95,  0x20,  0x96,  0x18,  0x97,  0x18,  0x98,  0x0D,  0x99,  0x19,  0x9A,  0x15, 	/* 001F0 */
+	0x9B,  0x19,  0x9C,  0x13,  0x9D,  0x0D,  0x9E,  0x10,  0x9F,  0x10,  0xA0,  0x0D,  0xA1,  0x08,  0xA2,  0x14, 	/* 00200 */
+	0xA3,  0x0F,  0xA4,  0x0D,  0xA5,  0x16,  0xA6,  0x14,  0xA7,  0x12,  0xA8,  0x16,  0xA9,  0x16,  0xAA,  0x13, 	/* 00210 */
+	0xAB,  0x20,  0xAC,  0x15,  0xAD,  0x17,  0xAE,  0x15,  0xAF,  0x13,  0xB0,  0x13,  0xB1,  0x11,  0xB2,  0x1C, 	/* 00220 */
+	0xB3,  0x16,  0xB4,  0x1F,  0xB5,  0x1A,  0xB6,  0x1A,  0xB7,  0x16,  0xB8,  0x19,  0xB9,  0x18,  0xBA,  0x0E, 	/* 00230 */
+	0xBC,  0x03,  0xBD,  0x17,  0xBE,  0x18,  0xBF,  0x12,  0x80,  0x16,  0x81,  0x16,  0x82,  0x19,  0x83,  0x14, 	/* 00240 */
+	0x84,  0x10,  0x85,  0x14,  0x86,  0x18,  0x87,  0x19,  0x88,  0x1E,  0x89,  0x15,  0x8A,  0x12,  0x8B,  0x17, 	/* 00250 */
+	0x8C,  0x16,  0x8D,  0x0D,  0x8E,  0x12,  0x8F,  0x15,  0x90,  0x12,  0x91,  0x14,  0x92,  0x10,  0x93,  0x11, 	/* 00260 */
+	0x94,  0x10,  0x95,  0x13,  0x96,  0x17,  0x97,  0x11,  0x98,  0x0E,  0x99,  0x0E,  0x9A,  0x0D,  0x9B,  0x16, 	/* 00270 */
+	0x9C,  0x13,  0x9D,  0x13,  0x9E,  0x0A,  0x9F,  0x0F,  0xA0,  0x0F,  0xA1,  0x19,  0xA2,  0x14,  0xA3,  0x17, 	/* 00280 */
+	0xA4,  0x10,  0xA5,  0x13,  0xA6,  0x19,  0xA7,  0x0A,  0xA8,  0x1A,  0xA9,  0x18,  0xAA,  0x1B,  0xAB,  0x1C, 	/* 00290 */
+	0xAC,  0x18,  0xAD,  0x15,  0xAE,  0x0B,  0xB0,  0x03,  0xB1,  0x12,  0xB2,  0x22,  0xB3,  0x1B,  0xB4,  0x0C, 	/* 002A0 */
+	0xB5,  0x0A,  0xB6,  0x09,  0xB7,  0x13,  0xB8,  0x0C,  0xB9,  0x12,  0xBA,  0x13,  0xBB,  0x12,  0xBC,  0x18, 	/* 002B0 */
+	0xBD,  0x0F,  0xBE,  0x12,  0xBF,  0x16,  0x80,  0x23,  0x81,  0x27,  0x82,  0x12,  0x83,  0x0C,  0x84,  0x06, 	/* 002C0 */
+	0x85,  0x15,  0x86,  0x12,  0x87,  0x1B,  0x88,  0x0B,  0x89,  0x0F,  0x8A,  0x0E,  0x8B,  0x0B,  0x8C,  0x13, 	/* 002D0 */
+	0x8D,  0x0D,  0x8E,  0x0B,  0x8F,  0x0C,  0x90,  0x0E,  0x91,  0x12,  0x92,  0x01,  0x95,  0x01,  0x96,  0x1B, 	/* 002E0 */
+	0x97,  0x0D,  0x98,  0x09,  0x99,  0x1D,  0x9A,  0x1E,  0x9B,  0x1C,  0x9C,  0x18,  0x9D,  0x18,  0x9E,  0x12, 	/* 002F0 */
+	0x9F,  0x0E,  0xA0,  0x19,  0xA1,  0x12,  0xA2,  0x05,  0xA3,  0x11,  0xA4,  0x14,  0xA5,  0x0A,  0xA6,  0x0C, 	/* 00300 */
+	0xA7,  0x15,  0xA8,  0x0C,  0xA9,  0x10,  0xAA,  0x05,  0xAB,  0x15,  0xAC,  0x11,  0xAD,  0x0E,  0xAE,  0x10, 	/* 00310 */
+	0xAF,  0x13,  0xB0,  0x19,  0xB1,  0x0A,  0xB3,  0x09,  0xB4,  0x13,  0xB5,  0x11,  0xB6,  0x0D,  0xB7,  0x0F, 	/* 00320 */
+	0xB8,  0x03,  0xB9,  0x05,  0xBA,  0x17,  0xBB,  0x19,  0xBC,  0x0A,  0xBD,  0x12,  0xBE,  0x05,  0xBC,  0x3D, 	/* 00330 */
+	0xBD,  0x1F,  0xBF,  0x05,  0xA7,  0x0E,  0x01,  0x10,  0x18,  0x00,  0xC0,  0x0E,  0x01,  0x30,  0x19,  0x00, 	/* 00340 */
+	0xE0,  0x06,  0x00,  0x30,  0x11,  0x00,  0xE0,  0xA8,  0x19,  0x81,  0x98,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 00350 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xB0,  0x00,  0x03,  0x00,  0x48,  0x04, 	/* 00360 */
+	0x80,  0x30,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xB1,  0x00,  0x00, 	/* 00370 */
+	0x40,  0x04,  0x00,  0x40,  0x04,  0x07,  0xFC,  0x04,  0x00,  0x40,  0x04,  0x00,  0x00,  0x7F,  0xC0,  0x00, 	/* 00380 */
+	0xB4,  0x02,  0x00,  0x40,  0x08,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 00390 */
+	0x00,  0x00,  0x00,  0xB6,  0x0F,  0x01,  0xD0,  0x1D,  0x01,  0xD0,  0x0D,  0x00,  0x50,  0x05,  0x00,  0x50, 	/* 003A0 */
+	0x05,  0x00,  0x50,  0x05,  0x00,  0x00,  0x97,  0x00,  0x00,  0x00,  0x20,  0x41,  0x08,  0x09,  0x00,  0x60, 	/* 003B0 */
+	0x06,  0x00,  0x90,  0x10,  0x82,  0x04,  0x00,  0x00,  0x00,  0xB7,  0x00,  0x00,  0x00,  0x0C,  0x00,  0xC0, 	/* 003C0 */
+	0x00,  0x00,  0x00,  0x7F,  0xC0,  0x00,  0x00,  0x00,  0xC0,  0x0C,  0x00,  0x00,  0x91,  0x00,  0x00,  0x40, 	/* 003D0 */
+	0x04,  0x00,  0xA0,  0x0A,  0x01,  0x10,  0x11,  0x01,  0xF0,  0x20,  0x82,  0x08,  0x71,  0xC0,  0x00,  0x92, 	/* 003E0 */
+	0x00,  0x03,  0xE0,  0x11,  0x01,  0x08,  0x11,  0x01,  0xE0,  0x11,  0x01,  0x08,  0x10,  0x81,  0x10,  0x3E, 	/* 003F0 */
+	0x00,  0x00,  0x93,  0x00,  0x03,  0xF0,  0x11,  0x01,  0x08,  0x10,  0x01,  0x00,  0x10,  0x01,  0x00,  0x10, 	/* 00400 */
+	0x01,  0x00,  0x38,  0x00,  0x00,  0x94,  0x00,  0x00,  0x40,  0x04,  0x00,  0x40,  0x0A,  0x00,  0xA0,  0x11, 	/* 00410 */
+	0x01,  0x10,  0x20,  0x82,  0x08,  0x7F,  0xC0,  0x00,  0x95,  0x00,  0x03,  0xF8,  0x10,  0x41,  0x00,  0x11, 	/* 00420 */
+	0x01,  0xF0,  0x11,  0x01,  0x00,  0x10,  0x41,  0x04,  0x3F,  0x80,  0x00,  0x96,  0x00,  0x03,  0xFC,  0x20, 	/* 00430 */
+	0x84,  0x10,  0x02,  0x00,  0x40,  0x04,  0x00,  0x80,  0x10,  0x42,  0x04,  0x7F,  0xC0,  0x00,  0x97,  0x00, 	/* 00440 */
+	0x07,  0x1C,  0x20,  0x82,  0x08,  0x20,  0x83,  0xF8,  0x20,  0x82,  0x08,  0x20,  0x82,  0x08,  0x71,  0xC0, 	/* 00450 */
+	0x00,  0x98,  0x00,  0x00,  0xE0,  0x11,  0x02,  0x08,  0x51,  0x45,  0xF4,  0x51,  0x44,  0x04,  0x20,  0x81, 	/* 00460 */
+	0x10,  0x0E,  0x00,  0x00,  0x99,  0x00,  0x00,  0xE0,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00, 	/* 00470 */
+	0x40,  0x04,  0x00,  0x40,  0x0E,  0x00,  0x00,  0x9A,  0x00,  0x03,  0xB8,  0x11,  0x01,  0x20,  0x14,  0x01, 	/* 00480 */
+	0x80,  0x14,  0x01,  0x20,  0x11,  0x01,  0x08,  0x39,  0xC0,  0x00,  0x9B,  0x00,  0x00,  0x40,  0x04,  0x00, 	/* 00490 */
+	0xA0,  0x0A,  0x01,  0x10,  0x11,  0x01,  0x10,  0x20,  0x82,  0x08,  0x71,  0xC0,  0x00,  0x9C,  0x00,  0x0C, 	/* 004A0 */
+	0x06,  0x40,  0x46,  0x0C,  0x60,  0xC5,  0x14,  0x51,  0x44,  0xA4,  0x4A,  0x44,  0x44,  0xE4,  0xE0,  0x00, 	/* 004B0 */
+	0x9D,  0x00,  0x03,  0x1C,  0x18,  0x81,  0x48,  0x14,  0x81,  0x28,  0x12,  0x81,  0x18,  0x11,  0x81,  0x08, 	/* 004C0 */
+	0x38,  0x80,  0x00,  0x9E,  0x00,  0x03,  0xFC,  0x20,  0x40,  0x00,  0x10,  0x81,  0xF8,  0x10,  0x80,  0x00, 	/* 004D0 */
+	0x00,  0x02,  0x04,  0x3F,  0xC0,  0x00,  0x9F,  0x00,  0x00,  0xE0,  0x11,  0x02,  0x08,  0x40,  0x44,  0x04, 	/* 004E0 */
+	0x40,  0x44,  0x04,  0x20,  0x81,  0x10,  0x0E,  0x00,  0x00,  0xA0,  0x00,  0x07,  0xFC,  0x20,  0x82,  0x08, 	/* 004F0 */
+	0x20,  0x82,  0x08,  0x20,  0x82,  0x08,  0x20,  0x82,  0x08,  0x71,  0xC0,  0x00,  0xA1,  0x00,  0x03,  0xE0, 	/* 00500 */
+	0x11,  0x01,  0x08,  0x10,  0x81,  0x10,  0x1E,  0x01,  0x00,  0x10,  0x01,  0x00,  0x38,  0x00,  0x00,  0xA3, 	/* 00510 */
+	0x00,  0x07,  0xF0,  0x21,  0x01,  0x08,  0x08,  0x00,  0x40,  0x04,  0x00,  0x80,  0x10,  0x42,  0x04,  0x7F, 	/* 00520 */
+	0x80,  0x00,  0xA4,  0x00,  0x07,  0xFC,  0x44,  0x44,  0x44,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04, 	/* 00530 */
+	0x00,  0x40,  0x0E,  0x00,  0x00,  0xA5,  0x00,  0x03,  0xB8,  0x44,  0x44,  0x44,  0x04,  0x00,  0x40,  0x04, 	/* 00540 */
+	0x00,  0x40,  0x04,  0x00,  0x40,  0x0E,  0x00,  0x00,  0xA6,  0x00,  0x00,  0xE0,  0x04,  0x01,  0xF0,  0x24, 	/* 00550 */
+	0x82,  0x48,  0x24,  0x81,  0xF0,  0x04,  0x00,  0x40,  0x0E,  0x00,  0x00,  0xA7,  0x00,  0x07,  0x1C,  0x20, 	/* 00560 */
+	0x81,  0x10,  0x0A,  0x00,  0x40,  0x04,  0x00,  0xA0,  0x11,  0x02,  0x08,  0x71,  0xC0,  0x00,  0xA8,  0x00, 	/* 00570 */
+	0x00,  0xE0,  0x44,  0x42,  0x48,  0x24,  0x82,  0x48,  0x15,  0x00,  0xE0,  0x04,  0x00,  0x40,  0x0E,  0x00, 	/* 00580 */
+	0x00,  0xA9,  0x00,  0x00,  0xE0,  0x11,  0x02,  0x08,  0x20,  0x82,  0x08,  0x20,  0x81,  0x10,  0x4A,  0x44, 	/* 00590 */
+	0xA4,  0x7B,  0xC0,  0x00,  0xB1,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0C,  0x81,  0x28,  0x23,  0x02, 	/* 005A0 */
+	0x20,  0x24,  0x02,  0x60,  0x19,  0x80,  0x00,  0xB2,  0x00,  0x00,  0x30,  0x04,  0x80,  0x48,  0x09,  0x00, 	/* 005B0 */
+	0xA0,  0x11,  0x01,  0x10,  0x32,  0x02,  0xC0,  0x40,  0x04,  0x00,  0xB3,  0x00,  0x00,  0x00,  0x00,  0x01, 	/* 005C0 */
+	0x8C,  0x25,  0x00,  0x20,  0x04,  0x00,  0x40,  0x08,  0x00,  0x80,  0x10,  0x00,  0x00,  0xB4,  0x00,  0x00, 	/* 005D0 */
+	0x60,  0x09,  0x80,  0x40,  0x02,  0x00,  0x60,  0x09,  0x01,  0x10,  0x21,  0x02,  0x20,  0x1C,  0x00,  0x00, 	/* 005E0 */
+	0xB5,  0x00,  0x00,  0x00,  0x00,  0x00,  0xE0,  0x11,  0x01,  0x00,  0x0C,  0x01,  0x00,  0x21,  0x02,  0x20, 	/* 005F0 */
+	0x1C,  0x00,  0x00,  0xB6,  0x00,  0x00,  0x80,  0x09,  0x80,  0x70,  0x04,  0x00,  0x80,  0x10,  0x01,  0x00, 	/* 00600 */
+	0x10,  0x00,  0xC0,  0x22,  0x01,  0xC0,  0xB7,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x13,  0x02,  0xC8, 	/* 00610 */
+	0x08,  0x81,  0x10,  0x11,  0x02,  0x20,  0x02,  0x00,  0x20,  0xB8,  0x00,  0x00,  0x30,  0x04,  0x80,  0x88, 	/* 00620 */
+	0x10,  0x81,  0xF8,  0x21,  0x02,  0x10,  0x22,  0x02,  0x40,  0x18,  0x00,  0x00,  0xB9,  0x00,  0x00,  0x00, 	/* 00630 */
+	0x00,  0x00,  0x20,  0x04,  0x00,  0x80,  0x08,  0x01,  0x00,  0x10,  0x81,  0x30,  0x0C,  0x00,  0x00,  0xBA, 	/* 00640 */
+	0x00,  0x00,  0x00,  0x00,  0x01,  0x08,  0x09,  0x00,  0xA0,  0x1C,  0x01,  0x40,  0x24,  0x82,  0x48,  0x43, 	/* 00650 */
+	0x00,  0x00,  0xBB,  0x00,  0x00,  0x00,  0x0C,  0x00,  0x20,  0x02,  0x00,  0x20,  0x06,  0x00,  0xA0,  0x11, 	/* 00660 */
+	0x02,  0x10,  0x20,  0xC0,  0x00,  0xBC,  0x00,  0x00,  0x00,  0x00,  0x00,  0x88,  0x08,  0x81,  0x08,  0x11, 	/* 00670 */
+	0x02,  0x10,  0x33,  0x02,  0xCC,  0x40,  0x04,  0x00,  0xBD,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x10, 	/* 00680 */
+	0x80,  0x88,  0x09,  0x01,  0x10,  0x12,  0x01,  0x40,  0x38,  0x00,  0x00,  0xBE,  0x00,  0x00,  0x40,  0x03, 	/* 00690 */
+	0x80,  0x40,  0x08,  0x00,  0x60,  0x08,  0x01,  0x00,  0x0E,  0x00,  0x10,  0x11,  0x00,  0xE0,  0xBF,  0x00, 	/* 006A0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x0E,  0x01,  0x10,  0x21,  0x02,  0x10,  0x21,  0x02,  0x20,  0x1C,  0x00, 	/* 006B0 */
+	0x00,  0x80,  0x00,  0x00,  0x00,  0x00,  0x00,  0x04,  0x1F,  0x82,  0x90,  0x0A,  0x01,  0x20,  0x14,  0x02, 	/* 006C0 */
+	0x48,  0x43,  0x00,  0x00,  0x81,  0x00,  0x00,  0x00,  0x00,  0x00,  0x70,  0x08,  0x81,  0x08,  0x10,  0x81, 	/* 006D0 */
+	0x90,  0x16,  0x02,  0x00,  0x20,  0x02,  0x00,  0x83,  0x00,  0x00,  0x00,  0x00,  0x00,  0x04,  0x07,  0x81, 	/* 006E0 */
+	0xA0,  0x21,  0x02,  0x10,  0x21,  0x01,  0x20,  0x0C,  0x00,  0x00,  0x84,  0x00,  0x00,  0x00,  0x00,  0x81, 	/* 006F0 */
+	0xF0,  0x24,  0x00,  0x40,  0x08,  0x00,  0x80,  0x10,  0x01,  0x20,  0x0C,  0x00,  0x00,  0x85,  0x00,  0x00, 	/* 00700 */
+	0x00,  0x00,  0x00,  0x00,  0x21,  0x05,  0x08,  0x10,  0x81,  0x10,  0x21,  0x02,  0x60,  0x18,  0x00,  0x00, 	/* 00710 */
+	0x86,  0x00,  0x00,  0x10,  0x01,  0x00,  0x20,  0x0F,  0x01,  0x28,  0x22,  0x42,  0x44,  0x24,  0x81,  0xF0, 	/* 00720 */
+	0x08,  0x00,  0x80,  0x87,  0x00,  0x00,  0x00,  0x00,  0x81,  0x08,  0x29,  0x02,  0x60,  0x04,  0x00,  0xC0, 	/* 00730 */
+	0x14,  0x02,  0x28,  0x21,  0x00,  0x00,  0x88,  0x00,  0x00,  0x10,  0x01,  0x02,  0x28,  0x12,  0x41,  0x24, 	/* 00740 */
+	0x24,  0x42,  0x48,  0x1F,  0x00,  0x80,  0x08,  0x00,  0x80,  0x89,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 00750 */
+	0x10,  0x82,  0x04,  0x20,  0x44,  0x44,  0x44,  0x44,  0xC8,  0x33,  0x00,  0x00,  0x81,  0x19,  0x80,  0x00, 	/* 00760 */
+	0x3F,  0x81,  0x04,  0x10,  0x01,  0x10,  0x1F,  0x01,  0x10,  0x10,  0x41,  0x04,  0x3F,  0x80,  0x00,  0x90, 	/* 00770 */
+	0x00,  0x00,  0x40,  0x04,  0x00,  0xA0,  0x0A,  0x01,  0x10,  0x11,  0x01,  0xF0,  0x20,  0x82,  0x08,  0x71, 	/* 00780 */
+	0xC0,  0x00,  0x91,  0x00,  0x03,  0xF8,  0x10,  0x81,  0x00,  0x10,  0x01,  0xE0,  0x11,  0x01,  0x08,  0x10, 	/* 00790 */
+	0x81,  0x10,  0x3E,  0x00,  0x00,  0x92,  0x00,  0x03,  0xE0,  0x11,  0x01,  0x08,  0x11,  0x01,  0xE0,  0x11, 	/* 007A0 */
+	0x01,  0x08,  0x10,  0x81,  0x10,  0x3E,  0x00,  0x00,  0x93,  0x00,  0x03,  0xF0,  0x11,  0x01,  0x08,  0x10, 	/* 007B0 */
+	0x01,  0x00,  0x10,  0x01,  0x00,  0x10,  0x01,  0x00,  0x38,  0x00,  0x00,  0x94,  0x00,  0x01,  0xFC,  0x09, 	/* 007C0 */
+	0x00,  0x90,  0x09,  0x00,  0x90,  0x09,  0x01,  0x10,  0x11,  0x02,  0x10,  0x7F,  0xC4,  0x04,  0x95,  0x00, 	/* 007D0 */
+	0x03,  0xF8,  0x10,  0x41,  0x00,  0x11,  0x01,  0xF0,  0x11,  0x01,  0x00,  0x10,  0x41,  0x04,  0x3F,  0x80, 	/* 007E0 */
+	0x00,  0x96,  0x00,  0x04,  0xE4,  0x24,  0x82,  0x48,  0x15,  0x00,  0xE0,  0x15,  0x02,  0x50,  0x24,  0x82, 	/* 007F0 */
+	0x48,  0x6E,  0xC0,  0x00,  0x97,  0x00,  0x00,  0xE0,  0x11,  0x02,  0x10,  0x01,  0x00,  0x60,  0x01,  0x00, 	/* 00800 */
+	0x08,  0x20,  0x83,  0x10,  0x2E,  0x00,  0x00,  0x98,  0x00,  0x03,  0x8C,  0x11,  0x81,  0x28,  0x12,  0x81, 	/* 00810 */
+	0x48,  0x14,  0x81,  0x88,  0x18,  0x81,  0x08,  0x39,  0xC0,  0x00,  0x99,  0x09,  0x00,  0x60,  0x38,  0xC1, 	/* 00820 */
+	0x18,  0x12,  0x81,  0x28,  0x14,  0x81,  0x88,  0x18,  0x81,  0x08,  0x39,  0xC0,  0x00,  0x9A,  0x00,  0x03, 	/* 00830 */
+	0x88,  0x11,  0x41,  0x20,  0x14,  0x01,  0x80,  0x14,  0x01,  0x20,  0x11,  0x01,  0x08,  0x39,  0xC0,  0x00, 	/* 00840 */
+	0x9B,  0x00,  0x01,  0xFC,  0x04,  0x80,  0x48,  0x04,  0x80,  0x48,  0x08,  0x80,  0x88,  0x08,  0x85,  0x08, 	/* 00850 */
+	0x21,  0xC0,  0x00,  0x9C,  0x00,  0x06,  0x0C,  0x20,  0x83,  0x18,  0x31,  0x82,  0xA8,  0x2A,  0x84,  0x44, 	/* 00860 */
+	0x44,  0x44,  0x44,  0xE0,  0xE0,  0x00,  0x9D,  0x00,  0x07,  0x1C,  0x20,  0x82,  0x08,  0x20,  0x83,  0xF8, 	/* 00870 */
+	0x20,  0x82,  0x08,  0x20,  0x82,  0x08,  0x71,  0xC0,  0x00,  0x9E,  0x00,  0x00,  0xE0,  0x11,  0x02,  0x08, 	/* 00880 */
+	0x40,  0x44,  0x04,  0x40,  0x44,  0x04,  0x20,  0x81,  0x10,  0x0E,  0x00,  0x00,  0x9F,  0x00,  0x07,  0xF8, 	/* 00890 */
+	0x21,  0x02,  0x10,  0x21,  0x02,  0x10,  0x21,  0x02,  0x10,  0x21,  0x02,  0x10,  0x73,  0x80,  0x00,  0xA0, 	/* 008A0 */
+	0x00,  0x03,  0xE0,  0x11,  0x01,  0x08,  0x10,  0x81,  0x10,  0x1E,  0x01,  0x00,  0x10,  0x01,  0x00,  0x38, 	/* 008B0 */
+	0x00,  0x00,  0xA1,  0x00,  0x00,  0x74,  0x08,  0xC1,  0x04,  0x20,  0x02,  0x00,  0x20,  0x02,  0x00,  0x10, 	/* 008C0 */
+	0x40,  0x88,  0x07,  0x00,  0x00,  0xA2,  0x00,  0x07,  0xFC,  0x44,  0x44,  0x44,  0x04,  0x00,  0x40,  0x04, 	/* 008D0 */
+	0x00,  0x40,  0x04,  0x00,  0x40,  0x0E,  0x00,  0x00,  0xA3,  0x00,  0x07,  0x1C,  0x20,  0x81,  0x10,  0x11, 	/* 008E0 */
+	0x00,  0xA0,  0x0A,  0x00,  0x40,  0x04,  0x02,  0x40,  0x18,  0x00,  0x00,  0xA4,  0x00,  0x00,  0xE0,  0x04, 	/* 008F0 */
+	0x01,  0xF0,  0x24,  0x84,  0x44,  0x44,  0x42,  0x48,  0x1F,  0x00,  0x40,  0x0E,  0x00,  0x00,  0xA5,  0x00, 	/* 00900 */
+	0x07,  0x1C,  0x20,  0x81,  0x10,  0x0A,  0x00,  0x40,  0x04,  0x00,  0xA0,  0x11,  0x02,  0x08,  0x71,  0xC0, 	/* 00910 */
+	0x00,  0xA6,  0x00,  0x07,  0x38,  0x21,  0x02,  0x10,  0x21,  0x02,  0x10,  0x21,  0x02,  0x10,  0x21,  0x02, 	/* 00920 */
+	0x10,  0x7F,  0xC0,  0x04,  0xA7,  0x00,  0x07,  0x38,  0x21,  0x02,  0x10,  0x21,  0x02,  0x10,  0x13,  0x00, 	/* 00930 */
+	0xD0,  0x01,  0x00,  0x10,  0x03,  0x80,  0x00,  0xA8,  0x00,  0x0E,  0xEE,  0x44,  0x44,  0x44,  0x44,  0x44, 	/* 00940 */
+	0x44,  0x44,  0x44,  0x44,  0x44,  0x44,  0x44,  0xFF,  0xE0,  0x00,  0xA9,  0x00,  0x0E,  0xEE,  0x44,  0x44, 	/* 00950 */
+	0x44,  0x44,  0x44,  0x44,  0x44,  0x44,  0x44,  0x44,  0x44,  0x44,  0xFF,  0xF0,  0x01,  0xAA,  0x00,  0x03, 	/* 00960 */
+	0x80,  0x48,  0x00,  0x80,  0x08,  0x00,  0xF0,  0x08,  0x80,  0x84,  0x08,  0x40,  0x88,  0x1F,  0x00,  0x00, 	/* 00970 */
+	0xAB,  0x00,  0x06,  0x1C,  0x20,  0x82,  0x08,  0x20,  0x83,  0x88,  0x24,  0x82,  0x28,  0x22,  0x82,  0x48, 	/* 00980 */
+	0x79,  0xC0,  0x00,  0xAC,  0x00,  0x03,  0x00,  0x10,  0x01,  0x00,  0x1E,  0x01,  0x10,  0x10,  0x81,  0x08, 	/* 00990 */
+	0x10,  0x81,  0x10,  0x1E,  0x00,  0x00,  0xAD,  0x00,  0x02,  0xE0,  0x31,  0x02,  0x08,  0x00,  0x80,  0xC8, 	/* 009A0 */
+	0x13,  0x80,  0x08,  0x20,  0x81,  0x10,  0x0E,  0x00,  0x00,  0xAE,  0x00,  0x0E,  0x30,  0x44,  0x84,  0x84, 	/* 009B0 */
+	0x48,  0x47,  0x84,  0x48,  0x44,  0x84,  0x48,  0x44,  0x48,  0xE3,  0x00,  0x00,  0xAF,  0x00,  0x00,  0xFC, 	/* 009C0 */
+	0x10,  0x82,  0x08,  0x10,  0x80,  0xF8,  0x02,  0x80,  0x48,  0x08,  0x81,  0x08,  0x71,  0xC0,  0x00,  0xB0, 	/* 009D0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x06,  0x00,  0x90,  0x07,  0x00,  0x90,  0x11,  0x01,  0x20,  0x0D, 	/* 009E0 */
+	0x80,  0x00,  0xB1,  0x00,  0x00,  0x30,  0x0C,  0x01,  0x00,  0x20,  0x02,  0xC0,  0x32,  0x02,  0x10,  0x21, 	/* 009F0 */
+	0x01,  0x20,  0x0C,  0x00,  0x00,  0xB2,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x3E,  0x01,  0x10,  0x11, 	/* 00A00 */
+	0x01,  0xE0,  0x11,  0x01,  0x10,  0x3E,  0x00,  0x00,  0xB3,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x3E, 	/* 00A10 */
+	0x01,  0x10,  0x10,  0x01,  0x00,  0x10,  0x01,  0x00,  0x38,  0x00,  0x00,  0xB4,  0x00,  0x00,  0x00,  0x00, 	/* 00A20 */
+	0x00,  0x00,  0x1F,  0x80,  0x90,  0x09,  0x00,  0x90,  0x11,  0x01,  0x10,  0x7F,  0x84,  0x08,  0xB5,  0x00, 	/* 00A30 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x0C,  0x01,  0x20,  0x21,  0x03,  0xF0,  0x20,  0x01,  0x10,  0x0E,  0x00, 	/* 00A40 */
+	0x00,  0xB6,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x6E,  0xC1,  0x50,  0x15,  0x00,  0xE0,  0x15,  0x02, 	/* 00A50 */
+	0x48,  0x6E,  0xC0,  0x00,  0xB7,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x07,  0x01,  0x88,  0x00,  0x80, 	/* 00A60 */
+	0x70,  0x00,  0x81,  0x08,  0x0F,  0x00,  0x00,  0xB8,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x39,  0xC1, 	/* 00A70 */
+	0x18,  0x12,  0x81,  0x48,  0x18,  0x81,  0x08,  0x39,  0xC0,  0x00,  0xB9,  0x00,  0x00,  0x90,  0x06,  0x00, 	/* 00A80 */
+	0x00,  0x39,  0xC1,  0x18,  0x12,  0x81,  0x48,  0x18,  0x81,  0x08,  0x39,  0xC0,  0x00,  0xBA,  0x00,  0x00, 	/* 00A90 */
+	0x00,  0x00,  0x00,  0x00,  0x39,  0x01,  0x28,  0x14,  0x01,  0x80,  0x14,  0x01,  0x20,  0x39,  0x80,  0x00, 	/* 00AA0 */
+	0xBB,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x1F,  0x00,  0xA0,  0x0A,  0x00,  0xA0,  0x12,  0x05,  0x20, 	/* 00AB0 */
+	0x27,  0x00,  0x00,  0xBC,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x60,  0xC3,  0x18,  0x31,  0x82,  0xA8, 	/* 00AC0 */
+	0x2A,  0x82,  0x48,  0x75,  0xC0,  0x00,  0xBD,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x3B,  0x81,  0x10, 	/* 00AD0 */
+	0x11,  0x01,  0xF0,  0x11,  0x01,  0x10,  0x3B,  0x80,  0x00,  0xBE,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 00AE0 */
+	0x0E,  0x01,  0x10,  0x20,  0x82,  0x08,  0x20,  0x81,  0x10,  0x0E,  0x00,  0x00,  0xBF,  0x00,  0x00,  0x00, 	/* 00AF0 */
+	0x00,  0x00,  0x00,  0x3F,  0x81,  0x10,  0x11,  0x01,  0x10,  0x11,  0x01,  0x10,  0x3B,  0x80,  0x00,  0x80, 	/* 00B00 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x36,  0x01,  0x90,  0x10,  0x81,  0x08,  0x19,  0x01,  0x60,  0x10, 	/* 00B10 */
+	0x03,  0x80,  0x81,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0E,  0x01,  0x10,  0x20,  0x02,  0x00,  0x20, 	/* 00B20 */
+	0x01,  0x10,  0x0E,  0x00,  0x00,  0x82,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x3F,  0x82,  0x48,  0x04, 	/* 00B30 */
+	0x00,  0x40,  0x04,  0x00,  0x40,  0x0E,  0x00,  0x00,  0x83,  0x00,  0x00,  0x00,  0x00,  0x03,  0x9C,  0x10, 	/* 00B40 */
+	0x80,  0x88,  0x05,  0x00,  0x30,  0x02,  0x00,  0x40,  0x24,  0x01,  0x80,  0x84,  0x00,  0x00,  0xE0,  0x04, 	/* 00B50 */
+	0x01,  0x50,  0x2E,  0x84,  0x44,  0x44,  0x44,  0x44,  0x2E,  0x81,  0x50,  0x04,  0x00,  0xE0,  0x85,  0x00, 	/* 00B60 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x3B,  0x81,  0x10,  0x0A,  0x00,  0x40,  0x0A,  0x01,  0x10,  0x3B,  0x80, 	/* 00B70 */
+	0x00,  0x86,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x3B,  0x81,  0x10,  0x11,  0x01,  0x10,  0x11,  0x01, 	/* 00B80 */
+	0x10,  0x3F,  0x80,  0x08,  0x87,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x3B,  0x81,  0x10,  0x11,  0x00, 	/* 00B90 */
+	0xF0,  0x01,  0x00,  0x10,  0x03,  0x80,  0x00,  0x88,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x24,  0x82, 	/* 00BA0 */
+	0x48,  0x24,  0x82,  0x48,  0x24,  0x82,  0x48,  0x3F,  0x80,  0x00,  0x89,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 00BB0 */
+	0x00,  0x49,  0x04,  0x90,  0x49,  0x04,  0x90,  0x49,  0x04,  0x90,  0x7F,  0xC0,  0x04,  0x8A,  0x00,  0x00, 	/* 00BC0 */
+	0x00,  0x00,  0x00,  0x00,  0x30,  0x05,  0x00,  0x1E,  0x01,  0x10,  0x11,  0x01,  0x10,  0x3E,  0x00,  0x00, 	/* 00BD0 */
+	0x8B,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x73,  0x82,  0x10,  0x21,  0x03,  0x90,  0x25,  0x02,  0x50, 	/* 00BE0 */
+	0x7B,  0x80,  0x00,  0x8C,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x38,  0x01,  0x00,  0x1E,  0x01,  0x10, 	/* 00BF0 */
+	0x11,  0x01,  0x10,  0x3E,  0x00,  0x00,  0x8D,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x1E,  0x02,  0x10, 	/* 00C00 */
+	0x0B,  0x01,  0x50,  0x01,  0x02,  0x10,  0x1E,  0x00,  0x00,  0x8E,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 00C10 */
+	0x73,  0x02,  0x48,  0x28,  0x43,  0x84,  0x28,  0x42,  0x48,  0x73,  0x00,  0x00,  0x8F,  0x00,  0x00,  0x00, 	/* 00C20 */
+	0x00,  0x00,  0x00,  0x0F,  0x81,  0x10,  0x11,  0x00,  0xF0,  0x09,  0x01,  0x10,  0x3B,  0x80,  0x00,  0x91, 	/* 00C30 */
+	0x00,  0x00,  0x00,  0x12,  0x00,  0x00,  0x0C,  0x01,  0x20,  0x21,  0x03,  0xF0,  0x20,  0x01,  0x10,  0x0E, 	/* 00C40 */
+	0x00,  0x00,  0x90,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0F,  0x00,  0x00,  0x00, 	/* 00C50 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x95,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xFF, 	/* 00C60 */
+	0xF0,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x98,  0x00,  0x20,  0x04,  0x00,  0x40,  0x06,  0x00, 	/* 00C70 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x99,  0x30,  0x01,  0x00,  0x10, 	/* 00C80 */
+	0x02,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x9C,  0x01, 	/* 00C90 */
+	0x20,  0x24,  0x02,  0x40,  0x36,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 00CA0 */
+	0x00,  0x9D,  0x6C,  0x02,  0x40,  0x24,  0x04,  0x80,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 00CB0 */
+	0x00,  0x00,  0x00,  0x00,  0xA0,  0x04,  0x00,  0xE0,  0x24,  0x87,  0xFC,  0x24,  0x80,  0xE0,  0x0E,  0x00, 	/* 00CC0 */
+	0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0xA1,  0x0E,  0x00,  0xE0,  0x24,  0x87,  0xFC,  0x24,  0x80, 	/* 00CD0 */
+	0x40,  0x04,  0x02,  0x48,  0x7F,  0xC2,  0x48,  0x0E,  0x00,  0xE0,  0xA5,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 00CE0 */
+	0x00,  0x00,  0x02,  0x08,  0x20,  0x80,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xA6,  0x00,  0x00, 	/* 00CF0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x04,  0x44,  0x44,  0x40,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 00D00 */
+	0xB0,  0x31,  0x04,  0x90,  0x4A,  0x04,  0xC0,  0x34,  0x00,  0x80,  0x10,  0x01,  0x44,  0x2A,  0xA4,  0xAA, 	/* 00D10 */
+	0x44,  0x40,  0x00,  0xB2,  0x18,  0x00,  0x80,  0x08,  0x01,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 00D20 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xB3,  0x36,  0x01,  0x20,  0x12,  0x02,  0x40,  0x00,  0x00,  0x00, 	/* 00D30 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xBB,  0x00,  0x04,  0x62,  0x26,  0x41,  0x08, 	/* 00D40 */
+	0x09,  0x06,  0x66,  0x66,  0x60,  0x90,  0x10,  0x82,  0x64,  0x46,  0x20,  0x00,  0x83,  0x00,  0x02,  0x34, 	/* 00D50 */
+	0x54,  0xC2,  0x84,  0x10,  0x01,  0x00,  0x10,  0x01,  0x00,  0x10,  0x40,  0x88,  0x07,  0x00,  0x00,  0xAB, 	/* 00D60 */
+	0x04,  0x00,  0xA0,  0x0A,  0x00,  0x40,  0x0A,  0x00,  0xA0,  0x11,  0x01,  0xF0,  0x20,  0x82,  0x08,  0x71, 	/* 00D70 */
+	0xC0,  0x00,  0x90,  0x00,  0x00,  0x00,  0x00,  0x00,  0xC0,  0x30,  0x0F,  0xFF,  0x30,  0x00,  0xC0,  0x00, 	/* 00D80 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x91,  0x02,  0x00,  0x20,  0x07,  0x00,  0x70,  0x0A,  0x80,  0xA8,  0x02, 	/* 00D90 */
+	0x00,  0x20,  0x02,  0x00,  0x20,  0x02,  0x00,  0x20,  0x92,  0x00,  0x00,  0x00,  0x00,  0x00,  0x30,  0x00, 	/* 00DA0 */
+	0xCF,  0xFF,  0x00,  0xC0,  0x30,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x93,  0x02,  0x00,  0x20,  0x02, 	/* 00DB0 */
+	0x00,  0x20,  0x02,  0x00,  0x20,  0x0A,  0x80,  0xA8,  0x07,  0x00,  0x70,  0x02,  0x00,  0x20,  0x92,  0x00, 	/* 00DC0 */
+	0x00,  0x00,  0x00,  0x80,  0x04,  0xFF,  0xE0,  0x01,  0xFF,  0xE0,  0x04,  0x00,  0x80,  0x00,  0x00,  0x00, 	/* 00DD0 */
+	0x00,  0x94,  0x00,  0x00,  0x00,  0x10,  0x82,  0x04,  0x7F,  0xE8,  0x01,  0x7F,  0xE2,  0x04,  0x10,  0x80, 	/* 00DE0 */
+	0x00,  0x00,  0x00,  0x00,  0x80,  0x00,  0x04,  0x04,  0x40,  0x42,  0x08,  0x3F,  0x81,  0x10,  0x11,  0x00, 	/* 00DF0 */
+	0xA0,  0x0A,  0x00,  0x40,  0x04,  0x00,  0x00,  0x82,  0x00,  0x00,  0x70,  0x08,  0x80,  0x08,  0x06,  0x80, 	/* 00E00 */
+	0x98,  0x11,  0x83,  0x10,  0x33,  0x01,  0x20,  0x0C,  0x00,  0x00,  0x83,  0x00,  0x03,  0xFC,  0x00,  0x40, 	/* 00E10 */
+	0x04,  0x00,  0x43,  0xFC,  0x00,  0x40,  0x04,  0x00,  0x43,  0xFC,  0x00,  0x00,  0x00,  0x87,  0x00,  0x0F, 	/* 00E20 */
+	0xFE,  0x7F,  0xC6,  0x04,  0x20,  0x83,  0x08,  0x11,  0x01,  0x90,  0x0A,  0x00,  0xE0,  0x04,  0x00,  0x40, 	/* 00E30 */
+	0x88,  0x00,  0x00,  0x00,  0x0F,  0xC1,  0x00,  0x20,  0x03,  0xFC,  0x20,  0x01,  0x00,  0x0F,  0xC0,  0x00, 	/* 00E40 */
+	0x00,  0x00,  0x00,  0x8B,  0x00,  0x00,  0x00,  0x3F,  0x00,  0x08,  0x00,  0x43,  0xFC,  0x00,  0x40,  0x08, 	/* 00E50 */
+	0x3F,  0x00,  0x00,  0x00,  0x00,  0x00,  0x9A,  0x03,  0xF0,  0x20,  0x02,  0x00,  0x40,  0x04,  0x00,  0x40, 	/* 00E60 */
+	0x08,  0x04,  0x80,  0xE8,  0x03,  0x00,  0x10,  0x00,  0x00,  0x9D,  0x00,  0x00,  0x00,  0x00,  0x01,  0x8C, 	/* 00E70 */
+	0x25,  0x24,  0x20,  0x42,  0x02,  0x52,  0x18,  0xC0,  0x00,  0x00,  0x00,  0x00,  0x9E,  0x00,  0x00,  0x00, 	/* 00E80 */
+	0x00,  0x03,  0x18,  0x4A,  0x48,  0x42,  0x84,  0x24,  0xA4,  0x31,  0x80,  0x00,  0x00,  0x00,  0x00,  0xA0, 	/* 00E90 */
+	0x00,  0x00,  0x04,  0x00,  0x80,  0x10,  0x02,  0x00,  0x40,  0x08,  0x01,  0x00,  0x20,  0x07,  0xFE,  0x00, 	/* 00EA0 */
+	0x00,  0x00,  0xA5,  0x09,  0x00,  0x90,  0x09,  0x00,  0x90,  0x09,  0x00,  0x90,  0x09,  0x00,  0x90,  0x09, 	/* 00EB0 */
+	0x00,  0x90,  0x09,  0x00,  0x90,  0xA7,  0x00,  0x00,  0x40,  0x04,  0x00,  0xA0,  0x0A,  0x01,  0x10,  0x11, 	/* 00EC0 */
+	0x02,  0x08,  0x20,  0x84,  0x04,  0x40,  0x40,  0x00,  0xA8,  0x00,  0x04,  0x04,  0x40,  0x42,  0x08,  0x20, 	/* 00ED0 */
+	0x81,  0x10,  0x11,  0x00,  0xA0,  0x0A,  0x00,  0x40,  0x04,  0x00,  0x00,  0xA9,  0x00,  0x01,  0xE0,  0x21, 	/* 00EE0 */
+	0x04,  0x08,  0x40,  0x84,  0x08,  0x40,  0x84,  0x08,  0x40,  0x84,  0x08,  0x40,  0x80,  0x00,  0xAA,  0x00, 	/* 00EF0 */
+	0x04,  0x08,  0x40,  0x84,  0x08,  0x40,  0x84,  0x08,  0x40,  0x84,  0x08,  0x40,  0x82,  0x10,  0x1E,  0x00, 	/* 00F00 */
+	0x00,  0xAB,  0x00,  0xC0,  0x10,  0x02,  0x00,  0x20,  0x03,  0x00,  0x30,  0x01,  0x00,  0x18,  0x01,  0x80, 	/* 00F10 */
+	0x08,  0x01,  0x00,  0x60,  0xAC,  0x06,  0x60,  0x88,  0x11,  0x01,  0x10,  0x19,  0x81,  0x98,  0x08,  0x80, 	/* 00F20 */
+	0xCC,  0x0C,  0xC0,  0x44,  0x08,  0x83,  0x30,  0xB4,  0x00,  0x00,  0x00,  0x06,  0x00,  0x60,  0x00,  0x00, 	/* 00F30 */
+	0x00,  0x00,  0x00,  0x00,  0x30,  0xC3,  0x0C,  0x00,  0x00,  0x00,  0xB5,  0x00,  0x00,  0x00,  0x61,  0x86, 	/* 00F40 */
+	0x18,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0C,  0x00,  0xC0,  0x00,  0x00,  0x00,  0xBD,  0x00,  0x00, 	/* 00F50 */
+	0x00,  0x00,  0x01,  0x98,  0x22,  0x44,  0x22,  0x44,  0x22,  0x44,  0x19,  0x80,  0x00,  0x00,  0x00,  0x00, 	/* 00F60 */
+	0x92,  0x00,  0x01,  0x80,  0x18,  0x00,  0x00,  0x7F,  0xE0,  0x00,  0x00,  0x07,  0xFE,  0x00,  0x00,  0x18, 	/* 00F70 */
+	0x01,  0x80,  0x00,  0xA0,  0x00,  0x00,  0x10,  0x01,  0x00,  0x20,  0x7F,  0xC0,  0x40,  0x04,  0x07,  0xFC, 	/* 00F80 */
+	0x08,  0x01,  0x00,  0x10,  0x00,  0x00,  0xA1,  0x00,  0x00,  0x00,  0x00,  0x07,  0xFE,  0x00,  0x00,  0x00, 	/* 00F90 */
+	0x7F,  0xE0,  0x00,  0x00,  0x07,  0xFE,  0x00,  0x00,  0x00,  0xA6,  0x00,  0x00,  0x06,  0x03,  0x81,  0xC0, 	/* 00FA0 */
+	0x60,  0x01,  0xC0,  0x03,  0x80,  0x06,  0x7F,  0xE0,  0x00,  0x7F,  0xE0,  0x00,  0xA7,  0x00,  0x06,  0x00, 	/* 00FB0 */
+	0x1C,  0x00,  0x38,  0x00,  0x60,  0x38,  0x1C,  0x06,  0x00,  0x7F,  0xE0,  0x00,  0x7F,  0xE0,  0x00,  0xAA, 	/* 00FC0 */
+	0x00,  0x00,  0x00,  0x04,  0x40,  0x88,  0x11,  0x02,  0x20,  0x44,  0x02,  0x20,  0x11,  0x00,  0x88,  0x04, 	/* 00FD0 */
+	0x40,  0x00,  0xAB,  0x00,  0x00,  0x00,  0x44,  0x02,  0x20,  0x11,  0x00,  0x88,  0x04,  0x40,  0x88,  0x11, 	/* 00FE0 */
+	0x02,  0x20,  0x44,  0x00,  0x00,  0x82,  0x00,  0x00,  0x00,  0x1F,  0xE2,  0x00,  0x40,  0x04,  0x00,  0x40, 	/* 00FF0 */
+	0x04,  0x00,  0x20,  0x01,  0xFE,  0x00,  0x00,  0x00,  0x83,  0x00,  0x00,  0x00,  0x7F,  0x80,  0x04,  0x00, 	/* 01000 */
+	0x20,  0x02,  0x00,  0x20,  0x02,  0x00,  0x47,  0xF8,  0x00,  0x00,  0x00,  0x86,  0x00,  0x00,  0x00,  0x1F, 	/* 01010 */
+	0xE2,  0x00,  0x40,  0x04,  0x00,  0x20,  0x01,  0xFE,  0x00,  0x00,  0x00,  0x3F,  0xE0,  0x00,  0x87,  0x00, 	/* 01020 */
+	0x00,  0x00,  0x7F,  0x80,  0x04,  0x00,  0x20,  0x02,  0x00,  0x47,  0xF8,  0x00,  0x00,  0x00,  0x7F,  0xC0, 	/* 01030 */
+	0x00,  0xA5,  0x00,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x07, 	/* 01040 */
+	0xFE,  0x00,  0x00,  0x00,  0x92,  0x0F,  0x03,  0x0C,  0x40,  0x20,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 01050 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x80,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0F, 	/* 01060 */
+	0xFF,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x81,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 01070 */
+	0x00,  0x00,  0x0F,  0xFF,  0xFF,  0xF0,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x82,  0x04,  0x00, 	/* 01080 */
+	0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40, 	/* 01090 */
+	0x83,  0x06,  0x00,  0x60,  0x06,  0x00,  0x60,  0x06,  0x00,  0x60,  0x06,  0x00,  0x60,  0x06,  0x00,  0x60, 	/* 010A0 */
+	0x06,  0x00,  0x60,  0x8C,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x7F,  0x04,  0x00,  0x40, 	/* 010B0 */
+	0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x8F,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x7F, 	/* 010C0 */
+	0x07,  0xF0,  0x60,  0x06,  0x00,  0x60,  0x06,  0x00,  0x60,  0x90,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 010D0 */
+	0x00,  0x0F,  0xC0,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x93,  0x00,  0x00,  0x00, 	/* 010E0 */
+	0x00,  0x00,  0x00,  0x00,  0x0F,  0xE0,  0xFE,  0x00,  0x60,  0x06,  0x00,  0x60,  0x06,  0x00,  0x60,  0x94, 	/* 010F0 */
+	0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x7F,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 01100 */
+	0x00,  0x00,  0x97,  0x06,  0x00,  0x60,  0x06,  0x00,  0x60,  0x06,  0x00,  0x7F,  0x07,  0xF0,  0x00,  0x00, 	/* 01110 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x98,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x0F,  0xC0,  0x00, 	/* 01120 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x9B,  0x06,  0x00,  0x60,  0x06,  0x00,  0x60,  0x06, 	/* 01130 */
+	0x0F,  0xE0,  0xFE,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x9C,  0x04,  0x00,  0x40,  0x04, 	/* 01140 */
+	0x00,  0x40,  0x04,  0x00,  0x7F,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x9D,  0x04, 	/* 01150 */
+	0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x7F,  0x07,  0xF0,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00, 	/* 01160 */
+	0x40,  0xA0,  0x06,  0x00,  0x60,  0x06,  0x00,  0x60,  0x06,  0x00,  0x7F,  0x06,  0x00,  0x60,  0x06,  0x00, 	/* 01170 */
+	0x60,  0x06,  0x00,  0x60,  0xA3,  0x06,  0x00,  0x60,  0x06,  0x00,  0x60,  0x06,  0x00,  0x7F,  0x07,  0xF0, 	/* 01180 */
+	0x60,  0x06,  0x00,  0x60,  0x06,  0x00,  0x60,  0xA4,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x0F, 	/* 01190 */
+	0xC0,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0xA5,  0x04,  0x00,  0x40,  0x04,  0x00, 	/* 011A0 */
+	0x40,  0x04,  0x0F,  0xC0,  0xFC,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0xA8,  0x06,  0x00, 	/* 011B0 */
+	0x60,  0x06,  0x00,  0x60,  0x06,  0x0F,  0xE0,  0x06,  0x00,  0x60,  0x06,  0x00,  0x60,  0x06,  0x00,  0x60, 	/* 011C0 */
+	0xAB,  0x06,  0x00,  0x60,  0x06,  0x00,  0x60,  0x06,  0x0F,  0xE0,  0xFE,  0x00,  0x60,  0x06,  0x00,  0x60, 	/* 011D0 */
+	0x06,  0x00,  0x60,  0xAC,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0F,  0xFF,  0x04,  0x00,  0x40, 	/* 011E0 */
+	0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0xAF,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0F,  0xFF, 	/* 011F0 */
+	0xFF,  0xF0,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0xB0,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 01200 */
+	0x00,  0x0F,  0xFF,  0x06,  0x00,  0x60,  0x06,  0x00,  0x60,  0x06,  0x00,  0x60,  0xB3,  0x00,  0x00,  0x00, 	/* 01210 */
+	0x00,  0x00,  0x00,  0x00,  0x0F,  0xFF,  0xFF,  0xF0,  0x60,  0x06,  0x00,  0x60,  0x06,  0x00,  0x60,  0xB4, 	/* 01220 */
+	0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x0F,  0xFF,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 01230 */
+	0x00,  0x00,  0xB7,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x0F,  0xFF,  0xFF,  0xF0,  0x00,  0x00, 	/* 01240 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0xB8,  0x06,  0x00,  0x60,  0x06,  0x00,  0x60,  0x06,  0x0F,  0xFF,  0x00, 	/* 01250 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xBB,  0x06,  0x00,  0x60,  0x06,  0x00,  0x60,  0x06, 	/* 01260 */
+	0x0F,  0xFF,  0xFF,  0xF0,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xBC,  0x04,  0x00,  0x40,  0x04, 	/* 01270 */
+	0x00,  0x40,  0x04,  0x0F,  0xFF,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0xBF,  0x04, 	/* 01280 */
+	0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x0F,  0xFF,  0xFF,  0xF0,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00, 	/* 01290 */
+	0x40,  0x82,  0x06,  0x00,  0x60,  0x06,  0x00,  0x60,  0x06,  0x0F,  0xFF,  0x06,  0x00,  0x60,  0x06,  0x00, 	/* 012A0 */
+	0x60,  0x06,  0x00,  0x60,  0x8B,  0x06,  0x00,  0x60,  0x06,  0x00,  0x60,  0x06,  0x0F,  0xFF,  0xFF,  0xF0, 	/* 012B0 */
+	0x60,  0x06,  0x00,  0x60,  0x06,  0x00,  0x60,  0xA0,  0x00,  0x0F,  0xFE,  0xFF,  0xEF,  0xFE,  0xFF,  0xEF, 	/* 012C0 */
+	0xFE,  0xFF,  0xEF,  0xFE,  0xFF,  0xEF,  0xFE,  0xFF,  0xEF,  0xFE,  0xA1,  0x00,  0x0F,  0xFE,  0x80,  0x28, 	/* 012D0 */
+	0x02,  0x80,  0x28,  0x02,  0x80,  0x28,  0x02,  0x80,  0x28,  0x02,  0x80,  0x2F,  0xFE,  0xB2,  0x04,  0x00, 	/* 012E0 */
+	0x40,  0x0E,  0x00,  0xE0,  0x1F,  0x01,  0xF0,  0x3F,  0x83,  0xF8,  0x7F,  0xC7,  0xFC,  0xFF,  0xE0,  0x00, 	/* 012F0 */
+	0xB3,  0x04,  0x00,  0x40,  0x0A,  0x00,  0xA0,  0x11,  0x01,  0x10,  0x20,  0x82,  0x08,  0x40,  0x44,  0x04, 	/* 01300 */
+	0xFF,  0xE0,  0x00,  0xBC,  0x00,  0x0F,  0xFE,  0x7F,  0xC7,  0xFC,  0x3F,  0x83,  0xF8,  0x1F,  0x01,  0xF0, 	/* 01310 */
+	0x0E,  0x00,  0xE0,  0x04,  0x00,  0x40,  0xBD,  0x00,  0x0F,  0xFE,  0x40,  0x44,  0x04,  0x20,  0x82,  0x08, 	/* 01320 */
+	0x11,  0x01,  0x10,  0x0A,  0x00,  0xA0,  0x04,  0x00,  0x40,  0x86,  0x00,  0x00,  0x40,  0x0E,  0x01,  0xF0, 	/* 01330 */
+	0x3F,  0x87,  0xFC,  0xFF,  0xE7,  0xFC,  0x3F,  0x81,  0xF0,  0x0E,  0x00,  0x40,  0x87,  0x00,  0x00,  0x40, 	/* 01340 */
+	0x0A,  0x01,  0x10,  0x20,  0x84,  0x04,  0x80,  0x24,  0x04,  0x20,  0x81,  0x10,  0x0A,  0x00,  0x40,  0x8B, 	/* 01350 */
+	0x00,  0x00,  0xE0,  0x31,  0x84,  0x04,  0x40,  0x48,  0x02,  0x80,  0x28,  0x02,  0x40,  0x44,  0x04,  0x31, 	/* 01360 */
+	0x80,  0xE0,  0x8E,  0x00,  0x00,  0xE0,  0x31,  0x84,  0xE4,  0x51,  0x4A,  0x0A,  0xA0,  0xAA,  0x0A,  0x51, 	/* 01370 */
+	0x44,  0xE4,  0x31,  0x80,  0xE0,  0x8F,  0x00,  0x00,  0xE0,  0x3F,  0x87,  0xFC,  0x7F,  0xCF,  0xFE,  0xFF, 	/* 01380 */
+	0xEF,  0xFE,  0x7F,  0xC7,  0xFC,  0x3F,  0x80,  0xE0,  0xAF,  0x0F,  0x03,  0x0C,  0x40,  0x24,  0x02,  0x80, 	/* 01390 */
+	0x18,  0x01,  0x80,  0x18,  0x01,  0x40,  0x24,  0x02,  0x30,  0xC0,  0xF0,  0x85,  0x00,  0x00,  0x40,  0x04, 	/* 013A0 */
+	0x00,  0xE0,  0xFF,  0xE7,  0xFC,  0x3F,  0x81,  0xF0,  0x3F,  0x83,  0xB8,  0x60,  0xC0,  0x00,  0x86,  0x00, 	/* 013B0 */
+	0x00,  0x40,  0x04,  0x00,  0xA0,  0xFB,  0xE4,  0x04,  0x20,  0x81,  0x10,  0x24,  0x83,  0xB8,  0x60,  0xC0, 	/* 013C0 */
+	0x00,  0x80,  0x00,  0x00,  0xE0,  0x11,  0x01,  0x10,  0x11,  0x00,  0xE0,  0x04,  0x00,  0x40,  0x3F,  0x80, 	/* 013D0 */
+	0x40,  0x04,  0x00,  0x40,  0x82,  0x00,  0x00,  0x3E,  0x00,  0x60,  0x0A,  0x01,  0x20,  0x22,  0x3C,  0x04, 	/* 013E0 */
+	0x40,  0x44,  0x04,  0x40,  0x38,  0x00,  0x00,  0xAA,  0x02,  0x00,  0x30,  0x03,  0x80,  0x2C,  0x02,  0x40, 	/* 013F0 */
+	0x24,  0x02,  0x80,  0x20,  0x1E,  0x03,  0xE0,  0x1C,  0x00,  0x00,  0xAD,  0x08,  0x00,  0x80,  0x08,  0x00, 	/* 01400 */
+	0x80,  0x08,  0x00,  0xB0,  0x0D,  0x80,  0x98,  0x09,  0x00,  0xA0,  0x0C,  0x00,  0x00,  0xAF,  0x01,  0x00, 	/* 01410 */
+	0x10,  0x09,  0xC0,  0xFC,  0x3F,  0x03,  0x90,  0x09,  0xC0,  0xFC,  0x3F,  0x03,  0x90,  0x08,  0x00,  0x80, 	/* 01420 */
+	0x80,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 01430 */
+	0x00,  0x00,  0x00,  0x81,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 01440 */
+	0x00,  0x04,  0x00,  0x20,  0x02,  0x00,  0x82,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 01450 */
+	0x00,  0x00,  0x00,  0x00,  0x03,  0x00,  0x48,  0x03,  0x00,  0x83,  0x00,  0x00,  0x00,  0x00,  0x00,  0x90, 	/* 01460 */
+	0x09,  0x00,  0x90,  0x12,  0x01,  0x20,  0x24,  0x00,  0x00,  0x00,  0x00,  0x00,  0x85,  0x00,  0x00,  0x00, 	/* 01470 */
+	0x08,  0x00,  0xF8,  0x08,  0x81,  0x10,  0x21,  0x04,  0xA0,  0x06,  0x00,  0x10,  0x00,  0x80,  0x00,  0x86, 	/* 01480 */
+	0x00,  0x00,  0x04,  0x00,  0x40,  0x08,  0x01,  0x01,  0xA0,  0x26,  0x04,  0x90,  0x50,  0x06,  0x00,  0x00, 	/* 01490 */
+	0x00,  0x00,  0x87,  0x00,  0x00,  0xE0,  0x31,  0x84,  0x04,  0x40,  0x48,  0x02,  0x80,  0x28,  0x02,  0x40, 	/* 014A0 */
+	0x44,  0x04,  0x31,  0x80,  0xE0,  0x88,  0x00,  0x40,  0x08,  0x00,  0x80,  0x10,  0x01,  0x00,  0x20,  0x02, 	/* 014B0 */
+	0x00,  0x10,  0x01,  0x00,  0x08,  0x00,  0x80,  0x04,  0x89,  0x20,  0x01,  0x00,  0x10,  0x00,  0x80,  0x08, 	/* 014C0 */
+	0x00,  0x40,  0x04,  0x00,  0x80,  0x08,  0x01,  0x00,  0x10,  0x02,  0x00,  0x8A,  0x02,  0x40,  0x48,  0x04, 	/* 014D0 */
+	0x80,  0x90,  0x09,  0x01,  0x20,  0x12,  0x00,  0x90,  0x09,  0x00,  0x48,  0x04,  0x80,  0x24,  0x8B,  0x24, 	/* 014E0 */
+	0x01,  0x20,  0x12,  0x00,  0x90,  0x09,  0x00,  0x48,  0x04,  0x80,  0x90,  0x09,  0x01,  0x20,  0x12,  0x02, 	/* 014F0 */
+	0x40,  0x8C,  0x03,  0xC0,  0x20,  0x02,  0x00,  0x20,  0x02,  0x00,  0x20,  0x02,  0x00,  0x20,  0x00,  0x00, 	/* 01500 */
+	0x00,  0x00,  0x00,  0x00,  0x8D,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x04,  0x00,  0x40,  0x04,  0x00, 	/* 01510 */
+	0x40,  0x04,  0x00,  0x40,  0x04,  0x03,  0xC0,  0x8E,  0x07,  0xC0,  0x44,  0x05,  0xC0,  0x50,  0x05,  0x00, 	/* 01520 */
+	0x50,  0x05,  0x00,  0x70,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x8F,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 01530 */
+	0x00,  0x0E,  0x00,  0xA0,  0x0A,  0x00,  0xA0,  0x0A,  0x03,  0xA0,  0x22,  0x03,  0xE0,  0x90,  0x03,  0xC0, 	/* 01540 */
+	0x38,  0x03,  0x80,  0x30,  0x03,  0x00,  0x30,  0x03,  0x00,  0x30,  0x03,  0x00,  0x38,  0x03,  0x80,  0x3C, 	/* 01550 */
+	0x91,  0x3C,  0x01,  0xC0,  0x1C,  0x00,  0xC0,  0x0C,  0x00,  0xC0,  0x0C,  0x00,  0xC0,  0x0C,  0x01,  0xC0, 	/* 01560 */
+	0x1C,  0x03,  0xC0,  0x92,  0x00,  0x07,  0xFE,  0x7F,  0xE0,  0x00,  0xFF,  0xFF,  0xFF,  0x06,  0x00,  0x60, 	/* 01570 */
+	0x06,  0x00,  0x60,  0x06,  0x00,  0x60,  0x93,  0x00,  0x00,  0x00,  0x00,  0x0F,  0xFF,  0xFF,  0xF0,  0x00, 	/* 01580 */
+	0x00,  0x0F,  0xFF,  0xFF,  0xF0,  0x00,  0x00,  0x00,  0x00,  0x94,  0x00,  0xC0,  0x30,  0x02,  0x00,  0x20, 	/* 01590 */
+	0x02,  0x00,  0x20,  0x02,  0x00,  0x20,  0x02,  0x00,  0x20,  0x03,  0x00,  0x0C,  0x95,  0x30,  0x00,  0xC0, 	/* 015A0 */
+	0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x0C,  0x03,  0x00,  0x81, 	/* 015B0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x08,  0x01,  0xE0,  0x0A,  0x01,  0xF0,  0x1C,  0x82,  0x88,  0x11, 	/* 015C0 */
+	0x00,  0x00,  0x82,  0x08,  0x00,  0x80,  0x3F,  0x00,  0x80,  0x0F,  0x01,  0x28,  0x32,  0x45,  0x44,  0x4C, 	/* 015D0 */
+	0x44,  0x88,  0x33,  0x00,  0x00,  0x83,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x01,  0x00,  0x12, 	/* 015E0 */
+	0x02,  0x10,  0x29,  0x01,  0x00,  0x00,  0x00,  0x00,  0x84,  0x00,  0x00,  0x00,  0x20,  0x02,  0x10,  0x40, 	/* 015F0 */
+	0x84,  0x08,  0x40,  0x44,  0x84,  0x28,  0x41,  0x00,  0x00,  0x00,  0x00,  0x85,  0x00,  0x00,  0x00,  0x00, 	/* 01600 */
+	0x00,  0x00,  0x10,  0x00,  0xC0,  0x1C,  0x02,  0x20,  0x02,  0x00,  0x40,  0x18,  0x00,  0x00,  0x86,  0x08, 	/* 01610 */
+	0x00,  0x60,  0x00,  0x00,  0xE0,  0x31,  0x00,  0x08,  0x00,  0x80,  0x08,  0x01,  0x00,  0x60,  0x18,  0x00, 	/* 01620 */
+	0x00,  0x87,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x10,  0x00,  0x80,  0x3E,  0x00,  0x40,  0x18,  0x02, 	/* 01630 */
+	0x40,  0x47,  0x00,  0x00,  0x88,  0x08,  0x00,  0x60,  0x00,  0x01,  0xF0,  0x01,  0x00,  0x20,  0x04,  0x00, 	/* 01640 */
+	0xC0,  0x12,  0x02,  0x20,  0x41,  0xC0,  0x00,  0x89,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x08,  0x03, 	/* 01650 */
+	0xD0,  0x08,  0x80,  0xE0,  0x19,  0x02,  0x90,  0x12,  0x00,  0x00,  0x8A,  0x08,  0x00,  0x80,  0x0E,  0x47, 	/* 01660 */
+	0x82,  0x08,  0x20,  0xF0,  0x18,  0x82,  0x84,  0x48,  0x44,  0x88,  0x33,  0x00,  0x00,  0x8B,  0x00,  0x01, 	/* 01670 */
+	0x00,  0x10,  0x87,  0xC4,  0x12,  0x41,  0x22,  0x12,  0x22,  0x20,  0x22,  0x05,  0x20,  0x0C,  0x00,  0x00, 	/* 01680 */
+	0x8C,  0x00,  0x01,  0x0A,  0x10,  0xA7,  0xC4,  0x12,  0x41,  0x22,  0x12,  0x22,  0x20,  0x22,  0x05,  0x20, 	/* 01690 */
+	0x0C,  0x00,  0x00,  0x8D,  0x04,  0x00,  0x70,  0x3C,  0x00,  0x38,  0x3E,  0x00,  0x10,  0x0E,  0x81,  0x18, 	/* 016A0 */
+	0x20,  0x01,  0x00,  0x0F,  0x00,  0x00,  0x8E,  0x05,  0x40,  0x74,  0x3C,  0x00,  0x38,  0x3E,  0x00,  0x10, 	/* 016B0 */
+	0x0E,  0x81,  0x18,  0x20,  0x01,  0x00,  0x0F,  0x00,  0x00,  0x8F,  0x00,  0x00,  0x20,  0x02,  0x00,  0x40, 	/* 016C0 */
+	0x08,  0x01,  0x00,  0x10,  0x00,  0x80,  0x04,  0x00,  0x20,  0x02,  0x00,  0x00,  0x90,  0x00,  0x00,  0x40, 	/* 016D0 */
+	0x06,  0x80,  0xA8,  0x10,  0x02,  0x00,  0x20,  0x01,  0x00,  0x08,  0x00,  0x40,  0x04,  0x00,  0x00,  0x91, 	/* 016E0 */
+	0x00,  0x82,  0x08,  0x20,  0xE2,  0x78,  0x40,  0x84,  0x08,  0x40,  0x85,  0x08,  0x20,  0x80,  0x10,  0x06, 	/* 016F0 */
+	0x00,  0x00,  0x92,  0x01,  0x52,  0x15,  0x20,  0xE2,  0x78,  0x40,  0x84,  0x08,  0x40,  0x85,  0x08,  0x20, 	/* 01700 */
+	0x80,  0x10,  0x06,  0x00,  0x00,  0x93,  0x00,  0x01,  0x00,  0x0F,  0x80,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 01710 */
+	0x02,  0x00,  0x20,  0x41,  0xF8,  0x00,  0x00,  0x00,  0x94,  0x00,  0x02,  0x14,  0x1F,  0x40,  0x00,  0x00, 	/* 01720 */
+	0x00,  0x00,  0x00,  0x04,  0x00,  0x40,  0x83,  0xF0,  0x00,  0x00,  0x00,  0x95,  0x04,  0x00,  0x40,  0x02, 	/* 01730 */
+	0xC3,  0xF0,  0x02,  0x00,  0x10,  0x1E,  0x82,  0x18,  0x20,  0x01,  0x80,  0x07,  0x00,  0x00,  0x96,  0x09, 	/* 01740 */
+	0x40,  0x94,  0x05,  0x87,  0xE0,  0x04,  0x00,  0x20,  0x3D,  0x04,  0x30,  0x40,  0x03,  0x00,  0x0E,  0x00, 	/* 01750 */
+	0x00,  0x97,  0x00,  0x01,  0x00,  0x10,  0x01,  0x00,  0x10,  0x01,  0x00,  0x10,  0x01,  0x00,  0x10,  0x40, 	/* 01760 */
+	0x98,  0x06,  0x00,  0x00,  0x98,  0x00,  0x01,  0x00,  0x11,  0x41,  0x14,  0x10,  0x01,  0x00,  0x10,  0x01, 	/* 01770 */
+	0x00,  0x10,  0x40,  0x98,  0x06,  0x00,  0x00,  0x99,  0x02,  0x00,  0x20,  0x7F,  0xC0,  0x20,  0x0E,  0x01, 	/* 01780 */
+	0x20,  0x12,  0x00,  0xE0,  0x02,  0x00,  0x40,  0x18,  0x00,  0x00,  0x9A,  0x02,  0xA0,  0x2A,  0x7F,  0xC0, 	/* 01790 */
+	0x20,  0x0E,  0x01,  0x20,  0x12,  0x00,  0xE0,  0x02,  0x00,  0x40,  0x18,  0x00,  0x00,  0x9B,  0x00,  0x00, 	/* 017A0 */
+	0x10,  0x11,  0x01,  0x1E,  0x7F,  0x01,  0x10,  0x11,  0x01,  0x20,  0x10,  0x00,  0x80,  0x07,  0x80,  0x00, 	/* 017B0 */
+	0x9C,  0x00,  0x00,  0x2A,  0x22,  0xA2,  0x38,  0xFE,  0x02,  0x20,  0x22,  0x02,  0x40,  0x20,  0x01,  0x00, 	/* 017C0 */
+	0x0F,  0x00,  0x00,  0x9D,  0x00,  0x01,  0xF0,  0x02,  0x00,  0x40,  0x09,  0xC7,  0xE0,  0x04,  0x00,  0x80, 	/* 017D0 */
+	0x08,  0x00,  0x40,  0x03,  0x00,  0x00,  0x9E,  0x00,  0x01,  0xFA,  0x02,  0xA0,  0x40,  0x09,  0xC7,  0xE0, 	/* 017E0 */
+	0x04,  0x00,  0x80,  0x08,  0x00,  0x40,  0x03,  0x00,  0x00,  0x9F,  0x08,  0x00,  0x80,  0x7E,  0x01,  0x00, 	/* 017F0 */
+	0x10,  0xC1,  0x30,  0x20,  0x02,  0x00,  0x24,  0x04,  0x40,  0x43,  0xC0,  0x00,  0xA0,  0x08,  0x00,  0x8A, 	/* 01800 */
+	0x7E,  0xA1,  0x00,  0x10,  0xC1,  0x30,  0x20,  0x02,  0x00,  0x24,  0x04,  0x40,  0x43,  0xC0,  0x00,  0xA1, 	/* 01810 */
+	0x10,  0x01,  0x00,  0x7F,  0x01,  0x00,  0x10,  0x02,  0x60,  0x39,  0x02,  0x08,  0x00,  0x80,  0x30,  0x1C, 	/* 01820 */
+	0x00,  0x00,  0xA2,  0x10,  0x01,  0x14,  0x7F,  0x41,  0x00,  0x10,  0x02,  0x60,  0x39,  0x02,  0x08,  0x00, 	/* 01830 */
+	0x80,  0x30,  0x1C,  0x00,  0x00,  0xA3,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0E, 	/* 01840 */
+	0x03,  0x10,  0x01,  0x00,  0x20,  0x0C,  0x00,  0x00,  0xA4,  0x00,  0x00,  0x00,  0x0F,  0x0F,  0x08,  0x00, 	/* 01850 */
+	0x40,  0x04,  0x00,  0x80,  0x30,  0x0C,  0x00,  0x00,  0x00,  0x00,  0x00,  0xA5,  0x00,  0x00,  0x0A,  0x1E, 	/* 01860 */
+	0xAE,  0x10,  0x00,  0x80,  0x08,  0x01,  0x00,  0x60,  0x18,  0x00,  0x00,  0x00,  0x00,  0x00,  0xA6,  0x00, 	/* 01870 */
+	0x00,  0x1C,  0x7E,  0x00,  0x20,  0x04,  0x00,  0x80,  0x08,  0x00,  0x80,  0x04,  0x00,  0x38,  0x00,  0x00, 	/* 01880 */
+	0x00,  0xA7,  0x00,  0x00,  0x38,  0xFC,  0x00,  0x54,  0x09,  0x41,  0x00,  0x10,  0x01,  0x00,  0x08,  0x00, 	/* 01890 */
+	0x70,  0x00,  0x00,  0x00,  0xA8,  0x00,  0x00,  0x80,  0x08,  0x00,  0x80,  0x04,  0xC0,  0x70,  0x0C,  0x01, 	/* 018A0 */
+	0x00,  0x20,  0x01,  0x00,  0x0F,  0xC0,  0x00,  0xA9,  0x00,  0x00,  0x8A,  0x08,  0xA0,  0x80,  0x04,  0xC0, 	/* 018B0 */
+	0x70,  0x0C,  0x01,  0x00,  0x20,  0x01,  0x00,  0x0F,  0xC0,  0x00,  0xAA,  0x08,  0x00,  0x80,  0x3E,  0x41, 	/* 018C0 */
+	0x0A,  0x10,  0x82,  0x08,  0x20,  0x84,  0x78,  0x08,  0xC0,  0x8A,  0x07,  0x00,  0x00,  0xAB,  0x00,  0x02, 	/* 018D0 */
+	0x00,  0x21,  0x82,  0x60,  0x40,  0x04,  0x00,  0x40,  0x04,  0x40,  0x44,  0x05,  0x3C,  0x20,  0x00,  0x00, 	/* 018E0 */
+	0xAC,  0x00,  0x00,  0x20,  0x22,  0x02,  0xF8,  0x32,  0x42,  0x22,  0x34,  0x25,  0x42,  0x49,  0xA4,  0xA4, 	/* 018F0 */
+	0x31,  0xC0,  0x00,  0xAD,  0x10,  0x01,  0x00,  0x10,  0x07,  0xB8,  0x14,  0x41,  0x84,  0x10,  0x43,  0x04, 	/* 01900 */
+	0x31,  0xC5,  0x26,  0x11,  0x80,  0x00,  0xAE,  0x00,  0x00,  0xF0,  0x14,  0x82,  0x44,  0x44,  0x24,  0x42, 	/* 01910 */
+	0x48,  0x24,  0x84,  0x30,  0x80,  0x30,  0x00,  0x00,  0x00,  0xAF,  0x00,  0x02,  0x08,  0x20,  0xE2,  0xF8, 	/* 01920 */
+	0x40,  0x84,  0x08,  0x40,  0x84,  0x78,  0x48,  0xC5,  0x8A,  0x27,  0x00,  0x00,  0xB0,  0x00,  0x52,  0x0D, 	/* 01930 */
+	0x20,  0x82,  0xFC,  0x40,  0x84,  0x08,  0x40,  0x84,  0x78,  0x48,  0xC5,  0x8A,  0x27,  0x00,  0x00,  0xB1, 	/* 01940 */
+	0x00,  0x62,  0x09,  0x20,  0xE2,  0xF8,  0x40,  0x84,  0x08,  0x40,  0x84,  0x78,  0x48,  0xC5,  0x8A,  0x27, 	/* 01950 */
+	0x00,  0x00,  0xB2,  0x00,  0x00,  0x20,  0x1C,  0x00,  0x88,  0x10,  0x81,  0x0C,  0x20,  0xA2,  0x08,  0x20, 	/* 01960 */
+	0x81,  0x10,  0x0E,  0x00,  0x00,  0xB3,  0x00,  0x00,  0x45,  0x38,  0x51,  0x10,  0x21,  0x02,  0x18,  0x41, 	/* 01970 */
+	0x44,  0x10,  0x41,  0x02,  0x20,  0x1C,  0x00,  0x00,  0xB4,  0x00,  0x60,  0x89,  0x70,  0x61,  0x10,  0x21, 	/* 01980 */
+	0x02,  0x18,  0x41,  0x44,  0x10,  0x41,  0x02,  0x20,  0x1C,  0x00,  0x00,  0xB5,  0x00,  0x00,  0x80,  0x07, 	/* 01990 */
+	0x00,  0x00,  0x04,  0x00,  0x48,  0x12,  0x41,  0x22,  0x21,  0x25,  0x10,  0x0E,  0x00,  0x00,  0xB6,  0x00, 	/* 019A0 */
+	0x00,  0x8A,  0x07,  0xA0,  0x00,  0x04,  0x00,  0x48,  0x12,  0x41,  0x22,  0x21,  0x25,  0x10,  0x0E,  0x00, 	/* 019B0 */
+	0x00,  0xB7,  0x00,  0x00,  0x86,  0x07,  0x90,  0x06,  0x04,  0x00,  0x48,  0x12,  0x41,  0x22,  0x21,  0x25, 	/* 019C0 */
+	0x10,  0x0E,  0x00,  0x00,  0xB8,  0x00,  0x00,  0x00,  0x00,  0x00,  0xC0,  0x12,  0x06,  0x10,  0x00,  0x80, 	/* 019D0 */
+	0x04,  0x00,  0x20,  0x00,  0x00,  0x00,  0x00,  0xB9,  0x00,  0x00,  0x0A,  0x00,  0xA0,  0xC0,  0x12,  0x06, 	/* 019E0 */
+	0x10,  0x00,  0x80,  0x04,  0x00,  0x20,  0x00,  0x00,  0x00,  0x00,  0xBA,  0x00,  0x00,  0x0C,  0x01,  0x20, 	/* 019F0 */
+	0xCC,  0x12,  0x02,  0x10,  0xC0,  0x80,  0x04,  0x00,  0x20,  0x00,  0x00,  0x00,  0x00,  0xBB,  0x00,  0x02, 	/* 01A00 */
+	0xFE,  0x20,  0x82,  0x08,  0x47,  0xC4,  0x08,  0x40,  0x84,  0x78,  0x48,  0xC5,  0x8A,  0x27,  0x00,  0x00, 	/* 01A10 */
+	0xBC,  0x00,  0x52,  0xFD,  0x20,  0x82,  0x08,  0x47,  0xC4,  0x08,  0x40,  0x84,  0x78,  0x48,  0xC5,  0x8A, 	/* 01A20 */
+	0x27,  0x00,  0x00,  0xBD,  0x00,  0x62,  0xF9,  0x20,  0xE2,  0x08,  0x47,  0xC4,  0x08,  0x40,  0x84,  0x78, 	/* 01A30 */
+	0x48,  0xC5,  0x8A,  0x27,  0x00,  0x00,  0xBE,  0x02,  0x00,  0x20,  0x3F,  0xC0,  0x20,  0x03,  0x83,  0xE0, 	/* 01A40 */
+	0x02,  0x01,  0xE0,  0x23,  0x82,  0x24,  0x1C,  0x00,  0x00,  0xBF,  0x00,  0x03,  0xC0,  0x04,  0x00,  0x48, 	/* 01A50 */
+	0x04,  0x81,  0xF8,  0x28,  0xC4,  0x8A,  0x50,  0x82,  0x10,  0x02,  0x00,  0x00,  0x80,  0x08,  0x00,  0x80, 	/* 01A60 */
+	0x7C,  0xC0,  0x82,  0x38,  0x04,  0x80,  0x48,  0x05,  0x04,  0x30,  0x41,  0x04,  0x0F,  0x80,  0x00,  0x81, 	/* 01A70 */
+	0x00,  0x00,  0x20,  0x27,  0x02,  0xA8,  0x32,  0x42,  0x42,  0x54,  0x24,  0x82,  0x48,  0x43,  0x08,  0x03, 	/* 01A80 */
+	0x00,  0x00,  0x82,  0x08,  0x00,  0x80,  0x3E,  0x00,  0x80,  0x11,  0x07,  0xE0,  0x10,  0x01,  0x08,  0x10, 	/* 01A90 */
+	0x80,  0x90,  0x06,  0x00,  0x00,  0x83,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0A,  0x00,  0xB8,  0x3D, 	/* 01AA0 */
+	0x40,  0x84,  0x05,  0x80,  0x40,  0x04,  0x00,  0x00,  0x84,  0x04,  0x02,  0x40,  0x23,  0x81,  0x64,  0x3A, 	/* 01AB0 */
+	0x2D,  0x04,  0x09,  0x80,  0x80,  0x08,  0x00,  0x40,  0x04,  0x00,  0x00,  0x85,  0x00,  0x00,  0x00,  0x00, 	/* 01AC0 */
+	0x00,  0x00,  0x02,  0x01,  0x38,  0x16,  0x41,  0xA4,  0x13,  0x80,  0x20,  0x04,  0x00,  0x00,  0x86,  0x02, 	/* 01AD0 */
+	0x00,  0x20,  0x47,  0x84,  0xA4,  0x52,  0x26,  0x22,  0x6A,  0x44,  0x78,  0x42,  0x00,  0x40,  0x08,  0x00, 	/* 01AE0 */
+	0x00,  0x87,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x04,  0x00,  0x70,  0x04,  0x00,  0x40,  0x1E,  0x02, 	/* 01AF0 */
+	0x58,  0x18,  0x00,  0x00,  0x88,  0x04,  0x00,  0x40,  0x04,  0x00,  0x78,  0x04,  0x00,  0x40,  0x04,  0x03, 	/* 01B00 */
+	0xC0,  0x47,  0x04,  0x4C,  0x38,  0x00,  0x00,  0x89,  0x08,  0x00,  0x60,  0x00,  0x02,  0x00,  0x20,  0x02, 	/* 01B10 */
+	0xF0,  0x30,  0x82,  0x08,  0x00,  0x80,  0x30,  0x1C,  0x00,  0x00,  0x8A,  0x01,  0x00,  0x88,  0x08,  0x81, 	/* 01B20 */
+	0x08,  0x10,  0x81,  0x08,  0x14,  0x80,  0x88,  0x00,  0x80,  0x10,  0x06,  0x00,  0x00,  0x8B,  0x00,  0x01, 	/* 01B30 */
+	0xF0,  0x02,  0x00,  0x40,  0x0F,  0x01,  0x88,  0x20,  0x44,  0x04,  0x0C,  0x81,  0x30,  0x0E,  0x00,  0x00, 	/* 01B40 */
+	0x8C,  0x10,  0x01,  0x00,  0x13,  0x01,  0x48,  0x78,  0x81,  0x08,  0x10,  0x83,  0x08,  0x30,  0x85,  0x06, 	/* 01B50 */
+	0x10,  0x00,  0x00,  0x8D,  0x00,  0x01,  0xF0,  0x02,  0x00,  0x40,  0x0F,  0x01,  0x88,  0x20,  0x44,  0x04, 	/* 01B60 */
+	0x00,  0x80,  0x10,  0x0E,  0x00,  0x00,  0x8E,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x08,  0x01,  0xC0, 	/* 01B70 */
+	0x0B,  0x80,  0xC4,  0x18,  0x42,  0x88,  0x09,  0x00,  0x00,  0x8F,  0x10,  0x01,  0x00,  0x10,  0x01,  0xB8, 	/* 01B80 */
+	0x74,  0x41,  0x82,  0x10,  0x23,  0x02,  0x50,  0x41,  0x18,  0x10,  0x00,  0x00,  0x90,  0x00,  0x01,  0xE0, 	/* 01B90 */
+	0x02,  0x00,  0x20,  0x0F,  0x81,  0x44,  0x24,  0x24,  0x82,  0x4B,  0x23,  0x4C,  0x03,  0x80,  0x00,  0x91, 	/* 01BA0 */
+	0x00,  0x01,  0xF8,  0x02,  0x00,  0xF8,  0x10,  0x42,  0x64,  0x09,  0x80,  0x60,  0x00,  0x02,  0xCC,  0x43, 	/* 01BB0 */
+	0x20,  0x00,  0x92,  0x04,  0x00,  0x40,  0x3F,  0x00,  0x80,  0x10,  0xC3,  0x90,  0x46,  0x00,  0xA0,  0x12, 	/* 01BC0 */
+	0x01,  0x00,  0x0F,  0x80,  0x00,  0x93,  0x00,  0x00,  0x40,  0x04,  0x00,  0x80,  0x08,  0x01,  0x00,  0x1C, 	/* 01BD0 */
+	0x02,  0x20,  0x22,  0x24,  0x24,  0x41,  0x80,  0x00,  0x9B,  0x20,  0x09,  0x00,  0x50,  0x04,  0x00,  0x00, 	/* 01BE0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x9C,  0x00,  0x04,  0x00,  0xA0, 	/* 01BF0 */
+	0x0A,  0x00,  0x40,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x9D,  0x00, 	/* 01C00 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x18,  0x00,  0x60,  0x01,  0x00,  0x38,  0x04,  0x00,  0x00,  0x00,  0x00, 	/* 01C10 */
+	0x00,  0x9E,  0x00,  0x00,  0x10,  0x04,  0x80,  0x20,  0x30,  0x00,  0xC0,  0x02,  0x00,  0x70,  0x08,  0x00, 	/* 01C20 */
+	0x00,  0x00,  0x00,  0x00,  0xA1,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x03,  0xF0,  0x09,  0x00, 	/* 01C30 */
+	0xE0,  0x08,  0x00,  0x80,  0x10,  0x00,  0x00,  0xA2,  0x00,  0x00,  0x00,  0xFF,  0xC0,  0x04,  0x08,  0x80, 	/* 01C40 */
+	0x90,  0x0E,  0x00,  0x80,  0x08,  0x01,  0x00,  0x20,  0x00,  0x00,  0xA3,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 01C50 */
+	0x00,  0x02,  0x00,  0x20,  0x04,  0x00,  0xC0,  0x34,  0x00,  0x40,  0x04,  0x00,  0x00,  0xA4,  0x00,  0x00, 	/* 01C60 */
+	0x08,  0x00,  0x80,  0x10,  0x02,  0x00,  0xE0,  0x32,  0x00,  0x20,  0x02,  0x00,  0x20,  0x02,  0x00,  0x00, 	/* 01C70 */
+	0xA5,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x08,  0x00,  0x80,  0x3F,  0x02,  0x10,  0x22,  0x00,  0x40, 	/* 01C80 */
+	0x18,  0x00,  0x00,  0xA6,  0x04,  0x00,  0x40,  0x04,  0x07,  0xFC,  0x40,  0x44,  0x04,  0x40,  0x80,  0x08, 	/* 01C90 */
+	0x01,  0x00,  0x60,  0x18,  0x00,  0x00,  0xA7,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 01CA0 */
+	0x1F,  0x00,  0x40,  0x04,  0x03,  0xF8,  0x00,  0x00,  0x00,  0xA8,  0x00,  0x00,  0x00,  0x00,  0x03,  0xFC, 	/* 01CB0 */
+	0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x07,  0xFE,  0x00,  0x00,  0x00,  0xA9,  0x00,  0x00,  0x00, 	/* 01CC0 */
+	0x00,  0x00,  0x00,  0x02,  0x00,  0x20,  0x3F,  0x80,  0x60,  0x0A,  0x03,  0x20,  0x06,  0x00,  0x00,  0xAA, 	/* 01CD0 */
+	0x01,  0x00,  0x10,  0x01,  0x03,  0xFE,  0x03,  0x00,  0x30,  0x05,  0x00,  0x90,  0x31,  0x00,  0x10,  0x03, 	/* 01CE0 */
+	0x00,  0x00,  0xAB,  0x04,  0x00,  0x40,  0x04,  0x03,  0xFC,  0x04,  0x40,  0x44,  0x04,  0x40,  0x84,  0x08, 	/* 01CF0 */
+	0x41,  0x04,  0x21,  0x80,  0x00,  0xAC,  0x04,  0xA0,  0x4A,  0x04,  0x03,  0xFC,  0x04,  0x40,  0x44,  0x04, 	/* 01D00 */
+	0x40,  0x84,  0x08,  0x41,  0x04,  0x21,  0x80,  0x00,  0xAD,  0x04,  0x00,  0x40,  0x07,  0x87,  0xC0,  0x04, 	/* 01D10 */
+	0x00,  0x7C,  0x7E,  0x00,  0x20,  0x02,  0x00,  0x20,  0x02,  0x00,  0x00,  0xAE,  0x04,  0xA0,  0x4A,  0x07, 	/* 01D20 */
+	0x87,  0xC0,  0x04,  0x00,  0x7C,  0x7E,  0x00,  0x20,  0x02,  0x00,  0x20,  0x02,  0x00,  0x00,  0xAF,  0x00, 	/* 01D30 */
+	0x00,  0x40,  0x07,  0xC0,  0x44,  0x08,  0x41,  0x08,  0x20,  0x80,  0x10,  0x02,  0x00,  0xC0,  0x30,  0x00, 	/* 01D40 */
+	0x00,  0xB0,  0x00,  0x50,  0x45,  0x07,  0xC0,  0x44,  0x08,  0x41,  0x08,  0x20,  0x80,  0x10,  0x02,  0x00, 	/* 01D50 */
+	0xC0,  0x30,  0x00,  0x00,  0xB1,  0x00,  0x01,  0x00,  0x10,  0x01,  0xFE,  0x11,  0x02,  0x10,  0x41,  0x00, 	/* 01D60 */
+	0x10,  0x02,  0x00,  0x40,  0x18,  0x00,  0x00,  0xB2,  0x00,  0x01,  0x05,  0x10,  0x51,  0xFC,  0x11,  0x02, 	/* 01D70 */
+	0x10,  0x41,  0x00,  0x10,  0x02,  0x00,  0x40,  0x18,  0x00,  0x00,  0xB3,  0x00,  0x00,  0x00,  0x3F,  0xC0, 	/* 01D80 */
+	0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x3F,  0xC0,  0x04,  0x00,  0x00,  0x00,  0xB4,  0x00,  0x00, 	/* 01D90 */
+	0x0A,  0x00,  0xA7,  0xF8,  0x00,  0x80,  0x08,  0x00,  0x80,  0x08,  0x00,  0x87,  0xF8,  0x00,  0x80,  0x00, 	/* 01DA0 */
+	0xB5,  0x00,  0x00,  0x88,  0x08,  0x80,  0x88,  0x7F,  0xE0,  0x88,  0x08,  0x80,  0x88,  0x01,  0x00,  0x20, 	/* 01DB0 */
+	0x0C,  0x00,  0x00,  0xB6,  0x00,  0x01,  0x15,  0x11,  0x51,  0x10,  0x7F,  0xC1,  0x10,  0x11,  0x01,  0x10, 	/* 01DC0 */
+	0x02,  0x00,  0x40,  0x18,  0x00,  0x00,  0xB7,  0x00,  0x03,  0x00,  0x08,  0x00,  0x04,  0x60,  0x41,  0x08, 	/* 01DD0 */
+	0x00,  0x80,  0x10,  0x02,  0x00,  0xC0,  0x70,  0x00,  0x00,  0xB8,  0x00,  0x03,  0x0A,  0x08,  0xA0,  0x00, 	/* 01DE0 */
+	0x60,  0x41,  0x04,  0x00,  0x80,  0x10,  0x02,  0x00,  0xC0,  0x70,  0x00,  0x00,  0xB9,  0x00,  0x00,  0x00, 	/* 01DF0 */
+	0x3F,  0x80,  0x08,  0x00,  0x80,  0x10,  0x01,  0x00,  0x28,  0x04,  0x41,  0x82,  0x60,  0x20,  0x00,  0xBA, 	/* 01E00 */
+	0x00,  0x00,  0x0A,  0x3F,  0xA0,  0x08,  0x00,  0x80,  0x10,  0x01,  0x00,  0x28,  0x04,  0x41,  0x82,  0x60, 	/* 01E10 */
+	0x20,  0x00,  0xBB,  0x00,  0x01,  0x00,  0x10,  0x01,  0x1C,  0x1E,  0x4F,  0x08,  0x11,  0x01,  0x20,  0x10, 	/* 01E20 */
+	0x01,  0x00,  0x0F,  0x80,  0x00,  0xBC,  0x00,  0x01,  0x0A,  0x10,  0xA1,  0x1C,  0x1E,  0x4F,  0x08,  0x11, 	/* 01E30 */
+	0x01,  0x20,  0x10,  0x01,  0x00,  0x0F,  0x80,  0x00,  0xBD,  0x00,  0x00,  0x00,  0x20,  0x41,  0x04,  0x10, 	/* 01E40 */
+	0x40,  0x08,  0x00,  0x80,  0x10,  0x02,  0x00,  0xC0,  0x30,  0x00,  0x00,  0xBE,  0x00,  0x00,  0x0A,  0x20, 	/* 01E50 */
+	0xA1,  0x04,  0x10,  0x40,  0x08,  0x00,  0x80,  0x10,  0x02,  0x00,  0xC0,  0x30,  0x00,  0x00,  0xBF,  0x00, 	/* 01E60 */
+	0x00,  0x40,  0x07,  0xC0,  0x84,  0x10,  0x46,  0x68,  0x01,  0x80,  0x10,  0x02,  0x00,  0xC0,  0x30,  0x00, 	/* 01E70 */
+	0x00,  0x80,  0x00,  0x00,  0x45,  0x07,  0xD0,  0x84,  0x10,  0x46,  0x68,  0x01,  0x80,  0x10,  0x02,  0x00, 	/* 01E80 */
+	0xC0,  0x30,  0x00,  0x00,  0x81,  0x00,  0x00,  0x18,  0x3E,  0x00,  0x20,  0x02,  0x07,  0xFE,  0x02,  0x00, 	/* 01E90 */
+	0x20,  0x02,  0x00,  0x40,  0x18,  0x00,  0x00,  0x82,  0x00,  0x00,  0x1D,  0x3E,  0x50,  0x20,  0x02,  0x07, 	/* 01EA0 */
+	0xFE,  0x02,  0x00,  0x20,  0x02,  0x00,  0x40,  0x18,  0x00,  0x00,  0x83,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 01EB0 */
+	0x00,  0x08,  0x02,  0x48,  0x14,  0x81,  0x10,  0x01,  0x00,  0x60,  0x18,  0x00,  0x00,  0x84,  0x00,  0x00, 	/* 01EC0 */
+	0x80,  0x44,  0x42,  0x44,  0x24,  0x42,  0x08,  0x00,  0x80,  0x10,  0x02,  0x00,  0xC0,  0x30,  0x00,  0x00, 	/* 01ED0 */
+	0x85,  0x00,  0xA0,  0x8A,  0x44,  0x02,  0x44,  0x24,  0x42,  0x08,  0x00,  0x80,  0x10,  0x02,  0x00,  0xC0, 	/* 01EE0 */
+	0x30,  0x00,  0x00,  0x86,  0x00,  0x00,  0x00,  0x1F,  0x80,  0x00,  0x00,  0x07,  0xFE,  0x02,  0x00,  0x20, 	/* 01EF0 */
+	0x04,  0x00,  0x80,  0x30,  0x00,  0x00,  0x87,  0x00,  0x00,  0x0A,  0x1F,  0xA0,  0x00,  0x00,  0x07,  0xFE, 	/* 01F00 */
+	0x02,  0x00,  0x20,  0x04,  0x00,  0x80,  0x30,  0x00,  0x00,  0x88,  0x10,  0x01,  0x00,  0x10,  0x01,  0x00, 	/* 01F10 */
+	0x1C,  0x01,  0x30,  0x10,  0x81,  0x00,  0x10,  0x01,  0x00,  0x10,  0x00,  0x00,  0x89,  0x10,  0x01,  0x14, 	/* 01F20 */
+	0x11,  0x41,  0x00,  0x1C,  0x01,  0x30,  0x10,  0x81,  0x00,  0x10,  0x01,  0x00,  0x10,  0x00,  0x00,  0x8A, 	/* 01F30 */
+	0x02,  0x00,  0x20,  0x02,  0x07,  0xFE,  0x02,  0x00,  0x20,  0x02,  0x00,  0x40,  0x04,  0x00,  0x80,  0x30, 	/* 01F40 */
+	0x00,  0x00,  0x8B,  0x00,  0x00,  0x00,  0x00,  0x01,  0xF8,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x7F, 	/* 01F50 */
+	0xE0,  0x00,  0x00,  0x00,  0x00,  0x8C,  0x00,  0x00,  0x00,  0x1F,  0xC0,  0x04,  0x00,  0x80,  0xC8,  0x03, 	/* 01F60 */
+	0x00,  0x28,  0x04,  0x41,  0x82,  0x60,  0x00,  0x00,  0x8D,  0x04,  0x00,  0x40,  0x3F,  0x80,  0x08,  0x01, 	/* 01F70 */
+	0x00,  0x60,  0x1D,  0x86,  0x46,  0x04,  0x00,  0x40,  0x04,  0x00,  0x00,  0x8E,  0x00,  0x00,  0x00,  0x00, 	/* 01F80 */
+	0x40,  0x04,  0x00,  0x80,  0x08,  0x01,  0x00,  0x20,  0x0C,  0x03,  0x00,  0x00,  0x00,  0x00,  0x8F,  0x00, 	/* 01F90 */
+	0x00,  0x00,  0x00,  0x00,  0x90,  0x08,  0x80,  0x88,  0x10,  0x41,  0x04,  0x10,  0x22,  0x02,  0x40,  0x20, 	/* 01FA0 */
+	0x00,  0x90,  0x00,  0x00,  0x05,  0x00,  0x50,  0x90,  0x08,  0x80,  0x88,  0x10,  0x41,  0x04,  0x10,  0x22, 	/* 01FB0 */
+	0x02,  0x40,  0x20,  0x00,  0x91,  0x00,  0x00,  0x06,  0x00,  0x90,  0x96,  0x08,  0x80,  0x88,  0x10,  0x41, 	/* 01FC0 */
+	0x04,  0x10,  0x22,  0x02,  0x40,  0x20,  0x00,  0x92,  0x00,  0x02,  0x00,  0x20,  0x02,  0x00,  0x21,  0x83, 	/* 01FD0 */
+	0xE0,  0x20,  0x02,  0x00,  0x20,  0x01,  0xFC,  0x00,  0x00,  0x00,  0x93,  0x00,  0x02,  0x0A,  0x20,  0xA2, 	/* 01FE0 */
+	0x00,  0x23,  0x83,  0xC0,  0x20,  0x02,  0x00,  0x20,  0x01,  0xFC,  0x00,  0x00,  0x00,  0x94,  0x00,  0x02, 	/* 01FF0 */
+	0x0C,  0x21,  0x22,  0x0C,  0x23,  0x83,  0xC0,  0x20,  0x02,  0x00,  0x20,  0x01,  0xFC,  0x00,  0x00,  0x00, 	/* 02000 */
+	0x95,  0x00,  0x00,  0x00,  0x7F,  0xC0,  0x04,  0x00,  0x40,  0x08,  0x00,  0x80,  0x10,  0x02,  0x00,  0xC0, 	/* 02010 */
+	0x30,  0x00,  0x00,  0x96,  0x01,  0x40,  0x14,  0x7F,  0x80,  0x08,  0x00,  0x80,  0x10,  0x01,  0x00,  0x20, 	/* 02020 */
+	0x04,  0x01,  0x80,  0x60,  0x00,  0x00,  0x97,  0x00,  0xC0,  0x12,  0x7F,  0xC0,  0x08,  0x00,  0x80,  0x10, 	/* 02030 */
+	0x01,  0x00,  0x20,  0x04,  0x01,  0x80,  0x60,  0x00,  0x00,  0x98,  0x00,  0x00,  0x00,  0x00,  0x00,  0xC0, 	/* 02040 */
+	0x12,  0x02,  0x10,  0x40,  0x80,  0x04,  0x00,  0x20,  0x00,  0x00,  0x00,  0x00,  0x99,  0x00,  0x00,  0x0A, 	/* 02050 */
+	0x00,  0xA0,  0xC0,  0x12,  0x02,  0x10,  0x40,  0x80,  0x04,  0x00,  0x20,  0x00,  0x00,  0x00,  0x00,  0x9A, 	/* 02060 */
+	0x00,  0x00,  0x0C,  0x01,  0x20,  0xCC,  0x12,  0x02,  0x10,  0x40,  0x80,  0x04,  0x00,  0x20,  0x00,  0x00, 	/* 02070 */
+	0x00,  0x00,  0x9B,  0x04,  0x00,  0x40,  0x04,  0x07,  0xFC,  0x04,  0x01,  0x50,  0x14,  0x82,  0x44,  0x24, 	/* 02080 */
+	0x44,  0x40,  0x0C,  0x00,  0x00,  0x9C,  0x08,  0x00,  0x94,  0x09,  0x4F,  0xF8,  0x08,  0x02,  0xA0,  0x29, 	/* 02090 */
+	0x04,  0x88,  0x48,  0x88,  0x80,  0x18,  0x00,  0x00,  0x9D,  0x08,  0x00,  0x8C,  0x09,  0x2F,  0xEC,  0x08, 	/* 020A0 */
+	0x02,  0xA0,  0x29,  0x04,  0x88,  0x48,  0x88,  0x80,  0x18,  0x00,  0x00,  0x9E,  0x00,  0x00,  0x00,  0x7F, 	/* 020B0 */
+	0xC0,  0x04,  0x00,  0x80,  0x10,  0x32,  0x00,  0xC0,  0x02,  0x00,  0x10,  0x00,  0x00,  0x00,  0x9F,  0x00, 	/* 020C0 */
+	0x01,  0xC0,  0x03,  0x00,  0x08,  0x00,  0x01,  0xC0,  0x02,  0x00,  0x00,  0x38,  0x00,  0x60,  0x01,  0x80, 	/* 020D0 */
+	0x00,  0xA0,  0x00,  0x00,  0x40,  0x04,  0x00,  0x40,  0x08,  0x00,  0xA0,  0x11,  0x01,  0x08,  0x27,  0x87, 	/* 020E0 */
+	0x84,  0x00,  0x40,  0x00,  0xA1,  0x00,  0x00,  0x04,  0x00,  0x40,  0x04,  0x0C,  0x40,  0x38,  0x00,  0x80, 	/* 020F0 */
+	0x14,  0x02,  0x20,  0xC0,  0x30,  0x00,  0x00,  0xA2,  0x00,  0x00,  0x00,  0x3F,  0x80,  0x80,  0x08,  0x07, 	/* 02100 */
+	0xFE,  0x08,  0x00,  0x80,  0x08,  0x00,  0x7C,  0x00,  0x00,  0x00,  0xA3,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 02110 */
+	0x00,  0x08,  0x00,  0x80,  0x0B,  0xC3,  0xC8,  0x05,  0x00,  0x40,  0x04,  0x00,  0x00,  0xA4,  0x00,  0x01, 	/* 02120 */
+	0x00,  0x10,  0x01,  0x1E,  0x1E,  0x4E,  0x88,  0x09,  0x00,  0x80,  0x04,  0x00,  0x40,  0x04,  0x00,  0x00, 	/* 02130 */
+	0xA5,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x1E,  0x00,  0x20,  0x02,  0x03,  0xF8, 	/* 02140 */
+	0x00,  0x00,  0x00,  0xA6,  0x00,  0x00,  0x00,  0x00,  0x03,  0xF8,  0x00,  0x80,  0x08,  0x01,  0x00,  0x10, 	/* 02150 */
+	0x01,  0x07,  0xFE,  0x00,  0x00,  0x00,  0xA7,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x03,  0xF0, 	/* 02160 */
+	0x01,  0x01,  0xF0,  0x01,  0x00,  0x10,  0x3F,  0x00,  0x00,  0xA8,  0x00,  0x00,  0x00,  0x7F,  0xC0,  0x04, 	/* 02170 */
+	0x00,  0x43,  0xFC,  0x00,  0x40,  0x04,  0x00,  0x47,  0xFC,  0x00,  0x40,  0x00,  0xA9,  0x00,  0x03,  0xF8, 	/* 02180 */
+	0x00,  0x00,  0x00,  0x7F,  0xC0,  0x04,  0x00,  0x80,  0x08,  0x01,  0x00,  0x60,  0x38,  0x00,  0x00,  0xAA, 	/* 02190 */
+	0x00,  0x01,  0x08,  0x10,  0x81,  0x08,  0x10,  0x81,  0x08,  0x10,  0x80,  0x10,  0x01,  0x00,  0x20,  0x0C, 	/* 021A0 */
+	0x00,  0x00,  0xAB,  0x00,  0x00,  0x20,  0x12,  0x01,  0x20,  0x12,  0x01,  0x22,  0x12,  0x21,  0x24,  0x22, 	/* 021B0 */
+	0x82,  0x30,  0x40,  0x00,  0x00,  0xAC,  0x00,  0x02,  0x00,  0x20,  0x02,  0x00,  0x20,  0x02,  0x00,  0x20, 	/* 021C0 */
+	0x82,  0x10,  0x22,  0x02,  0xC0,  0x30,  0x00,  0x00,  0xAD,  0x00,  0x00,  0x00,  0x3F,  0xC2,  0x04,  0x20, 	/* 021D0 */
+	0x42,  0x04,  0x20,  0x42,  0x04,  0x3F,  0xC2,  0x04,  0x00,  0x00,  0x00,  0xAE,  0x00,  0x00,  0x00,  0x00, 	/* 021E0 */
+	0x00,  0x00,  0x00,  0x03,  0xF0,  0x21,  0x02,  0x10,  0x02,  0x00,  0x40,  0x18,  0x00,  0x00,  0xAF,  0x00, 	/* 021F0 */
+	0x00,  0x00,  0x3F,  0xC2,  0x04,  0x20,  0x42,  0x04,  0x00,  0x80,  0x08,  0x01,  0x00,  0x60,  0x18,  0x00, 	/* 02200 */
+	0x00,  0xB0,  0x01,  0x00,  0x10,  0x01,  0x07,  0xFC,  0x11,  0x01,  0x10,  0x11,  0x07,  0xFE,  0x01,  0x00, 	/* 02210 */
+	0x10,  0x01,  0x00,  0x00,  0xB1,  0x00,  0x00,  0x00,  0x3F,  0x80,  0x08,  0x05,  0x00,  0x60,  0x04,  0x00, 	/* 02220 */
+	0x40,  0x04,  0x07,  0xFC,  0x00,  0x00,  0x00,  0xB2,  0x00,  0x00,  0x00,  0x3F,  0xC0,  0x04,  0x00,  0x41, 	/* 02230 */
+	0xFC,  0x00,  0x80,  0x08,  0x01,  0x00,  0x60,  0x38,  0x00,  0x00,  0xB3,  0x00,  0x00,  0x00,  0x60,  0x01, 	/* 02240 */
+	0x04,  0x00,  0x40,  0x08,  0x00,  0x80,  0x10,  0x02,  0x00,  0xC0,  0x70,  0x00,  0x00,  0xB4,  0x04,  0xA0, 	/* 02250 */
+	0x4A,  0x04,  0x07,  0xFC,  0x40,  0x44,  0x04,  0x00,  0x80,  0x08,  0x01,  0x00,  0x60,  0x18,  0x00,  0x00, 	/* 02260 */
+	0xB5,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x08,  0x00,  0x80,  0x3F,  0x00,  0x90,  0x09,  0x01,  0x10, 	/* 02270 */
+	0x26,  0x00,  0x00,  0xB6,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x08,  0x00,  0x80,  0x0F,  0x83,  0x20, 	/* 02280 */
+	0x02,  0x00,  0x40,  0x18,  0x00,  0x00,  0xBB,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x60, 	/* 02290 */
+	0x06,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xBC,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 022A0 */
+	0x00,  0x03,  0xFC,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xBD,  0x00,  0x00,  0x00, 	/* 022B0 */
+	0x00,  0x00,  0x00,  0x00,  0x03,  0x00,  0x0C,  0x00,  0x20,  0x01,  0x00,  0x00,  0x00,  0x00,  0x00,  0xBE, 	/* 022C0 */
+	0x00,  0x00,  0x00,  0x01,  0x00,  0x48,  0x02,  0x03,  0x00,  0x0C,  0x00,  0x20,  0x01,  0x00,  0x00,  0x00, 	/* 022D0 */
+	0x00,  0x00,  0x80,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x07,  0xFE,  0x00,  0x00,  0x00,  0x00, 	/* 022E0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x81,  0x00,  0x0F,  0xFE,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04, 	/* 022F0 */
+	0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0xC0,  0x83,  0x10,  0x01,  0x00,  0x10,  0x01,  0x00,  0x11, 	/* 02300 */
+	0xEF,  0xE0,  0x10,  0x01,  0x00,  0x10,  0x01,  0x04,  0x10,  0x40,  0xFC,  0x87,  0x00,  0x0F,  0xFE,  0x08, 	/* 02310 */
+	0x00,  0x80,  0x0F,  0x80,  0x88,  0x08,  0x80,  0x88,  0x10,  0x81,  0x08,  0x20,  0x84,  0x30,  0x88,  0x04, 	/* 02320 */
+	0x00,  0x40,  0x04,  0x0F,  0xFE,  0x04,  0x00,  0x40,  0x24,  0x01,  0x40,  0x0C,  0x00,  0xA0,  0x31,  0x8C, 	/* 02330 */
+	0x06,  0x89,  0x00,  0x07,  0xFC,  0x00,  0x00,  0x00,  0x00,  0x03,  0xF8,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 02340 */
+	0x00,  0xFF,  0xE0,  0x00,  0x8A,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x7C,  0x04,  0x00, 	/* 02350 */
+	0x40,  0x04,  0x00,  0x40,  0x04,  0x0F,  0xFE,  0x8B,  0x00,  0x0F,  0xFE,  0x04,  0x00,  0x40,  0x07,  0x00, 	/* 02360 */
+	0x48,  0x04,  0x40,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x8D,  0x00,  0x07,  0xFE,  0x02,  0x00, 	/* 02370 */
+	0x40,  0x06,  0x00,  0xD8,  0x34,  0x4C,  0x42,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x8E,  0x10,  0x01, 	/* 02380 */
+	0x00,  0x1F,  0xC1,  0x00,  0x1F,  0x02,  0x10,  0x01,  0x0F,  0xFE,  0x01,  0x00,  0x10,  0x01,  0x00,  0x60, 	/* 02390 */
+	0x90,  0x00,  0x0F,  0xFE,  0x04,  0x02,  0x7C,  0x24,  0x02,  0x40,  0x3F,  0xE2,  0x02,  0x00,  0x20,  0x02, 	/* 023A0 */
+	0x00,  0x40,  0x18,  0x91,  0x00,  0x03,  0xF8,  0x04,  0x80,  0x48,  0x04,  0x87,  0xFE,  0x04,  0x80,  0x88, 	/* 023B0 */
+	0x08,  0x80,  0x88,  0x08,  0x87,  0xFE,  0x94,  0x00,  0x01,  0xF8,  0x10,  0x81,  0x08,  0x1F,  0x81,  0x08, 	/* 023C0 */
+	0x10,  0x81,  0xF8,  0x10,  0x81,  0x08,  0x10,  0x87,  0xFE,  0x95,  0x00,  0x0F,  0xFE,  0x02,  0x00,  0x60, 	/* 023D0 */
+	0x0D,  0x83,  0x44,  0xC4,  0x20,  0x40,  0x04,  0x00,  0x40,  0x00,  0x0F,  0xFE,  0x96,  0x24,  0x82,  0x48, 	/* 023E0 */
+	0x24,  0x82,  0x48,  0xFF,  0xE2,  0x48,  0x24,  0x82,  0x48,  0x27,  0x82,  0x00,  0x20,  0x03,  0xFC,  0x97, 	/* 023F0 */
+	0x24,  0x82,  0x48,  0x24,  0x82,  0x48,  0x24,  0x8F,  0xFE,  0x24,  0x82,  0x48,  0x24,  0x82,  0x48,  0x24, 	/* 02400 */
+	0x83,  0xF8,  0x98,  0x00,  0x00,  0x18,  0x3E,  0x02,  0x00,  0x20,  0x03,  0xFC,  0x21,  0x02,  0x10,  0x21, 	/* 02410 */
+	0x02,  0x10,  0x21,  0x0F,  0xFE,  0x99,  0x00,  0x0F,  0xFF,  0x04,  0x00,  0x40,  0x7F,  0xE4,  0x62,  0x49, 	/* 02420 */
+	0x25,  0x0A,  0x60,  0xA4,  0x02,  0x40,  0x24,  0x06,  0x9E,  0x00,  0x03,  0xF0,  0x02,  0x00,  0x44,  0xF6, 	/* 02430 */
+	0x81,  0x70,  0x15,  0x02,  0x48,  0xC4,  0x60,  0xC0,  0x00,  0x0F,  0xFE,  0xA1,  0x00,  0x0F,  0xFE,  0x04, 	/* 02440 */
+	0x00,  0x40,  0xFF,  0xE8,  0x42,  0xA4,  0xAA,  0x4A,  0xA4,  0xAB,  0xFA,  0xA0,  0x28,  0x06,  0xA6,  0x20, 	/* 02450 */
+	0x81,  0x10,  0x12,  0x0F,  0xFE,  0x0A,  0x04,  0xA4,  0x2A,  0x42,  0xA8,  0x2B,  0x00,  0xA0,  0xFF,  0xE0, 	/* 02460 */
+	0x00,  0xAA,  0x04,  0x00,  0x40,  0x0A,  0x01,  0x10,  0x24,  0x84,  0x44,  0x84,  0x20,  0x40,  0x04,  0x00, 	/* 02470 */
+	0x40,  0x04,  0x00,  0x40,  0xAD,  0x04,  0x00,  0x40,  0x7F,  0xC4,  0x44,  0x44,  0x44,  0x44,  0x7F,  0xC0, 	/* 02480 */
+	0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0xB1,  0x09,  0x00,  0x90,  0x49,  0x24,  0x92,  0x49,  0x24, 	/* 02490 */
+	0x92,  0x49,  0x27,  0x9E,  0x49,  0x20,  0x90,  0x11,  0x02,  0x10,  0xB2,  0x04,  0x00,  0x40,  0x7F,  0xC4, 	/* 024A0 */
+	0x44,  0x7F,  0xC0,  0x40,  0xFF,  0xE8,  0x42,  0xFF,  0xE0,  0x40,  0x04,  0x00,  0x40,  0xB6,  0x00,  0x00, 	/* 024B0 */
+	0x00,  0x00,  0x01,  0x00,  0x08,  0x00,  0x40,  0x04,  0x00,  0x20,  0x02,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 024C0 */
+	0xB8,  0x10,  0x01,  0x00,  0x10,  0x0F,  0xF0,  0x11,  0x01,  0x10,  0x51,  0x03,  0x10,  0x19,  0x02,  0x52, 	/* 024D0 */
+	0x45,  0x28,  0x0E,  0xB9,  0x00,  0x03,  0xF8,  0x20,  0x82,  0x88,  0x24,  0x82,  0x48,  0xFF,  0xE2,  0x08, 	/* 024E0 */
+	0x20,  0x84,  0x08,  0x40,  0x88,  0x18,  0xBB,  0x08,  0x00,  0x40,  0x7F,  0xC0,  0x40,  0x04,  0x00,  0x40, 	/* 024F0 */
+	0x3F,  0x80,  0x40,  0x04,  0x00,  0x40,  0x04,  0x0F,  0xFE,  0xBC,  0x11,  0x01,  0x10,  0x11,  0x0F,  0xFC, 	/* 02500 */
+	0x11,  0x01,  0x50,  0x13,  0x0F,  0xFE,  0x11,  0x01,  0x10,  0x21,  0x04,  0x10,  0xBF,  0x02,  0x00,  0x20, 	/* 02510 */
+	0x02,  0x00,  0x20,  0x02,  0x00,  0x20,  0x02,  0x00,  0x20,  0x04,  0x00,  0x40,  0x08,  0x03,  0x00,  0x82, 	/* 02520 */
+	0x00,  0x81,  0x08,  0x10,  0x81,  0x08,  0x28,  0x80,  0x90,  0x05,  0x00,  0x20,  0x05,  0x00,  0x88,  0x30, 	/* 02530 */
+	0x4C,  0x03,  0x83,  0x00,  0x07,  0xF0,  0x09,  0x00,  0x90,  0x0B,  0xC0,  0x84,  0x08,  0x40,  0x84,  0x10, 	/* 02540 */
+	0x41,  0x04,  0x20,  0x44,  0x18,  0x85,  0x08,  0x00,  0x80,  0x0F,  0x01,  0x10,  0x11,  0x02,  0x20,  0x42, 	/* 02550 */
+	0x00,  0x40,  0x0A,  0x01,  0x10,  0x20,  0x8C,  0x06,  0x8B,  0x04,  0x00,  0x40,  0x3F,  0xC0,  0x04,  0x00, 	/* 02560 */
+	0x80,  0x10,  0x02,  0x02,  0x40,  0x28,  0x03,  0x00,  0x4C,  0x08,  0x3F,  0x8D,  0x20,  0x02,  0x00,  0x3F, 	/* 02570 */
+	0xE2,  0x40,  0x44,  0x04,  0x7C,  0x84,  0x00,  0x40,  0x07,  0xC0,  0x40,  0x04,  0x00,  0x40,  0x8E,  0x01, 	/* 02580 */
+	0x87,  0xE0,  0x04,  0x82,  0x48,  0x15,  0x01,  0x40,  0xFF,  0xE0,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00, 	/* 02590 */
+	0xC0,  0x8F,  0x03,  0xC7,  0xC0,  0x04,  0x00,  0x40,  0x7F,  0xC0,  0x08,  0x01,  0x04,  0x60,  0x58,  0x06, 	/* 025A0 */
+	0x00,  0x98,  0x08,  0x7E,  0x95,  0x01,  0xC7,  0xE0,  0x42,  0x07,  0xFE,  0x42,  0x07,  0xFE,  0x42,  0x05, 	/* 025B0 */
+	0xFC,  0x52,  0x49,  0x24,  0x93,  0x80,  0x20,  0x96,  0x03,  0x87,  0xC0,  0x04,  0x0F,  0xFE,  0x04,  0x01, 	/* 025C0 */
+	0x50,  0xF5,  0x61,  0x58,  0x15,  0x23,  0x52,  0xD4,  0xE0,  0x40,  0x97,  0x03,  0x83,  0xE0,  0x04,  0x0F, 	/* 025D0 */
+	0xFE,  0x24,  0x87,  0xFC,  0x24,  0x8F,  0xFE,  0x0E,  0x03,  0x58,  0xC4,  0x60,  0x40,  0x98,  0x03,  0x83, 	/* 025E0 */
+	0xC0,  0x04,  0x0F,  0xFE,  0x15,  0x07,  0x56,  0x15,  0x83,  0x52,  0xD4,  0xE0,  0xE0,  0x35,  0x8C,  0x46, 	/* 025F0 */
+	0x99,  0x00,  0x03,  0xF8,  0x00,  0x80,  0x10,  0x02,  0x00,  0x40,  0x08,  0x01,  0x00,  0x20,  0x04,  0x02, 	/* 02600 */
+	0x40,  0x23,  0xFE,  0x9D,  0x08,  0x00,  0x80,  0x08,  0x07,  0xF0,  0x09,  0x00,  0x90,  0x09,  0x00,  0x90, 	/* 02610 */
+	0x11,  0x01,  0x12,  0x21,  0x24,  0x0E,  0x9E,  0x10,  0x01,  0x00,  0x3F,  0xE2,  0x00,  0x5F,  0x88,  0x10, 	/* 02620 */
+	0x02,  0x00,  0xC0,  0x10,  0x02,  0x02,  0x20,  0x21,  0xFE,  0x9F,  0x04,  0x02,  0x40,  0x24,  0x02,  0x78, 	/* 02630 */
+	0x3C,  0x8E,  0x48,  0x24,  0x82,  0x48,  0x27,  0x02,  0x02,  0x20,  0x21,  0xFE,  0xA2,  0x22,  0x02,  0x20, 	/* 02640 */
+	0x22,  0x0A,  0xA0,  0xAA,  0x0A,  0xA0,  0xAA,  0x0A,  0xA0,  0xAA,  0x0F,  0xA2,  0x82,  0x20,  0x1E,  0xB1, 	/* 02650 */
+	0x05,  0x00,  0x90,  0x71,  0x01,  0x10,  0x11,  0x0F,  0xF0,  0x11,  0x01,  0x10,  0x7D,  0x04,  0x52,  0x45, 	/* 02660 */
+	0x27,  0xCE,  0xB3,  0x0D,  0x0F,  0x50,  0x95,  0x05,  0x90,  0x01,  0x07,  0xD0,  0x09,  0x01,  0x10,  0xFD, 	/* 02670 */
+	0x01,  0x12,  0x11,  0x23,  0x0E,  0xBE,  0x22,  0x0F,  0xA0,  0x23,  0xEF,  0xC0,  0x8B,  0xCF,  0x84,  0x88, 	/* 02680 */
+	0x8F,  0x90,  0x22,  0x0F,  0xC2,  0x24,  0x22,  0x3E,  0x80,  0x08,  0x01,  0xF0,  0x22,  0x0F,  0xF8,  0x24, 	/* 02690 */
+	0x83,  0xF8,  0x24,  0x87,  0xFC,  0x44,  0x47,  0xFC,  0x04,  0x20,  0x3E,  0x82,  0x0E,  0x8F,  0x48,  0x54, 	/* 026A0 */
+	0x89,  0x28,  0x7C,  0x82,  0x88,  0xFE,  0x8A,  0xA8,  0xFA,  0x8A,  0xA9,  0x92,  0x9A,  0xE7,  0x85,  0x04, 	/* 026B0 */
+	0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00, 	/* 026C0 */
+	0xC0,  0x86,  0x00,  0x07,  0xFC,  0x00,  0x80,  0x10,  0x06,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00, 	/* 026D0 */
+	0x40,  0x04,  0x00,  0xC0,  0x88,  0x00,  0x03,  0xF8,  0x01,  0x01,  0xA0,  0x04,  0x0F,  0xFE,  0x04,  0x40, 	/* 026E0 */
+	0x48,  0x04,  0x00,  0x40,  0x04,  0x00,  0xC0,  0x89,  0x08,  0x00,  0xF0,  0x31,  0x00,  0x20,  0x3F,  0x80, 	/* 026F0 */
+	0x48,  0xFF,  0xE0,  0x48,  0x3F,  0x80,  0x40,  0x04,  0x00,  0xC0,  0x8A,  0x04,  0x0F,  0xFE,  0x24,  0x81, 	/* 02700 */
+	0x50,  0x7F,  0xC0,  0x44,  0xFF,  0xE0,  0x44,  0x7F,  0xC0,  0x40,  0x04,  0x00,  0xC0,  0x8B,  0x04,  0x0F, 	/* 02710 */
+	0xFE,  0x24,  0x83,  0xF8,  0x04,  0x07,  0xF8,  0x04,  0x8F,  0xFE,  0x04,  0x87,  0xF8,  0x04,  0x00,  0xC0, 	/* 02720 */
+	0x8C,  0x00,  0x00,  0x00,  0x7F,  0xC0,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0F,  0xFE, 	/* 02730 */
+	0x00,  0x00,  0x00,  0x8E,  0x00,  0x07,  0xFC,  0x04,  0x00,  0x40,  0x04,  0x0F,  0xFE,  0x04,  0x00,  0x40, 	/* 02740 */
+	0x04,  0x00,  0x40,  0x04,  0x00,  0xC0,  0x91,  0x00,  0x03,  0xF8,  0x00,  0x00,  0x00,  0xFF,  0xE0,  0x40, 	/* 02750 */
+	0x04,  0x00,  0x90,  0x08,  0x81,  0x38,  0x7C,  0x40,  0x04,  0x92,  0x00,  0x07,  0xFC,  0x10,  0x01,  0x00, 	/* 02760 */
+	0x1F,  0x01,  0x10,  0x21,  0x02,  0x10,  0x7E,  0x00,  0x20,  0x02,  0x0F,  0xFE,  0x94,  0x00,  0x03,  0xFC, 	/* 02770 */
+	0x04,  0x00,  0x40,  0x04,  0x03,  0xF8,  0x04,  0x80,  0x48,  0x08,  0x80,  0x88,  0x08,  0x87,  0xFE,  0x95, 	/* 02780 */
+	0x08,  0x80,  0x88,  0x08,  0x87,  0xFE,  0x08,  0x80,  0x88,  0x08,  0x87,  0xFE,  0x08,  0x80,  0x88,  0x10, 	/* 02790 */
+	0x82,  0x08,  0x98,  0x00,  0x07,  0xFC,  0x00,  0x03,  0xF8,  0x20,  0x82,  0x08,  0x3F,  0x82,  0x08,  0x20, 	/* 027A0 */
+	0x83,  0xF8,  0x00,  0x0F,  0xFE,  0x99,  0x00,  0x0F,  0xFE,  0x10,  0x01,  0x00,  0x1F,  0x01,  0x90,  0x25, 	/* 027B0 */
+	0x03,  0x10,  0x4A,  0x04,  0xA0,  0x02,  0x0F,  0xFE,  0x9B,  0x12,  0x05,  0x20,  0x5A,  0x45,  0x38,  0x52, 	/* 027C0 */
+	0x25,  0xE2,  0xF1,  0xE0,  0x00,  0x3F,  0x80,  0x00,  0x00,  0x0F,  0xFE,  0x9C,  0x00,  0x07,  0xFE,  0x09, 	/* 027D0 */
+	0x00,  0x90,  0x3F,  0xC2,  0x94,  0x29,  0x42,  0x94,  0x3F,  0xC0,  0x90,  0x09,  0x07,  0xFE,  0x9E,  0x00, 	/* 027E0 */
+	0x0F,  0xFE,  0x09,  0x00,  0x90,  0x79,  0xE4,  0x02,  0x40,  0x27,  0x9E,  0x09,  0x00,  0x90,  0x09,  0x0F, 	/* 027F0 */
+	0xFE,  0x9F,  0x00,  0x07,  0xFC,  0x04,  0x00,  0x80,  0x1F,  0xEF,  0x32,  0x92,  0xA9,  0x2C,  0x93,  0x4F, 	/* 02800 */
+	0x22,  0x0C,  0x0F,  0xFE,  0xA0,  0x00,  0x00,  0x00,  0x00,  0x00,  0x40,  0x04,  0x00,  0x40,  0xFF,  0xE0, 	/* 02810 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xA1,  0x04,  0x00,  0x40,  0x04,  0x0F,  0xFE,  0x20,  0x02, 	/* 02820 */
+	0x00,  0x20,  0x02,  0x00,  0x20,  0x02,  0x00,  0x1F,  0xC0,  0x00,  0xA2,  0x04,  0x00,  0x40,  0xFF,  0xE0, 	/* 02830 */
+	0x00,  0x1E,  0x01,  0x20,  0x12,  0x01,  0x20,  0x12,  0x02,  0x22,  0x22,  0x24,  0x1E,  0xA4,  0x04,  0x00, 	/* 02840 */
+	0x40,  0xFF,  0xE1,  0x10,  0x10,  0x82,  0x14,  0x51,  0x00,  0xA0,  0x04,  0x00,  0xA0,  0x31,  0x8C,  0x06, 	/* 02850 */
+	0xA5,  0x04,  0x0F,  0xFE,  0x08,  0x00,  0xA0,  0x72,  0x01,  0x40,  0x0C,  0x81,  0x90,  0x62,  0x00,  0xD0, 	/* 02860 */
+	0x30,  0x8C,  0x04,  0xA6,  0x04,  0x00,  0x40,  0x7F,  0xE0,  0x90,  0x09,  0x02,  0x94,  0x29,  0x24,  0x92, 	/* 02870 */
+	0x89,  0x21,  0x10,  0x11,  0x02,  0x30,  0xA8,  0x04,  0x0F,  0xFE,  0x3F,  0x82,  0x08,  0x3F,  0x80,  0x00, 	/* 02880 */
+	0x7F,  0xC0,  0x10,  0x06,  0x00,  0x40,  0x04,  0x00,  0xC0,  0xAB,  0x04,  0x0F,  0xFE,  0x3F,  0x82,  0x08, 	/* 02890 */
+	0x3F,  0x80,  0x00,  0x3F,  0x80,  0x20,  0xFF,  0xE0,  0x40,  0x04,  0x00,  0xC0,  0xAC,  0x04,  0x0F,  0xFE, 	/* 028A0 */
+	0x00,  0x03,  0xF8,  0x20,  0x82,  0x08,  0x3F,  0x80,  0x40,  0x24,  0x82,  0x44,  0x44,  0x40,  0xC0,  0xAD, 	/* 028B0 */
+	0x04,  0x0F,  0xFE,  0x00,  0x03,  0xF8,  0x20,  0x8F,  0xFE,  0x80,  0x27,  0xFC,  0x04,  0x00,  0x40,  0x04, 	/* 028C0 */
+	0x00,  0xC0,  0xAE,  0x04,  0x0F,  0xFE,  0x00,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x00,  0x0F,  0xFE,  0x8A, 	/* 028D0 */
+	0x20,  0xA0,  0x12,  0x26,  0x1E,  0xB0,  0x04,  0x0F,  0xFE,  0x00,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20, 	/* 028E0 */
+	0x83,  0xF8,  0x05,  0x02,  0x48,  0x44,  0x40,  0xC0,  0xB3,  0x04,  0x0F,  0xFE,  0x00,  0x03,  0xF8,  0x20, 	/* 028F0 */
+	0x8F,  0xFE,  0x83,  0x23,  0xC0,  0x07,  0xC7,  0xC0,  0x04,  0x20,  0x3E,  0xB6,  0x04,  0x0F,  0xFE,  0x2E, 	/* 02900 */
+	0x82,  0xA8,  0x2E,  0x83,  0xF8,  0x00,  0x01,  0xF0,  0x11,  0x01,  0xF0,  0x11,  0x0F,  0xFE,  0xBA,  0x04, 	/* 02910 */
+	0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x0A,  0x00,  0xA0,  0x11,  0x02,  0x08,  0x40,  0x48, 	/* 02920 */
+	0x02,  0x80,  0x11,  0x01,  0x10,  0x11,  0x02,  0x10,  0x3F,  0xE6,  0x10,  0xA1,  0x02,  0x10,  0x21,  0x02, 	/* 02930 */
+	0x10,  0x21,  0x02,  0x10,  0x81,  0x10,  0x01,  0x00,  0x27,  0xC2,  0x00,  0x60,  0x0A,  0x00,  0x20,  0x02, 	/* 02940 */
+	0x00,  0x20,  0x02,  0x00,  0x2F,  0xE2,  0x00,  0x82,  0x12,  0x01,  0x20,  0x12,  0x02,  0xFE,  0x22,  0x26, 	/* 02950 */
+	0x22,  0xA2,  0x22,  0x22,  0x22,  0x22,  0x42,  0x24,  0x22,  0x8C,  0x84,  0x00,  0x03,  0xFE,  0x22,  0x02, 	/* 02960 */
+	0x20,  0x22,  0x02,  0x20,  0x22,  0x02,  0x50,  0x45,  0x04,  0x88,  0x90,  0x42,  0x02,  0x86,  0x11,  0x01, 	/* 02970 */
+	0x10,  0x11,  0x02,  0x10,  0x21,  0x86,  0x14,  0xA1,  0x22,  0x12,  0x21,  0x02,  0x10,  0x21,  0x02,  0x10, 	/* 02980 */
+	0x87,  0x24,  0x02,  0x40,  0x24,  0x05,  0xF8,  0x44,  0x8C,  0x48,  0x44,  0x84,  0x48,  0x48,  0x84,  0x8A, 	/* 02990 */
+	0x50,  0xA6,  0x06,  0x8A,  0x04,  0x00,  0x40,  0x0A,  0x01,  0x10,  0x3F,  0x8C,  0x06,  0x00,  0x03,  0xF8, 	/* 029A0 */
+	0x01,  0x00,  0x20,  0x02,  0x00,  0x40,  0x8B,  0x04,  0x00,  0x40,  0x0A,  0x01,  0x10,  0x20,  0x8D,  0x16, 	/* 029B0 */
+	0x11,  0x01,  0x10,  0x11,  0x02,  0x10,  0x21,  0x04,  0x10,  0x8D,  0x10,  0x01,  0xF8,  0x14,  0x82,  0x48, 	/* 029C0 */
+	0x24,  0x86,  0x4E,  0xA4,  0xA2,  0x42,  0x24,  0x22,  0x82,  0x28,  0x23,  0x0C,  0x8E,  0x10,  0x81,  0x08, 	/* 029D0 */
+	0x10,  0x81,  0x08,  0x10,  0x81,  0x08,  0x10,  0x82,  0x94,  0x29,  0x44,  0x62,  0x42,  0x28,  0x41,  0x8F, 	/* 029E0 */
+	0x12,  0x01,  0x20,  0x12,  0x02,  0x20,  0x22,  0x06,  0x20,  0xA4,  0x82,  0x44,  0x24,  0x42,  0x9E,  0x3E, 	/* 029F0 */
+	0x22,  0x02,  0x94,  0x10,  0x01,  0xFC,  0x10,  0x42,  0x08,  0x21,  0x06,  0x10,  0xBF,  0xE2,  0x10,  0x21, 	/* 02A00 */
+	0x02,  0x10,  0x21,  0x02,  0x30,  0x95,  0x11,  0x01,  0x10,  0x11,  0x02,  0x10,  0x3F,  0xF6,  0x10,  0xA1, 	/* 02A10 */
+	0x02,  0x10,  0x21,  0x02,  0x10,  0x2F,  0xC2,  0x00,  0x96,  0x11,  0x01,  0x50,  0x25,  0x02,  0x5C,  0x67, 	/* 02A20 */
+	0x4B,  0xD4,  0x25,  0x42,  0x54,  0x25,  0x82,  0x42,  0x24,  0x22,  0x3E,  0x97,  0x21,  0x02,  0x10,  0x21, 	/* 02A30 */
+	0x05,  0xFE,  0x41,  0x0C,  0x90,  0x49,  0x05,  0x50,  0x42,  0x04,  0x50,  0x48,  0x85,  0x06,  0x98,  0x10, 	/* 02A40 */
+	0x81,  0x08,  0x10,  0x82,  0xFE,  0x20,  0x86,  0x88,  0xA4,  0x82,  0x48,  0x20,  0x82,  0x08,  0x20,  0x82, 	/* 02A50 */
+	0x18,  0x99,  0x11,  0x01,  0x10,  0x11,  0x02,  0x92,  0x29,  0x26,  0x92,  0xA9,  0x22,  0x92,  0x29,  0x22, 	/* 02A60 */
+	0x92,  0x2F,  0xE2,  0x82,  0x9D,  0x04,  0x00,  0x40,  0x0A,  0x01,  0x10,  0x20,  0x8C,  0x06,  0x3F,  0x80, 	/* 02A70 */
+	0x40,  0x04,  0x00,  0x40,  0x04,  0x0F,  0xFE,  0x9E,  0x10,  0x01,  0xFE,  0x12,  0x22,  0x22,  0x22,  0x26, 	/* 02A80 */
+	0xA2,  0xAA,  0x23,  0x22,  0x22,  0x22,  0x42,  0x24,  0x22,  0x8C,  0x9F,  0x10,  0xC1,  0xF0,  0x11,  0x02, 	/* 02A90 */
+	0x10,  0x21,  0x07,  0xFE,  0xA1,  0x02,  0x10,  0x21,  0x02,  0x10,  0x21,  0x02,  0x10,  0xA3,  0x12,  0x81, 	/* 02AA0 */
+	0x24,  0x12,  0x02,  0x3E,  0x3E,  0x06,  0x10,  0xA1,  0x02,  0x10,  0x20,  0x82,  0x0A,  0x20,  0x62,  0x02, 	/* 02AB0 */
+	0xA4,  0x04,  0x00,  0x40,  0x0A,  0x01,  0x10,  0x3F,  0x8C,  0x06,  0x3F,  0xC0,  0x44,  0x04,  0x40,  0x58, 	/* 02AC0 */
+	0x04,  0x00,  0x40,  0xA5,  0x20,  0x42,  0x04,  0x28,  0x42,  0x44,  0x24,  0x42,  0x24,  0x20,  0x42,  0x84, 	/* 02AD0 */
+	0x30,  0xC4,  0x0A,  0x83,  0x10,  0xC0,  0xAD,  0x10,  0x01,  0xFE,  0x12,  0x22,  0x22,  0x2A,  0x26,  0x62, 	/* 02AE0 */
+	0xA3,  0x22,  0x2E,  0x22,  0x32,  0x42,  0x24,  0x22,  0x8C,  0xAE,  0x10,  0x01,  0x7E,  0x14,  0x02,  0x40, 	/* 02AF0 */
+	0x27,  0xC6,  0x64,  0xA5,  0x42,  0x58,  0x28,  0x82,  0x98,  0x32,  0x42,  0xC2,  0xB0,  0x23,  0x02,  0xC0, 	/* 02B00 */
+	0x29,  0xE4,  0x92,  0x49,  0x2C,  0x92,  0x49,  0x24,  0x92,  0x4B,  0x25,  0xDC,  0x41,  0x04,  0x10,  0xB2, 	/* 02B10 */
+	0x11,  0x01,  0x10,  0x1F,  0xE2,  0x92,  0x29,  0x26,  0x92,  0xAF,  0xE2,  0x10,  0x21,  0x02,  0x10,  0x21, 	/* 02B20 */
+	0x02,  0x10,  0xB6,  0x11,  0x01,  0x50,  0x15,  0x02,  0xFC,  0x29,  0x07,  0x10,  0xBF,  0xE2,  0x10,  0x21, 	/* 02B30 */
+	0x02,  0x10,  0x21,  0x02,  0x10,  0xB7,  0x12,  0x01,  0x20,  0x15,  0x02,  0x88,  0x30,  0x46,  0x4A,  0xA4, 	/* 02B40 */
+	0x92,  0x48,  0x24,  0x82,  0x88,  0x28,  0x83,  0x08,  0xBB,  0x10,  0xC1,  0xF0,  0x11,  0x02,  0x10,  0x21, 	/* 02B50 */
+	0x07,  0xFF,  0xA1,  0x02,  0x10,  0x21,  0x02,  0x10,  0x2F,  0xE2,  0x00,  0x81,  0x04,  0x00,  0x40,  0x0A, 	/* 02B60 */
+	0x01,  0x10,  0x24,  0x8C,  0x46,  0x04,  0x02,  0x78,  0x24,  0x02,  0x40,  0x24,  0x0F,  0xFE,  0x89,  0x22, 	/* 02B70 */
+	0x02,  0x20,  0x3F,  0xE4,  0x00,  0x4F,  0x0C,  0x90,  0x49,  0x04,  0x90,  0x49,  0x05,  0x12,  0x51,  0x26, 	/* 02B80 */
+	0x0E,  0x8A,  0x10,  0x01,  0xFC,  0x12,  0x42,  0x24,  0x7F,  0xEA,  0x24,  0x22,  0x42,  0xFC,  0x22,  0x02, 	/* 02B90 */
+	0x20,  0x24,  0x02,  0x80,  0x8D,  0x10,  0x01,  0xFE,  0x12,  0x02,  0x20,  0x22,  0x06,  0xF8,  0xA2,  0x82, 	/* 02BA0 */
+	0x48,  0x24,  0x82,  0x48,  0x24,  0x83,  0xFE,  0x8E,  0x11,  0x01,  0x10,  0x1F,  0xE2,  0x10,  0x21,  0x06, 	/* 02BB0 */
+	0xFE,  0xA0,  0x42,  0x44,  0x22,  0x82,  0x10,  0x26,  0x83,  0x86,  0x8F,  0x12,  0x01,  0x28,  0x12,  0x42, 	/* 02BC0 */
+	0x20,  0x3F,  0xE6,  0x20,  0xA2,  0x02,  0x50,  0x25,  0x02,  0x88,  0x30,  0x42,  0x02,  0x90,  0x12,  0x81, 	/* 02BD0 */
+	0x24,  0x12,  0x02,  0x3C,  0x3E,  0x06,  0x28,  0xA2,  0x82,  0x10,  0x23,  0x02,  0x4A,  0x38,  0x62,  0x02, 	/* 02BE0 */
+	0x91,  0x11,  0x01,  0x10,  0x11,  0x03,  0xFE,  0x21,  0x06,  0x38,  0xA3,  0x82,  0x54,  0x29,  0x23,  0x11, 	/* 02BF0 */
+	0x21,  0x02,  0x10,  0x9A,  0x04,  0x00,  0x40,  0x0A,  0x01,  0x10,  0x3F,  0x8C,  0x06,  0x00,  0x07,  0xFC, 	/* 02C00 */
+	0x0A,  0x01,  0x30,  0x7C,  0x80,  0x08,  0x9C,  0x22,  0x02,  0x20,  0x2F,  0x84,  0x28,  0x44,  0xAC,  0xA6, 	/* 02C10 */
+	0x52,  0x05,  0xFE,  0x42,  0x04,  0x20,  0x42,  0x04,  0x20,  0x9D,  0x10,  0x01,  0x7C,  0x10,  0x02,  0x00, 	/* 02C20 */
+	0x2F,  0xE6,  0x20,  0xA2,  0x02,  0x28,  0x24,  0x42,  0x5C,  0x2E,  0x22,  0x02,  0xAF,  0x11,  0x01,  0x10, 	/* 02C30 */
+	0x22,  0x02,  0x7E,  0x64,  0x2A,  0x42,  0x27,  0xE2,  0x42,  0x24,  0x22,  0x42,  0x24,  0x22,  0x7E,  0xB0, 	/* 02C40 */
+	0x11,  0x01,  0x10,  0x1F,  0xE2,  0x10,  0x21,  0x06,  0x10,  0xA7,  0xC2,  0x44,  0x24,  0x42,  0x44,  0x24, 	/* 02C50 */
+	0x42,  0x7C,  0xB4,  0x22,  0x03,  0x24,  0x2A,  0x44,  0xA8,  0x5F,  0xCC,  0x20,  0x42,  0x05,  0xFE,  0x42, 	/* 02C60 */
+	0x04,  0x20,  0x42,  0x04,  0x20,  0xB6,  0x12,  0x01,  0x20,  0x25,  0x02,  0x48,  0x6F,  0xCB,  0x02,  0x2F, 	/* 02C70 */
+	0xC2,  0x24,  0x22,  0x42,  0x38,  0x22,  0x02,  0x20,  0xB8,  0x11,  0x01,  0x10,  0x1F,  0xE2,  0x92,  0x2F, 	/* 02C80 */
+	0xE6,  0x92,  0xA9,  0x22,  0xFE,  0x21,  0x02,  0x10,  0x21,  0x02,  0x10,  0xBA,  0x10,  0x01,  0xFE,  0x10, 	/* 02C90 */
+	0x22,  0xFA,  0x20,  0x26,  0xF2,  0xA9,  0x22,  0x92,  0x2F,  0x22,  0x02,  0x20,  0x22,  0x06,  0xBC,  0x20, 	/* 02CA0 */
+	0x42,  0x84,  0x28,  0x44,  0xA4,  0x49,  0x4C,  0x84,  0x48,  0x44,  0x84,  0x4A,  0xC4,  0xCA,  0x71,  0x14, 	/* 02CB0 */
+	0x20,  0xBD,  0x28,  0x02,  0x80,  0x28,  0xE5,  0xEA,  0x4A,  0xAC,  0xAA,  0x4A,  0xA4,  0xAA,  0x52,  0xA5, 	/* 02CC0 */
+	0x2A,  0x62,  0xE4,  0xC0,  0x83,  0x10,  0x01,  0x7E,  0x25,  0x22,  0x52,  0x65,  0x2A,  0x7E,  0x25,  0x22, 	/* 02CD0 */
+	0x52,  0x25,  0x22,  0x52,  0x27,  0xE2,  0x00,  0x86,  0x10,  0x01,  0x7C,  0x14,  0x42,  0x44,  0x27,  0xC6, 	/* 02CE0 */
+	0x44,  0xA4,  0x42,  0x44,  0x27,  0xC2,  0x00,  0x20,  0x02,  0xFF,  0x87,  0x11,  0x01,  0xFE,  0x18,  0x22, 	/* 02CF0 */
+	0x00,  0x3F,  0xE6,  0x10,  0xA1,  0x02,  0x10,  0x21,  0x02,  0x10,  0x21,  0x02,  0x30,  0x8D,  0x11,  0x01, 	/* 02D00 */
+	0x10,  0x11,  0x02,  0xFE,  0x20,  0x46,  0x84,  0xA4,  0x42,  0x44,  0x24,  0x82,  0x48,  0x21,  0x03,  0xFE, 	/* 02D10 */
+	0x8E,  0x10,  0xC1,  0xF0,  0x19,  0x02,  0x90,  0x2F,  0xE6,  0x90,  0xA9,  0x02,  0x88,  0x2E,  0x83,  0x0A, 	/* 02D20 */
+	0x20,  0x62,  0xFA,  0x8F,  0x12,  0x01,  0x10,  0x1F,  0xE2,  0x10,  0x21,  0x06,  0x10,  0xA7,  0xC2,  0x10, 	/* 02D30 */
+	0x21,  0x02,  0x10,  0x21,  0x02,  0xFE,  0x90,  0x22,  0x02,  0x20,  0x22,  0x05,  0xFE,  0x42,  0x0C,  0x40, 	/* 02D40 */
+	0x47,  0xE4,  0x90,  0x51,  0x04,  0x10,  0x4F,  0xE4,  0x00,  0x91,  0x22,  0x02,  0x20,  0x22,  0x07,  0xFE, 	/* 02D50 */
+	0x42,  0x0C,  0x40,  0x44,  0x04,  0xFC,  0x54,  0x46,  0x44,  0x44,  0x44,  0x7C,  0x93,  0x11,  0x01,  0x10, 	/* 02D60 */
+	0x11,  0x03,  0xFE,  0x21,  0x06,  0x38,  0xA3,  0x82,  0x54,  0x29,  0x23,  0x7D,  0x21,  0x02,  0x10,  0x95, 	/* 02D70 */
+	0x10,  0x01,  0xFF,  0x10,  0x42,  0x04,  0x2F,  0x46,  0x94,  0xA9,  0x42,  0x94,  0x2F,  0x42,  0x04,  0x20, 	/* 02D80 */
+	0x42,  0x0C,  0x97,  0x12,  0x01,  0xFE,  0x18,  0x22,  0x82,  0x24,  0x06,  0x4C,  0xA7,  0x02,  0x40,  0x24, 	/* 02D90 */
+	0x02,  0x42,  0x24,  0x22,  0x3E,  0x99,  0x04,  0x00,  0x40,  0x0A,  0x03,  0x18,  0xDF,  0x60,  0x40,  0x7F, 	/* 02DA0 */
+	0xC0,  0x40,  0x24,  0x82,  0x44,  0x44,  0x40,  0xC0,  0x9A,  0x22,  0x02,  0xA0,  0x2A,  0x04,  0xFC,  0x52, 	/* 02DB0 */
+	0x0C,  0x20,  0x5F,  0xE4,  0x20,  0x45,  0x04,  0x50,  0x48,  0x85,  0x04,  0x9B,  0x25,  0x02,  0x50,  0x2F, 	/* 02DC0 */
+	0xC4,  0x54,  0x5F,  0xCD,  0x50,  0x5F,  0xE4,  0x52,  0x45,  0x24,  0x94,  0x49,  0x05,  0x10,  0x9C,  0x12, 	/* 02DD0 */
+	0x01,  0x20,  0x13,  0xE2,  0x50,  0x25,  0x06,  0x9E,  0xA1,  0x02,  0x10,  0x21,  0xE2,  0x10,  0x21,  0x02, 	/* 02DE0 */
+	0x10,  0x9D,  0x12,  0x01,  0x20,  0x17,  0xE2,  0x42,  0x28,  0x27,  0xF2,  0xA9,  0x22,  0x92,  0x2F,  0x22, 	/* 02DF0 */
+	0x02,  0x20,  0x22,  0x0C,  0x9E,  0x2F,  0xC2,  0x00,  0x2F,  0xE4,  0x20,  0x42,  0x0D,  0xFE,  0x44,  0x84, 	/* 02E00 */
+	0x48,  0x4F,  0x04,  0x18,  0x42,  0x45,  0xC2,  0xA9,  0x20,  0x03,  0xFC,  0x30,  0x45,  0xFC,  0x52,  0x4D, 	/* 02E10 */
+	0x24,  0x5F,  0xC5,  0xAC,  0x5A,  0xC6,  0xB5,  0x62,  0x34,  0x21,  0xAF,  0x14,  0x41,  0x28,  0x1F,  0xE2, 	/* 02E20 */
+	0x10,  0x21,  0x06,  0xFC,  0xA1,  0x02,  0x10,  0x3F,  0xE2,  0x10,  0x21,  0x02,  0x10,  0xB0,  0x10,  0x01, 	/* 02E30 */
+	0xFE,  0x11,  0x02,  0x20,  0x2F,  0xC6,  0x84,  0xA8,  0x42,  0xFC,  0x28,  0x42,  0x84,  0x28,  0x42,  0xFC, 	/* 02E40 */
+	0xB3,  0x22,  0x02,  0x20,  0x3F,  0xC4,  0x20,  0x42,  0x0D,  0xFE,  0x42,  0x04,  0x20,  0x5F,  0xC4,  0x20, 	/* 02E50 */
+	0x42,  0x07,  0xFE,  0xB5,  0x18,  0x41,  0x44,  0x24,  0x82,  0xFE,  0x64,  0x8A,  0x48,  0x3F,  0xF2,  0x48, 	/* 02E60 */
+	0x24,  0x82,  0x88,  0x28,  0x83,  0x08,  0xB6,  0x11,  0x01,  0x10,  0x1F,  0xE2,  0x10,  0x21,  0x06,  0xFC, 	/* 02E70 */
+	0xA0,  0x02,  0xFC,  0x28,  0x42,  0x84,  0x28,  0x42,  0xFC,  0xBB,  0x25,  0x02,  0x50,  0x25,  0x45,  0x54, 	/* 02E80 */
+	0x4D,  0x8C,  0x50,  0x4D,  0x85,  0x54,  0x45,  0x04,  0x92,  0x49,  0x25,  0x0E,  0xBC,  0x11,  0x01,  0x10, 	/* 02E90 */
+	0x1F,  0xE2,  0x28,  0x24,  0x46,  0xCA,  0xA4,  0x82,  0x28,  0x21,  0x02,  0x28,  0x24,  0x43,  0x82,  0xBF, 	/* 02EA0 */
+	0x11,  0x01,  0xFE,  0x11,  0x02,  0xFE,  0x29,  0x26,  0x92,  0xAF,  0xE2,  0x90,  0x25,  0x02,  0x30,  0x24, 	/* 02EB0 */
+	0x83,  0x86,  0x83,  0x10,  0x01,  0xFC,  0x18,  0x42,  0x84,  0x28,  0x46,  0xFC,  0xA0,  0x02,  0xA8,  0x2A, 	/* 02EC0 */
+	0x82,  0xAA,  0x32,  0xA2,  0x06,  0x86,  0x04,  0x00,  0x40,  0xFF,  0xE2,  0x48,  0x24,  0x83,  0x58,  0x4E, 	/* 02ED0 */
+	0x48,  0x42,  0x0E,  0x03,  0x58,  0xC4,  0x60,  0x40,  0x88,  0x12,  0x01,  0x3C,  0x14,  0x43,  0xA8,  0x21, 	/* 02EE0 */
+	0x06,  0x68,  0xB9,  0xE2,  0x22,  0x2D,  0x42,  0x08,  0x23,  0x02,  0xC0,  0x8B,  0x20,  0x23,  0xFA,  0x28, 	/* 02EF0 */
+	0xA4,  0x8A,  0x5E,  0xAD,  0x2A,  0x5A,  0xA6,  0x4A,  0x44,  0xA4,  0x82,  0x50,  0x26,  0x06,  0x8D,  0x12, 	/* 02F00 */
+	0x01,  0xFC,  0x12,  0x02,  0x20,  0x3F,  0xE6,  0x08,  0xBF,  0xE2,  0x88,  0x24,  0x82,  0x08,  0x20,  0x82, 	/* 02F10 */
+	0x18,  0x8F,  0x21,  0x02,  0x90,  0x2F,  0xE4,  0x90,  0x51,  0x0D,  0xFF,  0x41,  0x04,  0x38,  0x45,  0x45, 	/* 02F20 */
+	0x93,  0x41,  0x04,  0x10,  0x91,  0x12,  0x01,  0x20,  0x1F,  0xE2,  0x20,  0x27,  0xC6,  0x44,  0xAF,  0xC3, 	/* 02F30 */
+	0x44,  0x27,  0xC2,  0x44,  0x24,  0x42,  0x4C,  0x96,  0x04,  0x00,  0xA0,  0x31,  0x8D,  0xF6,  0x00,  0x07, 	/* 02F40 */
+	0xFC,  0x4A,  0x44,  0xA4,  0x7F,  0xC4,  0xA4,  0x4A,  0x44,  0xAC,  0x98,  0x22,  0x03,  0xFE,  0x30,  0x25, 	/* 02F50 */
+	0x0A,  0x43,  0x0C,  0xE0,  0x42,  0x04,  0x3E,  0x5E,  0x04,  0x20,  0x42,  0x24,  0x1E,  0x9B,  0x12,  0x41, 	/* 02F60 */
+	0x24,  0x12,  0x42,  0xFE,  0x22,  0x46,  0x24,  0xA2,  0x43,  0xFF,  0x20,  0x02,  0x24,  0x24,  0x22,  0x82, 	/* 02F70 */
+	0x9D,  0x11,  0x01,  0x10,  0x1F,  0xE2,  0x10,  0x22,  0x26,  0x54,  0xAD,  0x83,  0x50,  0x24,  0x82,  0x48, 	/* 02F80 */
+	0x27,  0x42,  0xC2,  0xA0,  0x22,  0x02,  0x20,  0x3F,  0xC5,  0x24,  0x4A,  0x8C,  0xA0,  0x7F,  0xE4,  0x20, 	/* 02F90 */
+	0x43,  0x04,  0x48,  0x48,  0x47,  0x02,  0xA1,  0x10,  0x01,  0xFE,  0x12,  0x82,  0x28,  0x2F,  0xE6,  0xAA, 	/* 02FA0 */
+	0xAA,  0xA2,  0xAA,  0x2A,  0xA2,  0xAA,  0x2F,  0xE2,  0x80,  0xAB,  0x21,  0x02,  0x10,  0x2F,  0xE4,  0x80, 	/* 02FB0 */
+	0x48,  0x0C,  0x7C,  0x44,  0x05,  0xFE,  0x44,  0x84,  0xE8,  0x43,  0x84,  0xC4,  0xAD,  0x20,  0x02,  0xFE, 	/* 02FC0 */
+	0x28,  0x24,  0xFE,  0x48,  0x8C,  0x88,  0x4B,  0x44,  0x8C,  0x50,  0x25,  0x61,  0x61,  0x04,  0x08,  0xAE, 	/* 02FD0 */
+	0x28,  0x02,  0xFE,  0x28,  0x05,  0x7C,  0x55,  0x4C,  0x54,  0x5F,  0xE4,  0x94,  0x49,  0x45,  0xFE,  0x50, 	/* 02FE0 */
+	0x44,  0x18,  0xAF,  0x10,  0x01,  0x7C,  0x10,  0x42,  0xFE,  0x24,  0x06,  0x7E,  0xA9,  0x03,  0x10,  0x2F, 	/* 02FF0 */
+	0xE2,  0x28,  0x24,  0x43,  0x82,  0xB5,  0x17,  0xC1,  0x04,  0x17,  0xC2,  0x04,  0x3F,  0xF7,  0x01,  0xB7, 	/* 03000 */
+	0xD2,  0x04,  0x26,  0x82,  0x10,  0x22,  0x82,  0xC6,  0xB6,  0x10,  0x01,  0x7C,  0x14,  0x42,  0x44,  0x27, 	/* 03010 */
+	0xC6,  0x20,  0xA4,  0x02,  0xFE,  0x28,  0x22,  0x82,  0x28,  0x22,  0xFE,  0xBF,  0x10,  0x01,  0xFE,  0x11, 	/* 03020 */
+	0x02,  0xFE,  0x29,  0x26,  0xFE,  0xA9,  0x22,  0xFE,  0x25,  0x02,  0x30,  0x24,  0x83,  0x86,  0x82,  0x10, 	/* 03030 */
+	0xC1,  0xF0,  0x12,  0x42,  0xC8,  0x23,  0x06,  0x24,  0xAF,  0xA2,  0x10,  0x25,  0x42,  0x52,  0x29,  0x22, 	/* 03040 */
+	0x10,  0x83,  0x20,  0x02,  0xFC,  0x28,  0x44,  0x84,  0x4F,  0xCC,  0x10,  0x49,  0x04,  0x9E,  0x49,  0x04, 	/* 03050 */
+	0xD0,  0x53,  0x06,  0x0E,  0x84,  0x25,  0x03,  0x94,  0x29,  0x22,  0x90,  0x7F,  0xE4,  0x90,  0xCD,  0x44, 	/* 03060 */
+	0x94,  0x58,  0x86,  0x9A,  0x4A,  0x65,  0x82,  0x8A,  0x11,  0x01,  0x24,  0x1F,  0xA2,  0x28,  0x22,  0xA6, 	/* 03070 */
+	0x4E,  0xAA,  0x02,  0x3C,  0x26,  0x42,  0x98,  0x26,  0xC3,  0x82,  0x8E,  0x27,  0xC2,  0x44,  0x24,  0x45, 	/* 03080 */
+	0x44,  0x4F,  0xCA,  0x44,  0x24,  0x42,  0x7C,  0x54,  0x44,  0xC4,  0x84,  0x41,  0xFE,  0x90,  0x23,  0x23, 	/* 03090 */
+	0xCA,  0x24,  0xA4,  0x4A,  0x7F,  0xAC,  0xCA,  0x4E,  0xA5,  0x5A,  0x64,  0xA4,  0x42,  0x44,  0x24,  0x46, 	/* 030A0 */
+	0x91,  0x10,  0x01,  0xFC,  0x12,  0x82,  0x10,  0x2F,  0xE6,  0x92,  0xAF,  0xE2,  0x92,  0x2F,  0xE2,  0x92, 	/* 030B0 */
+	0x29,  0x22,  0x96,  0x94,  0x20,  0x02,  0xFC,  0x28,  0x44,  0xFC,  0x48,  0x4C,  0xFC,  0x48,  0x44,  0xFC, 	/* 030C0 */
+	0x45,  0x04,  0x50,  0x49,  0x25,  0x0E,  0x97,  0x12,  0x81,  0x24,  0x15,  0x22,  0x92,  0x22,  0x86,  0x44, 	/* 030D0 */
+	0xA8,  0x23,  0x7D,  0x24,  0x42,  0x44,  0x24,  0x42,  0x7C,  0x98,  0x20,  0xC3,  0xF8,  0x2C,  0x85,  0x24, 	/* 030E0 */
+	0x62,  0x2D,  0xFC,  0x41,  0x84,  0x20,  0x7F,  0xE4,  0x20,  0x42,  0x04,  0x60,  0x9A,  0x10,  0x01,  0xFC, 	/* 030F0 */
+	0x1A,  0x42,  0xFC,  0x2A,  0x46,  0xA4,  0xAF,  0xC2,  0x20,  0x2F,  0xC2,  0x20,  0x22,  0x03,  0xFE,  0x9B, 	/* 03100 */
+	0x24,  0x02,  0x78,  0x28,  0x84,  0x10,  0x5F,  0xCD,  0x24,  0x52,  0x45,  0xFC,  0x45,  0x04,  0x52,  0x49, 	/* 03110 */
+	0x25,  0x0E,  0x9D,  0x20,  0x02,  0xFC,  0x28,  0x44,  0x84,  0x4F,  0xCC,  0x20,  0x7F,  0xE4,  0x70,  0x4A, 	/* 03120 */
+	0x85,  0x24,  0x62,  0x24,  0x20,  0x9F,  0x24,  0x02,  0x50,  0x28,  0x85,  0xF4,  0x48,  0x0C,  0xFC,  0x52, 	/* 03130 */
+	0x06,  0x20,  0x7F,  0xE4,  0x50,  0x48,  0x87,  0x06,  0xA1,  0x13,  0x81,  0x00,  0x1F,  0xE2,  0x00,  0x27, 	/* 03140 */
+	0xC6,  0x00,  0xA7,  0xC2,  0x00,  0x27,  0xC2,  0x44,  0x24,  0x42,  0x7C,  0xA3,  0x20,  0x02,  0xFC,  0x28, 	/* 03150 */
+	0x44,  0x84,  0x4F,  0xCC,  0x00,  0x4F,  0xC4,  0x20,  0x5F,  0xE4,  0x30,  0x44,  0x85,  0x86,  0xA4,  0x28, 	/* 03160 */
+	0x82,  0x50,  0x3F,  0xC2,  0x24,  0x5F,  0xC5,  0x20,  0xDF,  0xE4,  0x62,  0x4A,  0x25,  0x22,  0x62,  0xC4, 	/* 03170 */
+	0x20,  0xA5,  0x21,  0x03,  0xFF,  0x21,  0x04,  0xFE,  0x49,  0x2C,  0xFE,  0x49,  0x24,  0xFE,  0x41,  0x05, 	/* 03180 */
+	0xFF,  0x41,  0x04,  0x10,  0xAE,  0x24,  0x02,  0x7E,  0x2C,  0x45,  0x28,  0x51,  0x8D,  0xE4,  0x51,  0x35, 	/* 03190 */
+	0x68,  0x51,  0x25,  0x64,  0x41,  0x84,  0xE0,  0xAF,  0x22,  0x03,  0xFE,  0x32,  0x45,  0x24,  0x57,  0xED, 	/* 031A0 */
+	0xC4,  0x56,  0x45,  0x54,  0x55,  0x46,  0x44,  0x64,  0x44,  0x4C,  0xB3,  0x25,  0x02,  0x50,  0x3D,  0xE4, 	/* 031B0 */
+	0x50,  0x45,  0x0D,  0xDE,  0x45,  0x04,  0x50,  0x7D,  0xE4,  0x90,  0x49,  0x05,  0x10,  0xB5,  0x21,  0x02, 	/* 031C0 */
+	0xFE,  0x21,  0x04,  0xFE,  0x41,  0x0D,  0xFF,  0x42,  0x04,  0x52,  0x4D,  0x45,  0x48,  0x47,  0x44,  0xC2, 	/* 031D0 */
+	0xB6,  0x28,  0x02,  0x9E,  0x2E,  0x24,  0x8A,  0x7F,  0xAC,  0x8A,  0x4C,  0xA5,  0xA4,  0x5A,  0x46,  0x8C, 	/* 031E0 */
+	0x49,  0x24,  0xA2,  0xB8,  0x21,  0x02,  0xFE,  0x21,  0x04,  0x7C,  0x42,  0x8D,  0xFF,  0x45,  0x45,  0xFB, 	/* 031F0 */
+	0x41,  0x04,  0xFE,  0x41,  0x04,  0x10,  0xBA,  0x22,  0x02,  0x20,  0x3F,  0xE4,  0x50,  0xCA,  0xC5,  0xFA, 	/* 03200 */
+	0x6A,  0x84,  0xF8,  0x4A,  0x84,  0xF8,  0x42,  0x24,  0x1E,  0xBE,  0x22,  0x02,  0x40,  0x3F,  0xC5,  0x24, 	/* 03210 */
+	0x5F,  0xCD,  0x24,  0x5F,  0xC4,  0x90,  0x7F,  0xE4,  0x10,  0x41,  0x04,  0x10,  0x85,  0x22,  0x02,  0x20, 	/* 03220 */
+	0x3F,  0xE4,  0x88,  0x48,  0x8D,  0x54,  0x52,  0x24,  0x20,  0x7F,  0xE4,  0x20,  0x42,  0x04,  0x20,  0x86, 	/* 03230 */
+	0x20,  0x03,  0xFF,  0x21,  0x05,  0xFF,  0x51,  0x1D,  0xDD,  0x55,  0x55,  0x55,  0x5B,  0xB5,  0x11,  0x51, 	/* 03240 */
+	0x15,  0x13,  0x89,  0x04,  0x00,  0xA0,  0x31,  0x8F,  0xFE,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x20, 	/* 03250 */
+	0x03,  0xFC,  0x50,  0x49,  0xFC,  0x8B,  0x20,  0x03,  0xFE,  0x32,  0x25,  0x22,  0x5F,  0xED,  0x22,  0x57, 	/* 03260 */
+	0xA5,  0x4A,  0x54,  0xA5,  0x7A,  0x50,  0x25,  0xFE,  0x8D,  0x11,  0x01,  0x10,  0x1F,  0xE2,  0x44,  0x22, 	/* 03270 */
+	0x87,  0xFE,  0xA0,  0x02,  0x7C,  0x24,  0x42,  0x44,  0x24,  0x42,  0x7C,  0x8F,  0x24,  0x02,  0x7E,  0x24, 	/* 03280 */
+	0x45,  0xB8,  0x52,  0x8D,  0xC6,  0x51,  0x85,  0x14,  0x5F,  0xE5,  0x10,  0x42,  0x84,  0xC6,  0x91,  0x10, 	/* 03290 */
+	0x01,  0xEE,  0x1A,  0xA2,  0xEE,  0x2A,  0xA6,  0xEE,  0xA8,  0x22,  0x82,  0x28,  0x22,  0x82,  0x28,  0x22, 	/* 032A0 */
+	0x86,  0x92,  0x20,  0x23,  0xF2,  0x24,  0xA4,  0xAA,  0x5D,  0xAC,  0x4A,  0x5F,  0xA4,  0x4A,  0x44,  0xA4, 	/* 032B0 */
+	0x72,  0x58,  0x24,  0x06,  0x94,  0x20,  0x02,  0xFE,  0x28,  0x24,  0xFE,  0x49,  0x0C,  0xD4,  0x4D,  0x45, 	/* 032C0 */
+	0x7C,  0x51,  0x06,  0x92,  0x49,  0x24,  0xFE,  0x96,  0x11,  0x01,  0x10,  0x1F,  0xC2,  0x10,  0x3F,  0xE6, 	/* 032D0 */
+	0x44,  0xAF,  0xE2,  0x10,  0x2F,  0xC2,  0x10,  0x21,  0x02,  0x10,  0x99,  0x20,  0x02,  0x7C,  0x20,  0x45, 	/* 032E0 */
+	0xFE,  0x54,  0x0D,  0x7C,  0x59,  0x05,  0x10,  0x5F,  0xE5,  0x28,  0x44,  0x45,  0x82,  0x9A,  0x22,  0x03, 	/* 032F0 */
+	0xFE,  0x23,  0x04,  0x48,  0x58,  0x4F,  0xFE,  0x40,  0x44,  0xF4,  0x49,  0x44,  0xF4,  0x40,  0x44,  0x0C, 	/* 03300 */
+	0x9F,  0x14,  0x81,  0x48,  0x1F,  0xC2,  0x48,  0x3F,  0xE6,  0x00,  0xAF,  0xC2,  0x84,  0x2F,  0xC2,  0x84, 	/* 03310 */
+	0x28,  0x42,  0xFC,  0xA1,  0x17,  0xC1,  0x44,  0x17,  0xC2,  0x44,  0x27,  0xC6,  0x00,  0xAF,  0xE2,  0x82, 	/* 03320 */
+	0x2F,  0xE2,  0x82,  0x28,  0x22,  0xFE,  0xA3,  0x29,  0x02,  0x90,  0x29,  0xF7,  0xF2,  0x49,  0x2C,  0xEA, 	/* 03330 */
+	0x4A,  0xC4,  0xA4,  0x52,  0x45,  0x2A,  0x62,  0xA4,  0xD1,  0xA4,  0x21,  0x02,  0xFE,  0x21,  0x04,  0x7C, 	/* 03340 */
+	0x54,  0x4D,  0x7C,  0x54,  0x45,  0x7C,  0x54,  0x45,  0x7C,  0x50,  0x05,  0xFE,  0xA5,  0x22,  0x02,  0x20, 	/* 03350 */
+	0x3F,  0xE5,  0x52,  0x45,  0x0C,  0x9E,  0x50,  0x05,  0xFC,  0x42,  0x04,  0x20,  0x42,  0x07,  0xFE,  0xA6, 	/* 03360 */
+	0x22,  0x42,  0xA8,  0x3F,  0xC4,  0x20,  0x5F,  0xEC,  0x50,  0x48,  0x85,  0xF4,  0x61,  0x24,  0xF0,  0x48, 	/* 03370 */
+	0x44,  0x7C,  0xA8,  0x20,  0x02,  0xFE,  0x28,  0x24,  0xFE,  0x49,  0x0C,  0xFF,  0x49,  0x04,  0x90,  0x57, 	/* 03380 */
+	0xE5,  0x42,  0x64,  0x24,  0x7E,  0xA9,  0x22,  0x03,  0xFC,  0x22,  0x04,  0xF8,  0x42,  0x0F,  0xFE,  0x52, 	/* 03390 */
+	0x45,  0x24,  0x5F,  0xC5,  0x04,  0x50,  0x45,  0x0C,  0xAA,  0x22,  0x02,  0xCC,  0x28,  0x42,  0xEC,  0x48, 	/* 033A0 */
+	0x44,  0x84,  0xCF,  0xC4,  0x50,  0x45,  0x04,  0x52,  0x49,  0x25,  0x0E,  0xAB,  0x22,  0x02,  0x20,  0x25, 	/* 033B0 */
+	0x04,  0x88,  0x5F,  0xCE,  0x02,  0x5F,  0xC5,  0x54,  0x5F,  0xC5,  0x54,  0x55,  0x45,  0x0C,  0xAC,  0x22, 	/* 033C0 */
+	0x02,  0x3E,  0x22,  0x05,  0xFC,  0x50,  0x4D,  0xFC,  0x50,  0x45,  0xFC,  0x42,  0x07,  0xFE,  0x42,  0x04, 	/* 033D0 */
+	0x20,  0xAD,  0x20,  0xC2,  0xF0,  0x22,  0x05,  0xFE,  0x47,  0x0C,  0xA8,  0x52,  0x64,  0x40,  0x5F,  0xE4, 	/* 033E0 */
+	0xC8,  0x43,  0x05,  0xCC,  0xB6,  0x10,  0x01,  0xFC,  0x18,  0x42,  0x84,  0x2F,  0xC6,  0x84,  0xAF,  0xC2, 	/* 033F0 */
+	0x84,  0x3F,  0xE2,  0x28,  0x24,  0x43,  0x82,  0xB9,  0x11,  0x01,  0x28,  0x14,  0x42,  0xBA,  0x31,  0x16, 	/* 03400 */
+	0xFE,  0xA9,  0x22,  0xFE,  0x23,  0x02,  0x28,  0x24,  0x42,  0x82,  0x83,  0x20,  0x03,  0xFE,  0x37,  0xC5, 	/* 03410 */
+	0x44,  0x57,  0xCD,  0x44,  0x5F,  0xE5,  0x24,  0x56,  0x85,  0x18,  0x56,  0x45,  0xFE,  0x87,  0x20,  0x03, 	/* 03420 */
+	0xEE,  0x32,  0x25,  0x22,  0x5E,  0xED,  0x00,  0x5E,  0xE5,  0x12,  0x50,  0xA5,  0xE4,  0x50,  0xA5,  0x31, 	/* 03430 */
+	0x88,  0x20,  0x02,  0xFC,  0x28,  0x44,  0xFC,  0x48,  0x4C,  0xFC,  0x44,  0x04,  0xFE,  0x59,  0x26,  0xAA, 	/* 03440 */
+	0x4F,  0xA4,  0x0C,  0x89,  0x12,  0x01,  0x7C,  0x12,  0x43,  0xFF,  0x24,  0x46,  0x7C,  0xA1,  0x02,  0xFC, 	/* 03450 */
+	0x29,  0x03,  0xFE,  0x21,  0x02,  0x10,  0x8F,  0x2F,  0xC2,  0x00,  0x3F,  0xC5,  0x04,  0x5F,  0xCD,  0x00, 	/* 03460 */
+	0x5F,  0xE5,  0xAA,  0x5F,  0xE6,  0xAA,  0x6A,  0xA4,  0x86,  0x90,  0x21,  0x02,  0xFE,  0x24,  0x44,  0x28, 	/* 03470 */
+	0x4F,  0xEC,  0x88,  0x49,  0x44,  0xE8,  0x49,  0x25,  0x64,  0x51,  0x86,  0x60,  0x95,  0x29,  0x02,  0x90, 	/* 03480 */
+	0x2F,  0x64,  0x98,  0x4F,  0x2F,  0x8E,  0x40,  0x04,  0xFC,  0x48,  0x44,  0xFC,  0x48,  0x44,  0xFC,  0x96, 	/* 03490 */
+	0x22,  0x02,  0x20,  0x2F,  0xC4,  0x28,  0x5F,  0xEC,  0x30,  0x44,  0x84,  0xFC,  0x74,  0x44,  0x7C,  0x44, 	/* 034A0 */
+	0x44,  0x7C,  0x9A,  0x28,  0x82,  0x88,  0x28,  0x87,  0xFF,  0x49,  0x4C,  0xB4,  0x5D,  0x45,  0x54,  0x54, 	/* 034B0 */
+	0x85,  0xD8,  0x42,  0x44,  0x42,  0x9C,  0x11,  0x01,  0xFE,  0x10,  0x02,  0x7C,  0x24,  0x47,  0xFF,  0xB0, 	/* 034C0 */
+	0x12,  0x7C,  0x21,  0x02,  0x10,  0x21,  0x02,  0x30,  0xA5,  0x20,  0x82,  0x3E,  0x3C,  0xA4,  0x7F,  0x48, 	/* 034D0 */
+	0xAD,  0xFE,  0x44,  0x85,  0x7E,  0x4C,  0x84,  0x7E,  0x4A,  0x85,  0x1F,  0xAC,  0x24,  0x02,  0x40,  0x27, 	/* 034E0 */
+	0xE4,  0xAA,  0x56,  0xAE,  0x9A,  0x42,  0x24,  0x4C,  0x56,  0x05,  0x52,  0x64,  0x54,  0x3C,  0xB2,  0x20, 	/* 034F0 */
+	0x03,  0xFC,  0x32,  0x45,  0xFC,  0x52,  0x4D,  0x24,  0x5F,  0xC4,  0x20,  0x55,  0x45,  0x52,  0x64,  0xA4, 	/* 03500 */
+	0x38,  0xB4,  0x20,  0x23,  0xEA,  0x32,  0xA5,  0x2A,  0x5E,  0xA5,  0x2A,  0xDE,  0xA5,  0x2A,  0x5E,  0xA4, 	/* 03510 */
+	0x42,  0x4A,  0x25,  0x06,  0xB5,  0x11,  0x01,  0x1E,  0x11,  0x02,  0xFC,  0x28,  0x46,  0xFC,  0xA8,  0x42, 	/* 03520 */
+	0xFC,  0x28,  0x42,  0xFC,  0x24,  0x43,  0x82,  0xB6,  0x20,  0x02,  0xFC,  0x2A,  0x44,  0xFC,  0x4A,  0x4C, 	/* 03530 */
+	0xFC,  0x42,  0x05,  0xFE,  0x52,  0xA5,  0x3A,  0x5C,  0xA5,  0x06,  0xB8,  0x22,  0x02,  0x30,  0x24,  0x84, 	/* 03540 */
+	0xF4,  0x50,  0x2F,  0xCA,  0x54,  0xA5,  0xD4,  0x55,  0x45,  0xD4,  0x54,  0xA5,  0x4A,  0xBD,  0x29,  0x02, 	/* 03550 */
+	0x50,  0x22,  0x05,  0xF8,  0x44,  0x8C,  0x7C,  0x48,  0x45,  0xFE,  0x60,  0x24,  0xAA,  0x52,  0x24,  0x0C, 	/* 03560 */
+	0x80,  0x22,  0x02,  0x40,  0x3F,  0xC5,  0x24,  0x5F,  0xCD,  0x24,  0x5F,  0xC4,  0x68,  0x46,  0x84,  0xB6, 	/* 03570 */
+	0x4A,  0x25,  0x1E,  0x85,  0x22,  0x83,  0xFE,  0x22,  0x05,  0xFC,  0x52,  0x4D,  0xFC,  0x52,  0x44,  0x08, 	/* 03580 */
+	0x7F,  0xE4,  0x88,  0x44,  0x84,  0x18,  0x8D,  0x21,  0x03,  0xFE,  0x24,  0x84,  0x48,  0x5F,  0xED,  0x22, 	/* 03590 */
+	0x5F,  0xE4,  0x20,  0x43,  0xC4,  0x44,  0x48,  0x47,  0x18,  0x91,  0x28,  0x42,  0xC4,  0x35,  0xE5,  0xD4, 	/* 035A0 */
+	0x47,  0xEC,  0x84,  0x72,  0x45,  0xFE,  0x47,  0x04,  0xA8,  0x52,  0x64,  0x20,  0x98,  0x04,  0x00,  0xA0, 	/* 035B0 */
+	0x31,  0x8C,  0x46,  0x24,  0x85,  0x54,  0x24,  0x85,  0x54,  0xFF,  0xE0,  0x40,  0x04,  0x00,  0x40,  0x99, 	/* 035C0 */
+	0x24,  0x82,  0xFE,  0x24,  0x85,  0xFE,  0x50,  0x0D,  0x7E,  0x55,  0x25,  0x7E,  0x55,  0x25,  0x7E,  0x65, 	/* 035D0 */
+	0x24,  0x56,  0x9A,  0x28,  0x82,  0x88,  0x3F,  0xE5,  0x54,  0x62,  0x4D,  0x54,  0x55,  0x44,  0x88,  0x4C, 	/* 035E0 */
+	0x85,  0x34,  0x62,  0x44,  0x42,  0xAC,  0x11,  0x01,  0x92,  0x1F,  0xE2,  0x48,  0x29,  0x06,  0xFE,  0xB9, 	/* 035F0 */
+	0x02,  0xFC,  0x29,  0x02,  0xFC,  0x29,  0x02,  0xFE,  0xAD,  0x22,  0x03,  0xFE,  0x31,  0x05,  0x7C,  0x51, 	/* 03600 */
+	0x4D,  0xFE,  0xD5,  0x25,  0x7E,  0x55,  0x25,  0x7E,  0x55,  0x26,  0x56,  0xB2,  0x28,  0x82,  0x88,  0x3E, 	/* 03610 */
+	0xF4,  0x92,  0x7F,  0x2C,  0xAA,  0x7E,  0xC4,  0x84,  0x4E,  0xC4,  0xAA,  0x53,  0x26,  0x61,  0xB3,  0x22, 	/* 03620 */
+	0x83,  0xFE,  0x2A,  0x44,  0xFC,  0x4A,  0x4C,  0xFC,  0x42,  0xC5,  0xF2,  0x40,  0x87,  0xFE,  0x48,  0x84, 	/* 03630 */
+	0x18,  0xB4,  0x20,  0x03,  0xFE,  0x53,  0xC5,  0x24,  0xD3,  0xC5,  0x00,  0x57,  0xE5,  0x5A,  0x55,  0xA5, 	/* 03640 */
+	0x7E,  0x50,  0x05,  0xFE,  0xB5,  0x11,  0x01,  0xFC,  0x21,  0x02,  0xFC,  0x61,  0x0B,  0xFE,  0x24,  0x42, 	/* 03650 */
+	0x7C,  0x24,  0x42,  0x7C,  0x26,  0x43,  0x82,  0xB7,  0x14,  0x01,  0x7E,  0x2C,  0x43,  0x7C,  0x64,  0x4B, 	/* 03660 */
+	0xFF,  0x24,  0x02,  0xFE,  0x32,  0xA2,  0xD2,  0x22,  0x22,  0xCC,  0xBE,  0x20,  0x02,  0xFE,  0x21,  0x05, 	/* 03670 */
+	0x3C,  0x56,  0x4D,  0xBC,  0x52,  0x45,  0x3C,  0x56,  0x44,  0xFC,  0x43,  0x44,  0xC2,  0x82,  0x22,  0x02, 	/* 03680 */
+	0xFC,  0x2A,  0x47,  0xFE,  0x4A,  0x4C,  0xFC,  0x4A,  0x45,  0xFE,  0x44,  0x84,  0xC8,  0x43,  0x05,  0xCC, 	/* 03690 */
+	0x85,  0x22,  0x82,  0xFE,  0x22,  0x84,  0xFE,  0x49,  0x2C,  0xFE,  0x41,  0x04,  0xFE,  0x41,  0x04,  0x7C, 	/* 036A0 */
+	0x41,  0x04,  0xFE,  0x89,  0x04,  0x00,  0xA0,  0x31,  0x8D,  0xF6,  0x00,  0x07,  0xBC,  0x4A,  0x47,  0xBC, 	/* 036B0 */
+	0x20,  0x83,  0x0C,  0x49,  0x28,  0x22,  0x8A,  0x3F,  0xE2,  0x50,  0x3F,  0xC5,  0x54,  0x5F,  0xCC,  0x20, 	/* 036C0 */
+	0x7F,  0xE4,  0xFC,  0x58,  0xA6,  0xF8,  0x48,  0x24,  0x7E,  0x8D,  0x27,  0x43,  0xC4,  0x24,  0xF5,  0xF5, 	/* 036D0 */
+	0x55,  0x5D,  0xF5,  0x55,  0x55,  0xF5,  0x44,  0x55,  0xE5,  0x47,  0x95,  0x8B,  0x8F,  0x23,  0x82,  0x50, 	/* 036E0 */
+	0x3F,  0xE4,  0x92,  0x4F,  0xEC,  0x32,  0x5D,  0x44,  0x68,  0x59,  0xC4,  0x6A,  0x58,  0x94,  0x30,  0x91, 	/* 036F0 */
+	0x17,  0xC1,  0x10,  0x2F,  0xE2,  0x28,  0x2C,  0x66,  0x38,  0xA2,  0x82,  0xFE,  0x2B,  0xA2,  0xAA,  0x2B, 	/* 03700 */
+	0xA2,  0x86,  0x95,  0x25,  0x03,  0x54,  0x3F,  0xE6,  0x50,  0x5F,  0xCC,  0x20,  0x4F,  0xC4,  0x20,  0x5F, 	/* 03710 */
+	0xE4,  0x50,  0x48,  0x87,  0x06,  0x96,  0x22,  0x03,  0xFE,  0x22,  0x05,  0xFC,  0x50,  0x4D,  0xFC,  0x48, 	/* 03720 */
+	0x87,  0xFE,  0x40,  0x05,  0xFC,  0x50,  0x45,  0xFC,  0x9A,  0x22,  0x03,  0xFE,  0x22,  0x05,  0x54,  0x48, 	/* 03730 */
+	0x8D,  0xFC,  0x68,  0xA4,  0xF8,  0x42,  0x84,  0xA4,  0x52,  0x44,  0x60,  0x9E,  0x20,  0xC3,  0xF4,  0x29, 	/* 03740 */
+	0x25,  0xF8,  0x48,  0x8C,  0xFC,  0x48,  0x44,  0xFE,  0x51,  0x25,  0x4A,  0x6A,  0x24,  0x8C,  0xA3,  0x24, 	/* 03750 */
+	0x83,  0xFE,  0x24,  0x85,  0xFF,  0x44,  0x8C,  0xB4,  0x51,  0x24,  0xFC,  0x48,  0x44,  0xFC,  0x48,  0x44, 	/* 03760 */
+	0xFC,  0xA5,  0x22,  0x02,  0xFC,  0x22,  0x07,  0xFE,  0x48,  0x8D,  0xDC,  0x48,  0x85,  0xDC,  0x7F,  0xE4, 	/* 03770 */
+	0x50,  0x49,  0x25,  0x0E,  0xA7,  0x14,  0x41,  0x28,  0x2F,  0xE2,  0x92,  0x6F,  0xEA,  0x92,  0x2F,  0xE2, 	/* 03780 */
+	0x7C,  0x24,  0x42,  0x7C,  0x24,  0x42,  0x7C,  0xAD,  0x24,  0x43,  0xFE,  0x35,  0x45,  0xFF,  0x4C,  0xCD, 	/* 03790 */
+	0x55,  0x66,  0x74,  0xFC,  0x48,  0x44,  0xFC,  0x48,  0x44,  0xFC,  0xAE,  0x21,  0x02,  0xFE,  0x24,  0x45, 	/* 037A0 */
+	0xFF,  0x49,  0x2C,  0xFE,  0x49,  0x24,  0xFE,  0x41,  0x04,  0xFE,  0x41,  0x05,  0xFF,  0xB5,  0x20,  0x03, 	/* 037B0 */
+	0xFE,  0x2A,  0x44,  0xFC,  0x4A,  0x4D,  0xFE,  0x40,  0x04,  0xFC,  0x4A,  0x44,  0xFC,  0x4A,  0x45,  0xFE, 	/* 037C0 */
+	0xB9,  0x20,  0x03,  0xFE,  0x25,  0x05,  0xFE,  0x55,  0x2D,  0xFE,  0x48,  0x44,  0xFC,  0x4F,  0xC4,  0x84, 	/* 037D0 */
+	0x4F,  0xC5,  0x86,  0xBB,  0x20,  0x83,  0xC8,  0x37,  0xE5,  0x54,  0x5D,  0x4D,  0x3E,  0x5C,  0x87,  0x48, 	/* 037E0 */
+	0x57,  0xE5,  0x48,  0x5C,  0x84,  0x08,  0x80,  0x24,  0x83,  0xFE,  0x22,  0x04,  0xFC,  0x42,  0x0F,  0xFE, 	/* 037F0 */
+	0x4D,  0x45,  0xFE,  0x45,  0x45,  0xCA,  0x45,  0x64,  0xC2,  0x81,  0x24,  0x82,  0x50,  0x2F,  0xE5,  0x90, 	/* 03800 */
+	0x6F,  0xCC,  0x90,  0x4F,  0xE4,  0x00,  0x5D,  0xE5,  0x52,  0x57,  0x25,  0x06,  0x82,  0x22,  0x82,  0xFE, 	/* 03810 */
+	0x2A,  0xA4,  0xFE,  0x4A,  0xAD,  0xFE,  0x50,  0x05,  0xFE,  0x55,  0x25,  0x4C,  0x67,  0x44,  0xC2,  0x84, 	/* 03820 */
+	0x21,  0x02,  0xFC,  0x24,  0x83,  0xFE,  0x48,  0x44,  0xFC,  0xC8,  0x44,  0xFC,  0x56,  0x05,  0x54,  0x64, 	/* 03830 */
+	0xA4,  0x38,  0x89,  0x22,  0x02,  0x30,  0x24,  0x84,  0xFC,  0x50,  0x2D,  0xDD,  0x55,  0x45,  0xDC,  0x48, 	/* 03840 */
+	0x84,  0xCC,  0x51,  0x26,  0x20,  0x92,  0x2F,  0xC2,  0x20,  0x3F,  0xE5,  0x22,  0x57,  0xAC,  0x00,  0x5F, 	/* 03850 */
+	0xE4,  0x20,  0x4F,  0xE4,  0xAA,  0x4A,  0xA4,  0xAE,  0x94,  0x21,  0x02,  0xFE,  0x21,  0x05,  0xFE,  0x4F, 	/* 03860 */
+	0xAC,  0x20,  0x5F,  0xE4,  0x04,  0x7F,  0xE5,  0x64,  0x5D,  0x44,  0x0C,  0x95,  0x21,  0x02,  0xFE,  0x22, 	/* 03870 */
+	0xA5,  0xDE,  0x4D,  0x4D,  0x5A,  0x64,  0x44,  0x7C,  0x44,  0x44,  0x7C,  0x48,  0x45,  0x04,  0x96,  0x3E, 	/* 03880 */
+	0x83,  0x48,  0x3E,  0xE5,  0x30,  0x5E,  0x0D,  0x4E,  0x5F,  0x04,  0x00,  0x5F,  0xC5,  0x54,  0x55,  0x47, 	/* 03890 */
+	0xFE,  0x98,  0x22,  0x02,  0xFC,  0x22,  0x47,  0xFE,  0x4F,  0xCC,  0x20,  0x7F,  0xE5,  0x2A,  0x5F,  0xC5, 	/* 038A0 */
+	0x54,  0x55,  0x47,  0xFE,  0x9A,  0x24,  0x83,  0xFE,  0x24,  0x85,  0xFC,  0x55,  0x4D,  0xFC,  0x40,  0x07, 	/* 038B0 */
+	0xFE,  0x67,  0xA5,  0xC8,  0x43,  0x05,  0xC0,  0x9F,  0x2A,  0x42,  0x58,  0x3F,  0xE5,  0x7A,  0x54,  0xAC, 	/* 038C0 */
+	0xFC,  0x48,  0x44,  0xFC,  0x48,  0x44,  0xFC,  0x44,  0x45,  0x82,  0xA1,  0x20,  0x02,  0xFC,  0x2A,  0x44, 	/* 038D0 */
+	0xFC,  0x4A,  0x4C,  0xFC,  0x40,  0x07,  0xFE,  0x6A,  0xA7,  0xFE,  0x6A,  0xA7,  0xFE,  0xAA,  0x3F,  0xE2, 	/* 038E0 */
+	0x20,  0x27,  0x84,  0x48,  0x5F,  0xED,  0x6A,  0x4B,  0x45,  0x7A,  0x4C,  0x85,  0x30,  0x46,  0x85,  0x86, 	/* 038F0 */
+	0xB2,  0x2C,  0x82,  0x1E,  0x3E,  0x84,  0x08,  0x5F,  0xEC,  0x10,  0x5D,  0xE4,  0x12,  0x5F,  0xE5,  0x52, 	/* 03900 */
+	0x55,  0x25,  0xDE,  0xB7,  0x3D,  0xE2,  0x00,  0x3D,  0xE6,  0xAA,  0x5F,  0xED,  0xFC,  0x55,  0x45,  0xFC, 	/* 03910 */
+	0x5A,  0xA5,  0xCC,  0x6A,  0xA5,  0xCE,  0xBA,  0x2A,  0xA3,  0xF4,  0x2B,  0xF5,  0xF4,  0x55,  0x4D,  0xFE, 	/* 03920 */
+	0x45,  0x45,  0xF4,  0x45,  0xE7,  0xF4,  0x53,  0x46,  0x1F,  0xBB,  0x2A,  0x43,  0xFE,  0x34,  0xA4,  0x78, 	/* 03930 */
+	0x4F,  0xCC,  0xDC,  0x4B,  0x44,  0xFC,  0x41,  0x05,  0xFE,  0x4A,  0x45,  0x52,  0xBC,  0x2E,  0xE2,  0xAA, 	/* 03940 */
+	0x3F,  0xE5,  0x68,  0x52,  0x8D,  0xFF,  0x55,  0xA5,  0x7A,  0x55,  0x45,  0xF4,  0x52,  0xA6,  0x31,  0xBF, 	/* 03950 */
+	0x11,  0x01,  0x10,  0x11,  0x01,  0x10,  0x11,  0x01,  0x10,  0x11,  0x01,  0x10,  0x21,  0x02,  0x12,  0x41, 	/* 03960 */
+	0x28,  0x0E,  0x80,  0x00,  0x0F,  0xFE,  0x11,  0x01,  0x10,  0x11,  0x01,  0x10,  0x11,  0x01,  0x10,  0x21, 	/* 03970 */
+	0x02,  0x12,  0x41,  0x28,  0x0E,  0x81,  0x08,  0x00,  0x80,  0x13,  0x02,  0x0C,  0x7F,  0x20,  0xA0,  0x0A, 	/* 03980 */
+	0x00,  0xA0,  0x12,  0x01,  0x22,  0x22,  0x24,  0x1E,  0x83,  0x00,  0x01,  0xF8,  0x00,  0x00,  0x00,  0x7F, 	/* 03990 */
+	0xE0,  0x90,  0x09,  0x00,  0x90,  0x11,  0x01,  0x12,  0x21,  0x24,  0x0E,  0x84,  0x00,  0x03,  0xF8,  0x20, 	/* 039A0 */
+	0x82,  0x08,  0x20,  0x83,  0xF8,  0x0A,  0x00,  0xA0,  0x0A,  0x01,  0x22,  0x22,  0x2C,  0x1E,  0x85,  0x08, 	/* 039B0 */
+	0x00,  0x80,  0xFF,  0xE0,  0xA0,  0x11,  0x87,  0xE4,  0x12,  0x01,  0x20,  0x12,  0x02,  0x22,  0x42,  0x28, 	/* 039C0 */
+	0x1E,  0x86,  0x0A,  0x00,  0xA4,  0x4A,  0x42,  0xA8,  0x2B,  0x00,  0xA0,  0x1B,  0x02,  0xAC,  0xD2,  0x01, 	/* 039D0 */
+	0x22,  0x22,  0x2C,  0x1E,  0x87,  0x02,  0x05,  0xA4,  0x44,  0x44,  0x64,  0x49,  0x45,  0x04,  0x7F,  0xC0, 	/* 039E0 */
+	0xA0,  0x0A,  0x01,  0x22,  0x22,  0x2C,  0x1E,  0x88,  0x04,  0x02,  0x40,  0x24,  0x03,  0xF8,  0x24,  0x04, 	/* 039F0 */
+	0x40,  0xFF,  0xE0,  0xA0,  0x0A,  0x01,  0x22,  0x22,  0x2C,  0x1E,  0x89,  0x04,  0x04,  0x48,  0x24,  0x82, 	/* 03A00 */
+	0x50,  0x04,  0x07,  0xFE,  0x0A,  0x00,  0xA0,  0x12,  0x01,  0x22,  0x22,  0x2C,  0x1E,  0x8B,  0x04,  0x00, 	/* 03A10 */
+	0x40,  0xFF,  0xE0,  0x40,  0x3F,  0x82,  0x08,  0x20,  0x83,  0xF8,  0x0A,  0x00,  0xA2,  0x12,  0x2E,  0x1E, 	/* 03A20 */
+	0x8C,  0x0B,  0x01,  0x10,  0x20,  0x8D,  0xFE,  0x20,  0x82,  0x08,  0x3F,  0x80,  0xA0,  0x0A,  0x01,  0x22, 	/* 03A30 */
+	0x22,  0x2C,  0x1E,  0x8D,  0x08,  0x00,  0xF0,  0x12,  0x02,  0x40,  0xFF,  0xC2,  0x44,  0x24,  0x43,  0xFC, 	/* 03A40 */
+	0x0A,  0x01,  0x22,  0x22,  0x2C,  0x1E,  0x8E,  0x01,  0xC7,  0xE0,  0x04,  0x07,  0xFC,  0x44,  0x44,  0x44, 	/* 03A50 */
+	0x7F,  0xC0,  0xA0,  0x0B,  0x01,  0x2A,  0x22,  0x2C,  0x1E,  0x90,  0x4F,  0x84,  0x88,  0x48,  0x84,  0xF8, 	/* 03A60 */
+	0x48,  0x84,  0x88,  0x4F,  0x84,  0x20,  0x12,  0x01,  0x22,  0x22,  0x2C,  0x1E,  0x92,  0x08,  0x03,  0x38, 	/* 03A70 */
+	0x20,  0x82,  0x08,  0x3B,  0x82,  0x08,  0x20,  0x83,  0xF8,  0x09,  0x00,  0x92,  0x11,  0x26,  0x0E,  0x94, 	/* 03A80 */
+	0x08,  0x00,  0xF0,  0x12,  0x02,  0x40,  0xFF,  0xC4,  0x44,  0x44,  0x47,  0xFC,  0x0B,  0x01,  0x2A,  0x22, 	/* 03A90 */
+	0x2C,  0x1E,  0x9A,  0x24,  0x81,  0x50,  0xFF,  0xE8,  0x02,  0xBF,  0xA2,  0x08,  0x20,  0x83,  0xF8,  0x0A, 	/* 03AA0 */
+	0x00,  0xA0,  0x32,  0x2C,  0x1E,  0x9C,  0x14,  0x06,  0xFC,  0x4A,  0x44,  0xE4,  0x4A,  0x47,  0xBC,  0x4E, 	/* 03AB0 */
+	0x40,  0x00,  0x0A,  0x01,  0x22,  0x22,  0x2C,  0x1E,  0xA2,  0x10,  0x8F,  0xFE,  0x10,  0x87,  0xBC,  0x4A, 	/* 03AC0 */
+	0x44,  0xA4,  0x7B,  0xC3,  0x18,  0x31,  0x83,  0x6A,  0x5A,  0xA8,  0x46,  0xA5,  0x00,  0x01,  0xC0,  0x04, 	/* 03AD0 */
+	0x00,  0x40,  0x04,  0x00,  0x40,  0x0A,  0x00,  0xA0,  0x11,  0x02,  0x08,  0x40,  0x48,  0x02,  0xA8,  0x04, 	/* 03AE0 */
+	0x00,  0x40,  0x0A,  0x01,  0x10,  0x20,  0x8F,  0xFE,  0x04,  0x00,  0x40,  0x3F,  0x80,  0x40,  0x04,  0x0F, 	/* 03AF0 */
+	0xFE,  0xA9,  0x00,  0x0F,  0xFE,  0x04,  0x0F,  0xFE,  0x84,  0x2B,  0x5A,  0x94,  0xA9,  0x4A,  0xAD,  0x6C, 	/* 03B00 */
+	0x62,  0x84,  0x28,  0x46,  0xAA,  0x1C,  0x00,  0xA0,  0x11,  0x02,  0xE8,  0xC0,  0x67,  0x94,  0x69,  0x45, 	/* 03B10 */
+	0xA8,  0x6A,  0x85,  0x94,  0x49,  0x45,  0x94,  0xAB,  0x00,  0x01,  0xF0,  0x01,  0x00,  0x10,  0x11,  0x01, 	/* 03B20 */
+	0x10,  0x11,  0x01,  0x08,  0x20,  0x82,  0x04,  0x40,  0x48,  0x02,  0xAC,  0x11,  0x01,  0x10,  0x11,  0x02, 	/* 03B30 */
+	0x08,  0x24,  0x44,  0x42,  0x84,  0x00,  0x90,  0x08,  0x81,  0x78,  0x78,  0x40,  0x04,  0xAD,  0x04,  0x00, 	/* 03B40 */
+	0x40,  0x04,  0x0F,  0xFE,  0x00,  0x01,  0x20,  0x11,  0x02,  0x08,  0x20,  0x44,  0x04,  0x80,  0x40,  0x00, 	/* 03B50 */
+	0xAE,  0x16,  0x01,  0x20,  0x21,  0x04,  0x08,  0xBF,  0x60,  0x80,  0x08,  0x01,  0xF0,  0x11,  0x00,  0x10, 	/* 03B60 */
+	0x01,  0x00,  0x60,  0xB1,  0x11,  0x01,  0x10,  0x11,  0x07,  0xFC,  0x11,  0x01,  0x10,  0x11,  0x0F,  0xFE, 	/* 03B70 */
+	0x01,  0x01,  0x08,  0x20,  0x4C,  0x04,  0xB5,  0x03,  0x03,  0xC0,  0x20,  0x02,  0x00,  0x3F,  0xC2,  0x10, 	/* 03B80 */
+	0x21,  0x02,  0x10,  0xFF,  0xE1,  0x20,  0x21,  0x8C,  0x04,  0xB6,  0x11,  0x01,  0x10,  0x7F,  0xC1,  0x10, 	/* 03B90 */
+	0x1F,  0x01,  0x10,  0x1F,  0x01,  0x10,  0xFF,  0xE1,  0x10,  0x20,  0xCC,  0x02,  0xB7,  0x3F,  0x02,  0x10, 	/* 03BA0 */
+	0x3F,  0x02,  0x10,  0x3F,  0x02,  0x10,  0x3F,  0x00,  0x00,  0xFF,  0xE1,  0x20,  0x21,  0x8C,  0x04,  0xB8, 	/* 03BB0 */
+	0x0A,  0x00,  0xA0,  0x7F,  0xC4,  0xA4,  0x4A,  0x47,  0xFC,  0x4A,  0x44,  0xA4,  0xFF,  0xE1,  0x10,  0x20, 	/* 03BC0 */
+	0xCC,  0x02,  0xBC,  0x11,  0x0F,  0xFE,  0x0A,  0x07,  0xFC,  0x0A,  0x4F,  0xFE,  0x0A,  0x47,  0xFC,  0x1B, 	/* 03BD0 */
+	0x02,  0xA8,  0xCA,  0x60,  0xA0,  0x80,  0x12,  0x4F,  0x38,  0x12,  0x23,  0xFE,  0xE4,  0x83,  0xF8,  0x24, 	/* 03BE0 */
+	0x87,  0xFC,  0x11,  0x0F,  0xFF,  0x30,  0x8C,  0x04,  0x82,  0x00,  0x07,  0xFE,  0x40,  0x24,  0x02,  0x40, 	/* 03BF0 */
+	0x24,  0x02,  0x40,  0x24,  0x02,  0x40,  0x24,  0x02,  0x40,  0x24,  0x06,  0x85,  0x04,  0x00,  0x40,  0x7F, 	/* 03C00 */
+	0xE4,  0x42,  0x44,  0x24,  0xA2,  0x51,  0x26,  0x0A,  0x40,  0x24,  0x02,  0x40,  0x24,  0x06,  0x86,  0x00, 	/* 03C10 */
+	0x07,  0xFC,  0x44,  0x44,  0x44,  0x44,  0x47,  0xFC,  0x40,  0x44,  0x04,  0x40,  0x44,  0x04,  0x40,  0x44, 	/* 03C20 */
+	0x0C,  0x89,  0x04,  0x00,  0x40,  0x3F,  0x82,  0x48,  0x24,  0x83,  0xF8,  0x24,  0x82,  0x48,  0xFF,  0xE2, 	/* 03C30 */
+	0x08,  0x20,  0x82,  0x18,  0x8A,  0x00,  0x03,  0xFC,  0x29,  0x42,  0x94,  0x29,  0x42,  0x94,  0xFF,  0xE2, 	/* 03C40 */
+	0x94,  0x29,  0x42,  0x94,  0x29,  0x42,  0x0C,  0x8C,  0x7B,  0xC4,  0xA4,  0x4A,  0x44,  0xA4,  0x4A,  0x4F, 	/* 03C50 */
+	0xFE,  0x4A,  0x44,  0xA4,  0x4A,  0x44,  0xA4,  0x4A,  0x49,  0xCC,  0x8D,  0x00,  0x07,  0xFC,  0x04,  0x03, 	/* 03C60 */
+	0xF8,  0x24,  0x83,  0xF8,  0x24,  0x82,  0x48,  0xFF,  0xE2,  0x08,  0x20,  0x82,  0x18,  0x8F,  0x00,  0x07, 	/* 03C70 */
+	0xFE,  0x49,  0x24,  0x92,  0x50,  0xE6,  0x02,  0x4F,  0x24,  0x92,  0x49,  0x24,  0xF2,  0x40,  0x24,  0x06, 	/* 03C80 */
+	0x90,  0x7F,  0xE4,  0x02,  0x5F,  0xA4,  0x02,  0x5F,  0xA0,  0x00,  0x3F,  0xC2,  0x04,  0x3F,  0x42,  0xFC, 	/* 03C90 */
+	0x20,  0x42,  0x0C,  0x91,  0x04,  0x07,  0xFC,  0x44,  0x47,  0xFC,  0x44,  0x47,  0xFC,  0x20,  0x82,  0xE8, 	/* 03CA0 */
+	0x20,  0x82,  0xE8,  0x20,  0x82,  0x18,  0x92,  0x00,  0x07,  0xFC,  0x40,  0x47,  0xFC,  0x40,  0x47,  0xFC, 	/* 03CB0 */
+	0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x93,  0x11,  0x07,  0xFC,  0x11,  0x07,  0xFC, 	/* 03CC0 */
+	0x11,  0x0F,  0xFE,  0x24,  0x83,  0xF8,  0x24,  0x8F,  0xFE,  0x20,  0x82,  0x18,  0x95,  0x7F,  0xC4,  0x04, 	/* 03CD0 */
+	0x5F,  0x44,  0x04,  0x5F,  0x43,  0x20,  0xFF,  0xC4,  0x44,  0x7F,  0xC0,  0xA0,  0x32,  0x2C,  0x1E,  0x96, 	/* 03CE0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xFF,  0xE8,  0x02,  0x80,  0x20,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 03CF0 */
+	0x00,  0x00,  0x97,  0x00,  0x0F,  0xFE,  0x80,  0x28,  0x02,  0x1E,  0x01,  0x20,  0x12,  0x01,  0x20,  0x12, 	/* 03D00 */
+	0x01,  0x22,  0x22,  0x2C,  0x1E,  0x99,  0x00,  0x0F,  0xFE,  0x90,  0x29,  0x02,  0x1F,  0x81,  0x00,  0x1F, 	/* 03D10 */
+	0x00,  0x10,  0xFF,  0xE0,  0x10,  0x01,  0x00,  0x60,  0xA0,  0x00,  0x0F,  0xFE,  0x80,  0xAF,  0xCA,  0x03, 	/* 03D20 */
+	0xEF,  0xC8,  0x2A,  0x82,  0xA8,  0x28,  0x84,  0x9A,  0x48,  0x28,  0x7E,  0xA2,  0x00,  0x0F,  0xFE,  0x80, 	/* 03D30 */
+	0x2B,  0xFA,  0x0C,  0x45,  0x24,  0xE7,  0x81,  0xB0,  0x76,  0x81,  0xA4,  0x62,  0x00,  0xC0,  0xA4,  0x00, 	/* 03D40 */
+	0x0F,  0xFF,  0x84,  0x11,  0xF0,  0xE2,  0x07,  0xFC,  0x44,  0x44,  0x44,  0x7F,  0xC0,  0xB0,  0x32,  0xAC, 	/* 03D50 */
+	0x1E,  0xA5,  0x00,  0x0F,  0xFE,  0x80,  0x2B,  0xFA,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x04,  0x0F, 	/* 03D60 */
+	0xFE,  0x11,  0x86,  0x04,  0xA6,  0x00,  0x0F,  0xFE,  0x81,  0x27,  0x9C,  0x01,  0x0F,  0xFC,  0x54,  0x45, 	/* 03D70 */
+	0x28,  0x51,  0x85,  0x24,  0x94,  0x28,  0xFE,  0xA8,  0x00,  0x0F,  0xFE,  0x80,  0x2B,  0xFA,  0x00,  0x03, 	/* 03D80 */
+	0xF8,  0x20,  0x87,  0xFC,  0x44,  0x47,  0xFC,  0x44,  0x47,  0xFC,  0xA9,  0x00,  0x0F,  0xFE,  0x88,  0x2B, 	/* 03D90 */
+	0x9A,  0x20,  0x83,  0xB8,  0x20,  0x83,  0xF8,  0x08,  0x03,  0xFE,  0xD5,  0x22,  0x0C,  0xAA,  0x00,  0x0F, 	/* 03DA0 */
+	0xFE,  0x92,  0x2F,  0xFE,  0x21,  0x03,  0xF0,  0x21,  0x0F,  0xFE,  0x29,  0x07,  0xF8,  0xA9,  0x62,  0xB0, 	/* 03DB0 */
+	0xAB,  0x08,  0x00,  0x40,  0x04,  0x00,  0x00,  0x01,  0x00,  0x20,  0x04,  0x00,  0x40,  0x08,  0x00,  0x80, 	/* 03DC0 */
+	0x08,  0x00,  0x00,  0xAC,  0x04,  0x00,  0xF8,  0x10,  0x82,  0x90,  0xC6,  0x00,  0xA0,  0x31,  0x8C,  0xC6, 	/* 03DD0 */
+	0x02,  0x01,  0x80,  0x06,  0x00,  0x10,  0xB0,  0x01,  0x08,  0x10,  0x41,  0x04,  0x11,  0x1D,  0x20,  0x5C, 	/* 03DE0 */
+	0x05,  0x82,  0x94,  0x49,  0x25,  0x11,  0x81,  0x08,  0x30,  0xB1,  0x00,  0x09,  0xFE,  0x44,  0x04,  0x40, 	/* 03DF0 */
+	0x07,  0xC0,  0x44,  0x08,  0x42,  0x88,  0x4F,  0x84,  0x88,  0x80,  0x89,  0xFF,  0xB2,  0x01,  0x08,  0x10, 	/* 03E00 */
+	0x41,  0x04,  0xFF,  0x09,  0x10,  0x91,  0x09,  0x12,  0xFF,  0x49,  0x04,  0x10,  0x81,  0x08,  0x10,  0xB3, 	/* 03E10 */
+	0x01,  0x08,  0x10,  0x4F,  0xE4,  0x12,  0x01,  0x20,  0x12,  0x3F,  0xF4,  0x10,  0x41,  0x08,  0x28,  0x84, 	/* 03E20 */
+	0x41,  0x83,  0xB4,  0x00,  0x08,  0xFE,  0x44,  0x84,  0x48,  0x04,  0x81,  0xFE,  0x01,  0x82,  0x18,  0x42, 	/* 03E30 */
+	0x84,  0xC8,  0xB0,  0x88,  0x18,  0xB5,  0x00,  0x08,  0xFC,  0x48,  0x44,  0x84,  0x08,  0x40,  0xFC,  0x25, 	/* 03E40 */
+	0x04,  0x50,  0x45,  0x08,  0x92,  0x91,  0x22,  0x0E,  0xB6,  0x02,  0x08,  0x20,  0x42,  0x84,  0x44,  0x09, 	/* 03E50 */
+	0xE1,  0xE2,  0x00,  0x02,  0xFC,  0x48,  0x44,  0x84,  0x88,  0x48,  0xFC,  0xB7,  0x02,  0x08,  0x20,  0x45, 	/* 03E60 */
+	0x04,  0x98,  0x1F,  0xC2,  0x02,  0x0F,  0xC2,  0x24,  0x42,  0x44,  0x38,  0x82,  0x08,  0x20,  0xBD,  0x00, 	/* 03E70 */
+	0x29,  0xEA,  0x48,  0xA4,  0x8A,  0x1E,  0xA1,  0x2A,  0x1A,  0xA6,  0x6A,  0x44,  0xA8,  0x42,  0x88,  0x21, 	/* 03E80 */
+	0x06,  0x84,  0x02,  0x09,  0xFE,  0x42,  0x04,  0xFC,  0x02,  0x41,  0xFE,  0x22,  0x45,  0xFE,  0x44,  0x88, 	/* 03E90 */
+	0xE8,  0x83,  0x81,  0xC4,  0x85,  0x00,  0x09,  0xFE,  0x52,  0x25,  0xFE,  0x12,  0x21,  0x22,  0x3F,  0xA5, 	/* 03EA0 */
+	0x8A,  0x58,  0xA9,  0xFA,  0x90,  0x21,  0xFE,  0x86,  0x04,  0x48,  0x48,  0x4F,  0xE4,  0x90,  0x19,  0x02, 	/* 03EB0 */
+	0xFC,  0x29,  0x04,  0x90,  0x4F,  0xC8,  0x90,  0x89,  0x00,  0xFE,  0x89,  0x02,  0x09,  0xFE,  0x40,  0x04, 	/* 03EC0 */
+	0xFC,  0x08,  0x40,  0x84,  0x2F,  0xC4,  0x20,  0x4A,  0x88,  0xA4,  0x92,  0x40,  0x60,  0x8B,  0x00,  0x08, 	/* 03ED0 */
+	0xFE,  0x49,  0x24,  0xBA,  0x09,  0x20,  0xFE,  0x28,  0x24,  0xBA,  0x4A,  0xA8,  0xBA,  0x90,  0x22,  0x06, 	/* 03EE0 */
+	0x8C,  0x02,  0x09,  0xFC,  0x42,  0x05,  0xFE,  0x05,  0x03,  0x9E,  0x04,  0x04,  0x78,  0x58,  0x88,  0x70, 	/* 03EF0 */
+	0x8D,  0x8B,  0x06,  0x8D,  0x02,  0x09,  0xFE,  0x42,  0x04,  0xFC,  0x0A,  0x40,  0xFC,  0x2A,  0x44,  0xFC, 	/* 03F00 */
+	0x47,  0x08,  0xAC,  0xB2,  0x20,  0x20,  0x96,  0x04,  0x88,  0x50,  0x4F,  0xE1,  0x90,  0x0F,  0xC4,  0x90, 	/* 03F10 */
+	0x8F,  0xE8,  0x40,  0x04,  0x0F,  0xFE,  0x04,  0x00,  0x40,  0x9B,  0x01,  0x09,  0xFF,  0x4A,  0xA4,  0xBA, 	/* 03F20 */
+	0x08,  0x20,  0xFE,  0x27,  0xC4,  0x00,  0x5F,  0xF8,  0x92,  0x91,  0x10,  0x30,  0x9C,  0x02,  0x0B,  0xFE, 	/* 03F30 */
+	0x50,  0x41,  0x74,  0x15,  0x41,  0xFC,  0x01,  0x82,  0xE0,  0x5F,  0xE4,  0xA8,  0x92,  0x48,  0x20,  0x9D, 	/* 03F40 */
+	0x23,  0xE2,  0x42,  0xB9,  0x46,  0x48,  0x1F,  0xE1,  0x0A,  0x1E,  0x86,  0xAE,  0x5E,  0x88,  0xA8,  0x95, 	/* 03F50 */
+	0x82,  0x46,  0xA0,  0x1F,  0x01,  0x10,  0x11,  0x01,  0x10,  0x11,  0x01,  0x10,  0x11,  0x01,  0x10,  0x21, 	/* 03F60 */
+	0x02,  0x12,  0x41,  0x28,  0x0E,  0xA1,  0x00,  0x01,  0xF0,  0x11,  0x01,  0x10,  0x11,  0x01,  0x90,  0x15, 	/* 03F70 */
+	0x01,  0x50,  0x11,  0x02,  0x12,  0x21,  0x24,  0x0E,  0xA6,  0x20,  0x02,  0x38,  0x3A,  0x82,  0xA8,  0x4A, 	/* 03F80 */
+	0x84,  0xA8,  0xAA,  0xA1,  0x2A,  0x14,  0x62,  0x80,  0x46,  0x08,  0x1F,  0xA7,  0x00,  0x07,  0xFC,  0x44, 	/* 03F90 */
+	0x44,  0x44,  0x5F,  0x45,  0x54,  0x55,  0x45,  0x54,  0x55,  0x45,  0x75,  0x84,  0x38,  0x41,  0xA9,  0x00, 	/* 03FA0 */
+	0x07,  0xFC,  0x44,  0x44,  0x44,  0x7F,  0xC4,  0x44,  0x4E,  0x44,  0xD4,  0x54,  0xC6,  0x45,  0x84,  0x38, 	/* 03FB0 */
+	0x41,  0xAA,  0x00,  0x07,  0xFC,  0x44,  0x44,  0x44,  0x54,  0x45,  0x74,  0x54,  0x45,  0x44,  0x54,  0x57, 	/* 03FC0 */
+	0xFB,  0x40,  0x38,  0x01,  0xAD,  0x20,  0xC2,  0xF0,  0x41,  0x0D,  0xFE,  0x41,  0x04,  0xFC,  0x40,  0x01, 	/* 03FD0 */
+	0xF0,  0x11,  0x01,  0x12,  0x21,  0x24,  0x0E,  0xB0,  0x00,  0x07,  0xFC,  0x44,  0x45,  0xF4,  0x51,  0x45, 	/* 03FE0 */
+	0xF4,  0x51,  0x45,  0xF4,  0x44,  0x45,  0xF5,  0x84,  0x3B,  0xF9,  0xB1,  0x20,  0x0A,  0xBC,  0xFA,  0x40, 	/* 03FF0 */
+	0x24,  0xFA,  0x40,  0x24,  0xFA,  0x48,  0xA4,  0xFA,  0x45,  0x24,  0x7C,  0x4C,  0x87,  0xB5,  0x40,  0x24, 	/* 04000 */
+	0x02,  0x40,  0x24,  0x02,  0x40,  0x24,  0x02,  0x40,  0x24,  0x02,  0x40,  0x24,  0x02,  0x7F,  0xE4,  0x02, 	/* 04010 */
+	0xB6,  0x00,  0x84,  0x0A,  0x50,  0xA4,  0x92,  0x45,  0x24,  0x22,  0x45,  0x24,  0x8A,  0x70,  0xA4,  0x02, 	/* 04020 */
+	0x7F,  0xE4,  0x00,  0xB8,  0x00,  0x01,  0xF0,  0x11,  0x01,  0x10,  0x11,  0x0F,  0x1E,  0x80,  0x28,  0x02, 	/* 04030 */
+	0x80,  0x28,  0x02,  0xFF,  0xE0,  0x00,  0xB9,  0x00,  0x0F,  0x1E,  0x91,  0x29,  0x12,  0x91,  0x29,  0x12, 	/* 04040 */
+	0x9F,  0x28,  0x02,  0x80,  0x28,  0x02,  0xFF,  0xE0,  0x00,  0xBA,  0x04,  0x00,  0x40,  0x24,  0x82,  0x48, 	/* 04050 */
+	0x24,  0x83,  0xF8,  0x04,  0x04,  0x44,  0x44,  0x44,  0x44,  0x44,  0x47,  0xFC,  0xBD,  0x00,  0x07,  0xFC, 	/* 04060 */
+	0x04,  0x08,  0x42,  0x8E,  0xAA,  0x2A,  0x97,  0x28,  0xAA,  0xB2,  0x68,  0x62,  0x80,  0x2F,  0xFE,  0xBE, 	/* 04070 */
+	0x00,  0x01,  0xF8,  0x01,  0x08,  0x62,  0x84,  0x2B,  0xFE,  0xAD,  0x6A,  0xCA,  0xBD,  0x68,  0x62,  0x8C, 	/* 04080 */
+	0x2F,  0xFE,  0x80,  0x00,  0x07,  0xFE,  0x02,  0x20,  0x22,  0x02,  0x20,  0x22,  0x04,  0x20,  0x42,  0x08, 	/* 04090 */
+	0x20,  0x82,  0x10,  0x22,  0x0C,  0x83,  0x00,  0x07,  0xFE,  0x04,  0x20,  0x42,  0x04,  0x21,  0xC2,  0x06, 	/* 040A0 */
+	0x20,  0x52,  0x08,  0x20,  0x82,  0x10,  0x22,  0x0C,  0x84,  0x00,  0x07,  0xFC,  0x04,  0x40,  0x44,  0x44, 	/* 040B0 */
+	0x42,  0x44,  0x14,  0x40,  0x84,  0x0E,  0x41,  0x1E,  0x20,  0x44,  0x18,  0x86,  0x09,  0x00,  0x90,  0x08, 	/* 040C0 */
+	0x81,  0x08,  0x20,  0x45,  0xFA,  0x84,  0x90,  0x48,  0x04,  0x80,  0x88,  0x10,  0x82,  0x30,  0x87,  0x00, 	/* 040D0 */
+	0x04,  0xFE,  0x41,  0x24,  0xD2,  0xF1,  0x24,  0x12,  0x41,  0x24,  0x92,  0x3A,  0x20,  0x22,  0x04,  0x21, 	/* 040E0 */
+	0x8C,  0x88,  0x00,  0x20,  0x52,  0x05,  0x20,  0x52,  0xC9,  0x22,  0x92,  0x11,  0x21,  0x92,  0x25,  0x22, 	/* 040F0 */
+	0x42,  0x40,  0x28,  0x06,  0x8A,  0x00,  0x27,  0xD2,  0x11,  0x21,  0x12,  0x11,  0x2F,  0xD2,  0x11,  0x21, 	/* 04100 */
+	0x12,  0x11,  0x21,  0x02,  0x10,  0x21,  0x06,  0x8B,  0x1C,  0x2F,  0x12,  0x11,  0x21,  0x12,  0x11,  0x2F, 	/* 04110 */
+	0xF2,  0x11,  0x21,  0x12,  0x11,  0x21,  0x02,  0x20,  0x24,  0x06,  0x8E,  0x20,  0x22,  0x0A,  0x7E,  0xA5, 	/* 04120 */
+	0x6A,  0x96,  0xA2,  0x6A,  0x2A,  0xA4,  0xAA,  0x92,  0xA2,  0x22,  0x42,  0x20,  0xC6,  0x91,  0x00,  0x2F, 	/* 04130 */
+	0xD2,  0x49,  0x24,  0x92,  0x49,  0x2F,  0xF2,  0x49,  0x24,  0x92,  0x49,  0x24,  0x82,  0x48,  0x28,  0x86, 	/* 04140 */
+	0x94,  0x20,  0x22,  0x12,  0x7D,  0x22,  0x52,  0x25,  0x22,  0x52,  0xFF,  0x22,  0x12,  0x31,  0x22,  0x82, 	/* 04150 */
+	0x48,  0x28,  0x06,  0x97,  0x00,  0x2F,  0xD2,  0x21,  0x22,  0x12,  0x3D,  0x24,  0x52,  0x65,  0x29,  0x92, 	/* 04160 */
+	0x09,  0x21,  0x02,  0x20,  0x24,  0x06,  0x9D,  0x20,  0x02,  0x7E,  0xF9,  0x20,  0x92,  0x11,  0x22,  0x52, 	/* 04170 */
+	0x39,  0x26,  0x92,  0xA6,  0x22,  0x22,  0x24,  0x22,  0x8C,  0xA4,  0x10,  0x29,  0x52,  0x55,  0x25,  0x92, 	/* 04180 */
+	0x7D,  0x21,  0x12,  0x11,  0x2F,  0xF2,  0x11,  0x21,  0x02,  0x10,  0x21,  0x06,  0xA5,  0x00,  0x27,  0xD2, 	/* 04190 */
+	0x45,  0x24,  0x52,  0x7D,  0x22,  0x12,  0x3D,  0x22,  0x52,  0x25,  0x22,  0x42,  0x44,  0x29,  0x86,  0xA7, 	/* 041A0 */
+	0x20,  0x02,  0x7E,  0xF9,  0x22,  0x12,  0x21,  0x2F,  0xD2,  0x21,  0x22,  0x12,  0x51,  0x24,  0xA2,  0xFA, 	/* 041B0 */
+	0x20,  0x4C,  0xA9,  0x0C,  0x27,  0x12,  0x11,  0x21,  0x12,  0xFD,  0x23,  0x12,  0x39,  0x25,  0x52,  0x50, 	/* 041C0 */
+	0x29,  0x02,  0x10,  0x21,  0x06,  0xAA,  0x00,  0x2F,  0xEA,  0xAA,  0xAA,  0xAA,  0xAA,  0xAF,  0xFA,  0xAA, 	/* 041D0 */
+	0xAA,  0xAA,  0xAA,  0xAA,  0xA2,  0xAA,  0x28,  0x66,  0xAE,  0x06,  0x27,  0x92,  0x11,  0x21,  0x12,  0xFF, 	/* 041E0 */
+	0x21,  0x12,  0x11,  0x27,  0xD2,  0x45,  0x24,  0x42,  0x44,  0x27,  0xC6,  0xB0,  0x00,  0x2F,  0xF2,  0x11, 	/* 041F0 */
+	0x22,  0x92,  0xFD,  0x21,  0x32,  0x11,  0x2F,  0xD2,  0x11,  0x21,  0x02,  0x1E,  0x2E,  0x06,  0xB3,  0x10, 	/* 04200 */
+	0x2F,  0xEA,  0x28,  0xA4,  0x4A,  0xBA,  0xA0,  0x0A,  0xFE,  0xA2,  0x0A,  0x3C,  0xA4,  0x42,  0x04,  0x21, 	/* 04210 */
+	0x86,  0xB6,  0x50,  0x25,  0x12,  0x7D,  0x29,  0x12,  0xFF,  0x21,  0x12,  0x7D,  0x25,  0x52,  0x55,  0x25, 	/* 04220 */
+	0x52,  0x58,  0x21,  0x06,  0xB7,  0x7C,  0x24,  0x52,  0x45,  0x27,  0xD2,  0x51,  0x27,  0xD2,  0x55,  0x25, 	/* 04230 */
+	0x52,  0xD5,  0x2D,  0x42,  0x5C,  0x21,  0x06,  0xB8,  0x24,  0x81,  0x48,  0x15,  0x07,  0xFC,  0x0A,  0x0F, 	/* 04240 */
+	0xFE,  0x11,  0x03,  0xF8,  0xC9,  0x60,  0x90,  0x11,  0x02,  0x60,  0xB9,  0x04,  0x26,  0x92,  0x11,  0x22, 	/* 04250 */
+	0x92,  0xC5,  0x21,  0x12,  0xFF,  0x21,  0x92,  0x35,  0x25,  0x02,  0x90,  0x21,  0x06,  0xBA,  0x10,  0x2F, 	/* 04260 */
+	0xF2,  0x11,  0x27,  0xD2,  0x55,  0x25,  0x52,  0x55,  0x23,  0x92,  0x55,  0x29,  0x02,  0x10,  0x21,  0x06, 	/* 04270 */
+	0xBB,  0x10,  0x21,  0x12,  0xFF,  0x21,  0x12,  0x29,  0x26,  0x92,  0x15,  0x22,  0x52,  0x48,  0x21,  0x82, 	/* 04280 */
+	0x24,  0x2C,  0x06,  0x83,  0x44,  0x22,  0x92,  0xFD,  0x21,  0x52,  0x7D,  0x29,  0x12,  0xFD,  0x21,  0x52, 	/* 04290 */
+	0x35,  0x25,  0xC2,  0x90,  0x21,  0x06,  0x84,  0x00,  0x2F,  0xF2,  0x55,  0x25,  0x52,  0xA9,  0x25,  0x52, 	/* 042A0 */
+	0x55,  0x20,  0x12,  0xFD,  0x21,  0x02,  0x1E,  0x2F,  0x06,  0x87,  0x00,  0x27,  0x92,  0x49,  0x27,  0x92, 	/* 042B0 */
+	0x49,  0x27,  0x92,  0x49,  0x24,  0x92,  0x79,  0x22,  0x82,  0x44,  0x28,  0x06,  0x8A,  0x10,  0x29,  0x52, 	/* 042C0 */
+	0x59,  0x27,  0xD2,  0x45,  0x27,  0xD2,  0x45,  0x27,  0xD2,  0x45,  0x24,  0x42,  0x44,  0x24,  0xC6,  0x8B, 	/* 042D0 */
+	0x10,  0x2F,  0xD2,  0x11,  0x27,  0xD2,  0x45,  0x24,  0x52,  0x7D,  0x22,  0x92,  0x28,  0x24,  0x86,  0x48, 	/* 042E0 */
+	0x18,  0x7F,  0x8C,  0x10,  0x21,  0x12,  0xFF,  0x21,  0x12,  0xFD,  0x29,  0x52,  0x95,  0x2F,  0xD2,  0x39, 	/* 042F0 */
+	0x25,  0x42,  0x90,  0x21,  0x06,  0x8D,  0x21,  0x01,  0x20,  0xFF,  0xE0,  0x00,  0x7A,  0x44,  0xA4,  0x7A, 	/* 04300 */
+	0x44,  0xA4,  0x7A,  0x44,  0xA4,  0x48,  0x45,  0x8C,  0x8F,  0x88,  0x04,  0xBE,  0x50,  0xAF,  0x8A,  0x52, 	/* 04310 */
+	0xA5,  0x1A,  0xFC,  0xE5,  0x0B,  0x51,  0x25,  0x12,  0x92,  0x29,  0x4C,  0x94,  0x00,  0x27,  0xCA,  0x44, 	/* 04320 */
+	0xA7,  0xCA,  0x44,  0xA7,  0xCA,  0x20,  0xA7,  0xEA,  0xAA,  0xA4,  0xA2,  0x92,  0x22,  0xC6,  0x96,  0x10, 	/* 04330 */
+	0x21,  0x12,  0xFF,  0x24,  0x52,  0x29,  0x2F,  0xF2,  0x01,  0x27,  0xD2,  0x45,  0x24,  0x42,  0x7C,  0x24, 	/* 04340 */
+	0x06,  0x9B,  0x00,  0x2F,  0xEA,  0x82,  0xAC,  0x6A,  0xAA,  0xAF,  0xEA,  0x92,  0xAD,  0x6A,  0xD6,  0xAF, 	/* 04350 */
+	0xE2,  0x82,  0x28,  0x66,  0x9E,  0x10,  0x2F,  0xF2,  0x11,  0x22,  0x92,  0x45,  0x2F,  0xF2,  0x05,  0x27, 	/* 04360 */
+	0x52,  0x55,  0x27,  0x42,  0x04,  0x20,  0xC6,  0xA3,  0x10,  0x22,  0x92,  0x45,  0x2B,  0xB2,  0x11,  0x27, 	/* 04370 */
+	0xD2,  0x55,  0x27,  0xD2,  0x19,  0x21,  0x42,  0x22,  0x2C,  0x06,  0xA4,  0x10,  0x2F,  0xF2,  0x45,  0x23, 	/* 04380 */
+	0x92,  0x29,  0x2C,  0x72,  0x7D,  0x24,  0x52,  0x7D,  0x24,  0x42,  0x44,  0x28,  0xC6,  0xA5,  0x78,  0x20, 	/* 04390 */
+	0x92,  0x39,  0x20,  0x92,  0xFF,  0x21,  0x32,  0x55,  0x23,  0x92,  0x58,  0x29,  0x62,  0x10,  0x23,  0x06, 	/* 043A0 */
+	0xA9,  0x0C,  0x27,  0x0A,  0x10,  0xAF,  0xFA,  0x54,  0xAD,  0x6A,  0x54,  0xAD,  0x6A,  0x38,  0xA5,  0x42, 	/* 043B0 */
+	0x90,  0x21,  0x06,  0xAA,  0x20,  0x81,  0x10,  0xFF,  0xE6,  0xA4,  0x5A,  0x46,  0xA4,  0x5A,  0x44,  0x8C, 	/* 043C0 */
+	0xFF,  0xC0,  0x44,  0x18,  0x4E,  0x18,  0xAF,  0x00,  0x2F,  0xD2,  0x01,  0x27,  0xD2,  0x45,  0x27,  0xD2, 	/* 043D0 */
+	0x01,  0x2F,  0xD2,  0x95,  0x2F,  0xC2,  0x94,  0x2F,  0xC6,  0xB0,  0x0C,  0x27,  0x12,  0x11,  0x2F,  0xF2, 	/* 043E0 */
+	0x55,  0x2F,  0xF2,  0x55,  0x2F,  0xF2,  0x39,  0x25,  0x42,  0x92,  0x21,  0x06,  0xB1,  0x20,  0x03,  0x7E, 	/* 043F0 */
+	0x49,  0x2F,  0x52,  0x21,  0x2F,  0xB2,  0xA9,  0xAF,  0x97,  0x32,  0x22,  0xA2,  0x44,  0x28,  0x8C,  0xB2, 	/* 04400 */
+	0x10,  0x2F,  0xF2,  0x93,  0x27,  0xD2,  0x11,  0x27,  0xD2,  0x11,  0x2F,  0xF2,  0x01,  0x27,  0xC2,  0x44, 	/* 04410 */
+	0x27,  0xC6,  0xB3,  0x44,  0x2F,  0xEA,  0x44,  0xA1,  0x0A,  0x28,  0xA4,  0x4A,  0xBE,  0xA0,  0x0A,  0x7C, 	/* 04420 */
+	0xA4,  0x42,  0x44,  0x27,  0xC6,  0xB4,  0x10,  0x25,  0x52,  0x7D,  0x20,  0x12,  0xFF,  0x20,  0x12,  0x7D, 	/* 04430 */
+	0x24,  0x52,  0x7D,  0x24,  0x82,  0x3C,  0x2E,  0x06,  0xB5,  0x10,  0x22,  0x82,  0x45,  0x2F,  0xD2,  0x45, 	/* 04440 */
+	0x27,  0xD2,  0x45,  0x27,  0xD2,  0x41,  0x2B,  0xC2,  0xA4,  0x23,  0xC6,  0xBD,  0xFF,  0x22,  0x8A,  0xFE, 	/* 04450 */
+	0xAA,  0xAA,  0xFE,  0xA0,  0x0A,  0x7C,  0xA0,  0x0A,  0xFE,  0xA5,  0x42,  0x92,  0x23,  0x06,  0xBF,  0x54, 	/* 04460 */
+	0x2A,  0x92,  0x55,  0x27,  0xD2,  0x55,  0x27,  0xD2,  0x55,  0x2F,  0xF2,  0x39,  0x25,  0x42,  0x92,  0x21, 	/* 04470 */
+	0x06,  0x83,  0x10,  0x27,  0xD2,  0x15,  0x2F,  0xF2,  0x15,  0x2F,  0xF2,  0x55,  0x27,  0xD2,  0x55,  0x27, 	/* 04480 */
+	0xC2,  0x1E,  0x2E,  0x06,  0x87,  0x1C,  0x21,  0x12,  0x7D,  0x26,  0x52,  0x79,  0x24,  0x12,  0x7D,  0x25, 	/* 04490 */
+	0x32,  0x6D,  0x25,  0xC2,  0xAA,  0x21,  0x06,  0x88,  0x78,  0x84,  0xFE,  0x79,  0x44,  0x14,  0x7F,  0xEC, 	/* 044A0 */
+	0x88,  0x7B,  0xE0,  0x08,  0x7F,  0xE0,  0x82,  0x10,  0x26,  0x1C,  0x89,  0x20,  0x2D,  0xE2,  0xAB,  0x2A, 	/* 044B0 */
+	0xB2,  0xF5,  0x22,  0x92,  0xFD,  0x21,  0x12,  0xFD,  0x29,  0x02,  0x5C,  0x2F,  0x06,  0x8D,  0x20,  0x23, 	/* 044C0 */
+	0x12,  0x49,  0x2B,  0x52,  0x01,  0x2F,  0xD2,  0xB5,  0x2F,  0xD2,  0x49,  0x26,  0xD2,  0xB2,  0x29,  0x06, 	/* 044D0 */
+	0x91,  0x10,  0x2F,  0xEA,  0x28,  0xAF,  0x7A,  0x56,  0xAB,  0x5A,  0x44,  0xA7,  0xCA,  0x44,  0xA7,  0xC2, 	/* 044E0 */
+	0x44,  0x28,  0x46,  0x92,  0x20,  0x03,  0x7E,  0x48,  0xAF,  0x4A,  0x01,  0xAF,  0xDA,  0xB6,  0xAF,  0xD2, 	/* 044F0 */
+	0x51,  0x25,  0xA2,  0xA4,  0x28,  0x8C,  0x94,  0x20,  0x03,  0x7E,  0x48,  0xAF,  0x6A,  0x02,  0xAF,  0xDA, 	/* 04500 */
+	0xB4,  0xAF,  0xD6,  0x51,  0x35,  0xA2,  0xA4,  0x28,  0x8C,  0x9B,  0x04,  0x00,  0x40,  0x04,  0x07,  0xFC, 	/* 04510 */
+	0x04,  0x40,  0x44,  0x04,  0x40,  0x84,  0x08,  0x41,  0x04,  0x20,  0x44,  0x18,  0x9F,  0x01,  0x00,  0x10, 	/* 04520 */
+	0xF1,  0x02,  0xFE,  0x21,  0x22,  0x12,  0x21,  0x22,  0x92,  0x32,  0x2C,  0x22,  0x04,  0x20,  0x8C,  0xA0, 	/* 04530 */
+	0x20,  0x02,  0x00,  0x21,  0xEF,  0xD2,  0x25,  0x22,  0x52,  0x25,  0x22,  0x52,  0x25,  0x24,  0x52,  0x45, 	/* 04540 */
+	0xE9,  0x80,  0xA3,  0x04,  0x02,  0x48,  0x24,  0x44,  0xD2,  0x86,  0x21,  0x80,  0xE4,  0x07,  0xFC,  0x04, 	/* 04550 */
+	0x40,  0x84,  0x10,  0x46,  0x18,  0xA9,  0x01,  0x07,  0x90,  0x49,  0x04,  0xFE,  0x79,  0x24,  0x92,  0x49, 	/* 04560 */
+	0x27,  0x92,  0x49,  0x25,  0xE2,  0xE2,  0x20,  0x4C,  0xAA,  0x10,  0x0F,  0xBC,  0x28,  0x44,  0xA8,  0x31, 	/* 04570 */
+	0x02,  0xE8,  0xC4,  0x67,  0xFC,  0x04,  0x40,  0x44,  0x18,  0x46,  0x18,  0xAB,  0x10,  0x81,  0x08,  0x7C, 	/* 04580 */
+	0x81,  0x3E,  0x10,  0xAF,  0xEA,  0x10,  0xA1,  0x12,  0x29,  0x23,  0xD2,  0xC2,  0x20,  0x4C,  0xAC,  0x21, 	/* 04590 */
+	0x02,  0x10,  0x3D,  0x04,  0x7E,  0x45,  0x2F,  0x52,  0x55,  0x25,  0x52,  0x75,  0x20,  0x62,  0x04,  0x21, 	/* 045A0 */
+	0x8C,  0xAD,  0x01,  0x0F,  0x90,  0x29,  0x02,  0xFE,  0x49,  0x25,  0x92,  0x81,  0x27,  0x92,  0x4A,  0x24, 	/* 045B0 */
+	0xA2,  0x4C,  0x27,  0x8C,  0xB1,  0x0C,  0x87,  0x08,  0x40,  0x87,  0xFE,  0x50,  0xA5,  0xCA,  0x54,  0xA5, 	/* 045C0 */
+	0x4A,  0x55,  0x25,  0x52,  0xA6,  0x2C,  0xCC,  0xB4,  0x48,  0x42,  0x44,  0x14,  0x8F,  0xFE,  0x88,  0x28, 	/* 045D0 */
+	0x82,  0x7F,  0x80,  0x88,  0x08,  0x81,  0x08,  0x20,  0x84,  0x30,  0xB5,  0x04,  0x01,  0x50,  0x14,  0x83, 	/* 045E0 */
+	0xFC,  0x0A,  0x0F,  0xFE,  0x11,  0x02,  0x88,  0xFF,  0x60,  0x90,  0x11,  0x02,  0x60,  0xB9,  0x11,  0x01, 	/* 045F0 */
+	0x10,  0xFD,  0x02,  0xFE,  0x49,  0x28,  0xD2,  0x29,  0x21,  0x12,  0x12,  0x22,  0xA2,  0x44,  0x28,  0x8C, 	/* 04600 */
+	0xBC,  0x21,  0x02,  0x10,  0xFD,  0x02,  0x7E,  0x21,  0x2F,  0x92,  0x01,  0x27,  0x92,  0x4A,  0x24,  0xA2, 	/* 04610 */
+	0x4C,  0x27,  0x8C,  0xBE,  0x11,  0x01,  0x10,  0xFD,  0x02,  0x7E,  0x51,  0x2D,  0x12,  0x29,  0x24,  0x92, 	/* 04620 */
+	0x92,  0x22,  0xA2,  0x44,  0x28,  0x8C,  0x81,  0x01,  0x0F,  0xD0,  0x55,  0x05,  0x7E,  0xA9,  0x25,  0x52, 	/* 04630 */
+	0x01,  0x2F,  0xD2,  0x11,  0x21,  0x22,  0x1A,  0x2E,  0x4C,  0x83,  0x21,  0x0F,  0xD0,  0x21,  0x0F,  0xFE, 	/* 04640 */
+	0x85,  0x27,  0x92,  0x11,  0x21,  0xD2,  0xF1,  0x21,  0x22,  0x12,  0x23,  0x4C,  0x85,  0x11,  0x07,  0xD0, 	/* 04650 */
+	0x11,  0x07,  0xFE,  0x55,  0x25,  0x52,  0x7D,  0x23,  0x92,  0x35,  0x25,  0x22,  0x92,  0x21,  0x4C,  0x87, 	/* 04660 */
+	0x3F,  0x80,  0x90,  0x3F,  0xC2,  0x44,  0x3F,  0xC2,  0x44,  0x3F,  0xC0,  0x40,  0x7F,  0xE0,  0x82,  0x30, 	/* 04670 */
+	0x2C,  0x0C,  0x89,  0x20,  0x83,  0xC8,  0x48,  0x8F,  0xFE,  0x54,  0xA5,  0x4A,  0x7C,  0xA1,  0x92,  0x29, 	/* 04680 */
+	0x22,  0xAC,  0x48,  0x18,  0x7F,  0x8D,  0x11,  0x0F,  0xD0,  0x01,  0x07,  0xFE,  0x49,  0x24,  0x92,  0x79, 	/* 04690 */
+	0x21,  0x12,  0x59,  0x25,  0x62,  0x92,  0x23,  0x4C,  0x92,  0x51,  0x0F,  0x90,  0x51,  0x07,  0x7E,  0x21, 	/* 046A0 */
+	0x2F,  0x92,  0xA9,  0x2F,  0x92,  0x22,  0x2F,  0xA2,  0x24,  0x22,  0x8C,  0x95,  0x1D,  0x0F,  0x10,  0x13, 	/* 046B0 */
+	0xEF,  0xD2,  0x55,  0x27,  0xD2,  0x55,  0x27,  0xD2,  0x11,  0x27,  0xA2,  0x1E,  0x2E,  0x4C,  0x97,  0x3F, 	/* 046C0 */
+	0x82,  0x08,  0x3F,  0x82,  0x08,  0x3F,  0x87,  0x90,  0x4F,  0xE7,  0x92,  0x49,  0x27,  0x92,  0x5A,  0x2E, 	/* 046D0 */
+	0x4C,  0x98,  0x49,  0x0F,  0xD0,  0x49,  0x07,  0xFE,  0x49,  0x27,  0x92,  0x49,  0x2F,  0xD2,  0xA9,  0x2C, 	/* 046E0 */
+	0xD2,  0x82,  0x27,  0xCC,  0x99,  0x02,  0x0F,  0xBE,  0x0C,  0x85,  0x28,  0x21,  0x8F,  0xE6,  0x29,  0x02, 	/* 046F0 */
+	0xFC,  0x61,  0x4A,  0x24,  0x24,  0x46,  0x98,  0x9D,  0x01,  0x07,  0x54,  0x5F,  0xE5,  0x10,  0x7F,  0xE5, 	/* 04700 */
+	0x28,  0x55,  0x47,  0xFE,  0x52,  0x55,  0x24,  0x54,  0x4B,  0x98,  0x9E,  0x11,  0x05,  0x54,  0x2A,  0x84, 	/* 04710 */
+	0x44,  0xFF,  0xE8,  0x82,  0x08,  0x07,  0xFC,  0x08,  0x40,  0x84,  0x10,  0x46,  0x18,  0x9F,  0x11,  0x0F, 	/* 04720 */
+	0xFE,  0x11,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x8F,  0xFE,  0x24,  0x87,  0xFC,  0x88,  0xA3,  0x30, 	/* 04730 */
+	0xA0,  0xEE,  0x86,  0x68,  0xAA,  0x86,  0x7E,  0xAA,  0xA1,  0x0A,  0x28,  0xAC,  0x4A,  0x31,  0x2C,  0x92, 	/* 04740 */
+	0x32,  0x2C,  0x4C,  0xA2,  0x11,  0x07,  0x90,  0x17,  0xCF,  0xD4,  0x5B,  0xC9,  0x56,  0x7E,  0x20,  0x40, 	/* 04750 */
+	0x7F,  0xC0,  0x44,  0x08,  0x43,  0x18,  0xA3,  0x21,  0x0F,  0x90,  0x21,  0x07,  0xFE,  0x21,  0x2F,  0xD2, 	/* 04760 */
+	0x49,  0x27,  0x92,  0x49,  0x27,  0xA2,  0x2A,  0x2C,  0x4C,  0xA4,  0x29,  0x0F,  0xD0,  0x29,  0x07,  0xFE, 	/* 04770 */
+	0x55,  0x27,  0xD2,  0x11,  0x27,  0xD2,  0x11,  0x27,  0x92,  0x1E,  0x2F,  0x4C,  0xA6,  0x55,  0x0A,  0x90, 	/* 04780 */
+	0x55,  0x07,  0xFE,  0x55,  0x27,  0xD2,  0x55,  0x27,  0xD2,  0x19,  0x23,  0x52,  0x52,  0x29,  0x4C,  0xA7, 	/* 04790 */
+	0x41,  0x07,  0xD0,  0x49,  0x07,  0xFE,  0x91,  0x27,  0xD2,  0xD1,  0x27,  0xD2,  0x51,  0x27,  0xD2,  0x52, 	/* 047A0 */
+	0x27,  0xCC,  0xB2,  0x7D,  0x01,  0x10,  0xFF,  0xE5,  0x52,  0x7D,  0x25,  0x52,  0x7D,  0x21,  0x22,  0xFC, 	/* 047B0 */
+	0xC4,  0x08,  0x52,  0x48,  0x92,  0xB3,  0x0D,  0x0F,  0x10,  0x11,  0x0F,  0xFE,  0xD5,  0x2D,  0xD2,  0xB5, 	/* 047C0 */
+	0x2F,  0xD2,  0x11,  0x2F,  0xE2,  0x5A,  0x29,  0x4C,  0xB5,  0x00,  0x87,  0xE8,  0x54,  0x87,  0xFE,  0x7E, 	/* 047D0 */
+	0xA6,  0xAA,  0x7E,  0xA4,  0x8A,  0x7E,  0xAA,  0xB2,  0xBE,  0x22,  0x6C,  0xB8,  0x48,  0x8F,  0xE8,  0x48, 	/* 047E0 */
+	0x8E,  0xFE,  0xAA,  0xAE,  0xEA,  0x50,  0xAF,  0xCA,  0x51,  0x27,  0xD2,  0x52,  0x27,  0xCC,  0xB9,  0x10, 	/* 047F0 */
+	0x01,  0x00,  0x3F,  0xE2,  0x02,  0x40,  0x28,  0x02,  0x00,  0x20,  0x02,  0x00,  0x20,  0x02,  0x00,  0x40, 	/* 04800 */
+	0x18,  0xBA,  0x10,  0x01,  0x00,  0x1F,  0xC2,  0x04,  0x40,  0x49,  0x04,  0x08,  0x40,  0x44,  0x04,  0x40, 	/* 04810 */
+	0x04,  0x00,  0x40,  0x18,  0xBE,  0x20,  0x02,  0x00,  0x3F,  0xE2,  0x42,  0x44,  0x24,  0x42,  0x8A,  0x20, 	/* 04820 */
+	0x92,  0x17,  0xA7,  0x8A,  0x00,  0x20,  0x0C,  0xBF,  0x20,  0x02,  0x00,  0x3F,  0xE2,  0x92,  0x49,  0x28, 	/* 04830 */
+	0x92,  0x11,  0x21,  0x22,  0x22,  0x24,  0x42,  0x08,  0x21,  0x0C,  0x81,  0x10,  0x01,  0x00,  0x1F,  0xC1, 	/* 04840 */
+	0x24,  0x22,  0x45,  0x24,  0x8C,  0x40,  0x64,  0x09,  0xC1,  0x06,  0x20,  0x40,  0x18,  0x82,  0x10,  0x01, 	/* 04850 */
+	0x00,  0x1F,  0xE2,  0x02,  0x30,  0x25,  0x32,  0x9C,  0x21,  0x02,  0x11,  0x20,  0xF2,  0x00,  0x20,  0x0C, 	/* 04860 */
+	0x85,  0x10,  0x01,  0x00,  0x1F,  0xC2,  0x04,  0xDE,  0x40,  0x24,  0x02,  0x43,  0xE4,  0x20,  0x82,  0x02, 	/* 04870 */
+	0x20,  0x21,  0xFE,  0x86,  0x10,  0x01,  0x00,  0x3F,  0xE2,  0x92,  0x49,  0x2B,  0x92,  0x17,  0x21,  0x2A, 	/* 04880 */
+	0x22,  0x24,  0x42,  0x08,  0x40,  0x18,  0x88,  0x10,  0x01,  0x00,  0x3F,  0xE2,  0x02,  0x42,  0x2B,  0xAA, 	/* 04890 */
+	0x24,  0xA2,  0xAA,  0x30,  0xA3,  0xFA,  0x00,  0x40,  0x18,  0x8D,  0x10,  0x01,  0xFE,  0x25,  0x27,  0xFA, 	/* 048A0 */
+	0x84,  0x23,  0xFA,  0x24,  0xA3,  0xFA,  0x24,  0xA3,  0xFA,  0x24,  0xA0,  0x1C,  0x8F,  0x21,  0x02,  0x10, 	/* 048B0 */
+	0xFB,  0xE2,  0x22,  0x57,  0xAE,  0xAA,  0xFA,  0xA2,  0x3C,  0x3A,  0x04,  0xA2,  0x0A,  0x23,  0x1E,  0x90, 	/* 048C0 */
+	0x10,  0x01,  0xFE,  0x20,  0x27,  0xFA,  0x9F,  0x21,  0x12,  0x3F,  0xA2,  0x4A,  0x3F,  0xA2,  0x4A,  0x3F, 	/* 048D0 */
+	0xA0,  0x1C,  0x95,  0x20,  0x02,  0x00,  0x20,  0x02,  0x10,  0x22,  0x02,  0x40,  0x38,  0x0E,  0x00,  0x20, 	/* 048E0 */
+	0x02,  0x04,  0x20,  0x41,  0xFC,  0x96,  0x12,  0x01,  0x20,  0x12,  0x42,  0x24,  0x22,  0x86,  0x30,  0xA2, 	/* 048F0 */
+	0x02,  0x20,  0x22,  0x02,  0x22,  0x22,  0x22,  0x1E,  0x97,  0x12,  0x01,  0x20,  0x12,  0x01,  0x26,  0xF3, 	/* 04900 */
+	0x81,  0x20,  0x12,  0x01,  0x20,  0x32,  0x0D,  0x22,  0x12,  0x21,  0x1E,  0x99,  0x7A,  0x04,  0xA0,  0x7A, 	/* 04910 */
+	0x04,  0xA6,  0x7B,  0x80,  0x20,  0xFA,  0x01,  0x22,  0x5E,  0x27,  0x1E,  0x5C,  0x08,  0x3F,  0x9A,  0x00, 	/* 04920 */
+	0x07,  0xFF,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x7F,  0xF4, 	/* 04930 */
+	0x00,  0x9D,  0x00,  0x07,  0xFE,  0x42,  0x04,  0x20,  0x5F,  0xC5,  0x24,  0x52,  0x45,  0x24,  0x52,  0x84, 	/* 04940 */
+	0x20,  0x42,  0x07,  0xFE,  0xA0,  0x00,  0x07,  0xFE,  0x41,  0x84,  0xE0,  0x48,  0x04,  0xFC,  0x49,  0x04, 	/* 04950 */
+	0x90,  0x51,  0x06,  0x10,  0x41,  0x07,  0xFE,  0xA1,  0x00,  0x0F,  0xFE,  0x80,  0x0B,  0xFC,  0x84,  0x08, 	/* 04960 */
+	0x40,  0x9F,  0x88,  0x40,  0x84,  0x0B,  0xFC,  0x80,  0x0F,  0xFE,  0xA3,  0x00,  0x07,  0xFE,  0x40,  0x05, 	/* 04970 */
+	0xFC,  0x52,  0x45,  0xFC,  0x52,  0x45,  0xFC,  0x42,  0x04,  0x20,  0x42,  0x07,  0xFE,  0xAA,  0x00,  0x0F, 	/* 04980 */
+	0xFE,  0x8A,  0x08,  0xA0,  0xBB,  0xC8,  0xA0,  0xBB,  0xC8,  0xA0,  0xFB,  0xE9,  0x20,  0xA2,  0x0F,  0xFE, 	/* 04990 */
+	0xAF,  0x00,  0x0F,  0xFE,  0xA2,  0x89,  0x7E,  0xCD,  0x0A,  0x7C,  0x85,  0x09,  0x7C,  0x95,  0x0A,  0x7E, 	/* 049A0 */
+	0xA0,  0x0F,  0xFE,  0xB1,  0x00,  0x0F,  0xFE,  0x84,  0x09,  0xF8,  0x94,  0x8F,  0xFE,  0x90,  0x89,  0xF8, 	/* 049B0 */
+	0x90,  0x89,  0xF8,  0xB0,  0x4F,  0xFE,  0xB3,  0x00,  0x0F,  0xFE,  0x86,  0x08,  0x90,  0xB0,  0xCF,  0xB8, 	/* 049C0 */
+	0xAA,  0x8B,  0xB8,  0x91,  0x09,  0xA8,  0xA4,  0x4F,  0xFE,  0xB8,  0x00,  0x0F,  0xFE,  0x20,  0x02,  0x00, 	/* 049D0 */
+	0x20,  0x02,  0x00,  0x20,  0x02,  0x00,  0x20,  0x02,  0x00,  0x10,  0x00,  0xFC,  0xB9,  0x00,  0x0F,  0xFE, 	/* 049E0 */
+	0x92,  0x09,  0x20,  0x92,  0x4A,  0x24,  0xC1,  0xC8,  0x00,  0x80,  0x0F,  0xFE,  0x80,  0x00,  0x00,  0xBA, 	/* 049F0 */
+	0x00,  0x07,  0xFE,  0x40,  0x84,  0x08,  0x59,  0x04,  0x50,  0x42,  0x04,  0x50,  0x48,  0x85,  0x00,  0x7F, 	/* 04A00 */
+	0xE4,  0x00,  0xBB,  0x00,  0x07,  0xFE,  0x48,  0x04,  0xF8,  0x52,  0x06,  0x20,  0x5F,  0xC4,  0x20,  0x45, 	/* 04A10 */
+	0x04,  0x88,  0x50,  0x07,  0xFE,  0xBF,  0x00,  0x0F,  0xFE,  0x89,  0x0B,  0xFC,  0x89,  0x0F,  0xFC,  0x88, 	/* 04A20 */
+	0x09,  0xF8,  0xA8,  0x8C,  0xF8,  0x80,  0x0F,  0xFE,  0x80,  0x00,  0x0F,  0xFE,  0x40,  0x04,  0xF8,  0x48, 	/* 04A30 */
+	0x84,  0xF8,  0x40,  0x07,  0xDE,  0x65,  0x27,  0xDE,  0x40,  0x07,  0xFE,  0x81,  0x04,  0x00,  0x40,  0x04, 	/* 04A40 */
+	0x00,  0x40,  0xFF,  0xE0,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x83,  0x00, 	/* 04A50 */
+	0x80,  0x70,  0x7C,  0x00,  0x40,  0x04,  0x0F,  0xFE,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00, 	/* 04A60 */
+	0x40,  0x85,  0x24,  0x42,  0x44,  0x24,  0x42,  0x44,  0x24,  0x4F,  0xFE,  0x24,  0x42,  0x44,  0x24,  0x44, 	/* 04A70 */
+	0x44,  0x44,  0x48,  0x04,  0x86,  0x08,  0x00,  0x80,  0x7F,  0x01,  0x10,  0x11,  0x02,  0x12,  0x44,  0xE0, 	/* 04A80 */
+	0x40,  0xFF,  0xE0,  0x40,  0x04,  0x00,  0x40,  0x87,  0x01,  0x00,  0xD0,  0x71,  0x01,  0x10,  0x11,  0x0F, 	/* 04A90 */
+	0xFE,  0x11,  0x01,  0x10,  0x11,  0x02,  0x10,  0x21,  0x04,  0x10,  0x88,  0x10,  0x01,  0x00,  0x1F,  0xC2, 	/* 04AA0 */
+	0x20,  0x42,  0x00,  0x20,  0xFF,  0xE0,  0x20,  0x02,  0x00,  0x20,  0x02,  0x00,  0x20,  0x89,  0x04,  0x00, 	/* 04AB0 */
+	0x40,  0x7F,  0xC0,  0x40,  0x14,  0x81,  0x48,  0x10,  0x8F,  0xFE,  0x10,  0x82,  0x08,  0x20,  0x84,  0x08, 	/* 04AC0 */
+	0x8A,  0x04,  0x02,  0x48,  0x14,  0x81,  0x50,  0x7F,  0xC0,  0x40,  0x04,  0x0F,  0xFE,  0x04,  0x00,  0x40, 	/* 04AD0 */
+	0x04,  0x00,  0x40,  0x8D,  0x00,  0x07,  0xC2,  0x04,  0x20,  0x42,  0x04,  0x20,  0x42,  0x7F,  0xE4,  0x40, 	/* 04AE0 */
+	0x44,  0x04,  0x40,  0x44,  0x04,  0x7E,  0x91,  0x08,  0x03,  0xFC,  0x24,  0x43,  0xFC,  0x24,  0x43,  0xFC, 	/* 04AF0 */
+	0x12,  0x02,  0x20,  0xFF,  0xF0,  0x20,  0x02,  0x00,  0x20,  0x92,  0x04,  0x00,  0x40,  0x7F,  0xC1,  0x10, 	/* 04B00 */
+	0x11,  0x02,  0xA8,  0x44,  0x4F,  0xFE,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x93,  0x04,  0x00,  0x7C, 	/* 04B10 */
+	0x04,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x04,  0x0F,  0xFE,  0x04,  0x00,  0x40,  0x94, 	/* 04B20 */
+	0x42,  0x04,  0xFC,  0x42,  0x4F,  0x24,  0x44,  0x44,  0x98,  0x48,  0x87,  0xFE,  0x54,  0xA5,  0x4A,  0x65, 	/* 04B30 */
+	0x24,  0xE6,  0x97,  0x04,  0x0F,  0xFE,  0x04,  0x00,  0x40,  0x7F,  0xC5,  0x14,  0x4A,  0x45,  0xF4,  0x44, 	/* 04B40 */
+	0x45,  0xF4,  0x44,  0x44,  0x4C,  0x98,  0x24,  0x41,  0x28,  0x3F,  0x82,  0x48,  0x3F,  0x82,  0x48,  0x3F, 	/* 04B50 */
+	0x80,  0x40,  0xFF,  0xE0,  0x40,  0x04,  0x00,  0x40,  0x9A,  0x42,  0x45,  0xFE,  0x42,  0x05,  0xFC,  0xF2, 	/* 04B60 */
+	0x45,  0xFC,  0x52,  0x47,  0xFE,  0x40,  0x84,  0x88,  0x44,  0x84,  0x18,  0x9C,  0x08,  0x00,  0x80,  0x08, 	/* 04B70 */
+	0x00,  0xC0,  0x0A,  0x00,  0x90,  0x08,  0x80,  0x88,  0x08,  0x00,  0x80,  0x08,  0x00,  0x80,  0x9E,  0x04, 	/* 04B80 */
+	0x00,  0x40,  0xFF,  0xE0,  0x40,  0x06,  0x00,  0x50,  0x04,  0x80,  0x48,  0x04,  0x00,  0x40,  0x04,  0x00, 	/* 04B90 */
+	0x40,  0xA0,  0x04,  0x00,  0x40,  0x04,  0x00,  0x7E,  0x04,  0x00,  0x40,  0x04,  0x03,  0xF8,  0x20,  0x82, 	/* 04BA0 */
+	0x08,  0x20,  0x83,  0xF8,  0xA6,  0x11,  0x01,  0x10,  0x7D,  0x01,  0x10,  0xFD,  0x81,  0x14,  0x11,  0x27, 	/* 04BB0 */
+	0xD2,  0x11,  0x01,  0xF0,  0xE1,  0x00,  0x10,  0xA9,  0x00,  0x01,  0xFC,  0x10,  0x41,  0x04,  0x10,  0x41, 	/* 04BC0 */
+	0x04,  0x10,  0x41,  0x04,  0x13,  0x81,  0x00,  0x10,  0x01,  0x00,  0xAE,  0x01,  0xC3,  0xE0,  0x20,  0x03, 	/* 04BD0 */
+	0xFE,  0x20,  0x02,  0xF8,  0x28,  0x82,  0x88,  0x2B,  0x04,  0x80,  0x48,  0x28,  0x7E,  0xAF,  0x0C,  0x07, 	/* 04BE0 */
+	0x1E,  0x41,  0x24,  0x92,  0x49,  0x24,  0x92,  0x49,  0x25,  0x92,  0xE9,  0xC0,  0x90,  0x11,  0x02,  0x10, 	/* 04BF0 */
+	0xB0,  0x08,  0x07,  0x3E,  0x42,  0x24,  0x22,  0x7A,  0x24,  0x22,  0x42,  0x24,  0x22,  0x7A,  0xC4,  0x20, 	/* 04C00 */
+	0x02,  0x00,  0x20,  0xB1,  0x08,  0x01,  0xF0,  0x62,  0x00,  0x40,  0x3F,  0xE2,  0x00,  0x2F,  0x82,  0x88, 	/* 04C10 */
+	0x48,  0x84,  0x9A,  0x88,  0x20,  0x7E,  0xB3,  0x00,  0x07,  0xDE,  0x45,  0x27,  0xD2,  0x45,  0x24,  0x52, 	/* 04C20 */
+	0x7D,  0x25,  0x12,  0x49,  0xC7,  0x50,  0xC5,  0x00,  0x10,  0xB4,  0x20,  0x02,  0x1E,  0xFD,  0x22,  0x12, 	/* 04C30 */
+	0x21,  0x2F,  0xD2,  0x21,  0x22,  0x92,  0x4D,  0xC7,  0x50,  0xC5,  0x00,  0x10,  0xB5,  0x0C,  0x07,  0x1E, 	/* 04C40 */
+	0x45,  0x26,  0x52,  0x55,  0xA4,  0x56,  0x45,  0x25,  0x92,  0xE9,  0xC0,  0x90,  0x11,  0x02,  0x10,  0xB7, 	/* 04C50 */
+	0x04,  0x02,  0x48,  0x24,  0x47,  0xFC,  0x0A,  0x0F,  0xFE,  0x11,  0x03,  0xF8,  0xD1,  0x61,  0x70,  0x10, 	/* 04C60 */
+	0x40,  0xFC,  0xB8,  0x20,  0x03,  0xDE,  0x51,  0x29,  0x12,  0x7F,  0x21,  0x12,  0x5D,  0x25,  0x12,  0x51, 	/* 04C70 */
+	0xC5,  0xD0,  0xE1,  0x00,  0x10,  0xBB,  0x10,  0x02,  0x9E,  0x25,  0x25,  0x52,  0x91,  0x22,  0x92,  0x45, 	/* 04C80 */
+	0x2F,  0xB2,  0x49,  0xC4,  0x90,  0x49,  0x07,  0x90,  0xBF,  0x20,  0x0C,  0xEE,  0x8A,  0xAA,  0xEA,  0xAA, 	/* 04C90 */
+	0xAA,  0xAA,  0xAE,  0xAA,  0x8A,  0xEC,  0xE2,  0xA8,  0x5D,  0x88,  0x08,  0x82,  0x00,  0x03,  0xFE,  0x20, 	/* 04CA0 */
+	0x02,  0x00,  0x20,  0x02,  0x00,  0x20,  0x02,  0x00,  0x20,  0x04,  0x00,  0x40,  0x08,  0x00,  0x84,  0x00, 	/* 04CB0 */
+	0x03,  0xFE,  0x20,  0x02,  0x00,  0x2F,  0x82,  0x88,  0x28,  0x82,  0x88,  0x2B,  0x04,  0x82,  0x48,  0x28, 	/* 04CC0 */
+	0x7E,  0x96,  0x00,  0x07,  0xFE,  0x4A,  0x84,  0x88,  0x7F,  0x44,  0xA4,  0x4C,  0xA4,  0xD2,  0x4C,  0x45, 	/* 04CD0 */
+	0x48,  0x95,  0x2A,  0x3E,  0x98,  0x00,  0x07,  0xFE,  0x40,  0x05,  0xFC,  0x52,  0x45,  0xFC,  0x52,  0x45, 	/* 04CE0 */
+	0xFC,  0x42,  0x09,  0xFC,  0x82,  0x07,  0xFE,  0x9A,  0x00,  0x07,  0xFE,  0x50,  0x85,  0xF8,  0x50,  0x85, 	/* 04CF0 */
+	0xF8,  0x40,  0x05,  0xF8,  0x41,  0x07,  0xFE,  0x82,  0x00,  0x60,  0x9F,  0x00,  0x03,  0xFE,  0x22,  0x02, 	/* 04D00 */
+	0xFC,  0x28,  0x42,  0xFC,  0x28,  0x42,  0xFC,  0x42,  0x85,  0x24,  0xA2,  0x20,  0x60,  0xA0,  0x00,  0x07, 	/* 04D10 */
+	0xFE,  0x40,  0x05,  0xE2,  0x52,  0xA5,  0xEA,  0x52,  0xA5,  0xEA,  0x52,  0xA5,  0xEA,  0x94,  0x2A,  0x26, 	/* 04D20 */
+	0xA5,  0x00,  0x07,  0xFE,  0x65,  0x05,  0xA0,  0x7F,  0xE4,  0xAA,  0x6A,  0xC6,  0xA8,  0x7E,  0xC4,  0x94, 	/* 04D30 */
+	0x89,  0x29,  0x21,  0xA6,  0x00,  0x07,  0xFE,  0x40,  0x07,  0xFC,  0x44,  0x05,  0xF8,  0x5F,  0x85,  0x08, 	/* 04D40 */
+	0x5F,  0x86,  0x88,  0x87,  0x0B,  0x8E,  0xA8,  0x00,  0x07,  0xFE,  0x40,  0x07,  0xE4,  0x40,  0x47,  0xFF, 	/* 04D50 */
+	0x64,  0x47,  0xE4,  0x65,  0x45,  0x84,  0x8E,  0x4B,  0x0C,  0xA9,  0x7F,  0xE4,  0x00,  0x5D,  0xE5,  0x54, 	/* 04D60 */
+	0x5D,  0x45,  0x7E,  0x5C,  0x85,  0x18,  0x59,  0x85,  0x68,  0x9A,  0xA3,  0x46,  0xAD,  0x00,  0x07,  0xFE, 	/* 04D70 */
+	0x54,  0xC5,  0xCA,  0x40,  0x85,  0xFE,  0x54,  0x85,  0xC8,  0x55,  0x45,  0xD4,  0x95,  0x49,  0x62,  0xAE, 	/* 04D80 */
+	0x00,  0x07,  0xFE,  0x54,  0x47,  0xF8,  0x55,  0x05,  0xDE,  0x55,  0x45,  0xD4,  0x55,  0x47,  0xF4,  0x9A, 	/* 04D90 */
+	0x42,  0x44,  0xB0,  0x00,  0x07,  0xFE,  0x59,  0x07,  0x50,  0x51,  0xE7,  0xE4,  0x65,  0x47,  0xD8,  0x6C, 	/* 04DA0 */
+	0x87,  0xD8,  0xA6,  0x42,  0xC2,  0xB3,  0x24,  0x41,  0x28,  0x7F,  0xE4,  0x10,  0x5F,  0x04,  0x9E,  0x7E, 	/* 04DB0 */
+	0x45,  0x54,  0x5E,  0x85,  0x4C,  0xBD,  0x20,  0x62,  0xB6,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x08, 	/* 04DC0 */
+	0x00,  0x80,  0x09,  0x01,  0x08,  0x10,  0x42,  0x3E,  0xFC,  0x20,  0x02,  0xBB,  0x04,  0x00,  0x40,  0x7F, 	/* 04DD0 */
+	0xC0,  0x40,  0x04,  0x0F,  0xFE,  0x04,  0x00,  0x90,  0x08,  0x81,  0x38,  0x7C,  0x40,  0x04,  0x82,  0x0A, 	/* 04DE0 */
+	0x01,  0x10,  0x7E,  0x80,  0x40,  0xFF,  0xE1,  0x30,  0x2C,  0x87,  0x34,  0x8C,  0xA3,  0x10,  0x06,  0x03, 	/* 04DF0 */
+	0x80,  0x83,  0x08,  0x01,  0x10,  0x7F,  0xC2,  0x08,  0x51,  0x2F,  0x5E,  0x0E,  0x03,  0x98,  0xC6,  0x61, 	/* 04E00 */
+	0x90,  0x06,  0x07,  0x80,  0x88,  0x00,  0x03,  0xF8,  0x00,  0x81,  0x08,  0x10,  0x80,  0x90,  0x09,  0x00, 	/* 04E10 */
+	0x60,  0x06,  0x00,  0x90,  0x30,  0x8C,  0x06,  0x89,  0x00,  0x07,  0xFC,  0x08,  0x40,  0x48,  0x14,  0x81, 	/* 04E20 */
+	0x10,  0x09,  0x00,  0xA0,  0x04,  0x00,  0xA0,  0x31,  0x8C,  0x06,  0x8A,  0x00,  0x03,  0xF8,  0x08,  0x80, 	/* 04E30 */
+	0x90,  0x09,  0xC1,  0x44,  0x14,  0x41,  0x28,  0x21,  0x82,  0x18,  0x46,  0x49,  0x82,  0x8B,  0x08,  0x00, 	/* 04E40 */
+	0x80,  0xFF,  0xE0,  0x80,  0x08,  0x01,  0xF8,  0x10,  0x81,  0x50,  0x22,  0x04,  0x70,  0x98,  0x86,  0x06, 	/* 04E50 */
+	0x8C,  0x00,  0x0F,  0xBE,  0x08,  0x20,  0xA2,  0x49,  0x42,  0x94,  0x10,  0x81,  0x88,  0x25,  0x42,  0x24, 	/* 04E60 */
+	0x44,  0x28,  0x81,  0x8D,  0x00,  0x03,  0xFC,  0x20,  0x02,  0x00,  0x3F,  0x82,  0x08,  0x29,  0x02,  0x90, 	/* 04E70 */
+	0x46,  0x04,  0x60,  0x99,  0x06,  0x0C,  0x8E,  0x08,  0x04,  0xFC,  0x48,  0x44,  0xC4,  0x4C,  0x44,  0xA8, 	/* 04E80 */
+	0x4A,  0x84,  0x90,  0x79,  0x0C,  0xA8,  0x0C,  0x40,  0x82,  0x94,  0x20,  0x02,  0x7C,  0x38,  0x42,  0x44, 	/* 04E90 */
+	0x22,  0x8F,  0xA8,  0x21,  0x03,  0x10,  0xAA,  0x8A,  0xA8,  0xA4,  0x46,  0x82,  0x96,  0x00,  0x0F,  0xC0, 	/* 04EA0 */
+	0x4B,  0xE4,  0x82,  0x7A,  0x24,  0x94,  0x79,  0x44,  0x88,  0x79,  0x8C,  0xA4,  0x0C,  0x20,  0x81,  0x97, 	/* 04EB0 */
+	0x01,  0xC7,  0xE4,  0x24,  0x41,  0x28,  0xFF,  0xE8,  0x02,  0xBF,  0x21,  0x10,  0x0A,  0x00,  0x60,  0x19, 	/* 04EC0 */
+	0x06,  0x0C,  0x99,  0x10,  0x01,  0x3E,  0x28,  0x24,  0xA2,  0x7E,  0x2A,  0x54,  0x21,  0x4F,  0x88,  0x20, 	/* 04ED0 */
+	0x8A,  0x94,  0xAA,  0x26,  0x41,  0x9B,  0x20,  0x0A,  0xBE,  0x6A,  0x07,  0x20,  0xFF,  0xE2,  0x22,  0x3A, 	/* 04EE0 */
+	0x4E,  0x54,  0x45,  0x84,  0x88,  0x89,  0x40,  0x62,  0x9F,  0x14,  0x0E,  0x5E,  0x84,  0x2F,  0x5E,  0x84, 	/* 04EF0 */
+	0x2F,  0xFE,  0x04,  0x07,  0xFC,  0x19,  0x80,  0x60,  0x1B,  0x06,  0x0C,  0xA1,  0x38,  0x02,  0x3E,  0xFC, 	/* 04F00 */
+	0x2A,  0x52,  0x71,  0x48,  0xD4,  0x20,  0x87,  0x88,  0xCC,  0xC7,  0x94,  0x4A,  0x27,  0xC1,  0xA2,  0x0A, 	/* 04F10 */
+	0x02,  0xA8,  0xFF,  0xE1,  0x10,  0x7F,  0xC0,  0x40,  0xFF,  0xE4,  0xF8,  0x7A,  0x84,  0x90,  0xFA,  0x80, 	/* 04F20 */
+	0xC6,  0xA3,  0x00,  0x00,  0x00,  0x7F,  0xE4,  0x02,  0x40,  0x24,  0x02,  0x40,  0x24,  0x02,  0x40,  0x24, 	/* 04F30 */
+	0x02,  0x7F,  0xE4,  0x02,  0xA4,  0x04,  0x00,  0x40,  0x04,  0x0F,  0xFE,  0x04,  0x00,  0x40,  0x04,  0x03, 	/* 04F40 */
+	0xF8,  0x20,  0x82,  0x08,  0x20,  0x83,  0xF8,  0xA5,  0x10,  0x01,  0x00,  0x3F,  0xE2,  0x02,  0x5F,  0x29, 	/* 04F50 */
+	0x12,  0x11,  0x21,  0x12,  0x1F,  0x20,  0x02,  0x00,  0x20,  0x0C,  0xA8,  0x00,  0x00,  0xFE,  0xF1,  0x29, 	/* 04F60 */
+	0x12,  0x91,  0x29,  0x12,  0x91,  0x29,  0x12,  0x92,  0x2F,  0x22,  0x04,  0x20,  0x8C,  0xA9,  0x00,  0x00, 	/* 04F70 */
+	0x3E,  0x7A,  0x24,  0xA2,  0x4A,  0x24,  0xA2,  0x4A,  0x24,  0xA2,  0x7A,  0x24,  0x2C,  0x02,  0x00,  0x20, 	/* 04F80 */
+	0xAA,  0x00,  0x07,  0xF8,  0x40,  0x84,  0x08,  0x40,  0x84,  0x08,  0x7F,  0x80,  0x00,  0x11,  0x01,  0x08, 	/* 04F90 */
+	0x20,  0x4C,  0x04,  0xAB,  0x00,  0x8F,  0x48,  0x94,  0x89,  0x48,  0x94,  0x89,  0x48,  0x94,  0x89,  0x4E, 	/* 04FA0 */
+	0xF7,  0x88,  0xC8,  0x00,  0x80,  0x08,  0xAC,  0x00,  0x07,  0xFC,  0x08,  0x40,  0x84,  0x10,  0x42,  0x18, 	/* 04FB0 */
+	0x40,  0x03,  0xF8,  0x20,  0x82,  0x08,  0x20,  0x83,  0xF8,  0xAD,  0x07,  0x8F,  0x08,  0x94,  0x89,  0x48, 	/* 04FC0 */
+	0x94,  0x89,  0x48,  0x94,  0x89,  0x48,  0xF8,  0x80,  0x84,  0x10,  0x42,  0x02,  0xAE,  0x00,  0x00,  0xFE, 	/* 04FD0 */
+	0xF1,  0x09,  0x10,  0x91,  0x09,  0x10,  0x91,  0x09,  0x10,  0x91,  0x0F,  0x10,  0x01,  0x00,  0x30,  0xAF, 	/* 04FE0 */
+	0x00,  0x0F,  0xFE,  0x00,  0x83,  0xE8,  0x22,  0x82,  0x28,  0x22,  0x83,  0xE8,  0x20,  0x80,  0x08,  0x00, 	/* 04FF0 */
+	0x80,  0x18,  0xB0,  0x04,  0x00,  0x40,  0x08,  0x81,  0x04,  0x23,  0xCF,  0xC2,  0x00,  0x23,  0xFC,  0x20, 	/* 05000 */
+	0x42,  0x04,  0x20,  0x43,  0xFC,  0xB1,  0x04,  0x00,  0x40,  0xF4,  0x49,  0x44,  0x94,  0x89,  0x50,  0x96, 	/* 05010 */
+	0x09,  0xC0,  0x94,  0x0F,  0x42,  0x04,  0x20,  0x3E,  0xB2,  0x04,  0x00,  0x40,  0x7F,  0xC4,  0x44,  0x44, 	/* 05020 */
+	0x47,  0xFC,  0x24,  0x01,  0x40,  0x0C,  0x00,  0xA0,  0x31,  0x8C,  0x06,  0xB3,  0x08,  0x00,  0x80,  0x08, 	/* 05030 */
+	0x0F,  0xFE,  0x08,  0x00,  0x80,  0x10,  0x01,  0xFC,  0x30,  0x45,  0x04,  0x90,  0x41,  0xFC,  0xB6,  0x01, 	/* 05040 */
+	0x00,  0x10,  0xF1,  0x09,  0x10,  0x9F,  0xE9,  0x10,  0x91,  0x09,  0x10,  0x91,  0x0F,  0x10,  0x01,  0x00, 	/* 05050 */
+	0x10,  0xB7,  0x00,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x00,  0x0F,  0xFE,  0x10,  0x01,  0xF8,  0x20,  0x80, 	/* 05060 */
+	0x08,  0x00,  0x80,  0x30,  0xB8,  0x00,  0x07,  0xFE,  0x00,  0x23,  0xFA,  0x00,  0x21,  0xF2,  0x11,  0x21, 	/* 05070 */
+	0x12,  0x1F,  0x20,  0x02,  0x00,  0x20,  0x0C,  0xBA,  0x03,  0x00,  0x10,  0xF1,  0x09,  0x10,  0x91,  0x09, 	/* 05080 */
+	0x10,  0x93,  0x09,  0x28,  0xF4,  0x80,  0x44,  0x08,  0x43,  0x02,  0x81,  0x00,  0x00,  0xFC,  0xF1,  0x09, 	/* 05090 */
+	0x10,  0x91,  0x09,  0xFE,  0x91,  0x09,  0x10,  0xF1,  0x00,  0x10,  0x01,  0x00,  0x30,  0x83,  0x04,  0x00, 	/* 050A0 */
+	0x40,  0xF7,  0xE9,  0x80,  0x90,  0x09,  0xFC,  0x90,  0x89,  0x30,  0xF4,  0x00,  0x82,  0x08,  0x20,  0x7E, 	/* 050B0 */
+	0x84,  0x08,  0x00,  0xF8,  0x10,  0x82,  0x90,  0x46,  0x00,  0x90,  0x10,  0x83,  0xFC,  0xD0,  0xA1,  0x08, 	/* 050C0 */
+	0x10,  0x81,  0xF8,  0x88,  0x04,  0x00,  0x40,  0x0A,  0x01,  0x10,  0x3F,  0x8C,  0x06,  0x00,  0x03,  0xF8, 	/* 050D0 */
+	0x20,  0x82,  0x08,  0x20,  0x83,  0xF8,  0x89,  0x04,  0x00,  0x40,  0xFF,  0xE0,  0x40,  0x04,  0x07,  0xFC, 	/* 050E0 */
+	0x00,  0x03,  0xF8,  0x20,  0x82,  0x08,  0x20,  0x83,  0xF8,  0x8A,  0x00,  0x03,  0xF8,  0x20,  0x82,  0x08, 	/* 050F0 */
+	0x3F,  0x80,  0x40,  0x7F,  0xC4,  0x44,  0x44,  0x44,  0x44,  0x45,  0x80,  0x40,  0x8B,  0x00,  0x80,  0x08, 	/* 05100 */
+	0xF0,  0x89,  0xFE,  0x90,  0x89,  0x48,  0x92,  0x89,  0x28,  0x90,  0x8F,  0x08,  0x00,  0x80,  0x18,  0x8C, 	/* 05110 */
+	0x00,  0x07,  0xFE,  0x40,  0x24,  0x02,  0x5F,  0xA4,  0x02,  0x5F,  0xA5,  0x0A,  0x50,  0xA5,  0xFA,  0x40, 	/* 05120 */
+	0x24,  0x06,  0x8D,  0x04,  0x00,  0x40,  0x0F,  0x81,  0x08,  0x29,  0x04,  0x60,  0x04,  0x00,  0xFE,  0x38, 	/* 05130 */
+	0x2C,  0x82,  0x08,  0x20,  0xFE,  0x8E,  0x01,  0xC3,  0xE0,  0x20,  0x02,  0x00,  0x3F,  0xE2,  0x00,  0x20, 	/* 05140 */
+	0x02,  0xFC,  0x48,  0x44,  0x84,  0x88,  0x40,  0xFC,  0x8F,  0x04,  0x07,  0xFE,  0x04,  0x03,  0xFC,  0x24, 	/* 05150 */
+	0x42,  0x44,  0x3F,  0xC1,  0x40,  0x0C,  0x00,  0xA0,  0x31,  0x8C,  0x06,  0x90,  0x01,  0x00,  0x10,  0xF1, 	/* 05160 */
+	0x09,  0x10,  0x9F,  0xE9,  0x10,  0x91,  0x09,  0x10,  0xF1,  0x00,  0x10,  0x1F,  0xE0,  0x00,  0x91,  0x04, 	/* 05170 */
+	0x00,  0x80,  0x10,  0x07,  0xFE,  0x40,  0x24,  0x02,  0x4F,  0x24,  0x92,  0x49,  0x24,  0xF2,  0x40,  0x24, 	/* 05180 */
+	0x06,  0x9B,  0x00,  0x07,  0xF8,  0x08,  0x8F,  0xFE,  0x08,  0x80,  0x88,  0x7F,  0x81,  0x00,  0x3F,  0x85, 	/* 05190 */
+	0x08,  0x90,  0x81,  0xF8,  0x9D,  0x04,  0x0F,  0xFE,  0x21,  0x01,  0x20,  0x0C,  0x00,  0xA0,  0x31,  0x8C, 	/* 051A0 */
+	0x06,  0x3F,  0x82,  0x08,  0x20,  0x83,  0xF8,  0x9F,  0x02,  0x00,  0x30,  0xE5,  0x0A,  0x48,  0xAF,  0xCB, 	/* 051B0 */
+	0x02,  0xA0,  0x0A,  0xFC,  0xA0,  0x8E,  0x08,  0x01,  0x00,  0x20,  0xA0,  0x02,  0x0E,  0x28,  0xA2,  0x4A, 	/* 051C0 */
+	0x20,  0xBF,  0xEA,  0x20,  0xA2,  0x0A,  0x50,  0xE5,  0x00,  0x88,  0x10,  0x46,  0x02,  0xA6,  0x00,  0x07, 	/* 051D0 */
+	0xFE,  0x06,  0x00,  0xD8,  0x34,  0x4C,  0x42,  0x04,  0x03,  0xFC,  0x20,  0x42,  0x04,  0x20,  0x43,  0xFC, 	/* 051E0 */
+	0xA9,  0x03,  0x00,  0x90,  0xE9,  0x0A,  0x88,  0xB0,  0x4B,  0xFA,  0xA4,  0x8A,  0x48,  0xE4,  0x80,  0x88, 	/* 051F0 */
+	0x08,  0x81,  0x30,  0xAB,  0x04,  0x00,  0xA0,  0x11,  0x02,  0xE8,  0xC0,  0x67,  0xF8,  0x02,  0x00,  0x40, 	/* 05200 */
+	0x3F,  0x82,  0x08,  0x20,  0x83,  0xF8,  0xAC,  0x00,  0xCF,  0x70,  0x94,  0x09,  0x40,  0x97,  0xE9,  0x48, 	/* 05210 */
+	0x94,  0x89,  0x48,  0xF4,  0x80,  0x88,  0x08,  0x81,  0x08,  0xAD,  0x02,  0x0F,  0x20,  0x9F,  0xE9,  0x00, 	/* 05220 */
+	0x97,  0x89,  0x48,  0x94,  0x89,  0x48,  0xF4,  0x80,  0x4A,  0x08,  0xA1,  0x06,  0xAE,  0x02,  0x00,  0x28, 	/* 05230 */
+	0xF2,  0x49,  0x46,  0x9F,  0xA9,  0x28,  0x92,  0x89,  0x28,  0x94,  0x8F,  0x4A,  0x08,  0xA1,  0x06,  0xB6, 	/* 05240 */
+	0x01,  0x00,  0x10,  0xEF,  0xEA,  0x92,  0xA9,  0x2A,  0x92,  0xAA,  0xAA,  0xC6,  0xE8,  0x20,  0x82,  0x08, 	/* 05250 */
+	0x20,  0x86,  0xB8,  0x00,  0x00,  0xFC,  0xF2,  0x49,  0x28,  0x92,  0xE9,  0x22,  0x93,  0x29,  0x54,  0xF4, 	/* 05260 */
+	0x80,  0x4C,  0x09,  0x21,  0x61,  0xB9,  0x02,  0x00,  0x20,  0xF3,  0xE9,  0x42,  0x95,  0x49,  0x90,  0x91, 	/* 05270 */
+	0x09,  0x10,  0xF2,  0x80,  0x28,  0x04,  0x41,  0x82,  0xBB,  0x04,  0x00,  0x40,  0xE7,  0xEA,  0x6A,  0xAA, 	/* 05280 */
+	0xAA,  0xAA,  0xB2,  0xAA,  0x52,  0xA5,  0x2E,  0x92,  0x02,  0x20,  0x4C,  0xBC,  0x00,  0x81,  0xF8,  0xE2, 	/* 05290 */
+	0x8A,  0x48,  0xA4,  0x8A,  0x78,  0xBC,  0x8A,  0x48,  0xA4,  0x8E,  0x4A,  0x04,  0xA0,  0xC6,  0xBD,  0x01, 	/* 052A0 */
+	0x00,  0x50,  0xE5,  0x0A,  0x7E,  0xA9,  0x0B,  0x10,  0xBF,  0xEA,  0x10,  0xA1,  0x0E,  0x10,  0x01,  0x00, 	/* 052B0 */
+	0x10,  0xBE,  0x7F,  0xC0,  0x80,  0x08,  0x07,  0xF8,  0x10,  0x81,  0x08,  0xFF,  0xE0,  0x00,  0x3F,  0x82, 	/* 052C0 */
+	0x08,  0x20,  0x83,  0xF8,  0x80,  0x00,  0x00,  0xFE,  0xF4,  0x89,  0x48,  0x94,  0x89,  0xFE,  0x92,  0x89, 	/* 052D0 */
+	0x28,  0xF4,  0x80,  0x88,  0x10,  0x80,  0x18,  0x82,  0x00,  0x03,  0xF8,  0x20,  0x82,  0x08,  0x3F,  0x80, 	/* 052E0 */
+	0x40,  0x08,  0x07,  0xFC,  0x40,  0x44,  0x04,  0x40,  0x47,  0xFC,  0x86,  0x00,  0x03,  0xF8,  0x20,  0x82, 	/* 052F0 */
+	0x08,  0x3F,  0x80,  0x40,  0xFF,  0xE0,  0xE0,  0x35,  0x8C,  0x46,  0x04,  0x00,  0x40,  0x88,  0x00,  0x03, 	/* 05300 */
+	0xF8,  0x20,  0x82,  0x08,  0x3F,  0x80,  0x00,  0x7F,  0xC0,  0x40,  0x3F,  0x80,  0x40,  0x04,  0x0F,  0xFE, 	/* 05310 */
+	0x89,  0x1F,  0x85,  0x08,  0x50,  0x85,  0xF8,  0x40,  0x07,  0xF8,  0x40,  0x80,  0x08,  0xFF,  0xE1,  0x20, 	/* 05320 */
+	0x21,  0x8C,  0x04,  0x8A,  0x04,  0x02,  0x40,  0x24,  0x03,  0xFC,  0x24,  0x04,  0x40,  0xFF,  0xE0,  0x00, 	/* 05330 */
+	0x3F,  0x82,  0x08,  0x20,  0x83,  0xF8,  0x8E,  0x00,  0x00,  0x7E,  0xF4,  0x29,  0x42,  0x97,  0xE9,  0x60, 	/* 05340 */
+	0x95,  0x09,  0x50,  0xF8,  0x80,  0x88,  0x10,  0x42,  0x02,  0x91,  0x01,  0xC7,  0xE0,  0x04,  0x00,  0x40, 	/* 05350 */
+	0xFF,  0xE0,  0xA0,  0x11,  0x03,  0xF8,  0xD1,  0x61,  0x10,  0x11,  0x01,  0xF0,  0x9F,  0x01,  0x00,  0x10, 	/* 05360 */
+	0xEF,  0xEA,  0x10,  0xA1,  0x0A,  0xA4,  0xA4,  0x4A,  0x28,  0xA1,  0x4E,  0x62,  0x1F,  0xE0,  0x02,  0xA8, 	/* 05370 */
+	0x00,  0x07,  0xFC,  0x44,  0x45,  0xF4,  0x44,  0x47,  0xFC,  0x40,  0x45,  0xF4,  0x51,  0x45,  0xF4,  0x80, 	/* 05380 */
+	0x48,  0x0C,  0xAA,  0x00,  0x00,  0x7C,  0xF4,  0x49,  0x44,  0x94,  0x49,  0x7C,  0x92,  0x89,  0x28,  0xF4, 	/* 05390 */
+	0x80,  0x4A,  0x08,  0xA3,  0x06,  0xB0,  0x12,  0x05,  0x26,  0x5F,  0x85,  0x20,  0x52,  0x25,  0xE2,  0xE1, 	/* 053A0 */
+	0xE0,  0x00,  0x3F,  0x82,  0x08,  0x20,  0x83,  0xF8,  0xB1,  0x00,  0xC0,  0xF0,  0xEA,  0x8A,  0xA8,  0xAA, 	/* 053B0 */
+	0x8A,  0xA8,  0xAA,  0x8A,  0xA8,  0xEB,  0x41,  0x2C,  0x1F,  0xA2,  0x09,  0xB3,  0x02,  0x00,  0x20,  0xEF, 	/* 053C0 */
+	0xCA,  0x20,  0xA2,  0x0B,  0xFE,  0xA2,  0x0A,  0x70,  0xAA,  0x8F,  0x26,  0x02,  0x00,  0x20,  0xB5,  0x00, 	/* 053D0 */
+	0x01,  0xFE,  0xE0,  0x4A,  0xF4,  0xA9,  0x4A,  0x94,  0xA9,  0x4A,  0xF4,  0xA8,  0x4E,  0x04,  0x00,  0x40, 	/* 053E0 */
+	0x0C,  0xB6,  0x04,  0x00,  0x5E,  0xE4,  0x2B,  0xF2,  0xAA,  0xAA,  0xAA,  0xAA,  0xAB,  0xA4,  0xA4,  0x4E, 	/* 053F0 */
+	0xAA,  0x11,  0x22,  0x21,  0xB7,  0x00,  0x00,  0xFE,  0xE9,  0x2A,  0xFE,  0xA9,  0x2A,  0x92,  0xAF,  0xEA, 	/* 05400 */
+	0x90,  0xE1,  0x08,  0x10,  0x01,  0x00,  0x10,  0xBB,  0x01,  0x00,  0x10,  0xEF,  0xEA,  0x92,  0xAF,  0xEA, 	/* 05410 */
+	0x92,  0xA9,  0x2A,  0xFE,  0xE9,  0x08,  0x10,  0x01,  0x00,  0x10,  0xBC,  0x00,  0xC1,  0xF0,  0xE2,  0x4B, 	/* 05420 */
+	0x24,  0xAA,  0x8A,  0xA0,  0xBF,  0xEA,  0x20,  0xE2,  0x00,  0x20,  0x02,  0x00,  0x60,  0xBD,  0x04,  0x00, 	/* 05430 */
+	0xA0,  0x11,  0x03,  0xE8,  0xC0,  0x67,  0xBC,  0x4A,  0x44,  0xA4,  0x4A,  0x47,  0xB8,  0x02,  0x00,  0x20, 	/* 05440 */
+	0x80,  0x00,  0x00,  0x7C,  0xF4,  0x49,  0x44,  0x97,  0xC9,  0x44,  0x94,  0x49,  0x7C,  0xF4,  0x48,  0x44, 	/* 05450 */
+	0x04,  0x41,  0xFE,  0x84,  0x01,  0x00,  0x92,  0xE9,  0x2A,  0x92,  0xA9,  0x2A,  0xFE,  0xA1,  0x0A,  0x92, 	/* 05460 */
+	0xA9,  0x2E,  0x92,  0x09,  0x20,  0xFE,  0x86,  0x04,  0x00,  0x40,  0xE7,  0xEA,  0x82,  0xAF,  0xAB,  0x4A, 	/* 05470 */
+	0xA4,  0xAA,  0x7A,  0xA4,  0x4E,  0x40,  0x04,  0x20,  0x3E,  0x8B,  0x02,  0x00,  0x20,  0xF7,  0xF9,  0x50, 	/* 05480 */
+	0x95,  0x09,  0x9E,  0x91,  0x09,  0x10,  0x91,  0xEF,  0x10,  0x01,  0x00,  0x10,  0x8C,  0x0C,  0x07,  0x00, 	/* 05490 */
+	0x13,  0xE1,  0x22,  0xFE,  0x21,  0x22,  0x3A,  0x23,  0x62,  0x52,  0x25,  0x22,  0x93,  0xE1,  0x00,  0x8E, 	/* 054A0 */
+	0x20,  0x83,  0x88,  0x28,  0x86,  0x98,  0x92,  0x42,  0xC2,  0x43,  0xE8,  0x00,  0x3F,  0x82,  0x08,  0x20, 	/* 054B0 */
+	0x83,  0xF8,  0x8F,  0x01,  0x00,  0x08,  0xE7,  0x0A,  0x12,  0xA1,  0x4B,  0xF8,  0xA3,  0x8A,  0x34,  0xA5, 	/* 054C0 */
+	0x2E,  0x91,  0x11,  0x00,  0x30,  0x90,  0x04,  0x40,  0x44,  0xE4,  0x4A,  0xBE,  0xA8,  0x4B,  0xA4,  0xA9, 	/* 054D0 */
+	0x4A,  0x94,  0xA8,  0x4E,  0x84,  0x08,  0x40,  0x8C,  0x92,  0x00,  0x07,  0xBC,  0x4A,  0x44,  0xA4,  0x7B, 	/* 054E0 */
+	0xC0,  0x00,  0x1E,  0x01,  0x20,  0x12,  0x01,  0x22,  0x22,  0x24,  0x1E,  0xA2,  0x7B,  0xC4,  0xA4,  0x4A, 	/* 054F0 */
+	0x47,  0xBC,  0x00,  0x03,  0xF8,  0x00,  0x0F,  0xFE,  0x08,  0x01,  0xF8,  0x20,  0x80,  0x70,  0xA4,  0x02, 	/* 05500 */
+	0x01,  0xFE,  0xF0,  0x2B,  0x1A,  0xAE,  0x0A,  0x20,  0xA3,  0xEB,  0xE0,  0xA2,  0x0E,  0x20,  0x02,  0x20, 	/* 05510 */
+	0x1E,  0xA5,  0x00,  0x01,  0xFE,  0xE2,  0x0A,  0x48,  0xBF,  0xCA,  0x24,  0xA2,  0x0B,  0xFC,  0xA2,  0x0E, 	/* 05520 */
+	0x20,  0x02,  0x03,  0xFE,  0xA8,  0x04,  0x00,  0x40,  0xE7,  0xE0,  0x94,  0x11,  0x03,  0x28,  0xC4,  0x40, 	/* 05530 */
+	0x82,  0x3F,  0x82,  0x08,  0x20,  0x83,  0xF8,  0xAB,  0x00,  0x07,  0xBE,  0x4A,  0x24,  0xA2,  0x7A,  0x26, 	/* 05540 */
+	0x3E,  0x60,  0x85,  0x14,  0x51,  0x24,  0xA2,  0x86,  0x08,  0x1F,  0xAC,  0x02,  0x00,  0x20,  0xFF,  0xEA, 	/* 05550 */
+	0x48,  0xA4,  0x8A,  0x84,  0xB4,  0xAA,  0x50,  0xE2,  0x08,  0x50,  0x08,  0x83,  0x06,  0xAF,  0x01,  0x00, 	/* 05560 */
+	0x1C,  0xF2,  0x49,  0x64,  0x99,  0x89,  0x14,  0x92,  0x29,  0x7D,  0x9A,  0x4F,  0x24,  0x02,  0x40,  0x3C, 	/* 05570 */
+	0xB2,  0x08,  0x80,  0x48,  0xE5,  0x0A,  0xFC,  0xA2,  0x0A,  0x20,  0xBF,  0xEA,  0x20,  0xE3,  0x00,  0x48, 	/* 05580 */
+	0x08,  0x43,  0x02,  0xB3,  0x01,  0x00,  0x10,  0xFF,  0xE9,  0x10,  0x92,  0x49,  0x68,  0x91,  0x09,  0x24, 	/* 05590 */
+	0x9C,  0x8F,  0x38,  0x06,  0x41,  0x82,  0xB8,  0x01,  0x80,  0x14,  0x7F,  0xE4,  0x10,  0x5D,  0x24,  0x12, 	/* 055A0 */
+	0x5D,  0x45,  0x54,  0x54,  0x85,  0xCA,  0x81,  0x68,  0x22,  0xBC,  0x00,  0x01,  0xF8,  0x10,  0x81,  0x78, 	/* 055B0 */
+	0x14,  0x87,  0xFE,  0x40,  0x25,  0xFA,  0x50,  0xA5,  0xFA,  0x50,  0x24,  0x06,  0xBD,  0x00,  0x00,  0xFE, 	/* 055C0 */
+	0xE9,  0x2A,  0x92,  0xAF,  0xEA,  0x92,  0xA9,  0x2A,  0x9A,  0xAA,  0x6E,  0xA6,  0x0C,  0x20,  0xFE,  0xBE, 	/* 055D0 */
+	0x02,  0x00,  0x20,  0xEF,  0xCA,  0x24,  0xA2,  0x8B,  0xFE,  0xA2,  0x0A,  0x4C,  0xBF,  0x0E,  0x40,  0x04, 	/* 055E0 */
+	0x40,  0x3C,  0x80,  0x04,  0x0F,  0xFE,  0x00,  0x03,  0xF8,  0x20,  0x82,  0x08,  0x3F,  0x80,  0x84,  0x34, 	/* 055F0 */
+	0x8D,  0x20,  0x1D,  0x87,  0x06,  0x81,  0x00,  0x03,  0xF0,  0x21,  0x02,  0x10,  0x21,  0x03,  0xF0,  0x00, 	/* 05600 */
+	0x0F,  0xBE,  0x8A,  0x28,  0xA2,  0x8A,  0x2F,  0xBE,  0x82,  0x00,  0x00,  0xFE,  0xE2,  0x8A,  0x28,  0xAF, 	/* 05610 */
+	0xEA,  0xAA,  0xAA,  0xAA,  0xCE,  0xE8,  0x28,  0x82,  0x0F,  0xE0,  0x80,  0x84,  0x04,  0x80,  0x48,  0xE4, 	/* 05620 */
+	0x8A,  0xFC,  0xA4,  0x8A,  0x48,  0xA4,  0x8B,  0xFE,  0xA5,  0x0E,  0x48,  0x08,  0x41,  0x04,  0x87,  0x01, 	/* 05630 */
+	0x00,  0x10,  0xEF,  0xCA,  0x10,  0xA1,  0x0B,  0xFE,  0xA1,  0x0A,  0x10,  0xAF,  0xCE,  0x10,  0x01,  0x01, 	/* 05640 */
+	0xFE,  0x88,  0x01,  0x00,  0x10,  0xF2,  0x89,  0x28,  0x94,  0x49,  0xBA,  0x90,  0x09,  0x7C,  0xF4,  0x40, 	/* 05650 */
+	0x44,  0x04,  0x40,  0x7C,  0x89,  0x11,  0x07,  0xD8,  0x11,  0x41,  0x10,  0xFF,  0xE0,  0x10,  0x79,  0x44, 	/* 05660 */
+	0x94,  0x48,  0x84,  0x9A,  0x7A,  0x60,  0x42,  0x98,  0x04,  0x00,  0x5E,  0xE8,  0x0B,  0x40,  0xA5,  0xFA, 	/* 05670 */
+	0x84,  0xB8,  0x4A,  0x84,  0xA8,  0x4E,  0x84,  0x08,  0x40,  0x8C,  0xA1,  0x1F,  0x81,  0x08,  0x1F,  0x83, 	/* 05680 */
+	0xFC,  0x20,  0x43,  0xFC,  0x20,  0x43,  0xFC,  0x20,  0x43,  0xFC,  0x19,  0x86,  0x06,  0xA2,  0x00,  0x01, 	/* 05690 */
+	0xFE,  0xE1,  0x0A,  0xFC,  0xA1,  0x0B,  0xFE,  0xA4,  0x8A,  0x48,  0xBF,  0xEE,  0x48,  0x08,  0x81,  0x08, 	/* 056A0 */
+	0xA5,  0x00,  0x07,  0xFC,  0x3E,  0x82,  0x28,  0x3E,  0x80,  0x08,  0xFF,  0xE0,  0x08,  0x3E,  0x82,  0x28, 	/* 056B0 */
+	0x3E,  0x80,  0x18,  0xA6,  0x02,  0x81,  0xCC,  0xE4,  0xAA,  0x48,  0xBF,  0xEA,  0x4A,  0xA6,  0xAA,  0xCC, 	/* 056C0 */
+	0xB4,  0x8E,  0x5A,  0x06,  0x60,  0xC2,  0xA8,  0x02,  0x01,  0x24,  0xEA,  0x8A,  0xFC,  0xA8,  0x4A,  0x84, 	/* 056D0 */
+	0xAF,  0xCA,  0x84,  0xAF,  0xCE,  0x84,  0x08,  0x40,  0x8C,  0xA9,  0x00,  0x0E,  0xFE,  0xA9,  0x2A,  0xFE, 	/* 056E0 */
+	0xA9,  0x2A,  0x92,  0xAF,  0xEA,  0x10,  0xEF,  0xE8,  0x10,  0x01,  0x01,  0xFF,  0xAD,  0x00,  0x0F,  0xBE, 	/* 056F0 */
+	0x8A,  0x28,  0xA2,  0xFB,  0xE0,  0x48,  0x04,  0x4F,  0xFE,  0x04,  0x00,  0xA0,  0x31,  0x8C,  0x06,  0xAE, 	/* 05700 */
+	0x02,  0x00,  0x28,  0xFF,  0xCA,  0x28,  0xBF,  0xEA,  0x20,  0xA7,  0xCA,  0x98,  0xB1,  0x0E,  0xFE,  0x01, 	/* 05710 */
+	0x00,  0x30,  0xB2,  0x20,  0x62,  0x78,  0xF4,  0x02,  0x7E,  0x34,  0x8E,  0x48,  0x28,  0x86,  0x08,  0x3F, 	/* 05720 */
+	0x82,  0x08,  0x20,  0x83,  0xF8,  0xBA,  0x01,  0x40,  0x12,  0xFF,  0xFA,  0x10,  0xAF,  0xEA,  0x92,  0xAF, 	/* 05730 */
+	0xEA,  0x92,  0xAF,  0xEE,  0x92,  0x09,  0x20,  0x96,  0xBD,  0x00,  0x01,  0xFE,  0xE1,  0x0A,  0xFC,  0xA9, 	/* 05740 */
+	0x4A,  0xFC,  0xA9,  0x4A,  0xFC,  0xA5,  0x0E,  0x20,  0x0D,  0x83,  0x06,  0x84,  0x00,  0x00,  0x7C,  0xF4, 	/* 05750 */
+	0x49,  0x44,  0x97,  0xC9,  0x44,  0x97,  0xC9,  0x44,  0x94,  0x4F,  0x7C,  0x02,  0x40,  0xC2,  0x86,  0x01, 	/* 05760 */
+	0x00,  0x24,  0xFF,  0xA9,  0x28,  0x92,  0xA9,  0x4E,  0x9A,  0x09,  0x3C,  0x96,  0x4F,  0x98,  0x06,  0xC1, 	/* 05770 */
+	0x82,  0x87,  0x00,  0x07,  0xFE,  0x40,  0x05,  0xFE,  0x4A,  0x44,  0x98,  0x4A,  0x89,  0xC6,  0x3F,  0xC2, 	/* 05780 */
+	0x04,  0x20,  0x43,  0xFC,  0x8F,  0x06,  0x40,  0x18,  0xEE,  0x4A,  0x10,  0xBF,  0xFA,  0x50,  0xA7,  0xEA, 	/* 05790 */
+	0xD2,  0xF5,  0x22,  0x52,  0x05,  0x60,  0x10,  0x90,  0x02,  0x07,  0xFE,  0x42,  0x05,  0xFC,  0x42,  0x47, 	/* 057A0 */
+	0xFE,  0x42,  0x45,  0xFC,  0x40,  0x05,  0xFC,  0x90,  0x41,  0xFC,  0x94,  0x00,  0x00,  0xFE,  0xF1,  0x09, 	/* 057B0 */
+	0x7C,  0x92,  0x49,  0x24,  0x9F,  0xF9,  0x00,  0x97,  0xCF,  0x44,  0x04,  0x40,  0x7C,  0x96,  0x00,  0x01, 	/* 057C0 */
+	0xFE,  0xE2,  0x8A,  0x28,  0xAF,  0xEA,  0xAA,  0xAA,  0xAA,  0xAA,  0xAF,  0xEE,  0x28,  0x02,  0x81,  0xFE, 	/* 057D0 */
+	0xAE,  0x11,  0x01,  0x20,  0x3F,  0xE6,  0x20,  0xBF,  0xC2,  0x20,  0x3F,  0xC2,  0x20,  0x3F,  0xE2,  0x04, 	/* 057E0 */
+	0x20,  0x43,  0xFC,  0xAF,  0x04,  0x8E,  0x90,  0xAF,  0xEB,  0x90,  0xA9,  0x0A,  0xFC,  0xA9,  0x0A,  0x90, 	/* 057F0 */
+	0xAF,  0xCE,  0x90,  0x09,  0x00,  0xFE,  0xB1,  0x00,  0x00,  0x7C,  0xE4,  0x4A,  0x7C,  0xA4,  0x4A,  0x7C, 	/* 05800 */
+	0xA0,  0x0A,  0xFE,  0xE8,  0x20,  0xFE,  0x08,  0x20,  0xFE,  0xB3,  0x00,  0x01,  0xFE,  0xE0,  0x0A,  0xFE, 	/* 05810 */
+	0xA8,  0x2A,  0xFE,  0xA9,  0x0A,  0xFE,  0xF1,  0x01,  0x28,  0x24,  0x41,  0x82,  0xB8,  0x02,  0x0E,  0x30, 	/* 05820 */
+	0xA4,  0x8A,  0xF4,  0xB0,  0x2A,  0xFC,  0xA0,  0x8A,  0x30,  0xF5,  0x01,  0x44,  0x24,  0xA0,  0x38,  0xB9, 	/* 05830 */
+	0x08,  0x80,  0x88,  0xFE,  0xCA,  0x8C,  0xA9,  0x2A,  0xE9,  0xAA,  0x4A,  0xA2,  0xEA,  0x81,  0x24,  0x22, 	/* 05840 */
+	0x20,  0xC2,  0xBE,  0x00,  0xC0,  0xF0,  0xE1,  0x0A,  0xFE,  0xA5,  0x4B,  0xFF,  0xA5,  0x4A,  0x54,  0xAF, 	/* 05850 */
+	0xEE,  0x10,  0x01,  0x01,  0xFE,  0x80,  0x00,  0x00,  0xFE,  0xE8,  0x8A,  0xBC,  0xA8,  0x8A,  0xFE,  0xA8, 	/* 05860 */
+	0x8A,  0x88,  0xEB,  0xC1,  0x08,  0x10,  0x82,  0x7E,  0x84,  0x00,  0x01,  0xFE,  0xE2,  0x0A,  0x60,  0xB9, 	/* 05870 */
+	0x2A,  0x2C,  0xA4,  0x8B,  0x9C,  0xE2,  0xA8,  0xC9,  0x30,  0x80,  0x30,  0x85,  0x02,  0x00,  0x3E,  0xE2, 	/* 05880 */
+	0x0A,  0xFC,  0xA8,  0x4A,  0xFC,  0xA8,  0x4A,  0xFC,  0xA2,  0x0F,  0xFE,  0x02,  0x00,  0x20,  0x86,  0x04, 	/* 05890 */
+	0x0F,  0xFF,  0x10,  0x80,  0x90,  0x7F,  0xE4,  0x92,  0x51,  0x26,  0xFE,  0x49,  0x24,  0x92,  0x4F,  0x24, 	/* 058A0 */
+	0x06,  0x8C,  0x02,  0x01,  0xFE,  0xF5,  0x2B,  0x52,  0xA5,  0x0A,  0x8E,  0xB0,  0x0A,  0xFC,  0xA2,  0x0E, 	/* 058B0 */
+	0x20,  0x02,  0x01,  0xFE,  0x8F,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0x02,  0x9F,  0x29, 	/* 058C0 */
+	0x12,  0x91,  0x29,  0xF2,  0x80,  0x28,  0x06,  0x93,  0xFA,  0x00,  0x3E,  0x7A,  0x44,  0xD4,  0x78,  0x84, 	/* 058D0 */
+	0x14,  0x46,  0x28,  0x00,  0x3F,  0x82,  0x08,  0x20,  0x83,  0xF8,  0x96,  0x02,  0x00,  0x24,  0xEA,  0x8B, 	/* 058E0 */
+	0x30,  0xA4,  0x8B,  0xA6,  0xA2,  0x0A,  0x24,  0xEA,  0x81,  0x30,  0x0C,  0x83,  0x06,  0x97,  0x02,  0x00, 	/* 058F0 */
+	0x3E,  0xF2,  0x29,  0x42,  0x98,  0xC9,  0x10,  0x96,  0xE9,  0x42,  0x97,  0x6F,  0x42,  0x04,  0x20,  0x7E, 	/* 05900 */
+	0x9C,  0x00,  0x01,  0xFE,  0xEA,  0xAA,  0x64,  0xA5,  0xAA,  0x91,  0xAF,  0xEA,  0x12,  0xAA,  0xAE,  0x44, 	/* 05910 */
+	0x0A,  0xA1,  0x11,  0x9D,  0x03,  0x01,  0xC0,  0xE4,  0xEA,  0x4A,  0xBF,  0xAA,  0x4A,  0xAE,  0xAA,  0xEE, 	/* 05920 */
+	0xF5,  0x82,  0x46,  0x04,  0x00,  0x40,  0xA3,  0x08,  0x00,  0x8E,  0xEF,  0xAB,  0x2A,  0xAF,  0xAA,  0x2A, 	/* 05930 */
+	0xAB,  0xAA,  0xAA,  0xAA,  0xAE,  0xBC,  0x1C,  0x80,  0x08,  0xBB,  0x04,  0x07,  0xFC,  0x11,  0x0F,  0xFE, 	/* 05940 */
+	0x84,  0x23,  0xF8,  0x24,  0x82,  0x70,  0x04,  0x07,  0xFC,  0x40,  0x47,  0xFC,  0xBC,  0x02,  0x01,  0xFC, 	/* 05950 */
+	0xE8,  0x8A,  0x50,  0xBF,  0xEB,  0x22,  0xBF,  0xEA,  0xA4,  0xAA,  0x4E,  0xA4,  0x0A,  0xC0,  0x20,  0xBE, 	/* 05960 */
+	0x06,  0x81,  0xC8,  0xE4,  0xAB,  0xFA,  0xA4,  0xCA,  0xE8,  0xAD,  0x8B,  0x48,  0xA5,  0x4E,  0x54,  0x06, 	/* 05970 */
+	0x20,  0x41,  0x80,  0x01,  0x01,  0xFE,  0xF2,  0x2B,  0x3A,  0xA4,  0x8A,  0xB0,  0xA2,  0x8A,  0x44,  0xBF, 	/* 05980 */
+	0xEE,  0x44,  0x04,  0x40,  0x7C,  0x83,  0x01,  0x00,  0x10,  0xFF,  0xEA,  0x10,  0xAF,  0xEA,  0xCA,  0xAB, 	/* 05990 */
+	0x2A,  0xFE,  0xA9,  0x2E,  0xFE,  0x09,  0x20,  0x96,  0x84,  0x11,  0x07,  0xFC,  0x04,  0x03,  0xF8,  0x04, 	/* 059A0 */
+	0x07,  0xFC,  0x24,  0x8F,  0xFE,  0x00,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x87,  0x08,  0x20,  0x82,  0xFE, 	/* 059B0 */
+	0xAA,  0x8A,  0xBE,  0xAA,  0xAA,  0xAA,  0xAB,  0xEA,  0xEC,  0xA9,  0xA2,  0x28,  0x20,  0x86,  0x89,  0x04, 	/* 059C0 */
+	0x00,  0x7C,  0xE4,  0x4A,  0xFE,  0xA9,  0x0B,  0xBE,  0xAA,  0x8A,  0xC8,  0xAF,  0xEE,  0x98,  0x0A,  0x40, 	/* 059D0 */
+	0xC2,  0x8A,  0x00,  0xC0,  0x0A,  0xEF,  0xEA,  0x88,  0xAF,  0xAA,  0x8A,  0xAF,  0xAA,  0x9C,  0xEF,  0x41, 	/* 059E0 */
+	0x0E,  0x11,  0x22,  0x22,  0x8B,  0x0A,  0x80,  0xA8,  0xFF,  0xEA,  0xA8,  0xAB,  0x8A,  0x80,  0xAF,  0xEA, 	/* 059F0 */
+	0x20,  0xFF,  0xE0,  0xE8,  0x32,  0x60,  0x20,  0x98,  0x01,  0x00,  0x92,  0xE9,  0x2A,  0xFE,  0xA0,  0x0B, 	/* 05A00 */
+	0xFF,  0xA2,  0x0A,  0xFE,  0xAA,  0xAE,  0xAA,  0x0A,  0xA0,  0x86,  0x99,  0x07,  0xEE,  0x44,  0xAF,  0xCA, 	/* 05A10 */
+	0x10,  0xAF,  0xFA,  0x30,  0xAD,  0x8A,  0x2B,  0xED,  0xC8,  0x2A,  0x0C,  0x90,  0x10,  0x9A,  0x02,  0x00, 	/* 05A20 */
+	0x3C,  0xE4,  0x8A,  0xFE,  0xAA,  0xAA,  0xAA,  0xAC,  0xEA,  0x92,  0xFF,  0xF0,  0x28,  0x04,  0x61,  0x81, 	/* 05A30 */
+	0x9C,  0x04,  0x0F,  0xFE,  0x04,  0x07,  0xFC,  0x20,  0x83,  0xF8,  0x11,  0x0F,  0xFE,  0x00,  0x03,  0xF8, 	/* 05A40 */
+	0x20,  0x83,  0xF8,  0x9D,  0x0F,  0xCE,  0x84,  0xAF,  0xCA,  0x84,  0xAF,  0xCA,  0x40,  0xA7,  0xEE,  0x92, 	/* 05A50 */
+	0x1E,  0x22,  0x8A,  0x07,  0xA0,  0x0C,  0x9E,  0x04,  0x00,  0x4E,  0xEF,  0xAA,  0x9A,  0xAF,  0xAA,  0x9A, 	/* 05A60 */
+	0xAF,  0xAA,  0x8A,  0xAE,  0xAE,  0x8C,  0x0E,  0x80,  0x88,  0x9F,  0x00,  0x00,  0xFE,  0xE9,  0x2A,  0xFE, 	/* 05A70 */
+	0xA9,  0x2A,  0xFE,  0xA4,  0x4A,  0x7C,  0xA4,  0x4E,  0x7C,  0x04,  0x40,  0x4C,  0xA7,  0x01,  0x0F,  0xFE, 	/* 05A80 */
+	0xB0,  0x2A,  0xFC,  0xA0,  0x0A,  0xFC,  0xA8,  0x4A,  0xFC,  0xE8,  0x40,  0xFC,  0x00,  0x01,  0xFE,  0xA8, 	/* 05A90 */
+	0x01,  0x01,  0xFE,  0xE0,  0x0A,  0x78,  0xA4,  0x8A,  0x78,  0xBF,  0xEB,  0x02,  0xE5,  0x00,  0x50,  0x09, 	/* 05AA0 */
+	0x23,  0x0E,  0xA9,  0x02,  0x00,  0x30,  0xE4,  0x8B,  0xB6,  0xA0,  0x0A,  0xEA,  0xAA,  0xAA,  0xF4,  0xAB, 	/* 05AB0 */
+	0x4E,  0xF4,  0x8A,  0xA0,  0xAA,  0xAA,  0x04,  0x0F,  0xFE,  0x04,  0x07,  0x5C,  0x55,  0x47,  0x5C,  0x04, 	/* 05AC0 */
+	0x0F,  0xFE,  0x28,  0x42,  0x58,  0x23,  0x0F,  0x8C,  0xAB,  0x04,  0x0F,  0xFE,  0xA4,  0xAB,  0xEA,  0xA5, 	/* 05AD0 */
+	0x2B,  0xE4,  0xAF,  0x8A,  0x20,  0xFF,  0xE0,  0x50,  0x08,  0x83,  0x06,  0xAC,  0x03,  0x83,  0xC0,  0x04, 	/* 05AE0 */
+	0x0F,  0xFC,  0x1F,  0x03,  0x18,  0xDF,  0x67,  0xFC,  0x5F,  0x45,  0x14,  0x5F,  0x44,  0x0C,  0xAE,  0x7B, 	/* 05AF0 */
+	0xC4,  0xA4,  0x7B,  0xC3,  0xF8,  0x24,  0x83,  0xF8,  0x24,  0x83,  0xF8,  0x04,  0x0F,  0xFE,  0x04,  0x00, 	/* 05B00 */
+	0x40,  0xB0,  0x02,  0x00,  0x50,  0xEF,  0x8B,  0x04,  0xAF,  0xAA,  0x88,  0xAF,  0x8A,  0xF8,  0xAA,  0x4E, 	/* 05B10 */
+	0x98,  0x0C,  0xC3,  0x82,  0xB6,  0x28,  0x81,  0x50,  0xFF,  0xE8,  0x02,  0xBF,  0x22,  0x10,  0x3F,  0x00, 	/* 05B20 */
+	0x80,  0x7F,  0x84,  0x08,  0x40,  0x87,  0xF8,  0x84,  0x00,  0x01,  0xFE,  0xE2,  0x0A,  0xFC,  0xA8,  0x4A, 	/* 05B30 */
+	0xFC,  0xA8,  0x4A,  0xFC,  0xA3,  0xCE,  0xC8,  0x07,  0x83,  0x86,  0x85,  0x02,  0x0E,  0xFC,  0xA8,  0x4A, 	/* 05B40 */
+	0xFC,  0xA8,  0x4A,  0xFC,  0xA8,  0x4A,  0xFC,  0xE1,  0x43,  0xFE,  0x06,  0x81,  0x86,  0x87,  0x04,  0x07, 	/* 05B50 */
+	0xFC,  0x24,  0x82,  0x48,  0x55,  0x4F,  0xFE,  0x00,  0x07,  0xFC,  0x51,  0x45,  0xF4,  0x40,  0x47,  0xFC, 	/* 05B60 */
+	0x94,  0x04,  0x60,  0x78,  0xE4,  0x2A,  0x3E,  0xAA,  0x4A,  0xBC,  0xAA,  0x4A,  0xBC,  0xAA,  0x4E,  0xFF, 	/* 05B70 */
+	0x04,  0x41,  0x82,  0x9A,  0x02,  0x0E,  0xF8,  0xA8,  0x8A,  0x88,  0xAF,  0x8A,  0x80,  0xAF,  0xEE,  0x80, 	/* 05B80 */
+	0x0F,  0xE1,  0x52,  0x12,  0xA2,  0x0C,  0x9C,  0x01,  0x00,  0xFE,  0xE1,  0x4B,  0xFE,  0xA2,  0x4A,  0x78, 	/* 05B90 */
+	0xBA,  0x2A,  0xFE,  0xA8,  0x4E,  0xFC,  0x08,  0x40,  0xFC,  0x9F,  0x04,  0x40,  0x28,  0xEF,  0xEA,  0x10, 	/* 05BA0 */
+	0xAF,  0xCA,  0x10,  0xBF,  0xFA,  0x40,  0xEF,  0xC1,  0x10,  0x21,  0x00,  0xFE,  0xA3,  0x00,  0x0F,  0xFE, 	/* 05BB0 */
+	0x88,  0x2F,  0xBA,  0x00,  0x2F,  0xBA,  0xAA,  0xAA,  0xAA,  0xFA,  0xAA,  0xBA,  0xA8,  0x2A,  0x86,  0xA4, 	/* 05BC0 */
+	0x02,  0x01,  0x24,  0xFF,  0xCA,  0x40,  0xBF,  0xEA,  0x20,  0xAF,  0xCA,  0xA4,  0xAF,  0xCE,  0x28,  0x03, 	/* 05BD0 */
+	0xC1,  0xC2,  0xB7,  0x04,  0x80,  0x48,  0xFE,  0x8A,  0x4F,  0xBF,  0x2A,  0x52,  0xBE,  0xAA,  0x8A,  0xAE, 	/* 05BE0 */
+	0x4E,  0xAC,  0x13,  0x22,  0x61,  0xB9,  0x10,  0x80,  0xBE,  0xE0,  0x8B,  0x3E,  0xAA,  0xAA,  0x3E,  0xBA, 	/* 05BF0 */
+	0xAA,  0xBE,  0xA8,  0x8E,  0xBE,  0x16,  0x82,  0x1F,  0xBD,  0x09,  0x01,  0xF0,  0xE9,  0xCB,  0xF4,  0xAA, 	/* 05C00 */
+	0xCA,  0xA8,  0xBE,  0x8A,  0xC8,  0xFB,  0x82,  0x94,  0x4A,  0x40,  0xC2,  0xBE,  0x04,  0x80,  0x48,  0xFE, 	/* 05C10 */
+	0xEA,  0x94,  0xAA,  0xEA,  0xF4,  0xAA,  0x4A,  0xBF,  0xEA,  0x41,  0x24,  0x22,  0xA0,  0xD1,  0x86,  0x04, 	/* 05C20 */
+	0x81,  0xFE,  0xE4,  0x8A,  0xFE,  0xA9,  0x2A,  0xFE,  0xA1,  0x0A,  0xFE,  0xE1,  0x08,  0xFE,  0x06,  0xC1, 	/* 05C30 */
+	0x83,  0x89,  0x04,  0x0F,  0xFE,  0x04,  0x03,  0xF8,  0x20,  0x87,  0xFC,  0x09,  0x0F,  0xFE,  0x10,  0x0F, 	/* 05C40 */
+	0xBE,  0x2A,  0x2D,  0xBE,  0x94,  0x00,  0x00,  0xFE,  0xE8,  0x0A,  0xBC,  0xAA,  0x4A,  0xBC,  0xA8,  0x0A, 	/* 05C50 */
+	0xFE,  0xAD,  0xAE,  0xFE,  0x08,  0x00,  0xFE,  0x96,  0x02,  0x01,  0xFC,  0xE2,  0x0A,  0xFC,  0xA2,  0x0B, 	/* 05C60 */
+	0xFE,  0xA8,  0x8A,  0xF8,  0xA8,  0x8E,  0xF8,  0x04,  0x81,  0x84,  0x97,  0x24,  0x81,  0x50,  0xFF,  0xE9, 	/* 05C70 */
+	0x12,  0xDF,  0xA7,  0xE0,  0x40,  0x23,  0xFE,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x98,  0x02,  0x00, 	/* 05C80 */
+	0x3C,  0xE2,  0x0A,  0xFE,  0xAA,  0x0A,  0xFE,  0xAA,  0x4A,  0x9C,  0xAA,  0xAE,  0xAC,  0x16,  0x82,  0xFE, 	/* 05C90 */
+	0x9B,  0x02,  0x03,  0xFE,  0xE0,  0x0A,  0x88,  0xBF,  0xEA,  0x88,  0xAA,  0xAE,  0xAA,  0x2A,  0xA5,  0xAA, 	/* 05CA0 */
+	0x68,  0x88,  0x88,  0xA9,  0x08,  0x83,  0xFE,  0xE8,  0x8B,  0xFC,  0xAA,  0x8B,  0xFE,  0xAA,  0x8B,  0xFC, 	/* 05CB0 */
+	0xE2,  0x03,  0xFE,  0x02,  0x00,  0x20,  0xAF,  0x02,  0x00,  0xFC,  0xE2,  0x4A,  0xFE,  0xA2,  0x4A,  0xFC, 	/* 05CC0 */
+	0xAA,  0xAB,  0xAE,  0xFF,  0xE1,  0x22,  0x1A,  0xE2,  0xAA,  0xB1,  0x00,  0x00,  0xFF,  0xE8,  0x1A,  0xFF, 	/* 05CD0 */
+	0xA8,  0xEA,  0xBE,  0xAA,  0xAA,  0xFF,  0xED,  0x51,  0x5D,  0x17,  0x52,  0x47,  0xB2,  0x04,  0x0F,  0xFE, 	/* 05CE0 */
+	0xA4,  0xAA,  0xFA,  0xA9,  0xEA,  0xFA,  0xA9,  0xAA,  0xFE,  0xE4,  0xA9,  0xF2,  0x05,  0x20,  0x66,  0xB4, 	/* 05CF0 */
+	0x05,  0x01,  0x7E,  0xF5,  0x0B,  0xEE,  0xA3,  0xCA,  0x48,  0xAF,  0xEA,  0x92,  0xAF,  0xEE,  0x92,  0x0F, 	/* 05D00 */
+	0xE1,  0x02,  0xB6,  0x0A,  0x20,  0xAC,  0xFF,  0x8A,  0xA8,  0xAE,  0xFA,  0xAA,  0xAE,  0xAA,  0xAA,  0xBF, 	/* 05D10 */
+	0xAE,  0x6A,  0x09,  0x21,  0x22,  0xB8,  0x08,  0x00,  0x80,  0xEF,  0xEB,  0xB4,  0xAB,  0x4B,  0xFE,  0xAB, 	/* 05D20 */
+	0x4A,  0xB4,  0xBF,  0xEE,  0x00,  0x15,  0x42,  0x4A,  0x82,  0x08,  0x81,  0xFE,  0xE5,  0x0B,  0xFC,  0xB5, 	/* 05D30 */
+	0x4B,  0x9C,  0xBF,  0xCA,  0x08,  0xBF,  0xEE,  0x88,  0x04,  0x80,  0x18,  0x8C,  0x04,  0x40,  0x28,  0xEF, 	/* 05D40 */
+	0xEA,  0x92,  0xAF,  0xEA,  0x92,  0xAF,  0xEA,  0x44,  0xE7,  0xC0,  0x44,  0x04,  0x40,  0x7C,  0x8E,  0x02, 	/* 05D50 */
+	0x00,  0xFC,  0xE2,  0x0B,  0xFE,  0xB0,  0x2A,  0xFC,  0xA0,  0x0A,  0xFC,  0xA8,  0x4E,  0xFC,  0x04,  0x81, 	/* 05D60 */
+	0xFE,  0x90,  0x00,  0x07,  0xBC,  0x4A,  0x47,  0xBC,  0x00,  0x07,  0xFC,  0x04,  0x0F,  0xFE,  0x00,  0x07, 	/* 05D70 */
+	0xBC,  0x4A,  0x47,  0xBC,  0x9B,  0x01,  0x00,  0x5E,  0xE5,  0x0B,  0xFF,  0xA9,  0x2A,  0xD6,  0xAB,  0xAA, 	/* 05D80 */
+	0xFE,  0xE9,  0x28,  0xBA,  0x0D,  0x60,  0xFE,  0xA4,  0x04,  0x81,  0xFE,  0xE4,  0x8A,  0xEC,  0xB5,  0xAA, 	/* 05D90 */
+	0x49,  0xAF,  0xCA,  0x00,  0xBF,  0xEE,  0x94,  0x11,  0x20,  0x30,  0xA8,  0x00,  0x07,  0xBC,  0x4A,  0x47, 	/* 05DA0 */
+	0xBC,  0x04,  0x0F,  0xFE,  0x0A,  0x03,  0x18,  0xFB,  0xE4,  0xA4,  0x4A,  0x47,  0xBC,  0xAA,  0x07,  0xC0, 	/* 05DB0 */
+	0x44,  0xE7,  0xCA,  0xEE,  0xAA,  0xAA,  0xEE,  0xA1,  0x0B,  0xFE,  0xA3,  0x8E,  0x54,  0x19,  0x30,  0x10, 	/* 05DC0 */
+	0xAB,  0x02,  0x00,  0xFC,  0xE4,  0x8B,  0xFE,  0xA8,  0x4A,  0xFC,  0xA8,  0x4A,  0xFC,  0xA1,  0x0F,  0x54, 	/* 05DD0 */
+	0x14,  0x62,  0x3C,  0xAC,  0x08,  0x80,  0xEE,  0xF5,  0x4A,  0x44,  0xBF,  0xEA,  0x10,  0xAA,  0x8A,  0xA8, 	/* 05DE0 */
+	0xF7,  0x41,  0x22,  0x22,  0x03,  0xFE,  0xB4,  0x02,  0x01,  0xFC,  0xEA,  0x8B,  0xFE,  0xA4,  0x8A,  0xFC, 	/* 05DF0 */
+	0xA8,  0x4A,  0xFC,  0xA8,  0x4E,  0xFC,  0x04,  0x41,  0x82,  0xB8,  0x04,  0x0E,  0x5F,  0xBF,  0x8A,  0x4F, 	/* 05E00 */
+	0xB5,  0x9B,  0x5F,  0xBF,  0x9B,  0x4F,  0xE4,  0x98,  0x5F,  0x06,  0xA0,  0x11,  0xBA,  0x08,  0x43,  0xF8, 	/* 05E10 */
+	0xF5,  0x0B,  0x50,  0xBF,  0xEA,  0x94,  0xBF,  0x4A,  0x94,  0xFD,  0x42,  0xB4,  0x4A,  0x40,  0xC4,  0x80, 	/* 05E20 */
+	0x02,  0x01,  0xFE,  0xF4,  0x2A,  0xD4,  0xAB,  0xAB,  0x00,  0xAF,  0xEA,  0xAA,  0xBF,  0xFE,  0x08,  0x00, 	/* 05E30 */
+	0x80,  0x18,  0x86,  0x04,  0x81,  0xFE,  0xE4,  0x8A,  0x10,  0xBF,  0xEA,  0x44,  0xA7,  0xCA,  0x00,  0xFF, 	/* 05E40 */
+	0xE1,  0x4A,  0x17,  0xA1,  0x06,  0x87,  0x04,  0x4E,  0x44,  0xAE,  0xEA,  0x44,  0xBF,  0xFA,  0x54,  0xAD, 	/* 05E50 */
+	0x6A,  0xFE,  0xF7,  0xD9,  0x55,  0x25,  0x50,  0x64,  0x8A,  0x01,  0x00,  0x7C,  0xE4,  0x4A,  0x7C,  0xA4, 	/* 05E60 */
+	0x4A,  0xFE,  0xA9,  0x2A,  0xFE,  0xE9,  0x23,  0xFF,  0x04,  0x40,  0x84,  0x8F,  0x02,  0x01,  0xFC,  0xE2, 	/* 05E70 */
+	0x0B,  0xFE,  0xAA,  0xAA,  0xF8,  0xAA,  0x8F,  0xFE,  0x12,  0x21,  0x38,  0x2E,  0x04,  0x3E,  0x94,  0x02, 	/* 05E80 */
+	0x01,  0xFC,  0xE2,  0x0B,  0xFE,  0xAA,  0xAA,  0xF8,  0xA4,  0x4F,  0xFA,  0x12,  0x21,  0x38,  0x2E,  0x04, 	/* 05E90 */
+	0x3E,  0xA0,  0x08,  0x21,  0x7A,  0xF5,  0xAB,  0xBA,  0xA4,  0xAA,  0xAA,  0xBF,  0xAA,  0x4A,  0xBF,  0xAF, 	/* 05EA0 */
+	0x52,  0x0F,  0x23,  0x86,  0xA2,  0x04,  0x0F,  0xFE,  0x24,  0x8F,  0xFE,  0x91,  0x27,  0xF8,  0x11,  0x0F, 	/* 05EB0 */
+	0xFE,  0x34,  0x45,  0x28,  0x9D,  0x87,  0x06,  0xA5,  0x05,  0x01,  0xFE,  0xE5,  0x0A,  0x70,  0xA8,  0xAB, 	/* 05EC0 */
+	0xFC,  0xAD,  0x8A,  0xDA,  0xFF,  0xA0,  0x86,  0x15,  0x42,  0x4A,  0xAE,  0x26,  0xED,  0xEA,  0x6A,  0xC5, 	/* 05ED0 */
+	0xEA,  0xE8,  0x92,  0xEE,  0x48,  0x87,  0xFE,  0x4F,  0x24,  0x92,  0x4F,  0x24,  0x06,  0xB4,  0x3B,  0x82, 	/* 05EE0 */
+	0xA8,  0x7F,  0xC4,  0x10,  0x5D,  0x04,  0x9C,  0x7E,  0x45,  0x54,  0x5C,  0x85,  0x48,  0xBD,  0x48,  0x62, 	/* 05EF0 */
+	0xB6,  0x1D,  0xC1,  0x54,  0xFD,  0xCB,  0x54,  0xBD,  0xCB,  0x54,  0xBD,  0xCA,  0x22,  0xBF,  0xEE,  0x48, 	/* 05F00 */
+	0x03,  0x01,  0xCC,  0xBC,  0x00,  0xC1,  0xF4,  0xE9,  0x2B,  0xFE,  0xA5,  0x2B,  0xFE,  0xA4,  0x4B,  0xFE, 	/* 05F10 */
+	0xE2,  0x43,  0x94,  0x3C,  0x42,  0x0C,  0x80,  0x08,  0x83,  0xFE,  0xE8,  0x8B,  0xFE,  0xAA,  0xAB,  0xFE, 	/* 05F20 */
+	0xAA,  0xAB,  0xFD,  0xE8,  0x43,  0xFE,  0x09,  0x40,  0x8C,  0x81,  0x0F,  0xC0,  0x48,  0xE7,  0x8A,  0x48, 	/* 05F30 */
+	0xBF,  0xCA,  0x08,  0xBF,  0xEB,  0x54,  0xFD,  0xC1,  0x56,  0x3F,  0xC0,  0x44,  0x82,  0x7B,  0xC4,  0xA4, 	/* 05F40 */
+	0xFF,  0xE0,  0x80,  0x3F,  0x82,  0x08,  0x3F,  0x82,  0x08,  0x3F,  0x87,  0xBC,  0xAA,  0xA3,  0xB8,  0x83, 	/* 05F50 */
+	0x04,  0xA1,  0xF4,  0xEB,  0xEA,  0xB4,  0xB5,  0x4A,  0x5E,  0xBF,  0x4A,  0x54,  0xED,  0xE1,  0x74,  0x25, 	/* 05F60 */
+	0x40,  0x5E,  0x88,  0x04,  0x81,  0xFE,  0xE4,  0x8B,  0xFE,  0xAA,  0xAB,  0xBA,  0xA5,  0x6B,  0xE3,  0xE0, 	/* 05F70 */
+	0x01,  0xFE,  0x04,  0x81,  0xF4,  0x8E,  0x01,  0x41,  0xD4,  0xF6,  0x2B,  0xFF,  0xB6,  0xAB,  0x7E,  0xBE, 	/* 05F80 */
+	0xAB,  0x7E,  0xF5,  0x41,  0xDC,  0x19,  0x42,  0x5C,  0x91,  0x00,  0x01,  0xFE,  0xF8,  0x2B,  0xFE,  0xB7, 	/* 05F90 */
+	0xCB,  0x54,  0xB7,  0xEF,  0xD6,  0x97,  0xE1,  0x1A,  0x27,  0x64,  0x0C,  0x93,  0x08,  0x0E,  0x9E,  0xBE, 	/* 05FA0 */
+	0xAA,  0x8A,  0xBE,  0xAA,  0xF4,  0xB2,  0x0B,  0xFE,  0xF5,  0x41,  0xAC,  0x10,  0x41,  0xFC,  0x97,  0x00, 	/* 05FB0 */
+	0x0F,  0xFE,  0x80,  0x28,  0x02,  0x80,  0x28,  0x02,  0x80,  0x28,  0x02,  0x80,  0x28,  0x02,  0xFF,  0xE8, 	/* 05FC0 */
+	0x02,  0x98,  0x00,  0x0F,  0xFE,  0x80,  0x2B,  0xF2,  0xA1,  0x2A,  0x12,  0xBF,  0x2A,  0x02,  0xA0,  0xA9, 	/* 05FD0 */
+	0xFA,  0x80,  0x28,  0x06,  0x9A,  0x00,  0x07,  0xFE,  0x44,  0x24,  0x42,  0x44,  0x24,  0x42,  0x4A,  0x24, 	/* 05FE0 */
+	0xA2,  0x51,  0x26,  0x0A,  0x40,  0x27,  0xFE,  0x9B,  0x00,  0x0F,  0xFE,  0x8A,  0x28,  0xA2,  0x8A,  0x29, 	/* 05FF0 */
+	0x26,  0xA1,  0xEC,  0x02,  0x80,  0x2F,  0xFE,  0x00,  0x00,  0x00,  0x9E,  0x00,  0x07,  0xFE,  0x40,  0x24, 	/* 06000 */
+	0x02,  0x4F,  0x24,  0x92,  0x49,  0x24,  0xF2,  0x40,  0x24,  0x02,  0x7F,  0xE0,  0x00,  0xA0,  0x00,  0x07, 	/* 06010 */
+	0xFE,  0x44,  0x24,  0x42,  0x7F,  0xA4,  0x42,  0x44,  0x24,  0xA2,  0x51,  0x26,  0x0A,  0x40,  0x27,  0xFE, 	/* 06020 */
+	0xA3,  0x00,  0x07,  0xFE,  0x41,  0x24,  0x12,  0x7F,  0xE4,  0x12,  0x51,  0x24,  0x92,  0x41,  0x24,  0x32, 	/* 06030 */
+	0x40,  0x27,  0xFE,  0xAE,  0x00,  0x0F,  0xFE,  0x94,  0x29,  0x42,  0xA5,  0xAE,  0x72,  0xA4,  0x2A,  0x42, 	/* 06040 */
+	0xA4,  0xAA,  0x7A,  0x80,  0x2F,  0xFE,  0xB0,  0x00,  0x07,  0xFE,  0x44,  0x24,  0x42,  0x7F,  0xA4,  0x42, 	/* 06050 */
+	0x4C,  0x24,  0xE2,  0x55,  0x26,  0x4A,  0x44,  0x27,  0xFE,  0xB2,  0x00,  0x07,  0xFE,  0x49,  0x24,  0x92, 	/* 06060 */
+	0x7F,  0xE4,  0x92,  0x49,  0x27,  0xFE,  0x49,  0x24,  0x92,  0x50,  0x27,  0xFE,  0xB3,  0x00,  0x07,  0xFE, 	/* 06070 */
+	0x44,  0xA5,  0x2A,  0x49,  0x24,  0x12,  0x72,  0x24,  0xE2,  0x45,  0x24,  0x8A,  0x70,  0x27,  0xFE,  0xB9, 	/* 06080 */
+	0x00,  0x0F,  0xFE,  0x84,  0x28,  0xA2,  0x91,  0x2E,  0x0E,  0xBF,  0xA8,  0x4A,  0x84,  0xA8,  0x72,  0x84, 	/* 06090 */
+	0x2F,  0xFE,  0xBA,  0x00,  0x07,  0xFE,  0x44,  0x24,  0x42,  0x7F,  0xE4,  0x42,  0x5F,  0xA5,  0x0A,  0x50, 	/* 060A0 */
+	0xA5,  0xFA,  0x40,  0x27,  0xFE,  0xBD,  0x00,  0x07,  0xFE,  0x40,  0x27,  0xFA,  0x44,  0x24,  0x42,  0x5F, 	/* 060B0 */
+	0x24,  0x52,  0x44,  0xA7,  0xFA,  0x40,  0x27,  0xFE,  0xBF,  0x00,  0x0F,  0xFE,  0x88,  0x2B,  0xFA,  0x90, 	/* 060C0 */
+	0x2B,  0xF2,  0xD1,  0x29,  0xF2,  0x9F,  0x29,  0x12,  0x93,  0x2F,  0xFE,  0x80,  0x00,  0x0F,  0xFE,  0x91, 	/* 060D0 */
+	0x2E,  0x1E,  0x88,  0x2F,  0xFA,  0x88,  0x28,  0xF2,  0x91,  0x29,  0x12,  0xA6,  0x2F,  0xFE,  0x83,  0x00, 	/* 060E0 */
+	0x0F,  0xFE,  0x85,  0x2B,  0xFA,  0x84,  0x2B,  0xFA,  0xA4,  0xAB,  0xFA,  0xA4,  0xAB,  0xFA,  0xA4,  0xAF, 	/* 060F0 */
+	0xFE,  0x84,  0x00,  0x0F,  0xFE,  0x80,  0x2B,  0xFA,  0x88,  0x2B,  0xFA,  0x88,  0xAF,  0xFE,  0xA0,  0xAB, 	/* 06100 */
+	0xFA,  0x80,  0x2F,  0xFE,  0x88,  0x00,  0x0F,  0xFE,  0x95,  0x2A,  0x4A,  0xDF,  0x68,  0xA2,  0xFF,  0xE9, 	/* 06110 */
+	0x1A,  0xBF,  0x6D,  0x0A,  0x8F,  0xAF,  0xFE,  0x89,  0x00,  0x0F,  0xFE,  0x84,  0x2B,  0xF2,  0x84,  0x2F, 	/* 06120 */
+	0xFE,  0x91,  0x2B,  0xFA,  0x84,  0x2B,  0xFA,  0x84,  0x2F,  0xFE,  0x8B,  0x00,  0x0F,  0xFE,  0x82,  0xAF, 	/* 06130 */
+	0xFE,  0x82,  0x2B,  0xAA,  0xAA,  0xAB,  0x9A,  0x8D,  0x6F,  0x2E,  0x84,  0x6F,  0xFE,  0x8D,  0x00,  0x0F, 	/* 06140 */
+	0xFE,  0x84,  0x2B,  0xF2,  0x85,  0x2F,  0xFE,  0x91,  0x2B,  0xF2,  0xA2,  0x2B,  0xFE,  0x82,  0x2F,  0xFE, 	/* 06150 */
+	0x8F,  0x00,  0x0F,  0xFE,  0x95,  0x2B,  0xFA,  0x84,  0x2F,  0xFE,  0x9F,  0x2E,  0x2E,  0x9E,  0x29,  0x12, 	/* 06160 */
+	0x8F,  0x2F,  0xFE,  0x92,  0x00,  0x07,  0xFE,  0x44,  0x25,  0xFA,  0x44,  0x27,  0xFE,  0x50,  0xA5,  0xFA, 	/* 06170 */
+	0x4E,  0xA7,  0x52,  0x44,  0xA7,  0xFE,  0x93,  0x00,  0x0F,  0xFE,  0x9F,  0x29,  0x12,  0xBF,  0xAA,  0x0A, 	/* 06180 */
+	0xBF,  0xAB,  0xFA,  0xA0,  0xAB,  0xFA,  0x93,  0x2F,  0xFE,  0x96,  0x00,  0x0F,  0xFE,  0x9F,  0x29,  0x12, 	/* 06190 */
+	0x9F,  0x28,  0x42,  0xFF,  0xEA,  0xEA,  0xAA,  0xAB,  0xFA,  0x80,  0x2F,  0xFE,  0x98,  0x00,  0x0F,  0xFE, 	/* 061A0 */
+	0x84,  0x2F,  0xFE,  0x95,  0x29,  0xF2,  0xBF,  0xA8,  0x12,  0xFF,  0xE9,  0x12,  0x83,  0x2F,  0xFE,  0x9C, 	/* 061B0 */
+	0x00,  0x0F,  0xFE,  0x80,  0x2B,  0xFA,  0xAA,  0xAF,  0xFE,  0x91,  0x29,  0xF2,  0xB5,  0xA9,  0x62,  0xB9, 	/* 061C0 */
+	0xAF,  0xFE,  0x9F,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x7F,  0xC0,  0x40,  0x04,  0x00,  0x40,  0x04, 	/* 061D0 */
+	0x00,  0x40,  0xFF,  0xE0,  0x00,  0xA6,  0x23,  0x02,  0x10,  0x21,  0x0F,  0x90,  0x21,  0x02,  0x10,  0x23, 	/* 061E0 */
+	0x02,  0xA8,  0x34,  0x8C,  0x44,  0x08,  0x43,  0x02,  0xA7,  0x00,  0x03,  0xFE,  0x20,  0x02,  0x20,  0x22, 	/* 061F0 */
+	0x03,  0xFC,  0x22,  0x02,  0x20,  0x22,  0x04,  0x20,  0x5F,  0xE8,  0x00,  0xA8,  0x04,  0x00,  0x40,  0xFF, 	/* 06200 */
+	0xE0,  0x80,  0x32,  0x02,  0x20,  0x7F,  0xCA,  0x20,  0x22,  0x02,  0x20,  0x3F,  0xE2,  0x00,  0xAD,  0x04, 	/* 06210 */
+	0x00,  0x40,  0x3F,  0xC0,  0x40,  0x04,  0x07,  0xFE,  0x04,  0x00,  0x40,  0x7F,  0xC0,  0x40,  0x04,  0x0F, 	/* 06220 */
+	0xFE,  0xB0,  0x01,  0x02,  0x50,  0x25,  0x0F,  0x5C,  0x27,  0x43,  0xD4,  0x25,  0x42,  0x54,  0x35,  0x8C, 	/* 06230 */
+	0x40,  0x04,  0x20,  0x3E,  0xB7,  0x20,  0x02,  0xFE,  0x21,  0x0F,  0x90,  0x21,  0x82,  0x14,  0x21,  0x22, 	/* 06240 */
+	0x90,  0x31,  0x0C,  0x10,  0x01,  0x00,  0x10,  0xB8,  0x21,  0x02,  0x10,  0x21,  0x0F,  0x92,  0x29,  0x22, 	/* 06250 */
+	0x92,  0x29,  0x22,  0x92,  0x39,  0x2C,  0x92,  0x09,  0x20,  0xFE,  0xBB,  0x20,  0x62,  0x78,  0x24,  0x0F, 	/* 06260 */
+	0x40,  0x27,  0xE2,  0x48,  0x24,  0x83,  0x48,  0xC8,  0x80,  0x88,  0x10,  0x80,  0x08,  0x80,  0x21,  0x02, 	/* 06270 */
+	0x10,  0x21,  0x0F,  0x10,  0x25,  0xE2,  0x50,  0x25,  0x02,  0x50,  0x35,  0x0C,  0x50,  0x05,  0x01,  0xFE, 	/* 06280 */
+	0x82,  0x00,  0x02,  0x7E,  0x24,  0x02,  0x40,  0xF7,  0xC2,  0x64,  0x26,  0x42,  0x54,  0x38,  0x8C,  0x98, 	/* 06290 */
+	0x12,  0x40,  0xC2,  0x87,  0x22,  0x02,  0x20,  0x27,  0xEF,  0x42,  0x28,  0x23,  0x62,  0x20,  0xA3,  0x32, 	/* 062A0 */
+	0x2C,  0x2C,  0x02,  0x00,  0x20,  0x0C,  0x8A,  0x22,  0x02,  0x20,  0x2F,  0xE2,  0x20,  0xFA,  0x02,  0x3C, 	/* 062B0 */
+	0x22,  0x42,  0x24,  0x34,  0x4C,  0x44,  0x08,  0x41,  0x18,  0x8E,  0x04,  0x02,  0x40,  0x24,  0x02,  0x7E, 	/* 062C0 */
+	0xF9,  0x22,  0x94,  0x31,  0x02,  0x30,  0x32,  0x8E,  0x48,  0x08,  0x43,  0x02,  0x8F,  0x20,  0x02,  0xFE, 	/* 062D0 */
+	0x20,  0x8F,  0x88,  0x21,  0x82,  0x34,  0x25,  0x22,  0x92,  0x31,  0x0C,  0x10,  0x01,  0x00,  0x10,  0x90, 	/* 062E0 */
+	0x04,  0x02,  0x48,  0x24,  0x82,  0x48,  0x55,  0x44,  0xE4,  0x84,  0x20,  0x40,  0x7F,  0xC0,  0x40,  0x04, 	/* 062F0 */
+	0x0F,  0xFE,  0x91,  0x01,  0x02,  0x10,  0x2F,  0xE2,  0x00,  0xFF,  0x82,  0x48,  0x24,  0x82,  0x48,  0x34, 	/* 06300 */
+	0x8C,  0x4A,  0x08,  0xA1,  0x0E,  0xA1,  0x21,  0x02,  0x10,  0x2F,  0xEF,  0x92,  0x29,  0x42,  0xFC,  0x28, 	/* 06310 */
+	0x43,  0xC4,  0xCA,  0x81,  0x10,  0x26,  0x81,  0x86,  0xA4,  0x21,  0x02,  0x10,  0x2F,  0xEF,  0x92,  0x2F, 	/* 06320 */
+	0xE2,  0x92,  0x29,  0x22,  0xFE,  0x31,  0x0C,  0x10,  0x01,  0x00,  0x10,  0xA6,  0x20,  0x02,  0x7E,  0x24, 	/* 06330 */
+	0x22,  0x42,  0xF7,  0xE2,  0x42,  0x24,  0x22,  0x42,  0x37,  0xEC,  0x00,  0x00,  0x00,  0xFF,  0xA9,  0x24, 	/* 06340 */
+	0x82,  0x48,  0x24,  0x8F,  0xFE,  0x24,  0x82,  0x48,  0x27,  0x82,  0x48,  0x34,  0x8C,  0x48,  0x04,  0x80, 	/* 06350 */
+	0x78,  0xAA,  0x20,  0x02,  0xFE,  0x21,  0x42,  0x94,  0xF5,  0x82,  0x30,  0x2F,  0xE2,  0x10,  0x39,  0x0C, 	/* 06360 */
+	0x10,  0x01,  0x00,  0x10,  0xBF,  0x22,  0x42,  0x24,  0x24,  0x4F,  0x7E,  0x2C,  0x43,  0x64,  0x25,  0x42, 	/* 06370 */
+	0x54,  0x34,  0x4C,  0x44,  0x04,  0x40,  0x4C,  0x82,  0x01,  0x83,  0xE0,  0x04,  0x07,  0xFC,  0x24,  0x8F, 	/* 06380 */
+	0xFE,  0x24,  0x82,  0x48,  0x7F,  0xC0,  0x40,  0x04,  0x0F,  0xFE,  0x88,  0x12,  0x81,  0x24,  0x22,  0xE7, 	/* 06390 */
+	0xF0,  0xA1,  0x02,  0x0A,  0x20,  0x60,  0x42,  0x7F,  0xC0,  0x40,  0x04,  0x0F,  0xFE,  0x89,  0x22,  0x02, 	/* 063A0 */
+	0x20,  0x27,  0xCF,  0x44,  0x2F,  0x43,  0x54,  0x25,  0x42,  0x64,  0x35,  0x8C,  0x42,  0x04,  0x20,  0x3E, 	/* 063B0 */
+	0x8B,  0x00,  0x27,  0xF2,  0x29,  0x22,  0x92,  0xFF,  0x22,  0x92,  0x48,  0x28,  0x46,  0x3F,  0x80,  0x40, 	/* 063C0 */
+	0x04,  0x0F,  0xFE,  0x93,  0x01,  0x02,  0x10,  0x2F,  0xE2,  0x20,  0xF2,  0x82,  0xCA,  0x23,  0x22,  0x24, 	/* 063D0 */
+	0x34,  0x8C,  0x14,  0x06,  0x21,  0x82,  0xA0,  0x20,  0x02,  0x7C,  0x24,  0x4F,  0x7C,  0x24,  0x42,  0x7C, 	/* 063E0 */
+	0x25,  0x22,  0x54,  0x34,  0x8C,  0x48,  0x07,  0x41,  0x82,  0xA2,  0x20,  0x42,  0x78,  0x24,  0x0F,  0x40, 	/* 063F0 */
+	0x27,  0xE2,  0x40,  0x24,  0x02,  0x7E,  0x36,  0x2C,  0xA2,  0x0A,  0x21,  0x3E,  0xA3,  0x0F,  0xE2,  0x00, 	/* 06400 */
+	0x27,  0xC2,  0x44,  0xFC,  0x42,  0x7C,  0x24,  0x42,  0xC4,  0x37,  0xCE,  0x00,  0x00,  0x01,  0xFE,  0xA4, 	/* 06410 */
+	0x20,  0x02,  0xFE,  0x22,  0x8F,  0x44,  0x2F,  0xA2,  0x10,  0x21,  0x02,  0xFE,  0x31,  0x0C,  0x10,  0x01, 	/* 06420 */
+	0x01,  0xFE,  0xAA,  0x28,  0x42,  0x44,  0x24,  0x8F,  0xFE,  0x24,  0x82,  0x48,  0x3F,  0xE2,  0x48,  0x34, 	/* 06430 */
+	0x8C,  0x88,  0x08,  0x81,  0x08,  0xB0,  0x22,  0x02,  0x3C,  0x22,  0x0F,  0x20,  0x2F,  0xE2,  0x00,  0x2F, 	/* 06440 */
+	0xE3,  0x20,  0xC3,  0x80,  0x24,  0x02,  0x00,  0x20,  0xB3,  0x02,  0x02,  0x3E,  0x24,  0x02,  0xA0,  0xF3, 	/* 06450 */
+	0xF2,  0x44,  0x2C,  0x42,  0x44,  0x34,  0x4C,  0x44,  0x04,  0x40,  0x4C,  0x80,  0x01,  0x83,  0xE0,  0x04, 	/* 06460 */
+	0x0F,  0xFE,  0x15,  0x2F,  0x5C,  0x15,  0x03,  0x52,  0xD4,  0xE3,  0xF8,  0x04,  0x0F,  0xFE,  0x83,  0x21, 	/* 06470 */
+	0x02,  0x18,  0x22,  0x4F,  0xFE,  0x24,  0x22,  0x7C,  0x29,  0x02,  0x10,  0x3F,  0xEC,  0x30,  0x04,  0x81, 	/* 06480 */
+	0x86,  0x86,  0x21,  0x02,  0x3C,  0x24,  0x8F,  0xFE,  0x25,  0x22,  0x7E,  0x25,  0x23,  0x52,  0xC7,  0xE0, 	/* 06490 */
+	0x42,  0x08,  0x21,  0x06,  0x8B,  0x20,  0x02,  0xFE,  0x29,  0x22,  0xFE,  0xF9,  0x22,  0x92,  0x2F,  0xE2, 	/* 064A0 */
+	0x10,  0x37,  0xEC,  0x10,  0x01,  0x00,  0xFF,  0x8E,  0x00,  0xC2,  0x0A,  0x2F,  0xE2,  0x88,  0xF8,  0xA2, 	/* 064B0 */
+	0xEA,  0x2A,  0xC3,  0xA4,  0xCA,  0x41,  0xAD,  0x25,  0x34,  0x21,  0x92,  0x20,  0xE2,  0xF0,  0x25,  0x42, 	/* 064C0 */
+	0x52,  0xF8,  0x22,  0x08,  0x2F,  0xE2,  0x08,  0x34,  0x8C,  0x28,  0x00,  0x80,  0x18,  0x93,  0x21,  0x82, 	/* 064D0 */
+	0xF0,  0x24,  0xA2,  0x2C,  0xFF,  0x02,  0x08,  0x2F,  0xE2,  0x08,  0x34,  0x8C,  0x28,  0x00,  0x80,  0x18, 	/* 064E0 */
+	0x94,  0x21,  0x42,  0x12,  0x27,  0xFF,  0x90,  0x27,  0xE2,  0x52,  0x27,  0xE2,  0x52,  0x37,  0xEC,  0x52, 	/* 064F0 */
+	0x05,  0x20,  0x56,  0x96,  0x24,  0x83,  0xFE,  0x24,  0x8F,  0x48,  0x25,  0x02,  0x92,  0x29,  0x43,  0x98, 	/* 06500 */
+	0x29,  0x0C,  0x90,  0x09,  0x20,  0x8E,  0x9C,  0x11,  0x0F,  0xFE,  0x11,  0x03,  0xB8,  0x55,  0x49,  0x53, 	/* 06510 */
+	0x11,  0x00,  0x40,  0x7F,  0xC0,  0x40,  0x04,  0x0F,  0xFE,  0x9F,  0x01,  0x84,  0x14,  0x5F,  0xE4,  0x10, 	/* 06520 */
+	0xFD,  0x25,  0x52,  0x55,  0x45,  0xCC,  0x62,  0x8C,  0xCA,  0x31,  0x60,  0x22,  0xA0,  0x21,  0x02,  0x7C, 	/* 06530 */
+	0x24,  0x4F,  0x7C,  0x24,  0x02,  0x7E,  0x24,  0x23,  0x7E,  0xC1,  0x01,  0xFF,  0x01,  0x00,  0x10,  0xA3, 	/* 06540 */
+	0x21,  0x02,  0x10,  0x2F,  0xEF,  0x44,  0x24,  0x42,  0x6A,  0x29,  0x23,  0xFF,  0x21,  0x0C,  0x10,  0x01, 	/* 06550 */
+	0x00,  0x10,  0xB4,  0x21,  0x02,  0xFE,  0x21,  0x0F,  0xBC,  0x2A,  0x42,  0xBC,  0x2A,  0x43,  0xBC,  0x6A, 	/* 06560 */
+	0x48,  0xBC,  0x08,  0x00,  0xFE,  0xB7,  0x22,  0x02,  0x20,  0xFF,  0x82,  0x28,  0xFA,  0x85,  0x28,  0x56, 	/* 06570 */
+	0x8F,  0xB8,  0x22,  0x8F,  0x4A,  0x24,  0xA2,  0x86,  0xB9,  0x21,  0x02,  0x10,  0x2F,  0xE2,  0x44,  0xF2, 	/* 06580 */
+	0x83,  0xFE,  0x20,  0x02,  0x7C,  0x34,  0x4C,  0x44,  0x04,  0x40,  0x7C,  0xBA,  0x11,  0x07,  0xFC,  0x11, 	/* 06590 */
+	0x01,  0xF0,  0x11,  0x01,  0xF0,  0x11,  0x0F,  0xFE,  0x24,  0x8D,  0xF6,  0x04,  0x07,  0xFC,  0xBC,  0x21, 	/* 065A0 */
+	0x02,  0xFE,  0x21,  0x0F,  0x28,  0x24,  0x43,  0xFE,  0x20,  0x43,  0xF4,  0xE9,  0x40,  0xF4,  0x00,  0x40, 	/* 065B0 */
+	0x0C,  0x80,  0x20,  0x02,  0xFE,  0x28,  0x2F,  0xFE,  0x28,  0x82,  0xAA,  0x2A,  0xA3,  0xBE,  0xE8,  0x81, 	/* 065C0 */
+	0x4A,  0x14,  0xA2,  0x7E,  0x82,  0x24,  0x81,  0x50,  0xFF,  0xE8,  0x02,  0x9F,  0x21,  0x10,  0x11,  0x01, 	/* 065D0 */
+	0xF0,  0x04,  0x07,  0xFC,  0x04,  0x0F,  0xFE,  0x85,  0x00,  0x0F,  0xBE,  0xA0,  0x2F,  0xA4,  0x89,  0x4F, 	/* 065E0 */
+	0x88,  0xA1,  0x4F,  0xE2,  0x04,  0x03,  0xF8,  0x04,  0x0F,  0xFE,  0x86,  0x02,  0x42,  0x28,  0x27,  0xE2, 	/* 065F0 */
+	0xC8,  0xF4,  0x82,  0x7E,  0x24,  0x82,  0x48,  0x37,  0xEC,  0x48,  0x04,  0x80,  0x7E,  0x8A,  0x00,  0x0F, 	/* 06600 */
+	0xFE,  0x11,  0x0F,  0x1E,  0x80,  0x2F,  0x1E,  0x11,  0x0F,  0xFE,  0x04,  0x07,  0xFC,  0x04,  0x0F,  0xFE, 	/* 06610 */
+	0x8B,  0x20,  0x02,  0xEE,  0x2A,  0xAF,  0xAA,  0x2E,  0xE2,  0xAA,  0x2A,  0xA2,  0xEE,  0x3A,  0xAC,  0xAA, 	/* 06620 */
+	0x13,  0x22,  0x66,  0x95,  0x02,  0x0F,  0xFE,  0xA4,  0x0C,  0x7C,  0xAC,  0x4B,  0x7C,  0xE4,  0x48,  0x4C, 	/* 06630 */
+	0x84,  0x07,  0xFC,  0x04,  0x0F,  0xFE,  0x99,  0x20,  0x02,  0xFE,  0x22,  0x82,  0xFE,  0xFA,  0xA2,  0xAA, 	/* 06640 */
+	0x2F,  0xE2,  0x10,  0x37,  0xCC,  0x10,  0x01,  0x01,  0xFE,  0x9D,  0x20,  0x02,  0x7C,  0x24,  0x4F,  0x5C, 	/* 06650 */
+	0x25,  0x42,  0xFE,  0x28,  0x22,  0xBA,  0x3A,  0xAC,  0xAA,  0x0B,  0xA0,  0x86,  0xA1,  0x20,  0x02,  0xFC, 	/* 06660 */
+	0x48,  0x4C,  0xFC,  0x42,  0x07,  0xFE,  0x4A,  0x85,  0x24,  0x04,  0x03,  0xF8,  0x04,  0x0F,  0xFE,  0xA4, 	/* 06670 */
+	0x27,  0xC2,  0x44,  0x27,  0xCF,  0x44,  0x27,  0xC2,  0x00,  0x2F,  0xE3,  0x10,  0xE9,  0xE0,  0x90,  0x17, 	/* 06680 */
+	0x02,  0x0F,  0xAA,  0x04,  0x42,  0xFE,  0x24,  0x42,  0x7C,  0xF4,  0x42,  0x7C,  0x24,  0x43,  0xFE,  0x2A, 	/* 06690 */
+	0x8C,  0xEC,  0x08,  0x00,  0x7E,  0xAF,  0x04,  0x03,  0xF8,  0x04,  0x07,  0xFC,  0x20,  0x8F,  0xBE,  0x20, 	/* 066A0 */
+	0x8F,  0xFE,  0x00,  0x0F,  0xFC,  0x12,  0x2E,  0x1E,  0xB0,  0x20,  0x02,  0xFE,  0x2A,  0x42,  0xBC,  0xFA, 	/* 066B0 */
+	0x42,  0xBC,  0x29,  0x02,  0xFE,  0x3A,  0x4C,  0x98,  0x0E,  0x40,  0xFE,  0xB1,  0x20,  0x0F,  0xBE,  0x22, 	/* 066C0 */
+	0x2F,  0xE4,  0x4B,  0xE3,  0x22,  0xFE,  0xA2,  0x2C,  0xFA,  0x42,  0x2C,  0x23,  0x22,  0x21,  0xB4,  0x20, 	/* 066D0 */
+	0x02,  0x7C,  0x24,  0x42,  0x7C,  0xF4,  0x42,  0xFF,  0x24,  0x02,  0xFE,  0x32,  0xAC,  0xD2,  0x02,  0x20, 	/* 066E0 */
+	0xCC,  0xB5,  0x02,  0x02,  0x24,  0x2F,  0xC2,  0x28,  0xFF,  0xE2,  0x20,  0x27,  0xC2,  0xC4,  0x37,  0xCC, 	/* 066F0 */
+	0x44,  0x04,  0x40,  0x7C,  0xBA,  0x20,  0x02,  0xFE,  0x29,  0x22,  0xFE,  0xF9,  0x22,  0xFE,  0x22,  0x83, 	/* 06700 */
+	0xCC,  0xCC,  0xA3,  0x48,  0x04,  0x80,  0x88,  0xBD,  0x20,  0x02,  0xFE,  0x2A,  0xA2,  0xFE,  0xF0,  0x02, 	/* 06710 */
+	0xFE,  0x21,  0x02,  0x10,  0x39,  0xCC,  0x90,  0x09,  0x00,  0xFE,  0x80,  0x4F,  0xE4,  0x82,  0x4F,  0xEF, 	/* 06720 */
+	0xC4,  0x4A,  0x84,  0xFE,  0x5A,  0x86,  0xA8,  0xCF,  0xE1,  0x28,  0x24,  0x80,  0x88,  0x81,  0x00,  0x07, 	/* 06730 */
+	0xFC,  0x44,  0x47,  0xFC,  0x44,  0x47,  0xFC,  0xC0,  0x63,  0x18,  0xC4,  0x63,  0xF8,  0x04,  0x0F,  0xFE, 	/* 06740 */
+	0x8A,  0x21,  0x02,  0x20,  0x2F,  0xCF,  0x94,  0x2F,  0xC2,  0x94,  0x2F,  0xC2,  0x34,  0x3B,  0xAC,  0x5E, 	/* 06750 */
+	0x09,  0x23,  0x0E,  0x8B,  0x11,  0x05,  0x54,  0x95,  0x42,  0xA8,  0x44,  0x4F,  0xFE,  0x84,  0x20,  0x40, 	/* 06760 */
+	0x7F,  0xC0,  0x40,  0x04,  0x0F,  0xFE,  0x91,  0x44,  0x02,  0x9E,  0xFD,  0x21,  0x1E,  0x55,  0x27,  0xDE, 	/* 06770 */
+	0x11,  0x26,  0x66,  0x04,  0x03,  0xFC,  0x04,  0x07,  0xFE,  0x92,  0x00,  0x85,  0xC8,  0x57,  0xE5,  0x48, 	/* 06780 */
+	0xF4,  0x85,  0xFF,  0x54,  0x45,  0x7E,  0x76,  0x4D,  0xD4,  0x00,  0x40,  0x0C,  0x94,  0x24,  0x83,  0xFE, 	/* 06790 */
+	0x24,  0x8F,  0x30,  0x24,  0x82,  0x84,  0x37,  0xA2,  0x00,  0x3F,  0xCC,  0x84,  0x08,  0x40,  0xFC,  0x97, 	/* 067A0 */
+	0x41,  0x02,  0x28,  0x8C,  0x64,  0x7C,  0x01,  0x02,  0xFE,  0x45,  0x48,  0xB2,  0x04,  0x07,  0xFC,  0x04, 	/* 067B0 */
+	0x0F,  0xFE,  0x98,  0x01,  0x02,  0xFE,  0x29,  0x0F,  0xFE,  0x29,  0x22,  0xFF,  0x29,  0x23,  0xFE,  0xC8, 	/* 067C0 */
+	0x01,  0x7E,  0x24,  0x20,  0x7E,  0x99,  0x01,  0x02,  0xFE,  0x27,  0xC2,  0x44,  0xF7,  0xC2,  0x00,  0x2F, 	/* 067D0 */
+	0xE2,  0x82,  0x3B,  0xAC,  0xAA,  0x0B,  0xA0,  0x86,  0x9A,  0x20,  0x02,  0xFE,  0x28,  0x22,  0x7E,  0xF3, 	/* 067E0 */
+	0x02,  0xDA,  0x22,  0xC2,  0xD8,  0x32,  0xCC,  0x4B,  0x18,  0x80,  0x30,  0x9E,  0x04,  0x0F,  0xFE,  0x91, 	/* 067F0 */
+	0x27,  0xFC,  0x11,  0x07,  0xFC,  0x11,  0x0F,  0xFE,  0x24,  0x8D,  0xF6,  0x04,  0x07,  0xFC,  0xA2,  0x22, 	/* 06800 */
+	0x02,  0xFC,  0x28,  0x4F,  0x84,  0x2F,  0xC2,  0x80,  0x2F,  0xE3,  0x80,  0xCF,  0xE1,  0x52,  0x1A,  0xA2, 	/* 06810 */
+	0x0C,  0xA9,  0x24,  0x02,  0x7E,  0x28,  0x0F,  0x7C,  0x24,  0x42,  0x7C,  0x20,  0x07,  0xFE,  0xCA,  0xA0, 	/* 06820 */
+	0xAA,  0x0A,  0xA3,  0xFF,  0xAB,  0x01,  0x02,  0xFE,  0x21,  0x02,  0x7C,  0xFC,  0x42,  0x7C,  0x24,  0x42, 	/* 06830 */
+	0x7C,  0x34,  0x4D,  0xFF,  0x02,  0x40,  0xC2,  0xB0,  0x44,  0x02,  0x7E,  0x88,  0x04,  0x7C,  0x05,  0x45, 	/* 06840 */
+	0xFE,  0x89,  0x48,  0xFC,  0x04,  0x07,  0xFC,  0x04,  0x0F,  0xFE,  0xB2,  0x24,  0x02,  0x7E,  0x2C,  0x4F, 	/* 06850 */
+	0x7C,  0x24,  0x42,  0xFE,  0x24,  0x02,  0xFE,  0x3A,  0xAD,  0x2A,  0x05,  0x20,  0x0C,  0xB5,  0x02,  0x07, 	/* 06860 */
+	0xFE,  0x45,  0x05,  0xFE,  0x45,  0x25,  0xFE,  0x49,  0x05,  0xEE,  0x42,  0x05,  0xFC,  0x42,  0x0B,  0xFE, 	/* 06870 */
+	0xB9,  0x10,  0x6F,  0xF8,  0x56,  0x07,  0xFE,  0x56,  0x47,  0xE4,  0x12,  0x4F,  0xC4,  0x14,  0x43,  0xF8, 	/* 06880 */
+	0x04,  0x0F,  0xFE,  0xBE,  0x21,  0x0F,  0xD0,  0x4F,  0xCF,  0x94,  0x13,  0x4F,  0x94,  0x12,  0xC3,  0x42, 	/* 06890 */
+	0x04,  0x07,  0xFC,  0x04,  0x0F,  0xFE,  0x83,  0x42,  0x05,  0xFC,  0x48,  0x84,  0x50,  0xFF,  0xE4,  0x88, 	/* 068A0 */
+	0x4F,  0x84,  0x88,  0x7F,  0x8C,  0x50,  0x09,  0x23,  0x0E,  0x85,  0x7F,  0xE5,  0x54,  0x7C,  0x85,  0x7E, 	/* 068B0 */
+	0x7C,  0xA1,  0x0C,  0x1C,  0x8E,  0x58,  0x04,  0x03,  0xF8,  0x04,  0x0F,  0xFE,  0x93,  0x11,  0x0F,  0xFE, 	/* 068C0 */
+	0x11,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x8F,  0xFE,  0x24,  0x85,  0xF4,  0x84,  0x27,  0xFC,  0x97, 	/* 068D0 */
+	0x04,  0x42,  0x28,  0x2F,  0xE2,  0x92,  0xFF,  0xE2,  0x92,  0x2F,  0xE2,  0x44,  0x37,  0xCC,  0x44,  0x04, 	/* 068E0 */
+	0x40,  0x7C,  0x9C,  0xF4,  0x49,  0x28,  0xAF,  0xEE,  0x20,  0x9E,  0xC9,  0x30,  0xF5,  0x88,  0x96,  0x86, 	/* 068F0 */
+	0x07,  0xF8,  0x04,  0x0F,  0xFE,  0x9F,  0x02,  0x04,  0x3C,  0x42,  0x05,  0xFE,  0xF5,  0xA5,  0xE0,  0x57, 	/* 06900 */
+	0xE5,  0x28,  0x7A,  0xAD,  0xEE,  0x22,  0x85,  0xFF,  0xA8,  0x3F,  0x82,  0x48,  0x3F,  0x82,  0x48,  0x7F, 	/* 06910 */
+	0xC0,  0x40,  0xFF,  0xE5,  0x24,  0x95,  0x27,  0xFC,  0x04,  0x0F,  0xFE,  0xAB,  0x24,  0x42,  0xFE,  0x22, 	/* 06920 */
+	0x82,  0xFE,  0xFA,  0xA2,  0xCE,  0x28,  0x22,  0xFE,  0x30,  0x8C,  0xFF,  0x04,  0x80,  0x18,  0xAE,  0x71, 	/* 06930 */
+	0x05,  0xFE,  0x52,  0x86,  0x5E,  0x5B,  0xE5,  0x22,  0x73,  0xE4,  0x22,  0x44,  0x63,  0xFC,  0x04,  0x0F, 	/* 06940 */
+	0xFF,  0xB3,  0x02,  0x02,  0xFC,  0x2A,  0x8F,  0xFE,  0x24,  0x82,  0xFC,  0x28,  0x42,  0xFC,  0x38,  0x4C, 	/* 06950 */
+	0xFC,  0x04,  0x41,  0x82,  0xB8,  0x24,  0x82,  0xFE,  0x25,  0x82,  0xFC,  0xF1,  0x02,  0xFE,  0x22,  0x02, 	/* 06960 */
+	0x7C,  0x3C,  0x4C,  0x7C,  0x04,  0x40,  0x7C,  0xB9,  0x2E,  0xE2,  0xAA,  0x2E,  0xEF,  0xAA,  0x2E,  0xE2, 	/* 06970 */
+	0x82,  0x2B,  0xA2,  0xAA,  0x3B,  0xAC,  0xAA,  0x0B,  0xA0,  0x86,  0xBA,  0x22,  0x02,  0xFE,  0x2B,  0x62, 	/* 06980 */
+	0xDA,  0xFF,  0xE2,  0xBA,  0x2D,  0x62,  0x92,  0x31,  0x0C,  0xFE,  0x02,  0x80,  0xC6,  0xBB,  0x21,  0x02, 	/* 06990 */
+	0xFE,  0x25,  0x42,  0x54,  0xFB,  0xA2,  0xFF,  0x20,  0x02,  0xFE,  0x3A,  0xAC,  0xBA,  0x08,  0x20,  0xFE, 	/* 069A0 */
+	0xBE,  0x0B,  0xCF,  0x24,  0x57,  0xCF,  0xA4,  0x33,  0xCD,  0xB4,  0x2A,  0x8D,  0x76,  0x04,  0x07,  0xFC, 	/* 069B0 */
+	0x04,  0x0F,  0xFE,  0x81,  0x78,  0x84,  0xBE,  0x79,  0x44,  0x3F,  0x78,  0x84,  0xBE,  0xB8,  0x80,  0x48, 	/* 069C0 */
+	0x7F,  0xC0,  0x40,  0x04,  0x0F,  0xFE,  0x85,  0x04,  0x0F,  0xFE,  0x22,  0x85,  0x7E,  0x2C,  0x85,  0x7C, 	/* 069D0 */
+	0xF4,  0x82,  0x7E,  0x44,  0x03,  0xF8,  0x04,  0x0F,  0xFE,  0x87,  0x42,  0x07,  0xFE,  0x50,  0x4F,  0x74, 	/* 069E0 */
+	0x55,  0x45,  0xFC,  0x40,  0x05,  0xF8,  0x68,  0x8C,  0xF8,  0x08,  0x83,  0xFE,  0x8A,  0x01,  0x02,  0xFE, 	/* 069F0 */
+	0x21,  0x02,  0xFE,  0xFA,  0xA2,  0xFE,  0x21,  0x03,  0xFF,  0x2D,  0x4D,  0x48,  0x27,  0x40,  0xC2,  0x8C, 	/* 06A00 */
+	0x21,  0x02,  0xFE,  0x24,  0x8F,  0xAC,  0x32,  0xA2,  0xFE,  0x22,  0x83,  0xFE,  0xCD,  0x23,  0x4C,  0x07, 	/* 06A10 */
+	0x41,  0xC2,  0x91,  0x38,  0x02,  0x3C,  0xFC,  0x4A,  0x64,  0x51,  0x4F,  0xC8,  0x49,  0x47,  0xA2,  0x04, 	/* 06A20 */
+	0x03,  0xF8,  0x04,  0x0F,  0xFE,  0x93,  0x00,  0x07,  0xFE,  0x54,  0xC5,  0xEA,  0x53,  0xE5,  0xE8,  0x53, 	/* 06A30 */
+	0x49,  0x62,  0x04,  0x03,  0xF8,  0x04,  0x0F,  0xFE,  0x95,  0x42,  0x05,  0xFE,  0x48,  0x84,  0xF8,  0xFF, 	/* 06A40 */
+	0xE5,  0x02,  0x4F,  0x84,  0x62,  0x7B,  0x4C,  0x58,  0x19,  0x60,  0x60,  0x97,  0x22,  0x02,  0xFC,  0x22, 	/* 06A50 */
+	0x4F,  0xFE,  0x22,  0x02,  0xFE,  0x2D,  0x43,  0x2A,  0xDF,  0xC1,  0x54,  0x15,  0x43,  0xFE,  0x98,  0x3F, 	/* 06A60 */
+	0x82,  0x48,  0x3F,  0x82,  0x48,  0xFF,  0xEA,  0xAA,  0xFB,  0xEA,  0xAA,  0xFF,  0xE3,  0xF8,  0x04,  0x0F, 	/* 06A70 */
+	0xFE,  0x99,  0x21,  0x02,  0xFE,  0x2A,  0x8F,  0xFE,  0x2A,  0x82,  0xFE,  0x2D,  0x43,  0xFC,  0xCD,  0x41, 	/* 06A80 */
+	0x7C,  0x12,  0x42,  0xC2,  0x9C,  0x4F,  0xC4,  0x84,  0x5F,  0xEE,  0x10,  0x5F,  0xE5,  0x9A,  0x55,  0x64, 	/* 06A90 */
+	0xFC,  0x60,  0x09,  0xFE,  0x04,  0x81,  0xF4,  0x9E,  0x21,  0x02,  0xFF,  0x2A,  0xA2,  0xFE,  0xF0,  0x02, 	/* 06AA0 */
+	0xD6,  0x2D,  0x62,  0x28,  0x3C,  0xAC,  0xAA,  0x03,  0x40,  0xE2,  0x9F,  0x22,  0x0F,  0xFE,  0x48,  0x4F, 	/* 06AB0 */
+	0xFC,  0x4A,  0x07,  0xBC,  0x4A,  0x25,  0x9E,  0x04,  0x03,  0xF8,  0x04,  0x0F,  0xFE,  0xA4,  0x21,  0x03, 	/* 06AC0 */
+	0xFE,  0x2A,  0xAF,  0xEE,  0x22,  0x82,  0xFE,  0x22,  0x83,  0xFE,  0xC6,  0x21,  0xD4,  0x06,  0x80,  0xC6, 	/* 06AD0 */
+	0xA5,  0x20,  0x02,  0xFF,  0x2A,  0xAF,  0xBE,  0x2B,  0xE2,  0x88,  0x2F,  0xE2,  0xD5,  0x3B,  0xEC,  0xAA, 	/* 06AE0 */
+	0x0A,  0xA1,  0x7F,  0xAB,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0xFF,  0xE0,  0x40,  0x04,  0x00,  0x40, 	/* 06AF0 */
+	0x04,  0x00,  0x40,  0x7F,  0xC0,  0x00,  0xAC,  0x00,  0x00,  0x08,  0x07,  0x07,  0xC0,  0x04,  0x00,  0x40, 	/* 06B00 */
+	0xFF,  0xE0,  0x40,  0x04,  0x00,  0x40,  0x7F,  0xC0,  0x00,  0xAE,  0x21,  0x02,  0x10,  0x21,  0x0A,  0x10, 	/* 06B10 */
+	0x7F,  0xE2,  0x10,  0x21,  0x06,  0x10,  0xA1,  0x02,  0x10,  0x2F,  0xC2,  0x00,  0xAF,  0x11,  0x05,  0x10, 	/* 06B20 */
+	0x51,  0x05,  0x10,  0xFF,  0xF1,  0x10,  0xF1,  0x05,  0x10,  0x51,  0x05,  0x10,  0x91,  0x01,  0x7C,  0xB0, 	/* 06B30 */
+	0x02,  0x07,  0xFE,  0x02,  0x03,  0xFC,  0x00,  0x03,  0xFC,  0x24,  0x43,  0xFC,  0x20,  0x04,  0x00,  0x40, 	/* 06B40 */
+	0x08,  0x00,  0xB1,  0x04,  0x03,  0xF8,  0x04,  0x0F,  0xFE,  0x00,  0x0F,  0xFE,  0x90,  0x29,  0x02,  0x1F, 	/* 06B50 */
+	0x01,  0x00,  0x10,  0x40,  0xFC,  0xB2,  0x04,  0x0F,  0xFE,  0x04,  0x03,  0xF8,  0x00,  0x0F,  0xFE,  0x80, 	/* 06B60 */
+	0x29,  0x22,  0x12,  0x01,  0x22,  0x22,  0x2C,  0x1E,  0xB7,  0x04,  0x0F,  0xFE,  0x04,  0x03,  0xF8,  0x00, 	/* 06B70 */
+	0x0F,  0xFE,  0x8A,  0x2B,  0xFA,  0x2A,  0x83,  0xF8,  0x0A,  0x0F,  0xFE,  0xB9,  0x04,  0x0F,  0xFE,  0x04, 	/* 06B80 */
+	0x03,  0xF8,  0x00,  0x0F,  0xFE,  0x80,  0x2B,  0xFA,  0x20,  0x83,  0xF8,  0x11,  0x0F,  0xFE,  0xBA,  0x04, 	/* 06B90 */
+	0x0F,  0xFE,  0x04,  0x03,  0xF8,  0x00,  0x0F,  0xFE,  0x8A,  0x2B,  0xBA,  0x20,  0x83,  0xB8,  0x0A,  0x0F, 	/* 06BA0 */
+	0xFE,  0xBB,  0x1F,  0xE4,  0x14,  0x45,  0xCF,  0x70,  0x48,  0xE5,  0xFC,  0x48,  0x44,  0xFC,  0x78,  0x4C, 	/* 06BB0 */
+	0xFC,  0x08,  0x40,  0x8C,  0xBC,  0x04,  0x07,  0xFC,  0x04,  0x0F,  0xFE,  0x80,  0x2B,  0xFA,  0x0A,  0x03, 	/* 06BC0 */
+	0xB8,  0x20,  0x83,  0xB8,  0x0A,  0x0F,  0xFE,  0xBD,  0x04,  0x07,  0xFC,  0x04,  0x0F,  0xFE,  0x00,  0x27, 	/* 06BD0 */
+	0xF8,  0x04,  0x0F,  0xFE,  0x7A,  0x44,  0x94,  0x78,  0x40,  0x0C,  0x82,  0x08,  0x00,  0x80,  0x08,  0x01, 	/* 06BE0 */
+	0xF8,  0x10,  0x82,  0x10,  0x51,  0x08,  0xA0,  0x04,  0x00,  0xA0,  0x31,  0x8C,  0x06,  0x89,  0x04,  0x0F, 	/* 06BF0 */
+	0xFE,  0x09,  0x02,  0x98,  0x29,  0x45,  0x32,  0x88,  0x21,  0xF8,  0x69,  0x00,  0x60,  0x19,  0x8E,  0x06, 	/* 06C00 */
+	0x8A,  0x08,  0x00,  0x80,  0x88,  0x09,  0xF8,  0x50,  0x82,  0x10,  0x51,  0x08,  0xA0,  0x04,  0x00,  0xA0, 	/* 06C10 */
+	0x31,  0x8C,  0x06,  0x8F,  0x00,  0x0F,  0xFE,  0x08,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8, 	/* 06C20 */
+	0x1F,  0x07,  0x10,  0x0E,  0x0F,  0x1E,  0x90,  0x0F,  0x83,  0x10,  0xFF,  0xE4,  0x92,  0x7F,  0xE2,  0x04, 	/* 06C30 */
+	0x3F,  0xC2,  0x04,  0x3F,  0xC1,  0x88,  0xE7,  0x03,  0x8E,  0x95,  0x04,  0x00,  0x40,  0x0F,  0xC0,  0x84, 	/* 06C40 */
+	0x10,  0x42,  0xC8,  0x42,  0x80,  0x10,  0x02,  0x00,  0x40,  0x18,  0x06,  0x00,  0x96,  0x21,  0x02,  0x10, 	/* 06C50 */
+	0x3D,  0x02,  0x50,  0x45,  0x06,  0x58,  0x99,  0x40,  0x92,  0x11,  0x01,  0x10,  0x21,  0x04,  0x10,  0x98, 	/* 06C60 */
+	0x20,  0x02,  0x1E,  0x3D,  0x22,  0x52,  0x45,  0x25,  0x52,  0x89,  0x20,  0x92,  0x11,  0xC1,  0x10,  0x21, 	/* 06C70 */
+	0x04,  0x10,  0x99,  0x00,  0x07,  0xFC,  0x40,  0x47,  0xFC,  0x44,  0x44,  0xF4,  0x49,  0x45,  0x54,  0x62, 	/* 06C80 */
+	0x44,  0x45,  0x48,  0x39,  0x01,  0x9A,  0x04,  0x00,  0x78,  0x08,  0x83,  0x50,  0x06,  0x81,  0x9E,  0x62, 	/* 06C90 */
+	0x20,  0xE4,  0x31,  0x80,  0x30,  0x0C,  0x07,  0x00,  0x9B,  0x00,  0x03,  0xF0,  0x01,  0x01,  0xF0,  0x01, 	/* 06CA0 */
+	0x0F,  0xFE,  0x08,  0x01,  0xF8,  0x71,  0x00,  0xA0,  0x0C,  0x07,  0x00,  0x9C,  0x04,  0x00,  0x40,  0xFF, 	/* 06CB0 */
+	0xE1,  0x20,  0x13,  0xC2,  0x24,  0x65,  0x4A,  0xA8,  0x31,  0x02,  0x30,  0x2C,  0x83,  0x06,  0xA2,  0x12, 	/* 06CC0 */
+	0x0F,  0xFE,  0x12,  0x07,  0xFC,  0x4A,  0x47,  0xFC,  0x00,  0x0F,  0xFE,  0x8F,  0x23,  0x90,  0x06,  0x07, 	/* 06CD0 */
+	0x80,  0xA5,  0x01,  0x0F,  0x9C,  0xAA,  0x4F,  0xD8,  0xA9,  0x0F,  0xA8,  0x24,  0xEF,  0x92,  0x32,  0xA6, 	/* 06CE0 */
+	0x84,  0xA1,  0x82,  0x60,  0xA7,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0xFF,  0xE0,  0x40,  0x0A,  0x00, 	/* 06CF0 */
+	0xA0,  0x11,  0x01,  0x10,  0x20,  0x8C,  0x06,  0xA9,  0x00,  0x07,  0xFC,  0x04,  0x00,  0x40,  0x04,  0x0F, 	/* 06D00 */
+	0xFE,  0x04,  0x00,  0xA0,  0x0A,  0x01,  0x10,  0x20,  0x8C,  0x06,  0xAA,  0x04,  0x00,  0x40,  0x04,  0x07, 	/* 06D10 */
+	0xFE,  0x04,  0x00,  0x40,  0x0A,  0x00,  0xA0,  0x11,  0x01,  0x88,  0x24,  0x4C,  0x02,  0xAB,  0x04,  0x00, 	/* 06D20 */
+	0x40,  0x04,  0x07,  0xFC,  0x04,  0x00,  0x40,  0xFF,  0xE0,  0xA0,  0x0A,  0x01,  0x10,  0x20,  0x8C,  0x06, 	/* 06D30 */
+	0xAC,  0x04,  0x00,  0x40,  0x3F,  0x80,  0x48,  0x04,  0x80,  0x48,  0xFF,  0xE0,  0x40,  0x06,  0x00,  0x90, 	/* 06D40 */
+	0x30,  0x8C,  0x06,  0xAD,  0x01,  0x80,  0xE0,  0x74,  0x00,  0x40,  0x04,  0x0F,  0xFE,  0x04,  0x00,  0xC0, 	/* 06D50 */
+	0x0A,  0x01,  0x10,  0x20,  0x8C,  0x06,  0xAE,  0x04,  0x00,  0x40,  0x3F,  0x82,  0x48,  0x24,  0x82,  0x48, 	/* 06D60 */
+	0xFF,  0xE0,  0xC0,  0x0A,  0x01,  0x10,  0x20,  0x8C,  0x06,  0xB1,  0x04,  0x02,  0x40,  0x24,  0x03,  0xF8, 	/* 06D70 */
+	0x44,  0x04,  0x40,  0xFF,  0xE0,  0x40,  0x0A,  0x01,  0x10,  0x20,  0x8C,  0x06,  0xB2,  0x04,  0x00,  0x40, 	/* 06D80 */
+	0xFF,  0xE0,  0x40,  0x0A,  0x03,  0x18,  0xC4,  0x60,  0x40,  0x7F,  0xC0,  0x40,  0x04,  0x00,  0x40,  0xB7, 	/* 06D90 */
+	0x04,  0x0F,  0xFE,  0x04,  0x07,  0xF8,  0x04,  0x87,  0xF8,  0x44,  0x07,  0xFE,  0x0A,  0x21,  0x14,  0x20, 	/* 06DA0 */
+	0x8C,  0x06,  0xB8,  0x04,  0x0F,  0xFE,  0x0A,  0x03,  0x18,  0xDF,  0x60,  0x00,  0x7F,  0xC0,  0x80,  0x0F, 	/* 06DB0 */
+	0x81,  0x08,  0x00,  0x80,  0x30,  0xBE,  0x04,  0x00,  0x40,  0xFF,  0xE2,  0x48,  0x24,  0x82,  0x48,  0x55, 	/* 06DC0 */
+	0x48,  0x62,  0x0A,  0x01,  0x10,  0x20,  0x8C,  0x06,  0x84,  0x04,  0x00,  0x40,  0xFF,  0xE1,  0x50,  0x24, 	/* 06DD0 */
+	0x8F,  0xFE,  0x24,  0x83,  0xF8,  0x24,  0x83,  0xF8,  0x04,  0x20,  0x3E,  0x87,  0x04,  0x07,  0xFC,  0x0A, 	/* 06DE0 */
+	0x01,  0x10,  0x60,  0x8F,  0xFE,  0x00,  0x83,  0xE8,  0x22,  0x83,  0xE8,  0x00,  0x80,  0x18,  0x88,  0x04, 	/* 06DF0 */
+	0x0F,  0xFE,  0x0A,  0x01,  0x10,  0x3F,  0x8C,  0x06,  0x7F,  0xC0,  0x40,  0x15,  0x82,  0x44,  0x44,  0x20, 	/* 06E00 */
+	0xC0,  0x89,  0x04,  0x07,  0xFC,  0x04,  0x03,  0xF8,  0x0A,  0x0F,  0xFE,  0x24,  0x8D,  0xF6,  0x04,  0x03, 	/* 06E10 */
+	0xF8,  0x04,  0x00,  0x40,  0x8E,  0x04,  0x0F,  0xFE,  0x0A,  0x03,  0x18,  0xC4,  0x63,  0xF8,  0x04,  0x07, 	/* 06E20 */
+	0xFC,  0x04,  0x03,  0xF8,  0x04,  0x0F,  0xFE,  0x8F,  0x04,  0x07,  0xFC,  0x04,  0x03,  0xFC,  0x0A,  0x0F, 	/* 06E30 */
+	0xFE,  0x21,  0x8D,  0xE6,  0x04,  0x07,  0xFC,  0x1B,  0x06,  0x0C,  0x90,  0x08,  0x01,  0xF0,  0xE2,  0x07, 	/* 06E40 */
+	0xFC,  0x4A,  0x44,  0xA4,  0x71,  0xC4,  0x44,  0xFF,  0xE0,  0x40,  0x1B,  0x0E,  0x0E,  0x91,  0x10,  0x07, 	/* 06E50 */
+	0xBE,  0x11,  0x27,  0xD2,  0x11,  0x21,  0xA2,  0xE4,  0xC0,  0x40,  0xFF,  0xE0,  0xA0,  0x31,  0x8C,  0x06, 	/* 06E60 */
+	0x94,  0x04,  0x0F,  0xFE,  0x11,  0x02,  0x48,  0xDF,  0x60,  0x40,  0x15,  0x01,  0x10,  0xFF,  0xE1,  0x10, 	/* 06E70 */
+	0x21,  0x04,  0x10,  0x95,  0x04,  0x0F,  0xFE,  0x09,  0x02,  0x94,  0x49,  0x29,  0x32,  0x04,  0x0F,  0xFE, 	/* 06E80 */
+	0x04,  0x00,  0xA0,  0x31,  0x8C,  0x06,  0x97,  0x04,  0x0F,  0xFE,  0x0A,  0x01,  0x10,  0x3F,  0x8D,  0x06, 	/* 06E90 */
+	0x1F,  0x81,  0x00,  0xFF,  0xE1,  0x20,  0x11,  0x87,  0xE4,  0x98,  0x51,  0x07,  0x10,  0x1F,  0xEF,  0x10, 	/* 06EA0 */
+	0x51,  0x05,  0x7C,  0x94,  0x00,  0x40,  0xFF,  0xE0,  0xA0,  0x31,  0x8C,  0x06,  0x9A,  0x01,  0xC7,  0xE8, 	/* 06EB0 */
+	0x24,  0x42,  0x44,  0x49,  0x03,  0x20,  0x0C,  0x87,  0xFC,  0x04,  0x4F,  0xFE,  0x1B,  0x0E,  0x0E,  0xA0, 	/* 06EC0 */
+	0x17,  0x02,  0x08,  0x7F,  0xC8,  0xA2,  0x3F,  0x82,  0xA8,  0x33,  0x83,  0xF8,  0x24,  0x8F,  0xFE,  0x1B, 	/* 06ED0 */
+	0x0E,  0x0E,  0xA2,  0x04,  0x0F,  0xFE,  0x0A,  0x03,  0x18,  0xC4,  0x67,  0xFC,  0x05,  0x0F,  0xFE,  0x30, 	/* 06EE0 */
+	0x8D,  0xF8,  0x10,  0x81,  0xF8,  0xA5,  0x08,  0x01,  0x00,  0x7F,  0xC5,  0x54,  0x4E,  0x47,  0xFC,  0x55, 	/* 06EF0 */
+	0x46,  0x4C,  0xFF,  0xE0,  0xA0,  0x31,  0x8C,  0x06,  0xA7,  0x08,  0x07,  0xFC,  0x5E,  0x45,  0x54,  0x7F, 	/* 06F00 */
+	0xC4,  0xE4,  0x55,  0x46,  0x4C,  0xFF,  0xE0,  0x40,  0x1B,  0x0E,  0x0E,  0xA8,  0x10,  0x69,  0x78,  0x75, 	/* 06F10 */
+	0x21,  0x34,  0x3F,  0xED,  0x48,  0x12,  0x81,  0x18,  0xFF,  0xE0,  0xA0,  0x31,  0x8C,  0x06,  0xA9,  0x04, 	/* 06F20 */
+	0x0F,  0xFE,  0x0A,  0x03,  0x18,  0xC0,  0x6F,  0xFC,  0x49,  0x04,  0xF0,  0x40,  0x05,  0xDC,  0x55,  0x43, 	/* 06F30 */
+	0xFE,  0xAA,  0x08,  0x0F,  0xFE,  0x15,  0x03,  0xF8,  0xE4,  0x63,  0xF0,  0x24,  0x03,  0xF8,  0x01,  0x0F, 	/* 06F40 */
+	0xFE,  0x11,  0x00,  0x30,  0xAC,  0x50,  0xE5,  0x1A,  0xF6,  0x41,  0x18,  0xF6,  0x85,  0xFE,  0x52,  0x89, 	/* 06F50 */
+	0x58,  0xFF,  0xE0,  0xA0,  0x31,  0x8C,  0x06,  0xAE,  0x04,  0x0F,  0xFE,  0x15,  0x07,  0xF8,  0x24,  0x6F, 	/* 06F60 */
+	0xF8,  0x24,  0x07,  0xFC,  0x44,  0x47,  0xFC,  0x44,  0x47,  0xFC,  0xB3,  0x04,  0x00,  0x40,  0x04,  0x0F, 	/* 06F70 */
+	0xFE,  0x09,  0x00,  0x90,  0x11,  0x01,  0x10,  0x2E,  0x00,  0x60,  0x19,  0x8E,  0x06,  0xB4,  0x40,  0x04, 	/* 06F80 */
+	0x7C,  0x40,  0x4F,  0xC4,  0x54,  0x45,  0x28,  0x52,  0x89,  0x10,  0xF1,  0x82,  0xA8,  0x44,  0x48,  0x82, 	/* 06F90 */
+	0xB8,  0x40,  0x04,  0x7C,  0x51,  0x0F,  0x10,  0x51,  0x05,  0xFE,  0x51,  0x09,  0x10,  0xF1,  0x02,  0x90, 	/* 06FA0 */
+	0x41,  0x08,  0x10,  0xBD,  0x20,  0x02,  0x7C,  0x20,  0x4F,  0x88,  0x51,  0x05,  0x10,  0x5F,  0xE9,  0x10, 	/* 06FB0 */
+	0xF1,  0x02,  0x90,  0x41,  0x08,  0x30,  0x81,  0x41,  0x04,  0x10,  0x51,  0x0F,  0xBE,  0x52,  0x25,  0x62, 	/* 06FC0 */
+	0x59,  0x29,  0x12,  0xF0,  0x22,  0x82,  0x40,  0x28,  0x0C,  0x82,  0x20,  0x02,  0x00,  0x23,  0xEF,  0xE2, 	/* 06FD0 */
+	0x2A,  0x22,  0xA2,  0x4A,  0x24,  0xA2,  0xF2,  0x21,  0xA2,  0x23,  0xE4,  0x00,  0x83,  0x20,  0x02,  0x3C, 	/* 06FE0 */
+	0x20,  0x4F,  0x84,  0x48,  0x44,  0xBC,  0x4A,  0x09,  0x20,  0xF2,  0x02,  0xA2,  0x42,  0x28,  0x1E,  0x84, 	/* 06FF0 */
+	0x04,  0x00,  0x40,  0xFF,  0xE2,  0x00,  0x20,  0x01,  0xFC,  0x08,  0x0F,  0xFE,  0x11,  0x03,  0x90,  0x0E, 	/* 07000 */
+	0x07,  0x1C,  0x8A,  0x20,  0xC2,  0xF0,  0x21,  0x0F,  0x10,  0x51,  0x05,  0xFF,  0x51,  0x09,  0x10,  0xF1, 	/* 07010 */
+	0x02,  0x90,  0x4F,  0xE8,  0x00,  0x8D,  0x40,  0x04,  0x7E,  0x52,  0x4F,  0xA4,  0x52,  0x45,  0xFE,  0x52, 	/* 07020 */
+	0x49,  0x24,  0xF2,  0x42,  0xC4,  0x44,  0x48,  0x84,  0x93,  0x41,  0x04,  0x10,  0x57,  0xEF,  0x90,  0x51, 	/* 07030 */
+	0x05,  0x7C,  0x50,  0x49,  0x24,  0xF1,  0x82,  0x98,  0x42,  0x48,  0xC2,  0x96,  0x20,  0xC2,  0x70,  0x21, 	/* 07040 */
+	0x0F,  0x90,  0x51,  0x05,  0xFE,  0x51,  0x09,  0x10,  0xF2,  0x82,  0xA8,  0x44,  0x48,  0x82,  0x99,  0x21, 	/* 07050 */
+	0x02,  0x10,  0x25,  0x4F,  0xD4,  0x55,  0x25,  0x52,  0x59,  0x69,  0x34,  0xF0,  0x82,  0x90,  0x46,  0x09, 	/* 07060 */
+	0x80,  0x9B,  0x04,  0x04,  0x44,  0x44,  0x47,  0xFC,  0x00,  0x0F,  0xFE,  0x08,  0x07,  0xFC,  0x11,  0x03, 	/* 07070 */
+	0xA0,  0x0F,  0x0F,  0x0C,  0x9D,  0x51,  0x05,  0x10,  0x51,  0x07,  0xFF,  0x52,  0x41,  0x24,  0xF2,  0x45, 	/* 07080 */
+	0x44,  0x56,  0x45,  0x18,  0x53,  0x49,  0xC2,  0xA3,  0x44,  0x84,  0x48,  0x54,  0x8F,  0x48,  0x57,  0xB5, 	/* 07090 */
+	0x4E,  0x54,  0x89,  0x48,  0xF4,  0x82,  0xC8,  0x47,  0x98,  0xC7,  0xA5,  0x01,  0xC7,  0xE4,  0x48,  0x42, 	/* 070A0 */
+	0x48,  0x25,  0x00,  0x80,  0xFF,  0xE1,  0x10,  0x11,  0x03,  0x20,  0x0F,  0x07,  0x0C,  0xA8,  0x22,  0x02, 	/* 070B0 */
+	0x20,  0x2F,  0xEF,  0x20,  0x52,  0x05,  0x3C,  0x52,  0x49,  0x24,  0xF2,  0x42,  0xC4,  0x44,  0x48,  0x98, 	/* 070C0 */
+	0xAC,  0x40,  0x04,  0x7E,  0x51,  0x0F,  0x90,  0x51,  0x05,  0x20,  0x53,  0xE9,  0x32,  0xF5,  0x22,  0xD2, 	/* 070D0 */
+	0x49,  0x28,  0x1E,  0xB2,  0x40,  0x04,  0x7C,  0x54,  0x4F,  0xC4,  0x57,  0xC5,  0x44,  0x54,  0x49,  0x44, 	/* 070E0 */
+	0xF7,  0xC2,  0x80,  0x40,  0x08,  0xFE,  0xB9,  0x41,  0x04,  0x10,  0x47,  0xCF,  0x10,  0x51,  0x05,  0xFE, 	/* 070F0 */
+	0x51,  0x09,  0x38,  0xF5,  0x42,  0x92,  0x41,  0x08,  0x10,  0xBB,  0x04,  0x0F,  0xFE,  0x04,  0x03,  0xF8, 	/* 07100 */
+	0x04,  0x8F,  0xFE,  0x04,  0x8F,  0xFE,  0x11,  0x03,  0x10,  0x0E,  0x07,  0x18,  0xBE,  0x04,  0x00,  0x40, 	/* 07110 */
+	0x7F,  0xC1,  0x10,  0x0A,  0x0F,  0xFE,  0x08,  0x0F,  0xFE,  0x11,  0x03,  0x20,  0x0E,  0x07,  0x18,  0x86, 	/* 07120 */
+	0x47,  0xE4,  0x42,  0x55,  0x2F,  0xCA,  0x57,  0xF5,  0x42,  0x55,  0x29,  0x4A,  0xF4,  0x22,  0xFF,  0x44, 	/* 07130 */
+	0x28,  0x0E,  0x89,  0x41,  0x04,  0x10,  0x4F,  0xEF,  0x10,  0x57,  0xC5,  0x54,  0x55,  0x49,  0x54,  0xF5, 	/* 07140 */
+	0x42,  0xD8,  0x41,  0x08,  0x10,  0x8B,  0x42,  0x04,  0x20,  0x52,  0x8F,  0x44,  0x54,  0xC5,  0xF2,  0x50, 	/* 07150 */
+	0x29,  0x7C,  0xF4,  0x42,  0xC4,  0x44,  0x48,  0x7C,  0x90,  0x40,  0x04,  0x7C,  0x54,  0x4F,  0xC4,  0x57, 	/* 07160 */
+	0xC5,  0x44,  0x54,  0x49,  0x7C,  0xF4,  0x42,  0xC4,  0x44,  0x48,  0xFE,  0x91,  0x41,  0x04,  0x10,  0x51, 	/* 07170 */
+	0x0F,  0xFE,  0x51,  0x05,  0x10,  0x51,  0x09,  0x7C,  0xF4,  0x42,  0xC4,  0x44,  0x48,  0x7C,  0x93,  0x41, 	/* 07180 */
+	0x04,  0x50,  0x55,  0x0F,  0x7E,  0x55,  0x05,  0x90,  0x51,  0x09,  0x7C,  0xF1,  0x02,  0x90,  0x41,  0x08, 	/* 07190 */
+	0xFE,  0x94,  0x01,  0x83,  0xE0,  0x04,  0x0F,  0xFE,  0x0E,  0x03,  0x58,  0xC8,  0x67,  0xFC,  0x11,  0x03, 	/* 071A0 */
+	0xE0,  0x0D,  0x87,  0x04,  0x99,  0x42,  0x34,  0x2E,  0x52,  0x4F,  0x44,  0x54,  0x45,  0xDF,  0x54,  0x49, 	/* 071B0 */
+	0x44,  0xF4,  0x42,  0xC4,  0x44,  0x48,  0x5F,  0x9A,  0x41,  0x44,  0x14,  0x55,  0x5F,  0x55,  0x53,  0x65, 	/* 071C0 */
+	0x14,  0x53,  0x69,  0x55,  0xF5,  0x52,  0x94,  0x42,  0x58,  0x43,  0x9C,  0x20,  0x81,  0x10,  0xFF,  0xE0, 	/* 071D0 */
+	0x40,  0x7F,  0xC0,  0x40,  0xFF,  0xE2,  0x00,  0xFF,  0xE3,  0x18,  0x0E,  0x07,  0x1C,  0xA5,  0x41,  0x04, 	/* 071E0 */
+	0x10,  0x57,  0xEF,  0x94,  0x51,  0x85,  0xFE,  0x51,  0x09,  0x20,  0xF7,  0xC2,  0xA0,  0x42,  0x28,  0x1E, 	/* 071F0 */
+	0xA6,  0x04,  0x07,  0xFC,  0x09,  0x01,  0xA0,  0x06,  0x03,  0x98,  0x10,  0x8F,  0xFE,  0x29,  0x46,  0xB4, 	/* 07200 */
+	0x31,  0x8C,  0xE6,  0xA8,  0x41,  0x04,  0xFE,  0x51,  0x0F,  0xFE,  0x51,  0x25,  0x7E,  0x55,  0x09,  0x7E, 	/* 07210 */
+	0xF5,  0x22,  0x96,  0x42,  0x88,  0xC6,  0xAA,  0x20,  0x02,  0xFE,  0x22,  0x0F,  0x28,  0x55,  0xC5,  0xE2, 	/* 07220 */
+	0x51,  0x09,  0x10,  0xF7,  0xC2,  0x90,  0x41,  0x08,  0xFE,  0xAB,  0x40,  0x04,  0x7E,  0x54,  0x8F,  0x48, 	/* 07230 */
+	0x57,  0xE5,  0x42,  0x54,  0x29,  0x7E,  0xF4,  0x82,  0xC8,  0x44,  0x88,  0x7E,  0xB6,  0x41,  0x04,  0x10, 	/* 07240 */
+	0x52,  0x8F,  0xA8,  0x54,  0x45,  0xBA,  0x90,  0x0D,  0x7C,  0x34,  0x42,  0xC4,  0x44,  0x48,  0x7C,  0xBB, 	/* 07250 */
+	0x40,  0x04,  0x7E,  0x55,  0x2F,  0xD2,  0x57,  0xE5,  0x52,  0x55,  0x29,  0x5A,  0xF5,  0x62,  0xE6,  0x46, 	/* 07260 */
+	0x28,  0x7E,  0xBF,  0x04,  0x04,  0x7E,  0x25,  0x20,  0x94,  0x22,  0x8C,  0xC6,  0x04,  0x0F,  0xFE,  0x08, 	/* 07270 */
+	0x81,  0x90,  0x07,  0x03,  0x8C,  0x81,  0x01,  0x44,  0x12,  0x7F,  0xF4,  0x10,  0x7D,  0x25,  0x52,  0x7F, 	/* 07280 */
+	0x45,  0x4C,  0x54,  0x95,  0x4D,  0x89,  0x3B,  0x61,  0x83,  0x41,  0x04,  0x10,  0x57,  0xCF,  0x90,  0x51, 	/* 07290 */
+	0x05,  0xFE,  0x51,  0x09,  0x10,  0xF7,  0xC2,  0x90,  0x41,  0x08,  0xFE,  0x89,  0x42,  0x04,  0x7C,  0x45, 	/* 072A0 */
+	0x4F,  0xFC,  0x55,  0x45,  0x7C,  0x50,  0x09,  0xFE,  0xF2,  0x02,  0xBC,  0x40,  0x48,  0x18,  0x91,  0x41, 	/* 072B0 */
+	0x02,  0x54,  0x85,  0x24,  0xB2,  0x20,  0x8C,  0x30,  0x0C,  0x0F,  0xFE,  0x11,  0x01,  0xA0,  0x07,  0x07, 	/* 072C0 */
+	0x8C,  0x98,  0x22,  0x02,  0x20,  0x27,  0xCF,  0xC4,  0x57,  0xC5,  0x44,  0x57,  0xC9,  0x52,  0xF5,  0x42, 	/* 072D0 */
+	0xC8,  0x46,  0x49,  0x82,  0x9A,  0x40,  0x04,  0x7C,  0x45,  0x4F,  0x7C,  0x55,  0x45,  0x54,  0x57,  0xC9, 	/* 072E0 */
+	0x10,  0xFF,  0xE2,  0x92,  0x42,  0x28,  0x4C,  0x9C,  0x40,  0x05,  0xEE,  0x4A,  0xAF,  0xAA,  0x5E,  0xA5, 	/* 072F0 */
+	0xAC,  0x5A,  0xA9,  0xEA,  0xEA,  0xA2,  0xAE,  0x4A,  0x89,  0x68,  0x9F,  0x23,  0xE2,  0x22,  0x2B,  0xEF, 	/* 07300 */
+	0xC0,  0x4B,  0xE4,  0xA2,  0x4B,  0xE9,  0x22,  0xF3,  0xE2,  0xA2,  0x42,  0x28,  0x26,  0xA0,  0x47,  0xE4, 	/* 07310 */
+	0x40,  0x55,  0xCF,  0x40,  0x57,  0xE5,  0x50,  0x55,  0xA9,  0x5A,  0xF5,  0x42,  0x94,  0x49,  0xA9,  0x62, 	/* 07320 */
+	0xA5,  0x47,  0x64,  0x25,  0x52,  0x4F,  0x24,  0x5F,  0xF5,  0x24,  0x53,  0x59,  0x65,  0xF2,  0x62,  0xAC, 	/* 07330 */
+	0x42,  0x58,  0x63,  0xA9,  0x21,  0x02,  0x3C,  0x24,  0x8F,  0x90,  0x57,  0xC5,  0x54,  0x55,  0x49,  0x7C, 	/* 07340 */
+	0xF2,  0x82,  0xAA,  0x44,  0xA8,  0x86,  0xAF,  0x43,  0xC4,  0xA4,  0x5A,  0x4F,  0xBC,  0x58,  0x05,  0xFC, 	/* 07350 */
+	0x50,  0x49,  0x04,  0xFF,  0xE2,  0xA8,  0x44,  0x48,  0x82,  0xB5,  0x40,  0x05,  0xFE,  0x4A,  0x0F,  0xBE, 	/* 07360 */
+	0x5E,  0xA5,  0xAA,  0x5E,  0xA9,  0xA4,  0xEA,  0xA2,  0xEA,  0x73,  0x18,  0x20,  0xB6,  0x00,  0x0F,  0xFC, 	/* 07370 */
+	0x48,  0x47,  0xA4,  0x79,  0x84,  0x94,  0xFE,  0x20,  0x80,  0xFF,  0xE3,  0x10,  0x0E,  0x07,  0x18,  0xBC, 	/* 07380 */
+	0x20,  0x02,  0x3C,  0x22,  0x4F,  0xBC,  0x52,  0x45,  0x3C,  0x50,  0x09,  0x7E,  0xF4,  0x22,  0xFE,  0x44, 	/* 07390 */
+	0x28,  0x7E,  0x80,  0x40,  0x04,  0xFF,  0x4A,  0x2F,  0xC2,  0x5C,  0xE5,  0xAA,  0x5A,  0xA9,  0xAA,  0xFA, 	/* 073A0 */
+	0xE2,  0xC2,  0x48,  0x28,  0x86,  0x81,  0x3F,  0x82,  0x48,  0xFF,  0xE2,  0x48,  0x7F,  0xC4,  0x44,  0x7F, 	/* 073B0 */
+	0xC1,  0x00,  0xFF,  0xE3,  0x10,  0x0E,  0x07,  0x18,  0x86,  0x61,  0x00,  0xFE,  0xC9,  0x21,  0xFC,  0x2A, 	/* 073C0 */
+	0x4C,  0x98,  0x16,  0x6F,  0xFE,  0x11,  0x03,  0x20,  0x0F,  0x0F,  0x0E,  0x89,  0x41,  0x04,  0x10,  0x5F, 	/* 073D0 */
+	0xEF,  0x42,  0x56,  0xE5,  0xAA,  0x5A,  0xA9,  0x6C,  0xE4,  0x82,  0x48,  0x48,  0xA9,  0x06,  0x9A,  0x40, 	/* 073E0 */
+	0xE4,  0x78,  0x54,  0x8F,  0x7E,  0x54,  0x85,  0x66,  0x5C,  0x29,  0x7C,  0xF4,  0x42,  0xFC,  0x44,  0x48, 	/* 073F0 */
+	0x7C,  0xA2,  0x40,  0x84,  0x10,  0x57,  0xEF,  0xCA,  0x57,  0xE5,  0x4A,  0x57,  0xE9,  0x14,  0xF2,  0x42, 	/* 07400 */
+	0xFF,  0x40,  0x48,  0x04,  0xA6,  0x27,  0xC2,  0x04,  0x23,  0xCF,  0x04,  0x57,  0xF5,  0x51,  0x57,  0xF9, 	/* 07410 */
+	0x52,  0xF5,  0x22,  0xD6,  0x41,  0x08,  0x10,  0xAA,  0x11,  0x0F,  0xFE,  0x11,  0x83,  0xB4,  0x55,  0x29, 	/* 07420 */
+	0x10,  0x08,  0x0F,  0xFE,  0x11,  0x03,  0x20,  0x0F,  0x07,  0x0C,  0xAC,  0x40,  0x64,  0x78,  0x45,  0x4F, 	/* 07430 */
+	0x92,  0x50,  0xC5,  0xF0,  0x51,  0x09,  0x10,  0xFF,  0xC2,  0x90,  0x41,  0x08,  0xFE,  0xBF,  0x4F,  0xE4, 	/* 07440 */
+	0x10,  0x55,  0xCF,  0x50,  0x5B,  0xE5,  0x7C,  0x54,  0x49,  0x7C,  0xF4,  0x42,  0xFC,  0x44,  0x48,  0x4C, 	/* 07450 */
+	0x92,  0x44,  0x44,  0xFE,  0x54,  0x4F,  0x7C,  0x54,  0x45,  0x7C,  0x51,  0x09,  0xFE,  0xE3,  0x82,  0x54, 	/* 07460 */
+	0x49,  0x28,  0x10,  0x9A,  0x40,  0x04,  0x7E,  0x55,  0x2F,  0xFE,  0x54,  0x05,  0x5E,  0x55,  0x29,  0x5E, 	/* 07470 */
+	0xF5,  0x22,  0x9E,  0x49,  0x29,  0x1E,  0x9B,  0x20,  0xE2,  0xF2,  0x25,  0x4F,  0x28,  0x5F,  0xE5,  0x20, 	/* 07480 */
+	0x5F,  0xE9,  0x20,  0xF7,  0xC2,  0x54,  0x48,  0xC8,  0x72,  0xBC,  0x20,  0x02,  0x7C,  0x25,  0x4F,  0x54, 	/* 07490 */
+	0x56,  0xC5,  0x7C,  0x50,  0x09,  0xFE,  0xEA,  0xA2,  0xAA,  0x4A,  0xA9,  0xFF,  0xBD,  0x40,  0x04,  0x7C, 	/* 074A0 */
+	0x45,  0x0F,  0xFC,  0x55,  0x05,  0x7C,  0x55,  0x09,  0x7E,  0xE0,  0xA2,  0xAA,  0x4A,  0x29,  0x1C,  0xBE, 	/* 074B0 */
+	0x42,  0x84,  0xFC,  0x42,  0x8F,  0xFE,  0x51,  0x05,  0x7C,  0x55,  0x49,  0x7C,  0xE5,  0x42,  0xFE,  0x44, 	/* 074C0 */
+	0x48,  0x4C,  0x81,  0x41,  0x04,  0xFE,  0x58,  0x2F,  0x7C,  0x51,  0x05,  0xF2,  0x52,  0xC9,  0xD8,  0xF2, 	/* 074D0 */
+	0xC2,  0xCA,  0x40,  0x88,  0x30,  0x82,  0x41,  0x04,  0x6E,  0x44,  0xAF,  0x6E,  0x54,  0xA5,  0x6E,  0x50, 	/* 074E0 */
+	0x89,  0xFF,  0xE2,  0x42,  0x18,  0x41,  0x48,  0x62,  0x89,  0x40,  0x84,  0x08,  0x57,  0xEF,  0x50,  0x5D, 	/* 074F0 */
+	0x05,  0x5E,  0x56,  0x89,  0xC8,  0xF7,  0xE2,  0x48,  0x49,  0x49,  0x62,  0x8B,  0x40,  0x04,  0xEE,  0x42, 	/* 07500 */
+	0x2F,  0xEE,  0x58,  0x85,  0xEE,  0x56,  0x69,  0xAA,  0xF6,  0x62,  0xAA,  0x42,  0x28,  0xCC,  0x8C,  0x48, 	/* 07510 */
+	0x85,  0xFE,  0x45,  0x0F,  0xFC,  0x55,  0x45,  0xFE,  0x55,  0x49,  0xFC,  0xF5,  0x02,  0xD8,  0x55,  0x68, 	/* 07520 */
+	0x50,  0x90,  0x40,  0x85,  0xF8,  0x55,  0xAF,  0xFE,  0x55,  0xA5,  0xFA,  0x54,  0xA9,  0xF2,  0xD5,  0xA2, 	/* 07530 */
+	0x54,  0x59,  0xA9,  0x32,  0x96,  0x4F,  0xE4,  0x28,  0x4F,  0xEF,  0xAA,  0x5F,  0xE5,  0x00,  0x57,  0xC9, 	/* 07540 */
+	0x00,  0xFF,  0xE2,  0x54,  0x49,  0x28,  0x30,  0x97,  0x40,  0x04,  0x7E,  0x55,  0xCF,  0xD4,  0x55,  0xC5, 	/* 07550 */
+	0x40,  0x57,  0xE9,  0x5A,  0xF5,  0xA2,  0xFE,  0x44,  0x08,  0x7E,  0xA1,  0x41,  0x04,  0xFE,  0x44,  0x4F, 	/* 07560 */
+	0x28,  0x5F,  0xE5,  0x92,  0x5F,  0xE9,  0x92,  0xFB,  0xA2,  0xAA,  0x4B,  0xA8,  0x86,  0xA3,  0x4F,  0xC4, 	/* 07570 */
+	0x10,  0x45,  0xCF,  0x50,  0x5F,  0xE5,  0x40,  0x57,  0xC9,  0x40,  0xE7,  0xE2,  0x2A,  0x45,  0x28,  0x8C, 	/* 07580 */
+	0xA6,  0x49,  0x24,  0x54,  0x4F,  0xEF,  0x82,  0x57,  0xC5,  0x44,  0x57,  0xC9,  0x10,  0xFF,  0xE2,  0x92, 	/* 07590 */
+	0x49,  0x48,  0x10,  0xA9,  0x44,  0x84,  0x48,  0x5F,  0x8F,  0x4F,  0x5F,  0xA5,  0x52,  0x5F,  0xA9,  0x4A, 	/* 075A0 */
+	0xEE,  0x43,  0x54,  0x44,  0xA8,  0x51,  0xBA,  0x4E,  0xE4,  0xAA,  0x5E,  0xEF,  0xAA,  0x5E,  0xE5,  0x82, 	/* 075B0 */
+	0x5B,  0xA9,  0xAA,  0xEB,  0xA2,  0xAA,  0x4B,  0xA8,  0x86,  0xBB,  0x4E,  0xE4,  0xAA,  0x5E,  0xEF,  0xAA, 	/* 075C0 */
+	0x5E,  0xE5,  0x92,  0x5F,  0xE9,  0x92,  0xEB,  0xA2,  0xD6,  0x49,  0x28,  0x86,  0x89,  0x41,  0x04,  0xFE, 	/* 075D0 */
+	0x51,  0x0F,  0xFC,  0x54,  0x45,  0x7C,  0x52,  0x89,  0xFE,  0xF0,  0x02,  0xFC,  0x44,  0x48,  0x7C,  0x8B, 	/* 075E0 */
+	0x2E,  0xE2,  0xAA,  0x2E,  0xEF,  0x00,  0x57,  0xC5,  0x54,  0x57,  0xC9,  0x54,  0xF7,  0xC2,  0x90,  0x4F, 	/* 075F0 */
+	0xE8,  0x10,  0x8C,  0x40,  0xC4,  0xF0,  0x41,  0x0F,  0xFE,  0x53,  0xC5,  0x6A,  0x5B,  0x99,  0xFE,  0xEB, 	/* 07600 */
+	0xA2,  0xAA,  0x4B,  0xA8,  0x86,  0x96,  0x78,  0x84,  0xBE,  0x79,  0x44,  0x7F,  0x78,  0x84,  0xBE,  0xB8, 	/* 07610 */
+	0x80,  0x88,  0xFF,  0xE3,  0x10,  0x0E,  0x07,  0x18,  0xA2,  0x41,  0x04,  0xFE,  0x52,  0x8F,  0xC4,  0x52, 	/* 07620 */
+	0xA5,  0xFC,  0x52,  0x89,  0xFE,  0xF5,  0x42,  0xC8,  0x47,  0x48,  0xC2,  0xAA,  0x41,  0x04,  0xFE,  0x48, 	/* 07630 */
+	0x2F,  0x7C,  0x55,  0x45,  0xBE,  0x54,  0x49,  0xFC,  0xF4,  0x42,  0x7C,  0x42,  0x48,  0xC2,  0xAC,  0x47, 	/* 07640 */
+	0xC4,  0x10,  0x4F,  0xEF,  0x92,  0x5B,  0xA5,  0x00,  0x5F,  0xE9,  0x10,  0xFF,  0xE2,  0xAA,  0x4A,  0xA8, 	/* 07650 */
+	0x86,  0xB0,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFB,  0xE5,  0x14,  0x8A,  0x2F,  0xFE,  0x11,  0x03, 	/* 07660 */
+	0x10,  0x0E,  0x07,  0x1C,  0xB2,  0x08,  0x0F,  0xBE,  0xAA,  0xAF,  0xFE,  0xAA,  0xAF,  0xBE,  0x4A,  0x4F, 	/* 07670 */
+	0xBE,  0x5C,  0xA5,  0x6A,  0x59,  0x2B,  0x26,  0xB6,  0x42,  0x04,  0x7C,  0x54,  0x4F,  0x7C,  0x54,  0x45, 	/* 07680 */
+	0xFE,  0x59,  0x29,  0xFE,  0xE9,  0x22,  0xFE,  0x44,  0x48,  0x84,  0xBE,  0x44,  0x04,  0x5E,  0x5E,  0xAF, 	/* 07690 */
+	0x56,  0x5F,  0x05,  0x5E,  0x55,  0x29,  0xFE,  0xE5,  0x22,  0xDE,  0x56,  0xA8,  0x51,  0x80,  0x47,  0xC4, 	/* 076A0 */
+	0x10,  0x57,  0xEF,  0xD2,  0x57,  0xA5,  0x5E,  0x5F,  0x29,  0x5E,  0xEF,  0x22,  0xDE,  0x55,  0x28,  0x5E, 	/* 076B0 */
+	0x83,  0x41,  0x04,  0xFE,  0x50,  0x0F,  0xEE,  0x5A,  0xA5,  0xFE,  0x52,  0x89,  0xFE,  0xE3,  0x22,  0xCC, 	/* 076C0 */
+	0x44,  0x48,  0xE2,  0x85,  0x4A,  0x84,  0xAC,  0x55,  0x8F,  0xFE,  0x55,  0x85,  0x5A,  0x5D,  0xA9,  0x54, 	/* 076D0 */
+	0xED,  0xC2,  0x54,  0x47,  0xA9,  0x91,  0x90,  0x00,  0x03,  0xF8,  0x01,  0x00,  0x20,  0x04,  0x00,  0x40, 	/* 076E0 */
+	0xFF,  0xE0,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0xC0,  0x91,  0x00,  0x03,  0xF8,  0x01,  0x00,  0x20, 	/* 076F0 */
+	0x04,  0xC0,  0x70,  0x1C,  0x0E,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0xC0,  0x94,  0x02,  0x0F,  0xA0, 	/* 07700 */
+	0x0A,  0x01,  0x20,  0x22,  0x03,  0xA0,  0xE2,  0x02,  0x20,  0x22,  0x02,  0x20,  0x22,  0x26,  0x1E,  0x95, 	/* 07710 */
+	0x7F,  0x80,  0x88,  0x08,  0x80,  0x9E,  0x10,  0x23,  0xFA,  0xC3,  0x40,  0x40,  0xFF,  0xE0,  0x40,  0x04, 	/* 07720 */
+	0x00,  0xC0,  0x97,  0x04,  0x00,  0x40,  0xFF,  0xE8,  0x02,  0x9F,  0x20,  0x20,  0x04,  0x0F,  0xFE,  0x04, 	/* 07730 */
+	0x00,  0x40,  0x04,  0x00,  0xC0,  0x98,  0x08,  0x00,  0x80,  0xFF,  0xE0,  0x80,  0x17,  0xC1,  0x08,  0x21, 	/* 07740 */
+	0x06,  0xFE,  0xA1,  0x02,  0x10,  0x21,  0x02,  0x30,  0x9A,  0x07,  0xC7,  0x88,  0x44,  0x44,  0x42,  0xBF, 	/* 07750 */
+	0x80,  0x30,  0x04,  0x0F,  0xFE,  0x04,  0x00,  0x40,  0x04,  0x00,  0xC0,  0x9B,  0x04,  0x07,  0xFC,  0x04, 	/* 07760 */
+	0x0F,  0xFE,  0x80,  0x29,  0xF2,  0x02,  0x00,  0x40,  0xFF,  0xE0,  0x40,  0x04,  0x00,  0xC0,  0x9C,  0x02, 	/* 07770 */
+	0x0F,  0xA0,  0x13,  0xE2,  0x24,  0x24,  0x43,  0x54,  0xE9,  0x82,  0x08,  0x21,  0x82,  0x14,  0x22,  0x46, 	/* 07780 */
+	0xC2,  0x9D,  0x04,  0x00,  0x44,  0x3F,  0x80,  0x50,  0xFF,  0xE0,  0x40,  0x1F,  0x8E,  0x30,  0x7F,  0xE0, 	/* 07790 */
+	0x40,  0x04,  0x00,  0xC0,  0x9F,  0x00,  0x03,  0xF8,  0x02,  0x00,  0x40,  0xFF,  0xE0,  0x40,  0x04,  0x00, 	/* 077A0 */
+	0xC0,  0x7F,  0xC4,  0xA4,  0x4A,  0x4F,  0xFE,  0xA3,  0x03,  0x87,  0xC0,  0x04,  0x0F,  0xFE,  0x0E,  0x03, 	/* 077B0 */
+	0x58,  0xDF,  0x60,  0x20,  0x7F,  0xC0,  0x40,  0x04,  0x00,  0xC0,  0xA4,  0x00,  0x6F,  0x7C,  0x15,  0x42, 	/* 077C0 */
+	0x54,  0x25,  0x42,  0x54,  0x35,  0x4E,  0x54,  0x25,  0x42,  0x52,  0x25,  0x66,  0xBD,  0xA5,  0x10,  0x0F, 	/* 077D0 */
+	0xFE,  0x25,  0x26,  0x4C,  0x19,  0x42,  0x62,  0xDF,  0x00,  0x20,  0xFF,  0xE0,  0x40,  0x04,  0x00,  0xC0, 	/* 077E0 */
+	0xA6,  0x24,  0x41,  0x28,  0xFF,  0xE8,  0x02,  0x9F,  0x20,  0x20,  0x04,  0x07,  0xFE,  0x04,  0x00,  0x40, 	/* 077F0 */
+	0x04,  0x00,  0xC0,  0xA9,  0x00,  0x8F,  0x88,  0x17,  0xF1,  0x10,  0x26,  0x42,  0x94,  0x30,  0xA6,  0x12, 	/* 07800 */
+	0xA2,  0x42,  0x4C,  0x23,  0x26,  0xC1,  0xAB,  0x00,  0x4F,  0x78,  0x11,  0x02,  0x64,  0x21,  0x83,  0x24, 	/* 07810 */
+	0xEF,  0xA2,  0x12,  0x25,  0x42,  0x52,  0x29,  0x26,  0x10,  0xB0,  0x10,  0x8F,  0x88,  0x07,  0xE7,  0x8A, 	/* 07820 */
+	0x48,  0xA7,  0x8A,  0x03,  0xA7,  0xCE,  0x08,  0xAF,  0xEA,  0x11,  0x13,  0x21,  0xB1,  0x00,  0x07,  0xFC, 	/* 07830 */
+	0x40,  0x47,  0xFC,  0x47,  0x05,  0xFC,  0x42,  0x07,  0xFC,  0x48,  0x8B,  0xFE,  0x88,  0x81,  0x98,  0xB3, 	/* 07840 */
+	0x11,  0x0F,  0xFE,  0x29,  0x4D,  0x68,  0x29,  0x4F,  0xBE,  0x08,  0x23,  0xF8,  0x03,  0x0F,  0xFE,  0x04, 	/* 07850 */
+	0x00,  0xC0,  0xB5,  0x30,  0x4D,  0xF8,  0xB5,  0xCB,  0x6A,  0xFE,  0xAF,  0xC0,  0xB5,  0xCB,  0x44,  0xF7, 	/* 07860 */
+	0xE3,  0xC8,  0x30,  0x85,  0x18,  0xB8,  0x1A,  0x06,  0x5C,  0x4A,  0x47,  0x5C,  0x4A,  0x4F,  0xFE,  0x80, 	/* 07870 */
+	0x29,  0xF0,  0x02,  0x0F,  0xFE,  0x04,  0x00,  0xC0,  0xBA,  0x07,  0xCF,  0x10,  0x1F,  0xE2,  0x92,  0x2B, 	/* 07880 */
+	0xA3,  0x00,  0xEF,  0xE2,  0x20,  0x2F,  0xE2,  0xAA,  0x2A,  0xA6,  0x86,  0x80,  0x00,  0x00,  0x00,  0x04, 	/* 07890 */
+	0x00,  0x40,  0x04,  0x0F,  0xFE,  0x80,  0x28,  0x02,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x83,  0x04, 	/* 078A0 */
+	0x00,  0x40,  0xFF,  0xE8,  0x02,  0x90,  0x21,  0x00,  0x11,  0x81,  0xE0,  0x10,  0x01,  0x04,  0x10,  0x40, 	/* 078B0 */
+	0xFC,  0x85,  0x04,  0x0F,  0xFE,  0x80,  0x28,  0x12,  0x0E,  0x07,  0x80,  0x08,  0x00,  0xFE,  0xF8,  0x00, 	/* 078C0 */
+	0x80,  0x08,  0x40,  0x7C,  0x87,  0x04,  0x0F,  0xFE,  0x80,  0x2B,  0xFA,  0x04,  0x00,  0x40,  0x7F,  0xC0, 	/* 078D0 */
+	0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0xC0,  0x88,  0x04,  0x0F,  0xFE,  0x80,  0x28,  0x12,  0x01,  0x07, 	/* 078E0 */
+	0xFC,  0x01,  0x01,  0x10,  0x09,  0x00,  0x10,  0x01,  0x00,  0x30,  0x89,  0x04,  0x0F,  0xFE,  0x88,  0x28, 	/* 078F0 */
+	0x82,  0x08,  0x0F,  0xFE,  0x11,  0x01,  0x10,  0x3D,  0x00,  0x60,  0x19,  0x86,  0x04,  0x8B,  0x04,  0x00, 	/* 07900 */
+	0x40,  0xFF,  0xE8,  0x02,  0x84,  0x20,  0x40,  0xFF,  0xE0,  0x40,  0x0E,  0x03,  0x58,  0xC4,  0x60,  0x40, 	/* 07910 */
+	0x8C,  0x04,  0x0F,  0xFE,  0x80,  0x29,  0xF2,  0x00,  0x00,  0x00,  0xFF,  0xE0,  0xA0,  0x0A,  0x01,  0x22, 	/* 07920 */
+	0x22,  0x2C,  0x1E,  0x8D,  0x04,  0x00,  0x40,  0xFF,  0xE8,  0x02,  0x84,  0x20,  0x40,  0xFF,  0xE0,  0x00, 	/* 07930 */
+	0x11,  0x01,  0x08,  0x20,  0x4C,  0x04,  0x8F,  0x04,  0x0F,  0xFE,  0x88,  0x20,  0x80,  0xFF,  0xE0,  0x80, 	/* 07940 */
+	0x14,  0x01,  0x40,  0x25,  0x04,  0x88,  0x8F,  0x43,  0x04,  0x95,  0x04,  0x0F,  0xFE,  0x80,  0x20,  0x00, 	/* 07950 */
+	0xFF,  0xE0,  0x80,  0x10,  0x01,  0xFC,  0x30,  0x45,  0x04,  0x90,  0x41,  0xFC,  0x97,  0x04,  0x0F,  0xFE, 	/* 07960 */
+	0x80,  0x29,  0xF2,  0x00,  0x00,  0x00,  0xFF,  0xE0,  0x50,  0x24,  0x82,  0x44,  0x44,  0x40,  0xC0,  0x98, 	/* 07970 */
+	0x04,  0x0F,  0xFE,  0x80,  0x29,  0xF2,  0x11,  0x01,  0x10,  0x1F,  0x01,  0x00,  0x1F,  0x81,  0x08,  0x10, 	/* 07980 */
+	0x81,  0xF8,  0x99,  0x04,  0x0F,  0xFE,  0x84,  0x28,  0x42,  0x3F,  0x82,  0x48,  0x24,  0x83,  0xF8,  0x24, 	/* 07990 */
+	0x82,  0x48,  0x3F,  0x80,  0x00,  0x9A,  0x04,  0x0F,  0xFE,  0x80,  0x28,  0x02,  0x3F,  0x80,  0x40,  0x04, 	/* 079A0 */
+	0x02,  0x78,  0x24,  0x03,  0x40,  0x4C,  0x08,  0x3E,  0x9B,  0x04,  0x0F,  0xFE,  0x80,  0x2A,  0x02,  0x3B, 	/* 079B0 */
+	0xC2,  0xA4,  0x4A,  0x4A,  0xA4,  0x13,  0x81,  0x22,  0x22,  0x24,  0x1E,  0x9C,  0x04,  0x0F,  0xFE,  0x80, 	/* 079C0 */
+	0x29,  0xF2,  0x11,  0x01,  0x10,  0x1F,  0x01,  0x10,  0x1F,  0x01,  0x10,  0x11,  0x0F,  0xFE,  0x9D,  0x04, 	/* 079D0 */
+	0x0F,  0xFE,  0x80,  0x28,  0x02,  0x3F,  0x80,  0x40,  0x04,  0x03,  0xF0,  0x04,  0x00,  0x48,  0x04,  0x4F, 	/* 079E0 */
+	0xFE,  0x9F,  0x04,  0x0F,  0xFE,  0x84,  0x28,  0x42,  0x3F,  0x80,  0x40,  0x3F,  0x80,  0x40,  0xFF,  0xE0, 	/* 079F0 */
+	0xA0,  0x31,  0x8C,  0x06,  0xA2,  0x04,  0x0F,  0xFE,  0x88,  0x28,  0xF2,  0x11,  0x06,  0xA0,  0x06,  0x03, 	/* 07A00 */
+	0x98,  0xDF,  0xE1,  0x08,  0x10,  0x81,  0xF8,  0xA3,  0x04,  0x0F,  0xFE,  0x80,  0x2B,  0xFA,  0x00,  0x03, 	/* 07A10 */
+	0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x00,  0x0F,  0xFE,  0xA4,  0x04,  0x0F,  0xFE,  0x80,  0x2B, 	/* 07A20 */
+	0xFA,  0x0A,  0x01,  0x18,  0x7E,  0x40,  0x40,  0x7F,  0xC0,  0x40,  0x04,  0x0F,  0xFE,  0xA5,  0x04,  0x0F, 	/* 07A30 */
+	0xFE,  0x88,  0x2F,  0xFA,  0x10,  0x01,  0xF8,  0x30,  0x85,  0xF8,  0x90,  0x81,  0xF8,  0x10,  0x81,  0x18, 	/* 07A40 */
+	0xA6,  0x04,  0x0F,  0xFE,  0x80,  0x2F,  0xFC,  0x44,  0x04,  0x40,  0x7F,  0x84,  0x08,  0x7F,  0x84,  0x40, 	/* 07A50 */
+	0x44,  0x07,  0xFE,  0xAE,  0x04,  0x0F,  0xFE,  0x80,  0x29,  0xF2,  0x11,  0x01,  0x10,  0x1F,  0x00,  0x80, 	/* 07A60 */
+	0x3F,  0x82,  0x08,  0x20,  0x83,  0xF8,  0xB0,  0x04,  0x0F,  0xFE,  0x84,  0x27,  0xFC,  0x11,  0x00,  0xA0, 	/* 07A70 */
+	0xFF,  0xE0,  0x40,  0x7F,  0xC0,  0x40,  0x04,  0x00,  0x40,  0xB3,  0x04,  0x0F,  0xFE,  0x84,  0x2B,  0xFA, 	/* 07A80 */
+	0x04,  0x03,  0xF8,  0x04,  0x07,  0xFC,  0x00,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0xB4,  0x04,  0x0F,  0xFE, 	/* 07A90 */
+	0x9F,  0x29,  0x12,  0x1F,  0x01,  0x10,  0x1F,  0x00,  0x80,  0xFF,  0xE3,  0x10,  0x0E,  0x07,  0x18,  0xB5, 	/* 07AA0 */
+	0x04,  0x0F,  0xFE,  0x84,  0x2A,  0x4A,  0x15,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x20, 	/* 07AB0 */
+	0x82,  0x18,  0xB6,  0x04,  0x0F,  0xFE,  0x80,  0x2B,  0xFA,  0x08,  0x01,  0x54,  0x6B,  0x41,  0x68,  0x6A, 	/* 07AC0 */
+	0x81,  0x24,  0x62,  0x20,  0xC0,  0xB8,  0x04,  0x0F,  0xFE,  0x80,  0x2B,  0xFE,  0x20,  0x02,  0xF8,  0x20, 	/* 07AD0 */
+	0x03,  0xFC,  0x4A,  0x44,  0x98,  0x8C,  0x83,  0x06,  0xB9,  0x04,  0x0F,  0xFE,  0x92,  0x29,  0x12,  0x24, 	/* 07AE0 */
+	0x84,  0xA8,  0x11,  0x02,  0x08,  0xFF,  0xE2,  0x08,  0x20,  0x83,  0xF8,  0xBF,  0x04,  0x0F,  0xFE,  0x80, 	/* 07AF0 */
+	0x29,  0xFE,  0x11,  0x02,  0x7C,  0x64,  0x4A,  0x44,  0x27,  0xC2,  0x44,  0x24,  0x42,  0x7C,  0x82,  0x04, 	/* 07B00 */
+	0x0F,  0xFE,  0xA0,  0x2A,  0x02,  0x3B,  0xC2,  0x04,  0xFE,  0x82,  0x28,  0xB1,  0x0A,  0x98,  0xA2,  0x42, 	/* 07B10 */
+	0x42,  0x83,  0x04,  0x0F,  0xFE,  0x84,  0x28,  0xF2,  0x32,  0x0F,  0xF8,  0x24,  0x83,  0xF8,  0x0B,  0x00, 	/* 07B20 */
+	0xAA,  0x32,  0x2C,  0x1E,  0x84,  0x04,  0x0F,  0xFE,  0x84,  0x27,  0xF8,  0x0A,  0x03,  0x10,  0xFF,  0xE0, 	/* 07B30 */
+	0x08,  0x3E,  0x82,  0x28,  0x3E,  0x80,  0x18,  0x85,  0x04,  0x0F,  0xFE,  0x80,  0x2B,  0xFA,  0x04,  0x03, 	/* 07B40 */
+	0xF8,  0x24,  0x83,  0xF8,  0x24,  0x83,  0xF8,  0x11,  0x86,  0x04,  0x86,  0x04,  0x0F,  0xFE,  0x88,  0x28, 	/* 07B50 */
+	0x52,  0x51,  0x45,  0x22,  0x94,  0xA1,  0xF8,  0x24,  0x04,  0x44,  0x44,  0x47,  0xFC,  0x87,  0x04,  0x0F, 	/* 07B60 */
+	0xFE,  0x81,  0x27,  0xDC,  0x01,  0x0F,  0xFC,  0x28,  0x42,  0xA8,  0x29,  0x82,  0x98,  0x4A,  0x48,  0x7E, 	/* 07B70 */
+	0x89,  0x04,  0x0F,  0xFE,  0x90,  0x29,  0x12,  0x22,  0x03,  0xFC,  0x62,  0x0B,  0xF8,  0x22,  0x03,  0xF8, 	/* 07B80 */
+	0x22,  0x03,  0xFC,  0x8C,  0x04,  0x0F,  0xFE,  0x80,  0x27,  0xFC,  0x20,  0x83,  0xF8,  0x00,  0x07,  0xFC, 	/* 07B90 */
+	0x44,  0x47,  0xFC,  0x44,  0x47,  0xFC,  0x90,  0x04,  0x0F,  0xFE,  0x90,  0x25,  0x12,  0x57,  0xC7,  0x10, 	/* 07BA0 */
+	0x1F,  0xEF,  0x18,  0x53,  0x85,  0x54,  0x59,  0x29,  0x10,  0x92,  0x04,  0x0F,  0xFE,  0x92,  0x2F,  0xFA, 	/* 07BB0 */
+	0x12,  0x07,  0xF8,  0x12,  0x0F,  0xFC,  0x29,  0x04,  0x48,  0x98,  0x60,  0x60,  0x93,  0x04,  0x0F,  0xFE, 	/* 07BC0 */
+	0x80,  0x2B,  0xFA,  0x24,  0x83,  0xF8,  0x24,  0x87,  0xFC,  0x45,  0x45,  0xF4,  0x41,  0x44,  0x0C,  0x94, 	/* 07BD0 */
+	0x04,  0x0F,  0xFE,  0x80,  0x29,  0xF2,  0x11,  0x01,  0xF0,  0x11,  0x0F,  0xFE,  0x24,  0x02,  0x7C,  0x5C, 	/* 07BE0 */
+	0x08,  0x7E,  0x9B,  0x04,  0x0F,  0xFE,  0x91,  0x27,  0xFC,  0x11,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20, 	/* 07BF0 */
+	0x83,  0xF8,  0x1A,  0x2E,  0x1E,  0x9D,  0x04,  0x0F,  0xFE,  0xAF,  0xA2,  0x0A,  0xAF,  0x86,  0x08,  0x3F, 	/* 07C00 */
+	0xE7,  0x02,  0xAF,  0xC2,  0x48,  0x23,  0x03,  0xCE,  0x9E,  0x04,  0x0F,  0xFE,  0x91,  0x2B,  0xFA,  0x11, 	/* 07C10 */
+	0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x8F,  0xFE,  0x1B,  0x0E,  0x0E,  0x9F,  0x04,  0x0F,  0xFE,  0x80, 	/* 07C20 */
+	0x2B,  0xBE,  0x4A,  0x4B,  0x18,  0x2F,  0x4C,  0x02,  0x7F,  0xE2,  0x58,  0xC4,  0x40,  0xC0,  0xA1,  0x04, 	/* 07C30 */
+	0x0F,  0xFE,  0x88,  0x29,  0xF2,  0x11,  0x01,  0xF0,  0x11,  0x0F,  0xFE,  0x28,  0xCD,  0xFB,  0x08,  0x83, 	/* 07C40 */
+	0x30,  0xA2,  0x04,  0x0F,  0xFE,  0x97,  0xA5,  0x0A,  0x57,  0x87,  0x08,  0x1F,  0xEF,  0x82,  0x57,  0xC5, 	/* 07C50 */
+	0x24,  0x53,  0x89,  0xC6,  0xA4,  0x04,  0x0F,  0xFE,  0x90,  0x25,  0x7E,  0x51,  0x07,  0x7C,  0x11,  0x4F, 	/* 07C60 */
+	0xFE,  0x50,  0x05,  0x7C,  0x54,  0x49,  0x7C,  0xA5,  0x04,  0x0F,  0xFE,  0x80,  0x2F,  0xBE,  0x29,  0x45, 	/* 07C70 */
+	0xAC,  0x25,  0x00,  0xA0,  0x33,  0x8D,  0xC6,  0x03,  0x03,  0xC0,  0xA6,  0x04,  0x0F,  0xFE,  0x90,  0x29, 	/* 07C80 */
+	0xFA,  0x24,  0x87,  0xFE,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x11,  0x06,  0x0C,  0xA7,  0x04,  0x0F, 	/* 07C90 */
+	0xFE,  0x8C,  0x2A,  0xAA,  0x47,  0xC0,  0x00,  0x7F,  0xC4,  0xA4,  0xFF,  0xE0,  0x40,  0x04,  0x00,  0xC0, 	/* 07CA0 */
+	0xA8,  0x04,  0x0F,  0xFE,  0x91,  0x2B,  0xFA,  0x11,  0x07,  0xFC,  0x25,  0x07,  0xFC,  0x8E,  0x21,  0x50, 	/* 07CB0 */
+	0x64,  0xC0,  0x40,  0xA9,  0x04,  0x0F,  0xFE,  0x87,  0x23,  0xC8,  0x15,  0x0F,  0xFE,  0x0E,  0x03,  0xF8, 	/* 07CC0 */
+	0xE4,  0xE3,  0xF8,  0x24,  0x83,  0xF8,  0xAB,  0x04,  0x0F,  0xFE,  0x88,  0x2B,  0x3A,  0x20,  0x83,  0xB8, 	/* 07CD0 */
+	0x20,  0x83,  0xFE,  0x15,  0x22,  0xAA,  0xCA,  0x21,  0x0C,  0xAE,  0x04,  0x0F,  0xFE,  0x84,  0x2B,  0xFA, 	/* 07CE0 */
+	0x0E,  0x05,  0x14,  0x3F,  0x8D,  0x16,  0x1F,  0x01,  0x58,  0x64,  0x40,  0xC0,  0xB0,  0x04,  0x0F,  0xFE, 	/* 07CF0 */
+	0x80,  0x2B,  0xFA,  0x2A,  0x8F,  0xFE,  0x20,  0x83,  0xF8,  0x08,  0x43,  0x28,  0xDD,  0x83,  0x06,  0xB3, 	/* 07D00 */
+	0x04,  0x0F,  0xFE,  0x82,  0x27,  0xBE,  0x14,  0x87,  0x9C,  0x12,  0xA7,  0xF8,  0x20,  0x83,  0xF8,  0x19, 	/* 07D10 */
+	0x86,  0x04,  0xB5,  0x04,  0x0F,  0xFE,  0x92,  0x27,  0xFC,  0x2A,  0x0F,  0xFC,  0x48,  0x47,  0xBC,  0x4A, 	/* 07D20 */
+	0x07,  0xBC,  0x4A,  0x25,  0x9E,  0xB6,  0x04,  0x0F,  0xFE,  0x91,  0x67,  0xEA,  0x11,  0x07,  0xFE,  0x25, 	/* 07D30 */
+	0x43,  0xFC,  0x20,  0x83,  0xF8,  0x11,  0x86,  0x04,  0xB8,  0x01,  0x00,  0x10,  0x01,  0x0F,  0xFE,  0x01, 	/* 07D40 */
+	0x00,  0x10,  0x21,  0x01,  0x10,  0x11,  0x00,  0x10,  0x01,  0x00,  0x30,  0xBA,  0x04,  0x07,  0xFC,  0x04, 	/* 07D50 */
+	0x00,  0x40,  0xFF,  0xE0,  0x10,  0x7F,  0xE1,  0x10,  0x09,  0x00,  0x90,  0x01,  0x00,  0x30,  0xBE,  0x20, 	/* 07D60 */
+	0x42,  0x04,  0x20,  0x4F,  0xFF,  0x08,  0x44,  0xA4,  0x29,  0x41,  0x14,  0x10,  0x42,  0x84,  0x44,  0x48, 	/* 07D70 */
+	0x0C,  0xBF,  0x04,  0x07,  0xFC,  0x04,  0x03,  0xF8,  0x04,  0x0F,  0xFE,  0x08,  0x8F,  0xFE,  0x10,  0x82, 	/* 07D80 */
+	0x88,  0x44,  0x80,  0x18,  0x81,  0x10,  0x41,  0x04,  0x7C,  0x41,  0x7E,  0x10,  0x4F,  0xE4,  0x11,  0x47, 	/* 07D90 */
+	0xC4,  0x10,  0x41,  0x04,  0x1C,  0x4E,  0x0C,  0x82,  0x04,  0x0F,  0xFE,  0x04,  0x03,  0xF8,  0x24,  0x83, 	/* 07DA0 */
+	0xF8,  0x24,  0x8F,  0xFE,  0x21,  0x01,  0x10,  0x01,  0x00,  0x30,  0x84,  0x20,  0x47,  0x84,  0x48,  0x47, 	/* 07DB0 */
+	0xFE,  0x48,  0x47,  0xA4,  0x4D,  0x4F,  0x94,  0x18,  0x42,  0x84,  0xC8,  0x41,  0x8C,  0x85,  0x20,  0x42, 	/* 07DC0 */
+	0x04,  0xF8,  0x42,  0x7E,  0xF8,  0x48,  0xA4,  0x89,  0x4F,  0x84,  0x50,  0x45,  0x0C,  0x50,  0x18,  0xFF, 	/* 07DD0 */
+	0x86,  0x20,  0xC2,  0xF0,  0xAA,  0x46,  0x54,  0x25,  0x82,  0x08,  0x3F,  0xE6,  0x08,  0xA8,  0x82,  0x48, 	/* 07DE0 */
+	0x20,  0x82,  0x18,  0x87,  0x50,  0xE5,  0x79,  0x51,  0x65,  0x0C,  0x77,  0x81,  0x04,  0xFF,  0xF5,  0x04, 	/* 07DF0 */
+	0x54,  0x45,  0x24,  0x90,  0x41,  0x0C,  0x88,  0x04,  0x0F,  0xFE,  0x24,  0x83,  0xF8,  0x24,  0x83,  0xF8, 	/* 07E00 */
+	0x04,  0x87,  0xFC,  0x01,  0x2F,  0xFE,  0x21,  0x01,  0x30,  0x89,  0x00,  0x47,  0xC4,  0x44,  0x47,  0xFE, 	/* 07E10 */
+	0x40,  0x47,  0xD4,  0x41,  0x47,  0xD4,  0x48,  0x4A,  0xA4,  0xAA,  0x41,  0x8C,  0x8A,  0x11,  0x07,  0xFE, 	/* 07E20 */
+	0x0A,  0x03,  0xFC,  0x2A,  0x43,  0x3C,  0x3F,  0xC0,  0x10,  0xFF,  0xE1,  0x10,  0x09,  0x00,  0x30,  0x8B, 	/* 07E30 */
+	0x3F,  0x80,  0x08,  0x3F,  0x80,  0x08,  0xFF,  0xE2,  0x22,  0xFB,  0xE0,  0x10,  0xFF,  0xE1,  0x10,  0x09, 	/* 07E40 */
+	0x00,  0x30,  0x8D,  0x2A,  0x4A,  0xA4,  0x6C,  0x4F,  0xFF,  0x44,  0x42,  0x84,  0x7D,  0x41,  0x0C,  0x7C, 	/* 07E50 */
+	0x41,  0x04,  0x1C,  0x4E,  0x0C,  0x8E,  0x44,  0x82,  0xFC,  0x02,  0x0E,  0x7C,  0x24,  0x42,  0x7C,  0x5C, 	/* 07E60 */
+	0x48,  0xFE,  0x01,  0x0F,  0xFE,  0x11,  0x00,  0x30,  0x8F,  0x04,  0x00,  0x40,  0x04,  0x00,  0x50,  0x24, 	/* 07E70 */
+	0x82,  0x44,  0x44,  0x44,  0x42,  0x84,  0x20,  0x40,  0x04,  0x00,  0xC0,  0x91,  0x04,  0x00,  0x40,  0x05, 	/* 07E80 */
+	0x02,  0x48,  0x24,  0x42,  0x42,  0x44,  0xA8,  0xC8,  0x01,  0x00,  0x20,  0x0C,  0x03,  0x00,  0x93,  0x10, 	/* 07E90 */
+	0x01,  0x00,  0x10,  0x01,  0xFE,  0x22,  0x04,  0x20,  0x12,  0x81,  0x24,  0x22,  0x24,  0x22,  0x02,  0x00, 	/* 07EA0 */
+	0x60,  0x96,  0x04,  0x01,  0x50,  0x14,  0x82,  0x44,  0x44,  0x40,  0xC0,  0x04,  0x0F,  0xFE,  0x04,  0x00, 	/* 07EB0 */
+	0xA0,  0x31,  0x8C,  0x06,  0x9A,  0x04,  0x04,  0x44,  0x24,  0x42,  0x48,  0xFF,  0xE8,  0x02,  0x9F,  0x29, 	/* 07EC0 */
+	0x12,  0x91,  0x29,  0xF2,  0x80,  0x28,  0x06,  0xA0,  0x48,  0x8F,  0xC8,  0x4A,  0xC7,  0xAA,  0x4A,  0xA7, 	/* 07ED0 */
+	0xC9,  0x48,  0xAF,  0xDA,  0xA8,  0x4C,  0xC8,  0x83,  0x07,  0xC0,  0xA2,  0x08,  0x00,  0x80,  0x08,  0x0F, 	/* 07EE0 */
+	0xFE,  0x0A,  0x00,  0xA0,  0x0A,  0x00,  0xA0,  0x12,  0x01,  0x22,  0x22,  0x2C,  0x1E,  0xA4,  0x04,  0x80, 	/* 07EF0 */
+	0x44,  0x04,  0x07,  0xFE,  0x04,  0x00,  0x60,  0x06,  0x00,  0xA0,  0x0A,  0x01,  0x22,  0x22,  0x24,  0x1E, 	/* 07F00 */
+	0xA8,  0x20,  0x82,  0x88,  0x25,  0x0F,  0xD4,  0x2A,  0x42,  0x88,  0x29,  0x22,  0xA2,  0x28,  0x44,  0x88, 	/* 07F10 */
+	0x49,  0x28,  0x7E,  0xAD,  0x04,  0x07,  0xF8,  0x04,  0x02,  0x50,  0xFF,  0xC2,  0x10,  0x00,  0x0F,  0xFE, 	/* 07F20 */
+	0x12,  0x01,  0x24,  0x22,  0x4C,  0x1C,  0xB1,  0x21,  0x0F,  0xD4,  0x01,  0x27,  0xFE,  0x49,  0x04,  0x90, 	/* 07F30 */
+	0x7B,  0x02,  0x30,  0x6B,  0x0A,  0x52,  0x29,  0x26,  0x0E,  0xB8,  0x00,  0x03,  0xFE,  0x20,  0x22,  0x02, 	/* 07F40 */
+	0x3F,  0xE2,  0x00,  0x20,  0x02,  0x00,  0x20,  0x04,  0x00,  0x40,  0x08,  0x00,  0xB9,  0x00,  0x07,  0xFC, 	/* 07F50 */
+	0x04,  0x40,  0x44,  0xFF,  0xF0,  0x44,  0x04,  0x47,  0xFC,  0x04,  0x00,  0x80,  0x08,  0x01,  0x00,  0xBA, 	/* 07F60 */
+	0x00,  0x01,  0xFC,  0x10,  0x41,  0x04,  0x10,  0x41,  0xFC,  0x14,  0x01,  0x40,  0x22,  0x02,  0x10,  0x40, 	/* 07F70 */
+	0x88,  0x06,  0xBB,  0x00,  0x07,  0xFC,  0x40,  0x44,  0x04,  0x7F,  0xC4,  0x40,  0x7F,  0x84,  0x48,  0x44, 	/* 07F80 */
+	0x84,  0x4A,  0x88,  0xA1,  0x06,  0xBC,  0x00,  0x03,  0xFC,  0x20,  0x42,  0x04,  0x3F,  0xC2,  0x80,  0x28, 	/* 07F90 */
+	0xC2,  0xF0,  0x28,  0x04,  0x82,  0x48,  0x28,  0x7E,  0xBD,  0x3F,  0x82,  0x08,  0x20,  0x83,  0xF8,  0x21, 	/* 07FA0 */
+	0x02,  0x10,  0x2C,  0x84,  0x34,  0x40,  0x29,  0xC0,  0x03,  0x00,  0x08,  0xBE,  0x00,  0x03,  0xFC,  0x20, 	/* 07FB0 */
+	0x43,  0xFC,  0x23,  0x82,  0xE0,  0x23,  0xC3,  0xE0,  0x23,  0xE7,  0xE0,  0x42,  0x28,  0x1E,  0xBF,  0x00, 	/* 07FC0 */
+	0x07,  0xFC,  0x40,  0x44,  0x04,  0x7F,  0xC4,  0x24,  0x7A,  0x84,  0xB0,  0x4B,  0x09,  0x28,  0xA2,  0x60, 	/* 07FD0 */
+	0x60,  0x80,  0x00,  0x03,  0xFC,  0x20,  0x43,  0xFC,  0x20,  0x03,  0xFE,  0x20,  0x22,  0xF2,  0x49,  0x24, 	/* 07FE0 */
+	0x92,  0x8F,  0x20,  0x0C,  0x81,  0x00,  0x03,  0xFE,  0x20,  0x22,  0x02,  0x3F,  0xE2,  0x90,  0x29,  0x22, 	/* 07FF0 */
+	0xF4,  0x49,  0x84,  0x92,  0x9F,  0x23,  0x0E,  0x85,  0x00,  0x03,  0xFC,  0x20,  0x43,  0xFC,  0x22,  0x03, 	/* 08000 */
+	0xFE,  0x22,  0x02,  0x20,  0x5F,  0xC5,  0x04,  0x90,  0x41,  0xFC,  0x86,  0x00,  0x07,  0xFE,  0x40,  0x27, 	/* 08010 */
+	0xFE,  0x42,  0x05,  0x22,  0x5F,  0xE5,  0x22,  0x52,  0x29,  0xFA,  0x90,  0x21,  0xFE,  0x88,  0x00,  0x07, 	/* 08020 */
+	0xFE,  0x40,  0x27,  0xFE,  0x42,  0x05,  0x24,  0x52,  0x45,  0xFC,  0x42,  0x06,  0x22,  0xA2,  0x23,  0xFE, 	/* 08030 */
+	0x8A,  0x00,  0x03,  0xFE,  0x20,  0x23,  0xFE,  0x22,  0x03,  0xFE,  0x32,  0x23,  0x22,  0x5F,  0xE5,  0x22, 	/* 08040 */
+	0x92,  0x21,  0xFE,  0x8B,  0x3F,  0xC2,  0x04,  0x3F,  0xC2,  0x00,  0x3F,  0xE2,  0x50,  0x28,  0xC3,  0xF2, 	/* 08050 */
+	0x42,  0x05,  0xFC,  0x82,  0x07,  0xFE,  0x8D,  0x00,  0x07,  0xFE,  0x40,  0x27,  0xFE,  0x40,  0x07,  0xFE, 	/* 08060 */
+	0x5D,  0x06,  0x56,  0x55,  0x88,  0x92,  0x11,  0x26,  0x0E,  0x8E,  0x00,  0x07,  0xFE,  0x40,  0x27,  0xFE, 	/* 08070 */
+	0x42,  0x05,  0x24,  0x4A,  0x87,  0xFE,  0x47,  0x04,  0xA8,  0x92,  0x68,  0x20,  0x8F,  0x00,  0x07,  0xFC, 	/* 08080 */
+	0x40,  0x47,  0xFC,  0x50,  0x87,  0xFC,  0x49,  0x04,  0x90,  0x7F,  0xE8,  0x90,  0x91,  0x02,  0x10,  0x90, 	/* 08090 */
+	0x00,  0x07,  0xFC,  0x40,  0x47,  0xFC,  0x48,  0x85,  0x3E,  0x68,  0x84,  0xFE,  0x52,  0x4B,  0x18,  0x92, 	/* 080A0 */
+	0x41,  0xC2,  0x91,  0x7F,  0xE4,  0x02,  0x7F,  0xE5,  0x24,  0x4A,  0x85,  0xFC,  0x50,  0x45,  0xFC,  0x50, 	/* 080B0 */
+	0x45,  0xFC,  0x90,  0x41,  0x0C,  0x93,  0x00,  0x07,  0xFE,  0x40,  0x27,  0xFE,  0x50,  0x45,  0xFC,  0x50, 	/* 080C0 */
+	0x45,  0xFC,  0x50,  0x49,  0xFC,  0x8C,  0xC3,  0x02,  0x95,  0x00,  0x07,  0xFC,  0x40,  0x47,  0xFC,  0x49, 	/* 080D0 */
+	0x05,  0xFC,  0x49,  0x07,  0xFC,  0x4A,  0x28,  0x94,  0x8E,  0x83,  0x06,  0x9E,  0x3F,  0xC2,  0x04,  0x3F, 	/* 080E0 */
+	0xE2,  0xF8,  0x3A,  0x82,  0xF8,  0x22,  0x03,  0xFE,  0x62,  0xA6,  0x7E,  0xB8,  0x22,  0x06,  0xA0,  0x3F, 	/* 080F0 */
+	0xE2,  0x02,  0x3F,  0xE2,  0x20,  0x2F,  0xC2,  0x28,  0x3F,  0xF2,  0x7C,  0x4C,  0x45,  0x7C,  0xA4,  0x40, 	/* 08100 */
+	0x7C,  0xA1,  0x00,  0x07,  0xFC,  0x40,  0x47,  0xFC,  0x4A,  0x87,  0xFE,  0x4F,  0x85,  0x24,  0x7F,  0xE9, 	/* 08110 */
+	0x90,  0x87,  0x03,  0x8C,  0xA4,  0x7F,  0xE4,  0x02,  0x7F,  0xE5,  0x24,  0x5F,  0xC5,  0x24,  0x5F,  0xC4, 	/* 08120 */
+	0xF8,  0x48,  0x88,  0xF8,  0x88,  0x80,  0xF8,  0xA5,  0x00,  0x07,  0xFC,  0x40,  0x47,  0xFC,  0x52,  0x06, 	/* 08130 */
+	0xBE,  0x56,  0x47,  0xBC,  0x51,  0xC5,  0x64,  0x51,  0x89,  0xE6,  0xAC,  0x00,  0x07,  0xFC,  0x40,  0x47, 	/* 08140 */
+	0xFC,  0x42,  0x07,  0x2E,  0x5F,  0xC5,  0x54,  0x7F,  0xE9,  0xF2,  0x85,  0x23,  0xEC,  0xAE,  0x04,  0x00, 	/* 08150 */
+	0x40,  0x44,  0x44,  0x44,  0x44,  0x44,  0x44,  0x44,  0x47,  0xFC,  0x48,  0x00,  0x80,  0x10,  0x02,  0x00, 	/* 08160 */
+	0xAF,  0x04,  0x00,  0x5C,  0xFE,  0x00,  0x40,  0x44,  0x44,  0x44,  0x44,  0x47,  0xFC,  0x44,  0x00,  0x42, 	/* 08170 */
+	0x04,  0x20,  0x3E,  0xB1,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x04,  0x44,  0x44,  0x44,  0x44, 	/* 08180 */
+	0x44,  0x44,  0x44,  0x7F,  0xC4,  0x04,  0xB6,  0x04,  0x04,  0x44,  0x44,  0x47,  0xFC,  0x00,  0x0F,  0xFE, 	/* 08190 */
+	0x04,  0x20,  0x42,  0x04,  0x20,  0x82,  0x30,  0x2C,  0x0C,  0xB9,  0x22,  0x02,  0x20,  0xAB,  0xFA,  0xC0, 	/* 081A0 */
+	0xAB,  0xCA,  0x84,  0xA8,  0x8A,  0x90,  0xA9,  0x0F,  0xA2,  0x02,  0x20,  0x1E,  0x8C,  0x04,  0x04,  0x44, 	/* 081B0 */
+	0x7F,  0xC0,  0x00,  0x7F,  0x80,  0x90,  0x09,  0x01,  0xFC,  0x14,  0x82,  0x30,  0x46,  0x89,  0x86,  0x90, 	/* 081C0 */
+	0x01,  0x02,  0x10,  0x2F,  0xEA,  0x90,  0xA9,  0x0A,  0xFE,  0xAA,  0x4A,  0xA4,  0xA9,  0x8F,  0x88,  0x03, 	/* 081D0 */
+	0x40,  0xC2,  0x91,  0x04,  0x04,  0x44,  0x7F,  0xC0,  0x40,  0x0A,  0x03,  0x18,  0xDF,  0x60,  0x00,  0x3F, 	/* 081E0 */
+	0x80,  0x10,  0x02,  0x00,  0x40,  0x94,  0x0A,  0x01,  0x10,  0x20,  0x8D,  0xFE,  0x08,  0x81,  0x08,  0x63, 	/* 081F0 */
+	0x00,  0x40,  0x44,  0x44,  0x44,  0x44,  0x47,  0xFC,  0xA1,  0x00,  0x0F,  0xFE,  0x91,  0x28,  0x92,  0x8A, 	/* 08200 */
+	0x2F,  0xFE,  0x84,  0x2A,  0x4A,  0xA4,  0xAB,  0xFA,  0x80,  0x28,  0x06,  0xA8,  0x20,  0x02,  0x3C,  0xAA, 	/* 08210 */
+	0x4A,  0xA4,  0xAB,  0xCA,  0xA4,  0xAA,  0x4A,  0xBC,  0xAA,  0x4F,  0xA4,  0x8A,  0x40,  0x7E,  0xA9,  0x04, 	/* 08220 */
+	0x04,  0x44,  0x44,  0x47,  0xFC,  0x00,  0x0F,  0xFE,  0x10,  0x01,  0x00,  0x3F,  0xC5,  0x04,  0x90,  0x41, 	/* 08230 */
+	0xFC,  0xAB,  0x21,  0x02,  0x10,  0xA9,  0x0A,  0xFE,  0xAD,  0x2A,  0xD2,  0xAD,  0x2A,  0xFE,  0xFD,  0x28, 	/* 08240 */
+	0x52,  0x05,  0x20,  0x7E,  0xAC,  0x20,  0x02,  0xFE,  0x29,  0x2A,  0xFE,  0xA9,  0x2A,  0x92,  0xAF,  0xEA, 	/* 08250 */
+	0x90,  0xF9,  0x08,  0x10,  0x01,  0x00,  0x10,  0xB1,  0x22,  0x82,  0x24,  0x43,  0xED,  0xE0,  0x41,  0x04, 	/* 08260 */
+	0x0A,  0x44,  0x60,  0x40,  0x44,  0x44,  0x44,  0x44,  0x47,  0xFC,  0xB3,  0x01,  0x83,  0xE0,  0x20,  0x03, 	/* 08270 */
+	0xFC,  0x21,  0x02,  0x10,  0xFF,  0xE0,  0x40,  0x44,  0x44,  0x44,  0x44,  0x47,  0xFC,  0xB6,  0x20,  0x82, 	/* 08280 */
+	0x08,  0xA9,  0x0A,  0xBE,  0xAA,  0x2A,  0xA2,  0xAA,  0x2A,  0xBE,  0xAA,  0x2F,  0xA2,  0x02,  0x20,  0x3E, 	/* 08290 */
+	0xB7,  0x20,  0x02,  0x3E,  0xAA,  0x2A,  0xA2,  0xAB,  0xEA,  0xA8,  0xAB,  0xEA,  0xA8,  0xAA,  0xAF,  0xA6, 	/* 082A0 */
+	0x03,  0x60,  0xC2,  0xB8,  0x44,  0x44,  0x44,  0x7F,  0xC0,  0x00,  0x7F,  0xE4,  0x00,  0x5F,  0xC4,  0x20, 	/* 082B0 */
+	0x7F,  0xE4,  0x20,  0x82,  0x00,  0x20,  0xBB,  0x20,  0xC2,  0x38,  0xAA,  0x8A,  0xA8,  0xAA,  0x8A,  0xBE, 	/* 082C0 */
+	0xAA,  0x8A,  0xA8,  0xFA,  0xA0,  0xF6,  0x00,  0x60,  0xF2,  0xBC,  0x20,  0x02,  0x7E,  0xA8,  0x8A,  0xAC, 	/* 082D0 */
+	0xAC,  0xAA,  0x88,  0xAF,  0xFA,  0x88,  0xA8,  0x8F,  0x88,  0x00,  0x80,  0x08,  0xBE,  0x21,  0x02,  0x10, 	/* 082E0 */
+	0x21,  0x0A,  0x9E,  0xA9,  0x0A,  0x90,  0xA9,  0x0A,  0xFE,  0xAC,  0x2F,  0xC2,  0x04,  0x20,  0x7E,  0x85, 	/* 082F0 */
+	0x21,  0x02,  0x24,  0xAF,  0xEA,  0xA4,  0xAA,  0x4A,  0xA4,  0xAF,  0xFA,  0xA4,  0xFA,  0x40,  0x44,  0x04, 	/* 08300 */
+	0x40,  0x84,  0x87,  0x04,  0x04,  0x44,  0x44,  0x47,  0xFC,  0x0A,  0x01,  0x10,  0x3F,  0x8C,  0x06,  0x3F, 	/* 08310 */
+	0x82,  0x08,  0x20,  0x83,  0xF8,  0x99,  0x21,  0x02,  0x10,  0x27,  0xCA,  0x90,  0xAF,  0xEA,  0x88,  0xAF, 	/* 08320 */
+	0xEA,  0x88,  0xAC,  0x8F,  0xA8,  0x00,  0x80,  0x18,  0xA0,  0x21,  0x02,  0x10,  0xA9,  0xCA,  0x90,  0xAF, 	/* 08330 */
+	0xEA,  0x80,  0xAF,  0xEA,  0x90,  0xF9,  0xC8,  0x12,  0x01,  0x00,  0x10,  0xA1,  0x01,  0x02,  0x10,  0x2F, 	/* 08340 */
+	0xE2,  0x12,  0xAD,  0x4A,  0xB8,  0xAF,  0xEA,  0x90,  0xA9,  0x0F,  0xA8,  0x04,  0x41,  0x82,  0xA8,  0x02, 	/* 08350 */
+	0x82,  0xCC,  0x24,  0xA2,  0x48,  0x2F,  0xEA,  0xC8,  0xAE,  0xAA,  0xCA,  0xAC,  0x4F,  0xCC,  0x05,  0x60, 	/* 08360 */
+	0xC2,  0xA9,  0x04,  0x04,  0x44,  0x7F,  0xC0,  0xD0,  0x71,  0x41,  0x12,  0xFF,  0xE1,  0x14,  0x1D,  0x4F, 	/* 08370 */
+	0x0A,  0x11,  0x63,  0x22,  0xAA,  0x22,  0x82,  0x24,  0xAD,  0x4A,  0x92,  0xAA,  0x8A,  0xA4,  0xAF,  0xEA, 	/* 08380 */
+	0xA5,  0xAA,  0x4F,  0xA4,  0x02,  0x40,  0x3C,  0xAD,  0x20,  0x82,  0x2C,  0xAA,  0xAA,  0xC9,  0xAB,  0xFA, 	/* 08390 */
+	0xA2,  0xAB,  0xEA,  0xA2,  0xAB,  0xEF,  0xA2,  0x02,  0x20,  0x26,  0xAF,  0x04,  0x04,  0x44,  0x7F,  0xC0, 	/* 083A0 */
+	0xF0,  0x71,  0x00,  0xE0,  0x31,  0x8C,  0x46,  0x7F,  0xC0,  0x40,  0xFF,  0xE0,  0x40,  0xB0,  0x22,  0x02, 	/* 083B0 */
+	0x3C,  0xA4,  0x4A,  0xB8,  0xAA,  0x8A,  0xD4,  0xA9,  0x3A,  0xFC,  0xF9,  0x00,  0xFE,  0x01,  0x00,  0x10, 	/* 083C0 */
+	0xB6,  0x08,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xFE,  0x20,  0x03,  0xFE,  0x08,  0x24,  0x92, 	/* 083D0 */
+	0x7F,  0x20,  0x0C,  0xBA,  0x20,  0x02,  0xFF,  0xA8,  0x8A,  0xBE,  0xAA,  0xAA,  0xBE,  0xAA,  0xAA,  0xBE, 	/* 083E0 */
+	0xAA,  0x8F,  0x90,  0x02,  0xC0,  0xC3,  0xBB,  0x21,  0x02,  0x24,  0xAF,  0xAA,  0xA8,  0xAA,  0xAA,  0xC6, 	/* 083F0 */
+	0xA9,  0x0A,  0xBC,  0xFE,  0x40,  0x18,  0x06,  0x81,  0x86,  0xBD,  0x21,  0x02,  0x10,  0x27,  0xEA,  0xD4, 	/* 08400 */
+	0xAD,  0x4A,  0xBA,  0xA9,  0x2A,  0x90,  0xAA,  0x8F,  0xA4,  0x04,  0x21,  0x81,  0x87,  0x44,  0x47,  0xFC, 	/* 08410 */
+	0x04,  0x0F,  0xFE,  0x80,  0x23,  0xF8,  0x00,  0x0F,  0xFE,  0x04,  0x02,  0x58,  0xC4,  0x60,  0xC0,  0x8B, 	/* 08420 */
+	0x04,  0x04,  0x44,  0x7F,  0xC0,  0x00,  0x7F,  0xC2,  0x48,  0xFF,  0xE2,  0x48,  0x7F,  0xC0,  0x40,  0x7F, 	/* 08430 */
+	0xC0,  0x40,  0x8E,  0x21,  0x02,  0xFE,  0x21,  0x0A,  0xA8,  0xAC,  0x4A,  0xFE,  0xA8,  0x4A,  0xF4,  0xFD, 	/* 08440 */
+	0x48,  0x74,  0x00,  0x40,  0x0C,  0x91,  0x04,  0x04,  0x44,  0x7F,  0xC2,  0x08,  0x3F,  0x82,  0x08,  0x3F, 	/* 08450 */
+	0x82,  0x20,  0x3A,  0x42,  0x38,  0x3E,  0x2E,  0x1E,  0x94,  0x04,  0x04,  0x44,  0x7F,  0xC1,  0x10,  0x12, 	/* 08460 */
+	0x03,  0xFE,  0x62,  0x0B,  0xFC,  0x22,  0x03,  0xFC,  0x22,  0x03,  0xFE,  0x95,  0x20,  0x02,  0xFE,  0xA9, 	/* 08470 */
+	0x0A,  0xFC,  0xA9,  0x0A,  0xFE,  0xA9,  0x0A,  0x90,  0xFF,  0xC1,  0x10,  0x11,  0x02,  0xFE,  0x96,  0x44, 	/* 08480 */
+	0x47,  0xFC,  0x00,  0x07,  0xFE,  0x42,  0x05,  0xFC,  0x42,  0x07,  0xFE,  0x42,  0x05,  0xFC,  0x82,  0x03, 	/* 08490 */
+	0xFE,  0x97,  0x44,  0x44,  0x44,  0x7F,  0xC0,  0x00,  0xFF,  0xE9,  0x12,  0xBF,  0xA8,  0x42,  0xA4,  0xAA, 	/* 084A0 */
+	0x4A,  0xBF,  0xA8,  0x06,  0x98,  0x21,  0x02,  0x28,  0xAC,  0x4A,  0x82,  0xAF,  0xDA,  0x80,  0xAF,  0xEA, 	/* 084B0 */
+	0xAA,  0xAF,  0xEF,  0xAA,  0x0A,  0xA0,  0x86,  0x99,  0x04,  0x04,  0x44,  0x7F,  0xC0,  0xA0,  0x11,  0x03, 	/* 084C0 */
+	0xF8,  0xC0,  0x67,  0xFC,  0x4A,  0x47,  0xFC,  0x4A,  0x44,  0xAC,  0x9A,  0x21,  0x02,  0x7C,  0xA9,  0x0A, 	/* 084D0 */
+	0xFE,  0xAA,  0x8A,  0xAA,  0xAD,  0x6A,  0xBC,  0xFE,  0x40,  0x98,  0x06,  0x81,  0x86,  0x9B,  0x20,  0x02, 	/* 084E0 */
+	0xFE,  0xA8,  0x2A,  0xFE,  0xA9,  0x0A,  0xD4,  0xAD,  0x4A,  0xFC,  0xF9,  0x21,  0x92,  0x19,  0x22,  0xFE, 	/* 084F0 */
+	0x9F,  0x04,  0x04,  0x44,  0x44,  0x47,  0xFC,  0x0A,  0x01,  0x10,  0x3F,  0x8C,  0x46,  0x7F,  0xC2,  0x48, 	/* 08500 */
+	0x15,  0x0F,  0xFE,  0xA2,  0x20,  0xC2,  0x74,  0xAD,  0x2A,  0x92,  0xAB,  0xCA,  0x94,  0xAF,  0xEA,  0x94, 	/* 08510 */
+	0xAF,  0xCF,  0x90,  0x01,  0x00,  0x30,  0xA9,  0x04,  0x04,  0x44,  0x7F,  0xC0,  0x00,  0x79,  0xE4,  0x92, 	/* 08520 */
+	0x79,  0xE4,  0x92,  0x79,  0xE4,  0x92,  0x49,  0x29,  0xA6,  0x8B,  0x20,  0x02,  0xFE,  0xA9,  0x2A,  0xFE, 	/* 08530 */
+	0xA8,  0x0A,  0xBE,  0xAA,  0x2A,  0xBE,  0xFA,  0x20,  0xBE,  0x12,  0x22,  0x3E,  0x8C,  0x04,  0x04,  0x44, 	/* 08540 */
+	0x44,  0x47,  0xFC,  0x49,  0x04,  0x9E,  0xFD,  0xA4,  0xAC,  0x78,  0x84,  0x94,  0x4A,  0x47,  0xC2,  0x8E, 	/* 08550 */
+	0x20,  0x02,  0xFC,  0x2A,  0x4A,  0xFC,  0xAA,  0x4A,  0xFC,  0xAA,  0x0A,  0xFE,  0xAA,  0xAF,  0xF6,  0x08, 	/* 08560 */
+	0x20,  0x86,  0x90,  0x44,  0x44,  0x44,  0x7F,  0xC4,  0x34,  0x7C,  0x45,  0xF4,  0x55,  0x45,  0xF4,  0x46, 	/* 08570 */
+	0x44,  0x55,  0xBF,  0xB8,  0x09,  0x92,  0x00,  0x01,  0xF0,  0x11,  0x01,  0x10,  0xFF,  0xE8,  0xA2,  0xFB, 	/* 08580 */
+	0xE0,  0x40,  0x44,  0x44,  0x44,  0x44,  0x47,  0xFC,  0x9C,  0x44,  0x44,  0x44,  0x7F,  0xC0,  0x40,  0x7F, 	/* 08590 */
+	0xC1,  0x10,  0x0A,  0x0F,  0xFE,  0x3E,  0x42,  0x24,  0x3E,  0x40,  0x0C,  0xA9,  0x24,  0x43,  0xFC,  0x04, 	/* 085A0 */
+	0x0F,  0xFF,  0x10,  0x81,  0xF8,  0x00,  0x07,  0xFE,  0x4F,  0x24,  0x92,  0x4F,  0x24,  0x06,  0xAC,  0x04, 	/* 085B0 */
+	0x08,  0x42,  0xFF,  0xE0,  0x80,  0x3F,  0x82,  0x48,  0x3F,  0x82,  0x4C,  0x3F,  0xA0,  0xAE,  0x32,  0x2C, 	/* 085C0 */
+	0x1E,  0xAF,  0x24,  0x42,  0x28,  0xAF,  0xEA,  0x90,  0xAF,  0xCA,  0x90,  0xAF,  0xEA,  0xA0,  0xFF,  0xE8, 	/* 085D0 */
+	0x90,  0x11,  0x02,  0xFE,  0xB3,  0x04,  0x04,  0x44,  0x7F,  0xC1,  0x10,  0x7F,  0xC0,  0x40,  0x3F,  0x80, 	/* 085E0 */
+	0x40,  0xFF,  0xE2,  0xF8,  0x42,  0x0B,  0xFC,  0xB6,  0x20,  0x02,  0xEE,  0x22,  0x2A,  0xEE,  0xA8,  0x8A, 	/* 085F0 */
+	0xEE,  0xAE,  0x6A,  0xAA,  0xAE,  0x6F,  0xAA,  0x02,  0x20,  0xCC,  0x82,  0x21,  0x02,  0x7E,  0xAA,  0x8A, 	/* 08600 */
+	0xFE,  0xAC,  0x4A,  0xFC,  0xAC,  0x4A,  0xFC,  0xF9,  0x00,  0xFE,  0x01,  0x00,  0x10,  0x84,  0x04,  0x04, 	/* 08610 */
+	0x44,  0x7F,  0xC1,  0x02,  0xFF,  0xC5,  0x50,  0x7D,  0xE5,  0x54,  0x7D,  0x41,  0x24,  0xFE,  0x41,  0x44, 	/* 08620 */
+	0x87,  0x20,  0x02,  0xFE,  0xAB,  0x8A,  0xA8,  0xAB,  0x8A,  0x80,  0xAF,  0xEA,  0xDA,  0xAD,  0xAF,  0xFE, 	/* 08630 */
+	0x08,  0x00,  0xFE,  0x8B,  0x01,  0x02,  0x3C,  0x22,  0x4A,  0xBC,  0xAA,  0x4A,  0xBE,  0xAA,  0x0A,  0xBE, 	/* 08640 */
+	0xF8,  0x20,  0x56,  0x05,  0x20,  0x8C,  0x8C,  0x04,  0x04,  0x44,  0x7F,  0xC2,  0x08,  0x3F,  0x82,  0x08, 	/* 08650 */
+	0x3F,  0xE2,  0x00,  0x3F,  0xE4,  0xA2,  0x55,  0x28,  0x0C,  0x90,  0x04,  0x04,  0x44,  0x7F,  0xCE,  0x7C, 	/* 08660 */
+	0xBC,  0x8A,  0x38,  0xCD,  0x6B,  0x7C,  0xA9,  0x0A,  0xFC,  0xE1,  0x09,  0xFE,  0x9D,  0x23,  0x02,  0x54, 	/* 08670 */
+	0xAA,  0xAA,  0xC4,  0xAB,  0xAA,  0x81,  0xAF,  0xCA,  0xC4,  0xAF,  0xCF,  0xC4,  0x02,  0x81,  0xFE,  0xA2, 	/* 08680 */
+	0x21,  0x02,  0x7C,  0xA9,  0x0A,  0xFE,  0xAA,  0x4A,  0xFE,  0xAA,  0x4A,  0xFE,  0xF8,  0x00,  0xFE,  0x02, 	/* 08690 */
+	0xA1,  0xCE,  0xAC,  0x22,  0x82,  0xFE,  0xA1,  0x0A,  0xFC,  0xA9,  0x0A,  0xFE,  0xA9,  0x4A,  0xFE,  0xFC, 	/* 086A0 */
+	0xA1,  0x64,  0x04,  0xD0,  0xD3,  0xAE,  0x21,  0x02,  0x18,  0xAA,  0x4A,  0xFE,  0xA8,  0x1A,  0xFE,  0xAD, 	/* 086B0 */
+	0xAA,  0xFE,  0xFC,  0x80,  0x48,  0x0B,  0x41,  0x22,  0xB7,  0x04,  0x04,  0x42,  0x7F,  0xE4,  0xBE,  0x71, 	/* 086C0 */
+	0x44,  0x48,  0x7F,  0xE9,  0x08,  0xFE,  0xE1,  0x38,  0x2A,  0xC4,  0x43,  0xBA,  0x44,  0x44,  0x44,  0x7F, 	/* 086D0 */
+	0xC2,  0x3E,  0x31,  0x04,  0xBE,  0x7A,  0x2A,  0xBE,  0x2A,  0x23,  0x3E,  0x21,  0x42,  0x63,  0xBC,  0x22, 	/* 086E0 */
+	0x02,  0xFE,  0x2A,  0x2A,  0xA2,  0xAF,  0xEA,  0x8A,  0xAA,  0xAA,  0xEE,  0xFA,  0xA1,  0xFF,  0x02,  0x80, 	/* 086F0 */
+	0xC4,  0xBD,  0x04,  0x04,  0x44,  0x7F,  0xC8,  0x4C,  0x54,  0xA3,  0xE8,  0x61,  0xEA,  0xE8,  0x30,  0x8E, 	/* 08700 */
+	0xF4,  0x2B,  0x4C,  0xE2,  0x89,  0x23,  0x82,  0x50,  0xAF,  0xCA,  0xC4,  0xAF,  0xEA,  0xA4,  0xAF,  0x6A, 	/* 08710 */
+	0xFC,  0xAD,  0x4F,  0xFC,  0x02,  0xA0,  0xCE,  0x8C,  0x44,  0x47,  0xFC,  0x02,  0x07,  0xFE,  0x5D,  0x04, 	/* 08720 */
+	0x9F,  0x7E,  0x25,  0x6A,  0x5C,  0xC5,  0x44,  0xBC,  0xA8,  0x72,  0x8D,  0x04,  0x04,  0x44,  0x7F,  0xC7, 	/* 08730 */
+	0x90,  0x27,  0xCF,  0xD4,  0x77,  0xCA,  0xD4,  0xFF,  0xC5,  0x18,  0x32,  0xAC,  0xCE,  0x92,  0x44,  0x4A, 	/* 08740 */
+	0xEA,  0x40,  0x4A,  0xEA,  0xF1,  0xE2,  0xE4,  0x7A,  0xEA,  0xF5,  0x04,  0x04,  0x44,  0x44,  0x47,  0xFC, 	/* 08750 */
+	0x93,  0x44,  0x47,  0xFC,  0x43,  0xE7,  0xC8,  0xAB,  0xEB,  0xA2,  0xAB,  0xEB,  0xBE,  0xAA,  0x2F,  0xFE, 	/* 08760 */
+	0x51,  0x48,  0xA2,  0x96,  0x44,  0x47,  0xFC,  0x3B,  0x82,  0xA8,  0x7F,  0xE5,  0xD0,  0x4B,  0xF7,  0xD4, 	/* 08770 */
+	0x5F,  0x45,  0x48,  0x7D,  0x48,  0x62,  0x9B,  0x12,  0x41,  0x24,  0x24,  0x82,  0x48,  0x49,  0x09,  0x20, 	/* 08780 */
+	0x49,  0x02,  0x48,  0x24,  0x81,  0x24,  0x12,  0x41,  0x24,  0x9D,  0x20,  0x22,  0x22,  0x22,  0x22,  0x22, 	/* 08790 */
+	0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x24,  0x22,  0x40,  0x28,  0x02,  0x9E,  0x10,  0x21,  0x22, 	/* 087A0 */
+	0x12,  0x21,  0x22,  0x5B,  0x25,  0x6A,  0x96,  0xA1,  0x22,  0x12,  0x22,  0x22,  0x20,  0x24,  0x02,  0xA1, 	/* 087B0 */
+	0x05,  0x24,  0x52,  0x25,  0x20,  0xA4,  0x0A,  0x4F,  0x48,  0x2A,  0x42,  0xA2,  0x25,  0x22,  0x52,  0x58, 	/* 087C0 */
+	0x08,  0x7F,  0xA3,  0x28,  0x81,  0x50,  0x7F,  0xC4,  0x44,  0x7F,  0xC4,  0x44,  0x7F,  0xC0,  0x40,  0xFF, 	/* 087D0 */
+	0xE1,  0xF0,  0xE4,  0xE0,  0x40,  0xA5,  0x00,  0x00,  0x00,  0x7F,  0xC0,  0x40,  0x04,  0x00,  0x40,  0x04, 	/* 087E0 */
+	0x00,  0x40,  0x04,  0x00,  0x40,  0xFF,  0xE0,  0x00,  0xA6,  0x08,  0x00,  0x80,  0x08,  0x0F,  0xFE,  0x08, 	/* 087F0 */
+	0x00,  0x80,  0x10,  0x01,  0xFC,  0x22,  0x04,  0x20,  0x82,  0x03,  0xFE,  0xA7,  0x00,  0x00,  0xFE,  0xFA, 	/* 08800 */
+	0x02,  0x20,  0x22,  0x02,  0x3E,  0x24,  0x22,  0x02,  0x38,  0x2C,  0x02,  0x00,  0x20,  0x0C,  0xA8,  0x00, 	/* 08810 */
+	0x07,  0xFE,  0x40,  0x04,  0x00,  0x7F,  0xC4,  0x04,  0x40,  0x47,  0xFC,  0x40,  0x04,  0x00,  0x40,  0x07, 	/* 08820 */
+	0xFE,  0xAB,  0x00,  0x07,  0xFC,  0x04,  0x02,  0x48,  0x24,  0x82,  0x48,  0x24,  0x85,  0x54,  0x4E,  0x28, 	/* 08830 */
+	0x42,  0x04,  0x0F,  0xFF,  0xAE,  0x11,  0x00,  0xA0,  0x7F,  0xC0,  0x40,  0x3F,  0x80,  0x40,  0xFF,  0xE2, 	/* 08840 */
+	0x00,  0x3F,  0xC4,  0x20,  0x82,  0x03,  0xFE,  0xB1,  0x00,  0x07,  0xF8,  0x00,  0x80,  0x08,  0x00,  0x87, 	/* 08850 */
+	0xF8,  0x40,  0x04,  0x00,  0x40,  0x44,  0x04,  0x40,  0x43,  0xFC,  0xB2,  0x00,  0x0F,  0xF8,  0x00,  0x84, 	/* 08860 */
+	0x08,  0x40,  0x87,  0xF8,  0x40,  0x04,  0x00,  0x40,  0x04,  0x02,  0x40,  0x23,  0xFE,  0xB3,  0x00,  0x07, 	/* 08870 */
+	0xF8,  0x40,  0x84,  0x08,  0x40,  0x87,  0xF8,  0x40,  0x04,  0x00,  0x40,  0x04,  0x02,  0x40,  0x23,  0xFE, 	/* 08880 */
+	0xB4,  0x00,  0x07,  0xFC,  0x44,  0x44,  0x44,  0x44,  0x47,  0xFC,  0x40,  0x04,  0x00,  0x40,  0x04,  0x02, 	/* 08890 */
+	0x40,  0x23,  0xFE,  0xB5,  0x01,  0xC7,  0xE0,  0x40,  0x07,  0xFE,  0x40,  0x05,  0xF8,  0x52,  0x85,  0x28, 	/* 088A0 */
+	0x5F,  0x89,  0x00,  0x90,  0x20,  0xFE,  0xB7,  0x09,  0x00,  0x90,  0x7F,  0xE0,  0x90,  0xFF,  0xF1,  0x08, 	/* 088B0 */
+	0x1F,  0x82,  0x14,  0xDF,  0x31,  0x00,  0x10,  0x80,  0xF8,  0xBB,  0x04,  0x02,  0x48,  0x15,  0x07,  0xFC, 	/* 088C0 */
+	0x0A,  0x0F,  0xFE,  0x11,  0x03,  0xF8,  0xC1,  0x61,  0xF0,  0x10,  0x40,  0xFC,  0xBD,  0x00,  0x0F,  0xBE, 	/* 088D0 */
+	0x08,  0x2F,  0xBE,  0x82,  0x07,  0x9E,  0x11,  0x07,  0xFC,  0x11,  0x0F,  0xFE,  0x20,  0x8C,  0x04,  0xBE, 	/* 088E0 */
+	0x04,  0x00,  0x40,  0x04,  0x07,  0xFC,  0x44,  0x44,  0x44,  0x44,  0x44,  0x44,  0x45,  0x80,  0x40,  0x04, 	/* 088F0 */
+	0x00,  0x40,  0x82,  0x04,  0x00,  0x40,  0xFF,  0xE0,  0x40,  0x3F,  0xC2,  0x44,  0x24,  0x42,  0x44,  0x24, 	/* 08900 */
+	0x42,  0x58,  0x04,  0x00,  0x40,  0x83,  0x04,  0x00,  0x40,  0xFF,  0xE0,  0xA0,  0x0A,  0x01,  0xFC,  0x32, 	/* 08910 */
+	0x45,  0x24,  0x92,  0x41,  0x24,  0x13,  0x80,  0x20,  0x86,  0x20,  0x02,  0x3C,  0xFA,  0x4A,  0xA4,  0xAA, 	/* 08920 */
+	0x4A,  0xB4,  0xAA,  0xCA,  0xA4,  0xBA,  0x42,  0x45,  0x24,  0x52,  0x83,  0x8B,  0x01,  0x83,  0xE0,  0x22, 	/* 08930 */
+	0x03,  0xFE,  0x21,  0x0F,  0x8A,  0x04,  0x67,  0xFC,  0x44,  0x44,  0x44,  0x45,  0x80,  0x40,  0x8C,  0x18, 	/* 08940 */
+	0x80,  0x70,  0x78,  0x80,  0x80,  0xFF,  0xE1,  0x20,  0x3F,  0xC5,  0x24,  0x92,  0x41,  0x38,  0x12,  0x00, 	/* 08950 */
+	0x20,  0x91,  0x10,  0x0F,  0xFE,  0x25,  0x24,  0x8C,  0x39,  0x4E,  0x62,  0x04,  0x07,  0xFC,  0x44,  0x44, 	/* 08960 */
+	0x44,  0x45,  0x80,  0x40,  0x96,  0x21,  0x02,  0x10,  0xF9,  0x0A,  0x9E,  0xA9,  0x0A,  0x90,  0xA9,  0x0A, 	/* 08970 */
+	0xFE,  0xBC,  0x22,  0x42,  0x24,  0x22,  0x7E,  0x99,  0x21,  0x02,  0x50,  0xFD,  0x0A,  0xFE,  0xA9,  0x0A, 	/* 08980 */
+	0x90,  0xAF,  0xEA,  0x90,  0xBA,  0x82,  0x28,  0x24,  0x42,  0x82,  0x9A,  0x1F,  0x80,  0x08,  0xFF,  0xE0, 	/* 08990 */
+	0x08,  0x1F,  0x8F,  0xFE,  0x84,  0x2B,  0xFA,  0x24,  0x82,  0x48,  0x27,  0x00,  0x40,  0x9B,  0x08,  0x03, 	/* 089A0 */
+	0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x04,  0x07,  0xFC,  0x44,  0x44,  0x44,  0x45,  0x80,  0x40, 	/* 089B0 */
+	0x9D,  0x04,  0x0F,  0xFE,  0x20,  0x81,  0x10,  0xFF,  0xE8,  0x42,  0x7F,  0xC4,  0x44,  0x44,  0x44,  0x58, 	/* 089C0 */
+	0x04,  0x00,  0x40,  0xA5,  0x21,  0x02,  0x10,  0xF7,  0xE9,  0x52,  0xF5,  0x28,  0x52,  0xF5,  0x29,  0x52, 	/* 089D0 */
+	0x95,  0xC9,  0x50,  0xF1,  0x00,  0x10,  0xAB,  0x40,  0x04,  0x7E,  0xF1,  0x09,  0x10,  0xF7,  0xE8,  0x52, 	/* 089E0 */
+	0xF5,  0x29,  0x52,  0x95,  0x29,  0x56,  0xF1,  0x00,  0x10,  0xAD,  0x02,  0x07,  0xFE,  0x48,  0x87,  0xFE, 	/* 089F0 */
+	0x48,  0x84,  0xF8,  0x42,  0x05,  0xFC,  0x52,  0x49,  0x24,  0x93,  0x80,  0x20,  0xAF,  0x24,  0x8F,  0xFE, 	/* 08A00 */
+	0x24,  0x83,  0xF8,  0x00,  0x0F,  0xFE,  0x84,  0x2B,  0xFA,  0x24,  0x82,  0x48,  0x27,  0x00,  0x40,  0xB0, 	/* 08A10 */
+	0x2F,  0x82,  0x08,  0xAF,  0x8A,  0x08,  0xBF,  0xEB,  0x22,  0xAF,  0xE2,  0xA4,  0x2A,  0x44,  0xAC,  0x42, 	/* 08A20 */
+	0x08,  0x20,  0xB3,  0x23,  0xE2,  0x20,  0xFB,  0xCA,  0xA0,  0xAB,  0xCA,  0xA0,  0xAF,  0xEA,  0xB2,  0xBA, 	/* 08A30 */
+	0xC2,  0x28,  0x23,  0x42,  0x63,  0xB6,  0x2A,  0x8F,  0xFE,  0x2A,  0x82,  0xAA,  0x2E,  0x64,  0x00,  0xFF, 	/* 08A40 */
+	0xE8,  0x42,  0xBF,  0xA2,  0x48,  0x25,  0x80,  0x40,  0xB7,  0x21,  0x42,  0x14,  0xFB,  0xEA,  0xA8,  0xAE, 	/* 08A50 */
+	0x8A,  0xBE,  0xAA,  0x8A,  0xA8,  0xBB,  0xE2,  0x28,  0x22,  0x82,  0x3E,  0xB8,  0x24,  0x81,  0x50,  0xFF, 	/* 08A60 */
+	0xE9,  0xF2,  0x91,  0x21,  0xF0,  0x04,  0x03,  0xFC,  0x24,  0x42,  0x44,  0x24,  0x80,  0x40,  0xBD,  0x20, 	/* 08A70 */
+	0x02,  0xFE,  0xF8,  0x2A,  0xFE,  0xA8,  0x2A,  0xFE,  0xAC,  0x4A,  0xFC,  0xBC,  0x42,  0x7C,  0x24,  0x42, 	/* 08A80 */
+	0x7C,  0x80,  0x21,  0x02,  0x1E,  0xF9,  0x0A,  0xFC,  0xAC,  0x4A,  0xFC,  0xAC,  0x4A,  0xFC,  0xBC,  0x42, 	/* 08A90 */
+	0x7C,  0x22,  0x42,  0xC2,  0x83,  0x21,  0x02,  0x7E,  0xF9,  0x2A,  0xFF,  0xAB,  0xCA,  0xA4,  0xAB,  0xCA, 	/* 08AA0 */
+	0x88,  0xBB,  0xC2,  0x28,  0x27,  0xE2,  0x08,  0x84,  0x27,  0xC2,  0x44,  0xFF,  0xCA,  0xC0,  0xAF,  0xEA, 	/* 08AB0 */
+	0xD8,  0xAD,  0x4B,  0xFA,  0xA4,  0x82,  0x7E,  0x28,  0x83,  0x7E,  0x85,  0x27,  0xE2,  0x00,  0xFB,  0xCA, 	/* 08AC0 */
+	0xA4,  0xAB,  0xCA,  0x80,  0xAF,  0xEA,  0xD2,  0xBF,  0xEA,  0x52,  0x25,  0x22,  0x7E,  0x87,  0x20,  0x4F, 	/* 08AD0 */
+	0xFE,  0x22,  0x4F,  0x94,  0x20,  0x4F,  0x8C,  0x04,  0x07,  0xFC,  0x44,  0x44,  0x44,  0x45,  0x80,  0x40, 	/* 08AE0 */
+	0x8C,  0x27,  0xC2,  0x44,  0xFF,  0xCA,  0xC4,  0xAF,  0xCA,  0xD2,  0xAB,  0x4B,  0xFE,  0xA2,  0x82,  0x28, 	/* 08AF0 */
+	0x24,  0xA2,  0x86,  0x8E,  0x2F,  0xE2,  0x82,  0xF3,  0xCA,  0xA4,  0xAB,  0xCA,  0xA4,  0xAB,  0xCA,  0x90, 	/* 08B00 */
+	0xBF,  0xE2,  0x08,  0x22,  0x42,  0xC2,  0x94,  0x27,  0xC2,  0x44,  0xFF,  0xCA,  0xC4,  0xAF,  0xEA,  0xAA, 	/* 08B10 */
+	0xAF,  0xEB,  0x80,  0xA7,  0xC2,  0x48,  0x23,  0x02,  0xCC,  0x95,  0x11,  0x0F,  0xFE,  0x11,  0x03,  0xF8, 	/* 08B20 */
+	0x3F,  0x82,  0x08,  0xFF,  0xE2,  0x48,  0x7F,  0xCA,  0x4A,  0x25,  0x80,  0x40,  0x97,  0x20,  0x02,  0xFE, 	/* 08B30 */
+	0xF9,  0x6A,  0xFE,  0xA9,  0x2A,  0xF6,  0xAD,  0x6A,  0xFA,  0xB9,  0xA2,  0xEA,  0x29,  0x62,  0xFE,  0x9F, 	/* 08B40 */
+	0x22,  0x82,  0xFC,  0x25,  0xAF,  0xE8,  0xAF,  0xEA,  0x88,  0xAE,  0xAA,  0xAA,  0xAE,  0x4B,  0xAC,  0x2F, 	/* 08B50 */
+	0x42,  0x22,  0xA1,  0x20,  0xE2,  0xF2,  0x25,  0x4F,  0xFE,  0xAB,  0x8A,  0xD4,  0xA9,  0x2A,  0xFF,  0xBD, 	/* 08B60 */
+	0x2A,  0x7E,  0x25,  0x22,  0x7E,  0xA2,  0x21,  0x02,  0xFE,  0x22,  0x8F,  0xFE,  0xAD,  0x4A,  0xFC,  0xAD, 	/* 08B70 */
+	0x4A,  0xFC,  0xB9,  0x0A,  0x7C,  0x21,  0x02,  0xFE,  0xA3,  0xAA,  0x07,  0x3E,  0xFE,  0x4A,  0x94,  0xB8, 	/* 08B80 */
+	0x8A,  0xB4,  0x84,  0x23,  0xFC,  0x24,  0x42,  0x44,  0x25,  0x80,  0x40,  0xA4,  0x69,  0x0A,  0x5E,  0xFA, 	/* 08B90 */
+	0x4B,  0xD4,  0xA8,  0x8B,  0x94,  0x8E,  0x20,  0x40,  0x7F,  0xC4,  0x44,  0x45,  0x80,  0x40,  0xB2,  0x00, 	/* 08BA0 */
+	0x07,  0xFC,  0x04,  0x00,  0x40,  0x04,  0x0F,  0xFE,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00, 	/* 08BB0 */
+	0x40,  0xB3,  0x00,  0x07,  0xFC,  0x04,  0x82,  0x48,  0x15,  0x01,  0x40,  0xFF,  0xE0,  0x40,  0x04,  0x00, 	/* 08BC0 */
+	0x40,  0x04,  0x00,  0x40,  0xB4,  0x10,  0x01,  0x00,  0x1F,  0xC2,  0x20,  0x42,  0x09,  0xFC,  0x12,  0x01, 	/* 08BD0 */
+	0x20,  0x7F,  0xE0,  0x20,  0x02,  0x00,  0x20,  0xB5,  0x00,  0x07,  0xBC,  0x20,  0x82,  0x08,  0x20,  0x8F, 	/* 08BE0 */
+	0xFE,  0x20,  0x82,  0x08,  0x20,  0x82,  0x08,  0x20,  0x82,  0x08,  0xB6,  0x20,  0x81,  0x08,  0x11,  0x07, 	/* 08BF0 */
+	0xFC,  0x11,  0x01,  0x10,  0xFF,  0xE1,  0x10,  0x11,  0x02,  0x10,  0x21,  0x04,  0x10,  0xB8,  0x04,  0x00, 	/* 08C00 */
+	0x40,  0x7F,  0xC0,  0x40,  0xFF,  0xE2,  0x08,  0x11,  0x0F,  0xFE,  0x04,  0x07,  0xFC,  0x04,  0x00,  0x40, 	/* 08C10 */
+	0xB9,  0x20,  0x8F,  0x88,  0x21,  0x4F,  0xA2,  0x8F,  0xDF,  0x88,  0x88,  0x8F,  0xFE,  0x20,  0x8F,  0x88, 	/* 08C20 */
+	0x20,  0x82,  0x08,  0xBA,  0x04,  0x00,  0x40,  0x08,  0x07,  0x10,  0x11,  0x00,  0xA0,  0x04,  0x00,  0x88, 	/* 08C30 */
+	0x10,  0x42,  0x3C,  0xFC,  0x20,  0x02,  0xBB,  0x00,  0x02,  0x7E,  0x20,  0x24,  0x02,  0xC8,  0x22,  0x82, 	/* 08C40 */
+	0x10,  0x22,  0x02,  0x28,  0x24,  0x82,  0xF4,  0x20,  0x4C,  0xBC,  0x11,  0x01,  0x10,  0x21,  0x0A,  0xFE, 	/* 08C50 */
+	0x49,  0x22,  0x92,  0x11,  0x22,  0x92,  0x25,  0x23,  0xE2,  0xC6,  0x20,  0x4C,  0xBD,  0x04,  0x08,  0x42, 	/* 08C60 */
+	0x94,  0xA9,  0x4A,  0xA5,  0x2C,  0xE6,  0xB5,  0xA9,  0x4A,  0xEF,  0x68,  0x42,  0xFF,  0xE8,  0x02,  0xBE, 	/* 08C70 */
+	0x24,  0x85,  0x54,  0xA6,  0x85,  0x54,  0xF5,  0xC1,  0x44,  0xFF,  0xE2,  0x44,  0x22,  0x85,  0x12,  0x46, 	/* 08C80 */
+	0xAB,  0x86,  0xBF,  0x02,  0x00,  0x20,  0x3F,  0xE2,  0x00,  0x20,  0x02,  0x00,  0x20,  0x02,  0x00,  0x20, 	/* 08C90 */
+	0x04,  0x00,  0x40,  0x08,  0x00,  0x81,  0x02,  0x03,  0xFE,  0x20,  0x02,  0x00,  0x3F,  0xE2,  0x10,  0x21, 	/* 08CA0 */
+	0x02,  0x10,  0x41,  0x04,  0x10,  0x81,  0x00,  0x30,  0x83,  0x02,  0x03,  0xFE,  0x20,  0x02,  0x20,  0x22, 	/* 08CB0 */
+	0x02,  0x20,  0x22,  0x02,  0x48,  0x44,  0x44,  0xBA,  0xBC,  0x20,  0x02,  0x84,  0x02,  0x00,  0x20,  0x7F, 	/* 08CC0 */
+	0xE4,  0x00,  0x42,  0x04,  0x20,  0x5F,  0xC4,  0x20,  0x42,  0x08,  0x20,  0x9F,  0xE0,  0x00,  0x87,  0x02, 	/* 08CD0 */
+	0x07,  0xFE,  0x40,  0x05,  0x10,  0x51,  0x05,  0x12,  0x5D,  0xC5,  0x10,  0x51,  0x05,  0x12,  0x9D,  0x2B, 	/* 08CE0 */
+	0x0E,  0x8A,  0x02,  0x00,  0x20,  0x7F,  0xE4,  0x00,  0x42,  0x05,  0xFE,  0x42,  0x04,  0x70,  0x4A,  0x85, 	/* 08CF0 */
+	0x24,  0xA2,  0x20,  0x20,  0x8F,  0x02,  0x07,  0xFE,  0x40,  0x05,  0xFC,  0x40,  0x84,  0x70,  0x7F,  0xE4, 	/* 08D00 */
+	0x24,  0x42,  0x88,  0x20,  0x82,  0x00,  0x60,  0x95,  0x04,  0x07,  0xFE,  0x41,  0x85,  0xE0,  0x52,  0x05, 	/* 08D10 */
+	0x20,  0x5F,  0xC5,  0x10,  0x51,  0x07,  0xCA,  0x80,  0x67,  0xF2,  0x96,  0x02,  0x07,  0xFE,  0x50,  0x05, 	/* 08D20 */
+	0xFC,  0x50,  0x46,  0xF4,  0x41,  0x45,  0xF4,  0x50,  0x89,  0x00,  0x90,  0x20,  0xFE,  0x97,  0x02,  0x00, 	/* 08D30 */
+	0x20,  0x3F,  0xE2,  0x20,  0x22,  0x02,  0x3E,  0x22,  0x02,  0x20,  0x5F,  0xC5,  0x04,  0x90,  0x41,  0xFC, 	/* 08D40 */
+	0x9A,  0x02,  0x07,  0xFE,  0x42,  0x05,  0xFC,  0x42,  0x47,  0xFF,  0x42,  0x45,  0xFC,  0x46,  0x04,  0x50, 	/* 08D50 */
+	0x88,  0x83,  0x06,  0x9C,  0x04,  0x07,  0xFE,  0x48,  0x84,  0x88,  0x57,  0xE5,  0x08,  0x74,  0x85,  0x28, 	/* 08D60 */
+	0x52,  0x85,  0x08,  0x90,  0x81,  0x18,  0xA0,  0x02,  0x07,  0xFE,  0x48,  0x44,  0x48,  0x7F,  0xE4,  0x20, 	/* 08D70 */
+	0x4F,  0xC4,  0x20,  0x42,  0x0B,  0xFE,  0x82,  0x00,  0x20,  0xA6,  0x04,  0x07,  0xFE,  0x49,  0x07,  0xFE, 	/* 08D80 */
+	0x49,  0x04,  0xF0,  0x40,  0x05,  0xF8,  0x49,  0x08,  0x60,  0x8D,  0x87,  0x06,  0xA7,  0x02,  0x07,  0xFE, 	/* 08D90 */
+	0x40,  0x05,  0x28,  0x52,  0x85,  0xA8,  0x67,  0x44,  0x22,  0x5F,  0xC8,  0x20,  0x82,  0x03,  0xFE,  0xAB, 	/* 08DA0 */
+	0x02,  0x07,  0xFE,  0x42,  0x07,  0xFE,  0x52,  0x45,  0xFC,  0x52,  0x45,  0xFC,  0x42,  0x0B,  0xFE,  0x82, 	/* 08DB0 */
+	0x00,  0x20,  0xAD,  0x02,  0x07,  0xFE,  0x40,  0x07,  0x86,  0x4B,  0x85,  0x08,  0x7F,  0xE4,  0x88,  0x68, 	/* 08DC0 */
+	0x85,  0xBE,  0xA6,  0x04,  0x1E,  0xB5,  0x02,  0x07,  0xFE,  0x42,  0x07,  0xFE,  0x4A,  0x85,  0xFC,  0x72, 	/* 08DD0 */
+	0x65,  0xFC,  0x52,  0x45,  0xFC,  0x82,  0x28,  0x1E,  0xB6,  0x04,  0x07,  0xFE,  0x40,  0x04,  0x90,  0x7F, 	/* 08DE0 */
+	0xC4,  0x90,  0x49,  0x04,  0xF0,  0x40,  0x05,  0x54,  0x95,  0x2A,  0x52,  0xB7,  0x02,  0x07,  0xFE,  0x42, 	/* 08DF0 */
+	0x05,  0xFC,  0x42,  0x47,  0xFE,  0x42,  0x45,  0xFC,  0x52,  0x48,  0xF8,  0xB2,  0x60,  0x60,  0xB8,  0x02, 	/* 08E00 */
+	0x07,  0xFE,  0x42,  0x05,  0xFC,  0x42,  0x47,  0xFE,  0x52,  0x45,  0xFC,  0x52,  0x45,  0xFC,  0x52,  0x49, 	/* 08E10 */
+	0x2C,  0x81,  0x02,  0x07,  0xFE,  0x40,  0x05,  0xE2,  0x52,  0xA5,  0xEA,  0x52,  0xA5,  0xEA,  0x52,  0xA9, 	/* 08E20 */
+	0xEA,  0x8A,  0x21,  0x06,  0x82,  0x02,  0x07,  0xFE,  0x48,  0x04,  0x9E,  0x7F,  0x24,  0x92,  0x5D,  0xE5, 	/* 08E30 */
+	0xB2,  0x69,  0xEA,  0x92,  0x89,  0x20,  0x9E,  0x83,  0x02,  0x07,  0xFE,  0x5A,  0x46,  0x98,  0x50,  0xA7, 	/* 08E40 */
+	0xFC,  0x45,  0x37,  0xFC,  0x45,  0x04,  0x90,  0x91,  0x26,  0x0E,  0x88,  0x02,  0x07,  0xFE,  0x40,  0x07, 	/* 08E50 */
+	0xFE,  0x48,  0x84,  0xF8,  0x48,  0x84,  0xF8,  0x47,  0x89,  0xC8,  0x87,  0x03,  0x8E,  0x89,  0x02,  0x07, 	/* 08E60 */
+	0xFE,  0x45,  0x05,  0xFE,  0x45,  0x47,  0xFE,  0x45,  0x45,  0xFC,  0x4D,  0x89,  0x54,  0xA5,  0x20,  0x50, 	/* 08E70 */
+	0x8A,  0x04,  0x07,  0xFE,  0x48,  0x05,  0xDC,  0x55,  0x45,  0xD4,  0x55,  0x85,  0xD4,  0x59,  0x29,  0x52, 	/* 08E80 */
+	0x9D,  0xC3,  0x30,  0x8F,  0x04,  0x07,  0xFE,  0x48,  0x05,  0xDC,  0x55,  0x45,  0xD4,  0x55,  0x65,  0xE0, 	/* 08E90 */
+	0x53,  0xE9,  0xD4,  0x90,  0xC0,  0xF2,  0x90,  0x04,  0x07,  0xFE,  0x48,  0x05,  0xFE,  0x55,  0x45,  0xD4, 	/* 08EA0 */
+	0x57,  0xE5,  0xD8,  0x51,  0x89,  0xAA,  0x92,  0xA0,  0xC6,  0x93,  0x04,  0x07,  0xFE,  0x48,  0x07,  0xFE, 	/* 08EB0 */
+	0x5D,  0x25,  0x54,  0x5D,  0x87,  0xD6,  0x49,  0x2B,  0xF2,  0x89,  0xC1,  0x90,  0x96,  0x04,  0x07,  0xFE, 	/* 08EC0 */
+	0x40,  0x07,  0xDE,  0x54,  0xA6,  0xD6,  0x54,  0xA4,  0xB0,  0x72,  0xC9,  0xC0,  0x81,  0x80,  0xE0,  0x9A, 	/* 08ED0 */
+	0x04,  0x07,  0xFE,  0x48,  0x47,  0xE4,  0x4B,  0xE7,  0xC4,  0x66,  0x47,  0xD4,  0x64,  0x49,  0x84,  0x8E, 	/* 08EE0 */
+	0x47,  0x0C,  0x9B,  0x02,  0x07,  0xFE,  0x5F,  0xC5,  0x24,  0x5F,  0xC5,  0x24,  0x7F,  0xE4,  0x20,  0x7F, 	/* 08EF0 */
+	0xEA,  0xFA,  0xC2,  0x03,  0xFE,  0x9D,  0x02,  0x07,  0xFE,  0x54,  0x27,  0xDC,  0x55,  0x05,  0xDF,  0x55, 	/* 08F00 */
+	0x45,  0xD4,  0x55,  0x4B,  0xF4,  0x9A,  0x42,  0x44,  0x9F,  0x04,  0x07,  0xFE,  0x48,  0x07,  0xFE,  0x49, 	/* 08F10 */
+	0x25,  0xD2,  0x5D,  0xE5,  0x52,  0x5D,  0xE4,  0x92,  0xBF,  0x28,  0xA6,  0xA0,  0x02,  0x07,  0xFF,  0x48, 	/* 08F20 */
+	0x86,  0xA8,  0x5C,  0xF4,  0x8A,  0x7F,  0xA6,  0x34,  0x7A,  0x46,  0xAA,  0xBA,  0xA2,  0x71,  0xA1,  0x02, 	/* 08F30 */
+	0x07,  0xFE,  0x48,  0x05,  0xFE,  0x75,  0x45,  0x54,  0x7F,  0xE5,  0x54,  0x55,  0x47,  0xFE,  0x95,  0x42, 	/* 08F40 */
+	0x2A,  0xA2,  0x04,  0x07,  0xFE,  0x5A,  0x84,  0x92,  0x50,  0xC7,  0xBA,  0x4A,  0x87,  0xA6,  0x67,  0xCB, 	/* 08F50 */
+	0x94,  0x89,  0x83,  0x66,  0xA3,  0x02,  0x07,  0xFE,  0x49,  0x07,  0xFC,  0x49,  0x07,  0xFE,  0x52,  0x45, 	/* 08F60 */
+	0xFC,  0x52,  0x49,  0xFC,  0x88,  0x43,  0x02,  0xA8,  0x02,  0x07,  0xFE,  0x50,  0x05,  0xDE,  0x68,  0xA7, 	/* 08F70 */
+	0xF6,  0x6A,  0x47,  0xEE,  0x6B,  0x4B,  0xFE,  0xA2,  0x42,  0x64,  0xA9,  0x04,  0x07,  0xFE,  0x42,  0x07, 	/* 08F80 */
+	0xFE,  0x55,  0x45,  0x74,  0x50,  0x45,  0xFC,  0x42,  0x0B,  0xFE,  0x8A,  0x83,  0x26,  0xAC,  0x04,  0x07, 	/* 08F90 */
+	0xFE,  0x43,  0x85,  0xFE,  0x52,  0x05,  0x7E,  0x52,  0x05,  0x7E,  0x55,  0x49,  0xFE,  0xAA,  0xA5,  0xFF, 	/* 08FA0 */
+	0xB0,  0x04,  0x07,  0xFE,  0x40,  0x87,  0xFE,  0x54,  0x85,  0xFE,  0x56,  0xA5,  0xFE,  0x55,  0x49,  0xDA, 	/* 08FB0 */
+	0xB6,  0xA0,  0x46,  0xB1,  0x02,  0x07,  0xFE,  0x55,  0x26,  0xA4,  0x55,  0xE5,  0xD4,  0x55,  0xE7,  0xF4, 	/* 08FC0 */
+	0x6B,  0xEB,  0xF4,  0xA1,  0x41,  0xDE,  0xB3,  0x04,  0x07,  0xFE,  0x40,  0x87,  0xFE,  0x54,  0x85,  0xFE, 	/* 08FD0 */
+	0x56,  0xA7,  0xFE,  0x45,  0x49,  0x5A,  0xBE,  0xA0,  0x46,  0xB4,  0x00,  0x07,  0x80,  0x10,  0x02,  0x00, 	/* 08FE0 */
+	0x78,  0x00,  0x80,  0x48,  0x04,  0x80,  0x30,  0x03,  0x00,  0x4C,  0x08,  0x3F,  0xB6,  0x00,  0x6F,  0x78, 	/* 08FF0 */
+	0x11,  0x02,  0x10,  0x45,  0xE7,  0x50,  0x15,  0x05,  0x50,  0x25,  0x03,  0xFE,  0x4C,  0x08,  0x3F,  0xB7, 	/* 09000 */
+	0x00,  0xCF,  0x70,  0x11,  0x02,  0x10,  0x41,  0x07,  0xFE,  0x11,  0x05,  0x10,  0x21,  0x03,  0x7C,  0x4C, 	/* 09010 */
+	0x08,  0x3E,  0xB8,  0x01,  0x0E,  0x10,  0x21,  0x04,  0xFE,  0xE9,  0x22,  0x92,  0xAF,  0xEA,  0x92,  0x69, 	/* 09020 */
+	0x22,  0xFE,  0x58,  0x08,  0x7F,  0xBA,  0x01,  0x07,  0x7C,  0x11,  0x42,  0xFE,  0x41,  0x47,  0x7C,  0x11, 	/* 09030 */
+	0x05,  0x7C,  0x21,  0x03,  0x7E,  0x4D,  0x08,  0x3F,  0xBB,  0x00,  0x0E,  0xFE,  0x28,  0x22,  0xBA,  0x4A, 	/* 09040 */
+	0xAE,  0xAA,  0x2B,  0xAA,  0x82,  0x6F,  0xE2,  0x00,  0x58,  0x08,  0x7E,  0xBC,  0x00,  0x0E,  0xFE,  0x22, 	/* 09050 */
+	0x84,  0xFE,  0xEA,  0xA2,  0xAA,  0x2C,  0xEA,  0x82,  0x68,  0x23,  0xFE,  0x4C,  0x08,  0x3F,  0xBE,  0x11, 	/* 09060 */
+	0x01,  0x10,  0x11,  0x01,  0x10,  0xFF,  0xE1,  0x10,  0x11,  0x01,  0x10,  0x11,  0x02,  0x10,  0x21,  0x04, 	/* 09070 */
+	0x10,  0xBF,  0x11,  0x01,  0x10,  0x11,  0x01,  0x10,  0xFF,  0xE1,  0x10,  0x11,  0x01,  0x10,  0x11,  0x01, 	/* 09080 */
+	0x10,  0x11,  0x01,  0xF0,  0x81,  0x08,  0x00,  0xA0,  0x11,  0x87,  0xE4,  0x11,  0x01,  0x10,  0x11,  0x0F, 	/* 09090 */
+	0xFE,  0x11,  0x01,  0x10,  0x21,  0x04,  0x10,  0x83,  0x04,  0x0F,  0xFE,  0x09,  0x01,  0x08,  0x7F,  0x41, 	/* 090A0 */
+	0x14,  0x11,  0x0F,  0xFE,  0x11,  0x01,  0x10,  0x21,  0x04,  0x10,  0x84,  0x00,  0x07,  0xFC,  0x04,  0x03, 	/* 090B0 */
+	0xF8,  0x04,  0x0F,  0xFE,  0x11,  0x01,  0x10,  0xFF,  0xE1,  0x10,  0x21,  0x04,  0x10,  0x89,  0x51,  0x07, 	/* 090C0 */
+	0x10,  0x1F,  0xEF,  0x10,  0x51,  0x09,  0x7C,  0x10,  0x01,  0x10,  0xFF,  0xF1,  0x10,  0x11,  0x02,  0x10, 	/* 090D0 */
+	0x8A,  0xA9,  0x07,  0x10,  0xFB,  0xEA,  0xA4,  0xFD,  0x8A,  0x94,  0x9A,  0x21,  0x10,  0xFF,  0xE1,  0x10, 	/* 090E0 */
+	0x11,  0x02,  0x10,  0x8B,  0x05,  0x00,  0x48,  0x04,  0x00,  0x7E,  0xFC,  0x00,  0x40,  0x04,  0x00,  0x20, 	/* 090F0 */
+	0x02,  0x00,  0x12,  0x00,  0xA0,  0x06,  0x8C,  0x02,  0x80,  0x24,  0x02,  0x0F,  0xFE,  0x02,  0x00,  0x20, 	/* 09100 */
+	0x01,  0x0F,  0xD0,  0x00,  0x80,  0x0A,  0x00,  0x60,  0x02,  0x8D,  0x02,  0x80,  0x24,  0x02,  0x0F,  0xFE, 	/* 09110 */
+	0x02,  0x00,  0x20,  0x7D,  0x00,  0x10,  0x00,  0x81,  0xCA,  0xE0,  0x60,  0x02,  0x8F,  0x02,  0x00,  0x28, 	/* 09120 */
+	0x02,  0x4F,  0xFE,  0x02,  0x07,  0xE0,  0x12,  0x01,  0x10,  0x11,  0x01,  0xD4,  0xE0,  0xC0,  0x04,  0x90, 	/* 09130 */
+	0x02,  0x87,  0xA4,  0x02,  0x0F,  0xFE,  0x02,  0x00,  0x20,  0x7A,  0x00,  0x10,  0x0D,  0x03,  0x0A,  0xC0, 	/* 09140 */
+	0x60,  0x02,  0x91,  0x10,  0xCD,  0x0A,  0x2F,  0xE5,  0x08,  0x80,  0x82,  0xF8,  0xF2,  0x82,  0x24,  0x72, 	/* 09150 */
+	0x46,  0x3A,  0xAE,  0x22,  0x01,  0x93,  0x1F,  0x80,  0x08,  0x00,  0x83,  0xF8,  0x20,  0x02,  0x00,  0x3F, 	/* 09160 */
+	0xC0,  0x04,  0x00,  0x40,  0x04,  0x00,  0x80,  0x70,  0x94,  0x00,  0x07,  0xFC,  0x04,  0x40,  0x44,  0x7F, 	/* 09170 */
+	0xC4,  0x40,  0x7F,  0xE0,  0x42,  0x04,  0x20,  0x42,  0x04,  0xC0,  0x40,  0x95,  0x00,  0x47,  0xC4,  0x04, 	/* 09180 */
+	0x40,  0x44,  0x7C,  0x44,  0x04,  0x7C,  0x40,  0x44,  0x04,  0x40,  0x44,  0x04,  0x43,  0x84,  0x96,  0x00, 	/* 09190 */
+	0x03,  0xF0,  0x01,  0x00,  0x10,  0x3F,  0x02,  0x00,  0x3F,  0x82,  0x08,  0x00,  0x80,  0x08,  0x03,  0x0F, 	/* 091A0 */
+	0xFE,  0x97,  0x12,  0x0F,  0xFC,  0x12,  0x41,  0x24,  0xFF,  0xC9,  0x20,  0xFF,  0xE1,  0x22,  0x12,  0x21, 	/* 091B0 */
+	0x22,  0x22,  0xC4,  0x20,  0x98,  0x01,  0x0F,  0x10,  0x11,  0x01,  0x10,  0xF1,  0x08,  0x10,  0xF2,  0x01, 	/* 091C0 */
+	0x28,  0x12,  0x41,  0x4C,  0x2F,  0x2C,  0x02,  0x9B,  0x01,  0x0F,  0x50,  0x15,  0x01,  0x5C,  0xF7,  0x49, 	/* 091D0 */
+	0xD4,  0xF5,  0x41,  0x5C,  0x15,  0x01,  0x40,  0x24,  0x2C,  0x3E,  0x9F,  0x11,  0x00,  0xA0,  0x7F,  0xC0, 	/* 091E0 */
+	0x44,  0x3F,  0xC4,  0x40,  0x7F,  0xE0,  0x42,  0x0C,  0x23,  0x42,  0xC4,  0xC0,  0x40,  0xA5,  0x02,  0x0F, 	/* 091F0 */
+	0x20,  0x13,  0xE1,  0x50,  0xF9,  0x08,  0x10,  0xF5,  0x41,  0x52,  0x15,  0x21,  0x92,  0x21,  0x0C,  0x30, 	/* 09200 */
+	0xA6,  0x01,  0x0F,  0x10,  0x1F,  0xE1,  0x10,  0xF1,  0x48,  0xA4,  0xF4,  0x81,  0x28,  0x11,  0x81,  0x24, 	/* 09210 */
+	0x2F,  0xAC,  0x02,  0xA7,  0x00,  0x6F,  0x78,  0x15,  0x41,  0x54,  0xF5,  0x48,  0x54,  0xF5,  0x41,  0x54, 	/* 09220 */
+	0x15,  0xA1,  0x96,  0x29,  0xED,  0x65,  0xA9,  0x20,  0x0F,  0xFE,  0x4A,  0x43,  0x18,  0x2A,  0x4D,  0xF2, 	/* 09230 */
+	0x01,  0x03,  0xF0,  0x20,  0x07,  0xF8,  0x40,  0x80,  0x70,  0xAD,  0x00,  0x0F,  0xFE,  0x14,  0x41,  0x44, 	/* 09240 */
+	0xF7,  0xC8,  0x44,  0xF7,  0xC1,  0x44,  0x14,  0x41,  0x7C,  0x2C,  0x4C,  0x04,  0xAF,  0x04,  0x0F,  0xFE, 	/* 09250 */
+	0x09,  0x02,  0x94,  0x51,  0x29,  0xFA,  0x00,  0x83,  0xF8,  0x20,  0x07,  0xFC,  0x40,  0x40,  0x18,  0xB1, 	/* 09260 */
+	0x00,  0x0F,  0xBE,  0x08,  0x2F,  0xBE,  0x82,  0x0F,  0xBE,  0x08,  0x24,  0x92,  0x38,  0xEC,  0xB2,  0x08, 	/* 09270 */
+	0x23,  0x0C,  0xB5,  0x00,  0x0F,  0x7C,  0x14,  0x01,  0x7C,  0xF4,  0x08,  0x7C,  0xF4,  0x01,  0xFE,  0x15, 	/* 09280 */
+	0x41,  0x48,  0x27,  0x4D,  0x82,  0xB7,  0x02,  0x0F,  0x28,  0x14,  0x41,  0xFE,  0xF1,  0x28,  0x7C,  0xF5, 	/* 09290 */
+	0x41,  0x7C,  0x15,  0x41,  0x12,  0x21,  0xEC,  0xE2,  0xB8,  0x00,  0x0E,  0xEE,  0x2A,  0xA2,  0xAA,  0xEE, 	/* 092A0 */
+	0xE8,  0xAA,  0xEA,  0xA2,  0xEE,  0x2A,  0xA2,  0xAA,  0x2B,  0x2D,  0x66,  0xBC,  0x00,  0x0F,  0xEE,  0x24, 	/* 092B0 */
+	0x22,  0xE2,  0xEA,  0xE8,  0xA8,  0xEE,  0xEA,  0xAA,  0x2A,  0x22,  0xA2,  0x2E,  0x2C,  0x0C,  0xBE,  0x09, 	/* 092C0 */
+	0x2E,  0x54,  0x2F,  0xC2,  0x94,  0xEF,  0xC8,  0x94,  0xEF,  0xC2,  0x10,  0x3F,  0xE2,  0x10,  0x21,  0x0C, 	/* 092D0 */
+	0x10,  0x81,  0x00,  0x0F,  0xFE,  0x17,  0x41,  0x54,  0xF7,  0x48,  0x0C,  0xFF,  0xE1,  0x04,  0x17,  0x41, 	/* 092E0 */
+	0x54,  0x17,  0x46,  0x0C,  0x88,  0x07,  0x7F,  0x55,  0x17,  0x71,  0x3E,  0xF2,  0xA8,  0x3E,  0xF2,  0xA1, 	/* 092F0 */
+	0x3E,  0x10,  0x81,  0xFF,  0x10,  0x86,  0x08,  0x8A,  0x00,  0x0F,  0xFE,  0x29,  0x42,  0xFC,  0xE9,  0x48, 	/* 09300 */
+	0xFC,  0xFF,  0xE2,  0x94,  0x2F,  0xC2,  0x94,  0x2F,  0xCD,  0xFE,  0x8C,  0x00,  0x0F,  0xFE,  0x26,  0x82, 	/* 09310 */
+	0xA4,  0xFF,  0xE9,  0xB6,  0x96,  0xAF,  0xB6,  0x32,  0x23,  0xB6,  0x36,  0xAD,  0xB6,  0x8E,  0x44,  0x8B, 	/* 09320 */
+	0xF4,  0x50,  0xAF,  0xFE,  0x6B,  0xCA,  0xEA,  0x01,  0x01,  0xF0,  0x20,  0x03,  0xF8,  0x00,  0x80,  0x30, 	/* 09330 */
+	0x91,  0x08,  0x00,  0x80,  0x08,  0x00,  0xF8,  0x08,  0x81,  0x08,  0x11,  0x03,  0xF0,  0x21,  0x00,  0x20, 	/* 09340 */
+	0x02,  0x0F,  0xFF,  0x93,  0x04,  0x02,  0x48,  0x14,  0x81,  0x50,  0x7F,  0xC0,  0x04,  0x00,  0x43,  0xFC, 	/* 09350 */
+	0x00,  0x40,  0x04,  0x7F,  0xC0,  0x04,  0x96,  0x0F,  0x81,  0x10,  0x3E,  0x00,  0x20,  0xFF,  0xE0,  0xC0, 	/* 09360 */
+	0x32,  0x2C,  0xDC,  0x33,  0x80,  0xD4,  0x71,  0x20,  0x60,  0x97,  0x21,  0x0F,  0x7C,  0x21,  0x0F,  0x7C, 	/* 09370 */
+	0x21,  0x0F,  0x7C,  0x21,  0x07,  0xF8,  0x00,  0x8F,  0xFE,  0x00,  0x87,  0xF8,  0x99,  0x0F,  0x81,  0x10, 	/* 09380 */
+	0xFF,  0xE0,  0x00,  0xFF,  0xEA,  0x4A,  0x3F,  0x82,  0x48,  0xFF,  0xE1,  0xF0,  0xE4,  0xE0,  0x40,  0x9C, 	/* 09390 */
+	0x0F,  0x01,  0x20,  0xFF,  0xEA,  0x94,  0x72,  0x2F,  0xFD,  0x71,  0x4A,  0xAC,  0x11,  0x0F,  0xFE,  0x11, 	/* 093A0 */
+	0x02,  0x10,  0x9D,  0x1F,  0x02,  0x20,  0xFF,  0xEA,  0x48,  0x69,  0x4F,  0xCA,  0x73,  0xEA,  0x9C,  0x12, 	/* 093B0 */
+	0xAF,  0xFE,  0x11,  0x02,  0x10,  0xA1,  0x02,  0x00,  0x20,  0x04,  0x80,  0x88,  0x11,  0x02,  0x24,  0x04, 	/* 093C0 */
+	0x40,  0x88,  0x01,  0x00,  0x20,  0x0C,  0x03,  0x00,  0xA2,  0x00,  0x8F,  0xC8,  0x49,  0x04,  0x94,  0x4A, 	/* 093D0 */
+	0x4F,  0xC8,  0x48,  0x84,  0x92,  0x48,  0x24,  0x84,  0x48,  0x88,  0x90,  0xA6,  0x04,  0x07,  0xFE,  0x10, 	/* 093E0 */
+	0x80,  0x90,  0x3F,  0xE2,  0x10,  0x26,  0x43,  0x88,  0x27,  0x25,  0x84,  0x43,  0x8B,  0xC0,  0xA9,  0x18, 	/* 093F0 */
+	0x8E,  0x48,  0xA5,  0x05,  0x94,  0x52,  0x42,  0x08,  0xFC,  0x83,  0x12,  0x68,  0x26,  0x04,  0xA0,  0x82, 	/* 09400 */
+	0x10,  0xAA,  0x20,  0x83,  0xC8,  0x21,  0x0F,  0xD4,  0xAE,  0x4F,  0x08,  0xA4,  0xA9,  0xD2,  0xA8,  0x4A, 	/* 09410 */
+	0x85,  0xA8,  0x94,  0x7F,  0xAB,  0x00,  0x87,  0xC8,  0x55,  0x07,  0xD4,  0x56,  0x47,  0xC8,  0x44,  0x87, 	/* 09420 */
+	0xD2,  0x6C,  0x27,  0xC4,  0x44,  0x88,  0xD0,  0xAC,  0x24,  0x42,  0x44,  0x24,  0x8F,  0xFA,  0x25,  0x23, 	/* 09430 */
+	0x64,  0x6D,  0x46,  0xCA,  0xB4,  0x2A,  0x44,  0x24,  0x42,  0x48,  0xAD,  0x10,  0x4F,  0xE4,  0x10,  0x87, 	/* 09440 */
+	0xD0,  0x02,  0x47,  0xC4,  0x44,  0x87,  0xD2,  0x44,  0x22,  0x84,  0x1C,  0x8E,  0x10,  0xB0,  0x10,  0x8F, 	/* 09450 */
+	0xE8,  0x45,  0x02,  0x94,  0xFE,  0x44,  0x48,  0x7C,  0x84,  0x52,  0x7E,  0x21,  0x04,  0xFC,  0x81,  0x10, 	/* 09460 */
+	0xB1,  0x7C,  0x84,  0x48,  0x7D,  0x04,  0x64,  0x7C,  0x41,  0x08,  0xFE,  0x84,  0x52,  0x7C,  0x25,  0x44, 	/* 09470 */
+	0x92,  0x83,  0x10,  0xB3,  0x02,  0x00,  0x20,  0x05,  0x00,  0x90,  0x12,  0x00,  0x20,  0x04,  0x00,  0xC0, 	/* 09480 */
+	0x14,  0x00,  0x40,  0x04,  0x00,  0x40,  0xB7,  0x22,  0x02,  0x20,  0x5F,  0xE9,  0x20,  0x22,  0x02,  0x3C, 	/* 09490 */
+	0x62,  0x4A,  0x24,  0x24,  0x42,  0x44,  0x28,  0x43,  0x18,  0xB9,  0x27,  0x82,  0x48,  0x54,  0xA9,  0x4A, 	/* 094A0 */
+	0x28,  0x63,  0xF8,  0x64,  0x8A,  0x48,  0x23,  0x02,  0x30,  0x24,  0x83,  0x86,  0xBC,  0x21,  0x02,  0x10, 	/* 094B0 */
+	0x4F,  0xEA,  0x92,  0x29,  0x44,  0xFC,  0xC8,  0x44,  0xA8,  0x4A,  0x85,  0x90,  0x56,  0x85,  0x86,  0xBF, 	/* 094C0 */
+	0x25,  0x02,  0x50,  0x5F,  0xCA,  0x54,  0x2F,  0xC5,  0x50,  0xDF,  0xE4,  0x52,  0x45,  0x24,  0x96,  0x49, 	/* 094D0 */
+	0x05,  0x10,  0x80,  0x22,  0x02,  0x10,  0x5F,  0xE5,  0x10,  0x91,  0x02,  0x10,  0x27,  0xC6,  0x10,  0xA1, 	/* 094E0 */
+	0x02,  0x10,  0x21,  0x02,  0xFE,  0x81,  0x20,  0x02,  0xFE,  0x41,  0x05,  0x10,  0x95,  0x02,  0x5E,  0x25, 	/* 094F0 */
+	0x06,  0x50,  0xA5,  0x02,  0x50,  0x25,  0x03,  0xFE,  0x82,  0x27,  0xC2,  0x44,  0x54,  0x49,  0x44,  0x27, 	/* 09500 */
+	0xC2,  0x44,  0x64,  0x4A,  0x7C,  0x24,  0x42,  0x44,  0x24,  0x43,  0xFF,  0x83,  0x21,  0x02,  0x90,  0x49, 	/* 09510 */
+	0x0A,  0xFE,  0x29,  0x05,  0x10,  0xE1,  0x04,  0xFC,  0x41,  0x04,  0x10,  0x41,  0x05,  0xFE,  0x84,  0x20, 	/* 09520 */
+	0x02,  0xFC,  0x50,  0x49,  0x68,  0x21,  0x02,  0x28,  0x6D,  0x6A,  0x10,  0x2F,  0xC2,  0x10,  0x21,  0x03, 	/* 09530 */
+	0xFE,  0x85,  0x22,  0x02,  0xFC,  0x52,  0x09,  0x20,  0x3F,  0xE2,  0x08,  0x7F,  0xEA,  0x88,  0x24,  0x82, 	/* 09540 */
+	0x08,  0x20,  0x82,  0x18,  0x87,  0x24,  0x02,  0x40,  0x47,  0xEA,  0x82,  0x2F,  0xA5,  0x4A,  0xC7,  0xA4, 	/* 09550 */
+	0x4A,  0x44,  0xA4,  0x7A,  0x40,  0x24,  0x0C,  0x88,  0x20,  0x02,  0x7C,  0x54,  0x45,  0x7C,  0x94,  0x42, 	/* 09560 */
+	0x7C,  0x65,  0x2A,  0x52,  0x24,  0xC2,  0x48,  0x27,  0x42,  0xC2,  0x8A,  0x20,  0x02,  0xFE,  0x48,  0x24, 	/* 09570 */
+	0xBA,  0xAA,  0xA2,  0xAA,  0x4A,  0xAC,  0xAA,  0x4B,  0xA4,  0x82,  0x4F,  0xE4,  0x80,  0x8B,  0x22,  0x02, 	/* 09580 */
+	0xFC,  0x42,  0x4B,  0xFE,  0x22,  0x44,  0xFC,  0x42,  0x0C,  0xFC,  0x42,  0x05,  0xFE,  0x42,  0x04,  0x20, 	/* 09590 */
+	0x8C,  0x22,  0x02,  0x48,  0x49,  0x0A,  0x68,  0x24,  0x45,  0xFA,  0xC2,  0x24,  0x78,  0x5C,  0x84,  0x30, 	/* 095A0 */
+	0x46,  0x87,  0x86,  0x90,  0x22,  0x02,  0x30,  0x44,  0x8A,  0x84,  0x3F,  0xA4,  0x20,  0xDF,  0xE4,  0x20, 	/* 095B0 */
+	0x4A,  0x84,  0xA4,  0x52,  0x24,  0x60,  0x91,  0x20,  0x02,  0xFE,  0x45,  0x4A,  0x54,  0x2A,  0x84,  0x54, 	/* 095C0 */
+	0xC5,  0x44,  0x00,  0x4F,  0xE4,  0x10,  0x41,  0x05,  0xFE,  0x92,  0x22,  0x02,  0x20,  0x4F,  0xCA,  0x20, 	/* 095D0 */
+	0x22,  0x05,  0xFE,  0xC2,  0x04,  0xA0,  0x4B,  0xC5,  0x60,  0x63,  0x04,  0x0E,  0x93,  0x24,  0x42,  0x24, 	/* 095E0 */
+	0x42,  0x8A,  0xFE,  0x21,  0x04,  0x90,  0x49,  0xEC,  0x90,  0x49,  0x05,  0x50,  0x53,  0x06,  0x0E,  0x97, 	/* 095F0 */
+	0x20,  0x02,  0xF8,  0x48,  0x8A,  0xF8,  0x28,  0x85,  0xFE,  0xC0,  0x87,  0xFE,  0x48,  0x84,  0x48,  0x40, 	/* 09600 */
+	0x84,  0x18,  0x98,  0x25,  0x02,  0x50,  0x5D,  0xEA,  0x50,  0x25,  0x05,  0xDC,  0xC5,  0x04,  0x50,  0x7D, 	/* 09610 */
+	0xE4,  0x90,  0x49,  0x05,  0x10,  0x99,  0x21,  0x02,  0x90,  0x49,  0xEA,  0x90,  0x29,  0x05,  0xFE,  0xC1, 	/* 09620 */
+	0x04,  0x90,  0x49,  0xE4,  0xD0,  0x53,  0x06,  0x0E,  0x9E,  0x28,  0x82,  0x88,  0x48,  0x8B,  0x54,  0x22, 	/* 09630 */
+	0x24,  0x00,  0xC2,  0x05,  0x3C,  0x52,  0x05,  0xA0,  0x56,  0x06,  0x1E,  0xA0,  0x22,  0x02,  0x20,  0x5F, 	/* 09640 */
+	0xEA,  0x20,  0x2A,  0x84,  0xA8,  0xD7,  0x46,  0x32,  0x46,  0x84,  0xA4,  0x52,  0x24,  0x20,  0xA1,  0x50, 	/* 09650 */
+	0x05,  0x0E,  0x9F,  0xAA,  0x4A,  0x3F,  0xA4,  0x4A,  0xD7,  0xA5,  0x4A,  0x54,  0xA5,  0x7C,  0x7C,  0x84, 	/* 09660 */
+	0x08,  0xA8,  0x22,  0x02,  0xFC,  0x48,  0x4A,  0xFC,  0x28,  0x44,  0xFC,  0x40,  0x0D,  0xFE,  0x42,  0x04, 	/* 09670 */
+	0xFC,  0x42,  0x05,  0xFE,  0xA9,  0x24,  0x02,  0x7E,  0x54,  0x49,  0xFC,  0x24,  0x42,  0x7C,  0x62,  0x0A, 	/* 09680 */
+	0x3C,  0x2C,  0x82,  0x30,  0x25,  0x83,  0x86,  0xAA,  0x21,  0xC2,  0xE0,  0x49,  0x0A,  0xFE,  0x29,  0x04, 	/* 09690 */
+	0xFC,  0x4C,  0x4C,  0xFC,  0x54,  0x45,  0x7C,  0x64,  0x44,  0x7C,  0xAD,  0x21,  0xC2,  0x24,  0x4D,  0x4A, 	/* 096A0 */
+	0x48,  0x23,  0x04,  0xFC,  0xD2,  0x07,  0xFE,  0x42,  0x05,  0x24,  0x52,  0x45,  0xFC,  0xAE,  0x24,  0x42, 	/* 096B0 */
+	0x44,  0x55,  0x49,  0x57,  0x3F,  0xA4,  0x0A,  0xDF,  0xA4,  0xA4,  0x4A,  0x44,  0xAA,  0x51,  0x24,  0x21, 	/* 096C0 */
+	0xB3,  0x21,  0x02,  0xFE,  0x51,  0x05,  0xFE,  0xAA,  0xA2,  0xAA,  0x2F,  0xE6,  0x20,  0xA5,  0x42,  0xD2, 	/* 096D0 */
+	0x34,  0x62,  0x3C,  0xB4,  0x25,  0x03,  0x50,  0x55,  0xE9,  0xF4,  0x22,  0x45,  0xF4,  0xC5,  0x45,  0xE8, 	/* 096E0 */
+	0x44,  0x84,  0x74,  0x59,  0x44,  0x22,  0xB9,  0x24,  0x83,  0xE8,  0x4A,  0xFB,  0xF2,  0x21,  0x25,  0xEA, 	/* 096F0 */
+	0xD2,  0xA5,  0xE4,  0x52,  0x45,  0xEA,  0x52,  0xA5,  0x71,  0xBC,  0x28,  0x83,  0xE8,  0x52,  0xFB,  0xEA, 	/* 09700 */
+	0x32,  0xA5,  0xF2,  0xC9,  0x25,  0xEC,  0x48,  0x44,  0xE4,  0x52,  0xA6,  0x51,  0xBD,  0x15,  0x45,  0x54, 	/* 09710 */
+	0x5F,  0x78,  0x4A,  0x2B,  0x22,  0x4A,  0x4A,  0xAD,  0xF4,  0x44,  0x45,  0x6C,  0x65,  0x24,  0x61,  0x83, 	/* 09720 */
+	0x08,  0x00,  0x40,  0x02,  0x00,  0xA0,  0x08,  0x02,  0x84,  0x28,  0x24,  0x82,  0x48,  0x28,  0x88,  0x08, 	/* 09730 */
+	0x80,  0x78,  0x85,  0x08,  0x00,  0x48,  0x04,  0x81,  0x08,  0x11,  0x05,  0x14,  0x52,  0x25,  0x42,  0x98, 	/* 09740 */
+	0x01,  0x08,  0x30,  0x8C,  0xF8,  0x8C,  0x00,  0x03,  0xF8,  0x00,  0x83,  0xF8,  0x20,  0x02,  0x04,  0x1F, 	/* 09750 */
+	0xC0,  0x40,  0x52,  0x45,  0x22,  0x90,  0x90,  0xF8,  0x8D,  0x00,  0x07,  0xFC,  0x04,  0x41,  0x44,  0x08, 	/* 09760 */
+	0x43,  0x44,  0xC1,  0x81,  0x80,  0x54,  0x45,  0x12,  0x91,  0x20,  0xF0,  0x96,  0x20,  0x82,  0x08,  0x20, 	/* 09770 */
+	0x82,  0xFE,  0x70,  0x87,  0x48,  0xA2,  0x82,  0x28,  0x20,  0x82,  0x08,  0x20,  0x82,  0x18,  0x97,  0x04, 	/* 09780 */
+	0x00,  0x40,  0xFF,  0xE0,  0x40,  0x04,  0x07,  0xFC,  0x00,  0x01,  0x40,  0x52,  0x45,  0x2A,  0x90,  0xA0, 	/* 09790 */
+	0xF8,  0x98,  0x04,  0x00,  0x40,  0xFF,  0xE2,  0x00,  0x20,  0x01,  0xF8,  0x04,  0x01,  0x20,  0x52,  0x45, 	/* 097A0 */
+	0x02,  0x90,  0xA0,  0xF8,  0x99,  0x21,  0x02,  0x10,  0x21,  0x02,  0xFE,  0x74,  0x06,  0xC0,  0xA4,  0x02, 	/* 097B0 */
+	0x40,  0x24,  0x02,  0x40,  0x24,  0x02,  0x3E,  0x9C,  0x04,  0x00,  0x40,  0x7F,  0xE4,  0x20,  0x41,  0x04, 	/* 097C0 */
+	0x50,  0x54,  0x45,  0x42,  0x54,  0x2A,  0x48,  0xA4,  0x80,  0x38,  0x9D,  0x01,  0x87,  0xE0,  0x08,  0x0F, 	/* 097D0 */
+	0xFE,  0x0A,  0x01,  0x10,  0x24,  0x8C,  0x46,  0x26,  0x82,  0x54,  0x45,  0x40,  0xC0,  0xA0,  0x04,  0x00, 	/* 097E0 */
+	0x40,  0x7F,  0xC4,  0x44,  0x44,  0x47,  0xFC,  0x04,  0x01,  0x40,  0x52,  0x45,  0x22,  0x90,  0xA0,  0xF8, 	/* 097F0 */
+	0xA4,  0x24,  0x02,  0x40,  0x27,  0xC2,  0x90,  0x71,  0x07,  0x10,  0xAF,  0xE2,  0x10,  0x21,  0x02,  0x10, 	/* 09800 */
+	0x21,  0x02,  0x10,  0xAB,  0x22,  0x02,  0x20,  0x2F,  0xC2,  0x24,  0x72,  0x46,  0xFE,  0xA2,  0x02,  0x30, 	/* 09810 */
+	0x23,  0x02,  0x48,  0x28,  0x43,  0x02,  0xB0,  0x22,  0x02,  0x20,  0x2F,  0x82,  0x2A,  0x74,  0xA6,  0x86, 	/* 09820 */
+	0xA1,  0x02,  0xFE,  0x21,  0x02,  0x10,  0x21,  0x02,  0x10,  0xB1,  0x22,  0x02,  0x20,  0x22,  0x06,  0xFE, 	/* 09830 */
+	0x7A,  0x26,  0xA2,  0xA3,  0x02,  0x30,  0x23,  0x02,  0x52,  0x25,  0x22,  0x8E,  0xB5,  0x04,  0x00,  0xA0, 	/* 09840 */
+	0x11,  0x02,  0xE8,  0xC0,  0x63,  0xF8,  0x01,  0x00,  0x60,  0x52,  0x45,  0x22,  0x90,  0xA0,  0xF8,  0xB8, 	/* 09850 */
+	0x20,  0x02,  0xF8,  0x24,  0x82,  0x48,  0x74,  0x86,  0xFE,  0xA4,  0x82,  0x48,  0x24,  0x82,  0x48,  0x24, 	/* 09860 */
+	0x83,  0xFE,  0xBB,  0x20,  0x62,  0x78,  0x24,  0x02,  0x40,  0x77,  0xE6,  0xC8,  0xA4,  0x82,  0x48,  0x24, 	/* 09870 */
+	0x82,  0x88,  0x28,  0x83,  0x08,  0xBD,  0x10,  0x01,  0x00,  0x3F,  0xC4,  0x94,  0x92,  0x42,  0x44,  0x05, 	/* 09880 */
+	0x81,  0x20,  0x52,  0x45,  0x02,  0x90,  0xA0,  0xF8,  0xBF,  0x0B,  0x01,  0x08,  0x20,  0x4D,  0xFB,  0x04, 	/* 09890 */
+	0x80,  0x88,  0x33,  0x00,  0x00,  0x14,  0x05,  0x24,  0x90,  0xA0,  0xF8,  0x8E,  0x10,  0x01,  0x00,  0x3F, 	/* 098A0 */
+	0xE2,  0x40,  0x47,  0xC8,  0x40,  0x07,  0xC0,  0x40,  0x54,  0x45,  0x22,  0x90,  0xA0,  0xF8,  0x8F,  0x21, 	/* 098B0 */
+	0x02,  0x10,  0x2F,  0xC2,  0x94,  0x79,  0x46,  0x94,  0xBF,  0xE2,  0x10,  0x21,  0x02,  0x28,  0x24,  0x43, 	/* 098C0 */
+	0x82,  0x90,  0x24,  0x02,  0x40,  0x37,  0xE2,  0x82,  0x68,  0x27,  0x7A,  0xA4,  0xA2,  0x4A,  0x27,  0xA2, 	/* 098D0 */
+	0x02,  0x20,  0x22,  0x0C,  0x92,  0x10,  0x0F,  0xBC,  0x28,  0x44,  0xA8,  0x31,  0x02,  0xA8,  0xC4,  0x41, 	/* 098E0 */
+	0x40,  0x52,  0x45,  0x02,  0x90,  0xA0,  0xF8,  0x95,  0x20,  0x82,  0x10,  0x27,  0xE3,  0x42,  0x6C,  0x26, 	/* 098F0 */
+	0x42,  0xA7,  0xE2,  0x42,  0x24,  0x22,  0x42,  0x27,  0xE2,  0x00,  0x96,  0x22,  0x02,  0x20,  0x2F,  0xE2, 	/* 09900 */
+	0x20,  0x75,  0x06,  0x7E,  0xAD,  0x22,  0xD2,  0x35,  0x22,  0x5C,  0x25,  0x02,  0x10,  0x99,  0x21,  0x02, 	/* 09910 */
+	0x10,  0x21,  0x02,  0xFE,  0x71,  0x06,  0x90,  0xA1,  0x02,  0x7C,  0x24,  0x42,  0x44,  0x24,  0x42,  0x7C, 	/* 09920 */
+	0x9B,  0x20,  0x02,  0x7C,  0x24,  0x43,  0x44,  0x6C,  0x46,  0x7C,  0xA4,  0x42,  0x44,  0x24,  0x42,  0x7C, 	/* 09930 */
+	0x20,  0x02,  0xFF,  0x9C,  0x21,  0x02,  0x10,  0x22,  0x86,  0x7C,  0x68,  0x2B,  0xFD,  0xA2,  0x42,  0x24, 	/* 09940 */
+	0x22,  0x42,  0x38,  0x22,  0x02,  0x20,  0x9D,  0x00,  0x03,  0xFC,  0x24,  0x43,  0xFC,  0x24,  0x42,  0x44, 	/* 09950 */
+	0x3F,  0xC1,  0x40,  0x52,  0x45,  0x2A,  0x90,  0xA0,  0xF8,  0xA0,  0x08,  0x01,  0x10,  0x7E,  0xC0,  0x02, 	/* 09960 */
+	0x3F,  0x82,  0x08,  0x20,  0x83,  0xF8,  0x48,  0x05,  0x44,  0x91,  0x20,  0xF0,  0xA1,  0x22,  0x02,  0x20, 	/* 09970 */
+	0x22,  0x82,  0x24,  0x74,  0xC6,  0x72,  0xB8,  0x22,  0x7C,  0x24,  0x42,  0x44,  0x24,  0x42,  0x7C,  0xA5, 	/* 09980 */
+	0x10,  0x01,  0xF0,  0x22,  0x07,  0xF8,  0x00,  0x81,  0xF8,  0x00,  0x87,  0xF8,  0x44,  0x05,  0x24,  0x90, 	/* 09990 */
+	0xA0,  0xF8,  0xA6,  0x20,  0x02,  0x7E,  0x21,  0x02,  0x54,  0x75,  0x46,  0x92,  0xAF,  0xF2,  0x10,  0x21, 	/* 099A0 */
+	0x02,  0x10,  0x21,  0x02,  0x10,  0xA7,  0x21,  0x02,  0x50,  0x27,  0xC2,  0x50,  0x75,  0x06,  0x90,  0xA7, 	/* 099B0 */
+	0xC2,  0x10,  0x21,  0x02,  0x10,  0x21,  0x02,  0xFE,  0xA8,  0x20,  0x03,  0xBC,  0x4A,  0x4A,  0xA4,  0x12, 	/* 099C0 */
+	0xC2,  0x22,  0xC1,  0xE0,  0x40,  0x52,  0x45,  0x22,  0x90,  0xA0,  0xF8,  0xA9,  0x20,  0x02,  0x7E,  0x24, 	/* 099D0 */
+	0x22,  0x42,  0x77,  0xE6,  0x50,  0xA5,  0x22,  0x5C,  0x29,  0x02,  0x92,  0x31,  0x22,  0x0E,  0xAA,  0x2F, 	/* 099E0 */
+	0xC2,  0x44,  0x22,  0x82,  0x10,  0x72,  0x86,  0xC6,  0xA1,  0x02,  0x10,  0x2F,  0xC2,  0x10,  0x21,  0x03, 	/* 099F0 */
+	0xFE,  0xAB,  0x22,  0x82,  0x28,  0x2F,  0xE2,  0x2A,  0x7F,  0xE6,  0xA8,  0xAF,  0xF2,  0x29,  0x22,  0x92, 	/* 09A00 */
+	0x2E,  0x24,  0x82,  0x88,  0xAF,  0x21,  0x02,  0x10,  0x21,  0x06,  0xFC,  0x61,  0x0B,  0x10,  0xBF,  0xE2, 	/* 09A10 */
+	0x20,  0x22,  0x82,  0x48,  0x27,  0xC3,  0xC4,  0xB1,  0x10,  0x01,  0x00,  0x3F,  0xE4,  0x4A,  0xB9,  0x21, 	/* 09A20 */
+	0x72,  0x44,  0xC2,  0x20,  0x49,  0x24,  0x91,  0x88,  0x50,  0x7C,  0xBA,  0x23,  0x02,  0x08,  0x20,  0x03, 	/* 09A30 */
+	0x30,  0x69,  0x26,  0xF4,  0xA3,  0x82,  0x34,  0x25,  0x23,  0x91,  0x21,  0x02,  0x30,  0x81,  0x11,  0x81, 	/* 09A40 */
+	0xE0,  0x22,  0x05,  0xFE,  0xC2,  0x04,  0x20,  0x5F,  0xC4,  0x00,  0x14,  0x05,  0x24,  0x90,  0xA0,  0xF8, 	/* 09A50 */
+	0x82,  0x24,  0x02,  0x40,  0x27,  0xE2,  0x82,  0x6F,  0xA7,  0x4A,  0xA7,  0xA2,  0x4A,  0x27,  0xA2,  0x02, 	/* 09A60 */
+	0x20,  0x22,  0x0C,  0x83,  0x21,  0x02,  0x10,  0x27,  0xC2,  0x10,  0x67,  0xE7,  0x08,  0xAF,  0xE2,  0x08, 	/* 09A70 */
+	0x24,  0x82,  0x28,  0x20,  0x82,  0x18,  0x86,  0x20,  0x02,  0xFE,  0x24,  0x02,  0x7C,  0x76,  0x47,  0x54, 	/* 09A80 */
+	0xA5,  0x42,  0xC8,  0x2A,  0x82,  0xA8,  0x20,  0x83,  0xFE,  0x8A,  0x42,  0x04,  0xFC,  0x42,  0x46,  0x24, 	/* 09A90 */
+	0xD4,  0x4C,  0x98,  0x48,  0x87,  0xFE,  0x54,  0xA5,  0x4A,  0x55,  0x26,  0x66,  0x8B,  0x04,  0x00,  0x40, 	/* 09AA0 */
+	0xFF,  0xF0,  0x90,  0x29,  0x42,  0x92,  0x4B,  0x28,  0x40,  0x12,  0x45,  0x02,  0x90,  0xA0,  0xF8,  0x8D, 	/* 09AB0 */
+	0x21,  0x02,  0x52,  0x25,  0x23,  0x34,  0x69,  0x06,  0xFE,  0xA2,  0x82,  0x28,  0x22,  0x82,  0x48,  0x24, 	/* 09AC0 */
+	0xA2,  0x86,  0x90,  0x07,  0x8F,  0xC8,  0x24,  0x82,  0x68,  0x3D,  0xAE,  0x4A,  0x08,  0x61,  0x40,  0x52, 	/* 09AD0 */
+	0x45,  0x22,  0x90,  0xA0,  0xF8,  0x92,  0x20,  0x02,  0xFE,  0x20,  0x02,  0x7C,  0x74,  0x46,  0xC4,  0xA7, 	/* 09AE0 */
+	0xC2,  0x44,  0x24,  0x42,  0x7C,  0x20,  0x02,  0xFF,  0x95,  0x20,  0x02,  0x1E,  0xFD,  0x22,  0x52,  0x69, 	/* 09AF0 */
+	0x21,  0x92,  0x25,  0xEC,  0x40,  0x52,  0x45,  0x02,  0x90,  0xA0,  0xF8,  0x99,  0x20,  0x81,  0x10,  0x7F, 	/* 09B00 */
+	0xC0,  0x40,  0x3F,  0x80,  0x40,  0xFF,  0xE0,  0x40,  0x52,  0x45,  0x22,  0x90,  0xA0,  0xF8,  0x9A,  0x04, 	/* 09B10 */
+	0x03,  0xF8,  0x04,  0x0F,  0xFE,  0x04,  0x03,  0xF8,  0x04,  0x0F,  0xFE,  0x14,  0x05,  0x24,  0x90,  0xA0, 	/* 09B20 */
+	0xF8,  0x9F,  0x24,  0x02,  0x40,  0x27,  0xE2,  0x82,  0x79,  0x26,  0x52,  0xAA,  0xA2,  0xDA,  0x28,  0xA2, 	/* 09B30 */
+	0xFA,  0x20,  0x22,  0x0C,  0xA0,  0x22,  0x02,  0x20,  0x2F,  0xE3,  0x40,  0x64,  0x86,  0x88,  0xBB,  0xE2, 	/* 09B40 */
+	0x88,  0x28,  0x82,  0x88,  0x2F,  0xE2,  0x80,  0xA2,  0x20,  0x02,  0x7E,  0x24,  0x82,  0x4A,  0x65,  0xA7, 	/* 09B50 */
+	0x5C,  0x6E,  0x8A,  0x48,  0x28,  0x82,  0x94,  0x36,  0x43,  0x82,  0xA3,  0x08,  0x06,  0x80,  0x0F,  0xE1, 	/* 09B60 */
+	0x24,  0x22,  0x0C,  0xD8,  0x30,  0x60,  0x80,  0x54,  0x85,  0x44,  0x91,  0x40,  0xF0,  0xA4,  0x21,  0x02, 	/* 09B70 */
+	0x20,  0x2F,  0xE2,  0xAA,  0x6A,  0xA7,  0xAA,  0xAA,  0xA2,  0xAA,  0x2A,  0xA2,  0xAA,  0x3F,  0xF2,  0x00, 	/* 09B80 */
+	0xA5,  0x01,  0x0F,  0xC8,  0x48,  0x44,  0x94,  0x79,  0x04,  0x92,  0x7B,  0x24,  0xD1,  0x4D,  0x1F,  0xD2, 	/* 09B90 */
+	0x09,  0x20,  0x8E,  0xA8,  0x20,  0x02,  0x7C,  0x24,  0x46,  0x7C,  0x74,  0x4A,  0xFC,  0xA6,  0x22,  0x54, 	/* 09BA0 */
+	0x25,  0x82,  0x48,  0x27,  0x42,  0xC2,  0xA9,  0x00,  0x07,  0xFC,  0x44,  0x47,  0xFC,  0x4A,  0x47,  0x1C, 	/* 09BB0 */
+	0x7F,  0xC1,  0x40,  0x52,  0x45,  0x22,  0x90,  0xA0,  0xF8,  0xAA,  0x22,  0x02,  0x3C,  0x24,  0x43,  0x68, 	/* 09BC0 */
+	0x69,  0x06,  0x28,  0xA4,  0x42,  0xFE,  0x34,  0x52,  0x44,  0x24,  0x42,  0x7C,  0xAB,  0x20,  0x02,  0xFE, 	/* 09BD0 */
+	0x28,  0x22,  0xBA,  0x78,  0x26,  0xBA,  0xAA,  0xA2,  0xAA,  0x2B,  0xA2,  0xA2,  0x28,  0x22,  0x86,  0xAC, 	/* 09BE0 */
+	0x20,  0xC2,  0xF0,  0x21,  0x02,  0x10,  0x7F,  0xE6,  0x10,  0xA1,  0x02,  0xFC,  0x28,  0x42,  0x84,  0x28, 	/* 09BF0 */
+	0x42,  0xFC,  0xAD,  0x11,  0x01,  0x10,  0x7F,  0xC1,  0x10,  0x11,  0x0F,  0xFE,  0x11,  0x02,  0x88,  0xEA, 	/* 09C00 */
+	0xE2,  0x94,  0x49,  0x41,  0x80,  0xAF,  0x08,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x20, 	/* 09C10 */
+	0x83,  0xF8,  0x54,  0x45,  0x22,  0x90,  0xA0,  0xF8,  0xB0,  0x21,  0x02,  0x10,  0x22,  0x82,  0x28,  0x74, 	/* 09C20 */
+	0x46,  0xBA,  0xB0,  0x02,  0x7C,  0x24,  0x42,  0x44,  0x24,  0x42,  0x7C,  0xB5,  0x04,  0x0F,  0xFE,  0x04, 	/* 09C30 */
+	0x03,  0xFC,  0x24,  0x43,  0xFC,  0x24,  0x43,  0xFC,  0x14,  0x05,  0x24,  0x90,  0xA0,  0xF8,  0xB7,  0x11, 	/* 09C40 */
+	0x01,  0x10,  0x3F,  0xE6,  0x58,  0xA9,  0x43,  0x12,  0x21,  0x02,  0x50,  0x52,  0x45,  0x22,  0x90,  0xA0, 	/* 09C50 */
+	0xF8,  0x81,  0x20,  0x02,  0x7E,  0x24,  0x22,  0x7E,  0x70,  0x06,  0xFE,  0xA4,  0x22,  0x7E,  0x24,  0x22, 	/* 09C60 */
+	0x7E,  0x24,  0x22,  0x46,  0x83,  0x20,  0x02,  0xFE,  0x29,  0x22,  0xFE,  0x79,  0x26,  0x9A,  0xAB,  0xA2, 	/* 09C70 */
+	0xB6,  0x2D,  0x62,  0x92,  0x29,  0x22,  0xFE,  0x84,  0x21,  0x02,  0x54,  0x25,  0x42,  0x92,  0x77,  0xC7, 	/* 09C80 */
+	0x44,  0xA7,  0xC2,  0x44,  0x27,  0xC2,  0x44,  0x24,  0x42,  0x4C,  0x89,  0x01,  0xC7,  0xE4,  0x24,  0x8F, 	/* 09C90 */
+	0xFE,  0x0E,  0x03,  0x58,  0xC4,  0x60,  0x20,  0x2A,  0x42,  0x82,  0x48,  0xA8,  0x78,  0x8B,  0x21,  0x02, 	/* 09CA0 */
+	0xFE,  0x24,  0x42,  0x38,  0x72,  0x86,  0xC4,  0xA8,  0x22,  0x7C,  0x24,  0x42,  0x44,  0x24,  0x42,  0x7C, 	/* 09CB0 */
+	0x8C,  0x24,  0x42,  0x28,  0x2F,  0xE2,  0x12,  0x77,  0xE6,  0x90,  0xAF,  0xE2,  0x32,  0x25,  0x22,  0x92, 	/* 09CC0 */
+	0x31,  0xC2,  0x10,  0x8D,  0x20,  0x02,  0xFC,  0x28,  0x42,  0xFC,  0x78,  0x46,  0xFC,  0xA0,  0x02,  0xFC, 	/* 09CD0 */
+	0x22,  0x03,  0xFE,  0x22,  0x02,  0x20,  0x92,  0x27,  0x82,  0x48,  0x27,  0x82,  0x00,  0x6F,  0xC7,  0xA4, 	/* 09CE0 */
+	0xAA,  0x42,  0xFC,  0x28,  0x02,  0x80,  0x28,  0x22,  0x7E,  0x94,  0x22,  0x02,  0x3E,  0x24,  0x02,  0xFC, 	/* 09CF0 */
+	0x65,  0x47,  0x54,  0xA7,  0xE2,  0x94,  0x29,  0x42,  0xFE,  0x20,  0x42,  0x18,  0x96,  0x21,  0x02,  0xFE, 	/* 09D00 */
+	0x21,  0x02,  0xFE,  0x78,  0x26,  0xBA,  0xA0,  0x82,  0x10,  0x2F,  0xE2,  0x10,  0x21,  0x02,  0x30,  0x97, 	/* 09D10 */
+	0x22,  0x02,  0x38,  0x24,  0x82,  0x90,  0x7F,  0xC6,  0x94,  0xA9,  0x42,  0xFC,  0x23,  0x02,  0x52,  0x29, 	/* 09D20 */
+	0x23,  0x0E,  0x9A,  0x21,  0x02,  0xFE,  0x21,  0x02,  0xFE,  0x79,  0x26,  0x92,  0xAF,  0xE2,  0x38,  0x23, 	/* 09D30 */
+	0x42,  0x52,  0x29,  0x12,  0x10,  0x9B,  0x21,  0x02,  0x24,  0x2F,  0xE2,  0x2A,  0x62,  0x87,  0x46,  0xAA, 	/* 09D40 */
+	0x02,  0x3C,  0x26,  0x42,  0x98,  0x22,  0x42,  0xC2,  0x9F,  0x20,  0x02,  0xFE,  0x21,  0x02,  0xFC,  0x62, 	/* 09D50 */
+	0x47,  0x24,  0xAF,  0xF2,  0x00,  0x27,  0xC2,  0x44,  0x24,  0x42,  0x7C,  0xA0,  0x22,  0x02,  0x20,  0x6B, 	/* 09D60 */
+	0xEA,  0xC4,  0x29,  0x42,  0x88,  0x29,  0x42,  0x62,  0x14,  0x05,  0x24,  0x90,  0xA0,  0xF8,  0xA3,  0x04, 	/* 09D70 */
+	0x03,  0xF8,  0x24,  0x83,  0xF8,  0x04,  0x07,  0xFC,  0x44,  0x47,  0xFC,  0x04,  0x05,  0x24,  0x90,  0xA0, 	/* 09D80 */
+	0xF8,  0xA6,  0x24,  0x42,  0x28,  0x27,  0xC7,  0x44,  0x6C,  0x4A,  0x44,  0xA7,  0xC2,  0x28,  0x22,  0x82, 	/* 09D90 */
+	0x4A,  0x28,  0xA3,  0x06,  0xA7,  0x23,  0x23,  0xCA,  0x24,  0xA3,  0xFA,  0x64,  0xA7,  0x6A,  0xAD,  0xA2, 	/* 09DA0 */
+	0xCA,  0x34,  0xA2,  0x42,  0x24,  0x22,  0x46,  0xA9,  0x22,  0x22,  0x92,  0x25,  0x42,  0x48,  0x70,  0x06, 	/* 09DB0 */
+	0xCA,  0xAA,  0xA2,  0x92,  0x2A,  0xA2,  0xCA,  0x28,  0x22,  0xFE,  0xAA,  0x00,  0x0F,  0xFE,  0x0A,  0x07, 	/* 09DC0 */
+	0xFC,  0x4A,  0x47,  0xFC,  0x0A,  0x0F,  0xFE,  0x54,  0x05,  0x24,  0x90,  0xA0,  0xF8,  0xB2,  0x0A,  0x07, 	/* 09DD0 */
+	0xBC,  0x0A,  0x07,  0xBC,  0x0A,  0x0F,  0xBE,  0x0A,  0x01,  0x20,  0x44,  0x45,  0x22,  0x90,  0xA0,  0xF8, 	/* 09DE0 */
+	0xB3,  0x04,  0x0F,  0xFE,  0x04,  0x0B,  0xF8,  0xA0,  0x8B,  0xF8,  0xA0,  0x8F,  0xFE,  0x04,  0x05,  0x24, 	/* 09DF0 */
+	0x90,  0xA0,  0xF8,  0xB4,  0x21,  0x02,  0xFE,  0x24,  0x42,  0x44,  0x6A,  0xA7,  0x12,  0xA1,  0x03,  0xFE, 	/* 09E00 */
+	0x21,  0x02,  0x10,  0x21,  0x02,  0x10,  0xB5,  0x20,  0x02,  0x7E,  0x24,  0x03,  0x7C,  0x6C,  0x06,  0x7C, 	/* 09E10 */
+	0xA4,  0x03,  0xFF,  0x25,  0x22,  0x4C,  0x25,  0x42,  0xE2,  0xB6,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2, 	/* 09E20 */
+	0xFB,  0xE8,  0x42,  0x8A,  0x2A,  0x8A,  0xA8,  0x6C,  0x92,  0x87,  0x28,  0x06,  0xB8,  0x20,  0xC2,  0x70, 	/* 09E30 */
+	0x21,  0x02,  0xFE,  0x73,  0x86,  0xD6,  0xA1,  0x02,  0x7C,  0x20,  0x82,  0xFE,  0x21,  0x02,  0x30,  0xBC, 	/* 09E40 */
+	0x21,  0x02,  0x1E,  0x21,  0x02,  0xFC,  0x78,  0x46,  0xFC,  0xA8,  0x42,  0xFC,  0x21,  0x03,  0xFE,  0x21, 	/* 09E50 */
+	0x02,  0x10,  0xBD,  0x22,  0x03,  0xFE,  0x22,  0x02,  0xFC,  0x62,  0x47,  0xFE,  0xA2,  0x42,  0xFE,  0x24, 	/* 09E60 */
+	0x82,  0xC8,  0x23,  0x02,  0xCC,  0x85,  0x21,  0x02,  0xFE,  0x21,  0x02,  0xFC,  0x71,  0x06,  0xFF,  0xA4, 	/* 09E70 */
+	0x42,  0x7C,  0x24,  0x42,  0x7C,  0x24,  0x42,  0x4C,  0x86,  0x20,  0x02,  0xFE,  0x29,  0x22,  0xFA,  0x79, 	/* 09E80 */
+	0x26,  0xFE,  0xA9,  0x22,  0xBA,  0x2A,  0xA2,  0xBA,  0x30,  0x22,  0x06,  0x87,  0x21,  0x02,  0xFE,  0x20, 	/* 09E90 */
+	0x02,  0x7C,  0x74,  0x46,  0xFC,  0xA0,  0x02,  0x78,  0x21,  0x03,  0xFE,  0x21,  0x02,  0x30,  0x91,  0x02, 	/* 09EA0 */
+	0x80,  0x24,  0xFF,  0xE7,  0x94,  0x49,  0x87,  0xB0,  0x0C,  0xAF,  0x36,  0x14,  0x05,  0x24,  0x90,  0xA0, 	/* 09EB0 */
+	0xF8,  0x93,  0x21,  0x02,  0x54,  0x29,  0x22,  0x7C,  0x73,  0x06,  0xFE,  0xA4,  0x82,  0xFC,  0x34,  0xA2, 	/* 09EC0 */
+	0x58,  0x24,  0x22,  0x3E,  0x98,  0x20,  0x02,  0xFE,  0x2A,  0xA2,  0x92,  0x6F,  0xE7,  0x92,  0xAB,  0xE2, 	/* 09ED0 */
+	0xA2,  0x2A,  0x22,  0x9A,  0x30,  0x22,  0x06,  0x9A,  0x24,  0x02,  0x40,  0x27,  0xE6,  0xAA,  0x64,  0xAB, 	/* 09EE0 */
+	0x92,  0xA2,  0x42,  0x40,  0x2D,  0x42,  0xD2,  0x34,  0x62,  0x3C,  0x9C,  0x22,  0x42,  0x24,  0x27,  0xE3, 	/* 09EF0 */
+	0x24,  0x6F,  0xF6,  0x80,  0xA7,  0xC2,  0x44,  0x27,  0xC2,  0x44,  0x24,  0x42,  0x7C,  0x9F,  0x24,  0x42, 	/* 09F00 */
+	0x48,  0x27,  0xE6,  0xC8,  0x74,  0x8B,  0x7E,  0xA4,  0x82,  0x48,  0x27,  0xE2,  0x48,  0x24,  0x82,  0x7E, 	/* 09F10 */
+	0xA0,  0x04,  0x0F,  0xFE,  0x24,  0x83,  0xF8,  0x24,  0x83,  0xF8,  0x04,  0x8F,  0xFC,  0x04,  0x25,  0x24, 	/* 09F20 */
+	0x90,  0xA0,  0xF8,  0xA1,  0x00,  0x0F,  0xFE,  0x0A,  0x07,  0xBC,  0x40,  0x47,  0xBC,  0x0A,  0x0F,  0xFE, 	/* 09F30 */
+	0x04,  0x05,  0x24,  0x90,  0xA0,  0xF8,  0xA3,  0x52,  0x05,  0x20,  0x7F,  0xE9,  0x6A,  0x16,  0xA3,  0xAA, 	/* 09F40 */
+	0xD5,  0x21,  0x2C,  0x14,  0x05,  0x24,  0x90,  0xA0,  0xF8,  0xA7,  0x20,  0x02,  0x7C,  0x24,  0x42,  0x7C, 	/* 09F50 */
+	0x74,  0x46,  0xFC,  0xA4,  0x42,  0x7C,  0x24,  0x42,  0xFF,  0x22,  0x42,  0xC2,  0xA8,  0x22,  0x82,  0x48, 	/* 09F60 */
+	0x2F,  0xC6,  0x10,  0x6F,  0xEB,  0x30,  0xA4,  0x83,  0xA6,  0x2D,  0x02,  0x64,  0x21,  0x82,  0xE0,  0xB0, 	/* 09F70 */
+	0x22,  0x02,  0xFE,  0x22,  0x07,  0x7C,  0x69,  0x0A,  0xFE,  0xA4,  0x42,  0x7C,  0x24,  0x42,  0x7C,  0x24, 	/* 09F80 */
+	0x42,  0x4C,  0xB1,  0x25,  0x42,  0x54,  0x2A,  0x82,  0x54,  0x65,  0x47,  0x20,  0xAF,  0xE2,  0x8A,  0x2E, 	/* 09F90 */
+	0xA2,  0x9A,  0x2A,  0x62,  0xFE,  0xB3,  0x20,  0x0F,  0xFC,  0x24,  0x46,  0x7C,  0x74,  0x4A,  0xFC,  0xA4, 	/* 09FA0 */
+	0x42,  0x7C,  0x54,  0x05,  0x24,  0x91,  0x20,  0xF0,  0xB4,  0x21,  0x02,  0x92,  0x29,  0x22,  0xFE,  0x70, 	/* 09FB0 */
+	0x07,  0xFF,  0xA2,  0x02,  0xFE,  0x2A,  0xA2,  0xAA,  0x2A,  0xA2,  0x86,  0xB6,  0x22,  0x02,  0x7C,  0x24, 	/* 09FC0 */
+	0x42,  0x7C,  0x74,  0x46,  0xFC,  0xA0,  0x02,  0xFE,  0x21,  0x02,  0x7C,  0x21,  0x02,  0xFE,  0xB7,  0x04, 	/* 09FD0 */
+	0x07,  0xFC,  0x0A,  0x0F,  0xFF,  0x31,  0x85,  0xF4,  0x91,  0x21,  0xF0,  0x04,  0x05,  0x24,  0x90,  0xA0, 	/* 09FE0 */
+	0xF8,  0xB9,  0x11,  0x0F,  0xFE,  0x15,  0x0F,  0xFE,  0x08,  0x03,  0xF8,  0xD0,  0x81,  0xF8,  0x54,  0x05, 	/* 09FF0 */
+	0x24,  0x90,  0xA0,  0xF8,  0xBA,  0x20,  0x02,  0xFC,  0x28,  0x42,  0xFC,  0x78,  0x46,  0xFC,  0xA5,  0x02, 	/* 0A000 */
+	0xFE,  0x31,  0x02,  0x7C,  0x21,  0x03,  0xFE,  0xBB,  0x40,  0x25,  0xEA,  0x52,  0xAD,  0x2A,  0xFE,  0xAD, 	/* 0A010 */
+	0x2A,  0x5E,  0xA5,  0x2A,  0x5E,  0xA4,  0xC2,  0x52,  0x26,  0x06,  0x80,  0x22,  0x83,  0xC8,  0x24,  0xA2, 	/* 0A020 */
+	0x4A,  0x7E,  0xC6,  0x68,  0xAD,  0x82,  0xC8,  0x35,  0x42,  0x54,  0x26,  0x22,  0x41,  0x81,  0x31,  0x0E, 	/* 0A030 */
+	0x52,  0x25,  0x2F,  0x94,  0x21,  0x87,  0x24,  0xAC,  0x22,  0x20,  0x2A,  0x42,  0x82,  0x48,  0xA8,  0x78, 	/* 0A040 */
+	0x83,  0x21,  0x02,  0xFE,  0x28,  0x22,  0x7C,  0x70,  0x06,  0xFC,  0xA4,  0x42,  0x7C,  0x24,  0x42,  0x7C, 	/* 0A050 */
+	0x20,  0x02,  0xFE,  0x86,  0x4B,  0xCA,  0x40,  0x33,  0xE4,  0x88,  0xC4,  0x84,  0x88,  0x48,  0x84,  0x18, 	/* 0A060 */
+	0x14,  0x05,  0x24,  0x92,  0xA0,  0xF8,  0x88,  0x04,  0x00,  0xA0,  0x31,  0x8F,  0xD6,  0x25,  0x43,  0xD4, 	/* 0A070 */
+	0x24,  0x42,  0xCC,  0x14,  0x05,  0x24,  0x90,  0xA0,  0xF8,  0x89,  0x21,  0x02,  0x28,  0x24,  0x42,  0xBA, 	/* 0A080 */
+	0x70,  0x06,  0xEA,  0xAA,  0xA2,  0xEA,  0x2A,  0xA2,  0xEA,  0x2A,  0x22,  0xA6,  0x8D,  0x7D,  0x04,  0x50, 	/* 0A090 */
+	0x7D,  0xF5,  0x22,  0x7C,  0xC4,  0x8C,  0xE7,  0x20,  0x40,  0x52,  0x45,  0x22,  0x90,  0xA0,  0xF8,  0x8E, 	/* 0A0A0 */
+	0x24,  0x02,  0x7E,  0x2C,  0x46,  0x7C,  0x74,  0x4A,  0x7C,  0xA2,  0x02,  0x7C,  0x24,  0x43,  0xA8,  0x23, 	/* 0A0B0 */
+	0x83,  0xC6,  0x8F,  0x04,  0x07,  0xFC,  0x11,  0x0F,  0xFE,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x54, 	/* 0A0C0 */
+	0x05,  0x24,  0x90,  0xA0,  0xF8,  0x95,  0x2E,  0xE2,  0xAA,  0x2E,  0xE2,  0x00,  0x77,  0xC6,  0x00,  0xBF, 	/* 0A0D0 */
+	0xF2,  0x20,  0x23,  0xC2,  0x44,  0x20,  0x42,  0x18,  0x9A,  0x3F,  0x82,  0x48,  0x3F,  0x82,  0x48,  0xFF, 	/* 0A0E0 */
+	0xE8,  0xA2,  0x97,  0x2B,  0x8A,  0x14,  0x65,  0x24,  0x90,  0xA0,  0xF8,  0x9B,  0x01,  0xC7,  0xE8,  0x15, 	/* 0A0F0 */
+	0x0F,  0xFE,  0x8A,  0x2A,  0x94,  0x27,  0xA5,  0xF2,  0x71,  0x00,  0xE0,  0x1B,  0x0E,  0x0E,  0x9F,  0x02, 	/* 0A100 */
+	0x47,  0xFE,  0x42,  0x07,  0xD4,  0x41,  0x47,  0xCA,  0xA5,  0x63,  0xE2,  0x04,  0x05,  0x24,  0x90,  0xA0, 	/* 0A110 */
+	0xF8,  0xA1,  0x24,  0x02,  0x40,  0x27,  0xE2,  0xAA,  0x76,  0xA6,  0x9A,  0xA2,  0x22,  0x4C,  0x26,  0x02, 	/* 0A120 */
+	0xD4,  0x34,  0x62,  0x3C,  0xA7,  0x21,  0x02,  0x20,  0x2F,  0xC3,  0xA4,  0x6F,  0xC6,  0xA4,  0xAF,  0xC2, 	/* 0A130 */
+	0x54,  0x25,  0xA2,  0x5E,  0x29,  0x13,  0x0F,  0xA8,  0x23,  0x8F,  0xA8,  0x22,  0xAF,  0xCE,  0x03,  0xCF, 	/* 0A140 */
+	0xA4,  0x89,  0x83,  0xE6,  0x54,  0x05,  0x22,  0x90,  0x90,  0xF8,  0xAC,  0x44,  0x02,  0x9E,  0xFF,  0x21, 	/* 0A150 */
+	0x1E,  0x55,  0x27,  0xDE,  0x12,  0x22,  0x46,  0x54,  0x05,  0x24,  0x90,  0xA0,  0xF8,  0xB4,  0x21,  0x02, 	/* 0A160 */
+	0x28,  0x24,  0x46,  0xBA,  0x74,  0x4A,  0x7C,  0xA4,  0x42,  0x7C,  0x24,  0x02,  0xBE,  0x2A,  0x22,  0x3E, 	/* 0A170 */
+	0xBC,  0x24,  0xC2,  0x70,  0x24,  0x26,  0x7E,  0x72,  0x4A,  0xBC,  0xAA,  0x42,  0xBC,  0x2A,  0x42,  0xFE, 	/* 0A180 */
+	0x23,  0x42,  0xC2,  0xBD,  0x21,  0x43,  0xFE,  0x29,  0x42,  0xFC,  0x79,  0x46,  0xFC,  0xA9,  0x42,  0x08, 	/* 0A190 */
+	0x3F,  0xE2,  0x88,  0x24,  0x82,  0x18,  0xBE,  0x48,  0x04,  0xFE,  0x50,  0x0C,  0xFC,  0xE0,  0x0F,  0xFC, 	/* 0A1A0 */
+	0x55,  0x44,  0xE4,  0x5F,  0xC4,  0x64,  0x4D,  0x25,  0x42,  0xBF,  0x00,  0x07,  0xFE,  0x44,  0x05,  0xFC, 	/* 0A1B0 */
+	0x50,  0x45,  0xFC,  0x4A,  0x85,  0x24,  0x82,  0x05,  0x44,  0x52,  0xA8,  0xF8,  0x82,  0x4F,  0xE2,  0x24, 	/* 0A1C0 */
+	0x81,  0x84,  0xFE,  0x09,  0x22,  0xFE,  0x49,  0x28,  0x96,  0x44,  0x05,  0x24,  0x90,  0xA0,  0xF8,  0x84, 	/* 0A1D0 */
+	0x20,  0x02,  0xFE,  0x22,  0x82,  0xFE,  0x7A,  0xA6,  0xFE,  0xA1,  0x02,  0xFE,  0x23,  0x82,  0x54,  0x39, 	/* 0A1E0 */
+	0x22,  0x10,  0x87,  0x19,  0xC6,  0x14,  0x7A,  0x64,  0x80,  0x7B,  0xE4,  0xA4,  0x79,  0x84,  0x98,  0x8E, 	/* 0A1F0 */
+	0x65,  0x44,  0x52,  0xA8,  0xFA,  0x88,  0x21,  0x01,  0x20,  0xFF,  0xE2,  0x10,  0x52,  0x8A,  0x50,  0x4A, 	/* 0A200 */
+	0x4F,  0xBC,  0x54,  0x05,  0x24,  0x90,  0xA0,  0xF8,  0x8A,  0x22,  0x42,  0x48,  0x3F,  0xE2,  0x50,  0x6F, 	/* 0A210 */
+	0xC7,  0x54,  0xBF,  0xE2,  0x54,  0x3F,  0xC2,  0xD8,  0x35,  0x42,  0x50,  0x8B,  0x22,  0x44,  0xB8,  0xFA, 	/* 0A220 */
+	0x24,  0xDE,  0x7A,  0x44,  0xB8,  0x7A,  0x24,  0x9E,  0x14,  0x05,  0x24,  0x90,  0xA0,  0xF8,  0x8C,  0x24, 	/* 0A230 */
+	0x42,  0xFE,  0x24,  0x46,  0x10,  0x7F,  0xEB,  0x40,  0xA3,  0xC2,  0xA8,  0x2A,  0x82,  0xA8,  0x2A,  0xA3, 	/* 0A240 */
+	0x06,  0x8D,  0x20,  0x02,  0xFC,  0x29,  0x42,  0xB4,  0x7C,  0xC6,  0xFC,  0xA0,  0x02,  0xFE,  0x2A,  0xA2, 	/* 0A250 */
+	0xAA,  0x2A,  0xA3,  0xFF,  0x8E,  0x21,  0x02,  0xFE,  0x21,  0x02,  0x7C,  0x74,  0x46,  0xFC,  0xA4,  0x42, 	/* 0A260 */
+	0x7C,  0x24,  0x43,  0xFE,  0x22,  0x82,  0xC4,  0x93,  0x2F,  0xE2,  0x28,  0x2F,  0xE3,  0xAA,  0x6F,  0xE6, 	/* 0A270 */
+	0x00,  0xAF,  0xC2,  0x00,  0x2F,  0xE2,  0x54,  0x29,  0x22,  0x30,  0x95,  0x11,  0x0F,  0xFE,  0x11,  0x03, 	/* 0A280 */
+	0xF8,  0x20,  0x83,  0xF8,  0x20,  0x8F,  0xFE,  0x28,  0x85,  0xD4,  0xAA,  0xA1,  0x80,  0x98,  0x21,  0x02, 	/* 0A290 */
+	0x28,  0x2F,  0xC2,  0x48,  0x6B,  0x47,  0xFE,  0xA2,  0x82,  0x4C,  0x39,  0x32,  0x64,  0x21,  0x82,  0xE0, 	/* 0A2A0 */
+	0x99,  0x10,  0x4F,  0xF8,  0x55,  0x07,  0xDF,  0x55,  0x4F,  0xF4,  0x11,  0x41,  0x24,  0x54,  0x05,  0x24, 	/* 0A2B0 */
+	0x90,  0xA0,  0xF8,  0x9A,  0x44,  0x25,  0xFC,  0x45,  0x05,  0xF0,  0xF5,  0xFD,  0xF4,  0xD5,  0x45,  0xF4, 	/* 0A2C0 */
+	0x45,  0x45,  0xF4,  0x45,  0x44,  0x64,  0x9D,  0x7F,  0xE4,  0x90,  0x7F,  0xE4,  0x90,  0x7F,  0xE4,  0x80, 	/* 0A2D0 */
+	0x57,  0xC6,  0x44,  0x7F,  0xE5,  0x44,  0x90,  0xA0,  0xF8,  0x9F,  0x46,  0x87,  0x88,  0x49,  0xE7,  0xEA, 	/* 0A2E0 */
+	0xEA,  0xAF,  0xEA,  0x6A,  0xA7,  0xEA,  0x48,  0xA5,  0xEA,  0x4D,  0x27,  0xAC,  0xA2,  0x27,  0xC2,  0x44, 	/* 0A2F0 */
+	0x27,  0xC6,  0x44,  0x7F,  0xEA,  0xAA,  0xAF,  0xE2,  0x00,  0x2F,  0xC2,  0x44,  0x23,  0x83,  0xC6,  0xA3, 	/* 0A300 */
+	0x23,  0xE2,  0x2A,  0x2F,  0xE7,  0x54,  0x6F,  0xCA,  0x7E,  0xA4,  0x22,  0x7E,  0x24,  0x22,  0x7E,  0x22, 	/* 0A310 */
+	0x42,  0xC2,  0xA5,  0x22,  0x82,  0xA8,  0x27,  0xE3,  0x28,  0x6C,  0x86,  0x3E,  0xB8,  0x82,  0xBE,  0x2A, 	/* 0A320 */
+	0x22,  0xFE,  0x32,  0x02,  0x1F,  0xA7,  0xFB,  0xC2,  0x10,  0xFF,  0xC2,  0x10,  0x7F,  0xC0,  0x08,  0x7F, 	/* 0A330 */
+	0x80,  0x08,  0x7F,  0x85,  0x44,  0x92,  0xA0,  0xF8,  0xA8,  0x20,  0x02,  0xEE,  0x2A,  0xA2,  0xEA,  0x7A, 	/* 0A340 */
+	0xA6,  0xBF,  0xAE,  0x42,  0xC4,  0x2A,  0xC2,  0xED,  0x39,  0x52,  0x23,  0xAB,  0x24,  0x42,  0x44,  0x4A, 	/* 0A350 */
+	0xAB,  0x11,  0x29,  0xC6,  0x90,  0xAD,  0x03,  0x3E,  0x54,  0x05,  0x24,  0x90,  0xA0,  0xF8,  0xAE,  0x07, 	/* 0A360 */
+	0x80,  0x40,  0x7F,  0xE4,  0x72,  0x7C,  0x05,  0x3E,  0x5F,  0xC5,  0x24,  0x5F,  0xC4,  0xA4,  0x98,  0xAA, 	/* 0A370 */
+	0x78,  0xAF,  0x24,  0x02,  0x7E,  0x24,  0x42,  0xFC,  0x74,  0x46,  0x7C,  0xBF,  0xF2,  0x40,  0x27,  0xE2, 	/* 0A380 */
+	0xAA,  0x25,  0x22,  0xAC,  0xB0,  0x7C,  0x44,  0x44,  0x7F,  0xE4,  0x24,  0x7D,  0x44,  0x84,  0xAA,  0x4A, 	/* 0A390 */
+	0xAC,  0x14,  0x05,  0x24,  0x90,  0xA0,  0xF8,  0xB1,  0x21,  0x42,  0xFE,  0x25,  0x42,  0x7C,  0x75,  0x46, 	/* 0A3A0 */
+	0xFE,  0xA1,  0x42,  0xFE,  0x20,  0x83,  0xFE,  0x24,  0x82,  0x18,  0xB3,  0x20,  0x02,  0xFE,  0x2A,  0x22, 	/* 0A3B0 */
+	0xFA,  0x79,  0xA6,  0xF4,  0xAA,  0xA2,  0xF1,  0x21,  0x02,  0x7C,  0x21,  0x03,  0xFE,  0xB4,  0x2E,  0xE2, 	/* 0A3C0 */
+	0x22,  0x26,  0x62,  0xAA,  0x77,  0x67,  0xAA,  0xA3,  0x22,  0x7C,  0x24,  0x42,  0x7C,  0x24,  0x42,  0x7C, 	/* 0A3D0 */
+	0xB5,  0x21,  0x02,  0xFE,  0x29,  0x02,  0xFC,  0x79,  0x46,  0xFE,  0xA9,  0x42,  0xFC,  0x2D,  0x42,  0xFC, 	/* 0A3E0 */
+	0x35,  0x42,  0x4C,  0xB6,  0x04,  0x07,  0xFE,  0x49,  0x07,  0xFC,  0x49,  0x47,  0xFE,  0x5A,  0x46,  0x7A, 	/* 0A3F0 */
+	0x49,  0x2B,  0x60,  0x89,  0x87,  0x06,  0xB7,  0x21,  0x02,  0xFE,  0x29,  0x02,  0xFC,  0x79,  0x46,  0xFE, 	/* 0A400 */
+	0xA9,  0x42,  0xFC,  0x2D,  0x42,  0xB8,  0x35,  0x62,  0x10,  0xBE,  0x2A,  0x0D,  0x7E,  0x2B,  0x24,  0x54, 	/* 0A410 */
+	0xFD,  0x04,  0xA8,  0x7C,  0x60,  0x40,  0x52,  0x45,  0x22,  0x90,  0xA0,  0xF8,  0x82,  0x7F,  0xC0,  0x80, 	/* 0A420 */
+	0x1F,  0x01,  0x10,  0xFF,  0xEA,  0xAA,  0x49,  0x41,  0xFA,  0x19,  0x06,  0x60,  0x1B,  0x0E,  0x0E,  0x87, 	/* 0A430 */
+	0x1A,  0x4E,  0x24,  0x27,  0xEF,  0xA4,  0x23,  0xC7,  0xA4,  0x4A,  0x47,  0xBC,  0x14,  0x05,  0x24,  0x90, 	/* 0A440 */
+	0xA0,  0xF8,  0x8A,  0x22,  0x42,  0xFE,  0x42,  0x45,  0xFF,  0xD4,  0xA5,  0x7E,  0x54,  0xA6,  0x7E,  0x44, 	/* 0A450 */
+	0xA5,  0x22,  0x52,  0x98,  0xF8,  0x8E,  0x24,  0x42,  0x28,  0x2F,  0xE6,  0x92,  0x7F,  0xEA,  0x92,  0xAF, 	/* 0A460 */
+	0xE2,  0x44,  0x27,  0xC2,  0x44,  0x24,  0x42,  0x7C,  0x90,  0x29,  0x22,  0x54,  0x2F,  0xE6,  0x38,  0x75, 	/* 0A470 */
+	0x4A,  0x92,  0xA4,  0x42,  0x7E,  0x2B,  0x43,  0x3E,  0x24,  0x43,  0x84,  0x91,  0x8F,  0xE4,  0x90,  0x4F, 	/* 0A480 */
+	0xC0,  0x90,  0x2F,  0xE5,  0x52,  0x92,  0xA2,  0x0C,  0x14,  0x05,  0x22,  0x50,  0x98,  0xF9,  0x94,  0x22, 	/* 0A490 */
+	0x42,  0x28,  0x27,  0xE2,  0xC8,  0x77,  0xE6,  0xC8,  0xA7,  0xE2,  0x48,  0x27,  0xE2,  0x00,  0x26,  0xA2, 	/* 0A4A0 */
+	0x95,  0x96,  0x10,  0xCF,  0xCA,  0x54,  0x8B,  0x7E,  0x38,  0x85,  0x58,  0x92,  0x41,  0x42,  0x54,  0x05, 	/* 0A4B0 */
+	0x24,  0x90,  0xA0,  0xF8,  0x99,  0x04,  0x0F,  0xFE,  0x04,  0x07,  0xFC,  0x20,  0x83,  0xF8,  0xFF,  0xE2, 	/* 0A4C0 */
+	0x08,  0x3F,  0x85,  0x44,  0x90,  0xA0,  0xF8,  0x9A,  0x27,  0xE2,  0x5A,  0x27,  0xE2,  0x00,  0x77,  0xE6, 	/* 0A4D0 */
+	0xD2,  0xA7,  0xE2,  0x52,  0x2F,  0xF2,  0x10,  0x21,  0x02,  0x10,  0xA4,  0x22,  0x03,  0xFC,  0x2A,  0x87, 	/* 0A4E0 */
+	0xFE,  0x64,  0x8A,  0xFC,  0xA8,  0x42,  0xFC,  0x28,  0x42,  0xFC,  0x24,  0x43,  0x82,  0xA7,  0x21,  0x02, 	/* 0A4F0 */
+	0xFE,  0x24,  0x87,  0xFE,  0x68,  0x0A,  0x7C,  0xA5,  0x42,  0x7C,  0x25,  0x42,  0xFE,  0x21,  0x03,  0xFF, 	/* 0A500 */
+	0xA9,  0x19,  0x0E,  0x3C,  0x22,  0x4F,  0xBC,  0x22,  0x47,  0xBC,  0x4A,  0x47,  0xBC,  0x14,  0x05,  0x24, 	/* 0A510 */
+	0x90,  0xA0,  0xF8,  0xAB,  0x2E,  0xE2,  0xAA,  0x2E,  0xE2,  0xAA,  0x6E,  0xE7,  0x92,  0xAF,  0xE2,  0xAA, 	/* 0A520 */
+	0x2A,  0xA2,  0x92,  0x2A,  0xA2,  0xC6,  0xAC,  0x27,  0xC2,  0x44,  0x27,  0xC2,  0x44,  0x7F,  0xE6,  0x10, 	/* 0A530 */
+	0xAF,  0xE2,  0x44,  0x27,  0xC2,  0x94,  0x31,  0x22,  0x30,  0xAE,  0x28,  0x02,  0xFE,  0x2D,  0x43,  0x54, 	/* 0A540 */
+	0x6F,  0xE6,  0x54,  0xA5,  0x42,  0xFE,  0x20,  0x02,  0x94,  0x2A,  0xA3,  0x2A,  0xB2,  0x04,  0x0F,  0xFE, 	/* 0A550 */
+	0x84,  0x2B,  0xFA,  0x04,  0x0F,  0xFE,  0x4A,  0x47,  0xFC,  0x54,  0x05,  0x24,  0x90,  0xA0,  0xF8,  0xB6, 	/* 0A560 */
+	0x22,  0x02,  0xFC,  0x24,  0x83,  0xFE,  0x68,  0x46,  0xFC,  0xA8,  0x42,  0xFC,  0x25,  0x02,  0xD4,  0x34, 	/* 0A570 */
+	0xA2,  0x3A,  0xBA,  0x27,  0x82,  0x90,  0x3F,  0xE6,  0xA8,  0x7C,  0xEA,  0xB8,  0x28,  0x02,  0xFE,  0x28, 	/* 0A580 */
+	0x02,  0xFC,  0x34,  0x42,  0x7C,  0xBE,  0x40,  0xA4,  0xFE,  0x68,  0x85,  0xFA,  0xCE,  0x4C,  0xAC,  0xDF, 	/* 0A590 */
+	0x66,  0x22,  0x45,  0x05,  0x4A,  0x64,  0x24,  0x3E,  0x83,  0x48,  0x8F,  0xE8,  0x57,  0xE7,  0xCA,  0x10, 	/* 0A5A0 */
+	0xA7,  0xD2,  0x12,  0x2F,  0xCC,  0x14,  0x05,  0x24,  0x90,  0xA0,  0xF8,  0x86,  0x27,  0xC2,  0x44,  0x27, 	/* 0A5B0 */
+	0xC2,  0xEE,  0x7A,  0xA6,  0xEE,  0xA1,  0x02,  0xFE,  0x23,  0x82,  0x54,  0x29,  0x32,  0x10,  0x87,  0x0B, 	/* 0A5C0 */
+	0xCF,  0x24,  0x57,  0xCF,  0xA4,  0x33,  0xCD,  0xAA,  0x2B,  0x4D,  0x62,  0x14,  0x05,  0x24,  0x90,  0xA0, 	/* 0A5D0 */
+	0xF8,  0x88,  0x48,  0x04,  0xFE,  0x54,  0xA7,  0xFA,  0xD5,  0x6D,  0xF0,  0x55,  0xE5,  0xF4,  0x51,  0x45, 	/* 0A5E0 */
+	0x1E,  0x61,  0x44,  0x34,  0x89,  0x02,  0x07,  0xFE,  0x4A,  0x85,  0x7E,  0x7C,  0x85,  0x7E,  0x54,  0x85, 	/* 0A5F0 */
+	0x7E,  0x4A,  0x0A,  0x94,  0xA8,  0xA4,  0x7A,  0x8A,  0x22,  0x02,  0x40,  0x2F,  0xE2,  0xD6,  0x7B,  0xA6, 	/* 0A600 */
+	0xFE,  0xAB,  0xA2,  0xD6,  0x29,  0x23,  0xFF,  0x22,  0x82,  0xC6,  0x8B,  0x2E,  0x82,  0xA8,  0xF5,  0xE3, 	/* 0A610 */
+	0xF8,  0x6E,  0xC7,  0x5A,  0xA6,  0xA2,  0x48,  0x14,  0x05,  0x24,  0x90,  0xA0,  0xF8,  0x8C,  0x2F,  0xE2, 	/* 0A620 */
+	0xAA,  0x2F,  0xE3,  0x10,  0x6F,  0xE6,  0x10,  0xBF,  0xF2,  0x44,  0x3F,  0xF2,  0x10,  0x2F,  0xE2,  0x10, 	/* 0A630 */
+	0x8D,  0x21,  0x03,  0xFF,  0x2A,  0xA2,  0xBA,  0x78,  0x26,  0xFE,  0xA7,  0x82,  0x10,  0x2F,  0xE2,  0x5C, 	/* 0A640 */
+	0x39,  0x32,  0x10,  0x90,  0x21,  0x02,  0xFE,  0x21,  0x03,  0xFE,  0x6A,  0xA6,  0xFE,  0xA1,  0x03,  0xFF, 	/* 0A650 */
+	0x25,  0x42,  0xC8,  0x37,  0x42,  0xC2,  0xA3,  0x48,  0x83,  0xFE,  0x88,  0x84,  0xF8,  0x3F,  0xE6,  0xAA, 	/* 0A660 */
+	0xAA,  0xAB,  0x76,  0x22,  0x65,  0x44,  0x52,  0xA8,  0xFA,  0xA6,  0x27,  0xC2,  0x10,  0x2F,  0xE3,  0x92, 	/* 0A670 */
+	0x6D,  0xA6,  0x00,  0xAF,  0xE2,  0x40,  0x2F,  0xE2,  0xAA,  0x2A,  0xA2,  0x86,  0xB2,  0x24,  0x8D,  0x5E, 	/* 0A680 */
+	0x3F,  0x4C,  0x54,  0x5E,  0xC4,  0x48,  0x5F,  0x44,  0x22,  0x14,  0x05,  0x24,  0x50,  0xA8,  0xFA,  0xB4, 	/* 0A690 */
+	0x44,  0x84,  0x4C,  0x5F,  0xAC,  0x4E,  0xFF,  0x8C,  0xA8,  0x5B,  0xA4,  0xAA,  0x5B,  0x44,  0xA6,  0x4B, 	/* 0A6A0 */
+	0xA7,  0xC2,  0xB6,  0x49,  0xE4,  0x8A,  0x5E,  0xAC,  0x96,  0xFE,  0x0E,  0xBE,  0x7F,  0x25,  0x9E,  0x5D, 	/* 0A6B0 */
+	0x26,  0xBE,  0x49,  0x44,  0xA2,  0xB7,  0x21,  0x03,  0xFF,  0x2A,  0xA2,  0xFE,  0x71,  0x06,  0xD6,  0xA1, 	/* 0A6C0 */
+	0x02,  0xD6,  0x26,  0x22,  0xD4,  0x34,  0x82,  0x66,  0xB8,  0x39,  0xCA,  0xF0,  0xB9,  0x4A,  0xE8,  0xB9, 	/* 0A6D0 */
+	0x48,  0x7E,  0xF9,  0x02,  0xD4,  0xA5,  0x21,  0x24,  0x50,  0xA8,  0xFA,  0xBA,  0x52,  0x85,  0x2C,  0x6D, 	/* 0A6E0 */
+	0xAC,  0x0E,  0xFF,  0x8C,  0xAA,  0x5B,  0xA4,  0xAC,  0x5B,  0x44,  0xAE,  0x4B,  0xA7,  0xC2,  0xBC,  0x20, 	/* 0A6F0 */
+	0x02,  0xEE,  0x2A,  0xA2,  0xEE,  0x7A,  0xA6,  0xEE,  0xA2,  0x42,  0x7E,  0x2C,  0x82,  0x7E,  0x24,  0x82, 	/* 0A700 */
+	0x7E,  0xBD,  0x22,  0x82,  0xFE,  0x22,  0x82,  0xEE,  0x7A,  0xA6,  0xEE,  0xA2,  0x42,  0x7E,  0x2C,  0x82, 	/* 0A710 */
+	0x7E,  0x24,  0x82,  0x7E,  0xBE,  0x2F,  0xE2,  0x44,  0x27,  0xC2,  0x44,  0x7F,  0xE6,  0x04,  0xBF,  0xE2, 	/* 0A720 */
+	0xAA,  0x2E,  0xE2,  0xAB,  0x3F,  0xE2,  0x22,  0xBF,  0x21,  0x0F,  0xDE,  0x22,  0xAF,  0x88,  0x8A,  0x87, 	/* 0A730 */
+	0xD4,  0x4A,  0x27,  0x98,  0x4B,  0x53,  0x51,  0x39,  0x2E,  0x0E,  0x80,  0x44,  0x8A,  0xF4,  0x50,  0xAF, 	/* 0A740 */
+	0xDE,  0x20,  0x8A,  0xEC,  0xBA,  0xA2,  0xE8,  0x14,  0x05,  0x24,  0x90,  0xA0,  0xF8,  0x88,  0x04,  0x00, 	/* 0A750 */
+	0x48,  0x04,  0x4F,  0xFE,  0x04,  0x00,  0x48,  0x02,  0x80,  0x30,  0x05,  0x01,  0x8A,  0x60,  0x60,  0x02, 	/* 0A760 */
+	0x89,  0x04,  0x80,  0x44,  0x7F,  0xE4,  0x40,  0x44,  0x04,  0x44,  0x42,  0x44,  0xA8,  0x71,  0x0C,  0x2A, 	/* 0A770 */
+	0x0C,  0x63,  0x02,  0x8A,  0x02,  0x00,  0x24,  0x02,  0x23,  0xFE,  0x22,  0x02,  0x24,  0x22,  0x42,  0x28, 	/* 0A780 */
+	0x21,  0x04,  0x2A,  0x44,  0x69,  0x82,  0x8C,  0x02,  0x80,  0x24,  0x7F,  0xE4,  0x20,  0x42,  0x04,  0x24, 	/* 0A790 */
+	0x7A,  0x44,  0x18,  0x41,  0x24,  0x2A,  0x8C,  0x6B,  0x02,  0x8D,  0x02,  0x80,  0x24,  0x7F,  0xE4,  0x20, 	/* 0A7A0 */
+	0x42,  0x05,  0x24,  0x4A,  0x44,  0x98,  0x41,  0x24,  0x2A,  0x8C,  0x6B,  0x02,  0x8E,  0x02,  0x00,  0x28, 	/* 0A7B0 */
+	0x02,  0x4F,  0xFE,  0x12,  0x01,  0x24,  0x1D,  0x4F,  0x18,  0x13,  0x02,  0x4A,  0x28,  0x64,  0x02,  0x90, 	/* 0A7C0 */
+	0x02,  0x80,  0x24,  0x7F,  0xE4,  0x20,  0x42,  0x47,  0xA4,  0x4A,  0x84,  0x98,  0x49,  0x06,  0xAA,  0x54, 	/* 0A7D0 */
+	0x68,  0x82,  0x91,  0x0A,  0x07,  0x28,  0x12,  0x41,  0x20,  0xFF,  0xE1,  0x24,  0x12,  0x41,  0xD4,  0xF1, 	/* 0A7E0 */
+	0x81,  0x2A,  0x14,  0x63,  0x02,  0x92,  0x02,  0x80,  0x24,  0xFF,  0xE0,  0x20,  0x2A,  0x42,  0xA4,  0xFE, 	/* 0A7F0 */
+	0x82,  0x98,  0x29,  0x04,  0xAA,  0x8C,  0x60,  0x82,  0x94,  0x08,  0x8F,  0xFE,  0x05,  0x00,  0x22,  0x0D, 	/* 0A800 */
+	0xA7,  0x06,  0x08,  0x8F,  0xFF,  0x04,  0x80,  0x32,  0x0C,  0xE7,  0x02,  0x96,  0x02,  0x80,  0x24,  0xFF, 	/* 0A810 */
+	0xE0,  0x20,  0x7A,  0x44,  0xA4,  0x4A,  0x47,  0x98,  0x01,  0x81,  0xAA,  0xE4,  0x61,  0x82,  0x9A,  0x01, 	/* 0A820 */
+	0x40,  0x12,  0x7F,  0xF4,  0x90,  0x4F,  0x24,  0x92,  0x7F,  0xA4,  0x8A,  0x5A,  0x46,  0xAD,  0xA9,  0x38, 	/* 0A830 */
+	0xA1,  0x9B,  0xFF,  0xE0,  0x80,  0x7F,  0xC4,  0x04,  0x7F,  0xC4,  0x04,  0x7F,  0xC0,  0x84,  0xFF,  0xE0, 	/* 0A840 */
+	0x58,  0x0F,  0x27,  0x0E,  0x9D,  0x01,  0x07,  0x94,  0x49,  0x24,  0x9E,  0x7F,  0x04,  0x92,  0x79,  0x24, 	/* 0A850 */
+	0x8C,  0x78,  0x83,  0x1A,  0x4A,  0x68,  0x42,  0x9E,  0xFF,  0xE0,  0x80,  0x3F,  0x82,  0x08,  0x3F,  0x82, 	/* 0A860 */
+	0x08,  0xFF,  0xE8,  0x92,  0x7F,  0xC0,  0x48,  0x0F,  0x27,  0x0E,  0x9F,  0x21,  0x0F,  0x98,  0x21,  0x4F, 	/* 0A870 */
+	0x9E,  0x8F,  0x0F,  0x94,  0x89,  0x4F,  0x98,  0x20,  0x8F,  0x9A,  0x22,  0x62,  0x42,  0xA1,  0x49,  0x4F, 	/* 0A880 */
+	0xD2,  0x49,  0xE7,  0xF0,  0x49,  0x47,  0x94,  0x49,  0x4F,  0xD8,  0xA8,  0x8C,  0xDA,  0x82,  0x67,  0xC2, 	/* 0A890 */
+	0xA6,  0x25,  0x49,  0x52,  0x49,  0x07,  0xDE,  0x57,  0x07,  0xD4,  0x55,  0x47,  0xC8,  0x11,  0x8F,  0xEA, 	/* 0A8A0 */
+	0x12,  0x61,  0x42,  0xAA,  0x10,  0x87,  0xCC,  0x10,  0xAF,  0xFF,  0x24,  0x87,  0xEA,  0x48,  0xAF,  0xEC, 	/* 0A8B0 */
+	0x48,  0x47,  0xED,  0x49,  0x37,  0xE1,  0xAE,  0xFD,  0x46,  0xD2,  0xB5,  0x06,  0xFE,  0xB5,  0x01,  0x94, 	/* 0A8C0 */
+	0x25,  0x4C,  0xAC,  0x10,  0x86,  0x4A,  0x19,  0x6E,  0x22,  0xAF,  0x1D,  0x01,  0x14,  0x7D,  0x25,  0x50, 	/* 0A8D0 */
+	0x53,  0xE5,  0xD0,  0x41,  0x25,  0x4A,  0x74,  0xC5,  0x6A,  0x99,  0x66,  0x22,  0xB0,  0xEE,  0xCA,  0xAA, 	/* 0A8E0 */
+	0xEE,  0x87,  0xFF,  0x54,  0x87,  0xCA,  0x54,  0xA7,  0xCC,  0x10,  0x4F,  0xED,  0x11,  0x31,  0x21,  0xB2, 	/* 0A8F0 */
+	0x20,  0xC3,  0xCA,  0x20,  0x87,  0xFF,  0x50,  0x85,  0xCA,  0x64,  0xA7,  0xCA,  0x44,  0x45,  0x4D,  0x89, 	/* 0A900 */
+	0x3B,  0xE1,  0xB3,  0xEE,  0xC6,  0x6A,  0xAA,  0x86,  0x7F,  0xAA,  0x84,  0x4A,  0x48,  0xA7,  0xEC,  0xC8, 	/* 0A910 */
+	0x47,  0xED,  0x49,  0x37,  0xE1,  0xB4,  0x11,  0x07,  0xD4,  0x11,  0x2F,  0xFE,  0x55,  0x07,  0xD2,  0x29, 	/* 0A920 */
+	0x27,  0xD4,  0x28,  0x8F,  0xDA,  0x2A,  0x6C,  0x42,  0xB8,  0x00,  0x07,  0xFE,  0x00,  0x03,  0xFC,  0x20, 	/* 0A930 */
+	0x42,  0x04,  0x3F,  0xC2,  0x00,  0x20,  0x04,  0x00,  0x40,  0x08,  0x00,  0xBB,  0x00,  0x07,  0xFE,  0x00, 	/* 0A940 */
+	0x03,  0xFC,  0x20,  0x43,  0xFC,  0x22,  0x03,  0xFE,  0x42,  0x04,  0x50,  0x88,  0x83,  0x06,  0xBF,  0x7F, 	/* 0A950 */
+	0xE0,  0x00,  0x3F,  0xC2,  0x04,  0x3F,  0xC2,  0x20,  0x3F,  0xE2,  0x40,  0x47,  0xC4,  0x84,  0x90,  0x46, 	/* 0A960 */
+	0x18,  0x80,  0x00,  0x6F,  0xB8,  0x02,  0x07,  0xA0,  0x4B,  0xF4,  0xA4,  0x7A,  0x44,  0x24,  0x44,  0x44, 	/* 0A970 */
+	0x44,  0x88,  0x48,  0x04,  0x81,  0x7F,  0xE0,  0x00,  0x3F,  0xC2,  0x04,  0x3F,  0xC2,  0x00,  0x3F,  0xC3, 	/* 0A980 */
+	0x54,  0x5F,  0xC5,  0x54,  0x95,  0x41,  0x0C,  0x87,  0xFF,  0xE0,  0x00,  0x7F,  0xC4,  0x04,  0x7F,  0xC4, 	/* 0A990 */
+	0x00,  0x5D,  0xE4,  0x42,  0x75,  0xA4,  0xC6,  0xB5,  0xA8,  0xC6,  0x88,  0x00,  0x0F,  0xFE,  0x40,  0x47, 	/* 0A9A0 */
+	0xFC,  0x4F,  0x84,  0x88,  0x5F,  0xC5,  0x24,  0x5F,  0xC9,  0x00,  0x90,  0x20,  0xFE,  0x89,  0x3F,  0xE0, 	/* 0A9B0 */
+	0x00,  0x3F,  0xE2,  0x02,  0x3F,  0xE2,  0x50,  0x3D,  0xE2,  0x50,  0x5D,  0xE4,  0x50,  0xBD,  0xE0,  0x90, 	/* 0A9C0 */
+	0x8B,  0x00,  0x80,  0x30,  0x3C,  0x00,  0x40,  0x7F,  0xC0,  0x40,  0x04,  0x0F,  0xFE,  0x04,  0x00,  0x40, 	/* 0A9D0 */
+	0x04,  0x00,  0xC0,  0x8D,  0x02,  0x00,  0x20,  0x02,  0x0F,  0xFE,  0x02,  0x00,  0x28,  0x03,  0x00,  0x60, 	/* 0A9E0 */
+	0x1A,  0x06,  0x20,  0x02,  0x00,  0x60,  0x8E,  0x22,  0x02,  0x20,  0x22,  0x0F,  0xA0,  0x22,  0x02,  0x20, 	/* 0A9F0 */
+	0x32,  0x0E,  0x20,  0x22,  0x02,  0x22,  0x22,  0x26,  0x1E,  0x93,  0x20,  0x02,  0x7E,  0x20,  0x8F,  0x08, 	/* 0AA00 */
+	0x20,  0x82,  0x08,  0x30,  0x8E,  0x08,  0x20,  0x82,  0x08,  0x20,  0x86,  0x18,  0x95,  0x21,  0x02,  0x10, 	/* 0AA10 */
+	0x21,  0x0F,  0x10,  0x21,  0x02,  0x20,  0x32,  0x8E,  0x24,  0x24,  0x42,  0x4E,  0x2F,  0x26,  0x02,  0x98, 	/* 0AA20 */
+	0x20,  0xC2,  0xF0,  0x22,  0x0F,  0x20,  0x22,  0x03,  0xFE,  0x32,  0x0E,  0x20,  0x22,  0x02,  0x22,  0x22, 	/* 0AA30 */
+	0x26,  0x1E,  0x9B,  0x20,  0x02,  0xFC,  0x21,  0x0F,  0x90,  0x21,  0x02,  0x10,  0x39,  0x0E,  0x10,  0x21, 	/* 0AA40 */
+	0x02,  0x10,  0x3F,  0xE6,  0x00,  0x9E,  0x20,  0x02,  0x7C,  0x21,  0x0F,  0x90,  0x21,  0x02,  0xFE,  0x31, 	/* 0AA50 */
+	0x0E,  0x10,  0x21,  0x02,  0x10,  0x21,  0x06,  0x10,  0xA0,  0x20,  0x02,  0xFE,  0x20,  0x2F,  0x54,  0x24, 	/* 0AA60 */
+	0xC2,  0x28,  0x32,  0x8E,  0x10,  0x21,  0x02,  0x28,  0x24,  0x46,  0x82,  0xA3,  0x20,  0x02,  0x7E,  0x24, 	/* 0AA70 */
+	0x2F,  0xC2,  0x24,  0x22,  0x42,  0x34,  0x2E,  0x42,  0x24,  0x22,  0x42,  0x27,  0xE6,  0x42,  0xA8,  0x20, 	/* 0AA80 */
+	0x02,  0xFE,  0x21,  0x2F,  0x12,  0x25,  0x22,  0x32,  0x31,  0xAE,  0x17,  0x21,  0x22,  0x22,  0x22,  0x26, 	/* 0AA90 */
+	0x4C,  0xAE,  0x22,  0x82,  0x28,  0x22,  0x8F,  0x44,  0x28,  0x22,  0xFD,  0x32,  0x4E,  0x24,  0x22,  0x42, 	/* 0AAA0 */
+	0x44,  0x24,  0x46,  0x98,  0xB1,  0x20,  0x02,  0x7C,  0x22,  0x4F,  0xA8,  0x22,  0xE2,  0x22,  0x35,  0x2E, 	/* 0AAB0 */
+	0x54,  0x24,  0xC2,  0x94,  0x2A,  0x27,  0x41,  0xB6,  0x21,  0x02,  0x10,  0x21,  0x0F,  0xFC,  0x21,  0x02, 	/* 0AAC0 */
+	0x10,  0x3F,  0xEE,  0x10,  0x22,  0x82,  0x28,  0x24,  0x47,  0x82,  0xB9,  0x24,  0x82,  0x48,  0x24,  0x8F, 	/* 0AAD0 */
+	0x4B,  0x27,  0xC2,  0x48,  0x34,  0x8E,  0x48,  0x24,  0x82,  0x49,  0x27,  0x96,  0xC7,  0xBC,  0x40,  0x04, 	/* 0AAE0 */
+	0xFE,  0x48,  0x0F,  0xBC,  0x4A,  0x44,  0xA4,  0x6A,  0x4C,  0xAC,  0x4A,  0x05,  0x22,  0x52,  0x2E,  0x1E, 	/* 0AAF0 */
+	0xBE,  0x22,  0x82,  0x24,  0x22,  0x02,  0xFE,  0xFA,  0x42,  0x24,  0x22,  0x83,  0x98,  0xE1,  0x02,  0x2A, 	/* 0AB00 */
+	0x2C,  0x66,  0x02,  0xBF,  0x00,  0x03,  0xF8,  0x01,  0x00,  0x22,  0xEF,  0x42,  0x48,  0x3F,  0x82,  0x48, 	/* 0AB10 */
+	0x5F,  0x44,  0x44,  0x84,  0x20,  0xC0,  0x80,  0x21,  0x02,  0x10,  0x2F,  0xEF,  0x10,  0x21,  0x02,  0xFC, 	/* 0AB20 */
+	0x30,  0x4E,  0x28,  0x21,  0x82,  0x18,  0x22,  0x46,  0xC2,  0x82,  0x20,  0x02,  0xFE,  0x21,  0x0F,  0x90, 	/* 0AB30 */
+	0x21,  0x02,  0x7C,  0x31,  0x0E,  0x10,  0x21,  0x02,  0x10,  0x21,  0x06,  0xFE,  0x83,  0x21,  0x02,  0x10, 	/* 0AB40 */
+	0x2F,  0xEF,  0x10,  0x21,  0x02,  0x18,  0x31,  0x4E,  0x12,  0x21,  0x02,  0x10,  0x21,  0x06,  0x10,  0x84, 	/* 0AB50 */
+	0x21,  0x02,  0x10,  0x25,  0x8F,  0x54,  0x25,  0x22,  0x96,  0x31,  0x4E,  0x38,  0x20,  0x82,  0x10,  0x26, 	/* 0AB60 */
+	0x07,  0x80,  0x89,  0x22,  0x02,  0x20,  0x22,  0x0F,  0xFC,  0x22,  0x42,  0x24,  0x3F,  0xEE,  0x20,  0x25, 	/* 0AB70 */
+	0x02,  0x48,  0x28,  0x47,  0x02,  0x8A,  0x20,  0x02,  0xFE,  0x29,  0x2F,  0x92,  0x29,  0x22,  0xFE,  0x38, 	/* 0AB80 */
+	0x0E,  0x80,  0x28,  0x02,  0x82,  0x28,  0x26,  0x7E,  0x91,  0x22,  0x02,  0xDE,  0x29,  0x2F,  0x92,  0x29, 	/* 0AB90 */
+	0x22,  0x92,  0x39,  0x2E,  0x92,  0x2F,  0x23,  0x9C,  0x21,  0x06,  0x10,  0x92,  0x20,  0x02,  0x7C,  0x22, 	/* 0ABA0 */
+	0x8F,  0x90,  0x2F,  0xE2,  0x14,  0x31,  0x8E,  0x10,  0x21,  0x02,  0x10,  0x21,  0x06,  0x30,  0x93,  0x20, 	/* 0ABB0 */
+	0x62,  0x7C,  0x25,  0x4F,  0x54,  0x25,  0x42,  0x54,  0x35,  0x4E,  0x54,  0x25,  0x42,  0x52,  0x25,  0x26, 	/* 0ABC0 */
+	0x91,  0x94,  0x20,  0x02,  0xFE,  0x20,  0x8F,  0x90,  0x23,  0x82,  0x54,  0x39,  0x2E,  0x10,  0x21,  0x02, 	/* 0ABD0 */
+	0x10,  0x21,  0x06,  0x10,  0x95,  0x27,  0x82,  0x48,  0x24,  0x8F,  0x4A,  0x28,  0x63,  0x00,  0x2F,  0xCE, 	/* 0ABE0 */
+	0x04,  0x22,  0x82,  0x10,  0x26,  0x87,  0x86,  0x96,  0x20,  0x82,  0x48,  0x22,  0x8F,  0x08,  0x24,  0x82, 	/* 0ABF0 */
+	0x28,  0x30,  0x8E,  0x0E,  0x2F,  0x82,  0x08,  0x20,  0x86,  0x08,  0x97,  0x22,  0x02,  0x20,  0x2F,  0xCF, 	/* 0AC00 */
+	0x00,  0x27,  0x82,  0x48,  0x34,  0x8E,  0x48,  0x24,  0x82,  0x4A,  0x28,  0xA7,  0x06,  0x98,  0x20,  0x42, 	/* 0AC10 */
+	0x78,  0x24,  0x0F,  0x40,  0x27,  0xE2,  0x48,  0x34,  0x8E,  0x48,  0x28,  0x82,  0x88,  0x30,  0x86,  0x08, 	/* 0AC20 */
+	0x9B,  0x48,  0x84,  0x88,  0x48,  0x8E,  0x9E,  0x5E,  0xA4,  0xAA,  0x6A,  0xAC,  0xAA,  0x4B,  0x24,  0xA6, 	/* 0AC30 */
+	0x4A,  0x1D,  0x1F,  0x9C,  0x24,  0x02,  0x40,  0x2F,  0xEF,  0x40,  0x24,  0x02,  0x7C,  0x34,  0x4E,  0x68, 	/* 0AC40 */
+	0x29,  0x82,  0x98,  0x32,  0x46,  0xC2,  0x9E,  0x20,  0x02,  0x7C,  0x24,  0x4F,  0x44,  0x27,  0xC2,  0x50, 	/* 0AC50 */
+	0x35,  0x0E,  0x48,  0x24,  0x82,  0x84,  0x28,  0x47,  0x02,  0xAB,  0x21,  0x02,  0x10,  0x2F,  0xEF,  0x92, 	/* 0AC60 */
+	0x29,  0x42,  0xFC,  0x38,  0x4E,  0xA8,  0x2A,  0x82,  0x90,  0x32,  0x86,  0x46,  0xAC,  0x22,  0x02,  0x20, 	/* 0AC70 */
+	0x22,  0x0F,  0x48,  0x24,  0x42,  0xFE,  0x30,  0x2E,  0x7C,  0x24,  0x42,  0x44,  0x24,  0x46,  0x7C,  0xB1, 	/* 0AC80 */
+	0x24,  0x02,  0x40,  0x27,  0xEF,  0x42,  0x2B,  0xA2,  0x0A,  0x37,  0xAE,  0x44,  0x24,  0x02,  0x42,  0x24, 	/* 0AC90 */
+	0x26,  0x3E,  0xB5,  0x20,  0xC2,  0x70,  0x25,  0x0F,  0x50,  0x25,  0x02,  0x7E,  0x34,  0x8E,  0x48,  0x24, 	/* 0ACA0 */
+	0xA2,  0xE6,  0x20,  0x66,  0xF2,  0xB9,  0x21,  0x02,  0x10,  0x2F,  0xEF,  0x10,  0x21,  0x02,  0x7C,  0x31, 	/* 0ACB0 */
+	0x0E,  0x38,  0x25,  0x42,  0x93,  0x21,  0x06,  0x10,  0xBB,  0x21,  0x02,  0x10,  0x2F,  0xEF,  0x92,  0x29, 	/* 0ACC0 */
+	0x22,  0xFE,  0x39,  0x2E,  0x92,  0x2F,  0xE2,  0x10,  0x21,  0x06,  0x10,  0xBC,  0x20,  0x02,  0xFE,  0x29, 	/* 0ACD0 */
+	0x2F,  0x92,  0x2F,  0xE2,  0x92,  0x39,  0x2E,  0xFE,  0x21,  0x02,  0x10,  0x21,  0x06,  0x10,  0xBD,  0x21, 	/* 0ACE0 */
+	0x02,  0x10,  0x21,  0x0F,  0xFE,  0x29,  0x22,  0x92,  0x39,  0x2E,  0xFE,  0x29,  0x22,  0x92,  0x29,  0x26, 	/* 0ACF0 */
+	0xFE,  0x82,  0x45,  0x05,  0xFC,  0x45,  0x4E,  0x54,  0x5F,  0xC5,  0x50,  0x7F,  0xEC,  0x52,  0x45,  0x24, 	/* 0AD00 */
+	0x92,  0x49,  0xCD,  0x10,  0x85,  0x20,  0x02,  0x7C,  0x24,  0x4F,  0xC4,  0x27,  0xC2,  0x44,  0x34,  0x4E, 	/* 0AD10 */
+	0x44,  0x27,  0xC2,  0x00,  0x20,  0x06,  0xFF,  0x86,  0x20,  0x62,  0x78,  0x24,  0x0F,  0xC0,  0x27,  0xF2, 	/* 0AD20 */
+	0x48,  0x34,  0x8E,  0x58,  0x24,  0xE2,  0x49,  0x28,  0x86,  0x08,  0x87,  0x4F,  0xC4,  0x84,  0x4A,  0x4F, 	/* 0AD30 */
+	0x94,  0x5F,  0xE4,  0x84,  0x6A,  0x4C,  0x94,  0x48,  0x44,  0xFE,  0x48,  0x4C,  0x18,  0x88,  0x21,  0x02, 	/* 0AD40 */
+	0x10,  0x21,  0x0F,  0x9E,  0x21,  0x02,  0x10,  0x31,  0x0E,  0x7E,  0x24,  0x22,  0x42,  0x24,  0x26,  0x7E, 	/* 0AD50 */
+	0x89,  0x21,  0x02,  0x10,  0x21,  0x0F,  0xFE,  0x20,  0x42,  0x84,  0x34,  0x4E,  0x44,  0x22,  0x82,  0x28, 	/* 0AD60 */
+	0x21,  0x06,  0xFE,  0x8A,  0x22,  0x22,  0x22,  0x22,  0x2F,  0x5F,  0x24,  0x22,  0xD2,  0x34,  0xAE,  0x4A, 	/* 0AD70 */
+	0x24,  0x22,  0x42,  0x24,  0x26,  0x46,  0x8C,  0x21,  0x02,  0x54,  0x25,  0x2F,  0x90,  0x2F,  0xE2,  0x10, 	/* 0AD80 */
+	0x31,  0x0E,  0xFE,  0x21,  0x02,  0x10,  0x21,  0x06,  0x10,  0x8D,  0x21,  0x02,  0x10,  0x22,  0x0F,  0x7E, 	/* 0AD90 */
+	0x24,  0x22,  0x42,  0x37,  0xEE,  0x42,  0x24,  0x22,  0x42,  0x24,  0x26,  0x7E,  0x8F,  0x40,  0x0F,  0xFC, 	/* 0ADA0 */
+	0x4A,  0x4F,  0x18,  0x2A,  0x4C,  0x32,  0x1C,  0x07,  0xFC,  0x04,  0x0F,  0xFE,  0x04,  0x00,  0xC0,  0x90, 	/* 0ADB0 */
+	0x20,  0x02,  0x7E,  0x24,  0x2F,  0x42,  0x27,  0xE2,  0x00,  0x3F,  0xEE,  0x12,  0x21,  0x22,  0x22,  0x24, 	/* 0ADC0 */
+	0x26,  0x8C,  0x91,  0x24,  0x42,  0x44,  0x24,  0x4F,  0xFE,  0x24,  0x42,  0x44,  0x34,  0x4E,  0x7C,  0x24, 	/* 0ADD0 */
+	0x42,  0x44,  0x24,  0x46,  0x7C,  0x92,  0x20,  0x02,  0x7E,  0x24,  0x0F,  0x40,  0x27,  0xC2,  0x44,  0x34, 	/* 0ADE0 */
+	0x4E,  0x7C,  0x24,  0x02,  0x40,  0x24,  0x06,  0x7E,  0x93,  0x20,  0x02,  0xFE,  0x22,  0x0F,  0x20,  0x22, 	/* 0ADF0 */
+	0x02,  0x40,  0x37,  0xEE,  0xA2,  0x2A,  0x23,  0x22,  0x22,  0x26,  0x3E,  0x94,  0x22,  0x82,  0x24,  0x22, 	/* 0AE00 */
+	0x02,  0x3E,  0xFE,  0x02,  0x24,  0x21,  0x43,  0x98,  0xE1,  0x02,  0x2A,  0x2C,  0x66,  0x02,  0x97,  0x48, 	/* 0AE10 */
+	0x84,  0x88,  0x50,  0x85,  0x7E,  0xE4,  0xA5,  0x4A,  0x48,  0xA7,  0x4A,  0xD2,  0xA5,  0xEA,  0x73,  0x2C, 	/* 0AE20 */
+	0x26,  0x98,  0x24,  0x02,  0x40,  0x27,  0xEF,  0x42,  0x28,  0x22,  0xBA,  0x32,  0xAE,  0x2A,  0x23,  0xA2, 	/* 0AE30 */
+	0x22,  0x20,  0x26,  0x0C,  0x99,  0x21,  0x02,  0x10,  0x29,  0x2F,  0x92,  0x29,  0x22,  0xFE,  0x31,  0x0E, 	/* 0AE40 */
+	0x92,  0x29,  0x22,  0x92,  0x29,  0x26,  0xFE,  0x9B,  0x20,  0x02,  0xFE,  0x21,  0x2F,  0x12,  0x22,  0x22, 	/* 0AE50 */
+	0x4C,  0x38,  0x0E,  0x7E,  0x24,  0x22,  0x42,  0x24,  0x26,  0x7E,  0x9C,  0x10,  0x0E,  0xFE,  0x21,  0x02, 	/* 0AE60 */
+	0x7C,  0xF9,  0x02,  0x7C,  0x39,  0x0E,  0x10,  0x2F,  0xE4,  0x10,  0x41,  0x08,  0x10,  0x9D,  0x20,  0x02, 	/* 0AE70 */
+	0xFE,  0x21,  0x0F,  0x7C,  0x21,  0x02,  0x7C,  0x31,  0x0E,  0x10,  0x2F,  0xE2,  0x10,  0x21,  0x06,  0x10, 	/* 0AE80 */
+	0xA0,  0x20,  0x02,  0x4E,  0x24,  0xAF,  0x6A,  0x2A,  0xA2,  0xAA,  0x3A,  0xAE,  0x6A,  0x23,  0x22,  0x53, 	/* 0AE90 */
+	0x28,  0x87,  0x07,  0xA1,  0x21,  0x02,  0x10,  0x2F,  0xEF,  0x80,  0x29,  0x02,  0x90,  0x39,  0x0E,  0xA8, 	/* 0AEA0 */
+	0x2A,  0x42,  0xAE,  0x37,  0x26,  0x02,  0xAC,  0x20,  0xC2,  0xF0,  0x21,  0x0F,  0x10,  0x2F,  0xE2,  0x10, 	/* 0AEB0 */
+	0x31,  0x0E,  0x7C,  0x24,  0x42,  0x44,  0x24,  0x46,  0x7C,  0xAD,  0x21,  0x42,  0x12,  0x21,  0x0F,  0xFE, 	/* 0AEC0 */
+	0x21,  0x02,  0xF0,  0x35,  0x0E,  0x48,  0x25,  0xA2,  0x6A,  0x38,  0x66,  0x02,  0xAE,  0x21,  0x02,  0x10, 	/* 0AED0 */
+	0x2F,  0xFF,  0x10,  0x21,  0x02,  0x7E,  0x30,  0x0E,  0x7E,  0x24,  0x22,  0x42,  0x27,  0xE6,  0x40,  0xAF, 	/* 0AEE0 */
+	0x20,  0x02,  0x7C,  0x20,  0x8F,  0x12,  0x2F,  0x22,  0x3C,  0x33,  0x8E,  0x54,  0x29,  0x43,  0x12,  0x23, 	/* 0AEF0 */
+	0x06,  0xFE,  0xB1,  0x24,  0x82,  0x48,  0x24,  0x8F,  0xFE,  0x24,  0x82,  0x48,  0x34,  0x8E,  0xFF,  0x21, 	/* 0AF00 */
+	0x02,  0x48,  0x24,  0x46,  0x84,  0xB3,  0x24,  0x81,  0x50,  0x7F,  0xC0,  0xA0,  0xFF,  0xE2,  0x68,  0xDC, 	/* 0AF10 */
+	0x63,  0xF8,  0x04,  0x07,  0xFC,  0x04,  0x00,  0xC0,  0xB5,  0x22,  0x02,  0x20,  0x2F,  0xEF,  0x20,  0x23, 	/* 0AF20 */
+	0xE2,  0x44,  0x34,  0x8E,  0xFE,  0x38,  0x82,  0x88,  0x28,  0x86,  0x98,  0xB6,  0x22,  0xA2,  0x2A,  0x25, 	/* 0AF30 */
+	0x4F,  0x2A,  0x22,  0xA2,  0x10,  0x31,  0xEE,  0x22,  0x2E,  0x42,  0x18,  0x23,  0x06,  0xC0,  0xB7,  0x22, 	/* 0AF40 */
+	0x02,  0xFC,  0x22,  0x0F,  0x28,  0x3F,  0xE2,  0x60,  0x2B,  0xCF,  0x20,  0x27,  0xC2,  0x44,  0x20,  0x46, 	/* 0AF50 */
+	0x18,  0xBE,  0x21,  0x02,  0x10,  0x22,  0x8F,  0x44,  0x2F,  0xE3,  0x01,  0x30,  0x0E,  0x7C,  0x24,  0x42, 	/* 0AF60 */
+	0x44,  0x24,  0x46,  0x7C,  0xBF,  0x04,  0x00,  0xA0,  0x31,  0x8D,  0xF6,  0x11,  0x01,  0xF0,  0x1C,  0x07, 	/* 0AF70 */
+	0xFC,  0x04,  0x0F,  0xFE,  0x04,  0x00,  0xC0,  0x81,  0x22,  0x02,  0xFC,  0x22,  0x0F,  0x20,  0x2F,  0xE2, 	/* 0AF80 */
+	0x08,  0x3F,  0xEE,  0x88,  0x24,  0x82,  0x08,  0x20,  0x86,  0x18,  0x82,  0x21,  0x02,  0x10,  0x27,  0xCF, 	/* 0AF90 */
+	0x90,  0x21,  0x02,  0xFE,  0x31,  0x0E,  0x10,  0x27,  0xC2,  0x10,  0x21,  0x06,  0xFE,  0x87,  0x28,  0x02, 	/* 0AFA0 */
+	0x8C,  0x2F,  0x0F,  0x82,  0x27,  0xE2,  0x00,  0x3F,  0xCE,  0x84,  0x2F,  0xC2,  0x84,  0x28,  0x46,  0xFC, 	/* 0AFB0 */
+	0x88,  0x14,  0x01,  0xBE,  0x74,  0xA1,  0x8A,  0x75,  0x21,  0xA6,  0xE3,  0x83,  0xFC,  0x02,  0x0F,  0xFE, 	/* 0AFC0 */
+	0x02,  0x00,  0x60,  0x89,  0x21,  0x02,  0xFE,  0x28,  0x2F,  0xA2,  0x22,  0x02,  0xFF,  0x32,  0x4E,  0x24, 	/* 0AFD0 */
+	0x26,  0x42,  0x18,  0x22,  0x46,  0xC2,  0x8C,  0x22,  0x02,  0x3E,  0x24,  0x4F,  0x64,  0x29,  0x82,  0x14, 	/* 0AFE0 */
+	0x32,  0x2E,  0x7D,  0x2A,  0x42,  0x24,  0x22,  0x46,  0x3C,  0x91,  0x22,  0x82,  0x28,  0x22,  0x8F,  0xAA, 	/* 0AFF0 */
+	0x26,  0xC2,  0x28,  0x36,  0xCE,  0xAA,  0x2A,  0xA2,  0x28,  0x24,  0x96,  0x87,  0x99,  0x48,  0x82,  0x48, 	/* 0B000 */
+	0xFF,  0xE1,  0x20,  0x3F,  0x04,  0x88,  0xBF,  0x60,  0x40,  0x7F,  0x80,  0x40,  0x04,  0x01,  0x80,  0x9F, 	/* 0B010 */
+	0x21,  0x02,  0x10,  0x2F,  0xEF,  0x10,  0x25,  0x22,  0x54,  0x3F,  0xEE,  0x10,  0x21,  0x02,  0x28,  0x24, 	/* 0B020 */
+	0x47,  0x82,  0xA7,  0x20,  0x02,  0xFE,  0x22,  0x2F,  0x66,  0x26,  0x62,  0xAA,  0x33,  0x2E,  0x66,  0x2A, 	/* 0B030 */
+	0xA3,  0x32,  0x22,  0x26,  0x66,  0xA8,  0x22,  0x02,  0x28,  0x24,  0x4F,  0x7A,  0x28,  0x22,  0xFC,  0x31, 	/* 0B040 */
+	0x0E,  0xFE,  0x21,  0x02,  0x28,  0x24,  0x46,  0x83,  0xAB,  0x21,  0x02,  0x54,  0x25,  0x4F,  0x54,  0x25, 	/* 0B050 */
+	0x42,  0xBA,  0x39,  0x2E,  0x10,  0x2F,  0xE2,  0x10,  0x21,  0x06,  0xFF,  0xAF,  0x20,  0x02,  0xFE,  0x28, 	/* 0B060 */
+	0x0F,  0xBC,  0x28,  0x02,  0xFE,  0x3B,  0x2E,  0xB4,  0x2A,  0x82,  0xA8,  0x33,  0x46,  0x62,  0xBA,  0x20, 	/* 0B070 */
+	0x22,  0xEC,  0x22,  0x4F,  0x24,  0x24,  0x42,  0xFF,  0x32,  0x4E,  0xA4,  0x2A,  0x42,  0x5F,  0x2B,  0x07, 	/* 0B080 */
+	0x0F,  0xBD,  0x22,  0x02,  0x38,  0x24,  0x8F,  0x90,  0x2F,  0xE2,  0x92,  0x39,  0x2E,  0xFE,  0x22,  0x82, 	/* 0B090 */
+	0x29,  0x24,  0x96,  0x87,  0xBE,  0x21,  0x02,  0x10,  0x2F,  0xEF,  0x10,  0x25,  0x42,  0x54,  0x2B,  0xAF, 	/* 0B0A0 */
+	0x12,  0x22,  0x82,  0x28,  0x24,  0x46,  0x82,  0xBF,  0x20,  0xC2,  0xF0,  0x21,  0x0F,  0xFE,  0x21,  0x02, 	/* 0B0B0 */
+	0xFE,  0x39,  0x2E,  0xFE,  0x29,  0x22,  0xFE,  0x21,  0x06,  0x10,  0x89,  0x20,  0x02,  0xFC,  0x28,  0x4F, 	/* 0B0C0 */
+	0x84,  0x2F,  0xC2,  0x10,  0x39,  0x0E,  0x9E,  0x29,  0x02,  0xD0,  0x33,  0x06,  0x0E,  0x8C,  0x40,  0x25, 	/* 0B0D0 */
+	0xEA,  0x52,  0xAF,  0x2A,  0x5E,  0xA4,  0x8A,  0x6E,  0xAC,  0xAA,  0x4A,  0xA5,  0x22,  0x62,  0x2C,  0xC6, 	/* 0B0E0 */
+	0x8D,  0x27,  0xC2,  0x44,  0x27,  0xCF,  0xC4,  0x27,  0xC2,  0x00,  0x3F,  0xEE,  0x10,  0x21,  0x02,  0xFE, 	/* 0B0F0 */
+	0x21,  0x06,  0x10,  0x8F,  0x20,  0x02,  0xFE,  0x28,  0x2F,  0xFE,  0x28,  0x22,  0xFE,  0x31,  0x0E,  0x10, 	/* 0B100 */
+	0x27,  0xE2,  0x10,  0x21,  0x06,  0xFF,  0x90,  0x27,  0xE2,  0x42,  0x27,  0xEF,  0x80,  0x27,  0xE2,  0x42, 	/* 0B110 */
+	0x37,  0xEE,  0x42,  0x27,  0xE2,  0x42,  0x24,  0x26,  0x46,  0x95,  0x21,  0x42,  0x12,  0x2F,  0xFF,  0x10, 	/* 0B120 */
+	0x2F,  0xE2,  0x92,  0x3F,  0xEE,  0x92,  0x2F,  0xE2,  0x92,  0x29,  0x26,  0x96,  0x97,  0x21,  0x02,  0x50, 	/* 0B130 */
+	0x25,  0xEF,  0x50,  0x2F,  0xE2,  0x10,  0x35,  0x4E,  0x52,  0x2B,  0x62,  0x0A,  0x23,  0x06,  0xC0,  0x9C, 	/* 0B140 */
+	0x21,  0x02,  0xFE,  0x29,  0x2F,  0xFE,  0x29,  0x22,  0xFE,  0x31,  0x0E,  0xFC,  0x24,  0x42,  0x28,  0x23, 	/* 0B150 */
+	0x86,  0xC6,  0xA7,  0x21,  0x02,  0xFE,  0x21,  0x0F,  0x7C,  0x22,  0x82,  0xFE,  0x35,  0x4F,  0xBB,  0x21, 	/* 0B160 */
+	0x02,  0x7C,  0x21,  0x06,  0x10,  0xA8,  0x21,  0x02,  0x10,  0x22,  0x8F,  0xD6,  0x27,  0xC2,  0x10,  0x3F, 	/* 0B170 */
+	0xEE,  0x00,  0x27,  0xC2,  0x44,  0x24,  0x46,  0x7C,  0xA9,  0x2F,  0xE2,  0x00,  0x2F,  0xEF,  0x82,  0x2F, 	/* 0B180 */
+	0xE2,  0x90,  0x39,  0x0E,  0xFE,  0x31,  0x03,  0x28,  0x24,  0x46,  0x82,  0xAB,  0x4E,  0xE4,  0xAA,  0x4E, 	/* 0B190 */
+	0xEF,  0xAA,  0x4E,  0xE4,  0x82,  0x68,  0x2C,  0x82,  0x48,  0x24,  0x82,  0x48,  0x2C,  0x86,  0xAE,  0x20, 	/* 0B1A0 */
+	0x02,  0xFC,  0x28,  0x4F,  0xFC,  0x29,  0x02,  0xFE,  0x39,  0x0E,  0x90,  0x2F,  0xC3,  0x44,  0x34,  0x46, 	/* 0B1B0 */
+	0x7C,  0xB2,  0x29,  0x22,  0x54,  0x27,  0xCF,  0x10,  0x2F,  0xE2,  0x28,  0x34,  0x4E,  0xBB,  0x20,  0x82, 	/* 0B1C0 */
+	0x78,  0x24,  0x46,  0x3C,  0xB6,  0x40,  0xC4,  0xF0,  0x41,  0x0F,  0xFE,  0x45,  0x45,  0xFF,  0x65,  0x4C, 	/* 0B1D0 */
+	0x54,  0x4F,  0xE4,  0x10,  0x41,  0x0D,  0xFE,  0xB7,  0x21,  0x02,  0xFE,  0x21,  0x0F,  0x7C,  0x21,  0x42, 	/* 0B1E0 */
+	0xFE,  0x31,  0x4E,  0x7C,  0x25,  0x02,  0x5E,  0x2B,  0x07,  0x0F,  0xBA,  0x21,  0x02,  0x10,  0x2F,  0xEF, 	/* 0B1F0 */
+	0x28,  0x24,  0x42,  0xBA,  0x30,  0x0E,  0xFC,  0x21,  0x02,  0x54,  0x29,  0x26,  0x30,  0xBB,  0x21,  0x02, 	/* 0B200 */
+	0x28,  0x24,  0x4F,  0xBA,  0x20,  0x02,  0xFE,  0x30,  0x4E,  0x08,  0x23,  0x02,  0xAA,  0x32,  0x26,  0x1E, 	/* 0B210 */
+	0x80,  0x22,  0x82,  0xC8,  0x28,  0xEF,  0xF2,  0x2B,  0x62,  0xA4,  0x3A,  0x4E,  0xA4,  0x2A,  0xC2,  0xAA, 	/* 0B220 */
+	0x33,  0x26,  0x21,  0x83,  0x20,  0x02,  0x7C,  0x20,  0x4F,  0x7C,  0x20,  0x42,  0xFF,  0x39,  0x1E,  0xFF, 	/* 0B230 */
+	0x25,  0x22,  0x52,  0x25,  0x66,  0x10,  0x88,  0x20,  0xC2,  0xF2,  0x25,  0x2F,  0x44,  0x2F,  0xE2,  0x82, 	/* 0B240 */
+	0x37,  0xCE,  0x48,  0x22,  0x82,  0x10,  0x22,  0x86,  0xC6,  0x89,  0x21,  0x02,  0x1E,  0x21,  0x0F,  0xFE, 	/* 0B250 */
+	0x24,  0x22,  0x7E,  0x34,  0x2E,  0x7E,  0x21,  0x02,  0xFF,  0x21,  0x06,  0x10,  0x8C,  0x24,  0x81,  0x50, 	/* 0B260 */
+	0xFF,  0xE9,  0xF2,  0x91,  0x23,  0xF8,  0x04,  0x07,  0xFC,  0x04,  0x0F,  0xFE,  0x04,  0x00,  0xC0,  0x8E, 	/* 0B270 */
+	0x22,  0x03,  0xFC,  0x22,  0x0F,  0x50,  0x28,  0x83,  0xFE,  0x30,  0x4E,  0xF4,  0x29,  0x42,  0xF4,  0x20, 	/* 0B280 */
+	0x46,  0x0C,  0x8F,  0x48,  0x04,  0x80,  0x4F,  0xEE,  0xC2,  0x57,  0xA6,  0xA2,  0x4F,  0xA6,  0x22,  0xCA, 	/* 0B290 */
+	0xA4,  0xFA,  0x40,  0x2C,  0x0C,  0x92,  0x22,  0x82,  0x28,  0x2E,  0xEF,  0x28,  0x22,  0x82,  0xEE,  0x32, 	/* 0B2A0 */
+	0x8E,  0x28,  0x3E,  0xF2,  0x48,  0x24,  0x86,  0x88,  0x96,  0x21,  0x02,  0xFE,  0x22,  0x8F,  0x2E,  0x24, 	/* 0B2B0 */
+	0xA2,  0x56,  0x3E,  0xAE,  0x4C,  0x24,  0x42,  0x4A,  0x25,  0x26,  0x61,  0x98,  0x20,  0x02,  0xFE,  0x28, 	/* 0B2C0 */
+	0x2F,  0xFE,  0x28,  0x82,  0xAA,  0x3A,  0xAE,  0xBE,  0x28,  0x82,  0xCA,  0x34,  0xA6,  0x7E,  0x9B,  0x22, 	/* 0B2D0 */
+	0x42,  0x24,  0x2F,  0x4F,  0x24,  0x2F,  0xC2,  0x26,  0x32,  0x5E,  0xF5,  0x22,  0x42,  0x34,  0x2C,  0x46, 	/* 0B2E0 */
+	0x04,  0x9F,  0x41,  0x05,  0xFE,  0x50,  0x2F,  0x02,  0x4F,  0xC4,  0x10,  0x69,  0x0C,  0x9C,  0x49,  0x04, 	/* 0B2F0 */
+	0xD0,  0x53,  0x0E,  0x0E,  0xA0,  0x21,  0x02,  0xFE,  0x20,  0x0F,  0x7C,  0x24,  0x42,  0x44,  0x37,  0xCE, 	/* 0B300 */
+	0x10,  0x25,  0x42,  0x52,  0x29,  0x26,  0x30,  0xA1,  0x20,  0xE2,  0xF2,  0x29,  0x2F,  0x54,  0x24,  0x82, 	/* 0B310 */
+	0x10,  0x3F,  0xEE,  0x38,  0x25,  0x42,  0x92,  0x31,  0x16,  0x10,  0xA2,  0x20,  0x02,  0xFE,  0x2A,  0xAF, 	/* 0B320 */
+	0x28,  0x2C,  0xE2,  0x10,  0x3F,  0xEE,  0x10,  0x23,  0x82,  0x54,  0x29,  0x36,  0x10,  0xA3,  0x50,  0x27, 	/* 0B330 */
+	0xD2,  0x91,  0x27,  0xD2,  0x54,  0x25,  0x46,  0x07,  0x83,  0xFC,  0x02,  0x0F,  0xFE,  0x02,  0x00,  0x60, 	/* 0B340 */
+	0xA5,  0x21,  0x02,  0xFE,  0x24,  0x4F,  0x28,  0x2F,  0xF2,  0x10,  0x3F,  0xFE,  0x24,  0x22,  0x42,  0x78, 	/* 0B350 */
+	0x21,  0x46,  0xE2,  0xA7,  0x21,  0x02,  0x10,  0x2F,  0xEF,  0xAA,  0x22,  0x82,  0xC6,  0x30,  0x0E,  0x7E, 	/* 0B360 */
+	0x21,  0x02,  0x10,  0x21,  0x06,  0xFE,  0xA8,  0x22,  0x42,  0x28,  0x27,  0xEF,  0x48,  0x2C,  0x82,  0x7C, 	/* 0B370 */
+	0x34,  0x8E,  0x48,  0x27,  0xC2,  0x48,  0x24,  0x86,  0x7E,  0xA9,  0x21,  0x02,  0x10,  0x2F,  0xFF,  0x54, 	/* 0B380 */
+	0x29,  0x23,  0x7D,  0x35,  0x4E,  0x7C,  0x25,  0x42,  0x7C,  0x21,  0x16,  0x0F,  0xAA,  0x24,  0x82,  0x48, 	/* 0B390 */
+	0x2F,  0xCF,  0x48,  0x3F,  0xE2,  0x00,  0x3F,  0xCE,  0x84,  0x2F,  0xC2,  0x84,  0x28,  0x46,  0xFC,  0xAB, 	/* 0B3A0 */
+	0x20,  0x03,  0xFE,  0x2A,  0x0F,  0xBE,  0x2E,  0x22,  0xAA,  0x3E,  0xCE,  0xA4,  0x2A,  0x42,  0xEA,  0x33, 	/* 0B3B0 */
+	0x26,  0x21,  0xAC,  0x24,  0x02,  0x40,  0x27,  0xEF,  0xA2,  0x2A,  0xA2,  0x72,  0x3F,  0xAE,  0x22,  0x27, 	/* 0B3C0 */
+	0x22,  0xAA,  0x22,  0x26,  0x2C,  0xB2,  0x27,  0xC2,  0x44,  0x27,  0xCF,  0x44,  0x27,  0xC2,  0x20,  0x37, 	/* 0B3D0 */
+	0xEE,  0xC2,  0x37,  0xA2,  0x42,  0x23,  0xA6,  0x0C,  0xB4,  0x20,  0x02,  0xFE,  0x28,  0x2F,  0xFE,  0x29, 	/* 0B3E0 */
+	0x22,  0x92,  0x3F,  0xEE,  0x9A,  0x29,  0x62,  0xFE,  0x28,  0x26,  0xFE,  0xB5,  0x42,  0x04,  0x20,  0x43, 	/* 0B3F0 */
+	0x0F,  0x48,  0x4F,  0xC5,  0x02,  0x7D,  0xDD,  0x54,  0x55,  0x45,  0xDC,  0x41,  0x0C,  0x10,  0xBB,  0x20, 	/* 0B400 */
+	0x02,  0xFC,  0x24,  0x4F,  0x38,  0x2C,  0x62,  0x10,  0x3F,  0xEE,  0x92,  0x2F,  0xE2,  0x14,  0x21,  0xE6, 	/* 0B410 */
+	0xF2,  0xBE,  0x23,  0xC2,  0x44,  0x2F,  0x82,  0x08,  0xFF,  0xE2,  0x10,  0x26,  0xA3,  0x9C,  0xE6,  0xA2, 	/* 0B420 */
+	0x19,  0x26,  0x86,  0x10,  0x80,  0x21,  0x03,  0xFE,  0x21,  0x0F,  0xFE,  0x29,  0x22,  0xD6,  0x3B,  0xAE, 	/* 0B430 */
+	0xFE,  0x23,  0x82,  0x54,  0x29,  0x36,  0x10,  0x83,  0x48,  0x84,  0x50,  0x5F,  0xEE,  0x00,  0x5E,  0xA5, 	/* 0B440 */
+	0x2A,  0x7E,  0xAD,  0x2A,  0x5E,  0xA5,  0x2A,  0x52,  0x2D,  0x66,  0x84,  0x21,  0x02,  0x28,  0x24,  0x6F, 	/* 0B450 */
+	0xB8,  0x20,  0x02,  0xEA,  0x3A,  0xAE,  0xF4,  0x2B,  0x42,  0xEA,  0x2A,  0xA6,  0xAA,  0x86,  0x2E,  0x42, 	/* 0B460 */
+	0x28,  0x2F,  0x2F,  0x4C,  0x28,  0x43,  0x7E,  0x21,  0x1E,  0xFE,  0x21,  0x02,  0x28,  0x24,  0x47,  0x82, 	/* 0B470 */
+	0x89,  0x27,  0xC2,  0x48,  0x23,  0x0F,  0xFE,  0x23,  0x42,  0x50,  0x3B,  0x0E,  0xFE,  0x23,  0x82,  0x54, 	/* 0B480 */
+	0x29,  0x26,  0x10,  0x8F,  0x24,  0x42,  0xFE,  0x22,  0x4F,  0x24,  0x20,  0x02,  0xFE,  0x39,  0x2E,  0x92, 	/* 0B490 */
+	0x2F,  0xE2,  0x92,  0x29,  0x26,  0xFE,  0x90,  0x20,  0x02,  0x7C,  0x24,  0x4F,  0x7C,  0x24,  0x43,  0xFE, 	/* 0B4A0 */
+	0x21,  0x0E,  0x50,  0x25,  0xC2,  0xD0,  0x33,  0x06,  0x0F,  0x92,  0x20,  0xC2,  0xF0,  0x21,  0x0F,  0xFE, 	/* 0B4B0 */
+	0x21,  0x02,  0xD6,  0x39,  0x2E,  0x92,  0x2D,  0x62,  0x92,  0x29,  0x26,  0xFE,  0x96,  0x27,  0xC2,  0x44, 	/* 0B4C0 */
+	0x27,  0xCF,  0x00,  0x2F,  0xE2,  0x44,  0x37,  0xCE,  0x44,  0x27,  0xC2,  0x44,  0x2F,  0xC6,  0x04,  0x9A, 	/* 0B4D0 */
+	0x20,  0x02,  0x7C,  0x24,  0x4F,  0x7C,  0x24,  0x42,  0xFF,  0x34,  0x0E,  0xFE,  0x32,  0xA2,  0xD2,  0x22, 	/* 0B4E0 */
+	0x26,  0xCC,  0x9B,  0x22,  0x02,  0x3C,  0x24,  0x8F,  0xFE,  0x2A,  0xA2,  0xAA,  0x3C,  0xEE,  0x92,  0x3F, 	/* 0B4F0 */
+	0xF2,  0x18,  0x22,  0x46,  0xC3,  0xA1,  0x40,  0x05,  0xFC,  0x50,  0x4F,  0xFC,  0x50,  0x05,  0xFE,  0x72, 	/* 0B500 */
+	0xCD,  0xFA,  0x51,  0x05,  0x7C,  0x61,  0x0D,  0xFE,  0xA3,  0x21,  0x02,  0x92,  0x29,  0x2F,  0xFE,  0x20, 	/* 0B510 */
+	0x02,  0xFE,  0x32,  0x0E,  0xFE,  0x2A,  0xA2,  0xAA,  0x2A,  0xA6,  0x86,  0xA9,  0x24,  0x82,  0x49,  0x27, 	/* 0B520 */
+	0xEF,  0x48,  0x24,  0x92,  0xF7,  0x30,  0x8E,  0x7E,  0x24,  0x22,  0x7E,  0x24,  0x26,  0x7E,  0xAE,  0x20, 	/* 0B530 */
+	0x02,  0xFE,  0x29,  0x2F,  0x7C,  0x21,  0x02,  0xFE,  0x39,  0x2E,  0xFE,  0x21,  0x02,  0xFF,  0x21,  0x06, 	/* 0B540 */
+	0x10,  0xB4,  0x20,  0xE2,  0xF4,  0x2A,  0x4F,  0x58,  0x2F,  0xC2,  0x40,  0x3F,  0xEE,  0x40,  0x2F,  0xC2, 	/* 0B550 */
+	0xA4,  0x31,  0x86,  0xE6,  0xB6,  0x40,  0x05,  0xFE,  0x4A,  0xAF,  0xAA,  0x4E,  0xC4,  0xAA,  0x6E,  0xAC, 	/* 0B560 */
+	0xAA,  0x4A,  0xA4,  0xEC,  0x5A,  0x8C,  0x28,  0xBA,  0x20,  0xE2,  0xF2,  0x29,  0x2F,  0x54,  0x2F,  0xE2, 	/* 0B570 */
+	0x10,  0x3F,  0xEE,  0x10,  0x29,  0x22,  0x92,  0x29,  0x26,  0xFE,  0x86,  0x24,  0x82,  0xFC,  0x24,  0x8F, 	/* 0B580 */
+	0xFE,  0x21,  0x02,  0xFC,  0x39,  0x4E,  0xFC,  0x29,  0x43,  0xFE,  0x28,  0x46,  0x8C,  0x8D,  0x2F,  0xC2, 	/* 0B590 */
+	0x84,  0x2F,  0xCF,  0x00,  0x2F,  0xC2,  0x84,  0x3F,  0xCE,  0xFC,  0x28,  0x42,  0xFC,  0x24,  0xC7,  0x82, 	/* 0B5A0 */
+	0x8F,  0x21,  0x42,  0xFE,  0x25,  0x4F,  0x7C,  0x25,  0x42,  0x7C,  0x35,  0x4E,  0x08,  0x3F,  0xE2,  0x88, 	/* 0B5B0 */
+	0x24,  0x86,  0x18,  0x93,  0x24,  0x42,  0x28,  0x2F,  0xEF,  0x10,  0x27,  0xC2,  0x10,  0x3F,  0xFE,  0x40, 	/* 0B5C0 */
+	0x27,  0xC2,  0x90,  0x31,  0x06,  0xFE,  0x96,  0x21,  0xE2,  0x32,  0x2E,  0xCF,  0x18,  0x2E,  0x02,  0x40, 	/* 0B5D0 */
+	0x37,  0xEE,  0x90,  0x3F,  0xE2,  0x10,  0x29,  0x26,  0xFE,  0x97,  0x21,  0x02,  0x7C,  0x24,  0x4F,  0xFC, 	/* 0B5E0 */
+	0x24,  0x42,  0x7E,  0x34,  0x0E,  0x7E,  0x22,  0x22,  0xAA,  0x2F,  0xA6,  0x0C,  0x9C,  0x22,  0x02,  0xD6, 	/* 0B5F0 */
+	0x29,  0x2F,  0xD6,  0x29,  0x22,  0xFE,  0x31,  0x0E,  0xFE,  0x24,  0x82,  0x30,  0x22,  0x86,  0xC4,  0xA6, 	/* 0B600 */
+	0x20,  0x02,  0xEE,  0x22,  0x2F,  0xEE,  0x28,  0x82,  0xEE,  0x36,  0x6E,  0xAA,  0x26,  0x62,  0xAA,  0x22, 	/* 0B610 */
+	0x26,  0xCC,  0xA8,  0x27,  0xC2,  0x44,  0x27,  0xCF,  0x44,  0x27,  0xC2,  0x00,  0x3F,  0xEE,  0x66,  0x2A, 	/* 0B620 */
+	0xA2,  0x66,  0x2A,  0xA6,  0xCC,  0xAC,  0x49,  0xC5,  0xD4,  0x55,  0x4F,  0xD4,  0x56,  0x65,  0xC0,  0x77, 	/* 0B630 */
+	0xCD,  0xD4,  0x55,  0x45,  0x48,  0x65,  0x4C,  0x62,  0xAD,  0x24,  0x83,  0xFE,  0x24,  0x8F,  0x30,  0x24, 	/* 0B640 */
+	0x82,  0x84,  0x37,  0xAE,  0x00,  0x2F,  0xC2,  0x84,  0x28,  0x46,  0xFC,  0xB4,  0x04,  0x0F,  0xFE,  0x91, 	/* 0B650 */
+	0x23,  0xF8,  0x11,  0x0F,  0xFF,  0x11,  0x02,  0xE8,  0xC4,  0x63,  0xF8,  0x04,  0x00,  0xC0,  0xB6,  0x21, 	/* 0B660 */
+	0x02,  0x18,  0x22,  0x4F,  0x7A,  0x2C,  0x52,  0x7C,  0x34,  0x4E,  0x7C,  0x28,  0x02,  0xFC,  0x34,  0x46, 	/* 0B670 */
+	0x7C,  0xBA,  0x24,  0x42,  0x7E,  0x2C,  0x8F,  0x7E,  0x24,  0x82,  0x7E,  0x34,  0x8E,  0xFE,  0x22,  0x42, 	/* 0B680 */
+	0x26,  0x24,  0x26,  0x8C,  0xBE,  0x20,  0x82,  0xFF,  0x29,  0x5F,  0x14,  0x26,  0x72,  0x40,  0x37,  0xFE, 	/* 0B690 */
+	0x50,  0x25,  0xE2,  0x90,  0x21,  0xE6,  0x10,  0x82,  0x2F,  0xE2,  0x44,  0x27,  0xCF,  0x44,  0x27,  0xC2, 	/* 0B6A0 */
+	0x44,  0x3F,  0xFE,  0x84,  0x24,  0x82,  0x00,  0x2C,  0xC7,  0x02,  0x8E,  0x20,  0x02,  0xFE,  0x26,  0x6F, 	/* 0B6B0 */
+	0xAA,  0x26,  0x62,  0xAA,  0x31,  0x8E,  0x66,  0x39,  0x92,  0x64,  0x21,  0x86,  0xE0,  0x98,  0x21,  0x02, 	/* 0B6C0 */
+	0xFE,  0x24,  0x4F,  0x28,  0x2F,  0xE2,  0x92,  0x3B,  0xAE,  0x92,  0x2B,  0xA2,  0xAA,  0x2B,  0xA6,  0x86, 	/* 0B6D0 */
+	0xA7,  0x21,  0x02,  0x92,  0x2F,  0xEF,  0x48,  0x25,  0x02,  0xFE,  0x39,  0x0E,  0xFC,  0x29,  0x02,  0xFC, 	/* 0B6E0 */
+	0x29,  0x06,  0xFE,  0xA9,  0x04,  0x07,  0xFE,  0x48,  0x87,  0xFE,  0x5D,  0xC6,  0xAA,  0x48,  0x85,  0xF8, 	/* 0B6F0 */
+	0x42,  0x0B,  0xFE,  0x82,  0x00,  0xC0,  0xAF,  0x21,  0x0F,  0x90,  0x27,  0xCF,  0x94,  0x51,  0x5F,  0xA5, 	/* 0B700 */
+	0x27,  0x33,  0xF8,  0x02,  0x0F,  0xFE,  0x02,  0x00,  0x60,  0xB6,  0x21,  0x42,  0xFF,  0x25,  0x2F,  0x7E, 	/* 0B710 */
+	0x25,  0x22,  0xFE,  0x30,  0xAE,  0xFE,  0x20,  0x42,  0xFE,  0x22,  0x46,  0x0C,  0xB8,  0x22,  0x82,  0xFE, 	/* 0B720 */
+	0x22,  0x8F,  0x7C,  0x24,  0x42,  0x7C,  0x37,  0xCE,  0x10,  0x2F,  0xE2,  0x30,  0x24,  0x87,  0x86,  0xBA, 	/* 0B730 */
+	0x20,  0x03,  0xFE,  0x2A,  0xAF,  0x66,  0x2B,  0xA2,  0x66,  0x32,  0x0E,  0x7C,  0x24,  0x42,  0x7C,  0x24, 	/* 0B740 */
+	0x46,  0x7C,  0x83,  0x11,  0xCF,  0xD4,  0x55,  0x57,  0xFF,  0x55,  0x4F,  0xDC,  0x12,  0x33,  0xF8,  0x02, 	/* 0B750 */
+	0x0F,  0xFE,  0x02,  0x00,  0x60,  0x88,  0x22,  0x82,  0xAA,  0x25,  0x4F,  0xFE,  0x29,  0x22,  0x92,  0x2F, 	/* 0B760 */
+	0xCE,  0x14,  0x22,  0x42,  0x24,  0x24,  0x46,  0x98,  0x92,  0x4A,  0x84,  0xA8,  0x5F,  0xFE,  0xAA,  0x5F, 	/* 0B770 */
+	0xA4,  0xB2,  0x6E,  0xAC,  0xA4,  0x4E,  0x44,  0xAA,  0x4B,  0x2C,  0xA1,  0x93,  0x21,  0x02,  0x7C,  0x21, 	/* 0B780 */
+	0x0F,  0xFE,  0x24,  0x42,  0xFE,  0x34,  0x4E,  0xFE,  0x27,  0xC2,  0x28,  0x24,  0xA6,  0x86,  0x95,  0x54, 	/* 0B790 */
+	0x25,  0x5C,  0x7F,  0x0F,  0x50,  0x5D,  0xE5,  0x54,  0x7D,  0x4D,  0x54,  0x7F,  0x44,  0xD4,  0x52,  0x4E, 	/* 0B7A0 */
+	0x44,  0x9A,  0x48,  0x84,  0xEC,  0x4A,  0xAE,  0xBE,  0x56,  0x84,  0x48,  0x69,  0x4D,  0x22,  0x40,  0x05, 	/* 0B7B0 */
+	0x54,  0x52,  0xAE,  0x2A,  0x9E,  0x21,  0x02,  0xFC,  0x24,  0x8F,  0xFE,  0x20,  0x02,  0x7C,  0x35,  0x4E, 	/* 0B7C0 */
+	0x7C,  0x25,  0x42,  0xFE,  0x21,  0x07,  0xFF,  0xA4,  0x44,  0x85,  0xE8,  0x4A,  0xFF,  0xF2,  0x41,  0x25, 	/* 0B7D0 */
+	0xEA,  0x72,  0xAD,  0xE4,  0x52,  0x45,  0xEA,  0x52,  0xAD,  0x71,  0xA5,  0x2F,  0x42,  0x28,  0x2E,  0xAF, 	/* 0B7E0 */
+	0x44,  0x2F,  0xE3,  0x35,  0x2E,  0x6E,  0x9C,  0x2F,  0x42,  0x28,  0x23,  0x46,  0xD2,  0xA9,  0x21,  0x02, 	/* 0B7F0 */
+	0xFE,  0x2A,  0xAF,  0x7C,  0x2C,  0x62,  0x7C,  0x34,  0x4E,  0x7C,  0x21,  0x02,  0x54,  0x29,  0x26,  0x30, 	/* 0B800 */
+	0xAB,  0x48,  0x04,  0xFF,  0x5A,  0xAF,  0xAA,  0x5F,  0xF4,  0xAA,  0x6A,  0xAD,  0xFF,  0x40,  0x04,  0xAA, 	/* 0B810 */
+	0x4A,  0x9D,  0x25,  0xAD,  0x21,  0xC2,  0xE4,  0x2A,  0x8F,  0xFE,  0x27,  0x02,  0xA8,  0x32,  0x4E,  0xFE, 	/* 0B820 */
+	0x2A,  0x52,  0xFC,  0x2A,  0x46,  0xFC,  0xAE,  0x27,  0xC2,  0x44,  0x27,  0xCF,  0x44,  0x3F,  0xE2,  0xA0, 	/* 0B830 */
+	0x2F,  0xEF,  0xAA,  0x2E,  0xA2,  0xA4,  0x2E,  0xA6,  0x32,  0xB0,  0x2E,  0xE2,  0x22,  0x2E,  0xEF,  0x88, 	/* 0B840 */
+	0x2E,  0xE2,  0x48,  0x3F,  0xCE,  0x48,  0x24,  0x83,  0xFE,  0x24,  0x87,  0x84,  0xB2,  0x45,  0x05,  0x54, 	/* 0B850 */
+	0x7F,  0xEE,  0x50,  0x5F,  0xC4,  0x20,  0x6F,  0xCC,  0x20,  0x5F,  0xE4,  0x30,  0x44,  0x8D,  0x86,  0xB9, 	/* 0B860 */
+	0x2A,  0x22,  0x54,  0x2F,  0xEF,  0x82,  0x27,  0xC2,  0x44,  0x37,  0xCE,  0x44,  0x27,  0xC2,  0x28,  0x24, 	/* 0B870 */
+	0xA6,  0x86,  0xBB,  0x28,  0x82,  0x7E,  0x20,  0x8F,  0x7E,  0x2A,  0x22,  0x14,  0x3F,  0xEE,  0x88,  0x2B, 	/* 0B880 */
+	0xE2,  0x88,  0x34,  0x86,  0x3F,  0xBC,  0x20,  0xA2,  0xFE,  0x28,  0x8F,  0xFA,  0x28,  0xA2,  0xF4,  0x35, 	/* 0B890 */
+	0x5E,  0x7B,  0x29,  0x12,  0xAA,  0x32,  0x26,  0x1E,  0x81,  0x41,  0x05,  0xFE,  0x49,  0x4E,  0x94,  0x57, 	/* 0B8A0 */
+	0xE5,  0x68,  0x6B,  0xED,  0x68,  0x7F,  0xE4,  0xA8,  0x52,  0x8E,  0x3E,  0x82,  0x27,  0xC2,  0x10,  0x2F, 	/* 0B8B0 */
+	0xEF,  0xDA,  0x2B,  0x62,  0x92,  0x30,  0x0E,  0xFE,  0x29,  0x22,  0xFE,  0x29,  0x26,  0xFE,  0x85,  0x22, 	/* 0B8C0 */
+	0x03,  0xFE,  0x2D,  0x42,  0xF4,  0xF8,  0x42,  0xFC,  0x24,  0x83,  0x78,  0xE4,  0x82,  0x78,  0x20,  0x06, 	/* 0B8D0 */
+	0xFE,  0x87,  0x2F,  0xE2,  0xAA,  0x2F,  0xEF,  0x7C,  0x21,  0x02,  0xFE,  0x24,  0x83,  0xFE,  0xE1,  0x02, 	/* 0B8E0 */
+	0xFC,  0x21,  0x06,  0x10,  0x8D,  0x27,  0xC2,  0x44,  0x27,  0xCF,  0xEE,  0x2A,  0xA2,  0xEE,  0x31,  0x0E, 	/* 0B8F0 */
+	0xFE,  0x23,  0x82,  0x54,  0x29,  0x26,  0x10,  0x92,  0x22,  0x02,  0x70,  0x2A,  0x8F,  0xFC,  0x2A,  0x22, 	/* 0B900 */
+	0xD4,  0x3F,  0xCE,  0x20,  0x2F,  0xE2,  0xAA,  0x2F,  0xA6,  0x86,  0x94,  0x23,  0xC2,  0x48,  0x2F,  0xFF, 	/* 0B910 */
+	0x94,  0x2E,  0x72,  0x9C,  0x38,  0x0E,  0xFF,  0x28,  0x02,  0xBE,  0x2A,  0x27,  0x3E,  0x98,  0x78,  0x84, 	/* 0B920 */
+	0xBE,  0x79,  0x44,  0x7E,  0x78,  0x84,  0xBE,  0xB9,  0x81,  0xE0,  0x02,  0x0F,  0xFE,  0x02,  0x00,  0x60, 	/* 0B930 */
+	0x9A,  0x23,  0xC2,  0x20,  0x2F,  0xEF,  0xBA,  0x2D,  0xE2,  0x80,  0x3F,  0xEE,  0x9A,  0x2A,  0xC2,  0xDA, 	/* 0B940 */
+	0x32,  0x96,  0x58,  0xA0,  0x21,  0x02,  0xFE,  0x22,  0x8F,  0xEA,  0x2B,  0xC2,  0xB4,  0x35,  0x2E,  0x7C, 	/* 0B950 */
+	0x24,  0x42,  0x7C,  0x24,  0x46,  0x84,  0xA1,  0x21,  0x02,  0xFE,  0x24,  0x4F,  0xFE,  0x28,  0x22,  0x7C, 	/* 0B960 */
+	0x32,  0x4E,  0xFA,  0x21,  0x22,  0x7C,  0x21,  0x06,  0xFE,  0xA2,  0x2F,  0xE2,  0x22,  0x2E,  0xEF,  0x22, 	/* 0B970 */
+	0x2E,  0xE2,  0x48,  0x3F,  0xEE,  0x90,  0x2F,  0xC2,  0xFC,  0x29,  0x06,  0xFE,  0xA3,  0x21,  0x02,  0xFE, 	/* 0B980 */
+	0x21,  0x0F,  0x7E,  0x20,  0x22,  0x7C,  0x31,  0x0F,  0xFE,  0x2E,  0x42,  0xB4,  0x2E,  0x46,  0x0C,  0xA6, 	/* 0B990 */
+	0x41,  0x05,  0xFE,  0x50,  0x2E,  0xEE,  0x5A,  0xA4,  0x44,  0x6B,  0xAD,  0x00,  0x5F,  0xE4,  0x94,  0x51, 	/* 0B9A0 */
+	0x2C,  0x30,  0xA7,  0x18,  0x06,  0xEC,  0x48,  0x46,  0x6C,  0x4A,  0x4F,  0xFE,  0x11,  0x82,  0xF4,  0xC2, 	/* 0B9B0 */
+	0x27,  0xFE,  0x02,  0x00,  0x60,  0xAC,  0x51,  0xE5,  0xE2,  0x51,  0x4F,  0x28,  0x4F,  0xE5,  0x0A,  0x5E, 	/* 0B9C0 */
+	0xCF,  0x48,  0x5E,  0xE4,  0x68,  0x4B,  0x8D,  0x26,  0xAF,  0x21,  0x02,  0xFE,  0x29,  0x2F,  0x54,  0x2B, 	/* 0B9D0 */
+	0x82,  0xFC,  0x34,  0x4E,  0x7C,  0x24,  0x42,  0x7C,  0x22,  0x46,  0xC2,  0xB1,  0x5D,  0xE5,  0x52,  0x5D, 	/* 0B9E0 */
+	0xEF,  0x52,  0x5F,  0xE5,  0x52,  0x7B,  0x2D,  0x4A,  0x5F,  0x65,  0x52,  0x57,  0x2D,  0x06,  0xB2,  0x44, 	/* 0B9F0 */
+	0x04,  0xFC,  0x55,  0x4F,  0xF4,  0x55,  0x85,  0xB4,  0x7F,  0x2C,  0x92,  0x7F,  0x24,  0xDC,  0x53,  0x0E, 	/* 0BA00 */
+	0x10,  0xB4,  0x41,  0x05,  0xFE,  0x52,  0x8F,  0x7C,  0x52,  0x85,  0xFE,  0x55,  0x47,  0x7C,  0xD5,  0x45, 	/* 0BA10 */
+	0x7C,  0x62,  0x4C,  0xC2,  0xB6,  0x28,  0x82,  0xEE,  0x35,  0x4F,  0x28,  0x2F,  0xE2,  0x00,  0x3E,  0xAE, 	/* 0BA20 */
+	0xAA,  0x2E,  0xA2,  0xAA,  0x2E,  0x26,  0xA6,  0xBA,  0x5F,  0xE5,  0x4A,  0x5F,  0xEE,  0x90,  0x55,  0x25, 	/* 0BA30 */
+	0xFC,  0x75,  0x2D,  0xCE,  0x55,  0x25,  0xFC,  0x55,  0x2D,  0x4E,  0xBD,  0x52,  0x45,  0x74,  0x6D,  0xAF, 	/* 0BA40 */
+	0x74,  0x55,  0x86,  0xDA,  0x7F,  0xEC,  0x20,  0x5F,  0xE4,  0x68,  0x4A,  0x4C,  0x20,  0xBE,  0x5F,  0xE4, 	/* 0BA50 */
+	0x20,  0x47,  0x8E,  0x48,  0x5F,  0xE5,  0x6A,  0x6B,  0x4D,  0x7A,  0x4C,  0x85,  0x30,  0x46,  0x8D,  0x86, 	/* 0BA60 */
+	0x80,  0x2A,  0x8F,  0x5E,  0x6A,  0xCA,  0x5A,  0x2A,  0x8F,  0xFE,  0x11,  0x02,  0xE8,  0xC4,  0x63,  0xF8, 	/* 0BA70 */
+	0x04,  0x00,  0xC0,  0x85,  0x24,  0x42,  0xFE,  0x24,  0x4F,  0xFE,  0x2A,  0xA2,  0x7D,  0x34,  0x4E,  0x7C, 	/* 0BA80 */
+	0x24,  0x42,  0x7C,  0x22,  0x46,  0xC2,  0x98,  0x21,  0x03,  0xFE,  0x2A,  0xAF,  0xEE,  0x22,  0x82,  0xFE, 	/* 0BA90 */
+	0x32,  0x8E,  0xFE,  0x26,  0x23,  0xD4,  0x26,  0x86,  0xC6,  0x9C,  0x29,  0x22,  0xFE,  0x24,  0x8F,  0x7C, 	/* 0BAA0 */
+	0x2C,  0x82,  0x7C,  0x34,  0x8E,  0xFE,  0x2B,  0xA2,  0xEE,  0x2B,  0xA6,  0x86,  0x9D,  0x2F,  0xE2,  0x44, 	/* 0BAB0 */
+	0x27,  0xCF,  0x44,  0x2F,  0xE2,  0x04,  0x3F,  0xFE,  0xAA,  0x2E,  0xE2,  0xAA,  0x2F,  0xF6,  0x22,  0xA3, 	/* 0BAC0 */
+	0x44,  0x8A,  0xF4,  0x50,  0xAF,  0xFE,  0x6E,  0xCB,  0xBA,  0x2E,  0xC7,  0xF0,  0x04,  0x0F,  0xFE,  0x04, 	/* 0BAD0 */
+	0x00,  0xC0,  0xA4,  0x54,  0xA7,  0xF4,  0x55,  0xEF,  0xF4,  0x5B,  0x45,  0xFE,  0x69,  0x4D,  0xF4,  0x49, 	/* 0BAE0 */
+	0xE5,  0xF4,  0x55,  0x4E,  0x1E,  0xAA,  0x22,  0xC2,  0x54,  0x26,  0x4F,  0xFE,  0x28,  0x22,  0x7C,  0x34, 	/* 0BAF0 */
+	0x4E,  0x7C,  0x24,  0x42,  0x7C,  0x22,  0xA6,  0xC6,  0xAB,  0x2E,  0xE2,  0xAA,  0x2E,  0xE7,  0xAA,  0x6F, 	/* 0BB00 */
+	0xEA,  0x48,  0xAF,  0xE3,  0x48,  0x27,  0xE2,  0x24,  0x21,  0x82,  0xE6,  0xAC,  0x2E,  0x82,  0xAE,  0x2F, 	/* 0BB10 */
+	0x0F,  0xAE,  0x2E,  0xA2,  0x7E,  0x34,  0x4E,  0x7C,  0x24,  0x42,  0x7C,  0x22,  0xA6,  0xC6,  0xAF,  0x02, 	/* 0BB20 */
+	0x07,  0xFE,  0x02,  0x00,  0x20,  0x3F,  0x80,  0x88,  0x08,  0x80,  0x50,  0x02,  0x00,  0x50,  0x18,  0x86, 	/* 0BB30 */
+	0x06,  0xB4,  0x04,  0x00,  0x40,  0x07,  0xE0,  0x40,  0x04,  0x07,  0xF8,  0x11,  0x01,  0x10,  0x0A,  0x00, 	/* 0BB40 */
+	0x60,  0x19,  0x8E,  0x06,  0xB5,  0x08,  0x00,  0x80,  0x08,  0x01,  0xFE,  0x10,  0x82,  0x88,  0x49,  0x00, 	/* 0BB50 */
+	0x50,  0x02,  0x00,  0x50,  0x18,  0x8E,  0x06,  0xB6,  0x12,  0x01,  0x20,  0x53,  0xE5,  0x24,  0x54,  0x45, 	/* 0BB60 */
+	0x64,  0x59,  0x45,  0x18,  0x70,  0x8D,  0x18,  0x12,  0x41,  0xC2,  0xB7,  0x02,  0x0F,  0xA0,  0x43,  0xE4, 	/* 0BB70 */
+	0x24,  0x74,  0x45,  0x64,  0x9A,  0x89,  0x18,  0x11,  0x02,  0x28,  0x24,  0x4D,  0x82,  0xB8,  0x22,  0x02, 	/* 0BB80 */
+	0x20,  0x33,  0xE5,  0x24,  0x54,  0x4D,  0x64,  0x5A,  0x85,  0x18,  0x51,  0x05,  0x28,  0x44,  0x45,  0x82, 	/* 0BB90 */
+	0xB9,  0x02,  0x0F,  0xA0,  0x0B,  0xE0,  0xA4,  0xFC,  0x48,  0x64,  0x8A,  0x88,  0x10,  0x89,  0x87,  0xA8, 	/* 0BBA0 */
+	0x04,  0x41,  0x82,  0xBB,  0x02,  0x00,  0x20,  0xF2,  0x02,  0x7E,  0x24,  0x42,  0xA4,  0x22,  0x83,  0x18, 	/* 0BBB0 */
+	0xC1,  0x00,  0x28,  0x04,  0x41,  0x82,  0xBE,  0x22,  0x02,  0x20,  0xFE,  0x02,  0x3E,  0x24,  0x43,  0xC4, 	/* 0BBC0 */
+	0x2A,  0x82,  0xA8,  0x49,  0x04,  0xA8,  0x8C,  0x43,  0x82,  0xBF,  0x02,  0x0F,  0xE0,  0x12,  0x01,  0x3E, 	/* 0BBD0 */
+	0x5E,  0x45,  0x24,  0x55,  0x45,  0x08,  0x54,  0x85,  0x94,  0xE2,  0x20,  0xC1,  0x85,  0x21,  0x02,  0x10, 	/* 0BBE0 */
+	0x22,  0x0F,  0xBE,  0x24,  0x42,  0xA4,  0x7A,  0x44,  0x98,  0x48,  0x84,  0x98,  0x7A,  0x40,  0xC2,  0x88, 	/* 0BBF0 */
+	0x21,  0x02,  0x10,  0xF9,  0xE5,  0x24,  0x4A,  0x44,  0xC4,  0x89,  0x43,  0x18,  0x10,  0x82,  0x94,  0x42, 	/* 0BC00 */
+	0x48,  0x42,  0x8D,  0x10,  0x83,  0x08,  0x28,  0xF4,  0x48,  0x78,  0x89,  0x3E,  0x7C,  0x21,  0x14,  0x58, 	/* 0BC10 */
+	0xC5,  0x48,  0x91,  0x43,  0x62,  0x8F,  0x41,  0x04,  0x10,  0x7D,  0xF8,  0x12,  0x7E,  0x25,  0x72,  0xFD, 	/* 0BC20 */
+	0x45,  0x4C,  0x54,  0x8F,  0xCC,  0x89,  0x23,  0x61,  0x91,  0x19,  0x01,  0x50,  0xFD,  0xE1,  0x24,  0x92, 	/* 0BC30 */
+	0x45,  0x54,  0x58,  0x83,  0x58,  0x55,  0x89,  0x24,  0x14,  0x43,  0x82,  0x95,  0x21,  0x0F,  0xD0,  0x21, 	/* 0BC40 */
+	0xEF,  0xA4,  0xAA,  0x4A,  0xD4,  0xF9,  0x43,  0x08,  0x68,  0x86,  0x94,  0xA2,  0x42,  0xC2,  0x96,  0x11, 	/* 0BC50 */
+	0x01,  0x10,  0x7D,  0xF1,  0x24,  0xFC,  0x42,  0x14,  0xFD,  0x82,  0x08,  0x38,  0xC2,  0x94,  0x4A,  0x29, 	/* 0BC60 */
+	0xC2,  0x97,  0x02,  0x07,  0xA0,  0x4B,  0xE4,  0xA4,  0x7C,  0x44,  0xD4,  0x79,  0x84,  0x88,  0x79,  0x82, 	/* 0BC70 */
+	0xA4,  0x44,  0x48,  0x82,  0x98,  0x11,  0x03,  0x10,  0x29,  0xE4,  0x64,  0x7A,  0x49,  0x44,  0x7D,  0x41, 	/* 0BC80 */
+	0x18,  0x58,  0x85,  0x58,  0x92,  0x43,  0x42,  0x99,  0x21,  0x02,  0x50,  0xF9,  0x02,  0xBE,  0xFE,  0x42, 	/* 0BC90 */
+	0x64,  0x79,  0x49,  0x18,  0x1C,  0x8F,  0x18,  0x12,  0x43,  0xC2,  0x9D,  0x21,  0x06,  0x90,  0x69,  0xEA, 	/* 0BCA0 */
+	0x54,  0xFE,  0x4A,  0x74,  0xA5,  0x4B,  0x48,  0xEC,  0x8A,  0x54,  0xA6,  0x4A,  0xC2,  0x9E,  0x21,  0x06, 	/* 0BCB0 */
+	0x90,  0xA5,  0xF2,  0x12,  0xFA,  0x28,  0xB2,  0xBD,  0x4A,  0x94,  0xA8,  0x8B,  0x98,  0x8A,  0x49,  0xC2, 	/* 0BCC0 */
+	0xA2,  0x01,  0x07,  0xD0,  0x11,  0xEF,  0xE4,  0x4A,  0x47,  0xC4,  0x49,  0x47,  0x94,  0x4C,  0x87,  0x98, 	/* 0BCD0 */
+	0xCA,  0x40,  0xC2,  0xA3,  0x52,  0x0F,  0xA0,  0x53,  0xEF,  0xA4,  0x04,  0x47,  0xC4,  0x4A,  0x87,  0xA8, 	/* 0BCE0 */
+	0x49,  0x07,  0xA8,  0x4C,  0x45,  0x82,  0xA6,  0x12,  0x0F,  0xE0,  0x03,  0xE7,  0xA4,  0x4C,  0x47,  0xC4, 	/* 0BCF0 */
+	0x01,  0x47,  0x94,  0x10,  0x8F,  0xC8,  0x11,  0x43,  0x62,  0xAC,  0x29,  0x0F,  0xD0,  0x29,  0xE2,  0x24, 	/* 0BD00 */
+	0x7E,  0x44,  0x54,  0xF5,  0x45,  0x48,  0x54,  0x87,  0x58,  0x06,  0x41,  0x82,  0xB0,  0x2A,  0x0A,  0xA0, 	/* 0BD10 */
+	0x73,  0xEF,  0xA4,  0x34,  0x46,  0xA4,  0xA2,  0x8F,  0xD8,  0x48,  0x87,  0x18,  0x2A,  0x4C,  0x42,  0xB2, 	/* 0BD20 */
+	0x10,  0x8F,  0xC8,  0x78,  0xE4,  0x88,  0x7B,  0xE0,  0x02,  0xFD,  0x28,  0x54,  0xB4,  0xCB,  0x48,  0xB5, 	/* 0BD30 */
+	0x48,  0x62,  0xB4,  0x22,  0x0F,  0xBE,  0xAA,  0x4F,  0xA4,  0x75,  0x8A,  0x94,  0x22,  0x27,  0xFC,  0x04, 	/* 0BD40 */
+	0x02,  0x7C,  0x24,  0x0F,  0xFE,  0xB5,  0x22,  0x0F,  0xA0,  0x53,  0xE5,  0x24,  0xFC,  0x4A,  0xD4,  0xF9, 	/* 0BD50 */
+	0x4A,  0x88,  0xF8,  0x8C,  0x94,  0xFA,  0x48,  0xC2,  0xB7,  0x2A,  0x0F,  0xA0,  0x23,  0xEF,  0xA4,  0xAC, 	/* 0BD60 */
+	0x4F,  0xE4,  0xAA,  0x8F,  0x90,  0x41,  0x87,  0xA8,  0x4C,  0x49,  0x82,  0xB8,  0x7D,  0x05,  0x50,  0xFF, 	/* 0BD70 */
+	0xF5,  0x52,  0xFE,  0x25,  0x62,  0x7D,  0x42,  0x14,  0xFC,  0x84,  0x94,  0x3A,  0x4E,  0x42,  0x82,  0x11, 	/* 0BD80 */
+	0x02,  0x90,  0x45,  0xEB,  0x94,  0x02,  0x4F,  0xE4,  0xB5,  0x4F,  0xC8,  0x48,  0x86,  0xD4,  0x52,  0x4A, 	/* 0BD90 */
+	0x42,  0x83,  0xA9,  0x07,  0x1E,  0xFE,  0x4A,  0x54,  0xF4,  0x8A,  0xD4,  0x02,  0x2F,  0xFE,  0x22,  0x47, 	/* 0BDA0 */
+	0xB8,  0x92,  0x26,  0x1E,  0x87,  0x04,  0x00,  0x40,  0x7F,  0xE1,  0x08,  0x10,  0x80,  0x90,  0x09,  0x00, 	/* 0BDB0 */
+	0x60,  0x04,  0x00,  0xA0,  0x11,  0x86,  0x06,  0x88,  0x04,  0x0F,  0xFE,  0x11,  0x00,  0xE0,  0x0A,  0x03, 	/* 0BDC0 */
+	0x18,  0xDF,  0x60,  0x20,  0xFF,  0xE0,  0x40,  0x04,  0x00,  0xC0,  0x89,  0x04,  0x0F,  0xFE,  0x11,  0x00, 	/* 0BDD0 */
+	0xE0,  0x31,  0x8E,  0x0E,  0x3F,  0x82,  0x08,  0x3F,  0x82,  0x08,  0x20,  0x84,  0x08,  0x8C,  0x20,  0x82, 	/* 0BDE0 */
+	0x6C,  0xF8,  0xA2,  0xFE,  0xA2,  0x8A,  0xA8,  0x6B,  0x82,  0xA8,  0x5A,  0x84,  0xB4,  0x8E,  0x61,  0x82, 	/* 0BDF0 */
+	0x8E,  0x04,  0x0F,  0xFE,  0x31,  0x80,  0xE0,  0x1B,  0x0E,  0x0E,  0x3F,  0x42,  0x04,  0x3F,  0xC2,  0xD4, 	/* 0BE00 */
+	0x54,  0xC8,  0x44,  0x90,  0x0A,  0x07,  0xBC,  0x0A,  0x07,  0xBC,  0x0A,  0x0F,  0xBE,  0x16,  0x0F,  0xFE, 	/* 0BE10 */
+	0x11,  0x00,  0xE0,  0x1B,  0x0E,  0x0C,  0x91,  0x04,  0x0F,  0x5E,  0x2F,  0x82,  0x28,  0x2A,  0x8F,  0xBE, 	/* 0BE20 */
+	0x2A,  0x82,  0x48,  0x2A,  0x82,  0xA8,  0xF0,  0x82,  0x3E,  0x97,  0x02,  0x03,  0x20,  0x0A,  0x00,  0x20, 	/* 0BE30 */
+	0x62,  0x01,  0x20,  0x02,  0x00,  0x3E,  0xFE,  0x00,  0x20,  0x02,  0x00,  0x20,  0x99,  0x20,  0x4A,  0xA4, 	/* 0BE40 */
+	0x71,  0x42,  0x04,  0xFA,  0x42,  0x14,  0x70,  0x76,  0x9C,  0xA6,  0x4A,  0x04,  0x20,  0x42,  0x04,  0x9B, 	/* 0BE50 */
+	0x20,  0x43,  0xC4,  0x4A,  0x49,  0x14,  0x7C,  0x45,  0x64,  0x7D,  0x45,  0x47,  0x7F,  0xC4,  0x44,  0x44, 	/* 0BE60 */
+	0x48,  0xC4,  0x9C,  0x10,  0x41,  0xA4,  0x25,  0x44,  0x04,  0xBA,  0x41,  0x14,  0x7C,  0x71,  0x3C,  0x54, 	/* 0BE70 */
+	0x45,  0x44,  0x90,  0x43,  0x04,  0x9F,  0x48,  0x4F,  0xE4,  0x49,  0x47,  0x84,  0x4A,  0x47,  0x94,  0x48, 	/* 0BE80 */
+	0x4F,  0xC7,  0xAB,  0xCC,  0xC4,  0x80,  0x47,  0xC4,  0xA1,  0x21,  0x0F,  0x90,  0x22,  0x8F,  0xE4,  0x89, 	/* 0BE90 */
+	0xAF,  0x88,  0x8C,  0x8F,  0xA8,  0x21,  0xEF,  0xE8,  0x20,  0x82,  0x08,  0xA4,  0x00,  0x80,  0x30,  0x3C, 	/* 0BEA0 */
+	0x02,  0x00,  0x3F,  0xE2,  0x20,  0x22,  0x02,  0x20,  0x22,  0x04,  0x20,  0x42,  0x08,  0x20,  0xA5,  0x01, 	/* 0BEB0 */
+	0xC3,  0xE0,  0x20,  0x02,  0x00,  0x3F,  0xE2,  0x20,  0x22,  0x02,  0xE0,  0x43,  0x04,  0x28,  0x82,  0x40, 	/* 0BEC0 */
+	0x20,  0xA7,  0x0B,  0x01,  0x08,  0x69,  0x60,  0x60,  0x19,  0x86,  0x76,  0x3C,  0x02,  0x00,  0x3F,  0xE2, 	/* 0BED0 */
+	0x20,  0x42,  0x08,  0x20,  0xAB,  0x00,  0x6F,  0xF8,  0x22,  0x02,  0x20,  0x43,  0xE7,  0xA4,  0xCA,  0x44, 	/* 0BEE0 */
+	0xA4,  0x4A,  0x44,  0xC4,  0x78,  0x40,  0x04,  0xAC,  0x20,  0x6F,  0xB8,  0x22,  0x0F,  0xA0,  0xAB,  0xEF, 	/* 0BEF0 */
+	0xA4,  0xAA,  0x4F,  0xA4,  0x24,  0x4F,  0xC4,  0x28,  0x42,  0x04,  0xAD,  0x10,  0x49,  0x78,  0xDA,  0x0B, 	/* 0BF00 */
+	0x20,  0xFF,  0xE9,  0x24,  0xBA,  0x4B,  0x64,  0xD2,  0x49,  0x24,  0xFC,  0x40,  0x04,  0xAF,  0x48,  0x64, 	/* 0BF10 */
+	0xB8,  0xFE,  0x04,  0xBE,  0x7A,  0x44,  0xA4,  0x7A,  0x44,  0xA4,  0xFE,  0x42,  0xA4,  0x44,  0x48,  0x84, 	/* 0BF20 */
+	0xB0,  0x20,  0x4F,  0xF8,  0x4A,  0x04,  0xA0,  0xFF,  0xE2,  0x24,  0xFA,  0x43,  0x24,  0x6A,  0x46,  0x44, 	/* 0BF30 */
+	0xA8,  0x42,  0x04,  0xB7,  0xAC,  0x2D,  0x5C,  0xAD,  0x0F,  0xD0,  0x85,  0xFF,  0xD4,  0xAD,  0x4D,  0x54, 	/* 0BF40 */
+	0xAD,  0x4F,  0xD4,  0x86,  0x4F,  0xC4,  0xB9,  0x04,  0x00,  0x40,  0xFF,  0xE0,  0x80,  0x08,  0x00,  0xF8, 	/* 0BF50 */
+	0x08,  0x80,  0x88,  0x10,  0x81,  0x08,  0x20,  0x84,  0x30,  0xBC,  0x21,  0x02,  0x10,  0xFA,  0x82,  0x28, 	/* 0BF60 */
+	0x24,  0x43,  0x92,  0x28,  0x82,  0xA0,  0x49,  0x04,  0x88,  0x88,  0x43,  0x04,  0xBD,  0x22,  0x02,  0x20, 	/* 0BF70 */
+	0xF7,  0xE4,  0x90,  0x75,  0xC5,  0x74,  0x5D,  0x45,  0x54,  0x55,  0xC9,  0x50,  0x14,  0x26,  0x3E,  0x81, 	/* 0BF80 */
+	0x04,  0x07,  0xFE,  0x10,  0x80,  0x90,  0xFF,  0xE8,  0x42,  0xFF,  0xA0,  0x80,  0x0F,  0x80,  0x88,  0x10, 	/* 0BF90 */
+	0x86,  0x30,  0x83,  0x22,  0x02,  0x20,  0xFF,  0xE2,  0x40,  0x2B,  0xE3,  0xAA,  0x2A,  0xA2,  0xFF,  0x4A, 	/* 0BFA0 */
+	0x24,  0xA2,  0x8A,  0x23,  0x26,  0x84,  0x24,  0x02,  0x40,  0xF7,  0xE4,  0x80,  0x50,  0xC7,  0x70,  0x51, 	/* 0BFB0 */
+	0xC5,  0x70,  0x51,  0xE9,  0xF0,  0x91,  0x23,  0x0E,  0x85,  0x22,  0x02,  0x20,  0xFF,  0xE2,  0x28,  0x24, 	/* 0BFC0 */
+	0xA3,  0x94,  0x29,  0x82,  0xB4,  0x4D,  0x44,  0x92,  0x89,  0x13,  0x10,  0x86,  0x22,  0x02,  0x20,  0xF7, 	/* 0BFD0 */
+	0xE4,  0x90,  0x7F,  0xE5,  0x10,  0x57,  0xC5,  0x54,  0x55,  0x49,  0x5C,  0x95,  0x03,  0x10,  0x8B,  0x22, 	/* 0BFE0 */
+	0x02,  0x20,  0xF3,  0xE4,  0x40,  0x77,  0xC5,  0x90,  0x55,  0x05,  0x5C,  0x55,  0x05,  0x70,  0x95,  0x06, 	/* 0BFF0 */
+	0x8E,  0x8C,  0x22,  0x02,  0x20,  0xFB,  0xE4,  0x50,  0x75,  0x05,  0x7E,  0x59,  0x05,  0x10,  0x57,  0xC9, 	/* 0C000 */
+	0x10,  0x11,  0x06,  0xFE,  0x8F,  0x22,  0x02,  0x20,  0xFF,  0xE2,  0x50,  0x2B,  0xE3,  0xC8,  0x28,  0x82, 	/* 0C010 */
+	0xFE,  0x48,  0x84,  0x94,  0x8A,  0x43,  0x42,  0x92,  0x22,  0x02,  0x7E,  0xF9,  0x04,  0xFE,  0x42,  0x47, 	/* 0C020 */
+	0x7A,  0x50,  0x45,  0x54,  0x55,  0x49,  0x54,  0x15,  0x46,  0x83,  0x97,  0x22,  0x02,  0x7E,  0xFA,  0x42, 	/* 0C030 */
+	0xFE,  0x22,  0x43,  0xBC,  0x2A,  0x42,  0xBC,  0x4A,  0x44,  0xFE,  0x89,  0x43,  0x62,  0x99,  0x20,  0x42, 	/* 0C040 */
+	0xF8,  0xF9,  0x44,  0x58,  0x7F,  0xE5,  0x34,  0x55,  0x25,  0xFD,  0x55,  0x49,  0x7C,  0x15,  0x46,  0x7C, 	/* 0C050 */
+	0x9B,  0x22,  0x02,  0x3E,  0xF4,  0xC4,  0xF4,  0x75,  0x85,  0xFE,  0x53,  0x45,  0x7E,  0x5D,  0x59,  0x7C, 	/* 0C060 */
+	0x15,  0x46,  0x7C,  0xA0,  0x00,  0x07,  0xFC,  0x04,  0x00,  0x40,  0xFF,  0xE0,  0x40,  0x06,  0x00,  0xA0, 	/* 0C070 */
+	0x0A,  0x01,  0x22,  0x22,  0x2C,  0x1E,  0xA1,  0x00,  0x07,  0xFC,  0x04,  0x04,  0x40,  0x44,  0x07,  0xFE, 	/* 0C080 */
+	0x46,  0x00,  0xA0,  0x0A,  0x01,  0x22,  0x22,  0x2C,  0x1E,  0xA2,  0x00,  0x07,  0xFE,  0x4A,  0x87,  0xA8, 	/* 0C090 */
+	0x4A,  0x84,  0xFE,  0x79,  0x84,  0x18,  0x52,  0x85,  0xAA,  0x64,  0xA8,  0x86,  0xA5,  0x00,  0x03,  0xF8, 	/* 0C0A0 */
+	0x20,  0x82,  0x08,  0x20,  0x82,  0x08,  0x3F,  0x82,  0x08,  0x20,  0x82,  0x08,  0x20,  0x83,  0xF8,  0xA6, 	/* 0C0B0 */
+	0x00,  0x03,  0xF8,  0x20,  0x82,  0x08,  0x3F,  0x82,  0x08,  0x20,  0x82,  0x08,  0x3F,  0x80,  0x00,  0x00, 	/* 0C0C0 */
+	0x0F,  0xFE,  0xA7,  0x40,  0x04,  0xFC,  0x48,  0x44,  0x84,  0x48,  0x44,  0xFC,  0x48,  0x44,  0x84,  0x48, 	/* 0C0D0 */
+	0x44,  0x84,  0x4F,  0xC4,  0x00,  0xA8,  0x40,  0x04,  0x38,  0x7C,  0x04,  0x04,  0x3F,  0xC0,  0x00,  0x3F, 	/* 0C0E0 */
+	0x82,  0x08,  0x3F,  0x82,  0x08,  0x20,  0x83,  0xF8,  0xA9,  0x00,  0x03,  0xFC,  0x20,  0x43,  0xFC,  0x20, 	/* 0C0F0 */
+	0x43,  0xFC,  0x04,  0x00,  0x40,  0xFF,  0xE0,  0x40,  0x04,  0x00,  0x40,  0xAC,  0x10,  0x01,  0x00,  0x3F, 	/* 0C100 */
+	0xE2,  0x02,  0x5F,  0x29,  0x12,  0x1F,  0x21,  0x12,  0x11,  0x21,  0xF2,  0x00,  0x20,  0x0C,  0xAD,  0x20, 	/* 0C110 */
+	0x02,  0x3E,  0x22,  0x2F,  0xA2,  0x2B,  0xE2,  0xA2,  0x2A,  0x22,  0xA2,  0x2A,  0x24,  0xBE,  0x48,  0x18, 	/* 0C120 */
+	0x7F,  0xB1,  0x3F,  0x82,  0x08,  0x3F,  0x82,  0x08,  0x3F,  0x80,  0x00,  0x7F,  0xC0,  0x40,  0xFF,  0xE0, 	/* 0C130 */
+	0x40,  0x04,  0x00,  0x40,  0xBA,  0x00,  0x0F,  0xFE,  0x91,  0x09,  0x10,  0x91,  0x0F,  0x10,  0x9F,  0xC9, 	/* 0C140 */
+	0x10,  0x91,  0x0F,  0x10,  0x01,  0x01,  0xFE,  0xBB,  0x00,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83, 	/* 0C150 */
+	0xF8,  0x04,  0x0F,  0xFE,  0x31,  0x80,  0xE0,  0x19,  0x8E,  0x06,  0x82,  0x3F,  0xC2,  0x04,  0x3F,  0xC2, 	/* 0C160 */
+	0x04,  0x3F,  0xC0,  0x80,  0x73,  0xE4,  0x22,  0x42,  0x25,  0xA2,  0xE2,  0xC0,  0x20,  0x83,  0x3F,  0x82, 	/* 0C170 */
+	0x08,  0x3F,  0x82,  0x08,  0x3F,  0x80,  0x00,  0x7F,  0xE4,  0x40,  0x44,  0x04,  0xA0,  0x91,  0x0A,  0x0C, 	/* 0C180 */
+	0x86,  0x00,  0x03,  0xFC,  0x20,  0x43,  0xFC,  0x20,  0x43,  0xFC,  0x22,  0x03,  0xE6,  0x23,  0x82,  0x22, 	/* 0C190 */
+	0x3A,  0x2E,  0x1E,  0x87,  0x00,  0x03,  0xFC,  0x20,  0x43,  0xFC,  0x20,  0x43,  0xFC,  0x1D,  0x06,  0x90, 	/* 0C1A0 */
+	0xFF,  0xE1,  0x10,  0x21,  0x04,  0x10,  0x8A,  0x3F,  0x82,  0x08,  0x3F,  0x82,  0x08,  0x3F,  0x80,  0x00, 	/* 0C1B0 */
+	0xFF,  0xE0,  0x40,  0x7F,  0xC0,  0xA0,  0x31,  0x8C,  0x06,  0x8C,  0x00,  0x03,  0xF8,  0x20,  0x83,  0xF8, 	/* 0C1C0 */
+	0x20,  0x83,  0xF8,  0x00,  0x07,  0xFC,  0x40,  0x47,  0xFC,  0x40,  0x47,  0xFC,  0x8E,  0x00,  0x07,  0xBE, 	/* 0C1D0 */
+	0x4A,  0x24,  0xA2,  0x7B,  0xE4,  0xA2,  0x4A,  0x24,  0xBE,  0x7A,  0x24,  0x22,  0x04,  0x20,  0x86,  0x8F, 	/* 0C1E0 */
+	0x07,  0x87,  0xE0,  0x42,  0x07,  0xFE,  0x41,  0x05,  0x8A,  0xE0,  0x63,  0xFA,  0x20,  0x83,  0xF8,  0x20, 	/* 0C1F0 */
+	0x83,  0xF8,  0x93,  0x00,  0x01,  0xFC,  0x10,  0x41,  0xFC,  0x10,  0x41,  0xFC,  0x08,  0x01,  0xFE,  0x64, 	/* 0C200 */
+	0xA0,  0x92,  0x32,  0x20,  0xCC,  0x94,  0x11,  0x07,  0xFC,  0x11,  0x01,  0x10,  0xFF,  0xE0,  0x00,  0x3F, 	/* 0C210 */
+	0x82,  0x08,  0x3F,  0x82,  0x08,  0x20,  0x83,  0xF8,  0x9C,  0x00,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20, 	/* 0C220 */
+	0x8F,  0xFE,  0x10,  0x01,  0xFC,  0x29,  0x44,  0x94,  0x92,  0x42,  0x58,  0x9F,  0x00,  0x03,  0xFC,  0x20, 	/* 0C230 */
+	0x43,  0xFC,  0x20,  0x43,  0xFC,  0x24,  0x03,  0xFC,  0x44,  0x09,  0xF8,  0x04,  0x07,  0xFE,  0xA0,  0x02, 	/* 0C240 */
+	0x0E,  0x20,  0xAF,  0xCA,  0xA4,  0xAA,  0x4E,  0xA4,  0xBF,  0xEA,  0x30,  0xA5,  0x0E,  0x48,  0x08,  0x43, 	/* 0C250 */
+	0x02,  0xA5,  0x04,  0x03,  0xF8,  0x04,  0x07,  0xFC,  0x0A,  0x0F,  0xFE,  0x20,  0x85,  0xF4,  0x91,  0x21, 	/* 0C260 */
+	0xF0,  0x11,  0x01,  0xF0,  0xA7,  0x02,  0x0E,  0x20,  0xBF,  0xCA,  0x20,  0xA2,  0x0F,  0xFC,  0xA2,  0x0A, 	/* 0C270 */
+	0x70,  0xAA,  0x8F,  0x26,  0x82,  0x00,  0x20,  0xA8,  0x02,  0x0F,  0x20,  0x93,  0xF9,  0x50,  0x95,  0x0F, 	/* 0C280 */
+	0x9E,  0x91,  0x09,  0x10,  0x91,  0xEF,  0x10,  0x01,  0x00,  0x10,  0xAD,  0x00,  0x0F,  0xFE,  0x91,  0x29, 	/* 0C290 */
+	0x12,  0x92,  0x2F,  0x4C,  0x98,  0x09,  0x7E,  0x94,  0x2F,  0x42,  0x04,  0x20,  0x7E,  0xAF,  0x3F,  0x82, 	/* 0C2A0 */
+	0x08,  0x3F,  0x82,  0x08,  0x3F,  0x80,  0x00,  0xFF,  0xE0,  0x40,  0x27,  0xC3,  0x40,  0x4C,  0x08,  0x3E, 	/* 0C2B0 */
+	0xB4,  0x3F,  0xC2,  0x04,  0x3F,  0xC2,  0x04,  0x3F,  0xC0,  0x80,  0x75,  0xE4,  0x52,  0x45,  0x2F,  0x9C, 	/* 0C2C0 */
+	0x09,  0x01,  0x10,  0xB5,  0x00,  0x00,  0xFE,  0xE8,  0x2A,  0xFE,  0xAA,  0x0E,  0xA0,  0xAA,  0x6A,  0xB8, 	/* 0C2D0 */
+	0xAA,  0x0F,  0x22,  0x12,  0x22,  0x1E,  0xB6,  0x00,  0x07,  0x9E,  0x01,  0x27,  0x12,  0x13,  0xEF,  0x52, 	/* 0C2E0 */
+	0x39,  0x23,  0x52,  0x55,  0xE5,  0x20,  0x91,  0x83,  0x07,  0xBC,  0x00,  0x01,  0xFC,  0x10,  0x41,  0xFC, 	/* 0C2F0 */
+	0x10,  0x83,  0xFC,  0x50,  0xA9,  0xF9,  0x10,  0x81,  0xF8,  0x00,  0x0F,  0xFE,  0xBF,  0x01,  0x0E,  0x10, 	/* 0C300 */
+	0xAF,  0xEA,  0x80,  0xA9,  0x0E,  0x90,  0xA9,  0x0A,  0x90,  0xAA,  0x8F,  0x44,  0x1F,  0xA2,  0x02,  0x81, 	/* 0C310 */
+	0x00,  0x07,  0xFC,  0x40,  0x47,  0xFC,  0x40,  0x47,  0xFC,  0x4A,  0x42,  0xA8,  0x3B,  0x8D,  0x24,  0x22, 	/* 0C320 */
+	0x24,  0x1E,  0x82,  0x02,  0x0E,  0xFC,  0xA2,  0x0A,  0x20,  0xBF,  0xEE,  0x08,  0xBF,  0xEA,  0x88,  0xA4, 	/* 0C330 */
+	0x8A,  0x08,  0xE0,  0x80,  0x18,  0x83,  0x00,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x44, 	/* 0C340 */
+	0x42,  0x48,  0xFF,  0xE0,  0xA0,  0x32,  0x2C,  0x1E,  0x84,  0x02,  0x0E,  0x20,  0xB2,  0x4A,  0xA4,  0xAA, 	/* 0C350 */
+	0x8F,  0xFE,  0xA5,  0x0A,  0x50,  0xA5,  0x0E,  0x90,  0x11,  0x22,  0x0E,  0x89,  0x00,  0x0F,  0xFE,  0x29, 	/* 0C360 */
+	0x47,  0xBC,  0x08,  0x4F,  0xFE,  0x00,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x8B,  0x00, 	/* 0C370 */
+	0x07,  0xFC,  0x4A,  0x42,  0xA4,  0x2A,  0x8F,  0xFE,  0x00,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83, 	/* 0C380 */
+	0xF8,  0x8F,  0x3F,  0x82,  0x08,  0x3F,  0x82,  0x08,  0x3F,  0x8F,  0xFE,  0x88,  0x27,  0xFE,  0x11,  0x03, 	/* 0C390 */
+	0xE0,  0x0D,  0x87,  0x04,  0x92,  0x0F,  0xEE,  0x28,  0xA2,  0x8A,  0xFE,  0xAA,  0xAE,  0xAA,  0xAA,  0xAA, 	/* 0C3A0 */
+	0xAA,  0xAC,  0xEE,  0x82,  0x0F,  0xE0,  0x80,  0x9D,  0x04,  0x07,  0xF8,  0x04,  0x8F,  0xFE,  0x04,  0x87, 	/* 0C3B0 */
+	0xF8,  0x04,  0x0F,  0xFC,  0x20,  0x83,  0xF8,  0x20,  0x8F,  0xFE,  0x9E,  0x00,  0x4E,  0xC8,  0xA7,  0x0B, 	/* 0C3C0 */
+	0xA8,  0xBF,  0xEE,  0x50,  0xA7,  0xCA,  0xD4,  0xB5,  0x4E,  0x54,  0x05,  0xC0,  0x10,  0x9F,  0x3F,  0xC2, 	/* 0C3D0 */
+	0x04,  0x3F,  0xC2,  0x04,  0x3F,  0xC0,  0x14,  0x7F,  0xE4,  0x10,  0x79,  0x44,  0x88,  0x69,  0x69,  0x22, 	/* 0C3E0 */
+	0xA2,  0x20,  0x6F,  0xB8,  0x22,  0x03,  0x3E,  0xE2,  0x82,  0x48,  0x28,  0x87,  0xFC,  0x40,  0x47,  0xFC, 	/* 0C3F0 */
+	0x40,  0x47,  0xFC,  0xA4,  0x00,  0x01,  0xFE,  0xF1,  0x09,  0x7C,  0x92,  0x4F,  0x24,  0x9F,  0xF9,  0x00, 	/* 0C400 */
+	0x97,  0xC9,  0x44,  0xF4,  0x40,  0x7C,  0xA6,  0x04,  0x0E,  0x7E,  0xA4,  0x0A,  0xFC,  0xB5,  0x4E,  0x54, 	/* 0C410 */
+	0xBF,  0xEA,  0x94,  0xA9,  0x4E,  0xFE,  0x00,  0x40,  0x18,  0xA7,  0x01,  0x0F,  0x50,  0x97,  0xE9,  0x90, 	/* 0C420 */
+	0x91,  0x0F,  0xFF,  0x91,  0x09,  0x7C,  0x94,  0x4F,  0x44,  0x04,  0x40,  0x7C,  0xA8,  0x1F,  0x81,  0x08, 	/* 0C430 */
+	0x1F,  0x81,  0x08,  0x7F,  0xE4,  0x00,  0x5F,  0xE4,  0xA4,  0x49,  0x84,  0x88,  0x8E,  0x49,  0x82,  0xA9, 	/* 0C440 */
+	0x02,  0x00,  0x78,  0xE9,  0x0B,  0xFC,  0xAA,  0x4E,  0xA4,  0xAF,  0xCA,  0x50,  0xA5,  0x0E,  0x92,  0x11, 	/* 0C450 */
+	0x22,  0x0E,  0xAE,  0x20,  0x81,  0x10,  0xFF,  0xE4,  0xA4,  0x2A,  0x8F,  0xFE,  0x00,  0x03,  0xF8,  0x20, 	/* 0C460 */
+	0x83,  0xF8,  0x20,  0x83,  0xF8,  0xAF,  0x3F,  0x82,  0x08,  0x3F,  0x82,  0x08,  0xFF,  0xE0,  0x00,  0x3F, 	/* 0C470 */
+	0x82,  0x08,  0x3F,  0x80,  0x50,  0x24,  0x8C,  0xC4,  0xB0,  0x04,  0x2E,  0x5C,  0xA5,  0x0B,  0xF0,  0xA5, 	/* 0C480 */
+	0xEE,  0xD4,  0xAF,  0x4B,  0x54,  0xA5,  0x4A,  0x64,  0xE4,  0x40,  0x44,  0xB4,  0x01,  0x0F,  0xFE,  0x91, 	/* 0C490 */
+	0x09,  0x7C,  0x91,  0x0F,  0xFE,  0x94,  0x49,  0x7C,  0x94,  0x4F,  0x7C,  0x04,  0x40,  0x4C,  0xB6,  0x00, 	/* 0C4A0 */
+	0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x00,  0x0F,  0xBE,  0x8A,  0x2F,  0xBE,  0x8A,  0x2F, 	/* 0C4B0 */
+	0xBE,  0xBA,  0x40,  0x07,  0xBE,  0x92,  0x27,  0xE2,  0x12,  0x22,  0xBE,  0x44,  0x0B,  0xF8,  0x20,  0x83, 	/* 0C4C0 */
+	0xF8,  0x20,  0x83,  0xF8,  0x81,  0x02,  0x01,  0xFC,  0xE2,  0x0A,  0xA8,  0xBF,  0xEE,  0x88,  0xA0,  0x0B, 	/* 0C4D0 */
+	0xFE,  0xE5,  0x08,  0x52,  0x09,  0x23,  0x0E,  0x83,  0x3F,  0x82,  0x08,  0x3F,  0x82,  0x08,  0x3F,  0x80, 	/* 0C4E0 */
+	0xA0,  0xFB,  0xE0,  0xA0,  0x7B,  0xC0,  0xA0,  0xF3,  0xE2,  0x20,  0x84,  0x02,  0x0F,  0xFE,  0xB0,  0x2A, 	/* 0C4F0 */
+	0xFC,  0xA0,  0x0E,  0xFC,  0xA8,  0x4A,  0xFC,  0xA8,  0x4E,  0xFC,  0x00,  0x01,  0xFE,  0x87,  0x0E,  0xEE, 	/* 0C500 */
+	0xA2,  0xAA,  0x2A,  0xEE,  0xA8,  0x0E,  0x9E,  0xAE,  0x2A,  0x8A,  0xA8,  0x4E,  0xE4,  0x08,  0xA0,  0x91, 	/* 0C510 */
+	0x88,  0x3F,  0x82,  0x08,  0x3F,  0x82,  0x08,  0xFF,  0xE8,  0x42,  0x7F,  0xC2,  0x48,  0x3F,  0x82,  0x48, 	/* 0C520 */
+	0xFF,  0xE0,  0x40,  0x89,  0x1F,  0xEF,  0x22,  0xAF,  0xCA,  0x20,  0xAF,  0xCE,  0xA4,  0xAF,  0xCA,  0xA4, 	/* 0C530 */
+	0xAF,  0xCE,  0x20,  0x1F,  0xE0,  0x20,  0x8E,  0x08,  0x8F,  0xFE,  0xA8,  0x8A,  0x20,  0xAF,  0xCE,  0xA4, 	/* 0C540 */
+	0xAA,  0x4B,  0xFE,  0xA2,  0x0E,  0x30,  0x04,  0x81,  0x84,  0x91,  0x00,  0x03,  0xF8,  0x20,  0x83,  0xF8, 	/* 0C550 */
+	0x24,  0x87,  0xFC,  0x05,  0x0F,  0xFE,  0x30,  0x8D,  0xF8,  0x10,  0x81,  0xF8,  0x96,  0x00,  0xEE,  0xF2, 	/* 0C560 */
+	0xA5,  0x4A,  0xFE,  0xA2,  0x0F,  0xFE,  0xA2,  0x0A,  0x7C,  0xA6,  0x4E,  0x98,  0x13,  0x42,  0xC2,  0x97, 	/* 0C570 */
+	0x01,  0x0F,  0xFE,  0x94,  0x49,  0x48,  0x9F,  0xEF,  0x00,  0x97,  0xC9,  0x44,  0x97,  0xCF,  0x44,  0x04, 	/* 0C580 */
+	0x40,  0x7C,  0x98,  0x00,  0x0E,  0x7C,  0xA4,  0x4A,  0x7C,  0xE4,  0x4B,  0xFF,  0xA4,  0x0A,  0xFE,  0xF2, 	/* 0C590 */
+	0xA0,  0xD2,  0x02,  0x20,  0xCC,  0x9D,  0x00,  0x0F,  0xFE,  0xB0,  0x2A,  0xFC,  0xA8,  0x4E,  0xFC,  0xA8, 	/* 0C5A0 */
+	0x4A,  0xFC,  0xA2,  0x0F,  0xFE,  0x04,  0x81,  0x84,  0xA2,  0x20,  0x02,  0x3C,  0xFA,  0x4A,  0xBC,  0xFA, 	/* 0C5B0 */
+	0x4A,  0xFE,  0xAA,  0x0F,  0xBE,  0x24,  0xA2,  0x92,  0x22,  0x22,  0x4C,  0xA6,  0x00,  0x07,  0xFE,  0x48, 	/* 0C5C0 */
+	0x87,  0xDE,  0x48,  0x85,  0xDC,  0x6A,  0xA5,  0xFC,  0x50,  0x49,  0xFC,  0x90,  0x41,  0xFC,  0xAB,  0x10, 	/* 0C5D0 */
+	0x4F,  0xF8,  0x52,  0x07,  0xBE,  0x52,  0x4F,  0xE4,  0x14,  0x43,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83, 	/* 0C5E0 */
+	0xF8,  0xAE,  0x11,  0x0F,  0xFE,  0x11,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x8F,  0xFE,  0x31,  0x85, 	/* 0C5F0 */
+	0xF4,  0x91,  0x21,  0xF0,  0xB4,  0x3F,  0x82,  0x08,  0x3F,  0x82,  0x08,  0x7F,  0xC1,  0x10,  0xFF,  0xE2, 	/* 0C600 */
+	0x48,  0x55,  0x49,  0xF2,  0x64,  0xC0,  0xC0,  0xB8,  0x01,  0x00,  0xFE,  0xEA,  0xAA,  0x7C,  0xAC,  0x6F, 	/* 0C610 */
+	0x7D,  0xA4,  0x4A,  0x7C,  0xA5,  0x4E,  0x92,  0x11,  0x20,  0x30,  0xB9,  0x4F,  0xC2,  0x84,  0x0F,  0xC8, 	/* 0C620 */
+	0x84,  0x4F,  0xC0,  0x28,  0xE7,  0xE2,  0xC8,  0x27,  0xE2,  0x7E,  0x5C,  0x88,  0x7F,  0xBC,  0xA9,  0x07, 	/* 0C630 */
+	0x1E,  0xFA,  0x4A,  0xD4,  0xF8,  0x8A,  0x94,  0x8E,  0x23,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8, 	/* 0C640 */
+	0xBE,  0x04,  0x8F,  0xF8,  0xA0,  0xFA,  0xEA,  0xAB,  0x2E,  0xE2,  0xA0,  0xAB,  0xEC,  0xA4,  0x4F,  0xEC, 	/* 0C650 */
+	0x05,  0x20,  0xE2,  0x81,  0x20,  0x07,  0xFC,  0x4A,  0x87,  0xBE,  0x51,  0x85,  0xAA,  0x64,  0xE3,  0xF8, 	/* 0C660 */
+	0x20,  0x83,  0xF8,  0x20,  0x8F,  0xFE,  0x84,  0x04,  0x81,  0xFE,  0xE4,  0x8A,  0xFE,  0xA5,  0x4F,  0xFE, 	/* 0C670 */
+	0xA5,  0x4A,  0xFE,  0xA1,  0x0F,  0xFF,  0x01,  0x00,  0x10,  0x87,  0x3F,  0x82,  0x08,  0xFF,  0xE0,  0x40, 	/* 0C680 */
+	0xFF,  0xEA,  0x52,  0x94,  0xA3,  0xF8,  0x00,  0x0F,  0xFE,  0x11,  0x87,  0xE4,  0x89,  0x01,  0x0E,  0xFC, 	/* 0C690 */
+	0xA1,  0x0A,  0xFE,  0xA4,  0x4E,  0xEE,  0xA4,  0x4B,  0xFE,  0xA2,  0x8E,  0x2A,  0x04,  0xA1,  0x86,  0x96, 	/* 0C6A0 */
+	0x00,  0xCE,  0xF4,  0xAA,  0x8B,  0xFE,  0xB6,  0xAE,  0xD4,  0xB3,  0xEA,  0x78,  0xAC,  0x8F,  0x30,  0x04, 	/* 0C6B0 */
+	0x81,  0x86,  0x99,  0x0F,  0xEE,  0xAA,  0xAF,  0xEA,  0x10,  0xAF,  0xEE,  0x14,  0xBF,  0xFA,  0x7C,  0xAC, 	/* 0C6C0 */
+	0x4F,  0x7C,  0x04,  0x40,  0x7C,  0x9A,  0x08,  0x8F,  0xFE,  0xAA,  0x8B,  0xFE,  0xB0,  0x2E,  0xFC,  0xBD, 	/* 0C6D0 */
+	0x2A,  0x3A,  0xAC,  0xCE,  0x3A,  0x0C,  0x90,  0x30,  0x9C,  0x00,  0x0F,  0xFE,  0xA2,  0x2A,  0xEE,  0xA2, 	/* 0C6E0 */
+	0x2F,  0xFE,  0xA9,  0x0A,  0xFE,  0xB9,  0x0E,  0xFC,  0x09,  0x00,  0xFE,  0x9D,  0x07,  0xCF,  0x44,  0x97, 	/* 0C6F0 */
+	0xC9,  0x28,  0x97,  0xCF,  0x28,  0x9F,  0xE9,  0x54,  0x9D,  0x6F,  0x39,  0x0D,  0x60,  0x10,  0xA0,  0x01, 	/* 0C700 */
+	0x0E,  0xFE,  0xAA,  0x8A,  0xFC,  0xAA,  0x8E,  0xFE,  0xAD,  0x4A,  0xFC,  0xAD,  0x4F,  0x7C,  0x12,  0x42, 	/* 0C710 */
+	0xC2,  0xA6,  0x04,  0x4E,  0xFE,  0xA1,  0x0B,  0xFE,  0xA4,  0x8F,  0x8A,  0xBF,  0xEA,  0xC8,  0xBA,  0xAE, 	/* 0C720 */
+	0xD4,  0x04,  0xC1,  0x92,  0xA9,  0x3F,  0x82,  0x08,  0xFF,  0xE4,  0xA4,  0x7B,  0xC1,  0x10,  0x7F,  0xE1, 	/* 0C730 */
+	0x10,  0xFF,  0xE3,  0xA4,  0xC9,  0x83,  0xC6,  0xB0,  0x00,  0x07,  0xFC,  0x40,  0x44,  0x04,  0x40,  0x44, 	/* 0C740 */
+	0x04,  0x7E,  0x44,  0x04,  0x40,  0x44,  0x04,  0x40,  0x47,  0xFC,  0xB2,  0x09,  0x00,  0x90,  0x09,  0x07, 	/* 0C750 */
+	0xFE,  0x49,  0x24,  0x92,  0x7F,  0xE4,  0x92,  0x49,  0x24,  0x92,  0x49,  0x27,  0xFE,  0xB3,  0x08,  0x00, 	/* 0C760 */
+	0x80,  0x7F,  0x84,  0x88,  0x7F,  0x84,  0x88,  0x7F,  0xC0,  0x88,  0x07,  0x01,  0xA2,  0xE1,  0xA0,  0x06, 	/* 0C770 */
+	0xB4,  0x00,  0x0F,  0xFE,  0x04,  0x03,  0xF8,  0x24,  0x83,  0xF8,  0x24,  0x83,  0xF8,  0x14,  0x00,  0xC0, 	/* 0C780 */
+	0x33,  0x0C,  0x0E,  0xB5,  0x05,  0x00,  0x48,  0x7F,  0xC4,  0x44,  0x7F,  0x44,  0x44,  0x7F,  0xC0,  0x44, 	/* 0C790 */
+	0x04,  0x80,  0x32,  0x1D,  0xAE,  0x06,  0xB7,  0x00,  0x03,  0xFC,  0x20,  0x43,  0xFC,  0x20,  0x43,  0xFC, 	/* 0C7A0 */
+	0x10,  0x03,  0xFE,  0xD2,  0x21,  0x52,  0x1F,  0xA0,  0x0C,  0xB8,  0x04,  0x07,  0xFC,  0x04,  0x4F,  0xFE, 	/* 0C7B0 */
+	0x04,  0x47,  0xFC,  0x04,  0x0F,  0xFE,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0xB9,  0x09,  0x0F,  0xFE, 	/* 0C7C0 */
+	0x09,  0x07,  0xFE,  0x49,  0x27,  0xFE,  0x49,  0x27,  0xFE,  0x20,  0x43,  0xFC,  0x20,  0x43,  0xFC,  0xBC, 	/* 0C7D0 */
+	0x3F,  0x82,  0x08,  0x3F,  0x82,  0x08,  0xFF,  0xE9,  0x12,  0xFF,  0xE7,  0xF8,  0x11,  0x00,  0xE0,  0x1B, 	/* 0C7E0 */
+	0x0E,  0x0E,  0xBD,  0x20,  0x81,  0x10,  0x7F,  0xC4,  0x44,  0x7F,  0xC4,  0x44,  0x7F,  0xC3,  0xF8,  0x20, 	/* 0C7F0 */
+	0x83,  0xF8,  0x20,  0x83,  0xF8,  0xBE,  0x0E,  0x01,  0x10,  0x20,  0x8F,  0xFE,  0x55,  0x44,  0xE4,  0x7F, 	/* 0C800 */
+	0xC3,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0xBF,  0x20,  0x8F,  0xBE,  0x20,  0x8F,  0xBE,  0x20, 	/* 0C810 */
+	0x85,  0x14,  0x8A,  0x23,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x80,  0x3F,  0x82,  0x08,  0x3F, 	/* 0C820 */
+	0x82,  0x08,  0xFF,  0xE4,  0x80,  0x7F,  0xC4,  0xA4,  0x79,  0x44,  0x98,  0xFA,  0x40,  0xC2,  0x83,  0x04, 	/* 0C830 */
+	0x00,  0xA0,  0x3F,  0x8C,  0x06,  0x7F,  0xC6,  0x4C,  0x55,  0x47,  0xFC,  0x20,  0x83,  0xF8,  0x20,  0x83, 	/* 0C840 */
+	0xF8,  0x88,  0x00,  0x01,  0xFC,  0x10,  0x41,  0x04,  0x1F,  0xC1,  0x04,  0x10,  0x41,  0xFC,  0x10,  0x42, 	/* 0C850 */
+	0x04,  0x20,  0x44,  0x0C,  0x89,  0x04,  0x07,  0xFE,  0x04,  0x00,  0x80,  0x1F,  0xC1,  0x84,  0x2F,  0xC4, 	/* 0C860 */
+	0x84,  0x8F,  0xC0,  0x84,  0x08,  0x40,  0x8C,  0x8B,  0x00,  0x03,  0xDE,  0x25,  0x22,  0x52,  0x3D,  0xE2, 	/* 0C870 */
+	0x52,  0x25,  0x23,  0xDE,  0x25,  0x22,  0x52,  0x46,  0x28,  0xC6,  0x8D,  0x00,  0x07,  0x7E,  0x54,  0x25, 	/* 0C880 */
+	0x4C,  0x74,  0x05,  0x7C,  0x54,  0x47,  0x54,  0x54,  0x85,  0x58,  0x56,  0x4B,  0x42,  0x8F,  0x01,  0x07, 	/* 0C890 */
+	0x10,  0x55,  0x25,  0x52,  0x75,  0x25,  0x7E,  0x51,  0x07,  0x52,  0x55,  0x25,  0x52,  0x95,  0x2B,  0x7E, 	/* 0C8A0 */
+	0x94,  0x84,  0x04,  0x5E,  0x29,  0x2F,  0xF2,  0x11,  0xE5,  0x52,  0x55,  0x25,  0x5E,  0x7D,  0x21,  0x22, 	/* 0C8B0 */
+	0x22,  0x24,  0x46,  0x95,  0x04,  0x47,  0x24,  0x52,  0x85,  0xFC,  0x71,  0x05,  0x10,  0x5F,  0xE7,  0x10, 	/* 0C8C0 */
+	0x51,  0x05,  0x28,  0x54,  0x4B,  0x82,  0x96,  0x02,  0x07,  0x10,  0x57,  0xC5,  0x44,  0x77,  0xC5,  0x44, 	/* 0C8D0 */
+	0x57,  0xC7,  0x52,  0x54,  0xC5,  0x48,  0x57,  0x4B,  0xC2,  0x97,  0x10,  0x07,  0xDE,  0x45,  0x27,  0xDE, 	/* 0C8E0 */
+	0x45,  0x27,  0xD2,  0x51,  0xE4,  0x92,  0x4D,  0x27,  0x22,  0xC2,  0x20,  0x46,  0x9B,  0x23,  0xCF,  0xE4, 	/* 0C8F0 */
+	0x43,  0xC4,  0x24,  0x43,  0xC3,  0xC4,  0x09,  0x87,  0xFC,  0x04,  0x03,  0xF8,  0x04,  0x0F,  0xFE,  0x9D, 	/* 0C900 */
+	0x20,  0x0F,  0xBE,  0x22,  0x2F,  0xA2,  0x8B,  0xEF,  0xA2,  0x8A,  0x2F,  0xBE,  0x22,  0x2F,  0xA2,  0x24, 	/* 0C910 */
+	0x22,  0x86,  0x9E,  0x10,  0x83,  0xFC,  0x10,  0x81,  0xF8,  0x10,  0x8F,  0xFE,  0x10,  0x83,  0xFC,  0xD0, 	/* 0C920 */
+	0xA1,  0xF9,  0x10,  0x82,  0x18,  0x9F,  0x24,  0x02,  0x5E,  0xFF,  0x22,  0x52,  0x3D,  0xE2,  0x52,  0x3D, 	/* 0C930 */
+	0x22,  0x5E,  0xFF,  0x22,  0xA2,  0x46,  0x28,  0x46,  0xA6,  0x04,  0x47,  0xFE,  0x55,  0x45,  0xFE,  0x78, 	/* 0C940 */
+	0x25,  0x7C,  0x5D,  0x27,  0x3C,  0x5C,  0xC5,  0x3A,  0x5C,  0x9B,  0x30,  0xA7,  0x04,  0x8F,  0xFE,  0xAA, 	/* 0C950 */
+	0x8B,  0xFE,  0xE0,  0x2A,  0xEE,  0xAA,  0x8E,  0xEE,  0xAA,  0x8A,  0xEE,  0xAA,  0x8A,  0xA6,  0xA8,  0x04, 	/* 0C960 */
+	0x00,  0x40,  0x04,  0x0F,  0xFE,  0x0E,  0x00,  0xE0,  0x15,  0x02,  0x48,  0x44,  0x48,  0x42,  0x04,  0x00, 	/* 0C970 */
+	0x40,  0xAA,  0x04,  0x00,  0x40,  0x3F,  0x80,  0x40,  0x04,  0x0F,  0xFE,  0x04,  0x00,  0xE0,  0x35,  0x8C, 	/* 0C980 */
+	0x46,  0x04,  0x00,  0x40,  0xAB,  0x04,  0x00,  0x40,  0xFF,  0xE0,  0x40,  0x04,  0x03,  0xF8,  0x04,  0x00, 	/* 0C990 */
+	0xE0,  0x35,  0x8C,  0x46,  0x04,  0x00,  0x40,  0xAC,  0x04,  0x00,  0x40,  0x04,  0x0F,  0xFE,  0x0E,  0x00, 	/* 0C9A0 */
+	0xE0,  0x15,  0x02,  0x48,  0x5F,  0x48,  0x42,  0x04,  0x00,  0x40,  0xAD,  0x12,  0x01,  0x20,  0xFE,  0x01, 	/* 0C9B0 */
+	0x20,  0x12,  0x03,  0xA0,  0x36,  0x05,  0x20,  0x92,  0x01,  0x22,  0x12,  0x21,  0x1E,  0xAE,  0x04,  0x00, 	/* 0C9C0 */
+	0x48,  0x04,  0x4F,  0xFE,  0x04,  0x02,  0x50,  0x25,  0x02,  0x50,  0x25,  0x24,  0x52,  0x84,  0xE0,  0x40, 	/* 0C9D0 */
+	0xB1,  0x04,  0x02,  0x40,  0x24,  0x03,  0xFC,  0x24,  0x04,  0x40,  0xFF,  0xE0,  0xE0,  0x35,  0x8C,  0x46, 	/* 0C9E0 */
+	0x04,  0x00,  0x40,  0xB4,  0x11,  0x01,  0x10,  0x11,  0x07,  0xD0,  0x11,  0x83,  0x14,  0x39,  0x25,  0x52, 	/* 0C9F0 */
+	0x91,  0x01,  0x10,  0x11,  0x01,  0x10,  0xB6,  0x00,  0x07,  0xF0,  0x09,  0x00,  0x9E,  0x10,  0x22,  0x42, 	/* 0CA00 */
+	0x44,  0xCF,  0xFE,  0x0E,  0x03,  0x58,  0xC4,  0x60,  0x40,  0xB7,  0x20,  0x02,  0x7E,  0x21,  0x2F,  0x92, 	/* 0CA10 */
+	0x21,  0x23,  0x12,  0x69,  0x26,  0x22,  0xA2,  0x2A,  0x42,  0x28,  0x23,  0x0C,  0xB8,  0x21,  0x02,  0x10, 	/* 0CA20 */
+	0x21,  0x0F,  0xFE,  0x21,  0x23,  0x12,  0x69,  0x26,  0x12,  0xA2,  0x2A,  0x22,  0x24,  0x22,  0x8C,  0xBA, 	/* 0CA30 */
+	0x20,  0x02,  0x3C,  0x22,  0x4F,  0xA4,  0x22,  0x46,  0x24,  0x72,  0x46,  0xA4,  0xA2,  0x4A,  0x45,  0x24, 	/* 0CA40 */
+	0x52,  0x83,  0xBD,  0x20,  0x02,  0xFE,  0x22,  0x0F,  0xA0,  0x22,  0x06,  0x7C,  0x74,  0x46,  0x84,  0xA0, 	/* 0CA50 */
+	0x4A,  0x04,  0x20,  0x42,  0x18,  0xBF,  0x04,  0x00,  0x40,  0xFF,  0xE0,  0x40,  0x7F,  0xC4,  0x44,  0x44, 	/* 0CA60 */
+	0x44,  0xEC,  0x15,  0x02,  0x48,  0xC4,  0x60,  0x40,  0x81,  0x23,  0x02,  0x10,  0xF9,  0x02,  0x10,  0x21, 	/* 0CA70 */
+	0x07,  0x10,  0x6A,  0x8A,  0x28,  0xA4,  0x42,  0x44,  0x28,  0x23,  0x01,  0x86,  0x20,  0x02,  0x7C,  0xF9, 	/* 0CA80 */
+	0x02,  0x10,  0x31,  0x06,  0xFE,  0x61,  0x0A,  0x10,  0xA1,  0x02,  0x10,  0x21,  0x02,  0x10,  0x89,  0x20, 	/* 0CA90 */
+	0x82,  0x08,  0x21,  0x0F,  0xA4,  0x24,  0x43,  0x08,  0x69,  0x26,  0x62,  0xA0,  0x4A,  0x08,  0x21,  0x02, 	/* 0CAA0 */
+	0x60,  0x8E,  0x04,  0x0F,  0xFE,  0x0E,  0x01,  0x50,  0x24,  0x8C,  0x46,  0x3F,  0x00,  0x20,  0xFF,  0xE0, 	/* 0CAB0 */
+	0x40,  0x04,  0x00,  0xC0,  0x8F,  0x04,  0x00,  0x40,  0xFF,  0xE0,  0xE0,  0x15,  0x02,  0x48,  0xC4,  0x63, 	/* 0CAC0 */
+	0xF8,  0x20,  0x82,  0x08,  0x20,  0x83,  0xF8,  0x90,  0x20,  0x82,  0x08,  0x20,  0x8F,  0xFE,  0x20,  0x86, 	/* 0CAD0 */
+	0x18,  0x71,  0x86,  0xA8,  0xA4,  0x8A,  0x88,  0x20,  0x82,  0x18,  0x91,  0x10,  0x41,  0x04,  0x7F,  0xF1, 	/* 0CAE0 */
+	0x04,  0x30,  0x43,  0xA4,  0x55,  0x45,  0x14,  0x90,  0x41,  0x04,  0x10,  0x41,  0x0C,  0x93,  0x22,  0x02, 	/* 0CAF0 */
+	0x20,  0x23,  0xEF,  0x22,  0x24,  0x26,  0xA2,  0x71,  0x2A,  0x92,  0xA0,  0x22,  0x02,  0x20,  0x22,  0x0C, 	/* 0CB00 */
+	0x96,  0x20,  0x82,  0x08,  0x20,  0x8F,  0xFE,  0x24,  0x87,  0x48,  0x6A,  0x8A,  0x30,  0xA1,  0x02,  0x28, 	/* 0CB10 */
+	0x24,  0x43,  0x82,  0x99,  0x22,  0x02,  0x28,  0xFA,  0x42,  0x3E,  0x2E,  0x07,  0x20,  0x6A,  0x0A,  0x10, 	/* 0CB20 */
+	0xA1,  0x02,  0x0A,  0x20,  0x62,  0x02,  0x9C,  0x21,  0x02,  0x10,  0x21,  0x0F,  0x90,  0x27,  0xC2,  0x10, 	/* 0CB30 */
+	0x71,  0x06,  0x90,  0xA1,  0x0A,  0x10,  0x21,  0x02,  0xFE,  0x9E,  0x20,  0x02,  0x7C,  0x20,  0x4F,  0x84, 	/* 0CB40 */
+	0x20,  0x43,  0x7C,  0x6C,  0x06,  0x40,  0xA4,  0x0A,  0x42,  0x24,  0x22,  0x3E,  0x9F,  0x04,  0x07,  0xFE, 	/* 0CB50 */
+	0x04,  0x03,  0xFC,  0x24,  0x42,  0x44,  0x3F,  0xC0,  0xE0,  0x15,  0x02,  0x48,  0xC4,  0x60,  0x40,  0xA0, 	/* 0CB60 */
+	0x20,  0x02,  0x7C,  0xF9,  0x02,  0x10,  0x21,  0x07,  0x10,  0x69,  0x0A,  0x10,  0xA1,  0x02,  0x10,  0x21, 	/* 0CB70 */
+	0x02,  0xFE,  0xA1,  0x08,  0x01,  0xF8,  0x31,  0x0C,  0xA0,  0x1F,  0x0E,  0x4E,  0x04,  0x0F,  0xFE,  0x0E, 	/* 0CB80 */
+	0x03,  0x58,  0xC4,  0x60,  0x40,  0xA2,  0x04,  0x00,  0x40,  0xFF,  0xE0,  0xE0,  0x35,  0x8C,  0x46,  0x04, 	/* 0CB90 */
+	0x07,  0xFC,  0x04,  0x00,  0x40,  0x04,  0x0F,  0xFE,  0xA3,  0x21,  0x02,  0x10,  0xF9,  0x02,  0x10,  0x29, 	/* 0CBA0 */
+	0x27,  0x92,  0x69,  0x2A,  0x92,  0xA9,  0x22,  0x92,  0x29,  0x22,  0xFE,  0xA4,  0x20,  0x02,  0xFE,  0xFA, 	/* 0CBB0 */
+	0x02,  0x20,  0x23,  0xC7,  0x24,  0x6A,  0x4A,  0x24,  0xA4,  0x42,  0x44,  0x28,  0x43,  0x18,  0xA5,  0x04, 	/* 0CBC0 */
+	0x00,  0x40,  0x7F,  0xC2,  0x48,  0x14,  0x81,  0x50,  0xFF,  0xE0,  0xE0,  0x15,  0x02,  0x48,  0xC4,  0x60, 	/* 0CBD0 */
+	0x40,  0xAA,  0x21,  0x02,  0x10,  0xF5,  0x42,  0x54,  0x35,  0x26,  0x92,  0x71,  0x4A,  0x34,  0xA0,  0x82, 	/* 0CBE0 */
+	0x10,  0x26,  0x03,  0x80,  0xAD,  0x22,  0x02,  0x20,  0x2F,  0xEF,  0x00,  0x27,  0x86,  0x48,  0x74,  0x86, 	/* 0CBF0 */
+	0xC8,  0xA4,  0x8A,  0x4A,  0x28,  0xA3,  0x06,  0xAF,  0x20,  0x02,  0xFE,  0x20,  0x8F,  0x88,  0x21,  0x07, 	/* 0CC00 */
+	0x18,  0x6B,  0x46,  0x52,  0xA9,  0x2A,  0x10,  0x21,  0x02,  0x10,  0xB0,  0x04,  0x00,  0x40,  0xFF,  0xE0, 	/* 0CC10 */
+	0x40,  0x0E,  0x03,  0x58,  0xC4,  0x60,  0x40,  0x04,  0x05,  0x24,  0x49,  0x28,  0x92,  0xB1,  0x04,  0x0F, 	/* 0CC20 */
+	0xFE,  0x04,  0x07,  0xFC,  0x44,  0x47,  0xFC,  0x44,  0x47,  0xFC,  0x0E,  0x03,  0x58,  0xC4,  0x60,  0x40, 	/* 0CC30 */
+	0xB2,  0x00,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x04,  0x0F,  0xFE,  0x0E,  0x03,  0x58, 	/* 0CC40 */
+	0xC4,  0x60,  0x40,  0xB3,  0x04,  0x0F,  0xFE,  0x04,  0x00,  0xE0,  0x35,  0x8C,  0x46,  0x3F,  0x82,  0x08, 	/* 0CC50 */
+	0x3F,  0x82,  0x08,  0x20,  0x83,  0xF8,  0xB5,  0x24,  0x02,  0x40,  0x27,  0xCF,  0x50,  0x29,  0x06,  0x10, 	/* 0CC60 */
+	0x77,  0xE6,  0x90,  0xA1,  0x0A,  0x10,  0x21,  0x02,  0x10,  0xB7,  0x20,  0x02,  0xFC,  0x2A,  0x4F,  0xA4, 	/* 0CC70 */
+	0x2A,  0x46,  0xFC,  0x78,  0x06,  0x80,  0xA8,  0x0A,  0x82,  0x28,  0x22,  0x7E,  0xBC,  0x27,  0xC2,  0x04, 	/* 0CC80 */
+	0xFA,  0x82,  0x10,  0x2F,  0xE7,  0x12,  0x69,  0x4A,  0x10,  0xA1,  0x02,  0x10,  0x21,  0x02,  0x30,  0xBE, 	/* 0CC90 */
+	0x23,  0x82,  0x28,  0xF2,  0x82,  0x44,  0x25,  0x46,  0x92,  0x71,  0x0A,  0xA0,  0xA2,  0x82,  0x4C,  0x2F, 	/* 0CCA0 */
+	0x22,  0x02,  0xBF,  0x20,  0x02,  0x7E,  0x24,  0x0F,  0xC0,  0x27,  0xC6,  0x44,  0x75,  0x46,  0xD8,  0xA4, 	/* 0CCB0 */
+	0x8A,  0x94,  0x2A,  0x43,  0x42,  0x85,  0x20,  0x02,  0x7E,  0xFA,  0x42,  0x24,  0x32,  0x46,  0xFE,  0x62, 	/* 0CCC0 */
+	0x4A,  0x24,  0xA2,  0x42,  0x44,  0x24,  0x42,  0x84,  0x87,  0x29,  0x02,  0x90,  0x29,  0x0F,  0x92,  0x2F, 	/* 0CCD0 */
+	0xC2,  0x90,  0x79,  0x06,  0x90,  0xA9,  0x0A,  0x92,  0x2F,  0x23,  0x8E,  0x89,  0x20,  0x02,  0xFE,  0xF9, 	/* 0CCE0 */
+	0x02,  0x10,  0x21,  0x07,  0x7C,  0x69,  0x0A,  0x10,  0xA1,  0x02,  0x10,  0x21,  0x02,  0xFE,  0x8B,  0x22, 	/* 0CCF0 */
+	0x02,  0x20,  0xFF,  0xE2,  0x20,  0x22,  0x07,  0x3C,  0x6A,  0x4A,  0x24,  0xA2,  0x42,  0x44,  0x24,  0x42, 	/* 0CD00 */
+	0x98,  0x8C,  0x24,  0x82,  0x48,  0xFC,  0x42,  0x44,  0x28,  0x27,  0x7C,  0x6A,  0x4A,  0x24,  0xA2,  0x42, 	/* 0CD10 */
+	0x24,  0x24,  0x42,  0x98,  0x90,  0x20,  0x42,  0x78,  0x24,  0x0F,  0xC0,  0x27,  0xE3,  0x48,  0x6C,  0x86, 	/* 0CD20 */
+	0x48,  0xA4,  0x8A,  0x88,  0x28,  0x83,  0x08,  0x95,  0x22,  0x02,  0x20,  0x22,  0x0F,  0xFE,  0x2A,  0x26, 	/* 0CD30 */
+	0xB2,  0x73,  0x06,  0xB0,  0xA5,  0x0A,  0x52,  0x29,  0x23,  0x0E,  0x97,  0x21,  0x02,  0x10,  0xFF,  0xE2, 	/* 0CD40 */
+	0x10,  0x33,  0x87,  0x38,  0x6D,  0x4A,  0x52,  0xA9,  0x02,  0x10,  0x21,  0x02,  0x10,  0x9A,  0x22,  0x02, 	/* 0CD50 */
+	0x20,  0x23,  0xEF,  0xA4,  0x24,  0x47,  0x44,  0x6A,  0x86,  0xA8,  0xA1,  0x0A,  0x18,  0x22,  0x42,  0xC2, 	/* 0CD60 */
+	0x9C,  0x00,  0x03,  0xFC,  0x24,  0x43,  0xFC,  0x24,  0x43,  0xFC,  0x04,  0x07,  0xFE,  0x0E,  0x03,  0x58, 	/* 0CD70 */
+	0xC4,  0x60,  0x40,  0x9D,  0x21,  0x02,  0x10,  0x27,  0xEF,  0x90,  0x21,  0x06,  0xFC,  0x70,  0x46,  0x68, 	/* 0CD80 */
+	0xA1,  0x0A,  0x28,  0x24,  0x43,  0x82,  0xA0,  0x22,  0x02,  0x20,  0x2F,  0x8F,  0xA8,  0x22,  0xA7,  0x46, 	/* 0CD90 */
+	0x69,  0x06,  0xFE,  0xA1,  0x0A,  0x10,  0x21,  0x02,  0x10,  0xA1,  0x23,  0x42,  0xE4,  0xF2,  0x42,  0x24, 	/* 0CDA0 */
+	0x32,  0x46,  0xFE,  0x62,  0x4A,  0x24,  0xA2,  0x42,  0x44,  0x24,  0x42,  0x84,  0xA2,  0x20,  0x02,  0x7E, 	/* 0CDB0 */
+	0x24,  0x4F,  0xC4,  0x26,  0x43,  0x58,  0x6C,  0x86,  0x54,  0xA5,  0x4A,  0x60,  0x24,  0x02,  0x7E,  0xA6, 	/* 0CDC0 */
+	0x27,  0xE2,  0x00,  0xFF,  0xE2,  0x42,  0x24,  0x27,  0x7E,  0x6C,  0x0A,  0x40,  0xA4,  0x02,  0x80,  0x28, 	/* 0CDD0 */
+	0x03,  0x00,  0xA9,  0x04,  0x0F,  0xFE,  0x04,  0x00,  0xE0,  0x35,  0x8C,  0x46,  0x11,  0x02,  0x4C,  0xC4, 	/* 0CDE0 */
+	0x20,  0x90,  0x13,  0x87,  0xC4,  0xAF,  0x21,  0x02,  0x10,  0x21,  0x0F,  0xFE,  0x21,  0x06,  0x10,  0x71, 	/* 0CDF0 */
+	0x06,  0xFC,  0xA4,  0x4A,  0x44,  0x24,  0x42,  0x7C,  0xB3,  0x20,  0x02,  0x7C,  0xFC,  0x42,  0x44,  0x34, 	/* 0CE00 */
+	0x46,  0xC4,  0x67,  0xCA,  0x00,  0xA2,  0x82,  0x24,  0x24,  0x22,  0x82,  0xB4,  0x20,  0x02,  0x7C,  0xFC, 	/* 0CE10 */
+	0x42,  0x44,  0x27,  0xC7,  0x00,  0x6F,  0xEA,  0x12,  0xA1,  0x22,  0x22,  0x24,  0x22,  0x8C,  0xB6,  0x20, 	/* 0CE20 */
+	0x0F,  0xBC,  0x2A,  0x42,  0xA4,  0x4A,  0x4B,  0x3C,  0x04,  0x0F,  0xFE,  0x0E,  0x03,  0x58,  0xC4,  0x60, 	/* 0CE30 */
+	0x40,  0xB7,  0x28,  0x02,  0x80,  0xF8,  0xE3,  0xEA,  0x2A,  0xA7,  0xAA,  0x7A,  0xAA,  0xAA,  0xAA,  0xA2, 	/* 0CE40 */
+	0xAA,  0x32,  0xE2,  0xC0,  0xB8,  0x22,  0x02,  0x20,  0xFB,  0xE2,  0x42,  0x28,  0x27,  0x3A,  0x6A,  0xAA, 	/* 0CE50 */
+	0x2A,  0xA3,  0xA2,  0x02,  0x20,  0x22,  0x0C,  0xB9,  0x22,  0x02,  0x20,  0xFB,  0xE2,  0x42,  0x2B,  0xA7, 	/* 0CE60 */
+	0x2A,  0x6A,  0xAA,  0x3A,  0xA2,  0xC2,  0x20,  0x22,  0x12,  0x1F,  0x81,  0x20,  0x82,  0x7E,  0x24,  0x2F, 	/* 0CE70 */
+	0x42,  0x22,  0x06,  0x26,  0x73,  0x86,  0xA0,  0xA2,  0x0A,  0x22,  0x22,  0x22,  0x1E,  0x84,  0x20,  0x02, 	/* 0CE80 */
+	0x7E,  0x21,  0x0F,  0x90,  0x27,  0xE2,  0x52,  0x75,  0xA6,  0xE6,  0xA6,  0x6A,  0x42,  0x24,  0x22,  0x46, 	/* 0CE90 */
+	0x86,  0x21,  0x02,  0x10,  0xF9,  0x02,  0xFE,  0x30,  0x46,  0xC4,  0x64,  0x4A,  0x24,  0xA2,  0x82,  0x28, 	/* 0CEA0 */
+	0x21,  0x02,  0xFE,  0x8A,  0x22,  0x02,  0x3C,  0x24,  0x4F,  0xC8,  0x23,  0x07,  0x28,  0x74,  0x66,  0xB0, 	/* 0CEB0 */
+	0xA0,  0xCA,  0x60,  0x21,  0x82,  0x06,  0x8E,  0x22,  0x42,  0x24,  0xFC,  0x42,  0x7E,  0x2C,  0x47,  0x44, 	/* 0CEC0 */
+	0x6E,  0x4A,  0x54,  0xA4,  0x42,  0x44,  0x24,  0x42,  0x4C,  0x8F,  0x21,  0x02,  0x10,  0x22,  0x0F,  0x7E, 	/* 0CED0 */
+	0x24,  0x26,  0x42,  0x77,  0xE6,  0xC2,  0xA4,  0x2A,  0x42,  0x24,  0x22,  0x7E,  0x90,  0x11,  0x0F,  0xFE, 	/* 0CEE0 */
+	0x11,  0x01,  0xF0,  0x11,  0x01,  0xF0,  0x04,  0x0F,  0xFE,  0x0E,  0x03,  0x58,  0xC4,  0x60,  0x40,  0x91, 	/* 0CEF0 */
+	0x24,  0x42,  0x44,  0x2F,  0xEF,  0xC4,  0x24,  0x46,  0x44,  0x77,  0xC6,  0xC4,  0xA4,  0x4A,  0x44,  0x24, 	/* 0CF00 */
+	0x42,  0x7C,  0x93,  0x22,  0x01,  0x20,  0xCF,  0x80,  0x2A,  0x32,  0xAC,  0x46,  0x04,  0x0F,  0xFE,  0x0E, 	/* 0CF10 */
+	0x03,  0x58,  0xC4,  0x60,  0x40,  0x94,  0x3F,  0x80,  0x90,  0x06,  0x0F,  0xFE,  0x0C,  0x43,  0x48,  0xCC, 	/* 0CF20 */
+	0x0F,  0xFE,  0x0E,  0x03,  0x58,  0xC4,  0x60,  0x40,  0x98,  0x20,  0x02,  0xFE,  0x21,  0x0F,  0x90,  0x21, 	/* 0CF30 */
+	0x07,  0x20,  0x6B,  0xE6,  0x62,  0xAA,  0x2B,  0x22,  0x22,  0x22,  0x3E,  0x9A,  0x21,  0x02,  0x10,  0x21, 	/* 0CF40 */
+	0x0F,  0x10,  0x2F,  0xE6,  0x92,  0x79,  0x26,  0xFE,  0xA9,  0x2A,  0x92,  0x29,  0x22,  0xFE,  0x9D,  0x20, 	/* 0CF50 */
+	0xC2,  0x70,  0xFC,  0x02,  0x40,  0x27,  0xE7,  0x48,  0x6D,  0x8A,  0x4C,  0xA8,  0xA2,  0x88,  0x30,  0x82, 	/* 0CF60 */
+	0x08,  0x9E,  0x24,  0x02,  0x40,  0xFF,  0xE2,  0x50,  0x29,  0x07,  0x1C,  0x69,  0x0A,  0x10,  0xA1,  0xC2, 	/* 0CF70 */
+	0x10,  0x21,  0x02,  0x10,  0xA2,  0x20,  0xC2,  0x70,  0xF4,  0x82,  0x48,  0x27,  0xE7,  0x48,  0x6C,  0x8A, 	/* 0CF80 */
+	0x4A,  0xA4,  0x62,  0x76,  0x38,  0x22,  0xF8,  0xA4,  0x20,  0x02,  0x3C,  0xFA,  0x42,  0x24,  0x33,  0xC6, 	/* 0CF90 */
+	0xA4,  0x62,  0x4A,  0x3C,  0xA2,  0x42,  0x24,  0x22,  0x42,  0xFE,  0xA7,  0x20,  0x62,  0x78,  0xFD,  0x42, 	/* 0CFA0 */
+	0x54,  0x25,  0x47,  0x54,  0x6D,  0x4A,  0x54,  0xA5,  0xC2,  0x56,  0x27,  0xE2,  0x81,  0xA9,  0x20,  0x02, 	/* 0CFB0 */
+	0x7E,  0xFD,  0x02,  0x5C,  0x35,  0x46,  0xE4,  0x64,  0x8A,  0x4C,  0xA5,  0x22,  0x62,  0x24,  0x02,  0x7E, 	/* 0CFC0 */
+	0xAC,  0x04,  0x0F,  0xFE,  0x04,  0x07,  0xFC,  0x64,  0xC5,  0x54,  0x7F,  0xC0,  0xE0,  0x15,  0x02,  0x48, 	/* 0CFD0 */
+	0xC4,  0x60,  0x40,  0xAE,  0x20,  0x82,  0x08,  0xFC,  0xA2,  0x4A,  0x24,  0xA7,  0x7E,  0x68,  0x8A,  0x4A, 	/* 0CFE0 */
+	0xA4,  0xA2,  0x4A,  0x24,  0xA2,  0x7E,  0xAF,  0x20,  0x02,  0xFE,  0xF0,  0x42,  0x04,  0x37,  0x46,  0xD4, 	/* 0CFF0 */
+	0x65,  0x4A,  0x54,  0xA7,  0x42,  0x04,  0x20,  0x42,  0x0C,  0xB1,  0x22,  0x02,  0x10,  0x2F,  0xEF,  0x10, 	/* 0D000 */
+	0x21,  0x03,  0x10,  0x6F,  0xC6,  0x10,  0xA1,  0x0A,  0x10,  0x21,  0x02,  0xFE,  0xB3,  0x22,  0x02,  0xCE, 	/* 0D010 */
+	0x2A,  0xAF,  0xAA,  0x2A,  0xA6,  0xAA,  0x7A,  0xA6,  0xAA,  0xAE,  0xAA,  0xAE,  0x22,  0x82,  0x48,  0xB4, 	/* 0D020 */
+	0x12,  0x05,  0x26,  0x5B,  0x85,  0x20,  0x5E,  0x2F,  0x1E,  0x04,  0x0F,  0xFE,  0x0E,  0x03,  0x58,  0xC4, 	/* 0D030 */
+	0x60,  0x40,  0xB5,  0x20,  0x02,  0x7C,  0x25,  0x4F,  0xD4,  0x25,  0x46,  0xFE,  0x75,  0x46,  0xD4,  0xA5, 	/* 0D040 */
+	0x4A,  0x54,  0x25,  0x42,  0x4C,  0xBB,  0x04,  0x0F,  0xFE,  0x0E,  0x01,  0x50,  0x24,  0x8D,  0xF6,  0x11, 	/* 0D050 */
+	0x01,  0xF0,  0x11,  0x01,  0xF0,  0x11,  0x0F,  0xFE,  0xBE,  0x20,  0x02,  0xFE,  0x21,  0x0F,  0x90,  0x25, 	/* 0D060 */
+	0x06,  0x5C,  0x75,  0x06,  0xD0,  0xA5,  0x0A,  0x50,  0x25,  0x02,  0xFE,  0xBF,  0x21,  0x02,  0x10,  0x2F, 	/* 0D070 */
+	0xEF,  0x10,  0x27,  0xE6,  0x52,  0x75,  0x26,  0xD2,  0xA5,  0x2A,  0x56,  0x21,  0x02,  0x10,  0x82,  0x27, 	/* 0D080 */
+	0xC2,  0x44,  0x25,  0x4F,  0x4C,  0x2F,  0xE3,  0x44,  0x6D,  0x46,  0x4C,  0xA4,  0x4A,  0x7E,  0x20,  0x42, 	/* 0D090 */
+	0x18,  0x83,  0x20,  0x42,  0x78,  0x24,  0x0F,  0x7E,  0x25,  0x03,  0x50,  0x6D,  0xE6,  0x52,  0xA9,  0x2A, 	/* 0D0A0 */
+	0xA2,  0x32,  0x22,  0x4C,  0x84,  0x48,  0x42,  0x48,  0x25,  0x0F,  0xFE,  0x84,  0x28,  0x42,  0x7F,  0xC0, 	/* 0D0B0 */
+	0xE0,  0x15,  0x02,  0x48,  0xC4,  0x60,  0x40,  0x93,  0x21,  0x02,  0x10,  0x22,  0x8F,  0x44,  0x3F,  0xE2, 	/* 0D0C0 */
+	0x10,  0x71,  0x06,  0xFC,  0xA1,  0x0A,  0x10,  0x21,  0x02,  0xFE,  0x96,  0x20,  0x02,  0xFE,  0x22,  0x8F, 	/* 0D0D0 */
+	0xA8,  0x2F,  0xE2,  0xAA,  0x7A,  0xA6,  0xCE,  0xA8,  0x2A,  0x82,  0x2F,  0xE2,  0x80,  0x97,  0x00,  0x0F, 	/* 0D0E0 */
+	0xFE,  0x0A,  0x07,  0xFC,  0x4A,  0x47,  0xFC,  0x04,  0x0F,  0xFE,  0x0E,  0x03,  0x58,  0xC4,  0x60,  0x40, 	/* 0D0F0 */
+	0x9E,  0x00,  0x07,  0xBC,  0x20,  0x8F,  0xFE,  0x20,  0x82,  0x48,  0x04,  0x0F,  0xFE,  0x0E,  0x03,  0x58, 	/* 0D100 */
+	0xC4,  0x60,  0x40,  0xA1,  0x21,  0x02,  0x10,  0x2F,  0xEF,  0x28,  0x24,  0x46,  0xCA,  0x72,  0x86,  0x28, 	/* 0D110 */
+	0xA1,  0x0A,  0x28,  0x24,  0x43,  0x82,  0xA2,  0x20,  0x02,  0xFE,  0x21,  0x0F,  0x20,  0x27,  0xC6,  0x44, 	/* 0D120 */
+	0x74,  0x46,  0x7C,  0xA4,  0x4A,  0x44,  0x24,  0x42,  0x7C,  0xA9,  0x20,  0x02,  0xFE,  0xF2,  0x22,  0x66, 	/* 0D130 */
+	0x2A,  0xA7,  0x22,  0x6A,  0x2A,  0x66,  0xAA,  0xA2,  0x22,  0x22,  0x22,  0x66,  0xAA,  0x21,  0x02,  0x50, 	/* 0D140 */
+	0x27,  0xCF,  0xD0,  0x29,  0x06,  0xFE,  0x71,  0x06,  0xB8,  0xA3,  0x8A,  0x54,  0x29,  0x22,  0x10,  0xAB, 	/* 0D150 */
+	0x21,  0x02,  0x10,  0xFF,  0xE2,  0x20,  0x23,  0xE7,  0x44,  0x6C,  0x8B,  0x7E,  0xA4,  0x82,  0x48,  0x24, 	/* 0D160 */
+	0x82,  0x58,  0xB2,  0x21,  0x02,  0x12,  0x27,  0xCF,  0x14,  0x2F,  0xE6,  0x20,  0x77,  0xE6,  0xA0,  0xA3, 	/* 0D170 */
+	0xCA,  0x44,  0x20,  0x42,  0x18,  0xB4,  0x28,  0x02,  0x80,  0x2F,  0xEF,  0x80,  0x37,  0xC6,  0x54,  0x75, 	/* 0D180 */
+	0x47,  0xFE,  0xA4,  0x4A,  0x44,  0x24,  0x42,  0x4C,  0xB8,  0x21,  0x02,  0x10,  0x2F,  0xEF,  0x20,  0x22, 	/* 0D190 */
+	0x87,  0x68,  0x69,  0x06,  0x24,  0xAC,  0x8A,  0x18,  0x22,  0x42,  0xC2,  0xB9,  0x20,  0x02,  0x7C,  0x24, 	/* 0D1A0 */
+	0x4F,  0x7C,  0x24,  0x46,  0x7C,  0x76,  0x26,  0xD4,  0xA5,  0x8A,  0x48,  0x27,  0x42,  0xC2,  0xBC,  0x22, 	/* 0D1B0 */
+	0x02,  0x3C,  0x22,  0x4F,  0x64,  0x29,  0x86,  0x14,  0x72,  0x26,  0xFD,  0xA2,  0x4A,  0x24,  0x22,  0x42, 	/* 0D1C0 */
+	0x3C,  0xBD,  0x12,  0x01,  0x28,  0x7E,  0x41,  0x20,  0xFF,  0xE1,  0x20,  0xFE,  0x41,  0x14,  0x38,  0x85, 	/* 0D1D0 */
+	0x4A,  0x91,  0x61,  0x22,  0x80,  0x20,  0x83,  0x88,  0x4B,  0xEA,  0xA8,  0x12,  0x82,  0xFE,  0xC0,  0x80, 	/* 0D1E0 */
+	0x48,  0xFF,  0xE0,  0xE0,  0x35,  0x8C,  0x46,  0x81,  0x22,  0x02,  0x5C,  0x28,  0x0F,  0x20,  0x25,  0xE6, 	/* 0D1F0 */
+	0xC8,  0x74,  0x86,  0xC8,  0xA4,  0x8A,  0x48,  0x24,  0x82,  0x58,  0x82,  0x21,  0x02,  0x10,  0x27,  0xCF, 	/* 0D200 */
+	0x90,  0x21,  0x06,  0xFE,  0x71,  0x06,  0x90,  0xA7,  0xCA,  0x10,  0x21,  0x02,  0xFE,  0x83,  0x22,  0x82, 	/* 0D210 */
+	0x28,  0x2A,  0xAF,  0xAA,  0x26,  0xC2,  0x28,  0x76,  0xC6,  0xAA,  0xA2,  0xAA,  0x28,  0x24,  0xA2,  0x86, 	/* 0D220 */
+	0x86,  0x20,  0x02,  0xFE,  0xF8,  0x02,  0xBE,  0x28,  0x87,  0x88,  0x6B,  0xCA,  0x88,  0xA8,  0x82,  0xBE, 	/* 0D230 */
+	0x28,  0x02,  0xFE,  0x88,  0x04,  0x0F,  0xFE,  0x88,  0x2B,  0xFA,  0x11,  0x00,  0xE0,  0x35,  0x8F,  0xFE, 	/* 0D240 */
+	0x0E,  0x03,  0x58,  0xC4,  0x60,  0x40,  0x8D,  0x21,  0x02,  0x10,  0xFF,  0xE2,  0x28,  0x27,  0xC6,  0x82, 	/* 0D250 */
+	0x7F,  0xDA,  0x20,  0xA3,  0xC2,  0x44,  0x20,  0x42,  0x18,  0x8E,  0x20,  0x02,  0x7E,  0xF9,  0x02,  0x24, 	/* 0D260 */
+	0x2F,  0xA7,  0x12,  0x69,  0x0A,  0x7C,  0xA1,  0x02,  0x10,  0x21,  0x02,  0xFE,  0x90,  0x20,  0x02,  0xFE, 	/* 0D270 */
+	0x28,  0x2F,  0xBA,  0x28,  0x26,  0xBA,  0x7A,  0xA6,  0xAA,  0xAB,  0xAA,  0x82,  0x28,  0x22,  0x86,  0x91, 	/* 0D280 */
+	0x3F,  0x81,  0x10,  0x0E,  0x03,  0x18,  0xFF,  0xC4,  0xA4,  0x35,  0x8C,  0xE4,  0xFF,  0xE0,  0xE0,  0x35, 	/* 0D290 */
+	0x8C,  0x46,  0x93,  0x20,  0x02,  0xFE,  0x20,  0x0F,  0x7C,  0x24,  0x46,  0x44,  0x77,  0xC6,  0xC4,  0xA4, 	/* 0D2A0 */
+	0x4A,  0x7C,  0x20,  0x02,  0xFE,  0x94,  0x21,  0x02,  0x10,  0x2F,  0xEF,  0x10,  0x21,  0x06,  0x7C,  0x70, 	/* 0D2B0 */
+	0x06,  0xFC,  0xA4,  0x4A,  0x44,  0x24,  0x42,  0x7C,  0x99,  0x21,  0x02,  0x24,  0xFF,  0xE2,  0x12,  0x25, 	/* 0D2C0 */
+	0x07,  0x7C,  0x69,  0x0A,  0x10,  0xAF,  0xE2,  0x10,  0x21,  0x02,  0x10,  0x9C,  0x22,  0x42,  0x94,  0x25, 	/* 0D2D0 */
+	0x4F,  0xC8,  0x21,  0x07,  0x20,  0x6F,  0xE6,  0x48,  0xA4,  0x8A,  0xF0,  0x22,  0x82,  0xC4,  0x9D,  0x28, 	/* 0D2E0 */
+	0x42,  0x84,  0xFE,  0x42,  0xBE,  0x6E,  0x47,  0xA4,  0xAE,  0x4B,  0x3E,  0x24,  0x42,  0x44,  0x24,  0x42, 	/* 0D2F0 */
+	0x84,  0x9F,  0x22,  0x82,  0x24,  0x2F,  0xCF,  0x20,  0x2F,  0xC6,  0x20,  0x7F,  0xE6,  0x94,  0xA1,  0x8A, 	/* 0D300 */
+	0x2A,  0x2C,  0x63,  0x02,  0xA3,  0x21,  0x02,  0x92,  0xF5,  0x22,  0x54,  0x21,  0x07,  0x7E,  0x68,  0x2A, 	/* 0D310 */
+	0x02,  0xA7,  0xE2,  0x02,  0x20,  0x22,  0xFE,  0xA7,  0x21,  0x02,  0x10,  0x22,  0x8F,  0x44,  0x28,  0x26, 	/* 0D320 */
+	0x7C,  0x70,  0x06,  0xFE,  0xA2,  0x0A,  0x48,  0x25,  0xC2,  0xE4,  0xB4,  0x20,  0xE2,  0xF4,  0xF5,  0x22, 	/* 0D330 */
+	0x52,  0x28,  0x07,  0x7C,  0x68,  0x8A,  0x10,  0xAF,  0xE2,  0x10,  0x21,  0x02,  0x30,  0xB6,  0x2F,  0xC2, 	/* 0D340 */
+	0x48,  0x23,  0x0F,  0xFE,  0x29,  0x26,  0x92,  0x7F,  0xE6,  0x92,  0xAF,  0xEA,  0x92,  0x29,  0x22,  0x96, 	/* 0D350 */
+	0xB7,  0x21,  0x02,  0x3C,  0xF4,  0x82,  0xFE,  0x25,  0x27,  0x52,  0x6F,  0xEA,  0x52,  0xA7,  0xE2,  0x42, 	/* 0D360 */
+	0x28,  0x23,  0x06,  0xBE,  0x20,  0x02,  0xFC,  0xF2,  0x43,  0xFF,  0x22,  0x47,  0x24,  0x6F,  0xCA,  0x40, 	/* 0D370 */
+	0xAB,  0xE3,  0x22,  0x22,  0x22,  0x3E,  0xBF,  0x27,  0xC2,  0x44,  0xFF,  0xC2,  0x44,  0x27,  0xC7,  0x00, 	/* 0D380 */
+	0x6F,  0xEA,  0x10,  0xAF,  0xE2,  0x10,  0x21,  0x02,  0x10,  0x81,  0x80,  0x05,  0xF8,  0x84,  0x85,  0x4C, 	/* 0D390 */
+	0x28,  0xA5,  0x32,  0x84,  0x0F,  0xFE,  0x0E,  0x03,  0x58,  0xC4,  0x60,  0x40,  0x83,  0x20,  0x62,  0xF8, 	/* 0D3A0 */
+	0xF4,  0x82,  0x48,  0x2B,  0xE7,  0xC8,  0x64,  0x8B,  0x48,  0xAF,  0xE2,  0x40,  0x2B,  0x03,  0x0F,  0x85, 	/* 0D3B0 */
+	0x24,  0x02,  0x7E,  0xF4,  0x02,  0xFC,  0x2D,  0x47,  0x54,  0x6F,  0xE6,  0x54,  0xA5,  0x4A,  0xFE,  0x28, 	/* 0D3C0 */
+	0x42,  0x18,  0x8D,  0x22,  0x02,  0x7C,  0xFC,  0x42,  0x7C,  0x24,  0x47,  0x7C,  0x6A,  0x6A,  0x38,  0xAE, 	/* 0D3D0 */
+	0x02,  0x20,  0x22,  0x22,  0x1E,  0x8F,  0x25,  0x02,  0x50,  0xFF,  0xE2,  0x90,  0x21,  0x07,  0x7E,  0x69, 	/* 0D3E0 */
+	0x0A,  0x00,  0xA7,  0xC2,  0x44,  0x24,  0x42,  0x7C,  0x93,  0x21,  0x02,  0x10,  0x2F,  0xEF,  0x44,  0x22, 	/* 0D3F0 */
+	0x86,  0xFE,  0x71,  0x06,  0x10,  0xAF,  0xEA,  0x10,  0x21,  0x02,  0x10,  0x94,  0x20,  0x62,  0x78,  0xFC, 	/* 0D400 */
+	0x02,  0x7F,  0x24,  0x07,  0x7E,  0x6E,  0xAA,  0x6A,  0xAB,  0xE2,  0xA0,  0x32,  0x22,  0x1E,  0x97,  0x20, 	/* 0D410 */
+	0x02,  0xFE,  0x21,  0x0F,  0xFE,  0x25,  0x27,  0x7E,  0x6D,  0x2A,  0x7E,  0xA5,  0x02,  0x30,  0x26,  0xC2, 	/* 0D420 */
+	0x83,  0x9B,  0x20,  0x03,  0xEE,  0xFA,  0xA2,  0xAA,  0x3E,  0xC6,  0xAA,  0x6A,  0xAB,  0xEA,  0xAA,  0xA2, 	/* 0D430 */
+	0xAC,  0x32,  0x82,  0xC8,  0x9D,  0x22,  0x02,  0x3E,  0x24,  0x45,  0xA8,  0x53,  0x8D,  0xC6,  0x51,  0x05, 	/* 0D440 */
+	0xFE,  0x53,  0x85,  0x54,  0x59,  0x24,  0x10,  0x9F,  0x08,  0x03,  0xF8,  0x20,  0x83,  0xFE,  0x20,  0x03, 	/* 0D450 */
+	0xFC,  0x04,  0x40,  0x58,  0xFF,  0xF0,  0xE0,  0x35,  0x8C,  0x46,  0xA0,  0x20,  0x02,  0x7C,  0xFC,  0x42, 	/* 0D460 */
+	0x44,  0x27,  0xC7,  0x10,  0x6A,  0x0A,  0x7E,  0xA4,  0x22,  0x42,  0x24,  0x22,  0x7E,  0xA2,  0x21,  0x02, 	/* 0D470 */
+	0x92,  0x25,  0x4F,  0x10,  0x27,  0xC2,  0x44,  0x77,  0xC6,  0xC4,  0xA7,  0xCA,  0x44,  0x24,  0x42,  0x4C, 	/* 0D480 */
+	0xA6,  0x11,  0x0F,  0xFE,  0x11,  0x03,  0xB8,  0x55,  0x49,  0x12,  0x11,  0x01,  0xF8,  0x71,  0x00,  0xA0, 	/* 0D490 */
+	0x0C,  0x07,  0x00,  0xA7,  0x20,  0x02,  0xFE,  0x21,  0x0F,  0xFC,  0x22,  0x46,  0x24,  0x7F,  0xE6,  0x80, 	/* 0D4A0 */
+	0xA7,  0xCA,  0x44,  0xA4,  0x42,  0x7C,  0xA8,  0x18,  0x47,  0x24,  0x12,  0x4F,  0xE4,  0x3A,  0x45,  0x4C, 	/* 0D4B0 */
+	0x94,  0x0F,  0xFE,  0x0E,  0x03,  0x58,  0xC4,  0x60,  0x40,  0xAD,  0x21,  0x02,  0x24,  0xFF,  0xE2,  0x2A, 	/* 0D4C0 */
+	0x22,  0x87,  0x46,  0x6A,  0x0A,  0x3C,  0xA6,  0x42,  0x98,  0x23,  0x42,  0xC2,  0xAF,  0x24,  0x42,  0x28, 	/* 0D4D0 */
+	0x2F,  0xEF,  0x12,  0x27,  0xE2,  0x90,  0x7F,  0xE6,  0x32,  0xA3,  0x2A,  0x52,  0x39,  0x42,  0x10,  0xB0, 	/* 0D4E0 */
+	0x20,  0x62,  0x05,  0x2F,  0xFF,  0x04,  0x25,  0x47,  0x54,  0x6F,  0xD6,  0x55,  0xA5,  0x2A,  0x96,  0x30, 	/* 0D4F0 */
+	0x92,  0x11,  0xB1,  0x20,  0x02,  0xFE,  0x29,  0x2F,  0x92,  0x2F,  0xE6,  0x92,  0x7B,  0xA6,  0xBA,  0xAD, 	/* 0D500 */
+	0x6A,  0xD6,  0x29,  0x22,  0xFE,  0xB3,  0x21,  0x02,  0xFE,  0xF2,  0x82,  0x4C,  0x2F,  0x27,  0x00,  0x65, 	/* 0D510 */
+	0x4A,  0x54,  0xA5,  0x42,  0x55,  0x25,  0x52,  0x83,  0xB5,  0x20,  0x8F,  0xFE,  0x31,  0x86,  0xAC,  0xA4, 	/* 0D520 */
+	0xA2,  0x08,  0x1F,  0x01,  0x10,  0x19,  0x02,  0x52,  0x41,  0x28,  0x0E,  0xB6,  0x20,  0x02,  0x7E,  0x24, 	/* 0D530 */
+	0x2F,  0x7E,  0x24,  0x06,  0x7E,  0x74,  0x86,  0xFE,  0xA4,  0x82,  0x7D,  0x28,  0x92,  0x87,  0xB9,  0x20, 	/* 0D540 */
+	0xC2,  0x70,  0xFC,  0x02,  0x7C,  0x34,  0x86,  0xC8,  0x64,  0x8A,  0xFE,  0xA0,  0x02,  0x24,  0x24,  0x22, 	/* 0D550 */
+	0x82,  0xBA,  0x11,  0x0F,  0xFE,  0x39,  0x85,  0x74,  0x95,  0x21,  0x10,  0xFF,  0xE0,  0x60,  0x05,  0x80, 	/* 0D560 */
+	0x44,  0x04,  0x00,  0x40,  0xBC,  0x21,  0x02,  0xFE,  0x21,  0x0F,  0x7C,  0x21,  0x02,  0xFE,  0x72,  0x46, 	/* 0D570 */
+	0xFE,  0xA6,  0x4A,  0x94,  0x30,  0x42,  0x0C,  0x84,  0x04,  0x0F,  0xFE,  0x19,  0x07,  0xFC,  0x24,  0x8F, 	/* 0D580 */
+	0xFE,  0x24,  0x8F,  0xFE,  0x0E,  0x03,  0x58,  0xC4,  0x60,  0x40,  0x86,  0x21,  0x02,  0x10,  0xFA,  0x82, 	/* 0D590 */
+	0x44,  0x2F,  0xE7,  0x01,  0x6F,  0xEA,  0xAA,  0xAF,  0xE2,  0xAA,  0x2A,  0xA2,  0x86,  0x89,  0x21,  0x02, 	/* 0D5A0 */
+	0x7C,  0x24,  0x4F,  0x7C,  0x24,  0x47,  0x7C,  0x69,  0x06,  0x7E,  0xA5,  0x2A,  0x52,  0x25,  0x62,  0x10, 	/* 0D5B0 */
+	0x8A,  0x11,  0x0F,  0xFE,  0x11,  0x01,  0xF0,  0x11,  0x0F,  0xFE,  0x24,  0x84,  0x44,  0xBF,  0xA1,  0x50, 	/* 0D5C0 */
+	0x64,  0xC0,  0x40,  0x8B,  0x24,  0x42,  0x44,  0x2F,  0xEF,  0x44,  0x27,  0xC7,  0x44,  0x6F,  0xC6,  0x44, 	/* 0D5D0 */
+	0xAF,  0xEA,  0x28,  0x24,  0x42,  0x84,  0x8D,  0x20,  0x02,  0xFC,  0xF8,  0x42,  0xFC,  0x28,  0x46,  0xFC, 	/* 0D5E0 */
+	0x79,  0x0A,  0xF2,  0xA9,  0xC2,  0x90,  0x2F,  0x23,  0x8E,  0x92,  0x21,  0x02,  0xFE,  0x21,  0x0F,  0x7C, 	/* 0D5F0 */
+	0x22,  0x86,  0xFE,  0x75,  0x46,  0xBA,  0xA1,  0x0A,  0xFE,  0x21,  0x02,  0x10,  0x94,  0x20,  0x62,  0x78, 	/* 0D600 */
+	0xFC,  0x82,  0x7E,  0x24,  0x87,  0x76,  0x6C,  0x2A,  0x7C,  0xA4,  0x42,  0x7C,  0x24,  0x42,  0x7C,  0x95, 	/* 0D610 */
+	0x21,  0x02,  0xFE,  0xF8,  0x22,  0x82,  0x27,  0xC7,  0x00,  0x6F,  0xEA,  0x10,  0xA5,  0x42,  0x92,  0x31, 	/* 0D620 */
+	0x22,  0x30,  0x97,  0x04,  0x0F,  0xFE,  0x4E,  0x47,  0x58,  0xC4,  0x6F,  0xFE,  0x04,  0x07,  0xFC,  0x4E, 	/* 0D630 */
+	0x47,  0x58,  0xC4,  0x60,  0x40,  0x98,  0x20,  0x8F,  0xFE,  0x20,  0x8F,  0xBE,  0xAA,  0xAA,  0xAA,  0xAA, 	/* 0D640 */
+	0xA3,  0x0C,  0x69,  0xA6,  0x99,  0xA2,  0x82,  0x08,  0x9A,  0x20,  0x02,  0xEE,  0x2A,  0xAF,  0xAA,  0x2E, 	/* 0D650 */
+	0xE6,  0xAA,  0x7A,  0xA6,  0xEE,  0xAA,  0xAA,  0xAA,  0x2A,  0xA2,  0xB6,  0x9F,  0x21,  0x02,  0xFE,  0x21, 	/* 0D660 */
+	0x0F,  0x7E,  0x25,  0x23,  0x7E,  0x6D,  0x26,  0x7E,  0xA3,  0x8A,  0x54,  0x29,  0x22,  0x10,  0xA0,  0x44, 	/* 0D670 */
+	0x42,  0x48,  0xFF,  0xE9,  0xF2,  0x91,  0x21,  0xF0,  0x04,  0x0F,  0xFE,  0x0E,  0x03,  0x58,  0xC4,  0x60, 	/* 0D680 */
+	0x40,  0xA1,  0x20,  0x02,  0xFE,  0xFC,  0x62,  0xAA,  0x2F,  0xE7,  0x92,  0x6D,  0x6A,  0xD6,  0xAD,  0x62, 	/* 0D690 */
+	0xFE,  0x28,  0x22,  0x86,  0xA3,  0x21,  0x02,  0x7C,  0xF1,  0x42,  0xFE,  0x21,  0x47,  0x7C,  0x69,  0x2A, 	/* 0D6A0 */
+	0x54,  0xA3,  0x82,  0x54,  0x39,  0x22,  0x30,  0xA7,  0x21,  0x42,  0x1C,  0x2F,  0x0F,  0x14,  0x21,  0xA2, 	/* 0D6B0 */
+	0xE6,  0x71,  0x46,  0x1E,  0xAF,  0x4A,  0x18,  0x26,  0xA3,  0x86,  0xAE,  0x04,  0x07,  0xFC,  0x0E,  0x03, 	/* 0D6C0 */
+	0x58,  0xC4,  0x61,  0x48,  0x10,  0x8F,  0xFE,  0x31,  0x85,  0xAC,  0x94,  0xA1,  0x08,  0xAF,  0x21,  0x02, 	/* 0D6D0 */
+	0x28,  0x24,  0x4F,  0xBA,  0x20,  0x06,  0xFC,  0x70,  0x86,  0x10,  0xA2,  0x8A,  0xAA,  0x2A,  0x23,  0x1E, 	/* 0D6E0 */
+	0xB2,  0x21,  0x02,  0xFE,  0x21,  0x0F,  0x7C,  0x21,  0x46,  0xFE,  0x71,  0x46,  0xFE,  0xA2,  0x4A,  0x74, 	/* 0D6F0 */
+	0x21,  0x82,  0xE4,  0xB9,  0x21,  0x02,  0x1E,  0xF9,  0x02,  0x7C,  0x24,  0x47,  0x7C,  0x6C,  0x4A,  0x7C, 	/* 0D700 */
+	0xA1,  0x02,  0xFE,  0x21,  0x02,  0x10,  0xBA,  0x21,  0x02,  0xFE,  0x28,  0x2F,  0xFE,  0x24,  0x46,  0x44, 	/* 0D710 */
+	0x77,  0xC6,  0xC0,  0xA7,  0xEA,  0x42,  0x24,  0x22,  0x7E,  0x80,  0x21,  0x02,  0x10,  0x2F,  0xEF,  0x82, 	/* 0D720 */
+	0x2E,  0xE7,  0xAA,  0x6A,  0xA7,  0x6A,  0xA2,  0x8A,  0x48,  0x28,  0xA3,  0x06,  0x81,  0x21,  0x02,  0xFE, 	/* 0D730 */
+	0xF8,  0x02,  0x7C,  0x24,  0x47,  0x7C,  0x68,  0x0A,  0x7C,  0xA0,  0x82,  0xFF,  0x21,  0x02,  0x30,  0x84, 	/* 0D740 */
+	0x21,  0x02,  0xFE,  0xF4,  0x42,  0x28,  0x3F,  0xE6,  0x20,  0x7F,  0xEA,  0x48,  0xA4,  0x82,  0xF0,  0x22, 	/* 0D750 */
+	0x82,  0xC4,  0x85,  0x21,  0x02,  0x7E,  0x21,  0x0F,  0x28,  0x24,  0x46,  0xFE,  0x70,  0x46,  0x74,  0xA5, 	/* 0D760 */
+	0x4A,  0x74,  0x20,  0x42,  0x0C,  0x88,  0x22,  0x02,  0x20,  0xFB,  0xE2,  0x42,  0x29,  0x27,  0x56,  0x63, 	/* 0D770 */
+	0xAA,  0xFE,  0xA3,  0xA2,  0x56,  0x29,  0x22,  0x0C,  0x8B,  0x21,  0x02,  0xFE,  0x20,  0x0F,  0xFC,  0x24, 	/* 0D780 */
+	0x46,  0x44,  0x77,  0xC6,  0x90,  0xA5,  0x4A,  0x52,  0x29,  0x22,  0x30,  0x8C,  0x21,  0x02,  0xFE,  0xFA, 	/* 0D790 */
+	0xA2,  0xAA,  0x22,  0x87,  0x4E,  0x68,  0x0A,  0x7C,  0xA1,  0x02,  0x10,  0x21,  0x02,  0xFE,  0x8D,  0x20, 	/* 0D7A0 */
+	0x82,  0x7E,  0x20,  0x8F,  0xBC,  0x22,  0x42,  0xBC,  0x7A,  0x46,  0xBC,  0xAA,  0x4A,  0xBC,  0x28,  0x02, 	/* 0D7B0 */
+	0xFE,  0x8E,  0x22,  0x42,  0x28,  0x27,  0xEF,  0x48,  0x2C,  0x86,  0x7C,  0x74,  0x86,  0xC8,  0xA7,  0xCA, 	/* 0D7C0 */
+	0x48,  0x24,  0x82,  0x7E,  0x8F,  0x20,  0x02,  0xFE,  0xF2,  0x82,  0x28,  0x2E,  0xE7,  0x82,  0x68,  0x2A, 	/* 0D7D0 */
+	0x82,  0xAE,  0xE2,  0x28,  0x22,  0x82,  0xFE,  0x92,  0x24,  0x02,  0x5E,  0x27,  0x2F,  0x42,  0x24,  0xA3, 	/* 0D7E0 */
+	0xFA,  0x64,  0xC6,  0xE4,  0xAD,  0x4B,  0x4A,  0x25,  0x22,  0x62,  0x99,  0x27,  0xC2,  0x44,  0x27,  0xCF, 	/* 0D7F0 */
+	0xC4,  0x27,  0xC6,  0x00,  0x7F,  0xE6,  0x82,  0xAF,  0xEA,  0x82,  0x28,  0x22,  0xFE,  0x9A,  0x2E,  0xE2, 	/* 0D800 */
+	0xAA,  0xFE,  0xE2,  0xAA,  0x2E,  0xE7,  0x82,  0x68,  0x2A,  0x82,  0xA8,  0x22,  0x82,  0x28,  0x22,  0x86, 	/* 0D810 */
+	0x9B,  0x24,  0x83,  0xFE,  0x24,  0x8F,  0x20,  0x23,  0x06,  0x52,  0x6D,  0xC7,  0x50,  0xA5,  0x0A,  0x50, 	/* 0D820 */
+	0x25,  0x22,  0x4E,  0x9C,  0x21,  0x02,  0x28,  0x24,  0x4F,  0xFA,  0x21,  0x06,  0xFC,  0x79,  0x46,  0xFC, 	/* 0D830 */
+	0xA1,  0x0A,  0x28,  0x24,  0x43,  0x82,  0xA1,  0x20,  0x23,  0xF2,  0x2C,  0xAE,  0xAA,  0x3D,  0xA6,  0x4A, 	/* 0D840 */
+	0x7E,  0xA6,  0x4A,  0xA4,  0xAA,  0x72,  0x38,  0x22,  0x06,  0xA2,  0x20,  0x02,  0xFE,  0xF8,  0x22,  0xFE, 	/* 0D850 */
+	0x29,  0x27,  0x92,  0x6F,  0xEA,  0x9A,  0xA9,  0x62,  0xFE,  0x28,  0x22,  0xFE,  0xA3,  0x22,  0x82,  0x28, 	/* 0D860 */
+	0xFF,  0xE2,  0xAA,  0x2A,  0xA6,  0xFE,  0x7A,  0xAA,  0xAA,  0xBF,  0xF2,  0x28,  0x24,  0x42,  0x84,  0xA5, 	/* 0D870 */
+	0x24,  0x02,  0x8E,  0xFF,  0xA2,  0x4A,  0x24,  0xA7,  0xFA,  0x64,  0xAA,  0x4A,  0xAA,  0xA2,  0x9A,  0x30, 	/* 0D880 */
+	0xE2,  0x00,  0xA6,  0x21,  0x02,  0x54,  0xF9,  0x22,  0x7C,  0x22,  0x87,  0xFE,  0x64,  0x4A,  0x92,  0xB7, 	/* 0D890 */
+	0xD2,  0x24,  0x24,  0x42,  0x98,  0xA8,  0x20,  0x82,  0x7E,  0xFC,  0x02,  0x54,  0x25,  0x47,  0x5F,  0x66, 	/* 0D8A0 */
+	0x4A,  0x74,  0xAA,  0xC2,  0xA4,  0x32,  0x42,  0x2C,  0xAA,  0x24,  0x42,  0x28,  0xFF,  0xE2,  0x28,  0x22, 	/* 0D8B0 */
+	0x87,  0x2A,  0x6A,  0xAA,  0x6C,  0xA6,  0xC2,  0x28,  0x22,  0x82,  0xFE,  0xB0,  0x20,  0x03,  0xFE,  0xFA, 	/* 0D8C0 */
+	0xA2,  0xAA,  0x2E,  0xC7,  0xAC,  0x6E,  0xAA,  0xAA,  0xAA,  0xA3,  0xEC,  0x22,  0x82,  0x28,  0xB4,  0x25, 	/* 0D8D0 */
+	0xC2,  0x94,  0x29,  0x4F,  0xD5,  0x29,  0x32,  0xA0,  0x7D,  0xE6,  0x92,  0xAF,  0x4A,  0x88,  0x29,  0x42, 	/* 0D8E0 */
+	0xA2,  0xB6,  0x2A,  0xA2,  0x92,  0xFA,  0xA2,  0xFE,  0x22,  0x87,  0x4A,  0x6A,  0x6A,  0x3C,  0xA4,  0x42, 	/* 0D8F0 */
+	0xA8,  0x23,  0x82,  0xC6,  0xB9,  0x22,  0x42,  0x7E,  0xFA,  0x42,  0x3C,  0x22,  0x47,  0x3C,  0x6A,  0x4A, 	/* 0D900 */
+	0xFE,  0xAA,  0x82,  0xCE,  0x28,  0x02,  0x7E,  0xBD,  0x22,  0x02,  0x3C,  0x24,  0x4F,  0x78,  0x21,  0x06, 	/* 0D910 */
+	0xFE,  0x73,  0x26,  0xCC,  0xA1,  0xAA,  0xE9,  0x20,  0x82,  0x30,  0xBF,  0x21,  0x02,  0xFE,  0x21,  0x0F, 	/* 0D920 */
+	0xFE,  0x22,  0x87,  0xFE,  0x74,  0x46,  0xFE,  0xB4,  0x5A,  0x7C,  0x24,  0x42,  0x7C,  0x8A,  0x20,  0x02, 	/* 0D930 */
+	0x7C,  0x24,  0x4F,  0x7C,  0x24,  0x47,  0xFF,  0x74,  0x0A,  0xFE,  0xB2,  0xA2,  0xD2,  0x22,  0x22,  0xCC, 	/* 0D940 */
+	0x93,  0x20,  0x02,  0xFE,  0x28,  0xEF,  0xF2,  0x29,  0x26,  0xFE,  0x7D,  0x66,  0xFE,  0xA9,  0x2A,  0x96, 	/* 0D950 */
+	0x2F,  0xD3,  0x05,  0x94,  0x24,  0x02,  0xFE,  0x24,  0xAF,  0xEA,  0x25,  0x26,  0xEC,  0x75,  0x06,  0x10, 	/* 0D960 */
+	0xAF,  0xEA,  0x18,  0x22,  0x42,  0xC2,  0x95,  0x24,  0x02,  0xFE,  0x24,  0x0F,  0x7C,  0x29,  0x06,  0x7E, 	/* 0D970 */
+	0x70,  0x06,  0xFC,  0xA4,  0x4A,  0x7C,  0x24,  0x42,  0x4C,  0x99,  0x20,  0x42,  0xF4,  0x25,  0x4F,  0x2F, 	/* 0D980 */
+	0x3F,  0x46,  0x26,  0x76,  0xE6,  0x6D,  0xAB,  0x5B,  0x24,  0x22,  0x42,  0x64,  0x9A,  0x11,  0x0F,  0xFE, 	/* 0D990 */
+	0x11,  0x03,  0xB8,  0xD5,  0x61,  0x10,  0xFF,  0xE0,  0x44,  0x27,  0x82,  0x40,  0x5C,  0x08,  0x3E,  0x9C, 	/* 0D9A0 */
+	0x24,  0x02,  0x4E,  0xFF,  0xA2,  0x4A,  0x24,  0xE7,  0x4A,  0x6E,  0xAA,  0xAE,  0xAA,  0xA2,  0xEA,  0x21, 	/* 0D9B0 */
+	0x22,  0x26,  0x9D,  0x21,  0x02,  0xFE,  0x21,  0x0F,  0xFE,  0x2D,  0x66,  0xBA,  0x79,  0x26,  0xFE,  0xA3, 	/* 0D9C0 */
+	0x8A,  0x54,  0x29,  0x22,  0x10,  0x9E,  0x20,  0x02,  0xFE,  0x2A,  0xAF,  0xFE,  0x21,  0x07,  0x10,  0x6F, 	/* 0D9D0 */
+	0xE6,  0x20,  0xA3,  0xCA,  0x24,  0x24,  0x42,  0x98,  0xA0,  0x21,  0x02,  0xFE,  0x21,  0x0F,  0xFE,  0x2A, 	/* 0D9E0 */
+	0xA2,  0x92,  0x7F,  0xE6,  0x92,  0xAF,  0xEA,  0x92,  0x29,  0x22,  0x96,  0xA1,  0x21,  0x02,  0x10,  0x22, 	/* 0D9F0 */
+	0x8F,  0x7C,  0x28,  0x26,  0xEB,  0x7A,  0xA6,  0xF4,  0xAB,  0x4A,  0xEA,  0x2A,  0xA2,  0xAA,  0xA2,  0x24, 	/* 0DA00 */
+	0x42,  0x28,  0x2F,  0xEF,  0x28,  0x2F,  0xE2,  0xAA,  0x7A,  0xA6,  0xCE,  0xA8,  0x2A,  0xFE,  0x28,  0x22, 	/* 0DA10 */
+	0xFE,  0xAA,  0x25,  0x42,  0x54,  0x2F,  0xEF,  0x54,  0x25,  0xC6,  0x40,  0x77,  0xE6,  0x10,  0xAF,  0xEA, 	/* 0DA20 */
+	0x38,  0x25,  0x42,  0x92,  0xAB,  0x27,  0xC2,  0x44,  0xFF,  0xC2,  0x00,  0x2F,  0xE7,  0x44,  0x6F,  0xCA, 	/* 0DA30 */
+	0x44,  0xA7,  0xC2,  0x46,  0x2F,  0xC2,  0x04,  0xAD,  0x0A,  0x02,  0xA8,  0xFF,  0xE1,  0x10,  0x7F,  0xC0, 	/* 0DA40 */
+	0x40,  0x3F,  0x80,  0x40,  0xFF,  0xE1,  0x50,  0x24,  0x84,  0x44,  0xAE,  0x21,  0x02,  0xFC,  0x21,  0x4F, 	/* 0DA50 */
+	0x18,  0x2F,  0xE6,  0x30,  0x74,  0x86,  0xFC,  0xB4,  0x4A,  0x7C,  0x24,  0x42,  0x7C,  0xAF,  0x20,  0xC2, 	/* 0DA60 */
+	0x78,  0x24,  0x8F,  0x7E,  0x24,  0x87,  0x7E,  0x6E,  0x26,  0x7E,  0xAA,  0x2A,  0xBE,  0x32,  0x22,  0x3E, 	/* 0DA70 */
+	0xB3,  0x22,  0x42,  0xFE,  0x22,  0x4F,  0xBC,  0x22,  0x46,  0x3C,  0x71,  0x06,  0xFE,  0xA3,  0x8A,  0x54, 	/* 0DA80 */
+	0x29,  0x22,  0x10,  0xB4,  0x21,  0x02,  0xFE,  0xF4,  0x42,  0x28,  0x2F,  0xE7,  0x92,  0x69,  0x2A,  0x7C, 	/* 0DA90 */
+	0xA5,  0x42,  0x54,  0x25,  0x82,  0x10,  0xB5,  0x20,  0x02,  0xFE,  0x22,  0x0F,  0x40,  0x2E,  0xE6,  0x12, 	/* 0DAA0 */
+	0x7D,  0xA7,  0x54,  0xB5,  0x4B,  0xDA,  0x23,  0x02,  0xFE,  0xB7,  0x29,  0x02,  0x92,  0xFF,  0xC2,  0x90, 	/* 0DAB0 */
+	0x2B,  0x27,  0xCE,  0x60,  0x0B,  0x7C,  0xA4,  0x42,  0x7C,  0x24,  0x42,  0x7C,  0xB8,  0x22,  0x83,  0xC8, 	/* 0DAC0 */
+	0x24,  0x8F,  0x4A,  0x3F,  0xA6,  0x6C,  0x6D,  0x87,  0x48,  0xA4,  0xCA,  0x54,  0x25,  0x22,  0x61,  0xB9, 	/* 0DAD0 */
+	0x20,  0x02,  0x7C,  0xFA,  0x42,  0x26,  0x23,  0xA7,  0x2A,  0x65,  0x2A,  0xAC,  0xAF,  0xE2,  0xAA,  0x2A, 	/* 0DAE0 */
+	0xA3,  0xFF,  0xBC,  0x21,  0x02,  0x54,  0x2F,  0xEF,  0x38,  0x25,  0x46,  0x92,  0x72,  0x06,  0xFE,  0xA2, 	/* 0DAF0 */
+	0x8A,  0x48,  0x23,  0x82,  0xC4,  0xBD,  0x08,  0x09,  0xF2,  0x51,  0x41,  0xF0,  0x31,  0xCD,  0xF2,  0x04, 	/* 0DB00 */
+	0x0F,  0xFE,  0x0E,  0x03,  0x58,  0xC4,  0x60,  0x40,  0xBE,  0x21,  0x02,  0x7C,  0x24,  0x4F,  0xFC,  0x24, 	/* 0DB10 */
+	0x46,  0x7C,  0x79,  0x2A,  0x54,  0xA3,  0x82,  0x54,  0x29,  0x22,  0x30,  0x81,  0x21,  0x02,  0xFE,  0xF8, 	/* 0DB20 */
+	0x22,  0xFC,  0x21,  0x07,  0x24,  0x6F,  0xAA,  0x12,  0xA7,  0xC2,  0x10,  0x21,  0x02,  0xFE,  0x82,  0x20, 	/* 0DB30 */
+	0x02,  0xEE,  0x2A,  0xAF,  0xEA,  0x2A,  0xA6,  0xBF,  0x7E,  0x46,  0xC4,  0xAA,  0xCA,  0xED,  0x29,  0x52, 	/* 0DB40 */
+	0x23,  0x8A,  0x28,  0x82,  0x88,  0xFF,  0xE2,  0x6A,  0x26,  0xA6,  0xBE,  0x7A,  0xA7,  0xEA,  0xAB,  0xEA, 	/* 0DB50 */
+	0x88,  0x28,  0x82,  0x88,  0x8E,  0x2F,  0xE2,  0x10,  0x27,  0xEF,  0x42,  0x27,  0xE2,  0x42,  0x77,  0xE6, 	/* 0DB60 */
+	0x3C,  0xA6,  0x4A,  0x98,  0x21,  0x42,  0xE3,  0x91,  0x21,  0x42,  0xFE,  0xF5,  0x42,  0x7C,  0x25,  0x47, 	/* 0DB70 */
+	0x7C,  0x6D,  0x4A,  0x04,  0xAF,  0xE2,  0x44,  0x22,  0x42,  0x0C,  0x94,  0x24,  0x02,  0x4E,  0x2F,  0xAF, 	/* 0DB80 */
+	0x9A,  0x2F,  0xC6,  0x9A,  0x7F,  0x96,  0xC9,  0xAA,  0x9A,  0xDE,  0x39,  0x82,  0x08,  0x95,  0x21,  0x02, 	/* 0DB90 */
+	0xFE,  0x28,  0x2F,  0xAA,  0x25,  0x46,  0x92,  0x62,  0x87,  0x44,  0xAF,  0xEA,  0x44,  0x24,  0x42,  0x7C, 	/* 0DBA0 */
+	0x9B,  0x22,  0x02,  0xFC,  0x22,  0x0F,  0xFC,  0x25,  0x07,  0xFE,  0x69,  0x87,  0x64,  0xAF,  0xEA,  0x70, 	/* 0DBB0 */
+	0x3A,  0xC2,  0x20,  0x9C,  0x21,  0x02,  0xFE,  0xF4,  0x42,  0x28,  0x3F,  0xE7,  0x22,  0x6F,  0xCA,  0x20, 	/* 0DBC0 */
+	0xA3,  0xC2,  0x44,  0x24,  0x42,  0x98,  0xA0,  0x20,  0x02,  0xFE,  0x28,  0x2F,  0x7C,  0x24,  0x43,  0x7C, 	/* 0DBD0 */
+	0x6C,  0x46,  0x7C,  0xA1,  0x0A,  0xFE,  0x24,  0x82,  0x84,  0xA7,  0x20,  0x02,  0xFE,  0xFA,  0x82,  0xEE, 	/* 0DBE0 */
+	0x2A,  0x86,  0xEE,  0x7A,  0x8A,  0xEE,  0xAA,  0x82,  0xC8,  0x28,  0x82,  0xFE,  0xAE,  0x11,  0x05,  0x54, 	/* 0DBF0 */
+	0x2A,  0x84,  0x44,  0xFF,  0xE8,  0x42,  0x7F,  0xC0,  0xE0,  0x15,  0x02,  0x48,  0xC4,  0x60,  0x40,  0xB1, 	/* 0DC00 */
+	0x21,  0x02,  0xFE,  0x20,  0x0F,  0x7C,  0x24,  0x46,  0xFE,  0x74,  0x46,  0x7C,  0xA3,  0x2A,  0xEA,  0x23, 	/* 0DC10 */
+	0x42,  0x62,  0xB2,  0x20,  0x02,  0x7C,  0xF5,  0x42,  0x54,  0x26,  0xC7,  0x7C,  0x68,  0x0A,  0xFE,  0xAA, 	/* 0DC20 */
+	0xA2,  0xAA,  0x2A,  0xA3,  0xFF,  0xB4,  0x22,  0xF2,  0xC5,  0x29,  0x5F,  0x95,  0x2B,  0x56,  0xDB,  0x70, 	/* 0DC30 */
+	0x06,  0xFE,  0xA5,  0x2A,  0x7E,  0x25,  0x22,  0x7E,  0xBB,  0x27,  0xC2,  0x44,  0xF7,  0xC2,  0x44,  0x27, 	/* 0DC40 */
+	0xC7,  0x00,  0x6E,  0xEA,  0x66,  0xBB,  0xA2,  0x66,  0x3B,  0xA2,  0x66,  0xBE,  0x27,  0xC2,  0x44,  0xF5, 	/* 0DC50 */
+	0xC2,  0x54,  0x2F,  0xE7,  0x82,  0x6F,  0xCA,  0x44,  0xA7,  0xC2,  0x44,  0x24,  0x42,  0x4C,  0xBF,  0x21, 	/* 0DC60 */
+	0x02,  0x92,  0xFF,  0xE2,  0x00,  0x2F,  0xF7,  0x00,  0x6F,  0xEA,  0x42,  0xA7,  0xE2,  0x44,  0x22,  0x82, 	/* 0DC70 */
+	0xFE,  0x81,  0x21,  0x02,  0xFE,  0xF0,  0x02,  0x7C,  0x24,  0x47,  0x7C,  0x60,  0x0A,  0xFE,  0xAB,  0xA2, 	/* 0DC80 */
+	0xAA,  0x2B,  0xA2,  0x86,  0x83,  0x23,  0x87,  0xAA,  0x4A,  0x64,  0xDC,  0xFA,  0x44,  0x98,  0x5A,  0x4F, 	/* 0DC90 */
+	0xFE,  0x0E,  0x03,  0x58,  0xC4,  0x60,  0x40,  0x87,  0x24,  0xC2,  0x70,  0x24,  0x2F,  0x3E,  0x2A,  0x46, 	/* 0DCA0 */
+	0xBC,  0x7A,  0x46,  0xBC,  0xAA,  0x4A,  0xFE,  0x22,  0x42,  0xC2,  0x8A,  0x29,  0xEF,  0xD2,  0x11,  0xE5, 	/* 0DCB0 */
+	0x52,  0x7D,  0xE2,  0x22,  0x44,  0x6F,  0xFE,  0x0E,  0x03,  0x58,  0xC4,  0x60,  0x40,  0x8B,  0x24,  0x82, 	/* 0DCC0 */
+	0xFC,  0x24,  0x8F,  0xFC,  0x24,  0x86,  0xFE,  0x75,  0x46,  0x7C,  0xA5,  0x4A,  0xFE,  0x24,  0x42,  0x4C, 	/* 0DCD0 */
+	0x8C,  0x20,  0x42,  0x88,  0xF5,  0xE2,  0x12,  0x61,  0xE7,  0xD0,  0x65,  0xEA,  0x52,  0xA5,  0x22,  0x5E, 	/* 0DCE0 */
+	0x2A,  0x03,  0x1F,  0x8D,  0x21,  0x02,  0x28,  0x2C,  0x4F,  0x7E,  0x24,  0x42,  0x7C,  0x74,  0x46,  0xFC, 	/* 0DCF0 */
+	0xA4,  0x0A,  0xBE,  0x32,  0x22,  0x3E,  0x8E,  0x24,  0x42,  0x28,  0x2F,  0xEF,  0x10,  0x27,  0xC7,  0x10, 	/* 0DD00 */
+	0x6F,  0xF6,  0x20,  0xA7,  0xEA,  0x88,  0x30,  0x82,  0x7E,  0x90,  0x21,  0x02,  0x20,  0x2F,  0xCF,  0x94, 	/* 0DD10 */
+	0x2F,  0xC6,  0x94,  0x7F,  0xC6,  0xB4,  0xA3,  0xAA,  0x5E,  0x29,  0x03,  0x0E,  0x93,  0x27,  0xC2,  0x10, 	/* 0DD20 */
+	0xFF,  0xE2,  0x00,  0x27,  0xC7,  0x44,  0x6F,  0xCA,  0x44,  0xA7,  0xC2,  0x44,  0x27,  0xC2,  0xC2,  0x98, 	/* 0DD30 */
+	0x22,  0x42,  0xFE,  0x21,  0x0F,  0x7C,  0x21,  0x06,  0xFE,  0x79,  0x26,  0x54,  0xA3,  0x8A,  0xD4,  0x21, 	/* 0DD40 */
+	0x22,  0x30,  0x99,  0x21,  0x02,  0xFE,  0x21,  0x0F,  0xFC,  0x24,  0x46,  0x7C,  0x74,  0x46,  0xFC,  0xA4, 	/* 0DD50 */
+	0x4A,  0xFF,  0x22,  0x82,  0xC4,  0x9D,  0x21,  0x02,  0x7C,  0xFC,  0x42,  0x7C,  0x24,  0x47,  0x7E,  0x6C, 	/* 0DD60 */
+	0x0A,  0x7E,  0xA2,  0x22,  0xAA,  0x2F,  0xA2,  0x0C,  0x9E,  0x22,  0x02,  0xFC,  0xF4,  0x82,  0xFE,  0x20, 	/* 0DD70 */
+	0x07,  0xFC,  0x6A,  0x4A,  0xFC,  0xAA,  0x42,  0xFC,  0x22,  0x22,  0x1E,  0xA7,  0x10,  0x6F,  0xF8,  0x52, 	/* 0DD80 */
+	0x07,  0xBE,  0x52,  0x4F,  0xA4,  0x14,  0x40,  0x40,  0xFF,  0xE3,  0x70,  0xC4,  0xE0,  0x40,  0xA8,  0x24, 	/* 0DD90 */
+	0x03,  0xFE,  0x20,  0xAF,  0xEA,  0x2A,  0xC6,  0xEA,  0x70,  0xA6,  0xEA,  0xA4,  0xAB,  0xEC,  0x24,  0x82, 	/* 0DDA0 */
+	0xC8,  0xAB,  0x21,  0x02,  0xFE,  0xF9,  0x02,  0x7C,  0x35,  0x46,  0xFC,  0x65,  0x4A,  0xFE,  0xA8,  0x82, 	/* 0DDB0 */
+	0x48,  0x20,  0x82,  0x18,  0xAD,  0x20,  0xC2,  0x0A,  0x2F,  0xEF,  0x88,  0x2A,  0xA6,  0xBA,  0x7A,  0xA6, 	/* 0DDC0 */
+	0xFA,  0xAA,  0x4A,  0xF4,  0x2A,  0xB3,  0x31,  0xB2,  0x24,  0x22,  0x72,  0xFA,  0xA2,  0xF6,  0x2D,  0x26, 	/* 0DDD0 */
+	0xFA,  0x7D,  0x6A,  0xF3,  0xA9,  0xE2,  0x92,  0x29,  0x23,  0x32,  0xB9,  0x21,  0x02,  0x7C,  0xF4,  0x42, 	/* 0DDE0 */
+	0x7C,  0x24,  0x47,  0x7C,  0x69,  0x0A,  0xD6,  0xA1,  0x03,  0xFE,  0x21,  0x02,  0x10,  0xBB,  0x21,  0xE2, 	/* 0DDF0 */
+	0x52,  0x25,  0xEF,  0xF2,  0x25,  0xE6,  0xF2,  0x75,  0x26,  0x5E,  0xA4,  0xCA,  0xAC,  0x31,  0x52,  0x63, 	/* 0DE00 */
+	0xBD,  0x22,  0x82,  0xFE,  0x22,  0x8F,  0xFE,  0x2A,  0xA2,  0xFE,  0x7A,  0xA6,  0xFE,  0xA4,  0x4A,  0x7C, 	/* 0DE10 */
+	0x24,  0x42,  0x7C,  0xBF,  0x22,  0x42,  0xFE,  0xF2,  0x42,  0xFE,  0x29,  0x26,  0xFE,  0x71,  0x0A,  0xFC, 	/* 0DE20 */
+	0xA1,  0x02,  0xFC,  0x21,  0x03,  0xFE,  0x82,  0x44,  0x8A,  0x54,  0x5E,  0xAF,  0xBE,  0x2E,  0x87,  0xBC, 	/* 0DE30 */
+	0xAE,  0xA0,  0x40,  0xFF,  0xE0,  0xE0,  0x35,  0x8C,  0x46,  0x85,  0x25,  0x42,  0x54,  0x29,  0x4F,  0x5A, 	/* 0DE40 */
+	0x26,  0xA6,  0xA8,  0x68,  0x87,  0xAE,  0xAA,  0x8A,  0xA8,  0x2D,  0x82,  0x87,  0x8A,  0x2A,  0x82,  0x48, 	/* 0DE50 */
+	0xF5,  0xE2,  0xAC,  0x75,  0xAA,  0x68,  0x28,  0x80,  0x40,  0xFF,  0xE0,  0xA0,  0x31,  0x8C,  0x06,  0x8B, 	/* 0DE60 */
+	0x23,  0xE2,  0x94,  0x24,  0xCF,  0x3E,  0x22,  0xA7,  0xBE,  0x6A,  0xA6,  0xBE,  0xAA,  0xAA,  0xA6,  0x34, 	/* 0DE70 */
+	0x02,  0x3F,  0x8C,  0x27,  0xC2,  0x54,  0x2F,  0xEF,  0xA8,  0x2F,  0x86,  0x7C,  0x74,  0x46,  0x7C,  0xA4, 	/* 0DE80 */
+	0x4A,  0x7C,  0x24,  0x42,  0x82,  0x92,  0x21,  0x02,  0xFE,  0x2A,  0x2F,  0x90,  0x22,  0x42,  0xAA,  0x73, 	/* 0DE90 */
+	0x26,  0xCE,  0xA1,  0x0A,  0x92,  0x29,  0x22,  0xFE,  0x93,  0x21,  0x02,  0xFE,  0x29,  0x2F,  0xFF,  0x29, 	/* 0DEA0 */
+	0x26,  0xFE,  0x79,  0x26,  0xFF,  0xA2,  0x4A,  0x44,  0x23,  0x82,  0xE4,  0x94,  0x25,  0x42,  0xA8,  0xF5, 	/* 0DEB0 */
+	0x42,  0x7C,  0x35,  0x46,  0xFC,  0x65,  0x4A,  0xFE,  0xA3,  0x82,  0x54,  0x29,  0x22,  0x10,  0x97,  0x27, 	/* 0DEC0 */
+	0xC2,  0x10,  0x2F,  0xEF,  0x92,  0x2D,  0xA6,  0xB6,  0x70,  0x06,  0xFF,  0xA2,  0x0A,  0x3C,  0x20,  0x42, 	/* 0DED0 */
+	0x18,  0x99,  0x2F,  0xE2,  0x28,  0xFF,  0xE2,  0xAA,  0x2F,  0xE7,  0x00,  0x6F,  0xCA,  0x00,  0xAF,  0xE2, 	/* 0DEE0 */
+	0x54,  0x29,  0x22,  0x30,  0x9B,  0x20,  0x02,  0xFE,  0x2A,  0xAF,  0x76,  0x2A,  0xA6,  0x76,  0x72,  0xC6, 	/* 0DEF0 */
+	0x4A,  0xAB,  0x1A,  0xC4,  0x21,  0x82,  0xE0,  0x9E,  0x20,  0x02,  0xFE,  0xFB,  0xC2,  0xA4,  0x2B,  0xC6, 	/* 0DF00 */
+	0x80,  0x7E,  0xEA,  0xAA,  0xAA,  0xA2,  0xEE,  0x28,  0x02,  0xFE,  0x9F,  0x21,  0x02,  0xFC,  0x22,  0x8F, 	/* 0DF10 */
+	0xFE,  0x24,  0x43,  0x7C,  0x6C,  0x46,  0x7C,  0xA1,  0x0B,  0xFE,  0x21,  0x02,  0x10,  0xA1,  0x22,  0x82, 	/* 0DF20 */
+	0xFE,  0xFA,  0x82,  0x7C,  0x74,  0x46,  0xFC,  0x67,  0xCA,  0x10,  0xAF,  0xE2,  0x30,  0x24,  0x83,  0x86, 	/* 0DF30 */
+	0xA2,  0x22,  0x02,  0x7C,  0x24,  0x4F,  0xFC,  0x24,  0x46,  0x7E,  0x74,  0x06,  0x7E,  0xAA,  0xAA,  0x96, 	/* 0DF40 */
+	0x30,  0x22,  0x0C,  0xA3,  0x22,  0x42,  0xFE,  0x21,  0x0F,  0x7C,  0x21,  0x06,  0xFE,  0x71,  0x06,  0x34, 	/* 0DF50 */
+	0xAD,  0x8A,  0x34,  0x2D,  0x22,  0x30,  0xA9,  0x24,  0x02,  0x7C,  0x29,  0x0F,  0x7E,  0x22,  0x83,  0x7E, 	/* 0DF60 */
+	0x6D,  0x07,  0x7C,  0xA5,  0x0A,  0x7C,  0x25,  0x02,  0x7E,  0xAA,  0x22,  0x42,  0x7E,  0xF2,  0x42,  0xFF, 	/* 0DF70 */
+	0x21,  0x06,  0x7E,  0x75,  0x26,  0xFE,  0xA5,  0x2A,  0x7E,  0x22,  0x42,  0xC2,  0xAB,  0x2F,  0xE2,  0xAA, 	/* 0DF80 */
+	0x2F,  0xAF,  0x94,  0x2F,  0x46,  0xAA,  0x7F,  0x26,  0x10,  0xA7,  0xCA,  0x10,  0x21,  0x02,  0xFE,  0xAE, 	/* 0DF90 */
+	0x20,  0x02,  0xFE,  0xF2,  0x82,  0xFE,  0x2A,  0xA6,  0xFE,  0x71,  0x0A,  0x52,  0xA5,  0x42,  0x98,  0x22, 	/* 0DFA0 */
+	0x42,  0xC2,  0xB5,  0x22,  0x42,  0x28,  0x27,  0xEF,  0xC8,  0x27,  0xC3,  0x48,  0x6F,  0xC6,  0x48,  0xA7, 	/* 0DFB0 */
+	0xEA,  0x00,  0x2D,  0x43,  0x2A,  0xB6,  0x27,  0xC2,  0x44,  0x27,  0xCF,  0x44,  0x2F,  0xF7,  0xA0,  0x6F, 	/* 0DFC0 */
+	0xE6,  0xAA,  0xAE,  0xAA,  0xA4,  0x3E,  0xA2,  0x31,  0xB8,  0x2A,  0xA2,  0x6C,  0x2F,  0xEF,  0x44,  0x22, 	/* 0DFD0 */
+	0x86,  0xFE,  0x71,  0x06,  0x7C,  0xA1,  0x0A,  0xFE,  0x24,  0x42,  0x82,  0xB9,  0x22,  0x22,  0xF2,  0x22, 	/* 0DFE0 */
+	0x2F,  0xFF,  0x20,  0x26,  0xFA,  0x79,  0x66,  0xF2,  0xA9,  0x2A,  0x7A,  0x38,  0x22,  0x06,  0xBA,  0x24, 	/* 0DFF0 */
+	0x82,  0xFE,  0x24,  0x8F,  0xFE,  0x25,  0x46,  0xFE,  0x75,  0x46,  0xFE,  0xA1,  0x0A,  0xFE,  0x21,  0x02, 	/* 0E000 */
+	0x10,  0xBD,  0x28,  0x83,  0xFC,  0x25,  0x0F,  0xFC,  0x2D,  0x42,  0x8C,  0x6F,  0xC7,  0xFE,  0xA4,  0x8A, 	/* 0E010 */
+	0x28,  0x20,  0x82,  0x18,  0x84,  0x20,  0x42,  0xF4,  0x24,  0xFF,  0xEA,  0x2B,  0x26,  0xEA,  0x7A,  0xC6, 	/* 0E020 */
+	0xE4,  0xAA,  0x4A,  0xEA,  0x33,  0x22,  0x21,  0x87,  0x20,  0xC2,  0x70,  0x22,  0x0F,  0xFC,  0x22,  0x26, 	/* 0E030 */
+	0x1E,  0x70,  0x06,  0xEE,  0xA4,  0x4A,  0xEE,  0x24,  0x42,  0x33,  0x88,  0x27,  0xC2,  0x10,  0x2F,  0xEF, 	/* 0E040 */
+	0x44,  0x2E,  0xE7,  0x44,  0x7F,  0xE6,  0x00,  0xAF,  0xEA,  0x28,  0x24,  0xA3,  0x86,  0x8B,  0x27,  0xC2, 	/* 0E050 */
+	0x10,  0x2F,  0xEF,  0x28,  0x24,  0x46,  0xBA,  0x72,  0x86,  0xFE,  0xAB,  0xAA,  0xAA,  0x2B,  0xA2,  0x86, 	/* 0E060 */
+	0x98,  0x27,  0xC2,  0x28,  0x2F,  0xEF,  0x34,  0x2D,  0x06,  0xFE,  0x7A,  0xA6,  0xCE,  0xAB,  0xAA,  0xAA, 	/* 0E070 */
+	0x2B,  0xA2,  0x86,  0x99,  0x27,  0x02,  0x16,  0x2E,  0x8F,  0x2A,  0x24,  0x46,  0x82,  0x77,  0xC6,  0xC4, 	/* 0E080 */
+	0xA7,  0xCA,  0x44,  0x22,  0x82,  0xFE,  0x9F,  0x22,  0x42,  0x48,  0x2F,  0xCF,  0x5A,  0x2F,  0xE6,  0x14, 	/* 0E090 */
+	0x7F,  0xE6,  0x94,  0xAD,  0x8A,  0xAA,  0x31,  0x62,  0x62,  0xA1,  0x23,  0x82,  0xC8,  0x2F,  0xEF,  0x92, 	/* 0E0A0 */
+	0x2F,  0xE2,  0x30,  0x7D,  0xA6,  0x2C,  0xAD,  0x8A,  0x2C,  0x2C,  0xA2,  0x30,  0xA2,  0x20,  0x82,  0xFE, 	/* 0E0B0 */
+	0x2A,  0x8F,  0xAE,  0x2D,  0x46,  0xBE,  0x7A,  0x06,  0xBE,  0xAB,  0x2A,  0xDE,  0x29,  0x22,  0x96,  0xA6, 	/* 0E0C0 */
+	0x21,  0x02,  0xFC,  0x24,  0x8F,  0xFE,  0x20,  0x06,  0x7C,  0x75,  0x46,  0x7C,  0xA5,  0x4A,  0xFE,  0x21, 	/* 0E0D0 */
+	0x02,  0xFE,  0xB2,  0x21,  0x02,  0xFE,  0x21,  0x0F,  0x7C,  0x20,  0x07,  0x7C,  0x6C,  0x46,  0x7C,  0xA2, 	/* 0E0E0 */
+	0x8A,  0xFE,  0x24,  0x42,  0x7C,  0xB8,  0x27,  0xC2,  0x44,  0x27,  0xCF,  0x44,  0x27,  0xC6,  0x00,  0x7E, 	/* 0E0F0 */
+	0xE6,  0xAA,  0xAE,  0xEA,  0xAA,  0x2A,  0xA2,  0xEE,  0xBF,  0x20,  0x02,  0xFE,  0x25,  0x4F,  0x7C,  0x25, 	/* 0E100 */
+	0x47,  0x7C,  0x68,  0x06,  0xFE,  0xA5,  0x4A,  0x7C,  0x25,  0x42,  0xFE,  0x80,  0x22,  0x03,  0xFE,  0x28, 	/* 0E110 */
+	0x4F,  0xF4,  0x2D,  0x46,  0xFC,  0x70,  0x06,  0x78,  0xA4,  0x8A,  0x78,  0x24,  0x82,  0xFE,  0x84,  0x24, 	/* 0E120 */
+	0x02,  0xE8,  0x2A,  0x8F,  0xEE,  0x2A,  0xA6,  0xF2,  0x75,  0xA6,  0xF4,  0xA4,  0x4A,  0x64,  0x2A,  0xA3, 	/* 0E130 */
+	0x71,  0x8D,  0x21,  0x02,  0xFC,  0x24,  0x8F,  0xFE,  0x24,  0x46,  0x7C,  0x74,  0x46,  0x7C,  0xAA,  0x0A, 	/* 0E140 */
+	0xD4,  0x34,  0xA2,  0x38,  0x8E,  0x21,  0x02,  0x30,  0x24,  0x8F,  0xCC,  0x2B,  0x66,  0xCC,  0x6F,  0xC7, 	/* 0E150 */
+	0x10,  0xAF,  0xEA,  0x96,  0x2F,  0xA2,  0x86,  0x90,  0x23,  0xC2,  0x48,  0x2F,  0xEF,  0x94,  0x2E,  0x76, 	/* 0E160 */
+	0x9C,  0x78,  0x06,  0xFE,  0xA8,  0x0A,  0xBE,  0x32,  0x22,  0x3E,  0x97,  0x79,  0x04,  0xFC,  0x7A,  0x84, 	/* 0E170 */
+	0x7E,  0x79,  0x04,  0xFE,  0xB9,  0x00,  0x40,  0xFF,  0xE0,  0xE0,  0x35,  0x8C,  0x46,  0x9C,  0x21,  0x02, 	/* 0E180 */
+	0x28,  0xF4,  0x42,  0x82,  0x2F,  0xF7,  0xAA,  0x69,  0x2A,  0xFE,  0xA4,  0x42,  0x7C,  0x24,  0x42,  0x7C, 	/* 0E190 */
+	0xA0,  0x29,  0x0F,  0xDE,  0x2A,  0x47,  0xF4,  0xD4,  0x87,  0x54,  0x1A,  0x20,  0x40,  0xFF,  0xE0,  0xE0, 	/* 0E1A0 */
+	0x35,  0x8C,  0x46,  0xA2,  0x22,  0x02,  0x50,  0x28,  0x8F,  0x74,  0x20,  0x27,  0xDC,  0x75,  0x47,  0xDC, 	/* 0E1B0 */
+	0xA4,  0x8A,  0x48,  0x2B,  0x43,  0x12,  0xA3,  0x21,  0x02,  0xFE,  0x21,  0x0F,  0x54,  0x25,  0x46,  0xBA, 	/* 0E1C0 */
+	0x71,  0x06,  0xFE,  0xAA,  0xAA,  0xBA,  0x28,  0x22,  0xFE,  0xAA,  0x21,  0x02,  0x10,  0x23,  0x8F,  0xAA, 	/* 0E1D0 */
+	0x27,  0xC6,  0xAA,  0x73,  0x86,  0x10,  0xAF,  0xEA,  0x38,  0x25,  0x42,  0x92,  0xAC,  0x28,  0x83,  0xFC, 	/* 0E1E0 */
+	0x2A,  0x8F,  0xFC,  0x28,  0x47,  0x7C,  0x6D,  0x06,  0x34,  0xAD,  0x8A,  0x34,  0x2D,  0x22,  0x20,  0xAE, 	/* 0E1F0 */
+	0x21,  0x02,  0xFE,  0xF1,  0x02,  0x7E,  0x30,  0x26,  0xFC,  0x61,  0x0A,  0xFF,  0xAE,  0x22,  0xBF,  0x2E, 	/* 0E200 */
+	0xA2,  0x02,  0xB3,  0x21,  0x02,  0xFE,  0x2B,  0x2F,  0x54,  0x2B,  0x86,  0xFC,  0x74,  0x46,  0x7C,  0xA4, 	/* 0E210 */
+	0x4A,  0x7C,  0x22,  0x42,  0x42,  0xB8,  0x21,  0x02,  0xFE,  0x2A,  0x2F,  0x54,  0x2B,  0xA7,  0x00,  0x6F, 	/* 0E220 */
+	0xE6,  0xAA,  0xBF,  0xFA,  0x08,  0x20,  0x82,  0x18,  0xBB,  0x2E,  0x82,  0x88,  0x2E,  0xEF,  0xB0,  0x2E, 	/* 0E230 */
+	0x07,  0x8E,  0x6E,  0x06,  0x00,  0xAF,  0xEA,  0xAA,  0x2A,  0xA3,  0xFF,  0x81,  0x21,  0x02,  0xFE,  0x2B, 	/* 0E240 */
+	0x6F,  0x28,  0x2B,  0x46,  0xCE,  0x71,  0x26,  0x7C,  0xA5,  0x4A,  0x7C,  0x21,  0x42,  0xFA,  0x82,  0x20, 	/* 0E250 */
+	0x02,  0xFE,  0x26,  0x6F,  0xAA,  0x26,  0x66,  0x2A,  0x74,  0x86,  0xFC,  0xB9,  0x0A,  0xFC,  0x29,  0x02, 	/* 0E260 */
+	0xFC,  0x83,  0x20,  0x02,  0xFF,  0x28,  0x8F,  0xBE,  0x2A,  0xA6,  0xFF,  0x7A,  0x26,  0xBE,  0xAA,  0x2A, 	/* 0E270 */
+	0xBE,  0x2C,  0x12,  0xFF,  0x91,  0x27,  0xC2,  0x54,  0x27,  0xCF,  0x54,  0x27,  0xC7,  0x00,  0x6E,  0xE6, 	/* 0E280 */
+	0xAA,  0xAE,  0xEA,  0xAA,  0x2A,  0xA2,  0xEE,  0x93,  0x23,  0xC2,  0x48,  0x2F,  0xEF,  0x92,  0x2F,  0xE6, 	/* 0E290 */
+	0x92,  0x7F,  0xE6,  0xAA,  0xB2,  0x9A,  0xFE,  0x28,  0x22,  0xFE,  0x9A,  0x2E,  0xE2,  0xAA,  0x2E,  0xEF, 	/* 0E2A0 */
+	0xAA,  0x2F,  0xE6,  0xAA,  0x7B,  0xA6,  0x92,  0xAB,  0xAA,  0xAA,  0x2B,  0xA2,  0x86,  0x9B,  0x28,  0x82, 	/* 0E2B0 */
+	0xEE,  0x35,  0x4F,  0x44,  0x2E,  0xE6,  0xAA,  0x7E,  0xA6,  0xAA,  0xAE,  0xAA,  0x8E,  0x2E,  0x82,  0xA8, 	/* 0E2C0 */
+	0x9E,  0x24,  0x82,  0x8E,  0x31,  0x4E,  0xDC,  0x2B,  0xE7,  0xE8,  0x64,  0xA7,  0x7A,  0xAE,  0xCB,  0x5A, 	/* 0E2D0 */
+	0x26,  0x92,  0x58,  0x9F,  0x29,  0x23,  0x54,  0x2B,  0xAF,  0xEC,  0x2B,  0xA7,  0xEE,  0x6B,  0xA6,  0x10, 	/* 0E2E0 */
+	0xBF,  0xEA,  0x34,  0x25,  0x22,  0x10,  0xA8,  0x22,  0x02,  0x3C,  0x22,  0x0F,  0xFE,  0x29,  0x06,  0xBE, 	/* 0E2F0 */
+	0x79,  0x06,  0xBE,  0xAA,  0xAA,  0xBE,  0x32,  0xA2,  0x7F,  0xAA,  0x20,  0x02,  0xFE,  0x2A,  0x4F,  0xFE, 	/* 0E300 */
+	0x2A,  0xC6,  0xF6,  0x7A,  0x46,  0x90,  0xA9,  0x0B,  0x5E,  0x25,  0x02,  0xFE,  0xBA,  0x27,  0xC2,  0x10, 	/* 0E310 */
+	0x2F,  0xEF,  0x92,  0x2D,  0xA6,  0xB6,  0x79,  0x26,  0x00,  0xAD,  0x6A,  0xAA,  0x2A,  0xA2,  0xD6,  0xBB, 	/* 0E320 */
+	0x2E,  0xE2,  0xAA,  0x2E,  0xEF,  0xAA,  0x2E,  0xE6,  0x44,  0x7A,  0xA6,  0x20,  0xBF,  0xEA,  0x64,  0x23, 	/* 0E330 */
+	0x82,  0x64,  0x84,  0x2E,  0xE2,  0xAA,  0x2E,  0xEF,  0x92,  0x2F,  0xE6,  0x92,  0x7F,  0xE6,  0x96,  0xAF, 	/* 0E340 */
+	0xEA,  0xBA,  0x2D,  0x62,  0x92,  0x85,  0x22,  0x02,  0xDC,  0x2A,  0x4F,  0xFC,  0x2B,  0x47,  0xFE,  0x74, 	/* 0E350 */
+	0x86,  0xBC,  0xB1,  0x2A,  0xFC,  0x21,  0x02,  0x30,  0x8A,  0x22,  0x82,  0xFE,  0x22,  0x8F,  0xEE,  0x2A, 	/* 0E360 */
+	0xA6,  0xEE,  0x74,  0x06,  0x7E,  0xAC,  0x8A,  0x7E,  0x24,  0x82,  0x7E,  0x92,  0x45,  0x0A,  0xE8,  0x51, 	/* 0E370 */
+	0x2F,  0xFE,  0x6E,  0xCB,  0xBA,  0x2E,  0x80,  0x40,  0xFF,  0xE1,  0xF0,  0xE4,  0xE0,  0x40,  0x96,  0x2E, 	/* 0E380 */
+	0x82,  0xAE,  0x2F,  0x0F,  0xFE,  0x2A,  0xA6,  0xFE,  0x74,  0x46,  0x7C,  0xA4,  0x4A,  0x7C,  0x22,  0xA2, 	/* 0E390 */
+	0xCE,  0x9D,  0x24,  0x8F,  0xBE,  0x75,  0xCA,  0xAA,  0x7F,  0xC4,  0xA4,  0x7F,  0xC4,  0x88,  0x7F,  0xE5, 	/* 0E3A0 */
+	0x28,  0x48,  0x8F,  0x58,  0x9F,  0x4A,  0x05,  0xFE,  0x4A,  0xAF,  0xFE,  0x45,  0xAC,  0xFE,  0xDA,  0xAE, 	/* 0E3B0 */
+	0xFE,  0xCA,  0x44,  0xF4,  0x4A,  0x54,  0xFB,  0xA0,  0x10,  0x01,  0x00,  0x10,  0x01,  0xFE,  0x24,  0x42, 	/* 0E3C0 */
+	0x48,  0x44,  0x00,  0x60,  0x0A,  0x01,  0x10,  0x20,  0x8C,  0x06,  0xA1,  0x04,  0x04,  0x40,  0x24,  0x02, 	/* 0E3D0 */
+	0x7E,  0x0A,  0x21,  0x24,  0x02,  0x02,  0x30,  0x45,  0x04,  0x48,  0x88,  0x4B,  0x02,  0xA3,  0x1A,  0x06, 	/* 0E3E0 */
+	0x20,  0x42,  0x04,  0x3E,  0x7D,  0x25,  0x54,  0x59,  0x05,  0x10,  0x53,  0x05,  0x28,  0x94,  0x41,  0x82, 	/* 0E3F0 */
+	0xA7,  0x02,  0x0F,  0xA0,  0x82,  0x0C,  0xBE,  0xAA,  0xA9,  0x4C,  0x94,  0x8A,  0x88,  0xC9,  0x88,  0x14, 	/* 0E400 */
+	0xFA,  0x40,  0xC2,  0xB2,  0x2A,  0x02,  0xA0,  0x47,  0xE9,  0x22,  0x15,  0x42,  0x90,  0x45,  0x0F,  0xD0, 	/* 0E410 */
+	0x4A,  0x84,  0xA8,  0x4C,  0x47,  0x82,  0xB7,  0x65,  0x01,  0x90,  0x65,  0xE1,  0x2A,  0xFC,  0xC2,  0x08, 	/* 0E420 */
+	0x7C,  0x85,  0x48,  0xD5,  0x45,  0xD4,  0x52,  0x21,  0x41,  0xB8,  0x11,  0x02,  0x90,  0xF5,  0xE2,  0x2A, 	/* 0E430 */
+	0x3C,  0xC5,  0x08,  0x90,  0x8F,  0xC8,  0x11,  0x42,  0x94,  0x42,  0x28,  0x41,  0xB9,  0x21,  0x02,  0x10, 	/* 0E440 */
+	0xFD,  0xE3,  0x2A,  0x4A,  0xCF,  0xC8,  0x04,  0x87,  0x48,  0x55,  0x47,  0x54,  0x06,  0x40,  0xC2,  0xBA, 	/* 0E450 */
+	0x4A,  0x04,  0xA0,  0xFE,  0x04,  0xBE,  0x7D,  0x24,  0xD4,  0x79,  0x04,  0x90,  0xFD,  0x05,  0x28,  0x4C, 	/* 0E460 */
+	0x49,  0x82,  0xBD,  0x22,  0x02,  0x20,  0x52,  0x04,  0xBE,  0xFD,  0x22,  0x54,  0xF9,  0x02,  0x10,  0xB1, 	/* 0E470 */
+	0x86,  0xA8,  0x34,  0x4C,  0x82,  0xBE,  0x22,  0x0F,  0xA0,  0x22,  0x07,  0xBE,  0x05,  0x27,  0x54,  0x01, 	/* 0E480 */
+	0x0F,  0x90,  0x32,  0x8A,  0xA8,  0xA4,  0x46,  0x82,  0x83,  0x19,  0x0E,  0x10,  0x21,  0xEF,  0x9A,  0x22, 	/* 0E490 */
+	0xC6,  0x28,  0xBC,  0x8A,  0x88,  0xF9,  0x4A,  0x94,  0xAA,  0x2F,  0xC1,  0x87,  0x02,  0x07,  0xA0,  0x4B, 	/* 0E4A0 */
+	0xE7,  0xAA,  0x4A,  0xC7,  0xC8,  0x20,  0x87,  0xC8,  0xA5,  0x45,  0x54,  0x76,  0x21,  0xC1,  0x89,  0x29, 	/* 0E4B0 */
+	0x05,  0x10,  0xFD,  0x05,  0x3E,  0xFE,  0xA5,  0x4C,  0xFE,  0x85,  0x4C,  0xFC,  0xC5,  0x8A,  0xD5,  0x25, 	/* 0E4C0 */
+	0x21,  0x8C,  0x01,  0x0F,  0xD0,  0xE9,  0xEA,  0xAA,  0xEA,  0xC0,  0xC8,  0xF8,  0x80,  0x98,  0xE9,  0x4A, 	/* 0E4D0 */
+	0xA4,  0xEC,  0x21,  0x81,  0x8E,  0x51,  0x0F,  0x90,  0x51,  0xEF,  0x9A,  0xAA,  0xAF,  0xAC,  0x24,  0x8F, 	/* 0E4E0 */
+	0x88,  0x21,  0x8F,  0x94,  0x52,  0x48,  0xC2,  0x90,  0x01,  0x0F,  0xD0,  0x81,  0xEB,  0xAA,  0xAC,  0xCB, 	/* 0E4F0 */
+	0x88,  0xEE,  0x8A,  0xA8,  0xEF,  0x48,  0x14,  0xFE,  0x28,  0x41,  0x93,  0x41,  0x07,  0xD0,  0x51,  0x07, 	/* 0E500 */
+	0xDE,  0xAA,  0xA7,  0xCC,  0x50,  0x8F,  0xC8,  0x51,  0x87,  0xD4,  0x52,  0x47,  0xC2,  0x94,  0x21,  0x03, 	/* 0E510 */
+	0x90,  0x21,  0xE7,  0xEA,  0x54,  0xC7,  0xA8,  0x5E,  0x85,  0x48,  0x75,  0x45,  0x54,  0x9E,  0x23,  0x41, 	/* 0E520 */
+	0x99,  0x21,  0x03,  0x10,  0x49,  0xEB,  0x5A,  0x7A,  0xC4,  0x88,  0xFC,  0x86,  0xC8,  0xB5,  0x46,  0xD4, 	/* 0E530 */
+	0xB5,  0x22,  0x61,  0x9B,  0x21,  0x03,  0x10,  0x49,  0x0B,  0xDE,  0x02,  0xAF,  0xCC,  0xB4,  0x8F,  0xC8, 	/* 0E540 */
+	0x29,  0x42,  0x94,  0x56,  0x28,  0x41,  0x9F,  0x10,  0x87,  0x68,  0x52,  0x87,  0xEE,  0x4B,  0xA6,  0xAC, 	/* 0E550 */
+	0x6E,  0x86,  0xA8,  0x6A,  0xCF,  0xF4,  0x2A,  0x2C,  0x41,  0xA1,  0x29,  0x0F,  0xD0,  0x29,  0x0F,  0xDE, 	/* 0E560 */
+	0xB6,  0xAF,  0xCC,  0x48,  0x87,  0xC8,  0xD0,  0xC7,  0xD4,  0x52,  0x27,  0xC1,  0xA2,  0x04,  0x00,  0x40, 	/* 0E570 */
+	0x04,  0x00,  0x40,  0x24,  0x02,  0x7C,  0x24,  0x02,  0x40,  0x24,  0x02,  0x40,  0x24,  0x0F,  0xFE,  0xA3, 	/* 0E580 */
+	0x00,  0x07,  0xFC,  0x04,  0x00,  0x40,  0x04,  0x02,  0x7C,  0x24,  0x02,  0x40,  0x24,  0x02,  0x40,  0x24, 	/* 0E590 */
+	0x0F,  0xFE,  0xA4,  0x12,  0x01,  0x20,  0x12,  0x01,  0x20,  0x5E,  0x65,  0x38,  0x52,  0x05,  0x20,  0x52, 	/* 0E5A0 */
+	0x05,  0x22,  0x5E,  0x2E,  0x1E,  0xA6,  0x01,  0x47,  0xD2,  0x01,  0x0F,  0xFE,  0x11,  0x01,  0x10,  0x5F, 	/* 0E5B0 */
+	0x05,  0x10,  0x50,  0xA5,  0xEA,  0xF0,  0x60,  0x02,  0xA9,  0x04,  0x02,  0x40,  0x27,  0x82,  0x40,  0x24, 	/* 0E5C0 */
+	0x0F,  0xFE,  0x05,  0x02,  0x48,  0x4D,  0x48,  0x24,  0x0C,  0x07,  0x00,  0xAA,  0x00,  0x0F,  0xFE,  0x04, 	/* 0E5D0 */
+	0x00,  0xE0,  0x35,  0x8C,  0x46,  0x7F,  0xE0,  0x40,  0x27,  0xC2,  0x40,  0x24,  0x0F,  0xFE,  0xAF,  0x04, 	/* 0E5E0 */
+	0x02,  0x78,  0x24,  0x0F,  0xFE,  0x64,  0xC5,  0x54,  0x7F,  0xC4,  0xE4,  0x55,  0x46,  0x4C,  0x44,  0x47, 	/* 0E5F0 */
+	0xFC,  0xB3,  0x02,  0x01,  0x3C,  0x12,  0x0F,  0xFE,  0x01,  0x47,  0xFE,  0x5D,  0x04,  0x14,  0x7F,  0x45, 	/* 0E600 */
+	0xAA,  0x69,  0x68,  0xA2,  0xB4,  0x00,  0x07,  0xFE,  0x48,  0x87,  0xDE,  0x48,  0x85,  0xDC,  0x6A,  0xA4, 	/* 0E610 */
+	0xA8,  0x52,  0x09,  0x3C,  0x92,  0x07,  0xFE,  0xB8,  0x47,  0xCF,  0x04,  0x97,  0xEF,  0x04,  0xFF,  0xE8, 	/* 0E620 */
+	0x92,  0xFF,  0xC2,  0x54,  0xFD,  0x42,  0x5C,  0x35,  0x0C,  0x10,  0xB9,  0x00,  0x0F,  0xFE,  0x08,  0x00, 	/* 0E630 */
+	0xF8,  0x08,  0x81,  0x48,  0x23,  0x00,  0x10,  0x02,  0x00,  0x40,  0x18,  0x06,  0x00,  0xBB,  0x00,  0x0F, 	/* 0E640 */
+	0xFE,  0x22,  0x02,  0x24,  0x3A,  0x44,  0xA8,  0x4B,  0x0A,  0xA0,  0x12,  0x01,  0x22,  0x22,  0x24,  0x1E, 	/* 0E650 */
+	0xBF,  0x02,  0x0F,  0xBC,  0x22,  0x42,  0x44,  0x79,  0x85,  0x00,  0xDF,  0xCB,  0x44,  0x12,  0x82,  0x10, 	/* 0E660 */
+	0x46,  0x89,  0x86,  0x80,  0x00,  0xCF,  0xF0,  0x21,  0x02,  0x10,  0x79,  0x04,  0xFE,  0x69,  0x09,  0x10, 	/* 0E670 */
+	0x12,  0x82,  0x28,  0x44,  0x49,  0x82,  0x83,  0x01,  0x0F,  0x90,  0x27,  0xC2,  0x54,  0x75,  0x45,  0x54, 	/* 0E680 */
+	0x5F,  0xEB,  0x10,  0x22,  0x82,  0x28,  0x44,  0x49,  0x82,  0x84,  0x00,  0x8F,  0xC8,  0x21,  0x42,  0x22, 	/* 0E690 */
+	0x7C,  0x94,  0xB0,  0x6C,  0x49,  0x18,  0x16,  0x22,  0x04,  0x41,  0x88,  0x60,  0x86,  0x00,  0x8F,  0xC8, 	/* 0E6A0 */
+	0x21,  0x43,  0x92,  0x4A,  0x64,  0xFA,  0xA8,  0x01,  0x3E,  0x12,  0x22,  0x22,  0x42,  0x28,  0x3E,  0x89, 	/* 0E6B0 */
+	0x02,  0x0F,  0xA0,  0x43,  0xE7,  0x42,  0x57,  0xA5,  0xAA,  0x73,  0xA9,  0x2A,  0x22,  0xA2,  0x3A,  0x40, 	/* 0E6C0 */
+	0x28,  0x0C,  0x8A,  0x01,  0x0F,  0xD0,  0x25,  0x03,  0x7C,  0x59,  0x05,  0x10,  0xBF,  0xE1,  0x38,  0x25, 	/* 0E6D0 */
+	0x42,  0x92,  0x41,  0x08,  0x10,  0x8B,  0x01,  0x4F,  0xD2,  0x27,  0xC3,  0x90,  0x2F,  0xC4,  0x90,  0x6F, 	/* 0E6E0 */
+	0xE9,  0x0A,  0x10,  0xC2,  0x1A,  0x46,  0x68,  0x02,  0x8D,  0x00,  0xCF,  0xF8,  0x25,  0x42,  0x52,  0x78, 	/* 0E6F0 */
+	0x25,  0x7C,  0x50,  0x8B,  0x10,  0x2F,  0xE2,  0x10,  0x41,  0x08,  0x30,  0x95,  0x01,  0x0F,  0x90,  0x2F, 	/* 0E700 */
+	0xE2,  0x24,  0x7A,  0x84,  0xFE,  0x68,  0x09,  0x00,  0x17,  0xC2,  0x44,  0x44,  0x48,  0x7C,  0x96,  0x01, 	/* 0E710 */
+	0x0F,  0xFE,  0x21,  0x07,  0x3C,  0x5A,  0x45,  0xBC,  0x7A,  0x49,  0xBC,  0x2A,  0x42,  0xBC,  0x48,  0x08, 	/* 0E720 */
+	0xFE,  0x98,  0x01,  0x4F,  0x9E,  0x27,  0x42,  0x0A,  0x79,  0x64,  0xE4,  0x69,  0x69,  0xF8,  0x11,  0x42, 	/* 0E730 */
+	0x0A,  0x43,  0x68,  0xC2,  0x9E,  0x00,  0x0F,  0xBC,  0x22,  0x42,  0x7E,  0x74,  0x25,  0x7E,  0x54,  0x2B, 	/* 0E740 */
+	0x7E,  0x24,  0x22,  0x7E,  0x42,  0x48,  0x42,  0xA4,  0x04,  0x0F,  0xFE,  0x26,  0x42,  0xBC,  0x72,  0x45, 	/* 0E750 */
+	0xFE,  0x52,  0x0B,  0x7E,  0x2A,  0xA2,  0x4A,  0x49,  0x28,  0x0C,  0xAA,  0x01,  0x0F,  0xFE,  0x21,  0x02, 	/* 0E760 */
+	0xFE,  0x78,  0x25,  0x7C,  0x50,  0x0B,  0x7C,  0x24,  0x42,  0x7C,  0x42,  0x89,  0xFE,  0xAB,  0x0E,  0xEF, 	/* 0E770 */
+	0xAA,  0x4E,  0xE7,  0x00,  0x57,  0xC5,  0x54,  0xB7,  0xC1,  0x54,  0x27,  0xC2,  0x10,  0x4F,  0xE8,  0x10, 	/* 0E780 */
+	0xAF,  0x00,  0x0F,  0xFE,  0x4B,  0x27,  0x54,  0x53,  0x85,  0xFC,  0xB4,  0x41,  0x7C,  0x24,  0x42,  0x7C, 	/* 0E790 */
+	0x42,  0x48,  0xC2,  0xB1,  0x04,  0x8F,  0x4C,  0x4F,  0xA7,  0x4E,  0x5F,  0x85,  0xEA,  0xBB,  0xA1,  0xAA, 	/* 0E7A0 */
+	0x2B,  0x43,  0xA4,  0x4F,  0xA9,  0x91,  0xB2,  0x0A,  0x8F,  0xAC,  0x4D,  0xA7,  0x0E,  0x5F,  0x85,  0xAA, 	/* 0E7B0 */
+	0xBB,  0xA1,  0xAA,  0x2B,  0x43,  0xAC,  0x4F,  0xA9,  0x91,  0xB3,  0x00,  0x01,  0xF0,  0x11,  0x01,  0x10, 	/* 0E7C0 */
+	0x21,  0x2C,  0x0E,  0x3F,  0x01,  0x10,  0x0A,  0x00,  0x40,  0x1B,  0x0E,  0x0E,  0xB4,  0x03,  0x8F,  0xA8, 	/* 0E7D0 */
+	0x82,  0x8C,  0xAA,  0xAC,  0x69,  0x3C,  0x90,  0x4A,  0xA4,  0xC9,  0x88,  0x08,  0xFB,  0x40,  0xC2,  0xB5, 	/* 0E7E0 */
+	0x17,  0x86,  0x48,  0x44,  0x84,  0x4A,  0x78,  0x64,  0x7C,  0x70,  0x44,  0x28,  0x5A,  0x8E,  0x10,  0x42, 	/* 0E7F0 */
+	0x84,  0x46,  0xB7,  0x1B,  0x86,  0x28,  0x7A,  0x84,  0xAA,  0x7A,  0x64,  0xC0,  0x7B,  0xC4,  0x04,  0x79, 	/* 0E800 */
+	0x44,  0x88,  0x49,  0x4B,  0x62,  0xBA,  0x93,  0x85,  0x28,  0x22,  0x85,  0xAA,  0x84,  0x62,  0x00,  0xF7, 	/* 0E810 */
+	0xC2,  0x44,  0x72,  0x86,  0x90,  0xA2,  0x82,  0xC6,  0xBB,  0x23,  0x8F,  0xA8,  0x22,  0x87,  0xAA,  0x04, 	/* 0E820 */
+	0x6F,  0x80,  0x8B,  0xC7,  0x04,  0x52,  0x85,  0x90,  0x52,  0x88,  0xC4,  0xBC,  0x21,  0xCF,  0x94,  0x21, 	/* 0E830 */
+	0x4F,  0x95,  0x8A,  0x77,  0x40,  0x07,  0xE7,  0x12,  0x51,  0x45,  0x48,  0x59,  0x49,  0x62,  0xBF,  0x7D, 	/* 0E840 */
+	0xC4,  0x54,  0x45,  0x47,  0xD5,  0x52,  0x77,  0xE0,  0x55,  0xE5,  0x52,  0x7F,  0x49,  0x88,  0xA5,  0x44, 	/* 0E850 */
+	0x62,  0x80,  0x43,  0x89,  0xA8,  0x8A,  0x8D,  0xAA,  0x8C,  0x6F,  0x80,  0x27,  0xC2,  0x24,  0xF9,  0x42, 	/* 0E860 */
+	0x18,  0x3A,  0x4C,  0x42,  0x85,  0x23,  0x8F,  0xA8,  0x52,  0x85,  0x4A,  0xF8,  0x62,  0x7C,  0xE8,  0x43, 	/* 0E870 */
+	0x64,  0xD9,  0x83,  0x48,  0xD1,  0x43,  0x62,  0x86,  0x01,  0xCF,  0xD4,  0x81,  0x5B,  0x95,  0xAA,  0x3B, 	/* 0E880 */
+	0xC0,  0x83,  0xEE,  0xE2,  0xAB,  0x4E,  0xE8,  0x81,  0x4F,  0xE2,  0x8B,  0x00,  0x01,  0xFC,  0x12,  0x41, 	/* 0E890 */
+	0x24,  0x12,  0x4F,  0xFE,  0x24,  0x42,  0x44,  0x24,  0x47,  0xFE,  0x00,  0x40,  0x18,  0x8D,  0x00,  0x01, 	/* 0E8A0 */
+	0xFC,  0x14,  0x41,  0x24,  0x10,  0x4F,  0xFF,  0x24,  0x42,  0x24,  0x20,  0x47,  0xFE,  0x40,  0x80,  0x30, 	/* 0E8B0 */
+	0x8E,  0x20,  0x03,  0xFE,  0x40,  0x09,  0xF8,  0x14,  0x81,  0x48,  0xFF,  0xE2,  0x48,  0x24,  0x87,  0xFE, 	/* 0E8C0 */
+	0x40,  0x80,  0x30,  0x92,  0x04,  0x07,  0xFC,  0x04,  0x07,  0xFC,  0x04,  0x0F,  0xFE,  0x24,  0x8F,  0xFE, 	/* 0E8D0 */
+	0x48,  0x87,  0xF8,  0x00,  0x80,  0x30,  0x93,  0x40,  0x87,  0xFE,  0x80,  0x87,  0x94,  0x4F,  0xE6,  0x82, 	/* 0E8E0 */
+	0x7B,  0x4C,  0xB4,  0xAB,  0x4F,  0xB6,  0x15,  0x66,  0x82,  0x94,  0x42,  0x04,  0x20,  0x42,  0x04,  0x24, 	/* 0E8F0 */
+	0x7A,  0x44,  0x28,  0x43,  0x04,  0x20,  0x42,  0x05,  0xA2,  0x62,  0x2C,  0x1E,  0x98,  0x00,  0x07,  0xFC, 	/* 0E900 */
+	0x44,  0x47,  0xFC,  0x44,  0x47,  0xFC,  0x22,  0x03,  0xAC,  0x23,  0x02,  0x22,  0x3E,  0x2E,  0x1E,  0x9B, 	/* 0E910 */
+	0x01,  0x80,  0xE0,  0x78,  0x00,  0x80,  0x7F,  0xC0,  0x80,  0x08,  0x0F,  0xFE,  0x08,  0x00,  0x82,  0x08, 	/* 0E920 */
+	0x20,  0x7E,  0x9F,  0x04,  0x02,  0x48,  0x24,  0x44,  0xCA,  0x83,  0x20,  0xF8,  0x74,  0x00,  0x7C,  0x7C, 	/* 0E930 */
+	0x00,  0x7E,  0xFC,  0x10,  0x3F,  0xAB,  0x04,  0x0F,  0xFE,  0x3F,  0x82,  0x08,  0xFF,  0xE8,  0x3A,  0x9C, 	/* 0E940 */
+	0x27,  0xF8,  0x08,  0x0F,  0xFC,  0x08,  0x20,  0x7E,  0xAC,  0x09,  0x43,  0x12,  0xEF,  0xE2,  0x10,  0x3D, 	/* 0E950 */
+	0x2E,  0x5C,  0x23,  0x83,  0x54,  0xE9,  0x22,  0x30,  0x20,  0x11,  0xFF,  0xAF,  0x09,  0x23,  0x54,  0xE9, 	/* 0E960 */
+	0x82,  0x28,  0x3C,  0x4E,  0x10,  0x25,  0x23,  0x94,  0xE2,  0x82,  0xC4,  0x20,  0x11,  0xFF,  0xB3,  0x03, 	/* 0E970 */
+	0x03,  0xC0,  0x08,  0x07,  0xF8,  0x08,  0x40,  0x7C,  0x10,  0x83,  0x9E,  0xE7,  0x03,  0xDE,  0xE7,  0x21, 	/* 0E980 */
+	0xCE,  0x88,  0x10,  0xCF,  0xF0,  0x89,  0x0B,  0x96,  0xAF,  0x8F,  0x90,  0x49,  0x67,  0xF8,  0x49,  0x07, 	/* 0E990 */
+	0x90,  0x49,  0x2F,  0xCE,  0x8F,  0x01,  0x00,  0x60,  0x7C,  0x04,  0x40,  0x44,  0x04,  0x7C,  0x7C,  0x04, 	/* 0E9A0 */
+	0x20,  0x42,  0x04,  0x12,  0x58,  0xAE,  0x06,  0x91,  0x00,  0x03,  0xFC,  0x20,  0x42,  0x04,  0x3F,  0xC2, 	/* 0E9B0 */
+	0x20,  0x3F,  0xE2,  0x10,  0x21,  0x02,  0x0A,  0x38,  0x6E,  0x02,  0x93,  0x20,  0x02,  0x7E,  0xFC,  0x28, 	/* 0E9C0 */
+	0x42,  0x87,  0xE8,  0x48,  0x87,  0xF8,  0x48,  0x94,  0x47,  0x46,  0x07,  0x21,  0x82,  0x94,  0x20,  0x03, 	/* 0E9D0 */
+	0xF8,  0x20,  0x05,  0xF0,  0x80,  0x07,  0xF8,  0x00,  0x80,  0x08,  0x00,  0x80,  0x0A,  0x00,  0x60,  0x02, 	/* 0E9E0 */
+	0x97,  0x20,  0x03,  0xFC,  0x20,  0x05,  0xF0,  0x80,  0x07,  0xF8,  0x04,  0x83,  0x48,  0x08,  0x81,  0x4A, 	/* 0E9F0 */
+	0x20,  0x6C,  0x02,  0x9B,  0x20,  0x03,  0xFC,  0x20,  0x05,  0xF8,  0x80,  0x07,  0xF8,  0x24,  0x82,  0x28, 	/* 0EA00 */
+	0x7D,  0x89,  0x4A,  0x24,  0x64,  0xC2,  0xA3,  0x20,  0x03,  0xFC,  0x20,  0x05,  0xF8,  0x80,  0x07,  0xF8, 	/* 0EA10 */
+	0x49,  0x82,  0xA8,  0x7F,  0x81,  0xCA,  0x6A,  0x60,  0x82,  0xA4,  0x20,  0x03,  0xFC,  0x20,  0x05,  0xF0, 	/* 0EA20 */
+	0x80,  0x0F,  0xFC,  0x7F,  0x44,  0x94,  0x7F,  0x45,  0x56,  0x63,  0x67,  0xF2,  0xB4,  0x04,  0x00,  0x40, 	/* 0EA30 */
+	0x04,  0x40,  0x64,  0x7E,  0x80,  0xD0,  0x0D,  0x01,  0x48,  0x24,  0x44,  0x42,  0x04,  0x00,  0xC0,  0xB7, 	/* 0EA40 */
+	0x04,  0x04,  0x40,  0x24,  0x42,  0x64,  0x06,  0x8F,  0x50,  0x15,  0x01,  0x48,  0x24,  0x44,  0x42,  0x84, 	/* 0EA50 */
+	0x00,  0xC0,  0xB8,  0x0C,  0x00,  0x20,  0x00,  0x01,  0xC4,  0x06,  0x8F,  0xF0,  0x15,  0x01,  0x48,  0x24, 	/* 0EA60 */
+	0x4C,  0x42,  0x04,  0x00,  0xC0,  0xBE,  0x40,  0x02,  0xFC,  0x08,  0x48,  0x84,  0x48,  0x40,  0x84,  0x09, 	/* 0EA70 */
+	0x82,  0x80,  0x48,  0x04,  0x82,  0x88,  0x28,  0x7E,  0x80,  0x40,  0x02,  0xFE,  0x01,  0x08,  0x10,  0x41, 	/* 0EA80 */
+	0x00,  0x10,  0x01,  0x02,  0x10,  0x41,  0x04,  0x10,  0x81,  0x08,  0x30,  0x81,  0x41,  0x02,  0x10,  0x01, 	/* 0EA90 */
+	0x08,  0x10,  0x4F,  0xE0,  0x10,  0x01,  0x02,  0x10,  0x41,  0x04,  0x10,  0x81,  0x08,  0x10,  0x82,  0x04, 	/* 0EAA0 */
+	0x00,  0x50,  0x04,  0x8F,  0xFE,  0x04,  0x04,  0x64,  0x26,  0x80,  0xD0,  0x34,  0x8C,  0x44,  0x04,  0x20, 	/* 0EAB0 */
+	0xC0,  0x8E,  0x40,  0x02,  0x78,  0x04,  0x88,  0x48,  0x44,  0x80,  0x68,  0x05,  0x82,  0x48,  0x44,  0x84, 	/* 0EAC0 */
+	0x8A,  0x88,  0xA9,  0x06,  0x90,  0x42,  0x02,  0x20,  0x03,  0xE8,  0x22,  0x44,  0x20,  0x64,  0x09,  0x42, 	/* 0EAD0 */
+	0x08,  0x40,  0x84,  0x10,  0x86,  0x09,  0x80,  0x95,  0x41,  0x02,  0x10,  0x01,  0x08,  0x10,  0x41,  0x00, 	/* 0EAE0 */
+	0x92,  0x09,  0x22,  0x92,  0x49,  0x24,  0x92,  0x89,  0x28,  0xFE,  0x97,  0x40,  0x03,  0xFC,  0x02,  0x08, 	/* 0EAF0 */
+	0x20,  0x42,  0x03,  0xFE,  0x02,  0x02,  0x20,  0x42,  0x04,  0x20,  0x82,  0x08,  0x20,  0x9A,  0x40,  0x02, 	/* 0EB00 */
+	0xFC,  0x02,  0x08,  0x20,  0x5F,  0xE0,  0x40,  0x07,  0xC2,  0x84,  0x48,  0x44,  0x04,  0x80,  0x48,  0x18, 	/* 0EB10 */
+	0x9D,  0x44,  0x02,  0x40,  0x04,  0x0B,  0xFE,  0x44,  0x80,  0x88,  0x09,  0x02,  0xD0,  0x52,  0x04,  0x58, 	/* 0EB20 */
+	0x88,  0x4B,  0x02,  0x9E,  0x00,  0x07,  0xFC,  0x04,  0x00,  0x40,  0xFF,  0xE0,  0x44,  0x06,  0x4F,  0x68, 	/* 0EB30 */
+	0x15,  0x02,  0x48,  0xC4,  0x60,  0xC0,  0x9F,  0x40,  0x02,  0xFC,  0x01,  0x08,  0x10,  0x41,  0x00,  0x10, 	/* 0EB40 */
+	0x01,  0x02,  0x10,  0x41,  0x04,  0x10,  0x9F,  0xE8,  0x00,  0xA0,  0x41,  0x02,  0x50,  0x05,  0x08,  0x5C, 	/* 0EB50 */
+	0x47,  0x41,  0xD4,  0x05,  0x42,  0x54,  0x45,  0x84,  0x40,  0x84,  0x28,  0x3E,  0xA2,  0x42,  0x02,  0x20, 	/* 0EB60 */
+	0x02,  0x08,  0x20,  0x4F,  0xC0,  0x20,  0x02,  0x02,  0x20,  0x42,  0x04,  0x20,  0x82,  0x09,  0xFE,  0xA8, 	/* 0EB70 */
+	0x40,  0x02,  0x7E,  0x04,  0x28,  0x42,  0x44,  0x20,  0x42,  0x07,  0xE2,  0x42,  0x44,  0x24,  0x42,  0x84, 	/* 0EB80 */
+	0x28,  0x7E,  0xAA,  0x40,  0x03,  0xFE,  0x02,  0x08,  0x20,  0x42,  0x00,  0xFC,  0x02,  0x02,  0x20,  0x42, 	/* 0EB90 */
+	0x04,  0x20,  0x82,  0x09,  0xFE,  0xB0,  0x41,  0x02,  0x10,  0x01,  0x08,  0x10,  0x4F,  0xE0,  0x10,  0x03, 	/* 0EBA0 */
+	0x02,  0x30,  0x44,  0x84,  0x68,  0x89,  0x49,  0x02,  0xB2,  0x40,  0x03,  0xF8,  0x04,  0x88,  0x50,  0x45, 	/* 0EBB0 */
+	0xC0,  0x44,  0x0A,  0x42,  0xA8,  0x49,  0x04,  0x98,  0x92,  0x4A,  0xC2,  0xB3,  0x40,  0x02,  0xFE,  0x08, 	/* 0EBC0 */
+	0x08,  0x80,  0x4F,  0xC0,  0x84,  0x0C,  0x82,  0xA8,  0x49,  0x05,  0x18,  0x92,  0x4A,  0xC2,  0xBA,  0x42, 	/* 0EBD0 */
+	0x02,  0x20,  0x1F,  0xC8,  0x24,  0x42,  0x40,  0x24,  0x3F,  0xF2,  0x30,  0x45,  0x04,  0x48,  0x88,  0x4B, 	/* 0EBE0 */
+	0x02,  0xBD,  0x50,  0x03,  0xFC,  0x10,  0x0A,  0xF8,  0x40,  0x01,  0xF8,  0x00,  0x82,  0x08,  0x40,  0xA4, 	/* 0EBF0 */
+	0x0A,  0x80,  0x68,  0x02,  0xBE,  0x44,  0x82,  0x48,  0x04,  0x88,  0x84,  0x48,  0x43,  0x7E,  0x02,  0x52, 	/* 0EC00 */
+	0x24,  0x42,  0x44,  0x44,  0x84,  0x48,  0x98,  0x81,  0x42,  0x02,  0x10,  0x01,  0x08,  0x40,  0x44,  0x01, 	/* 0EC10 */
+	0x40,  0x14,  0x45,  0x42,  0x64,  0x24,  0x4A,  0x84,  0x88,  0x38,  0x82,  0x40,  0xC2,  0x70,  0x04,  0x08, 	/* 0EC20 */
+	0x40,  0x47,  0xE0,  0x48,  0x04,  0x82,  0x48,  0x44,  0x84,  0x88,  0x88,  0x89,  0x08,  0x83,  0x40,  0xC2, 	/* 0EC30 */
+	0xF0,  0x02,  0x08,  0x20,  0x42,  0x01,  0xFE,  0x02,  0x02,  0x30,  0x43,  0x04,  0x48,  0x88,  0x4B,  0x02, 	/* 0EC40 */
+	0x88,  0x42,  0x02,  0x20,  0x1F,  0xE9,  0x22,  0x52,  0x20,  0x30,  0x03,  0x02,  0x30,  0x45,  0x04,  0x52, 	/* 0EC50 */
+	0x89,  0x29,  0x0E,  0x8C,  0x82,  0x04,  0x26,  0x1F,  0x80,  0x20,  0x92,  0x45,  0x24,  0x12,  0x43,  0xFC, 	/* 0EC60 */
+	0x52,  0x04,  0x22,  0x82,  0x28,  0x1E,  0x8D,  0x40,  0x02,  0xFE,  0x02,  0x08,  0x20,  0x47,  0xC0,  0x44, 	/* 0EC70 */
+	0x08,  0x42,  0x88,  0x5F,  0x85,  0x08,  0x80,  0x8B,  0xFE,  0x90,  0x42,  0x02,  0x20,  0x02,  0x09,  0xFE, 	/* 0EC80 */
+	0x42,  0x02,  0x70,  0x07,  0x02,  0x68,  0x4A,  0x84,  0xA4,  0x92,  0x28,  0x20,  0x92,  0x42,  0x02,  0x3C, 	/* 0EC90 */
+	0x02,  0x48,  0x44,  0x49,  0x80,  0x00,  0x0F,  0xC2,  0x44,  0x42,  0x84,  0x10,  0x86,  0x89,  0x86,  0x93, 	/* 0ECA0 */
+	0x04,  0x00,  0x4C,  0xF7,  0x01,  0x60,  0x25,  0x8C,  0x46,  0x0C,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20, 	/* 0ECB0 */
+	0x83,  0xF8,  0x96,  0x41,  0x02,  0x10,  0x0F,  0xE8,  0x92,  0x49,  0x20,  0x92,  0x0F,  0xE2,  0x10,  0x41, 	/* 0ECC0 */
+	0x04,  0x10,  0x81,  0x08,  0x10,  0x99,  0x41,  0x02,  0x10,  0x05,  0x48,  0x54,  0x45,  0x20,  0x92,  0x11, 	/* 0ECD0 */
+	0x60,  0x34,  0x20,  0x84,  0x10,  0x46,  0x09,  0x80,  0x9A,  0x41,  0x02,  0x10,  0x01,  0x08,  0x90,  0x49, 	/* 0ECE0 */
+	0xE0,  0x90,  0x09,  0x02,  0x90,  0x49,  0x04,  0x90,  0x89,  0x0B,  0xFE,  0x9B,  0x82,  0x04,  0x20,  0x3F, 	/* 0ECF0 */
+	0xE8,  0x20,  0x5F,  0xC1,  0x24,  0x12,  0x43,  0x24,  0x52,  0x45,  0x38,  0x82,  0x08,  0x20,  0xA1,  0x47, 	/* 0ED00 */
+	0x82,  0x48,  0x04,  0x88,  0x4A,  0x58,  0x60,  0xF8,  0x00,  0x82,  0x48,  0x43,  0x04,  0x30,  0x84,  0x89, 	/* 0ED10 */
+	0x86,  0xA2,  0x40,  0x02,  0x7E,  0x04,  0x28,  0x42,  0x47,  0xE0,  0x50,  0x05,  0x02,  0x48,  0x44,  0x84, 	/* 0ED20 */
+	0x84,  0x88,  0x49,  0x02,  0xAB,  0x42,  0x02,  0x20,  0x3F,  0xE8,  0x20,  0x42,  0x01,  0xFC,  0x06,  0x02, 	/* 0ED30 */
+	0x70,  0x4A,  0x85,  0x24,  0xA2,  0x28,  0x20,  0xAE,  0x40,  0x02,  0x7C,  0x04,  0x48,  0x44,  0x47,  0xC0, 	/* 0ED40 */
+	0x44,  0x04,  0x42,  0x7C,  0x44,  0x44,  0x44,  0x84,  0x49,  0xFE,  0xB1,  0x42,  0x02,  0x20,  0x1F,  0xE9, 	/* 0ED50 */
+	0x02,  0x50,  0x22,  0x40,  0x04,  0xC2,  0x70,  0x44,  0x04,  0x40,  0x84,  0x28,  0x3E,  0xB3,  0x40,  0x02, 	/* 0ED60 */
+	0xFE,  0x00,  0x48,  0x04,  0x4F,  0x40,  0x94,  0x09,  0x42,  0xF4,  0x40,  0x44,  0x04,  0x80,  0x48,  0x0C, 	/* 0ED70 */
+	0xB8,  0x45,  0x02,  0xFC,  0x05,  0x48,  0x54,  0x5F,  0xC1,  0x50,  0x1F,  0xE2,  0x52,  0x45,  0x24,  0x52, 	/* 0ED80 */
+	0x89,  0xC9,  0x10,  0xB9,  0x41,  0x02,  0x10,  0x01,  0x08,  0xFE,  0x49,  0x20,  0x92,  0x09,  0x22,  0xFE, 	/* 0ED90 */
+	0x49,  0x24,  0x92,  0x89,  0x28,  0xFE,  0xBA,  0x40,  0x02,  0xFE,  0x09,  0x28,  0x92,  0x49,  0x20,  0xFE, 	/* 0EDA0 */
+	0x09,  0x22,  0x92,  0x49,  0x24,  0x92,  0x89,  0x28,  0xFE,  0xBB,  0x42,  0x02,  0x20,  0x02,  0x88,  0x44, 	/* 0EDB0 */
+	0x49,  0xE1,  0xE2,  0x00,  0x02,  0xFC,  0x48,  0x44,  0x84,  0x88,  0x48,  0xFC,  0xBC,  0x40,  0x02,  0xFE, 	/* 0EDC0 */
+	0x01,  0x28,  0x12,  0x42,  0x20,  0x4C,  0x08,  0x02,  0x7E,  0x44,  0x24,  0x42,  0x84,  0x28,  0x7E,  0xBD, 	/* 0EDD0 */
+	0x42,  0x02,  0x20,  0x02,  0x09,  0xFE,  0x42,  0x00,  0x20,  0x02,  0x02,  0xFC,  0x48,  0x44,  0x84,  0x88, 	/* 0EDE0 */
+	0x48,  0xFC,  0xBE,  0x42,  0x02,  0x20,  0x02,  0x08,  0x3E,  0x42,  0x00,  0x20,  0x02,  0x02,  0xFC,  0x48, 	/* 0EDF0 */
+	0x44,  0x84,  0x88,  0x48,  0xFC,  0xBF,  0x45,  0x02,  0x50,  0x05,  0x00,  0x88,  0x88,  0x85,  0x04,  0x2F, 	/* 0EE00 */
+	0xA2,  0x88,  0x48,  0x84,  0x88,  0x88,  0x88,  0xF8,  0x81,  0x40,  0x02,  0xFC,  0x08,  0x48,  0x84,  0x48, 	/* 0EE10 */
+	0x40,  0xFC,  0x05,  0x02,  0x50,  0x45,  0x04,  0x92,  0x89,  0x29,  0x0E,  0x84,  0x45,  0x42,  0x54,  0x05, 	/* 0EE20 */
+	0x49,  0xFE,  0x45,  0x40,  0x54,  0x05,  0x42,  0x5C,  0x45,  0x04,  0x40,  0x87,  0xE8,  0x40,  0x85,  0x40, 	/* 0EE30 */
+	0x02,  0xFE,  0x09,  0x28,  0x92,  0x49,  0x22,  0x92,  0x09,  0xA2,  0xAA,  0x4A,  0x64,  0xC6,  0x88,  0x28, 	/* 0EE40 */
+	0xFE,  0x89,  0x08,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x04,  0x4F,  0xD8,  0x15,  0x02, 	/* 0EE50 */
+	0x48,  0xC4,  0x60,  0xC0,  0x8A,  0x41,  0x02,  0x10,  0x02,  0x08,  0xFC,  0x48,  0x40,  0x84,  0x08,  0x42, 	/* 0EE60 */
+	0xFC,  0x48,  0x44,  0x84,  0x88,  0x48,  0xFC,  0x8C,  0x42,  0x02,  0x10,  0x01,  0x48,  0x44,  0x44,  0x81, 	/* 0EE70 */
+	0x48,  0x15,  0x45,  0x62,  0x64,  0x24,  0xCA,  0xB4,  0x88,  0x38,  0x93,  0x80,  0x85,  0xC8,  0x04,  0x88, 	/* 0EE80 */
+	0x48,  0x5C,  0x81,  0x10,  0x1D,  0x03,  0x54,  0x45,  0x44,  0x52,  0x85,  0xE9,  0xB2,  0x95,  0x41,  0x02, 	/* 0EE90 */
+	0x10,  0x0F,  0xE8,  0x10,  0x41,  0x01,  0xFF,  0x01,  0x02,  0x28,  0x42,  0x44,  0x5C,  0x8E,  0x28,  0x02, 	/* 0EEA0 */
+	0x97,  0x40,  0x03,  0xFE,  0x15,  0x29,  0x52,  0x55,  0x21,  0x52,  0x15,  0x23,  0x9E,  0x50,  0x25,  0x02, 	/* 0EEB0 */
+	0x9F,  0xE8,  0x00,  0x99,  0x40,  0x02,  0xFE,  0x01,  0x08,  0x54,  0x45,  0x20,  0x90,  0x1F,  0xF2,  0x10, 	/* 0EEC0 */
+	0x41,  0x04,  0x10,  0x81,  0x08,  0x10,  0x9B,  0x40,  0xE2,  0xF0,  0x01,  0x08,  0x10,  0x4F,  0xE0,  0x04, 	/* 0EED0 */
+	0x00,  0x82,  0x10,  0x4A,  0x04,  0xC0,  0x8B,  0x09,  0x0F,  0x9D,  0x40,  0xC2,  0x70,  0x04,  0x08,  0x40, 	/* 0EEE0 */
+	0x47,  0xE0,  0x48,  0x06,  0x82,  0x58,  0x44,  0xC4,  0x8A,  0x88,  0x89,  0x08,  0xA1,  0x44,  0x02,  0x40, 	/* 0EEF0 */
+	0x07,  0xE8,  0x42,  0x4F,  0xA1,  0x0A,  0x07,  0xA2,  0x44,  0x44,  0x04,  0x42,  0x84,  0x28,  0x3E,  0xA2, 	/* 0EF00 */
+	0x41,  0x02,  0x10,  0x0F,  0xE8,  0x92,  0x49,  0x40,  0xFC,  0x08,  0x42,  0xC8,  0x4B,  0x05,  0x30,  0x94, 	/* 0EF10 */
+	0x8B,  0x86,  0xA3,  0x42,  0x02,  0x20,  0x02,  0x09,  0xFE,  0x40,  0x40,  0x84,  0x08,  0x42,  0x44,  0x44, 	/* 0EF20 */
+	0x84,  0x48,  0x84,  0x89,  0xFE,  0xA5,  0x40,  0x02,  0xFE,  0x08,  0x28,  0x82,  0x4F,  0xE0,  0xA0,  0x0A, 	/* 0EF30 */
+	0x62,  0xB8,  0x4A,  0x05,  0x22,  0x92,  0x2A,  0x1E,  0xA8,  0x42,  0x02,  0x10,  0x0F,  0xE8,  0x10,  0x41, 	/* 0EF40 */
+	0x00,  0x10,  0x07,  0xC2,  0x10,  0x41,  0x04,  0x10,  0x81,  0x08,  0xFE,  0xAA,  0x40,  0x02,  0xFE,  0x08, 	/* 0EF50 */
+	0x28,  0x82,  0x4F,  0xE0,  0x82,  0x08,  0x22,  0xFE,  0x48,  0x24,  0x82,  0x88,  0x28,  0xFE,  0xAF,  0x40, 	/* 0EF60 */
+	0x02,  0xFC,  0x08,  0x48,  0xFC,  0x49,  0x00,  0x90,  0x0F,  0xE2,  0x88,  0x48,  0x84,  0x86,  0x8B,  0x69, 	/* 0EF70 */
+	0xC2,  0xB0,  0x04,  0x07,  0xFC,  0x04,  0x03,  0xF8,  0x0A,  0x0F,  0xFE,  0x24,  0x85,  0x54,  0x8E,  0x31, 	/* 0EF80 */
+	0x50,  0x64,  0xC0,  0x40,  0xB1,  0x42,  0x02,  0x20,  0x0F,  0xC8,  0xA4,  0x4A,  0x42,  0xA4,  0x1F,  0xE2, 	/* 0EF90 */
+	0x20,  0x42,  0x04,  0x50,  0x88,  0x8B,  0x06,  0xB3,  0x43,  0x02,  0x08,  0x00,  0x08,  0x72,  0x41,  0xC1, 	/* 0EFA0 */
+	0xD8,  0x05,  0x82,  0x54,  0x49,  0x25,  0x11,  0x81,  0x08,  0x30,  0x8B,  0x48,  0x82,  0x48,  0x05,  0x09, 	/* 0EFB0 */
+	0xFE,  0x42,  0x00,  0xFC,  0x02,  0x02,  0x20,  0x5F,  0xE4,  0x20,  0x82,  0x08,  0x20,  0x8C,  0x40,  0x23, 	/* 0EFC0 */
+	0xEA,  0x08,  0xA8,  0x8A,  0x4E,  0xA3,  0x2A,  0x1A,  0xA2,  0x6A,  0x44,  0xA4,  0x42,  0x88,  0x29,  0x06, 	/* 0EFD0 */
+	0x92,  0x4F,  0xE2,  0x28,  0x02,  0x88,  0xFE,  0x4A,  0xA0,  0xAA,  0x0A,  0xA2,  0xCE,  0x48,  0x24,  0x82, 	/* 0EFE0 */
+	0x8F,  0xE8,  0x80,  0x97,  0x4A,  0x02,  0xA0,  0x0F,  0xC9,  0x20,  0x52,  0x03,  0xFE,  0x05,  0x02,  0x50, 	/* 0EFF0 */
+	0x49,  0x04,  0x92,  0x91,  0x2A,  0x0E,  0x99,  0x41,  0x02,  0x10,  0x09,  0x00,  0xFE,  0x89,  0x05,  0x10, 	/* 0F000 */
+	0x0F,  0xE2,  0x38,  0x45,  0x44,  0x92,  0x91,  0x18,  0x10,  0x9B,  0x42,  0x02,  0x3C,  0x04,  0x48,  0xC8, 	/* 0F010 */
+	0x53,  0x00,  0x28,  0x04,  0x42,  0xFE,  0x54,  0x54,  0x44,  0x84,  0x48,  0x7C,  0x9E,  0x40,  0x02,  0xFE, 	/* 0F020 */
+	0x08,  0x28,  0xBA,  0x48,  0x20,  0xBA,  0x0A,  0xA2,  0xAA,  0x2B,  0xA4,  0x82,  0x48,  0x28,  0x86,  0x9F, 	/* 0F030 */
+	0x42,  0x03,  0xFE,  0x02,  0x09,  0xFC,  0x42,  0x41,  0xFC,  0x12,  0x03,  0xFE,  0x42,  0x24,  0x56,  0x88, 	/* 0F040 */
+	0x8B,  0x06,  0xA5,  0x41,  0x02,  0xFE,  0x01,  0x29,  0xFF,  0x41,  0x20,  0xFE,  0x01,  0x02,  0xFE,  0x41, 	/* 0F050 */
+	0x05,  0xFF,  0x81,  0x08,  0x10,  0xA9,  0x42,  0x02,  0x20,  0x1F,  0xC9,  0x24,  0x5F,  0xC1,  0x24,  0x1F, 	/* 0F060 */
+	0xC2,  0x20,  0x42,  0x84,  0x10,  0x86,  0xA9,  0x86,  0xAA,  0x44,  0x82,  0x48,  0x04,  0x89,  0xFE,  0x44, 	/* 0F070 */
+	0x80,  0x48,  0x04,  0x83,  0xFE,  0x40,  0x04,  0x48,  0x88,  0x49,  0x02,  0xAB,  0x41,  0x02,  0x20,  0x0F, 	/* 0F080 */
+	0xE8,  0xAA,  0x4A,  0xA0,  0xAA,  0x0A,  0xA2,  0xAA,  0x4A,  0xA4,  0xAA,  0x9F,  0xF8,  0x00,  0xB2,  0x08, 	/* 0F090 */
+	0x24,  0x92,  0x29,  0x20,  0x92,  0xAD,  0xA5,  0xB6,  0x09,  0x22,  0x92,  0x49,  0x25,  0x12,  0x91,  0x2A, 	/* 0F0A0 */
+	0x02,  0xB3,  0x90,  0x05,  0x00,  0x15,  0xEB,  0xF2,  0x55,  0x21,  0x52,  0x15,  0x23,  0x52,  0x35,  0x24, 	/* 0F0B0 */
+	0x92,  0x55,  0xEA,  0x00,  0xB5,  0x44,  0x02,  0x40,  0x07,  0xE8,  0x82,  0x57,  0xA0,  0x4A,  0x07,  0xA2, 	/* 0F0C0 */
+	0x4A,  0x44,  0xA4,  0x7A,  0x80,  0x28,  0x0C,  0xB6,  0x44,  0x02,  0x40,  0x0F,  0xE8,  0x82,  0x50,  0xA0, 	/* 0F0D0 */
+	0xDA,  0x0A,  0xA2,  0xDA,  0x48,  0xA4,  0xFA,  0x88,  0x28,  0x0C,  0xB8,  0x82,  0x05,  0x24,  0x0A,  0x48, 	/* 0F0E0 */
+	0xA8,  0x42,  0x03,  0xFE,  0x05,  0x02,  0x50,  0x45,  0x04,  0x52,  0x89,  0x29,  0x0E,  0xBB,  0x40,  0xC2, 	/* 0F0F0 */
+	0xF0,  0x02,  0x08,  0x20,  0x5F,  0xE0,  0x20,  0x02,  0x02,  0xFC,  0x48,  0x44,  0x84,  0x88,  0x48,  0xFC, 	/* 0F100 */
+	0xBD,  0x42,  0x02,  0x20,  0x05,  0x08,  0x88,  0x50,  0x42,  0xFA,  0x00,  0x02,  0x00,  0x4F,  0xC4,  0x84, 	/* 0F110 */
+	0x88,  0x48,  0xFC,  0xBE,  0x40,  0xC2,  0xF0,  0x08,  0x48,  0xB8,  0x4A,  0x20,  0xBC,  0x0B,  0x02,  0xB0, 	/* 0F120 */
+	0x4A,  0x85,  0x24,  0x92,  0x2A,  0x20,  0x81,  0x42,  0x03,  0xFC,  0x02,  0x08,  0x48,  0x5F,  0x40,  0x04, 	/* 0F130 */
+	0x0A,  0x82,  0xA8,  0x4A,  0x84,  0xAA,  0x92,  0xAA,  0x06,  0x84,  0x44,  0x02,  0x78,  0x19,  0x00,  0xFC, 	/* 0F140 */
+	0x82,  0x45,  0xFE,  0x02,  0x42,  0xFC,  0x42,  0x04,  0x20,  0x82,  0x08,  0x60,  0x85,  0x42,  0x82,  0x3C, 	/* 0F150 */
+	0x1E,  0x08,  0x3C,  0x4E,  0x00,  0x2E,  0x1F,  0x42,  0x18,  0x21,  0x04,  0x6A,  0x58,  0x68,  0x02,  0x99, 	/* 0F160 */
+	0x88,  0x64,  0x98,  0x09,  0x0B,  0xD0,  0x49,  0xE2,  0x94,  0x0D,  0x43,  0x94,  0x49,  0x44,  0x94,  0x8A, 	/* 0F170 */
+	0x49,  0xC4,  0x9A,  0x42,  0x02,  0x48,  0x1F,  0xC8,  0x52,  0x45,  0x01,  0x8E,  0x04,  0x02,  0x7C,  0x58, 	/* 0F180 */
+	0x84,  0x70,  0x8D,  0x8B,  0x06,  0x9C,  0x41,  0x82,  0xE0,  0x08,  0x08,  0xFC,  0x49,  0x00,  0x90,  0x09, 	/* 0F190 */
+	0x03,  0xFE,  0x40,  0x04,  0x88,  0x88,  0x49,  0x04,  0xA3,  0x41,  0x03,  0xFE,  0x10,  0x29,  0xFA,  0x40, 	/* 0F1A0 */
+	0x00,  0x00,  0x1F,  0xE2,  0x50,  0x45,  0x04,  0x92,  0x89,  0x29,  0x0E,  0xA4,  0x42,  0x03,  0xFE,  0x12, 	/* 0F1B0 */
+	0x29,  0x20,  0x5F,  0xE0,  0x40,  0x05,  0x02,  0x90,  0x4A,  0x45,  0x24,  0x84,  0xE8,  0xF2,  0xA6,  0x41, 	/* 0F1C0 */
+	0x22,  0x11,  0x0F,  0xE8,  0x10,  0x4F,  0xE0,  0x92,  0x0F,  0xE2,  0x92,  0x4F,  0xE4,  0x92,  0x89,  0x28, 	/* 0F1D0 */
+	0x96,  0xA9,  0x41,  0x02,  0x90,  0x0F,  0xC8,  0x90,  0x51,  0x01,  0xFE,  0x00,  0x02,  0xFC,  0x48,  0x44, 	/* 0F1E0 */
+	0x84,  0x88,  0x48,  0xFC,  0xAA,  0x42,  0x02,  0x20,  0x0F,  0xC8,  0x84,  0x4F,  0xC0,  0x84,  0x0F,  0xC2, 	/* 0F1F0 */
+	0xA2,  0x49,  0x44,  0x88,  0x8E,  0x49,  0x82,  0xAC,  0x40,  0x03,  0xFC,  0x12,  0x49,  0xFC,  0x52,  0x41, 	/* 0F200 */
+	0x24,  0x1F,  0xC2,  0x20,  0x5F,  0xC4,  0x20,  0x82,  0x0B,  0xFE,  0xAE,  0x40,  0xC2,  0xF0,  0x12,  0x48, 	/* 0F210 */
+	0xA4,  0x48,  0x81,  0xFC,  0x01,  0x82,  0x20,  0x5F,  0xE4,  0x20,  0x82,  0x08,  0x60,  0xB4,  0x48,  0x82, 	/* 0F220 */
+	0xA8,  0x12,  0x48,  0x50,  0x45,  0x00,  0x88,  0x10,  0x42,  0xFA,  0x48,  0x84,  0x88,  0x88,  0x88,  0xF8, 	/* 0F230 */
+	0xB7,  0x44,  0x02,  0x7E,  0x04,  0x08,  0xFC,  0x55,  0x40,  0x54,  0x07,  0xE2,  0x94,  0x49,  0x44,  0xFE, 	/* 0F240 */
+	0x80,  0x48,  0x18,  0xB8,  0x4F,  0xC2,  0x04,  0x0F,  0xC8,  0x04,  0x5F,  0xF1,  0x01,  0x1F,  0xD2,  0x44, 	/* 0F250 */
+	0x42,  0x84,  0x10,  0x86,  0x89,  0x86,  0xB9,  0x42,  0x02,  0x20,  0x1F,  0xC8,  0x20,  0x4A,  0x80,  0xA8, 	/* 0F260 */
+	0x17,  0x42,  0x22,  0x45,  0x04,  0x48,  0x88,  0x49,  0x02,  0x85,  0x4F,  0xC2,  0x84,  0x0F,  0xC8,  0x84, 	/* 0F270 */
+	0x48,  0x40,  0xFC,  0x02,  0x02,  0x20,  0x5F,  0xC4,  0x20,  0x82,  0x0B,  0xFE,  0x88,  0x42,  0x03,  0x24, 	/* 0F280 */
+	0x0A,  0x48,  0xA8,  0x4F,  0xC0,  0x84,  0x0F,  0xC2,  0x84,  0x4F,  0xC4,  0x84,  0x88,  0x48,  0x8C,  0x8C, 	/* 0F290 */
+	0x40,  0x02,  0xFE,  0x02,  0xC8,  0x10,  0x4F,  0xE0,  0x92,  0x0F,  0xE2,  0x92,  0x4F,  0xE4,  0x92,  0x89, 	/* 0F2A0 */
+	0x28,  0x96,  0x8E,  0x80,  0x65,  0xDC,  0x04,  0x40,  0x84,  0x91,  0x45,  0xD6,  0x05,  0x41,  0x54,  0x4D, 	/* 0F2B0 */
+	0x44,  0xDE,  0x93,  0x0A,  0x0F,  0x93,  0x4F,  0xE2,  0x82,  0x0F,  0xE8,  0x00,  0x4F,  0xE0,  0x82,  0x0F, 	/* 0F2C0 */
+	0xE2,  0x82,  0x4F,  0xE4,  0x82,  0x88,  0x28,  0x86,  0x95,  0x48,  0x82,  0x50,  0x1F,  0xC8,  0x24,  0x4F, 	/* 0F2D0 */
+	0xC1,  0x20,  0x1F,  0xE2,  0x22,  0x46,  0x24,  0xA2,  0x92,  0xC8,  0x20,  0x99,  0x40,  0x03,  0xFE,  0x00, 	/* 0F2E0 */
+	0x01,  0xFC,  0x90,  0x45,  0xFC,  0x11,  0x03,  0xFE,  0x51,  0x05,  0x28,  0xA4,  0x49,  0x82,  0x9B,  0x42, 	/* 0F2F0 */
+	0x02,  0xFE,  0x02,  0x08,  0xFC,  0x42,  0x01,  0xFE,  0x04,  0x83,  0xFE,  0x48,  0x85,  0x48,  0xA0,  0x88, 	/* 0F300 */
+	0x18,  0x9C,  0x41,  0x02,  0xFE,  0x01,  0x08,  0x7C,  0x40,  0x00,  0xFE,  0x08,  0x22,  0xAA,  0x42,  0x84, 	/* 0F310 */
+	0x2A,  0x84,  0xA9,  0x86,  0xAF,  0x40,  0x03,  0xFE,  0x11,  0x09,  0x7C,  0x51,  0x01,  0xFE,  0x11,  0x03, 	/* 0F320 */
+	0x10,  0x57,  0xC5,  0x10,  0x91,  0x0A,  0xFE,  0xB2,  0x41,  0x02,  0xFE,  0x05,  0x08,  0x5E,  0x49,  0x20, 	/* 0F330 */
+	0x9A,  0x1A,  0x46,  0xB4,  0x4C,  0x84,  0x94,  0x8A,  0x28,  0xC2,  0xB5,  0x40,  0x03,  0xFE,  0x02,  0x09, 	/* 0F340 */
+	0x32,  0x55,  0x61,  0xDA,  0x13,  0x23,  0x5A,  0x59,  0x65,  0x62,  0x90,  0x29,  0xFE,  0xB8,  0x80,  0x05, 	/* 0F350 */
+	0xFE,  0x12,  0x29,  0xFE,  0x52,  0x21,  0x22,  0x17,  0xA3,  0x4A,  0x54,  0xA5,  0x7A,  0x90,  0x29,  0xFE, 	/* 0F360 */
+	0xBC,  0x82,  0x05,  0xFE,  0x00,  0x00,  0xFC,  0x88,  0x44,  0x84,  0x0F,  0xC2,  0x20,  0x4A,  0x84,  0xA4, 	/* 0F370 */
+	0x92,  0x48,  0x60,  0x80,  0x42,  0x03,  0xFE,  0x10,  0x29,  0x02,  0x5F,  0xC0,  0x20,  0x0A,  0x02,  0xBC, 	/* 0F380 */
+	0x4A,  0x04,  0xA0,  0x96,  0x0A,  0x1E,  0x85,  0x48,  0x22,  0x9C,  0x09,  0x0B,  0xF0,  0x49,  0xE0,  0xD4, 	/* 0F390 */
+	0x1B,  0x45,  0x94,  0x69,  0x44,  0xA4,  0x8C,  0x48,  0x84,  0x86,  0x4C,  0xC2,  0x30,  0x0C,  0x8B,  0xFE, 	/* 0F3A0 */
+	0x44,  0x00,  0xFC,  0x18,  0x45,  0xFC,  0x68,  0x44,  0xFC,  0x88,  0x48,  0x8C,  0x87,  0x48,  0x82,  0x88, 	/* 0F3B0 */
+	0x1F,  0xC8,  0x88,  0x4F,  0x80,  0x88,  0x0F,  0x82,  0x88,  0x5F,  0xE4,  0x08,  0x8C,  0x49,  0x04,  0x8B, 	/* 0F3C0 */
+	0x88,  0x84,  0x88,  0x3F,  0xE8,  0x88,  0x5D,  0xC1,  0xDC,  0x1B,  0xA6,  0xAA,  0x6A,  0x84,  0x88,  0x88, 	/* 0F3D0 */
+	0x88,  0x88,  0x8C,  0x42,  0x02,  0xA8,  0x0A,  0x49,  0x22,  0x5F,  0xE1,  0x02,  0x17,  0xA3,  0x4A,  0x54, 	/* 0F3E0 */
+	0xA5,  0x7A,  0x90,  0x29,  0x06,  0x91,  0x48,  0x02,  0x80,  0x0F,  0xE8,  0x92,  0x49,  0x43,  0xF4,  0x08, 	/* 0F3F0 */
+	0xC5,  0xC8,  0x5A,  0x8A,  0x94,  0xAA,  0x48,  0xC2,  0x92,  0x82,  0x05,  0xFE,  0x02,  0x00,  0xFC,  0x82, 	/* 0F400 */
+	0x45,  0xFE,  0x02,  0x43,  0xFE,  0x44,  0x84,  0xC8,  0x87,  0x09,  0x8E,  0x95,  0x42,  0x02,  0xFC,  0x02, 	/* 0F410 */
+	0x0B,  0xFE,  0x44,  0x80,  0x48,  0x18,  0xE2,  0x20,  0x5F,  0xC4,  0x20,  0x82,  0x09,  0xFE,  0x98,  0x48, 	/* 0F420 */
+	0x02,  0x80,  0x0F,  0xE9,  0x42,  0x67,  0xA0,  0xA2,  0x1F,  0xA2,  0x22,  0x4A,  0xA4,  0xAA,  0x8F,  0xA8, 	/* 0F430 */
+	0x0C,  0x99,  0x42,  0x03,  0xFE,  0x10,  0x29,  0xFA,  0x40,  0x00,  0x00,  0x1F,  0xE2,  0x20,  0x4A,  0x84, 	/* 0F440 */
+	0xA4,  0x92,  0x48,  0x60,  0x9E,  0x44,  0x42,  0x54,  0x05,  0x49,  0xF2,  0x45,  0x20,  0xE9,  0x0E,  0x82, 	/* 0F450 */
+	0xC8,  0x54,  0xC5,  0x52,  0x85,  0xE8,  0x72,  0xA1,  0x42,  0x42,  0xA8,  0x0A,  0x09,  0x30,  0x44,  0x81, 	/* 0F460 */
+	0x86,  0x02,  0x42,  0xA8,  0x4A,  0x05,  0x30,  0x84,  0x89,  0x86,  0xA4,  0x48,  0x42,  0x84,  0x3F,  0x40, 	/* 0F470 */
+	0x8A,  0x88,  0xA4,  0xF1,  0x0A,  0x42,  0xA2,  0x52,  0x85,  0x24,  0xA2,  0x28,  0xC2,  0xA6,  0x42,  0x02, 	/* 0F480 */
+	0x20,  0x05,  0x08,  0x88,  0x5F,  0xC2,  0x22,  0x02,  0x03,  0xFC,  0x42,  0x04,  0xA4,  0x86,  0x8B,  0xFE, 	/* 0F490 */
+	0xA8,  0x81,  0xC5,  0xE8,  0x0A,  0x41,  0x12,  0x9F,  0xC4,  0x24,  0x3F,  0xE0,  0x24,  0x5F,  0xC4,  0x20, 	/* 0F4A0 */
+	0x82,  0x08,  0x60,  0xAA,  0x41,  0x02,  0x10,  0x02,  0x88,  0x44,  0x4F,  0xE1,  0x01,  0x0F,  0xE2,  0xAA, 	/* 0F4B0 */
+	0x4F,  0xE4,  0xAA,  0x8A,  0xA8,  0x86,  0xAB,  0x40,  0xE2,  0xF0,  0x12,  0x48,  0xA4,  0x48,  0x82,  0xFE, 	/* 0F4C0 */
+	0x02,  0x02,  0x20,  0x4F,  0xC4,  0x20,  0x82,  0x09,  0xFE,  0xAC,  0x41,  0x02,  0xFE,  0x04,  0x48,  0x44, 	/* 0F4D0 */
+	0x4A,  0xA1,  0x11,  0x01,  0x02,  0xFE,  0x41,  0x04,  0x10,  0x81,  0x08,  0x10,  0xAE,  0x44,  0x82,  0x50, 	/* 0F4E0 */
+	0x0F,  0xE9,  0x90,  0x69,  0x00,  0xFC,  0x09,  0x02,  0x90,  0x4F,  0xC4,  0x90,  0x89,  0x08,  0xFE,  0xB1, 	/* 0F4F0 */
+	0x40,  0x03,  0xFE,  0x15,  0x29,  0x52,  0x49,  0x01,  0x2E,  0x02,  0x02,  0xFE,  0x46,  0x84,  0xA4,  0x92, 	/* 0F500 */
+	0x28,  0x20,  0xB3,  0x41,  0x03,  0xFE,  0x0F,  0xC8,  0x84,  0x4F,  0xC0,  0x00,  0x0F,  0xC2,  0x08,  0x5F, 	/* 0F510 */
+	0xE4,  0x10,  0x81,  0x08,  0x30,  0xB5,  0x4A,  0xA2,  0xAA,  0x0A,  0xA8,  0xEE,  0x48,  0x20,  0xFE,  0x08, 	/* 0F520 */
+	0x22,  0xEE,  0x4A,  0xA5,  0x2A,  0x92,  0xAA,  0x02,  0xB7,  0x40,  0x02,  0xFC,  0x08,  0x48,  0xFC,  0x48, 	/* 0F530 */
+	0x40,  0xFC,  0x09,  0x02,  0xF2,  0x49,  0xC4,  0x90,  0x8F,  0x29,  0x8E,  0xB9,  0x42,  0x02,  0x20,  0x1F, 	/* 0F540 */
+	0xE8,  0xA8,  0x52,  0x42,  0xFA,  0x0A,  0x82,  0xF8,  0x4A,  0x84,  0xF8,  0x82,  0x28,  0x1E,  0xBA,  0x42, 	/* 0F550 */
+	0x83,  0xFE,  0x02,  0x88,  0x10,  0x46,  0xA1,  0x86,  0x02,  0x43,  0xFE,  0x42,  0x84,  0x10,  0x86,  0xA9, 	/* 0F560 */
+	0x86,  0xBB,  0x40,  0xC2,  0xF0,  0x02,  0x09,  0xFE,  0x43,  0x00,  0x48,  0x0A,  0x43,  0x22,  0x4B,  0x44, 	/* 0F570 */
+	0xAA,  0x92,  0xA8,  0x60,  0x85,  0x42,  0x03,  0xFC,  0x02,  0x08,  0xF8,  0x42,  0x03,  0xFE,  0x08,  0x82, 	/* 0F580 */
+	0xF8,  0x48,  0x84,  0xF8,  0x88,  0x88,  0x98,  0x87,  0x4F,  0xC2,  0x84,  0x0F,  0xC8,  0x84,  0x4F,  0xC0, 	/* 0F590 */
+	0x40,  0x0F,  0xE3,  0x4A,  0x47,  0x24,  0x4A,  0x83,  0xA8,  0x0C,  0x88,  0x42,  0x03,  0xFE,  0x08,  0x88, 	/* 0F5A0 */
+	0x70,  0x4D,  0x83,  0x8E,  0x0F,  0x82,  0x88,  0x4F,  0x84,  0x88,  0x90,  0x8A,  0x08,  0x89,  0x42,  0x02, 	/* 0F5B0 */
+	0xA0,  0x0B,  0xC8,  0xA0,  0x5F,  0xE0,  0x28,  0x0A,  0x42,  0xAA,  0x56,  0xA4,  0x10,  0x86,  0x09,  0x80, 	/* 0F5C0 */
+	0x8A,  0x49,  0x22,  0x92,  0x0D,  0x68,  0xBA,  0x49,  0x20,  0xFE,  0x09,  0x22,  0xBA,  0x4B,  0xA4,  0xD6, 	/* 0F5D0 */
+	0x95,  0x29,  0x12,  0x8B,  0x41,  0x02,  0x50,  0x05,  0xC8,  0x50,  0x45,  0x01,  0xFE,  0x00,  0x02,  0x86, 	/* 0F5E0 */
+	0x46,  0x84,  0x00,  0x86,  0xC9,  0x82,  0x93,  0x43,  0xC3,  0xC4,  0x12,  0x48,  0xA8,  0x4A,  0x80,  0xFC, 	/* 0F5F0 */
+	0x02,  0x03,  0xFE,  0x42,  0x04,  0x30,  0x84,  0x89,  0x86,  0x95,  0x52,  0x22,  0xAA,  0x04,  0xA9,  0xFA, 	/* 0F600 */
+	0x44,  0xA0,  0x4A,  0x1F,  0xA2,  0x4A,  0x46,  0xA4,  0x92,  0x90,  0x2A,  0x06,  0x99,  0x43,  0xC2,  0x44, 	/* 0F610 */
+	0x08,  0x88,  0xFE,  0x4A,  0xA0,  0xAA,  0x0C,  0xE2,  0x92,  0x5F,  0xF4,  0x28,  0x84,  0x48,  0x83,  0x9A, 	/* 0F620 */
+	0x41,  0x02,  0xFE,  0x01,  0x28,  0x14,  0x5F,  0xF0,  0x30,  0x07,  0xC2,  0xC4,  0x57,  0xC4,  0x44,  0x84, 	/* 0F630 */
+	0x48,  0x7C,  0x9B,  0x40,  0xC2,  0x0A,  0x1F,  0xE1,  0x08,  0x9E,  0xA5,  0x0A,  0x1E,  0xC3,  0xA8,  0x5A, 	/* 0F640 */
+	0xC5,  0xF5,  0x92,  0x3A,  0x41,  0x9D,  0x43,  0x02,  0x10,  0x02,  0x88,  0x7C,  0x48,  0x21,  0xEB,  0x0A, 	/* 0F650 */
+	0xA2,  0xEA,  0x4B,  0x44,  0xEA,  0x8A,  0xA8,  0xAA,  0x9F,  0x41,  0x03,  0xFE,  0x00,  0x08,  0xFC,  0x48, 	/* 0F660 */
+	0x41,  0xFE,  0x10,  0x22,  0xFC,  0x41,  0x04,  0x10,  0x81,  0x08,  0x30,  0xA0,  0x4F,  0xE2,  0x80,  0x8F, 	/* 0F670 */
+	0xC4,  0x84,  0x0F,  0xC2,  0x80,  0x4F,  0xE8,  0x40,  0xFF,  0xE0,  0xE0,  0x35,  0x8C,  0x46,  0xA1,  0x41, 	/* 0F680 */
+	0x03,  0xFE,  0x14,  0x89,  0xFE,  0x54,  0x81,  0x78,  0x10,  0x03,  0xFC,  0x54,  0x85,  0x30,  0xA5,  0x8D, 	/* 0F690 */
+	0x86,  0xA3,  0x82,  0x04,  0x20,  0x3F,  0xE0,  0x70,  0x8A,  0x85,  0xFC,  0x28,  0xA2,  0xF8,  0x48,  0x84, 	/* 0F6A0 */
+	0xF8,  0x88,  0x8B,  0xFE,  0xA4,  0x88,  0x87,  0xF8,  0x08,  0x83,  0xFE,  0xA2,  0xA5,  0xCA,  0x04,  0xA2, 	/* 0F6B0 */
+	0x8A,  0x7E,  0xA4,  0x92,  0x89,  0x29,  0xAC,  0xA5,  0x80,  0x05,  0xFC,  0x10,  0x49,  0xFC,  0x50,  0x01, 	/* 0F6C0 */
+	0xFE,  0x12,  0xC3,  0x7A,  0x51,  0x05,  0x7C,  0x91,  0x0A,  0xFE,  0xA6,  0x40,  0x02,  0xFC,  0x08,  0x48, 	/* 0F6D0 */
+	0xBC,  0x4A,  0x41,  0xFE,  0x10,  0x23,  0x7A,  0x54,  0xA5,  0x7A,  0x90,  0x29,  0x06,  0xA9,  0x40,  0x02, 	/* 0F6E0 */
+	0xF8,  0x08,  0x88,  0xF8,  0x48,  0x80,  0xF8,  0x00,  0x03,  0xFC,  0x55,  0x45,  0x54,  0x95,  0x4B,  0xFE, 	/* 0F6F0 */
+	0xAB,  0x4A,  0x82,  0xA8,  0x3F,  0xE8,  0xA8,  0x4B,  0x80,  0x80,  0x0F,  0xC2,  0x20,  0x7F,  0xE4,  0xF8, 	/* 0F700 */
+	0xB2,  0x68,  0x20,  0xAC,  0x80,  0x25,  0xEA,  0x12,  0xA9,  0x2A,  0x5E,  0xA1,  0x2A,  0x1E,  0xA3,  0x2A, 	/* 0F710 */
+	0x5E,  0xA4,  0xC2,  0x92,  0x2A,  0x06,  0xAD,  0x4F,  0xE2,  0x92,  0x0F,  0xE8,  0x92,  0x49,  0x20,  0xFE, 	/* 0F720 */
+	0x04,  0x42,  0x7C,  0x44,  0x44,  0x7C,  0x84,  0x48,  0x4C,  0xAE,  0x44,  0x83,  0xFE,  0x04,  0x88,  0x00, 	/* 0F730 */
+	0x5F,  0xE0,  0x04,  0x0F,  0x42,  0x94,  0x49,  0x44,  0xF4,  0x80,  0x48,  0x0C,  0xAF,  0x89,  0x04,  0x90, 	/* 0F740 */
+	0x1F,  0xC8,  0x90,  0x7F,  0xE0,  0x50,  0x08,  0x85,  0xF6,  0x61,  0x08,  0xF0,  0x88,  0x48,  0x7C,  0xB8, 	/* 0F750 */
+	0x48,  0x82,  0x88,  0x3F,  0xE0,  0x90,  0x8B,  0xE4,  0xE4,  0x0A,  0x82,  0xBE,  0x4A,  0x85,  0x28,  0x92, 	/* 0F760 */
+	0x8A,  0xD8,  0xBA,  0x40,  0x83,  0xC8,  0x14,  0xC9,  0x5A,  0x5D,  0xA1,  0x69,  0x1C,  0x93,  0x5A,  0x54, 	/* 0F770 */
+	0x45,  0xC8,  0x83,  0x08,  0xC0,  0xBE,  0x80,  0x07,  0xFE,  0x22,  0x21,  0xFC,  0x82,  0x05,  0xFC,  0x12, 	/* 0F780 */
+	0x45,  0xFC,  0x42,  0x07,  0xFE,  0x82,  0x08,  0x20,  0x83,  0x87,  0xE7,  0x88,  0x08,  0x80,  0xBE,  0xBC, 	/* 0F790 */
+	0x84,  0xBE,  0x0C,  0x83,  0x88,  0x4B,  0xE4,  0x88,  0x90,  0x8A,  0x08,  0x8A,  0x41,  0x02,  0xFE,  0x01, 	/* 0F7A0 */
+	0x08,  0xFE,  0x42,  0x81,  0xFF,  0x04,  0x42,  0xFE,  0x51,  0x14,  0xFE,  0x82,  0x88,  0xC6,  0x8D,  0x41, 	/* 0F7B0 */
+	0x02,  0x92,  0x09,  0x28,  0xFE,  0x40,  0x00,  0xFE,  0x06,  0x02,  0xFE,  0x4A,  0xA4,  0xAA,  0x8A,  0xA8, 	/* 0F7C0 */
+	0x86,  0x8E,  0x40,  0x03,  0xFE,  0x02,  0x08,  0x40,  0x5F,  0xE1,  0x4A,  0x17,  0xA3,  0x4A,  0x57,  0xA5, 	/* 0F7D0 */
+	0x4A,  0x94,  0xA9,  0xFE,  0x96,  0x88,  0x04,  0x9E,  0x09,  0x23,  0xF2,  0x89,  0xE4,  0x92,  0x1F,  0x23, 	/* 0F7E0 */
+	0x3E,  0x53,  0x25,  0xF2,  0x82,  0x28,  0x46,  0x98,  0x48,  0x02,  0x9E,  0x09,  0x2B,  0xF2,  0x49,  0xE0, 	/* 0F7F0 */
+	0x92,  0x1D,  0x25,  0xBE,  0x69,  0x2A,  0x92,  0x89,  0x28,  0x9E,  0x9B,  0x48,  0x83,  0xFC,  0x08,  0x88, 	/* 0F800 */
+	0xF8,  0x48,  0x80,  0xF8,  0x08,  0x83,  0xFE,  0x55,  0x05,  0x8C,  0x90,  0x08,  0xFE,  0x9F,  0x44,  0x02, 	/* 0F810 */
+	0xFC,  0x08,  0x48,  0xFC,  0x48,  0x40,  0xFC,  0x00,  0x03,  0xFE,  0x42,  0x04,  0xFC,  0x82,  0x0B,  0xFE, 	/* 0F820 */
+	0xA7,  0x4F,  0xC2,  0x28,  0x0F,  0xC8,  0xA4,  0x4F,  0xC0,  0xA4,  0x0F,  0xC2,  0x10,  0x5F,  0xE4,  0x22, 	/* 0F830 */
+	0x84,  0x29,  0x8C,  0xAB,  0x84,  0x87,  0x88,  0x08,  0xA0,  0x9A,  0xBF,  0xA4,  0xAC,  0x1C,  0x81,  0xA8, 	/* 0F840 */
+	0x68,  0xC4,  0x94,  0x8A,  0x28,  0xC1,  0xAE,  0x40,  0x03,  0xFF,  0x02,  0x88,  0xFE,  0x4A,  0xA0,  0xAA, 	/* 0F850 */
+	0x0F,  0xE2,  0x10,  0x4F,  0xE4,  0x10,  0x81,  0x09,  0xFF,  0xAF,  0x40,  0x02,  0x7C,  0x04,  0x48,  0x7C, 	/* 0F860 */
+	0x44,  0x41,  0xFF,  0x04,  0x02,  0xFE,  0x52,  0xA4,  0xD2,  0x82,  0x28,  0xCC,  0xB2,  0x41,  0xC2,  0xE8, 	/* 0F870 */
+	0x0A,  0x49,  0x12,  0x5F,  0xA0,  0x40,  0x1F,  0xE2,  0x40,  0x4F,  0xC4,  0xA4,  0x91,  0x8A,  0x66,  0xB6, 	/* 0F880 */
+	0x41,  0x02,  0xFC,  0x08,  0x48,  0xFC,  0x48,  0x40,  0xFC,  0x01,  0x22,  0xFC,  0x43,  0x84,  0x54,  0x99, 	/* 0F890 */
+	0x28,  0x30,  0xBE,  0x82,  0x07,  0xFE,  0x15,  0x41,  0x52,  0xA5,  0x24,  0xFC,  0x00,  0x42,  0xFC,  0x48, 	/* 0F8A0 */
+	0x05,  0xFE,  0x90,  0x28,  0x1C,  0xBF,  0x40,  0x02,  0xFE,  0x08,  0x28,  0xFE,  0x48,  0x20,  0xFE,  0x02, 	/* 0F8B0 */
+	0x82,  0x2A,  0x4A,  0xA4,  0x6C,  0x82,  0x89,  0xFF,  0x80,  0x89,  0x05,  0xFC,  0x09,  0x03,  0xFE,  0x82, 	/* 0F8C0 */
+	0x07,  0xFE,  0x22,  0x22,  0xAA,  0x6A,  0xA6,  0xFA,  0xA8,  0x2A,  0x06,  0x82,  0x88,  0x27,  0xFA,  0x08, 	/* 0F8D0 */
+	0xA3,  0xEA,  0xAA,  0xA6,  0xAA,  0x3E,  0xA0,  0x8A,  0x5C,  0xA5,  0xA2,  0xA8,  0x28,  0x86,  0x8C,  0x4E, 	/* 0F8E0 */
+	0x82,  0x30,  0x0D,  0x48,  0x48,  0x4F,  0xC1,  0x4A,  0x24,  0x81,  0xFE,  0x44,  0x84,  0x48,  0x88,  0xAB, 	/* 0F8F0 */
+	0x06,  0x8F,  0x41,  0x03,  0xFE,  0x11,  0x01,  0x7E,  0x91,  0x25,  0xFF,  0x11,  0x23,  0x7E,  0x51,  0x05, 	/* 0F900 */
+	0x7E,  0x94,  0x2A,  0x7E,  0x90,  0x40,  0x03,  0xFE,  0x11,  0x09,  0x7C,  0x54,  0x41,  0x7C,  0x14,  0x43, 	/* 0F910 */
+	0x7C,  0x51,  0x45,  0x52,  0xA9,  0x2C,  0x30,  0x96,  0x44,  0x82,  0x50,  0x8F,  0xE5,  0x90,  0x0F,  0xC2, 	/* 0F920 */
+	0x90,  0x4F,  0xE8,  0x40,  0xFF,  0xE0,  0x40,  0x04,  0x00,  0x40,  0x98,  0x42,  0x02,  0xF8,  0x02,  0x09, 	/* 0F930 */
+	0xFE,  0x45,  0x00,  0x88,  0x1F,  0xC2,  0x04,  0x5F,  0xC5,  0x54,  0x95,  0x4B,  0xFE,  0x9C,  0x84,  0x05, 	/* 0F940 */
+	0x9E,  0x14,  0xA9,  0x2A,  0x56,  0xA1,  0xB6,  0x00,  0x03,  0xFC,  0x52,  0x45,  0xFC,  0x92,  0x49,  0xFC, 	/* 0F950 */
+	0x9D,  0x45,  0x02,  0xFC,  0x05,  0x08,  0xFC,  0x45,  0x01,  0xFE,  0x0A,  0x42,  0xFC,  0x4A,  0x45,  0xFE, 	/* 0F960 */
+	0x88,  0x48,  0x8C,  0x9F,  0x40,  0x03,  0xFE,  0x10,  0x28,  0xFC,  0x48,  0x40,  0xFC,  0x08,  0x42,  0xFC, 	/* 0F970 */
+	0x42,  0x05,  0xFE,  0x88,  0x89,  0x04,  0xA2,  0x48,  0x82,  0x48,  0x05,  0x0B,  0xFE,  0x48,  0x80,  0x88, 	/* 0F980 */
+	0x10,  0x43,  0xFE,  0x55,  0x45,  0x54,  0x95,  0x4B,  0xFE,  0xA5,  0x42,  0x83,  0xFE,  0x12,  0x41,  0xFC, 	/* 0F990 */
+	0x92,  0x45,  0xFC,  0x12,  0x40,  0x08,  0x7F,  0xE4,  0x88,  0x84,  0x88,  0x18,  0xAA,  0x40,  0xC2,  0xF4, 	/* 0F9A0 */
+	0x09,  0x29,  0x22,  0x42,  0x80,  0xD0,  0x02,  0x42,  0xFA,  0x41,  0x04,  0xFE,  0x84,  0x89,  0x86,  0xAF, 	/* 0F9B0 */
+	0x91,  0x04,  0x9E,  0x06,  0xA1,  0xFA,  0x84,  0xE5,  0x5A,  0x15,  0xA1,  0xFE,  0x54,  0xA4,  0x4A,  0x89, 	/* 0F9C0 */
+	0x29,  0x26,  0xB2,  0x46,  0x03,  0xAC,  0x12,  0x49,  0xAC,  0x52,  0x41,  0xAC,  0x02,  0x03,  0xFE,  0x48, 	/* 0F9D0 */
+	0x84,  0x50,  0x87,  0x0B,  0x8E,  0xB6,  0x42,  0x03,  0xFE,  0x10,  0x29,  0xAA,  0x4A,  0x41,  0x54,  0x08, 	/* 0F9E0 */
+	0x83,  0x04,  0x4F,  0xA4,  0x88,  0x88,  0x88,  0xF8,  0xB7,  0x40,  0x03,  0xFE,  0x10,  0x29,  0xFE,  0x52, 	/* 0F9F0 */
+	0x21,  0xD6,  0x13,  0xA3,  0xD2,  0x53,  0xA5,  0xD6,  0x92,  0x29,  0xFE,  0xBA,  0x80,  0x05,  0xDE,  0x04, 	/* 0FA00 */
+	0x21,  0xCE,  0x91,  0x05,  0xDE,  0x04,  0x23,  0x5A,  0x4C,  0x65,  0x5A,  0x84,  0x29,  0x8C,  0xBD,  0x5F, 	/* 0FA10 */
+	0xE3,  0x00,  0x1F,  0xE9,  0x52,  0x54,  0xC1,  0x74,  0x2C,  0x20,  0x08,  0x5F,  0xE4,  0x88,  0x84,  0x88, 	/* 0FA20 */
+	0x18,  0x82,  0x42,  0x03,  0xFE,  0x08,  0x88,  0x50,  0x7F,  0xE2,  0x22,  0x1F,  0xC2,  0x20,  0x43,  0xC4, 	/* 0FA30 */
+	0x44,  0x88,  0x4B,  0x18,  0x84,  0x41,  0x02,  0x28,  0x04,  0x48,  0xBA,  0x58,  0x50,  0xFC,  0x08,  0x42, 	/* 0FA40 */
+	0xFC,  0x48,  0x05,  0x7E,  0xA4,  0x28,  0x7E,  0x85,  0x40,  0xA2,  0x09,  0x1F,  0xF1,  0x08,  0x9F,  0xA5, 	/* 0FA50 */
+	0x2A,  0x1B,  0xA3,  0x6C,  0x52,  0x45,  0x5D,  0x99,  0x3A,  0x21,  0x89,  0x4F,  0xC2,  0x84,  0x0F,  0xC8, 	/* 0FA60 */
+	0x84,  0x4F,  0xC1,  0x24,  0x0A,  0x83,  0xFE,  0x45,  0x04,  0x52,  0x89,  0x2B,  0x0E,  0x8B,  0x48,  0x42, 	/* 0FA70 */
+	0x48,  0x1F,  0xE8,  0x88,  0x4A,  0xA1,  0x32,  0x35,  0x40,  0xCC,  0x48,  0x85,  0x54,  0xBF,  0xE8,  0x22, 	/* 0FA80 */
+	0x8C,  0x49,  0x02,  0x9E,  0x0A,  0x49,  0x58,  0x51,  0x43,  0x62,  0x14,  0x95,  0x7E,  0x54,  0x89,  0x5C, 	/* 0FA90 */
+	0x92,  0xA9,  0x08,  0x91,  0x47,  0xC2,  0x44,  0x05,  0xC8,  0x54,  0x5F,  0xF1,  0x45,  0x17,  0xD2,  0x44, 	/* 0FAA0 */
+	0x47,  0xC4,  0x44,  0x84,  0x48,  0x4C,  0x93,  0x82,  0x07,  0xFE,  0x20,  0x20,  0x20,  0x9F,  0xC4,  0x88, 	/* 0FAB0 */
+	0x05,  0x03,  0xFE,  0x42,  0x05,  0xFC,  0x82,  0x08,  0x20,  0x94,  0x41,  0xE2,  0xE4,  0x09,  0x29,  0x12, 	/* 0FAC0 */
+	0x40,  0x00,  0x20,  0x0C,  0xC2,  0x84,  0x4E,  0xC4,  0x84,  0x88,  0x48,  0xFC,  0x95,  0x01,  0x07,  0x54, 	/* 0FAD0 */
+	0x5F,  0xE5,  0x10,  0x7F,  0xE5,  0x28,  0x55,  0x47,  0x92,  0x55,  0x55,  0x78,  0x59,  0x6B,  0x10,  0x9D, 	/* 0FAE0 */
+	0x42,  0x02,  0x20,  0x1F,  0xC8,  0x88,  0x45,  0x03,  0xFE,  0x12,  0x81,  0xF8,  0x52,  0x85,  0xFA,  0x82, 	/* 0FAF0 */
+	0x28,  0x1E,  0x9E,  0x4A,  0x83,  0xFE,  0x0A,  0x88,  0xF8,  0x40,  0x01,  0xFE,  0x12,  0x23,  0xFE,  0x4A, 	/* 0FB00 */
+	0x44,  0xA4,  0x8B,  0x88,  0x20,  0xAC,  0x40,  0x02,  0xFE,  0x00,  0x01,  0xFE,  0x90,  0x25,  0xFE,  0x17, 	/* 0FB10 */
+	0xE3,  0x52,  0x57,  0xE5,  0x40,  0x94,  0x2A,  0x3E,  0xAF,  0x95,  0x45,  0x54,  0x3F,  0xE1,  0x54,  0xA7, 	/* 0FB20 */
+	0x64,  0x00,  0x1F,  0xE3,  0x22,  0x5F,  0xE4,  0xA4,  0x8A,  0xC8,  0x20,  0xB2,  0x42,  0x02,  0x48,  0x0F, 	/* 0FB30 */
+	0x48,  0x44,  0x4A,  0xA1,  0xFF,  0x04,  0xC2,  0xB3,  0x5D,  0x84,  0x66,  0x81,  0x88,  0xE0,  0xB4,  0x41, 	/* 0FB40 */
+	0x02,  0xFE,  0x04,  0x48,  0x28,  0x4F,  0xE0,  0x92,  0x0F,  0xE2,  0x92,  0x4B,  0xA4,  0xAA,  0x8B,  0xA8, 	/* 0FB50 */
+	0x86,  0xB7,  0x42,  0x02,  0x3E,  0x02,  0x01,  0xFE,  0x92,  0x25,  0x8A,  0x15,  0x23,  0xA6,  0x55,  0x25, 	/* 0FB60 */
+	0x8A,  0x92,  0x29,  0xFE,  0xB8,  0x99,  0x04,  0x10,  0x3F,  0xE0,  0x28,  0xBA,  0x84,  0x08,  0x3B,  0xE4, 	/* 0FB70 */
+	0x08,  0x7C,  0x8A,  0x48,  0xA4,  0x8B,  0xC8,  0xBE,  0x82,  0x07,  0xFE,  0x08,  0x81,  0x04,  0xBF,  0xA5, 	/* 0FB80 */
+	0x08,  0x1F,  0x80,  0x52,  0x49,  0x47,  0x88,  0x8B,  0x49,  0xC2,  0xBF,  0x44,  0x82,  0x48,  0x1F,  0xE8, 	/* 0FB90 */
+	0x48,  0x5F,  0xF0,  0x20,  0x1F,  0xE3,  0x22,  0x57,  0xA5,  0x6A,  0x9B,  0x69,  0x22,  0x81,  0x42,  0x02, 	/* 0FBA0 */
+	0x3C,  0x04,  0x89,  0x90,  0x4F,  0xE0,  0x92,  0x0F,  0xE2,  0x92,  0x4F,  0xE4,  0x00,  0x8A,  0xA9,  0x25, 	/* 0FBB0 */
+	0x82,  0x5F,  0xE2,  0x28,  0x0F,  0xE8,  0xAA,  0x4F,  0xE0,  0x00,  0x0F,  0xC2,  0x00,  0x5F,  0xE4,  0x54, 	/* 0FBC0 */
+	0x89,  0x28,  0x30,  0x86,  0x42,  0x03,  0xFE,  0x07,  0x09,  0xAE,  0x42,  0x00,  0x48,  0x1A,  0x62,  0x2C, 	/* 0FBD0 */
+	0x5F,  0x04,  0xA8,  0x92,  0x68,  0x60,  0x89,  0x41,  0x03,  0xFE,  0x12,  0x81,  0xFE,  0x92,  0xA5,  0xFE, 	/* 0FBE0 */
+	0x14,  0x83,  0x4A,  0x57,  0xC5,  0x48,  0xA7,  0x98,  0xC7,  0x8F,  0x9F,  0xC5,  0x04,  0x1F,  0xC9,  0x00, 	/* 0FBF0 */
+	0x5F,  0xE1,  0x10,  0x1F,  0xE3,  0x92,  0x5D,  0xA5,  0xB6,  0xAD,  0xA8,  0xB6,  0x91,  0x88,  0x04,  0x9E, 	/* 0FC00 */
+	0x3D,  0x42,  0x54,  0xBD,  0x46,  0x7E,  0x3C,  0x42,  0x0C,  0x7C,  0xC6,  0x14,  0xBD,  0x4A,  0x26,  0x93, 	/* 0FC10 */
+	0x42,  0x03,  0xFE,  0x15,  0x41,  0x24,  0x95,  0x45,  0xFC,  0x02,  0x01,  0xFE,  0x52,  0x25,  0x52,  0x9E, 	/* 0FC20 */
+	0xA9,  0x06,  0x94,  0x82,  0x07,  0xFE,  0x20,  0x21,  0xFC,  0x82,  0x05,  0xFC,  0x12,  0x43,  0xFC,  0x52, 	/* 0FC30 */
+	0x45,  0xFC,  0x88,  0x4B,  0x02,  0x95,  0x44,  0x83,  0xFE,  0x04,  0x89,  0xFE,  0x54,  0xA1,  0xFE,  0x14, 	/* 0FC40 */
+	0xA1,  0xFE,  0x48,  0x44,  0xFC,  0x88,  0x48,  0xFC,  0xA0,  0x44,  0x83,  0xFE,  0x04,  0x88,  0xFC,  0x48, 	/* 0FC50 */
+	0x40,  0xFC,  0x08,  0x42,  0xFC,  0x42,  0x05,  0xFE,  0x8D,  0x8B,  0x06,  0xA2,  0x89,  0x07,  0xFE,  0x09, 	/* 0FC60 */
+	0x01,  0xFC,  0x92,  0x45,  0xFC,  0x02,  0x03,  0xFC,  0x42,  0x05,  0xFC,  0x85,  0x8B,  0x86,  0xA3,  0x41, 	/* 0FC70 */
+	0x02,  0xFE,  0x01,  0x0A,  0x7C,  0x55,  0x40,  0x7C,  0x35,  0x41,  0x7C,  0x51,  0x05,  0x7E,  0xA9,  0x0A, 	/* 0FC80 */
+	0x7F,  0xAB,  0x4F,  0xC2,  0x84,  0x0F,  0xC8,  0x84,  0x5F,  0xE1,  0x4A,  0x1F,  0xE2,  0x00,  0x4F,  0xC4, 	/* 0FC90 */
+	0x48,  0x83,  0x09,  0xCE,  0xAC,  0x42,  0x02,  0xFC,  0x02,  0x08,  0xFC,  0x42,  0x03,  0xFE,  0x08,  0x82, 	/* 0FCA0 */
+	0xF8,  0x48,  0x84,  0xF8,  0x84,  0x89,  0x84,  0xB1,  0x88,  0x47,  0xE4,  0x08,  0x73,  0xED,  0xAB,  0x66, 	/* 0FCB0 */
+	0xA4,  0x3E,  0x40,  0xC4,  0x5A,  0xC5,  0x8A,  0xA9,  0x28,  0xA1,  0xB2,  0xBB,  0xC4,  0xA0,  0x0B,  0xC3, 	/* 0FCC0 */
+	0xA0,  0xA3,  0xC6,  0x20,  0x3F,  0xE0,  0xA2,  0x4B,  0x44,  0xA8,  0x8B,  0x4B,  0x62,  0xB8,  0x08,  0x2B, 	/* 0FCD0 */
+	0xE4,  0x49,  0x83,  0xF0,  0xAB,  0xE7,  0xF4,  0x2B,  0x43,  0xF4,  0x49,  0x47,  0xF4,  0x8A,  0x48,  0xC4, 	/* 0FCE0 */
+	0xBE,  0x44,  0x42,  0xFE,  0x01,  0x08,  0xFC,  0x41,  0x01,  0xFE,  0x03,  0x02,  0x12,  0x5F,  0xA4,  0x54, 	/* 0FCF0 */
+	0x99,  0x38,  0x30,  0xBF,  0x50,  0xC7,  0x72,  0x12,  0xCF,  0x70,  0x5F,  0xE5,  0x48,  0x91,  0x80,  0x4C, 	/* 0FD00 */
+	0xFF,  0x03,  0x58,  0xC4,  0x60,  0xC0,  0x81,  0x80,  0x08,  0xFF,  0xF1,  0x08,  0x3E,  0x7A,  0x22,  0x3E, 	/* 0FD10 */
+	0x2A,  0x2F,  0x3E,  0x32,  0x26,  0xBE,  0xA5,  0x22,  0x21,  0x85,  0x48,  0x02,  0xFC,  0x12,  0x0A,  0xFE, 	/* 0FD20 */
+	0x45,  0x00,  0xFE,  0x19,  0x02,  0xFC,  0x49,  0x04,  0xFC,  0x89,  0x08,  0xFE,  0x94,  0x49,  0xE3,  0xEA, 	/* 0FD30 */
+	0x08,  0xA3,  0xCA,  0x8F,  0x27,  0x24,  0x1D,  0x02,  0x64,  0x5F,  0xA4,  0xA8,  0xB2,  0x48,  0x20,  0x98, 	/* 0FD40 */
+	0x41,  0xC3,  0xE4,  0x0A,  0x89,  0xFE,  0x47,  0x00,  0xA8,  0x32,  0x63,  0xFC,  0x52,  0x45,  0xFC,  0x92, 	/* 0FD50 */
+	0x49,  0xFC,  0x9B,  0x44,  0x43,  0xDE,  0x15,  0x49,  0xFE,  0x4C,  0xC1,  0x54,  0x26,  0x60,  0xFC,  0x48, 	/* 0FD60 */
+	0x44,  0xFC,  0x88,  0x48,  0xFC,  0x9C,  0x88,  0x85,  0xDE,  0x08,  0x81,  0xDE,  0x8C,  0x85,  0x34,  0x20, 	/* 0FD70 */
+	0x20,  0xFC,  0x48,  0x44,  0xFC,  0x88,  0x48,  0xFC,  0x9F,  0x42,  0x02,  0xCC,  0x08,  0x40,  0xEC,  0x88, 	/* 0FD80 */
+	0x44,  0xFC,  0x04,  0x02,  0x7E,  0x48,  0x25,  0x52,  0x84,  0xA8,  0x0C,  0xA4,  0x5D,  0xE3,  0x52,  0x1D, 	/* 0FD90 */
+	0xE1,  0x52,  0x9D,  0xE5,  0x02,  0x17,  0xA1,  0x22,  0x57,  0xA5,  0x22,  0x97,  0xA9,  0x06,  0xA6,  0x82, 	/* 0FDA0 */
+	0x07,  0xFE,  0x25,  0x20,  0xF8,  0x98,  0xC6,  0xFA,  0x08,  0x80,  0xF8,  0x4A,  0x84,  0xA4,  0x92,  0x48, 	/* 0FDB0 */
+	0x60,  0xAD,  0x80,  0x07,  0xFE,  0x05,  0x03,  0xFE,  0xA5,  0x27,  0xFE,  0x1F,  0xC3,  0x04,  0x5F,  0xC4, 	/* 0FDC0 */
+	0x20,  0xBF,  0xE8,  0x20,  0xAE,  0x88,  0x07,  0xEE,  0x08,  0xAB,  0xEA,  0x62,  0xE3,  0xEA,  0x22,  0xA3, 	/* 0FDD0 */
+	0xEE,  0x48,  0xA7,  0xEA,  0x89,  0x28,  0xA6,  0xAF,  0x4F,  0x82,  0x08,  0x1F,  0xE8,  0x08,  0x5F,  0xC0, 	/* 0FDE0 */
+	0x94,  0x1D,  0xC2,  0x08,  0x5F,  0xE4,  0x88,  0x84,  0x88,  0x18,  0xB0,  0x42,  0x02,  0xFC,  0x0A,  0x4B, 	/* 0FDF0 */
+	0xFF,  0x40,  0x00,  0xFC,  0x08,  0x42,  0xFC,  0x48,  0x44,  0xFC,  0x84,  0xC9,  0x82,  0xB4,  0xA4,  0x85, 	/* 0FE00 */
+	0x48,  0x0B,  0xE1,  0x8A,  0xAF,  0xF4,  0xD4,  0x1B,  0xE2,  0xD2,  0x49,  0xE4,  0x92,  0x89,  0x2B,  0x1E, 	/* 0FE10 */
+	0xB8,  0x48,  0x83,  0xFE,  0x08,  0x82,  0xAA,  0xAA,  0xA4,  0xFC,  0x08,  0x42,  0xFC,  0x48,  0x44,  0xFC, 	/* 0FE20 */
+	0x88,  0x49,  0x0C,  0xBA,  0x40,  0x02,  0xFE,  0x08,  0x28,  0xFE,  0x49,  0xC0,  0xFE,  0x09,  0x02,  0xEE, 	/* 0FE30 */
+	0x54,  0x45,  0xEE,  0xA4,  0x48,  0xCC,  0xBC,  0x42,  0x02,  0xFC,  0x04,  0x8B,  0xFE,  0x4A,  0x40,  0xFC, 	/* 0FE40 */
+	0x0A,  0x42,  0xFC,  0x42,  0x05,  0xFC,  0x82,  0x0B,  0xFE,  0x80,  0x40,  0x03,  0xFE,  0x2B,  0xA9,  0xAA, 	/* 0FE50 */
+	0x53,  0x22,  0x66,  0x04,  0x42,  0x66,  0x55,  0x45,  0x54,  0x97,  0x49,  0xDE,  0x81,  0x42,  0x02,  0xA0, 	/* 0FE60 */
+	0x0B,  0xC8,  0xA0,  0x5F,  0xE0,  0x44,  0x14,  0x43,  0x76,  0x55,  0x45,  0x54,  0x9D,  0x4B,  0x3E,  0x82, 	/* 0FE70 */
+	0x88,  0x06,  0xA8,  0x2A,  0x83,  0xEF,  0x81,  0x27,  0xEA,  0x08,  0xA3,  0xE4,  0x48,  0x44,  0xEC,  0xB1, 	/* 0FE80 */
+	0x28,  0x61,  0x84,  0x47,  0x02,  0x16,  0x0E,  0x88,  0x2B,  0x47,  0x40,  0x82,  0x17,  0xD2,  0x44,  0x47, 	/* 0FE90 */
+	0xC4,  0x44,  0x82,  0x89,  0xFE,  0x86,  0x47,  0xC2,  0x10,  0x1F,  0xE8,  0x44,  0x4E,  0xE0,  0x44,  0x1F, 	/* 0FEA0 */
+	0xF2,  0x00,  0x4F,  0xE4,  0x28,  0x84,  0xA9,  0x86,  0x8E,  0x44,  0x43,  0xF4,  0x04,  0x89,  0xF2,  0x40, 	/* 0FEB0 */
+	0x21,  0xE4,  0x12,  0x83,  0xE2,  0x49,  0x24,  0xA4,  0x86,  0x89,  0x90,  0x91,  0xBF,  0xE4,  0x50,  0x1D, 	/* 0FEC0 */
+	0xC1,  0x54,  0x95,  0x45,  0xDC,  0x05,  0x03,  0xFC,  0x52,  0x45,  0xFC,  0x92,  0x49,  0xFC,  0x97,  0x5D, 	/* 0FED0 */
+	0xE3,  0x52,  0x1D,  0xE9,  0x52,  0x5D,  0xE1,  0x02,  0x17,  0xA3,  0x4A,  0x57,  0xA5,  0x4A,  0x97,  0xA9, 	/* 0FEE0 */
+	0x06,  0xA1,  0x47,  0xC2,  0x44,  0x07,  0xC8,  0xEE,  0x4A,  0xA0,  0xEE,  0x01,  0x02,  0xFE,  0x43,  0x84, 	/* 0FEF0 */
+	0x54,  0x89,  0x38,  0x10,  0xA3,  0x88,  0x87,  0xE8,  0x09,  0x43,  0xD4,  0xA6,  0x27,  0xDD,  0x24,  0x83, 	/* 0FF00 */
+	0xC8,  0x4B,  0xE7,  0xC8,  0x88,  0x88,  0x88,  0xA4,  0x9F,  0xC5,  0x54,  0x1F,  0xC0,  0xF8,  0x82,  0x07, 	/* 0FF10 */
+	0xFE,  0x08,  0x83,  0xFE,  0x42,  0x05,  0xFC,  0x82,  0x08,  0x20,  0xAA,  0x9F,  0xC4,  0x20,  0x3F,  0xE2, 	/* 0FF20 */
+	0x22,  0xBB,  0xA4,  0x30,  0x0C,  0xC3,  0x33,  0x4F,  0xE4,  0x22,  0x82,  0xC8,  0x20,  0xB1,  0x5E,  0xE3, 	/* 0FF30 */
+	0x2A,  0x12,  0xA9,  0xEA,  0x55,  0x31,  0xF0,  0x15,  0xE3,  0x4A,  0x5F,  0xA5,  0x44,  0x96,  0xAA,  0xB1, 	/* 0FF40 */
+	0xB3,  0x42,  0x02,  0xFE,  0x08,  0xA8,  0xF6,  0x4D,  0x20,  0xFE,  0x0B,  0xA2,  0xD6,  0x41,  0x05,  0xFF, 	/* 0FF50 */
+	0x86,  0xC9,  0x83,  0xB9,  0x47,  0x82,  0x90,  0x1F,  0xE9,  0x28,  0x5C,  0xE1,  0x38,  0x10,  0x03,  0xFE, 	/* 0FF60 */
+	0x50,  0x05,  0x7C,  0x94,  0x4A,  0x7C,  0x80,  0x49,  0x03,  0xD0,  0x15,  0xE9,  0xD4,  0x56,  0x41,  0xE4, 	/* 0FF70 */
+	0x09,  0x43,  0xE8,  0x48,  0x84,  0xD4,  0x96,  0x4A,  0xC2,  0x81,  0x9F,  0xE5,  0x52,  0x1F,  0xE0,  0x80, 	/* 0FF80 */
+	0x8F,  0xE5,  0x22,  0x0F,  0xA2,  0xAA,  0x4F,  0xA4,  0x2A,  0x87,  0xA9,  0x8C,  0x82,  0x42,  0x03,  0xFE, 	/* 0FF90 */
+	0x15,  0x09,  0xFC,  0x55,  0x41,  0xFE,  0x15,  0x43,  0xFC,  0x55,  0x05,  0x58,  0xAD,  0x4B,  0x50,  0x83, 	/* 0FFA0 */
+	0x85,  0x05,  0xFC,  0x15,  0x41,  0xFC,  0x95,  0x45,  0xFE,  0x10,  0x01,  0xFE,  0x55,  0x05,  0x56,  0x94, 	/* 0FFB0 */
+	0x8A,  0xE6,  0x86,  0x42,  0x03,  0xFC,  0x0A,  0x8B,  0xFE,  0x48,  0x80,  0xFC,  0x08,  0x42,  0xFC,  0x48, 	/* 0FFC0 */
+	0x44,  0xFC,  0x84,  0x49,  0x82,  0x94,  0x40,  0x03,  0xFE,  0x0A,  0x89,  0x24,  0x5F,  0xE1,  0x76,  0x1A, 	/* 0FFD0 */
+	0xA3,  0x76,  0x57,  0x65,  0xAA,  0x97,  0x69,  0x22,  0x95,  0x4F,  0xC2,  0x84,  0x0F,  0xC8,  0x84,  0x4F, 	/* 0FFE0 */
+	0xC0,  0x44,  0x0A,  0xA2,  0x54,  0x4A,  0xA5,  0xFE,  0x95,  0x4A,  0x2A,  0x98,  0x42,  0x03,  0xFE,  0x11, 	/* 0FFF0 */
+	0x28,  0xA8,  0x4A,  0x21,  0x1A,  0x1F,  0xC1,  0x54,  0x7F,  0xE4,  0x10,  0x81,  0x08,  0x30,  0x9B,  0x48, 	/* 10000 */
+	0x83,  0xFE,  0x0A,  0x89,  0xFE,  0x50,  0x20,  0xFC,  0x1A,  0x42,  0x74,  0x59,  0x84,  0x74,  0x99,  0x28, 	/* 10010 */
+	0x30,  0x9F,  0x41,  0x03,  0xFE,  0x02,  0xA9,  0xFC,  0x4B,  0x80,  0xB4,  0x15,  0x22,  0x84,  0x4F,  0xC4, 	/* 10020 */
+	0x84,  0x8F,  0xC9,  0x04,  0xA0,  0x42,  0x03,  0xFE,  0x07,  0x88,  0x48,  0x5F,  0xE1,  0x02,  0x0F,  0xC2, 	/* 10030 */
+	0x64,  0x5B,  0x84,  0x54,  0x99,  0x28,  0x60,  0xA1,  0x9F,  0xC4,  0x20,  0x3F,  0xE2,  0x22,  0xAF,  0xA4, 	/* 10040 */
+	0x00,  0x1F,  0xE2,  0x20,  0x5F,  0xC5,  0x54,  0x95,  0x49,  0x0C,  0xA4,  0x82,  0x05,  0xFE,  0x02,  0x0B, 	/* 10050 */
+	0xFE,  0x40,  0x40,  0xF8,  0x02,  0x07,  0xFE,  0x5C,  0x45,  0x7E,  0x9D,  0x48,  0x0C,  0xAB,  0xBD,  0x06, 	/* 10060 */
+	0x90,  0x3D,  0xE2,  0x50,  0xBE,  0x06,  0x9E,  0x3C,  0x00,  0x00,  0x5F,  0xC5,  0x54,  0x95,  0x4B,  0xFE, 	/* 10070 */
+	0xAC,  0x43,  0xC2,  0x20,  0x1F,  0xE9,  0x02,  0x4F,  0x81,  0x54,  0x28,  0xA1,  0xFC,  0x68,  0xA4,  0xF8, 	/* 10080 */
+	0x88,  0x88,  0xF8,  0xAE,  0x88,  0x84,  0xAA,  0x09,  0xC1,  0x7F,  0x92,  0x27,  0x14,  0x13,  0xE1,  0x08, 	/* 10090 */
+	0x57,  0xF5,  0x14,  0x92,  0x29,  0x41,  0xAF,  0x40,  0x03,  0xDE,  0x04,  0x23,  0xDE,  0x84,  0x25,  0xDE, 	/* 100A0 */
+	0x08,  0x82,  0xFC,  0x59,  0x04,  0xFC,  0x89,  0x08,  0xFE,  0xB1,  0x41,  0x02,  0xFE,  0x09,  0x28,  0x54, 	/* 100B0 */
+	0x49,  0x80,  0x7C,  0x0C,  0x42,  0x7C,  0x44,  0x44,  0x7C,  0x82,  0x48,  0xC2,  0xB3,  0x59,  0x43,  0xDE, 	/* 100C0 */
+	0x2A,  0x4B,  0xFE,  0x48,  0x41,  0xAC,  0x2D,  0x60,  0xFC,  0x48,  0x44,  0xFC,  0x88,  0x48,  0xFC,  0xB6, 	/* 100D0 */
+	0x5E,  0xF3,  0x29,  0x1E,  0xF9,  0x29,  0x5E,  0xF1,  0x79,  0x11,  0x13,  0x7D,  0x51,  0x15,  0x7D,  0x94, 	/* 100E0 */
+	0x59,  0x7D,  0xBA,  0x40,  0xA3,  0xCE,  0x17,  0x89,  0xCA,  0x54,  0x41,  0x5A,  0x1C,  0xE3,  0x78,  0x54, 	/* 100F0 */
+	0xA5,  0xC4,  0x88,  0xCB,  0x52,  0xBE,  0x43,  0xC2,  0x20,  0x1F,  0xE9,  0x3A,  0x5E,  0x01,  0x1E,  0x17, 	/* 10100 */
+	0xC3,  0x54,  0x57,  0xC5,  0x74,  0x9A,  0xAA,  0x38,  0x81,  0x44,  0x83,  0xFE,  0x02,  0x09,  0xFC,  0x4A, 	/* 10110 */
+	0x81,  0x24,  0x0F,  0xA2,  0x88,  0x4F,  0xA4,  0xA4,  0x89,  0x89,  0xE6,  0x89,  0x42,  0x03,  0xFE,  0x14, 	/* 10120 */
+	0x28,  0x9C,  0x4C,  0xC0,  0x84,  0x0F,  0xC2,  0x40,  0x4F,  0xE5,  0x02,  0x8A,  0xA9,  0x0C,  0x8B,  0x42, 	/* 10130 */
+	0x03,  0xFE,  0x11,  0xA0,  0xE8,  0x8B,  0x05,  0xFE,  0x0A,  0x81,  0xFC,  0x6A,  0xA4,  0xF8,  0x8A,  0x88, 	/* 10140 */
+	0xF8,  0x8F,  0x4A,  0x23,  0x72,  0x15,  0xA9,  0xDA,  0x44,  0xA0,  0xAA,  0x0F,  0xA3,  0x4A,  0x5F,  0xA5, 	/* 10150 */
+	0x52,  0x8F,  0x29,  0x86,  0x91,  0x4F,  0xC2,  0x84,  0x0F,  0xC8,  0x48,  0x4F,  0xC0,  0x48,  0x1F,  0xE0, 	/* 10160 */
+	0x54,  0x4D,  0x65,  0x39,  0x8D,  0x68,  0x10,  0x95,  0x88,  0x04,  0xBE,  0x2E,  0x82,  0x9E,  0xBF,  0x24, 	/* 10170 */
+	0x9E,  0x1B,  0x22,  0x9E,  0x6B,  0x24,  0x5E,  0x89,  0x4B,  0x22,  0x98,  0x43,  0xC2,  0x20,  0x1F,  0xE9, 	/* 10180 */
+	0x22,  0x5F,  0x81,  0x7E,  0x15,  0x43,  0x7C,  0x55,  0x46,  0xFE,  0xAA,  0xAD,  0xFF,  0x9A,  0x90,  0x87, 	/* 10190 */
+	0xD4,  0x11,  0x43,  0xA2,  0xAC,  0x17,  0xFE,  0x2B,  0x63,  0xDA,  0x53,  0x67,  0xDA,  0x91,  0x29,  0x36, 	/* 101A0 */
+	0x9B,  0x42,  0x03,  0xFE,  0x10,  0x09,  0xFC,  0x48,  0x80,  0xF8,  0x1D,  0xC3,  0x54,  0x57,  0x45,  0xDC, 	/* 101B0 */
+	0x95,  0x4A,  0xE6,  0x9D,  0x9F,  0xE5,  0xFC,  0x14,  0x81,  0xFE,  0x95,  0xC5,  0xEA,  0x14,  0x83,  0x10, 	/* 101C0 */
+	0x55,  0x05,  0x5C,  0x95,  0x0A,  0xFE,  0x9E,  0x89,  0xC7,  0xD4,  0x0A,  0x49,  0xC8,  0x4B,  0xE3,  0xCA, 	/* 101D0 */
+	0x17,  0xF5,  0xCA,  0x57,  0xE5,  0xC8,  0x94,  0x89,  0x58,  0x9F,  0x48,  0x83,  0xFE,  0x0A,  0x89,  0xFE, 	/* 101E0 */
+	0x42,  0x83,  0xFF,  0x1A,  0xA3,  0xFE,  0x52,  0x25,  0xAE,  0x9A,  0xAA,  0xAA,  0xA6,  0x40,  0x83,  0xE8, 	/* 101F0 */
+	0x09,  0xE8,  0x8C,  0x5B,  0xE2,  0x48,  0x0D,  0xE1,  0x72,  0x4D,  0xE5,  0x52,  0xA5,  0x28,  0x9E,  0xA7, 	/* 10200 */
+	0x89,  0x07,  0xFE,  0x15,  0x01,  0x5E,  0xBE,  0x25,  0x5E,  0x1D,  0x03,  0x5C,  0x5D,  0x05,  0x5C,  0x95, 	/* 10210 */
+	0x29,  0x4E,  0xAC,  0x88,  0x04,  0x9E,  0x3E,  0x88,  0x9E,  0x7F,  0x22,  0xBE,  0x3F,  0x25,  0x9E,  0x5D, 	/* 10220 */
+	0x26,  0xBE,  0xA8,  0xC8,  0x92,  0xB0,  0x40,  0x03,  0xFE,  0x15,  0x49,  0xFE,  0x7B,  0xA2,  0xD6,  0x3B, 	/* 10230 */
+	0xA4,  0xD6,  0x4B,  0xA8,  0xD6,  0x9B,  0xAA,  0x96,  0xB2,  0x89,  0x05,  0x50,  0x23,  0xE1,  0xD4,  0x81, 	/* 10240 */
+	0x47,  0xE4,  0x2B,  0x43,  0xE8,  0x54,  0x85,  0x54,  0xAB,  0x4A,  0x22,  0xBE,  0xBD,  0xE6,  0x52,  0x3D, 	/* 10250 */
+	0xE2,  0x22,  0xAF,  0xA6,  0x22,  0x2F,  0xA2,  0xAA,  0x6F,  0xA6,  0x72,  0xAA,  0xAA,  0x26,  0x8C,  0x44, 	/* 10260 */
+	0x83,  0xFE,  0x04,  0x89,  0xDC,  0x55,  0x41,  0xDC,  0x04,  0x02,  0xFE,  0x59,  0x04,  0xFC,  0x89,  0x08, 	/* 10270 */
+	0xFE,  0x91,  0x5D,  0xE2,  0x00,  0x1D,  0xC9,  0x54,  0x5F,  0xE1,  0x28,  0x1F,  0xE3,  0x2A,  0x5F,  0xE5, 	/* 10280 */
+	0x6C,  0x94,  0xAA,  0xEE,  0x98,  0x94,  0xA7,  0xF4,  0x15,  0xEB,  0xF4,  0x69,  0x43,  0xFE,  0x09,  0x47, 	/* 10290 */
+	0xF4,  0x49,  0xE7,  0xF4,  0x95,  0x4A,  0x1E,  0xA3,  0x89,  0x45,  0x7A,  0x08,  0x51,  0xFF,  0x8D,  0x65, 	/* 102A0 */
+	0x7D,  0x00,  0x42,  0xFC,  0x48,  0x04,  0xFE,  0x80,  0x28,  0x1C,  0xAB,  0x04,  0x00,  0x40,  0x04,  0x42, 	/* 102B0 */
+	0x44,  0x24,  0x84,  0x50,  0x44,  0x00,  0x60,  0x0A,  0x00,  0x90,  0x30,  0x8C,  0x06,  0xAF,  0x20,  0x02, 	/* 102C0 */
+	0xFE,  0x20,  0x8A,  0x88,  0xB0,  0x82,  0x08,  0x20,  0x82,  0x08,  0x50,  0x84,  0x88,  0x80,  0x80,  0x18, 	/* 102D0 */
+	0xB0,  0x00,  0x03,  0xFE,  0x22,  0x02,  0x24,  0x2A,  0x42,  0xA4,  0x32,  0x82,  0x20,  0x45,  0x04,  0x50, 	/* 102E0 */
+	0x88,  0x83,  0x06,  0xB8,  0x08,  0x00,  0xF0,  0x11,  0x06,  0x60,  0x09,  0x83,  0x46,  0xC4,  0x01,  0x44, 	/* 102F0 */
+	0x6D,  0x80,  0xA0,  0x31,  0x0C,  0x0E,  0xBC,  0x22,  0x02,  0x20,  0x2B,  0xE7,  0x42,  0xA4,  0x2A,  0xA2, 	/* 10300 */
+	0x21,  0x23,  0x12,  0x50,  0x24,  0x82,  0x80,  0x20,  0x0C,  0xBD,  0x12,  0x42,  0x48,  0x49,  0x02,  0x48, 	/* 10310 */
+	0x24,  0x80,  0x00,  0x04,  0x42,  0x44,  0x24,  0x84,  0xA0,  0x31,  0x8C,  0x06,  0x89,  0x2F,  0xE2,  0x00, 	/* 10320 */
+	0x27,  0xE6,  0xC2,  0x74,  0x2A,  0x7E,  0x24,  0x02,  0x40,  0x54,  0x04,  0x80,  0x88,  0x01,  0x00,  0x8A, 	/* 10330 */
+	0x24,  0x02,  0x40,  0x24,  0x06,  0xFE,  0x75,  0x2A,  0x54,  0x29,  0x02,  0x10,  0x52,  0x84,  0x28,  0x84, 	/* 10340 */
+	0x49,  0x82,  0x8E,  0x04,  0x01,  0x44,  0x24,  0x80,  0x60,  0x19,  0x86,  0x44,  0x14,  0x01,  0x44,  0x26, 	/* 10350 */
+	0x80,  0x90,  0x30,  0x8C,  0x06,  0x92,  0x21,  0x02,  0x10,  0x21,  0x46,  0xD4,  0x75,  0x2A,  0x52,  0xA9, 	/* 10360 */
+	0x62,  0x34,  0x50,  0x84,  0x90,  0x46,  0x09,  0x80,  0x99,  0x04,  0x00,  0xFC,  0x74,  0x81,  0x30,  0x0E, 	/* 10370 */
+	0x0F,  0x40,  0x24,  0x42,  0x44,  0x44,  0x80,  0xA0,  0x31,  0x8C,  0x06,  0xAC,  0x20,  0x02,  0x7E,  0x24, 	/* 10380 */
+	0x06,  0xC0,  0x77,  0xEA,  0x42,  0xA4,  0x22,  0x7E,  0x54,  0x04,  0xC0,  0x44,  0x08,  0x7E,  0xAD,  0x44, 	/* 10390 */
+	0x44,  0x44,  0x7F,  0xC0,  0x00,  0x7F,  0xC5,  0x48,  0x54,  0x85,  0x50,  0x46,  0x04,  0x90,  0x90,  0x8E, 	/* 103A0 */
+	0x06,  0xAE,  0x22,  0x02,  0x20,  0x27,  0xE6,  0x82,  0x77,  0xAA,  0x4A,  0xA4,  0xA2,  0x7C,  0x34,  0x04, 	/* 103B0 */
+	0xC0,  0x44,  0x28,  0x3E,  0xAF,  0x20,  0x02,  0x7E,  0x24,  0x26,  0xC2,  0x77,  0xAA,  0x6A,  0xA6,  0xA2, 	/* 103C0 */
+	0x6A,  0x57,  0xA4,  0xC2,  0x44,  0x28,  0x46,  0xB3,  0x20,  0x02,  0x7E,  0x21,  0x06,  0x90,  0x77,  0xEA, 	/* 103D0 */
+	0x52,  0xA6,  0xA2,  0x66,  0x34,  0x24,  0xC2,  0x44,  0x28,  0x46,  0xB8,  0x24,  0x02,  0x40,  0x27,  0xE6, 	/* 103E0 */
+	0xD0,  0x75,  0x0A,  0x9E,  0xA1,  0x02,  0x10,  0x51,  0xE4,  0x90,  0x41,  0x08,  0x10,  0xB9,  0x04,  0x00, 	/* 103F0 */
+	0x40,  0x07,  0xE0,  0x40,  0x3F,  0x82,  0x08,  0x20,  0x83,  0xF8,  0x00,  0x05,  0x24,  0x49,  0x28,  0x92, 	/* 10400 */
+	0xBA,  0x22,  0x01,  0x20,  0x04,  0x07,  0xF0,  0x09,  0x01,  0xFC,  0x10,  0x43,  0xFE,  0x40,  0x29,  0x52, 	/* 10410 */
+	0x2A,  0xA4,  0x0C,  0x88,  0x00,  0x2F,  0xD2,  0x21,  0x23,  0xD2,  0x65,  0x29,  0x42,  0x08,  0x23,  0x02, 	/* 10420 */
+	0xC0,  0x64,  0xA4,  0x49,  0x28,  0x92,  0x8B,  0x22,  0x02,  0x20,  0x3F,  0xE4,  0x70,  0xC7,  0x04,  0xA8, 	/* 10430 */
+	0x52,  0x46,  0x22,  0x42,  0x02,  0x24,  0x49,  0x28,  0x92,  0x8F,  0x08,  0x03,  0xF8,  0x20,  0x83,  0xF8, 	/* 10440 */
+	0x20,  0x03,  0xFE,  0x20,  0x03,  0xFE,  0x01,  0x25,  0x4A,  0x4A,  0x28,  0x0C,  0x99,  0x21,  0x02,  0x1C, 	/* 10450 */
+	0x2A,  0x47,  0x24,  0x65,  0x8A,  0x18,  0xA2,  0x42,  0x7E,  0x5A,  0x54,  0xA4,  0x42,  0x48,  0x3C,  0x9D, 	/* 10460 */
+	0x3F,  0x80,  0x10,  0x06,  0x4F,  0x68,  0x15,  0x02,  0x48,  0xC4,  0x60,  0xC0,  0xFF,  0xE0,  0x00,  0x4A, 	/* 10470 */
+	0x48,  0x92,  0x9F,  0x20,  0x02,  0x7E,  0x25,  0x26,  0xD2,  0x77,  0xEA,  0x52,  0xA5,  0x22,  0x5A,  0x36, 	/* 10480 */
+	0xA4,  0xE6,  0x44,  0x28,  0x7E,  0xB1,  0x20,  0x02,  0xFE,  0x2A,  0xA6,  0xAA,  0x7C,  0xEA,  0x82,  0xAB, 	/* 10490 */
+	0xA2,  0xAA,  0x2A,  0xA5,  0xBA,  0x48,  0x28,  0x86,  0xB9,  0x04,  0x0F,  0xFE,  0x00,  0x03,  0xF8,  0x20, 	/* 104A0 */
+	0x87,  0xFC,  0x03,  0x00,  0x40,  0x0C,  0x04,  0x24,  0x49,  0x28,  0x92,  0xBD,  0x24,  0x02,  0x7C,  0x2A, 	/* 104B0 */
+	0x47,  0x18,  0xBE,  0x6A,  0x10,  0x27,  0xC2,  0x10,  0x37,  0xC4,  0x90,  0x4F,  0xE8,  0x10,  0x89,  0x00, 	/* 104C0 */
+	0x0F,  0xFE,  0x04,  0x02,  0x7C,  0x24,  0x0F,  0xFE,  0x3F,  0xC2,  0x00,  0x3F,  0xC5,  0x54,  0x6A,  0x48, 	/* 104D0 */
+	0x18,  0x94,  0x20,  0x82,  0x0E,  0x23,  0x26,  0x84,  0xB0,  0x8A,  0x5E,  0x25,  0x22,  0x52,  0x55,  0xE4, 	/* 104E0 */
+	0xD2,  0x85,  0x20,  0x5E,  0x99,  0x21,  0x02,  0x10,  0x2F,  0xE6,  0xC4,  0xB2,  0x8A,  0xFE,  0x20,  0x02, 	/* 104F0 */
+	0x7C,  0x34,  0x44,  0xC4,  0x44,  0x48,  0x7C,  0x9A,  0x10,  0x8F,  0xFE,  0x11,  0x03,  0xB8,  0x55,  0x49, 	/* 10500 */
+	0x12,  0x04,  0x02,  0x44,  0x24,  0x84,  0xA0,  0x31,  0x8C,  0x06,  0x9C,  0x20,  0x02,  0x7E,  0x24,  0x26, 	/* 10510 */
+	0xC2,  0xB7,  0xEA,  0x42,  0x27,  0xE2,  0x48,  0x37,  0xE4,  0xC8,  0x45,  0x98,  0xEF,  0xA1,  0x20,  0x03, 	/* 10520 */
+	0xFE,  0x6A,  0x8A,  0xA8,  0xFF,  0xC2,  0xA8,  0x2A,  0x8F,  0xFE,  0x00,  0x04,  0xA4,  0x49,  0x28,  0x92, 	/* 10530 */
+	0xA6,  0x11,  0x01,  0x20,  0x3F,  0xE6,  0x20,  0xBF,  0xC2,  0x20,  0x3F,  0xC2,  0x20,  0x3F,  0xE4,  0x04, 	/* 10540 */
+	0x49,  0x28,  0x92,  0xB6,  0x11,  0x41,  0xD2,  0x35,  0x04,  0xFE,  0xA9,  0x01,  0x18,  0x22,  0x4C,  0xC2, 	/* 10550 */
+	0x00,  0x05,  0x24,  0x49,  0x28,  0x02,  0xBC,  0x22,  0x02,  0xFC,  0x22,  0x06,  0x68,  0x7F,  0xCA,  0x48, 	/* 10560 */
+	0xAF,  0xE2,  0x28,  0x52,  0x84,  0xCA,  0x48,  0xA9,  0x06,  0x89,  0x21,  0x02,  0xFE,  0x21,  0x06,  0xFC, 	/* 10570 */
+	0xB9,  0x4A,  0xFC,  0x29,  0x42,  0xFC,  0x53,  0x84,  0xD4,  0x89,  0x20,  0x10,  0x8C,  0x22,  0x02,  0x7C, 	/* 10580 */
+	0x24,  0x46,  0xFC,  0xB4,  0x4A,  0x7C,  0x20,  0x02,  0xFE,  0x31,  0x04,  0xFC,  0x41,  0x08,  0xFE,  0x8E, 	/* 10590 */
+	0x20,  0x81,  0x10,  0xFF,  0xE4,  0x84,  0x7A,  0x44,  0xA4,  0x7A,  0x44,  0xA4,  0x58,  0xC0,  0x00,  0x49, 	/* 105A0 */
+	0x48,  0x92,  0x95,  0x00,  0x0F,  0xBC,  0x92,  0x4B,  0xA4,  0xAA,  0x4A,  0xBC,  0x9A,  0x09,  0x22,  0xF9, 	/* 105B0 */
+	0xE0,  0x00,  0x4A,  0x48,  0x92,  0x96,  0x20,  0xE2,  0xF2,  0x25,  0x47,  0x34,  0x6F,  0xEA,  0x20,  0xBF, 	/* 105C0 */
+	0xE2,  0x20,  0x57,  0xE4,  0x54,  0x49,  0xC9,  0x62,  0x99,  0x20,  0x02,  0xFE,  0x22,  0x86,  0xFE,  0xBA, 	/* 105D0 */
+	0xAA,  0xAA,  0x2F,  0xE2,  0x10,  0x57,  0xC4,  0x90,  0x81,  0x00,  0xFE,  0xA2,  0x22,  0x0A,  0xA8,  0x55, 	/* 105E0 */
+	0x08,  0x88,  0xFF,  0xC8,  0x04,  0x7F,  0x80,  0x88,  0x08,  0x87,  0xEA,  0x08,  0x60,  0x82,  0xA4,  0x22, 	/* 105F0 */
+	0x42,  0xFE,  0x22,  0x46,  0xFC,  0x72,  0x4A,  0x3C,  0x21,  0x02,  0xFE,  0x53,  0x84,  0x54,  0x99,  0x28, 	/* 10600 */
+	0x10,  0xA5,  0x23,  0xC2,  0x44,  0x28,  0x86,  0xFE,  0x6A,  0xAB,  0xAA,  0x2C,  0xE2,  0x92,  0x3F,  0xF4, 	/* 10610 */
+	0x90,  0x46,  0x89,  0x86,  0xA6,  0x02,  0x0F,  0x3E,  0x94,  0x29,  0xFA,  0xF4,  0xA9,  0x4A,  0x97,  0xAF, 	/* 10620 */
+	0x02,  0x00,  0xC4,  0x00,  0x4A,  0x48,  0x92,  0xA7,  0x00,  0x0F,  0xFC,  0x92,  0x49,  0x24,  0xF4,  0x89, 	/* 10630 */
+	0xFC,  0x94,  0x49,  0x44,  0xF7,  0xC0,  0x00,  0x52,  0x48,  0x92,  0xA9,  0x20,  0x02,  0x7E,  0x69,  0x07, 	/* 10640 */
+	0x7E,  0xA4,  0x2A,  0x7E,  0x24,  0x22,  0x7E,  0x54,  0x24,  0xFE,  0x42,  0x48,  0xC2,  0xAC,  0x20,  0x02, 	/* 10650 */
+	0x7C,  0x24,  0x46,  0xFC,  0xB4,  0x4A,  0xFE,  0x24,  0x02,  0xFE,  0x34,  0xA4,  0x92,  0x42,  0x28,  0xCC, 	/* 10660 */
+	0xAE,  0x04,  0x87,  0xFC,  0x05,  0x0F,  0xFE,  0x08,  0x03,  0xF8,  0xD0,  0x81,  0xF8,  0x10,  0x81,  0xF8, 	/* 10670 */
+	0x2A,  0x44,  0x92,  0xBD,  0x2F,  0xE2,  0x00,  0x2F,  0xC2,  0x84,  0x6F,  0xC7,  0x80,  0xAF,  0xE2,  0xDA, 	/* 10680 */
+	0x2B,  0x65,  0xDA,  0x49,  0x28,  0xB6,  0x84,  0x22,  0x02,  0x7C,  0x24,  0x46,  0xFC,  0x74,  0x4A,  0x7C, 	/* 10690 */
+	0xA4,  0x42,  0x7C,  0x21,  0x05,  0x4A,  0x46,  0x28,  0x9E,  0x88,  0x00,  0x05,  0xFE,  0x55,  0x25,  0xF2, 	/* 106A0 */
+	0x53,  0xE5,  0x30,  0x5F,  0x05,  0x52,  0x9E,  0xE0,  0x00,  0x4A,  0x48,  0x92,  0x8A,  0x22,  0x44,  0xB8, 	/* 106B0 */
+	0xFA,  0x24,  0xDE,  0x78,  0x04,  0xA4,  0x7B,  0x84,  0xA2,  0x89,  0xE0,  0x00,  0x52,  0x48,  0x92,  0x8F, 	/* 106C0 */
+	0x3F,  0x80,  0x40,  0xFF,  0xE0,  0x40,  0xFF,  0xE6,  0x4C,  0x55,  0x4F,  0xFE,  0x04,  0x0F,  0xFE,  0x4A, 	/* 106D0 */
+	0x48,  0x92,  0x94,  0x21,  0x02,  0xFE,  0x28,  0x26,  0x2A,  0xB5,  0x4A,  0x28,  0x2C,  0x62,  0x00,  0x57, 	/* 106E0 */
+	0xC4,  0x44,  0x84,  0x40,  0x7C,  0x95,  0x20,  0x02,  0x7C,  0x21,  0x06,  0xFE,  0x6C,  0x4B,  0x7C,  0xA4, 	/* 106F0 */
+	0x42,  0x7C,  0x34,  0x44,  0xFC,  0x42,  0xC8,  0xC2,  0x99,  0x00,  0x0F,  0xDE,  0x91,  0x2B,  0x92,  0xA9, 	/* 10700 */
+	0xEA,  0x90,  0xB9,  0x29,  0x12,  0xFC,  0xE0,  0x00,  0x4A,  0x48,  0x92,  0x9F,  0x11,  0x0F,  0xD0,  0x7B, 	/* 10710 */
+	0xC4,  0x94,  0x7B,  0x41,  0x14,  0xFA,  0xC1,  0x46,  0x38,  0x25,  0x24,  0x49,  0x28,  0x92,  0xA8,  0x7C, 	/* 10720 */
+	0x44,  0x7E,  0x7E,  0x44,  0x94,  0x48,  0x4A,  0xA4,  0xAA,  0xC0,  0x44,  0x24,  0x84,  0x40,  0x1B,  0x0E, 	/* 10730 */
+	0x0E,  0xAC,  0x22,  0x07,  0xA0,  0x23,  0xEF,  0xA4,  0x25,  0x43,  0x94,  0x28,  0x84,  0x94,  0x9A,  0x20, 	/* 10740 */
+	0x00,  0x4A,  0x48,  0x92,  0xB1,  0x21,  0x0F,  0x90,  0x27,  0xCF,  0x94,  0x53,  0x4F,  0x94,  0x22,  0xC3, 	/* 10750 */
+	0xA4,  0xC4,  0x64,  0x08,  0x52,  0x48,  0x92,  0xB9,  0x04,  0x0F,  0xFE,  0x04,  0x07,  0xFC,  0x20,  0x83, 	/* 10760 */
+	0xF8,  0x11,  0x0F,  0xFE,  0x20,  0x83,  0xF8,  0x52,  0x48,  0x92,  0xBE,  0x22,  0x42,  0xFE,  0x25,  0x56, 	/* 10770 */
+	0x54,  0x6F,  0xFB,  0x04,  0xA7,  0x52,  0x55,  0x57,  0x54,  0x52,  0x47,  0x68,  0x19,  0x83,  0x24,  0xC2, 	/* 10780 */
+	0x6A,  0x2A,  0x86,  0xFE,  0x7A,  0x8A,  0x48,  0x25,  0x42,  0xA2,  0x30,  0x05,  0x54,  0x4A,  0xA9,  0x2A, 	/* 10790 */
+	0x88,  0x27,  0x02,  0x16,  0x2E,  0x86,  0xAA,  0x77,  0xCA,  0x82,  0x27,  0xC2,  0x44,  0x57,  0xC4,  0x44, 	/* 107A0 */
+	0x82,  0x80,  0xFE,  0x89,  0x24,  0x82,  0xF8,  0x20,  0xE6,  0xEA,  0x7B,  0xAA,  0xEA,  0xA1,  0x42,  0xE4, 	/* 107B0 */
+	0x35,  0x45,  0xEA,  0x44,  0xA8,  0xD1,  0x8E,  0x21,  0x02,  0xFE,  0x22,  0x86,  0xBA,  0x74,  0x4A,  0xFE, 	/* 107C0 */
+	0xA4,  0x52,  0x7C,  0x31,  0x04,  0x54,  0x49,  0x28,  0x30,  0x90,  0x29,  0x22,  0x54,  0x6F,  0xE7,  0x38, 	/* 107D0 */
+	0xA5,  0x4A,  0x92,  0x24,  0x42,  0x7E,  0x5B,  0x45,  0x3E,  0x84,  0x41,  0x84,  0x92,  0x21,  0x02,  0x7C, 	/* 107E0 */
+	0x21,  0x06,  0xFE,  0x74,  0x4A,  0xEE,  0xA4,  0x42,  0xFE,  0x50,  0x04,  0xFE,  0x42,  0x88,  0xCE,  0x94, 	/* 107F0 */
+	0x20,  0xC2,  0xF2,  0x25,  0x46,  0xFE,  0x73,  0x8A,  0x54,  0xA9,  0x22,  0x7F,  0x35,  0x24,  0xFE,  0x45, 	/* 10800 */
+	0x28,  0x7E,  0x95,  0x0A,  0x0F,  0xFE,  0x0A,  0x02,  0xE8,  0x20,  0xEE,  0xE8,  0x2A,  0xAE,  0xEA,  0x20, 	/* 10810 */
+	0x62,  0xA4,  0x49,  0x28,  0x92,  0x97,  0x2E,  0xE2,  0xAA,  0x2E,  0xE6,  0xAA,  0xBE,  0xEA,  0xBA,  0x2A, 	/* 10820 */
+	0xA2,  0xBA,  0x5A,  0xA4,  0xBA,  0x4C,  0xA8,  0x86,  0x9F,  0x55,  0x42,  0xA8,  0x44,  0x4F,  0xFE,  0x80, 	/* 10830 */
+	0x2B,  0xFA,  0x20,  0x83,  0xF8,  0x08,  0x07,  0xFC,  0x40,  0x47,  0xFC,  0xA0,  0x22,  0x02,  0xFE,  0x2D, 	/* 10840 */
+	0x66,  0xBA,  0x79,  0x2A,  0xFE,  0xAB,  0xA2,  0xD6,  0x39,  0x24,  0xFF,  0x42,  0x88,  0xC6,  0xA5,  0x27, 	/* 10850 */
+	0xC2,  0x44,  0x27,  0xC6,  0xEE,  0x7A,  0xAA,  0xEE,  0x21,  0x02,  0xFE,  0x53,  0x84,  0x54,  0x89,  0x30, 	/* 10860 */
+	0x10,  0xA6,  0x2E,  0xE2,  0x82,  0x2E,  0xAA,  0xA4,  0xB6,  0xA6,  0xD0,  0x29,  0x22,  0x54,  0x2F,  0xE5, 	/* 10870 */
+	0x38,  0x4D,  0x68,  0x10,  0xA7,  0x25,  0x42,  0x22,  0x2B,  0xC6,  0x50,  0xB2,  0xAA,  0xDA,  0x26,  0xC2, 	/* 10880 */
+	0x5A,  0x36,  0x94,  0x48,  0x4B,  0x09,  0x1F,  0xAC,  0x24,  0x02,  0x8E,  0x2E,  0xA6,  0xAA,  0x7F,  0x3A, 	/* 10890 */
+	0xA0,  0xAF,  0xE2,  0x4A,  0x2F,  0xA5,  0x44,  0x46,  0xA9,  0x91,  0xAD,  0x2F,  0xE2,  0xAA,  0x2F,  0xE6, 	/* 108A0 */
+	0xC0,  0xB7,  0xEA,  0xA2,  0x3F,  0xA2,  0xAA,  0x5F,  0xA4,  0x2A,  0x83,  0xA1,  0xCC,  0xAE,  0x2E,  0x82, 	/* 108B0 */
+	0x08,  0x7F,  0xAA,  0xEA,  0x2E,  0xC5,  0xB4,  0x8E,  0x20,  0x40,  0x7F,  0xC1,  0x10,  0x0E,  0x0F,  0x1E, 	/* 108C0 */
+	0xB5,  0x24,  0x82,  0x3C,  0x28,  0x86,  0x7E,  0x71,  0x4A,  0xFE,  0xA4,  0x82,  0x7E,  0x34,  0x84,  0x7C, 	/* 108D0 */
+	0x4A,  0x89,  0x1F,  0xB9,  0x00,  0x0F,  0xBE,  0x61,  0x0B,  0x6A,  0xD9,  0xC3,  0x6A,  0xD1,  0x82,  0x50, 	/* 108E0 */
+	0x24,  0x44,  0xE8,  0x31,  0x8C,  0x06,  0xBB,  0x20,  0xC2,  0x70,  0x2F,  0xE6,  0x10,  0x7F,  0xEA,  0xD6, 	/* 108F0 */
+	0x2B,  0xA2,  0xFE,  0x51,  0x04,  0xFE,  0x4D,  0x49,  0x2A,  0xBC,  0x22,  0x02,  0xFC,  0x22,  0x46,  0xFE, 	/* 10900 */
+	0x72,  0x0A,  0xFC,  0xA5,  0x42,  0xAA,  0x2F,  0xC5,  0xB4,  0x4B,  0x49,  0xFE,  0xBF,  0x20,  0x02,  0xFE, 	/* 10910 */
+	0x25,  0xA6,  0xB6,  0x75,  0xAA,  0x36,  0xA2,  0x42,  0xFE,  0x34,  0x84,  0xFE,  0x44,  0x88,  0x7E,  0x86, 	/* 10920 */
+	0x27,  0xC2,  0x44,  0x27,  0xC6,  0xA8,  0x77,  0xCA,  0x28,  0x2F,  0xE2,  0x54,  0x55,  0x64,  0xB9,  0x8D, 	/* 10930 */
+	0x60,  0x10,  0x8D,  0x29,  0x23,  0x54,  0x2B,  0xA7,  0xEC,  0x6B,  0xAB,  0xEE,  0xAB,  0xA3,  0x10,  0x2F, 	/* 10940 */
+	0xE4,  0x58,  0x49,  0x48,  0x10,  0x90,  0x21,  0x02,  0x1C,  0x21,  0x06,  0xFE,  0x69,  0x0B,  0xFE,  0xAD, 	/* 10950 */
+	0x42,  0xFC,  0x3D,  0x44,  0xFE,  0x4A,  0xA9,  0x7F,  0x9B,  0x2E,  0xE2,  0xAA,  0x2E,  0xE6,  0xAA,  0x7E, 	/* 10960 */
+	0xEA,  0x92,  0xAF,  0xE2,  0xD6,  0x3F,  0xE4,  0xBA,  0x4D,  0x68,  0x92,  0xA8,  0x3F,  0xC5,  0xD4,  0x55, 	/* 10970 */
+	0x4F,  0xFE,  0x91,  0x2F,  0xFC,  0x3B,  0x85,  0x54,  0xFF,  0xE4,  0x44,  0x9B,  0x26,  0x0C,  0xAA,  0x00, 	/* 10980 */
+	0xC3,  0xF0,  0x25,  0x02,  0x50,  0x25,  0x02,  0x50,  0x24,  0x82,  0x48,  0x24,  0x84,  0x44,  0x44,  0x48, 	/* 10990 */
+	0x42,  0xAC,  0x0C,  0x07,  0x3E,  0x46,  0xA5,  0x6A,  0x57,  0xE5,  0x60,  0x56,  0x05,  0x62,  0x55,  0xE5, 	/* 109A0 */
+	0x20,  0x51,  0x89,  0x07,  0xAD,  0x03,  0x87,  0xD0,  0x28,  0x84,  0x48,  0x7F,  0xC0,  0x44,  0xFF,  0xE0, 	/* 109B0 */
+	0x44,  0x7F,  0xC0,  0x40,  0x04,  0x00,  0xC0,  0xB0,  0x01,  0xC7,  0xE8,  0x24,  0x42,  0x24,  0x5F,  0xC8, 	/* 109C0 */
+	0x80,  0xFF,  0xE1,  0x00,  0x1F,  0x82,  0x90,  0x47,  0x0B,  0x8E,  0xB2,  0x03,  0xC3,  0xC8,  0x24,  0x44, 	/* 109D0 */
+	0x24,  0xBF,  0x82,  0x08,  0x3F,  0xC2,  0x04,  0x3F,  0xE2,  0xAA,  0x55,  0x2A,  0x0C,  0xB5,  0x03,  0xCF, 	/* 109E0 */
+	0xC8,  0x25,  0x0F,  0xFE,  0x91,  0x2F,  0xFE,  0x48,  0x87,  0xFE,  0x4C,  0x87,  0xA8,  0x58,  0x8E,  0x58, 	/* 109F0 */
+	0xB6,  0x0A,  0x00,  0x90,  0x10,  0x82,  0x04,  0xD1,  0x21,  0x12,  0x09,  0x00,  0xA0,  0x04,  0x00,  0xA0, 	/* 10A00 */
+	0x31,  0x8C,  0x06,  0xBA,  0x0B,  0x03,  0x0C,  0xC9,  0x20,  0x60,  0x39,  0xCF,  0xFE,  0x49,  0x47,  0x98, 	/* 10A10 */
+	0x49,  0x47,  0xD2,  0xC9,  0xC0,  0x90,  0xBB,  0x01,  0x03,  0x20,  0x0C,  0x00,  0xB0,  0x30,  0x8C,  0x00, 	/* 10A20 */
+	0x11,  0x01,  0x10,  0x2A,  0x00,  0x40,  0x1B,  0x0E,  0x0E,  0xBC,  0x13,  0xC1,  0x24,  0xD2,  0x43,  0x24, 	/* 10A30 */
+	0x2B,  0xC4,  0x24,  0x8A,  0x44,  0xBC,  0x32,  0x42,  0xA4,  0x42,  0x48,  0x7E,  0xBD,  0x04,  0x0F,  0xFE, 	/* 10A40 */
+	0x04,  0x09,  0x52,  0x64,  0xC9,  0x52,  0x64,  0xC9,  0x52,  0x0A,  0x01,  0x10,  0x20,  0x8C,  0x06,  0xBE, 	/* 10A50 */
+	0x00,  0x0F,  0xFE,  0x24,  0x84,  0x44,  0xFF,  0xEC,  0xE6,  0xB5,  0xAC,  0xE6,  0xCE,  0x6B,  0x5A,  0xCE, 	/* 10A60 */
+	0x68,  0x46,  0xBF,  0x08,  0x40,  0x84,  0x08,  0x40,  0x84,  0x0F,  0xC0,  0x04,  0x3F,  0xC0,  0x44,  0x04, 	/* 10A70 */
+	0x40,  0x44,  0x08,  0x43,  0x04,  0x80,  0x11,  0x05,  0x10,  0x51,  0x05,  0xFE,  0x71,  0x01,  0x38,  0xF3, 	/* 10A80 */
+	0x85,  0x54,  0x55,  0x49,  0x92,  0x11,  0x01,  0x10,  0x86,  0x11,  0x05,  0xFE,  0x55,  0x45,  0x54,  0xFB, 	/* 10A90 */
+	0xA1,  0xFE,  0xF1,  0x05,  0xFE,  0x56,  0xA5,  0x7A,  0x94,  0x21,  0x7E,  0x87,  0x12,  0x01,  0x20,  0x12, 	/* 10AA0 */
+	0x01,  0xFC,  0x10,  0x01,  0x00,  0x1F,  0x81,  0x10,  0x21,  0x02,  0x10,  0x41,  0x08,  0x10,  0x88,  0x50, 	/* 10AB0 */
+	0x05,  0x7E,  0x54,  0x05,  0x40,  0x7F,  0xC4,  0x44,  0x76,  0x45,  0x68,  0x55,  0x85,  0x58,  0x9A,  0x49, 	/* 10AC0 */
+	0x42,  0x8B,  0x51,  0x45,  0x1E,  0x5F,  0x45,  0x18,  0x72,  0xA4,  0xC6,  0x72,  0x45,  0x3E,  0x5E,  0x45, 	/* 10AD0 */
+	0x1A,  0x96,  0x69,  0x02,  0x8C,  0x50,  0x85,  0x10,  0x57,  0xE7,  0xD2,  0x47,  0xE4,  0x52,  0x7F,  0xE4, 	/* 10AE0 */
+	0xA8,  0x4A,  0x84,  0xFE,  0x88,  0x88,  0x88,  0x92,  0x55,  0x45,  0x54,  0x5F,  0xE5,  0x54,  0x75,  0xC4, 	/* 10AF0 */
+	0x40,  0x77,  0xE5,  0x10,  0x5F,  0xE5,  0x38,  0x5D,  0x6B,  0x10,  0x98,  0x51,  0x05,  0xFE,  0x51,  0x05, 	/* 10B00 */
+	0xFE,  0x79,  0x24,  0xFE,  0x74,  0x45,  0x7C,  0x54,  0x45,  0x7C,  0x92,  0x49,  0xC2,  0x99,  0x00,  0x01, 	/* 10B10 */
+	0xFC,  0x11,  0x01,  0x10,  0x11,  0x0F,  0xFE,  0x03,  0x00,  0x50,  0x09,  0x03,  0x10,  0xC1,  0x00,  0x30, 	/* 10B20 */
+	0x9B,  0x04,  0x02,  0x40,  0x24,  0x03,  0xFC,  0x44,  0x08,  0x40,  0x04,  0x0F,  0xFE,  0x04,  0x00,  0x40, 	/* 10B30 */
+	0x04,  0x00,  0x40,  0x9D,  0x12,  0x05,  0x20,  0x52,  0x07,  0xE2,  0x92,  0x49,  0x38,  0x1A,  0x03,  0x20, 	/* 10B40 */
+	0xD2,  0x01,  0x22,  0x12,  0x21,  0x1E,  0x9F,  0x08,  0x00,  0x90,  0x10,  0x87,  0xFC,  0x24,  0x43,  0xFC, 	/* 10B50 */
+	0x44,  0x08,  0x40,  0xFF,  0xE0,  0x40,  0x04,  0x00,  0x40,  0xA1,  0x11,  0x05,  0x10,  0x51,  0x07,  0x90, 	/* 10B60 */
+	0x97,  0xE1,  0x10,  0x19,  0x0F,  0x10,  0x11,  0x01,  0x10,  0x11,  0x01,  0xFF,  0xA2,  0x04,  0x0F,  0xFE, 	/* 10B70 */
+	0x80,  0x2A,  0x42,  0x24,  0x03,  0xF8,  0x44,  0x04,  0x40,  0xFF,  0xE0,  0x40,  0x04,  0x00,  0x40,  0xA7, 	/* 10B80 */
+	0x12,  0x05,  0x20,  0x52,  0x07,  0xBE,  0x54,  0x49,  0x44,  0x1A,  0x83,  0x28,  0xD1,  0x01,  0x28,  0x14, 	/* 10B90 */
+	0x41,  0x82,  0xA9,  0x24,  0x0A,  0x40,  0xA7,  0xEF,  0x6A,  0xA6,  0xAA,  0xAA,  0x3A,  0xAE,  0x4A,  0x25, 	/* 10BA0 */
+	0x22,  0x92,  0x22,  0x22,  0x4C,  0xB2,  0x21,  0x0A,  0x50,  0xA5,  0x0F,  0x7E,  0xA9,  0x0A,  0x90,  0x31, 	/* 10BB0 */
+	0x0E,  0x7C,  0x21,  0x02,  0x10,  0x21,  0x02,  0xFE,  0xB4,  0x20,  0xCA,  0x70,  0xA5,  0x0F,  0x50,  0xA5, 	/* 10BC0 */
+	0x02,  0x7E,  0x34,  0x8E,  0x48,  0x24,  0xA2,  0xE6,  0x20,  0x62,  0xF2,  0xB9,  0x20,  0x8A,  0x7E,  0xA0, 	/* 10BD0 */
+	0x8F,  0x88,  0xAF,  0xFA,  0x04,  0x37,  0xEE,  0x24,  0x21,  0x42,  0x04,  0x20,  0x42,  0x0C,  0xBD,  0x04, 	/* 10BE0 */
+	0x0F,  0xFE,  0x05,  0x01,  0xA0,  0xFF,  0xE8,  0x92,  0x9E,  0xA2,  0x40,  0x3F,  0x84,  0x40,  0xFF,  0xE0, 	/* 10BF0 */
+	0x40,  0xBE,  0x20,  0x0A,  0xFE,  0xA1,  0x0F,  0xFC,  0xA2,  0x42,  0x24,  0x3F,  0xFE,  0x00,  0x27,  0xE2, 	/* 10C00 */
+	0x42,  0x24,  0x22,  0x7E,  0x80,  0x00,  0x07,  0xFE,  0x40,  0x27,  0xFE,  0x5E,  0xE4,  0x20,  0x5E,  0xE5, 	/* 10C10 */
+	0x20,  0x5F,  0xCA,  0x20,  0x9F,  0xE0,  0x20,  0x81,  0x7C,  0x21,  0x12,  0xFD,  0x23,  0x92,  0x55,  0x29, 	/* 10C20 */
+	0x06,  0x24,  0x03,  0xFC,  0x44,  0x0F,  0xFE,  0x04,  0x00,  0x40,  0x82,  0x7A,  0x01,  0x3E,  0xFE,  0xA3, 	/* 10C30 */
+	0xAA,  0x55,  0x29,  0x26,  0x24,  0x03,  0xFC,  0x44,  0x0F,  0xFE,  0x04,  0x00,  0x40,  0x87,  0x24,  0x03, 	/* 10C40 */
+	0xFC,  0x44,  0x0F,  0xFE,  0x04,  0x01,  0x48,  0x52,  0x87,  0xBE,  0x94,  0x8F,  0xBF,  0x10,  0x81,  0x08, 	/* 10C50 */
+	0x92,  0x21,  0x0A,  0xFE,  0xA7,  0xCF,  0x44,  0xA7,  0xC2,  0x00,  0x3F,  0xEE,  0x82,  0x2B,  0xA2,  0xAA, 	/* 10C60 */
+	0x2B,  0xA2,  0x86,  0x96,  0x11,  0x05,  0x54,  0xAA,  0x84,  0x44,  0xFF,  0xEA,  0x42,  0x3F,  0xC4,  0x40, 	/* 10C70 */
+	0xFF,  0xE0,  0x40,  0x04,  0x00,  0x40,  0xA0,  0x22,  0x8A,  0xFE,  0xA1,  0x0F,  0x7E,  0xA1,  0x0A,  0xFE, 	/* 10C80 */
+	0x34,  0xAE,  0xFE,  0x24,  0xA2,  0xE5,  0x25,  0xB2,  0xC1,  0xA2,  0x21,  0x0A,  0xFE,  0xA1,  0x0F,  0xFE, 	/* 10C90 */
+	0xA9,  0x2A,  0xFE,  0x34,  0x4E,  0x7C,  0x24,  0x42,  0x7C,  0x22,  0x42,  0xC2,  0xA7,  0x22,  0x8A,  0xFE, 	/* 10CA0 */
+	0xA1,  0x0F,  0x7C,  0xA1,  0x0A,  0xFE,  0x34,  0xAE,  0xFF,  0x2C,  0xA3,  0x64,  0x22,  0xE2,  0xD2,  0xAC, 	/* 10CB0 */
+	0x04,  0x00,  0x48,  0x04,  0x40,  0x40,  0xFF,  0xE0,  0x40,  0x0A,  0x00,  0xA0,  0x11,  0x01,  0x10,  0x20, 	/* 10CC0 */
+	0x8C,  0x06,  0xAF,  0x90,  0x06,  0x7C,  0x44,  0x4A,  0x44,  0x24,  0x42,  0x44,  0x65,  0x8A,  0x40,  0x24, 	/* 10CD0 */
+	0x02,  0x42,  0x24,  0x2C,  0x3E,  0xB2,  0x90,  0x86,  0x08,  0x40,  0x8A,  0xFE,  0x20,  0x82,  0x18,  0x61, 	/* 10CE0 */
+	0x8A,  0x28,  0x24,  0x82,  0x88,  0xC0,  0x84,  0x18,  0xB6,  0x11,  0x01,  0x14,  0x91,  0x25,  0x10,  0x1F, 	/* 10CF0 */
+	0xE1,  0x10,  0x31,  0x05,  0x28,  0x92,  0x81,  0x44,  0x18,  0x41,  0x02,  0xB9,  0x92,  0x86,  0x24,  0x42, 	/* 10D00 */
+	0x0B,  0xFE,  0x22,  0x02,  0x60,  0x66,  0x0A,  0x60,  0x26,  0x02,  0xA2,  0xCA,  0x25,  0x1E,  0x82,  0x90, 	/* 10D10 */
+	0x05,  0xFE,  0x21,  0x06,  0x10,  0xA1,  0x02,  0xFC,  0x31,  0x06,  0x10,  0xA1,  0x02,  0x10,  0x21,  0x0C, 	/* 10D20 */
+	0xFE,  0x83,  0x90,  0x06,  0xF8,  0x44,  0x8A,  0x48,  0x24,  0x82,  0xFE,  0x64,  0x8A,  0x48,  0x24,  0x82, 	/* 10D30 */
+	0x48,  0xC4,  0x85,  0xFE,  0x84,  0x91,  0x06,  0x10,  0x41,  0x2A,  0x52,  0x25,  0x42,  0x90,  0x69,  0x0A, 	/* 10D40 */
+	0x10,  0x22,  0x82,  0x28,  0xC4,  0x45,  0x82,  0x86,  0x91,  0x06,  0x10,  0x4F,  0xEA,  0x92,  0x29,  0x22, 	/* 10D50 */
+	0x92,  0x6F,  0xEA,  0x10,  0x21,  0x02,  0x10,  0xC1,  0x04,  0x10,  0x8E,  0x90,  0x06,  0xFE,  0x49,  0x2A, 	/* 10D60 */
+	0x92,  0x2F,  0xE2,  0x92,  0x69,  0x2A,  0xFE,  0x21,  0x02,  0x10,  0xC1,  0x04,  0x10,  0x90,  0xA0,  0xC6, 	/* 10D70 */
+	0xF0,  0x4A,  0x8A,  0xA8,  0x2A,  0x82,  0xA8,  0x6A,  0x8A,  0xA8,  0x2A,  0x82,  0xB4,  0x2B,  0xCD,  0x62, 	/* 10D80 */
+	0x92,  0x92,  0x86,  0x28,  0x4F,  0xEA,  0x2A,  0x2F,  0xE2,  0xA8,  0x2F,  0xF6,  0x29,  0xA2,  0x92,  0x4B, 	/* 10D90 */
+	0xC4,  0x84,  0x88,  0x97,  0x94,  0x06,  0x40,  0x47,  0xEA,  0x82,  0x28,  0x23,  0x7A,  0x64,  0xAA,  0x4A, 	/* 10DA0 */
+	0x27,  0xA2,  0x02,  0x20,  0x2C,  0x0C,  0x99,  0x90,  0x06,  0x7C,  0x44,  0x4A,  0x44,  0x27,  0xC2,  0x44, 	/* 10DB0 */
+	0x64,  0x4A,  0x7C,  0x24,  0x42,  0x44,  0x24,  0x4D,  0xFE,  0x9B,  0x91,  0x06,  0x20,  0x47,  0xEA,  0x42, 	/* 10DC0 */
+	0x24,  0x22,  0x42,  0x67,  0xEA,  0x42,  0x24,  0x22,  0x42,  0x27,  0xEC,  0x42,  0xA0,  0x90,  0x06,  0x7C, 	/* 10DD0 */
+	0x44,  0x4A,  0x7C,  0x24,  0x42,  0x7C,  0x64,  0x2A,  0x64,  0x25,  0x82,  0x48,  0xC7,  0x44,  0xC2,  0xA1, 	/* 10DE0 */
+	0x91,  0x06,  0x10,  0x5F,  0xEA,  0x28,  0x24,  0x42,  0xC6,  0x74,  0x4A,  0x28,  0x21,  0x02,  0x28,  0xC4, 	/* 10DF0 */
+	0x45,  0x82,  0xA2,  0x92,  0x06,  0x3C,  0x42,  0x4A,  0x6C,  0x29,  0x82,  0x24,  0x64,  0x2B,  0xBD,  0x22, 	/* 10E00 */
+	0x42,  0x24,  0xC2,  0x44,  0x3C,  0xA9,  0x91,  0x06,  0xFE,  0x48,  0x2A,  0x8A,  0x20,  0x83,  0xFE,  0x60, 	/* 10E10 */
+	0x8A,  0x48,  0x22,  0x82,  0x08,  0x20,  0x8C,  0x18,  0xAC,  0x92,  0x06,  0x20,  0x42,  0x0B,  0xFC,  0x32, 	/* 10E20 */
+	0x43,  0x24,  0x7F,  0xCA,  0x20,  0x22,  0x82,  0x24,  0x23,  0xED,  0xC2,  0xAD,  0x92,  0x05,  0x20,  0x2F, 	/* 10E30 */
+	0xC7,  0x24,  0xAA,  0x82,  0xA0,  0x3F,  0xE6,  0x20,  0xA2,  0x02,  0x50,  0x28,  0x8D,  0x06,  0xB7,  0x97, 	/* 10E40 */
+	0xE6,  0x42,  0x47,  0xEA,  0x00,  0x27,  0xE2,  0x42,  0x67,  0xEA,  0x42,  0x27,  0xE2,  0x42,  0xC4,  0x24, 	/* 10E50 */
+	0x46,  0xB8,  0x90,  0x05,  0xFE,  0x29,  0x26,  0xFE,  0xA9,  0x22,  0x92,  0x3F,  0xE6,  0x10,  0xA7,  0xC2, 	/* 10E60 */
+	0x10,  0x21,  0x0D,  0xFF,  0xB9,  0x92,  0x06,  0x20,  0x5F,  0xEA,  0x20,  0x2A,  0x82,  0xA8,  0x77,  0x4A, 	/* 10E70 */
+	0x22,  0x25,  0x02,  0x50,  0xC8,  0x85,  0x06,  0xBC,  0x92,  0x06,  0x20,  0x4F,  0xCA,  0x84,  0x2F,  0xC2, 	/* 10E80 */
+	0x84,  0x6F,  0xCA,  0xA4,  0x29,  0x82,  0x88,  0x2E,  0x4D,  0x82,  0xBD,  0x90,  0x06,  0x7C,  0x44,  0x4A, 	/* 10E90 */
+	0x44,  0x27,  0xC2,  0x44,  0x67,  0xCA,  0x44,  0x24,  0x42,  0x7C,  0x22,  0x4C,  0xC2,  0x8A,  0x92,  0x06, 	/* 10EA0 */
+	0x40,  0x4D,  0xCA,  0x84,  0x2D,  0xC2,  0x84,  0x6F,  0xCA,  0x50,  0x25,  0x02,  0x50,  0xC9,  0x25,  0x0E, 	/* 10EB0 */
+	0x96,  0x97,  0xC6,  0x44,  0x47,  0xCA,  0x44,  0x27,  0xC2,  0x00,  0x6F,  0xEA,  0x82,  0x2F,  0xE2,  0x82, 	/* 10EC0 */
+	0xC8,  0x24,  0xFE,  0x97,  0x92,  0x06,  0xFC,  0x42,  0x0A,  0x50,  0x28,  0x83,  0xFE,  0x60,  0x4A,  0xF4, 	/* 10ED0 */
+	0x29,  0x42,  0xF4,  0xC0,  0x44,  0x0C,  0x9B,  0x90,  0x05,  0x7C,  0x20,  0x86,  0x10,  0xAF,  0xE2,  0x10, 	/* 10EE0 */
+	0x31,  0x06,  0x30,  0xAF,  0xE2,  0xAA,  0x2A,  0xAD,  0xFF,  0x9C,  0x91,  0x06,  0xFC,  0x41,  0x0A,  0xFC, 	/* 10EF0 */
+	0x21,  0x03,  0xFE,  0x69,  0x4A,  0x94,  0x2F,  0xC2,  0x84,  0xC8,  0x44,  0x8C,  0x9D,  0x91,  0x06,  0xFE, 	/* 10F00 */
+	0x44,  0x4A,  0x44,  0x26,  0xA2,  0xB2,  0x71,  0x0A,  0xFE,  0x21,  0x02,  0x10,  0xC1,  0x04,  0x10,  0x9F, 	/* 10F10 */
+	0x9A,  0x26,  0x52,  0x45,  0x4A,  0x00,  0x27,  0xC2,  0x54,  0x67,  0xCA,  0x54,  0x27,  0xC2,  0x95,  0x29, 	/* 10F20 */
+	0x3D,  0x11,  0xA5,  0x90,  0x06,  0xFC,  0x4A,  0x4A,  0xFC,  0x2A,  0x42,  0xFC,  0x60,  0x0B,  0xFE,  0x25, 	/* 10F30 */
+	0x42,  0x48,  0xC7,  0x45,  0x82,  0xA9,  0x90,  0x06,  0xFC,  0x48,  0x4A,  0xFC,  0x28,  0x42,  0xFC,  0x65, 	/* 10F40 */
+	0x0A,  0xFE,  0x31,  0x02,  0x7C,  0xC1,  0x05,  0xFE,  0xAA,  0x92,  0x05,  0xFC,  0x22,  0x86,  0x30,  0xBF, 	/* 10F50 */
+	0xE2,  0x20,  0x67,  0xCA,  0xC4,  0x37,  0xC2,  0x44,  0x24,  0x4C,  0x7C,  0xAB,  0x94,  0x45,  0xFE,  0x24, 	/* 10F60 */
+	0x86,  0x48,  0xAF,  0xE2,  0x92,  0x39,  0x26,  0xFE,  0xA9,  0x22,  0x92,  0x2F,  0xEC,  0x00,  0xAE,  0x10, 	/* 10F70 */
+	0x8F,  0xCC,  0x10,  0xAF,  0xC8,  0xCF,  0xEB,  0x48,  0xFC,  0x89,  0x54,  0xFD,  0x49,  0x52,  0x96,  0x29, 	/* 10F80 */
+	0x41,  0xAF,  0x91,  0x06,  0x92,  0x49,  0x2A,  0xFE,  0x20,  0x03,  0xFE,  0x61,  0x0A,  0xFE,  0x2A,  0xA2, 	/* 10F90 */
+	0xAA,  0xCA,  0xA4,  0x86,  0xB4,  0x94,  0x06,  0x7C,  0x44,  0x4A,  0xFE,  0x3A,  0x02,  0xBE,  0x6C,  0x8A, 	/* 10FA0 */
+	0xC8,  0x2B,  0xE2,  0x88,  0xC9,  0x44,  0xA2,  0xB6,  0x94,  0x46,  0x28,  0x4F,  0xEA,  0x28,  0x2F,  0xE2, 	/* 10FB0 */
+	0xAA,  0x6A,  0xAA,  0xCE,  0x28,  0x22,  0xFE,  0x28,  0x2C,  0xFE,  0xB7,  0x44,  0x82,  0x8C,  0xFE,  0xA2, 	/* 10FC0 */
+	0x88,  0xFF,  0xEB,  0x48,  0xB4,  0x8D,  0xC8,  0x85,  0x4F,  0xD4,  0x86,  0x2F,  0xC1,  0xBE,  0x97,  0xC6, 	/* 10FD0 */
+	0x44,  0x45,  0xCA,  0x54,  0x3F,  0xF3,  0x7D,  0x64,  0x5A,  0x7C,  0x24,  0x42,  0x7C,  0xC4,  0x44,  0x4C, 	/* 10FE0 */
+	0xBF,  0x91,  0x06,  0xFE,  0x41,  0x0B,  0xFF,  0x27,  0xC2,  0x44,  0x67,  0xCA,  0x32,  0x25,  0x23,  0xCC, 	/* 10FF0 */
+	0x25,  0x4C,  0xE2,  0x84,  0x96,  0x45,  0x06,  0x2F,  0x56,  0x04,  0xAE,  0xF2,  0x04,  0x2E,  0x46,  0x04, 	/* 11000 */
+	0xAE,  0xC2,  0xAA,  0x2F,  0x2C,  0x21,  0x85,  0x90,  0x05,  0x7E,  0x2C,  0x86,  0xBE,  0xAA,  0xA2,  0xEA, 	/* 11010 */
+	0x38,  0xA6,  0xEA,  0xAA,  0xA2,  0xAE,  0x2E,  0x8C,  0x08,  0x8E,  0x50,  0xE5,  0x72,  0x70,  0xC1,  0x70, 	/* 11020 */
+	0xFF,  0xE5,  0x48,  0x51,  0x89,  0x48,  0xFF,  0xE0,  0xA0,  0x39,  0x8C,  0x06,  0x8F,  0x92,  0x86,  0xFE, 	/* 11030 */
+	0x42,  0x8A,  0x7C,  0x34,  0x42,  0xFC,  0x67,  0xCA,  0x10,  0x2F,  0xE2,  0x30,  0xC4,  0x85,  0x86,  0x97, 	/* 11040 */
+	0x9F,  0xF6,  0x80,  0x4D,  0x4A,  0xA8,  0x2F,  0xF2,  0xA5,  0x6D,  0x4A,  0xD4,  0x2F,  0x62,  0xA6,  0xD2, 	/* 11050 */
+	0x95,  0x49,  0xA3,  0x25,  0x09,  0x54,  0x49,  0x2F,  0x90,  0xAF,  0xEF,  0x90,  0xA9,  0x0F,  0x98,  0x02, 	/* 11060 */
+	0x8F,  0xA4,  0x8C,  0x4F,  0x82,  0xA8,  0x9F,  0xE6,  0xAA,  0x4F,  0xEA,  0x80,  0x2F,  0xE3,  0x22,  0x6F, 	/* 11070 */
+	0xAA,  0xAA,  0x2F,  0xA2,  0x2A,  0xC3,  0xA5,  0xCC,  0xAA,  0x91,  0x06,  0x28,  0x47,  0xCB,  0x83,  0x2F, 	/* 11080 */
+	0xE2,  0xD6,  0x6B,  0xAA,  0xFE,  0x24,  0x42,  0x7C,  0xC4,  0x44,  0x7C,  0xB0,  0x91,  0x06,  0xFF,  0x49, 	/* 11090 */
+	0x1A,  0xAA,  0x32,  0x52,  0x1C,  0x6F,  0xEA,  0xAA,  0x3F,  0xF2,  0x10,  0xC1,  0x04,  0x30,  0xB2,  0x94, 	/* 110A0 */
+	0x87,  0xFE,  0x45,  0x0A,  0x88,  0x2F,  0xE3,  0x90,  0x6F,  0xEA,  0x90,  0x2F,  0xE2,  0x48,  0xC3,  0x05, 	/* 110B0 */
+	0xCE,  0xB5,  0x95,  0x46,  0xA8,  0x45,  0x4A,  0xFE,  0x2A,  0xA2,  0x92,  0x6A,  0xAA,  0xFE,  0x2D,  0xA2, 	/* 110C0 */
+	0xB6,  0xCD,  0xB5,  0xB1,  0xB8,  0xEE,  0x8A,  0xAC,  0xEE,  0xA7,  0xC8,  0x57,  0xE7,  0xC8,  0x54,  0x87, 	/* 110D0 */
+	0xC8,  0x00,  0xCF,  0xD4,  0x46,  0x27,  0xC1,  0xBA,  0xA8,  0x06,  0x9E,  0x5E,  0xAC,  0x8A,  0x7F,  0x66, 	/* 110E0 */
+	0xBE,  0x7F,  0x2C,  0x9E,  0x5D,  0x26,  0xBE,  0x48,  0xCC,  0xB2,  0xBB,  0x38,  0x82,  0x0C,  0x7C,  0xA5, 	/* 110F0 */
+	0x3E,  0x5C,  0x84,  0x08,  0x5C,  0x85,  0x4C,  0x7D,  0x46,  0x52,  0xBE,  0x2A,  0x41,  0x84,  0x04,  0x00, 	/* 11100 */
+	0x40,  0xFF,  0xE0,  0x80,  0x09,  0x01,  0x10,  0x72,  0x00,  0xC0,  0x05,  0x00,  0x88,  0x1F,  0xCE,  0x04, 	/* 11110 */
+	0x87,  0x04,  0x0F,  0xFE,  0x04,  0x04,  0x92,  0x26,  0x42,  0x94,  0x5F,  0x20,  0x50,  0xFF,  0xE0,  0x40, 	/* 11120 */
+	0x04,  0x00,  0x40,  0x89,  0x00,  0x07,  0xFC,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x3F,  0x80,  0x40, 	/* 11130 */
+	0x05,  0x00,  0x48,  0x04,  0x8F,  0xFE,  0x8B,  0x00,  0x07,  0xFC,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40, 	/* 11140 */
+	0x3F,  0x80,  0x40,  0x04,  0x00,  0x40,  0x04,  0x0F,  0xFE,  0x96,  0x02,  0x0F,  0xA0,  0x23,  0xC2,  0x24, 	/* 11150 */
+	0xF4,  0x42,  0x48,  0x28,  0x82,  0x18,  0x39,  0x4C,  0x24,  0x04,  0x21,  0x82,  0xA9,  0x00,  0x00,  0xFC, 	/* 11160 */
+	0xF0,  0x02,  0x00,  0x20,  0x0F,  0xFE,  0x25,  0x02,  0x50,  0x35,  0x0C,  0x90,  0x11,  0x22,  0x0E,  0xB2, 	/* 11170 */
+	0x02,  0x00,  0x20,  0xF3,  0x02,  0x48,  0x2F,  0xCF,  0x02,  0x2F,  0xC2,  0x24,  0x2A,  0x43,  0x38,  0xC2, 	/* 11180 */
+	0x00,  0x20,  0xB3,  0x02,  0x80,  0x2C,  0xF2,  0xA2,  0x4E,  0x27,  0x82,  0xC8,  0xF4,  0x82,  0x48,  0x24, 	/* 11190 */
+	0x43,  0x46,  0xC4,  0x60,  0x42,  0xBB,  0x01,  0x00,  0x10,  0xFF,  0xE2,  0x94,  0x29,  0x0F,  0xFC,  0x2A, 	/* 111A0 */
+	0x42,  0xA4,  0x39,  0x8D,  0x18,  0x12,  0x42,  0xC2,  0x80,  0x01,  0x00,  0x20,  0xF7,  0xE2,  0x42,  0x24, 	/* 111B0 */
+	0x22,  0x42,  0xF7,  0xE2,  0x42,  0x24,  0x23,  0x42,  0xC4,  0x20,  0x7E,  0x82,  0x00,  0x00,  0xFE,  0xF0, 	/* 111C0 */
+	0x42,  0x74,  0x25,  0x42,  0x54,  0xF5,  0x42,  0x74,  0x20,  0x43,  0x04,  0xC0,  0x40,  0x0C,  0x88,  0x08, 	/* 111D0 */
+	0x00,  0x80,  0xE8,  0xE5,  0xEA,  0x4A,  0xA4,  0xAA,  0xEA,  0xA4,  0xAA,  0x4A,  0xA7,  0x2A,  0x92,  0xE2, 	/* 111E0 */
+	0x60,  0x8A,  0x00,  0x0F,  0xFE,  0x2A,  0xA2,  0xAA,  0xFA,  0xA2,  0xAA,  0x2F,  0xF2,  0xAA,  0x3A,  0xAC, 	/* 111F0 */
+	0xAA,  0x0A,  0xA0,  0x86,  0x8D,  0x01,  0x0F,  0x90,  0x22,  0x82,  0x44,  0xF8,  0xA2,  0x31,  0x2C,  0x42, 	/* 11200 */
+	0x1A,  0x36,  0x4E,  0x08,  0x03,  0x00,  0xC0,  0x8E,  0x04,  0x0F,  0x40,  0x27,  0xE2,  0x90,  0x31,  0x0F, 	/* 11210 */
+	0x18,  0x25,  0x42,  0x54,  0x39,  0x2D,  0x12,  0x01,  0x00,  0x30,  0x9E,  0x02,  0x00,  0x3C,  0xF2,  0x42, 	/* 11220 */
+	0x64,  0x29,  0x82,  0x14,  0xF2,  0x22,  0xFD,  0x22,  0x43,  0x24,  0xC2,  0x40,  0x3C,  0xA0,  0x01,  0x0F, 	/* 11230 */
+	0x50,  0x25,  0x02,  0x7C,  0x29,  0x0F,  0x90,  0x2F,  0xE2,  0x18,  0x33,  0x4C,  0x52,  0x19,  0x00,  0x10, 	/* 11240 */
+	0xA5,  0x00,  0x00,  0xFE,  0xF4,  0x42,  0x44,  0x27,  0xC2,  0x44,  0xF7,  0xC2,  0x44,  0x24,  0x43,  0x7C, 	/* 11250 */
+	0xDC,  0x40,  0x04,  0xAA,  0x01,  0x0F,  0x10,  0x2F,  0xC2,  0x10,  0xF1,  0x02,  0xFE,  0x21,  0x02,  0x10, 	/* 11260 */
+	0x3F,  0xCE,  0x10,  0x01,  0x01,  0xFE,  0xAD,  0x02,  0x0F,  0x3E,  0x2A,  0x82,  0xA8,  0x2A,  0x8F,  0xBE, 	/* 11270 */
+	0x2A,  0x82,  0xA8,  0x22,  0x83,  0x48,  0xE4,  0x80,  0x9E,  0xAE,  0x1F,  0xEF,  0x02,  0x57,  0xE5,  0x12, 	/* 11280 */
+	0x57,  0xEF,  0x56,  0x55,  0x65,  0x56,  0x75,  0x69,  0x12,  0x21,  0x12,  0x11,  0xB1,  0x02,  0x40,  0x94, 	/* 11290 */
+	0xF5,  0x42,  0x48,  0x21,  0x02,  0x20,  0xFF,  0xE2,  0x48,  0x24,  0x83,  0xF0,  0xC2,  0x80,  0xC4,  0xB8, 	/* 112A0 */
+	0x00,  0x00,  0xFE,  0xF1,  0x02,  0x7C,  0x22,  0x42,  0x24,  0xFF,  0xF2,  0x00,  0x27,  0xE3,  0x42,  0xC4, 	/* 112B0 */
+	0x20,  0x7E,  0xBE,  0x07,  0xEF,  0xC2,  0x27,  0xE2,  0x42,  0x27,  0xEF,  0xC2,  0x27,  0xE2,  0x28,  0x32, 	/* 112C0 */
+	0x8C,  0x49,  0x08,  0x93,  0x07,  0x83,  0x01,  0x0F,  0x18,  0x21,  0x42,  0xFE,  0xF1,  0x02,  0x92,  0x27, 	/* 112D0 */
+	0xC2,  0x38,  0x35,  0x4E,  0x93,  0x01,  0x00,  0x30,  0x85,  0x01,  0x00,  0x20,  0xF7,  0xC2,  0x44,  0x27, 	/* 112E0 */
+	0xC2,  0x44,  0xF7,  0xC2,  0x52,  0x25,  0x43,  0x48,  0xC7,  0x40,  0xC2,  0x86,  0x00,  0x00,  0xFE,  0xF9, 	/* 112F0 */
+	0x22,  0xFE,  0x29,  0x2F,  0x92,  0x2F,  0xE2,  0x10,  0x27,  0xC3,  0x10,  0xC1,  0x01,  0xFF,  0x89,  0x02, 	/* 11300 */
+	0x0F,  0xFC,  0x22,  0x02,  0x48,  0x3F,  0xCF,  0x04,  0x2A,  0x82,  0xA8,  0x3A,  0x8C,  0xAA,  0x12,  0xA2, 	/* 11310 */
+	0x06,  0xA2,  0x00,  0x00,  0xFE,  0xF1,  0x02,  0x30,  0x2C,  0xAF,  0x1C,  0x22,  0x82,  0xCC,  0x31,  0xAC, 	/* 11320 */
+	0x69,  0x18,  0x80,  0x30,  0xA5,  0x01,  0x00,  0x1C,  0xF1,  0x02,  0xFE,  0x2A,  0x22,  0xFC,  0xFA,  0x02, 	/* 11330 */
+	0xBE,  0x2A,  0x83,  0x28,  0xD4,  0xA2,  0x86,  0xB2,  0x02,  0x80,  0x28,  0xFE,  0xE2,  0x28,  0x22,  0x82, 	/* 11340 */
+	0xEE,  0xF2,  0x82,  0x28,  0x2E,  0xF3,  0x28,  0xC4,  0x80,  0x88,  0xB3,  0x04,  0x4E,  0x44,  0x5F,  0xF4, 	/* 11350 */
+	0x44,  0x4E,  0xEE,  0xEE,  0x4D,  0xD5,  0x54,  0x55,  0x46,  0x44,  0x84,  0x40,  0x44,  0xB4,  0xFB,  0xE2, 	/* 11360 */
+	0x08,  0xFB,  0xE2,  0x08,  0xF7,  0xE0,  0xE0,  0x31,  0x8D,  0xF6,  0x00,  0x03,  0xF8,  0x01,  0x00,  0x60, 	/* 11370 */
+	0xB5,  0x00,  0x0F,  0xBE,  0x20,  0x8F,  0xBE,  0x20,  0x8F,  0xBE,  0x22,  0x43,  0xB8,  0x22,  0x02,  0x22, 	/* 11380 */
+	0x3E,  0x2C,  0x1E,  0xB6,  0xFB,  0xE2,  0x08,  0xFB,  0xE2,  0x08,  0xFB,  0xE0,  0x00,  0x7F,  0xC4,  0x44, 	/* 11390 */
+	0x7F,  0xC4,  0x00,  0x40,  0x23,  0xFE,  0xBA,  0x08,  0x80,  0x48,  0xF3,  0xE2,  0x88,  0x24,  0x82,  0x7E, 	/* 113A0 */
+	0xF0,  0x82,  0x48,  0x29,  0x43,  0x92,  0xD3,  0xE1,  0x02,  0xBF,  0x0F,  0xEF,  0x92,  0x27,  0xC2,  0x10, 	/* 113B0 */
+	0x27,  0xCF,  0x54,  0x27,  0xC2,  0x54,  0x37,  0xCC,  0x10,  0x0F,  0xE0,  0x10,  0x81,  0x00,  0x00,  0xFE, 	/* 113C0 */
+	0xF8,  0x22,  0xBA,  0x28,  0x22,  0xBA,  0xF0,  0x02,  0x7C,  0x24,  0x43,  0x7C,  0xC4,  0x40,  0x7C,  0x95, 	/* 113D0 */
+	0x00,  0x00,  0xFE,  0xFA,  0x22,  0xEE,  0x28,  0x0F,  0x9E,  0x2E,  0x22,  0x8A,  0x38,  0xAC,  0xE4,  0x08, 	/* 113E0 */
+	0xA0,  0x91,  0x99,  0x05,  0x40,  0x54,  0xFA,  0x82,  0x54,  0x25,  0x42,  0xFE,  0xF8,  0xA2,  0xEA,  0x29, 	/* 113F0 */
+	0x23,  0xAA,  0xCC,  0x20,  0xFE,  0x9A,  0x04,  0x0F,  0x5E,  0x45,  0x25,  0xF2,  0x45,  0xEE,  0x52,  0x5F, 	/* 11400 */
+	0x25,  0x3E,  0x73,  0x2D,  0xF2,  0x02,  0x20,  0x46,  0x9B,  0x04,  0x8F,  0xFE,  0x44,  0x84,  0x58,  0x4F, 	/* 11410 */
+	0xCF,  0x94,  0x49,  0x45,  0xFE,  0x71,  0x0C,  0x28,  0x04,  0x41,  0x82,  0x9C,  0x01,  0x00,  0x28,  0xF4, 	/* 11420 */
+	0x42,  0xBA,  0x20,  0x02,  0xEA,  0xFA,  0xA2,  0xF4,  0x2B,  0x43,  0xF4,  0xCA,  0xA0,  0xAA,  0x9E,  0x01, 	/* 11430 */
+	0x00,  0x92,  0xF9,  0x22,  0xFE,  0x20,  0x0F,  0xFE,  0x24,  0x02,  0xFE,  0x3A,  0xAC,  0xAA,  0x0A,  0xA0, 	/* 11440 */
+	0x86,  0x9F,  0x00,  0x0F,  0xBE,  0x20,  0x8F,  0xBE,  0x20,  0x8F,  0xBE,  0x09,  0x01,  0x50,  0x52,  0x45, 	/* 11450 */
+	0x42,  0x98,  0xA6,  0xF8,  0xA0,  0x04,  0x0F,  0x9E,  0x2A,  0xA2,  0xAA,  0x2E,  0xAF,  0x92,  0x22,  0xC2, 	/* 11460 */
+	0xFE,  0x39,  0x2C,  0xFE,  0x09,  0x20,  0xFE,  0xA3,  0x01,  0x00,  0x54,  0xF9,  0x22,  0x7C,  0x24,  0x42, 	/* 11470 */
+	0x7C,  0xF4,  0x42,  0x7C,  0x24,  0x43,  0x7C,  0xC4,  0xC1,  0x82,  0xA4,  0x00,  0x80,  0x1E,  0xF2,  0xA2, 	/* 11480 */
+	0xE4,  0x21,  0x8F,  0x60,  0x27,  0xE2,  0x90,  0x3F,  0xF2,  0x92,  0xC9,  0x20,  0xFE,  0xA9,  0x11,  0x05, 	/* 11490 */
+	0x54,  0x2A,  0x84,  0x44,  0xFF,  0xE8,  0x02,  0x7F,  0xC0,  0x40,  0x3F,  0xC0,  0x50,  0x04,  0x8F,  0xFE, 	/* 114A0 */
+	0xAA,  0x00,  0x00,  0xFE,  0xF9,  0x02,  0xFC,  0x29,  0x02,  0xFC,  0xF9,  0x02,  0xFE,  0x20,  0x23,  0xAA, 	/* 114B0 */
+	0xCA,  0x21,  0x0C,  0xAF,  0x04,  0x00,  0x5C,  0xFF,  0x42,  0xB4,  0x2F,  0x8F,  0xB4,  0x2F,  0x22,  0x92, 	/* 114C0 */
+	0x3D,  0x2C,  0xBC,  0x0F,  0x03,  0x90,  0xB0,  0x01,  0x00,  0x20,  0xFF,  0xC2,  0xA4,  0x2F,  0xCF,  0xA4, 	/* 114D0 */
+	0x2F,  0xC2,  0x54,  0x35,  0xAC,  0x9E,  0x11,  0x26,  0x0E,  0xB3,  0x04,  0x40,  0x28,  0xFF,  0xE2,  0x10, 	/* 114E0 */
+	0x27,  0xCF,  0x10,  0x2F,  0xE2,  0x40,  0x37,  0xEC,  0x90,  0x11,  0x02,  0xFE,  0xB6,  0x00,  0xC0,  0xF2, 	/* 114F0 */
+	0xF1,  0x22,  0x94,  0x24,  0x82,  0xFE,  0xF1,  0x02,  0xFE,  0x21,  0x03,  0x92,  0xC9,  0x20,  0xFE,  0xBE, 	/* 11500 */
+	0x02,  0x80,  0xFE,  0xF2,  0x82,  0xFE,  0x29,  0x22,  0xFE,  0xF1,  0x02,  0xFC,  0x21,  0x03,  0xFC,  0xC1, 	/* 11510 */
+	0x01,  0xFE,  0x83,  0x02,  0x0F,  0xFE,  0x55,  0x45,  0x24,  0x55,  0x4F,  0xFC,  0x42,  0x05,  0xFE,  0x55, 	/* 11520 */
+	0x2F,  0x7A,  0x1C,  0xA1,  0x06,  0x8B,  0x01,  0x00,  0xFE,  0xF2,  0x82,  0xFE,  0x24,  0x42,  0x7C,  0xF4, 	/* 11530 */
+	0x42,  0x7C,  0x21,  0x03,  0xFE,  0xC1,  0x00,  0x10,  0x9E,  0x02,  0x80,  0xAA,  0xFF,  0xF2,  0x28,  0x2F, 	/* 11540 */
+	0xE2,  0x10,  0xFF,  0xE2,  0x10,  0x2F,  0xF3,  0x28,  0xC4,  0x41,  0x82,  0xA2,  0x1F,  0xCE,  0x50,  0x5D, 	/* 11550 */
+	0xC5,  0x54,  0x55,  0x45,  0xDC,  0xE5,  0x05,  0xFC,  0x52,  0x47,  0xFC,  0x92,  0x41,  0xFC,  0xA7,  0x01, 	/* 11560 */
+	0x07,  0xFC,  0x4A,  0x87,  0xFE,  0x41,  0x0B,  0xBC,  0x29,  0x0F,  0xFE,  0x04,  0x07,  0xFC,  0x04,  0x8F, 	/* 11570 */
+	0xFE,  0xB0,  0x1F,  0xCF,  0x54,  0x3F,  0xC2,  0x00,  0xFF,  0xE2,  0x84,  0x2F,  0xC3,  0x64,  0xCD,  0x81, 	/* 11580 */
+	0x48,  0x24,  0x60,  0x40,  0xBD,  0xFF,  0xE4,  0x44,  0xFF,  0xEC,  0xE6,  0xB5,  0xAC,  0xE6,  0xB5,  0xAC, 	/* 11590 */
+	0xE6,  0x04,  0x07,  0xFC,  0x04,  0x8F,  0xFE,  0x8A,  0x03,  0xCF,  0x48,  0x2F,  0xE2,  0xAA,  0x2F,  0xEF, 	/* 115A0 */
+	0x7C,  0x24,  0x42,  0xFC,  0x34,  0x4C,  0x78,  0x19,  0x80,  0xE6,  0x8F,  0x04,  0x81,  0xFE,  0xFA,  0x82, 	/* 115B0 */
+	0xAE,  0x3F,  0x22,  0xEE,  0xFA,  0x82,  0xEE,  0x2A,  0x83,  0xEE,  0xCA,  0x90,  0xA7,  0x94,  0x0E,  0xE0, 	/* 115C0 */
+	0xAA,  0xFE,  0xE2,  0xAA,  0x2E,  0xE2,  0x44,  0xEA,  0xA3,  0xFE,  0x24,  0x83,  0xF0,  0xC2,  0x80,  0xC4, 	/* 115D0 */
+	0x9C,  0x00,  0xC3,  0xF0,  0x25,  0x02,  0x50,  0x25,  0x02,  0x50,  0x24,  0x82,  0x68,  0x25,  0x84,  0x74, 	/* 115E0 */
+	0x79,  0x48,  0x02,  0xA0,  0x20,  0x6F,  0xF8,  0x25,  0x45,  0x54,  0xFD,  0x40,  0x54,  0xFD,  0x44,  0x54, 	/* 115F0 */
+	0x75,  0x49,  0x5C,  0x17,  0x66,  0x8A,  0xA2,  0xF8,  0xE2,  0x74,  0xFD,  0x4A,  0xD4,  0xFD,  0x40,  0x54, 	/* 11600 */
+	0x75,  0x40,  0x54,  0xFD,  0xC7,  0x54,  0xA9,  0xE3,  0x61,  0xA3,  0x42,  0x85,  0xC8,  0xFB,  0xEB,  0xB4, 	/* 11610 */
+	0x5A,  0xCF,  0xBE,  0x5A,  0x8F,  0xA8,  0x5F,  0xE5,  0xA8,  0x5F,  0x8A,  0x08,  0xA6,  0x00,  0x0F,  0xFC, 	/* 11620 */
+	0x10,  0x01,  0x00,  0x1F,  0x01,  0x10,  0x19,  0x01,  0x50,  0x21,  0x22,  0x72,  0x39,  0x2C,  0x0E,  0xA7, 	/* 11630 */
+	0x01,  0x0F,  0x90,  0x41,  0x04,  0x10,  0x7F,  0xE4,  0x90,  0x69,  0x05,  0x90,  0x49,  0x05,  0x92,  0x68, 	/* 11640 */
+	0x2C,  0x7E,  0xA9,  0x00,  0x4F,  0x98,  0x47,  0x04,  0x10,  0x79,  0x04,  0xFE,  0x69,  0x05,  0x90,  0x49, 	/* 11650 */
+	0x05,  0x92,  0x68,  0x2C,  0x7E,  0xAE,  0x12,  0x01,  0x10,  0x28,  0x8C,  0xA6,  0x13,  0x03,  0xD0,  0x00, 	/* 11660 */
+	0x0F,  0xFE,  0x15,  0x01,  0x30,  0x2D,  0x2F,  0x0E,  0xB0,  0x01,  0x8F,  0xA8,  0x42,  0x44,  0x24,  0x7C, 	/* 11670 */
+	0x24,  0xFC,  0x69,  0x45,  0x94,  0x4A,  0x45,  0xD8,  0x68,  0x2C,  0x7E,  0xB1,  0x00,  0x4F,  0x98,  0x47, 	/* 11680 */
+	0x04,  0x10,  0x79,  0xE4,  0xF0,  0x69,  0xE5,  0xF0,  0x49,  0x25,  0x8E,  0x68,  0x0C,  0x7E,  0xB2,  0x01, 	/* 11690 */
+	0x0F,  0x9C,  0x47,  0x04,  0x10,  0x7D,  0x44,  0xD4,  0x6D,  0x45,  0xFC,  0x49,  0x25,  0x8E,  0x68,  0x0C, 	/* 116A0 */
+	0x7E,  0xB6,  0x44,  0x02,  0xBE,  0xFD,  0x02,  0x90,  0x29,  0xC2,  0xA4,  0xFF,  0x42,  0xAC,  0x2A,  0x42, 	/* 116B0 */
+	0xA5,  0x4B,  0xB8,  0xE1,  0xB7,  0x04,  0x0E,  0x7E,  0x09,  0x42,  0x10,  0xC6,  0x81,  0x86,  0x00,  0x0F, 	/* 116C0 */
+	0xFE,  0x15,  0x01,  0x10,  0x2D,  0x2F,  0x0E,  0xB8,  0x00,  0x0F,  0xFE,  0x40,  0x84,  0x10,  0x7B,  0xC4, 	/* 116D0 */
+	0xA4,  0x6B,  0xC5,  0xA4,  0x4A,  0x45,  0xBC,  0x68,  0x2C,  0x7E,  0x83,  0x79,  0x02,  0x54,  0xFD,  0x43, 	/* 116E0 */
+	0x10,  0x6A,  0x8A,  0x44,  0xFF,  0xE0,  0x80,  0x0F,  0x81,  0x2A,  0x3F,  0xAE,  0x06,  0x84,  0x00,  0x0F, 	/* 116F0 */
+	0xFE,  0x52,  0x0F,  0xBC,  0xAA,  0x4A,  0xA4,  0xFB,  0x42,  0x2C,  0xFA,  0x42,  0x24,  0x3A,  0xDC,  0x73, 	/* 11700 */
+	0x85,  0x00,  0x0F,  0xBE,  0x42,  0x04,  0x3E,  0x7A,  0xA4,  0xBE,  0x6A,  0xA5,  0xBE,  0x4A,  0x84,  0xFE, 	/* 11710 */
+	0x74,  0x8C,  0xBE,  0x8C,  0x00,  0x0F,  0xFE,  0xBA,  0x0A,  0xBC,  0xBA,  0x48,  0x24,  0xFF,  0x4B,  0x6C, 	/* 11720 */
+	0xB6,  0x4F,  0xE4,  0x82,  0xDF,  0xF3,  0x8D,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xFC,  0x4A,  0x4F,  0xFE, 	/* 11730 */
+	0x80,  0x23,  0xFC,  0x19,  0x01,  0x50,  0x2F,  0x2F,  0x0E,  0x8E,  0x20,  0x0F,  0xFE,  0x22,  0x0F,  0xBC, 	/* 11740 */
+	0xAA,  0x4F,  0xA4,  0xAB,  0x4F,  0xAC,  0x16,  0x4F,  0xA4,  0x52,  0xE3,  0x72,  0x91,  0x88,  0x05,  0x7E, 	/* 11750 */
+	0xFA,  0x0A,  0xBC,  0xFA,  0x4A,  0xA4,  0xFB,  0x45,  0x2C,  0x72,  0x45,  0x44,  0x75,  0xC4,  0xE6,  0x93, 	/* 11760 */
+	0x79,  0x04,  0xFC,  0x7A,  0x84,  0x7E,  0x79,  0x0A,  0xBC,  0x39,  0x0F,  0xFE,  0x19,  0x01,  0x50,  0x2F, 	/* 11770 */
+	0x2F,  0x0E,  0x95,  0x04,  0x0F,  0xFE,  0x2A,  0x81,  0x3E,  0x7A,  0x81,  0x3E,  0x20,  0x0F,  0xFE,  0x19, 	/* 11780 */
+	0x01,  0x50,  0x2F,  0x2F,  0x0E,  0x98,  0x10,  0x81,  0x08,  0x10,  0x8F,  0xFE,  0x10,  0x81,  0x08,  0x1F, 	/* 11790 */
+	0x81,  0x08,  0x10,  0x81,  0x08,  0x10,  0x81,  0xF8,  0x9A,  0x21,  0x0F,  0xFC,  0x21,  0x03,  0xF0,  0x21, 	/* 117A0 */
+	0x03,  0xF0,  0x21,  0x0F,  0xFE,  0x49,  0x07,  0x1C,  0x40,  0x03,  0xFC,  0x9C,  0x1A,  0x4E,  0x24,  0x22, 	/* 117B0 */
+	0x42,  0x7E,  0xFA,  0x42,  0x24,  0x22,  0x47,  0xBC,  0x4A,  0x44,  0xA4,  0x4A,  0x47,  0xBC,  0x9E,  0x44, 	/* 117C0 */
+	0x42,  0x48,  0xFF,  0xEB,  0xFA,  0xA0,  0xA3,  0xF8,  0x11,  0x0F,  0xFE,  0x11,  0x01,  0xF0,  0x11,  0x01, 	/* 117D0 */
+	0xF0,  0x9F,  0x04,  0x02,  0x40,  0x24,  0x07,  0xFC,  0x44,  0x08,  0x40,  0x04,  0x03,  0xF8,  0x04,  0x00, 	/* 117E0 */
+	0x40,  0x04,  0x0F,  0xFE,  0xA3,  0x02,  0x07,  0xFE,  0x10,  0x80,  0x90,  0x3F,  0xE2,  0xA0,  0x2F,  0xC3, 	/* 117F0 */
+	0x20,  0x4F,  0xC4,  0x20,  0x82,  0x03,  0xFE,  0xA5,  0x10,  0x05,  0x7E,  0x55,  0x27,  0xFE,  0x95,  0x21, 	/* 11800 */
+	0x7E,  0x79,  0x01,  0x7E,  0x11,  0x23,  0xA2,  0xC2,  0x20,  0xCC,  0xA6,  0x02,  0x8F,  0xA8,  0x23,  0xEF, 	/* 11810 */
+	0xA8,  0xAC,  0x8F,  0xBE,  0xA8,  0x8F,  0x88,  0x67,  0xE2,  0x00,  0x58,  0x08,  0x7F,  0xA8,  0x00,  0x03, 	/* 11820 */
+	0xFE,  0x22,  0x22,  0x22,  0x3F,  0xE2,  0x22,  0x22,  0x23,  0xFE,  0x22,  0x22,  0x22,  0x42,  0x28,  0x26, 	/* 11830 */
+	0xAB,  0x04,  0x80,  0x44,  0xFF,  0xE0,  0x40,  0x7F,  0xC4,  0x44,  0x7F,  0xC4,  0x44,  0x7F,  0xC4,  0x44, 	/* 11840 */
+	0x44,  0x44,  0x4C,  0xAC,  0x00,  0x03,  0xF8,  0x19,  0x00,  0x60,  0x7F,  0xC4,  0x44,  0x7F,  0xC4,  0x44, 	/* 11850 */
+	0x7F,  0xC4,  0x44,  0x44,  0x44,  0x4C,  0xB0,  0x00,  0x07,  0xFC,  0x44,  0x44,  0x44,  0x44,  0x47,  0xFC, 	/* 11860 */
+	0x44,  0x44,  0x44,  0x44,  0x44,  0x44,  0x7F,  0xC0,  0x00,  0xB1,  0x04,  0x00,  0x40,  0x04,  0x07,  0xFC, 	/* 11870 */
+	0x44,  0x44,  0x44,  0x44,  0x47,  0xFC,  0x44,  0x44,  0x44,  0x44,  0x47,  0xFC,  0xB2,  0x00,  0x07,  0xFC, 	/* 11880 */
+	0x44,  0x44,  0x44,  0x7F,  0xC4,  0x44,  0x44,  0x47,  0xFC,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0xB3, 	/* 11890 */
+	0x04,  0x00,  0x40,  0x7F,  0xC4,  0x44,  0x7F,  0xC4,  0x44,  0x44,  0x47,  0xFC,  0x04,  0x00,  0x40,  0x04, 	/* 118A0 */
+	0x00,  0x40,  0xB7,  0x00,  0x03,  0xFC,  0x24,  0x43,  0xFC,  0x24,  0x43,  0xFC,  0x04,  0x07,  0xFE,  0x04, 	/* 118B0 */
+	0x20,  0x42,  0x18,  0x26,  0x0C,  0xB8,  0x10,  0x01,  0x00,  0x3F,  0xE2,  0x02,  0x7F,  0xAA,  0x4A,  0x3F, 	/* 118C0 */
+	0xA2,  0x4A,  0x24,  0xA3,  0xFA,  0x00,  0x40,  0x18,  0xBA,  0x00,  0x0F,  0xC0,  0xA7,  0xEA,  0x48,  0xFC, 	/* 118D0 */
+	0x8A,  0x48,  0xA4,  0x8A,  0x48,  0xFC,  0x80,  0x08,  0x00,  0x80,  0x18,  0xBB,  0x00,  0x0F,  0xFE,  0x04, 	/* 118E0 */
+	0x03,  0xF8,  0xA4,  0xAA,  0x4A,  0xBF,  0xAA,  0x4A,  0xA4,  0xAB,  0xFA,  0x80,  0x2F,  0xFE,  0xBC,  0x3F, 	/* 118F0 */
+	0x82,  0x48,  0x3F,  0x82,  0x48,  0x24,  0x83,  0xF8,  0x00,  0x0F,  0xFE,  0x04,  0x00,  0x40,  0x04,  0x00, 	/* 11900 */
+	0xC0,  0x84,  0x08,  0x44,  0x44,  0x24,  0x82,  0x10,  0x7F,  0xC4,  0x44,  0x44,  0x47,  0xFC,  0x44,  0x44, 	/* 11910 */
+	0x44,  0x44,  0x47,  0xFC,  0x86,  0x10,  0x81,  0x08,  0xFE,  0x80,  0x08,  0x7C,  0x85,  0x48,  0x55,  0x07, 	/* 11920 */
+	0xD8,  0x55,  0x45,  0x52,  0x56,  0x67,  0xFA,  0x89,  0x01,  0x0F,  0x90,  0xAF,  0xCA,  0x90,  0xA9,  0x0F, 	/* 11930 */
+	0xFE,  0xA9,  0x0A,  0x90,  0xAA,  0x8F,  0xA8,  0x04,  0x40,  0x82,  0x8A,  0x02,  0x4F,  0xA4,  0xAF,  0xFA, 	/* 11940 */
+	0xA4,  0xAA,  0x4F,  0xA4,  0xAF,  0xFA,  0xA4,  0xAA,  0x4F,  0xA4,  0x04,  0x40,  0x84,  0x8B,  0x01,  0x0F, 	/* 11950 */
+	0x90,  0xAB,  0xEA,  0xA4,  0xAA,  0x4F,  0xC4,  0xA9,  0x4A,  0x98,  0xA8,  0x8F,  0x98,  0x86,  0x41,  0x82, 	/* 11960 */
+	0x8C,  0x00,  0x03,  0xFC,  0x24,  0x43,  0xFC,  0x24,  0x43,  0xFC,  0x0A,  0x03,  0x18,  0xC9,  0x60,  0x90, 	/* 11970 */
+	0x11,  0x02,  0x10,  0x8D,  0x00,  0x8F,  0x88,  0xA9,  0x4A,  0x94,  0xAA,  0x2F,  0xD5,  0xA9,  0x4A,  0x94, 	/* 11980 */
+	0xAA,  0x4F,  0xA4,  0x04,  0x40,  0x84,  0x8F,  0x00,  0x03,  0xFC,  0x24,  0x43,  0xFC,  0x24,  0x43,  0xFC, 	/* 11990 */
+	0x00,  0x0F,  0xFE,  0x24,  0x42,  0x28,  0x3D,  0x8E,  0x06,  0x91,  0x20,  0x02,  0x7E,  0x25,  0x22,  0xD2, 	/* 119A0 */
+	0x75,  0x26,  0x7E,  0xA5,  0x22,  0x52,  0x35,  0x24,  0xD2,  0x47,  0xE8,  0x40,  0x94,  0x01,  0x00,  0x92, 	/* 119B0 */
+	0xFD,  0x4A,  0x90,  0xAF,  0xEA,  0x90,  0xF9,  0x0A,  0xFE,  0xA9,  0x0F,  0x90,  0x01,  0x00,  0x10,  0x99, 	/* 119C0 */
+	0x18,  0x06,  0x7E,  0x41,  0x25,  0x12,  0x4A,  0x27,  0x42,  0xC8,  0xC3,  0xFC,  0x24,  0x43,  0xFC,  0x24, 	/* 119D0 */
+	0x43,  0xFC,  0x9A,  0x08,  0x01,  0x10,  0x7E,  0x80,  0x44,  0xFF,  0xE0,  0xA0,  0x31,  0x8F,  0xFE,  0x24, 	/* 119E0 */
+	0x83,  0xF8,  0x24,  0x83,  0xF8,  0x9B,  0x00,  0x8F,  0x88,  0xA9,  0x4A,  0xA2,  0xAC,  0x9F,  0x90,  0xAE, 	/* 119F0 */
+	0x4A,  0x88,  0xAB,  0x2F,  0x84,  0x01,  0x80,  0x60,  0x9C,  0x04,  0x0F,  0xFE,  0x09,  0x03,  0x20,  0x14, 	/* 11A00 */
+	0x80,  0xFC,  0xF0,  0x23,  0xFA,  0x24,  0x83,  0xF8,  0x24,  0x83,  0xF8,  0x9D,  0x22,  0x02,  0x20,  0xFB, 	/* 11A10 */
+	0xC0,  0x24,  0xFC,  0x4A,  0xC8,  0xA8,  0x8F,  0x98,  0xA9,  0x4A,  0xA4,  0xFC,  0x20,  0x82,  0xA0,  0x08, 	/* 11A20 */
+	0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x00,  0x07,  0xFC,  0x44,  0x47,  0xFC,  0x44,  0x47, 	/* 11A30 */
+	0xFC,  0xA2,  0x7F,  0xC4,  0x44,  0x7F,  0xC4,  0x44,  0x7F,  0xC2,  0x48,  0xFF,  0xE2,  0x48,  0x7F,  0xC0, 	/* 11A40 */
+	0x40,  0xFF,  0xE0,  0x40,  0xA4,  0x00,  0x8F,  0x88,  0xAF,  0xEA,  0x88,  0xAF,  0xFF,  0x84,  0xAF,  0xEA, 	/* 11A50 */
+	0xC4,  0xAA,  0x4F,  0x84,  0x00,  0x40,  0x0C,  0xA5,  0x01,  0x0F,  0x9C,  0xAA,  0x4A,  0xD4,  0xA8,  0x8F, 	/* 11A60 */
+	0x94,  0xAA,  0x2A,  0xFD,  0xAA,  0x4F,  0xA4,  0x02,  0x40,  0x3C,  0xA6,  0x01,  0x0F,  0x90,  0xAF,  0xCA, 	/* 11A70 */
+	0x90,  0xA9,  0x0F,  0xFE,  0xA9,  0x0A,  0x90,  0xAF,  0xCF,  0x90,  0x01,  0x00,  0xFE,  0xA7,  0x00,  0x03, 	/* 11A80 */
+	0xFC,  0x24,  0x43,  0xFC,  0x24,  0x43,  0xFC,  0x19,  0x06,  0x60,  0x19,  0x8F,  0xFE,  0x10,  0x81,  0xF8, 	/* 11A90 */
+	0xA9,  0x01,  0x0F,  0x90,  0xAF,  0xEA,  0x90,  0xA9,  0x2F,  0xAA,  0xAE,  0xCA,  0xA8,  0xAA,  0x4F,  0xA4, 	/* 11AA0 */
+	0x03,  0xA0,  0x61,  0xAA,  0x01,  0xC7,  0xE8,  0x24,  0x81,  0x50,  0xFF,  0xE0,  0xE0,  0x35,  0x8F,  0xFE, 	/* 11AB0 */
+	0x24,  0x83,  0xF8,  0x24,  0x83,  0xF8,  0xAB,  0x04,  0x03,  0xF8,  0x04,  0x8F,  0xFE,  0x04,  0x83,  0xF8, 	/* 11AC0 */
+	0x04,  0x0F,  0xFE,  0x24,  0x83,  0xF8,  0x24,  0x8F,  0xFE,  0xAD,  0x01,  0x0F,  0x90,  0xAA,  0x8A,  0xC4, 	/* 11AD0 */
+	0xAF,  0xAF,  0x90,  0xAF,  0xEA,  0x90,  0xAB,  0x4F,  0xD2,  0x09,  0x20,  0x30,  0xB0,  0x00,  0x07,  0xFC, 	/* 11AE0 */
+	0x44,  0x47,  0xFC,  0x44,  0x47,  0xFC,  0x11,  0x07,  0xFC,  0x11,  0x0F,  0xFE,  0x21,  0x8C,  0x04,  0xB3, 	/* 11AF0 */
+	0x3F,  0x82,  0x48,  0x3F,  0x82,  0x48,  0xFF,  0xEB,  0xFA,  0xA0,  0xA3,  0xF8,  0x20,  0x83,  0xF8,  0x20, 	/* 11B00 */
+	0x8F,  0xFE,  0xB4,  0x01,  0x0F,  0xFE,  0xA9,  0x0A,  0xBC,  0xF9,  0x0A,  0xFE,  0xAA,  0x4A,  0xBE,  0xFC, 	/* 11B10 */
+	0x40,  0x64,  0x09,  0x40,  0x0C,  0xB6,  0x24,  0x81,  0x50,  0xFF,  0xE8,  0x02,  0xBF,  0xA2,  0x08,  0x3F, 	/* 11B20 */
+	0x87,  0xFC,  0x44,  0x47,  0xFC,  0x44,  0x47,  0xFC,  0xB7,  0x07,  0xEF,  0x92,  0xAE,  0xCA,  0xA4,  0xAD, 	/* 11B30 */
+	0xAF,  0x80,  0xAF,  0xEA,  0x92,  0xAD,  0xAF,  0xA4,  0x05,  0xA0,  0x91,  0xB8,  0x01,  0x0F,  0xFC,  0xA9, 	/* 11B40 */
+	0x0A,  0xA8,  0xAC,  0x4F,  0xFE,  0xA8,  0x4A,  0xF4,  0xAD,  0x4F,  0xF4,  0x00,  0x40,  0x0C,  0xBF,  0x24, 	/* 11B50 */
+	0x85,  0x54,  0xA6,  0x85,  0x54,  0xF5,  0xC1,  0x44,  0xFF,  0xE7,  0xC4,  0x56,  0x87,  0xD2,  0x56,  0xA7, 	/* 11B60 */
+	0xC6,  0x82,  0x3F,  0x82,  0x48,  0x3F,  0x83,  0xF8,  0x60,  0xC1,  0xB0,  0xE0,  0xEF,  0xFE,  0xA0,  0xA3, 	/* 11B70 */
+	0xF8,  0x20,  0x8F,  0xFE,  0x86,  0x00,  0x0F,  0xFE,  0x15,  0x4F,  0x7C,  0x85,  0x4F,  0xFE,  0x50,  0x0F, 	/* 11B80 */
+	0x7C,  0x55,  0x4F,  0x7C,  0x25,  0x4C,  0xFE,  0x87,  0x01,  0x0F,  0xFE,  0xA9,  0x0A,  0xFE,  0xA8,  0x2F, 	/* 11B90 */
+	0xFC,  0xA9,  0x0A,  0xFE,  0xAE,  0x4F,  0xB4,  0x0E,  0x40,  0x0C,  0x89,  0x3F,  0x82,  0x48,  0x3F,  0x8F, 	/* 11BA0 */
+	0xBE,  0xAA,  0xAF,  0xBE,  0x7F,  0xE9,  0x02,  0x1F,  0x82,  0x90,  0x06,  0x0F,  0xFE,  0x8A,  0x3F,  0x82, 	/* 11BB0 */
+	0x48,  0x3F,  0x8F,  0xBE,  0xAA,  0xAF,  0xBE,  0x00,  0x0F,  0xFE,  0x91,  0x21,  0xF0,  0x11,  0x0F,  0xFE, 	/* 11BC0 */
+	0x8B,  0x00,  0x07,  0xFE,  0x04,  0x40,  0x48,  0x24,  0x02,  0x40,  0x27,  0xC2,  0x40,  0x24,  0x05,  0x40, 	/* 11BD0 */
+	0x4C,  0x08,  0x3E,  0x8E,  0x01,  0x0F,  0xFE,  0x11,  0x02,  0x7C,  0x25,  0x4B,  0xD4,  0xA7,  0xCA,  0x10, 	/* 11BE0 */
+	0xA3,  0x8B,  0xD4,  0xE1,  0x28,  0x10,  0x8F,  0x01,  0x0F,  0x90,  0x17,  0xC2,  0x10,  0x22,  0xCB,  0xFA, 	/* 11BF0 */
+	0xAA,  0x8A,  0xA8,  0xAA,  0x8B,  0xA8,  0xEA,  0xA9,  0x06,  0x91,  0x47,  0xE7,  0x84,  0x42,  0x84,  0x98, 	/* 11C00 */
+	0x3F,  0xE4,  0x12,  0x79,  0x49,  0x50,  0x7D,  0xC2,  0x70,  0x55,  0x88,  0x86,  0x94,  0x02,  0x03,  0xFE, 	/* 11C10 */
+	0xA0,  0x06,  0x00,  0x3F,  0xE2,  0x10,  0x61,  0x0A,  0x10,  0x21,  0x04,  0x10,  0x41,  0x08,  0x30,  0x9A, 	/* 11C20 */
+	0x02,  0x03,  0xFE,  0xA0,  0x06,  0x20,  0x23,  0xC2,  0x44,  0x64,  0x8A,  0x88,  0x21,  0x04,  0x28,  0x44, 	/* 11C30 */
+	0x49,  0x82,  0x9D,  0x02,  0x03,  0xFF,  0xA1,  0x06,  0x10,  0x29,  0x22,  0x92,  0x69,  0x2A,  0x92,  0x29, 	/* 11C40 */
+	0x24,  0x92,  0x4F,  0xE8,  0x82,  0xA3,  0x02,  0x03,  0xFE,  0xA2,  0x86,  0x24,  0x3F,  0xE2,  0x20,  0x63, 	/* 11C50 */
+	0x0A,  0x30,  0x25,  0x04,  0x50,  0x49,  0x2B,  0x0E,  0xA5,  0x02,  0x03,  0xFE,  0xA1,  0x06,  0x10,  0x22, 	/* 11C60 */
+	0x82,  0x44,  0x6C,  0xAB,  0x48,  0x24,  0x84,  0x48,  0x48,  0x89,  0x08,  0xAB,  0x02,  0x03,  0xFE,  0xA7, 	/* 11C70 */
+	0x86,  0x48,  0x24,  0xA2,  0x86,  0x77,  0x8A,  0x08,  0x24,  0x84,  0x30,  0x45,  0x89,  0x86,  0xB1,  0x02, 	/* 11C80 */
+	0x03,  0xFE,  0xA4,  0x06,  0x7E,  0x28,  0x22,  0xF2,  0x75,  0x2A,  0x72,  0x24,  0xC4,  0x40,  0x44,  0x28, 	/* 11C90 */
+	0x3E,  0xB2,  0x02,  0x03,  0xFF,  0xA1,  0x06,  0xFE,  0x29,  0x22,  0x94,  0x6F,  0xEA,  0xA2,  0x29,  0x45, 	/* 11CA0 */
+	0x08,  0x53,  0x4A,  0xC2,  0xB3,  0x02,  0x03,  0xFE,  0xA0,  0x06,  0x88,  0x3F,  0xE2,  0x88,  0x68,  0x8A, 	/* 11CB0 */
+	0xF8,  0x28,  0x84,  0x88,  0x48,  0x88,  0xF8,  0xB5,  0x02,  0x03,  0xFE,  0xA0,  0x06,  0x50,  0x25,  0x03, 	/* 11CC0 */
+	0x76,  0x75,  0x8B,  0x50,  0x35,  0x05,  0x52,  0x5F,  0x2B,  0x0E,  0xB8,  0x02,  0x03,  0xFE,  0xA0,  0x06, 	/* 11CD0 */
+	0x7C,  0x24,  0x42,  0x44,  0x67,  0xCA,  0x44,  0x24,  0x44,  0x7C,  0x40,  0x09,  0xFE,  0xB9,  0x02,  0x03, 	/* 11CE0 */
+	0xFE,  0xA2,  0x06,  0x50,  0x28,  0x83,  0x24,  0x64,  0x2B,  0x90,  0x22,  0x44,  0xC8,  0x43,  0x09,  0xC0, 	/* 11CF0 */
+	0xBC,  0x02,  0x03,  0xFE,  0xA4,  0x06,  0x78,  0x38,  0x82,  0x70,  0x6D,  0x8B,  0x06,  0x26,  0x04,  0x10, 	/* 11D00 */
+	0x4E,  0x08,  0x18,  0xBD,  0x02,  0x03,  0xFE,  0xA0,  0x06,  0x7C,  0x24,  0x42,  0x44,  0x67,  0xCA,  0x44, 	/* 11D10 */
+	0x27,  0xC4,  0x44,  0x44,  0x49,  0xFE,  0xBE,  0x02,  0x03,  0xFE,  0x28,  0x0A,  0x80,  0x6F,  0xC3,  0x20, 	/* 11D20 */
+	0x62,  0x0B,  0xFE,  0x23,  0x04,  0x48,  0x48,  0x4B,  0x02,  0x82,  0x02,  0x03,  0xFE,  0xA8,  0x06,  0x8E, 	/* 11D30 */
+	0x3E,  0xA2,  0xAA,  0x6A,  0xAA,  0xAA,  0x2A,  0xA4,  0xAA,  0x52,  0xEA,  0xC0,  0x83,  0x02,  0x03,  0xFE, 	/* 11D40 */
+	0xA2,  0x06,  0x20,  0x3F,  0xE2,  0x20,  0x74,  0x8A,  0x90,  0x27,  0x04,  0x48,  0x4B,  0xCB,  0xC4,  0x85, 	/* 11D50 */
+	0x01,  0x03,  0xFF,  0xA0,  0x06,  0xFE,  0x21,  0x02,  0xFE,  0x69,  0x2A,  0xAA,  0x2A,  0xA4,  0xC6,  0x48, 	/* 11D60 */
+	0x28,  0x86,  0x87,  0x02,  0x03,  0xFE,  0x20,  0x0A,  0x00,  0x6F,  0xE2,  0x10,  0x61,  0x0A,  0x9E,  0x29, 	/* 11D70 */
+	0x04,  0x90,  0x49,  0x09,  0xFE,  0x8A,  0x02,  0x03,  0xFE,  0xA2,  0x06,  0x50,  0x28,  0x83,  0xFE,  0x62, 	/* 11D80 */
+	0x0A,  0x20,  0x2F,  0x84,  0x20,  0x42,  0x0B,  0xFE,  0x8D,  0x02,  0x03,  0xFE,  0xA2,  0x07,  0xFC,  0x22, 	/* 11D90 */
+	0x43,  0xFC,  0x72,  0x0B,  0xFC,  0x22,  0x44,  0x6C,  0x49,  0x0B,  0x0E,  0x92,  0x02,  0x03,  0xFE,  0xA8, 	/* 11DA0 */
+	0x86,  0x50,  0x3F,  0xC2,  0x20,  0x7F,  0xCA,  0x20,  0x3F,  0xE4,  0x20,  0x42,  0x08,  0x20,  0x94,  0x02, 	/* 11DB0 */
+	0x03,  0xFE,  0xA2,  0x06,  0xFC,  0x22,  0x03,  0xFE,  0x60,  0x8B,  0xFE,  0x28,  0x84,  0x48,  0x40,  0x80, 	/* 11DC0 */
+	0x18,  0x95,  0x02,  0x03,  0xFE,  0x20,  0x0A,  0xFC,  0x68,  0x42,  0xFC,  0x68,  0x4A,  0xFC,  0x2A,  0x22, 	/* 11DD0 */
+	0x94,  0x4E,  0x89,  0x86,  0x98,  0x02,  0x03,  0xFE,  0xA0,  0x06,  0xFE,  0x20,  0x02,  0xFC,  0x68,  0x4A, 	/* 11DE0 */
+	0xFC,  0x28,  0x84,  0x48,  0x45,  0x09,  0xFE,  0x99,  0x02,  0x03,  0xFE,  0xA0,  0x07,  0xFE,  0x29,  0x23, 	/* 11DF0 */
+	0x24,  0x69,  0x2B,  0xFC,  0x22,  0x04,  0x20,  0x42,  0x0B,  0xFE,  0x9B,  0x02,  0x03,  0xFE,  0xA0,  0x06, 	/* 11E00 */
+	0xFE,  0x26,  0x82,  0xFE,  0x69,  0x2A,  0xFE,  0x29,  0x24,  0xFE,  0x49,  0x28,  0x96,  0x9E,  0x02,  0x03, 	/* 11E10 */
+	0xFE,  0xA0,  0x07,  0xFE,  0x27,  0x02,  0xAC,  0x72,  0x2A,  0x20,  0x3F,  0xC5,  0x04,  0x50,  0x49,  0xFC, 	/* 11E20 */
+	0xA2,  0x02,  0x03,  0xFE,  0xA2,  0x06,  0xCA,  0x24,  0xA3,  0xFA,  0x64,  0xAA,  0xEA,  0x2E,  0xA5,  0x52, 	/* 11E30 */
+	0x54,  0x28,  0x46,  0xA3,  0x02,  0x03,  0xFE,  0xA2,  0x06,  0x20,  0x3F,  0xC2,  0x20,  0x6F,  0x8A,  0x40, 	/* 11E40 */
+	0x2A,  0x45,  0x82,  0x68,  0xA8,  0x78,  0xA9,  0x02,  0x03,  0xFE,  0xA2,  0x06,  0xFC,  0x2A,  0x42,  0xFC, 	/* 11E50 */
+	0x6A,  0x4A,  0xFC,  0x28,  0x84,  0x50,  0x47,  0x09,  0x8E,  0xB0,  0x02,  0x03,  0xFE,  0xA2,  0x46,  0xA8, 	/* 11E60 */
+	0x32,  0x02,  0x50,  0x78,  0xCA,  0x24,  0x2A,  0x85,  0x20,  0x45,  0x8B,  0x86,  0xB2,  0x02,  0x03,  0xFF, 	/* 11E70 */
+	0xA4,  0x46,  0x44,  0x3F,  0xF2,  0x44,  0x65,  0x5B,  0x55,  0x35,  0x55,  0x55,  0x55,  0x5A,  0x44,  0xB3, 	/* 11E80 */
+	0x04,  0x03,  0xFE,  0xA8,  0x86,  0x88,  0x3F,  0xE2,  0x88,  0x7D,  0xCB,  0xDC,  0x2A,  0xA4,  0xAA,  0x4A, 	/* 11E90 */
+	0x88,  0x88,  0xB4,  0x02,  0x03,  0xFE,  0xA8,  0x06,  0x9E,  0x2F,  0x23,  0x52,  0x65,  0x2B,  0xF2,  0x25, 	/* 11EA0 */
+	0x24,  0xB2,  0x91,  0xE2,  0x10,  0xBA,  0x02,  0x03,  0xFE,  0xA2,  0x06,  0xFC,  0x29,  0x42,  0xFC,  0x69, 	/* 11EB0 */
+	0x4A,  0xFC,  0x25,  0x05,  0xFE,  0x41,  0x08,  0x10,  0xBC,  0x02,  0x03,  0xFE,  0xA0,  0x06,  0xFE,  0x29, 	/* 11EC0 */
+	0x22,  0xFE,  0x69,  0x2A,  0xBA,  0x2A,  0xA4,  0xBA,  0x48,  0x28,  0xFE,  0xBE,  0x02,  0x03,  0xFE,  0xA0, 	/* 11ED0 */
+	0x06,  0xFF,  0x2A,  0x26,  0xCE,  0xAC,  0xA2,  0xAA,  0x4A,  0xE4,  0xE2,  0x48,  0x28,  0x86,  0xBF,  0x02, 	/* 11EE0 */
+	0x03,  0xFE,  0xA0,  0x86,  0xF0,  0x22,  0x03,  0xFE,  0x6A,  0x8B,  0x24,  0x3F,  0xE4,  0xC8,  0x43,  0x09, 	/* 11EF0 */
+	0xC8,  0x81,  0x02,  0x03,  0xFE,  0xA2,  0x07,  0xFC,  0x28,  0x82,  0xD8,  0x72,  0x4A,  0x20,  0x3F,  0xE4, 	/* 11F00 */
+	0x20,  0x42,  0x08,  0x20,  0x89,  0x02,  0x03,  0xFE,  0xA5,  0x06,  0xF8,  0x30,  0x63,  0xD4,  0x75,  0x4B, 	/* 11F10 */
+	0xE8,  0x36,  0x85,  0xD4,  0x55,  0x49,  0x54,  0x8B,  0x02,  0x03,  0xFE,  0xA0,  0x06,  0xFC,  0x2F,  0x42, 	/* 11F20 */
+	0xA4,  0x6F,  0xCA,  0xAC,  0x2F,  0xC5,  0x24,  0x52,  0xAA,  0xF6,  0x8D,  0x02,  0x03,  0xFE,  0xAF,  0x86, 	/* 11F30 */
+	0x88,  0x2F,  0x82,  0x88,  0x7F,  0xEA,  0x40,  0x2F,  0xE5,  0x2A,  0x65,  0x28,  0xA4,  0x9F,  0x02,  0x03, 	/* 11F40 */
+	0xFE,  0xA0,  0x06,  0xFC,  0x2A,  0x42,  0xBC,  0x6C,  0x4A,  0xFC,  0x20,  0x04,  0xFE,  0x4A,  0xAB,  0xFF, 	/* 11F50 */
+	0xA0,  0x02,  0x03,  0xFE,  0xA2,  0x07,  0xAC,  0x22,  0x03,  0xDC,  0x68,  0x8B,  0x76,  0x28,  0x84,  0xF8, 	/* 11F60 */
+	0x48,  0x88,  0x98,  0xA1,  0x02,  0x03,  0xFE,  0xA2,  0x06,  0xD8,  0x32,  0x62,  0xF8,  0x68,  0x8A,  0xF8, 	/* 11F70 */
+	0x28,  0x05,  0x7E,  0x54,  0x2A,  0x7E,  0xA2,  0x02,  0x03,  0xFE,  0xA4,  0x06,  0xEE,  0x2A,  0xA2,  0xEA, 	/* 11F80 */
+	0x6B,  0x3B,  0xFE,  0x2A,  0xA4,  0xE4,  0x52,  0xCA,  0x72,  0xA4,  0x02,  0x03,  0xFE,  0xA2,  0x06,  0xDE, 	/* 11F90 */
+	0x2A,  0xA2,  0xF2,  0x7A,  0xCA,  0xFE,  0x29,  0x24,  0xFE,  0x49,  0x28,  0xFE,  0xA7,  0x02,  0x03,  0xFE, 	/* 11FA0 */
+	0xA2,  0x06,  0xFE,  0x2B,  0xC2,  0xE2,  0x69,  0xEA,  0xBC,  0x2A,  0x05,  0x7E,  0x52,  0x0A,  0x3E,  0xB0, 	/* 11FB0 */
+	0x02,  0x03,  0xFE,  0xAF,  0xC6,  0x94,  0x2F,  0xC2,  0x94,  0x6F,  0xCA,  0x48,  0x23,  0x45,  0xFE,  0x45, 	/* 11FC0 */
+	0x49,  0x92,  0xB4,  0x02,  0x03,  0xFE,  0xA2,  0x07,  0xFE,  0x24,  0x83,  0xFE,  0x68,  0x4A,  0xFC,  0x28, 	/* 11FD0 */
+	0x45,  0xFE,  0x42,  0x08,  0x20,  0xBB,  0x02,  0x03,  0xFE,  0xAF,  0xC6,  0xA4,  0x3F,  0xE2,  0xA4,  0x6F, 	/* 11FE0 */
+	0xCA,  0x40,  0x3F,  0xE4,  0x88,  0x47,  0x09,  0xC8,  0x82,  0x02,  0x03,  0xFE,  0xA2,  0x07,  0xFE,  0x35, 	/* 11FF0 */
+	0x42,  0x88,  0x7F,  0xCA,  0x8A,  0x2F,  0x84,  0xA8,  0x52,  0x48,  0x60,  0x86,  0x02,  0x03,  0xFE,  0xB6, 	/* 12000 */
+	0xA6,  0xDC,  0x24,  0x82,  0xB4,  0x7F,  0xEB,  0x22,  0x2F,  0xC4,  0x24,  0x44,  0x48,  0x98,  0x87,  0x02, 	/* 12010 */
+	0x03,  0xFF,  0xAE,  0xE6,  0xAA,  0x2E,  0xE2,  0xAA,  0x6F,  0x6A,  0xAA,  0x2B,  0xA4,  0xAA,  0x4B,  0xA8, 	/* 12020 */
+	0x86,  0x88,  0x02,  0x03,  0xFE,  0xAE,  0x86,  0x32,  0x2C,  0xC3,  0xDE,  0x65,  0x4B,  0xD6,  0x33,  0xC5, 	/* 12030 */
+	0xD4,  0x44,  0xC9,  0xB2,  0x8C,  0x02,  0x03,  0xFE,  0xA7,  0x86,  0x48,  0x27,  0x86,  0xEE,  0xAA,  0xA2, 	/* 12040 */
+	0xEE,  0x21,  0x05,  0x12,  0x51,  0x29,  0xFE,  0x92,  0x02,  0x03,  0xFE,  0xA2,  0x86,  0x44,  0x2E,  0xA3, 	/* 12050 */
+	0xAB,  0x6E,  0xAA,  0xA2,  0x2A,  0x64,  0x54,  0x54,  0xAA,  0x3A,  0x96,  0x02,  0x03,  0xFF,  0xA0,  0x46, 	/* 12060 */
+	0xE4,  0x2B,  0xF2,  0xEA,  0x68,  0xAA,  0xFF,  0x3A,  0x44,  0xBF,  0x4E,  0x48,  0x84,  0x98,  0x02,  0x03, 	/* 12070 */
+	0xFE,  0xA4,  0x87,  0xFE,  0x2A,  0x42,  0xFC,  0x6A,  0x4A,  0xFC,  0x3F,  0xE5,  0x2A,  0x5F,  0xA9,  0x06, 	/* 12080 */
+	0x9C,  0x02,  0x03,  0xFE,  0xA0,  0x06,  0xEE,  0x2A,  0xA2,  0xEA,  0x6B,  0x3A,  0xFE,  0x2A,  0xA4,  0xFA, 	/* 12090 */
+	0x56,  0x4A,  0x9A,  0xA1,  0x02,  0x03,  0xFE,  0xA8,  0x06,  0xFE,  0x29,  0x42,  0xE8,  0x65,  0xEB,  0xEA, 	/* 120A0 */
+	0x34,  0x85,  0xFE,  0x4D,  0x89,  0x26,  0xA2,  0x02,  0x03,  0xFE,  0xA4,  0x46,  0xFE,  0x21,  0x02,  0xFE, 	/* 120B0 */
+	0x64,  0x8A,  0xFC,  0x34,  0x64,  0x7C,  0x45,  0xA8,  0xE7,  0xA7,  0x02,  0x03,  0xFE,  0xA0,  0x06,  0xFE, 	/* 120C0 */
+	0x2A,  0x82,  0xFE,  0x6E,  0xCA,  0xBA,  0x29,  0x04,  0xDE,  0x55,  0x0A,  0xFE,  0xA8,  0x02,  0x03,  0xFE, 	/* 120D0 */
+	0xA2,  0x07,  0xFE,  0x32,  0x23,  0xAE,  0x69,  0x0A,  0xFE,  0x59,  0x06,  0xFC,  0x49,  0x08,  0xFE,  0xA9, 	/* 120E0 */
+	0x02,  0x03,  0xFE,  0xA4,  0x07,  0xFE,  0x24,  0xA3,  0xFE,  0x77,  0x2B,  0xFE,  0x25,  0x24,  0xFE,  0x54, 	/* 120F0 */
+	0xC8,  0x52,  0xAA,  0x02,  0x03,  0xFE,  0xA2,  0x87,  0xDE,  0x24,  0x83,  0xFF,  0x65,  0x2A,  0xDE,  0x2F, 	/* 12100 */
+	0x25,  0x5E,  0x54,  0xC8,  0x52,  0xAC,  0x04,  0x07,  0xFE,  0xD1,  0x4D,  0xC8,  0x69,  0xE7,  0xE8,  0xEB, 	/* 12110 */
+	0xCF,  0xE8,  0x6B,  0xEB,  0xE8,  0x94,  0x82,  0xA8,  0xB0,  0x02,  0x03,  0xFE,  0xAA,  0x87,  0x4A,  0x2B, 	/* 12120 */
+	0xE7,  0xD4,  0xB5,  0xE3,  0xF4,  0x6B,  0xE7,  0xF4,  0xA1,  0x41,  0xDE,  0xB2,  0x02,  0x03,  0xFE,  0xA4, 	/* 12130 */
+	0x07,  0xBE,  0x34,  0x83,  0xDE,  0x75,  0x2B,  0xDE,  0x35,  0x25,  0xFE,  0x54,  0xAA,  0x11,  0xB6,  0x00, 	/* 12140 */
+	0x00,  0x00,  0x3C,  0x80,  0x50,  0x8A,  0x25,  0x14,  0x20,  0x8C,  0x06,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 12150 */
+	0x00,  0xB8,  0x38,  0x80,  0xA8,  0x8B,  0x25,  0x14,  0x20,  0x85,  0xF4,  0x84,  0x23,  0xF8,  0x04,  0x00, 	/* 12160 */
+	0xA0,  0x31,  0x8C,  0x06,  0xBA,  0x3A,  0x40,  0xA8,  0x49,  0x23,  0x14,  0x3F,  0x84,  0x94,  0x89,  0x27, 	/* 12170 */
+	0xFE,  0x09,  0x00,  0x92,  0x31,  0x2C,  0x0E,  0xBB,  0x3A,  0x40,  0xA8,  0x49,  0x23,  0x14,  0x3F,  0x84, 	/* 12180 */
+	0x04,  0xBF,  0xA2,  0x08,  0x3F,  0x81,  0x10,  0x0A,  0x07,  0xFC,  0xBC,  0x3A,  0x80,  0xB2,  0x51,  0x42, 	/* 12190 */
+	0x08,  0x73,  0xC9,  0x2A,  0x74,  0xC4,  0xF8,  0x72,  0x81,  0x10,  0x12,  0x86,  0xC6,  0xBD,  0x04,  0x00, 	/* 121A0 */
+	0x40,  0x08,  0x03,  0xF8,  0x20,  0x82,  0x08,  0x20,  0x83,  0xF8,  0x20,  0x82,  0x08,  0x20,  0x83,  0xF8, 	/* 121B0 */
+	0xBE,  0x00,  0x0F,  0xFE,  0x04,  0x00,  0x80,  0x3F,  0x82,  0x08,  0x20,  0x83,  0xF8,  0x20,  0x82,  0x08, 	/* 121C0 */
+	0x20,  0x83,  0xF8,  0x80,  0x08,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x82,  0x08,  0x3F,  0x81,  0x18, 	/* 121D0 */
+	0x1E,  0x01,  0x00,  0x10,  0x20,  0xFE,  0x83,  0x04,  0x00,  0x80,  0x3F,  0x82,  0x08,  0x3F,  0x82,  0x08, 	/* 121E0 */
+	0x3F,  0x80,  0xA0,  0x0A,  0x01,  0x22,  0x22,  0x2C,  0x1E,  0x84,  0x11,  0x02,  0x10,  0x79,  0xE4,  0xA2, 	/* 121F0 */
+	0x4A,  0x27,  0xD2,  0x48,  0xA4,  0x8A,  0x48,  0x27,  0x82,  0x00,  0x20,  0x0C,  0x86,  0x42,  0x04,  0x26, 	/* 12200 */
+	0x7B,  0x84,  0x20,  0x5A,  0x2E,  0x5E,  0x08,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x87, 	/* 12210 */
+	0x08,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x00,  0x07,  0xFC,  0x04,  0x03,  0xF8,  0x04, 	/* 12220 */
+	0x0F,  0xFE,  0x88,  0x20,  0x04,  0x7E,  0xF4,  0x09,  0x40,  0x97,  0xCF,  0x44,  0x96,  0x49,  0x58,  0x98, 	/* 12230 */
+	0x8F,  0x98,  0x12,  0x42,  0xC2,  0x8B,  0x04,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x04, 	/* 12240 */
+	0x0F,  0xFE,  0x31,  0x8C,  0x46,  0x3F,  0x80,  0x40,  0x8E,  0x21,  0x04,  0x10,  0xFF,  0xE9,  0x28,  0x94, 	/* 12250 */
+	0x4F,  0x8A,  0x94,  0x89,  0x28,  0x91,  0x0F,  0x28,  0x0C,  0x43,  0x02,  0x90,  0x08,  0x03,  0xF8,  0x20, 	/* 12260 */
+	0x83,  0xF8,  0x20,  0x87,  0xFC,  0x04,  0x07,  0x5C,  0x04,  0x0F,  0xFE,  0x04,  0x00,  0x40,  0x93,  0x25, 	/* 12270 */
+	0x04,  0x50,  0xF7,  0xE9,  0x90,  0x91,  0x0F,  0xFE,  0x90,  0x09,  0x7C,  0x94,  0x4F,  0x44,  0x04,  0x40, 	/* 12280 */
+	0x7C,  0x96,  0x21,  0x04,  0x10,  0xFF,  0xE9,  0x82,  0x97,  0xCF,  0x00,  0x9F,  0xE9,  0x28,  0x92,  0x8F, 	/* 12290 */
+	0x4A,  0x08,  0xA1,  0x06,  0x99,  0x20,  0x2F,  0xBC,  0x22,  0x07,  0x3E,  0x6A,  0x4A,  0x44,  0x20,  0x43, 	/* 122A0 */
+	0xFC,  0x20,  0x43,  0xFC,  0x20,  0x43,  0xFC,  0x9A,  0x21,  0x04,  0x92,  0xFF,  0xE9,  0x00,  0x9F,  0xEF, 	/* 122B0 */
+	0x00,  0x97,  0xC9,  0x44,  0x97,  0xCF,  0x44,  0x02,  0x81,  0xFE,  0xAE,  0x02,  0x00,  0x20,  0x3F,  0xE2, 	/* 122C0 */
+	0x22,  0x22,  0x43,  0xF8,  0x20,  0x82,  0x90,  0x25,  0x04,  0x20,  0x4D,  0x8B,  0x06,  0xB0,  0x11,  0x01, 	/* 122D0 */
+	0x10,  0x7F,  0xE5,  0x42,  0x7B,  0xA5,  0x2A,  0x7A,  0xA6,  0xBA,  0x52,  0xC5,  0xA0,  0xA6,  0x24,  0x1E, 	/* 122E0 */
+	0xB4,  0x10,  0x82,  0x88,  0xF7,  0xE5,  0x2A,  0x52,  0xC5,  0xFE,  0x92,  0x23,  0xB4,  0x4A,  0x8B,  0x2C, 	/* 122F0 */
+	0x2D,  0x2C,  0xA1,  0xB7,  0x20,  0x8F,  0xC8,  0x23,  0xFF,  0xAA,  0x02,  0x87,  0xBE,  0x4A,  0x27,  0xB2, 	/* 12300 */
+	0x4B,  0x43,  0x48,  0x19,  0x4E,  0x22,  0xB8,  0x00,  0x8F,  0xC8,  0xA7,  0xF2,  0x29,  0xFA,  0xAA,  0xBE, 	/* 12310 */
+	0xFB,  0x2A,  0xAA,  0xFA,  0x42,  0x4C,  0xFD,  0x22,  0xA1,  0xB9,  0x10,  0x01,  0x7F,  0x7D,  0xD5,  0x48, 	/* 12320 */
+	0x53,  0xE7,  0xAA,  0x6B,  0xE6,  0xAA,  0x53,  0xE5,  0x08,  0xAB,  0xF4,  0x08,  0xBA,  0x40,  0x87,  0x88, 	/* 12330 */
+	0xAB,  0xE7,  0xAA,  0x2A,  0xC4,  0xBE,  0x5A,  0x27,  0xB4,  0xAA,  0x87,  0xCC,  0x2D,  0x25,  0xA1,  0xBF, 	/* 12340 */
+	0x00,  0x00,  0x00,  0x3F,  0xC2,  0x94,  0x29,  0x42,  0x94,  0x29,  0x42,  0x94,  0x29,  0x42,  0x94,  0xFF, 	/* 12350 */
+	0xF0,  0x00,  0x82,  0x00,  0x03,  0xF8,  0x04,  0x00,  0x40,  0xFF,  0xE0,  0x40,  0x04,  0x00,  0xC0,  0x7F, 	/* 12360 */
+	0xC4,  0xA4,  0x4A,  0x4F,  0xFE,  0x83,  0x00,  0x0F,  0xFE,  0x02,  0x00,  0xD8,  0x34,  0x4C,  0x42,  0x04, 	/* 12370 */
+	0x07,  0xFC,  0x4A,  0x44,  0xA4,  0x4A,  0x4F,  0xFE,  0x86,  0x17,  0x01,  0x10,  0x20,  0x87,  0xF4,  0x89, 	/* 12380 */
+	0x20,  0x90,  0x11,  0x02,  0x60,  0x7F,  0xC4,  0xA4,  0x4A,  0x4F,  0xFE,  0x88,  0x00,  0x07,  0xF0,  0x11, 	/* 12390 */
+	0x01,  0xFC,  0x2A,  0x42,  0x44,  0x5A,  0x48,  0x18,  0x7F,  0xC4,  0xA4,  0x4A,  0x4F,  0xFE,  0x8A,  0x20, 	/* 123A0 */
+	0x81,  0x08,  0x09,  0x0F,  0xFE,  0x11,  0x01,  0x10,  0x20,  0x87,  0xFC,  0xAA,  0xA2,  0xA8,  0x2A,  0x8F, 	/* 123B0 */
+	0xFE,  0x8D,  0x04,  0x03,  0xF8,  0x04,  0x0F,  0xFE,  0x0A,  0x01,  0x18,  0x7E,  0x40,  0x00,  0x7F,  0xC4, 	/* 123C0 */
+	0xA4,  0x4A,  0x4F,  0xFE,  0x92,  0x04,  0x00,  0xA0,  0x11,  0x03,  0xF8,  0xC0,  0x63,  0xF8,  0x20,  0x83, 	/* 123D0 */
+	0xF8,  0x7F,  0xC4,  0xA4,  0x4A,  0x4F,  0xFE,  0x96,  0x20,  0x81,  0x10,  0x7F,  0xC0,  0x40,  0x3F,  0x80, 	/* 123E0 */
+	0x40,  0xFF,  0xE0,  0x00,  0x7F,  0xC4,  0xA4,  0x4A,  0x4F,  0xFE,  0x97,  0x08,  0x08,  0xFE,  0x4A,  0x41, 	/* 123F0 */
+	0x28,  0x45,  0x08,  0x88,  0x90,  0x67,  0xFC,  0x4A,  0x44,  0xA4,  0x4A,  0x4F,  0xFE,  0x9B,  0x02,  0x80, 	/* 12400 */
+	0x24,  0x7F,  0xE4,  0x20,  0x7A,  0x44,  0x98,  0x49,  0xA9,  0xA6,  0x7F,  0xC4,  0xA4,  0x4A,  0x4F,  0xFE, 	/* 12410 */
+	0x9C,  0x44,  0x02,  0x7E,  0x85,  0x24,  0x94,  0x13,  0x04,  0x48,  0x88,  0x67,  0xFC,  0x4A,  0x44,  0xA4, 	/* 12420 */
+	0x4A,  0x4F,  0xFE,  0x9E,  0x11,  0x0F,  0xFE,  0x05,  0x00,  0x34,  0x1C,  0xCF,  0xFE,  0x04,  0x80,  0x32, 	/* 12430 */
+	0x18,  0xE7,  0xFC,  0x4A,  0x4F,  0xFE,  0x9F,  0x00,  0x07,  0xBC,  0x4A,  0x47,  0xBC,  0x4A,  0x47,  0xBC, 	/* 12440 */
+	0x04,  0x40,  0x8C,  0x7F,  0xC4,  0xA4,  0x4A,  0x4F,  0xFE,  0xA1,  0x04,  0x07,  0xF8,  0x04,  0x8F,  0xFE, 	/* 12450 */
+	0x00,  0x8F,  0xFE,  0x32,  0x84,  0x94,  0xFF,  0xE4,  0xA4,  0x4A,  0x4F,  0xFF,  0xA3,  0xFA,  0x0A,  0x20, 	/* 12460 */
+	0xFB,  0xE8,  0xC0,  0xF8,  0x0A,  0x3C,  0xF8,  0x00,  0x00,  0x7F,  0xC4,  0xA4,  0x4A,  0x4F,  0xFE,  0xA4, 	/* 12470 */
+	0x23,  0x87,  0xAA,  0x4C,  0xE6,  0x80,  0xFF,  0xC5,  0xA4,  0x49,  0x89,  0xE6,  0x7F,  0xC4,  0xA4,  0x4A, 	/* 12480 */
+	0x4F,  0xFE,  0xA5,  0x20,  0x04,  0x4E,  0x85,  0x2D,  0xEE,  0x8E,  0x2D,  0x56,  0xA4,  0xA8,  0xC2,  0x7F, 	/* 12490 */
+	0xC4,  0xA4,  0x4A,  0x4F,  0xFE,  0xA7,  0x07,  0x80,  0x40,  0x7F,  0xE4,  0x9C,  0x7E,  0x25,  0xFE,  0x52, 	/* 124A0 */
+	0x45,  0xFC,  0x52,  0x47,  0xFE,  0xA5,  0x27,  0xFF,  0xAA,  0x4F,  0x82,  0x88,  0x8F,  0x84,  0x88,  0x0F, 	/* 124B0 */
+	0xE2,  0xAA,  0x55,  0x28,  0x0C,  0x7F,  0xC4,  0xA4,  0x4A,  0x4F,  0xFE,  0xAE,  0x00,  0x03,  0xF8,  0x20, 	/* 124C0 */
+	0x82,  0x08,  0x3F,  0x82,  0x08,  0x20,  0x83,  0xF8,  0x20,  0x82,  0x08,  0x20,  0x83,  0xF8,  0xB2,  0x02, 	/* 124D0 */
+	0x0F,  0xFF,  0x20,  0x01,  0xFE,  0x00,  0x01,  0xFC,  0x10,  0x41,  0xFC,  0x10,  0x41,  0xFC,  0x10,  0x41, 	/* 124E0 */
+	0xFC,  0xB4,  0x04,  0x0F,  0xFE,  0x04,  0x09,  0xF8,  0x90,  0x89,  0xF8,  0x90,  0x89,  0xF8,  0x90,  0x89, 	/* 124F0 */
+	0xF8,  0x80,  0x0F,  0xFE,  0xB8,  0x10,  0x01,  0x3E,  0x12,  0x2F,  0xE2,  0x13,  0xE3,  0x22,  0x3A,  0x25, 	/* 12500 */
+	0x7E,  0x52,  0x29,  0x22,  0x12,  0x21,  0x3E,  0xBB,  0x03,  0x8F,  0x48,  0x94,  0x89,  0x44,  0xF8,  0x29, 	/* 12510 */
+	0xFC,  0x92,  0x0F,  0x3C,  0x94,  0x49,  0x04,  0xF0,  0x40,  0x18,  0xBE,  0x00,  0xC3,  0xF0,  0x22,  0x03, 	/* 12520 */
+	0xFE,  0x22,  0x02,  0xFC,  0x28,  0x42,  0xFC,  0x48,  0x44,  0xFC,  0x88,  0x40,  0xFC,  0x81,  0x04,  0x01, 	/* 12530 */
+	0x48,  0x24,  0x4C,  0xCA,  0x01,  0x01,  0xF8,  0xF0,  0x81,  0xF8,  0x10,  0x81,  0xF8,  0x10,  0x81,  0xF8, 	/* 12540 */
+	0x84,  0x00,  0x00,  0xFF,  0xF1,  0x09,  0x5E,  0xF5,  0x29,  0x52,  0x95,  0x2F,  0x52,  0x97,  0xE9,  0x02, 	/* 12550 */
+	0xF0,  0x20,  0x0C,  0x87,  0x01,  0x0F,  0x10,  0x91,  0x49,  0x54,  0xF5,  0x29,  0x51,  0xF9,  0x49,  0x34, 	/* 12560 */
+	0x90,  0x8F,  0x10,  0x06,  0x01,  0x80,  0x88,  0x01,  0x0F,  0x10,  0x9F,  0xE9,  0x92,  0xF9,  0x29,  0x18, 	/* 12570 */
+	0x91,  0x8F,  0x18,  0x92,  0x89,  0x29,  0xF4,  0x91,  0x87,  0x89,  0x00,  0x07,  0xFE,  0x44,  0x27,  0xFE, 	/* 12580 */
+	0x40,  0x04,  0xFC,  0x48,  0x44,  0xFC,  0x48,  0x44,  0xFC,  0x88,  0x48,  0xFC,  0x8B,  0x00,  0xC7,  0xF0, 	/* 12590 */
+	0x08,  0x0F,  0xFE,  0x10,  0x0F,  0xFE,  0x30,  0x85,  0xF8,  0x90,  0x81,  0xF8,  0x10,  0x81,  0xF8,  0x8C, 	/* 125A0 */
+	0x00,  0x01,  0xF8,  0x90,  0x89,  0xF8,  0x90,  0x89,  0xF8,  0x90,  0x89,  0xF8,  0x80,  0x0F,  0xFE,  0x25, 	/* 125B0 */
+	0x8C,  0x46,  0x9B,  0x01,  0x0F,  0x10,  0x97,  0xC9,  0x10,  0xF1,  0x09,  0xFE,  0x91,  0x0F,  0x38,  0x93, 	/* 125C0 */
+	0x49,  0x52,  0xF9,  0x00,  0x10,  0x9E,  0x40,  0xC4,  0x70,  0x78,  0x23,  0xFE,  0x90,  0x89,  0xF8,  0x90, 	/* 125D0 */
+	0x89,  0xF8,  0x90,  0x8F,  0xFE,  0x19,  0x8E,  0x06,  0x9F,  0x04,  0x0F,  0xFE,  0x04,  0x03,  0xF0,  0x21, 	/* 125E0 */
+	0x03,  0xF0,  0x21,  0x03,  0xF0,  0x21,  0x0F,  0xFE,  0x13,  0x0E,  0x0C,  0xA0,  0x00,  0x0F,  0x7E,  0x94, 	/* 125F0 */
+	0x2F,  0x42,  0x97,  0xE9,  0x48,  0xF7,  0xF9,  0x48,  0x94,  0x4F,  0x45,  0x07,  0x31,  0x81,  0xA4,  0x00, 	/* 12600 */
+	0x0F,  0x7E,  0x94,  0x29,  0x7E,  0xF5,  0x09,  0x50,  0x95,  0x2F,  0x5C,  0x95,  0x0F,  0x92,  0x09,  0x21, 	/* 12610 */
+	0x0E,  0xA5,  0x11,  0x05,  0xD2,  0x51,  0xC5,  0x50,  0x79,  0x2B,  0xFE,  0x20,  0x83,  0xF8,  0x20,  0x83, 	/* 12620 */
+	0xF8,  0x20,  0x83,  0xF8,  0xA6,  0x09,  0x0E,  0x90,  0xA9,  0x0A,  0x92,  0xEF,  0x4A,  0x98,  0xA9,  0x0E, 	/* 12630 */
+	0x90,  0xA9,  0x0A,  0x92,  0xEF,  0x23,  0x0E,  0xA9,  0x01,  0x0F,  0x10,  0x9F,  0xE9,  0x10,  0xF5,  0x49, 	/* 12640 */
+	0x24,  0x92,  0x8F,  0x18,  0x91,  0x09,  0x24,  0xF2,  0xE0,  0xF2,  0xB7,  0x04,  0x01,  0x50,  0x3F,  0x84, 	/* 12650 */
+	0xA4,  0xFF,  0xE1,  0x10,  0x3F,  0x86,  0x0C,  0xBF,  0xA3,  0xF8,  0x20,  0x83,  0xF8,  0xB8,  0x02,  0x0F, 	/* 12660 */
+	0x28,  0x94,  0x49,  0xFE,  0xF5,  0x29,  0x50,  0x97,  0xEF,  0x90,  0x91,  0x09,  0xFF,  0xF1,  0x00,  0x10, 	/* 12670 */
+	0xBA,  0x05,  0x0E,  0x50,  0xA5,  0x4F,  0x54,  0xAD,  0x8A,  0x50,  0xED,  0x8B,  0x54,  0xA5,  0x2E,  0x90, 	/* 12680 */
+	0x09,  0x21,  0x0E,  0xBC,  0x00,  0x0F,  0x7C,  0x94,  0x49,  0x7C,  0xF4,  0x49,  0x44,  0x97,  0xCF,  0x42, 	/* 12690 */
+	0x95,  0x49,  0x48,  0xF7,  0x40,  0xC2,  0x80,  0x11,  0x0F,  0xFE,  0x04,  0x07,  0xFC,  0x04,  0x0F,  0xFE, 	/* 126A0 */
+	0x10,  0x83,  0xF8,  0x50,  0x89,  0xF8,  0x10,  0x81,  0xF8,  0x87,  0x08,  0x8E,  0x50,  0xBF,  0xCA,  0x24, 	/* 126B0 */
+	0xEF,  0xCA,  0xA0,  0xAF,  0xEE,  0x22,  0xA6,  0x2A,  0xA2,  0xF2,  0xC0,  0x20,  0x9A,  0x00,  0x0E,  0xFE, 	/* 126C0 */
+	0xA9,  0x0A,  0xFC,  0xE9,  0x0A,  0xFE,  0xA9,  0x0E,  0x90,  0xAF,  0xCF,  0x10,  0x11,  0x02,  0xFE,  0x9B, 	/* 126D0 */
+	0x02,  0x0E,  0xFE,  0xA2,  0x0A,  0x7C,  0xE2,  0x0B,  0xFE,  0xAA,  0x4E,  0xA4,  0xAF,  0xCA,  0x84,  0xE8, 	/* 126E0 */
+	0x40,  0x8C,  0xA1,  0x01,  0xCE,  0xE0,  0xA2,  0x0B,  0xFC,  0xEA,  0x8B,  0xFE,  0xEA,  0x8A,  0xA8,  0xBF, 	/* 126F0 */
+	0xCE,  0x20,  0x02,  0x03,  0xFE,  0xA3,  0x20,  0x03,  0xBE,  0x22,  0x2F,  0xD4,  0x58,  0x85,  0x54,  0xB6, 	/* 12700 */
+	0x23,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0xA5,  0x02,  0x0E,  0x40,  0xAF,  0xCA,  0xA4,  0xEF, 	/* 12710 */
+	0xCA,  0xA4,  0xAF,  0xCE,  0x50,  0xA9,  0x0B,  0xFE,  0xE1,  0x00,  0x10,  0xA6,  0x02,  0x0E,  0xFC,  0xA2, 	/* 12720 */
+	0x0B,  0xFE,  0xE5,  0x0A,  0x92,  0xB2,  0xEE,  0x20,  0xAF,  0xCA,  0x20,  0xE2,  0x03,  0xFE,  0xA8,  0x02, 	/* 12730 */
+	0x0E,  0xCC,  0xA8,  0x4A,  0x84,  0xED,  0xCA,  0x84,  0xAF,  0xCE,  0x30,  0xA3,  0x0A,  0x52,  0xE9,  0x21, 	/* 12740 */
+	0x0E,  0xAB,  0x02,  0x0F,  0xFE,  0xA2,  0x0A,  0xFC,  0xE2,  0x4B,  0xFE,  0xAF,  0xCE,  0x20,  0xAB,  0xEE, 	/* 12750 */
+	0xE0,  0x13,  0x02,  0x0E,  0xB9,  0x02,  0x0E,  0x20,  0xAF,  0xCA,  0x24,  0xE2,  0x8B,  0xFE,  0xA2,  0x8E, 	/* 12760 */
+	0x7C,  0xAC,  0x4B,  0x7C,  0xE4,  0x40,  0x7C,  0xBE,  0x04,  0x07,  0xFC,  0x4A,  0x47,  0xFC,  0x04,  0x0F, 	/* 12770 */
+	0xFE,  0x11,  0x0F,  0xFE,  0x04,  0x07,  0xFC,  0x04,  0x00,  0x40,  0xBF,  0x07,  0x80,  0x40,  0xFF,  0xE9, 	/* 12780 */
+	0x22,  0x9F,  0x22,  0x48,  0x4A,  0x43,  0xF8,  0xD1,  0x61,  0xF0,  0x11,  0x01,  0xF0,  0x8B,  0x04,  0xCE, 	/* 12790 */
+	0x70,  0xA4,  0x2A,  0x7E,  0xEA,  0x4A,  0xBC,  0xAA,  0x4E,  0xBC,  0xA8,  0x0A,  0xFE,  0xE2,  0x40,  0xC2, 	/* 127A0 */
+	0x8E,  0x01,  0x0F,  0xFE,  0xB1,  0x2A,  0xFC,  0xE1,  0x0A,  0xFC,  0xA1,  0x0F,  0xFF,  0xA1,  0x0A,  0x7C, 	/* 127B0 */
+	0xE4,  0x40,  0x7C,  0x91,  0x00,  0x0F,  0xFE,  0xB0,  0x2A,  0xFC,  0xE8,  0x4A,  0xFC,  0xA8,  0x4E,  0xFC, 	/* 127C0 */
+	0xA2,  0x0B,  0xFE,  0xE4,  0x81,  0x84,  0x9E,  0x08,  0x8F,  0xFE,  0xA8,  0x8A,  0xF8,  0xE2,  0x0B,  0xFE, 	/* 127D0 */
+	0xA2,  0x2E,  0xAA,  0xAA,  0xAB,  0x76,  0xE2,  0x22,  0x26,  0xA0,  0x0A,  0x4E,  0x68,  0xBF,  0xEB,  0x02, 	/* 127E0 */
+	0xEF,  0xCA,  0x84,  0xA8,  0x4E,  0xFC,  0xA2,  0x0A,  0xFC,  0xE2,  0x03,  0xFE,  0xA5,  0xAA,  0x05,  0x3E, 	/* 127F0 */
+	0xFE,  0x4A,  0x94,  0xF8,  0x8A,  0x94,  0xAE,  0x23,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0xAC, 	/* 12800 */
+	0x01,  0xEE,  0xE4,  0xAA,  0x4A,  0x58,  0xFF,  0xEB,  0x02,  0xAE,  0x4F,  0x3E,  0xB5,  0x4A,  0xFE,  0xE8, 	/* 12810 */
+	0x41,  0x04,  0xAD,  0xE2,  0x0B,  0xFE,  0xA2,  0x0F,  0x54,  0xA8,  0x8B,  0xFC,  0xE8,  0xAA,  0xF8,  0xAA, 	/* 12820 */
+	0x8E,  0xA4,  0x92,  0x40,  0x60,  0xB0,  0x00,  0x8F,  0xE8,  0xA4,  0xEB,  0xEA,  0xEA,  0xAA,  0xEA,  0xAB, 	/* 12830 */
+	0xAE,  0xE4,  0xAA,  0x4B,  0xEA,  0xE3,  0x20,  0x21,  0xB3,  0x02,  0x0E,  0xFC,  0xA4,  0x8B,  0xFE,  0xE0, 	/* 12840 */
+	0x0A,  0xFC,  0xAA,  0x4E,  0xFC,  0xAA,  0x4A,  0xFC,  0xE2,  0x01,  0xFE,  0xB6,  0x02,  0x0E,  0xFC,  0xAA, 	/* 12850 */
+	0x4B,  0xFE,  0xE0,  0x0A,  0xFC,  0xA8,  0x4E,  0xFC,  0xA8,  0x4A,  0xFC,  0xE4,  0x41,  0x82,  0xB9,  0x00, 	/* 12860 */
+	0xCF,  0xF4,  0xAA,  0x8B,  0xFE,  0xF5,  0x2A,  0xCC,  0xB3,  0xAE,  0x7A,  0xBC,  0x8A,  0x30,  0xE6,  0x81, 	/* 12870 */
+	0x86,  0xBB,  0x03,  0xCE,  0x48,  0xAF,  0xEA,  0xA8,  0xEC,  0xEA,  0xB8,  0xEF,  0xEA,  0x80,  0xAB,  0x8F, 	/* 12880 */
+	0x7C,  0x14,  0x42,  0x7C,  0xBC,  0x02,  0x0E,  0x50,  0xA8,  0x8B,  0x74,  0xE0,  0x2B,  0xDC,  0xB5,  0x4F, 	/* 12890 */
+	0xDC,  0xA4,  0x8A,  0x48,  0xEB,  0x41,  0x12,  0xBD,  0x20,  0x8F,  0xBE,  0x20,  0x8F,  0xFC,  0x4A,  0x47, 	/* 128A0 */
+	0x98,  0x52,  0x4F,  0xFA,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0xBF,  0x7B,  0xC4,  0xA4,  0x7B,  0xC4, 	/* 128B0 */
+	0xA4,  0x7B,  0xC4,  0xA4,  0x21,  0x03,  0xFE,  0x62,  0x0B,  0xFC,  0x22,  0x03,  0xFE,  0x87,  0x08,  0x8F, 	/* 128C0 */
+	0xFE,  0xAA,  0x8B,  0xFE,  0xF0,  0x2A,  0xFC,  0xA7,  0x2F,  0xAC,  0xAD,  0xCA,  0x2A,  0xEC,  0x90,  0x30, 	/* 128D0 */
+	0x8D,  0x7B,  0xC4,  0xA4,  0x7B,  0xC4,  0xA4,  0x3F,  0xC6,  0x40,  0xBF,  0x82,  0x40,  0x7F,  0xC1,  0x98, 	/* 128E0 */
+	0x0E,  0x0F,  0x1E,  0x97,  0x04,  0x07,  0xFC,  0x11,  0x05,  0xF0,  0x51,  0x07,  0xFC,  0x20,  0x8F,  0xDE, 	/* 128F0 */
+	0x28,  0xAB,  0xAE,  0xAA,  0xAF,  0xFF,  0x9A,  0x0F,  0xEE,  0x82,  0xAF,  0xEE,  0x90,  0xAD,  0x6A,  0xFC, 	/* 12900 */
+	0xED,  0x4A,  0xFE,  0xFA,  0xA1,  0xFA,  0x22,  0xA0,  0xF4,  0x9B,  0x00,  0x07,  0xF8,  0x01,  0x01,  0xA0, 	/* 12910 */
+	0x04,  0x0F,  0xFE,  0x04,  0x40,  0xC8,  0x14,  0x02,  0x40,  0xC4,  0x00,  0xC0,  0x9C,  0x01,  0x0F,  0x90, 	/* 12920 */
+	0x12,  0x86,  0x28,  0x14,  0x4F,  0xBA,  0x10,  0x03,  0x7C,  0x50,  0x49,  0x04,  0x10,  0x83,  0x08,  0xA2, 	/* 12930 */
+	0x10,  0x01,  0x00,  0x1F,  0xC2,  0x40,  0x44,  0x00,  0x40,  0xFF,  0xE0,  0x40,  0x06,  0x00,  0x90,  0x30, 	/* 12940 */
+	0x8C,  0x06,  0xA3,  0x08,  0x00,  0x90,  0x10,  0xC7,  0xF2,  0x10,  0x01,  0xFC,  0x24,  0x04,  0x40,  0xFF, 	/* 12950 */
+	0xE0,  0xA0,  0x31,  0x8C,  0x06,  0xA5,  0x20,  0x02,  0x00,  0x7F,  0xE5,  0x22,  0x92,  0x2F,  0xE2,  0x12, 	/* 12960 */
+	0x21,  0x22,  0x2A,  0x22,  0x7E,  0x42,  0x08,  0x00,  0xA7,  0x40,  0x24,  0x3A,  0x78,  0xAA,  0x0A,  0x23, 	/* 12970 */
+	0xAF,  0xC2,  0x27,  0xA3,  0x0A,  0x50,  0xA4,  0x8A,  0x80,  0xA0,  0x32,  0xA9,  0x40,  0x04,  0x7E,  0x7C, 	/* 12980 */
+	0x0A,  0x40,  0xA7,  0xC2,  0x44,  0x7C,  0x42,  0x7C,  0x34,  0x04,  0xC0,  0x44,  0x08,  0x7E,  0xAD,  0x40, 	/* 12990 */
+	0x04,  0x7E,  0x78,  0x05,  0x3C,  0x92,  0x41,  0x24,  0x7B,  0xC1,  0x00,  0x2C,  0x42,  0xA4,  0x42,  0x88, 	/* 129A0 */
+	0xFF,  0xAE,  0x40,  0xC4,  0x70,  0x79,  0x0A,  0xFE,  0x23,  0x4F,  0xD2,  0x29,  0x02,  0xFE,  0x52,  0x44, 	/* 129B0 */
+	0x64,  0x81,  0x80,  0x64,  0xAF,  0x47,  0xC4,  0x10,  0x77,  0xEA,  0x28,  0xAC,  0x62,  0x38,  0xF2,  0x82, 	/* 129C0 */
+	0xFE,  0x5B,  0xA4,  0xAA,  0x8B,  0xA0,  0x86,  0xB3,  0x00,  0x07,  0xFE,  0x04,  0x00,  0x40,  0x08,  0x00, 	/* 129D0 */
+	0x80,  0x1F,  0xC2,  0x84,  0x48,  0x48,  0x84,  0x08,  0x40,  0xFC,  0xBC,  0x00,  0x0F,  0xFE,  0x21,  0x02, 	/* 129E0 */
+	0x10,  0x41,  0x07,  0x90,  0xC9,  0x04,  0x90,  0x49,  0x04,  0x90,  0x79,  0x00,  0x7E,  0x82,  0x01,  0x0F, 	/* 129F0 */
+	0xD0,  0x21,  0x82,  0x54,  0x45,  0x47,  0x52,  0xD9,  0x65,  0x34,  0x50,  0x87,  0x10,  0x06,  0x01,  0x80, 	/* 12A00 */
+	0x8C,  0x04,  0x0F,  0xDE,  0x24,  0xA2,  0x5A,  0x4E,  0xA7,  0x4A,  0xD4,  0xA5,  0x5A,  0x56,  0xA5,  0x12, 	/* 12A10 */
+	0x71,  0x20,  0x26,  0x92,  0x04,  0x8F,  0x48,  0x24,  0x82,  0x4A,  0x47,  0xC7,  0x48,  0xD4,  0x85,  0x48, 	/* 12A20 */
+	0x54,  0x85,  0x4A,  0x77,  0xA0,  0xC6,  0x94,  0x00,  0x0F,  0xFE,  0x22,  0x42,  0x24,  0x42,  0x47,  0xFE, 	/* 12A30 */
+	0xCA,  0x44,  0xA4,  0x4A,  0x47,  0xC4,  0x04,  0x40,  0x84,  0x95,  0x02,  0x0F,  0xA0,  0x2F,  0x82,  0x28, 	/* 12A40 */
+	0x42,  0xA7,  0x46,  0xD9,  0x05,  0xFE,  0x51,  0x05,  0x10,  0x71,  0x00,  0x10,  0xA0,  0x00,  0x0F,  0xBC, 	/* 12A50 */
+	0x22,  0x42,  0x24,  0x43,  0xC7,  0xA4,  0xCA,  0x44,  0xBC,  0x4A,  0x44,  0xA4,  0x7A,  0x40,  0xFE,  0xA5, 	/* 12A60 */
+	0x00,  0x6F,  0xF8,  0x24,  0x82,  0x48,  0x47,  0xE7,  0x48,  0xD4,  0x85,  0x48,  0x56,  0x45,  0x86,  0x70, 	/* 12A70 */
+	0x60,  0x7A,  0xA6,  0x12,  0x05,  0x24,  0x5B,  0x85,  0x20,  0x5E,  0x2F,  0x1E,  0x00,  0x0F,  0xFE,  0x08, 	/* 12A80 */
+	0x03,  0xF8,  0xD0,  0x81,  0xF8,  0xA7,  0x01,  0x0F,  0x90,  0x21,  0x02,  0x1E,  0x41,  0x07,  0x90,  0xC9, 	/* 12A90 */
+	0x04,  0xFC,  0x4C,  0x44,  0xC4,  0x7C,  0x40,  0x7C,  0xB2,  0x02,  0x0F,  0xA0,  0x27,  0xE2,  0x82,  0x47, 	/* 12AA0 */
+	0xA7,  0x8A,  0xCB,  0xA4,  0xAC,  0x4A,  0x04,  0xA0,  0x7A,  0x20,  0x1E,  0xB4,  0x01,  0x0F,  0x90,  0x27, 	/* 12AB0 */
+	0xE2,  0x52,  0x45,  0x47,  0x7C,  0xD4,  0x45,  0x64,  0x55,  0x87,  0x98,  0x0A,  0x41,  0x42,  0xBA,  0x00, 	/* 12AC0 */
+	0x4F,  0xF8,  0x24,  0x02,  0x7E,  0x45,  0x07,  0x50,  0xD5,  0xC5,  0x54,  0x59,  0x47,  0xA4,  0x12,  0x42, 	/* 12AD0 */
+	0x4C,  0xBF,  0x00,  0x8F,  0x88,  0x27,  0xE2,  0x40,  0x44,  0x87,  0x48,  0xD4,  0x85,  0x4C,  0x55,  0x47, 	/* 12AE0 */
+	0x96,  0x0F,  0xA1,  0x02,  0x85,  0x01,  0x0F,  0x90,  0x27,  0xC2,  0x10,  0x41,  0x07,  0xFE,  0xD1,  0x05, 	/* 12AF0 */
+	0x10,  0x57,  0xC5,  0x10,  0x71,  0x00,  0xFE,  0x9D,  0x01,  0x0F,  0xD2,  0x23,  0x42,  0x7C,  0x44,  0x47, 	/* 12B00 */
+	0x44,  0xD7,  0xC5,  0x44,  0x57,  0xC5,  0x44,  0x74,  0x40,  0x4C,  0xAB,  0x01,  0x0F,  0xFE,  0x23,  0x02, 	/* 12B10 */
+	0x48,  0x4F,  0x47,  0x04,  0xDA,  0x85,  0xA8,  0x5A,  0x87,  0xAA,  0x0A,  0xA1,  0x06,  0xAC,  0x00,  0x0F, 	/* 12B20 */
+	0xFE,  0x21,  0x02,  0xFC,  0x49,  0x47,  0xFC,  0xD9,  0x45,  0xFC,  0x55,  0x07,  0x20,  0x0D,  0x83,  0x06, 	/* 12B30 */
+	0xAF,  0x00,  0x0F,  0xFC,  0x24,  0x42,  0x7C,  0x44,  0x47,  0x7C,  0xD4,  0x45,  0x7C,  0x52,  0x85,  0x28, 	/* 12B40 */
+	0x74,  0xA0,  0x86,  0xB2,  0x01,  0x4F,  0xD2,  0x22,  0xA2,  0x4A,  0x41,  0x47,  0xA2,  0xCC,  0x14,  0xBE, 	/* 12B50 */
+	0x4A,  0x24,  0xA2,  0x7A,  0x20,  0x3E,  0xB4,  0x02,  0x4F,  0x24,  0x2F,  0xE2,  0x24,  0x45,  0x07,  0x52, 	/* 12B60 */
+	0xDD,  0x45,  0x58,  0x55,  0x05,  0x50,  0x75,  0x20,  0x4E,  0xBC,  0x00,  0x0F,  0xEE,  0x2A,  0xA2,  0xAA, 	/* 12B70 */
+	0x4E,  0xE7,  0xAA,  0xDA,  0xA5,  0xEE,  0x5A,  0xA5,  0xAA,  0x7A,  0xA1,  0x76,  0x81,  0x10,  0x87,  0xFE, 	/* 12B80 */
+	0x10,  0x81,  0xF8,  0x10,  0x81,  0xF8,  0x10,  0x8F,  0xFF,  0x14,  0x82,  0xFC,  0xD8,  0xB0,  0xF8,  0x86, 	/* 12B90 */
+	0x41,  0x02,  0xFE,  0x89,  0x24,  0xFC,  0x2A,  0x44,  0x98,  0x96,  0x6F,  0xFE,  0x08,  0x03,  0xFC,  0xD0, 	/* 12BA0 */
+	0x41,  0xFC,  0x87,  0x01,  0x0F,  0xFE,  0x28,  0x22,  0x00,  0x7F,  0xE5,  0x10,  0xD5,  0x05,  0x50,  0x55, 	/* 12BB0 */
+	0xC7,  0x50,  0x0B,  0x01,  0x0E,  0x8C,  0x02,  0x0F,  0xBC,  0x24,  0x42,  0x78,  0x40,  0x87,  0xFE,  0xD1, 	/* 12BC0 */
+	0x25,  0xDA,  0x53,  0x45,  0x54,  0x79,  0x20,  0x30,  0x8D,  0x00,  0x0F,  0x7C,  0x24,  0x42,  0x7C,  0x44, 	/* 12BD0 */
+	0x47,  0xFE,  0xD0,  0x45,  0xFE,  0x52,  0x45,  0x14,  0x70,  0x40,  0x0C,  0x8E,  0x01,  0x0F,  0x90,  0x2F, 	/* 12BE0 */
+	0xE2,  0x44,  0x44,  0x47,  0x6C,  0xD9,  0x25,  0x10,  0x5F,  0xE5,  0x10,  0x71,  0x00,  0x10,  0x91,  0x01, 	/* 12BF0 */
+	0x0F,  0xA0,  0x27,  0xE2,  0x52,  0x47,  0xE7,  0x52,  0xD7,  0xE5,  0x28,  0x54,  0x85,  0xFE,  0x70,  0x80, 	/* 12C00 */
+	0x08,  0x93,  0x02,  0x4F,  0x48,  0x27,  0xE2,  0xC8,  0x54,  0x87,  0x7E,  0xD4,  0x85,  0x48,  0x57,  0xE5, 	/* 12C10 */
+	0x48,  0x74,  0x80,  0x7E,  0x95,  0x01,  0x0F,  0xFE,  0x21,  0x02,  0x28,  0x44,  0x47,  0xFE,  0xD0,  0x45, 	/* 12C20 */
+	0x74,  0x55,  0x45,  0x74,  0x70,  0x40,  0x0C,  0x97,  0x00,  0x8F,  0x08,  0x2F,  0xF2,  0x81,  0x47,  0x77, 	/* 12C30 */
+	0x55,  0xD5,  0x55,  0xB7,  0x51,  0x45,  0x24,  0x74,  0x50,  0x83,  0x9A,  0x01,  0x0F,  0x90,  0x2F,  0xE2, 	/* 12C40 */
+	0x44,  0x42,  0x87,  0xFE,  0xD0,  0x05,  0x7C,  0x54,  0x45,  0x44,  0x74,  0x40,  0x7C,  0xA3,  0x00,  0x0F, 	/* 12C50 */
+	0xFC,  0x24,  0x42,  0x7C,  0x44,  0x47,  0x7C,  0xD2,  0x05,  0x7E,  0x5D,  0x25,  0x6A,  0x77,  0xA0,  0x0C, 	/* 12C60 */
+	0xA7,  0x00,  0x8F,  0xBE,  0x22,  0x2F,  0xBE,  0x3A,  0x2E,  0x3E,  0x00,  0x0F,  0xFE,  0x10,  0x03,  0xFC, 	/* 12C70 */
+	0xD0,  0x41,  0xFC,  0xA9,  0x00,  0x0F,  0xFE,  0x22,  0x02,  0x7C,  0x44,  0x47,  0x7C,  0xD4,  0x45,  0x7C, 	/* 12C80 */
+	0x54,  0x45,  0x7C,  0x72,  0x40,  0xC2,  0xAA,  0x02,  0x4F,  0xFE,  0x22,  0x42,  0x3C,  0x42,  0x47,  0x3C, 	/* 12C90 */
+	0xD2,  0x45,  0xFF,  0x55,  0x45,  0x66,  0x74,  0x00,  0x7E,  0xAF,  0x02,  0xAF,  0xAA,  0x25,  0x42,  0x2A, 	/* 12CA0 */
+	0x42,  0xA7,  0x7E,  0xD4,  0xA5,  0x6A,  0x55,  0x25,  0x6A,  0x74,  0x60,  0x7E,  0xB5,  0x01,  0x0F,  0x9E, 	/* 12CB0 */
+	0x21,  0x02,  0x7C,  0x44,  0x47,  0x7C,  0xD4,  0x45,  0x7C,  0x54,  0x45,  0x7C,  0x72,  0x40,  0xC2,  0xBA, 	/* 12CC0 */
+	0x01,  0x0F,  0xFE,  0x2A,  0x22,  0x28,  0x47,  0xE7,  0xC8,  0xD7,  0xC5,  0x48,  0x57,  0xC5,  0x48,  0x74, 	/* 12CD0 */
+	0x80,  0x7E,  0xBC,  0x00,  0x0F,  0xFE,  0x24,  0x82,  0x7E,  0x44,  0x87,  0x7E,  0xD4,  0x85,  0x7E,  0x50, 	/* 12CE0 */
+	0x25,  0x56,  0x75,  0x20,  0x8C,  0xBE,  0x00,  0x0F,  0xFE,  0x24,  0x22,  0x7E,  0x45,  0x47,  0x7E,  0xD5, 	/* 12CF0 */
+	0x45,  0x7F,  0x56,  0xA7,  0xA4,  0x4B,  0xA1,  0x61,  0x81,  0x04,  0x4F,  0x28,  0x2F,  0xE2,  0x24,  0x42, 	/* 12D00 */
+	0x47,  0xDA,  0xD5,  0xA5,  0x24,  0x56,  0xC5,  0x5A,  0x7F,  0xE0,  0x12,  0x85,  0x01,  0x0F,  0xFE,  0x24, 	/* 12D10 */
+	0x42,  0x28,  0x4F,  0xE7,  0x92,  0xDF,  0xE5,  0x20,  0x53,  0xC5,  0x24,  0x74,  0x40,  0x98,  0x86,  0x00, 	/* 12D20 */
+	0x0F,  0xFC,  0x24,  0x42,  0x5C,  0x45,  0x47,  0xFF,  0xD4,  0x55,  0x7C,  0x54,  0x45,  0x7C,  0x74,  0x40, 	/* 12D30 */
+	0x4C,  0x8A,  0x00,  0x07,  0xFC,  0x10,  0x03,  0xF8,  0x50,  0x81,  0xF8,  0xFB,  0xF2,  0x08,  0x79,  0xEC, 	/* 12D40 */
+	0xB2,  0x4D,  0x27,  0x9E,  0x8B,  0x04,  0x4F,  0x28,  0x2F,  0xE2,  0x10,  0x47,  0xC7,  0x10,  0xDF,  0xE5, 	/* 12D50 */
+	0x20,  0x57,  0xE5,  0x88,  0x70,  0x80,  0x7E,  0x90,  0x23,  0x87,  0xAA,  0x4A,  0xEF,  0xFC,  0x5A,  0x44, 	/* 12D60 */
+	0x98,  0x9E,  0x67,  0xFE,  0x08,  0x03,  0xFC,  0xD0,  0x41,  0xFC,  0x91,  0x01,  0x0F,  0x92,  0x2F,  0xE2, 	/* 12D70 */
+	0x00,  0x4F,  0xE7,  0x00,  0xD7,  0xC5,  0x44,  0x57,  0xC5,  0x44,  0x72,  0x80,  0xFE,  0x94,  0x04,  0x4F, 	/* 12D80 */
+	0x74,  0x25,  0xE2,  0xB4,  0x43,  0xE7,  0x44,  0xD9,  0x45,  0xFE,  0x53,  0x85,  0x54,  0x79,  0x20,  0x10, 	/* 12D90 */
+	0x9A,  0x01,  0x0F,  0xFE,  0x25,  0x42,  0x7C,  0x45,  0x47,  0x7C,  0xD1,  0x25,  0xFD,  0x50,  0x45,  0xFE, 	/* 12DA0 */
+	0x72,  0x40,  0x0C,  0xA7,  0x01,  0x0F,  0xFE,  0x21,  0x02,  0x7C,  0x41,  0x07,  0xFF,  0xD4,  0x45,  0x7C, 	/* 12DB0 */
+	0x54,  0x45,  0x7C,  0x72,  0x40,  0xC2,  0xA8,  0x02,  0x07,  0xFE,  0x48,  0x87,  0xFE,  0x5D,  0xC6,  0xAA, 	/* 12DC0 */
+	0x48,  0x87,  0xFE,  0x48,  0x09,  0xFC,  0xA8,  0x40,  0xFC,  0xAC,  0x11,  0xCF,  0xD4,  0x12,  0x67,  0xFC, 	/* 12DD0 */
+	0x55,  0x47,  0xCC,  0x83,  0x2F,  0xFE,  0x10,  0x03,  0xFC,  0xD0,  0x41,  0xFC,  0xAF,  0x04,  0x4F,  0xAA, 	/* 12DE0 */
+	0x2D,  0xC2,  0x56,  0x4F,  0xE7,  0x1A,  0xDF,  0xF5,  0x4A,  0x54,  0xC5,  0xBA,  0x72,  0x60,  0xC2,  0xB4, 	/* 12DF0 */
+	0x06,  0xAF,  0xAC,  0x2A,  0xA2,  0x44,  0x4B,  0xA7,  0x01,  0xD7,  0xC5,  0x44,  0x57,  0xC5,  0x24,  0x71, 	/* 12E00 */
+	0x80,  0xFE,  0xBD,  0x01,  0x0F,  0x7C,  0x21,  0x02,  0xFE,  0x44,  0x47,  0xEE,  0xD4,  0x45,  0xFE,  0x50, 	/* 12E10 */
+	0x05,  0xFE,  0x72,  0x80,  0xCE,  0x81,  0x02,  0x4F,  0x28,  0x27,  0xE2,  0xC8,  0x47,  0xE7,  0x48,  0xD7, 	/* 12E20 */
+	0xE5,  0x48,  0x57,  0xE5,  0x00,  0x76,  0xA0,  0x95,  0x87,  0x01,  0x0F,  0xFE,  0x24,  0xA2,  0x76,  0x45, 	/* 12E30 */
+	0xA7,  0xFE,  0xD5,  0xA5,  0x76,  0x51,  0x05,  0xFF,  0x72,  0x80,  0xC6,  0x8E,  0x04,  0x8F,  0xFE,  0x24, 	/* 12E40 */
+	0x82,  0xEC,  0x55,  0xA4,  0x48,  0x7F,  0xED,  0x10,  0x55,  0xE5,  0x50,  0x77,  0x00,  0x8F,  0x91,  0x05, 	/* 12E50 */
+	0x2F,  0xB4,  0x27,  0xE2,  0x42,  0x43,  0xC7,  0x24,  0xD3,  0xC5,  0x7E,  0x55,  0x25,  0x7E,  0x75,  0x20, 	/* 12E60 */
+	0x7E,  0x92,  0x04,  0x4F,  0xFE,  0x21,  0x02,  0x7C,  0x41,  0x07,  0xFE,  0xD2,  0x85,  0xCA,  0x5F,  0xE5, 	/* 12E70 */
+	0x44,  0x7E,  0xA0,  0x52,  0x99,  0x09,  0xEF,  0xEA,  0x28,  0x42,  0x9F,  0x47,  0x67,  0x44,  0xDF,  0x45, 	/* 12E80 */
+	0xA6,  0x5F,  0x47,  0x5C,  0x0B,  0x41,  0x23,  0xA6,  0x01,  0x0F,  0xFE,  0x25,  0x42,  0x7E,  0x45,  0x47, 	/* 12E90 */
+	0x7F,  0xD6,  0xA5,  0x7E,  0x56,  0xA7,  0xBE,  0x49,  0x41,  0x22,  0xAA,  0x00,  0x0F,  0xFE,  0x26,  0x82, 	/* 12EA0 */
+	0x7E,  0x45,  0x47,  0x7C,  0xD5,  0x45,  0x7C,  0x57,  0xE7,  0xD2,  0x0F,  0xA1,  0x46,  0xAB,  0x09,  0x2F, 	/* 12EB0 */
+	0x54,  0x2B,  0xA2,  0xEC,  0x4B,  0xA7,  0xEE,  0xDB,  0xA5,  0x10,  0x5F,  0xE7,  0x34,  0x0D,  0x20,  0x10, 	/* 12EC0 */
+	0xAC,  0x2A,  0x8F,  0x5E,  0x2A,  0xC7,  0x5A,  0xAA,  0x8F,  0xFE,  0x11,  0x03,  0xF8,  0xC8,  0x61,  0xF8, 	/* 12ED0 */
+	0x68,  0x80,  0xF8,  0xBA,  0x00,  0x03,  0xF8,  0x00,  0x00,  0x00,  0xFF,  0xE0,  0x40,  0x24,  0x82,  0x44, 	/* 12EE0 */
+	0x44,  0x28,  0x42,  0x04,  0x00,  0xC0,  0xBC,  0x22,  0x02,  0x20,  0xFA,  0x00,  0xA0,  0x12,  0x03,  0x20, 	/* 12EF0 */
+	0x6A,  0x0A,  0x60,  0x22,  0x02,  0x22,  0x22,  0x22,  0x1E,  0xBE,  0x21,  0x02,  0x10,  0xF9,  0x01,  0x10, 	/* 12F00 */
+	0x17,  0xC2,  0x10,  0x71,  0x06,  0x90,  0xA1,  0x02,  0x10,  0x2F,  0xE2,  0x00,  0x80,  0x00,  0x07,  0x3C, 	/* 12F10 */
+	0x02,  0x40,  0x24,  0xFA,  0x42,  0x3C,  0xAA,  0x0A,  0xA0,  0xAA,  0x0A,  0xA2,  0xA2,  0x22,  0x1E,  0x81, 	/* 12F20 */
+	0x20,  0x02,  0x3C,  0xFA,  0x40,  0xA8,  0x13,  0x02,  0x28,  0x72,  0x4A,  0xA2,  0x22,  0x22,  0x2C,  0x22, 	/* 12F30 */
+	0x02,  0x20,  0x87,  0x20,  0xC2,  0x78,  0xFC,  0x80,  0xC8,  0x14,  0x82,  0x7E,  0x74,  0x8A,  0xC8,  0x24, 	/* 12F40 */
+	0x82,  0x44,  0x27,  0x62,  0xC2,  0x88,  0x20,  0x42,  0x78,  0xF4,  0x01,  0x40,  0x17,  0xE2,  0x48,  0x74, 	/* 12F50 */
+	0x8A,  0xC8,  0x24,  0x82,  0x88,  0x28,  0x83,  0x08,  0x89,  0x21,  0x02,  0x10,  0xF1,  0x01,  0x10,  0x15, 	/* 12F60 */
+	0xE2,  0x50,  0x75,  0x0A,  0x50,  0x25,  0x02,  0x50,  0x25,  0x02,  0xFE,  0x90,  0x21,  0x02,  0x10,  0xFF, 	/* 12F70 */
+	0xF1,  0x10,  0x21,  0x02,  0x20,  0x73,  0xEA,  0xE2,  0x26,  0x22,  0xA2,  0x22,  0x22,  0x3E,  0x93,  0x02, 	/* 12F80 */
+	0x8F,  0x24,  0x07,  0xEF,  0x20,  0x22,  0x0A,  0xA4,  0xAA,  0x4A,  0xD4,  0xAC,  0x8A,  0x88,  0x21,  0x42, 	/* 12F90 */
+	0x62,  0x95,  0xF1,  0x00,  0x08,  0xF8,  0x02,  0x12,  0x21,  0x2A,  0xD4,  0xAD,  0x4A,  0x9A,  0xA9,  0x2A, 	/* 12FA0 */
+	0x30,  0x25,  0x22,  0x0E,  0x96,  0x20,  0x02,  0x7C,  0xF4,  0x41,  0x44,  0x27,  0xC2,  0x44,  0x74,  0x4A, 	/* 12FB0 */
+	0xFC,  0x24,  0x42,  0x44,  0x24,  0x42,  0xFE,  0x97,  0x00,  0x67,  0x38,  0x02,  0x80,  0x28,  0xFA,  0x82, 	/* 12FC0 */
+	0x3E,  0xAA,  0x8A,  0xA8,  0xAA,  0x4A,  0x76,  0xA0,  0x22,  0x7A,  0x9A,  0x02,  0x07,  0x20,  0x03,  0xE0, 	/* 12FD0 */
+	0x30,  0xFD,  0x02,  0x5E,  0xA9,  0x0A,  0x90,  0xA9,  0xEA,  0x90,  0xA1,  0x02,  0x10,  0x9D,  0x20,  0x02, 	/* 12FE0 */
+	0x7C,  0xF4,  0x41,  0x44,  0x24,  0x42,  0x7C,  0x72,  0x8A,  0xA8,  0x22,  0x82,  0x4A,  0x24,  0xA2,  0x86, 	/* 12FF0 */
+	0x9E,  0x21,  0x02,  0x10,  0xFF,  0xE1,  0x52,  0x17,  0xE2,  0x52,  0x35,  0x26,  0xFE,  0xA1,  0x02,  0x10, 	/* 13000 */
+	0x21,  0x02,  0x10,  0x9F,  0x04,  0x04,  0x44,  0x7F,  0xC0,  0x40,  0x7F,  0xE4,  0x02,  0x7F,  0xA0,  0x00, 	/* 13010 */
+	0xFF,  0xE1,  0x58,  0x64,  0x60,  0xC0,  0xA0,  0x00,  0x07,  0x7E,  0x00,  0x20,  0x3A,  0xF8,  0x22,  0x3A, 	/* 13020 */
+	0xAA,  0xAA,  0xAA,  0xAB,  0xAA,  0x82,  0xA0,  0x22,  0x06,  0xA2,  0x22,  0x02,  0x20,  0xF4,  0x01,  0x7E, 	/* 13030 */
+	0x29,  0x02,  0x10,  0x75,  0x4A,  0xD2,  0x25,  0x22,  0x92,  0x21,  0x02,  0x30,  0xA5,  0x24,  0x42,  0x28, 	/* 13040 */
+	0xF7,  0xE1,  0x10,  0x11,  0x02,  0x7C,  0x71,  0x0A,  0x90,  0x2F,  0xE2,  0x10,  0x21,  0x02,  0x10,  0xA8, 	/* 13050 */
+	0xFF,  0xE0,  0xA0,  0x7F,  0xC4,  0xA4,  0x7F,  0xC0,  0x00,  0x7F,  0xC0,  0x00,  0xFF,  0xE2,  0x58,  0xC4, 	/* 13060 */
+	0x60,  0xC0,  0xAD,  0x20,  0x03,  0xFC,  0x4A,  0x8A,  0x90,  0x52,  0x82,  0x46,  0xDF,  0x80,  0x00,  0x7F, 	/* 13070 */
+	0xE2,  0x50,  0x24,  0x84,  0xC4,  0xB7,  0x21,  0x02,  0x7E,  0xF1,  0x01,  0x7C,  0x21,  0x02,  0xFE,  0x72, 	/* 13080 */
+	0x4A,  0xFE,  0x26,  0x42,  0x94,  0x30,  0x42,  0x0C,  0xBA,  0x02,  0x47,  0x24,  0x0F,  0xE0,  0x24,  0xFB, 	/* 13090 */
+	0xC2,  0x24,  0xAB,  0xCA,  0xA4,  0xAA,  0x4A,  0x7E,  0xA1,  0x42,  0x62,  0xBF,  0x01,  0x0F,  0x1E,  0x02, 	/* 130A0 */
+	0x4F,  0xFE,  0x20,  0x8A,  0xFE,  0xA8,  0xAA,  0xAA,  0xA9,  0xCA,  0x2A,  0x2C,  0x92,  0x18,  0x80,  0x04, 	/* 130B0 */
+	0x0F,  0xFE,  0x2A,  0x82,  0xE8,  0x20,  0x83,  0xF8,  0x7F,  0xC0,  0x00,  0xFF,  0xE2,  0x48,  0xC4,  0x40, 	/* 130C0 */
+	0xC0,  0x81,  0x21,  0x0F,  0xFE,  0x33,  0x02,  0xD8,  0x65,  0x4A,  0x12,  0x3F,  0x80,  0x00,  0xFF,  0xE2, 	/* 130D0 */
+	0x48,  0xC4,  0x40,  0xC0,  0x84,  0x20,  0x02,  0x7C,  0xF0,  0x41,  0x7C,  0x20,  0x42,  0xFE,  0x79,  0x2A, 	/* 130E0 */
+	0x54,  0x23,  0x82,  0xD4,  0x21,  0x22,  0x30,  0x85,  0x29,  0x22,  0x54,  0xF7,  0xC1,  0x54,  0x27,  0xC3, 	/* 130F0 */
+	0x54,  0x6F,  0xCA,  0x10,  0x2F,  0xE2,  0x10,  0x21,  0x02,  0x10,  0x8A,  0x04,  0x0E,  0xFE,  0x04,  0xAF, 	/* 13100 */
+	0xEA,  0x24,  0xAA,  0x72,  0xBA,  0x6A,  0x90,  0xAF,  0xEA,  0x90,  0x22,  0x82,  0xC6,  0x8D,  0x27,  0xC2, 	/* 13110 */
+	0x44,  0xF5,  0xC1,  0x54,  0x25,  0x42,  0xFE,  0x78,  0x2A,  0xBA,  0x2A,  0xA2,  0xAA,  0x2B,  0xA2,  0x86, 	/* 13120 */
+	0x8E,  0x21,  0x02,  0x1E,  0xF1,  0x01,  0x7C,  0x24,  0x42,  0x7C,  0x74,  0x4A,  0xFC,  0x24,  0x42,  0x7C, 	/* 13130 */
+	0x22,  0x42,  0xC2,  0x8F,  0x2F,  0xE2,  0x00,  0xF7,  0xC1,  0x44,  0x27,  0xC3,  0x00,  0x6F,  0xEA,  0x92, 	/* 13140 */
+	0x2F,  0xE2,  0x92,  0x29,  0x22,  0xFE,  0x9D,  0x07,  0xC7,  0x54,  0x07,  0xCF,  0xD4,  0x27,  0xCB,  0x28, 	/* 13150 */
+	0xB4,  0xEB,  0x78,  0xAC,  0x8A,  0x30,  0x24,  0x83,  0x86,  0xA6,  0x28,  0xE4,  0xFA,  0xAA,  0xA6,  0x3A, 	/* 13160 */
+	0xAA,  0xE2,  0xF8,  0x20,  0x87,  0xFC,  0x00,  0x0F,  0xFE,  0x15,  0x06,  0x4C,  0xA7,  0x01,  0x0F,  0xFE, 	/* 13170 */
+	0x01,  0x0F,  0x7C,  0x24,  0x4A,  0xFC,  0xAA,  0x8A,  0xFE,  0xA8,  0x0A,  0x7C,  0x24,  0x42,  0x7C,  0xAA, 	/* 13180 */
+	0x0E,  0xEF,  0xAA,  0x0E,  0xEF,  0x80,  0x27,  0xCA,  0xD4,  0xAF,  0xCA,  0xD4,  0xA7,  0xCA,  0x10,  0x2F, 	/* 13190 */
+	0xE2,  0x10,  0xAE,  0x01,  0x87,  0x7E,  0x05,  0xAF,  0xFE,  0x25,  0xAA,  0xFE,  0xA8,  0x0A,  0xFE,  0xAC, 	/* 131A0 */
+	0x4A,  0x7C,  0x22,  0x82,  0xFE,  0xB0,  0x2F,  0xE2,  0x54,  0xF9,  0x21,  0xFE,  0x29,  0x22,  0xD6,  0x7B, 	/* 131B0 */
+	0xAA,  0xD6,  0x2B,  0xA2,  0xD6,  0x29,  0x22,  0x96,  0xB3,  0x01,  0x07,  0x7E,  0x00,  0x0F,  0xEE,  0x2A, 	/* 131C0 */
+	0xAA,  0xEE,  0xB2,  0x8B,  0xFE,  0xB2,  0x2A,  0xD4,  0x24,  0x82,  0xE6,  0xB9,  0x01,  0xC7,  0xE0,  0x04, 	/* 131D0 */
+	0x07,  0xFC,  0x44,  0x47,  0xFC,  0x04,  0x0F,  0xFE,  0x86,  0x28,  0x52,  0xBE,  0xA8,  0x06,  0xBA,  0x00, 	/* 131E0 */
+	0x07,  0xFC,  0x44,  0x47,  0xFC,  0x44,  0x47,  0xFC,  0x04,  0x0F,  0xFE,  0x86,  0x28,  0x52,  0xBE,  0xA8, 	/* 131F0 */
+	0x06,  0xBD,  0x04,  0x00,  0xB0,  0x3F,  0xCC,  0x93,  0x26,  0x42,  0x94,  0x3F,  0xC0,  0x40,  0x7F,  0xE4, 	/* 13200 */
+	0x52,  0x5F,  0xA4,  0x0A,  0xBE,  0x01,  0x87,  0xE0,  0x04,  0x00,  0x40,  0xFF,  0xE0,  0x40,  0x0E,  0x01, 	/* 13210 */
+	0x50,  0x24,  0x8C,  0x46,  0x04,  0x00,  0x40,  0xBF,  0x01,  0xC3,  0xE0,  0x04,  0x0F,  0xFE,  0x0E,  0x03, 	/* 13220 */
+	0x58,  0xC4,  0x60,  0x90,  0x09,  0x00,  0x92,  0x31,  0x2C,  0x0E,  0x80,  0x00,  0x83,  0xF0,  0x04,  0x0F, 	/* 13230 */
+	0xFE,  0x0E,  0x03,  0x58,  0xC4,  0x63,  0xF0,  0x09,  0xC0,  0x84,  0x10,  0x46,  0x18,  0x81,  0x0D,  0x07, 	/* 13240 */
+	0x10,  0x11,  0x01,  0x10,  0x7D,  0x03,  0x20,  0x3A,  0x85,  0x24,  0x52,  0x49,  0x5E,  0x1E,  0x21,  0x02, 	/* 13250 */
+	0x89,  0x01,  0x83,  0xE0,  0x04,  0x0F,  0xFE,  0x04,  0x8F,  0xFE,  0x04,  0x87,  0xF8,  0x0E,  0x03,  0x58, 	/* 13260 */
+	0xC4,  0x60,  0x40,  0x8B,  0x19,  0x0E,  0x10,  0x21,  0x22,  0x52,  0xFD,  0x42,  0x98,  0x71,  0x06,  0x90, 	/* 13270 */
+	0xA2,  0x8A,  0x28,  0x24,  0x42,  0x82,  0x91,  0x18,  0x4E,  0x24,  0x21,  0x42,  0x04,  0xFA,  0x43,  0x14, 	/* 13280 */
+	0x68,  0x46,  0x0F,  0xA7,  0x42,  0x04,  0x20,  0x42,  0x04,  0x92,  0x31,  0x0E,  0x10,  0x25,  0x82,  0x54, 	/* 13290 */
+	0xF5,  0x22,  0x96,  0x71,  0x46,  0xB8,  0xA0,  0x8A,  0x10,  0x26,  0x03,  0x80,  0x95,  0x14,  0x8E,  0x48, 	/* 132A0 */
+	0x24,  0x8F,  0x49,  0x27,  0xA7,  0x4C,  0x74,  0x8A,  0x48,  0xA4,  0x8A,  0x48,  0x27,  0x92,  0xC7,  0x98, 	/* 132B0 */
+	0x12,  0x0E,  0x10,  0x21,  0x4F,  0x24,  0x2A,  0x86,  0xA8,  0x7B,  0x46,  0xB2,  0xB2,  0x2A,  0x60,  0x3A, 	/* 132C0 */
+	0x42,  0x1C,  0x9F,  0x10,  0x0E,  0x7C,  0x24,  0x42,  0x44,  0xFF,  0xC2,  0x44,  0x74,  0x46,  0xFC,  0xA4, 	/* 132D0 */
+	0x4A,  0x44,  0x24,  0x42,  0xFE,  0xA1,  0x12,  0x0E,  0x28,  0x22,  0x42,  0xFE,  0xF2,  0x02,  0x24,  0x72, 	/* 132E0 */
+	0x46,  0xA4,  0xA5,  0x8A,  0x48,  0x29,  0x43,  0x22,  0xA3,  0x19,  0x0E,  0x10,  0x2F,  0xE2,  0x10,  0xF9, 	/* 132F0 */
+	0x02,  0x7C,  0x71,  0x06,  0xB8,  0xA3,  0x8A,  0x54,  0x29,  0x22,  0x10,  0xA4,  0x30,  0x0E,  0xFE,  0x21, 	/* 13300 */
+	0x42,  0x54,  0xFB,  0x86,  0x30,  0x7F,  0xEA,  0x90,  0xA1,  0x02,  0x10,  0x21,  0x02,  0x10,  0xA6,  0x04, 	/* 13310 */
+	0x07,  0xFC,  0x04,  0x03,  0xF8,  0x0A,  0x0F,  0xFE,  0x26,  0x85,  0xC4,  0xBF,  0xB0,  0xE0,  0x35,  0x80, 	/* 13320 */
+	0x40,  0xA7,  0x31,  0x0E,  0x10,  0x27,  0xC2,  0x54,  0xF5,  0x42,  0x54,  0x7F,  0xF6,  0x90,  0xA3,  0x0A, 	/* 13330 */
+	0x28,  0x24,  0x42,  0x82,  0xA9,  0x31,  0x0E,  0x50,  0x25,  0x0F,  0x7E,  0x29,  0x06,  0x10,  0x77,  0xEA, 	/* 13340 */
+	0x90,  0xA2,  0x82,  0x28,  0x24,  0x43,  0x82,  0xAC,  0x18,  0x0E,  0x7E,  0x22,  0x02,  0x20,  0xFB,  0xE2, 	/* 13350 */
+	0x22,  0x72,  0x26,  0xBE,  0xA2,  0x0A,  0x20,  0x22,  0x02,  0x3E,  0xB0,  0x1A,  0x0E,  0x20,  0x27,  0xE2, 	/* 13360 */
+	0x50,  0xF9,  0x02,  0x18,  0x75,  0x46,  0xD4,  0xA5,  0x2A,  0x92,  0x21,  0x02,  0x30,  0xBB,  0x1A,  0x0E, 	/* 13370 */
+	0x3C,  0x24,  0x4F,  0xA8,  0x21,  0x07,  0x68,  0x69,  0xE6,  0x22,  0xAD,  0x4A,  0x08,  0x23,  0x02,  0xC0, 	/* 13380 */
+	0x80,  0x12,  0x4E,  0x18,  0x26,  0x42,  0xFE,  0xF5,  0x02,  0x7C,  0x6D,  0x47,  0x54,  0xA5,  0x4A,  0x5C, 	/* 13390 */
+	0x21,  0x02,  0x10,  0x88,  0x17,  0xCE,  0x44,  0x27,  0xC2,  0x44,  0xF7,  0xC2,  0x00,  0x77,  0xC6,  0x90, 	/* 133A0 */
+	0xA1,  0x0A,  0xFE,  0x21,  0x02,  0x10,  0x8B,  0x18,  0x0E,  0x7C,  0x24,  0x42,  0x44,  0xFF,  0xC2,  0x00, 	/* 133B0 */
+	0x77,  0xC6,  0x90,  0xA7,  0xCA,  0x10,  0x21,  0x02,  0xFE,  0x8D,  0x11,  0x0E,  0x54,  0x29,  0x22,  0x10, 	/* 133C0 */
+	0xF7,  0xC2,  0x44,  0x77,  0xC6,  0xC4,  0xA7,  0xCA,  0x44,  0x24,  0x42,  0x4C,  0x8E,  0x14,  0x4E,  0x28, 	/* 133D0 */
+	0x27,  0xC2,  0x44,  0xFC,  0x42,  0x7C,  0x71,  0x86,  0x98,  0xA2,  0x8A,  0x2A,  0x24,  0xA2,  0x86,  0x94, 	/* 133E0 */
+	0x09,  0x0F,  0x28,  0x24,  0x42,  0x3A,  0xF8,  0x02,  0x7C,  0x70,  0x86,  0x90,  0xA2,  0x8A,  0x6A,  0x2A, 	/* 133F0 */
+	0x52,  0x1C,  0x97,  0x08,  0x8F,  0x10,  0x27,  0xE2,  0x52,  0xFF,  0xE2,  0x52,  0x77,  0xE6,  0x28,  0xAF, 	/* 13400 */
+	0xEA,  0x08,  0x20,  0x82,  0x08,  0x98,  0x1A,  0x4E,  0x24,  0x27,  0xEF,  0xA4,  0x23,  0xC7,  0x24,  0x6B, 	/* 13410 */
+	0xC6,  0x24,  0xAF,  0xFA,  0x14,  0x22,  0x22,  0x42,  0x99,  0x19,  0x0E,  0x7E,  0x21,  0x02,  0xBC,  0xFA, 	/* 13420 */
+	0x42,  0xBC,  0x7A,  0x46,  0xBC,  0xAA,  0x4A,  0xBC,  0x28,  0x02,  0xFE,  0x9A,  0x12,  0x4E,  0x28,  0x27, 	/* 13430 */
+	0xE2,  0x48,  0xFC,  0x82,  0x7C,  0x74,  0x86,  0xC8,  0xA7,  0xCA,  0x48,  0x24,  0x82,  0x7E,  0x9C,  0x31, 	/* 13440 */
+	0x0E,  0x7E,  0x21,  0x02,  0xFE,  0xF2,  0x82,  0xCE,  0x61,  0x07,  0x3C,  0xAE,  0x42,  0x18,  0x22,  0x82, 	/* 13450 */
+	0xC6,  0x9F,  0x04,  0x0F,  0xFE,  0x2A,  0x82,  0xE8,  0x20,  0x83,  0xF8,  0x7F,  0xC0,  0x40,  0xFF,  0xE1, 	/* 13460 */
+	0x50,  0x24,  0xCC,  0x42,  0xA0,  0x17,  0xEE,  0x52,  0x25,  0x22,  0x7E,  0xF5,  0x22,  0x7E,  0x75,  0x26, 	/* 13470 */
+	0x7A,  0xA6,  0xAA,  0xBA,  0x28,  0x23,  0x06,  0xAE,  0x18,  0xCE,  0x70,  0x21,  0x02,  0xFE,  0xFD,  0x42, 	/* 13480 */
+	0x7C,  0x75,  0x46,  0xFC,  0xA1,  0x0A,  0x7C,  0x21,  0x02,  0xFE,  0xB1,  0x10,  0xEE,  0x74,  0x25,  0x22, 	/* 13490 */
+	0x8A,  0xF9,  0x02,  0x7C,  0x75,  0x46,  0xFC,  0xA5,  0x4A,  0xFE,  0x24,  0x42,  0x4C,  0xB2,  0x18,  0xEE, 	/* 134A0 */
+	0x7A,  0x22,  0xAF,  0xAC,  0x22,  0x87,  0x5E,  0x6D,  0x26,  0xD2,  0xA5,  0xEA,  0x52,  0x25,  0x22,  0x5E, 	/* 134B0 */
+	0xB7,  0x18,  0x0E,  0x7E,  0x24,  0xA2,  0x7E,  0xFC,  0xA2,  0x7E,  0x72,  0x86,  0xCF,  0xA3,  0xCA,  0xE4, 	/* 134C0 */
+	0x21,  0x82,  0xE6,  0xBB,  0x10,  0xEE,  0xF4,  0x25,  0x42,  0x92,  0xF2,  0x22,  0x6C,  0x74,  0x46,  0xC4, 	/* 134D0 */
+	0xA6,  0xCA,  0x44,  0x24,  0x42,  0x7C,  0xBC,  0x31,  0x0E,  0xFE,  0x28,  0x22,  0xFC,  0xFA,  0x03,  0x32, 	/* 134E0 */
+	0x6D,  0x4B,  0x38,  0xAD,  0x43,  0x12,  0x21,  0x02,  0x60,  0xBD,  0x12,  0x4E,  0xFE,  0x23,  0x02,  0x4E, 	/* 134F0 */
+	0xFC,  0x42,  0x78,  0x74,  0x26,  0xFE,  0xA4,  0x4A,  0x7C,  0x24,  0x42,  0x7C,  0xBE,  0x04,  0x0F,  0xFE, 	/* 13500 */
+	0x11,  0x07,  0xFC,  0x51,  0x45,  0xF4,  0x43,  0xC3,  0xC0,  0xFF,  0xE3,  0x58,  0xC4,  0x60,  0x40,  0xBF, 	/* 13510 */
+	0x19,  0x0E,  0xFE,  0x20,  0x02,  0x7C,  0xFC,  0x42,  0x7C,  0x6F,  0xE7,  0x82,  0xAB,  0xAA,  0xAA,  0x2B, 	/* 13520 */
+	0xA2,  0x86,  0x80,  0x23,  0x8F,  0xA8,  0x22,  0x8F,  0xAA,  0x8C,  0xE7,  0x80,  0x23,  0xCF,  0x84,  0x72, 	/* 13530 */
+	0x86,  0x90,  0xA2,  0x82,  0x46,  0x82,  0x31,  0x0E,  0xFE,  0x21,  0x0F,  0xFE,  0x29,  0x26,  0xFE,  0x79, 	/* 13540 */
+	0x26,  0xFE,  0xA0,  0x8A,  0xA8,  0x2A,  0x23,  0x1A,  0x83,  0x11,  0x0E,  0xFE,  0x28,  0x22,  0xAA,  0xFB, 	/* 13550 */
+	0x42,  0x52,  0x72,  0x86,  0x44,  0xAF,  0xEA,  0x44,  0x24,  0x42,  0x7C,  0x86,  0x11,  0x0E,  0x7C,  0x24, 	/* 13560 */
+	0x4F,  0xFC,  0x24,  0x43,  0x7C,  0x65,  0x47,  0x9A,  0xA1,  0x0A,  0x64,  0x21,  0x82,  0xE0,  0x89,  0x17, 	/* 13570 */
+	0xEE,  0x42,  0x27,  0xEF,  0x48,  0x26,  0xE6,  0x48,  0x75,  0x86,  0x5E,  0xAA,  0x8A,  0xFE,  0x30,  0x82, 	/* 13580 */
+	0x08,  0x8D,  0x11,  0x0E,  0xFE,  0x21,  0x02,  0x7C,  0xF1,  0x02,  0xFE,  0x74,  0x46,  0xFC,  0xA4,  0x4A, 	/* 13590 */
+	0x7C,  0x22,  0x42,  0xC2,  0x8E,  0x80,  0x0F,  0x7E,  0x81,  0x07,  0xBE,  0x02,  0x27,  0xBE,  0x22,  0x2F, 	/* 135A0 */
+	0xBE,  0x22,  0x27,  0x3E,  0xAA,  0x42,  0x42,  0x8F,  0x31,  0xEE,  0xE4,  0x29,  0x42,  0x58,  0xFF,  0xC2, 	/* 135B0 */
+	0x04,  0x77,  0xC6,  0x04,  0xAF,  0xCA,  0xB4,  0x2A,  0xA2,  0x9E,  0x90,  0x1A,  0x0E,  0x3C,  0x24,  0x82, 	/* 135C0 */
+	0x7C,  0xFD,  0x42,  0x7C,  0x75,  0x46,  0xFE,  0xA9,  0x2A,  0xFE,  0x21,  0x12,  0x0F,  0x97,  0x11,  0x0E, 	/* 135D0 */
+	0xFE,  0x25,  0x4F,  0x7C,  0x25,  0x46,  0x7C,  0x71,  0x46,  0xFA,  0xA3,  0x0A,  0xAA,  0x32,  0x22,  0x1E, 	/* 135E0 */
+	0xA1,  0x19,  0x0E,  0xFE,  0x21,  0x02,  0x54,  0xF5,  0x42,  0xBA,  0x71,  0x06,  0xFE,  0xAA,  0xAA,  0xBA, 	/* 135F0 */
+	0x28,  0x22,  0xFE,  0xA2,  0x11,  0x0E,  0x5C,  0x25,  0x0F,  0xFE,  0x20,  0xA6,  0xFE,  0x78,  0x86,  0xFA, 	/* 13600 */
+	0xAA,  0xAA,  0xB4,  0x2A,  0xC3,  0x52,  0xA3,  0x11,  0x0E,  0xFE,  0x22,  0x82,  0x44,  0xFA,  0xA2,  0xFC, 	/* 13610 */
+	0x72,  0x86,  0xFE,  0xA5,  0x2B,  0xCC,  0x27,  0x42,  0xC2,  0xA9,  0x10,  0xEE,  0xF4,  0x25,  0x22,  0x88, 	/* 13620 */
+	0xFF,  0xC2,  0x10,  0x7F,  0xE6,  0x04,  0xAF,  0xCA,  0x54,  0x2C,  0xA3,  0x3E,  0xAB,  0x32,  0x8E,  0xFE, 	/* 13630 */
+	0x22,  0x8F,  0x50,  0x27,  0xE6,  0xD0,  0x77,  0xC6,  0x50,  0xAF,  0xEA,  0x48,  0x23,  0x02,  0xCE,  0xB0, 	/* 13640 */
+	0x11,  0x0E,  0xFE,  0x2A,  0xA2,  0xEE,  0xF2,  0x82,  0xFE,  0x72,  0x86,  0xFE,  0xA2,  0x2B,  0xD4,  0x24, 	/* 13650 */
+	0x82,  0xE6,  0xB4,  0x04,  0x00,  0x40,  0xFF,  0xE8,  0x02,  0x80,  0x21,  0x70,  0x11,  0x01,  0x10,  0x20, 	/* 13660 */
+	0x82,  0x08,  0x40,  0x48,  0x02,  0xB6,  0x04,  0x0F,  0xFE,  0x92,  0x29,  0x22,  0x12,  0x42,  0x5C,  0x44, 	/* 13670 */
+	0x07,  0xF0,  0x09,  0x00,  0x92,  0x11,  0x26,  0x0E,  0xB9,  0x04,  0x0F,  0xFE,  0x8A,  0x21,  0x24,  0xE1, 	/* 13680 */
+	0xC1,  0xF8,  0x00,  0x83,  0xF8,  0x20,  0x03,  0xFC,  0x00,  0x40,  0x38,  0xBA,  0x04,  0x0F,  0xFE,  0x92, 	/* 13690 */
+	0x29,  0x22,  0x12,  0x42,  0x1C,  0x40,  0x03,  0xFC,  0x04,  0x00,  0x40,  0x04,  0x0F,  0xFE,  0xBD,  0x04, 	/* 136A0 */
+	0x0F,  0xFE,  0x8A,  0x21,  0x24,  0xE1,  0xC1,  0x10,  0x7F,  0xC1,  0x10,  0xFF,  0xE1,  0x10,  0x21,  0x04, 	/* 136B0 */
+	0x10,  0xBF,  0x04,  0x0F,  0xFE,  0x8A,  0x27,  0x3C,  0x00,  0x07,  0xFC,  0x11,  0x01,  0x10,  0xFF,  0xE0, 	/* 136C0 */
+	0xD0,  0x31,  0x0C,  0x30,  0x81,  0x04,  0x0F,  0xFE,  0x92,  0x29,  0x22,  0x12,  0x42,  0x5C,  0x44,  0x0F, 	/* 136D0 */
+	0xFE,  0x04,  0x00,  0xA0,  0x31,  0x8C,  0x06,  0x83,  0x04,  0x0F,  0xFE,  0x8A,  0x28,  0xA2,  0x73,  0xC0, 	/* 136E0 */
+	0x00,  0x4F,  0xCF,  0xA4,  0x42,  0x44,  0x24,  0x34,  0x40,  0x98,  0x84,  0x04,  0x0F,  0xFE,  0x92,  0x21, 	/* 136F0 */
+	0x20,  0x29,  0xE4,  0x80,  0x0F,  0xE3,  0x40,  0xC7,  0xC0,  0x40,  0x07,  0xC0,  0x40,  0x88,  0x04,  0x0F, 	/* 13700 */
+	0xFE,  0x8A,  0x21,  0x24,  0xE1,  0xC2,  0x10,  0x2F,  0xCC,  0x94,  0x31,  0x42,  0xA4,  0x5C,  0x4E,  0x98, 	/* 13710 */
+	0x92,  0x04,  0x0F,  0xFE,  0x8A,  0x21,  0x3C,  0x60,  0x0F,  0xFE,  0x11,  0x87,  0xE4,  0x04,  0x03,  0xF8, 	/* 13720 */
+	0x04,  0x0F,  0xFE,  0x93,  0x04,  0x0F,  0xFE,  0x92,  0x2A,  0x9E,  0x4A,  0x01,  0x18,  0x7E,  0x40,  0x40, 	/* 13730 */
+	0x52,  0x45,  0x02,  0x91,  0x20,  0xF0,  0x95,  0x04,  0x0F,  0xFE,  0x8A,  0x21,  0x24,  0xE1,  0xC0,  0xA0, 	/* 13740 */
+	0x4A,  0xC2,  0xB0,  0x3B,  0x8D,  0x24,  0x22,  0x24,  0x1E,  0x96,  0x04,  0x0F,  0xFE,  0x8A,  0x27,  0x3C, 	/* 13750 */
+	0x24,  0x03,  0xF8,  0x44,  0x0F,  0xFE,  0x04,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x97,  0x04,  0x0F,  0xFE, 	/* 13760 */
+	0x8A,  0x21,  0x24,  0xE1,  0xE7,  0xFC,  0x47,  0x45,  0x94,  0x76,  0x44,  0xB4,  0x70,  0xC7,  0xFC,  0x98, 	/* 13770 */
+	0x04,  0x0F,  0xFE,  0x8A,  0x27,  0x3C,  0x3F,  0x80,  0x88,  0xFF,  0xE0,  0x88,  0x7F,  0x83,  0xFC,  0xD0, 	/* 13780 */
+	0x41,  0xFC,  0x9F,  0x04,  0x0F,  0xFE,  0x90,  0xA3,  0xF8,  0xE0,  0xE3,  0xF8,  0x22,  0x03,  0x24,  0x3F, 	/* 13790 */
+	0xC4,  0x20,  0xA2,  0x43,  0xFC,  0xA9,  0x04,  0x0F,  0xFE,  0x8A,  0x2F,  0x3C,  0x3F,  0x82,  0x78,  0x24, 	/* 137A0 */
+	0x8F,  0xFE,  0x9F,  0x29,  0x12,  0x9F,  0x28,  0x06,  0xAA,  0x04,  0x0F,  0xFE,  0x8A,  0x27,  0x1C,  0x42, 	/* 137B0 */
+	0x02,  0xFC,  0x82,  0x05,  0xFE,  0x02,  0x02,  0xFC,  0x42,  0x0B,  0xFE,  0xAE,  0x04,  0x0F,  0xFE,  0x8A, 	/* 137C0 */
+	0x27,  0x3E,  0x10,  0x07,  0xBE,  0x48,  0x27,  0x9E,  0x4A,  0x0F,  0xBE,  0x28,  0x2D,  0x8C,  0xAF,  0x04, 	/* 137D0 */
+	0x0F,  0xFE,  0x8A,  0x27,  0x3C,  0x1B,  0x07,  0xFC,  0x04,  0x07,  0xFC,  0x04,  0x0F,  0xFE,  0x4A,  0x48, 	/* 137E0 */
+	0x92,  0xB0,  0x04,  0x0F,  0xFE,  0x8A,  0x2F,  0x3C,  0x0F,  0x07,  0x20,  0x2C,  0x0F,  0xFC,  0x24,  0x0F, 	/* 137F0 */
+	0xFE,  0x44,  0x47,  0xFC,  0xB6,  0x04,  0x0F,  0xFE,  0x8A,  0x27,  0x3C,  0xFF,  0xE2,  0x48,  0x7F,  0xC4, 	/* 13800 */
+	0x44,  0xFF,  0xE3,  0x10,  0x0E,  0x07,  0x18,  0xBA,  0x04,  0x0F,  0xFE,  0x8A,  0x27,  0x3C,  0x20,  0x07, 	/* 13810 */
+	0xBC,  0x22,  0x4F,  0xFC,  0x32,  0x42,  0xBC,  0x42,  0xA8,  0xCE,  0xBF,  0x04,  0x0F,  0xFE,  0x8A,  0x2F, 	/* 13820 */
+	0x3C,  0x73,  0x85,  0x48,  0x6B,  0x05,  0x68,  0x5D,  0x67,  0x7C,  0x41,  0x04,  0xFE,  0x83,  0x04,  0x0F, 	/* 13830 */
+	0xFE,  0x95,  0x26,  0xEC,  0x04,  0x07,  0xFC,  0x24,  0x87,  0xFC,  0x44,  0x47,  0xFC,  0x04,  0x20,  0x3E, 	/* 13840 */
+	0x84,  0x04,  0x0F,  0xFE,  0x8A,  0x27,  0x3C,  0x10,  0x07,  0xBC,  0x40,  0x47,  0xFC,  0x24,  0x83,  0x6A, 	/* 13850 */
+	0x24,  0x6F,  0x72,  0x85,  0x04,  0x0F,  0xFE,  0x8A,  0x27,  0x3C,  0x21,  0x07,  0xDE,  0x46,  0x47,  0xD4, 	/* 13860 */
+	0x11,  0x4F,  0xC8,  0x25,  0x45,  0xA2,  0x87,  0x04,  0x0F,  0xFE,  0x8A,  0x27,  0x1C,  0xFF,  0xE4,  0xA4, 	/* 13870 */
+	0x7F,  0xC2,  0x08,  0x3F,  0x82,  0x08,  0x3F,  0x86,  0x0C,  0x88,  0x04,  0x0F,  0xFE,  0x8A,  0x27,  0x3C, 	/* 13880 */
+	0x04,  0x07,  0xFC,  0x4A,  0x4F,  0xBE,  0x8A,  0x2F,  0xBE,  0x0A,  0x10,  0x7F,  0x8A,  0x04,  0x0F,  0xFE, 	/* 13890 */
+	0x8A,  0x27,  0x3C,  0x18,  0x8E,  0xBE,  0xB3,  0x4F,  0xAC,  0x37,  0xE6,  0xCA,  0xA7,  0xE2,  0x42,  0x8B, 	/* 138A0 */
+	0x04,  0x00,  0x40,  0x04,  0x07,  0xFC,  0x00,  0x82,  0x08,  0x10,  0x81,  0x08,  0x09,  0x00,  0x90,  0x02, 	/* 138B0 */
+	0x0F,  0xFE,  0x8D,  0x21,  0x02,  0x10,  0x21,  0x0F,  0x90,  0x11,  0x09,  0xFE,  0x51,  0x05,  0x10,  0x21, 	/* 138C0 */
+	0x03,  0x90,  0xC1,  0x00,  0x10,  0x8F,  0x20,  0xC2,  0x70,  0x21,  0x0F,  0x90,  0x11,  0x09,  0xFE,  0x51, 	/* 138D0 */
+	0x05,  0x10,  0x21,  0x03,  0x90,  0xC1,  0x00,  0x10,  0x92,  0x08,  0x00,  0x80,  0x7F,  0xC2,  0x10,  0x12, 	/* 138E0 */
+	0x0F,  0xFE,  0x00,  0x83,  0xC8,  0x24,  0x82,  0x48,  0x3C,  0x80,  0x18,  0x93,  0x20,  0xC2,  0x70,  0x21, 	/* 138F0 */
+	0x0F,  0x9E,  0x17,  0x09,  0x10,  0x51,  0xE5,  0xF0,  0x21,  0x03,  0x92,  0xC1,  0x20,  0x0E,  0x95,  0x20, 	/* 13900 */
+	0x82,  0x28,  0x22,  0x4F,  0xA4,  0x14,  0x29,  0x7D,  0x59,  0x45,  0x14,  0x22,  0x43,  0xA4,  0xC4,  0x40, 	/* 13910 */
+	0x98,  0x99,  0x21,  0x02,  0x10,  0x21,  0x0F,  0x9E,  0x11,  0x09,  0x10,  0x51,  0x05,  0x7C,  0x24,  0x43, 	/* 13920 */
+	0xC4,  0xC4,  0x40,  0x7C,  0x9A,  0x21,  0x02,  0xFE,  0x28,  0x2F,  0x80,  0x17,  0xE9,  0x10,  0x51,  0x05, 	/* 13930 */
+	0x10,  0x21,  0x03,  0x90,  0xC1,  0x00,  0x30,  0x9C,  0x04,  0x07,  0xFC,  0x11,  0x0F,  0xFE,  0x00,  0x03, 	/* 13940 */
+	0xF8,  0x24,  0x83,  0xF8,  0x24,  0x83,  0xFA,  0x04,  0x20,  0x3E,  0x9D,  0x21,  0x02,  0x10,  0x2F,  0xEF, 	/* 13950 */
+	0x84,  0x14,  0x49,  0x24,  0x52,  0x45,  0x28,  0x22,  0x83,  0x88,  0xC1,  0x00,  0xFE,  0x9F,  0x04,  0x07, 	/* 13960 */
+	0xFC,  0x11,  0x0F,  0xFE,  0x00,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xFA,  0x09,  0x2F,  0x0E, 	/* 13970 */
+	0xA0,  0x04,  0x07,  0xFC,  0x11,  0x0F,  0xFE,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x04,  0x0F,  0xFE, 	/* 13980 */
+	0x04,  0x00,  0x40,  0xA1,  0x20,  0x02,  0xFE,  0x21,  0x0F,  0xA0,  0x17,  0xC9,  0x44,  0x54,  0x45,  0x7C, 	/* 13990 */
+	0x24,  0x43,  0xC4,  0xC4,  0x40,  0x7C,  0xA2,  0x20,  0x82,  0x14,  0x27,  0xAF,  0xA2,  0x12,  0x09,  0x3E, 	/* 139A0 */
+	0x52,  0x85,  0x48,  0x23,  0xE3,  0x98,  0xC2,  0x40,  0xC2,  0xA3,  0x01,  0x02,  0x24,  0x2F,  0xEF,  0xAA, 	/* 139B0 */
+	0x12,  0x89,  0xCE,  0x52,  0x04,  0xBC,  0x36,  0x4C,  0x18,  0x03,  0x81,  0xC6,  0xA5,  0x04,  0x07,  0xFC, 	/* 139C0 */
+	0x11,  0x0F,  0xFE,  0x24,  0x83,  0xF8,  0x24,  0x83,  0xF8,  0x04,  0x07,  0xFC,  0x04,  0x0F,  0xFE,  0xA6, 	/* 139D0 */
+	0x21,  0x02,  0x10,  0x2F,  0xEF,  0x90,  0x17,  0xC9,  0x54,  0x55,  0x45,  0x7C,  0x23,  0x83,  0x54,  0xC9, 	/* 139E0 */
+	0x20,  0x10,  0xAA,  0x00,  0x0F,  0xBE,  0xA2,  0x2F,  0x94,  0xF8,  0x8A,  0x14,  0xFA,  0x20,  0x40,  0x7F, 	/* 139F0 */
+	0xE1,  0x08,  0x09,  0x0F,  0xFE,  0xAD,  0x20,  0x02,  0x7C,  0x24,  0x4F,  0xFC,  0x14,  0x49,  0x7C,  0x52, 	/* 13A00 */
+	0x05,  0x7E,  0x2C,  0xA3,  0x56,  0xC7,  0xE0,  0x0C,  0xAF,  0x21,  0x02,  0x92,  0xF9,  0x21,  0xFE,  0x50, 	/* 13A10 */
+	0x05,  0xFE,  0x52,  0x06,  0xFE,  0x7A,  0xAC,  0xAA,  0x0A,  0xA0,  0x86,  0xB0,  0x27,  0xE2,  0x40,  0x27, 	/* 13A20 */
+	0xEF,  0xEA,  0x17,  0xE9,  0x6A,  0x57,  0xE5,  0x48,  0x27,  0xE3,  0x48,  0xC8,  0x80,  0xFE,  0xB6,  0x11, 	/* 13A30 */
+	0x0F,  0xFC,  0x52,  0x8F,  0xFE,  0x00,  0x07,  0xBC,  0x4A,  0x47,  0xBC,  0x2A,  0x82,  0xAA,  0x4C,  0xA8, 	/* 13A40 */
+	0x86,  0xB8,  0x10,  0x87,  0xFE,  0x29,  0x4F,  0xFE,  0x4A,  0x47,  0xBC,  0x4A,  0x47,  0xBC,  0x31,  0x83, 	/* 13A50 */
+	0x1A,  0x5A,  0xA9,  0x46,  0xB9,  0x22,  0x02,  0x20,  0x22,  0x03,  0xBE,  0x52,  0x85,  0x48,  0x94,  0x81, 	/* 13A60 */
+	0x08,  0x10,  0x81,  0x08,  0x10,  0x81,  0x18,  0xBA,  0x42,  0x04,  0x20,  0x7B,  0xE9,  0x48,  0x11,  0x00, 	/* 13A70 */
+	0x00,  0x7F,  0x80,  0x00,  0x00,  0x00,  0x00,  0xFF,  0xE0,  0x00,  0xBF,  0x42,  0x07,  0xBE,  0x94,  0x82, 	/* 13A80 */
+	0x10,  0x7F,  0xC0,  0x40,  0x04,  0x0F,  0xFE,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x82,  0x42,  0x07, 	/* 13A90 */
+	0xBE,  0x94,  0x82,  0x50,  0x04,  0x0F,  0xF8,  0x04,  0x83,  0x48,  0x0C,  0x80,  0xAA,  0x31,  0xAC,  0x06, 	/* 13AA0 */
+	0x84,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x10,  0x00,  0x07,  0xFC,  0x11,  0x01,  0x10,  0xFF,  0xE1,  0x10, 	/* 13AB0 */
+	0x21,  0x04,  0x10,  0x86,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x10,  0x3F,  0x82,  0x48,  0x24,  0x83,  0xF8, 	/* 13AC0 */
+	0x20,  0x02,  0x00,  0x20,  0x21,  0xFE,  0x88,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x10,  0x7E,  0x01,  0x20, 	/* 13AD0 */
+	0x13,  0x81,  0x08,  0x29,  0x04,  0x60,  0x9B,  0x06,  0x0C,  0x8A,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x10, 	/* 13AE0 */
+	0x03,  0x83,  0xD0,  0x25,  0x02,  0x50,  0x24,  0x84,  0x48,  0x44,  0x48,  0x42,  0x8B,  0x42,  0x07,  0xBE, 	/* 13AF0 */
+	0x94,  0x82,  0x10,  0x3F,  0x80,  0x48,  0xFF,  0xE0,  0x48,  0x3F,  0x80,  0x40,  0x08,  0x03,  0x00,  0x8F, 	/* 13B00 */
+	0x42,  0x07,  0xBE,  0x94,  0x81,  0x10,  0x10,  0x01,  0xFE,  0x29,  0x24,  0x92,  0x92,  0x22,  0x22,  0x04, 	/* 13B10 */
+	0x40,  0x18,  0x91,  0x41,  0x07,  0xDE,  0xA2,  0x81,  0x04,  0x03,  0x03,  0xC0,  0x04,  0x0F,  0xFE,  0x04, 	/* 13B20 */
+	0x00,  0xA0,  0x31,  0x8C,  0x06,  0x98,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x10,  0x04,  0x00,  0x7E,  0x04, 	/* 13B30 */
+	0x00,  0x40,  0x3F,  0x82,  0x08,  0x20,  0x83,  0xF8,  0x99,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x10,  0x14, 	/* 13B40 */
+	0x01,  0x40,  0x3F,  0xC4,  0x40,  0xBF,  0x80,  0x40,  0x04,  0x0F,  0xFE,  0x9B,  0x42,  0x07,  0xBE,  0x52, 	/* 13B50 */
+	0x89,  0x48,  0x25,  0x00,  0x40,  0x7F,  0xC4,  0x44,  0x7F,  0xC4,  0x44,  0x44,  0x47,  0xFC,  0x9E,  0x42, 	/* 13B60 */
+	0x07,  0xBE,  0x94,  0x82,  0x50,  0x0A,  0x01,  0x18,  0xFF,  0x40,  0x02,  0x3F,  0x82,  0x08,  0x20,  0x83, 	/* 13B70 */
+	0xF8,  0xA0,  0x42,  0x04,  0x20,  0x7B,  0xE5,  0x48,  0x89,  0x00,  0x40,  0xFF,  0xE0,  0x10,  0x21,  0x01, 	/* 13B80 */
+	0x10,  0x12,  0x0F,  0xFE,  0xA5,  0x21,  0x03,  0xDE,  0x52,  0x40,  0x88,  0xFF,  0xE0,  0x02,  0x7F,  0xA0, 	/* 13B90 */
+	0x02,  0x3E,  0x22,  0x22,  0x3E,  0x20,  0x06,  0xA6,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x10,  0x10,  0x82, 	/* 13BA0 */
+	0xFE,  0x68,  0x8A,  0x48,  0x24,  0x82,  0x08,  0x20,  0x82,  0x18,  0xA8,  0x42,  0x07,  0xBE,  0x94,  0x82, 	/* 13BB0 */
+	0x10,  0x04,  0x0F,  0xFE,  0x0E,  0x01,  0x50,  0x24,  0x8D,  0xF6,  0x04,  0x00,  0x40,  0xAC,  0x42,  0x07, 	/* 13BC0 */
+	0xBE,  0x94,  0x87,  0xFC,  0x04,  0x47,  0xFC,  0x44,  0x07,  0xFE,  0x0C,  0x23,  0x42,  0xC4,  0xC0,  0x40, 	/* 13BD0 */
+	0xB3,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x10,  0x20,  0x0F,  0xBE,  0x2A,  0x22,  0xA2,  0x2A,  0x24,  0xA2, 	/* 13BE0 */
+	0x4B,  0xEB,  0x00,  0xB5,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x10,  0x40,  0x02,  0xFC,  0x88,  0x44,  0x84, 	/* 13BF0 */
+	0x09,  0x82,  0x80,  0x48,  0x28,  0x7E,  0xB6,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x10,  0x20,  0x03,  0xF8, 	/* 13C00 */
+	0x44,  0x00,  0x40,  0x7F,  0xE0,  0xA0,  0x31,  0x8C,  0x06,  0xB9,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x10, 	/* 13C10 */
+	0x25,  0x02,  0x50,  0xFF,  0xE2,  0x50,  0x25,  0x02,  0x70,  0x20,  0x03,  0xFC,  0x85,  0x42,  0x07,  0xBE, 	/* 13C20 */
+	0x94,  0x82,  0x50,  0x14,  0x03,  0xFC,  0x44,  0x0F,  0xFE,  0x12,  0x01,  0x20,  0x22,  0x2C,  0x1E,  0x86, 	/* 13C30 */
+	0x42,  0x07,  0xBE,  0x94,  0x83,  0xF8,  0x04,  0x8F,  0xFE,  0x04,  0x83,  0xF8,  0x04,  0x07,  0xFC,  0x04, 	/* 13C40 */
+	0x00,  0x40,  0x88,  0x42,  0x07,  0xBE,  0x94,  0x80,  0x84,  0x07,  0x87,  0xC0,  0x04,  0x0F,  0xFE,  0x04, 	/* 13C50 */
+	0x03,  0xF8,  0x20,  0x83,  0xF8,  0x89,  0x42,  0x07,  0xBC,  0xA4,  0x81,  0x50,  0x7F,  0xC0,  0x40,  0xFF, 	/* 13C60 */
+	0xE0,  0x10,  0x7F,  0xC1,  0x10,  0x09,  0x00,  0x30,  0x8B,  0x42,  0x07,  0xBE,  0x94,  0x87,  0x90,  0x4F, 	/* 13C70 */
+	0xE7,  0x92,  0x49,  0x24,  0x92,  0x79,  0x24,  0xA2,  0x4A,  0x29,  0xCC,  0x8C,  0x42,  0x07,  0xBE,  0x94, 	/* 13C80 */
+	0x82,  0x50,  0x0A,  0x03,  0x18,  0xC0,  0x63,  0xF8,  0x04,  0x01,  0xF0,  0x04,  0x0F,  0xFE,  0x8D,  0x42, 	/* 13C90 */
+	0x07,  0xBE,  0x94,  0x82,  0x10,  0x10,  0x01,  0xFE,  0x3F,  0x2D,  0x12,  0x1F,  0x21,  0x12,  0x1F,  0x20, 	/* 13CA0 */
+	0x0C,  0x8F,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x20,  0x22,  0x83,  0xFE,  0x62,  0x4A,  0x18,  0x21,  0x02, 	/* 13CB0 */
+	0x2A,  0x2C,  0x62,  0x02,  0x90,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x10,  0x7F,  0xE5,  0xFC,  0x42,  0x04, 	/* 13CC0 */
+	0xF8,  0x42,  0x05,  0xFC,  0x40,  0x07,  0xFE,  0x91,  0x42,  0x07,  0xBE,  0x94,  0x81,  0x10,  0xFF,  0x82, 	/* 13CD0 */
+	0x48,  0x24,  0x82,  0x68,  0x35,  0x8E,  0x4A,  0x08,  0xA1,  0x06,  0x92,  0x21,  0x07,  0xBE,  0xA4,  0x81, 	/* 13CE0 */
+	0x10,  0x7F,  0xE4,  0x02,  0x5F,  0xA4,  0x02,  0x5F,  0xA5,  0x0A,  0x5F,  0xA4,  0x06,  0x94,  0x41,  0x07, 	/* 13CF0 */
+	0xBE,  0xA4,  0x81,  0x48,  0x0A,  0x01,  0x10,  0x2E,  0x8C,  0x06,  0x3F,  0x82,  0x08,  0x20,  0x83,  0xF8, 	/* 13D00 */
+	0x96,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x10,  0xFF,  0xE0,  0x40,  0x7F,  0xC4,  0x44,  0x4E,  0xC3,  0x58, 	/* 13D10 */
+	0xC4,  0x60,  0x40,  0x9D,  0x42,  0x07,  0xBE,  0x94,  0x82,  0xF0,  0x12,  0x07,  0xF8,  0x04,  0x8F,  0xFE, 	/* 13D20 */
+	0x04,  0x87,  0xF8,  0x04,  0x00,  0xC0,  0xA5,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x10,  0x3F,  0x82,  0x08, 	/* 13D30 */
+	0x3F,  0x80,  0x80,  0x7F,  0xC4,  0x04,  0x40,  0x47,  0xFC,  0xA7,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x10, 	/* 13D40 */
+	0x3F,  0x82,  0x08,  0x3F,  0x82,  0x08,  0x3F,  0x80,  0x92,  0x31,  0x2C,  0x0E,  0xAC,  0x42,  0x07,  0xBE, 	/* 13D50 */
+	0x94,  0x82,  0x10,  0x02,  0x47,  0xFE,  0x42,  0x07,  0x94,  0x49,  0x44,  0x8A,  0x69,  0x69,  0x22,  0xAE, 	/* 13D60 */
+	0x42,  0x07,  0xBE,  0x94,  0x82,  0x10,  0x7F,  0xC0,  0x40,  0x24,  0x82,  0x48,  0x55,  0x48,  0x42,  0x04, 	/* 13D70 */
+	0x0F,  0xFE,  0xB0,  0x42,  0x07,  0xBE,  0x94,  0x83,  0x50,  0x17,  0xE2,  0xA0,  0x6B,  0xEB,  0x20,  0x23, 	/* 13D80 */
+	0xE2,  0x20,  0x22,  0x02,  0x20,  0xB1,  0x41,  0x07,  0xBE,  0x94,  0x82,  0x20,  0x23,  0xE3,  0x44,  0x5A, 	/* 13D90 */
+	0x4D,  0x28,  0x51,  0x85,  0x18,  0x52,  0x44,  0xC2,  0xB4,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x10,  0x04, 	/* 13DA0 */
+	0x0F,  0xFE,  0x24,  0x82,  0x48,  0x55,  0x48,  0xA2,  0x31,  0x8C,  0x06,  0xB5,  0x42,  0x07,  0xBE,  0x94, 	/* 13DB0 */
+	0x82,  0x10,  0xF0,  0x61,  0x78,  0x21,  0x07,  0x5C,  0xD5,  0x03,  0x7E,  0x2C,  0x0C,  0x3F,  0xBA,  0x42, 	/* 13DC0 */
+	0x07,  0xBE,  0x94,  0x82,  0x10,  0x7F,  0xE5,  0xFC,  0x42,  0x04,  0xFC,  0x42,  0x25,  0xFC,  0x40,  0x07, 	/* 13DD0 */
+	0xFE,  0x86,  0x41,  0x07,  0xDF,  0x92,  0x47,  0xFC,  0x44,  0x44,  0xA4,  0x51,  0x44,  0x20,  0x7B,  0xC4, 	/* 13DE0 */
+	0x20,  0x5A,  0x2E,  0x1E,  0x87,  0x21,  0x07,  0xBE,  0x94,  0x87,  0xFE,  0x44,  0x25,  0xFA,  0x44,  0x25, 	/* 13DF0 */
+	0xFA,  0x50,  0xA5,  0xFA,  0x40,  0x27,  0xFE,  0x8B,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x10,  0xFF,  0xE0, 	/* 13E00 */
+	0x90,  0x7E,  0x42,  0x1C,  0xFF,  0xE1,  0x98,  0x07,  0x27,  0x8E,  0x8D,  0x42,  0x07,  0xBE,  0x94,  0x82, 	/* 13E10 */
+	0x10,  0x2F,  0xEF,  0x88,  0x2B,  0xE2,  0xAA,  0x3A,  0xAE,  0xAE,  0x28,  0x86,  0xFE,  0x8F,  0x42,  0x07, 	/* 13E20 */
+	0xBE,  0x95,  0x83,  0xE8,  0x22,  0x45,  0xF8,  0x04,  0x8F,  0xFE,  0x04,  0x87,  0xF8,  0x04,  0x00,  0xC0, 	/* 13E30 */
+	0x92,  0x42,  0x07,  0xBE,  0x94,  0x83,  0xF0,  0x01,  0x0F,  0xFC,  0x01,  0x0F,  0xFE,  0xBF,  0xA2,  0x48, 	/* 13E40 */
+	0x25,  0x80,  0x40,  0x94,  0x42,  0x07,  0xBE,  0x94,  0x80,  0x40,  0x4F,  0xC2,  0x84,  0x88,  0x44,  0xFC, 	/* 13E50 */
+	0x28,  0x44,  0x84,  0x88,  0x48,  0xFC,  0x95,  0x42,  0x07,  0xBE,  0x94,  0x81,  0x10,  0x7F,  0xE1,  0x08, 	/* 13E60 */
+	0x1F,  0x81,  0xF8,  0x10,  0x87,  0xFE,  0x19,  0x8E,  0x06,  0x97,  0x42,  0x07,  0xBE,  0x94,  0x83,  0xF8, 	/* 13E70 */
+	0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x8F,  0xFE,  0x11,  0x02,  0x10,  0x98,  0x42,  0x07,  0xBE, 	/* 13E80 */
+	0x94,  0x82,  0x10,  0x7F,  0xC5,  0xF4,  0x44,  0x47,  0xFC,  0x4E,  0x47,  0x5C,  0x44,  0x47,  0xFC,  0x99, 	/* 13E90 */
+	0x42,  0x07,  0xBE,  0x94,  0x87,  0xBE,  0x4A,  0x24,  0xA4,  0x7B,  0xE4,  0xB2,  0x7A,  0xC4,  0xA4,  0x4A, 	/* 13EA0 */
+	0xC9,  0xD2,  0x9A,  0x42,  0x07,  0xBE,  0x94,  0x81,  0x10,  0x10,  0x22,  0x92,  0x45,  0x2B,  0xF2,  0x01, 	/* 13EB0 */
+	0x27,  0xD2,  0x44,  0x27,  0xC6,  0x9C,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x50,  0xFF,  0xE8,  0xA2,  0x31, 	/* 13EC0 */
+	0xEC,  0x00,  0x3F,  0x80,  0x40,  0x04,  0x0F,  0xFE,  0x9D,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x10,  0x24, 	/* 13ED0 */
+	0x4F,  0xFE,  0x24,  0x42,  0x44,  0x37,  0xCE,  0x44,  0x24,  0x46,  0x7C,  0x9F,  0x42,  0x07,  0xBE,  0x94, 	/* 13EE0 */
+	0x83,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x22,  0x43,  0xB8,  0x22,  0x2F,  0x9E,  0xA1,  0x41, 	/* 13EF0 */
+	0x07,  0xDE,  0x92,  0x4F,  0xFE,  0x80,  0x29,  0xF2,  0x11,  0x01,  0xF0,  0x10,  0x01,  0xF8,  0x10,  0x81, 	/* 13F00 */
+	0xF8,  0xAA,  0x41,  0x07,  0xDE,  0x92,  0x82,  0x50,  0x3F,  0x82,  0x48,  0x3F,  0x82,  0x48,  0xFF,  0xE0, 	/* 13F10 */
+	0x40,  0x04,  0x00,  0x40,  0xAD,  0x42,  0x07,  0xBE,  0x94,  0x81,  0x20,  0xFF,  0xE4,  0x80,  0x7A,  0x44, 	/* 13F20 */
+	0xA4,  0x7A,  0x44,  0xA4,  0x48,  0x45,  0x8C,  0xB1,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x10,  0x23,  0xEF, 	/* 13F30 */
+	0xA2,  0x23,  0xE7,  0x22,  0x73,  0xEA,  0xA2,  0xA2,  0x22,  0x3E,  0xB4,  0x41,  0x07,  0xDF,  0x92,  0x42, 	/* 13F40 */
+	0x14,  0x7F,  0xE4,  0x10,  0x7D,  0x44,  0x14,  0x5C,  0x85,  0x5A,  0x5E,  0x68,  0x42,  0xB8,  0x42,  0x07, 	/* 13F50 */
+	0xBE,  0x94,  0x83,  0xFC,  0x05,  0x0F,  0xFE,  0x06,  0x01,  0xF8,  0x30,  0x8D,  0xF8,  0x10,  0x81,  0xF8, 	/* 13F60 */
+	0x80,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x10,  0x7D,  0xE4,  0x52,  0x7D,  0x24,  0x52,  0x7D,  0x25,  0x1C, 	/* 13F70 */
+	0x79,  0x0C,  0x50,  0x81,  0x42,  0x07,  0xBE,  0x94,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x87,  0xFC, 	/* 13F80 */
+	0x04,  0x03,  0xF8,  0x04,  0x0F,  0xFE,  0x84,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x10,  0xFF,  0xC5,  0x64, 	/* 13F90 */
+	0x7E,  0x45,  0x64,  0x7E,  0x81,  0x22,  0xFE,  0x21,  0x1E,  0x86,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x90, 	/* 13FA0 */
+	0x0F,  0x81,  0x10,  0xFF,  0xE0,  0xC8,  0x73,  0x00,  0xE8,  0xF2,  0x60,  0xC0,  0x87,  0x42,  0x07,  0xBE, 	/* 13FB0 */
+	0x94,  0x82,  0x10,  0xFF,  0xE4,  0x08,  0x7F,  0xC5,  0x54,  0x55,  0x45,  0xFC,  0x95,  0x49,  0x5C,  0x89, 	/* 13FC0 */
+	0x42,  0x07,  0xBE,  0x94,  0x8F,  0xBC,  0x22,  0x4F,  0x56,  0x04,  0x0F,  0xFE,  0x0E,  0x03,  0x58,  0xC4, 	/* 13FD0 */
+	0x60,  0x40,  0x8B,  0x42,  0x07,  0xBE,  0x94,  0x87,  0xFE,  0x42,  0x07,  0xFE,  0x52,  0x85,  0xB8,  0x66, 	/* 13FE0 */
+	0x44,  0x90,  0x50,  0x87,  0xFE,  0x8C,  0x42,  0x07,  0xBE,  0x94,  0x41,  0x78,  0x20,  0x83,  0xFE,  0x62, 	/* 13FF0 */
+	0x0A,  0x7C,  0x29,  0x02,  0xFE,  0x22,  0x82,  0xC6,  0x8F,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x10,  0x49, 	/* 14000 */
+	0x0F,  0xFE,  0x4B,  0x24,  0xD4,  0x79,  0x04,  0x98,  0x4A,  0x47,  0xC2,  0x9D,  0x42,  0x07,  0xBE,  0x94, 	/* 14010 */
+	0x81,  0x10,  0x7F,  0xC1,  0x10,  0x7F,  0xE2,  0x48,  0x3F,  0x82,  0x48,  0xFF,  0xE2,  0x08,  0xA0,  0x42, 	/* 14020 */
+	0x07,  0xBE,  0x94,  0x82,  0x40,  0x47,  0xE5,  0xA4,  0xD3,  0x85,  0xD6,  0x57,  0xC5,  0x38,  0x4D,  0x44, 	/* 14030 */
+	0x12,  0xA4,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x10,  0x3F,  0xC2,  0x20,  0x3F,  0xC2,  0x20,  0x3F,  0xE5, 	/* 14040 */
+	0x52,  0x54,  0x28,  0x0C,  0xA5,  0x42,  0x07,  0xBE,  0x94,  0x8F,  0xFE,  0x0A,  0x07,  0xFC,  0x4A,  0x47, 	/* 14050 */
+	0xFC,  0x04,  0x0F,  0xFE,  0x35,  0x8C,  0x46,  0xA6,  0x42,  0x07,  0xBE,  0x94,  0x83,  0xFC,  0x29,  0x42, 	/* 14060 */
+	0x64,  0x29,  0x43,  0xFC,  0x22,  0x63,  0xF8,  0x22,  0x2F,  0x9E,  0xA9,  0x42,  0x07,  0xBE,  0x94,  0x82, 	/* 14070 */
+	0x00,  0x7F,  0xE4,  0x88,  0x7B,  0xE4,  0x2A,  0x7A,  0xA4,  0xAA,  0x7A,  0xE4,  0x08,  0xAD,  0x41,  0x07, 	/* 14080 */
+	0xDF,  0x92,  0x42,  0x48,  0x7F,  0xC1,  0x10,  0xFF,  0xE2,  0x48,  0x3F,  0x83,  0xF8,  0x24,  0x20,  0x3E, 	/* 14090 */
+	0xB3,  0x42,  0x07,  0xBE,  0x94,  0x87,  0xFC,  0x44,  0x47,  0xFC,  0xFF,  0xE2,  0x48,  0xFF,  0xE0,  0x40, 	/* 140A0 */
+	0x7F,  0xC0,  0x40,  0xB6,  0x41,  0x07,  0xBE,  0x94,  0x87,  0xFC,  0x04,  0x02,  0x78,  0x24,  0x0F,  0xFE, 	/* 140B0 */
+	0x10,  0x01,  0xFE,  0x2A,  0xA4,  0x0C,  0xB7,  0x42,  0x07,  0xBE,  0x94,  0x84,  0x38,  0x2C,  0x88,  0x38, 	/* 140C0 */
+	0x4D,  0x4F,  0x7A,  0x21,  0x02,  0xFC,  0x59,  0x08,  0x7F,  0x80,  0x42,  0x07,  0xBE,  0x94,  0x87,  0xFC, 	/* 140D0 */
+	0x04,  0x0F,  0xFE,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x10,  0x86,  0x04,  0x87,  0x42,  0x07,  0xBE, 	/* 140E0 */
+	0x94,  0x82,  0x20,  0xFF,  0xE2,  0x50,  0x3B,  0xE2,  0xC8,  0x2B,  0xE4,  0x98,  0x8A,  0x43,  0x42,  0x8D, 	/* 140F0 */
+	0x42,  0x07,  0xBE,  0x94,  0x82,  0x50,  0xFF,  0xE2,  0x48,  0x7F,  0xC4,  0x44,  0xFF,  0xE3,  0x10,  0x0E, 	/* 14100 */
+	0x07,  0x18,  0x91,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x50,  0xFF,  0xE2,  0x08,  0xFF,  0xE2,  0x08,  0x3F, 	/* 14110 */
+	0x83,  0x24,  0xD5,  0x83,  0x86,  0x92,  0x42,  0x07,  0xBE,  0x94,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x20, 	/* 14120 */
+	0x8F,  0xFE,  0x24,  0x8C,  0x66,  0x09,  0x03,  0xE8,  0x93,  0x42,  0x07,  0xBE,  0x94,  0x87,  0xC8,  0x55, 	/* 14130 */
+	0x47,  0xE4,  0x54,  0x87,  0xD2,  0x6C,  0x27,  0xC4,  0x44,  0x88,  0xD0,  0x94,  0x42,  0x07,  0xBE,  0x94, 	/* 14140 */
+	0x82,  0x50,  0xFF,  0xE1,  0x10,  0x7F,  0xC1,  0x10,  0xFF,  0xE3,  0x24,  0xD5,  0x83,  0x86,  0x97,  0x42, 	/* 14150 */
+	0x07,  0xBE,  0x94,  0x82,  0xF8,  0x92,  0x84,  0xAC,  0x54,  0xA8,  0xB0,  0xFF,  0xE3,  0x58,  0xC4,  0x60, 	/* 14160 */
+	0x40,  0x9F,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x10,  0x7F,  0xC4,  0xA4,  0x7F,  0xC2,  0x08,  0x3F,  0x82, 	/* 14170 */
+	0x08,  0xFF,  0xE0,  0x40,  0xA1,  0x41,  0x07,  0xDF,  0x92,  0x47,  0xBE,  0x4A,  0x27,  0xBE,  0x4E,  0x27, 	/* 14180 */
+	0x9E,  0x4F,  0x24,  0x92,  0x4F,  0x24,  0x06,  0xA3,  0x42,  0x07,  0xBE,  0x94,  0x83,  0xF8,  0x24,  0x8F, 	/* 14190 */
+	0xFE,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x11,  0x8E,  0x04,  0xA7,  0x42,  0x07,  0xBE,  0xA4,  0x81, 	/* 141A0 */
+	0x10,  0x7F,  0xC1,  0x10,  0xFF,  0xE2,  0x48,  0x3F,  0x82,  0x48,  0x3F,  0x86,  0x0C,  0xAA,  0x42,  0x07, 	/* 141B0 */
+	0xBE,  0x94,  0x87,  0xBC,  0x52,  0x8F,  0xFC,  0x52,  0x8B,  0xFE,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8, 	/* 141C0 */
+	0xAB,  0x42,  0x07,  0xBE,  0x94,  0x83,  0xF8,  0x04,  0x8F,  0xFE,  0x55,  0x45,  0x54,  0x7F,  0xC4,  0x44, 	/* 141D0 */
+	0x75,  0xC9,  0x54,  0xB7,  0x42,  0x07,  0xBE,  0x94,  0x80,  0xF8,  0x71,  0x03,  0xFE,  0x25,  0x03,  0x9E, 	/* 141E0 */
+	0x20,  0x04,  0xFC,  0x48,  0x48,  0xFC,  0xB8,  0x42,  0x07,  0xBE,  0xA4,  0x81,  0x10,  0x4B,  0xEF,  0xEA, 	/* 141F0 */
+	0x4A,  0xC7,  0xBE,  0x4B,  0x2F,  0xEC,  0x52,  0xC8,  0xD2,  0xBD,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x50, 	/* 14200 */
+	0x0A,  0x03,  0x18,  0xFB,  0xE4,  0xA4,  0x7B,  0xC1,  0x10,  0x2A,  0x8C,  0x46,  0xBE,  0x42,  0x07,  0xBE, 	/* 14210 */
+	0x94,  0x87,  0xFE,  0x49,  0x07,  0xFE,  0x49,  0x47,  0xFE,  0x59,  0x8A,  0x94,  0xC9,  0x20,  0x90,  0xBF, 	/* 14220 */
+	0x42,  0x07,  0xBE,  0x96,  0x85,  0xFE,  0x2A,  0x80,  0xF8,  0x8A,  0x87,  0xFE,  0x08,  0x82,  0x48,  0x40, 	/* 14230 */
+	0x88,  0x18,  0x80,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x5E,  0x28,  0xAF,  0xAA,  0x2F,  0x22,  0xFC,  0x3A, 	/* 14240 */
+	0x4E,  0xFC,  0x2A,  0x46,  0xFC,  0x83,  0x42,  0x07,  0xBE,  0x94,  0x87,  0xD0,  0x51,  0xE7,  0xE0,  0x44, 	/* 14250 */
+	0x07,  0xDC,  0x50,  0x07,  0xFC,  0x4A,  0x4F,  0xFE,  0x8C,  0x42,  0x07,  0xBE,  0x94,  0x87,  0xFC,  0x04, 	/* 14260 */
+	0x0F,  0xFE,  0x7F,  0xA0,  0x40,  0xFF,  0xE4,  0xC8,  0x7A,  0x80,  0x18,  0x8D,  0x42,  0x07,  0xBE,  0x94, 	/* 14270 */
+	0x82,  0x28,  0xFF,  0xC2,  0x28,  0xFF,  0xE2,  0x44,  0x77,  0xCA,  0xFC,  0x24,  0x42,  0x7C,  0x8F,  0x42, 	/* 14280 */
+	0x07,  0xBE,  0x94,  0x82,  0x20,  0xFF,  0xE2,  0x24,  0x3B,  0xC2,  0xBC,  0x2A,  0x44,  0xFE,  0x49,  0x4B, 	/* 14290 */
+	0x62,  0x90,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x10,  0x75,  0x45,  0xBE,  0x71,  0x05,  0xFE,  0x75,  0x45, 	/* 142A0 */
+	0xBA,  0x55,  0x4B,  0x92,  0x94,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x10,  0xF9,  0xEA,  0xA4,  0xFA,  0x4A, 	/* 142B0 */
+	0xD4,  0xF9,  0x84,  0x88,  0x31,  0x4C,  0xA2,  0x96,  0x42,  0x07,  0xBE,  0x94,  0x87,  0xD0,  0x11,  0x4F, 	/* 142C0 */
+	0xFE,  0x29,  0x0E,  0xF4,  0x29,  0x4E,  0xEA,  0x2D,  0x6F,  0x22,  0x98,  0x42,  0x07,  0xBE,  0x94,  0x82, 	/* 142D0 */
+	0x10,  0x75,  0x45,  0xFA,  0x72,  0x85,  0xFE,  0x75,  0x45,  0xFA,  0x56,  0x8B,  0xA4,  0x9F,  0x41,  0x07, 	/* 142E0 */
+	0xDE,  0x92,  0x42,  0x08,  0xFB,  0xE2,  0x12,  0xFE,  0xCA,  0xBE,  0xFA,  0x27,  0x3E,  0xA9,  0x22,  0x21, 	/* 142F0 */
+	0xA0,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x3E,  0xFE,  0x04,  0xBC,  0xFC,  0x44,  0xBC,  0x7A,  0x04,  0xBC, 	/* 14300 */
+	0x7A,  0x24,  0x9E,  0xA4,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x90,  0x55,  0x4F,  0xFE,  0x29,  0x0E,  0xF4, 	/* 14310 */
+	0x29,  0x4E,  0xEA,  0x2D,  0x6F,  0x22,  0xA5,  0x42,  0x07,  0xBE,  0xA4,  0x80,  0xA0,  0x3F,  0x8C,  0x06, 	/* 14320 */
+	0xEE,  0xEA,  0xAA,  0x7F,  0xC4,  0xA4,  0x7F,  0xC4,  0xA4,  0xAC,  0x42,  0x07,  0xBE,  0x94,  0x82,  0x14, 	/* 14330 */
+	0xFA,  0x85,  0xFE,  0x6A,  0x87,  0xBC,  0xFA,  0x8A,  0xBC,  0xFA,  0x88,  0xBE,  0xB3,  0x04,  0x04,  0x48, 	/* 14340 */
+	0x24,  0x82,  0x50,  0xFF,  0xE0,  0xE0,  0x0E,  0x01,  0x50,  0x24,  0x8C,  0x46,  0x04,  0x00,  0x40,  0xB5, 	/* 14350 */
+	0x21,  0x0A,  0x90,  0x71,  0x02,  0x10,  0xFF,  0xE2,  0x10,  0x71,  0x07,  0x10,  0xA9,  0x0A,  0x10,  0x21, 	/* 14360 */
+	0x02,  0x10,  0xBE,  0x20,  0x0A,  0xFE,  0x71,  0x22,  0x12,  0xF9,  0x22,  0x72,  0x71,  0xA6,  0x96,  0xA2, 	/* 14370 */
+	0x2A,  0x22,  0x24,  0x22,  0x8C,  0x81,  0x20,  0xCA,  0xF0,  0x71,  0x02,  0x10,  0xF1,  0x02,  0xFE,  0x71, 	/* 14380 */
+	0x06,  0x90,  0xA1,  0x0A,  0x10,  0x21,  0x02,  0x10,  0x82,  0x08,  0x00,  0xF0,  0x31,  0x0C,  0x60,  0x19, 	/* 14390 */
+	0x8E,  0x46,  0x24,  0x81,  0x50,  0xFF,  0xE0,  0xE0,  0x35,  0x8C,  0x46,  0x83,  0x24,  0x8A,  0xC8,  0x74, 	/* 143A0 */
+	0x82,  0x48,  0xFF,  0xA2,  0x4C,  0x74,  0x86,  0xC8,  0xA4,  0x8A,  0x4A,  0x27,  0xA2,  0xC6,  0x89,  0x22, 	/* 143B0 */
+	0x8A,  0xA8,  0x72,  0x86,  0x44,  0xF8,  0x22,  0x7D,  0x71,  0x47,  0x14,  0xAA,  0x4A,  0x24,  0x24,  0x42, 	/* 143C0 */
+	0x98,  0x8B,  0x22,  0x0A,  0xA0,  0x77,  0x82,  0x28,  0xFA,  0xA2,  0x46,  0x71,  0x07,  0x7E,  0xA9,  0x0A, 	/* 143D0 */
+	0x10,  0x21,  0x02,  0x10,  0x8D,  0x20,  0x4A,  0x98,  0x6F,  0x07,  0x10,  0xFF,  0xE2,  0x10,  0x71,  0x06, 	/* 143E0 */
+	0xFE,  0xA9,  0x0A,  0x12,  0x21,  0x22,  0x0E,  0x90,  0x20,  0x0A,  0xBE,  0x70,  0x02,  0x3E,  0xFA,  0x22, 	/* 143F0 */
+	0x22,  0x73,  0xE6,  0xA0,  0xA4,  0x0A,  0x40,  0x28,  0x03,  0x00,  0x92,  0x21,  0x0A,  0x90,  0x71,  0x02, 	/* 14400 */
+	0x7E,  0xF8,  0x42,  0x44,  0x72,  0x46,  0xA4,  0xA2,  0x8A,  0x28,  0x21,  0x02,  0xFE,  0x95,  0x20,  0x8A, 	/* 14410 */
+	0x90,  0x71,  0x02,  0x3E,  0xFA,  0x22,  0x22,  0x73,  0xE7,  0x22,  0xAA,  0x2A,  0x22,  0x22,  0x22,  0x3E, 	/* 14420 */
+	0x97,  0x20,  0x02,  0xFC,  0xB4,  0x46,  0x44,  0xFF,  0xC2,  0x44,  0x74,  0x47,  0x7C,  0xAC,  0x4A,  0x44, 	/* 14430 */
+	0x24,  0x42,  0xFE,  0x98,  0x21,  0x0A,  0x90,  0x71,  0x02,  0x1E,  0xF9,  0x02,  0x10,  0x71,  0x06,  0xFC, 	/* 14440 */
+	0xA4,  0x4A,  0x44,  0x24,  0x42,  0x7C,  0x9B,  0x04,  0x07,  0xF8,  0x04,  0x8F,  0xFE,  0x04,  0x87,  0xFC, 	/* 14450 */
+	0x64,  0xC5,  0x54,  0x7F,  0xC4,  0xE4,  0x55,  0x4A,  0x4C,  0x9F,  0xFF,  0xE0,  0xA0,  0x7F,  0xC4,  0xA4, 	/* 14460 */
+	0x7F,  0xC6,  0x4C,  0x15,  0x0F,  0xFE,  0x0E,  0x03,  0x58,  0xC4,  0x60,  0x40,  0xA1,  0x20,  0x0A,  0xFE, 	/* 14470 */
+	0x74,  0x22,  0x7A,  0xFC,  0x22,  0x42,  0x77,  0xA6,  0xEA,  0xA6,  0xAA,  0x7A,  0x24,  0x22,  0x46,  0xA2, 	/* 14480 */
+	0x02,  0x0E,  0x7E,  0x09,  0x42,  0x28,  0xCC,  0x62,  0x48,  0x15,  0x0F,  0xFE,  0x0E,  0x03,  0x58,  0xC4, 	/* 14490 */
+	0x60,  0x40,  0xA4,  0x10,  0x07,  0xFC,  0x55,  0x44,  0xE4,  0x7F,  0xC5,  0x54,  0x64,  0xCF,  0xFE,  0x08, 	/* 144A0 */
+	0x01,  0xF8,  0x00,  0x80,  0x30,  0xA5,  0x04,  0x0F,  0x5E,  0x2D,  0x22,  0x62,  0xFF,  0xE8,  0x48,  0xEE, 	/* 144B0 */
+	0xE2,  0xE2,  0x35,  0x22,  0x42,  0x24,  0x2C,  0x4C,  0xA7,  0x20,  0x8A,  0x88,  0x77,  0xE2,  0x48,  0xFC, 	/* 144C0 */
+	0x82,  0x48,  0x77,  0xE6,  0xC8,  0xA4,  0x8A,  0x88,  0x2F,  0xF3,  0x00,  0xA8,  0x20,  0x0A,  0xFE,  0x71, 	/* 144D0 */
+	0x02,  0x20,  0xFF,  0xE2,  0x42,  0x74,  0x27,  0x7E,  0xAC,  0x2A,  0x42,  0x24,  0x22,  0x7E,  0xAB,  0x20, 	/* 144E0 */
+	0x0A,  0xFE,  0x72,  0x02,  0x40,  0xFF,  0xE2,  0xAA,  0x7A,  0xA6,  0xAA,  0xAA,  0xAA,  0xAA,  0x2A,  0xA2, 	/* 144F0 */
+	0x86,  0xAD,  0x21,  0x02,  0x90,  0xB2,  0x86,  0x44,  0xFF,  0xE2,  0x01,  0x70,  0x06,  0xFC,  0xA4,  0x4A, 	/* 14500 */
+	0x44,  0x24,  0x42,  0x7C,  0xAE,  0x21,  0x0A,  0xFC,  0x74,  0x42,  0x7C,  0xFC,  0x42,  0x7C,  0x75,  0x26, 	/* 14510 */
+	0xD4,  0xA4,  0x8A,  0x48,  0x27,  0x42,  0xC2,  0xB1,  0x20,  0x09,  0xF8,  0x4A,  0xC1,  0xAA,  0x64,  0xA8, 	/* 14520 */
+	0x98,  0x24,  0x41,  0x48,  0xFF,  0xE0,  0xE0,  0x35,  0x8C,  0x46,  0xB2,  0x10,  0x01,  0xDE,  0x21,  0x27, 	/* 14530 */
+	0xCC,  0x99,  0x46,  0x22,  0x24,  0x81,  0x50,  0xFF,  0xE0,  0xE0,  0x35,  0x8C,  0x46,  0xB3,  0x20,  0x0A, 	/* 14540 */
+	0xFE,  0x71,  0x02,  0x7E,  0xFD,  0x22,  0x7E,  0x75,  0x26,  0xFE,  0xA5,  0x0A,  0x30,  0x22,  0x82,  0xC6, 	/* 14550 */
+	0xB9,  0x21,  0x0A,  0x90,  0x77,  0xE2,  0x44,  0xFC,  0x43,  0x6C,  0x69,  0x26,  0x10,  0xAF,  0xEA,  0x10, 	/* 14560 */
+	0x21,  0x02,  0x10,  0xBD,  0x21,  0x0A,  0x90,  0x7F,  0xE2,  0x82,  0xF7,  0xC3,  0x00,  0x6F,  0xE6,  0x10, 	/* 14570 */
+	0xA5,  0x4A,  0x52,  0x29,  0x22,  0x30,  0xBE,  0x21,  0x0A,  0xFE,  0x71,  0x02,  0x7C,  0xF9,  0x02,  0xFE, 	/* 14580 */
+	0x74,  0x47,  0x7C,  0xAC,  0x4A,  0x7C,  0x24,  0x42,  0x4C,  0x80,  0x22,  0x8A,  0xFE,  0x72,  0x82,  0x20, 	/* 14590 */
+	0xFA,  0x82,  0x68,  0x76,  0xA6,  0xAC,  0xA2,  0x8A,  0x28,  0x22,  0xA2,  0x26,  0x82,  0x22,  0x4A,  0xFE, 	/* 145A0 */
+	0x72,  0x42,  0x3C,  0xFA,  0x42,  0x3C,  0x72,  0x46,  0xFF,  0xA5,  0x4A,  0x66,  0x24,  0x02,  0x3E,  0x85, 	/* 145B0 */
+	0x27,  0xCA,  0xA8,  0x71,  0x02,  0x7E,  0xFB,  0x42,  0x50,  0x71,  0x06,  0xFE,  0xA3,  0x8A,  0x54,  0x29, 	/* 145C0 */
+	0x22,  0x10,  0x8A,  0x24,  0xEB,  0x4A,  0x7F,  0xA2,  0x4A,  0xF4,  0xE2,  0x4A,  0x6E,  0xA7,  0xAE,  0xAA, 	/* 145D0 */
+	0xAA,  0xEA,  0x21,  0x22,  0x26,  0x8E,  0x20,  0x02,  0xFE,  0xB8,  0x06,  0xBE,  0xFA,  0xA2,  0xBE,  0x7A, 	/* 145E0 */
+	0xA7,  0xBE,  0xA8,  0x8A,  0xBE,  0x28,  0x83,  0x7E,  0x92,  0x22,  0x4A,  0xFE,  0x72,  0x42,  0x7E,  0xFC, 	/* 145F0 */
+	0x02,  0x7E,  0x76,  0xA6,  0x7E,  0xAA,  0xAA,  0xBE,  0x32,  0xA2,  0x26,  0x96,  0x28,  0x8A,  0xFF,  0x74, 	/* 14600 */
+	0x82,  0x5E,  0xFC,  0xA2,  0x7F,  0x64,  0xA7,  0x5E,  0xAC,  0x0A,  0x5E,  0x29,  0x23,  0x1E,  0x98,  0x21, 	/* 14610 */
+	0x0A,  0xFE,  0x78,  0x22,  0xFE,  0xF9,  0x02,  0x6A,  0x71,  0xA7,  0x6C,  0xA9,  0xAA,  0x69,  0x20,  0x82, 	/* 14620 */
+	0x30,  0x9C,  0x02,  0x07,  0xFE,  0x48,  0x87,  0xFE,  0x48,  0x86,  0xAA,  0x6A,  0xA5,  0x24,  0x7F,  0xE4, 	/* 14630 */
+	0xA8,  0xB2,  0x40,  0x20,  0x9E,  0x24,  0x8F,  0xFE,  0x15,  0x02,  0x48,  0xFF,  0xE2,  0x48,  0x3F,  0x82, 	/* 14640 */
+	0x48,  0x7F,  0xC1,  0x10,  0xFF,  0xF6,  0x0C,  0x9F,  0x22,  0x8A,  0xFE,  0x72,  0x82,  0xFE,  0xFA,  0xA2, 	/* 14650 */
+	0xFE,  0x6A,  0xA7,  0xFE,  0xA4,  0x4A,  0x7C,  0x24,  0x42,  0x7C,  0xA0,  0x21,  0x0A,  0xFE,  0x75,  0x02, 	/* 14660 */
+	0x7C,  0xFD,  0x42,  0x7E,  0x75,  0x46,  0xFE,  0xA5,  0x42,  0xB8,  0x35,  0x62,  0x10,  0xA2,  0x24,  0x8A, 	/* 14670 */
+	0xFE,  0x74,  0x82,  0x7C,  0xFC,  0x42,  0x7C,  0x74,  0x46,  0xFC,  0xA1,  0x0A,  0xFE,  0x22,  0x82,  0xC6, 	/* 14680 */
+	0xA7,  0x23,  0xEA,  0xA2,  0x73,  0xE2,  0x22,  0xFF,  0xF3,  0x2A,  0x6B,  0xE6,  0xAA,  0xA2,  0xAA,  0x3E, 	/* 14690 */
+	0x20,  0x82,  0x7F,  0xAF,  0x27,  0xCA,  0x90,  0x7F,  0xE2,  0x92,  0xFB,  0xA3,  0x00,  0x6F,  0xE6,  0x20, 	/* 146A0 */
+	0xAF,  0xEA,  0xAA,  0x2A,  0xA2,  0x86,  0xB2,  0x20,  0x0B,  0x7E,  0x75,  0x42,  0x7E,  0xFD,  0x42,  0x7E, 	/* 146B0 */
+	0x76,  0xA6,  0x7E,  0xAA,  0xAA,  0xBE,  0x32,  0x22,  0x26,  0xB4,  0x6F,  0xE2,  0x66,  0x2A,  0xA5,  0x26, 	/* 146C0 */
+	0x8E,  0xA2,  0x22,  0xAC,  0x87,  0x7E,  0xFD,  0x03,  0x7C,  0x6D,  0x0A,  0x7E,  0xB6,  0x2F,  0xEA,  0xB6, 	/* 146D0 */
+	0xFD,  0xA2,  0x36,  0xAD,  0xAF,  0x92,  0xAA,  0x47,  0x7E,  0xFC,  0x83,  0x7C,  0x6C,  0x8A,  0x7E,  0xB8, 	/* 146E0 */
+	0x04,  0x00,  0x80,  0x31,  0x00,  0xA0,  0x0D,  0x01,  0x0C,  0x7F,  0x20,  0x40,  0x24,  0x82,  0x44,  0x44, 	/* 146F0 */
+	0x40,  0x40,  0xBA,  0x22,  0x02,  0x20,  0xD2,  0x05,  0x20,  0x22,  0x05,  0x20,  0xFA,  0x02,  0x20,  0xB2, 	/* 14700 */
+	0x0A,  0xA0,  0xA2,  0x22,  0x1E,  0xBB,  0x01,  0xC7,  0xE0,  0x04,  0x82,  0x90,  0x12,  0x00,  0xC8,  0xFF, 	/* 14710 */
+	0xC0,  0x42,  0x25,  0x02,  0x48,  0x44,  0x40,  0x40,  0xBE,  0x20,  0x42,  0x24,  0xD2,  0x45,  0x24,  0x22, 	/* 14720 */
+	0x45,  0x24,  0xFA,  0x4A,  0x2F,  0xAF,  0x4A,  0x84,  0xA0,  0x42,  0x04,  0x80,  0x20,  0x02,  0x7C,  0xD0, 	/* 14730 */
+	0x45,  0x04,  0x20,  0x45,  0x3C,  0xFA,  0x02,  0x20,  0xB2,  0x0A,  0xA2,  0xA2,  0x22,  0x1E,  0x82,  0x20, 	/* 14740 */
+	0x82,  0x08,  0xC0,  0x85,  0x7E,  0x20,  0x85,  0x48,  0xFA,  0x82,  0x28,  0xB0,  0x8A,  0x88,  0xA0,  0x82, 	/* 14750 */
+	0x18,  0x84,  0x22,  0x02,  0x20,  0xD3,  0xE5,  0x22,  0x24,  0x24,  0xA2,  0xF9,  0x22,  0x12,  0xB0,  0x2A, 	/* 14760 */
+	0x82,  0xA0,  0x22,  0x0C,  0x85,  0x20,  0x02,  0x7C,  0xD1,  0x05,  0x10,  0x21,  0x05,  0x10,  0xF9,  0x02, 	/* 14770 */
+	0x90,  0xB1,  0x0A,  0x90,  0xAF,  0xE2,  0x00,  0x86,  0x20,  0x02,  0x7C,  0xD1,  0x05,  0x10,  0x21,  0x05, 	/* 14780 */
+	0x7E,  0xF9,  0x02,  0x10,  0xB1,  0x0A,  0x90,  0xA1,  0x02,  0x30,  0x8A,  0x04,  0x0F,  0xFE,  0x11,  0x00, 	/* 14790 */
+	0xE0,  0x31,  0x8C,  0x56,  0x1A,  0x00,  0x4C,  0xFF,  0xA1,  0x50,  0x24,  0xC4,  0x42,  0x8B,  0x21,  0x04, 	/* 147A0 */
+	0x10,  0x9F,  0xE6,  0x44,  0x54,  0x4F,  0xA8,  0x2A,  0x8B,  0x10,  0xA9,  0x0A,  0xA8,  0xA4,  0x42,  0x82, 	/* 147B0 */
+	0x8D,  0x21,  0x04,  0x10,  0x91,  0x06,  0xFE,  0x49,  0x2F,  0x92,  0x2A,  0xAB,  0xAA,  0xAC,  0x6A,  0x82, 	/* 147C0 */
+	0xA8,  0x22,  0x86,  0x90,  0x20,  0x02,  0x7C,  0xD2,  0x45,  0x24,  0x22,  0x45,  0x7E,  0xFA,  0x42,  0x24, 	/* 147D0 */
+	0xB2,  0x4A,  0xA4,  0xA2,  0x42,  0x7E,  0x94,  0x21,  0x22,  0x1C,  0xDF,  0x05,  0x14,  0x25,  0x45,  0x54, 	/* 147E0 */
+	0xFD,  0x42,  0x7C,  0xB1,  0x0A,  0x92,  0xA1,  0x22,  0x0E,  0x95,  0x24,  0x84,  0x48,  0x94,  0x86,  0x48, 	/* 147F0 */
+	0x57,  0xAF,  0xCC,  0x2C,  0x8B,  0x48,  0xAC,  0x8A,  0x48,  0xA7,  0xA2,  0xC6,  0x97,  0x21,  0x02,  0x10, 	/* 14800 */
+	0xD1,  0x85,  0x54,  0x25,  0x25,  0x52,  0xF5,  0x02,  0x94,  0xB0,  0x4A,  0x88,  0xA1,  0x02,  0x60,  0x98, 	/* 14810 */
+	0x22,  0x02,  0x20,  0xD2,  0x05,  0xFE,  0x22,  0x05,  0x28,  0xFA,  0x82,  0x48,  0xB4,  0x8A,  0xD4,  0xAB, 	/* 14820 */
+	0xE3,  0x02,  0x99,  0x20,  0xC2,  0x70,  0xD5,  0x05,  0x50,  0x25,  0x65,  0x78,  0xFD,  0x02,  0x48,  0xB4, 	/* 14830 */
+	0x8A,  0xCA,  0xA7,  0x62,  0xC2,  0x9A,  0x20,  0x02,  0x78,  0xD4,  0x85,  0x50,  0x25,  0xC5,  0x64,  0xFD, 	/* 14840 */
+	0x42,  0x58,  0xB4,  0x8A,  0x94,  0xAA,  0x43,  0x42,  0x9B,  0x22,  0x82,  0x28,  0xD2,  0x85,  0x24,  0x24, 	/* 14850 */
+	0x25,  0x7D,  0xF9,  0x42,  0x14,  0xB1,  0x4A,  0xA4,  0xA4,  0x42,  0x98,  0x9C,  0x20,  0x02,  0x3C,  0xD0, 	/* 14860 */
+	0x05,  0x00,  0x2F,  0xE5,  0x10,  0xF9,  0x02,  0x18,  0xB2,  0x4A,  0xA4,  0xAF,  0xA2,  0x02,  0xA0,  0x04, 	/* 14870 */
+	0x07,  0xFC,  0x04,  0x03,  0xF8,  0x04,  0x0F,  0xFE,  0x19,  0x00,  0xEC,  0xF5,  0x21,  0x48,  0x64,  0x40, 	/* 14880 */
+	0x40,  0xA1,  0x22,  0x02,  0x20,  0xDF,  0xE5,  0x20,  0x22,  0x05,  0x3C,  0xFA,  0x42,  0x24,  0xB2,  0x4A, 	/* 14890 */
+	0xC4,  0xA4,  0x42,  0x98,  0xA2,  0x04,  0x0F,  0xFE,  0x04,  0x0F,  0xFE,  0x8C,  0x2B,  0x32,  0x0C,  0x87, 	/* 148A0 */
+	0xFC,  0x15,  0x42,  0x48,  0xC4,  0x40,  0x40,  0xAB,  0x12,  0x05,  0x3C,  0x5A,  0x05,  0x22,  0x5D,  0xEF, 	/* 148B0 */
+	0x60,  0x19,  0x80,  0x68,  0x7F,  0xC1,  0x52,  0x24,  0x84,  0x44,  0xAC,  0x21,  0x02,  0x10,  0xD1,  0x05, 	/* 148C0 */
+	0x7E,  0x25,  0x25,  0x52,  0xFF,  0xE2,  0x52,  0xB5,  0x2A,  0xD2,  0xA5,  0x22,  0x7E,  0xAE,  0x22,  0x0F, 	/* 148D0 */
+	0xE0,  0x32,  0x06,  0xA2,  0xA2,  0x22,  0x5E,  0x09,  0x03,  0xA0,  0x04,  0xCF,  0xF2,  0x25,  0x84,  0x44, 	/* 148E0 */
+	0xAF,  0x7F,  0xC4,  0x44,  0x7F,  0xC4,  0x44,  0x7F,  0xC0,  0x90,  0x73,  0x00,  0xCC,  0xFF,  0x23,  0x58, 	/* 148F0 */
+	0xC4,  0x60,  0x40,  0xB0,  0x10,  0x01,  0x3E,  0xE2,  0xA2,  0xAA,  0x12,  0xA2,  0xBE,  0xFE,  0xA1,  0x2A, 	/* 14900 */
+	0x5A,  0xA5,  0x6A,  0x93,  0xE1,  0x00,  0xB2,  0x25,  0x42,  0x54,  0xD5,  0x45,  0xFE,  0x25,  0x45,  0x54, 	/* 14910 */
+	0xFD,  0x42,  0x54,  0xB5,  0xCA,  0xC0,  0xA4,  0x02,  0x7E,  0xB3,  0x21,  0x02,  0x10,  0xD7,  0xE5,  0x52, 	/* 14920 */
+	0x27,  0xE5,  0x52,  0xFD,  0x22,  0x7E,  0xB1,  0x0A,  0x90,  0xA1,  0x02,  0x10,  0xB5,  0x21,  0x02,  0x7E, 	/* 14930 */
+	0xD4,  0x25,  0x00,  0x2F,  0xE5,  0x08,  0xF8,  0x82,  0x08,  0xB0,  0x8A,  0x88,  0xA8,  0x82,  0x18,  0xB9, 	/* 14940 */
+	0x20,  0x02,  0x7E,  0xD1,  0x25,  0x12,  0x22,  0x25,  0x4C,  0xF8,  0x02,  0x3E,  0xB2,  0x2A,  0xA2,  0xA2, 	/* 14950 */
+	0x22,  0x3E,  0xBA,  0x22,  0x44,  0x24,  0x92,  0x46,  0x7E,  0x4A,  0x4F,  0xA4,  0x2A,  0x43,  0x3C,  0xAA, 	/* 14960 */
+	0x4A,  0xA4,  0xA2,  0x42,  0x3C,  0xBF,  0x22,  0x02,  0x20,  0xD2,  0x85,  0x24,  0x25,  0xC5,  0x62,  0xF8, 	/* 14970 */
+	0x22,  0x7C,  0xB4,  0x4A,  0xC4,  0xA4,  0x42,  0x7C,  0x82,  0x21,  0x02,  0x1C,  0xD2,  0x45,  0x68,  0x21, 	/* 14980 */
+	0x85,  0x24,  0xFC,  0x22,  0x98,  0xB0,  0x4A,  0xB0,  0xA0,  0xC2,  0x02,  0x83,  0x21,  0x02,  0x10,  0xD7, 	/* 14990 */
+	0xE5,  0x10,  0x21,  0x45,  0x64,  0xFA,  0x82,  0x10,  0xB1,  0x8A,  0xA4,  0xAF,  0xE2,  0x02,  0x84,  0x20, 	/* 149A0 */
+	0x02,  0x7C,  0xD4,  0x45,  0x44,  0x27,  0xC5,  0x44,  0xFC,  0x42,  0xFC,  0xB4,  0x4A,  0xC4,  0xA4,  0x43, 	/* 149B0 */
+	0xFE,  0x85,  0x20,  0x02,  0x7E,  0xD4,  0x25,  0x42,  0x25,  0xE5,  0x56,  0xFD,  0x62,  0x56,  0xB5,  0xEA, 	/* 149C0 */
+	0xC2,  0xA4,  0x22,  0x46,  0x86,  0x21,  0x02,  0x54,  0xD5,  0x45,  0x92,  0x27,  0xC5,  0x10,  0xF9,  0x02, 	/* 149D0 */
+	0xFE,  0xB1,  0x0A,  0x90,  0xA1,  0x02,  0x10,  0x8B,  0x20,  0x82,  0x08,  0xD7,  0xE5,  0x40,  0x24,  0x85, 	/* 149E0 */
+	0x48,  0xFC,  0x82,  0x48,  0xB5,  0x4B,  0x56,  0xAB,  0xA3,  0x02,  0x8C,  0x20,  0x02,  0x7C,  0xD2,  0x45, 	/* 149F0 */
+	0x18,  0x22,  0x85,  0x46,  0xF9,  0x02,  0x10,  0xB7,  0xCA,  0x90,  0xA1,  0x02,  0xFE,  0x8E,  0x21,  0x02, 	/* 14A00 */
+	0x1E,  0xD2,  0x05,  0x50,  0x29,  0xF5,  0x24,  0xF6,  0x42,  0xA4,  0xB2,  0x4A,  0xA4,  0xA2,  0x42,  0x2C, 	/* 14A10 */
+	0x8F,  0x21,  0x04,  0x10,  0x97,  0xE6,  0x52,  0x57,  0xEF,  0xD2,  0x2F,  0xEB,  0x14,  0xA8,  0x8A,  0x9A, 	/* 14A20 */
+	0xA6,  0x63,  0x82,  0x90,  0x21,  0x02,  0x10,  0xDF,  0xE5,  0x10,  0x21,  0x05,  0x7C,  0xF8,  0x02,  0x7C, 	/* 14A30 */
+	0xB4,  0x4A,  0xC4,  0xA4,  0x42,  0x7C,  0x96,  0x21,  0x02,  0x92,  0xD5,  0x25,  0x54,  0x21,  0x05,  0x7E, 	/* 14A40 */
+	0xFA,  0x82,  0x28,  0xB2,  0x8A,  0xC8,  0xA4,  0xA2,  0x86,  0x9B,  0x22,  0x02,  0x3E,  0x26,  0x45,  0x98, 	/* 14A50 */
+	0x53,  0x4D,  0xD2,  0x56,  0x85,  0x34,  0x5F,  0xA5,  0x54,  0x49,  0x24,  0x10,  0x9E,  0x21,  0x02,  0x10, 	/* 14A60 */
+	0xDF,  0xE5,  0x28,  0x24,  0x45,  0x0A,  0xFA,  0x82,  0x28,  0xA9,  0x0A,  0xA8,  0xA4,  0x42,  0x82,  0xA1, 	/* 14A70 */
+	0x21,  0x02,  0x1C,  0xD2,  0x45,  0x64,  0x21,  0x85,  0x14,  0xFA,  0x22,  0x7D,  0xAA,  0x4A,  0xA4,  0xA2, 	/* 14A80 */
+	0x42,  0x3C,  0xA2,  0x21,  0x04,  0x10,  0x93,  0xE6,  0x42,  0x53,  0xAF,  0xAA,  0x2B,  0xAB,  0x2A,  0xAA, 	/* 14A90 */
+	0xAA,  0xBA,  0xA0,  0x22,  0x0C,  0xA3,  0x22,  0x22,  0x14,  0xD7,  0xE5,  0x14,  0x21,  0x45,  0x7E,  0xF9, 	/* 14AA0 */
+	0x42,  0x14,  0xB2,  0x4A,  0xA4,  0xA4,  0x42,  0x84,  0xA6,  0x21,  0x02,  0x10,  0xD2,  0x85,  0x44,  0x2F, 	/* 14AB0 */
+	0xC5,  0x02,  0xF8,  0x02,  0x7C,  0xB4,  0x4A,  0xC4,  0xA4,  0x42,  0x7C,  0xA8,  0x21,  0x44,  0x12,  0x97, 	/* 14AC0 */
+	0xE6,  0x28,  0x4A,  0x8F,  0xF8,  0x2A,  0xAB,  0x2A,  0xAA,  0x4A,  0x4C,  0xA1,  0x62,  0x62,  0xAE,  0x10, 	/* 14AD0 */
+	0x0F,  0xDE,  0x29,  0x24,  0x92,  0x31,  0x22,  0x9E,  0xC4,  0x81,  0xB0,  0x04,  0xCF,  0xFA,  0x25,  0x04, 	/* 14AE0 */
+	0x4C,  0xB1,  0x21,  0x02,  0x10,  0xD7,  0xE5,  0x10,  0x22,  0x45,  0x7C,  0xFA,  0xA2,  0x28,  0xB2,  0x8A, 	/* 14AF0 */
+	0xAA,  0xA4,  0xA2,  0x86,  0xB2,  0x20,  0x82,  0x08,  0xCB,  0x25,  0x14,  0x20,  0x85,  0x14,  0xFF,  0xE2, 	/* 14B00 */
+	0x08,  0xB2,  0xCA,  0xAA,  0xA4,  0xA2,  0x08,  0xB3,  0x21,  0x02,  0x3C,  0xD6,  0x45,  0x18,  0x22,  0x45, 	/* 14B10 */
+	0x52,  0xF9,  0x02,  0x7C,  0xB5,  0x0A,  0xFE,  0xA1,  0x02,  0x10,  0xB5,  0x21,  0x02,  0x10,  0xD2,  0x85, 	/* 14B20 */
+	0x44,  0x2B,  0xA5,  0x00,  0xFF,  0xE2,  0x20,  0xB2,  0x8A,  0x48,  0xAF,  0x42,  0x04,  0xB6,  0x22,  0x02, 	/* 14B30 */
+	0x38,  0xD4,  0x85,  0x10,  0x27,  0xC5,  0x54,  0xFD,  0x42,  0x7C,  0xB4,  0x0A,  0xC2,  0xA4,  0x22,  0x3E, 	/* 14B40 */
+	0xB9,  0x23,  0xE4,  0x22,  0x93,  0xE6,  0x00,  0x4B,  0xEF,  0xA2,  0x2B,  0xEB,  0x22,  0xAB,  0xEA,  0xA2, 	/* 14B50 */
+	0xA2,  0x22,  0x26,  0xBD,  0x20,  0x02,  0x3C,  0xD2,  0x45,  0x24,  0x23,  0xC5,  0x10,  0xFA,  0x02,  0x3E, 	/* 14B60 */
+	0xB2,  0x2A,  0xA2,  0xAA,  0x22,  0x3E,  0x89,  0x20,  0x44,  0x78,  0x91,  0x06,  0x7E,  0x4B,  0x8F,  0xD4, 	/* 14B70 */
+	0x29,  0x2B,  0x7C,  0xA9,  0x4A,  0x96,  0xA2,  0x22,  0x4C,  0x8F,  0x20,  0x62,  0x78,  0xD2,  0x45,  0x2A, 	/* 14B80 */
+	0x24,  0xA5,  0x10,  0xFF,  0xEA,  0x14,  0xB2,  0x4A,  0xB8,  0xA1,  0x42,  0x62,  0x93,  0x20,  0x02,  0x7E, 	/* 14B90 */
+	0xD2,  0xA5,  0x2A,  0x25,  0x45,  0x2A,  0xFA,  0xA2,  0x00,  0xB3,  0xEA,  0x88,  0xA0,  0x82,  0x7F,  0x99, 	/* 14BA0 */
+	0x24,  0x82,  0x48,  0xD6,  0xA5,  0x5C,  0x27,  0xE5,  0x48,  0xFD,  0xC2,  0x5C,  0xB6,  0xAA,  0xC8,  0xA4, 	/* 14BB0 */
+	0x82,  0x7E,  0x9A,  0x21,  0x02,  0xFE,  0xD1,  0x05,  0x7C,  0x20,  0x05,  0x7E,  0xFC,  0x22,  0x28,  0xB2, 	/* 14BC0 */
+	0x8A,  0xA8,  0xA2,  0xA2,  0x46,  0x9B,  0x20,  0x02,  0x7E,  0xD0,  0xA5,  0x2A,  0x21,  0xA5,  0x22,  0xF4, 	/* 14BD0 */
+	0xC2,  0x10,  0xAA,  0x8A,  0xA2,  0xB2,  0x52,  0x1C,  0x9C,  0x21,  0x02,  0x10,  0xDF,  0xE5,  0x82,  0x2B, 	/* 14BE0 */
+	0xA5,  0x00,  0xFF,  0xE2,  0x10,  0xB5,  0x4B,  0x52,  0xA9,  0x22,  0x30,  0x9F,  0x20,  0x02,  0x7E,  0xD0, 	/* 14BF0 */
+	0x05,  0x7E,  0x24,  0x25,  0x7E,  0xFC,  0x82,  0x7E,  0xB4,  0x8A,  0x54,  0xA9,  0x43,  0x22,  0xA2,  0x20, 	/* 14C00 */
+	0x02,  0x7E,  0xD4,  0x25,  0x52,  0x27,  0xE5,  0x52,  0xFF,  0xE2,  0x52,  0xB7,  0xAA,  0x6A,  0xAB,  0xA3, 	/* 14C10 */
+	0x06,  0xA3,  0x21,  0x04,  0x34,  0x95,  0x26,  0x7E,  0x4A,  0x8F,  0xFE,  0x2C,  0x4A,  0xBA,  0xB2,  0x8A, 	/* 14C20 */
+	0xB8,  0xA2,  0x42,  0x1C,  0xAB,  0x21,  0x42,  0x1E,  0xDF,  0x05,  0x14,  0x21,  0xA5,  0x26,  0xF9,  0x42, 	/* 14C30 */
+	0x1E,  0xB7,  0x0A,  0x94,  0xA1,  0xA2,  0xE6,  0xAC,  0x20,  0xC2,  0x72,  0xD4,  0xA5,  0x24,  0x27,  0xE5, 	/* 14C40 */
+	0x42,  0xFF,  0xC2,  0x24,  0xAA,  0x8A,  0x98,  0xA2,  0x42,  0xC2,  0xAD,  0x22,  0x42,  0x28,  0xD7,  0xE5, 	/* 14C50 */
+	0xC8,  0x24,  0x85,  0x7C,  0xFC,  0x82,  0x48,  0xB7,  0xCA,  0xC8,  0xA4,  0x82,  0x7E,  0xAE,  0xF9,  0x00, 	/* 14C60 */
+	0x1E,  0x7A,  0x44,  0xD8,  0x79,  0x44,  0x22,  0x8C,  0x8B,  0x30,  0x0C,  0xCF,  0xFA,  0x14,  0x86,  0x44, 	/* 14C70 */
+	0xAF,  0x22,  0x02,  0x20,  0xD3,  0xE5,  0x42,  0x2B,  0xE5,  0x52,  0xFF,  0xE2,  0x12,  0xB5,  0x6A,  0x7E, 	/* 14C80 */
+	0xA0,  0x22,  0x0C,  0xB0,  0x20,  0x82,  0x7E,  0xD4,  0x25,  0x3C,  0x22,  0x45,  0x24,  0xFB,  0xC2,  0x20, 	/* 14C90 */
+	0xB3,  0xEA,  0xA2,  0xA2,  0x22,  0x3E,  0xB1,  0x20,  0x02,  0x7E,  0xD4,  0xA5,  0x6A,  0x25,  0x25,  0x7E, 	/* 14CA0 */
+	0xFD,  0x22,  0x56,  0xB5,  0x6A,  0xFE,  0xA4,  0x22,  0x46,  0xB2,  0x20,  0x02,  0x7E,  0xD4,  0x65,  0x6A, 	/* 14CB0 */
+	0x27,  0xE5,  0x52,  0xFF,  0xE2,  0x52,  0xB5,  0x2A,  0xCE,  0xA4,  0x22,  0x46,  0xB4,  0x2E,  0xE2,  0x22, 	/* 14CC0 */
+	0xDC,  0xC5,  0x44,  0x2A,  0xA5,  0x00,  0xFE,  0xE2,  0x22,  0xAA,  0xAA,  0x44,  0xAA,  0xA3,  0x12,  0xB5, 	/* 14CD0 */
+	0x20,  0x64,  0x7C,  0x95,  0x26,  0x4A,  0x48,  0x8F,  0x90,  0x2F,  0xEB,  0x10,  0xAB,  0x8A,  0xD4,  0xA9, 	/* 14CE0 */
+	0x22,  0x10,  0xB8,  0x22,  0x04,  0x30,  0x94,  0x86,  0x84,  0x5F,  0xEF,  0x01,  0x2F,  0xEA,  0xAA,  0xBF, 	/* 14CF0 */
+	0xEA,  0xAA,  0xAA,  0xA2,  0x86,  0xBA,  0x21,  0x02,  0x7C,  0xD1,  0x05,  0x28,  0x24,  0x45,  0x7E,  0xF8, 	/* 14D00 */
+	0x42,  0x74,  0xB5,  0x4A,  0xF4,  0xA8,  0x42,  0x0C,  0xBB,  0x20,  0x84,  0x7E,  0x94,  0x26,  0x42,  0x4B, 	/* 14D10 */
+	0xCF,  0x88,  0x2A,  0x8B,  0x2E,  0xAA,  0x8A,  0xA8,  0xA5,  0x82,  0x87,  0xBD,  0x21,  0x02,  0x1E,  0xD1, 	/* 14D20 */
+	0x05,  0x7C,  0x24,  0x45,  0x7C,  0xFC,  0x42,  0x7C,  0xB1,  0x0A,  0xFE,  0xA9,  0x02,  0x10,  0xBE,  0x21, 	/* 14D30 */
+	0x04,  0x7C,  0x91,  0x06,  0x7E,  0x52,  0x8F,  0xA4,  0x2D,  0xEB,  0x24,  0xAE,  0x8A,  0x90,  0xA2,  0x82, 	/* 14D40 */
+	0xC6,  0xBF,  0x21,  0x02,  0x7C,  0xD4,  0x45,  0x7C,  0x24,  0x45,  0x7C,  0xF9,  0x02,  0x7E,  0xB5,  0x2A, 	/* 14D50 */
+	0xD2,  0xA5,  0x62,  0x10,  0x87,  0x22,  0xA4,  0x2A,  0x95,  0x46,  0x2A,  0x52,  0xAF,  0x80,  0x2B,  0xEB, 	/* 14D60 */
+	0x2A,  0xAB,  0xEA,  0xAA,  0xA2,  0xA2,  0x3E,  0x8A,  0x00,  0x07,  0xDE,  0x50,  0x27,  0xD4,  0x7C,  0x85, 	/* 14D70 */
+	0x14,  0x7E,  0x23,  0x18,  0x0E,  0x4F,  0xFE,  0x15,  0x26,  0x48,  0x8B,  0x22,  0x82,  0x28,  0xD6,  0xE5, 	/* 14D80 */
+	0x28,  0x22,  0x85,  0xEE,  0xF2,  0x82,  0x28,  0xBE,  0xEA,  0x28,  0xA4,  0x82,  0x88,  0x8F,  0x22,  0x82, 	/* 14D90 */
+	0x28,  0xD5,  0x45,  0x12,  0x22,  0x85,  0x7C,  0xF8,  0x42,  0x50,  0xB4,  0xCA,  0xAA,  0xAA,  0x22,  0x18, 	/* 14DA0 */
+	0x91,  0x20,  0x02,  0x7C,  0xD0,  0x45,  0x7C,  0x20,  0x45,  0x7E,  0xF9,  0x42,  0x54,  0xB3,  0x8A,  0x54, 	/* 14DB0 */
+	0xA9,  0x22,  0x30,  0x92,  0x21,  0x02,  0x7E,  0xD1,  0x45,  0x18,  0x2F,  0xE5,  0x20,  0xF7,  0xC2,  0xA4, 	/* 14DC0 */
+	0xB3,  0xCA,  0xA4,  0xA2,  0x42,  0x3C,  0x95,  0x21,  0x04,  0xFE,  0x92,  0x46,  0x18,  0x52,  0x4F,  0xE6, 	/* 14DD0 */
+	0x2B,  0xDB,  0x24,  0xAB,  0xCA,  0xA4,  0xA4,  0x42,  0x84,  0x98,  0x20,  0xC4,  0x0A,  0x97,  0xE6,  0x48, 	/* 14DE0 */
+	0x57,  0xAF,  0x4A,  0x2F,  0xAA,  0x6C,  0xB7,  0xCA,  0xCE,  0xA9,  0x23,  0x22,  0x9A,  0x21,  0x02,  0x7C, 	/* 14DF0 */
+	0xD4,  0x45,  0x7C,  0x24,  0x45,  0x7C,  0xF9,  0x22,  0x54,  0xB3,  0x8A,  0xD4,  0xA1,  0x22,  0x30,  0x9C, 	/* 14E00 */
+	0x20,  0x6F,  0xF8,  0x8A,  0x4F,  0xE8,  0x89,  0x0F,  0xA4,  0x27,  0xEF,  0x92,  0xAB,  0x4A,  0xD2,  0xB9, 	/* 14E10 */
+	0x02,  0x10,  0x9D,  0x23,  0xC2,  0x24,  0xD3,  0xC5,  0x00,  0x27,  0xE5,  0x24,  0xFB,  0xC2,  0x24,  0xAB, 	/* 14E20 */
+	0xCA,  0xA4,  0xAF,  0xC2,  0x04,  0x9E,  0x23,  0xC4,  0xD4,  0x99,  0x46,  0x95,  0x5E,  0x3F,  0x80,  0x2F, 	/* 14E30 */
+	0xCA,  0x94,  0xBF,  0x4A,  0x88,  0xA9,  0x42,  0xA2,  0xA0,  0x21,  0x02,  0xFE,  0xD4,  0x45,  0x28,  0x2F, 	/* 14E40 */
+	0xE4,  0x92,  0xFF,  0xC2,  0x54,  0xB5,  0x4A,  0xD4,  0xA1,  0x02,  0x10,  0xA1,  0x27,  0xC4,  0x44,  0x97, 	/* 14E50 */
+	0xC6,  0x48,  0x57,  0xEF,  0xC8,  0x2E,  0x4B,  0x7E,  0xAC,  0x4A,  0x7C,  0xA4,  0x42,  0x7C,  0xA4,  0x25, 	/* 14E60 */
+	0x42,  0xFE,  0xD5,  0x45,  0x5C,  0x24,  0x05,  0x7E,  0xF9,  0x02,  0x7E,  0xB1,  0x8A,  0xB4,  0xA5,  0x22, 	/* 14E70 */
+	0x10,  0xA8,  0x2F,  0xE2,  0x00,  0xD7,  0xC5,  0x44,  0x27,  0xC5,  0x40,  0xFF,  0xE2,  0x6A,  0xB7,  0xEA, 	/* 14E80 */
+	0xAA,  0xB2,  0xA2,  0x26,  0xA9,  0x20,  0xC2,  0x74,  0xD2,  0x85,  0xFE,  0x22,  0x05,  0x7E,  0xFA,  0x02, 	/* 14E90 */
+	0x3C,  0xB5,  0x4A,  0x58,  0xAA,  0x42,  0x42,  0xAC,  0x20,  0x02,  0xFE,  0xD1,  0x05,  0x20,  0x2F,  0xE5, 	/* 14EA0 */
+	0xAA,  0xFB,  0xA2,  0xAA,  0xBB,  0xAA,  0xAA,  0xAA,  0xA2,  0xFE,  0xAF,  0x21,  0x02,  0x7E,  0xD1,  0x25, 	/* 14EB0 */
+	0x7F,  0x22,  0x25,  0x3E,  0xF8,  0x82,  0x3E,  0xAA,  0x8A,  0xFF,  0xA0,  0x82,  0x08,  0xB2,  0x20,  0x84, 	/* 14EC0 */
+	0xE8,  0x9A,  0xC6,  0xAA,  0x4F,  0xAF,  0xB9,  0x2A,  0xBA,  0xEA,  0xBB,  0xAA,  0xE4,  0xA1,  0x82,  0x60, 	/* 14ED0 */
+	0xB4,  0x21,  0x02,  0xFE,  0xD1,  0x05,  0x7C,  0x25,  0x45,  0x7C,  0xFD,  0x42,  0x7C,  0xA3,  0x8B,  0x54, 	/* 14EE0 */
+	0xA9,  0x22,  0x10,  0xBB,  0x20,  0x44,  0xFC,  0x96,  0x46,  0x57,  0x4F,  0x6F,  0xAA,  0x2A,  0xAA,  0xF4, 	/* 14EF0 */
+	0xB2,  0x4A,  0xAA,  0xAF,  0x22,  0x21,  0x81,  0x27,  0x82,  0x08,  0xD7,  0x85,  0x08,  0x27,  0xE5,  0x32, 	/* 14F00 */
+	0xFD,  0x42,  0x28,  0xB5,  0xCA,  0xAA,  0xA4,  0x82,  0x18,  0x84,  0x27,  0xC2,  0x54,  0xD7,  0xC5,  0x54, 	/* 14F10 */
+	0x27,  0xC5,  0x7E,  0xF9,  0x22,  0xFE,  0xB9,  0x2A,  0xFE,  0xA1,  0x22,  0x0E,  0x85,  0x20,  0x84,  0x0A, 	/* 14F20 */
+	0x97,  0xE6,  0x48,  0x57,  0xAF,  0xEA,  0x27,  0xAB,  0x54,  0xA5,  0x4A,  0xAD,  0xAD,  0x33,  0x21,  0x89, 	/* 14F30 */
+	0x20,  0x04,  0xFE,  0x92,  0x46,  0x4A,  0x4E,  0xEF,  0x80,  0x2F,  0xEB,  0x3C,  0xAA,  0x4A,  0xBC,  0xA2, 	/* 14F40 */
+	0x42,  0x3C,  0x8A,  0x23,  0xC4,  0x24,  0x97,  0xC6,  0x82,  0x57,  0xDF,  0xA8,  0x2C,  0x4A,  0xFE,  0xB5, 	/* 14F50 */
+	0x5A,  0xD4,  0xA5,  0x42,  0xFE,  0x8B,  0x20,  0x44,  0x48,  0x93,  0xE6,  0x92,  0x55,  0xEF,  0x10,  0x2D, 	/* 14F60 */
+	0xEB,  0x52,  0xB5,  0x2A,  0x5E,  0xAB,  0x03,  0x0F,  0x92,  0x24,  0x44,  0x28,  0x97,  0xE6,  0x10,  0x53, 	/* 14F70 */
+	0xCF,  0x90,  0x2F,  0xEB,  0x20,  0xAF,  0xEA,  0x48,  0xA8,  0x82,  0x7E,  0x9B,  0x21,  0x42,  0xFE,  0xD1, 	/* 14F80 */
+	0x05,  0x7C,  0x25,  0x45,  0x7C,  0xF5,  0x42,  0xFE,  0xB2,  0x4A,  0x94,  0xA0,  0x42,  0x0C,  0x9E,  0x21, 	/* 14F90 */
+	0x02,  0xFE,  0xD7,  0xC5,  0x44,  0x27,  0xC5,  0x00,  0xFF,  0xE2,  0x82,  0xAB,  0xAB,  0xAA,  0xAB,  0xA2, 	/* 14FA0 */
+	0x86,  0x9F,  0x20,  0x04,  0x7E,  0x94,  0x06,  0x7E,  0x55,  0xAF,  0xD4,  0x27,  0x2B,  0x44,  0xAF,  0xFA, 	/* 14FB0 */
+	0xA4,  0xB0,  0x42,  0x0C,  0xA1,  0x21,  0x04,  0xFE,  0x99,  0x26,  0x7C,  0x52,  0x8F,  0xA8,  0x2F,  0xEB, 	/* 14FC0 */
+	0x10,  0xAF,  0xCA,  0x90,  0xA1,  0x02,  0x10,  0xA2,  0x0A,  0x47,  0xFA,  0x52,  0x05,  0xFE,  0x74,  0x85, 	/* 14FD0 */
+	0xA4,  0x5D,  0x27,  0x28,  0x5F,  0xC5,  0x54,  0x59,  0x2B,  0x10,  0xA3,  0x38,  0x62,  0xB8,  0xB8,  0xAA, 	/* 14FE0 */
+	0xB2,  0xB9,  0x4A,  0x8C,  0xB9,  0x28,  0x7E,  0xFA,  0xA5,  0xAC,  0x54,  0xA9,  0x08,  0xA6,  0x24,  0x02, 	/* 14FF0 */
+	0x52,  0xD8,  0xC5,  0x7E,  0x24,  0x85,  0x68,  0xFA,  0x82,  0xAE,  0xBA,  0x8A,  0xD8,  0xAC,  0x82,  0x86, 	/* 15000 */
+	0xAB,  0x21,  0x02,  0x1E,  0xD3,  0x45,  0x48,  0x23,  0x45,  0x4A,  0xFF,  0xD2,  0x48,  0xB7,  0xEA,  0x48, 	/* 15010 */
+	0xAA,  0x83,  0x1F,  0xAE,  0x21,  0x04,  0xFE,  0x98,  0x26,  0xBE,  0x4A,  0x8F,  0x5E,  0x2D,  0x2A,  0x52, 	/* 15020 */
+	0xB5,  0xEA,  0xD2,  0xA5,  0x22,  0x5E,  0xB1,  0x25,  0x44,  0x54,  0x95,  0x46,  0xAA,  0x55,  0x1F,  0x48, 	/* 15030 */
+	0x2A,  0x8A,  0xAE,  0xBA,  0x8A,  0xB8,  0xAC,  0x82,  0x87,  0xB2,  0x27,  0xE4,  0x52,  0x97,  0xE6,  0x52, 	/* 15040 */
+	0x4F,  0xEF,  0xB0,  0x2C,  0xCB,  0x32,  0xAF,  0xEA,  0x54,  0xA9,  0x22,  0x10,  0xB5,  0x27,  0xC2,  0x44, 	/* 15050 */
+	0xD7,  0xC5,  0x44,  0x2F,  0xE5,  0xAA,  0xFF,  0xE2,  0x00,  0xB7,  0xCA,  0xA4,  0xA1,  0x82,  0xE6,  0xB7, 	/* 15060 */
+	0x27,  0xC4,  0x54,  0x9F,  0xE6,  0x54,  0x4F,  0xEF,  0x92,  0x2F,  0xEA,  0x10,  0xB7,  0xEA,  0xA4,  0xA1, 	/* 15070 */
+	0x82,  0x64,  0xB9,  0x27,  0xE4,  0x28,  0x9F,  0xE6,  0xAA,  0x4F,  0xEF,  0x80,  0x2B,  0xCB,  0x00,  0xAF, 	/* 15080 */
+	0xEA,  0x54,  0xA9,  0x22,  0x30,  0xBA,  0x28,  0x84,  0x7E,  0xA0,  0x86,  0xBE,  0x56,  0xAF,  0x3E,  0x3E, 	/* 15090 */
+	0xAA,  0x7E,  0xB4,  0x8A,  0x7E,  0xAA,  0x83,  0x1F,  0xBB,  0x02,  0x07,  0xFE,  0x49,  0x07,  0xFE,  0x4A, 	/* 150A0 */
+	0x86,  0xAA,  0x6E,  0xA5,  0x90,  0x46,  0xC7,  0xFA,  0x8A,  0x83,  0x24,  0xBD,  0x22,  0x02,  0x7E,  0xD4, 	/* 150B0 */
+	0xA5,  0x56,  0x26,  0xE5,  0x4A,  0xFD,  0x22,  0x7E,  0xB0,  0xAA,  0xA5,  0xA5,  0x22,  0x4E,  0xBE,  0x21, 	/* 150C0 */
+	0x02,  0xFE,  0xD1,  0x05,  0x7C,  0x21,  0x05,  0xFE,  0xF4,  0x42,  0x7C,  0xB4,  0x4A,  0xFC,  0xA2,  0x42, 	/* 150D0 */
+	0xC2,  0x81,  0x42,  0x07,  0xBE,  0xAA,  0x4F,  0xD4,  0xA9,  0x8F,  0xE6,  0x1D,  0x00,  0xA8,  0x7F,  0xC1, 	/* 150E0 */
+	0x54,  0x64,  0xC0,  0x40,  0x83,  0x21,  0x04,  0x92,  0x9F,  0xE6,  0x00,  0x4E,  0xEF,  0xAA,  0x2E,  0xEA, 	/* 150F0 */
+	0xAA,  0xBE,  0xEA,  0xAA,  0xAA,  0xA2,  0xB6,  0x86,  0x20,  0x04,  0xFE,  0x95,  0xA6,  0x36,  0x55,  0xAF, 	/* 15100 */
+	0xB6,  0x2A,  0x83,  0x4C,  0xA9,  0x2A,  0x65,  0xA1,  0x82,  0x60,  0x8A,  0x24,  0xA2,  0x4A,  0xDF,  0x86, 	/* 15110 */
+	0x4E,  0x24,  0x85,  0xFA,  0xFA,  0xA2,  0xAC,  0xBB,  0x4A,  0xA4,  0xBF,  0xA2,  0x12,  0x8B,  0xFB,  0x82, 	/* 15120 */
+	0x2A,  0xFC,  0xEA,  0xFC,  0xFA,  0x42,  0x18,  0xFE,  0x63,  0x28,  0x0D,  0x0F,  0xFE,  0x15,  0x06,  0x4C, 	/* 15130 */
+	0x8D,  0x21,  0x02,  0x7C,  0xD1,  0x45,  0x7E,  0x21,  0x45,  0xFE,  0xF7,  0x62,  0x5A,  0xB7,  0xEB,  0x52, 	/* 15140 */
+	0xAB,  0xA3,  0x56,  0x94,  0x24,  0x83,  0xFC,  0xDA,  0xA6,  0xA8,  0x3F,  0xF5,  0x08,  0xFE,  0xA2,  0xAA, 	/* 15150 */
+	0xBE,  0x4A,  0xAC,  0xAF,  0x22,  0x22,  0x95,  0x22,  0x84,  0xFE,  0x91,  0x06,  0x7C,  0x51,  0x0F,  0xFE, 	/* 15160 */
+	0x25,  0x4A,  0xFE,  0xB0,  0x0A,  0xFC,  0xA4,  0x42,  0x7C,  0x96,  0x2A,  0x84,  0xA8,  0x9F,  0xE6,  0xAA, 	/* 15170 */
+	0x5F,  0x2F,  0x0A,  0x2E,  0x4B,  0xA4,  0xAE,  0xAA,  0xAA,  0x2B,  0x22,  0xA1,  0x99,  0x20,  0xC4,  0x72, 	/* 15180 */
+	0x95,  0x46,  0xFE,  0x53,  0x8F,  0xD4,  0x29,  0x2A,  0x7D,  0xB5,  0x4A,  0xFC,  0xA5,  0x42,  0x7C,  0x9A, 	/* 15190 */
+	0x21,  0x04,  0xFE,  0x91,  0x06,  0xBA,  0x56,  0x4F,  0xBE,  0x2A,  0x5B,  0x3C,  0xA9,  0x4A,  0xB2,  0xA5, 	/* 151A0 */
+	0x22,  0x30,  0x9D,  0x2E,  0xE4,  0xAA,  0x9E,  0xE6,  0xAA,  0x4F,  0xEF,  0xAA,  0x2B,  0xAA,  0xAA,  0xBB, 	/* 151B0 */
+	0xAA,  0xAA,  0xAD,  0xA2,  0x82,  0x9E,  0x23,  0xC4,  0x10,  0x97,  0xE6,  0x24,  0x57,  0xEF,  0xA4,  0x2F, 	/* 151C0 */
+	0xEA,  0x00,  0xB7,  0xEA,  0xA8,  0xA2,  0xA2,  0x46,  0xA6,  0x21,  0xE2,  0xF2,  0xD3,  0xE5,  0x28,  0x2F, 	/* 151D0 */
+	0xE5,  0xAA,  0xFE,  0xA2,  0x3E,  0xB2,  0xCA,  0xAA,  0xA4,  0xE2,  0xB1,  0xA7,  0x27,  0xC2,  0x10,  0xDF, 	/* 151E0 */
+	0xE6,  0x92,  0x2B,  0xA5,  0x80,  0xFF,  0xC2,  0x00,  0xAF,  0xEA,  0xA8,  0xA5,  0xC2,  0xE2,  0xA9,  0x2F, 	/* 151F0 */
+	0xE4,  0xAA,  0x9E,  0xE6,  0x28,  0x4E,  0xEF,  0xAA,  0x2E,  0xEA,  0xAA,  0xBE,  0xEA,  0xA0,  0xA2,  0x22, 	/* 15200 */
+	0x1E,  0xAA,  0x21,  0x02,  0x30,  0xD2,  0x85,  0x44,  0x2F,  0xE5,  0xAB,  0xF9,  0x22,  0xFE,  0xB4,  0x4B, 	/* 15210 */
+	0x7C,  0xA4,  0x42,  0x7C,  0xAD,  0x11,  0x0F,  0xFE,  0x11,  0x0F,  0xFE,  0xA5,  0x2D,  0x7E,  0xA5,  0x6F, 	/* 15220 */
+	0xFE,  0x95,  0x2B,  0xD6,  0xD5,  0xA9,  0x66,  0xB0,  0x23,  0x82,  0x28,  0xD3,  0x85,  0x00,  0x2E,  0xE5, 	/* 15230 */
+	0xAA,  0xFE,  0xE2,  0x10,  0xAF,  0xEA,  0xB8,  0xA5,  0x42,  0x92,  0xB9,  0x2F,  0xE4,  0xAA,  0x9F,  0xE6, 	/* 15240 */
+	0x78,  0x51,  0x0F,  0xFE,  0x2A,  0x8B,  0x7E,  0xA9,  0x0A,  0xFC,  0xA1,  0x02,  0x10,  0xBB,  0x27,  0xC4, 	/* 15250 */
+	0x10,  0x9F,  0xE6,  0x92,  0x4B,  0xAF,  0x80,  0x2F,  0xEB,  0x20,  0xAF,  0xEA,  0xAA,  0xAA,  0xA2,  0x86, 	/* 15260 */
+	0xBC,  0x2A,  0x44,  0xDA,  0x9A,  0x46,  0xFE,  0x49,  0x2F,  0xFE,  0x2A,  0x4A,  0xDA,  0xBA,  0x4A,  0xFE, 	/* 15270 */
+	0xA9,  0x22,  0xFE,  0xBD,  0x21,  0x04,  0xFE,  0x99,  0x26,  0x34,  0x55,  0x8F,  0xBC,  0x2E,  0x4A,  0x3C, 	/* 15280 */
+	0xB2,  0x4A,  0xBC,  0xA1,  0x42,  0x62,  0xBF,  0x2E,  0x84,  0x8E,  0x9E,  0x86,  0xB0,  0x4E,  0x0F,  0x8E, 	/* 15290 */
+	0x2E,  0x0A,  0x7C,  0xB5,  0x4A,  0xD4,  0xA5,  0x42,  0xFE,  0x82,  0x42,  0x07,  0xBE,  0x94,  0x83,  0xF8, 	/* 152A0 */
+	0x20,  0x83,  0xF8,  0x20,  0x8F,  0xFE,  0x25,  0x8D,  0xE6,  0x15,  0x06,  0x4C,  0x83,  0x21,  0x04,  0xFE, 	/* 152B0 */
+	0x92,  0x86,  0xD6,  0x55,  0x4F,  0x52,  0x2A,  0x5B,  0x3C,  0xAA,  0x4A,  0xBC,  0xA2,  0x42,  0x44,  0x88, 	/* 152C0 */
+	0x24,  0x04,  0x5E,  0x9E,  0x86,  0x5E,  0x55,  0x2F,  0xFE,  0x21,  0x2A,  0xFE,  0xBB,  0x2A,  0xBE,  0xAE, 	/* 152D0 */
+	0xA2,  0x11,  0x89,  0x22,  0x42,  0x7E,  0xD2,  0x45,  0x7E,  0x25,  0xA5,  0x3C,  0xFA,  0x42,  0x3C,  0xAA, 	/* 152E0 */
+	0x4A,  0xBC,  0xA1,  0x42,  0x62,  0x8C,  0x21,  0x04,  0xFE,  0x91,  0x06,  0xFE,  0x4A,  0xAF,  0xFE,  0x24, 	/* 152F0 */
+	0x4A,  0x7C,  0xB4,  0x4A,  0xFC,  0xA2,  0x42,  0xC2,  0x8E,  0x24,  0x84,  0x4C,  0x9E,  0xA6,  0x4E,  0x5F, 	/* 15300 */
+	0x8F,  0xAA,  0x2B,  0xAB,  0xAA,  0xAB,  0x4B,  0xA5,  0xAF,  0xB3,  0x91,  0x8F,  0x20,  0x82,  0xFE,  0xDA, 	/* 15310 */
+	0xA2,  0xBE,  0x4A,  0xAF,  0xBE,  0x29,  0x4A,  0xE6,  0xB8,  0x8A,  0xBE,  0xB0,  0x82,  0xFF,  0x90,  0x24, 	/* 15320 */
+	0x04,  0x5F,  0x9F,  0x46,  0xAE,  0x5A,  0xAF,  0x1E,  0x2A,  0xA2,  0xAE,  0xB4,  0xAA,  0xAE,  0xA8,  0xA3, 	/* 15330 */
+	0x11,  0x92,  0x20,  0x04,  0xFF,  0x9A,  0xA6,  0xBE,  0x4A,  0xAF,  0xBE,  0x2F,  0xFA,  0xAA,  0xBC,  0x9A, 	/* 15340 */
+	0xBE,  0xA8,  0x83,  0x7F,  0x93,  0x2E,  0xE4,  0xAA,  0x9E,  0xE6,  0xAA,  0x5E,  0xEF,  0x44,  0x2A,  0xAB, 	/* 15350 */
+	0x10,  0xAF,  0xEA,  0x64,  0xA1,  0x82,  0xE4,  0x94,  0x23,  0xC4,  0xC8,  0x97,  0xC6,  0x44,  0x57,  0xEF, 	/* 15360 */
+	0xC8,  0x2E,  0xEA,  0x7C,  0xB5,  0x4A,  0xFC,  0xA5,  0x23,  0x9E,  0x96,  0x2A,  0x84,  0xAC,  0x9A,  0xA6, 	/* 15370 */
+	0xDE,  0x54,  0x8F,  0xFA,  0x2A,  0xAB,  0xBA,  0xAA,  0x4B,  0xB5,  0xAB,  0xB3,  0xD1,  0x9B,  0x04,  0x07, 	/* 15380 */
+	0xFC,  0x04,  0x0F,  0xFE,  0x24,  0x8B,  0xF8,  0xA9,  0x0B,  0xE8,  0xA9,  0x4F,  0xFE,  0x73,  0x4A,  0xD2, 	/* 15390 */
+	0x9C,  0x2E,  0x82,  0xAE,  0xDF,  0x05,  0xFE,  0x2A,  0xA4,  0xFE,  0xF4,  0x42,  0x7C,  0xB4,  0x4A,  0x7C, 	/* 153A0 */
+	0xA2,  0xA2,  0xC6,  0xB6,  0x20,  0x02,  0x00,  0x3F,  0xC4,  0x40,  0x84,  0x0F,  0xFE,  0x04,  0x04,  0x44, 	/* 153B0 */
+	0x44,  0x44,  0x44,  0x7F,  0xC4,  0x04,  0xB8,  0x20,  0x02,  0x3E,  0x3C,  0x85,  0x08,  0x90,  0x8F,  0xC8, 	/* 153C0 */
+	0x10,  0x85,  0x48,  0x54,  0x85,  0x48,  0x7C,  0x84,  0x3E,  0xBA,  0x41,  0x04,  0x10,  0x79,  0x0A,  0x7C, 	/* 153D0 */
+	0x21,  0x4F,  0x94,  0x27,  0xEA,  0x90,  0xA9,  0x8A,  0xA8,  0xFC,  0x48,  0x82,  0x85,  0x41,  0xC4,  0x10, 	/* 153E0 */
+	0x7F,  0xEA,  0xA0,  0x2B,  0xCF,  0x86,  0x2F,  0x8A,  0xAA,  0xA9,  0xCF,  0xFF,  0x88,  0x81,  0x18,  0x8C, 	/* 153F0 */
+	0x7B,  0xC4,  0xA4,  0x7B,  0xC4,  0xA4,  0x7B,  0xC2,  0x94,  0xD6,  0x21,  0xFC,  0x24,  0x0F,  0xFE,  0x24, 	/* 15400 */
+	0x43,  0xFC,  0x8D,  0x3F,  0x82,  0x48,  0x3F,  0x8F,  0xBE,  0xAA,  0xAF,  0xBE,  0x20,  0x03,  0xFC,  0x44, 	/* 15410 */
+	0x0F,  0xFE,  0x24,  0x43,  0xFC,  0x8E,  0x47,  0xC4,  0x44,  0x7F,  0xCA,  0x10,  0x2F,  0xEF,  0x92,  0x23, 	/* 15420 */
+	0xAA,  0x80,  0xAF,  0xEA,  0x94,  0xFA,  0xE8,  0x72,  0x90,  0x42,  0x84,  0xFE,  0x7A,  0x8A,  0xEE,  0x2A, 	/* 15430 */
+	0xAF,  0xEE,  0x21,  0x0A,  0xBE,  0xAE,  0x8A,  0xBE,  0xFA,  0x88,  0x3E,  0x91,  0x00,  0x0F,  0xFE,  0x91, 	/* 15440 */
+	0x2D,  0x12,  0xB5,  0x29,  0x32,  0x99,  0x2A,  0x9A,  0xA2,  0xAC,  0x22,  0x84,  0x28,  0x06,  0x94,  0x00, 	/* 15450 */
+	0x0F,  0xFE,  0x91,  0x28,  0xA2,  0xFF,  0xE8,  0x42,  0xBF,  0xA9,  0x02,  0x90,  0x29,  0x02,  0x8F,  0x28, 	/* 15460 */
+	0x06,  0x95,  0x00,  0x0F,  0xFE,  0x8A,  0x28,  0xA2,  0x13,  0xC2,  0x00,  0x3F,  0x80,  0x40,  0xFF,  0xE0, 	/* 15470 */
+	0x40,  0x04,  0x00,  0x40,  0x98,  0x00,  0x0F,  0xFE,  0x91,  0x2F,  0xFE,  0x00,  0x0F,  0xFE,  0x02,  0x00, 	/* 15480 */
+	0xC0,  0x35,  0x8C,  0x46,  0x04,  0x00,  0x40,  0x9F,  0x00,  0x0F,  0xFE,  0x91,  0x2F,  0xFE,  0x04,  0x00, 	/* 15490 */
+	0x40,  0xFF,  0xE0,  0x40,  0x3F,  0x82,  0x08,  0x20,  0x83,  0xF8,  0xA0,  0x7F,  0xC4,  0xA4,  0x7F,  0xC0, 	/* 154A0 */
+	0x00,  0x7F,  0xC4,  0x04,  0x7F,  0xC4,  0x40,  0x7F,  0xC4,  0x20,  0x79,  0xAC,  0x06,  0xA7,  0x00,  0x07, 	/* 154B0 */
+	0xFE,  0x49,  0x27,  0xFE,  0x10,  0x8F,  0xFE,  0x30,  0x83,  0x9C,  0x56,  0xC5,  0x4A,  0x90,  0x81,  0x08, 	/* 154C0 */
+	0xA8,  0x7F,  0xC4,  0xA4,  0x7F,  0xC0,  0x80,  0xFF,  0xE3,  0xF8,  0x64,  0xCB,  0xFA,  0x24,  0x83,  0xF8, 	/* 154D0 */
+	0x04,  0x20,  0x3E,  0xA9,  0x7F,  0xE4,  0x92,  0x7F,  0xE0,  0x40,  0x07,  0xC0,  0x40,  0x3F,  0x82,  0x08, 	/* 154E0 */
+	0x3F,  0x82,  0x08,  0xFF,  0xE0,  0x40,  0xAA,  0x00,  0x07,  0xFC,  0x4A,  0x47,  0xFC,  0x0A,  0x07,  0xBC, 	/* 154F0 */
+	0x0A,  0x07,  0xBC,  0x0A,  0x0F,  0x3E,  0x12,  0x02,  0x20,  0xAB,  0x00,  0x07,  0xFC,  0x4A,  0x47,  0xFC, 	/* 15500 */
+	0x11,  0x07,  0xD0,  0x11,  0x8F,  0xF4,  0x11,  0x27,  0xD0,  0x1D,  0x0F,  0x10,  0xAE,  0x00,  0x07,  0xFC, 	/* 15510 */
+	0x4A,  0x47,  0xFC,  0x04,  0x0F,  0xFE,  0x04,  0x05,  0xF8,  0x50,  0x85,  0xF8,  0x50,  0x87,  0xFE,  0xB0, 	/* 15520 */
+	0x7F,  0xE4,  0x92,  0x7F,  0xE0,  0x00,  0x39,  0x2F,  0xF2,  0x01,  0x27,  0xD2,  0x01,  0x27,  0xD2,  0x44, 	/* 15530 */
+	0x27,  0xC6,  0xB2,  0x7F,  0xC4,  0xA4,  0x7F,  0xC0,  0x40,  0x7F,  0xC0,  0x50,  0xFF,  0xE1,  0xF8,  0x30, 	/* 15540 */
+	0x8D,  0xF8,  0x10,  0x81,  0xF8,  0xB5,  0x7F,  0xE4,  0x92,  0x7F,  0xE0,  0x00,  0x3F,  0xE2,  0x20,  0x3F, 	/* 15550 */
+	0xC2,  0x20,  0x3F,  0xE4,  0x4A,  0x52,  0x28,  0x8C,  0xB7,  0x7F,  0xE4,  0x92,  0x7F,  0xE1,  0x20,  0x2B, 	/* 15560 */
+	0xCF,  0xA2,  0x49,  0xE7,  0xA0,  0x4A,  0xC7,  0xB0,  0x4A,  0x25,  0x9E,  0xB8,  0x7F,  0xE4,  0x92,  0x7F, 	/* 15570 */
+	0xE2,  0x04,  0x10,  0x4F,  0xFE,  0x00,  0x47,  0xA4,  0x01,  0x47,  0x84,  0x48,  0x47,  0x8C,  0xB9,  0x7F, 	/* 15580 */
+	0xC4,  0xA4,  0x7F,  0xC2,  0x48,  0x25,  0x06,  0xFE,  0x79,  0x0A,  0xFC,  0x29,  0x02,  0xFC,  0x29,  0x02, 	/* 15590 */
+	0xFE,  0x82,  0x7F,  0xE4,  0x92,  0x7F,  0xE2,  0x3C,  0x42,  0x49,  0x3E,  0x6A,  0x2F,  0xBE,  0x2A,  0x2B, 	/* 155A0 */
+	0x3E,  0xAA,  0x22,  0x26,  0x83,  0x7F,  0xC5,  0x24,  0x7F,  0xC0,  0xA0,  0xFF,  0xE2,  0x08,  0x3F,  0x82, 	/* 155B0 */
+	0x08,  0xFF,  0xE3,  0x4C,  0xD5,  0xA0,  0x40,  0x85,  0x00,  0x07,  0xFE,  0x49,  0x27,  0xFE,  0x2A,  0x8D, 	/* 155C0 */
+	0x3E,  0x2E,  0x8F,  0xBE,  0x2A,  0x8B,  0x3E,  0xAA,  0x82,  0x3E,  0x86,  0x7F,  0xC4,  0xA4,  0x7F,  0xC2, 	/* 155D0 */
+	0xA0,  0xFF,  0xC4,  0xA2,  0x79,  0xE4,  0xBC,  0x7A,  0x24,  0x9E,  0x52,  0x48,  0x92,  0x87,  0x7F,  0xC4, 	/* 155E0 */
+	0xA4,  0x7F,  0xC5,  0x10,  0xFF,  0xE5,  0x18,  0xFA,  0x4A,  0xFE,  0xFF,  0x42,  0x54,  0xFF,  0x42,  0x0C, 	/* 155F0 */
+	0x88,  0x7F,  0xC4,  0xA4,  0x7F,  0xC5,  0x00,  0xFF,  0xE5,  0x28,  0xFB,  0xCA,  0xA8,  0xFB,  0xE2,  0x02, 	/* 15600 */
+	0xFA,  0xA2,  0x4C,  0x8A,  0x20,  0x81,  0x10,  0xFF,  0xE0,  0x40,  0x04,  0x07,  0xFC,  0x04,  0x00,  0x40, 	/* 15610 */
+	0xFF,  0xE0,  0x40,  0x04,  0x00,  0x40,  0x8C,  0x20,  0x81,  0x10,  0x7F,  0xC0,  0x40,  0x3F,  0x80,  0x40, 	/* 15620 */
+	0xFF,  0xE0,  0x90,  0x09,  0x01,  0x10,  0x21,  0x2C,  0x0E,  0x8E,  0x20,  0x81,  0x10,  0x7F,  0xC0,  0x40, 	/* 15630 */
+	0x3F,  0x80,  0x40,  0x7F,  0xC0,  0x40,  0xFF,  0xE0,  0xA0,  0x31,  0x8C,  0x06,  0x94,  0x20,  0x81,  0x10, 	/* 15640 */
+	0x7F,  0xC0,  0x40,  0x04,  0x03,  0xF8,  0x04,  0x00,  0x40,  0xFF,  0xE5,  0x24,  0x49,  0x28,  0x92,  0x9A, 	/* 15650 */
+	0x49,  0x05,  0x10,  0x21,  0x8F,  0xA4,  0x27,  0xEF,  0x81,  0x27,  0xC3,  0xA4,  0xE2,  0x42,  0x38,  0x42, 	/* 15660 */
+	0x08,  0x20,  0x9D,  0x48,  0x65,  0x78,  0x24,  0x8F,  0xC8,  0x24,  0x8F,  0xFE,  0x24,  0x83,  0xC8,  0xE6, 	/* 15670 */
+	0x82,  0xCA,  0x40,  0x68,  0xF2,  0x9E,  0x11,  0x07,  0xFC,  0x04,  0x03,  0xFC,  0x04,  0x0F,  0xFE,  0x10, 	/* 15680 */
+	0x03,  0xF8,  0x24,  0x85,  0xFE,  0x88,  0x87,  0xFE,  0xA3,  0x00,  0x07,  0xF8,  0x08,  0x8F,  0xFE,  0x3F, 	/* 15690 */
+	0x85,  0x08,  0x9F,  0x81,  0x10,  0x7F,  0xC0,  0x40,  0xFF,  0xE0,  0x40,  0xA4,  0x02,  0x27,  0xD4,  0x27, 	/* 156A0 */
+	0xEF,  0xE8,  0x24,  0x87,  0xFE,  0x20,  0x83,  0xC8,  0x67,  0xE6,  0x48,  0xA4,  0x83,  0xC8,  0xA8,  0x11, 	/* 156B0 */
+	0x07,  0xFC,  0x04,  0x03,  0xF8,  0x04,  0x0F,  0xFE,  0x24,  0x09,  0x7E,  0x4A,  0x43,  0x20,  0x4D,  0x8B, 	/* 156C0 */
+	0x06,  0xA9,  0x11,  0x07,  0xFE,  0x04,  0x03,  0xFC,  0x04,  0x07,  0xFE,  0x12,  0x4F,  0xFE,  0x11,  0x47, 	/* 156D0 */
+	0xCA,  0x13,  0x63,  0x02,  0xAE,  0x11,  0x0F,  0xFE,  0x04,  0x07,  0xFC,  0x04,  0x0F,  0xFE,  0x52,  0x4B, 	/* 156E0 */
+	0xFA,  0x04,  0x0F,  0xFE,  0x1B,  0x0E,  0x0E,  0xAF,  0x48,  0x05,  0x3C,  0x22,  0x4F,  0xFC,  0x22,  0x4F, 	/* 156F0 */
+	0xBC,  0x22,  0x03,  0x3E,  0xE5,  0x22,  0xEA,  0x47,  0xA8,  0x0C,  0xB2,  0x11,  0x07,  0xFC,  0x04,  0x03, 	/* 15700 */
+	0xF8,  0x04,  0x0F,  0xFE,  0x71,  0x4F,  0xFE,  0x69,  0x4B,  0xC8,  0x09,  0x63,  0x22,  0xB6,  0x91,  0x05, 	/* 15710 */
+	0xFE,  0x2A,  0xAF,  0xBA,  0x28,  0x2F,  0xFE,  0x20,  0x03,  0x7C,  0xE4,  0x42,  0x7C,  0x44,  0x49,  0xFF, 	/* 15720 */
+	0xB8,  0x04,  0x0F,  0xFE,  0x40,  0x03,  0xFC,  0x20,  0x8F,  0xFE,  0xAA,  0xAE,  0xFA,  0xA5,  0xAF,  0xEE, 	/* 15730 */
+	0xA4,  0xAA,  0x92,  0xB9,  0x11,  0x0F,  0xFE,  0x3F,  0x80,  0x40,  0xFF,  0xE5,  0x14,  0x9B,  0x2F,  0xFC, 	/* 15740 */
+	0x04,  0x0F,  0xFE,  0x1B,  0x0E,  0x0E,  0xBD,  0x00,  0x0F,  0xFE,  0x08,  0x24,  0xA2,  0x29,  0x20,  0x82, 	/* 15750 */
+	0x18,  0x62,  0x8A,  0xCB,  0x20,  0x82,  0x08,  0x21,  0x86,  0x81,  0x09,  0x01,  0x48,  0x24,  0x4C,  0x93, 	/* 15760 */
+	0x3F,  0x80,  0x04,  0xFF,  0xE4,  0x92,  0x28,  0xA3,  0x8E,  0xCB,  0x21,  0x86,  0x85,  0x20,  0x02,  0xFE, 	/* 15770 */
+	0xF9,  0x22,  0x36,  0x25,  0xAF,  0x12,  0x13,  0x65,  0x5A,  0x29,  0x23,  0x36,  0x4C,  0x08,  0x3F,  0x86, 	/* 15780 */
+	0xFB,  0xE2,  0x8A,  0xDB,  0x62,  0x8A,  0xCB,  0x20,  0x80,  0xFF,  0x81,  0x0A,  0x24,  0x6F,  0xFE,  0x04, 	/* 15790 */
+	0x00,  0x40,  0x8A,  0x20,  0x02,  0x7E,  0x21,  0x2F,  0xB6,  0x15,  0xA9,  0x12,  0x51,  0x25,  0x36,  0x25, 	/* 157A0 */
+	0xA3,  0x12,  0xC1,  0x20,  0x36,  0x8C,  0x00,  0x0F,  0xBE,  0x49,  0x22,  0x8A,  0xCB,  0x21,  0x86,  0x04, 	/* 157B0 */
+	0x07,  0xFC,  0x11,  0x00,  0x90,  0x0A,  0x0F,  0xFE,  0x92,  0x00,  0x0F,  0xBE,  0x49,  0x23,  0x8E,  0xCB, 	/* 157C0 */
+	0x21,  0x86,  0x08,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x94,  0x90,  0x05,  0xFE,  0x22, 	/* 157D0 */
+	0x2F,  0xB2,  0x26,  0xAF,  0xA2,  0x22,  0x63,  0x6A,  0xEB,  0x22,  0x22,  0x42,  0x28,  0x66,  0x95,  0x04, 	/* 157E0 */
+	0x00,  0xA0,  0x3F,  0x8C,  0x06,  0x3F,  0x82,  0x08,  0x3F,  0x8F,  0xBE,  0x28,  0xAD,  0xB6,  0x28,  0xAC, 	/* 157F0 */
+	0xB2,  0xA0,  0x00,  0x0F,  0xBE,  0x49,  0x22,  0x8A,  0xCB,  0x20,  0x40,  0xFF,  0xE2,  0x48,  0x55,  0x4F, 	/* 15800 */
+	0xFE,  0x04,  0x00,  0x40,  0xA1,  0x0A,  0x0F,  0xBE,  0x0A,  0x07,  0xBC,  0x0A,  0x0F,  0xBE,  0x12,  0x0F, 	/* 15810 */
+	0xBE,  0x28,  0xAD,  0xB6,  0x28,  0xAC,  0xB2,  0xA6,  0x11,  0x0F,  0xFE,  0x7A,  0x44,  0xA4,  0x7A,  0x44, 	/* 15820 */
+	0xA4,  0x58,  0xCF,  0xBE,  0x28,  0xAD,  0xB6,  0x28,  0xAC,  0xB2,  0xA9,  0xF8,  0x00,  0xFE,  0x79,  0x24, 	/* 15830 */
+	0xB6,  0x7D,  0xA4,  0x12,  0x7F,  0x6D,  0x5A,  0xD5,  0x27,  0xD2,  0x55,  0x24,  0xD6,  0xAB,  0x00,  0x0F, 	/* 15840 */
+	0xFC,  0xB4,  0x06,  0xC0,  0xB7,  0xE2,  0x68,  0x22,  0x8F,  0xA8,  0x8A,  0x8F,  0xA8,  0x8A,  0xAF,  0xC6, 	/* 15850 */
+	0xB0,  0x20,  0x8F,  0x94,  0x22,  0x2F,  0xC1,  0x8F,  0xEF,  0x92,  0x8D,  0xAF,  0xB6,  0x21,  0x2F,  0xB6, 	/* 15860 */
+	0x25,  0xA2,  0x12,  0xB3,  0xFB,  0x8A,  0x2A,  0xFC,  0xAB,  0x7E,  0xCA,  0x4F,  0x98,  0x06,  0x6F,  0xFC, 	/* 15870 */
+	0x29,  0x4D,  0xEC,  0x29,  0x4C,  0xE4,  0xB9,  0x20,  0x0F,  0x7E,  0x21,  0x25,  0x36,  0xFD,  0xA5,  0x12, 	/* 15880 */
+	0xFB,  0x60,  0x5A,  0xF9,  0x25,  0x36,  0x50,  0x18,  0xFF,  0xBB,  0x18,  0x0E,  0xFE,  0x71,  0x2F,  0x92, 	/* 15890 */
+	0x35,  0xA6,  0xB6,  0xA1,  0x2F,  0xB6,  0xAD,  0xAF,  0x92,  0xA9,  0x2F,  0xB6,  0xBC,  0xFF,  0xC4,  0xA4, 	/* 158A0 */
+	0x29,  0x47,  0xFC,  0x24,  0x83,  0xF8,  0x24,  0x87,  0xFC,  0x11,  0x0F,  0xFF,  0x11,  0x8E,  0x06,  0x80, 	/* 158B0 */
+	0x27,  0xE2,  0x12,  0xAB,  0x67,  0x12,  0x27,  0xEF,  0xA8,  0x53,  0xE5,  0x68,  0x5B,  0xE5,  0x3E,  0x82, 	/* 158C0 */
+	0x80,  0x3E,  0x81,  0x04,  0x00,  0x40,  0x7F,  0xC0,  0x50,  0x06,  0x0F,  0xFE,  0x18,  0x02,  0x98,  0xCE, 	/* 158D0 */
+	0x00,  0x80,  0x08,  0x40,  0x7C,  0x83,  0x04,  0x00,  0x44,  0x3F,  0x80,  0x50,  0xFF,  0xE0,  0x40,  0x0F, 	/* 158E0 */
+	0xC3,  0x80,  0xCF,  0x80,  0x08,  0x00,  0x80,  0x30,  0x84,  0x04,  0x07,  0xFC,  0x05,  0x0F,  0xFE,  0x38, 	/* 158F0 */
+	0x8C,  0xF0,  0x08,  0x47,  0xFC,  0x08,  0x0F,  0xFC,  0x08,  0x20,  0x7E,  0x85,  0x04,  0x03,  0xF8,  0x04, 	/* 15900 */
+	0x80,  0x50,  0xFF,  0xE0,  0x40,  0x1F,  0x83,  0x08,  0xDF,  0x81,  0x08,  0x10,  0x81,  0xF8,  0x86,  0x04, 	/* 15910 */
+	0x07,  0xFC,  0x05,  0x0F,  0xFE,  0x38,  0xCC,  0xF0,  0x08,  0x23,  0xFE,  0x20,  0x83,  0xF8,  0x20,  0x83, 	/* 15920 */
+	0xF8,  0x8B,  0x04,  0x07,  0xFC,  0x05,  0x0F,  0xFE,  0x30,  0x0C,  0xFC,  0x00,  0x0F,  0xFE,  0x11,  0x87, 	/* 15930 */
+	0xE4,  0x04,  0x0F,  0xFE,  0x8C,  0x00,  0x0F,  0xFE,  0x02,  0x00,  0x40,  0x7F,  0xE4,  0x92,  0x49,  0x24, 	/* 15940 */
+	0x92,  0x49,  0x24,  0x92,  0x49,  0x24,  0x06,  0x90,  0x00,  0x4F,  0x84,  0x20,  0x4F,  0xFF,  0xA8,  0x4A, 	/* 15950 */
+	0xA4,  0xA9,  0x4A,  0x94,  0xA8,  0x4A,  0x84,  0xA8,  0x49,  0x8C,  0x92,  0x04,  0x00,  0x4C,  0x7F,  0x00, 	/* 15960 */
+	0x40,  0x7F,  0xC0,  0x40,  0xFF,  0xE0,  0x40,  0x0E,  0x03,  0x58,  0xC4,  0x60,  0x40,  0x95,  0x22,  0x42, 	/* 15970 */
+	0x24,  0xFA,  0x42,  0x7E,  0x7A,  0x42,  0x24,  0xFA,  0x46,  0xFE,  0x72,  0x4A,  0xA4,  0xA4,  0x42,  0x84, 	/* 15980 */
+	0x97,  0x20,  0xCF,  0xF0,  0x21,  0x0F,  0x9E,  0x27,  0x0F,  0x90,  0x21,  0xE7,  0x70,  0x69,  0x0A,  0x12, 	/* 15990 */
+	0xA1,  0x22,  0x0E,  0x98,  0x20,  0x03,  0xBC,  0xE0,  0x02,  0x00,  0xFF,  0xE2,  0x10,  0xF9,  0x02,  0x14, 	/* 159A0 */
+	0x72,  0x46,  0xAE,  0xA7,  0x22,  0x02,  0x99,  0x20,  0x03,  0x7C,  0xE5,  0x42,  0x54,  0xF5,  0x42,  0x54, 	/* 159B0 */
+	0xFF,  0xC2,  0x40,  0x74,  0x06,  0xC0,  0xA4,  0x22,  0x3E,  0x9C,  0x20,  0x03,  0xBC,  0xE2,  0x42,  0x24, 	/* 159C0 */
+	0xFB,  0xC2,  0x20,  0xFA,  0x02,  0x3E,  0x72,  0x26,  0xA2,  0xA2,  0x22,  0x3E,  0xA1,  0x20,  0x82,  0xE8, 	/* 159D0 */
+	0xFA,  0x82,  0xBE,  0xFE,  0xA2,  0xAA,  0xFA,  0xA2,  0xEA,  0x6A,  0xA6,  0xBA,  0xBD,  0x22,  0x2C,  0xA8, 	/* 159E0 */
+	0x20,  0x02,  0xFE,  0xF5,  0xC2,  0x40,  0xFF,  0xE2,  0x5A,  0xFD,  0x43,  0x7A,  0x68,  0x46,  0xFE,  0xB1, 	/* 159F0 */
+	0x42,  0x0C,  0xB3,  0x00,  0x0F,  0xFE,  0x21,  0x02,  0x10,  0x3F,  0x02,  0x10,  0x3F,  0x02,  0x10,  0x21, 	/* 15A00 */
+	0xE3,  0xF0,  0xE1,  0x00,  0x10,  0xB6,  0x00,  0x0F,  0xFC,  0x4A,  0x44,  0xA8,  0x7B,  0x04,  0xB8,  0x7A, 	/* 15A10 */
+	0x44,  0xA2,  0x4E,  0x27,  0xBC,  0xCA,  0x00,  0xA0,  0xBB,  0x01,  0x0F,  0xD0,  0x51,  0x07,  0x10,  0x55, 	/* 15A20 */
+	0xC5,  0x50,  0x75,  0x05,  0x50,  0x55,  0x07,  0x50,  0xD5,  0x01,  0xFE,  0xBD,  0x01,  0x0F,  0x90,  0x5F, 	/* 15A30 */
+	0xE5,  0x92,  0x79,  0x25,  0x10,  0x71,  0x85,  0x18,  0x5A,  0x8F,  0x2A,  0x14,  0xA1,  0x86,  0xBF,  0x01, 	/* 15A40 */
+	0x0F,  0xD0,  0x51,  0x47,  0x54,  0x55,  0x45,  0x98,  0x71,  0x05,  0x28,  0x52,  0x87,  0x44,  0xD8,  0x41, 	/* 15A50 */
+	0x02,  0x86,  0x01,  0x0F,  0x90,  0x52,  0x85,  0x44,  0x7F,  0xE5,  0x01,  0x7F,  0xC5,  0x24,  0x52,  0x4F, 	/* 15A60 */
+	0x38,  0x12,  0x01,  0x20,  0x8A,  0x02,  0x0F,  0xCE,  0x5A,  0xA7,  0xAA,  0x5A,  0xA5,  0xAA,  0x7A,  0xA5, 	/* 15A70 */
+	0xAA,  0x5E,  0xAF,  0x2E,  0x14,  0x81,  0x88,  0x92,  0x00,  0xCF,  0xF0,  0x51,  0x05,  0x10,  0x7F,  0xE5, 	/* 15A80 */
+	0x10,  0x71,  0x05,  0x7C,  0x54,  0x4F,  0x44,  0x14,  0x41,  0x7C,  0x96,  0x00,  0x0F,  0xFE,  0x4A,  0x27, 	/* 15A90 */
+	0xA2,  0x4A,  0x2F,  0xBE,  0x08,  0x07,  0xFE,  0x04,  0x01,  0xF8,  0x04,  0x07,  0xFE,  0x98,  0x01,  0x0F, 	/* 15AA0 */
+	0xFE,  0x55,  0x25,  0x7E,  0x75,  0x25,  0x7E,  0x70,  0x05,  0xFF,  0x51,  0x0F,  0x3C,  0x10,  0x41,  0x18, 	/* 15AB0 */
+	0x9A,  0xFC,  0x04,  0xFE,  0x7A,  0x44,  0x98,  0x7E,  0x4C,  0x82,  0x0B,  0x87,  0xC2,  0x26,  0xCD,  0x58, 	/* 15AC0 */
+	0x24,  0x6C,  0x40,  0x9E,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0x02,  0xBF,  0xA9,  0x12, 	/* 15AD0 */
+	0x9F,  0x29,  0x12,  0xBF,  0x28,  0x16,  0x9F,  0x40,  0x07,  0xDE,  0x91,  0x2F,  0xF2,  0x29,  0xE4,  0x40, 	/* 15AE0 */
+	0xFF,  0xE1,  0x08,  0x1F,  0x81,  0x0E,  0x7F,  0x80,  0x08,  0xA1,  0x02,  0x8F,  0xA8,  0x55,  0x45,  0x92, 	/* 15AF0 */
+	0x72,  0x45,  0x2C,  0x77,  0x45,  0x00,  0x54,  0x8F,  0xAA,  0x1A,  0x21,  0x1A,  0xA2,  0x01,  0x0F,  0xFE, 	/* 15B00 */
+	0x54,  0x25,  0x42,  0x77,  0xC5,  0x10,  0x75,  0x05,  0x5C,  0x55,  0x07,  0x70,  0xD5,  0x81,  0x86,  0xA8, 	/* 15B10 */
+	0x02,  0x2F,  0xA2,  0x54,  0x47,  0xAA,  0x54,  0x55,  0xEF,  0x72,  0x55,  0x24,  0x5F,  0xF7,  0x24,  0xD2, 	/* 15B20 */
+	0x41,  0x44,  0xAF,  0x01,  0x1F,  0xA2,  0x55,  0x55,  0x22,  0x77,  0x75,  0x11,  0x75,  0x55,  0x55,  0x57, 	/* 15B30 */
+	0x77,  0x55,  0xD2,  0x51,  0x44,  0xB0,  0x02,  0x0F,  0xFE,  0x55,  0x25,  0x5E,  0x76,  0x65,  0x4A,  0x75, 	/* 15B40 */
+	0x25,  0x7E,  0x53,  0x07,  0x6A,  0xDA,  0x21,  0x1E,  0xB2,  0x13,  0x8F,  0xEA,  0x57,  0xE7,  0xE8,  0x41, 	/* 15B50 */
+	0x88,  0x64,  0x7F,  0xE1,  0x08,  0x1F,  0x81,  0x0E,  0xFF,  0x80,  0x08,  0xB3,  0x24,  0x45,  0x6A,  0xA9, 	/* 15B60 */
+	0x06,  0x5C,  0xA7,  0x02,  0x8E,  0x7F,  0xE1,  0x08,  0x1F,  0x81,  0x0E,  0xFF,  0x80,  0x08,  0xB4,  0x01, 	/* 15B70 */
+	0x0F,  0xFE,  0x51,  0x07,  0xFE,  0x5A,  0xA5,  0xAA,  0x7F,  0xE5,  0x20,  0x52,  0x8F,  0x6A,  0x1A,  0x21, 	/* 15B80 */
+	0x1A,  0xB6,  0x7F,  0xC1,  0x10,  0x1F,  0x01,  0x10,  0x7F,  0x80,  0x10,  0xFF,  0xE4,  0xA4,  0x7B,  0xC4, 	/* 15B90 */
+	0xA4,  0xFF,  0xC0,  0x84,  0xB7,  0x02,  0x4F,  0xFE,  0x55,  0x55,  0x54,  0x7F,  0xF5,  0x04,  0x77,  0x55, 	/* 15BA0 */
+	0x55,  0x57,  0x67,  0x5A,  0xD7,  0xA1,  0x11,  0xB9,  0x00,  0x8F,  0xFF,  0x55,  0x17,  0x1A,  0x55,  0x55, 	/* 15BB0 */
+	0x8F,  0x77,  0xE5,  0x5A,  0x5F,  0xFF,  0x08,  0x10,  0x81,  0x18,  0xBD,  0xF1,  0x05,  0xFE,  0x71,  0x05, 	/* 15BC0 */
+	0xFE,  0xFA,  0xA1,  0xFE,  0xF0,  0x05,  0x7E,  0x73,  0x05,  0x6A,  0xFA,  0x21,  0x1E,  0xBE,  0xFA,  0x04, 	/* 15BD0 */
+	0xBE,  0xFC,  0x44,  0xBC,  0x7A,  0x24,  0x9E,  0xFF,  0xE1,  0x10,  0x1F,  0x01,  0x10,  0xFF,  0xE0,  0x10, 	/* 15BE0 */
+	0xBF,  0x04,  0x03,  0xF8,  0x04,  0x8F,  0xFE,  0x04,  0x83,  0xF8,  0x04,  0x07,  0xFC,  0x04,  0x0F,  0xFE, 	/* 15BF0 */
+	0x04,  0x00,  0x40,  0x84,  0x81,  0x0F,  0x7C,  0x81,  0x4F,  0xFE,  0x41,  0x47,  0xFC,  0x51,  0x0F,  0xBC, 	/* 15C00 */
+	0x11,  0x03,  0x7E,  0x49,  0x08,  0x10,  0x85,  0x04,  0x07,  0xFC,  0x04,  0x4F,  0xFF,  0x04,  0x47,  0xFC, 	/* 15C10 */
+	0x55,  0x45,  0x54,  0x7F,  0xC4,  0x44,  0x75,  0xC9,  0x54,  0x86,  0x01,  0x07,  0xFC,  0x41,  0x47,  0xFE, 	/* 15C20 */
+	0x41,  0x47,  0x7C,  0x41,  0x0F,  0xFC,  0x51,  0x04,  0xFE,  0x79,  0x0C,  0x50,  0x87,  0xFA,  0x00,  0x3E, 	/* 15C30 */
+	0x7D,  0x44,  0x98,  0x7E,  0x68,  0x40,  0x7F,  0xC0,  0x44,  0xFF,  0xE0,  0x40,  0x7F,  0xC0,  0x40,  0x89, 	/* 15C40 */
+	0x04,  0x00,  0x40,  0xFF,  0xE8,  0x42,  0x8A,  0x2B,  0x1A,  0x84,  0x28,  0x42,  0x8A,  0x2B,  0x1A,  0x80, 	/* 15C50 */
+	0x28,  0x06,  0x8B,  0x01,  0x07,  0x10,  0x51,  0x05,  0xFE,  0x71,  0x25,  0x12,  0x51,  0x27,  0x12,  0x52, 	/* 15C60 */
+	0x25,  0x22,  0x54,  0x2B,  0x8C,  0x8C,  0x77,  0x85,  0x48,  0x54,  0x85,  0x48,  0x74,  0x85,  0x48,  0x54, 	/* 15C70 */
+	0x87,  0x48,  0x54,  0x85,  0x4A,  0x58,  0xAB,  0x86,  0x93,  0x04,  0x0F,  0xFE,  0x40,  0x03,  0xFC,  0x00, 	/* 15C80 */
+	0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x82,  0x18,  0x96,  0x24,  0x81,  0x48,  0x15, 	/* 15C90 */
+	0x00,  0x40,  0x3F,  0x82,  0x08,  0x3F,  0x82,  0x08,  0x3F,  0x82,  0x08,  0x20,  0x82,  0x18,  0x98,  0x00, 	/* 15CA0 */
+	0x47,  0x84,  0x48,  0x44,  0xBF,  0x78,  0x44,  0x84,  0x4A,  0x47,  0x94,  0x49,  0x44,  0x84,  0x48,  0x49, 	/* 15CB0 */
+	0x8C,  0x9A,  0x01,  0x07,  0x10,  0x51,  0x05,  0x10,  0x7F,  0xC5,  0x10,  0x51,  0x07,  0x10,  0x51,  0x05, 	/* 15CC0 */
+	0x10,  0x5F,  0xEB,  0x00,  0x9B,  0x00,  0x07,  0x7C,  0x51,  0x05,  0x10,  0x71,  0x05,  0x10,  0x51,  0x07, 	/* 15CD0 */
+	0x10,  0x51,  0x05,  0x10,  0x5F,  0xEB,  0x00,  0x9D,  0x7B,  0xE4,  0x88,  0x48,  0x84,  0x88,  0x7F,  0xF4, 	/* 15CE0 */
+	0x88,  0x48,  0x87,  0x88,  0x48,  0x84,  0x88,  0x48,  0x89,  0x88,  0xA1,  0x03,  0x87,  0xA8,  0x4A,  0x84, 	/* 15CF0 */
+	0xAA,  0x7C,  0x64,  0x80,  0x4F,  0xC7,  0x84,  0x4A,  0x84,  0x90,  0x4A,  0x89,  0xC6,  0xA2,  0x01,  0x07, 	/* 15D00 */
+	0x90,  0x4F,  0xE4,  0x90,  0x79,  0x04,  0xFE,  0x4A,  0x47,  0xA4,  0x49,  0x84,  0x98,  0x4A,  0x49,  0xC2, 	/* 15D10 */
+	0xA5,  0x00,  0x07,  0x7E,  0x55,  0x25,  0x52,  0x75,  0x25,  0x7E,  0x54,  0x07,  0x40,  0x54,  0x05,  0x42, 	/* 15D20 */
+	0x54,  0x2B,  0x3E,  0xA9,  0x00,  0x07,  0xFE,  0x00,  0x07,  0xFE,  0x40,  0x27,  0xFE,  0x50,  0x45,  0xFC, 	/* 15D30 */
+	0x50,  0x45,  0xFC,  0x90,  0x41,  0x0C,  0xAA,  0x02,  0x0F,  0x20,  0x9F,  0xE9,  0x20,  0xF2,  0x09,  0x3C, 	/* 15D40 */
+	0x92,  0x4F,  0x24,  0x94,  0x49,  0x44,  0x98,  0x4B,  0x18,  0xAC,  0x01,  0x07,  0x94,  0x49,  0x24,  0xFE, 	/* 15D50 */
+	0x79,  0x04,  0x90,  0x49,  0x87,  0x98,  0x4A,  0x84,  0xAA,  0x4C,  0xA9,  0x86,  0xAD,  0x07,  0x0E,  0x10, 	/* 15D60 */
+	0xA1,  0x0A,  0xFE,  0xE9,  0x2A,  0x92,  0xAA,  0xAE,  0xAA,  0xAC,  0x6A,  0x82,  0xA8,  0x2A,  0x86,  0xAF, 	/* 15D70 */
+	0x04,  0x02,  0x78,  0x24,  0x0F,  0xFE,  0x00,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x20, 	/* 15D80 */
+	0x82,  0x18,  0xB1,  0x01,  0x07,  0x10,  0x51,  0x05,  0xFE,  0x72,  0x05,  0x28,  0x52,  0x87,  0x48,  0x55, 	/* 15D90 */
+	0x45,  0x92,  0x59,  0xEB,  0x32,  0xB2,  0x04,  0x0F,  0xFE,  0x09,  0x01,  0x38,  0x7C,  0x43,  0xF8,  0x20, 	/* 15DA0 */
+	0x83,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x82,  0x18,  0xB4,  0x30,  0x80,  0xD0,  0x07,  0x07,  0x88,  0x08, 	/* 15DB0 */
+	0x0F,  0xFE,  0x10,  0x83,  0xF8,  0xD0,  0x81,  0xF8,  0x10,  0x81,  0x18,  0xBA,  0x01,  0x07,  0x10,  0x5F, 	/* 15DC0 */
+	0xE5,  0x10,  0x71,  0x05,  0x7E,  0x55,  0x27,  0x52,  0x55,  0x25,  0x56,  0x51,  0x0B,  0x10,  0x83,  0x00, 	/* 15DD0 */
+	0x07,  0xFC,  0x44,  0x47,  0xFC,  0x44,  0x47,  0xFC,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x82, 	/* 15DE0 */
+	0x18,  0x84,  0x04,  0x07,  0xFC,  0x44,  0x47,  0xFC,  0x44,  0x47,  0xFC,  0x20,  0x83,  0xF8,  0x20,  0x83, 	/* 15DF0 */
+	0xF8,  0x20,  0x82,  0x18,  0x86,  0x00,  0x07,  0xBC,  0x4A,  0x44,  0xA4,  0x7B,  0xC4,  0xA4,  0x4A,  0x47, 	/* 15E00 */
+	0xA4,  0x4B,  0xC4,  0x80,  0x48,  0x09,  0xFE,  0x8C,  0x0A,  0x0F,  0xA6,  0x0B,  0x83,  0xA2,  0xC9,  0xE3, 	/* 15E10 */
+	0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x82,  0x18,  0x8E,  0x01,  0x0F,  0x10,  0x92,  0x89, 	/* 15E20 */
+	0x24,  0xF4,  0xE9,  0xF2,  0x90,  0x0F,  0x7C,  0x94,  0x49,  0x44,  0x94,  0x4B,  0x7C,  0x96,  0x01,  0x07, 	/* 15E30 */
+	0x98,  0x4B,  0x44,  0xD2,  0x7F,  0xC4,  0x90,  0x49,  0x07,  0xFE,  0x49,  0x04,  0x90,  0x49,  0x09,  0x90, 	/* 15E40 */
+	0x99,  0x02,  0x07,  0xA0,  0x4B,  0xE4,  0xD0,  0x7D,  0x04,  0x9E,  0x49,  0x07,  0x90,  0x49,  0xE4,  0x90, 	/* 15E50 */
+	0x49,  0x09,  0x90,  0x9A,  0x00,  0x07,  0xFE,  0x48,  0x84,  0x88,  0x79,  0x04,  0x9C,  0x4B,  0x27,  0xD0, 	/* 15E60 */
+	0x49,  0x04,  0x90,  0x49,  0x09,  0xFE,  0x9B,  0x00,  0x07,  0x7E,  0x55,  0x25,  0x52,  0x77,  0xE5,  0x52, 	/* 15E70 */
+	0x55,  0x27,  0x7E,  0x51,  0x05,  0x10,  0x51,  0x0B,  0x10,  0x9D,  0x00,  0xC7,  0x70,  0x55,  0x05,  0x50, 	/* 15E80 */
+	0x75,  0x05,  0x7E,  0x54,  0x87,  0x48,  0x54,  0x85,  0xEA,  0x50,  0x6B,  0xFA,  0x9E,  0x04,  0x07,  0x40, 	/* 15E90 */
+	0x57,  0xE5,  0x82,  0x77,  0xA5,  0x0A,  0x50,  0xA7,  0x7A,  0x54,  0xC5,  0x40,  0x54,  0x2B,  0x3E,  0xA1, 	/* 15EA0 */
+	0x00,  0x02,  0x3E,  0x22,  0x2F,  0xE2,  0x23,  0xE2,  0x22,  0x7A,  0x24,  0xBE,  0x4A,  0x24,  0xA2,  0x7A, 	/* 15EB0 */
+	0x20,  0x46,  0xA4,  0x44,  0x44,  0x94,  0x52,  0x44,  0xC4,  0x49,  0x47,  0xFC,  0x51,  0x45,  0xF4,  0x51, 	/* 15EC0 */
+	0x45,  0xF5,  0x51,  0x59,  0x33,  0xA5,  0x00,  0x0F,  0xFE,  0x24,  0x02,  0x7C,  0x54,  0x0B,  0xFE,  0x20, 	/* 15ED0 */
+	0x83,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x82,  0x18,  0xAF,  0x01,  0x07,  0x10,  0x5F,  0xE5,  0x28,  0x77, 	/* 15EE0 */
+	0xC5,  0x83,  0x57,  0xE7,  0x20,  0x53,  0xC5,  0x24,  0x50,  0x4B,  0x18,  0xB1,  0x01,  0x07,  0x92,  0x4D, 	/* 15EF0 */
+	0x24,  0xB4,  0x79,  0x04,  0xFE,  0x4A,  0x87,  0xA8,  0x4A,  0x84,  0xCA,  0x4C,  0xA9,  0x86,  0xB4,  0x00, 	/* 15F00 */
+	0x0E,  0xFE,  0xA8,  0x2A,  0xBA,  0xE8,  0x2A,  0xBA,  0xAA,  0xAE,  0xAA,  0xAB,  0xAA,  0x82,  0xA8,  0x2A, 	/* 15F10 */
+	0x86,  0xB8,  0x04,  0x0E,  0x40,  0xA7,  0xEA,  0x82,  0xF0,  0xAA,  0xDA,  0xAA,  0xAE,  0xDA,  0xA8,  0xAA, 	/* 15F20 */
+	0xFA,  0xA0,  0x2A,  0x0C,  0xBC,  0x04,  0x47,  0x24,  0x52,  0x85,  0x7E,  0x72,  0x45,  0x24,  0x5F,  0xF7, 	/* 15F30 */
+	0x24,  0x52,  0x45,  0x24,  0x54,  0x4B,  0x84,  0xBD,  0x22,  0x02,  0x24,  0x4B,  0x8F,  0x60,  0x06,  0x27, 	/* 15F40 */
+	0x9E,  0x4A,  0x07,  0xA4,  0x4B,  0x87,  0xA0,  0x4A,  0x25,  0x9E,  0x82,  0x02,  0x07,  0xA4,  0x4B,  0x84, 	/* 15F50 */
+	0xA0,  0x7A,  0x24,  0x9E,  0x48,  0x07,  0xBE,  0x4A,  0x24,  0xBE,  0x4A,  0x29,  0xBE,  0x85,  0x04,  0x03, 	/* 15F60 */
+	0xF8,  0x04,  0x82,  0x98,  0xFB,  0xE2,  0x92,  0xDA,  0x63,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x82,  0x18, 	/* 15F70 */
+	0x86,  0x01,  0x07,  0x1E,  0x52,  0x45,  0xFE,  0x74,  0x05,  0x5C,  0x55,  0x47,  0x54,  0x55,  0xC5,  0x50, 	/* 15F80 */
+	0x59,  0x2B,  0x0E,  0x87,  0x02,  0x0E,  0xFC,  0xA2,  0x4A,  0x24,  0xE4,  0x4A,  0x98,  0xA8,  0x8F,  0xFE, 	/* 15F90 */
+	0xAA,  0xAA,  0xAA,  0xAA,  0xAB,  0x54,  0x88,  0x00,  0xC7,  0x70,  0x54,  0x25,  0x5C,  0x75,  0x15,  0x52, 	/* 15FA0 */
+	0x55,  0xC7,  0x58,  0x55,  0x45,  0x54,  0x55,  0x2B,  0x91,  0x89,  0x02,  0x07,  0x10,  0x50,  0x05,  0x70, 	/* 15FB0 */
+	0x71,  0x25,  0xFC,  0x53,  0x87,  0x54,  0x55,  0x45,  0x92,  0x51,  0x1B,  0x30,  0x8A,  0x04,  0x0F,  0x5E, 	/* 15FC0 */
+	0x04,  0x0F,  0xBE,  0x11,  0x03,  0xF8,  0xD1,  0x61,  0xF0,  0x11,  0x01,  0xF0,  0x11,  0x01,  0x30,  0x9A, 	/* 15FD0 */
+	0x04,  0x0E,  0x4E,  0xBF,  0xAA,  0x4A,  0xE4,  0xAB,  0xFA,  0xA4,  0xAE,  0xAA,  0xAB,  0xCB,  0xD8,  0xA0, 	/* 15FE0 */
+	0x8A,  0x08,  0x9B,  0x00,  0x07,  0xFC,  0x55,  0x45,  0xA8,  0x75,  0x45,  0x54,  0x50,  0x07,  0xFC,  0x52, 	/* 15FF0 */
+	0x05,  0x20,  0x52,  0x0B,  0xFC,  0xA3,  0x00,  0x03,  0xFE,  0x20,  0x03,  0xFE,  0x2A,  0x44,  0xD8,  0x98, 	/* 16000 */
+	0x63,  0xFC,  0x20,  0x43,  0xFC,  0x20,  0x42,  0x0C,  0xA9,  0x22,  0x02,  0x7E,  0x2A,  0x44,  0x38,  0x54, 	/* 16010 */
+	0x4D,  0xFE,  0x54,  0x55,  0x7C,  0x54,  0x45,  0x7C,  0x44,  0x44,  0x4C,  0xAF,  0x01,  0x47,  0x12,  0x57, 	/* 16020 */
+	0xE5,  0x10,  0x77,  0xE5,  0x52,  0x57,  0xE7,  0x52,  0x57,  0xE5,  0x52,  0x55,  0x2B,  0x56,  0xB1,  0x04, 	/* 16030 */
+	0x47,  0x24,  0x52,  0x85,  0x7C,  0x74,  0x45,  0x44,  0x57,  0xC7,  0x28,  0x52,  0x85,  0x2A,  0x54,  0xAB, 	/* 16040 */
+	0x46,  0xB3,  0x02,  0x2E,  0x92,  0xA5,  0x4A,  0x48,  0xE0,  0x0A,  0x8A,  0xAE,  0xAE,  0x92,  0xAA,  0xAA, 	/* 16050 */
+	0xCA,  0xA8,  0x2A,  0xFE,  0xB9,  0x00,  0x07,  0x7C,  0x54,  0x05,  0x7C,  0x74,  0x05,  0x7C,  0x54,  0x07, 	/* 16060 */
+	0xFE,  0x55,  0x45,  0x48,  0x57,  0x4B,  0xC2,  0xBE,  0x01,  0x07,  0x7E,  0x55,  0x25,  0x7E,  0x75,  0x25, 	/* 16070 */
+	0x7E,  0x52,  0x87,  0x48,  0x5F,  0xF5,  0x08,  0x50,  0x8B,  0x08,  0x86,  0x02,  0x87,  0x28,  0x5F,  0xE5, 	/* 16080 */
+	0xAA,  0x7A,  0xA5,  0xFE,  0x5A,  0xA7,  0xAA,  0x5F,  0xF5,  0x14,  0x52,  0x2B,  0x42,  0x8B,  0x01,  0x07, 	/* 16090 */
+	0x10,  0x5F,  0xE5,  0x28,  0x73,  0xC5,  0x54,  0x5E,  0xC7,  0x58,  0x54,  0x85,  0x54,  0x56,  0x4B,  0x42, 	/* 160A0 */
+	0x8E,  0xFB,  0xEA,  0x02,  0xFB,  0x4A,  0x08,  0xFB,  0x63,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8, 	/* 160B0 */
+	0x20,  0x82,  0x18,  0x90,  0x04,  0x07,  0xFE,  0x48,  0x85,  0xFE,  0x6A,  0x84,  0x98,  0x5F,  0xC5,  0x24, 	/* 160C0 */
+	0x5D,  0xC9,  0x24,  0x9D,  0xC1,  0x0C,  0x91,  0x01,  0x07,  0x7E,  0x54,  0x05,  0x52,  0x75,  0x25,  0x5F, 	/* 160D0 */
+	0x57,  0x27,  0x5A,  0x55,  0x65,  0x52,  0x59,  0x2B,  0x16,  0x93,  0x02,  0x87,  0x28,  0x5E,  0xE5,  0x28, 	/* 160E0 */
+	0x72,  0x85,  0xEE,  0x52,  0x87,  0x28,  0x5E,  0xE5,  0x48,  0x54,  0x8B,  0x88,  0x94,  0x01,  0x07,  0xFE, 	/* 160F0 */
+	0x5A,  0xA5,  0xAA,  0x72,  0x85,  0x4E,  0x58,  0x07,  0x7C,  0x51,  0x05,  0x10,  0x51,  0x0B,  0xFE,  0x95, 	/* 16100 */
+	0x01,  0x0E,  0x10,  0xBF,  0xEB,  0x02,  0xEE,  0xEA,  0xAA,  0xAA,  0xAF,  0x6E,  0xA2,  0x8A,  0x48,  0xA8, 	/* 16110 */
+	0xAB,  0x06,  0x9F,  0x01,  0x07,  0xFE,  0x58,  0x25,  0xFE,  0x71,  0x05,  0x2C,  0x5F,  0xA7,  0x10,  0x57, 	/* 16120 */
+	0xC5,  0x10,  0x51,  0x0B,  0xFE,  0xA5,  0x00,  0x07,  0x7C,  0x54,  0x45,  0x7C,  0x74,  0x45,  0x7C,  0x55, 	/* 16130 */
+	0x07,  0x7E,  0x59,  0x05,  0x7C,  0x51,  0x0B,  0xFE,  0xA6,  0x05,  0x47,  0x54,  0x5A,  0x85,  0x54,  0x75, 	/* 16140 */
+	0x45,  0x00,  0x57,  0xE7,  0x4A,  0x56,  0xA5,  0x5A,  0x56,  0x6B,  0x7E,  0xAB,  0x00,  0xC7,  0x70,  0x51, 	/* 16150 */
+	0x05,  0xFE,  0x75,  0x45,  0x7C,  0x55,  0x47,  0x7C,  0x51,  0x05,  0x7C,  0x51,  0x09,  0xFE,  0xAE,  0x00, 	/* 16160 */
+	0x07,  0x7E,  0x55,  0x25,  0x52,  0x77,  0xE5,  0x52,  0x57,  0xE7,  0x20,  0x53,  0x45,  0x6A,  0x5A,  0x0B, 	/* 16170 */
+	0x1E,  0xB0,  0x00,  0x0F,  0xFE,  0xA2,  0x8A,  0xFE,  0xEA,  0xAA,  0xFE,  0xA2,  0x0F,  0xFE,  0xA4,  0x8A, 	/* 16180 */
+	0xC8,  0xA3,  0x0A,  0xCC,  0xB1,  0x00,  0x87,  0x3E,  0x5C,  0xA5,  0x7F,  0x74,  0xA5,  0xBE,  0x5C,  0x87, 	/* 16190 */
+	0x7E,  0x5C,  0x85,  0x7E,  0x5A,  0x8B,  0x1F,  0xB4,  0x03,  0x07,  0x56,  0x55,  0x25,  0x52,  0x77,  0x65, 	/* 161A0 */
+	0x52,  0x55,  0x27,  0x76,  0x51,  0x05,  0x28,  0x54,  0x4B,  0x82,  0xB8,  0x00,  0x07,  0x7C,  0x54,  0x45, 	/* 161B0 */
+	0x7C,  0x74,  0x45,  0xFF,  0x54,  0x07,  0xFE,  0x52,  0xA5,  0xD2,  0x92,  0x2B,  0x4C,  0xB9,  0x04,  0x07, 	/* 161C0 */
+	0x7E,  0x5C,  0x45,  0x7C,  0x74,  0x45,  0x7C,  0x52,  0x07,  0x3C,  0x54,  0x85,  0xB0,  0x52,  0x8B,  0xC6, 	/* 161D0 */
+	0xBA,  0x01,  0x07,  0x7C,  0x54,  0x45,  0x7C,  0x74,  0x45,  0x7C,  0x51,  0x27,  0xDC,  0x53,  0x85,  0x54, 	/* 161E0 */
+	0x59,  0x29,  0x30,  0xBF,  0xE3,  0xCB,  0x24,  0xAB,  0xCA,  0x24,  0xE3,  0xCB,  0xA2,  0xAB,  0x4E,  0xA8, 	/* 161F0 */
+	0xAA,  0x8A,  0xF6,  0xB4,  0x0B,  0x3E,  0x80,  0x01,  0x07,  0xFE,  0x54,  0x45,  0x28,  0x7F,  0xE5,  0x92, 	/* 16200 */
+	0x5F,  0xE7,  0x20,  0x53,  0xC5,  0x24,  0x54,  0x4B,  0x98,  0x82,  0x22,  0x0F,  0xBE,  0x25,  0x23,  0xAC, 	/* 16210 */
+	0x2E,  0x84,  0xA4,  0xB2,  0x23,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x84,  0x18,  0x83,  0x00,  0x07,  0x7C, 	/* 16220 */
+	0x55,  0x45,  0x54,  0x76,  0xC5,  0x7C,  0x50,  0x07,  0xFE,  0x5A,  0xA5,  0xAA,  0x5A,  0xAB,  0xFF,  0x88, 	/* 16230 */
+	0x0F,  0xE7,  0x00,  0x57,  0xC5,  0x44,  0x77,  0xC5,  0x00,  0x57,  0xE7,  0x5A,  0x56,  0xE5,  0x7E,  0x55, 	/* 16240 */
+	0x2B,  0x56,  0x8A,  0x01,  0x47,  0x7E,  0x51,  0x05,  0x7E,  0x75,  0x25,  0x7E,  0x55,  0x27,  0x04,  0x5F, 	/* 16250 */
+	0xF5,  0x44,  0x52,  0x4B,  0x0C,  0x8F,  0x04,  0x0F,  0xFE,  0x11,  0x01,  0xF0,  0x00,  0x0F,  0xFE,  0x91, 	/* 16260 */
+	0x23,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x82,  0x18,  0x93,  0x02,  0x07,  0x7E,  0x5C,  0x45,  0x7C,  0x74, 	/* 16270 */
+	0x45,  0x7E,  0x52,  0x07,  0x7E,  0x5A,  0xA5,  0x2A,  0x55,  0x2B,  0x0C,  0x95,  0x00,  0x07,  0x7E,  0x55, 	/* 16280 */
+	0x65,  0x7E,  0x75,  0x25,  0x56,  0x57,  0x67,  0x6A,  0x57,  0xA5,  0x4A,  0x55,  0x6B,  0x7E,  0x9A,  0x07, 	/* 16290 */
+	0x80,  0x40,  0x3F,  0xE2,  0x48,  0x3F,  0xE3,  0x22,  0x3F,  0xE2,  0x84,  0x2F,  0xC4,  0x84,  0x4F,  0xC8, 	/* 162A0 */
+	0x84,  0x9C,  0x02,  0x87,  0xFE,  0x52,  0x85,  0x7C,  0x74,  0x45,  0x7C,  0x54,  0x47,  0x7C,  0x51,  0x05, 	/* 162B0 */
+	0xFE,  0x52,  0x8B,  0x46,  0x9D,  0x71,  0x05,  0xFE,  0x53,  0x85,  0x54,  0x79,  0x25,  0x28,  0x5C,  0x67, 	/* 162C0 */
+	0x10,  0x5D,  0x65,  0x38,  0x55,  0x4B,  0xB2,  0xA0,  0x00,  0x07,  0xFE,  0x55,  0xA5,  0xB6,  0x7D,  0xA5, 	/* 162D0 */
+	0x36,  0x52,  0x87,  0x4C,  0x59,  0x35,  0x64,  0x51,  0x8B,  0x60,  0xA3,  0x01,  0x07,  0xFE,  0x5A,  0xA5, 	/* 162E0 */
+	0x4E,  0x78,  0x05,  0x7E,  0x52,  0xC7,  0xFA,  0x51,  0x05,  0x7C,  0x51,  0x0B,  0xFE,  0xA4,  0x07,  0xC7, 	/* 162F0 */
+	0x10,  0x5F,  0xE5,  0x92,  0x7B,  0xA5,  0x92,  0x50,  0x07,  0x7C,  0x50,  0x45,  0xFE,  0x50,  0x4B,  0x7C, 	/* 16300 */
+	0xA8,  0x04,  0x4E,  0xE4,  0xA4,  0x8B,  0xF2,  0xE0,  0x2A,  0xE4,  0xAA,  0x8E,  0xE2,  0xB1,  0x2A,  0xA4, 	/* 16310 */
+	0xAE,  0x8B,  0x10,  0xA9,  0x00,  0x87,  0x0A,  0x5F,  0xE5,  0x08,  0x7F,  0x85,  0x08,  0x57,  0x87,  0x58, 	/* 16320 */
+	0x57,  0x45,  0x54,  0x57,  0x2B,  0x89,  0xB0,  0x00,  0xC7,  0x72,  0x55,  0x45,  0xFE,  0x73,  0x85,  0x54, 	/* 16330 */
+	0x59,  0x27,  0x7F,  0x55,  0x25,  0x7E,  0x55,  0x2B,  0x7E,  0xB3,  0x02,  0x87,  0xFE,  0x51,  0x05,  0x7C, 	/* 16340 */
+	0x71,  0x05,  0xFE,  0x55,  0x47,  0xFE,  0x50,  0x05,  0x7C,  0x94,  0x4B,  0x7C,  0xB5,  0x04,  0x47,  0xFE, 	/* 16350 */
+	0x54,  0x45,  0x10,  0x77,  0xE5,  0x24,  0x55,  0xA7,  0x10,  0x5F,  0xF5,  0x10,  0x51,  0x0B,  0x10,  0xB8, 	/* 16360 */
+	0x00,  0x87,  0xBE,  0x55,  0x05,  0x1E,  0x7A,  0x45,  0x5F,  0x5D,  0x27,  0x5E,  0x55,  0x25,  0x56,  0x5B, 	/* 16370 */
+	0x0B,  0x0F,  0xBA,  0x02,  0x07,  0xFE,  0x52,  0x85,  0x7E,  0x7C,  0x85,  0x7E,  0x54,  0x85,  0xFE,  0x48, 	/* 16380 */
+	0x44,  0xFC,  0x88,  0x40,  0x8C,  0xBD,  0x03,  0xC7,  0x48,  0x5F,  0xE5,  0x58,  0x76,  0xE5,  0x5C,  0x54, 	/* 16390 */
+	0x07,  0x7E,  0x54,  0x05,  0xBC,  0x52,  0x4B,  0x3C,  0xBE,  0x01,  0x07,  0x28,  0x57,  0xC5,  0x83,  0x7F, 	/* 163A0 */
+	0xE5,  0xBA,  0x59,  0x27,  0xFE,  0x54,  0x45,  0x7C,  0x54,  0x4B,  0x7C,  0xBF,  0x02,  0x8E,  0xFE,  0xAA, 	/* 163B0 */
+	0xAA,  0xFE,  0xEA,  0xAA,  0xFE,  0xA8,  0x0E,  0xFE,  0xAB,  0x2A,  0xAC,  0xB3,  0x4A,  0xE2,  0x80,  0x7D, 	/* 163C0 */
+	0xC4,  0x55,  0x7F,  0x75,  0x7C,  0x7D,  0x49,  0x48,  0x23,  0x63,  0xFC,  0x20,  0x43,  0xFC,  0x20,  0x42, 	/* 163D0 */
+	0x0C,  0x82,  0x7C,  0x84,  0x7E,  0x7D,  0x44,  0x3E,  0x7C,  0x8A,  0x7E,  0x3C,  0x83,  0xFC,  0x20,  0x43, 	/* 163E0 */
+	0xFC,  0x20,  0x42,  0x0C,  0x86,  0x01,  0x0E,  0xFC,  0xA4,  0x8B,  0xFE,  0xE8,  0x4A,  0xFC,  0xA8,  0x4E, 	/* 163F0 */
+	0xFC,  0xA5,  0x0A,  0xD4,  0xB4,  0xAA,  0x3A,  0x88,  0x02,  0x87,  0xFE,  0x52,  0x85,  0x7C,  0x74,  0x45, 	/* 16400 */
+	0x7C,  0x54,  0x47,  0x7E,  0x55,  0x25,  0xEA,  0x57,  0xAB,  0x0C,  0x89,  0x01,  0x07,  0x10,  0x52,  0x85, 	/* 16410 */
+	0x7C,  0x78,  0x25,  0xEF,  0x5A,  0xA7,  0xEE,  0x54,  0x45,  0x44,  0x5A,  0xAB,  0x12,  0x8D,  0x01,  0x07, 	/* 16420 */
+	0xFE,  0x52,  0x85,  0xD6,  0x75,  0x45,  0x52,  0x5B,  0x47,  0x44,  0x57,  0xC5,  0x44,  0x57,  0xCB,  0x84, 	/* 16430 */
+	0x91,  0x07,  0xC7,  0x10,  0x5F,  0xE5,  0x92,  0x7B,  0xA5,  0x00,  0x5F,  0xE7,  0x20,  0x5F,  0xE5,  0xAA, 	/* 16440 */
+	0x5A,  0xAB,  0x86,  0x93,  0x02,  0x47,  0xFF,  0x52,  0x45,  0x04,  0x77,  0xF5,  0x74,  0x54,  0x57,  0x76, 	/* 16450 */
+	0x55,  0x45,  0xF6,  0x5C,  0xBB,  0x71,  0x98,  0x02,  0xA7,  0x54,  0x52,  0xA5,  0x7E,  0x76,  0xA5,  0x52, 	/* 16460 */
+	0x56,  0xA7,  0x7E,  0x55,  0xA5,  0x76,  0x55,  0xAB,  0x91,  0x99,  0x04,  0x87,  0xFE,  0x54,  0x85,  0x30, 	/* 16470 */
+	0x74,  0x85,  0x7A,  0x5E,  0xC7,  0x58,  0x58,  0x65,  0x54,  0x56,  0xAB,  0xAA,  0x9A,  0x01,  0xC7,  0x10, 	/* 16480 */
+	0x57,  0xE5,  0x50,  0x75,  0xE5,  0x7E,  0x56,  0xA7,  0x7E,  0x56,  0xA5,  0xBE,  0x5A,  0xAB,  0x7F,  0x9F, 	/* 16490 */
+	0x04,  0x87,  0xFE,  0x54,  0x85,  0x04,  0x77,  0xE5,  0x44,  0x5F,  0xC7,  0x56,  0x5F,  0x65,  0x74,  0x5D, 	/* 164A0 */
+	0xAB,  0x71,  0xA0,  0x44,  0x8A,  0xF4,  0x50,  0xAF,  0xFE,  0x6B,  0xCA,  0xEA,  0x7F,  0xC4,  0x44,  0x5B, 	/* 164B0 */
+	0x44,  0x44,  0x5B,  0x44,  0x0C,  0xA3,  0x00,  0x07,  0xFE,  0x44,  0x04,  0x40,  0x7F,  0xC4,  0x04,  0x40, 	/* 164C0 */
+	0x47,  0xFC,  0x44,  0x04,  0x40,  0x44,  0x07,  0xFE,  0xA5,  0x00,  0x8F,  0xC8,  0x90,  0x89,  0x08,  0xFC, 	/* 164D0 */
+	0x88,  0x48,  0xFC,  0x89,  0x14,  0x91,  0x49,  0x14,  0xFE,  0x20,  0x41,  0xA7,  0x00,  0xC0,  0x0A,  0xBF, 	/* 164E0 */
+	0xEA,  0x08,  0xEF,  0xA2,  0xAA,  0xEF,  0xAA,  0x94,  0xAF,  0x42,  0xAA,  0x4F,  0x38,  0x21,  0xA8,  0x04, 	/* 164F0 */
+	0x0F,  0x40,  0xA7,  0xEA,  0x80,  0xF7,  0xC9,  0x44,  0x97,  0xCF,  0x00,  0xAE,  0xEA,  0xAA,  0xFA,  0xA0, 	/* 16500 */
+	0xEE,  0xAA,  0x04,  0x00,  0x80,  0x3F,  0x82,  0x08,  0x20,  0x83,  0xF8,  0x20,  0x82,  0x08,  0x3F,  0x82, 	/* 16510 */
+	0x08,  0x20,  0x83,  0xF8,  0xAD,  0x08,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83, 	/* 16520 */
+	0xF8,  0x04,  0x07,  0xFE,  0x19,  0x86,  0x06,  0xB3,  0x00,  0x0F,  0xFE,  0x04,  0x00,  0x90,  0x13,  0x87, 	/* 16530 */
+	0xC4,  0x04,  0x47,  0xFC,  0x04,  0x00,  0x40,  0x04,  0x0F,  0xFE,  0xB4,  0x02,  0x0F,  0xA0,  0x23,  0xE4, 	/* 16540 */
+	0xA4,  0xFC,  0x42,  0xA4,  0x22,  0x8F,  0x98,  0x21,  0x02,  0x28,  0x34,  0x4C,  0x82,  0xBA,  0x04,  0x07, 	/* 16550 */
+	0xFC,  0x04,  0x07,  0xFC,  0x20,  0x8F,  0xFE,  0x80,  0x27,  0xFC,  0x13,  0x03,  0xE8,  0x04,  0x0F,  0xFE, 	/* 16560 */
+	0xBB,  0x01,  0x0F,  0xFE,  0x21,  0x05,  0x7C,  0xFA,  0x82,  0x7E,  0x22,  0x4F,  0xFA,  0x29,  0x12,  0x7E, 	/* 16570 */
+	0x33,  0x4C,  0x52,  0xBC,  0x04,  0x00,  0x80,  0x33,  0xC2,  0x04,  0x20,  0x42,  0x04,  0x3B,  0xC2,  0x04, 	/* 16580 */
+	0x20,  0x42,  0x04,  0x3F,  0xC0,  0x00,  0xBE,  0x14,  0x06,  0x5C,  0x44,  0x44,  0x44,  0x75,  0xC4,  0x44, 	/* 16590 */
+	0x44,  0x47,  0x5C,  0x04,  0x00,  0xA0,  0x31,  0x8C,  0x06,  0x81,  0x0C,  0x03,  0x1C,  0x20,  0x43,  0xDC, 	/* 165A0 */
+	0x20,  0x42,  0x04,  0x3F,  0xC0,  0x90,  0xFF,  0xF0,  0x90,  0x11,  0x02,  0x10,  0x82,  0x04,  0x03,  0xF8, 	/* 165B0 */
+	0x04,  0x07,  0xFC,  0x0A,  0x07,  0xFE,  0x24,  0x85,  0xB4,  0x91,  0x21,  0xB0,  0x11,  0x01,  0xF0,  0x85, 	/* 165C0 */
+	0x08,  0x07,  0x3C,  0x40,  0x47,  0xFC,  0x24,  0x83,  0xF8,  0x24,  0x83,  0xF8,  0x04,  0x0F,  0xFE,  0x18, 	/* 165D0 */
+	0x26,  0x0C,  0x87,  0x18,  0x06,  0xEC,  0x48,  0x46,  0x9C,  0x4E,  0x47,  0x2C,  0x4A,  0x44,  0xA4,  0xFF, 	/* 165E0 */
+	0xE1,  0x10,  0x20,  0xCC,  0x02,  0x88,  0x10,  0x06,  0xFC,  0x4A,  0x47,  0xFC,  0x4A,  0x44,  0xE4,  0x7B, 	/* 165F0 */
+	0xC4,  0xE4,  0xFF,  0xE0,  0x90,  0x10,  0x86,  0x04,  0x89,  0x18,  0x06,  0xEC,  0x48,  0x46,  0xEC,  0x4A, 	/* 16600 */
+	0x4F,  0xFE,  0x15,  0x02,  0x48,  0xDF,  0x60,  0x40,  0x3F,  0x80,  0x40,  0x8A,  0x11,  0x0F,  0xFE,  0x11, 	/* 16610 */
+	0x03,  0xFE,  0x62,  0x0B,  0xFC,  0x22,  0x03,  0xFE,  0x0C,  0x03,  0x1C,  0x20,  0x43,  0xFC,  0x8C,  0x01, 	/* 16620 */
+	0x87,  0xE0,  0x04,  0x00,  0x40,  0xFF,  0xE0,  0x40,  0x04,  0x03,  0xF8,  0x20,  0x82,  0x08,  0x20,  0x83, 	/* 16630 */
+	0xF8,  0x8D,  0x04,  0x00,  0xA0,  0x11,  0x03,  0xF8,  0xC4,  0x60,  0x40,  0x7F,  0xC0,  0x40,  0x3F,  0x82, 	/* 16640 */
+	0x08,  0x20,  0x83,  0xF8,  0x8E,  0x04,  0x00,  0xA0,  0x31,  0x8C,  0x46,  0x3F,  0x80,  0x40,  0x7F,  0xC0, 	/* 16650 */
+	0x00,  0x3F,  0x82,  0x08,  0x20,  0x83,  0xF8,  0x90,  0x18,  0x6E,  0x38,  0x22,  0x82,  0x28,  0xFE,  0x82, 	/* 16660 */
+	0x3E,  0x22,  0x87,  0xA8,  0x4A,  0x44,  0xA6,  0x7B,  0x20,  0x62,  0x92,  0x10,  0x01,  0x3E,  0x29,  0x44, 	/* 16670 */
+	0x48,  0xBB,  0xF1,  0x0A,  0x7C,  0xC1,  0x08,  0x78,  0x84,  0x88,  0x48,  0x87,  0x98,  0x96,  0x20,  0xC3, 	/* 16680 */
+	0x0A,  0x4B,  0xEF,  0x88,  0x23,  0xE2,  0x2A,  0xFF,  0xE2,  0x2A,  0x7B,  0xE4,  0xAA,  0x4A,  0xA7,  0xA6, 	/* 16690 */
+	0x97,  0x21,  0x43,  0x12,  0x7F,  0xEA,  0x90,  0xFF,  0xE2,  0x52,  0xFF,  0xE0,  0x52,  0x77,  0xE5,  0x52, 	/* 166A0 */
+	0x55,  0x27,  0x56,  0x98,  0x21,  0x02,  0xFE,  0x58,  0x28,  0xBC,  0xFA,  0x42,  0x24,  0xFB,  0xC2,  0x20, 	/* 166B0 */
+	0x7B,  0xE4,  0xA2,  0x4A,  0x27,  0xBE,  0x9B,  0x20,  0x82,  0x08,  0x38,  0x82,  0xBE,  0x4A,  0x87,  0xA8, 	/* 166C0 */
+	0x8A,  0x81,  0x7E,  0x10,  0x82,  0x08,  0x40,  0x88,  0x08,  0x9C,  0x03,  0xC7,  0xC8,  0x28,  0x81,  0x50, 	/* 166D0 */
+	0xFF,  0xE8,  0x0A,  0x3B,  0xE4,  0xA8,  0xAA,  0x81,  0xFE,  0x20,  0x8C,  0x08,  0x9E,  0x20,  0x03,  0xFC, 	/* 166E0 */
+	0x6A,  0x8B,  0xFE,  0x2A,  0x8F,  0xFE,  0x20,  0x83,  0xBE,  0x4A,  0x8B,  0x7E,  0x20,  0x8C,  0x08,  0x9F, 	/* 166F0 */
+	0x04,  0x01,  0xF8,  0x10,  0x81,  0x48,  0x12,  0x8F,  0xFE,  0x10,  0x81,  0x48,  0x22,  0x82,  0x28,  0x40, 	/* 16700 */
+	0x88,  0x18,  0xA9,  0x21,  0xC7,  0x84,  0x49,  0x46,  0x94,  0x5A,  0x24,  0xAA,  0xFC,  0x94,  0x88,  0x69, 	/* 16710 */
+	0x45,  0x94,  0x4B,  0xA9,  0xE2,  0xAA,  0x11,  0x02,  0x10,  0x7F,  0xE5,  0x00,  0x73,  0x85,  0x28,  0xFE, 	/* 16720 */
+	0x85,  0x28,  0x74,  0x85,  0x4A,  0x58,  0xAB,  0x06,  0xAB,  0x20,  0x87,  0x88,  0x4F,  0xE6,  0x90,  0x59, 	/* 16730 */
+	0x04,  0x9E,  0xFD,  0x24,  0x92,  0x6A,  0x25,  0xA2,  0x4C,  0x29,  0x8C,  0xAC,  0x23,  0x87,  0xA8,  0x4A, 	/* 16740 */
+	0x86,  0xAA,  0x5C,  0xE4,  0x80,  0xFF,  0xC4,  0x84,  0x6A,  0x85,  0x90,  0x4A,  0x89,  0xC6,  0xAE,  0x20, 	/* 16750 */
+	0x07,  0xBE,  0x48,  0x06,  0xBE,  0x5A,  0x24,  0xA2,  0xFF,  0xE4,  0xA0,  0x6A,  0x05,  0xC0,  0x4C,  0x09, 	/* 16760 */
+	0x80,  0xB3,  0x20,  0x87,  0x88,  0x48,  0x86,  0xBE,  0x5A,  0xA4,  0xAA,  0xFE,  0xA4,  0xBE,  0x6A,  0xA5, 	/* 16770 */
+	0xAA,  0x4A,  0xA9,  0xBE,  0xB5,  0x20,  0x87,  0x88,  0x4F,  0xE6,  0xC2,  0x5C,  0x24,  0xA0,  0xFE,  0xC4, 	/* 16780 */
+	0xB0,  0x6A,  0x05,  0xA2,  0x4A,  0x29,  0x9E,  0xB6,  0x20,  0x87,  0x90,  0x4B,  0xE6,  0xA2,  0x5A,  0x24, 	/* 16790 */
+	0xA2,  0xFB,  0xE4,  0xA2,  0x6A,  0x25,  0xA2,  0x4A,  0x29,  0xBE,  0xB7,  0x20,  0x87,  0x88,  0x4F,  0xE6, 	/* 167A0 */
+	0x90,  0x59,  0x44,  0xE4,  0xFA,  0x84,  0x90,  0x69,  0x45,  0xA4,  0x4F,  0xA9,  0x82,  0xB8,  0x20,  0x07, 	/* 167B0 */
+	0xFE,  0x48,  0x46,  0x84,  0x5B,  0xC4,  0xAC,  0xFE,  0xC4,  0xAC,  0x6B,  0xC5,  0x84,  0x48,  0x49,  0x8C, 	/* 167C0 */
+	0xB9,  0x22,  0x87,  0xA8,  0x4A,  0x86,  0xA4,  0x5C,  0x24,  0x80,  0xFF,  0xC4,  0xA4,  0x6A,  0x45,  0xA4, 	/* 167D0 */
+	0x4A,  0x49,  0xBC,  0x80,  0x20,  0x67,  0xBC,  0x4A,  0xA6,  0xCA,  0x5B,  0xC4,  0x84,  0xFC,  0x84,  0xBE, 	/* 167E0 */
+	0x68,  0x85,  0x88,  0x48,  0x89,  0x98,  0x87,  0x20,  0x22,  0xFC,  0x72,  0x85,  0x28,  0x74,  0x85,  0xFE, 	/* 167F0 */
+	0xF2,  0x85,  0xA8,  0x7A,  0x85,  0x5E,  0x56,  0x0B,  0x9F,  0x98,  0x21,  0x87,  0xAE,  0x4A,  0xA6,  0xBE, 	/* 16800 */
+	0x5A,  0xA4,  0xBE,  0xF8,  0x84,  0xFE,  0x6A,  0x45,  0x98,  0x49,  0x49,  0xE2,  0x99,  0x20,  0x87,  0x94, 	/* 16810 */
+	0x4A,  0xA6,  0xFF,  0x5A,  0x24,  0xBE,  0xFE,  0x24,  0xBE,  0x6A,  0x05,  0xDE,  0x4D,  0x29,  0x9E,  0x9A, 	/* 16820 */
+	0x22,  0x87,  0xFE,  0x4A,  0x86,  0xFE,  0x5A,  0xA4,  0xFE,  0xFA,  0xA4,  0xFE,  0x6A,  0x45,  0xBC,  0x4A, 	/* 16830 */
+	0x49,  0xBC,  0x9D,  0x27,  0xE7,  0x90,  0x4F,  0xE6,  0x92,  0x5D,  0xA4,  0xB6,  0xF8,  0x04,  0xBE,  0x68, 	/* 16840 */
+	0x25,  0xFF,  0x48,  0x29,  0xBE,  0x9F,  0x21,  0x07,  0xFC,  0x4A,  0x86,  0xFE,  0x5D,  0x44,  0xFC,  0xFD, 	/* 16850 */
+	0x44,  0xFC,  0x69,  0x05,  0xFC,  0x49,  0x09,  0xFE,  0xA2,  0x21,  0x07,  0xFE,  0x4B,  0x46,  0xB4,  0x5D, 	/* 16860 */
+	0xA4,  0xFE,  0xF9,  0x04,  0xFE,  0x6D,  0xA5,  0xDA,  0x4C,  0x29,  0xFE,  0xA4,  0x22,  0x87,  0xFE,  0x49, 	/* 16870 */
+	0x06,  0xFC,  0x59,  0x04,  0xFE,  0xFA,  0xA4,  0xFE,  0x6A,  0xC5,  0xAA,  0x4F,  0x69,  0xA2,  0xA6,  0x4E, 	/* 16880 */
+	0x8E,  0x8E,  0xAE,  0x8E,  0xB0,  0xAE,  0x0F,  0x8E,  0xAE,  0x0E,  0x00,  0xAF,  0xCA,  0x54,  0xA5,  0x4A, 	/* 16890 */
+	0xFE,  0xA8,  0x22,  0x47,  0xFE,  0x4A,  0x46,  0xFE,  0x5C,  0x24,  0xBE,  0xFE,  0xA4,  0x9A,  0x6E,  0xC5, 	/* 168A0 */
+	0x9A,  0x4E,  0x99,  0x90,  0xAA,  0x21,  0xC7,  0xA8,  0x4F,  0xE6,  0xAA,  0x5B,  0xE4,  0xAA,  0xFB,  0xE4, 	/* 168B0 */
+	0xAA,  0x6D,  0x55,  0xBE,  0x4A,  0x29,  0xBE,  0xAB,  0x41,  0xCF,  0x10,  0x97,  0xED,  0x56,  0xB7,  0x89, 	/* 168C0 */
+	0x5E,  0xFF,  0xE9,  0x6A,  0xD7,  0xEB,  0x6A,  0x9A,  0xAB,  0x7F,  0xAE,  0x00,  0x03,  0xF0,  0x21,  0x03, 	/* 168D0 */
+	0xF0,  0x21,  0x02,  0x10,  0x3F,  0x02,  0x88,  0x25,  0x02,  0x20,  0x39,  0x0E,  0x0C,  0xAF,  0x08,  0x03, 	/* 168E0 */
+	0xF0,  0x21,  0x02,  0x10,  0x3F,  0x02,  0x10,  0x3F,  0x02,  0x08,  0x29,  0x02,  0x60,  0x39,  0x0E,  0x0C, 	/* 168F0 */
+	0xB1,  0x50,  0x0F,  0xBC,  0x52,  0x4F,  0xBC,  0xAA,  0x4F,  0xBC,  0x23,  0x2F,  0xAC,  0x22,  0x8F,  0xA4, 	/* 16900 */
+	0x53,  0xA8,  0x61,  0xB2,  0x10,  0x01,  0xF0,  0x22,  0x0C,  0x40,  0x7F,  0x84,  0x88,  0x48,  0x87,  0xF8, 	/* 16910 */
+	0x40,  0x04,  0x04,  0x40,  0x43,  0xFC,  0xB6,  0x28,  0x8F,  0xEE,  0xAB,  0x4F,  0xFE,  0xAA,  0xAF,  0xEA, 	/* 16920 */
+	0x7B,  0xE4,  0xA0,  0x7A,  0x05,  0x22,  0x3E,  0x2E,  0x1E,  0xB7,  0xA8,  0x8F,  0x9E,  0xAA,  0x4F,  0xC8, 	/* 16930 */
+	0x03,  0xEF,  0xEA,  0x7A,  0xA4,  0xBE,  0x7A,  0x04,  0xA2,  0x2E,  0x2F,  0x1E,  0xB8,  0x20,  0x82,  0x08, 	/* 16940 */
+	0x20,  0x8A,  0xAA,  0xAA,  0xAA,  0xAA,  0xAA,  0xAF,  0xBE,  0x20,  0x82,  0x08,  0x40,  0x88,  0x08,  0xBE, 	/* 16950 */
+	0x11,  0x0F,  0xFE,  0x11,  0x00,  0x00,  0x21,  0x02,  0x10,  0x12,  0x00,  0xA0,  0x04,  0x00,  0xA0,  0x31, 	/* 16960 */
+	0x8C,  0x06,  0x8B,  0x11,  0x0F,  0xFE,  0x11,  0x03,  0xF8,  0x04,  0x00,  0x40,  0xFF,  0xE0,  0x40,  0x04, 	/* 16970 */
+	0x00,  0x40,  0x04,  0x00,  0xC0,  0x8D,  0x11,  0x0F,  0xFE,  0x11,  0x01,  0x00,  0x3F,  0xC2,  0x04,  0x48, 	/* 16980 */
+	0x48,  0x44,  0x04,  0x40,  0x04,  0x00,  0x40,  0x18,  0x92,  0x11,  0x0F,  0xFE,  0x11,  0x01,  0x50,  0x04, 	/* 16990 */
+	0x0F,  0xFE,  0x20,  0x02,  0x00,  0x20,  0x02,  0x00,  0x20,  0x01,  0xFC,  0x99,  0x11,  0x0F,  0xFE,  0x11, 	/* 169A0 */
+	0x01,  0x50,  0x04,  0x07,  0xFC,  0x04,  0x00,  0x40,  0xFF,  0xE0,  0xA0,  0x31,  0x8C,  0x06,  0x9D,  0x11, 	/* 169B0 */
+	0x0F,  0xFE,  0x11,  0x01,  0x50,  0x04,  0x07,  0xFC,  0x00,  0x80,  0x30,  0x2C,  0x03,  0x00,  0x4C,  0x08, 	/* 169C0 */
+	0x3E,  0x9F,  0x11,  0x0F,  0xFE,  0x11,  0x01,  0xF0,  0x11,  0x41,  0x14,  0x20,  0xC7,  0xF0,  0x11,  0x00, 	/* 169D0 */
+	0xE0,  0x1B,  0x0E,  0x0E,  0xA5,  0x10,  0x8F,  0xFE,  0x11,  0x01,  0x50,  0x0A,  0x01,  0x10,  0x29,  0x8C, 	/* 169E0 */
+	0x96,  0x09,  0x01,  0x10,  0x11,  0x02,  0x10,  0xA6,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xFC,  0x00,  0x03, 	/* 169F0 */
+	0xFC,  0x20,  0x43,  0xFC,  0x20,  0x04,  0x00,  0x40,  0x08,  0x00,  0xAB,  0x11,  0x0F,  0xFE,  0x11,  0x00, 	/* 16A00 */
+	0x00,  0x7F,  0xC0,  0x00,  0xFF,  0xE1,  0x20,  0x12,  0x01,  0x22,  0x22,  0x2C,  0x1E,  0xAC,  0x11,  0x0F, 	/* 16A10 */
+	0xFE,  0x11,  0x00,  0x00,  0x09,  0x01,  0x08,  0x20,  0x4F,  0xFA,  0x08,  0x80,  0x88,  0x10,  0x86,  0x30, 	/* 16A20 */
+	0xAD,  0x11,  0x0F,  0xFE,  0x11,  0x00,  0x00,  0x7F,  0xC4,  0x44,  0x44,  0x47,  0xFC,  0x40,  0x04,  0x02, 	/* 16A30 */
+	0x40,  0x23,  0xFE,  0xAF,  0x11,  0x0F,  0xFE,  0x11,  0x01,  0x10,  0x00,  0x01,  0x40,  0x52,  0x85,  0x24, 	/* 16A40 */
+	0x50,  0x29,  0x0A,  0x90,  0x80,  0xF8,  0xB1,  0x11,  0x01,  0x10,  0xFF,  0xE1,  0x90,  0x0A,  0x01,  0x22, 	/* 16A50 */
+	0x32,  0xC5,  0x30,  0x92,  0x01,  0x22,  0x12,  0x21,  0x1E,  0xB3,  0x11,  0x0F,  0xFE,  0x11,  0x00,  0x40, 	/* 16A60 */
+	0xFF,  0xE0,  0x80,  0x08,  0x00,  0xF8,  0x08,  0x81,  0x08,  0x20,  0x8C,  0x30,  0xB8,  0x11,  0x0F,  0xFE, 	/* 16A70 */
+	0x11,  0x01,  0x10,  0x7F,  0xC0,  0x00,  0xFF,  0xE0,  0x40,  0x09,  0x01,  0x38,  0x7C,  0x40,  0x04,  0xB9, 	/* 16A80 */
+	0x11,  0x0F,  0xFE,  0x11,  0x00,  0x1C,  0x3E,  0x02,  0x00,  0x3F,  0xE2,  0x20,  0x22,  0x04,  0x20,  0x42, 	/* 16A90 */
+	0x08,  0x20,  0xBB,  0x20,  0x03,  0xFE,  0x24,  0x26,  0x4A,  0xBF,  0xA2,  0x42,  0x3F,  0xE4,  0x42,  0xA4, 	/* 16AA0 */
+	0xA3,  0xFA,  0x08,  0x23,  0x0C,  0xBD,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xFE,  0x21,  0x02,  0x10,  0xFF, 	/* 16AB0 */
+	0xE0,  0x50,  0x09,  0x03,  0x10,  0xC1,  0x00,  0x30,  0x85,  0x11,  0x0F,  0xFE,  0x11,  0x00,  0x84,  0x0A, 	/* 16AC0 */
+	0x4C,  0xA4,  0x2A,  0x41,  0x24,  0x12,  0x42,  0xA4,  0x48,  0x48,  0x0C,  0x91,  0x11,  0x0F,  0xFE,  0x11, 	/* 16AD0 */
+	0x02,  0x00,  0x3B,  0xC2,  0xA4,  0x4A,  0x46,  0xA4,  0x9B,  0x81,  0x22,  0x22,  0x24,  0x1E,  0x92,  0x11, 	/* 16AE0 */
+	0x0F,  0xFE,  0x11,  0x00,  0x40,  0x3F,  0x82,  0x48,  0x3F,  0x82,  0x48,  0xFF,  0xE2,  0x08,  0x20,  0x82, 	/* 16AF0 */
+	0x18,  0x93,  0x11,  0x0F,  0xFE,  0x15,  0x00,  0xA0,  0x31,  0x8D,  0xF6,  0x00,  0x07,  0xFC,  0x04,  0x40, 	/* 16B00 */
+	0x44,  0x05,  0x80,  0x40,  0x94,  0x11,  0x0F,  0xFE,  0x11,  0x00,  0x40,  0x08,  0x81,  0x34,  0xFC,  0x20, 	/* 16B10 */
+	0x02,  0x3F,  0x82,  0x08,  0x20,  0x83,  0xF8,  0x97,  0x11,  0x0F,  0xFE,  0x11,  0x01,  0x10,  0x7F,  0xC4, 	/* 16B20 */
+	0x44,  0x44,  0x47,  0xFC,  0x44,  0x44,  0x44,  0x44,  0x47,  0xFC,  0x99,  0x11,  0x0F,  0xFE,  0x11,  0x01, 	/* 16B30 */
+	0x50,  0x04,  0x07,  0xFC,  0x00,  0x82,  0x08,  0x11,  0x00,  0x90,  0x0A,  0x0F,  0xFE,  0x9B,  0x11,  0x0F, 	/* 16B40 */
+	0xFE,  0x11,  0x00,  0x00,  0xFF,  0xE0,  0x08,  0x3E,  0x82,  0x28,  0x22,  0x83,  0xE8,  0x00,  0x80,  0x18, 	/* 16B50 */
+	0x9C,  0x11,  0x0F,  0xFE,  0x11,  0x03,  0xF8,  0x20,  0x82,  0x08,  0x3F,  0x82,  0x08,  0x3F,  0x82,  0x08, 	/* 16B60 */
+	0x20,  0x83,  0xF8,  0x9E,  0x11,  0x0F,  0xFE,  0x11,  0x02,  0x00,  0x3F,  0xC4,  0x04,  0x7E,  0x4A,  0x24, 	/* 16B70 */
+	0x3E,  0x82,  0x00,  0x20,  0x21,  0xFE,  0x9F,  0x11,  0x0F,  0xFE,  0x11,  0x01,  0x00,  0x3F,  0xE2,  0x02, 	/* 16B80 */
+	0x5E,  0x29,  0x22,  0x12,  0x21,  0xE2,  0x00,  0x20,  0x0C,  0xA1,  0x11,  0x0F,  0xFE,  0x11,  0x00,  0x00, 	/* 16B90 */
+	0x20,  0x82,  0x88,  0x24,  0x82,  0x48,  0x20,  0x82,  0x98,  0x32,  0x4C,  0xC2,  0xA3,  0x11,  0x0F,  0xFE, 	/* 16BA0 */
+	0x11,  0x00,  0x00,  0x7F,  0xC4,  0x00,  0x7F,  0x84,  0x08,  0x7F,  0x84,  0x00,  0x40,  0x07,  0xFC,  0xA5, 	/* 16BB0 */
+	0x11,  0x0F,  0xFE,  0x11,  0x00,  0x80,  0x08,  0x0F,  0xFE,  0x08,  0x01,  0xF8,  0x30,  0x85,  0x08,  0x90, 	/* 16BC0 */
+	0x81,  0xF8,  0xA6,  0x11,  0x0F,  0xFE,  0x11,  0x01,  0x50,  0x04,  0x0F,  0xFE,  0x04,  0x00,  0x40,  0x3F, 	/* 16BD0 */
+	0x82,  0x08,  0x20,  0x83,  0xF8,  0xA7,  0x11,  0x0F,  0xFE,  0x11,  0x00,  0x40,  0xFF,  0xE8,  0x02,  0xBF, 	/* 16BE0 */
+	0xA0,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0xC0,  0xAB,  0x11,  0x0F,  0xFE,  0x11,  0x01,  0x50,  0x07, 	/* 16BF0 */
+	0xC0,  0x40,  0x04,  0x03,  0xF8,  0x20,  0x82,  0x08,  0x20,  0x83,  0xF8,  0xB1,  0x11,  0x07,  0xFC,  0x15, 	/* 16C00 */
+	0x00,  0x40,  0x3F,  0x82,  0x48,  0x24,  0x8F,  0xFE,  0x04,  0x00,  0xA0,  0x31,  0x8C,  0x06,  0xB3,  0x11, 	/* 16C10 */
+	0x0F,  0xFE,  0x11,  0x00,  0xFC,  0x10,  0x86,  0x90,  0x06,  0x01,  0x98,  0xEC,  0x60,  0x10,  0x06,  0x01, 	/* 16C20 */
+	0x80,  0xB4,  0x11,  0x0F,  0xFE,  0x11,  0x00,  0x00,  0x3F,  0x82,  0x08,  0x3F,  0x82,  0x08,  0x3F,  0x82, 	/* 16C30 */
+	0x08,  0x20,  0x8F,  0xFE,  0xB9,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xFC,  0x05,  0x02,  0x48,  0x44,  0x4F, 	/* 16C40 */
+	0xFE,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0xBA,  0x11,  0x0F,  0xFE,  0x11,  0x03,  0xF8,  0x24,  0x82, 	/* 16C50 */
+	0x28,  0xFF,  0xE4,  0x88,  0x44,  0x87,  0xFC,  0x00,  0x80,  0x30,  0xBB,  0x11,  0x0F,  0xFE,  0x11,  0x01, 	/* 16C60 */
+	0x08,  0x20,  0x82,  0xFE,  0x60,  0x8A,  0x88,  0x24,  0x82,  0x48,  0x20,  0x82,  0x18,  0x82,  0x11,  0x0F, 	/* 16C70 */
+	0xFE,  0x11,  0x01,  0x58,  0x44,  0x47,  0xFE,  0x42,  0x04,  0x24,  0x41,  0x84,  0x2A,  0x44,  0x69,  0x82, 	/* 16C80 */
+	0x83,  0x11,  0x0F,  0xFE,  0x11,  0x01,  0x10,  0x47,  0xC2,  0x44,  0x84,  0x44,  0x58,  0x14,  0x02,  0x42, 	/* 16C90 */
+	0x24,  0x24,  0x3E,  0x84,  0x11,  0x0F,  0xFE,  0x11,  0x02,  0x10,  0x21,  0xEF,  0xD2,  0x25,  0x22,  0x52, 	/* 16CA0 */
+	0x25,  0x24,  0x52,  0x45,  0xE9,  0x80,  0x85,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xF8,  0x11,  0x00,  0xA0, 	/* 16CB0 */
+	0xFF,  0xE0,  0xC4,  0x14,  0x82,  0x40,  0xC4,  0x00,  0xC0,  0x86,  0x11,  0x0F,  0xFE,  0x11,  0x01,  0x80, 	/* 16CC0 */
+	0x63,  0xC4,  0x24,  0x4A,  0x44,  0xA4,  0x7A,  0x4C,  0xB8,  0x12,  0x02,  0x20,  0x89,  0x11,  0x0F,  0xFE, 	/* 16CD0 */
+	0x11,  0x01,  0x50,  0x04,  0x0F,  0xFE,  0x04,  0x07,  0xFC,  0x0E,  0x03,  0x58,  0xC4,  0x60,  0x40,  0x8E, 	/* 16CE0 */
+	0x11,  0x0F,  0xFE,  0x11,  0x07,  0xF8,  0x13,  0x00,  0xC0,  0x33,  0x0C,  0x4E,  0x3F,  0x80,  0x40,  0x04, 	/* 16CF0 */
+	0x0F,  0xFE,  0x96,  0x11,  0x0F,  0xFE,  0x11,  0x00,  0x80,  0x1F,  0x87,  0x10,  0x0E,  0x03,  0x18,  0xFF, 	/* 16D00 */
+	0xE2,  0x08,  0x20,  0x83,  0xF8,  0x97,  0x11,  0x0F,  0xFE,  0x11,  0x00,  0x40,  0x0F,  0x81,  0x08,  0x6B, 	/* 16D10 */
+	0x00,  0xC0,  0x3F,  0xCD,  0x04,  0x10,  0x41,  0xFC,  0x98,  0x11,  0x0F,  0xFE,  0x11,  0x03,  0xF8,  0x08, 	/* 16D20 */
+	0x81,  0x08,  0x23,  0x0F,  0xFE,  0x49,  0x24,  0x92,  0x4A,  0x2B,  0x4C,  0x9C,  0x11,  0x0F,  0xFE,  0x11, 	/* 16D30 */
+	0x0F,  0xFE,  0x0A,  0x07,  0xFC,  0x4A,  0x44,  0xA4,  0x51,  0xC6,  0x04,  0x40,  0x47,  0xFC,  0xA3,  0x11, 	/* 16D40 */
+	0x0F,  0xFE,  0x11,  0x00,  0xF8,  0x28,  0x82,  0xF8,  0x20,  0x03,  0xF8,  0x04,  0x8F,  0xFE,  0x19,  0x86, 	/* 16D50 */
+	0x06,  0xA8,  0x11,  0x0F,  0xFE,  0x11,  0x01,  0x50,  0x47,  0xE2,  0x52,  0x29,  0x40,  0x90,  0x11,  0x02, 	/* 16D60 */
+	0x28,  0xCC,  0x43,  0x02,  0xAB,  0x11,  0x0F,  0xFE,  0x11,  0x04,  0x10,  0x27,  0xE8,  0x40,  0x44,  0x00, 	/* 16D70 */
+	0x40,  0x14,  0x02,  0x40,  0x44,  0x04,  0x3C,  0xAF,  0x11,  0x0F,  0xFE,  0x11,  0x01,  0x28,  0x22,  0x43, 	/* 16D80 */
+	0xFE,  0x62,  0x0A,  0x20,  0x25,  0x02,  0x50,  0x28,  0x83,  0x04,  0xB1,  0x11,  0x0F,  0xFE,  0x11,  0x02, 	/* 16D90 */
+	0x40,  0x24,  0x07,  0xFC,  0x84,  0x0F,  0xFE,  0x0E,  0x03,  0x58,  0xC4,  0x60,  0x40,  0xB2,  0x11,  0x0F, 	/* 16DA0 */
+	0xFE,  0x11,  0x01,  0x08,  0x10,  0x86,  0x72,  0x25,  0x21,  0x8C,  0x10,  0x82,  0x94,  0xFF,  0xE0,  0x42, 	/* 16DB0 */
+	0xB4,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xFC,  0x40,  0x45,  0xF4,  0x51,  0x45,  0x14,  0x51,  0x45,  0xF4, 	/* 16DC0 */
+	0x40,  0x47,  0xFC,  0xB5,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xFC,  0x44,  0x44,  0x44,  0x7F,  0xC4,  0x44, 	/* 16DD0 */
+	0x4A,  0x45,  0x14,  0x60,  0xC7,  0xFC,  0xB6,  0x11,  0x0F,  0xFE,  0x15,  0x00,  0xA0,  0x31,  0x8C,  0x46, 	/* 16DE0 */
+	0x7F,  0xC0,  0x40,  0x15,  0x02,  0x48,  0xC4,  0x40,  0x40,  0xB8,  0x10,  0x8F,  0xFE,  0x10,  0x87,  0xFE, 	/* 16DF0 */
+	0x10,  0x81,  0xF8,  0x10,  0x81,  0xF8,  0x10,  0xE1,  0xF8,  0xE0,  0x80,  0x08,  0xB9,  0x11,  0x0F,  0xFE, 	/* 16E00 */
+	0x11,  0x05,  0x10,  0x4B,  0xCF,  0xE4,  0x4A,  0x44,  0xA4,  0xF2,  0x42,  0xA4,  0x47,  0xC8,  0x00,  0x80, 	/* 16E10 */
+	0x11,  0x0F,  0xFE,  0x11,  0x01,  0x00,  0x3F,  0xC2,  0x04,  0x5E,  0x49,  0x24,  0x1E,  0x41,  0x24,  0x1E, 	/* 16E20 */
+	0x40,  0x18,  0x85,  0x11,  0x0F,  0xFE,  0x15,  0x00,  0xA0,  0x11,  0x03,  0xF8,  0xC0,  0x63,  0xF8,  0x20, 	/* 16E30 */
+	0x82,  0x08,  0x20,  0x83,  0xF8,  0x89,  0x11,  0x0F,  0xFE,  0x11,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20, 	/* 16E40 */
+	0x83,  0xF8,  0x04,  0x0F,  0xFE,  0x04,  0x00,  0x40,  0x8A,  0x12,  0x0F,  0xFE,  0x12,  0x00,  0x04,  0xFE, 	/* 16E50 */
+	0x42,  0xA4,  0x2A,  0x4F,  0xE4,  0x2A,  0x44,  0xA4,  0x48,  0x48,  0x8C,  0x8F,  0x11,  0x0F,  0xFE,  0x11, 	/* 16E60 */
+	0x01,  0x0C,  0x17,  0x02,  0x10,  0x21,  0x07,  0xFE,  0xA1,  0x02,  0x10,  0x2F,  0xC2,  0x00,  0x90,  0x11, 	/* 16E70 */
+	0x0F,  0xFE,  0x11,  0x00,  0x80,  0xFF,  0xE1,  0x00,  0x2F,  0xC6,  0x08,  0xBF,  0xE2,  0x10,  0x21,  0x02, 	/* 16E80 */
+	0x30,  0x92,  0x11,  0x0F,  0xFE,  0x11,  0x00,  0x40,  0xFF,  0xE2,  0x00,  0x1F,  0xC2,  0x48,  0x24,  0x82, 	/* 16E90 */
+	0x4A,  0x44,  0xA8,  0x06,  0x98,  0x11,  0x0F,  0xFE,  0x11,  0x01,  0x10,  0x22,  0x0A,  0x20,  0x7F,  0xE2, 	/* 16EA0 */
+	0x20,  0x62,  0x0A,  0x20,  0x2F,  0xC2,  0x00,  0xB3,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xFC,  0x00,  0x03, 	/* 16EB0 */
+	0xF8,  0x20,  0x82,  0x08,  0x3F,  0x81,  0x10,  0x0A,  0x0F,  0xFE,  0xB5,  0x11,  0x0F,  0xFE,  0x11,  0x07, 	/* 16EC0 */
+	0xFC,  0x04,  0x43,  0xC4,  0x16,  0x46,  0x18,  0x14,  0x05,  0x24,  0x90,  0xA0,  0xF8,  0xB7,  0x11,  0x0F, 	/* 16ED0 */
+	0xFE,  0x09,  0x02,  0x00,  0x3F,  0xE4,  0x08,  0x5E,  0x8D,  0x28,  0x52,  0x85,  0xE8,  0x40,  0x84,  0x18, 	/* 16EE0 */
+	0xBB,  0x11,  0x0F,  0xFE,  0x11,  0x01,  0x10,  0xA1,  0x44,  0x54,  0xA5,  0x83,  0x50,  0x53,  0x09,  0x28, 	/* 16EF0 */
+	0x14,  0x46,  0x82,  0xBC,  0x11,  0x0F,  0xFF,  0x15,  0x00,  0xA0,  0x31,  0x8D,  0xF6,  0x04,  0x07,  0xFC, 	/* 16F00 */
+	0x05,  0x02,  0x4C,  0xC4,  0x20,  0xC0,  0x85,  0x11,  0x0F,  0xFE,  0x11,  0x02,  0x20,  0x3F,  0xC4,  0x08, 	/* 16F10 */
+	0x48,  0x8C,  0x88,  0x44,  0x84,  0x50,  0x45,  0x05,  0xFE,  0x87,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0x90, 	/* 16F20 */
+	0x4B,  0xE4,  0x92,  0x79,  0x24,  0x92,  0x79,  0x24,  0xE2,  0x72,  0x2C,  0x4C,  0x89,  0x11,  0x0F,  0xFE, 	/* 16F30 */
+	0x11,  0x01,  0x82,  0x71,  0x21,  0x12,  0xFD,  0x23,  0x12,  0x39,  0x25,  0x52,  0x90,  0x21,  0x06,  0x8A, 	/* 16F40 */
+	0x11,  0x0F,  0xFE,  0x11,  0x05,  0x10,  0x51,  0x07,  0x10,  0x1F,  0xEF,  0x10,  0x51,  0x05,  0x10,  0x51, 	/* 16F50 */
+	0x09,  0xFE,  0x8E,  0x11,  0x0F,  0xFE,  0x11,  0x04,  0x10,  0x25,  0x48,  0x54,  0x45,  0x20,  0x96,  0x33, 	/* 16F60 */
+	0x44,  0x08,  0x83,  0x08,  0xC0,  0x93,  0x11,  0x0F,  0xFE,  0x11,  0x02,  0x00,  0x3F,  0xE4,  0x00,  0x9F, 	/* 16F70 */
+	0x81,  0x28,  0xFF,  0xE2,  0x48,  0x7F,  0xC0,  0x30,  0x96,  0x11,  0x0F,  0xFE,  0x11,  0x0F,  0xFE,  0x24, 	/* 16F80 */
+	0x84,  0x90,  0xDB,  0x02,  0x48,  0x7F,  0xC0,  0x40,  0x04,  0x0F,  0xFE,  0x9A,  0x11,  0x0F,  0xFE,  0x11, 	/* 16F90 */
+	0x0F,  0x06,  0x17,  0x82,  0x10,  0x75,  0xC9,  0x50,  0x55,  0x02,  0x7E,  0x58,  0x08,  0x7F,  0x9E,  0x11, 	/* 16FA0 */
+	0x0F,  0xFE,  0x11,  0x00,  0x40,  0xFF,  0xE8,  0x02,  0x3F,  0x80,  0x00,  0xFF,  0xE0,  0xA0,  0x32,  0x2C, 	/* 16FB0 */
+	0x1E,  0x9F,  0x11,  0x0F,  0xFE,  0x15,  0x00,  0xA0,  0x11,  0x03,  0xF8,  0xC2,  0x60,  0x40,  0x3F,  0x82, 	/* 16FC0 */
+	0x08,  0x20,  0x83,  0xF8,  0xA0,  0x11,  0x0F,  0xFE,  0x11,  0x83,  0xF0,  0x04,  0x0F,  0xFE,  0x0E,  0x03, 	/* 16FD0 */
+	0x58,  0xDF,  0x60,  0x9C,  0x10,  0x46,  0x18,  0xA2,  0x11,  0x0F,  0xFE,  0x11,  0x00,  0x40,  0xFF,  0xE2, 	/* 16FE0 */
+	0x48,  0x24,  0x85,  0x54,  0x8A,  0x21,  0x10,  0x20,  0x8C,  0x06,  0xA8,  0x11,  0x0F,  0xFE,  0x15,  0x03, 	/* 16FF0 */
+	0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x24,  0x42,  0x28,  0x39,  0x86,  0x06,  0xAA,  0x11,  0x0F, 	/* 17000 */
+	0xFE,  0x11,  0x00,  0xD0,  0x71,  0x81,  0x14,  0xFF,  0xE1,  0x14,  0x1C,  0x8F,  0x1A,  0x16,  0x63,  0x02, 	/* 17010 */
+	0xAB,  0x11,  0x0F,  0xFE,  0x11,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x04,  0x0F,  0xFE, 	/* 17020 */
+	0x1B,  0x0E,  0x0E,  0xB1,  0x11,  0x0F,  0xFE,  0x15,  0x07,  0xFC,  0x24,  0x81,  0x50,  0xFF,  0xE0,  0xE0, 	/* 17030 */
+	0x15,  0x02,  0x48,  0xC4,  0x60,  0x40,  0xB5,  0x11,  0x0F,  0xFE,  0x15,  0x00,  0x80,  0x3F,  0x82,  0x48, 	/* 17040 */
+	0x24,  0x83,  0xF8,  0x0C,  0x01,  0x52,  0x24,  0xAC,  0x3E,  0xBD,  0x11,  0x0F,  0xFE,  0x11,  0x00,  0x40, 	/* 17050 */
+	0xFF,  0xE0,  0xA0,  0x31,  0x8D,  0x16,  0x11,  0x0F,  0xFC,  0x21,  0x04,  0x10,  0x81,  0x11,  0x0F,  0xFE, 	/* 17060 */
+	0x15,  0x07,  0xFC,  0x04,  0x03,  0xF8,  0x04,  0x0F,  0xFE,  0x24,  0x83,  0xF8,  0x20,  0x82,  0x18,  0x85, 	/* 17070 */
+	0x11,  0x0F,  0xFE,  0x15,  0x0F,  0xFE,  0x80,  0x2B,  0xF2,  0x21,  0x03,  0xF0,  0x20,  0x03,  0xF8,  0x20, 	/* 17080 */
+	0x83,  0xF8,  0x8A,  0x11,  0x0F,  0xFE,  0x11,  0x02,  0x00,  0x3F,  0xE4,  0x4A,  0x95,  0x27,  0xFE,  0x0E, 	/* 17090 */
+	0x21,  0x52,  0x64,  0xA0,  0x4C,  0x8C,  0x09,  0x0F,  0xFF,  0x09,  0x07,  0xFE,  0x43,  0x25,  0xC2,  0x44, 	/* 170A0 */
+	0x27,  0xFE,  0x4E,  0x27,  0x5A,  0x44,  0x27,  0xFE,  0x8E,  0x11,  0x0F,  0xFE,  0x11,  0x03,  0xF8,  0x20, 	/* 170B0 */
+	0x83,  0xF8,  0x20,  0x83,  0xF8,  0x22,  0x43,  0xB8,  0x22,  0x2F,  0x9E,  0x93,  0x11,  0x0F,  0xFE,  0x11, 	/* 170C0 */
+	0x03,  0xF8,  0x24,  0x83,  0xF8,  0x24,  0x8F,  0xFE,  0x0E,  0x03,  0x58,  0xC4,  0x60,  0x40,  0x96,  0x12, 	/* 170D0 */
+	0x0F,  0xFE,  0x12,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x87,  0xFC,  0x40,  0x47,  0xFC,  0x40,  0x47, 	/* 170E0 */
+	0xFC,  0x98,  0x11,  0x0F,  0xFE,  0x11,  0x02,  0x38,  0x24,  0x8F,  0x44,  0x29,  0x27,  0x10,  0xAA,  0x8A, 	/* 170F0 */
+	0x24,  0x2F,  0xC2,  0x04,  0x9C,  0x11,  0x0F,  0xFE,  0x13,  0x87,  0xC8,  0x24,  0x81,  0x50,  0x04,  0x0F, 	/* 17100 */
+	0xFE,  0x0E,  0x03,  0x58,  0xC4,  0x60,  0x40,  0x9F,  0x11,  0x0F,  0xFE,  0x11,  0x00,  0xF0,  0x71,  0x03, 	/* 17110 */
+	0xF8,  0x24,  0x83,  0xF8,  0x0B,  0x01,  0x28,  0x22,  0x2C,  0x1E,  0xA0,  0x11,  0x0F,  0xFE,  0x11,  0x05, 	/* 17120 */
+	0x10,  0x2F,  0xE8,  0x94,  0x49,  0x00,  0xFC,  0x2A,  0x45,  0x18,  0x52,  0x4A,  0x42,  0xA9,  0x11,  0x0F, 	/* 17130 */
+	0xFE,  0x15,  0x07,  0xFC,  0x11,  0x00,  0xA0,  0xFF,  0xE0,  0x00,  0x3F,  0x82,  0x08,  0x20,  0x83,  0xF8, 	/* 17140 */
+	0xAB,  0x11,  0x0F,  0xFE,  0x11,  0x0F,  0xFE,  0x04,  0x07,  0xFC,  0x44,  0x47,  0xFC,  0x04,  0x03,  0xF8, 	/* 17150 */
+	0x04,  0x0F,  0xFE,  0xAF,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xFC,  0x24,  0x8F,  0xFE,  0x24,  0x87,  0xFC, 	/* 17160 */
+	0x04,  0x0F,  0xFE,  0x04,  0x00,  0x40,  0xB0,  0x12,  0x0F,  0xFC,  0x12,  0x00,  0x0C,  0xFF,  0x81,  0xA8, 	/* 17170 */
+	0x2A,  0x83,  0xA8,  0xEA,  0x82,  0xA4,  0x2A,  0xC7,  0x7A,  0xB1,  0x11,  0x0F,  0xFE,  0x15,  0x07,  0xFC, 	/* 17180 */
+	0x04,  0x0F,  0xFE,  0x28,  0x8C,  0xF6,  0x19,  0x06,  0x60,  0x0D,  0x8F,  0x06,  0xB2,  0x11,  0x0F,  0xFE, 	/* 17190 */
+	0x11,  0x00,  0xA0,  0xFB,  0xE0,  0xA0,  0x7B,  0xC0,  0xA0,  0xF3,  0xE1,  0x20,  0x22,  0x0C,  0x20,  0xB4, 	/* 171A0 */
+	0x11,  0x0F,  0xFE,  0x15,  0x00,  0x80,  0xFF,  0xE3,  0xF8,  0x64,  0xCB,  0xFA,  0x24,  0x83,  0xF8,  0x04, 	/* 171B0 */
+	0x20,  0x3E,  0xB7,  0x11,  0x0F,  0xFE,  0x11,  0x03,  0xF8,  0xFF,  0xE0,  0x08,  0xFF,  0xE8,  0x42,  0xBF, 	/* 171C0 */
+	0xA2,  0x48,  0x25,  0x80,  0x40,  0xBB,  0x11,  0x0F,  0xFE,  0x11,  0x01,  0x10,  0xFF,  0xE1,  0x10,  0x3B, 	/* 171D0 */
+	0x83,  0x58,  0x55,  0x45,  0x92,  0x91,  0x01,  0x10,  0xBD,  0x11,  0x0F,  0xFE,  0x11,  0x02,  0x00,  0x3B, 	/* 171E0 */
+	0xC2,  0x04,  0xFA,  0x42,  0x14,  0x68,  0x86,  0x58,  0xA2,  0x42,  0xC2,  0x83,  0x11,  0x0F,  0xFE,  0x11, 	/* 171F0 */
+	0x00,  0x40,  0x7F,  0xC1,  0x10,  0x31,  0x84,  0xA4,  0xFF,  0xE0,  0x40,  0x04,  0x00,  0x40,  0x84,  0x09, 	/* 17200 */
+	0x07,  0xFE,  0x29,  0x03,  0xFE,  0x30,  0x25,  0xFA,  0x94,  0x23,  0xFA,  0x04,  0x22,  0x4A,  0x3F,  0xA0, 	/* 17210 */
+	0x0C,  0x87,  0x11,  0x0F,  0xFE,  0x11,  0x03,  0xF8,  0x20,  0x03,  0xF0,  0x20,  0x0F,  0xFE,  0x24,  0x82, 	/* 17220 */
+	0x30,  0x39,  0x86,  0x06,  0x8B,  0x11,  0x0F,  0xFE,  0x15,  0x07,  0xFE,  0x3F,  0xC0,  0x44,  0xFF,  0xF0, 	/* 17230 */
+	0x44,  0x7F,  0xE1,  0x88,  0x0F,  0x07,  0x0C,  0x8C,  0x11,  0x0F,  0xFF,  0x11,  0x00,  0x00,  0x7B,  0xE4, 	/* 17240 */
+	0xA2,  0x7B,  0xE4,  0xA2,  0x4B,  0xE7,  0xA2,  0x04,  0x20,  0x86,  0x8D,  0x11,  0x0F,  0xFF,  0x11,  0x04, 	/* 17250 */
+	0xFE,  0x25,  0x48,  0x54,  0x49,  0x21,  0xFF,  0x21,  0x04,  0x10,  0x81,  0x08,  0x10,  0x8E,  0x11,  0x0F, 	/* 17260 */
+	0xFE,  0x11,  0x07,  0xFC,  0x04,  0x0F,  0xFE,  0x35,  0x8C,  0x46,  0x7F,  0xC1,  0x10,  0x0F,  0x07,  0x8C, 	/* 17270 */
+	0x93,  0x11,  0x0F,  0xFE,  0x15,  0x0F,  0xFE,  0x80,  0x29,  0xF2,  0x11,  0x01,  0xF0,  0x11,  0x01,  0xF0, 	/* 17280 */
+	0x11,  0x0F,  0xFE,  0xA0,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xBC,  0x4A,  0x46,  0xB4,  0x5A,  0xC6,  0xB4, 	/* 17290 */
+	0x5A,  0xC4,  0xA4,  0x4A,  0x49,  0xCC,  0xA2,  0x11,  0x0F,  0xFE,  0x11,  0x04,  0x40,  0x27,  0xC8,  0x84, 	/* 172A0 */
+	0x5F,  0x40,  0x14,  0x2F,  0x84,  0x80,  0x88,  0x28,  0x7E,  0xA9,  0x11,  0x0F,  0xFE,  0x12,  0x0E,  0x10, 	/* 172B0 */
+	0x25,  0x2F,  0xD2,  0x25,  0x47,  0x10,  0x69,  0x0A,  0x28,  0x24,  0x43,  0x82,  0xAA,  0x11,  0x0F,  0xFE, 	/* 172C0 */
+	0x11,  0x01,  0x88,  0xE2,  0x82,  0x18,  0xFC,  0x87,  0x28,  0x68,  0xEA,  0x78,  0x20,  0x82,  0x08,  0xAC, 	/* 172D0 */
+	0x11,  0x0F,  0xFE,  0x24,  0x83,  0xF8,  0x24,  0x83,  0xF8,  0x04,  0x07,  0xFE,  0x45,  0x24,  0x7A,  0x78, 	/* 172E0 */
+	0xA4,  0x06,  0xB1,  0x11,  0x0F,  0xFE,  0x15,  0x0F,  0xFE,  0x80,  0x27,  0xFC,  0x20,  0x83,  0xF8,  0x20, 	/* 172F0 */
+	0x83,  0xF8,  0x00,  0x0F,  0xFE,  0xB5,  0x11,  0x0F,  0xFE,  0x11,  0x03,  0xF8,  0x20,  0x82,  0xF8,  0x28, 	/* 17300 */
+	0x8F,  0xFE,  0x9F,  0x29,  0x12,  0x9F,  0x28,  0x06,  0xB8,  0x11,  0x0F,  0xFE,  0x11,  0x01,  0x40,  0x65, 	/* 17310 */
+	0xC4,  0x44,  0x75,  0xC4,  0x44,  0x75,  0xC0,  0xA0,  0x31,  0x8C,  0x06,  0xBC,  0x11,  0x0F,  0xFE,  0x11, 	/* 17320 */
+	0x07,  0xBC,  0x4A,  0x47,  0xBC,  0x00,  0x0F,  0xFE,  0x08,  0x01,  0xF8,  0x20,  0x80,  0x30,  0xBD,  0x11, 	/* 17330 */
+	0x0F,  0xFE,  0x15,  0x05,  0x78,  0x24,  0x88,  0xB0,  0x43,  0x00,  0xC8,  0x3F,  0xE4,  0x88,  0x88,  0x88, 	/* 17340 */
+	0xF8,  0x86,  0x11,  0x0F,  0xFE,  0x11,  0x02,  0x7C,  0x24,  0x44,  0x7C,  0xC1,  0x05,  0xFE,  0x43,  0x84, 	/* 17350 */
+	0x54,  0x59,  0x24,  0x10,  0x89,  0x10,  0x8F,  0xFE,  0x11,  0x02,  0x50,  0xFF,  0xE2,  0x50,  0x3F,  0x80, 	/* 17360 */
+	0x40,  0xFF,  0xE3,  0x58,  0xC4,  0x60,  0x40,  0x8E,  0x11,  0x0F,  0xFE,  0x11,  0x02,  0x20,  0x3F,  0xC4, 	/* 17370 */
+	0x24,  0xBF,  0xE2,  0x24,  0x5F,  0xCC,  0x20,  0x5F,  0xE4,  0x20,  0x97,  0x11,  0x0F,  0xFE,  0x15,  0x07, 	/* 17380 */
+	0xF8,  0x06,  0x0F,  0xFE,  0x08,  0x01,  0xF8,  0x30,  0x8D,  0xF8,  0x10,  0x81,  0xF8,  0x9B,  0x11,  0x0F, 	/* 17390 */
+	0xFE,  0x11,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xFE,  0x33,  0x2D,  0xCA,  0x0F,  0xA0,  0x0C, 	/* 173A0 */
+	0xA1,  0x09,  0x0F,  0xFE,  0x29,  0x03,  0xFE,  0x44,  0xA7,  0xFA,  0x84,  0x23,  0xFA,  0x24,  0xA3,  0xFA, 	/* 173B0 */
+	0x24,  0xA2,  0x5C,  0xA2,  0x11,  0x0F,  0xFE,  0x11,  0x00,  0x40,  0xFF,  0xE0,  0xA0,  0x35,  0x8C,  0x26, 	/* 173C0 */
+	0x3F,  0x82,  0xA8,  0x2A,  0x8F,  0xFE,  0xA3,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xFC,  0x04,  0x0F,  0xFE, 	/* 173D0 */
+	0x24,  0x83,  0xF8,  0x24,  0x87,  0xFC,  0x04,  0x0F,  0xFE,  0xA6,  0x11,  0x0F,  0xFE,  0x15,  0x07,  0xF8, 	/* 173E0 */
+	0x08,  0x8F,  0xFE,  0x10,  0x81,  0xF8,  0x3F,  0xC2,  0x40,  0xFF,  0xE0,  0x40,  0xA9,  0x11,  0x0F,  0xFE, 	/* 173F0 */
+	0x11,  0x02,  0x00,  0x47,  0xCF,  0x54,  0x95,  0x4F,  0x7C,  0x94,  0x09,  0x40,  0xF4,  0x20,  0x3E,  0xAB, 	/* 17400 */
+	0x11,  0x0F,  0xFE,  0x11,  0x02,  0x00,  0x23,  0xCF,  0xE4,  0x23,  0xC7,  0xA4,  0x4B,  0xC4,  0xA4,  0x7C, 	/* 17410 */
+	0x40,  0x8C,  0xAC,  0x11,  0x0F,  0xFE,  0x11,  0x0F,  0xFE,  0x22,  0x0F,  0xBC,  0x2A,  0x2F,  0x3E,  0x11, 	/* 17420 */
+	0x0F,  0xFE,  0x11,  0x06,  0x10,  0xAD,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xBC,  0x48,  0x47,  0xBC,  0x40, 	/* 17430 */
+	0x07,  0xBE,  0x41,  0x27,  0x8C,  0x41,  0x44,  0x62,  0xAE,  0x11,  0x0F,  0xFE,  0x11,  0x03,  0x38,  0x42, 	/* 17440 */
+	0x87,  0x2A,  0x44,  0x67,  0xBC,  0x42,  0x47,  0x98,  0xC3,  0x44,  0xC2,  0xAF,  0x11,  0x0F,  0xFE,  0x11, 	/* 17450 */
+	0x02,  0x10,  0x29,  0xED,  0x22,  0x2A,  0x2F,  0xD2,  0x28,  0xAB,  0x02,  0xA8,  0x22,  0x0C,  0xB1,  0x12, 	/* 17460 */
+	0x0F,  0xFE,  0x32,  0x03,  0xFC,  0x52,  0x4B,  0xF4,  0x24,  0x44,  0x98,  0x08,  0x05,  0x54,  0x91,  0x20, 	/* 17470 */
+	0xF0,  0xB5,  0x11,  0x0F,  0xFE,  0x11,  0x01,  0xF0,  0x49,  0x43,  0x0A,  0x3F,  0xCC,  0x43,  0x3F,  0xC0, 	/* 17480 */
+	0x60,  0x19,  0x86,  0x06,  0xB7,  0x11,  0x0F,  0xFE,  0x11,  0x0F,  0xFE,  0x84,  0x27,  0xFC,  0x24,  0x83, 	/* 17490 */
+	0xF8,  0x24,  0x8F,  0xFE,  0x04,  0x00,  0x40,  0xB9,  0x11,  0x0F,  0xFE,  0x11,  0x02,  0x20,  0xFB,  0xE2, 	/* 174A0 */
+	0x48,  0x2B,  0xE3,  0xEA,  0x2A,  0xC4,  0xA8,  0x8A,  0x23,  0x1E,  0xBA,  0x12,  0x0F,  0xFE,  0x12,  0x03, 	/* 174B0 */
+	0xF8,  0x20,  0x8F,  0xFE,  0x11,  0x01,  0xF0,  0x11,  0x01,  0xFE,  0xF1,  0x00,  0x10,  0x82,  0x11,  0x0F, 	/* 174C0 */
+	0xFE,  0x15,  0x00,  0x40,  0x7F,  0xC1,  0x10,  0xFF,  0xE8,  0x42,  0x3F,  0x82,  0x48,  0x27,  0x00,  0x40, 	/* 174D0 */
+	0x84,  0x11,  0x0F,  0xFE,  0x11,  0x0F,  0xFE,  0x80,  0xA7,  0x8A,  0x03,  0xCF,  0xC8,  0x2A,  0x82,  0x88, 	/* 174E0 */
+	0x49,  0xA8,  0x7E,  0x8B,  0x11,  0x0F,  0xFE,  0x11,  0x02,  0x1C,  0x2F,  0x4A,  0xA4,  0x65,  0x82,  0x08, 	/* 174F0 */
+	0x6F,  0xEA,  0x48,  0x22,  0x82,  0x18,  0x90,  0x11,  0x0F,  0xFE,  0x11,  0x00,  0x40,  0x3F,  0x82,  0x48, 	/* 17500 */
+	0x3F,  0x82,  0x48,  0x3F,  0xA1,  0x24,  0x22,  0xAC,  0x1E,  0x94,  0x10,  0x8F,  0xFE,  0x11,  0x0E,  0x20, 	/* 17510 */
+	0xAF,  0xCA,  0x20,  0xFF,  0xEA,  0x08,  0xBF,  0xEA,  0x88,  0xE4,  0x80,  0x18,  0x99,  0x11,  0x0F,  0xFE, 	/* 17520 */
+	0x15,  0x0F,  0xFE,  0x80,  0x27,  0xFC,  0x14,  0x4E,  0x68,  0x1B,  0x0E,  0x78,  0x1A,  0x66,  0x60,  0x9C, 	/* 17530 */
+	0x20,  0x8F,  0xBE,  0x20,  0x87,  0xBC,  0x00,  0x0F,  0xBE,  0x20,  0x8B,  0x2C,  0xAA,  0xAA,  0xAA,  0xA2, 	/* 17540 */
+	0xA6,  0x18,  0x9F,  0x11,  0x0F,  0xFE,  0x11,  0x02,  0x10,  0xFB,  0xE1,  0x42,  0x5B,  0xA5,  0x2A,  0x22, 	/* 17550 */
+	0xA3,  0xBA,  0xC0,  0x20,  0x0C,  0xA1,  0x11,  0x0F,  0xFE,  0x15,  0x07,  0xFC,  0x11,  0x0F,  0xFE,  0x84, 	/* 17560 */
+	0x27,  0xFE,  0x08,  0x00,  0xF8,  0x10,  0x86,  0x30,  0xAD,  0x11,  0x0F,  0xFE,  0x21,  0x03,  0xFC,  0x65, 	/* 17570 */
+	0x4B,  0xF4,  0x29,  0x83,  0xFC,  0x44,  0x4A,  0x54,  0x3F,  0x40,  0x98,  0xB2,  0x11,  0x0F,  0xFE,  0x12, 	/* 17580 */
+	0x84,  0xFC,  0x22,  0x08,  0xFC,  0x4A,  0x40,  0xFC,  0x2A,  0x44,  0xFC,  0x4A,  0x48,  0xAC,  0xB8,  0x11, 	/* 17590 */
+	0x0F,  0xFE,  0x11,  0x03,  0xF8,  0x02,  0x27,  0x5C,  0x15,  0x02,  0x48,  0xDF,  0x60,  0x00,  0x4A,  0x48, 	/* 175A0 */
+	0x92,  0xB9,  0x11,  0x0F,  0xFE,  0x19,  0x83,  0x30,  0x7F,  0xC0,  0xA4,  0xFF,  0xE0,  0xA4,  0x7F,  0xC1, 	/* 175B0 */
+	0xB0,  0x2A,  0x84,  0xA4,  0xBB,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xBC,  0x08,  0x47,  0xBC,  0x42,  0x07, 	/* 175C0 */
+	0xBC,  0x29,  0x45,  0xAC,  0x29,  0x41,  0x8C,  0xBC,  0x11,  0x0F,  0xFE,  0x15,  0x00,  0xA0,  0x35,  0x8F, 	/* 175D0 */
+	0xF6,  0x21,  0x03,  0xF0,  0x21,  0x03,  0xF8,  0x50,  0x89,  0xF8,  0xBF,  0x11,  0x0F,  0xFE,  0x11,  0x00, 	/* 175E0 */
+	0x40,  0xFF,  0xE2,  0x08,  0x3F,  0x80,  0x00,  0xFF,  0xE9,  0x12,  0x9F,  0x28,  0x06,  0x81,  0x11,  0x0F, 	/* 175F0 */
+	0xFE,  0x11,  0x07,  0xFC,  0x0A,  0x0F,  0xFE,  0x26,  0x8D,  0xC6,  0x7F,  0xC1,  0x58,  0x64,  0x40,  0x40, 	/* 17600 */
+	0x84,  0x11,  0x0F,  0xFE,  0x15,  0x0F,  0xFE,  0x04,  0x83,  0xB0,  0x0C,  0x8F,  0xFC,  0x24,  0xA3,  0xF8, 	/* 17610 */
+	0x24,  0x83,  0xF8,  0x86,  0x11,  0x0F,  0xFE,  0x15,  0x07,  0xFE,  0x49,  0x07,  0xFC,  0x49,  0x04,  0xF0, 	/* 17620 */
+	0x5F,  0xC5,  0x24,  0x93,  0x80,  0x20,  0x89,  0x11,  0x0F,  0xFE,  0x15,  0x0F,  0xFE,  0x91,  0x22,  0x48, 	/* 17630 */
+	0x4A,  0x43,  0x18,  0xC0,  0x63,  0xF8,  0x20,  0x83,  0xF8,  0x8A,  0x21,  0x0F,  0xFE,  0x15,  0x00,  0xE0, 	/* 17640 */
+	0x35,  0x8D,  0xA6,  0x7F,  0xC1,  0x8C,  0x6B,  0x41,  0x8C,  0x6B,  0x41,  0x8C,  0x8B,  0x11,  0x0F,  0xFE, 	/* 17650 */
+	0x11,  0x00,  0x40,  0x7F,  0xC0,  0x40,  0xFF,  0xE1,  0x08,  0x7F,  0xC2,  0xAA,  0x2A,  0x8F,  0xFE,  0x8D, 	/* 17660 */
+	0x11,  0x0F,  0xFE,  0x15,  0x07,  0xFC,  0x05,  0x0F,  0xFE,  0x18,  0xC2,  0xF0,  0xC8,  0x23,  0xFE,  0x20, 	/* 17670 */
+	0x83,  0xF8,  0x90,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xFE,  0x40,  0x07,  0xFC,  0x56,  0x87,  0x9C,  0x41, 	/* 17680 */
+	0x0B,  0xFE,  0x11,  0x00,  0x30,  0x91,  0x11,  0x0F,  0xFE,  0x11,  0x00,  0x40,  0xFF,  0xE2,  0x08,  0xFF, 	/* 17690 */
+	0xE2,  0x08,  0x3F,  0xA1,  0xA4,  0xE9,  0x83,  0xC6,  0x96,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xFC,  0x51, 	/* 176A0 */
+	0x44,  0xE4,  0x51,  0x47,  0xFC,  0x22,  0x43,  0xB8,  0x22,  0x2F,  0x9E,  0x99,  0x11,  0x0F,  0xFE,  0x11, 	/* 176B0 */
+	0x00,  0x40,  0x7F,  0xE5,  0x24,  0x5A,  0xC5,  0x74,  0x62,  0x25,  0xFC,  0x82,  0x0B,  0xFE,  0x9A,  0x11, 	/* 176C0 */
+	0x0F,  0xFE,  0x11,  0x01,  0x20,  0x27,  0xE2,  0xA4,  0x69,  0x8A,  0xA4,  0x2D,  0xA2,  0xE5,  0x21,  0x82, 	/* 176D0 */
+	0x60,  0xAC,  0x11,  0x0F,  0xFF,  0x11,  0x04,  0x7E,  0x2C,  0x40,  0x38,  0xED,  0x72,  0x7C,  0x21,  0x02, 	/* 176E0 */
+	0xFE,  0x59,  0x08,  0x7F,  0xAE,  0x11,  0x0F,  0xFE,  0x13,  0x05,  0xFC,  0x22,  0x00,  0xFC,  0xEA,  0x42, 	/* 176F0 */
+	0xFC,  0x2A,  0x43,  0xFE,  0x52,  0x08,  0xFF,  0xB4,  0x11,  0x0F,  0xFE,  0x15,  0x0F,  0xFE,  0x24,  0x83, 	/* 17700 */
+	0xF8,  0x24,  0xC7,  0xFE,  0x01,  0x0F,  0xFE,  0x11,  0x00,  0xB0,  0xBC,  0x11,  0x0F,  0xFE,  0x11,  0x07, 	/* 17710 */
+	0xBC,  0x18,  0xC6,  0xB4,  0x1C,  0xC6,  0xB4,  0x32,  0xCC,  0xCA,  0x03,  0x03,  0xC0,  0xBF,  0x11,  0x0F, 	/* 17720 */
+	0xFE,  0x15,  0x0F,  0xFE,  0x80,  0x29,  0x7E,  0x11,  0x02,  0x7C,  0x64,  0x4A,  0x7C,  0x24,  0x42,  0x7C, 	/* 17730 */
+	0x80,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xDE,  0x29,  0x22,  0x94,  0xFF,  0xE0,  0x12,  0x7D,  0x24,  0x5C, 	/* 17740 */
+	0x7D,  0x04,  0x10,  0x86,  0x11,  0x0F,  0xFE,  0x11,  0x04,  0xFC,  0x22,  0x09,  0xFE,  0x44,  0x81,  0xA4, 	/* 17750 */
+	0x27,  0xA5,  0xC8,  0x83,  0x09,  0xCC,  0x91,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xFC,  0x4A,  0x47,  0xFC, 	/* 17760 */
+	0x02,  0x87,  0xFE,  0x52,  0x44,  0x98,  0x41,  0xA8,  0x66,  0x93,  0x11,  0x0F,  0xFE,  0x20,  0x83,  0xF8, 	/* 17770 */
+	0x20,  0x87,  0xFC,  0x4A,  0x47,  0xFC,  0x11,  0x00,  0xE0,  0x1B,  0x8E,  0x06,  0x94,  0x11,  0x0F,  0xFE, 	/* 17780 */
+	0x11,  0x01,  0xFE,  0x20,  0x27,  0xFA,  0x91,  0x23,  0xFA,  0x3F,  0xA2,  0x4A,  0x3F,  0xA0,  0x0C,  0x95, 	/* 17790 */
+	0x11,  0x0F,  0xFE,  0x11,  0x02,  0xA8,  0xFF,  0xE2,  0xAA,  0xCE,  0x6F,  0xFE,  0xA4,  0xA2,  0x48,  0x27, 	/* 177A0 */
+	0x00,  0x40,  0x97,  0x11,  0x0F,  0xFE,  0x11,  0x00,  0x40,  0x7F,  0xE4,  0x90,  0x7F,  0xE4,  0x90,  0x4F, 	/* 177B0 */
+	0x04,  0x00,  0x95,  0x4A,  0x2A,  0x98,  0x11,  0x0F,  0xFE,  0x15,  0x01,  0xB0,  0x7E,  0x82,  0x48,  0x55, 	/* 177C0 */
+	0x4F,  0xBE,  0x35,  0x8D,  0x96,  0x06,  0x03,  0x80,  0x9A,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xC4,  0x44, 	/* 177D0 */
+	0x47,  0xFE,  0x40,  0x47,  0xD4,  0x49,  0x46,  0xC4,  0xAA,  0x42,  0xAC,  0x9F,  0x11,  0x0F,  0xFE,  0x11, 	/* 177E0 */
+	0x02,  0x20,  0x23,  0xEF,  0xE0,  0x23,  0xE3,  0xC8,  0x2B,  0xE4,  0x88,  0x89,  0x43,  0x62,  0xA1,  0x11, 	/* 177F0 */
+	0x0F,  0xFE,  0x11,  0x03,  0xFE,  0x4A,  0x4B,  0x18,  0x2E,  0x6C,  0x00,  0x7F,  0xE2,  0x48,  0xC4,  0x40, 	/* 17800 */
+	0xC0,  0xA6,  0x11,  0x0F,  0xFE,  0x15,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xFE,  0x20,  0x03, 	/* 17810 */
+	0xFE,  0x4A,  0xA9,  0x0C,  0xAC,  0x11,  0x0F,  0xFE,  0x11,  0x0F,  0x90,  0x17,  0xE2,  0x28,  0x3F,  0xC2, 	/* 17820 */
+	0x02,  0xA5,  0x4B,  0xD4,  0xE5,  0x48,  0x86,  0xAD,  0x11,  0x0F,  0xFE,  0x11,  0x0E,  0x30,  0xA7,  0x8C, 	/* 17830 */
+	0x84,  0xB7,  0xEA,  0x08,  0xBF,  0xEC,  0x48,  0x85,  0xC8,  0xE4,  0xB5,  0x11,  0x0F,  0xFE,  0x11,  0x47, 	/* 17840 */
+	0xFE,  0x41,  0x05,  0xF4,  0x55,  0x45,  0xF4,  0x52,  0x85,  0xEA,  0x55,  0x69,  0xE2,  0xBD,  0x11,  0x0F, 	/* 17850 */
+	0xFE,  0x11,  0x05,  0x50,  0x39,  0xEF,  0xE4,  0x96,  0x4B,  0x54,  0xBC,  0x8D,  0x48,  0x95,  0x49,  0x62, 	/* 17860 */
+	0x80,  0x11,  0x0F,  0xFE,  0x31,  0x8F,  0xBE,  0x20,  0x8F,  0xBE,  0xAA,  0xAA,  0xAA,  0x71,  0xC6,  0xAA, 	/* 17870 */
+	0xA4,  0x92,  0x08,  0x81,  0x11,  0x0F,  0xFE,  0x11,  0x03,  0xF8,  0x00,  0x8F,  0xFE,  0x7B,  0xC1,  0x24, 	/* 17880 */
+	0xFF,  0xE1,  0x08,  0x08,  0x80,  0x18,  0x83,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xFC,  0x24,  0x8F,  0xFE, 	/* 17890 */
+	0x15,  0x03,  0xF8,  0xE4,  0xE3,  0xF8,  0x24,  0x83,  0xF8,  0x88,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xFC, 	/* 178A0 */
+	0x55,  0x47,  0xFC,  0x20,  0x83,  0xF8,  0x20,  0x8F,  0xFE,  0x04,  0x00,  0x40,  0x89,  0x08,  0x8F,  0xFE, 	/* 178B0 */
+	0x2A,  0x83,  0xFE,  0x22,  0x07,  0xFC,  0xA2,  0x03,  0xFC,  0x22,  0x03,  0xFE,  0x52,  0x48,  0x92,  0x8A, 	/* 178C0 */
+	0x11,  0x0F,  0xFE,  0x11,  0x00,  0xC0,  0x2A,  0x44,  0x8A,  0x07,  0x81,  0x08,  0x69,  0x46,  0x72,  0xA5, 	/* 178D0 */
+	0x31,  0xCE,  0x8B,  0x11,  0x0F,  0xFE,  0x15,  0x02,  0x40,  0x27,  0x82,  0x40,  0xFF,  0xE1,  0x08,  0x5A, 	/* 178E0 */
+	0xE5,  0x28,  0x5E,  0x8E,  0x3E,  0x8E,  0x11,  0x0F,  0xFE,  0x11,  0x03,  0xF8,  0x04,  0x0F,  0xFE,  0x3B, 	/* 178F0 */
+	0x8C,  0xE6,  0x7F,  0xC4,  0xE4,  0x4A,  0x44,  0xEC,  0x95,  0x11,  0x0F,  0xFE,  0x11,  0x0A,  0x7C,  0x44, 	/* 17900 */
+	0x44,  0xBA,  0xA2,  0x82,  0xFE,  0x6A,  0xAA,  0xCE,  0x28,  0x2C,  0xFE,  0x97,  0x12,  0x0F,  0xFE,  0x12, 	/* 17910 */
+	0x07,  0xBC,  0x4A,  0x44,  0xE4,  0x79,  0x81,  0x24,  0x5F,  0xE5,  0x24,  0x5E,  0x4E,  0x3C,  0x98,  0x11, 	/* 17920 */
+	0x0F,  0xFE,  0x15,  0x03,  0xF8,  0xFB,  0xE2,  0x08,  0x7B,  0xC2,  0x08,  0xFF,  0xE0,  0xA0,  0x32,  0x2C, 	/* 17930 */
+	0x1E,  0x9A,  0x11,  0x0F,  0xFE,  0x1F,  0x01,  0x10,  0x1F,  0x07,  0xFC,  0x4A,  0x4F,  0xFE,  0x10,  0x01, 	/* 17940 */
+	0xF8,  0x20,  0x80,  0x30,  0xA3,  0x11,  0x0F,  0xFE,  0x11,  0xC7,  0xE4,  0x24,  0x8F,  0xFE,  0xA0,  0xAB, 	/* 17950 */
+	0xBE,  0x2A,  0x85,  0xFE,  0x10,  0x86,  0x08,  0xA8,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xFE,  0x54,  0x87, 	/* 17960 */
+	0xEF,  0x49,  0x56,  0xA4,  0x6A,  0x47,  0xE4,  0x48,  0xA9,  0x31,  0xA9,  0x11,  0x0F,  0xFE,  0x11,  0x04, 	/* 17970 */
+	0xFC,  0x28,  0x48,  0xFC,  0x5F,  0xE0,  0x40,  0x2F,  0xE5,  0x2A,  0x4D,  0x28,  0x2C,  0xAA,  0x09,  0x0F, 	/* 17980 */
+	0xFE,  0x29,  0x07,  0xFE,  0x6A,  0x8A,  0xA8,  0xFF,  0xF2,  0xA8,  0xFF,  0xE4,  0xA4,  0x49,  0x28,  0x92, 	/* 17990 */
+	0xAD,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xF8,  0x04,  0x8F,  0xFE,  0x55,  0x47,  0x5C,  0x44,  0x47,  0xFC, 	/* 179A0 */
+	0x55,  0x49,  0x54,  0xB7,  0x11,  0x0F,  0xFE,  0x11,  0x0F,  0xFE,  0x52,  0x02,  0x7C,  0xFC,  0x42,  0xFC, 	/* 179B0 */
+	0x34,  0x42,  0x7C,  0x22,  0x46,  0xC2,  0xBE,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xFC,  0x04,  0x0F,  0xFE, 	/* 179C0 */
+	0x84,  0x27,  0x5C,  0x44,  0x47,  0xFC,  0x44,  0x47,  0xFC,  0x80,  0x11,  0x0F,  0xFE,  0x11,  0x04,  0xF8, 	/* 179D0 */
+	0x2A,  0x88,  0xD8,  0x4F,  0x80,  0x00,  0x3F,  0xC5,  0x54,  0x55,  0x4B,  0xFE,  0x84,  0x11,  0x0F,  0xFE, 	/* 179E0 */
+	0x12,  0x89,  0xFE,  0x52,  0x41,  0xFC,  0x92,  0x47,  0xFE,  0x08,  0x84,  0x48,  0x80,  0x88,  0x18,  0x87, 	/* 179F0 */
+	0x11,  0x0F,  0xFE,  0x11,  0x03,  0x58,  0x55,  0xEB,  0xFA,  0x21,  0x25,  0xFA,  0xCA,  0x44,  0xB4,  0x52, 	/* 17A00 */
+	0xA4,  0x12,  0x88,  0x11,  0x0F,  0xFE,  0x15,  0x00,  0xA0,  0x31,  0x8F,  0xFE,  0x4A,  0x47,  0xFC,  0x20, 	/* 17A10 */
+	0x83,  0xF8,  0x20,  0x83,  0xF8,  0x8A,  0x11,  0x0F,  0xFE,  0x11,  0x03,  0xC4,  0x49,  0x4F,  0xD4,  0x55, 	/* 17A20 */
+	0x47,  0xD4,  0x55,  0x47,  0xC4,  0x54,  0x4A,  0xAC,  0x90,  0x11,  0x0F,  0xFE,  0x19,  0x0F,  0x7C,  0x21, 	/* 17A30 */
+	0x0F,  0xFE,  0x32,  0x86,  0xDE,  0x62,  0x4A,  0xD8,  0x22,  0x82,  0xC6,  0x91,  0x11,  0x0F,  0xFE,  0x11, 	/* 17A40 */
+	0x0F,  0xFE,  0x24,  0x83,  0xF8,  0x24,  0x8F,  0xFE,  0x24,  0x83,  0xF8,  0x24,  0x8F,  0xFE,  0x94,  0x11, 	/* 17A50 */
+	0x0F,  0xFE,  0x11,  0x07,  0xFC,  0x24,  0x86,  0x4C,  0x95,  0x27,  0xFC,  0x51,  0x45,  0xF4,  0x40,  0x47, 	/* 17A60 */
+	0xFC,  0x97,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xFE,  0x4F,  0x27,  0xFE,  0x50,  0xA5,  0xFA,  0x4A,  0xA7, 	/* 17A70 */
+	0x92,  0x4C,  0xA7,  0xFE,  0x99,  0x11,  0x0F,  0xFE,  0x11,  0x04,  0x44,  0x74,  0x86,  0x7E,  0xAC,  0x8F, 	/* 17A80 */
+	0x7E,  0x24,  0x85,  0x7E,  0x44,  0x88,  0x7E,  0x9B,  0x12,  0x0F,  0xFE,  0x12,  0x04,  0x10,  0xFF,  0xE9, 	/* 17A90 */
+	0x44,  0xF2,  0x88,  0xFE,  0xF9,  0x08,  0xFC,  0xF9,  0x08,  0x10,  0x9C,  0x11,  0x0F,  0xFF,  0x11,  0x87, 	/* 17AA0 */
+	0xFE,  0x4A,  0x47,  0xA4,  0x47,  0xE7,  0x88,  0xAF,  0xEA,  0x88,  0xB8,  0x80,  0x08,  0xA4,  0x11,  0x0F, 	/* 17AB0 */
+	0xFE,  0x11,  0x0F,  0xA8,  0x22,  0x83,  0xEE,  0x4A,  0x86,  0xEE,  0x92,  0x82,  0xEE,  0x42,  0x89,  0xFF, 	/* 17AC0 */
+	0xA6,  0x11,  0x0F,  0xFE,  0x15,  0x07,  0xFE,  0x4A,  0x07,  0xFC,  0x4A,  0x47,  0xFC,  0x50,  0x05,  0xFE, 	/* 17AD0 */
+	0x95,  0x2A,  0x4C,  0xA8,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xFC,  0x4A,  0x4F,  0xFE,  0x80,  0x27,  0xFC, 	/* 17AE0 */
+	0x2A,  0x4C,  0xB8,  0x32,  0x2C,  0x1E,  0xA9,  0x11,  0x0F,  0xFE,  0x11,  0x0E,  0xFE,  0xA4,  0x4C,  0xFE, 	/* 17AF0 */
+	0xAA,  0x8A,  0xBE,  0xAC,  0x8C,  0xBC,  0x90,  0x8A,  0x7E,  0xAA,  0x11,  0x0F,  0xFE,  0x11,  0x02,  0x06, 	/* 17B00 */
+	0xFB,  0x84,  0xA0,  0xFF,  0xE1,  0x24,  0xFE,  0x43,  0xA4,  0x52,  0x49,  0x44,  0xAB,  0x11,  0x0F,  0xFE, 	/* 17B10 */
+	0x11,  0x07,  0xFC,  0x04,  0x0F,  0xFE,  0x24,  0x83,  0xF8,  0x24,  0x8F,  0xFE,  0x52,  0x48,  0x92,  0xAC, 	/* 17B20 */
+	0x11,  0x0F,  0xFE,  0x15,  0x05,  0xF4,  0x31,  0x8D,  0xF6,  0x11,  0x0F,  0xFF,  0x0E,  0x03,  0x58,  0xC4, 	/* 17B30 */
+	0x60,  0x40,  0xAE,  0x11,  0x0F,  0xFE,  0x11,  0x0A,  0xA0,  0x73,  0xEF,  0xA4,  0x74,  0x4A,  0x94,  0xFD, 	/* 17B40 */
+	0x85,  0x08,  0x31,  0x4C,  0xA2,  0xAF,  0x11,  0x0F,  0xFE,  0x4A,  0x47,  0xFC,  0x08,  0x07,  0xFC,  0x0A, 	/* 17B50 */
+	0x0F,  0xFF,  0x10,  0x83,  0xF8,  0xD0,  0x81,  0xF8,  0xB9,  0x11,  0x0F,  0xFE,  0x15,  0x07,  0xFC,  0x20, 	/* 17B60 */
+	0x8F,  0xFE,  0x80,  0x27,  0xFC,  0x11,  0x83,  0xE4,  0x04,  0x0F,  0xFE,  0xBA,  0x11,  0x0F,  0xFE,  0x15, 	/* 17B70 */
+	0x0F,  0xFE,  0x0A,  0x4F,  0x58,  0x55,  0x4B,  0xFA,  0x20,  0x83,  0xF8,  0x20,  0x84,  0x08,  0x81,  0x11, 	/* 17B80 */
+	0x0F,  0xFE,  0x15,  0x0F,  0xFE,  0x11,  0x07,  0xFC,  0x51,  0x45,  0xF4,  0x04,  0x0F,  0xFE,  0x1F,  0x0E, 	/* 17B90 */
+	0x4E,  0x89,  0x11,  0x0F,  0xFE,  0x11,  0x02,  0x28,  0xF7,  0xC2,  0x28,  0xFF,  0xE2,  0x7C,  0x74,  0x4A, 	/* 17BA0 */
+	0xFC,  0x24,  0x42,  0x7C,  0x8D,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xD0,  0x51,  0xE7,  0xE0,  0x79,  0xE5, 	/* 17BB0 */
+	0x00,  0x7F,  0xC4,  0xA4,  0x4A,  0x4F,  0xFE,  0x8F,  0x11,  0x0F,  0xFE,  0x11,  0x00,  0x08,  0xBF,  0xEA, 	/* 17BC0 */
+	0xF8,  0xEA,  0xA2,  0xFA,  0xE9,  0xAA,  0xF4,  0xAA,  0xA4,  0xF1,  0x90,  0x11,  0x0F,  0xFE,  0x11,  0x03, 	/* 17BD0 */
+	0x10,  0xD7,  0xC6,  0xC4,  0xF7,  0xC2,  0x44,  0xD7,  0xC2,  0xA8,  0xCA,  0xA3,  0x46,  0x95,  0x11,  0x0F, 	/* 17BE0 */
+	0xFE,  0x11,  0x02,  0x7C,  0xF5,  0x42,  0x7C,  0xF5,  0x42,  0xFE,  0x69,  0x2B,  0xFE,  0x28,  0xA2,  0x86, 	/* 17BF0 */
+	0x9C,  0x11,  0x0F,  0xFE,  0x11,  0x0F,  0xA0,  0x23,  0xEF,  0xCA,  0x71,  0x2A,  0xE6,  0x31,  0x8D,  0xF6, 	/* 17C00 */
+	0x35,  0x8C,  0xC6,  0x9D,  0x11,  0x0F,  0xFE,  0x11,  0x0F,  0xFC,  0x29,  0x4D,  0x74,  0x79,  0xC1,  0xA6, 	/* 17C10 */
+	0x60,  0x0F,  0xFE,  0x11,  0x87,  0xE4,  0xA4,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0x54,  0x5F,  0xE5,  0x28, 	/* 17C20 */
+	0x7F,  0xE5,  0x54,  0x7D,  0x65,  0x39,  0x55,  0x4B,  0x10,  0xA5,  0x11,  0x0F,  0xFE,  0x5F,  0x44,  0xA8, 	/* 17C30 */
+	0xAF,  0x45,  0xAA,  0xFF,  0xE0,  0x40,  0xFF,  0xF3,  0x58,  0xC4,  0x60,  0x40,  0xA9,  0x11,  0x0F,  0xFE, 	/* 17C40 */
+	0x11,  0x09,  0xFC,  0x4A,  0x83,  0xFE,  0x8A,  0x85,  0xFC,  0x2A,  0xA4,  0xF8,  0x4A,  0x88,  0xF8,  0xAA, 	/* 17C50 */
+	0x11,  0x0F,  0xFE,  0x11,  0x07,  0xD0,  0x55,  0xEF,  0xE4,  0x56,  0x4F,  0xD4,  0x29,  0x44,  0x88,  0x39, 	/* 17C60 */
+	0x44,  0x62,  0xB7,  0x11,  0x0F,  0xFE,  0x11,  0x06,  0xFC,  0x01,  0x0F,  0xFE,  0x02,  0x07,  0x7C,  0x0C, 	/* 17C70 */
+	0x4F,  0x7C,  0x94,  0x4F,  0x7C,  0xB9,  0x09,  0x0F,  0xFE,  0x09,  0x0E,  0x7C,  0x04,  0x4F,  0x7C,  0x04, 	/* 17C80 */
+	0x4F,  0x7E,  0x02,  0xAF,  0xD6,  0x97,  0xAF,  0x0C,  0xBA,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xBC,  0x4A, 	/* 17C90 */
+	0x47,  0xBC,  0x4A,  0x45,  0xF4,  0x74,  0x45,  0xF4,  0x54,  0x45,  0xF4,  0xBB,  0x12,  0x0F,  0xFE,  0x17, 	/* 17CA0 */
+	0x08,  0x50,  0x7F,  0xC1,  0x54,  0x9D,  0xC4,  0x20,  0x1F,  0xC2,  0xB0,  0x52,  0xC8,  0x20,  0xBE,  0x11, 	/* 17CB0 */
+	0x0F,  0xFE,  0x11,  0x02,  0x7E,  0xF9,  0x22,  0x6C,  0xFB,  0xCA,  0xA4,  0xFB,  0xC7,  0x24,  0xAB,  0xC2, 	/* 17CC0 */
+	0x42,  0x82,  0x11,  0x0F,  0xFE,  0x14,  0x85,  0x14,  0x8F,  0x02,  0x94,  0xA5,  0x29,  0xCE,  0x04,  0x0F, 	/* 17CD0 */
+	0xFE,  0x35,  0x8C,  0x46,  0x86,  0x11,  0x0F,  0xFE,  0x15,  0x07,  0xFE,  0x4C,  0x47,  0x7C,  0x4F,  0x84, 	/* 17CE0 */
+	0xA8,  0x5F,  0xC5,  0x54,  0x95,  0x4B,  0xFE,  0x87,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0x0C,  0xA7,  0x0F, 	/* 17CF0 */
+	0x90,  0xAF,  0xEF,  0x98,  0xAB,  0x4F,  0xB2,  0x2D,  0x0A,  0x90,  0x8A,  0x11,  0x0F,  0xFE,  0x11,  0x04, 	/* 17D00 */
+	0x7C,  0x55,  0x4A,  0x6C,  0x57,  0xCF,  0x80,  0x2F,  0xEB,  0xAA,  0xAA,  0xA3,  0xFF,  0x8B,  0x12,  0x0F, 	/* 17D10 */
+	0xFE,  0x12,  0x02,  0x7E,  0xB9,  0x0A,  0x7C,  0xFC,  0x42,  0x7C,  0xAC,  0x4B,  0x7C,  0x22,  0x4C,  0xC2, 	/* 17D20 */
+	0x93,  0x11,  0x0F,  0xFE,  0x11,  0x01,  0xBC,  0xE4,  0x82,  0x7C,  0xFD,  0x42,  0x7C,  0x75,  0x46,  0xFC, 	/* 17D30 */
+	0xA5,  0x42,  0xAA,  0x96,  0x11,  0x0F,  0xFE,  0x78,  0x84,  0xBE,  0x79,  0x44,  0x3E,  0xB8,  0x82,  0xC8, 	/* 17D40 */
+	0xFF,  0xE1,  0xF0,  0xE4,  0xE0,  0x40,  0x97,  0x11,  0x0F,  0xFE,  0x79,  0x04,  0xFE,  0x7A,  0x47,  0x7E, 	/* 17D50 */
+	0x68,  0x8B,  0xC8,  0xFF,  0xF1,  0xF0,  0xE4,  0xE0,  0x40,  0x9A,  0x11,  0x0F,  0xFE,  0x11,  0x03,  0xC4, 	/* 17D60 */
+	0x52,  0x8F,  0xFE,  0xA9,  0x0F,  0xFC,  0xA9,  0x0F,  0xFE,  0x51,  0x0A,  0x90,  0xA2,  0x11,  0x0F,  0xFE, 	/* 17D70 */
+	0x11,  0x07,  0xDE,  0x29,  0x0F,  0xFC,  0x48,  0x47,  0xBC,  0x4A,  0x07,  0xBC,  0x4A,  0x25,  0x9E,  0xAD, 	/* 17D80 */
+	0x11,  0x0F,  0xFE,  0x4A,  0x47,  0xBC,  0x4A,  0x47,  0xBC,  0x44,  0x45,  0xF4,  0x55,  0x45,  0xF4,  0x4E, 	/* 17D90 */
+	0x45,  0x5C,  0xAF,  0x11,  0x0F,  0xFE,  0x51,  0x02,  0xF8,  0x88,  0x84,  0xFE,  0x0A,  0xA5,  0x52,  0x80, 	/* 17DA0 */
+	0xC7,  0xFC,  0x4A,  0x4F,  0xFE,  0xB0,  0x11,  0x0F,  0xFE,  0x14,  0x42,  0x7C,  0xD4,  0x42,  0x7C,  0x4F, 	/* 17DB0 */
+	0xEF,  0xAA,  0x2F,  0xEB,  0x24,  0xA9,  0x82,  0x66,  0xBF,  0x11,  0x0F,  0xFE,  0x11,  0x07,  0xFC,  0x4A, 	/* 17DC0 */
+	0x47,  0xFC,  0x52,  0x42,  0x7E,  0xFC,  0x83,  0x7E,  0xAC,  0x8A,  0x7E,  0x8D,  0x04,  0x00,  0x7C,  0x04, 	/* 17DD0 */
+	0x07,  0xFE,  0x44,  0x44,  0x40,  0x45,  0xC4,  0xE0,  0x74,  0x04,  0x42,  0x44,  0x28,  0x3E,  0x8E,  0x04, 	/* 17DE0 */
+	0x00,  0x78,  0x04,  0x03,  0xFE,  0x28,  0x43,  0xF8,  0x28,  0x02,  0x7C,  0x25,  0x04,  0x52,  0x49,  0x29, 	/* 17DF0 */
+	0x0E,  0x90,  0x04,  0x00,  0x7C,  0x04,  0x07,  0xFE,  0x44,  0x25,  0xF8,  0x44,  0x45,  0xFC,  0x50,  0x05, 	/* 17E00 */
+	0xFC,  0x90,  0x01,  0xFC,  0x94,  0x07,  0x80,  0x40,  0x3F,  0xE2,  0x44,  0x27,  0x83,  0xC2,  0x23,  0xE2, 	/* 17E10 */
+	0x20,  0x3F,  0xE4,  0x88,  0x47,  0x0B,  0x8E,  0x95,  0x07,  0x80,  0x40,  0x7F,  0xE4,  0x80,  0x5F,  0xC4, 	/* 17E20 */
+	0x80,  0x5D,  0xC5,  0x54,  0x55,  0x4A,  0xA6,  0x96,  0x06,  0x1F,  0x9A,  0x04,  0x00,  0x78,  0x04,  0x07, 	/* 17E30 */
+	0xFE,  0x48,  0x27,  0xF8,  0x48,  0x44,  0x7C,  0x6A,  0x85,  0xB0,  0x8A,  0x07,  0xFE,  0x9C,  0x04,  0x00, 	/* 17E40 */
+	0x78,  0x7F,  0xE5,  0xC8,  0x47,  0x85,  0xFC,  0x52,  0x45,  0xFC,  0x52,  0x47,  0xFE,  0x44,  0x29,  0x8C, 	/* 17E50 */
+	0x9E,  0x04,  0x00,  0x78,  0x7F,  0xE4,  0x44,  0x5F,  0xC6,  0x88,  0x6F,  0x87,  0xF0,  0x41,  0x07,  0xFE, 	/* 17E60 */
+	0x88,  0x8B,  0x04,  0x9F,  0x01,  0x07,  0x9E,  0x49,  0x07,  0xBE,  0x02,  0x8F,  0xBE,  0x22,  0x83,  0xAE, 	/* 17E70 */
+	0x4B,  0x40,  0xB4,  0x15,  0x46,  0xA6,  0xA7,  0x20,  0x03,  0xDE,  0x20,  0x87,  0xC8,  0x53,  0xF7,  0xC8, 	/* 17E80 */
+	0x51,  0x07,  0xDE,  0x69,  0x27,  0xC2,  0xA8,  0x23,  0xCC,  0xAB,  0x04,  0x00,  0x40,  0x04,  0x07,  0xF8, 	/* 17E90 */
+	0x44,  0x84,  0x48,  0x7F,  0x80,  0x40,  0x04,  0x80,  0x44,  0x07,  0xEF,  0x82,  0xB1,  0x00,  0x07,  0xF8, 	/* 17EA0 */
+	0x02,  0x87,  0xC8,  0x08,  0x87,  0xE8,  0x4A,  0x87,  0xE8,  0x0A,  0xA0,  0x96,  0x1E,  0xEE,  0x0A,  0xB9, 	/* 17EB0 */
+	0x20,  0x02,  0x7E,  0x21,  0x0F,  0x90,  0xA9,  0x0A,  0x90,  0xA9,  0x0F,  0x90,  0x31,  0x02,  0x90,  0x3F, 	/* 17EC0 */
+	0xEC,  0x80,  0xBB,  0x20,  0x82,  0x08,  0xF8,  0x8A,  0xFE,  0xAA,  0x0F,  0xA0,  0x22,  0x03,  0x20,  0x2A, 	/* 17ED0 */
+	0x03,  0xA0,  0xC5,  0xE0,  0x40,  0x8A,  0x21,  0x02,  0x10,  0x2F,  0xEF,  0xA4,  0xAA,  0x4A,  0xA8,  0xF9, 	/* 17EE0 */
+	0x83,  0x10,  0x29,  0x83,  0xA8,  0xC4,  0x40,  0x82,  0x8B,  0x21,  0x82,  0x08,  0x23,  0xEF,  0xAA,  0xAA, 	/* 17EF0 */
+	0xAA,  0xAA,  0xFB,  0x62,  0x36,  0x32,  0x22,  0xA2,  0x3A,  0x2C,  0x66,  0x8C,  0x21,  0x02,  0x10,  0x2F, 	/* 17F00 */
+	0xEF,  0x90,  0xA9,  0x0A,  0xFC,  0xF9,  0x02,  0x10,  0x37,  0xE2,  0x90,  0x39,  0x0C,  0x50,  0x93,  0x20, 	/* 17F10 */
+	0x22,  0x7A,  0x20,  0xAF,  0xBA,  0xAA,  0x2A,  0xA2,  0xFB,  0xA2,  0x0A,  0x30,  0xA2,  0x8A,  0x3C,  0xAC, 	/* 17F20 */
+	0x72,  0x95,  0x00,  0x0F,  0xFE,  0x04,  0x07,  0xFC,  0x0A,  0x03,  0x58,  0xFF,  0xE2,  0x48,  0x3F,  0x80, 	/* 17F30 */
+	0x44,  0x07,  0xEF,  0x82,  0xA3,  0x21,  0xC2,  0x04,  0x22,  0x4F,  0xA4,  0xAA,  0x2A,  0xAA,  0xFC,  0x92, 	/* 17F40 */
+	0x10,  0x31,  0x82,  0xA4,  0x3A,  0xEC,  0x72,  0xA4,  0x7F,  0xE1,  0x24,  0x49,  0x82,  0x70,  0x19,  0xCE, 	/* 17F50 */
+	0x43,  0x3F,  0x82,  0x48,  0x3F,  0x80,  0x48,  0x07,  0x4F,  0x82,  0xA9,  0x04,  0x04,  0x44,  0x7F,  0xC1, 	/* 17F60 */
+	0x00,  0xFF,  0xE0,  0x40,  0x7F,  0xC4,  0x44,  0x7F,  0xC0,  0x48,  0x07,  0xCF,  0x82,  0xAA,  0x20,  0x42, 	/* 17F70 */
+	0x24,  0x21,  0x4F,  0x84,  0xAC,  0x4A,  0xA4,  0xF8,  0x42,  0x0F,  0x37,  0x42,  0x84,  0x38,  0x4C,  0x44, 	/* 17F80 */
+	0xAB,  0x21,  0x02,  0x10,  0x23,  0xEF,  0xC2,  0xAB,  0xAA,  0xAA,  0xFA,  0xA2,  0x3A,  0x32,  0xC2,  0xA0, 	/* 17F90 */
+	0x3A,  0x2C,  0x5E,  0xAF,  0x20,  0x42,  0x08,  0x23,  0x0F,  0xA0,  0xAB,  0xEA,  0xA4,  0xFA,  0x42,  0x24, 	/* 17FA0 */
+	0x32,  0x42,  0xA4,  0x3A,  0x4C,  0x7E,  0xB0,  0x20,  0x82,  0x08,  0x20,  0x8F,  0xBE,  0xAA,  0xAA,  0xAA, 	/* 17FB0 */
+	0xFA,  0xA2,  0x3E,  0x32,  0xA2,  0xAA,  0x3A,  0xAE,  0x7E,  0xB6,  0x22,  0x42,  0x24,  0x22,  0x4F,  0xFE, 	/* 17FC0 */
+	0xAA,  0x4A,  0xA4,  0xFA,  0x42,  0x3C,  0x32,  0x42,  0xA4,  0x3A,  0x4C,  0x7C,  0x84,  0x21,  0x02,  0x10, 	/* 17FD0 */
+	0x21,  0x0F,  0xFE,  0xA9,  0x0A,  0x90,  0xF9,  0x02,  0x3C,  0x32,  0x42,  0xA4,  0x3A,  0x4C,  0x7C,  0x86, 	/* 17FE0 */
+	0x20,  0x02,  0x3C,  0xFA,  0x4A,  0xA4,  0xAB,  0xCF,  0xA4,  0xA2,  0x42,  0x3C,  0x2A,  0x43,  0xA4,  0xCA, 	/* 17FF0 */
+	0x40,  0x7E,  0x87,  0x21,  0x02,  0x10,  0x27,  0xEF,  0xC2,  0xAC,  0x2A,  0xA0,  0xFA,  0xCA,  0x30,  0x32, 	/* 18000 */
+	0x02,  0xA2,  0x3A,  0x2C,  0x9E,  0x89,  0x21,  0x02,  0x10,  0x22,  0x8F,  0xA4,  0xAF,  0xEA,  0x81,  0xFF, 	/* 18010 */
+	0xE2,  0x12,  0x31,  0x22,  0x9C,  0x39,  0x0C,  0x50,  0x8B,  0x00,  0x07,  0xFE,  0x04,  0x02,  0x7C,  0x3C, 	/* 18020 */
+	0x04,  0x7E,  0x84,  0x03,  0xF8,  0x24,  0x83,  0xF8,  0x05,  0xCF,  0xE2,  0x8D,  0x48,  0x82,  0x48,  0x25, 	/* 18030 */
+	0x0F,  0xFE,  0x84,  0x2B,  0xFA,  0x24,  0x82,  0x48,  0x3F,  0x80,  0x44,  0x07,  0xEF,  0x82,  0x8E,  0x20, 	/* 18040 */
+	0x02,  0x3E,  0x22,  0x0F,  0xBE,  0xAA,  0x8A,  0xA8,  0xFA,  0xE3,  0x2A,  0x2B,  0x23,  0xD2,  0xCA,  0x20, 	/* 18050 */
+	0x4C,  0x94,  0x20,  0x02,  0x7E,  0x24,  0x2F,  0xC2,  0xAF,  0xAA,  0xEA,  0xFE,  0xA2,  0x6A,  0x37,  0xA2, 	/* 18060 */
+	0xC2,  0x3C,  0x2C,  0x7E,  0x99,  0x21,  0x02,  0x10,  0x27,  0xCF,  0x90,  0xA9,  0x0A,  0xFE,  0xF9,  0x02, 	/* 18070 */
+	0x10,  0x37,  0xC2,  0x90,  0x39,  0x0C,  0x7E,  0x9B,  0x21,  0x02,  0x50,  0x25,  0x0F,  0xFC,  0xA9,  0x0A, 	/* 18080 */
+	0x90,  0xFF,  0xE2,  0x38,  0x2D,  0x43,  0x92,  0xC9,  0x00,  0x10,  0x9E,  0x20,  0xC2,  0x70,  0x21,  0x0F, 	/* 18090 */
+	0x90,  0xAF,  0xEA,  0x90,  0xF9,  0x02,  0x3C,  0x32,  0x42,  0xA4,  0x3A,  0x4C,  0x7C,  0x9F,  0x21,  0x02, 	/* 180A0 */
+	0x10,  0x27,  0xEF,  0xA8,  0xAA,  0x4A,  0xC2,  0xFA,  0x42,  0x14,  0x28,  0x83,  0x98,  0xCA,  0x40,  0x42, 	/* 180B0 */
+	0xA4,  0x21,  0x02,  0x10,  0x22,  0x8F,  0xC4,  0xAF,  0xEA,  0x80,  0xF8,  0x02,  0x7C,  0x34,  0x42,  0xC4, 	/* 180C0 */
+	0x3C,  0x4C,  0x7C,  0xA9,  0x07,  0x8F,  0x48,  0x26,  0x83,  0x58,  0xE4,  0xA0,  0x86,  0x04,  0x07,  0xF8, 	/* 180D0 */
+	0x44,  0x87,  0xF8,  0x04,  0x4F,  0xFA,  0xAC,  0x11,  0x01,  0x10,  0x7F,  0xC1,  0x10,  0xFF,  0xE2,  0x48, 	/* 180E0 */
+	0x7F,  0xCA,  0x4A,  0x3F,  0x80,  0x44,  0x07,  0xCF,  0x82,  0xAD,  0x20,  0x02,  0x7E,  0x21,  0x8F,  0x94, 	/* 180F0 */
+	0xAA,  0x6A,  0xFA,  0xF8,  0xA2,  0x08,  0x33,  0xE2,  0x88,  0x38,  0x8C,  0x7F,  0xAE,  0x04,  0x0F,  0xFE, 	/* 18100 */
+	0x2A,  0x84,  0xA4,  0x92,  0x42,  0x60,  0x3F,  0x82,  0x48,  0x3F,  0x80,  0x48,  0x07,  0xCF,  0x82,  0xAF, 	/* 18110 */
+	0x21,  0x02,  0x10,  0xFF,  0xCA,  0x90,  0xAF,  0xEF,  0xA0,  0x24,  0x02,  0xA6,  0x2B,  0x83,  0xA0,  0xCA, 	/* 18120 */
+	0x20,  0x1E,  0xB8,  0x24,  0xA2,  0x2A,  0xFA,  0xCA,  0x88,  0xAB,  0xEF,  0xA2,  0x23,  0xE3,  0x22,  0x2B, 	/* 18130 */
+	0xE3,  0xA2,  0xC6,  0x20,  0x26,  0xB9,  0x20,  0x02,  0x7E,  0x21,  0x4F,  0xBE,  0xAA,  0xAA,  0xAA,  0xFB, 	/* 18140 */
+	0xE2,  0x2A,  0x33,  0xE2,  0xAA,  0x3A,  0xAC,  0x66,  0xBB,  0x22,  0x82,  0x28,  0x22,  0x4F,  0xC2,  0xAB, 	/* 18150 */
+	0xCA,  0xA4,  0xFA,  0x42,  0x3C,  0x31,  0x82,  0xAA,  0x3A,  0xAC,  0x46,  0xBE,  0x02,  0x82,  0xCC,  0x24, 	/* 18160 */
+	0xAF,  0xC8,  0xAF,  0xEA,  0xC8,  0xFE,  0xA2,  0x4A,  0x2C,  0x43,  0xCC,  0xC5,  0x60,  0xC2,  0x80,  0x7F, 	/* 18170 */
+	0xE4,  0x92,  0x7F,  0xE1,  0x00,  0x3F,  0xE4,  0x82,  0xBF,  0x22,  0x92,  0x3F,  0x20,  0x92,  0x0F,  0xAF, 	/* 18180 */
+	0x0C,  0x82,  0x21,  0x02,  0x1E,  0xFA,  0x2A,  0xDC,  0xA9,  0x4A,  0xEB,  0xF8,  0x83,  0x3E,  0x28,  0x83, 	/* 18190 */
+	0xFF,  0xC4,  0x80,  0x08,  0x83,  0x7F,  0xC4,  0x00,  0x7F,  0xE5,  0x4C,  0x53,  0x07,  0x8E,  0x44,  0x0B, 	/* 181A0 */
+	0xF8,  0x24,  0x83,  0xF8,  0x04,  0x4F,  0xFA,  0x86,  0x20,  0x02,  0x3C,  0x22,  0x4F,  0xA4,  0xAB,  0xCA, 	/* 181B0 */
+	0xA4,  0xFB,  0xC2,  0x24,  0x33,  0xC2,  0x98,  0x3A,  0xAC,  0x46,  0x88,  0x21,  0xC2,  0x54,  0x25,  0x4F, 	/* 181C0 */
+	0xDC,  0xAC,  0x0A,  0xFC,  0xF9,  0x42,  0x14,  0x2F,  0xE3,  0x90,  0xEA,  0x80,  0x44,  0x89,  0x20,  0x62, 	/* 181D0 */
+	0x78,  0x22,  0xCF,  0xAA,  0xAC,  0x2A,  0xBC,  0xF8,  0x42,  0x08,  0x37,  0xE2,  0x88,  0x38,  0x8C,  0x58, 	/* 181E0 */
+	0x8A,  0x21,  0x22,  0x6A,  0x22,  0xAF,  0xAA,  0xAF,  0xAA,  0xAA,  0xFB,  0xA2,  0x6A,  0x36,  0xA2,  0xA2, 	/* 181F0 */
+	0x3A,  0x2C,  0x66,  0x8D,  0x21,  0x02,  0x18,  0x22,  0x4F,  0xC2,  0xAF,  0xDA,  0x90,  0xFF,  0xE2,  0x10, 	/* 18200 */
+	0x33,  0x42,  0xD2,  0x39,  0x2C,  0xB0,  0x91,  0x70,  0x62,  0x78,  0xF0,  0x85,  0x2E,  0x3A,  0x84,  0x7F, 	/* 18210 */
+	0x84,  0x03,  0xF8,  0x24,  0x83,  0xF8,  0x04,  0x4F,  0xFA,  0x92,  0x20,  0x22,  0x7C,  0xFA,  0x4A,  0xA4, 	/* 18220 */
+	0xAD,  0x4F,  0xF6,  0x23,  0x43,  0x74,  0x2B,  0x43,  0xDF,  0xC4,  0x80,  0x87,  0x98,  0x24,  0x02,  0x4E, 	/* 18230 */
+	0x27,  0xAF,  0xAA,  0xAA,  0xAA,  0xAA,  0xFF,  0xA2,  0x2A,  0x2A,  0xA3,  0xAA,  0xC5,  0xE0,  0x88,  0x9A, 	/* 18240 */
+	0x09,  0x0F,  0x9E,  0x09,  0x07,  0x9C,  0x09,  0x0F,  0x1E,  0x25,  0x03,  0xF8,  0x24,  0x83,  0xF8,  0x04, 	/* 18250 */
+	0x4F,  0xFA,  0x9C,  0x04,  0x0F,  0xFE,  0x92,  0x25,  0x54,  0x4F,  0x29,  0x42,  0x3F,  0x82,  0x48,  0x3F, 	/* 18260 */
+	0x80,  0x44,  0x07,  0xEF,  0x82,  0xA5,  0x22,  0x22,  0x2C,  0x22,  0x8F,  0xF8,  0xAA,  0xFA,  0xEA,  0xFF, 	/* 18270 */
+	0xA2,  0xAA,  0x32,  0xA2,  0xAA,  0x3B,  0x2C,  0x62,  0xA9,  0x20,  0x02,  0x3E,  0xFA,  0xAA,  0xBE,  0xAA, 	/* 18280 */
+	0xAF,  0xBE,  0x22,  0xA3,  0x3E,  0x2A,  0x63,  0xBE,  0xC4,  0x20,  0x86,  0xB4,  0x20,  0x02,  0x3C,  0x22, 	/* 18290 */
+	0x4F,  0xBC,  0xAA,  0x4A,  0xBC,  0xF9,  0x02,  0x3E,  0x36,  0xA2,  0xAA,  0x3D,  0x2C,  0x4C,  0xB7,  0x21, 	/* 182A0 */
+	0x02,  0x54,  0x2F,  0xEF,  0x90,  0xAF,  0xEA,  0xA8,  0xFC,  0x42,  0x7A,  0x34,  0x82,  0xF8,  0x34,  0x4C, 	/* 182B0 */
+	0x3C,  0xBB,  0x21,  0x02,  0x7C,  0x21,  0x0F,  0xFC,  0xA9,  0x0A,  0xFE,  0xFD,  0x42,  0x54,  0x37,  0xC2, 	/* 182C0 */
+	0xC4,  0x3C,  0x4C,  0x4C,  0xBF,  0x21,  0x02,  0x10,  0x2F,  0xEF,  0x82,  0xAE,  0xEA,  0xAA,  0xFE,  0xA2, 	/* 182D0 */
+	0x2E,  0x2A,  0x83,  0x48,  0xE4,  0xA0,  0x86,  0x89,  0x21,  0x12,  0x49,  0x22,  0x2F,  0xBE,  0xAA,  0xAA, 	/* 182E0 */
+	0xBE,  0xFA,  0xA2,  0x3E,  0x30,  0x82,  0xFF,  0x38,  0x8C,  0x48,  0x8B,  0x21,  0x12,  0x49,  0xFA,  0x2A, 	/* 182F0 */
+	0xBE,  0xAA,  0xAF,  0xBE,  0x22,  0xA3,  0x2A,  0x2B,  0xE3,  0xEA,  0xC4,  0xA0,  0x89,  0x8C,  0x22,  0x42, 	/* 18300 */
+	0xD4,  0x24,  0xCF,  0xE4,  0xAD,  0x4A,  0xCC,  0xFE,  0x42,  0x57,  0x35,  0xC2,  0xC4,  0x3C,  0x4C,  0x44, 	/* 18310 */
+	0x8E,  0x23,  0xC2,  0x24,  0x23,  0xCF,  0xA4,  0xAB,  0xCA,  0x90,  0xFB,  0xE2,  0x6A,  0x33,  0x62,  0xBE, 	/* 18320 */
+	0x38,  0x2C,  0x4C,  0x93,  0x21,  0x02,  0x18,  0x22,  0x4F,  0xFE,  0xA8,  0x1A,  0xFA,  0xFD,  0xA2,  0x7A, 	/* 18330 */
+	0x35,  0x42,  0xF4,  0x3D,  0xAC,  0x5A,  0x95,  0x21,  0x03,  0x10,  0x49,  0x0B,  0x7C,  0x4D,  0x47,  0xD4, 	/* 18340 */
+	0x4F,  0xC7,  0x90,  0x51,  0x44,  0x94,  0x75,  0xEC,  0x72,  0x97,  0x21,  0x02,  0x3C,  0x22,  0x4F,  0xBC, 	/* 18350 */
+	0xAA,  0x4A,  0xBC,  0xF8,  0x02,  0x7E,  0x31,  0x02,  0xBC,  0x39,  0x0C,  0x7E,  0x99,  0x27,  0xE2,  0x00, 	/* 18360 */
+	0xFB,  0xEA,  0xA2,  0xAB,  0xEF,  0xA0,  0x23,  0xF3,  0x35,  0x2B,  0xF3,  0xD5,  0xC5,  0x50,  0x93,  0x9F, 	/* 18370 */
+	0x20,  0x02,  0x7E,  0x25,  0x2F,  0xFE,  0xAD,  0x2A,  0xFE,  0xFA,  0x42,  0x3C,  0x32,  0x42,  0xBC,  0x3A, 	/* 18380 */
+	0x4C,  0x6C,  0xA0,  0x27,  0xE2,  0x00,  0x23,  0xCF,  0xA4,  0xAB,  0xCA,  0x80,  0xFF,  0xE2,  0x52,  0x37, 	/* 18390 */
+	0xE2,  0xD2,  0x3D,  0x2C,  0x7E,  0xA3,  0x22,  0x42,  0x24,  0x22,  0x7F,  0xF8,  0xAA,  0xEA,  0xA2,  0xFB, 	/* 183A0 */
+	0xC2,  0x2F,  0x32,  0xA2,  0xCA,  0x38,  0xAC,  0x36,  0xA6,  0x20,  0x02,  0x7E,  0x25,  0x2F,  0xF6,  0xAC, 	/* 183B0 */
+	0x0A,  0xCE,  0xFF,  0x22,  0x4A,  0x34,  0x42,  0xF4,  0x3C,  0xAC,  0x52,  0xA8,  0x00,  0x07,  0xF0,  0x09, 	/* 183C0 */
+	0x07,  0xF2,  0x08,  0xA1,  0x06,  0x20,  0x8F,  0xBE,  0xAA,  0xAF,  0xBE,  0x28,  0xAF,  0x7D,  0xAA,  0x20, 	/* 183D0 */
+	0x02,  0x3C,  0xFA,  0x4A,  0xBC,  0xAA,  0x4F,  0xFF,  0x22,  0x03,  0x7E,  0x2A,  0xA3,  0xCA,  0xC5,  0x20, 	/* 183E0 */
+	0x0C,  0xAE,  0x22,  0x02,  0x3E,  0x24,  0x0F,  0xBC,  0xAA,  0x4A,  0xBC,  0xFA,  0x42,  0x3C,  0x31,  0xC2, 	/* 183F0 */
+	0xE4,  0x39,  0x8C,  0x66,  0xB4,  0x22,  0x02,  0x2E,  0x27,  0xAF,  0xAA,  0xAA,  0xEA,  0xAA,  0xFF,  0xA2, 	/* 18400 */
+	0x5E,  0x35,  0xA2,  0xFA,  0x39,  0x2C,  0x66,  0xB6,  0x25,  0x42,  0x54,  0xFF,  0xEA,  0xD4,  0xAD,  0xCF, 	/* 18410 */
+	0xC0,  0x27,  0xE3,  0x10,  0x2F,  0xE3,  0xB4,  0xCD,  0x20,  0x10,  0xB8,  0x23,  0xC2,  0x24,  0x23,  0xCF, 	/* 18420 */
+	0xB4,  0xAB,  0x4A,  0xFE,  0xFC,  0x22,  0x7A,  0x36,  0xA2,  0xEA,  0x3F,  0xAC,  0x46,  0xBF,  0x27,  0xC2, 	/* 18430 */
+	0x54,  0x27,  0xCF,  0xD4,  0xAF,  0xEA,  0xD2,  0xFF,  0xE2,  0x52,  0x37,  0xE2,  0x90,  0x39,  0x2C,  0x4E, 	/* 18440 */
+	0x82,  0x22,  0x02,  0x2E,  0x2F,  0xAF,  0x9A,  0xAF,  0xCA,  0x9A,  0xFF,  0xA2,  0xDA,  0x2A,  0xA3,  0xEE, 	/* 18450 */
+	0xC9,  0x80,  0x08,  0x8D,  0xFC,  0x80,  0x08,  0x78,  0x84,  0xBE,  0x7A,  0xA0,  0x2A,  0xFF,  0xEB,  0x48, 	/* 18460 */
+	0xDC,  0xCB,  0xCA,  0x94,  0xE9,  0x79,  0x9F,  0x20,  0x02,  0x7E,  0x24,  0x2F,  0xBC,  0xAA,  0x4A,  0xBC, 	/* 18470 */
+	0xFA,  0x42,  0x3C,  0x31,  0x02,  0xFE,  0x3A,  0x4C,  0x42,  0xA2,  0x11,  0x05,  0x54,  0x2A,  0x84,  0x44, 	/* 18480 */
+	0xFF,  0xE8,  0x42,  0xBF,  0xA2,  0x48,  0x3F,  0x80,  0x48,  0x07,  0xCF,  0x82,  0xAB,  0x11,  0x07,  0xDE, 	/* 18490 */
+	0x12,  0x4F,  0xD8,  0x55,  0x49,  0x22,  0x7F,  0x84,  0x48,  0x7F,  0x80,  0x48,  0x07,  0xCF,  0x82,  0xAF, 	/* 184A0 */
+	0x12,  0x07,  0xBE,  0x12,  0x4F,  0xD4,  0x28,  0x84,  0x94,  0x1A,  0x27,  0xFC,  0x44,  0x47,  0xFC,  0x04, 	/* 184B0 */
+	0x4F,  0xFA,  0xB3,  0x29,  0x22,  0x54,  0x2F,  0xEF,  0x82,  0xAB,  0xCA,  0xA4,  0xFB,  0xC2,  0x10,  0x37, 	/* 184C0 */
+	0xC2,  0x90,  0x39,  0x0C,  0xFE,  0xBA,  0x20,  0x02,  0x3E,  0x22,  0xAF,  0xBE,  0xAA,  0xAA,  0xBE,  0xF8, 	/* 184D0 */
+	0x82,  0x34,  0x37,  0xE2,  0xAC,  0x3C,  0xAC,  0x48,  0xBB,  0x27,  0xC2,  0x54,  0x2F,  0xEF,  0x54,  0xAF, 	/* 184E0 */
+	0xEA,  0x92,  0xFF,  0xE2,  0x20,  0x37,  0xE2,  0xA4,  0x39,  0x8C,  0x64,  0xBD,  0x0F,  0x81,  0x90,  0x66, 	/* 184F0 */
+	0x01,  0x98,  0xE2,  0x60,  0x90,  0x26,  0x0F,  0xBE,  0xAA,  0xAF,  0xBE,  0x28,  0xAF,  0x7D,  0x80,  0x21, 	/* 18500 */
+	0x02,  0xFE,  0x21,  0x0F,  0xAC,  0xAD,  0x2A,  0xAC,  0xFF,  0xA2,  0x10,  0x37,  0xE2,  0x90,  0x39,  0x0C, 	/* 18510 */
+	0x90,  0x84,  0x22,  0x0F,  0xF8,  0x52,  0x8F,  0xE8,  0x25,  0x8F,  0x8A,  0x24,  0x67,  0xF8,  0x44,  0x87, 	/* 18520 */
+	0xF8,  0x04,  0x4F,  0xFA,  0x86,  0x22,  0x82,  0xFE,  0x22,  0x8F,  0xBC,  0xAA,  0x4A,  0xBC,  0xFA,  0x42, 	/* 18530 */
+	0x3C,  0x31,  0x02,  0xFE,  0x3A,  0x4C,  0x42,  0x87,  0x11,  0x0F,  0xFE,  0x20,  0x83,  0xF8,  0x20,  0x8F, 	/* 18540 */
+	0xFE,  0x24,  0x87,  0xFC,  0xA4,  0xA3,  0xF8,  0x04,  0xCF,  0xF2,  0x8B,  0x20,  0xC2,  0x70,  0x25,  0x2F, 	/* 18550 */
+	0xB4,  0xAF,  0xEA,  0x98,  0xFB,  0x42,  0x52,  0x31,  0x02,  0xAA,  0x3D,  0x2C,  0x8E,  0x90,  0x29,  0x22, 	/* 18560 */
+	0x54,  0x2F,  0xEF,  0x82,  0xAB,  0xCA,  0xA4,  0xFB,  0xC2,  0x10,  0x37,  0xE2,  0xD2,  0x3D,  0x4C,  0x50, 	/* 18570 */
+	0x92,  0x22,  0x82,  0x7C,  0x22,  0x8F,  0xFE,  0xAA,  0x8A,  0xC4,  0xFA,  0xA2,  0x28,  0x37,  0xE2,  0xA8, 	/* 18580 */
+	0x3C,  0x8C,  0x88,  0xA0,  0x20,  0xC2,  0xF0,  0x25,  0x2F,  0xB4,  0xAF,  0xEA,  0xB4,  0xFD,  0x22,  0x7D, 	/* 18590 */
+	0x35,  0x42,  0xFC,  0x3D,  0x4C,  0x7C,  0xAF,  0x23,  0xC2,  0x10,  0x27,  0xEF,  0xA4,  0xAF,  0xEA,  0xA4, 	/* 185A0 */
+	0xFF,  0xE2,  0x00,  0x37,  0xE2,  0xA8,  0x3A,  0xAC,  0x46,  0xB2,  0x04,  0x07,  0xF8,  0x44,  0x87,  0xF8, 	/* 185B0 */
+	0x04,  0x4F,  0xFA,  0x20,  0x8F,  0xBE,  0xAA,  0xAF,  0xBE,  0x28,  0xAF,  0x7D,  0xB6,  0x2F,  0x02,  0xAE, 	/* 185C0 */
+	0x2E,  0xAF,  0xAA,  0xAE,  0xAA,  0xAE,  0xFA,  0x02,  0x7C,  0x31,  0x02,  0xFC,  0x39,  0x0C,  0x7E,  0xB7, 	/* 185D0 */
+	0x29,  0x22,  0x54,  0x2F,  0xEF,  0x82,  0xAB,  0xCA,  0xA4,  0xFB,  0xC2,  0x7E,  0x34,  0xA2,  0xFE,  0x3C, 	/* 185E0 */
+	0xAC,  0x7E,  0xB9,  0x3B,  0xED,  0x0A,  0x7D,  0x45,  0x7E,  0x7C,  0x84,  0x7E,  0x8C,  0x83,  0xF8,  0x24, 	/* 185F0 */
+	0x83,  0xF8,  0x04,  0xCF,  0xF2,  0xBB,  0x22,  0x82,  0xFE,  0x21,  0x0F,  0xFE,  0xA9,  0x0A,  0xFE,  0xFC, 	/* 18600 */
+	0xA2,  0xFF,  0x24,  0xC2,  0xEA,  0x35,  0x6C,  0xC2,  0xBE,  0x23,  0x82,  0x50,  0x2F,  0xEF,  0x98,  0xAE, 	/* 18610 */
+	0x6A,  0xB8,  0xF8,  0x02,  0xFE,  0x28,  0x03,  0xBC,  0xCA,  0x41,  0x3C,  0x85,  0x27,  0xC2,  0x54,  0x27, 	/* 18620 */
+	0xCF,  0x28,  0xAE,  0xEA,  0xAA,  0xFE,  0xE2,  0xAA,  0x2E,  0xE3,  0x28,  0x3A,  0x2C,  0x9E,  0x8D,  0x20, 	/* 18630 */
+	0x42,  0xF4,  0x29,  0x4F,  0xF7,  0xA9,  0xDA,  0xF6,  0xF4,  0x42,  0xF4,  0x29,  0x42,  0xFA,  0x39,  0x2E, 	/* 18640 */
+	0x61,  0x8E,  0x22,  0x82,  0xFE,  0x22,  0x8F,  0xFE,  0xAB,  0x4A,  0xD2,  0xFF,  0xD2,  0x10,  0x32,  0x42, 	/* 18650 */
+	0xFE,  0x3A,  0x4C,  0x44,  0x8F,  0x24,  0x02,  0x7E,  0x2A,  0xAF,  0x4A,  0xAF,  0x6A,  0xB0,  0xFF,  0xE2, 	/* 18660 */
+	0xB4,  0x2F,  0x43,  0x9E,  0xC9,  0x41,  0x34,  0x91,  0x25,  0xA2,  0xEC,  0x24,  0x8F,  0xB4,  0xAF,  0xEA, 	/* 18670 */
+	0x92,  0xF9,  0x02,  0x7E,  0x33,  0x82,  0xD4,  0x39,  0x2C,  0x50,  0x95,  0x27,  0xC2,  0x10,  0x2F,  0xEF, 	/* 18680 */
+	0x92,  0xAB,  0xAA,  0x80,  0xFF,  0xE2,  0x20,  0x37,  0xE2,  0xAA,  0x3A,  0xAC,  0x86,  0x96,  0x22,  0x82, 	/* 18690 */
+	0xFE,  0x22,  0x4F,  0xBE,  0xAE,  0x8A,  0xBE,  0xFA,  0x82,  0x3E,  0x32,  0x42,  0x98,  0x3A,  0x4C,  0xC2, 	/* 186A0 */
+	0xA1,  0x0F,  0x81,  0x10,  0xFF,  0xE1,  0xA4,  0x65,  0x81,  0xB6,  0x26,  0x8F,  0xBE,  0xAA,  0xAF,  0xBE, 	/* 186B0 */
+	0x28,  0xAF,  0x7D,  0xA2,  0x04,  0x07,  0xFC,  0x0A,  0x0F,  0xFE,  0x31,  0x8D,  0xF6,  0x11,  0x0F,  0xBE, 	/* 186C0 */
+	0xAA,  0xAF,  0xBE,  0x28,  0xAF,  0x7D,  0xA3,  0x20,  0x02,  0x7E,  0xFD,  0x4A,  0xFE,  0xAE,  0xAF,  0xFE, 	/* 186D0 */
+	0x24,  0x83,  0x7E,  0x2E,  0xA3,  0x6E,  0xCB,  0xE1,  0x22,  0xA7,  0x04,  0x07,  0xFC,  0x04,  0x0F,  0xFE, 	/* 186E0 */
+	0x9F,  0xA2,  0x88,  0x4F,  0x8F,  0xBE,  0xAA,  0xAF,  0xBE,  0x28,  0xAF,  0x7D,  0xB1,  0x04,  0x03,  0xF8, 	/* 186F0 */
+	0x24,  0xC3,  0xFA,  0xFB,  0xEA,  0xAA,  0xFB,  0xE2,  0x8A,  0xF7,  0xD7,  0xFC,  0x4A,  0x4F,  0xFE,  0xB6, 	/* 18700 */
+	0xFB,  0xE5,  0x14,  0xFB,  0xE5,  0x14,  0x9A,  0x63,  0xF8,  0x20,  0x8F,  0xFE,  0xAA,  0xAF,  0xBE,  0x24, 	/* 18710 */
+	0xAF,  0xBD,  0xB9,  0x04,  0x07,  0xFC,  0x24,  0x8F,  0xFE,  0x9F,  0xA2,  0x88,  0x4F,  0x8F,  0xBE,  0xAA, 	/* 18720 */
+	0xAF,  0xBE,  0x28,  0xAF,  0x7D,  0xBB,  0x46,  0x4B,  0xF2,  0x40,  0x4A,  0xEA,  0xEE,  0xE6,  0xAC,  0xDF, 	/* 18730 */
+	0x67,  0xF8,  0x44,  0x87,  0xF8,  0x04,  0x4F,  0xFA,  0x80,  0x08,  0x00,  0x80,  0x10,  0x07,  0xFC,  0x4A, 	/* 18740 */
+	0x44,  0xA4,  0x4A,  0x44,  0xA4,  0x4A,  0x44,  0xA4,  0xFF,  0xE0,  0x00,  0x82,  0x20,  0x04,  0x7E,  0xF9, 	/* 18750 */
+	0x2A,  0x92,  0xAD,  0x2A,  0xB2,  0xA9,  0xEA,  0x93,  0xBD,  0x2E,  0x12,  0x02,  0x20,  0x4C,  0x84,  0x10, 	/* 18760 */
+	0x02,  0x3C,  0x7D,  0x45,  0x54,  0x55,  0x45,  0x54,  0x57,  0xE5,  0x64,  0x5E,  0x4F,  0x24,  0x02,  0x40, 	/* 18770 */
+	0xFE,  0x86,  0x08,  0x07,  0xFC,  0x4A,  0x44,  0xA4,  0xFF,  0xE1,  0x20,  0x24,  0x4C,  0xE8,  0x15,  0x02, 	/* 18780 */
+	0x48,  0xC4,  0x60,  0x40,  0x8C,  0x20,  0x02,  0x7C,  0x40,  0x05,  0x00,  0x9F,  0xE2,  0x08,  0x20,  0x86, 	/* 18790 */
+	0x08,  0xA0,  0x82,  0x08,  0x20,  0x82,  0x18,  0x8D,  0x28,  0x02,  0x5E,  0x40,  0x0A,  0x80,  0x25,  0xE4, 	/* 187A0 */
+	0x04,  0xC0,  0x44,  0x24,  0x44,  0x44,  0x44,  0x48,  0x44,  0x8C,  0x92,  0x24,  0x02,  0x4E,  0x5F,  0x0A, 	/* 187B0 */
+	0x40,  0x25,  0xF4,  0x84,  0xDA,  0x44,  0x44,  0x4A,  0x45,  0x34,  0x7D,  0x44,  0x0C,  0x93,  0x24,  0x02, 	/* 187C0 */
+	0x6E,  0x45,  0x0B,  0xFE,  0x24,  0x44,  0x64,  0xD6,  0x45,  0x54,  0x55,  0x46,  0x44,  0x44,  0x44,  0x4C, 	/* 187D0 */
+	0x97,  0x24,  0x02,  0x5E,  0x5E,  0x0A,  0x5E,  0x24,  0x45,  0xF4,  0x44,  0x4D,  0xF4,  0x44,  0x44,  0x74, 	/* 187E0 */
+	0x58,  0x44,  0x0C,  0x99,  0x20,  0x03,  0xFE,  0x48,  0x0B,  0xE0,  0x2A,  0xF4,  0xA4,  0x7F,  0x4C,  0x04, 	/* 187F0 */
+	0x5E,  0x45,  0x24,  0x52,  0x45,  0xEC,  0x9B,  0x28,  0x03,  0xEE,  0x4A,  0x0B,  0xF0,  0x33,  0xF5,  0xE4, 	/* 18800 */
+	0xC4,  0x45,  0xE4,  0x54,  0x47,  0xF4,  0x44,  0x44,  0x4C,  0x9D,  0x26,  0x03,  0xCE,  0x44,  0x0B,  0xF0, 	/* 18810 */
+	0x34,  0xF5,  0xF4,  0xD5,  0x45,  0xF4,  0x44,  0x45,  0xE4,  0x47,  0x45,  0xCC,  0x9E,  0x24,  0x02,  0xFE, 	/* 18820 */
+	0x45,  0x0B,  0xFF,  0x29,  0x44,  0xF4,  0x7F,  0xCC,  0x44,  0x5F,  0x45,  0x54,  0x57,  0x44,  0x4C,  0xA1, 	/* 18830 */
+	0x24,  0x02,  0xEE,  0x52,  0x09,  0xF0,  0x35,  0xE5,  0xF4,  0xD5,  0x45,  0xF4,  0x44,  0x45,  0xF4,  0x4A, 	/* 18840 */
+	0x45,  0x0C,  0xA2,  0x3F,  0x02,  0xDE,  0x7F,  0x0A,  0xDF,  0x3F,  0x45,  0x24,  0x5F,  0x4F,  0x44,  0x5F, 	/* 18850 */
+	0x45,  0x44,  0x5F,  0x45,  0x0C,  0xA3,  0x04,  0x00,  0x40,  0xFF,  0xE0,  0x80,  0x0C,  0x41,  0x44,  0x32, 	/* 18860 */
+	0x8D,  0x20,  0x11,  0x01,  0x08,  0x1C,  0x47,  0x02,  0xA8,  0x04,  0x07,  0xFC,  0x04,  0x07,  0xFC,  0x04, 	/* 18870 */
+	0x0F,  0xFE,  0x14,  0x83,  0x28,  0xD3,  0x01,  0x10,  0x1C,  0x87,  0x06,  0xAB,  0x20,  0x82,  0x08,  0xF9, 	/* 18880 */
+	0x01,  0x14,  0x22,  0x42,  0x88,  0x71,  0x2A,  0xA2,  0x24,  0x42,  0x08,  0x23,  0x02,  0xC0,  0xB0,  0x04, 	/* 18890 */
+	0x0F,  0xFE,  0x00,  0x03,  0xF8,  0x20,  0x8F,  0xFE,  0x20,  0x83,  0xF8,  0x14,  0x43,  0x28,  0xDD,  0x83, 	/* 188A0 */
+	0x06,  0xB2,  0x23,  0x02,  0x10,  0xF9,  0x01,  0x7E,  0x25,  0x22,  0xD2,  0x76,  0xAA,  0xE6,  0x24,  0x22, 	/* 188B0 */
+	0x42,  0x24,  0x22,  0x46,  0xB5,  0x20,  0x02,  0x3E,  0xFA,  0x21,  0x22,  0x22,  0x22,  0xA2,  0x73,  0xEA, 	/* 188C0 */
+	0xA2,  0x22,  0x22,  0x22,  0x22,  0x22,  0x3E,  0xB7,  0x04,  0x0F,  0xFE,  0x04,  0x07,  0xFC,  0x44,  0x47, 	/* 188D0 */
+	0xFC,  0x04,  0x00,  0x84,  0x32,  0x8D,  0x10,  0x1C,  0x83,  0x06,  0xBD,  0x20,  0xC2,  0x78,  0xF9,  0x01, 	/* 188E0 */
+	0x10,  0x21,  0x02,  0xFE,  0x71,  0x0A,  0x90,  0x21,  0x02,  0x10,  0x27,  0xC2,  0x00,  0xBE,  0x04,  0x00, 	/* 188F0 */
+	0xA0,  0x3F,  0x8C,  0x06,  0x3F,  0x80,  0x10,  0x06,  0x0F,  0xFE,  0x34,  0x4D,  0x28,  0x1D,  0x87,  0x06, 	/* 18900 */
+	0xBF,  0x21,  0x02,  0x10,  0xFA,  0x80,  0xA8,  0x14,  0x42,  0xBA,  0x70,  0x0A,  0xFC,  0x20,  0x42,  0x08, 	/* 18910 */
+	0x20,  0x82,  0x10,  0x81,  0x04,  0x07,  0xFC,  0x04,  0x0F,  0xFE,  0x00,  0x03,  0xF8,  0x20,  0x83,  0xF8, 	/* 18920 */
+	0x1A,  0x4F,  0x18,  0x1C,  0x87,  0x06,  0x82,  0x21,  0x02,  0x10,  0xFB,  0xC1,  0x14,  0x21,  0x42,  0x94, 	/* 18930 */
+	0x77,  0xEA,  0x90,  0x21,  0x82,  0x28,  0x24,  0x42,  0x82,  0x88,  0x20,  0x02,  0x3C,  0xFA,  0x42,  0xA4, 	/* 18940 */
+	0x2A,  0x45,  0xBC,  0x80,  0x0F,  0xFE,  0x14,  0x43,  0x28,  0xDD,  0x83,  0x06,  0x8B,  0x15,  0x01,  0x48, 	/* 18950 */
+	0x23,  0xE7,  0xE0,  0xA1,  0x02,  0x0A,  0x24,  0x6F,  0xFE,  0x0A,  0x43,  0x18,  0xDC,  0x83,  0x06,  0x8D, 	/* 18960 */
+	0x22,  0x02,  0x20,  0xFB,  0xE1,  0x42,  0x27,  0xA2,  0xCA,  0x74,  0xAA,  0xFA,  0x24,  0xC2,  0x40,  0x24, 	/* 18970 */
+	0x22,  0x3E,  0x92,  0x20,  0x02,  0x3C,  0xFA,  0x41,  0x24,  0x22,  0x42,  0xBC,  0x72,  0x4A,  0xA4,  0x22, 	/* 18980 */
+	0x42,  0x3C,  0x20,  0x02,  0x7E,  0x96,  0x21,  0x02,  0x10,  0xF9,  0x01,  0x7E,  0x25,  0x22,  0xD2,  0x75, 	/* 18990 */
+	0x2A,  0xFE,  0x25,  0x22,  0x52,  0x25,  0x22,  0x7E,  0x97,  0x21,  0x02,  0x10,  0xFA,  0x81,  0x4C,  0x29, 	/* 189A0 */
+	0x22,  0x60,  0x70,  0x8A,  0x32,  0x2C,  0x42,  0x08,  0x23,  0x02,  0xC0,  0x99,  0x20,  0x82,  0x10,  0xFB, 	/* 189B0 */
+	0xE1,  0x22,  0x22,  0x22,  0xA2,  0x73,  0xEA,  0xA2,  0x22,  0x22,  0x22,  0x22,  0x22,  0x3E,  0x9E,  0x04, 	/* 189C0 */
+	0x0F,  0xFE,  0x0A,  0x03,  0x18,  0xFF,  0xE2,  0x08,  0x20,  0x83,  0xF8,  0x1A,  0x4F,  0x18,  0x1C,  0x87, 	/* 189D0 */
+	0x06,  0xA2,  0x21,  0x02,  0x54,  0xFD,  0x41,  0x12,  0x2F,  0xC3,  0x10,  0x69,  0x0A,  0x7E,  0x21,  0x02, 	/* 189E0 */
+	0x10,  0x21,  0x02,  0x10,  0xA4,  0x04,  0x0F,  0xFE,  0x3F,  0x80,  0x90,  0x7F,  0xC0,  0xA8,  0x33,  0x0C, 	/* 189F0 */
+	0x60,  0x0E,  0x03,  0x24,  0xED,  0x83,  0x0C,  0xAB,  0x21,  0x02,  0x10,  0xF7,  0xE1,  0x52,  0x25,  0x42, 	/* 18A00 */
+	0xFC,  0x74,  0x4A,  0xE8,  0x25,  0x82,  0x98,  0x32,  0x42,  0xC2,  0xAE,  0x21,  0x02,  0x10,  0xFA,  0x01, 	/* 18A10 */
+	0x3E,  0x24,  0x82,  0x88,  0x72,  0xCA,  0xAA,  0x24,  0xA2,  0x08,  0x20,  0x82,  0x18,  0xB0,  0x1F,  0x81, 	/* 18A20 */
+	0x48,  0x12,  0x8F,  0xFE,  0x24,  0x82,  0x28,  0x3F,  0x00,  0x50,  0xFF,  0xE3,  0x24,  0xDD,  0x83,  0x06, 	/* 18A30 */
+	0xB1,  0x22,  0x82,  0x2C,  0xFA,  0xA1,  0x48,  0x2F,  0xE3,  0x48,  0x74,  0x8A,  0xC8,  0x25,  0x42,  0x54, 	/* 18A40 */
+	0x26,  0x22,  0x41,  0xB4,  0x21,  0x02,  0x10,  0xF7,  0xE1,  0x28,  0x27,  0xC2,  0x82,  0x7F,  0xCA,  0xA0, 	/* 18A50 */
+	0x23,  0xC2,  0x04,  0x20,  0x42,  0x18,  0xB5,  0x22,  0x02,  0x26,  0xFD,  0xC1,  0x48,  0x2C,  0x82,  0x48, 	/* 18A60 */
+	0x77,  0xFA,  0xC8,  0x24,  0x82,  0x48,  0x27,  0xE2,  0x40,  0xB7,  0x21,  0x02,  0x10,  0xFA,  0x81,  0x28, 	/* 18A70 */
+	0x24,  0x43,  0xBA,  0x70,  0x0A,  0xFC,  0x24,  0x42,  0x44,  0x24,  0x42,  0x7C,  0xBF,  0x21,  0x02,  0x10, 	/* 18A80 */
+	0xF7,  0xC1,  0x10,  0x21,  0x02,  0xFE,  0x71,  0x0A,  0x90,  0x27,  0xC2,  0x10,  0x21,  0x02,  0xFE,  0x81, 	/* 18A90 */
+	0x11,  0x47,  0xD2,  0x11,  0x0F,  0xFE,  0x11,  0x0F,  0xF4,  0x23,  0x47,  0x48,  0xA8,  0x82,  0x5A,  0x32, 	/* 18AA0 */
+	0x66,  0x42,  0x82,  0x7C,  0x22,  0x12,  0x3D,  0x26,  0x52,  0x99,  0x23,  0x02,  0xC4,  0x6F,  0xFE,  0x0A, 	/* 18AB0 */
+	0x43,  0x98,  0xCE,  0x83,  0x06,  0x83,  0x21,  0x02,  0x1C,  0xF9,  0x01,  0x10,  0x2F,  0xE2,  0x80,  0x77, 	/* 18AC0 */
+	0xEA,  0x90,  0x21,  0xC2,  0x12,  0x21,  0x02,  0x10,  0x84,  0x22,  0x02,  0x2E,  0xF4,  0x01,  0xA0,  0x23, 	/* 18AD0 */
+	0xF2,  0xC4,  0x74,  0x4A,  0xC4,  0x24,  0x42,  0x44,  0x24,  0x42,  0x4C,  0x85,  0x22,  0x0A,  0x20,  0x7F, 	/* 18AE0 */
+	0xE2,  0x20,  0x62,  0x0A,  0xFC,  0x04,  0x0F,  0xFE,  0x1A,  0x42,  0x98,  0xCE,  0x83,  0x86,  0x8F,  0x04, 	/* 18AF0 */
+	0x0F,  0xFE,  0x24,  0x83,  0xF8,  0x24,  0x87,  0xFC,  0x04,  0x0F,  0xFE,  0x34,  0x4D,  0x28,  0x1D,  0x87, 	/* 18B00 */
+	0x06,  0x94,  0x04,  0x0F,  0xFE,  0x34,  0xCD,  0x30,  0x7F,  0xE1,  0x10,  0x7F,  0xC4,  0xA4,  0x73,  0xC4, 	/* 18B10 */
+	0xE4,  0x4A,  0x44,  0xEC,  0x95,  0x22,  0x82,  0x24,  0xFA,  0x41,  0x54,  0x21,  0x02,  0xA8,  0x74,  0x4A, 	/* 18B20 */
+	0xFE,  0x34,  0x52,  0x44,  0x24,  0x42,  0x7C,  0x98,  0x04,  0x8F,  0xFE,  0x64,  0x41,  0xE8,  0x35,  0x8C, 	/* 18B30 */
+	0x46,  0x04,  0x0F,  0xFF,  0x0A,  0x23,  0x94,  0xCE,  0x83,  0x06,  0x99,  0x20,  0x02,  0x3C,  0xF9,  0x41, 	/* 18B40 */
+	0x14,  0x27,  0xE2,  0x94,  0x77,  0xCA,  0xA0,  0x23,  0xE2,  0x52,  0x29,  0x22,  0x1E,  0x9C,  0x21,  0x42, 	/* 18B50 */
+	0x12,  0xF7,  0xE1,  0x10,  0x27,  0xE2,  0xD2,  0x77,  0xEA,  0xD2,  0x27,  0xE2,  0x52,  0x25,  0x22,  0x56, 	/* 18B60 */
+	0x9D,  0x51,  0x07,  0x10,  0x1F,  0xEF,  0x10,  0x51,  0x09,  0x7C,  0x04,  0x0F,  0xFE,  0x34,  0x4D,  0x28, 	/* 18B70 */
+	0x1D,  0x86,  0x06,  0x9F,  0x41,  0x02,  0x54,  0x85,  0x24,  0xBA,  0x31,  0x0C,  0xE0,  0x04,  0x0F,  0xFE, 	/* 18B80 */
+	0x0A,  0x43,  0x98,  0xCE,  0x83,  0x86,  0xA1,  0x20,  0x02,  0x7E,  0xF5,  0x21,  0x7E,  0x25,  0x22,  0xD2, 	/* 18B90 */
+	0x77,  0xEA,  0x90,  0x27,  0xC2,  0x10,  0x21,  0x02,  0xFE,  0xA8,  0x21,  0x02,  0x20,  0xFF,  0xE1,  0x52, 	/* 18BA0 */
+	0x27,  0xE2,  0xD2,  0x77,  0xEA,  0xA8,  0x24,  0x82,  0xFE,  0x20,  0x82,  0x08,  0xB2,  0x20,  0x02,  0x7E, 	/* 18BB0 */
+	0xF9,  0x01,  0xFE,  0x29,  0x22,  0xFE,  0x7B,  0x6A,  0xB6,  0x2D,  0xA2,  0x92,  0x29,  0x22,  0x96,  0xB3, 	/* 18BC0 */
+	0x24,  0x81,  0x50,  0xFF,  0xE8,  0x02,  0xBF,  0xA2,  0x08,  0x3F,  0x80,  0x40,  0xFF,  0xE3,  0x24,  0xDD, 	/* 18BD0 */
+	0x83,  0x06,  0xB4,  0x09,  0x07,  0x9E,  0x09,  0x07,  0x9C,  0x09,  0x0F,  0x9E,  0x15,  0x0F,  0xFE,  0x1A, 	/* 18BE0 */
+	0x43,  0x18,  0xDC,  0x83,  0x06,  0xB8,  0x20,  0x02,  0x7E,  0xF5,  0x21,  0x7E,  0x25,  0x22,  0xFE,  0x71, 	/* 18BF0 */
+	0x0A,  0xFF,  0x23,  0x82,  0x54,  0x29,  0x22,  0x10,  0xB9,  0x04,  0x0F,  0xFE,  0x24,  0x83,  0xF8,  0x24, 	/* 18C00 */
+	0x87,  0xFC,  0x04,  0x0F,  0xFE,  0x54,  0xCB,  0x32,  0xDD,  0x83,  0x06,  0xBC,  0x20,  0x02,  0x3C,  0xFA, 	/* 18C10 */
+	0x41,  0x3C,  0x22,  0x42,  0xBC,  0x71,  0x0A,  0xBE,  0x26,  0xA2,  0xAA,  0x25,  0x22,  0x0C,  0xBD,  0x50, 	/* 18C20 */
+	0x47,  0xD4,  0x91,  0x47,  0xD4,  0x55,  0x45,  0xC4,  0x14,  0xCF,  0xFE,  0x0C,  0x83,  0x30,  0xDD,  0x83, 	/* 18C30 */
+	0x06,  0xBE,  0x20,  0x02,  0x7E,  0xF4,  0x21,  0x7E,  0x24,  0x82,  0xFE,  0x74,  0x8A,  0xFE,  0x26,  0x22, 	/* 18C40 */
+	0xA2,  0x2A,  0x23,  0x3E,  0x82,  0x24,  0x82,  0x48,  0xFF,  0x81,  0x48,  0x2F,  0xC2,  0xCA,  0x74,  0xAA, 	/* 18C50 */
+	0xF8,  0x24,  0x82,  0x78,  0x2C,  0x82,  0x08,  0x84,  0x21,  0x02,  0x7E,  0xF9,  0x01,  0x7C,  0x29,  0x43, 	/* 18C60 */
+	0x7E,  0x69,  0x4A,  0x7E,  0x22,  0x42,  0x64,  0x21,  0x82,  0xE4,  0x87,  0x24,  0x02,  0x7E,  0xFC,  0x41, 	/* 18C70 */
+	0x7C,  0x24,  0x42,  0xFC,  0x72,  0x0A,  0xBC,  0x24,  0x82,  0xB0,  0x26,  0x83,  0x86,  0x8A,  0x20,  0xC2, 	/* 18C80 */
+	0x70,  0xFF,  0xE1,  0x42,  0x27,  0xE2,  0xC0,  0x77,  0xEA,  0xEA,  0x27,  0xE2,  0xAA,  0x32,  0xA2,  0x26, 	/* 18C90 */
+	0x8C,  0x20,  0x02,  0x7E,  0xFD,  0x21,  0x10,  0x2F,  0xE3,  0x52,  0x6F,  0xEA,  0x52,  0x27,  0xE2,  0x10, 	/* 18CA0 */
+	0x2F,  0xE2,  0x10,  0x90,  0x27,  0xC2,  0x44,  0xF7,  0xC1,  0x44,  0x27,  0xC2,  0xA0,  0x77,  0xEA,  0xCA, 	/* 18CB0 */
+	0x37,  0x22,  0x4A,  0x23,  0xA2,  0x0C,  0x92,  0x04,  0x0F,  0xFE,  0x10,  0x01,  0x7C,  0x24,  0x46,  0xFE, 	/* 18CC0 */
+	0xA3,  0x42,  0x52,  0x1A,  0x47,  0x28,  0x19,  0x87,  0x06,  0x93,  0x22,  0x02,  0x7E,  0xF6,  0x21,  0x62, 	/* 18CD0 */
+	0x2F,  0xE2,  0xC8,  0x77,  0xFA,  0xC8,  0x25,  0xC2,  0x5A,  0x26,  0x92,  0x48,  0x9D,  0x22,  0x22,  0x92, 	/* 18CE0 */
+	0xF4,  0x41,  0x7C,  0x25,  0x43,  0x7C,  0x65,  0x4B,  0x7C,  0x21,  0x02,  0xFE,  0x21,  0x02,  0x10,  0x9E, 	/* 18CF0 */
+	0x20,  0x02,  0x7C,  0xF5,  0x41,  0x6C,  0x24,  0x42,  0xFC,  0x70,  0x0A,  0xFE,  0x2A,  0xA2,  0xAA,  0x2A, 	/* 18D00 */
+	0xA3,  0xFF,  0xA5,  0x20,  0x02,  0x7E,  0xFC,  0x01,  0x7F,  0x26,  0xA3,  0xA4,  0x6B,  0x2B,  0x04,  0x2F, 	/* 18D10 */
+	0xE2,  0x24,  0x20,  0x42,  0x0C,  0xAA,  0x28,  0x02,  0x5E,  0xF1,  0x21,  0x9E,  0x25,  0x22,  0x9E,  0x71, 	/* 18D20 */
+	0xAA,  0xD4,  0x25,  0x22,  0x59,  0x2A,  0x03,  0x1F,  0xAB,  0x40,  0xC4,  0xF8,  0xF8,  0xE2,  0xBE,  0x2A, 	/* 18D30 */
+	0x85,  0xBF,  0xEA,  0x85,  0xAF,  0x55,  0x45,  0x54,  0x69,  0x55,  0x23,  0xB6,  0x20,  0x02,  0xFE,  0xF3, 	/* 18D40 */
+	0x61,  0x5A,  0x23,  0x62,  0xDA,  0x72,  0x0A,  0xFC,  0x24,  0x42,  0x7C,  0x24,  0x42,  0x7C,  0xB8,  0x27, 	/* 18D50 */
+	0xC2,  0x54,  0xFF,  0xE1,  0x54,  0x2F,  0xE3,  0x92,  0x6F,  0xEB,  0x10,  0x2F,  0xE2,  0x64,  0x21,  0x82, 	/* 18D60 */
+	0x64,  0xBB,  0x08,  0x0F,  0xFC,  0x22,  0x07,  0x78,  0xFA,  0x86,  0xE8,  0xB5,  0xAC,  0x86,  0x18,  0x8E, 	/* 18D70 */
+	0x50,  0x3B,  0x06,  0x0C,  0x81,  0x20,  0x82,  0xE8,  0xF3,  0x41,  0x3E,  0x2C,  0x83,  0xBE,  0x6E,  0xAB, 	/* 18D80 */
+	0x3E,  0x22,  0x82,  0x2A,  0x22,  0xE2,  0xDA,  0x83,  0x04,  0x0F,  0xFE,  0x27,  0xC4,  0x44,  0x7F,  0xE4, 	/* 18D90 */
+	0x38,  0x75,  0x44,  0x92,  0x34,  0x4D,  0x28,  0x1D,  0x83,  0x06,  0x84,  0x04,  0x0F,  0xFE,  0x4A,  0x47, 	/* 18DA0 */
+	0xBC,  0x11,  0x07,  0xFC,  0x11,  0x0F,  0xFE,  0x0C,  0x4F,  0x28,  0x11,  0x83,  0x86,  0x8C,  0x2E,  0xE2, 	/* 18DB0 */
+	0xAA,  0xFE,  0xE1,  0x00,  0x27,  0xC2,  0xD4,  0x77,  0xCA,  0xD4,  0x27,  0xC2,  0x10,  0x2F,  0xE2,  0x10, 	/* 18DC0 */
+	0x8D,  0x24,  0x82,  0x50,  0xF7,  0xE1,  0xD0,  0x27,  0xC2,  0xD0,  0x77,  0xEA,  0x90,  0x2F,  0xE2,  0x34, 	/* 18DD0 */
+	0x25,  0x22,  0x10,  0x96,  0x21,  0x02,  0x7E,  0xF6,  0xE1,  0x5A,  0x17,  0xE2,  0x5A,  0x6E,  0xEB,  0x4A, 	/* 18DE0 */
+	0x28,  0x82,  0x7F,  0x21,  0x42,  0xE3,  0x9E,  0x79,  0x04,  0xFC,  0x7A,  0x84,  0x7E,  0x79,  0x0A,  0xFC, 	/* 18DF0 */
+	0x39,  0x0F,  0xFE,  0x34,  0x4D,  0x28,  0x1D,  0x87,  0x06,  0x9F,  0x44,  0x85,  0xFE,  0xE4,  0x82,  0xFC, 	/* 18E00 */
+	0x34,  0xA4,  0xFE,  0x60,  0x0F,  0xFE,  0x49,  0x44,  0x92,  0x51,  0x24,  0x30,  0xA0,  0x29,  0x22,  0x54, 	/* 18E10 */
+	0xFF,  0xE1,  0x82,  0x23,  0xC2,  0xA4,  0x73,  0xCA,  0xFE,  0x25,  0x22,  0x7E,  0x25,  0x22,  0x7E,  0xA4, 	/* 18E20 */
+	0x2F,  0x42,  0xA4,  0xFF,  0x61,  0x98,  0x2F,  0x03,  0xAE,  0x6F,  0x0B,  0x00,  0x2F,  0xE2,  0xAA,  0x2A, 	/* 18E30 */
+	0xA3,  0xFF,  0xA6,  0x27,  0xC2,  0x10,  0xFF,  0xE1,  0x92,  0x2B,  0xA3,  0x00,  0x6F,  0xEB,  0x20,  0x2F, 	/* 18E40 */
+	0xE2,  0xAA,  0x2A,  0xA2,  0x86,  0xAA,  0x22,  0x82,  0xFE,  0xF2,  0x81,  0xFE,  0x1A,  0xA2,  0xFE,  0x30, 	/* 18E50 */
+	0x86,  0xFE,  0xA6,  0xA2,  0x54,  0x24,  0xC2,  0x92,  0xAD,  0x24,  0x02,  0x5F,  0xFE,  0x81,  0x5E,  0x25, 	/* 18E60 */
+	0x22,  0xFE,  0x71,  0x2A,  0xFE,  0x2B,  0x22,  0xBE,  0x2E,  0xA2,  0x31,  0xAF,  0x44,  0x05,  0xFE,  0xEA, 	/* 18E70 */
+	0xA2,  0xAE,  0x3F,  0xA4,  0x4A,  0x5F,  0xEE,  0x4A,  0x5E,  0xE4,  0x4C,  0x45,  0x54,  0x63,  0xB2,  0x23, 	/* 18E80 */
+	0x8F,  0xA0,  0x53,  0xCF,  0x84,  0x4B,  0xC7,  0xA0,  0x4B,  0xC5,  0xA2,  0xFF,  0xE3,  0x4C,  0xD3,  0x03, 	/* 18E90 */
+	0x8E,  0xB4,  0x4E,  0xE4,  0xAA,  0xFE,  0xE1,  0xAA,  0x2E,  0xE2,  0x92,  0x5F,  0xEE,  0xD6,  0x5F,  0xE4, 	/* 18EA0 */
+	0xBA,  0x4D,  0x64,  0x96,  0xB7,  0x21,  0x02,  0x7E,  0xF5,  0x21,  0x7E,  0x15,  0xA2,  0xFF,  0x32,  0x46, 	/* 18EB0 */
+	0xDA,  0xA8,  0x92,  0x7E,  0x20,  0x82,  0x18,  0xBE,  0x00,  0x0F,  0xFE,  0x12,  0x01,  0x20,  0xFF,  0xC9, 	/* 18EC0 */
+	0x24,  0x92,  0x49,  0x24,  0x9E,  0x48,  0x04,  0x80,  0x48,  0x04,  0xBF,  0x00,  0x0F,  0xFE,  0x0A,  0x00, 	/* 18ED0 */
+	0xA0,  0x7F,  0xC4,  0xA4,  0x4A,  0x45,  0x1C,  0x60,  0x44,  0x04,  0x7F,  0xC0,  0x00,  0x81,  0x00,  0x0F, 	/* 18EE0 */
+	0xFE,  0x0A,  0x07,  0xFC,  0x4A,  0x47,  0xFC,  0x08,  0x0F,  0xFE,  0x11,  0x01,  0xA0,  0x07,  0x07,  0x8C, 	/* 18EF0 */
+	0x83,  0xFF,  0xE1,  0x10,  0x7F,  0xC5,  0x14,  0x5F,  0x40,  0x00,  0x3F,  0x82,  0x08,  0x3F,  0x82,  0x08, 	/* 18F00 */
+	0xFF,  0xE0,  0x40,  0x86,  0xFF,  0xE0,  0xA0,  0x7F,  0xC4,  0xA4,  0x7F,  0xC2,  0x80,  0x4F,  0xEA,  0xA8, 	/* 18F10 */
+	0x27,  0xC5,  0x88,  0xC3,  0x05,  0xCE,  0x87,  0xFF,  0xE0,  0xA0,  0x7F,  0xC4,  0xA4,  0x7F,  0xE2,  0x92, 	/* 18F20 */
+	0x7D,  0xE2,  0x92,  0x7D,  0xE5,  0x52,  0xFF,  0x21,  0x26,  0x88,  0x7F,  0xC1,  0x10,  0xFF,  0xE9,  0x12, 	/* 18F30 */
+	0x7F,  0x04,  0x9E,  0x7A,  0x44,  0xE4,  0xFD,  0x82,  0x88,  0x2B,  0x45,  0xC2,  0x8A,  0x00,  0x0F,  0xFE, 	/* 18F40 */
+	0x0A,  0x07,  0xFC,  0x4A,  0x4F,  0xFE,  0x2A,  0x87,  0xFE,  0x56,  0x8F,  0xFE,  0x12,  0xA1,  0x4C,  0x8B, 	/* 18F50 */
+	0x00,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x0A,  0x01,  0x22,  0x22, 	/* 18F60 */
+	0x2C,  0x1E,  0x8F,  0x27,  0xC2,  0x44,  0xFC,  0x42,  0x7C,  0x24,  0x4F,  0xFC,  0x24,  0x42,  0x7C,  0x32, 	/* 18F70 */
+	0x84,  0xA8,  0x44,  0xA8,  0x86,  0x93,  0x03,  0x87,  0xC8,  0x24,  0x44,  0x42,  0xBF,  0x82,  0x08,  0x3F, 	/* 18F80 */
+	0x82,  0x08,  0x3F,  0x80,  0xA0,  0x32,  0x2C,  0x1E,  0x96,  0x20,  0x02,  0x7C,  0xF4,  0x41,  0x7C,  0x24, 	/* 18F90 */
+	0x42,  0x7C,  0x74,  0x4A,  0xFC,  0x22,  0x82,  0x28,  0x24,  0xA2,  0x86,  0x97,  0x03,  0xEF,  0xA2,  0x0A, 	/* 18FA0 */
+	0x2E,  0xBE,  0x0A,  0x2E,  0xBE,  0xAA,  0x2A,  0xBE,  0xE9,  0x40,  0x94,  0x0A,  0x51,  0xC3,  0x98,  0x20, 	/* 18FB0 */
+	0x02,  0x7C,  0x3C,  0x42,  0x7C,  0x24,  0x42,  0x7C,  0xFC,  0x48,  0xC4,  0x8F,  0xCF,  0xA8,  0x04,  0xA1, 	/* 18FC0 */
+	0x86,  0x9A,  0x28,  0x81,  0x50,  0xFF,  0xEA,  0x0A,  0xBF,  0xA2,  0x08,  0x3F,  0x82,  0x08,  0x3F,  0x80, 	/* 18FD0 */
+	0xA0,  0x32,  0x2C,  0x1E,  0xA1,  0x00,  0x07,  0xFC,  0x14,  0x45,  0x7C,  0x54,  0x45,  0xFC,  0xB4,  0x49, 	/* 18FE0 */
+	0x7C,  0x1A,  0x8E,  0x2A,  0x04,  0xA1,  0x86,  0xA6,  0x10,  0x02,  0x9E,  0x45,  0x2B,  0xBE,  0x01,  0x2E, 	/* 18FF0 */
+	0xBE,  0xAB,  0x2F,  0x52,  0xB5,  0xEE,  0xAC,  0xAB,  0x5A,  0xA7,  0xA7,  0xFA,  0x09,  0x3E,  0xFC,  0x09, 	/* 19000 */
+	0x3E,  0xF8,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xFA,  0x1A,  0x2E,  0x1E,  0xA9,  0x20,  0x02, 	/* 19010 */
+	0x3E,  0x7A,  0x22,  0xBE,  0xFE,  0x22,  0x3E,  0x7A,  0x24,  0xBE,  0xF9,  0x44,  0x95,  0x4A,  0x57,  0xC3, 	/* 19020 */
+	0xAA,  0x27,  0xCF,  0xC4,  0x57,  0xC5,  0x44,  0xFF,  0xC2,  0x44,  0xFC,  0x47,  0x7C,  0x6A,  0x8A,  0xA8, 	/* 19030 */
+	0x24,  0xA2,  0x86,  0xAC,  0x20,  0x0A,  0xBE,  0xFA,  0x20,  0x22,  0xFF,  0xE0,  0x22,  0x7B,  0xE4,  0xA2, 	/* 19040 */
+	0x7B,  0xE4,  0xD4,  0x32,  0x5C,  0xC3,  0xAF,  0x28,  0x07,  0xDE,  0x29,  0x27,  0xDE,  0x29,  0x2F,  0xFE, 	/* 19050 */
+	0x55,  0x27,  0xD2,  0x55,  0xEF,  0xF4,  0x45,  0x44,  0xE6,  0xB2,  0x50,  0x0F,  0xBC,  0x52,  0x4F,  0xBC, 	/* 19060 */
+	0xAA,  0x4F,  0xBC,  0x22,  0x47,  0xA4,  0x23,  0xCF,  0x58,  0x3A,  0xAE,  0x46,  0xB3,  0x43,  0xE7,  0xE2, 	/* 19070 */
+	0x52,  0x27,  0xFE,  0xAA,  0x27,  0xFE,  0x52,  0x2F,  0xFE,  0x51,  0x47,  0xD4,  0x52,  0x57,  0xC3,  0xBA, 	/* 19080 */
+	0x12,  0x06,  0x5C,  0x4A,  0x47,  0x5C,  0x4A,  0x4F,  0xFE,  0xA0,  0xAB,  0xF8,  0x20,  0x83,  0xF8,  0x1A, 	/* 19090 */
+	0x2E,  0x1E,  0xBD,  0xF2,  0x0A,  0x7E,  0xF8,  0x0F,  0xFE,  0xAA,  0xAF,  0xFE,  0x20,  0x83,  0xF8,  0x20, 	/* 190A0 */
+	0x83,  0xF8,  0x12,  0x2E,  0x1E,  0xBF,  0x20,  0x0F,  0xDE,  0x21,  0x27,  0x9E,  0xFD,  0x2B,  0x5E,  0xFD, 	/* 190B0 */
+	0x24,  0x9E,  0x78,  0xC4,  0x94,  0x7A,  0x5C,  0x43,  0x80,  0x28,  0x0F,  0xFC,  0x2A,  0x4E,  0xFC,  0xAA, 	/* 190C0 */
+	0x4E,  0xFC,  0x2A,  0x47,  0xE4,  0xD3,  0xC7,  0x98,  0x52,  0xA7,  0xCE,  0x92,  0x08,  0x01,  0xF0,  0x22, 	/* 190D0 */
+	0x0F,  0xFC,  0x24,  0x43,  0xFC,  0x24,  0x43,  0xFC,  0x20,  0x42,  0x04,  0x20,  0x44,  0x0C,  0x9A,  0x10, 	/* 190E0 */
+	0x63,  0xB8,  0x55,  0x4F,  0xD4,  0x55,  0x47,  0xD4,  0x55,  0x47,  0xDC,  0x45,  0x44,  0x5D,  0x46,  0x38, 	/* 190F0 */
+	0x81,  0x9C,  0x12,  0x05,  0xBC,  0x52,  0x2F,  0xFE,  0x1A,  0x07,  0xF8,  0x24,  0x83,  0xF8,  0x24,  0x83, 	/* 19100 */
+	0xF8,  0x40,  0x88,  0x18,  0x9D,  0x20,  0x63,  0xD8,  0x49,  0x49,  0x14,  0x7D,  0x45,  0x5E,  0x7D,  0x45, 	/* 19110 */
+	0x55,  0x7D,  0x34,  0x79,  0x44,  0x08,  0xDE,  0xA3,  0x20,  0x03,  0xFE,  0x49,  0x29,  0x22,  0x7C,  0xC5, 	/* 19120 */
+	0x5E,  0x7E,  0x85,  0x48,  0x7F,  0xF4,  0x48,  0x44,  0x88,  0xC8,  0xA6,  0x20,  0x83,  0xC8,  0x48,  0x89, 	/* 19130 */
+	0x3E,  0x7E,  0xA5,  0x6A,  0x7F,  0xE5,  0x48,  0x7C,  0xC4,  0x4A,  0x44,  0xE8,  0xF1,  0xA7,  0x22,  0x43, 	/* 19140 */
+	0xD4,  0x49,  0x89,  0x7E,  0x7C,  0x85,  0x7E,  0x7C,  0x85,  0x48,  0x7F,  0xE4,  0x48,  0x44,  0x88,  0xC8, 	/* 19150 */
+	0xB4,  0x22,  0x07,  0xBE,  0x96,  0x4F,  0xBC,  0xAA,  0x4F,  0xFF,  0xA9,  0x0F,  0x9E,  0x8A,  0xA8,  0xCA, 	/* 19160 */
+	0x89,  0x29,  0x8C,  0xB8,  0x47,  0xE7,  0x5A,  0xA7,  0xEF,  0x90,  0xAB,  0xEF,  0xD2,  0xAF,  0xEF,  0xD6, 	/* 19170 */
+	0x8F,  0xE8,  0x92,  0x8B,  0xA9,  0x8C,  0x80,  0x1F,  0x00,  0x00,  0xFF,  0xE0,  0x00,  0x1F,  0x00,  0x00, 	/* 19180 */
+	0x1F,  0x00,  0x00,  0x3F,  0x82,  0x08,  0x20,  0x83,  0xF8,  0x82,  0x60,  0x00,  0xFE,  0xF1,  0x00,  0x10, 	/* 19190 */
+	0x71,  0x00,  0x10,  0x71,  0x00,  0x10,  0xF1,  0x09,  0x10,  0x91,  0x0F,  0x30,  0x83,  0x71,  0x00,  0x10, 	/* 191A0 */
+	0xF9,  0x00,  0x10,  0x71,  0x80,  0x14,  0x71,  0x20,  0x12,  0xF9,  0x08,  0x90,  0x89,  0x0F,  0x90,  0x88, 	/* 191B0 */
+	0x71,  0x00,  0x10,  0xF9,  0x00,  0x10,  0x7F,  0xE0,  0x10,  0x71,  0x00,  0x10,  0xF1,  0x09,  0x10,  0x91, 	/* 191C0 */
+	0x0F,  0x10,  0x8A,  0xE0,  0x00,  0xF8,  0xF2,  0x80,  0x28,  0x72,  0x80,  0xF8,  0x72,  0x80,  0x28,  0xF2, 	/* 191D0 */
+	0xA9,  0x2A,  0x92,  0x6F,  0x42,  0x8C,  0x70,  0x00,  0x7C,  0xF9,  0x00,  0x10,  0x71,  0x00,  0x10,  0x71, 	/* 191E0 */
+	0x00,  0x10,  0xF1,  0x09,  0x10,  0x9F,  0xEF,  0x00,  0x8E,  0x60,  0x80,  0x08,  0xF0,  0x80,  0xFE,  0x70, 	/* 191F0 */
+	0x80,  0x88,  0x74,  0x80,  0x48,  0xF0,  0x89,  0x08,  0x90,  0x8F,  0x18,  0x90,  0x70,  0x00,  0x7C,  0xF1, 	/* 19200 */
+	0x00,  0x10,  0x71,  0x00,  0xFE,  0x71,  0x00,  0x10,  0xF1,  0x09,  0x10,  0x91,  0x0F,  0x10,  0x93,  0x72, 	/* 19210 */
+	0x20,  0x2A,  0xFA,  0xA0,  0x2A,  0x72,  0xA0,  0x2A,  0x72,  0xA0,  0x2A,  0xF2,  0xA9,  0x2A,  0x94,  0x2F, 	/* 19220 */
+	0x42,  0x96,  0x72,  0x00,  0x20,  0xF3,  0xE0,  0x40,  0x7F,  0xE0,  0x04,  0x70,  0x80,  0x10,  0xF2,  0x09, 	/* 19230 */
+	0x42,  0x94,  0x2F,  0x3E,  0x97,  0x60,  0xC0,  0xF0,  0xF2,  0x00,  0x20,  0x72,  0x00,  0xFE,  0x72,  0x00, 	/* 19240 */
+	0x20,  0xF2,  0x09,  0x22,  0x92,  0x2F,  0x1E,  0x98,  0x70,  0x00,  0x7C,  0xF8,  0x40,  0x04,  0x78,  0x40, 	/* 19250 */
+	0x3C,  0x7A,  0x00,  0x20,  0xFA,  0x08,  0xA2,  0x8A,  0x2F,  0x9E,  0x9B,  0x73,  0x00,  0x30,  0xF3,  0x00, 	/* 19260 */
+	0x52,  0x75,  0xC0,  0xD0,  0x75,  0x00,  0x50,  0xF5,  0x09,  0x52,  0x95,  0x2F,  0x4E,  0x9D,  0x70,  0x00, 	/* 19270 */
+	0x3E,  0xF2,  0x40,  0x24,  0x72,  0x40,  0xFE,  0x70,  0x40,  0x0C,  0xF1,  0x49,  0x24,  0x9C,  0x4F,  0x0C, 	/* 19280 */
+	0x9F,  0x73,  0x80,  0x08,  0xFA,  0x80,  0x24,  0x74,  0x40,  0x92,  0x71,  0x00,  0x28,  0xF2,  0x49,  0x4C, 	/* 19290 */
+	0x9F,  0x2F,  0x02,  0xA3,  0x72,  0x00,  0x20,  0xF2,  0x00,  0xFC,  0x72,  0x40,  0x24,  0x7F,  0xE0,  0x20, 	/* 192A0 */
+	0xF3,  0x09,  0x48,  0x98,  0x4F,  0x02,  0xA5,  0x73,  0x00,  0x10,  0xF1,  0x00,  0xFE,  0x79,  0x20,  0x92, 	/* 192B0 */
+	0x79,  0x20,  0xAA,  0xFC,  0x69,  0x82,  0x98,  0x2F,  0x86,  0xAA,  0x62,  0x00,  0x20,  0xFF,  0xE0,  0x20, 	/* 192C0 */
+	0x72,  0x00,  0x3C,  0x72,  0x40,  0x24,  0xF4,  0x49,  0x44,  0x98,  0x4F,  0x18,  0xAD,  0x77,  0x80,  0x48, 	/* 192D0 */
+	0xF4,  0xA0,  0x4A,  0x78,  0x60,  0x7C,  0x70,  0x40,  0x48,  0xF2,  0x89,  0x10,  0x92,  0x8F,  0xC6,  0xB1, 	/* 192E0 */
+	0x74,  0x00,  0x40,  0xF7,  0xC0,  0x90,  0x71,  0x00,  0x10,  0x7F,  0xE0,  0x10,  0xF1,  0x09,  0x10,  0x91, 	/* 192F0 */
+	0x0F,  0x10,  0xB3,  0x70,  0x00,  0x3E,  0xFA,  0x20,  0x22,  0x73,  0xE0,  0x28,  0x72,  0x80,  0x28,  0xF2, 	/* 19300 */
+	0x89,  0x44,  0x94,  0x4F,  0x82,  0xB4,  0x70,  0x40,  0x78,  0xF4,  0x00,  0x40,  0x77,  0xE0,  0x48,  0x74, 	/* 19310 */
+	0x80,  0x58,  0xF4,  0xC9,  0x4A,  0x98,  0x8F,  0x08,  0xB6,  0x70,  0x00,  0xFE,  0xF0,  0x40,  0x04,  0x77, 	/* 19320 */
+	0x40,  0x54,  0x75,  0x40,  0x54,  0xF7,  0x49,  0x04,  0x90,  0x4F,  0x0C,  0xBA,  0x61,  0x00,  0x10,  0xF2, 	/* 19330 */
+	0x80,  0x44,  0xE9,  0x20,  0x24,  0xEC,  0x80,  0x10,  0xF6,  0x29,  0x04,  0x91,  0x8F,  0x60,  0xBB,  0x62, 	/* 19340 */
+	0x00,  0x10,  0xF7,  0xE0,  0x10,  0x71,  0x00,  0x10,  0x77,  0xC0,  0x10,  0xF1,  0x09,  0x10,  0x91,  0x0F, 	/* 19350 */
+	0xFE,  0xBC,  0x60,  0x00,  0xFE,  0xF1,  0x00,  0x10,  0x75,  0x00,  0x50,  0x75,  0xC0,  0x50,  0xF5,  0x09, 	/* 19360 */
+	0x50,  0x95,  0x0F,  0xFE,  0x81,  0x71,  0x00,  0x10,  0xF1,  0x00,  0xFE,  0x71,  0x00,  0x10,  0x71,  0x00, 	/* 19370 */
+	0x7C,  0xF4,  0x49,  0x44,  0x94,  0x4F,  0x7C,  0x86,  0x70,  0xC0,  0x78,  0xFC,  0x80,  0x48,  0x77,  0xE0, 	/* 19380 */
+	0x48,  0x74,  0x80,  0x48,  0xF4,  0xA9,  0xE6,  0x90,  0x2F,  0xFA,  0x88,  0x7F,  0xC4,  0xA4,  0x7F,  0xC0, 	/* 19390 */
+	0x00,  0x1F,  0x0F,  0xFE,  0x00,  0x03,  0xF8,  0x00,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x90,  0x72,  0x00, 	/* 193A0 */
+	0x20,  0xFB,  0xE0,  0x30,  0x75,  0x00,  0x9E,  0x71,  0x00,  0x10,  0xF1,  0xE9,  0x10,  0x91,  0x0F,  0x10, 	/* 193B0 */
+	0x91,  0x60,  0x80,  0x7E,  0xF4,  0x20,  0x42,  0x72,  0x00,  0x24,  0x73,  0x80,  0x20,  0xF2,  0x09,  0x22, 	/* 193C0 */
+	0x92,  0x2F,  0x1E,  0x92,  0x71,  0x00,  0x10,  0xF2,  0x00,  0x24,  0x74,  0xE0,  0xF2,  0x70,  0x00,  0x7C, 	/* 193D0 */
+	0xF4,  0x49,  0x44,  0x94,  0x4F,  0x7C,  0x94,  0x70,  0x00,  0x7E,  0xF9,  0x20,  0x12,  0x72,  0x20,  0x4C, 	/* 193E0 */
+	0x78,  0x00,  0x3E,  0x7A,  0x24,  0xA2,  0x4A,  0x27,  0xBE,  0x95,  0x60,  0x00,  0xFE,  0xF1,  0x40,  0x94, 	/* 193F0 */
+	0x75,  0x80,  0x50,  0x7F,  0xE0,  0x10,  0xF1,  0x09,  0x10,  0x91,  0x0F,  0x10,  0x9B,  0x77,  0xC0,  0x44, 	/* 19400 */
+	0xF4,  0x40,  0x44,  0x77,  0xC0,  0x44,  0x74,  0x40,  0x7C,  0xF4,  0x49,  0x44,  0x94,  0x4F,  0xFE,  0x9E, 	/* 19410 */
+	0x70,  0x00,  0x7E,  0xF8,  0x20,  0x7A,  0x70,  0x20,  0x7A,  0x74,  0xA0,  0x4A,  0xF7,  0xA9,  0x02,  0x90, 	/* 19420 */
+	0x2F,  0x06,  0xA0,  0x73,  0x00,  0x08,  0xF7,  0x00,  0x12,  0x71,  0xC0,  0xF8,  0x73,  0x80,  0x34,  0xF5, 	/* 19430 */
+	0x49,  0x92,  0x91,  0x0F,  0x30,  0xA2,  0x74,  0x00,  0x40,  0xF7,  0xE0,  0x82,  0x77,  0xA0,  0x4A,  0x77, 	/* 19440 */
+	0xA0,  0x4A,  0xF4,  0xA9,  0x7A,  0x90,  0x2F,  0x0C,  0xA3,  0x74,  0x00,  0x4C,  0xFF,  0x00,  0x42,  0x73, 	/* 19450 */
+	0xE0,  0x00,  0x77,  0xC0,  0x44,  0xF7,  0xC9,  0x44,  0x94,  0x4F,  0x7C,  0xA6,  0x60,  0xC0,  0x0A,  0xF8, 	/* 19460 */
+	0x80,  0xFE,  0x70,  0x80,  0xF8,  0x72,  0x80,  0x28,  0xF2,  0xA9,  0x36,  0x9C,  0x6F,  0x02,  0xA9,  0x71, 	/* 19470 */
+	0x00,  0x7C,  0xF9,  0x00,  0x10,  0x7F,  0xE0,  0x08,  0x7F,  0xE0,  0x08,  0xF4,  0x89,  0x28,  0x90,  0x8F, 	/* 19480 */
+	0x18,  0xAB,  0x71,  0x00,  0x10,  0xFF,  0xE0,  0x82,  0x71,  0x80,  0xE0,  0x72,  0x00,  0x3C,  0xFE,  0x09, 	/* 19490 */
+	0x22,  0x92,  0x2F,  0x1E,  0xAC,  0x70,  0x60,  0x78,  0xF4,  0x00,  0x40,  0x77,  0xE0,  0x40,  0x74,  0x00, 	/* 194A0 */
+	0x7E,  0xF6,  0x29,  0x62,  0x9A,  0x2F,  0x3E,  0xAD,  0x72,  0x00,  0x3C,  0xF4,  0x80,  0x10,  0x77,  0xE0, 	/* 194B0 */
+	0x40,  0x75,  0xC0,  0x54,  0xF5,  0xC9,  0x50,  0x99,  0x2F,  0x0E,  0xAE,  0x61,  0x00,  0x10,  0xF2,  0x80, 	/* 194C0 */
+	0x44,  0xEF,  0xA0,  0x10,  0xE1,  0x00,  0x7C,  0xF1,  0x09,  0x10,  0x91,  0x0F,  0x7E,  0xB0,  0x71,  0x00, 	/* 194D0 */
+	0x10,  0xFF,  0xE0,  0x10,  0x71,  0x00,  0xFC,  0x70,  0x00,  0x7C,  0xF4,  0x49,  0x44,  0x94,  0x4F,  0x7C, 	/* 194E0 */
+	0xB1,  0x70,  0xC0,  0x70,  0xF1,  0x00,  0x10,  0x7F,  0xE0,  0x10,  0x71,  0x00,  0x7C,  0xF4,  0x49,  0x44, 	/* 194F0 */
+	0x94,  0x4F,  0x7C,  0xB2,  0x38,  0x80,  0x08,  0xFF,  0xE0,  0x10,  0x71,  0x40,  0x24,  0x75,  0x80,  0x12, 	/* 19500 */
+	0x7A,  0x44,  0xC8,  0x49,  0x47,  0xE2,  0xB3,  0x74,  0x40,  0x28,  0xF7,  0xE0,  0x10,  0x71,  0x00,  0x7C, 	/* 19510 */
+	0x71,  0x00,  0x10,  0xFF,  0xE9,  0x10,  0x91,  0x0F,  0x10,  0xBC,  0x72,  0x00,  0x20,  0xFF,  0xE0,  0x28, 	/* 19520 */
+	0x72,  0xA0,  0x3A,  0x72,  0xC0,  0x48,  0xF5,  0x49,  0x94,  0x92,  0x2F,  0x41,  0x82,  0x72,  0x80,  0x28, 	/* 19530 */
+	0xFA,  0xA0,  0x6C,  0x72,  0x80,  0x28,  0x76,  0xC0,  0xAA,  0xF2,  0x89,  0x2A,  0x94,  0xAF,  0x86,  0x84, 	/* 19540 */
+	0x71,  0x00,  0x1C,  0xFF,  0x00,  0x10,  0x77,  0xC0,  0x10,  0x7F,  0xE0,  0x10,  0xF3,  0x89,  0x54,  0x99, 	/* 19550 */
+	0x2F,  0x10,  0x85,  0x71,  0x00,  0x50,  0xF5,  0x00,  0x7C,  0x79,  0x00,  0x10,  0x7F,  0xE0,  0x10,  0xF3, 	/* 19560 */
+	0x89,  0x54,  0x99,  0x2F,  0x10,  0x87,  0x61,  0x00,  0xFE,  0xF2,  0x80,  0x44,  0xEB,  0xA0,  0x00,  0xE7, 	/* 19570 */
+	0xC0,  0x20,  0xF3,  0xC9,  0x04,  0x90,  0x4F,  0x18,  0x89,  0x48,  0x42,  0x48,  0xFF,  0xE1,  0x10,  0x2C, 	/* 19580 */
+	0x87,  0xFC,  0x80,  0x21,  0xF0,  0x00,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x8C,  0x61,  0x00,  0x10,  0xFF, 	/* 19590 */
+	0xE0,  0x10,  0x71,  0x00,  0xFC,  0x70,  0x00,  0x2C,  0xF6,  0xA9,  0xA2,  0x92,  0x4F,  0x1C,  0x8D,  0x70, 	/* 195A0 */
+	0x00,  0x7E,  0xF1,  0x20,  0x32,  0x71,  0xA0,  0x22,  0x74,  0xC0,  0x20,  0xF2,  0x89,  0x6A,  0x9A,  0x2F, 	/* 195B0 */
+	0x1E,  0x91,  0x62,  0x01,  0x5E,  0xF8,  0x80,  0x48,  0x74,  0x80,  0x68,  0x75,  0xE0,  0xC8,  0xF4,  0x89, 	/* 195C0 */
+	0x48,  0x94,  0x8F,  0xBE,  0x93,  0x20,  0x6F,  0xB8,  0x23,  0xEF,  0x24,  0x22,  0x46,  0xF4,  0x00,  0x0F, 	/* 195D0 */
+	0xFE,  0x00,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x95,  0x60,  0x61,  0xDC,  0xE4,  0x40,  0x54,  0x69,  0x41, 	/* 195E0 */
+	0xD6,  0x65,  0x41,  0x54,  0xED,  0x4A,  0x7F,  0xAB,  0x0F,  0x0F,  0x98,  0xE1,  0xC0,  0x70,  0xF1,  0x00, 	/* 195F0 */
+	0xFE,  0xE3,  0x80,  0x54,  0xEF,  0xA0,  0x28,  0xF2,  0xC9,  0x44,  0x94,  0x4F,  0x98,  0x9A,  0x71,  0x00, 	/* 19600 */
+	0x54,  0xF5,  0x20,  0x92,  0x77,  0xC0,  0x44,  0x77,  0xC0,  0x44,  0xF7,  0xC9,  0x44,  0x94,  0x4F,  0x4C, 	/* 19610 */
+	0x9E,  0x70,  0x00,  0xFC,  0xF2,  0x00,  0xF8,  0x74,  0x80,  0x48,  0x7F,  0xE0,  0x00,  0xF7,  0xC9,  0x44, 	/* 19620 */
+	0x94,  0x4F,  0x7C,  0xA0,  0x60,  0xC0,  0x0A,  0xF0,  0x80,  0xFE,  0xE8,  0x80,  0xE8,  0xEA,  0xA0,  0xAA, 	/* 19630 */
+	0xEA,  0x4A,  0xA4,  0xAA,  0xAF,  0x71,  0xA1,  0x70,  0xC0,  0x0A,  0xFF,  0xE0,  0x08,  0x7A,  0xA0,  0xAA, 	/* 19640 */
+	0x7F,  0xC0,  0xA8,  0xFA,  0xC9,  0x14,  0x92,  0x2F,  0x41,  0xA3,  0x70,  0x00,  0xFE,  0xF1,  0x00,  0x10, 	/* 19650 */
+	0x75,  0x40,  0x54,  0x75,  0x40,  0xBA,  0xF1,  0x29,  0x10,  0x91,  0x0F,  0xFE,  0xA4,  0x63,  0xC0,  0xA4, 	/* 19660 */
+	0xFA,  0x40,  0xBC,  0x78,  0x00,  0xFC,  0x70,  0x40,  0x04,  0xFF,  0xE9,  0x28,  0x92,  0x4F,  0x42,  0xA5, 	/* 19670 */
+	0x75,  0x00,  0x50,  0xF7,  0xE0,  0x90,  0x71,  0x00,  0xFE,  0x71,  0x00,  0x7C,  0xF4,  0x49,  0x44,  0x94, 	/* 19680 */
+	0x4F,  0x7C,  0xA6,  0x77,  0xC0,  0x04,  0xF2,  0x80,  0x10,  0x77,  0xE0,  0x52,  0x77,  0xE0,  0x52,  0xF7, 	/* 19690 */
+	0xE9,  0x52,  0x95,  0x2F,  0x56,  0xA8,  0x74,  0x00,  0x7E,  0xF8,  0x00,  0x7E,  0x75,  0x20,  0x4A,  0x7F, 	/* 196A0 */
+	0xE0,  0xA4,  0xF9,  0x49,  0xFE,  0x90,  0x4F,  0x18,  0xAC,  0x64,  0x40,  0x24,  0xF2,  0x80,  0x7C,  0x74, 	/* 196B0 */
+	0x40,  0x44,  0x77,  0xC0,  0x28,  0xF2,  0x89,  0x2A,  0x94,  0xAF,  0x86,  0xAD,  0x61,  0x00,  0xFE,  0xF1, 	/* 196C0 */
+	0x00,  0x7C,  0x70,  0x00,  0x7E,  0x74,  0x20,  0x2A,  0xF2,  0x89,  0x28,  0x94,  0xAF,  0x8E,  0xB0,  0x64, 	/* 196D0 */
+	0x40,  0x48,  0xF7,  0xE0,  0x48,  0xEC,  0x80,  0xFC,  0xE4,  0x80,  0x48,  0xF7,  0xC9,  0x48,  0x94,  0x8F, 	/* 196E0 */
+	0x7E,  0xB2,  0x77,  0xE0,  0x52,  0xF7,  0xE0,  0x52,  0x75,  0x20,  0x7E,  0x71,  0x00,  0xFE,  0xF3,  0x89, 	/* 196F0 */
+	0x54,  0x99,  0x2F,  0x10,  0xB9,  0x62,  0x80,  0x28,  0xFE,  0xE0,  0x28,  0x72,  0x80,  0xEE,  0x72,  0x80, 	/* 19700 */
+	0x28,  0xFE,  0xE9,  0x28,  0x94,  0x8F,  0x88,  0xBC,  0x71,  0x00,  0xFE,  0xF8,  0x20,  0x7C,  0x74,  0x40, 	/* 19710 */
+	0x44,  0x77,  0xC0,  0x44,  0xF7,  0xC9,  0x44,  0x94,  0x4F,  0xFE,  0xBF,  0x60,  0x00,  0xFE,  0xF9,  0x20, 	/* 19720 */
+	0xFE,  0x69,  0x20,  0xFE,  0x68,  0x20,  0xBA,  0xFA,  0xA9,  0xAA,  0x9B,  0xAF,  0x86,  0x82,  0x71,  0x00, 	/* 19730 */
+	0x1E,  0xF1,  0x20,  0x22,  0x74,  0xC0,  0x10,  0x76,  0xE0,  0x42,  0xF7,  0x69,  0x42,  0x94,  0x2F,  0x7E, 	/* 19740 */
+	0x84,  0x71,  0x00,  0xFE,  0xF0,  0x00,  0x7C,  0x74,  0x40,  0x7C,  0x70,  0x00,  0x7C,  0xF0,  0x89,  0xFE, 	/* 19750 */
+	0x91,  0x0F,  0x30,  0x87,  0x61,  0x00,  0x54,  0xF5,  0x40,  0x10,  0x72,  0x80,  0xD6,  0x71,  0x00,  0x54, 	/* 19760 */
+	0xF5,  0x49,  0x28,  0x94,  0x4F,  0x82,  0x8B,  0x61,  0x00,  0x7E,  0xF9,  0x00,  0x7C,  0x71,  0x00,  0xFE, 	/* 19770 */
+	0x74,  0x40,  0x7C,  0xF4,  0x49,  0x7C,  0x94,  0x4F,  0x4C,  0x8C,  0xE1,  0x00,  0xFE,  0xF1,  0x00,  0xFC, 	/* 19780 */
+	0xF9,  0x40,  0xFC,  0xE9,  0x40,  0xFC,  0xF3,  0x89,  0x54,  0x99,  0x2F,  0x10,  0x8D,  0x70,  0xE0,  0xF4, 	/* 19790 */
+	0xF5,  0x20,  0x8A,  0x77,  0xC0,  0x14,  0x7F,  0xE0,  0x14,  0xF7,  0xC9,  0x10,  0x91,  0x0F,  0x30,  0x8F, 	/* 197A0 */
+	0x60,  0x01,  0xE0,  0xEB,  0xE0,  0xAA,  0xEE,  0xA0,  0xAA,  0xEE,  0x40,  0xA4,  0xEA,  0xAA,  0xEA,  0xB3, 	/* 197B0 */
+	0x2E,  0x21,  0x92,  0x71,  0x00,  0x7E,  0xF8,  0x00,  0x7C,  0x74,  0x40,  0x44,  0x77,  0xC0,  0x10,  0xF5, 	/* 197C0 */
+	0x49,  0x52,  0x99,  0x2F,  0x30,  0x96,  0x71,  0x00,  0x28,  0xF2,  0x80,  0x44,  0x7F,  0xA0,  0x00,  0x7F, 	/* 197D0 */
+	0xE0,  0xAA,  0xFF,  0xE9,  0xAA,  0x9A,  0xAF,  0x86,  0x9A,  0x71,  0x00,  0x10,  0xFF,  0xE0,  0x82,  0x77, 	/* 197E0 */
+	0xC0,  0x10,  0x71,  0x00,  0x5C,  0xF5,  0x09,  0x70,  0x95,  0x8F,  0x86,  0x9B,  0x71,  0x00,  0x36,  0xFD, 	/* 197F0 */
+	0x20,  0x52,  0x77,  0x60,  0x52,  0x75,  0x20,  0x7E,  0xF1,  0x89,  0x28,  0x94,  0x4F,  0x82,  0x9C,  0x65, 	/* 19800 */
+	0x40,  0x54,  0xFF,  0xE0,  0x54,  0x75,  0xC0,  0x40,  0x77,  0xE0,  0x10,  0xFF,  0xE9,  0x38,  0x9D,  0x6F, 	/* 19810 */
+	0x10,  0x9E,  0x77,  0xE0,  0x00,  0xFF,  0xE0,  0x42,  0x77,  0xE0,  0x40,  0x77,  0xE0,  0x6A,  0xF7,  0xE9, 	/* 19820 */
+	0x6A,  0x9A,  0xAF,  0x26,  0xA0,  0x71,  0x00,  0xFE,  0xF8,  0x20,  0x7C,  0x70,  0x00,  0x7C,  0x74,  0x40, 	/* 19830 */
+	0x7C,  0xF4,  0x49,  0x7C,  0x90,  0x0F,  0xFE,  0xA1,  0x72,  0x80,  0x28,  0xF4,  0x40,  0xFE,  0x72,  0x10, 	/* 19840 */
+	0x3C,  0x70,  0x40,  0x18,  0xFF,  0xE9,  0xAA,  0x9A,  0xAF,  0xFF,  0xA2,  0x6F,  0xE0,  0x92,  0xF7,  0xC0, 	/* 19850 */
+	0x10,  0x77,  0xC0,  0x54,  0x77,  0xC0,  0x54,  0xF7,  0xC9,  0x10,  0x9F,  0xEF,  0x10,  0xA4,  0x7E,  0xE0, 	/* 19860 */
+	0xAA,  0xFE,  0xE0,  0x00,  0x77,  0xC0,  0x00,  0x7F,  0xE0,  0x40,  0xF7,  0xC9,  0x44,  0x90,  0x4F,  0x18, 	/* 19870 */
+	0xA6,  0x61,  0x00,  0xFE,  0xF4,  0x40,  0x28,  0x7F,  0xE0,  0x92,  0x77,  0xC0,  0x54,  0xF5,  0x49,  0x5C, 	/* 19880 */
+	0x95,  0x0F,  0x10,  0xA7,  0x75,  0x00,  0x56,  0xF7,  0x80,  0x50,  0x75,  0x20,  0xEE,  0x70,  0x00,  0x7C, 	/* 19890 */
+	0xF4,  0x49,  0x7C,  0x94,  0x4F,  0x7C,  0xAB,  0x71,  0x00,  0xFE,  0xF1,  0x00,  0xFE,  0x7D,  0x60,  0xBA, 	/* 198A0 */
+	0x7F,  0xE0,  0x10,  0xF3,  0x89,  0x54,  0x99,  0x2F,  0x10,  0xAD,  0x61,  0x00,  0x28,  0xF4,  0x60,  0xB8, 	/* 198B0 */
+	0xE0,  0x00,  0xEA,  0xEA,  0xA0,  0xEA,  0xEA,  0xAA,  0xEA,  0xAA,  0x2E,  0xA6,  0xAE,  0x6A,  0x00,  0x60, 	/* 198C0 */
+	0xF3,  0xE0,  0x2C,  0x74,  0x80,  0x94,  0x7A,  0x20,  0x00,  0xF7,  0xC9,  0x44,  0x94,  0x4F,  0x7C,  0xB1, 	/* 198D0 */
+	0x72,  0x00,  0x7C,  0xF2,  0x40,  0xFE,  0x74,  0x40,  0x7C,  0x70,  0x80,  0xFE,  0xF4,  0x89,  0xFE,  0x90, 	/* 198E0 */
+	0x8F,  0x08,  0xB3,  0x71,  0x00,  0x10,  0xFF,  0xE0,  0x44,  0x72,  0x80,  0xFE,  0x70,  0x00,  0x7C,  0xF4, 	/* 198F0 */
+	0x49,  0x7C,  0x94,  0x4F,  0x7C,  0xB7,  0x70,  0x00,  0x7E,  0xFC,  0xE0,  0x72,  0x75,  0x20,  0x7E,  0x75, 	/* 19900 */
+	0x60,  0x7E,  0xF5,  0xA9,  0x96,  0x99,  0xDF,  0x65,  0xB8,  0x72,  0x00,  0x7C,  0xF2,  0x40,  0x28,  0x7F, 	/* 19910 */
+	0xE0,  0x20,  0x77,  0xC0,  0xC4,  0xF7,  0xC9,  0x44,  0x94,  0x4F,  0x7C,  0xBA,  0x71,  0x00,  0x7E,  0xFA, 	/* 19920 */
+	0x40,  0x24,  0x77,  0xE0,  0x48,  0x77,  0x20,  0x44,  0xF5,  0x89,  0x42,  0x98,  0xCF,  0xB0,  0xBE,  0x64, 	/* 19930 */
+	0x80,  0xFE,  0xF4,  0x80,  0x28,  0x72,  0x00,  0xFE,  0x72,  0x00,  0x3C,  0xF6,  0x49,  0xA4,  0x92,  0x4F, 	/* 19940 */
+	0x3C,  0x80,  0x64,  0x40,  0xFE,  0xF4,  0x40,  0x7C,  0xE4,  0x40,  0x7C,  0xE1,  0x00,  0xFE,  0xF3,  0x89, 	/* 19950 */
+	0x54,  0x99,  0x2F,  0x10,  0x81,  0x77,  0xC0,  0x44,  0xFF,  0xC0,  0x44,  0x77,  0xC0,  0x20,  0x73,  0xE0, 	/* 19960 */
+	0x4A,  0xF7,  0x29,  0xAA,  0x93,  0xAF,  0x0C,  0x82,  0x70,  0x00,  0xFE,  0xF9,  0x20,  0xFE,  0xF9,  0x20, 	/* 19970 */
+	0xFE,  0xF4,  0x40,  0x7C,  0xF4,  0x49,  0x7C,  0x94,  0x4F,  0x4C,  0x84,  0xEA,  0x8A,  0xFC,  0xA2,  0x0B, 	/* 19980 */
+	0xFE,  0xE4,  0x8A,  0xB4,  0xB0,  0x2E,  0xFC,  0xA0,  0x0A,  0xFC,  0xA8,  0x4A,  0xFC,  0x87,  0x04,  0x0F, 	/* 19990 */
+	0xFE,  0x91,  0x2B,  0xFA,  0x11,  0x07,  0xFC,  0x24,  0x87,  0xFC,  0x8E,  0x23,  0xF8,  0x20,  0x83,  0xF8, 	/* 199A0 */
+	0x8C,  0x6F,  0xE0,  0x04,  0xF7,  0x40,  0x54,  0x77,  0x40,  0x0C,  0x7F,  0xE0,  0x04,  0xF7,  0x49,  0x54, 	/* 199B0 */
+	0x97,  0x4F,  0x0C,  0x8E,  0x60,  0x80,  0x2A,  0xF1,  0xC0,  0x88,  0xE7,  0xE1,  0xC8,  0xE5,  0xC0,  0x6A, 	/* 199C0 */
+	0xE4,  0x8A,  0x48,  0xAA,  0x0F,  0x1F,  0x90,  0x72,  0x00,  0x14,  0xF2,  0x20,  0xA8,  0x73,  0x20,  0xCE, 	/* 199D0 */
+	0x70,  0x00,  0x7C,  0xF5,  0x49,  0x54,  0x95,  0x4F,  0xFE,  0x94,  0x71,  0x00,  0x1E,  0xF1,  0x00,  0x7E, 	/* 199E0 */
+	0x75,  0x00,  0x7C,  0x74,  0xA0,  0x5E,  0xF5,  0x09,  0x7E,  0x99,  0x0F,  0x1E,  0x96,  0x77,  0xE0,  0x52, 	/* 199F0 */
+	0xFF,  0xE0,  0x52,  0x77,  0xE0,  0x28,  0x74,  0xE0,  0x9C,  0xF6,  0x49,  0x18,  0x93,  0x4F,  0xC2,  0x97, 	/* 19A00 */
+	0x71,  0x00,  0xFE,  0xF4,  0x40,  0x28,  0x7F,  0xE0,  0xA2,  0x7F,  0xC0,  0x20,  0xF3,  0xC9,  0x24,  0x94, 	/* 19A10 */
+	0x4F,  0x98,  0x99,  0xE4,  0x40,  0xFE,  0xF2,  0x80,  0xFE,  0xE2,  0xA0,  0xFF,  0xE2,  0xA0,  0xFE,  0xF2, 	/* 19A20 */
+	0x89,  0x6C,  0x9A,  0xAF,  0x28,  0x9A,  0x72,  0xC0,  0x24,  0xF4,  0x20,  0xBD,  0x70,  0x00,  0x3C,  0x72, 	/* 19A30 */
+	0x40,  0x42,  0xFF,  0xD9,  0x54,  0x95,  0x4F,  0xFE,  0x9B,  0x72,  0x80,  0x7E,  0xFA,  0x80,  0x7E,  0x72, 	/* 19A40 */
+	0x80,  0xFE,  0x75,  0x40,  0x7C,  0xF5,  0x49,  0xFE,  0x94,  0x4F,  0x4C,  0x9D,  0x64,  0x40,  0xE4,  0xFA, 	/* 19A50 */
+	0x40,  0xFE,  0xEA,  0x40,  0xE4,  0xEB,  0x41,  0xEC,  0xF6,  0x49,  0xA4,  0x92,  0x4F,  0x6C,  0xA0,  0x70, 	/* 19A60 */
+	0x80,  0x1E,  0xF6,  0xA0,  0x14,  0x71,  0x80,  0xE0,  0x77,  0xE0,  0x10,  0xFF,  0xE9,  0x10,  0x95,  0x2F, 	/* 19A70 */
+	0x7E,  0xA1,  0x60,  0x60,  0xFA,  0xF9,  0x20,  0x54,  0xE2,  0x80,  0xFE,  0xE1,  0x00,  0xFE,  0xE1,  0x0A, 	/* 19A80 */
+	0x92,  0xA9,  0x2E,  0xFE,  0xA6,  0x79,  0xC1,  0x14,  0xFE,  0x75,  0x7C,  0x7A,  0x44,  0x18,  0x86,  0x67, 	/* 19A90 */
+	0xFC,  0x0F,  0x01,  0xF8,  0x10,  0x81,  0xF8,  0xA8,  0x74,  0x80,  0xFE,  0xF4,  0x80,  0x7C,  0x74,  0x40, 	/* 19AA0 */
+	0x7C,  0x74,  0x40,  0x7C,  0xF1,  0x09,  0xFE,  0x92,  0x4F,  0xC2,  0xAB,  0x71,  0x00,  0xFE,  0xF4,  0x40, 	/* 19AB0 */
+	0x28,  0x77,  0xE0,  0x52,  0x77,  0xE0,  0x52,  0xF7,  0xA9,  0x6A,  0x97,  0xAF,  0x46,  0xAC,  0x6E,  0xE0, 	/* 19AC0 */
+	0x22,  0xFA,  0xA0,  0x66,  0xEB,  0xA0,  0x32,  0xE6,  0xC1,  0x93,  0xF6,  0x89,  0x36,  0x91,  0x8F,  0xE0, 	/* 19AD0 */
+	0xB3,  0x70,  0x00,  0x7E,  0xFC,  0x00,  0x5C,  0x75,  0x40,  0x5C,  0x77,  0xE0,  0x5A,  0xF5,  0xA9,  0x7E, 	/* 19AE0 */
+	0x94,  0x0F,  0x7E,  0xB9,  0x72,  0x40,  0xFE,  0xF2,  0x40,  0x7C,  0x75,  0x40,  0x7C,  0x71,  0x00,  0xFC, 	/* 19AF0 */
+	0xF1,  0x09,  0x7C,  0x91,  0x0F,  0xFE,  0xBE,  0x77,  0xC0,  0x44,  0xFF,  0xC0,  0x44,  0x7F,  0xE0,  0xAA, 	/* 19B00 */
+	0x7F,  0xE0,  0x00,  0xFF,  0xC9,  0x48,  0x93,  0x0F,  0xCC,  0x81,  0x72,  0x40,  0xFE,  0xF2,  0x40,  0xFE, 	/* 19B10 */
+	0x75,  0x40,  0xFF,  0x75,  0x40,  0xFE,  0xF1,  0x09,  0xFE,  0x91,  0x0F,  0x10,  0x89,  0x77,  0x40,  0x1C, 	/* 19B20 */
+	0xFA,  0xA0,  0x44,  0x7B,  0xA0,  0x01,  0x77,  0xC0,  0x44,  0xF7,  0xC9,  0x44,  0x92,  0x8F,  0xFE,  0x8C, 	/* 19B30 */
+	0x70,  0xE0,  0xF4,  0xF4,  0xA0,  0x78,  0x74,  0x80,  0x7C,  0x74,  0x40,  0x7E,  0xFA,  0xA9,  0x56,  0x98, 	/* 19B40 */
+	0x2F,  0x0C,  0x8E,  0x77,  0xC0,  0x28,  0xFF,  0xF0,  0x1A,  0x72,  0x80,  0xFE,  0x75,  0xA0,  0x6E,  0xF7, 	/* 19B50 */
+	0xA9,  0x6A,  0x97,  0xAF,  0x46,  0x8F,  0x62,  0x40,  0x48,  0xFF,  0xC0,  0x5A,  0x6F,  0xE0,  0x14,  0x7F, 	/* 19B60 */
+	0xE0,  0x94,  0xFD,  0x89,  0xAA,  0x91,  0x6F,  0x62,  0x96,  0x64,  0x41,  0xDE,  0xF5,  0x41,  0xFE,  0x6D, 	/* 19B70 */
+	0x41,  0x66,  0x60,  0x00,  0x7C,  0xF4,  0x49,  0x7C,  0x94,  0x4F,  0x7C,  0x98,  0xC4,  0x81,  0xEC,  0xEA, 	/* 19B80 */
+	0xA0,  0xA8,  0xFF,  0xF0,  0x08,  0xEE,  0xA0,  0xAA,  0xEE,  0xAA,  0xA4,  0xAE,  0xCE,  0x32,  0x9A,  0x6F, 	/* 19B90 */
+	0xE0,  0x28,  0xFF,  0xE0,  0xAA,  0x7F,  0xE0,  0x44,  0x77,  0xC0,  0x44,  0xF7,  0xC9,  0x10,  0x9F,  0xEF, 	/* 19BA0 */
+	0x10,  0x9B,  0x72,  0x40,  0x7E,  0xF2,  0x40,  0x7E,  0x72,  0x40,  0x5A,  0x79,  0x10,  0x7C,  0xF4,  0x49, 	/* 19BB0 */
+	0x7C,  0x94,  0x4F,  0x7C,  0x9C,  0x64,  0x40,  0x28,  0xFF,  0xE0,  0xAA,  0xE6,  0xC0,  0xFE,  0xE0,  0x00, 	/* 19BC0 */
+	0x7C,  0xF4,  0x49,  0x7C,  0x94,  0x4F,  0x7C,  0x9F,  0x77,  0x80,  0x48,  0xF7,  0x80,  0xEE,  0x7A,  0xA0, 	/* 19BD0 */
+	0xEE,  0x71,  0x00,  0xFE,  0xF3,  0x89,  0x54,  0x99,  0x2F,  0x10,  0xA6,  0x29,  0x0F,  0xDF,  0x46,  0x2F, 	/* 19BE0 */
+	0x54,  0x54,  0xC7,  0x73,  0x0C,  0x07,  0xFE,  0x0F,  0x03,  0xFC,  0x20,  0x43,  0xFC,  0xAB,  0x73,  0xC0, 	/* 19BF0 */
+	0x48,  0xFF,  0xE0,  0x54,  0x76,  0x60,  0x58,  0x74,  0x00,  0x7E,  0xF5,  0x89,  0x7C,  0x9A,  0x4F,  0x3C, 	/* 19C00 */
+	0xAC,  0x78,  0x84,  0xBE,  0x79,  0x44,  0x3E,  0x7C,  0x8A,  0x7C,  0x3C,  0x87,  0xFE,  0x0F,  0x01,  0xF8, 	/* 19C10 */
+	0x10,  0x81,  0xF8,  0xAF,  0x6F,  0xE0,  0xAA,  0xFF,  0xE0,  0x10,  0x77,  0xC0,  0x10,  0x7F,  0xE0,  0x44, 	/* 19C20 */
+	0xFF,  0xE9,  0x10,  0x97,  0xCF,  0x10,  0xB0,  0x72,  0x40,  0xFE,  0xF1,  0x00,  0x7C,  0x71,  0x00,  0xFE, 	/* 19C30 */
+	0x74,  0xA0,  0xFF,  0xF4,  0xC9,  0xEA,  0x95,  0x6F,  0xC2,  0xB1,  0x11,  0x0F,  0xFE,  0x04,  0x07,  0xFC, 	/* 19C40 */
+	0x04,  0x06,  0x4C,  0xFF,  0xE0,  0x40,  0x64,  0xCF,  0x5E,  0x95,  0x2F,  0x5E,  0xB2,  0x61,  0x00,  0xFE, 	/* 19C50 */
+	0xF2,  0x80,  0x44,  0x7A,  0xA0,  0xFC,  0x72,  0x80,  0xFE,  0xF5,  0x29,  0xCC,  0x97,  0x4F,  0xC2,  0xB4, 	/* 19C60 */
+	0x70,  0x80,  0x3E,  0xFA,  0xA0,  0x7F,  0x71,  0x20,  0xDE,  0x75,  0x00,  0x5E,  0xF5,  0x29,  0x5E,  0x9A, 	/* 19C70 */
+	0x0F,  0x1F,  0xB7,  0x62,  0x80,  0xFE,  0xF2,  0x80,  0x7E,  0x76,  0x80,  0xBE,  0x72,  0x80,  0x7E,  0xF4, 	/* 19C80 */
+	0x49,  0x38,  0x92,  0x8F,  0xC6,  0xBD,  0x1E,  0x02,  0x9C,  0x2E,  0x43,  0xAC,  0x2A,  0x4F,  0xFF,  0x26, 	/* 19C90 */
+	0x47,  0xFE,  0x8F,  0x11,  0xF8,  0x10,  0x81,  0xF8,  0x80,  0x71,  0x00,  0xFE,  0xF9,  0x00,  0xFE,  0x7A, 	/* 19CA0 */
+	0xA0,  0xFE,  0x74,  0x40,  0x7C,  0xF4,  0x49,  0x7C,  0x92,  0x4F,  0xC2,  0x83,  0x72,  0x80,  0x7E,  0xF2, 	/* 19CB0 */
+	0x80,  0xFE,  0x75,  0x40,  0xFE,  0x74,  0x40,  0x7C,  0xF4,  0x49,  0x7C,  0x92,  0x4F,  0xC2,  0x8A,  0x45, 	/* 19CC0 */
+	0x0A,  0xE8,  0x51,  0x2F,  0xFE,  0x6E,  0xCB,  0xBA,  0x2E,  0x80,  0x80,  0x1F,  0xE6,  0x88,  0x07,  0x0F, 	/* 19CD0 */
+	0x8E,  0x8C,  0x74,  0x80,  0xFE,  0xF4,  0x80,  0x78,  0x7C,  0xA0,  0x7C,  0x76,  0x80,  0xFA,  0xF4,  0xE9, 	/* 19CE0 */
+	0x00,  0x95,  0x4F,  0xAA,  0x8E,  0x26,  0x82,  0x08,  0x7F,  0xED,  0x14,  0x57,  0x47,  0x9E,  0x57,  0x45, 	/* 19CF0 */
+	0x14,  0x77,  0xE5,  0x54,  0x55,  0x47,  0xFE,  0x90,  0x52,  0x87,  0xBC,  0xD6,  0x8F,  0xFC,  0x52,  0x8F, 	/* 19D00 */
+	0xFE,  0x00,  0x03,  0xF8,  0x00,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x92,  0x73,  0x80,  0xD0,  0xF7,  0xC0, 	/* 19D10 */
+	0x44,  0x77,  0xC0,  0x4A,  0x7E,  0xE0,  0x7C,  0xF5,  0x49,  0x7C,  0x92,  0xAF,  0xCE,  0x93,  0x71,  0x00, 	/* 19D20 */
+	0xFE,  0xFA,  0xA0,  0xEE,  0x72,  0x80,  0xFE,  0x72,  0x80,  0xFE,  0xF2,  0x29,  0xD4,  0x94,  0x8F,  0x66, 	/* 19D30 */
+	0x96,  0x6A,  0xA0,  0xAA,  0xF5,  0x80,  0xFE,  0x75,  0x80,  0xFA,  0x75,  0x60,  0xDC,  0xF5,  0x49,  0xDE, 	/* 19D40 */
+	0x95,  0xBF,  0xE9,  0x99,  0x72,  0x80,  0xFE,  0xF2,  0x80,  0xEE,  0x7A,  0xA0,  0xEE,  0x72,  0x40,  0x7E, 	/* 19D50 */
+	0xFC,  0x89,  0x7C,  0x94,  0x8F,  0x7E,  0x9A,  0x66,  0x40,  0x7E,  0xFA,  0x40,  0xFE,  0x76,  0xC0,  0xB6, 	/* 19D60 */
+	0x70,  0x00,  0x7C,  0xF4,  0x49,  0x7C,  0x94,  0x4F,  0x7C,  0xB7,  0x11,  0x01,  0x08,  0x24,  0x44,  0x44, 	/* 19D70 */
+	0x0A,  0x01,  0x10,  0x20,  0x8F,  0xFE,  0x20,  0x82,  0x08,  0x20,  0x83,  0xF8,  0xBA,  0x28,  0x02,  0x7E, 	/* 19D80 */
+	0x52,  0x41,  0x24,  0x2A,  0x44,  0x7F,  0x80,  0xC7,  0x94,  0x49,  0x44,  0xA4,  0x4C,  0x47,  0x8C,  0xBF, 	/* 19D90 */
+	0x1A,  0x8F,  0x24,  0xAD,  0x42,  0x10,  0xDA,  0x82,  0xA4,  0xFC,  0x22,  0x3D,  0xFA,  0x43,  0x24,  0x4A, 	/* 19DA0 */
+	0x48,  0x3C,  0x81,  0x22,  0x8F,  0xA4,  0xAD,  0x4F,  0x90,  0x22,  0x87,  0xA4,  0x24,  0x2F,  0xBD,  0x22, 	/* 19DB0 */
+	0x4F,  0xA4,  0x8A,  0x4F,  0xBC,  0x86,  0x00,  0x07,  0xFE,  0x00,  0x03,  0xFC,  0x20,  0x42,  0x04,  0x3F, 	/* 19DC0 */
+	0xC2,  0x08,  0x10,  0x80,  0x90,  0x01,  0x07,  0xFE,  0x88,  0x04,  0x04,  0x44,  0x7F,  0xC0,  0x00,  0xFF, 	/* 19DD0 */
+	0xE0,  0x00,  0x3F,  0x82,  0x08,  0x3F,  0x81,  0x10,  0x0A,  0x0F,  0xFE,  0x8A,  0x0A,  0x07,  0xFC,  0x4A, 	/* 19DE0 */
+	0x47,  0xFC,  0x4A,  0x4F,  0xFE,  0x00,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x11,  0x0F,  0xFE,  0x8C,  0x01, 	/* 19DF0 */
+	0x0F,  0xFE,  0x08,  0x2F,  0x40,  0x97,  0xE9,  0x5A,  0xF5,  0xA1,  0xAE,  0x52,  0x82,  0x48,  0x34,  0xAC, 	/* 19E00 */
+	0x86,  0x8E,  0x00,  0x0F,  0xFC,  0xA2,  0x4F,  0x98,  0xA2,  0x4F,  0xC2,  0x00,  0x07,  0xFC,  0x20,  0x83, 	/* 19E10 */
+	0xF8,  0x11,  0x0F,  0xFE,  0x90,  0x95,  0x2B,  0xFA,  0x95,  0x2B,  0xFA,  0x95,  0x2F,  0xFE,  0x00,  0x07, 	/* 19E20 */
+	0xFC,  0x20,  0x83,  0xF8,  0x11,  0x0F,  0xFE,  0x95,  0x00,  0x0F,  0xFE,  0x04,  0x01,  0x84,  0xE5,  0x40, 	/* 19E30 */
+	0xB8,  0x32,  0x8C,  0x68,  0x0A,  0x43,  0x22,  0xC2,  0x00,  0xC0,  0x9A,  0x00,  0x07,  0xFE,  0x51,  0x05, 	/* 19E40 */
+	0x30,  0x7D,  0xA5,  0x2C,  0x5C,  0x87,  0x1C,  0x52,  0xA5,  0xC9,  0x50,  0x8B,  0x30,  0xA1,  0x1E,  0x0E, 	/* 19E50 */
+	0x40,  0x3F,  0x82,  0x48,  0x3F,  0xA1,  0xC4,  0xE7,  0x81,  0xB0,  0x66,  0x81,  0xA4,  0x62,  0x20,  0xC0, 	/* 19E60 */
+	0xA2,  0x04,  0x02,  0x48,  0x7F,  0xC0,  0xA0,  0xFF,  0xE2,  0x08,  0x5F,  0x48,  0xCA,  0x73,  0x00,  0xE8, 	/* 19E70 */
+	0x72,  0x40,  0xC0,  0xAA,  0x04,  0x0F,  0xFE,  0x1F,  0x01,  0x10,  0xFF,  0xE8,  0x02,  0x3F,  0x80,  0xA4, 	/* 19E80 */
+	0x73,  0x80,  0xD4,  0x71,  0x20,  0x60,  0xAB,  0x03,  0xCF,  0x48,  0x2F,  0xEC,  0x92,  0x2F,  0xEF,  0x32, 	/* 19E90 */
+	0x5D,  0x46,  0x68,  0x49,  0xC4,  0x6A,  0x58,  0x9C,  0x30,  0xAC,  0x01,  0x0F,  0xD0,  0x23,  0xE6,  0x54, 	/* 19EA0 */
+	0xB7,  0xE5,  0x90,  0x9B,  0xC3,  0x64,  0x53,  0xC9,  0x24,  0x12,  0x46,  0x3C,  0xB8,  0x01,  0x00,  0x60, 	/* 19EB0 */
+	0x79,  0x40,  0x98,  0x0E,  0x0F,  0x30,  0x0C,  0x87,  0x18,  0x02,  0x80,  0xC8,  0x70,  0x80,  0x30,  0xB9, 	/* 19EC0 */
+	0x09,  0x03,  0x10,  0xD1,  0xE5,  0x12,  0x3A,  0x2F,  0x32,  0x14,  0xA3,  0x8A,  0xC8,  0x23,  0x82,  0xC8, 	/* 19ED0 */
+	0x23,  0x0C,  0xBA,  0x08,  0x83,  0x08,  0xD0,  0x85,  0xFE,  0x30,  0x8D,  0x18,  0x29,  0x8C,  0xA8,  0x1A, 	/* 19EE0 */
+	0x8E,  0xC8,  0x08,  0x83,  0x18,  0xBC,  0x0A,  0x83,  0x28,  0xD2,  0x85,  0xA8,  0x33,  0xAD,  0x2C,  0x2A, 	/* 19EF0 */
+	0x8C,  0xA8,  0x1A,  0x8E,  0xAA,  0x0B,  0xA3,  0x46,  0x82,  0x08,  0x03,  0x7E,  0xD1,  0x25,  0x92,  0x32, 	/* 19F00 */
+	0x2D,  0x4C,  0x28,  0x0C,  0xBE,  0x1A,  0x2E,  0xA2,  0x0A,  0x23,  0x3E,  0x85,  0x12,  0x82,  0x28,  0xDA, 	/* 19F10 */
+	0x85,  0x7E,  0x34,  0x8E,  0xDC,  0x35,  0xCD,  0x6A,  0x34,  0xAD,  0x49,  0x14,  0x86,  0x48,  0x89,  0x09, 	/* 19F20 */
+	0x03,  0x3E,  0xD4,  0x45,  0xA4,  0x31,  0x8D,  0x24,  0x2C,  0x2C,  0xBC,  0x1A,  0x4E,  0xA4,  0x0A,  0x43, 	/* 19F30 */
+	0x3C,  0x8A,  0x08,  0x03,  0x7F,  0xD0,  0x85,  0x50,  0x3B,  0xED,  0x22,  0x2A,  0x2C,  0xBE,  0x1A,  0x2E, 	/* 19F40 */
+	0xA2,  0x0A,  0x23,  0x3E,  0x8C,  0x09,  0x03,  0x20,  0xD7,  0xC5,  0x44,  0x3F,  0xCF,  0x44,  0x37,  0xCC, 	/* 19F50 */
+	0xA8,  0x3A,  0x8C,  0xAA,  0x0A,  0xA3,  0x46,  0x8D,  0x08,  0x03,  0x3E,  0xD2,  0xA5,  0x6A,  0x3B,  0xED, 	/* 19F60 */
+	0x2A,  0x2B,  0xEC,  0x88,  0x1B,  0xEE,  0x88,  0x08,  0x83,  0x7F,  0x8E,  0x09,  0x03,  0x26,  0xD2,  0x25, 	/* 19F70 */
+	0x76,  0x3A,  0x2D,  0x22,  0x2B,  0xEC,  0x98,  0x19,  0x8E,  0xAA,  0x0A,  0xA3,  0x46,  0x94,  0x12,  0x0E, 	/* 19F80 */
+	0xFE,  0xAA,  0xA6,  0x92,  0x7E,  0xAA,  0x8A,  0x6F,  0xE9,  0x4A,  0x37,  0xCD,  0x48,  0x17,  0xA6,  0xC6, 	/* 19F90 */
+	0x98,  0x0A,  0x43,  0x7E,  0xD3,  0xC5,  0x24,  0x3B,  0xCD,  0x24,  0x2B,  0xCC,  0x90,  0x1F,  0xEE,  0x98, 	/* 19FA0 */
+	0x0A,  0x43,  0x42,  0x9D,  0x00,  0x03,  0xF8,  0x20,  0x82,  0x08,  0x3F,  0x82,  0x08,  0x3F,  0x82,  0x08, 	/* 19FB0 */
+	0x20,  0x83,  0xF8,  0x1B,  0x06,  0x0C,  0x9E,  0x04,  0x00,  0x7C,  0x04,  0x03,  0xF8,  0x20,  0x83,  0xF8, 	/* 19FC0 */
+	0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x19,  0x86,  0x06,  0xA0,  0x08,  0x01,  0xF0,  0xE2,  0x03,  0xF8, 	/* 19FD0 */
+	0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x1B,  0x0E,  0x0C,  0xA1,  0x00,  0x47,  0x84, 	/* 19FE0 */
+	0x48,  0x47,  0xFE,  0x48,  0x47,  0x8C,  0x48,  0xC4,  0x94,  0x7A,  0x42,  0xC4,  0x44,  0x48,  0x0C,  0xA2, 	/* 19FF0 */
+	0x00,  0x03,  0xF8,  0x04,  0x0F,  0xFE,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x1B, 	/* 1A000 */
+	0x0E,  0x0C,  0xA7,  0x0A,  0x01,  0x10,  0x3F,  0x8C,  0x56,  0x19,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20, 	/* 1A010 */
+	0x83,  0xF8,  0x0B,  0x07,  0x0C,  0xA8,  0x0A,  0x63,  0x38,  0xD2,  0x23,  0xFE,  0x20,  0x83,  0xF8,  0x20, 	/* 1A020 */
+	0x83,  0xF8,  0x20,  0x83,  0xF8,  0x31,  0x8C,  0x04,  0xA9,  0x00,  0x0F,  0x7E,  0x94,  0x0F,  0x40,  0x97, 	/* 1A030 */
+	0xCF,  0x44,  0x94,  0x49,  0x64,  0xF5,  0x85,  0x48,  0x49,  0x49,  0x62,  0xAA,  0x04,  0x00,  0xA0,  0x3F, 	/* 1A040 */
+	0x8C,  0x16,  0x0E,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x10,  0xCE,  0x02,  0xAB,  0x00, 	/* 1A050 */
+	0x03,  0xF8,  0x24,  0x8F,  0xFE,  0x49,  0x07,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x19,  0x86, 	/* 1A060 */
+	0x06,  0xAC,  0x04,  0x07,  0xFC,  0x04,  0x03,  0xF8,  0x04,  0x0F,  0xFE,  0x20,  0x83,  0xF8,  0x20,  0x83, 	/* 1A070 */
+	0xF8,  0x19,  0x06,  0x0C,  0xAD,  0x00,  0xC3,  0xF0,  0x22,  0x03,  0xFE,  0x22,  0x02,  0xFC,  0x28,  0x42, 	/* 1A080 */
+	0xFC,  0x48,  0x44,  0xFC,  0x8C,  0x43,  0x02,  0xAE,  0x01,  0x07,  0xD8,  0x01,  0x4F,  0xFE,  0x45,  0x07, 	/* 1A090 */
+	0xD0,  0x45,  0x07,  0xD0,  0x44,  0x87,  0xCA,  0x24,  0x6C,  0x22,  0xAF,  0x01,  0x0F,  0xFE,  0x98,  0x29, 	/* 1A0A0 */
+	0x00,  0xF7,  0xE9,  0x10,  0xF1,  0x09,  0x10,  0xF1,  0x03,  0x10,  0x49,  0x08,  0x30,  0xB0,  0x49,  0x0F, 	/* 1A0B0 */
+	0xFE,  0x49,  0x07,  0xFE,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x19,  0x8E,  0x06, 	/* 1A0C0 */
+	0xB2,  0x12,  0x01,  0xE4,  0x53,  0x85,  0xA2,  0xE1,  0xE3,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8, 	/* 1A0D0 */
+	0x10,  0xC6,  0x02,  0xB3,  0x01,  0x80,  0x14,  0xFF,  0xE0,  0x10,  0xFF,  0x00,  0x10,  0x7D,  0x04,  0x48, 	/* 1A0E0 */
+	0x7C,  0x84,  0x4A,  0x7C,  0x6C,  0x22,  0xB4,  0x04,  0x03,  0xF8,  0x24,  0x8F,  0xFE,  0x00,  0x03,  0xF8, 	/* 1A0F0 */
+	0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x11,  0x86,  0x04,  0xB6,  0x00,  0xCF,  0xF0,  0x91,  0x09,  0x10, 	/* 1A100 */
+	0xFF,  0xC9,  0x04,  0xF0,  0x89,  0x08,  0xF5,  0x02,  0x60,  0x55,  0x08,  0x8E,  0xB7,  0x00,  0x07,  0xFC, 	/* 1A110 */
+	0x4A,  0x47,  0xFC,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x11,  0x86,  0x04,  0xB8, 	/* 1A120 */
+	0x12,  0x42,  0xFE,  0xE2,  0x02,  0x12,  0x20,  0xE3,  0xFA,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x11, 	/* 1A130 */
+	0x8E,  0x06,  0xBB,  0x11,  0x0F,  0xFC,  0x51,  0x4F,  0xFE,  0x11,  0x23,  0xFC,  0x20,  0x83,  0xF8,  0x20, 	/* 1A140 */
+	0x83,  0xF8,  0x11,  0x86,  0x06,  0xBC,  0x00,  0x87,  0x88,  0x48,  0x87,  0x8F,  0x48,  0x87,  0x88,  0x48, 	/* 1A150 */
+	0x84,  0xBE,  0x7A,  0x22,  0xA2,  0x46,  0x28,  0x3E,  0xBD,  0x01,  0x07,  0x90,  0x49,  0x04,  0xA8,  0x7A, 	/* 1A160 */
+	0x44,  0xFA,  0x78,  0x24,  0xBC,  0x7A,  0x42,  0xA4,  0x46,  0x48,  0x3C,  0xBF,  0x7B,  0xE4,  0x12,  0x51, 	/* 1A170 */
+	0x27,  0xA6,  0xCC,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x1B,  0x06,  0x0C,  0x80,  0x20, 	/* 1A180 */
+	0x0F,  0xBE,  0x2A,  0x24,  0xA2,  0x9B,  0xE3,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x11,  0x0E, 	/* 1A190 */
+	0x0C,  0x81,  0x04,  0x07,  0xFC,  0x15,  0x0F,  0xFE,  0x11,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83, 	/* 1A1A0 */
+	0xF8,  0x10,  0xCE,  0x02,  0x82,  0x02,  0x0F,  0x3C,  0x92,  0x49,  0x68,  0xF1,  0x89,  0x2C,  0xF4,  0x39, 	/* 1A1B0 */
+	0xBC,  0x92,  0x4F,  0x24,  0x52,  0x48,  0xBC,  0x83,  0x2F,  0xC2,  0x10,  0x7F,  0xEA,  0x10,  0x27,  0xC3, 	/* 1A1C0 */
+	0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x1B,  0x06,  0x0C,  0x84,  0x02,  0x0F,  0x20,  0x9F,  0xEF, 	/* 1A1D0 */
+	0x20,  0x97,  0xC9,  0x44,  0xFF,  0xC9,  0x44,  0xF7,  0xC2,  0x44,  0x54,  0x48,  0x4C,  0x87,  0x44,  0x02, 	/* 1A1E0 */
+	0x7E,  0x09,  0x41,  0x30,  0x24,  0xCF,  0xFA,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x18,  0x86,  0x04, 	/* 1A1F0 */
+	0x88,  0x00,  0x0F,  0xFE,  0x0A,  0x07,  0xFC,  0x4A,  0x47,  0xFC,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8, 	/* 1A200 */
+	0x10,  0xCE,  0x02,  0x8A,  0x00,  0x8F,  0x0A,  0x9F,  0xE9,  0x08,  0xF2,  0xA9,  0x2A,  0xFF,  0xA9,  0x24, 	/* 1A210 */
+	0xF2,  0x42,  0x2E,  0x53,  0x28,  0x22,  0x8D,  0x00,  0x87,  0xBE,  0x4A,  0x84,  0xA8,  0x7A,  0x84,  0xBE, 	/* 1A220 */
+	0x7A,  0x84,  0xA8,  0x7A,  0x82,  0xC8,  0x44,  0x88,  0xBE,  0x8E,  0x02,  0x8F,  0x24,  0x93,  0xC9,  0xE0, 	/* 1A230 */
+	0xF3,  0xC9,  0xE0,  0xF3,  0xE9,  0xD4,  0xF1,  0x42,  0x0A,  0x51,  0x68,  0x62,  0x91,  0x00,  0x0F,  0x7E, 	/* 1A240 */
+	0x94,  0x09,  0x7E,  0xF4,  0x09,  0x7E,  0xF5,  0x29,  0x5C,  0x95,  0x8F,  0x54,  0x55,  0xA8,  0xB1,  0x93, 	/* 1A250 */
+	0x00,  0x0F,  0xFE,  0x94,  0xA2,  0x54,  0xCE,  0x23,  0xFA,  0xE0,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x11, 	/* 1A260 */
+	0x8E,  0x06,  0x9A,  0x04,  0x0F,  0xFE,  0x44,  0x4A,  0xEA,  0x35,  0x8C,  0x46,  0x3F,  0x82,  0x08,  0x3F, 	/* 1A270 */
+	0x82,  0x08,  0x3F,  0x86,  0x0C,  0x9B,  0x20,  0x87,  0xBC,  0x20,  0x8F,  0xBE,  0x51,  0x4B,  0xFA,  0x20, 	/* 1A280 */
+	0x83,  0xF8,  0x20,  0x83,  0xF8,  0x19,  0x86,  0x04,  0x9C,  0x00,  0x0F,  0x7C,  0x94,  0x49,  0x7C,  0xF4, 	/* 1A290 */
+	0x49,  0x7C,  0xF2,  0x09,  0x7E,  0xFA,  0xA2,  0x52,  0x52,  0x28,  0x4C,  0x9E,  0x24,  0x81,  0x50,  0xFF, 	/* 1A2A0 */
+	0xE9,  0xF2,  0x91,  0x23,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x0B,  0x07,  0x0C,  0xA0,  0x01, 	/* 1A2B0 */
+	0x07,  0x90,  0x4F,  0xE7,  0xC4,  0x4A,  0x87,  0xFE,  0x48,  0x04,  0xBC,  0x7A,  0x42,  0xA4,  0x46,  0x48, 	/* 1A2C0 */
+	0x3C,  0xA2,  0xFF,  0xEA,  0x24,  0xF9,  0x88,  0x94,  0xFE,  0x23,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83, 	/* 1A2D0 */
+	0xF8,  0x19,  0x8E,  0x06,  0xA3,  0x04,  0x0F,  0xFE,  0x04,  0x07,  0xFC,  0x4A,  0x47,  0xFC,  0x20,  0x83, 	/* 1A2E0 */
+	0xF8,  0x20,  0x83,  0xF8,  0x10,  0xCE,  0x02,  0xA4,  0x01,  0x4F,  0x16,  0x9F,  0xAF,  0x0C,  0x91,  0x69, 	/* 1A2F0 */
+	0x62,  0xF1,  0x49,  0x1E,  0xFF,  0x42,  0x08,  0x51,  0x68,  0x62,  0xA6,  0x00,  0x6F,  0x75,  0x90,  0x49, 	/* 1A300 */
+	0xFF,  0xF1,  0x49,  0x54,  0xF5,  0xC9,  0x54,  0x95,  0x4F,  0x5A,  0x57,  0x28,  0xC1,  0xAA,  0x18,  0xC6, 	/* 1A310 */
+	0x30,  0x7B,  0xE5,  0x28,  0x94,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x11,  0x86,  0x04, 	/* 1A320 */
+	0xAD,  0x01,  0x0F,  0x7E,  0x91,  0x0F,  0x14,  0x9F,  0xEF,  0x10,  0x93,  0xC9,  0x64,  0xFB,  0xC5,  0x24, 	/* 1A330 */
+	0x4A,  0x48,  0x3C,  0xBA,  0x0D,  0x8F,  0xFC,  0xA5,  0x0A,  0xFC,  0xE5,  0x4B,  0xFE,  0xE5,  0x4B,  0xFC, 	/* 1A340 */
+	0xED,  0x46,  0xD8,  0x55,  0x68,  0x50,  0xBB,  0x02,  0x8F,  0xFE,  0xA2,  0x0E,  0xFC,  0xAA,  0x4A,  0xFC, 	/* 1A350 */
+	0xEA,  0x4A,  0x08,  0xFF,  0xE6,  0x88,  0x54,  0x88,  0x18,  0xBC,  0x04,  0x8F,  0xFE,  0x94,  0x89,  0xFC, 	/* 1A360 */
+	0xF4,  0x89,  0xFE,  0xF5,  0x49,  0x7C,  0xF5,  0x42,  0xFE,  0x54,  0x48,  0x4C,  0xBD,  0x04,  0x0F,  0xFE, 	/* 1A370 */
+	0x91,  0x27,  0xFC,  0x11,  0x0F,  0xFE,  0x20,  0x8F,  0xFE,  0x20,  0x83,  0xF8,  0x11,  0x86,  0x04,  0x84, 	/* 1A380 */
+	0x71,  0x02,  0x7C,  0xF9,  0x45,  0x54,  0xFA,  0x42,  0x56,  0x3F,  0x82,  0x08,  0x3F,  0x82,  0x08,  0x3F, 	/* 1A390 */
+	0x86,  0x0C,  0x85,  0x22,  0x0F,  0xBE,  0x26,  0x4F,  0xD4,  0x51,  0x8B,  0x66,  0x3F,  0x82,  0x08,  0x3F, 	/* 1A3A0 */
+	0x82,  0x08,  0x3F,  0x86,  0x0C,  0x87,  0x23,  0x4F,  0xFE,  0x51,  0x42,  0x5C,  0x55,  0x6B,  0xFA,  0x20, 	/* 1A3B0 */
+	0x83,  0xF8,  0x20,  0x83,  0xF8,  0x11,  0x86,  0x04,  0x88,  0x04,  0x4F,  0x28,  0x9F,  0xEF,  0x92,  0x9F, 	/* 1A3C0 */
+	0xEF,  0x92,  0x9F,  0xE9,  0x44,  0xF7,  0xC2,  0x44,  0x54,  0x48,  0x7C,  0x8A,  0x63,  0x07,  0xBC,  0xA5, 	/* 1A3D0 */
+	0x0F,  0xFC,  0x52,  0x89,  0xCE,  0x3F,  0x82,  0x08,  0x3F,  0x82,  0x08,  0x3F,  0x86,  0x0C,  0x8B,  0x00, 	/* 1A3E0 */
+	0x07,  0xFE,  0x4A,  0x87,  0xFE,  0x54,  0x85,  0x7E,  0x5F,  0x85,  0x08,  0x9F,  0x89,  0x08,  0x1F,  0x83, 	/* 1A3F0 */
+	0x9C,  0x8D,  0x03,  0x8F,  0x50,  0x9F,  0xE9,  0x58,  0xF6,  0xE9,  0x58,  0xF7,  0xE9,  0x40,  0xF5,  0x82, 	/* 1A400 */
+	0xBC,  0x52,  0x48,  0x3C,  0x8F,  0x04,  0x0F,  0xFE,  0x40,  0x07,  0xFC,  0x20,  0x83,  0xF8,  0x79,  0xC5, 	/* 1A410 */
+	0xF4,  0x79,  0xC5,  0xF4,  0x75,  0x49,  0xA6,  0x90,  0x02,  0x0F,  0x7C,  0x92,  0x4F,  0xFE,  0x92,  0x49, 	/* 1A420 */
+	0xFC,  0xF6,  0xA9,  0x95,  0xF7,  0xE2,  0x5A,  0x55,  0xA8,  0xFF,  0x93,  0x00,  0xCF,  0x0A,  0x97,  0xF9, 	/* 1A430 */
+	0x48,  0xF7,  0xA9,  0xDA,  0xF7,  0xA9,  0xD4,  0xF7,  0x43,  0x54,  0x4B,  0xB9,  0x11,  0x94,  0x1F,  0x01, 	/* 1A440 */
+	0x10,  0x1F,  0x01,  0x10,  0x1F,  0x00,  0xA0,  0x71,  0xC4,  0xA4,  0x7B,  0xC4,  0xA4,  0x7B,  0xCC,  0x66, 	/* 1A450 */
+	0x96,  0x01,  0x0F,  0xFE,  0x91,  0x09,  0xFE,  0xFA,  0xA9,  0xFE,  0xF4,  0x49,  0x7C,  0xF4,  0x42,  0x7C, 	/* 1A460 */
+	0x52,  0x48,  0x42,  0xA4,  0x04,  0x00,  0x40,  0x3F,  0x80,  0x40,  0x04,  0x0F,  0xFE,  0x09,  0x02,  0x94, 	/* 1A470 */
+	0x29,  0x24,  0x92,  0x11,  0x02,  0x30,  0xA6,  0x22,  0x02,  0x20,  0xFB,  0xE2,  0x24,  0x24,  0x4F,  0xD4, 	/* 1A480 */
+	0x51,  0x8D,  0x88,  0xD5,  0x85,  0x54,  0x52,  0x4B,  0x42,  0xA7,  0x10,  0x01,  0x3E,  0x7E,  0x21,  0x3E, 	/* 1A490 */
+	0xFE,  0x02,  0xBE,  0x2B,  0x26,  0xEA,  0x6A,  0x4A,  0xAC,  0x2B,  0x25,  0xA1,  0xAB,  0x11,  0x01,  0x10, 	/* 1A4A0 */
+	0x7F,  0xC1,  0x10,  0xFF,  0xE2,  0xA8,  0x2A,  0x86,  0xEC,  0xAA,  0xA2,  0xA8,  0x4C,  0x84,  0xC8,  0xAD, 	/* 1A4B0 */
+	0x10,  0x81,  0x08,  0x7F,  0xE1,  0x0A,  0xFF,  0xF2,  0x94,  0x2B,  0xE6,  0xD2,  0x69,  0xEA,  0x92,  0x29, 	/* 1A4C0 */
+	0x25,  0x9E,  0xB0,  0x04,  0x00,  0x40,  0x7F,  0xC0,  0x40,  0x04,  0x0F,  0xFE,  0x04,  0x02,  0x40,  0x27, 	/* 1A4D0 */
+	0xC3,  0x40,  0x4C,  0x08,  0x3E,  0xB1,  0x04,  0x00,  0x40,  0x7F,  0xC0,  0x40,  0xFF,  0xE1,  0x00,  0x08, 	/* 1A4E0 */
+	0x40,  0x88,  0x23,  0x02,  0xC0,  0x58,  0x08,  0x7F,  0xB3,  0x10,  0x41,  0x24,  0x7A,  0x41,  0x24,  0xFE, 	/* 1A4F0 */
+	0x41,  0x24,  0x52,  0xE5,  0xF4,  0x70,  0x45,  0x04,  0x4C,  0x08,  0x3F,  0xB4,  0x11,  0x01,  0x10,  0x7D, 	/* 1A500 */
+	0x01,  0x10,  0xFD,  0x81,  0x14,  0x5D,  0x25,  0x12,  0x51,  0x07,  0x10,  0x4C,  0x08,  0x3F,  0xB7,  0x10, 	/* 1A510 */
+	0x01,  0x3C,  0x7C,  0x41,  0x04,  0xFF,  0xC1,  0x20,  0x52,  0x05,  0xE2,  0x72,  0x25,  0x1E,  0x8C,  0x08, 	/* 1A520 */
+	0x3F,  0x81,  0x10,  0x81,  0x08,  0x79,  0x41,  0x2A,  0xFF,  0x51,  0x08,  0x51,  0x25,  0xE4,  0x70,  0x85, 	/* 1A530 */
+	0x30,  0x4C,  0x08,  0x3F,  0x85,  0x10,  0x01,  0x7E,  0x79,  0x21,  0x12,  0xFA,  0xC1,  0x40,  0x53,  0xE5, 	/* 1A540 */
+	0xE2,  0x72,  0x25,  0x3E,  0x8C,  0x08,  0x3F,  0x8A,  0x10,  0x81,  0x0A,  0x7B,  0xE1,  0x28,  0xFE,  0xA1, 	/* 1A550 */
+	0x2A,  0x5E,  0x45,  0x2E,  0x77,  0x25,  0x02,  0x8C,  0x08,  0x3F,  0x99,  0x11,  0x01,  0x34,  0x7D,  0x21, 	/* 1A560 */
+	0x3C,  0xFE,  0x41,  0x3C,  0x52,  0x45,  0xFC,  0x72,  0x45,  0x2C,  0x4C,  0x08,  0x3F,  0xA3,  0x20,  0x02, 	/* 1A570 */
+	0xFE,  0xF5,  0x02,  0x7E,  0x25,  0x2F,  0xFA,  0x25,  0x4B,  0x54,  0xEF,  0xAA,  0x12,  0x99,  0x08,  0x7F, 	/* 1A580 */
+	0xA8,  0x22,  0x02,  0x3E,  0xF4,  0xA2,  0xBE,  0x20,  0xAF,  0xB2,  0x23,  0xEB,  0xCA,  0xEB,  0xEA,  0x12, 	/* 1A590 */
+	0x9A,  0x48,  0x7F,  0xB3,  0x00,  0x03,  0xFC,  0x20,  0x42,  0x04,  0x3F,  0xC0,  0x40,  0x24,  0x02,  0x7C, 	/* 1A5A0 */
+	0x24,  0x03,  0x40,  0x4E,  0x08,  0x1E,  0xBA,  0x01,  0x0F,  0x10,  0x97,  0xC9,  0x10,  0xF1,  0x02,  0xFE, 	/* 1A5B0 */
+	0xA1,  0x0B,  0x10,  0xA2,  0x8A,  0x28,  0xB4,  0x4D,  0x82,  0xBE,  0x01,  0x0F,  0x10,  0x91,  0x09,  0x10, 	/* 1A5C0 */
+	0xF5,  0x02,  0x5C,  0xA5,  0x0B,  0x50,  0xA5,  0x0A,  0xD0,  0xB5,  0x0C,  0xFE,  0x82,  0x01,  0x0F,  0x10, 	/* 1A5D0 */
+	0x97,  0xE9,  0x10,  0xF1,  0x02,  0x7C,  0xA0,  0x4B,  0xA4,  0xA1,  0x8B,  0x98,  0xE6,  0x49,  0x82,  0x8B, 	/* 1A5E0 */
+	0x02,  0x8F,  0x24,  0x9F,  0xE9,  0x20,  0xF2,  0x22,  0x32,  0xA3,  0x4B,  0x34,  0xA4,  0x8A,  0x58,  0xB9, 	/* 1A5F0 */
+	0x4D,  0x22,  0x8C,  0x01,  0x0F,  0x50,  0x97,  0xC9,  0x50,  0xF5,  0x02,  0x90,  0xAF,  0xEB,  0x10,  0xA3, 	/* 1A600 */
+	0x0A,  0x28,  0xB4,  0x4D,  0x82,  0x8F,  0x04,  0x0F,  0x4E,  0x94,  0xA9,  0xFA,  0xF5,  0xA2,  0x5A,  0xA5, 	/* 1A610 */
+	0xAB,  0x5A,  0xA5,  0xAB,  0x5A,  0xE9,  0xE9,  0x60,  0x96,  0x00,  0x0F,  0x7E,  0x91,  0x09,  0x10,  0xF1, 	/* 1A620 */
+	0x02,  0x3E,  0xA3,  0x2B,  0x52,  0xA5,  0x2A,  0x92,  0xB1,  0x2C,  0x1E,  0x9A,  0x00,  0x0F,  0xFE,  0x9A, 	/* 1A630 */
+	0xA9,  0xAA,  0xFA,  0xA2,  0xFF,  0xAA,  0xAB,  0xAA,  0xAA,  0xAA,  0xAA,  0xBA,  0xAC,  0x86,  0x9B,  0x01, 	/* 1A640 */
+	0x0F,  0x10,  0x97,  0xE9,  0x54,  0xF5,  0x02,  0x50,  0xA7,  0xCB,  0x44,  0xA5,  0x4A,  0x88,  0xB9,  0x4D, 	/* 1A650 */
+	0x62,  0x9D,  0x00,  0x0F,  0x7E,  0x94,  0x09,  0x40,  0xF7,  0xC2,  0x44,  0xA4,  0x4B,  0xFC,  0xA4,  0x0A, 	/* 1A660 */
+	0xC0,  0xB4,  0x0C,  0x7E,  0x9F,  0x00,  0x0F,  0x7C,  0x94,  0x49,  0x7C,  0xF4,  0x42,  0x44,  0xA7,  0xCB, 	/* 1A670 */
+	0xD2,  0xA5,  0x4A,  0xC8,  0xB6,  0x4C,  0xC2,  0xA1,  0x01,  0x0F,  0x10,  0x9F,  0xE9,  0x28,  0xF2,  0x82, 	/* 1A680 */
+	0xAC,  0xBA,  0xAA,  0xAA,  0xAA,  0xAB,  0xA8,  0xE4,  0x88,  0x98,  0xA3,  0x01,  0x0F,  0x50,  0x97,  0xC9, 	/* 1A690 */
+	0x50,  0xF5,  0x02,  0x90,  0xAF,  0xEB,  0xA8,  0xA2,  0x8A,  0xAA,  0xB4,  0xAC,  0x86,  0xA8,  0x01,  0x0F, 	/* 1A6A0 */
+	0x7E,  0x91,  0x09,  0x28,  0xF7,  0xC2,  0x82,  0xA7,  0xEB,  0xA0,  0xA3,  0xCA,  0x84,  0xB0,  0x4C,  0x18, 	/* 1A6B0 */
+	0xAA,  0x03,  0xCF,  0x48,  0x99,  0x09,  0x7E,  0xF4,  0x02,  0x5C,  0xA5,  0x4B,  0x54,  0xA5,  0xCA,  0x90, 	/* 1A6C0 */
+	0xB9,  0x2D,  0x0E,  0xAB,  0x00,  0x0F,  0xBC,  0x22,  0x43,  0xB5,  0xC4,  0xB3,  0xFC,  0x20,  0x43,  0xFC, 	/* 1A6D0 */
+	0x14,  0x01,  0x7C,  0x2C,  0x0C,  0x3E,  0xAF,  0x02,  0x0F,  0x3C,  0x92,  0x49,  0x68,  0xF1,  0x02,  0x2C, 	/* 1A6E0 */
+	0xA4,  0x3B,  0xBC,  0xA2,  0x4A,  0xA4,  0xB2,  0x4C,  0x3C,  0xB3,  0x02,  0x8F,  0x28,  0x92,  0x89,  0xAA, 	/* 1A6F0 */
+	0xF6,  0xC2,  0x28,  0xA6,  0xCB,  0xAA,  0xA2,  0xAB,  0xA8,  0xE4,  0xA8,  0x86,  0xB5,  0x02,  0x8F,  0x24, 	/* 1A700 */
+	0x93,  0xC9,  0xE0,  0xF3,  0xC2,  0xE0,  0xA3,  0xEB,  0xD4,  0xA1,  0x4B,  0x8A,  0xE3,  0x68,  0xC2,  0xBC, 	/* 1A710 */
+	0x00,  0x0F,  0x7C,  0x94,  0x49,  0x7C,  0xF4,  0x02,  0x7E,  0xA4,  0x2B,  0xFA,  0xA6,  0xAA,  0xBA,  0xB8, 	/* 1A720 */
+	0x2D,  0x0C,  0xBF,  0x01,  0x0F,  0x10,  0x97,  0xC9,  0x10,  0xFF,  0xE2,  0x10,  0xA5,  0x0B,  0xDC,  0xA5, 	/* 1A730 */
+	0x0A,  0x50,  0xBB,  0x0D,  0x0E,  0x88,  0x01,  0x0F,  0x7E,  0x91,  0x09,  0x7C,  0xF5,  0x42,  0x54,  0xA7, 	/* 1A740 */
+	0xCB,  0xB8,  0xA3,  0x8A,  0x54,  0xB9,  0x2C,  0x10,  0x89,  0x01,  0x0F,  0x20,  0x97,  0xC9,  0x44,  0xF7, 	/* 1A750 */
+	0xC2,  0x44,  0xA7,  0xCB,  0xD2,  0xA5,  0x4A,  0xC8,  0xB7,  0x4C,  0xC2,  0x8A,  0x00,  0x0F,  0x7C,  0x92, 	/* 1A760 */
+	0x89,  0x10,  0xFF,  0xE2,  0x92,  0xAF,  0xEB,  0x92,  0xAF,  0xEB,  0x92,  0xE9,  0x28,  0x96,  0x8F,  0x01, 	/* 1A770 */
+	0x0F,  0x90,  0x95,  0x69,  0x38,  0xF5,  0x42,  0x92,  0xA3,  0x0B,  0xFC,  0xA4,  0x4A,  0x7C,  0xBC,  0x4C, 	/* 1A780 */
+	0x7C,  0x90,  0x02,  0x8F,  0x24,  0x91,  0xE9,  0xF4,  0xF0,  0xA2,  0x36,  0xAE,  0x8B,  0x3E,  0xAE,  0x8A, 	/* 1A790 */
+	0x12,  0xB2,  0xEC,  0xC2,  0x9D,  0x00,  0x0F,  0x7C,  0x95,  0x49,  0x7C,  0xF5,  0x42,  0x7C,  0xA1,  0x0B, 	/* 1A7A0 */
+	0xFE,  0xA3,  0x8A,  0x54,  0xB9,  0x2C,  0x10,  0x9E,  0x00,  0x0F,  0x7E,  0x94,  0x29,  0x7E,  0xF4,  0x82, 	/* 1A7B0 */
+	0x7F,  0xA4,  0x8B,  0xC8,  0xA7,  0xEA,  0xA2,  0xBA,  0x2D,  0x3E,  0x9F,  0x04,  0x0F,  0x4E,  0x97,  0xA9, 	/* 1A7C0 */
+	0x6A,  0xFA,  0xA2,  0xAA,  0xAF,  0xAB,  0x2A,  0xA2,  0xAA,  0x3A,  0xB4,  0xEC,  0x80,  0xAA,  0x01,  0x0F, 	/* 1A7D0 */
+	0xFE,  0x98,  0x29,  0x82,  0xF3,  0x82,  0x00,  0xA7,  0xEB,  0x10,  0xA5,  0x4A,  0x52,  0xB9,  0x2C,  0x30, 	/* 1A7E0 */
+	0xB0,  0x07,  0x0F,  0x28,  0x94,  0x49,  0xBA,  0xF0,  0x12,  0xEA,  0xAA,  0xAB,  0xF4,  0xAB,  0x4A,  0xF4, 	/* 1A7F0 */
+	0xBA,  0xAC,  0xAA,  0xB4,  0x00,  0x0F,  0x7E,  0x91,  0x49,  0x7E,  0xF5,  0x22,  0x7E,  0xA7,  0xEB,  0x90, 	/* 1A800 */
+	0xA7,  0xEA,  0x92,  0xB2,  0x2C,  0x4C,  0xB5,  0x00,  0xCF,  0x70,  0x91,  0x09,  0xFE,  0xF5,  0x42,  0x7C, 	/* 1A810 */
+	0xA5,  0x4B,  0xFC,  0xA1,  0x0A,  0x7C,  0xB1,  0x0C,  0xFE,  0x82,  0x00,  0x0F,  0x7C,  0x92,  0x89,  0xFE, 	/* 1A820 */
+	0xF3,  0x42,  0x50,  0xAB,  0x0B,  0x10,  0xAF,  0xEA,  0x38,  0xB5,  0x4C,  0x92,  0x84,  0x01,  0x0F,  0xFE, 	/* 1A830 */
+	0x94,  0x49,  0x28,  0xFF,  0xE2,  0x92,  0xA7,  0xCB,  0xD4,  0xA5,  0x4A,  0xDC,  0xB5,  0x0C,  0x10,  0x87, 	/* 1A840 */
+	0x04,  0x0F,  0xFE,  0x91,  0x2B,  0xFA,  0x11,  0x0F,  0xFE,  0x20,  0x85,  0xF4,  0x91,  0x25,  0xFC,  0x64, 	/* 1A850 */
+	0x09,  0xFE,  0x88,  0x00,  0xCF,  0x78,  0x95,  0x49,  0x52,  0xF9,  0x22,  0x20,  0xA6,  0xCB,  0xC4,  0xA6, 	/* 1A860 */
+	0xCA,  0xC4,  0xB4,  0x4C,  0x7C,  0x89,  0x02,  0x4F,  0x7E,  0x91,  0x09,  0x7C,  0xF1,  0x02,  0xFE,  0xA2, 	/* 1A870 */
+	0x0B,  0xBE,  0xA2,  0x8A,  0x48,  0xB8,  0x8D,  0x7E,  0x8A,  0x00,  0xCF,  0x78,  0x95,  0x49,  0x92,  0xF3, 	/* 1A880 */
+	0x02,  0xC8,  0xA3,  0x4B,  0xFE,  0xA1,  0x0A,  0x7E,  0xBA,  0x8C,  0x44,  0x8C,  0x01,  0x0F,  0x18,  0x92, 	/* 1A890 */
+	0x49,  0x7E,  0xFA,  0x52,  0x3C,  0xA2,  0x4B,  0xBC,  0xA4,  0x0A,  0xBE,  0xB2,  0x2C,  0x3E,  0x90,  0x01, 	/* 1A8A0 */
+	0x0F,  0xD6,  0x91,  0x09,  0xD6,  0xF2,  0x82,  0x7C,  0xAC,  0x6B,  0x7D,  0xA4,  0x4A,  0x7C,  0xB4,  0x4C, 	/* 1A8B0 */
+	0x4C,  0x95,  0x00,  0x0F,  0x7E,  0x95,  0x29,  0x7E,  0xF5,  0x22,  0xFE,  0xA5,  0x4B,  0xFF,  0xA5,  0x4A, 	/* 1A8C0 */
+	0xFE,  0xB1,  0x0C,  0x10,  0x99,  0x01,  0x47,  0xFE,  0x49,  0x07,  0xF4,  0x48,  0xAA,  0xAE,  0xA9,  0x23, 	/* 1A8D0 */
+	0xF8,  0x20,  0x83,  0xFC,  0x5A,  0x08,  0x7E,  0x9F,  0x01,  0x0F,  0xFE,  0x91,  0x09,  0x7C,  0xF1,  0x02, 	/* 1A8E0 */
+	0xFE,  0xB4,  0x4A,  0x7C,  0xA4,  0x4B,  0xFC,  0xE2,  0x48,  0xC2,  0xA0,  0x00,  0x8F,  0x7E,  0x94,  0x09, 	/* 1A8F0 */
+	0x54,  0xF7,  0xE2,  0x54,  0xA5,  0x4B,  0xDC,  0xA4,  0x0A,  0x54,  0xBA,  0xAC,  0xAA,  0xA3,  0x02,  0x8F, 	/* 1A900 */
+	0xFE,  0x92,  0x89,  0x38,  0xF1,  0x02,  0xFE,  0xA9,  0x2B,  0xFE,  0xAB,  0x6A,  0xDA,  0xB9,  0x2C,  0x96, 	/* 1A910 */
+	0xA4,  0x05,  0x4F,  0x54,  0x99,  0x49,  0x6A,  0x94,  0x2E,  0x88,  0x3A,  0x8A,  0xAE,  0xBA,  0x8A,  0xA8, 	/* 1A920 */
+	0xBD,  0x8C,  0x87,  0xB2,  0x01,  0xCF,  0x24,  0x92,  0x29,  0x7F,  0xFD,  0xA2,  0x56,  0xA7,  0xEB,  0x84, 	/* 1A930 */
+	0xA7,  0xFA,  0xA4,  0xB0,  0x4C,  0x0C,  0xB4,  0x04,  0x8F,  0xEC,  0x90,  0xA9,  0xFE,  0xFA,  0x82,  0xA8, 	/* 1A940 */
+	0xBF,  0x8A,  0x58,  0xAF,  0x8B,  0x5A,  0xE6,  0xA8,  0xC6,  0xB6,  0x00,  0x0F,  0x7E,  0x96,  0xC9,  0x54, 	/* 1A950 */
+	0xF7,  0xF2,  0x5A,  0xB5,  0x6A,  0x54,  0xA7,  0xEB,  0x96,  0xEA,  0xA1,  0x51,  0xBC,  0x02,  0x8F,  0x6A, 	/* 1A960 */
+	0x9F,  0xE9,  0x28,  0xFF,  0xE2,  0x10,  0xAF,  0xEB,  0x10,  0xAF,  0xEA,  0xA8,  0xB4,  0x4C,  0x82,  0x81, 	/* 1A970 */
+	0x07,  0x8F,  0x48,  0x97,  0x89,  0xEE,  0xFA,  0xA2,  0xEE,  0xA1,  0x0B,  0xFE,  0xA3,  0x8A,  0x54,  0xB9, 	/* 1A980 */
+	0x2C,  0x10,  0x84,  0x78,  0x84,  0xBE,  0x79,  0x44,  0x3E,  0x78,  0x84,  0xBE,  0xB8,  0x81,  0xF8,  0x10, 	/* 1A990 */
+	0x85,  0xFC,  0x62,  0x09,  0xFE,  0x85,  0x1F,  0xCF,  0x54,  0x9F,  0xC9,  0x40,  0xF7,  0xE2,  0xA2,  0xAF, 	/* 1A9A0 */
+	0xAB,  0xAA,  0xAF,  0xAA,  0x22,  0xB3,  0xAC,  0xCC,  0x87,  0x04,  0x8F,  0xFE,  0x94,  0x89,  0xFE,  0xF2, 	/* 1A9B0 */
+	0x42,  0xFE,  0xA2,  0x8B,  0x7C,  0xA4,  0x4A,  0xFC,  0xB4,  0x4C,  0x7C,  0x8A,  0x00,  0x8F,  0x7E,  0x90, 	/* 1A9C0 */
+	0x89,  0x7F,  0xF0,  0x22,  0x7E,  0xA0,  0x8B,  0xFF,  0xA7,  0x2A,  0xDA,  0xB7,  0x2C,  0x06,  0x8B,  0x01, 	/* 1A9D0 */
+	0x0F,  0xFE,  0x92,  0x89,  0xF6,  0xF5,  0xC2,  0x54,  0xAA,  0xAB,  0xFC,  0xA4,  0x4A,  0xFC,  0xB4,  0x4C, 	/* 1A9E0 */
+	0x84,  0x8D,  0x00,  0x0F,  0xEE,  0x92,  0x29,  0xEE,  0xF2,  0x22,  0xEE,  0xA4,  0x8B,  0xFE,  0xA9,  0x0A, 	/* 1A9F0 */
+	0xFC,  0xB9,  0x0C,  0xFE,  0x91,  0x06,  0x0F,  0x5E,  0x98,  0xA9,  0xFA,  0xFA,  0xA2,  0xDC,  0xAF,  0xAA, 	/* 1AA00 */
+	0x2A,  0xBF,  0xAA,  0x6E,  0xB5,  0x8C,  0x88,  0x93,  0x02,  0x4F,  0x48,  0x97,  0xF9,  0xAA,  0xFA,  0xA2, 	/* 1AA10 */
+	0x7C,  0xA4,  0x4B,  0xFC,  0xA4,  0x4A,  0xFC,  0xB2,  0x4E,  0xC2,  0x94,  0x00,  0x8F,  0x7E,  0x96,  0xA9, 	/* 1AA20 */
+	0x7E,  0xF6,  0xA2,  0x7E,  0xBD,  0x4A,  0x66,  0xA4,  0x8B,  0xBE,  0xC8,  0x81,  0x7F,  0x99,  0x77,  0x75, 	/* 1AA30 */
+	0x55,  0x57,  0x75,  0x41,  0x75,  0x52,  0x5F,  0x27,  0x53,  0xDF,  0xA5,  0x5A,  0x5F,  0xBD,  0x5C,  0x5F, 	/* 1AA40 */
+	0xA1,  0x0F,  0xEF,  0x24,  0x93,  0xC9,  0x24,  0x97,  0xCF,  0x04,  0x2F,  0xFA,  0xAA,  0xBE,  0xEA,  0xAA, 	/* 1AA50 */
+	0xBF,  0xEC,  0x22,  0xAA,  0x02,  0x8F,  0xFE,  0x92,  0x89,  0xEE,  0xFA,  0xA2,  0xEE,  0xAA,  0xAB,  0xFE, 	/* 1AA60 */
+	0xAA,  0xAA,  0xBA,  0xBA,  0xAC,  0xBA,  0xAB,  0x04,  0x01,  0xF8,  0x10,  0x81,  0xF8,  0x10,  0x91,  0xFA, 	/* 1AA70 */
+	0x10,  0xCF,  0xF8,  0x06,  0x81,  0x88,  0x60,  0x80,  0x18,  0xAC,  0x20,  0x07,  0x9E,  0x48,  0x27,  0x82, 	/* 1AA80 */
+	0x49,  0xE7,  0xA0,  0x4F,  0xEF,  0x82,  0x18,  0x22,  0x82,  0xC8,  0x21,  0x8C,  0xAF,  0x20,  0x07,  0xBE, 	/* 1AA90 */
+	0x4A,  0x07,  0xA2,  0x4B,  0x27,  0xAC,  0x4E,  0x4F,  0xAA,  0x1A,  0xA2,  0xB0,  0xCA,  0x01,  0xBE,  0xB0, 	/* 1AAA0 */
+	0x21,  0x07,  0x90,  0x49,  0x07,  0xFE,  0x49,  0x07,  0xB8,  0x4B,  0x8F,  0xD4,  0x1D,  0x42,  0xBA,  0xC9, 	/* 1AAB0 */
+	0x01,  0x90,  0xB1,  0x20,  0x07,  0xFC,  0x49,  0x47,  0x96,  0x4A,  0x27,  0xCC,  0x49,  0x0F,  0xFE,  0x19, 	/* 1AAC0 */
+	0x02,  0xB8,  0xCD,  0x61,  0x90,  0xBE,  0x24,  0x47,  0xA8,  0x4F,  0xE7,  0x90,  0x4F,  0xC7,  0x90,  0x4F, 	/* 1AAD0 */
+	0xEF,  0x90,  0x1F,  0xE2,  0x90,  0xCA,  0x81,  0xC6,  0x85,  0x20,  0x07,  0x7E,  0x55,  0x27,  0x54,  0x55, 	/* 1AAE0 */
+	0xE7,  0x74,  0x57,  0xEF,  0x54,  0x35,  0xE5,  0x54,  0x9D,  0x43,  0x5E,  0x86,  0x21,  0x87,  0x7E,  0x55, 	/* 1AAF0 */
+	0xA7,  0x7E,  0x55,  0xA7,  0xFF,  0x58,  0x0F,  0x7E,  0x34,  0x25,  0x7E,  0x92,  0x43,  0x7E,  0x88,  0x20, 	/* 1AB00 */
+	0x87,  0x7E,  0x55,  0x47,  0x7E,  0x55,  0x47,  0x5E,  0x55,  0x4F,  0x5E,  0x35,  0x05,  0x54,  0x9B,  0x23, 	/* 1AB10 */
+	0x4E,  0x8A,  0x04,  0x0F,  0xFE,  0x04,  0x07,  0xFC,  0x44,  0x47,  0xFC,  0x44,  0x47,  0xFC,  0x04,  0x0F, 	/* 1AB20 */
+	0xFE,  0x04,  0x00,  0x40,  0x8B,  0x11,  0x0F,  0xF0,  0x11,  0x07,  0xD0,  0x55,  0x07,  0xD0,  0x55,  0x07, 	/* 1AB30 */
+	0xD0,  0x11,  0x0F,  0xF2,  0x11,  0x21,  0x0E,  0x8C,  0x22,  0x0F,  0xA0,  0x22,  0x0F,  0xF8,  0xAA,  0x8F, 	/* 1AB40 */
+	0xA8,  0xAA,  0x8F,  0xA8,  0x22,  0x8F,  0xCA,  0x24,  0xA2,  0x86,  0x8D,  0xFF,  0xE8,  0x42,  0xBF,  0xA0, 	/* 1AB50 */
+	0x40,  0x7F,  0xC4,  0x44,  0x7F,  0xC4,  0x44,  0x7F,  0xC0,  0x40,  0xFF,  0xE0,  0x40,  0x92,  0x20,  0x0F, 	/* 1AB60 */
+	0xBE,  0x20,  0x8F,  0x88,  0xA8,  0x8F,  0xFE,  0xA8,  0x8F,  0x88,  0x20,  0x8F,  0xC8,  0x20,  0x82,  0x08, 	/* 1AB70 */
+	0x9B,  0x20,  0x0F,  0xBE,  0x22,  0x0F,  0xA0,  0xAB,  0xEF,  0xB2,  0xAB,  0x2F,  0xB6,  0x23,  0x0F,  0xD2, 	/* 1AB80 */
+	0x25,  0x22,  0x8E,  0x9F,  0x22,  0x0F,  0xA0,  0x22,  0x0F,  0xBE,  0xAD,  0x2F,  0xD4,  0xA9,  0x0F,  0x90, 	/* 1AB90 */
+	0x23,  0x0F,  0xA8,  0x24,  0x42,  0x82,  0xA2,  0x20,  0x0F,  0xBC,  0x20,  0x0F,  0x80,  0xAF,  0xEF,  0x90, 	/* 1ABA0 */
+	0xA9,  0x0F,  0x98,  0x22,  0x4F,  0xAC,  0x27,  0x22,  0x02,  0xA3,  0x04,  0x0F,  0xFE,  0x24,  0x83,  0xF8, 	/* 1ABB0 */
+	0x24,  0x8F,  0xFE,  0x04,  0x06,  0x0C,  0x11,  0x00,  0xA0,  0x31,  0x8C,  0x06,  0xAB,  0x21,  0x0F,  0x90, 	/* 1ABC0 */
+	0x22,  0x8F,  0xC4,  0xA9,  0x2F,  0xE4,  0xA8,  0x8F,  0x92,  0x26,  0x4F,  0x88,  0x23,  0x02,  0xC0,  0xB8, 	/* 1ABD0 */
+	0x20,  0x8F,  0x88,  0x23,  0xEF,  0xAA,  0xAA,  0xAF,  0xAA,  0xAB,  0xEF,  0xAA,  0x22,  0xAF,  0xAA,  0x23, 	/* 1ABE0 */
+	0xE2,  0x20,  0xBB,  0x20,  0x0F,  0xFE,  0x20,  0x4F,  0x84,  0xAF,  0x4F,  0xD4,  0xAD,  0x4F,  0xD4,  0x27, 	/* 1ABF0 */
+	0x4F,  0x84,  0x20,  0x42,  0x0C,  0xBC,  0x20,  0x8F,  0xA8,  0x22,  0x8F,  0xBE,  0xAC,  0x8F,  0x88,  0xAF, 	/* 1AC00 */
+	0xEF,  0x88,  0x21,  0x8F,  0x94,  0x22,  0x22,  0xC1,  0xBD,  0x20,  0x0F,  0xBE,  0x20,  0x2F,  0x94,  0xA8, 	/* 1AC10 */
+	0x8F,  0xB6,  0xA8,  0x8F,  0x88,  0x23,  0xEF,  0x88,  0x20,  0x82,  0x7F,  0xBE,  0x20,  0xCF,  0x8A,  0x20, 	/* 1AC20 */
+	0x8F,  0xFE,  0xA8,  0x8F,  0xF8,  0xAA,  0x8F,  0xA8,  0x22,  0xAF,  0xBA,  0x2C,  0x62,  0x02,  0x83,  0x21, 	/* 1AC30 */
+	0x0F,  0x10,  0x2F,  0xEF,  0xA8,  0xAC,  0x4F,  0x8A,  0xAC,  0x8F,  0xA8,  0x21,  0x0F,  0xA8,  0x24,  0x42, 	/* 1AC40 */
+	0x82,  0x85,  0x21,  0x0F,  0x9E,  0x22,  0x4F,  0xD4,  0xA8,  0x8F,  0x94,  0xAA,  0x2F,  0xC1,  0x23,  0xCF, 	/* 1AC50 */
+	0xA4,  0x22,  0x42,  0x3C,  0x89,  0x11,  0x07,  0xD4,  0x11,  0x2F,  0xFE,  0x11,  0x0F,  0xF4,  0x55,  0x47, 	/* 1AC60 */
+	0xC8,  0x54,  0x8F,  0xFA,  0x12,  0x61,  0x02,  0x8A,  0x20,  0x0F,  0xFE,  0x22,  0x0F,  0xA8,  0xAC,  0x4F, 	/* 1AC70 */
+	0xFE,  0xA9,  0x2F,  0x90,  0x27,  0xCF,  0x90,  0x21,  0x02,  0xFE,  0x8C,  0x20,  0x0F,  0xFE,  0x21,  0x0F, 	/* 1AC80 */
+	0x90,  0xAF,  0xEF,  0x92,  0xAD,  0x6F,  0xD6,  0x2F,  0xEF,  0x82,  0x28,  0x22,  0x86,  0x92,  0x20,  0x0F, 	/* 1AC90 */
+	0xFF,  0x25,  0x4F,  0x54,  0xA7,  0x4F,  0x54,  0xA7,  0x4F,  0x54,  0x25,  0x4F,  0x75,  0x2D,  0x52,  0x13, 	/* 1ACA0 */
+	0x93,  0x22,  0x0F,  0xBC,  0x24,  0x8F,  0xFC,  0xAD,  0x4F,  0xD4,  0xAF,  0xCF,  0xA8,  0x22,  0x8F,  0xAA, 	/* 1ACB0 */
+	0x24,  0xA2,  0x86,  0x94,  0x21,  0x4F,  0x92,  0x27,  0xEF,  0x90,  0xAF,  0xEF,  0xD2,  0xAF,  0xEF,  0xD2, 	/* 1ACC0 */
+	0x27,  0xEF,  0xD2,  0x25,  0x22,  0x56,  0x95,  0x27,  0xEF,  0x80,  0x22,  0xAF,  0xAA,  0xAD,  0x4F,  0xAA, 	/* 1ACD0 */
+	0xAA,  0xAF,  0x80,  0x27,  0xEF,  0x90,  0x21,  0x02,  0xFE,  0x99,  0x20,  0x0F,  0xFF,  0x25,  0x0F,  0xDE, 	/* 1ACE0 */
+	0xAF,  0xAF,  0xDA,  0xAF,  0x4F,  0xD4,  0x25,  0x4F,  0xFA,  0x2D,  0xA2,  0x11,  0x9B,  0x20,  0x0F,  0xFE, 	/* 1ACF0 */
+	0x21,  0x0F,  0x90,  0xAF,  0xEF,  0x92,  0xAF,  0xEF,  0xB6,  0x2D,  0xAF,  0x92,  0x29,  0x22,  0x96,  0x9C, 	/* 1AD00 */
+	0x22,  0xAF,  0xAA,  0x25,  0x4F,  0xAA,  0xAA,  0xAF,  0x80,  0xAF,  0xEF,  0xD2,  0x27,  0xEF,  0xD2,  0x25, 	/* 1AD10 */
+	0x22,  0x7E,  0x9D,  0x27,  0xEA,  0x52,  0xAF,  0xC7,  0x10,  0x27,  0xEF,  0xD2,  0x57,  0xE5,  0x52,  0x5F, 	/* 1AD20 */
+	0xE5,  0x10,  0x8F,  0xE0,  0x10,  0x9F,  0x20,  0x0F,  0xFE,  0x25,  0xAF,  0xB4,  0xAA,  0xAF,  0xD0,  0xAF, 	/* 1AD30 */
+	0xEF,  0x92,  0x25,  0xAF,  0xA4,  0x25,  0xA2,  0x91,  0xA6,  0x20,  0x87,  0xBC,  0x20,  0x8F,  0xBE,  0x51, 	/* 1AD40 */
+	0x48,  0xA2,  0x7F,  0xC2,  0x48,  0x3F,  0x82,  0x48,  0xFF,  0xE0,  0x40,  0xA9,  0x0A,  0x07,  0xBC,  0x0A, 	/* 1AD50 */
+	0x0F,  0xBE,  0x16,  0x0F,  0xFE,  0x24,  0x83,  0xF8,  0x24,  0x83,  0xF8,  0xFF,  0xE0,  0x40,  0xAA,  0x21, 	/* 1AD60 */
+	0x0F,  0x90,  0x22,  0x8F,  0xC4,  0xAF,  0xEF,  0x81,  0xAF,  0xEF,  0xAA,  0x2F,  0xEF,  0xAA,  0x2A,  0xA2, 	/* 1AD70 */
+	0x86,  0xAF,  0x23,  0xEF,  0xA2,  0x23,  0xEF,  0x80,  0xAF,  0xFF,  0xA2,  0xAB,  0xEF,  0xA2,  0x23,  0xEF, 	/* 1AD80 */
+	0xA2,  0x27,  0xF2,  0x02,  0xB3,  0x21,  0x0F,  0xFC,  0x21,  0x0F,  0xFE,  0xAA,  0x8F,  0xC4,  0xAB,  0xAF, 	/* 1AD90 */
+	0x91,  0x27,  0xCF,  0x90,  0x22,  0x82,  0x44,  0xB8,  0x21,  0x0F,  0xA8,  0x24,  0x4F,  0xBA,  0xA8,  0x0F, 	/* 1ADA0 */
+	0xEA,  0xAA,  0xAF,  0xEA,  0x2A,  0xAF,  0xEA,  0x2A,  0x22,  0xA6,  0xB9,  0x21,  0x0F,  0xBE,  0x26,  0x4F, 	/* 1ADB0 */
+	0xBC,  0xAA,  0x4F,  0xBC,  0xA9,  0x0F,  0x9C,  0x22,  0x4F,  0xD8,  0x22,  0x42,  0xC2,  0xBB,  0x27,  0xEF, 	/* 1ADC0 */
+	0x80,  0x23,  0xCF,  0xA4,  0xAB,  0xCF,  0x80,  0xAF,  0xEF,  0xD2,  0x27,  0xEF,  0xD2,  0x25,  0x22,  0x7E, 	/* 1ADD0 */
+	0xBE,  0x20,  0x0F,  0x7E,  0x24,  0x2F,  0x7E,  0xA5,  0x4F,  0x7E,  0xA5,  0x4F,  0x7E,  0x26,  0x8F,  0xAA, 	/* 1ADE0 */
+	0x2A,  0x42,  0x72,  0xBF,  0x2E,  0x0C,  0x4E,  0x9F,  0x2F,  0x5E,  0x9F,  0x29,  0x52,  0xFF,  0xE8,  0x42, 	/* 1ADF0 */
+	0xFF,  0xF1,  0x10,  0x20,  0xCC,  0x02,  0x82,  0x23,  0x8F,  0xA8,  0x22,  0xAF,  0xAA,  0x8C,  0x62,  0x00, 	/* 1AE00 */
+	0xFB,  0xEA,  0xA4,  0xF9,  0x4A,  0x88,  0xFD,  0x42,  0x62,  0x84,  0x21,  0x0F,  0xFE,  0x29,  0x2F,  0xFC, 	/* 1AE10 */
+	0xA9,  0x0F,  0xFC,  0xA9,  0x0F,  0xFE,  0x20,  0x0F,  0xFC,  0x24,  0x42,  0x7C,  0x85,  0x21,  0x0F,  0xFC, 	/* 1AE20 */
+	0x21,  0x0F,  0xFE,  0xA8,  0x0F,  0xFC,  0xAC,  0x4F,  0xBC,  0x26,  0xAF,  0xAC,  0x22,  0x42,  0x72,  0x86, 	/* 1AE30 */
+	0x20,  0x8F,  0x7E,  0x25,  0x8F,  0x7E,  0xA5,  0xAF,  0x7E,  0xA6,  0x8F,  0x6A,  0x27,  0xCF,  0xE8,  0x2B, 	/* 1AE40 */
+	0xA2,  0x66,  0x89,  0x21,  0x0F,  0xFE,  0x25,  0x4F,  0xFC,  0xAD,  0x4F,  0xFC,  0xAA,  0xAF,  0xFE,  0x24, 	/* 1AE50 */
+	0x8F,  0xA8,  0x20,  0x82,  0x18,  0x8C,  0x27,  0xCF,  0x10,  0x2F,  0xEF,  0x92,  0xAD,  0xAF,  0xB6,  0xA8, 	/* 1AE60 */
+	0x0F,  0xFC,  0x20,  0x4F,  0xFE,  0x20,  0x42,  0x7C,  0x8D,  0x24,  0x8F,  0xF8,  0x2A,  0xFF,  0xEA,  0xB3, 	/* 1AE70 */
+	0x2F,  0xEA,  0xBA,  0xAF,  0xE4,  0x2A,  0x4F,  0xE4,  0x2A,  0xA2,  0xB1,  0x8E,  0x27,  0xCF,  0x90,  0x27, 	/* 1AE80 */
+	0xEF,  0xB8,  0xAC,  0x4F,  0xBA,  0xAA,  0x8F,  0x7E,  0x2B,  0xAF,  0xAA,  0x2B,  0xA2,  0x86,  0x97,  0x20, 	/* 1AE90 */
+	0xAF,  0xFE,  0x24,  0x8F,  0x7A,  0xA4,  0xAF,  0x74,  0xA5,  0x4F,  0x7A,  0x29,  0x0F,  0x28,  0x2A,  0xA2, 	/* 1AEA0 */
+	0x9E,  0x9C,  0x27,  0xCF,  0x10,  0x2F,  0xEF,  0x92,  0xAB,  0xAF,  0x80,  0xAF,  0xEF,  0x60,  0x2F,  0xEF, 	/* 1AEB0 */
+	0xAA,  0x2A,  0xA2,  0x86,  0x9F,  0x7F,  0xC2,  0x48,  0x3F,  0x82,  0x48,  0x7F,  0xC1,  0x50,  0xFB,  0xE5, 	/* 1AEC0 */
+	0x14,  0x7B,  0xC5,  0x14,  0xFB,  0xE1,  0x10,  0xA1,  0x5F,  0x48,  0x48,  0xBF,  0x45,  0x5A,  0xFF,  0xE4, 	/* 1AED0 */
+	0x4A,  0xFF,  0xC4,  0x4A,  0x3F,  0x82,  0x08,  0x20,  0x83,  0xF8,  0xA2,  0x29,  0x2F,  0x54,  0x2B,  0xAF, 	/* 1AEE0 */
+	0xEC,  0xAB,  0xAF,  0xEE,  0xAB,  0xAF,  0x10,  0x2F,  0xEF,  0x38,  0x2D,  0x62,  0x10,  0xA3,  0x20,  0x0F, 	/* 1AEF0 */
+	0x7E,  0x25,  0x4F,  0x7E,  0xA5,  0xCF,  0x76,  0xA5,  0x4F,  0x48,  0x26,  0xEF,  0xE8,  0x2A,  0x82,  0x7E, 	/* 1AF00 */
+	0xA4,  0x21,  0xCF,  0x10,  0x27,  0xEF,  0x50,  0xA5,  0xCF,  0x40,  0xA7,  0xEF,  0x6A,  0x27,  0xEF,  0x6A, 	/* 1AF10 */
+	0x2A,  0xA3,  0x7F,  0x9B,  0x04,  0x00,  0x40,  0x7F,  0xC1,  0x08,  0x11,  0x0F,  0xFE,  0x04,  0x00,  0x40, 	/* 1AF20 */
+	0x7F,  0xC0,  0x40,  0x04,  0x00,  0x40,  0x9C,  0x04,  0x0F,  0xFE,  0x04,  0x03,  0xF8,  0x20,  0x87,  0xFC, 	/* 1AF30 */
+	0x11,  0x0F,  0xFE,  0x04,  0x07,  0xFC,  0x04,  0x00,  0x40,  0x9E,  0x19,  0x0E,  0x7E,  0x22,  0x42,  0x24, 	/* 1AF40 */
+	0xFF,  0xE2,  0x10,  0x21,  0x0F,  0xFE,  0x89,  0x08,  0x90,  0x89,  0x0F,  0x90,  0x9F,  0x00,  0x87,  0x88, 	/* 1AF50 */
+	0x4F,  0xE4,  0xA4,  0x79,  0x44,  0x08,  0x47,  0xE7,  0x88,  0x6F,  0xEA,  0x88,  0x28,  0x83,  0x88,  0xA3, 	/* 1AF60 */
+	0x21,  0x02,  0x7E,  0xF9,  0x08,  0xFE,  0x55,  0x2F,  0xD2,  0x27,  0xE3,  0x90,  0xE3,  0x82,  0x54,  0x49, 	/* 1AF70 */
+	0x28,  0x10,  0xA7,  0x40,  0x85,  0xE8,  0xFB,  0xEA,  0xB4,  0xAB,  0x4F,  0xBE,  0x4A,  0x8F,  0xBE,  0x4A, 	/* 1AF80 */
+	0x84,  0xA8,  0x52,  0x8A,  0xC8,  0xA8,  0x42,  0x84,  0x28,  0xF3,  0xEA,  0xB4,  0xAB,  0x4F,  0xBE,  0x4A, 	/* 1AF90 */
+	0x8F,  0xBE,  0x4A,  0x84,  0x28,  0x44,  0x88,  0x88,  0xAD,  0x0C,  0x8F,  0x88,  0x57,  0xEF,  0xE4,  0x51, 	/* 1AFA0 */
+	0x8F,  0xFE,  0xA4,  0x8F,  0xC8,  0xD7,  0xEA,  0xC8,  0xF4,  0x88,  0xC8,  0xAE,  0x44,  0x8F,  0x5E,  0x29, 	/* 1AFB0 */
+	0x4B,  0xB4,  0xA5,  0x4E,  0xBE,  0x5E,  0x84,  0x48,  0xF7,  0xE5,  0x68,  0x55,  0x88,  0x48,  0xAF,  0x26, 	/* 1AFC0 */
+	0x82,  0x08,  0xFF,  0xE5,  0x14,  0x5F,  0x4F,  0x1E,  0x2E,  0x83,  0x08,  0xCF,  0xE4,  0xA8,  0x4A,  0x88, 	/* 1AFD0 */
+	0xE8,  0xB0,  0x00,  0x03,  0xFC,  0x20,  0x02,  0xFC,  0x20,  0x03,  0xFE,  0x2A,  0x42,  0xA4,  0x49,  0x84, 	/* 1AFE0 */
+	0x88,  0x8E,  0x43,  0x02,  0xB1,  0x00,  0x07,  0xFE,  0x40,  0x07,  0xFC,  0x4A,  0x48,  0x98,  0x3C,  0x60, 	/* 1AFF0 */
+	0x10,  0x7F,  0xE1,  0x10,  0x09,  0x00,  0x30,  0xB2,  0x09,  0x03,  0xFC,  0x29,  0x43,  0xFC,  0x29,  0x47, 	/* 1B000 */
+	0xFE,  0x40,  0x07,  0xFE,  0x4C,  0x44,  0xA8,  0x4D,  0x8B,  0x86,  0xB7,  0x40,  0x02,  0x00,  0x00,  0x08, 	/* 1B010 */
+	0x00,  0x4F,  0xE0,  0x00,  0xE0,  0x02,  0x00,  0x20,  0x02,  0x00,  0x58,  0x08,  0x7F,  0xBA,  0x00,  0x04, 	/* 1B020 */
+	0xFE,  0x22,  0x20,  0x22,  0x02,  0x2E,  0x22,  0x22,  0x22,  0x42,  0x24,  0x22,  0x8C,  0x58,  0x08,  0x7F, 	/* 1B030 */
+	0xBB,  0x01,  0x04,  0x10,  0x21,  0x00,  0x10,  0x0F,  0xEE,  0x10,  0x21,  0x02,  0x10,  0x21,  0x02,  0x10, 	/* 1B040 */
+	0x58,  0x08,  0x7F,  0xBC,  0x00,  0x04,  0x30,  0x21,  0x00,  0x10,  0x01,  0x0E,  0x30,  0x22,  0x82,  0x48, 	/* 1B050 */
+	0x28,  0x43,  0x02,  0x58,  0x08,  0x7F,  0xBF,  0x01,  0x04,  0x10,  0x21,  0x00,  0x92,  0x09,  0x2E,  0x92, 	/* 1B060 */
+	0x29,  0x22,  0x92,  0x2F,  0xE2,  0x82,  0x58,  0x08,  0x7F,  0x82,  0x00,  0x04,  0xFC,  0x21,  0x00,  0x10, 	/* 1B070 */
+	0x1F,  0xEE,  0x10,  0x21,  0x02,  0x10,  0x21,  0x02,  0x30,  0x58,  0x08,  0x7F,  0x84,  0x04,  0x04,  0x40, 	/* 1B080 */
+	0x27,  0xE0,  0x80,  0x07,  0xCE,  0x08,  0x23,  0x02,  0x42,  0x28,  0x22,  0x7E,  0x58,  0x08,  0x7F,  0x85, 	/* 1B090 */
+	0x00,  0x05,  0xF8,  0x24,  0x80,  0x48,  0x04,  0x8F,  0xF8,  0x24,  0xA2,  0x4A,  0x24,  0x62,  0x42,  0x58, 	/* 1B0A0 */
+	0x08,  0x7F,  0x8E,  0x00,  0x04,  0x20,  0x2D,  0xE0,  0x92,  0x09,  0x2E,  0x92,  0x29,  0x22,  0xF2,  0x29, 	/* 1B0B0 */
+	0xC2,  0x10,  0x59,  0x08,  0x7F,  0x91,  0x00,  0x64,  0x78,  0x24,  0x00,  0x40,  0x07,  0xEE,  0x48,  0x24, 	/* 1B0C0 */
+	0x82,  0x48,  0x28,  0x83,  0x08,  0x58,  0x08,  0x7F,  0x94,  0x0F,  0xE4,  0x80,  0x28,  0x00,  0xFC,  0x08, 	/* 1B0D0 */
+	0x4E,  0xA4,  0x29,  0x83,  0x18,  0x32,  0x42,  0xC2,  0x58,  0x08,  0x7F,  0x9A,  0x41,  0x02,  0x10,  0x01, 	/* 1B0E0 */
+	0x08,  0xFE,  0x49,  0x20,  0x92,  0xEF,  0xE2,  0x10,  0x21,  0x02,  0x10,  0x59,  0x08,  0x7F,  0xA2,  0x40, 	/* 1B0F0 */
+	0x02,  0x7E,  0x01,  0x28,  0x12,  0x42,  0x20,  0x4C,  0xEF,  0xE2,  0x42,  0x24,  0x22,  0x7E,  0x58,  0x08, 	/* 1B100 */
+	0x7F,  0xA5,  0x40,  0x02,  0xFE,  0x08,  0x28,  0x82,  0x4B,  0xA0,  0xAA,  0xEA,  0xA2,  0xBA,  0x28,  0x22, 	/* 1B110 */
+	0x86,  0x58,  0x08,  0x7F,  0xA6,  0x08,  0x04,  0x8E,  0x3E,  0xA0,  0xAA,  0x0A,  0xAE,  0xAA,  0x2A,  0xA2, 	/* 1B120 */
+	0xAA,  0x2A,  0xE3,  0x60,  0x58,  0x08,  0x7F,  0xA9,  0x04,  0x08,  0x40,  0x4F,  0xE0,  0x90,  0x11,  0x0E, 	/* 1B130 */
+	0x54,  0x25,  0x22,  0x52,  0x29,  0x22,  0x30,  0x58,  0x08,  0x7F,  0xAA,  0x41,  0x02,  0x10,  0x01,  0x08, 	/* 1B140 */
+	0xFE,  0x49,  0x20,  0x92,  0xEF,  0xE2,  0x92,  0x29,  0x22,  0xFE,  0x58,  0x08,  0x7F,  0xAB,  0x01,  0x04, 	/* 1B150 */
+	0x20,  0x27,  0xC0,  0x44,  0x04,  0x4E,  0x7C,  0x24,  0x42,  0x44,  0x24,  0x42,  0x7C,  0x58,  0x08,  0x7F, 	/* 1B160 */
+	0xAD,  0x01,  0x04,  0x90,  0x29,  0x00,  0xFC,  0x11,  0x0E,  0x10,  0x2F,  0xE2,  0x28,  0x24,  0x42,  0x82, 	/* 1B170 */
+	0x58,  0x08,  0x7F,  0xAF,  0x44,  0x82,  0x48,  0x0E,  0x88,  0xA8,  0x52,  0xC0,  0x6A,  0xE2,  0x82,  0x48, 	/* 1B180 */
+	0x28,  0x83,  0x08,  0x58,  0x08,  0x7F,  0xB0,  0x02,  0x84,  0x24,  0x22,  0x01,  0xFC,  0x02,  0x0E,  0xA8, 	/* 1B190 */
+	0x2A,  0x42,  0xA4,  0x32,  0x42,  0x20,  0x58,  0x08,  0x7F,  0xB4,  0x40,  0x02,  0xFE,  0x08,  0x28,  0xBA, 	/* 1B1A0 */
+	0x4A,  0xA0,  0xAA,  0xEA,  0xA2,  0xBA,  0x28,  0x22,  0xFE,  0x58,  0x08,  0x7F,  0xB7,  0x02,  0x04,  0xA4, 	/* 1B1B0 */
+	0x26,  0x80,  0x20,  0x1F,  0xEE,  0x30,  0x26,  0x82,  0xA4,  0x32,  0x22,  0x20,  0x58,  0x08,  0x7F,  0xB8, 	/* 1B1C0 */
+	0x48,  0x42,  0x48,  0x1F,  0xC8,  0x48,  0x44,  0x81,  0xFE,  0xE4,  0x82,  0x48,  0x28,  0x83,  0x08,  0x58, 	/* 1B1D0 */
+	0x08,  0x7F,  0xB9,  0x41,  0x02,  0x10,  0x1F,  0xE8,  0x28,  0x4A,  0xC0,  0xAA,  0xEA,  0xA3,  0x2A,  0x22, 	/* 1B1E0 */
+	0x82,  0x58,  0x58,  0x08,  0x7F,  0xBA,  0x40,  0x02,  0xFE,  0x02,  0x88,  0x28,  0x4F,  0xE0,  0xAA,  0xEA, 	/* 1B1F0 */
+	0xA2,  0xCE,  0x28,  0x22,  0xFE,  0x58,  0x08,  0x7F,  0xBD,  0x02,  0x04,  0x40,  0x2F,  0xC0,  0x84,  0x0F, 	/* 1B200 */
+	0xCE,  0x80,  0x2F,  0xC2,  0x84,  0x28,  0x42,  0xFC,  0x58,  0x08,  0x7F,  0x80,  0x07,  0xC4,  0x44,  0x27, 	/* 1B210 */
+	0xC0,  0x44,  0x07,  0xCE,  0x52,  0x25,  0x42,  0x48,  0x24,  0x42,  0xE2,  0x58,  0x08,  0x7F,  0x81,  0x04, 	/* 1B220 */
+	0x44,  0x24,  0x22,  0x80,  0xFE,  0x01,  0x0E,  0x10,  0x2F,  0xE2,  0x18,  0x22,  0x42,  0xC2,  0x58,  0x08, 	/* 1B230 */
+	0x7F,  0x83,  0x05,  0x04,  0x50,  0x35,  0x40,  0xD8,  0x05,  0x0E,  0xD8,  0x35,  0x42,  0x90,  0x29,  0x23, 	/* 1B240 */
+	0x0E,  0x58,  0x08,  0x7F,  0x85,  0x40,  0xC2,  0xF0,  0x08,  0x08,  0xFE,  0x48,  0x00,  0x80,  0xEF,  0xC3, 	/* 1B250 */
+	0x44,  0x34,  0x42,  0x7C,  0x58,  0x08,  0x7F,  0x86,  0x04,  0x44,  0x28,  0x2F,  0xE0,  0x10,  0x09,  0x2E, 	/* 1B260 */
+	0x92,  0x2F,  0xE2,  0x90,  0x21,  0x02,  0x20,  0x58,  0x08,  0x7F,  0x8B,  0x41,  0x42,  0xFE,  0x01,  0x08, 	/* 1B270 */
+	0xFE,  0x49,  0x20,  0xFE,  0xE9,  0x22,  0xFE,  0x29,  0x22,  0x96,  0x58,  0x08,  0x7F,  0x8D,  0x41,  0x02, 	/* 1B280 */
+	0x54,  0x09,  0x29,  0x7E,  0x44,  0x40,  0x7C,  0xE4,  0x42,  0x7C,  0x24,  0x42,  0x4C,  0x58,  0x08,  0x7F, 	/* 1B290 */
+	0x8E,  0x40,  0x02,  0xFE,  0x02,  0x88,  0xFE,  0x4A,  0xA0,  0xCE,  0xE8,  0x22,  0xFE,  0x28,  0x22,  0xFE, 	/* 1B2A0 */
+	0x58,  0x08,  0x7F,  0x8F,  0x0F,  0x84,  0x20,  0x3F,  0xC0,  0x70,  0x0A,  0x8F,  0x26,  0x2F,  0x82,  0x2C, 	/* 1B2B0 */
+	0x22,  0x42,  0x4C,  0x58,  0x08,  0x7F,  0x90,  0x00,  0x04,  0xFE,  0x21,  0x00,  0x72,  0x09,  0xCE,  0x28, 	/* 1B2C0 */
+	0x2D,  0xC2,  0x2A,  0x2C,  0x92,  0x10,  0x58,  0x08,  0x7F,  0x91,  0x41,  0x82,  0x14,  0x0F,  0xE8,  0x10, 	/* 1B2D0 */
+	0x49,  0x20,  0x54,  0xE3,  0x82,  0xD4,  0x21,  0x22,  0x30,  0x58,  0x08,  0x7F,  0x93,  0x00,  0xC4,  0xF0, 	/* 1B2E0 */
+	0x29,  0x00,  0xFC,  0x09,  0x0E,  0xFC,  0x29,  0x02,  0xFC,  0x35,  0x42,  0x54,  0x59,  0x08,  0x7F,  0x94, 	/* 1B2F0 */
+	0x01,  0x04,  0x28,  0x24,  0x40,  0xFB,  0x01,  0x0E,  0xFE,  0x25,  0x42,  0x52,  0x29,  0x22,  0x30,  0x58, 	/* 1B300 */
+	0x08,  0x7F,  0x95,  0x40,  0x02,  0xFE,  0x05,  0x48,  0x54,  0x4A,  0x80,  0x54,  0xEF,  0xE2,  0x10,  0x21, 	/* 1B310 */
+	0x02,  0xFE,  0x58,  0x08,  0x7F,  0x96,  0x42,  0x82,  0xA8,  0x05,  0xA8,  0xDA,  0x56,  0xC0,  0x48,  0xED, 	/* 1B320 */
+	0x43,  0x54,  0x26,  0x22,  0xC2,  0x58,  0x08,  0x7F,  0x97,  0x00,  0x04,  0xFE,  0x20,  0x00,  0xFC,  0x08, 	/* 1B330 */
+	0x4E,  0xFC,  0x20,  0x02,  0x84,  0x24,  0x82,  0xFE,  0x58,  0x08,  0x7F,  0x99,  0x01,  0x04,  0xFE,  0x20, 	/* 1B340 */
+	0x00,  0x7C,  0x00,  0x0E,  0x7C,  0x20,  0x02,  0x7C,  0x24,  0x42,  0x7C,  0x58,  0x08,  0x7F,  0x9A,  0x0F, 	/* 1B350 */
+	0xC4,  0x48,  0x23,  0x00,  0xFE,  0x09,  0x2E,  0xFE,  0x29,  0x22,  0xFE,  0x29,  0x22,  0x96,  0x58,  0x08, 	/* 1B360 */
+	0x7F,  0x9D,  0x08,  0x64,  0x98,  0x3D,  0x00,  0x9E,  0x09,  0x4E,  0xD4,  0x39,  0x42,  0xA4,  0x2A,  0x43, 	/* 1B370 */
+	0xC4,  0x58,  0x08,  0x7F,  0x9E,  0x40,  0x02,  0x7C,  0x04,  0x48,  0x7C,  0x40,  0x00,  0xFE,  0xE1,  0x02, 	/* 1B380 */
+	0x7C,  0x21,  0x02,  0xFE,  0x58,  0x08,  0x7F,  0x9F,  0x01,  0x04,  0xFE,  0x21,  0x00,  0xFE,  0x09,  0x2E, 	/* 1B390 */
+	0xFE,  0x23,  0x82,  0x54,  0x29,  0x22,  0x10,  0x58,  0x08,  0x7F,  0xA0,  0x05,  0x04,  0x50,  0x27,  0xC0, 	/* 1B3A0 */
+	0x90,  0x1F,  0xEE,  0x00,  0x27,  0xC2,  0x44,  0x24,  0x43,  0x7C,  0x4C,  0x08,  0x3F,  0xA1,  0x41,  0x02, 	/* 1B3B0 */
+	0x24,  0x0F,  0xA8,  0x28,  0x44,  0xE0,  0x90,  0xE3,  0xC2,  0x64,  0x29,  0x82,  0x2C,  0x5C,  0x28,  0x7F, 	/* 1B3C0 */
+	0xA2,  0x02,  0x04,  0x3C,  0x2C,  0x80,  0x30,  0x0C,  0xCF,  0xFE,  0x22,  0x02,  0xFC,  0x22,  0x02,  0xFC, 	/* 1B3D0 */
+	0x5A,  0x08,  0x7F,  0xA3,  0x01,  0x04,  0xFE,  0x21,  0x00,  0xFE,  0x09,  0x2E,  0xFE,  0x29,  0x22,  0xFE, 	/* 1B3E0 */
+	0x21,  0x02,  0xFE,  0x59,  0x08,  0x7F,  0xA7,  0x44,  0x82,  0x44,  0x09,  0x48,  0x28,  0x44,  0x41,  0x82, 	/* 1B3F0 */
+	0xE7,  0xC2,  0x44,  0x24,  0x42,  0x7C,  0x58,  0x08,  0x7F,  0xAE,  0x02,  0x04,  0xFC,  0x22,  0x41,  0xFE, 	/* 1B400 */
+	0x02,  0x4E,  0xFC,  0x32,  0x42,  0xA8,  0x27,  0x03,  0xAC,  0x5A,  0x08,  0x7F,  0xB1,  0x00,  0x04,  0xFE, 	/* 1B410 */
+	0x29,  0x20,  0xBA,  0x09,  0x2E,  0xFE,  0x2B,  0xA2,  0xAA,  0x2B,  0xA3,  0x06,  0x58,  0x08,  0x7F,  0xB2, 	/* 1B420 */
+	0x04,  0x84,  0x50,  0x2F,  0xE1,  0x90,  0x0F,  0xCE,  0x90,  0x2F,  0xC2,  0x90,  0x29,  0x02,  0xFE,  0x58, 	/* 1B430 */
+	0x08,  0x7F,  0xB5,  0x41,  0x02,  0x7C,  0x01,  0x08,  0xFE,  0x42,  0x80,  0x4E,  0xE9,  0x02,  0x7C,  0x21, 	/* 1B440 */
+	0x02,  0xFE,  0x58,  0x08,  0x7F,  0xB6,  0x40,  0xC2,  0x70,  0x01,  0x09,  0xFE,  0x43,  0x80,  0x54,  0xEF, 	/* 1B450 */
+	0xE2,  0x24,  0x21,  0x82,  0x64,  0x58,  0x08,  0x7F,  0xB8,  0x02,  0x04,  0x3C,  0x24,  0x80,  0xFE,  0x09, 	/* 1B460 */
+	0x2E,  0xFE,  0x23,  0x02,  0x30,  0x25,  0x22,  0x8E,  0x58,  0x08,  0x7F,  0xB9,  0x41,  0x02,  0x10,  0x0F, 	/* 1B470 */
+	0xC8,  0x10,  0x5F,  0xE0,  0x44,  0xEF,  0xE2,  0x10,  0x2F,  0xC2,  0x10,  0x59,  0x08,  0x7F,  0xBC,  0x0F, 	/* 1B480 */
+	0xE4,  0x00,  0x27,  0xC0,  0x44,  0x07,  0xCE,  0xFE,  0x29,  0x22,  0xFE,  0x29,  0x22,  0xFE,  0x58,  0x08, 	/* 1B490 */
+	0x7F,  0xBE,  0x47,  0x02,  0x28,  0x04,  0x49,  0xBA,  0x40,  0x00,  0xEA,  0xEA,  0xA2,  0xF4,  0x2B,  0x42, 	/* 1B4A0 */
+	0xEA,  0x5A,  0xA8,  0x7F,  0x81,  0x00,  0x64,  0xF8,  0x28,  0x80,  0xFF,  0x08,  0x8E,  0xBE,  0x2A,  0x22, 	/* 1B4B0 */
+	0xBE,  0x32,  0x22,  0x3E,  0x58,  0x08,  0x7F,  0x82,  0x04,  0x44,  0x28,  0x2F,  0xF0,  0x30,  0x0C,  0xAE, 	/* 1B4C0 */
+	0x3C,  0x2C,  0xC2,  0x3A,  0x3C,  0x92,  0x18,  0x58,  0x08,  0x7F,  0x85,  0x0F,  0xE4,  0x82,  0x2F,  0xE0, 	/* 1B4D0 */
+	0xA8,  0x0F,  0xCE,  0x90,  0x2F,  0xC2,  0x90,  0x37,  0xE2,  0x10,  0x59,  0x08,  0x7F,  0x87,  0x0F,  0xC4, 	/* 1B4E0 */
+	0xA4,  0x2F,  0xC0,  0xA4,  0x0F,  0xCE,  0x20,  0x2F,  0xE2,  0xAA,  0x2F,  0xA2,  0x8E,  0x58,  0x08,  0x7F, 	/* 1B4F0 */
+	0x89,  0x41,  0x02,  0x1E,  0x01,  0x08,  0x7C,  0x44,  0x40,  0x7C,  0xE4,  0x42,  0x7C,  0x24,  0x42,  0x7C, 	/* 1B500 */
+	0x58,  0x68,  0x7F,  0x8A,  0x08,  0x84,  0x48,  0x3E,  0xF0,  0x90,  0x0F,  0xEE,  0xA4,  0x2B,  0xF2,  0xA4, 	/* 1B510 */
+	0x32,  0x42,  0x6C,  0x58,  0x08,  0x7F,  0x8B,  0x1F,  0xE5,  0x12,  0x3F,  0xE0,  0x94,  0x0F,  0xCE,  0x94, 	/* 1B520 */
+	0x2F,  0xC2,  0x10,  0x3F,  0xE2,  0x10,  0x59,  0x08,  0x7F,  0x8D,  0x0F,  0xC4,  0x00,  0x2F,  0xC0,  0x84, 	/* 1B530 */
+	0x0F,  0xCE,  0x80,  0x2F,  0xE3,  0xAA,  0x2F,  0xE2,  0xAA,  0x58,  0x68,  0x7F,  0x8E,  0x07,  0xC4,  0x44, 	/* 1B540 */
+	0x25,  0xC0,  0x54,  0x0F,  0xEE,  0x82,  0x2B,  0xA2,  0xAA,  0x2B,  0xA2,  0x86,  0x58,  0x08,  0x7F,  0x8F, 	/* 1B550 */
+	0x40,  0x02,  0x7C,  0x04,  0x48,  0x7C,  0x44,  0x40,  0x7C,  0xE7,  0xE2,  0xD2,  0x36,  0xA2,  0x7E,  0x58, 	/* 1B560 */
+	0xC8,  0x7F,  0x90,  0x40,  0x02,  0xEE,  0x0A,  0x28,  0xEE,  0x48,  0x00,  0xFE,  0xE8,  0xA2,  0xE4,  0x28, 	/* 1B570 */
+	0xA2,  0x92,  0x58,  0x08,  0x7F,  0x91,  0x42,  0x02,  0x7C,  0x04,  0x48,  0x7C,  0x44,  0x40,  0xFE,  0xE1, 	/* 1B580 */
+	0x02,  0x7C,  0x21,  0x02,  0xFE,  0x58,  0x08,  0x7F,  0x92,  0x44,  0x82,  0x44,  0x08,  0x29,  0xFE,  0x42, 	/* 1B590 */
+	0x80,  0xFE,  0xEA,  0xA2,  0xCE,  0x28,  0x22,  0xFE,  0x58,  0x08,  0x7F,  0x93,  0x04,  0x85,  0xFE,  0x22, 	/* 1B5A0 */
+	0x00,  0x7C,  0x04,  0x4E,  0x7C,  0x24,  0x42,  0x7C,  0x24,  0x43,  0x7C,  0x4C,  0x08,  0x3F,  0x94,  0x01, 	/* 1B5B0 */
+	0x04,  0x7C,  0x21,  0x00,  0xFE,  0x04,  0x8F,  0xFF,  0x21,  0x02,  0xFE,  0x21,  0x02,  0xFE,  0x59,  0x08, 	/* 1B5C0 */
+	0x7F,  0x95,  0x02,  0x04,  0xFC,  0x22,  0x41,  0xFE,  0x04,  0x4E,  0x7C,  0x21,  0x02,  0xFC,  0x29,  0x03, 	/* 1B5D0 */
+	0xFE,  0x51,  0x08,  0xFF,  0x96,  0x41,  0x02,  0xFE,  0x01,  0x08,  0xFE,  0x4A,  0xA0,  0xFE,  0xE9,  0x22, 	/* 1B5E0 */
+	0xFE,  0x29,  0x22,  0x96,  0x58,  0x08,  0x7F,  0x98,  0x42,  0x82,  0x7C,  0x02,  0x88,  0xFE,  0x47,  0xC0, 	/* 1B5F0 */
+	0x54,  0xE7,  0xC2,  0x54,  0x3F,  0xF2,  0x44,  0x5C,  0xC8,  0x7F,  0x99,  0x41,  0x02,  0x3E,  0x0D,  0x48, 	/* 1B600 */
+	0x38,  0x5E,  0x00,  0x7C,  0xE9,  0x03,  0xFE,  0x29,  0x42,  0xFC,  0x58,  0x08,  0x7F,  0x9C,  0x00,  0x65, 	/* 1B610 */
+	0xF8,  0x24,  0xA0,  0xB4,  0x0C,  0xAF,  0x7E,  0x24,  0xA2,  0x5C,  0x26,  0xA2,  0xC8,  0x58,  0x08,  0x7F, 	/* 1B620 */
+	0x9E,  0x40,  0xC2,  0xF0,  0x09,  0xC8,  0xFE,  0x4D,  0x00,  0xDE,  0xED,  0x83,  0x58,  0x25,  0xA2,  0xA6, 	/* 1B630 */
+	0x58,  0x08,  0x7F,  0xA0,  0x02,  0x04,  0xFC,  0x22,  0x01,  0xFE,  0x0F,  0xCE,  0x84,  0x2F,  0xC2,  0x74, 	/* 1B640 */
+	0x2A,  0x83,  0x26,  0x5B,  0x08,  0x7F,  0xA1,  0x12,  0x04,  0xDE,  0x3F,  0x20,  0x52,  0x15,  0xEF,  0x52, 	/* 1B650 */
+	0x3F,  0xE2,  0x52,  0x25,  0x22,  0x96,  0x58,  0x08,  0x7F,  0xA3,  0x02,  0x04,  0xFC,  0x2A,  0x41,  0xFE, 	/* 1B660 */
+	0x00,  0x0E,  0xF8,  0x28,  0x82,  0xFC,  0x28,  0x42,  0xFC,  0x58,  0x08,  0x7F,  0xA5,  0x00,  0x64,  0xF8, 	/* 1B670 */
+	0x29,  0x20,  0x54,  0x0F,  0xEE,  0x10,  0x2F,  0xE2,  0x10,  0x29,  0x22,  0xFE,  0x58,  0x08,  0x7F,  0xA8, 	/* 1B680 */
+	0x44,  0x82,  0xE8,  0x04,  0xF9,  0xEA,  0x45,  0x21,  0xF4,  0xE6,  0xC2,  0xB4,  0x32,  0x22,  0x61,  0x58, 	/* 1B690 */
+	0x08,  0x7F,  0xA9,  0x01,  0x04,  0xFE,  0x22,  0x80,  0xFE,  0x0B,  0xAE,  0x92,  0x2B,  0xA2,  0xAA,  0x2B, 	/* 1B6A0 */
+	0xA2,  0x86,  0x58,  0x08,  0x7F,  0xAD,  0x02,  0x85,  0xFF,  0x2A,  0xA0,  0xFE,  0x0A,  0xAE,  0xFE,  0x24, 	/* 1B6B0 */
+	0x42,  0x7C,  0x24,  0x42,  0x7C,  0x58,  0x08,  0x7F,  0xAE,  0x00,  0x84,  0xFF,  0x29,  0x40,  0xBE,  0x09, 	/* 1B6C0 */
+	0x4E,  0x94,  0x29,  0xC2,  0x80,  0x32,  0xA2,  0x4A,  0x58,  0x08,  0x7F,  0xAF,  0x4F,  0xF2,  0xA8,  0x0A, 	/* 1B6D0 */
+	0xC8,  0xF5,  0x4A,  0xE0,  0xB6,  0xEE,  0xD2,  0xB4,  0x2A,  0x42,  0xA8,  0x58,  0x08,  0x7F,  0xB2,  0x40, 	/* 1B6E0 */
+	0x02,  0xFE,  0x08,  0x28,  0xFE,  0x48,  0x80,  0xEE,  0xEB,  0xC2,  0xC8,  0x37,  0xE2,  0x08,  0x58,  0x88, 	/* 1B6F0 */
+	0x7F,  0xB5,  0x08,  0x85,  0xFE,  0x25,  0x01,  0xFC,  0x15,  0x4F,  0xFC,  0x20,  0x83,  0xFE,  0x24,  0x82, 	/* 1B700 */
+	0x28,  0x59,  0x88,  0x7F,  0xB6,  0x42,  0x02,  0xFC,  0x02,  0x09,  0xFE,  0x44,  0x80,  0xFC,  0xE4,  0x83, 	/* 1B710 */
+	0xFE,  0x25,  0x02,  0x8E,  0x58,  0x08,  0x7F,  0xB7,  0x1F,  0xF4,  0x28,  0x2F,  0xE0,  0xAA,  0x1F,  0xFE, 	/* 1B720 */
+	0x4C,  0x2F,  0xA3,  0x41,  0x24,  0x42,  0x3C,  0x58,  0x08,  0x7F,  0xB8,  0x0E,  0xE4,  0x22,  0x2E,  0xE0, 	/* 1B730 */
+	0x88,  0x0E,  0xEE,  0x48,  0x2F,  0xE2,  0x48,  0x3F,  0xF2,  0x48,  0x58,  0x48,  0x7F,  0xBA,  0x02,  0x04, 	/* 1B740 */
+	0xFC,  0x2A,  0x41,  0xFE,  0x00,  0x0E,  0xFC,  0x28,  0x42,  0xFC,  0x28,  0x42,  0xFC,  0x5C,  0x68,  0xFF, 	/* 1B750 */
+	0xBC,  0x01,  0x04,  0xFE,  0x22,  0x81,  0x7D,  0x0C,  0x6F,  0x7D,  0x24,  0x42,  0x7C,  0x25,  0x42,  0x92, 	/* 1B760 */
+	0x5B,  0x08,  0x7F,  0xBD,  0x41,  0xE2,  0x10,  0x0F,  0xE8,  0x94,  0x4F,  0xE0,  0x98,  0xEE,  0xA2,  0x9C, 	/* 1B770 */
+	0x36,  0xA2,  0x08,  0x5B,  0x08,  0x7F,  0xBF,  0x0E,  0x44,  0xBF,  0x2A,  0xA0,  0xEA,  0x09,  0xFE,  0xE4, 	/* 1B780 */
+	0x2A,  0x43,  0xBF,  0x2E,  0x42,  0x04,  0x58,  0x08,  0x7F,  0x80,  0x44,  0x82,  0xE8,  0x0A,  0xF8,  0xEA, 	/* 1B790 */
+	0x4B,  0x20,  0xEA,  0xE4,  0x43,  0xF4,  0x26,  0xA2,  0xB1,  0x5C,  0x08,  0x7F,  0x81,  0x42,  0x82,  0xFE, 	/* 1B7A0 */
+	0x02,  0x88,  0x7C,  0x45,  0x40,  0x7C,  0xE5,  0x42,  0xFE,  0x29,  0x22,  0xFA,  0x58,  0x68,  0x7F,  0x82, 	/* 1B7B0 */
+	0x48,  0x02,  0xFE,  0x14,  0xA8,  0xF2,  0x4D,  0x40,  0xFE,  0xED,  0x42,  0xFF,  0x29,  0x42,  0xB4,  0x58, 	/* 1B7C0 */
+	0x08,  0x7F,  0x83,  0x82,  0x05,  0xFE,  0x12,  0xA8,  0xCE,  0x44,  0x40,  0xFE,  0xE3,  0x02,  0xCA,  0x23, 	/* 1B7D0 */
+	0xC2,  0xCA,  0x59,  0x88,  0x7F,  0x84,  0x0F,  0xC4,  0xB4,  0x3F,  0xE0,  0x00,  0x0F,  0xCE,  0x84,  0x2F, 	/* 1B7E0 */
+	0xC2,  0x72,  0x2A,  0xC2,  0x26,  0x5B,  0x08,  0x7F,  0x87,  0x40,  0x02,  0xFE,  0x05,  0x48,  0x92,  0x4F, 	/* 1B7F0 */
+	0xE0,  0xB6,  0xED,  0xA2,  0xB6,  0x2D,  0xA2,  0x96,  0x58,  0x08,  0x7F,  0x89,  0x42,  0x02,  0x7C,  0x04, 	/* 1B800 */
+	0x48,  0x7C,  0x4F,  0xE0,  0xAA,  0xE4,  0x42,  0xFE,  0x24,  0x42,  0x7C,  0x58,  0x08,  0x7F,  0x8A,  0x47, 	/* 1B810 */
+	0xC2,  0x44,  0x07,  0xC8,  0x44,  0x4F,  0xE0,  0xB6,  0xE4,  0xA2,  0xFF,  0x23,  0xC2,  0x44,  0x59,  0x88, 	/* 1B820 */
+	0x7F,  0x8F,  0x4F,  0xE2,  0xAA,  0x0F,  0xE8,  0x48,  0x5B,  0x40,  0x5E,  0xEF,  0x42,  0x5E,  0x2F,  0x43, 	/* 1B830 */
+	0x5E,  0x5C,  0x08,  0x7F,  0x91,  0x00,  0x03,  0xF0,  0x21,  0x03,  0xF0,  0x00,  0x07,  0xF8,  0x48,  0x84, 	/* 1B840 */
+	0x88,  0x7F,  0x84,  0x00,  0x40,  0x23,  0xFE,  0xA3,  0x00,  0x0F,  0xDE,  0x25,  0x22,  0x54,  0x7D,  0x82, 	/* 1B850 */
+	0x54,  0x25,  0x27,  0xD2,  0x25,  0x22,  0x5A,  0x45,  0x48,  0xD0,  0xA6,  0x20,  0x02,  0x3C,  0xFA,  0x42, 	/* 1B860 */
+	0x28,  0xFB,  0x02,  0x38,  0x3A,  0x4E,  0x22,  0x22,  0x22,  0x3C,  0x42,  0x08,  0x20,  0xA8,  0x10,  0x01, 	/* 1B870 */
+	0xFC,  0xF1,  0x41,  0x54,  0x55,  0x85,  0x54,  0x55,  0x25,  0xD2,  0x71,  0x21,  0x5C,  0x19,  0x01,  0x10, 	/* 1B880 */
+	0xAA,  0x00,  0x0F,  0xFC,  0x4A,  0x44,  0xA8,  0x4B,  0x0F,  0xE8,  0x2A,  0x42,  0xA2,  0x4B,  0x24,  0xAC, 	/* 1B890 */
+	0x8A,  0x01,  0xA0,  0xAF,  0x48,  0x04,  0x9C,  0xFF,  0x44,  0x94,  0x49,  0x84,  0x94,  0x79,  0x24,  0x92, 	/* 1B8A0 */
+	0x49,  0x24,  0x9C,  0x49,  0x07,  0x90,  0xB1,  0x0C,  0x07,  0x1C,  0x41,  0x47,  0xF4,  0x49,  0x84,  0x94, 	/* 1B8B0 */
+	0x49,  0x24,  0x92,  0x4D,  0x27,  0x1C,  0xC1,  0x00,  0x10,  0xB5,  0x00,  0x0F,  0xDC,  0x25,  0x42,  0x54, 	/* 1B8C0 */
+	0x25,  0x84,  0x54,  0x99,  0x27,  0xD2,  0x45,  0x24,  0x5C,  0x45,  0x07,  0xD0,  0xB8,  0x0C,  0x07,  0x1E, 	/* 1B8D0 */
+	0x49,  0x24,  0x94,  0x7D,  0x84,  0x94,  0x49,  0x24,  0x92,  0x45,  0x2E,  0x5C,  0x03,  0x07,  0xD0,  0x81, 	/* 1B8E0 */
+	0x10,  0x01,  0x1E,  0xFF,  0x22,  0x14,  0x3D,  0x86,  0x5C,  0x7D,  0x2A,  0x52,  0x3D,  0x22,  0x5C,  0x25, 	/* 1B8F0 */
+	0x02,  0xD0,  0x8A,  0x10,  0x01,  0x1C,  0xFF,  0x42,  0x94,  0x25,  0x84,  0xB4,  0xAB,  0x21,  0x12,  0x19, 	/* 1B900 */
+	0x22,  0x5C,  0x41,  0x08,  0x10,  0x8E,  0x11,  0xC7,  0xD4,  0x45,  0x47,  0xD8,  0x45,  0xC7,  0xD2,  0x41, 	/* 1B910 */
+	0x25,  0x12,  0x49,  0x27,  0x5C,  0xC5,  0x00,  0x10,  0x9B,  0x1C,  0x0E,  0x1C,  0x55,  0x45,  0x34,  0x81, 	/* 1B920 */
+	0x87,  0xD4,  0x09,  0x21,  0xD1,  0xF1,  0x11,  0x1E,  0x11,  0x03,  0x10,  0xA1,  0x00,  0x07,  0xDE,  0x25, 	/* 1B930 */
+	0x2F,  0xF4,  0x25,  0x87,  0xD4,  0x21,  0x23,  0xD2,  0x65,  0x26,  0x5C,  0xA5,  0x03,  0xD0,  0xA2,  0x00, 	/* 1B940 */
+	0x07,  0xDC,  0x45,  0x44,  0x54,  0x7D,  0x80,  0x54,  0xF9,  0x21,  0x12,  0x7D,  0x21,  0x1C,  0x1D,  0x0F, 	/* 1B950 */
+	0x10,  0xA4,  0x10,  0x02,  0x9C,  0x25,  0x45,  0x54,  0x99,  0x82,  0x54,  0x41,  0x2F,  0xD2,  0x45,  0x24, 	/* 1B960 */
+	0x5C,  0x7D,  0x04,  0x10,  0xA8,  0x11,  0xCF,  0xF4,  0x45,  0x42,  0x58,  0x29,  0x4F,  0xF2,  0x01,  0x27, 	/* 1B970 */
+	0xD2,  0x45,  0xC4,  0x50,  0x7D,  0x00,  0x10,  0xAD,  0x10,  0x0F,  0xFC,  0x7D,  0x44,  0x54,  0x7D,  0x80, 	/* 1B980 */
+	0x14,  0x7D,  0x20,  0x92,  0xFD,  0x21,  0x1C,  0x11,  0x03,  0x10,  0xB5,  0x04,  0x07,  0x9C,  0x11,  0x4F, 	/* 1B990 */
+	0xF4,  0x55,  0x8F,  0xF4,  0x55,  0x25,  0x52,  0xFF,  0x21,  0x1C,  0x1D,  0x0F,  0x10,  0xB7,  0x40,  0x04, 	/* 1B9A0 */
+	0xEE,  0xAA,  0xA6,  0xEA,  0x2A,  0xC4,  0xEA,  0xA8,  0x9E,  0xC9,  0x2A,  0x92,  0xDE,  0x49,  0x88,  0x08, 	/* 1B9B0 */
+	0xBD,  0x10,  0x07,  0xDC,  0x15,  0x41,  0x94,  0xFF,  0x81,  0x14,  0x3D,  0x26,  0x52,  0xBD,  0x22,  0x5C, 	/* 1B9C0 */
+	0x25,  0x03,  0xD0,  0x82,  0x00,  0x0E,  0xFC,  0xAB,  0x4E,  0xF4,  0x01,  0x87,  0xD4,  0x01,  0x2F,  0xD2, 	/* 1B9D0 */
+	0x21,  0x23,  0xDC,  0x45,  0x01,  0x90,  0x92,  0x20,  0x07,  0xDC,  0x95,  0x45,  0x54,  0x7D,  0x82,  0x54, 	/* 1B9E0 */
+	0x59,  0x27,  0xD2,  0x95,  0x27,  0xDC,  0x25,  0x05,  0x90,  0x99,  0x00,  0x07,  0xDC,  0x45,  0x47,  0xD4, 	/* 1B9F0 */
+	0x11,  0x8F,  0xF4,  0x45,  0x27,  0xD2,  0x6D,  0x27,  0xDC,  0x45,  0x07,  0xD0,  0xAD,  0x45,  0xEF,  0xF2, 	/* 1BA00 */
+	0x29,  0x4F,  0xF8,  0xAB,  0x8C,  0xF4,  0xFF,  0x21,  0x12,  0xFF,  0x21,  0x9C,  0x27,  0x0C,  0x10,  0xB0, 	/* 1BA10 */
+	0x10,  0x05,  0x5C,  0xFF,  0x43,  0x94,  0x55,  0x89,  0x14,  0x75,  0x25,  0xF2,  0x95,  0x23,  0xFC,  0x45, 	/* 1BA20 */
+	0x08,  0x50,  0xB2,  0xFC,  0x0B,  0x5C,  0xFD,  0x40,  0x14,  0x7D,  0x85,  0x54,  0x7D,  0x25,  0x52,  0x7D, 	/* 1BA30 */
+	0x21,  0x1C,  0xFF,  0x01,  0x10,  0x89,  0x00,  0x0F,  0xFE,  0x0A,  0x00,  0xA0,  0x7F,  0xC4,  0xA4,  0x52, 	/* 1BA40 */
+	0x46,  0x1C,  0x40,  0x47,  0xFC,  0x40,  0x47,  0xFC,  0x8A,  0x00,  0x0F,  0xFE,  0x28,  0x82,  0x88,  0xFC, 	/* 1BA50 */
+	0x8B,  0x48,  0xB4,  0x8D,  0xC8,  0x84,  0x8F,  0xC8,  0x84,  0x8F,  0xD8,  0x8B,  0x11,  0x00,  0xA0,  0xFF, 	/* 1BA60 */
+	0xE0,  0xA0,  0x7F,  0xC4,  0xA4,  0x4A,  0x47,  0x3C,  0x40,  0x47,  0xFC,  0x40,  0x47,  0xFC,  0x8C,  0x01, 	/* 1BA70 */
+	0x0F,  0xD0,  0x53,  0xE5,  0x22,  0xFC,  0x2A,  0xA2,  0xA9,  0x2D,  0x92,  0x88,  0x2F,  0x82,  0x88,  0x2F, 	/* 1BA80 */
+	0x8C,  0x8D,  0x00,  0x0F,  0xBC,  0x50,  0x45,  0x04,  0xF8,  0x4A,  0xBC,  0xAA,  0x0D,  0xA0,  0x8A,  0x0F, 	/* 1BA90 */
+	0xA2,  0x8A,  0x2F,  0x9E,  0x8E,  0x00,  0x4F,  0x84,  0x50,  0x45,  0x7E,  0xF8,  0x4A,  0xA4,  0xA9,  0x4D, 	/* 1BAA0 */
+	0x94,  0x88,  0x4F,  0x84,  0x88,  0x4F,  0x8C,  0x92,  0x40,  0x02,  0xFE,  0x02,  0x88,  0x28,  0x4F,  0xE0, 	/* 1BAB0 */
+	0xAA,  0x0A,  0xA2,  0xCE,  0x48,  0x24,  0xFE,  0x88,  0x28,  0xFE,  0x94,  0x02,  0x0F,  0xA0,  0x57,  0x85, 	/* 1BAC0 */
+	0x28,  0xFA,  0xAA,  0xC6,  0xA9,  0x0D,  0xFE,  0x89,  0x0F,  0x90,  0x89,  0x0F,  0x90,  0x96,  0x01,  0x0F, 	/* 1BAD0 */
+	0x90,  0x51,  0x05,  0x7E,  0xFD,  0x2A,  0x90,  0xA9,  0x8D,  0x98,  0x8A,  0x8F,  0xAA,  0x8C,  0xAF,  0x86, 	/* 1BAE0 */
+	0x98,  0x00,  0x0F,  0xB8,  0x52,  0x85,  0x2A,  0xFC,  0x6A,  0x80,  0xAF,  0xCD,  0xA4,  0x89,  0x8F,  0x98, 	/* 1BAF0 */
+	0x8A,  0x4F,  0xC2,  0xA2,  0x02,  0x0F,  0xA0,  0x52,  0x05,  0x3E,  0xFD,  0x0A,  0xD0,  0xA9,  0xED,  0x90, 	/* 1BB00 */
+	0x89,  0xEF,  0x90,  0x89,  0x0F,  0x90,  0xA3,  0x02,  0x4F,  0xA4,  0x57,  0xE5,  0x24,  0xFA,  0x4A,  0xA4, 	/* 1BB10 */
+	0xAB,  0xCD,  0xA4,  0x8A,  0x4F,  0xA4,  0x8A,  0x4F,  0xBC,  0xA5,  0x00,  0x4F,  0x98,  0x57,  0x05,  0x10, 	/* 1BB20 */
+	0xFF,  0xEA,  0x90,  0xAB,  0x8D,  0xB4,  0x8D,  0x4F,  0x92,  0x89,  0x0F,  0x90,  0xA9,  0x01,  0x0F,  0x90, 	/* 1BB30 */
+	0x51,  0xC5,  0x24,  0xFD,  0x4A,  0x88,  0xA9,  0x0D,  0xBE,  0x8D,  0x2F,  0x92,  0x89,  0x2F,  0x9E,  0xAA, 	/* 1BB40 */
+	0x01,  0x0F,  0x9C,  0x52,  0x45,  0x44,  0xFA,  0x8A,  0x90,  0xAA,  0x8D,  0xFC,  0x8A,  0x6F,  0xA4,  0x8A, 	/* 1BB50 */
+	0x4F,  0xBC,  0xAC,  0x02,  0x2F,  0xAA,  0x52,  0xA5,  0x2A,  0xFA,  0xAA,  0xBE,  0xDF,  0xE8,  0xEA,  0x8A, 	/* 1BB60 */
+	0xAF,  0xAA,  0x8A,  0x2F,  0xC2,  0xB2,  0x00,  0x0F,  0xBC,  0x52,  0x45,  0x24,  0xFB,  0xCA,  0x80,  0xA8, 	/* 1BB70 */
+	0xCD,  0xF0,  0x89,  0x0F,  0xFC,  0x89,  0x0F,  0xFE,  0xB3,  0x00,  0x8F,  0x90,  0x56,  0x45,  0x18,  0xFA, 	/* 1BB80 */
+	0x4A,  0xFE,  0xAA,  0x2D,  0xBC,  0x8A,  0x4F,  0xBC,  0x8A,  0x4F,  0xAC,  0xB5,  0x01,  0x0F,  0x90,  0x57, 	/* 1BB90 */
+	0xC5,  0x14,  0xFF,  0xEA,  0x90,  0xAB,  0xCD,  0xC8,  0x8F,  0xEF,  0x88,  0x88,  0x8F,  0x98,  0xB7,  0x02, 	/* 1BBA0 */
+	0x8F,  0xA8,  0x53,  0xE5,  0x28,  0xF8,  0x8A,  0xFE,  0xA8,  0x0D,  0xBE,  0x8A,  0x2F,  0xA2,  0x8A,  0x2F, 	/* 1BBB0 */
+	0xBE,  0xB8,  0x01,  0x0F,  0x94,  0x57,  0xE5,  0x28,  0xFA,  0xAA,  0xCE,  0xA9,  0x0D,  0xBC,  0x8E,  0x4F, 	/* 1BBC0 */
+	0x98,  0x8A,  0x4F,  0xC2,  0x82,  0x02,  0x4F,  0xA4,  0x52,  0x45,  0x7E,  0xFA,  0x4A,  0xB6,  0xAE,  0xED, 	/* 1BBD0 */
+	0xED,  0x8B,  0x5F,  0xA4,  0x8A,  0x4F,  0xA4,  0x87,  0x00,  0x8F,  0xFF,  0x52,  0x25,  0x3E,  0xF8,  0x0A, 	/* 1BBE0 */
+	0xBE,  0xA8,  0x4D,  0x88,  0x8B,  0xFF,  0x88,  0x88,  0x8F,  0x98,  0x89,  0x00,  0x8F,  0xFE,  0x52,  0x45, 	/* 1BBF0 */
+	0x24,  0xFA,  0xAA,  0xCA,  0xA8,  0x8D,  0xFE,  0x88,  0x8F,  0x88,  0x88,  0x8F,  0x88,  0x8B,  0x02,  0x8F, 	/* 1BC00 */
+	0xA8,  0x57,  0xE5,  0x28,  0xFA,  0x8A,  0xFE,  0xA8,  0x0D,  0xBC,  0x8A,  0x4F,  0xBC,  0x8A,  0x4F,  0xBC, 	/* 1BC10 */
+	0x8D,  0x03,  0xCF,  0xA4,  0x53,  0xC5,  0x24,  0xFB,  0xCA,  0x80,  0xAF,  0xED,  0x88,  0x8A,  0xEF,  0xB8, 	/* 1BC20 */
+	0x8C,  0x8F,  0x87,  0x90,  0x02,  0x0F,  0xAE,  0x57,  0xA5,  0x2E,  0xFA,  0xAA,  0xFA,  0xD9,  0xA8,  0x9E, 	/* 1BC30 */
+	0xF9,  0xA8,  0xF2,  0xF9,  0x20,  0x26,  0x92,  0x00,  0x0F,  0xBE,  0x52,  0x25,  0x3E,  0xFA,  0x2A,  0xBE, 	/* 1BC40 */
+	0xAA,  0x8D,  0xBE,  0x8C,  0x8F,  0xBC,  0x88,  0x8F,  0xFE,  0x97,  0x03,  0xAF,  0x8C,  0x52,  0xD5,  0x16, 	/* 1BC50 */
+	0xFB,  0xEA,  0xD5,  0xA9,  0x4D,  0xFF,  0x89,  0x4F,  0x94,  0x8A,  0x5F,  0xC3,  0x9C,  0x01,  0x0F,  0xA0, 	/* 1BC60 */
+	0x57,  0xC5,  0x54,  0xFF,  0xCA,  0xD4,  0xAF,  0xCD,  0xB4,  0x8B,  0xAF,  0xDE,  0x8D,  0x2F,  0x8E,  0xA2, 	/* 1BC70 */
+	0x01,  0x0F,  0xFE,  0x51,  0x05,  0x3E,  0xFD,  0x2A,  0x9E,  0xA8,  0x0D,  0xBE,  0x8A,  0xAF,  0xAA,  0x8A, 	/* 1BC80 */
+	0xAF,  0xFF,  0xA4,  0x57,  0xE3,  0x54,  0x1F,  0xE3,  0x44,  0x52,  0xCF,  0xFE,  0x0A,  0x07,  0xFC,  0x4A, 	/* 1BC90 */
+	0x47,  0x3C,  0x40,  0x47,  0xFC,  0xAA,  0x00,  0x0F,  0xFE,  0x53,  0x65,  0x5A,  0xFB,  0x6A,  0xDA,  0xAA, 	/* 1BCA0 */
+	0x4D,  0xCA,  0x8B,  0x5F,  0xC8,  0x8B,  0x0F,  0xC0,  0xAB,  0xFB,  0x8A,  0x2A,  0xBF,  0x6D,  0x28,  0xA9, 	/* 1BCB0 */
+	0x0F,  0xFE,  0x0A,  0x07,  0xFC,  0x4A,  0x47,  0x3C,  0x40,  0x47,  0xFC,  0xAF,  0x01,  0x0F,  0xFE,  0x52, 	/* 1BCC0 */
+	0x45,  0x7E,  0xF8,  0x0A,  0xAA,  0xAA,  0xAD,  0xC3,  0x8B,  0xEF,  0xAA,  0x8A,  0xAF,  0xFF,  0xB4,  0x01, 	/* 1BCD0 */
+	0x8F,  0xFE,  0x55,  0xA5,  0x7E,  0xFD,  0xAA,  0xFF,  0xA8,  0x0D,  0xFE,  0x8A,  0x4F,  0xBC,  0x8A,  0x8F, 	/* 1BCE0 */
+	0xFE,  0xB5,  0x01,  0xCF,  0x90,  0x67,  0xE6,  0x56,  0xF7,  0x8B,  0x4C,  0xB7,  0xFD,  0x52,  0x96,  0xCF, 	/* 1BCF0 */
+	0x5A,  0x9A,  0x8F,  0x18,  0xB8,  0xF9,  0x05,  0x7E,  0x52,  0x8F,  0xC6,  0xAA,  0x8A,  0xFE,  0xAA,  0x8D, 	/* 1BD00 */
+	0xFE,  0x8B,  0x2F,  0xEC,  0x8B,  0x4F,  0xE2,  0xBA,  0x00,  0xCF,  0xF0,  0x51,  0x05,  0x7E,  0xFD,  0x4A, 	/* 1BD10 */
+	0xFC,  0xAD,  0x4D,  0xFC,  0x89,  0x0F,  0xFE,  0x8B,  0x4F,  0xCA,  0x80,  0x01,  0x0F,  0xFF,  0x6A,  0xA6, 	/* 1BD20 */
+	0xEE,  0xFA,  0x8A,  0xFE,  0xAA,  0x8D,  0xFF,  0x8B,  0x2F,  0xEC,  0x8A,  0x4F,  0xB2,  0x81,  0x6E,  0xC4, 	/* 1BD30 */
+	0xA4,  0x6E,  0xCF,  0xFE,  0xAA,  0xA3,  0x38,  0x20,  0x83,  0xF8,  0x11,  0x03,  0xF8,  0xC9,  0x63,  0x30, 	/* 1BD40 */
+	0x86,  0x00,  0xC0,  0x70,  0x7C,  0x82,  0x48,  0x15,  0x0F,  0xFE,  0x0E,  0x01,  0x50,  0x24,  0x8C,  0x46, 	/* 1BD50 */
+	0x04,  0x00,  0x40,  0x87,  0x01,  0x87,  0xE4,  0x08,  0x42,  0x48,  0x11,  0x00,  0x40,  0xFF,  0xE0,  0xE0, 	/* 1BD60 */
+	0x15,  0x02,  0x48,  0xC4,  0x60,  0x40,  0x88,  0x18,  0x0E,  0x3E,  0x2A,  0x2B,  0x22,  0x63,  0xEF,  0xA8, 	/* 1BD70 */
+	0x32,  0x86,  0xA8,  0x62,  0x4A,  0x24,  0x24,  0x22,  0x81,  0x89,  0x19,  0x0E,  0x10,  0x29,  0x0B,  0x7E, 	/* 1BD80 */
+	0x65,  0x2F,  0xD2,  0x35,  0x26,  0xFE,  0x65,  0x2A,  0x52,  0x27,  0xE2,  0x42,  0x8B,  0x1F,  0xEE,  0xAA, 	/* 1BD90 */
+	0x2F,  0xEB,  0x10,  0x67,  0xEF,  0x90,  0x2F,  0xE7,  0x48,  0x6F,  0xEA,  0x10,  0x27,  0xC2,  0x10,  0x8C, 	/* 1BDA0 */
+	0x00,  0x03,  0xFC,  0x24,  0x43,  0xFC,  0x24,  0x42,  0x44,  0x3F,  0xC0,  0x40,  0x3F,  0xC0,  0x40,  0x04, 	/* 1BDB0 */
+	0x07,  0xFE,  0x8D,  0x01,  0x83,  0xE0,  0x04,  0x0F,  0xFE,  0x24,  0x83,  0xF8,  0x24,  0x83,  0xF8,  0x04, 	/* 1BDC0 */
+	0x07,  0xFC,  0x04,  0x0F,  0xFE,  0x8E,  0x00,  0x0F,  0xFC,  0xAC,  0x8F,  0xB0,  0xA9,  0x0A,  0xFE,  0xF9, 	/* 1BDD0 */
+	0x42,  0x18,  0xF9,  0x02,  0x10,  0x39,  0x0E,  0x30,  0x8F,  0x3F,  0x82,  0x08,  0x3F,  0x82,  0x08,  0xFF, 	/* 1BDE0 */
+	0xE3,  0xF8,  0x24,  0x83,  0xF8,  0x24,  0x87,  0xFC,  0x04,  0x0F,  0xFE,  0x90,  0x21,  0x07,  0x9E,  0x22, 	/* 1BDF0 */
+	0x4F,  0x98,  0x4E,  0x47,  0xFE,  0x54,  0x85,  0xF8,  0x54,  0x85,  0xF8,  0x44,  0x0B,  0xFC,  0x91,  0x04, 	/* 1BE00 */
+	0x00,  0x40,  0x0A,  0x01,  0x10,  0x3F,  0x8C,  0x46,  0x04,  0x07,  0xFC,  0x04,  0x02,  0x48,  0x15,  0x0F, 	/* 1BE10 */
+	0xFE,  0x96,  0x20,  0x02,  0x7E,  0x51,  0x24,  0x92,  0xF9,  0x22,  0x12,  0xF9,  0x22,  0x92,  0xB1,  0x26, 	/* 1BE20 */
+	0xA2,  0x32,  0x2C,  0x4C,  0x98,  0x10,  0x01,  0x7E,  0x28,  0x84,  0x48,  0xF8,  0x81,  0x08,  0xFC,  0x81, 	/* 1BE30 */
+	0x08,  0x58,  0x83,  0x48,  0x38,  0x8C,  0x18,  0x9B,  0x21,  0x02,  0x10,  0x51,  0x04,  0xFE,  0xF1,  0x22, 	/* 1BE40 */
+	0x12,  0xF9,  0x22,  0x92,  0xB1,  0x26,  0xA2,  0x32,  0x2C,  0x4C,  0x9C,  0x0A,  0x01,  0x10,  0x2A,  0x8C, 	/* 1BE50 */
+	0x46,  0x1B,  0x0E,  0x0E,  0x3F,  0x80,  0x40,  0x7F,  0xC2,  0x48,  0x15,  0x0F,  0xFE,  0x9D,  0x20,  0x82, 	/* 1BE60 */
+	0x08,  0x50,  0x84,  0x88,  0xFF,  0xE2,  0x08,  0xF8,  0x82,  0x08,  0xA8,  0x87,  0x08,  0x38,  0x8C,  0x08, 	/* 1BE70 */
+	0x9F,  0x23,  0x83,  0x08,  0x4A,  0x88,  0x28,  0xFA,  0x82,  0x28,  0xFA,  0x42,  0x24,  0xAA,  0x47,  0x44, 	/* 1BE80 */
+	0x3C,  0x2C,  0x82,  0xA1,  0x11,  0x01,  0x08,  0x24,  0x44,  0xA4,  0x11,  0x02,  0x08,  0xDF,  0xE0,  0x40, 	/* 1BE90 */
+	0x7F,  0xC2,  0x48,  0x15,  0x0F,  0xFE,  0xA3,  0x21,  0x02,  0x10,  0x51,  0x04,  0xBE,  0xFA,  0x22,  0x52, 	/* 1BEA0 */
+	0xF8,  0xA2,  0x8A,  0xB0,  0x26,  0x82,  0x30,  0x2C,  0x0C,  0xA6,  0x20,  0x02,  0x3E,  0x52,  0x24,  0xA2, 	/* 1BEB0 */
+	0xFA,  0x22,  0x22,  0xFA,  0x22,  0x22,  0xB2,  0x26,  0xA2,  0x33,  0xEC,  0x00,  0xA7,  0x22,  0x22,  0x2A, 	/* 1BEC0 */
+	0x52,  0xA4,  0xAA,  0xFA,  0xA2,  0x2A,  0xFA,  0xA2,  0x2A,  0xB2,  0xA6,  0xAA,  0x32,  0x2C,  0x42,  0xB5, 	/* 1BED0 */
+	0x20,  0x02,  0x7E,  0x51,  0x24,  0xAA,  0xF5,  0x42,  0x14,  0xF8,  0x82,  0x88,  0xB1,  0x46,  0xA4,  0x34, 	/* 1BEE0 */
+	0x2C,  0x81,  0xB6,  0x21,  0x03,  0x54,  0x4D,  0xC8,  0x74,  0xFD,  0x42,  0x54,  0xF5,  0x42,  0x5C,  0xAD, 	/* 1BEF0 */
+	0x07,  0x42,  0x3C,  0x2C,  0x3E,  0xBC,  0x20,  0x02,  0x7C,  0x51,  0x44,  0x94,  0xF9,  0x42,  0x34,  0xF9, 	/* 1BF00 */
+	0x42,  0x9C,  0xB2,  0x66,  0xA4,  0x34,  0x4C,  0x98,  0xBF,  0x20,  0x62,  0x38,  0x52,  0x04,  0xA0,  0xFB, 	/* 1BF10 */
+	0xE2,  0x24,  0xFA,  0x42,  0xA4,  0xB2,  0x46,  0x44,  0x38,  0x4C,  0x04,  0x8D,  0x21,  0x02,  0x16,  0x57, 	/* 1BF20 */
+	0x84,  0x90,  0xF5,  0x42,  0x54,  0xF5,  0x42,  0x7C,  0xB5,  0x06,  0x92,  0x31,  0x2C,  0x0E,  0x8E,  0x21, 	/* 1BF30 */
+	0x02,  0x10,  0x51,  0xE4,  0xA2,  0xFB,  0x22,  0x52,  0xF9,  0x22,  0x2A,  0xB3,  0xA6,  0x8A,  0x30,  0x2C, 	/* 1BF40 */
+	0x0C,  0x91,  0x20,  0x03,  0x3E,  0x4A,  0x08,  0x20,  0xFB,  0xC2,  0x24,  0xFA,  0x42,  0x34,  0xAA,  0x87, 	/* 1BF50 */
+	0x48,  0x39,  0x4C,  0x62,  0x94,  0x20,  0x82,  0x08,  0x52,  0xA4,  0xAA,  0xFA,  0x92,  0x49,  0xF8,  0xA2, 	/* 1BF60 */
+	0x9A,  0xB0,  0x46,  0x88,  0x31,  0x0C,  0x60,  0x95,  0x27,  0xC2,  0x14,  0x51,  0x44,  0x94,  0xF9,  0x42, 	/* 1BF70 */
+	0x7E,  0xF9,  0x42,  0xA4,  0xB2,  0x46,  0xA4,  0x32,  0x4C,  0x7E,  0x9E,  0x21,  0x03,  0x10,  0x4A,  0x08, 	/* 1BF80 */
+	0x3E,  0xFC,  0x22,  0x3A,  0xF8,  0x22,  0x0A,  0xAB,  0x27,  0x02,  0x38,  0x2C,  0x0C,  0xA9,  0x20,  0x02, 	/* 1BF90 */
+	0x3E,  0x50,  0x04,  0xBE,  0xFA,  0x22,  0x22,  0xFB,  0xE2,  0xA0,  0xB2,  0x06,  0xC0,  0x34,  0x0C,  0x80, 	/* 1BFA0 */
+	0xAC,  0x20,  0x02,  0x3E,  0x52,  0x24,  0xA2,  0xFB,  0xE2,  0x28,  0xFA,  0x82,  0xA8,  0xB2,  0x86,  0xC4, 	/* 1BFB0 */
+	0x34,  0x4C,  0x82,  0xB4,  0x21,  0x02,  0x10,  0x52,  0x84,  0xBC,  0xF4,  0x22,  0xFC,  0xFA,  0x42,  0x24, 	/* 1BFC0 */
+	0xB2,  0x46,  0xB8,  0x32,  0x0C,  0x20,  0xB7,  0x21,  0x02,  0x10,  0x51,  0x04,  0xFE,  0xF1,  0x02,  0x10, 	/* 1BFD0 */
+	0xF9,  0x02,  0xFC,  0xB4,  0x46,  0xC4,  0x34,  0x4C,  0x7C,  0xBF,  0x20,  0x02,  0x3E,  0x52,  0xA4,  0xAA, 	/* 1BFE0 */
+	0xFE,  0xA2,  0x3E,  0xFA,  0xA2,  0xAA,  0xB2,  0xA6,  0xAA,  0x33,  0xEC,  0x20,  0x84,  0x21,  0x02,  0x50, 	/* 1BFF0 */
+	0x55,  0x04,  0xFC,  0xF9,  0x02,  0x10,  0xFF,  0xE2,  0x10,  0xB2,  0x86,  0xA8,  0x34,  0x4C,  0x82,  0x85, 	/* 1C000 */
+	0x20,  0x02,  0x7E,  0x54,  0x04,  0xC0,  0xF7,  0xC2,  0x44,  0xFC,  0x42,  0x7C,  0xB4,  0x06,  0xC0,  0x34, 	/* 1C010 */
+	0x0C,  0xFE,  0x88,  0x21,  0x02,  0x10,  0x57,  0xE4,  0xC2,  0xFA,  0x02,  0x20,  0xFA,  0x42,  0xB8,  0xB2, 	/* 1C020 */
+	0x06,  0xA2,  0x32,  0x2C,  0x1E,  0x89,  0x21,  0x02,  0x10,  0x57,  0xE4,  0x90,  0xF9,  0x42,  0x64,  0xFA, 	/* 1C030 */
+	0x82,  0x90,  0xB1,  0x86,  0x24,  0x3F,  0xAC,  0x02,  0x8B,  0x22,  0x02,  0x20,  0x53,  0xE4,  0xC2,  0xFB, 	/* 1C040 */
+	0xA2,  0x2A,  0xFA,  0xA2,  0xBA,  0xB2,  0xC6,  0xA1,  0x32,  0x1C,  0x1F,  0x90,  0x20,  0x02,  0x7F,  0x51, 	/* 1C050 */
+	0x04,  0x90,  0xF9,  0x02,  0x20,  0xFB,  0xE2,  0x52,  0xA9,  0x27,  0x12,  0x39,  0x2C,  0x1E,  0x97,  0x22, 	/* 1C060 */
+	0x42,  0x24,  0x52,  0x44,  0xFE,  0xFA,  0x42,  0x24,  0xFA,  0x42,  0xBC,  0xB2,  0x46,  0xA4,  0x32,  0x4C, 	/* 1C070 */
+	0x3C,  0x9A,  0x24,  0x02,  0xCE,  0x5A,  0xA8,  0xAA,  0xFA,  0xA2,  0xAA,  0xFA,  0xA2,  0xAA,  0xAE,  0xA7, 	/* 1C080 */
+	0x2E,  0x3A,  0x8C,  0x48,  0x9B,  0x22,  0x82,  0x28,  0x52,  0x84,  0xC4,  0xF8,  0x42,  0x02,  0xFF,  0xC2, 	/* 1C090 */
+	0x44,  0xB4,  0x46,  0x44,  0x3C,  0x4E,  0x7C,  0x9E,  0x20,  0x83,  0x0C,  0x48,  0xA8,  0x7E,  0xFC,  0x82, 	/* 1C0A0 */
+	0x4A,  0xF4,  0xA2,  0x4C,  0xB6,  0x86,  0xD4,  0x32,  0x4C,  0x42,  0xA2,  0x21,  0x02,  0x10,  0x51,  0x04, 	/* 1C0B0 */
+	0xFE,  0xF9,  0x02,  0x38,  0xF5,  0x42,  0x92,  0xB7,  0xC6,  0x10,  0x39,  0x0C,  0x10,  0xA4,  0x22,  0x02, 	/* 1C0C0 */
+	0x20,  0x53,  0xE4,  0xC2,  0xFB,  0xA2,  0x2A,  0xFA,  0xA2,  0xAA,  0xB3,  0xA6,  0x82,  0x30,  0x2C,  0x0C, 	/* 1C0D0 */
+	0xA6,  0x20,  0x02,  0x7E,  0x50,  0x84,  0x88,  0xF8,  0x82,  0x2E,  0xFA,  0x82,  0x28,  0xB2,  0x86,  0xA8, 	/* 1C0E0 */
+	0x32,  0x8C,  0x7E,  0xB1,  0x20,  0x83,  0x08,  0x4F,  0xE8,  0x40,  0x7C,  0x82,  0x48,  0xF4,  0x82,  0x48, 	/* 1C0F0 */
+	0xAD,  0x47,  0x52,  0x3D,  0xEC,  0xB2,  0xBE,  0x21,  0x02,  0x18,  0x52,  0x48,  0xFA,  0xF5,  0x02,  0x7C, 	/* 1C100 */
+	0xF5,  0x02,  0x90,  0xB7,  0xE6,  0x90,  0x31,  0x0C,  0x10,  0x80,  0x20,  0x02,  0x7C,  0x54,  0x44,  0xFC, 	/* 1C110 */
+	0xF4,  0x42,  0x7C,  0xFD,  0x22,  0x54,  0xB4,  0x86,  0xC8,  0x37,  0x4C,  0xC2,  0x83,  0x21,  0x02,  0x10, 	/* 1C120 */
+	0x57,  0xE4,  0xA8,  0xF4,  0xC2,  0xFA,  0xFA,  0x82,  0x28,  0xB2,  0x86,  0xAA,  0x34,  0xAC,  0x86,  0x85, 	/* 1C130 */
+	0x20,  0x03,  0x7E,  0x4C,  0x28,  0xFA,  0xF4,  0x22,  0x7A,  0xF6,  0xA2,  0x6A,  0xAF,  0xA7,  0x42,  0x3C, 	/* 1C140 */
+	0x2C,  0x46,  0x91,  0x21,  0x02,  0x50,  0x55,  0x04,  0xFC,  0xF9,  0x02,  0x10,  0xFF,  0xE2,  0x28,  0xB2, 	/* 1C150 */
+	0x86,  0xAA,  0x34,  0xAC,  0x86,  0x93,  0x23,  0x02,  0x10,  0x52,  0x84,  0xC4,  0xF7,  0xE2,  0x10,  0xF9, 	/* 1C160 */
+	0x02,  0x7C,  0xB1,  0x06,  0x90,  0x31,  0x0C,  0xFE,  0x95,  0x21,  0x03,  0x7E,  0x49,  0x08,  0x7C,  0xF9, 	/* 1C170 */
+	0x42,  0x7C,  0xF5,  0x02,  0x7E,  0xA9,  0x27,  0x1C,  0x3A,  0x4C,  0xC2,  0x96,  0x21,  0x02,  0x50,  0x55, 	/* 1C180 */
+	0x04,  0xFC,  0xF9,  0x02,  0x10,  0xFF,  0xE2,  0x98,  0xB3,  0x46,  0x52,  0x39,  0x0C,  0x10,  0x98,  0x21, 	/* 1C190 */
+	0x02,  0x1C,  0x52,  0x44,  0xA4,  0xF5,  0x82,  0x08,  0xF9,  0x02,  0x3E,  0xB3,  0x26,  0xD2,  0x31,  0x2C, 	/* 1C1A0 */
+	0x1E,  0x9A,  0x22,  0x83,  0x28,  0x4A,  0x88,  0xAA,  0xF6,  0xC2,  0x28,  0xF6,  0xC2,  0xAA,  0xAA,  0xA7, 	/* 1C1B0 */
+	0x28,  0x3C,  0xAC,  0x86,  0x9B,  0x20,  0xC2,  0x70,  0x51,  0x04,  0x90,  0xFF,  0xE2,  0x10,  0xF9,  0x02, 	/* 1C1C0 */
+	0x7C,  0xB4,  0x46,  0xC4,  0x34,  0x4C,  0x7C,  0x9C,  0x24,  0x02,  0x4E,  0x4A,  0x0B,  0x10,  0x3F,  0xF4, 	/* 1C1D0 */
+	0x44,  0xDF,  0x44,  0x44,  0x55,  0x44,  0xE4,  0x47,  0x45,  0x8C,  0xAD,  0x21,  0x82,  0x14,  0x51,  0xC4, 	/* 1C1E0 */
+	0xF0,  0xF9,  0xC2,  0x70,  0xF9,  0xE2,  0x74,  0xB0,  0x86,  0x9A,  0x36,  0x6C,  0x02,  0xB7,  0x21,  0x02, 	/* 1C1F0 */
+	0x54,  0x55,  0x44,  0x92,  0xF7,  0xC2,  0x44,  0xFF,  0xC2,  0x44,  0xB7,  0xC6,  0xC4,  0x34,  0x4C,  0x4C, 	/* 1C200 */
+	0xB9,  0x20,  0xC3,  0x70,  0x49,  0x08,  0x7E,  0xFB,  0x82,  0x54,  0xF9,  0x22,  0x7C,  0xA9,  0x67,  0x12, 	/* 1C210 */
+	0x3A,  0x2C,  0x4C,  0x8F,  0x21,  0x03,  0x10,  0x4F,  0xE8,  0x10,  0xFD,  0x42,  0x54,  0xFB,  0xA2,  0x12, 	/* 1C220 */
+	0xA9,  0x87,  0x18,  0x3A,  0x4C,  0x42,  0x92,  0x22,  0x02,  0x3C,  0x52,  0x44,  0xD8,  0xF9,  0x42,  0x6B, 	/* 1C230 */
+	0xF8,  0x82,  0x3E,  0xB0,  0x86,  0xFF,  0x30,  0x8C,  0x08,  0xA4,  0x20,  0x82,  0xE8,  0x5A,  0x84,  0xBE, 	/* 1C240 */
+	0xFE,  0xA2,  0xAA,  0xFE,  0xA2,  0xAA,  0xBB,  0xA6,  0xEA,  0x39,  0x2C,  0x26,  0xA9,  0x22,  0x42,  0x7E, 	/* 1C250 */
+	0x52,  0x44,  0x88,  0xF8,  0x82,  0x7E,  0xFA,  0x02,  0xA0,  0xB2,  0x06,  0x20,  0x3A,  0x0C,  0x1E,  0xAA, 	/* 1C260 */
+	0x21,  0x42,  0x12,  0x57,  0xE4,  0x90,  0xF7,  0xE2,  0x52,  0xFF,  0xE2,  0x52,  0xB7,  0xE6,  0xD2,  0x35, 	/* 1C270 */
+	0x2C,  0x56,  0xAD,  0x24,  0x43,  0x24,  0x4A,  0x88,  0x7C,  0x7C,  0x42,  0x44,  0xFF,  0xC2,  0x28,  0xAA, 	/* 1C280 */
+	0x87,  0x28,  0x3C,  0xAC,  0x86,  0xB2,  0x20,  0x42,  0x38,  0x52,  0x04,  0xBE,  0xFA,  0x42,  0x24,  0xFA, 	/* 1C290 */
+	0x42,  0x7E,  0xB0,  0x06,  0xA4,  0x32,  0x2C,  0x42,  0xB3,  0x21,  0x02,  0x7E,  0x51,  0x04,  0xBC,  0xF1, 	/* 1C2A0 */
+	0x02,  0xFE,  0xF2,  0x42,  0xFE,  0xB2,  0x46,  0x54,  0x39,  0x4C,  0x0C,  0xB8,  0x20,  0x02,  0x7E,  0x54, 	/* 1C2B0 */
+	0x24,  0xFE,  0xF4,  0x82,  0x7E,  0xFC,  0x82,  0x48,  0xB7,  0xE6,  0xA2,  0x32,  0x2C,  0x3E,  0xBA,  0x20, 	/* 1C2C0 */
+	0x82,  0xFE,  0x58,  0x28,  0x40,  0xFF,  0xE2,  0x5A,  0xF5,  0xA2,  0xBA,  0xB2,  0xE6,  0xA8,  0x34,  0xAC, 	/* 1C2D0 */
+	0x86,  0xBC,  0x20,  0x03,  0xFE,  0x4C,  0x68,  0xAA,  0x7F,  0xE2,  0x92,  0xF9,  0x22,  0xD6,  0xAD,  0x67, 	/* 1C2E0 */
+	0xFE,  0x38,  0x2C,  0x86,  0x86,  0x21,  0x03,  0x7C,  0x49,  0x08,  0xFC,  0xF1,  0x02,  0xFE,  0xF4,  0x42, 	/* 1C2F0 */
+	0x7C,  0xAC,  0x47,  0x7C,  0x3C,  0x4C,  0x4C,  0x8F,  0x20,  0x03,  0x7E,  0x4A,  0x88,  0x28,  0xFE,  0xE2, 	/* 1C300 */
+	0x42,  0xFC,  0x22,  0x42,  0xAE,  0xE7,  0x28,  0x3A,  0x8C,  0x7E,  0x90,  0x22,  0x42,  0x28,  0x57,  0xE4, 	/* 1C310 */
+	0xC8,  0xF4,  0x82,  0x7C,  0xFC,  0x82,  0x48,  0xB7,  0xC6,  0xC8,  0x34,  0x8C,  0x7E,  0x98,  0x20,  0xC2, 	/* 1C320 */
+	0x70,  0x51,  0x04,  0xFE,  0xF5,  0x42,  0xFE,  0xF5,  0x42,  0x54,  0xBF,  0xE6,  0x90,  0x31,  0x0C,  0x7E, 	/* 1C330 */
+	0x99,  0x22,  0xA2,  0x2A,  0x55,  0x44,  0xAA,  0xFA,  0xA2,  0x00,  0xFB,  0xE2,  0xAA,  0xB3,  0xE6,  0xAA, 	/* 1C340 */
+	0x32,  0xAC,  0x3E,  0x9A,  0x20,  0xC3,  0x74,  0x4B,  0x28,  0x4A,  0xF7,  0xC2,  0x14,  0xFF,  0xF2,  0x14, 	/* 1C350 */
+	0xB7,  0xC6,  0x10,  0x39,  0x0C,  0x30,  0xA0,  0x21,  0x02,  0x7E,  0x54,  0x24,  0x80,  0xFF,  0xE2,  0x10, 	/* 1C360 */
+	0xF5,  0x02,  0x5C,  0xB5,  0x06,  0xF0,  0x35,  0x8C,  0x86,  0xA2,  0x21,  0x02,  0x14,  0x57,  0xE4,  0x94, 	/* 1C370 */
+	0xF8,  0xA2,  0x76,  0xF9,  0x02,  0x7E,  0xB1,  0x46,  0x98,  0x32,  0xAC,  0x46,  0xA3,  0x20,  0x02,  0xFE, 	/* 1C380 */
+	0x55,  0x24,  0xB4,  0xF2,  0xC2,  0x52,  0xFF,  0xE2,  0x22,  0xB2,  0xA6,  0x44,  0x3A,  0xAC,  0x91,  0xA6, 	/* 1C390 */
+	0x22,  0x02,  0x7C,  0x54,  0x44,  0xFC,  0xFC,  0x42,  0x7C,  0xF9,  0x02,  0x7E,  0xB5,  0x26,  0xD2,  0x35, 	/* 1C3A0 */
+	0x6C,  0x10,  0xA8,  0x22,  0x42,  0x24,  0x57,  0xE4,  0xA4,  0xF2,  0x42,  0x7E,  0xFD,  0x22,  0x52,  0xB7, 	/* 1C3B0 */
+	0xE6,  0xD2,  0x35,  0x2C,  0x7E,  0xAB,  0x20,  0x02,  0x7C,  0x54,  0x44,  0xFC,  0xF4,  0x42,  0xFF,  0xF2, 	/* 1C3C0 */
+	0x02,  0x7E,  0xBA,  0xA6,  0xAA,  0x35,  0x2C,  0x0C,  0xAC,  0x21,  0x02,  0x7E,  0x51,  0x04,  0xFC,  0xFD, 	/* 1C3D0 */
+	0x42,  0x7C,  0xFD,  0x42,  0x7C,  0xB3,  0x86,  0xD4,  0x31,  0x2C,  0x10,  0xAE,  0x20,  0x03,  0x7E,  0x4D, 	/* 1C3E0 */
+	0x28,  0x7E,  0xFD,  0x22,  0x52,  0xF7,  0xA2,  0x6A,  0xAE,  0xA7,  0x7A,  0x3C,  0x2C,  0x7E,  0xAF,  0x22, 	/* 1C3F0 */
+	0x82,  0x28,  0x57,  0xC4,  0xA8,  0xFA,  0x82,  0x7E,  0xF8,  0x02,  0x3C,  0xB2,  0x46,  0xBC,  0x32,  0x4C, 	/* 1C400 */
+	0x3C,  0xB2,  0x20,  0x02,  0x7C,  0x50,  0x44,  0xBC,  0xF8,  0x42,  0x7E,  0xF9,  0x42,  0x58,  0xB3,  0x86, 	/* 1C410 */
+	0xD4,  0x31,  0x2C,  0x30,  0xB5,  0x22,  0x82,  0x7E,  0x52,  0x84,  0x90,  0xF9,  0x82,  0x2A,  0xFE,  0xC2, 	/* 1C420 */
+	0xA8,  0xB2,  0x86,  0x2A,  0x3A,  0xAC,  0x26,  0xBA,  0x22,  0x42,  0x7E,  0x52,  0x44,  0x90,  0xF9,  0x02, 	/* 1C430 */
+	0x7E,  0xF9,  0x02,  0x9C,  0xB1,  0x46,  0xA4,  0x32,  0x4C,  0x58,  0xBB,  0x20,  0x42,  0x76,  0x50,  0x44, 	/* 1C440 */
+	0xFF,  0xF1,  0x42,  0x14,  0xF9,  0xC2,  0x54,  0xB5,  0x46,  0x5D,  0x3E,  0x3C,  0x01,  0x84,  0x20,  0x83, 	/* 1C450 */
+	0x7E,  0x48,  0x08,  0x3C,  0xFA,  0x42,  0x24,  0xFB,  0xC2,  0x08,  0xAA,  0xC7,  0x4A,  0x38,  0xAC,  0x18, 	/* 1C460 */
+	0x8B,  0x27,  0xC2,  0x44,  0x55,  0xC4,  0xD4,  0xF5,  0x42,  0xFE,  0xF8,  0x22,  0xBA,  0xBA,  0xA6,  0xBA, 	/* 1C470 */
+	0x38,  0x2C,  0x86,  0x8D,  0x20,  0x83,  0x7E,  0x4D,  0x48,  0xFE,  0xF5,  0x42,  0x5C,  0xFC,  0x02,  0x7E, 	/* 1C480 */
+	0xAD,  0x47,  0x48,  0x39,  0x4C,  0xA2,  0x94,  0x2E,  0xE2,  0xAA,  0x5A,  0xA4,  0xEE,  0xF8,  0x02,  0x7C, 	/* 1C490 */
+	0xF8,  0x02,  0x7E,  0xB2,  0x06,  0xBC,  0x30,  0x4C,  0x18,  0x96,  0x22,  0x42,  0x7E,  0x52,  0x44,  0xBC, 	/* 1C4A0 */
+	0xFA,  0x42,  0x3C,  0xFA,  0x42,  0xFE,  0xB5,  0x46,  0x66,  0x3C,  0x0C,  0x7E,  0x9B,  0x21,  0xC3,  0x54, 	/* 1C4B0 */
+	0x49,  0x48,  0x94,  0xFF,  0x62,  0x80,  0xFD,  0xE2,  0x82,  0xAF,  0x47,  0x88,  0x39,  0x4C,  0xA2,  0x9C, 	/* 1C4C0 */
+	0x20,  0x02,  0x7E,  0x55,  0x24,  0xD2,  0xF7,  0x62,  0x40,  0xFF,  0xE2,  0x4A,  0xB7,  0xA6,  0xC4,  0x34, 	/* 1C4D0 */
+	0xAC,  0x51,  0xA0,  0x21,  0x02,  0x7C,  0x54,  0x44,  0xFC,  0xFC,  0x42,  0x7C,  0xF8,  0x02,  0x7E,  0xB1, 	/* 1C4E0 */
+	0x06,  0x7C,  0x39,  0x0C,  0xFE,  0xAC,  0x21,  0x42,  0x64,  0x52,  0x44,  0xA5,  0xF7,  0xD2,  0x2E,  0xF6, 	/* 1C4F0 */
+	0x42,  0x74,  0xAA,  0xA7,  0x2A,  0x3B,  0x2C,  0x21,  0xAE,  0x27,  0x02,  0x28,  0x54,  0x48,  0xBA,  0xF0, 	/* 1C500 */
+	0x02,  0xEA,  0xFA,  0xA2,  0xEA,  0xBB,  0x46,  0xEA,  0x3A,  0xAC,  0xAA,  0xB5,  0x20,  0x83,  0x3E,  0x5C, 	/* 1C510 */
+	0xA8,  0x7F,  0x74,  0xA2,  0xBE,  0xFE,  0x82,  0xBE,  0xB6,  0x86,  0x3E,  0x35,  0x8C,  0x8F,  0xBC,  0x20, 	/* 1C520 */
+	0x42,  0x05,  0x57,  0xF4,  0xC4,  0xF7,  0xC2,  0x45,  0xFF,  0x52,  0x55,  0xB7,  0x26,  0xC6,  0x34,  0xAC, 	/* 1C530 */
+	0x91,  0xBE,  0x21,  0xC2,  0x70,  0x51,  0x04,  0xFE,  0xFD,  0x42,  0x7C,  0xF5,  0x42,  0x7C,  0xA9,  0x07, 	/* 1C540 */
+	0x7C,  0x39,  0x0C,  0xFE,  0x8C,  0x22,  0x82,  0x7E,  0x52,  0x84,  0xFE,  0xFA,  0xA2,  0x7E,  0xFA,  0xA2, 	/* 1C550 */
+	0x7E,  0xB2,  0x86,  0x6C,  0x3A,  0xAC,  0x28,  0x94,  0x21,  0x02,  0xFE,  0x59,  0x24,  0xAA,  0xF4,  0x42, 	/* 1C560 */
+	0x14,  0xFA,  0x82,  0x44,  0xAF,  0xE7,  0x45,  0x3C,  0x4C,  0x7C,  0x96,  0x21,  0x03,  0x52,  0x4B,  0x48, 	/* 1C570 */
+	0x7C,  0xF4,  0x42,  0x7C,  0x74,  0x42,  0x7C,  0xAC,  0x47,  0x7C,  0x3A,  0x4C,  0xC2,  0x97,  0x20,  0x82, 	/* 1C580 */
+	0x14,  0x52,  0x24,  0xFF,  0xFA,  0x22,  0x3E,  0xFA,  0x22,  0x3E,  0xB4,  0x06,  0xFE,  0x32,  0x2C,  0x3E, 	/* 1C590 */
+	0x9A,  0x20,  0x42,  0x08,  0x55,  0xE4,  0xB2,  0xF9,  0xE2,  0x10,  0xFD,  0xE2,  0x52,  0xB5,  0x26,  0xDE, 	/* 1C5A0 */
+	0x36,  0x0C,  0x9F,  0xA7,  0x25,  0x43,  0x54,  0x4F,  0xC8,  0x80,  0xFF,  0xE2,  0x00,  0x7F,  0xC2,  0x44, 	/* 1C5B0 */
+	0xAF,  0xC7,  0x44,  0x3A,  0x8C,  0x7E,  0xAC,  0x20,  0x82,  0x7E,  0x50,  0x04,  0xBC,  0xFA,  0x42,  0x3C, 	/* 1C5C0 */
+	0xFF,  0xE2,  0x42,  0xB7,  0xA6,  0xEA,  0x37,  0xAC,  0x46,  0xAD,  0x24,  0xC2,  0x70,  0x54,  0x24,  0xBE, 	/* 1C5D0 */
+	0xFA,  0x42,  0xBC,  0xFA,  0x42,  0xBC,  0xBA,  0x46,  0xFE,  0x32,  0x4C,  0xC2,  0xAE,  0x21,  0x02,  0x7E, 	/* 1C5E0 */
+	0x51,  0x04,  0xFC,  0xF4,  0x42,  0x7C,  0xFC,  0x42,  0x7C,  0xB4,  0x46,  0xFE,  0x32,  0x4C,  0xC2,  0xB0, 	/* 1C5F0 */
+	0x21,  0xC2,  0x24,  0x54,  0x24,  0xBC,  0xF8,  0x02,  0x3C,  0xFA,  0x42,  0x42,  0xAF,  0xD7,  0x54,  0x35, 	/* 1C600 */
+	0x4C,  0xFE,  0xB9,  0x21,  0xC2,  0x14,  0x52,  0x24,  0xFC,  0xF0,  0x82,  0xC8,  0xF7,  0xE2,  0x48,  0xB5, 	/* 1C610 */
+	0x46,  0x62,  0x3A,  0x0C,  0x9F,  0x83,  0x24,  0x82,  0x48,  0x5F,  0xE4,  0x48,  0xF5,  0x02,  0x7E,  0xFE, 	/* 1C620 */
+	0x42,  0x7E,  0xBA,  0x46,  0xAC,  0x33,  0x2C,  0x61,  0x88,  0x24,  0x82,  0x3E,  0x50,  0x84,  0xBE,  0xFE, 	/* 1C630 */
+	0xA2,  0x3E,  0xFE,  0xA2,  0x7E,  0xB4,  0x87,  0x5E,  0x2A,  0x8D,  0x1F,  0x90,  0x20,  0x03,  0xFE,  0x53, 	/* 1C640 */
+	0x68,  0xDA,  0xF3,  0x62,  0x5A,  0xFA,  0x82,  0x4C,  0xA9,  0x37,  0x64,  0x39,  0x8C,  0x60,  0x91,  0x21, 	/* 1C650 */
+	0x02,  0x7E,  0x52,  0x44,  0xA8,  0xF7,  0xE2,  0x52,  0xF7,  0xA2,  0x52,  0xB7,  0xA6,  0xEA,  0x37,  0xAC, 	/* 1C660 */
+	0x46,  0x96,  0x04,  0x07,  0xFE,  0x49,  0x47,  0xFC,  0x5E,  0x65,  0x38,  0xBD,  0xE0,  0xA0,  0x31,  0x8D, 	/* 1C670 */
+	0xF6,  0x0A,  0x07,  0xFC,  0x97,  0x2F,  0xE2,  0xAA,  0x5F,  0xA4,  0x94,  0xFF,  0x42,  0xAA,  0xFF,  0x12, 	/* 1C680 */
+	0x10,  0xB7,  0xC6,  0x90,  0x31,  0x0C,  0xFE,  0x98,  0x22,  0x82,  0xAE,  0x5A,  0xA8,  0xBA,  0xFE,  0x42, 	/* 1C690 */
+	0x28,  0xFE,  0x22,  0xBF,  0xAB,  0x27,  0xAA,  0x2A,  0x2C,  0x26,  0x9D,  0x27,  0xC2,  0x44,  0x57,  0xC4, 	/* 1C6A0 */
+	0xC4,  0xFF,  0xE2,  0xAA,  0xFF,  0xE2,  0x00,  0xB7,  0xC6,  0xA4,  0x31,  0x8C,  0x66,  0xA1,  0x21,  0x02, 	/* 1C6B0 */
+	0x7C,  0x52,  0x84,  0xFE,  0xF4,  0x42,  0x7C,  0xFC,  0x42,  0x7C,  0xB2,  0x86,  0xA8,  0x34,  0xAC,  0x86, 	/* 1C6C0 */
+	0xA4,  0x21,  0x03,  0x7C,  0x4D,  0x48,  0x7E,  0xFD,  0x42,  0x7C,  0xF5,  0x42,  0xFE,  0xA9,  0x47,  0x24, 	/* 1C6D0 */
+	0x3B,  0x8C,  0x64,  0xA5,  0x21,  0x02,  0xFE,  0x58,  0x24,  0xBE,  0xFA,  0x82,  0x5E,  0xF5,  0x22,  0xD2, 	/* 1C6E0 */
+	0xB5,  0xE6,  0xD2,  0x35,  0x2C,  0x5E,  0xA8,  0x10,  0x4F,  0xF8,  0x55,  0x07,  0xDF,  0x55,  0x4F,  0xD4, 	/* 1C6F0 */
+	0x16,  0x41,  0xA4,  0x31,  0x8F,  0xFE,  0x15,  0x07,  0xFC,  0x83,  0x21,  0x02,  0x7C,  0x51,  0x04,  0x54, 	/* 1C700 */
+	0xFE,  0xE2,  0x44,  0xFF,  0xE2,  0x00,  0xB7,  0xE6,  0xA8,  0x32,  0xAC,  0x46,  0x87,  0x20,  0xC2,  0x70, 	/* 1C710 */
+	0x55,  0x44,  0xB8,  0xFF,  0xE2,  0x34,  0xF5,  0x22,  0xFD,  0xB5,  0x46,  0x7C,  0x3D,  0x4C,  0x7C,  0x90, 	/* 1C720 */
+	0x21,  0x02,  0x7E,  0x52,  0x84,  0xFC,  0xF4,  0x62,  0x7D,  0xFC,  0x42,  0x7C,  0xB1,  0x06,  0x54,  0x39, 	/* 1C730 */
+	0x2C,  0x30,  0x93,  0x22,  0x42,  0xF4,  0x50,  0x48,  0xEF,  0xFA,  0xA2,  0xF2,  0xF0,  0xA2,  0xF4,  0xB2, 	/* 1C740 */
+	0x46,  0xFA,  0x32,  0xAC,  0x71,  0x94,  0x2F,  0xE2,  0x28,  0x5F,  0xE8,  0xAA,  0xFF,  0xE2,  0x44,  0xF7, 	/* 1C750 */
+	0xC2,  0x44,  0xB7,  0xC6,  0x10,  0x3F,  0xEC,  0x10,  0x98,  0x21,  0x02,  0x7C,  0x52,  0x84,  0xFE,  0xF5, 	/* 1C760 */
+	0x42,  0x7C,  0xFD,  0x42,  0x7C,  0xB1,  0x06,  0xFC,  0x31,  0x0C,  0xFE,  0x99,  0x27,  0x02,  0x16,  0x56, 	/* 1C770 */
+	0x84,  0xAA,  0xFD,  0xC2,  0x82,  0xF7,  0xC2,  0x44,  0xB7,  0xC6,  0xC4,  0x32,  0x8C,  0x7E,  0x9A,  0x20, 	/* 1C780 */
+	0x03,  0x7E,  0x4A,  0x88,  0x6E,  0xFC,  0x22,  0x6E,  0xFA,  0x82,  0x7E,  0xAA,  0x07,  0x6A,  0x3A,  0x2C, 	/* 1C790 */
+	0x1E,  0xA1,  0x24,  0x82,  0xEC,  0x54,  0xA4,  0xFF,  0xF0,  0x82,  0xEA,  0xFA,  0xA2,  0xEA,  0xBA,  0x46, 	/* 1C7A0 */
+	0x54,  0x36,  0xCD,  0x92,  0xAB,  0x22,  0x82,  0x7E,  0x54,  0x84,  0xFC,  0xFC,  0x82,  0x7E,  0xF0,  0x02, 	/* 1C7B0 */
+	0xEE,  0xBA,  0xA6,  0xBA,  0x38,  0x2C,  0x86,  0xB5,  0x24,  0x82,  0xEC,  0x54,  0xA4,  0xFF,  0xF8,  0x82, 	/* 1C7C0 */
+	0xEA,  0xFA,  0xA2,  0xEA,  0xB4,  0x46,  0xEC,  0x35,  0x4C,  0xE2,  0xB6,  0x2F,  0xE2,  0xAA,  0x5F,  0xF4, 	/* 1C7D0 */
+	0x00,  0xFF,  0xE2,  0x44,  0xF7,  0xC2,  0x12,  0xB3,  0x46,  0x68,  0x3B,  0x4C,  0x62,  0xB8,  0x2F,  0xE3, 	/* 1C7E0 */
+	0xAA,  0x4F,  0xE8,  0x10,  0xF7,  0xC2,  0x10,  0xFF,  0xE2,  0x44,  0xAF,  0xE7,  0x10,  0x3F,  0xCC,  0x10, 	/* 1C7F0 */
+	0xBA,  0x25,  0x42,  0x38,  0x57,  0xE4,  0xC2,  0xFB,  0xC2,  0x24,  0xFB,  0xC2,  0x7E,  0xB5,  0x26,  0x7E, 	/* 1C800 */
+	0x3D,  0x2C,  0x7E,  0x81,  0x26,  0xA2,  0x52,  0x56,  0xA4,  0xFE,  0xFA,  0x82,  0x2A,  0xF4,  0x62,  0x90, 	/* 1C810 */
+	0xB3,  0xC6,  0xE4,  0x31,  0x8C,  0x66,  0x84,  0x20,  0x82,  0x7E,  0x50,  0x84,  0xFF,  0xF0,  0x22,  0x7C, 	/* 1C820 */
+	0xF9,  0x02,  0x7F,  0xB7,  0xA6,  0xD6,  0x37,  0x2C,  0x06,  0x91,  0x27,  0x42,  0x47,  0x57,  0x44,  0xD8, 	/* 1C830 */
+	0xFF,  0x02,  0x47,  0xFF,  0x02,  0x00,  0xB3,  0xE6,  0xAA,  0x32,  0xAC,  0x7F,  0x92,  0xFA,  0x0A,  0x3E, 	/* 1C840 */
+	0xF4,  0x09,  0xFE,  0xF5,  0xAA,  0x7E,  0xFC,  0x00,  0xA0,  0x31,  0x8D,  0xF6,  0x0A,  0x07,  0xFC,  0x93, 	/* 1C850 */
+	0x20,  0x83,  0x3E,  0x4A,  0xA8,  0xFF,  0xF0,  0x02,  0xDC,  0xF1,  0x42,  0xDE,  0xB5,  0x26,  0x5E,  0x36, 	/* 1C860 */
+	0x0C,  0x9F,  0x9A,  0x22,  0x42,  0x7E,  0x52,  0x44,  0xFE,  0xF6,  0xC2,  0x92,  0xF7,  0xC2,  0x44,  0xB7, 	/* 1C870 */
+	0xC6,  0xC4,  0x37,  0xCC,  0xC2,  0x9B,  0x21,  0x02,  0x7E,  0x55,  0x44,  0xFE,  0xFD,  0x42,  0x7F,  0xF6, 	/* 1C880 */
+	0xA2,  0x7E,  0xB6,  0xA6,  0xBE,  0x3A,  0x4D,  0x42,  0x9E,  0x25,  0x42,  0xA8,  0x55,  0x48,  0xFE,  0xFA, 	/* 1C890 */
+	0xA2,  0x92,  0xFF,  0xE2,  0x5C,  0xB7,  0x46,  0xDC,  0x37,  0x2C,  0xDA,  0xA0,  0x29,  0x23,  0x54,  0x5B, 	/* 1C8A0 */
+	0xA8,  0xEC,  0xFB,  0xA2,  0xEE,  0xFB,  0xA2,  0x10,  0xB7,  0xE6,  0xB8,  0x35,  0x4C,  0x12,  0xA2,  0x21, 	/* 1C8B0 */
+	0xC2,  0x10,  0x57,  0xE4,  0xD0,  0xF7,  0xE2,  0x50,  0xFF,  0xE2,  0x6A,  0xB7,  0xE6,  0xD4,  0x35,  0x2C, 	/* 1C8C0 */
+	0xAE,  0xAA,  0x21,  0xC2,  0x10,  0x57,  0xE4,  0xD0,  0xF5,  0xE2,  0x6A,  0xFF,  0xE2,  0x6A,  0xB7,  0xE6, 	/* 1C8D0 */
+	0xAA,  0x3A,  0xAD,  0x7F,  0xB0,  0x21,  0x02,  0x28,  0x57,  0xC4,  0x83,  0xF7,  0xE2,  0x5A,  0xFF,  0xE2, 	/* 1C8E0 */
+	0x00,  0xBF,  0xE6,  0xAA,  0x3F,  0xEC,  0xAA,  0xB5,  0x22,  0x82,  0xFE,  0x52,  0x84,  0xEE,  0xFA,  0xA2, 	/* 1C8F0 */
+	0xFE,  0xF4,  0x42,  0x7E,  0xB4,  0x86,  0xFE,  0x34,  0x8C,  0x7E,  0xB7,  0x27,  0xE2,  0x24,  0x53,  0xC4, 	/* 1C900 */
+	0xA4,  0xF7,  0xC2,  0x04,  0xFF,  0xF2,  0xAA,  0xBE,  0xE6,  0xAA,  0x3F,  0xEC,  0x22,  0xBC,  0x20,  0x02, 	/* 1C910 */
+	0xFE,  0x5A,  0xA8,  0xFE,  0xF4,  0xA2,  0xBE,  0xF5,  0x42,  0xFE,  0xB5,  0x46,  0xDE,  0x37,  0x4C,  0x5E, 	/* 1C920 */
+	0xBD,  0x2A,  0x42,  0xFE,  0x52,  0x48,  0xFE,  0xF6,  0xC2,  0xB6,  0xF7,  0xC2,  0x44,  0xB7,  0xC6,  0xC4, 	/* 1C930 */
+	0x37,  0xCC,  0xC2,  0xBE,  0x46,  0x4B,  0xFA,  0x50,  0x4F,  0xFE,  0x2A,  0xC6,  0xF6,  0xA4,  0x40,  0xA0, 	/* 1C940 */
+	0x31,  0x8F,  0xF6,  0x15,  0x07,  0xFC,  0xBF,  0xA9,  0xCF,  0xD4,  0x52,  0x6A,  0x80,  0xFF,  0xCA,  0x94, 	/* 1C950 */
+	0xFC,  0x80,  0xB4,  0x31,  0x8D,  0xF6,  0x15,  0x07,  0xFC,  0x81,  0x2E,  0xE2,  0xAA,  0x5E,  0xE8,  0xAA, 	/* 1C960 */
+	0xFF,  0xE2,  0x48,  0xFF,  0xC2,  0x48,  0xAF,  0xE7,  0x24,  0x39,  0x8C,  0x66,  0xB7,  0x00,  0x01,  0xF8, 	/* 1C970 */
+	0x10,  0x01,  0xF0,  0x10,  0x01,  0xF0,  0x10,  0x0F,  0xFE,  0x14,  0x81,  0x30,  0x1D,  0x87,  0x06,  0x80, 	/* 1C980 */
+	0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0x02,  0x80,  0x28,  0x02,  0x80,  0x28,  0x02,  0x80, 	/* 1C990 */
+	0x28,  0x06,  0x82,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0x02,  0x80,  0x29,  0xF2,  0x80, 	/* 1C9A0 */
+	0x28,  0x02,  0x80,  0x28,  0x06,  0x83,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0x42,  0x84, 	/* 1C9B0 */
+	0x28,  0x42,  0x8A,  0x2B,  0x1A,  0x80,  0x28,  0x06,  0x87,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFB, 	/* 1C9C0 */
+	0xE8,  0x02,  0xBF,  0xA8,  0x42,  0x86,  0x28,  0x52,  0x84,  0x28,  0x46,  0x89,  0xFB,  0xE8,  0xA2,  0xFB, 	/* 1C9D0 */
+	0xE8,  0xA2,  0xFB,  0xE8,  0x22,  0xBF,  0xA8,  0x62,  0x8A,  0x29,  0x22,  0xA6,  0x28,  0x06,  0x8A,  0xFB, 	/* 1C9E0 */
+	0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0x42,  0xA4,  0xAA,  0x4A,  0xA4,  0xAB,  0xFA,  0x80,  0x28, 	/* 1C9F0 */
+	0x06,  0x8B,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0x02,  0xBF,  0xA8,  0xA2,  0xBF,  0xA9, 	/* 1CA00 */
+	0x22,  0xA2,  0x28,  0x26,  0x8F,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0x02,  0xBF,  0xA8, 	/* 1CA10 */
+	0x42,  0x9F,  0x28,  0x42,  0xBF,  0xA8,  0x06,  0x91,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8, 	/* 1CA20 */
+	0x42,  0xBF,  0xA8,  0x42,  0x8E,  0x29,  0x52,  0xA4,  0xA8,  0x46,  0x93,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8, 	/* 1CA30 */
+	0xA2,  0xFB,  0xE8,  0x02,  0x9F,  0x29,  0x12,  0x9F,  0x29,  0x12,  0x9F,  0x28,  0x06,  0x94,  0xFB,  0xE8, 	/* 1CA40 */
+	0xA2,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0x42,  0xFF,  0xA9,  0x22,  0x8C,  0x29,  0x22,  0xA1,  0x28,  0x06, 	/* 1CA50 */
+	0x96,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0x4A,  0xBD,  0x28,  0xE2,  0x95,  0x2A,  0x4A, 	/* 1CA60 */
+	0x8C,  0x28,  0x06,  0x98,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFB,  0xE9,  0xF2,  0x95,  0x29,  0xF2, 	/* 1CA70 */
+	0x95,  0x29,  0xF2,  0x84,  0x28,  0x46,  0x99,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0x42, 	/* 1CA80 */
+	0xFF,  0xE8,  0x42,  0xBF,  0xAA,  0x4A,  0xA7,  0x28,  0x46,  0xA0,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2, 	/* 1CA90 */
+	0xFB,  0xE8,  0x02,  0x9F,  0x28,  0x42,  0x9F,  0x28,  0x52,  0xBF,  0xA8,  0x06,  0xA2,  0xFB,  0xE8,  0xA2, 	/* 1CAA0 */
+	0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xBF,  0xA8,  0x42,  0xBF,  0xA8,  0xA2,  0x91,  0x2A,  0x06,  0xA3, 	/* 1CAB0 */
+	0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFF,  0xE9,  0x22,  0xAC,  0x29,  0x22,  0xBF,  0x2D,  0x2A,  0x9E, 	/* 1CAC0 */
+	0x28,  0x06,  0xA4,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFF,  0xE8,  0xA2,  0x9F,  0x2A,  0x0A,  0xDF, 	/* 1CAD0 */
+	0x69,  0x12,  0x9F,  0x28,  0x06,  0xA5,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFB,  0xE9,  0x42,  0x95, 	/* 1CAE0 */
+	0x29,  0xFA,  0xB5,  0x29,  0x22,  0x95,  0xA9,  0x0A,  0xA7,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFB, 	/* 1CAF0 */
+	0xE8,  0xA2,  0xBF,  0xA8,  0xA2,  0xBF,  0xE8,  0x92,  0xB0,  0xA8,  0x06,  0xA8,  0xFB,  0xE8,  0xA2,  0xFB, 	/* 1CB00 */
+	0xE8,  0xA2,  0xFF,  0xE8,  0x42,  0xBF,  0xA8,  0x42,  0x9F,  0x28,  0x42,  0xBF,  0xA8,  0x06,  0xAD,  0xFB, 	/* 1CB10 */
+	0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFB,  0xE9,  0xF2,  0x91,  0x29,  0xF2,  0x88,  0x29,  0xF2,  0x91,  0x29, 	/* 1CB20 */
+	0xF6,  0xB2,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0x9F,  0x29,  0x12,  0x9F,  0x28, 	/* 1CB30 */
+	0xA2,  0x93,  0xAA,  0x06,  0xB9,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0x42,  0xBF,  0xA8, 	/* 1CB40 */
+	0xA2,  0xBF,  0x2D,  0x5A,  0x9F,  0x68,  0x3E,  0xBB,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8, 	/* 1CB50 */
+	0xE2,  0x94,  0x2B,  0xB2,  0x91,  0x29,  0xB2,  0x91,  0x29,  0xF6,  0xBC,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8, 	/* 1CB60 */
+	0xA2,  0xFB,  0xE9,  0x12,  0xFA,  0xAA,  0x46,  0xBB,  0x2A,  0x8A,  0xCF,  0x29,  0x8E,  0xBE,  0xFB,  0xE8, 	/* 1CB70 */
+	0xA2,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0x22,  0xFF,  0xAB,  0xAA,  0xAA,  0xAB,  0x92,  0xF3,  0xA8,  0x4A, 	/* 1CB80 */
+	0x83,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFF,  0xE9,  0x12,  0x9F,  0x29,  0xF2,  0x85,  0x2B,  0xFA, 	/* 1CB90 */
+	0x8A,  0x2B,  0x1E,  0x87,  0xFB,  0xE8,  0xA2,  0xFB,  0xEF,  0xBE,  0x84,  0x2B,  0xFA,  0x8A,  0x2F,  0xFE, 	/* 1CBA0 */
+	0x91,  0x29,  0xF2,  0x91,  0x29,  0xF6,  0x8A,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFB,  0xEA,  0xF2, 	/* 1CBB0 */
+	0xD2,  0x2A,  0xFA,  0x82,  0x2A,  0xFA,  0xA8,  0xAC,  0xFA,  0x8C,  0xFB,  0xE8,  0xA2,  0xFB,  0xEF,  0xBE, 	/* 1CBC0 */
+	0x84,  0x2B,  0xFA,  0x95,  0x29,  0xF2,  0x95,  0x29,  0xF2,  0x95,  0x2A,  0x4A,  0x8D,  0xFB,  0xE8,  0xA2, 	/* 1CBD0 */
+	0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0x52,  0x9F,  0x2B,  0xFA,  0x89,  0x29,  0xF2,  0xA9,  0x28,  0xF6,  0x94, 	/* 1CBE0 */
+	0xFB,  0xE8,  0xA2,  0xFB,  0xEF,  0xBE,  0x84,  0x29,  0xE2,  0x85,  0x2B,  0xFA,  0x80,  0xAB,  0xFA,  0xAA, 	/* 1CBF0 */
+	0xAF,  0xFE,  0x95,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFB,  0xEA,  0x92,  0xFD,  0xEA,  0xAA,  0xAE, 	/* 1CC00 */
+	0xAB,  0x92,  0x92,  0xAA,  0x46,  0x96,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFB,  0xE9,  0xFA,  0x94, 	/* 1CC10 */
+	0x29,  0xF2,  0x94,  0x29,  0xFA,  0xAA,  0xAC,  0x36,  0x98,  0xFB,  0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFB, 	/* 1CC20 */
+	0xEB,  0xCA,  0xA7,  0xEB,  0xCA,  0xA6,  0xA9,  0xAA,  0xBD,  0xA8,  0x06,  0x9C,  0xFB,  0xEF,  0xBE,  0x8A, 	/* 1CC30 */
+	0x2F,  0xBE,  0x91,  0x2A,  0xAA,  0x91,  0x6F,  0xFE,  0xAA,  0xAB,  0xBA,  0x8A,  0x29,  0x26,  0xA1,  0xFB, 	/* 1CC40 */
+	0xE8,  0xA2,  0xFB,  0xE8,  0xA2,  0xFB,  0xEA,  0xAA,  0xBF,  0xA9,  0x52,  0x9F,  0x29,  0x52,  0xBF,  0xA8, 	/* 1CC50 */
+	0x46,  0xA2,  0xFB,  0xEF,  0xBE,  0x8A,  0x2F,  0xBE,  0x81,  0x2B,  0xBA,  0xAA,  0xAB,  0x92,  0xA7,  0xAB, 	/* 1CC60 */
+	0x92,  0xEF,  0xAB,  0x96,  0xA5,  0xFB,  0xEF,  0xBE,  0x8A,  0x2F,  0xFE,  0x82,  0x2C,  0xFA,  0xA5,  0x28, 	/* 1CC70 */
+	0xFA,  0xE2,  0x2A,  0xFA,  0xB2,  0x2C,  0xFA,  0x9C,  0x04,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x03, 	/* 1CC80 */
+	0xFC,  0x20,  0x43,  0xFC,  0x04,  0x0F,  0xFE,  0x04,  0x00,  0x40,  0xA1,  0x00,  0xCE,  0xF0,  0xA1,  0x0A, 	/* 1CC90 */
+	0x10,  0xC1,  0x0A,  0xFE,  0x91,  0x09,  0x10,  0xE1,  0x08,  0x10,  0x81,  0x08,  0x10,  0xA8,  0x00,  0x0E, 	/* 1CCA0 */
+	0xFE,  0xA8,  0x0A,  0xBC,  0xCA,  0x4A,  0xA4,  0xAA,  0x4A,  0xAC,  0xEA,  0x09,  0x22,  0x92,  0x2A,  0x1E, 	/* 1CCB0 */
+	0xAA,  0x00,  0x0E,  0xFE,  0xA8,  0x0A,  0x80,  0xCF,  0xCA,  0xA4,  0x9A,  0x49,  0x98,  0xE8,  0x88,  0x98, 	/* 1CCC0 */
+	0x92,  0x4A,  0xC2,  0xAE,  0x00,  0x0E,  0x7C,  0xA0,  0x0A,  0x00,  0xCF,  0xEA,  0x28,  0x92,  0x89,  0x28, 	/* 1CCD0 */
+	0xE2,  0x88,  0x48,  0x88,  0xA9,  0x06,  0xAF,  0x02,  0x0E,  0x20,  0xA2,  0x0A,  0x20,  0xCA,  0x0A,  0xBC, 	/* 1CCE0 */
+	0xAA,  0x0A,  0xA0,  0xEA,  0x08,  0xA0,  0x8A,  0x0B,  0xFE,  0xB2,  0x02,  0x0E,  0x20,  0xBF,  0xEA,  0x20, 	/* 1CCF0 */
+	0xC2,  0x0A,  0x3C,  0x92,  0x49,  0x44,  0xE4,  0x48,  0x84,  0x90,  0x4A,  0x18,  0xBB,  0x00,  0x0E,  0x7C, 	/* 1CD00 */
+	0xA4,  0x4A,  0x44,  0xC7,  0xCA,  0x44,  0x94,  0x49,  0x7C,  0x94,  0x4E,  0x44,  0x84,  0x48,  0xFE,  0xBF, 	/* 1CD10 */
+	0x00,  0x0F,  0xFE,  0xA0,  0x4A,  0xF4,  0xC9,  0x4A,  0x94,  0xA9,  0x4A,  0xF4,  0xC8,  0x48,  0x04,  0x80, 	/* 1CD20 */
+	0x48,  0x0C,  0x80,  0x01,  0x0E,  0x10,  0xAF,  0xEA,  0x82,  0xC8,  0x2A,  0x40,  0x94,  0xC9,  0x70,  0xE4, 	/* 1CD30 */
+	0x08,  0x42,  0x84,  0x28,  0x3E,  0x82,  0x01,  0x0E,  0x10,  0xAF,  0xEA,  0x94,  0xC9,  0x0A,  0xBC,  0xA8, 	/* 1CD40 */
+	0x4A,  0xA8,  0xE9,  0x89,  0x18,  0x92,  0x4A,  0xC2,  0x84,  0x04,  0x4E,  0x44,  0xA4,  0x4A,  0xBE,  0xC8, 	/* 1CD50 */
+	0x4B,  0xA4,  0xA9,  0x4A,  0x94,  0xA8,  0x4C,  0x84,  0x88,  0x48,  0x8C,  0x8B,  0x00,  0x0E,  0x7E,  0xA0, 	/* 1CD60 */
+	0x8A,  0xBE,  0xCA,  0xAA,  0xAA,  0xAB,  0x6A,  0xA2,  0xEA,  0x28,  0xA6,  0x88,  0x08,  0xFE,  0x8C,  0x00, 	/* 1CD70 */
+	0x0E,  0xFE,  0xA1,  0x0A,  0x20,  0xE7,  0xC9,  0x44,  0x94,  0x49,  0x7C,  0xE4,  0x48,  0x44,  0x84,  0x48, 	/* 1CD80 */
+	0x7C,  0x8D,  0x02,  0x0E,  0x3C,  0xA6,  0x4A,  0x98,  0xC3,  0x4A,  0xCB,  0x90,  0x89,  0x7C,  0x94,  0x8E, 	/* 1CD90 */
+	0xFE,  0x80,  0x88,  0x08,  0x8F,  0x02,  0x0E,  0x20,  0xBF,  0xEA,  0x20,  0xC7,  0xCA,  0x44,  0xAF,  0xCB, 	/* 1CDA0 */
+	0x44,  0xE7,  0xC8,  0x44,  0x84,  0x48,  0x4C,  0x90,  0x00,  0x0E,  0xF8,  0xA8,  0x8A,  0xF8,  0xC8,  0x8A, 	/* 1CDB0 */
+	0x88,  0x9F,  0x89,  0xA4,  0xE9,  0x88,  0xA8,  0x8C,  0x4B,  0x02,  0x9B,  0xE9,  0x0A,  0x96,  0xAF,  0xCC, 	/* 1CDC0 */
+	0x90,  0xA9,  0x2B,  0xCE,  0xA2,  0x0A,  0x20,  0xCF,  0xC8,  0x20,  0x82,  0x09,  0xFE,  0x9C,  0x01,  0x0E, 	/* 1CDD0 */
+	0x10,  0xAF,  0xEA,  0x54,  0xC5,  0x4A,  0x54,  0xAB,  0x4A,  0x9A,  0xF1,  0x28,  0x28,  0x84,  0x49,  0x82, 	/* 1CDE0 */
+	0x9D,  0x01,  0x0E,  0x10,  0xBF,  0xEA,  0x10,  0xCD,  0xCA,  0x54,  0xA5,  0x4A,  0xBA,  0xF1,  0x28,  0x28, 	/* 1CDF0 */
+	0x84,  0x49,  0x82,  0x9E,  0xE1,  0x0A,  0xE8,  0xA4,  0x8D,  0xFE,  0xA4,  0x8A,  0x88,  0xB2,  0x8A,  0x20, 	/* 1CE00 */
+	0xDF,  0xC8,  0x20,  0x82,  0x0B,  0xFE,  0x9F,  0x01,  0x0E,  0x10,  0xA5,  0xCA,  0x50,  0xDF,  0xEA,  0x10, 	/* 1CE10 */
+	0xA5,  0x4A,  0x56,  0xEB,  0xA9,  0x10,  0x86,  0x09,  0x80,  0xA2,  0xE1,  0x0B,  0xFE,  0xB0,  0x2D,  0xFA, 	/* 1CE20 */
+	0xA0,  0x0B,  0xFE,  0xA2,  0x8A,  0x28,  0xC4,  0x88,  0x4A,  0x88,  0xA9,  0x06,  0xA3,  0x01,  0x0E,  0xFE, 	/* 1CE30 */
+	0xA1,  0x0A,  0xFE,  0xC9,  0x2A,  0xFE,  0xA9,  0x2A,  0xFE,  0xE1,  0x09,  0xFF,  0x81,  0x08,  0x10,  0xA4, 	/* 1CE40 */
+	0x02,  0x0E,  0x30,  0xA4,  0x8A,  0x84,  0xDF,  0xAA,  0x20,  0x9F,  0xE9,  0x20,  0xEA,  0x88,  0xA4,  0x92, 	/* 1CE50 */
+	0x28,  0x60,  0xA5,  0x02,  0x0E,  0x3C,  0xA4,  0x4A,  0x88,  0xC1,  0x0A,  0xBE,  0xAA,  0x2A,  0xA2,  0xAB, 	/* 1CE60 */
+	0xEC,  0xA2,  0x8A,  0x28,  0xBE,  0xA6,  0x02,  0x0F,  0xFE,  0xA2,  0x0A,  0xFC,  0xC2,  0x0B,  0xFE,  0xA4, 	/* 1CE70 */
+	0x8B,  0xFE,  0xEC,  0x88,  0xA8,  0x90,  0x88,  0x18,  0xAA,  0xE2,  0x0A,  0x20,  0xBF,  0xCC,  0x88,  0xA5, 	/* 1CE80 */
+	0x0B,  0xFE,  0xA0,  0x0A,  0xFC,  0xC8,  0x48,  0x84,  0x88,  0x48,  0xFC,  0xAC,  0x00,  0x0F,  0xFE,  0xAA, 	/* 1CE90 */
+	0x0A,  0xBE,  0xCE,  0x2A,  0xAA,  0xAE,  0xAA,  0xA4,  0xEA,  0x48,  0xEA,  0x93,  0x28,  0x20,  0xB0,  0x02, 	/* 1CEA0 */
+	0x0E,  0x30,  0xA4,  0x8A,  0xFC,  0xD0,  0x2A,  0xFC,  0xA1,  0x0B,  0xFE,  0xA2,  0x8C,  0x4C,  0x9F,  0x48, 	/* 1CEB0 */
+	0x04,  0xB2,  0xE1,  0x8A,  0xE0,  0xA2,  0x0F,  0xFC,  0xCA,  0x8A,  0xA8,  0xBF,  0xEA,  0xA8,  0xFF,  0xC8, 	/* 1CEC0 */
+	0x20,  0x82,  0x0B,  0xFE,  0xB3,  0x02,  0x0F,  0xFE,  0xA2,  0x0B,  0xFC,  0xD2,  0x4B,  0xFC,  0xB2,  0x4B, 	/* 1CED0 */
+	0xFC,  0xE7,  0x08,  0xA8,  0xB2,  0x68,  0x20,  0xB5,  0xE1,  0x0A,  0xFC,  0xC1,  0x09,  0xFE,  0xC2,  0x8A, 	/* 1CEE0 */
+	0xCE,  0xA2,  0x0A,  0x3C,  0xAC,  0x4C,  0x38,  0x86,  0x89,  0x86,  0xB6,  0x04,  0x0E,  0x40,  0xAF,  0xEA, 	/* 1CEF0 */
+	0x82,  0xDF,  0xAA,  0xA2,  0xBF,  0xAA,  0x22,  0xAA,  0xAE,  0xFA,  0x88,  0x28,  0x0C,  0xB7,  0x02,  0x0E, 	/* 1CF00 */
+	0x3E,  0xA2,  0x2A,  0x42,  0xC8,  0xCA,  0x10,  0x96,  0xE9,  0x42,  0xE6,  0xE8,  0x42,  0x84,  0x28,  0x7E, 	/* 1CF10 */
+	0xB8,  0x01,  0x0E,  0xFC,  0xA1,  0x0B,  0xFE,  0xC2,  0x8A,  0x48,  0xB8,  0xEA,  0x10,  0xCF,  0xC8,  0x10, 	/* 1CF20 */
+	0x81,  0x09,  0xFE,  0xBA,  0xE2,  0x0A,  0x50,  0xA8,  0x8B,  0xF6,  0xC2,  0x0B,  0xFC,  0xB2,  0x4B,  0xFC, 	/* 1CF30 */
+	0xC2,  0x08,  0x50,  0x88,  0x89,  0x04,  0xBD,  0x00,  0x0E,  0x7C,  0xA4,  0x4A,  0x7C,  0xC4,  0x4B,  0xFF, 	/* 1CF40 */
+	0xA4,  0x0A,  0xFE,  0xB2,  0xAE,  0xD2,  0x82,  0x28,  0xCC,  0x85,  0x00,  0x0E,  0xFC,  0xAA,  0x4A,  0xFC, 	/* 1CF50 */
+	0xCA,  0x4A,  0xFC,  0xA2,  0x0B,  0xFE,  0xB2,  0xAD,  0x3A,  0x9C,  0xA9,  0x06,  0x86,  0x04,  0x0E,  0x7C, 	/* 1CF60 */
+	0xAC,  0x8B,  0x30,  0xCC,  0x8B,  0x16,  0xA9,  0x0A,  0xFC,  0xE9,  0x09,  0x7C,  0x81,  0x08,  0xFE,  0x88, 	/* 1CF70 */
+	0x00,  0x0E,  0xFC,  0xAA,  0x4A,  0xFC,  0xCA,  0x4A,  0xFC,  0xA0,  0x0B,  0xFE,  0xAA,  0x4C,  0x98,  0x8A, 	/* 1CF80 */
+	0x49,  0xC2,  0x8A,  0x04,  0x4E,  0x28,  0xAF,  0xEA,  0x20,  0xC6,  0x4B,  0xB4,  0xA5,  0x8B,  0xB8,  0xC5, 	/* 1CF90 */
+	0x49,  0x92,  0x81,  0x08,  0x60,  0x8B,  0x02,  0x0E,  0xFE,  0xA2,  0x0A,  0x7C,  0xC9,  0x0B,  0x7E,  0x94, 	/* 1CFA0 */
+	0x49,  0x7C,  0x94,  0x4E,  0x7C,  0x84,  0x48,  0x4C,  0x8D,  0x02,  0x0E,  0xFC,  0xA8,  0x4A,  0xFC,  0xC8, 	/* 1CFB0 */
+	0x4A,  0xFC,  0xA0,  0x0B,  0xFE,  0xE1,  0x08,  0xFC,  0x81,  0x09,  0xFE,  0x8E,  0x09,  0x0E,  0x92,  0xAF, 	/* 1CFC0 */
+	0xCA,  0x90,  0xC9,  0x2A,  0xCE,  0xB2,  0x0A,  0xFC,  0xE8,  0x48,  0xFC,  0x88,  0x48,  0xFC,  0x8F,  0x02, 	/* 1CFD0 */
+	0x0E,  0x7C,  0xB2,  0x0A,  0xBC,  0xC2,  0x4B,  0xFC,  0xAE,  0x4A,  0xBC,  0xEA,  0x48,  0xAC,  0x94,  0x0A, 	/* 1CFE0 */
+	0x3E,  0x94,  0xEF,  0xEA,  0x00,  0xAF,  0xCC,  0x84,  0xAF,  0xCA,  0x00,  0xAF,  0xEA,  0xAA,  0xEC,  0xE8, 	/* 1CFF0 */
+	0xBA,  0x89,  0x28,  0x96,  0x95,  0xEF,  0xCA,  0x84,  0xAF,  0xCA,  0x00,  0xCF,  0xCA,  0x84,  0xAF,  0xCA, 	/* 1D000 */
+	0x84,  0xEF,  0xC8,  0x84,  0x8F,  0xC9,  0x86,  0x97,  0x02,  0x0E,  0x40,  0xAF,  0xCA,  0xA4,  0xCF,  0xCA, 	/* 1D010 */
+	0xA4,  0xAF,  0xCA,  0x54,  0xE5,  0xA8,  0x5E,  0x89,  0x19,  0x0F,  0x98,  0x07,  0x8E,  0x48,  0xA8,  0x4B, 	/* 1D020 */
+	0x7A,  0xC0,  0x0A,  0x78,  0xA4,  0x8A,  0x84,  0xFF,  0xEA,  0xB5,  0x8B,  0x49,  0xFE,  0x99,  0x01,  0x0E, 	/* 1D030 */
+	0x54,  0xA9,  0x2A,  0xFC,  0xC8,  0x4A,  0xFC,  0xA8,  0x4A,  0xFC,  0xC5,  0x48,  0x92,  0x91,  0x28,  0x30, 	/* 1D040 */
+	0x9B,  0x08,  0x0E,  0xFC,  0xAA,  0x4B,  0x58,  0xC9,  0x4A,  0xFA,  0xB0,  0x1B,  0xFC,  0xA2,  0x8E,  0xA4, 	/* 1D050 */
+	0x92,  0x28,  0x60,  0x9C,  0x02,  0x0E,  0xFC,  0xA4,  0x8B,  0xFE,  0xC8,  0x4A,  0xFC,  0xA8,  0x4A,  0xFC, 	/* 1D060 */
+	0xC2,  0x0B,  0xFE,  0x82,  0x08,  0x20,  0xA0,  0xE3,  0xCB,  0xE4,  0xAA,  0x8D,  0xFC,  0xC0,  0x4A,  0xFC, 	/* 1D070 */
+	0xA0,  0x4B,  0xFC,  0xC5,  0x49,  0x4A,  0xA4,  0x2A,  0x3E,  0xA3,  0x09,  0x2E,  0x54,  0xAF,  0xEA,  0x38, 	/* 1D080 */
+	0xC5,  0x4B,  0x92,  0xA4,  0x4A,  0x7E,  0xAB,  0x4F,  0x7E,  0x84,  0x49,  0x84,  0xA7,  0x13,  0xCE,  0xA4, 	/* 1D090 */
+	0xA4,  0x2B,  0x7E,  0xC9,  0x0A,  0x6A,  0xB9,  0xCA,  0xEC,  0xE9,  0xA8,  0xAA,  0x8D,  0x89,  0x3F,  0xA8, 	/* 1D0A0 */
+	0x09,  0x0E,  0x7E,  0xB1,  0x0A,  0x9E,  0xC2,  0x4B,  0xDE,  0xA9,  0x2A,  0x9E,  0xA9,  0x2C,  0x96,  0x94, 	/* 1D0B0 */
+	0x0A,  0x3F,  0xAA,  0x02,  0x0E,  0x50,  0xA8,  0x8B,  0x76,  0xC0,  0x0B,  0xDC,  0xB5,  0x4B,  0xDC,  0xE8, 	/* 1D0C0 */
+	0x88,  0x88,  0x95,  0x4A,  0x22,  0xB0,  0x00,  0x0E,  0xFC,  0xA8,  0x4A,  0xFC,  0xC8,  0x4A,  0xFC,  0xA4, 	/* 1D0D0 */
+	0x4A,  0xAA,  0xE4,  0x49,  0xEE,  0x8D,  0x49,  0x2A,  0xB1,  0x01,  0xCE,  0xE8,  0xAA,  0x4B,  0xFA,  0xC1, 	/* 1D0E0 */
+	0x0A,  0xFC,  0xBF,  0xEA,  0x04,  0xEF,  0xC9,  0x54,  0x95,  0x2A,  0x3C,  0xB2,  0x01,  0x0E,  0x54,  0xA9, 	/* 1D0F0 */
+	0xAA,  0x30,  0xC6,  0x0B,  0xFC,  0xA9,  0x0A,  0xFC,  0xE9,  0x08,  0xFE,  0x8A,  0xA9,  0x0C,  0xB4,  0x04, 	/* 1D100 */
+	0x8F,  0xFE,  0xAA,  0x8B,  0xFE,  0xC0,  0x2A,  0xEE,  0xAA,  0x8A,  0xEE,  0xEA,  0x88,  0xEE,  0x8A,  0x88, 	/* 1D110 */
+	0xAE,  0xB6,  0x04,  0x00,  0x40,  0x3F,  0x80,  0x48,  0xFF,  0xE0,  0x48,  0x3F,  0x84,  0x44,  0x2E,  0x83, 	/* 1D120 */
+	0x50,  0xC4,  0xC0,  0xC0,  0xB7,  0x20,  0x8F,  0xBE,  0x20,  0xAF,  0xFF,  0x00,  0xA7,  0x3E,  0xF8,  0x82, 	/* 1D130 */
+	0x2A,  0xA9,  0xCA,  0xAA,  0x24,  0x96,  0x18,  0xB8,  0x20,  0x8F,  0xBE,  0x20,  0xA7,  0x7F,  0xA8,  0xAF, 	/* 1D140 */
+	0x3E,  0x04,  0x9F,  0x2A,  0x21,  0xCA,  0xAA,  0xAC,  0x96,  0x08,  0xB9,  0x21,  0x02,  0x20,  0x3F,  0xE6, 	/* 1D150 */
+	0x20,  0x62,  0x0B,  0xFC,  0x22,  0x02,  0x20,  0x3F,  0xC2,  0x20,  0x22,  0x03,  0xFE,  0xBB,  0x11,  0x01, 	/* 1D160 */
+	0x20,  0x3F,  0xE6,  0x20,  0xBF,  0xC2,  0x20,  0x3F,  0xE0,  0x00,  0x7F,  0xC1,  0x88,  0x07,  0x07,  0x8E, 	/* 1D170 */
+	0xBC,  0x21,  0x02,  0x20,  0x3F,  0xE6,  0x20,  0xBF,  0xC2,  0x20,  0x3F,  0xE0,  0x20,  0xFF,  0xF0,  0x20, 	/* 1D180 */
+	0x02,  0x00,  0x20,  0x80,  0x04,  0x01,  0x50,  0x24,  0x8C,  0xD6,  0x06,  0x01,  0x90,  0xFF,  0xE2,  0x20, 	/* 1D190 */
+	0x3F,  0xC2,  0x20,  0x22,  0x03,  0xFE,  0x81,  0x00,  0x07,  0xFE,  0x4A,  0x44,  0xBE,  0x56,  0x85,  0x68, 	/* 1D1A0 */
+	0x73,  0xE5,  0x28,  0x53,  0xE9,  0x28,  0x92,  0x81,  0x3E,  0x84,  0x21,  0x42,  0x24,  0xFF,  0xE2,  0x68, 	/* 1D1B0 */
+	0x2A,  0x83,  0x3E,  0x32,  0x85,  0x28,  0x5B,  0xEA,  0x68,  0x3E,  0x8E,  0x3E,  0x85,  0x02,  0x4F,  0xA8, 	/* 1D1C0 */
+	0x57,  0xE5,  0x48,  0xFC,  0x81,  0x7C,  0x34,  0x83,  0x48,  0x57,  0xC9,  0x48,  0x14,  0x83,  0x7E,  0x86, 	/* 1D1D0 */
+	0x22,  0x03,  0xFC,  0x64,  0x0B,  0xF8,  0x24,  0x03,  0xF8,  0x24,  0x0F,  0xFE,  0x0E,  0x03,  0x58,  0xC4, 	/* 1D1E0 */
+	0x60,  0x40,  0x87,  0x00,  0x07,  0xFE,  0x00,  0x03,  0xFC,  0x20,  0x43,  0xFC,  0x28,  0x83,  0xFE,  0x69, 	/* 1D1F0 */
+	0x04,  0xFC,  0x49,  0x08,  0xFE,  0x89,  0x42,  0x44,  0x28,  0x77,  0xEA,  0xC8,  0xA4,  0x8F,  0xFC,  0x24, 	/* 1D200 */
+	0x82,  0x48,  0x37,  0xC4,  0xC8,  0x44,  0x88,  0x7E,  0x8B,  0x21,  0x02,  0x20,  0x3F,  0xE6,  0x20,  0xBF, 	/* 1D210 */
+	0x82,  0x20,  0x3F,  0xE0,  0x00,  0x7B,  0xC4,  0xA4,  0x4E,  0x44,  0x0C,  0x8C,  0x29,  0x22,  0x94,  0x2B, 	/* 1D220 */
+	0xE3,  0xE8,  0xAA,  0x8A,  0xBE,  0xAA,  0x8A,  0xA8,  0xAB,  0xEA,  0xE8,  0xB2,  0x8C,  0x3E,  0x8D,  0x04, 	/* 1D230 */
+	0x0F,  0xFE,  0x22,  0x42,  0x28,  0xC7,  0xE5,  0xC8,  0x27,  0xC4,  0xC8,  0xFF,  0xC1,  0x48,  0x24,  0x84, 	/* 1D240 */
+	0x7E,  0x8E,  0x01,  0x27,  0xA4,  0x4B,  0xE4,  0xE8,  0x7A,  0x84,  0xBE,  0x7A,  0x84,  0xA8,  0x4B,  0xE5, 	/* 1D250 */
+	0xE8,  0x62,  0x8C,  0x3E,  0x91,  0x42,  0x4F,  0x28,  0x57,  0xE5,  0x48,  0x9C,  0x82,  0x7C,  0xFC,  0x82, 	/* 1D260 */
+	0x48,  0x77,  0xCA,  0xC8,  0x24,  0x82,  0x7E,  0x95,  0xFA,  0x48,  0xA8,  0xAB,  0xEF,  0xE8,  0xAA,  0x8F, 	/* 1D270 */
+	0xBC,  0xAA,  0x8F,  0xA8,  0xDB,  0xCF,  0xA8,  0x8A,  0x89,  0xBE,  0x96,  0x79,  0x44,  0x94,  0x7B,  0xE2, 	/* 1D280 */
+	0x68,  0xFA,  0x8A,  0xBC,  0xAA,  0x8F,  0xA8,  0x33,  0xC2,  0xA8,  0x3A,  0x8C,  0x7E,  0x99,  0x25,  0x22, 	/* 1D290 */
+	0x94,  0x7F,  0xED,  0x28,  0x7B,  0xC5,  0x28,  0x7F,  0xE0,  0x00,  0x7F,  0xC1,  0x98,  0x06,  0x07,  0x9E, 	/* 1D2A0 */
+	0x9B,  0x41,  0x47,  0x94,  0x6B,  0xEB,  0xA8,  0x2E,  0x85,  0xBC,  0x42,  0x87,  0xA8,  0x6B,  0xCB,  0xA8, 	/* 1D2B0 */
+	0x2A,  0x85,  0xBE,  0x9C,  0x21,  0x42,  0x14,  0xFB,  0xE5,  0x68,  0x52,  0x8A,  0xBE,  0x22,  0x8F,  0xA8, 	/* 1D2C0 */
+	0x33,  0xE6,  0xA8,  0xA2,  0x82,  0x3E,  0xA2,  0x22,  0x4F,  0xE8,  0xDB,  0xEA,  0xE8,  0xDA,  0x8F,  0xBC, 	/* 1D2D0 */
+	0x22,  0x8F,  0xA8,  0xAB,  0xCD,  0xA8,  0xFA,  0x88,  0xBE,  0xA3,  0x51,  0x2F,  0xA4,  0x53,  0xEF,  0xE8, 	/* 1D2E0 */
+	0xAA,  0x8F,  0xBE,  0x22,  0x8F,  0xA8,  0x23,  0xEF,  0xE8,  0x4A,  0x88,  0x3E,  0xA8,  0x00,  0x07,  0xFE, 	/* 1D2F0 */
+	0x04,  0x00,  0x40,  0x7F,  0xE6,  0x52,  0x54,  0xA4,  0x42,  0x65,  0x25,  0x4A,  0x44,  0x24,  0x46,  0xAA, 	/* 1D300 */
+	0x7F,  0xC0,  0x40,  0xFF,  0xEB,  0x5A,  0x84,  0x2B,  0x5A,  0x00,  0x03,  0xF8,  0x00,  0x83,  0xF8,  0x00, 	/* 1D310 */
+	0x83,  0xF8,  0xAB,  0x3F,  0x80,  0x40,  0xFF,  0xE8,  0x42,  0xA5,  0x29,  0x4A,  0x00,  0x0F,  0xFE,  0x06, 	/* 1D320 */
+	0x00,  0x50,  0x04,  0x80,  0x40,  0xB0,  0x3F,  0xC0,  0x40,  0xFF,  0xEB,  0x5A,  0x84,  0x23,  0x58,  0x0A, 	/* 1D330 */
+	0x03,  0x18,  0xDF,  0x60,  0x90,  0x11,  0x02,  0x60,  0xB2,  0x7F,  0xC0,  0x40,  0xFF,  0xE8,  0x42,  0xB5, 	/* 1D340 */
+	0xA0,  0x40,  0x3F,  0x80,  0x00,  0xFF,  0xE0,  0x90,  0x13,  0x87,  0xC4,  0xB6,  0x7F,  0xC0,  0x40,  0xFF, 	/* 1D350 */
+	0xE8,  0x42,  0xB5,  0xA0,  0xA0,  0x3F,  0x8C,  0x06,  0x7F,  0x80,  0x48,  0x05,  0x80,  0x40,  0xB7,  0x7F, 	/* 1D360 */
+	0xC0,  0x40,  0xFF,  0xEB,  0x5A,  0x84,  0x2B,  0x5A,  0x04,  0x07,  0xFC,  0x44,  0x47,  0xFC,  0x44,  0x47, 	/* 1D370 */
+	0xFC,  0xB9,  0x7F,  0xC0,  0x40,  0xFF,  0xE8,  0x42,  0xB5,  0xA2,  0x40,  0x3F,  0xC3,  0xE4,  0x62,  0x4B, 	/* 1D380 */
+	0xE8,  0x20,  0x21,  0xFE,  0xBB,  0x7F,  0xC0,  0x40,  0xFF,  0xEA,  0x52,  0x94,  0xAF,  0xF8,  0x44,  0x87, 	/* 1D390 */
+	0xF8,  0x44,  0x87,  0xFA,  0x04,  0x20,  0x3E,  0x80,  0x7F,  0xC0,  0x40,  0xFF,  0xE8,  0x42,  0xB5,  0xA0, 	/* 1D3A0 */
+	0x00,  0xFF,  0xE1,  0x00,  0x7F,  0xC4,  0xA4,  0x4A,  0x44,  0xAC,  0x84,  0x7F,  0xC0,  0x40,  0xFF,  0xEA, 	/* 1D3B0 */
+	0x52,  0x94,  0xA3,  0xF8,  0x60,  0xCB,  0xFA,  0x20,  0x83,  0xF8,  0x20,  0x82,  0x18,  0x86,  0x7F,  0xC0, 	/* 1D3C0 */
+	0x40,  0xFF,  0xE9,  0x4A,  0x25,  0x2F,  0x78,  0x21,  0x07,  0xFE,  0xD1,  0x03,  0x7C,  0x2C,  0x0C,  0x3E, 	/* 1D3D0 */
+	0x87,  0x7F,  0xC0,  0x40,  0xFF,  0xE8,  0x42,  0xB5,  0xA0,  0x00,  0x7F,  0xE4,  0x00,  0x7F,  0xC5,  0x48, 	/* 1D3E0 */
+	0x53,  0x0B,  0x8C,  0x88,  0x7F,  0xC0,  0x40,  0xFF,  0xE8,  0x42,  0xB5,  0xA2,  0x20,  0x9F,  0xE4,  0x20, 	/* 1D3F0 */
+	0x0F,  0xC2,  0xA4,  0x4B,  0x88,  0x20,  0x8A,  0x7F,  0xC0,  0x40,  0xFF,  0xE8,  0x42,  0xB5,  0xA7,  0xFC, 	/* 1D400 */
+	0x00,  0x07,  0xFC,  0x0A,  0x02,  0xA8,  0x1B,  0x0F,  0xFE,  0x8D,  0x7F,  0xC0,  0x40,  0xFF,  0xE8,  0x42, 	/* 1D410 */
+	0xB5,  0xA8,  0x42,  0x12,  0x03,  0xFC,  0xE4,  0x03,  0xF8,  0x24,  0x03,  0xFE,  0x8E,  0x7F,  0xC0,  0x40, 	/* 1D420 */
+	0xFF,  0xE8,  0x42,  0xB5,  0xA0,  0x40,  0x7F,  0x81,  0x20,  0xFF,  0xE3,  0x10,  0x0E,  0x07,  0x18,  0x8F, 	/* 1D430 */
+	0x7F,  0xC0,  0x40,  0xFF,  0xE8,  0x42,  0xB5,  0xA0,  0xA0,  0x7B,  0xC0,  0xA0,  0x7B,  0xC0,  0xA0,  0xF3, 	/* 1D440 */
+	0xE2,  0x20,  0x91,  0x7F,  0xC0,  0x40,  0xFF,  0xE8,  0x42,  0xB5,  0xA2,  0x10,  0x91,  0xE4,  0x10,  0x07, 	/* 1D450 */
+	0xC2,  0x44,  0x44,  0x48,  0x7C,  0x93,  0x7F,  0xC0,  0x40,  0xFF,  0xE8,  0x42,  0xB5,  0xA2,  0x08,  0x3B, 	/* 1D460 */
+	0x82,  0x08,  0x3F,  0x80,  0xA2,  0x32,  0x2C,  0x1E,  0x96,  0x7F,  0xC0,  0x40,  0xFF,  0xE8,  0x42,  0xB5, 	/* 1D470 */
+	0xA2,  0x10,  0xFF,  0xC2,  0x10,  0x73,  0x86,  0xD4,  0xA1,  0x22,  0x10,  0x99,  0x7F,  0xC0,  0x40,  0xFF, 	/* 1D480 */
+	0xEA,  0x52,  0x14,  0x8F,  0xFE,  0x15,  0x03,  0xF8,  0x24,  0x8F,  0xFE,  0x1B,  0x0E,  0x0E,  0x9C,  0x7F, 	/* 1D490 */
+	0xC0,  0x40,  0xFF,  0xE8,  0x42,  0xB5,  0xA2,  0x7C,  0xFC,  0x42,  0x7C,  0x74,  0x46,  0xFC,  0xA4,  0x42, 	/* 1D4A0 */
+	0x7C,  0x9E,  0x7F,  0xC0,  0x40,  0xFF,  0xE8,  0x42,  0xB5,  0xA0,  0x00,  0x7B,  0xC4,  0x84,  0x7B,  0xC4, 	/* 1D4B0 */
+	0x14,  0x78,  0x84,  0x36,  0xA4,  0x7F,  0xC0,  0x40,  0xFF,  0xE8,  0x42,  0xB5,  0xA3,  0xBC,  0x51,  0x4F, 	/* 1D4C0 */
+	0xF4,  0x24,  0x83,  0xF8,  0x24,  0x83,  0xF8,  0xA7,  0x7F,  0xC0,  0x40,  0xFF,  0xEA,  0x52,  0x94,  0xA7, 	/* 1D4D0 */
+	0xBE,  0x4A,  0x83,  0x56,  0xF9,  0x03,  0x7C,  0x51,  0x49,  0x6C,  0xAA,  0x7F,  0xC0,  0x40,  0xFF,  0xE8, 	/* 1D4E0 */
+	0x42,  0xB5,  0xA4,  0x00,  0x2F,  0xE8,  0x54,  0x49,  0x22,  0xFE,  0x41,  0x08,  0xFE,  0xB0,  0x7F,  0xC0, 	/* 1D4F0 */
+	0x40,  0xFF,  0xE8,  0x42,  0xB5,  0xAF,  0xD0,  0x49,  0xEF,  0xE4,  0x4A,  0x47,  0x98,  0x49,  0x45,  0xA2, 	/* 1D500 */
+	0xB2,  0x7F,  0xC0,  0x40,  0xFF,  0xEA,  0x52,  0x94,  0xA7,  0x9C,  0x4A,  0x47,  0xD8,  0x3A,  0x4A,  0x7E, 	/* 1D510 */
+	0xBA,  0x4C,  0x3C,  0xB8,  0x7F,  0xC0,  0x40,  0xFF,  0xE8,  0x42,  0xB5,  0xA2,  0x9E,  0xFD,  0x22,  0x9E, 	/* 1D520 */
+	0x7D,  0x25,  0x5E,  0xFF,  0x21,  0x26,  0xB9,  0x7F,  0xC0,  0x40,  0xFF,  0xE8,  0x42,  0xB5,  0xA7,  0x88, 	/* 1D530 */
+	0x4F,  0xC7,  0xA8,  0x47,  0xE7,  0x90,  0xCF,  0xC7,  0x90,  0xBD,  0x7F,  0xC0,  0x40,  0xFF,  0xEB,  0x5A, 	/* 1D540 */
+	0x7F,  0xCF,  0xAE,  0x35,  0x85,  0x54,  0xBF,  0xA2,  0x08,  0x3F,  0x84,  0x08,  0xBE,  0x7F,  0xC0,  0x40, 	/* 1D550 */
+	0xFF,  0xEA,  0x52,  0x94,  0xA3,  0xFC,  0xD5,  0x47,  0x7C,  0x95,  0x43,  0x7C,  0xD1,  0x06,  0x7E,  0x82, 	/* 1D560 */
+	0x7F,  0xC0,  0x40,  0xFF,  0xE8,  0x42,  0xB5,  0xA3,  0xFC,  0x28,  0x83,  0xDE,  0x2A,  0xC5,  0xBA,  0x8A, 	/* 1D570 */
+	0x07,  0xFE,  0x84,  0x7F,  0xC0,  0x40,  0xFF,  0xEA,  0x52,  0x94,  0xA7,  0xBC,  0x02,  0x4F,  0xBE,  0x02, 	/* 1D580 */
+	0xA7,  0xDE,  0x48,  0x27,  0x8C,  0x86,  0xF8,  0x82,  0x3E,  0xFC,  0xAA,  0xBF,  0xAC,  0xA0,  0x3E,  0x7C, 	/* 1D590 */
+	0x80,  0x6A,  0xFD,  0xC5,  0x6A,  0x76,  0x8C,  0x9F,  0x88,  0x7F,  0xC0,  0x40,  0xFF,  0xE8,  0x42,  0xB5, 	/* 1D5A0 */
+	0xA0,  0x00,  0xEE,  0xEA,  0xAA,  0xFF,  0xE2,  0x48,  0x55,  0x4F,  0xFE,  0x89,  0xF8,  0x62,  0x7A,  0xFD, 	/* 1D5B0 */
+	0x4A,  0xFE,  0xAB,  0x60,  0x6A,  0xFB,  0xE0,  0x1C,  0xFE,  0x45,  0x18,  0x6A,  0x4C,  0xC2,  0x92,  0x04, 	/* 1D5C0 */
+	0x07,  0xFC,  0x04,  0x03,  0xF8,  0x04,  0x0F,  0xFE,  0x10,  0x81,  0xF8,  0x10,  0x81,  0xF8,  0x10,  0x81, 	/* 1D5D0 */
+	0x18,  0x96,  0x21,  0x02,  0x7E,  0xF9,  0x01,  0x7C,  0x91,  0x05,  0xFE,  0x54,  0x42,  0x7C,  0x3C,  0x4C, 	/* 1D5E0 */
+	0x7C,  0x04,  0x40,  0x4C,  0x99,  0x21,  0xCF,  0x94,  0x22,  0x87,  0xFE,  0x20,  0xAF,  0xFF,  0x48,  0xA7, 	/* 1D5F0 */
+	0x8A,  0x4B,  0xE7,  0x88,  0x48,  0x85,  0x98,  0x9C,  0x10,  0xCF,  0xF0,  0x15,  0x47,  0x92,  0x17,  0xCF, 	/* 1D600 */
+	0xD4,  0x57,  0xE5,  0x54,  0x7F,  0xC4,  0x50,  0x45,  0x04,  0xD0,  0x9E,  0x12,  0x01,  0x20,  0xF3,  0xE1, 	/* 1D610 */
+	0x20,  0x12,  0x0F,  0x3C,  0x12,  0x01,  0x20,  0xF3,  0xE1,  0x20,  0x22,  0x04,  0x20,  0xA0,  0x24,  0x03, 	/* 1D620 */
+	0xF8,  0x44,  0x0F,  0xFE,  0x20,  0x83,  0xF8,  0x0A,  0x0F,  0xBE,  0x0A,  0x0F,  0xBE,  0x12,  0x06,  0x20, 	/* 1D630 */
+	0xA1,  0x02,  0x07,  0xFE,  0x48,  0x87,  0xFE,  0x48,  0x86,  0xAA,  0x6A,  0xA5,  0xD0,  0x45,  0xE5,  0xD0, 	/* 1D640 */
+	0x85,  0xE1,  0x90,  0xA2,  0x00,  0x0F,  0xFE,  0x04,  0x00,  0x80,  0x7F,  0xE4,  0x92,  0x4F,  0x24,  0x92, 	/* 1D650 */
+	0x4F,  0x24,  0x92,  0x49,  0x27,  0xFE,  0xA4,  0x01,  0x0F,  0xD0,  0x21,  0xE4,  0x22,  0xFF,  0xAA,  0xAA, 	/* 1D660 */
+	0xBA,  0xAA,  0xBC,  0xBA,  0x0A,  0xA2,  0xAA,  0x2F,  0x9E,  0xA6,  0x00,  0x0F,  0xBC,  0x22,  0x44,  0x3C, 	/* 1D670 */
+	0xFA,  0x4A,  0xBC,  0xBA,  0x4A,  0xBC,  0xB9,  0x8A,  0x9A,  0xAA,  0xAF,  0xC6,  0xA8,  0x7F,  0xE5,  0x4C, 	/* 1D680 */
+	0x5F,  0xE5,  0x48,  0x9D,  0x41,  0x62,  0xFF,  0xE0,  0x80,  0x7F,  0xE4,  0xF2,  0x49,  0x27,  0xFE,  0xA9, 	/* 1D690 */
+	0x11,  0x0F,  0xFE,  0x11,  0x01,  0xF0,  0x04,  0x07,  0xFC,  0x44,  0x47,  0xFC,  0x04,  0x0F,  0xFE,  0x04, 	/* 1D6A0 */
+	0x00,  0x40,  0xAB,  0x50,  0x0F,  0xFE,  0x51,  0x27,  0x2A,  0x22,  0x4F,  0x94,  0xA9,  0x8F,  0x88,  0x21, 	/* 1D6B0 */
+	0x8F,  0xA4,  0x24,  0x42,  0x82,  0xAD,  0x50,  0x0F,  0xBE,  0x51,  0x27,  0x12,  0x21,  0x2F,  0xB2,  0xA9, 	/* 1D6C0 */
+	0xAF,  0x92,  0x21,  0x2F,  0xA2,  0x22,  0x22,  0x4C,  0xB1,  0x50,  0x0F,  0xFE,  0x51,  0x27,  0x12,  0x25, 	/* 1D6D0 */
+	0x2F,  0xB2,  0xA9,  0xAF,  0x96,  0x21,  0x2F,  0xA2,  0x24,  0x22,  0x8C,  0xB4,  0x52,  0x8F,  0xA8,  0x52, 	/* 1D6E0 */
+	0x87,  0x4A,  0x2A,  0xAF,  0xAC,  0xAA,  0x8F,  0xA8,  0x22,  0x8F,  0xAA,  0x22,  0xA2,  0x26,  0xB9,  0x53, 	/* 1D6F0 */
+	0x0F,  0x90,  0x51,  0x07,  0x7E,  0x25,  0x2F,  0xD2,  0xAD,  0x2F,  0xEA,  0x24,  0x6F,  0xC2,  0x24,  0x22, 	/* 1D700 */
+	0x46,  0xBA,  0x51,  0x0F,  0x90,  0x5F,  0xE7,  0x10,  0x21,  0x0F,  0xFC,  0xA9,  0x0F,  0xB8,  0x23,  0x8F, 	/* 1D710 */
+	0xD4,  0x29,  0x22,  0x10,  0xBC,  0x50,  0x0F,  0xBC,  0x52,  0x47,  0x24,  0x23,  0xCF,  0xA4,  0xAA,  0x4F, 	/* 1D720 */
+	0xA4,  0x23,  0xCF,  0xC0,  0x20,  0x02,  0x7E,  0x81,  0x51,  0x0F,  0x90,  0x57,  0xF7,  0x52,  0x25,  0x4F, 	/* 1D730 */
+	0xFE,  0xAC,  0x2F,  0xE4,  0x25,  0x4F,  0xC8,  0x29,  0x42,  0xA2,  0x84,  0x52,  0x0F,  0xA0,  0x53,  0xE7, 	/* 1D740 */
+	0x42,  0x2B,  0xAF,  0x8A,  0xA8,  0xAF,  0xBA,  0x22,  0xCF,  0xA0,  0x22,  0x22,  0x1E,  0x85,  0x50,  0x8F, 	/* 1D750 */
+	0x88,  0x50,  0x87,  0x3E,  0x22,  0xAF,  0xAA,  0xAF,  0xFF,  0x88,  0x21,  0x8F,  0x94,  0x22,  0x22,  0x41, 	/* 1D760 */
+	0x86,  0x50,  0x0F,  0xFE,  0x51,  0x07,  0x10,  0x27,  0xEF,  0xD2,  0xAD,  0x2F,  0xDA,  0x26,  0x6F,  0xC2, 	/* 1D770 */
+	0x24,  0x22,  0x46,  0x8B,  0x51,  0x0F,  0x90,  0x57,  0xC7,  0x10,  0x21,  0x0F,  0xFE,  0xA9,  0x0F,  0x90, 	/* 1D780 */
+	0x27,  0xCF,  0x90,  0x21,  0x02,  0xFE,  0x8D,  0x51,  0x0F,  0xFE,  0x5A,  0x27,  0x20,  0x2F,  0xFF,  0xA4, 	/* 1D790 */
+	0xAA,  0x4F,  0xA4,  0x26,  0x8F,  0x98,  0x22,  0x42,  0x42,  0x8F,  0x07,  0x8F,  0xC8,  0x26,  0x83,  0x5A, 	/* 1D7A0 */
+	0xC8,  0xE1,  0x10,  0xFF,  0xE1,  0x10,  0x3F,  0x82,  0x48,  0xFF,  0xE0,  0x40,  0x90,  0x51,  0x0F,  0x90, 	/* 1D7B0 */
+	0x51,  0xC7,  0x10,  0x27,  0xEF,  0x80,  0xAF,  0xEF,  0x98,  0x21,  0x4F,  0xD2,  0x21,  0x02,  0x10,  0x98, 	/* 1D7C0 */
+	0x54,  0xAF,  0xAA,  0x52,  0xC7,  0x08,  0x23,  0xEF,  0xA2,  0xAB,  0xEF,  0xA2,  0x23,  0xEF,  0xA2,  0x22, 	/* 1D7D0 */
+	0x22,  0x26,  0x9C,  0x51,  0x0F,  0x92,  0x57,  0x47,  0x38,  0x25,  0x4F,  0x92,  0xA9,  0x0F,  0xFC,  0x24, 	/* 1D7E0 */
+	0x4F,  0xFC,  0x24,  0x42,  0x7C,  0xA0,  0x52,  0x0F,  0xA0,  0x53,  0xE7,  0x52,  0x25,  0x6F,  0xBA,  0xAF, 	/* 1D7F0 */
+	0xEF,  0x92,  0x23,  0xAF,  0xD6,  0x21,  0x22,  0x0C,  0xA3,  0x53,  0xEF,  0x94,  0x50,  0x87,  0x7E,  0x21, 	/* 1D800 */
+	0xAF,  0xAC,  0xAC,  0x8F,  0xFE,  0x21,  0x8F,  0xB4,  0x25,  0x22,  0x10,  0xA6,  0x52,  0x8F,  0xC8,  0x54, 	/* 1D810 */
+	0xA7,  0xFA,  0x25,  0xCF,  0x58,  0xB6,  0x8F,  0xC8,  0x2C,  0xCF,  0x54,  0x26,  0x22,  0x41,  0xA8,  0x50, 	/* 1D820 */
+	0x0F,  0xFC,  0x54,  0x47,  0x7C,  0x24,  0x4F,  0xFC,  0xAA,  0x0F,  0xBE,  0x25,  0x2F,  0xEA,  0x27,  0xA2, 	/* 1D830 */
+	0x0C,  0xAB,  0x52,  0x0F,  0xA0,  0x53,  0xE7,  0x42,  0x2B,  0xAF,  0xFE,  0xA8,  0x2F,  0xBA,  0x23,  0xAF, 	/* 1D840 */
+	0xEA,  0x23,  0xA2,  0x0C,  0xAD,  0x50,  0x0F,  0xFE,  0x51,  0x07,  0x7E,  0x25,  0x2F,  0xFE,  0xAD,  0x2F, 	/* 1D850 */
+	0xFE,  0x21,  0x0F,  0xB0,  0x22,  0x82,  0xC6,  0xB3,  0x52,  0x8F,  0xFE,  0x52,  0x87,  0x10,  0x22,  0x8F, 	/* 1D860 */
+	0xC4,  0xAB,  0xAF,  0x81,  0x23,  0xCF,  0xA4,  0x22,  0x42,  0x3C,  0xB4,  0x52,  0x4F,  0xFE,  0x52,  0x47, 	/* 1D870 */
+	0x7E,  0x24,  0x0F,  0x7E,  0xB6,  0xAF,  0x7E,  0x2A,  0xAF,  0xBE,  0x32,  0xA2,  0x26,  0x83,  0x54,  0x8F, 	/* 1D880 */
+	0xBE,  0x50,  0x87,  0x7E,  0x22,  0x4F,  0xD8,  0xB7,  0xEF,  0x48,  0x27,  0xEF,  0x48,  0x2B,  0x03,  0x0F, 	/* 1D890 */
+	0x86,  0x53,  0xEF,  0x94,  0x53,  0xE7,  0xAA,  0x27,  0xEF,  0x1C,  0xBE,  0x6F,  0x5D,  0x25,  0x2F,  0x4E, 	/* 1D8A0 */
+	0x2A,  0x03,  0x1F,  0x88,  0x52,  0x4F,  0xFE,  0x52,  0x47,  0x7E,  0x25,  0xAF,  0xFE,  0xA8,  0x8F,  0xFE, 	/* 1D8B0 */
+	0x24,  0x8F,  0xEA,  0x25,  0x42,  0x8A,  0x8B,  0x04,  0x03,  0xF8,  0x04,  0x8F,  0xFE,  0x20,  0x83,  0xF8, 	/* 1D8C0 */
+	0x02,  0x03,  0xFC,  0x22,  0x0F,  0xFE,  0x02,  0x00,  0x20,  0x93,  0x20,  0x8F,  0xBE,  0x20,  0xAF,  0xFF, 	/* 1D8D0 */
+	0x8A,  0x2F,  0xBE,  0x88,  0x4F,  0xBE,  0x22,  0x4F,  0xFF,  0x20,  0x42,  0x04,  0x9C,  0x20,  0x6F,  0xB8, 	/* 1D8E0 */
+	0x2B,  0x4F,  0xD2,  0x49,  0x07,  0x88,  0x13,  0x6F,  0xA2,  0x53,  0x6F,  0xE2,  0x12,  0x21,  0x3E,  0xAD, 	/* 1D8F0 */
+	0x0A,  0x00,  0xA0,  0x7B,  0xC0,  0xA0,  0x0A,  0x07,  0xBC,  0x0A,  0x00,  0xA0,  0x7B,  0xC0,  0xA0,  0x0A, 	/* 1D900 */
+	0x0F,  0xFE,  0xAE,  0x11,  0x0F,  0xFE,  0x11,  0x00,  0x00,  0x0A,  0x07,  0xBC,  0x0A,  0x07,  0xBC,  0x0A, 	/* 1D910 */
+	0x07,  0xBC,  0x0A,  0x0F,  0xFE,  0xB2,  0x04,  0x0F,  0xFE,  0x0A,  0x4F,  0x58,  0x55,  0x4B,  0x5A,  0x0A, 	/* 1D920 */
+	0x07,  0xBC,  0x0A,  0x07,  0xBC,  0x0A,  0x0F,  0xFE,  0xB3,  0x04,  0x07,  0xFC,  0x11,  0x00,  0xA0,  0xFF, 	/* 1D930 */
+	0xE0,  0x00,  0x1F,  0x81,  0x08,  0x1F,  0x81,  0x08,  0x10,  0x81,  0xF8,  0xB5,  0x22,  0x02,  0x20,  0xFB, 	/* 1D940 */
+	0xE5,  0x22,  0x24,  0x2F,  0xB2,  0x00,  0x27,  0x8A,  0x4B,  0x27,  0xC2,  0x48,  0x27,  0x8C,  0xB6,  0x20, 	/* 1D950 */
+	0x02,  0x7E,  0xFD,  0x24,  0x92,  0x49,  0x2F,  0xEC,  0x04,  0x07,  0xBE,  0x4A,  0x27,  0xA2,  0x4A,  0x27, 	/* 1D960 */
+	0xBE,  0xBB,  0x23,  0xCF,  0xA4,  0x52,  0x45,  0x3E,  0xFA,  0x20,  0x3E,  0x7A,  0x24,  0xBE,  0x7A,  0x24, 	/* 1D970 */
+	0xBE,  0x79,  0x40,  0x62,  0xBF,  0x2E,  0xED,  0xAA,  0x6E,  0xCF,  0xCA,  0x2A,  0xA4,  0xDC,  0xFF,  0xE1, 	/* 1D980 */
+	0x10,  0xFF,  0xE3,  0xF8,  0x20,  0x83,  0xF8,  0x81,  0x00,  0x0F,  0xFE,  0x08,  0x03,  0xF8,  0x20,  0x83, 	/* 1D990 */
+	0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8,  0x10,  0xCE,  0x02,  0x82,  0x00,  0x0F,  0xFE,  0x22,  0x02, 	/* 1D9A0 */
+	0x7C,  0x24,  0x42,  0x7C,  0x24,  0x42,  0x7C,  0x24,  0x42,  0x7C,  0x22,  0x46,  0xC2,  0x83,  0x00,  0x09, 	/* 1D9B0 */
+	0xFE,  0x81,  0x09,  0xFC,  0xE4,  0x48,  0x7C,  0x84,  0x49,  0x7C,  0x94,  0x47,  0x7C,  0x06,  0x41,  0x82, 	/* 1D9C0 */
+	0x85,  0x00,  0x00,  0xFE,  0xFA,  0x02,  0x7C,  0x24,  0x42,  0x7C,  0x24,  0x42,  0xFC,  0x34,  0x4C,  0x7C, 	/* 1D9D0 */
+	0x06,  0x41,  0x82,  0x86,  0x88,  0x08,  0xFF,  0xA9,  0x0A,  0xBE,  0xAA,  0x2A,  0xBE,  0xAA,  0x2A,  0xBE, 	/* 1D9E0 */
+	0xAA,  0x2A,  0xBE,  0x89,  0x28,  0xE1,  0x88,  0x20,  0x02,  0xFE,  0x42,  0x09,  0x7C,  0x14,  0x42,  0x7C, 	/* 1D9F0 */
+	0x44,  0x49,  0x7C,  0x14,  0x42,  0x7C,  0x42,  0x48,  0xC2,  0x8C,  0x00,  0x07,  0x7E,  0x11,  0x05,  0x7C, 	/* 1DA00 */
+	0x4C,  0x4A,  0x7C,  0xA4,  0x43,  0x7C,  0x54,  0x45,  0xFC,  0xEA,  0x40,  0xC2,  0x8F,  0x20,  0x02,  0xFE, 	/* 1DA10 */
+	0xFA,  0x00,  0x7C,  0x74,  0x45,  0x7C,  0x54,  0x45,  0x7C,  0x54,  0x45,  0xFC,  0x86,  0x41,  0x82,  0x90, 	/* 1DA20 */
+	0x00,  0x0F,  0xFF,  0x11,  0x05,  0x3E,  0x22,  0x2F,  0xBE,  0x2A,  0x23,  0x3E,  0x22,  0x22,  0x3E,  0x21, 	/* 1DA30 */
+	0x26,  0x61,  0x91,  0x00,  0x00,  0x7E,  0xF9,  0x00,  0x3E,  0x02,  0x2F,  0xFE,  0x52,  0x25,  0x7E,  0x52, 	/* 1DA40 */
+	0x25,  0xBE,  0x51,  0x48,  0x62,  0x92,  0x10,  0x05,  0x3E,  0x49,  0x04,  0xBE,  0x86,  0x2F,  0xBE,  0x2A, 	/* 1DA50 */
+	0x22,  0xBE,  0x2A,  0x24,  0xBE,  0x49,  0x4B,  0x62,  0x93,  0x20,  0x02,  0x7E,  0xF9,  0x02,  0x3E,  0xAA, 	/* 1DA60 */
+	0x2A,  0xBE,  0xFA,  0x2A,  0x3E,  0x2A,  0x23,  0x3E,  0x21,  0x40,  0x62,  0x97,  0x10,  0x07,  0xFE,  0x55, 	/* 1DA70 */
+	0x05,  0xBE,  0x52,  0x27,  0xFE,  0x46,  0x26,  0x7E,  0x5A,  0x25,  0xBE,  0xA5,  0x4C,  0x62,  0x98,  0x20, 	/* 1DA80 */
+	0x03,  0x7E,  0x29,  0x04,  0x7E,  0x7A,  0x28,  0x3E,  0xFA,  0x22,  0xBE,  0x2A,  0x23,  0xBE,  0x21,  0x42, 	/* 1DA90 */
+	0x62,  0x9A,  0x00,  0x0F,  0xBE,  0x09,  0x05,  0x3E,  0x32,  0x24,  0xBE,  0xA2,  0x27,  0xBE,  0x22,  0x22, 	/* 1DAA0 */
+	0xBE,  0x31,  0x4C,  0x62,  0xA1,  0x20,  0x02,  0x7E,  0xFD,  0x02,  0x3C,  0x22,  0x4F,  0xBC,  0x02,  0x47, 	/* 1DAB0 */
+	0xBC,  0x4A,  0x44,  0xBC,  0x79,  0x40,  0x62,  0xA4,  0x00,  0x0F,  0xFE,  0x91,  0x09,  0x3E,  0xBA,  0x2A, 	/* 1DAC0 */
+	0xBE,  0xAA,  0x2B,  0xBE,  0x92,  0x29,  0x3E,  0xFD,  0x40,  0x62,  0xAC,  0x20,  0x02,  0x7E,  0xF9,  0x02, 	/* 1DAD0 */
+	0xFE,  0xB4,  0x26,  0x7E,  0xFC,  0x22,  0x7E,  0x34,  0x24,  0xFE,  0x42,  0x48,  0xC2,  0xAD,  0x00,  0x0F, 	/* 1DAE0 */
+	0xFE,  0x01,  0x07,  0xBE,  0x4A,  0x24,  0xBE,  0x7A,  0x28,  0xBE,  0x4A,  0x25,  0x3E,  0x19,  0x4E,  0x62, 	/* 1DAF0 */
+	0xB4,  0x80,  0x0F,  0xBE,  0x81,  0x07,  0xBE,  0x02,  0x27,  0xBE,  0x02,  0x2F,  0xBE,  0x22,  0x2A,  0xBE, 	/* 1DB00 */
+	0xA9,  0x42,  0x62,  0xB7,  0x20,  0x03,  0x7E,  0x4A,  0x0B,  0x7C,  0x04,  0x4F,  0x7C,  0x14,  0x42,  0x7C, 	/* 1DB10 */
+	0x7C,  0x44,  0xFC,  0x4A,  0x47,  0xC2,  0xB8,  0x07,  0xEF,  0xC8,  0x55,  0x0A,  0xBE,  0xAA,  0x25,  0x7E, 	/* 1DB20 */
+	0xFA,  0x22,  0x3E,  0x22,  0x23,  0xBE,  0xE2,  0x40,  0x42,  0xBB,  0x10,  0x05,  0x3E,  0x5D,  0x05,  0x3E, 	/* 1DB30 */
+	0xFE,  0x22,  0x3E,  0xAA,  0x2A,  0x7E,  0xAA,  0x21,  0x3E,  0x21,  0x4C,  0x62,  0xBC,  0x20,  0x02,  0x7F, 	/* 1DB40 */
+	0xF9,  0x02,  0x3E,  0xFA,  0x2A,  0xBE,  0xAA,  0x2F,  0xBE,  0x32,  0x26,  0xBE,  0xA3,  0x22,  0xC1,  0xBD, 	/* 1DB50 */
+	0x18,  0x0E,  0x7E,  0x21,  0x0F,  0xBC,  0x32,  0x46,  0xBC,  0xA6,  0x47,  0x3C,  0x56,  0x45,  0xBC,  0x51, 	/* 1DB60 */
+	0x48,  0x62,  0x86,  0x00,  0x0F,  0xFE,  0xA9,  0x0F,  0xBE,  0xAA,  0x2F,  0xBE,  0x22,  0x2F,  0xFE,  0x32, 	/* 1DB70 */
+	0x26,  0xBE,  0xA1,  0x42,  0x62,  0x8B,  0x00,  0x0F,  0xFE,  0xA9,  0x0F,  0xBE,  0xAA,  0x2A,  0xBE,  0xFA, 	/* 1DB80 */
+	0x22,  0x3E,  0xAA,  0x2A,  0xBE,  0xA5,  0x41,  0xE2,  0x8C,  0x7F,  0xE4,  0x90,  0x7B,  0xE4,  0xA2,  0x7B, 	/* 1DB90 */
+	0xE0,  0x22,  0xFF,  0xE1,  0x22,  0x5F,  0xE7,  0x14,  0x5E,  0x28,  0x3F,  0x8D,  0x10,  0x0F,  0xFE,  0x85, 	/* 1DBA0 */
+	0x07,  0xBE,  0x4A,  0x25,  0x3E,  0xB2,  0x24,  0xBE,  0xFE,  0x24,  0xBE,  0x49,  0x47,  0xA2,  0x8E,  0x00, 	/* 1DBB0 */
+	0x0F,  0xFE,  0xA9,  0x0F,  0xBE,  0x02,  0x27,  0xBE,  0x02,  0x2F,  0xFE,  0x22,  0x27,  0xBE,  0x09,  0x23, 	/* 1DBC0 */
+	0x61,  0x8F,  0x20,  0x0F,  0xFF,  0x49,  0x03,  0x3E,  0xCA,  0x27,  0xFE,  0x52,  0x26,  0xBE,  0x52,  0x2E, 	/* 1DBD0 */
+	0x7E,  0x99,  0x26,  0x21,  0x94,  0x10,  0x0F,  0xFE,  0x49,  0x03,  0x3E,  0x7E,  0x24,  0xBE,  0x72,  0x24, 	/* 1DBE0 */
+	0xBE,  0x72,  0x28,  0xBE,  0x91,  0x46,  0x62,  0x95,  0x00,  0x0F,  0xBE,  0x89,  0x0F,  0xBE,  0x8A,  0x2F, 	/* 1DBF0 */
+	0xBE,  0x52,  0x2D,  0x7E,  0xDA,  0x25,  0x3E,  0x59,  0x4E,  0x62,  0x98,  0x00,  0x07,  0xFF,  0x48,  0x87, 	/* 1DC00 */
+	0xDE,  0x65,  0x27,  0xDE,  0x65,  0x27,  0xDE,  0x59,  0x27,  0x5E,  0x51,  0xAB,  0x61,  0x9B,  0x20,  0x0F, 	/* 1DC10 */
+	0xBE,  0x21,  0x07,  0xBE,  0x4A,  0x27,  0xBE,  0x4A,  0x27,  0xBE,  0x4A,  0x2F,  0xFE,  0x51,  0x48,  0xA2, 	/* 1DC20 */
+	0x9E,  0x28,  0x0A,  0xFE,  0x71,  0x0F,  0xFE,  0x32,  0x26,  0xBE,  0xAA,  0x22,  0x3E,  0xFE,  0x22,  0x3E, 	/* 1DC30 */
+	0x51,  0x48,  0xA2,  0xA7,  0x00,  0x0F,  0xBE,  0x00,  0x8F,  0xFE,  0x86,  0x2F,  0xFE,  0xAA,  0x2B,  0xFE, 	/* 1DC40 */
+	0xEA,  0x2B,  0xFE,  0xA9,  0x43,  0xE2,  0xAB,  0x20,  0x0F,  0xFE,  0x89,  0x0B,  0xBE,  0xAA,  0x2F,  0xBE, 	/* 1DC50 */
+	0x4A,  0x27,  0xBE,  0x4A,  0x27,  0xBE,  0x01,  0x4F,  0xE2,  0xAF,  0x00,  0x0F,  0xFE,  0x89,  0x0F,  0xBE, 	/* 1DC60 */
+	0x8A,  0x2F,  0xBE,  0x52,  0x2A,  0xBE,  0x52,  0x2F,  0xBE,  0x69,  0x4A,  0xA2,  0xB0,  0x5B,  0xE5,  0x10, 	/* 1DC70 */
+	0xFF,  0xC6,  0x24,  0xAB,  0xC3,  0x62,  0xFF,  0x82,  0x48,  0x3F,  0x82,  0x48,  0xFF,  0xE0,  0x20,  0xB1, 	/* 1DC80 */
+	0x38,  0x02,  0x3F,  0xFD,  0x0A,  0x3E,  0xBA,  0x2A,  0xBE,  0xBA,  0x2A,  0xBE,  0xFE,  0x2A,  0xBE,  0x29, 	/* 1DC90 */
+	0x2F,  0xE1,  0xB3,  0x7C,  0x02,  0xBE,  0x38,  0x82,  0x9E,  0xFD,  0x20,  0x9E,  0xFF,  0x25,  0x5E,  0x7D, 	/* 1DCA0 */
+	0x25,  0x5E,  0xFD,  0x42,  0x62,  0xB4,  0x50,  0x0F,  0xFF,  0x51,  0x0F,  0xBE,  0xAA,  0x2F,  0xBE,  0x52, 	/* 1DCB0 */
+	0x27,  0xFE,  0xD2,  0x27,  0xBE,  0x51,  0x27,  0xE1,  0xA8,  0x00,  0x07,  0xF8,  0x46,  0x85,  0x88,  0x7E, 	/* 1DCC0 */
+	0x86,  0xA8,  0x6A,  0x87,  0xE8,  0x48,  0xA4,  0xAA,  0x4F,  0x6B,  0x12,  0xAA,  0xFF,  0xC0,  0x80,  0x0F, 	/* 1DCD0 */
+	0x80,  0x80,  0x7F,  0x84,  0x88,  0x7E,  0x86,  0xA8,  0x7E,  0x84,  0xAA,  0x4F,  0x6B,  0x8A,  0xAF,  0x20, 	/* 1DCE0 */
+	0x02,  0x7C,  0xFC,  0xC1,  0x74,  0x95,  0x45,  0x7C,  0x55,  0x42,  0x7C,  0x35,  0x4C,  0x9D,  0x11,  0xB2, 	/* 1DCF0 */
+	0x65,  0xB1,  0x00,  0x87,  0xC8,  0x4D,  0x47,  0x7E,  0x54,  0x17,  0xDE,  0x55,  0x27,  0xD2,  0x55,  0xE5, 	/* 1DD00 */
+	0x20,  0x5D,  0x9B,  0x47,  0xB6,  0x01,  0xE7,  0xD2,  0x4D,  0xE7,  0x52,  0x55,  0xE7,  0xD2,  0x57,  0xF7, 	/* 1DD10 */
+	0xCC,  0x55,  0x25,  0x20,  0x5D,  0x9B,  0x47,  0x83,  0x03,  0xEF,  0x94,  0x9B,  0xEE,  0xAA,  0xAB,  0xEF, 	/* 1DD20 */
+	0x80,  0xAB,  0xEF,  0x88,  0xAA,  0xAA,  0x4A,  0xBB,  0x1E,  0x8F,  0x84,  0x00,  0x0F,  0xFE,  0x52,  0x6F, 	/* 1DD30 */
+	0xBA,  0xAA,  0xAF,  0xBE,  0x02,  0xAF,  0xBE,  0x72,  0xAA,  0xCE,  0xA4,  0xE6,  0xB1,  0x86,  0x14,  0x07, 	/* 1DD40 */
+	0xFE,  0x12,  0x62,  0xBA,  0x46,  0xA4,  0xBE,  0x4A,  0xAF,  0xFE,  0x4A,  0xA4,  0xCA,  0xB4,  0xF8,  0xB5, 	/* 1DD50 */
+	0x9B,  0x00,  0x07,  0xF2,  0x19,  0xCE,  0x94,  0x29,  0x22,  0x8E,  0xFF,  0x42,  0x98,  0x49,  0x44,  0x92, 	/* 1DD60 */
+	0x88,  0xA0,  0x86,  0x9C,  0x18,  0x0E,  0x7C,  0x23,  0x6F,  0xD4,  0x75,  0x4A,  0xD2,  0x27,  0xCF,  0xD6, 	/* 1DD70 */
+	0xAD,  0x4F,  0xD6,  0xAD,  0x4F,  0x92,  0x9F,  0x04,  0x00,  0xA0,  0x15,  0x03,  0xF8,  0xD0,  0xE1,  0xF8, 	/* 1DD80 */
+	0x10,  0x81,  0xF8,  0x14,  0x41,  0x28,  0x1D,  0x87,  0x06,  0xA2,  0x20,  0x03,  0x38,  0x4A,  0x8B,  0x68, 	/* 1DD90 */
+	0x4A,  0x87,  0xA8,  0x4A,  0x87,  0xA8,  0x52,  0x84,  0xAA,  0x54,  0xAE,  0x86,  0xA9,  0x21,  0x03,  0x10, 	/* 1DDA0 */
+	0x49,  0xEB,  0x70,  0x79,  0x44,  0xD4,  0x7D,  0x44,  0x7C,  0x79,  0x04,  0x12,  0x7D,  0x24,  0x0E,  0xAB, 	/* 1DDB0 */
+	0x20,  0xC3,  0x70,  0x49,  0x0B,  0x10,  0x79,  0x04,  0xFE,  0x79,  0x04,  0x10,  0x7A,  0x84,  0x28,  0x7C, 	/* 1DDC0 */
+	0x44,  0x82,  0xAD,  0x21,  0x03,  0x10,  0x4B,  0xEB,  0x50,  0x49,  0x07,  0xFE,  0x49,  0x27,  0x92,  0x42, 	/* 1DDD0 */
+	0x27,  0xA2,  0x44,  0x2F,  0x8C,  0xAE,  0x21,  0x03,  0x10,  0x49,  0xEB,  0xEA,  0x4A,  0xC7,  0xC8,  0x48, 	/* 1DDE0 */
+	0x87,  0x88,  0x41,  0x47,  0x94,  0x42,  0x27,  0xC1,  0xAF,  0x20,  0x03,  0x3E,  0x4A,  0x0B,  0x20,  0x4B, 	/* 1DDF0 */
+	0xE7,  0xA2,  0x4A,  0x47,  0xB4,  0x52,  0x84,  0xCC,  0x55,  0x2E,  0xA1,  0xB2,  0x21,  0x03,  0x10,  0x4D, 	/* 1DE00 */
+	0x0B,  0x1F,  0x4A,  0xA7,  0xAA,  0x4C,  0x87,  0x88,  0x51,  0x44,  0x94,  0x56,  0x2E,  0xC1,  0xB4,  0x21, 	/* 1DE10 */
+	0x03,  0x10,  0x49,  0x0B,  0x58,  0x4A,  0x47,  0xBC,  0x4E,  0x27,  0xBC,  0x52,  0x44,  0xA4,  0x56,  0x4E, 	/* 1DE20 */
+	0x3C,  0xBC,  0x20,  0x03,  0x7E,  0x48,  0x2B,  0x3E,  0x48,  0x27,  0xBA,  0x4A,  0xA7,  0xAA,  0x52,  0xA4, 	/* 1DE30 */
+	0xBA,  0x54,  0x2E,  0x06,  0xBD,  0x22,  0x03,  0x20,  0x4B,  0xEB,  0xC2,  0x4B,  0xA7,  0x8A,  0x48,  0xA7, 	/* 1DE40 */
+	0xBA,  0x52,  0x44,  0xA0,  0x56,  0x2E,  0x1E,  0xBE,  0x22,  0x03,  0x20,  0x4B,  0xEB,  0x48,  0x4B,  0xE7, 	/* 1DE50 */
+	0xAA,  0x4A,  0xA7,  0xAA,  0x52,  0xA4,  0xAE,  0x54,  0x8E,  0x08,  0x83,  0x21,  0x03,  0x10,  0x4F,  0xEB, 	/* 1DE60 */
+	0x28,  0x7C,  0x44,  0xAA,  0x7A,  0x84,  0x10,  0x79,  0x04,  0x28,  0x7C,  0x44,  0x82,  0x85,  0x24,  0x43, 	/* 1DE70 */
+	0x24,  0x4A,  0x8B,  0x7E,  0x4A,  0x47,  0xA4,  0x4F,  0xF7,  0xA4,  0x52,  0x44,  0xA4,  0x54,  0x4E,  0x84, 	/* 1DE80 */
+	0x89,  0x21,  0x03,  0x10,  0x4A,  0x0B,  0x7E,  0x74,  0x25,  0x7A,  0x76,  0xA4,  0x6A,  0x7F,  0xA4,  0x42, 	/* 1DE90 */
+	0x7C,  0x24,  0x46,  0x8A,  0x11,  0x0F,  0xFE,  0x04,  0x07,  0xFC,  0x15,  0x02,  0x48,  0xDF,  0x61,  0x10, 	/* 1DEA0 */
+	0x1F,  0x41,  0x48,  0x13,  0x07,  0xCC,  0x8C,  0x20,  0x03,  0x7E,  0x4A,  0x4B,  0x3C,  0x4A,  0x47,  0xA4, 	/* 1DEB0 */
+	0x4B,  0xC7,  0xA4,  0x52,  0x44,  0xBE,  0x56,  0x4E,  0x04,  0x90,  0x3B,  0xC2,  0x24,  0x79,  0x8D,  0x27, 	/* 1DEC0 */
+	0x26,  0x0D,  0x98,  0x3F,  0xCD,  0x0B,  0x1F,  0x81,  0x4C,  0x13,  0x07,  0x8E,  0x92,  0x20,  0x63,  0x38, 	/* 1DED0 */
+	0x48,  0xCB,  0x2A,  0x7A,  0xA4,  0xC8,  0x79,  0x04,  0x7E,  0x7A,  0x44,  0x74,  0x79,  0x84,  0x64,  0x93, 	/* 1DEE0 */
+	0x22,  0x83,  0x4C,  0x4C,  0xAF,  0x48,  0x5F,  0xE7,  0x48,  0x56,  0xA7,  0xCA,  0x44,  0x45,  0x4C,  0x5D, 	/* 1DEF0 */
+	0x6E,  0xC2,  0x94,  0x20,  0xC3,  0x0A,  0x4B,  0xFB,  0x48,  0x7B,  0xE4,  0xAA,  0x7B,  0xE4,  0x2A,  0x7B, 	/* 1DF00 */
+	0xE4,  0x2A,  0x7A,  0xA4,  0x26,  0x98,  0x21,  0x03,  0x18,  0x4A,  0x4B,  0x42,  0x7B,  0xC4,  0x90,  0x7F, 	/* 1DF10 */
+	0xE4,  0x10,  0x75,  0x84,  0x54,  0x79,  0x24,  0x30,  0x9D,  0x22,  0x43,  0x7E,  0x4A,  0x4B,  0x88,  0x78, 	/* 1DF20 */
+	0x84,  0xFE,  0x79,  0x04,  0x1C,  0x79,  0x44,  0x24,  0x7C,  0x44,  0x98,  0x9E,  0x22,  0x83,  0x2E,  0x4F, 	/* 1DF30 */
+	0x4B,  0x08,  0x79,  0x64,  0xE2,  0x7A,  0x84,  0x1E,  0x77,  0x44,  0x08,  0x79,  0x64,  0x62,  0xA0,  0x22, 	/* 1DF40 */
+	0x43,  0x24,  0x4C,  0x8B,  0x7E,  0x7A,  0x44,  0xA4,  0x7B,  0x44,  0x6F,  0x7A,  0x44,  0x24,  0x7C,  0x44, 	/* 1DF50 */
+	0x84,  0xA1,  0x21,  0x03,  0x1E,  0x49,  0x2B,  0x12,  0x7A,  0x24,  0xCC,  0x79,  0x04,  0x66,  0x74,  0x24, 	/* 1DF60 */
+	0x76,  0x7C,  0x24,  0x7E,  0xA4,  0x20,  0x83,  0x2A,  0x4A,  0xCB,  0x48,  0x79,  0x44,  0xE2,  0x78,  0x84, 	/* 1DF70 */
+	0x2A,  0x7A,  0xC4,  0x48,  0x79,  0x44,  0x62,  0xA8,  0x21,  0x02,  0x7E,  0x54,  0x27,  0xBC,  0xCE,  0x47, 	/* 1DF80 */
+	0xA4,  0x4B,  0xC7,  0xA0,  0x53,  0xE4,  0xA2,  0x56,  0x2E,  0x3E,  0xAC,  0x20,  0x03,  0x2E,  0x4A,  0xAB, 	/* 1DF90 */
+	0x7A,  0x7A,  0xE4,  0xAA,  0x7F,  0xA4,  0x5E,  0x75,  0xA4,  0x7A,  0x79,  0x24,  0x26,  0xAE,  0x7C,  0x82, 	/* 1DFA0 */
+	0xB4,  0xD8,  0xB1,  0x34,  0xE5,  0x80,  0xA0,  0x35,  0x8D,  0xFE,  0x11,  0x01,  0xF4,  0x13,  0x87,  0x8E, 	/* 1DFB0 */
+	0xBD,  0x21,  0x03,  0x20,  0x4F,  0xCB,  0x54,  0x7F,  0xC4,  0xD4,  0x7F,  0xC4,  0x28,  0x7A,  0xA4,  0x2E, 	/* 1DFC0 */
+	0x7C,  0x84,  0x86,  0xBE,  0x22,  0x03,  0x7E,  0x48,  0xAB,  0x8A,  0x7A,  0xA4,  0xF2,  0x7A,  0xC4,  0x3E, 	/* 1DFD0 */
+	0x7A,  0xA4,  0x3E,  0x7E,  0xA4,  0x3E,  0x82,  0x20,  0x03,  0x3E,  0x4A,  0xAB,  0x36,  0x7A,  0x24,  0xBE, 	/* 1DFE0 */
+	0x78,  0x04,  0x3E,  0x7A,  0xA4,  0x2A,  0x7A,  0xA4,  0x7F,  0x85,  0x27,  0xC3,  0x44,  0x4F,  0xCB,  0x44, 	/* 1DFF0 */
+	0x7F,  0xE4,  0xAA,  0x7F,  0xE4,  0x00,  0x7F,  0xC4,  0x24,  0x79,  0x84,  0x66,  0x89,  0x22,  0x83,  0x7E, 	/* 1E000 */
+	0x4A,  0x8B,  0x38,  0x78,  0x04,  0xFC,  0x7D,  0x44,  0x7E,  0x79,  0x04,  0x7C,  0x79,  0x04,  0xFE,  0x8B, 	/* 1E010 */
+	0x21,  0x03,  0x7C,  0x4D,  0x4B,  0x7C,  0x79,  0x04,  0xFE,  0x7C,  0x44,  0x7C,  0x74,  0x44,  0x7C,  0x7A, 	/* 1E020 */
+	0x44,  0x42,  0x8C,  0x27,  0xE3,  0x5A,  0x4F,  0xEB,  0x48,  0x7C,  0xA4,  0xB6,  0x79,  0x44,  0x7E,  0x79, 	/* 1E030 */
+	0x44,  0x7F,  0x7A,  0x44,  0x42,  0x90,  0x21,  0x03,  0x7E,  0x49,  0x0B,  0x7E,  0x7C,  0x24,  0xBC,  0x78, 	/* 1E040 */
+	0x04,  0x3C,  0x7A,  0x44,  0x3C,  0x7A,  0x84,  0xFE,  0x91,  0x22,  0x43,  0x48,  0x4F,  0xCB,  0x5A,  0x7F, 	/* 1E050 */
+	0xE4,  0x94,  0x7F,  0xE4,  0x54,  0x75,  0x84,  0xAA,  0x79,  0x64,  0x62,  0x92,  0x21,  0x03,  0x7C,  0x49, 	/* 1E060 */
+	0x0B,  0x34,  0x7F,  0xE4,  0xA4,  0x7F,  0xE4,  0x00,  0x7F,  0xE4,  0x28,  0x7A,  0xA4,  0x46,  0x95,  0x79, 	/* 1E070 */
+	0xC4,  0x90,  0xFF,  0xE7,  0x2C,  0x15,  0xA6,  0xAE,  0x35,  0x8D,  0xF6,  0x11,  0x01,  0xF4,  0x13,  0x87, 	/* 1E080 */
+	0x8E,  0x97,  0x2E,  0xED,  0xAA,  0x6E,  0xCF,  0xCA,  0x2A,  0xA5,  0xDC,  0x06,  0x83,  0xF8,  0xD1,  0x61, 	/* 1E090 */
+	0xF0,  0x12,  0x83,  0x9C,  0x96,  0x21,  0x01,  0x20,  0xFF,  0xE0,  0x80,  0x3F,  0x82,  0x08,  0x3F,  0x82, 	/* 1E0A0 */
+	0x08,  0x3F,  0x82,  0x08,  0x20,  0x83,  0xF8,  0x97,  0x24,  0x22,  0x24,  0x27,  0xEF,  0x90,  0x2B,  0xE2, 	/* 1E0B0 */
+	0xA2,  0x2B,  0xE2,  0xBE,  0x2A,  0x24,  0xBE,  0x48,  0x18,  0x7F,  0x98,  0x51,  0x02,  0x14,  0xFF,  0xE4, 	/* 1E0C0 */
+	0x08,  0xF7,  0xA9,  0x5A,  0xF7,  0xA9,  0x0A,  0xF3,  0x49,  0xCD,  0x91,  0x3F,  0x21,  0x99,  0x01,  0xC3, 	/* 1E0D0 */
+	0xE0,  0x04,  0x0F,  0xFE,  0x0E,  0x03,  0x58,  0xC4,  0x63,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xF8, 	/* 1E0E0 */
+	0xA5,  0x1A,  0x07,  0x3E,  0x16,  0x4F,  0xBC,  0x32,  0x45,  0xBC,  0x91,  0x07,  0x9C,  0x4A,  0x47,  0xD8, 	/* 1E0F0 */
+	0x49,  0x47,  0xE2,  0xA8,  0x7D,  0xC1,  0x14,  0xFF,  0x25,  0x5C,  0x7D,  0x49,  0xE8,  0x85,  0x6F,  0xFE, 	/* 1E100 */
+	0x14,  0x83,  0xFC,  0xD0,  0xA1,  0xF8,  0xAC,  0x00,  0x03,  0xFE,  0x22,  0x03,  0xFC,  0x22,  0x03,  0xFC, 	/* 1E110 */
+	0x22,  0x03,  0xFE,  0x00,  0x25,  0x52,  0x54,  0x28,  0x1C,  0xAD,  0x00,  0x0F,  0xFC,  0xA2,  0x4F,  0x24, 	/* 1E120 */
+	0xA2,  0x4F,  0x14,  0xA1,  0x8F,  0x88,  0x09,  0x8A,  0x94,  0x8A,  0x23,  0x41,  0xAE,  0x00,  0x08,  0xFE, 	/* 1E130 */
+	0x49,  0x04,  0xFC,  0x09,  0x00,  0xFC,  0x29,  0x04,  0xFE,  0x41,  0x29,  0x4A,  0x92,  0x22,  0x0C,  0xB3, 	/* 1E140 */
+	0x00,  0x8F,  0xA8,  0xA2,  0xEF,  0xBA,  0xA6,  0xAF,  0xAA,  0xA2,  0xAF,  0xAE,  0x0A,  0x8A,  0xA0,  0x8A, 	/* 1E150 */
+	0x23,  0x1E,  0xB4,  0xFA,  0xAA,  0x2A,  0xF2,  0xAA,  0x2A,  0xF2,  0xAA,  0x2A,  0xFA,  0xA0,  0xAA,  0xAA, 	/* 1E160 */
+	0xAA,  0xAA,  0x8C,  0xA3,  0x42,  0xBC,  0x01,  0x0F,  0x90,  0xAF,  0xEF,  0x24,  0xA2,  0x4F,  0x28,  0xA1, 	/* 1E170 */
+	0x8F,  0x90,  0x09,  0x8A,  0xA8,  0x8C,  0x43,  0x02,  0x81,  0x04,  0x4F,  0xE8,  0xA1,  0x0F,  0x2C,  0xA4, 	/* 1E180 */
+	0x2F,  0x24,  0xA2,  0x4F,  0x98,  0x08,  0x8A,  0x94,  0x8A,  0x43,  0x42,  0x84,  0x01,  0x0F,  0x90,  0xA1, 	/* 1E190 */
+	0x0F,  0xFE,  0xA1,  0x0F,  0x10,  0xA2,  0x8F,  0xA8,  0x0A,  0x8A,  0xA4,  0x95,  0x46,  0x82,  0x85,  0x00, 	/* 1E1A0 */
+	0x0F,  0xBE,  0xA2,  0x2F,  0x22,  0xA3,  0xEF,  0x28,  0xA2,  0x8F,  0xA8,  0x0A,  0x4A,  0xA4,  0x8A,  0x23, 	/* 1E1B0 */
+	0x41,  0x86,  0x00,  0x0F,  0xFE,  0xA4,  0x4F,  0x44,  0xA5,  0x4F,  0x48,  0xA4,  0x8F,  0xD4,  0x0D,  0x2A, 	/* 1E1C0 */
+	0xE0,  0x8C,  0x03,  0x7E,  0x88,  0x00,  0x4F,  0x88,  0xA3,  0x0F,  0x20,  0xA3,  0xEF,  0x24,  0xA2,  0x4F, 	/* 1E1D0 */
+	0xA4,  0x0A,  0x4A,  0xA4,  0x8A,  0x43,  0x7F,  0x90,  0x02,  0x0F,  0x90,  0xAF,  0xEF,  0x10,  0xA1,  0x0F, 	/* 1E1E0 */
+	0x10,  0xA7,  0xCF,  0x90,  0x09,  0x0A,  0x90,  0x89,  0x03,  0x7E,  0x91,  0x20,  0x0F,  0xFE,  0x49,  0x27, 	/* 1E1F0 */
+	0x0C,  0x2B,  0x4D,  0xFA,  0x12,  0x01,  0xF8,  0x12,  0x01,  0xFE,  0x52,  0xA8,  0x8C,  0x92,  0x02,  0x0F, 	/* 1E200 */
+	0xA0,  0xA3,  0xEF,  0x42,  0xA7,  0xAF,  0xAA,  0xA2,  0xAF,  0xAA,  0x0B,  0xAA,  0x82,  0x88,  0x23,  0x0C, 	/* 1E210 */
+	0x95,  0x20,  0x0F,  0xBE,  0x2A,  0x24,  0xBE,  0x98,  0x03,  0xFC,  0x24,  0x03,  0xF8,  0x24,  0x03,  0xFE, 	/* 1E220 */
+	0x4A,  0xA9,  0x0C,  0x98,  0x01,  0x0F,  0x90,  0xA2,  0x8F,  0x24,  0xA4,  0xEF,  0xF2,  0xA0,  0x2F,  0xBC, 	/* 1E230 */
+	0x0A,  0x4A,  0xA4,  0x8A,  0x43,  0x3C,  0x9B,  0x01,  0x0F,  0x90,  0xA7,  0xCF,  0x54,  0xA5,  0x4F,  0x54, 	/* 1E240 */
+	0xA7,  0xCF,  0xD0,  0x0B,  0x0A,  0xA8,  0x8C,  0x63,  0x81,  0x9D,  0x01,  0x0F,  0x90,  0xAF,  0xEF,  0x82, 	/* 1E250 */
+	0xA2,  0x2F,  0x20,  0xA2,  0x6F,  0xB8,  0x0A,  0x0A,  0xA0,  0x8A,  0x23,  0x1E,  0x9F,  0x00,  0x0F,  0xFE, 	/* 1E260 */
+	0xA5,  0xAF,  0x5A,  0xA5,  0xAF,  0x5A,  0xA6,  0xAF,  0xCE,  0x0C,  0x2A,  0xC2,  0x8F,  0xE3,  0x00,  0xA2, 	/* 1E270 */
+	0x02,  0x2F,  0x94,  0xA7,  0xEF,  0x14,  0xA1,  0x4F,  0x14,  0xA7,  0xFF,  0x94,  0x09,  0x4A,  0xA4,  0x8A, 	/* 1E280 */
+	0x43,  0x44,  0xAD,  0x01,  0x0F,  0x90,  0xAF,  0xEF,  0x10,  0xA1,  0x4F,  0x64,  0xA1,  0x8F,  0x92,  0x0A, 	/* 1E290 */
+	0x4A,  0x88,  0x89,  0x43,  0x62,  0xAE,  0x01,  0x0F,  0x90,  0xAF,  0xEF,  0x28,  0xA2,  0x4F,  0x4A,  0xAA, 	/* 1E2A0 */
+	0x8F,  0xA8,  0x09,  0x0A,  0x98,  0x8A,  0x43,  0x42,  0xB1,  0x01,  0x0F,  0x9C,  0xA2,  0x4F,  0x34,  0xA4, 	/* 1E2B0 */
+	0x8F,  0x14,  0xA2,  0x2F,  0xFD,  0x0A,  0x4A,  0xA4,  0x8A,  0x43,  0x3C,  0xB2,  0x02,  0xAF,  0xAA,  0xA2, 	/* 1E2C0 */
+	0xAF,  0x2A,  0xA2,  0xAF,  0x6E,  0xAB,  0xAF,  0xAA,  0x0A,  0xAA,  0xAA,  0x8C,  0xA3,  0x8A,  0xB8,  0x00, 	/* 1E2D0 */
+	0x0F,  0xBC,  0xA0,  0x4F,  0x7E,  0xA0,  0x4F,  0x7E,  0xA4,  0x2F,  0xFC,  0x09,  0x4A,  0x88,  0x89,  0x43, 	/* 1E2E0 */
+	0x62,  0xBB,  0x07,  0xCF,  0xC4,  0xA7,  0xCF,  0x44,  0xA7,  0xCF,  0x00,  0xA7,  0xEF,  0x90,  0x0F,  0xFA, 	/* 1E2F0 */
+	0x90,  0x89,  0x03,  0x10,  0xBF,  0x01,  0x0F,  0x94,  0xA7,  0xEF,  0x2A,  0xA2,  0x8F,  0xCE,  0xA2,  0x0F, 	/* 1E300 */
+	0xBC,  0x0E,  0x4A,  0x98,  0x8B,  0x43,  0x42,  0x81,  0x02,  0x0F,  0xFC,  0xA5,  0x4F,  0x7C,  0xA5,  0x4F, 	/* 1E310 */
+	0x7C,  0xA0,  0x0F,  0xFE,  0x0A,  0x0A,  0xBC,  0x88,  0x43,  0x18,  0x85,  0x01,  0x2F,  0x94,  0xA3,  0xEF, 	/* 1E320 */
+	0x68,  0xA2,  0x8F,  0x3E,  0xA2,  0x8F,  0xA8,  0x0B,  0xEA,  0xA8,  0x8A,  0x83,  0x3E,  0x8E,  0x01,  0x0F, 	/* 1E330 */
+	0x7C,  0xA1,  0x0F,  0x28,  0xA4,  0x6F,  0xFE,  0xA0,  0x4F,  0xF4,  0x0D,  0x4A,  0xF4,  0x88,  0x43,  0x0C, 	/* 1E340 */
+	0x8F,  0x02,  0x4F,  0xA4,  0xA7,  0xEF,  0x24,  0xA3,  0xCF,  0x24,  0xA3,  0xCF,  0xA4,  0x0F,  0xEA,  0x94, 	/* 1E350 */
+	0x8A,  0x23,  0x42,  0x92,  0xFF,  0xCA,  0x44,  0xF2,  0x8A,  0x38,  0xFD,  0x6A,  0x7C,  0xFD,  0x40,  0xD4, 	/* 1E360 */
+	0xAF,  0xCA,  0x92,  0x89,  0xE3,  0x62,  0x93,  0x01,  0x0F,  0xA8,  0xA4,  0x4F,  0xFA,  0xA1,  0x0F,  0x7C, 	/* 1E370 */
+	0xA5,  0x4F,  0xFC,  0x29,  0x0A,  0x98,  0x8A,  0x43,  0x42,  0x99,  0x07,  0xEF,  0x80,  0xA3,  0xEF,  0x22, 	/* 1E380 */
+	0xA3,  0xEF,  0x20,  0xA3,  0xFF,  0xB5,  0x0D,  0xFA,  0xD5,  0x89,  0x53,  0x13,  0xA8,  0x0A,  0x2F,  0x54, 	/* 1E390 */
+	0xA7,  0xCF,  0x54,  0xA7,  0xCF,  0x54,  0xA7,  0xCF,  0x90,  0x0F,  0xEA,  0x90,  0x89,  0x03,  0x10,  0xAB, 	/* 1E3A0 */
+	0x04,  0x0F,  0xFE,  0x91,  0x23,  0xF8,  0x11,  0x0F,  0xFE,  0x32,  0x45,  0xFA,  0x92,  0x01,  0xFC,  0x55, 	/* 1E3B0 */
+	0x48,  0x98,  0xB0,  0x0A,  0x8E,  0xFC,  0xA2,  0x0B,  0xFE,  0xE5,  0x0A,  0xF8,  0xB5,  0x6E,  0x78,  0xA5, 	/* 1E3C0 */
+	0x0A,  0x7E,  0xAA,  0xAB,  0x5C,  0xB7,  0xFB,  0xFA,  0x15,  0xF4,  0xAA,  0x2C,  0xF7,  0x3A,  0x08,  0xFB, 	/* 1E3D0 */
+	0xF0,  0xA9,  0xAB,  0xFA,  0x8A,  0x88,  0xF3,  0x71,  0xBE,  0x00,  0x0F,  0xFE,  0xA4,  0xAF,  0x7E,  0xA4, 	/* 1E3E0 */
+	0xAF,  0x7E,  0xA0,  0x8F,  0xB4,  0x08,  0xAA,  0xFE,  0x8A,  0xC3,  0x4A,  0x80,  0x09,  0x0F,  0xFE,  0x10, 	/* 1E3F0 */
+	0x81,  0xF8,  0x10,  0x8F,  0xFE,  0x32,  0x45,  0xFA,  0x92,  0x11,  0xFC,  0x2A,  0x45,  0x18,  0x82,  0x00, 	/* 1E400 */
+	0x8F,  0x94,  0xA7,  0xEF,  0x2A,  0xAF,  0xFF,  0x14,  0xA2,  0xAF,  0xF1,  0x08,  0xCA,  0xB2,  0x88,  0xC3, 	/* 1E410 */
+	0x30,  0x83,  0x00,  0x0F,  0xFE,  0xA2,  0x8F,  0x7E,  0xAA,  0xAF,  0xFE,  0xA7,  0xCF,  0x80,  0x0F,  0xEA, 	/* 1E420 */
+	0xB4,  0x8D,  0x23,  0x30,  0x85,  0x00,  0x0F,  0xFE,  0xA5,  0xCF,  0x54,  0xA5,  0xCF,  0x40,  0xA7,  0xEF, 	/* 1E430 */
+	0xEA,  0x0E,  0xAA,  0xFE,  0x8C,  0x03,  0x7E,  0x8D,  0x01,  0x0F,  0xFC,  0xA1,  0x0F,  0x54,  0xAE,  0xEF, 	/* 1E440 */
+	0x44,  0xAF,  0xEF,  0x80,  0x0F,  0xEA,  0xA8,  0x8A,  0xA3,  0x46,  0x95,  0x00,  0xCF,  0xF0,  0xA1,  0x0F, 	/* 1E450 */
+	0x7E,  0xA2,  0x8F,  0x6C,  0xAB,  0xAF,  0x80,  0x0F,  0xEA,  0xAA,  0x8B,  0xA3,  0x86,  0x97,  0x01,  0x0F, 	/* 1E460 */
+	0xA8,  0xA4,  0x4F,  0x7A,  0xA8,  0x1F,  0xEE,  0xAA,  0xAF,  0xEE,  0x0A,  0x4A,  0xB4,  0x8C,  0xA3,  0x91, 	/* 1E470 */
+	0x9A,  0x29,  0x0F,  0xDE,  0x45,  0x2F,  0x6C,  0x55,  0x47,  0xFA,  0x22,  0x03,  0xFC,  0x22,  0x03,  0xFE, 	/* 1E480 */
+	0x52,  0xA8,  0x8C,  0x9B,  0x00,  0x0F,  0x7E,  0xAA,  0xAF,  0xFE,  0xA1,  0x0F,  0x7C,  0xA2,  0x8F,  0xFE, 	/* 1E490 */
+	0x09,  0x0A,  0xFC,  0x89,  0x03,  0x10,  0x9F,  0x00,  0x0F,  0xFE,  0xA5,  0xAF,  0x74,  0xA5,  0xAF,  0xF1, 	/* 1E4A0 */
+	0xA5,  0x8F,  0xB2,  0x0D,  0xAA,  0xB4,  0x8D,  0x23,  0x10,  0xA2,  0x01,  0xCF,  0x90,  0xA7,  0xEF,  0x50, 	/* 1E4B0 */
+	0xA5,  0xFF,  0x40,  0xA7,  0xEF,  0xEA,  0x0F,  0xEA,  0xEA,  0x8A,  0xA3,  0x7F,  0xA4,  0x01,  0x0F,  0xFF, 	/* 1E4C0 */
+	0xA5,  0xAF,  0x7E,  0xA2,  0x8F,  0x7C,  0xA2,  0x8F,  0xFE,  0x09,  0x2A,  0xEC,  0x8A,  0x43,  0x72,  0xA5, 	/* 1E4D0 */
+	0x02,  0x8F,  0xEE,  0xA2,  0x8F,  0xFE,  0xA5,  0x4F,  0x7C,  0xA5,  0x4F,  0xFE,  0x0A,  0x8A,  0xFE,  0x8A, 	/* 1E4E0 */
+	0x43,  0x42,  0xA9,  0x02,  0x8F,  0xFE,  0xA2,  0x8F,  0xEE,  0xAA,  0xAF,  0xFE,  0xA2,  0x8F,  0xBE,  0x0E, 	/* 1E4F0 */
+	0x8A,  0xBE,  0x8A,  0x83,  0x3E,  0xAA,  0x06,  0xEF,  0x80,  0xA7,  0xEF,  0x56,  0xA0,  0x8F,  0x7E,  0xA5, 	/* 1E500 */
+	0x4F,  0xFE,  0x0E,  0x8A,  0xBE,  0x8A,  0x83,  0x76,  0xAB,  0x3F,  0x82,  0x40,  0x3F,  0xC2,  0xA4,  0x41, 	/* 1E510 */
+	0x87,  0xFE,  0x52,  0x87,  0xBC,  0x52,  0x87,  0xBE,  0x6A,  0xAB,  0x4C,  0xA8,  0x1F,  0x81,  0x08,  0x17, 	/* 1E520 */
+	0x81,  0x48,  0x7F,  0xE5,  0xFA,  0x50,  0xA1,  0xF8,  0x10,  0x81,  0xF8,  0x10,  0x81,  0x18,  0xAD,  0x78, 	/* 1E530 */
+	0x04,  0xBE,  0x58,  0x8F,  0xC8,  0x84,  0x87,  0xFF,  0x48,  0x87,  0x88,  0x48,  0x87,  0x88,  0x48,  0x85, 	/* 1E540 */
+	0x88,  0xB0,  0x79,  0xC4,  0x94,  0x59,  0x4F,  0xD5,  0x86,  0x37,  0xC0,  0x4F,  0xC7,  0xA4,  0x4A,  0x87, 	/* 1E550 */
+	0x98,  0x4A,  0x45,  0xC2,  0xB8,  0x78,  0x84,  0x88,  0x5F,  0xEF,  0xD0,  0x85,  0x07,  0xA4,  0x4D,  0x87, 	/* 1E560 */
+	0x92,  0x4A,  0x47,  0xC8,  0x49,  0x45,  0xE2,  0xBC,  0x79,  0x04,  0x9C,  0x5A,  0x4F,  0xD8,  0x84,  0x87, 	/* 1E570 */
+	0x94,  0x4A,  0x27,  0xFD,  0x4A,  0x47,  0xA4,  0x4A,  0x45,  0xBC,  0x80,  0x78,  0x84,  0x90,  0x5B,  0xEF, 	/* 1E580 */
+	0xEA,  0x87,  0xE7,  0xAA,  0x4B,  0xE7,  0x94,  0x4A,  0x47,  0xFF,  0x48,  0x45,  0x84,  0x84,  0x78,  0x44, 	/* 1E590 */
+	0x9F,  0x5C,  0x45,  0xAF,  0xFC,  0x98,  0x5F,  0x4E,  0x97,  0xAF,  0x4A,  0x97,  0xAB,  0x4D,  0x05,  0x8F, 	/* 1E5A0 */
+	0x8F,  0x78,  0x84,  0xBE,  0x5A,  0xAF,  0xFF,  0x87,  0xE7,  0xAA,  0x4B,  0xE7,  0x90,  0x4F,  0xF7,  0x92, 	/* 1E5B0 */
+	0x49,  0xC5,  0xB2,  0x91,  0x77,  0xE5,  0x5A,  0x77,  0xEF,  0xA0,  0x8B,  0xE7,  0x52,  0x5F,  0xE7,  0x56, 	/* 1E5C0 */
+	0x57,  0xE7,  0x1A,  0x5F,  0x65,  0x0C,  0x93,  0x78,  0x84,  0xBE,  0x59,  0x4F,  0xEE,  0x88,  0x07,  0x1E, 	/* 1E5D0 */
+	0x5D,  0x27,  0x5E,  0x55,  0x27,  0x52,  0x5B,  0x65,  0x1F,  0x94,  0x79,  0x44,  0xBE,  0x5A,  0xAF,  0xFE, 	/* 1E5E0 */
+	0x86,  0xA7,  0xFF,  0x48,  0x07,  0xBE,  0x4A,  0x27,  0xBE,  0x49,  0x45,  0xFF,  0x98,  0x02,  0x07,  0xFE, 	/* 1E5F0 */
+	0x00,  0x01,  0xF8,  0x10,  0x81,  0xF8,  0x7F,  0xE4,  0x02,  0x4F,  0x24,  0x92,  0x4F,  0x24,  0x06,  0x9E, 	/* 1E600 */
+	0x23,  0x8F,  0xA8,  0x73,  0x85,  0x00,  0x7E,  0xE0,  0xAA,  0xFE,  0xEB,  0x90,  0xAF,  0xEB,  0xB4,  0x8D, 	/* 1E610 */
+	0x29,  0x90,  0x9F,  0x00,  0x87,  0xC8,  0x41,  0x07,  0x94,  0x42,  0x47,  0x88,  0x40,  0x8F,  0xD2,  0x20, 	/* 1E620 */
+	0x22,  0x84,  0x3C,  0x8E,  0x50,  0xA2,  0x78,  0x84,  0x14,  0x7A,  0x84,  0x12,  0xFC,  0x45,  0x08,  0xFD, 	/* 1E630 */
+	0x02,  0x7C,  0xFC,  0x42,  0x58,  0x20,  0x21,  0xFE,  0xA3,  0x7C,  0x84,  0x32,  0x78,  0xC4,  0x32,  0xFC, 	/* 1E640 */
+	0xC4,  0xB0,  0x04,  0x0F,  0xFE,  0x04,  0x00,  0xF8,  0x10,  0x86,  0x30,  0xA6,  0x7C,  0x84,  0x32,  0x78, 	/* 1E650 */
+	0xC4,  0x32,  0xFC,  0xC4,  0xB0,  0x07,  0x03,  0xF8,  0x08,  0x0F,  0xFE,  0x08,  0x20,  0x7E,  0xAA,  0x7C, 	/* 1E660 */
+	0xC4,  0x32,  0x78,  0xC4,  0x32,  0xFC,  0xC4,  0xB0,  0xFF,  0xE1,  0x00,  0x3F,  0x8C,  0x90,  0x0E,  0x0F, 	/* 1E670 */
+	0x1C,  0xAB,  0x7C,  0x84,  0x32,  0x78,  0xC4,  0x32,  0xFC,  0xC4,  0xB0,  0xFF,  0xC0,  0x84,  0x31,  0x8D, 	/* 1E680 */
+	0xF8,  0x10,  0x81,  0xF8,  0xAD,  0x7C,  0xC4,  0x32,  0x78,  0xC4,  0x32,  0xF8,  0xC5,  0x30,  0xEC,  0x01, 	/* 1E690 */
+	0x26,  0x5B,  0x85,  0x20,  0x5E,  0x2E,  0x1E,  0xAE,  0x7C,  0xC4,  0x32,  0x78,  0xC4,  0x32,  0xFC,  0xC5, 	/* 1E6A0 */
+	0x30,  0x4D,  0x4F,  0xFE,  0x15,  0x02,  0x20,  0xCD,  0x83,  0x06,  0xAF,  0x7C,  0x84,  0x32,  0x78,  0xC4, 	/* 1E6B0 */
+	0x32,  0xFC,  0xC4,  0xB0,  0x3F,  0x82,  0x48,  0x3F,  0x82,  0x48,  0xFF,  0xE2,  0x18,  0xB1,  0x78,  0x84, 	/* 1E6C0 */
+	0x32,  0x70,  0xC4,  0x32,  0xFC,  0xC4,  0xB0,  0x08,  0x01,  0xFC,  0x32,  0x4D,  0xE8,  0x10,  0x20,  0xFE, 	/* 1E6D0 */
+	0xB4,  0x7C,  0xC4,  0x32,  0x78,  0xC4,  0x32,  0xFC,  0xC5,  0x30,  0x4D,  0x47,  0xF8,  0x12,  0x8F,  0xFE, 	/* 1E6E0 */
+	0x22,  0x24,  0x2C,  0xB7,  0x7C,  0x84,  0x32,  0x78,  0xC4,  0x32,  0xFC,  0xC4,  0xB0,  0x0A,  0x07,  0xFC, 	/* 1E6F0 */
+	0x4A,  0x47,  0xFC,  0x4A,  0x47,  0xFC,  0xBB,  0x7C,  0x84,  0x32,  0x78,  0xC4,  0x32,  0xFC,  0xC4,  0xB0, 	/* 1E700 */
+	0x04,  0x0F,  0xFE,  0x04,  0x07,  0xFC,  0x20,  0x83,  0xF8,  0x86,  0x78,  0x84,  0x32,  0x70,  0xC4,  0x32, 	/* 1E710 */
+	0xFC,  0xC4,  0xB0,  0x22,  0x4F,  0xA4,  0x75,  0x26,  0x98,  0xA2,  0x42,  0x7A,  0x98,  0x7C,  0x44,  0x18, 	/* 1E720 */
+	0xFE,  0x24,  0x84,  0xF5,  0x81,  0x08,  0x7F,  0xE4,  0x92,  0x7F,  0xE3,  0x08,  0x0F,  0x07,  0x0E,  0x9A, 	/* 1E730 */
+	0x7C,  0x44,  0x18,  0xFE,  0x24,  0x84,  0xF5,  0x80,  0x00,  0x37,  0xEC,  0x20,  0x37,  0xCC,  0x44,  0x37, 	/* 1E740 */
+	0xCC,  0x82,  0x9F,  0x78,  0x84,  0x32,  0xFC,  0xC5,  0x32,  0xFF,  0xC4,  0xA4,  0xFF,  0xE2,  0x08,  0x3F, 	/* 1E750 */
+	0x80,  0xCC,  0xF3,  0x01,  0x8E,  0xA2,  0x78,  0x84,  0x32,  0x74,  0xCF,  0xB2,  0x40,  0xCF,  0xFE,  0x95, 	/* 1E760 */
+	0x22,  0xE0,  0x7F,  0x8A,  0x08,  0x3F,  0x87,  0x1C,  0xA3,  0x7C,  0x84,  0x32,  0xFC,  0xC5,  0x32,  0xF8, 	/* 1E770 */
+	0xC2,  0xB0,  0x7F,  0xC5,  0x54,  0x7F,  0xC2,  0x4A,  0x37,  0x6E,  0xC2,  0xA5,  0x80,  0x2B,  0xBA,  0x91, 	/* 1E780 */
+	0x2B,  0xBA,  0x91,  0x2B,  0xBA,  0x80,  0x28,  0x02,  0x80,  0x28,  0x02,  0x80,  0x28,  0x06,  0xA7,  0x80, 	/* 1E790 */
+	0x2B,  0xBA,  0x91,  0x2B,  0xBA,  0x91,  0x2B,  0xBA,  0x84,  0x2B,  0xFA,  0x9F,  0x29,  0x52,  0x95,  0x28, 	/* 1E7A0 */
+	0x46,  0xA8,  0x80,  0x2B,  0xBA,  0x91,  0x2B,  0xBA,  0x91,  0x2B,  0xBA,  0x8A,  0x29,  0xF2,  0x8A,  0x2B, 	/* 1E7B0 */
+	0xFA,  0x8A,  0x29,  0x16,  0xA9,  0xBB,  0xA9,  0x12,  0xBB,  0xA9,  0x12,  0xBB,  0xA8,  0xB2,  0x91,  0x29, 	/* 1E7C0 */
+	0xB2,  0x91,  0x29,  0xF2,  0x8A,  0xAB,  0x1A,  0xAA,  0xBB,  0xA9,  0x12,  0xBB,  0xA8,  0x02,  0xBC,  0xA8, 	/* 1E7D0 */
+	0x0A,  0xBF,  0xEA,  0x4A,  0xBE,  0xAA,  0x5A,  0x94,  0xAB,  0xDA,  0xAE,  0xBB,  0xA9,  0x12,  0xBB,  0xA8, 	/* 1E7E0 */
+	0xF2,  0xB2,  0x29,  0xF2,  0xA9,  0x2F,  0xFA,  0xAB,  0xAF,  0xFA,  0x94,  0x6A,  0x3E,  0xAF,  0x91,  0x28, 	/* 1E7F0 */
+	0x92,  0xE2,  0x29,  0xCE,  0xCB,  0x2B,  0x4A,  0xC2,  0x2F,  0xFE,  0x21,  0x83,  0xE0,  0x20,  0x21,  0xFE, 	/* 1E800 */
+	0xB1,  0x24,  0x8F,  0x7E,  0x6D,  0xCB,  0x6A,  0xFF,  0xEA,  0x82,  0x54,  0xC6,  0xF0,  0x44,  0xC7,  0xB0, 	/* 1E810 */
+	0x44,  0x63,  0xF8,  0xB2,  0x00,  0x0F,  0xFE,  0x00,  0x03,  0xF8,  0x20,  0x8F,  0xFE,  0x8A,  0x2F,  0x3E, 	/* 1E820 */
+	0x80,  0x2B,  0xFA,  0x84,  0x28,  0x46,  0xBB,  0xE4,  0xE3,  0x52,  0xDF,  0xC2,  0xE2,  0x35,  0x2C,  0x4C, 	/* 1E830 */
+	0xFF,  0xE1,  0x10,  0x7F,  0xC4,  0xA4,  0x7F,  0x44,  0x0C,  0xBC,  0x04,  0x00,  0x80,  0x3F,  0x82,  0x48, 	/* 1E840 */
+	0x3F,  0x82,  0x48,  0x3F,  0x80,  0xA8,  0x0B,  0x41,  0x3C,  0x22,  0x2C,  0x1E,  0x81,  0x20,  0x44,  0x04, 	/* 1E850 */
+	0xF9,  0x4A,  0xA4,  0xF9,  0x4A,  0xA4,  0xF8,  0x63,  0x7C,  0x3A,  0x45,  0xE4,  0x51,  0x28,  0xFE,  0x82, 	/* 1E860 */
+	0x02,  0x00,  0xFC,  0xEA,  0x40,  0xFC,  0x0A,  0x4F,  0xA4,  0x4F,  0xC5,  0x54,  0xB5,  0xAD,  0x5E,  0x09, 	/* 1E870 */
+	0x23,  0x0E,  0x83,  0x21,  0x44,  0x12,  0xFF,  0xEA,  0x90,  0xF9,  0x4A,  0x94,  0xF8,  0x83,  0x48,  0x3B, 	/* 1E880 */
+	0x45,  0xE2,  0x52,  0x08,  0xFF,  0x84,  0x22,  0x04,  0x40,  0xEF,  0xCA,  0xA4,  0xAF,  0xCE,  0xA4,  0xAF, 	/* 1E890 */
+	0xCA,  0x64,  0xA6,  0xAE,  0xBE,  0x12,  0x16,  0x1F,  0x85,  0x20,  0x84,  0x08,  0xFB,  0xEA,  0x88,  0xF8, 	/* 1E8A0 */
+	0x8A,  0xFE,  0xF9,  0xC3,  0x6A,  0x3A,  0x85,  0xE8,  0x50,  0x18,  0xFF,  0x8D,  0x20,  0x04,  0x3E,  0xFA, 	/* 1E8B0 */
+	0x2A,  0xB6,  0xFA,  0xAA,  0xBE,  0xFA,  0xA3,  0x6E,  0x3A,  0x25,  0xE6,  0x54,  0x18,  0xFF,  0x8E,  0x20, 	/* 1E8C0 */
+	0x04,  0x7E,  0xF8,  0x8A,  0xBE,  0xFA,  0xAA,  0xBE,  0xFA,  0xE3,  0x7A,  0x3A,  0xA5,  0xEE,  0x50,  0x18, 	/* 1E8D0 */
+	0xFF,  0x8F,  0x19,  0x0E,  0x20,  0x27,  0xCF,  0xD4,  0x77,  0xCA,  0xD4,  0x27,  0xCF,  0x9A,  0x49,  0xC7, 	/* 1E8E0 */
+	0x2E,  0x2A,  0x9C,  0x4F,  0x91,  0x20,  0x84,  0x7E,  0xFA,  0x6A,  0xBA,  0xFB,  0x6A,  0xBE,  0xF8,  0x83, 	/* 1E8F0 */
+	0x7E,  0x3B,  0x65,  0xFE,  0x52,  0x38,  0xFF,  0x94,  0x02,  0x07,  0xFE,  0x48,  0x87,  0xFE,  0x5D,  0xC6, 	/* 1E900 */
+	0xAA,  0x5F,  0xC5,  0x24,  0x5F,  0xC8,  0x55,  0x89,  0x37,  0x0F,  0x98,  0x00,  0x07,  0xFE,  0x52,  0xA7, 	/* 1E910 */
+	0xFE,  0x52,  0x85,  0xF4,  0x56,  0x25,  0xFC,  0x52,  0x45,  0xFC,  0x8A,  0xA3,  0x1E,  0x9A,  0x08,  0x00, 	/* 1E920 */
+	0xF0,  0x11,  0x02,  0x20,  0x7F,  0xCA,  0x44,  0x3F,  0xC2,  0x44,  0x3F,  0xC0,  0x00,  0x4A,  0x48,  0x92, 	/* 1E930 */
+	0xAF,  0x1F,  0x06,  0x20,  0x3F,  0xC2,  0x44,  0x3F,  0xC2,  0x44,  0x3F,  0xC4,  0xA4,  0x89,  0x23,  0xFC, 	/* 1E940 */
+	0x20,  0x43,  0xFC,  0xB4,  0x21,  0x03,  0x90,  0x57,  0xEF,  0x90,  0xA9,  0x0F,  0x9C,  0xA9,  0x4F,  0x94, 	/* 1E950 */
+	0x12,  0x46,  0xA4,  0x54,  0x48,  0x98,  0x83,  0x20,  0x03,  0xFE,  0x51,  0x0F,  0xB8,  0xAD,  0x4F,  0x90, 	/* 1E960 */
+	0xAF,  0xEF,  0x90,  0x11,  0x06,  0x90,  0x51,  0x08,  0x10,  0x8E,  0x21,  0x03,  0x90,  0x51,  0x0F,  0x9E, 	/* 1E970 */
+	0xA9,  0x0F,  0x90,  0xAB,  0xCF,  0xA4,  0x12,  0x46,  0xA4,  0x52,  0x48,  0x3C,  0x91,  0x21,  0x03,  0x90, 	/* 1E980 */
+	0x53,  0xEF,  0xA2,  0xAF,  0xAF,  0xAA,  0xAA,  0xAF,  0xBC,  0x12,  0x06,  0xA0,  0x52,  0x28,  0x1E,  0x92, 	/* 1E990 */
+	0x21,  0x43,  0x94,  0x52,  0x4F,  0xBF,  0xAE,  0x4F,  0xA4,  0xAB,  0x4F,  0xAC,  0x12,  0x46,  0xA4,  0x52, 	/* 1E9A0 */
+	0x48,  0x2C,  0x93,  0x21,  0x03,  0x90,  0x53,  0xEF,  0xB0,  0xAD,  0x0F,  0x9E,  0xA9,  0x0F,  0x90,  0x11, 	/* 1E9B0 */
+	0xE6,  0x90,  0x51,  0x08,  0x10,  0x96,  0x20,  0x03,  0xFE,  0x51,  0x0F,  0x90,  0xA9,  0x0F,  0xA0,  0xAB, 	/* 1E9C0 */
+	0xEF,  0xD2,  0x11,  0x26,  0x92,  0x51,  0x28,  0x1E,  0x97,  0x20,  0x83,  0x9C,  0x52,  0x4F,  0xE8,  0xA9, 	/* 1E9D0 */
+	0x8F,  0xA4,  0xAD,  0x2F,  0x88,  0x12,  0x06,  0x98,  0x50,  0x48,  0x02,  0x9F,  0x20,  0x83,  0x88,  0x57, 	/* 1E9E0 */
+	0xEF,  0xD2,  0xA9,  0x0F,  0xFE,  0xAA,  0x4F,  0xA4,  0x17,  0x86,  0x88,  0x51,  0x48,  0x62,  0xA0,  0x20, 	/* 1E9F0 */
+	0x83,  0x9E,  0x52,  0x4F,  0xBE,  0xAA,  0x0F,  0xBC,  0xAB,  0x4F,  0xB4,  0x13,  0xC6,  0xD0,  0x55,  0x28, 	/* 1EA00 */
+	0x8E,  0xA8,  0x22,  0x03,  0xA6,  0x53,  0x8F,  0xA2,  0xA9,  0xEF,  0x80,  0xAB,  0xEF,  0xA2,  0x13,  0xE6, 	/* 1EA10 */
+	0xA2,  0x52,  0x28,  0x3E,  0xAA,  0x21,  0x03,  0x90,  0x57,  0xEF,  0x90,  0xAB,  0xCF,  0xA4,  0xAF,  0xCF, 	/* 1EA20 */
+	0xA4,  0x13,  0xC6,  0xA4,  0x52,  0x48,  0x2C,  0xAB,  0x21,  0x03,  0x90,  0x57,  0xEF,  0xA8,  0xAA,  0x4F, 	/* 1EA30 */
+	0xCA,  0xAA,  0x8F,  0xA8,  0x11,  0x06,  0xA8,  0x54,  0x48,  0x82,  0xAD,  0x21,  0x03,  0x90,  0x57,  0xCF, 	/* 1EA40 */
+	0x90,  0xA9,  0x0F,  0xFE,  0xA9,  0x0F,  0x90,  0x17,  0xC6,  0x90,  0x51,  0x08,  0xFE,  0xAE,  0x24,  0x43, 	/* 1EA50 */
+	0xA8,  0x57,  0xEF,  0x90,  0xA9,  0x0F,  0xFC,  0xA9,  0x0F,  0x90,  0x17,  0xE6,  0x90,  0x51,  0x08,  0x10, 	/* 1EA60 */
+	0xB4,  0x21,  0x43,  0x94,  0x51,  0x4F,  0xBF,  0xAA,  0x4F,  0xEE,  0xAA,  0xEF,  0xB5,  0x13,  0x56,  0xA4, 	/* 1EA70 */
+	0x52,  0x48,  0x24,  0xB9,  0x21,  0x03,  0xB4,  0x53,  0x4F,  0xD2,  0xAB,  0xCF,  0xA4,  0xAB,  0xCF,  0xA4, 	/* 1EA80 */
+	0x13,  0xC6,  0xA4,  0x52,  0x48,  0x2C,  0x80,  0x20,  0x63,  0xF8,  0x51,  0x0F,  0xE4,  0xAA,  0x8F,  0x94, 	/* 1EA90 */
+	0xAF,  0xEF,  0x92,  0x13,  0x46,  0xD2,  0x51,  0x28,  0x10,  0x86,  0x20,  0xA3,  0xFF,  0x50,  0x8F,  0xBE, 	/* 1EAA0 */
+	0xAA,  0xAF,  0xAA,  0xAB,  0xEF,  0xAA,  0x13,  0xE6,  0xAA,  0x52,  0xA8,  0x26,  0x89,  0x20,  0x03,  0xBE, 	/* 1EAB0 */
+	0x52,  0xAF,  0xBE,  0xAA,  0xAF,  0xAA,  0xAB,  0xEF,  0x88,  0x13,  0xE6,  0x88,  0x50,  0x88,  0x7E,  0x8A, 	/* 1EAC0 */
+	0x21,  0x09,  0x54,  0x45,  0x22,  0xB6,  0x41,  0x88,  0xF0,  0x72,  0x03,  0xFC,  0x22,  0x43,  0xFC,  0x3F, 	/* 1EAD0 */
+	0xC4,  0x92,  0x8F,  0x21,  0xA3,  0xE2,  0x52,  0xAF,  0xAA,  0xAF,  0xAF,  0xAA,  0xAB,  0xAF,  0xEA,  0x16, 	/* 1EAE0 */
+	0x26,  0xA2,  0x52,  0x28,  0x26,  0x91,  0x23,  0x23,  0x8C,  0x53,  0x2F,  0x90,  0xAF,  0xFF,  0x98,  0xAB, 	/* 1EAF0 */
+	0xEF,  0xAA,  0x16,  0xA6,  0xAE,  0x50,  0x88,  0x08,  0x92,  0x20,  0x03,  0xFE,  0x51,  0x4F,  0x88,  0xAB, 	/* 1EB00 */
+	0xEF,  0xAA,  0xAB,  0xEF,  0xAA,  0x13,  0xE6,  0xAA,  0x52,  0xA8,  0x26,  0x94,  0x22,  0xA3,  0xAA,  0x55, 	/* 1EB10 */
+	0x4F,  0xAA,  0xAA,  0xAF,  0x80,  0xAB,  0xEF,  0xAA,  0x13,  0xE6,  0xAA,  0x52,  0xA8,  0x3E,  0x96,  0x20, 	/* 1EB20 */
+	0x83,  0xBE,  0x50,  0x8F,  0xBC,  0xA8,  0x8F,  0xFE,  0xAA,  0x4F,  0xBC,  0x12,  0x46,  0xBC,  0x52,  0x48, 	/* 1EB30 */
+	0x2C,  0x9B,  0x20,  0x03,  0xBE,  0x52,  0xAF,  0xBE,  0xAA,  0xAF,  0xAA,  0xAB,  0xEF,  0xB6,  0x13,  0x66, 	/* 1EB40 */
+	0xBE,  0x54,  0x28,  0x86,  0xA1,  0x22,  0x83,  0xA8,  0x56,  0xEF,  0xA8,  0xAA,  0x8F,  0xEE,  0xAA,  0x8F, 	/* 1EB50 */
+	0xA8,  0x16,  0xE6,  0xC8,  0x54,  0x88,  0x88,  0xA2,  0x20,  0x83,  0x90,  0x52,  0xCF,  0xA4,  0xAB,  0xCF, 	/* 1EB60 */
+	0xA4,  0xAA,  0x4F,  0xBC,  0x11,  0x86,  0x9A,  0x52,  0xA8,  0x46,  0xA3,  0x20,  0x03,  0xBC,  0x52,  0x4F, 	/* 1EB70 */
+	0xBC,  0xAA,  0x4F,  0xBC,  0xA9,  0x0F,  0xBE,  0x12,  0xA6,  0xD2,  0x52,  0x28,  0x0C,  0xA4,  0x20,  0x03, 	/* 1EB80 */
+	0xBE,  0x52,  0x2F,  0xBE,  0xAA,  0x2F,  0xBE,  0xAA,  0x8F,  0xBA,  0x12,  0xC6,  0xAA,  0x53,  0xA8,  0x66, 	/* 1EB90 */
+	0xA8,  0x21,  0x03,  0xFE,  0x50,  0x0F,  0xBC,  0xAA,  0x4F,  0xA4,  0xAB,  0xCF,  0x88,  0x12,  0xC6,  0xAA, 	/* 1EBA0 */
+	0x54,  0xA8,  0x18,  0xB0,  0x21,  0x03,  0x90,  0x52,  0x8F,  0xFC,  0xA8,  0x2F,  0xBC,  0xA8,  0x4F,  0x88, 	/* 1EBB0 */
+	0x13,  0x46,  0xAA,  0x56,  0x28,  0x1E,  0xB1,  0x20,  0x83,  0x8E,  0x50,  0x8F,  0xBE,  0xAA,  0x8F,  0xBE, 	/* 1EBC0 */
+	0xAA,  0x8F,  0xA7,  0x12,  0xC6,  0xAC,  0x55,  0x58,  0xA3,  0xB2,  0x22,  0x43,  0xA4,  0x57,  0xAF,  0xAA, 	/* 1EBD0 */
+	0xAA,  0x1F,  0xB8,  0xAB,  0x4F,  0xB4,  0x15,  0x06,  0xD4,  0x51,  0x28,  0x62,  0xB5,  0x21,  0x07,  0xA4, 	/* 1EBE0 */
+	0x97,  0xAF,  0x90,  0xAF,  0xEF,  0x98,  0xAA,  0x4F,  0xCA,  0x13,  0x16,  0x84,  0x51,  0x88,  0x60,  0x84, 	/* 1EBF0 */
+	0x20,  0x43,  0x86,  0x53,  0xFF,  0xA4,  0xAB,  0xCF,  0xA4,  0xAB,  0xDF,  0xB6,  0x15,  0xC6,  0xD2,  0x56, 	/* 1EC00 */
+	0xB8,  0x81,  0x86,  0x21,  0x03,  0xFC,  0x51,  0x0F,  0xBC,  0xA9,  0x0F,  0xFE,  0xAA,  0x8F,  0xBC,  0x16, 	/* 1EC10 */
+	0x66,  0xBD,  0x52,  0x48,  0x3C,  0x88,  0x25,  0x43,  0xFE,  0x55,  0x4F,  0xDC,  0xAC,  0x0F,  0xFE,  0xA9, 	/* 1EC20 */
+	0x0F,  0xFE,  0x11,  0x86,  0xB4,  0x55,  0x28,  0x10,  0x89,  0x21,  0x03,  0xBC,  0x52,  0x4F,  0xBC,  0xAA, 	/* 1EC30 */
+	0x4F,  0xBC,  0xA8,  0x0F,  0xFE,  0x10,  0x86,  0xBE,  0x50,  0x88,  0x7E,  0x8A,  0x20,  0x83,  0xFE,  0x50, 	/* 1EC40 */
+	0x8F,  0xBE,  0xAB,  0xAF,  0xAE,  0xAB,  0xEF,  0x9C,  0x12,  0xA6,  0xC9,  0x50,  0x88,  0x08,  0x8C,  0x21, 	/* 1EC50 */
+	0xC3,  0x94,  0x52,  0x2F,  0xFE,  0xA9,  0x4F,  0xBE,  0xAA,  0xAF,  0xB6,  0x12,  0x26,  0xBE,  0x52,  0x28, 	/* 1EC60 */
+	0x3E,  0x8D,  0x21,  0xC3,  0xE4,  0x52,  0x4F,  0xA5,  0xAF,  0x6F,  0xAE,  0xAF,  0x4F,  0xA4,  0x12,  0xA6, 	/* 1EC70 */
+	0xAA,  0x53,  0x28,  0xA1,  0x90,  0x27,  0xE3,  0xDA,  0x57,  0xEF,  0x80,  0xAB,  0xCF,  0x80,  0xAF,  0xEF, 	/* 1EC80 */
+	0xA0,  0x13,  0xC6,  0x84,  0x50,  0x48,  0x18,  0x92,  0x22,  0x03,  0xBE,  0x56,  0x4F,  0xBC,  0xAA,  0x4F, 	/* 1EC90 */
+	0xBC,  0xA9,  0x0F,  0x9E,  0x13,  0x46,  0xC8,  0x51,  0x48,  0x62,  0x93,  0x20,  0x03,  0xBE,  0x52,  0xAF, 	/* 1ECA0 */
+	0xAA,  0xAB,  0xEF,  0xAA,  0xAB,  0xEF,  0x94,  0x12,  0xA6,  0xB0,  0x5D,  0x29,  0x0E,  0x94,  0x20,  0x43, 	/* 1ECB0 */
+	0x86,  0x53,  0xFF,  0xA4,  0xAB,  0xCF,  0xA4,  0xAB,  0xDF,  0xB6,  0x15,  0xC6,  0xCA,  0x55,  0x38,  0x81, 	/* 1ECC0 */
+	0x95,  0x20,  0x03,  0xF6,  0x55,  0x2F,  0xD2,  0xAF,  0x6F,  0xC0,  0xAF,  0xEF,  0xCA,  0x14,  0xA6,  0xF4, 	/* 1ECD0 */
+	0x54,  0xA8,  0x51,  0x9B,  0x20,  0x03,  0xBC,  0x52,  0x4F,  0xBC,  0xAA,  0x4F,  0xBC,  0xA8,  0x0F,  0xBE, 	/* 1ECE0 */
+	0x12,  0xA6,  0xAA,  0x52,  0xA8,  0x7F,  0xA1,  0x21,  0x03,  0xAE,  0x54,  0xAF,  0xEA,  0xAD,  0x2F,  0xF6, 	/* 1ECF0 */
+	0xA8,  0x0F,  0xBE,  0x12,  0xA6,  0xBE,  0x52,  0xA8,  0x3E,  0xA4,  0x20,  0x03,  0xBE,  0x54,  0x8F,  0xFE, 	/* 1ED00 */
+	0xAA,  0xAF,  0xEA,  0xA8,  0xAF,  0xEA,  0x1A,  0xA6,  0xA8,  0x5E,  0x88,  0x08,  0xA5,  0x20,  0x03,  0xFE, 	/* 1ED10 */
+	0x55,  0xAF,  0xDA,  0xAF,  0xEF,  0x88,  0xAA,  0xCF,  0xCA,  0x11,  0xC6,  0xAA,  0x54,  0x98,  0x08,  0xAD, 	/* 1ED20 */
+	0x21,  0x27,  0xBE,  0x91,  0x4F,  0xFE,  0xAA,  0x0F,  0xFC,  0xAA,  0x2F,  0x9E,  0x10,  0x06,  0xBE,  0x52, 	/* 1ED30 */
+	0x28,  0x3E,  0xAE,  0x20,  0x03,  0xBE,  0x52,  0xAF,  0xB6,  0xAA,  0x2F,  0xBE,  0xA8,  0x0F,  0xBE,  0x12, 	/* 1ED40 */
+	0xA6,  0xAA,  0x52,  0xA8,  0x7F,  0xAF,  0x20,  0x03,  0xFE,  0x51,  0x2F,  0xBE,  0xAC,  0x8F,  0xFE,  0xA9, 	/* 1ED50 */
+	0x2F,  0xDA,  0x13,  0x66,  0xDA,  0x51,  0x28,  0x6C,  0xB0,  0x20,  0x87,  0x68,  0xA1,  0xEF,  0x1A,  0xBF, 	/* 1ED60 */
+	0xAF,  0x5E,  0xB7,  0xAF,  0xFA,  0x15,  0xE6,  0xC8,  0x54,  0x88,  0x48,  0xB2,  0x20,  0x87,  0x9E,  0x23, 	/* 1ED70 */
+	0x4F,  0xC8,  0x49,  0x49,  0xE2,  0x64,  0x03,  0xF8,  0x24,  0x83,  0xF8,  0x29,  0x44,  0x4A,  0xB9,  0x20, 	/* 1ED80 */
+	0x03,  0x7E,  0x54,  0xAF,  0xFA,  0xAF,  0x4F,  0xCA,  0xAF,  0x1F,  0x88,  0x13,  0xE6,  0x88,  0x50,  0x88, 	/* 1ED90 */
+	0x7F,  0xBA,  0x21,  0x03,  0xA4,  0x57,  0xAF,  0x90,  0xAF,  0xEF,  0x98,  0xAA,  0x4F,  0xCA,  0x13,  0x56, 	/* 1EDA0 */
+	0x88,  0x53,  0x08,  0xC0,  0xBB,  0x23,  0xC7,  0xA4,  0x93,  0xCF,  0xA4,  0xAF,  0xEF,  0xAA,  0xAF,  0xEF, 	/* 1EDB0 */
+	0xA4,  0x11,  0x46,  0x98,  0x52,  0x48,  0x42,  0xBE,  0x27,  0xE3,  0x94,  0x57,  0xEF,  0xDA,  0xAF,  0xEF, 	/* 1EDC0 */
+	0x80,  0xAB,  0xEF,  0x80,  0x17,  0xF6,  0xAC,  0x54,  0xA8,  0x18,  0x86,  0x20,  0x83,  0xFE,  0x52,  0x4F, 	/* 1EDD0 */
+	0x98,  0xAF,  0xEF,  0xA4,  0xAB,  0xCF,  0xA4,  0x13,  0xC6,  0x88,  0x57,  0xE8,  0x08,  0x87,  0x20,  0x83, 	/* 1EDE0 */
+	0xBE,  0x52,  0x8F,  0xBE,  0xAA,  0xAF,  0xBF,  0xAA,  0xAF,  0xBE,  0x12,  0xA6,  0xDC,  0x56,  0xA8,  0x88, 	/* 1EDF0 */
+	0x88,  0x23,  0xE3,  0x88,  0x57,  0xFF,  0xC9,  0xAE,  0xDF,  0xDB,  0xA8,  0x0F,  0xBE,  0x10,  0x26,  0xBE, 	/* 1EE00 */
+	0x50,  0x28,  0x3E,  0x92,  0x24,  0x47,  0xA8,  0x97,  0xEF,  0xA8,  0xAF,  0xEF,  0xAA,  0xAC,  0xEF,  0xFF, 	/* 1EE10 */
+	0x12,  0x46,  0x94,  0x50,  0x48,  0x0C,  0x97,  0x20,  0x83,  0xAA,  0x57,  0xFF,  0x9C,  0xAA,  0xAF,  0xC9, 	/* 1EE20 */
+	0xAB,  0xCF,  0xAE,  0x16,  0xC6,  0x94,  0x52,  0xF8,  0x44,  0x9A,  0x20,  0x83,  0xFF,  0x50,  0x8F,  0xBE, 	/* 1EE30 */
+	0xAA,  0x2F,  0xBE,  0xA9,  0x4F,  0xFF,  0x10,  0x06,  0xBE,  0x52,  0x28,  0x3E,  0xA0,  0x20,  0x83,  0xD4, 	/* 1EE40 */
+	0x53,  0xEF,  0xC1,  0xAF,  0xEF,  0xEE,  0xAD,  0xAF,  0xFE,  0x12,  0x46,  0xBC,  0x52,  0x48,  0x3C,  0xA7, 	/* 1EE50 */
+	0x21,  0x43,  0xBE,  0x52,  0xAF,  0xBE,  0xAA,  0xAF,  0xBE,  0xA8,  0x0F,  0xFE,  0x12,  0x46,  0xBC,  0x52, 	/* 1EE60 */
+	0x88,  0x7E,  0xB6,  0x21,  0x43,  0xFE,  0x50,  0x8F,  0xBE,  0xA9,  0x8F,  0xA4,  0xAF,  0xEF,  0xA5,  0x13, 	/* 1EE70 */
+	0xC6,  0xAA,  0x53,  0x49,  0x62,  0xB8,  0x20,  0x83,  0x8E,  0x50,  0x8F,  0xBE,  0xAA,  0x8F,  0xBE,  0xAA, 	/* 1EE80 */
+	0xAF,  0xBE,  0x14,  0x06,  0xFE,  0x5A,  0xA9,  0x7F,  0xA5,  0x08,  0x03,  0xF8,  0x20,  0x83,  0xF8,  0x20, 	/* 1EE90 */
+	0x83,  0xFE,  0x20,  0x03,  0xFE,  0x01,  0x25,  0x4A,  0x4A,  0x28,  0x0C,  0xA7,  0x08,  0x03,  0xF0,  0x21, 	/* 1EEA0 */
+	0x03,  0xFE,  0x20,  0x03,  0xFE,  0x55,  0x28,  0xAC,  0x1F,  0x01,  0x10,  0x21,  0x2C,  0x0E,  0xA9,  0x42, 	/* 1EEB0 */
+	0x04,  0x7C,  0x44,  0x4F,  0x7C,  0x54,  0x45,  0x7E,  0x54,  0x05,  0x7E,  0x58,  0x24,  0xAA,  0x8A,  0x21, 	/* 1EEC0 */
+	0x0C,  0xAB,  0x00,  0x07,  0xFE,  0x44,  0x05,  0xF8,  0x50,  0x85,  0xF8,  0x5F,  0xE5,  0x00,  0x5F,  0xE5, 	/* 1EED0 */
+	0x52,  0xAA,  0xA4,  0x0C,  0xAC,  0x08,  0x03,  0xF0,  0x21,  0x03,  0xFE,  0x20,  0x03,  0xFE,  0x00,  0x21, 	/* 1EEE0 */
+	0xF2,  0x11,  0xC1,  0x10,  0x21,  0x2C,  0x0E,  0xB0,  0x01,  0x00,  0x3C,  0x72,  0x41,  0x3C,  0x12,  0x41, 	/* 1EEF0 */
+	0x3E,  0x2A,  0x02,  0x7E,  0x41,  0x68,  0x2A,  0x04,  0x20,  0x0C,  0xB3,  0x7F,  0xC4,  0x44,  0x5F,  0x45, 	/* 1EF00 */
+	0x14,  0x5F,  0x45,  0x14,  0x5F,  0xC5,  0x04,  0x5F,  0xC4,  0xAD,  0x55,  0xBA,  0x31,  0xB4,  0x04,  0x00, 	/* 1EF10 */
+	0xF8,  0xE8,  0x8A,  0xF8,  0xA8,  0x8A,  0xFC,  0xA8,  0x0A,  0xFE,  0xE0,  0x21,  0x56,  0x15,  0x22,  0x0C, 	/* 1EF20 */
+	0xB6,  0x04,  0x8F,  0xFE,  0x02,  0x01,  0x1A,  0x3F,  0x62,  0x12,  0x3F,  0x02,  0x00,  0x3F,  0xE5,  0x52, 	/* 1EF30 */
+	0x4A,  0xA8,  0x0C,  0x83,  0x41,  0x0F,  0x10,  0x91,  0x0F,  0x7C,  0x91,  0x4F,  0x94,  0x87,  0xEF,  0x90, 	/* 1EF40 */
+	0x59,  0x8A,  0xA8,  0x8A,  0x43,  0x42,  0x86,  0x21,  0x02,  0x3C,  0xFA,  0x4A,  0xBC,  0xAA,  0x42,  0x3E, 	/* 1EF50 */
+	0x32,  0x03,  0x7E,  0x59,  0x65,  0x2A,  0x44,  0x28,  0x0C,  0x87,  0x82,  0x0F,  0x7C,  0x84,  0x48,  0x7C, 	/* 1EF60 */
+	0x74,  0x42,  0x7E,  0x24,  0x0F,  0x7E,  0x20,  0x22,  0xAA,  0x2A,  0x22,  0x8C,  0x88,  0x00,  0x07,  0xFE, 	/* 1EF70 */
+	0x49,  0x04,  0xBC,  0x4A,  0x45,  0x3C,  0x53,  0xE7,  0x20,  0x53,  0xE5,  0x52,  0x9A,  0xA1,  0x0C,  0x89, 	/* 1EF80 */
+	0x01,  0x07,  0xBC,  0x52,  0x45,  0x3C,  0x52,  0x4F,  0xBE,  0x12,  0x03,  0x3E,  0x31,  0x65,  0x2A,  0x94, 	/* 1EF90 */
+	0x23,  0x0C,  0x8E,  0x01,  0x0F,  0xBC,  0x82,  0x48,  0xBC,  0xCA,  0x4B,  0x3E,  0x92,  0x0A,  0xBE,  0xC9, 	/* 1EFA0 */
+	0x68,  0x2A,  0xFC,  0x28,  0x0C,  0x92,  0x21,  0x02,  0x3C,  0x32,  0x44,  0xBC,  0xF6,  0x40,  0x3E,  0xFA, 	/* 1EFB0 */
+	0x02,  0xBE,  0x29,  0x63,  0x2A,  0x24,  0x22,  0x0C,  0x95,  0x20,  0x87,  0xBE,  0x4A,  0x27,  0xA2,  0x49, 	/* 1EFC0 */
+	0x07,  0xD2,  0x41,  0xC7,  0xD0,  0x2D,  0x05,  0x52,  0x85,  0x21,  0x8E,  0x9B,  0x1D,  0xE2,  0x52,  0xD5, 	/* 1EFD0 */
+	0x63,  0x90,  0xE4,  0xE3,  0xF8,  0x20,  0x83,  0xFC,  0x20,  0x03,  0xFE,  0x55,  0x2A,  0x4C,  0x9F,  0x19, 	/* 1EFE0 */
+	0x0E,  0x3C,  0xA2,  0x4B,  0xBC,  0xE2,  0x4A,  0x3E,  0xAA,  0x09,  0xBE,  0x89,  0x6C,  0x2A,  0x1C,  0x2E, 	/* 1EFF0 */
+	0x0C,  0xA3,  0x21,  0x02,  0x3C,  0x22,  0x4F,  0xFC,  0x22,  0x42,  0x3E,  0x22,  0x07,  0xBE,  0x49,  0x64, 	/* 1F000 */
+	0xAA,  0x7C,  0x20,  0x0C,  0xA6,  0x04,  0x03,  0xF8,  0x28,  0x8F,  0xFE,  0x15,  0x03,  0xF8,  0xE1,  0x63, 	/* 1F010 */
+	0xF0,  0x21,  0x03,  0xFE,  0x55,  0x28,  0xAC,  0xA8,  0x01,  0x0F,  0xBC,  0xAA,  0x4A,  0xBC,  0xFA,  0x0A, 	/* 1F020 */
+	0xBE,  0xAA,  0x0F,  0xBE,  0x20,  0x22,  0x56,  0x25,  0x22,  0x8C,  0xAA,  0x21,  0x02,  0x3C,  0xFA,  0x48, 	/* 1F030 */
+	0xBC,  0x0A,  0x47,  0x3E,  0x52,  0x05,  0x3E,  0x51,  0x64,  0xAA,  0x84,  0x20,  0x0C,  0xAB,  0x01,  0x00, 	/* 1F040 */
+	0x3C,  0xFA,  0x4A,  0xBC,  0xAA,  0x4F,  0xBE,  0xAA,  0x0A,  0xBE,  0xA9,  0x6F,  0xAA,  0x04,  0x20,  0x0C, 	/* 1F050 */
+	0xAC,  0x28,  0x81,  0x50,  0xFF,  0xE8,  0x82,  0x3F,  0x02,  0x10,  0x3F,  0xE2,  0x00,  0x3F,  0xC1,  0x54, 	/* 1F060 */
+	0x4A,  0x48,  0x18,  0xBB,  0x41,  0x02,  0x7C,  0x04,  0x4B,  0xFC,  0x54,  0x41,  0x7E,  0x14,  0x05,  0x7E, 	/* 1F070 */
+	0x78,  0x24,  0xAA,  0x8A,  0x29,  0x0C,  0xBE,  0x01,  0x0F,  0xFC,  0x22,  0x44,  0xBC,  0xF6,  0x45,  0x3E, 	/* 1F080 */
+	0x7A,  0x09,  0x3E,  0x11,  0x6F,  0xEA,  0x14,  0x21,  0x0C,  0xBF,  0x21,  0x02,  0x3C,  0x52,  0x44,  0xBC, 	/* 1F090 */
+	0xFE,  0x40,  0x3E,  0x7A,  0x04,  0xBE,  0x49,  0x64,  0xAA,  0x7C,  0x20,  0x0C,  0x81,  0x21,  0x02,  0x3C, 	/* 1F0A0 */
+	0xFA,  0x45,  0x3C,  0x4A,  0x49,  0x7E,  0x32,  0x01,  0x3E,  0x29,  0x62,  0x2A,  0x44,  0x28,  0x0C,  0x84, 	/* 1F0B0 */
+	0x01,  0x0F,  0xBC,  0x32,  0x44,  0xBC,  0xF6,  0x42,  0x3E,  0x22,  0x0F,  0xBE,  0x21,  0x63,  0xAA,  0xE4, 	/* 1F0C0 */
+	0x20,  0x0C,  0x86,  0x28,  0x03,  0xEE,  0x52,  0x0B,  0xE0,  0x32,  0xF5,  0xF4,  0xD0,  0x45,  0xF4,  0x4B, 	/* 1F0D0 */
+	0x45,  0x54,  0x61,  0x44,  0x6C,  0x88,  0x01,  0x0F,  0xFC,  0x4A,  0x44,  0xBC,  0x7A,  0x44,  0xBE,  0x7A, 	/* 1F0E0 */
+	0x04,  0xBE,  0x49,  0x67,  0xAA,  0xCC,  0x20,  0x8C,  0x90,  0x01,  0x0F,  0xBC,  0x22,  0x46,  0xBC,  0x6A, 	/* 1F0F0 */
+	0x46,  0xBE,  0xB6,  0x0A,  0x3E,  0x29,  0x63,  0x2A,  0xC4,  0x20,  0x0C,  0x91,  0x01,  0x0F,  0xBC,  0x8A, 	/* 1F100 */
+	0x4F,  0xBC,  0x02,  0x4F,  0xBE,  0x8A,  0x0F,  0xBE,  0x89,  0x6F,  0xAA,  0x8C,  0x29,  0x8C,  0x99,  0x01, 	/* 1F110 */
+	0x07,  0xBC,  0x4A,  0x44,  0xBC,  0x7A,  0x44,  0xBE,  0x7A,  0x04,  0xBE,  0x79,  0x62,  0xAA,  0x44,  0x28, 	/* 1F120 */
+	0x0C,  0x9C,  0x49,  0x03,  0x3C,  0xFA,  0x42,  0xBC,  0xFA,  0x4A,  0x3E,  0xFA,  0x02,  0xBE,  0x69,  0x67, 	/* 1F130 */
+	0xAA,  0xA4,  0x22,  0x0C,  0x9D,  0x31,  0x0D,  0xBC,  0x56,  0x45,  0x3C,  0xFE,  0x45,  0x7E,  0x5A,  0x07, 	/* 1F140 */
+	0x3E,  0xD1,  0x64,  0xAA,  0x4C,  0x2C,  0x4C,  0x9E,  0x39,  0x81,  0x14,  0xFF,  0xE1,  0x14,  0xF8,  0x81, 	/* 1F150 */
+	0x36,  0x34,  0x23,  0xF8,  0x20,  0x83,  0xFE,  0x4A,  0xA8,  0x0C,  0xA0,  0x51,  0x05,  0x3C,  0x7E,  0x49, 	/* 1F160 */
+	0x3C,  0x12,  0x4F,  0xFE,  0x02,  0x07,  0xBE,  0x48,  0x24,  0xD6,  0x4D,  0x27,  0xCC,  0xA1,  0x09,  0x0E, 	/* 1F170 */
+	0xFC,  0x0A,  0x4F,  0xFC,  0x2A,  0x42,  0xBE,  0xBA,  0x0A,  0xBE,  0xA8,  0x2B,  0xAA,  0xC6,  0x28,  0x4C, 	/* 1F180 */
+	0xA4,  0x41,  0x07,  0x3C,  0xA2,  0x4F,  0xBC,  0xAA,  0x4F,  0xBE,  0xAA,  0x0A,  0xBE,  0xF9,  0x68,  0xAA, 	/* 1F190 */
+	0x8C,  0x29,  0x8C,  0xAC,  0x01,  0x0F,  0xFC,  0xB6,  0x4B,  0x7C,  0xFE,  0x4B,  0x7C,  0xB6,  0x0F,  0xFE, 	/* 1F1A0 */
+	0xB6,  0x0B,  0x7E,  0xB6,  0xAA,  0xD6,  0xAF,  0x41,  0x0F,  0xFC,  0xAA,  0x4F,  0xBC,  0xAA,  0x4F,  0xBE, 	/* 1F1B0 */
+	0x32,  0x05,  0x3E,  0xF9,  0x61,  0x2A,  0x14,  0x21,  0x0C,  0xB2,  0x49,  0x04,  0xBC,  0xFE,  0x44,  0xBC, 	/* 1F1C0 */
+	0xFE,  0x40,  0x3E,  0x7A,  0x04,  0xBE,  0x79,  0x64,  0xAA,  0x4C,  0x27,  0x8C,  0xBA,  0x10,  0x81,  0x1E, 	/* 1F1D0 */
+	0xFF,  0x22,  0x9E,  0x5F,  0x25,  0x5F,  0xDD,  0x07,  0x5E,  0x49,  0x65,  0x6A,  0x64,  0x24,  0x0C,  0x87, 	/* 1F1E0 */
+	0x21,  0x0F,  0xFC,  0x22,  0x4F,  0xBC,  0xAA,  0x4F,  0xBE,  0xAA,  0x0F,  0xBE,  0x31,  0x66,  0xAA,  0xA4, 	/* 1F1F0 */
+	0x22,  0x0C,  0x89,  0x11,  0x0F,  0xFC,  0x02,  0x47,  0xBC,  0x4A,  0x47,  0xBE,  0x02,  0x07,  0xBE,  0x1D, 	/* 1F200 */
+	0x6F,  0x2A,  0x14,  0x23,  0x0C,  0x8F,  0x1A,  0x0E,  0x7C,  0x04,  0x4A,  0xFC,  0xAC,  0x00,  0x7C,  0xFC, 	/* 1F210 */
+	0x02,  0x7E,  0xF8,  0x22,  0x2A,  0x54,  0x28,  0x0C,  0x9A,  0x01,  0x0F,  0xBC,  0xAA,  0x4F,  0xBC,  0x02, 	/* 1F220 */
+	0x4F,  0xBE,  0x02,  0x0F,  0xBE,  0x41,  0x67,  0x2A,  0x94,  0x23,  0x0C,  0xA4,  0x01,  0x0F,  0xBC,  0xAA, 	/* 1F230 */
+	0x42,  0x3C,  0xFA,  0x4A,  0xBE,  0xFA,  0x0A,  0xBE,  0xF9,  0x62,  0x2A,  0xFC,  0x22,  0x0C,  0xA9,  0x7C, 	/* 1F240 */
+	0x82,  0x9F,  0xFF,  0x42,  0x8C,  0x49,  0x23,  0xF0,  0x21,  0x03,  0xFE,  0x20,  0x03,  0xFC,  0x55,  0x48, 	/* 1F250 */
+	0x98,  0xAB,  0x21,  0x0F,  0xFC,  0x22,  0x4F,  0xBC,  0xEA,  0x4B,  0xBE,  0xFA,  0x02,  0x3E,  0x71,  0x66, 	/* 1F260 */
+	0xAA,  0xA4,  0x22,  0x0C,  0xAF,  0x55,  0x42,  0xA8,  0x44,  0x4F,  0xFE,  0x91,  0x29,  0xF2,  0x11,  0x01, 	/* 1F270 */
+	0xFC,  0x10,  0x01,  0xFC,  0x55,  0x48,  0x18,  0xB2,  0x51,  0x05,  0x3C,  0xAA,  0x45,  0x3C,  0xFA,  0x40, 	/* 1F280 */
+	0x3E,  0xFA,  0x06,  0xBE,  0xB9,  0x66,  0xAA,  0xBC,  0x22,  0x8C,  0xB4,  0x21,  0x02,  0x3C,  0xFA,  0x4A, 	/* 1F290 */
+	0xBC,  0x22,  0x47,  0xBE,  0xD2,  0x07,  0xBE,  0x51,  0x67,  0xAA,  0x54,  0x27,  0xCC,  0xB8,  0x01,  0x0F, 	/* 1F2A0 */
+	0xBC,  0x2A,  0x4F,  0xBC,  0x92,  0x4F,  0xBE,  0x6A,  0x0A,  0xBE,  0x79,  0x6A,  0xAA,  0x2C,  0x2D,  0x8C, 	/* 1F2B0 */
+	0xBA,  0x21,  0x0E,  0xBC,  0x22,  0x4E,  0xBC,  0x52,  0x48,  0xBE,  0x7E,  0x04,  0xBE,  0x79,  0x64,  0xAA, 	/* 1F2C0 */
+	0x4C,  0x25,  0x8C,  0xBB,  0x79,  0x04,  0xBC,  0x5A,  0x4F,  0xFC,  0x86,  0x47,  0xBE,  0x4A,  0x07,  0xBE, 	/* 1F2D0 */
+	0x49,  0x67,  0xAA,  0x4C,  0x25,  0x8C,  0x81,  0x39,  0x02,  0xBC,  0x76,  0x48,  0x3C,  0x3A,  0x42,  0xBE, 	/* 1F2E0 */
+	0x46,  0x08,  0x3E,  0x7D,  0x65,  0x6A,  0x54,  0x2F,  0xEC,  0x82,  0x21,  0x03,  0xBC,  0x4A,  0x4B,  0x3C, 	/* 1F2F0 */
+	0x22,  0x4C,  0x3E,  0x7A,  0x0A,  0x3E,  0xF9,  0x62,  0x2A,  0xAC,  0x2F,  0x8C,  0x84,  0x19,  0x0E,  0xBC, 	/* 1F300 */
+	0xAA,  0x45,  0x7C,  0x22,  0x4D,  0x3E,  0x2A,  0x0F,  0xBE,  0x21,  0x6F,  0xAA,  0x54,  0x28,  0x0C,  0x86, 	/* 1F310 */
+	0x41,  0x07,  0xBC,  0x42,  0x47,  0xFC,  0x2A,  0x4B,  0xBE,  0xAA,  0x0B,  0xBE,  0xA9,  0x6F,  0xEA,  0x24, 	/* 1F320 */
+	0x2C,  0x0C,  0x8F,  0x21,  0x0F,  0xFC,  0x22,  0x47,  0xBC,  0x4A,  0x47,  0xBE,  0x4A,  0x07,  0xBE,  0x49, 	/* 1F330 */
+	0x6F,  0xEA,  0x32,  0x2C,  0x8C,  0x93,  0x11,  0x07,  0xFC,  0x42,  0x46,  0xBC,  0x7E,  0x46,  0xBE,  0x6A, 	/* 1F340 */
+	0x06,  0xBE,  0xB9,  0x68,  0x2A,  0x54,  0x2A,  0x8C,  0x99,  0x21,  0x0F,  0xBC,  0x51,  0x4F,  0xB4,  0x22, 	/* 1F350 */
+	0xA5,  0xF8,  0x10,  0x81,  0xFE,  0x10,  0x01,  0xFE,  0x2A,  0xA4,  0x0C,  0xA6,  0x49,  0x05,  0x3C,  0x7E, 	/* 1F360 */
+	0x4D,  0x3C,  0x7A,  0x45,  0x3E,  0x7A,  0x05,  0x3E,  0x79,  0x60,  0x2A,  0x54,  0x2A,  0x8C,  0xAD,  0x19, 	/* 1F370 */
+	0x0E,  0xBC,  0xB2,  0x4F,  0xBC,  0x72,  0x4A,  0xBE,  0x22,  0x0F,  0xBE,  0xA9,  0x6F,  0xAA,  0xAC,  0x2F, 	/* 1F380 */
+	0x8C,  0xAF,  0x21,  0x0F,  0xBC,  0xAA,  0x45,  0x3C,  0xFE,  0x44,  0xBE,  0x7A,  0x04,  0xBE,  0x79,  0x66, 	/* 1F390 */
+	0xAA,  0xA4,  0x22,  0x0C,  0xB2,  0x21,  0x2F,  0xFC,  0x51,  0x87,  0x2A,  0xAC,  0x63,  0xF8,  0x20,  0x83, 	/* 1F3A0 */
+	0xFE,  0x20,  0x03,  0xFE,  0x55,  0x28,  0xAC,  0xB8,  0x01,  0x0F,  0xBC,  0x52,  0x4F,  0xBC,  0x32,  0x4D, 	/* 1F3B0 */
+	0x3E,  0x32,  0x0F,  0xBE,  0xA9,  0x6D,  0xAA,  0xBC,  0x28,  0x8C,  0xB9,  0x02,  0x07,  0xFE,  0x4A,  0x85, 	/* 1F3C0 */
+	0x7E,  0x74,  0x85,  0xFE,  0x51,  0x05,  0xFC,  0x50,  0x05,  0xFE,  0x95,  0x2A,  0x2C,  0xBA,  0x79,  0xC4, 	/* 1F3D0 */
+	0xA4,  0x7D,  0x81,  0xBC,  0x55,  0x6F,  0xFC,  0x20,  0x83,  0xFE,  0x20,  0x03,  0xFE,  0x55,  0x2A,  0x8C, 	/* 1F3E0 */
+	0xBD,  0x1A,  0x06,  0x5C,  0x4A,  0x47,  0x5C,  0x4A,  0x4F,  0xFE,  0xA1,  0x2B,  0xF0,  0x21,  0x03,  0xFE, 	/* 1F3F0 */
+	0x55,  0x48,  0x18,  0x9A,  0xF9,  0x0A,  0xBC,  0xFA,  0x4A,  0xBC,  0xFA,  0x45,  0x3E,  0xAA,  0x04,  0x3E, 	/* 1F400 */
+	0xF9,  0x6D,  0x2A,  0x34,  0x2C,  0x8C,  0x9B,  0x51,  0x0F,  0xBC,  0x52,  0x4F,  0xBC,  0xAA,  0x4F,  0xBE, 	/* 1F410 */
+	0x52,  0x0F,  0xBE,  0x51,  0x67,  0xAA,  0x50,  0x27,  0xCC,  0x9E,  0x40,  0x4A,  0xEA,  0x40,  0x4F,  0xFE, 	/* 1F420 */
+	0x75,  0x4B,  0xFA,  0x20,  0x83,  0xF8,  0x20,  0x83,  0xFE,  0x2A,  0x44,  0x38,  0xB5,  0x08,  0x00,  0xFE, 	/* 1F430 */
+	0x08,  0x0F,  0xFC,  0x84,  0x4B,  0x14,  0x8A,  0x4E,  0x4C,  0x8A,  0x49,  0x54,  0xA4,  0xCF,  0xFC,  0xB8, 	/* 1F440 */
+	0x21,  0x03,  0xA8,  0x24,  0x4F,  0xFA,  0x89,  0x0D,  0xFC,  0xBD,  0x4A,  0xFC,  0xE9,  0x0D,  0x98,  0x8A, 	/* 1F450 */
+	0x4F,  0xC2,  0xB9,  0x20,  0x83,  0xCA,  0x23,  0xFF,  0xC8,  0x97,  0xAC,  0x4A,  0xAF,  0xA9,  0x6A,  0xAF, 	/* 1F460 */
+	0xCC,  0x4D,  0x95,  0x3F,  0xE1,  0xBD,  0x01,  0x0F,  0xBE,  0xA4,  0x8F,  0xBF,  0x8B,  0x6F,  0xAA,  0xA3, 	/* 1F470 */
+	0x6F,  0xBE,  0x00,  0x07,  0xFC,  0x4A,  0x4F,  0xFE,  0xBF,  0x02,  0x07,  0xFE,  0x49,  0x07,  0xFE,  0x49, 	/* 1F480 */
+	0x27,  0xFE,  0x51,  0x05,  0x10,  0x5D,  0xE5,  0x10,  0x95,  0x23,  0x8E,  0x81,  0x08,  0x01,  0xF8,  0x29, 	/* 1F490 */
+	0x0F,  0xFE,  0x49,  0x07,  0xFC,  0x49,  0x47,  0xFC,  0x51,  0x25,  0xDC,  0x91,  0x23,  0xEE,  0x88,  0x02, 	/* 1F4A0 */
+	0x07,  0xFE,  0x45,  0x07,  0xFE,  0x45,  0x27,  0xFE,  0x51,  0x25,  0xDC,  0x51,  0x2B,  0xEE,  0x82,  0x07, 	/* 1F4B0 */
+	0xFE,  0x8B,  0x02,  0x07,  0xFE,  0x49,  0x47,  0xFC,  0x51,  0x29,  0xCE,  0x3F,  0x40,  0xA8,  0xFF,  0xE0, 	/* 1F4C0 */
+	0xF8,  0x72,  0x60,  0x20,  0x8C,  0x04,  0x07,  0xFE,  0x49,  0x47,  0xFC,  0x51,  0x29,  0xFE,  0x28,  0x42, 	/* 1F4D0 */
+	0xFC,  0x22,  0x0F,  0xFE,  0x09,  0x87,  0x04,  0x91,  0x04,  0x07,  0xFE,  0x4A,  0x47,  0xFC,  0x49,  0x27, 	/* 1F4E0 */
+	0xFE,  0xA0,  0x43,  0xDC,  0x20,  0x43,  0xFC,  0x09,  0x27,  0x0E,  0x92,  0x11,  0x47,  0xD4,  0x53,  0xE7, 	/* 1F4F0 */
+	0xD4,  0x55,  0xC5,  0x54,  0x7D,  0xC6,  0x94,  0x7F,  0xEA,  0x88,  0x3B,  0x46,  0x64,  0x93,  0x10,  0x87, 	/* 1F500 */
+	0xFE,  0x39,  0xC5,  0x6A,  0x7F,  0xE4,  0x90,  0x7F,  0xC4,  0x94,  0x7F,  0xE5,  0xDC,  0x51,  0x2B,  0xCE, 	/* 1F510 */
+	0x95,  0x04,  0x07,  0xFE,  0x49,  0x47,  0xFC,  0x51,  0x2B,  0xFE,  0x2F,  0x42,  0x24,  0x3F,  0xC2,  0x74, 	/* 1F520 */
+	0x2A,  0xC3,  0xFC,  0x97,  0xFB,  0xE0,  0x00,  0xFB,  0xEA,  0xAA,  0x04,  0x07,  0xFE,  0x4A,  0x47,  0xFC, 	/* 1F530 */
+	0x51,  0x05,  0xDC,  0x51,  0x2B,  0xCE,  0x9D,  0x04,  0x07,  0xFE,  0x4A,  0x47,  0xFC,  0x51,  0x0B,  0xEE, 	/* 1F540 */
+	0x28,  0x43,  0xFF,  0x2A,  0x4F,  0x94,  0x28,  0x44,  0x8C,  0x9F,  0x12,  0xA7,  0xDC,  0x57,  0xE7,  0xDC, 	/* 1F550 */
+	0x56,  0xA5,  0x4C,  0x7F,  0xE6,  0xB4,  0x7B,  0x46,  0xDE,  0xA9,  0x47,  0x64,  0xA5,  0x04,  0x0F,  0xFE, 	/* 1F560 */
+	0x24,  0x82,  0x48,  0x55,  0x48,  0xA2,  0x31,  0x8C,  0x66,  0x19,  0x06,  0x60,  0x0B,  0x07,  0x0C,  0xA6, 	/* 1F570 */
+	0x04,  0x07,  0xFC,  0x04,  0x07,  0xFC,  0x04,  0x0F,  0xFE,  0x08,  0x01,  0xF8,  0x69,  0x00,  0x60,  0x1B, 	/* 1F580 */
+	0x0E,  0x0E,  0xA9,  0x21,  0x0F,  0xD0,  0x2B,  0xC6,  0x90,  0x75,  0x0A,  0x7E,  0x39,  0x02,  0x98,  0x6A, 	/* 1F590 */
+	0x49,  0x42,  0x2C,  0x0C,  0x3F,  0xAA,  0x20,  0x0F,  0xFE,  0x28,  0x86,  0x8E,  0x76,  0xAA,  0x2A,  0x3B, 	/* 1F5A0 */
+	0xE2,  0xA2,  0x68,  0x29,  0x0C,  0x2C,  0x0C,  0x3F,  0xAD,  0x22,  0x0F,  0xA0,  0x2B,  0xE6,  0xC2,  0x77, 	/* 1F5B0 */
+	0xAA,  0x2A,  0x3B,  0xC2,  0xA0,  0x6A,  0x29,  0x1E,  0x2C,  0x0C,  0x3F,  0xB8,  0x21,  0x0F,  0xD0,  0x23, 	/* 1F5C0 */
+	0xC7,  0x90,  0x21,  0x0F,  0xFE,  0x21,  0x03,  0x98,  0x6A,  0x49,  0x42,  0x2C,  0x0C,  0x3F,  0xB9,  0x22, 	/* 1F5D0 */
+	0x02,  0x3E,  0xF2,  0x22,  0x36,  0xF7,  0xA2,  0x12,  0xFF,  0xE4,  0xBA,  0xAD,  0x61,  0x12,  0x2C,  0xCC, 	/* 1F5E0 */
+	0x3F,  0xBA,  0x2F,  0xEF,  0x20,  0x24,  0x0F,  0xFE,  0x2A,  0xAF,  0xBA,  0x2A,  0xA7,  0xBA,  0xDA,  0xA3, 	/* 1F5F0 */
+	0xFE,  0x4C,  0x08,  0x3F,  0xBB,  0x02,  0x07,  0xFE,  0x48,  0x84,  0x88,  0x7F,  0xE4,  0x88,  0x5D,  0xC5, 	/* 1F600 */
+	0xDC,  0x6A,  0xAA,  0xAA,  0x88,  0x80,  0x88,  0xBC,  0x04,  0x07,  0xFE,  0x48,  0x87,  0xFE,  0x5A,  0xC6, 	/* 1F610 */
+	0xAA,  0x42,  0x04,  0x48,  0x59,  0x08,  0x64,  0x87,  0xE3,  0x82,  0xBE,  0x04,  0x07,  0xFE,  0x48,  0x87, 	/* 1F620 */
+	0xFE,  0x48,  0x86,  0xAA,  0x6A,  0xA4,  0x38,  0x5E,  0x08,  0x3C,  0xBE,  0x20,  0x1E,  0xBF,  0x02,  0x07, 	/* 1F630 */
+	0xFE,  0x48,  0x87,  0xFE,  0x5D,  0xC6,  0xAA,  0x4F,  0xC4,  0x84,  0x4F,  0xC9,  0xFE,  0x90,  0x21,  0xFE, 	/* 1F640 */
+	0x84,  0x11,  0x07,  0xFC,  0x11,  0x0F,  0xFE,  0x04,  0x03,  0xF8,  0x24,  0x83,  0xF8,  0x24,  0x83,  0xF8, 	/* 1F650 */
+	0x11,  0x8E,  0x06,  0x8C,  0x14,  0x06,  0xBC,  0x44,  0x47,  0xBC,  0xFF,  0xE9,  0x12,  0x7F,  0xC1,  0x10, 	/* 1F660 */
+	0xFF,  0xE2,  0x48,  0x3F,  0x87,  0x1C,  0x8D,  0x01,  0xC3,  0xE0,  0x04,  0x0F,  0xFE,  0x15,  0x06,  0x4C, 	/* 1F670 */
+	0x0A,  0x03,  0x58,  0xD5,  0x60,  0xE0,  0x75,  0xC0,  0x40,  0x8E,  0x1A,  0x0E,  0x3E,  0x24,  0xAF,  0x92, 	/* 1F680 */
+	0x72,  0x2A,  0x4C,  0x2A,  0x03,  0x58,  0xD6,  0xE1,  0xD0,  0x64,  0xC0,  0xC0,  0x8F,  0x19,  0x0E,  0x10, 	/* 1F690 */
+	0x21,  0x0F,  0xDE,  0x71,  0x0A,  0x90,  0x73,  0xCA,  0xE4,  0xEA,  0x47,  0x24,  0xAA,  0x46,  0x3C,  0x90, 	/* 1F6A0 */
+	0x19,  0x0E,  0xFE,  0x26,  0xCF,  0xD4,  0x76,  0xCA,  0xFC,  0x31,  0x06,  0xFE,  0xAD,  0xA7,  0x7E,  0xAC, 	/* 1F6B0 */
+	0x26,  0x46,  0x92,  0x00,  0x07,  0xF8,  0x48,  0x87,  0xF8,  0x48,  0x87,  0xF8,  0x08,  0x07,  0xF8,  0x08, 	/* 1F6C0 */
+	0x0F,  0xFC,  0x52,  0x48,  0x92,  0x94,  0x01,  0x0F,  0x90,  0xAA,  0x8F,  0xA8,  0xAC,  0x4F,  0xBE,  0x20, 	/* 1F6D0 */
+	0x1F,  0xBC,  0x20,  0x4F,  0xC4,  0x50,  0x8A,  0x88,  0x98,  0x7C,  0xA5,  0xC9,  0x74,  0x85,  0x7F,  0x7C, 	/* 1F6E0 */
+	0x81,  0x08,  0x7C,  0x81,  0x1C,  0x1D,  0x4E,  0x12,  0x56,  0x2A,  0xA1,  0x99,  0x7D,  0x45,  0x52,  0x7D, 	/* 1F6F0 */
+	0x05,  0x7E,  0x7D,  0x01,  0x18,  0x7E,  0x41,  0x42,  0xFC,  0x04,  0xA4,  0x49,  0x28,  0x92,  0x9B,  0x12, 	/* 1F700 */
+	0x42,  0xFE,  0xE1,  0x03,  0xFC,  0x24,  0xA3,  0xF8,  0x24,  0x87,  0xFC,  0x04,  0x0F,  0xFE,  0x52,  0x48, 	/* 1F710 */
+	0x92,  0x9C,  0x01,  0x0F,  0x90,  0xAD,  0x4F,  0xD4,  0xAD,  0x4F,  0xFC,  0x21,  0x0F,  0x90,  0x25,  0x2F, 	/* 1F720 */
+	0xD2,  0x55,  0x2A,  0xFE,  0x9D,  0x02,  0x8F,  0xA8,  0xAB,  0xEF,  0xAA,  0xAC,  0xAF,  0xDA,  0x22,  0xAF, 	/* 1F730 */
+	0xAA,  0x25,  0xAF,  0xFA,  0x51,  0x2A,  0xAC,  0x9E,  0x01,  0x0F,  0x90,  0xA9,  0x0F,  0x9E,  0xA9,  0x0F, 	/* 1F740 */
+	0x90,  0x23,  0xCF,  0xA4,  0x22,  0x4F,  0xE4,  0x52,  0x4A,  0xBC,  0xA0,  0x01,  0x0F,  0x90,  0xAF,  0xEF, 	/* 1F750 */
+	0x90,  0xA9,  0x0F,  0xFC,  0x20,  0x0F,  0xBC,  0x22,  0x4F,  0xE4,  0x52,  0x4A,  0xBC,  0xA5,  0x01,  0x0F, 	/* 1F760 */
+	0xFE,  0xA8,  0x0F,  0xBC,  0xAA,  0x4F,  0xA4,  0x23,  0xCF,  0x88,  0x22,  0xCF,  0xAA,  0x54,  0xAA,  0x98, 	/* 1F770 */
+	0xA8,  0x24,  0x81,  0x50,  0xFF,  0xE8,  0x02,  0x3F,  0x83,  0x58,  0x2E,  0x87,  0xFC,  0x04,  0x0F,  0xFE, 	/* 1F780 */
+	0x2A,  0x84,  0x54,  0xAF,  0x00,  0x8F,  0xFE,  0xAA,  0x4F,  0x98,  0xAF,  0xEF,  0x80,  0x23,  0xCF,  0xA4, 	/* 1F790 */
+	0x23,  0xCF,  0xA4,  0x52,  0x4A,  0xBC,  0xB4,  0x24,  0x83,  0x58,  0x55,  0xFB,  0xF2,  0x35,  0x25,  0xFA, 	/* 1F7A0 */
+	0xD5,  0xC5,  0xF4,  0x44,  0xC5,  0xF4,  0x4A,  0x25,  0x52,  0xB6,  0x7F,  0xE5,  0x4A,  0x5F,  0xE5,  0x48, 	/* 1F7B0 */
+	0x5D,  0x49,  0x62,  0x3F,  0x82,  0xD8,  0x7F,  0xC0,  0x40,  0xFF,  0xE5,  0x54,  0xB7,  0x01,  0x0F,  0xFE, 	/* 1F7C0 */
+	0xA9,  0x0F,  0xFE,  0xAD,  0xAF,  0xFE,  0x22,  0x47,  0xBC,  0x22,  0x4F,  0xFC,  0x6A,  0x49,  0x42,  0xB9, 	/* 1F7D0 */
+	0x0A,  0x02,  0xA8,  0xFF,  0xE1,  0x50,  0x24,  0x87,  0xFC,  0xC4,  0x65,  0x54,  0x55,  0x45,  0x54,  0x65, 	/* 1F7E0 */
+	0x44,  0x4C,  0xBB,  0x21,  0x0A,  0x94,  0x71,  0x2F,  0xFE,  0x21,  0x0F,  0xD4,  0xA5,  0x4E,  0xD4,  0xEC, 	/* 1F7F0 */
+	0x8E,  0xD8,  0xA6,  0x4A,  0xC2,  0xBC,  0x20,  0x8A,  0x8A,  0x77,  0xFF,  0xC8,  0x23,  0xEF,  0xAA,  0xAB, 	/* 1F800 */
+	0xEF,  0xAA,  0xFB,  0xEE,  0xAA,  0xAA,  0xA9,  0xA6,  0xBD,  0x7F,  0xC4,  0xA4,  0x7B,  0xC0,  0xA0,  0x7B, 	/* 1F810 */
+	0xC4,  0xA4,  0x7B,  0xC4,  0xA4,  0x7B,  0xC0,  0xA0,  0x08,  0x20,  0x7E,  0x87,  0x11,  0x07,  0xDE,  0x13, 	/* 1F820 */
+	0x4F,  0xC8,  0x29,  0x45,  0xA2,  0x3F,  0x82,  0xA8,  0x7B,  0xC4,  0xA4,  0x7B,  0xD0,  0x7F,  0x88,  0xA9, 	/* 1F830 */
+	0x07,  0x1E,  0xFB,  0x4A,  0xC8,  0xF9,  0x4A,  0xA2,  0x3F,  0x82,  0xA8,  0x7B,  0xC4,  0xA4,  0x7B,  0xD0, 	/* 1F840 */
+	0x7F,  0x8E,  0x5F,  0x45,  0x14,  0x5F,  0x45,  0x14,  0x5F,  0x45,  0x14,  0x7F,  0xC0,  0xA0,  0xFB,  0xE2, 	/* 1F850 */
+	0xA4,  0x4A,  0x44,  0xA4,  0x93,  0x21,  0x0F,  0x90,  0x27,  0xCF,  0x10,  0x01,  0x0F,  0xFC,  0x88,  0x4F, 	/* 1F860 */
+	0xC4,  0x4A,  0x85,  0x10,  0x3A,  0x8C,  0x46,  0x95,  0x20,  0x8F,  0xFE,  0x48,  0x87,  0xBE,  0x51,  0x43, 	/* 1F870 */
+	0x88,  0xEF,  0x61,  0x90,  0x6E,  0x01,  0x98,  0xE2,  0x60,  0xC0,  0xA0,  0xF3,  0xC8,  0x04,  0xFB,  0xC8, 	/* 1F880 */
+	0x04,  0xFF,  0xC4,  0x48,  0x77,  0x84,  0x48,  0x77,  0x84,  0x4A,  0x77,  0x6C,  0xC2,  0xA1,  0x48,  0x42, 	/* 1F890 */
+	0x48,  0x3F,  0x82,  0x48,  0x24,  0x83,  0xF8,  0x24,  0x82,  0x48,  0x3F,  0x84,  0x4A,  0x44,  0x68,  0x42, 	/* 1F8A0 */
+	0xAC,  0x20,  0x85,  0xC8,  0x44,  0x86,  0xFE,  0x46,  0xA7,  0xEA,  0x5B,  0xE7,  0xAA,  0x5A,  0xA7,  0xBF, 	/* 1F8B0 */
+	0x56,  0x19,  0x1F,  0xBB,  0x04,  0x01,  0xF0,  0x11,  0x01,  0xF0,  0x11,  0x03,  0xF8,  0x24,  0x83,  0xF8, 	/* 1F8C0 */
+	0x24,  0x8F,  0xFE,  0x11,  0x06,  0x10,  0xBE,  0x10,  0x03,  0xDE,  0x24,  0x83,  0xC8,  0x24,  0x87,  0xFF, 	/* 1F8D0 */
+	0x54,  0x87,  0xC8,  0x54,  0x8F,  0xE8,  0x28,  0x84,  0x88,  0x8A,  0x04,  0x0F,  0xFE,  0x0A,  0x4F,  0x58, 	/* 1F8E0 */
+	0x55,  0x45,  0x54,  0xA1,  0xA3,  0xF8,  0x20,  0x83,  0xF8,  0x20,  0x84,  0x08,  0x8B,  0x04,  0x0F,  0xFE, 	/* 1F8F0 */
+	0x0A,  0x0F,  0x5E,  0x55,  0x45,  0x54,  0xBF,  0xA4,  0x04,  0x7F,  0xC5,  0x54,  0x64,  0xC8,  0x44,  0x8E, 	/* 1F900 */
+	0x04,  0x0F,  0xFE,  0x0A,  0x0F,  0x5E,  0x55,  0x45,  0x54,  0xAF,  0x62,  0x94,  0x2F,  0x42,  0x94,  0x2F, 	/* 1F910 */
+	0x45,  0x9C,  0x8F,  0x04,  0x0F,  0xFE,  0x0A,  0x6F,  0x58,  0x55,  0x6F,  0xFC,  0x40,  0x47,  0xFC,  0x4A, 	/* 1F920 */
+	0x45,  0xB4,  0x4A,  0x4B,  0xF4,  0x92,  0x04,  0x02,  0x7C,  0x24,  0x0F,  0xFE,  0x49,  0x45,  0xB4,  0x64, 	/* 1F930 */
+	0xC7,  0xFC,  0x49,  0x45,  0xB4,  0x64,  0xC7,  0xFC,  0x94,  0x11,  0x05,  0xD0,  0x51,  0x0F,  0xF2,  0xAD, 	/* 1F940 */
+	0x4D,  0x58,  0x85,  0x0F,  0xD0,  0xAD,  0x0D,  0x50,  0x85,  0x2F,  0xCE,  0x9F,  0x10,  0x05,  0xDE,  0x51, 	/* 1F950 */
+	0x2F,  0xD2,  0xAD,  0xED,  0x52,  0x85,  0x2F,  0xDE,  0xAD,  0x2D,  0x52,  0x85,  0x2F,  0xFF,  0xA0,  0x10, 	/* 1F960 */
+	0x05,  0xFE,  0x50,  0xAF,  0xCA,  0xAD,  0x2D,  0x6C,  0x84,  0x0F,  0xDE,  0xAD,  0x2D,  0x52,  0x85,  0x2F, 	/* 1F970 */
+	0xDE,  0xA1,  0x10,  0x85,  0xC8,  0x51,  0x4F,  0xD4,  0xAF,  0xAD,  0x41,  0x87,  0xEF,  0xCA,  0xAC,  0xAD, 	/* 1F980 */
+	0x4C,  0x84,  0x8F,  0xC8,  0xA2,  0x10,  0x85,  0xC8,  0x51,  0x4F,  0xD4,  0xA7,  0xAE,  0xC0,  0xB7,  0xEF, 	/* 1F990 */
+	0xD2,  0xB5,  0x2E,  0xD2,  0xA5,  0xCF,  0xD0,  0xA3,  0x11,  0x05,  0xD0,  0x51,  0x0F,  0xDE,  0xAE,  0x2D, 	/* 1F9A0 */
+	0x7A,  0x86,  0xAF,  0xEA,  0xAF,  0xAD,  0x42,  0x84,  0x2F,  0xCC,  0xA6,  0x10,  0x05,  0xDE,  0x51,  0x2F, 	/* 1F9B0 */
+	0xDE,  0xAD,  0x2D,  0x52,  0x85,  0xEF,  0xD9,  0xAD,  0x6D,  0x54,  0x85,  0x2F,  0xF9,  0xA7,  0x20,  0x0F, 	/* 1F9C0 */
+	0xFE,  0x21,  0x2F,  0x12,  0x3A,  0x6E,  0x78,  0x24,  0x0F,  0xFE,  0x55,  0x47,  0xFC,  0x64,  0xC7,  0xFC, 	/* 1F9D0 */
+	0xAA,  0x20,  0x0B,  0xBC,  0xA2,  0x4F,  0xE4,  0xAB,  0xCD,  0x88,  0x8A,  0x8F,  0xAE,  0xAA,  0x8D,  0xA8, 	/* 1F9E0 */
+	0x8D,  0x8F,  0x86,  0xAC,  0x10,  0x05,  0xFE,  0x50,  0x8F,  0xFC,  0xAD,  0x4D,  0x54,  0x87,  0xFF,  0xC0, 	/* 1F9F0 */
+	0xAD,  0xED,  0x52,  0x85,  0x2F,  0xDE,  0xB2,  0x20,  0x6B,  0xB8,  0xA0,  0x8F,  0xFE,  0xAA,  0xAD,  0xBE, 	/* 1FA00 */
+	0x88,  0x8F,  0xBE,  0xAA,  0xAD,  0xBE,  0x8A,  0x2F,  0xA6,  0xB6,  0x10,  0x05,  0xFE,  0x52,  0xAF,  0xFE, 	/* 1FA10 */
+	0xAC,  0x0D,  0x5C,  0x84,  0x0F,  0xFE,  0xAD,  0x0D,  0x5E,  0x84,  0x2F,  0xCC,  0xB7,  0x23,  0xEB,  0xA2, 	/* 1FA20 */
+	0xA3,  0xEF,  0xE0,  0xAB,  0xED,  0xA8,  0x8B,  0x4F,  0xBE,  0xAA,  0xAD,  0xBE,  0x8C,  0x8F,  0xBE,  0x8D, 	/* 1FA30 */
+	0x22,  0x02,  0x3E,  0xFE,  0x08,  0xBC,  0x50,  0x4F,  0xFC,  0x4A,  0x07,  0xBC,  0x4A,  0x07,  0xBC,  0x4A, 	/* 1FA40 */
+	0x25,  0x9E,  0x95,  0x04,  0x01,  0xF0,  0xF1,  0xE1,  0xF0,  0x21,  0x0F,  0xBE,  0x50,  0x4F,  0xBC,  0x52, 	/* 1FA50 */
+	0x07,  0x3C,  0x52,  0x25,  0x1E,  0x9C,  0x1F,  0x02,  0x20,  0xFF,  0xC4,  0xA4,  0xFB,  0xC2,  0xA0,  0xFF, 	/* 1FA60 */
+	0xE2,  0xAA,  0xFB,  0x62,  0xFE,  0xE8,  0x00,  0x7E,  0x9D,  0x13,  0x8E,  0x48,  0x29,  0x02,  0xFE,  0xFA, 	/* 1FA70 */
+	0xA2,  0xFE,  0x71,  0xC6,  0xDA,  0xA5,  0x6A,  0xFE,  0x25,  0x02,  0xCE,  0xA0,  0x04,  0x00,  0xA0,  0x31, 	/* 1FA80 */
+	0x8D,  0xF6,  0x00,  0x0E,  0xEE,  0xAA,  0xAF,  0xFE,  0x4A,  0x47,  0xFC,  0x4A,  0x44,  0xAC,  0x81,  0x00, 	/* 1FA90 */
+	0x00,  0x60,  0x06,  0x00,  0x60,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x00,  0x00,  0x40,  0x04,  0x00, 	/* 1FAA0 */
+	0x00,  0x83,  0x08,  0x80,  0x88,  0x08,  0x87,  0xFE,  0x11,  0x01,  0x10,  0x11,  0x01,  0x10,  0xFF,  0xC2, 	/* 1FAB0 */
+	0x20,  0x22,  0x02,  0x20,  0x84,  0x0A,  0x01,  0xE8,  0x2B,  0x82,  0xA8,  0x1A,  0x00,  0xE0,  0x0A,  0x00, 	/* 1FAC0 */
+	0xB0,  0x2A,  0x83,  0xA8,  0x2F,  0x00,  0xA0,  0x85,  0x00,  0x03,  0x02,  0x48,  0x44,  0x88,  0x31,  0x00, 	/* 1FAD0 */
+	0x20,  0x04,  0x00,  0x8C,  0x11,  0x22,  0x12,  0x40,  0xC0,  0x00,  0x86,  0x00,  0x01,  0xC0,  0x22,  0x02, 	/* 1FAE0 */
+	0x20,  0x24,  0x01,  0x84,  0x28,  0x44,  0x48,  0x43,  0x02,  0x30,  0x1C,  0xC0,  0x00,  0x88,  0x00,  0x40, 	/* 1FAF0 */
+	0x08,  0x01,  0x00,  0x10,  0x02,  0x00,  0x20,  0x02,  0x00,  0x20,  0x01,  0x00,  0x10,  0x00,  0x80,  0x04, 	/* 1FB00 */
+	0x89,  0x20,  0x01,  0x00,  0x08,  0x00,  0x80,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x08,  0x00,  0x80, 	/* 1FB10 */
+	0x10,  0x02,  0x00,  0x8A,  0x00,  0x00,  0x00,  0x00,  0x00,  0x40,  0x35,  0x80,  0xE0,  0x04,  0x00,  0xE0, 	/* 1FB20 */
+	0x35,  0x80,  0x40,  0x00,  0x00,  0x00,  0x8B,  0x00,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x07,  0xFC, 	/* 1FB30 */
+	0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x00,  0x00,  0x00,  0x8C,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 1FB40 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x02,  0x00,  0x20,  0x04,  0x00,  0x8D,  0x00,  0x00,  0x00, 	/* 1FB50 */
+	0x00,  0x00,  0x00,  0x00,  0x03,  0xFC,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x8E, 	/* 1FB60 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x06,  0x00,  0x60, 	/* 1FB70 */
+	0x00,  0x00,  0x8F,  0x00,  0x10,  0x02,  0x00,  0x40,  0x08,  0x01,  0x00,  0x20,  0x04,  0x00,  0x80,  0x10, 	/* 1FB80 */
+	0x02,  0x00,  0x40,  0x08,  0x00,  0x90,  0x00,  0x00,  0xE0,  0x11,  0x02,  0x08,  0x20,  0x82,  0x08,  0x20, 	/* 1FB90 */
+	0x82,  0x08,  0x20,  0x81,  0x10,  0x0E,  0x00,  0x00,  0x91,  0x00,  0x00,  0x40,  0x04,  0x01,  0xC0,  0x04, 	/* 1FBA0 */
+	0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x0E,  0x00,  0x00,  0x92,  0x00,  0x00,  0xF0,  0x10, 	/* 1FBB0 */
+	0x81,  0x08,  0x00,  0x80,  0x10,  0x02,  0x00,  0x40,  0x08,  0x01,  0x00,  0x1F,  0x80,  0x00,  0x93,  0x00, 	/* 1FBC0 */
+	0x00,  0xE0,  0x11,  0x00,  0x08,  0x01,  0x00,  0x60,  0x01,  0x00,  0x08,  0x00,  0x81,  0x10,  0x0E,  0x00, 	/* 1FBD0 */
+	0x00,  0x94,  0x00,  0x00,  0x20,  0x06,  0x00,  0xA0,  0x0A,  0x01,  0x20,  0x12,  0x02,  0x20,  0x3F,  0x80, 	/* 1FBE0 */
+	0x20,  0x07,  0x00,  0x00,  0x95,  0x00,  0x01,  0xF8,  0x10,  0x01,  0x00,  0x16,  0x01,  0x90,  0x10,  0x80, 	/* 1FBF0 */
+	0x08,  0x00,  0x81,  0x10,  0x0E,  0x00,  0x00,  0x96,  0x00,  0x00,  0xE0,  0x11,  0x02,  0x00,  0x20,  0x02, 	/* 1FC00 */
+	0xE0,  0x31,  0x02,  0x08,  0x20,  0x81,  0x10,  0x0E,  0x00,  0x00,  0x97,  0x00,  0x01,  0xF8,  0x10,  0x81, 	/* 1FC10 */
+	0x08,  0x01,  0x00,  0x10,  0x02,  0x00,  0x20,  0x04,  0x00,  0x40,  0x04,  0x00,  0x00,  0x98,  0x00,  0x00, 	/* 1FC20 */
+	0xE0,  0x11,  0x02,  0x08,  0x11,  0x00,  0xE0,  0x11,  0x02,  0x08,  0x20,  0x81,  0x10,  0x0E,  0x00,  0x00, 	/* 1FC30 */
+	0x99,  0x00,  0x00,  0xE0,  0x11,  0x02,  0x08,  0x20,  0x81,  0x18,  0x0E,  0x80,  0x08,  0x20,  0x81,  0x10, 	/* 1FC40 */
+	0x0E,  0x00,  0x00,  0x9A,  0x00,  0x00,  0x00,  0x00,  0x00,  0x40,  0x04,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 1FC50 */
+	0x04,  0x00,  0x40,  0x00,  0x00,  0x00,  0x9B,  0x00,  0x00,  0x00,  0x00,  0x00,  0x40,  0x04,  0x00,  0x00, 	/* 1FC60 */
+	0x00,  0x00,  0x00,  0x04,  0x00,  0x40,  0x08,  0x00,  0x00,  0x9C,  0x00,  0x00,  0x0C,  0x03,  0x00,  0xC0, 	/* 1FC70 */
+	0x30,  0x04,  0x00,  0x30,  0x00,  0xC0,  0x03,  0x00,  0x0C,  0x00,  0x00,  0x00,  0x9D,  0x00,  0x00,  0x00, 	/* 1FC80 */
+	0x00,  0x00,  0x00,  0x7F,  0xC0,  0x00,  0x00,  0x07,  0xFC,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x9E, 	/* 1FC90 */
+	0x00,  0x06,  0x00,  0x18,  0x00,  0x60,  0x01,  0x80,  0x04,  0x01,  0x80,  0x60,  0x18,  0x06,  0x00,  0x00, 	/* 1FCA0 */
+	0x00,  0x00,  0x9F,  0x00,  0x00,  0xF0,  0x10,  0x81,  0x08,  0x11,  0x00,  0x20,  0x02,  0x00,  0x20,  0x00, 	/* 1FCB0 */
+	0x00,  0x20,  0x02,  0x00,  0x00,  0xA0,  0x00,  0x00,  0xF0,  0x10,  0x82,  0x74,  0x49,  0xA4,  0x9A,  0x49, 	/* 1FCC0 */
+	0xA4,  0x6C,  0x20,  0x01,  0x8C,  0x07,  0x00,  0x00,  0xA1,  0x00,  0x00,  0x40,  0x04,  0x00,  0xA0,  0x0A, 	/* 1FCD0 */
+	0x01,  0x10,  0x11,  0x01,  0xF0,  0x20,  0x82,  0x08,  0x71,  0xC0,  0x00,  0xA2,  0x00,  0x03,  0xE0,  0x11, 	/* 1FCE0 */
+	0x01,  0x08,  0x11,  0x01,  0xE0,  0x11,  0x01,  0x08,  0x10,  0x81,  0x10,  0x3E,  0x00,  0x00,  0xA3,  0x00, 	/* 1FCF0 */
+	0x00,  0x74,  0x08,  0xC1,  0x04,  0x20,  0x02,  0x00,  0x20,  0x02,  0x00,  0x10,  0x40,  0x88,  0x07,  0x00, 	/* 1FD00 */
+	0x00,  0xA4,  0x00,  0x03,  0xE0,  0x11,  0x01,  0x08,  0x10,  0x81,  0x04,  0x10,  0x41,  0x08,  0x10,  0x81, 	/* 1FD10 */
+	0x10,  0x3E,  0x00,  0x00,  0xA5,  0x00,  0x03,  0xF8,  0x10,  0x41,  0x00,  0x11,  0x01,  0xF0,  0x11,  0x01, 	/* 1FD20 */
+	0x00,  0x10,  0x41,  0x04,  0x3F,  0x80,  0x00,  0xA6,  0x00,  0x03,  0xF8,  0x10,  0x41,  0x00,  0x11,  0x01, 	/* 1FD30 */
+	0xF0,  0x11,  0x01,  0x00,  0x10,  0x01,  0x00,  0x38,  0x00,  0x00,  0xA7,  0x00,  0x00,  0xE8,  0x11,  0x82, 	/* 1FD40 */
+	0x08,  0x40,  0x04,  0x00,  0x47,  0xC4,  0x08,  0x20,  0x81,  0x18,  0x0E,  0x80,  0x00,  0xA8,  0x00,  0x07, 	/* 1FD50 */
+	0x1C,  0x20,  0x82,  0x08,  0x20,  0x83,  0xF8,  0x20,  0x82,  0x08,  0x20,  0x82,  0x08,  0x71,  0xC0,  0x00, 	/* 1FD60 */
+	0xA9,  0x00,  0x00,  0xE0,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40, 	/* 1FD70 */
+	0x0E,  0x00,  0x00,  0xAA,  0x00,  0x00,  0x70,  0x02,  0x00,  0x20,  0x02,  0x00,  0x20,  0x02,  0x00,  0x20, 	/* 1FD80 */
+	0x02,  0x00,  0x20,  0x24,  0x01,  0x80,  0xAB,  0x00,  0x03,  0xB8,  0x11,  0x01,  0x20,  0x14,  0x01,  0x80, 	/* 1FD90 */
+	0x14,  0x01,  0x20,  0x11,  0x01,  0x08,  0x39,  0xC0,  0x00,  0xAC,  0x00,  0x03,  0x80,  0x10,  0x01,  0x00, 	/* 1FDA0 */
+	0x10,  0x01,  0x00,  0x10,  0x01,  0x00,  0x10,  0x41,  0x08,  0x3F,  0x80,  0x00,  0xAD,  0x00,  0x0C,  0x06, 	/* 1FDB0 */
+	0x40,  0x46,  0x0C,  0x60,  0xC5,  0x14,  0x51,  0x44,  0xA4,  0x4A,  0x44,  0x44,  0xE4,  0xE0,  0x00,  0xAE, 	/* 1FDC0 */
+	0x00,  0x03,  0x1C,  0x18,  0x81,  0x48,  0x14,  0x81,  0x28,  0x12,  0x81,  0x18,  0x11,  0x81,  0x08,  0x38, 	/* 1FDD0 */
+	0x80,  0x00,  0xAF,  0x00,  0x00,  0xE0,  0x11,  0x02,  0x08,  0x40,  0x44,  0x04,  0x40,  0x44,  0x04,  0x20, 	/* 1FDE0 */
+	0x81,  0x10,  0x0E,  0x00,  0x00,  0xB0,  0x00,  0x03,  0xE0,  0x11,  0x01,  0x08,  0x10,  0x81,  0x10,  0x1E, 	/* 1FDF0 */
+	0x01,  0x00,  0x10,  0x01,  0x00,  0x38,  0x00,  0x00,  0xB1,  0x00,  0x00,  0xE0,  0x11,  0x02,  0x08,  0x40, 	/* 1FE00 */
+	0x44,  0x04,  0x40,  0x44,  0xC4,  0x22,  0x81,  0x10,  0x0E,  0xA0,  0x06,  0xB2,  0x00,  0x07,  0xE0,  0x21, 	/* 1FE10 */
+	0x02,  0x08,  0x21,  0x03,  0xE0,  0x22,  0x02,  0x10,  0x21,  0x02,  0x10,  0x71,  0x40,  0x08,  0xB3,  0x00, 	/* 1FE20 */
+	0x01,  0xE8,  0x21,  0x82,  0x08,  0x10,  0x00,  0xC0,  0x02,  0x00,  0x10,  0x20,  0x83,  0x08,  0x2F,  0x00, 	/* 1FE30 */
+	0x00,  0xB4,  0x00,  0x07,  0xFC,  0x44,  0x44,  0x44,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00, 	/* 1FE40 */
+	0x40,  0x0E,  0x00,  0x00,  0xB5,  0x00,  0x07,  0x1C,  0x20,  0x82,  0x08,  0x20,  0x82,  0x08,  0x20,  0x82, 	/* 1FE50 */
+	0x08,  0x20,  0x81,  0x10,  0x0E,  0x00,  0x00,  0xB6,  0x00,  0x07,  0x1C,  0x20,  0x82,  0x08,  0x11,  0x01, 	/* 1FE60 */
+	0x10,  0x11,  0x00,  0xA0,  0x0A,  0x00,  0x40,  0x04,  0x00,  0x00,  0xB7,  0x00,  0x0E,  0xEE,  0x44,  0x44, 	/* 1FE70 */
+	0x44,  0x44,  0x42,  0xA8,  0x2A,  0x82,  0xA8,  0x11,  0x01,  0x10,  0x11,  0x00,  0x00,  0xB8,  0x00,  0x07, 	/* 1FE80 */
+	0x1C,  0x20,  0x81,  0x10,  0x0A,  0x00,  0x40,  0x04,  0x00,  0xA0,  0x11,  0x02,  0x08,  0x71,  0xC0,  0x00, 	/* 1FE90 */
+	0xB9,  0x00,  0x07,  0x1C,  0x20,  0x81,  0x10,  0x0A,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40, 	/* 1FEA0 */
+	0x0E,  0x00,  0x00,  0xBA,  0x00,  0x01,  0xFC,  0x10,  0x82,  0x10,  0x02,  0x00,  0x40,  0x04,  0x00,  0x80, 	/* 1FEB0 */
+	0x10,  0x42,  0x04,  0x7F,  0xC0,  0x00,  0xBB,  0x03,  0xC0,  0x20,  0x02,  0x00,  0x20,  0x02,  0x00,  0x20, 	/* 1FEC0 */
+	0x02,  0x00,  0x20,  0x02,  0x00,  0x20,  0x02,  0x00,  0x3C,  0xBC,  0x80,  0x04,  0x00,  0x20,  0x01,  0x00, 	/* 1FED0 */
+	0x08,  0x00,  0x40,  0x02,  0x00,  0x10,  0x00,  0x80,  0x04,  0x00,  0x20,  0x01,  0xBD,  0x3C,  0x00,  0x40, 	/* 1FEE0 */
+	0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x03,  0xC0,  0xBE, 	/* 1FEF0 */
+	0x02,  0x00,  0x50,  0x08,  0x80,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 1FF00 */
+	0x00,  0x00,  0xBF,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 1FF10 */
+	0x00,  0x00,  0x00,  0x0F,  0xFF,  0x80,  0x08,  0x00,  0x40,  0x02,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 1FF20 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x81,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x06, 	/* 1FF30 */
+	0x00,  0x90,  0x07,  0x00,  0x90,  0x11,  0x01,  0x20,  0x0D,  0x80,  0x00,  0x82,  0x00,  0x03,  0x00,  0x10, 	/* 1FF40 */
+	0x01,  0x00,  0x16,  0x01,  0x90,  0x10,  0x81,  0x08,  0x10,  0x81,  0x90,  0x16,  0x00,  0x00,  0x83,  0x00, 	/* 1FF50 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x0E,  0x01,  0x10,  0x20,  0x02,  0x00,  0x20,  0x01,  0x10,  0x0E,  0x00, 	/* 1FF60 */
+	0x00,  0x84,  0x00,  0x00,  0x30,  0x01,  0x00,  0x10,  0x0D,  0x01,  0x30,  0x21,  0x02,  0x10,  0x21,  0x01, 	/* 1FF70 */
+	0x30,  0x0D,  0x80,  0x00,  0x85,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0C,  0x01,  0x20,  0x21,  0x03, 	/* 1FF80 */
+	0xF0,  0x20,  0x01,  0x10,  0x0E,  0x00,  0x00,  0x86,  0x00,  0x00,  0x60,  0x09,  0x00,  0x80,  0x3E,  0x00, 	/* 1FF90 */
+	0x80,  0x08,  0x00,  0x80,  0x08,  0x00,  0x80,  0x1C,  0x00,  0x00,  0x87,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 1FFA0 */
+	0x00,  0x0E,  0x81,  0x10,  0x11,  0x00,  0xE0,  0x08,  0x01,  0xF0,  0x30,  0x80,  0xF0,  0x88,  0x00,  0x03, 	/* 1FFB0 */
+	0x00,  0x10,  0x01,  0x00,  0x16,  0x01,  0x90,  0x11,  0x01,  0x10,  0x11,  0x01,  0x10,  0x3B,  0x80,  0x00, 	/* 1FFC0 */
+	0x89,  0x00,  0x00,  0xC0,  0x04,  0x00,  0x00,  0x0C,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40, 	/* 1FFD0 */
+	0x0E,  0x00,  0x00,  0x8A,  0x00,  0x00,  0x60,  0x02,  0x00,  0x00,  0x06,  0x00,  0x20,  0x02,  0x00,  0x20, 	/* 1FFE0 */
+	0x02,  0x00,  0x20,  0x22,  0x01,  0xC0,  0x8B,  0x00,  0x03,  0x00,  0x10,  0x01,  0x00,  0x17,  0x01,  0x20, 	/* 1FFF0 */
+	0x14,  0x01,  0xC0,  0x12,  0x01,  0x10,  0x3B,  0x80,  0x00,  0x8C,  0x00,  0x00,  0xC0,  0x04,  0x00,  0x40, 	/* 20000 */
+	0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x04,  0x00,  0x40,  0x0E,  0x00,  0x00,  0x8D,  0x00,  0x00,  0x00, 	/* 20010 */
+	0x00,  0x00,  0x00,  0x59,  0x82,  0x64,  0x24,  0x42,  0x44,  0x24,  0x42,  0x44,  0x6E,  0xE0,  0x00,  0x8E, 	/* 20020 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x36,  0x01,  0x90,  0x11,  0x01,  0x10,  0x11,  0x01,  0x10,  0x3B, 	/* 20030 */
+	0x80,  0x00,  0x8F,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0E,  0x01,  0x10,  0x20,  0x82,  0x08,  0x20, 	/* 20040 */
+	0x81,  0x10,  0x0E,  0x00,  0x00,  0x90,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x36,  0x01,  0x90,  0x10, 	/* 20050 */
+	0x81,  0x08,  0x19,  0x01,  0x60,  0x10,  0x03,  0x80,  0x91,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0D, 	/* 20060 */
+	0x81,  0x30,  0x21,  0x02,  0x10,  0x13,  0x00,  0xD0,  0x01,  0x00,  0x38,  0x92,  0x00,  0x00,  0x00,  0x00, 	/* 20070 */
+	0x00,  0x00,  0x1B,  0x00,  0xC8,  0x08,  0x00,  0x80,  0x08,  0x00,  0x80,  0x1C,  0x00,  0x00,  0x93,  0x00, 	/* 20080 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x0E,  0x01,  0x10,  0x10,  0x00,  0xE0,  0x01,  0x01,  0x10,  0x0E,  0x00, 	/* 20090 */
+	0x00,  0x94,  0x00,  0x00,  0x80,  0x08,  0x00,  0x80,  0x3E,  0x00,  0x80,  0x08,  0x00,  0x80,  0x08,  0x00, 	/* 200A0 */
+	0x90,  0x06,  0x00,  0x00,  0x95,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x3B,  0x81,  0x10,  0x11,  0x01, 	/* 200B0 */
+	0x10,  0x11,  0x01,  0x10,  0x0E,  0x80,  0x00,  0x96,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x73,  0x82, 	/* 200C0 */
+	0x10,  0x11,  0x01,  0x20,  0x0A,  0x00,  0xC0,  0x04,  0x00,  0x00,  0x97,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 200D0 */
+	0x00,  0xEE,  0xE4,  0x44,  0x44,  0x42,  0xA8,  0x2A,  0x81,  0x10,  0x11,  0x00,  0x00,  0x98,  0x00,  0x00, 	/* 200E0 */
+	0x00,  0x00,  0x00,  0x00,  0x3B,  0x81,  0x10,  0x0A,  0x00,  0x40,  0x0A,  0x01,  0x10,  0x3B,  0x80,  0x00, 	/* 200F0 */
+	0x99,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x3B,  0x81,  0x10,  0x0A,  0x00,  0xA0,  0x04,  0x00,  0x40, 	/* 20100 */
+	0x24,  0x01,  0x80,  0x9A,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x1F,  0x02,  0x20,  0x04,  0x00,  0x40, 	/* 20110 */
+	0x08,  0x81,  0x10,  0x3F,  0x00,  0x00,  0x9B,  0x00,  0x40,  0x08,  0x00,  0x80,  0x08,  0x00,  0x80,  0x10, 	/* 20120 */
+	0x00,  0x80,  0x08,  0x00,  0x80,  0x08,  0x00,  0x80,  0x04,  0x9C,  0x02,  0x00,  0x20,  0x02,  0x00,  0x20, 	/* 20130 */
+	0x02,  0x00,  0x20,  0x02,  0x00,  0x20,  0x02,  0x00,  0x20,  0x02,  0x00,  0x20,  0x9D,  0x20,  0x01,  0x00, 	/* 20140 */
+	0x10,  0x01,  0x00,  0x10,  0x00,  0x80,  0x10,  0x01,  0x00,  0x10,  0x01,  0x00,  0x10,  0x02,  0x00,  0x9E, 	/* 20150 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x38,  0x04,  0x40,  0x02,  0x20,  0x1C,  0x00,  0x00,  0x00,  0x00, 	/* 20160 */
+	0x00,  0x00,  0xA0,  0x00,  0x00,  0x00,  0x00,  0x00,  0x40,  0x1C,  0x02,  0x60,  0x69,  0x06,  0x80,  0x69, 	/* 20170 */
+	0x03,  0x20,  0x1C,  0x01,  0x00,  0xA1,  0x00,  0x00,  0x30,  0x04,  0x80,  0x40,  0x0C,  0x00,  0xC0,  0x7F, 	/* 20180 */
+	0x00,  0xC0,  0x38,  0x24,  0xE4,  0x33,  0x80,  0x00,  0xA2,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 20190 */
+	0x07,  0xFE,  0x00,  0x20,  0x02,  0x00,  0x20,  0x00,  0x00,  0x00,  0x00,  0xA3,  0xFF,  0xF0,  0x00,  0x00, 	/* 201A0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xA5,  0x00, 	/* 201B0 */
+	0x07,  0x1C,  0x20,  0x81,  0x10,  0x3F,  0x80,  0xA0,  0x3F,  0x80,  0x40,  0x04,  0x00,  0x40,  0x0E,  0x00, 	/* 201C0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x03,  0x7A,  0x04,  's',   'h',   'i',   'n',   'o',   'n',   'o',   'm', 	/* 201D0 */
+	'e',   '_',   'f',   'o',   'n',   't',   '1',   '6',   '.',   'f',   'n',   't',   0x00,  0x00,  0x00,  0x00, 	/* 201E0 */
+	0x00,  0x00,  0x00,  0x00,  'F',   'O',   'N',   'T',   's',   'h',   'i',   'n',   'o',   'n',   'o',   'm', 	/* 201F0 */
+	'e',   '_',   'f',   'o',   'n',   't',   '1',   '6',   0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 20200 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xE3,  0x79,  0x03,  0x00,  0x01,  0x00,  0x00,  0x00, 	/* 20210 */
+	0x20,  0x00,  0x00,  0x00,  0x58,  0x00,  0x00,  0x00,  0x06,  0x00,  0x00,  0x00,  0x64,  0x00,  0x00,  0x00, 	/* 20220 */
+	0x09,  0x00,  0x00,  0x00,  0x76,  0x00,  0x00,  0x00,  0x57,  0x01,  0x00,  0x00,  0x24,  0x03,  0x00,  0x00, 	/* 20230 */
+	0x7A,  0x00,  0x00,  0x00,  0xDE,  0x12,  0x00,  0x00,  0x65,  0x1A,  0x00,  0x00,  0xC2,  0x06,  0xC3,  0x02, 	/* 20240 */
+	0xCE,  0x27,  0xCF,  0x09,  0xD0,  0x31,  0xD1,  0x11,  0xE2,  0x0E,  0xE3,  0x04,  0xE4,  0x08,  0xE5,  0x40, 	/* 20250 */
+	0xE6,  0x40,  0xE7,  0x3F,  0xE8,  0x3F,  0xE9,  0x3C,  0xEF,  0x03,  0x80,  0x0E,  0x84,  0x02,  0x86,  0x04, 	/* 20260 */
+	0x87,  0x02,  0x88,  0x14,  0x89,  0x07,  0x8A,  0x05,  0x8C,  0x01,  0x94,  0x1E,  0x95,  0x02,  0x96,  0x06, 	/* 20270 */
+	0x97,  0x06,  0x98,  0x02,  0x99,  0x05,  0x80,  0x15,  0x81,  0x3F,  0x82,  0x37,  0x83,  0x3B,  0xB8,  0x1F, 	/* 20280 */
+	0xB9,  0x13,  0xBA,  0x23,  0xBB,  0x1E,  0xBC,  0x13,  0xBD,  0x1A,  0xBE,  0x14,  0xBF,  0x1A,  0x80,  0x1A, 	/* 20290 */
+	0x81,  0x12,  0x82,  0x0F,  0x83,  0x13,  0x84,  0x14,  0x85,  0x21,  0x86,  0x24,  0x87,  0x1B,  0x88,  0x1B, 	/* 202A0 */
+	0x89,  0x1A,  0x8A,  0x17,  0x8B,  0x1C,  0x8C,  0x1A,  0x8D,  0x21,  0x8E,  0x11,  0x8F,  0x24,  0x90,  0x1E, 	/* 202B0 */
+	0x91,  0x14,  0x92,  0x16,  0x93,  0x13,  0x94,  0x0E,  0x95,  0x0F,  0x96,  0x17,  0x97,  0x0D,  0x98,  0x0E, 	/* 202C0 */
+	0x99,  0x0D,  0x9A,  0x0D,  0x9B,  0x17,  0x9C,  0x16,  0x9D,  0x0E,  0x9E,  0x0C,  0x9F,  0x12,  0xA0,  0x13, 	/* 202D0 */
+	0xA1,  0x14,  0xA2,  0x0F,  0xA3,  0x1D,  0xA4,  0x1A,  0xA5,  0x1A,  0xA6,  0x13,  0xA7,  0x12,  0xA8,  0x0F, 	/* 202E0 */
+	0xA9,  0x0A,  0xAA,  0x06,  0xAB,  0x0E,  0xAC,  0x0B,  0xAD,  0x1A,  0xAE,  0x21,  0xAF,  0x22,  0xB0,  0x1F, 	/* 202F0 */
+	0xB1,  0x19,  0xB2,  0x11,  0xB3,  0x0F,  0xB4,  0x0F,  0xB5,  0x0B,  0xB6,  0x0E,  0xB7,  0x1A,  0xB8,  0x15, 	/* 20300 */
+	0xB9,  0x1C,  0xBA,  0x14,  0xBB,  0x21,  0xBC,  0x1F,  0xBD,  0x1B,  0xBE,  0x1F,  0xBF,  0x14,  0x80,  0x16, 	/* 20310 */
+	0x81,  0x1C,  0x82,  0x1C,  0x83,  0x17,  0x84,  0x16,  0x85,  0x20,  0x86,  0x14,  0x87,  0x16,  0x88,  0x1D, 	/* 20320 */
+	0x89,  0x17,  0x8A,  0x19,  0x8B,  0x22,  0x8C,  0x11,  0x8D,  0x12,  0x8E,  0x1C,  0x8F,  0x12,  0x90,  0x0F, 	/* 20330 */
+	0x91,  0x09,  0x92,  0x12,  0x93,  0x18,  0x94,  0x14,  0x95,  0x16,  0x96,  0x1B,  0x97,  0x19,  0x98,  0x17, 	/* 20340 */
+	0x99,  0x17,  0x9A,  0x15,  0x9B,  0x18,  0x9C,  0x1F,  0x9D,  0x1F,  0x9E,  0x17,  0x9F,  0x1C,  0xA0,  0x12, 	/* 20350 */
+	0xA1,  0x17,  0xA2,  0x1A,  0xA3,  0x16,  0xA4,  0x1C,  0xA5,  0x1A,  0xA6,  0x12,  0xA7,  0x17,  0xA8,  0x1A, 	/* 20360 */
+	0xA9,  0x0D,  0xAA,  0x10,  0xAB,  0x0D,  0xAC,  0x12,  0xAD,  0x19,  0xAE,  0x1A,  0xAF,  0x10,  0xB0,  0x0D, 	/* 20370 */
+	0xB1,  0x15,  0xB2,  0x1B,  0xB3,  0x16,  0xB4,  0x14,  0xB5,  0x11,  0xB6,  0x0E,  0xB7,  0x1B,  0xB8,  0x1C, 	/* 20380 */
+	0xB9,  0x10,  0xBA,  0x13,  0xBB,  0x14,  0xBC,  0x13,  0xBD,  0x11,  0xBE,  0x0F,  0xBF,  0x16,  0x80,  0x12, 	/* 20390 */
+	0x81,  0x0A,  0x82,  0x0D,  0x83,  0x09,  0x84,  0x09,  0x85,  0x0F,  0x86,  0x0D,  0x87,  0x16,  0x88,  0x12, 	/* 203A0 */
+	0x89,  0x15,  0x8A,  0x0E,  0x8B,  0x15,  0x8C,  0x12,  0x8D,  0x0E,  0x8E,  0x09,  0x8F,  0x0F,  0x90,  0x0D, 	/* 203B0 */
+	0x91,  0x12,  0x92,  0x07,  0x93,  0x11,  0x94,  0x1D,  0x95,  0x20,  0x96,  0x18,  0x97,  0x18,  0x98,  0x0D, 	/* 203C0 */
+	0x99,  0x19,  0x9A,  0x15,  0x9B,  0x19,  0x9C,  0x13,  0x9D,  0x0D,  0x9E,  0x10,  0x9F,  0x10,  0xA0,  0x0D, 	/* 203D0 */
+	0xA1,  0x08,  0xA2,  0x14,  0xA3,  0x0F,  0xA4,  0x0D,  0xA5,  0x16,  0xA6,  0x14,  0xA7,  0x12,  0xA8,  0x16, 	/* 203E0 */
+	0xA9,  0x16,  0xAA,  0x13,  0xAB,  0x20,  0xAC,  0x15,  0xAD,  0x17,  0xAE,  0x15,  0xAF,  0x13,  0xB0,  0x13, 	/* 203F0 */
+	0xB1,  0x11,  0xB2,  0x1C,  0xB3,  0x16,  0xB4,  0x1F,  0xB5,  0x1A,  0xB6,  0x1A,  0xB7,  0x16,  0xB8,  0x19, 	/* 20400 */
+	0xB9,  0x18,  0xBA,  0x0E,  0xBC,  0x03,  0xBD,  0x17,  0xBE,  0x18,  0xBF,  0x12,  0x80,  0x16,  0x81,  0x16, 	/* 20410 */
+	0x82,  0x19,  0x83,  0x14,  0x84,  0x10,  0x85,  0x14,  0x86,  0x18,  0x87,  0x19,  0x88,  0x1E,  0x89,  0x15, 	/* 20420 */
+	0x8A,  0x12,  0x8B,  0x17,  0x8C,  0x16,  0x8D,  0x0D,  0x8E,  0x12,  0x8F,  0x15,  0x90,  0x12,  0x91,  0x14, 	/* 20430 */
+	0x92,  0x10,  0x93,  0x11,  0x94,  0x10,  0x95,  0x13,  0x96,  0x17,  0x97,  0x11,  0x98,  0x0E,  0x99,  0x0E, 	/* 20440 */
+	0x9A,  0x0D,  0x9B,  0x16,  0x9C,  0x13,  0x9D,  0x13,  0x9E,  0x0A,  0x9F,  0x0F,  0xA0,  0x0F,  0xA1,  0x19, 	/* 20450 */
+	0xA2,  0x14,  0xA3,  0x17,  0xA4,  0x10,  0xA5,  0x13,  0xA6,  0x19,  0xA7,  0x0A,  0xA8,  0x1A,  0xA9,  0x18, 	/* 20460 */
+	0xAA,  0x1B,  0xAB,  0x1C,  0xAC,  0x18,  0xAD,  0x15,  0xAE,  0x0B,  0xB0,  0x03,  0xB1,  0x12,  0xB2,  0x22, 	/* 20470 */
+	0xB3,  0x1B,  0xB4,  0x0C,  0xB5,  0x0A,  0xB6,  0x09,  0xB7,  0x13,  0xB8,  0x0C,  0xB9,  0x12,  0xBA,  0x13, 	/* 20480 */
+	0xBB,  0x12,  0xBC,  0x18,  0xBD,  0x0F,  0xBE,  0x12,  0xBF,  0x16,  0x80,  0x23,  0x81,  0x27,  0x82,  0x12, 	/* 20490 */
+	0x83,  0x0C,  0x84,  0x06,  0x85,  0x15,  0x86,  0x12,  0x87,  0x1B,  0x88,  0x0B,  0x89,  0x0F,  0x8A,  0x0E, 	/* 204A0 */
+	0x8B,  0x0B,  0x8C,  0x13,  0x8D,  0x0D,  0x8E,  0x0B,  0x8F,  0x0C,  0x90,  0x0E,  0x91,  0x12,  0x92,  0x01, 	/* 204B0 */
+	0x95,  0x01,  0x96,  0x1B,  0x97,  0x0D,  0x98,  0x09,  0x99,  0x1D,  0x9A,  0x1E,  0x9B,  0x1C,  0x9C,  0x18, 	/* 204C0 */
+	0x9D,  0x18,  0x9E,  0x12,  0x9F,  0x0E,  0xA0,  0x19,  0xA1,  0x12,  0xA2,  0x05,  0xA3,  0x11,  0xA4,  0x14, 	/* 204D0 */
+	0xA5,  0x0A,  0xA6,  0x0C,  0xA7,  0x15,  0xA8,  0x0C,  0xA9,  0x10,  0xAA,  0x05,  0xAB,  0x15,  0xAC,  0x11, 	/* 204E0 */
+	0xAD,  0x0E,  0xAE,  0x10,  0xAF,  0x13,  0xB0,  0x19,  0xB1,  0x0A,  0xB3,  0x09,  0xB4,  0x13,  0xB5,  0x11, 	/* 204F0 */
+	0xB6,  0x0D,  0xB7,  0x0F,  0xB8,  0x03,  0xB9,  0x05,  0xBA,  0x17,  0xBB,  0x19,  0xBC,  0x0A,  0xBD,  0x12, 	/* 20500 */
+	0xBE,  0x05,  0xBC,  0x3D,  0xBD,  0x1F,  0xBF,  0x05,  0xA7,  0x01,  0x80,  0x02,  0x40,  0x04,  0x20,  0x06, 	/* 20510 */
+	0x20,  0x03,  0x00,  0x03,  0x80,  0x04,  0xC0,  0x04,  0x60,  0x06,  0x20,  0x03,  0x20,  0x01,  0xC0,  0x00, 	/* 20520 */
+	0xC0,  0x04,  0x60,  0x04,  0x20,  0x02,  0x40,  0x01,  0x80,  0xA8,  0x06,  0x60,  0x06,  0x60,  0x00,  0x00, 	/* 20530 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 20540 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xB0,  0x00,  0x00,  0x30,  0x00,  0x48, 	/* 20550 */
+	0x00,  0x48,  0x00,  0x30,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 20560 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xB1,  0x00,  0x00,  0x00,  0x00, 	/* 20570 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80, 	/* 20580 */
+	0x00,  0x80,  0x00,  0x00,  0x00,  0x00,  0x1F,  0xFE,  0x00,  0x00,  0x00,  0x00,  0xB4,  0x00,  0x80,  0x00, 	/* 20590 */
+	0x80,  0x01,  0x00,  0x02,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 205A0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xB6,  0x00,  0x00, 	/* 205B0 */
+	0x07,  0xE0,  0x0F,  0x20,  0x1F,  0x20,  0x1F,  0x20,  0x0F,  0x20,  0x07,  0x20,  0x01,  0x20,  0x01,  0x20, 	/* 205C0 */
+	0x01,  0x20,  0x01,  0x20,  0x01,  0x20,  0x01,  0x20,  0x01,  0x20,  0x01,  0x20,  0x01,  0x20,  0x97,  0x00, 	/* 205D0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x10,  0x08,  0x08,  0x10,  0x04,  0x20,  0x02,  0x40,  0x01,  0x80,  0x01, 	/* 205E0 */
+	0x80,  0x02,  0x40,  0x04,  0x20,  0x08,  0x10,  0x10,  0x08,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xB7, 	/* 205F0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x01,  0x80,  0x01,  0x80,  0x00,  0x00,  0x00,  0x00,  0x3F,  0xFC, 	/* 20600 */
+	0x00,  0x00,  0x00,  0x00,  0x01,  0x80,  0x01,  0x80,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 20610 */
+	0x91,  0x00,  0x00,  0x00,  0x80,  0x00,  0x80,  0x01,  0x40,  0x01,  0x40,  0x02,  0x20,  0x02,  0x20,  0x04, 	/* 20620 */
+	0x10,  0x07,  0xF0,  0x04,  0x10,  0x08,  0x08,  0x08,  0x08,  0x10,  0x04,  0x38,  0x0E,  0x00,  0x00,  0x00, 	/* 20630 */
+	0x00,  0x92,  0x00,  0x00,  0x3F,  0xE0,  0x08,  0x10,  0x08,  0x08,  0x08,  0x08,  0x08,  0x10,  0x0F,  0xE0, 	/* 20640 */
+	0x08,  0x10,  0x08,  0x08,  0x08,  0x04,  0x08,  0x04,  0x08,  0x08,  0x08,  0x30,  0x3F,  0xC0,  0x00,  0x00, 	/* 20650 */
+	0x00,  0x00,  0x93,  0x00,  0x00,  0x1F,  0xF8,  0x04,  0x08,  0x04,  0x04,  0x04,  0x00,  0x04,  0x00,  0x04, 	/* 20660 */
+	0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x0E,  0x00,  0x00, 	/* 20670 */
+	0x00,  0x00,  0x00,  0x94,  0x00,  0x00,  0x01,  0x00,  0x01,  0x00,  0x02,  0x80,  0x02,  0x80,  0x04,  0x40, 	/* 20680 */
+	0x04,  0x40,  0x08,  0x20,  0x08,  0x20,  0x08,  0x10,  0x10,  0x10,  0x10,  0x10,  0x20,  0x08,  0x7F,  0xFC, 	/* 20690 */
+	0x00,  0x00,  0x00,  0x00,  0x95,  0x00,  0x00,  0x3F,  0xF8,  0x08,  0x08,  0x08,  0x04,  0x08,  0x00,  0x08, 	/* 206A0 */
+	0x00,  0x08,  0x40,  0x0F,  0xC0,  0x08,  0x40,  0x08,  0x00,  0x08,  0x00,  0x08,  0x04,  0x08,  0x08,  0x3F, 	/* 206B0 */
+	0xF8,  0x00,  0x00,  0x00,  0x00,  0x96,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x10,  0x10,  0x20,  0x00,  0x40, 	/* 206C0 */
+	0x00,  0x40,  0x00,  0x80,  0x01,  0x00,  0x01,  0x00,  0x02,  0x00,  0x04,  0x00,  0x04,  0x08,  0x08,  0x08, 	/* 206D0 */
+	0x1F,  0xF8,  0x00,  0x00,  0x00,  0x00,  0x97,  0x00,  0x00,  0x38,  0x1C,  0x10,  0x08,  0x10,  0x08,  0x10, 	/* 206E0 */
+	0x08,  0x10,  0x08,  0x10,  0x08,  0x1F,  0xF8,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10, 	/* 206F0 */
+	0x08,  0x38,  0x1C,  0x00,  0x00,  0x00,  0x00,  0x98,  0x00,  0x00,  0x03,  0xC0,  0x0C,  0x30,  0x18,  0x18, 	/* 20700 */
+	0x10,  0x08,  0x20,  0x04,  0x24,  0x24,  0x27,  0xE4,  0x24,  0x24,  0x20,  0x04,  0x10,  0x08,  0x18,  0x18, 	/* 20710 */
+	0x0C,  0x30,  0x03,  0xC0,  0x00,  0x00,  0x00,  0x00,  0x99,  0x00,  0x00,  0x03,  0x80,  0x01,  0x00,  0x01, 	/* 20720 */
+	0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01, 	/* 20730 */
+	0x00,  0x01,  0x00,  0x03,  0x80,  0x00,  0x00,  0x00,  0x00,  0x9A,  0x00,  0x00,  0x1C,  0x1C,  0x08,  0x10, 	/* 20740 */
+	0x08,  0x20,  0x08,  0x40,  0x08,  0x80,  0x09,  0x00,  0x0B,  0x00,  0x0C,  0x80,  0x08,  0x40,  0x08,  0x20, 	/* 20750 */
+	0x08,  0x10,  0x08,  0x08,  0x1C,  0x0E,  0x00,  0x00,  0x00,  0x00,  0x9B,  0x00,  0x00,  0x00,  0x80,  0x00, 	/* 20760 */
+	0x80,  0x01,  0x40,  0x01,  0x40,  0x02,  0x20,  0x02,  0x20,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x08, 	/* 20770 */
+	0x08,  0x08,  0x08,  0x10,  0x04,  0x38,  0x0E,  0x00,  0x00,  0x00,  0x00,  0x9C,  0x00,  0x00,  0x60,  0x0C, 	/* 20780 */
+	0x20,  0x08,  0x30,  0x18,  0x30,  0x18,  0x28,  0x28,  0x28,  0x28,  0x24,  0x48,  0x24,  0x48,  0x24,  0x48, 	/* 20790 */
+	0x22,  0x88,  0x22,  0x88,  0x21,  0x08,  0x71,  0x1C,  0x00,  0x00,  0x00,  0x00,  0x9D,  0x00,  0x00,  0x38, 	/* 207A0 */
+	0x1C,  0x18,  0x08,  0x14,  0x08,  0x14,  0x08,  0x12,  0x08,  0x11,  0x08,  0x11,  0x08,  0x10,  0x88,  0x10, 	/* 207B0 */
+	0x48,  0x10,  0x48,  0x10,  0x28,  0x10,  0x18,  0x38,  0x08,  0x00,  0x00,  0x00,  0x00,  0x9E,  0x00,  0x00, 	/* 207C0 */
+	0x3F,  0xFC,  0x20,  0x04,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x10,  0x08,  0x1F,  0xF8,  0x10,  0x08, 	/* 207D0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x20,  0x04,  0x3F,  0xFC,  0x00,  0x00,  0x00,  0x00,  0x9F,  0x00, 	/* 207E0 */
+	0x00,  0x03,  0xC0,  0x0C,  0x30,  0x18,  0x18,  0x10,  0x08,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20, 	/* 207F0 */
+	0x04,  0x20,  0x04,  0x10,  0x08,  0x18,  0x18,  0x0C,  0x30,  0x03,  0xC0,  0x00,  0x00,  0x00,  0x00,  0xA0, 	/* 20800 */
+	0x00,  0x00,  0x1F,  0xF8,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10, 	/* 20810 */
+	0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x1C,  0x38,  0x00,  0x00,  0x00,  0x00, 	/* 20820 */
+	0xA1,  0x00,  0x00,  0x1F,  0xE0,  0x04,  0x18,  0x04,  0x04,  0x04,  0x04,  0x04,  0x04,  0x04,  0x18,  0x07, 	/* 20830 */
+	0xE0,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x0E,  0x00,  0x00,  0x00,  0x00, 	/* 20840 */
+	0x00,  0xA3,  0x00,  0x00,  0x1F,  0xF0,  0x08,  0x10,  0x04,  0x08,  0x02,  0x00,  0x01,  0x00,  0x00,  0x80, 	/* 20850 */
+	0x00,  0xC0,  0x00,  0x80,  0x01,  0x00,  0x02,  0x00,  0x04,  0x08,  0x08,  0x08,  0x1F,  0xF8,  0x00,  0x00, 	/* 20860 */
+	0x00,  0x00,  0xA4,  0x00,  0x00,  0x3F,  0xF8,  0x21,  0x08,  0x41,  0x04,  0x01,  0x00,  0x01,  0x00,  0x01, 	/* 20870 */
+	0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x03,  0x80,  0x00, 	/* 20880 */
+	0x00,  0x00,  0x00,  0xA5,  0x00,  0x00,  0x0E,  0x38,  0x11,  0x44,  0x20,  0x82,  0x00,  0x80,  0x00,  0x80, 	/* 20890 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x01,  0xC0, 	/* 208A0 */
+	0x00,  0x00,  0x00,  0x00,  0xA6,  0x00,  0x00,  0x01,  0xC0,  0x00,  0x80,  0x03,  0xE0,  0x0C,  0x98,  0x08, 	/* 208B0 */
+	0x88,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x08,  0x88,  0x0C,  0x98,  0x03,  0xE0,  0x00,  0x80,  0x01, 	/* 208C0 */
+	0xC0,  0x00,  0x00,  0x00,  0x00,  0xA7,  0x00,  0x00,  0x38,  0x38,  0x10,  0x10,  0x08,  0x20,  0x04,  0x40, 	/* 208D0 */
+	0x04,  0x40,  0x02,  0x80,  0x01,  0x00,  0x02,  0x80,  0x04,  0x40,  0x04,  0x40,  0x08,  0x20,  0x10,  0x10, 	/* 208E0 */
+	0x38,  0x38,  0x00,  0x00,  0x00,  0x00,  0xA8,  0x00,  0x00,  0x03,  0x80,  0x61,  0x0C,  0x91,  0x12,  0x11, 	/* 208F0 */
+	0x10,  0x11,  0x10,  0x11,  0x10,  0x11,  0x10,  0x19,  0x30,  0x09,  0x20,  0x07,  0xC0,  0x01,  0x00,  0x01, 	/* 20900 */
+	0x00,  0x03,  0x80,  0x00,  0x00,  0x00,  0x00,  0xA9,  0x00,  0x00,  0x01,  0xC0,  0x06,  0x30,  0x0C,  0x18, 	/* 20910 */
+	0x08,  0x08,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x08,  0x08,  0x0C,  0x18,  0x06,  0x30,  0x11,  0x44, 	/* 20920 */
+	0x11,  0x44,  0x1F,  0x7C,  0x00,  0x00,  0x00,  0x00,  0xB1,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 20930 */
+	0x00,  0x00,  0x00,  0x00,  0x08,  0x03,  0x88,  0x04,  0x50,  0x08,  0x50,  0x08,  0x60,  0x10,  0x40,  0x10, 	/* 20940 */
+	0xC0,  0x11,  0x48,  0x0E,  0x30,  0x00,  0x00,  0x00,  0x00,  0xB2,  0x00,  0x00,  0x00,  0x70,  0x00,  0x88, 	/* 20950 */
+	0x01,  0x08,  0x01,  0x08,  0x02,  0x08,  0x02,  0x10,  0x04,  0xE0,  0x04,  0x20,  0x04,  0x10,  0x08,  0x10, 	/* 20960 */
+	0x08,  0x10,  0x0A,  0x20,  0x09,  0xC0,  0x10,  0x00,  0x10,  0x00,  0xB3,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 20970 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0E,  0x18,  0x11,  0x20,  0x21,  0x40,  0x01,  0x80,  0x01, 	/* 20980 */
+	0x80,  0x01,  0x00,  0x02,  0x00,  0x02,  0x00,  0x04,  0x00,  0x04,  0x00,  0xB4,  0x00,  0x00,  0x01,  0x80, 	/* 20990 */
+	0x02,  0x60,  0x02,  0x10,  0x01,  0x08,  0x00,  0x80,  0x03,  0x40,  0x04,  0x40,  0x08,  0x20,  0x10,  0x20, 	/* 209A0 */
+	0x10,  0x40,  0x10,  0x40,  0x08,  0x80,  0x07,  0x00,  0x00,  0x00,  0x00,  0x00,  0xB5,  0x00,  0x00,  0x00, 	/* 209B0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x01,  0xE0,  0x02,  0x10,  0x02,  0x00,  0x01, 	/* 209C0 */
+	0xC0,  0x02,  0x00,  0x04,  0x00,  0x04,  0x20,  0x03,  0xC0,  0x00,  0x00,  0x00,  0x00,  0xB6,  0x02,  0x00, 	/* 209D0 */
+	0x04,  0x10,  0x04,  0x20,  0x03,  0xC0,  0x00,  0x80,  0x01,  0x00,  0x02,  0x00,  0x04,  0x00,  0x08,  0x00, 	/* 209E0 */
+	0x08,  0x00,  0x04,  0x00,  0x03,  0x00,  0x00,  0x80,  0x00,  0x40,  0x00,  0x40,  0x01,  0x80,  0xB7,  0x00, 	/* 209F0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0C,  0xE0,  0x13,  0x10,  0x02, 	/* 20A00 */
+	0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x20,  0x08,  0x20,  0x08,  0x20,  0x00,  0x40,  0x00,  0x40,  0xB8, 	/* 20A10 */
+	0x00,  0x00,  0x00,  0x60,  0x00,  0x90,  0x01,  0x08,  0x02,  0x08,  0x02,  0x08,  0x07,  0xF8,  0x04,  0x10, 	/* 20A20 */
+	0x08,  0x10,  0x08,  0x20,  0x08,  0x20,  0x08,  0x40,  0x04,  0x80,  0x03,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 20A30 */
+	0xB9,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x02,  0x00,  0x02, 	/* 20A40 */
+	0x00,  0x04,  0x00,  0x04,  0x00,  0x08,  0x00,  0x08,  0x20,  0x08,  0xC0,  0x07,  0x00,  0x00,  0x00,  0x00, 	/* 20A50 */
+	0x00,  0xBA,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x04,  0x30, 	/* 20A60 */
+	0x04,  0x48,  0x05,  0x80,  0x06,  0x00,  0x09,  0x00,  0x09,  0x00,  0x11,  0x10,  0x10,  0xE0,  0x00,  0x00, 	/* 20A70 */
+	0x00,  0x00,  0xBB,  0x00,  0x00,  0x00,  0x80,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0x00, 	/* 20A80 */
+	0x40,  0x00,  0xC0,  0x01,  0x40,  0x01,  0x40,  0x02,  0x20,  0x04,  0x20,  0x08,  0x10,  0x10,  0x08,  0x00, 	/* 20A90 */
+	0x00,  0x00,  0x00,  0xBC,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 20AA0 */
+	0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x40,  0x08,  0x40,  0x08,  0x40,  0x0C,  0xC8,  0x13,  0x30, 	/* 20AB0 */
+	0x10,  0x00,  0x20,  0x00,  0xBD,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 20AC0 */
+	0x00,  0x18,  0x10,  0x04,  0x10,  0x04,  0x20,  0x04,  0x20,  0x04,  0x40,  0x08,  0x80,  0x0B,  0x00,  0x1C, 	/* 20AD0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0xBE,  0x00,  0x10,  0x00,  0xE0,  0x01,  0x00,  0x00,  0x80,  0x03,  0xE0, 	/* 20AE0 */
+	0x04,  0x00,  0x04,  0x00,  0x02,  0x00,  0x0F,  0xC0,  0x10,  0x00,  0x10,  0x00,  0x0E,  0x00,  0x01,  0x80, 	/* 20AF0 */
+	0x00,  0x40,  0x00,  0x40,  0x0F,  0x80,  0xBF,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 20B00 */
+	0x00,  0x00,  0x00,  0x01,  0xC0,  0x02,  0x20,  0x04,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x20,  0x04, 	/* 20B10 */
+	0x40,  0x03,  0x80,  0x00,  0x00,  0x00,  0x00,  0x80,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 20B20 */
+	0x00,  0x00,  0x00,  0x08,  0x0F,  0xF0,  0x12,  0x40,  0x02,  0x40,  0x02,  0x40,  0x04,  0x80,  0x04,  0x80, 	/* 20B30 */
+	0x08,  0x90,  0x10,  0x60,  0x00,  0x00,  0x00,  0x00,  0x81,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 20B40 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x01,  0xC0,  0x02,  0x20,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x08, 	/* 20B50 */
+	0x10,  0x0A,  0x20,  0x09,  0xC0,  0x10,  0x00,  0x10,  0x00,  0x83,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 20B60 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x08,  0x00,  0xF0,  0x01,  0x20,  0x02,  0x10,  0x04,  0x10,  0x04,  0x10, 	/* 20B70 */
+	0x04,  0x20,  0x02,  0x40,  0x01,  0x80,  0x00,  0x00,  0x00,  0x00,  0x84,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 20B80 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x08,  0x0F,  0xF0,  0x11,  0x00,  0x01,  0x00,  0x02,  0x00,  0x02, 	/* 20B90 */
+	0x00,  0x04,  0x20,  0x04,  0x40,  0x03,  0x80,  0x00,  0x00,  0x00,  0x00,  0x85,  0x00,  0x00,  0x00,  0x00, 	/* 20BA0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x01,  0x10,  0x01,  0x08,  0x01,  0x08,  0x01,  0x10, 	/* 20BB0 */
+	0x02,  0x10,  0x02,  0x20,  0x02,  0x40,  0x01,  0x80,  0x00,  0x00,  0x00,  0x00,  0x86,  0x00,  0x00,  0x00, 	/* 20BC0 */
+	0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x40,  0x00,  0x40,  0x01,  0xE0,  0x06,  0x90,  0x08,  0x90,  0x08, 	/* 20BD0 */
+	0x90,  0x09,  0x10,  0x09,  0x60,  0x07,  0x80,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x87,  0x00,  0x00, 	/* 20BE0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x06,  0x10,  0x09,  0x20,  0x01,  0x40, 	/* 20BF0 */
+	0x01,  0x80,  0x01,  0x00,  0x03,  0x00,  0x05,  0x00,  0x09,  0x00,  0x10,  0x90,  0x20,  0x60,  0x88,  0x00, 	/* 20C00 */
+	0x00,  0x00,  0x20,  0x00,  0x20,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0x08,  0x88,  0x14,  0x88,  0x04, 	/* 20C10 */
+	0x90,  0x05,  0x10,  0x09,  0x20,  0x09,  0x40,  0x07,  0x80,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x89, 	/* 20C20 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x04,  0x10,  0x08,  0x90, 	/* 20C30 */
+	0x10,  0x88,  0x10,  0x88,  0x21,  0x08,  0x21,  0x08,  0x22,  0x90,  0x1C,  0x60,  0x00,  0x00,  0x00,  0x00, 	/* 20C40 */
+	0x81,  0x04,  0x10,  0x04,  0x10,  0x00,  0x00,  0x3F,  0xF0,  0x08,  0x10,  0x08,  0x08,  0x08,  0x00,  0x08, 	/* 20C50 */
+	0x40,  0x0F,  0xC0,  0x08,  0x40,  0x08,  0x00,  0x08,  0x08,  0x08,  0x10,  0x3F,  0xF0,  0x00,  0x00,  0x00, 	/* 20C60 */
+	0x00,  0x90,  0x00,  0x00,  0x00,  0x80,  0x00,  0x80,  0x01,  0x40,  0x01,  0x40,  0x02,  0x20,  0x02,  0x20, 	/* 20C70 */
+	0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x08,  0x08,  0x08,  0x08,  0x10,  0x04,  0x38,  0x0E,  0x00,  0x00, 	/* 20C80 */
+	0x00,  0x00,  0x91,  0x00,  0x00,  0x3F,  0xF0,  0x08,  0x10,  0x08,  0x08,  0x08,  0x00,  0x08,  0x00,  0x0F, 	/* 20C90 */
+	0xE0,  0x08,  0x10,  0x08,  0x08,  0x08,  0x04,  0x08,  0x04,  0x08,  0x08,  0x08,  0x30,  0x3F,  0xC0,  0x00, 	/* 20CA0 */
+	0x00,  0x00,  0x00,  0x92,  0x00,  0x00,  0x3F,  0xE0,  0x08,  0x10,  0x08,  0x08,  0x08,  0x08,  0x08,  0x10, 	/* 20CB0 */
+	0x0F,  0xE0,  0x08,  0x10,  0x08,  0x08,  0x08,  0x04,  0x08,  0x04,  0x08,  0x08,  0x08,  0x30,  0x3F,  0xC0, 	/* 20CC0 */
+	0x00,  0x00,  0x00,  0x00,  0x93,  0x00,  0x00,  0x1F,  0xF8,  0x04,  0x08,  0x04,  0x04,  0x04,  0x00,  0x04, 	/* 20CD0 */
+	0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x0E, 	/* 20CE0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x94,  0x00,  0x00,  0x0F,  0xFC,  0x02,  0x10,  0x02,  0x10,  0x02,  0x10, 	/* 20CF0 */
+	0x02,  0x10,  0x02,  0x10,  0x02,  0x10,  0x02,  0x10,  0x02,  0x10,  0x04,  0x10,  0x04,  0x10,  0x08,  0x10, 	/* 20D00 */
+	0x3F,  0xFC,  0x20,  0x04,  0x20,  0x04,  0x95,  0x00,  0x00,  0x3F,  0xF8,  0x08,  0x08,  0x08,  0x04,  0x08, 	/* 20D10 */
+	0x00,  0x08,  0x00,  0x08,  0x40,  0x0F,  0xC0,  0x08,  0x40,  0x08,  0x00,  0x08,  0x00,  0x08,  0x04,  0x08, 	/* 20D20 */
+	0x08,  0x3F,  0xF8,  0x00,  0x00,  0x00,  0x00,  0x96,  0x00,  0x00,  0x31,  0xC6,  0x48,  0x89,  0x08,  0x88, 	/* 20D30 */
+	0x08,  0x88,  0x08,  0x88,  0x04,  0x90,  0x07,  0xF0,  0x08,  0x88,  0x10,  0x84,  0x10,  0x84,  0x20,  0x82, 	/* 20D40 */
+	0x20,  0x82,  0x71,  0xC7,  0x00,  0x00,  0x00,  0x00,  0x97,  0x00,  0x00,  0x03,  0xC0,  0x0C,  0x30,  0x10, 	/* 20D50 */
+	0x18,  0x00,  0x08,  0x00,  0x08,  0x00,  0x10,  0x03,  0xE0,  0x00,  0x10,  0x00,  0x08,  0x00,  0x08,  0x10, 	/* 20D60 */
+	0x10,  0x0C,  0x30,  0x03,  0xC0,  0x00,  0x00,  0x00,  0x00,  0x98,  0x00,  0x00,  0x38,  0x1C,  0x10,  0x18, 	/* 20D70 */
+	0x10,  0x28,  0x10,  0x28,  0x10,  0x48,  0x10,  0x88,  0x10,  0x88,  0x11,  0x08,  0x12,  0x08,  0x12,  0x08, 	/* 20D80 */
+	0x14,  0x08,  0x18,  0x08,  0x10,  0x1C,  0x00,  0x00,  0x00,  0x00,  0x99,  0x06,  0x60,  0x04,  0x20,  0x3B, 	/* 20D90 */
+	0xCC,  0x10,  0x18,  0x10,  0x18,  0x10,  0x28,  0x10,  0x48,  0x10,  0x88,  0x10,  0x88,  0x11,  0x08,  0x12, 	/* 20DA0 */
+	0x08,  0x14,  0x08,  0x18,  0x08,  0x10,  0x1C,  0x00,  0x00,  0x00,  0x00,  0x9A,  0x00,  0x00,  0x1C,  0x38, 	/* 20DB0 */
+	0x08,  0x44,  0x08,  0x40,  0x08,  0x80,  0x08,  0x80,  0x09,  0x00,  0x0F,  0x00,  0x08,  0x80,  0x08,  0x40, 	/* 20DC0 */
+	0x08,  0x20,  0x08,  0x10,  0x08,  0x08,  0x1C,  0x1C,  0x00,  0x00,  0x00,  0x00,  0x9B,  0x00,  0x00,  0x0F, 	/* 20DD0 */
+	0xF8,  0x02,  0x10,  0x02,  0x10,  0x02,  0x10,  0x02,  0x10,  0x02,  0x10,  0x02,  0x10,  0x02,  0x10,  0x04, 	/* 20DE0 */
+	0x10,  0x04,  0x10,  0x08,  0x10,  0x50,  0x10,  0x60,  0x38,  0x00,  0x00,  0x00,  0x00,  0x9C,  0x00,  0x00, 	/* 20DF0 */
+	0x30,  0x0C,  0x10,  0x08,  0x18,  0x18,  0x18,  0x18,  0x14,  0x28,  0x14,  0x28,  0x12,  0x28,  0x12,  0x48, 	/* 20E00 */
+	0x22,  0x44,  0x21,  0x44,  0x21,  0x84,  0x20,  0x84,  0x78,  0x8E,  0x00,  0x00,  0x00,  0x00,  0x9D,  0x00, 	/* 20E10 */
+	0x00,  0x38,  0x1C,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x1F,  0xF8,  0x10, 	/* 20E20 */
+	0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x38,  0x1C,  0x00,  0x00,  0x00,  0x00,  0x9E, 	/* 20E30 */
+	0x00,  0x00,  0x03,  0xC0,  0x0C,  0x30,  0x18,  0x18,  0x10,  0x08,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04, 	/* 20E40 */
+	0x20,  0x04,  0x20,  0x04,  0x10,  0x08,  0x18,  0x18,  0x0C,  0x30,  0x03,  0xC0,  0x00,  0x00,  0x00,  0x00, 	/* 20E50 */
+	0x9F,  0x00,  0x00,  0x1F,  0xFC,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08, 	/* 20E60 */
+	0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x1C,  0x1C,  0x00,  0x00,  0x00, 	/* 20E70 */
+	0x00,  0xA0,  0x00,  0x00,  0x1F,  0xE0,  0x04,  0x18,  0x04,  0x04,  0x04,  0x04,  0x04,  0x04,  0x04,  0x18, 	/* 20E80 */
+	0x07,  0xE0,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x0E,  0x00,  0x00,  0x00, 	/* 20E90 */
+	0x00,  0x00,  0xA1,  0x00,  0x00,  0x03,  0xC0,  0x0C,  0x28,  0x18,  0x18,  0x10,  0x08,  0x20,  0x00,  0x20, 	/* 20EA0 */
+	0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x10,  0x08,  0x18,  0x18,  0x0C,  0x30,  0x03,  0xC0,  0x00, 	/* 20EB0 */
+	0x00,  0x00,  0x00,  0xA2,  0x00,  0x00,  0x3F,  0xF8,  0x21,  0x08,  0x41,  0x04,  0x01,  0x00,  0x01,  0x00, 	/* 20EC0 */
+	0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x03,  0x80, 	/* 20ED0 */
+	0x00,  0x00,  0x00,  0x00,  0xA3,  0x00,  0x00,  0x1C,  0x1C,  0x08,  0x08,  0x04,  0x10,  0x04,  0x10,  0x02, 	/* 20EE0 */
+	0x20,  0x02,  0x20,  0x01,  0x40,  0x01,  0x40,  0x00,  0x80,  0x00,  0x80,  0x01,  0x00,  0x12,  0x00,  0x0C, 	/* 20EF0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0xA4,  0x00,  0x00,  0x01,  0xC0,  0x00,  0x80,  0x03,  0xE0,  0x0C,  0x98, 	/* 20F00 */
+	0x08,  0x88,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x08,  0x88,  0x0C,  0x98,  0x03,  0xE0,  0x00,  0x80, 	/* 20F10 */
+	0x01,  0xC0,  0x00,  0x00,  0x00,  0x00,  0xA5,  0x00,  0x00,  0x38,  0x38,  0x10,  0x10,  0x08,  0x20,  0x04, 	/* 20F20 */
+	0x40,  0x04,  0x40,  0x02,  0x80,  0x01,  0x00,  0x02,  0x80,  0x04,  0x40,  0x04,  0x40,  0x08,  0x20,  0x10, 	/* 20F30 */
+	0x10,  0x38,  0x38,  0x00,  0x00,  0x00,  0x00,  0xA6,  0x00,  0x00,  0x38,  0x38,  0x10,  0x10,  0x10,  0x10, 	/* 20F40 */
+	0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x10, 	/* 20F50 */
+	0x10,  0x10,  0x3F,  0xFC,  0x00,  0x04,  0x00,  0x04,  0xA7,  0x00,  0x00,  0x1C,  0x38,  0x08,  0x10,  0x08, 	/* 20F60 */
+	0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x04,  0x30,  0x03,  0xD0,  0x00,  0x10,  0x00,  0x10,  0x00, 	/* 20F70 */
+	0x10,  0x00,  0x10,  0x00,  0x38,  0x00,  0x00,  0x00,  0x00,  0xA8,  0x00,  0x00,  0x39,  0xCE,  0x10,  0x84, 	/* 20F80 */
+	0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84, 	/* 20F90 */
+	0x10,  0x84,  0x10,  0x84,  0x3F,  0xFE,  0x00,  0x00,  0x00,  0x00,  0xA9,  0x00,  0x00,  0x39,  0xCE,  0x10, 	/* 20FA0 */
+	0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10, 	/* 20FB0 */
+	0x84,  0x10,  0x84,  0x10,  0x84,  0x3F,  0xFF,  0x00,  0x01,  0x00,  0x01,  0xAA,  0x00,  0x00,  0x3F,  0x00, 	/* 20FC0 */
+	0x22,  0x00,  0x42,  0x00,  0x02,  0x00,  0x02,  0x00,  0x03,  0xF0,  0x02,  0x0C,  0x02,  0x06,  0x02,  0x02, 	/* 20FD0 */
+	0x02,  0x02,  0x02,  0x06,  0x02,  0x0C,  0x07,  0xF0,  0x00,  0x00,  0x00,  0x00,  0xAB,  0x00,  0x00,  0x38, 	/* 20FE0 */
+	0x1C,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x1E,  0x08,  0x11,  0x88,  0x10,  0xC8,  0x10, 	/* 20FF0 */
+	0x48,  0x10,  0x48,  0x10,  0xC8,  0x11,  0x88,  0x3E,  0x1C,  0x00,  0x00,  0x00,  0x00,  0xAC,  0x00,  0x00, 	/* 21000 */
+	0x1C,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x0F,  0xC0,  0x08,  0x30,  0x08,  0x18, 	/* 21010 */
+	0x08,  0x08,  0x08,  0x08,  0x08,  0x18,  0x08,  0x30,  0x1F,  0xC0,  0x00,  0x00,  0x00,  0x00,  0xAD,  0x00, 	/* 21020 */
+	0x00,  0x03,  0xC0,  0x0C,  0x30,  0x08,  0x18,  0x10,  0x08,  0x00,  0x0C,  0x07,  0x14,  0x08,  0xE4,  0x00, 	/* 21030 */
+	0x04,  0x00,  0x04,  0x10,  0x08,  0x08,  0x18,  0x0C,  0x30,  0x03,  0xC0,  0x00,  0x00,  0x00,  0x00,  0xAE, 	/* 21040 */
+	0x00,  0x00,  0x38,  0x70,  0x10,  0x88,  0x11,  0x04,  0x11,  0x04,  0x12,  0x02,  0x12,  0x02,  0x1E,  0x02, 	/* 21050 */
+	0x12,  0x02,  0x12,  0x02,  0x11,  0x04,  0x11,  0x04,  0x10,  0x88,  0x38,  0x70,  0x00,  0x00,  0x00,  0x00, 	/* 21060 */
+	0xAF,  0x00,  0x00,  0x03,  0xF8,  0x0C,  0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x0C,  0x10,  0x03, 	/* 21070 */
+	0xF0,  0x01,  0x10,  0x02,  0x10,  0x04,  0x10,  0x04,  0x10,  0x18,  0x10,  0x60,  0x38,  0x00,  0x00,  0x00, 	/* 21080 */
+	0x00,  0xB0,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x03,  0xC0,  0x04,  0x20, 	/* 21090 */
+	0x00,  0x20,  0x03,  0xA0,  0x04,  0x60,  0x08,  0x20,  0x08,  0x60,  0x08,  0xA8,  0x07,  0x18,  0x00,  0x00, 	/* 210A0 */
+	0x00,  0x00,  0xB1,  0x00,  0x00,  0x00,  0x10,  0x01,  0xE0,  0x02,  0x00,  0x04,  0x00,  0x04,  0x00,  0x0B, 	/* 210B0 */
+	0xC0,  0x0C,  0x20,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x04,  0x20,  0x03,  0xC0,  0x00, 	/* 210C0 */
+	0x00,  0x00,  0x00,  0xB2,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0F,  0xE0, 	/* 210D0 */
+	0x04,  0x10,  0x04,  0x10,  0x04,  0x20,  0x07,  0xE0,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x0F,  0xE0, 	/* 210E0 */
+	0x00,  0x00,  0x00,  0x00,  0xB3,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0F, 	/* 210F0 */
+	0xF0,  0x04,  0x10,  0x04,  0x10,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x0E, 	/* 21100 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0xB4,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21110 */
+	0x07,  0xF0,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x04,  0x20,  0x04,  0x20, 	/* 21120 */
+	0x1F,  0xF8,  0x10,  0x08,  0x10,  0x08,  0xB5,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21130 */
+	0x00,  0x03,  0x80,  0x04,  0x40,  0x08,  0x20,  0x08,  0x20,  0x0F,  0xE0,  0x08,  0x00,  0x08,  0x00,  0x04, 	/* 21140 */
+	0x20,  0x03,  0xC0,  0x00,  0x00,  0x00,  0x00,  0xB6,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21150 */
+	0x00,  0x00,  0x19,  0xCC,  0x08,  0x88,  0x04,  0x90,  0x03,  0xE0,  0x02,  0xA0,  0x04,  0x90,  0x04,  0x90, 	/* 21160 */
+	0x08,  0x88,  0x11,  0xC4,  0x00,  0x00,  0x00,  0x00,  0xB7,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21170 */
+	0x00,  0x00,  0x00,  0x03,  0xE0,  0x06,  0x10,  0x00,  0x10,  0x00,  0x20,  0x01,  0xE0,  0x00,  0x10,  0x00, 	/* 21180 */
+	0x10,  0x06,  0x10,  0x03,  0xE0,  0x00,  0x00,  0x00,  0x00,  0xB8,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21190 */
+	0x00,  0x00,  0x00,  0x00,  0x0E,  0x1C,  0x04,  0x08,  0x04,  0x18,  0x04,  0x28,  0x04,  0x48,  0x05,  0x88, 	/* 211A0 */
+	0x06,  0x08,  0x04,  0x08,  0x0E,  0x1C,  0x00,  0x00,  0x00,  0x00,  0xB9,  0x00,  0x00,  0x00,  0x00,  0x03, 	/* 211B0 */
+	0x30,  0x02,  0x10,  0x01,  0xE0,  0x0E,  0x1C,  0x04,  0x08,  0x04,  0x18,  0x04,  0x28,  0x04,  0x48,  0x05, 	/* 211C0 */
+	0x88,  0x06,  0x08,  0x04,  0x08,  0x0E,  0x1C,  0x00,  0x00,  0x00,  0x00,  0xBA,  0x00,  0x00,  0x00,  0x00, 	/* 211D0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0E,  0x30,  0x04,  0x50,  0x04,  0x80,  0x05,  0x00,  0x07,  0x00, 	/* 211E0 */
+	0x04,  0x80,  0x04,  0x40,  0x04,  0x20,  0x0E,  0x38,  0x00,  0x00,  0x00,  0x00,  0xBB,  0x00,  0x00,  0x00, 	/* 211F0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x03,  0xF8,  0x01,  0x10,  0x01,  0x10,  0x01,  0x10,  0x01, 	/* 21200 */
+	0x10,  0x01,  0x10,  0x11,  0x10,  0x12,  0x10,  0x0C,  0x38,  0x00,  0x00,  0x00,  0x00,  0xBC,  0x00,  0x00, 	/* 21210 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x1C,  0x1C,  0x0C,  0x18,  0x0A,  0x28,  0x0A,  0x28, 	/* 21220 */
+	0x09,  0x48,  0x09,  0x48,  0x08,  0x88,  0x08,  0x88,  0x1C,  0x1C,  0x00,  0x00,  0x00,  0x00,  0xBD,  0x00, 	/* 21230 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0E,  0x38,  0x04,  0x10,  0x04,  0x10,  0x04, 	/* 21240 */
+	0x10,  0x07,  0xF0,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x0E,  0x38,  0x00,  0x00,  0x00,  0x00,  0xBE, 	/* 21250 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x03,  0xC0,  0x04,  0x20,  0x08,  0x10, 	/* 21260 */
+	0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x04,  0x20,  0x03,  0xC0,  0x00,  0x00,  0x00,  0x00, 	/* 21270 */
+	0xBF,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x1F,  0xF0,  0x08,  0x20,  0x08, 	/* 21280 */
+	0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x1C,  0x70,  0x00,  0x00,  0x00, 	/* 21290 */
+	0x00,  0x80,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0D,  0xC0,  0x06,  0x20, 	/* 212A0 */
+	0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x06,  0x20,  0x05,  0xC0,  0x04,  0x00,  0x04,  0x00, 	/* 212B0 */
+	0x0E,  0x00,  0x81,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x03,  0x80,  0x04, 	/* 212C0 */
+	0x40,  0x08,  0x20,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x20,  0x04,  0x40,  0x03,  0x80,  0x00, 	/* 212D0 */
+	0x00,  0x00,  0x00,  0x82,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x1F,  0xF0, 	/* 212E0 */
+	0x11,  0x10,  0x11,  0x10,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x03,  0x80, 	/* 212F0 */
+	0x00,  0x00,  0x00,  0x00,  0x83,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0E, 	/* 21300 */
+	0x38,  0x04,  0x10,  0x04,  0x10,  0x02,  0x20,  0x02,  0x20,  0x01,  0x40,  0x01,  0x40,  0x00,  0x80,  0x01, 	/* 21310 */
+	0x00,  0x09,  0x00,  0x06,  0x00,  0x84,  0x00,  0x00,  0x01,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80, 	/* 21320 */
+	0x00,  0x80,  0x06,  0xB0,  0x09,  0xC8,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x09,  0xC8, 	/* 21330 */
+	0x06,  0xB0,  0x00,  0x80,  0x01,  0xC0,  0x85,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21340 */
+	0x00,  0x0E,  0x38,  0x04,  0x10,  0x02,  0x20,  0x01,  0x40,  0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x04, 	/* 21350 */
+	0x10,  0x0E,  0x38,  0x00,  0x00,  0x00,  0x00,  0x86,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21360 */
+	0x00,  0x00,  0x1C,  0x70,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20, 	/* 21370 */
+	0x08,  0x20,  0x1F,  0xF8,  0x00,  0x08,  0x00,  0x08,  0x87,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21380 */
+	0x00,  0x00,  0x00,  0x0E,  0x38,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x03,  0xF0,  0x00, 	/* 21390 */
+	0x10,  0x00,  0x10,  0x00,  0x38,  0x00,  0x00,  0x00,  0x00,  0x88,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 213A0 */
+	0x00,  0x00,  0x00,  0x00,  0x39,  0xCE,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84, 	/* 213B0 */
+	0x10,  0x84,  0x10,  0x84,  0x3F,  0xFE,  0x00,  0x00,  0x00,  0x00,  0x89,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 213C0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x39,  0xCE,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10, 	/* 213D0 */
+	0x84,  0x10,  0x84,  0x10,  0x84,  0x3F,  0xFF,  0x00,  0x01,  0x00,  0x01,  0x8A,  0x00,  0x00,  0x00,  0x00, 	/* 213E0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x1F,  0x80,  0x11,  0x00,  0x11,  0x00,  0x01,  0x00,  0x01,  0xF0, 	/* 213F0 */
+	0x01,  0x0C,  0x01,  0x04,  0x01,  0x0C,  0x03,  0xF0,  0x00,  0x00,  0x00,  0x00,  0x8B,  0x00,  0x00,  0x00, 	/* 21400 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x1C,  0x1C,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x0F, 	/* 21410 */
+	0x08,  0x08,  0xC8,  0x08,  0x48,  0x08,  0xC8,  0x1F,  0x1C,  0x00,  0x00,  0x00,  0x00,  0x8C,  0x00,  0x00, 	/* 21420 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x07,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00, 	/* 21430 */
+	0x03,  0xE0,  0x02,  0x18,  0x02,  0x08,  0x02,  0x18,  0x07,  0xE0,  0x00,  0x00,  0x00,  0x00,  0x8D,  0x00, 	/* 21440 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x03,  0xC0,  0x04,  0x20,  0x08,  0x10,  0x03, 	/* 21450 */
+	0x30,  0x04,  0xD0,  0x00,  0x10,  0x08,  0x10,  0x04,  0x20,  0x03,  0xC0,  0x00,  0x00,  0x00,  0x00,  0x8E, 	/* 21460 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x1C,  0x70,  0x08,  0x88,  0x09,  0x04, 	/* 21470 */
+	0x09,  0x04,  0x0F,  0x04,  0x09,  0x04,  0x09,  0x04,  0x08,  0x88,  0x1C,  0x70,  0x00,  0x00,  0x00,  0x00, 	/* 21480 */
+	0x8F,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x07,  0xF0,  0x08,  0x20,  0x08, 	/* 21490 */
+	0x20,  0x08,  0x20,  0x07,  0xE0,  0x02,  0x20,  0x04,  0x20,  0x04,  0x20,  0x18,  0x70,  0x00,  0x00,  0x00, 	/* 214A0 */
+	0x00,  0x91,  0x00,  0x00,  0x00,  0x00,  0x04,  0x40,  0x04,  0x40,  0x00,  0x00,  0x03,  0x80,  0x04,  0x40, 	/* 214B0 */
+	0x08,  0x20,  0x08,  0x20,  0x0F,  0xE0,  0x08,  0x00,  0x08,  0x00,  0x04,  0x20,  0x03,  0xC0,  0x00,  0x00, 	/* 214C0 */
+	0x00,  0x00,  0x90,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 214D0 */
+	0x00,  0x07,  0xE0,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 214E0 */
+	0x00,  0x00,  0x00,  0x95,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 214F0 */
+	0x00,  0x00,  0xFF,  0xFF,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21500 */
+	0x00,  0x00,  0x00,  0x00,  0x98,  0x00,  0x08,  0x00,  0x10,  0x00,  0x18,  0x00,  0x18,  0x00,  0x00,  0x00, 	/* 21510 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21520 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x99,  0x18,  0x00,  0x18,  0x00,  0x08,  0x00,  0x10,  0x00,  0x00,  0x00, 	/* 21530 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21540 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x9C,  0x00,  0x24,  0x00,  0x48,  0x00,  0x6C,  0x00,  0x6C,  0x00, 	/* 21550 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21560 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x9D,  0x36,  0x00,  0x36,  0x00,  0x12,  0x00,  0x24,  0x00, 	/* 21570 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21580 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xA0,  0x00,  0x80,  0x01,  0xC0,  0x04,  0x90,  0x0F, 	/* 21590 */
+	0xF8,  0x04,  0x90,  0x00,  0x80,  0x03,  0xE0,  0x01,  0xC0,  0x01,  0xC0,  0x01,  0xC0,  0x01,  0xC0,  0x01, 	/* 215A0 */
+	0xC0,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0xA1,  0x01,  0x00,  0x03,  0x80,  0x09,  0x20, 	/* 215B0 */
+	0x1F,  0xF0,  0x09,  0x20,  0x03,  0x80,  0x03,  0x80,  0x01,  0x00,  0x01,  0x00,  0x03,  0x80,  0x03,  0x80, 	/* 215C0 */
+	0x09,  0x20,  0x1F,  0xF0,  0x09,  0x20,  0x03,  0x80,  0x01,  0x00,  0xA5,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 215D0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x18,  0x18,  0x18,  0x18,  0x00,  0x00,  0x00, 	/* 215E0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xA6,  0x00,  0x00,  0x00,  0x00, 	/* 215F0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x61,  0x86,  0x61,  0x86,  0x00,  0x00, 	/* 21600 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xB0,  0x00,  0x00,  0x00, 	/* 21610 */
+	0x08,  0x18,  0x10,  0x34,  0x20,  0x24,  0x20,  0x24,  0x40,  0x24,  0x80,  0x2D,  0x00,  0x1A,  0x00,  0x05, 	/* 21620 */
+	0x8C,  0x07,  0x5A,  0x0A,  0x52,  0x12,  0x52,  0x22,  0xD6,  0x41,  0x8C,  0x00,  0x00,  0xB2,  0x00,  0x00, 	/* 21630 */
+	0x08,  0x00,  0x18,  0x00,  0x30,  0x00,  0x20,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21640 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xB3,  0x00, 	/* 21650 */
+	0x00,  0x11,  0x00,  0x33,  0x00,  0x66,  0x00,  0x44,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21660 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xBB, 	/* 21670 */
+	0x00,  0x00,  0x00,  0x00,  0x21,  0x84,  0x11,  0x88,  0x08,  0x10,  0x04,  0x20,  0x02,  0x40,  0x31,  0x8C, 	/* 21680 */
+	0x31,  0x8C,  0x02,  0x40,  0x04,  0x20,  0x08,  0x10,  0x11,  0x88,  0x21,  0x84,  0x00,  0x00,  0x00,  0x00, 	/* 21690 */
+	0x83,  0x00,  0x00,  0x30,  0x72,  0x49,  0x8A,  0x4A,  0x06,  0x32,  0x02,  0x04,  0x02,  0x04,  0x00,  0x04, 	/* 216A0 */
+	0x00,  0x04,  0x00,  0x04,  0x00,  0x02,  0x02,  0x02,  0x04,  0x01,  0x98,  0x00,  0x60,  0x00,  0x00,  0x00, 	/* 216B0 */
+	0x00,  0xAB,  0x00,  0xC0,  0x01,  0x20,  0x01,  0x20,  0x00,  0xC0,  0x00,  0x80,  0x00,  0x80,  0x01,  0x40, 	/* 216C0 */
+	0x01,  0x40,  0x02,  0x20,  0x02,  0x20,  0x03,  0xE0,  0x04,  0x10,  0x04,  0x10,  0x0E,  0x38,  0x00,  0x00, 	/* 216D0 */
+	0x00,  0x00,  0x90,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x04,  0x00,  0x08,  0x00,  0x30, 	/* 216E0 */
+	0x00,  0xFF,  0xFF,  0x30,  0x00,  0x08,  0x00,  0x04,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 216F0 */
+	0x00,  0x00,  0x00,  0x91,  0x01,  0x00,  0x01,  0x00,  0x03,  0x80,  0x03,  0x80,  0x05,  0x40,  0x09,  0x20, 	/* 21700 */
+	0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 21710 */
+	0x01,  0x00,  0x01,  0x00,  0x92,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x20,  0x00, 	/* 21720 */
+	0x10,  0x00,  0x0C,  0xFF,  0xFF,  0x00,  0x0C,  0x00,  0x10,  0x00,  0x20,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21730 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x93,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 21740 */
+	0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x09,  0x20,  0x05,  0x40,  0x03,  0x80, 	/* 21750 */
+	0x03,  0x80,  0x01,  0x00,  0x01,  0x00,  0x92,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x10,  0x00, 	/* 21760 */
+	0x08,  0xFF,  0xFC,  0x00,  0x02,  0x00,  0x01,  0x00,  0x02,  0xFF,  0xFC,  0x00,  0x08,  0x00,  0x10,  0x00, 	/* 21770 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x94,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x08,  0x10, 	/* 21780 */
+	0x10,  0x08,  0x3F,  0xFC,  0x40,  0x02,  0x80,  0x01,  0x40,  0x02,  0x3F,  0xFC,  0x10,  0x08,  0x08,  0x10, 	/* 21790 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x80,  0x00,  0x00,  0x20,  0x02,  0x20,  0x02,  0x10, 	/* 217A0 */
+	0x04,  0x10,  0x04,  0x0F,  0xF8,  0x08,  0x08,  0x04,  0x10,  0x04,  0x10,  0x02,  0x20,  0x02,  0x20,  0x01, 	/* 217B0 */
+	0x40,  0x01,  0x40,  0x00,  0x80,  0x00,  0x80,  0x00,  0x00,  0x82,  0x00,  0x00,  0x00,  0xC0,  0x03,  0x20, 	/* 217C0 */
+	0x04,  0x10,  0x00,  0x10,  0x00,  0x10,  0x03,  0xB0,  0x04,  0x60,  0x0C,  0x60,  0x08,  0x60,  0x18,  0x40, 	/* 217D0 */
+	0x18,  0xC0,  0x09,  0x80,  0x06,  0x00,  0x00,  0x00,  0x00,  0x00,  0x83,  0x00,  0x00,  0x00,  0x00,  0x1F, 	/* 217E0 */
+	0xF0,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x1F,  0xF0,  0x00,  0x10,  0x00,  0x10,  0x00, 	/* 217F0 */
+	0x10,  0x00,  0x10,  0x1F,  0xF0,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x87,  0x00,  0x00,  0x7F,  0xFE, 	/* 21800 */
+	0x20,  0x04,  0x30,  0x04,  0x10,  0x08,  0x18,  0x08,  0x08,  0x10,  0x0C,  0x10,  0x04,  0x20,  0x06,  0x20, 	/* 21810 */
+	0x02,  0x40,  0x03,  0x40,  0x01,  0x80,  0x00,  0x80,  0x00,  0x00,  0x00,  0x00,  0x88,  0x00,  0x00,  0x00, 	/* 21820 */
+	0x00,  0x00,  0x00,  0x07,  0xF8,  0x08,  0x00,  0x10,  0x00,  0x10,  0x00,  0x1F,  0xF8,  0x10,  0x00,  0x10, 	/* 21830 */
+	0x00,  0x08,  0x00,  0x07,  0xF8,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x8B,  0x00,  0x00, 	/* 21840 */
+	0x00,  0x00,  0x00,  0x00,  0x1F,  0xE0,  0x00,  0x10,  0x00,  0x08,  0x00,  0x08,  0x1F,  0xF8,  0x00,  0x08, 	/* 21850 */
+	0x00,  0x08,  0x00,  0x10,  0x1F,  0xE0,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x9A,  0x00, 	/* 21860 */
+	0xFF,  0x00,  0x80,  0x00,  0x80,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x02,  0x00,  0x02, 	/* 21870 */
+	0x00,  0x22,  0x00,  0x22,  0x00,  0x34,  0x00,  0x54,  0x00,  0x5C,  0x00,  0x08,  0x00,  0x08,  0x00,  0x9D, 	/* 21880 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x1C,  0x38,  0x22,  0x44,  0x41,  0x80,  0x41,  0x80, 	/* 21890 */
+	0x41,  0x80,  0x41,  0x80,  0x22,  0x44,  0x1C,  0x38,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 218A0 */
+	0x9E,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x1C,  0x18,  0x26,  0x64,  0x42,  0x42,  0x41, 	/* 218B0 */
+	0x82,  0x41,  0x82,  0x42,  0x42,  0x26,  0x64,  0x18,  0x38,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 218C0 */
+	0x00,  0xA0,  0x00,  0x00,  0x00,  0x00,  0x00,  0x08,  0x00,  0x10,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80, 	/* 218D0 */
+	0x01,  0x00,  0x02,  0x00,  0x04,  0x00,  0x08,  0x00,  0x10,  0x00,  0x3F,  0xFC,  0x00,  0x00,  0x00,  0x00, 	/* 218E0 */
+	0x00,  0x00,  0xA5,  0x04,  0x40,  0x04,  0x40,  0x04,  0x40,  0x04,  0x40,  0x04,  0x40,  0x04,  0x40,  0x04, 	/* 218F0 */
+	0x40,  0x04,  0x40,  0x04,  0x40,  0x04,  0x40,  0x04,  0x40,  0x04,  0x40,  0x04,  0x40,  0x04,  0x40,  0x04, 	/* 21900 */
+	0x40,  0x04,  0x40,  0xA7,  0x00,  0x00,  0x00,  0x00,  0x00,  0x80,  0x00,  0x80,  0x01,  0x40,  0x01,  0x40, 	/* 21910 */
+	0x02,  0x20,  0x02,  0x20,  0x04,  0x10,  0x04,  0x10,  0x08,  0x08,  0x08,  0x08,  0x10,  0x04,  0x10,  0x04, 	/* 21920 */
+	0x00,  0x00,  0x00,  0x00,  0xA8,  0x00,  0x00,  0x00,  0x00,  0x10,  0x04,  0x10,  0x04,  0x08,  0x08,  0x08, 	/* 21930 */
+	0x08,  0x04,  0x10,  0x04,  0x10,  0x02,  0x20,  0x02,  0x20,  0x01,  0x40,  0x01,  0x40,  0x00,  0x80,  0x00, 	/* 21940 */
+	0x80,  0x00,  0x00,  0x00,  0x00,  0xA9,  0x00,  0x00,  0x00,  0x00,  0x03,  0xC0,  0x04,  0x20,  0x08,  0x10, 	/* 21950 */
+	0x08,  0x10,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08, 	/* 21960 */
+	0x10,  0x08,  0x00,  0x00,  0x00,  0x00,  0xAA,  0x00,  0x00,  0x00,  0x00,  0x10,  0x08,  0x10,  0x08,  0x10, 	/* 21970 */
+	0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x08,  0x10,  0x08,  0x10,  0x04, 	/* 21980 */
+	0x20,  0x03,  0xC0,  0x00,  0x00,  0x00,  0x00,  0xAB,  0x01,  0xC0,  0x02,  0x40,  0x02,  0x00,  0x02,  0x00, 	/* 21990 */
+	0x03,  0x00,  0x03,  0x00,  0x01,  0x00,  0x01,  0x80,  0x01,  0x80,  0x00,  0x80,  0x00,  0xC0,  0x00,  0xC0, 	/* 219A0 */
+	0x00,  0x40,  0x00,  0x40,  0x02,  0x40,  0x03,  0x80,  0xAC,  0x0E,  0x38,  0x12,  0x48,  0x10,  0x40,  0x10, 	/* 219B0 */
+	0x40,  0x18,  0x60,  0x18,  0x60,  0x08,  0x20,  0x0C,  0x30,  0x0C,  0x30,  0x04,  0x10,  0x06,  0x18,  0x06, 	/* 219C0 */
+	0x18,  0x02,  0x08,  0x02,  0x08,  0x12,  0x48,  0x1C,  0x70,  0xB4,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 219D0 */
+	0x01,  0x80,  0x01,  0x80,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 219E0 */
+	0x30,  0x0C,  0x30,  0x0C,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xB5,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 219F0 */
+	0x00,  0x30,  0x0C,  0x30,  0x0C,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21A00 */
+	0x00,  0x01,  0x80,  0x01,  0x80,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xBD,  0x00,  0x00,  0x00,  0x00, 	/* 21A10 */
+	0x00,  0x00,  0x00,  0x00,  0x1C,  0x38,  0x20,  0x44,  0x40,  0x82,  0x40,  0x82,  0x41,  0x02,  0x41,  0x02, 	/* 21A20 */
+	0x22,  0x04,  0x1C,  0x38,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x92,  0x00,  0x00,  0x00, 	/* 21A30 */
+	0x00,  0x18,  0x00,  0x18,  0x00,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x3F, 	/* 21A40 */
+	0xFC,  0x00,  0x00,  0x00,  0x18,  0x00,  0x18,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xA0,  0x00,  0x00, 	/* 21A50 */
+	0x00,  0x00,  0x00,  0x40,  0x00,  0x40,  0x00,  0x80,  0x3F,  0xFC,  0x00,  0x80,  0x01,  0x00,  0x01,  0x00, 	/* 21A60 */
+	0x3F,  0xFC,  0x01,  0x00,  0x02,  0x00,  0x02,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xA1,  0x00, 	/* 21A70 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x3F,  0xFC,  0x00, 	/* 21A80 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xA6, 	/* 21A90 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x1C,  0x00,  0xE0,  0x07,  0x00,  0x38,  0x00,  0x07,  0x00,  0x00,  0xE0, 	/* 21AA0 */
+	0x00,  0x1C,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x00,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x00,  0x00,  0x00, 	/* 21AB0 */
+	0xA7,  0x00,  0x00,  0x00,  0x00,  0x38,  0x00,  0x07,  0x00,  0x00,  0xE0,  0x00,  0x1C,  0x00,  0xE0,  0x07, 	/* 21AC0 */
+	0x00,  0x38,  0x00,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x00,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x00,  0x00, 	/* 21AD0 */
+	0x00,  0xAA,  0x00,  0x00,  0x00,  0x88,  0x01,  0x10,  0x02,  0x20,  0x04,  0x40,  0x08,  0x80,  0x11,  0x00, 	/* 21AE0 */
+	0x22,  0x00,  0x11,  0x00,  0x08,  0x80,  0x04,  0x40,  0x02,  0x20,  0x01,  0x10,  0x00,  0x88,  0x00,  0x44, 	/* 21AF0 */
+	0x00,  0x00,  0xAB,  0x00,  0x00,  0x11,  0x00,  0x08,  0x80,  0x04,  0x40,  0x02,  0x20,  0x01,  0x10,  0x00, 	/* 21B00 */
+	0x88,  0x00,  0x44,  0x00,  0x88,  0x01,  0x10,  0x02,  0x20,  0x04,  0x40,  0x08,  0x80,  0x11,  0x00,  0x22, 	/* 21B10 */
+	0x00,  0x00,  0x00,  0x82,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x03,  0xFC,  0x0C,  0x00,  0x10,  0x00, 	/* 21B20 */
+	0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x10,  0x00,  0x0C,  0x00,  0x03,  0xFC,  0x00,  0x00, 	/* 21B30 */
+	0x00,  0x00,  0x00,  0x00,  0x83,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x3F,  0xC0,  0x00,  0x30,  0x00, 	/* 21B40 */
+	0x08,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x08,  0x00,  0x30,  0x3F,  0xC0,  0x00, 	/* 21B50 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x86,  0x00,  0x00,  0x00,  0x00,  0x0F,  0xFC,  0x10,  0x00,  0x20,  0x00, 	/* 21B60 */
+	0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x10,  0x00,  0x0F,  0xFC,  0x00,  0x00,  0x00,  0x00,  0x3F,  0xFC, 	/* 21B70 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x87,  0x00,  0x00,  0x00,  0x00,  0x3F,  0xF0,  0x00,  0x08,  0x00, 	/* 21B80 */
+	0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x08,  0x3F,  0xF0,  0x00,  0x00,  0x00,  0x00,  0x3F, 	/* 21B90 */
+	0xFC,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xA5,  0x00,  0x00,  0x00,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 21BA0 */
+	0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 21BB0 */
+	0x3F,  0xFC,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x92,  0x07,  0xE0,  0x38,  0x1C,  0x40,  0x02,  0x00, 	/* 21BC0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21BD0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x80,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21BE0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xFF,  0xFF,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21BF0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x81,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21C00 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xFF,  0xFF,  0xFF,  0xFF,  0x00,  0x00,  0x00, 	/* 21C10 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x82,  0x01,  0x00,  0x01,  0x00, 	/* 21C20 */
+	0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 21C30 */
+	0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x83,  0x01,  0x80,  0x01, 	/* 21C40 */
+	0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01, 	/* 21C50 */
+	0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x8C,  0x00,  0x00, 	/* 21C60 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x01,  0xFF,  0x01,  0x00, 	/* 21C70 */
+	0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x8F,  0x00, 	/* 21C80 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x01,  0xFF,  0x01, 	/* 21C90 */
+	0xFF,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x90, 	/* 21CA0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xFF,  0x00, 	/* 21CB0 */
+	0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 21CC0 */
+	0x93,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xFF, 	/* 21CD0 */
+	0x80,  0xFF,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01, 	/* 21CE0 */
+	0x80,  0x94,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 21CF0 */
+	0x01,  0xFF,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21D00 */
+	0x00,  0x00,  0x97,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01, 	/* 21D10 */
+	0x80,  0x01,  0xFF,  0x01,  0xFF,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21D20 */
+	0x00,  0x00,  0x00,  0x98,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 21D30 */
+	0x01,  0x00,  0xFF,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21D40 */
+	0x00,  0x00,  0x00,  0x00,  0x9B,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01, 	/* 21D50 */
+	0x80,  0x01,  0x80,  0xFF,  0x80,  0xFF,  0x80,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21D60 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x9C,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 21D70 */
+	0x01,  0x00,  0x01,  0x00,  0x01,  0xFF,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 21D80 */
+	0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x9D,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01, 	/* 21D90 */
+	0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0xFF,  0x01,  0xFF,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01, 	/* 21DA0 */
+	0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0xA0,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80, 	/* 21DB0 */
+	0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0xFF,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80, 	/* 21DC0 */
+	0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0xA3,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01, 	/* 21DD0 */
+	0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0xFF,  0x01,  0xFF,  0x01,  0x80,  0x01,  0x80,  0x01, 	/* 21DE0 */
+	0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0xA4,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 21DF0 */
+	0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0xFF,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 21E00 */
+	0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0xA5,  0x01,  0x00,  0x01,  0x00,  0x01, 	/* 21E10 */
+	0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0xFF,  0x00,  0xFF,  0x00,  0x01,  0x00,  0x01, 	/* 21E20 */
+	0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0xA8,  0x01,  0x80,  0x01,  0x80, 	/* 21E30 */
+	0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0xFF,  0x80,  0x01,  0x80,  0x01,  0x80, 	/* 21E40 */
+	0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0xAB,  0x01,  0x80,  0x01, 	/* 21E50 */
+	0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0xFF,  0x80,  0xFF,  0x80,  0x01, 	/* 21E60 */
+	0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0xAC,  0x00,  0x00, 	/* 21E70 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xFF,  0xFF,  0x01,  0x00, 	/* 21E80 */
+	0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0xAF,  0x00, 	/* 21E90 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xFF,  0xFF,  0xFF, 	/* 21EA0 */
+	0xFF,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0xB0, 	/* 21EB0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xFF,  0xFF, 	/* 21EC0 */
+	0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80, 	/* 21ED0 */
+	0xB3,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xFF, 	/* 21EE0 */
+	0xFF,  0xFF,  0xFF,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01, 	/* 21EF0 */
+	0x80,  0xB4,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 21F00 */
+	0xFF,  0xFF,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21F10 */
+	0x00,  0x00,  0xB7,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01, 	/* 21F20 */
+	0x00,  0xFF,  0xFF,  0xFF,  0xFF,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21F30 */
+	0x00,  0x00,  0x00,  0xB8,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80, 	/* 21F40 */
+	0x01,  0x80,  0xFF,  0xFF,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21F50 */
+	0x00,  0x00,  0x00,  0x00,  0xBB,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01, 	/* 21F60 */
+	0x80,  0x01,  0x80,  0xFF,  0xFF,  0xFF,  0xFF,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 21F70 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0xBC,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 21F80 */
+	0x01,  0x00,  0x01,  0x00,  0xFF,  0xFF,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 21F90 */
+	0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0xBF,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01, 	/* 21FA0 */
+	0x00,  0x01,  0x00,  0x01,  0x00,  0xFF,  0xFF,  0xFF,  0xFF,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01, 	/* 21FB0 */
+	0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x82,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80, 	/* 21FC0 */
+	0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0xFF,  0xFF,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80, 	/* 21FD0 */
+	0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x8B,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01, 	/* 21FE0 */
+	0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0xFF,  0xFF,  0xFF,  0xFF,  0x01,  0x80,  0x01,  0x80,  0x01, 	/* 21FF0 */
+	0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0xA0,  0x00,  0x00,  0x7F,  0xFE,  0x7F,  0xFE, 	/* 22000 */
+	0x7F,  0xFE,  0x7F,  0xFE,  0x7F,  0xFE,  0x7F,  0xFE,  0x7F,  0xFE,  0x7F,  0xFE,  0x7F,  0xFE,  0x7F,  0xFE, 	/* 22010 */
+	0x7F,  0xFE,  0x7F,  0xFE,  0x7F,  0xFE,  0x7F,  0xFE,  0x00,  0x00,  0xA1,  0x00,  0x00,  0x7F,  0xFE,  0x40, 	/* 22020 */
+	0x02,  0x40,  0x02,  0x40,  0x02,  0x40,  0x02,  0x40,  0x02,  0x40,  0x02,  0x40,  0x02,  0x40,  0x02,  0x40, 	/* 22030 */
+	0x02,  0x40,  0x02,  0x40,  0x02,  0x40,  0x02,  0x7F,  0xFE,  0x00,  0x00,  0xB2,  0x00,  0x00,  0x01,  0x00, 	/* 22040 */
+	0x01,  0x00,  0x03,  0x80,  0x03,  0x80,  0x07,  0xC0,  0x07,  0xE0,  0x0F,  0xE0,  0x0F,  0xF0,  0x1F,  0xF0, 	/* 22050 */
+	0x1F,  0xF8,  0x3F,  0xFC,  0x3F,  0xFC,  0x7F,  0xFE,  0x00,  0x00,  0x00,  0x00,  0xB3,  0x00,  0x00,  0x01, 	/* 22060 */
+	0x00,  0x01,  0x00,  0x02,  0x80,  0x02,  0x80,  0x04,  0x40,  0x04,  0x40,  0x08,  0x20,  0x08,  0x10,  0x10, 	/* 22070 */
+	0x10,  0x10,  0x08,  0x20,  0x08,  0x20,  0x04,  0x7F,  0xFE,  0x00,  0x00,  0x00,  0x00,  0xBC,  0x00,  0x00, 	/* 22080 */
+	0x00,  0x00,  0x7F,  0xFE,  0x3F,  0xFC,  0x3F,  0xFC,  0x1F,  0xF8,  0x1F,  0xF0,  0x0F,  0xF0,  0x0F,  0xE0, 	/* 22090 */
+	0x07,  0xE0,  0x07,  0xC0,  0x03,  0x80,  0x03,  0x80,  0x01,  0x00,  0x01,  0x00,  0x00,  0x00,  0xBD,  0x00, 	/* 220A0 */
+	0x00,  0x00,  0x00,  0x7F,  0xFE,  0x20,  0x04,  0x20,  0x08,  0x10,  0x08,  0x10,  0x10,  0x08,  0x10,  0x08, 	/* 220B0 */
+	0x20,  0x04,  0x40,  0x04,  0x40,  0x02,  0x80,  0x02,  0x80,  0x01,  0x00,  0x01,  0x00,  0x00,  0x00,  0x86, 	/* 220C0 */
+	0x01,  0x80,  0x03,  0xC0,  0x07,  0xE0,  0x0F,  0xF0,  0x1F,  0xF8,  0x3F,  0xFC,  0x7F,  0xFE,  0xFF,  0xFF, 	/* 220D0 */
+	0xFF,  0xFF,  0x7F,  0xFE,  0x3F,  0xFC,  0x1F,  0xF8,  0x0F,  0xF0,  0x07,  0xE0,  0x03,  0xC0,  0x01,  0x80, 	/* 220E0 */
+	0x87,  0x01,  0x80,  0x02,  0x40,  0x04,  0x20,  0x08,  0x10,  0x10,  0x08,  0x20,  0x04,  0x40,  0x02,  0x80, 	/* 220F0 */
+	0x01,  0x80,  0x01,  0x40,  0x02,  0x20,  0x04,  0x10,  0x08,  0x08,  0x10,  0x04,  0x20,  0x02,  0x40,  0x01, 	/* 22100 */
+	0x80,  0x8B,  0x00,  0x00,  0x03,  0xC0,  0x0C,  0x30,  0x10,  0x08,  0x20,  0x04,  0x20,  0x04,  0x40,  0x02, 	/* 22110 */
+	0x40,  0x02,  0x40,  0x02,  0x40,  0x02,  0x20,  0x04,  0x20,  0x04,  0x10,  0x08,  0x0C,  0x30,  0x03,  0xC0, 	/* 22120 */
+	0x00,  0x00,  0x8E,  0x00,  0x00,  0x03,  0xC0,  0x0C,  0x30,  0x10,  0x08,  0x23,  0xC4,  0x24,  0x24,  0x48, 	/* 22130 */
+	0x12,  0x48,  0x12,  0x48,  0x12,  0x48,  0x12,  0x24,  0x24,  0x23,  0xC4,  0x10,  0x08,  0x0C,  0x30,  0x03, 	/* 22140 */
+	0xC0,  0x00,  0x00,  0x8F,  0x00,  0x00,  0x03,  0xC0,  0x0F,  0xF0,  0x1F,  0xF8,  0x3F,  0xFC,  0x3F,  0xFC, 	/* 22150 */
+	0x7F,  0xFE,  0x7F,  0xFE,  0x7F,  0xFE,  0x7F,  0xFE,  0x3F,  0xFC,  0x3F,  0xFC,  0x1F,  0xF8,  0x0F,  0xF0, 	/* 22160 */
+	0x03,  0xC0,  0x00,  0x00,  0xAF,  0x03,  0xC0,  0x0C,  0x30,  0x10,  0x08,  0x20,  0x04,  0x40,  0x02,  0x40, 	/* 22170 */
+	0x02,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x40,  0x02,  0x40,  0x02,  0x20,  0x04,  0x10, 	/* 22180 */
+	0x08,  0x0C,  0x30,  0x03,  0xC0,  0x85,  0x00,  0x00,  0x01,  0x00,  0x01,  0x00,  0x03,  0x80,  0x03,  0x80, 	/* 22190 */
+	0x07,  0xC0,  0x7F,  0xFC,  0x3F,  0xF8,  0x1F,  0xF0,  0x0F,  0xE0,  0x0F,  0xE0,  0x1E,  0xF0,  0x1C,  0x70, 	/* 221A0 */
+	0x38,  0x38,  0x20,  0x08,  0x00,  0x00,  0x86,  0x00,  0x00,  0x01,  0x00,  0x01,  0x00,  0x02,  0x80,  0x02, 	/* 221B0 */
+	0x80,  0x04,  0x40,  0x7C,  0x7C,  0x20,  0x08,  0x10,  0x10,  0x08,  0x20,  0x08,  0x20,  0x11,  0x10,  0x12, 	/* 221C0 */
+	0x90,  0x2C,  0x68,  0x30,  0x18,  0x00,  0x00,  0x80,  0x00,  0x00,  0x03,  0xC0,  0x04,  0x20,  0x08,  0x10, 	/* 221D0 */
+	0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x04,  0x20,  0x03,  0xC0,  0x01,  0x00,  0x1F,  0xF8,  0x01,  0x00, 	/* 221E0 */
+	0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x82,  0x00,  0x00,  0x00,  0xFE,  0x00,  0x06,  0x00, 	/* 221F0 */
+	0x0A,  0x00,  0x12,  0x00,  0x22,  0x00,  0x42,  0x1E,  0x82,  0x21,  0x00,  0x40,  0x80,  0x40,  0x80,  0x40, 	/* 22200 */
+	0x80,  0x40,  0x80,  0x21,  0x00,  0x1E,  0x00,  0x00,  0x00,  0xAA,  0x00,  0x80,  0x00,  0x80,  0x00,  0xC0, 	/* 22210 */
+	0x00,  0xE0,  0x00,  0xB0,  0x00,  0x98,  0x00,  0x8C,  0x00,  0x84,  0x00,  0x84,  0x00,  0x88,  0x00,  0x90, 	/* 22220 */
+	0x00,  0x80,  0x0F,  0x80,  0x1F,  0x80,  0x1F,  0x00,  0x0E,  0x00,  0xAD,  0x04,  0x00,  0x04,  0x00,  0x04, 	/* 22230 */
+	0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x05,  0xE0,  0x06,  0x30,  0x04,  0x30,  0x04, 	/* 22240 */
+	0x30,  0x04,  0x60,  0x04,  0xC0,  0x05,  0x00,  0x06,  0x00,  0x04,  0x00,  0xAF,  0x00,  0x20,  0x04,  0x20, 	/* 22250 */
+	0x04,  0x20,  0x04,  0x3C,  0x07,  0xFC,  0x3F,  0xE0,  0x3C,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x3C, 	/* 22260 */
+	0x07,  0xFC,  0x3F,  0xE0,  0x3C,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x00,  0x80,  0x00,  0x00,  0x00, 	/* 22270 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 22280 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x81,  0x00,  0x00, 	/* 22290 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 222A0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x20,  0x00,  0x10,  0x00,  0x08,  0x00,  0x08,  0x00,  0x82,  0x00, 	/* 222B0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 222C0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x30,  0x00,  0x48,  0x00,  0x48,  0x00,  0x30,  0x00,  0x00,  0x00,  0x83, 	/* 222D0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x01,  0x10,  0x01,  0x10,  0x01,  0x10,  0x02,  0x20, 	/* 222E0 */
+	0x02,  0x20,  0x04,  0x40,  0x08,  0x80,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 222F0 */
+	0x85,  0x00,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0xF8,  0x01,  0x08,  0x02,  0x08,  0x02, 	/* 22300 */
+	0x10,  0x04,  0x10,  0x09,  0xA0,  0x10,  0x60,  0x00,  0x10,  0x00,  0x08,  0x00,  0x08,  0x00,  0x00,  0x00, 	/* 22310 */
+	0x00,  0x86,  0x00,  0x00,  0x00,  0x02,  0x00,  0x02,  0x00,  0x04,  0x00,  0x08,  0x01,  0x90,  0x02,  0x60, 	/* 22320 */
+	0x04,  0x40,  0x04,  0xA0,  0x09,  0x00,  0x0A,  0x00,  0x0C,  0x00,  0x08,  0x00,  0x10,  0x00,  0x10,  0x00, 	/* 22330 */
+	0x00,  0x00,  0x87,  0x00,  0x00,  0x03,  0xC0,  0x0C,  0x30,  0x10,  0x08,  0x20,  0x04,  0x20,  0x04,  0x40, 	/* 22340 */
+	0x02,  0x40,  0x02,  0x40,  0x02,  0x40,  0x02,  0x20,  0x04,  0x20,  0x04,  0x10,  0x08,  0x0C,  0x30,  0x03, 	/* 22350 */
+	0xC0,  0x00,  0x00,  0x88,  0x00,  0x08,  0x00,  0x08,  0x00,  0x10,  0x00,  0x10,  0x00,  0x20,  0x00,  0x20, 	/* 22360 */
+	0x00,  0x40,  0x00,  0x80,  0x00,  0x80,  0x00,  0x40,  0x00,  0x20,  0x00,  0x20,  0x00,  0x10,  0x00,  0x10, 	/* 22370 */
+	0x00,  0x08,  0x00,  0x08,  0x89,  0x10,  0x00,  0x10,  0x00,  0x08,  0x00,  0x08,  0x00,  0x04,  0x00,  0x04, 	/* 22380 */
+	0x00,  0x02,  0x00,  0x01,  0x00,  0x01,  0x00,  0x02,  0x00,  0x04,  0x00,  0x04,  0x00,  0x08,  0x00,  0x08, 	/* 22390 */
+	0x00,  0x10,  0x00,  0x10,  0x00,  0x8A,  0x00,  0x24,  0x00,  0x24,  0x00,  0x48,  0x00,  0x48,  0x00,  0x90, 	/* 223A0 */
+	0x00,  0x90,  0x01,  0x20,  0x02,  0x40,  0x02,  0x40,  0x01,  0x20,  0x00,  0x90,  0x00,  0x90,  0x00,  0x48, 	/* 223B0 */
+	0x00,  0x48,  0x00,  0x24,  0x00,  0x24,  0x8B,  0x24,  0x00,  0x24,  0x00,  0x12,  0x00,  0x12,  0x00,  0x09, 	/* 223C0 */
+	0x00,  0x09,  0x00,  0x04,  0x80,  0x02,  0x40,  0x02,  0x40,  0x04,  0x80,  0x09,  0x00,  0x09,  0x00,  0x12, 	/* 223D0 */
+	0x00,  0x12,  0x00,  0x24,  0x00,  0x24,  0x00,  0x8C,  0x00,  0xF8,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80, 	/* 223E0 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x00, 	/* 223F0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x8D,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 22400 */
+	0x00,  0x00,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01, 	/* 22410 */
+	0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x1F,  0x00,  0x8E,  0x01,  0xF8,  0x01,  0x08,  0x01,  0x78, 	/* 22420 */
+	0x01,  0x40,  0x01,  0x40,  0x01,  0x40,  0x01,  0x40,  0x01,  0x40,  0x01,  0x40,  0x01,  0x40,  0x01,  0xC0, 	/* 22430 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x8F,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 22440 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x03,  0x80,  0x02,  0x80,  0x02,  0x80,  0x02,  0x80,  0x02,  0x80,  0x02, 	/* 22450 */
+	0x80,  0x02,  0x80,  0x02,  0x80,  0x1E,  0x80,  0x10,  0x80,  0x1F,  0x80,  0x90,  0x00,  0xF8,  0x00,  0xF0, 	/* 22460 */
+	0x00,  0xE0,  0x00,  0xC0,  0x00,  0xC0,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80, 	/* 22470 */
+	0x00,  0x80,  0x00,  0xC0,  0x00,  0xC0,  0x00,  0xE0,  0x00,  0xF0,  0x00,  0xF8,  0x91,  0x1F,  0x00,  0x0F, 	/* 22480 */
+	0x00,  0x07,  0x00,  0x03,  0x00,  0x03,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01, 	/* 22490 */
+	0x00,  0x01,  0x00,  0x03,  0x00,  0x03,  0x00,  0x07,  0x00,  0x0F,  0x00,  0x1F,  0x00,  0x92,  0x00,  0x00, 	/* 224A0 */
+	0x3F,  0xFC,  0x3F,  0xFC,  0x00,  0x00,  0x00,  0x00,  0x7F,  0xFE,  0x7F,  0xFE,  0x01,  0x80,  0x01,  0x80, 	/* 224B0 */
+	0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x00,  0x00,  0x93,  0x00, 	/* 224C0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x3F,  0xFE,  0x3F,  0xFE,  0x3F,  0xFE,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 224D0 */
+	0x00,  0x00,  0x00,  0x3F,  0xFE,  0x3F,  0xFE,  0x3F,  0xFE,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x94, 	/* 224E0 */
+	0x00,  0x08,  0x00,  0x30,  0x00,  0xC0,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80, 	/* 224F0 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0xC0,  0x00,  0x30,  0x00,  0x08, 	/* 22500 */
+	0x95,  0x10,  0x00,  0x0C,  0x00,  0x03,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01, 	/* 22510 */
+	0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x03,  0x00,  0x0C,  0x00,  0x10, 	/* 22520 */
+	0x00,  0x81,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x02,  0x00,  0x02,  0xC0,  0x0F,  0x00,  0x02,  0x40, 	/* 22530 */
+	0x03,  0xE0,  0x06,  0x50,  0x0A,  0x88,  0x12,  0x88,  0x13,  0x08,  0x12,  0x10,  0x0C,  0x20,  0x00,  0xC0, 	/* 22540 */
+	0x00,  0x00,  0x82,  0x02,  0x00,  0x02,  0x00,  0x02,  0x60,  0x1F,  0x80,  0x02,  0x00,  0x02,  0x40,  0x03, 	/* 22550 */
+	0xF0,  0x04,  0x48,  0x0C,  0x44,  0x14,  0x82,  0x24,  0x82,  0x23,  0x02,  0x25,  0x04,  0x18,  0x18,  0x00, 	/* 22560 */
+	0x60,  0x00,  0x00,  0x83,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 22570 */
+	0x04,  0x00,  0x04,  0x10,  0x08,  0x08,  0x08,  0x08,  0x08,  0x04,  0x08,  0x04,  0x09,  0x04,  0x05,  0x00, 	/* 22580 */
+	0x02,  0x00,  0x00,  0x00,  0x84,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x10,  0x00,  0x10,  0x10,  0x10, 	/* 22590 */
+	0x08,  0x20,  0x04,  0x20,  0x04,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x12,  0x02,  0x12,  0x00,  0x0C, 	/* 225A0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x85,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x01,  0x00,  0x00,  0xC0, 	/* 225B0 */
+	0x00,  0x00,  0x00,  0x00,  0x01,  0xE0,  0x06,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x20,  0x00,  0x20, 	/* 225C0 */
+	0x00,  0x40,  0x01,  0x80,  0x00,  0x00,  0x86,  0x03,  0x00,  0x00,  0xC0,  0x00,  0x00,  0x00,  0x00,  0x03, 	/* 225D0 */
+	0xE0,  0x1C,  0x10,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x10,  0x00,  0x10,  0x00,  0x20,  0x00, 	/* 225E0 */
+	0x40,  0x01,  0x80,  0x06,  0x00,  0x00,  0x00,  0x87,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 225F0 */
+	0x02,  0x00,  0x01,  0x80,  0x00,  0x60,  0x00,  0x00,  0x0F,  0xE0,  0x00,  0x40,  0x00,  0x80,  0x01,  0x00, 	/* 22600 */
+	0x06,  0x80,  0x08,  0x80,  0x10,  0x80,  0x00,  0x78,  0x88,  0x02,  0x00,  0x01,  0x00,  0x00,  0xC0,  0x00, 	/* 22610 */
+	0x00,  0x0F,  0xF0,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x01,  0x00,  0x03,  0x80,  0x04,  0x40,  0x08, 	/* 22620 */
+	0x40,  0x10,  0x40,  0x20,  0x20,  0x00,  0x1C,  0x00,  0x00,  0x89,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 22630 */
+	0x00,  0x00,  0x02,  0x00,  0x02,  0x10,  0x03,  0xC8,  0x1E,  0x08,  0x02,  0x00,  0x03,  0xE0,  0x06,  0x10, 	/* 22640 */
+	0x0A,  0x08,  0x12,  0x08,  0x12,  0x10,  0x0C,  0x60,  0x00,  0x00,  0x8A,  0x02,  0x00,  0x02,  0x00,  0x02, 	/* 22650 */
+	0x18,  0x03,  0xC4,  0x3E,  0x02,  0x02,  0x01,  0x02,  0x00,  0x03,  0xE0,  0x0E,  0x18,  0x12,  0x04,  0x22, 	/* 22660 */
+	0x04,  0x22,  0x04,  0x24,  0x08,  0x18,  0x30,  0x00,  0xC0,  0x00,  0x00,  0x8B,  0x00,  0x00,  0x04,  0x00, 	/* 22670 */
+	0x04,  0x00,  0x04,  0x10,  0x04,  0x08,  0x3F,  0x84,  0x04,  0x44,  0x08,  0x42,  0x08,  0x42,  0x08,  0x42, 	/* 22680 */
+	0x10,  0x40,  0x10,  0x40,  0x20,  0x80,  0x24,  0x80,  0x03,  0x00,  0x00,  0x00,  0x8C,  0x04,  0x00,  0x04, 	/* 22690 */
+	0x0A,  0x04,  0x0A,  0x04,  0x12,  0x04,  0x08,  0x3F,  0x84,  0x04,  0x44,  0x08,  0x42,  0x08,  0x42,  0x08, 	/* 226A0 */
+	0x42,  0x10,  0x40,  0x10,  0x40,  0x20,  0x80,  0x24,  0x80,  0x03,  0x00,  0x00,  0x00,  0x8D,  0x01,  0x00, 	/* 226B0 */
+	0x01,  0x00,  0x01,  0x70,  0x1F,  0x80,  0x00,  0x80,  0x00,  0xF8,  0x3F,  0x40,  0x00,  0x20,  0x00,  0x20, 	/* 226C0 */
+	0x07,  0xD0,  0x08,  0x30,  0x10,  0x00,  0x10,  0x00,  0x0C,  0x00,  0x03,  0xC0,  0x00,  0x00,  0x8E,  0x01, 	/* 226D0 */
+	0x04,  0x01,  0x12,  0x01,  0x7A,  0x1F,  0x88,  0x00,  0x80,  0x00,  0xF8,  0x3F,  0x40,  0x00,  0x20,  0x00, 	/* 226E0 */
+	0x20,  0x07,  0xD0,  0x08,  0x30,  0x10,  0x00,  0x10,  0x00,  0x0C,  0x00,  0x03,  0xC0,  0x00,  0x00,  0x8F, 	/* 226F0 */
+	0x00,  0x20,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x01,  0x00,  0x02,  0x00,  0x04,  0x00,  0x04,  0x00, 	/* 22700 */
+	0x02,  0x00,  0x01,  0x00,  0x00,  0x80,  0x00,  0x40,  0x00,  0x40,  0x00,  0x20,  0x00,  0x20,  0x00,  0x00, 	/* 22710 */
+	0x90,  0x00,  0x20,  0x00,  0x20,  0x00,  0x44,  0x00,  0x92,  0x01,  0x0A,  0x02,  0x08,  0x04,  0x00,  0x04, 	/* 22720 */
+	0x00,  0x02,  0x00,  0x01,  0x00,  0x00,  0x80,  0x00,  0x40,  0x00,  0x40,  0x00,  0x20,  0x00,  0x20,  0x00, 	/* 22730 */
+	0x00,  0x91,  0x00,  0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x1E,  0x23,  0xF0,  0x20,  0x10, 	/* 22740 */
+	0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x28,  0x10,  0x10,  0x10,  0x10,  0x10,  0x00,  0x20,  0x00,  0xC0, 	/* 22750 */
+	0x00,  0x00,  0x92,  0x00,  0x12,  0x10,  0x19,  0x10,  0x15,  0x10,  0x14,  0x10,  0x1E,  0x23,  0xF0,  0x20, 	/* 22760 */
+	0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x28,  0x10,  0x10,  0x10,  0x10,  0x10,  0x00,  0x20,  0x00, 	/* 22770 */
+	0xC0,  0x00,  0x00,  0x93,  0x00,  0x00,  0x00,  0x00,  0x07,  0x00,  0x00,  0xF8,  0x00,  0x00,  0x00,  0x00, 	/* 22780 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x08,  0x04,  0x07,  0xF8, 	/* 22790 */
+	0x00,  0x00,  0x00,  0x00,  0x94,  0x00,  0x00,  0x00,  0x0A,  0x07,  0x0A,  0x00,  0xFA,  0x00,  0x00,  0x00, 	/* 227A0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x08,  0x04,  0x07, 	/* 227B0 */
+	0xF8,  0x00,  0x00,  0x00,  0x00,  0x95,  0x00,  0x80,  0x00,  0x80,  0x00,  0x8C,  0x0F,  0xF0,  0x00,  0x40, 	/* 227C0 */
+	0x00,  0x20,  0x00,  0x20,  0x00,  0x10,  0x03,  0xE8,  0x04,  0x18,  0x08,  0x00,  0x08,  0x00,  0x04,  0x00, 	/* 227D0 */
+	0x03,  0x00,  0x00,  0xF0,  0x00,  0x00,  0x96,  0x01,  0x04,  0x01,  0x12,  0x01,  0x0A,  0x1F,  0xF8,  0x00, 	/* 227E0 */
+	0x80,  0x00,  0x40,  0x00,  0x40,  0x00,  0x20,  0x07,  0xD0,  0x08,  0x30,  0x10,  0x00,  0x10,  0x00,  0x08, 	/* 227F0 */
+	0x00,  0x06,  0x00,  0x01,  0xE0,  0x00,  0x00,  0x97,  0x00,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00, 	/* 22800 */
+	0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x08, 	/* 22810 */
+	0x08,  0x10,  0x04,  0x60,  0x03,  0x80,  0x00,  0x00,  0x98,  0x00,  0x00,  0x08,  0x00,  0x08,  0x10,  0x08, 	/* 22820 */
+	0x48,  0x08,  0x28,  0x08,  0x20,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08, 	/* 22830 */
+	0x08,  0x08,  0x10,  0x04,  0x60,  0x03,  0x80,  0x00,  0x00,  0x99,  0x00,  0x40,  0x00,  0x40,  0x00,  0x7E, 	/* 22840 */
+	0x3F,  0xC0,  0x00,  0x40,  0x00,  0x40,  0x03,  0x40,  0x04,  0xC0,  0x04,  0x40,  0x04,  0x40,  0x04,  0xC0, 	/* 22850 */
+	0x03,  0x40,  0x00,  0x40,  0x00,  0x40,  0x00,  0x80,  0x03,  0x00,  0x9A,  0x00,  0x42,  0x00,  0x49,  0x00, 	/* 22860 */
+	0x7D,  0x3F,  0xC4,  0x00,  0x40,  0x00,  0x40,  0x03,  0x40,  0x04,  0xC0,  0x04,  0x40,  0x04,  0x40,  0x04, 	/* 22870 */
+	0xC0,  0x03,  0x40,  0x00,  0x40,  0x00,  0x40,  0x00,  0x80,  0x03,  0x00,  0x9B,  0x00,  0x00,  0x00,  0x20, 	/* 22880 */
+	0x04,  0x20,  0x04,  0x20,  0x04,  0x3E,  0x07,  0xE0,  0x7C,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20, 	/* 22890 */
+	0x04,  0x40,  0x04,  0x00,  0x02,  0x00,  0x01,  0xF8,  0x00,  0x00,  0x00,  0x00,  0x9C,  0x00,  0x00,  0x00, 	/* 228A0 */
+	0x22,  0x04,  0x29,  0x04,  0x25,  0x04,  0x3C,  0x07,  0xE0,  0x7C,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04, 	/* 228B0 */
+	0x20,  0x04,  0x40,  0x04,  0x00,  0x02,  0x00,  0x01,  0xF8,  0x00,  0x00,  0x00,  0x00,  0x9D,  0x00,  0x00, 	/* 228C0 */
+	0x07,  0xF0,  0x00,  0x40,  0x00,  0x80,  0x01,  0x00,  0x02,  0x00,  0x04,  0x3C,  0x3F,  0xC0,  0x00,  0x80, 	/* 228D0 */
+	0x01,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x01,  0x00,  0x00,  0xE0,  0x00,  0x00,  0x9E,  0x00, 	/* 228E0 */
+	0x04,  0x07,  0xF2,  0x00,  0x4A,  0x00,  0x88,  0x01,  0x00,  0x02,  0x00,  0x04,  0x3C,  0x3F,  0xC0,  0x00, 	/* 228F0 */
+	0x80,  0x01,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x01,  0x00,  0x00,  0xE0,  0x00,  0x00,  0x9F, 	/* 22900 */
+	0x04,  0x00,  0x04,  0x00,  0x04,  0xC0,  0x3F,  0x00,  0x04,  0x00,  0x08,  0x00,  0x08,  0x1C,  0x08,  0xE0, 	/* 22910 */
+	0x08,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x20,  0x80,  0x20,  0x80,  0x20,  0x7E,  0x00,  0x00, 	/* 22920 */
+	0xA0,  0x04,  0x00,  0x04,  0x04,  0x04,  0xD2,  0x3F,  0x0A,  0x04,  0x08,  0x08,  0x00,  0x08,  0x1C,  0x08, 	/* 22930 */
+	0xE0,  0x08,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x20,  0x80,  0x20,  0x80,  0x20,  0x7E,  0x00, 	/* 22940 */
+	0x00,  0xA1,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x3F,  0xF0,  0x02,  0x00,  0x04,  0x00,  0x04,  0x00, 	/* 22950 */
+	0x04,  0xF0,  0x0B,  0x08,  0x0C,  0x04,  0x08,  0x04,  0x00,  0x04,  0x00,  0x08,  0x00,  0x30,  0x03,  0xC0, 	/* 22960 */
+	0x00,  0x00,  0xA2,  0x02,  0x04,  0x02,  0x12,  0x02,  0x0A,  0x3F,  0xF8,  0x02,  0x00,  0x04,  0x00,  0x04, 	/* 22970 */
+	0x00,  0x04,  0xF0,  0x0B,  0x08,  0x0C,  0x04,  0x08,  0x04,  0x00,  0x04,  0x00,  0x08,  0x00,  0x30,  0x03, 	/* 22980 */
+	0xC0,  0x00,  0x00,  0xA3,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 22990 */
+	0x00,  0x00,  0x00,  0x00,  0x01,  0xF0,  0x0E,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x10,  0x00,  0x60, 	/* 229A0 */
+	0x01,  0x80,  0x00,  0x00,  0xA4,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xE0,  0x07,  0x18,  0x78, 	/* 229B0 */
+	0x04,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x04,  0x00,  0x08,  0x00,  0x30,  0x01,  0xC0,  0x00, 	/* 229C0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0xA5,  0x00,  0x02,  0x00,  0x09,  0x00,  0x05,  0x00,  0xE4,  0x07,  0x18, 	/* 229D0 */
+	0x78,  0x04,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x04,  0x00,  0x08,  0x00,  0x30,  0x01,  0xC0, 	/* 229E0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xA6,  0x00,  0x00,  0x00,  0x0E,  0x03,  0xF0,  0x7C,  0x20,  0x00, 	/* 229F0 */
+	0x40,  0x00,  0x80,  0x00,  0x80,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x00,  0x80,  0x00, 	/* 22A00 */
+	0x40,  0x00,  0x38,  0x00,  0x00,  0x00,  0x00,  0xA7,  0x00,  0x00,  0x00,  0x0E,  0x03,  0xF0,  0x7C,  0x22, 	/* 22A10 */
+	0x00,  0x49,  0x00,  0x85,  0x00,  0x84,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x00,  0x80, 	/* 22A20 */
+	0x00,  0x40,  0x00,  0x38,  0x00,  0x00,  0x00,  0x00,  0xA8,  0x00,  0x00,  0x04,  0x00,  0x04,  0x00,  0x02, 	/* 22A30 */
+	0x00,  0x02,  0x00,  0x01,  0x0C,  0x01,  0x30,  0x00,  0xC0,  0x01,  0x00,  0x02,  0x00,  0x04,  0x00,  0x08, 	/* 22A40 */
+	0x00,  0x08,  0x00,  0x04,  0x00,  0x03,  0xFC,  0x00,  0x00,  0xA9,  0x00,  0x00,  0x08,  0x04,  0x08,  0x12, 	/* 22A50 */
+	0x04,  0x0A,  0x04,  0x08,  0x02,  0x18,  0x02,  0x60,  0x01,  0x80,  0x02,  0x00,  0x04,  0x00,  0x08,  0x00, 	/* 22A60 */
+	0x10,  0x00,  0x10,  0x00,  0x08,  0x00,  0x07,  0xF8,  0x00,  0x00,  0xAA,  0x04,  0x00,  0x04,  0x00,  0x07, 	/* 22A70 */
+	0x80,  0x3C,  0x18,  0x04,  0x04,  0x08,  0x22,  0x08,  0x20,  0x08,  0x20,  0x10,  0x20,  0x10,  0x20,  0x20, 	/* 22A80 */
+	0x20,  0x03,  0xE0,  0x04,  0x38,  0x04,  0x24,  0x03,  0xC0,  0x00,  0x00,  0xAB,  0x00,  0x00,  0x10,  0x00, 	/* 22A90 */
+	0x10,  0x00,  0x10,  0x38,  0x11,  0xC0,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00, 	/* 22AA0 */
+	0x22,  0x00,  0x22,  0x00,  0x21,  0x80,  0x28,  0x7C,  0x10,  0x00,  0x00,  0x00,  0xAC,  0x00,  0x00,  0x00, 	/* 22AB0 */
+	0x80,  0x10,  0x80,  0x10,  0x80,  0x13,  0xF0,  0x1C,  0x88,  0x10,  0x84,  0x10,  0x82,  0x29,  0x02,  0x29, 	/* 22AC0 */
+	0x02,  0x46,  0x02,  0x44,  0x3A,  0x4A,  0x44,  0x30,  0x44,  0x00,  0x3A,  0x00,  0x00,  0xAD,  0x08,  0x00, 	/* 22AD0 */
+	0x08,  0x00,  0x08,  0x00,  0x0C,  0x70,  0x78,  0x88,  0x09,  0x04,  0x0A,  0x04,  0x0C,  0x04,  0x08,  0x04, 	/* 22AE0 */
+	0x18,  0x04,  0x18,  0x3C,  0x28,  0x44,  0x48,  0x46,  0x08,  0x38,  0x08,  0x00,  0x00,  0x00,  0xAE,  0x00, 	/* 22AF0 */
+	0x00,  0x00,  0x00,  0x01,  0xE0,  0x06,  0x90,  0x08,  0x88,  0x10,  0x84,  0x10,  0x84,  0x21,  0x02,  0x21, 	/* 22B00 */
+	0x02,  0x22,  0x04,  0x24,  0x04,  0x18,  0x08,  0x00,  0x10,  0x00,  0x60,  0x00,  0x00,  0x00,  0x00,  0xAF, 	/* 22B10 */
+	0x00,  0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x1E,  0x23,  0xF0,  0x20,  0x10,  0x20,  0x10, 	/* 22B20 */
+	0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x21,  0xF0,  0x2A,  0x1C,  0x12,  0x12,  0x11,  0xE0,  0x00,  0x00, 	/* 22B30 */
+	0xB0,  0x00,  0x10,  0x10,  0x15,  0x10,  0x15,  0x10,  0x15,  0x10,  0x1E,  0x13,  0xF0,  0x20,  0x10,  0x20, 	/* 22B40 */
+	0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x21,  0xF0,  0x2A,  0x1C,  0x12,  0x12,  0x11,  0xE0,  0x00, 	/* 22B50 */
+	0x00,  0xB1,  0x00,  0x16,  0x10,  0x19,  0x10,  0x19,  0x10,  0x16,  0x10,  0x1E,  0x13,  0xF0,  0x20,  0x10, 	/* 22B60 */
+	0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x21,  0xF0,  0x2A,  0x1C,  0x12,  0x12,  0x11,  0xE0, 	/* 22B70 */
+	0x00,  0x00,  0xB2,  0x00,  0x00,  0x01,  0x00,  0x0F,  0x00,  0x72,  0x10,  0x04,  0x10,  0x08,  0x18,  0x10, 	/* 22B80 */
+	0x18,  0x10,  0x14,  0x20,  0x12,  0x20,  0x10,  0x20,  0x10,  0x20,  0x20,  0x10,  0x20,  0x08,  0xC0,  0x07, 	/* 22B90 */
+	0x00,  0x00,  0x00,  0xB3,  0x00,  0x00,  0x01,  0x02,  0x0F,  0x09,  0x72,  0x15,  0x04,  0x14,  0x08,  0x18, 	/* 22BA0 */
+	0x10,  0x18,  0x10,  0x14,  0x20,  0x12,  0x20,  0x10,  0x20,  0x10,  0x20,  0x20,  0x10,  0x20,  0x08,  0xC0, 	/* 22BB0 */
+	0x07,  0x00,  0x00,  0x00,  0xB4,  0x00,  0x06,  0x01,  0x09,  0x0F,  0x09,  0x72,  0x16,  0x04,  0x10,  0x08, 	/* 22BC0 */
+	0x18,  0x10,  0x18,  0x10,  0x14,  0x20,  0x12,  0x20,  0x10,  0x20,  0x10,  0x20,  0x20,  0x10,  0x20,  0x08, 	/* 22BD0 */
+	0xC0,  0x07,  0x00,  0x00,  0x00,  0xB5,  0x00,  0x00,  0x02,  0x00,  0x01,  0xC0,  0x00,  0x40,  0x00,  0x80, 	/* 22BE0 */
+	0x01,  0x00,  0x01,  0x00,  0x00,  0x88,  0x10,  0x44,  0x10,  0x42,  0x20,  0x21,  0x20,  0x21,  0x40,  0x20, 	/* 22BF0 */
+	0x04,  0x40,  0x03,  0x80,  0x00,  0x00,  0xB6,  0x00,  0x00,  0x02,  0x04,  0x01,  0xD2,  0x00,  0x4A,  0x00, 	/* 22C00 */
+	0x88,  0x01,  0x00,  0x01,  0x00,  0x00,  0x88,  0x10,  0x44,  0x10,  0x42,  0x20,  0x21,  0x20,  0x21,  0x40, 	/* 22C10 */
+	0x20,  0x04,  0x40,  0x03,  0x80,  0x00,  0x00,  0xB7,  0x00,  0x0C,  0x02,  0x12,  0x01,  0xD2,  0x00,  0x4C, 	/* 22C20 */
+	0x00,  0x80,  0x01,  0x00,  0x01,  0x00,  0x00,  0x88,  0x10,  0x44,  0x10,  0x42,  0x20,  0x21,  0x20,  0x21, 	/* 22C30 */
+	0x40,  0x20,  0x04,  0x40,  0x03,  0x80,  0x00,  0x00,  0xB8,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 22C40 */
+	0x00,  0x06,  0x00,  0x09,  0x00,  0x10,  0x80,  0x20,  0x40,  0x40,  0x20,  0x00,  0x18,  0x00,  0x06,  0x00, 	/* 22C50 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xB9,  0x00,  0x00,  0x00,  0x00,  0x00,  0x08, 	/* 22C60 */
+	0x00,  0x24,  0x06,  0x14,  0x09,  0x10,  0x10,  0x80,  0x20,  0x40,  0x40,  0x20,  0x00,  0x18,  0x00,  0x06, 	/* 22C70 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xBA,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 22C80 */
+	0x18,  0x00,  0x24,  0x00,  0x24,  0x06,  0x18,  0x09,  0x00,  0x10,  0x80,  0x20,  0x40,  0x40,  0x20,  0x00, 	/* 22C90 */
+	0x18,  0x00,  0x06,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xBB,  0x00,  0x00,  0x13,  0xFC, 	/* 22CA0 */
+	0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x20,  0x1C,  0x23,  0xF0,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10, 	/* 22CB0 */
+	0x20,  0x10,  0x21,  0xF0,  0x2A,  0x1C,  0x12,  0x12,  0x11,  0xE0,  0x00,  0x00,  0xBC,  0x00,  0x02,  0x13, 	/* 22CC0 */
+	0xF9,  0x10,  0x15,  0x10,  0x14,  0x10,  0x10,  0x20,  0x1C,  0x23,  0xF0,  0x20,  0x10,  0x20,  0x10,  0x20, 	/* 22CD0 */
+	0x10,  0x20,  0x10,  0x21,  0xF0,  0x2A,  0x1C,  0x12,  0x12,  0x11,  0xE0,  0x00,  0x00,  0xBD,  0x00,  0x06, 	/* 22CE0 */
+	0x13,  0xF9,  0x10,  0x19,  0x10,  0x16,  0x10,  0x10,  0x20,  0x1C,  0x23,  0xF0,  0x20,  0x10,  0x20,  0x10, 	/* 22CF0 */
+	0x20,  0x10,  0x20,  0x10,  0x21,  0xF0,  0x2A,  0x1C,  0x12,  0x12,  0x11,  0xE0,  0x00,  0x00,  0xBE,  0x00, 	/* 22D00 */
+	0x40,  0x00,  0x40,  0x1F,  0xFC,  0x00,  0x40,  0x00,  0x40,  0x00,  0x78,  0x1F,  0xC0,  0x00,  0x40,  0x00, 	/* 22D10 */
+	0x40,  0x00,  0x40,  0x07,  0xC0,  0x08,  0x70,  0x10,  0x4C,  0x18,  0x40,  0x07,  0x80,  0x00,  0x00,  0xBF, 	/* 22D20 */
+	0x00,  0x00,  0x00,  0x00,  0x1F,  0x80,  0x00,  0x80,  0x00,  0x80,  0x01,  0x08,  0x01,  0x08,  0x01,  0x08, 	/* 22D30 */
+	0x07,  0xE8,  0x1A,  0x1C,  0x22,  0x12,  0x44,  0x10,  0x48,  0x20,  0x30,  0x20,  0x00,  0x40,  0x00,  0x00, 	/* 22D40 */
+	0x80,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x3F,  0x88,  0x04,  0x04,  0x04,  0x04,  0x1C,  0x02,  0x24, 	/* 22D50 */
+	0x02,  0x24,  0x10,  0x24,  0x08,  0x28,  0x08,  0x18,  0x08,  0x08,  0x08,  0x08,  0x10,  0x07,  0xE0,  0x00, 	/* 22D60 */
+	0x00,  0x81,  0x00,  0x00,  0x00,  0x40,  0x10,  0x40,  0x10,  0x40,  0x11,  0xF0,  0x16,  0x88,  0x18,  0x84, 	/* 22D70 */
+	0x18,  0x84,  0x29,  0x02,  0x25,  0x02,  0x42,  0x02,  0x42,  0x04,  0x4D,  0x04,  0x30,  0x08,  0x00,  0x30, 	/* 22D80 */
+	0x00,  0x00,  0x82,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x1F,  0xC0,  0x02,  0x00,  0x02,  0x00,  0x04, 	/* 22D90 */
+	0x60,  0x3F,  0x80,  0x04,  0x00,  0x04,  0x04,  0x04,  0x04,  0x04,  0x04,  0x02,  0x08,  0x01,  0x10,  0x00, 	/* 22DA0 */
+	0xE0,  0x00,  0x00,  0x83,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xC0,  0x08,  0x20, 	/* 22DB0 */
+	0x08,  0x00,  0x04,  0xF0,  0x07,  0x08,  0x0C,  0x08,  0x32,  0x10,  0x02,  0x60,  0x01,  0x00,  0x01,  0x00, 	/* 22DC0 */
+	0x01,  0x00,  0x00,  0x00,  0x84,  0x00,  0x40,  0x00,  0x20,  0x10,  0x10,  0x10,  0x10,  0x08,  0x00,  0x08, 	/* 22DD0 */
+	0x7C,  0x05,  0x82,  0x0E,  0x02,  0x74,  0x02,  0x02,  0x04,  0x02,  0x38,  0x01,  0x00,  0x01,  0x00,  0x00, 	/* 22DE0 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x85,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x80, 	/* 22DF0 */
+	0x10,  0x80,  0x11,  0xE0,  0x12,  0x90,  0x14,  0x88,  0x18,  0x88,  0x18,  0x88,  0x12,  0x90,  0x11,  0xE0, 	/* 22E00 */
+	0x00,  0x80,  0x01,  0x00,  0x02,  0x00,  0x86,  0x00,  0x00,  0x00,  0x80,  0x20,  0x40,  0x20,  0xF8,  0x23, 	/* 22E10 */
+	0x44,  0x24,  0x42,  0x28,  0x42,  0x30,  0x42,  0x30,  0x42,  0x22,  0x44,  0x21,  0x48,  0x20,  0xF0,  0x00, 	/* 22E20 */
+	0x40,  0x00,  0x80,  0x01,  0x00,  0x00,  0x00,  0x87,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 22E30 */
+	0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0xE0,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x0F,  0x00, 	/* 22E40 */
+	0x11,  0xC0,  0x11,  0x30,  0x0E,  0x00,  0x00,  0x00,  0x88,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 22E50 */
+	0x8C,  0x00,  0xF0,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x0F,  0x80,  0x30, 	/* 22E60 */
+	0xE0,  0x20,  0x98,  0x21,  0x04,  0x1E,  0x00,  0x00,  0x00,  0x89,  0x01,  0x00,  0x00,  0x80,  0x00,  0x60, 	/* 22E70 */
+	0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0xF0,  0x0B,  0x08,  0x0C,  0x04,  0x08,  0x04, 	/* 22E80 */
+	0x00,  0x08,  0x00,  0x10,  0x00,  0x60,  0x03,  0x80,  0x00,  0x00,  0x8A,  0x00,  0x20,  0x04,  0x10,  0x04, 	/* 22E90 */
+	0x10,  0x04,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x0A,  0x10,  0x04,  0x10,  0x00, 	/* 22EA0 */
+	0x20,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x03,  0x00,  0x00,  0x00,  0x8B,  0x00,  0x00,  0x07,  0xE0, 	/* 22EB0 */
+	0x00,  0x40,  0x00,  0x80,  0x01,  0x00,  0x02,  0x00,  0x07,  0xE0,  0x0C,  0x10,  0x10,  0x08,  0x20,  0x04, 	/* 22EC0 */
+	0x00,  0x04,  0x03,  0x04,  0x04,  0x88,  0x04,  0x70,  0x03,  0xC0,  0x00,  0x00,  0x8C,  0x04,  0x00,  0x04, 	/* 22ED0 */
+	0x00,  0x04,  0x00,  0x04,  0xE0,  0x0D,  0x10,  0x76,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x0C, 	/* 22EE0 */
+	0x10,  0x0C,  0x10,  0x14,  0x11,  0x24,  0x12,  0x44,  0x0C,  0x04,  0x00,  0x00,  0x00,  0x8D,  0x00,  0x00, 	/* 22EF0 */
+	0x07,  0xE0,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x01,  0x00,  0x03,  0xF0,  0x06,  0x08,  0x08,  0x04, 	/* 22F00 */
+	0x10,  0x04,  0x00,  0x04,  0x00,  0x08,  0x00,  0x10,  0x00,  0x60,  0x01,  0x80,  0x00,  0x00,  0x8E,  0x00, 	/* 22F10 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x06,  0xE0,  0x1D, 	/* 22F20 */
+	0x10,  0x06,  0x08,  0x04,  0x08,  0x0C,  0x08,  0x14,  0x10,  0x04,  0x60,  0x04,  0x00,  0x04,  0x00,  0x8F, 	/* 22F30 */
+	0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x0E,  0x00,  0x1C,  0x00,  0x68,  0xF0,  0x0B,  0x08,  0x0C,  0x04, 	/* 22F40 */
+	0x08,  0x02,  0x18,  0x02,  0x28,  0x04,  0x48,  0x04,  0x08,  0x18,  0x08,  0x60,  0x08,  0x00,  0x00,  0x00, 	/* 22F50 */
+	0x90,  0x00,  0x00,  0x0F,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x03,  0xF0,  0x0D, 	/* 22F60 */
+	0x08,  0x11,  0x04,  0x22,  0x02,  0x42,  0x02,  0x44,  0x72,  0x48,  0x8C,  0x30,  0x8A,  0x00,  0x70,  0x00, 	/* 22F70 */
+	0x00,  0x91,  0x00,  0x00,  0x1F,  0xC0,  0x00,  0x80,  0x03,  0x00,  0x07,  0xC0,  0x08,  0x20,  0x10,  0x10, 	/* 22F80 */
+	0x06,  0x10,  0x09,  0x20,  0x09,  0x40,  0x07,  0x80,  0x04,  0x00,  0x0E,  0x70,  0x31,  0x88,  0x40,  0x1C, 	/* 22F90 */
+	0x00,  0x00,  0x92,  0x01,  0x00,  0x01,  0x00,  0x01,  0xE0,  0x1F,  0x00,  0x02,  0x00,  0x02,  0x06,  0x07, 	/* 22FA0 */
+	0x98,  0x08,  0x60,  0x10,  0xC0,  0x21,  0x40,  0x02,  0x40,  0x04,  0x40,  0x04,  0x00,  0x02,  0x00,  0x01, 	/* 22FB0 */
+	0xF8,  0x00,  0x00,  0x93,  0x00,  0x80,  0x00,  0x80,  0x01,  0x00,  0x01,  0x00,  0x02,  0x00,  0x02,  0x00, 	/* 22FC0 */
+	0x02,  0x00,  0x05,  0x80,  0x06,  0x40,  0x0C,  0x40,  0x08,  0x40,  0x10,  0x41,  0x10,  0x42,  0x20,  0x24, 	/* 22FD0 */
+	0x20,  0x18,  0x00,  0x00,  0x9B,  0x10,  0x00,  0x48,  0x00,  0x28,  0x00,  0x20,  0x00,  0x00,  0x00,  0x00, 	/* 22FE0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 22FF0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x9C,  0x00,  0x00,  0x60,  0x00,  0x90,  0x00,  0x90,  0x00,  0x60,  0x00, 	/* 23000 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 23010 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x9D,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0C, 	/* 23020 */
+	0x00,  0x03,  0x00,  0x00,  0x80,  0x00,  0x40,  0x00,  0x20,  0x00,  0x70,  0x00,  0x80,  0x01,  0x00,  0x00, 	/* 23030 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x9E,  0x00,  0x00,  0x00,  0x00,  0x00,  0x10,  0x00,  0x48, 	/* 23040 */
+	0x0C,  0x28,  0x03,  0x20,  0x00,  0x80,  0x00,  0x40,  0x00,  0x20,  0x00,  0x70,  0x00,  0x80,  0x01,  0x00, 	/* 23050 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xA1,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 23060 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x1F,  0xF0,  0x01,  0x10,  0x01,  0x20,  0x01,  0x40,  0x01, 	/* 23070 */
+	0x00,  0x01,  0x00,  0x02,  0x00,  0x04,  0x00,  0x00,  0x00,  0xA2,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 23080 */
+	0x7F,  0xFC,  0x00,  0x04,  0x01,  0x04,  0x01,  0x08,  0x01,  0x10,  0x01,  0x60,  0x01,  0x00,  0x01,  0x00, 	/* 23090 */
+	0x02,  0x00,  0x02,  0x00,  0x04,  0x00,  0x18,  0x00,  0x00,  0x00,  0xA3,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 230A0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x10,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x03,  0x80,  0x0C, 	/* 230B0 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x00,  0xA4,  0x00,  0x00,  0x00,  0x10, 	/* 230C0 */
+	0x00,  0x10,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x03,  0x80,  0x0C,  0x80,  0x30,  0x80,  0x00,  0x80, 	/* 230D0 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x00,  0xA5,  0x00,  0x00,  0x00, 	/* 230E0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x0F,  0xF8,  0x08,  0x08,  0x08, 	/* 230F0 */
+	0x08,  0x08,  0x10,  0x00,  0x10,  0x00,  0x20,  0x00,  0xC0,  0x03,  0x00,  0x00,  0x00,  0xA6,  0x00,  0x00, 	/* 23100 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04, 	/* 23110 */
+	0x00,  0x08,  0x00,  0x08,  0x00,  0x10,  0x00,  0x20,  0x00,  0xC0,  0x03,  0x00,  0x00,  0x00,  0xA7,  0x00, 	/* 23120 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0F, 	/* 23130 */
+	0xE0,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x1F,  0xF0,  0x00,  0x00,  0xA8, 	/* 23140 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x1F,  0xF8,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80, 	/* 23150 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFE,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 23160 */
+	0xA9,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x40,  0x00,  0x40,  0x00, 	/* 23170 */
+	0x40,  0x0F,  0xF8,  0x00,  0xC0,  0x01,  0x40,  0x02,  0x40,  0x04,  0x40,  0x08,  0x40,  0x00,  0xC0,  0x00, 	/* 23180 */
+	0x00,  0xAA,  0x00,  0x00,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x1F,  0xFE,  0x00,  0x20,  0x00,  0x60, 	/* 23190 */
+	0x00,  0xA0,  0x00,  0xA0,  0x01,  0x20,  0x02,  0x20,  0x04,  0x20,  0x18,  0x20,  0x00,  0x20,  0x00,  0xE0, 	/* 231A0 */
+	0x00,  0x00,  0xAB,  0x00,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x3F,  0xF8,  0x01,  0x08,  0x01, 	/* 231B0 */
+	0x08,  0x01,  0x08,  0x01,  0x08,  0x02,  0x08,  0x02,  0x08,  0x04,  0x08,  0x08,  0x08,  0x10,  0x10,  0x20, 	/* 231C0 */
+	0x60,  0x00,  0x00,  0xAC,  0x00,  0x00,  0x01,  0x02,  0x01,  0x09,  0x01,  0x05,  0x3F,  0xFC,  0x01,  0x08, 	/* 231D0 */
+	0x01,  0x08,  0x01,  0x08,  0x01,  0x08,  0x02,  0x08,  0x02,  0x08,  0x04,  0x08,  0x08,  0x08,  0x10,  0x10, 	/* 231E0 */
+	0x20,  0x60,  0x00,  0x00,  0xAD,  0x00,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x18,  0x01,  0xE0,  0x1E, 	/* 231F0 */
+	0x80,  0x00,  0x80,  0x00,  0x8E,  0x00,  0xF0,  0x03,  0x40,  0x3C,  0x40,  0x00,  0x40,  0x00,  0x40,  0x00, 	/* 23200 */
+	0x20,  0x00,  0x20,  0x00,  0x20,  0xAE,  0x00,  0x00,  0x01,  0x04,  0x01,  0x12,  0x01,  0x1A,  0x01,  0xE8, 	/* 23210 */
+	0x1E,  0x80,  0x00,  0x80,  0x00,  0x8E,  0x00,  0xF0,  0x03,  0x40,  0x3C,  0x40,  0x00,  0x40,  0x00,  0x40, 	/* 23220 */
+	0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0xAF,  0x00,  0x00,  0x00,  0x80,  0x00,  0x80,  0x01,  0xFC,  0x01, 	/* 23230 */
+	0x04,  0x02,  0x08,  0x04,  0x08,  0x08,  0x10,  0x10,  0x10,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x01, 	/* 23240 */
+	0x00,  0x06,  0x00,  0x18,  0x00,  0x00,  0x00,  0xB0,  0x00,  0x02,  0x01,  0x09,  0x01,  0x05,  0x03,  0xF4, 	/* 23250 */
+	0x02,  0x10,  0x04,  0x10,  0x08,  0x20,  0x10,  0x20,  0x20,  0x40,  0x00,  0x40,  0x00,  0x80,  0x01,  0x00, 	/* 23260 */
+	0x02,  0x00,  0x0C,  0x00,  0x30,  0x00,  0x00,  0x00,  0xB1,  0x00,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04, 	/* 23270 */
+	0x00,  0x07,  0xFE,  0x04,  0x20,  0x08,  0x20,  0x08,  0x20,  0x10,  0x20,  0x20,  0x20,  0x00,  0x40,  0x00, 	/* 23280 */
+	0x40,  0x00,  0x80,  0x01,  0x00,  0x06,  0x00,  0x00,  0x00,  0xB2,  0x00,  0x00,  0x04,  0x02,  0x04,  0x09, 	/* 23290 */
+	0x04,  0x05,  0x07,  0xFC,  0x04,  0x20,  0x08,  0x20,  0x08,  0x20,  0x10,  0x20,  0x20,  0x20,  0x00,  0x40, 	/* 232A0 */
+	0x00,  0x40,  0x00,  0x80,  0x01,  0x00,  0x06,  0x00,  0x00,  0x00,  0xB3,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 232B0 */
+	0x00,  0x3F,  0xF8,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00, 	/* 232C0 */
+	0x08,  0x00,  0x08,  0x3F,  0xF8,  0x00,  0x08,  0x00,  0x00,  0x00,  0x00,  0xB4,  0x00,  0x02,  0x00,  0x09, 	/* 232D0 */
+	0x00,  0x05,  0x3F,  0xFC,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08, 	/* 232E0 */
+	0x00,  0x08,  0x00,  0x08,  0x3F,  0xF8,  0x00,  0x08,  0x00,  0x00,  0x00,  0x00,  0xB5,  0x00,  0x00,  0x04, 	/* 232F0 */
+	0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFE,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04, 	/* 23300 */
+	0x10,  0x04,  0x20,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x03,  0x00,  0x00,  0x00,  0xB6,  0x00,  0x02, 	/* 23310 */
+	0x04,  0x19,  0x04,  0x15,  0x04,  0x14,  0x04,  0x10,  0x7F,  0xFE,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10, 	/* 23320 */
+	0x04,  0x10,  0x04,  0x20,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x03,  0x00,  0x00,  0x00,  0xB7,  0x00, 	/* 23330 */
+	0x00,  0x00,  0x00,  0x0C,  0x00,  0x02,  0x00,  0x00,  0x00,  0x00,  0x02,  0x18,  0x02,  0x04,  0x04,  0x00, 	/* 23340 */
+	0x04,  0x00,  0x08,  0x00,  0x10,  0x00,  0x20,  0x00,  0xC0,  0x03,  0x00,  0x1C,  0x00,  0x00,  0x00,  0xB8, 	/* 23350 */
+	0x00,  0x00,  0x00,  0x04,  0x0C,  0x12,  0x02,  0x0A,  0x00,  0x08,  0x00,  0x02,  0x18,  0x02,  0x04,  0x04, 	/* 23360 */
+	0x00,  0x04,  0x00,  0x08,  0x00,  0x10,  0x00,  0x20,  0x00,  0xC0,  0x03,  0x00,  0x1C,  0x00,  0x00,  0x00, 	/* 23370 */
+	0xB9,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x1F,  0xE0,  0x00,  0x20,  0x00,  0x20,  0x00,  0x40,  0x00, 	/* 23380 */
+	0x40,  0x00,  0x80,  0x00,  0xC0,  0x01,  0x20,  0x02,  0x10,  0x04,  0x08,  0x18,  0x04,  0x60,  0x04,  0x00, 	/* 23390 */
+	0x00,  0xBA,  0x00,  0x00,  0x00,  0x04,  0x00,  0x12,  0x1F,  0xEA,  0x00,  0x28,  0x00,  0x20,  0x00,  0x40, 	/* 233A0 */
+	0x00,  0x40,  0x00,  0x80,  0x00,  0xC0,  0x01,  0x20,  0x02,  0x10,  0x04,  0x08,  0x18,  0x04,  0x60,  0x04, 	/* 233B0 */
+	0x00,  0x00,  0xBB,  0x00,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02,  0x1E,  0x03,  0xE2,  0x3E, 	/* 233C0 */
+	0x04,  0x02,  0x08,  0x02,  0x10,  0x02,  0x20,  0x02,  0x00,  0x02,  0x00,  0x01,  0x00,  0x00,  0xFC,  0x00, 	/* 233D0 */
+	0x00,  0x00,  0x00,  0xBC,  0x00,  0x02,  0x02,  0x09,  0x02,  0x05,  0x02,  0x04,  0x02,  0x1E,  0x03,  0xE2, 	/* 233E0 */
+	0x3E,  0x04,  0x02,  0x08,  0x02,  0x10,  0x02,  0x20,  0x02,  0x00,  0x02,  0x00,  0x01,  0x00,  0x00,  0xFC, 	/* 233F0 */
+	0x00,  0x00,  0x00,  0x00,  0xBD,  0x00,  0x00,  0x00,  0x00,  0x00,  0x04,  0x10,  0x04,  0x08,  0x04,  0x04, 	/* 23400 */
+	0x04,  0x04,  0x08,  0x04,  0x08,  0x00,  0x10,  0x00,  0x10,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x03, 	/* 23410 */
+	0x00,  0x0C,  0x00,  0x00,  0x00,  0xBE,  0x00,  0x00,  0x00,  0x04,  0x00,  0x12,  0x20,  0x0A,  0x10,  0x08, 	/* 23420 */
+	0x08,  0x08,  0x08,  0x10,  0x08,  0x10,  0x00,  0x20,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x01,  0x00, 	/* 23430 */
+	0x06,  0x00,  0x18,  0x00,  0x00,  0x00,  0xBF,  0x00,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0xFC,  0x02, 	/* 23440 */
+	0x04,  0x04,  0x08,  0x08,  0x08,  0x33,  0x10,  0x00,  0xD0,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x01, 	/* 23450 */
+	0x00,  0x06,  0x00,  0x38,  0x00,  0x00,  0x00,  0x80,  0x00,  0x02,  0x01,  0x09,  0x01,  0x05,  0x01,  0xFC, 	/* 23460 */
+	0x02,  0x04,  0x04,  0x08,  0x08,  0x08,  0x33,  0x10,  0x00,  0xD0,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80, 	/* 23470 */
+	0x01,  0x00,  0x06,  0x00,  0x38,  0x00,  0x00,  0x00,  0x81,  0x00,  0x00,  0x00,  0x10,  0x00,  0xE0,  0x1F, 	/* 23480 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x01, 	/* 23490 */
+	0x00,  0x01,  0x00,  0x02,  0x00,  0x0C,  0x00,  0x00,  0x00,  0x82,  0x00,  0x04,  0x00,  0x12,  0x00,  0xEA, 	/* 234A0 */
+	0x1F,  0x88,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80, 	/* 234B0 */
+	0x01,  0x00,  0x01,  0x00,  0x02,  0x00,  0x0C,  0x00,  0x00,  0x00,  0x83,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 234C0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x02,  0x00,  0x11,  0x10,  0x09,  0x10,  0x08,  0x10,  0x00, 	/* 234D0 */
+	0x20,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x03,  0x00,  0x00,  0x00,  0x84,  0x00,  0x00,  0x00,  0x00, 	/* 234E0 */
+	0x02,  0x00,  0x21,  0x04,  0x11,  0x04,  0x11,  0x04,  0x10,  0x08,  0x00,  0x08,  0x00,  0x10,  0x00,  0x10, 	/* 234F0 */
+	0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x03,  0x00,  0x0C,  0x00,  0x00,  0x00,  0x85,  0x00,  0x02,  0x00, 	/* 23500 */
+	0x09,  0x02,  0x05,  0x21,  0x04,  0x11,  0x08,  0x11,  0x08,  0x10,  0x08,  0x00,  0x10,  0x00,  0x10,  0x00, 	/* 23510 */
+	0x20,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x03,  0x00,  0x0C,  0x00,  0x00,  0x00,  0x86,  0x00,  0x00, 	/* 23520 */
+	0x00,  0x00,  0x00,  0x00,  0x0F,  0xF8,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x3F,  0xFE,  0x00,  0x40, 	/* 23530 */
+	0x00,  0x40,  0x00,  0x40,  0x00,  0x80,  0x00,  0x80,  0x01,  0x00,  0x06,  0x00,  0x00,  0x00,  0x87,  0x00, 	/* 23540 */
+	0x00,  0x00,  0x04,  0x00,  0x12,  0x0F,  0xEA,  0x00,  0x08,  0x00,  0x00,  0x00,  0x00,  0x3F,  0xFE,  0x00, 	/* 23550 */
+	0x40,  0x00,  0x40,  0x00,  0x40,  0x00,  0x80,  0x00,  0x80,  0x01,  0x00,  0x06,  0x00,  0x00,  0x00,  0x88, 	/* 23560 */
+	0x00,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x03,  0x80, 	/* 23570 */
+	0x02,  0x60,  0x02,  0x10,  0x02,  0x08,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00, 	/* 23580 */
+	0x89,  0x00,  0x00,  0x02,  0x04,  0x02,  0x12,  0x02,  0x0A,  0x02,  0x08,  0x02,  0x00,  0x02,  0x00,  0x03, 	/* 23590 */
+	0x80,  0x02,  0x60,  0x02,  0x10,  0x02,  0x08,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02, 	/* 235A0 */
+	0x00,  0x8A,  0x00,  0x00,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0x3F,  0xFE,  0x00,  0x40, 	/* 235B0 */
+	0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0x00,  0x80,  0x00,  0x80,  0x03,  0x00,  0x0C,  0x00, 	/* 235C0 */
+	0x00,  0x00,  0x8B,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x1F,  0xF8,  0x00,  0x00,  0x00, 	/* 235D0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x7F,  0xFE,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 235E0 */
+	0x00,  0x00,  0x00,  0x8C,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0F,  0xF8,  0x00,  0x08,  0x00,  0x10, 	/* 235F0 */
+	0x00,  0x10,  0x06,  0x20,  0x01,  0xA0,  0x00,  0x40,  0x00,  0xA0,  0x01,  0x10,  0x02,  0x08,  0x0C,  0x04, 	/* 23600 */
+	0x30,  0x00,  0x00,  0x00,  0x8D,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xF8,  0x00,  0x08,  0x00, 	/* 23610 */
+	0x10,  0x00,  0x20,  0x00,  0x40,  0x01,  0xB0,  0x06,  0x8C,  0x38,  0x82,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 23620 */
+	0x80,  0x00,  0x80,  0x00,  0x00,  0x8E,  0x00,  0x00,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08, 	/* 23630 */
+	0x00,  0x10,  0x00,  0x10,  0x00,  0x20,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x01,  0x00,  0x02,  0x00, 	/* 23640 */
+	0x0C,  0x00,  0x30,  0x00,  0x00,  0x00,  0x8F,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x04,  0x40,  0x04, 	/* 23650 */
+	0x20,  0x04,  0x10,  0x04,  0x10,  0x08,  0x08,  0x08,  0x08,  0x08,  0x04,  0x10,  0x04,  0x10,  0x02,  0x20, 	/* 23660 */
+	0x02,  0x40,  0x02,  0x00,  0x00,  0x00,  0x00,  0x90,  0x00,  0x00,  0x00,  0x04,  0x00,  0x12,  0x04,  0x4A, 	/* 23670 */
+	0x04,  0x28,  0x04,  0x10,  0x04,  0x10,  0x08,  0x08,  0x08,  0x08,  0x08,  0x04,  0x10,  0x04,  0x10,  0x02, 	/* 23680 */
+	0x20,  0x02,  0x40,  0x02,  0x00,  0x00,  0x00,  0x00,  0x91,  0x00,  0x0C,  0x00,  0x12,  0x00,  0x12,  0x04, 	/* 23690 */
+	0x4C,  0x04,  0x20,  0x04,  0x10,  0x04,  0x10,  0x08,  0x08,  0x08,  0x08,  0x08,  0x04,  0x10,  0x04,  0x10, 	/* 236A0 */
+	0x02,  0x20,  0x02,  0x40,  0x02,  0x00,  0x00,  0x00,  0x00,  0x92,  0x00,  0x00,  0x10,  0x00,  0x10,  0x00, 	/* 236B0 */
+	0x10,  0x00,  0x10,  0x00,  0x10,  0x30,  0x11,  0xC0,  0x1E,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00, 	/* 236C0 */
+	0x10,  0x00,  0x08,  0x00,  0x07,  0xF8,  0x00,  0x00,  0x00,  0x00,  0x93,  0x00,  0x00,  0x10,  0x04,  0x10, 	/* 236D0 */
+	0x12,  0x10,  0x0A,  0x10,  0x08,  0x10,  0x30,  0x11,  0xC0,  0x1E,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10, 	/* 236E0 */
+	0x00,  0x10,  0x00,  0x08,  0x00,  0x07,  0xF8,  0x00,  0x00,  0x00,  0x00,  0x94,  0x00,  0x00,  0x20,  0x0C, 	/* 236F0 */
+	0x20,  0x12,  0x20,  0x12,  0x20,  0x0C,  0x20,  0x60,  0x23,  0x80,  0x3C,  0x00,  0x20,  0x00,  0x20,  0x00, 	/* 23700 */
+	0x20,  0x00,  0x20,  0x00,  0x10,  0x00,  0x0F,  0xF0,  0x00,  0x00,  0x00,  0x00,  0x95,  0x00,  0x00,  0x00, 	/* 23710 */
+	0x00,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x04,  0x00,  0x04,  0x00,  0x08,  0x00,  0x08,  0x00,  0x10,  0x00, 	/* 23720 */
+	0x10,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x03,  0x00,  0x0C,  0x00,  0x00,  0x00,  0x96,  0x00,  0x04, 	/* 23730 */
+	0x00,  0x12,  0x00,  0x0A,  0x3F,  0xF8,  0x00,  0x08,  0x00,  0x08,  0x00,  0x10,  0x00,  0x10,  0x00,  0x20, 	/* 23740 */
+	0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x01,  0x00,  0x06,  0x00,  0x18,  0x00,  0x00,  0x00,  0x97,  0x00, 	/* 23750 */
+	0x00,  0x00,  0x06,  0x00,  0x09,  0x3F,  0xF9,  0x00,  0x0E,  0x00,  0x08,  0x00,  0x10,  0x00,  0x10,  0x00, 	/* 23760 */
+	0x20,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x01,  0x00,  0x06,  0x00,  0x18,  0x00,  0x00,  0x00,  0x98, 	/* 23770 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x03,  0x00,  0x04,  0x80,  0x08,  0x40,  0x10,  0x20, 	/* 23780 */
+	0x20,  0x10,  0x40,  0x08,  0x00,  0x04,  0x00,  0x02,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 23790 */
+	0x99,  0x00,  0x00,  0x00,  0x00,  0x00,  0x04,  0x00,  0x12,  0x03,  0x0A,  0x04,  0x88,  0x08,  0x40,  0x10, 	/* 237A0 */
+	0x20,  0x20,  0x10,  0x40,  0x08,  0x00,  0x04,  0x00,  0x02,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 237B0 */
+	0x00,  0x9A,  0x00,  0x00,  0x00,  0x18,  0x00,  0x24,  0x00,  0x24,  0x03,  0x18,  0x04,  0x80,  0x08,  0x40, 	/* 237C0 */
+	0x10,  0x20,  0x20,  0x10,  0x40,  0x08,  0x00,  0x04,  0x00,  0x02,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 237D0 */
+	0x00,  0x00,  0x9B,  0x00,  0x00,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80,  0x00, 	/* 237E0 */
+	0x80,  0x04,  0x90,  0x04,  0x88,  0x04,  0x84,  0x08,  0x84,  0x08,  0x82,  0x10,  0x82,  0x20,  0x80,  0x01, 	/* 237F0 */
+	0x80,  0x00,  0x00,  0x9C,  0x00,  0x00,  0x00,  0x82,  0x00,  0x89,  0x00,  0x85,  0x3F,  0xFC,  0x00,  0x80, 	/* 23800 */
+	0x00,  0x80,  0x04,  0x90,  0x04,  0x88,  0x04,  0x84,  0x08,  0x84,  0x08,  0x82,  0x10,  0x82,  0x20,  0x80, 	/* 23810 */
+	0x01,  0x80,  0x00,  0x00,  0x9D,  0x00,  0x00,  0x00,  0x86,  0x00,  0x89,  0x00,  0x89,  0x3F,  0xFE,  0x00, 	/* 23820 */
+	0x80,  0x00,  0x80,  0x04,  0x90,  0x04,  0x88,  0x04,  0x84,  0x08,  0x84,  0x08,  0x82,  0x10,  0x82,  0x20, 	/* 23830 */
+	0x80,  0x01,  0x80,  0x00,  0x00,  0x9E,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x3F,  0xFE,  0x00,  0x04, 	/* 23840 */
+	0x00,  0x04,  0x00,  0x08,  0x00,  0x10,  0x0C,  0x20,  0x03,  0x40,  0x00,  0x80,  0x00,  0x40,  0x00,  0x20, 	/* 23850 */
+	0x00,  0x20,  0x00,  0x00,  0x00,  0x00,  0x9F,  0x00,  0x00,  0x06,  0x00,  0x01,  0x80,  0x00,  0x60,  0x00, 	/* 23860 */
+	0x10,  0x00,  0x00,  0x06,  0x00,  0x01,  0x80,  0x00,  0x40,  0x00,  0x20,  0x10,  0x00,  0x0C,  0x00,  0x03, 	/* 23870 */
+	0x00,  0x00,  0xC0,  0x00,  0x20,  0x00,  0x10,  0xA0,  0x00,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 23880 */
+	0x01,  0x00,  0x01,  0x00,  0x02,  0x00,  0x02,  0x20,  0x02,  0x10,  0x04,  0x10,  0x04,  0x08,  0x09,  0xF8, 	/* 23890 */
+	0x3E,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x00,  0xA1,  0x00,  0x00,  0x00,  0x08,  0x00,  0x08,  0x00, 	/* 238A0 */
+	0x08,  0x00,  0x08,  0x06,  0x10,  0x01,  0x90,  0x00,  0x50,  0x00,  0x20,  0x00,  0x30,  0x00,  0x48,  0x00, 	/* 238B0 */
+	0x84,  0x01,  0x00,  0x06,  0x00,  0x18,  0x00,  0x00,  0x00,  0xA2,  0x00,  0x00,  0x00,  0x00,  0x1F,  0xF0, 	/* 238C0 */
+	0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x7F,  0xFC,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00, 	/* 238D0 */
+	0x02,  0x00,  0x01,  0x00,  0x00,  0xF8,  0x00,  0x00,  0x00,  0x00,  0xA3,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 238E0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x02,  0x00,  0x02,  0x00,  0x01,  0x38,  0x01,  0xC8,  0x07,  0x10,  0x19, 	/* 238F0 */
+	0x20,  0x00,  0x80,  0x00,  0x80,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0xA4,  0x00,  0x00,  0x04,  0x00, 	/* 23900 */
+	0x04,  0x00,  0x02,  0x0E,  0x02,  0x72,  0x07,  0x84,  0x3A,  0x08,  0x01,  0x10,  0x01,  0x20,  0x00,  0x80, 	/* 23910 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0x00,  0x00,  0xA5,  0x00,  0x00,  0x00, 	/* 23920 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0F,  0xC0,  0x00, 	/* 23930 */
+	0x40,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0x3F,  0xF8,  0x00,  0x00,  0x00,  0x00,  0xA6,  0x00,  0x00, 	/* 23940 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x1F,  0xE0,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20, 	/* 23950 */
+	0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x7F,  0xFE,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xA7,  0x00, 	/* 23960 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x07,  0xF0,  0x00,  0x10,  0x00, 	/* 23970 */
+	0x10,  0x00,  0x10,  0x07,  0xF0,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x07,  0xF0,  0x00,  0x00,  0xA8, 	/* 23980 */
+	0x00,  0x00,  0x00,  0x00,  0x1F,  0xF8,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x1F,  0xF8, 	/* 23990 */
+	0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x1F,  0xF8,  0x00,  0x08,  0x00,  0x00, 	/* 239A0 */
+	0xA9,  0x00,  0x00,  0x00,  0x00,  0x1F,  0xF8,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x3F,  0xFC,  0x00, 	/* 239B0 */
+	0x04,  0x00,  0x04,  0x00,  0x08,  0x00,  0x08,  0x00,  0x10,  0x00,  0x60,  0x01,  0x80,  0x0E,  0x00,  0x00, 	/* 239C0 */
+	0x00,  0xAA,  0x00,  0x00,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10, 	/* 239D0 */
+	0x08,  0x10,  0x08,  0x10,  0x00,  0x10,  0x00,  0x20,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x03,  0x00, 	/* 239E0 */
+	0x00,  0x00,  0xAB,  0x00,  0x00,  0x00,  0x40,  0x00,  0x40,  0x04,  0x40,  0x04,  0x40,  0x04,  0x40,  0x04, 	/* 239F0 */
+	0x41,  0x04,  0x41,  0x04,  0x42,  0x04,  0x42,  0x04,  0x44,  0x08,  0x48,  0x08,  0x50,  0x10,  0x60,  0x20, 	/* 23A00 */
+	0x00,  0x00,  0x00,  0xAC,  0x00,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00, 	/* 23A10 */
+	0x04,  0x00,  0x04,  0x00,  0x04,  0x04,  0x04,  0x04,  0x04,  0x08,  0x04,  0x10,  0x04,  0x20,  0x04,  0xC0, 	/* 23A20 */
+	0x07,  0x00,  0x00,  0x00,  0xAD,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x1F,  0xFC,  0x10,  0x04,  0x10, 	/* 23A30 */
+	0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x1F,  0xFC,  0x10, 	/* 23A40 */
+	0x04,  0x00,  0x00,  0x00,  0x00,  0xAE,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 23A50 */
+	0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x00,  0x10,  0x00,  0x10,  0x00,  0x20, 	/* 23A60 */
+	0x00,  0x40,  0x01,  0x80,  0x00,  0x00,  0xAF,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x3F,  0xF8,  0x20, 	/* 23A70 */
+	0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x00,  0x08,  0x00,  0x10,  0x00,  0x10,  0x00,  0x20,  0x00, 	/* 23A80 */
+	0x40,  0x01,  0x80,  0x06,  0x00,  0x00,  0x00,  0xB0,  0x00,  0x00,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40, 	/* 23A90 */
+	0x3F,  0xFC,  0x08,  0x40,  0x08,  0x40,  0x08,  0x40,  0x08,  0x40,  0x08,  0x40,  0x7F,  0xFE,  0x00,  0x40, 	/* 23AA0 */
+	0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0x00,  0x00,  0xB1,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x1F, 	/* 23AB0 */
+	0xF8,  0x00,  0x10,  0x00,  0x20,  0x01,  0x40,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01, 	/* 23AC0 */
+	0x00,  0x7F,  0xFC,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xB2,  0x00,  0x00,  0x00,  0x00,  0x0F,  0xFC, 	/* 23AD0 */
+	0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x07,  0xFC,  0x00,  0x08,  0x00,  0x08,  0x00,  0x10,  0x00,  0x20, 	/* 23AE0 */
+	0x00,  0x40,  0x01,  0x80,  0x0E,  0x00,  0x00,  0x00,  0x00,  0x00,  0xB3,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 23AF0 */
+	0x00,  0x18,  0x00,  0x04,  0x00,  0x02,  0x02,  0x00,  0x02,  0x00,  0x04,  0x00,  0x04,  0x00,  0x08,  0x00, 	/* 23B00 */
+	0x10,  0x00,  0x20,  0x00,  0xC0,  0x03,  0x00,  0x1C,  0x00,  0x00,  0x00,  0xB4,  0x00,  0x80,  0x00,  0x82, 	/* 23B10 */
+	0x00,  0x89,  0x00,  0x85,  0x1F,  0xFC,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x00,  0x08, 	/* 23B20 */
+	0x00,  0x08,  0x00,  0x10,  0x00,  0x20,  0x00,  0xC0,  0x03,  0x00,  0x00,  0x00,  0xB5,  0x00,  0x00,  0x00, 	/* 23B30 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x1F,  0xF0,  0x01,  0x10,  0x01, 	/* 23B40 */
+	0x10,  0x01,  0x10,  0x02,  0x10,  0x02,  0x10,  0x04,  0x10,  0x08,  0x60,  0x00,  0x00,  0xB6,  0x00,  0x00, 	/* 23B50 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x07,  0xFC,  0x04,  0x20, 	/* 23B60 */
+	0x08,  0x20,  0x10,  0x40,  0x00,  0x40,  0x00,  0x80,  0x01,  0x00,  0x06,  0x00,  0x00,  0x00,  0xBB,  0x00, 	/* 23B70 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x01,  0x80,  0x01, 	/* 23B80 */
+	0x80,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xBC, 	/* 23B90 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x40,  0x00,  0x3F,  0xFC, 	/* 23BA0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 23BB0 */
+	0xBD,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0C,  0x00,  0x03,  0x00,  0x00, 	/* 23BC0 */
+	0x80,  0x00,  0x40,  0x00,  0x20,  0x00,  0x10,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 23BD0 */
+	0x00,  0xBE,  0x00,  0x00,  0x00,  0x00,  0x00,  0x20,  0x00,  0x90,  0x00,  0x50,  0x0C,  0x40,  0x03,  0x00, 	/* 23BE0 */
+	0x00,  0x80,  0x00,  0x40,  0x00,  0x20,  0x00,  0x10,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 23BF0 */
+	0x00,  0x00,  0x80,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 23C00 */
+	0x02,  0x7F,  0xFF,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 23C10 */
+	0x00,  0x00,  0x00,  0x81,  0x00,  0x00,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80, 	/* 23C20 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80, 	/* 23C30 */
+	0x00,  0x80,  0x01,  0x80,  0x83,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x06,  0x04, 	/* 23C40 */
+	0x78,  0x07,  0x80,  0x7C,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x04,  0x04,  0x04,  0x02, 	/* 23C50 */
+	0x04,  0x01,  0xFC,  0x00,  0x00,  0x87,  0x00,  0x00,  0x7F,  0xFE,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 23C60 */
+	0x01,  0xF8,  0x01,  0x08,  0x01,  0x08,  0x02,  0x08,  0x02,  0x08,  0x02,  0x08,  0x04,  0x08,  0x04,  0x08, 	/* 23C70 */
+	0x08,  0x08,  0x10,  0x10,  0x20,  0x60,  0x88,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0x3F,  0xFF,  0x00, 	/* 23C80 */
+	0x40,  0x04,  0x40,  0x04,  0x40,  0x02,  0x40,  0x02,  0x80,  0x01,  0x80,  0x00,  0x80,  0x01,  0x40,  0x02, 	/* 23C90 */
+	0x20,  0x04,  0x10,  0x18,  0x0C,  0x60,  0x03,  0x89,  0x00,  0x00,  0x1F,  0xFC,  0x00,  0x00,  0x00,  0x00, 	/* 23CA0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0F,  0xF8,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 23CB0 */
+	0x00,  0x00,  0x7F,  0xFF,  0x00,  0x00,  0x00,  0x00,  0x8A,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 23CC0 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 23CD0 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x8B,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x80, 	/* 23CE0 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0xC0,  0x00,  0xA0,  0x00,  0x90,  0x00,  0x88,  0x00,  0x88,  0x00,  0x80, 	/* 23CF0 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x8D,  0x00,  0x00,  0x7F,  0xFF,  0x00, 	/* 23D00 */
+	0x40,  0x00,  0x40,  0x00,  0x80,  0x00,  0xC0,  0x01,  0xB0,  0x02,  0x88,  0x04,  0x84,  0x18,  0x82,  0x60, 	/* 23D10 */
+	0x81,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x8E,  0x02,  0x00,  0x02,  0x00, 	/* 23D20 */
+	0x03,  0xFC,  0x02,  0x00,  0x02,  0x00,  0x03,  0xF0,  0x00,  0x10,  0x00,  0x10,  0x7F,  0xFF,  0x00,  0x10, 	/* 23D30 */
+	0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x60,  0x01,  0x80,  0x90,  0x00,  0x00,  0x7F, 	/* 23D40 */
+	0xFF,  0x00,  0x80,  0x08,  0x80,  0x08,  0xFE,  0x08,  0x80,  0x08,  0x80,  0x0F,  0xFC,  0x00,  0x04,  0x00, 	/* 23D50 */
+	0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x08,  0x00,  0x08,  0x00,  0x30,  0x91,  0x00,  0x00, 	/* 23D60 */
+	0x1F,  0xF0,  0x02,  0x10,  0x02,  0x10,  0x02,  0x10,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFE,  0x04,  0x10, 	/* 23D70 */
+	0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x00,  0x00,  0x94,  0x00, 	/* 23D80 */
+	0x00,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10,  0x08, 	/* 23D90 */
+	0x10,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x7F,  0xFE,  0x00,  0x00,  0x95, 	/* 23DA0 */
+	0x00,  0x00,  0x3F,  0xFE,  0x00,  0x40,  0x00,  0x40,  0x00,  0x80,  0x01,  0x80,  0x02,  0xB0,  0x04,  0x8C, 	/* 23DB0 */
+	0x18,  0x82,  0x60,  0x81,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x00,  0x3F,  0xFE,  0x00,  0x00, 	/* 23DC0 */
+	0x96,  0x00,  0x00,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x7F,  0xFF,  0x08,  0x88,  0x08, 	/* 23DD0 */
+	0x88,  0x08,  0x88,  0x08,  0x88,  0x08,  0xF8,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x0F,  0xFE,  0x00, 	/* 23DE0 */
+	0x00,  0x97,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x7F,  0xFF, 	/* 23DF0 */
+	0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x0F,  0xF8, 	/* 23E00 */
+	0x00,  0x00,  0x98,  0x00,  0x10,  0x00,  0xE0,  0x0F,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x0F, 	/* 23E10 */
+	0xFC,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x7F, 	/* 23E20 */
+	0xFE,  0x00,  0x00,  0x99,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x10,  0x84, 	/* 23E30 */
+	0x10,  0x84,  0x11,  0x44,  0x12,  0x24,  0x1C,  0x14,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04, 	/* 23E40 */
+	0x10,  0x04,  0x10,  0x0C,  0x9E,  0x00,  0x00,  0x1F,  0xF8,  0x00,  0x10,  0x00,  0x60,  0x00,  0x82,  0x3E, 	/* 23E50 */
+	0xA2,  0x02,  0xA4,  0x04,  0x98,  0x04,  0x88,  0x08,  0x84,  0x10,  0x82,  0x20,  0x81,  0x41,  0x80,  0x00, 	/* 23E60 */
+	0x00,  0x7F,  0xFE,  0x00,  0x00,  0xA1,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80, 	/* 23E70 */
+	0x3F,  0xFE,  0x20,  0x82,  0x24,  0x92,  0x24,  0x92,  0x24,  0x92,  0x24,  0x92,  0x27,  0xF2,  0x24,  0x12, 	/* 23E80 */
+	0x20,  0x02,  0x20,  0x02,  0x20,  0x06,  0xA6,  0x08,  0x08,  0x04,  0x08,  0x02,  0x10,  0x02,  0x20,  0x3F, 	/* 23E90 */
+	0xFE,  0x02,  0x20,  0x02,  0x20,  0x22,  0x22,  0x12,  0x22,  0x12,  0x24,  0x0A,  0x24,  0x0A,  0x28,  0x02, 	/* 23EA0 */
+	0x20,  0x02,  0x20,  0x7F,  0xFF,  0x00,  0x00,  0xAA,  0x00,  0x80,  0x00,  0x80,  0x01,  0x40,  0x01,  0x40, 	/* 23EB0 */
+	0x02,  0x20,  0x04,  0x10,  0x08,  0x88,  0x10,  0x84,  0x20,  0x82,  0x40,  0x81,  0x00,  0x80,  0x00,  0x80, 	/* 23EC0 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0xAD,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x3F, 	/* 23ED0 */
+	0xFE,  0x20,  0x82,  0x20,  0x82,  0x20,  0x82,  0x20,  0x82,  0x20,  0x82,  0x3F,  0xFE,  0x00,  0x80,  0x00, 	/* 23EE0 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0xB1,  0x02,  0x20,  0x02,  0x20,  0x22,  0x22, 	/* 23EF0 */
+	0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x3E,  0x3E, 	/* 23F00 */
+	0x02,  0x20,  0x04,  0x20,  0x04,  0x20,  0x08,  0x20,  0x10,  0x20,  0xB2,  0x00,  0x80,  0x00,  0x80,  0x1F, 	/* 23F10 */
+	0xFC,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x20,  0x82,  0x20, 	/* 23F20 */
+	0x82,  0x3F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0xB6,  0x00,  0x00,  0x00,  0x00, 	/* 23F30 */
+	0x00,  0x00,  0x0C,  0x00,  0x03,  0x00,  0x00,  0x80,  0x00,  0x40,  0x00,  0x20,  0x00,  0x20,  0x00,  0x10, 	/* 23F40 */
+	0x00,  0x10,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xB8,  0x02,  0x00,  0x02, 	/* 23F50 */
+	0x00,  0x02,  0x00,  0x02,  0x00,  0x7F,  0xF0,  0x02,  0x10,  0x02,  0x10,  0x0A,  0x10,  0x06,  0x10,  0x02, 	/* 23F60 */
+	0x10,  0x05,  0x10,  0x04,  0x90,  0x08,  0x92,  0x10,  0x12,  0x20,  0x12,  0x40,  0x0E,  0xB9,  0x00,  0x00, 	/* 23F70 */
+	0x0F,  0xF8,  0x08,  0x08,  0x0A,  0x08,  0x09,  0x08,  0x08,  0x88,  0x08,  0x88,  0x08,  0x08,  0x7F,  0xFF, 	/* 23F80 */
+	0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x10,  0x08,  0x10,  0x08,  0x20,  0x08,  0x40,  0x18,  0xBB,  0x01, 	/* 23F90 */
+	0x00,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x1F, 	/* 23FA0 */
+	0xFC,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0xBC, 	/* 23FB0 */
+	0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x3F,  0xFC,  0x04,  0x20,  0x05,  0x20,  0x04,  0xA0, 	/* 23FC0 */
+	0x04,  0xA0,  0x7F,  0xFE,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x08,  0x20,  0x08,  0x20,  0x10,  0x20, 	/* 23FD0 */
+	0xBF,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0x00, 	/* 23FE0 */
+	0x40,  0x00,  0x40,  0x00,  0x40,  0x00,  0x80,  0x00,  0x80,  0x01,  0x00,  0x02,  0x00,  0x0C,  0x00,  0x30, 	/* 23FF0 */
+	0x00,  0x82,  0x00,  0x00,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x02,  0x20, 	/* 24000 */
+	0x02,  0x20,  0x01,  0x40,  0x01,  0x40,  0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x04,  0x10,  0x18,  0x0C, 	/* 24010 */
+	0x60,  0x03,  0x83,  0x00,  0x00,  0x3F,  0xF0,  0x01,  0x10,  0x01,  0x10,  0x01,  0x10,  0x01,  0x10,  0x01, 	/* 24020 */
+	0x1C,  0x02,  0x04,  0x02,  0x04,  0x04,  0x04,  0x04,  0x04,  0x08,  0x04,  0x10,  0x04,  0x20,  0x08,  0x40, 	/* 24030 */
+	0x30,  0x00,  0x00,  0x85,  0x01,  0x00,  0x01,  0x00,  0x01,  0xF0,  0x02,  0x10,  0x02,  0x10,  0x04,  0x20, 	/* 24040 */
+	0x08,  0x20,  0x10,  0x40,  0x00,  0x40,  0x00,  0xC0,  0x00,  0xA0,  0x01,  0x20,  0x02,  0x10,  0x04,  0x08, 	/* 24050 */
+	0x18,  0x04,  0x60,  0x03,  0x8B,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00, 	/* 24060 */
+	0x08,  0x00,  0x10,  0x00,  0x10,  0x00,  0x20,  0x00,  0x40,  0x08,  0x80,  0x09,  0x00,  0x0E,  0x00,  0x12, 	/* 24070 */
+	0x00,  0x21,  0x80,  0x40,  0x7F,  0x8D,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x07,  0xFE,  0x08,  0x80, 	/* 24080 */
+	0x08,  0x80,  0x10,  0x80,  0x20,  0xFC,  0x40,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0xFC,  0x00,  0x80, 	/* 24090 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x8E,  0x00,  0x04,  0x00,  0x38,  0x3F,  0xC0,  0x00,  0x84,  0x08, 	/* 240A0 */
+	0x84,  0x04,  0x88,  0x04,  0x90,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 240B0 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x01,  0x80,  0x8F,  0x00,  0x04,  0x00,  0x38,  0x7F,  0xC0,  0x01,  0x00, 	/* 240C0 */
+	0x01,  0x00,  0x01,  0x00,  0x3F,  0xF8,  0x00,  0x08,  0x00,  0x10,  0x00,  0x20,  0x08,  0x40,  0x09,  0x80, 	/* 240D0 */
+	0x1E,  0x00,  0x12,  0x00,  0x21,  0x80,  0x40,  0x7F,  0x95,  0x00,  0x04,  0x00,  0x38,  0x0F,  0xC0,  0x08, 	/* 240E0 */
+	0x40,  0x0F,  0xFF,  0x08,  0x40,  0x08,  0x40,  0x0F,  0xFF,  0x08,  0x40,  0x08,  0x40,  0x17,  0xFE,  0x14, 	/* 240F0 */
+	0x42,  0x24,  0x42,  0x44,  0x42,  0x04,  0x4C,  0x00,  0x40,  0x96,  0x00,  0x08,  0x00,  0x70,  0x1F,  0x80, 	/* 24100 */
+	0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x04,  0x90,  0x04,  0x93,  0x7C,  0x9C,  0x04,  0x90, 	/* 24110 */
+	0x04,  0x91,  0x1C,  0x91,  0x64,  0x8F,  0x04,  0x80,  0x00,  0x80,  0x97,  0x00,  0x10,  0x0F,  0xE0,  0x00, 	/* 24120 */
+	0x80,  0x3F,  0xFE,  0x08,  0x88,  0x08,  0x88,  0x7F,  0xFF,  0x08,  0x88,  0x08,  0x88,  0x3F,  0xFE,  0x01, 	/* 24130 */
+	0xC0,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0x98,  0x00,  0x08,  0x00,  0x70, 	/* 24140 */
+	0x1F,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x04,  0x92,  0x7C,  0x9C,  0x04,  0x91,  0x1C,  0x91, 	/* 24150 */
+	0x65,  0xCF,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0x99,  0x00,  0x00,  0x1F, 	/* 24160 */
+	0xF8,  0x00,  0x10,  0x00,  0x60,  0x00,  0x80,  0x01,  0x00,  0x02,  0x00,  0x04,  0x00,  0x08,  0x00,  0x10, 	/* 24170 */
+	0x00,  0x10,  0x00,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x1F,  0xFC,  0x00,  0x00,  0x9D,  0x00,  0x00, 	/* 24180 */
+	0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x7F,  0xE0,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20, 	/* 24190 */
+	0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x08,  0x22,  0x10,  0x22,  0x20,  0x1E,  0x40,  0x00,  0x9E,  0x04, 	/* 241A0 */
+	0x00,  0x04,  0x00,  0x04,  0x00,  0x0F,  0xFE,  0x08,  0x00,  0x10,  0x00,  0x2F,  0xF0,  0x40,  0x40,  0x01, 	/* 241B0 */
+	0x80,  0x02,  0x00,  0x04,  0x00,  0x08,  0x00,  0x10,  0x00,  0x10,  0x04,  0x10,  0x04,  0x0F,  0xFC,  0x9F, 	/* 241C0 */
+	0x00,  0x80,  0x08,  0x80,  0x08,  0x80,  0x08,  0x98,  0x08,  0xE8,  0x0F,  0x88,  0x78,  0x88,  0x08,  0x88, 	/* 241D0 */
+	0x08,  0x88,  0x08,  0x88,  0x08,  0xB0,  0x08,  0x82,  0x08,  0x02,  0x04,  0x02,  0x03,  0xFE,  0x00,  0x00, 	/* 241E0 */
+	0xA2,  0x08,  0x40,  0x08,  0x40,  0x08,  0x40,  0x29,  0x40,  0x29,  0x40,  0x29,  0x40,  0x29,  0x40,  0x29, 	/* 241F0 */
+	0x40,  0x29,  0x40,  0x29,  0x40,  0x29,  0x40,  0x29,  0x41,  0x3F,  0x41,  0x00,  0x41,  0x00,  0x3F,  0x00, 	/* 24200 */
+	0x00,  0xB1,  0x01,  0x20,  0x06,  0x20,  0x38,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x7F,  0xA0, 	/* 24210 */
+	0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x3F,  0x20,  0x21,  0x20,  0x21,  0x21,  0x21,  0x21,  0x3F,  0x21, 	/* 24220 */
+	0x00,  0x1F,  0xB3,  0x00,  0xA0,  0x07,  0x20,  0x78,  0xA0,  0x24,  0xA0,  0x15,  0x20,  0x12,  0x20,  0x3F, 	/* 24230 */
+	0xA0,  0x01,  0x20,  0x02,  0x20,  0x04,  0x20,  0x07,  0xE0,  0x7C,  0x20,  0x04,  0x20,  0x04,  0x21,  0x04, 	/* 24240 */
+	0x11,  0x0C,  0x0F,  0xBE,  0x08,  0x40,  0x08,  0x40,  0x7F,  0x40,  0x08,  0x7F,  0x3E,  0x40,  0x22,  0x80, 	/* 24250 */
+	0x22,  0xFC,  0x3F,  0x04,  0x22,  0x08,  0x22,  0x10,  0x3E,  0x20,  0x08,  0x20,  0x7F,  0xC2,  0x08,  0x42, 	/* 24260 */
+	0x08,  0x42,  0x08,  0x3E,  0x80,  0x02,  0x00,  0x07,  0xF0,  0x08,  0x20,  0x1F,  0xF8,  0x68,  0x88,  0x0F, 	/* 24270 */
+	0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x80,  0x1F,  0xFC,  0x10,  0x84,  0x1F,  0xFC,  0x10,  0x84,  0x1F, 	/* 24280 */
+	0xFD,  0x00,  0x81,  0x00,  0x7F,  0x82,  0x01,  0x10,  0x06,  0x10,  0x7C,  0x90,  0x12,  0x50,  0x22,  0x50, 	/* 24290 */
+	0x7F,  0xD0,  0x11,  0x10,  0x0A,  0x10,  0x3F,  0xD0,  0x25,  0x50,  0x3E,  0xD0,  0x20,  0x51,  0x2F,  0x51, 	/* 242A0 */
+	0x25,  0x51,  0x22,  0x4F,  0x2D,  0xC0,  0x85,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01, 	/* 242B0 */
+	0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01, 	/* 242C0 */
+	0x00,  0x01,  0x00,  0x01,  0x00,  0x03,  0x00,  0x86,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x08,  0x00,  0x10, 	/* 242D0 */
+	0x00,  0x20,  0x00,  0xC0,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80, 	/* 242E0 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x01,  0x80,  0x88,  0x00,  0x00,  0x1F,  0xF8,  0x00,  0x10,  0x06, 	/* 242F0 */
+	0x20,  0x01,  0x40,  0x00,  0x80,  0x7F,  0xFE,  0x00,  0x82,  0x00,  0x84,  0x00,  0x88,  0x00,  0x80,  0x00, 	/* 24300 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x01,  0x80,  0x89,  0x01,  0x00,  0x01,  0xE0,  0x02,  0x20, 	/* 24310 */
+	0x04,  0x40,  0x18,  0x80,  0x1F,  0xF8,  0x00,  0x88,  0x00,  0x88,  0x7F,  0xFF,  0x00,  0x88,  0x00,  0x88, 	/* 24320 */
+	0x1F,  0xF8,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x01,  0x80,  0x8A,  0x00,  0x80,  0x00,  0x80,  0x3F, 	/* 24330 */
+	0xFE,  0x08,  0x88,  0x04,  0x90,  0x04,  0x80,  0x1F,  0xFC,  0x00,  0x84,  0x00,  0x84,  0x7F,  0xFF,  0x00, 	/* 24340 */
+	0x84,  0x00,  0x84,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x01,  0x80,  0x8B,  0x00,  0x80,  0x00,  0x80, 	/* 24350 */
+	0x7F,  0xFF,  0x00,  0x80,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x84, 	/* 24360 */
+	0x7F,  0xFF,  0x00,  0x84,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x01,  0x80,  0x8C,  0x00,  0x00,  0x00, 	/* 24370 */
+	0x00,  0x1F,  0xFC,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 24380 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x00,  0x00,  0x00,  0x8E,  0x00,  0x00, 	/* 24390 */
+	0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80, 	/* 243A0 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x01,  0x80,  0x91,  0x00, 	/* 243B0 */
+	0x00,  0x00,  0x00,  0x1F,  0xF8,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x7F,  0xFE,  0x01,  0x00,  0x01, 	/* 243C0 */
+	0x00,  0x02,  0x20,  0x02,  0x10,  0x04,  0x08,  0x08,  0xF8,  0x7F,  0x04,  0x00,  0x04,  0x00,  0x04,  0x92, 	/* 243D0 */
+	0x00,  0x00,  0x3F,  0xFE,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x03,  0xF0,  0x04,  0x10,  0x04,  0x10, 	/* 243E0 */
+	0x04,  0x10,  0x08,  0x10,  0x0F,  0xE0,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x7F,  0xFF,  0x00,  0x00, 	/* 243F0 */
+	0x94,  0x00,  0x00,  0x3F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xF8,  0x01, 	/* 24400 */
+	0x08,  0x01,  0x08,  0x01,  0x08,  0x01,  0x08,  0x02,  0x08,  0x02,  0x08,  0x02,  0x08,  0x7F,  0xFF,  0x00, 	/* 24410 */
+	0x00,  0x95,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x3F,  0xFC,  0x04,  0x20,  0x04,  0x20, 	/* 24420 */
+	0x04,  0x20,  0x04,  0x20,  0x7F,  0xFE,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x08,  0x20,  0x08,  0x20, 	/* 24430 */
+	0x10,  0x20,  0x98,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x00,  0x00,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x08, 	/* 24440 */
+	0x10,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x00,  0x00,  0x00,  0x00,  0x7F, 	/* 24450 */
+	0xFE,  0x00,  0x00,  0x99,  0x00,  0x00,  0x3F,  0xFE,  0x02,  0x00,  0x02,  0x00,  0x03,  0xF0,  0x02,  0x10, 	/* 24460 */
+	0x05,  0x90,  0x04,  0x50,  0x04,  0x10,  0x0B,  0x20,  0x08,  0xA0,  0x08,  0x20,  0x00,  0x20,  0x00,  0x20, 	/* 24470 */
+	0x7F,  0xFF,  0x00,  0x00,  0x9B,  0x04,  0x40,  0x04,  0x40,  0x14,  0x44,  0x17,  0x78,  0x14,  0x40,  0x14, 	/* 24480 */
+	0x40,  0x14,  0x42,  0x17,  0x42,  0x18,  0x3E,  0x60,  0x00,  0x0F,  0xF8,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 24490 */
+	0x00,  0x7F,  0xFF,  0x00,  0x00,  0x9C,  0x00,  0x00,  0x3F,  0xFF,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20, 	/* 244A0 */
+	0x1F,  0xFC,  0x12,  0x24,  0x12,  0x24,  0x12,  0x24,  0x12,  0x24,  0x1F,  0xFC,  0x02,  0x20,  0x02,  0x20, 	/* 244B0 */
+	0x02,  0x20,  0x7F,  0xFF,  0x00,  0x00,  0x9E,  0x00,  0x00,  0x7F,  0xFF,  0x02,  0x20,  0x02,  0x20,  0x02, 	/* 244C0 */
+	0x20,  0x3E,  0x3E,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x3E,  0x3E,  0x02,  0x20,  0x02, 	/* 244D0 */
+	0x20,  0x02,  0x20,  0x7F,  0xFF,  0x00,  0x00,  0x9F,  0x00,  0x00,  0x3F,  0xFE,  0x01,  0x00,  0x01,  0x00, 	/* 244E0 */
+	0x03,  0xC0,  0x00,  0x7E,  0x3E,  0x42,  0x22,  0x54,  0x22,  0x4C,  0x3E,  0x4C,  0x22,  0x52,  0x00,  0xA1, 	/* 244F0 */
+	0x03,  0x00,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x00,  0xA0,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 24500 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 24510 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xA1,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80, 	/* 24520 */
+	0x7F,  0xFF,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00, 	/* 24530 */
+	0x08,  0x00,  0x08,  0x00,  0x04,  0x00,  0x03,  0xFC,  0x00,  0x00,  0xA2,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 24540 */
+	0x80,  0x7F,  0xFE,  0x00,  0x00,  0x00,  0x00,  0x03,  0xE0,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02, 	/* 24550 */
+	0x20,  0x02,  0x20,  0x04,  0x22,  0x04,  0x22,  0x08,  0x22,  0x30,  0x1E,  0xA4,  0x00,  0x80,  0x00,  0x80, 	/* 24560 */
+	0x00,  0x80,  0x7F,  0xFF,  0x04,  0x20,  0x04,  0x10,  0x08,  0x28,  0x0A,  0x28,  0x12,  0x24,  0x21,  0x44, 	/* 24570 */
+	0x01,  0x40,  0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x0C,  0x18,  0x70,  0x07,  0xA5,  0x00,  0x80,  0x00, 	/* 24580 */
+	0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x00,  0x01,  0x10,  0x1A,  0x20,  0x04,  0x40,  0x02,  0x88,  0x01, 	/* 24590 */
+	0x10,  0x06,  0x20,  0x18,  0x60,  0x00,  0x90,  0x03,  0x08,  0x0C,  0x04,  0x70,  0x04,  0xA6,  0x00,  0x80, 	/* 245A0 */
+	0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0x20,  0x02,  0x20,  0x0A,  0x28,  0x0A,  0x24,  0x0A,  0x24, 	/* 245B0 */
+	0x12,  0x22,  0x22,  0x22,  0x42,  0x22,  0x04,  0x20,  0x04,  0x20,  0x08,  0x20,  0x10,  0x60,  0xA8,  0x00, 	/* 245C0 */
+	0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x3F, 	/* 245D0 */
+	0xFC,  0x00,  0x08,  0x00,  0x30,  0x00,  0xC0,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x01,  0x80,  0xAB, 	/* 245E0 */
+	0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00, 	/* 245F0 */
+	0x1F,  0xF8,  0x00,  0x20,  0x00,  0x40,  0x7F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x01,  0x80, 	/* 24600 */
+	0xAC,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08, 	/* 24610 */
+	0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x80,  0x04,  0xB0,  0x08,  0x88,  0x10,  0x84,  0x60,  0x82,  0x01, 	/* 24620 */
+	0x80,  0xAD,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0, 	/* 24630 */
+	0x00,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x4F,  0xF2,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80, 	/* 24640 */
+	0x01,  0x80,  0xAE,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F, 	/* 24650 */
+	0xF8,  0x00,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x42,  0x42,  0x02,  0x40,  0x02,  0x40,  0x04,  0x41,  0x18, 	/* 24660 */
+	0x21,  0x60,  0x1F,  0xB0,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF0,  0x08,  0x10, 	/* 24670 */
+	0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x00,  0x80,  0x04,  0xA0,  0x08,  0x98,  0x10,  0x84, 	/* 24680 */
+	0x60,  0x82,  0x01,  0x80,  0xB3,  0x01,  0x00,  0x7F,  0xFE,  0x00,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x0F, 	/* 24690 */
+	0xF0,  0x00,  0x00,  0x7F,  0xFE,  0x40,  0x12,  0x41,  0xE2,  0x1F,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x01, 	/* 246A0 */
+	0x00,  0x00,  0x82,  0x00,  0x7E,  0xB6,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x1F,  0xFC,  0x13,  0xE4, 	/* 246B0 */
+	0x12,  0x24,  0x13,  0xE4,  0x10,  0x04,  0x1F,  0xFC,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x07,  0xF0, 	/* 246C0 */
+	0x00,  0x00,  0x7F,  0xFF,  0x00,  0x00,  0xBA,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 246D0 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x01,  0x40,  0x01,  0x40,  0x02,  0x20,  0x02,  0x20,  0x04,  0x10,  0x08, 	/* 246E0 */
+	0x08,  0x10,  0x04,  0x20,  0x02,  0x40,  0x01,  0x80,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x08,  0x10, 	/* 246F0 */
+	0x08,  0x10,  0x18,  0x10,  0x1B,  0xFF,  0x28,  0x10,  0x48,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10, 	/* 24700 */
+	0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x81,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x09, 	/* 24710 */
+	0xFC,  0x08,  0x00,  0x10,  0x00,  0x30,  0x00,  0x50,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10, 	/* 24720 */
+	0x00,  0x10,  0x00,  0x17,  0xFF,  0x10,  0x00,  0x10,  0x00,  0x82,  0x04,  0x40,  0x04,  0x40,  0x04,  0x40, 	/* 24730 */
+	0x08,  0x40,  0x0B,  0xFE,  0x10,  0x42,  0x10,  0x42,  0x30,  0x42,  0x50,  0x42,  0x10,  0x42,  0x10,  0x42, 	/* 24740 */
+	0x10,  0x82,  0x10,  0x82,  0x11,  0x02,  0x12,  0x04,  0x14,  0x18,  0x84,  0x00,  0x00,  0x1F,  0xFF,  0x10, 	/* 24750 */
+	0x00,  0x10,  0x40,  0x10,  0x40,  0x10,  0x40,  0x10,  0x40,  0x10,  0x40,  0x10,  0x40,  0x10,  0x40,  0x10, 	/* 24760 */
+	0xA0,  0x10,  0xA0,  0x21,  0x10,  0x22,  0x08,  0x4C,  0x04,  0x30,  0x03,  0x86,  0x02,  0x20,  0x02,  0x20, 	/* 24770 */
+	0x04,  0x20,  0x04,  0x20,  0x08,  0x20,  0x08,  0x20,  0x18,  0x30,  0x28,  0x28,  0x48,  0x24,  0x08,  0x22, 	/* 24780 */
+	0x08,  0x22,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x87,  0x04,  0x80,  0x04, 	/* 24790 */
+	0x80,  0x04,  0x80,  0x08,  0x80,  0x08,  0xF0,  0x0F,  0x90,  0x10,  0x90,  0x30,  0x90,  0x50,  0x90,  0x10, 	/* 247A0 */
+	0x90,  0x10,  0x90,  0x11,  0x12,  0x11,  0x12,  0x12,  0x12,  0x14,  0x0E,  0x18,  0x00,  0x8A,  0x00,  0x80, 	/* 247B0 */
+	0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x04,  0x10,  0x08,  0x08,  0x13,  0xE4,  0x60,  0x03,  0x00,  0x00, 	/* 247C0 */
+	0x0F,  0xF0,  0x00,  0x10,  0x00,  0x20,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x01,  0x00,  0x8B,  0x00, 	/* 247D0 */
+	0x80,  0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x04,  0x10,  0x18,  0x0C,  0x64,  0x13,  0x04,  0x10,  0x04, 	/* 247E0 */
+	0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x08,  0x10,  0x08,  0x10,  0x10,  0x10,  0x20,  0x10,  0x8D, 	/* 247F0 */
+	0x04,  0x00,  0x07,  0xF8,  0x04,  0x88,  0x08,  0x88,  0x08,  0x88,  0x10,  0x88,  0x10,  0x8E,  0x30,  0x82, 	/* 24800 */
+	0x50,  0x82,  0x10,  0x82,  0x10,  0x82,  0x11,  0x02,  0x11,  0x02,  0x12,  0x02,  0x14,  0x04,  0x18,  0x18, 	/* 24810 */
+	0x8E,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04, 	/* 24820 */
+	0x10,  0x06,  0x10,  0x0A,  0x18,  0x09,  0x28,  0x09,  0x28,  0x10,  0xC4,  0x10,  0x44,  0x20,  0x82,  0x41, 	/* 24830 */
+	0x01,  0x8F,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x08,  0x20,  0x08,  0x20,  0x10,  0x20,  0x10,  0x40, 	/* 24840 */
+	0x30,  0x40,  0x50,  0x50,  0x10,  0x48,  0x10,  0x84,  0x10,  0x84,  0x10,  0x82,  0x11,  0x3E,  0x17,  0xC1, 	/* 24850 */
+	0x10,  0x01,  0x94,  0x04,  0x00,  0x05,  0xFC,  0x04,  0x04,  0x08,  0x08,  0x08,  0x10,  0x10,  0x20,  0x30, 	/* 24860 */
+	0x20,  0x57,  0xFF,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10, 	/* 24870 */
+	0x20,  0x10,  0x60,  0x95,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x08,  0x20,  0x08,  0x20,  0x10,  0x20, 	/* 24880 */
+	0x17,  0xFF,  0x30,  0x20,  0x50,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20, 	/* 24890 */
+	0x13,  0xFE,  0x10,  0x00,  0x96,  0x04,  0x10,  0x04,  0x10,  0x04,  0x90,  0x08,  0x92,  0x08,  0x9E,  0x18, 	/* 248A0 */
+	0xF2,  0x1B,  0x92,  0x28,  0x92,  0x48,  0x92,  0x08,  0x92,  0x08,  0x9C,  0x08,  0x90,  0x08,  0x81,  0x08, 	/* 248B0 */
+	0x81,  0x08,  0x41,  0x08,  0x3F,  0x97,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x08,  0x20,  0x0B,  0xFF, 	/* 248C0 */
+	0x10,  0x20,  0x11,  0x20,  0x31,  0x20,  0x50,  0xA0,  0x10,  0xA0,  0x10,  0x40,  0x10,  0x40,  0x10,  0xA0, 	/* 248D0 */
+	0x11,  0x10,  0x12,  0x0C,  0x1C,  0x03,  0x98,  0x02,  0x08,  0x02,  0x08,  0x02,  0x08,  0x04,  0x08,  0x05, 	/* 248E0 */
+	0xFF,  0x08,  0x08,  0x0A,  0x08,  0x19,  0x08,  0x28,  0x88,  0x48,  0x88,  0x08,  0x88,  0x08,  0x08,  0x08, 	/* 248F0 */
+	0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x18,  0x99,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x08,  0x20, 	/* 24900 */
+	0x0A,  0x22,  0x12,  0x22,  0x12,  0x22,  0x32,  0x22,  0x52,  0x22,  0x12,  0x22,  0x12,  0x22,  0x12,  0x22, 	/* 24910 */
+	0x12,  0x22,  0x12,  0x22,  0x13,  0xFE,  0x10,  0x00,  0x9D,  0x00,  0x80,  0x00,  0x80,  0x01,  0x40,  0x02, 	/* 24920 */
+	0x20,  0x04,  0x10,  0x18,  0x0C,  0x60,  0x03,  0x00,  0x00,  0x0F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 24930 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x00,  0x9E,  0x04,  0x00,  0x07,  0xFE,  0x04,  0x42, 	/* 24940 */
+	0x08,  0x42,  0x08,  0x42,  0x11,  0x42,  0x11,  0x42,  0x31,  0x42,  0x52,  0x42,  0x14,  0x42,  0x10,  0x42, 	/* 24950 */
+	0x10,  0x82,  0x10,  0x82,  0x11,  0x02,  0x12,  0x04,  0x14,  0x18,  0x9F,  0x04,  0x04,  0x04,  0x18,  0x05, 	/* 24960 */
+	0xE0,  0x08,  0x20,  0x08,  0x20,  0x10,  0x20,  0x10,  0x20,  0x37,  0xFF,  0x50,  0x20,  0x10,  0x20,  0x10, 	/* 24970 */
+	0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0xA3,  0x04,  0x28,  0x04,  0x24, 	/* 24980 */
+	0x04,  0x22,  0x08,  0x20,  0x08,  0x20,  0x18,  0x3F,  0x1B,  0xE0,  0x28,  0x20,  0x48,  0x10,  0x08,  0x10, 	/* 24990 */
+	0x08,  0x10,  0x08,  0x08,  0x08,  0x09,  0x08,  0x05,  0x08,  0x03,  0x08,  0x01,  0xA4,  0x00,  0x80,  0x00, 	/* 249A0 */
+	0x80,  0x01,  0x40,  0x02,  0x20,  0x04,  0x10,  0x18,  0x0C,  0x67,  0xF3,  0x00,  0x00,  0x00,  0x00,  0x3F, 	/* 249B0 */
+	0xFC,  0x00,  0x84,  0x00,  0x84,  0x00,  0x84,  0x00,  0x98,  0x00,  0x80,  0x00,  0x80,  0xA5,  0x00,  0x00, 	/* 249C0 */
+	0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x12,  0x08,  0x11,  0x08,  0x10,  0x88,  0x10,  0x88,  0x10,  0x08, 	/* 249D0 */
+	0x10,  0x08,  0x10,  0x18,  0x11,  0x14,  0x16,  0x22,  0x18,  0x42,  0x60,  0x81,  0x03,  0x01,  0xAD,  0x04, 	/* 249E0 */
+	0x00,  0x07,  0xFC,  0x04,  0x44,  0x08,  0x44,  0x08,  0x44,  0x10,  0x44,  0x12,  0x44,  0x31,  0x44,  0x50, 	/* 249F0 */
+	0xC4,  0x10,  0x74,  0x10,  0x4F,  0x10,  0x84,  0x10,  0x84,  0x11,  0x04,  0x12,  0x08,  0x14,  0x30,  0xAE, 	/* 24A00 */
+	0x04,  0x00,  0x05,  0xFF,  0x05,  0x00,  0x09,  0x00,  0x09,  0x00,  0x11,  0xFC,  0x11,  0x84,  0x31,  0x44, 	/* 24A10 */
+	0x51,  0x48,  0x11,  0x28,  0x12,  0x30,  0x12,  0x10,  0x14,  0x28,  0x14,  0x44,  0x19,  0x82,  0x16,  0x01, 	/* 24A20 */
+	0xB0,  0x04,  0x40,  0x04,  0x80,  0x07,  0x3E,  0x0A,  0x22,  0x0A,  0x22,  0x12,  0x22,  0x12,  0x22,  0x32, 	/* 24A30 */
+	0x22,  0x52,  0x22,  0x12,  0x22,  0x12,  0x62,  0x13,  0xA2,  0x16,  0x2C,  0x10,  0x20,  0x10,  0x20,  0x10, 	/* 24A40 */
+	0x20,  0xB2,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x08,  0x20,  0x0B,  0xFE,  0x1A,  0x22,  0x1A,  0x22, 	/* 24A50 */
+	0x2A,  0x22,  0x4A,  0x22,  0x0B,  0xFE,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20, 	/* 24A60 */
+	0x08,  0x20,  0xB6,  0x04,  0x20,  0x05,  0x20,  0x05,  0x20,  0x09,  0x20,  0x09,  0xFE,  0x12,  0x20,  0x12, 	/* 24A70 */
+	0x20,  0x34,  0x20,  0x50,  0x20,  0x13,  0xFF,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10, 	/* 24A80 */
+	0x20,  0x10,  0x20,  0xB7,  0x04,  0x20,  0x04,  0x20,  0x04,  0x50,  0x08,  0x50,  0x08,  0x88,  0x11,  0x8C, 	/* 24A90 */
+	0x12,  0x8A,  0x34,  0x89,  0x50,  0x88,  0x10,  0x88,  0x10,  0x88,  0x10,  0x88,  0x11,  0x08,  0x11,  0x08, 	/* 24AA0 */
+	0x12,  0x08,  0x14,  0x08,  0xBB,  0x04,  0x04,  0x04,  0x18,  0x04,  0x60,  0x0B,  0xA0,  0x08,  0x20,  0x18, 	/* 24AB0 */
+	0x20,  0x18,  0x20,  0x2F,  0xFF,  0x48,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x0B, 	/* 24AC0 */
+	0xFE,  0x08,  0x00,  0x08,  0x00,  0x81,  0x00,  0x80,  0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x04,  0x10, 	/* 24AD0 */
+	0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0x08,  0xFC,  0x08,  0x80,  0x08,  0x80,  0x08,  0x80,  0x08,  0x80, 	/* 24AE0 */
+	0x08,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x89,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x0B,  0xFF,  0x08, 	/* 24AF0 */
+	0x00,  0x10,  0x00,  0x10,  0xF0,  0x30,  0x90,  0x50,  0x90,  0x10,  0x90,  0x10,  0x90,  0x11,  0x10,  0x11, 	/* 24B00 */
+	0x10,  0x12,  0x12,  0x14,  0x12,  0x18,  0x0E,  0x8A,  0x04,  0x00,  0x05,  0xFC,  0x04,  0x24,  0x08,  0x24, 	/* 24B10 */
+	0x08,  0x24,  0x1F,  0xFF,  0x18,  0x24,  0x28,  0x24,  0x48,  0x24,  0x09,  0xFC,  0x08,  0x20,  0x08,  0x20, 	/* 24B20 */
+	0x08,  0x40,  0x08,  0x40,  0x08,  0x80,  0x09,  0x00,  0x8D,  0x04,  0x00,  0x07,  0xFE,  0x04,  0x40,  0x08, 	/* 24B30 */
+	0x40,  0x08,  0x40,  0x10,  0x40,  0x13,  0xF8,  0x30,  0x48,  0x50,  0x48,  0x10,  0x48,  0x10,  0x88,  0x10, 	/* 24B40 */
+	0x88,  0x10,  0x88,  0x10,  0x88,  0x17,  0xFF,  0x10,  0x00,  0x8E,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20, 	/* 24B50 */
+	0x0F,  0xFF,  0x08,  0x20,  0x18,  0x20,  0x18,  0x20,  0x2B,  0xFC,  0x48,  0x84,  0x08,  0x48,  0x08,  0x48, 	/* 24B60 */
+	0x08,  0x30,  0x08,  0x30,  0x08,  0x48,  0x08,  0x84,  0x0B,  0x03,  0x8F,  0x04,  0x40,  0x04,  0x48,  0x04, 	/* 24B70 */
+	0x44,  0x08,  0x44,  0x08,  0x40,  0x17,  0xFF,  0x10,  0x40,  0x30,  0x40,  0x50,  0x40,  0x10,  0x60,  0x10, 	/* 24B80 */
+	0xA0,  0x10,  0x90,  0x11,  0x08,  0x12,  0x04,  0x14,  0x02,  0x18,  0x01,  0x90,  0x04,  0x88,  0x04,  0x84, 	/* 24B90 */
+	0x04,  0x84,  0x08,  0x80,  0x0F,  0xFF,  0x10,  0x84,  0x10,  0x84,  0x30,  0x48,  0x50,  0x48,  0x10,  0x50, 	/* 24BA0 */
+	0x10,  0x20,  0x10,  0x50,  0x11,  0x92,  0x16,  0x0A,  0x10,  0x06,  0x10,  0x02,  0x91,  0x08,  0x40,  0x08, 	/* 24BB0 */
+	0x40,  0x08,  0x40,  0x08,  0x40,  0x17,  0xFE,  0x10,  0xE0,  0x10,  0xE0,  0x31,  0x50,  0x51,  0x50,  0x12, 	/* 24BC0 */
+	0x48,  0x12,  0x44,  0x14,  0x42,  0x18,  0x41,  0x10,  0x40,  0x10,  0x40,  0x10,  0x40,  0x9A,  0x00,  0x80, 	/* 24BD0 */
+	0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x04,  0x10,  0x18,  0x0C,  0x67,  0xF3,  0x00,  0x00,  0x00,  0x00, 	/* 24BE0 */
+	0x3F,  0xFE,  0x01,  0x00,  0x01,  0x20,  0x02,  0x10,  0x04,  0x68,  0x3F,  0x84,  0x00,  0x04,  0x9C,  0x04, 	/* 24BF0 */
+	0x40,  0x04,  0x40,  0x07,  0xF8,  0x08,  0x48,  0x08,  0x88,  0x10,  0x89,  0x11,  0x09,  0x32,  0x07,  0x54, 	/* 24C00 */
+	0x20,  0x10,  0x20,  0x17,  0xFF,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x9D, 	/* 24C10 */
+	0x04,  0x00,  0x04,  0x00,  0x05,  0xFC,  0x08,  0x00,  0x08,  0x00,  0x10,  0x00,  0x17,  0xFF,  0x30,  0x40, 	/* 24C20 */
+	0x50,  0x40,  0x10,  0x50,  0x10,  0x88,  0x10,  0x84,  0x11,  0x04,  0x11,  0x3E,  0x17,  0xC2,  0x10,  0x02, 	/* 24C30 */
+	0xAF,  0x04,  0x20,  0x04,  0x20,  0x04,  0x40,  0x09,  0xFC,  0x09,  0x04,  0x11,  0x04,  0x11,  0x04,  0x31, 	/* 24C40 */
+	0x04,  0x51,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x11,  0x04,  0x11,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x10, 	/* 24C50 */
+	0x00,  0xB0,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x08,  0x20,  0x0F,  0xFF,  0x10,  0x20,  0x10,  0x20, 	/* 24C60 */
+	0x30,  0x20,  0x50,  0x20,  0x11,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x11,  0x04,  0x11,  0x04,  0x11,  0xFC, 	/* 24C70 */
+	0x10,  0x00,  0xB4,  0x04,  0x20,  0x04,  0x24,  0x05,  0x24,  0x08,  0xA4,  0x08,  0xA8,  0x18,  0x20,  0x1B, 	/* 24C80 */
+	0xFE,  0x28,  0x20,  0x48,  0x20,  0x08,  0x20,  0x0F,  0xFF,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08, 	/* 24C90 */
+	0x20,  0x08,  0x20,  0xB6,  0x04,  0x20,  0x04,  0x20,  0x04,  0x50,  0x08,  0x88,  0x09,  0x04,  0x12,  0xFA, 	/* 24CA0 */
+	0x14,  0x01,  0x30,  0x00,  0x53,  0xFC,  0x10,  0x44,  0x10,  0x44,  0x10,  0x44,  0x10,  0x44,  0x10,  0x58, 	/* 24CB0 */
+	0x10,  0x40,  0x10,  0x40,  0xB8,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x0B,  0xFE,  0x0A,  0x22,  0x12, 	/* 24CC0 */
+	0x22,  0x12,  0x22,  0x33,  0xFE,  0x52,  0x22,  0x12,  0x22,  0x13,  0xFE,  0x10,  0x20,  0x10,  0x20,  0x10, 	/* 24CD0 */
+	0x20,  0x10,  0x20,  0x10,  0x20,  0xBA,  0x04,  0x00,  0x07,  0xFE,  0x04,  0x02,  0x08,  0x02,  0x0B,  0xFA, 	/* 24CE0 */
+	0x10,  0x02,  0x10,  0x02,  0x31,  0xF2,  0x51,  0x12,  0x11,  0x12,  0x11,  0x12,  0x11,  0xF2,  0x10,  0x02, 	/* 24CF0 */
+	0x10,  0x02,  0x10,  0x02,  0x10,  0x06,  0xBC,  0x04,  0x04,  0x05,  0x04,  0x05,  0x04,  0x09,  0x84,  0x09, 	/* 24D00 */
+	0x44,  0x11,  0x24,  0x11,  0x24,  0x31,  0x04,  0x51,  0x04,  0x11,  0x04,  0x11,  0x04,  0x11,  0x4C,  0x11, 	/* 24D10 */
+	0x8A,  0x13,  0x12,  0x1C,  0x21,  0x10,  0x41,  0xBD,  0x0A,  0x00,  0x0A,  0x00,  0x0A,  0x1E,  0x12,  0x12, 	/* 24D20 */
+	0x1F,  0xD2,  0x12,  0x52,  0x32,  0x52,  0x32,  0x52,  0x52,  0x52,  0x12,  0x52,  0x12,  0x52,  0x12,  0x52, 	/* 24D30 */
+	0x14,  0x52,  0x14,  0x5E,  0x19,  0x80,  0x10,  0x00,  0x83,  0x04,  0x00,  0x05,  0xFE,  0x05,  0x22,  0x09, 	/* 24D40 */
+	0x22,  0x09,  0x22,  0x11,  0x22,  0x11,  0x22,  0x31,  0xFE,  0x51,  0x22,  0x11,  0x22,  0x11,  0x22,  0x11, 	/* 24D50 */
+	0x22,  0x11,  0x22,  0x11,  0x22,  0x11,  0xFE,  0x10,  0x00,  0x86,  0x04,  0x00,  0x05,  0xFC,  0x05,  0x04, 	/* 24D60 */
+	0x09,  0x04,  0x09,  0x04,  0x19,  0x04,  0x19,  0xFC,  0x29,  0x04,  0x49,  0x04,  0x09,  0x04,  0x09,  0x04, 	/* 24D70 */
+	0x09,  0xFC,  0x08,  0x00,  0x08,  0x00,  0x0F,  0xFF,  0x08,  0x00,  0x87,  0x04,  0x20,  0x04,  0x20,  0x07, 	/* 24D80 */
+	0xFE,  0x0A,  0x02,  0x0A,  0x02,  0x10,  0x00,  0x13,  0xFF,  0x30,  0x20,  0x50,  0x20,  0x10,  0x20,  0x10, 	/* 24D90 */
+	0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x60,  0x8D,  0x04,  0x20,  0x04,  0x20, 	/* 24DA0 */
+	0x04,  0x20,  0x08,  0x20,  0x0B,  0xFE,  0x18,  0x04,  0x18,  0x04,  0x29,  0x04,  0x48,  0x88,  0x08,  0x88, 	/* 24DB0 */
+	0x08,  0x88,  0x08,  0x90,  0x08,  0x90,  0x08,  0x20,  0x0F,  0xFF,  0x08,  0x00,  0x8E,  0x04,  0x04,  0x04, 	/* 24DC0 */
+	0x18,  0x05,  0xF0,  0x09,  0x10,  0x09,  0x10,  0x11,  0x10,  0x11,  0xFF,  0x31,  0x10,  0x51,  0x10,  0x11, 	/* 24DD0 */
+	0x08,  0x11,  0x08,  0x11,  0xC8,  0x16,  0x04,  0x10,  0x05,  0x17,  0xF3,  0x10,  0x01,  0x8F,  0x04,  0x40, 	/* 24DE0 */
+	0x04,  0x20,  0x04,  0x20,  0x0B,  0xFE,  0x08,  0x20,  0x10,  0x20,  0x10,  0x20,  0x30,  0x20,  0x53,  0xFE, 	/* 24DF0 */
+	0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x17,  0xFF,  0x10,  0x00,  0x90,  0x04, 	/* 24E00 */
+	0x40,  0x04,  0x40,  0x04,  0x40,  0x0B,  0xFF,  0x08,  0x40,  0x10,  0x40,  0x10,  0x80,  0x30,  0x80,  0x51, 	/* 24E10 */
+	0xFE,  0x11,  0x20,  0x12,  0x20,  0x14,  0x20,  0x10,  0x20,  0x10,  0x20,  0x13,  0xFF,  0x10,  0x00,  0x91, 	/* 24E20 */
+	0x04,  0x40,  0x04,  0x40,  0x04,  0x40,  0x0F,  0xFF,  0x08,  0x40,  0x10,  0x40,  0x10,  0x80,  0x30,  0x80, 	/* 24E30 */
+	0x51,  0xFC,  0x11,  0x84,  0x12,  0x84,  0x14,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0xFC,  0x10,  0x00, 	/* 24E40 */
+	0x93,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x17,  0xFF,  0x10,  0x70,  0x10,  0x70,  0x30, 	/* 24E50 */
+	0xA8,  0x50,  0xA8,  0x11,  0x24,  0x12,  0x22,  0x14,  0xFD,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10, 	/* 24E60 */
+	0x20,  0x95,  0x04,  0x00,  0x04,  0x00,  0x07,  0xFF,  0x08,  0x04,  0x08,  0x04,  0x13,  0xE4,  0x12,  0x24, 	/* 24E70 */
+	0x32,  0x24,  0x52,  0x24,  0x12,  0x24,  0x13,  0xE4,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04, 	/* 24E80 */
+	0x10,  0x0C,  0x97,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x0B,  0xFE,  0x0A,  0x02,  0x12,  0x82,  0x10, 	/* 24E90 */
+	0x80,  0x30,  0x84,  0x50,  0x98,  0x10,  0xE0,  0x10,  0x80,  0x10,  0x80,  0x10,  0x80,  0x10,  0x82,  0x10, 	/* 24EA0 */
+	0x42,  0x10,  0x3E,  0x99,  0x00,  0x80,  0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x04,  0x10,  0x18,  0x0C, 	/* 24EB0 */
+	0x67,  0xFB,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80,  0x04,  0x90,  0x04,  0x88,  0x08,  0x84, 	/* 24EC0 */
+	0x10,  0x84,  0x01,  0x80,  0x9A,  0x04,  0x20,  0x05,  0x20,  0x05,  0x20,  0x09,  0x20,  0x09,  0xFE,  0x12, 	/* 24ED0 */
+	0x20,  0x12,  0x20,  0x34,  0x20,  0x53,  0xFF,  0x10,  0x30,  0x10,  0x50,  0x10,  0x48,  0x10,  0x88,  0x11, 	/* 24EE0 */
+	0x04,  0x12,  0x02,  0x14,  0x01,  0x9B,  0x04,  0x90,  0x04,  0x90,  0x07,  0xFE,  0x08,  0x92,  0x08,  0x92, 	/* 24EF0 */
+	0x13,  0xFE,  0x12,  0x90,  0x32,  0x90,  0x53,  0xFF,  0x10,  0x91,  0x10,  0x91,  0x10,  0x91,  0x11,  0x12, 	/* 24F00 */
+	0x11,  0x1C,  0x12,  0x10,  0x14,  0x10,  0x9C,  0x04,  0x80,  0x04,  0x80,  0x04,  0x80,  0x08,  0xFF,  0x09, 	/* 24F10 */
+	0x20,  0x19,  0x20,  0x1A,  0x20,  0x2C,  0x3E,  0x48,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x3E,  0x08, 	/* 24F20 */
+	0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x9D,  0x04,  0x80,  0x04,  0x80,  0x04,  0x80,  0x08,  0xFE, 	/* 24F30 */
+	0x09,  0x02,  0x11,  0x02,  0x13,  0xF2,  0x35,  0x12,  0x51,  0x12,  0x11,  0x12,  0x11,  0x12,  0x11,  0xF2, 	/* 24F40 */
+	0x10,  0x02,  0x10,  0x02,  0x10,  0x04,  0x10,  0x18,  0x9E,  0x04,  0x00,  0x05,  0xFC,  0x04,  0x00,  0x08, 	/* 24F50 */
+	0x00,  0x08,  0x00,  0x17,  0xFF,  0x10,  0x40,  0x30,  0x40,  0x57,  0xFF,  0x10,  0x88,  0x10,  0x88,  0x11, 	/* 24F60 */
+	0x10,  0x13,  0xF0,  0x10,  0x28,  0x10,  0xC4,  0x17,  0x02,  0xA9,  0x08,  0x00,  0x0B,  0xFC,  0x0A,  0x04, 	/* 24F70 */
+	0x0A,  0x04,  0x13,  0xFC,  0x12,  0x44,  0x32,  0x44,  0x33,  0xF4,  0x53,  0x54,  0x13,  0x54,  0x13,  0x54, 	/* 24F80 */
+	0x13,  0x54,  0x15,  0x75,  0x15,  0x45,  0x18,  0x43,  0x10,  0x41,  0xAF,  0x04,  0x84,  0x04,  0x44,  0x04, 	/* 24F90 */
+	0x48,  0x0B,  0xFE,  0x08,  0x20,  0x10,  0x20,  0x10,  0x20,  0x31,  0xFC,  0x50,  0x20,  0x10,  0x20,  0x10, 	/* 24FA0 */
+	0x20,  0x17,  0xFF,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0xB0,  0x04,  0x00,  0x07,  0xFF, 	/* 24FB0 */
+	0x04,  0x20,  0x08,  0x20,  0x08,  0x40,  0x11,  0xFC,  0x11,  0x04,  0x31,  0x04,  0x51,  0x04,  0x11,  0xFC, 	/* 24FC0 */
+	0x11,  0x04,  0x11,  0x04,  0x11,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x10,  0x00,  0xB3,  0x04,  0x20,  0x04, 	/* 24FD0 */
+	0x20,  0x05,  0xFC,  0x08,  0x20,  0x08,  0x20,  0x18,  0x20,  0x2B,  0xFE,  0x28,  0x20,  0x48,  0x20,  0x08, 	/* 24FE0 */
+	0x20,  0x09,  0xFC,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x0B,  0xFE,  0x08,  0x00,  0xB5,  0x05,  0x04, 	/* 24FF0 */
+	0x04,  0x84,  0x04,  0x88,  0x0B,  0xFE,  0x08,  0x88,  0x10,  0x88,  0x10,  0x88,  0x30,  0x88,  0x57,  0xFF, 	/* 25000 */
+	0x10,  0x88,  0x10,  0x88,  0x10,  0x88,  0x10,  0x88,  0x11,  0x08,  0x11,  0x08,  0x12,  0x08,  0xB6,  0x04, 	/* 25010 */
+	0x20,  0x04,  0x20,  0x04,  0x20,  0x0F,  0xFF,  0x08,  0x20,  0x10,  0x20,  0x10,  0x20,  0x33,  0xFE,  0x50, 	/* 25020 */
+	0x00,  0x10,  0x00,  0x11,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x10,  0x00,  0xBB, 	/* 25030 */
+	0x04,  0x90,  0x04,  0x90,  0x04,  0x92,  0x08,  0x92,  0x0C,  0x94,  0x12,  0x90,  0x12,  0x90,  0x30,  0x98, 	/* 25040 */
+	0x50,  0x94,  0x11,  0x92,  0x12,  0x91,  0x1C,  0x90,  0x11,  0x10,  0x11,  0x11,  0x12,  0x11,  0x14,  0x0F, 	/* 25050 */
+	0xBC,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x0B,  0xFF,  0x08,  0x88,  0x10,  0x84,  0x11,  0x0A,  0x32, 	/* 25060 */
+	0x8A,  0x54,  0x88,  0x10,  0x50,  0x10,  0x50,  0x10,  0x20,  0x10,  0x50,  0x10,  0x88,  0x11,  0x04,  0x16, 	/* 25070 */
+	0x03,  0xBF,  0x04,  0x20,  0x04,  0x20,  0x07,  0xFF,  0x08,  0x20,  0x08,  0x20,  0x13,  0xFE,  0x12,  0x22, 	/* 25080 */
+	0x32,  0x22,  0x52,  0x22,  0x13,  0xFE,  0x10,  0xA0,  0x10,  0x40,  0x10,  0x60,  0x10,  0x90,  0x13,  0x0C, 	/* 25090 */
+	0x1C,  0x03,  0x83,  0x04,  0x00,  0x05,  0xFC,  0x05,  0x04,  0x09,  0x04,  0x09,  0x04,  0x11,  0xFC,  0x10, 	/* 250A0 */
+	0x00,  0x31,  0x24,  0x51,  0x24,  0x11,  0x24,  0x11,  0x24,  0x11,  0x24,  0x11,  0x24,  0x12,  0x25,  0x12, 	/* 250B0 */
+	0x25,  0x14,  0x03,  0x86,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x08,  0x88,  0x08,  0x88,  0x0C,  0x8C, 	/* 250C0 */
+	0x14,  0x94,  0x12,  0x92,  0x20,  0xA0,  0x01,  0xC0,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83, 	/* 250D0 */
+	0x00,  0x80,  0x00,  0x80,  0x88,  0x04,  0x40,  0x04,  0x40,  0x04,  0x78,  0x08,  0x88,  0x09,  0x90,  0x16, 	/* 250E0 */
+	0x50,  0x10,  0x20,  0x30,  0x50,  0x51,  0x9E,  0x16,  0x22,  0x10,  0x64,  0x11,  0x94,  0x10,  0x08,  0x10, 	/* 250F0 */
+	0x10,  0x10,  0x60,  0x13,  0x80,  0x8B,  0x08,  0x02,  0x0F,  0xF2,  0x09,  0x12,  0x11,  0x12,  0x11,  0x12, 	/* 25100 */
+	0x11,  0xD2,  0x32,  0x52,  0x32,  0x52,  0x53,  0x52,  0x14,  0xD2,  0x18,  0x92,  0x10,  0x82,  0x11,  0x02, 	/* 25110 */
+	0x11,  0x02,  0x12,  0x02,  0x14,  0x06,  0x8D,  0x04,  0x20,  0x04,  0x20,  0x05,  0xFE,  0x08,  0x20,  0x08, 	/* 25120 */
+	0x20,  0x10,  0x20,  0x17,  0xFF,  0x30,  0x08,  0x50,  0x08,  0x13,  0xFE,  0x11,  0x08,  0x10,  0x88,  0x10, 	/* 25130 */
+	0x88,  0x10,  0x88,  0x10,  0x08,  0x10,  0x18,  0x8F,  0x04,  0x20,  0x04,  0xA0,  0x04,  0xA0,  0x08,  0xFE, 	/* 25140 */
+	0x09,  0x20,  0x12,  0x20,  0x10,  0x20,  0x33,  0xFF,  0x50,  0x70,  0x10,  0x70,  0x10,  0xA8,  0x11,  0x28, 	/* 25150 */
+	0x12,  0x24,  0x14,  0x22,  0x10,  0x21,  0x10,  0x20,  0x91,  0x04,  0x40,  0x04,  0x40,  0x07,  0xFF,  0x08, 	/* 25160 */
+	0x40,  0x08,  0x80,  0x10,  0xFC,  0x11,  0x84,  0x31,  0x84,  0x52,  0xFC,  0x14,  0x84,  0x10,  0x84,  0x10, 	/* 25170 */
+	0xFC,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x8C,  0x96,  0x00,  0x80,  0x00,  0x80,  0x01,  0x40, 	/* 25180 */
+	0x02,  0x30,  0x0C,  0x0C,  0x37,  0xFB,  0x00,  0x00,  0x00,  0x00,  0x0F,  0xFC,  0x09,  0x24,  0x09,  0x24, 	/* 25190 */
+	0x0F,  0xFC,  0x09,  0x24,  0x09,  0x24,  0x09,  0x24,  0x09,  0x2C,  0x98,  0x04,  0x20,  0x04,  0x20,  0x07, 	/* 251A0 */
+	0xFE,  0x0A,  0x02,  0x0A,  0x0A,  0x10,  0x30,  0x13,  0xC0,  0x30,  0x40,  0x50,  0x40,  0x10,  0x7F,  0x17, 	/* 251B0 */
+	0xC0,  0x10,  0x40,  0x10,  0x40,  0x10,  0x42,  0x10,  0x22,  0x10,  0x1E,  0x9B,  0x04,  0x88,  0x04,  0x88, 	/* 251C0 */
+	0x04,  0x88,  0x08,  0x88,  0x0B,  0xFE,  0x18,  0x88,  0x18,  0x88,  0x28,  0x88,  0x48,  0x88,  0x0F,  0xFF, 	/* 251D0 */
+	0x08,  0x00,  0x08,  0x88,  0x08,  0x84,  0x09,  0x04,  0x0A,  0x02,  0x0C,  0x02,  0x9D,  0x04,  0x20,  0x04, 	/* 251E0 */
+	0x20,  0x04,  0x20,  0x0F,  0xFF,  0x08,  0xC0,  0x10,  0xA2,  0x10,  0xA2,  0x31,  0x24,  0x53,  0x24,  0x15, 	/* 251F0 */
+	0x18,  0x19,  0x10,  0x11,  0x08,  0x11,  0x08,  0x11,  0x64,  0x11,  0x82,  0x16,  0x01,  0xA0,  0x04,  0x40, 	/* 25200 */
+	0x04,  0x40,  0x07,  0xFE,  0x08,  0x40,  0x0A,  0x48,  0x11,  0x48,  0x11,  0x48,  0x31,  0x50,  0x50,  0x40, 	/* 25210 */
+	0x1F,  0xFF,  0x10,  0x60,  0x10,  0xA0,  0x10,  0x90,  0x11,  0x08,  0x12,  0x04,  0x1C,  0x02,  0xA1,  0x04, 	/* 25220 */
+	0x00,  0x04,  0x00,  0x07,  0xFF,  0x08,  0x50,  0x08,  0x50,  0x10,  0x50,  0x13,  0xFE,  0x32,  0x52,  0x52, 	/* 25230 */
+	0x52,  0x12,  0x52,  0x12,  0x52,  0x12,  0x52,  0x12,  0x52,  0x12,  0x52,  0x13,  0xFE,  0x10,  0x00,  0xAB, 	/* 25240 */
+	0x04,  0x20,  0x04,  0x20,  0x05,  0xFF,  0x05,  0x00,  0x09,  0x00,  0x10,  0xFE,  0x10,  0x40,  0x30,  0x40, 	/* 25250 */
+	0x57,  0xFF,  0x10,  0x88,  0x10,  0x88,  0x11,  0x10,  0x13,  0xF0,  0x10,  0x28,  0x10,  0xC4,  0x17,  0x02, 	/* 25260 */
+	0xAD,  0x04,  0x00,  0x05,  0xFC,  0x05,  0x04,  0x09,  0x04,  0x09,  0x04,  0x11,  0xFC,  0x11,  0x10,  0x31, 	/* 25270 */
+	0x10,  0x52,  0x08,  0x12,  0xC4,  0x14,  0x22,  0x18,  0x11,  0x11,  0x80,  0x10,  0x60,  0x10,  0x10,  0x10, 	/* 25280 */
+	0x08,  0xAE,  0x04,  0x80,  0x04,  0x80,  0x04,  0xFF,  0x09,  0x00,  0x09,  0x00,  0x12,  0xFC,  0x14,  0xA4, 	/* 25290 */
+	0x30,  0xA4,  0x57,  0xFF,  0x11,  0x24,  0x11,  0x24,  0x11,  0x24,  0x13,  0xFF,  0x12,  0x04,  0x10,  0x08, 	/* 252A0 */
+	0x10,  0x30,  0xAF,  0x04,  0x00,  0x05,  0xF8,  0x04,  0x08,  0x08,  0x08,  0x0F,  0xFF,  0x10,  0x80,  0x10, 	/* 252B0 */
+	0x80,  0x30,  0xFC,  0x51,  0x20,  0x12,  0x20,  0x17,  0xFF,  0x10,  0x20,  0x10,  0x50,  0x10,  0x88,  0x11, 	/* 252C0 */
+	0x04,  0x16,  0x03,  0xB5,  0x04,  0x00,  0x05,  0xFC,  0x04,  0x04,  0x08,  0xFC,  0x08,  0x04,  0x11,  0xFC, 	/* 252D0 */
+	0x10,  0x00,  0x37,  0xFF,  0x54,  0x01,  0x17,  0xF9,  0x10,  0x88,  0x10,  0x50,  0x10,  0x20,  0x10,  0x50, 	/* 252E0 */
+	0x11,  0x8C,  0x16,  0x03,  0xB6,  0x04,  0x00,  0x05,  0xFC,  0x05,  0x04,  0x09,  0x04,  0x09,  0x04,  0x11, 	/* 252F0 */
+	0xFC,  0x10,  0x20,  0x30,  0x20,  0x50,  0x40,  0x13,  0xFE,  0x12,  0x02,  0x12,  0x02,  0x12,  0x02,  0x12, 	/* 25300 */
+	0x02,  0x13,  0xFE,  0x10,  0x00,  0xBF,  0x04,  0x00,  0x07,  0xFF,  0x04,  0x20,  0x09,  0xFE,  0x09,  0x22, 	/* 25310 */
+	0x19,  0x22,  0x19,  0xFE,  0x29,  0x22,  0x49,  0x22,  0x09,  0xFE,  0x08,  0xA0,  0x08,  0x40,  0x08,  0x60, 	/* 25320 */
+	0x08,  0x90,  0x0B,  0x0C,  0x0C,  0x03,  0x82,  0x04,  0x06,  0x04,  0x38,  0x07,  0xC0,  0x08,  0x48,  0x08, 	/* 25330 */
+	0x88,  0x13,  0x10,  0x10,  0xA0,  0x30,  0x48,  0x50,  0x84,  0x17,  0xFE,  0x10,  0x22,  0x11,  0x28,  0x11, 	/* 25340 */
+	0x24,  0x12,  0x22,  0x14,  0x22,  0x10,  0x20,  0x83,  0x04,  0x00,  0x05,  0xFE,  0x05,  0x02,  0x09,  0x02, 	/* 25350 */
+	0x09,  0x02,  0x11,  0x02,  0x11,  0xFE,  0x30,  0x20,  0x50,  0x20,  0x11,  0x20,  0x11,  0x3E,  0x11,  0x20, 	/* 25360 */
+	0x12,  0xA0,  0x12,  0x60,  0x14,  0x30,  0x18,  0x0F,  0x84,  0x04,  0x50,  0x04,  0x94,  0x07,  0x12,  0x09, 	/* 25370 */
+	0x12,  0x09,  0x10,  0x1F,  0xFF,  0x11,  0x10,  0x31,  0x12,  0x51,  0x52,  0x11,  0x94,  0x17,  0x08,  0x11, 	/* 25380 */
+	0x1A,  0x11,  0x2A,  0x11,  0x46,  0x11,  0x86,  0x13,  0x02,  0x8A,  0x04,  0x40,  0x04,  0x50,  0x04,  0x8C, 	/* 25390 */
+	0x0B,  0xFA,  0x08,  0x90,  0x10,  0x91,  0x11,  0x0F,  0x32,  0x80,  0x54,  0xF8,  0x10,  0x88,  0x11,  0x88, 	/* 253A0 */
+	0x12,  0x50,  0x14,  0x20,  0x10,  0x50,  0x11,  0x8C,  0x16,  0x03,  0x8E,  0x08,  0x00,  0x08,  0x7C,  0x08, 	/* 253B0 */
+	0x44,  0x14,  0x44,  0x12,  0x44,  0x21,  0x7C,  0x40,  0x44,  0x08,  0x44,  0x08,  0x44,  0x08,  0x7C,  0x14, 	/* 253C0 */
+	0x44,  0x12,  0x44,  0x21,  0x44,  0x40,  0x44,  0x03,  0xFF,  0x00,  0x00,  0x90,  0x08,  0x42,  0x09,  0x92, 	/* 253D0 */
+	0x0F,  0x12,  0x11,  0x12,  0x11,  0x12,  0x1F,  0xD2,  0x31,  0x12,  0x31,  0x12,  0x53,  0x92,  0x13,  0x52, 	/* 253E0 */
+	0x15,  0x52,  0x15,  0x12,  0x19,  0x02,  0x11,  0x02,  0x11,  0x02,  0x11,  0x06,  0x91,  0x04,  0x00,  0x07, 	/* 253F0 */
+	0xFC,  0x04,  0x08,  0x08,  0xD0,  0x08,  0x20,  0x13,  0xFE,  0x12,  0x22,  0x32,  0x22,  0x53,  0xFE,  0x12, 	/* 25400 */
+	0x22,  0x12,  0x22,  0x13,  0xFE,  0x12,  0x22,  0x12,  0x22,  0x12,  0x22,  0x12,  0x26,  0x94,  0x04,  0x00, 	/* 25410 */
+	0x05,  0xFC,  0x05,  0x04,  0x09,  0x04,  0x09,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x31,  0x04,  0x51,  0x04, 	/* 25420 */
+	0x11,  0xFC,  0x10,  0x50,  0x10,  0x50,  0x10,  0x90,  0x11,  0x11,  0x12,  0x11,  0x1C,  0x0F,  0x97,  0x04, 	/* 25430 */
+	0x88,  0x04,  0x84,  0x04,  0x84,  0x09,  0x22,  0x0A,  0x22,  0x10,  0x50,  0x10,  0x50,  0x30,  0x88,  0x51, 	/* 25440 */
+	0x04,  0x13,  0xFE,  0x15,  0x05,  0x11,  0x04,  0x11,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x10,  0x00,  0x98, 	/* 25450 */
+	0x04,  0x04,  0x04,  0x38,  0x07,  0xC4,  0x09,  0x22,  0x09,  0x22,  0x12,  0x01,  0x15,  0xFD,  0x30,  0x08, 	/* 25460 */
+	0x50,  0x10,  0x10,  0x20,  0x17,  0xFF,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x60, 	/* 25470 */
+	0x9A,  0x04,  0x00,  0x05,  0xFC,  0x05,  0x24,  0x09,  0x24,  0x09,  0xFC,  0x11,  0x24,  0x11,  0x24,  0x31, 	/* 25480 */
+	0xFC,  0x50,  0x20,  0x10,  0x20,  0x13,  0xFE,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x17,  0xFF,  0x10, 	/* 25490 */
+	0x00,  0x9B,  0x04,  0x40,  0x04,  0x78,  0x04,  0x88,  0x09,  0x10,  0x09,  0x20,  0x13,  0xFE,  0x15,  0x22, 	/* 254A0 */
+	0x31,  0x22,  0x51,  0x42,  0x11,  0xFE,  0x10,  0x50,  0x10,  0x50,  0x10,  0x90,  0x11,  0x11,  0x12,  0x11, 	/* 254B0 */
+	0x1C,  0x0F,  0x9D,  0x04,  0x00,  0x05,  0xFC,  0x05,  0x04,  0x09,  0x04,  0x09,  0x04,  0x11,  0xFC,  0x10, 	/* 254C0 */
+	0x20,  0x30,  0x20,  0x57,  0xFF,  0x10,  0x70,  0x10,  0xA8,  0x11,  0x24,  0x12,  0x22,  0x14,  0x21,  0x10, 	/* 254D0 */
+	0x20,  0x10,  0x20,  0x9F,  0x04,  0x40,  0x04,  0x50,  0x04,  0x4C,  0x08,  0x9A,  0x0B,  0xE1,  0x10,  0x80, 	/* 254E0 */
+	0x10,  0x80,  0x31,  0xFE,  0x51,  0x20,  0x12,  0x20,  0x17,  0xFF,  0x10,  0x50,  0x10,  0x48,  0x10,  0x84, 	/* 254F0 */
+	0x13,  0x02,  0x1C,  0x01,  0xA1,  0x08,  0x00,  0x09,  0xF8,  0x08,  0x00,  0x0F,  0xFF,  0x10,  0x00,  0x13, 	/* 25500 */
+	0xFC,  0x30,  0x00,  0x30,  0x00,  0x53,  0xFC,  0x10,  0x00,  0x13,  0xFC,  0x12,  0x04,  0x12,  0x04,  0x12, 	/* 25510 */
+	0x04,  0x13,  0xFC,  0x10,  0x00,  0xA3,  0x04,  0x00,  0x05,  0xFC,  0x05,  0x04,  0x09,  0x04,  0x09,  0x04, 	/* 25520 */
+	0x11,  0xFC,  0x10,  0x00,  0x33,  0xFE,  0x50,  0x20,  0x10,  0x20,  0x17,  0xFF,  0x10,  0x50,  0x10,  0x48, 	/* 25530 */
+	0x10,  0x84,  0x11,  0x02,  0x12,  0x01,  0xA4,  0x05,  0x08,  0x04,  0x88,  0x04,  0x90,  0x0F,  0xFE,  0x08, 	/* 25540 */
+	0x22,  0x10,  0x22,  0x13,  0xFE,  0x32,  0x20,  0x52,  0x20,  0x13,  0xFE,  0x10,  0x62,  0x10,  0xA2,  0x11, 	/* 25550 */
+	0x22,  0x12,  0x22,  0x14,  0x2C,  0x10,  0x20,  0xA5,  0x04,  0x20,  0x04,  0x20,  0x07,  0xFF,  0x08,  0x20, 	/* 25560 */
+	0x09,  0xFC,  0x11,  0x24,  0x11,  0x24,  0x31,  0xFC,  0x51,  0x24,  0x11,  0x24,  0x11,  0xFC,  0x10,  0x20, 	/* 25570 */
+	0x17,  0xFF,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0xAE,  0x04,  0x40,  0x04,  0x40,  0x04,  0x7F,  0x08, 	/* 25580 */
+	0x88,  0x09,  0x88,  0x16,  0x50,  0x14,  0x30,  0x34,  0xCC,  0x57,  0x13,  0x14,  0x64,  0x15,  0x98,  0x14, 	/* 25590 */
+	0x62,  0x15,  0x84,  0x14,  0x18,  0x10,  0x60,  0x13,  0x80,  0xAF,  0x04,  0x20,  0x04,  0x20,  0x07,  0xFF, 	/* 255A0 */
+	0x0A,  0x00,  0x0A,  0x44,  0x12,  0x44,  0x12,  0x7F,  0x32,  0x84,  0x52,  0xA4,  0x13,  0x94,  0x12,  0x94, 	/* 255B0 */
+	0x12,  0x84,  0x14,  0x84,  0x14,  0x84,  0x18,  0x84,  0x10,  0x8C,  0xB3,  0x04,  0x90,  0x04,  0x90,  0x04, 	/* 255C0 */
+	0x90,  0x0F,  0x9E,  0x08,  0x90,  0x10,  0x90,  0x10,  0x90,  0x37,  0x9E,  0x50,  0x90,  0x10,  0x90,  0x13, 	/* 255D0 */
+	0x90,  0x1C,  0x9F,  0x11,  0x10,  0x11,  0x10,  0x12,  0x10,  0x14,  0x10,  0xB5,  0x04,  0x20,  0x04,  0x20, 	/* 255E0 */
+	0x07,  0xFE,  0x08,  0x20,  0x0B,  0xFE,  0x10,  0x20,  0x10,  0x20,  0x37,  0xFF,  0x50,  0xA0,  0x11,  0x24, 	/* 255F0 */
+	0x13,  0x14,  0x15,  0x18,  0x11,  0x08,  0x11,  0x04,  0x11,  0xC2,  0x16,  0x01,  0xB6,  0x09,  0x00,  0x09, 	/* 25600 */
+	0x3E,  0x09,  0x02,  0x19,  0xE2,  0x11,  0x12,  0x31,  0x12,  0x3F,  0xF4,  0x51,  0x14,  0x11,  0x14,  0x15, 	/* 25610 */
+	0x88,  0x15,  0x48,  0x15,  0x4C,  0x19,  0x14,  0x11,  0x22,  0x13,  0x42,  0x10,  0x81,  0xB8,  0x04,  0x20, 	/* 25620 */
+	0x04,  0x20,  0x07,  0xFE,  0x08,  0x20,  0x09,  0xFE,  0x10,  0x50,  0x17,  0xFF,  0x30,  0x88,  0x51,  0x24, 	/* 25630 */
+	0x16,  0x23,  0x11,  0xFC,  0x10,  0x20,  0x17,  0xFF,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0xBA,  0x04, 	/* 25640 */
+	0x40,  0x04,  0x40,  0x07,  0xFF,  0x08,  0xA0,  0x08,  0xD0,  0x11,  0x48,  0x13,  0xFC,  0x36,  0x4A,  0x5A, 	/* 25650 */
+	0x49,  0x13,  0xF8,  0x12,  0x48,  0x12,  0x48,  0x13,  0xF8,  0x10,  0x42,  0x10,  0x42,  0x10,  0x3E,  0xBE, 	/* 25660 */
+	0x04,  0x20,  0x04,  0x40,  0x07,  0xFC,  0x0A,  0x24,  0x0A,  0x24,  0x13,  0xFC,  0x12,  0x24,  0x32,  0x24, 	/* 25670 */
+	0x53,  0xFC,  0x10,  0x90,  0x11,  0x10,  0x17,  0xFF,  0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x10, 	/* 25680 */
+	0x85,  0x04,  0x20,  0x04,  0x20,  0x07,  0xFF,  0x09,  0x08,  0x09,  0x08,  0x11,  0x8C,  0x12,  0x52,  0x34, 	/* 25690 */
+	0x20,  0x50,  0x20,  0x17,  0xFF,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10, 	/* 256A0 */
+	0x20,  0x86,  0x08,  0x00,  0x0F,  0xFF,  0x08,  0x20,  0x08,  0x20,  0x13,  0xFE,  0x12,  0x22,  0x32,  0x22, 	/* 256B0 */
+	0x33,  0xFE,  0x52,  0x66,  0x12,  0xAA,  0x12,  0xAA,  0x13,  0x76,  0x12,  0x22,  0x12,  0x22,  0x12,  0x22, 	/* 256C0 */
+	0x12,  0x26,  0x89,  0x00,  0x80,  0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x07,  0xF0,  0x18,  0x0C,  0x67, 	/* 256D0 */
+	0xF3,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x07,  0xF0,  0x08,  0x00,  0x0F,  0xF8,  0x14,  0x08,  0x27, 	/* 256E0 */
+	0xF8,  0x00,  0x00,  0x8B,  0x04,  0x00,  0x07,  0xFE,  0x06,  0x22,  0x0A,  0x22,  0x0A,  0x22,  0x13,  0xFE, 	/* 256F0 */
+	0x12,  0x22,  0x32,  0x22,  0x52,  0xFA,  0x12,  0x8A,  0x12,  0x8A,  0x12,  0xFA,  0x12,  0x02,  0x12,  0x02, 	/* 25700 */
+	0x13,  0xFE,  0x10,  0x00,  0x8D,  0x04,  0x20,  0x04,  0x20,  0x07,  0xFE,  0x09,  0x04,  0x08,  0x84,  0x10, 	/* 25710 */
+	0x88,  0x10,  0x88,  0x37,  0xFF,  0x50,  0x00,  0x10,  0x00,  0x11,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x11, 	/* 25720 */
+	0x04,  0x11,  0xFC,  0x10,  0x00,  0x8F,  0x04,  0x20,  0x04,  0x3C,  0x04,  0x44,  0x08,  0x88,  0x09,  0x50, 	/* 25730 */
+	0x14,  0x30,  0x14,  0xCC,  0x37,  0x03,  0x54,  0x28,  0x14,  0x24,  0x14,  0x24,  0x17,  0xFF,  0x14,  0x30, 	/* 25740 */
+	0x10,  0x48,  0x11,  0x84,  0x16,  0x03,  0x91,  0x08,  0x00,  0x0B,  0xDE,  0x0A,  0x52,  0x0B,  0xDE,  0x12, 	/* 25750 */
+	0x52,  0x12,  0x52,  0x33,  0xDE,  0x32,  0x02,  0x52,  0x02,  0x12,  0x02,  0x12,  0x02,  0x12,  0x02,  0x12, 	/* 25760 */
+	0x02,  0x12,  0x02,  0x12,  0x02,  0x12,  0x06,  0x92,  0x08,  0x02,  0x0F,  0xFA,  0x09,  0x0A,  0x11,  0x4A, 	/* 25770 */
+	0x11,  0x2A,  0x12,  0x6A,  0x33,  0x9A,  0x3C,  0x9A,  0x50,  0x8A,  0x17,  0xEA,  0x10,  0x8A,  0x10,  0x8A, 	/* 25780 */
+	0x10,  0xB2,  0x11,  0xC2,  0x16,  0x02,  0x10,  0x06,  0x94,  0x04,  0x00,  0x07,  0xFE,  0x06,  0x02,  0x0A, 	/* 25790 */
+	0x02,  0x0B,  0xFE,  0x12,  0x10,  0x12,  0x92,  0x32,  0x92,  0x52,  0x92,  0x12,  0xFE,  0x12,  0x10,  0x12, 	/* 257A0 */
+	0x92,  0x14,  0x92,  0x14,  0x92,  0x18,  0xFE,  0x10,  0x00,  0x96,  0x04,  0x20,  0x04,  0x20,  0x05,  0xFE, 	/* 257B0 */
+	0x08,  0x20,  0x08,  0x20,  0x17,  0xFF,  0x11,  0x08,  0x30,  0x88,  0x50,  0x90,  0x17,  0xFE,  0x10,  0x20, 	/* 257C0 */
+	0x10,  0x20,  0x13,  0xFE,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x99,  0x08,  0x00,  0x09,  0xF8,  0x08, 	/* 257D0 */
+	0x08,  0x14,  0x08,  0x17,  0xFF,  0x14,  0x80,  0x34,  0x80,  0x35,  0xFE,  0x55,  0x20,  0x16,  0x20,  0x17, 	/* 257E0 */
+	0xFF,  0x14,  0x30,  0x14,  0x50,  0x14,  0x88,  0x11,  0x04,  0x12,  0x03,  0x9A,  0x04,  0x20,  0x04,  0x20, 	/* 257F0 */
+	0x07,  0xFE,  0x08,  0x50,  0x08,  0x88,  0x13,  0x04,  0x10,  0x00,  0x37,  0xFF,  0x50,  0x04,  0x13,  0xE4, 	/* 25800 */
+	0x12,  0x24,  0x12,  0x24,  0x13,  0xE4,  0x10,  0x04,  0x10,  0x04,  0x10,  0x0C,  0x9F,  0x04,  0x88,  0x04, 	/* 25810 */
+	0x88,  0x04,  0x88,  0x0B,  0xFE,  0x08,  0x88,  0x10,  0x88,  0x17,  0xFF,  0x30,  0x00,  0x51,  0xFC,  0x11, 	/* 25820 */
+	0x04,  0x11,  0x04,  0x11,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x10,  0x00,  0xA1,  0x04,  0x00, 	/* 25830 */
+	0x05,  0xFC,  0x05,  0x04,  0x09,  0x04,  0x09,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x31,  0xFC,  0x50,  0x00, 	/* 25840 */
+	0x13,  0xFE,  0x12,  0x02,  0x13,  0xFE,  0x12,  0x02,  0x12,  0x02,  0x13,  0xFE,  0x10,  0x00,  0xA3,  0x05, 	/* 25850 */
+	0x10,  0x05,  0x10,  0x05,  0x10,  0x0F,  0xFF,  0x0A,  0x12,  0x12,  0x12,  0x13,  0xE2,  0x32,  0x74,  0x52, 	/* 25860 */
+	0x54,  0x12,  0x54,  0x12,  0x48,  0x14,  0x58,  0x14,  0x54,  0x18,  0x64,  0x10,  0x42,  0x11,  0x81,  0xA4, 	/* 25870 */
+	0x04,  0x10,  0x04,  0x10,  0x07,  0xFF,  0x08,  0x10,  0x0A,  0xFC,  0x12,  0x84,  0x12,  0x84,  0x32,  0xFC, 	/* 25880 */
+	0x52,  0x84,  0x12,  0xFC,  0x12,  0x84,  0x12,  0x84,  0x12,  0xFC,  0x12,  0x00,  0x13,  0xFF,  0x10,  0x00, 	/* 25890 */
+	0xA5,  0x04,  0x20,  0x04,  0x20,  0x07,  0xFF,  0x0A,  0x51,  0x0A,  0x51,  0x12,  0x50,  0x10,  0x92,  0x31, 	/* 258A0 */
+	0x0E,  0x52,  0x00,  0x11,  0xFC,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x17,  0xFF,  0x10, 	/* 258B0 */
+	0x00,  0xA6,  0x05,  0x24,  0x04,  0xA4,  0x04,  0xA8,  0x0F,  0xFE,  0x08,  0x50,  0x10,  0x50,  0x17,  0xFF, 	/* 258C0 */
+	0x30,  0x88,  0x51,  0x04,  0x12,  0xF2,  0x14,  0x11,  0x10,  0x10,  0x11,  0xF0,  0x11,  0x04,  0x11,  0x04, 	/* 258D0 */
+	0x10,  0xFC,  0xA8,  0x04,  0x00,  0x05,  0xFE,  0x05,  0x02,  0x09,  0x02,  0x09,  0xFE,  0x11,  0x10,  0x11, 	/* 258E0 */
+	0x10,  0x31,  0xFF,  0x51,  0x10,  0x11,  0x10,  0x12,  0xFE,  0x12,  0x82,  0x14,  0x82,  0x18,  0x82,  0x10, 	/* 258F0 */
+	0xFE,  0x10,  0x00,  0xA9,  0x04,  0x20,  0x04,  0x20,  0x07,  0xFE,  0x08,  0x20,  0x09,  0xFC,  0x10,  0x20, 	/* 25900 */
+	0x17,  0xFF,  0x30,  0x00,  0x51,  0xFC,  0x11,  0x24,  0x11,  0x24,  0x11,  0xFC,  0x11,  0x04,  0x11,  0x04, 	/* 25910 */
+	0x11,  0x04,  0x11,  0x0C,  0xAA,  0x04,  0x20,  0x04,  0x40,  0x07,  0x9C,  0x0A,  0x04,  0x0A,  0x04,  0x13, 	/* 25920 */
+	0xBC,  0x12,  0x04,  0x32,  0x04,  0x53,  0xFC,  0x10,  0x50,  0x10,  0x50,  0x10,  0x90,  0x10,  0x91,  0x11, 	/* 25930 */
+	0x11,  0x12,  0x11,  0x14,  0x0F,  0xAB,  0x04,  0x20,  0x04,  0x60,  0x04,  0x50,  0x08,  0x88,  0x09,  0x04, 	/* 25940 */
+	0x16,  0xFB,  0x10,  0x00,  0x30,  0x00,  0x53,  0xFE,  0x12,  0x52,  0x12,  0x52,  0x13,  0xFE,  0x12,  0x52, 	/* 25950 */
+	0x12,  0x52,  0x12,  0x52,  0x12,  0x56,  0xAC,  0x04,  0x20,  0x04,  0x20,  0x04,  0x3F,  0x08,  0x20,  0x09, 	/* 25960 */
+	0xFC,  0x11,  0x04,  0x11,  0x04,  0x31,  0xFC,  0x51,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x10,  0x20,  0x17, 	/* 25970 */
+	0xFF,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0xAD,  0x04,  0x08,  0x04,  0x30,  0x05,  0xE0,  0x08,  0x20, 	/* 25980 */
+	0x0F,  0xFF,  0x10,  0x70,  0x11,  0xAC,  0x36,  0x23,  0x50,  0x60,  0x17,  0xFF,  0x10,  0x48,  0x10,  0x88, 	/* 25990 */
+	0x11,  0xD0,  0x10,  0x70,  0x11,  0x88,  0x16,  0x04,  0xB6,  0x04,  0x00,  0x05,  0xFC,  0x05,  0x04,  0x09, 	/* 259A0 */
+	0x04,  0x09,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x31,  0xFC,  0x51,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x10, 	/* 259B0 */
+	0x00,  0x17,  0xFF,  0x10,  0x98,  0x11,  0x04,  0x16,  0x02,  0xB9,  0x04,  0x20,  0x04,  0x20,  0x04,  0x50, 	/* 259C0 */
+	0x08,  0x88,  0x09,  0x04,  0x1B,  0xFE,  0x1C,  0x21,  0x29,  0xFC,  0x49,  0x24,  0x09,  0x24,  0x09,  0xFC, 	/* 259D0 */
+	0x08,  0x30,  0x08,  0x50,  0x08,  0x88,  0x09,  0x04,  0x0E,  0x03,  0x83,  0x08,  0x00,  0x0B,  0xFF,  0x0A, 	/* 259E0 */
+	0x00,  0x12,  0x7E,  0x12,  0x42,  0x32,  0x7E,  0x32,  0x42,  0x52,  0x7E,  0x12,  0x10,  0x13,  0xFF,  0x12, 	/* 259F0 */
+	0x24,  0x12,  0x78,  0x12,  0x14,  0x12,  0x62,  0x13,  0xFF,  0x12,  0x00,  0x87,  0x04,  0x00,  0x07,  0xDE, 	/* 25A00 */
+	0x06,  0x42,  0x0A,  0x42,  0x0A,  0x42,  0x13,  0xDE,  0x12,  0x00,  0x32,  0x7E,  0x53,  0xA4,  0x12,  0x24, 	/* 25A10 */
+	0x12,  0x14,  0x13,  0x98,  0x12,  0x08,  0x12,  0x14,  0x12,  0x22,  0x12,  0xC1,  0x88,  0x04,  0x00,  0x05, 	/* 25A20 */
+	0xFC,  0x05,  0x04,  0x09,  0xFC,  0x09,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x30,  0x80,  0x51,  0xFE,  0x12, 	/* 25A30 */
+	0x22,  0x1D,  0x32,  0x11,  0x52,  0x11,  0x82,  0x11,  0xFA,  0x10,  0x02,  0x10,  0x1C,  0x89,  0x04,  0x20, 	/* 25A40 */
+	0x05,  0xFC,  0x04,  0x44,  0x08,  0x44,  0x0F,  0xFF,  0x10,  0x00,  0x11,  0xFC,  0x31,  0x04,  0x51,  0xFC, 	/* 25A50 */
+	0x10,  0x10,  0x11,  0xFE,  0x11,  0x10,  0x11,  0x10,  0x17,  0xFF,  0x10,  0x10,  0x10,  0x10,  0x8F,  0x04, 	/* 25A60 */
+	0x00,  0x07,  0xFE,  0x04,  0x00,  0x0B,  0xFC,  0x0A,  0x04,  0x12,  0x04,  0x13,  0xFC,  0x32,  0x00,  0x53, 	/* 25A70 */
+	0xFE,  0x12,  0x52,  0x16,  0x52,  0x17,  0xFE,  0x1A,  0x52,  0x12,  0x52,  0x12,  0x52,  0x12,  0x06,  0x90, 	/* 25A80 */
+	0x04,  0x20,  0x07,  0xFF,  0x04,  0x48,  0x08,  0x30,  0x08,  0xCC,  0x13,  0xFF,  0x12,  0x08,  0x32,  0x10, 	/* 25A90 */
+	0x52,  0x62,  0x13,  0x84,  0x12,  0x08,  0x12,  0x31,  0x14,  0xC2,  0x14,  0x0C,  0x18,  0x30,  0x11,  0xC0, 	/* 25AA0 */
+	0x95,  0x05,  0x10,  0x05,  0x32,  0x05,  0xDC,  0x09,  0x10,  0x09,  0x10,  0x11,  0x31,  0x11,  0xCF,  0x32, 	/* 25AB0 */
+	0x20,  0x50,  0x40,  0x11,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x10, 	/* 25AC0 */
+	0x00,  0x96,  0x04,  0x40,  0x04,  0x44,  0x07,  0xFC,  0x08,  0x48,  0x08,  0x48,  0x10,  0x50,  0x17,  0xFF, 	/* 25AD0 */
+	0x30,  0x48,  0x50,  0x84,  0x10,  0xFC,  0x11,  0x84,  0x12,  0xFC,  0x14,  0x84,  0x10,  0x84,  0x10,  0xFC, 	/* 25AE0 */
+	0x10,  0x00,  0x9A,  0x09,  0x10,  0x09,  0x10,  0x09,  0x10,  0x0F,  0xDF,  0x11,  0x24,  0x11,  0x24,  0x31, 	/* 25AF0 */
+	0x44,  0x31,  0x14,  0x57,  0xD4,  0x14,  0x54,  0x14,  0x48,  0x14,  0x48,  0x17,  0xD4,  0x10,  0x24,  0x10, 	/* 25B00 */
+	0x42,  0x11,  0x81,  0x9C,  0x04,  0x20,  0x04,  0x20,  0x07,  0xFF,  0x08,  0x00,  0x09,  0xFC,  0x11,  0x04, 	/* 25B10 */
+	0x11,  0xFC,  0x30,  0x00,  0x17,  0xFF,  0x14,  0x01,  0x15,  0xFD,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20, 	/* 25B20 */
+	0x10,  0x20,  0x10,  0x60,  0xA5,  0x08,  0x08,  0x0F,  0xBE,  0x08,  0x8A,  0x09,  0x0A,  0x11,  0x7F,  0x12, 	/* 25B30 */
+	0x0A,  0x37,  0x8A,  0x30,  0xBE,  0x52,  0x88,  0x12,  0xBE,  0x12,  0x88,  0x11,  0x7F,  0x11,  0x08,  0x12, 	/* 25B40 */
+	0x88,  0x14,  0x60,  0x18,  0x1F,  0xAC,  0x04,  0x80,  0x04,  0x80,  0x04,  0xFE,  0x09,  0x2A,  0x09,  0x2A, 	/* 25B50 */
+	0x12,  0xEA,  0x14,  0x5A,  0x30,  0x96,  0x51,  0x22,  0x10,  0x0C,  0x12,  0xA0,  0x12,  0x92,  0x12,  0x91, 	/* 25B60 */
+	0x14,  0x85,  0x18,  0x45,  0x10,  0x3C,  0xB2,  0x04,  0x00,  0x05,  0xFE,  0x05,  0x22,  0x09,  0x22,  0x09, 	/* 25B70 */
+	0xFE,  0x11,  0x22,  0x11,  0x22,  0x31,  0x22,  0x51,  0xFE,  0x10,  0x20,  0x10,  0x90,  0x12,  0x92,  0x12, 	/* 25B80 */
+	0x81,  0x12,  0x85,  0x14,  0x84,  0x10,  0x7C,  0xB4,  0x08,  0x02,  0x0F,  0xD2,  0x0C,  0x52,  0x14,  0x52, 	/* 25B90 */
+	0x17,  0xD2,  0x34,  0x52,  0x34,  0x52,  0x54,  0x52,  0x17,  0xD2,  0x14,  0x52,  0x14,  0x52,  0x17,  0xD2, 	/* 25BA0 */
+	0x12,  0x82,  0x12,  0x42,  0x14,  0x42,  0x18,  0x06,  0xB5,  0x04,  0x20,  0x04,  0x20,  0x04,  0x3F,  0x08, 	/* 25BB0 */
+	0x20,  0x09,  0xFC,  0x19,  0x04,  0x19,  0x04,  0x29,  0xFC,  0x49,  0x04,  0x09,  0xFC,  0x09,  0x04,  0x09, 	/* 25BC0 */
+	0x04,  0x09,  0xFC,  0x08,  0x98,  0x09,  0x04,  0x0E,  0x02,  0xB6,  0x04,  0x00,  0x07,  0xFC,  0x06,  0x24, 	/* 25BD0 */
+	0x0A,  0x24,  0x0B,  0xFC,  0x12,  0x24,  0x12,  0x24,  0x33,  0xFC,  0x50,  0x20,  0x17,  0xFE,  0x14,  0x32, 	/* 25BE0 */
+	0x14,  0x2A,  0x14,  0x36,  0x15,  0xC6,  0x14,  0x02,  0x14,  0x06,  0xB8,  0x04,  0xE0,  0x04,  0x20,  0x04, 	/* 25BF0 */
+	0x50,  0x08,  0x88,  0x0B,  0x04,  0x1D,  0xFB,  0x10,  0x00,  0x33,  0xD2,  0x52,  0x52,  0x13,  0x52,  0x12, 	/* 25C00 */
+	0xE4,  0x13,  0x64,  0x12,  0xE4,  0x12,  0x52,  0x12,  0x52,  0x12,  0xD2,  0xBD,  0x0A,  0x20,  0x09,  0x20, 	/* 25C10 */
+	0x09,  0x20,  0x0B,  0xF8,  0x10,  0x48,  0x10,  0x48,  0x10,  0xFC,  0x30,  0x84,  0x51,  0x04,  0x11,  0xFE, 	/* 25C20 */
+	0x12,  0x12,  0x15,  0x4A,  0x1A,  0xAA,  0x12,  0xA2,  0x14,  0x02,  0x10,  0x0C,  0x80,  0x04,  0x20,  0x04, 	/* 25C30 */
+	0x40,  0x07,  0xFC,  0x0A,  0x44,  0x0A,  0x44,  0x13,  0xFC,  0x12,  0x44,  0x32,  0x44,  0x53,  0xFC,  0x10, 	/* 25C40 */
+	0xA4,  0x10,  0xA4,  0x11,  0x2A,  0x11,  0x3E,  0x12,  0x21,  0x14,  0x11,  0x18,  0x0F,  0x85,  0x04,  0x24, 	/* 25C50 */
+	0x04,  0x22,  0x07,  0xFF,  0x08,  0x20,  0x0B,  0xFC,  0x12,  0x24,  0x13,  0xFC,  0x32,  0x24,  0x53,  0xFC, 	/* 25C60 */
+	0x12,  0x24,  0x10,  0x08,  0x17,  0xFF,  0x11,  0x08,  0x10,  0x88,  0x10,  0x88,  0x10,  0x18,  0x8D,  0x04, 	/* 25C70 */
+	0x20,  0x04,  0x20,  0x07,  0xFE,  0x08,  0x88,  0x08,  0x50,  0x13,  0xFE,  0x12,  0x02,  0x32,  0x22,  0x50, 	/* 25C80 */
+	0x20,  0x13,  0xFE,  0x10,  0x40,  0x10,  0x7C,  0x10,  0x44,  0x10,  0x84,  0x11,  0x04,  0x16,  0x18,  0x91, 	/* 25C90 */
+	0x05,  0x04,  0x05,  0xC4,  0x05,  0x7F,  0x0B,  0x54,  0x0A,  0xD4,  0x14,  0x94,  0x10,  0xBF,  0x31,  0x04, 	/* 25CA0 */
+	0x52,  0x24,  0x10,  0x20,  0x17,  0xFF,  0x10,  0x68,  0x10,  0xA4,  0x11,  0x22,  0x12,  0x21,  0x10,  0x20, 	/* 25CB0 */
+	0x98,  0x00,  0x80,  0x00,  0x80,  0x01,  0x40,  0x06,  0x30,  0x18,  0x8C,  0x68,  0x8B,  0x08,  0x88,  0x14, 	/* 25CC0 */
+	0x94,  0x2A,  0xAA,  0x08,  0x88,  0x14,  0x94,  0x22,  0xA2,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 25CD0 */
+	0x80,  0x99,  0x04,  0x88,  0x04,  0x88,  0x07,  0xFE,  0x08,  0x88,  0x08,  0x88,  0x13,  0xFF,  0x12,  0x00, 	/* 25CE0 */
+	0x32,  0xFE,  0x52,  0x92,  0x12,  0xFE,  0x12,  0x92,  0x12,  0x92,  0x14,  0xFE,  0x14,  0x92,  0x18,  0x92, 	/* 25CF0 */
+	0x10,  0x86,  0x9A,  0x09,  0x10,  0x09,  0x10,  0x09,  0x10,  0x1F,  0xDF,  0x10,  0x14,  0x12,  0xA4,  0x32, 	/* 25D00 */
+	0xA4,  0x34,  0x54,  0x5A,  0xB4,  0x12,  0x94,  0x11,  0x08,  0x11,  0x88,  0x12,  0x4C,  0x12,  0x14,  0x14, 	/* 25D10 */
+	0x22,  0x18,  0xC1,  0xAC,  0x04,  0x20,  0x05,  0x22,  0x05,  0x22,  0x09,  0xFE,  0x08,  0x88,  0x10,  0x90, 	/* 25D20 */
+	0x11,  0xFE,  0x31,  0x10,  0x53,  0x10,  0x15,  0xFE,  0x11,  0x10,  0x11,  0xFE,  0x11,  0x10,  0x11,  0x10, 	/* 25D30 */
+	0x11,  0xFF,  0x10,  0x00,  0xAD,  0x04,  0x20,  0x07,  0xFF,  0x06,  0x10,  0x0A,  0xFE,  0x0A,  0x12,  0x13, 	/* 25D40 */
+	0xFF,  0x12,  0x12,  0x32,  0xFE,  0x52,  0x10,  0x12,  0xFE,  0x12,  0x92,  0x14,  0xFE,  0x14,  0x92,  0x18, 	/* 25D50 */
+	0xFE,  0x10,  0x92,  0x10,  0x96,  0xB2,  0x09,  0x10,  0x09,  0x10,  0x0F,  0xD0,  0x09,  0x1F,  0x11,  0x14, 	/* 25D60 */
+	0x17,  0xE4,  0x31,  0x44,  0x31,  0x14,  0x5F,  0xF4,  0x11,  0x14,  0x11,  0xD8,  0x11,  0x48,  0x12,  0x54, 	/* 25D70 */
+	0x12,  0x54,  0x14,  0x62,  0x11,  0x81,  0xB3,  0x04,  0x20,  0x04,  0x20,  0x07,  0xFF,  0x08,  0x20,  0x0B, 	/* 25D80 */
+	0xFC,  0x12,  0x24,  0x13,  0xFC,  0x32,  0x24,  0x53,  0xFC,  0x10,  0x2E,  0x17,  0xF9,  0x10,  0x08,  0x17, 	/* 25D90 */
+	0xFE,  0x11,  0x08,  0x10,  0x88,  0x10,  0x18,  0xB4,  0x04,  0x00,  0x07,  0xFE,  0x06,  0x00,  0x0A,  0x78, 	/* 25DA0 */
+	0x0A,  0x48,  0x12,  0x48,  0x12,  0x78,  0x32,  0x00,  0x52,  0xEE,  0x12,  0xAA,  0x12,  0xAA,  0x12,  0xAA, 	/* 25DB0 */
+	0x12,  0xEE,  0x12,  0x00,  0x13,  0xFF,  0x10,  0x00,  0xB5,  0x04,  0x20,  0x07,  0xFE,  0x04,  0x20,  0x09, 	/* 25DC0 */
+	0xFC,  0x08,  0x20,  0x1F,  0xFF,  0x10,  0x00,  0x31,  0xFC,  0x51,  0x04,  0x11,  0xFC,  0x11,  0x04,  0x11, 	/* 25DD0 */
+	0xFC,  0x11,  0x04,  0x11,  0xFC,  0x10,  0x8C,  0x17,  0x03,  0xB7,  0x04,  0x80,  0x04,  0xFE,  0x05,  0x00, 	/* 25DE0 */
+	0x09,  0xF8,  0x0A,  0x88,  0x14,  0xF8,  0x10,  0x88,  0x30,  0xF8,  0x50,  0x00,  0x17,  0xFF,  0x10,  0x80, 	/* 25DF0 */
+	0x11,  0xFE,  0x16,  0x4A,  0x11,  0x92,  0x16,  0x22,  0x10,  0xCC,  0xBE,  0x08,  0x00,  0x09,  0xFF,  0x08, 	/* 25E00 */
+	0x10,  0x14,  0x20,  0x14,  0x7E,  0x15,  0x42,  0x36,  0x42,  0x54,  0x7E,  0x14,  0x42,  0x14,  0x7E,  0x15, 	/* 25E10 */
+	0x42,  0x15,  0x42,  0x13,  0x7E,  0x10,  0x14,  0x10,  0x22,  0x10,  0xC1,  0x82,  0x04,  0x20,  0x05,  0xFE, 	/* 25E20 */
+	0x05,  0x22,  0x0F,  0xFF,  0x09,  0x22,  0x11,  0xFE,  0x10,  0x20,  0x31,  0xFE,  0x51,  0x22,  0x11,  0xFE, 	/* 25E30 */
+	0x10,  0x20,  0x17,  0xFF,  0x10,  0x44,  0x10,  0xF8,  0x10,  0x34,  0x11,  0xC2,  0x85,  0x04,  0x88,  0x04, 	/* 25E40 */
+	0x88,  0x07,  0xFF,  0x08,  0x88,  0x0B,  0xFE,  0x12,  0x22,  0x12,  0x22,  0x33,  0xFE,  0x50,  0x20,  0x11, 	/* 25E50 */
+	0xFC,  0x10,  0x20,  0x11,  0xFC,  0x10,  0x20,  0x10,  0x20,  0x17,  0xFF,  0x10,  0x00,  0x89,  0x00,  0x80, 	/* 25E60 */
+	0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x04,  0x10,  0x1B,  0xEC,  0x60,  0x03,  0x1F,  0x7C,  0x11,  0x44, 	/* 25E70 */
+	0x11,  0x44,  0x1F,  0x7C,  0x04,  0x10,  0x06,  0x18,  0x09,  0x24,  0x11,  0x42,  0x60,  0x80,  0x8A,  0x08, 	/* 25E80 */
+	0x00,  0x0F,  0xFF,  0x08,  0x90,  0x0B,  0xFC,  0x12,  0x94,  0x12,  0x94,  0x33,  0xFC,  0x30,  0x80,  0x57, 	/* 25E90 */
+	0xFF,  0x11,  0x08,  0x13,  0xF4,  0x15,  0x13,  0x19,  0xF0,  0x11,  0x04,  0x11,  0x04,  0x10,  0xFC,  0x8D, 	/* 25EA0 */
+	0x08,  0xC8,  0x0F,  0x08,  0x09,  0x08,  0x0F,  0xE8,  0x11,  0x1E,  0x17,  0xEA,  0x35,  0x2A,  0x37,  0xEA, 	/* 25EB0 */
+	0x55,  0x2A,  0x17,  0xEA,  0x11,  0x0A,  0x17,  0xCA,  0x11,  0x32,  0x11,  0xD2,  0x1E,  0x22,  0x10,  0x4C, 	/* 25EC0 */
+	0x8F,  0x04,  0x40,  0x04,  0x78,  0x04,  0x88,  0x0B,  0x10,  0x0D,  0xFE,  0x11,  0x22,  0x11,  0x22,  0x31, 	/* 25ED0 */
+	0xFE,  0x50,  0xC4,  0x17,  0x24,  0x10,  0xD8,  0x17,  0x38,  0x10,  0x54,  0x11,  0x92,  0x16,  0x11,  0x10, 	/* 25EE0 */
+	0x60,  0x91,  0x04,  0x0C,  0x05,  0xF0,  0x04,  0x40,  0x0F,  0xFF,  0x08,  0x88,  0x11,  0xFC,  0x16,  0x8B, 	/* 25EF0 */
+	0x30,  0xF8,  0x50,  0x00,  0x13,  0xFE,  0x12,  0x02,  0x12,  0xFA,  0x12,  0x8A,  0x12,  0xFA,  0x12,  0x02, 	/* 25F00 */
+	0x12,  0x06,  0x95,  0x04,  0x50,  0x06,  0x52,  0x05,  0x54,  0x08,  0x50,  0x0F,  0xFF,  0x11,  0x08,  0x10, 	/* 25F10 */
+	0x90,  0x37,  0xFE,  0x50,  0x20,  0x13,  0xFC,  0x10,  0x20,  0x17,  0xFF,  0x10,  0x50,  0x10,  0x88,  0x13, 	/* 25F20 */
+	0x04,  0x1C,  0x03,  0x96,  0x04,  0x20,  0x07,  0xFF,  0x04,  0x20,  0x0B,  0xFC,  0x08,  0x00,  0x13,  0xFC, 	/* 25F30 */
+	0x12,  0x04,  0x33,  0xFC,  0x51,  0x08,  0x10,  0x90,  0x1F,  0xFF,  0x10,  0x00,  0x13,  0xFC,  0x12,  0x04, 	/* 25F40 */
+	0x13,  0xFC,  0x10,  0x00,  0x9A,  0x04,  0x20,  0x04,  0x20,  0x07,  0xFF,  0x08,  0x50,  0x0A,  0x8A,  0x11, 	/* 25F50 */
+	0x04,  0x13,  0xFE,  0x35,  0x05,  0x51,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x10,  0x28,  0x11,  0x24,  0x12, 	/* 25F60 */
+	0x22,  0x14,  0x22,  0x10,  0x60,  0x9E,  0x08,  0x18,  0x0B,  0xE0,  0x09,  0x48,  0x0A,  0x44,  0x17,  0xF4, 	/* 25F70 */
+	0x12,  0x10,  0x32,  0x10,  0x33,  0xFC,  0x52,  0x04,  0x12,  0x04,  0x13,  0xFF,  0x14,  0x25,  0x14,  0x95, 	/* 25F80 */
+	0x1A,  0x51,  0x11,  0x42,  0x11,  0x0C,  0xA3,  0x09,  0x08,  0x09,  0x08,  0x0F,  0xDE,  0x09,  0x08,  0x17, 	/* 25F90 */
+	0xFF,  0x11,  0x08,  0x32,  0x8C,  0x32,  0x52,  0x54,  0x21,  0x19,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x11, 	/* 25FA0 */
+	0x04,  0x11,  0x04,  0x11,  0xFC,  0x10,  0x00,  0xA5,  0x04,  0x20,  0x05,  0xFC,  0x04,  0x20,  0x0B,  0xFE, 	/* 25FB0 */
+	0x08,  0x00,  0x11,  0x04,  0x17,  0xDF,  0x31,  0x04,  0x51,  0xC4,  0x16,  0x1F,  0x10,  0x00,  0x17,  0xFF, 	/* 25FC0 */
+	0x10,  0x50,  0x10,  0x91,  0x13,  0x11,  0x1C,  0x0F,  0xA7,  0x05,  0x04,  0x04,  0x88,  0x07,  0xFE,  0x0A, 	/* 25FD0 */
+	0x22,  0x0B,  0xFE,  0x12,  0x22,  0x12,  0x22,  0x33,  0xFE,  0x50,  0x00,  0x11,  0xFC,  0x11,  0x04,  0x11, 	/* 25FE0 */
+	0xFC,  0x11,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x10,  0x00,  0xAD,  0x08,  0x84,  0x0F,  0xDE,  0x0A,  0x94, 	/* 25FF0 */
+	0x0A,  0x94,  0x17,  0xFF,  0x11,  0xAC,  0x32,  0xCD,  0x32,  0x97,  0x54,  0x20,  0x11,  0xFC,  0x11,  0x04, 	/* 26000 */
+	0x11,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x10,  0x00,  0xAE,  0x04,  0x20,  0x04,  0x20,  0x07, 	/* 26010 */
+	0xFE,  0x08,  0x88,  0x0F,  0xFF,  0x10,  0x00,  0x11,  0xFC,  0x31,  0x24,  0x51,  0xFC,  0x11,  0x24,  0x11, 	/* 26020 */
+	0xFC,  0x10,  0x20,  0x13,  0xFE,  0x10,  0x20,  0x17,  0xFF,  0x10,  0x00,  0xB5,  0x04,  0x00,  0x07,  0xFF, 	/* 26030 */
+	0x04,  0x00,  0x09,  0xFC,  0x09,  0x24,  0x11,  0xFC,  0x11,  0x24,  0x37,  0xFF,  0x50,  0x00,  0x11,  0xFC, 	/* 26040 */
+	0x11,  0x24,  0x11,  0xFC,  0x11,  0x24,  0x11,  0xFC,  0x17,  0xFF,  0x10,  0x00,  0xB9,  0x04,  0x00,  0x07, 	/* 26050 */
+	0xFF,  0x04,  0x90,  0x0B,  0xFE,  0x0A,  0x92,  0x13,  0xFE,  0x10,  0x00,  0x31,  0xFC,  0x51,  0x04,  0x11, 	/* 26060 */
+	0xFC,  0x11,  0x04,  0x11,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x10,  0x8C,  0x13,  0x02,  0xBB,  0x08,  0x08, 	/* 26070 */
+	0x0B,  0xC8,  0x0A,  0x7F,  0x12,  0x42,  0x12,  0x62,  0x13,  0xD4,  0x32,  0x14,  0x32,  0x7F,  0x52,  0x08, 	/* 26080 */
+	0x17,  0xC8,  0x16,  0x7F,  0x1A,  0x48,  0x12,  0x48,  0x13,  0xC8,  0x12,  0x48,  0x12,  0x08,  0x80,  0x09, 	/* 26090 */
+	0x08,  0x08,  0x90,  0x1B,  0xFE,  0x10,  0x20,  0x11,  0xF8,  0x30,  0x20,  0x37,  0xFF,  0x50,  0x58,  0x13, 	/* 260A0 */
+	0x94,  0x11,  0x10,  0x17,  0xFF,  0x11,  0x12,  0x11,  0xCC,  0x17,  0x0A,  0x11,  0x16,  0x13,  0x62,  0x81, 	/* 260B0 */
+	0x04,  0x88,  0x04,  0x90,  0x05,  0xFF,  0x09,  0x10,  0x0B,  0xFE,  0x15,  0x10,  0x11,  0xFE,  0x31,  0x10, 	/* 260C0 */
+	0x51,  0xFF,  0x10,  0x00,  0x13,  0xDE,  0x12,  0x52,  0x12,  0x52,  0x12,  0x72,  0x12,  0x02,  0x12,  0x06, 	/* 260D0 */
+	0x82,  0x04,  0x50,  0x05,  0xFC,  0x05,  0x54,  0x09,  0xFC,  0x09,  0x54,  0x11,  0xFC,  0x10,  0x00,  0x33, 	/* 260E0 */
+	0xFF,  0x52,  0x00,  0x12,  0xFC,  0x12,  0x00,  0x13,  0xFF,  0x12,  0xA4,  0x14,  0x98,  0x18,  0xEC,  0x13, 	/* 260F0 */
+	0x03,  0x84,  0x04,  0x20,  0x04,  0x20,  0x07,  0xFE,  0x09,  0x04,  0x08,  0x88,  0x17,  0xFF,  0x10,  0x00, 	/* 26100 */
+	0x31,  0xFC,  0x51,  0x04,  0x11,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x12,  0xA2,  0x12,  0x91,  0x14,  0x85, 	/* 26110 */
+	0x10,  0x7C,  0x89,  0x04,  0x20,  0x04,  0x20,  0x04,  0x50,  0x08,  0x88,  0x09,  0x04,  0x16,  0xFB,  0x10, 	/* 26120 */
+	0x00,  0x33,  0xDE,  0x52,  0x52,  0x12,  0x52,  0x13,  0xDE,  0x11,  0x08,  0x11,  0x08,  0x11,  0x8C,  0x12, 	/* 26130 */
+	0x52,  0x14,  0x21,  0x92,  0x04,  0x00,  0x07,  0xFE,  0x04,  0x20,  0x0F,  0xFF,  0x0C,  0x21,  0x15,  0xAD, 	/* 26140 */
+	0x14,  0x21,  0x31,  0xAC,  0x50,  0x00,  0x17,  0xFE,  0x10,  0x20,  0x13,  0xFE,  0x12,  0x52,  0x12,  0x52, 	/* 26150 */
+	0x12,  0x52,  0x12,  0x06,  0x94,  0x04,  0x20,  0x07,  0xFE,  0x04,  0x20,  0x09,  0xFC,  0x08,  0x00,  0x17, 	/* 26160 */
+	0xFF,  0x10,  0x22,  0x33,  0xF8,  0x50,  0x00,  0x17,  0xFF,  0x10,  0x04,  0x17,  0xFF,  0x14,  0xA4,  0x14, 	/* 26170 */
+	0x94,  0x17,  0x84,  0x10,  0x0C,  0x95,  0x04,  0x20,  0x04,  0x20,  0x07,  0xFF,  0x08,  0x51,  0x0F,  0xAE, 	/* 26180 */
+	0x12,  0xAA,  0x12,  0xAA,  0x35,  0xAD,  0x50,  0x00,  0x11,  0x04,  0x11,  0xFC,  0x11,  0x04,  0x11,  0xFC, 	/* 26190 */
+	0x11,  0x04,  0x12,  0x04,  0x14,  0x04,  0x96,  0x08,  0x08,  0x0F,  0xC8,  0x0D,  0x08,  0x15,  0x1F,  0x17, 	/* 261A0 */
+	0xD0,  0x34,  0x60,  0x37,  0xDF,  0x55,  0x00,  0x17,  0xC0,  0x10,  0x00,  0x13,  0xFE,  0x12,  0x52,  0x12, 	/* 261B0 */
+	0x52,  0x12,  0x52,  0x1F,  0xFF,  0x10,  0x00,  0x98,  0x04,  0x20,  0x05,  0xFC,  0x04,  0x24,  0x0B,  0xFF, 	/* 261C0 */
+	0x08,  0x24,  0x11,  0xFC,  0x10,  0x20,  0x37,  0xFF,  0x52,  0xA4,  0x12,  0x52,  0x14,  0x02,  0x13,  0xFC, 	/* 261D0 */
+	0x12,  0x94,  0x12,  0x94,  0x1F,  0xFF,  0x10,  0x00,  0x9A,  0x04,  0x88,  0x04,  0x88,  0x07,  0xFF,  0x08, 	/* 261E0 */
+	0x88,  0x0B,  0xFE,  0x12,  0x52,  0x13,  0xFE,  0x30,  0x00,  0x57,  0xFF,  0x14,  0x21,  0x14,  0x7D,  0x10, 	/* 261F0 */
+	0xC4,  0x13,  0x28,  0x10,  0x10,  0x10,  0x60,  0x13,  0x80,  0x9F,  0x05,  0x24,  0x04,  0xA8,  0x07,  0xFE, 	/* 26200 */
+	0x0A,  0x02,  0x0A,  0xFA,  0x10,  0x88,  0x10,  0xF8,  0x31,  0xFC,  0x51,  0x04,  0x11,  0xFC,  0x11,  0x04, 	/* 26210 */
+	0x11,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x10,  0xCC,  0x13,  0x02,  0xA1,  0x04,  0x00,  0x05,  0xFC,  0x05, 	/* 26220 */
+	0x24,  0x09,  0xFC,  0x09,  0x24,  0x11,  0x24,  0x11,  0xFC,  0x30,  0x00,  0x57,  0xDF,  0x15,  0x55,  0x15, 	/* 26230 */
+	0x55,  0x17,  0xDF,  0x15,  0x55,  0x15,  0x55,  0x17,  0xDF,  0x10,  0x00,  0xAA,  0x04,  0x00,  0x07,  0xFF, 	/* 26240 */
+	0x04,  0x20,  0x09,  0xFC,  0x09,  0x04,  0x11,  0xFC,  0x11,  0x04,  0x37,  0xFF,  0x54,  0xA5,  0x12,  0x92, 	/* 26250 */
+	0x12,  0x7D,  0x14,  0x89,  0x13,  0x50,  0x10,  0x30,  0x10,  0xCC,  0x17,  0x03,  0xB2,  0x08,  0x08,  0x0B, 	/* 26260 */
+	0x88,  0x08,  0x3E,  0x1F,  0xCA,  0x10,  0x0C,  0x17,  0x8C,  0x30,  0x7F,  0x30,  0x10,  0x57,  0xBE,  0x10, 	/* 26270 */
+	0x62,  0x17,  0xA2,  0x14,  0xBE,  0x14,  0xA2,  0x14,  0xA2,  0x17,  0xBE,  0x10,  0x00,  0xB7,  0x0B,  0xDF, 	/* 26280 */
+	0x08,  0x00,  0x0F,  0xDF,  0x0C,  0x51,  0x15,  0x55,  0x10,  0x20,  0x33,  0xFF,  0x32,  0x50,  0x53,  0xFE, 	/* 26290 */
+	0x12,  0x52,  0x13,  0xFE,  0x13,  0x10,  0x15,  0xFE,  0x15,  0x10,  0x19,  0xD1,  0x13,  0x0F,  0xBA,  0x0A, 	/* 262A0 */
+	0x8A,  0x0F,  0xEA,  0x0A,  0x94,  0x0B,  0x9F,  0x11,  0x34,  0x17,  0xD4,  0x35,  0x54,  0x37,  0xDF,  0x51, 	/* 262B0 */
+	0x14,  0x17,  0xD4,  0x11,  0x1F,  0x17,  0xD4,  0x12,  0x94,  0x12,  0x54,  0x14,  0x5F,  0x18,  0x00,  0xBB, 	/* 262C0 */
+	0x05,  0x24,  0x04,  0xA8,  0x07,  0xFE,  0x0A,  0x8A,  0x0A,  0xFA,  0x10,  0x00,  0x11,  0xFC,  0x31,  0x2C, 	/* 262D0 */
+	0x51,  0xB4,  0x11,  0xFC,  0x10,  0x20,  0x13,  0xFE,  0x10,  0x20,  0x17,  0xFF,  0x12,  0x92,  0x14,  0x49, 	/* 262E0 */
+	0xBC,  0x08,  0x00,  0x0B,  0xDE,  0x0A,  0x52,  0x0B,  0xDE,  0x10,  0x00,  0x17,  0xFF,  0x34,  0x08,  0x37, 	/* 262F0 */
+	0xE8,  0x54,  0x8F,  0x17,  0xF2,  0x15,  0x4A,  0x15,  0xCA,  0x15,  0xC4,  0x15,  0x6C,  0x1B,  0xD2,  0x10, 	/* 26300 */
+	0x61,  0xBF,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20, 	/* 26310 */
+	0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x04,  0x21,  0x04,  0x21,  0x08,  0x11,  0x10,  0x0F, 	/* 26320 */
+	0x60,  0x00,  0x80,  0x00,  0x00,  0x7F,  0xFF,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02, 	/* 26330 */
+	0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x04,  0x20,  0x04,  0x21,  0x08,  0x11,  0x10, 	/* 26340 */
+	0x0F,  0x60,  0x00,  0x81,  0x01,  0x00,  0x01,  0x00,  0x01,  0x40,  0x02,  0x20,  0x02,  0x18,  0x04,  0xF4, 	/* 26350 */
+	0x7F,  0x42,  0x02,  0x40,  0x02,  0x40,  0x02,  0x40,  0x04,  0x40,  0x04,  0x40,  0x08,  0x40,  0x08,  0x42, 	/* 26360 */
+	0x10,  0x22,  0x20,  0x1E,  0x83,  0x00,  0x00,  0x0F,  0xF8,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 26370 */
+	0x00,  0x7F,  0xFF,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x04,  0x20,  0x04,  0x20,  0x08, 	/* 26380 */
+	0x21,  0x10,  0x11,  0x20,  0x0F,  0x84,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08, 	/* 26390 */
+	0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x02,  0x40,  0x02,  0x40,  0x02,  0x40,  0x04,  0x40,  0x04,  0x42, 	/* 263A0 */
+	0x08,  0x42,  0x10,  0x22,  0x20,  0x1E,  0x85,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x00,  0x01, 	/* 263B0 */
+	0x20,  0x02,  0x18,  0x04,  0x74,  0x1F,  0xA2,  0x01,  0x20,  0x01,  0x20,  0x01,  0x20,  0x02,  0x20,  0x02, 	/* 263C0 */
+	0x22,  0x04,  0x22,  0x08,  0x22,  0x30,  0x1E,  0x86,  0x02,  0x40,  0x02,  0x40,  0x02,  0x44,  0x22,  0x44, 	/* 263D0 */
+	0x12,  0x48,  0x0A,  0x50,  0x02,  0x40,  0x02,  0x40,  0x06,  0x70,  0x1A,  0x4C,  0x62,  0x42,  0x04,  0x40, 	/* 263E0 */
+	0x04,  0x40,  0x08,  0x41,  0x10,  0x21,  0x60,  0x1F,  0x87,  0x00,  0x20,  0x10,  0x28,  0x16,  0x48,  0x11, 	/* 263F0 */
+	0x48,  0x10,  0x88,  0x11,  0x48,  0x12,  0x28,  0x1C,  0x28,  0x10,  0x08,  0x1F,  0xF8,  0x02,  0x40,  0x02, 	/* 26400 */
+	0x40,  0x04,  0x40,  0x08,  0x42,  0x10,  0x22,  0x60,  0x1E,  0x88,  0x00,  0x80,  0x04,  0x80,  0x04,  0x80, 	/* 26410 */
+	0x07,  0xFC,  0x08,  0x80,  0x08,  0x80,  0x10,  0x80,  0x7F,  0xFF,  0x01,  0x20,  0x01,  0x20,  0x01,  0x20, 	/* 26420 */
+	0x02,  0x20,  0x02,  0x20,  0x04,  0x21,  0x08,  0x11,  0x30,  0x0F,  0x89,  0x00,  0x80,  0x00,  0x80,  0x08, 	/* 26430 */
+	0x88,  0x04,  0x88,  0x04,  0x90,  0x04,  0xA0,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x20,  0x01,  0x20,  0x01, 	/* 26440 */
+	0x20,  0x02,  0x20,  0x02,  0x20,  0x04,  0x21,  0x08,  0x11,  0x30,  0x0F,  0x8B,  0x01,  0x00,  0x01,  0x00, 	/* 26450 */
+	0x7F,  0xFE,  0x01,  0x00,  0x01,  0x00,  0x1F,  0xF0,  0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x1F,  0xF0, 	/* 26460 */
+	0x02,  0x40,  0x02,  0x40,  0x02,  0x40,  0x04,  0x42,  0x18,  0x22,  0x60,  0x1E,  0x8C,  0x01,  0xE0,  0x04, 	/* 26470 */
+	0x20,  0x04,  0x20,  0x08,  0x10,  0x0F,  0xF0,  0x18,  0x18,  0x28,  0x14,  0x48,  0x13,  0x08,  0x10,  0x0F, 	/* 26480 */
+	0xF0,  0x02,  0x40,  0x02,  0x40,  0x02,  0x40,  0x04,  0x41,  0x18,  0x21,  0x60,  0x1F,  0x8D,  0x01,  0x00, 	/* 26490 */
+	0x01,  0xE0,  0x02,  0x20,  0x04,  0x40,  0x08,  0x80,  0x3F,  0xFC,  0x08,  0x84,  0x08,  0x84,  0x08,  0x84, 	/* 264A0 */
+	0x0F,  0xFC,  0x01,  0x20,  0x01,  0x20,  0x02,  0x20,  0x04,  0x21,  0x18,  0x11,  0x60,  0x0F,  0x8E,  0x00, 	/* 264B0 */
+	0x08,  0x00,  0x30,  0x3F,  0xC0,  0x01,  0x00,  0x01,  0x00,  0x1F,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x11, 	/* 264C0 */
+	0x08,  0x1F,  0xF8,  0x02,  0x50,  0x02,  0x48,  0x02,  0x48,  0x04,  0x42,  0x18,  0x42,  0x60,  0x3E,  0x90, 	/* 264D0 */
+	0x10,  0x00,  0x11,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x11,  0x04,  0x11,  0x04, 	/* 264E0 */
+	0x11,  0x04,  0x11,  0xFC,  0x12,  0x40,  0x02,  0x40,  0x02,  0x40,  0x04,  0x41,  0x18,  0x41,  0x60,  0x3F, 	/* 264F0 */
+	0x92,  0x01,  0x00,  0x02,  0x00,  0x1C,  0xFC,  0x10,  0x04,  0x10,  0x04,  0x1E,  0x7C,  0x10,  0x04,  0x10, 	/* 26500 */
+	0x04,  0x10,  0x04,  0x1F,  0xFC,  0x02,  0x40,  0x02,  0x40,  0x02,  0x41,  0x04,  0x41,  0x18,  0x21,  0x60, 	/* 26510 */
+	0x1F,  0x94,  0x01,  0x00,  0x01,  0xE0,  0x02,  0x20,  0x04,  0x40,  0x18,  0x80,  0x7F,  0xF8,  0x10,  0x88, 	/* 26520 */
+	0x10,  0x88,  0x11,  0x08,  0x1F,  0xF8,  0x01,  0x50,  0x02,  0x48,  0x02,  0x48,  0x04,  0x41,  0x18,  0x21, 	/* 26530 */
+	0x60,  0x1F,  0x9A,  0x00,  0x80,  0x08,  0x88,  0x04,  0x88,  0x04,  0x90,  0x7F,  0xFE,  0x40,  0x02,  0x4F, 	/* 26540 */
+	0xF2,  0x48,  0x12,  0x08,  0x10,  0x0F,  0xF0,  0x02,  0x40,  0x02,  0x40,  0x02,  0x42,  0x04,  0x42,  0x18, 	/* 26550 */
+	0x22,  0x60,  0x1E,  0x9C,  0x04,  0x80,  0x09,  0x00,  0x33,  0xDC,  0x22,  0x44,  0x22,  0x44,  0x23,  0xC4, 	/* 26560 */
+	0x22,  0x44,  0x22,  0x44,  0x3B,  0xDC,  0x00,  0x00,  0x02,  0x40,  0x02,  0x40,  0x02,  0x42,  0x04,  0x42, 	/* 26570 */
+	0x18,  0x42,  0x60,  0x3E,  0xA2,  0x08,  0x10,  0x08,  0x10,  0x7F,  0xFF,  0x08,  0x10,  0x08,  0x10,  0x3E, 	/* 26580 */
+	0x7C,  0x22,  0x44,  0x22,  0x44,  0x22,  0x44,  0x3E,  0x7C,  0x14,  0x28,  0x14,  0x28,  0x15,  0x48,  0x26, 	/* 26590 */
+	0x49,  0x2C,  0x89,  0x41,  0x07,  0xA5,  0x03,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80, 	/* 265A0 */
+	0x00,  0x80,  0x00,  0x80,  0x01,  0x40,  0x01,  0x40,  0x02,  0x20,  0x02,  0x20,  0x04,  0x10,  0x08,  0x08, 	/* 265B0 */
+	0x10,  0x04,  0x20,  0x02,  0x40,  0x01,  0xA8,  0x00,  0x80,  0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x04, 	/* 265C0 */
+	0x10,  0x18,  0x0C,  0x6F,  0xFB,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xF8,  0x00,  0x80,  0x00, 	/* 265D0 */
+	0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0xA9,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80, 	/* 265E0 */
+	0x3F,  0xFE,  0x20,  0x82,  0x20,  0x82,  0x2C,  0xB2,  0x24,  0x92,  0x24,  0x92,  0x2A,  0xAA,  0x2A,  0xAA, 	/* 265F0 */
+	0x31,  0xC6,  0x20,  0x82,  0x20,  0x82,  0x20,  0x86,  0xAA,  0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x04, 	/* 26600 */
+	0x10,  0x18,  0x0C,  0x67,  0xF3,  0x00,  0x00,  0x3E,  0x22,  0x22,  0x22,  0x2A,  0x44,  0x26,  0x88,  0x23, 	/* 26610 */
+	0x10,  0x2A,  0x88,  0x26,  0x44,  0x22,  0x22,  0x26,  0x22,  0xAB,  0x00,  0x00,  0x03,  0xE0,  0x00,  0x20, 	/* 26620 */
+	0x00,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10, 	/* 26630 */
+	0x08,  0x08,  0x08,  0x08,  0x10,  0x04,  0x20,  0x02,  0x40,  0x01,  0xAC,  0x01,  0xE0,  0x04,  0x20,  0x04, 	/* 26640 */
+	0x20,  0x04,  0x10,  0x08,  0x10,  0x08,  0x08,  0x11,  0x04,  0x21,  0x02,  0x41,  0x01,  0x01,  0x40,  0x02, 	/* 26650 */
+	0x20,  0x02,  0x10,  0x04,  0x08,  0x05,  0xF8,  0x3E,  0x04,  0x00,  0x04,  0xAD,  0x00,  0x80,  0x00,  0x80, 	/* 26660 */
+	0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x04,  0x20,  0x04,  0x10, 	/* 26670 */
+	0x04,  0x08,  0x08,  0x08,  0x08,  0x04,  0x10,  0x04,  0x20,  0x04,  0x00,  0x00,  0xAE,  0x00,  0xE0,  0x02, 	/* 26680 */
+	0x20,  0x02,  0x10,  0x04,  0x10,  0x0F,  0xF8,  0x11,  0x04,  0x21,  0x02,  0x42,  0x01,  0x07,  0xF8,  0x04, 	/* 26690 */
+	0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x10,  0x00,  0x10,  0x00,  0x60,  0xB1,  0x04,  0x20, 	/* 266A0 */
+	0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x3F,  0xFC,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20, 	/* 266B0 */
+	0x7F,  0xFF,  0x00,  0x00,  0x04,  0x20,  0x04,  0x10,  0x08,  0x08,  0x10,  0x04,  0x20,  0x04,  0xB5,  0x00, 	/* 266C0 */
+	0x10,  0x00,  0xE0,  0x07,  0x00,  0x04,  0x00,  0x07,  0xFE,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04, 	/* 266D0 */
+	0x10,  0x04,  0x10,  0x7F,  0xFF,  0x00,  0x00,  0x02,  0x20,  0x04,  0x18,  0x08,  0x04,  0x30,  0x02,  0xB6, 	/* 266E0 */
+	0x04,  0x10,  0x04,  0x10,  0x3F,  0xFE,  0x04,  0x10,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x04,  0x10, 	/* 266F0 */
+	0x07,  0xF0,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x00,  0x00,  0x02,  0x30,  0x0C,  0x0C,  0x30,  0x02, 	/* 26700 */
+	0xB7,  0x00,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10,  0x0F, 	/* 26710 */
+	0xF0,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x00,  0x00,  0x7F,  0xFF,  0x04,  0x60,  0x18,  0x18,  0x60, 	/* 26720 */
+	0x04,  0xB8,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x1F,  0xFC,  0x12,  0x24,  0x12,  0x24,  0x12,  0x24, 	/* 26730 */
+	0x1F,  0xFC,  0x12,  0x24,  0x12,  0x24,  0x12,  0x24,  0x7F,  0xFF,  0x00,  0x00,  0x06,  0x30,  0x18,  0x0C, 	/* 26740 */
+	0x60,  0x02,  0xBC,  0x08,  0x10,  0x04,  0x20,  0x7F,  0xFE,  0x02,  0x40,  0x1F,  0xF8,  0x02,  0x48,  0x02, 	/* 26750 */
+	0x48,  0x7F,  0xFE,  0x02,  0x48,  0x1F,  0xF8,  0x02,  0x40,  0x06,  0x60,  0x0A,  0x50,  0x12,  0x48,  0x62, 	/* 26760 */
+	0x46,  0x02,  0x40,  0x80,  0x02,  0x22,  0x7E,  0x24,  0x02,  0x39,  0x0E,  0x21,  0x72,  0x1F,  0x0F,  0xF8, 	/* 26770 */
+	0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x02,  0x20,  0x1F,  0xFC,  0x02,  0x20,  0x7F,  0xFF, 	/* 26780 */
+	0x06,  0x38,  0x78,  0x06,  0x82,  0x00,  0x00,  0x3F,  0xFE,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20, 	/* 26790 */
+	0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20, 	/* 267A0 */
+	0x02,  0x20,  0x02,  0x20,  0x06,  0x85,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x20,  0x82, 	/* 267B0 */
+	0x20,  0x82,  0x21,  0x42,  0x21,  0x42,  0x22,  0x22,  0x24,  0x12,  0x28,  0x0A,  0x20,  0x02,  0x20,  0x02, 	/* 267C0 */
+	0x20,  0x02,  0x20,  0x02,  0x20,  0x06,  0x86,  0x00,  0x00,  0x3F,  0xFC,  0x21,  0x04,  0x21,  0x04,  0x21, 	/* 267D0 */
+	0x04,  0x21,  0x04,  0x21,  0x04,  0x3F,  0xFC,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20, 	/* 267E0 */
+	0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x0C,  0x89,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC, 	/* 267F0 */
+	0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x7F,  0xFF,  0x10,  0x04, 	/* 26800 */
+	0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x0C,  0x8A,  0x00,  0x00,  0x1F,  0xFC,  0x12,  0x24,  0x12, 	/* 26810 */
+	0x24,  0x12,  0x24,  0x12,  0x24,  0x12,  0x24,  0x7F,  0xFF,  0x12,  0x24,  0x12,  0x24,  0x12,  0x24,  0x12, 	/* 26820 */
+	0x24,  0x12,  0x24,  0x12,  0x24,  0x12,  0x24,  0x12,  0x2C,  0x8C,  0x00,  0x00,  0x1E,  0x3C,  0x12,  0x24, 	/* 26830 */
+	0x12,  0x24,  0x12,  0x24,  0x12,  0x24,  0x12,  0x24,  0x7F,  0xFF,  0x12,  0x24,  0x12,  0x24,  0x12,  0x24, 	/* 26840 */
+	0x12,  0x24,  0x12,  0x44,  0x12,  0x44,  0x26,  0x84,  0x41,  0x0C,  0x8D,  0x00,  0x00,  0x3F,  0xFE,  0x00, 	/* 26850 */
+	0x80,  0x00,  0x80,  0x0F,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x08, 	/* 26860 */
+	0x88,  0x7F,  0xFF,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x18,  0x8F,  0x00,  0x00,  0x3F,  0xFE, 	/* 26870 */
+	0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x26,  0x24,  0x1E,  0x28,  0x02,  0x33,  0xE2,  0x22,  0x22, 	/* 26880 */
+	0x22,  0x22,  0x22,  0x22,  0x23,  0xE2,  0x20,  0x02,  0x20,  0x02,  0x20,  0x06,  0x90,  0x00,  0x00,  0x3F, 	/* 26890 */
+	0xFE,  0x20,  0x02,  0x2F,  0xFA,  0x20,  0x02,  0x2F,  0xFA,  0x00,  0x00,  0x00,  0x00,  0x0F,  0xF8,  0x08, 	/* 268A0 */
+	0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x08,  0x18,  0x91,  0x00,  0x80, 	/* 268B0 */
+	0x00,  0x80,  0x3F,  0xFE,  0x20,  0x82,  0x3F,  0xFE,  0x20,  0x82,  0x3F,  0xFE,  0x00,  0x00,  0x1F,  0xFC, 	/* 268C0 */
+	0x10,  0x04,  0x17,  0xF4,  0x10,  0x04,  0x17,  0xF4,  0x10,  0x04,  0x10,  0x04,  0x10,  0x0C,  0x92,  0x00, 	/* 268D0 */
+	0x00,  0x3F,  0xFC,  0x20,  0x04,  0x3F,  0xFC,  0x20,  0x04,  0x3F,  0xFC,  0x00,  0x00,  0x0F,  0xF0,  0x08, 	/* 268E0 */
+	0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x00,  0x00,  0x93, 	/* 268F0 */
+	0x02,  0x20,  0x02,  0x20,  0x3F,  0xFE,  0x02,  0x20,  0x1F,  0xFC,  0x02,  0x20,  0x7F,  0xFF,  0x00,  0x80, 	/* 26900 */
+	0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88,  0x7F,  0xFF,  0x08,  0x08,  0x08,  0x08,  0x08,  0x18, 	/* 26910 */
+	0x95,  0x00,  0x00,  0x3F,  0xFC,  0x20,  0x04,  0x2F,  0xF4,  0x20,  0x04,  0x2F,  0xF4,  0x22,  0x04,  0x07, 	/* 26920 */
+	0xC0,  0x18,  0x80,  0x7F,  0xF0,  0x11,  0x10,  0x11,  0x10,  0x1F,  0xF2,  0x02,  0x42,  0x0C,  0x42,  0x70, 	/* 26930 */
+	0x3E,  0x96,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x7F,  0xFE, 	/* 26940 */
+	0x40,  0x02,  0x40,  0x02,  0x40,  0x02,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 26950 */
+	0x00,  0x00,  0x97,  0x00,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x40,  0x02,  0x43,  0xE2,  0x02,  0x20,  0x02, 	/* 26960 */
+	0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x04,  0x20,  0x04,  0x20,  0x08,  0x20,  0x08,  0x22,  0x10, 	/* 26970 */
+	0x22,  0x20,  0x1E,  0x99,  0x00,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x44,  0x02,  0x47,  0xF2,  0x04,  0x00, 	/* 26980 */
+	0x04,  0x00,  0x07,  0xE0,  0x00,  0x20,  0x00,  0x20,  0x7F,  0xFE,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20, 	/* 26990 */
+	0x00,  0x40,  0x03,  0x80,  0xA0,  0x00,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x40,  0x02,  0x3F,  0x08,  0x00, 	/* 269A0 */
+	0x08,  0x00,  0xFE,  0x7F,  0x08,  0x12,  0x88,  0x12,  0x48,  0x12,  0x48,  0x12,  0x08,  0x12,  0x08,  0x22, 	/* 269B0 */
+	0x1A,  0x21,  0x02,  0x40,  0xFE,  0xA2,  0x00,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x40,  0x02,  0x1F,  0xF8, 	/* 269C0 */
+	0x02,  0x00,  0x0D,  0x08,  0x71,  0x48,  0x12,  0xD0,  0x0C,  0xA0,  0x79,  0xA0,  0x06,  0x90,  0x0C,  0x8C, 	/* 269D0 */
+	0x70,  0x83,  0x00,  0x80,  0x03,  0x00,  0xA4,  0x00,  0x00,  0x7F,  0xFE,  0x41,  0x02,  0x43,  0xE2,  0x04, 	/* 269E0 */
+	0x40,  0x18,  0x80,  0x7F,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x1F,  0xF8,  0x02,  0x40,  0x02,  0x50,  0x04, 	/* 269F0 */
+	0x48,  0x08,  0x42,  0x10,  0x22,  0x60,  0x1E,  0xA5,  0x00,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x4F,  0xF2, 	/* 26A00 */
+	0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x01,  0x00,  0x7F,  0xFE, 	/* 26A10 */
+	0x00,  0x00,  0x04,  0x60,  0x18,  0x18,  0x60,  0x04,  0xA6,  0x00,  0x00,  0x7F,  0xFE,  0x40,  0x22,  0x40, 	/* 26A20 */
+	0x22,  0x3E,  0x3C,  0x00,  0x20,  0x00,  0xF8,  0x7F,  0x08,  0x14,  0x48,  0x14,  0x50,  0x14,  0x30,  0x14, 	/* 26A30 */
+	0x48,  0x15,  0x86,  0x24,  0x02,  0x22,  0x02,  0x41,  0xFE,  0xA8,  0x00,  0x00,  0x7F,  0xFE,  0x40,  0x02, 	/* 26A40 */
+	0x5F,  0xFA,  0x00,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x00,  0x00,  0x1F,  0xF8,  0x11,  0x08, 	/* 26A50 */
+	0x1F,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x1F,  0xF8,  0x00,  0x00,  0xA9,  0x00,  0x00,  0x7F,  0xFE,  0x41, 	/* 26A60 */
+	0x02,  0x42,  0x02,  0x0C,  0xF0,  0x08,  0x10,  0x0F,  0x70,  0x08,  0x10,  0x0F,  0xF0,  0x04,  0x00,  0x0F, 	/* 26A70 */
+	0xFC,  0x10,  0x24,  0x64,  0x94,  0x12,  0x54,  0x12,  0x44,  0x20,  0x18,  0xAA,  0x00,  0x00,  0x7F,  0xFE, 	/* 26A80 */
+	0x44,  0x22,  0x3F,  0xFC,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x02,  0x00,  0x7F,  0xFE, 	/* 26A90 */
+	0x09,  0x10,  0x1F,  0xF8,  0x29,  0x14,  0x49,  0x12,  0x09,  0x60,  0x01,  0x00,  0xAB,  0x00,  0x00,  0x02, 	/* 26AA0 */
+	0x00,  0x01,  0x00,  0x00,  0x80,  0x00,  0x80,  0x00,  0x00,  0x00,  0x00,  0x00,  0x20,  0x00,  0x20,  0x00, 	/* 26AB0 */
+	0x40,  0x00,  0x80,  0x00,  0x80,  0x01,  0x00,  0x02,  0x00,  0x04,  0x00,  0x00,  0x00,  0xAC,  0x01,  0x00, 	/* 26AC0 */
+	0x01,  0x00,  0x01,  0xF8,  0x02,  0x08,  0x06,  0x10,  0x19,  0xA0,  0x00,  0x40,  0x00,  0xA0,  0x03,  0x10, 	/* 26AD0 */
+	0x0D,  0x8C,  0x70,  0x43,  0x00,  0x20,  0x06,  0x00,  0x01,  0x80,  0x00,  0x60,  0x00,  0x10,  0xB0,  0x00, 	/* 26AE0 */
+	0x40,  0x20,  0x40,  0x10,  0x42,  0x10,  0x42,  0x00,  0x64,  0x0F,  0x64,  0x01,  0x68,  0x01,  0x50,  0x09, 	/* 26AF0 */
+	0x50,  0x12,  0x48,  0x12,  0x48,  0x24,  0x44,  0x24,  0x42,  0x48,  0x41,  0x50,  0x40,  0x00,  0xC0,  0xB1, 	/* 26B00 */
+	0x00,  0x00,  0x27,  0xFE,  0x10,  0x80,  0x10,  0x80,  0x00,  0x80,  0x00,  0xF8,  0x00,  0x88,  0x09,  0x08, 	/* 26B10 */
+	0x09,  0x08,  0x11,  0x08,  0x13,  0xF0,  0x22,  0x10,  0x20,  0x10,  0x40,  0x10,  0x4F,  0xFF,  0x00,  0x00, 	/* 26B20 */
+	0xB2,  0x00,  0x20,  0x20,  0x20,  0x10,  0x20,  0x10,  0x20,  0x03,  0xFE,  0x02,  0x22,  0x02,  0x22,  0x0A, 	/* 26B30 */
+	0x22,  0x0A,  0x22,  0x13,  0xFE,  0x10,  0x20,  0x20,  0x20,  0x20,  0x20,  0x40,  0x20,  0x40,  0x20,  0x00, 	/* 26B40 */
+	0x20,  0xB3,  0x00,  0x40,  0x20,  0x40,  0x10,  0x40,  0x13,  0xFC,  0x00,  0x44,  0x00,  0x44,  0x00,  0x44, 	/* 26B50 */
+	0x08,  0x44,  0x0F,  0xFF,  0x10,  0x60,  0x10,  0x50,  0x20,  0x90,  0x20,  0x88,  0x41,  0x04,  0x42,  0x02, 	/* 26B60 */
+	0x0C,  0x01,  0xB4,  0x00,  0x00,  0x23,  0xFE,  0x10,  0x88,  0x08,  0x88,  0x08,  0x88,  0x00,  0x88,  0x00, 	/* 26B70 */
+	0x88,  0x0B,  0xFF,  0x08,  0x28,  0x10,  0x28,  0x10,  0x48,  0x20,  0x88,  0x21,  0x08,  0x42,  0x08,  0x4C, 	/* 26B80 */
+	0x08,  0x00,  0x18,  0xB5,  0x00,  0x00,  0x23,  0xFC,  0x12,  0x04,  0x12,  0x04,  0x02,  0x04,  0x02,  0x04, 	/* 26B90 */
+	0x02,  0x04,  0x0B,  0xFC,  0x08,  0x90,  0x10,  0x90,  0x10,  0x90,  0x20,  0x90,  0x21,  0x11,  0x41,  0x11, 	/* 26BA0 */
+	0x42,  0x11,  0x04,  0x0F,  0xB6,  0x00,  0x40,  0x20,  0x40,  0x10,  0x40,  0x08,  0x90,  0x08,  0x88,  0x01, 	/* 26BB0 */
+	0x04,  0x01,  0x3C,  0x07,  0xC2,  0x08,  0x02,  0x09,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x21,  0x04,  0x21, 	/* 26BC0 */
+	0x04,  0x41,  0xFC,  0x00,  0x00,  0xB7,  0x00,  0x40,  0x20,  0x60,  0x10,  0xA0,  0x10,  0x90,  0x11,  0x08, 	/* 26BD0 */
+	0x01,  0xFC,  0x02,  0x02,  0x04,  0x01,  0x13,  0xFC,  0x10,  0x44,  0x10,  0x44,  0x20,  0x44,  0x20,  0x58, 	/* 26BE0 */
+	0x40,  0x40,  0x40,  0x40,  0x00,  0x40,  0xBD,  0x00,  0x02,  0x2F,  0xF2,  0x12,  0x12,  0x12,  0x12,  0x02, 	/* 26BF0 */
+	0x12,  0x03,  0xD2,  0x02,  0x52,  0x12,  0x52,  0x15,  0x52,  0x14,  0x92,  0x28,  0x92,  0x21,  0x02,  0x41, 	/* 26C00 */
+	0x02,  0x42,  0x02,  0x44,  0x02,  0x18,  0x06,  0x84,  0x00,  0x40,  0x20,  0x40,  0x17,  0xFE,  0x10,  0x40, 	/* 26C10 */
+	0x13,  0xF8,  0x00,  0x48,  0x0F,  0xFF,  0x00,  0x48,  0x0B,  0xF8,  0x10,  0x80,  0x1F,  0xFF,  0x20,  0x88, 	/* 26C20 */
+	0x21,  0x10,  0x43,  0xF0,  0x40,  0xC8,  0x0F,  0x04,  0x85,  0x00,  0x00,  0x27,  0xFE,  0x14,  0x42,  0x14, 	/* 26C30 */
+	0x42,  0x07,  0xFE,  0x04,  0x42,  0x04,  0x42,  0x04,  0xF2,  0x14,  0x92,  0x14,  0x92,  0x14,  0x92,  0x24, 	/* 26C40 */
+	0xF2,  0x24,  0x02,  0x44,  0x02,  0x47,  0xFE,  0x00,  0x00,  0x86,  0x00,  0x88,  0x20,  0x88,  0x11,  0x10, 	/* 26C50 */
+	0x11,  0xFE,  0x03,  0x10,  0x03,  0x10,  0x05,  0x10,  0x01,  0xFE,  0x09,  0x10,  0x11,  0x10,  0x11,  0xFE, 	/* 26C60 */
+	0x21,  0x10,  0x21,  0x10,  0x41,  0x10,  0x41,  0xFF,  0x00,  0x00,  0x89,  0x00,  0x20,  0x20,  0x20,  0x10, 	/* 26C70 */
+	0x20,  0x17,  0xFF,  0x00,  0x00,  0x01,  0xFC,  0x01,  0x04,  0x09,  0x04,  0x09,  0x04,  0x11,  0xFC,  0x10, 	/* 26C80 */
+	0x20,  0x21,  0x28,  0x21,  0x24,  0x42,  0x22,  0x44,  0x22,  0x00,  0x60,  0x8B,  0x00,  0x00,  0x23,  0xFE, 	/* 26C90 */
+	0x12,  0x22,  0x12,  0x22,  0x02,  0xFA,  0x02,  0x22,  0x02,  0x22,  0x0B,  0xFE,  0x0A,  0x02,  0x12,  0xFA, 	/* 26CA0 */
+	0x12,  0x8A,  0x22,  0x8A,  0x22,  0xFA,  0x44,  0x02,  0x44,  0x02,  0x08,  0x06,  0x8C,  0x00,  0x20,  0x20, 	/* 26CB0 */
+	0x20,  0x13,  0xFE,  0x10,  0x20,  0x00,  0x20,  0x07,  0xFF,  0x00,  0x90,  0x08,  0x92,  0x09,  0x4E,  0x12, 	/* 26CC0 */
+	0x78,  0x14,  0x88,  0x21,  0x90,  0x26,  0x50,  0x40,  0x60,  0x41,  0x98,  0x06,  0x07,  0x8D,  0x00,  0x40, 	/* 26CD0 */
+	0x20,  0x40,  0x27,  0xFE,  0x10,  0x40,  0x13,  0xFC,  0x02,  0x44,  0x03,  0xFC,  0x02,  0x44,  0x0A,  0x44, 	/* 26CE0 */
+	0x13,  0xFC,  0x10,  0xE0,  0x21,  0x50,  0x22,  0x48,  0x44,  0x44,  0x48,  0x42,  0x00,  0x40,  0x96,  0x00, 	/* 26CF0 */
+	0x88,  0x20,  0x90,  0x11,  0xFE,  0x11,  0x20,  0x03,  0xFC,  0x05,  0x20,  0x01,  0xFC,  0x09,  0x20,  0x31, 	/* 26D00 */
+	0xFE,  0x40,  0x80,  0x00,  0x80,  0x7F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x9B, 	/* 26D10 */
+	0x00,  0x20,  0x27,  0xFF,  0x12,  0x04,  0x12,  0xF4,  0x02,  0x94,  0x02,  0xF4,  0x02,  0x04,  0x0B,  0xFC, 	/* 26D20 */
+	0x08,  0x00,  0x13,  0xFC,  0x10,  0x00,  0x2F,  0xFF,  0x21,  0x28,  0x41,  0x24,  0x42,  0x22,  0x04,  0x60, 	/* 26D30 */
+	0x9C,  0x00,  0x20,  0x00,  0x20,  0x27,  0xFF,  0x21,  0x74,  0x11,  0x54,  0x11,  0x74,  0x01,  0x04,  0x01, 	/* 26D40 */
+	0xFC,  0x08,  0x0C,  0x11,  0xF0,  0x10,  0x20,  0x27,  0xFF,  0x20,  0x70,  0x41,  0xAC,  0x46,  0x23,  0x00, 	/* 26D50 */
+	0x20,  0x9D,  0x04,  0x00,  0x04,  0xBE,  0x27,  0x02,  0x14,  0x14,  0x14,  0x88,  0x03,  0x84,  0x02,  0x7F, 	/* 26D60 */
+	0x13,  0x8A,  0x15,  0x0C,  0x11,  0x28,  0x2F,  0xEE,  0x21,  0x28,  0x22,  0xA8,  0x42,  0x58,  0x44,  0x4C, 	/* 26D70 */
+	0x08,  0x83,  0xA0,  0x00,  0x00,  0x07,  0xE0,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04, 	/* 26D80 */
+	0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x08,  0x20,  0x08,  0x21,  0x10,  0x21,  0x20, 	/* 26D90 */
+	0x1F,  0x40,  0x00,  0xA1,  0x00,  0x00,  0x07,  0xE0,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x06,  0x20, 	/* 26DA0 */
+	0x05,  0x20,  0x04,  0xA0,  0x04,  0xA0,  0x04,  0x20,  0x04,  0x20,  0x08,  0x20,  0x08,  0x22,  0x10,  0x22, 	/* 26DB0 */
+	0x20,  0x1E,  0x40,  0x00,  0xA6,  0x08,  0x00,  0x08,  0x3C,  0x08,  0x24,  0x0F,  0x24,  0x09,  0x24,  0x11, 	/* 26DC0 */
+	0x24,  0x11,  0x24,  0x2A,  0x24,  0x2A,  0x24,  0x44,  0x44,  0x04,  0x45,  0x0A,  0x85,  0x09,  0x03,  0x10, 	/* 26DD0 */
+	0x80,  0x20,  0x60,  0x40,  0x1F,  0xA7,  0x00,  0x00,  0x1F,  0xF8,  0x10,  0x08,  0x11,  0x08,  0x11,  0x08, 	/* 26DE0 */
+	0x17,  0xE8,  0x15,  0x28,  0x15,  0x28,  0x15,  0x28,  0x15,  0x28,  0x15,  0x28,  0x15,  0x48,  0x15,  0x05, 	/* 26DF0 */
+	0x21,  0x05,  0x21,  0x03,  0x41,  0x01,  0xA9,  0x00,  0x00,  0x1F,  0xF8,  0x10,  0x08,  0x10,  0x88,  0x10, 	/* 26E00 */
+	0x88,  0x17,  0xF8,  0x10,  0x88,  0x10,  0x88,  0x11,  0xC8,  0x11,  0xC8,  0x12,  0xA8,  0x12,  0xA8,  0x14, 	/* 26E10 */
+	0x95,  0x28,  0x85,  0x20,  0x83,  0x40,  0x81,  0xAA,  0x00,  0x00,  0x1F,  0xF8,  0x10,  0x08,  0x10,  0x88, 	/* 26E20 */
+	0x10,  0x88,  0x10,  0x88,  0x14,  0x88,  0x14,  0x88,  0x14,  0xE8,  0x14,  0x88,  0x14,  0x88,  0x14,  0x88, 	/* 26E30 */
+	0x14,  0x85,  0x24,  0x85,  0x3F,  0xFB,  0x40,  0x01,  0xAD,  0x04,  0x08,  0x04,  0x30,  0x09,  0xE0,  0x10, 	/* 26E40 */
+	0x20,  0x37,  0xFF,  0x50,  0x20,  0x10,  0x20,  0x13,  0xFE,  0x10,  0x00,  0x00,  0x00,  0x07,  0xE0,  0x04, 	/* 26E50 */
+	0x20,  0x04,  0x20,  0x08,  0x22,  0x10,  0x22,  0x60,  0x1E,  0xB0,  0x00,  0x00,  0x1F,  0xFC,  0x10,  0x84, 	/* 26E60 */
+	0x11,  0x04,  0x17,  0xF4,  0x14,  0x14,  0x17,  0xF4,  0x14,  0x14,  0x17,  0xF4,  0x10,  0x04,  0x17,  0xF4, 	/* 26E70 */
+	0x10,  0x84,  0x13,  0xE5,  0x20,  0x85,  0x2F,  0xFB,  0x40,  0x01,  0xB1,  0x08,  0x00,  0x29,  0x3C,  0x29, 	/* 26E80 */
+	0x24,  0x3F,  0x24,  0x00,  0x24,  0x7F,  0xA4,  0x00,  0x24,  0x3F,  0x24,  0x21,  0x24,  0x21,  0x24,  0x3F, 	/* 26E90 */
+	0x24,  0x22,  0x24,  0x12,  0x24,  0x15,  0xC5,  0x0E,  0x45,  0x70,  0x83,  0xB5,  0x20,  0x02,  0x20,  0x02, 	/* 26EA0 */
+	0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02, 	/* 26EB0 */
+	0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x3F,  0xFE,  0x00,  0x00,  0xB6,  0x00,  0x00,  0x00, 	/* 26EC0 */
+	0x10,  0x20,  0x12,  0x20,  0x12,  0x26,  0x22,  0x21,  0xA2,  0x20,  0x42,  0x20,  0x62,  0x20,  0x92,  0x21, 	/* 26ED0 */
+	0x12,  0x22,  0x0A,  0x24,  0x0A,  0x28,  0x02,  0x20,  0x02,  0x3F,  0xFE,  0x00,  0x00,  0xB8,  0x00,  0x00, 	/* 26EE0 */
+	0x03,  0xE0,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x3E,  0x3E,  0x20,  0x02, 	/* 26EF0 */
+	0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x3F,  0xFE,  0x00,  0x00,  0x00,  0x00,  0xB9,  0x00, 	/* 26F00 */
+	0x00,  0x3E,  0x3E,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x23, 	/* 26F10 */
+	0xE2,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x3F,  0xFE,  0x00,  0x00,  0x00,  0x00,  0xBA, 	/* 26F20 */
+	0x00,  0x80,  0x00,  0x80,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x00,  0x80, 	/* 26F30 */
+	0x00,  0x80,  0x20,  0x82,  0x20,  0x82,  0x20,  0x82,  0x20,  0x82,  0x20,  0x82,  0x3F,  0xFE,  0x00,  0x00, 	/* 26F40 */
+	0xBD,  0x00,  0x00,  0x7F,  0xFF,  0x02,  0x00,  0x02,  0x00,  0x23,  0x8A,  0x28,  0x8A,  0x24,  0xD2,  0x22, 	/* 26F50 */
+	0xC2,  0x20,  0xA2,  0x21,  0xA2,  0x26,  0x92,  0x38,  0x8A,  0x23,  0x02,  0x20,  0x02,  0x3F,  0xFE,  0x00, 	/* 26F60 */
+	0x00,  0xBE,  0x00,  0x00,  0x0F,  0xF8,  0x00,  0x10,  0x00,  0x60,  0x20,  0x82,  0x2E,  0xFA,  0x2A,  0x8A, 	/* 26F70 */
+	0x2A,  0xAA,  0x2A,  0xAA,  0x2A,  0xB2,  0x2E,  0xD2,  0x28,  0x8A,  0x21,  0x86,  0x20,  0x02,  0x3F,  0xFE, 	/* 26F80 */
+	0x20,  0x02,  0x80,  0x00,  0x00,  0x00,  0x00,  0x3F,  0xFE,  0x00,  0x82,  0x00,  0x82,  0x00,  0x82,  0x00, 	/* 26F90 */
+	0x82,  0x00,  0x82,  0x01,  0x02,  0x01,  0x02,  0x01,  0x02,  0x02,  0x02,  0x04,  0x02,  0x08,  0x04,  0x10, 	/* 26FA0 */
+	0x18,  0x00,  0x00,  0x83,  0x00,  0x00,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x84,  0x00,  0x84,  0x00,  0x84, 	/* 26FB0 */
+	0x0C,  0x84,  0x03,  0x04,  0x01,  0x84,  0x02,  0x44,  0x02,  0x24,  0x04,  0x04,  0x08,  0x04,  0x10,  0x08, 	/* 26FC0 */
+	0x20,  0x30,  0x00,  0x00,  0x84,  0x00,  0x00,  0x7F,  0xFC,  0x00,  0x84,  0x00,  0x84,  0x10,  0x84,  0x08, 	/* 26FD0 */
+	0x84,  0x04,  0x84,  0x03,  0x04,  0x01,  0x04,  0x01,  0x84,  0x02,  0x64,  0x02,  0x1C,  0x04,  0x07,  0x08, 	/* 26FE0 */
+	0x04,  0x10,  0x08,  0x20,  0x70,  0x86,  0x03,  0xE0,  0x00,  0x20,  0x04,  0x20,  0x04,  0x10,  0x08,  0x10, 	/* 26FF0 */
+	0x08,  0x08,  0x10,  0x04,  0x2F,  0xF2,  0x41,  0x11,  0x01,  0x10,  0x01,  0x10,  0x02,  0x10,  0x02,  0x10, 	/* 27000 */
+	0x04,  0x10,  0x08,  0x10,  0x10,  0x60,  0x87,  0x10,  0x00,  0x11,  0xFE,  0x10,  0x22,  0x10,  0x22,  0x13, 	/* 27010 */
+	0x22,  0x1C,  0x22,  0x70,  0x22,  0x10,  0x22,  0x10,  0x22,  0x10,  0x22,  0x12,  0x42,  0x12,  0x42,  0x0E, 	/* 27020 */
+	0x82,  0x01,  0x02,  0x02,  0x04,  0x0C,  0x18,  0x88,  0x01,  0x02,  0x01,  0x22,  0x01,  0x22,  0x01,  0x22, 	/* 27030 */
+	0x21,  0x22,  0x11,  0x22,  0x0A,  0x22,  0x06,  0x22,  0x02,  0x22,  0x05,  0x22,  0x05,  0x22,  0x08,  0x82, 	/* 27040 */
+	0x08,  0x82,  0x10,  0x82,  0x20,  0x02,  0x40,  0x06,  0x8A,  0x00,  0x02,  0x3F,  0xA2,  0x04,  0x22,  0x04, 	/* 27050 */
+	0x22,  0x04,  0x22,  0x04,  0x22,  0x7F,  0xE2,  0x04,  0x22,  0x04,  0x22,  0x04,  0x22,  0x04,  0x22,  0x04, 	/* 27060 */
+	0x02,  0x04,  0x02,  0x04,  0x02,  0x04,  0x02,  0x04,  0x06,  0x8B,  0x00,  0x82,  0x07,  0x22,  0x7C,  0x22, 	/* 27070 */
+	0x04,  0x22,  0x04,  0x22,  0x04,  0x22,  0x7F,  0xA2,  0x04,  0x22,  0x04,  0x22,  0x04,  0x22,  0x04,  0x22, 	/* 27080 */
+	0x08,  0x22,  0x08,  0x02,  0x10,  0x02,  0x20,  0x02,  0x40,  0x06,  0x8E,  0x10,  0x02,  0x10,  0x12,  0x1F, 	/* 27090 */
+	0x92,  0x15,  0x92,  0x25,  0x92,  0x25,  0x92,  0x49,  0x92,  0x0A,  0x92,  0x12,  0x92,  0x12,  0x92,  0x24, 	/* 270A0 */
+	0x92,  0x44,  0x92,  0x08,  0x82,  0x10,  0x82,  0x20,  0x82,  0x03,  0x06,  0x91,  0x00,  0x02,  0x3F,  0xE2, 	/* 270B0 */
+	0x09,  0x22,  0x09,  0x22,  0x09,  0x22,  0x09,  0x22,  0x7F,  0xE2,  0x09,  0x22,  0x09,  0x22,  0x09,  0x22, 	/* 270C0 */
+	0x09,  0x22,  0x09,  0x02,  0x11,  0x02,  0x11,  0x02,  0x21,  0x02,  0x41,  0x06,  0x94,  0x04,  0x02,  0x04, 	/* 270D0 */
+	0x12,  0x04,  0x12,  0x3F,  0x92,  0x04,  0x92,  0x04,  0x92,  0x04,  0x92,  0x04,  0x92,  0x7F,  0xF2,  0x04, 	/* 270E0 */
+	0x12,  0x06,  0x12,  0x09,  0x02,  0x09,  0x02,  0x10,  0x82,  0x20,  0x42,  0x40,  0x06,  0x97,  0x00,  0x02, 	/* 270F0 */
+	0x7F,  0xE2,  0x08,  0x22,  0x08,  0x22,  0x08,  0x22,  0x0F,  0x22,  0x11,  0x22,  0x11,  0x22,  0x29,  0x22, 	/* 27100 */
+	0x46,  0x22,  0x02,  0x22,  0x04,  0x02,  0x04,  0x02,  0x08,  0x02,  0x10,  0x02,  0x20,  0x06,  0x9D,  0x08, 	/* 27110 */
+	0x00,  0x08,  0x00,  0x09,  0xFE,  0x7E,  0x22,  0x02,  0x22,  0x04,  0x22,  0x05,  0x22,  0x09,  0x22,  0x0E, 	/* 27120 */
+	0x22,  0x1A,  0x22,  0x29,  0x22,  0x49,  0x42,  0x08,  0x42,  0x08,  0x82,  0x09,  0x02,  0x0A,  0x0C,  0xA4, 	/* 27130 */
+	0x04,  0x02,  0x04,  0x92,  0x24,  0x92,  0x14,  0x92,  0x15,  0x12,  0x04,  0x12,  0x7F,  0xD2,  0x04,  0x12, 	/* 27140 */
+	0x04,  0x12,  0x04,  0x12,  0x7F,  0xD2,  0x04,  0x12,  0x04,  0x02,  0x04,  0x02,  0x04,  0x02,  0x04,  0x06, 	/* 27150 */
+	0xA5,  0x00,  0x02,  0x3F,  0xA2,  0x20,  0xA2,  0x20,  0xA2,  0x20,  0xA2,  0x3F,  0xA2,  0x08,  0x22,  0x08, 	/* 27160 */
+	0x22,  0x0F,  0xA2,  0x08,  0xA2,  0x08,  0xA2,  0x08,  0x82,  0x10,  0x82,  0x10,  0x82,  0x21,  0x02,  0x46, 	/* 27170 */
+	0x06,  0xA7,  0x04,  0x00,  0x04,  0x7E,  0x04,  0x12,  0x3F,  0x92,  0x04,  0x12,  0x04,  0x12,  0x04,  0x12, 	/* 27180 */
+	0x7F,  0xD2,  0x04,  0x12,  0x04,  0x12,  0x08,  0x12,  0x0A,  0x22,  0x09,  0x22,  0x13,  0x42,  0x7C,  0x82, 	/* 27190 */
+	0x00,  0x8C,  0xA9,  0x00,  0x82,  0x03,  0x22,  0x3C,  0x22,  0x04,  0x22,  0x04,  0x22,  0x04,  0x22,  0x7F, 	/* 271A0 */
+	0xA2,  0x0C,  0x22,  0x0E,  0x22,  0x15,  0x22,  0x14,  0xA2,  0x24,  0xA2,  0x44,  0x02,  0x04,  0x02,  0x04, 	/* 271B0 */
+	0x02,  0x04,  0x06,  0xAA,  0x00,  0x02,  0x3F,  0x92,  0x2A,  0x92,  0x2A,  0x92,  0x2A,  0x92,  0x2A,  0x92, 	/* 271C0 */
+	0x2A,  0x92,  0x7F,  0xD2,  0x2A,  0x92,  0x2A,  0x92,  0x2A,  0x92,  0x2A,  0x82,  0x2A,  0x82,  0x2A,  0x82, 	/* 271D0 */
+	0x2A,  0x82,  0x21,  0x86,  0xAE,  0x00,  0x82,  0x03,  0x12,  0x3C,  0x12,  0x04,  0x12,  0x04,  0x12,  0x04, 	/* 271E0 */
+	0x12,  0x7F,  0xD2,  0x04,  0x12,  0x04,  0x12,  0x04,  0x12,  0x1F,  0x92,  0x10,  0x82,  0x10,  0x82,  0x10, 	/* 271F0 */
+	0x82,  0x1F,  0x82,  0x00,  0x06,  0xB0,  0x00,  0x02,  0x7F,  0xE2,  0x08,  0x22,  0x0A,  0x22,  0x11,  0x22, 	/* 27200 */
+	0x13,  0x22,  0x7C,  0xA2,  0x04,  0xA2,  0x04,  0x22,  0x3F,  0xA2,  0x04,  0x22,  0x04,  0x02,  0x04,  0x02, 	/* 27210 */
+	0x07,  0x82,  0x78,  0x02,  0x00,  0x06,  0xB3,  0x04,  0x02,  0x04,  0x12,  0x7F,  0xD2,  0x0A,  0x12,  0x11, 	/* 27220 */
+	0x12,  0x20,  0x92,  0x5F,  0x52,  0x00,  0x12,  0x7F,  0xD2,  0x08,  0x12,  0x08,  0x12,  0x1F,  0x02,  0x11, 	/* 27230 */
+	0x02,  0x01,  0x02,  0x01,  0x02,  0x06,  0x06,  0xB6,  0x02,  0x02,  0x12,  0x12,  0x12,  0x12,  0x1F,  0xD2, 	/* 27240 */
+	0x22,  0x12,  0x22,  0x12,  0x7F,  0xF2,  0x02,  0x12,  0x1F,  0xD2,  0x12,  0x52,  0x12,  0x52,  0x12,  0x52, 	/* 27250 */
+	0x12,  0x42,  0x13,  0x82,  0x12,  0x02,  0x02,  0x06,  0xB7,  0x00,  0x02,  0x3F,  0x92,  0x20,  0x92,  0x20, 	/* 27260 */
+	0x92,  0x3F,  0x92,  0x24,  0x12,  0x24,  0x12,  0x3F,  0x92,  0x34,  0x92,  0x34,  0x92,  0x54,  0x92,  0x54, 	/* 27270 */
+	0x92,  0x94,  0x82,  0x15,  0x82,  0x14,  0x02,  0x04,  0x06,  0xB8,  0x08,  0x88,  0x04,  0x88,  0x04,  0x90, 	/* 27280 */
+	0x1F,  0xFE,  0x00,  0x80,  0x01,  0x40,  0x7F,  0xFF,  0x02,  0x20,  0x04,  0x10,  0x1F,  0xFC,  0x61,  0x13, 	/* 27290 */
+	0x01,  0x10,  0x02,  0x10,  0x02,  0x10,  0x04,  0x10,  0x18,  0x60,  0xB9,  0x02,  0x02,  0x02,  0x22,  0x34, 	/* 272A0 */
+	0x22,  0x0C,  0x22,  0x0A,  0x22,  0x11,  0x22,  0x25,  0x22,  0x44,  0x22,  0x7F,  0xA2,  0x04,  0x22,  0x0E, 	/* 272B0 */
+	0x22,  0x15,  0x02,  0x24,  0x82,  0x44,  0x02,  0x04,  0x02,  0x04,  0x06,  0xBA,  0x04,  0x02,  0x04,  0x12, 	/* 272C0 */
+	0x7F,  0xD2,  0x04,  0x12,  0x04,  0x12,  0x3F,  0x92,  0x24,  0x92,  0x24,  0x92,  0x25,  0x92,  0x2E,  0x12, 	/* 272D0 */
+	0x0D,  0x12,  0x14,  0x92,  0x14,  0x82,  0x24,  0x02,  0x44,  0x02,  0x04,  0x06,  0xBB,  0x04,  0x02,  0x04, 	/* 272E0 */
+	0x22,  0x7F,  0xE2,  0x04,  0x22,  0x04,  0x22,  0x39,  0x22,  0x0A,  0x22,  0x06,  0x22,  0x04,  0xA2,  0x08, 	/* 272F0 */
+	0xA2,  0x11,  0x22,  0x23,  0x02,  0x04,  0x82,  0x08,  0x42,  0x10,  0x42,  0x60,  0x06,  0x83,  0x11,  0x02, 	/* 27300 */
+	0x0A,  0x12,  0x7F,  0x92,  0x04,  0x92,  0x04,  0x92,  0x3F,  0x92,  0x24,  0x12,  0x24,  0x12,  0x3F,  0xD2, 	/* 27310 */
+	0x04,  0x52,  0x0C,  0x52,  0x0C,  0x42,  0x14,  0x42,  0x25,  0x82,  0x44,  0x02,  0x04,  0x06,  0x84,  0x00, 	/* 27320 */
+	0x02,  0x7F,  0x92,  0x00,  0x12,  0x12,  0x52,  0x12,  0x52,  0x6D,  0x92,  0x24,  0x92,  0x12,  0x52,  0x00, 	/* 27330 */
+	0x12,  0x7F,  0xD2,  0x04,  0x12,  0x04,  0x02,  0x04,  0x02,  0x05,  0x82,  0x1E,  0x02,  0x60,  0x06,  0x87, 	/* 27340 */
+	0x00,  0x02,  0x3F,  0x22,  0x21,  0x22,  0x21,  0x22,  0x3F,  0x22,  0x21,  0x22,  0x21,  0x22,  0x21,  0x22, 	/* 27350 */
+	0x3F,  0x22,  0x21,  0x22,  0x21,  0x22,  0x3F,  0x22,  0x12,  0x22,  0x11,  0x02,  0x21,  0x02,  0x40,  0x06, 	/* 27360 */
+	0x8A,  0x08,  0x02,  0x49,  0x22,  0x29,  0x22,  0x2A,  0x22,  0x08,  0x22,  0x3F,  0x22,  0x21,  0x22,  0x21, 	/* 27370 */
+	0x22,  0x3F,  0x22,  0x21,  0x22,  0x21,  0x22,  0x3F,  0x22,  0x21,  0x02,  0x21,  0x02,  0x21,  0x02,  0x23, 	/* 27380 */
+	0x06,  0x8B,  0x04,  0x04,  0x04,  0x24,  0x7F,  0xE4,  0x04,  0x24,  0x04,  0x24,  0x3F,  0xA4,  0x20,  0xA4, 	/* 27390 */
+	0x20,  0xA4,  0x20,  0xA4,  0x3F,  0xA4,  0x0A,  0x04,  0x0A,  0x04,  0x0A,  0x0C,  0x12,  0x01,  0x21,  0x01, 	/* 273A0 */
+	0x40,  0xFF,  0x8C,  0x04,  0x02,  0x04,  0x12,  0x7F,  0xD2,  0x04,  0x12,  0x04,  0x12,  0x3F,  0x92,  0x24, 	/* 273B0 */
+	0x92,  0x24,  0x92,  0x24,  0x92,  0x3F,  0x92,  0x0C,  0x12,  0x0E,  0x02,  0x15,  0x02,  0x24,  0x82,  0x44, 	/* 273C0 */
+	0x02,  0x04,  0x06,  0x8D,  0x08,  0x10,  0x04,  0x10,  0x04,  0x20,  0x7F,  0xFF,  0x00,  0x00,  0x3E,  0x44, 	/* 273D0 */
+	0x22,  0x44,  0x22,  0x44,  0x3E,  0x44,  0x22,  0x44,  0x22,  0x44,  0x3E,  0x44,  0x22,  0x44,  0x22,  0x04, 	/* 273E0 */
+	0x22,  0x04,  0x26,  0x0C,  0x8F,  0x21,  0x00,  0x11,  0x7E,  0x12,  0x12,  0x7F,  0x92,  0x12,  0x12,  0x12, 	/* 273F0 */
+	0x12,  0x12,  0x52,  0x7F,  0xB2,  0x12,  0x12,  0x12,  0x1A,  0x12,  0x16,  0x12,  0x23,  0x12,  0x22,  0x22, 	/* 27400 */
+	0x42,  0x22,  0x82,  0x43,  0x0C,  0x94,  0x00,  0x02,  0x1F,  0x92,  0x10,  0x92,  0x1F,  0x92,  0x10,  0x92, 	/* 27410 */
+	0x10,  0x92,  0x1F,  0x92,  0x08,  0x12,  0x0F,  0xD2,  0x15,  0x52,  0x25,  0x52,  0x49,  0x42,  0x12,  0x42, 	/* 27420 */
+	0x24,  0x42,  0x08,  0x42,  0x01,  0x86,  0x96,  0x04,  0x02,  0x04,  0x12,  0x3F,  0xD2,  0x10,  0x92,  0x08, 	/* 27430 */
+	0x92,  0x09,  0x12,  0x09,  0x12,  0x7F,  0xF2,  0x00,  0x12,  0x00,  0x12,  0x1F,  0x92,  0x10,  0x92,  0x10, 	/* 27440 */
+	0x82,  0x10,  0x82,  0x1F,  0x82,  0x00,  0x06,  0x9B,  0x00,  0x02,  0x3F,  0xD2,  0x20,  0x52,  0x31,  0x52, 	/* 27450 */
+	0x2A,  0x52,  0x20,  0x52,  0x3F,  0xD2,  0x24,  0x52,  0x35,  0x52,  0x35,  0x52,  0x35,  0x52,  0x3F,  0x42, 	/* 27460 */
+	0x31,  0x42,  0x20,  0x42,  0x20,  0x42,  0x20,  0xC6,  0x9E,  0x04,  0x02,  0x04,  0x12,  0x7F,  0xD2,  0x04, 	/* 27470 */
+	0x12,  0x0A,  0x12,  0x31,  0x12,  0x00,  0x12,  0x7F,  0xF2,  0x00,  0x92,  0x3C,  0x92,  0x24,  0x92,  0x24, 	/* 27480 */
+	0x82,  0x3C,  0x82,  0x00,  0x82,  0x00,  0x82,  0x01,  0x86,  0xA3,  0x04,  0x02,  0x04,  0x12,  0x0A,  0x12, 	/* 27490 */
+	0x09,  0x12,  0x10,  0x92,  0x3F,  0x52,  0x44,  0x12,  0x3F,  0x92,  0x24,  0x92,  0x24,  0x92,  0x3F,  0x92, 	/* 274A0 */
+	0x06,  0x12,  0x05,  0x02,  0x08,  0x82,  0x10,  0x82,  0x60,  0x06,  0xA4,  0x04,  0x02,  0x04,  0x12,  0x7F, 	/* 274B0 */
+	0xF2,  0x11,  0x12,  0x0A,  0x12,  0x06,  0x12,  0x19,  0x92,  0x70,  0xF2,  0x10,  0x92,  0x1F,  0x92,  0x10, 	/* 274C0 */
+	0x92,  0x1F,  0x82,  0x10,  0x82,  0x20,  0x82,  0x20,  0x82,  0x40,  0x86,  0xA5,  0x00,  0x02,  0x3F,  0x12, 	/* 274D0 */
+	0x01,  0x12,  0x3F,  0x12,  0x01,  0x12,  0x01,  0x12,  0x7F,  0xD2,  0x04,  0x12,  0x44,  0x92,  0x27,  0x12, 	/* 274E0 */
+	0x26,  0x12,  0x0D,  0x02,  0x14,  0x82,  0x64,  0x42,  0x04,  0x02,  0x0C,  0x06,  0xA9,  0x01,  0x02,  0x3E, 	/* 274F0 */
+	0x12,  0x04,  0x12,  0x7F,  0xD2,  0x04,  0x12,  0x15,  0x52,  0x75,  0x92,  0x15,  0x12,  0x35,  0x52,  0x54, 	/* 27500 */
+	0xD2,  0x0E,  0x12,  0x0D,  0x02,  0x14,  0x82,  0x24,  0x42,  0x44,  0x02,  0x04,  0x06,  0xAA,  0x04,  0x10, 	/* 27510 */
+	0x02,  0x20,  0x7F,  0xFF,  0x11,  0x04,  0x1D,  0x24,  0x13,  0x24,  0x1D,  0x24,  0x13,  0x24,  0x11,  0x24, 	/* 27520 */
+	0x13,  0x0C,  0x00,  0x00,  0x7F,  0xFE,  0x01,  0x02,  0x02,  0x02,  0x0C,  0x02,  0x70,  0x0C,  0xAF,  0x00, 	/* 27530 */
+	0x02,  0x7F,  0xD2,  0x00,  0x12,  0x1F,  0x12,  0x11,  0x12,  0x11,  0x12,  0x1F,  0x12,  0x00,  0x12,  0x3F, 	/* 27540 */
+	0x92,  0x24,  0x92,  0x24,  0x92,  0x3F,  0x92,  0x24,  0x82,  0x24,  0x82,  0x3F,  0x82,  0x00,  0x06,  0xB0, 	/* 27550 */
+	0x01,  0x02,  0x1E,  0x12,  0x04,  0x12,  0x3F,  0xD2,  0x14,  0x92,  0x14,  0x92,  0x7F,  0xF2,  0x14,  0x92, 	/* 27560 */
+	0x14,  0x92,  0x3F,  0xD2,  0x0E,  0x12,  0x0D,  0x12,  0x14,  0x82,  0x24,  0x42,  0x44,  0x02,  0x04,  0x06, 	/* 27570 */
+	0xB1,  0x04,  0x00,  0x04,  0x7E,  0x0A,  0x12,  0x11,  0x12,  0x3F,  0x92,  0x44,  0x52,  0x04,  0x12,  0x3F, 	/* 27580 */
+	0xB2,  0x24,  0x92,  0x24,  0x9A,  0x3F,  0x96,  0x04,  0x13,  0x0A,  0x12,  0x11,  0x22,  0x21,  0x42,  0x40, 	/* 27590 */
+	0x8C,  0xB2,  0x04,  0x02,  0x7F,  0xD2,  0x40,  0x52,  0x44,  0x52,  0x3F,  0x92,  0x04,  0x12,  0x3F,  0x92, 	/* 275A0 */
+	0x04,  0x12,  0x7F,  0xD2,  0x00,  0x12,  0x1F,  0x92,  0x10,  0x92,  0x10,  0x82,  0x10,  0x82,  0x1F,  0x82, 	/* 275B0 */
+	0x00,  0x06,  0xB3,  0x11,  0x02,  0x11,  0x12,  0x7F,  0xD2,  0x11,  0x12,  0x04,  0x12,  0x04,  0x12,  0x0A, 	/* 275C0 */
+	0x12,  0x11,  0x12,  0x3F,  0x92,  0x40,  0x52,  0x00,  0x12,  0x3F,  0x82,  0x20,  0x82,  0x20,  0x82,  0x3F, 	/* 275D0 */
+	0x82,  0x00,  0x06,  0xB4,  0x04,  0x02,  0x24,  0x92,  0x24,  0x92,  0x3F,  0x92,  0x00,  0x12,  0x7F,  0xD2, 	/* 275E0 */
+	0x00,  0x12,  0x3F,  0x92,  0x20,  0x92,  0x20,  0x92,  0x3F,  0x92,  0x11,  0x02,  0x09,  0x02,  0x0A,  0xC2, 	/* 275F0 */
+	0x0F,  0x02,  0x70,  0x06,  0xB5,  0x02,  0x02,  0x02,  0x12,  0x05,  0x12,  0x08,  0x92,  0x1F,  0x52,  0x20, 	/* 27600 */
+	0x32,  0x5F,  0x92,  0x10,  0x92,  0x1F,  0x92,  0x10,  0x92,  0x1F,  0x92,  0x10,  0x12,  0x2F,  0x82,  0x28, 	/* 27610 */
+	0x82,  0x4F,  0x82,  0x00,  0x06,  0xBD,  0x00,  0x02,  0x7F,  0xF2,  0x09,  0x12,  0x3F,  0xD2,  0x29,  0x52, 	/* 27620 */
+	0x29,  0x52,  0x3F,  0xD2,  0x00,  0x12,  0x3F,  0xD2,  0x00,  0x12,  0x7F,  0xF2,  0x12,  0x92,  0x12,  0x42, 	/* 27630 */
+	0x22,  0x42,  0x42,  0x02,  0x06,  0x06,  0xBF,  0x12,  0x82,  0x24,  0x92,  0x6D,  0x12,  0x12,  0x92,  0x3F, 	/* 27640 */
+	0x92,  0x24,  0x92,  0x3F,  0x92,  0x24,  0x92,  0x3F,  0x92,  0x04,  0x12,  0x7F,  0xD2,  0x0E,  0x02,  0x15, 	/* 27650 */
+	0x02,  0x24,  0x82,  0x44,  0x42,  0x04,  0x06,  0x83,  0x04,  0x02,  0x3F,  0x92,  0x04,  0x92,  0x7F,  0xF2, 	/* 27660 */
+	0x04,  0x92,  0x3F,  0x92,  0x04,  0x12,  0x1F,  0x12,  0x7F,  0xD2,  0x24,  0x92,  0x3F,  0x92,  0x24,  0x92, 	/* 27670 */
+	0x3F,  0x82,  0x00,  0x02,  0x7F,  0xC2,  0x00,  0x06,  0x87,  0x04,  0x02,  0x07,  0x92,  0x04,  0x12,  0x3F, 	/* 27680 */
+	0xD2,  0x25,  0x52,  0x3E,  0x12,  0x24,  0x92,  0x23,  0x92,  0x3F,  0xD2,  0x26,  0x12,  0x3A,  0x52,  0x25, 	/* 27690 */
+	0x42,  0x3B,  0x82,  0x25,  0x42,  0x59,  0x22,  0x06,  0x06,  0x88,  0x00,  0x08,  0x1F,  0x08,  0x11,  0x7F, 	/* 276A0 */
+	0x11,  0x22,  0x1F,  0x14,  0x10,  0xFF,  0x1F,  0x08,  0x29,  0x7F,  0x29,  0x08,  0x4F,  0x08,  0x00,  0x00, 	/* 276B0 */
+	0x7F,  0xFE,  0x00,  0x82,  0x03,  0x02,  0x0C,  0x02,  0x70,  0x1C,  0x89,  0x08,  0x02,  0x33,  0xC2,  0x21, 	/* 276C0 */
+	0x52,  0x29,  0x52,  0x3A,  0x52,  0x65,  0xD2,  0x04,  0x12,  0x0B,  0x12,  0x10,  0xD2,  0x7F,  0x12,  0x04, 	/* 276D0 */
+	0x12,  0x7F,  0xD2,  0x04,  0x82,  0x25,  0x02,  0x17,  0x82,  0x78,  0x06,  0x8D,  0x04,  0x02,  0x04,  0x12, 	/* 276E0 */
+	0x0A,  0x12,  0x11,  0x12,  0x20,  0x92,  0x5F,  0x52,  0x00,  0x12,  0x3B,  0x92,  0x2A,  0x92,  0x2A,  0x92, 	/* 276F0 */
+	0x3B,  0x92,  0x11,  0x12,  0x19,  0x82,  0x26,  0x42,  0x22,  0x02,  0x44,  0x06,  0x91,  0x04,  0x02,  0x04, 	/* 27700 */
+	0x12,  0x7F,  0xF2,  0x0A,  0x52,  0x75,  0x92,  0x35,  0x52,  0x35,  0x52,  0x55,  0xB2,  0x00,  0x12,  0x10, 	/* 27710 */
+	0x92,  0x1F,  0x92,  0x10,  0x82,  0x1F,  0x82,  0x10,  0x82,  0x20,  0x82,  0x40,  0x86,  0x92,  0x04,  0x00, 	/* 27720 */
+	0x04,  0x7E,  0x0A,  0x12,  0x11,  0x12,  0x20,  0x92,  0x5F,  0x12,  0x00,  0x32,  0x3B,  0xB2,  0x2A,  0xD2, 	/* 27730 */
+	0x2A,  0x92,  0x3B,  0x92,  0x11,  0x12,  0x19,  0xA2,  0x26,  0x62,  0x22,  0x42,  0x44,  0x8C,  0x94,  0x04, 	/* 27740 */
+	0x00,  0x04,  0x7E,  0x0A,  0x12,  0x11,  0x12,  0x20,  0x92,  0x5F,  0x12,  0x00,  0x52,  0x3B,  0xB2,  0x2A, 	/* 27750 */
+	0x92,  0x2A,  0x9A,  0x3B,  0x97,  0x11,  0x12,  0x19,  0xA2,  0x26,  0x62,  0x22,  0x42,  0x44,  0x8C,  0x9B, 	/* 27760 */
+	0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFC,  0x01,  0x04,  0x01,  0x04,  0x01,  0x04, 	/* 27770 */
+	0x02,  0x04,  0x02,  0x04,  0x02,  0x04,  0x04,  0x04,  0x04,  0x04,  0x08,  0x04,  0x10,  0x08,  0x20,  0x30, 	/* 27780 */
+	0x9F,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x7E,  0x20,  0x09,  0xFE,  0x08,  0x22,  0x08,  0x22,  0x08, 	/* 27790 */
+	0x22,  0x08,  0x22,  0x08,  0x22,  0x0E,  0x42,  0x18,  0x42,  0x60,  0x42,  0x00,  0x82,  0x01,  0x04,  0x02, 	/* 277A0 */
+	0x18,  0xA0,  0x08,  0x00,  0x08,  0x00,  0x08,  0x3E,  0x08,  0x22,  0x7F,  0xA2,  0x08,  0xA2,  0x08,  0xA2, 	/* 277B0 */
+	0x08,  0xA2,  0x08,  0xA2,  0x08,  0xA2,  0x08,  0xA2,  0x08,  0xA2,  0x10,  0xA2,  0x10,  0xBE,  0x20,  0x80, 	/* 277C0 */
+	0x43,  0x00,  0xA3,  0x00,  0x80,  0x04,  0x90,  0x04,  0x88,  0x08,  0x84,  0x10,  0x94,  0x21,  0xA2,  0x00, 	/* 277D0 */
+	0xC2,  0x07,  0x40,  0x78,  0x40,  0x00,  0x40,  0x1F,  0xFC,  0x00,  0x84,  0x01,  0x04,  0x02,  0x04,  0x0C, 	/* 277E0 */
+	0x04,  0x30,  0x18,  0xA9,  0x00,  0x20,  0x3E,  0x20,  0x22,  0x20,  0x22,  0x20,  0x23,  0xFE,  0x3E,  0x22, 	/* 277F0 */
+	0x22,  0x22,  0x22,  0x22,  0x3E,  0x22,  0x22,  0x22,  0x22,  0x42,  0x23,  0x42,  0x26,  0x42,  0x38,  0x82, 	/* 27800 */
+	0x61,  0x04,  0x02,  0x18,  0xAA,  0x04,  0x00,  0x04,  0x00,  0x7F,  0xFC,  0x09,  0x44,  0x09,  0x44,  0x11, 	/* 27810 */
+	0x28,  0x3E,  0x10,  0x05,  0x68,  0x18,  0x86,  0x60,  0x80,  0x1F,  0xF8,  0x00,  0x88,  0x01,  0x08,  0x02, 	/* 27820 */
+	0x08,  0x0C,  0x08,  0x30,  0x30,  0xAB,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x3F,  0x90,  0x04,  0x7E, 	/* 27830 */
+	0x04,  0x12,  0x04,  0x12,  0x04,  0x12,  0x7F,  0x92,  0x04,  0x12,  0x04,  0x12,  0x0A,  0x22,  0x09,  0x22, 	/* 27840 */
+	0x13,  0x22,  0x7C,  0xC2,  0x00,  0x8C,  0xAC,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x1F,  0x90,  0x10, 	/* 27850 */
+	0xFE,  0x20,  0x92,  0x3E,  0x92,  0x52,  0x92,  0x12,  0x92,  0x12,  0x92,  0x12,  0x92,  0x1E,  0xA2,  0x00, 	/* 27860 */
+	0xA2,  0x00,  0xA2,  0x01,  0x42,  0x06,  0x8C,  0xAD,  0x00,  0x10,  0x7F,  0x90,  0x08,  0x90,  0x08,  0x90, 	/* 27870 */
+	0x08,  0xFE,  0x10,  0x92,  0x20,  0x92,  0x43,  0x12,  0x00,  0x12,  0x3F,  0x12,  0x21,  0x12,  0x21,  0x22, 	/* 27880 */
+	0x21,  0x22,  0x21,  0x22,  0x3F,  0x42,  0x00,  0x8C,  0xB1,  0x00,  0x10,  0x1F,  0xD0,  0x10,  0x10,  0x10, 	/* 27890 */
+	0x10,  0x1F,  0xFE,  0x14,  0x12,  0x14,  0x12,  0x17,  0x92,  0x14,  0x92,  0x14,  0x92,  0x14,  0x92,  0x14, 	/* 278A0 */
+	0x92,  0x28,  0xA2,  0x28,  0xA2,  0x51,  0x42,  0x06,  0x8C,  0xB4,  0x11,  0x04,  0x08,  0x84,  0x08,  0x88, 	/* 278B0 */
+	0x08,  0x90,  0x7F,  0xFE,  0x40,  0x02,  0x41,  0x02,  0x01,  0x00,  0x3F,  0xF8,  0x01,  0x08,  0x01,  0x08, 	/* 278C0 */
+	0x02,  0x08,  0x02,  0x08,  0x04,  0x08,  0x18,  0x08,  0x60,  0x30,  0xB5,  0x04,  0x90,  0x04,  0x88,  0x08, 	/* 278D0 */
+	0x88,  0x3F,  0xFE,  0x00,  0x80,  0x01,  0x40,  0x7F,  0xFF,  0x02,  0x20,  0x04,  0x90,  0x18,  0x8C,  0x6F, 	/* 278E0 */
+	0xF3,  0x01,  0x10,  0x01,  0x10,  0x02,  0x10,  0x0C,  0x10,  0x30,  0x60,  0xB9,  0x04,  0x10,  0x04,  0x10, 	/* 278F0 */
+	0x04,  0x10,  0x7F,  0x90,  0x12,  0x7E,  0x11,  0x12,  0x11,  0x12,  0x29,  0x92,  0x2A,  0x12,  0x46,  0x12, 	/* 27900 */
+	0x02,  0x22,  0x05,  0x22,  0x09,  0x42,  0x10,  0x42,  0x20,  0x82,  0x41,  0x0C,  0xBC,  0x08,  0x10,  0x08, 	/* 27910 */
+	0x10,  0x08,  0x10,  0x7F,  0x90,  0x08,  0xFE,  0x08,  0x12,  0x08,  0x12,  0x3F,  0x12,  0x00,  0x12,  0x00, 	/* 27920 */
+	0x12,  0x3F,  0x12,  0x21,  0x22,  0x21,  0x22,  0x21,  0x42,  0x3F,  0x82,  0x01,  0x0C,  0xBE,  0x04,  0x10, 	/* 27930 */
+	0x04,  0x10,  0x04,  0x10,  0x7F,  0xFE,  0x08,  0x12,  0x0A,  0x12,  0x72,  0x12,  0x14,  0x92,  0x0C,  0x92, 	/* 27940 */
+	0x09,  0x12,  0x11,  0x22,  0x22,  0x22,  0x05,  0x22,  0x08,  0xC2,  0x10,  0x82,  0x61,  0x0C,  0x81,  0x00, 	/* 27950 */
+	0x10,  0x7F,  0x90,  0x00,  0x10,  0x15,  0x10,  0x15,  0x7E,  0x2A,  0x12,  0x6A,  0x12,  0x15,  0x12,  0x15, 	/* 27960 */
+	0x12,  0x00,  0x12,  0x7F,  0x12,  0x08,  0x22,  0x08,  0x22,  0x0B,  0x22,  0x1C,  0x42,  0x60,  0x8C,  0x83, 	/* 27970 */
+	0x04,  0x10,  0x04,  0x10,  0x3F,  0x10,  0x04,  0x10,  0x04,  0x7E,  0x7F,  0x92,  0x40,  0x92,  0x5E,  0x92, 	/* 27980 */
+	0x02,  0x12,  0x04,  0x12,  0x07,  0xA2,  0x7C,  0x22,  0x04,  0x22,  0x04,  0x42,  0x04,  0x82,  0x0D,  0x0C, 	/* 27990 */
+	0x85,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xD0,  0x04,  0x10,  0x04,  0xFE,  0x3F,  0x92,  0x24,  0x92,  0x24, 	/* 279A0 */
+	0x92,  0x3F,  0x92,  0x0C,  0x12,  0x0E,  0x12,  0x15,  0x22,  0x14,  0xA2,  0x24,  0x42,  0x44,  0x82,  0x05, 	/* 279B0 */
+	0x0C,  0x87,  0x00,  0x00,  0x1F,  0xF0,  0x06,  0x40,  0x01,  0x80,  0x1F,  0xF8,  0x11,  0x08,  0x1F,  0xF8, 	/* 279C0 */
+	0x11,  0x08,  0x11,  0x08,  0x1F,  0xF8,  0x01,  0x00,  0x7F,  0xFC,  0x01,  0x04,  0x02,  0x04,  0x0C,  0x04, 	/* 279D0 */
+	0x70,  0x38,  0x89,  0x08,  0x10,  0x08,  0x10,  0x1E,  0x10,  0x12,  0x10,  0x24,  0x10,  0x7F,  0xFE,  0x24, 	/* 279E0 */
+	0x92,  0x24,  0x92,  0x24,  0x92,  0x3F,  0x92,  0x0A,  0x22,  0x0A,  0x22,  0x12,  0x44,  0x12,  0x99,  0x21, 	/* 279F0 */
+	0x01,  0x40,  0xFF,  0x8D,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x7F,  0x90,  0x00,  0x7E,  0x1F,  0x12, 	/* 27A00 */
+	0x11,  0x12,  0x11,  0x12,  0x11,  0x12,  0x1F,  0x12,  0x04,  0x22,  0x16,  0x22,  0x15,  0x22,  0x25,  0x42, 	/* 27A10 */
+	0x44,  0x82,  0x0D,  0x0C,  0x92,  0x12,  0x10,  0x12,  0x10,  0x7F,  0x10,  0x12,  0x10,  0x12,  0xFE,  0x1E, 	/* 27A20 */
+	0x12,  0x08,  0x12,  0x3F,  0x12,  0x29,  0x12,  0x29,  0x12,  0x3F,  0x12,  0x08,  0x22,  0x7F,  0xA2,  0x08, 	/* 27A30 */
+	0x42,  0x08,  0x82,  0x09,  0x1C,  0x95,  0x01,  0x90,  0x1E,  0x10,  0x04,  0x10,  0x7F,  0xD0,  0x04,  0x7E, 	/* 27A40 */
+	0x1F,  0x92,  0x14,  0x92,  0x1F,  0x92,  0x14,  0x92,  0x14,  0x92,  0x1F,  0x92,  0x04,  0x12,  0x3F,  0x22, 	/* 27A50 */
+	0x05,  0xA2,  0x0E,  0x42,  0x70,  0x8C,  0x97,  0x00,  0x00,  0x1F,  0xF8,  0x10,  0x08,  0x1F,  0xF8,  0x10, 	/* 27A60 */
+	0x08,  0x1F,  0xF8,  0x00,  0x10,  0x1F,  0x10,  0x11,  0xFE,  0x1F,  0x12,  0x11,  0x12,  0x1F,  0x22,  0x11, 	/* 27A70 */
+	0xA2,  0x1F,  0x42,  0x70,  0x82,  0x01,  0x0C,  0x98,  0x11,  0x10,  0x11,  0x10,  0x7F,  0x90,  0x11,  0x10, 	/* 27A80 */
+	0x1F,  0x7E,  0x11,  0x12,  0x1F,  0x12,  0x11,  0x12,  0x7F,  0x92,  0x2A,  0x12,  0x2A,  0x12,  0x2A,  0xA2, 	/* 27A90 */
+	0x31,  0xA2,  0x20,  0x22,  0x3F,  0x42,  0x00,  0x8C,  0x99,  0x00,  0x40,  0x3F,  0x40,  0x02,  0x7F,  0x14, 	/* 27AA0 */
+	0x84,  0x09,  0x44,  0x08,  0x28,  0x7F,  0x10,  0x0A,  0x6C,  0x0B,  0xA3,  0x1C,  0x20,  0x19,  0xFC,  0x28, 	/* 27AB0 */
+	0x24,  0x28,  0x24,  0x48,  0x44,  0x08,  0x84,  0x19,  0x18,  0x9D,  0x00,  0x20,  0x3D,  0x24,  0x24,  0xA8, 	/* 27AC0 */
+	0x24,  0x20,  0x25,  0xFE,  0x3C,  0x20,  0x24,  0x30,  0x27,  0xFF,  0x24,  0x48,  0x3C,  0xA4,  0x25,  0xFE, 	/* 27AD0 */
+	0x26,  0x25,  0x24,  0x24,  0x24,  0x44,  0x24,  0x84,  0x4D,  0x18,  0x9E,  0x04,  0x10,  0x15,  0x54,  0x15, 	/* 27AE0 */
+	0x54,  0x2A,  0x28,  0x11,  0x44,  0x20,  0x80,  0x7F,  0xFE,  0x41,  0x02,  0x41,  0x02,  0x3F,  0xF8,  0x01, 	/* 27AF0 */
+	0x08,  0x01,  0x08,  0x02,  0x08,  0x04,  0x08,  0x18,  0x08,  0x60,  0x30,  0x9F,  0x02,  0x20,  0x7F,  0xFF, 	/* 27B00 */
+	0x02,  0x20,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x01,  0x00,  0x7F,  0xFF, 	/* 27B10 */
+	0x04,  0x90,  0x1F,  0xFC,  0x61,  0x13,  0x02,  0x10,  0x0C,  0x10,  0x30,  0x60,  0xA0,  0x00,  0x10,  0x7F, 	/* 27B20 */
+	0x90,  0x2A,  0x90,  0x4C,  0x90,  0x19,  0xFE,  0x6A,  0x92,  0x0C,  0x92,  0x0A,  0x12,  0x11,  0x12,  0x64, 	/* 27B30 */
+	0x92,  0x0A,  0x12,  0x34,  0x92,  0x09,  0x22,  0x32,  0x22,  0x0C,  0x42,  0x70,  0x8C,  0xA2,  0x04,  0x10, 	/* 27B40 */
+	0x3F,  0x10,  0x04,  0x10,  0x7F,  0xFC,  0x15,  0x14,  0x15,  0xD4,  0x3F,  0x24,  0x44,  0xB4,  0x07,  0x4D, 	/* 27B50 */
+	0x79,  0x85,  0x01,  0x03,  0x3F,  0xF8,  0x01,  0x08,  0x02,  0x08,  0x0C,  0x08,  0x30,  0x30,  0xA3,  0x04, 	/* 27B60 */
+	0x10,  0x3F,  0x10,  0x04,  0x10,  0x3F,  0x10,  0x04,  0x7E,  0x7F,  0x92,  0x00,  0x12,  0x1F,  0x12,  0x11, 	/* 27B70 */
+	0x12,  0x1F,  0x12,  0x11,  0x12,  0x1F,  0x12,  0x11,  0x22,  0x1F,  0x22,  0x19,  0x42,  0x60,  0x8C,  0xA4, 	/* 27B80 */
+	0x11,  0x10,  0x11,  0x10,  0x7F,  0xD0,  0x11,  0x10,  0x00,  0x7E,  0x3F,  0x92,  0x24,  0x92,  0x24,  0x92, 	/* 27B90 */
+	0x3F,  0x92,  0x04,  0x12,  0x3F,  0x92,  0x04,  0x22,  0x3F,  0xA2,  0x04,  0x22,  0x07,  0x42,  0x78,  0x8C, 	/* 27BA0 */
+	0xA6,  0x12,  0x90,  0x24,  0x90,  0x6D,  0x10,  0x12,  0x90,  0x3F,  0xFE,  0x24,  0x92,  0x3F,  0x92,  0x24, 	/* 27BB0 */
+	0x92,  0x3F,  0x92,  0x04,  0x12,  0x7F,  0xD2,  0x0D,  0x12,  0x14,  0xA2,  0x24,  0x22,  0x44,  0x42,  0x04, 	/* 27BC0 */
+	0x8C,  0xA7,  0x10,  0x10,  0x10,  0x10,  0x1F,  0x90,  0x24,  0x10,  0x24,  0x7E,  0x5F,  0x92,  0x09,  0x12, 	/* 27BD0 */
+	0x12,  0x12,  0x3F,  0x92,  0x52,  0x12,  0x1F,  0x22,  0x12,  0x22,  0x1F,  0x22,  0x12,  0x42,  0x1F,  0xC2, 	/* 27BE0 */
+	0x00,  0x8C,  0xB2,  0x01,  0x10,  0x3E,  0x10,  0x04,  0x10,  0x7F,  0x90,  0x04,  0x7E,  0x3F,  0x12,  0x25, 	/* 27BF0 */
+	0x12,  0x3F,  0x12,  0x25,  0x12,  0x3F,  0x22,  0x1E,  0x22,  0x07,  0x4C,  0x78,  0x00,  0x12,  0x24,  0x21, 	/* 27C00 */
+	0x12,  0x41,  0x11,  0xB3,  0x02,  0x10,  0x3C,  0x10,  0x08,  0x10,  0x7F,  0x90,  0x08,  0x7E,  0x3F,  0x12, 	/* 27C10 */
+	0x3B,  0x12,  0x2D,  0x12,  0x3F,  0x12,  0x08,  0x12,  0x3F,  0x12,  0x08,  0x12,  0x7F,  0xA2,  0x35,  0x22, 	/* 27C20 */
+	0x2A,  0x42,  0x4A,  0x8C,  0xB5,  0x00,  0x08,  0x3F,  0xC8,  0x25,  0x08,  0x3F,  0xC8,  0x25,  0x7E,  0x2F, 	/* 27C30 */
+	0x8A,  0x2A,  0x8A,  0x2F,  0x8A,  0x2A,  0x8A,  0x2F,  0x8A,  0x22,  0x0A,  0x3F,  0xD2,  0x35,  0x52,  0x5E, 	/* 27C40 */
+	0xE2,  0x10,  0x42,  0x10,  0xCC,  0xB8,  0x09,  0x10,  0x7F,  0xD0,  0x09,  0x10,  0x3B,  0x90,  0x2A,  0xFE, 	/* 27C50 */
+	0x3B,  0x92,  0x12,  0x12,  0x14,  0x12,  0x3F,  0x92,  0x64,  0x12,  0x3F,  0x12,  0x24,  0x12,  0x3F,  0x22, 	/* 27C60 */
+	0x24,  0x22,  0x3F,  0xC2,  0x00,  0x8C,  0xB9,  0x08,  0x00,  0x08,  0x00,  0x0F,  0xFE,  0x08,  0x02,  0x10, 	/* 27C70 */
+	0x02,  0x10,  0x02,  0x20,  0x02,  0x40,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00, 	/* 27C80 */
+	0x02,  0x00,  0x02,  0x00,  0x04,  0x00,  0x38,  0xBA,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x07,  0xFE, 	/* 27C90 */
+	0x08,  0x02,  0x08,  0x02,  0x10,  0x02,  0x23,  0x02,  0x40,  0x82,  0x00,  0x42,  0x00,  0x42,  0x00,  0x02, 	/* 27CA0 */
+	0x00,  0x02,  0x00,  0x02,  0x00,  0x04,  0x00,  0x18,  0xBE,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x0F, 	/* 27CB0 */
+	0xFE,  0x09,  0x02,  0x11,  0x02,  0x11,  0x02,  0x21,  0x02,  0x42,  0x42,  0x02,  0x22,  0x02,  0x22,  0x04, 	/* 27CC0 */
+	0xF2,  0x1F,  0x12,  0x00,  0x02,  0x00,  0x04,  0x00,  0x38,  0xBF,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00, 	/* 27CD0 */
+	0x0F,  0xFC,  0x12,  0x24,  0x12,  0x24,  0x22,  0x24,  0x44,  0x44,  0x04,  0x44,  0x08,  0x44,  0x10,  0x84, 	/* 27CE0 */
+	0x20,  0x84,  0x01,  0x04,  0x02,  0x04,  0x04,  0x08,  0x00,  0x30,  0x81,  0x08,  0x00,  0x08,  0x00,  0x0F, 	/* 27CF0 */
+	0xFC,  0x08,  0x84,  0x18,  0x84,  0x14,  0x84,  0x24,  0x84,  0x42,  0x84,  0x01,  0x04,  0x01,  0x84,  0x01, 	/* 27D00 */
+	0x64,  0x02,  0x1C,  0x04,  0x07,  0x18,  0x04,  0x60,  0x08,  0x00,  0x70,  0x82,  0x08,  0x00,  0x08,  0x00, 	/* 27D10 */
+	0x08,  0x00,  0x0F,  0xFE,  0x14,  0x02,  0x14,  0x02,  0x24,  0x22,  0x44,  0xC2,  0x07,  0x02,  0x04,  0x02, 	/* 27D20 */
+	0x04,  0x12,  0x04,  0x12,  0x03,  0xF2,  0x00,  0x02,  0x00,  0x04,  0x00,  0x18,  0x85,  0x04,  0x00,  0x04, 	/* 27D30 */
+	0x00,  0x07,  0xFC,  0x08,  0x04,  0x08,  0x04,  0x1F,  0xE4,  0x20,  0x24,  0x40,  0x24,  0x00,  0x24,  0x0F, 	/* 27D40 */
+	0xE8,  0x08,  0x30,  0x08,  0x00,  0x08,  0x00,  0x08,  0x02,  0x04,  0x02,  0x03,  0xFE,  0x86,  0x08,  0x00, 	/* 27D50 */
+	0x08,  0x00,  0x0F,  0xFE,  0x09,  0x22,  0x11,  0x22,  0x11,  0x22,  0x21,  0x22,  0x4E,  0x22,  0x03,  0x22, 	/* 27D60 */
+	0x04,  0xC2,  0x18,  0x62,  0x60,  0x92,  0x01,  0x02,  0x06,  0x02,  0x18,  0x04,  0x00,  0x18,  0x88,  0x08, 	/* 27D70 */
+	0x00,  0x08,  0x00,  0x0F,  0xFE,  0x08,  0x02,  0x10,  0x22,  0x12,  0x22,  0x29,  0x4A,  0x48,  0xCA,  0x08, 	/* 27D80 */
+	0xCA,  0x08,  0xAA,  0x09,  0x2A,  0x0A,  0x0A,  0x0F,  0xFA,  0x00,  0x02,  0x00,  0x04,  0x00,  0x18,  0x8D, 	/* 27D90 */
+	0x08,  0x00,  0x08,  0x00,  0x0F,  0xFE,  0x08,  0x42,  0x11,  0x22,  0x1F,  0xFA,  0x21,  0x02,  0x5F,  0xF2, 	/* 27DA0 */
+	0x11,  0x12,  0x1F,  0xF2,  0x11,  0x12,  0x1F,  0xF2,  0x11,  0x12,  0x11,  0x12,  0x11,  0x34,  0x00,  0x18, 	/* 27DB0 */
+	0x8F,  0x08,  0x20,  0x08,  0x20,  0x7F,  0x3E,  0x14,  0x22,  0x12,  0x42,  0x21,  0x7A,  0x7E,  0xCA,  0x00, 	/* 27DC0 */
+	0x4A,  0x7F,  0x7A,  0x10,  0x42,  0x10,  0x42,  0x3E,  0x4C,  0x22,  0x40,  0x02,  0x41,  0x02,  0x21,  0x0C, 	/* 27DD0 */
+	0x1F,  0x90,  0x08,  0x00,  0x08,  0x00,  0x0F,  0xFE,  0x10,  0x02,  0x1F,  0xF2,  0x20,  0x02,  0x4F,  0xE2, 	/* 27DE0 */
+	0x08,  0x22,  0x0F,  0xE2,  0x00,  0x02,  0x1F,  0xF2,  0x11,  0x12,  0x1F,  0xF2,  0x11,  0x12,  0x1F,  0xF4, 	/* 27DF0 */
+	0x00,  0x18,  0x95,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x04,  0x08,  0x08,  0x08,  0x10,  0x08, 	/* 27E00 */
+	0x60,  0x09,  0x80,  0x0E,  0x00,  0x38,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x02,  0x08,  0x02,  0x04, 	/* 27E10 */
+	0x02,  0x03,  0xFE,  0x96,  0x02,  0x40,  0x02,  0x40,  0x02,  0x42,  0x04,  0x42,  0x04,  0x44,  0x08,  0x44, 	/* 27E20 */
+	0x08,  0x48,  0x18,  0x50,  0x28,  0x60,  0x48,  0x40,  0x08,  0x40,  0x08,  0x40,  0x08,  0x41,  0x08,  0x41, 	/* 27E30 */
+	0x08,  0x21,  0x08,  0x1F,  0x97,  0x04,  0x40,  0x04,  0x40,  0x04,  0x40,  0x04,  0x44,  0x04,  0x44,  0x7C, 	/* 27E40 */
+	0x48,  0x04,  0x50,  0x04,  0x60,  0x04,  0x40,  0x04,  0x40,  0x0C,  0x40,  0x14,  0x42,  0x64,  0x42,  0x04, 	/* 27E50 */
+	0x22,  0x04,  0x1E,  0x04,  0x00,  0x99,  0x00,  0x20,  0x1F,  0x20,  0x11,  0x20,  0x1F,  0x22,  0x11,  0x24, 	/* 27E60 */
+	0x11,  0x38,  0x1F,  0x20,  0x00,  0x20,  0x7F,  0xA0,  0x14,  0x22,  0x14,  0x22,  0x17,  0xA2,  0x1C,  0x1E, 	/* 27E70 */
+	0x24,  0x00,  0x23,  0x00,  0x40,  0xFF,  0x9A,  0x00,  0x00,  0x3F,  0xFE,  0x20,  0x00,  0x20,  0x00,  0x20, 	/* 27E80 */
+	0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20, 	/* 27E90 */
+	0x00,  0x20,  0x00,  0x3F,  0xFE,  0x00,  0x00,  0x9D,  0x00,  0x00,  0x3F,  0xFE,  0x20,  0x00,  0x20,  0x40, 	/* 27EA0 */
+	0x20,  0x40,  0x27,  0xFC,  0x24,  0x44,  0x24,  0x44,  0x24,  0x44,  0x24,  0x44,  0x24,  0x58,  0x24,  0x40, 	/* 27EB0 */
+	0x20,  0x40,  0x20,  0x40,  0x3F,  0xFF,  0x00,  0x00,  0xA0,  0x00,  0x00,  0x3F,  0xFE,  0x20,  0x08,  0x20, 	/* 27EC0 */
+	0x70,  0x27,  0x80,  0x24,  0x00,  0x27,  0xFC,  0x24,  0x20,  0x24,  0x20,  0x24,  0x20,  0x24,  0x20,  0x28, 	/* 27ED0 */
+	0x20,  0x28,  0x20,  0x30,  0x20,  0x3F,  0xFE,  0x00,  0x00,  0xA1,  0x00,  0x00,  0x3F,  0xFE,  0x20,  0x00, 	/* 27EE0 */
+	0x20,  0x00,  0x2F,  0xF8,  0x20,  0x80,  0x20,  0x80,  0x27,  0xF0,  0x20,  0x80,  0x20,  0x80,  0x20,  0x80, 	/* 27EF0 */
+	0x2F,  0xFC,  0x20,  0x00,  0x20,  0x00,  0x3F,  0xFE,  0x00,  0x00,  0xA3,  0x00,  0x00,  0x3F,  0xFE,  0x20, 	/* 27F00 */
+	0x00,  0x27,  0xFC,  0x24,  0x44,  0x24,  0x44,  0x27,  0xFC,  0x24,  0x44,  0x24,  0x44,  0x27,  0xFC,  0x20, 	/* 27F10 */
+	0x40,  0x20,  0x40,  0x20,  0x40,  0x20,  0x40,  0x3F,  0xFF,  0x00,  0x00,  0xAA,  0x00,  0x00,  0x3F,  0xFE, 	/* 27F20 */
+	0x21,  0x20,  0x21,  0x20,  0x2F,  0x3C,  0x21,  0x20,  0x21,  0x20,  0x2F,  0x3C,  0x21,  0x20,  0x23,  0xA0, 	/* 27F30 */
+	0x2D,  0x3E,  0x22,  0x20,  0x22,  0x20,  0x24,  0x00,  0x3F,  0xFE,  0x00,  0x00,  0xAF,  0x00,  0x00,  0x3F, 	/* 27F40 */
+	0xFF,  0x28,  0x00,  0x24,  0x88,  0x20,  0x90,  0x31,  0xFE,  0x29,  0x20,  0x23,  0xFC,  0x21,  0x20,  0x25, 	/* 27F50 */
+	0xFC,  0x29,  0x20,  0x29,  0x20,  0x31,  0xFE,  0x20,  0x00,  0x3F,  0xFF,  0x20,  0x00,  0xB1,  0x00,  0x00, 	/* 27F60 */
+	0x3F,  0xFF,  0x20,  0x40,  0x23,  0xFC,  0x22,  0x44,  0x23,  0xFC,  0x20,  0x40,  0x2F,  0xFF,  0x21,  0x08, 	/* 27F70 */
+	0x21,  0xF8,  0x21,  0x08,  0x21,  0xF8,  0x21,  0x98,  0x26,  0x04,  0x3F,  0xFF,  0x20,  0x00,  0xB3,  0x00, 	/* 27F80 */
+	0x00,  0x3F,  0xFF,  0x20,  0x40,  0x20,  0xA0,  0x21,  0x10,  0x27,  0xEC,  0x38,  0x03,  0x27,  0xBC,  0x24, 	/* 27F90 */
+	0xA4,  0x27,  0xBC,  0x22,  0x08,  0x23,  0x0C,  0x24,  0x92,  0x28,  0x20,  0x3F,  0xFF,  0x20,  0x00,  0xB8, 	/* 27FA0 */
+	0x00,  0x00,  0x7F,  0xFF,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00, 	/* 27FB0 */
+	0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x08,  0x00,  0x07,  0xFE,  0x00,  0x00, 	/* 27FC0 */
+	0xB9,  0x00,  0x00,  0x00,  0x00,  0x7F,  0xFF,  0x42,  0x20,  0x42,  0x20,  0x42,  0x20,  0x42,  0x20,  0x44, 	/* 27FD0 */
+	0x20,  0x44,  0x22,  0x48,  0x22,  0x50,  0x1E,  0x40,  0x00,  0x40,  0x00,  0x7F,  0xFF,  0x00,  0x00,  0x00, 	/* 27FE0 */
+	0x00,  0xBA,  0x00,  0x00,  0x3F,  0xFE,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x10,  0x2E,  0x10, 	/* 27FF0 */
+	0x21,  0xA0,  0x20,  0x40,  0x20,  0xA0,  0x21,  0x10,  0x22,  0x08,  0x24,  0x08,  0x28,  0x00,  0x3F,  0xFF, 	/* 28000 */
+	0x00,  0x00,  0xBB,  0x00,  0x00,  0x3F,  0xFE,  0x21,  0x00,  0x21,  0x00,  0x23,  0xFC,  0x24,  0x40,  0x28, 	/* 28010 */
+	0x40,  0x3F,  0xFE,  0x20,  0xA0,  0x20,  0x90,  0x21,  0x08,  0x22,  0x04,  0x24,  0x04,  0x28,  0x00,  0x3F, 	/* 28020 */
+	0xFE,  0x00,  0x00,  0xBF,  0x00,  0x00,  0x3F,  0xFE,  0x20,  0x00,  0x22,  0x10,  0x3F,  0xFE,  0x22,  0x90, 	/* 28030 */
+	0x20,  0x80,  0x3F,  0xFE,  0x21,  0x00,  0x23,  0xF8,  0x26,  0x08,  0x3A,  0x08,  0x23,  0xF8,  0x20,  0x00, 	/* 28040 */
+	0x3F,  0xFE,  0x00,  0x00,  0x80,  0x00,  0x00,  0x7F,  0xFF,  0x20,  0x00,  0x23,  0xF0,  0x22,  0x10,  0x22, 	/* 28050 */
+	0x10,  0x23,  0xF0,  0x20,  0x00,  0x2F,  0x3C,  0x29,  0x24,  0x29,  0x24,  0x29,  0x24,  0x2F,  0x3C,  0x20, 	/* 28060 */
+	0x00,  0x3F,  0xFF,  0x00,  0x00,  0x81,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80, 	/* 28070 */
+	0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80, 	/* 28080 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x83,  0x00,  0x08,  0x00,  0x30,  0x1F,  0xC0,  0x00,  0x80,  0x00, 	/* 28090 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 280A0 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x85,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88, 	/* 280B0 */
+	0x08,  0x88,  0x08,  0x88,  0x7F,  0xFF,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88, 	/* 280C0 */
+	0x10,  0x88,  0x10,  0x88,  0x20,  0x88,  0x40,  0x88,  0x86,  0x02,  0x00,  0x02,  0x00,  0x7F,  0xE0,  0x02, 	/* 280D0 */
+	0x20,  0x02,  0x20,  0x04,  0x20,  0x08,  0x22,  0x11,  0x12,  0x61,  0x0E,  0x01,  0x00,  0x7F,  0xFE,  0x01, 	/* 280E0 */
+	0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x87,  0x00,  0x10,  0x00,  0x90,  0x03,  0x10, 	/* 280F0 */
+	0x3C,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10, 	/* 28100 */
+	0x04,  0x10,  0x08,  0x10,  0x08,  0x10,  0x10,  0x10,  0x20,  0x10,  0x88,  0x04,  0x00,  0x04,  0x00,  0x07, 	/* 28110 */
+	0xFC,  0x08,  0x80,  0x08,  0x80,  0x10,  0x80,  0x20,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00, 	/* 28120 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x89,  0x00,  0x80,  0x00,  0x80, 	/* 28130 */
+	0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x04,  0x88,  0x04,  0x08,  0x04,  0x08,  0x7F,  0xFF,  0x04,  0x08, 	/* 28140 */
+	0x04,  0x08,  0x04,  0x08,  0x08,  0x08,  0x08,  0x08,  0x10,  0x08,  0x20,  0x08,  0x8A,  0x00,  0x80,  0x00, 	/* 28150 */
+	0x84,  0x10,  0x84,  0x08,  0x88,  0x04,  0x90,  0x04,  0x80,  0x3F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 28160 */
+	0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x8D,  0x00,  0x02, 	/* 28170 */
+	0x7F,  0x82,  0x00,  0x82,  0x00,  0x82,  0x00,  0x82,  0x00,  0x82,  0x00,  0x82,  0x3F,  0xFE,  0x20,  0x80, 	/* 28180 */
+	0x20,  0x80,  0x20,  0x80,  0x20,  0x80,  0x20,  0x80,  0x20,  0x80,  0x20,  0xFF,  0x20,  0x00,  0x91,  0x00, 	/* 28190 */
+	0x80,  0x01,  0x00,  0x0F,  0xFC,  0x08,  0x84,  0x08,  0x84,  0x0F,  0xFC,  0x08,  0x84,  0x08,  0x84,  0x0F, 	/* 281A0 */
+	0xFC,  0x02,  0x40,  0x04,  0x40,  0x7F,  0xFF,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0x92, 	/* 281B0 */
+	0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x04,  0x10,  0x04,  0x10,  0x06,  0x18,  0x09,  0x24,  0x10,  0xC2, 	/* 281C0 */
+	0x20,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80, 	/* 281D0 */
+	0x93,  0x00,  0x80,  0x00,  0x80,  0x00,  0xFC,  0x00,  0x80,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F, 	/* 281E0 */
+	0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 281F0 */
+	0x80,  0x94,  0x10,  0x40,  0x10,  0x40,  0x13,  0xFC,  0x10,  0x44,  0x10,  0x44,  0x7C,  0x84,  0x11,  0x18, 	/* 28200 */
+	0x12,  0x08,  0x12,  0x08,  0x1F,  0xFF,  0x12,  0x49,  0x12,  0x49,  0x12,  0x49,  0x14,  0x49,  0x14,  0x51, 	/* 28210 */
+	0x19,  0xA6,  0x97,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x12, 	/* 28220 */
+	0x24,  0x11,  0x44,  0x17,  0xF4,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84,  0x10, 	/* 28230 */
+	0x84,  0x10,  0x8C,  0x98,  0x09,  0x08,  0x04,  0x88,  0x04,  0x90,  0x0F,  0xFC,  0x08,  0x84,  0x08,  0x84, 	/* 28240 */
+	0x0F,  0xFC,  0x08,  0x84,  0x08,  0x84,  0x0F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80, 	/* 28250 */
+	0x00,  0x80,  0x00,  0x80,  0x9A,  0x10,  0x28,  0x10,  0x24,  0x17,  0xFF,  0x10,  0x20,  0x11,  0xFE,  0x11, 	/* 28260 */
+	0x22,  0x7D,  0xFE,  0x11,  0x22,  0x11,  0xFE,  0x10,  0x08,  0x17,  0xFF,  0x11,  0x08,  0x10,  0x88,  0x10, 	/* 28270 */
+	0x88,  0x10,  0x08,  0x10,  0x18,  0x9C,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00, 	/* 28280 */
+	0x03,  0x80,  0x02,  0x40,  0x02,  0x20,  0x02,  0x10,  0x02,  0x08,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00, 	/* 28290 */
+	0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x9E,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00, 	/* 282A0 */
+	0x80,  0x00,  0x80,  0x00,  0xC0,  0x00,  0xB0,  0x00,  0x88,  0x00,  0x84,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 282B0 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0xA0,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 282C0 */
+	0x01,  0xFF,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x1F,  0xF8,  0x10,  0x08,  0x10,  0x08, 	/* 282D0 */
+	0x10,  0x08,  0x10,  0x08,  0x1F,  0xF8,  0x00,  0x00,  0xA6,  0x04,  0x10,  0x04,  0x10,  0x3F,  0x90,  0x04, 	/* 282E0 */
+	0x10,  0x04,  0x10,  0x04,  0x18,  0x7F,  0xD4,  0x04,  0x12,  0x04,  0x12,  0x3F,  0x90,  0x04,  0x10,  0x04, 	/* 282F0 */
+	0x10,  0x05,  0xD0,  0x0E,  0x10,  0x70,  0x10,  0x00,  0x10,  0xA9,  0x00,  0x00,  0x0F,  0xF0,  0x08,  0x10, 	/* 28300 */
+	0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10, 	/* 28310 */
+	0x08,  0xE0,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0xAE,  0x00,  0x08,  0x00,  0x70,  0x1F, 	/* 28320 */
+	0x80,  0x10,  0x00,  0x10,  0x00,  0x1F,  0xFF,  0x10,  0x00,  0x13,  0xF8,  0x12,  0x08,  0x12,  0x08,  0x12, 	/* 28330 */
+	0x08,  0x12,  0x38,  0x22,  0x02,  0x22,  0x02,  0x41,  0x02,  0x00,  0xFE,  0xAF,  0x02,  0x00,  0x0C,  0x00, 	/* 28340 */
+	0x30,  0x7C,  0x22,  0x44,  0x22,  0x44,  0x22,  0x44,  0x22,  0x44,  0x22,  0x44,  0x22,  0x44,  0x22,  0x44, 	/* 28350 */
+	0x3E,  0x44,  0x62,  0x44,  0x04,  0x58,  0x04,  0x40,  0x08,  0x40,  0x10,  0x40,  0xB0,  0x01,  0x00,  0x06, 	/* 28360 */
+	0x00,  0x38,  0x7E,  0x20,  0x42,  0x20,  0x42,  0x20,  0x42,  0x3F,  0x42,  0x20,  0x42,  0x20,  0x42,  0x20, 	/* 28370 */
+	0x42,  0x20,  0x42,  0x3F,  0x5C,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0xB1,  0x04,  0x00, 	/* 28380 */
+	0x07,  0xF0,  0x08,  0x20,  0x10,  0x40,  0x3F,  0xFE,  0x50,  0x00,  0x10,  0x00,  0x13,  0xF8,  0x12,  0x08, 	/* 28390 */
+	0x12,  0x08,  0x12,  0x08,  0x12,  0x30,  0x22,  0x02,  0x22,  0x02,  0x41,  0x02,  0x00,  0xFE,  0xB3,  0x00, 	/* 283A0 */
+	0x00,  0x1F,  0xBE,  0x10,  0xA2,  0x10,  0xA2,  0x1F,  0xA2,  0x10,  0xA2,  0x10,  0xA2,  0x10,  0xA2,  0x1F, 	/* 283B0 */
+	0xA2,  0x14,  0x22,  0x12,  0x22,  0x11,  0x22,  0x16,  0xAC,  0x18,  0xA0,  0x60,  0x20,  0x00,  0x20,  0xB4, 	/* 283C0 */
+	0x04,  0x00,  0x04,  0x3E,  0x3F,  0xA2,  0x04,  0x22,  0x04,  0x22,  0x04,  0x22,  0x04,  0x22,  0x7F,  0xE2, 	/* 283D0 */
+	0x08,  0x22,  0x0A,  0x22,  0x09,  0x22,  0x11,  0x22,  0x13,  0xAC,  0x7C,  0xA0,  0x00,  0xA0,  0x00,  0x20, 	/* 283E0 */
+	0xB5,  0x02,  0x00,  0x04,  0x00,  0x18,  0x3E,  0x11,  0x22,  0x11,  0x22,  0x11,  0x22,  0x19,  0x32,  0x15, 	/* 283F0 */
+	0x2A,  0x15,  0x2A,  0x11,  0x22,  0x11,  0x22,  0x1F,  0x22,  0x62,  0x2C,  0x02,  0x20,  0x04,  0x20,  0x08, 	/* 28400 */
+	0x20,  0xB7,  0x04,  0x90,  0x04,  0x88,  0x08,  0x88,  0x3F,  0xFE,  0x00,  0x80,  0x01,  0x40,  0x7F,  0xFF, 	/* 28410 */
+	0x02,  0x20,  0x04,  0x10,  0x1F,  0xFC,  0x64,  0x13,  0x04,  0x10,  0x04,  0x60,  0x04,  0x04,  0x02,  0x04, 	/* 28420 */
+	0x01,  0xFC,  0xB8,  0x10,  0x00,  0x10,  0x3E,  0x1F,  0xA2,  0x14,  0x22,  0x24,  0x22,  0x44,  0x22,  0x7F, 	/* 28430 */
+	0xE2,  0x04,  0x22,  0x24,  0x22,  0x27,  0xA2,  0x24,  0x22,  0x24,  0x22,  0x27,  0xBC,  0x3C,  0x20,  0x60, 	/* 28440 */
+	0x20,  0x00,  0x20,  0xBB,  0x04,  0x00,  0x0A,  0x3E,  0x09,  0x22,  0x10,  0xA2,  0x24,  0xA2,  0x4A,  0x22, 	/* 28450 */
+	0x09,  0x22,  0x10,  0xA2,  0x10,  0xA2,  0x3F,  0x22,  0x51,  0x22,  0x11,  0x22,  0x11,  0x2C,  0x11,  0x20, 	/* 28460 */
+	0x1F,  0x20,  0x00,  0x20,  0xBF,  0x04,  0x00,  0x0B,  0xDE,  0x32,  0x52,  0x2A,  0x52,  0x2B,  0xD2,  0x2A, 	/* 28470 */
+	0x52,  0x2A,  0x52,  0x2B,  0xD2,  0x2A,  0x12,  0x2B,  0x12,  0x3A,  0x92,  0x6A,  0x52,  0x0B,  0xDC,  0x16, 	/* 28480 */
+	0x30,  0x10,  0x10,  0x20,  0x10,  0x82,  0x00,  0x00,  0x1F,  0xFE,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00, 	/* 28490 */
+	0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x20,  0x00, 	/* 284A0 */
+	0x20,  0x00,  0x40,  0x00,  0x00,  0x00,  0x84,  0x00,  0x00,  0x1F,  0xFF,  0x10,  0x00,  0x10,  0x00,  0x13, 	/* 284B0 */
+	0xF8,  0x12,  0x08,  0x12,  0x08,  0x12,  0x08,  0x12,  0x08,  0x12,  0x08,  0x12,  0x30,  0x12,  0x02,  0x22, 	/* 284C0 */
+	0x02,  0x21,  0x02,  0x40,  0xFE,  0x00,  0x00,  0x96,  0x00,  0x00,  0x1F,  0xFF,  0x10,  0x04,  0x12,  0x84, 	/* 284D0 */
+	0x12,  0x48,  0x12,  0x12,  0x1F,  0xE2,  0x12,  0x04,  0x12,  0x09,  0x13,  0x11,  0x15,  0x22,  0x15,  0x04, 	/* 284E0 */
+	0x25,  0x08,  0x29,  0x31,  0x49,  0x01,  0x10,  0xFF,  0x98,  0x00,  0x00,  0x1F,  0xFF,  0x10,  0x00,  0x13, 	/* 284F0 */
+	0xFC,  0x12,  0x44,  0x13,  0xFC,  0x12,  0x44,  0x12,  0x44,  0x13,  0xFC,  0x10,  0x40,  0x10,  0x40,  0x17, 	/* 28500 */
+	0xFE,  0x20,  0x40,  0x20,  0x40,  0x5F,  0xFF,  0x00,  0x00,  0x9A,  0x00,  0x00,  0x1F,  0xFE,  0x10,  0x00, 	/* 28510 */
+	0x13,  0xF8,  0x12,  0x08,  0x13,  0xF8,  0x12,  0x08,  0x13,  0xF8,  0x10,  0x00,  0x17,  0xF8,  0x10,  0x20, 	/* 28520 */
+	0x10,  0x40,  0x2F,  0xFF,  0x20,  0x40,  0x40,  0x40,  0x00,  0xC0,  0x9F,  0x00,  0x00,  0x1F,  0xFF,  0x10, 	/* 28530 */
+	0x40,  0x10,  0x80,  0x13,  0xF8,  0x12,  0x08,  0x13,  0xF8,  0x12,  0x08,  0x12,  0x08,  0x13,  0xF8,  0x10, 	/* 28540 */
+	0x40,  0x12,  0x48,  0x22,  0x44,  0x24,  0x42,  0x48,  0x42,  0x00,  0xC0,  0xA0,  0x00,  0x00,  0x1F,  0xFF, 	/* 28550 */
+	0x10,  0x00,  0x17,  0xC2,  0x14,  0x52,  0x14,  0x52,  0x17,  0xD2,  0x14,  0x52,  0x14,  0x52,  0x17,  0xD2, 	/* 28560 */
+	0x14,  0x52,  0x14,  0x52,  0x27,  0xC2,  0x22,  0x82,  0x44,  0x42,  0x08,  0x06,  0xA5,  0x00,  0x00,  0x1F, 	/* 28570 */
+	0xFF,  0x14,  0x50,  0x12,  0x50,  0x12,  0x90,  0x1F,  0xDF,  0x11,  0x21,  0x15,  0x6A,  0x15,  0x48,  0x15, 	/* 28580 */
+	0x48,  0x15,  0x48,  0x17,  0xD4,  0x22,  0x14,  0x22,  0x24,  0x44,  0x42,  0x08,  0x81,  0xA6,  0x00,  0x00, 	/* 28590 */
+	0x1F,  0xFF,  0x10,  0x00,  0x1F,  0xFF,  0x10,  0x40,  0x13,  0xFC,  0x12,  0x04,  0x13,  0xFC,  0x12,  0x04, 	/* 285A0 */
+	0x13,  0xFC,  0x10,  0x40,  0x10,  0xFC,  0x23,  0x88,  0x2C,  0x70,  0x40,  0xD8,  0x1F,  0x07,  0xA8,  0x00, 	/* 285B0 */
+	0x00,  0x1F,  0xFF,  0x10,  0x00,  0x10,  0x04,  0x1F,  0xC4,  0x10,  0x04,  0x17,  0xFF,  0x14,  0x84,  0x14, 	/* 285C0 */
+	0xC4,  0x17,  0xA4,  0x10,  0x24,  0x14,  0x84,  0x22,  0x84,  0x23,  0x64,  0x43,  0x84,  0x1C,  0x0C,  0xA9, 	/* 285D0 */
+	0x00,  0x00,  0x1F,  0xFF,  0x10,  0x00,  0x17,  0xBE,  0x14,  0xA8,  0x14,  0xA8,  0x17,  0xA8,  0x14,  0xA8, 	/* 285E0 */
+	0x14,  0xFF,  0x17,  0x88,  0x14,  0x18,  0x15,  0x18,  0x24,  0xA8,  0x25,  0xA9,  0x46,  0x49,  0x18,  0x87, 	/* 285F0 */
+	0xAD,  0x00,  0x00,  0x3F,  0xFF,  0x20,  0x00,  0x2F,  0x8A,  0x28,  0x89,  0x2F,  0x88,  0x28,  0xFF,  0x2F, 	/* 28600 */
+	0x88,  0x20,  0x08,  0x2F,  0x8C,  0x28,  0x94,  0x2F,  0x94,  0x28,  0x94,  0x2F,  0xA2,  0x48,  0xC2,  0x49, 	/* 28610 */
+	0x81,  0xAE,  0x00,  0x00,  0x1F,  0xFF,  0x10,  0x02,  0x14,  0x84,  0x14,  0x98,  0x1F,  0xF0,  0x14,  0x9F, 	/* 28620 */
+	0x17,  0x92,  0x14,  0x92,  0x17,  0x92,  0x14,  0x92,  0x14,  0x92,  0x3F,  0xE2,  0x25,  0x22,  0x48,  0xC2, 	/* 28630 */
+	0x10,  0x82,  0xB0,  0x00,  0x00,  0x3F,  0xFF,  0x21,  0x08,  0x25,  0x48,  0x25,  0x48,  0x29,  0x2F,  0x21, 	/* 28640 */
+	0x12,  0x2F,  0xD2,  0x28,  0x52,  0x2B,  0xEA,  0x2A,  0xCA,  0x2A,  0xC4,  0x2B,  0xC4,  0x28,  0x4A,  0x48, 	/* 28650 */
+	0x52,  0x08,  0xE1,  0xB3,  0x08,  0x84,  0x04,  0x48,  0x1F,  0xFF,  0x10,  0x10,  0x17,  0xD0,  0x11,  0x10, 	/* 28660 */
+	0x1F,  0xDF,  0x14,  0xA4,  0x17,  0xA4,  0x14,  0xD4,  0x17,  0x94,  0x14,  0x88,  0x24,  0xC8,  0x27,  0x94, 	/* 28670 */
+	0x5C,  0xA2,  0x00,  0xC1,  0xB6,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01, 	/* 28680 */
+	0x00,  0x01,  0x00,  0x02,  0x00,  0x02,  0x20,  0x02,  0x10,  0x02,  0x08,  0x04,  0x08,  0x04,  0x3C,  0x09, 	/* 28690 */
+	0xC4,  0x7E,  0x02,  0x00,  0x02,  0xBB,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80, 	/* 286A0 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x00,  0x01,  0x20,  0x02,  0x10,  0x02,  0x08, 	/* 286B0 */
+	0x04,  0xF8,  0x3F,  0x04,  0x00,  0x04,  0x82,  0x01,  0x00,  0x01,  0x60,  0x02,  0x18,  0x1F,  0xE4,  0x01, 	/* 286C0 */
+	0x00,  0x7F,  0xFF,  0x02,  0x20,  0x04,  0x50,  0x19,  0x8C,  0x6E,  0x23,  0x00,  0x40,  0x01,  0x88,  0x1E, 	/* 286D0 */
+	0x10,  0x00,  0x60,  0x01,  0x80,  0x1E,  0x00,  0x83,  0x01,  0x40,  0x02,  0x30,  0x1F,  0xE8,  0x08,  0x08, 	/* 286E0 */
+	0x0C,  0x8C,  0x12,  0x92,  0x7D,  0x7D,  0x02,  0x20,  0x04,  0x90,  0x19,  0x1C,  0x66,  0x23,  0x18,  0xC8, 	/* 286F0 */
+	0x03,  0x10,  0x1C,  0x60,  0x01,  0x80,  0x1E,  0x00,  0x88,  0x00,  0x00,  0x00,  0x00,  0x3F,  0xFC,  0x04, 	/* 28700 */
+	0x04,  0x04,  0x04,  0x04,  0x08,  0x02,  0x08,  0x02,  0x10,  0x01,  0x10,  0x00,  0xA0,  0x00,  0xC0,  0x01, 	/* 28710 */
+	0x40,  0x02,  0x20,  0x04,  0x10,  0x18,  0x0C,  0x60,  0x03,  0x89,  0x00,  0x00,  0x00,  0x00,  0x3F,  0xF8, 	/* 28720 */
+	0x09,  0x08,  0x08,  0x88,  0x04,  0x90,  0x04,  0x90,  0x02,  0x20,  0x02,  0x20,  0x01,  0x40,  0x00,  0x80, 	/* 28730 */
+	0x01,  0x40,  0x02,  0x20,  0x04,  0x10,  0x18,  0x0C,  0x60,  0x03,  0x8A,  0x00,  0x00,  0x3F,  0xE0,  0x04, 	/* 28740 */
+	0x20,  0x04,  0x40,  0x04,  0x40,  0x06,  0xF0,  0x06,  0x10,  0x05,  0x10,  0x05,  0x10,  0x08,  0xA0,  0x08, 	/* 28750 */
+	0x60,  0x08,  0x40,  0x10,  0xA0,  0x11,  0x10,  0x22,  0x08,  0x4C,  0x06,  0x8B,  0x01,  0x00,  0x01,  0x00, 	/* 28760 */
+	0x01,  0x00,  0x7F,  0xFF,  0x01,  0x00,  0x01,  0x00,  0x03,  0xF0,  0x02,  0x10,  0x03,  0x10,  0x05,  0x20, 	/* 28770 */
+	0x04,  0xA0,  0x08,  0x40,  0x10,  0xA0,  0x21,  0x10,  0x46,  0x0C,  0x18,  0x03,  0x8C,  0x00,  0x00,  0x7F, 	/* 28780 */
+	0xFC,  0x02,  0x04,  0x02,  0x44,  0x42,  0x44,  0x22,  0x44,  0x12,  0x44,  0x0C,  0x28,  0x04,  0x28,  0x06, 	/* 28790 */
+	0x10,  0x0A,  0x10,  0x09,  0x28,  0x11,  0x48,  0x10,  0x84,  0x23,  0x02,  0x4C,  0x01,  0x8D,  0x00,  0x00, 	/* 287A0 */
+	0x1F,  0xFE,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x1F,  0xF8,  0x12,  0x08,  0x12,  0x08,  0x11,  0x10, 	/* 287B0 */
+	0x11,  0x10,  0x10,  0xA0,  0x10,  0x40,  0x10,  0xA0,  0x21,  0x10,  0x26,  0x0C,  0x58,  0x03,  0x8E,  0x04, 	/* 287C0 */
+	0x00,  0x04,  0x00,  0x27,  0xFC,  0x24,  0x84,  0x24,  0x84,  0x24,  0x84,  0x24,  0x84,  0x24,  0x48,  0x24, 	/* 287D0 */
+	0x48,  0x24,  0x30,  0x26,  0x30,  0x3C,  0x28,  0xC4,  0x48,  0x04,  0x84,  0x05,  0x02,  0x04,  0x01,  0x94, 	/* 287E0 */
+	0x04,  0x00,  0x04,  0x00,  0x04,  0xFC,  0x07,  0x44,  0x04,  0x44,  0x04,  0x24,  0x7F,  0xA4,  0x04,  0x28, 	/* 287F0 */
+	0x04,  0x28,  0x15,  0x18,  0x15,  0x10,  0x24,  0x98,  0x24,  0xA8,  0x44,  0x44,  0x04,  0x82,  0x0D,  0x01, 	/* 28800 */
+	0x96,  0x00,  0x00,  0x7F,  0x80,  0x11,  0x7E,  0x11,  0x22,  0x11,  0x22,  0x1F,  0x22,  0x11,  0x22,  0x11, 	/* 28810 */
+	0x14,  0x1F,  0x14,  0x11,  0x18,  0x11,  0x08,  0x11,  0x14,  0x1F,  0x24,  0x61,  0x42,  0x01,  0x82,  0x01, 	/* 28820 */
+	0x01,  0x97,  0x00,  0x08,  0x00,  0x70,  0x7F,  0x88,  0x12,  0x08,  0x09,  0x10,  0x09,  0x20,  0x7F,  0xFE, 	/* 28830 */
+	0x40,  0x02,  0x5F,  0xF2,  0x04,  0x10,  0x02,  0x20,  0x01,  0x40,  0x00,  0x80,  0x03,  0x60,  0x0C,  0x18, 	/* 28840 */
+	0x70,  0x06,  0x99,  0x04,  0x00,  0x04,  0xFC,  0x0A,  0x04,  0x09,  0x04,  0x10,  0x84,  0x3F,  0x24,  0x44, 	/* 28850 */
+	0x24,  0x04,  0x28,  0x7F,  0xA8,  0x04,  0x18,  0x15,  0x10,  0x14,  0x98,  0x24,  0xA8,  0x24,  0x44,  0x44, 	/* 28860 */
+	0x82,  0x0D,  0x01,  0x9B,  0x08,  0x00,  0x0A,  0xFF,  0x4A,  0x80,  0x2A,  0x80,  0x2C,  0x80,  0x08,  0xFC, 	/* 28870 */
+	0x7F,  0xA4,  0x08,  0xA4,  0x08,  0xA4,  0x0E,  0x94,  0x78,  0x98,  0x08,  0x88,  0x11,  0x14,  0x11,  0x24, 	/* 28880 */
+	0x22,  0x42,  0x45,  0x81,  0x9F,  0x01,  0x00,  0x05,  0x00,  0x19,  0x78,  0x11,  0x08,  0x11,  0x08,  0x1D, 	/* 28890 */
+	0x78,  0x11,  0x08,  0x11,  0x08,  0x1F,  0xF8,  0x01,  0x00,  0x7F,  0xF8,  0x08,  0x10,  0x06,  0x20,  0x01, 	/* 288A0 */
+	0xC0,  0x0E,  0x38,  0x70,  0x07,  0xA1,  0x08,  0x00,  0x0F,  0x7C,  0x08,  0x04,  0x7F,  0xA4,  0x40,  0xA4, 	/* 288B0 */
+	0x3F,  0x24,  0x05,  0x24,  0x2C,  0xA4,  0x4A,  0x14,  0x1F,  0x98,  0x31,  0x48,  0x5F,  0x18,  0x11,  0x14, 	/* 288C0 */
+	0x1F,  0x24,  0x11,  0xC2,  0x1F,  0x01,  0xA2,  0x09,  0x48,  0x05,  0x50,  0x7F,  0xFF,  0x02,  0x20,  0x1F, 	/* 288D0 */
+	0xFC,  0x00,  0x80,  0x0F,  0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x11,  0x00,  0x1F,  0x7C,  0x11,  0x24,  0x1F, 	/* 288E0 */
+	0x14,  0x11,  0x08,  0x7F,  0x34,  0x01,  0xC3,  0xA3,  0x00,  0x00,  0x00,  0x00,  0x3F,  0xFC,  0x20,  0x04, 	/* 288F0 */
+	0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04, 	/* 28900 */
+	0x20,  0x04,  0x3F,  0xFC,  0x20,  0x04,  0x00,  0x00,  0xA4,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F, 	/* 28910 */
+	0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x08, 	/* 28920 */
+	0x08,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0xA5,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00, 	/* 28930 */
+	0x0F,  0xFE,  0x08,  0x02,  0x10,  0x02,  0x27,  0xE2,  0x44,  0x22,  0x04,  0x22,  0x04,  0x22,  0x04,  0x22, 	/* 28940 */
+	0x07,  0xE2,  0x00,  0x02,  0x00,  0x02,  0x00,  0x04,  0x00,  0x18,  0xA8,  0x00,  0x00,  0x01,  0xFE,  0x3E, 	/* 28950 */
+	0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x42,  0x22, 	/* 28960 */
+	0x42,  0x3E,  0x42,  0x00,  0x82,  0x01,  0x02,  0x02,  0x04,  0x04,  0x18,  0xA9,  0x00,  0x00,  0x3E,  0x7E, 	/* 28970 */
+	0x22,  0x42,  0x22,  0x42,  0x22,  0x42,  0x22,  0x42,  0x22,  0x42,  0x22,  0x42,  0x22,  0x42,  0x22,  0x42, 	/* 28980 */
+	0x22,  0x42,  0x3E,  0x5C,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0xAA,  0x00,  0x00,  0x00, 	/* 28990 */
+	0x00,  0x1F,  0xF8,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x1F, 	/* 289A0 */
+	0xF8,  0x00,  0x00,  0x04,  0x20,  0x04,  0x10,  0x08,  0x08,  0x10,  0x04,  0x20,  0x04,  0xAB,  0x00,  0x04, 	/* 289B0 */
+	0x00,  0x04,  0x3E,  0x44,  0x22,  0x44,  0x22,  0x44,  0x22,  0x44,  0x22,  0x44,  0x22,  0x44,  0x22,  0x44, 	/* 289C0 */
+	0x22,  0x44,  0x22,  0x47,  0x3E,  0x7C,  0x03,  0xC4,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0xAC,  0x00, 	/* 289D0 */
+	0x00,  0x7F,  0xFE,  0x01,  0x02,  0x01,  0x02,  0x02,  0x02,  0x02,  0x02,  0x04,  0x02,  0x18,  0x0C,  0x60, 	/* 289E0 */
+	0x00,  0x0F,  0xFC,  0x08,  0x04,  0x08,  0x04,  0x08,  0x04,  0x08,  0x04,  0x0F,  0xFC,  0x00,  0x00,  0xAD, 	/* 289F0 */
+	0x00,  0xF8,  0x00,  0x08,  0x7C,  0x08,  0x44,  0x08,  0x44,  0x88,  0x44,  0x88,  0x44,  0x88,  0x44,  0x88, 	/* 28A00 */
+	0x44,  0x88,  0x44,  0x88,  0x44,  0x88,  0x7D,  0x08,  0x01,  0x04,  0x02,  0x04,  0x04,  0x02,  0x08,  0x01, 	/* 28A10 */
+	0xAE,  0x00,  0x00,  0x03,  0xFF,  0x7C,  0x10,  0x44,  0x10,  0x44,  0x10,  0x44,  0x10,  0x44,  0x10,  0x44, 	/* 28A20 */
+	0x10,  0x44,  0x10,  0x44,  0x10,  0x44,  0x10,  0x7C,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00, 	/* 28A30 */
+	0x30,  0xAF,  0x00,  0x00,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x08,  0x00,  0x08,  0x0F,  0xC8,  0x08,  0x48, 	/* 28A40 */
+	0x08,  0x48,  0x08,  0x48,  0x08,  0x48,  0x0F,  0xC8,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08, 	/* 28A50 */
+	0x00,  0x18,  0xB0,  0x01,  0x00,  0x01,  0x00,  0x02,  0x20,  0x02,  0x10,  0x04,  0x08,  0x08,  0xFC,  0x7F, 	/* 28A60 */
+	0x04,  0x00,  0x02,  0x00,  0x02,  0x1F,  0xF8,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x1F, 	/* 28A70 */
+	0xF8,  0x00,  0x00,  0xB1,  0x00,  0x80,  0x00,  0x80,  0x7C,  0x80,  0x44,  0x84,  0x44,  0x88,  0x44,  0x90, 	/* 28A80 */
+	0x44,  0xA0,  0x44,  0xC0,  0x47,  0x80,  0x44,  0x80,  0x44,  0x80,  0x44,  0x80,  0x7C,  0x82,  0x00,  0x82, 	/* 28A90 */
+	0x00,  0x42,  0x00,  0x3E,  0xB2,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x10,  0x84,  0x10, 	/* 28AA0 */
+	0x84,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x00,  0x80,  0x04,  0x80,  0x03,  0x00,  0x01,  0x80,  0x02, 	/* 28AB0 */
+	0x60,  0x0C,  0x18,  0x30,  0x07,  0xB3,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x02,  0x00, 	/* 28AC0 */
+	0x02,  0x00,  0x02,  0x00,  0x04,  0x00,  0x07,  0xF8,  0x0C,  0x08,  0x14,  0x08,  0x24,  0x08,  0x44,  0x08, 	/* 28AD0 */
+	0x04,  0x08,  0x07,  0xF8,  0x00,  0x00,  0xB6,  0x00,  0x10,  0x00,  0x10,  0x3E,  0x10,  0x22,  0x10,  0x22, 	/* 28AE0 */
+	0x10,  0x22,  0x10,  0x23,  0xFF,  0x22,  0x10,  0x22,  0x10,  0x22,  0x10,  0x22,  0x10,  0x3E,  0x10,  0x00, 	/* 28AF0 */
+	0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0xB7,  0x00,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10, 	/* 28B00 */
+	0x08,  0x10,  0x0F,  0xF0,  0x00,  0x00,  0x7F,  0xFF,  0x04,  0x00,  0x04,  0x00,  0x07,  0xF0,  0x08,  0x10, 	/* 28B10 */
+	0x00,  0x10,  0x00,  0x10,  0x00,  0x20,  0x00,  0xC0,  0xB8,  0x00,  0x00,  0x7F,  0xFC,  0x00,  0x04,  0x00, 	/* 28B20 */
+	0x04,  0x3F,  0xE4,  0x00,  0x04,  0x00,  0x04,  0x1F,  0xC4,  0x10,  0x44,  0x10,  0x44,  0x10,  0x44,  0x1F, 	/* 28B30 */
+	0xC4,  0x00,  0x04,  0x00,  0x04,  0x00,  0x08,  0x00,  0x30,  0xBA,  0x00,  0xE0,  0x00,  0x20,  0x7C,  0x20, 	/* 28B40 */
+	0x44,  0x20,  0x44,  0x20,  0x44,  0x20,  0x44,  0x20,  0x44,  0x30,  0x44,  0x30,  0x44,  0x50,  0x44,  0x50, 	/* 28B50 */
+	0x7C,  0x88,  0x00,  0x88,  0x01,  0x04,  0x06,  0x02,  0x18,  0x01,  0x81,  0x00,  0x00,  0x01,  0xFC,  0x7C, 	/* 28B60 */
+	0x20,  0x44,  0x20,  0x44,  0x20,  0x44,  0x20,  0x44,  0x20,  0x47,  0xFF,  0x44,  0x20,  0x44,  0x20,  0x44, 	/* 28B70 */
+	0x20,  0x7C,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x60,  0x83,  0x00,  0x80,  0x00,  0x80, 	/* 28B80 */
+	0x78,  0x80,  0x49,  0xFF,  0x49,  0x00,  0x49,  0x00,  0x4A,  0xFC,  0x4C,  0x08,  0x48,  0x10,  0x48,  0x20, 	/* 28B90 */
+	0x48,  0x40,  0x78,  0x80,  0x01,  0x02,  0x01,  0x02,  0x01,  0x02,  0x00,  0xFE,  0x84,  0x02,  0x00,  0x02, 	/* 28BA0 */
+	0x00,  0x07,  0xF8,  0x04,  0x10,  0x0A,  0x20,  0x11,  0x40,  0x20,  0xC0,  0x03,  0x20,  0x04,  0x10,  0x18, 	/* 28BB0 */
+	0x0C,  0x6F,  0xFB,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x88,  0x00,  0x80, 	/* 28BC0 */
+	0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x04,  0x10,  0x18,  0x0C,  0x67,  0xF3,  0x00,  0x00,  0x00,  0x00, 	/* 28BD0 */
+	0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x89,  0x00, 	/* 28BE0 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00, 	/* 28BF0 */
+	0x00,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x8A, 	/* 28C00 */
+	0x00,  0x00,  0x07,  0xF0,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x07,  0xF0,  0x00,  0x80, 	/* 28C10 */
+	0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x98,  0x10,  0x80,  0x00,  0x80, 	/* 28C20 */
+	0x8B,  0x00,  0x08,  0x00,  0x08,  0x7C,  0x08,  0x44,  0x08,  0x47,  0xFF,  0x44,  0x08,  0x45,  0x08,  0x44, 	/* 28C30 */
+	0x88,  0x44,  0x48,  0x44,  0x48,  0x44,  0x08,  0x7C,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00, 	/* 28C40 */
+	0x18,  0x8C,  0x00,  0x00,  0x3F,  0xFE,  0x20,  0x02,  0x20,  0x02,  0x2F,  0xFA,  0x20,  0x02,  0x20,  0x02, 	/* 28C50 */
+	0x27,  0xF2,  0x24,  0x12,  0x24,  0x12,  0x24,  0x12,  0x27,  0xF2,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02, 	/* 28C60 */
+	0x20,  0x06,  0x8D,  0x01,  0x00,  0x01,  0x00,  0x01,  0xF8,  0x02,  0x08,  0x04,  0x10,  0x0A,  0x20,  0x11, 	/* 28C70 */
+	0x40,  0x20,  0x80,  0x01,  0x00,  0x07,  0xFE,  0x1A,  0x02,  0x62,  0x02,  0x02,  0x02,  0x02,  0x02,  0x03, 	/* 28C80 */
+	0xFE,  0x00,  0x00,  0x8E,  0x00,  0x04,  0x00,  0x38,  0x0F,  0xC0,  0x08,  0x00,  0x08,  0x00,  0x0F,  0xFF, 	/* 28C90 */
+	0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x0B,  0xFC,  0x0A,  0x04,  0x12,  0x04,  0x12,  0x04,  0x22,  0x04, 	/* 28CA0 */
+	0x43,  0xFC,  0x00,  0x00,  0x8F,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x1F,  0xF8,  0x10, 	/* 28CB0 */
+	0x88,  0x10,  0x88,  0x10,  0x88,  0x1F,  0xF8,  0x04,  0x80,  0x02,  0x80,  0x01,  0x00,  0x01,  0x80,  0x02, 	/* 28CC0 */
+	0x60,  0x0C,  0x18,  0x70,  0x06,  0x90,  0x00,  0x20,  0x00,  0x20,  0x7C,  0x20,  0x44,  0x20,  0x44,  0x20, 	/* 28CD0 */
+	0x44,  0x20,  0x47,  0xFE,  0x44,  0x20,  0x44,  0x20,  0x44,  0x20,  0x44,  0x20,  0x7C,  0x20,  0x00,  0x20, 	/* 28CE0 */
+	0x00,  0x20,  0x0F,  0xFF,  0x00,  0x00,  0x91,  0x01,  0x00,  0x01,  0x00,  0x02,  0x00,  0x04,  0x00,  0x3F, 	/* 28CF0 */
+	0xFE,  0x20,  0x02,  0x20,  0x02,  0x27,  0xF2,  0x24,  0x12,  0x24,  0x12,  0x24,  0x12,  0x27,  0xF2,  0x20, 	/* 28D00 */
+	0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x06,  0x9B,  0x00,  0x00,  0x1F,  0xF8,  0x01,  0x08,  0x01,  0x08, 	/* 28D10 */
+	0x7F,  0xFF,  0x01,  0x08,  0x01,  0x08,  0x1F,  0xF8,  0x02,  0x00,  0x02,  0x00,  0x07,  0xFC,  0x0C,  0x04, 	/* 28D20 */
+	0x14,  0x04,  0x24,  0x04,  0x47,  0xFC,  0x00,  0x00,  0x9D,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x04, 	/* 28D30 */
+	0x10,  0x02,  0x20,  0x01,  0x40,  0x00,  0x80,  0x03,  0x60,  0x0C,  0x18,  0x70,  0x07,  0x0F,  0xF8,  0x08, 	/* 28D40 */
+	0x08,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x9F,  0x00,  0x20,  0x00,  0x20,  0x7C,  0x50, 	/* 28D50 */
+	0x44,  0x50,  0x44,  0x88,  0x45,  0x04,  0x46,  0xFA,  0x44,  0x01,  0x44,  0x00,  0x45,  0xFC,  0x44,  0x04, 	/* 28D60 */
+	0x7C,  0x08,  0x00,  0x08,  0x00,  0x10,  0x00,  0x10,  0x00,  0x20,  0xA0,  0x00,  0x20,  0x00,  0x28,  0x3E, 	/* 28D70 */
+	0x24,  0x22,  0x24,  0x22,  0x20,  0x23,  0xFF,  0x22,  0x20,  0x22,  0x20,  0x22,  0x20,  0x22,  0x50,  0x3E, 	/* 28D80 */
+	0x50,  0x00,  0x88,  0x00,  0x88,  0x01,  0x04,  0x06,  0x02,  0x18,  0x01,  0xA6,  0x00,  0x00,  0x7F,  0xFF, 	/* 28D90 */
+	0x00,  0x40,  0x00,  0xE0,  0x01,  0x98,  0x06,  0x84,  0x18,  0x82,  0x60,  0x81,  0x00,  0x80,  0x0F,  0xF8, 	/* 28DA0 */
+	0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0xA9,  0x00,  0x78,  0x00, 	/* 28DB0 */
+	0x08,  0x78,  0x88,  0x48,  0x88,  0x48,  0x84,  0x49,  0x04,  0x49,  0xFE,  0x4A,  0x25,  0x4C,  0x24,  0x48, 	/* 28DC0 */
+	0x24,  0x48,  0x24,  0x78,  0x44,  0x00,  0x44,  0x00,  0x84,  0x01,  0x04,  0x02,  0x18,  0xAB,  0x00,  0x80, 	/* 28DD0 */
+	0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x07,  0xF0,  0x18,  0x0C,  0x60,  0x03,  0x0F,  0xF0,  0x00,  0x10, 	/* 28DE0 */
+	0x00,  0x20,  0x00,  0x40,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0xAC,  0x00, 	/* 28DF0 */
+	0x04,  0x00,  0x18,  0x7C,  0xE0,  0x44,  0x80,  0x44,  0x80,  0x44,  0xFF,  0x44,  0x88,  0x44,  0x88,  0x44, 	/* 28E00 */
+	0x88,  0x44,  0x88,  0x44,  0x88,  0x7D,  0x08,  0x01,  0x08,  0x02,  0x08,  0x04,  0x08,  0x00,  0x08,  0xAD, 	/* 28E10 */
+	0x00,  0x20,  0x00,  0x20,  0x7C,  0x20,  0x47,  0xFF,  0x44,  0x00,  0x44,  0x00,  0x44,  0xF8,  0x44,  0x88, 	/* 28E20 */
+	0x44,  0x88,  0x44,  0x88,  0x44,  0x88,  0x7C,  0x88,  0x00,  0x89,  0x01,  0x09,  0x02,  0x07,  0x04,  0x00, 	/* 28E30 */
+	0xAE,  0x00,  0x20,  0x00,  0x20,  0x7C,  0x40,  0x44,  0x50,  0x44,  0x4C,  0x44,  0x9A,  0x47,  0xE9,  0x44, 	/* 28E40 */
+	0x48,  0x44,  0x48,  0x44,  0x48,  0x44,  0x48,  0x7C,  0x88,  0x00,  0x88,  0x01,  0x09,  0x02,  0x09,  0x04, 	/* 28E50 */
+	0x07,  0xB6,  0x00,  0x20,  0x00,  0x20,  0x78,  0x20,  0x4B,  0xFE,  0x4A,  0x22,  0x4A,  0x22,  0x4A,  0x22, 	/* 28E60 */
+	0x4A,  0x22,  0x4A,  0x52,  0x4A,  0x52,  0x4A,  0x8A,  0x7B,  0x06,  0x02,  0x02,  0x02,  0x02,  0x02,  0x02, 	/* 28E70 */
+	0x02,  0x06,  0xB8,  0x00,  0x00,  0x01,  0xF8,  0x7C,  0x88,  0x44,  0x90,  0x44,  0x90,  0x44,  0xBC,  0x44, 	/* 28E80 */
+	0xC4,  0x44,  0xC4,  0x44,  0xA4,  0x45,  0x28,  0x7D,  0x28,  0x01,  0x10,  0x02,  0x28,  0x02,  0x44,  0x04, 	/* 28E90 */
+	0x82,  0x09,  0x01,  0xB9,  0x00,  0x80,  0x00,  0x80,  0x7C,  0x80,  0x44,  0xFE,  0x45,  0x02,  0x45,  0x24, 	/* 28EA0 */
+	0x46,  0x28,  0x44,  0x20,  0x44,  0x20,  0x44,  0x20,  0x44,  0x50,  0x7C,  0x50,  0x00,  0x88,  0x01,  0x04, 	/* 28EB0 */
+	0x06,  0x02,  0x18,  0x01,  0xBB,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x79,  0xFE,  0x49,  0x4A,  0x49, 	/* 28EC0 */
+	0x4A,  0x4A,  0x4A,  0x4A,  0x4A,  0x4C,  0x8A,  0x48,  0x92,  0x49,  0x12,  0x4A,  0x22,  0x78,  0x22,  0x00, 	/* 28ED0 */
+	0x42,  0x00,  0x84,  0x00,  0x18,  0xBC,  0x00,  0x08,  0x03,  0xE8,  0x78,  0x28,  0x48,  0x48,  0x48,  0x88, 	/* 28EE0 */
+	0x48,  0x88,  0x48,  0xA8,  0x48,  0xC8,  0x49,  0x88,  0x4E,  0x88,  0x48,  0x88,  0x78,  0x88,  0x00,  0x88, 	/* 28EF0 */
+	0x00,  0x89,  0x00,  0x89,  0x01,  0x87,  0xBD,  0x00,  0x20,  0x01,  0x20,  0x79,  0x20,  0x49,  0x20,  0x4B, 	/* 28F00 */
+	0xFE,  0x4A,  0x20,  0x4C,  0x20,  0x48,  0x20,  0x48,  0x20,  0x4F,  0xFF,  0x48,  0x20,  0x78,  0x20,  0x00, 	/* 28F10 */
+	0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0xBE,  0x00,  0x00,  0x3F,  0xFC,  0x01,  0x00,  0x01,  0x00, 	/* 28F20 */
+	0x1F,  0xF0,  0x02,  0x10,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFE,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08, 	/* 28F30 */
+	0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x80,  0x00,  0x00,  0x03,  0xFE,  0x78,  0x88,  0x48, 	/* 28F40 */
+	0x88,  0x48,  0x88,  0x48,  0x88,  0x48,  0x88,  0x4F,  0xFF,  0x48,  0x28,  0x48,  0x28,  0x78,  0x48,  0x00, 	/* 28F50 */
+	0x88,  0x01,  0x08,  0x02,  0x08,  0x04,  0x08,  0x00,  0x18,  0x82,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08, 	/* 28F60 */
+	0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x80,  0x00,  0x80,  0x01,  0x00,  0x1F,  0xFC,  0x10,  0x04, 	/* 28F70 */
+	0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x1F,  0xFC,  0x00,  0x00,  0x86,  0x00,  0x00,  0x0F,  0xF8,  0x08, 	/* 28F80 */
+	0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01, 	/* 28F90 */
+	0xC0,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0x88,  0x00,  0x00,  0x0F,  0xF8, 	/* 28FA0 */
+	0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x00,  0x00,  0x1F,  0xFC,  0x00,  0x80, 	/* 28FB0 */
+	0x00,  0x80,  0x0F,  0xF8,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFE,  0x00,  0x00,  0x89,  0x00,  0x00,  0x03, 	/* 28FC0 */
+	0xF8,  0x12,  0x08,  0x12,  0x08,  0x12,  0x08,  0x13,  0xF8,  0x10,  0x00,  0x10,  0x00,  0x1F,  0xF8,  0x00, 	/* 28FD0 */
+	0x08,  0x00,  0x08,  0x7F,  0xFF,  0x00,  0x00,  0x02,  0x10,  0x0C,  0x08,  0x30,  0x04,  0x8A,  0x00,  0x80, 	/* 28FE0 */
+	0x08,  0x80,  0x08,  0x80,  0x0F,  0xFC,  0x10,  0x80,  0x10,  0x80,  0x20,  0x80,  0x7F,  0xFF,  0x00,  0x00, 	/* 28FF0 */
+	0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x8E,  0x00, 	/* 29000 */
+	0x00,  0x01,  0xFC,  0x7D,  0x04,  0x45,  0x04,  0x45,  0x04,  0x45,  0x04,  0x45,  0xFC,  0x45,  0x20,  0x45, 	/* 29010 */
+	0x20,  0x45,  0x20,  0x7D,  0x10,  0x02,  0x10,  0x02,  0x08,  0x04,  0x04,  0x08,  0x02,  0x10,  0x01,  0x91, 	/* 29020 */
+	0x00,  0x10,  0x00,  0x60,  0x1F,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x40,  0x02,  0x20, 	/* 29030 */
+	0x04,  0x10,  0x18,  0x0C,  0x6F,  0xFB,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00, 	/* 29040 */
+	0x9F,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x7F,  0xFF,  0x48,  0x20,  0x48,  0x20,  0x48,  0x48,  0x4B, 	/* 29050 */
+	0x88,  0x48,  0x50,  0x48,  0x60,  0x48,  0x20,  0x48,  0x48,  0x78,  0x84,  0x01,  0x3C,  0x07,  0xC2,  0x00, 	/* 29060 */
+	0x02,  0xA8,  0x00,  0x00,  0x1F,  0xFE,  0x10,  0x42,  0x10,  0x42,  0x17,  0xFA,  0x10,  0x42,  0x10,  0x42, 	/* 29070 */
+	0x1F,  0xFE,  0x10,  0x02,  0x13,  0xF2,  0x12,  0x12,  0x12,  0x12,  0x12,  0x12,  0x23,  0xF2,  0x20,  0x02, 	/* 29080 */
+	0x40,  0x06,  0xAA,  0x00,  0x00,  0x01,  0xFC,  0x7D,  0x04,  0x45,  0x04,  0x45,  0x04,  0x45,  0x04,  0x45, 	/* 29090 */
+	0x04,  0x45,  0xFC,  0x44,  0x50,  0x44,  0x50,  0x7C,  0x50,  0x00,  0x90,  0x00,  0x90,  0x01,  0x11,  0x02, 	/* 290A0 */
+	0x11,  0x04,  0x0F,  0xB0,  0x04,  0x40,  0x04,  0x42,  0x14,  0x4C,  0x17,  0xF0,  0x14,  0x40,  0x14,  0x40, 	/* 290B0 */
+	0x14,  0x42,  0x17,  0x42,  0x1C,  0x3E,  0x60,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08, 	/* 290C0 */
+	0x0F,  0xF8,  0x00,  0x00,  0xB1,  0x00,  0x04,  0x00,  0x18,  0x7B,  0xE8,  0x4A,  0x08,  0x4A,  0x48,  0x4A, 	/* 290D0 */
+	0x48,  0x4A,  0x48,  0x4A,  0x48,  0x4A,  0x48,  0x4A,  0x48,  0x4A,  0x64,  0x7A,  0x54,  0x04,  0x54,  0x04, 	/* 290E0 */
+	0x5A,  0x0B,  0xEA,  0x10,  0x09,  0xB3,  0x00,  0x20,  0x00,  0x20,  0x78,  0x20,  0x4B,  0xFE,  0x48,  0x20, 	/* 290F0 */
+	0x48,  0x20,  0x48,  0x20,  0x4F,  0xFF,  0x48,  0x70,  0x48,  0x70,  0x48,  0xA8,  0x79,  0x24,  0x02,  0x22, 	/* 29100 */
+	0x04,  0x21,  0x00,  0x20,  0x00,  0x20,  0xB5,  0x00,  0x00,  0x07,  0xFF,  0x78,  0x04,  0x48,  0x04,  0x49, 	/* 29110 */
+	0xE4,  0x49,  0x24,  0x49,  0x24,  0x49,  0x24,  0x49,  0x24,  0x49,  0xE4,  0x48,  0x04,  0x48,  0x04,  0x78, 	/* 29120 */
+	0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x0C,  0xB6,  0x01,  0x00,  0x01,  0x3E,  0x79,  0x02,  0x4F,  0xC2, 	/* 29130 */
+	0x49,  0x52,  0x49,  0x52,  0x49,  0x52,  0x4A,  0x52,  0x4A,  0x54,  0x4F,  0xD4,  0x48,  0x88,  0x78,  0xCC, 	/* 29140 */
+	0x01,  0x14,  0x02,  0x22,  0x0C,  0x42,  0x00,  0x81,  0xB7,  0x00,  0x00,  0x01,  0xFE,  0x3D,  0x22,  0x25, 	/* 29150 */
+	0x22,  0x25,  0x22,  0x25,  0xFE,  0x25,  0x22,  0x25,  0x22,  0x25,  0x22,  0x25,  0xFE,  0x24,  0x20,  0x3C, 	/* 29160 */
+	0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0xBB,  0x00,  0x20,  0x00,  0x20,  0x3D,  0xFE, 	/* 29170 */
+	0x25,  0x22,  0x25,  0x22,  0x25,  0x22,  0x25,  0xFE,  0x25,  0x22,  0x25,  0x22,  0x25,  0x22,  0x25,  0xFE, 	/* 29180 */
+	0x3C,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0xBC,  0x00,  0x06,  0x00,  0x38,  0x7D, 	/* 29190 */
+	0xE0,  0x44,  0x22,  0x45,  0x22,  0x44,  0xA4,  0x44,  0xA8,  0x44,  0x20,  0x47,  0xFF,  0x44,  0x20,  0x44, 	/* 291A0 */
+	0x20,  0x7C,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x60,  0xBD,  0x00,  0x80,  0x00,  0x80, 	/* 291B0 */
+	0x01,  0x40,  0x02,  0x20,  0x04,  0x10,  0x1B,  0xEC,  0x60,  0x03,  0x00,  0x00,  0x1E,  0x7C,  0x12,  0x44, 	/* 291C0 */
+	0x12,  0x44,  0x12,  0x44,  0x12,  0x44,  0x1E,  0x58,  0x00,  0x40,  0x00,  0x40,  0x80,  0x00,  0x00,  0x00, 	/* 291D0 */
+	0xFC,  0x7C,  0x84,  0x44,  0x84,  0x44,  0x84,  0x44,  0xFC,  0x44,  0x84,  0x44,  0x84,  0x44,  0x84,  0x44, 	/* 291E0 */
+	0xFC,  0x7C,  0x84,  0x00,  0x84,  0x00,  0x84,  0x00,  0x84,  0x07,  0xFF,  0x00,  0x00,  0x84,  0x00,  0x20, 	/* 291F0 */
+	0x02,  0x22,  0x7A,  0x22,  0x4A,  0x22,  0x4A,  0x22,  0x4A,  0x22,  0x4B,  0xFE,  0x48,  0x20,  0x48,  0x20, 	/* 29200 */
+	0x4A,  0x22,  0x4A,  0x22,  0x7A,  0x22,  0x02,  0x22,  0x02,  0x22,  0x03,  0xFE,  0x00,  0x00,  0x86,  0x01, 	/* 29210 */
+	0x00,  0x01,  0x00,  0x79,  0xFE,  0x49,  0x02,  0x4A,  0x02,  0x4B,  0xF2,  0x4D,  0x12,  0x49,  0x12,  0x49, 	/* 29220 */
+	0x12,  0x49,  0xF2,  0x49,  0x04,  0x79,  0x18,  0x01,  0x01,  0x01,  0x01,  0x00,  0x81,  0x00,  0x7F,  0x8B, 	/* 29230 */
+	0x00,  0x80,  0x00,  0x80,  0x7C,  0x80,  0x44,  0xFF,  0x45,  0x20,  0x45,  0x20,  0x46,  0x20,  0x44,  0x3E, 	/* 29240 */
+	0x44,  0x20,  0x44,  0x20,  0x44,  0x20,  0x7C,  0x3E,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20, 	/* 29250 */
+	0x8C,  0x01,  0x00,  0x06,  0x00,  0x3C,  0x7E,  0x04,  0x42,  0x04,  0x42,  0x04,  0x42,  0x7F,  0xC2,  0x0C, 	/* 29260 */
+	0x42,  0x0E,  0x42,  0x15,  0x42,  0x14,  0xC2,  0x24,  0x42,  0x44,  0x7E,  0x04,  0x00,  0x04,  0x00,  0x04, 	/* 29270 */
+	0x00,  0x8E,  0x08,  0x10,  0x0F,  0x10,  0x09,  0x10,  0x12,  0x10,  0x32,  0x28,  0x4C,  0x44,  0x04,  0x82, 	/* 29280 */
+	0x0B,  0x00,  0x10,  0xC0,  0x20,  0x3F,  0x40,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8, 	/* 29290 */
+	0x00,  0x00,  0x8F,  0x00,  0x40,  0x00,  0x20,  0x00,  0x20,  0x78,  0x00,  0x49,  0xE2,  0x48,  0x22,  0x48, 	/* 292A0 */
+	0x34,  0x4F,  0xB4,  0x48,  0xB8,  0x49,  0x28,  0x49,  0x28,  0x7A,  0x24,  0x04,  0x22,  0x18,  0x21,  0x00, 	/* 292B0 */
+	0x20,  0x00,  0x60,  0x90,  0x00,  0x84,  0x00,  0x84,  0x78,  0x84,  0x48,  0x84,  0x49,  0x7F,  0x49,  0x04, 	/* 292C0 */
+	0x4B,  0x04,  0x4D,  0x44,  0x49,  0x24,  0x49,  0x24,  0x49,  0x04,  0x79,  0x04,  0x01,  0x04,  0x01,  0x04, 	/* 292D0 */
+	0x01,  0x04,  0x01,  0x0C,  0x92,  0x00,  0x00,  0x3E,  0x7C,  0x22,  0x44,  0x22,  0x44,  0x22,  0x44,  0x3E, 	/* 292E0 */
+	0x7C,  0x00,  0x00,  0x07,  0xE0,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x22,  0x04,  0x22,  0x08, 	/* 292F0 */
+	0x22,  0x10,  0x1E,  0x60,  0x00,  0xA2,  0x00,  0x00,  0x1F,  0x3E,  0x11,  0x22,  0x11,  0x22,  0x1F,  0x3E, 	/* 29300 */
+	0x00,  0x00,  0x0F,  0xFC,  0x00,  0x00,  0x7F,  0xFF,  0x01,  0x00,  0x01,  0x00,  0x03,  0xF8,  0x02,  0x08, 	/* 29310 */
+	0x00,  0x08,  0x00,  0x10,  0x00,  0xE0,  0xA4,  0x00,  0x20,  0x00,  0x20,  0x7B,  0xFF,  0x4A,  0x01,  0x4A, 	/* 29320 */
+	0x09,  0x48,  0x30,  0x4B,  0xC0,  0x48,  0x40,  0x48,  0x40,  0x48,  0x7F,  0x4F,  0xC0,  0x78,  0x40,  0x00, 	/* 29330 */
+	0x40,  0x00,  0x42,  0x00,  0x22,  0x00,  0x1E,  0xA5,  0x00,  0x00,  0x07,  0xFF,  0x00,  0x40,  0x7C,  0x50, 	/* 29340 */
+	0x44,  0x8C,  0x45,  0x1A,  0x47,  0xE1,  0x44,  0x00,  0x44,  0x20,  0x44,  0x20,  0x45,  0xFE,  0x7C,  0x20, 	/* 29350 */
+	0x00,  0x20,  0x00,  0x20,  0x07,  0xFF,  0x00,  0x00,  0xA8,  0x00,  0x80,  0x00,  0x80,  0x79,  0xFF,  0x01, 	/* 29360 */
+	0x22,  0x02,  0x24,  0x00,  0x30,  0x0C,  0x48,  0x31,  0x84,  0x46,  0x03,  0x00,  0x00,  0x0F,  0xF8,  0x08, 	/* 29370 */
+	0x08,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0xAB,  0x00,  0x00,  0x1F,  0x7E,  0x11,  0x42, 	/* 29380 */
+	0x11,  0x42,  0x11,  0x42,  0x11,  0x42,  0x11,  0x42,  0x1F,  0x7E,  0x18,  0x00,  0x18,  0x24,  0x14,  0x22, 	/* 29390 */
+	0x14,  0x41,  0x12,  0x81,  0x21,  0x00,  0x20,  0xC0,  0x40,  0x3F,  0xAC,  0x00,  0x20,  0x00,  0x20,  0x78, 	/* 293A0 */
+	0x20,  0x4F,  0xFF,  0x48,  0x88,  0x48,  0x84,  0x49,  0x02,  0x4A,  0x8A,  0x48,  0x88,  0x48,  0x50,  0x48, 	/* 293B0 */
+	0x50,  0x78,  0x20,  0x00,  0x50,  0x00,  0x88,  0x03,  0x04,  0x0C,  0x03,  0xAF,  0x00,  0x40,  0x00,  0x40, 	/* 293C0 */
+	0x78,  0xF8,  0x48,  0x88,  0x49,  0x88,  0x49,  0x50,  0x4A,  0x20,  0x48,  0x50,  0x48,  0x8C,  0x49,  0x03, 	/* 293D0 */
+	0x4F,  0xFC,  0x79,  0x04,  0x01,  0x04,  0x01,  0x04,  0x01,  0xFC,  0x00,  0x00,  0xB2,  0x01,  0x04,  0x00, 	/* 293E0 */
+	0x84,  0x00,  0x48,  0x3E,  0x50,  0x23,  0xFE,  0x22,  0x20,  0x22,  0x20,  0x22,  0x20,  0x23,  0xFF,  0x22, 	/* 293F0 */
+	0x20,  0x22,  0x50,  0x3E,  0x50,  0x00,  0x88,  0x01,  0x04,  0x06,  0x02,  0x18,  0x01,  0xB3,  0x00,  0x20, 	/* 29400 */
+	0x00,  0x20,  0x7C,  0x20,  0x47,  0xFF,  0x44,  0x40,  0x44,  0x48,  0x44,  0x90,  0x47,  0x90,  0x44,  0x64, 	/* 29410 */
+	0x44,  0x44,  0x44,  0x88,  0x7F,  0x10,  0x00,  0x28,  0x00,  0x44,  0x01,  0x82,  0x06,  0x02,  0xB8,  0x00, 	/* 29420 */
+	0x24,  0x00,  0x22,  0x00,  0x22,  0x1F,  0xFF,  0x10,  0x20,  0x10,  0x20,  0x1F,  0xE2,  0x10,  0x12,  0x10, 	/* 29430 */
+	0x12,  0x17,  0xD4,  0x14,  0x54,  0x14,  0x48,  0x17,  0xD9,  0x20,  0x25,  0x20,  0x43,  0x40,  0x81,  0xBC, 	/* 29440 */
+	0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x3F,  0xFE, 	/* 29450 */
+	0x20,  0x02,  0x23,  0xE2,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x23,  0xE2,  0x20,  0x02,  0x20,  0x06, 	/* 29460 */
+	0xBD,  0x00,  0x00,  0x03,  0xFE,  0x7A,  0x22,  0x4A,  0x22,  0x4A,  0x22,  0x4A,  0x22,  0x4B,  0xFE,  0x4A, 	/* 29470 */
+	0x22,  0x4A,  0x22,  0x4A,  0x52,  0x4A,  0x52,  0x7A,  0x8A,  0x03,  0x06,  0x02,  0x02,  0x03,  0xFE,  0x00, 	/* 29480 */
+	0x00,  0xBE,  0x00,  0x40,  0x00,  0x44,  0x03,  0xFC,  0x7C,  0x48,  0x44,  0x48,  0x44,  0x50,  0x47,  0xFF, 	/* 29490 */
+	0x44,  0x20,  0x44,  0x40,  0x44,  0x44,  0x44,  0xC8,  0x45,  0x70,  0x7E,  0x40,  0x04,  0x42,  0x00,  0x22, 	/* 294A0 */
+	0x00,  0x1E,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08, 	/* 294B0 */
+	0x08,  0x08,  0x08,  0x0F,  0xFA,  0x01,  0x82,  0x0E,  0x84,  0x72,  0x48,  0x02,  0x30,  0x03,  0x90,  0x0E, 	/* 294C0 */
+	0x0C,  0x30,  0x03,  0x81,  0x00,  0x00,  0x07,  0xF0,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10, 	/* 294D0 */
+	0x07,  0xF0,  0x00,  0x00,  0x00,  0x00,  0x3F,  0x7E,  0x21,  0x42,  0x21,  0x42,  0x21,  0x42,  0x21,  0x42, 	/* 294E0 */
+	0x3F,  0x7E,  0x00,  0x00,  0x82,  0x00,  0x00,  0x07,  0xFF,  0x78,  0x50,  0x48,  0x50,  0x48,  0x50,  0x4B, 	/* 294F0 */
+	0xFE,  0x4A,  0x52,  0x4A,  0x52,  0x4A,  0x56,  0x4A,  0x96,  0x4A,  0x8E,  0x7B,  0x02,  0x02,  0x02,  0x02, 	/* 29500 */
+	0x02,  0x03,  0xFE,  0x00,  0x00,  0x84,  0x00,  0x88,  0x00,  0x88,  0x78,  0x88,  0x4B,  0xFE,  0x48,  0x88, 	/* 29510 */
+	0x48,  0x88,  0x48,  0x88,  0x48,  0x88,  0x48,  0x88,  0x4F,  0xFF,  0x48,  0x00,  0x78,  0x00,  0x00,  0x88, 	/* 29520 */
+	0x01,  0x04,  0x02,  0x02,  0x0C,  0x02,  0x87,  0x00,  0x20,  0x00,  0x20,  0x7D,  0xFC,  0x44,  0x20,  0x44, 	/* 29530 */
+	0x20,  0x44,  0x20,  0x47,  0xFE,  0x44,  0x00,  0x44,  0x20,  0x44,  0x20,  0x47,  0xFE,  0x7C,  0x20,  0x00, 	/* 29540 */
+	0x20,  0x00,  0x20,  0x07,  0xFF,  0x00,  0x00,  0x88,  0x00,  0x20,  0x00,  0x20,  0x78,  0x50,  0x48,  0x50, 	/* 29550 */
+	0x48,  0x88,  0x49,  0x04,  0x4A,  0x02,  0x4D,  0xFD,  0x48,  0x00,  0x48,  0x00,  0x49,  0xFC,  0x79,  0x04, 	/* 29560 */
+	0x01,  0x04,  0x01,  0x04,  0x01,  0xFC,  0x00,  0x00,  0x89,  0x02,  0x20,  0x02,  0x28,  0x1F,  0xE4,  0x02, 	/* 29570 */
+	0x24,  0x02,  0x20,  0x7F,  0xFF,  0x00,  0x24,  0x00,  0x24,  0x1F,  0x24,  0x11,  0x28,  0x11,  0x18,  0x11, 	/* 29580 */
+	0x10,  0x1F,  0x2A,  0x00,  0x4A,  0x00,  0x86,  0x03,  0x02,  0x98,  0x00,  0x80,  0x00,  0x9E,  0x79,  0x00, 	/* 29590 */
+	0x49,  0x00,  0x4A,  0x40,  0x4C,  0x40,  0x48,  0xBF,  0x48,  0x84,  0x49,  0x04,  0x4B,  0x04,  0x4D,  0x04, 	/* 295A0 */
+	0x79,  0x04,  0x01,  0x04,  0x01,  0x04,  0x01,  0x04,  0x01,  0x0C,  0xA1,  0x00,  0x00,  0x0F,  0xF8,  0x08, 	/* 295B0 */
+	0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x1F,  0xFC,  0x10,  0x04,  0x1F,  0xFC,  0x10,  0x04,  0x1F, 	/* 295C0 */
+	0xFC,  0x10,  0x04,  0x1F,  0xFC,  0x02,  0x30,  0x0C,  0x0C,  0x30,  0x02,  0xA2,  0x00,  0x00,  0x03,  0xFE, 	/* 295D0 */
+	0x78,  0x20,  0x48,  0x20,  0x49,  0xFC,  0x48,  0x20,  0x48,  0x20,  0x4F,  0xFF,  0x48,  0x88,  0x48,  0x88, 	/* 295E0 */
+	0x4F,  0xFF,  0x78,  0x88,  0x00,  0x88,  0x01,  0x08,  0x01,  0x08,  0x02,  0x08,  0xA5,  0x00,  0x00,  0x7F, 	/* 295F0 */
+	0xFF,  0x00,  0x08,  0x0F,  0x88,  0x08,  0x88,  0x08,  0x88,  0x0F,  0x98,  0x00,  0x00,  0x7F,  0xFF,  0x00, 	/* 29600 */
+	0x08,  0x0F,  0x88,  0x08,  0x88,  0x08,  0x88,  0x0F,  0x88,  0x00,  0x08,  0x00,  0x18,  0xA6,  0x00,  0x30, 	/* 29610 */
+	0x00,  0xD4,  0x7B,  0x92,  0x48,  0x92,  0x48,  0x90,  0x4F,  0xFF,  0x48,  0x90,  0x48,  0x92,  0x48,  0x92, 	/* 29620 */
+	0x48,  0xD4,  0x4B,  0x8C,  0x78,  0x88,  0x00,  0x95,  0x00,  0xA5,  0x00,  0xC3,  0x01,  0x81,  0xA8,  0x00, 	/* 29630 */
+	0x10,  0x00,  0x92,  0x00,  0x52,  0x3E,  0x54,  0x22,  0x10,  0x22,  0xFE,  0x22,  0x82,  0x22,  0x82,  0x22, 	/* 29640 */
+	0xFE,  0x22,  0x82,  0x22,  0x82,  0x3E,  0xFE,  0x00,  0x82,  0x00,  0x82,  0x00,  0x82,  0x00,  0x86,  0xA9, 	/* 29650 */
+	0x00,  0x00,  0x01,  0xFC,  0x7D,  0x24,  0x45,  0x24,  0x45,  0xFC,  0x45,  0x24,  0x45,  0x24,  0x45,  0x24, 	/* 29660 */
+	0x45,  0xFC,  0x44,  0x20,  0x7C,  0x20,  0x03,  0xFE,  0x00,  0x20,  0x00,  0x20,  0x07,  0xFF,  0x00,  0x00, 	/* 29670 */
+	0xAD,  0x00,  0x00,  0x3E,  0x7C,  0x22,  0x44,  0x22,  0x44,  0x22,  0x44,  0x3E,  0x7C,  0x00,  0x90,  0x00, 	/* 29680 */
+	0x88,  0x00,  0x88,  0x7F,  0xFF,  0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x04,  0x10,  0x18,  0x0C,  0x60, 	/* 29690 */
+	0x03,  0xAE,  0x00,  0x40,  0x00,  0x44,  0x7B,  0xFC,  0x48,  0x48,  0x48,  0x50,  0x4F,  0xFF,  0x48,  0x20, 	/* 296A0 */
+	0x48,  0x7C,  0x48,  0x88,  0x4B,  0x10,  0x4C,  0x20,  0x7B,  0xFF,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20, 	/* 296B0 */
+	0x00,  0x60,  0xB2,  0x08,  0x04,  0x08,  0xF8,  0x7E,  0x80,  0x08,  0x80,  0x08,  0xFF,  0x0E,  0x88,  0x78, 	/* 296C0 */
+	0x88,  0x09,  0x08,  0x09,  0x08,  0x1A,  0x08,  0x00,  0x08,  0x1F,  0xF8,  0x10,  0x08,  0x10,  0x08,  0x1F, 	/* 296D0 */
+	0xF8,  0x00,  0x00,  0xBA,  0x00,  0x28,  0x00,  0x24,  0x07,  0xFF,  0x78,  0x20,  0x48,  0x20,  0x4B,  0xFC, 	/* 296E0 */
+	0x4A,  0x24,  0x4A,  0x24,  0x4B,  0xFC,  0x4A,  0x24,  0x4A,  0x24,  0x4B,  0xFC,  0x7A,  0x24,  0x02,  0x24, 	/* 296F0 */
+	0x02,  0x24,  0x02,  0x2C,  0xBD,  0x00,  0x00,  0x07,  0xFF,  0x78,  0x20,  0x49,  0xFC,  0x49,  0x24,  0x49, 	/* 29700 */
+	0x24,  0x49,  0xFC,  0x49,  0x24,  0x49,  0x24,  0x49,  0xFC,  0x79,  0x20,  0x00,  0xA0,  0x00,  0x40,  0x00, 	/* 29710 */
+	0xA0,  0x03,  0x18,  0x0C,  0x07,  0x84,  0x00,  0x00,  0x00,  0x7E,  0x3E,  0x42,  0x22,  0x42,  0x22,  0x42, 	/* 29720 */
+	0x22,  0x7E,  0x22,  0x42,  0x22,  0x42,  0x22,  0x7E,  0x22,  0x42,  0x22,  0x42,  0x3E,  0x42,  0x00,  0x7E, 	/* 29730 */
+	0x00,  0x24,  0x00,  0xC2,  0x03,  0x01,  0x86,  0x00,  0x40,  0x00,  0x50,  0x00,  0x8C,  0x7B,  0xFA,  0x48, 	/* 29740 */
+	0x90,  0x48,  0x91,  0x49,  0x0F,  0x4A,  0x40,  0x4C,  0x78,  0x48,  0x88,  0x49,  0x08,  0x7E,  0xD0,  0x48, 	/* 29750 */
+	0x20,  0x00,  0xD0,  0x03,  0x0C,  0x0C,  0x03,  0x87,  0x00,  0x00,  0x1F,  0xFE,  0x10,  0x00,  0x1F,  0xFC, 	/* 29760 */
+	0x10,  0x00,  0x1F,  0xFF,  0x12,  0x84,  0x12,  0x58,  0x32,  0x20,  0x23,  0x98,  0x5C,  0x07,  0x0F,  0xF8, 	/* 29770 */
+	0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x8F,  0x00,  0x04,  0x00,  0xC8,  0x78,  0x30,  0x48, 	/* 29780 */
+	0x68,  0x4B,  0xA4,  0x48,  0x40,  0x4F,  0xFF,  0x48,  0x40,  0x48,  0xA0,  0x49,  0xFC,  0x4B,  0x24,  0x7D, 	/* 29790 */
+	0x24,  0x09,  0x24,  0x01,  0x38,  0x01,  0x20,  0x00,  0x20,  0x90,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFF, 	/* 297A0 */
+	0x10,  0x40,  0x17,  0xFC,  0x10,  0x44,  0x1F,  0xFF,  0x10,  0x44,  0x10,  0x44,  0x17,  0xFC,  0x10,  0x00, 	/* 297B0 */
+	0x17,  0xFC,  0x24,  0x04,  0x24,  0x04,  0x47,  0xFC,  0x00,  0x00,  0x94,  0x00,  0x00,  0x07,  0xFE,  0x78, 	/* 297C0 */
+	0x40,  0x48,  0x40,  0x4B,  0xF8,  0x48,  0x88,  0x48,  0x88,  0x48,  0x88,  0x4F,  0xFF,  0x48,  0x00,  0x49, 	/* 297D0 */
+	0xFC,  0x79,  0x04,  0x01,  0x04,  0x01,  0x04,  0x01,  0xFC,  0x00,  0x00,  0x96,  0x00,  0x00,  0x07,  0xFF, 	/* 297E0 */
+	0x78,  0x48,  0x48,  0x48,  0x48,  0x48,  0x4B,  0xFE,  0x4A,  0x4A,  0x4A,  0x4A,  0x4A,  0x4A,  0x4B,  0xFE, 	/* 297F0 */
+	0x48,  0x48,  0x78,  0x48,  0x48,  0x48,  0x00,  0x48,  0x07,  0xFF,  0x00,  0x00,  0xAE,  0x08,  0x20,  0x08, 	/* 29800 */
+	0x40,  0x1F,  0xFE,  0x10,  0x40,  0x3F,  0xFC,  0x50,  0x40,  0x1F,  0xFC,  0x10,  0x40,  0x1F,  0xFE,  0x00, 	/* 29810 */
+	0x00,  0x1F,  0xF8,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x1F,  0xF8,  0x00,  0x00,  0xAF,  0x00,  0x44, 	/* 29820 */
+	0x00,  0x44,  0x3C,  0x48,  0x24,  0xFF,  0x24,  0x88,  0x25,  0x88,  0x26,  0x88,  0x24,  0xFE,  0x24,  0x88, 	/* 29830 */
+	0x24,  0x88,  0x24,  0xFE,  0x3C,  0x88,  0x00,  0x88,  0x00,  0x88,  0x00,  0xFF,  0x00,  0x00,  0xB1,  0x00, 	/* 29840 */
+	0x00,  0x00,  0xFC,  0x00,  0x84,  0x7C,  0x84,  0x44,  0xFC,  0x44,  0x84,  0x44,  0x84,  0x44,  0xFC,  0x44, 	/* 29850 */
+	0x00,  0x45,  0xFE,  0x7D,  0x02,  0x01,  0xFE,  0x01,  0x02,  0x01,  0x02,  0x01,  0xFE,  0x00,  0x00,  0xB3, 	/* 29860 */
+	0x00,  0x00,  0x03,  0xFF,  0x78,  0x00,  0x49,  0xFE,  0x49,  0x02,  0x49,  0x02,  0x49,  0xFE,  0x49,  0x10, 	/* 29870 */
+	0x49,  0x10,  0x49,  0xFF,  0x49,  0x10,  0x7A,  0x18,  0x02,  0x28,  0x04,  0x44,  0x09,  0x82,  0x06,  0x01, 	/* 29880 */
+	0xB8,  0x00,  0x20,  0x00,  0x20,  0x00,  0x50,  0x78,  0x88,  0x49,  0x04,  0x4E,  0xFB,  0x48,  0x00,  0x49, 	/* 29890 */
+	0xF8,  0x48,  0x08,  0x48,  0x10,  0x48,  0x20,  0x7A,  0x94,  0x02,  0x92,  0x04,  0x85,  0x08,  0x85,  0x00, 	/* 298A0 */
+	0x7C,  0xB9,  0x01,  0x08,  0x01,  0x08,  0x79,  0x08,  0x4F,  0xF4,  0x49,  0x14,  0x49,  0x14,  0x49,  0xE2, 	/* 298B0 */
+	0x49,  0x72,  0x49,  0x49,  0x49,  0x48,  0x4A,  0x40,  0x7A,  0x50,  0x02,  0x48,  0x04,  0x44,  0x08,  0x42, 	/* 298C0 */
+	0x11,  0x82,  0xBE,  0x00,  0x04,  0x00,  0x18,  0x79,  0xE0,  0x48,  0x20,  0x4B,  0xFE,  0x49,  0x24,  0x49, 	/* 298D0 */
+	0x24,  0x49,  0x24,  0x4F,  0xFF,  0x49,  0x24,  0x49,  0x24,  0x7B,  0xFE,  0x00,  0x20,  0x00,  0x20,  0x07, 	/* 298E0 */
+	0xFF,  0x00,  0x00,  0x80,  0x00,  0x00,  0x03,  0xFF,  0x7A,  0x10,  0x4A,  0x10,  0x4A,  0xFE,  0x4A,  0x10, 	/* 298F0 */
+	0x4A,  0x10,  0x4B,  0xFF,  0x4A,  0x00,  0x4A,  0x10,  0x7A,  0x10,  0x04,  0xFE,  0x04,  0x10,  0x08,  0x10, 	/* 29900 */
+	0x13,  0xFF,  0x00,  0x00,  0x84,  0x00,  0x00,  0x07,  0xFF,  0x78,  0x40,  0x48,  0xC2,  0x49,  0x22,  0x4E, 	/* 29910 */
+	0x24,  0x48,  0x68,  0x48,  0x90,  0x49,  0x18,  0x4E,  0x38,  0x78,  0x54,  0x48,  0x92,  0x03,  0x11,  0x0C, 	/* 29920 */
+	0x10,  0x00,  0x10,  0x00,  0x60,  0x85,  0x00,  0x20,  0x00,  0x20,  0x78,  0x3E,  0x48,  0x20,  0x49,  0xFC, 	/* 29930 */
+	0x49,  0x04,  0x49,  0x04,  0x49,  0xFC,  0x49,  0x04,  0x49,  0x04,  0x49,  0xFC,  0x78,  0x20,  0x07,  0xFF, 	/* 29940 */
+	0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x86,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x04,  0x10,  0x02, 	/* 29950 */
+	0x20,  0x3F,  0xFE,  0x22,  0x22,  0x22,  0x26,  0x24,  0x1E,  0x2B,  0xE2,  0x32,  0x22,  0x22,  0x22,  0x23, 	/* 29960 */
+	0xE2,  0x20,  0x02,  0x20,  0x02,  0x20,  0x06,  0x8C,  0x00,  0x20,  0x00,  0x20,  0x7B,  0xFE,  0x4A,  0x52, 	/* 29970 */
+	0x4A,  0x52,  0x48,  0x50,  0x48,  0x92,  0x49,  0x0E,  0x4A,  0x00,  0x49,  0xFC,  0x48,  0x20,  0x78,  0x20, 	/* 29980 */
+	0x00,  0x20,  0x00,  0x20,  0x07,  0xFE,  0x00,  0x00,  0x8F,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E, 	/* 29990 */
+	0x7E,  0x42,  0x42,  0x42,  0x42,  0x7E,  0x7E,  0x40,  0x02,  0x40,  0x02,  0x47,  0xE2,  0x44,  0x22,  0x44, 	/* 299A0 */
+	0x22,  0x44,  0x22,  0x47,  0xE2,  0x40,  0x02,  0x40,  0x06,  0x93,  0x00,  0x10,  0x7F,  0x90,  0x00,  0x1F, 	/* 299B0 */
+	0x1F,  0x24,  0x11,  0x24,  0x11,  0x54,  0x1F,  0x08,  0x10,  0x34,  0x20,  0xC2,  0x20,  0x01,  0x4F,  0xF8, 	/* 299C0 */
+	0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x96,  0x00,  0x20,  0x00,  0x24,  0x79, 	/* 299D0 */
+	0x24,  0x49,  0x28,  0x49,  0x50,  0x4A,  0x48,  0x48,  0x84,  0x49,  0x04,  0x4A,  0x20,  0x49,  0x24,  0x49, 	/* 299E0 */
+	0x24,  0x79,  0x38,  0x02,  0x50,  0x00,  0x88,  0x03,  0x04,  0x0C,  0x03,  0x97,  0x00,  0x40,  0x00,  0x7C, 	/* 299F0 */
+	0x78,  0x84,  0x48,  0x84,  0x49,  0x04,  0x4A,  0x38,  0x48,  0x20,  0x48,  0x40,  0x49,  0x8E,  0x49,  0x02, 	/* 29A00 */
+	0x49,  0x02,  0x79,  0xDE,  0x01,  0x02,  0x01,  0x02,  0x01,  0xFE,  0x00,  0x00,  0x9C,  0x00,  0x00,  0x03, 	/* 29A10 */
+	0xFE,  0x78,  0x44,  0x49,  0x94,  0x48,  0x88,  0x49,  0x54,  0x4A,  0x24,  0x48,  0x40,  0x4B,  0xFE,  0x48, 	/* 29A20 */
+	0x42,  0x4A,  0x54,  0x79,  0x94,  0x00,  0x88,  0x01,  0x54,  0x02,  0x22,  0x0C,  0x41,  0x9D,  0x00,  0x20, 	/* 29A30 */
+	0x00,  0xC0,  0x7B,  0x9E,  0x48,  0x92,  0x48,  0x92,  0x4F,  0xF2,  0x48,  0x92,  0x48,  0x92,  0x49,  0xD2, 	/* 29A40 */
+	0x49,  0xD2,  0x4A,  0xBE,  0x7A,  0x90,  0x04,  0x88,  0x00,  0x84,  0x00,  0x80,  0x00,  0x80,  0xA3,  0x01, 	/* 29A50 */
+	0x00,  0x01,  0x1E,  0x79,  0xF2,  0x4A,  0x92,  0x4C,  0x92,  0x4F,  0xF2,  0x48,  0x92,  0x48,  0x92,  0x4A, 	/* 29A60 */
+	0xF2,  0x4A,  0x92,  0x4A,  0x92,  0x7A,  0xB2,  0x02,  0xDC,  0x03,  0x10,  0x0C,  0x10,  0x00,  0x10,  0xBB, 	/* 29A70 */
+	0x01,  0x00,  0x7F,  0xFE,  0x08,  0x20,  0x04,  0x40,  0x7F,  0xFE,  0x41,  0x02,  0x5F,  0xFA,  0x11,  0x08, 	/* 29A80 */
+	0x11,  0x08,  0x11,  0x30,  0x01,  0x00,  0x1F,  0xF8,  0x10,  0x08,  0x10,  0x08,  0x1F,  0xF8,  0x00,  0x00, 	/* 29A90 */
+	0xBC,  0x00,  0x20,  0x00,  0x20,  0x7B,  0xFE,  0x48,  0x88,  0x48,  0x48,  0x48,  0x50,  0x4B,  0xFF,  0x4A, 	/* 29AA0 */
+	0x21,  0x4A,  0x21,  0x49,  0xFE,  0x49,  0x22,  0x79,  0x22,  0x01,  0x22,  0x01,  0x2C,  0x00,  0x20,  0x00, 	/* 29AB0 */
+	0x20,  0xBE,  0x00,  0x48,  0x01,  0x88,  0x07,  0x0A,  0x79,  0x0A,  0x49,  0x2A,  0x4F,  0xEC,  0x49,  0x28, 	/* 29AC0 */
+	0x49,  0x28,  0x4B,  0xA8,  0x4B,  0x4C,  0x4B,  0x14,  0x7D,  0x14,  0x05,  0x14,  0x09,  0x22,  0x01,  0x42, 	/* 29AD0 */
+	0x01,  0x81,  0x80,  0x00,  0x20,  0x00,  0x20,  0x7B,  0xFE,  0x4A,  0x42,  0x48,  0x78,  0x48,  0x88,  0x49, 	/* 29AE0 */
+	0x50,  0x4A,  0x30,  0x48,  0x48,  0x49,  0x84,  0x4F,  0xFF,  0x79,  0x04,  0x01,  0x04,  0x01,  0x04,  0x01, 	/* 29AF0 */
+	0xFC,  0x00,  0x00,  0x83,  0x00,  0x20,  0x00,  0x20,  0x07,  0xFF,  0x78,  0x20,  0x48,  0x20,  0x4B,  0xFE, 	/* 29B00 */
+	0x4A,  0x8A,  0x4A,  0x4A,  0x4A,  0x52,  0x4A,  0xFA,  0x4A,  0x22,  0x7A,  0x22,  0x02,  0xFA,  0x02,  0x22, 	/* 29B10 */
+	0x02,  0x22,  0x02,  0x26,  0x84,  0x04,  0x08,  0x02,  0x10,  0x3F,  0xFE,  0x00,  0x80,  0x1F,  0xFC,  0x00, 	/* 29B20 */
+	0x80,  0x3F,  0xFE,  0x08,  0x88,  0x04,  0x90,  0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08, 	/* 29B30 */
+	0x08,  0x0F,  0xF8,  0x00,  0x00,  0x87,  0x00,  0x82,  0x78,  0x8A,  0x4F,  0xFA,  0x48,  0x8A,  0x4B,  0xEA, 	/* 29B40 */
+	0x4A,  0xAA,  0x4A,  0xAA,  0x4A,  0xAA,  0x4B,  0xEA,  0x48,  0x8A,  0x49,  0xCA,  0x79,  0xA2,  0x02,  0x92, 	/* 29B50 */
+	0x04,  0x82,  0x08,  0x82,  0x00,  0x86,  0x89,  0x00,  0x80,  0x00,  0xBC,  0x78,  0x84,  0x49,  0x04,  0x49, 	/* 29B60 */
+	0xFF,  0x4B,  0x20,  0x4B,  0x20,  0x4D,  0x7E,  0x49,  0x50,  0x49,  0x90,  0x49,  0xFF,  0x79,  0x28,  0x01, 	/* 29B70 */
+	0x28,  0x01,  0x44,  0x01,  0x82,  0x01,  0x01,  0x8A,  0x00,  0x14,  0x00,  0x12,  0x78,  0x12,  0x4B,  0xFF, 	/* 29B80 */
+	0x4A,  0x10,  0x4B,  0xF0,  0x4A,  0x12,  0x4A,  0xF2,  0x4A,  0xB4,  0x4A,  0xAC,  0x4A,  0xA8,  0x7A,  0xE9, 	/* 29B90 */
+	0x04,  0x15,  0x04,  0x25,  0x08,  0x43,  0x10,  0x01,  0x8B,  0x01,  0x24,  0x01,  0x24,  0x7F,  0xFF,  0x49, 	/* 29BA0 */
+	0x24,  0x49,  0x24,  0x49,  0x3C,  0x49,  0x00,  0x49,  0xFE,  0x48,  0x20,  0x4F,  0xFF,  0x78,  0x70,  0x00, 	/* 29BB0 */
+	0xA8,  0x01,  0x24,  0x06,  0x23,  0x00,  0x20,  0x00,  0x20,  0x98,  0x00,  0x20,  0x02,  0x22,  0x7A,  0x22, 	/* 29BC0 */
+	0x4A,  0x22,  0x4B,  0xFE,  0x48,  0x00,  0x4F,  0xFF,  0x48,  0x20,  0x48,  0x40,  0x4B,  0xFE,  0x4A,  0x92, 	/* 29BD0 */
+	0x7A,  0x92,  0x02,  0x92,  0x02,  0x92,  0x02,  0x92,  0x02,  0x06,  0x99,  0x00,  0x40,  0x00,  0xFC,  0x78, 	/* 29BE0 */
+	0x88,  0x49,  0xF8,  0x48,  0x10,  0x4F,  0xFF,  0x48,  0x40,  0x48,  0xAA,  0x4B,  0x2C,  0x48,  0x58,  0x48, 	/* 29BF0 */
+	0x94,  0x7B,  0x34,  0x00,  0x52,  0x01,  0x91,  0x06,  0x10,  0x00,  0x60,  0x9A,  0x00,  0x80,  0x00,  0xF8, 	/* 29C00 */
+	0x79,  0x10,  0x4A,  0x20,  0x4F,  0xFC,  0x4A,  0xA4,  0x4A,  0xA4,  0x4A,  0xAC,  0x4A,  0x9C,  0x4B,  0x04, 	/* 29C10 */
+	0x7A,  0x24,  0x4F,  0xFF,  0x00,  0x20,  0x00,  0x50,  0x01,  0x8C,  0x0E,  0x03,  0x9C,  0x01,  0x00,  0x7F, 	/* 29C20 */
+	0xFE,  0x01,  0x00,  0x3F,  0xFC,  0x00,  0x00,  0x1F,  0xF8,  0x10,  0x08,  0x1F,  0xF8,  0x08,  0x10,  0x04, 	/* 29C30 */
+	0x20,  0xFF,  0xFF,  0x00,  0x00,  0x1F,  0xF8,  0x10,  0x08,  0x1F,  0xF8,  0x00,  0x00,  0x9D,  0x00,  0x00, 	/* 29C40 */
+	0x01,  0xF8,  0x79,  0x08,  0x49,  0x08,  0x49,  0xF8,  0x49,  0x08,  0x49,  0x08,  0x49,  0xF8,  0x48,  0x40, 	/* 29C50 */
+	0x48,  0xFE,  0x79,  0x12,  0x03,  0xE2,  0x05,  0x02,  0x01,  0x12,  0x00,  0xF2,  0x00,  0x0C,  0x9E,  0x01, 	/* 29C60 */
+	0x00,  0x01,  0x1E,  0x7B,  0xD2,  0x4A,  0x52,  0x4A,  0x52,  0x4B,  0xD2,  0x4A,  0x52,  0x4A,  0x52,  0x4B, 	/* 29C70 */
+	0xD2,  0x4A,  0x12,  0x4A,  0x12,  0x7B,  0xDC,  0x02,  0x10,  0x02,  0x10,  0x03,  0xD0,  0x02,  0x10,  0x9F, 	/* 29C80 */
+	0x00,  0x00,  0x03,  0xFE,  0x7A,  0x22,  0x4B,  0xFE,  0x4A,  0x22,  0x4A,  0x22,  0x4B,  0xFE,  0x48,  0x00, 	/* 29C90 */
+	0x49,  0xFC,  0x49,  0x04,  0x79,  0xFC,  0x01,  0x04,  0x01,  0xFC,  0x01,  0x04,  0x01,  0x04,  0x01,  0x0C, 	/* 29CA0 */
+	0xA7,  0x00,  0x20,  0x00,  0x20,  0x7B,  0xFF,  0x4A,  0x01,  0x4A,  0x01,  0x49,  0xFE,  0x48,  0x00,  0x48, 	/* 29CB0 */
+	0xFC,  0x48,  0x84,  0x48,  0xFC,  0x48,  0x84,  0x78,  0x84,  0x00,  0xFC,  0x00,  0x00,  0x07,  0xFF,  0x00, 	/* 29CC0 */
+	0x00,  0xA8,  0x00,  0x20,  0x00,  0x20,  0x7B,  0xFF,  0x48,  0x00,  0x48,  0xFC,  0x48,  0x84,  0x48,  0xFC, 	/* 29CD0 */
+	0x48,  0x00,  0x4B,  0xFF,  0x4A,  0x01,  0x4A,  0x49,  0x78,  0x48,  0x00,  0x48,  0x00,  0x89,  0x03,  0x09, 	/* 29CE0 */
+	0x0C,  0x07,  0xA9,  0x00,  0x20,  0x00,  0x20,  0x78,  0x50,  0x48,  0x88,  0x49,  0xFC,  0x4A,  0x02,  0x4F, 	/* 29CF0 */
+	0xD3,  0x4E,  0x52,  0x4B,  0x52,  0x4A,  0xE4,  0x4A,  0x64,  0x7B,  0x64,  0x02,  0xD2,  0x02,  0x52,  0x02, 	/* 29D00 */
+	0x52,  0x02,  0xD2,  0xAA,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80,  0x1E,  0xBC,  0x12,  0xA4, 	/* 29D10 */
+	0x12,  0xA4,  0x1E,  0xBC,  0x00,  0x80,  0x7F,  0xFF,  0x04,  0x84,  0x04,  0x44,  0x04,  0x28,  0x04,  0x90, 	/* 29D20 */
+	0x07,  0x0C,  0x38,  0x03,  0xAB,  0x01,  0x00,  0x01,  0x3E,  0x7F,  0xCA,  0x49,  0x0A,  0x49,  0x0A,  0x4F, 	/* 29D30 */
+	0xCA,  0x49,  0x12,  0x49,  0xD2,  0x4E,  0x2C,  0x48,  0x40,  0x7F,  0xFF,  0x48,  0x40,  0x00,  0xA0,  0x01, 	/* 29D40 */
+	0x10,  0x06,  0x0C,  0x18,  0x03,  0xAC,  0x00,  0x38,  0x1F,  0xC0,  0x01,  0x00,  0x7F,  0xFE,  0x02,  0x20, 	/* 29D50 */
+	0x07,  0xF0,  0x1A,  0x2C,  0x63,  0xE2,  0x00,  0x00,  0x1F,  0xFC,  0x10,  0x04,  0x13,  0xE4,  0x12,  0x24, 	/* 29D60 */
+	0x13,  0xE4,  0x10,  0x04,  0x10,  0x0C,  0xAE,  0x00,  0x00,  0x1F,  0x7C,  0x11,  0x44,  0x1F,  0x7C,  0x00, 	/* 29D70 */
+	0x00,  0x0F,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x80,  0x7F, 	/* 29D80 */
+	0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0xB0,  0x00,  0x20,  0x00,  0x20,  0x7C,  0x50,  0x44,  0x88, 	/* 29D90 */
+	0x45,  0x24,  0x46,  0xFB,  0x44,  0x88,  0x44,  0xF8,  0x44,  0x88,  0x44,  0x8A,  0x44,  0xFA,  0x7C,  0xA4, 	/* 29DA0 */
+	0x00,  0x90,  0x00,  0x88,  0x00,  0xE4,  0x07,  0x03,  0xB6,  0x12,  0x08,  0x09,  0x08,  0x09,  0x10,  0x7F, 	/* 29DB0 */
+	0xFE,  0x40,  0x02,  0x4F,  0xF2,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x01,  0x00,  0x02,  0x00,  0x1F, 	/* 29DC0 */
+	0xF8,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x1F,  0xF8,  0x84,  0x00,  0x00,  0x07,  0xFF,  0x00,  0x40, 	/* 29DD0 */
+	0x79,  0xFC,  0x49,  0x04,  0x49,  0xFC,  0x49,  0x04,  0x49,  0xFC,  0x49,  0x04,  0x49,  0xFC,  0x48,  0x20, 	/* 29DE0 */
+	0x78,  0xFC,  0x07,  0x48,  0x00,  0x30,  0x00,  0xD8,  0x0F,  0x07,  0x85,  0x00,  0x20,  0x00,  0x40,  0x79, 	/* 29DF0 */
+	0xFC,  0x49,  0x04,  0x49,  0xFC,  0x49,  0x04,  0x49,  0xFC,  0x49,  0x04,  0x49,  0x04,  0x49,  0xFC,  0x78, 	/* 29E00 */
+	0x28,  0x00,  0x24,  0x0F,  0xFF,  0x00,  0x50,  0x01,  0x8C,  0x0E,  0x03,  0x87,  0x00,  0x80,  0x00,  0x80, 	/* 29E10 */
+	0x3F,  0xFE,  0x04,  0x88,  0x04,  0x88,  0x0A,  0x94,  0x10,  0xA2,  0x7F,  0xFF,  0x00,  0x00,  0x1F,  0xFC, 	/* 29E20 */
+	0x13,  0xE4,  0x12,  0x24,  0x13,  0xE4,  0x10,  0x04,  0x1F,  0xFC,  0x00,  0x00,  0x94,  0x01,  0x04,  0x01, 	/* 29E30 */
+	0xF8,  0x79,  0x02,  0x48,  0xFE,  0x4A,  0x00,  0x4A,  0xFC,  0x4A,  0x84,  0x4A,  0xFC,  0x4A,  0x84,  0x4A, 	/* 29E40 */
+	0xFC,  0x4A,  0x84,  0x7A,  0xFC,  0x02,  0x00,  0x03,  0xFF,  0x01,  0x8C,  0x0E,  0x02,  0x9A,  0x00,  0x20, 	/* 29E50 */
+	0x00,  0x40,  0x79,  0xF8,  0x49,  0x08,  0x49,  0x08,  0x49,  0x08,  0x49,  0xF8,  0x49,  0x00,  0x49,  0xFF, 	/* 29E60 */
+	0x49,  0x00,  0x79,  0xFE,  0x00,  0x92,  0x06,  0x4A,  0x05,  0x42,  0x05,  0x04,  0x08,  0x18,  0x9C,  0x00, 	/* 29E70 */
+	0x40,  0x00,  0x44,  0x7B,  0xF8,  0x48,  0x50,  0x4F,  0xFF,  0x48,  0x84,  0x49,  0xF8,  0x4E,  0x81,  0x48, 	/* 29E80 */
+	0x7F,  0x48,  0x00,  0x79,  0xFC,  0x01,  0x04,  0x01,  0xFC,  0x01,  0x04,  0x01,  0xFC,  0x00,  0x00,  0x9F, 	/* 29E90 */
+	0x00,  0x84,  0x00,  0x48,  0x7B,  0xFE,  0x48,  0x20,  0x48,  0x20,  0x49,  0xFC,  0x48,  0x20,  0x4F,  0xFF, 	/* 29EA0 */
+	0x48,  0x80,  0x48,  0x80,  0x79,  0xFE,  0x02,  0x10,  0x04,  0x10,  0x08,  0x10,  0x03,  0xFF,  0x00,  0x00, 	/* 29EB0 */
+	0xA3,  0x00,  0x00,  0x3E,  0xFE,  0x22,  0x02,  0x22,  0x02,  0x3E,  0xFE,  0x00,  0x02,  0x7F,  0x02,  0x55, 	/* 29EC0 */
+	0x7A,  0x55,  0x4A,  0x55,  0x4A,  0x7F,  0x4A,  0x55,  0x7A,  0x55,  0x02,  0x55,  0x02,  0x55,  0x02,  0x43, 	/* 29ED0 */
+	0x0C,  0xA4,  0x00,  0x20,  0x02,  0x22,  0x7A,  0x22,  0x4B,  0xFE,  0x48,  0x40,  0x48,  0x80,  0x4F,  0xFF, 	/* 29EE0 */
+	0x48,  0x20,  0x49,  0xFC,  0x49,  0x24,  0x49,  0x24,  0x79,  0xFC,  0x00,  0x28,  0x00,  0x24,  0x00,  0xFE, 	/* 29EF0 */
+	0x07,  0x01,  0xB7,  0x01,  0x10,  0x01,  0x10,  0x7B,  0xD0,  0x49,  0x1F,  0x49,  0x24,  0x4F,  0xE4,  0x49, 	/* 29F00 */
+	0x04,  0x49,  0x14,  0x4F,  0xF4,  0x49,  0x14,  0x49,  0xC8,  0x79,  0x48,  0x02,  0x54,  0x04,  0x54,  0x08, 	/* 29F10 */
+	0x62,  0x01,  0x81,  0xB9,  0x00,  0x10,  0x02,  0x10,  0x71,  0xFF,  0x51,  0x10,  0x54,  0x7E,  0x52,  0x52, 	/* 29F20 */
+	0x52,  0x52,  0x50,  0x7E,  0x5F,  0x52,  0x51,  0x52,  0x51,  0x7E,  0x71,  0x10,  0x02,  0xFF,  0x02,  0x90, 	/* 29F30 */
+	0x04,  0x70,  0x08,  0x1F,  0xBD,  0x01,  0x08,  0x01,  0x08,  0x7F,  0xE8,  0x51,  0x1F,  0x57,  0xD1,  0x55, 	/* 29F40 */
+	0x6A,  0x55,  0x48,  0x55,  0x48,  0x57,  0xC8,  0x51,  0x08,  0x53,  0x94,  0x73,  0x54,  0x05,  0x14,  0x09, 	/* 29F50 */
+	0x22,  0x01,  0x42,  0x01,  0x81,  0xBE,  0x01,  0x10,  0x01,  0x10,  0x79,  0x10,  0x4F,  0xDF,  0x4A,  0x20, 	/* 29F60 */
+	0x4A,  0x50,  0x4B,  0xDE,  0x4A,  0x68,  0x4A,  0x48,  0x4A,  0x7F,  0x4A,  0x48,  0x7A,  0x48,  0x02,  0x54, 	/* 29F70 */
+	0x04,  0x54,  0x04,  0x62,  0x09,  0x81,  0x86,  0x00,  0x88,  0x00,  0x88,  0x7F,  0xFF,  0x48,  0x88,  0x4B, 	/* 29F80 */
+	0xFE,  0x4A,  0x22,  0x4A,  0x22,  0x4B,  0xFE,  0x48,  0x20,  0x4B,  0xFC,  0x48,  0x20,  0x7F,  0xFF,  0x48, 	/* 29F90 */
+	0x50,  0x00,  0x88,  0x01,  0x04,  0x06,  0x03,  0x89,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80, 	/* 29FA0 */
+	0x1F,  0xFC,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x02,  0x20,  0x7F,  0xFF,  0x08,  0x00, 	/* 29FB0 */
+	0x3F,  0x7C,  0x09,  0x44,  0x11,  0x7C,  0x66,  0x00,  0x94,  0x00,  0x00,  0x03,  0xFF,  0x7A,  0x00,  0x4A, 	/* 29FC0 */
+	0x7C,  0x4A,  0x44,  0x4A,  0x44,  0x4A,  0x7C,  0x4A,  0x00,  0x4A,  0xEE,  0x4A,  0xAA,  0x4A,  0xAA,  0x7A, 	/* 29FD0 */
+	0xAA,  0x02,  0xEE,  0x02,  0x00,  0x03,  0xFF,  0x00,  0x00,  0x96,  0x00,  0x40,  0x03,  0xFE,  0x78,  0x40, 	/* 29FE0 */
+	0x4B,  0xFC,  0x48,  0x40,  0x4F,  0xFF,  0x48,  0x00,  0x49,  0xF8,  0x49,  0x08,  0x49,  0xF8,  0x49,  0x08, 	/* 29FF0 */
+	0x79,  0xF8,  0x01,  0x08,  0x01,  0xF8,  0x00,  0x8C,  0x07,  0x02,  0x97,  0x11,  0x10,  0x09,  0x20,  0x7F, 	/* 2A000 */
+	0xFE,  0x40,  0x02,  0x4F,  0xF2,  0x08,  0x10,  0x2F,  0xF0,  0x20,  0x18,  0x3F,  0xE0,  0x20,  0x02,  0x1F, 	/* 2A010 */
+	0xFE,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x00,  0x00,  0x98,  0x00,  0x20,  0x00,  0x3E, 	/* 2A020 */
+	0x78,  0x20,  0x4B,  0xFF,  0x4A,  0x42,  0x4A,  0x7C,  0x4B,  0xC0,  0x4A,  0x42,  0x4A,  0x3E,  0x4A,  0x28, 	/* 2A030 */
+	0x7B,  0x2A,  0x44,  0xAA,  0x04,  0xAC,  0x08,  0x28,  0x13,  0xFF,  0x00,  0x00,  0x9B,  0x00,  0x20,  0x00, 	/* 2A040 */
+	0x20,  0x77,  0xFF,  0x54,  0x88,  0x54,  0x88,  0x57,  0xFF,  0x54,  0x88,  0x54,  0xAC,  0x56,  0xAC,  0x56, 	/* 2A050 */
+	0xAC,  0x76,  0xAD,  0x0A,  0xAD,  0x0A,  0xAB,  0x14,  0xC8,  0x20,  0x88,  0x00,  0x88,  0xA9,  0x00,  0x88, 	/* 2A060 */
+	0x00,  0x88,  0x7F,  0xFF,  0x48,  0x88,  0x4B,  0xFE,  0x49,  0x24,  0x49,  0x24,  0x4F,  0xFF,  0x49,  0x24, 	/* 2A070 */
+	0x49,  0x24,  0x4B,  0xFE,  0x78,  0x20,  0x00,  0x20,  0x07,  0xFF,  0x00,  0x20,  0x00,  0x20,  0xAF,  0x00, 	/* 2A080 */
+	0x20,  0x03,  0xFE,  0x78,  0x22,  0x4F,  0xFF,  0x48,  0x22,  0x4B,  0xFE,  0x48,  0x20,  0x4A,  0xAA,  0x4A, 	/* 2A090 */
+	0xAA,  0x4B,  0xAE,  0x4A,  0x22,  0x7B,  0xFE,  0x02,  0x22,  0x03,  0xAE,  0x04,  0xAA,  0x08,  0xAA,  0xB1, 	/* 2A0A0 */
+	0x00,  0x00,  0x03,  0xFE,  0x7A,  0x02,  0x4B,  0xFE,  0x4A,  0x04,  0x4A,  0xF8,  0x4A,  0x10,  0x4A,  0xFE, 	/* 2A0B0 */
+	0x4A,  0x92,  0x4A,  0xFE,  0x7A,  0x10,  0x03,  0xFF,  0x05,  0x15,  0x05,  0x1B,  0x09,  0xE1,  0x11,  0x03, 	/* 2A0C0 */
+	0xB2,  0x00,  0x80,  0x00,  0x9E,  0x7F,  0xF2,  0x48,  0x92,  0x4B,  0xD2,  0x4A,  0x5E,  0x4A,  0x52,  0x4B, 	/* 2A0D0 */
+	0xD2,  0x4A,  0x52,  0x4A,  0x5E,  0x4B,  0xD2,  0x78,  0x92,  0x07,  0xF2,  0x00,  0x92,  0x00,  0xA2,  0x00, 	/* 2A0E0 */
+	0xC6,  0xB4,  0x00,  0x90,  0x02,  0x92,  0x7A,  0xFC,  0x4A,  0x90,  0x4A,  0xF1,  0x4F,  0x4F,  0x48,  0xF0, 	/* 2A0F0 */
+	0x49,  0x20,  0x4B,  0xFE,  0x49,  0x22,  0x49,  0xFE,  0x79,  0x22,  0x01,  0xFE,  0x01,  0x02,  0x02,  0x02, 	/* 2A100 */
+	0x04,  0x06,  0xB6,  0x04,  0x82,  0x04,  0x84,  0x74,  0x98,  0x5F,  0xF0,  0x54,  0x90,  0x54,  0x9F,  0x57, 	/* 2A110 */
+	0x92,  0x54,  0x92,  0x57,  0x92,  0x54,  0x92,  0x54,  0x92,  0x5F,  0xF2,  0x75,  0x22,  0x04,  0xA2,  0x08, 	/* 2A120 */
+	0x42,  0x10,  0x82,  0xB8,  0x00,  0x80,  0x00,  0x80,  0x79,  0xFF,  0x4B,  0x54,  0x4D,  0x54,  0x49,  0x54, 	/* 2A130 */
+	0x49,  0x54,  0x4F,  0xFF,  0x49,  0x54,  0x49,  0x54,  0x49,  0x54,  0x7F,  0xFF,  0x00,  0x00,  0x02,  0x94, 	/* 2A140 */
+	0x04,  0x4A,  0x08,  0x49,  0x82,  0x01,  0x08,  0x00,  0x90,  0x7F,  0xFF,  0x48,  0xA0,  0x4B,  0xFC,  0x4A, 	/* 2A150 */
+	0xA4,  0x4B,  0x1C,  0x4B,  0xFC,  0x4A,  0x04,  0x4B,  0xFC,  0x78,  0x10,  0x0F,  0xFF,  0x02,  0x10,  0x01, 	/* 2A160 */
+	0x10,  0x01,  0x10,  0x00,  0x30,  0x8C,  0x01,  0x04,  0x00,  0x88,  0x7B,  0xFE,  0x4A,  0x22,  0x4B,  0xFE, 	/* 2A170 */
+	0x4A,  0x22,  0x4A,  0x22,  0x4B,  0xFE,  0x48,  0x00,  0x49,  0xFC,  0x79,  0x04,  0x01,  0xFC,  0x01,  0x04, 	/* 2A180 */
+	0x01,  0x04,  0x01,  0xFC,  0x00,  0x00,  0x8E,  0x00,  0x20,  0x00,  0x20,  0x07,  0xFF,  0x78,  0x20,  0x49, 	/* 2A190 */
+	0xFC,  0x48,  0x00,  0x4B,  0xFE,  0x4A,  0x02,  0x4A,  0xFA,  0x48,  0x00,  0x49,  0xFC,  0x79,  0x04,  0x01, 	/* 2A1A0 */
+	0xFC,  0x00,  0x88,  0x0F,  0xFF,  0x00,  0x00,  0x90,  0x00,  0x00,  0x3E,  0x7C,  0x22,  0x44,  0x22,  0x44, 	/* 2A1B0 */
+	0x3E,  0x7C,  0x00,  0x00,  0x1F,  0xF8,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFF,  0x00,  0x00,  0x3E,  0x7C, 	/* 2A1C0 */
+	0x22,  0x44,  0x22,  0x44,  0x3E,  0x7C,  0x00,  0x00,  0x9B,  0x00,  0x20,  0x01,  0x20,  0x79,  0x3E,  0x49, 	/* 2A1D0 */
+	0x20,  0x49,  0x20,  0x4F,  0xFF,  0x4A,  0x22,  0x4A,  0xAA,  0x4A,  0x72,  0x4B,  0xFE,  0x4A,  0x22,  0x7A, 	/* 2A1E0 */
+	0x72,  0x02,  0xAA,  0x03,  0x22,  0x03,  0xFE,  0x00,  0x00,  0xA4,  0x00,  0x88,  0x00,  0x88,  0x07,  0xFF, 	/* 2A1F0 */
+	0x78,  0x88,  0x49,  0xDC,  0x4A,  0xAA,  0x4C,  0x89,  0x48,  0x88,  0x49,  0xFC,  0x48,  0x00,  0x4B,  0xFE, 	/* 2A200 */
+	0x48,  0x20,  0x79,  0x24,  0x02,  0x22,  0x04,  0x22,  0x00,  0x60,  0xA8,  0x00,  0x00,  0x1F,  0x7C,  0x11, 	/* 2A210 */
+	0x44,  0x11,  0x44,  0x1F,  0x7C,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x40,  0x06,  0x30,  0x18, 	/* 2A220 */
+	0x0C,  0x7F,  0x7F,  0x11,  0x44,  0x11,  0x44,  0x1F,  0x7C,  0x00,  0x00,  0xAA,  0x00,  0x00,  0x00,  0xF8, 	/* 2A230 */
+	0x00,  0x88,  0x78,  0x88,  0x48,  0xF8,  0x4B,  0xDE,  0x4A,  0x52,  0x4A,  0x52,  0x4B,  0xDE,  0x48,  0x20, 	/* 2A240 */
+	0x4F,  0xFF,  0x78,  0x70,  0x00,  0xA8,  0x01,  0x24,  0x06,  0x23,  0x00,  0x20,  0xAB,  0x00,  0x20,  0x00, 	/* 2A250 */
+	0x20,  0x7B,  0xFE,  0x48,  0x88,  0x48,  0x50,  0x4F,  0xFF,  0x48,  0x00,  0x49,  0xFC,  0x49,  0x04,  0x49, 	/* 2A260 */
+	0xFC,  0x49,  0x04,  0x79,  0xFC,  0x04,  0xA0,  0x04,  0x92,  0x08,  0x85,  0x00,  0x7C,  0xAC,  0x01,  0x08, 	/* 2A270 */
+	0x01,  0x08,  0x79,  0xEF,  0x4A,  0x94,  0x4A,  0x52,  0x4C,  0x20,  0x4B,  0xFE,  0x49,  0x24,  0x49,  0x24, 	/* 2A280 */
+	0x49,  0xA6,  0x7A,  0xAA,  0x02,  0x69,  0x04,  0x30,  0x00,  0x20,  0x0F,  0xFF,  0x00,  0x00,  0xB4,  0x00, 	/* 2A290 */
+	0x20,  0x03,  0xFE,  0x78,  0x20,  0x48,  0x88,  0x4F,  0xFF,  0x48,  0x88,  0x48,  0x00,  0x49,  0xFC,  0x49, 	/* 2A2A0 */
+	0x04,  0x49,  0xFC,  0x79,  0x04,  0x01,  0xFC,  0x01,  0x04,  0x01,  0xFC,  0x01,  0x8C,  0x06,  0x02,  0xB8, 	/* 2A2B0 */
+	0x01,  0x00,  0x01,  0x7F,  0x71,  0x04,  0x51,  0xE8,  0x5F,  0x1E,  0x51,  0x52,  0x55,  0x52,  0x55,  0x5E, 	/* 2A2C0 */
+	0x55,  0x52,  0x57,  0xDE,  0x51,  0x12,  0x71,  0x12,  0x01,  0x5E,  0x00,  0xD4,  0x00,  0x22,  0x00,  0xC1, 	/* 2A2D0 */
+	0xBA,  0x01,  0x02,  0x01,  0x1C,  0x77,  0xF0,  0x54,  0x50,  0x52,  0x50,  0x52,  0x9F,  0x5F,  0xF2,  0x51, 	/* 2A2E0 */
+	0x12,  0x51,  0x12,  0x57,  0xF2,  0x51,  0x92,  0x73,  0x52,  0x55,  0x22,  0x09,  0x22,  0x01,  0x42,  0x01, 	/* 2A2F0 */
+	0x02,  0x80,  0x00,  0x20,  0x07,  0xFF,  0x7C,  0xA1,  0x4C,  0x91,  0x4A,  0x8A,  0x4A,  0x79,  0x4C,  0x01, 	/* 2A300 */
+	0x4B,  0xFE,  0x4A,  0x92,  0x4B,  0xFE,  0x78,  0x00,  0x07,  0xFF,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20, 	/* 2A310 */
+	0x00,  0x60,  0x86,  0x00,  0x88,  0x07,  0xFF,  0x78,  0x88,  0x48,  0x20,  0x4F,  0xFF,  0x48,  0x00,  0x49, 	/* 2A320 */
+	0xF8,  0x49,  0x08,  0x49,  0xF8,  0x48,  0x00,  0x4B,  0xFE,  0x7A,  0x02,  0x02,  0xFA,  0x02,  0x8A,  0x02, 	/* 2A330 */
+	0xFA,  0x02,  0x06,  0x87,  0x01,  0x08,  0x01,  0x08,  0x77,  0xFE,  0x51,  0x08,  0x51,  0x08,  0x51,  0x08, 	/* 2A340 */
+	0x5F,  0xFF,  0x52,  0x94,  0x52,  0x94,  0x5A,  0xD6,  0x7A,  0xB5,  0x0A,  0xB5,  0x12,  0x94,  0x04,  0xA4, 	/* 2A350 */
+	0x04,  0xA4,  0x09,  0xCC,  0x8A,  0x00,  0x20,  0x00,  0xF8,  0x78,  0x88,  0x48,  0xF8,  0x48,  0x88,  0x48, 	/* 2A360 */
+	0xF8,  0x48,  0x88,  0x4B,  0xFE,  0x4A,  0x22,  0x4B,  0xFE,  0x7A,  0x22,  0x03,  0xFE,  0x00,  0x00,  0x0F, 	/* 2A370 */
+	0xFF,  0x00,  0x88,  0x01,  0x08,  0x8F,  0x00,  0x20,  0x03,  0xFE,  0x78,  0x20,  0x4F,  0xFF,  0x4C,  0x01, 	/* 2A380 */
+	0x4D,  0xFD,  0x49,  0x24,  0x49,  0xFC,  0x49,  0x24,  0x49,  0xFC,  0x78,  0x00,  0x07,  0xFF,  0x01,  0x22, 	/* 2A390 */
+	0x01,  0xBC,  0x02,  0x60,  0x0C,  0x1F,  0x94,  0x00,  0x20,  0x03,  0xFE,  0x78,  0x20,  0x4F,  0xFF,  0x4C, 	/* 2A3A0 */
+	0x01,  0x4D,  0xFD,  0x49,  0x24,  0x49,  0xFC,  0x49,  0x24,  0x49,  0xFC,  0x78,  0x46,  0x07,  0xFD,  0x01, 	/* 2A3B0 */
+	0x20,  0x01,  0xBC,  0x02,  0x60,  0x0C,  0x1F,  0xA0,  0x01,  0x02,  0x06,  0xFA,  0x74,  0x2A,  0x55,  0x2A, 	/* 2A3C0 */
+	0x57,  0x4A,  0x54,  0x9A,  0x51,  0x4A,  0x52,  0x2A,  0x55,  0xDA,  0x50,  0x8A,  0x53,  0xFA,  0x70,  0xA2, 	/* 2A3D0 */
+	0x04,  0xC2,  0x02,  0xB2,  0x01,  0xC2,  0x06,  0x06,  0xA2,  0x01,  0x00,  0x7F,  0xFC,  0x11,  0x10,  0x1F, 	/* 2A3E0 */
+	0xF0,  0x01,  0x00,  0x7F,  0xFE,  0x44,  0x22,  0x1A,  0x5E,  0x6F,  0xF8,  0x02,  0x40,  0x3F,  0xF8,  0x02, 	/* 2A3F0 */
+	0x40,  0x7F,  0xFE,  0x04,  0x88,  0x78,  0x70,  0x0E,  0x0E,  0xA5,  0x00,  0x88,  0x00,  0x88,  0x07,  0xFF, 	/* 2A400 */
+	0x78,  0x88,  0x48,  0xF8,  0x49,  0x04,  0x4F,  0x75,  0x49,  0x56,  0x49,  0x54,  0x49,  0x54,  0x4B,  0x75, 	/* 2A410 */
+	0x7D,  0x03,  0x00,  0x00,  0x02,  0x94,  0x04,  0x4A,  0x08,  0x49,  0xAE,  0x11,  0xE0,  0x10,  0x0E,  0x65, 	/* 2A420 */
+	0xEA,  0x29,  0x2A,  0x11,  0xEC,  0x1D,  0x0A,  0x65,  0xE9,  0x09,  0x09,  0x11,  0xEE,  0x21,  0x08,  0x7F, 	/* 2A430 */
+	0xFC,  0x20,  0x04,  0x27,  0xE4,  0x24,  0x24,  0x27,  0xE4,  0x20,  0x0C,  0xB4,  0x0F,  0x3C,  0x09,  0x24, 	/* 2A440 */
+	0x0F,  0x3C,  0x00,  0x00,  0x1F,  0xFF,  0x10,  0x00,  0x17,  0x90,  0x12,  0x10,  0x1F,  0xDF,  0x14,  0xA4, 	/* 2A450 */
+	0x17,  0xB4,  0x14,  0xD8,  0x27,  0x88,  0x24,  0x94,  0x47,  0xA2,  0x18,  0xC1,  0xB6,  0x00,  0x00,  0x03, 	/* 2A460 */
+	0xDE,  0x02,  0x52,  0x7B,  0xDE,  0x4A,  0x52,  0x4B,  0xDE,  0x4A,  0x52,  0x4B,  0xDE,  0x49,  0x4A,  0x4E, 	/* 2A470 */
+	0x31,  0x48,  0x40,  0x7F,  0xFF,  0x00,  0x88,  0x03,  0xD0,  0x00,  0x78,  0x07,  0x84,  0xBC,  0x00,  0x0C, 	/* 2A480 */
+	0x03,  0xF4,  0x79,  0x22,  0x4A,  0x11,  0x4F,  0xFE,  0x4A,  0x52,  0x4B,  0xFE,  0x48,  0x00,  0x4B,  0xE2, 	/* 2A490 */
+	0x4A,  0x3F,  0x4B,  0xE2,  0x7A,  0x32,  0x03,  0xEA,  0x02,  0x0A,  0x03,  0xE2,  0x02,  0x06,  0x80,  0x01, 	/* 2A4A0 */
+	0x08,  0x01,  0x7F,  0x7F,  0xC8,  0x51,  0x3E,  0x57,  0xAA,  0x55,  0xBE,  0x55,  0xAA,  0x57,  0xBE,  0x55, 	/* 2A4B0 */
+	0x92,  0x55,  0xFD,  0x57,  0x84,  0x71,  0x7F,  0x0F,  0xA4,  0x01,  0x14,  0x01,  0x04,  0x01,  0x0C,  0x81, 	/* 2A4C0 */
+	0x00,  0x00,  0x03,  0xFE,  0x78,  0x88,  0x48,  0xF8,  0x48,  0x88,  0x48,  0xFE,  0x4B,  0x88,  0x48,  0x08, 	/* 2A4D0 */
+	0x4F,  0xFF,  0x4A,  0x52,  0x4B,  0xDE,  0x7A,  0x52,  0x03,  0xDE,  0x02,  0x53,  0x0F,  0xFE,  0x00,  0x42, 	/* 2A4E0 */
+	0x82,  0x1F,  0x7C,  0x11,  0x44,  0x1F,  0x7C,  0x00,  0x00,  0x7F,  0xFF,  0x01,  0x00,  0x0F,  0xF8,  0x08, 	/* 2A4F0 */
+	0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x10,  0x04,  0x3F,  0x7E,  0x51,  0x45,  0x1F,  0x7C,  0x00, 	/* 2A500 */
+	0x00,  0x83,  0x01,  0x12,  0x01,  0x12,  0x7F,  0xE4,  0x54,  0xBF,  0x54,  0xE4,  0x54,  0xA4,  0x5B,  0x64, 	/* 2A510 */
+	0x5A,  0x3F,  0x51,  0x24,  0x5F,  0xE4,  0x51,  0x3F,  0x73,  0xA4,  0x03,  0x64,  0x05,  0x24,  0x09,  0x3F, 	/* 2A520 */
+	0x01,  0x00,  0x88,  0x00,  0x90,  0x07,  0xFF,  0x78,  0x90,  0x49,  0x08,  0x4B,  0xC8,  0x49,  0x3E,  0x4F, 	/* 2A530 */
+	0xEA,  0x4A,  0x5A,  0x4D,  0x6E,  0x4B,  0x8A,  0x79,  0xD3,  0x06,  0x21,  0x0F,  0xFE,  0x00,  0x98,  0x0F, 	/* 2A540 */
+	0xF4,  0x00,  0x02,  0x8E,  0x00,  0x1C,  0x07,  0x94,  0x74,  0xA2,  0x54,  0xFF,  0x54,  0xAB,  0x57,  0xBD, 	/* 2A550 */
+	0x54,  0xA9,  0x54,  0xBF,  0x57,  0x80,  0x54,  0x9E,  0x54,  0x92,  0x77,  0x9E,  0x03,  0x12,  0x02,  0x92, 	/* 2A560 */
+	0x04,  0x9E,  0x08,  0x00,  0x91,  0x00,  0x00,  0x07,  0xFE,  0x04,  0x02,  0x77,  0xFE,  0x57,  0xAE,  0x55, 	/* 2A570 */
+	0xE7,  0x55,  0xFE,  0x55,  0x4A,  0x55,  0xFE,  0x54,  0x40,  0x54,  0xFE,  0x75,  0xAA,  0x0A,  0xFA,  0x08, 	/* 2A580 */
+	0x2A,  0x11,  0xF6,  0x20,  0x0C,  0x93,  0x01,  0x00,  0x01,  0xFF,  0x77,  0x09,  0x51,  0xC9,  0x57,  0x11, 	/* 2A590 */
+	0x51,  0xE3,  0x57,  0x3C,  0x51,  0x20,  0x5F,  0xFF,  0x54,  0x92,  0x75,  0x6A,  0x07,  0xFE,  0x04,  0x92, 	/* 2A5A0 */
+	0x05,  0x6A,  0x07,  0xFE,  0x00,  0x00,  0x97,  0x00,  0x00,  0x3F,  0xFE,  0x20,  0x02,  0x20,  0x02,  0x20, 	/* 2A5B0 */
+	0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20, 	/* 2A5C0 */
+	0x02,  0x20,  0x02,  0x3F,  0xFE,  0x20,  0x02,  0x98,  0x00,  0x00,  0x3F,  0xFE,  0x20,  0x02,  0x20,  0x02, 	/* 2A5D0 */
+	0x27,  0xE2,  0x24,  0x22,  0x24,  0x22,  0x27,  0xE2,  0x24,  0x02,  0x24,  0x02,  0x24,  0x12,  0x24,  0x12, 	/* 2A5E0 */
+	0x23,  0xF2,  0x20,  0x02,  0x20,  0x02,  0x20,  0x06,  0x9A,  0x00,  0x00,  0x3F,  0xFE,  0x20,  0x02,  0x20, 	/* 2A5F0 */
+	0x82,  0x20,  0x82,  0x20,  0x82,  0x20,  0x82,  0x21,  0x42,  0x21,  0x42,  0x22,  0x22,  0x24,  0x12,  0x28, 	/* 2A600 */
+	0x0A,  0x30,  0x06,  0x20,  0x02,  0x3F,  0xFE,  0x00,  0x00,  0x9B,  0x00,  0x00,  0x00,  0x00,  0x7F,  0xFE, 	/* 2A610 */
+	0x44,  0x42,  0x44,  0x42,  0x44,  0x42,  0x44,  0x42,  0x44,  0x46,  0x48,  0x46,  0x48,  0x3E,  0x50,  0x02, 	/* 2A620 */
+	0x60,  0x02,  0x40,  0x02,  0x7F,  0xFE,  0x00,  0x00,  0x00,  0x00,  0x9E,  0x00,  0x00,  0x3F,  0xFE,  0x20, 	/* 2A630 */
+	0x02,  0x20,  0x02,  0x20,  0x02,  0x23,  0xE2,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x23, 	/* 2A640 */
+	0xE2,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x3F,  0xFE,  0x00,  0x00,  0xA0,  0x00,  0x00,  0x3F,  0xFE, 	/* 2A650 */
+	0x20,  0x02,  0x20,  0x82,  0x20,  0x82,  0x20,  0x82,  0x3F,  0xFE,  0x21,  0x42,  0x21,  0x42,  0x22,  0x22, 	/* 2A660 */
+	0x22,  0x22,  0x24,  0x12,  0x28,  0x0A,  0x20,  0x02,  0x3F,  0xFE,  0x00,  0x00,  0xA3,  0x00,  0x00,  0x3F, 	/* 2A670 */
+	0xFE,  0x20,  0x22,  0x20,  0x22,  0x20,  0x22,  0x2F,  0xFE,  0x20,  0x22,  0x24,  0x22,  0x22,  0x22,  0x22, 	/* 2A680 */
+	0x22,  0x20,  0x22,  0x20,  0x22,  0x20,  0x62,  0x20,  0x02,  0x3F,  0xFE,  0x00,  0x00,  0xAE,  0x00,  0x00, 	/* 2A690 */
+	0x3F,  0xFE,  0x22,  0x82,  0x22,  0x82,  0x24,  0x92,  0x24,  0x92,  0x2C,  0xA2,  0x34,  0xC2,  0x24,  0x82, 	/* 2A6A0 */
+	0x24,  0x82,  0x24,  0x8A,  0x24,  0x8A,  0x24,  0x7A,  0x24,  0x02,  0x3F,  0xFE,  0x20,  0x02,  0xB0,  0x00, 	/* 2A6B0 */
+	0x00,  0x3F,  0xFE,  0x20,  0x82,  0x20,  0x82,  0x20,  0x82,  0x3F,  0xFE,  0x21,  0xC2,  0x21,  0xC2,  0x22, 	/* 2A6C0 */
+	0xA2,  0x22,  0xA2,  0x24,  0x92,  0x28,  0x8A,  0x30,  0x86,  0x20,  0x82,  0x3F,  0xFE,  0x00,  0x00,  0xB2, 	/* 2A6D0 */
+	0x00,  0x00,  0x3F,  0xFE,  0x20,  0x02,  0x22,  0x22,  0x22,  0x22,  0x2F,  0xFA,  0x22,  0x22,  0x22,  0x22, 	/* 2A6E0 */
+	0x22,  0x22,  0x3F,  0xFE,  0x22,  0x22,  0x22,  0x22,  0x24,  0x22,  0x28,  0x22,  0x3F,  0xFE,  0x00,  0x00, 	/* 2A6F0 */
+	0xB3,  0x00,  0x00,  0x3F,  0xFE,  0x20,  0x02,  0x21,  0x0A,  0x28,  0x8A,  0x24,  0x92,  0x24,  0x12,  0x20, 	/* 2A700 */
+	0x22,  0x2E,  0x42,  0x21,  0x82,  0x21,  0x42,  0x26,  0x22,  0x38,  0x12,  0x20,  0x02,  0x3F,  0xFE,  0x00, 	/* 2A710 */
+	0x00,  0xB9,  0x00,  0x00,  0x3F,  0xFE,  0x20,  0x82,  0x21,  0x42,  0x22,  0x22,  0x24,  0x12,  0x3B,  0xEE, 	/* 2A720 */
+	0x20,  0x02,  0x2F,  0xF2,  0x21,  0x12,  0x21,  0x12,  0x21,  0x62,  0x21,  0x02,  0x21,  0x02,  0x3F,  0xFE, 	/* 2A730 */
+	0x20,  0x02,  0xBA,  0x00,  0x00,  0x3F,  0xFE,  0x20,  0x82,  0x20,  0x82,  0x20,  0x82,  0x3F,  0xFE,  0x20, 	/* 2A740 */
+	0x82,  0x20,  0x82,  0x27,  0xF2,  0x24,  0x12,  0x24,  0x12,  0x24,  0x12,  0x27,  0xF2,  0x20,  0x02,  0x3F, 	/* 2A750 */
+	0xFE,  0x00,  0x00,  0xBD,  0x00,  0x00,  0x3F,  0xFE,  0x20,  0x02,  0x2F,  0xFA,  0x20,  0x82,  0x20,  0x82, 	/* 2A760 */
+	0x20,  0x82,  0x27,  0xF2,  0x20,  0x82,  0x20,  0xA2,  0x20,  0x92,  0x20,  0x92,  0x2F,  0xFA,  0x20,  0x02, 	/* 2A770 */
+	0x3F,  0xFE,  0x00,  0x00,  0xBF,  0x00,  0x00,  0x3F,  0xFE,  0x20,  0x82,  0x20,  0x82,  0x3F,  0xFE,  0x21, 	/* 2A780 */
+	0x02,  0x23,  0xF2,  0x22,  0x12,  0x27,  0xF2,  0x2A,  0x12,  0x33,  0xF2,  0x22,  0x12,  0x22,  0x12,  0x22, 	/* 2A790 */
+	0x32,  0x3F,  0xFE,  0x20,  0x02,  0x80,  0x00,  0x00,  0x3F,  0xFE,  0x21,  0x22,  0x26,  0x26,  0x38,  0x9E, 	/* 2A7A0 */
+	0x20,  0x82,  0x3F,  0xFE,  0x21,  0x02,  0x21,  0xF2,  0x21,  0x12,  0x22,  0x12,  0x24,  0x12,  0x38,  0x62, 	/* 2A7B0 */
+	0x20,  0x02,  0x3F,  0xFE,  0x20,  0x02,  0x83,  0x00,  0x00,  0x3F,  0xFE,  0x20,  0x92,  0x20,  0x8A,  0x3F, 	/* 2A7C0 */
+	0xFE,  0x20,  0x82,  0x2F,  0xFA,  0x28,  0x8A,  0x2F,  0xFA,  0x28,  0x8A,  0x2F,  0xFA,  0x28,  0x8A,  0x28, 	/* 2A7D0 */
+	0x9A,  0x20,  0x02,  0x3F,  0xFE,  0x00,  0x00,  0x84,  0x00,  0x00,  0x3F,  0xFE,  0x20,  0x02,  0x2F,  0xFA, 	/* 2A7E0 */
+	0x20,  0x82,  0x2F,  0xF2,  0x21,  0x12,  0x3F,  0xFE,  0x20,  0x02,  0x27,  0xF2,  0x24,  0x12,  0x24,  0x12, 	/* 2A7F0 */
+	0x27,  0xF2,  0x20,  0x02,  0x3F,  0xFE,  0x20,  0x02,  0x88,  0x00,  0x00,  0x3F,  0xFE,  0x22,  0xA2,  0x24, 	/* 2A800 */
+	0x92,  0x2F,  0xFA,  0x21,  0x22,  0x3F,  0xFE,  0x22,  0x12,  0x27,  0xFA,  0x2A,  0x26,  0x32,  0x62,  0x22, 	/* 2A810 */
+	0x0A,  0x21,  0xFA,  0x20,  0x02,  0x3F,  0xFE,  0x20,  0x02,  0x89,  0x00,  0x00,  0x3F,  0xFE,  0x20,  0x82, 	/* 2A820 */
+	0x20,  0x82,  0x27,  0xFA,  0x20,  0x82,  0x3F,  0xFE,  0x24,  0x12,  0x22,  0x22,  0x2F,  0xFA,  0x20,  0x82, 	/* 2A830 */
+	0x3F,  0xFE,  0x20,  0x82,  0x20,  0x82,  0x3F,  0xFE,  0x20,  0x02,  0x8B,  0x00,  0x00,  0x3F,  0xFE,  0x20, 	/* 2A840 */
+	0x52,  0x20,  0x4A,  0x3F,  0xFE,  0x20,  0x42,  0x2F,  0x4A,  0x29,  0x4A,  0x2F,  0x52,  0x20,  0x22,  0x23, 	/* 2A850 */
+	0x6A,  0x3C,  0x9A,  0x21,  0x0A,  0x20,  0x02,  0x3F,  0xFE,  0x20,  0x02,  0x8D,  0x00,  0x00,  0x3F,  0xFE, 	/* 2A860 */
+	0x21,  0x02,  0x27,  0xF2,  0x21,  0x12,  0x3F,  0xFE,  0x24,  0x12,  0x27,  0xF2,  0x20,  0x42,  0x2F,  0xFA, 	/* 2A870 */
+	0x28,  0x42,  0x2F,  0xFE,  0x20,  0x42,  0x20,  0x42,  0x3F,  0xFE,  0x20,  0x02,  0x8F,  0x00,  0x00,  0x3F, 	/* 2A880 */
+	0xFE,  0x24,  0x92,  0x22,  0xA2,  0x2F,  0xFA,  0x21,  0x42,  0x3F,  0xFE,  0x22,  0x22,  0x27,  0xF2,  0x38, 	/* 2A890 */
+	0x2E,  0x27,  0xE2,  0x24,  0x12,  0x23,  0xF2,  0x20,  0x02,  0x3F,  0xFE,  0x00,  0x00,  0x92,  0x00,  0x00, 	/* 2A8A0 */
+	0x3F,  0xFE,  0x20,  0x82,  0x27,  0xF2,  0x20,  0x82,  0x3F,  0xFE,  0x20,  0x02,  0x27,  0xF2,  0x24,  0x12, 	/* 2A8B0 */
+	0x27,  0xF2,  0x23,  0x4A,  0x25,  0x32,  0x39,  0x1E,  0x21,  0x02,  0x3F,  0xFE,  0x20,  0x02,  0x93,  0x00, 	/* 2A8C0 */
+	0x00,  0x3F,  0xFE,  0x20,  0x02,  0x27,  0xF2,  0x24,  0x12,  0x2F,  0xFA,  0x28,  0x0A,  0x2F,  0xFA,  0x28, 	/* 2A8D0 */
+	0x0A,  0x2F,  0xFA,  0x28,  0x0A,  0x2F,  0xFA,  0x22,  0x32,  0x2C,  0x0A,  0x3F,  0xFE,  0x20,  0x02,  0x96, 	/* 2A8E0 */
+	0x00,  0x00,  0x3F,  0xFE,  0x20,  0x02,  0x27,  0xF2,  0x24,  0x12,  0x27,  0xF2,  0x20,  0x82,  0x3F,  0xFE, 	/* 2A8F0 */
+	0x28,  0x0A,  0x2B,  0xEA,  0x2A,  0x2A,  0x2B,  0xEA,  0x2F,  0xFA,  0x20,  0x02,  0x3F,  0xFE,  0x20,  0x02, 	/* 2A900 */
+	0x98,  0x00,  0x00,  0x3F,  0xFE,  0x20,  0x82,  0x3F,  0xFE,  0x20,  0x82,  0x27,  0xF2,  0x24,  0x92,  0x27, 	/* 2A910 */
+	0xF2,  0x24,  0x9A,  0x3F,  0xF6,  0x20,  0x22,  0x3F,  0xFE,  0x22,  0x22,  0x20,  0x62,  0x3F,  0xFE,  0x20, 	/* 2A920 */
+	0x02,  0x9C,  0x00,  0x00,  0x3F,  0xFE,  0x20,  0x02,  0x2F,  0xFA,  0x29,  0x4A,  0x3F,  0xFE,  0x20,  0x02, 	/* 2A930 */
+	0x27,  0xF2,  0x24,  0x12,  0x27,  0xF2,  0x21,  0x8A,  0x26,  0x52,  0x3B,  0xA2,  0x26,  0x1A,  0x3F,  0xFE, 	/* 2A940 */
+	0x00,  0x02,  0x9F,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x1F, 	/* 2A950 */
+	0xFC,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F, 	/* 2A960 */
+	0xFF,  0x00,  0x00,  0xA6,  0x08,  0x00,  0x08,  0xE0,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x7E,  0x20, 	/* 2A970 */
+	0x08,  0x20,  0x08,  0x20,  0x08,  0x30,  0x08,  0x50,  0x0E,  0x50,  0x18,  0x88,  0x60,  0x88,  0x01,  0x04, 	/* 2A980 */
+	0x02,  0x02,  0x0C,  0x01,  0xA7,  0x00,  0x00,  0x1F,  0xFE,  0x10,  0x00,  0x10,  0x40,  0x10,  0x40,  0x10, 	/* 2A990 */
+	0x40,  0x10,  0x40,  0x17,  0xFE,  0x10,  0x40,  0x10,  0x40,  0x10,  0x40,  0x20,  0x40,  0x20,  0x40,  0x5F, 	/* 2A9A0 */
+	0xFF,  0x00,  0x00,  0x00,  0x00,  0xA8,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFF,  0x02,  0x20, 	/* 2A9B0 */
+	0x02,  0x20,  0x0C,  0x20,  0x0C,  0x20,  0x0B,  0xFE,  0x18,  0x20,  0x28,  0x20,  0x48,  0x20,  0x08,  0x20, 	/* 2A9C0 */
+	0x08,  0x20,  0x0F,  0xFF,  0x08,  0x00,  0xAD,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00, 	/* 2A9D0 */
+	0x80,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x00,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00, 	/* 2A9E0 */
+	0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0xB0,  0x08,  0x10,  0x08,  0x90,  0x08,  0x90,  0x08,  0x92, 	/* 2A9F0 */
+	0x7E,  0x9E,  0x08,  0xF2,  0x0B,  0x92,  0x08,  0x92,  0x08,  0x92,  0x08,  0x92,  0x0A,  0x9C,  0x0C,  0x90, 	/* 2AA00 */
+	0x10,  0x80,  0x60,  0x81,  0x00,  0x41,  0x00,  0x3F,  0xB7,  0x00,  0x00,  0x0B,  0xFF,  0x08,  0x20,  0x08, 	/* 2AA10 */
+	0x20,  0x08,  0x20,  0x7E,  0x30,  0x08,  0x28,  0x08,  0x24,  0x08,  0x22,  0x08,  0x20,  0x0E,  0x20,  0x18, 	/* 2AA20 */
+	0x20,  0x60,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0xB8,  0x00,  0x20,  0x10,  0x20,  0x10,  0x20, 	/* 2AA30 */
+	0x10,  0x20,  0x10,  0x20,  0x7D,  0x22,  0x11,  0x22,  0x11,  0x22,  0x11,  0x22,  0x11,  0x22,  0x15,  0x22, 	/* 2AA40 */
+	0x19,  0x22,  0x61,  0x22,  0x01,  0x22,  0x01,  0xFE,  0x00,  0x00,  0xBB,  0x10,  0x04,  0x10,  0x18,  0x10, 	/* 2AA50 */
+	0xE0,  0x10,  0x80,  0x7C,  0x80,  0x10,  0xFF,  0x10,  0x88,  0x10,  0x88,  0x10,  0x88,  0x14,  0x88,  0x18, 	/* 2AA60 */
+	0x88,  0x61,  0x08,  0x01,  0x08,  0x02,  0x08,  0x04,  0x08,  0x00,  0x08,  0x80,  0x00,  0x20,  0x10,  0x20, 	/* 2AA70 */
+	0x10,  0x20,  0x11,  0x20,  0x11,  0x20,  0x7D,  0x20,  0x11,  0x3E,  0x11,  0x20,  0x11,  0x20,  0x11,  0x20, 	/* 2AA80 */
+	0x15,  0x20,  0x19,  0x20,  0x61,  0x20,  0x01,  0x20,  0x0F,  0xFF,  0x00,  0x00,  0x82,  0x08,  0x00,  0x09, 	/* 2AA90 */
+	0xFF,  0x09,  0x00,  0x09,  0x00,  0x7F,  0x00,  0x09,  0xFC,  0x09,  0x44,  0x09,  0x44,  0x09,  0x44,  0x09, 	/* 2AAA0 */
+	0x28,  0x0E,  0x28,  0x1A,  0x10,  0x62,  0x18,  0x04,  0x24,  0x08,  0xC2,  0x03,  0x01,  0x87,  0x00,  0x40, 	/* 2AAB0 */
+	0x08,  0x40,  0x08,  0x40,  0x08,  0xFE,  0x7E,  0x82,  0x09,  0x02,  0x0A,  0xC2,  0x08,  0x22,  0x08,  0x02, 	/* 2AAC0 */
+	0x08,  0x0A,  0x0E,  0x12,  0x18,  0x62,  0x61,  0x82,  0x00,  0x02,  0x00,  0x04,  0x00,  0x38,  0x8A,  0x08, 	/* 2AAD0 */
+	0x20,  0x08,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x7E,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x3C,  0x08, 	/* 2AAE0 */
+	0x44,  0x08,  0x44,  0x0E,  0x44,  0x18,  0x84,  0x60,  0x84,  0x01,  0x04,  0x02,  0x04,  0x04,  0x18,  0x8E, 	/* 2AAF0 */
+	0x00,  0x80,  0x10,  0x80,  0x10,  0x80,  0x10,  0xFE,  0x10,  0x82,  0x7D,  0x24,  0x11,  0x28,  0x12,  0x20, 	/* 2AB00 */
+	0x10,  0x20,  0x10,  0x30,  0x14,  0x50,  0x18,  0x48,  0x60,  0x88,  0x01,  0x04,  0x02,  0x02,  0x0C,  0x01, 	/* 2AB10 */
+	0x8F,  0x00,  0x00,  0x13,  0xFF,  0x10,  0x10,  0x10,  0x10,  0x10,  0x20,  0x7C,  0x20,  0x10,  0x68,  0x10, 	/* 2AB20 */
+	0xA4,  0x11,  0x22,  0x12,  0x21,  0x10,  0x20,  0x1C,  0x20,  0x60,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00, 	/* 2AB30 */
+	0x20,  0x90,  0x00,  0x80,  0x00,  0x80,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x0C,  0x94, 	/* 2AB40 */
+	0x12,  0x92,  0x12,  0xA2,  0x20,  0x80,  0x0F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF, 	/* 2AB50 */
+	0x00,  0x00,  0x91,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x7E,  0x00,  0x08,  0x00,  0x08, 	/* 2AB60 */
+	0xF0,  0x08,  0x90,  0x08,  0x90,  0x08,  0x90,  0x0E,  0x90,  0x18,  0x90,  0x61,  0x10,  0x01,  0x12,  0x02, 	/* 2AB70 */
+	0x12,  0x04,  0x0E,  0xA1,  0x00,  0x20,  0x10,  0x20,  0x10,  0x20,  0x13,  0xFF,  0x12,  0x22,  0x7E,  0x24, 	/* 2AB80 */
+	0x12,  0x20,  0x13,  0xFC,  0x12,  0x84,  0x12,  0x88,  0x16,  0x48,  0x1A,  0x30,  0x64,  0x30,  0x04,  0x48, 	/* 2AB90 */
+	0x09,  0x84,  0x16,  0x03,  0xA4,  0x00,  0x20,  0x08,  0x20,  0x08,  0x20,  0x09,  0xFE,  0x09,  0x22,  0x7F, 	/* 2ABA0 */
+	0x22,  0x09,  0xFE,  0x09,  0x22,  0x09,  0x22,  0x09,  0x22,  0x09,  0xFE,  0x0E,  0x20,  0x18,  0x20,  0x60, 	/* 2ABB0 */
+	0x20,  0x00,  0x20,  0x00,  0x20,  0xA6,  0x10,  0x00,  0x11,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x7D,  0x04, 	/* 2ABC0 */
+	0x11,  0x04,  0x11,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x17,  0x04,  0x19,  0x04,  0x61,  0xFC,  0x00,  0x00, 	/* 2ABD0 */
+	0x00,  0x00,  0x0F,  0xFF,  0x00,  0x00,  0xA9,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x17,  0xFF,  0x10, 	/* 2ABE0 */
+	0x84,  0x7C,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0xFC,  0x14,  0x84,  0x18,  0x84,  0x60, 	/* 2ABF0 */
+	0x84,  0x00,  0x84,  0x00,  0xFC,  0x00,  0x00,  0xAA,  0x00,  0x00,  0x13,  0xFE,  0x10,  0x24,  0x11,  0x24, 	/* 2AC00 */
+	0x10,  0xA4,  0x7C,  0xA8,  0x10,  0xA0,  0x10,  0x20,  0x17,  0xFF,  0x10,  0x20,  0x10,  0x20,  0x16,  0x20, 	/* 2AC10 */
+	0x18,  0x20,  0x60,  0x20,  0x00,  0x20,  0x00,  0x20,  0xBF,  0x00,  0x44,  0x10,  0x44,  0x10,  0x84,  0x10, 	/* 2AC20 */
+	0x84,  0x11,  0x7F,  0x7D,  0x04,  0x13,  0x04,  0x15,  0x44,  0x11,  0x24,  0x11,  0x24,  0x15,  0x04,  0x19, 	/* 2AC30 */
+	0x04,  0x61,  0x04,  0x01,  0x04,  0x01,  0x04,  0x01,  0x0C,  0x82,  0x00,  0x18,  0x00,  0xE0,  0x1F,  0x80, 	/* 2AC40 */
+	0x00,  0x80,  0x3F,  0xFE,  0x08,  0x88,  0x08,  0x88,  0x7F,  0xFF,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88, 	/* 2AC50 */
+	0x3F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x88,  0x04,  0x28,  0x04,  0x24,  0x08, 	/* 2AC60 */
+	0x24,  0x0B,  0xFF,  0x18,  0x20,  0x28,  0x10,  0x48,  0x10,  0x08,  0x09,  0x08,  0x85,  0x08,  0x83,  0x00, 	/* 2AC70 */
+	0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x89,  0x00,  0x40,  0x08,  0x40, 	/* 2AC80 */
+	0x08,  0x7E,  0x08,  0x82,  0x7E,  0x82,  0x09,  0xF2,  0x0A,  0x92,  0x08,  0x92,  0x08,  0x92,  0x08,  0xF2, 	/* 2AC90 */
+	0x0E,  0x84,  0x18,  0x98,  0x60,  0x80,  0x00,  0x81,  0x00,  0x81,  0x00,  0x7E,  0x8B,  0x00,  0x04,  0x7F, 	/* 2ACA0 */
+	0xA4,  0x12,  0x24,  0x12,  0x24,  0x12,  0x24,  0x7F,  0xE4,  0x12,  0x24,  0x12,  0x24,  0x12,  0x04,  0x22, 	/* 2ACB0 */
+	0x8C,  0x40,  0x80,  0x1F,  0xF8,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFE,  0x00,  0x00,  0x93,  0x10,  0x20, 	/* 2ACC0 */
+	0x10,  0x20,  0x10,  0x20,  0x17,  0xFF,  0x10,  0x40,  0x7C,  0x48,  0x10,  0x48,  0x11,  0x90,  0x10,  0x54, 	/* 2ACD0 */
+	0x10,  0x24,  0x14,  0x48,  0x19,  0x90,  0x60,  0x30,  0x00,  0x48,  0x01,  0x84,  0x06,  0x02,  0xA0,  0x10, 	/* 2ACE0 */
+	0x00,  0x11,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x7F,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x11, 	/* 2ACF0 */
+	0x22,  0x11,  0x22,  0x15,  0x14,  0x19,  0x18,  0x61,  0x08,  0x01,  0x64,  0x01,  0x82,  0x06,  0x01,  0xA2, 	/* 2AD00 */
+	0x00,  0x04,  0x10,  0x38,  0x11,  0xC0,  0x11,  0x00,  0x11,  0x00,  0x7D,  0xFF,  0x11,  0x00,  0x11,  0x00, 	/* 2AD10 */
+	0x11,  0xFC,  0x13,  0x84,  0x15,  0x84,  0x1A,  0x84,  0x62,  0x84,  0x04,  0x84,  0x08,  0xFC,  0x00,  0x00, 	/* 2AD20 */
+	0xA3,  0x08,  0x00,  0x09,  0xFE,  0x08,  0x00,  0x08,  0x00,  0x7E,  0xFC,  0x08,  0x84,  0x08,  0x84,  0x08, 	/* 2AD30 */
+	0xFC,  0x08,  0x84,  0x08,  0x84,  0x0E,  0x84,  0x18,  0xFC,  0x60,  0x00,  0x00,  0x00,  0x07,  0xFF,  0x00, 	/* 2AD40 */
+	0x00,  0xA4,  0x00,  0x00,  0x17,  0xFF,  0x10,  0x40,  0x10,  0x50,  0x10,  0x4C,  0x7C,  0x9A,  0x13,  0xE1, 	/* 2AD50 */
+	0x10,  0x00,  0x10,  0x20,  0x10,  0x20,  0x15,  0xFC,  0x18,  0x20,  0x60,  0x20,  0x00,  0x20,  0x07,  0xFF, 	/* 2AD60 */
+	0x00,  0x00,  0xAA,  0x01,  0x04,  0x10,  0x84,  0x10,  0x88,  0x13,  0xFE,  0x10,  0x88,  0x7C,  0x88,  0x10, 	/* 2AD70 */
+	0x88,  0x10,  0x88,  0x17,  0xFF,  0x10,  0x88,  0x10,  0x88,  0x1C,  0x88,  0x71,  0x08,  0x01,  0x08,  0x02, 	/* 2AD80 */
+	0x08,  0x04,  0x08,  0xB0,  0x00,  0x20,  0x10,  0x20,  0x10,  0x3E,  0x10,  0x20,  0x10,  0x20,  0x7F,  0xFF, 	/* 2AD90 */
+	0x10,  0x00,  0x10,  0x00,  0x13,  0xFF,  0x10,  0x20,  0x14,  0x30,  0x18,  0x2C,  0x60,  0x22,  0x00,  0x20, 	/* 2ADA0 */
+	0x00,  0x20,  0x00,  0x20,  0xB3,  0x00,  0x80,  0x10,  0xBE,  0x11,  0x00,  0x11,  0x00,  0x12,  0x00,  0x7C, 	/* 2ADB0 */
+	0xFF,  0x10,  0x84,  0x11,  0x04,  0x13,  0x04,  0x15,  0x04,  0x11,  0x04,  0x1D,  0x04,  0x61,  0x04,  0x01, 	/* 2ADC0 */
+	0x04,  0x01,  0x04,  0x01,  0x0C,  0x80,  0x00,  0x08,  0x00,  0x70,  0x1F,  0x80,  0x00,  0x80,  0x7F,  0xFF, 	/* 2ADD0 */
+	0x00,  0x80,  0x04,  0x92,  0x3C,  0x9C,  0x04,  0x90,  0x0C,  0x91,  0x34,  0x8F,  0x00,  0x80,  0x1F,  0xFC, 	/* 2ADE0 */
+	0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x83,  0x00,  0x20,  0x10,  0x28,  0x10,  0x44,  0x10,  0x8C,  0x13, 	/* 2ADF0 */
+	0xF2,  0x7C,  0x82,  0x10,  0x80,  0x10,  0xFE,  0x11,  0x20,  0x12,  0x20,  0x13,  0xFF,  0x1C,  0x20,  0x70, 	/* 2AE00 */
+	0x50,  0x00,  0x88,  0x03,  0x04,  0x0C,  0x03,  0x86,  0x00,  0x40,  0x10,  0x7C,  0x10,  0x88,  0x11,  0x10, 	/* 2AE10 */
+	0x13,  0xFE,  0x7D,  0x12,  0x11,  0x12,  0x11,  0xFE,  0x11,  0x12,  0x11,  0x12,  0x15,  0xFE,  0x19,  0x02, 	/* 2AE20 */
+	0x61,  0x02,  0x02,  0x02,  0x02,  0x02,  0x04,  0x06,  0x8B,  0x08,  0x00,  0x09,  0xFC,  0x09,  0x24,  0x09, 	/* 2AE30 */
+	0x24,  0x09,  0xFC,  0x7F,  0x24,  0x09,  0x24,  0x09,  0xFC,  0x08,  0x20,  0x08,  0x20,  0x0D,  0xFE,  0x18, 	/* 2AE40 */
+	0x20,  0x60,  0x20,  0x00,  0x20,  0x07,  0xFF,  0x00,  0x00,  0x8E,  0x10,  0x14,  0x10,  0x12,  0x10,  0x12, 	/* 2AE50 */
+	0x13,  0xFF,  0x7E,  0x10,  0x12,  0x12,  0x13,  0xD2,  0x12,  0x52,  0x12,  0x4C,  0x16,  0x4C,  0x1A,  0x48, 	/* 2AE60 */
+	0x62,  0x58,  0x04,  0x55,  0x05,  0xA5,  0x08,  0x43,  0x10,  0x01,  0x92,  0x00,  0x04,  0x10,  0x38,  0x13, 	/* 2AE70 */
+	0xC4,  0x10,  0x22,  0x11,  0x11,  0x7D,  0x11,  0x12,  0x00,  0x10,  0x08,  0x13,  0xFF,  0x10,  0x08,  0x14, 	/* 2AE80 */
+	0x88,  0x18,  0x48,  0x60,  0x48,  0x00,  0x08,  0x00,  0x08,  0x00,  0x18,  0x93,  0x10,  0x10,  0x10,  0x20, 	/* 2AE90 */
+	0x10,  0xD2,  0x13,  0x8C,  0x10,  0x48,  0x7C,  0x30,  0x10,  0x60,  0x13,  0x88,  0x10,  0x08,  0x11,  0xFF, 	/* 2AEA0 */
+	0x12,  0x08,  0x1D,  0x08,  0x60,  0x88,  0x00,  0x88,  0x00,  0x08,  0x00,  0x18,  0x94,  0x00,  0x24,  0x10, 	/* 2AEB0 */
+	0x22,  0x13,  0xFF,  0x10,  0x20,  0x10,  0x20,  0x7D,  0xFE,  0x11,  0x22,  0x11,  0x22,  0x11,  0xFE,  0x11, 	/* 2AEC0 */
+	0x22,  0x15,  0x22,  0x19,  0xFE,  0x61,  0x22,  0x01,  0x22,  0x01,  0x22,  0x01,  0x26,  0x96,  0x00,  0x88, 	/* 2AED0 */
+	0x10,  0x88,  0x17,  0xFF,  0x10,  0x88,  0x10,  0x88,  0x7C,  0x50,  0x10,  0x50,  0x10,  0x52,  0x10,  0x92, 	/* 2AEE0 */
+	0x10,  0x94,  0x15,  0x98,  0x1A,  0x90,  0x60,  0x90,  0x00,  0x91,  0x00,  0x91,  0x00,  0x8F,  0x9C,  0x04, 	/* 2AEF0 */
+	0x10,  0x04,  0x10,  0x7F,  0xFF,  0x0C,  0x18,  0x0E,  0x38,  0x15,  0x54,  0x24,  0x92,  0x44,  0x11,  0x04, 	/* 2AF00 */
+	0x10,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x9F, 	/* 2AF10 */
+	0x10,  0x10,  0x10,  0x14,  0x10,  0x12,  0x13,  0xFF,  0x10,  0x10,  0x7F,  0xD2,  0x12,  0x52,  0x12,  0x52, 	/* 2AF20 */
+	0x12,  0x54,  0x13,  0xCC,  0x12,  0x4C,  0x16,  0x28,  0x18,  0xCD,  0x63,  0x15,  0x0C,  0x23,  0x00,  0x41, 	/* 2AF30 */
+	0xA0,  0x00,  0x20,  0x10,  0x40,  0x11,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x7D,  0x00,  0x11,  0xFC,  0x11, 	/* 2AF40 */
+	0x04,  0x11,  0x04,  0x11,  0xFC,  0x14,  0x20,  0x1B,  0xFF,  0x60,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00, 	/* 2AF50 */
+	0x20,  0xA3,  0x10,  0x20,  0x10,  0x20,  0x13,  0xFE,  0x11,  0x08,  0x11,  0x08,  0x7D,  0x8C,  0x12,  0x52, 	/* 2AF60 */
+	0x14,  0x60,  0x10,  0x00,  0x10,  0x20,  0x17,  0xFF,  0x18,  0x20,  0x60,  0x20,  0x00,  0x20,  0x00,  0x20, 	/* 2AF70 */
+	0x00,  0x20,  0xB4,  0x00,  0x10,  0x10,  0x10,  0x13,  0xFF,  0x10,  0x10,  0x10,  0x7C,  0x7C,  0x44,  0x11, 	/* 2AF80 */
+	0x44,  0x11,  0x7C,  0x11,  0x44,  0x11,  0x7C,  0x13,  0x44,  0x1D,  0x44,  0x71,  0x7C,  0x01,  0x00,  0x01, 	/* 2AF90 */
+	0xFF,  0x00,  0x00,  0xB7,  0x08,  0x20,  0x08,  0x20,  0x3F,  0x20,  0x08,  0x20,  0x08,  0xFC,  0x7F,  0xA4, 	/* 2AFA0 */
+	0x22,  0x24,  0x14,  0xA4,  0x7F,  0x64,  0x08,  0x24,  0x08,  0x24,  0x3F,  0x54,  0x08,  0x54,  0x08,  0x85, 	/* 2AFB0 */
+	0x09,  0x05,  0x0A,  0x03,  0xB9,  0x00,  0x20,  0x10,  0x20,  0x13,  0xFE,  0x11,  0x04,  0x10,  0x84,  0x7C, 	/* 2AFC0 */
+	0x88,  0x10,  0x88,  0x17,  0xFF,  0x10,  0x00,  0x10,  0x00,  0x17,  0xFC,  0x19,  0x04,  0x61,  0x04,  0x01, 	/* 2AFD0 */
+	0x04,  0x01,  0xFC,  0x00,  0x00,  0xBA,  0x04,  0x10,  0x04,  0x10,  0x3F,  0xFE,  0x04,  0x10,  0x07,  0xF0, 	/* 2AFE0 */
+	0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x90,  0x08,  0x88,  0x17,  0xF4,  0x60,  0x83, 	/* 2AFF0 */
+	0x00,  0x80,  0x3F,  0xFE,  0x00,  0x00,  0xBC,  0x00,  0x20,  0x10,  0x20,  0x13,  0xFE,  0x10,  0x30,  0x10, 	/* 2B000 */
+	0x48,  0x7D,  0x84,  0x10,  0x00,  0x13,  0xFF,  0x10,  0x04,  0x11,  0xE4,  0x11,  0x24,  0x15,  0x24,  0x19, 	/* 2B010 */
+	0xE4,  0x60,  0x04,  0x00,  0x04,  0x00,  0x0C,  0x80,  0x00,  0x00,  0x13,  0xFE,  0x12,  0x02,  0x12,  0x02, 	/* 2B020 */
+	0x13,  0xFE,  0x7E,  0x10,  0x12,  0x92,  0x12,  0x92,  0x12,  0x92,  0x12,  0xFE,  0x16,  0x10,  0x1A,  0x92, 	/* 2B030 */
+	0x64,  0x92,  0x04,  0x92,  0x08,  0xFE,  0x10,  0x00,  0x82,  0x11,  0x10,  0x09,  0x10,  0x09,  0x20,  0x7F, 	/* 2B040 */
+	0xFE,  0x40,  0x02,  0x4F,  0xF2,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x01,  0x00,  0x01,  0x00,  0x1F, 	/* 2B050 */
+	0xF8,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x00,  0x00,  0x85,  0x00,  0x00,  0x3F,  0xFC,  0x24,  0x24, 	/* 2B060 */
+	0x24,  0x24,  0x3F,  0x14,  0x21,  0x18,  0x3F,  0x08,  0x24,  0x14,  0x24,  0x62,  0x3F,  0x81,  0x00,  0x80, 	/* 2B070 */
+	0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x86,  0x00,  0x44,  0x08,  0x44,  0x08, 	/* 2B080 */
+	0x88,  0x08,  0xFF,  0x09,  0x88,  0x7E,  0x88,  0x08,  0x88,  0x08,  0xFE,  0x08,  0x88,  0x08,  0x88,  0x08, 	/* 2B090 */
+	0xFE,  0x0E,  0x88,  0x18,  0x88,  0x60,  0x88,  0x00,  0xFF,  0x00,  0x00,  0x8A,  0x00,  0x00,  0x3F,  0xFE, 	/* 2B0A0 */
+	0x02,  0x20,  0x0E,  0x38,  0x08,  0x08,  0x08,  0x08,  0x0E,  0x38,  0x02,  0x20,  0x7F,  0xFF,  0x00,  0x80, 	/* 2B0B0 */
+	0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x8B,  0x10,  0x00,  0x13, 	/* 2B0C0 */
+	0xDE,  0x12,  0x52,  0x12,  0x52,  0x7E,  0x52,  0x13,  0xDE,  0x12,  0x52,  0x12,  0x52,  0x12,  0x52,  0x17, 	/* 2B0D0 */
+	0xDE,  0x1A,  0x52,  0x62,  0x52,  0x02,  0x52,  0x02,  0x52,  0x04,  0x62,  0x08,  0xC6,  0x95,  0x00,  0x40, 	/* 2B0E0 */
+	0x3C,  0x40,  0x27,  0xFE,  0x28,  0x40,  0x30,  0xFC,  0x28,  0x84,  0x25,  0xFC,  0x25,  0x84,  0x3A,  0xFC, 	/* 2B0F0 */
+	0x24,  0x84,  0x20,  0x8C,  0x20,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x99,  0x00, 	/* 2B100 */
+	0x00,  0x17,  0xFF,  0x10,  0x50,  0x10,  0x50,  0x11,  0xFE,  0x7D,  0x52,  0x11,  0x52,  0x11,  0x52,  0x11, 	/* 2B110 */
+	0xFE,  0x10,  0x20,  0x14,  0x20,  0x1B,  0xFE,  0x60,  0x20,  0x00,  0x20,  0x07,  0xFF,  0x00,  0x00,  0x9D, 	/* 2B120 */
+	0x00,  0x00,  0x10,  0xF8,  0x10,  0x88,  0x10,  0x88,  0x10,  0xB8,  0x7E,  0xA8,  0x10,  0xA8,  0x13,  0xFE, 	/* 2B130 */
+	0x12,  0x02,  0x12,  0x7A,  0x12,  0x4A,  0x1E,  0x4A,  0x72,  0x4A,  0x02,  0x7A,  0x02,  0x02,  0x02,  0x06, 	/* 2B140 */
+	0xA1,  0x04,  0x00,  0x05,  0xFC,  0x09,  0x04,  0x11,  0x04,  0x31,  0xFC,  0x50,  0x20,  0x17,  0xFF,  0x10, 	/* 2B150 */
+	0x70,  0x11,  0xAC,  0x16,  0x23,  0x00,  0xA0,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00, 	/* 2B160 */
+	0x00,  0xA4,  0x00,  0x00,  0x10,  0xFC,  0x10,  0x84,  0x10,  0xFC,  0x10,  0x84,  0x7C,  0x84,  0x10,  0xFC, 	/* 2B170 */
+	0x10,  0x00,  0x17,  0xFF,  0x10,  0x20,  0x11,  0x20,  0x1D,  0x3E,  0x71,  0x20,  0x02,  0xA0,  0x04,  0x60, 	/* 2B180 */
+	0x18,  0x1F,  0xAA,  0x00,  0x84,  0x10,  0x84,  0x13,  0xFF,  0x10,  0x84,  0x10,  0xFC,  0x7C,  0x84,  0x10, 	/* 2B190 */
+	0xFC,  0x10,  0x84,  0x10,  0x84,  0x17,  0xFF,  0x12,  0x50,  0x16,  0x52,  0x1A,  0x8E,  0x63,  0x00,  0x03, 	/* 2B1A0 */
+	0xFF,  0x00,  0x00,  0xAF,  0x00,  0x80,  0x0F,  0xF8,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x00,  0x04,  0x10, 	/* 2B1B0 */
+	0x3F,  0x7E,  0x04,  0x10,  0x07,  0x10,  0x78,  0xFF,  0x00,  0x00,  0x7F,  0xFE,  0x02,  0x20,  0x04,  0x21, 	/* 2B1C0 */
+	0x18,  0x21,  0x60,  0x1F,  0xB0,  0x10,  0x00,  0x13,  0xFF,  0x12,  0x00,  0x12,  0xFC,  0x12,  0x84,  0x7E, 	/* 2B1D0 */
+	0xFC,  0x12,  0x84,  0x12,  0xFC,  0x12,  0x20,  0x13,  0xFF,  0x16,  0x48,  0x1A,  0xD0,  0x62,  0x38,  0x02, 	/* 2B1E0 */
+	0xC4,  0x03,  0xFF,  0x02,  0x00,  0xB1,  0x08,  0x00,  0x08,  0x7E,  0x3F,  0x42,  0x08,  0x42,  0x08,  0x4C, 	/* 2B1F0 */
+	0x7F,  0x40,  0x22,  0x7E,  0x12,  0x62,  0x14,  0x62,  0x7F,  0xD4,  0x08,  0x54,  0x08,  0x48,  0x3F,  0x48, 	/* 2B200 */
+	0x08,  0x54,  0x08,  0x62,  0x08,  0x41,  0xB4,  0x00,  0x00,  0x10,  0xFC,  0x10,  0x84,  0x10,  0xFC,  0x10, 	/* 2B210 */
+	0x84,  0x7E,  0xFC,  0x10,  0x00,  0x17,  0xFF,  0x10,  0x80,  0x10,  0xFE,  0x15,  0x4A,  0x1A,  0x4A,  0x10, 	/* 2B220 */
+	0x92,  0x61,  0x12,  0x02,  0x22,  0x00,  0x4C,  0xB5,  0x10,  0x20,  0x10,  0x24,  0x11,  0xFC,  0x10,  0x24, 	/* 2B230 */
+	0x7C,  0x28,  0x10,  0x30,  0x13,  0xFF,  0x10,  0x20,  0x10,  0xFC,  0x12,  0x84,  0x1D,  0x84,  0x12,  0xFC, 	/* 2B240 */
+	0x64,  0x84,  0x00,  0x84,  0x00,  0xFC,  0x00,  0x00,  0xBA,  0x00,  0x00,  0x11,  0xFE,  0x11,  0x22,  0x11, 	/* 2B250 */
+	0x22,  0x11,  0xFE,  0x7D,  0x22,  0x11,  0x22,  0x11,  0xFE,  0x10,  0x50,  0x10,  0x88,  0x15,  0x4C,  0x1A, 	/* 2B260 */
+	0x4B,  0x60,  0x48,  0x00,  0x88,  0x01,  0x08,  0x02,  0x08,  0xBD,  0x10,  0x00,  0x11,  0xFE,  0x11,  0x52, 	/* 2B270 */
+	0x11,  0x52,  0x11,  0xFE,  0x7E,  0x00,  0x11,  0xFF,  0x10,  0x20,  0x10,  0x20,  0x11,  0x20,  0x17,  0x3E, 	/* 2B280 */
+	0x19,  0x20,  0x61,  0x20,  0x01,  0x20,  0x01,  0xFF,  0x00,  0x00,  0x80,  0x10,  0x00,  0x13,  0xFE,  0x12, 	/* 2B290 */
+	0x02,  0x12,  0x02,  0x7F,  0xFE,  0x12,  0x84,  0x12,  0x48,  0x13,  0xFE,  0x12,  0x48,  0x16,  0x48,  0x1B, 	/* 2B2A0 */
+	0xFF,  0x62,  0x48,  0x04,  0x48,  0x04,  0x88,  0x08,  0x88,  0x11,  0x08,  0x81,  0x00,  0x00,  0x0F,  0xF8, 	/* 2B2B0 */
+	0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x0F,  0xFA,  0x30,  0x0C,  0x08,  0x10,  0x03,  0x40, 	/* 2B2C0 */
+	0x0C,  0xB8,  0x30,  0x86,  0x07,  0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x8A,  0x00,  0x20,  0x10, 	/* 2B2D0 */
+	0x40,  0x11,  0xFC,  0x11,  0x24,  0x11,  0x24,  0x7F,  0xFC,  0x11,  0x24,  0x11,  0x24,  0x11,  0xFC,  0x10, 	/* 2B2E0 */
+	0x54,  0x16,  0x54,  0x18,  0x9A,  0x60,  0x9F,  0x01,  0x10,  0x06,  0x11,  0x18,  0x0F,  0x8B,  0x08,  0x10, 	/* 2B2F0 */
+	0x2A,  0x54,  0x2A,  0x54,  0x28,  0x50,  0x4C,  0x98,  0x12,  0x24,  0x20,  0x40,  0x7F,  0xFE,  0x40,  0x02, 	/* 2B300 */
+	0x41,  0x02,  0x01,  0x00,  0x1F,  0xF8,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x00,  0x00,  0x91,  0x11, 	/* 2B310 */
+	0x00,  0x0A,  0x3E,  0x7F,  0xA2,  0x04,  0x3E,  0x25,  0x22,  0x25,  0x3E,  0x25,  0x22,  0x3F,  0x22,  0x04, 	/* 2B320 */
+	0x22,  0x08,  0x46,  0x10,  0x80,  0x2F,  0xF8,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x92, 	/* 2B330 */
+	0x10,  0x10,  0x10,  0x10,  0x13,  0xFE,  0x12,  0x90,  0x12,  0x90,  0x7E,  0x90,  0x12,  0xFF,  0x13,  0x84, 	/* 2B340 */
+	0x12,  0x84,  0x12,  0xFF,  0x16,  0x84,  0x1A,  0xC4,  0x63,  0xA4,  0x00,  0x24,  0x00,  0x04,  0x00,  0x0C, 	/* 2B350 */
+	0x94,  0x00,  0x88,  0x10,  0x88,  0x17,  0xFF,  0x10,  0x88,  0x10,  0x20,  0x7C,  0x20,  0x10,  0x50,  0x10, 	/* 2B360 */
+	0x88,  0x11,  0xFC,  0x16,  0x03,  0x10,  0x00,  0x1D,  0xFC,  0x71,  0x04,  0x01,  0x04,  0x01,  0xFC,  0x00, 	/* 2B370 */
+	0x00,  0x97,  0x00,  0x20,  0x18,  0x20,  0x04,  0x50,  0x61,  0x8C,  0x16,  0xFB,  0x00,  0x20,  0x0F,  0xFF, 	/* 2B380 */
+	0x11,  0x28,  0x21,  0x24,  0x42,  0x62,  0x00,  0x80,  0x0F,  0xF8,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF, 	/* 2B390 */
+	0x00,  0x00,  0x98,  0x00,  0x20,  0x10,  0x20,  0x11,  0xFF,  0x11,  0x10,  0x11,  0xFE,  0x7D,  0x12,  0x11, 	/* 2B3A0 */
+	0xFF,  0x11,  0x12,  0x11,  0x12,  0x11,  0xFE,  0x15,  0x00,  0x1A,  0xFE,  0x62,  0x82,  0x04,  0x82,  0x08, 	/* 2B3B0 */
+	0xFE,  0x00,  0x00,  0x99,  0x10,  0x20,  0x10,  0x20,  0x13,  0xFF,  0x10,  0x00,  0x7C,  0xF8,  0x10,  0x88, 	/* 2B3C0 */
+	0x10,  0xF8,  0x10,  0x00,  0x13,  0xFE,  0x12,  0x02,  0x1E,  0xFA,  0x72,  0x8A,  0x02,  0x8A,  0x02,  0xFA, 	/* 2B3D0 */
+	0x02,  0x02,  0x02,  0x06,  0x9A,  0x00,  0x00,  0x13,  0xFE,  0x12,  0x02,  0x12,  0x02,  0x13,  0xFC,  0x7C, 	/* 2B3E0 */
+	0x40,  0x10,  0x84,  0x11,  0x54,  0x16,  0x74,  0x10,  0xA8,  0x11,  0x28,  0x1E,  0x64,  0x70,  0xA2,  0x03, 	/* 2B3F0 */
+	0x21,  0x0C,  0x20,  0x00,  0xC0,  0x9E,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x44,  0x42,  0x5F,  0xFA, 	/* 2B400 */
+	0x04,  0x40,  0x1F,  0xF8,  0x04,  0x40,  0x7F,  0xFE,  0x04,  0x40,  0x09,  0x20,  0x1F,  0xF8,  0x61,  0x06, 	/* 2B410 */
+	0x01,  0x00,  0x7F,  0xFE,  0x00,  0x00,  0xA2,  0x10,  0x20,  0x10,  0x40,  0x11,  0xFC,  0x11,  0x04,  0x11, 	/* 2B420 */
+	0x04,  0x7D,  0xFC,  0x11,  0x00,  0x11,  0x00,  0x11,  0xFF,  0x11,  0x00,  0x15,  0xFE,  0x18,  0x2A,  0x62, 	/* 2B430 */
+	0x96,  0x02,  0x52,  0x04,  0x42,  0x08,  0x0C,  0xA9,  0x01,  0x00,  0x11,  0x00,  0x11,  0xFE,  0x12,  0x00, 	/* 2B440 */
+	0x13,  0xF8,  0x7D,  0x08,  0x15,  0x08,  0x11,  0xF8,  0x10,  0x00,  0x13,  0xFC,  0x16,  0x94,  0x1A,  0x94, 	/* 2B450 */
+	0x62,  0x94,  0x02,  0x94,  0x0F,  0xFF,  0x00,  0x00,  0xAB,  0x00,  0x20,  0x10,  0x20,  0x13,  0xFF,  0x10, 	/* 2B460 */
+	0x20,  0x10,  0xFC,  0x7E,  0x84,  0x10,  0xFC,  0x10,  0x84,  0x10,  0xFC,  0x10,  0x84,  0x10,  0xFC,  0x14, 	/* 2B470 */
+	0x00,  0x1B,  0xFF,  0x60,  0x48,  0x01,  0x84,  0x06,  0x02,  0xB0,  0x00,  0x80,  0x10,  0xFF,  0x09,  0x00, 	/* 2B480 */
+	0x02,  0xFC,  0x24,  0xA4,  0x10,  0x94,  0x03,  0xFF,  0x09,  0x24,  0x11,  0x14,  0x21,  0xFF,  0x40,  0x04, 	/* 2B490 */
+	0x00,  0x98,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0xB2,  0x10,  0x40,  0x10,  0x7E,  0x10, 	/* 2B4A0 */
+	0x80,  0x11,  0xFC,  0x7E,  0x84,  0x10,  0xFC,  0x10,  0x84,  0x10,  0xFC,  0x10,  0x00,  0x13,  0xFF,  0x1C, 	/* 2B4B0 */
+	0x80,  0x71,  0xFE,  0x02,  0x4A,  0x04,  0x92,  0x01,  0x22,  0x00,  0x4C,  0xB5,  0x00,  0x80,  0x00,  0x80, 	/* 2B4C0 */
+	0x1F,  0xFF,  0x11,  0x20,  0x1F,  0xFC,  0x11,  0x24,  0x1F,  0xFC,  0x14,  0x20,  0x17,  0xA4,  0x24,  0x3A, 	/* 2B4D0 */
+	0x27,  0xA2,  0x5C,  0x9E,  0x0F,  0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0xB9,  0x04,  0x04,  0x7F, 	/* 2B4E0 */
+	0xB8,  0x04,  0x20,  0x3F,  0x20,  0x25,  0x3F,  0x3F,  0x24,  0x25,  0x24,  0x3F,  0x24,  0x04,  0x24,  0x7F, 	/* 2B4F0 */
+	0xC4,  0x04,  0x04,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0xBE,  0x04,  0x10, 	/* 2B500 */
+	0x7F,  0x90,  0x1E,  0x10,  0x12,  0xFC,  0x1E,  0x14,  0x00,  0x54,  0x3E,  0x24,  0x05,  0x34,  0x1E,  0x55, 	/* 2B510 */
+	0x64,  0x8B,  0x0C,  0x81,  0x1F,  0xF8,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x83,  0x00, 	/* 2B520 */
+	0x20,  0x10,  0x20,  0x17,  0xFE,  0x11,  0x08,  0x10,  0x90,  0x7F,  0xFF,  0x10,  0x00,  0x11,  0xFC,  0x11, 	/* 2B530 */
+	0x04,  0x11,  0xFC,  0x15,  0x04,  0x19,  0xFC,  0x60,  0x50,  0x00,  0x91,  0x03,  0x11,  0x0C,  0x0F,  0x85, 	/* 2B540 */
+	0x00,  0x00,  0x3F,  0x7E,  0x29,  0x02,  0x3F,  0x14,  0x29,  0x08,  0x3F,  0x7F,  0x08,  0x0A,  0x3F,  0x0C, 	/* 2B550 */
+	0x08,  0x08,  0x0F,  0x08,  0x70,  0x98,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00, 	/* 2B560 */
+	0x93,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x20,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F, 	/* 2B570 */
+	0xF8,  0x01,  0x00,  0x7F,  0xFF,  0x02,  0xA0,  0x0F,  0xF8,  0x70,  0x87,  0x00,  0x80,  0x3F,  0xFE,  0x00, 	/* 2B580 */
+	0x00,  0x97,  0x01,  0x04,  0x10,  0x88,  0x13,  0xFE,  0x12,  0x22,  0x12,  0x22,  0x7F,  0xFE,  0x12,  0x22, 	/* 2B590 */
+	0x13,  0xFE,  0x10,  0x00,  0x11,  0xFC,  0x15,  0x04,  0x19,  0xFC,  0x61,  0x04,  0x01,  0x04,  0x01,  0xFC, 	/* 2B5A0 */
+	0x00,  0x00,  0x9C,  0x00,  0x84,  0x3C,  0x48,  0x27,  0xFF,  0x28,  0x40,  0x30,  0xAA,  0x2B,  0x5C,  0x24, 	/* 2B5B0 */
+	0xB8,  0x27,  0x54,  0x24,  0x92,  0x3B,  0x11,  0x20,  0x30,  0x20,  0x80,  0x0F,  0xF8,  0x00,  0x80,  0x7F, 	/* 2B5C0 */
+	0xFF,  0x00,  0x00,  0x9F,  0x10,  0x20,  0x10,  0x3E,  0x10,  0x20,  0x11,  0xFF,  0x11,  0x42,  0x7D,  0x48, 	/* 2B5D0 */
+	0x11,  0x70,  0x11,  0xC2,  0x11,  0x3E,  0x11,  0x00,  0x15,  0xAA,  0x1A,  0xAA,  0x62,  0xEE,  0x04,  0x28, 	/* 2B5E0 */
+	0x0B,  0xFF,  0x00,  0x00,  0xA8,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88,  0x0F, 	/* 2B5F0 */
+	0xF8,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFE,  0x12,  0x24,  0x61,  0x92,  0x1F,  0xF8,  0x00, 	/* 2B600 */
+	0x80,  0x7F,  0xFF,  0x00,  0x00,  0xAB,  0x10,  0xBC,  0x10,  0x84,  0x11,  0xFC,  0x12,  0x52,  0x15,  0xFD, 	/* 2B610 */
+	0x7D,  0x54,  0x11,  0x9C,  0x11,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x14,  0x08,  0x1B,  0xFF,  0x60,  0x88, 	/* 2B620 */
+	0x00,  0x48,  0x00,  0x08,  0x00,  0x18,  0xAE,  0x00,  0x20,  0x3D,  0xFF,  0x24,  0x40,  0x28,  0xFE,  0x31, 	/* 2B630 */
+	0x10,  0x2A,  0xFF,  0x24,  0x44,  0x24,  0x7C,  0x24,  0x44,  0x38,  0x7C,  0x20,  0x4C,  0x20,  0x80,  0x0F, 	/* 2B640 */
+	0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0xB3,  0x00,  0x20,  0x13,  0xFE,  0x10,  0x20,  0x10,  0x88, 	/* 2B650 */
+	0x17,  0xFF,  0x7C,  0x88,  0x10,  0x00,  0x11,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x15,  0x04,  0x19,  0xFC, 	/* 2B660 */
+	0x61,  0x04,  0x01,  0xFC,  0x01,  0x8C,  0x06,  0x02,  0xB8,  0x10,  0x88,  0x10,  0x88,  0x17,  0xFF,  0x10, 	/* 2B670 */
+	0xA8,  0x10,  0x24,  0x7D,  0xFC,  0x10,  0x28,  0x17,  0xFF,  0x10,  0x28,  0x10,  0x44,  0x14,  0xFC,  0x19, 	/* 2B680 */
+	0x84,  0x66,  0xFC,  0x00,  0x84,  0x00,  0xFC,  0x00,  0x00,  0xB9,  0x10,  0x00,  0x13,  0xDE,  0x12,  0x52, 	/* 2B690 */
+	0x13,  0xDE,  0x12,  0x52,  0x7E,  0x52,  0x13,  0xDE,  0x12,  0x02,  0x12,  0xFA,  0x12,  0x8A,  0x16,  0xFA, 	/* 2B6A0 */
+	0x1A,  0x8A,  0x62,  0x8A,  0x02,  0xFA,  0x02,  0x02,  0x02,  0x06,  0xBA,  0x10,  0x20,  0x10,  0x40,  0x11, 	/* 2B6B0 */
+	0xFE,  0x11,  0x12,  0x11,  0xEA,  0x7D,  0xB2,  0x11,  0xFE,  0x11,  0x72,  0x11,  0xAA,  0x11,  0x26,  0x14, 	/* 2B6C0 */
+	0x20,  0x1B,  0xFF,  0x60,  0x30,  0x00,  0x48,  0x01,  0x84,  0x06,  0x03,  0xBB,  0x10,  0x20,  0x13,  0xFE, 	/* 2B6D0 */
+	0x11,  0x24,  0x11,  0x24,  0x11,  0xA6,  0x7D,  0x6A,  0x12,  0x30,  0x17,  0xFF,  0x10,  0x00,  0x11,  0xFE, 	/* 2B6E0 */
+	0x15,  0x7A,  0x19,  0x4A,  0x61,  0x7A,  0x01,  0x02,  0x01,  0xFE,  0x00,  0x00,  0xBE,  0x04,  0x00,  0x39, 	/* 2B6F0 */
+	0x7C,  0x26,  0x44,  0x1C,  0x7C,  0x76,  0x44,  0x09,  0x7E,  0x33,  0x52,  0x05,  0x54,  0x19,  0x48,  0x62, 	/* 2B700 */
+	0x74,  0x0C,  0xC3,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x81,  0x00,  0x08, 	/* 2B710 */
+	0x1F,  0x08,  0x11,  0x7F,  0x11,  0x22,  0x1F,  0x14,  0x10,  0x7F,  0x2F,  0x08,  0x29,  0x7F,  0x49,  0x08, 	/* 2B720 */
+	0x0F,  0x08,  0x00,  0x88,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x85,  0x00, 	/* 2B730 */
+	0x80,  0x7F,  0xFF,  0x08,  0x24,  0x0A,  0x48,  0x74,  0xFE,  0x15,  0x90,  0x08,  0xFE,  0x0E,  0x90,  0x72, 	/* 2B740 */
+	0xFE,  0x04,  0x90,  0x08,  0xFF,  0x30,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x87, 	/* 2B750 */
+	0x00,  0x20,  0x13,  0xFF,  0x10,  0x00,  0x11,  0xFE,  0x11,  0x7A,  0x7D,  0x4A,  0x11,  0x7A,  0x11,  0x02, 	/* 2B760 */
+	0x11,  0xFE,  0x10,  0x84,  0x14,  0xFC,  0x18,  0x84,  0x60,  0xFC,  0x00,  0x84,  0x07,  0xFF,  0x00,  0x00, 	/* 2B770 */
+	0x8A,  0x00,  0x20,  0x10,  0x20,  0x13,  0xFE,  0x10,  0x20,  0x11,  0xFC,  0x7F,  0x54,  0x11,  0x54,  0x11, 	/* 2B780 */
+	0xFC,  0x10,  0x20,  0x13,  0xFF,  0x14,  0x44,  0x18,  0xA8,  0x61,  0x90,  0x06,  0x88,  0x00,  0xE4,  0x03, 	/* 2B790 */
+	0x83,  0x8C,  0x00,  0x20,  0x10,  0x20,  0x13,  0xFF,  0x10,  0x48,  0x10,  0x84,  0x7F,  0x4B,  0x11,  0xFE, 	/* 2B7A0 */
+	0x10,  0x48,  0x11,  0xFE,  0x10,  0x48,  0x13,  0xFF,  0x1C,  0x62,  0x70,  0x94,  0x07,  0x88,  0x00,  0xE4, 	/* 2B7B0 */
+	0x03,  0x83,  0x91,  0x04,  0x00,  0x07,  0xFC,  0x04,  0x24,  0x7F,  0xA4,  0x44,  0xA4,  0x25,  0x14,  0x4A, 	/* 2B7C0 */
+	0x98,  0x11,  0x08,  0x7F,  0x94,  0x11,  0x22,  0x1F,  0x41,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F, 	/* 2B7D0 */
+	0xFF,  0x00,  0x00,  0x93,  0x00,  0x00,  0x1F,  0xFF,  0x14,  0x8C,  0x17,  0x8A,  0x10,  0x7F,  0x17,  0x88, 	/* 2B7E0 */
+	0x14,  0x88,  0x17,  0x94,  0x14,  0x94,  0x27,  0xA2,  0x24,  0xC1,  0x40,  0x80,  0x0F,  0xFC,  0x00,  0x80, 	/* 2B7F0 */
+	0x7F,  0xFF,  0x00,  0x00,  0x95,  0x00,  0x20,  0x17,  0xFF,  0x10,  0x00,  0x11,  0xFC,  0x11,  0x04,  0x7D, 	/* 2B800 */
+	0xFC,  0x10,  0x00,  0x13,  0xFF,  0x12,  0x01,  0x12,  0xFD,  0x10,  0x22,  0x14,  0xD4,  0x1B,  0x38,  0x60, 	/* 2B810 */
+	0xD4,  0x07,  0x13,  0x00,  0x30,  0x97,  0x10,  0x20,  0x11,  0xFC,  0x10,  0x24,  0x17,  0xFF,  0x7C,  0x24, 	/* 2B820 */
+	0x11,  0xFC,  0x10,  0x20,  0x17,  0xFF,  0x12,  0x92,  0x12,  0x49,  0x1C,  0x00,  0x73,  0xFE,  0x02,  0x92, 	/* 2B830 */
+	0x02,  0x92,  0x0F,  0xFF,  0x00,  0x00,  0x98,  0x00,  0x00,  0x07,  0xF0,  0x04,  0x90,  0x07,  0xF0,  0x04, 	/* 2B840 */
+	0x90,  0x07,  0xF0,  0x3E,  0x3E,  0x2A,  0x2A,  0x3E,  0x3E,  0x2A,  0x2A,  0x3E,  0xBE,  0x00,  0x80,  0x1F, 	/* 2B850 */
+	0xFE,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x99,  0x10,  0x10,  0x10,  0x10,  0x13,  0xFF,  0x12,  0x48, 	/* 2B860 */
+	0x7E,  0xFE,  0x12,  0x48,  0x12,  0x78,  0x13,  0xFF,  0x12,  0x10,  0x16,  0xFE,  0x1A,  0x92,  0x64,  0xFE, 	/* 2B870 */
+	0x04,  0x92,  0x08,  0xFE,  0x10,  0xC6,  0x07,  0x01,  0x9C,  0x11,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x11, 	/* 2B880 */
+	0x04,  0x13,  0xFE,  0x7C,  0x20,  0x17,  0xFF,  0x14,  0x21,  0x15,  0xAD,  0x10,  0x20,  0x1D,  0xFC,  0x60, 	/* 2B890 */
+	0x00,  0x07,  0xFF,  0x00,  0x58,  0x00,  0x8C,  0x03,  0xF2,  0x9E,  0x10,  0x10,  0x13,  0xFF,  0x10,  0x00, 	/* 2B8A0 */
+	0x11,  0xFE,  0x7D,  0x4A,  0x11,  0xFE,  0x10,  0x00,  0x13,  0xAE,  0x10,  0x20,  0x13,  0xBE,  0x1C,  0x52, 	/* 2B8B0 */
+	0x70,  0x8C,  0x07,  0x88,  0x00,  0x84,  0x00,  0xF2,  0x03,  0x01,  0x9F,  0x04,  0x20,  0x3F,  0xBF,  0x11, 	/* 2B8C0 */
+	0x20,  0x7F,  0xFE,  0x00,  0x02,  0x1F,  0x3E,  0x11,  0x20,  0x1F,  0x3E,  0x11,  0x3E,  0x1F,  0x21,  0x11, 	/* 2B8D0 */
+	0x9F,  0x00,  0x80,  0x1F,  0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0xA4,  0x00,  0x20,  0x13,  0xFF, 	/* 2B8E0 */
+	0x10,  0x00,  0x11,  0xCE,  0x11,  0x4A,  0x7D,  0xCE,  0x10,  0x48,  0x11,  0xFE,  0x10,  0x48,  0x11,  0xFE, 	/* 2B8F0 */
+	0x14,  0x48,  0x1B,  0xFF,  0x60,  0x51,  0x03,  0x8A,  0x00,  0xE4,  0x01,  0x83,  0xA5,  0x10,  0x00,  0x13, 	/* 2B900 */
+	0xFE,  0x12,  0x00,  0x12,  0xFC,  0x7E,  0xAC,  0x12,  0xF4,  0x12,  0xA4,  0x13,  0xFE,  0x12,  0x20,  0x17, 	/* 2B910 */
+	0xFF,  0x1A,  0xCA,  0x65,  0x25,  0x05,  0xFC,  0x08,  0x20,  0x07,  0xFF,  0x00,  0x00,  0xAB,  0x00,  0x80, 	/* 2B920 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80, 	/* 2B930 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x00,  0xAC,  0x00, 	/* 2B940 */
+	0x04,  0x00,  0x18,  0x00,  0xE0,  0x1F,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F, 	/* 2B950 */
+	0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x00,  0xAE, 	/* 2B960 */
+	0x04,  0x20,  0x04,  0x10,  0x04,  0x10,  0x24,  0x10,  0x24,  0x10,  0x17,  0xFF,  0x14,  0x10,  0x04,  0x10, 	/* 2B970 */
+	0x0C,  0x10,  0x14,  0x10,  0x14,  0x10,  0x24,  0x10,  0x44,  0x10,  0x05,  0xFE,  0x04,  0x00,  0x04,  0x00, 	/* 2B980 */
+	0xAF,  0x02,  0x10,  0x12,  0x10,  0x12,  0x10,  0x12,  0x10,  0x12,  0x10,  0x1F,  0xFF,  0x02,  0x10,  0x02, 	/* 2B990 */
+	0x10,  0x3E,  0x10,  0x12,  0x10,  0x12,  0x10,  0x12,  0x10,  0x22,  0x10,  0x22,  0x10,  0x42,  0xFE,  0x02, 	/* 2B9A0 */
+	0x00,  0xB0,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x00, 	/* 2B9B0 */
+	0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x10,  0x00,  0x10,  0x00,  0x20,  0x00,  0x20,  0x00, 	/* 2B9C0 */
+	0x40,  0x00,  0xB1,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x01,  0x00,  0x01,  0x00,  0x1F,  0xF8,  0x00, 	/* 2B9D0 */
+	0x00,  0x7F,  0xFE,  0x40,  0x02,  0x48,  0x22,  0x08,  0xC0,  0x0F,  0x00,  0x08,  0x00,  0x08,  0x08,  0x04, 	/* 2B9E0 */
+	0x08,  0x03,  0xF8,  0xB2,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC, 	/* 2B9F0 */
+	0x00,  0x00,  0x7F,  0xFF,  0x40,  0x01,  0x42,  0x21,  0x02,  0x20,  0x02,  0x20,  0x04,  0x20,  0x08,  0x21, 	/* 2BA00 */
+	0x10,  0x21,  0x60,  0x1F,  0xB7,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x01,  0x00,  0x1F,  0xF8,  0x00, 	/* 2BA10 */
+	0x00,  0x7F,  0xFE,  0x42,  0x42,  0x5F,  0xFA,  0x12,  0x48,  0x12,  0x48,  0x1F,  0xF8,  0x02,  0x40,  0x02, 	/* 2BA20 */
+	0x40,  0x7F,  0xFE,  0x00,  0x00,  0xB9,  0x00,  0x80,  0x7F,  0xFE,  0x00,  0x80,  0x1F,  0xF8,  0x00,  0x00, 	/* 2BA30 */
+	0x7F,  0xFE,  0x40,  0x02,  0x5F,  0xFA,  0x00,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x04,  0x20, 	/* 2BA40 */
+	0x02,  0x40,  0x7F,  0xFE,  0x00,  0x00,  0xBA,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFE,  0x00,  0x80,  0x1F, 	/* 2BA50 */
+	0xF8,  0x00,  0x00,  0x7F,  0xFE,  0x42,  0x42,  0x5E,  0x7A,  0x10,  0x08,  0x10,  0x08,  0x1E,  0x78,  0x02, 	/* 2BA60 */
+	0x40,  0x02,  0x40,  0x7F,  0xFE,  0x00,  0x00,  0xBB,  0x00,  0x00,  0x13,  0xFF,  0x10,  0x12,  0x10,  0x90, 	/* 2BA70 */
+	0x10,  0x9E,  0x7D,  0x70,  0x12,  0x1F,  0x14,  0x00,  0x11,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x1D,  0x04, 	/* 2BA80 */
+	0x71,  0xFC,  0x01,  0x04,  0x01,  0x04,  0x01,  0x0C,  0xBC,  0x00,  0x80,  0x7F,  0xFE,  0x00,  0x80,  0x1F, 	/* 2BA90 */
+	0xF8,  0x00,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x5F,  0xFA,  0x02,  0x40,  0x1E,  0x78,  0x10,  0x08,  0x10, 	/* 2BAA0 */
+	0x08,  0x1E,  0x78,  0x02,  0x40,  0x7F,  0xFF,  0x00,  0x00,  0xBD,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80, 	/* 2BAB0 */
+	0x0F,  0xF8,  0x00,  0x00,  0x7F,  0xFE,  0x00,  0x02,  0x0F,  0xF2,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x08, 	/* 2BAC0 */
+	0x1F,  0xFF,  0x12,  0x88,  0x12,  0x48,  0x1E,  0x08,  0x00,  0x18,  0x82,  0x02,  0x00,  0x02,  0x00,  0x02, 	/* 2BAD0 */
+	0x00,  0x07,  0xF0,  0x04,  0x10,  0x0A,  0x10,  0x0A,  0x20,  0x11,  0x20,  0x21,  0x40,  0x00,  0x80,  0x00, 	/* 2BAE0 */
+	0x80,  0x01,  0x40,  0x02,  0x20,  0x04,  0x10,  0x18,  0x0C,  0x60,  0x03,  0x89,  0x00,  0x80,  0x00,  0x80, 	/* 2BAF0 */
+	0x7F,  0xFF,  0x02,  0x20,  0x12,  0x28,  0x12,  0x24,  0x12,  0x24,  0x24,  0x62,  0x4A,  0x02,  0x03,  0xF0, 	/* 2BB00 */
+	0x04,  0x20,  0x0A,  0x40,  0x31,  0x80,  0x01,  0xC0,  0x0E,  0x30,  0x70,  0x0F,  0x8A,  0x02,  0x00,  0x12, 	/* 2BB10 */
+	0x00,  0x12,  0x00,  0x0B,  0xF0,  0x0A,  0x10,  0x04,  0x10,  0x0C,  0x20,  0x12,  0x20,  0x22,  0x40,  0x01, 	/* 2BB20 */
+	0x80,  0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x04,  0x10,  0x18,  0x0C,  0x60,  0x03,  0x8F,  0x00,  0x00, 	/* 2BB30 */
+	0x3F,  0xFE,  0x00,  0x80,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08, 	/* 2BB40 */
+	0x0F,  0xF8,  0x02,  0x00,  0x07,  0xF8,  0x0A,  0x20,  0x31,  0xC0,  0x06,  0x70,  0x78,  0x0E,  0x90,  0x02, 	/* 2BB50 */
+	0x00,  0x07,  0xE0,  0x18,  0x40,  0x7F,  0xFE,  0x20,  0xC2,  0x23,  0x22,  0x0F,  0xF8,  0x08,  0x08,  0x0F, 	/* 2BB60 */
+	0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x80,  0x03,  0xF8,  0x3D,  0x10,  0x01,  0xE0,  0x7E,  0x1F,  0x95, 	/* 2BB70 */
+	0x01,  0x00,  0x01,  0x00,  0x01,  0xFC,  0x01,  0x04,  0x02,  0x04,  0x02,  0x04,  0x04,  0x08,  0x0A,  0x08, 	/* 2BB80 */
+	0x11,  0x90,  0x00,  0x50,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x03,  0x00,  0x0C,  0x00,  0x30,  0x00, 	/* 2BB90 */
+	0x96,  0x04,  0x20,  0x04,  0x20,  0x07,  0xA0,  0x08,  0xA0,  0x08,  0xA0,  0x10,  0xA0,  0x19,  0x30,  0x25, 	/* 2BBA0 */
+	0x2C,  0x43,  0x22,  0x02,  0x21,  0x02,  0x20,  0x04,  0x20,  0x04,  0x20,  0x08,  0x20,  0x10,  0x20,  0x20, 	/* 2BBB0 */
+	0x20,  0x98,  0x04,  0x00,  0x04,  0x3E,  0x07,  0xA2,  0x08,  0xA2,  0x08,  0xA2,  0x10,  0xA2,  0x19,  0x22, 	/* 2BBC0 */
+	0x25,  0x22,  0x43,  0x22,  0x02,  0x22,  0x02,  0x22,  0x04,  0x22,  0x04,  0x2C,  0x08,  0x20,  0x10,  0x20, 	/* 2BBD0 */
+	0x20,  0x20,  0x99,  0x00,  0x00,  0x1F,  0xF8,  0x10,  0x08,  0x10,  0x08,  0x1F,  0xF8,  0x11,  0x08,  0x11, 	/* 2BBE0 */
+	0xE8,  0x11,  0x28,  0x12,  0x28,  0x13,  0x28,  0x14,  0xC8,  0x18,  0x48,  0x10,  0x85,  0x21,  0x05,  0x22, 	/* 2BBF0 */
+	0x03,  0x44,  0x01,  0x9A,  0x01,  0x00,  0x01,  0xF0,  0x02,  0x10,  0x04,  0x20,  0x0A,  0x40,  0x31,  0x80, 	/* 2BC00 */
+	0x01,  0x20,  0x02,  0x3E,  0x0C,  0x42,  0x30,  0x84,  0x03,  0x48,  0x0C,  0x30,  0x00,  0x20,  0x00,  0xC0, 	/* 2BC10 */
+	0x03,  0x00,  0x3C,  0x00,  0x9B,  0x00,  0x00,  0x0F,  0xF0,  0x00,  0x10,  0x0F,  0xF0,  0x00,  0x10,  0x00, 	/* 2BC20 */
+	0x10,  0x7F,  0xFF,  0x01,  0x00,  0x03,  0xF8,  0x0C,  0x08,  0x33,  0x10,  0x00,  0xA0,  0x00,  0x40,  0x01, 	/* 2BC30 */
+	0x80,  0x06,  0x00,  0x38,  0x00,  0x9C,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0x40,  0x02,  0x40, 	/* 2BC40 */
+	0x04,  0x7C,  0x04,  0x44,  0x08,  0xC4,  0x18,  0xA8,  0x29,  0x98,  0x4A,  0x50,  0x08,  0x20,  0x08,  0x20, 	/* 2BC50 */
+	0x08,  0x50,  0x09,  0x8C,  0x0E,  0x03,  0xA2,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFE,  0x04,  0x20,  0x1F, 	/* 2BC60 */
+	0xF8,  0x12,  0x48,  0x1F,  0xF8,  0x00,  0x00,  0x7F,  0xFE,  0x41,  0x02,  0x43,  0xF2,  0x0E,  0x20,  0x31, 	/* 2BC70 */
+	0x40,  0x01,  0x80,  0x06,  0x00,  0x38,  0x00,  0xA5,  0x00,  0x08,  0x3F,  0x8E,  0x24,  0x92,  0x24,  0xA4, 	/* 2BC80 */
+	0x3F,  0xD4,  0x24,  0x88,  0x24,  0x90,  0x3F,  0xA4,  0x04,  0x47,  0x7F,  0xC9,  0x0E,  0x12,  0x0D,  0x2A, 	/* 2BC90 */
+	0x14,  0x84,  0x24,  0x88,  0x44,  0x10,  0x04,  0x60,  0xA7,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 2BCA0 */
+	0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x01,  0x40,  0x01,  0x40,  0x02,  0x20,  0x02, 	/* 2BCB0 */
+	0x20,  0x04,  0x10,  0x08,  0x08,  0x10,  0x04,  0x60,  0x03,  0xA9,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x80, 	/* 2BCC0 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x01,  0x40,  0x01,  0x40, 	/* 2BCD0 */
+	0x02,  0x20,  0x04,  0x10,  0x08,  0x08,  0x10,  0x04,  0x60,  0x03,  0xAA,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 2BCE0 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x40,  0x01,  0x40,  0x01,  0x20,  0x02,  0x20,  0x02, 	/* 2BCF0 */
+	0x10,  0x05,  0x10,  0x04,  0x88,  0x08,  0x44,  0x10,  0x42,  0x60,  0x01,  0xAB,  0x00,  0x80,  0x00,  0x80, 	/* 2BD00 */
+	0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80, 	/* 2BD10 */
+	0x01,  0x40,  0x01,  0x40,  0x02,  0x20,  0x04,  0x10,  0x18,  0x0C,  0x60,  0x03,  0xAC,  0x00,  0x80,  0x00, 	/* 2BD20 */
+	0x80,  0x00,  0x80,  0x1F,  0xF8,  0x00,  0x88,  0x00,  0x88,  0x00,  0x88,  0x00,  0x88,  0x7F,  0xFF,  0x00, 	/* 2BD30 */
+	0x80,  0x00,  0xC0,  0x01,  0x40,  0x02,  0x20,  0x04,  0x10,  0x18,  0x0C,  0x60,  0x03,  0xAD,  0x00,  0x10, 	/* 2BD40 */
+	0x00,  0x60,  0x1F,  0x80,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x01,  0x80, 	/* 2BD50 */
+	0x01,  0x80,  0x01,  0x40,  0x02,  0x40,  0x02,  0x20,  0x04,  0x10,  0x18,  0x0C,  0x60,  0x03,  0xAE,  0x00, 	/* 2BD60 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x7F, 	/* 2BD70 */
+	0xFF,  0x00,  0x80,  0x01,  0x40,  0x01,  0x40,  0x02,  0x20,  0x04,  0x10,  0x18,  0x0C,  0x60,  0x03,  0xB1, 	/* 2BD80 */
+	0x00,  0x80,  0x08,  0x80,  0x08,  0x80,  0x08,  0x80,  0x0F,  0xFC,  0x10,  0x80,  0x10,  0x80,  0x20,  0x80, 	/* 2BD90 */
+	0x7F,  0xFF,  0x00,  0x80,  0x01,  0x40,  0x01,  0x40,  0x02,  0x20,  0x04,  0x10,  0x18,  0x0C,  0x60,  0x03, 	/* 2BDA0 */
+	0xB2,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x04, 	/* 2BDB0 */
+	0x10,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 2BDC0 */
+	0x80,  0xB7,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x3F,  0xFC,  0x00,  0x84,  0x1F,  0xFC, 	/* 2BDD0 */
+	0x10,  0x80,  0x10,  0x80,  0x1F,  0xFE,  0x01,  0x42,  0x01,  0x42,  0x02,  0x2C,  0x04,  0x10,  0x18,  0x0C, 	/* 2BDE0 */
+	0x60,  0x03,  0xB8,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x40,  0x02,  0x20,  0x04,  0x10,  0x1B, 	/* 2BDF0 */
+	0xEC,  0x60,  0x03,  0x00,  0x00,  0x1F,  0xFC,  0x02,  0x00,  0x07,  0xF0,  0x04,  0x10,  0x00,  0x10,  0x00, 	/* 2BE00 */
+	0x10,  0x00,  0x60,  0xBE,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x08,  0x88,  0x08,  0x88, 	/* 2BE10 */
+	0x08,  0x88,  0x14,  0x94,  0x12,  0x94,  0x20,  0xA2,  0x41,  0x41,  0x01,  0x40,  0x02,  0x20,  0x04,  0x10, 	/* 2BE20 */
+	0x18,  0x0C,  0x60,  0x03,  0x84,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x40,  0x02,  0x20,  0x04, 	/* 2BE30 */
+	0x90,  0x1F,  0xFC,  0x68,  0x93,  0x08,  0x90,  0x0F,  0xF0,  0x08,  0x90,  0x08,  0x90,  0x0F,  0xF0,  0x00, 	/* 2BE40 */
+	0x82,  0x00,  0x82,  0x00,  0x7E,  0x87,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x01,  0x40,  0x02,  0x20, 	/* 2BE50 */
+	0x0C,  0x18,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x08,  0x0F,  0xC8,  0x08,  0x48,  0x08,  0x48,  0x0F,  0xC8, 	/* 2BE60 */
+	0x00,  0x08,  0x00,  0x08,  0x00,  0x18,  0x88,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x01,  0x40,  0x02, 	/* 2BE70 */
+	0x20,  0x04,  0x10,  0x1B,  0xEC,  0x60,  0x03,  0x00,  0x00,  0x3F,  0xFE,  0x00,  0x80,  0x02,  0xA0,  0x04, 	/* 2BE80 */
+	0x98,  0x18,  0x84,  0x60,  0x82,  0x01,  0x80,  0x89,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80, 	/* 2BE90 */
+	0x0F,  0xF8,  0x01,  0x40,  0x7F,  0xFF,  0x02,  0x20,  0x04,  0x90,  0x18,  0x8C,  0x67,  0xF3,  0x00,  0x80, 	/* 2BEA0 */
+	0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x8E,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01, 	/* 2BEB0 */
+	0x40,  0x02,  0xA0,  0x0C,  0x98,  0x77,  0xF7,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x1F, 	/* 2BEC0 */
+	0xFC,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x8F,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE, 	/* 2BED0 */
+	0x00,  0x80,  0x1F,  0xFC,  0x01,  0x40,  0x7F,  0xFF,  0x02,  0x20,  0x04,  0x10,  0x1B,  0xEC,  0x60,  0x83, 	/* 2BEE0 */
+	0x1F,  0xFC,  0x01,  0x40,  0x02,  0x20,  0x0C,  0x18,  0x30,  0x06,  0x90,  0x02,  0x00,  0x03,  0xE0,  0x04, 	/* 2BEF0 */
+	0x40,  0x18,  0x80,  0x7F,  0xFC,  0x11,  0x44,  0x11,  0x44,  0x12,  0x44,  0x14,  0x3C,  0x10,  0x84,  0x00, 	/* 2BF00 */
+	0x80,  0x7F,  0xFF,  0x01,  0x40,  0x02,  0x20,  0x0C,  0x18,  0x70,  0x07,  0x91,  0x04,  0x00,  0x04,  0x00, 	/* 2BF10 */
+	0x3F,  0xBE,  0x04,  0x12,  0x3F,  0x92,  0x04,  0x12,  0x05,  0xA2,  0x0E,  0x22,  0x70,  0x4C,  0x00,  0x80, 	/* 2BF20 */
+	0x00,  0x80,  0x7F,  0xFF,  0x01,  0x40,  0x02,  0x20,  0x0C,  0x18,  0x70,  0x06,  0x94,  0x00,  0x80,  0x00, 	/* 2BF30 */
+	0x80,  0x7F,  0xFF,  0x01,  0x40,  0x02,  0x20,  0x04,  0x90,  0x18,  0x8C,  0x67,  0xFB,  0x00,  0x80,  0x04, 	/* 2BF40 */
+	0x90,  0x04,  0x90,  0x7F,  0xFF,  0x04,  0x10,  0x08,  0x10,  0x08,  0x10,  0x10,  0x10,  0x95,  0x00,  0x80, 	/* 2BF50 */
+	0x00,  0x80,  0x7F,  0xFF,  0x01,  0x20,  0x09,  0x28,  0x09,  0x24,  0x09,  0x22,  0x12,  0x22,  0x24,  0x60, 	/* 2BF60 */
+	0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x40,  0x02,  0x20,  0x0C,  0x18,  0x70,  0x07,  0x97,  0x00, 	/* 2BF70 */
+	0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x40,  0x02,  0x20,  0x0F,  0xF8,  0x72,  0x07,  0x03,  0xF0,  0x02, 	/* 2BF80 */
+	0x00,  0x03,  0xF0,  0x02,  0x00,  0x7F,  0xFF,  0x02,  0x20,  0x02,  0x18,  0x04,  0xF4,  0x3F,  0x02,  0x98, 	/* 2BF90 */
+	0x24,  0x20,  0x24,  0x20,  0x24,  0x20,  0x3F,  0xFF,  0x04,  0x20,  0x7C,  0x20,  0x14,  0x20,  0x15,  0xFE, 	/* 2BFA0 */
+	0x24,  0x00,  0x44,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x40,  0x02,  0x20,  0x0C,  0x18,  0x70,  0x07, 	/* 2BFB0 */
+	0x9A,  0x00,  0x04,  0x00,  0x38,  0x3F,  0xC8,  0x08,  0x44,  0x09,  0x22,  0x11,  0x02,  0x2E,  0x20,  0x42, 	/* 2BFC0 */
+	0x48,  0x01,  0x84,  0x1F,  0xFA,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x40,  0x02,  0x20,  0x0C,  0x18,  0x70, 	/* 2BFD0 */
+	0x07,  0xA0,  0x0B,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x11,  0x24,  0x2F,  0xFE,  0x49,  0x2D,  0x0A,  0x1C, 	/* 2BFE0 */
+	0x0C,  0x04,  0x0F,  0xFC,  0x08,  0x04,  0x0F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x20,  0x06,  0x18, 	/* 2BFF0 */
+	0x78,  0x07,  0xA2,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0x20,  0x04,  0x90,  0x1F,  0xFC,  0x60, 	/* 2C000 */
+	0x93,  0x00,  0xA0,  0x7F,  0xFF,  0x01,  0x10,  0x07,  0xF8,  0x1C,  0x08,  0x67,  0xF8,  0x04,  0x08,  0x07, 	/* 2C010 */
+	0xF8,  0x00,  0x00,  0xA5,  0x01,  0x00,  0x02,  0x00,  0x1F,  0xFC,  0x10,  0x84,  0x14,  0x94,  0x12,  0xA4, 	/* 2C020 */
+	0x1F,  0xFC,  0x11,  0xC4,  0x12,  0xA4,  0x14,  0x9C,  0x18,  0x84,  0x11,  0x04,  0x7F,  0xFF,  0x01,  0x40, 	/* 2C030 */
+	0x06,  0x30,  0x78,  0x0E,  0xA7,  0x00,  0x80,  0x01,  0x00,  0x1F,  0xFC,  0x10,  0x24,  0x13,  0xC4,  0x14, 	/* 2C040 */
+	0x94,  0x12,  0xA4,  0x1F,  0xFC,  0x11,  0xC4,  0x12,  0xA4,  0x14,  0x94,  0x00,  0x80,  0x7F,  0xFF,  0x01, 	/* 2C050 */
+	0x40,  0x06,  0x30,  0x78,  0x0F,  0xA8,  0x04,  0x0C,  0x25,  0xF2,  0x15,  0x22,  0x14,  0xA4,  0x04,  0x88, 	/* 2C060 */
+	0x0F,  0xFF,  0x14,  0x44,  0x64,  0x24,  0x04,  0x24,  0x04,  0x8C,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x40, 	/* 2C070 */
+	0x02,  0x20,  0x0C,  0x18,  0x70,  0x07,  0xA9,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x40,  0x06, 	/* 2C080 */
+	0x30,  0x1F,  0xFC,  0x70,  0x03,  0x11,  0xF0,  0x11,  0x10,  0x11,  0xF0,  0x17,  0xBC,  0x14,  0xA4,  0x17, 	/* 2C090 */
+	0xBC,  0x10,  0x00,  0x1F,  0xFE,  0x00,  0x00,  0xAA,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x40,  0x06,  0x30, 	/* 2C0A0 */
+	0x1A,  0x4C,  0x67,  0xFB,  0x0C,  0x40,  0x37,  0xF8,  0x04,  0x40,  0x07,  0xF8,  0x00,  0x10,  0x7F,  0xFF, 	/* 2C0B0 */
+	0x04,  0x10,  0x02,  0x10,  0x02,  0x10,  0x00,  0x30,  0xAC,  0x24,  0x10,  0x24,  0x3E,  0x25,  0xCA,  0x3C, 	/* 2C0C0 */
+	0x2C,  0x05,  0xF0,  0x7C,  0x04,  0x25,  0xFF,  0x24,  0x44,  0x24,  0x24,  0x44,  0x8C,  0x00,  0x80,  0x7F, 	/* 2C0D0 */
+	0xFF,  0x01,  0x40,  0x02,  0x20,  0x0C,  0x18,  0x70,  0x07,  0xAE,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0x20, 	/* 2C0E0 */
+	0x0D,  0x58,  0x77,  0xF7,  0x0C,  0x40,  0x17,  0xF0,  0x04,  0x40,  0x07,  0xFC,  0x04,  0x00,  0x1F,  0xFC, 	/* 2C0F0 */
+	0x10,  0x84,  0x1F,  0xFC,  0x10,  0x84,  0x1F,  0xFC,  0x10,  0x04,  0xB3,  0x01,  0x00,  0x01,  0x00,  0x01, 	/* 2C100 */
+	0x00,  0x01,  0x00,  0xFF,  0xFF,  0x02,  0x10,  0x02,  0x10,  0x02,  0x10,  0x04,  0x20,  0x04,  0x20,  0x1F, 	/* 2C110 */
+	0x40,  0x10,  0xC0,  0x01,  0x20,  0x02,  0x10,  0x0C,  0x08,  0x30,  0x04,  0xB4,  0x08,  0x00,  0x08,  0x00, 	/* 2C120 */
+	0x08,  0xFC,  0x08,  0x04,  0x7F,  0x44,  0x09,  0x44,  0x09,  0x44,  0x11,  0x44,  0x12,  0x28,  0x22,  0x28, 	/* 2C130 */
+	0x7C,  0x18,  0x06,  0x10,  0x0A,  0x28,  0x10,  0x44,  0x60,  0x82,  0x03,  0x01,  0xB8,  0x08,  0x00,  0x08, 	/* 2C140 */
+	0xFE,  0x08,  0x10,  0x08,  0x10,  0x7F,  0x10,  0x11,  0x10,  0x11,  0x10,  0x11,  0xFF,  0x22,  0x10,  0x7A, 	/* 2C150 */
+	0x10,  0x46,  0x10,  0x05,  0x10,  0x09,  0x10,  0x10,  0x10,  0x60,  0x10,  0x00,  0x10,  0xBD,  0x08,  0x00, 	/* 2C160 */
+	0x08,  0x7E,  0x08,  0x02,  0x08,  0x04,  0x7F,  0x08,  0x12,  0x08,  0x12,  0x10,  0x13,  0xFF,  0x12,  0x10, 	/* 2C170 */
+	0x22,  0x10,  0x3C,  0x10,  0x26,  0x10,  0x09,  0x10,  0x10,  0x10,  0x60,  0x10,  0x00,  0x30,  0x81,  0x08, 	/* 2C180 */
+	0x40,  0x08,  0x40,  0x08,  0x40,  0x08,  0x7E,  0x7E,  0x42,  0x12,  0x82,  0x12,  0x82,  0x13,  0x42,  0x22, 	/* 2C190 */
+	0x22,  0x22,  0x22,  0x7C,  0x22,  0x46,  0x02,  0x05,  0x02,  0x18,  0x82,  0x60,  0x04,  0x00,  0x18,  0x82, 	/* 2C1A0 */
+	0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x7E,  0x7F,  0x42,  0x12,  0x42,  0x12,  0x42,  0x12,  0x42, 	/* 2C1B0 */
+	0x22,  0x42,  0x24,  0x42,  0x7C,  0x42,  0x44,  0x42,  0x0A,  0x7E,  0x11,  0x00,  0x60,  0x00,  0x00,  0x00, 	/* 2C1C0 */
+	0x83,  0x08,  0x00,  0x08,  0xFC,  0x08,  0x04,  0x08,  0x04,  0x7E,  0x04,  0x12,  0x04,  0x12,  0xFC,  0x12, 	/* 2C1D0 */
+	0x80,  0x22,  0x80,  0x24,  0x80,  0x7C,  0x80,  0x46,  0x80,  0x0A,  0x82,  0x10,  0x42,  0x60,  0x3E,  0x00, 	/* 2C1E0 */
+	0x00,  0x84,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x07,  0xFC, 	/* 2C1F0 */
+	0x01,  0x00,  0x01,  0x00,  0x7F,  0xFF,  0x02,  0x10,  0x04,  0x10,  0x0F,  0xA0,  0x00,  0xE0,  0x03,  0x18, 	/* 2C200 */
+	0x3C,  0x04,  0x8A,  0x08,  0x04,  0x08,  0x18,  0x08,  0xF0,  0x08,  0x10,  0x7F,  0x10,  0x12,  0x10,  0x12, 	/* 2C210 */
+	0x10,  0x13,  0xFF,  0x22,  0x10,  0x24,  0x10,  0x7C,  0x10,  0x46,  0x10,  0x0A,  0x10,  0x10,  0x10,  0x60, 	/* 2C220 */
+	0xFE,  0x00,  0x00,  0x8D,  0x08,  0x00,  0x08,  0xFF,  0x08,  0x24,  0x08,  0x24,  0x7E,  0x24,  0x12,  0x24, 	/* 2C230 */
+	0x13,  0xFF,  0x12,  0x24,  0x22,  0x24,  0x24,  0x24,  0x7C,  0x24,  0x46,  0x24,  0x0A,  0x44,  0x11,  0x44, 	/* 2C240 */
+	0x60,  0x84,  0x01,  0x04,  0x93,  0x08,  0x10,  0x08,  0x10,  0x09,  0xFF,  0x08,  0x10,  0x7F,  0x10,  0x12, 	/* 2C250 */
+	0x10,  0x12,  0xFC,  0x12,  0x44,  0x22,  0x44,  0x24,  0x28,  0x7C,  0x28,  0x06,  0x10,  0x09,  0x28,  0x10, 	/* 2C260 */
+	0x44,  0x60,  0x82,  0x03,  0x01,  0x96,  0x08,  0x04,  0x08,  0x18,  0x08,  0xF0,  0x08,  0x10,  0x7F,  0x10, 	/* 2C270 */
+	0x12,  0x10,  0x13,  0xFF,  0x12,  0x10,  0x22,  0x10,  0x22,  0x10,  0x7C,  0x28,  0x44,  0x28,  0x0A,  0x44, 	/* 2C280 */
+	0x12,  0x84,  0x61,  0x02,  0x02,  0x01,  0x99,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x58,  0x7E, 	/* 2C290 */
+	0x54,  0x12,  0x52,  0x12,  0x92,  0x12,  0x91,  0x23,  0x15,  0x22,  0x14,  0x7C,  0x38,  0x46,  0x08,  0x09, 	/* 2C2A0 */
+	0x10,  0x10,  0x20,  0x60,  0xC0,  0x03,  0x00,  0x9B,  0x00,  0x80,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84, 	/* 2C2B0 */
+	0x1F,  0xFC,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x00,  0x02,  0x00,  0x7F,  0xFF,  0x02,  0x10,  0x04,  0x10, 	/* 2C2C0 */
+	0x1F,  0x20,  0x01,  0xC0,  0x06,  0x30,  0x38,  0x0C,  0x9D,  0x04,  0x20,  0x24,  0x20,  0x24,  0x20,  0x24, 	/* 2C2D0 */
+	0x20,  0x27,  0xFF,  0x3C,  0x44,  0x04,  0x44,  0x04,  0x44,  0x7C,  0x44,  0x14,  0x88,  0x15,  0xE8,  0x14, 	/* 2C2E0 */
+	0x10,  0x24,  0x28,  0x24,  0x44,  0x45,  0x82,  0x06,  0x02,  0xA3,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88, 	/* 2C2F0 */
+	0x08,  0x88,  0x7F,  0x89,  0x12,  0x89,  0x12,  0xFA,  0x12,  0x8C,  0x22,  0x88,  0x24,  0x88,  0x7C,  0x88, 	/* 2C300 */
+	0x46,  0x88,  0x0A,  0x88,  0x10,  0xB9,  0x60,  0xC9,  0x03,  0x07,  0xA5,  0x00,  0x04,  0x00,  0x38,  0x1F, 	/* 2C310 */
+	0xC4,  0x00,  0x84,  0x08,  0x48,  0x04,  0x48,  0x05,  0x10,  0x01,  0x00,  0x7F,  0xFF,  0x02,  0x10,  0x02, 	/* 2C320 */
+	0x10,  0x04,  0x20,  0x0F,  0xC0,  0x00,  0xB0,  0x03,  0x08,  0x3C,  0x04,  0xA8,  0x08,  0x20,  0x08,  0x20, 	/* 2C330 */
+	0x08,  0x20,  0x09,  0xFF,  0x7E,  0x40,  0x12,  0x40,  0x12,  0x40,  0x12,  0x7C,  0x22,  0x44,  0x24,  0x44, 	/* 2C340 */
+	0x7C,  0x44,  0x46,  0x44,  0x0A,  0x84,  0x10,  0x84,  0x61,  0x04,  0x02,  0x18,  0xAC,  0x08,  0x00,  0x09, 	/* 2C350 */
+	0xFF,  0x08,  0x10,  0x08,  0x10,  0x7E,  0x10,  0x12,  0x20,  0x12,  0x20,  0x12,  0x7E,  0x22,  0x42,  0x24, 	/* 2C360 */
+	0xC2,  0x7D,  0x42,  0x06,  0x42,  0x0A,  0x42,  0x10,  0x42,  0x60,  0x7E,  0x00,  0x00,  0xB2,  0x08,  0x00, 	/* 2C370 */
+	0x08,  0xFC,  0x08,  0x84,  0x08,  0x84,  0x7E,  0x84,  0x12,  0x84,  0x12,  0xFC,  0x12,  0x84,  0x22,  0x84, 	/* 2C380 */
+	0x24,  0x84,  0x7C,  0x84,  0x46,  0xFC,  0x0A,  0x00,  0x10,  0x00,  0x63,  0xFF,  0x00,  0x00,  0xB9,  0x08, 	/* 2C390 */
+	0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0xFE,  0x7F,  0x10,  0x12,  0x10,  0x12,  0x10,  0x13,  0xFF,  0x22, 	/* 2C3A0 */
+	0x38,  0x24,  0x38,  0x7C,  0x54,  0x04,  0x54,  0x0A,  0x92,  0x11,  0x11,  0x60,  0x10,  0x00,  0x10,  0xBB, 	/* 2C3B0 */
+	0x00,  0x80,  0x00,  0x80,  0x3F,  0xFF,  0x00,  0x80,  0x0F,  0xFC,  0x00,  0x84,  0x7F,  0xFF,  0x00,  0x84, 	/* 2C3C0 */
+	0x0F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x10,  0x02,  0x10,  0x0F,  0xE0,  0x01,  0x98,  0x1E,  0x04, 	/* 2C3D0 */
+	0xBE,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x04,  0x10,  0x02,  0x10,  0x02,  0x20,  0x7F,  0xFF,  0x00, 	/* 2C3E0 */
+	0x00,  0x01,  0x00,  0x7F,  0xFF,  0x01,  0x10,  0x02,  0x10,  0x0F,  0x20,  0x00,  0xE0,  0x03,  0x18,  0x3C, 	/* 2C3F0 */
+	0x04,  0x86,  0x08,  0x00,  0x08,  0x7E,  0x08,  0x42,  0x08,  0x52,  0x7F,  0x4A,  0x12,  0x4A,  0x12,  0x42, 	/* 2C400 */
+	0x13,  0xFF,  0x22,  0x82,  0x24,  0xA2,  0x7C,  0x92,  0x46,  0x92,  0x0B,  0xFF,  0x10,  0x02,  0x60,  0x04, 	/* 2C410 */
+	0x00,  0x18,  0x89,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x09,  0xFF,  0x7F,  0x10,  0x12,  0x10,  0x12, 	/* 2C420 */
+	0xFE,  0x12,  0x92,  0x22,  0x92,  0x3C,  0x92,  0x44,  0x92,  0x06,  0x92,  0x0A,  0x9C,  0x10,  0x10,  0x60, 	/* 2C430 */
+	0x10,  0x00,  0x10,  0x8B,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x24,  0x7F,  0x22,  0x12,  0x42, 	/* 2C440 */
+	0x12,  0x4F,  0x13,  0xF1,  0x22,  0x01,  0x3C,  0x00,  0x44,  0x7E,  0x06,  0x42,  0x0A,  0x42,  0x10,  0x42, 	/* 2C450 */
+	0x60,  0x7E,  0x00,  0x00,  0x90,  0x08,  0x00,  0x08,  0xFC,  0x08,  0x84,  0x08,  0x84,  0x7F,  0x84,  0x12, 	/* 2C460 */
+	0xFC,  0x12,  0x84,  0x12,  0x84,  0x22,  0x84,  0x24,  0x84,  0x7C,  0xFC,  0x06,  0x84,  0x0A,  0x84,  0x10, 	/* 2C470 */
+	0x84,  0x67,  0xFF,  0x00,  0x00,  0x91,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x7F,  0xFF, 	/* 2C480 */
+	0x12,  0x20,  0x12,  0x20,  0x12,  0x20,  0x22,  0x20,  0x22,  0xFC,  0x7C,  0x84,  0x04,  0x84,  0x0A,  0x84, 	/* 2C490 */
+	0x12,  0x84,  0x60,  0xFC,  0x00,  0x00,  0x93,  0x08,  0x10,  0x08,  0x90,  0x08,  0x90,  0x08,  0x90,  0x7E, 	/* 2C4A0 */
+	0xFE,  0x12,  0x90,  0x13,  0x10,  0x12,  0x10,  0x22,  0x10,  0x24,  0xFE,  0x7C,  0x10,  0x06,  0x10,  0x0A, 	/* 2C4B0 */
+	0x10,  0x10,  0x10,  0x63,  0xFF,  0x00,  0x00,  0x94,  0x00,  0x18,  0x1F,  0xE0,  0x00,  0x80,  0x7F,  0xFF, 	/* 2C4C0 */
+	0x01,  0xC0,  0x02,  0xA0,  0x0C,  0x98,  0x70,  0x87,  0x01,  0x00,  0x7F,  0xFF,  0x02,  0x10,  0x02,  0x10, 	/* 2C4D0 */
+	0x07,  0xA0,  0x08,  0x40,  0x01,  0xB0,  0x3E,  0x0C,  0x99,  0x10,  0x42,  0x10,  0x44,  0x10,  0x78,  0x10, 	/* 2C4E0 */
+	0x88,  0x7E,  0x88,  0x13,  0x88,  0x12,  0x88,  0x12,  0xFF,  0x22,  0x88,  0x24,  0x88,  0x7C,  0x88,  0x46, 	/* 2C4F0 */
+	0x88,  0x0A,  0x88,  0x10,  0x88,  0x60,  0xBF,  0x00,  0x80,  0x9A,  0x08,  0x28,  0x08,  0x28,  0x08,  0x2A, 	/* 2C500 */
+	0x09,  0x2A,  0x7E,  0xAA,  0x12,  0xAC,  0x12,  0xAC,  0x12,  0x28,  0x22,  0x2C,  0x24,  0x6A,  0x7C,  0xC9, 	/* 2C510 */
+	0x47,  0x48,  0x0A,  0x48,  0x10,  0x89,  0x61,  0x09,  0x06,  0x07,  0x9C,  0x04,  0x10,  0x02,  0x20,  0x3F, 	/* 2C520 */
+	0xFE,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x00,  0x3F,  0xFE,  0x02, 	/* 2C530 */
+	0x20,  0x04,  0x20,  0x0F,  0xC0,  0x01,  0x60,  0x06,  0x10,  0x38,  0x08,  0xA5,  0x08,  0x20,  0x08,  0x24, 	/* 2C540 */
+	0x09,  0xFC,  0x08,  0x28,  0x7E,  0x28,  0x12,  0x30,  0x13,  0xFF,  0x12,  0x20,  0x22,  0x40,  0x24,  0xC4, 	/* 2C550 */
+	0x7D,  0x58,  0x46,  0x60,  0x0A,  0x40,  0x10,  0x42,  0x60,  0x42,  0x00,  0x3E,  0xA6,  0x01,  0x00,  0x01, 	/* 2C560 */
+	0x00,  0x3F,  0xFC,  0x02,  0x20,  0x04,  0x40,  0x0F,  0x80,  0x02,  0x70,  0x3C,  0x08,  0x04,  0x10,  0x7F, 	/* 2C570 */
+	0xFF,  0x09,  0x24,  0x09,  0x24,  0x3D,  0xF4,  0x06,  0x18,  0x0B,  0x2C,  0x70,  0xC2,  0xA8,  0x08,  0x10, 	/* 2C580 */
+	0x08,  0x10,  0x09,  0xFF,  0x08,  0x10,  0x7E,  0xFE,  0x12,  0x12,  0x12,  0xFE,  0x12,  0x90,  0x22,  0x90, 	/* 2C590 */
+	0x7C,  0xFF,  0x44,  0x11,  0x06,  0x29,  0x0A,  0x2A,  0x10,  0x44,  0x61,  0x82,  0x06,  0x01,  0xAA,  0x08, 	/* 2C5A0 */
+	0x00,  0x09,  0xFF,  0x08,  0x20,  0x08,  0x28,  0x7E,  0x24,  0x12,  0x4E,  0x13,  0xF1,  0x12,  0x00,  0x22, 	/* 2C5B0 */
+	0x10,  0x7C,  0x10,  0x44,  0xFE,  0x06,  0x10,  0x0A,  0x10,  0x10,  0x10,  0x63,  0xFF,  0x00,  0x00,  0xAB, 	/* 2C5C0 */
+	0x08,  0x00,  0x08,  0xFF,  0x08,  0x88,  0x08,  0x88,  0x7F,  0x88,  0x12,  0xFE,  0x12,  0x82,  0x12,  0x82, 	/* 2C5D0 */
+	0x22,  0x82,  0x24,  0xFE,  0x7C,  0x88,  0x06,  0x88,  0x0A,  0x88,  0x12,  0x88,  0x60,  0xFF,  0x00,  0x80, 	/* 2C5E0 */
+	0xB6,  0x08,  0x10,  0x08,  0x10,  0x08,  0x28,  0x08,  0x28,  0x7E,  0x44,  0x12,  0x82,  0x13,  0x01,  0x12, 	/* 2C5F0 */
+	0x7C,  0x22,  0x00,  0x24,  0x00,  0x7C,  0xFE,  0x46,  0x82,  0x0A,  0x82,  0x10,  0x82,  0x60,  0xFE,  0x00, 	/* 2C600 */
+	0x00,  0xBB,  0x08,  0x00,  0x08,  0xFE,  0x08,  0x82,  0x08,  0x92,  0x7E,  0x92,  0x12,  0xFE,  0x12,  0x92, 	/* 2C610 */
+	0x12,  0x92,  0x22,  0xAA,  0x24,  0xAA,  0x7C,  0xAA,  0x06,  0xC6,  0x0A,  0x82,  0x10,  0x82,  0x60,  0xFE, 	/* 2C620 */
+	0x00,  0x00,  0xBF,  0x01,  0x00,  0x21,  0x00,  0x11,  0xFE,  0x12,  0x44,  0x02,  0x48,  0x0C,  0x60,  0x31, 	/* 2C630 */
+	0x98,  0x4E,  0x06,  0x01,  0x00,  0x7F,  0xFF,  0x02,  0x10,  0x04,  0x10,  0x1F,  0xA0,  0x00,  0xE0,  0x03, 	/* 2C640 */
+	0x18,  0x3C,  0x04,  0x81,  0x00,  0x28,  0x00,  0x24,  0x00,  0x24,  0x1F,  0xFF,  0x10,  0x20,  0x1F,  0xA0, 	/* 2C650 */
+	0x12,  0x22,  0x12,  0x22,  0x1F,  0xD4,  0x14,  0x94,  0x14,  0x98,  0x1F,  0x08,  0x11,  0x9A,  0x22,  0xA6, 	/* 2C660 */
+	0x2C,  0x42,  0x40,  0x82,  0x83,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0xFE,  0x7F,  0x10,  0x12, 	/* 2C670 */
+	0x10,  0x12,  0x10,  0x13,  0xFF,  0x22,  0x10,  0x7C,  0x10,  0x44,  0xFE,  0x06,  0x10,  0x0A,  0x10,  0x10, 	/* 2C680 */
+	0x10,  0x61,  0xFF,  0x00,  0x00,  0x89,  0x08,  0x10,  0x08,  0x10,  0x08,  0xFE,  0x08,  0x92,  0x7E,  0xFE, 	/* 2C690 */
+	0x12,  0x92,  0x12,  0x92,  0x12,  0xFE,  0x22,  0x00,  0x25,  0xFF,  0x7C,  0x20,  0x46,  0x7C,  0x0A,  0x44, 	/* 2C6A0 */
+	0x10,  0x04,  0x60,  0x04,  0x00,  0x18,  0x91,  0x00,  0x10,  0x18,  0x10,  0x04,  0x94,  0x60,  0x92,  0x11, 	/* 2C6B0 */
+	0x11,  0x02,  0x34,  0x08,  0x08,  0x30,  0x30,  0x41,  0xC0,  0x01,  0x00,  0x7F,  0xFF,  0x02,  0x20,  0x04, 	/* 2C6C0 */
+	0x20,  0x0F,  0xC0,  0x01,  0xB0,  0x3E,  0x0C,  0x98,  0x08,  0x20,  0x08,  0x20,  0x08,  0xFC,  0x08,  0x84, 	/* 2C6D0 */
+	0x7F,  0x84,  0x12,  0xFC,  0x12,  0x84,  0x12,  0x84,  0x22,  0xFE,  0x7C,  0x92,  0x44,  0x94,  0x06,  0x88, 	/* 2C6E0 */
+	0x0A,  0x88,  0x10,  0xA4,  0x60,  0xC2,  0x03,  0x01,  0x9A,  0x08,  0x00,  0x08,  0xFE,  0x08,  0x92,  0x08, 	/* 2C6F0 */
+	0x92,  0x7E,  0xFE,  0x12,  0x92,  0x12,  0x92,  0x12,  0xFE,  0x22,  0x20,  0x24,  0x20,  0x7C,  0xFE,  0x46, 	/* 2C700 */
+	0x22,  0x0A,  0x22,  0x10,  0x42,  0x60,  0x82,  0x03,  0x0C,  0x9C,  0x10,  0x00,  0x13,  0xEF,  0x10,  0xA9, 	/* 2C710 */
+	0x10,  0xA9,  0x7E,  0xAA,  0x15,  0xEC,  0x14,  0xAA,  0x14,  0xAA,  0x24,  0xA9,  0x25,  0xE9,  0x78,  0xA9, 	/* 2C720 */
+	0x0C,  0xA9,  0x0B,  0x2E,  0x11,  0x28,  0x62,  0x28,  0x04,  0x68,  0x9F,  0x08,  0x00,  0x08,  0xFE,  0x08, 	/* 2C730 */
+	0x82,  0x08,  0x82,  0x7E,  0xFE,  0x12,  0x00,  0x12,  0xFE,  0x12,  0x82,  0x22,  0x82,  0x24,  0xFE,  0x7C, 	/* 2C740 */
+	0x82,  0x46,  0x82,  0x0A,  0xFE,  0x10,  0x82,  0x60,  0x82,  0x00,  0x86,  0xA0,  0x08,  0x00,  0x08,  0xFF, 	/* 2C750 */
+	0x08,  0x80,  0x08,  0x80,  0x7F,  0xBE,  0x12,  0x80,  0x12,  0x80,  0x12,  0xFF,  0x22,  0xAA,  0x3C,  0xAA, 	/* 2C760 */
+	0x44,  0xAA,  0x07,  0x2C,  0x09,  0x24,  0x12,  0x34,  0x64,  0x62,  0x00,  0x81,  0xA5,  0x08,  0x28,  0x08, 	/* 2C770 */
+	0x4C,  0x09,  0xCA,  0x08,  0x4A,  0x7E,  0x48,  0x13,  0xFF,  0x12,  0x48,  0x12,  0x4A,  0x22,  0x4A,  0x24, 	/* 2C780 */
+	0x6C,  0x7D,  0xC4,  0x46,  0x4D,  0x0A,  0x55,  0x10,  0x63,  0x60,  0x43,  0x00,  0xC1,  0xA9,  0x08,  0x20, 	/* 2C790 */
+	0x08,  0x3C,  0x08,  0x48,  0x08,  0x48,  0x7E,  0x90,  0x13,  0xFE,  0x12,  0x92,  0x12,  0x92,  0x22,  0x92, 	/* 2C7A0 */
+	0x24,  0xFE,  0x7C,  0x28,  0x46,  0x28,  0x0A,  0x28,  0x10,  0x49,  0x60,  0x89,  0x03,  0x07,  0xAF,  0x08, 	/* 2C7B0 */
+	0x00,  0x08,  0xBC,  0x08,  0xA4,  0x08,  0xA4,  0x7E,  0xA4,  0x12,  0xBC,  0x12,  0x80,  0x12,  0x80,  0x22, 	/* 2C7C0 */
+	0xFC,  0x24,  0x04,  0x7C,  0x04,  0x05,  0xFF,  0x0A,  0x00,  0x12,  0x24,  0x60,  0x42,  0x01,  0x81,  0xB5, 	/* 2C7D0 */
+	0x08,  0x00,  0x0B,  0xFF,  0x09,  0x20,  0x09,  0x20,  0x7D,  0x3E,  0x15,  0xEA,  0x15,  0x2A,  0x15,  0x2A, 	/* 2C7E0 */
+	0x25,  0x2A,  0x25,  0xEA,  0x79,  0x24,  0x09,  0x24,  0x0D,  0xEA,  0x17,  0x32,  0x60,  0x21,  0x00,  0x20, 	/* 2C7F0 */
+	0xB6,  0x00,  0x00,  0x7F,  0x80,  0x11,  0xFE,  0x1F,  0x42,  0x11,  0x24,  0x1F,  0x28,  0x11,  0x18,  0x1F, 	/* 2C800 */
+	0x24,  0x71,  0xC3,  0x01,  0x00,  0x7F,  0xFF,  0x02,  0x20,  0x04,  0x20,  0x0F,  0xC0,  0x01,  0xB0,  0x3E, 	/* 2C810 */
+	0x08,  0xBC,  0x08,  0x00,  0x08,  0x7C,  0x08,  0x44,  0x08,  0x44,  0x7E,  0x7C,  0x12,  0x44,  0x12,  0x7C, 	/* 2C820 */
+	0x12,  0x00,  0x22,  0xFE,  0x24,  0x82,  0x7C,  0x82,  0x06,  0xFE,  0x0A,  0x82,  0x10,  0x82,  0x60,  0xFE, 	/* 2C830 */
+	0x00,  0x00,  0x80,  0x08,  0x00,  0x09,  0xDF,  0x09,  0x42,  0x09,  0x42,  0x7F,  0x7A,  0x15,  0xAA,  0x15, 	/* 2C840 */
+	0xAA,  0x15,  0x6A,  0x25,  0x6A,  0x25,  0x6A,  0x79,  0x7A,  0x0D,  0x42,  0x09,  0xC2,  0x11,  0x02,  0x61, 	/* 2C850 */
+	0x02,  0x01,  0x06,  0x81,  0x00,  0x80,  0x0F,  0xF8,  0x08,  0x88,  0x7F,  0xFF,  0x08,  0x88,  0x0F,  0xF8, 	/* 2C860 */
+	0x00,  0x80,  0x1F,  0xFC,  0x10,  0x84,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0x10,  0x0F,  0xE0, 	/* 2C870 */
+	0x01,  0xB0,  0x1E,  0x0C,  0x86,  0x00,  0x20,  0x19,  0xFE,  0x05,  0x24,  0x61,  0xFC,  0x11,  0x48,  0x05, 	/* 2C880 */
+	0x28,  0x0A,  0x30,  0x12,  0xC8,  0x65,  0x06,  0x01,  0x00,  0x7F,  0xFF,  0x02,  0x10,  0x0F,  0x20,  0x00, 	/* 2C890 */
+	0xC0,  0x03,  0x30,  0x3C,  0x08,  0x89,  0x08,  0x10,  0x08,  0x10,  0x09,  0xFF,  0x09,  0x01,  0x7F,  0x01, 	/* 2C8A0 */
+	0x12,  0x80,  0x12,  0xEE,  0x12,  0xAA,  0x25,  0x2A,  0x25,  0x2A,  0x7E,  0xAA,  0x04,  0x4E,  0x08,  0x48, 	/* 2C8B0 */
+	0x10,  0x89,  0x61,  0x09,  0x02,  0x07,  0x9A,  0x08,  0x06,  0x08,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x7E, 	/* 2C8C0 */
+	0xFF,  0x12,  0x88,  0x12,  0x88,  0x12,  0xE5,  0x23,  0x83,  0x24,  0xFD,  0x7C,  0x84,  0x46,  0xFC,  0x0A, 	/* 2C8D0 */
+	0x84,  0x10,  0x84,  0x60,  0xFC,  0x00,  0x00,  0xA2,  0x08,  0x10,  0x08,  0x20,  0x08,  0xFE,  0x08,  0x92, 	/* 2C8E0 */
+	0x7E,  0x92,  0x12,  0xFE,  0x12,  0x92,  0x12,  0x92,  0x22,  0xFE,  0x24,  0x28,  0x7C,  0x48,  0x07,  0xFF, 	/* 2C8F0 */
+	0x0A,  0x08,  0x10,  0x08,  0x60,  0x08,  0x00,  0x08,  0xA6,  0x08,  0x00,  0x08,  0xFC,  0x08,  0x04,  0x08, 	/* 2C900 */
+	0xFC,  0x7E,  0x04,  0x12,  0xFC,  0x12,  0x00,  0x13,  0xFF,  0x23,  0x11,  0x25,  0x11,  0x7C,  0xFE,  0x06, 	/* 2C910 */
+	0x92,  0x0A,  0x92,  0x10,  0x9C,  0x60,  0x90,  0x00,  0x10,  0xAA,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF, 	/* 2C920 */
+	0x0E,  0x18,  0x0D,  0x34,  0x14,  0xD4,  0x24,  0x92,  0x44,  0x11,  0x01,  0x00,  0x7F,  0xFF,  0x02,  0x20, 	/* 2C930 */
+	0x04,  0x20,  0x0F,  0x40,  0x00,  0xC0,  0x03,  0x30,  0x3C,  0x08,  0xAC,  0x08,  0x02,  0x08,  0x0C,  0x08, 	/* 2C940 */
+	0xF0,  0x08,  0x04,  0x7F,  0x52,  0x12,  0x49,  0x12,  0x89,  0x12,  0x04,  0x22,  0xF8,  0x24,  0x10,  0x7C, 	/* 2C950 */
+	0x10,  0x47,  0xFF,  0x0A,  0x10,  0x10,  0x10,  0x61,  0xFE,  0x00,  0x00,  0xBF,  0x08,  0x00,  0x09,  0xFF, 	/* 2C960 */
+	0x08,  0x12,  0x08,  0x9E,  0x7E,  0xD0,  0x12,  0xB0,  0x13,  0x1F,  0x12,  0x00,  0x22,  0xFC,  0x7C,  0x84, 	/* 2C970 */
+	0x44,  0xFC,  0x06,  0x84,  0x0A,  0xFC,  0x12,  0x84,  0x60,  0x84,  0x00,  0x8C,  0x92,  0x08,  0x44,  0x08, 	/* 2C980 */
+	0x44,  0x09,  0xFF,  0x08,  0x44,  0x7F,  0x7C,  0x12,  0x44,  0x12,  0x44,  0x12,  0x7C,  0x22,  0x10,  0x23, 	/* 2C990 */
+	0xFF,  0x7C,  0x38,  0x06,  0x34,  0x0A,  0x54,  0x10,  0x92,  0x63,  0x11,  0x00,  0x10,  0x9A,  0x08,  0x00, 	/* 2C9A0 */
+	0x08,  0xFF,  0x08,  0x91,  0x08,  0x91,  0x7E,  0xFF,  0x12,  0x80,  0x12,  0xBE,  0x12,  0xA2,  0x22,  0xA2, 	/* 2C9B0 */
+	0x24,  0xBE,  0x7C,  0xA2,  0x46,  0xBE,  0x09,  0x22,  0x11,  0x22,  0x62,  0x3E,  0x00,  0x00,  0x9B,  0x08, 	/* 2C9C0 */
+	0x04,  0x08,  0x1A,  0x09,  0xE2,  0x08,  0x24,  0x7E,  0x94,  0x12,  0x58,  0x13,  0xFE,  0x12,  0x40,  0x23, 	/* 2C9D0 */
+	0xFF,  0x24,  0x40,  0x7C,  0x7C,  0x46,  0xA4,  0x0A,  0x98,  0x11,  0x10,  0x62,  0x6C,  0x01,  0x83,  0xBC, 	/* 2C9E0 */
+	0x08,  0x00,  0x08,  0xFC,  0x08,  0xA4,  0x08,  0xA4,  0x7E,  0xB4,  0x12,  0xD4,  0x12,  0x8C,  0x12,  0xFC, 	/* 2C9F0 */
+	0x22,  0x00,  0x24,  0xFE,  0x7C,  0xAA,  0x46,  0xAA,  0x0A,  0xAA,  0x10,  0xAA,  0x63,  0xFF,  0x00,  0x00, 	/* 2CA00 */
+	0xBD,  0x08,  0x00,  0x08,  0xFE,  0x08,  0x90,  0x08,  0x90,  0x7E,  0xFC,  0x12,  0x90,  0x12,  0x90,  0x12, 	/* 2CA10 */
+	0xFC,  0x22,  0x90,  0x24,  0x90,  0x7C,  0xFE,  0x46,  0x2A,  0x0B,  0x56,  0x11,  0x52,  0x62,  0x02,  0x00, 	/* 2CA20 */
+	0x0C,  0xBE,  0x08,  0x48,  0x08,  0x48,  0x08,  0xFE,  0x08,  0x48,  0x7E,  0xFE,  0x12,  0x48,  0x13,  0xFF, 	/* 2CA30 */
+	0x12,  0x10,  0x22,  0xFE,  0x24,  0x92,  0x7C,  0xFE,  0x46,  0x92,  0x0B,  0xFF,  0x10,  0x82,  0x60,  0x82, 	/* 2CA40 */
+	0x00,  0x86,  0x81,  0x08,  0x20,  0x08,  0x20,  0x09,  0xFE,  0x09,  0x02,  0x7E,  0x00,  0x13,  0xFC,  0x12, 	/* 2CA50 */
+	0x40,  0x12,  0xA2,  0x25,  0x2A,  0x24,  0x5C,  0x78,  0x94,  0x0D,  0x34,  0x14,  0x52,  0x20,  0x91,  0x43, 	/* 2CA60 */
+	0x10,  0x00,  0x60,  0x82,  0x08,  0x10,  0x08,  0x50,  0x08,  0xD6,  0x08,  0x92,  0x7E,  0x92,  0x12,  0xD6, 	/* 2CA70 */
+	0x12,  0x92,  0x12,  0x92,  0x22,  0xFE,  0x24,  0x10,  0x7D,  0xFE,  0x46,  0x44,  0x0A,  0x28,  0x10,  0x30, 	/* 2CA80 */
+	0x60,  0xCC,  0x03,  0x03,  0x89,  0x10,  0x08,  0x10,  0x08,  0x10,  0xFF,  0x12,  0x90,  0x7D,  0x90,  0x25, 	/* 2CA90 */
+	0xBF,  0x24,  0xA8,  0x24,  0xC8,  0x25,  0x88,  0x4A,  0xFF,  0x78,  0x88,  0x0C,  0x98,  0x09,  0x14,  0x11, 	/* 2CAA0 */
+	0x24,  0x62,  0x42,  0x04,  0x81,  0x8B,  0x10,  0x00,  0x11,  0xFE,  0x10,  0x22,  0x10,  0x22,  0x7D,  0xEE, 	/* 2CAB0 */
+	0x15,  0x08,  0x15,  0x08,  0x25,  0xEE,  0x24,  0x66,  0x24,  0xAA,  0x79,  0x32,  0x4C,  0x66,  0x0A,  0xAA, 	/* 2CAC0 */
+	0x11,  0x32,  0x60,  0x44,  0x01,  0x98,  0x8C,  0x11,  0x04,  0x10,  0x88,  0x13,  0xFF,  0x10,  0x50,  0x7F, 	/* 2CAD0 */
+	0xFC,  0x12,  0x54,  0x12,  0x54,  0x13,  0xFF,  0x22,  0x54,  0x24,  0x54,  0x7D,  0xFC,  0x06,  0x58,  0x0A, 	/* 2CAE0 */
+	0xD4,  0x11,  0x52,  0x62,  0x51,  0x00,  0x50,  0x90,  0x10,  0x08,  0x13,  0xE8,  0x12,  0xA8,  0x12,  0xA8, 	/* 2CAF0 */
+	0x7F,  0xFF,  0x2A,  0xAA,  0x2A,  0xAA,  0x2B,  0xEA,  0x28,  0x8A,  0x4B,  0xF2,  0x70,  0xBC,  0x48,  0xA4, 	/* 2CB00 */
+	0x14,  0xA6,  0x25,  0x2A,  0x42,  0x31,  0x04,  0xC1,  0x96,  0x08,  0x00,  0x09,  0xFF,  0x08,  0x28,  0x08, 	/* 2CB10 */
+	0xFE,  0x7E,  0xAA,  0x12,  0xAA,  0x12,  0xFE,  0x12,  0x00,  0x22,  0xFE,  0x24,  0x00,  0x7D,  0xFF,  0x46, 	/* 2CB20 */
+	0x10,  0x0A,  0x94,  0x10,  0x92,  0x61,  0x12,  0x00,  0x30,  0x97,  0x08,  0x00,  0x09,  0xFF,  0x09,  0x00, 	/* 2CB30 */
+	0x09,  0x7C,  0x7F,  0x44,  0x15,  0x44,  0x15,  0x7C,  0x15,  0x00,  0x25,  0xEE,  0x25,  0xAA,  0x79,  0xAA, 	/* 2CB40 */
+	0x4D,  0xAA,  0x0B,  0xEE,  0x11,  0x00,  0x61,  0xFF,  0x01,  0x00,  0xA1,  0x08,  0x20,  0x08,  0x20,  0x0B, 	/* 2CB50 */
+	0xFF,  0x08,  0x84,  0x7E,  0x48,  0x13,  0xFE,  0x13,  0x22,  0x13,  0x22,  0x23,  0xFE,  0x25,  0x22,  0x7D, 	/* 2CB60 */
+	0x7A,  0x45,  0x4A,  0x09,  0x4A,  0x11,  0x7A,  0x61,  0x02,  0x01,  0x06,  0xA3,  0x08,  0x00,  0x09,  0xFF, 	/* 2CB70 */
+	0x08,  0x10,  0x08,  0x50,  0x7E,  0x5E,  0x12,  0x50,  0x12,  0x50,  0x13,  0xFF,  0x22,  0x80,  0x24,  0xFF, 	/* 2CB80 */
+	0x7C,  0x80,  0x46,  0xFE,  0x0A,  0x0A,  0x11,  0x56,  0x61,  0x52,  0x02,  0x0C,  0xA6,  0x08,  0x92,  0x08, 	/* 2CB90 */
+	0x52,  0x08,  0x54,  0x09,  0xFF,  0x7F,  0x01,  0x13,  0x7D,  0x12,  0x44,  0x12,  0x44,  0x22,  0x7C,  0x24, 	/* 2CBA0 */
+	0x10,  0x7C,  0xFE,  0x46,  0x92,  0x0A,  0x92,  0x10,  0x92,  0x60,  0x9C,  0x00,  0x10,  0xA9,  0x11,  0x10, 	/* 2CBB0 */
+	0x11,  0x10,  0x17,  0xD0,  0x11,  0x1F,  0x7F,  0xD4,  0x15,  0x64,  0x15,  0x54,  0x15,  0x54,  0x27,  0xD4, 	/* 2CBC0 */
+	0x25,  0x18,  0x79,  0x88,  0x0B,  0x54,  0x13,  0x14,  0x25,  0x22,  0x41,  0x42,  0x01,  0x81,  0xBA,  0x10, 	/* 2CBD0 */
+	0x00,  0x11,  0xDE,  0x11,  0x52,  0x11,  0xDE,  0x7F,  0x52,  0x15,  0x52,  0x15,  0xDE,  0x15,  0x02,  0x25, 	/* 2CBE0 */
+	0x7A,  0x25,  0x4A,  0x79,  0x7A,  0x0D,  0x4A,  0x09,  0x7A,  0x11,  0x4A,  0x61,  0x9A,  0x01,  0x06,  0xBB, 	/* 2CBF0 */
+	0x10,  0x00,  0x11,  0xDE,  0x11,  0x52,  0x11,  0xDE,  0x7F,  0x52,  0x15,  0x52,  0x15,  0xDE,  0x15,  0x22, 	/* 2CC00 */
+	0x25,  0x22,  0x25,  0xFA,  0x79,  0x32,  0x4D,  0x6A,  0x09,  0xA6,  0x11,  0x22,  0x61,  0x22,  0x01,  0x06, 	/* 2CC10 */
+	0x89,  0x08,  0x10,  0x09,  0xFF,  0x08,  0x10,  0x08,  0xFE,  0x7E,  0x00,  0x12,  0xFE,  0x12,  0x82,  0x12, 	/* 2CC20 */
+	0xFE,  0x22,  0x44,  0x24,  0x28,  0x7D,  0xFF,  0x06,  0x00,  0x0A,  0xFE,  0x10,  0x82,  0x60,  0xFE,  0x00, 	/* 2CC30 */
+	0x00,  0x8B,  0x08,  0x00,  0x09,  0xEF,  0x09,  0x29,  0x09,  0xEF,  0x7E,  0x00,  0x12,  0xFE,  0x12,  0x92, 	/* 2CC40 */
+	0x12,  0xFE,  0x22,  0x92,  0x24,  0x92,  0x7C,  0xFE,  0x46,  0x10,  0x0B,  0xFF,  0x10,  0x10,  0x60,  0x10, 	/* 2CC50 */
+	0x00,  0x10,  0x8C,  0x08,  0x0C,  0x08,  0xF0,  0x08,  0x10,  0x09,  0xFF,  0x7E,  0x48,  0x12,  0xFC,  0x13, 	/* 2CC60 */
+	0x4B,  0x12,  0x78,  0x22,  0x00,  0x25,  0xFE,  0x7D,  0x02,  0x47,  0x7A,  0x0B,  0x4A,  0x11,  0x7A,  0x61, 	/* 2CC70 */
+	0x02,  0x01,  0x06,  0x96,  0x00,  0x10,  0x1F,  0x10,  0x11,  0xFE,  0x11,  0x44,  0x1F,  0x28,  0x10,  0xFF, 	/* 2CC80 */
+	0x1F,  0x10,  0x29,  0xFE,  0x29,  0x10,  0x4F,  0x10,  0x01,  0x00,  0x7F,  0xFF,  0x04,  0x20,  0x0F,  0xC0, 	/* 2CC90 */
+	0x01,  0xB0,  0x3E,  0x0C,  0xA2,  0x08,  0x10,  0x08,  0x10,  0x09,  0xFF,  0x08,  0x44,  0x7F,  0xAA,  0x12, 	/* 2CCA0 */
+	0x29,  0x12,  0xFE,  0x12,  0x28,  0x22,  0xFE,  0x24,  0x28,  0x7D,  0xFF,  0x46,  0x28,  0x0A,  0x4A,  0x11, 	/* 2CCB0 */
+	0xC4,  0x60,  0x72,  0x01,  0x81,  0xAA,  0x08,  0x20,  0x09,  0xFE,  0x09,  0x02,  0x09,  0xFC,  0x7E,  0xA4, 	/* 2CCC0 */
+	0x14,  0xA8,  0x15,  0x30,  0x14,  0xFC,  0x27,  0x84,  0x24,  0xFC,  0x78,  0x84,  0x0C,  0xFC,  0x0A,  0x84, 	/* 2CCD0 */
+	0x10,  0xFC,  0x60,  0xC4,  0x03,  0x02,  0xAC,  0x08,  0x00,  0x08,  0xFE,  0x08,  0x10,  0x09,  0xFF,  0x7F, 	/* 2CCE0 */
+	0x11,  0x13,  0x77,  0x13,  0x11,  0x12,  0x76,  0x12,  0x00,  0x24,  0xFF,  0x7C,  0x10,  0x06,  0xFE,  0x0A, 	/* 2CCF0 */
+	0xAA,  0x10,  0xAA,  0x60,  0xAA,  0x00,  0x86,  0xB0,  0x00,  0x00,  0x3E,  0x7C,  0x22,  0x44,  0x3E,  0x7C, 	/* 2CD00 */
+	0x22,  0x44,  0x3E,  0x7C,  0x22,  0x44,  0x3E,  0x7C,  0x13,  0x24,  0x21,  0x42,  0x7F,  0xFF,  0x02,  0x20, 	/* 2CD10 */
+	0x04,  0x40,  0x0F,  0xC0,  0x03,  0x60,  0x3C,  0x18,  0xB2,  0x01,  0x00,  0x7D,  0x1F,  0x55,  0x15,  0x55, 	/* 2CD20 */
+	0x15,  0x7F,  0xFF,  0x55,  0x55,  0x55,  0x55,  0x7D,  0x5F,  0x12,  0x44,  0x7E,  0x5F,  0x17,  0x85,  0x14, 	/* 2CD30 */
+	0xC5,  0x24,  0xA9,  0x25,  0x09,  0x46,  0x11,  0x18,  0x26,  0xB6,  0x08,  0x20,  0x08,  0xFC,  0x08,  0x84, 	/* 2CD40 */
+	0x08,  0xFC,  0x7E,  0x84,  0x12,  0xFC,  0x12,  0x84,  0x13,  0xFE,  0x25,  0x22,  0x7D,  0xFE,  0x45,  0x22, 	/* 2CD50 */
+	0x09,  0xFE,  0x08,  0x00,  0x13,  0xFF,  0x60,  0x88,  0x01,  0x08,  0xBE,  0x11,  0x00,  0x11,  0x3F,  0x17, 	/* 2CD60 */
+	0xE9,  0x11,  0x09,  0x7F,  0xD6,  0x15,  0x60,  0x15,  0x5E,  0x25,  0x52,  0x27,  0xDE,  0x79,  0x12,  0x4B, 	/* 2CD70 */
+	0x9E,  0x0B,  0x52,  0x15,  0x3E,  0x25,  0x0C,  0x49,  0x12,  0x01,  0x61,  0x80,  0x10,  0x00,  0x13,  0xFE, 	/* 2CD80 */
+	0x10,  0x10,  0x13,  0xFF,  0x7E,  0x11,  0x17,  0x9D,  0x16,  0xD6,  0x24,  0x00,  0x25,  0x3E,  0x7F,  0xE2, 	/* 2CD90 */
+	0x49,  0x3E,  0x0B,  0xA2,  0x17,  0x7E,  0x65,  0x22,  0x09,  0x3E,  0x01,  0x00,  0x83,  0x08,  0x20,  0x0B, 	/* 2CDA0 */
+	0xFF,  0x08,  0x00,  0x09,  0xFE,  0x7F,  0x32,  0x13,  0xFE,  0x12,  0x48,  0x15,  0xFE,  0x24,  0x48,  0x25, 	/* 2CDB0 */
+	0xFE,  0x7C,  0x48,  0x07,  0xFF,  0x08,  0xD0,  0x13,  0x4A,  0x60,  0x74,  0x01,  0xC3,  0x85,  0x11,  0x28, 	/* 2CDC0 */
+	0x11,  0x2A,  0x12,  0xD9,  0x12,  0x49,  0x7C,  0x88,  0x17,  0xFF,  0x15,  0x48,  0x17,  0x6A,  0x25,  0x4A, 	/* 2CDD0 */
+	0x27,  0x6A,  0x79,  0x44,  0x0F,  0x64,  0x15,  0x5D,  0x21,  0xEB,  0x47,  0x13,  0x00,  0x21,  0x90,  0x00, 	/* 2CDE0 */
+	0x00,  0x1F,  0xF8,  0x00,  0x08,  0x00,  0x10,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x00,  0x80,  0x7F, 	/* 2CDF0 */
+	0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x01,  0x80,  0x91, 	/* 2CE00 */
+	0x00,  0x00,  0x1F,  0xF8,  0x00,  0x10,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x00,  0x82,  0x00,  0x9C, 	/* 2CE10 */
+	0x03,  0xE0,  0x7C,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x01,  0x80, 	/* 2CE20 */
+	0x94,  0x00,  0x20,  0x3F,  0xA0,  0x01,  0x20,  0x02,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0xA0,  0x07, 	/* 2CE30 */
+	0x20,  0x0C,  0x20,  0x74,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x21,  0x04,  0x21,  0x04,  0x1F,  0x0C, 	/* 2CE40 */
+	0x00,  0x95,  0x00,  0x00,  0x3F,  0xF8,  0x01,  0x08,  0x01,  0x08,  0x02,  0x1E,  0x04,  0x02,  0x18,  0x02, 	/* 2CE50 */
+	0x67,  0xF2,  0x00,  0x2C,  0x00,  0x40,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80, 	/* 2CE60 */
+	0x01,  0x80,  0x97,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFE,  0x40,  0x02,  0x40,  0x02,  0x0F,  0xF0,  0x00, 	/* 2CE70 */
+	0x20,  0x00,  0xC0,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 2CE80 */
+	0x80,  0x01,  0x80,  0x98,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFF,  0x02,  0x00,  0x04,  0x00, 	/* 2CE90 */
+	0x15,  0xFC,  0x18,  0x08,  0x10,  0x10,  0x30,  0x20,  0x57,  0xFF,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20, 	/* 2CEA0 */
+	0x10,  0x20,  0x10,  0x60,  0x9A,  0x00,  0x08,  0x00,  0x70,  0x1F,  0x80,  0x10,  0x84,  0x10,  0x42,  0x20, 	/* 2CEB0 */
+	0x41,  0x4F,  0xF8,  0x00,  0x10,  0x00,  0x20,  0x00,  0x40,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 2CEC0 */
+	0x80,  0x00,  0x80,  0x01,  0x80,  0x9B,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFC,  0x00,  0x80,  0x00,  0x80, 	/* 2CED0 */
+	0x7F,  0xFE,  0x40,  0x02,  0x40,  0x02,  0x0F,  0xF0,  0x00,  0x60,  0x00,  0x80,  0x7F,  0xFE,  0x00,  0x80, 	/* 2CEE0 */
+	0x00,  0x80,  0x00,  0x80,  0x01,  0x80,  0x9C,  0x00,  0x40,  0x7F,  0x40,  0x02,  0x40,  0x04,  0x7F,  0x08, 	/* 2CEF0 */
+	0x44,  0x08,  0x44,  0x0B,  0x84,  0x0C,  0x84,  0x19,  0x28,  0x68,  0x28,  0x08,  0x10,  0x08,  0x18,  0x08, 	/* 2CF00 */
+	0x28,  0x08,  0x44,  0x08,  0x82,  0x19,  0x01,  0x9D,  0x00,  0x80,  0x00,  0x84,  0x1F,  0xFC,  0x00,  0x88, 	/* 2CF10 */
+	0x00,  0x90,  0x7F,  0xFF,  0x00,  0xC0,  0x03,  0x00,  0x0F,  0xF0,  0x70,  0x20,  0x00,  0x40,  0x3F,  0xFE, 	/* 2CF20 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x01,  0x80,  0x9F,  0x00,  0x00,  0x1F,  0xF8,  0x00,  0x10,  0x00, 	/* 2CF30 */
+	0x60,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x01,  0x80,  0x00,  0x00,  0x1F,  0xFC,  0x12, 	/* 2CF40 */
+	0x24,  0x12,  0x24,  0x12,  0x24,  0x7F,  0xFF,  0x00,  0x00,  0xA3,  0x00,  0x08,  0x00,  0x30,  0x1F,  0xC0, 	/* 2CF50 */
+	0x00,  0x80,  0x7F,  0xFF,  0x01,  0xC0,  0x02,  0xA0,  0x0C,  0x98,  0x70,  0x87,  0x07,  0xF0,  0x00,  0x40, 	/* 2CF60 */
+	0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x01,  0x80,  0xA4,  0x00,  0x02,  0x7E,  0x0C,  0x03, 	/* 2CF70 */
+	0xF4,  0x05,  0x04,  0x09,  0x24,  0x09,  0x24,  0x0B,  0x24,  0x0D,  0x24,  0x79,  0x24,  0x09,  0x24,  0x09, 	/* 2CF80 */
+	0x24,  0x09,  0x34,  0x0A,  0x2A,  0x0A,  0x3A,  0x0D,  0xC6,  0x18,  0x01,  0xA5,  0x04,  0x00,  0x04,  0x00, 	/* 2CF90 */
+	0x7F,  0xFE,  0x08,  0xA2,  0x09,  0x24,  0x11,  0x14,  0x3E,  0x18,  0x05,  0x64,  0x18,  0x03,  0x67,  0xF0, 	/* 2CFA0 */
+	0x00,  0x60,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x01,  0x80,  0xA6,  0x11,  0x08,  0x08, 	/* 2CFB0 */
+	0x88,  0x08,  0x90,  0x7F,  0xFE,  0x40,  0x02,  0x40,  0x02,  0x1F,  0xF0,  0x00,  0x20,  0x00,  0xC0,  0x01, 	/* 2CFC0 */
+	0x00,  0x7F,  0xFE,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x03,  0x00,  0xA9,  0x00,  0x20, 	/* 2CFD0 */
+	0x7E,  0x20,  0x02,  0x20,  0x07,  0xFF,  0x08,  0x20,  0x08,  0x28,  0x09,  0xC8,  0x0E,  0x52,  0x78,  0x32, 	/* 2CFE0 */
+	0x08,  0x24,  0x08,  0x44,  0x09,  0x88,  0x08,  0x10,  0x08,  0x28,  0x08,  0xC4,  0x1B,  0x02,  0xAB,  0x00, 	/* 2CFF0 */
+	0x04,  0x7E,  0x18,  0x03,  0xE0,  0x04,  0x20,  0x08,  0x44,  0x09,  0xC8,  0x08,  0x30,  0x0C,  0x28,  0x18, 	/* 2D000 */
+	0x44,  0x6B,  0xFA,  0x08,  0x21,  0x08,  0xA8,  0x08,  0xA4,  0x09,  0x22,  0x0A,  0x22,  0x18,  0x20,  0xB0, 	/* 2D010 */
+	0x08,  0x10,  0x08,  0x10,  0x7F,  0x90,  0x00,  0x10,  0x3E,  0xFC,  0x22,  0x14,  0x3E,  0x14,  0x00,  0x94, 	/* 2D020 */
+	0x7F,  0x54,  0x02,  0x24,  0x04,  0x24,  0x07,  0x34,  0x7C,  0x55,  0x04,  0x55,  0x04,  0x83,  0x0D,  0x01, 	/* 2D030 */
+	0xB1,  0x00,  0x00,  0x1F,  0xFE,  0x10,  0x02,  0x1F,  0xFE,  0x10,  0x00,  0x13,  0xF0,  0x10,  0x20,  0x1F, 	/* 2D040 */
+	0xFE,  0x10,  0x20,  0x10,  0x60,  0x17,  0xBE,  0x11,  0x04,  0x3F,  0xFF,  0x22,  0x08,  0x42,  0x08,  0x06, 	/* 2D050 */
+	0x18,  0xB3,  0x08,  0x08,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x19,  0x64,  0x0A,  0x28,  0x05,  0x14, 	/* 2D060 */
+	0x3E,  0xFA,  0x00,  0x00,  0x0F,  0xF8,  0x00,  0x60,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80, 	/* 2D070 */
+	0x01,  0x80,  0xB5,  0x08,  0x02,  0x33,  0x8C,  0x2A,  0xF2,  0x2A,  0xA9,  0x2A,  0xA9,  0x3B,  0xA1,  0x3B, 	/* 2D080 */
+	0xC0,  0x2B,  0xBE,  0x2A,  0x84,  0x2A,  0x88,  0x3A,  0xFF,  0x6B,  0x88,  0x12,  0x08,  0x12,  0x08,  0x22, 	/* 2D090 */
+	0x08,  0x42,  0x18,  0xB8,  0x04,  0x00,  0x1A,  0xB8,  0x11,  0x08,  0x1E,  0xB8,  0x12,  0x88,  0x1D,  0x38, 	/* 2D0A0 */
+	0x12,  0x88,  0x7F,  0xFE,  0x40,  0x02,  0x4F,  0xF2,  0x00,  0x40,  0x00,  0x80,  0x7F,  0xFE,  0x00,  0x80, 	/* 2D0B0 */
+	0x00,  0x80,  0x01,  0x80,  0xBA,  0x00,  0x00,  0x7D,  0xFE,  0x04,  0x10,  0x0B,  0xFF,  0x1A,  0x11,  0x12, 	/* 2D0C0 */
+	0xDD,  0x12,  0x11,  0x14,  0xDD,  0x18,  0x00,  0x77,  0xFF,  0x10,  0x20,  0x11,  0xFE,  0x11,  0x52,  0x11, 	/* 2D0D0 */
+	0x52,  0x11,  0x52,  0x31,  0x06,  0x80,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 2D0E0 */
+	0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x40,  0x02,  0x40,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 2D0F0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x83,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x48, 	/* 2D100 */
+	0x02,  0x48,  0x00,  0x08,  0x10,  0x08,  0x20,  0x08,  0xC0,  0x0F,  0x00,  0x08,  0x00,  0x08,  0x02,  0x08, 	/* 2D110 */
+	0x02,  0x04,  0x02,  0x03,  0xFE,  0x00,  0x00,  0x85,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02, 	/* 2D120 */
+	0x40,  0x12,  0x40,  0x62,  0x1F,  0x80,  0x02,  0x00,  0x02,  0x0E,  0x03,  0xF0,  0x7E,  0x00,  0x02,  0x00, 	/* 2D130 */
+	0x02,  0x00,  0x02,  0x04,  0x01,  0x04,  0x00,  0xFC,  0x87,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x40, 	/* 2D140 */
+	0x02,  0x40,  0x02,  0x0F,  0xF0,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x01,  0x00,  0x01, 	/* 2D150 */
+	0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x03,  0x00,  0x88,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE, 	/* 2D160 */
+	0x40,  0x02,  0x40,  0x22,  0x00,  0x20,  0x00,  0x20,  0x7F,  0xFE,  0x00,  0x20,  0x08,  0x20,  0x04,  0x20, 	/* 2D170 */
+	0x04,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x60,  0x89,  0x01,  0x00,  0x01,  0x00,  0x7F, 	/* 2D180 */
+	0xFE,  0x42,  0x02,  0x42,  0x02,  0x02,  0x00,  0x02,  0x00,  0x7F,  0xFE,  0x04,  0x40,  0x04,  0x40,  0x08, 	/* 2D190 */
+	0x40,  0x0E,  0x40,  0x01,  0x80,  0x02,  0x60,  0x0C,  0x10,  0x30,  0x08,  0x8B,  0x01,  0x00,  0x01,  0x00, 	/* 2D1A0 */
+	0x7F,  0xFE,  0x40,  0x02,  0x41,  0x02,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x01,  0x00,  0x03,  0x80, 	/* 2D1B0 */
+	0x05,  0x40,  0x09,  0x20,  0x11,  0x18,  0x61,  0x06,  0x01,  0x00,  0x01,  0x00,  0x8C,  0x01,  0x00,  0x01, 	/* 2D1C0 */
+	0x00,  0x7F,  0xFE,  0x40,  0x02,  0x40,  0x02,  0x1F,  0xF8,  0x00,  0x00,  0x00,  0x00,  0x7F,  0xFE,  0x02, 	/* 2D1D0 */
+	0x40,  0x02,  0x40,  0x02,  0x40,  0x04,  0x42,  0x08,  0x42,  0x10,  0x22,  0x60,  0x1E,  0x8D,  0x01,  0x00, 	/* 2D1E0 */
+	0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x41,  0x02,  0x41,  0x02,  0x01,  0x00,  0x7F,  0xFE, 	/* 2D1F0 */
+	0x00,  0x00,  0x04,  0x20,  0x04,  0x10,  0x08,  0x08,  0x08,  0x08,  0x10,  0x04,  0x20,  0x04,  0x8F,  0x01, 	/* 2D200 */
+	0x00,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x42,  0x02,  0x02,  0x00,  0x7F,  0xFE,  0x02,  0x00,  0x02, 	/* 2D210 */
+	0x40,  0x04,  0x40,  0x04,  0x80,  0x08,  0x90,  0x11,  0x08,  0x22,  0x38,  0x4F,  0xC4,  0x00,  0x04,  0x95, 	/* 2D220 */
+	0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x40,  0x02,  0x00,  0x00,  0x7F,  0xFE,  0x01,  0x00, 	/* 2D230 */
+	0x02,  0x00,  0x04,  0x00,  0x0F,  0xF8,  0x18,  0x08,  0x68,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00, 	/* 2D240 */
+	0x97,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x40,  0x02,  0x4F,  0xF2,  0x00,  0x00,  0x00, 	/* 2D250 */
+	0x00,  0x7F,  0xFE,  0x01,  0x00,  0x11,  0x10,  0x11,  0x08,  0x21,  0x04,  0x41,  0x04,  0x01,  0x00,  0x03, 	/* 2D260 */
+	0x00,  0x98,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x4F,  0xF2,  0x08,  0x10,  0x08,  0x10, 	/* 2D270 */
+	0x0F,  0xF0,  0x08,  0x00,  0x08,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8, 	/* 2D280 */
+	0x00,  0x00,  0x99,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x41,  0x02,  0x41,  0x02,  0x01,  0x00,  0x1F, 	/* 2D290 */
+	0xF8,  0x11,  0x08,  0x11,  0x08,  0x11,  0x08,  0x1F,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x11,  0x08,  0x1F, 	/* 2D2A0 */
+	0xF8,  0x00,  0x00,  0x9A,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x40,  0x02,  0x1F,  0xF8, 	/* 2D2B0 */
+	0x01,  0x00,  0x01,  0x00,  0x09,  0x00,  0x09,  0xF8,  0x09,  0x00,  0x09,  0x00,  0x15,  0x00,  0x13,  0x00, 	/* 2D2C0 */
+	0x21,  0x80,  0x40,  0x7E,  0x9B,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFE,  0x48,  0x02,  0x48,  0x02,  0x08, 	/* 2D2D0 */
+	0x00,  0x0F,  0x7C,  0x11,  0x44,  0x12,  0x44,  0x2A,  0x44,  0x46,  0x44,  0x04,  0x58,  0x04,  0x40,  0x08, 	/* 2D2E0 */
+	0x42,  0x10,  0x42,  0x60,  0x3E,  0x9C,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFC,  0x40,  0x04,  0x40,  0x04, 	/* 2D2F0 */
+	0x0F,  0xE0,  0x08,  0x20,  0x08,  0x20,  0x0F,  0xE0,  0x08,  0x20,  0x08,  0x20,  0x0F,  0xE0,  0x08,  0x20, 	/* 2D300 */
+	0x08,  0x20,  0x7F,  0xFE,  0x00,  0x00,  0x9D,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x40, 	/* 2D310 */
+	0x02,  0x5F,  0xFA,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x1F,  0xF8,  0x01,  0x00,  0x01,  0x10,  0x01, 	/* 2D320 */
+	0x08,  0x01,  0x08,  0x7F,  0xFE,  0x00,  0x00,  0x9F,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02, 	/* 2D330 */
+	0x41,  0x02,  0x3F,  0xF8,  0x01,  0x00,  0x01,  0x00,  0x1F,  0xF0,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE, 	/* 2D340 */
+	0x02,  0x40,  0x04,  0x20,  0x18,  0x18,  0x60,  0x06,  0xA2,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x42, 	/* 2D350 */
+	0x02,  0x43,  0xE2,  0x04,  0x20,  0x0A,  0x40,  0x31,  0x80,  0x02,  0x40,  0x04,  0x20,  0x1F,  0xF8,  0x68, 	/* 2D360 */
+	0x16,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x00,  0x00,  0xA3,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE, 	/* 2D370 */
+	0x40,  0x02,  0x5F,  0xFA,  0x00,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10, 	/* 2D380 */
+	0x08,  0x10,  0x0F,  0xF0,  0x00,  0x00,  0x7F,  0xFE,  0x00,  0x00,  0xA4,  0x01,  0x00,  0x01,  0x00,  0x7F, 	/* 2D390 */
+	0xFE,  0x40,  0x02,  0x40,  0x02,  0x3F,  0xFC,  0x02,  0x40,  0x04,  0x30,  0x3F,  0xC8,  0x01,  0x04,  0x01, 	/* 2D3A0 */
+	0x00,  0x1F,  0xF8,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFF,  0x00,  0x00,  0xA5,  0x01,  0x00,  0x01,  0x00, 	/* 2D3B0 */
+	0x7F,  0xFE,  0x42,  0x02,  0x42,  0x02,  0x7F,  0xFC,  0x02,  0x00,  0x04,  0x00,  0x07,  0xF0,  0x0C,  0x10, 	/* 2D3C0 */
+	0x17,  0xF0,  0x24,  0x10,  0x47,  0xF0,  0x04,  0x10,  0x04,  0x10,  0x04,  0x30,  0xA6,  0x01,  0x00,  0x01, 	/* 2D3D0 */
+	0x00,  0x7F,  0xFE,  0x40,  0x02,  0x5F,  0xFA,  0x50,  0x80,  0x10,  0x80,  0x1F,  0xF8,  0x10,  0x08,  0x10, 	/* 2D3E0 */
+	0x08,  0x1F,  0xF8,  0x10,  0x80,  0x10,  0x80,  0x10,  0x80,  0x1F,  0xFC,  0x00,  0x00,  0xAE,  0x01,  0x00, 	/* 2D3F0 */
+	0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x4F,  0xF2,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x01,  0x00, 	/* 2D400 */
+	0x02,  0x00,  0x1F,  0xF8,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x1F,  0xF8,  0x00,  0x00,  0xB0,  0x01, 	/* 2D410 */
+	0x00,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x41,  0x02,  0x3F,  0xF8,  0x08,  0x20,  0x04,  0x40,  0x7F, 	/* 2D420 */
+	0xFE,  0x01,  0x00,  0x01,  0x00,  0x3F,  0xFC,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0xB3, 	/* 2D430 */
+	0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x41,  0x02,  0x41,  0x02,  0x3F,  0xFC,  0x01,  0x00,  0x1F,  0xF8, 	/* 2D440 */
+	0x01,  0x00,  0x7F,  0xFE,  0x00,  0x00,  0x1F,  0xF8,  0x10,  0x08,  0x10,  0x08,  0x1F,  0xF8,  0x00,  0x00, 	/* 2D450 */
+	0xB4,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x4F,  0xF2,  0x08,  0x10,  0x0F,  0xF0,  0x08, 	/* 2D460 */
+	0x10,  0x0F,  0xF0,  0x01,  0x00,  0x7F,  0xFE,  0x02,  0x20,  0x04,  0x20,  0x0F,  0xC0,  0x03,  0x30,  0x3C, 	/* 2D470 */
+	0x08,  0xB5,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x41,  0x02,  0x49,  0x22,  0x05,  0x20,  0x05,  0x40, 	/* 2D480 */
+	0x1F,  0xF0,  0x10,  0x10,  0x10,  0x10,  0x1F,  0xF0,  0x10,  0x10,  0x1F,  0xF0,  0x10,  0x10,  0x10,  0x10, 	/* 2D490 */
+	0x10,  0x30,  0xB6,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x40,  0x02,  0x1F,  0xF0,  0x02, 	/* 2D4A0 */
+	0x04,  0x0D,  0x44,  0x31,  0xC8,  0x02,  0xB0,  0x0C,  0xA0,  0x31,  0x90,  0x02,  0x88,  0x0C,  0x84,  0x70, 	/* 2D4B0 */
+	0x82,  0x03,  0x00,  0xB8,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x40,  0x02,  0x1F,  0xFC, 	/* 2D4C0 */
+	0x10,  0x00,  0x17,  0xF8,  0x10,  0x00,  0x1F,  0xFE,  0x14,  0x88,  0x14,  0x50,  0x24,  0x20,  0x24,  0x10, 	/* 2D4D0 */
+	0x47,  0x8C,  0x1C,  0x03,  0xB9,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x44,  0x42,  0x44,  0x22,  0x09, 	/* 2D4E0 */
+	0x10,  0x11,  0x90,  0x22,  0x40,  0x04,  0x20,  0x18,  0x18,  0x6F,  0xF6,  0x08,  0x10,  0x08,  0x10,  0x08, 	/* 2D4F0 */
+	0x10,  0x0F,  0xF0,  0x00,  0x00,  0xBF,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x44,  0x02, 	/* 2D500 */
+	0x07,  0xFC,  0x08,  0x40,  0x08,  0x80,  0x13,  0xF8,  0x32,  0x08,  0x52,  0x08,  0x13,  0xF8,  0x12,  0x08, 	/* 2D510 */
+	0x12,  0x08,  0x13,  0xF8,  0x10,  0x00,  0x82,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x48,  0x02,  0x48, 	/* 2D520 */
+	0x02,  0x0F,  0x00,  0x08,  0xFC,  0x08,  0x44,  0x7F,  0xC4,  0x08,  0x28,  0x1A,  0x28,  0x1A,  0x10,  0x29, 	/* 2D530 */
+	0x10,  0x49,  0x28,  0x08,  0x44,  0x19,  0x83,  0x83,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x41,  0x02, 	/* 2D540 */
+	0x43,  0xE2,  0x04,  0x40,  0x18,  0x80,  0x7F,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x1F,  0xF8,  0x02,  0xA0, 	/* 2D550 */
+	0x02,  0x90,  0x04,  0x8A,  0x18,  0x82,  0x60,  0x7E,  0x84,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x41, 	/* 2D560 */
+	0x02,  0x5F,  0xFA,  0x01,  0x80,  0x02,  0x40,  0x0C,  0x30,  0x7F,  0xFE,  0x00,  0x10,  0x1F,  0x90,  0x10, 	/* 2D570 */
+	0x90,  0x10,  0x90,  0x1F,  0x90,  0x00,  0x10,  0x00,  0x30,  0x85,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE, 	/* 2D580 */
+	0x40,  0x02,  0x5F,  0xFA,  0x01,  0x00,  0x1F,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x1F,  0xF8,  0x11,  0x08, 	/* 2D590 */
+	0x11,  0x08,  0x1F,  0xF8,  0x04,  0x20,  0x18,  0x18,  0x60,  0x04,  0x86,  0x01,  0x00,  0x01,  0x00,  0x7F, 	/* 2D5A0 */
+	0xFE,  0x41,  0x02,  0x44,  0xA2,  0x14,  0xA0,  0x14,  0x48,  0x24,  0x94,  0x43,  0x12,  0x1D,  0xF2,  0x01, 	/* 2D5B0 */
+	0x00,  0x21,  0x08,  0x21,  0x08,  0x21,  0x08,  0x3F,  0xF8,  0x00,  0x00,  0x87,  0x01,  0x00,  0x01,  0x00, 	/* 2D5C0 */
+	0x7F,  0xFE,  0x40,  0x02,  0x40,  0x22,  0x3E,  0x22,  0x00,  0x3C,  0x00,  0x20,  0x7F,  0xF8,  0x14,  0x88, 	/* 2D5D0 */
+	0x14,  0x50,  0x14,  0x20,  0x14,  0xD2,  0x17,  0x0E,  0x22,  0x02,  0x41,  0xFE,  0x89,  0x01,  0x00,  0x01, 	/* 2D5E0 */
+	0x00,  0x7F,  0xFE,  0x44,  0x02,  0x44,  0x22,  0x08,  0x40,  0x1F,  0xFC,  0x10,  0x80,  0x30,  0x80,  0x5F, 	/* 2D5F0 */
+	0xF8,  0x10,  0x80,  0x1F,  0xF8,  0x10,  0x80,  0x10,  0x80,  0x1F,  0xFE,  0x10,  0x00,  0x8C,  0x01,  0x00, 	/* 2D600 */
+	0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x5F,  0xFA,  0x00,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0, 	/* 2D610 */
+	0x00,  0x00,  0x1F,  0xF8,  0x11,  0x08,  0x1F,  0xF8,  0x11,  0x08,  0x1F,  0xF8,  0x00,  0x00,  0x90,  0x01, 	/* 2D620 */
+	0x00,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x44,  0x22,  0x24,  0x20,  0x25,  0xFC,  0x24,  0x20,  0x3C, 	/* 2D630 */
+	0x20,  0x07,  0xFF,  0x04,  0x70,  0x7C,  0xA8,  0x25,  0x24,  0x26,  0x23,  0x44,  0x20,  0x04,  0x60,  0x92, 	/* 2D640 */
+	0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x44,  0x42,  0x1F,  0xF8,  0x04,  0x40,  0x1F,  0xF8, 	/* 2D650 */
+	0x04,  0x40,  0x7F,  0xFE,  0x04,  0x20,  0x19,  0x98,  0x60,  0x46,  0x0F,  0x00,  0x00,  0xE0,  0x00,  0x10, 	/* 2D660 */
+	0x93,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x4F,  0xF2,  0x09,  0x10,  0x0F,  0xF0,  0x09, 	/* 2D670 */
+	0x10,  0x0F,  0xF0,  0x01,  0x00,  0x3F,  0xFC,  0x21,  0x44,  0x21,  0x34,  0x3F,  0xCC,  0x20,  0x04,  0x20, 	/* 2D680 */
+	0x0C,  0x94,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x20,  0x02,  0x27,  0xF2,  0x04,  0x10,  0x07,  0xF0, 	/* 2D690 */
+	0x04,  0x10,  0x07,  0xF0,  0x00,  0x00,  0x7F,  0xFF,  0x04,  0x80,  0x04,  0xFC,  0x0C,  0x80,  0x13,  0x80, 	/* 2D6A0 */
+	0x60,  0xFF,  0x9B,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x44,  0x22,  0x5F,  0xFA,  0x04,  0x20,  0x0F, 	/* 2D6B0 */
+	0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF2,  0x02,  0x42,  0x0C, 	/* 2D6C0 */
+	0x42,  0x70,  0x3E,  0x9D,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x49,  0xFA,  0x08,  0x08, 	/* 2D6D0 */
+	0x49,  0xF8,  0x28,  0x08,  0x29,  0xF8,  0x0F,  0xFE,  0x1C,  0x02,  0x2D,  0xFA,  0x48,  0x90,  0x08,  0x60, 	/* 2D6E0 */
+	0x08,  0xD8,  0x0F,  0x06,  0x9E,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFE,  0x44,  0x22,  0x5F,  0xFA,  0x04, 	/* 2D6F0 */
+	0x20,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x00,  0x80,  0x7F,  0xFE,  0x01, 	/* 2D700 */
+	0x40,  0x06,  0x30,  0x78,  0x0F,  0x9F,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x44,  0x02,  0x4F,  0xFE, 	/* 2D710 */
+	0x11,  0x48,  0x6A,  0x30,  0x04,  0x50,  0x19,  0x88,  0x67,  0xE6,  0x00,  0x00,  0x3F,  0xFC,  0x05,  0x60, 	/* 2D720 */
+	0x19,  0x18,  0x61,  0x04,  0x03,  0x00,  0xA1,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x5F, 	/* 2D730 */
+	0xFA,  0x01,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x7F,  0xFE,  0x04,  0x10,  0x1F, 	/* 2D740 */
+	0xFC,  0x61,  0x13,  0x06,  0x10,  0x18,  0x60,  0xA2,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02, 	/* 2D750 */
+	0x64,  0xFA,  0x24,  0x08,  0x25,  0xFE,  0x3C,  0x08,  0x07,  0xFE,  0x06,  0x02,  0x7D,  0xF8,  0x24,  0x88, 	/* 2D760 */
+	0x24,  0x50,  0x24,  0x20,  0x44,  0xD8,  0x07,  0x07,  0xA4,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x44, 	/* 2D770 */
+	0x02,  0x45,  0xFC,  0x24,  0x40,  0x27,  0xF8,  0x24,  0x88,  0x3C,  0x88,  0x07,  0xFF,  0x04,  0x00,  0x7D, 	/* 2D780 */
+	0xFC,  0x25,  0x04,  0x25,  0x04,  0x45,  0xFC,  0x04,  0x00,  0xA5,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFE, 	/* 2D790 */
+	0x40,  0x02,  0x5E,  0xFA,  0x0A,  0x28,  0x36,  0xD8,  0x0A,  0xA8,  0x33,  0x48,  0x06,  0x60,  0x19,  0x98, 	/* 2D7A0 */
+	0x6E,  0x47,  0x01,  0x90,  0x1E,  0x60,  0x01,  0x80,  0x1E,  0x00,  0xA6,  0x00,  0x80,  0x7F,  0xFE,  0x40, 	/* 2D7B0 */
+	0x02,  0x47,  0xFA,  0x04,  0x88,  0x3F,  0xFE,  0x11,  0x10,  0x1F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08, 	/* 2D7C0 */
+	0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x06,  0x18,  0x38,  0x06,  0xA7,  0x01,  0x00,  0x01,  0x00, 	/* 2D7D0 */
+	0x7F,  0xFE,  0x45,  0x02,  0x54,  0x8A,  0x12,  0x24,  0x21,  0xE2,  0x5F,  0xFA,  0x12,  0x48,  0x1F,  0xF8, 	/* 2D7E0 */
+	0x00,  0x00,  0x7F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x01,  0x80,  0xA8,  0x00,  0x80,  0x00, 	/* 2D7F0 */
+	0x80,  0x3F,  0xFE,  0x22,  0x22,  0x2F,  0xFA,  0x02,  0x20,  0x0F,  0xF8,  0x02,  0x20,  0x7F,  0xFF,  0x04, 	/* 2D800 */
+	0x90,  0x18,  0x8C,  0x6F,  0xFB,  0x02,  0xA0,  0x0C,  0x98,  0x70,  0x87,  0x00,  0x80,  0xA9,  0x01,  0x00, 	/* 2D810 */
+	0x01,  0x00,  0x3F,  0xFE,  0x20,  0x32,  0x2F,  0xCA,  0x04,  0x88,  0x02,  0x90,  0x7F,  0xFF,  0x02,  0xA0, 	/* 2D820 */
+	0x04,  0x90,  0x1F,  0xFC,  0x68,  0x8B,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x00,  0xAB,  0x01, 	/* 2D830 */
+	0x00,  0x01,  0x00,  0x7F,  0xFE,  0x41,  0x02,  0x4E,  0x72,  0x08,  0x10,  0x0E,  0x70,  0x08,  0x10,  0x0F, 	/* 2D840 */
+	0xF0,  0x04,  0x00,  0x0F,  0xFC,  0x10,  0x24,  0x64,  0x94,  0x12,  0x54,  0x12,  0x44,  0x20,  0x18,  0xAE, 	/* 2D850 */
+	0x01,  0x00,  0x7F,  0xFE,  0x41,  0x02,  0x01,  0x00,  0x7F,  0xFE,  0x22,  0x44,  0x14,  0x28,  0x1F,  0xF8, 	/* 2D860 */
+	0x68,  0x16,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x05,  0x60,  0x19,  0x18,  0x61,  0x04,  0x03,  0x00, 	/* 2D870 */
+	0xB0,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x5F,  0xFA,  0x12,  0x48,  0x1F,  0xF8,  0x00,  0x00,  0x7F, 	/* 2D880 */
+	0xFE,  0x00,  0x00,  0x1F,  0xF8,  0x10,  0x08,  0x1F,  0xFC,  0x02,  0x84,  0x0E,  0x68,  0x73,  0x98,  0x0E, 	/* 2D890 */
+	0x07,  0xB3,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x42,  0x3E,  0x7E,  0x08,  0x90,  0x3E,  0x54,  0x08,  0x92, 	/* 2D8A0 */
+	0x1F,  0xF2,  0x68,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x06,  0x30, 	/* 2D8B0 */
+	0x38,  0x0C,  0xB5,  0x01,  0x00,  0x7F,  0xFE,  0x48,  0x42,  0x7F,  0x7A,  0x22,  0x40,  0x14,  0x7C,  0x7F, 	/* 2D8C0 */
+	0x84,  0x00,  0x7C,  0x3E,  0x40,  0x22,  0x7C,  0x3E,  0x40,  0x22,  0x7C,  0x3E,  0x40,  0x22,  0x7C,  0x22, 	/* 2D8D0 */
+	0x42,  0x26,  0x3E,  0xB6,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x42,  0x3E,  0x7C,  0x08,  0x90,  0x3E,  0x7C, 	/* 2D8E0 */
+	0x08,  0x92,  0x1F,  0xFE,  0x68,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0, 	/* 2D8F0 */
+	0x06,  0x30,  0x38,  0x0C,  0xB8,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x3F,  0xFF,  0x00, 	/* 2D900 */
+	0x10,  0x00,  0x10,  0x08,  0x10,  0x04,  0x10,  0x02,  0x10,  0x02,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00, 	/* 2D910 */
+	0x10,  0x00,  0x10,  0x00,  0x30,  0xBA,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80, 	/* 2D920 */
+	0x00,  0x80,  0x7F,  0xFF,  0x00,  0x10,  0x00,  0x10,  0x3F,  0xFE,  0x08,  0x10,  0x04,  0x10,  0x02,  0x10, 	/* 2D930 */
+	0x02,  0x10,  0x00,  0x10,  0x00,  0x30,  0xBE,  0x04,  0x04,  0x04,  0x04,  0x04,  0x04,  0x7F,  0xC4,  0x01, 	/* 2D940 */
+	0x7F,  0x01,  0x04,  0x11,  0x04,  0x0A,  0x44,  0x06,  0x24,  0x02,  0x14,  0x05,  0x14,  0x09,  0x04,  0x08, 	/* 2D950 */
+	0x84,  0x10,  0x84,  0x20,  0x04,  0x40,  0x0C,  0xBF,  0x01,  0x00,  0x01,  0x00,  0x3F,  0xFE,  0x01,  0x00, 	/* 2D960 */
+	0x1F,  0xF8,  0x01,  0x00,  0x7F,  0xFE,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x05,  0x10, 	/* 2D970 */
+	0x08,  0x90,  0x10,  0x90,  0x20,  0x10,  0x00,  0x30,  0x81,  0x04,  0x04,  0x04,  0x04,  0x3F,  0x84,  0x04, 	/* 2D980 */
+	0x04,  0x04,  0x7F,  0x04,  0x04,  0x7F,  0x84,  0x04,  0x44,  0x04,  0x24,  0x3F,  0xA4,  0x04,  0x24,  0x04, 	/* 2D990 */
+	0x04,  0x05,  0x84,  0x0E,  0x04,  0x70,  0x04,  0x00,  0x0C,  0x82,  0x00,  0x80,  0x7F,  0xFE,  0x00,  0x80, 	/* 2D9A0 */
+	0x1F,  0xF8,  0x10,  0x88,  0x1F,  0xF8,  0x10,  0x88,  0x10,  0x88,  0x1F,  0xF8,  0x00,  0x20,  0x7F,  0xFF, 	/* 2D9B0 */
+	0x04,  0x20,  0x02,  0x20,  0x02,  0x20,  0x00,  0x20,  0x00,  0x60,  0x84,  0x02,  0x04,  0x04,  0x04,  0x1F, 	/* 2D9C0 */
+	0x04,  0x11,  0x04,  0x11,  0xFF,  0x1F,  0x04,  0x11,  0x04,  0x1F,  0x64,  0x11,  0x94,  0x1F,  0x14,  0x71, 	/* 2D9D0 */
+	0x04,  0x03,  0x04,  0x05,  0x04,  0x19,  0x04,  0x61,  0x04,  0x03,  0x0C,  0x85,  0x04,  0x04,  0x04,  0x04, 	/* 2D9E0 */
+	0x7F,  0xC4,  0x04,  0x04,  0x04,  0x7F,  0x3F,  0x04,  0x21,  0x04,  0x21,  0x44,  0x3F,  0x24,  0x0A,  0x24, 	/* 2D9F0 */
+	0x0A,  0x04,  0x0A,  0x04,  0x12,  0x05,  0x12,  0x0D,  0x21,  0x01,  0x40,  0xFF,  0x86,  0x08,  0x04,  0x08, 	/* 2DA00 */
+	0x38,  0x4B,  0xC2,  0x28,  0x22,  0x29,  0x14,  0x28,  0x94,  0x08,  0x88,  0x08,  0x08,  0x1B,  0xFF,  0x29, 	/* 2DA10 */
+	0x08,  0x28,  0x88,  0x48,  0x88,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x18,  0x87,  0x04,  0x20, 	/* 2DA20 */
+	0x24,  0x3C,  0x24,  0x44,  0x24,  0xA8,  0x25,  0x50,  0x3C,  0x20,  0x04,  0xC0,  0x07,  0x08,  0x7C,  0x08, 	/* 2DA30 */
+	0x27,  0xFF,  0x24,  0x08,  0x24,  0x88,  0x24,  0x48,  0x24,  0x48,  0x44,  0x08,  0x04,  0x18,  0x88,  0x00, 	/* 2DA40 */
+	0x80,  0x7F,  0xFF,  0x00,  0x80,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x00, 	/* 2DA50 */
+	0x88,  0x01,  0xF4,  0x3E,  0x02,  0x00,  0x08,  0x7F,  0xFF,  0x04,  0x08,  0x02,  0x08,  0x00,  0x18,  0x89, 	/* 2DA60 */
+	0x00,  0x04,  0x3F,  0x84,  0x20,  0x84,  0x20,  0x84,  0x3F,  0x84,  0x20,  0x7F,  0x2F,  0x04,  0x20,  0x04, 	/* 2DA70 */
+	0x20,  0x24,  0x3F,  0x94,  0x22,  0x14,  0x2B,  0x04,  0x2A,  0x84,  0x2A,  0x84,  0x52,  0x04,  0x06,  0x0C, 	/* 2DA80 */
+	0x8A,  0x08,  0x10,  0x04,  0x20,  0x7F,  0xFE,  0x02,  0x40,  0x1F,  0xF8,  0x12,  0x48,  0x14,  0x48,  0x1F, 	/* 2DA90 */
+	0xF8,  0x10,  0x08,  0x1F,  0xF8,  0x00,  0x20,  0x7F,  0xFE,  0x08,  0x20,  0x04,  0x20,  0x04,  0x20,  0x00, 	/* 2DAA0 */
+	0x60,  0x8B,  0x00,  0x00,  0x0F,  0xF0,  0x00,  0x10,  0x07,  0xF0,  0x00,  0x10,  0x0F,  0xF0,  0x00,  0x3E, 	/* 2DAB0 */
+	0x3F,  0xA2,  0x04,  0x22,  0x07,  0xBE,  0x38,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x02,  0x10,  0x02,  0x10, 	/* 2DAC0 */
+	0x00,  0x30,  0x8D,  0x0A,  0x04,  0x4A,  0x84,  0x2B,  0x04,  0x0A,  0x04,  0x7F,  0xFF,  0x00,  0x04,  0x11, 	/* 2DAD0 */
+	0x04,  0x0A,  0x44,  0x7F,  0xA4,  0x04,  0x24,  0x04,  0x04,  0x3F,  0x84,  0x04,  0x04,  0x07,  0x84,  0x0C, 	/* 2DAE0 */
+	0x04,  0x70,  0x0C,  0x8E,  0x00,  0x88,  0x27,  0xFF,  0x10,  0x40,  0x11,  0xFC,  0x01,  0x04,  0x79,  0xFC, 	/* 2DAF0 */
+	0x09,  0x04,  0x09,  0xFC,  0x09,  0x04,  0x17,  0x04,  0x21,  0xFF,  0x40,  0x08,  0x7F,  0xFF,  0x04,  0x08, 	/* 2DB00 */
+	0x02,  0x08,  0x00,  0x18,  0x8F,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x09, 	/* 2DB10 */
+	0x20,  0x09,  0x10,  0x09,  0x08,  0x11,  0x08,  0x11,  0x04,  0x21,  0x04,  0x41,  0x04,  0x01,  0x00,  0x01, 	/* 2DB20 */
+	0x00,  0x01,  0x00,  0x03,  0x00,  0x91,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x04,  0x90,  0x04,  0x88, 	/* 2DB30 */
+	0x08,  0x84,  0x08,  0x84,  0x10,  0x8A,  0x20,  0x8A,  0x40,  0x90,  0x01,  0x90,  0x00,  0x20,  0x00,  0x40, 	/* 2DB40 */
+	0x01,  0x80,  0x06,  0x00,  0x38,  0x00,  0x93,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x0F,  0xFF,  0x10, 	/* 2DB50 */
+	0x80,  0x10,  0x80,  0x20,  0x80,  0x44,  0x90,  0x04,  0x88,  0x04,  0x84,  0x08,  0x84,  0x08,  0x82,  0x10, 	/* 2DB60 */
+	0x82,  0x20,  0x82,  0x00,  0x80,  0x01,  0x80,  0x96,  0x00,  0x80,  0x00,  0x80,  0x02,  0xA0,  0x04,  0x98, 	/* 2DB70 */
+	0x08,  0x84,  0x30,  0x82,  0x00,  0x80,  0x01,  0x80,  0x00,  0x00,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80, 	/* 2DB80 */
+	0x01,  0x40,  0x02,  0x20,  0x0C,  0x18,  0x70,  0x07,  0x9A,  0x00,  0x80,  0x10,  0x88,  0x08,  0x88,  0x04, 	/* 2DB90 */
+	0x90,  0x04,  0xA0,  0x3F,  0xFE,  0x20,  0x02,  0x20,  0x02,  0x27,  0xF2,  0x24,  0x12,  0x24,  0x12,  0x24, 	/* 2DBA0 */
+	0x12,  0x27,  0xF2,  0x20,  0x02,  0x20,  0x02,  0x20,  0x06,  0xA0,  0x11,  0x08,  0x11,  0x08,  0x7F,  0x88, 	/* 2DBB0 */
+	0x11,  0x2C,  0x1F,  0x2A,  0x11,  0x2A,  0x1F,  0x49,  0x11,  0x09,  0x7F,  0xC8,  0x2A,  0x1A,  0x2A,  0x82, 	/* 2DBC0 */
+	0x29,  0x84,  0x30,  0x04,  0x20,  0x08,  0x3F,  0xB0,  0x00,  0xC0,  0xA2,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 2DBD0 */
+	0x80,  0x00,  0x80,  0x3F,  0xFF,  0x00,  0x80,  0x00,  0xC0,  0x00,  0xA0,  0x00,  0xA0,  0x01,  0x20,  0x01, 	/* 2DBE0 */
+	0x20,  0x02,  0x20,  0x02,  0x21,  0x04,  0x21,  0x18,  0x11,  0x60,  0x0F,  0xA4,  0x01,  0x00,  0x01,  0x10, 	/* 2DBF0 */
+	0x01,  0x08,  0x01,  0x08,  0x7F,  0xFF,  0x01,  0x00,  0x01,  0x00,  0x01,  0x80,  0x01,  0x40,  0x01,  0x40, 	/* 2DC00 */
+	0x01,  0x40,  0x02,  0x40,  0x02,  0x42,  0x04,  0x42,  0x18,  0x42,  0x60,  0x3E,  0xA8,  0x08,  0x08,  0x0A, 	/* 2DC10 */
+	0x08,  0x09,  0x08,  0x08,  0x12,  0x7F,  0xD2,  0x08,  0x24,  0x08,  0x45,  0x0C,  0x89,  0x0A,  0x12,  0x0A, 	/* 2DC20 */
+	0x22,  0x0A,  0x44,  0x12,  0x08,  0x12,  0x10,  0x12,  0x21,  0x21,  0x01,  0x40,  0xFF,  0xAD,  0x01,  0x00, 	/* 2DC30 */
+	0x01,  0x00,  0x3F,  0xF8,  0x01,  0x00,  0x09,  0x10,  0x08,  0x10,  0x7F,  0xFE,  0x08,  0x10,  0x08,  0x10, 	/* 2DC40 */
+	0x00,  0x00,  0x7F,  0xFE,  0x02,  0x40,  0x02,  0x40,  0x04,  0x42,  0x08,  0x42,  0x30,  0x3E,  0xB1,  0x04, 	/* 2DC50 */
+	0x14,  0x04,  0x12,  0x04,  0x12,  0x7F,  0x90,  0x00,  0x7F,  0x3F,  0x10,  0x21,  0x10,  0x21,  0x18,  0x3F, 	/* 2DC60 */
+	0x18,  0x04,  0x28,  0x15,  0x28,  0x14,  0xA8,  0x14,  0xA8,  0x24,  0x49,  0x44,  0x49,  0x0C,  0x87,  0xB8, 	/* 2DC70 */
+	0x00,  0x00,  0x0F,  0xFE,  0x08,  0x02,  0x08,  0x02,  0x08,  0x02,  0x0F,  0xFE,  0x08,  0x00,  0x08,  0x00, 	/* 2DC80 */
+	0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x10,  0x00,  0x10,  0x00,  0x20,  0x00,  0x40,  0x00, 	/* 2DC90 */
+	0xB9,  0x00,  0x00,  0x1F,  0xFC,  0x00,  0x84,  0x00,  0x84,  0x00,  0x84,  0x7F,  0xFF,  0x00,  0x84,  0x00, 	/* 2DCA0 */
+	0x84,  0x00,  0x84,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x01,  0x00,  0x02,  0x00,  0x0C,  0x00,  0x30, 	/* 2DCB0 */
+	0x00,  0xBA,  0x00,  0x00,  0x07,  0xFC,  0x04,  0x04,  0x04,  0x04,  0x04,  0x04,  0x04,  0x04,  0x07,  0xFC, 	/* 2DCC0 */
+	0x04,  0x80,  0x04,  0x80,  0x04,  0x80,  0x08,  0x40,  0x08,  0x40,  0x08,  0x20,  0x10,  0x10,  0x20,  0x0C, 	/* 2DCD0 */
+	0x40,  0x03,  0xBB,  0x00,  0x00,  0x1F,  0xFC,  0x10,  0x04,  0x10,  0x04,  0x1F,  0xFC,  0x11,  0x00,  0x11, 	/* 2DCE0 */
+	0x00,  0x11,  0x00,  0x1F,  0xF0,  0x11,  0x10,  0x11,  0x10,  0x11,  0x12,  0x22,  0x12,  0x22,  0x12,  0x44, 	/* 2DCF0 */
+	0x0E,  0x08,  0x00,  0xBC,  0x00,  0x00,  0x1F,  0xFE,  0x10,  0x02,  0x10,  0x02,  0x10,  0x02,  0x1F,  0xFE, 	/* 2DD00 */
+	0x12,  0x02,  0x12,  0x00,  0x12,  0x04,  0x12,  0x38,  0x13,  0xC0,  0x12,  0x00,  0x22,  0x02,  0x22,  0x02, 	/* 2DD10 */
+	0x41,  0x02,  0x00,  0xFE,  0xBD,  0x00,  0x00,  0x0F,  0xFC,  0x08,  0x04,  0x08,  0x04,  0x08,  0x04,  0x0F, 	/* 2DD20 */
+	0xFC,  0x08,  0x80,  0x08,  0x40,  0x0B,  0x20,  0x10,  0x90,  0x10,  0x4C,  0x20,  0x03,  0x47,  0x00,  0x00, 	/* 2DD30 */
+	0xC0,  0x00,  0x20,  0x00,  0x10,  0xBE,  0x00,  0x00,  0x1F,  0xFC,  0x10,  0x04,  0x10,  0x04,  0x1F,  0xFC, 	/* 2DD40 */
+	0x10,  0x10,  0x10,  0xE0,  0x17,  0x80,  0x10,  0x9C,  0x1F,  0xE0,  0x10,  0x80,  0x10,  0xFE,  0x1F,  0x80, 	/* 2DD50 */
+	0x20,  0x82,  0x20,  0x82,  0x40,  0x7E,  0xBF,  0x00,  0x00,  0x1F,  0xFC,  0x10,  0x04,  0x10,  0x04,  0x1F, 	/* 2DD60 */
+	0xFC,  0x10,  0x40,  0x10,  0x40,  0x10,  0x44,  0x1F,  0x64,  0x11,  0x68,  0x11,  0x50,  0x12,  0x50,  0x22, 	/* 2DD70 */
+	0x48,  0x24,  0x44,  0x48,  0x43,  0x00,  0xC0,  0x80,  0x00,  0x00,  0x1F,  0xFC,  0x10,  0x04,  0x10,  0x04, 	/* 2DD80 */
+	0x1F,  0xFC,  0x10,  0x00,  0x10,  0x00,  0x1F,  0xFE,  0x10,  0x02,  0x13,  0xF2,  0x12,  0x12,  0x12,  0x12, 	/* 2DD90 */
+	0x13,  0xF2,  0x20,  0x02,  0x20,  0x04,  0x40,  0x18,  0x81,  0x00,  0x00,  0x1F,  0xFE,  0x10,  0x02,  0x10, 	/* 2DDA0 */
+	0x02,  0x1F,  0xFE,  0x10,  0x00,  0x12,  0x10,  0x12,  0x10,  0x12,  0x12,  0x13,  0xD4,  0x12,  0x18,  0x12, 	/* 2DDB0 */
+	0x10,  0x22,  0x10,  0x22,  0xD1,  0x47,  0x11,  0x18,  0x0F,  0x85,  0x00,  0x00,  0x1F,  0xFC,  0x10,  0x04, 	/* 2DDC0 */
+	0x10,  0x04,  0x1F,  0xFC,  0x10,  0x40,  0x10,  0x40,  0x1F,  0xFF,  0x10,  0x40,  0x10,  0x40,  0x17,  0xFC, 	/* 2DDD0 */
+	0x14,  0x04,  0x24,  0x04,  0x24,  0x04,  0x47,  0xFC,  0x00,  0x00,  0x86,  0x00,  0x00,  0x1F,  0xFE,  0x10, 	/* 2DDE0 */
+	0x02,  0x10,  0x02,  0x1F,  0xFE,  0x10,  0x00,  0x10,  0x20,  0x14,  0x22,  0x17,  0xFE,  0x14,  0x22,  0x14, 	/* 2DDF0 */
+	0x22,  0x14,  0x22,  0x25,  0xFA,  0x24,  0x02,  0x47,  0xFE,  0x00,  0x00,  0x88,  0x00,  0x00,  0x1F,  0xFC, 	/* 2DE00 */
+	0x10,  0x04,  0x10,  0x04,  0x1F,  0xFC,  0x10,  0x80,  0x14,  0x88,  0x14,  0x88,  0x14,  0x88,  0x17,  0xF8, 	/* 2DE10 */
+	0x10,  0x80,  0x18,  0x84,  0x28,  0x84,  0x28,  0x84,  0x4F,  0xFC,  0x00,  0x00,  0x8A,  0x00,  0x00,  0x1F, 	/* 2DE20 */
+	0xFE,  0x10,  0x02,  0x10,  0x02,  0x1F,  0xFE,  0x10,  0x40,  0x10,  0x40,  0x17,  0xFE,  0x14,  0x42,  0x14, 	/* 2DE30 */
+	0x42,  0x14,  0x42,  0x17,  0xFE,  0x24,  0x42,  0x24,  0x42,  0x47,  0xFE,  0x00,  0x00,  0x8B,  0x00,  0x00, 	/* 2DE40 */
+	0x1F,  0xFC,  0x10,  0x04,  0x10,  0x04,  0x1F,  0xFC,  0x10,  0x00,  0x1F,  0xFE,  0x10,  0xB0,  0x13,  0x0C, 	/* 2DE50 */
+	0x1F,  0xFA,  0x10,  0x40,  0x17,  0xFC,  0x20,  0x40,  0x20,  0x40,  0x5F,  0xFF,  0x00,  0x00,  0x8D,  0x00, 	/* 2DE60 */
+	0x00,  0x1F,  0xFC,  0x10,  0x04,  0x10,  0x04,  0x1F,  0xFC,  0x10,  0x04,  0x10,  0x00,  0x1F,  0xFE,  0x12, 	/* 2DE70 */
+	0x20,  0x13,  0xA2,  0x12,  0xA4,  0x14,  0xB8,  0x3B,  0x20,  0x21,  0x22,  0x46,  0x22,  0x18,  0x1E,  0x8E, 	/* 2DE80 */
+	0x00,  0x00,  0x1F,  0xFE,  0x10,  0x02,  0x10,  0x02,  0x1F,  0xFE,  0x10,  0x40,  0x14,  0x48,  0x12,  0x48, 	/* 2DE90 */
+	0x12,  0x50,  0x1F,  0xFE,  0x10,  0xE0,  0x11,  0x50,  0x26,  0x4C,  0x38,  0x43,  0x40,  0x40,  0x00,  0x40, 	/* 2DEA0 */
+	0x8F,  0x00,  0x00,  0x1F,  0xFE,  0x10,  0x02,  0x10,  0x02,  0x1F,  0xFE,  0x12,  0x08,  0x11,  0x10,  0x17, 	/* 2DEB0 */
+	0xFE,  0x11,  0x10,  0x11,  0x10,  0x1F,  0xFF,  0x11,  0x10,  0x21,  0x10,  0x22,  0x10,  0x42,  0x10,  0x04, 	/* 2DEC0 */
+	0x10,  0x90,  0x00,  0x00,  0x1F,  0xFE,  0x10,  0x02,  0x10,  0x02,  0x1F,  0xFE,  0x12,  0x10,  0x12,  0xFF, 	/* 2DED0 */
+	0x15,  0x10,  0x19,  0x10,  0x12,  0xFC,  0x12,  0x44,  0x16,  0x28,  0x2A,  0x10,  0x22,  0x28,  0x42,  0x44, 	/* 2DEE0 */
+	0x03,  0x83,  0x91,  0x00,  0x00,  0x1F,  0xFC,  0x10,  0x04,  0x10,  0x04,  0x1F,  0xFC,  0x10,  0x40,  0x12, 	/* 2DEF0 */
+	0x48,  0x11,  0x50,  0x17,  0xF8,  0x14,  0x08,  0x17,  0xF8,  0x14,  0x08,  0x27,  0xF8,  0x24,  0x08,  0x44, 	/* 2DF00 */
+	0x08,  0x04,  0x18,  0x93,  0x00,  0x00,  0x1F,  0xFE,  0x10,  0x02,  0x10,  0x02,  0x1F,  0xFE,  0x10,  0x00, 	/* 2DF10 */
+	0x17,  0xFC,  0x14,  0x04,  0x17,  0xFC,  0x14,  0x04,  0x17,  0xFC,  0x14,  0x04,  0x27,  0xFC,  0x21,  0x10, 	/* 2DF20 */
+	0x46,  0x0C,  0x18,  0x02,  0x95,  0x00,  0x00,  0x1F,  0xFE,  0x10,  0x02,  0x10,  0x02,  0x1F,  0xFE,  0x11, 	/* 2DF30 */
+	0x10,  0x11,  0x10,  0x17,  0xFE,  0x11,  0x10,  0x11,  0x10,  0x1F,  0xFF,  0x12,  0x84,  0x12,  0x48,  0x22, 	/* 2DF40 */
+	0x30,  0x23,  0x8C,  0x4C,  0x03,  0x9E,  0x00,  0x00,  0x1F,  0xFC,  0x10,  0x04,  0x1F,  0xFC,  0x10,  0x0E, 	/* 2DF50 */
+	0x17,  0xF0,  0x10,  0x40,  0x17,  0xFC,  0x14,  0x44,  0x17,  0xFC,  0x10,  0x40,  0x1F,  0xFE,  0x28,  0x52, 	/* 2DF60 */
+	0x28,  0x6A,  0x4B,  0x8A,  0x08,  0x06,  0xA0,  0x00,  0x00,  0x1F,  0xFE,  0x10,  0x02,  0x10,  0x02,  0x1F, 	/* 2DF70 */
+	0xFE,  0x10,  0x48,  0x13,  0xFC,  0x10,  0x50,  0x1F,  0xFF,  0x10,  0x40,  0x11,  0xFC,  0x13,  0x04,  0x2D, 	/* 2DF80 */
+	0xFC,  0x21,  0x04,  0x41,  0xFC,  0x00,  0x00,  0xA1,  0x00,  0x00,  0x1F,  0xFE,  0x10,  0x02,  0x10,  0x02, 	/* 2DF90 */
+	0x1F,  0xFE,  0x12,  0x48,  0x11,  0x50,  0x1F,  0xFF,  0x13,  0x58,  0x1C,  0x46,  0x11,  0x40,  0x1F,  0xFF, 	/* 2DFA0 */
+	0x22,  0x10,  0x27,  0xE0,  0x41,  0x98,  0x1E,  0x04,  0xA4,  0x00,  0x00,  0x1F,  0xFE,  0x10,  0x02,  0x1F, 	/* 2DFB0 */
+	0xFE,  0x11,  0x10,  0x17,  0xFC,  0x14,  0x44,  0x17,  0xFC,  0x14,  0x44,  0x17,  0xFC,  0x10,  0x00,  0x13, 	/* 2DFC0 */
+	0xF8,  0x22,  0x08,  0x23,  0xF8,  0x42,  0x08,  0x03,  0xF8,  0xA5,  0x00,  0x00,  0x1F,  0xFE,  0x10,  0x02, 	/* 2DFD0 */
+	0x1F,  0xFE,  0x12,  0x40,  0x12,  0x7E,  0x14,  0x84,  0x19,  0xFC,  0x12,  0x84,  0x12,  0xFC,  0x14,  0x20, 	/* 2DFE0 */
+	0x1C,  0x7C,  0x25,  0xC8,  0x24,  0x30,  0x44,  0x4C,  0x07,  0x83,  0xAC,  0x00,  0x00,  0x1F,  0xFE,  0x10, 	/* 2DFF0 */
+	0x02,  0x1F,  0xFE,  0x17,  0x5C,  0x10,  0x40,  0x17,  0xFC,  0x14,  0xA4,  0x17,  0xFC,  0x11,  0x00,  0x13, 	/* 2E000 */
+	0xFE,  0x16,  0x4A,  0x2B,  0xFA,  0x20,  0x52,  0x4F,  0xEA,  0x00,  0x0C,  0xAE,  0x01,  0x00,  0x01,  0x00, 	/* 2E010 */
+	0x01,  0x00,  0x21,  0x04,  0x21,  0x04,  0x21,  0x04,  0x21,  0x04,  0x21,  0x04,  0x21,  0x04,  0x3F,  0xFC, 	/* 2E020 */
+	0x01,  0x00,  0x01,  0x00,  0x02,  0x00,  0x04,  0x00,  0x18,  0x00,  0x60,  0x00,  0xAF,  0x00,  0x80,  0x00, 	/* 2E030 */
+	0x83,  0x00,  0xFC,  0x7F,  0x80,  0x00,  0x80,  0x00,  0x80,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x08, 	/* 2E040 */
+	0x88,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x80,  0x00,  0x82,  0x00,  0x42,  0x00,  0x3E,  0xB1,  0x00,  0x80, 	/* 2E050 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x20,  0x82,  0x20,  0x82,  0x20,  0x82,  0x20,  0x82, 	/* 2E060 */
+	0x20,  0x82,  0x20,  0x82,  0x20,  0x82,  0x20,  0x82,  0x20,  0x82,  0x3F,  0xFE,  0x00,  0x00,  0xB6,  0x01, 	/* 2E070 */
+	0x00,  0x21,  0x04,  0x21,  0x04,  0x21,  0x04,  0x3F,  0xFC,  0x00,  0x00,  0x00,  0x00,  0x7F,  0xFE,  0x00, 	/* 2E080 */
+	0x82,  0x00,  0x82,  0x01,  0x02,  0x01,  0x02,  0x02,  0x02,  0x04,  0x02,  0x18,  0x04,  0x60,  0x18,  0xB9, 	/* 2E090 */
+	0x10,  0x40,  0x10,  0x40,  0x10,  0x40,  0x10,  0xFF,  0x54,  0x80,  0x55,  0x00,  0x57,  0xFC,  0x54,  0x08, 	/* 2E0A0 */
+	0x54,  0x10,  0x54,  0x20,  0x54,  0x40,  0x54,  0x80,  0x7D,  0x02,  0x01,  0x02,  0x00,  0x82,  0x00,  0x7E, 	/* 2E0B0 */
+	0x8C,  0x00,  0x80,  0x20,  0x82,  0x20,  0x82,  0x3F,  0xFE,  0x00,  0x00,  0x3F,  0xE0,  0x02,  0x20,  0x02, 	/* 2E0C0 */
+	0x20,  0x03,  0xF8,  0x05,  0x08,  0x05,  0x10,  0x08,  0xA0,  0x10,  0x40,  0x20,  0xA0,  0x43,  0x18,  0x1C, 	/* 2E0D0 */
+	0x07,  0x90,  0x10,  0x20,  0x10,  0x20,  0x13,  0xFF,  0x54,  0x20,  0x54,  0x20,  0x54,  0x20,  0x57,  0xFC, 	/* 2E0E0 */
+	0x54,  0x84,  0x54,  0x88,  0x54,  0x48,  0x54,  0x50,  0x7C,  0x30,  0x00,  0x30,  0x00,  0x48,  0x01,  0x84, 	/* 2E0F0 */
+	0x06,  0x03,  0x91,  0x00,  0x80,  0x20,  0x82,  0x20,  0x82,  0x3F,  0xFE,  0x00,  0x80,  0x01,  0x40,  0x02, 	/* 2E100 */
+	0x20,  0x07,  0xF0,  0x18,  0x0C,  0x60,  0x03,  0x0F,  0xF0,  0x00,  0x10,  0x00,  0x20,  0x00,  0x20,  0x00, 	/* 2E110 */
+	0x40,  0x00,  0x80,  0x94,  0x03,  0xE0,  0x00,  0x20,  0x04,  0x10,  0x08,  0x08,  0x1F,  0xF4,  0x61,  0x13, 	/* 2E120 */
+	0x01,  0x10,  0x02,  0x10,  0x0C,  0x10,  0x30,  0x60,  0x00,  0x80,  0x20,  0x82,  0x20,  0x82,  0x20,  0x82, 	/* 2E130 */
+	0x3F,  0xFE,  0x00,  0x00,  0xA1,  0x00,  0x00,  0x3F,  0xFE,  0x20,  0x22,  0x24,  0x22,  0x22,  0x22,  0x22, 	/* 2E140 */
+	0x42,  0x3F,  0xFE,  0x20,  0x82,  0x24,  0x92,  0x24,  0x92,  0x24,  0x92,  0x24,  0x92,  0x27,  0xF2,  0x20, 	/* 2E150 */
+	0x02,  0x20,  0x02,  0x20,  0x06,  0xA8,  0x10,  0x00,  0x10,  0xFC,  0x10,  0x84,  0x54,  0x84,  0x54,  0x84, 	/* 2E160 */
+	0x54,  0xFC,  0x54,  0x84,  0x54,  0x84,  0x54,  0x84,  0x54,  0xFC,  0x54,  0x84,  0x7C,  0x84,  0x00,  0x84, 	/* 2E170 */
+	0x00,  0x84,  0x07,  0xFF,  0x00,  0x00,  0xA9,  0x00,  0x80,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x1F, 	/* 2E180 */
+	0xFC,  0x00,  0x00,  0x00,  0x00,  0x7F,  0xFF,  0x02,  0x00,  0x04,  0x00,  0x0F,  0xF8,  0x14,  0x08,  0x64, 	/* 2E190 */
+	0x08,  0x04,  0x08,  0x07,  0xF8,  0x00,  0x00,  0xAB,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x54,  0x20, 	/* 2E1A0 */
+	0x55,  0xFE,  0x55,  0x22,  0x55,  0x22,  0x55,  0x22,  0x55,  0x22,  0x55,  0xFE,  0x55,  0x22,  0x55,  0x22, 	/* 2E1B0 */
+	0x7D,  0x22,  0x01,  0x22,  0x01,  0xFE,  0x00,  0x00,  0xAC,  0x10,  0x00,  0x11,  0xFE,  0x11,  0x22,  0x55, 	/* 2E1C0 */
+	0x22,  0x55,  0x22,  0x55,  0xFE,  0x55,  0x22,  0x55,  0x22,  0x55,  0x22,  0x55,  0xFE,  0x54,  0x20,  0x7C, 	/* 2E1D0 */
+	0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0xB1,  0x04,  0x48,  0x04,  0x44,  0x08,  0x44, 	/* 2E1E0 */
+	0x0F,  0xFF,  0x10,  0x20,  0x30,  0x20,  0x50,  0x12,  0x10,  0x0A,  0x10,  0x86,  0x10,  0x82,  0x20,  0x84, 	/* 2E1F0 */
+	0x20,  0x84,  0x20,  0x84,  0x20,  0x84,  0x3F,  0xFC,  0x00,  0x00,  0xB3,  0x00,  0x10,  0x00,  0x60,  0x07, 	/* 2E200 */
+	0x80,  0x04,  0x00,  0x07,  0xFC,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x00,  0x80,  0x10, 	/* 2E210 */
+	0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x00,  0x00,  0xB6,  0x10,  0x10,  0x10,  0x10, 	/* 2E220 */
+	0x10,  0x20,  0x52,  0xFE,  0x52,  0x82,  0x52,  0x82,  0x52,  0x82,  0x52,  0x82,  0x52,  0xFE,  0x52,  0x82, 	/* 2E230 */
+	0x52,  0x82,  0x52,  0x82,  0x7E,  0x82,  0x00,  0x82,  0x00,  0xFE,  0x00,  0x00,  0xB7,  0x10,  0x00,  0x11, 	/* 2E240 */
+	0xFE,  0x11,  0x02,  0x11,  0x02,  0x55,  0x02,  0x55,  0xFE,  0x55,  0x10,  0x55,  0x10,  0x55,  0xFF,  0x55, 	/* 2E250 */
+	0x10,  0x55,  0x10,  0x55,  0x08,  0x7D,  0x08,  0x01,  0x65,  0x01,  0x83,  0x06,  0x01,  0xB8,  0x00,  0x80, 	/* 2E260 */
+	0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x00,  0x00,  0x1F,  0xFF,  0x10,  0x00,  0x17,  0xFC,  0x10,  0x40, 	/* 2E270 */
+	0x10,  0x40,  0x1F,  0xFF,  0x10,  0x40,  0x20,  0x40,  0x20,  0x40,  0x40,  0x40,  0x00,  0x40,  0xBB,  0x10, 	/* 2E280 */
+	0x04,  0x10,  0x18,  0x55,  0xF0,  0x55,  0x10,  0x55,  0x10,  0x55,  0x10,  0x55,  0xFF,  0x55,  0x10,  0x55, 	/* 2E290 */
+	0x10,  0x55,  0x08,  0x55,  0x08,  0x7D,  0xE8,  0x07,  0x05,  0x00,  0x05,  0x07,  0xF3,  0x00,  0x01,  0xBC, 	/* 2E2A0 */
+	0x10,  0x00,  0x11,  0xFE,  0x10,  0x20,  0x54,  0xA8,  0x54,  0xA8,  0x54,  0xA4,  0x55,  0x24,  0x54,  0x20, 	/* 2E2B0 */
+	0x57,  0xFF,  0x54,  0x20,  0x54,  0x20,  0x7C,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20, 	/* 2E2C0 */
+	0xBE,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x54,  0x3F,  0x54,  0x20,  0x54,  0x20,  0x54, 	/* 2E2D0 */
+	0x20,  0x54,  0x20,  0x55,  0xFC,  0x55,  0x04,  0x55,  0x04,  0x7D,  0x04,  0x01,  0x04,  0x01,  0xFC,  0x00, 	/* 2E2E0 */
+	0x00,  0x85,  0x10,  0x20,  0x10,  0x20,  0x10,  0x48,  0x54,  0x8C,  0x57,  0xF2,  0x54,  0x89,  0x54,  0x88, 	/* 2E2F0 */
+	0x54,  0x88,  0x57,  0xFF,  0x54,  0x88,  0x54,  0x88,  0x7C,  0x88,  0x01,  0x08,  0x01,  0x08,  0x02,  0x08, 	/* 2E300 */
+	0x04,  0x08,  0x87,  0x00,  0x80,  0x20,  0x82,  0x20,  0x82,  0x3F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x01, 	/* 2E310 */
+	0x40,  0x06,  0x30,  0x1B,  0xEC,  0x60,  0x03,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F, 	/* 2E320 */
+	0xF8,  0x00,  0x00,  0x99,  0x10,  0x20,  0x10,  0x20,  0x11,  0xFE,  0x10,  0x20,  0x54,  0x20,  0x54,  0x20, 	/* 2E330 */
+	0x57,  0xFF,  0x54,  0x04,  0x54,  0x04,  0x57,  0xFF,  0x55,  0x04,  0x54,  0x84,  0x7C,  0x44,  0x00,  0x44, 	/* 2E340 */
+	0x00,  0x04,  0x00,  0x0C,  0xA0,  0x10,  0x20,  0x10,  0x20,  0x10,  0x3E,  0x54,  0x20,  0x54,  0x20,  0x57, 	/* 2E350 */
+	0xFF,  0x54,  0x00,  0x54,  0x00,  0x57,  0xFF,  0x54,  0x20,  0x54,  0x20,  0x54,  0x38,  0x7C,  0x26,  0x00, 	/* 2E360 */
+	0x20,  0x00,  0x20,  0x00,  0x20,  0xA1,  0x10,  0x10,  0x10,  0x10,  0x11,  0xFE,  0x54,  0x10,  0x54,  0x92, 	/* 2E370 */
+	0x54,  0x52,  0x54,  0x54,  0x54,  0x10,  0x57,  0xFF,  0x54,  0x10,  0x54,  0x10,  0x7C,  0x28,  0x44,  0x28, 	/* 2E380 */
+	0x00,  0x44,  0x00,  0x82,  0x03,  0x01,  0xA8,  0x10,  0x50,  0x10,  0x94,  0x13,  0x92,  0x54,  0x92,  0x54, 	/* 2E390 */
+	0x90,  0x57,  0xFF,  0x54,  0x90,  0x54,  0x92,  0x54,  0xD2,  0x55,  0x94,  0x56,  0x88,  0x7C,  0x9A,  0x44, 	/* 2E3A0 */
+	0xAA,  0x40,  0xC6,  0x00,  0x86,  0x03,  0x02,  0xA9,  0x00,  0x80,  0x20,  0x82,  0x20,  0x82,  0x3F,  0xFE, 	/* 2E3B0 */
+	0x02,  0x00,  0x0C,  0x28,  0x38,  0x24,  0x08,  0x24,  0x7F,  0xFF,  0x08,  0x20,  0x09,  0x24,  0x0E,  0x18, 	/* 2E3C0 */
+	0x78,  0x12,  0x08,  0x2A,  0x08,  0xC6,  0x1B,  0x02,  0xAA,  0x10,  0x88,  0x10,  0x88,  0x10,  0x84,  0x55, 	/* 2E3D0 */
+	0x24,  0x55,  0x24,  0x56,  0x50,  0x54,  0x48,  0x54,  0x84,  0x55,  0x02,  0x56,  0x01,  0x55,  0xFC,  0x7D, 	/* 2E3E0 */
+	0x04,  0x01,  0x04,  0x01,  0x04,  0x01,  0xFC,  0x00,  0x00,  0xAD,  0x10,  0x28,  0x11,  0x24,  0x11,  0x22, 	/* 2E3F0 */
+	0x12,  0x22,  0x54,  0x20,  0x55,  0xFC,  0x55,  0x04,  0x55,  0x04,  0x55,  0xFC,  0x55,  0x04,  0x55,  0x04, 	/* 2E400 */
+	0x55,  0xFC,  0x7D,  0x04,  0x01,  0x04,  0x01,  0x04,  0x01,  0x0C,  0xAF,  0x20,  0x82,  0x20,  0x82,  0x3F, 	/* 2E410 */
+	0xFE,  0x01,  0x00,  0x01,  0xF0,  0x06,  0x20,  0x3B,  0x40,  0x01,  0xC0,  0x06,  0x38,  0x78,  0x87,  0x0F, 	/* 2E420 */
+	0xF8,  0x00,  0x80,  0x0F,  0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0xB0,  0x00,  0x20,  0x10,  0x3C, 	/* 2E430 */
+	0x10,  0x44,  0x54,  0x88,  0x57,  0x50,  0x54,  0x20,  0x54,  0xD0,  0x57,  0x0C,  0x54,  0x23,  0x55,  0xFC, 	/* 2E440 */
+	0x54,  0x20,  0x7D,  0xFC,  0x00,  0x20,  0x07,  0xFF,  0x00,  0x20,  0x00,  0x20,  0xB6,  0x01,  0x00,  0x02, 	/* 2E450 */
+	0x00,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x00,  0x0F,  0xFF,  0x08, 	/* 2E460 */
+	0x00,  0x0F,  0xFE,  0x02,  0x02,  0x22,  0x22,  0x22,  0x22,  0x3F,  0xE2,  0x00,  0x1C,  0xBA,  0x10,  0x00, 	/* 2E470 */
+	0x13,  0xFF,  0x10,  0x20,  0x55,  0xFC,  0x55,  0x24,  0x55,  0x24,  0x55,  0xFC,  0x55,  0x24,  0x55,  0x24, 	/* 2E480 */
+	0x55,  0xFC,  0x54,  0x20,  0x7C,  0xA0,  0x00,  0x60,  0x00,  0x90,  0x03,  0x0C,  0x0C,  0x03,  0xBB,  0x00, 	/* 2E490 */
+	0x40,  0x10,  0x50,  0x10,  0x8C,  0x13,  0xFA,  0x54,  0x50,  0x54,  0x51,  0x54,  0x9F,  0x55,  0x40,  0x56, 	/* 2E4A0 */
+	0x78,  0x54,  0x48,  0x54,  0x88,  0x57,  0x50,  0x7C,  0x20,  0x44,  0x50,  0x41,  0x8C,  0x06,  0x03,  0xBD, 	/* 2E4B0 */
+	0x00,  0x20,  0x10,  0x20,  0x13,  0xFF,  0x54,  0x20,  0x55,  0x24,  0x55,  0x24,  0x55,  0x24,  0x55,  0xA6, 	/* 2E4C0 */
+	0x56,  0x69,  0x56,  0x30,  0x54,  0x50,  0x7C,  0x50,  0x00,  0x88,  0x01,  0x04,  0x02,  0x02,  0x0C,  0x01, 	/* 2E4D0 */
+	0x87,  0x21,  0x04,  0x21,  0x04,  0x3F,  0xFC,  0x21,  0x04,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x4F, 	/* 2E4E0 */
+	0xF2,  0x00,  0x00,  0x00,  0x00,  0x7F,  0xFE,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x82,  0x00,  0x80,  0x01, 	/* 2E4F0 */
+	0x80,  0x8B,  0x00,  0x80,  0x20,  0x82,  0x20,  0x82,  0x3F,  0xFE,  0x00,  0x00,  0x3F,  0xFE,  0x08,  0x88, 	/* 2E500 */
+	0x08,  0x88,  0x7F,  0xFF,  0x08,  0x88,  0x08,  0x88,  0x3F,  0xFE,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80, 	/* 2E510 */
+	0x00,  0x80,  0x8E,  0x00,  0x20,  0x10,  0x20,  0x13,  0xFE,  0x54,  0x50,  0x54,  0x88,  0x55,  0x04,  0x54, 	/* 2E520 */
+	0x00,  0x57,  0xFF,  0x54,  0x04,  0x55,  0xE4,  0x55,  0x24,  0x55,  0x24,  0x7D,  0xE4,  0x00,  0x04,  0x00, 	/* 2E530 */
+	0x04,  0x00,  0x0C,  0x91,  0x00,  0x80,  0x20,  0x82,  0x20,  0x82,  0x3F,  0xFE,  0x00,  0x00,  0x1F,  0xF8, 	/* 2E540 */
+	0x10,  0x08,  0x1F,  0xF8,  0x10,  0x08,  0x1F,  0xF8,  0x10,  0x40,  0x10,  0x44,  0x1F,  0x58,  0x10,  0x62, 	/* 2E550 */
+	0x1F,  0x42,  0x70,  0x3E,  0x94,  0x00,  0x80,  0x20,  0x82,  0x20,  0x82,  0x3F,  0xFE,  0x08,  0x20,  0x08, 	/* 2E560 */
+	0x40,  0x1F,  0xFE,  0x30,  0x80,  0x50,  0x80,  0x1F,  0xFC,  0x10,  0x80,  0x1F,  0xFC,  0x10,  0x80,  0x10, 	/* 2E570 */
+	0x80,  0x1F,  0xFF,  0x00,  0x00,  0x95,  0x10,  0x00,  0x11,  0xFF,  0x11,  0x10,  0x55,  0x10,  0x55,  0x7E, 	/* 2E580 */
+	0x55,  0x10,  0x55,  0x10,  0x55,  0xFF,  0x55,  0x10,  0x55,  0x10,  0x7D,  0xFE,  0x02,  0x10,  0x02,  0x10, 	/* 2E590 */
+	0x04,  0x10,  0x09,  0xFF,  0x00,  0x00,  0x96,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x00,  0x00,  0x1F, 	/* 2E5A0 */
+	0xFF,  0x10,  0x40,  0x17,  0xFC,  0x10,  0x40,  0x10,  0x40,  0x1F,  0xFE,  0x10,  0x40,  0x17,  0xFC,  0x20, 	/* 2E5B0 */
+	0x40,  0x20,  0x40,  0x5F,  0xFF,  0x00,  0x00,  0x97,  0x00,  0x80,  0x20,  0x82,  0x20,  0x82,  0x3F,  0xFE, 	/* 2E5C0 */
+	0x00,  0x00,  0x3F,  0xFE,  0x24,  0x12,  0x22,  0x22,  0x3F,  0xFE,  0x20,  0x82,  0x24,  0x92,  0x24,  0x92, 	/* 2E5D0 */
+	0x24,  0x92,  0x27,  0xF2,  0x20,  0x02,  0x20,  0x06,  0x98,  0x10,  0x20,  0x10,  0x20,  0x10,  0x50,  0x10, 	/* 2E5E0 */
+	0x48,  0x54,  0x84,  0x55,  0xFA,  0x56,  0x01,  0x54,  0x00,  0x55,  0xFE,  0x55,  0x52,  0x55,  0x52,  0x55, 	/* 2E5F0 */
+	0xFE,  0x7D,  0x52,  0x01,  0x52,  0x01,  0x52,  0x01,  0x06,  0x99,  0x00,  0x80,  0x20,  0x82,  0x20,  0x82, 	/* 2E600 */
+	0x3F,  0xFE,  0x00,  0x80,  0x01,  0x40,  0x06,  0x30,  0x1B,  0xEC,  0x60,  0x03,  0x1F,  0xFC,  0x12,  0x24, 	/* 2E610 */
+	0x12,  0x24,  0x1F,  0xFC,  0x12,  0x24,  0x12,  0x24,  0x12,  0x2C,  0x9A,  0x10,  0x20,  0x10,  0x20,  0x13, 	/* 2E620 */
+	0xFE,  0x10,  0x20,  0x57,  0xFF,  0x54,  0x88,  0x54,  0x89,  0x55,  0x27,  0x56,  0x20,  0x54,  0x7C,  0x54, 	/* 2E630 */
+	0x84,  0x57,  0x48,  0x7C,  0x30,  0x00,  0x70,  0x01,  0x8C,  0x0E,  0x03,  0x9B,  0x10,  0x00,  0x11,  0xFE, 	/* 2E640 */
+	0x11,  0x02,  0x55,  0x02,  0x55,  0xFE,  0x55,  0x10,  0x55,  0x92,  0x55,  0x92,  0x55,  0x92,  0x55,  0xFE, 	/* 2E650 */
+	0x55,  0x10,  0x7D,  0x90,  0x02,  0x92,  0x02,  0x92,  0x04,  0xFE,  0x08,  0x00,  0x9F,  0x00,  0x80,  0x20, 	/* 2E660 */
+	0x82,  0x20,  0x82,  0x3F,  0xFE,  0x00,  0x80,  0x01,  0x40,  0x06,  0x30,  0x1F,  0xFC,  0x60,  0x83,  0x00, 	/* 2E670 */
+	0x80,  0x7F,  0xFF,  0x00,  0x80,  0x08,  0x88,  0x04,  0x90,  0x3F,  0xFE,  0x00,  0x00,  0xA2,  0x10,  0x04, 	/* 2E680 */
+	0x10,  0x18,  0x13,  0xE4,  0x10,  0x92,  0x55,  0x12,  0x57,  0xFC,  0x54,  0x24,  0x54,  0x24,  0x57,  0xFF, 	/* 2E690 */
+	0x54,  0x24,  0x54,  0x24,  0x55,  0xFC,  0x7C,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x60,  0xA9,  0x00, 	/* 2E6A0 */
+	0x80,  0x10,  0x82,  0x10,  0x82,  0x1F,  0xFE,  0x00,  0x00,  0x1F,  0x3E,  0x11,  0x22,  0x11,  0x22,  0x1F, 	/* 2E6B0 */
+	0x3E,  0x11,  0x22,  0x11,  0x22,  0x1F,  0x3E,  0x11,  0x22,  0x21,  0x42,  0x21,  0x42,  0x43,  0x86,  0x8B, 	/* 2E6C0 */
+	0x10,  0x00,  0x11,  0xFE,  0x11,  0x12,  0x55,  0x12,  0x55,  0xFE,  0x55,  0x00,  0x55,  0x7E,  0x55,  0x42, 	/* 2E6D0 */
+	0x55,  0x42,  0x55,  0x7E,  0x55,  0x42,  0x7D,  0x7E,  0x02,  0x42,  0x02,  0x42,  0x04,  0x7E,  0x08,  0x00, 	/* 2E6E0 */
+	0x8C,  0x00,  0x80,  0x20,  0x82,  0x20,  0x82,  0x3F,  0xFE,  0x00,  0x40,  0x22,  0x40,  0x22,  0x7F,  0x7F, 	/* 2E6F0 */
+	0x42,  0x22,  0x94,  0x23,  0x10,  0x3E,  0x10,  0x22,  0x28,  0x22,  0x28,  0x22,  0x44,  0x3E,  0x82,  0x03, 	/* 2E700 */
+	0x01,  0x8E,  0x10,  0x00,  0x11,  0xFC,  0x11,  0x24,  0x55,  0x24,  0x55,  0xFC,  0x55,  0x24,  0x55,  0x24, 	/* 2E710 */
+	0x55,  0xFC,  0x54,  0x20,  0x57,  0xFE,  0x56,  0x22,  0x7E,  0x2A,  0x02,  0x7A,  0x03,  0x86,  0x02,  0x02, 	/* 2E720 */
+	0x02,  0x06,  0x90,  0x11,  0x08,  0x11,  0x08,  0x1F,  0xF8,  0x00,  0x00,  0x1F,  0xF8,  0x10,  0x28,  0x1F, 	/* 2E730 */
+	0xC8,  0x11,  0x08,  0x17,  0xE8,  0x15,  0x28,  0x15,  0x28,  0x17,  0xE8,  0x11,  0x44,  0x21,  0x25,  0x2F, 	/* 2E740 */
+	0xD3,  0x40,  0x11,  0x92,  0x00,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x00,  0x00, 	/* 2E750 */
+	0x7E,  0x7E,  0x42,  0x42,  0x42,  0x42,  0x7E,  0x7E,  0x01,  0x00,  0x21,  0x04,  0x21,  0x04,  0x21,  0x04, 	/* 2E760 */
+	0x3F,  0xFC,  0x00,  0x00,  0x9C,  0x00,  0x80,  0x10,  0x82,  0x10,  0x82,  0x1F,  0xFE,  0x00,  0x80,  0x3F, 	/* 2E770 */
+	0xFE,  0x04,  0x10,  0x02,  0x20,  0x7F,  0xFF,  0x00,  0x04,  0x0F,  0xC4,  0x08,  0x44,  0x08,  0x44,  0x0F, 	/* 2E780 */
+	0xC4,  0x00,  0x04,  0x00,  0x0C,  0xA9,  0x21,  0x04,  0x21,  0x04,  0x3F,  0xFC,  0x01,  0x00,  0x7F,  0xFF, 	/* 2E790 */
+	0x00,  0x00,  0x07,  0xE0,  0x04,  0x20,  0x07,  0xE0,  0x00,  0x00,  0x3F,  0xFC,  0x20,  0x04,  0x27,  0xE4, 	/* 2E7A0 */
+	0x24,  0x24,  0x27,  0xE4,  0x20,  0x0C,  0xAC,  0x00,  0x80,  0x20,  0x82,  0x20,  0x82,  0x3F,  0xFE,  0x01, 	/* 2E7B0 */
+	0x00,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x0F,  0xFC,  0x01,  0x44,  0x01, 	/* 2E7C0 */
+	0x4A,  0x02,  0x5F,  0x0C,  0x21,  0x70,  0x1F,  0xAF,  0x10,  0x84,  0x10,  0x48,  0x13,  0xFE,  0x54,  0x20, 	/* 2E7D0 */
+	0x54,  0x20,  0x55,  0xFC,  0x54,  0x20,  0x54,  0x20,  0x57,  0xFF,  0x54,  0x80,  0x54,  0x80,  0x7D,  0xFE, 	/* 2E7E0 */
+	0x42,  0x10,  0x44,  0x10,  0x01,  0xFF,  0x00,  0x00,  0xB3,  0x20,  0x82,  0x20,  0x82,  0x3F,  0xFE,  0x04, 	/* 2E7F0 */
+	0x10,  0x02,  0x20,  0x3F,  0xFC,  0x00,  0x80,  0x1F,  0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0x00,  0x07, 	/* 2E800 */
+	0xFC,  0x08,  0x40,  0x10,  0x40,  0x6F,  0xFF,  0x00,  0x00,  0xB6,  0x10,  0x00,  0x13,  0xFE,  0x10,  0x42, 	/* 2E810 */
+	0x54,  0x42,  0x54,  0x42,  0x55,  0xDE,  0x55,  0x10,  0x55,  0x10,  0x55,  0xDE,  0x55,  0x4A,  0x56,  0x52, 	/* 2E820 */
+	0x54,  0xC6,  0x7D,  0x4A,  0x02,  0x52,  0x00,  0x42,  0x01,  0x8C,  0x82,  0x10,  0x20,  0x10,  0x20,  0x11, 	/* 2E830 */
+	0xFE,  0x54,  0x84,  0x54,  0x48,  0x57,  0xFF,  0x54,  0x00,  0x54,  0xFC,  0x54,  0x84,  0x54,  0xFC,  0x54, 	/* 2E840 */
+	0x84,  0x7C,  0xFC,  0x00,  0x20,  0x07,  0xFF,  0x00,  0x20,  0x00,  0x20,  0x84,  0x00,  0x80,  0x20,  0x82, 	/* 2E850 */
+	0x20,  0x82,  0x3F,  0xFE,  0x04,  0x02,  0x7F,  0xC4,  0x04,  0x38,  0x3F,  0xA0,  0x24,  0xBF,  0x3F,  0xA4, 	/* 2E860 */
+	0x24,  0xA4,  0x3F,  0xA4,  0x04,  0x24,  0x7F,  0xC4,  0x04,  0x44,  0x04,  0x84,  0x87,  0x10,  0x00,  0x11, 	/* 2E870 */
+	0xFF,  0x11,  0x00,  0x55,  0x3C,  0x55,  0x24,  0x55,  0x24,  0x55,  0x3C,  0x55,  0x00,  0x55,  0xEE,  0x55, 	/* 2E880 */
+	0xAA,  0x55,  0xAA,  0x55,  0xAA,  0x7D,  0xEE,  0x01,  0x00,  0x01,  0xFF,  0x00,  0x00,  0x8B,  0x10,  0x20, 	/* 2E890 */
+	0x10,  0x40,  0x11,  0xF8,  0x55,  0x08,  0x55,  0xF8,  0x55,  0x08,  0x55,  0xF8,  0x55,  0x00,  0x55,  0xFF, 	/* 2E8A0 */
+	0x55,  0x00,  0x55,  0xFE,  0x7C,  0x52,  0x03,  0x2A,  0x02,  0xAA,  0x04,  0x82,  0x08,  0x0C,  0x8C,  0x20, 	/* 2E8B0 */
+	0x82,  0x20,  0x82,  0x3F,  0xFE,  0x01,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F, 	/* 2E8C0 */
+	0xF8,  0x08,  0x00,  0x0F,  0xFF,  0x08,  0x00,  0x0F,  0xFE,  0x24,  0x92,  0x22,  0x4A,  0x40,  0x0C,  0x90, 	/* 2E8D0 */
+	0x21,  0x02,  0x21,  0x02,  0x3F,  0xFE,  0x00,  0x80,  0x3C,  0xF8,  0x25,  0x88,  0x2B,  0x50,  0x30,  0x70, 	/* 2E8E0 */
+	0x29,  0x8C,  0x26,  0x7B,  0x24,  0xA0,  0x25,  0xFE,  0x3A,  0x20,  0x20,  0xFC,  0x20,  0x20,  0x27,  0xFF, 	/* 2E8F0 */
+	0x9D,  0x11,  0xD2,  0x10,  0x54,  0x11,  0x49,  0x54,  0x8A,  0x54,  0xFC,  0x55,  0x02,  0x56,  0x01,  0x54, 	/* 2E900 */
+	0xFC,  0x54,  0x84,  0x54,  0x84,  0x54,  0xFC,  0x7C,  0x84,  0x00,  0x44,  0x00,  0x48,  0x07,  0xFF,  0x00, 	/* 2E910 */
+	0x00,  0xA2,  0x10,  0x20,  0x10,  0xFC,  0x10,  0x20,  0x57,  0xFE,  0x54,  0x00,  0x54,  0x84,  0x55,  0xFF, 	/* 2E920 */
+	0x54,  0x84,  0x54,  0xE4,  0x57,  0x9F,  0x54,  0x00,  0x7D,  0xFF,  0x00,  0x48,  0x00,  0x49,  0x01,  0x89, 	/* 2E930 */
+	0x06,  0x07,  0xAC,  0x10,  0x84,  0x10,  0x48,  0x11,  0xFE,  0x54,  0x20,  0x54,  0xFC,  0x54,  0x20,  0x57, 	/* 2E940 */
+	0xFF,  0x54,  0x54,  0x55,  0x92,  0x54,  0x90,  0x57,  0xFF,  0x7C,  0x8A,  0x00,  0xE4,  0x07,  0x85,  0x00, 	/* 2E950 */
+	0x8B,  0x01,  0x91,  0xAE,  0x10,  0x20,  0x10,  0x20,  0x10,  0x50,  0x54,  0x88,  0x55,  0x04,  0x56,  0xFA, 	/* 2E960 */
+	0x54,  0x01,  0x57,  0xDE,  0x56,  0x52,  0x56,  0x52,  0x57,  0xDE,  0x55,  0x08,  0x7D,  0x08,  0x01,  0x8C, 	/* 2E970 */
+	0x02,  0x52,  0x04,  0x22,  0xB7,  0x20,  0x82,  0x20,  0x82,  0x3F,  0xFE,  0x00,  0x00,  0x26,  0x7E,  0x38, 	/* 2E980 */
+	0x04,  0x21,  0x38,  0x1F,  0x08,  0x10,  0xFF,  0x1F,  0x12,  0x24,  0x50,  0x7F,  0xDE,  0x04,  0x50,  0x0A, 	/* 2E990 */
+	0x70,  0x12,  0x98,  0x61,  0x07,  0xBA,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x14,  0x04,  0x0C,  0xFF, 	/* 2E9A0 */
+	0x0A,  0x10,  0x11,  0x20,  0x3E,  0x7E,  0x40,  0x42,  0x3F,  0x7E,  0x09,  0x42,  0x09,  0x7E,  0x09,  0x42, 	/* 2E9B0 */
+	0x0E,  0x7E,  0x08,  0x26,  0x09,  0xC1,  0xBC,  0x10,  0x60,  0x11,  0xA6,  0x11,  0x3A,  0x55,  0x22,  0x55, 	/* 2E9C0 */
+	0xA6,  0x55,  0x3A,  0x55,  0x0A,  0x55,  0xAE,  0x55,  0x2A,  0x55,  0x2A,  0x55,  0x2A,  0x57,  0xFF,  0x7C, 	/* 2E9D0 */
+	0x00,  0x00,  0x88,  0x03,  0x06,  0x0C,  0x01,  0xBD,  0x20,  0x82,  0x20,  0x82,  0x3F,  0xFE,  0x00,  0x00, 	/* 2E9E0 */
+	0x4B,  0xCA,  0x28,  0x09,  0x17,  0xE8,  0x30,  0x3F,  0x4B,  0xC8,  0x08,  0x08,  0x1B,  0xCC,  0x28,  0x0C, 	/* 2E9F0 */
+	0x4B,  0xD4,  0x0A,  0x52,  0x6B,  0xE2,  0x10,  0x41,  0x89,  0x10,  0x78,  0x10,  0x90,  0x13,  0xFE,  0x55, 	/* 2EA00 */
+	0x02,  0x55,  0xFE,  0x54,  0x99,  0x54,  0xEE,  0x54,  0x89,  0x55,  0xF7,  0x54,  0x38,  0x55,  0xFE,  0x7D, 	/* 2EA10 */
+	0x12,  0x01,  0xFE,  0x00,  0x34,  0x00,  0xD1,  0x07,  0x0F,  0x8C,  0x10,  0x42,  0x10,  0x42,  0x1F,  0xFE, 	/* 2EA20 */
+	0x05,  0x08,  0x1F,  0xFF,  0x17,  0x90,  0x12,  0x10,  0x1F,  0xDF,  0x14,  0xA4,  0x17,  0xA4,  0x14,  0xD4, 	/* 2EA30 */
+	0x17,  0x88,  0x14,  0x88,  0x27,  0x94,  0x2C,  0xA2,  0x40,  0xC1,  0x8D,  0x20,  0x82,  0x20,  0x82,  0x3F, 	/* 2EA40 */
+	0xFE,  0x02,  0x10,  0x3C,  0x20,  0x08,  0xFE,  0x7F,  0x92,  0x1C,  0xFE,  0x2A,  0x92,  0x49,  0xFE,  0x7F, 	/* 2EA50 */
+	0x34,  0x14,  0x34,  0x34,  0x5A,  0x08,  0x5F,  0x14,  0x91,  0x63,  0x0F,  0x92,  0x11,  0xC4,  0x10,  0x04, 	/* 2EA60 */
+	0x6F,  0xFA,  0x28,  0x0A,  0x11,  0xC4,  0x28,  0x0A,  0x7D,  0xDF,  0x10,  0x04,  0x59,  0xD6,  0x55,  0x55, 	/* 2EA70 */
+	0x11,  0xE4,  0x00,  0x80,  0x20,  0x82,  0x20,  0x82,  0x3F,  0xFE,  0x00,  0x00,  0x93,  0x20,  0x82,  0x20, 	/* 2EA80 */
+	0x82,  0x3F,  0xFE,  0x26,  0x00,  0x38,  0xFF,  0x21,  0x10,  0x5F,  0x7E,  0x52,  0x42,  0x5E,  0x7E,  0x52, 	/* 2EA90 */
+	0x42,  0x5E,  0x7E,  0x52,  0x42,  0x5E,  0x7E,  0x7F,  0x14,  0x22,  0x62,  0x41,  0x81,  0x96,  0x08,  0x42, 	/* 2EAA0 */
+	0x0F,  0xFE,  0x00,  0x00,  0x07,  0xBC,  0x04,  0xA4,  0x1F,  0xFF,  0x10,  0x10,  0x17,  0xD0,  0x11,  0x1F, 	/* 2EAB0 */
+	0x1F,  0xE4,  0x14,  0xA4,  0x17,  0xD4,  0x14,  0x88,  0x27,  0x94,  0x2C,  0xA2,  0x40,  0xC1,  0x9B,  0x04, 	/* 2EAC0 */
+	0x21,  0x04,  0x21,  0x08,  0x42,  0x08,  0x42,  0x10,  0x84,  0x10,  0x84,  0x21,  0x08,  0x42,  0x10,  0x42, 	/* 2EAD0 */
+	0x10,  0x21,  0x08,  0x10,  0x84,  0x10,  0x84,  0x08,  0x42,  0x08,  0x42,  0x04,  0x21,  0x04,  0x21,  0x9D, 	/* 2EAE0 */
+	0x00,  0x04,  0x10,  0x04,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84, 	/* 2EAF0 */
+	0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x20,  0x04,  0x20,  0x04,  0x40,  0x04,  0x00,  0x04, 	/* 2EB00 */
+	0x9E,  0x08,  0x04,  0x08,  0x84,  0x08,  0x84,  0x08,  0x84,  0x08,  0x84,  0x2C,  0xA4,  0x2A,  0x94,  0x2A, 	/* 2EB10 */
+	0x94,  0x2A,  0x94,  0x48,  0x84,  0x08,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x20,  0x04,  0x40, 	/* 2EB20 */
+	0x04,  0xA1,  0x00,  0x00,  0x20,  0x92,  0x10,  0x92,  0x11,  0x24,  0x01,  0x24,  0x02,  0x48,  0x04,  0x90, 	/* 2EB30 */
+	0x7C,  0x90,  0x0A,  0x48,  0x09,  0x24,  0x09,  0x24,  0x08,  0x92,  0x14,  0x92,  0x12,  0x00,  0x21,  0x80, 	/* 2EB40 */
+	0x40,  0x7F,  0xA3,  0x09,  0x08,  0x04,  0x88,  0x04,  0x90,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x08, 	/* 2EB50 */
+	0x88,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x80,  0x7F,  0xFE,  0x01,  0xC0,  0x02,  0xA0,  0x0C,  0x98,  0x30, 	/* 2EB60 */
+	0x86,  0x00,  0x80,  0xA5,  0x00,  0x00,  0x00,  0x00,  0x3F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80, 	/* 2EB70 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF, 	/* 2EB80 */
+	0x00,  0x00,  0x00,  0x00,  0xA6,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x01,  0x00,  0x02, 	/* 2EB90 */
+	0x00,  0x02,  0x00,  0x02,  0x00,  0x07,  0xFC,  0x04,  0x40,  0x08,  0x40,  0x10,  0x40,  0x20,  0x40,  0x40, 	/* 2EBA0 */
+	0x40,  0x1F,  0xFF,  0x00,  0x00,  0xA7,  0x00,  0x00,  0x03,  0xFF,  0x7E,  0x20,  0x08,  0x20,  0x08,  0x40, 	/* 2EBB0 */
+	0x08,  0x40,  0x08,  0xFC,  0x08,  0x84,  0x08,  0x04,  0x0E,  0x04,  0x18,  0x04,  0x60,  0x04,  0x00,  0x04, 	/* 2EBC0 */
+	0x00,  0x04,  0x00,  0x08,  0x00,  0x70,  0xA8,  0x00,  0x00,  0x3F,  0xFC,  0x20,  0x00,  0x20,  0x00,  0x20, 	/* 2EBD0 */
+	0x00,  0x3F,  0xF0,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x3F,  0xF0,  0x20,  0x00,  0x20,  0x00,  0x20, 	/* 2EBE0 */
+	0x00,  0x20,  0x00,  0x3F,  0xFC,  0x00,  0x00,  0xAB,  0x00,  0x00,  0x3F,  0xFE,  0x00,  0x80,  0x08,  0x88, 	/* 2EBF0 */
+	0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x0C,  0x8C,  0x14,  0x94,  0x12,  0x92,  0x22,  0xA2,  0x40,  0xC0, 	/* 2EC00 */
+	0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0xAE,  0x04,  0x10,  0x02,  0x20,  0x1F,  0xFE,  0x00, 	/* 2EC10 */
+	0x80,  0x00,  0x80,  0x0F,  0xF8,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x04,  0x00,  0x07,  0xFC,  0x08, 	/* 2EC20 */
+	0x40,  0x08,  0x40,  0x10,  0x40,  0x2F,  0xFF,  0x40,  0x00,  0xB1,  0x00,  0x00,  0x3F,  0xF8,  0x00,  0x08, 	/* 2EC30 */
+	0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x1F,  0xF8,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00, 	/* 2EC40 */
+	0x10,  0x04,  0x10,  0x04,  0x08,  0x04,  0x07,  0xFC,  0x00,  0x00,  0xB2,  0x00,  0x00,  0x7F,  0xFC,  0x00, 	/* 2EC50 */
+	0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x3F,  0xFC,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20, 	/* 2EC60 */
+	0x00,  0x20,  0x02,  0x20,  0x02,  0x10,  0x02,  0x0F,  0xFE,  0x00,  0x00,  0xB3,  0x00,  0x00,  0x3F,  0xF8, 	/* 2EC70 */
+	0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x3F,  0xF8,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00, 	/* 2EC80 */
+	0x20,  0x00,  0x20,  0x00,  0x20,  0x02,  0x10,  0x02,  0x0F,  0xFE,  0x00,  0x00,  0xB4,  0x00,  0x00,  0x3F, 	/* 2EC90 */
+	0xF8,  0x21,  0x08,  0x21,  0x08,  0x21,  0x08,  0x21,  0x08,  0x21,  0x08,  0x3F,  0xF8,  0x20,  0x00,  0x20, 	/* 2ECA0 */
+	0x00,  0x20,  0x00,  0x20,  0x02,  0x20,  0x02,  0x10,  0x02,  0x0F,  0xFE,  0x00,  0x00,  0xB5,  0x00,  0x08, 	/* 2ECB0 */
+	0x00,  0x30,  0x1F,  0xC0,  0x10,  0x00,  0x1F,  0xFF,  0x10,  0x00,  0x17,  0xFC,  0x14,  0x44,  0x14,  0x44, 	/* 2ECC0 */
+	0x14,  0x44,  0x17,  0xFC,  0x14,  0x00,  0x24,  0x02,  0x24,  0x02,  0x42,  0x02,  0x01,  0xFE,  0xB7,  0x02, 	/* 2ECD0 */
+	0x20,  0x02,  0x20,  0x1F,  0xFC,  0x02,  0x20,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x20,  0x04,  0x10,  0x0F, 	/* 2ECE0 */
+	0xF8,  0x10,  0x14,  0x60,  0x13,  0x07,  0xF0,  0x04,  0x00,  0x04,  0x04,  0x04,  0x04,  0x03,  0xFC,  0xBB, 	/* 2ECF0 */
+	0x08,  0x88,  0x04,  0x88,  0x04,  0x90,  0x1F,  0xFE,  0x00,  0x80,  0x01,  0x40,  0x7F,  0xFF,  0x02,  0x20, 	/* 2ED00 */
+	0x07,  0xF0,  0x18,  0x1C,  0x60,  0x13,  0x07,  0xF0,  0x04,  0x00,  0x04,  0x08,  0x04,  0x08,  0x03,  0xF8, 	/* 2ED10 */
+	0xBD,  0x00,  0x00,  0x3E,  0x7C,  0x02,  0x04,  0x3E,  0x7C,  0x20,  0x40,  0x21,  0x42,  0x1F,  0x3E,  0x00, 	/* 2ED20 */
+	0x00,  0x02,  0x20,  0x1F,  0xFC,  0x02,  0x20,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x60,  0x0C,  0x18,  0x30, 	/* 2ED30 */
+	0x04,  0xBE,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x3F,  0xFC,  0x21,  0x04,  0x21,  0x04, 	/* 2ED40 */
+	0x21,  0x04,  0x21,  0x04,  0x21,  0x04,  0x21,  0x04,  0x21,  0x18,  0x21,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 2ED50 */
+	0x01,  0x00,  0x82,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x1F, 	/* 2ED60 */
+	0xFC,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x98,  0x00,  0x80,  0x00, 	/* 2ED70 */
+	0x80,  0x00,  0x80,  0x83,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFF,  0x02,  0x40,  0x02,  0x40, 	/* 2ED80 */
+	0x04,  0x40,  0x07,  0xFC,  0x0C,  0x44,  0x14,  0x44,  0x24,  0x44,  0x44,  0x44,  0x04,  0x44,  0x04,  0x58, 	/* 2ED90 */
+	0x00,  0x40,  0x00,  0x40,  0x86,  0x10,  0x00,  0x10,  0x7C,  0x10,  0x44,  0x7E,  0x44,  0x52,  0x44,  0x52, 	/* 2EDA0 */
+	0x64,  0x52,  0x54,  0x52,  0x54,  0x52,  0x54,  0x52,  0x44,  0x56,  0x44,  0x50,  0x44,  0x10,  0x84,  0x10, 	/* 2EDB0 */
+	0x85,  0x11,  0x05,  0x12,  0x03,  0x8B,  0x00,  0x04,  0x00,  0x38,  0x1F,  0xC0,  0x10,  0x40,  0x1F,  0xFF, 	/* 2EDC0 */
+	0x10,  0x40,  0x10,  0x22,  0x1E,  0x1A,  0x70,  0x86,  0x00,  0x80,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84, 	/* 2EDD0 */
+	0x10,  0x84,  0x10,  0x98,  0x00,  0x80,  0x8C,  0x06,  0x04,  0x01,  0x98,  0x00,  0x60,  0x03,  0xB0,  0x3C, 	/* 2EDE0 */
+	0x88,  0x01,  0x00,  0x7F,  0xFF,  0x02,  0x40,  0x04,  0x40,  0x0F,  0xFE,  0x14,  0x42,  0x24,  0x42,  0x44, 	/* 2EDF0 */
+	0x42,  0x04,  0x42,  0x04,  0x4C,  0x00,  0x40,  0x91,  0x04,  0x00,  0x04,  0x00,  0x7F,  0xFE,  0x09,  0x22, 	/* 2EE00 */
+	0x09,  0x22,  0x11,  0x14,  0x3E,  0x08,  0x04,  0x94,  0x18,  0xE3,  0x60,  0x80,  0x1F,  0xFC,  0x10,  0x84, 	/* 2EE10 */
+	0x10,  0x84,  0x10,  0x84,  0x10,  0x98,  0x00,  0x80,  0x96,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x7E, 	/* 2EE20 */
+	0x20,  0x52,  0x3F,  0x52,  0x20,  0x52,  0x20,  0x52,  0x20,  0x52,  0xFC,  0x52,  0x84,  0x56,  0x84,  0x50, 	/* 2EE30 */
+	0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0xFC,  0x10,  0x00,  0x99,  0x10,  0x10,  0x10,  0x50,  0x10,  0x50, 	/* 2EE40 */
+	0x7E,  0x7E,  0x52,  0x90,  0x52,  0x90,  0x53,  0x10,  0x53,  0xFF,  0x52,  0x10,  0x52,  0x10,  0x56,  0x28, 	/* 2EE50 */
+	0x50,  0x28,  0x10,  0x44,  0x10,  0x84,  0x11,  0x02,  0x12,  0x01,  0x9A,  0x00,  0x00,  0x1F,  0xF8,  0x00, 	/* 2EE60 */
+	0x08,  0x7F,  0xFF,  0x00,  0x08,  0x1F,  0xF8,  0x00,  0x00,  0x7F,  0xFE,  0x41,  0x02,  0x41,  0x02,  0x1F, 	/* 2EE70 */
+	0xF8,  0x11,  0x08,  0x11,  0x08,  0x11,  0x08,  0x11,  0x30,  0x01,  0x00,  0x9B,  0x01,  0x00,  0x02,  0x00, 	/* 2EE80 */
+	0x1F,  0xF8,  0x10,  0x08,  0x1F,  0xF8,  0x10,  0x08,  0x10,  0x08,  0x1F,  0xF8,  0x01,  0x00,  0x3F,  0xFC, 	/* 2EE90 */
+	0x21,  0x04,  0x21,  0x04,  0x21,  0x04,  0x21,  0x18,  0x21,  0x00,  0x01,  0x00,  0x9D,  0x00,  0x80,  0x00, 	/* 2EEA0 */
+	0x80,  0x3F,  0xFE,  0x08,  0x10,  0x04,  0x10,  0x04,  0x20,  0x7F,  0xFE,  0x40,  0x82,  0x40,  0x82,  0x0F, 	/* 2EEB0 */
+	0xF8,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x08,  0xB0,  0x08,  0x80,  0x00,  0x80,  0xA5,  0x08,  0x10, 	/* 2EEC0 */
+	0x10,  0x10,  0x3E,  0x10,  0x22,  0xFE,  0x22,  0x92,  0x22,  0x92,  0x3E,  0x92,  0x20,  0x92,  0x20,  0x92, 	/* 2EED0 */
+	0x3E,  0x92,  0x22,  0x92,  0x22,  0x9C,  0x22,  0x90,  0x3E,  0x90,  0x00,  0x10,  0x00,  0x10,  0xAB,  0x04, 	/* 2EEE0 */
+	0x00,  0x09,  0xFF,  0x3E,  0x10,  0x22,  0x10,  0x22,  0xFE,  0x22,  0x92,  0x3E,  0x92,  0x20,  0x92,  0x20, 	/* 2EEF0 */
+	0x92,  0x3E,  0x92,  0x22,  0x92,  0x22,  0x92,  0x22,  0x9C,  0x3E,  0x90,  0x00,  0x10,  0x00,  0x10,  0xAD, 	/* 2EF00 */
+	0x00,  0x40,  0x00,  0x40,  0x1F,  0xFF,  0x11,  0x10,  0x11,  0x10,  0x1F,  0xFE,  0x11,  0x10,  0x11,  0x10, 	/* 2EF10 */
+	0x11,  0xF0,  0x10,  0x40,  0x17,  0xFC,  0x14,  0x44,  0x24,  0x44,  0x24,  0x44,  0x44,  0x58,  0x00,  0x40, 	/* 2EF20 */
+	0xAF,  0x08,  0x88,  0x08,  0x88,  0x7F,  0xFF,  0x08,  0x88,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x00,  0x7F, 	/* 2EF30 */
+	0xFE,  0x40,  0x82,  0x4F,  0xFA,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x08,  0xB0,  0x08,  0x80,  0x00, 	/* 2EF40 */
+	0x80,  0xB0,  0x08,  0x00,  0x09,  0xFC,  0x08,  0x04,  0x28,  0xFC,  0x28,  0x04,  0x29,  0xFC,  0x28,  0x00, 	/* 2EF50 */
+	0x2B,  0xFF,  0x2A,  0x21,  0x4A,  0x21,  0x09,  0xFC,  0x09,  0x24,  0x09,  0x24,  0x11,  0x24,  0x11,  0x2C, 	/* 2EF60 */
+	0x20,  0x20,  0xB3,  0x10,  0x00,  0x10,  0x7E,  0x10,  0x40,  0x7E,  0x7C,  0x52,  0x40,  0x52,  0x7C,  0x52, 	/* 2EF70 */
+	0x40,  0x52,  0x40,  0x53,  0xFF,  0x52,  0x52,  0x56,  0x54,  0x50,  0x48,  0x10,  0x48,  0x10,  0x74,  0x10, 	/* 2EF80 */
+	0xC2,  0x11,  0x01,  0xB6,  0x0A,  0xA0,  0x0A,  0xA0,  0x7F,  0xFF,  0x0A,  0xA0,  0x0A,  0xA4,  0x13,  0x9C, 	/* 2EF90 */
+	0x20,  0x00,  0x7F,  0xFE,  0x41,  0x02,  0x41,  0x02,  0x1F,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x11,  0x30, 	/* 2EFA0 */
+	0x11,  0x00,  0x01,  0x00,  0xB7,  0x10,  0x24,  0x10,  0x24,  0x10,  0x48,  0x7E,  0x7F,  0x52,  0xC8,  0x52, 	/* 2EFB0 */
+	0xC8,  0x53,  0x48,  0x52,  0x7E,  0x52,  0x48,  0x52,  0x48,  0x56,  0x7E,  0x50,  0x48,  0x10,  0x48,  0x10, 	/* 2EFC0 */
+	0x48,  0x10,  0x7F,  0x10,  0x00,  0xB8,  0x11,  0x08,  0x09,  0x08,  0x09,  0x10,  0x7F,  0xFE,  0x40,  0x02, 	/* 2EFD0 */
+	0x4F,  0xF2,  0x48,  0x12,  0x08,  0x10,  0x0F,  0xF0,  0x01,  0x00,  0x1F,  0xF8,  0x11,  0x08,  0x11,  0x08, 	/* 2EFE0 */
+	0x11,  0x08,  0x11,  0x30,  0x01,  0x00,  0xBD,  0x10,  0x00,  0x11,  0xFE,  0x11,  0x02,  0x7F,  0xFE,  0x53, 	/* 2EFF0 */
+	0x02,  0x53,  0xFE,  0x52,  0x00,  0x52,  0xFC,  0x52,  0x84,  0x52,  0xFC,  0x5C,  0x84,  0x50,  0xFC,  0x50, 	/* 2F000 */
+	0x84,  0x10,  0x84,  0x10,  0xFC,  0x10,  0x00,  0x80,  0x10,  0x20,  0x10,  0x20,  0x10,  0x3F,  0x7E,  0x20, 	/* 2F010 */
+	0x52,  0xFC,  0x52,  0x84,  0x52,  0x84,  0x52,  0xFC,  0x52,  0x84,  0x52,  0xFC,  0x56,  0x84,  0x50,  0x84, 	/* 2F020 */
+	0x10,  0xFC,  0x10,  0x48,  0x10,  0x84,  0x13,  0x02,  0x83,  0x10,  0x20,  0x11,  0xFC,  0x10,  0x44,  0x7C, 	/* 2F030 */
+	0x44,  0x57,  0xFF,  0x54,  0x00,  0x54,  0xFC,  0x54,  0x84,  0x54,  0xFC,  0x54,  0x08,  0x5D,  0xFE,  0x10, 	/* 2F040 */
+	0x88,  0x10,  0x88,  0x13,  0xFF,  0x10,  0x08,  0x10,  0x08,  0x84,  0x10,  0x00,  0x11,  0xFE,  0x11,  0x02, 	/* 2F050 */
+	0x7D,  0x02,  0x55,  0xFE,  0x55,  0x00,  0x55,  0xFF,  0x55,  0x28,  0x55,  0x44,  0x55,  0xFA,  0x5D,  0x10, 	/* 2F060 */
+	0x52,  0xFE,  0x12,  0x10,  0x14,  0x10,  0x19,  0xFF,  0x10,  0x00,  0x85,  0x10,  0x00,  0x11,  0xFE,  0x10, 	/* 2F070 */
+	0x00,  0x7E,  0xFC,  0x52,  0x84,  0x52,  0x84,  0x52,  0xFC,  0x52,  0x00,  0x53,  0xFE,  0x53,  0x22,  0x53, 	/* 2F080 */
+	0x22,  0x57,  0xFE,  0x51,  0x22,  0x11,  0x22,  0x11,  0xFE,  0x10,  0x00,  0x87,  0x04,  0x04,  0x3F,  0x04, 	/* 2F090 */
+	0x04,  0x7F,  0x7F,  0x84,  0x04,  0x24,  0x3F,  0x14,  0x04,  0x14,  0x07,  0x84,  0x79,  0x0C,  0x01,  0x00, 	/* 2F0A0 */
+	0x1F,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x11,  0x18,  0x11,  0x00,  0x01,  0x00,  0x8C,  0x10,  0x00,  0x10, 	/* 2F0B0 */
+	0xFC,  0x10,  0x84,  0x7E,  0xFC,  0x52,  0x84,  0x52,  0xFC,  0x52,  0x92,  0x52,  0x52,  0x52,  0x54,  0x53, 	/* 2F0C0 */
+	0xFF,  0x56,  0x48,  0x50,  0x48,  0x50,  0x48,  0x10,  0x89,  0x11,  0x09,  0x16,  0x07,  0x8E,  0x10,  0x00, 	/* 2F0D0 */
+	0x11,  0xFF,  0x11,  0x01,  0x7D,  0x7D,  0x54,  0x44,  0x54,  0x44,  0x54,  0x7C,  0x54,  0x44,  0x54,  0x44, 	/* 2F0E0 */
+	0x54,  0x7C,  0x5C,  0x10,  0x53,  0xFF,  0x10,  0x00,  0x10,  0x44,  0x10,  0x82,  0x13,  0x02,  0x94,  0x10, 	/* 2F0F0 */
+	0x00,  0x10,  0xFE,  0x10,  0x82,  0x7C,  0xFE,  0x54,  0x82,  0x54,  0xFE,  0x54,  0x00,  0x55,  0xFF,  0x55, 	/* 2F100 */
+	0x29,  0x55,  0xFF,  0x5C,  0x00,  0x51,  0xFE,  0x10,  0x64,  0x10,  0x18,  0x10,  0x6C,  0x13,  0x83,  0x95, 	/* 2F110 */
+	0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x07,  0xF8,  0x04,  0x08,  0x07,  0xF8,  0x04,  0x08,  0x07,  0xF8, 	/* 2F120 */
+	0x01,  0x00,  0x7F,  0xFF,  0x04,  0x90,  0x0F,  0xFC,  0x14,  0x8B,  0x64,  0x88,  0x04,  0xB0,  0x00,  0x80, 	/* 2F130 */
+	0x97,  0x10,  0x00,  0x11,  0xFE,  0x11,  0x1A,  0x7D,  0x16,  0x55,  0xFE,  0x55,  0x12,  0x55,  0x76,  0x55, 	/* 2F140 */
+	0x56,  0x55,  0x76,  0x55,  0x1A,  0x5D,  0xEA,  0x11,  0x1E,  0x11,  0x26,  0x11,  0x42,  0x11,  0xFE,  0x10, 	/* 2F150 */
+	0x00,  0x9F,  0x10,  0x88,  0x10,  0x8C,  0x13,  0xFA,  0x7D,  0x2A,  0x54,  0xA8,  0x54,  0xC8,  0x57,  0xFF, 	/* 2F160 */
+	0x54,  0x08,  0x55,  0xEA,  0x55,  0x2A,  0x5D,  0xEA,  0x51,  0x24,  0x11,  0x25,  0x11,  0xEB,  0x10,  0x13, 	/* 2F170 */
+	0x10,  0x21,  0xA1,  0x10,  0x04,  0x10,  0x18,  0x11,  0xE4,  0x7D,  0x24,  0x54,  0xA8,  0x57,  0xFF,  0x54, 	/* 2F180 */
+	0x70,  0x54,  0xA8,  0x55,  0x24,  0x57,  0xFE,  0x5D,  0x25,  0x51,  0xFC,  0x11,  0x24,  0x11,  0x24,  0x11, 	/* 2F190 */
+	0xFC,  0x10,  0x00,  0xA2,  0x10,  0x20,  0x13,  0xFE,  0x10,  0x88,  0x7C,  0x50,  0x57,  0xFF,  0x54,  0x00, 	/* 2F1A0 */
+	0x55,  0xFC,  0x55,  0x24,  0x55,  0xFC,  0x55,  0x24,  0x5D,  0xFC,  0x10,  0x20,  0x11,  0xFE,  0x10,  0x20, 	/* 2F1B0 */
+	0x17,  0xFF,  0x10,  0x00,  0xA3,  0x04,  0x10,  0x25,  0x10,  0x16,  0x1F,  0x3F,  0xA2,  0x24,  0xB2,  0x2E, 	/* 2F1C0 */
+	0xCC,  0x35,  0x84,  0x24,  0x9A,  0x25,  0xE1,  0x00,  0x80,  0x0F,  0xFC,  0x08,  0x84,  0x08,  0x84,  0x08, 	/* 2F1D0 */
+	0x98,  0x08,  0x80,  0x00,  0x80,  0xA4,  0x08,  0x20,  0x2A,  0x20,  0x49,  0x3F,  0x7F,  0x44,  0x41,  0x64, 	/* 2F1E0 */
+	0x5D,  0x94,  0x55,  0x08,  0x5D,  0x14,  0x43,  0x62,  0x00,  0x81,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84, 	/* 2F1F0 */
+	0x10,  0x84,  0x10,  0x98,  0x00,  0x80,  0xB2,  0x00,  0x00,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 2F200 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 2F210 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0xB3,  0x00,  0x00,  0x1F,  0xFC,  0x00,  0x80,  0x08,  0x88, 	/* 2F220 */
+	0x04,  0x88,  0x04,  0x90,  0x04,  0xA0,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80, 	/* 2F230 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0xB4,  0x04,  0x00,  0x04,  0x00,  0x0F,  0xFE,  0x08, 	/* 2F240 */
+	0x40,  0x10,  0x40,  0x20,  0x40,  0x4F,  0xFC,  0x08,  0x40,  0x08,  0x40,  0x08,  0x40,  0x08,  0x40,  0x7F, 	/* 2F250 */
+	0xFF,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0xB5,  0x00,  0x00,  0x3E,  0x3E,  0x08,  0x08, 	/* 2F260 */
+	0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x7F,  0x7F,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08, 	/* 2F270 */
+	0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0xB6,  0x08,  0x10,  0x04,  0x10,  0x04, 	/* 2F280 */
+	0x20,  0x3F,  0xFC,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x04, 	/* 2F290 */
+	0x20,  0x04,  0x20,  0x08,  0x20,  0x08,  0x20,  0x10,  0x20,  0x20,  0x20,  0xB8,  0x00,  0x80,  0x00,  0x80, 	/* 2F2A0 */
+	0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x04,  0x10,  0x02,  0x10,  0x02,  0x20,  0x3F,  0xFE, 	/* 2F2B0 */
+	0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0xB9,  0x08,  0x10,  0x08, 	/* 2F2C0 */
+	0x10,  0x7F,  0x28,  0x08,  0x28,  0x3E,  0x44,  0x22,  0x82,  0x23,  0x7D,  0x3E,  0x10,  0x22,  0x10,  0x22, 	/* 2F2D0 */
+	0x10,  0x3F,  0xFF,  0x08,  0x10,  0x7F,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0xBA,  0x00,  0x80, 	/* 2F2E0 */
+	0x00,  0x80,  0x00,  0x80,  0x01,  0x00,  0x01,  0x10,  0x02,  0x10,  0x1C,  0x20,  0x02,  0x20,  0x01,  0x40, 	/* 2F2F0 */
+	0x01,  0x80,  0x00,  0x90,  0x01,  0x08,  0x02,  0x04,  0x04,  0x7C,  0x7F,  0x82,  0x00,  0x02,  0xBB,  0x04, 	/* 2F300 */
+	0x00,  0x04,  0x7E,  0x04,  0x02,  0x08,  0x02,  0x09,  0x02,  0x71,  0x02,  0x11,  0x02,  0x0A,  0x02,  0x06, 	/* 2F310 */
+	0x02,  0x04,  0x02,  0x05,  0x02,  0x08,  0x82,  0x08,  0x82,  0x7F,  0x42,  0x00,  0x44,  0x00,  0x18,  0xBC, 	/* 2F320 */
+	0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x08,  0x20,  0x0A,  0xFE,  0x12,  0x22,  0x62,  0x22,  0x14,  0x22, 	/* 2F330 */
+	0x0C,  0x22,  0x06,  0x22,  0x0A,  0x22,  0x09,  0x42,  0x13,  0x42,  0x1C,  0x82,  0x61,  0x04,  0x02,  0x18, 	/* 2F340 */
+	0xBD,  0x00,  0x80,  0x24,  0x92,  0x24,  0x92,  0x24,  0x92,  0x25,  0x96,  0x39,  0xE6,  0x2E,  0x9A,  0x22, 	/* 2F350 */
+	0x8A,  0x24,  0x92,  0x26,  0x9A,  0x2A,  0xAA,  0x2F,  0xBE,  0x39,  0xE6,  0x21,  0x86,  0x3F,  0xFE,  0x20, 	/* 2F360 */
+	0x02,  0xBE,  0x08,  0x90,  0x08,  0x90,  0x32,  0xE4,  0x0A,  0x94,  0x04,  0x88,  0x0A,  0x94,  0x0E,  0x9C, 	/* 2F370 */
+	0x31,  0xF2,  0x00,  0x88,  0x7F,  0xFF,  0x04,  0x40,  0x06,  0x44,  0x09,  0x28,  0x08,  0x32,  0x10,  0xCA, 	/* 2F380 */
+	0x23,  0x06,  0xBF,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFE,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10, 	/* 2F390 */
+	0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x20,  0x00,  0x20,  0x00,  0x40, 	/* 2F3A0 */
+	0x00,  0x00,  0x00,  0x81,  0x00,  0x40,  0x00,  0x40,  0x1F,  0xFF,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00, 	/* 2F3B0 */
+	0x17,  0xFE,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x20,  0x20,  0x20,  0x20, 	/* 2F3C0 */
+	0x40,  0x20,  0x00,  0x60,  0x83,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0x1F,  0xFF,  0x10,  0x00,  0x10, 	/* 2F3D0 */
+	0x80,  0x10,  0x80,  0x10,  0x80,  0x10,  0x80,  0x10,  0x80,  0x11,  0x10,  0x11,  0x08,  0x11,  0x04,  0x22, 	/* 2F3E0 */
+	0x7C,  0x2F,  0x82,  0x40,  0x02,  0x84,  0x00,  0x40,  0x00,  0x40,  0x1F,  0xFF,  0x10,  0x00,  0x10,  0x40, 	/* 2F3F0 */
+	0x10,  0x40,  0x10,  0x40,  0x10,  0x40,  0x17,  0xFC,  0x10,  0x40,  0x10,  0x40,  0x10,  0x40,  0x20,  0x40, 	/* 2F400 */
+	0x20,  0x40,  0x5F,  0xFF,  0x00,  0x00,  0x87,  0x00,  0x40,  0x00,  0x40,  0x1F,  0xFF,  0x10,  0x00,  0x12, 	/* 2F410 */
+	0x20,  0x12,  0x20,  0x12,  0x22,  0x12,  0x24,  0x13,  0xB8,  0x12,  0x20,  0x12,  0x20,  0x12,  0x20,  0x22, 	/* 2F420 */
+	0x22,  0x22,  0x62,  0x43,  0xA2,  0x0E,  0x1E,  0x8A,  0x00,  0x40,  0x00,  0x40,  0x1F,  0xFF,  0x10,  0x40, 	/* 2F430 */
+	0x10,  0x40,  0x10,  0x40,  0x1F,  0xFF,  0x10,  0xE0,  0x10,  0xE0,  0x11,  0x50,  0x11,  0x50,  0x12,  0x48, 	/* 2F440 */
+	0x24,  0x44,  0x28,  0x42,  0x40,  0x40,  0x00,  0x40,  0x8F,  0x00,  0x40,  0x00,  0x40,  0x1F,  0xFF,  0x10, 	/* 2F450 */
+	0x00,  0x17,  0xF8,  0x10,  0x10,  0x11,  0xA0,  0x10,  0x40,  0x1F,  0xFE,  0x10,  0x44,  0x10,  0x48,  0x10, 	/* 2F460 */
+	0x50,  0x20,  0x40,  0x20,  0x40,  0x40,  0x40,  0x00,  0xC0,  0x95,  0x00,  0x40,  0x00,  0x40,  0x1F,  0xFF, 	/* 2F470 */
+	0x10,  0x04,  0x10,  0x18,  0x13,  0xE0,  0x12,  0x20,  0x12,  0x20,  0x13,  0xFF,  0x12,  0x10,  0x12,  0x10, 	/* 2F480 */
+	0x13,  0x88,  0x2C,  0x08,  0x20,  0x05,  0x47,  0xE3,  0x00,  0x01,  0x96,  0x00,  0x80,  0x00,  0x80,  0x1F, 	/* 2F490 */
+	0xFF,  0x12,  0x00,  0x12,  0x00,  0x13,  0xFC,  0x14,  0x04,  0x17,  0xE4,  0x18,  0x24,  0x10,  0x24,  0x17, 	/* 2F4A0 */
+	0xE4,  0x14,  0x18,  0x24,  0x02,  0x24,  0x02,  0x42,  0x02,  0x01,  0xFE,  0x97,  0x00,  0x40,  0x00,  0x40, 	/* 2F4B0 */
+	0x1F,  0xFF,  0x10,  0x00,  0x10,  0x40,  0x10,  0x40,  0x10,  0x7E,  0x10,  0x40,  0x10,  0x40,  0x10,  0x40, 	/* 2F4C0 */
+	0x17,  0xFC,  0x14,  0x04,  0x14,  0x04,  0x24,  0x04,  0x27,  0xFC,  0x40,  0x00,  0x9A,  0x00,  0x80,  0x00, 	/* 2F4D0 */
+	0x80,  0x1F,  0xFF,  0x10,  0x40,  0x17,  0xFC,  0x10,  0x44,  0x10,  0x44,  0x1F,  0xFF,  0x10,  0x44,  0x17, 	/* 2F4E0 */
+	0xFC,  0x10,  0x40,  0x10,  0x40,  0x20,  0xA0,  0x21,  0x10,  0x46,  0x0C,  0x18,  0x03,  0x9C,  0x00,  0x40, 	/* 2F4F0 */
+	0x00,  0x40,  0x1F,  0xFE,  0x10,  0x00,  0x11,  0x08,  0x11,  0x08,  0x11,  0xFF,  0x12,  0x08,  0x12,  0x88, 	/* 2F500 */
+	0x16,  0x48,  0x1A,  0x48,  0x12,  0x08,  0x22,  0x08,  0x22,  0x08,  0x42,  0x08,  0x02,  0x18,  0xA0,  0x00, 	/* 2F510 */
+	0x40,  0x00,  0x40,  0x1F,  0xFF,  0x10,  0x00,  0x12,  0x08,  0x11,  0x10,  0x17,  0xFE,  0x10,  0x40,  0x10, 	/* 2F520 */
+	0x40,  0x13,  0xFC,  0x10,  0x40,  0x10,  0x40,  0x2F,  0xFF,  0x20,  0x40,  0x40,  0x40,  0x00,  0x40,  0xA6, 	/* 2F530 */
+	0x00,  0x40,  0x00,  0x40,  0x1F,  0xFE,  0x11,  0x10,  0x11,  0x10,  0x1F,  0xFE,  0x11,  0x10,  0x11,  0xF0, 	/* 2F540 */
+	0x10,  0x00,  0x17,  0xF8,  0x11,  0x08,  0x10,  0x90,  0x10,  0x60,  0x20,  0xA0,  0x23,  0x18,  0x5C,  0x06, 	/* 2F550 */
+	0xA7,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFF,  0x10,  0x00,  0x12,  0x48,  0x12,  0x48,  0x12,  0x48,  0x15, 	/* 2F560 */
+	0x54,  0x15,  0x54,  0x18,  0xE2,  0x17,  0xFC,  0x20,  0x40,  0x20,  0x40,  0x40,  0x40,  0x1F,  0xFF,  0x00, 	/* 2F570 */
+	0x00,  0xAB,  0x00,  0x40,  0x1F,  0xFF,  0x10,  0x40,  0x10,  0x40,  0x1F,  0xFE,  0x10,  0x40,  0x17,  0xFC, 	/* 2F580 */
+	0x14,  0x44,  0x17,  0xFC,  0x14,  0x44,  0x14,  0x44,  0x27,  0xFC,  0x20,  0x40,  0x3F,  0xFF,  0x40,  0x40, 	/* 2F590 */
+	0x00,  0x40,  0xAD,  0x00,  0x40,  0x00,  0x40,  0x1F,  0xFF,  0x10,  0x00,  0x10,  0x02,  0x1F,  0x7C,  0x11, 	/* 2F5A0 */
+	0x08,  0x12,  0x08,  0x17,  0x7F,  0x11,  0x08,  0x15,  0x08,  0x15,  0x08,  0x22,  0x3E,  0x25,  0x00,  0x48, 	/* 2F5B0 */
+	0xC0,  0x10,  0x3F,  0xB5,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFE,  0x10,  0x40,  0x1F,  0xFE,  0x10,  0xA0, 	/* 2F5C0 */
+	0x11,  0x10,  0x13,  0xFC,  0x1E,  0x4B,  0x12,  0x48,  0x13,  0xF8,  0x12,  0x48,  0x22,  0x48,  0x23,  0xFA, 	/* 2F5D0 */
+	0x40,  0x42,  0x00,  0x3E,  0xB6,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFE,  0x10,  0x00,  0x11,  0x10,  0x11, 	/* 2F5E0 */
+	0x10,  0x1F,  0xFF,  0x11,  0x10,  0x11,  0x10,  0x11,  0x10,  0x11,  0xF0,  0x20,  0x00,  0x2A,  0x48,  0x49, 	/* 2F5F0 */
+	0x24,  0x11,  0x22,  0x20,  0x02,  0xB7,  0x00,  0x40,  0x00,  0x40,  0x1F,  0xFF,  0x10,  0x40,  0x17,  0xFC, 	/* 2F600 */
+	0x10,  0x44,  0x1F,  0xFF,  0x10,  0x44,  0x17,  0xFC,  0x14,  0x42,  0x12,  0x44,  0x12,  0xE8,  0x21,  0x50, 	/* 2F610 */
+	0x26,  0x4C,  0x58,  0x43,  0x00,  0xC0,  0xB8,  0x00,  0x80,  0x1F,  0xFF,  0x10,  0x40,  0x17,  0xFC,  0x10, 	/* 2F620 */
+	0x44,  0x1F,  0xFF,  0x10,  0x44,  0x17,  0xFC,  0x10,  0x40,  0x17,  0xFC,  0x14,  0x44,  0x17,  0xFC,  0x24, 	/* 2F630 */
+	0x44,  0x27,  0xFC,  0x44,  0x44,  0x04,  0x4C,  0x81,  0x00,  0x40,  0x00,  0x40,  0x1F,  0xFF,  0x10,  0x00, 	/* 2F640 */
+	0x17,  0xC2,  0x14,  0x52,  0x14,  0x52,  0x17,  0xD2,  0x14,  0x52,  0x17,  0xD2,  0x14,  0x52,  0x14,  0x52, 	/* 2F650 */
+	0x27,  0xD2,  0x22,  0x82,  0x44,  0x42,  0x08,  0x06,  0x82,  0x00,  0x40,  0x00,  0x40,  0x1F,  0xFF,  0x12, 	/* 2F660 */
+	0x00,  0x12,  0x00,  0x12,  0x3E,  0x1F,  0xE2,  0x12,  0x22,  0x13,  0x3E,  0x16,  0xA2,  0x16,  0xA2,  0x1A, 	/* 2F670 */
+	0x3E,  0x2A,  0x22,  0x22,  0x22,  0x42,  0x3E,  0x02,  0x00,  0x83,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFF, 	/* 2F680 */
+	0x10,  0x20,  0x17,  0x94,  0x10,  0x99,  0x15,  0x0A,  0x12,  0x04,  0x17,  0xFB,  0x18,  0x90,  0x10,  0x90, 	/* 2F690 */
+	0x17,  0xFF,  0x20,  0x90,  0x21,  0x11,  0x46,  0x11,  0x18,  0x0F,  0x88,  0x00,  0x40,  0x00,  0x40,  0x1F, 	/* 2F6A0 */
+	0xFF,  0x10,  0x00,  0x1F,  0xFF,  0x10,  0x40,  0x13,  0xF8,  0x12,  0x08,  0x13,  0xF8,  0x12,  0x08,  0x13, 	/* 2F6B0 */
+	0xF8,  0x10,  0x80,  0x21,  0xF0,  0x27,  0x10,  0x40,  0xE0,  0x1F,  0x1F,  0x89,  0x00,  0x80,  0x1F,  0xFF, 	/* 2F6C0 */
+	0x12,  0x08,  0x11,  0x10,  0x1F,  0xFE,  0x11,  0x20,  0x17,  0xFC,  0x11,  0x24,  0x1F,  0xFF,  0x11,  0x24, 	/* 2F6D0 */
+	0x17,  0xFC,  0x13,  0x30,  0x25,  0x28,  0x29,  0x24,  0x51,  0x22,  0x01,  0x20,  0x8A,  0x00,  0x40,  0x00, 	/* 2F6E0 */
+	0x40,  0x1F,  0xFF,  0x11,  0x00,  0x11,  0x1E,  0x17,  0xD2,  0x14,  0x54,  0x17,  0xD8,  0x14,  0x54,  0x17, 	/* 2F6F0 */
+	0xD2,  0x14,  0x11,  0x15,  0x11,  0x24,  0x99,  0x27,  0xD6,  0x58,  0x30,  0x00,  0x10,  0x8F,  0x00,  0x40, 	/* 2F700 */
+	0x00,  0x40,  0x1F,  0xFF,  0x12,  0x00,  0x17,  0xBC,  0x14,  0xA4,  0x17,  0xA5,  0x14,  0xA3,  0x14,  0xC0, 	/* 2F710 */
+	0x17,  0xBC,  0x10,  0x04,  0x14,  0xA4,  0x27,  0x18,  0x24,  0x18,  0x44,  0xA4,  0x03,  0xC3,  0x90,  0x00, 	/* 2F720 */
+	0x40,  0x00,  0x40,  0x1F,  0xFF,  0x12,  0x00,  0x17,  0xFE,  0x14,  0xA4,  0x17,  0xA4,  0x14,  0xA4,  0x14, 	/* 2F730 */
+	0xBF,  0x17,  0x88,  0x10,  0x08,  0x14,  0x8C,  0x27,  0x14,  0x24,  0x15,  0x44,  0xA5,  0x03,  0xC3,  0x93, 	/* 2F740 */
+	0x00,  0x80,  0x00,  0x80,  0x1F,  0xFF,  0x11,  0x00,  0x1F,  0xFE,  0x10,  0x12,  0x17,  0x94,  0x14,  0x98, 	/* 2F750 */
+	0x17,  0x94,  0x10,  0x12,  0x17,  0x92,  0x11,  0x12,  0x21,  0xD2,  0x2F,  0x1C,  0x41,  0x10,  0x03,  0x10, 	/* 2F760 */
+	0x96,  0x00,  0x40,  0x00,  0x40,  0x1F,  0xFF,  0x10,  0x00,  0x1F,  0xBE,  0x12,  0x8A,  0x15,  0x96,  0x12, 	/* 2F770 */
+	0xCA,  0x14,  0xA2,  0x13,  0x58,  0x1C,  0x97,  0x13,  0x20,  0x20,  0xC4,  0x23,  0x18,  0x40,  0x60,  0x07, 	/* 2F780 */
+	0x80,  0x9A,  0x00,  0x40,  0x00,  0x40,  0x1F,  0xFF,  0x11,  0x00,  0x1F,  0xE4,  0x11,  0x04,  0x17,  0xFF, 	/* 2F790 */
+	0x10,  0x04,  0x17,  0xC4,  0x14,  0xA4,  0x17,  0xA4,  0x10,  0x84,  0x24,  0x84,  0x23,  0x04,  0x43,  0xC4, 	/* 2F7A0 */
+	0x1C,  0x0C,  0x9B,  0x00,  0x40,  0x00,  0x40,  0x1F,  0xFF,  0x10,  0x00,  0x13,  0xFC,  0x12,  0x44,  0x13, 	/* 2F7B0 */
+	0xFC,  0x12,  0x44,  0x13,  0xFC,  0x10,  0x40,  0x1F,  0xFF,  0x11,  0x12,  0x26,  0x4E,  0x3B,  0xF8,  0x40, 	/* 2F7C0 */
+	0x40,  0x1F,  0xFF,  0x9D,  0x00,  0x40,  0x00,  0x40,  0x1F,  0xFF,  0x10,  0x00,  0x14,  0x86,  0x1F,  0xF8, 	/* 2F7D0 */
+	0x14,  0xA0,  0x17,  0xBF,  0x14,  0xA4,  0x17,  0xA4,  0x14,  0xA4,  0x14,  0xA4,  0x2F,  0xE4,  0x25,  0x24, 	/* 2F7E0 */
+	0x48,  0xC4,  0x10,  0x84,  0x9F,  0x00,  0x40,  0x3F,  0xFF,  0x22,  0x00,  0x22,  0x3E,  0x3F,  0xE2,  0x22, 	/* 2F7F0 */
+	0x22,  0x2F,  0xA2,  0x28,  0xBE,  0x2F,  0xA2,  0x28,  0xA2,  0x2F,  0xBE,  0x22,  0x22,  0x3F,  0xE2,  0x42, 	/* 2F800 */
+	0x22,  0x42,  0x42,  0x02,  0x86,  0xA0,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFF,  0x12,  0x10,  0x1A,  0x50, 	/* 2F810 */
+	0x16,  0x90,  0x12,  0x1F,  0x1F,  0xE4,  0x18,  0x54,  0x1F,  0x54,  0x1D,  0x54,  0x1D,  0x48,  0x2F,  0x48, 	/* 2F820 */
+	0x28,  0x54,  0x48,  0x62,  0x08,  0xC1,  0xA1,  0x00,  0x40,  0x00,  0x40,  0x1F,  0xFF,  0x11,  0x00,  0x12, 	/* 2F830 */
+	0x00,  0x17,  0xFF,  0x1A,  0x94,  0x12,  0x94,  0x1F,  0xFF,  0x12,  0x94,  0x12,  0x94,  0x17,  0xFF,  0x20, 	/* 2F840 */
+	0x00,  0x25,  0x24,  0x48,  0x92,  0x10,  0x91,  0xA2,  0x00,  0x40,  0x00,  0x40,  0x1F,  0xFF,  0x10,  0x14, 	/* 2F850 */
+	0x13,  0xD8,  0x14,  0x8A,  0x13,  0x04,  0x17,  0xBA,  0x18,  0xA9,  0x17,  0xAA,  0x14,  0x46,  0x17,  0xBC, 	/* 2F860 */
+	0x20,  0xA4,  0x20,  0x98,  0x41,  0x2C,  0x06,  0xC3,  0xA3,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFF,  0x11, 	/* 2F870 */
+	0x10,  0x1F,  0xFE,  0x11,  0x10,  0x11,  0xF0,  0x1F,  0xFF,  0x10,  0x40,  0x17,  0xFC,  0x14,  0x44,  0x17, 	/* 2F880 */
+	0xFC,  0x24,  0x44,  0x27,  0xFC,  0x43,  0x0C,  0x1C,  0x02,  0xA8,  0x00,  0x40,  0x00,  0x40,  0x1F,  0xFF, 	/* 2F890 */
+	0x12,  0x00,  0x13,  0xFE,  0x14,  0x92,  0x19,  0x12,  0x17,  0xE6,  0x15,  0x58,  0x17,  0xE8,  0x15,  0x7E, 	/* 2F8A0 */
+	0x17,  0xC8,  0x24,  0x48,  0x28,  0x7F,  0x48,  0x48,  0x10,  0xC8,  0xA9,  0x00,  0x80,  0x1F,  0xFF,  0x10, 	/* 2F8B0 */
+	0x40,  0x1F,  0xFE,  0x15,  0xF4,  0x15,  0x14,  0x15,  0xF4,  0x14,  0x04,  0x17,  0xFC,  0x10,  0x0C,  0x17, 	/* 2F8C0 */
+	0xF0,  0x10,  0x40,  0x3F,  0xFF,  0x21,  0x50,  0x46,  0x4C,  0x18,  0x43,  0xAC,  0x00,  0x40,  0x1F,  0xFF, 	/* 2F8D0 */
+	0x10,  0x7C,  0x10,  0x40,  0x17,  0xFF,  0x14,  0x9A,  0x17,  0xE0,  0x14,  0x82,  0x15,  0xFE,  0x15,  0x24, 	/* 2F8E0 */
+	0x15,  0xFC,  0x15,  0x24,  0x2B,  0xFE,  0x32,  0x52,  0x4F,  0xFF,  0x00,  0x00,  0xB0,  0x00,  0x40,  0x00, 	/* 2F8F0 */
+	0x40,  0x1F,  0xFF,  0x10,  0x10,  0x1F,  0xD0,  0x15,  0x7F,  0x15,  0x10,  0x17,  0x7E,  0x15,  0x6A,  0x15, 	/* 2F900 */
+	0x6A,  0x17,  0x7E,  0x15,  0x30,  0x25,  0x6A,  0x27,  0x61,  0x5D,  0xA5,  0x01,  0x1C,  0xB1,  0x00,  0x40, 	/* 2F910 */
+	0x1F,  0xFF,  0x15,  0x48,  0x1A,  0x8A,  0x15,  0x54,  0x10,  0x1F,  0x17,  0xB4,  0x14,  0x94,  0x17,  0x9F, 	/* 2F920 */
+	0x10,  0x14,  0x1F,  0xD4,  0x1A,  0x5F,  0x2F,  0xD4,  0x28,  0x14,  0x48,  0x5F,  0x07,  0xC0,  0xB3,  0x00, 	/* 2F930 */
+	0x40,  0x3F,  0xFF,  0x20,  0x08,  0x3F,  0x88,  0x24,  0xFF,  0x27,  0x88,  0x24,  0xBE,  0x27,  0xAA,  0x24, 	/* 2F940 */
+	0xBE,  0x27,  0x80,  0x38,  0xFF,  0x2E,  0x98,  0x24,  0xB5,  0x2E,  0xB1,  0x44,  0xD2,  0x0E,  0x8E,  0xB4, 	/* 2F950 */
+	0x00,  0x00,  0x7C,  0x00,  0x04,  0x00,  0x08,  0x00,  0x08,  0x00,  0x10,  0x00,  0x3C,  0x00,  0x04,  0x00, 	/* 2F960 */
+	0x04,  0x00,  0x44,  0x00,  0x28,  0x00,  0x18,  0x00,  0x08,  0x00,  0x16,  0x00,  0x21,  0x80,  0x40,  0x7F, 	/* 2F970 */
+	0xB6,  0x00,  0x04,  0x7C,  0x18,  0x05,  0xF0,  0x08,  0x10,  0x08,  0x10,  0x10,  0x90,  0x3C,  0x9E,  0x04, 	/* 2F980 */
+	0x90,  0x24,  0x90,  0x14,  0x90,  0x14,  0x90,  0x08,  0x90,  0x0F,  0xFF,  0x12,  0x00,  0x21,  0x80,  0x40, 	/* 2F990 */
+	0x7F,  0xB7,  0x00,  0x08,  0x7C,  0x30,  0x05,  0xE0,  0x08,  0x20,  0x08,  0x20,  0x10,  0x20,  0x3F,  0xFE, 	/* 2F9A0 */
+	0x04,  0x20,  0x24,  0x20,  0x24,  0x20,  0x14,  0x20,  0x08,  0x20,  0x0D,  0xFC,  0x12,  0x00,  0x21,  0x80, 	/* 2F9B0 */
+	0x40,  0x7F,  0xB8,  0x00,  0x20,  0x7C,  0x20,  0x04,  0x20,  0x09,  0xFE,  0x09,  0x22,  0x11,  0x22,  0x3D, 	/* 2F9C0 */
+	0x22,  0x05,  0xFE,  0x05,  0x22,  0x45,  0x22,  0x29,  0x22,  0x19,  0xFE,  0x08,  0x00,  0x16,  0x00,  0x21, 	/* 2F9D0 */
+	0x80,  0x40,  0x7F,  0xBA,  0x00,  0x20,  0x7D,  0xFC,  0x04,  0x24,  0x08,  0x24,  0x13,  0xFF,  0x20,  0x24, 	/* 2F9E0 */
+	0x3D,  0xFC,  0x04,  0x20,  0x45,  0xFC,  0x24,  0x20,  0x18,  0x20,  0x0B,  0xFE,  0x14,  0x20,  0x13,  0x20, 	/* 2F9F0 */
+	0x20,  0xC0,  0x40,  0x3F,  0xBB,  0x00,  0x00,  0x3D,  0xFE,  0x05,  0x02,  0x09,  0x02,  0x09,  0x7A,  0x11, 	/* 2FA00 */
+	0x4A,  0x3D,  0x4A,  0x05,  0x4A,  0x05,  0x7A,  0x25,  0x02,  0x15,  0x02,  0x09,  0xFE,  0x0C,  0x00,  0x13, 	/* 2FA10 */
+	0x00,  0x20,  0xE0,  0x40,  0x1F,  0xBC,  0x00,  0x00,  0x7D,  0xFF,  0x04,  0x28,  0x08,  0x28,  0x08,  0xFE, 	/* 2FA20 */
+	0x10,  0xAA,  0x3C,  0xAA,  0x04,  0xAA,  0x24,  0xAE,  0x14,  0xC2,  0x1C,  0x82,  0x08,  0x82,  0x0C,  0xFE, 	/* 2FA30 */
+	0x12,  0x00,  0x21,  0x80,  0x40,  0x7F,  0xBE,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04, 	/* 2FA40 */
+	0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x08,  0x10,  0x08, 	/* 2FA50 */
+	0x10,  0x10,  0x10,  0x20,  0x10,  0x40,  0x10,  0xBF,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10, 	/* 2FA60 */
+	0x7F,  0xFF,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10, 	/* 2FA70 */
+	0x04,  0x10,  0x04,  0x10,  0x07,  0xF0,  0x00,  0x00,  0x81,  0x01,  0x00,  0x01,  0x20,  0x02,  0x10,  0x02, 	/* 2FA80 */
+	0x38,  0x07,  0xC4,  0x3C,  0x04,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x02,  0x10,  0x02, 	/* 2FA90 */
+	0x10,  0x04,  0x10,  0x04,  0x10,  0x08,  0x10,  0x10,  0x10,  0x83,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF, 	/* 2FAA0 */
+	0x01,  0x20,  0x01,  0x18,  0x02,  0x6C,  0x1F,  0x92,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10, 	/* 2FAB0 */
+	0x02,  0x10,  0x04,  0x10,  0x04,  0x10,  0x08,  0x10,  0x10,  0x10,  0x84,  0x00,  0x00,  0x1F,  0xFC,  0x00, 	/* 2FAC0 */
+	0x80,  0x00,  0x80,  0x0F,  0xF8,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x04,  0x10,  0x04,  0x10,  0x7F, 	/* 2FAD0 */
+	0xFF,  0x04,  0x10,  0x04,  0x10,  0x08,  0x10,  0x08,  0x10,  0x10,  0x10,  0x89,  0x24,  0x20,  0x24,  0x20, 	/* 2FAE0 */
+	0x24,  0x20,  0x3F,  0xFF,  0x04,  0x20,  0x7C,  0x20,  0x24,  0x20,  0x25,  0xFE,  0x44,  0x00,  0x02,  0x10, 	/* 2FAF0 */
+	0x7F,  0xFF,  0x02,  0x10,  0x02,  0x10,  0x04,  0x10,  0x08,  0x10,  0x10,  0x10,  0x8A,  0x24,  0xA0,  0x14, 	/* 2FB00 */
+	0xA0,  0x15,  0x3F,  0x3F,  0xA4,  0x24,  0xD4,  0x2E,  0x94,  0x35,  0x88,  0x24,  0x94,  0x25,  0xA2,  0x20, 	/* 2FB10 */
+	0x41,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x04,  0x20,  0x08,  0x20,  0x10,  0x20,  0x8B,  0x01,  0x10, 	/* 2FB20 */
+	0x01,  0x08,  0x01,  0x08,  0x01,  0x00,  0x7F,  0xFF,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x00,  0x80, 	/* 2FB30 */
+	0x00,  0x80,  0x00,  0x40,  0x00,  0x40,  0x00,  0x22,  0x00,  0x12,  0x00,  0x0A,  0x00,  0x06,  0x8C,  0x00, 	/* 2FB40 */
+	0x48,  0x00,  0x44,  0x00,  0x44,  0x00,  0x40,  0x7F,  0xFF,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00, 	/* 2FB50 */
+	0x20,  0x00,  0x10,  0x7F,  0x90,  0x00,  0x10,  0x00,  0x0A,  0x00,  0x0A,  0x00,  0x06,  0x00,  0x02,  0x8D, 	/* 2FB60 */
+	0x00,  0x48,  0x00,  0x44,  0x00,  0x44,  0x00,  0x40,  0x7F,  0xFF,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20, 	/* 2FB70 */
+	0x3F,  0xA0,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x0A,  0x7F,  0xCA,  0x00,  0x06,  0x00,  0x02, 	/* 2FB80 */
+	0x8F,  0x00,  0x20,  0x00,  0x28,  0x00,  0x24,  0x00,  0x24,  0x7F,  0xFF,  0x00,  0x20,  0x00,  0x20,  0x3F, 	/* 2FB90 */
+	0xA0,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x08,  0x05,  0xC9,  0x0E,  0x05,  0x70,  0x03,  0x00, 	/* 2FBA0 */
+	0x01,  0x90,  0x00,  0x48,  0x3F,  0x44,  0x00,  0x44,  0x00,  0x40,  0x7F,  0xFF,  0x00,  0x20,  0x00,  0x20, 	/* 2FBB0 */
+	0x3F,  0x20,  0x00,  0x20,  0x00,  0x10,  0x00,  0x10,  0x01,  0x90,  0x0E,  0x0A,  0x70,  0x0A,  0x00,  0x06, 	/* 2FBC0 */
+	0x00,  0x02,  0x91,  0x02,  0x0C,  0x22,  0x0A,  0x14,  0x0A,  0x08,  0x08,  0x15,  0xFF,  0x22,  0x08,  0x48, 	/* 2FBD0 */
+	0x08,  0x0B,  0xF8,  0x7E,  0x48,  0x08,  0x48,  0x1C,  0x48,  0x1A,  0x54,  0x28,  0x65,  0x4B,  0x83,  0x08, 	/* 2FBE0 */
+	0x03,  0x08,  0x01,  0x93,  0x00,  0x00,  0x3F,  0xF0,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x1F,  0xF0, 	/* 2FBF0 */
+	0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x1F,  0xF8,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08, 	/* 2FC00 */
+	0x00,  0x10,  0x00,  0xE0,  0x94,  0x00,  0x00,  0x7F,  0xF8,  0x01,  0x08,  0x01,  0x08,  0x01,  0x08,  0x3F, 	/* 2FC10 */
+	0xF8,  0x21,  0x00,  0x21,  0x00,  0x3F,  0xFC,  0x01,  0x04,  0x01,  0x04,  0x01,  0x04,  0x01,  0x04,  0x01, 	/* 2FC20 */
+	0x08,  0x01,  0x30,  0x01,  0x00,  0x95,  0x00,  0x04,  0x7F,  0x84,  0x00,  0x84,  0x00,  0x84,  0x00,  0x84, 	/* 2FC30 */
+	0x3F,  0x84,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x3F,  0x84,  0x00,  0x84,  0x00,  0x84,  0x00,  0x84, 	/* 2FC40 */
+	0x00,  0x84,  0x01,  0x04,  0x0E,  0x04,  0x96,  0x00,  0x00,  0x1F,  0xF8,  0x00,  0x08,  0x00,  0x08,  0x0F, 	/* 2FC50 */
+	0xF8,  0x08,  0x00,  0x08,  0x00,  0x0F,  0xFC,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x08,  0x00, 	/* 2FC60 */
+	0x70,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x00,  0x97,  0x02,  0x40,  0x02,  0x40,  0x7F,  0xFC,  0x02,  0x44, 	/* 2FC70 */
+	0x02,  0x44,  0x3F,  0xFC,  0x22,  0x40,  0x22,  0x40,  0x3F,  0xFE,  0x02,  0x42,  0x02,  0x42,  0x04,  0x42, 	/* 2FC80 */
+	0x04,  0x42,  0x08,  0x4C,  0x10,  0x40,  0x20,  0x40,  0x98,  0x00,  0x10,  0x7E,  0x10,  0x02,  0x10,  0x02, 	/* 2FC90 */
+	0x10,  0x02,  0x10,  0x3E,  0x10,  0x20,  0x20,  0x20,  0x20,  0x20,  0x20,  0x3E,  0x28,  0x02,  0x24,  0x02, 	/* 2FCA0 */
+	0x44,  0x02,  0x42,  0x02,  0x5E,  0x05,  0xE2,  0x38,  0x02,  0x9B,  0x00,  0x10,  0x7E,  0x90,  0x02,  0x90, 	/* 2FCB0 */
+	0x02,  0x92,  0x02,  0x9E,  0x3E,  0xF2,  0x21,  0x92,  0x20,  0x92,  0x3E,  0x92,  0x02,  0x9C,  0x02,  0x90, 	/* 2FCC0 */
+	0x02,  0x80,  0x02,  0x81,  0x02,  0x81,  0x04,  0x41,  0x18,  0x3F,  0x9F,  0x08,  0x20,  0x04,  0x20,  0x04, 	/* 2FCD0 */
+	0x40,  0x3F,  0xF8,  0x01,  0x08,  0x01,  0x08,  0x3F,  0xF8,  0x21,  0x00,  0x21,  0x00,  0x3F,  0xFC,  0x23, 	/* 2FCE0 */
+	0x04,  0x03,  0x04,  0x05,  0x04,  0x19,  0x08,  0x61,  0x30,  0x01,  0x00,  0xA5,  0x00,  0x40,  0x7C,  0x40, 	/* 2FCF0 */
+	0x04,  0x40,  0x04,  0xFF,  0x04,  0x90,  0x3D,  0x10,  0x22,  0x10,  0x20,  0x18,  0x20,  0x54,  0x3C,  0x54, 	/* 2FD00 */
+	0x04,  0x92,  0x04,  0x92,  0x05,  0x12,  0x04,  0x10,  0x08,  0x10,  0x30,  0x30,  0xA6,  0x00,  0x20,  0x7C, 	/* 2FD10 */
+	0x20,  0x04,  0x20,  0x07,  0xFF,  0x04,  0x20,  0x3C,  0x20,  0x20,  0x48,  0x21,  0x88,  0x20,  0x50,  0x3C, 	/* 2FD20 */
+	0x50,  0x04,  0x20,  0x04,  0x28,  0x04,  0x44,  0x04,  0x9C,  0x0B,  0xE2,  0x30,  0x02,  0xA7,  0x00,  0x02, 	/* 2FD30 */
+	0x78,  0x1C,  0x09,  0xE4,  0x09,  0x04,  0x09,  0x24,  0x79,  0x24,  0x41,  0x24,  0x41,  0x24,  0x41,  0x24, 	/* 2FD40 */
+	0x79,  0x24,  0x09,  0x24,  0x09,  0x34,  0x09,  0x2C,  0x0A,  0x3A,  0x12,  0xC6,  0x64,  0x01,  0xA9,  0x04, 	/* 2FD50 */
+	0x00,  0x04,  0x00,  0x7F,  0xFE,  0x09,  0x22,  0x11,  0x14,  0x3E,  0x08,  0x05,  0x94,  0x18,  0x63,  0x6F, 	/* 2FD60 */
+	0xF0,  0x00,  0x10,  0x0F,  0xF0,  0x08,  0x00,  0x0F,  0xF8,  0x00,  0x08,  0x00,  0x08,  0x00,  0x70,  0xAD, 	/* 2FD70 */
+	0x00,  0x00,  0x7F,  0xFF,  0x04,  0x84,  0x04,  0x84,  0x04,  0xFC,  0x3C,  0x84,  0x20,  0x84,  0x20,  0x84, 	/* 2FD80 */
+	0x20,  0xFC,  0x3C,  0x84,  0x04,  0x84,  0x04,  0x86,  0x04,  0xFC,  0x07,  0x84,  0x08,  0x04,  0x30,  0x04, 	/* 2FD90 */
+	0xAF,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0x40,  0x0A,  0x58,  0x12,  0x44,  0x64,  0x42,  0x00, 	/* 2FDA0 */
+	0x00,  0x1F,  0xF8,  0x00,  0x08,  0x0F,  0xF8,  0x08,  0x00,  0x0F,  0xFC,  0x00,  0x04,  0x00,  0x04,  0x00, 	/* 2FDB0 */
+	0x78,  0xB1,  0x00,  0x00,  0x3F,  0x7E,  0x01,  0x02,  0x01,  0x02,  0x1F,  0x3E,  0x10,  0x20,  0x10,  0x20, 	/* 2FDC0 */
+	0x1F,  0x3E,  0x01,  0x02,  0x31,  0x62,  0x09,  0x12,  0x07,  0x0E,  0x19,  0x32,  0x61,  0xC2,  0x02,  0x04, 	/* 2FDD0 */
+	0x0C,  0x18,  0xB5,  0x00,  0x00,  0x7C,  0xFE,  0x04,  0x80,  0x04,  0xFC,  0x04,  0x80,  0x7C,  0xFC,  0x40, 	/* 2FDE0 */
+	0x80,  0x40,  0x80,  0x7F,  0xFF,  0x04,  0xA2,  0x04,  0xA4,  0x04,  0x90,  0x04,  0x88,  0x08,  0xA4,  0x10, 	/* 2FDF0 */
+	0xC2,  0x63,  0x01,  0xB7,  0x00,  0x40,  0x7C,  0x50,  0x04,  0x8C,  0x07,  0xFA,  0x04,  0x21,  0x3C,  0x20, 	/* 2FE00 */
+	0x21,  0xFC,  0x21,  0x24,  0x3D,  0x24,  0x05,  0x24,  0x05,  0xFC,  0x04,  0x24,  0x04,  0x22,  0x04,  0x3E, 	/* 2FE10 */
+	0x0B,  0xC1,  0x30,  0x01,  0xB8,  0x00,  0x00,  0x7B,  0xDE,  0x0A,  0x52,  0x0A,  0x52,  0x0A,  0x52,  0x7B, 	/* 2FE20 */
+	0xDE,  0x42,  0x52,  0x42,  0x52,  0x42,  0x52,  0x7B,  0xDE,  0x0A,  0x52,  0x0A,  0x52,  0x0A,  0x52,  0x0A, 	/* 2FE30 */
+	0x52,  0x12,  0x62,  0x64,  0xC6,  0xBC,  0x00,  0x00,  0x78,  0x1E,  0x0F,  0xE2,  0x08,  0x82,  0x09,  0x02, 	/* 2FE40 */
+	0x3B,  0xDE,  0x22,  0x50,  0x22,  0x50,  0x3A,  0x5E,  0x0B,  0xC2,  0x0A,  0x42,  0x0A,  0x42,  0x0A,  0x42, 	/* 2FE50 */
+	0x0B,  0xC2,  0x10,  0x04,  0x60,  0x18,  0xBE,  0x02,  0x44,  0x7D,  0x24,  0x05,  0x28,  0x05,  0xFC,  0x05, 	/* 2FE60 */
+	0x24,  0x3D,  0x24,  0x21,  0xFC,  0x21,  0x24,  0x21,  0x24,  0x3D,  0xFC,  0x04,  0x20,  0x04,  0x20,  0x07, 	/* 2FE70 */
+	0xFF,  0x04,  0x20,  0x08,  0x20,  0x30,  0x20,  0x81,  0x00,  0x00,  0x7F,  0xFF,  0x04,  0x04,  0x04,  0xF4, 	/* 2FE80 */
+	0x04,  0x94,  0x3C,  0x94,  0x20,  0xF4,  0x20,  0x0C,  0x3D,  0xFF,  0x04,  0x04,  0x04,  0xF4,  0x04,  0x94, 	/* 2FE90 */
+	0x04,  0x94,  0x04,  0xF4,  0x08,  0x04,  0x30,  0x0C,  0x88,  0x00,  0x00,  0x7F,  0xDE,  0x06,  0x52,  0x07, 	/* 2FEA0 */
+	0xDE,  0x04,  0x00,  0x3D,  0xFC,  0x21,  0x24,  0x21,  0x24,  0x21,  0xFC,  0x3D,  0x24,  0x05,  0xFC,  0x04, 	/* 2FEB0 */
+	0x20,  0x07,  0xFF,  0x04,  0x20,  0x08,  0x20,  0x30,  0x20,  0x8A,  0x00,  0x00,  0x7F,  0xFF,  0x04,  0x00, 	/* 2FEC0 */
+	0x05,  0xFC,  0x05,  0x24,  0x3D,  0xFC,  0x21,  0x24,  0x23,  0xFE,  0x3C,  0x00,  0x05,  0xFC,  0x05,  0x24, 	/* 2FED0 */
+	0x05,  0xFC,  0x05,  0x24,  0x05,  0xFC,  0x08,  0x00,  0x33,  0xFF,  0x8C,  0x00,  0x00,  0x7F,  0xFF,  0x09, 	/* 2FEE0 */
+	0x24,  0x0A,  0x22,  0x0F,  0xFF,  0x7B,  0x76,  0x42,  0xAA,  0x42,  0xEE,  0x43,  0x76,  0x7A,  0x22,  0x0B, 	/* 2FEF0 */
+	0x66,  0x0A,  0xBA,  0x0A,  0xEE,  0x0B,  0x76,  0x12,  0x22,  0x62,  0x26,  0x8E,  0x11,  0x84,  0x17,  0xE4, 	/* 2FF00 */
+	0x68,  0x1A,  0x13,  0xC4,  0x28,  0x0A,  0x7F,  0xDF,  0x12,  0x44,  0x3B,  0xD6,  0x54,  0x25,  0x1F,  0xF4, 	/* 2FF10 */
+	0x00,  0x10,  0x0F,  0xF0,  0x08,  0x00,  0x0F,  0xF8,  0x00,  0x08,  0x00,  0x70,  0x91,  0x02,  0x00,  0x02, 	/* 2FF20 */
+	0x00,  0x02,  0x00,  0x02,  0x00,  0x03,  0xF0,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x08, 	/* 2FF30 */
+	0x20,  0x0F,  0xE0,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x7F,  0xFF,  0x00,  0x00,  0x93,  0x01,  0x00, 	/* 2FF40 */
+	0x11,  0x08,  0x09,  0x08,  0x05,  0x10,  0x05,  0x20,  0x01,  0x00,  0x3F,  0xFC,  0x00,  0x04,  0x00,  0x04, 	/* 2FF50 */
+	0x00,  0x04,  0x1F,  0xFC,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x3F,  0xFC,  0x00,  0x00,  0x96,  0x02, 	/* 2FF60 */
+	0x00,  0x03,  0xF8,  0x04,  0x10,  0x0F,  0xF0,  0x00,  0x20,  0x7F,  0xFF,  0x01,  0x00,  0x06,  0xA4,  0x38, 	/* 2FF70 */
+	0xA8,  0x03,  0x58,  0x0C,  0x50,  0x30,  0xC8,  0x03,  0x44,  0x0C,  0x42,  0x70,  0x41,  0x01,  0x80,  0x97, 	/* 2FF80 */
+	0x08,  0x10,  0x08,  0x10,  0x7F,  0xFE,  0x08,  0x10,  0x3E,  0x7C,  0x08,  0x10,  0x0E,  0xFE,  0x78,  0x10, 	/* 2FF90 */
+	0x08,  0x10,  0x1F,  0xF8,  0x00,  0x08,  0x00,  0x08,  0x7F,  0xFF,  0x00,  0x08,  0x1F,  0xF8,  0x00,  0x00, 	/* 2FFA0 */
+	0x99,  0x02,  0x00,  0x03,  0xF8,  0x04,  0x10,  0x0F,  0xF0,  0x00,  0x20,  0x7F,  0xFF,  0x00,  0x00,  0x7F, 	/* 2FFB0 */
+	0xFE,  0x48,  0x8A,  0x4F,  0xFA,  0x08,  0x88,  0x0F,  0xF8,  0x7F,  0xFF,  0x02,  0xA0,  0x0C,  0x98,  0x70, 	/* 2FFC0 */
+	0x87,  0x9C,  0x02,  0x00,  0x03,  0xF8,  0x04,  0x10,  0x0F,  0xF0,  0x00,  0x20,  0x7F,  0xFF,  0x08,  0x14, 	/* 2FFD0 */
+	0x2A,  0x22,  0x7F,  0x7D,  0x1C,  0x94,  0x2A,  0x24,  0x48,  0x4C,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20, 	/* 2FFE0 */
+	0x18,  0x20,  0x9D,  0x02,  0x00,  0x03,  0xF8,  0x04,  0x10,  0x0F,  0xF0,  0x00,  0x20,  0x7F,  0xFF,  0x08, 	/* 2FFF0 */
+	0x10,  0x2A,  0x64,  0x7F,  0x1A,  0x1C,  0xFD,  0x2A,  0x2A,  0x48,  0xC9,  0x02,  0x10,  0x7F,  0xFF,  0x02, 	/* 30000 */
+	0x10,  0x04,  0x10,  0xA1,  0x00,  0x20,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x03,  0x00,  0x0C,  0x10, 	/* 30010 */
+	0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x03,  0x08,  0x0C,  0x10,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80, 	/* 30020 */
+	0x03,  0x00,  0x1C,  0x00,  0xA2,  0x00,  0x04,  0x3F,  0xC4,  0x09,  0x08,  0x09,  0x08,  0x09,  0x12,  0x09, 	/* 30030 */
+	0x22,  0x7F,  0xC4,  0x09,  0x04,  0x09,  0x09,  0x09,  0x11,  0x09,  0x22,  0x11,  0x02,  0x11,  0x04,  0x11, 	/* 30040 */
+	0x08,  0x21,  0x10,  0x41,  0x20,  0xA6,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFE,  0x04,  0x10,  0x02,  0x20, 	/* 30050 */
+	0x1F,  0xFE,  0x10,  0x10,  0x10,  0x60,  0x11,  0x88,  0x1E,  0x10,  0x10,  0x60,  0x11,  0x84,  0x2E,  0x08, 	/* 30060 */
+	0x20,  0x30,  0x41,  0xC0,  0x0E,  0x00,  0xA9,  0x01,  0x08,  0x06,  0x08,  0x78,  0x90,  0x10,  0x90,  0x49, 	/* 30070 */
+	0x24,  0x29,  0x44,  0x22,  0x08,  0x08,  0x08,  0x7F,  0x92,  0x08,  0x22,  0x0C,  0x44,  0x1A,  0x04,  0x19, 	/* 30080 */
+	0x08,  0x28,  0x10,  0x48,  0x20,  0x08,  0xC0,  0xAA,  0x04,  0x08,  0x07,  0x88,  0x04,  0x10,  0x3F,  0xD0, 	/* 30090 */
+	0x24,  0xA4,  0x27,  0x04,  0x3C,  0x08,  0x24,  0x90,  0x23,  0xA2,  0x20,  0x02,  0x25,  0x04,  0x25,  0x08, 	/* 300A0 */
+	0x25,  0x30,  0x29,  0x01,  0x48,  0x81,  0x10,  0x7F,  0xAB,  0x00,  0x04,  0x3F,  0xC4,  0x24,  0x48,  0x24, 	/* 300B0 */
+	0x48,  0x2F,  0x52,  0x24,  0x62,  0x24,  0x44,  0x3F,  0xC4,  0x20,  0x49,  0x2F,  0x51,  0x29,  0x42,  0x29, 	/* 300C0 */
+	0x42,  0x2F,  0x44,  0x20,  0x48,  0x20,  0x50,  0x40,  0xE0,  0xAC,  0x10,  0x84,  0x10,  0x84,  0x10,  0x88, 	/* 300D0 */
+	0x7F,  0xF8,  0x10,  0x92,  0x10,  0xA2,  0x39,  0xC4,  0x35,  0xA4,  0x52,  0x89,  0x52,  0x91,  0x14,  0xA2, 	/* 300E0 */
+	0x10,  0x82,  0x10,  0x84,  0x10,  0x88,  0x10,  0x90,  0x10,  0xA0,  0xAD,  0x04,  0x04,  0x04,  0x04,  0x7F, 	/* 300F0 */
+	0xC8,  0x04,  0x12,  0x04,  0x22,  0x3F,  0x84,  0x00,  0x04,  0x3F,  0x88,  0x20,  0x91,  0x20,  0xA1,  0x3F, 	/* 30100 */
+	0x82,  0x11,  0x02,  0x0A,  0x04,  0x09,  0xC8,  0x1E,  0x10,  0x70,  0x60,  0xB0,  0x04,  0x08,  0x04,  0x08, 	/* 30110 */
+	0x7F,  0xD0,  0x11,  0x10,  0x0A,  0x24,  0x7F,  0xC4,  0x00,  0x08,  0x3F,  0x88,  0x20,  0x92,  0x3F,  0xA2, 	/* 30120 */
+	0x20,  0xC4,  0x3F,  0x84,  0x04,  0x08,  0x7F,  0xD0,  0x04,  0x20,  0x04,  0x40,  0xB1,  0x00,  0x04,  0x1F, 	/* 30130 */
+	0x84,  0x10,  0x88,  0x1F,  0x88,  0x10,  0x92,  0x1F,  0xA2,  0x04,  0x04,  0x7F,  0xC4,  0x00,  0x09,  0x1F, 	/* 30140 */
+	0x91,  0x10,  0x82,  0x1F,  0x82,  0x04,  0x04,  0x24,  0x84,  0x44,  0x48,  0x0C,  0x10,  0xB3,  0x00,  0x40, 	/* 30150 */
+	0x00,  0x40,  0x00,  0x80,  0x01,  0x00,  0x02,  0x10,  0x04,  0x20,  0x18,  0x40,  0x00,  0x80,  0x01,  0x80, 	/* 30160 */
+	0x02,  0x80,  0x0C,  0x80,  0x30,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0xB7,  0x08, 	/* 30170 */
+	0x20,  0x08,  0x20,  0x10,  0x20,  0x13,  0xFF,  0x24,  0x40,  0x44,  0x40,  0x08,  0x40,  0x08,  0x7C,  0x18, 	/* 30180 */
+	0x44,  0x28,  0x44,  0x48,  0x44,  0x08,  0x84,  0x08,  0x84,  0x09,  0x04,  0x0A,  0x04,  0x0C,  0x18,  0xB9, 	/* 30190 */
+	0x08,  0x00,  0x08,  0xF8,  0x10,  0x88,  0x10,  0x89,  0x24,  0x89,  0x44,  0x89,  0x09,  0x07,  0x0A,  0x00, 	/* 301A0 */
+	0x17,  0xFC,  0x30,  0x84,  0x50,  0x88,  0x10,  0x50,  0x10,  0x60,  0x10,  0x50,  0x11,  0x8C,  0x16,  0x03, 	/* 301B0 */
+	0xBC,  0x08,  0x20,  0x08,  0x20,  0x10,  0x20,  0x11,  0xFF,  0x25,  0x22,  0x45,  0x24,  0x09,  0x20,  0x09, 	/* 301C0 */
+	0xFC,  0x11,  0x44,  0x31,  0x44,  0x51,  0x48,  0x11,  0x28,  0x12,  0x10,  0x12,  0x28,  0x14,  0xC4,  0x13, 	/* 301D0 */
+	0x03,  0xBF,  0x08,  0x90,  0x08,  0x90,  0x13,  0xFE,  0x10,  0x92,  0x24,  0x92,  0x47,  0xFE,  0x0A,  0x90, 	/* 301E0 */
+	0x0A,  0x90,  0x13,  0xFE,  0x30,  0x92,  0x50,  0x92,  0x10,  0x92,  0x10,  0x92,  0x11,  0x1C,  0x12,  0x10, 	/* 301F0 */
+	0x14,  0x10,  0x80,  0x08,  0x40,  0x08,  0x20,  0x10,  0x20,  0x13,  0xFE,  0x24,  0x20,  0x44,  0x20,  0x08, 	/* 30200 */
+	0x20,  0x08,  0x20,  0x11,  0xFC,  0x30,  0x20,  0x50,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x13, 	/* 30210 */
+	0xFF,  0x10,  0x00,  0x81,  0x04,  0x00,  0x07,  0xFE,  0x08,  0x20,  0x08,  0x20,  0x10,  0x20,  0x25,  0x20, 	/* 30220 */
+	0x45,  0x20,  0x09,  0x3E,  0x09,  0x20,  0x19,  0x20,  0x29,  0x20,  0x49,  0x20,  0x09,  0x20,  0x09,  0x20, 	/* 30230 */
+	0x0F,  0xFF,  0x08,  0x00,  0x82,  0x08,  0x00,  0x09,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x25,  0x04,  0x45, 	/* 30240 */
+	0xFC,  0x09,  0x04,  0x09,  0x04,  0x11,  0x04,  0x31,  0xFC,  0x51,  0x04,  0x11,  0x04,  0x11,  0x04,  0x11, 	/* 30250 */
+	0x04,  0x17,  0xFF,  0x10,  0x00,  0x83,  0x08,  0x20,  0x09,  0x20,  0x11,  0x20,  0x11,  0x20,  0x25,  0xFE, 	/* 30260 */
+	0x46,  0x20,  0x0A,  0x20,  0x0C,  0x20,  0x10,  0x20,  0x31,  0xFC,  0x50,  0x20,  0x10,  0x20,  0x10,  0x20, 	/* 30270 */
+	0x10,  0x20,  0x17,  0xFF,  0x10,  0x00,  0x84,  0x08,  0x00,  0x0B,  0xFC,  0x11,  0x04,  0x10,  0x88,  0x24, 	/* 30280 */
+	0x50,  0x44,  0x30,  0x08,  0xCC,  0x0F,  0x03,  0x10,  0x20,  0x10,  0x20,  0x33,  0xFE,  0x50,  0x20,  0x10, 	/* 30290 */
+	0x20,  0x10,  0x20,  0x17,  0xFF,  0x10,  0x00,  0x85,  0x04,  0x20,  0x04,  0x20,  0x09,  0xFE,  0x08,  0x20, 	/* 302A0 */
+	0x12,  0x20,  0x22,  0x20,  0x05,  0xFF,  0x04,  0x04,  0x08,  0x04,  0x1B,  0xFF,  0x28,  0x84,  0x48,  0x44, 	/* 302B0 */
+	0x08,  0x44,  0x08,  0x04,  0x08,  0x04,  0x08,  0x0C,  0x87,  0x08,  0x80,  0x08,  0x80,  0x10,  0xFE,  0x14, 	/* 302C0 */
+	0x82,  0x25,  0x02,  0x49,  0xF2,  0x0B,  0x12,  0x15,  0x12,  0x11,  0xF2,  0x31,  0x12,  0x51,  0x12,  0x11, 	/* 302D0 */
+	0x12,  0x11,  0xF2,  0x10,  0x02,  0x10,  0x04,  0x10,  0x18,  0x88,  0x08,  0x00,  0x09,  0xFC,  0x11,  0x04, 	/* 302E0 */
+	0x11,  0x04,  0x25,  0xFC,  0x45,  0x04,  0x09,  0x04,  0x09,  0xFC,  0x11,  0x22,  0x31,  0x24,  0x51,  0x18, 	/* 302F0 */
+	0x11,  0x10,  0x11,  0x08,  0x11,  0x64,  0x11,  0x82,  0x16,  0x01,  0x8A,  0x08,  0x00,  0x0B,  0xFE,  0x12, 	/* 30300 */
+	0x02,  0x12,  0x02,  0x26,  0xFA,  0x46,  0x8A,  0x0A,  0x8A,  0x0A,  0x8A,  0x1A,  0x8A,  0x2A,  0x8A,  0x4A, 	/* 30310 */
+	0xFA,  0x0A,  0x02,  0x0A,  0x02,  0x0A,  0x02,  0x0B,  0xFE,  0x08,  0x00,  0x8B,  0x08,  0x20,  0x08,  0x20, 	/* 30320 */
+	0x13,  0xFC,  0x10,  0x24,  0x24,  0x24,  0x47,  0xFF,  0x08,  0x24,  0x08,  0x24,  0x13,  0xFC,  0x10,  0x20, 	/* 30330 */
+	0x33,  0xFC,  0x50,  0x20,  0x10,  0x20,  0x17,  0xFF,  0x10,  0x20,  0x10,  0x20,  0x8C,  0x08,  0x40,  0x08, 	/* 30340 */
+	0x48,  0x10,  0x88,  0x13,  0x10,  0x24,  0xD0,  0x44,  0x24,  0x08,  0x42,  0x0B,  0xFD,  0x10,  0x41,  0x10, 	/* 30350 */
+	0xFC,  0x31,  0x88,  0x56,  0x48,  0x10,  0x30,  0x10,  0x70,  0x11,  0x8C,  0x16,  0x03,  0x90,  0x08,  0x20, 	/* 30360 */
+	0x08,  0x20,  0x10,  0x50,  0x10,  0x50,  0x24,  0x88,  0x45,  0x04,  0x0A,  0xFA,  0x0C,  0x21,  0x10,  0x20, 	/* 30370 */
+	0x37,  0xFE,  0x50,  0x20,  0x11,  0x28,  0x11,  0x24,  0x12,  0x22,  0x14,  0x22,  0x10,  0x60,  0x91,  0x08, 	/* 30380 */
+	0x00,  0x0B,  0xFE,  0x10,  0x00,  0x11,  0x24,  0x25,  0x24,  0x46,  0x48,  0x0A,  0xD8,  0x09,  0x24,  0x19, 	/* 30390 */
+	0x24,  0x18,  0x00,  0x29,  0xFC,  0x48,  0x20,  0x08,  0x20,  0x08,  0x20,  0x0F,  0xFF,  0x08,  0x00,  0x92, 	/* 303A0 */
+	0x08,  0x20,  0x08,  0x20,  0x11,  0xFE,  0x10,  0x20,  0x24,  0x20,  0x47,  0xFF,  0x08,  0x20,  0x08,  0x20, 	/* 303B0 */
+	0x11,  0x20,  0x11,  0x3E,  0x31,  0x20,  0x51,  0xA0,  0x11,  0x60,  0x12,  0x20,  0x12,  0x18,  0x14,  0x07, 	/* 303C0 */
+	0x93,  0x09,  0x04,  0x08,  0x84,  0x10,  0x88,  0x10,  0x10,  0x27,  0xFE,  0x48,  0x20,  0x08,  0x20,  0x11, 	/* 303D0 */
+	0x20,  0x11,  0x3E,  0x31,  0x20,  0x51,  0x20,  0x11,  0x20,  0x12,  0xA0,  0x12,  0x60,  0x14,  0x30,  0x18, 	/* 303E0 */
+	0x0F,  0x97,  0x08,  0x00,  0x09,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x25,  0x04,  0x45,  0x04,  0x09,  0xFC, 	/* 303F0 */
+	0x08,  0x00,  0x17,  0xFF,  0x30,  0x08,  0x57,  0xFF,  0x11,  0x08,  0x10,  0x88,  0x10,  0x88,  0x10,  0x08, 	/* 30400 */
+	0x10,  0x18,  0x98,  0x08,  0x48,  0x08,  0x48,  0x10,  0x48,  0x13,  0xCF,  0x24,  0x48,  0x44,  0x48,  0x08, 	/* 30410 */
+	0x48,  0x0B,  0xCF,  0x10,  0x48,  0x30,  0x48,  0x51,  0xC8,  0x16,  0x4F,  0x10,  0x88,  0x10,  0x88,  0x11, 	/* 30420 */
+	0x08,  0x12,  0x08,  0x99,  0x08,  0x10,  0x08,  0x90,  0x10,  0x90,  0x10,  0x9E,  0x24,  0x90,  0x44,  0x90, 	/* 30430 */
+	0x0B,  0xFF,  0x08,  0x10,  0x10,  0x90,  0x30,  0x90,  0x50,  0x9E,  0x10,  0x90,  0x11,  0x50,  0x11,  0x30, 	/* 30440 */
+	0x12,  0x18,  0x14,  0x07,  0x9E,  0x08,  0x84,  0x08,  0x84,  0x10,  0x84,  0x10,  0xC6,  0x25,  0x4A,  0x45, 	/* 30450 */
+	0x29,  0x0A,  0x10,  0x08,  0x10,  0x10,  0x90,  0x30,  0x90,  0x50,  0x9E,  0x10,  0x90,  0x11,  0x50,  0x11, 	/* 30460 */
+	0x30,  0x12,  0x18,  0x14,  0x07,  0xA0,  0x08,  0x20,  0x08,  0x20,  0x13,  0xFF,  0x10,  0x20,  0x25,  0x24, 	/* 30470 */
+	0x45,  0x24,  0x09,  0x26,  0x0A,  0xAA,  0x12,  0x69,  0x34,  0x30,  0x50,  0x70,  0x10,  0xA8,  0x11,  0x24, 	/* 30480 */
+	0x12,  0x22,  0x14,  0x21,  0x10,  0x20,  0xA1,  0x0A,  0x00,  0x0A,  0x1E,  0x13,  0xF2,  0x12,  0x92,  0x24, 	/* 30490 */
+	0x92,  0x44,  0x92,  0x0B,  0xF2,  0x08,  0x92,  0x12,  0x92,  0x32,  0xF2,  0x52,  0x92,  0x12,  0x92,  0x12, 	/* 304A0 */
+	0xFC,  0x13,  0x90,  0x1C,  0x10,  0x10,  0x10,  0xA8,  0x08,  0x20,  0x08,  0x40,  0x11,  0xFC,  0x11,  0x04, 	/* 304B0 */
+	0x25,  0xFC,  0x45,  0x04,  0x09,  0x04,  0x09,  0xFC,  0x10,  0x00,  0x33,  0xFE,  0x50,  0x20,  0x11,  0xFC, 	/* 304C0 */
+	0x10,  0x20,  0x10,  0x20,  0x17,  0xFF,  0x10,  0x00,  0xA9,  0x08,  0x80,  0x08,  0x80,  0x10,  0xFF,  0x15, 	/* 304D0 */
+	0x00,  0x25,  0xFC,  0x46,  0x84,  0x08,  0xFC,  0x08,  0x84,  0x18,  0xFC,  0x28,  0x20,  0x48,  0x7C,  0x08, 	/* 304E0 */
+	0x84,  0x09,  0x68,  0x08,  0x10,  0x08,  0x6C,  0x0B,  0x83,  0xAA,  0x08,  0x04,  0x08,  0x18,  0x11,  0xF0, 	/* 304F0 */
+	0x11,  0x10,  0x25,  0xFF,  0x45,  0x10,  0x09,  0x7C,  0x09,  0x44,  0x11,  0x44,  0x31,  0x7C,  0x52,  0x44, 	/* 30500 */
+	0x12,  0x7C,  0x12,  0x44,  0x14,  0x44,  0x18,  0x7C,  0x10,  0x00,  0xAD,  0x08,  0x10,  0x08,  0x3E,  0x10, 	/* 30510 */
+	0x62,  0x11,  0x94,  0x24,  0x48,  0x44,  0x30,  0x09,  0xC0,  0x0E,  0xFE,  0x10,  0xA0,  0x31,  0x20,  0x57, 	/* 30520 */
+	0xFF,  0x10,  0x20,  0x12,  0x22,  0x12,  0x22,  0x13,  0xFE,  0x10,  0x00,  0xAE,  0x09,  0x08,  0x0D,  0x48, 	/* 30530 */
+	0x15,  0x48,  0x15,  0x4F,  0x27,  0xCA,  0x4C,  0x52,  0x08,  0x12,  0x17,  0xE2,  0x12,  0x8A,  0x32,  0x8A, 	/* 30540 */
+	0x52,  0x84,  0x12,  0xA4,  0x12,  0xCC,  0x14,  0x92,  0x18,  0x22,  0x10,  0x41,  0xB3,  0x08,  0x40,  0x08, 	/* 30550 */
+	0x40,  0x17,  0xFF,  0x10,  0x40,  0x27,  0xFC,  0x46,  0x94,  0x0A,  0x94,  0x0A,  0x94,  0x13,  0xFC,  0x30, 	/* 30560 */
+	0x40,  0x50,  0x24,  0x12,  0xA2,  0x12,  0x81,  0x14,  0x89,  0x18,  0x88,  0x10,  0x78,  0xB4,  0x09,  0x10, 	/* 30570 */
+	0x0D,  0x50,  0x15,  0x50,  0x15,  0x5F,  0x27,  0xE4,  0x48,  0x24,  0x08,  0x44,  0x17,  0xD4,  0x11,  0x14, 	/* 30580 */
+	0x31,  0x14,  0x57,  0xC8,  0x11,  0x08,  0x11,  0x4C,  0x11,  0x94,  0x16,  0x22,  0x10,  0x41,  0xB9,  0x09, 	/* 30590 */
+	0x08,  0x09,  0x08,  0x0F,  0xE8,  0x11,  0x8F,  0x15,  0x54,  0x26,  0x54,  0x0B,  0xA4,  0x08,  0x14,  0x13, 	/* 305A0 */
+	0xD4,  0x32,  0x54,  0x53,  0xC8,  0x12,  0x48,  0x13,  0xCC,  0x12,  0x54,  0x12,  0x62,  0x12,  0xC1,  0xBC, 	/* 305B0 */
+	0x09,  0x08,  0x0A,  0x08,  0x17,  0xC8,  0x14,  0x4F,  0x27,  0xD4,  0x4C,  0x64,  0x0F,  0xD4,  0x11,  0x14, 	/* 305C0 */
+	0x1F,  0xF4,  0x32,  0x14,  0x53,  0x88,  0x12,  0x88,  0x12,  0x94,  0x14,  0x94,  0x18,  0xA2,  0x11,  0xC1, 	/* 305D0 */
+	0xBD,  0x09,  0x10,  0x0D,  0x50,  0x15,  0x50,  0x17,  0xDF,  0x21,  0x24,  0x49,  0x24,  0x0A,  0xD4,  0x16, 	/* 305E0 */
+	0x94,  0x11,  0x54,  0x37,  0xD4,  0x51,  0x28,  0x15,  0x88,  0x15,  0x4C,  0x15,  0x14,  0x19,  0x22,  0x11, 	/* 305F0 */
+	0x41,  0x83,  0x02,  0x00,  0x01,  0x00,  0x00,  0x80,  0x00,  0x40,  0x02,  0x40,  0x02,  0x00,  0x12,  0x08, 	/* 30600 */
+	0x12,  0x04,  0x12,  0x02,  0x12,  0x02,  0x22,  0x09,  0x22,  0x09,  0x42,  0x08,  0x01,  0x08,  0x00,  0xF8, 	/* 30610 */
+	0x00,  0x00,  0x85,  0x01,  0x00,  0x00,  0x88,  0x00,  0x48,  0x02,  0x48,  0x02,  0x10,  0x02,  0x10,  0x12, 	/* 30620 */
+	0x24,  0x12,  0x22,  0x12,  0x42,  0x22,  0x81,  0x23,  0x01,  0x42,  0x04,  0x02,  0x04,  0x05,  0x04,  0x18, 	/* 30630 */
+	0xFC,  0x60,  0x00,  0x8C,  0x00,  0x00,  0x1F,  0xF0,  0x00,  0x10,  0x00,  0x10,  0x1F,  0xF0,  0x10,  0x00, 	/* 30640 */
+	0x10,  0x08,  0x10,  0x08,  0x0F,  0xF8,  0x00,  0x80,  0x12,  0x44,  0x12,  0x22,  0x12,  0x21,  0x22,  0x09, 	/* 30650 */
+	0x41,  0x08,  0x00,  0xF8,  0x8D,  0x00,  0x00,  0x3F,  0xF8,  0x00,  0x88,  0x18,  0x88,  0x05,  0x08,  0x02, 	/* 30660 */
+	0x08,  0x05,  0x08,  0x18,  0x88,  0x60,  0x30,  0x04,  0x80,  0x04,  0x40,  0x14,  0x48,  0x14,  0x04,  0x24, 	/* 30670 */
+	0x12,  0x42,  0x12,  0x01,  0xF0,  0x96,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x09,  0xFF,  0x0C,  0x08, 	/* 30680 */
+	0x2A,  0x08,  0x2A,  0x08,  0x28,  0x88,  0x28,  0x48,  0x48,  0x48,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08, 	/* 30690 */
+	0x08,  0x08,  0x08,  0x08,  0x08,  0x18,  0x97,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00, 	/* 306A0 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x02,  0x40,  0x12,  0x24,  0x12,  0x22,  0x12, 	/* 306B0 */
+	0x01,  0x22,  0x09,  0x41,  0x08,  0x00,  0xF8,  0x98,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF, 	/* 306C0 */
+	0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x03,  0xFC,  0x00,  0x80,  0x12,  0x40,  0x12,  0x24, 	/* 306D0 */
+	0x12,  0x22,  0x22,  0x09,  0x42,  0x09,  0x01,  0xF8,  0x99,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x0B, 	/* 306E0 */
+	0xFF,  0x08,  0x80,  0x2C,  0x80,  0x2A,  0x80,  0x2A,  0x80,  0x28,  0x80,  0x48,  0x80,  0x08,  0x80,  0x08, 	/* 306F0 */
+	0x80,  0x08,  0x80,  0x08,  0x40,  0x08,  0x3E,  0x08,  0x00,  0x9C,  0x00,  0x40,  0x00,  0x40,  0x1F,  0xFF, 	/* 30700 */
+	0x10,  0x80,  0x10,  0x40,  0x10,  0x20,  0x10,  0x90,  0x10,  0x90,  0x14,  0x84,  0x14,  0x82,  0x14,  0x81, 	/* 30710 */
+	0x24,  0x81,  0x28,  0x81,  0x28,  0x84,  0x50,  0x44,  0x00,  0x3C,  0x9D,  0x00,  0x08,  0x00,  0x70,  0x1F, 	/* 30720 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x40,  0x02,  0x20,  0x0D,  0x18,  0x71,  0x07,  0x01, 	/* 30730 */
+	0x48,  0x09,  0x24,  0x09,  0x12,  0x11,  0x12,  0x21,  0x00,  0x03,  0x00,  0xA0,  0x01,  0x00,  0x01,  0x00, 	/* 30740 */
+	0x1F,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x11,  0x08,  0x1F,  0xF8,  0x01,  0x00,  0x01,  0x00,  0x01,  0x40, 	/* 30750 */
+	0x12,  0x24,  0x12,  0x22,  0x22,  0x21,  0x22,  0x09,  0x41,  0x08,  0x00,  0xF8,  0xA4,  0x08,  0x80,  0x08, 	/* 30760 */
+	0x80,  0x08,  0xFE,  0x08,  0x90,  0x0D,  0x10,  0x2A,  0x10,  0x2A,  0x10,  0x2B,  0xFF,  0x28,  0x10,  0x48, 	/* 30770 */
+	0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0xAB,  0x08,  0x20, 	/* 30780 */
+	0x08,  0x20,  0x08,  0x20,  0x09,  0xFC,  0x2C,  0x24,  0x2A,  0x24,  0x2A,  0x24,  0x28,  0x24,  0x4B,  0xFF, 	/* 30790 */
+	0x08,  0x20,  0x08,  0x50,  0x08,  0x50,  0x08,  0x88,  0x08,  0x88,  0x09,  0x04,  0x0A,  0x02,  0xB0,  0x08, 	/* 307A0 */
+	0x40,  0x08,  0x40,  0x09,  0xF8,  0x08,  0x48,  0x2C,  0x48,  0x2A,  0x89,  0x28,  0x89,  0x29,  0x27,  0x4A, 	/* 307B0 */
+	0x20,  0x08,  0x20,  0x0B,  0xFF,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0xB1, 	/* 307C0 */
+	0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x09,  0xFF,  0x09,  0x21,  0x2D,  0x21,  0x2A,  0x20,  0x2A,  0x30, 	/* 307D0 */
+	0x28,  0x30,  0x48,  0x30,  0x08,  0x50,  0x08,  0x50,  0x08,  0x90,  0x09,  0x11,  0x0A,  0x09,  0x0C,  0x07, 	/* 307E0 */
+	0xB5,  0x00,  0x80,  0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x04,  0x10,  0x1B,  0xEC,  0x60,  0x03,  0x0F, 	/* 307F0 */
+	0xF0,  0x00,  0x20,  0x00,  0x40,  0x12,  0x80,  0x12,  0x48,  0x12,  0x24,  0x22,  0x2A,  0x41,  0x0A,  0x00, 	/* 30800 */
+	0xF8,  0xB8,  0x08,  0x00,  0x09,  0xFC,  0x08,  0x44,  0x08,  0x44,  0x08,  0x44,  0x2C,  0x44,  0x2A,  0x44, 	/* 30810 */
+	0x2B,  0xFF,  0x28,  0x44,  0x48,  0x44,  0x08,  0x44,  0x08,  0x44,  0x08,  0x44,  0x08,  0x44,  0x0B,  0xFF, 	/* 30820 */
+	0x08,  0x00,  0xBB,  0x08,  0x04,  0x08,  0x18,  0x08,  0xE0,  0x08,  0x80,  0x0C,  0x80,  0x2A,  0xFF,  0x2A, 	/* 30830 */
+	0x88,  0x28,  0x88,  0x28,  0x88,  0x48,  0x88,  0x08,  0x88,  0x08,  0x88,  0x09,  0x08,  0x09,  0x08,  0x0A, 	/* 30840 */
+	0x08,  0x08,  0x08,  0xBD,  0x02,  0x00,  0x02,  0x00,  0x07,  0xFE,  0x18,  0x92,  0x61,  0x12,  0x06,  0x22, 	/* 30850 */
+	0x18,  0x42,  0x01,  0x82,  0x06,  0x04,  0x18,  0x98,  0x00,  0x40,  0x12,  0x42,  0x12,  0x01,  0x22,  0x09, 	/* 30860 */
+	0x42,  0x08,  0x01,  0xF8,  0xBF,  0x01,  0xE0,  0x04,  0x20,  0x04,  0x10,  0x08,  0x08,  0x1F,  0xF4,  0x62, 	/* 30870 */
+	0x13,  0x02,  0x10,  0x04,  0x10,  0x08,  0x10,  0x30,  0xE0,  0x00,  0x40,  0x12,  0x24,  0x12,  0x22,  0x22, 	/* 30880 */
+	0x09,  0x41,  0x09,  0x00,  0xF8,  0x8E,  0x04,  0x00,  0x04,  0x00,  0x0F,  0xFE,  0x09,  0x00,  0x11,  0x00, 	/* 30890 */
+	0x21,  0xF8,  0x41,  0x00,  0x01,  0x00,  0x01,  0xF8,  0x01,  0x00,  0x01,  0x40,  0x12,  0x24,  0x12,  0x22, 	/* 308A0 */
+	0x22,  0x09,  0x41,  0x09,  0x00,  0xF8,  0x8F,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0xFE,  0x2C, 	/* 308B0 */
+	0x92,  0x2A,  0x92,  0x2A,  0x92,  0x28,  0x92,  0x48,  0x92,  0x0B,  0xFF,  0x08,  0x10,  0x08,  0x28,  0x08, 	/* 308C0 */
+	0x28,  0x08,  0x44,  0x08,  0x82,  0x0B,  0x01,  0x90,  0x08,  0x40,  0x08,  0x40,  0x08,  0x40,  0x08,  0xFE, 	/* 308D0 */
+	0x2C,  0x82,  0x2B,  0x02,  0x2A,  0xF2,  0x28,  0x92,  0x48,  0x92,  0x08,  0x92,  0x08,  0x92,  0x08,  0xF2, 	/* 308E0 */
+	0x08,  0x02,  0x08,  0x02,  0x08,  0x04,  0x08,  0x18,  0x92,  0x04,  0x00,  0x04,  0x00,  0x7F,  0xFE,  0x09, 	/* 308F0 */
+	0x22,  0x09,  0x14,  0x12,  0x08,  0x3E,  0x14,  0x05,  0x62,  0x18,  0x81,  0x60,  0x40,  0x00,  0x20,  0x12, 	/* 30900 */
+	0x24,  0x12,  0x02,  0x22,  0x09,  0x41,  0x09,  0x00,  0xF8,  0x95,  0x08,  0x10,  0x08,  0x10,  0x08,  0x20, 	/* 30910 */
+	0x08,  0xFE,  0x0C,  0x82,  0x2A,  0x82,  0x2A,  0x82,  0x28,  0x82,  0x28,  0xFE,  0x48,  0x82,  0x08,  0x82, 	/* 30920 */
+	0x08,  0x82,  0x08,  0x82,  0x08,  0x82,  0x08,  0xFE,  0x08,  0x00,  0x96,  0x08,  0x40,  0x08,  0x40,  0x08, 	/* 30930 */
+	0x40,  0x0B,  0xFF,  0x08,  0x40,  0x0C,  0x50,  0x2A,  0x90,  0x28,  0xFE,  0x29,  0x92,  0x49,  0x92,  0x0A, 	/* 30940 */
+	0x92,  0x08,  0x92,  0x08,  0x92,  0x08,  0x9C,  0x08,  0x10,  0x08,  0x10,  0x99,  0x08,  0x20,  0x08,  0x20, 	/* 30950 */
+	0x08,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x2C,  0x20,  0x2A,  0x20,  0x2A,  0x20,  0x48,  0x20,  0x09,  0xFC, 	/* 30960 */
+	0x09,  0x04,  0x09,  0x04,  0x09,  0x04,  0x09,  0x04,  0x09,  0xFC,  0x08,  0x00,  0x9B,  0x08,  0x00,  0x08, 	/* 30970 */
+	0xFC,  0x08,  0x84,  0x08,  0x84,  0x2C,  0x84,  0x2A,  0xFC,  0x2A,  0x84,  0x28,  0x84,  0x48,  0x84,  0x08, 	/* 30980 */
+	0x84,  0x08,  0xFC,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x0B,  0xFF,  0x08,  0x00,  0x9C,  0x08,  0x20, 	/* 30990 */
+	0x08,  0x20,  0x08,  0x50,  0x08,  0x88,  0x0D,  0x04,  0x2A,  0xFE,  0x2A,  0x01,  0x28,  0x00,  0x29,  0xFC, 	/* 309A0 */
+	0x48,  0x44,  0x08,  0x44,  0x08,  0x44,  0x08,  0x44,  0x08,  0x58,  0x08,  0x40,  0x08,  0x40,  0x9D,  0x00, 	/* 309B0 */
+	0x00,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x1F, 	/* 309C0 */
+	0xFC,  0x00,  0x80,  0x12,  0x40,  0x12,  0x24,  0x12,  0x22,  0x22,  0x09,  0x41,  0x09,  0x00,  0xF8,  0xA0, 	/* 309D0 */
+	0x01,  0x00,  0x01,  0x60,  0x02,  0x18,  0x04,  0xF4,  0x7F,  0x02,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08, 	/* 309E0 */
+	0x08,  0x08,  0x0F,  0xF8,  0x00,  0x80,  0x12,  0x44,  0x12,  0x42,  0x22,  0x09,  0x41,  0x09,  0x00,  0xF8, 	/* 309F0 */
+	0xA1,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x28,  0x2C,  0x44,  0x2A,  0x44,  0x2A,  0x8E,  0x2B, 	/* 30A00 */
+	0xF2,  0x48,  0x02,  0x08,  0x00,  0x09,  0xFC,  0x09,  0x04,  0x09,  0x04,  0x09,  0x04,  0x09,  0xFC,  0x08, 	/* 30A10 */
+	0x00,  0xA5,  0x01,  0x00,  0x03,  0xE0,  0x04,  0x40,  0x08,  0x80,  0x3F,  0xF8,  0x00,  0x08,  0x00,  0x08, 	/* 30A20 */
+	0x0F,  0xF8,  0x00,  0x08,  0x1F,  0xF8,  0x00,  0x80,  0x12,  0x44,  0x12,  0x42,  0x22,  0x49,  0x42,  0x09, 	/* 30A30 */
+	0x01,  0xF8,  0xA6,  0x08,  0x00,  0x0B,  0xFE,  0x08,  0x20,  0x08,  0x28,  0x2C,  0xA4,  0x2A,  0xA4,  0x29, 	/* 30A40 */
+	0x22,  0x2A,  0x20,  0x4B,  0xFF,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08, 	/* 30A50 */
+	0x20,  0x08,  0x20,  0xA7,  0x08,  0x20,  0x08,  0xA0,  0x08,  0xA0,  0x08,  0xA0,  0x09,  0xFE,  0x2D,  0x20, 	/* 30A60 */
+	0x2B,  0x20,  0x2A,  0x20,  0x48,  0x20,  0x09,  0xFC,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20, 	/* 30A70 */
+	0x0B,  0xFF,  0x08,  0x00,  0xA8,  0x08,  0x00,  0x0F,  0x7E,  0x09,  0x42,  0x11,  0x42,  0x32,  0x4C,  0x4A, 	/* 30A80 */
+	0x40,  0x04,  0x41,  0x08,  0x21,  0x10,  0x1F,  0x61,  0x00,  0x04,  0x80,  0x14,  0x44,  0x14,  0x42,  0x24, 	/* 30A90 */
+	0x09,  0x42,  0x09,  0x01,  0xF8,  0xA9,  0x08,  0x00,  0x09,  0xFE,  0x09,  0x02,  0x09,  0x02,  0x0D,  0xFE, 	/* 30AA0 */
+	0x2B,  0x00,  0x29,  0x40,  0x29,  0x44,  0x49,  0x48,  0x09,  0x70,  0x09,  0x40,  0x09,  0x40,  0x0A,  0x41, 	/* 30AB0 */
+	0x0A,  0x41,  0x0C,  0x21,  0x08,  0x1F,  0xAA,  0x08,  0x00,  0x0B,  0xFC,  0x08,  0x88,  0x08,  0x48,  0x08, 	/* 30AC0 */
+	0x50,  0x2C,  0x20,  0x2A,  0x50,  0x2A,  0x8C,  0x2B,  0x23,  0x48,  0x20,  0x09,  0xFC,  0x08,  0x20,  0x08, 	/* 30AD0 */
+	0x20,  0x08,  0x20,  0x0B,  0xFE,  0x08,  0x00,  0xAB,  0x10,  0x90,  0x10,  0x90,  0x17,  0xFE,  0x10,  0x92, 	/* 30AE0 */
+	0x30,  0x92,  0x3B,  0xFE,  0x36,  0x90,  0x52,  0x90,  0x53,  0xFE,  0x10,  0x92,  0x10,  0x92,  0x10,  0x92, 	/* 30AF0 */
+	0x10,  0x92,  0x11,  0x1C,  0x11,  0x10,  0x12,  0x10,  0xAF,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x09, 	/* 30B00 */
+	0xFC,  0x2C,  0x20,  0x2A,  0x20,  0x2A,  0x20,  0x28,  0x20,  0x4B,  0xFF,  0x08,  0x20,  0x08,  0x20,  0x08, 	/* 30B10 */
+	0x48,  0x08,  0x44,  0x08,  0xBC,  0x0B,  0xC2,  0x08,  0x02,  0xB1,  0x04,  0x00,  0x04,  0x00,  0x0F,  0xFC, 	/* 30B20 */
+	0x09,  0x24,  0x11,  0x24,  0x2F,  0x44,  0x44,  0xE4,  0x08,  0x94,  0x01,  0x08,  0x02,  0x30,  0x00,  0x80, 	/* 30B30 */
+	0x12,  0x44,  0x12,  0x42,  0x22,  0x09,  0x42,  0x09,  0x01,  0xF8,  0xBA,  0x08,  0x40,  0x08,  0x20,  0x08, 	/* 30B40 */
+	0x10,  0x08,  0x00,  0x0C,  0xE0,  0x2A,  0x22,  0x28,  0x22,  0x2B,  0xB4,  0x28,  0xB4,  0x48,  0xA8,  0x09, 	/* 30B50 */
+	0x28,  0x09,  0x24,  0x0A,  0x24,  0x0C,  0x22,  0x08,  0x21,  0x08,  0x60,  0x81,  0x04,  0x04,  0x04,  0x38, 	/* 30B60 */
+	0x0B,  0xE0,  0x08,  0x20,  0x10,  0x20,  0x37,  0xFF,  0x50,  0x20,  0x10,  0x20,  0x10,  0x20,  0x13,  0xFE, 	/* 30B70 */
+	0x10,  0x40,  0x12,  0x24,  0x12,  0x22,  0x22,  0x09,  0x41,  0x09,  0x00,  0xF8,  0x82,  0x08,  0x80,  0x08, 	/* 30B80 */
+	0x80,  0x08,  0xFE,  0x08,  0x82,  0x29,  0x02,  0x2D,  0xF2,  0x2A,  0x92,  0x2A,  0x92,  0x48,  0xF2,  0x08, 	/* 30B90 */
+	0x92,  0x08,  0x92,  0x08,  0x92,  0x08,  0xF2,  0x08,  0x02,  0x08,  0x04,  0x08,  0x18,  0x83,  0x08,  0x10, 	/* 30BA0 */
+	0x08,  0x10,  0x09,  0xFE,  0x08,  0x10,  0x2C,  0x10,  0x2A,  0x10,  0x2B,  0xFF,  0x28,  0x04,  0x48,  0x04, 	/* 30BB0 */
+	0x09,  0xFF,  0x08,  0x04,  0x08,  0x84,  0x08,  0x44,  0x08,  0x44,  0x08,  0x04,  0x08,  0x0C,  0x86,  0x08, 	/* 30BC0 */
+	0x00,  0x0B,  0xFF,  0x08,  0x40,  0x08,  0x40,  0x0C,  0x7C,  0x2A,  0x64,  0x2A,  0x94,  0x28,  0x94,  0x48, 	/* 30BD0 */
+	0xC4,  0x08,  0xA8,  0x09,  0x28,  0x09,  0x08,  0x08,  0x08,  0x08,  0x08,  0x0B,  0xFF,  0x08,  0x00,  0x8A, 	/* 30BE0 */
+	0x08,  0x40,  0x08,  0x40,  0x09,  0xFC,  0x08,  0x44,  0x2C,  0x44,  0x2A,  0x84,  0x2B,  0x18,  0x28,  0x00, 	/* 30BF0 */
+	0x49,  0x08,  0x0F,  0xFF,  0x09,  0x29,  0x09,  0x29,  0x09,  0x29,  0x0A,  0x31,  0x0C,  0x21,  0x08,  0xC6, 	/* 30C00 */
+	0x8B,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x20,  0x09,  0x28,  0x09,  0x24,  0x11,  0x24,  0x22, 	/* 30C10 */
+	0x22,  0x42,  0x62,  0x04,  0x00,  0x00,  0x80,  0x12,  0x44,  0x12,  0x42,  0x22,  0x09,  0x41,  0x09,  0x00, 	/* 30C20 */
+	0xF8,  0x8D,  0x08,  0x20,  0x08,  0x24,  0x09,  0x24,  0x08,  0xA4,  0x2C,  0xA8,  0x2A,  0x20,  0x2A,  0x20, 	/* 30C30 */
+	0x2B,  0xFF,  0x48,  0x50,  0x08,  0x50,  0x08,  0x50,  0x08,  0x90,  0x08,  0x90,  0x09,  0x11,  0x0A,  0x11, 	/* 30C40 */
+	0x0C,  0x0F,  0x90,  0x00,  0x00,  0x7F,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x11,  0x48,  0x15,  0x28,  0x19, 	/* 30C50 */
+	0x2A,  0x62,  0x0A,  0x04,  0x06,  0x01,  0x00,  0x04,  0x80,  0x14,  0x48,  0x14,  0x44,  0x24,  0x12,  0x42, 	/* 30C60 */
+	0x12,  0x01,  0xF0,  0x92,  0x08,  0x00,  0x09,  0xFE,  0x08,  0x00,  0x08,  0x00,  0x2C,  0xFC,  0x2A,  0x84, 	/* 30C70 */
+	0x2A,  0x84,  0x48,  0xFC,  0x08,  0x84,  0x08,  0x84,  0x08,  0x84,  0x08,  0xFC,  0x08,  0x00,  0x08,  0x00, 	/* 30C80 */
+	0x0B,  0xFF,  0x08,  0x00,  0x95,  0x04,  0x00,  0x04,  0x00,  0x7F,  0xFE,  0x09,  0x22,  0x09,  0x22,  0x11, 	/* 30C90 */
+	0x22,  0x3E,  0x22,  0x05,  0x3E,  0x18,  0x22,  0x61,  0x00,  0x00,  0x80,  0x12,  0x44,  0x12,  0x42,  0x22, 	/* 30CA0 */
+	0x09,  0x42,  0x09,  0x01,  0xF8,  0x99,  0x04,  0x08,  0x02,  0x10,  0x02,  0x20,  0x3F,  0xFE,  0x00,  0x80, 	/* 30CB0 */
+	0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x40,  0x12,  0x24,  0x12,  0x22, 	/* 30CC0 */
+	0x22,  0x09,  0x41,  0x09,  0x00,  0xF8,  0x9A,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00, 	/* 30CD0 */
+	0x80,  0x3F,  0xFE,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x40,  0x12, 	/* 30CE0 */
+	0x22,  0x12,  0x29,  0x22,  0x09,  0x41,  0xF8,  0x9F,  0x08,  0x80,  0x08,  0x80,  0x08,  0xFE,  0x08,  0x82, 	/* 30CF0 */
+	0x2D,  0x12,  0x2D,  0x12,  0x2A,  0x9A,  0x29,  0x6A,  0x49,  0x2A,  0x09,  0x5A,  0x09,  0x8A,  0x09,  0x0A, 	/* 30D00 */
+	0x09,  0xFA,  0x08,  0x02,  0x08,  0x04,  0x08,  0x18,  0xA0,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x0B, 	/* 30D10 */
+	0xFF,  0x08,  0x40,  0x0C,  0x48,  0x2A,  0xC8,  0x2A,  0x88,  0x28,  0xBE,  0x49,  0x88,  0x0A,  0x88,  0x0C, 	/* 30D20 */
+	0x88,  0x08,  0x88,  0x08,  0x88,  0x08,  0xFF,  0x08,  0x80,  0xA2,  0x08,  0x00,  0x09,  0xFF,  0x09,  0x00, 	/* 30D30 */
+	0x09,  0x10,  0x2D,  0x12,  0x2B,  0x52,  0x29,  0x54,  0x29,  0x54,  0x49,  0x50,  0x09,  0x90,  0x09,  0x18, 	/* 30D40 */
+	0x09,  0x28,  0x0A,  0x24,  0x0A,  0x44,  0x0D,  0x82,  0x0E,  0x01,  0xA3,  0x00,  0x80,  0x00,  0x80,  0x79, 	/* 30D50 */
+	0xFE,  0x01,  0x22,  0x02,  0x24,  0x04,  0x20,  0x00,  0x50,  0x18,  0x88,  0x63,  0x04,  0x0C,  0x43,  0x00, 	/* 30D60 */
+	0x20,  0x12,  0x24,  0x12,  0x02,  0x22,  0x09,  0x41,  0x09,  0x00,  0xF8,  0xA4,  0x08,  0x20,  0x08,  0x20, 	/* 30D70 */
+	0x08,  0x40,  0x08,  0x80,  0x2D,  0xFC,  0x2B,  0x54,  0x29,  0x54,  0x29,  0x54,  0x49,  0x54,  0x09,  0x54, 	/* 30D80 */
+	0x09,  0x54,  0x09,  0x54,  0x09,  0x54,  0x09,  0x54,  0x0B,  0xFF,  0x08,  0x00,  0xA5,  0x00,  0x00,  0x7F, 	/* 30D90 */
+	0xA0,  0x12,  0x10,  0x12,  0x08,  0x12,  0x28,  0x1E,  0x20,  0x12,  0x20,  0x12,  0x24,  0x1E,  0xA2,  0x12, 	/* 30DA0 */
+	0xA1,  0x12,  0xA1,  0x12,  0xA0,  0x1F,  0x22,  0x72,  0x22,  0x02,  0x1E,  0x02,  0x00,  0xA8,  0x08,  0x00, 	/* 30DB0 */
+	0x08,  0xFC,  0x08,  0x84,  0x08,  0x84,  0x2C,  0xFC,  0x2A,  0x84,  0x2A,  0x84,  0x28,  0xFC,  0x48,  0xC2, 	/* 30DC0 */
+	0x08,  0xA2,  0x08,  0xA4,  0x08,  0x98,  0x08,  0x88,  0x08,  0xA4,  0x08,  0xC2,  0x0B,  0x01,  0xA9,  0x00, 	/* 30DD0 */
+	0x00,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x11,  0x44,  0x12,  0x34,  0x1C,  0x0C,  0x1F, 	/* 30DE0 */
+	0xFC,  0x00,  0x80,  0x12,  0x40,  0x12,  0x24,  0x12,  0x22,  0x22,  0x09,  0x41,  0x09,  0x00,  0xF8,  0xAA, 	/* 30DF0 */
+	0x08,  0x40,  0x08,  0x40,  0x08,  0x7C,  0x08,  0x84,  0x2C,  0xC8,  0x2B,  0x28,  0x2A,  0x10,  0x28,  0x28, 	/* 30E00 */
+	0x48,  0x44,  0x08,  0x82,  0x09,  0xFD,  0x0A,  0x84,  0x08,  0x84,  0x08,  0x84,  0x08,  0xFC,  0x08,  0x00, 	/* 30E10 */
+	0xAB,  0x08,  0x00,  0x09,  0xFE,  0x09,  0x02,  0x09,  0x02,  0x2D,  0xFE,  0x2B,  0x02,  0x29,  0x02,  0x29, 	/* 30E20 */
+	0x7A,  0x49,  0x4A,  0x09,  0x4A,  0x09,  0x4A,  0x09,  0x7A,  0x09,  0x02,  0x09,  0x02,  0x09,  0x02,  0x09, 	/* 30E30 */
+	0x06,  0xAC,  0x08,  0x08,  0x08,  0x30,  0x09,  0xE0,  0x0C,  0x20,  0x2A,  0x20,  0x28,  0x20,  0x2B,  0xFF, 	/* 30E40 */
+	0x28,  0x20,  0x48,  0x20,  0x08,  0x20,  0x09,  0xFC,  0x09,  0x04,  0x09,  0x04,  0x09,  0x04,  0x09,  0xFC, 	/* 30E50 */
+	0x08,  0x00,  0xAD,  0x02,  0x20,  0x02,  0x20,  0x1F,  0xFC,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x7F, 	/* 30E60 */
+	0xFF,  0x04,  0x10,  0x09,  0x08,  0x11,  0x04,  0x61,  0x03,  0x09,  0x48,  0x09,  0x24,  0x11,  0x24,  0x21, 	/* 30E70 */
+	0x00,  0x03,  0x00,  0xAF,  0x01,  0x00,  0x02,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10, 	/* 30E80 */
+	0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x24,  0x84,  0x24,  0x42,  0x24,  0x49, 	/* 30E90 */
+	0x42,  0x09,  0x01,  0xF8,  0xB0,  0x08,  0x20,  0x08,  0x20,  0x08,  0x50,  0x08,  0x50,  0x0C,  0x88,  0x2A, 	/* 30EA0 */
+	0x84,  0x29,  0x02,  0x2A,  0xFD,  0x4C,  0x00,  0x08,  0x00,  0x08,  0xFC,  0x08,  0x84,  0x08,  0x84,  0x08, 	/* 30EB0 */
+	0x84,  0x08,  0xFC,  0x08,  0x00,  0xB5,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x1F,  0xFC, 	/* 30EC0 */
+	0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x10,  0x84,  0x1F,  0xFC,  0x00,  0x40,  0x12,  0x24,  0x12,  0x22, 	/* 30ED0 */
+	0x22,  0x09,  0x41,  0x09,  0x00,  0xF8,  0xB7,  0x04,  0x20,  0x04,  0x20,  0x08,  0x20,  0x17,  0xFF,  0x30, 	/* 30EE0 */
+	0x70,  0x50,  0xA8,  0x11,  0x24,  0x12,  0x22,  0x14,  0x21,  0x10,  0x20,  0x00,  0x80,  0x12,  0x44,  0x12, 	/* 30EF0 */
+	0x42,  0x22,  0x09,  0x42,  0x09,  0x01,  0xF8,  0x81,  0x08,  0x00,  0x08,  0xFE,  0x08,  0x82,  0x08,  0x82, 	/* 30F00 */
+	0x2C,  0xFE,  0x2A,  0x00,  0x2A,  0xFE,  0x28,  0x82,  0x48,  0x82,  0x08,  0xFE,  0x08,  0x82,  0x08,  0x82, 	/* 30F10 */
+	0x08,  0xFE,  0x08,  0x82,  0x08,  0x82,  0x08,  0x86,  0x83,  0x08,  0x00,  0x0B,  0xFE,  0x0A,  0x22,  0x0A, 	/* 30F20 */
+	0x22,  0x2E,  0x22,  0x2B,  0xFE,  0x2A,  0x22,  0x2A,  0x72,  0x4A,  0x72,  0x0A,  0xAA,  0x0A,  0xAA,  0x0B, 	/* 30F30 */
+	0x26,  0x0A,  0x22,  0x0A,  0x02,  0x0B,  0xFE,  0x08,  0x00,  0x84,  0x08,  0x10,  0x08,  0x54,  0x08,  0x52, 	/* 30F40 */
+	0x08,  0x92,  0x2D,  0x10,  0x2A,  0xFE,  0x2A,  0x82,  0x28,  0x82,  0x48,  0xFE,  0x08,  0x82,  0x08,  0x82, 	/* 30F50 */
+	0x08,  0xFE,  0x08,  0x82,  0x08,  0x82,  0x08,  0x82,  0x08,  0x86,  0x89,  0x00,  0x08,  0x00,  0x70,  0x3F, 	/* 30F60 */
+	0x88,  0x08,  0x88,  0x04,  0x90,  0x7F,  0xFF,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x02, 	/* 30F70 */
+	0x40,  0x12,  0x24,  0x12,  0x22,  0x22,  0x09,  0x41,  0x09,  0x00,  0xF8,  0x8B,  0x08,  0x20,  0x08,  0x20, 	/* 30F80 */
+	0x0B,  0xFF,  0x08,  0x88,  0x2C,  0x88,  0x2A,  0x50,  0x28,  0x20,  0x28,  0x50,  0x49,  0x8C,  0x0E,  0x03, 	/* 30F90 */
+	0x09,  0xFC,  0x09,  0x04,  0x09,  0x04,  0x09,  0x04,  0x09,  0xFC,  0x08,  0x00,  0x8C,  0x08,  0x84,  0x08, 	/* 30FA0 */
+	0x48,  0x0B,  0xFE,  0x08,  0x22,  0x2C,  0x22,  0x2B,  0xFE,  0x29,  0x20,  0x29,  0x20,  0x49,  0xFE,  0x08, 	/* 30FB0 */
+	0x22,  0x08,  0x62,  0x08,  0xA2,  0x09,  0x22,  0x0E,  0x3C,  0x08,  0x20,  0x08,  0x20,  0x8D,  0x08,  0x00, 	/* 30FC0 */
+	0x09,  0xFC,  0x09,  0x04,  0x09,  0xFC,  0x2D,  0x04,  0x2B,  0x04,  0x29,  0xFC,  0x28,  0x00,  0x4B,  0xFE, 	/* 30FD0 */
+	0x08,  0x20,  0x08,  0x20,  0x0F,  0xFF,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x92,  0x08, 	/* 30FE0 */
+	0x00,  0x08,  0xFC,  0x08,  0x84,  0x08,  0x84,  0x2C,  0xFC,  0x2A,  0x00,  0x29,  0xFE,  0x29,  0x22,  0x49, 	/* 30FF0 */
+	0x22,  0x09,  0x22,  0x09,  0xFE,  0x09,  0x00,  0x09,  0x01,  0x09,  0x01,  0x08,  0xFF,  0x08,  0x00,  0x94, 	/* 31000 */
+	0x09,  0x00,  0x09,  0x00,  0x09,  0xFE,  0x09,  0x00,  0x2A,  0x00,  0x2A,  0xFC,  0x2C,  0xA4,  0x2C,  0xA4, 	/* 31010 */
+	0x4B,  0xFF,  0x09,  0x24,  0x09,  0x24,  0x09,  0x24,  0x0B,  0xFF,  0x0A,  0x04,  0x08,  0x08,  0x08,  0x30, 	/* 31020 */
+	0x96,  0x08,  0x10,  0x08,  0x10,  0x0B,  0xFF,  0x08,  0x10,  0x0C,  0x10,  0x2B,  0xFF,  0x29,  0x01,  0x29, 	/* 31030 */
+	0x01,  0x48,  0xFE,  0x08,  0x04,  0x08,  0x08,  0x0B,  0xFF,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08, 	/* 31040 */
+	0x30,  0x97,  0x08,  0x40,  0x08,  0x7C,  0x08,  0x48,  0x08,  0x88,  0x2D,  0x10,  0x2B,  0xFE,  0x29,  0x22, 	/* 31050 */
+	0x29,  0x22,  0x49,  0x42,  0x09,  0xFE,  0x08,  0x50,  0x08,  0x50,  0x08,  0x90,  0x08,  0x91,  0x09,  0x11, 	/* 31060 */
+	0x0A,  0x0F,  0x9A,  0x08,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x08,  0x20,  0x2D,  0xFC,  0x2B,  0x24,  0x2B, 	/* 31070 */
+	0x24,  0x29,  0x24,  0x49,  0xFC,  0x08,  0x70,  0x08,  0x68,  0x08,  0xA4,  0x09,  0x22,  0x0A,  0x21,  0x0C, 	/* 31080 */
+	0x20,  0x08,  0x20,  0x9B,  0x08,  0x40,  0x08,  0x50,  0x08,  0x8C,  0x0B,  0xFA,  0x08,  0x50,  0x2C,  0x51, 	/* 31090 */
+	0x2A,  0x8F,  0x2B,  0x20,  0x48,  0x78,  0x08,  0x88,  0x0B,  0x50,  0x08,  0x30,  0x08,  0x20,  0x08,  0xD0, 	/* 310A0 */
+	0x0B,  0x0C,  0x0C,  0x03,  0x9F,  0x08,  0x00,  0x0B,  0xFE,  0x08,  0x20,  0x08,  0x20,  0x2D,  0xF8,  0x2A, 	/* 310B0 */
+	0x48,  0x2A,  0x48,  0x28,  0x48,  0x4B,  0xFF,  0x08,  0x00,  0x09,  0xFC,  0x09,  0x04,  0x09,  0x04,  0x09, 	/* 310C0 */
+	0x04,  0x09,  0xFC,  0x08,  0x00,  0xA0,  0x04,  0x20,  0x04,  0x20,  0x08,  0x7F,  0x0A,  0x44,  0x12,  0xC4, 	/* 310D0 */
+	0x33,  0x28,  0x52,  0x10,  0x12,  0x28,  0x10,  0x44,  0x11,  0x83,  0x04,  0x80,  0x14,  0x44,  0x14,  0x42, 	/* 310E0 */
+	0x24,  0x09,  0x42,  0x09,  0x01,  0xF8,  0xA3,  0x01,  0x00,  0x01,  0x00,  0x3F,  0xF8,  0x21,  0x08,  0x3F, 	/* 310F0 */
+	0xF8,  0x01,  0x00,  0x3F,  0xF8,  0x21,  0x08,  0x3F,  0xF8,  0x01,  0x00,  0x01,  0x00,  0x14,  0x88,  0x14, 	/* 31100 */
+	0x84,  0x24,  0x12,  0x42,  0x12,  0x01,  0xF0,  0xA6,  0x08,  0x84,  0x08,  0x44,  0x08,  0x48,  0x08,  0xFC, 	/* 31110 */
+	0x2C,  0x84,  0x2A,  0x84,  0x2A,  0x84,  0x28,  0x84,  0x48,  0xFC,  0x08,  0x50,  0x08,  0x50,  0x08,  0x50, 	/* 31120 */
+	0x08,  0x90,  0x08,  0x92,  0x09,  0x12,  0x0A,  0x0E,  0xA7,  0x10,  0x22,  0x10,  0xC2,  0x13,  0x92,  0x10, 	/* 31130 */
+	0x92,  0x18,  0x92,  0x37,  0xF2,  0x34,  0x92,  0x30,  0x92,  0x51,  0xD2,  0x51,  0xB2,  0x12,  0x92,  0x12, 	/* 31140 */
+	0x82,  0x14,  0x82,  0x10,  0x82,  0x10,  0x82,  0x10,  0x86,  0xA9,  0x08,  0x42,  0x09,  0x22,  0x08,  0xA4, 	/* 31150 */
+	0x08,  0xA4,  0x2C,  0x88,  0x2A,  0x00,  0x2B,  0x0A,  0x29,  0x0A,  0x49,  0xCA,  0x09,  0x32,  0x09,  0x12, 	/* 31160 */
+	0x09,  0x2A,  0x09,  0x4A,  0x09,  0x82,  0x09,  0xFE,  0x08,  0x00,  0xAA,  0x00,  0x00,  0x3F,  0xFE,  0x02, 	/* 31170 */
+	0x40,  0x02,  0x40,  0x1F,  0xF8,  0x12,  0x48,  0x12,  0x48,  0x1F,  0xF8,  0x02,  0x40,  0x7F,  0xFE,  0x00, 	/* 31180 */
+	0x80,  0x12,  0x48,  0x12,  0x44,  0x22,  0x12,  0x42,  0x12,  0x01,  0xF0,  0xB2,  0x02,  0x20,  0x02,  0x20, 	/* 31190 */
+	0x7E,  0x3F,  0x02,  0x20,  0x3E,  0x3E,  0x02,  0x20,  0x0E,  0x20,  0x72,  0x3F,  0x02,  0x20,  0x04,  0x20, 	/* 311A0 */
+	0x08,  0x80,  0x12,  0x48,  0x12,  0x44,  0x22,  0x0A,  0x41,  0x0A,  0x00,  0xF8,  0xB3,  0x00,  0x80,  0x7F, 	/* 311B0 */
+	0xFF,  0x00,  0x80,  0x07,  0xF8,  0x24,  0x08,  0x27,  0xF8,  0x24,  0x08,  0x27,  0xF8,  0x24,  0x08,  0x27, 	/* 311C0 */
+	0xF8,  0x3F,  0xFF,  0x02,  0x80,  0x12,  0x44,  0x12,  0x52,  0x22,  0x11,  0x41,  0xF1,  0xB4,  0x08,  0x20, 	/* 311D0 */
+	0x08,  0x20,  0x0B,  0xFE,  0x08,  0x00,  0x2C,  0x88,  0x2A,  0x88,  0x2A,  0xCC,  0x29,  0x32,  0x4A,  0x20, 	/* 311E0 */
+	0x08,  0x20,  0x0B,  0xFF,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0xB5,  0x08, 	/* 311F0 */
+	0x00,  0x08,  0xFE,  0x08,  0x80,  0x08,  0xFC,  0x2C,  0x80,  0x2A,  0xFC,  0x2A,  0x80,  0x28,  0x80,  0x4B, 	/* 31200 */
+	0xFF,  0x08,  0xA2,  0x08,  0x92,  0x08,  0x94,  0x08,  0x88,  0x08,  0x84,  0x08,  0xE2,  0x0B,  0x01,  0xB6, 	/* 31210 */
+	0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42,  0x42,  0x42,  0x7E,  0x7E,  0x41,  0x02, 	/* 31220 */
+	0x42,  0x82,  0x42,  0x92,  0x4A,  0x0A,  0x4A,  0x2A,  0x4A,  0x22,  0x51,  0xE2,  0x40,  0x02,  0x40,  0x06, 	/* 31230 */
+	0xB8,  0x08,  0x04,  0x08,  0x18,  0x09,  0xE0,  0x08,  0x20,  0x2D,  0xFF,  0x2A,  0x70,  0x28,  0xAC,  0x2B, 	/* 31240 */
+	0x23,  0x48,  0x20,  0x09,  0xFC,  0x08,  0x10,  0x08,  0x20,  0x0B,  0xFF,  0x08,  0x20,  0x08,  0x20,  0x08, 	/* 31250 */
+	0x60,  0xBC,  0x08,  0x20,  0x08,  0x20,  0x08,  0x3F,  0x08,  0x20,  0x2C,  0xFC,  0x2A,  0x84,  0x2A,  0x84, 	/* 31260 */
+	0x28,  0xFC,  0x48,  0x84,  0x08,  0x84,  0x08,  0xFC,  0x08,  0x20,  0x0B,  0xFF,  0x08,  0x20,  0x08,  0x20, 	/* 31270 */
+	0x08,  0x20,  0xBD,  0x08,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x08,  0x20,  0x2D,  0xFC,  0x2A,  0x24,  0x2B, 	/* 31280 */
+	0xFF,  0x28,  0x24,  0x49,  0xFC,  0x08,  0x20,  0x0B,  0xFF,  0x08,  0x48,  0x08,  0x88,  0x09,  0xF0,  0x08, 	/* 31290 */
+	0x68,  0x0B,  0x84,  0x85,  0x08,  0x20,  0x08,  0x20,  0x0B,  0xFE,  0x08,  0x20,  0x0D,  0xFC,  0x2A,  0x20, 	/* 312A0 */
+	0x2B,  0xFF,  0x28,  0x00,  0x28,  0xFC,  0x48,  0x84,  0x08,  0xFC,  0x08,  0x84,  0x08,  0xFC,  0x08,  0x84, 	/* 312B0 */
+	0x08,  0x84,  0x08,  0x8C,  0x86,  0x08,  0x00,  0x09,  0xFE,  0x09,  0x22,  0x09,  0x22,  0x29,  0x7A,  0x2D, 	/* 312C0 */
+	0x22,  0x2B,  0x22,  0x29,  0xFE,  0x49,  0x22,  0x09,  0x7A,  0x09,  0x4A,  0x09,  0x4A,  0x09,  0x7A,  0x09, 	/* 312D0 */
+	0x02,  0x09,  0x02,  0x0A,  0x06,  0x87,  0x08,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x08,  0x00,  0x0C,  0xFC, 	/* 312E0 */
+	0x2A,  0x84,  0x2A,  0xFC,  0x28,  0x00,  0x49,  0xFC,  0x08,  0x08,  0x08,  0x10,  0x0B,  0xFF,  0x08,  0x10, 	/* 312F0 */
+	0x08,  0x10,  0x08,  0x10,  0x08,  0x30,  0x91,  0x00,  0x48,  0x00,  0x44,  0x7F,  0xFF,  0x00,  0x40,  0x1F, 	/* 31300 */
+	0x44,  0x11,  0x24,  0x11,  0x28,  0x1F,  0x12,  0x07,  0xAA,  0x78,  0x46,  0x02,  0x82,  0x12,  0x44,  0x12, 	/* 31310 */
+	0x42,  0x22,  0x09,  0x41,  0x09,  0x00,  0xF8,  0x93,  0x08,  0xA8,  0x08,  0xA4,  0x09,  0x24,  0x0B,  0xFE, 	/* 31320 */
+	0x28,  0x20,  0x2C,  0x50,  0x2B,  0xFF,  0x28,  0x48,  0x48,  0x84,  0x09,  0xFA,  0x0A,  0x89,  0x08,  0x88, 	/* 31330 */
+	0x08,  0xB0,  0x08,  0x84,  0x08,  0x84,  0x08,  0x7C,  0x98,  0x08,  0x00,  0x09,  0xFE,  0x09,  0x0A,  0x09, 	/* 31340 */
+	0x4A,  0x29,  0x32,  0x2D,  0xFE,  0x2B,  0x22,  0x29,  0x22,  0x49,  0xFE,  0x09,  0x42,  0x09,  0x42,  0x09, 	/* 31350 */
+	0x42,  0x09,  0x3A,  0x09,  0x02,  0x09,  0x02,  0x09,  0x06,  0x9A,  0x08,  0x80,  0x08,  0x80,  0x08,  0xFE, 	/* 31360 */
+	0x08,  0xAA,  0x2D,  0x2A,  0x2A,  0x4A,  0x2A,  0x92,  0x28,  0x22,  0x48,  0x4C,  0x08,  0x20,  0x08,  0x90, 	/* 31370 */
+	0x0A,  0x94,  0x0A,  0x82,  0x0A,  0x89,  0x0C,  0x89,  0x08,  0x78,  0x9C,  0x08,  0x48,  0x08,  0x48,  0x09, 	/* 31380 */
+	0xFE,  0x08,  0x48,  0x0C,  0x48,  0x2A,  0x48,  0x2B,  0xFF,  0x28,  0x00,  0x48,  0xFC,  0x08,  0x84,  0x08, 	/* 31390 */
+	0x84,  0x08,  0xFC,  0x08,  0x84,  0x08,  0x84,  0x08,  0xFC,  0x08,  0x00,  0x9F,  0x08,  0x40,  0x08,  0x48, 	/* 313A0 */
+	0x08,  0x48,  0x08,  0x90,  0x0C,  0xFE,  0x2A,  0x90,  0x2B,  0x90,  0x28,  0xFE,  0x48,  0x90,  0x08,  0x90, 	/* 313B0 */
+	0x08,  0xFE,  0x08,  0x90,  0x08,  0x90,  0x08,  0x90,  0x08,  0xFF,  0x08,  0x80,  0xA0,  0x01,  0x00,  0x7F, 	/* 313C0 */
+	0xFE,  0x01,  0x00,  0x1F,  0xF8,  0x11,  0x08,  0x1F,  0xF8,  0x11,  0x08,  0x1F,  0xF8,  0x01,  0x18,  0x01, 	/* 313D0 */
+	0xF4,  0x7E,  0x82,  0x10,  0x44,  0x12,  0x42,  0x22,  0x09,  0x42,  0x09,  0x01,  0xF8,  0xA1,  0x00,  0x00, 	/* 313E0 */
+	0x7F,  0xFF,  0x02,  0x20,  0x02,  0x20,  0x1E,  0x3C,  0x10,  0x04,  0x10,  0x04,  0x1E,  0x3C,  0x02,  0x20, 	/* 313F0 */
+	0x7F,  0xFF,  0x00,  0x80,  0x12,  0x44,  0x12,  0x42,  0x22,  0x09,  0x41,  0x09,  0x00,  0xF8,  0xA3,  0x08, 	/* 31400 */
+	0x80,  0x28,  0x80,  0x3E,  0xFE,  0x29,  0x2A,  0x4A,  0x2A,  0x08,  0x4A,  0x0E,  0x92,  0x79,  0x12,  0x08, 	/* 31410 */
+	0x22,  0x08,  0x4C,  0x08,  0xC0,  0x12,  0x20,  0x12,  0x22,  0x12,  0x09,  0x21,  0x09,  0x40,  0xF8,  0xA7, 	/* 31420 */
+	0x08,  0x00,  0x08,  0xFC,  0x08,  0x84,  0x08,  0x84,  0x2C,  0xFC,  0x2A,  0x84,  0x2A,  0x84,  0x28,  0xFC, 	/* 31430 */
+	0x48,  0x84,  0x08,  0x84,  0x08,  0xFC,  0x08,  0x84,  0x0B,  0xFF,  0x08,  0x28,  0x08,  0xC4,  0x0B,  0x02, 	/* 31440 */
+	0xA8,  0x08,  0x20,  0x08,  0x28,  0x08,  0x44,  0x09,  0xFA,  0x0C,  0x20,  0x2B,  0xFF,  0x28,  0x48,  0x28, 	/* 31450 */
+	0x84,  0x4B,  0x12,  0x08,  0x61,  0x09,  0x88,  0x08,  0x32,  0x09,  0xC4,  0x08,  0x18,  0x08,  0x60,  0x0B, 	/* 31460 */
+	0x80,  0xB0,  0x08,  0x20,  0x08,  0x20,  0x09,  0xFF,  0x08,  0x40,  0x2C,  0x7E,  0x2A,  0x90,  0x29,  0xFF, 	/* 31470 */
+	0x2A,  0x00,  0x48,  0xFE,  0x08,  0x82,  0x08,  0xFE,  0x08,  0x82,  0x08,  0xFE,  0x08,  0x82,  0x08,  0x82, 	/* 31480 */
+	0x08,  0x86,  0xB1,  0x08,  0x92,  0x08,  0x92,  0x0B,  0x6C,  0x09,  0x24,  0x2C,  0x92,  0x2A,  0x92,  0x2A, 	/* 31490 */
+	0x20,  0x29,  0xFE,  0x49,  0x0A,  0x09,  0x4A,  0x09,  0x32,  0x09,  0x2A,  0x09,  0x4A,  0x09,  0x82,  0x09, 	/* 314A0 */
+	0xFE,  0x08,  0x00,  0xB3,  0x04,  0x00,  0x04,  0x7E,  0x7F,  0xC2,  0x04,  0x7E,  0x0C,  0x42,  0x0E,  0x42, 	/* 314B0 */
+	0x15,  0x7E,  0x24,  0x42,  0x44,  0x42,  0x04,  0xFE,  0x02,  0x40,  0x12,  0x24,  0x12,  0x22,  0x22,  0x09, 	/* 314C0 */
+	0x41,  0x09,  0x00,  0xF8,  0xB4,  0x08,  0x20,  0x09,  0x22,  0x09,  0x22,  0x09,  0x22,  0x0D,  0xFE,  0x2A, 	/* 314D0 */
+	0x00,  0x2B,  0xFF,  0x28,  0x20,  0x48,  0x40,  0x09,  0xFE,  0x09,  0x52,  0x09,  0x52,  0x09,  0x52,  0x09, 	/* 314E0 */
+	0x52,  0x09,  0x52,  0x09,  0x06,  0xB6,  0x08,  0x20,  0x08,  0x40,  0x09,  0xFC,  0x09,  0x04,  0x2D,  0xFC, 	/* 314F0 */
+	0x2B,  0x04,  0x29,  0x04,  0x29,  0xFC,  0x48,  0x00,  0x0B,  0xFE,  0x08,  0x20,  0x09,  0xFC,  0x08,  0x20, 	/* 31500 */
+	0x08,  0x20,  0x0F,  0xFF,  0x08,  0x00,  0xB7,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80,  0x1F,  0xFC,  0x01, 	/* 31510 */
+	0x40,  0x7F,  0xFF,  0x02,  0x20,  0x0F,  0xF8,  0x74,  0x17,  0x07,  0xF0,  0x04,  0x10,  0x17,  0xF0,  0x12, 	/* 31520 */
+	0x42,  0x22,  0x21,  0x42,  0x09,  0x01,  0xF8,  0xB9,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10, 	/* 31530 */
+	0x01,  0x00,  0x7F,  0xFE,  0x02,  0x00,  0x07,  0xF8,  0x1C,  0x08,  0x64,  0x08,  0x07,  0xF8,  0x12,  0x44, 	/* 31540 */
+	0x12,  0x22,  0x22,  0x29,  0x42,  0x09,  0x01,  0xF8,  0xBA,  0x08,  0x00,  0x09,  0xFC,  0x09,  0x04,  0x09, 	/* 31550 */
+	0xFC,  0x2D,  0x04,  0x2B,  0x04,  0x29,  0xFC,  0x28,  0xA0,  0x48,  0xA0,  0x09,  0xFE,  0x0A,  0x20,  0x0B, 	/* 31560 */
+	0xFC,  0x08,  0x20,  0x08,  0x20,  0x0F,  0xFF,  0x08,  0x00,  0xBB,  0x10,  0x02,  0x13,  0xD2,  0x12,  0x52, 	/* 31570 */
+	0x12,  0x52,  0x33,  0xD2,  0x3A,  0x52,  0x36,  0x52,  0x52,  0x52,  0x53,  0xD2,  0x12,  0x52,  0x12,  0x52, 	/* 31580 */
+	0x13,  0xD2,  0x11,  0x42,  0x11,  0x22,  0x12,  0x02,  0x14,  0x06,  0x80,  0x10,  0x48,  0x11,  0x88,  0x17, 	/* 31590 */
+	0x08,  0x11,  0x0A,  0x19,  0x2A,  0x37,  0xEC,  0x31,  0x2C,  0x31,  0x48,  0x53,  0x88,  0x13,  0x54,  0x15, 	/* 315A0 */
+	0x54,  0x15,  0x14,  0x19,  0x24,  0x11,  0x22,  0x11,  0x22,  0x11,  0x41,  0x81,  0x01,  0x10,  0x06,  0x10, 	/* 315B0 */
+	0x3C,  0x12,  0x04,  0x52,  0x7F,  0x54,  0x04,  0xA8,  0x0E,  0x28,  0x15,  0x44,  0x24,  0x82,  0x45,  0x01, 	/* 315C0 */
+	0x14,  0x80,  0x14,  0x48,  0x14,  0x44,  0x24,  0x12,  0x42,  0x12,  0x01,  0xF0,  0x83,  0x08,  0x20,  0x08, 	/* 315D0 */
+	0x20,  0x0B,  0xFF,  0x0A,  0x01,  0x2A,  0xFD,  0x2C,  0x00,  0x2A,  0xFC,  0x28,  0x84,  0x48,  0x84,  0x08, 	/* 315E0 */
+	0xFC,  0x08,  0x84,  0x08,  0x84,  0x08,  0xFC,  0x08,  0x00,  0x0B,  0xFF,  0x08,  0x00,  0x86,  0x09,  0x00, 	/* 315F0 */
+	0x08,  0xBE,  0x10,  0x80,  0x26,  0x00,  0x45,  0x7F,  0x09,  0x04,  0x10,  0x44,  0x30,  0x84,  0x50,  0x84, 	/* 31600 */
+	0x11,  0x04,  0x12,  0x8C,  0x00,  0x40,  0x12,  0x42,  0x12,  0x09,  0x22,  0x09,  0x41,  0xF8,  0x88,  0x00, 	/* 31610 */
+	0x80,  0x01,  0x40,  0x02,  0x20,  0x0F,  0xF8,  0x70,  0x07,  0x1F,  0x04,  0x11,  0x24,  0x1F,  0x24,  0x11, 	/* 31620 */
+	0x24,  0x1F,  0x24,  0x11,  0x04,  0x13,  0x8C,  0x02,  0x44,  0x12,  0x42,  0x22,  0x11,  0x41,  0xF1,  0x89, 	/* 31630 */
+	0x08,  0x20,  0x08,  0x20,  0x08,  0x50,  0x08,  0x48,  0x0C,  0x84,  0x2B,  0x7A,  0x2A,  0x01,  0x29,  0xE2, 	/* 31640 */
+	0x49,  0x2A,  0x09,  0xEA,  0x09,  0x2A,  0x09,  0xEA,  0x09,  0x2A,  0x09,  0x22,  0x09,  0x22,  0x09,  0x66, 	/* 31650 */
+	0x8D,  0x00,  0x20,  0x3F,  0x20,  0x21,  0x3F,  0x21,  0x24,  0x3F,  0x54,  0x28,  0x94,  0x3F,  0x08,  0x24, 	/* 31660 */
+	0x08,  0x22,  0x94,  0x39,  0xA2,  0x60,  0xC1,  0x12,  0x24,  0x12,  0x22,  0x22,  0x09,  0x42,  0x09,  0x01, 	/* 31670 */
+	0xF8,  0x8E,  0x08,  0x40,  0x08,  0x40,  0x08,  0xFF,  0x08,  0x80,  0x2D,  0xFC,  0x2A,  0x84,  0x2A,  0xFC, 	/* 31680 */
+	0x28,  0x84,  0x48,  0xFC,  0x08,  0x20,  0x08,  0x7C,  0x08,  0x88,  0x0B,  0x50,  0x08,  0x30,  0x08,  0xCC, 	/* 31690 */
+	0x0F,  0x03,  0x8F,  0x00,  0x80,  0x3F,  0xFE,  0x04,  0x10,  0x02,  0x20,  0x7F,  0xFF,  0x00,  0x00,  0x07, 	/* 316A0 */
+	0xF8,  0x04,  0x08,  0x07,  0xF8,  0x04,  0x08,  0x07,  0xF8,  0x12,  0x80,  0x12,  0x42,  0x22,  0x49,  0x42, 	/* 316B0 */
+	0x09,  0x01,  0xF8,  0x95,  0x08,  0x00,  0x0B,  0xDE,  0x0A,  0x52,  0x0A,  0x52,  0x0B,  0xDE,  0x2C,  0x00, 	/* 316C0 */
+	0x2B,  0xFC,  0x28,  0x00,  0x4B,  0xFF,  0x08,  0x40,  0x08,  0x40,  0x08,  0xFC,  0x08,  0x84,  0x08,  0x04, 	/* 316D0 */
+	0x08,  0x04,  0x08,  0x18,  0x9A,  0x00,  0x00,  0x1F,  0xF0,  0x11,  0x10,  0x1F,  0xF0,  0x11,  0x10,  0x1F, 	/* 316E0 */
+	0xF0,  0x01,  0x00,  0x7F,  0xFC,  0x41,  0x34,  0x41,  0xEC,  0x5E,  0x04,  0x40,  0x8C,  0x14,  0x40,  0x14, 	/* 316F0 */
+	0x54,  0x24,  0x12,  0x43,  0xF2,  0x9B,  0x00,  0x3C,  0x1F,  0xC8,  0x11,  0x08,  0x08,  0x90,  0x7F,  0xFE, 	/* 31700 */
+	0x44,  0x82,  0x54,  0x48,  0x14,  0x14,  0x23,  0xF2,  0x42,  0x02,  0x07,  0xE0,  0x0C,  0x20,  0x33,  0x40, 	/* 31710 */
+	0x01,  0x80,  0x06,  0x70,  0x78,  0x0E,  0x9F,  0x00,  0x48,  0x00,  0x44,  0x1F,  0xFF,  0x10,  0x40,  0x1F, 	/* 31720 */
+	0xA4,  0x10,  0x24,  0x17,  0x98,  0x14,  0x90,  0x17,  0xAA,  0x20,  0x46,  0x40,  0x82,  0x12,  0x44,  0x12, 	/* 31730 */
+	0x42,  0x22,  0x09,  0x41,  0x09,  0x00,  0xF8,  0xA1,  0x08,  0x80,  0x08,  0x80,  0x08,  0xFE,  0x09,  0x4A, 	/* 31740 */
+	0x2B,  0x4A,  0x2C,  0xD2,  0x29,  0x32,  0x2A,  0x2A,  0x48,  0x42,  0x08,  0x0C,  0x08,  0xA0,  0x0A,  0x90, 	/* 31750 */
+	0x0A,  0x92,  0x0A,  0x85,  0x0C,  0x45,  0x08,  0x3C,  0xA7,  0x08,  0x20,  0x08,  0x40,  0x09,  0xFC,  0x09, 	/* 31760 */
+	0x24,  0x0D,  0x24,  0x2B,  0xFC,  0x2B,  0x24,  0x29,  0x24,  0x29,  0xFC,  0x48,  0x54,  0x08,  0x54,  0x08, 	/* 31770 */
+	0x5A,  0x08,  0x9E,  0x08,  0x91,  0x09,  0x11,  0x0A,  0x0F,  0xA8,  0x08,  0x00,  0x08,  0x78,  0x7F,  0x49, 	/* 31780 */
+	0x08,  0x49,  0x3E,  0x47,  0x00,  0x80,  0x7F,  0xFC,  0x41,  0x44,  0x00,  0x28,  0x3E,  0x10,  0x00,  0x6C, 	/* 31790 */
+	0x12,  0x83,  0x12,  0x44,  0x22,  0x4A,  0x42,  0x09,  0x01,  0xF8,  0xAC,  0x21,  0x00,  0x11,  0x3E,  0x12, 	/* 317A0 */
+	0x22,  0x7F,  0xE2,  0x04,  0x3E,  0x24,  0xA2,  0x24,  0xBE,  0x3F,  0xA2,  0x08,  0x22,  0x10,  0x46,  0x20, 	/* 317B0 */
+	0x80,  0x12,  0x40,  0x12,  0x42,  0x22,  0x09,  0x41,  0x09,  0x00,  0xF8,  0xB4,  0x08,  0x20,  0x08,  0x20, 	/* 317C0 */
+	0x08,  0x50,  0x08,  0x48,  0x08,  0xF4,  0x2D,  0x02,  0x2B,  0xFD,  0x29,  0x04,  0x49,  0xFC,  0x09,  0x04, 	/* 317D0 */
+	0x09,  0xFC,  0x09,  0x00,  0x0A,  0xFE,  0x0A,  0x82,  0x0C,  0xFE,  0x08,  0x00,  0xBC,  0x08,  0x8C,  0x08, 	/* 317E0 */
+	0xF0,  0x08,  0x81,  0x08,  0x7F,  0x2D,  0x00,  0x2B,  0x7E,  0x2B,  0x42,  0x29,  0x7E,  0x49,  0x42,  0x09, 	/* 317F0 */
+	0x7E,  0x09,  0x42,  0x09,  0x7E,  0x09,  0x00,  0x09,  0xFF,  0x08,  0x66,  0x0B,  0x81,  0xBD,  0x08,  0x24, 	/* 31800 */
+	0x08,  0x22,  0x0B,  0xFF,  0x08,  0x20,  0x2D,  0xFC,  0x2B,  0x24,  0x29,  0xFC,  0x29,  0x24,  0x49,  0xFC, 	/* 31810 */
+	0x09,  0x24,  0x08,  0x08,  0x0B,  0xFF,  0x09,  0x08,  0x08,  0x88,  0x08,  0x88,  0x08,  0x18,  0xBE,  0x08, 	/* 31820 */
+	0x40,  0x08,  0x40,  0x08,  0xFE,  0x08,  0x80,  0x09,  0x78,  0x2C,  0x00,  0x2B,  0xFC,  0x28,  0x44,  0x4A, 	/* 31830 */
+	0x54,  0x09,  0x64,  0x08,  0x44,  0x0B,  0xF5,  0x08,  0xE5,  0x09,  0x53,  0x0A,  0x4B,  0x08,  0x41,  0xBF, 	/* 31840 */
+	0x00,  0x00,  0x1F,  0xFF,  0x10,  0x40,  0x13,  0xFC,  0x12,  0x04,  0x13,  0xFC,  0x12,  0x04,  0x13,  0xFC, 	/* 31850 */
+	0x22,  0x48,  0x24,  0x44,  0x48,  0xC2,  0x02,  0x40,  0x12,  0x22,  0x12,  0x09,  0x22,  0x09,  0x41,  0xF8, 	/* 31860 */
+	0x82,  0x10,  0x00,  0x0B,  0xFC,  0x08,  0x88,  0x40,  0x50,  0x23,  0xFE,  0x22,  0x22,  0x03,  0xFE,  0x0A, 	/* 31870 */
+	0x22,  0x13,  0xFE,  0x22,  0x22,  0x40,  0x26,  0x12,  0x44,  0x12,  0x22,  0x22,  0x29,  0x41,  0x09,  0x00, 	/* 31880 */
+	0xF8,  0x84,  0x08,  0x00,  0x0B,  0xFF,  0x08,  0x48,  0x08,  0x48,  0x0D,  0xFE,  0x2B,  0x4A,  0x29,  0x4A, 	/* 31890 */
+	0x29,  0xFE,  0x48,  0x20,  0x0F,  0xFF,  0x08,  0x70,  0x08,  0xA8,  0x09,  0x24,  0x0E,  0x23,  0x08,  0x20, 	/* 318A0 */
+	0x08,  0x20,  0x87,  0x02,  0x00,  0x1C,  0x78,  0x10,  0x49,  0x1E,  0x49,  0x12,  0x87,  0x1F,  0x00,  0x12, 	/* 318B0 */
+	0xFC,  0x1E,  0x24,  0x10,  0x28,  0x1E,  0x10,  0x22,  0x6C,  0x47,  0x83,  0x12,  0x44,  0x12,  0x22,  0x22, 	/* 318C0 */
+	0x09,  0x41,  0xF8,  0x88,  0x04,  0x08,  0x02,  0x10,  0x7F,  0xFF,  0x08,  0x20,  0x0A,  0x28,  0x32,  0xC8, 	/* 318D0 */
+	0x0C,  0x30,  0x05,  0x14,  0x09,  0x24,  0x7E,  0xFA,  0x00,  0x82,  0x12,  0x44,  0x12,  0x42,  0x22,  0x09, 	/* 318E0 */
+	0x41,  0x09,  0x00,  0xF8,  0x8A,  0x08,  0x44,  0x09,  0x98,  0x08,  0x48,  0x0B,  0xFF,  0x08,  0x48,  0x2D, 	/* 318F0 */
+	0xFE,  0x2A,  0x4A,  0x2B,  0xFF,  0x28,  0x4A,  0x49,  0xFE,  0x08,  0x48,  0x08,  0xCC,  0x09,  0x4A,  0x0A, 	/* 31900 */
+	0x49,  0x08,  0x48,  0x08,  0x48,  0x8B,  0x08,  0x20,  0x0A,  0x26,  0x11,  0x38,  0x7F,  0xA1,  0x11,  0x9F, 	/* 31910 */
+	0x1F,  0x20,  0x11,  0x26,  0x1F,  0x38,  0x11,  0x21,  0x13,  0x1F,  0x00,  0x80,  0x12,  0x44,  0x12,  0x42, 	/* 31920 */
+	0x22,  0x09,  0x41,  0x09,  0x00,  0xF8,  0x8C,  0x08,  0x88,  0x08,  0x88,  0x0B,  0xFF,  0x08,  0x88,  0x28, 	/* 31930 */
+	0x20,  0x2D,  0xFF,  0x2A,  0x80,  0x2A,  0x80,  0x48,  0x7C,  0x08,  0x00,  0x09,  0x24,  0x09,  0x24,  0x09, 	/* 31940 */
+	0x24,  0x09,  0x25,  0x0A,  0x25,  0x0C,  0x03,  0x8D,  0x08,  0x00,  0x08,  0xFC,  0x08,  0xA4,  0x08,  0xA4, 	/* 31950 */
+	0x28,  0xB4,  0x2C,  0xD4,  0x2A,  0x8C,  0x28,  0xFC,  0x48,  0x00,  0x09,  0xFE,  0x09,  0x4A,  0x09,  0x4A, 	/* 31960 */
+	0x09,  0x4A,  0x09,  0x4A,  0x0B,  0xFF,  0x08,  0x00,  0x8E,  0x08,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x08, 	/* 31970 */
+	0x20,  0x08,  0xFC,  0x2C,  0x84,  0x2A,  0xFC,  0x2A,  0x84,  0x28,  0xFC,  0x48,  0x84,  0x08,  0xFC,  0x08, 	/* 31980 */
+	0x00,  0x0B,  0xFF,  0x08,  0x48,  0x08,  0x84,  0x0B,  0x02,  0x93,  0x08,  0x00,  0x0B,  0xFF,  0x08,  0x48, 	/* 31990 */
+	0x09,  0xFE,  0x0D,  0x4A,  0x2B,  0x4A,  0x2B,  0xFE,  0x28,  0x00,  0x29,  0xFE,  0x48,  0x00,  0x0B,  0xFF, 	/* 319A0 */
+	0x08,  0x10,  0x08,  0x94,  0x09,  0x12,  0x0A,  0x11,  0x08,  0x30,  0x95,  0x02,  0x20,  0x7F,  0xFF,  0x02, 	/* 319B0 */
+	0x20,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x01,  0x00,  0x7F,  0xFF,  0x04, 	/* 319C0 */
+	0x10,  0x19,  0x0C,  0x65,  0x4B,  0x09,  0x24,  0x11,  0x24,  0x03,  0x00,  0x98,  0x08,  0x20,  0x08,  0x20, 	/* 319D0 */
+	0x08,  0x50,  0x09,  0xFC,  0x09,  0x04,  0x2A,  0x8A,  0x2F,  0x7D,  0x28,  0x50,  0x49,  0x8C,  0x0E,  0x23, 	/* 319E0 */
+	0x08,  0x48,  0x09,  0x92,  0x08,  0x64,  0x09,  0x88,  0x08,  0x30,  0x0B,  0xC0,  0x99,  0x04,  0x04,  0x7F, 	/* 319F0 */
+	0xF8,  0x04,  0x20,  0x3F,  0xA0,  0x24,  0xBF,  0x3F,  0xA4,  0x24,  0xA4,  0x3F,  0xA4,  0x04,  0x44,  0x7F, 	/* 31A00 */
+	0x84,  0x04,  0x84,  0x12,  0x44,  0x12,  0x42,  0x22,  0x09,  0x41,  0x09,  0x00,  0xF8,  0x9A,  0x11,  0x02, 	/* 31A10 */
+	0x11,  0x04,  0x17,  0xF8,  0x11,  0x10,  0x17,  0xD0,  0x3D,  0x5F,  0x35,  0x52,  0x37,  0xD2,  0x55,  0x52, 	/* 31A20 */
+	0x15,  0x52,  0x17,  0xD2,  0x11,  0x12,  0x1F,  0xF2,  0x11,  0x12,  0x11,  0x22,  0x11,  0x02,  0x9D,  0x00, 	/* 31A30 */
+	0x00,  0x3F,  0xFE,  0x22,  0x10,  0x3F,  0xFE,  0x21,  0x10,  0x3F,  0xFC,  0x22,  0x00,  0x27,  0xF8,  0x2A, 	/* 31A40 */
+	0x08,  0x33,  0xF8,  0x20,  0x00,  0x3F,  0xFE,  0x12,  0x40,  0x12,  0x22,  0x22,  0x09,  0x41,  0xF9,  0x9F, 	/* 31A50 */
+	0x10,  0x48,  0x17,  0x88,  0x11,  0x08,  0x17,  0xE8,  0x39,  0x1E,  0x37,  0xCA,  0x35,  0x4A,  0x37,  0xCA, 	/* 31A60 */
+	0x55,  0x4A,  0x17,  0xCA,  0x11,  0x0A,  0x17,  0xCA,  0x11,  0x12,  0x11,  0xD2,  0x16,  0x22,  0x10,  0x4C, 	/* 31A70 */
+	0xA2,  0x08,  0x00,  0x08,  0xFC,  0x08,  0x84,  0x08,  0xFC,  0x2C,  0x84,  0x2A,  0xFC,  0x28,  0x00,  0x2B, 	/* 31A80 */
+	0xFE,  0x4A,  0x4A,  0x0B,  0xFE,  0x08,  0x00,  0x0B,  0xFC,  0x08,  0xC8,  0x08,  0x30,  0x08,  0xCC,  0x0B, 	/* 31A90 */
+	0x03,  0xA3,  0x08,  0x00,  0x08,  0xFE,  0x08,  0x92,  0x0B,  0xFF,  0x09,  0x24,  0x2D,  0xFC,  0x2A,  0x00, 	/* 31AA0 */
+	0x2B,  0xFC,  0x49,  0x04,  0x09,  0xFC,  0x09,  0x04,  0x09,  0xFC,  0x09,  0x04,  0x09,  0xFC,  0x08,  0x4C, 	/* 31AB0 */
+	0x0B,  0x83,  0xA5,  0x08,  0x08,  0x09,  0x28,  0x08,  0xA8,  0x08,  0xBE,  0x0A,  0x48,  0x2D,  0x08,  0x2D, 	/* 31AC0 */
+	0x7F,  0x28,  0x08,  0x2B,  0xBE,  0x48,  0xA2,  0x08,  0xA2,  0x08,  0xA2,  0x08,  0xBE,  0x09,  0x40,  0x0A, 	/* 31AD0 */
+	0x30,  0x0C,  0x0F,  0xA7,  0x08,  0x10,  0x7F,  0xFE,  0x08,  0x10,  0x7E,  0xFE,  0x08,  0x10,  0x7F,  0xFE, 	/* 31AE0 */
+	0x08,  0x10,  0x1F,  0xF8,  0x00,  0x08,  0x0F,  0xF8,  0x00,  0x08,  0x3F,  0xF8,  0x14,  0x84,  0x14,  0x52, 	/* 31AF0 */
+	0x24,  0x12,  0x43,  0xF0,  0xA8,  0x10,  0x00,  0x13,  0xFF,  0x12,  0x44,  0x12,  0x54,  0x33,  0xD4,  0x3A, 	/* 31B00 */
+	0x54,  0x36,  0x54,  0x33,  0xFF,  0x53,  0x04,  0x12,  0x8C,  0x12,  0x8C,  0x12,  0x4C,  0x12,  0xD4,  0x13, 	/* 31B10 */
+	0x55,  0x1C,  0x25,  0x10,  0x43,  0xAB,  0x08,  0x84,  0x08,  0x84,  0x11,  0x4A,  0x25,  0x29,  0x46,  0x10, 	/* 31B20 */
+	0x08,  0x90,  0x18,  0x9E,  0x28,  0x90,  0x49,  0x50,  0x0A,  0x30,  0x0C,  0x8F,  0x12,  0x44,  0x12,  0x42, 	/* 31B30 */
+	0x22,  0x09,  0x41,  0x09,  0x00,  0xF8,  0xAE,  0x00,  0x80,  0x00,  0xFC,  0x00,  0x80,  0x1F,  0xFF,  0x10, 	/* 31B40 */
+	0x9A,  0x1F,  0xE0,  0x10,  0x82,  0x17,  0xFE,  0x14,  0x48,  0x17,  0xF8,  0x14,  0x48,  0x17,  0xF8,  0x2A, 	/* 31B50 */
+	0x44,  0x2A,  0x2A,  0x52,  0x09,  0x21,  0xF9,  0xAF,  0x08,  0x80,  0x08,  0xFF,  0x09,  0x00,  0x0A,  0xFC, 	/* 31B60 */
+	0x2C,  0x84,  0x2A,  0xFC,  0x28,  0x84,  0x28,  0xFC,  0x48,  0x00,  0x0B,  0xFF,  0x08,  0x80,  0x09,  0xFE, 	/* 31B70 */
+	0x0A,  0x4A,  0x08,  0x92,  0x09,  0x22,  0x08,  0x4C,  0xB0,  0x00,  0x04,  0x3F,  0x84,  0x20,  0x84,  0x3F, 	/* 31B80 */
+	0x84,  0x20,  0x7F,  0x2F,  0x04,  0x20,  0x24,  0x3F,  0x94,  0x22,  0x14,  0x2A,  0x84,  0x56,  0x84,  0x05, 	/* 31B90 */
+	0x0C,  0x14,  0x80,  0x14,  0x92,  0x24,  0x11,  0x43,  0xF1,  0xB1,  0x08,  0x20,  0x08,  0x20,  0x0B,  0xFF, 	/* 31BA0 */
+	0x08,  0x20,  0x09,  0xFC,  0x2D,  0x24,  0x2B,  0xFC,  0x2B,  0x24,  0x29,  0xFC,  0x48,  0x24,  0x0B,  0xFE, 	/* 31BB0 */
+	0x08,  0x09,  0x0F,  0xFF,  0x09,  0x08,  0x08,  0x88,  0x08,  0x18,  0xB3,  0x10,  0x00,  0x13,  0xFE,  0x12, 	/* 31BC0 */
+	0x92,  0x12,  0x92,  0x33,  0xEA,  0x3A,  0x2A,  0x37,  0xE4,  0x32,  0x8A,  0x52,  0x91,  0x13,  0xE0,  0x10, 	/* 31BD0 */
+	0x20,  0x13,  0xFE,  0x10,  0x20,  0x10,  0x20,  0x17,  0xFF,  0x10,  0x00,  0xB4,  0x08,  0x00,  0x0B,  0xFF, 	/* 31BE0 */
+	0x08,  0xA5,  0x09,  0x29,  0x2C,  0x63,  0x2A,  0xA5,  0x29,  0x29,  0x28,  0x63,  0x48,  0x10,  0x08,  0xFE, 	/* 31BF0 */
+	0x08,  0x82,  0x08,  0xFE,  0x08,  0x82,  0x08,  0x82,  0x08,  0xFE,  0x08,  0x00,  0xB5,  0x10,  0x10,  0x13, 	/* 31C00 */
+	0xFF,  0x12,  0x10,  0x12,  0xFE,  0x3A,  0x12,  0x37,  0xFF,  0x32,  0x12,  0x52,  0xFE,  0x52,  0x10,  0x12, 	/* 31C10 */
+	0xFE,  0x12,  0x92,  0x12,  0xFE,  0x14,  0x92,  0x14,  0xFE,  0x18,  0x92,  0x10,  0x96,  0xB6,  0x00,  0x40, 	/* 31C20 */
+	0x1F,  0xFF,  0x11,  0x10,  0x1F,  0xFE,  0x11,  0x12,  0x1F,  0xFE,  0x10,  0x00,  0x1F,  0xFF,  0x15,  0x44, 	/* 31C30 */
+	0x15,  0x2A,  0x19,  0xF9,  0x12,  0x11,  0x2D,  0xA0,  0x20,  0xE0,  0x43,  0x18,  0x1C,  0x07,  0xB7,  0x10, 	/* 31C40 */
+	0x20,  0x10,  0x20,  0x13,  0xFF,  0x12,  0x20,  0x33,  0xFC,  0x3A,  0x24,  0x37,  0xFF,  0x32,  0x24,  0x53, 	/* 31C50 */
+	0xFC,  0x13,  0x22,  0x12,  0xB2,  0x12,  0xAC,  0x14,  0x68,  0x14,  0xA4,  0x1B,  0x23,  0x10,  0x60,  0xBE, 	/* 31C60 */
+	0x12,  0x20,  0x11,  0x20,  0x15,  0x3F,  0x26,  0x52,  0x09,  0x54,  0x10,  0x90,  0x3F,  0x18,  0x51,  0x28, 	/* 31C70 */
+	0x11,  0x24,  0x1F,  0x42,  0x00,  0x81,  0x12,  0x44,  0x12,  0x42,  0x22,  0x09,  0x41,  0x09,  0x00,  0xF8, 	/* 31C80 */
+	0x82,  0x00,  0x00,  0x7F,  0xFE,  0x01,  0x00,  0x0F,  0xE0,  0x08,  0x20,  0x0F,  0xE0,  0x08,  0x20,  0x7F, 	/* 31C90 */
+	0xFE,  0x45,  0x02,  0x54,  0xAA,  0x23,  0xE4,  0x44,  0x22,  0x0F,  0x40,  0x30,  0xC0,  0x07,  0x30,  0x78, 	/* 31CA0 */
+	0x0E,  0x87,  0x02,  0x44,  0x0C,  0x44,  0x79,  0xFF,  0x08,  0x44,  0x7F,  0x44,  0x08,  0x7C,  0x3E,  0x44, 	/* 31CB0 */
+	0x22,  0x44,  0x22,  0x44,  0x3E,  0x7C,  0x04,  0x80,  0x14,  0x44,  0x14,  0x42,  0x24,  0x09,  0x42,  0x09, 	/* 31CC0 */
+	0x01,  0xF8,  0x8A,  0x04,  0x48,  0x05,  0xFE,  0x08,  0x48,  0x0B,  0xFF,  0x12,  0xFE,  0x32,  0x92,  0x52, 	/* 31CD0 */
+	0xFE,  0x12,  0x92,  0x12,  0xFE,  0x14,  0x92,  0x18,  0x96,  0x02,  0x40,  0x12,  0x22,  0x12,  0x09,  0x21, 	/* 31CE0 */
+	0x09,  0x40,  0xF8,  0x8E,  0x09,  0x04,  0x08,  0x88,  0x0B,  0xFE,  0x0A,  0x22,  0x2E,  0x22,  0x2F,  0xFE, 	/* 31CF0 */
+	0x2A,  0x22,  0x2B,  0xFE,  0x48,  0x00,  0x09,  0xFC,  0x09,  0x04,  0x09,  0xFC,  0x09,  0x04,  0x09,  0x04, 	/* 31D00 */
+	0x09,  0xFC,  0x08,  0x00,  0x90,  0x08,  0x92,  0x08,  0x52,  0x08,  0x54,  0x09,  0xFF,  0x2C,  0x38,  0x2A, 	/* 31D10 */
+	0x54,  0x2B,  0x93,  0x28,  0x90,  0x48,  0x84,  0x08,  0xFF,  0x09,  0x54,  0x0B,  0x54,  0x0C,  0xBF,  0x08, 	/* 31D20 */
+	0x84,  0x09,  0x04,  0x0A,  0x04,  0x91,  0x00,  0x00,  0x23,  0xFC,  0x12,  0x20,  0x03,  0xF8,  0x02,  0x20, 	/* 31D30 */
+	0x0B,  0xF8,  0x0A,  0x20,  0x13,  0xFE,  0x24,  0x92,  0x44,  0x4A,  0x08,  0x8C,  0x02,  0x40,  0x12,  0x42, 	/* 31D40 */
+	0x22,  0x09,  0x42,  0x09,  0x01,  0xF8,  0x94,  0x08,  0x44,  0x08,  0x48,  0x08,  0xFF,  0x08,  0x90,  0x2D, 	/* 31D50 */
+	0x90,  0x2A,  0xFE,  0x28,  0x90,  0x28,  0xFE,  0x48,  0x90,  0x08,  0x90,  0x08,  0xFF,  0x08,  0x00,  0x08, 	/* 31D60 */
+	0x84,  0x08,  0xD2,  0x09,  0x29,  0x0A,  0x29,  0x96,  0x04,  0x14,  0x04,  0x12,  0x7F,  0x92,  0x15,  0x7F, 	/* 31D70 */
+	0x15,  0x10,  0x1E,  0xA8,  0x24,  0xA8,  0x4E,  0x24,  0x15,  0x42,  0x24,  0x81,  0x44,  0x80,  0x12,  0x44, 	/* 31D80 */
+	0x12,  0x42,  0x22,  0x09,  0x41,  0x09,  0x00,  0xF8,  0x99,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80,  0x0F, 	/* 31D90 */
+	0xF8,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x02,  0x20,  0x7F,  0xFF,  0x08,  0x08,  0x0F, 	/* 31DA0 */
+	0xF8,  0x12,  0x40,  0x12,  0x2A,  0x21,  0x09,  0x40,  0xF9,  0x9A,  0x08,  0x00,  0x0B,  0xDE,  0x0A,  0x52, 	/* 31DB0 */
+	0x0B,  0xDE,  0x28,  0x00,  0x2D,  0xFC,  0x2B,  0x24,  0x29,  0xFC,  0x49,  0x24,  0x09,  0x24,  0x09,  0xFC, 	/* 31DC0 */
+	0x08,  0x20,  0x0F,  0xFF,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0xA4,  0x08,  0x20,  0x0B,  0xFE,  0x08, 	/* 31DD0 */
+	0x20,  0x08,  0x88,  0x0F,  0xFF,  0x28,  0x88,  0x2C,  0x00,  0x2B,  0xFC,  0x49,  0x04,  0x09,  0xFC,  0x09, 	/* 31DE0 */
+	0x04,  0x09,  0xFC,  0x09,  0x04,  0x09,  0xFC,  0x09,  0x8C,  0x0E,  0x02,  0xA7,  0x08,  0x20,  0x08,  0x20, 	/* 31DF0 */
+	0x0B,  0xFE,  0x08,  0x88,  0x2F,  0xFF,  0x28,  0x00,  0x2D,  0xFC,  0x2B,  0x24,  0x49,  0xFC,  0x09,  0x24, 	/* 31E00 */
+	0x09,  0xFC,  0x08,  0x20,  0x09,  0xFC,  0x08,  0x20,  0x0F,  0xFF,  0x08,  0x00,  0xA9,  0x01,  0x08,  0x06, 	/* 31E10 */
+	0x10,  0x38,  0x7C,  0x08,  0x44,  0x7F,  0xFC,  0x08,  0x44,  0x08,  0x44,  0x3F,  0x7C,  0x21,  0x44,  0x21, 	/* 31E20 */
+	0x44,  0x3F,  0x7C,  0x02,  0x80,  0x12,  0x42,  0x12,  0x49,  0x22,  0x09,  0x41,  0xF8,  0xAB,  0x10,  0x00, 	/* 31E30 */
+	0x13,  0xDE,  0x12,  0x52,  0x13,  0xDE,  0x32,  0x52,  0x3B,  0xDE,  0x36,  0x02,  0x32,  0x22,  0x53,  0xFE, 	/* 31E40 */
+	0x12,  0x8A,  0x12,  0x52,  0x12,  0x22,  0x12,  0x52,  0x12,  0x8A,  0x12,  0x02,  0x12,  0x06,  0xAC,  0x08, 	/* 31E50 */
+	0x00,  0x09,  0xFC,  0x09,  0x04,  0x09,  0xFC,  0x09,  0x04,  0x2D,  0xFC,  0x2A,  0x20,  0x2B,  0xFF,  0x48, 	/* 31E60 */
+	0x00,  0x09,  0xFC,  0x09,  0x04,  0x09,  0xFC,  0x08,  0xA8,  0x09,  0x24,  0x0A,  0x22,  0x08,  0x60,  0xAE, 	/* 31E70 */
+	0x09,  0x00,  0x09,  0x00,  0x0B,  0xFF,  0x0D,  0x54,  0x29,  0x54,  0x2D,  0x54,  0x2B,  0xFF,  0x29,  0x54, 	/* 31E80 */
+	0x49,  0x54,  0x09,  0x54,  0x0F,  0xFF,  0x08,  0x00,  0x0A,  0x04,  0x0A,  0x92,  0x0C,  0x49,  0x08,  0x49, 	/* 31E90 */
+	0xB2,  0x01,  0x00,  0x7F,  0xFE,  0x41,  0x02,  0x5F,  0xFA,  0x01,  0x00,  0x0F,  0xF0,  0x01,  0x00,  0x7F, 	/* 31EA0 */
+	0xFE,  0x00,  0x00,  0x1F,  0xF8,  0x12,  0x48,  0x1F,  0xF8,  0x24,  0x88,  0x24,  0x44,  0x44,  0x12,  0x03, 	/* 31EB0 */
+	0xF2,  0xB6,  0x10,  0x40,  0x10,  0x40,  0x17,  0xFC,  0x11,  0x08,  0x30,  0x90,  0x37,  0xFF,  0x38,  0x00, 	/* 31EC0 */
+	0x55,  0xFC,  0x51,  0x04,  0x11,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x12,  0xA0,  0x12,  0x92,  0x14,  0x89, 	/* 31ED0 */
+	0x10,  0x78,  0xBA,  0x08,  0x20,  0x08,  0x78,  0x08,  0x90,  0x0B,  0xFF,  0x29,  0x2A,  0x2D,  0x46,  0x2B, 	/* 31EE0 */
+	0xBC,  0x29,  0x00,  0x49,  0xFF,  0x09,  0x00,  0x09,  0x3C,  0x09,  0x00,  0x0A,  0x7E,  0x0A,  0x42,  0x0C, 	/* 31EF0 */
+	0x7E,  0x08,  0x00,  0xBE,  0x08,  0x14,  0x08,  0x12,  0x09,  0xFF,  0x09,  0x10,  0x29,  0xF2,  0x2D,  0x0A, 	/* 31F00 */
+	0x2B,  0xEC,  0x29,  0xA4,  0x4A,  0xED,  0x0A,  0x93,  0x0C,  0x21,  0x09,  0x50,  0x09,  0x52,  0x0A,  0x45, 	/* 31F10 */
+	0x0C,  0x45,  0x08,  0x3C,  0x83,  0x12,  0x10,  0x7F,  0x90,  0x12,  0x10,  0x3F,  0x7E,  0x25,  0x12,  0x3F, 	/* 31F20 */
+	0x12,  0x04,  0x12,  0x3F,  0x12,  0x04,  0x22,  0x07,  0x22,  0x78,  0x42,  0x04,  0x8C,  0x14,  0x40,  0x14, 	/* 31F30 */
+	0x4A,  0x22,  0x09,  0x41,  0xF9,  0x86,  0x08,  0x00,  0x08,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x0C,  0xF8, 	/* 31F40 */
+	0x2B,  0xDE,  0x2A,  0x52,  0x2A,  0x52,  0x4B,  0xDE,  0x08,  0x20,  0x0B,  0xFF,  0x08,  0x70,  0x08,  0xA8, 	/* 31F50 */
+	0x09,  0x24,  0x0A,  0x23,  0x08,  0x20,  0x87,  0x04,  0x00,  0x39,  0x7C,  0x26,  0x44,  0x1C,  0x7C,  0x76, 	/* 31F60 */
+	0x44,  0x09,  0x7E,  0x33,  0x52,  0x05,  0x54,  0x19,  0x48,  0x62,  0x74,  0x0C,  0xC3,  0x12,  0x84,  0x12, 	/* 31F70 */
+	0x42,  0x22,  0x09,  0x41,  0x09,  0x00,  0xF8,  0x88,  0x10,  0x80,  0x10,  0xFF,  0x11,  0x29,  0x12,  0x49, 	/* 31F80 */
+	0x37,  0xE9,  0x3A,  0xB3,  0x36,  0xA4,  0x33,  0xE4,  0x52,  0xB4,  0x12,  0xBF,  0x13,  0xE4,  0x12,  0x24, 	/* 31F90 */
+	0x12,  0x3F,  0x12,  0x24,  0x12,  0x24,  0x14,  0x64,  0x89,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFF,  0x12, 	/* 31FA0 */
+	0x48,  0x12,  0xFE,  0x15,  0x90,  0x16,  0xFC,  0x1C,  0x90,  0x14,  0xFC,  0x14,  0x90,  0x14,  0xFF,  0x15, 	/* 31FB0 */
+	0x40,  0x25,  0x22,  0x29,  0x29,  0x51,  0x09,  0x00,  0xF8,  0x8A,  0x08,  0x20,  0x08,  0x40,  0x09,  0xFE, 	/* 31FC0 */
+	0x09,  0x1A,  0x29,  0x62,  0x2D,  0xAA,  0x2B,  0xFE,  0x29,  0x6A,  0x49,  0xA6,  0x09,  0x22,  0x08,  0x20, 	/* 31FD0 */
+	0x0B,  0xFF,  0x08,  0x20,  0x08,  0x50,  0x09,  0x8C,  0x0E,  0x03,  0x8B,  0x10,  0x04,  0x13,  0xE4,  0x7D, 	/* 31FE0 */
+	0x5F,  0x10,  0x84,  0x13,  0xE4,  0x38,  0xAE,  0x35,  0xCE,  0x52,  0x95,  0x54,  0xA4,  0x11,  0x84,  0x00, 	/* 31FF0 */
+	0x80,  0x12,  0x44,  0x12,  0x42,  0x22,  0x09,  0x42,  0x09,  0x01,  0xF8,  0x8C,  0x08,  0x00,  0x09,  0xFE, 	/* 32000 */
+	0x09,  0x52,  0x09,  0xFE,  0x28,  0x20,  0x2D,  0xFE,  0x2A,  0x20,  0x2B,  0xFF,  0x48,  0x84,  0x08,  0x48, 	/* 32010 */
+	0x09,  0xFE,  0x08,  0x20,  0x09,  0xFE,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x8D,  0x08,  0x10,  0x0B, 	/* 32020 */
+	0xFF,  0x08,  0x82,  0x08,  0xBA,  0x2C,  0xAA,  0x2A,  0xBA,  0x2A,  0x82,  0x28,  0xFE,  0x48,  0x04,  0x09, 	/* 32030 */
+	0xF8,  0x08,  0x10,  0x0B,  0xFF,  0x08,  0x38,  0x08,  0xD4,  0x0B,  0x13,  0x08,  0x10,  0x90,  0x08,  0x20, 	/* 32040 */
+	0x08,  0x20,  0x0B,  0xFF,  0x08,  0x20,  0x29,  0xFC,  0x2D,  0x54,  0x2D,  0x54,  0x2B,  0xFC,  0x48,  0x20, 	/* 32050 */
+	0x0B,  0xFF,  0x08,  0x44,  0x08,  0xA4,  0x09,  0x98,  0x0A,  0x88,  0x08,  0xE4,  0x09,  0x83,  0xA3,  0x20, 	/* 32060 */
+	0x88,  0x17,  0xFF,  0x10,  0x88,  0x00,  0xF8,  0x40,  0x20,  0x23,  0xFE,  0x0A,  0xAA,  0x0A,  0xAA,  0x12, 	/* 32070 */
+	0xEE,  0x23,  0x32,  0x42,  0x26,  0x12,  0x40,  0x12,  0x22,  0x22,  0x09,  0x41,  0x09,  0x00,  0xF8,  0xA6, 	/* 32080 */
+	0x10,  0x00,  0x13,  0xFE,  0x10,  0x20,  0x13,  0xFF,  0x3A,  0x21,  0x37,  0xAD,  0x32,  0x21,  0x31,  0xAC, 	/* 32090 */
+	0x50,  0x00,  0x17,  0xFF,  0x10,  0x40,  0x13,  0xFE,  0x12,  0x52,  0x12,  0x52,  0x12,  0x52,  0x12,  0x06, 	/* 320A0 */
+	0xB2,  0x11,  0x10,  0x15,  0x50,  0x25,  0x5F,  0x4F,  0xE4,  0x08,  0x24,  0x17,  0xD4,  0x31,  0x0C,  0x57, 	/* 320B0 */
+	0xC8,  0x11,  0x14,  0x17,  0xE2,  0x12,  0x41,  0x15,  0x08,  0x14,  0x84,  0x24,  0x92,  0x44,  0x12,  0x03, 	/* 320C0 */
+	0xF0,  0xB4,  0x10,  0x88,  0x10,  0x8C,  0x13,  0xEA,  0x10,  0x8A,  0x38,  0x88,  0x37,  0xFF,  0x31,  0x48, 	/* 320D0 */
+	0x37,  0x6A,  0x51,  0x4A,  0x17,  0x6A,  0x11,  0x44,  0x17,  0x6C,  0x11,  0x4D,  0x11,  0xF5,  0x17,  0x23, 	/* 320E0 */
+	0x10,  0x41,  0xB6,  0x11,  0x00,  0x11,  0x3E,  0x11,  0x0A,  0x17,  0xEA,  0x39,  0x12,  0x37,  0xE4,  0x35, 	/* 320F0 */
+	0x7E,  0x55,  0x62,  0x57,  0xFE,  0x11,  0x22,  0x13,  0xBE,  0x13,  0x62,  0x15,  0x3E,  0x19,  0x14,  0x11, 	/* 32100 */
+	0x22,  0x11,  0xC1,  0xB7,  0x08,  0x20,  0x0B,  0xFF,  0x08,  0x00,  0x09,  0xFE,  0x29,  0x52,  0x2D,  0xFE, 	/* 32110 */
+	0x2A,  0x20,  0x2B,  0xAE,  0x48,  0x20,  0x0B,  0xAE,  0x08,  0x52,  0x09,  0x94,  0x0E,  0x88,  0x08,  0x84, 	/* 32120 */
+	0x08,  0xE2,  0x0B,  0x01,  0xB8,  0x00,  0x06,  0x5E,  0x78,  0x52,  0x10,  0x5E,  0x14,  0x52,  0x68,  0x5E, 	/* 32130 */
+	0x14,  0x52,  0xFE,  0x7F,  0x91,  0x0C,  0x54,  0x2A,  0x52,  0x2A,  0x92,  0x48,  0x40,  0x12,  0x42,  0x12, 	/* 32140 */
+	0x01,  0x22,  0x09,  0x41,  0xF8,  0xBA,  0x12,  0x48,  0x12,  0x4C,  0x13,  0xAA,  0x14,  0x9A,  0x38,  0x08, 	/* 32150 */
+	0x37,  0xFF,  0x31,  0x48,  0x37,  0x6A,  0x51,  0x4A,  0x17,  0x6A,  0x11,  0x44,  0x17,  0x6C,  0x11,  0x4D, 	/* 32160 */
+	0x11,  0xF5,  0x17,  0x23,  0x10,  0x41,  0xBC,  0x08,  0x00,  0x0B,  0xDE,  0x0A,  0x52,  0x0B,  0xDE,  0x2E, 	/* 32170 */
+	0x52,  0x2B,  0xDE,  0x2A,  0x52,  0x2B,  0xDE,  0x48,  0x90,  0x09,  0xFE,  0x0B,  0x20,  0x0D,  0xFC,  0x09, 	/* 32180 */
+	0xFC,  0x09,  0x20,  0x09,  0xFF,  0x08,  0x00,  0xBD,  0x08,  0x88,  0x0B,  0xFF,  0x08,  0x88,  0x0B,  0xDE, 	/* 32190 */
+	0x2A,  0x52,  0x2B,  0xDE,  0x2C,  0x48,  0x2A,  0x90,  0x49,  0xFE,  0x0B,  0x10,  0x09,  0xFC,  0x09,  0x10, 	/* 321A0 */
+	0x09,  0xFC,  0x09,  0x10,  0x09,  0xFF,  0x08,  0x00,  0xBE,  0x08,  0x00,  0x0B,  0xFE,  0x08,  0x88,  0x08, 	/* 321B0 */
+	0xF8,  0x28,  0x88,  0x2C,  0xFE,  0x2B,  0x88,  0x28,  0x08,  0x4F,  0xFF,  0x0A,  0x52,  0x0B,  0xDE,  0x0A, 	/* 321C0 */
+	0x52,  0x0B,  0xDE,  0x0A,  0x53,  0x0F,  0xFE,  0x08,  0x42,  0xBF,  0x08,  0x10,  0x7F,  0x10,  0x08,  0x9F, 	/* 321D0 */
+	0x3E,  0x69,  0x00,  0x0A,  0x7F,  0x48,  0x41,  0x94,  0x3E,  0x22,  0x00,  0xC1,  0x3E,  0x10,  0x22,  0x08, 	/* 321E0 */
+	0x3E,  0xAA,  0x22,  0xA1,  0x15,  0x25,  0x1E,  0x24,  0x60,  0x1C,  0x80,  0x13,  0xC4,  0x10,  0x04,  0x6B, 	/* 321F0 */
+	0xFA,  0x10,  0x04,  0x2B,  0xCA,  0x7C,  0x3F,  0x17,  0xC5,  0x30,  0x14,  0x3B,  0xD6,  0x56,  0x65,  0x13, 	/* 32200 */
+	0xC4,  0x02,  0x40,  0x12,  0x22,  0x12,  0x09,  0x21,  0x09,  0x40,  0xF8,  0x88,  0x01,  0x10,  0x01,  0x08, 	/* 32210 */
+	0x01,  0x08,  0x01,  0x00,  0x7F,  0xFF,  0x01,  0x00,  0x01,  0x08,  0x01,  0x08,  0x00,  0x90,  0x00,  0xA0, 	/* 32220 */
+	0x00,  0x40,  0x00,  0xC0,  0x01,  0x22,  0x06,  0x12,  0x78,  0x0A,  0x00,  0x06,  0x89,  0x00,  0x48,  0x00, 	/* 32230 */
+	0x44,  0x00,  0x44,  0x00,  0x40,  0x1F,  0xFF,  0x10,  0x40,  0x10,  0x44,  0x10,  0x44,  0x10,  0x28,  0x10, 	/* 32240 */
+	0x28,  0x10,  0x30,  0x13,  0x10,  0x1C,  0x29,  0x70,  0x45,  0x01,  0x83,  0x0E,  0x01,  0x8A,  0x00,  0x48, 	/* 32250 */
+	0x00,  0x44,  0x00,  0x44,  0x1F,  0xFF,  0x10,  0x40,  0x10,  0x40,  0x10,  0x42,  0x10,  0x42,  0x10,  0x24, 	/* 32260 */
+	0x10,  0x24,  0x10,  0x38,  0x10,  0x10,  0x10,  0x6A,  0x21,  0x8A,  0x26,  0x06,  0x40,  0x02,  0x8C,  0x00, 	/* 32270 */
+	0x24,  0x00,  0x22,  0x00,  0x22,  0x00,  0x20,  0x1F,  0xFF,  0x10,  0x20,  0x10,  0x20,  0x10,  0x24,  0x17, 	/* 32280 */
+	0xA4,  0x10,  0x18,  0x10,  0x10,  0x10,  0x28,  0x10,  0x49,  0x21,  0x85,  0x26,  0x03,  0x40,  0x01,  0x8D, 	/* 32290 */
+	0x00,  0x24,  0x00,  0x22,  0x00,  0x22,  0x00,  0x20,  0x1F,  0xFF,  0x10,  0x20,  0x10,  0x20,  0x14,  0x24, 	/* 322A0 */
+	0x12,  0x24,  0x11,  0x18,  0x11,  0x10,  0x10,  0x28,  0x10,  0x49,  0x21,  0x85,  0x26,  0x03,  0x40,  0x01, 	/* 322B0 */
+	0x8E,  0x00,  0x48,  0x00,  0x44,  0x00,  0x44,  0x7F,  0xFF,  0x00,  0x40,  0x04,  0x44,  0x04,  0x44,  0x04, 	/* 322C0 */
+	0x24,  0x7F,  0xA8,  0x04,  0x28,  0x04,  0x10,  0x08,  0x10,  0x08,  0x2A,  0x10,  0x4A,  0x21,  0x86,  0x06, 	/* 322D0 */
+	0x02,  0x90,  0x00,  0x24,  0x00,  0x22,  0x00,  0x22,  0x1F,  0xFF,  0x10,  0x20,  0x10,  0x20,  0x10,  0x24, 	/* 322E0 */
+	0x1F,  0x24,  0x11,  0x14,  0x11,  0x14,  0x11,  0x18,  0x11,  0x18,  0x11,  0x29,  0x26,  0x45,  0x20,  0x83, 	/* 322F0 */
+	0x40,  0x01,  0x91,  0x01,  0x40,  0x02,  0x50,  0x0C,  0x48,  0x34,  0x44,  0x04,  0x40,  0x04,  0x40,  0x7F, 	/* 32300 */
+	0xFF,  0x04,  0x24,  0x04,  0x24,  0x07,  0x28,  0x0C,  0x18,  0x74,  0x10,  0x04,  0x29,  0x04,  0x45,  0x05, 	/* 32310 */
+	0x83,  0x0C,  0x01,  0x92,  0x00,  0x48,  0x00,  0x44,  0x00,  0x44,  0x7F,  0xFF,  0x00,  0x40,  0x09,  0x44, 	/* 32320 */
+	0x09,  0x44,  0x09,  0x28,  0x7F,  0xE8,  0x09,  0x30,  0x09,  0x10,  0x11,  0x30,  0x11,  0x2A,  0x21,  0x4A, 	/* 32330 */
+	0x40,  0x86,  0x01,  0x02,  0x94,  0x04,  0x80,  0x04,  0x40,  0x7F,  0xFE,  0x02,  0x10,  0x01,  0x20,  0x00, 	/* 32340 */
+	0xC2,  0x07,  0x32,  0x38,  0x0E,  0x04,  0x40,  0x04,  0x20,  0x7F,  0xFF,  0x02,  0x10,  0x01,  0x20,  0x00, 	/* 32350 */
+	0xC2,  0x07,  0x32,  0x38,  0x0E,  0x96,  0x00,  0x48,  0x00,  0x44,  0x00,  0x44,  0x7F,  0xFF,  0x00,  0x40, 	/* 32360 */
+	0x00,  0x44,  0x1F,  0x44,  0x11,  0x44,  0x11,  0x28,  0x11,  0x28,  0x1F,  0x28,  0x00,  0x92,  0x03,  0x32, 	/* 32370 */
+	0x0C,  0x4A,  0x71,  0x86,  0x06,  0x02,  0x9A,  0x00,  0x28,  0x00,  0x24,  0x00,  0x24,  0x1F,  0xFF,  0x11, 	/* 32380 */
+	0x20,  0x11,  0x22,  0x11,  0xE2,  0x11,  0x12,  0x1F,  0xF4,  0x11,  0x14,  0x15,  0x88,  0x15,  0x48,  0x19, 	/* 32390 */
+	0x5A,  0x21,  0x26,  0x23,  0x46,  0x40,  0x82,  0x9B,  0x00,  0x00,  0x7F,  0xFE,  0x01,  0x00,  0x0F,  0xF0, 	/* 323A0 */
+	0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x01,  0x04,  0x7F,  0xFF, 	/* 323B0 */
+	0x00,  0x90,  0x00,  0x62,  0x03,  0x9A,  0x3C,  0x06,  0x9D,  0x00,  0x24,  0x3E,  0x22,  0x22,  0x22,  0x22, 	/* 323C0 */
+	0x20,  0x3E,  0x3F,  0x23,  0xE0,  0x22,  0x22,  0x22,  0x22,  0x3E,  0x12,  0x22,  0x14,  0x22,  0x14,  0x3E, 	/* 323D0 */
+	0x08,  0x14,  0x19,  0x12,  0x25,  0x22,  0x43,  0x40,  0x81,  0x9E,  0x00,  0x00,  0x7F,  0xFE,  0x01,  0x00, 	/* 323E0 */
+	0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x7F,  0xFE,  0x42,  0x22,  0x42,  0x12,  0x3F,  0xFC, 	/* 323F0 */
+	0x01,  0x10,  0x00,  0xA0,  0x00,  0xC2,  0x03,  0x32,  0x3C,  0x0E,  0x9F,  0x04,  0x20,  0x04,  0x28,  0x7F, 	/* 32400 */
+	0xA4,  0x04,  0x20,  0x04,  0x27,  0x3F,  0xF8,  0x21,  0x24,  0x3F,  0x24,  0x21,  0x24,  0x21,  0x28,  0x3F, 	/* 32410 */
+	0x18,  0x04,  0x12,  0x7F,  0xAA,  0x04,  0x2A,  0x04,  0x46,  0x04,  0x82,  0xA1,  0x11,  0x14,  0x11,  0x12, 	/* 32420 */
+	0x7F,  0xD2,  0x11,  0x10,  0x1F,  0x17,  0x11,  0xF8,  0x1F,  0x12,  0x11,  0x12,  0x11,  0x12,  0x7F,  0xD4, 	/* 32430 */
+	0x2A,  0x0C,  0x2A,  0x08,  0x33,  0x95,  0x20,  0x25,  0x3F,  0xC3,  0x00,  0x81,  0xA6,  0x08,  0x90,  0x24, 	/* 32440 */
+	0x94,  0x15,  0x12,  0x12,  0x12,  0x3F,  0x9F,  0x24,  0xF0,  0x24,  0x92,  0x3F,  0x92,  0x24,  0x92,  0x3F, 	/* 32450 */
+	0x94,  0x04,  0x0C,  0x04,  0x08,  0x7F,  0xCD,  0x04,  0x15,  0x04,  0x23,  0x04,  0x41,  0xAA,  0x02,  0x10, 	/* 32460 */
+	0x02,  0x14,  0x3F,  0xD2,  0x02,  0x12,  0x02,  0x10,  0x7F,  0xFF,  0x08,  0x90,  0x09,  0x12,  0x1F,  0xD2, 	/* 32470 */
+	0x32,  0x14,  0x5F,  0xCC,  0x12,  0x08,  0x1F,  0xCD,  0x12,  0x15,  0x1F,  0xE3,  0x00,  0x41,  0xAE,  0x00, 	/* 32480 */
+	0x14,  0x7F,  0x92,  0x2A,  0x92,  0x4C,  0x90,  0x19,  0x9F,  0x2A,  0xF0,  0x4C,  0x92,  0x0C,  0x12,  0x12, 	/* 32490 */
+	0x12,  0x25,  0x8C,  0x5A,  0x0C,  0x04,  0x08,  0x39,  0x15,  0x02,  0x25,  0x0C,  0x43,  0x70,  0x81,  0xAF, 	/* 324A0 */
+	0x08,  0x18,  0x0F,  0x14,  0x08,  0x14,  0x3F,  0xD3,  0x28,  0x9C,  0x2E,  0x72,  0x38,  0x92,  0x27,  0x92, 	/* 324B0 */
+	0x2A,  0x14,  0x2A,  0x94,  0x2B,  0x08,  0x3A,  0x08,  0x2A,  0x95,  0x2B,  0x25,  0x4C,  0x43,  0x30,  0x01, 	/* 324C0 */
+	0xB0,  0x00,  0x14,  0x7B,  0xD2,  0x4A,  0x52,  0x7B,  0xD0,  0x00,  0x1F,  0x3F,  0xF0,  0x24,  0x92,  0x3F, 	/* 324D0 */
+	0x92,  0x24,  0x94,  0x24,  0x94,  0x3F,  0x88,  0x04,  0x08,  0x7F,  0x95,  0x04,  0x23,  0x04,  0x43,  0x04, 	/* 324E0 */
+	0x81,  0xB2,  0x02,  0x14,  0x03,  0xD2,  0x02,  0x12,  0x1F,  0xF0,  0x12,  0x3F,  0x1F,  0xD0,  0x12,  0x12, 	/* 324F0 */
+	0x11,  0xD2,  0x1F,  0xD2,  0x10,  0x14,  0x17,  0xCC,  0x14,  0x48,  0x27,  0xCD,  0x22,  0x95,  0x41,  0xE3, 	/* 32500 */
+	0x0E,  0x41,  0xB3,  0x00,  0x14,  0x7B,  0xD2,  0x29,  0x52,  0x5A,  0xD0,  0x29,  0x57,  0x4A,  0x78,  0x11, 	/* 32510 */
+	0x12,  0x12,  0x12,  0x3F,  0x94,  0x64,  0x14,  0x3F,  0x88,  0x24,  0x09,  0x3F,  0x95,  0x24,  0x25,  0x3F, 	/* 32520 */
+	0xC3,  0x00,  0x81,  0xB4,  0x02,  0x18,  0x1F,  0xD4,  0x02,  0x14,  0x7F,  0xFF,  0x00,  0x10,  0x1F,  0xD2, 	/* 32530 */
+	0x12,  0x52,  0x1F,  0xD2,  0x12,  0x54,  0x1F,  0xCC,  0x09,  0x08,  0x3F,  0xE8,  0x09,  0x15,  0x7F,  0xE5, 	/* 32540 */
+	0x09,  0x43,  0x30,  0x81,  0xB8,  0x00,  0x00,  0x7F,  0xFE,  0x00,  0x00,  0x00,  0x00,  0x1F,  0xFC,  0x10, 	/* 32550 */
+	0x04,  0x10,  0x04,  0x10,  0x04,  0x1F,  0xFC,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x20, 	/* 32560 */
+	0x00,  0x20,  0x00,  0x40,  0x00,  0xBB,  0x00,  0x00,  0x3F,  0xFF,  0x00,  0x00,  0x1F,  0xFC,  0x10,  0x04, 	/* 32570 */
+	0x10,  0x04,  0x1F,  0xFC,  0x10,  0x40,  0x10,  0x40,  0x1F,  0xFF,  0x10,  0x40,  0x10,  0xC0,  0x20,  0xA0, 	/* 32580 */
+	0x21,  0x10,  0x46,  0x08,  0x18,  0x06,  0xBF,  0x00,  0x00,  0x7F,  0xFE,  0x00,  0x00,  0x1F,  0xF8,  0x10, 	/* 32590 */
+	0x08,  0x10,  0x08,  0x1F,  0xF8,  0x10,  0x80,  0x10,  0x80,  0x1F,  0xFE,  0x11,  0x00,  0x11,  0xF8,  0x21, 	/* 325A0 */
+	0x08,  0x22,  0x08,  0x44,  0x08,  0x18,  0x30,  0x80,  0x00,  0x02,  0x3F,  0x8C,  0x00,  0x70,  0x00,  0x40, 	/* 325B0 */
+	0x1F,  0x40,  0x11,  0x7F,  0x11,  0x44,  0x11,  0x44,  0x1F,  0x44,  0x10,  0x44,  0x10,  0x44,  0x10,  0x84, 	/* 325C0 */
+	0x10,  0x84,  0x21,  0x04,  0x22,  0x04,  0x40,  0x04,  0x81,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x00,  0x1F, 	/* 325D0 */
+	0xFC,  0x10,  0x04,  0x10,  0x04,  0x1F,  0xFC,  0x10,  0x00,  0x1F,  0xFC,  0x19,  0x24,  0x19,  0x24,  0x1F, 	/* 325E0 */
+	0xFC,  0x29,  0x24,  0x29,  0x24,  0x49,  0x24,  0x09,  0x2C,  0x87,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x00, 	/* 325F0 */
+	0x1F,  0xFC,  0x10,  0x04,  0x10,  0x04,  0x1F,  0xFC,  0x10,  0x00,  0x1F,  0xBE,  0x10,  0x82,  0x18,  0xA2, 	/* 32600 */
+	0x14,  0x92,  0x22,  0x86,  0x2C,  0x9A,  0x50,  0xA2,  0x01,  0x86,  0x88,  0x00,  0x00,  0x3F,  0xFF,  0x00, 	/* 32610 */
+	0x00,  0x1F,  0xFE,  0x10,  0x02,  0x1F,  0xFE,  0x10,  0x00,  0x13,  0xF8,  0x12,  0x08,  0x13,  0xF8,  0x17, 	/* 32620 */
+	0xFC,  0x14,  0x44,  0x27,  0xFC,  0x24,  0x01,  0x44,  0x01,  0x03,  0xFF,  0x89,  0x00,  0x00,  0x3F,  0xFF, 	/* 32630 */
+	0x00,  0x00,  0x1F,  0xFE,  0x10,  0x02,  0x1F,  0xFE,  0x10,  0x90,  0x10,  0x90,  0x17,  0x9E,  0x10,  0x90, 	/* 32640 */
+	0x17,  0x9E,  0x10,  0x90,  0x23,  0x90,  0x2D,  0x1F,  0x41,  0x10,  0x02,  0x10,  0x8B,  0x00,  0x08,  0x00, 	/* 32650 */
+	0x30,  0x0F,  0xC0,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 32660 */
+	0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x01,  0x80,  0x8D,  0x00,  0x40, 	/* 32670 */
+	0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0x7F,  0xFE,  0x00,  0x40,  0x00,  0x48,  0x00,  0x50,  0x00,  0x60, 	/* 32680 */
+	0x00,  0xC0,  0x01,  0x40,  0x06,  0x40,  0x18,  0x40,  0x60,  0x40,  0x00,  0x40,  0x00,  0xC0,  0x8E,  0x08, 	/* 32690 */
+	0x40,  0x08,  0x40,  0x08,  0x40,  0x08,  0x40,  0x7F,  0x40,  0x08,  0x40,  0x08,  0x40,  0x08,  0x40,  0x0B, 	/* 326A0 */
+	0x40,  0x1C,  0x40,  0x68,  0x40,  0x08,  0x41,  0x08,  0x41,  0x08,  0x21,  0x08,  0x1F,  0x18,  0x00,  0x93, 	/* 326B0 */
+	0x08,  0x00,  0x08,  0x00,  0x09,  0xFF,  0x08,  0x08,  0x7E,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08, 	/* 326C0 */
+	0x08,  0x08,  0x0E,  0x08,  0x78,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x18,  0x18, 	/* 326D0 */
+	0x95,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x7E,  0x20,  0x08,  0x20,  0x08,  0x40,  0x08, 	/* 326E0 */
+	0x40,  0x0E,  0x50,  0x78,  0x48,  0x08,  0x88,  0x08,  0x84,  0x08,  0x84,  0x09,  0x3E,  0x0F,  0xC2,  0x18, 	/* 326F0 */
+	0x02,  0x98,  0x08,  0x04,  0x08,  0x18,  0x09,  0xE0,  0x08,  0x40,  0x7E,  0x40,  0x08,  0x40,  0x08,  0x4F, 	/* 32700 */
+	0x0B,  0xF0,  0x0E,  0x40,  0x78,  0x40,  0x08,  0x40,  0x08,  0x40,  0x08,  0x40,  0x08,  0x42,  0x08,  0x22, 	/* 32710 */
+	0x18,  0x1E,  0x9B,  0x08,  0x00,  0x08,  0x00,  0x09,  0xFE,  0x08,  0x20,  0x7E,  0x20,  0x08,  0x20,  0x08, 	/* 32720 */
+	0x20,  0x08,  0x20,  0x0E,  0x20,  0x18,  0x20,  0x68,  0x20,  0x08,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x08, 	/* 32730 */
+	0x00,  0x18,  0x00,  0x9E,  0x08,  0x00,  0x08,  0xFE,  0x08,  0x10,  0x08,  0x10,  0x7E,  0x10,  0x08,  0x10, 	/* 32740 */
+	0x08,  0x10,  0x09,  0xFF,  0x0E,  0x10,  0x18,  0x10,  0x68,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10, 	/* 32750 */
+	0x08,  0x10,  0x18,  0x10,  0xA0,  0x10,  0x00,  0x13,  0xFC,  0x10,  0x04,  0x11,  0x04,  0x7D,  0x44,  0x11, 	/* 32760 */
+	0x24,  0x10,  0xA8,  0x10,  0x88,  0x1C,  0x48,  0x70,  0x50,  0x10,  0x30,  0x10,  0x30,  0x10,  0x48,  0x10, 	/* 32770 */
+	0x84,  0x13,  0x02,  0x3C,  0x01,  0xA3,  0x10,  0x00,  0x11,  0xFE,  0x11,  0x02,  0x11,  0x02,  0x7D,  0x02, 	/* 32780 */
+	0x11,  0x02,  0x11,  0x02,  0x11,  0x02,  0x11,  0x02,  0x1D,  0x02,  0x71,  0x02,  0x11,  0x02,  0x11,  0x02, 	/* 32790 */
+	0x11,  0x02,  0x11,  0xFE,  0x30,  0x00,  0xA8,  0x10,  0x00,  0x13,  0xFC,  0x10,  0x44,  0x10,  0x44,  0x7C, 	/* 327A0 */
+	0x44,  0x10,  0x44,  0x11,  0x44,  0x10,  0xC4,  0x1C,  0x44,  0x70,  0x64,  0x10,  0x5C,  0x10,  0x87,  0x10, 	/* 327B0 */
+	0x84,  0x11,  0x04,  0x12,  0x08,  0x34,  0x30,  0xAE,  0x10,  0x78,  0x10,  0x08,  0x10,  0x48,  0x10,  0x44, 	/* 327C0 */
+	0x7C,  0x84,  0x10,  0x82,  0x11,  0x01,  0x13,  0xFC,  0x1C,  0x44,  0x70,  0x44,  0x10,  0x44,  0x10,  0x44, 	/* 327D0 */
+	0x10,  0x84,  0x10,  0x84,  0x11,  0x04,  0x32,  0x18,  0xB1,  0x10,  0x00,  0x13,  0xF8,  0x10,  0x88,  0x10, 	/* 327E0 */
+	0x88,  0x7E,  0x90,  0x10,  0x90,  0x10,  0xBC,  0x10,  0xC4,  0x11,  0x44,  0x1D,  0x24,  0x71,  0x28,  0x11, 	/* 327F0 */
+	0x10,  0x12,  0x18,  0x12,  0x24,  0x14,  0xC2,  0x3B,  0x01,  0xB6,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20, 	/* 32800 */
+	0x11,  0xFC,  0x7C,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x1B,  0xFF,  0x70,  0x50,  0x10,  0x50, 	/* 32810 */
+	0x10,  0x88,  0x10,  0x88,  0x11,  0x04,  0x12,  0x02,  0x34,  0x01,  0xB9,  0x12,  0x20,  0x12,  0x20,  0x12, 	/* 32820 */
+	0x20,  0x12,  0x20,  0x7E,  0x24,  0x12,  0x24,  0x13,  0xE8,  0x12,  0x30,  0x1E,  0x20,  0x72,  0x20,  0x12, 	/* 32830 */
+	0x20,  0x12,  0x20,  0x12,  0x21,  0x12,  0xE1,  0x13,  0x1F,  0x3C,  0x00,  0xBC,  0x10,  0x00,  0x11,  0xFF, 	/* 32840 */
+	0x11,  0x00,  0x11,  0x00,  0x7D,  0x7C,  0x11,  0x44,  0x11,  0x44,  0x11,  0x44,  0x1D,  0x44,  0x71,  0x58, 	/* 32850 */
+	0x11,  0x40,  0x11,  0x42,  0x12,  0x42,  0x12,  0x42,  0x14,  0x22,  0x30,  0x1E,  0xBE,  0x10,  0x48,  0x10, 	/* 32860 */
+	0x44,  0x10,  0x44,  0x10,  0x40,  0x7F,  0xFF,  0x10,  0x40,  0x10,  0x44,  0x10,  0x44,  0x1C,  0x48,  0x70, 	/* 32870 */
+	0x28,  0x10,  0x30,  0x10,  0x22,  0x10,  0x52,  0x11,  0x8A,  0x16,  0x06,  0x30,  0x02,  0xBF,  0x00,  0x00, 	/* 32880 */
+	0x0F,  0xF0,  0x00,  0x20,  0x00,  0x40,  0x00,  0x92,  0x78,  0x92,  0x0F,  0xF4,  0x08,  0x88,  0x0F,  0xF8, 	/* 32890 */
+	0x08,  0x88,  0x10,  0x84,  0x1F,  0xFC,  0x20,  0x82,  0x40,  0x81,  0x00,  0x80,  0x01,  0x80,  0x80,  0x10, 	/* 328A0 */
+	0x20,  0x10,  0x20,  0x10,  0x20,  0x13,  0xFF,  0x7C,  0x20,  0x10,  0x20,  0x10,  0x20,  0x13,  0xFC,  0x10, 	/* 328B0 */
+	0x84,  0x1C,  0x88,  0x70,  0x48,  0x10,  0x30,  0x10,  0x30,  0x10,  0x48,  0x11,  0x84,  0x36,  0x03,  0x82, 	/* 328C0 */
+	0x10,  0x00,  0x13,  0xFE,  0x10,  0x20,  0x10,  0x20,  0x7C,  0x20,  0x10,  0x20,  0x10,  0x20,  0x11,  0xFC, 	/* 328D0 */
+	0x1C,  0x20,  0x70,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x17,  0xFF,  0x30,  0x00, 	/* 328E0 */
+	0x83,  0x08,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x08,  0x20,  0x7E,  0x20,  0x08,  0x20,  0x08,  0x30,  0x08, 	/* 328F0 */
+	0x28,  0x0E,  0x24,  0x78,  0x24,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x18, 	/* 32900 */
+	0x20,  0x84,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x11,  0x28,  0x7D,  0x24,  0x11,  0x24,  0x12,  0x22, 	/* 32910 */
+	0x14,  0x22,  0x10,  0x25,  0x1C,  0x64,  0x70,  0x08,  0x10,  0x08,  0x10,  0x10,  0x10,  0x20,  0x10,  0xC0, 	/* 32920 */
+	0x33,  0x00,  0x89,  0x10,  0x40,  0x10,  0x40,  0x10,  0x40,  0x13,  0xFC,  0x7C,  0x44,  0x10,  0x44,  0x10, 	/* 32930 */
+	0x44,  0x10,  0x44,  0x1F,  0xFF,  0x70,  0x40,  0x10,  0x60,  0x10,  0xA0,  0x10,  0x90,  0x11,  0x08,  0x12, 	/* 32940 */
+	0x04,  0x34,  0x02,  0x8A,  0x10,  0x00,  0x11,  0xFC,  0x11,  0x24,  0x11,  0x24,  0x7D,  0x24,  0x11,  0x24, 	/* 32950 */
+	0x11,  0x24,  0x11,  0xFC,  0x1D,  0x00,  0x71,  0x00,  0x11,  0x00,  0x11,  0x02,  0x11,  0x02,  0x10,  0x82, 	/* 32960 */
+	0x10,  0x7E,  0x30,  0x00,  0x91,  0x10,  0x40,  0x10,  0x80,  0x13,  0x3E,  0x12,  0x22,  0x7E,  0x22,  0x12, 	/* 32970 */
+	0x22,  0x12,  0x22,  0x12,  0x22,  0x1E,  0x22,  0x72,  0x22,  0x12,  0x62,  0x13,  0xA2,  0x16,  0x2C,  0x10, 	/* 32980 */
+	0x20,  0x10,  0x20,  0x30,  0x20,  0x92,  0x10,  0x00,  0x11,  0xFC,  0x10,  0x04,  0x10,  0xC8,  0x7C,  0x30, 	/* 32990 */
+	0x10,  0x10,  0x17,  0xFF,  0x10,  0x22,  0x1C,  0x24,  0x70,  0x28,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20, 	/* 329A0 */
+	0x10,  0x20,  0x10,  0x20,  0x30,  0x60,  0x93,  0x10,  0x04,  0x10,  0x18,  0x11,  0xE8,  0x11,  0x08,  0x7D, 	/* 329B0 */
+	0x28,  0x11,  0x28,  0x11,  0x28,  0x11,  0x28,  0x11,  0x28,  0x1D,  0x28,  0x71,  0x28,  0x11,  0x28,  0x12, 	/* 329C0 */
+	0x24,  0x12,  0x24,  0x14,  0x22,  0x38,  0x01,  0x94,  0x10,  0x00,  0x17,  0xFF,  0x10,  0x20,  0x10,  0x20, 	/* 329D0 */
+	0x7C,  0x20,  0x10,  0x40,  0x10,  0x50,  0x10,  0xC8,  0x1C,  0xC4,  0x71,  0x42,  0x12,  0x42,  0x14,  0x40, 	/* 329E0 */
+	0x10,  0x40,  0x10,  0x40,  0x10,  0x40,  0x30,  0x40,  0x95,  0x10,  0x00,  0x10,  0xF8,  0x10,  0x88,  0x10, 	/* 329F0 */
+	0x88,  0x7C,  0x89,  0x11,  0x09,  0x11,  0x07,  0x12,  0x00,  0x1D,  0xF8,  0x70,  0x88,  0x10,  0x88,  0x10, 	/* 32A00 */
+	0x50,  0x10,  0x20,  0x10,  0x50,  0x10,  0x8C,  0x33,  0x03,  0x96,  0x08,  0x04,  0x08,  0x44,  0x08,  0x24, 	/* 32A10 */
+	0x08,  0x24,  0x7E,  0x04,  0x08,  0x04,  0x08,  0x84,  0x08,  0x44,  0x0E,  0x44,  0x18,  0x07,  0x68,  0x3C, 	/* 32A20 */
+	0x09,  0xC4,  0x08,  0x04,  0x08,  0x04,  0x08,  0x04,  0x18,  0x04,  0x97,  0x10,  0x20,  0x10,  0x20,  0x10, 	/* 32A30 */
+	0x20,  0x13,  0xFF,  0x7C,  0x00,  0x10,  0x00,  0x10,  0xF0,  0x10,  0x90,  0x1C,  0x90,  0x70,  0x90,  0x10, 	/* 32A40 */
+	0x90,  0x10,  0x90,  0x11,  0x10,  0x11,  0x12,  0x12,  0x12,  0x34,  0x0E,  0x98,  0x08,  0x04,  0x08,  0x18, 	/* 32A50 */
+	0x08,  0xE0,  0x08,  0x80,  0x7E,  0x80,  0x08,  0xFF,  0x08,  0x88,  0x08,  0x88,  0x0E,  0x88,  0x78,  0x88, 	/* 32A60 */
+	0x08,  0x88,  0x08,  0x88,  0x09,  0x08,  0x09,  0x08,  0x0A,  0x08,  0x18,  0x08,  0x9B,  0x12,  0x10,  0x12, 	/* 32A70 */
+	0x10,  0x12,  0x10,  0x12,  0x7E,  0x7F,  0x92,  0x12,  0x92,  0x12,  0x92,  0x12,  0x92,  0x1A,  0x92,  0x72, 	/* 32A80 */
+	0xA2,  0x12,  0xA2,  0x12,  0xC2,  0x14,  0x8C,  0x14,  0x81,  0x18,  0x41,  0x30,  0x3F,  0x9C,  0x10,  0x40, 	/* 32A90 */
+	0x10,  0x40,  0x10,  0x40,  0x13,  0xFF,  0x7C,  0x40,  0x10,  0x40,  0x10,  0xFC,  0x10,  0x84,  0x1C,  0xC4, 	/* 32AA0 */
+	0x70,  0xA8,  0x11,  0x28,  0x11,  0x10,  0x12,  0x30,  0x14,  0x48,  0x10,  0x84,  0x33,  0x02,  0x9E,  0x10, 	/* 32AB0 */
+	0x00,  0x10,  0xFE,  0x10,  0x82,  0x10,  0x82,  0x7E,  0x82,  0x10,  0x82,  0x10,  0xFE,  0x10,  0xA0,  0x10, 	/* 32AC0 */
+	0xA0,  0x1C,  0x90,  0x70,  0x90,  0x11,  0x08,  0x11,  0x08,  0x12,  0x04,  0x14,  0x02,  0x38,  0x01,  0xAB, 	/* 32AD0 */
+	0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x11,  0xFF,  0x7D,  0x11,  0x11,  0x12,  0x11,  0x10,  0x11,  0xFC, 	/* 32AE0 */
+	0x1D,  0x44,  0x71,  0x44,  0x11,  0x28,  0x12,  0x28,  0x12,  0x10,  0x14,  0x28,  0x18,  0xC4,  0x33,  0x03, 	/* 32AF0 */
+	0xAC,  0x10,  0x40,  0x10,  0x40,  0x10,  0x40,  0x10,  0x50,  0x7C,  0x88,  0x10,  0x84,  0x11,  0x1C,  0x13, 	/* 32B00 */
+	0xE2,  0x1C,  0x02,  0x70,  0x00,  0x11,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x30, 	/* 32B10 */
+	0x00,  0xB1,  0x10,  0x80,  0x10,  0x80,  0x10,  0xFE,  0x10,  0x82,  0x7D,  0x02,  0x11,  0xF2,  0x11,  0x12, 	/* 32B20 */
+	0x12,  0x12,  0x1C,  0x12,  0x71,  0xF2,  0x11,  0x04,  0x11,  0x18,  0x11,  0x01,  0x11,  0x01,  0x10,  0x81, 	/* 32B30 */
+	0x30,  0x7F,  0xB5,  0x10,  0x04,  0x10,  0x18,  0x11,  0xF0,  0x11,  0x10,  0x7D,  0x10,  0x11,  0x10,  0x11, 	/* 32B40 */
+	0xFF,  0x11,  0x10,  0x1D,  0x10,  0x71,  0x10,  0x11,  0x08,  0x11,  0xCA,  0x17,  0x0A,  0x10,  0x06,  0x17, 	/* 32B50 */
+	0xF6,  0x30,  0x02,  0xB9,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x17,  0xFF,  0x7C,  0x20,  0x10,  0x20, 	/* 32B60 */
+	0x10,  0x20,  0x13,  0xFE,  0x1C,  0x70,  0x70,  0x70,  0x10,  0xA8,  0x10,  0xA8,  0x11,  0x24,  0x12,  0x22, 	/* 32B70 */
+	0x14,  0x21,  0x30,  0x20,  0xBB,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x11,  0xFE,  0x7D,  0x22,  0x11, 	/* 32B80 */
+	0x22,  0x11,  0x22,  0x11,  0xFE,  0x1D,  0x22,  0x71,  0x22,  0x11,  0xFE,  0x10,  0x20,  0x10,  0x20,  0x10, 	/* 32B90 */
+	0x20,  0x10,  0x20,  0x30,  0x20,  0xBC,  0x10,  0x00,  0x11,  0xFE,  0x11,  0x22,  0x11,  0x22,  0x7D,  0x22, 	/* 32BA0 */
+	0x11,  0xFE,  0x11,  0x22,  0x11,  0x22,  0x11,  0x22,  0x1D,  0xFE,  0x70,  0x20,  0x10,  0x20,  0x10,  0x20, 	/* 32BB0 */
+	0x10,  0x20,  0x10,  0x20,  0x30,  0x20,  0xBD,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x7D, 	/* 32BC0 */
+	0xFE,  0x11,  0x22,  0x11,  0x22,  0x11,  0x22,  0x11,  0x22,  0x1D,  0xFE,  0x71,  0x22,  0x11,  0x22,  0x11, 	/* 32BD0 */
+	0x22,  0x11,  0x22,  0x11,  0xFE,  0x30,  0x00,  0x82,  0x10,  0x50,  0x10,  0x50,  0x13,  0xFE,  0x10,  0x52, 	/* 32BE0 */
+	0x7C,  0x52,  0x13,  0xFE,  0x12,  0x50,  0x12,  0x50,  0x1B,  0xFE,  0x70,  0x52,  0x10,  0x52,  0x10,  0x92, 	/* 32BF0 */
+	0x10,  0x92,  0x11,  0x1C,  0x12,  0x10,  0x34,  0x10,  0x85,  0x10,  0x00,  0x11,  0xFC,  0x11,  0x04,  0x11, 	/* 32C00 */
+	0x04,  0x7D,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x11,  0x04,  0x1D,  0x04,  0x71,  0x04,  0x11,  0x04,  0x11, 	/* 32C10 */
+	0xFC,  0x10,  0x00,  0x10,  0x00,  0x17,  0xFF,  0x30,  0x00,  0x86,  0x10,  0x02,  0x10,  0x0C,  0x10,  0xF0, 	/* 32C20 */
+	0x10,  0x80,  0x7C,  0x80,  0x10,  0xFF,  0x10,  0x88,  0x10,  0x88,  0x1C,  0xB8,  0x70,  0x8E,  0x10,  0x89, 	/* 32C30 */
+	0x10,  0x88,  0x11,  0x08,  0x11,  0x08,  0x12,  0x08,  0x30,  0x08,  0x87,  0x10,  0x00,  0x11,  0xFC,  0x11, 	/* 32C40 */
+	0x04,  0x11,  0x44,  0x7D,  0x24,  0x11,  0x24,  0x11,  0x04,  0x17,  0xFF,  0x12,  0x04,  0x1E,  0x44,  0x72, 	/* 32C50 */
+	0x24,  0x12,  0x24,  0x13,  0xFF,  0x10,  0x04,  0x10,  0x08,  0x30,  0x30,  0x88,  0x08,  0x20,  0x08,  0x20, 	/* 32C60 */
+	0x08,  0x20,  0x08,  0x20,  0x7E,  0x3F,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x0E,  0x20,  0x19,  0xFC, 	/* 32C70 */
+	0x69,  0x04,  0x09,  0x04,  0x09,  0x04,  0x09,  0x04,  0x09,  0xFC,  0x18,  0x00,  0x89,  0x10,  0x20,  0x10, 	/* 32C80 */
+	0x20,  0x10,  0x20,  0x13,  0xFE,  0x7C,  0x00,  0x10,  0x08,  0x11,  0x08,  0x11,  0x08,  0x1C,  0x88,  0x70, 	/* 32C90 */
+	0x88,  0x10,  0x90,  0x10,  0x90,  0x10,  0x10,  0x10,  0x20,  0x17,  0xFF,  0x30,  0x00,  0x8A,  0x10,  0x84, 	/* 32CA0 */
+	0x10,  0x84,  0x10,  0x84,  0x11,  0x04,  0x7D,  0x7F,  0x13,  0x04,  0x13,  0x04,  0x15,  0x44,  0x11,  0x24, 	/* 32CB0 */
+	0x1D,  0x24,  0x71,  0x04,  0x11,  0x04,  0x11,  0x04,  0x11,  0x04,  0x11,  0x04,  0x31,  0x0C,  0x8C,  0x10, 	/* 32CC0 */
+	0x20,  0x10,  0xA8,  0x10,  0xA4,  0x11,  0x22,  0x7E,  0x22,  0x11,  0xFC,  0x10,  0x20,  0x10,  0x20,  0x1C, 	/* 32CD0 */
+	0x20,  0x73,  0xFF,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x30,  0x20,  0x8D, 	/* 32CE0 */
+	0x08,  0x10,  0x08,  0x10,  0x08,  0x20,  0x08,  0xFE,  0x7E,  0x82,  0x08,  0x82,  0x08,  0x82,  0x0A,  0x82, 	/* 32CF0 */
+	0x0C,  0xFE,  0x18,  0x82,  0x68,  0x82,  0x08,  0x82,  0x08,  0x82,  0x08,  0x82,  0x08,  0xFE,  0x18,  0x00, 	/* 32D00 */
+	0x8F,  0x04,  0x00,  0x04,  0x00,  0x7F,  0x7E,  0x09,  0x22,  0x11,  0x14,  0x3E,  0x08,  0x05,  0x34,  0x19, 	/* 32D10 */
+	0xC3,  0x60,  0x10,  0x0F,  0xE0,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x01, 	/* 32D20 */
+	0x80,  0x90,  0x08,  0x00,  0x08,  0xFC,  0x08,  0x84,  0x08,  0x84,  0x7E,  0x84,  0x08,  0xFC,  0x08,  0x00, 	/* 32D30 */
+	0x08,  0x00,  0x09,  0xFE,  0x0E,  0x22,  0x78,  0x22,  0x08,  0x22,  0x08,  0x42,  0x08,  0x42,  0x08,  0x82, 	/* 32D40 */
+	0x19,  0x0C,  0x91,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x13,  0xFF,  0x7C,  0x84,  0x10,  0x84,  0x10, 	/* 32D50 */
+	0x84,  0x10,  0x84,  0x1C,  0xFC,  0x70,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10, 	/* 32D60 */
+	0xFC,  0x30,  0x00,  0x92,  0x08,  0x00,  0x08,  0xFE,  0x08,  0x80,  0x08,  0x80,  0x7E,  0x80,  0x08,  0xFC, 	/* 32D70 */
+	0x08,  0x84,  0x08,  0x84,  0x08,  0x84,  0x0E,  0xFC,  0x78,  0x80,  0x08,  0x80,  0x08,  0x80,  0x08,  0x80, 	/* 32D80 */
+	0x08,  0xFF,  0x18,  0x00,  0x93,  0x10,  0x00,  0x13,  0xFF,  0x10,  0x40,  0x10,  0x40,  0x7C,  0x40,  0x10, 	/* 32D90 */
+	0x40,  0x10,  0x80,  0x10,  0xFE,  0x11,  0x82,  0x1D,  0x82,  0x72,  0x82,  0x14,  0x82,  0x10,  0x82,  0x10, 	/* 32DA0 */
+	0x82,  0x10,  0xFE,  0x30,  0x00,  0x94,  0x10,  0x48,  0x10,  0x44,  0x10,  0x44,  0x13,  0xFF,  0x7C,  0x40, 	/* 32DB0 */
+	0x10,  0x44,  0x10,  0x44,  0x10,  0x44,  0x1C,  0xA8,  0x70,  0xA8,  0x11,  0x10,  0x11,  0x10,  0x12,  0x28, 	/* 32DC0 */
+	0x14,  0x44,  0x10,  0x82,  0x31,  0x01,  0x97,  0x10,  0x88,  0x10,  0x88,  0x10,  0x88,  0x10,  0x88,  0x7D, 	/* 32DD0 */
+	0x3E,  0x11,  0x4A,  0x16,  0x4A,  0x11,  0x4A,  0x1C,  0x8A,  0x70,  0x8A,  0x11,  0x92,  0x11,  0x52,  0x12, 	/* 32DE0 */
+	0x52,  0x1F,  0xA2,  0x10,  0x42,  0x30,  0x8C,  0x98,  0x10,  0x80,  0x10,  0x80,  0x10,  0x80,  0x10,  0xFE, 	/* 32DF0 */
+	0x7D,  0x02,  0x11,  0x02,  0x12,  0xF2,  0x14,  0x92,  0x10,  0x92,  0x1C,  0x92,  0x70,  0x92,  0x10,  0xF2, 	/* 32E00 */
+	0x10,  0x02,  0x10,  0x02,  0x10,  0x04,  0x30,  0x18,  0x99,  0x10,  0x20,  0x10,  0x20,  0x11,  0x22,  0x11, 	/* 32E10 */
+	0x22,  0x7D,  0x22,  0x11,  0x22,  0x11,  0xFE,  0x11,  0x22,  0x1C,  0x20,  0x70,  0x20,  0x11,  0x22,  0x11, 	/* 32E20 */
+	0x22,  0x11,  0x22,  0x11,  0x22,  0x11,  0xFE,  0x31,  0x02,  0x9B,  0x10,  0x00,  0x17,  0xFE,  0x10,  0x42, 	/* 32E30 */
+	0x10,  0x42,  0x7C,  0x42,  0x10,  0x82,  0x10,  0x82,  0x11,  0x0C,  0x1E,  0x00,  0x75,  0xFC,  0x11,  0x04, 	/* 32E40 */
+	0x11,  0x04,  0x11,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x30,  0x00,  0x9C,  0x02,  0x00,  0x0D,  0xFF,  0x78, 	/* 32E50 */
+	0x10,  0x08,  0x10,  0x08,  0xFE,  0x7E,  0x10,  0x08,  0x10,  0x08,  0xFE,  0x0E,  0x10,  0x18,  0x10,  0x68, 	/* 32E60 */
+	0x10,  0x09,  0xFF,  0x10,  0x10,  0x10,  0x10,  0x20,  0x10,  0x40,  0x10,  0x9D,  0x10,  0x00,  0x13,  0xFF, 	/* 32E70 */
+	0x10,  0x20,  0x10,  0x20,  0x7D,  0xFE,  0x10,  0x20,  0x10,  0x20,  0x11,  0xFE,  0x1C,  0x20,  0x70,  0x20, 	/* 32E80 */
+	0x10,  0x20,  0x13,  0xFF,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x30,  0x20,  0xA0,  0x11,  0x00,  0x11, 	/* 32E90 */
+	0x1C,  0x11,  0x14,  0x11,  0x14,  0x7F,  0xD4,  0x12,  0x54,  0x12,  0x54,  0x15,  0x54,  0x14,  0x94,  0x18, 	/* 32EA0 */
+	0xA4,  0x71,  0xA5,  0x11,  0x45,  0x12,  0x43,  0x14,  0x20,  0x18,  0x18,  0x30,  0x07,  0xA1,  0x10,  0x10, 	/* 32EB0 */
+	0x10,  0x10,  0x10,  0x10,  0x11,  0xFF,  0x7D,  0x00,  0x11,  0x10,  0x11,  0x10,  0x11,  0x10,  0x11,  0x10, 	/* 32EC0 */
+	0x1D,  0x10,  0x71,  0x24,  0x12,  0x24,  0x12,  0x42,  0x12,  0x5E,  0x15,  0xE1,  0x38,  0x01,  0xAC,  0x10, 	/* 32ED0 */
+	0x04,  0x10,  0x18,  0x11,  0xE0,  0x10,  0x20,  0x7C,  0x20,  0x10,  0x20,  0x13,  0xFF,  0x10,  0x20,  0x1C, 	/* 32EE0 */
+	0x20,  0x70,  0x20,  0x11,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x30,  0x00,  0xAD, 	/* 32EF0 */
+	0x10,  0x10,  0x10,  0x14,  0x10,  0x12,  0x10,  0x12,  0x7F,  0xFF,  0x10,  0x10,  0x10,  0x10,  0x13,  0xF0, 	/* 32F00 */
+	0x1C,  0x88,  0x70,  0x88,  0x10,  0x88,  0x10,  0xA8,  0x10,  0xC5,  0x13,  0x05,  0x10,  0x03,  0x30,  0x01, 	/* 32F10 */
+	0xAE,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x13,  0xFF,  0x7C,  0x20,  0x10,  0x20,  0x10,  0x20,  0x11, 	/* 32F20 */
+	0xFE,  0x1C,  0x00,  0x70,  0x00,  0x11,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x30, 	/* 32F30 */
+	0x00,  0xAF,  0x10,  0x00,  0x13,  0xFC,  0x10,  0x08,  0x10,  0x10,  0x7C,  0x22,  0x13,  0xA2,  0x10,  0xB4, 	/* 32F40 */
+	0x10,  0xB4,  0x1D,  0x28,  0x71,  0x24,  0x12,  0x22,  0x14,  0x21,  0x10,  0x60,  0x10,  0x00,  0x17,  0xFF, 	/* 32F50 */
+	0x30,  0x00,  0xB1,  0x10,  0x88,  0x10,  0x88,  0x10,  0x88,  0x10,  0x88,  0x7B,  0xFE,  0x10,  0x88,  0x10, 	/* 32F60 */
+	0x88,  0x10,  0x88,  0x1C,  0x88,  0x70,  0x88,  0x17,  0xFF,  0x10,  0x00,  0x10,  0x88,  0x10,  0x84,  0x11, 	/* 32F70 */
+	0x02,  0x32,  0x02,  0xB3,  0x08,  0x88,  0x04,  0x88,  0x04,  0x90,  0x3F,  0xFE,  0x01,  0x40,  0x7F,  0xFF, 	/* 32F80 */
+	0x02,  0x20,  0x04,  0x50,  0x1B,  0x8C,  0x60,  0x83,  0x0F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80, 	/* 32F90 */
+	0x00,  0x80,  0x01,  0x80,  0xB5,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x13,  0xFF,  0x7C,  0x40,  0x10, 	/* 32FA0 */
+	0x40,  0x10,  0x7E,  0x10,  0x84,  0x1D,  0x88,  0x71,  0x08,  0x13,  0x7F,  0x15,  0x08,  0x11,  0x08,  0x11, 	/* 32FB0 */
+	0x08,  0x11,  0x08,  0x31,  0x18,  0xB6,  0x10,  0x92,  0x10,  0x92,  0x13,  0x6C,  0x11,  0x24,  0x7C,  0x92, 	/* 32FC0 */
+	0x10,  0x92,  0x10,  0x20,  0x10,  0x3E,  0x1C,  0x42,  0x70,  0x84,  0x11,  0x44,  0x16,  0x28,  0x10,  0x10, 	/* 32FD0 */
+	0x10,  0x20,  0x10,  0xC0,  0x33,  0x00,  0xB7,  0x10,  0x40,  0x10,  0x44,  0x13,  0xFC,  0x10,  0x48,  0x7C, 	/* 32FE0 */
+	0x50,  0x17,  0xFF,  0x10,  0x20,  0x10,  0x40,  0x1C,  0xFC,  0x71,  0x40,  0x16,  0x40,  0x10,  0x7C,  0x10, 	/* 32FF0 */
+	0x44,  0x10,  0x04,  0x10,  0x04,  0x30,  0x18,  0xBE,  0x10,  0x20,  0x10,  0x20,  0x10,  0x50,  0x10,  0x50, 	/* 33000 */
+	0x7C,  0x88,  0x11,  0x04,  0x12,  0xFA,  0x14,  0x01,  0x1C,  0x00,  0x71,  0xFC,  0x11,  0x04,  0x11,  0x04, 	/* 33010 */
+	0x11,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x30,  0x00,  0xBF,  0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x07, 	/* 33020 */
+	0xF0,  0x18,  0x0C,  0x6F,  0xFB,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x10,  0x0F,  0xE0,  0x00,  0x80,  0x1F, 	/* 33030 */
+	0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x01,  0x80,  0x81,  0x08,  0x20,  0x08,  0x20,  0x09,  0xFE, 	/* 33040 */
+	0x08,  0x20,  0x7E,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x08,  0x04,  0x08,  0x04,  0x0F,  0xFF,  0x78,  0x84, 	/* 33050 */
+	0x08,  0x44,  0x08,  0x44,  0x08,  0x04,  0x08,  0x04,  0x18,  0x0C,  0x82,  0x10,  0x20,  0x10,  0x20,  0x11, 	/* 33060 */
+	0xFC,  0x7C,  0x20,  0x10,  0x20,  0x10,  0x20,  0x13,  0xFE,  0x10,  0x00,  0x1C,  0x20,  0x70,  0x20,  0x11, 	/* 33070 */
+	0xFC,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x17,  0xFF,  0x30,  0x00,  0x87,  0x08,  0x80,  0x08,  0x86, 	/* 33080 */
+	0x08,  0xF8,  0x08,  0x80,  0x7F,  0x81,  0x08,  0x81,  0x08,  0x7F,  0x08,  0x00,  0x0E,  0xFE,  0x78,  0x82, 	/* 33090 */
+	0x08,  0x82,  0x08,  0xFE,  0x08,  0x82,  0x08,  0x82,  0x08,  0xFE,  0x18,  0x00,  0x88,  0x04,  0x00,  0x07, 	/* 330A0 */
+	0x7E,  0x7C,  0x12,  0x07,  0x12,  0x3C,  0x12,  0x05,  0xA2,  0x0E,  0x42,  0x74,  0x8C,  0x00,  0x10,  0x07, 	/* 330B0 */
+	0xE0,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x01,  0x80,  0x89,  0x10,  0x40, 	/* 330C0 */
+	0x10,  0x40,  0x13,  0xFE,  0x12,  0x02,  0x7E,  0x42,  0x10,  0x40,  0x10,  0x40,  0x13,  0xFF,  0x1C,  0x88, 	/* 330D0 */
+	0x70,  0x88,  0x11,  0x10,  0x13,  0xD0,  0x10,  0x20,  0x10,  0x50,  0x11,  0x88,  0x36,  0x04,  0x8C,  0x10, 	/* 330E0 */
+	0x40,  0x10,  0x40,  0x10,  0x7C,  0x10,  0x84,  0x7C,  0x88,  0x11,  0x50,  0x12,  0x20,  0x10,  0x50,  0x19, 	/* 330F0 */
+	0x8C,  0x76,  0x03,  0x11,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x30,  0x00,  0x91, 	/* 33100 */
+	0x10,  0x50,  0x10,  0x50,  0x12,  0x54,  0x11,  0x54,  0x7D,  0x54,  0x11,  0x58,  0x10,  0x50,  0x10,  0x50, 	/* 33110 */
+	0x1C,  0xD8,  0x71,  0x54,  0x16,  0x52,  0x10,  0x50,  0x10,  0x91,  0x10,  0x91,  0x11,  0x0F,  0x32,  0x00, 	/* 33120 */
+	0x99,  0x09,  0x04,  0x04,  0x84,  0x04,  0x88,  0x7F,  0xFF,  0x02,  0x20,  0x04,  0x30,  0x18,  0xCC,  0x6F, 	/* 33130 */
+	0x83,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x01, 	/* 33140 */
+	0x80,  0x9F,  0x10,  0x20,  0x10,  0x20,  0x13,  0xFE,  0x10,  0x20,  0x7E,  0x24,  0x11,  0x24,  0x10,  0xA4, 	/* 33150 */
+	0x10,  0xA8,  0x1F,  0xFF,  0x70,  0x20,  0x10,  0x50,  0x10,  0x50,  0x10,  0x88,  0x11,  0x04,  0x12,  0x02, 	/* 33160 */
+	0x34,  0x01,  0xA7,  0x10,  0x00,  0x17,  0xFE,  0x10,  0x42,  0x10,  0xC6,  0x7C,  0xC6,  0x11,  0x4A,  0x12, 	/* 33170 */
+	0x52,  0x14,  0x62,  0x1C,  0xC6,  0x70,  0xC6,  0x11,  0x4A,  0x12,  0x52,  0x14,  0x62,  0x10,  0x42,  0x10, 	/* 33180 */
+	0x42,  0x30,  0xC6,  0xA8,  0x10,  0x40,  0x10,  0x50,  0x10,  0x48,  0x7C,  0x84,  0x13,  0xFA,  0x10,  0x82, 	/* 33190 */
+	0x10,  0x80,  0x11,  0xFE,  0x15,  0x20,  0x1A,  0x20,  0x73,  0xFF,  0x10,  0x50,  0x10,  0x50,  0x10,  0x88, 	/* 331A0 */
+	0x11,  0x04,  0x36,  0x02,  0xAB,  0x10,  0x20,  0x11,  0x24,  0x11,  0x24,  0x11,  0x24,  0x7D,  0x24,  0x11, 	/* 331B0 */
+	0x2C,  0x11,  0xAA,  0x12,  0x72,  0x12,  0x21,  0x1C,  0x20,  0x71,  0xFC,  0x10,  0x20,  0x10,  0x20,  0x10, 	/* 331C0 */
+	0x20,  0x17,  0xFF,  0x30,  0x00,  0xAF,  0x10,  0x00,  0x13,  0xFF,  0x12,  0x00,  0x12,  0x00,  0x7E,  0xFC, 	/* 331D0 */
+	0x12,  0x00,  0x12,  0x00,  0x13,  0xFF,  0x1E,  0x92,  0x72,  0x92,  0x12,  0x94,  0x12,  0x88,  0x14,  0x88, 	/* 331E0 */
+	0x14,  0xA4,  0x18,  0xC2,  0x33,  0x01,  0xBA,  0x10,  0x02,  0x17,  0xCC,  0x10,  0xB8,  0x10,  0x88,  0x7C, 	/* 331F0 */
+	0x88,  0x11,  0x08,  0x13,  0xFF,  0x10,  0x48,  0x1E,  0x48,  0x71,  0x48,  0x11,  0x88,  0x10,  0x88,  0x11, 	/* 33200 */
+	0xBF,  0x11,  0x40,  0x12,  0x30,  0x34,  0x0F,  0xBD,  0x10,  0x40,  0x10,  0x78,  0x10,  0x88,  0x7D,  0x10, 	/* 33210 */
+	0x12,  0x20,  0x15,  0xFC,  0x11,  0x24,  0x11,  0x24,  0x1D,  0x24,  0x71,  0xFC,  0x10,  0x50,  0x10,  0x50, 	/* 33220 */
+	0x10,  0x90,  0x11,  0x11,  0x12,  0x11,  0x34,  0x0F,  0xBE,  0x10,  0x20,  0x10,  0x20,  0x17,  0xFF,  0x10, 	/* 33230 */
+	0x20,  0x7D,  0x24,  0x11,  0x24,  0x11,  0x24,  0x11,  0xAA,  0x1E,  0x6A,  0x72,  0x31,  0x14,  0x50,  0x10, 	/* 33240 */
+	0x50,  0x10,  0x88,  0x11,  0x04,  0x12,  0x02,  0x34,  0x01,  0xBF,  0x10,  0x04,  0x10,  0x18,  0x11,  0xE0, 	/* 33250 */
+	0x7C,  0x20,  0x17,  0xFF,  0x10,  0x20,  0x11,  0xFC,  0x11,  0x24,  0x1D,  0x24,  0x71,  0xFC,  0x11,  0x24, 	/* 33260 */
+	0x11,  0x24,  0x11,  0xFC,  0x10,  0x20,  0x10,  0x20,  0x30,  0x20,  0x89,  0x10,  0x00,  0x11,  0xFE,  0x11, 	/* 33270 */
+	0x02,  0x11,  0x02,  0x7D,  0x02,  0x11,  0x02,  0x11,  0xFE,  0x10,  0x20,  0x14,  0x20,  0x19,  0x20,  0x71, 	/* 33280 */
+	0x3E,  0x11,  0x20,  0x12,  0xA0,  0x12,  0x60,  0x14,  0x30,  0x38,  0x0F,  0x8C,  0x10,  0x02,  0x17,  0xD2, 	/* 33290 */
+	0x14,  0x52,  0x14,  0x52,  0x7C,  0x52,  0x17,  0xD2,  0x11,  0x12,  0x11,  0x12,  0x11,  0xD2,  0x1D,  0x52, 	/* 332A0 */
+	0x72,  0x52,  0x12,  0x42,  0x12,  0x42,  0x14,  0x42,  0x18,  0x42,  0x31,  0x86,  0x8D,  0x10,  0x00,  0x11, 	/* 332B0 */
+	0xFC,  0x11,  0x04,  0x11,  0xFC,  0x7D,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x10,  0x00,  0x1B,  0xFE,  0x70, 	/* 332C0 */
+	0x20,  0x10,  0x20,  0x17,  0xFF,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x30,  0x20,  0x8F,  0x10,  0x00, 	/* 332D0 */
+	0x11,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x7D,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x1C,  0x20, 	/* 332E0 */
+	0x70,  0x20,  0x13,  0xFE,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x17,  0xFF,  0x30,  0x00,  0x90,  0x10, 	/* 332F0 */
+	0x00,  0x11,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x7D,  0xFC,  0x10,  0x00,  0x11,  0xFC,  0x11,  0x04,  0x1D, 	/* 33300 */
+	0x04,  0x71,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x31,  0x0C,  0x95, 	/* 33310 */
+	0x10,  0x28,  0x10,  0x24,  0x13,  0xFF,  0x10,  0x20,  0x7C,  0x20,  0x11,  0xFE,  0x11,  0x22,  0x11,  0x22, 	/* 33320 */
+	0x1D,  0xFE,  0x71,  0x22,  0x11,  0x22,  0x11,  0xFE,  0x11,  0x22,  0x11,  0x22,  0x11,  0x22,  0x31,  0x26, 	/* 33330 */
+	0x97,  0x10,  0x20,  0x11,  0x20,  0x11,  0x3E,  0x11,  0x20,  0x7D,  0x20,  0x17,  0xFF,  0x10,  0x20,  0x10, 	/* 33340 */
+	0xA8,  0x1C,  0xA4,  0x71,  0x22,  0x12,  0x2A,  0x14,  0x68,  0x10,  0x10,  0x10,  0x20,  0x10,  0xC0,  0x33, 	/* 33350 */
+	0x00,  0x9C,  0x10,  0x20,  0x10,  0x20,  0x11,  0xFC,  0x11,  0x24,  0x7D,  0x24,  0x11,  0xFC,  0x11,  0x24, 	/* 33360 */
+	0x11,  0x24,  0x1D,  0xFC,  0x70,  0x20,  0x13,  0xFC,  0x10,  0x88,  0x10,  0x50,  0x10,  0x20,  0x10,  0xD8, 	/* 33370 */
+	0x37,  0x07,  0xA7,  0x10,  0x20,  0x10,  0x20,  0x13,  0xFE,  0x10,  0x20,  0x7D,  0xFC,  0x10,  0x50,  0x17, 	/* 33380 */
+	0xFF,  0x10,  0x88,  0x1D,  0x24,  0x76,  0x23,  0x11,  0xFC,  0x10,  0x20,  0x13,  0xFE,  0x10,  0x20,  0x10, 	/* 33390 */
+	0x20,  0x30,  0x20,  0xA8,  0x10,  0x20,  0x10,  0x20,  0x10,  0x50,  0x7C,  0x88,  0x11,  0x24,  0x16,  0x23, 	/* 333A0 */
+	0x11,  0xFC,  0x10,  0x20,  0x1C,  0x20,  0x73,  0xFF,  0x10,  0x00,  0x11,  0xFC,  0x11,  0x04,  0x11,  0x04, 	/* 333B0 */
+	0x11,  0xFC,  0x30,  0x00,  0xA9,  0x10,  0x00,  0x13,  0xFF,  0x10,  0x00,  0x11,  0xFE,  0x7D,  0x02,  0x11, 	/* 333C0 */
+	0x02,  0x11,  0xFE,  0x11,  0x10,  0x1D,  0x10,  0x71,  0xFF,  0x11,  0x10,  0x12,  0x28,  0x12,  0x28,  0x14, 	/* 333D0 */
+	0x44,  0x18,  0x82,  0x33,  0x01,  0xAB,  0x10,  0x00,  0x13,  0xDE,  0x12,  0x52,  0x13,  0xDE,  0x7E,  0x52, 	/* 333E0 */
+	0x12,  0x52,  0x13,  0xDE,  0x12,  0x02,  0x1E,  0x02,  0x72,  0x02,  0x12,  0x02,  0x12,  0x02,  0x12,  0x02, 	/* 333F0 */
+	0x12,  0x02,  0x12,  0x02,  0x32,  0x06,  0xAE,  0x10,  0x00,  0x13,  0xFE,  0x12,  0x02,  0x12,  0x02,  0x7F, 	/* 33400 */
+	0xFE,  0x12,  0x20,  0x12,  0x20,  0x13,  0xFF,  0x1E,  0x20,  0x72,  0x20,  0x12,  0xFC,  0x12,  0x84,  0x14, 	/* 33410 */
+	0x84,  0x14,  0x84,  0x18,  0xFC,  0x30,  0x00,  0xB2,  0x11,  0x24,  0x10,  0xA4,  0x10,  0xA8,  0x13,  0xFE, 	/* 33420 */
+	0x7C,  0x20,  0x10,  0x50,  0x13,  0xFF,  0x10,  0x50,  0x1C,  0x88,  0x71,  0xF4,  0x16,  0x13,  0x10,  0x10, 	/* 33430 */
+	0x11,  0xF0,  0x11,  0x04,  0x11,  0x04,  0x30,  0xFC,  0xB6,  0x10,  0x04,  0x10,  0x18,  0x13,  0xE0,  0x10, 	/* 33440 */
+	0x20,  0x7F,  0xFE,  0x11,  0x24,  0x11,  0x24,  0x17,  0xFF,  0x19,  0x24,  0x71,  0x24,  0x11,  0x24,  0x13, 	/* 33450 */
+	0xFE,  0x10,  0x20,  0x10,  0x20,  0x17,  0xFF,  0x30,  0x00,  0xB7,  0x10,  0x20,  0x10,  0x20,  0x13,  0xFF, 	/* 33460 */
+	0x10,  0x20,  0x7D,  0xFC,  0x10,  0x24,  0x13,  0xFF,  0x10,  0x24,  0x1D,  0xFC,  0x70,  0x20,  0x11,  0x20, 	/* 33470 */
+	0x11,  0x3E,  0x11,  0xA0,  0x12,  0x60,  0x14,  0x30,  0x38,  0x0F,  0xBA,  0x10,  0x20,  0x10,  0x20,  0x13, 	/* 33480 */
+	0xFF,  0x10,  0x30,  0x7C,  0x50,  0x10,  0x88,  0x11,  0x04,  0x12,  0xFA,  0x1C,  0x01,  0x70,  0x00,  0x13, 	/* 33490 */
+	0xFE,  0x10,  0xA0,  0x10,  0xA8,  0x11,  0x24,  0x12,  0x22,  0x30,  0x60,  0xBB,  0x10,  0x20,  0x10,  0x20, 	/* 334A0 */
+	0x10,  0x50,  0x7D,  0x8C,  0x16,  0xFB,  0x10,  0x00,  0x11,  0xFC,  0x10,  0x08,  0x1C,  0x10,  0x70,  0x50, 	/* 334B0 */
+	0x12,  0x20,  0x12,  0xA4,  0x12,  0xA2,  0x14,  0x89,  0x18,  0x49,  0x30,  0x38,  0x80,  0x10,  0x48,  0x10, 	/* 334C0 */
+	0x88,  0x13,  0x08,  0x12,  0x1F,  0x7E,  0x11,  0x13,  0xFA,  0x12,  0x5C,  0x12,  0x68,  0x1E,  0x48,  0x72, 	/* 334D0 */
+	0x48,  0x12,  0x54,  0x12,  0x54,  0x12,  0x54,  0x12,  0x62,  0x14,  0x62,  0x30,  0x41,  0x83,  0x10,  0x00, 	/* 334E0 */
+	0x11,  0xF8,  0x10,  0x08,  0x10,  0xF8,  0x7C,  0x08,  0x11,  0xF8,  0x10,  0x00,  0x13,  0xFE,  0x1E,  0x22, 	/* 334F0 */
+	0x73,  0xFC,  0x11,  0x24,  0x11,  0x24,  0x11,  0x24,  0x11,  0x38,  0x11,  0x20,  0x30,  0x20,  0x88,  0x10, 	/* 33500 */
+	0x04,  0x10,  0x18,  0x13,  0xE4,  0x11,  0x24,  0x7C,  0x88,  0x13,  0xFE,  0x12,  0x02,  0x12,  0x02,  0x13, 	/* 33510 */
+	0xF8,  0x1C,  0x88,  0x70,  0x48,  0x10,  0x50,  0x10,  0x20,  0x10,  0x50,  0x11,  0x8C,  0x36,  0x03,  0x89, 	/* 33520 */
+	0x10,  0x20,  0x10,  0x20,  0x10,  0x3E,  0x10,  0x20,  0x7D,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x11,  0xFC, 	/* 33530 */
+	0x1D,  0x04,  0x71,  0x04,  0x11,  0xFC,  0x10,  0x20,  0x17,  0xFF,  0x10,  0x20,  0x10,  0x20,  0x30,  0x20, 	/* 33540 */
+	0x8C,  0x11,  0x10,  0x09,  0x10,  0x09,  0x20,  0x7F,  0xFE,  0x40,  0x02,  0x4F,  0xF2,  0x08,  0x10,  0x0F, 	/* 33550 */
+	0xF0,  0x00,  0x18,  0x0F,  0xE0,  0x00,  0x80,  0x3F,  0xFC,  0x00,  0x80,  0x7F,  0xFE,  0x00,  0x80,  0x01, 	/* 33560 */
+	0x80,  0x8E,  0x10,  0x20,  0x10,  0x20,  0x13,  0xFE,  0x10,  0x30,  0x7C,  0x48,  0x11,  0x84,  0x10,  0x00, 	/* 33570 */
+	0x17,  0xFF,  0x1C,  0x04,  0x71,  0xE4,  0x11,  0x24,  0x11,  0x24,  0x11,  0xE4,  0x10,  0x04,  0x10,  0x04, 	/* 33580 */
+	0x30,  0x0C,  0x8F,  0x11,  0x00,  0x11,  0x00,  0x11,  0xFE,  0x11,  0x02,  0x7E,  0x82,  0x12,  0xFA,  0x15, 	/* 33590 */
+	0x42,  0x12,  0x42,  0x1F,  0xFE,  0x70,  0x42,  0x11,  0x4A,  0x11,  0x4A,  0x11,  0xFA,  0x10,  0x02,  0x10, 	/* 335A0 */
+	0x04,  0x30,  0x18,  0x92,  0x10,  0x48,  0x10,  0x48,  0x10,  0x48,  0x13,  0xCF,  0x7C,  0x48,  0x10,  0x48, 	/* 335B0 */
+	0x10,  0x48,  0x13,  0xCF,  0x1C,  0x48,  0x70,  0x48,  0x11,  0xC8,  0x16,  0x4F,  0x10,  0x88,  0x10,  0x88, 	/* 335C0 */
+	0x11,  0x08,  0x32,  0x08,  0x96,  0x10,  0x20,  0x10,  0x20,  0x17,  0xFF,  0x10,  0x90,  0x7C,  0x90,  0x10, 	/* 335D0 */
+	0x9C,  0x11,  0x24,  0x11,  0x34,  0x1F,  0x2C,  0x73,  0x44,  0x15,  0xA8,  0x11,  0x18,  0x11,  0x18,  0x11, 	/* 335E0 */
+	0x24,  0x11,  0x42,  0x31,  0x81,  0x98,  0x10,  0x00,  0x13,  0xFE,  0x12,  0x02,  0x12,  0x02,  0x7F,  0xFE, 	/* 335F0 */
+	0x12,  0x10,  0x12,  0x92,  0x12,  0x92,  0x1E,  0x92,  0x72,  0xFE,  0x12,  0x10,  0x12,  0x92,  0x14,  0x92, 	/* 33600 */
+	0x14,  0x92,  0x18,  0xFE,  0x30,  0x00,  0x9B,  0x10,  0x84,  0x10,  0x84,  0x13,  0xE4,  0x10,  0x84,  0x7C, 	/* 33610 */
+	0x84,  0x10,  0x84,  0x17,  0xF6,  0x10,  0x85,  0x1C,  0x85,  0x73,  0xE4,  0x10,  0x84,  0x10,  0x84,  0x10, 	/* 33620 */
+	0xB4,  0x11,  0xC4,  0x16,  0x04,  0x30,  0x04,  0x9F,  0x10,  0x20,  0x10,  0x20,  0x13,  0xFE,  0x12,  0x02, 	/* 33630 */
+	0x7E,  0x02,  0x11,  0xFC,  0x10,  0x20,  0x10,  0x20,  0x1D,  0x20,  0x71,  0x3E,  0x11,  0x20,  0x11,  0x20, 	/* 33640 */
+	0x11,  0x20,  0x12,  0xA0,  0x12,  0x60,  0x34,  0x1F,  0xA0,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x17, 	/* 33650 */
+	0xFF,  0x7C,  0x00,  0x11,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x1D,  0xFC,  0x70,  0x20,  0x11,  0x28,  0x11, 	/* 33660 */
+	0x24,  0x11,  0x22,  0x12,  0x22,  0x14,  0x20,  0x30,  0x60,  0xA1,  0x10,  0x06,  0x10,  0x38,  0x13,  0xC2, 	/* 33670 */
+	0x12,  0x42,  0x7D,  0x24,  0x11,  0x24,  0x11,  0x28,  0x10,  0x20,  0x1C,  0x20,  0x73,  0xFF,  0x10,  0x70, 	/* 33680 */
+	0x10,  0xA8,  0x11,  0x24,  0x16,  0x22,  0x10,  0x21,  0x30,  0x20,  0xA2,  0x10,  0x00,  0x13,  0xFE,  0x12, 	/* 33690 */
+	0x52,  0x12,  0x52,  0x7C,  0x90,  0x10,  0x92,  0x11,  0x0E,  0x12,  0x20,  0x10,  0x20,  0x1F,  0xFF,  0x70, 	/* 336A0 */
+	0x68,  0x10,  0xA4,  0x11,  0x22,  0x12,  0x21,  0x10,  0x20,  0x30,  0x20,  0xA3,  0x14,  0x02,  0x1F,  0x12, 	/* 336B0 */
+	0x24,  0x12,  0x7F,  0x92,  0x04,  0x12,  0x3F,  0x92,  0x24,  0x82,  0x25,  0x82,  0x20,  0x16,  0x07,  0xE0, 	/* 336C0 */
+	0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x01,  0x80,  0xA5,  0x10,  0x20,  0x10, 	/* 336D0 */
+	0x20,  0x13,  0xFE,  0x11,  0x08,  0x7C,  0x88,  0x10,  0x90,  0x17,  0xFF,  0x10,  0x40,  0x10,  0x40,  0x1F, 	/* 336E0 */
+	0xFF,  0x70,  0x88,  0x10,  0x88,  0x13,  0xD0,  0x10,  0x30,  0x10,  0xCC,  0x37,  0x02,  0xA7,  0x10,  0x20, 	/* 336F0 */
+	0x10,  0x20,  0x13,  0xFE,  0x12,  0x52,  0x7E,  0x50,  0x10,  0x52,  0x10,  0x8E,  0x11,  0x00,  0x1E,  0x00, 	/* 33700 */
+	0x71,  0xFE,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x13,  0xFF,  0x30,  0x00,  0xA8,  0x08, 	/* 33710 */
+	0x88,  0x08,  0x88,  0x09,  0x10,  0x09,  0xFE,  0x7F,  0x10,  0x09,  0x10,  0x09,  0x10,  0x09,  0xFE,  0x0D, 	/* 33720 */
+	0x10,  0x19,  0x10,  0x69,  0xFE,  0x09,  0x10,  0x09,  0x10,  0x09,  0x10,  0x09,  0xFF,  0x18,  0x00,  0xA9, 	/* 33730 */
+	0x10,  0x20,  0x10,  0x20,  0x17,  0xFF,  0x10,  0x50,  0x7C,  0xA8,  0x11,  0x24,  0x13,  0xFE,  0x15,  0x25, 	/* 33740 */
+	0x11,  0x24,  0x1D,  0xFC,  0x71,  0x24,  0x11,  0x24,  0x11,  0xFC,  0x10,  0x21,  0x10,  0x21,  0x30,  0x1F, 	/* 33750 */
+	0xAA,  0x10,  0x88,  0x10,  0x88,  0x13,  0xFE,  0x10,  0x88,  0x7C,  0x88,  0x10,  0x88,  0x17,  0xFF,  0x10, 	/* 33760 */
+	0x00,  0x1D,  0xFC,  0x71,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x30, 	/* 33770 */
+	0x00,  0xAB,  0x10,  0x00,  0x17,  0xFF,  0x12,  0x40,  0x12,  0x40,  0x7E,  0x7E,  0x13,  0xC2,  0x12,  0x52, 	/* 33780 */
+	0x12,  0x54,  0x1F,  0xD4,  0x72,  0x4C,  0x12,  0x48,  0x12,  0x4C,  0x13,  0xD4,  0x16,  0x54,  0x10,  0x62, 	/* 33790 */
+	0x30,  0x41,  0xAC,  0x11,  0x00,  0x11,  0x00,  0x11,  0x00,  0x11,  0xFE,  0x7E,  0x02,  0x12,  0x4A,  0x15, 	/* 337A0 */
+	0x52,  0x11,  0x42,  0x1B,  0xFE,  0x70,  0x42,  0x10,  0xE2,  0x10,  0xD2,  0x11,  0x4A,  0x12,  0x42,  0x10, 	/* 337B0 */
+	0x44,  0x30,  0x18,  0xB2,  0x10,  0x00,  0x11,  0xF8,  0x11,  0x08,  0x11,  0xF8,  0x7D,  0x08,  0x11,  0x08, 	/* 337C0 */
+	0x11,  0xF8,  0x10,  0x80,  0x1C,  0xFE,  0x71,  0x02,  0x13,  0x32,  0x15,  0xC2,  0x11,  0x02,  0x11,  0x12, 	/* 337D0 */
+	0x10,  0xF2,  0x30,  0x0C,  0xB4,  0x10,  0x00,  0x13,  0xFE,  0x12,  0x02,  0x12,  0x02,  0x7F,  0xFE,  0x12, 	/* 337E0 */
+	0x22,  0x12,  0x22,  0x12,  0xFA,  0x1E,  0x22,  0x72,  0x32,  0x12,  0x2A,  0x12,  0x22,  0x13,  0xFE,  0x12, 	/* 337F0 */
+	0x02,  0x13,  0xFE,  0x30,  0x00,  0xB5,  0x10,  0x20,  0x10,  0x20,  0x10,  0x50,  0x10,  0x88,  0x7D,  0x04, 	/* 33800 */
+	0x12,  0xFA,  0x14,  0x01,  0x10,  0x00,  0x1F,  0xDE,  0x72,  0x52,  0x12,  0x52,  0x12,  0x52,  0x13,  0xD2, 	/* 33810 */
+	0x10,  0x1C,  0x10,  0x10,  0x30,  0x10,  0xBB,  0x10,  0x00,  0x13,  0xFC,  0x10,  0x84,  0x10,  0x48,  0x7C, 	/* 33820 */
+	0x30,  0x10,  0xCC,  0x13,  0x23,  0x10,  0x20,  0x1D,  0xFC,  0x71,  0x24,  0x11,  0x24,  0x11,  0xFC,  0x10, 	/* 33830 */
+	0x20,  0x10,  0x2C,  0x10,  0x7A,  0x37,  0x81,  0xBE,  0x10,  0x40,  0x10,  0x7C,  0x10,  0x88,  0x11,  0xF8, 	/* 33840 */
+	0x7C,  0x10,  0x13,  0xFF,  0x10,  0x40,  0x10,  0xAA,  0x1B,  0x2A,  0x70,  0x5C,  0x10,  0x94,  0x13,  0x34, 	/* 33850 */
+	0x10,  0x52,  0x10,  0x91,  0x13,  0x10,  0x30,  0x60,  0x80,  0x10,  0x20,  0x10,  0x20,  0x17,  0xFF,  0x10, 	/* 33860 */
+	0x20,  0x7D,  0xFC,  0x11,  0x24,  0x11,  0xAC,  0x11,  0x74,  0x1D,  0x24,  0x71,  0xFC,  0x10,  0x70,  0x10, 	/* 33870 */
+	0xA8,  0x11,  0x24,  0x16,  0x23,  0x10,  0x20,  0x30,  0x20,  0x83,  0x11,  0x04,  0x10,  0x84,  0x10,  0x88, 	/* 33880 */
+	0x17,  0xFF,  0x7C,  0x00,  0x13,  0xC2,  0x12,  0x52,  0x12,  0x52,  0x1F,  0xD2,  0x72,  0x52,  0x12,  0x52, 	/* 33890 */
+	0x13,  0xD2,  0x12,  0x42,  0x12,  0x42,  0x12,  0x42,  0x32,  0xC6,  0x84,  0x10,  0x20,  0x10,  0x20,  0x10, 	/* 338A0 */
+	0x50,  0x7C,  0x88,  0x11,  0xF6,  0x12,  0x01,  0x17,  0xD2,  0x12,  0x52,  0x1F,  0x52,  0x72,  0xE4,  0x12, 	/* 338B0 */
+	0x64,  0x13,  0x64,  0x12,  0xD2,  0x12,  0x52,  0x12,  0x52,  0x32,  0xD2,  0x86,  0x10,  0x10,  0x11,  0xD4, 	/* 338C0 */
+	0x10,  0x58,  0x12,  0x4A,  0x7D,  0x8C,  0x10,  0x84,  0x11,  0x02,  0x13,  0xFD,  0x1C,  0x20,  0x70,  0x20, 	/* 338D0 */
+	0x17,  0xFF,  0x10,  0x20,  0x10,  0x30,  0x10,  0x48,  0x11,  0x84,  0x36,  0x03,  0x89,  0x10,  0x00,  0x11, 	/* 338E0 */
+	0xFC,  0x10,  0xC8,  0x10,  0x30,  0x7F,  0xFF,  0x10,  0x32,  0x10,  0x54,  0x11,  0x90,  0x1E,  0x30,  0x70, 	/* 338F0 */
+	0x20,  0x13,  0xFF,  0x10,  0x70,  0x10,  0xA8,  0x11,  0x24,  0x16,  0x23,  0x30,  0x20,  0x8F,  0x10,  0x88, 	/* 33900 */
+	0x10,  0x88,  0x13,  0xFF,  0x10,  0x88,  0x7C,  0x88,  0x10,  0x00,  0x11,  0xFE,  0x11,  0x22,  0x1D,  0x22, 	/* 33910 */
+	0x71,  0x22,  0x11,  0xFE,  0x11,  0x22,  0x11,  0x22,  0x11,  0x22,  0x11,  0xFE,  0x31,  0x02,  0x90,  0x10, 	/* 33920 */
+	0x00,  0x10,  0xFC,  0x10,  0x84,  0x10,  0xFC,  0x7C,  0x84,  0x10,  0x84,  0x10,  0xFC,  0x10,  0x00,  0x13, 	/* 33930 */
+	0xFF,  0x1C,  0x20,  0x71,  0x20,  0x11,  0x3E,  0x11,  0xA0,  0x11,  0x60,  0x12,  0x30,  0x34,  0x0F,  0x92, 	/* 33940 */
+	0x10,  0x04,  0x10,  0x38,  0x11,  0xE0,  0x10,  0x20,  0x7C,  0x20,  0x13,  0xFF,  0x10,  0x20,  0x10,  0xA0, 	/* 33950 */
+	0x1F,  0x2E,  0x72,  0x22,  0x12,  0x22,  0x13,  0xAE,  0x12,  0x22,  0x12,  0x22,  0x13,  0xFE,  0x30,  0x00, 	/* 33960 */
+	0x96,  0x10,  0x00,  0x11,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x7D,  0xFC,  0x10,  0x00,  0x17,  0xFF,  0x11, 	/* 33970 */
+	0x04,  0x1D,  0xFC,  0x71,  0x04,  0x11,  0xFC,  0x11,  0x07,  0x11,  0xFC,  0x17,  0x04,  0x10,  0x04,  0x30, 	/* 33980 */
+	0x04,  0x9A,  0x10,  0x00,  0x11,  0xF8,  0x11,  0x08,  0x11,  0xF8,  0x7D,  0x08,  0x11,  0x08,  0x11,  0xF8, 	/* 33990 */
+	0x10,  0x00,  0x1B,  0xFF,  0x70,  0x40,  0x11,  0xFE,  0x16,  0x52,  0x10,  0x92,  0x13,  0x22,  0x10,  0x44, 	/* 339A0 */
+	0x31,  0x98,  0x9B,  0x10,  0x40,  0x10,  0x7C,  0x10,  0x88,  0x7D,  0x10,  0x13,  0xFE,  0x16,  0x52,  0x12, 	/* 339B0 */
+	0x52,  0x12,  0x52,  0x1E,  0x8E,  0x73,  0x22,  0x12,  0x22,  0x17,  0xFF,  0x10,  0x60,  0x10,  0x90,  0x11, 	/* 339C0 */
+	0x0C,  0x36,  0x03,  0xA1,  0x10,  0x00,  0x13,  0xFE,  0x12,  0x02,  0x12,  0x02,  0x7F,  0xFE,  0x12,  0x00, 	/* 339D0 */
+	0x13,  0xFE,  0x12,  0x28,  0x16,  0x44,  0x1B,  0xFA,  0x72,  0x22,  0x15,  0xFC,  0x14,  0x20,  0x18,  0x20, 	/* 339E0 */
+	0x17,  0xFF,  0x30,  0x00,  0xA3,  0x10,  0x20,  0x11,  0x22,  0x11,  0x22,  0x11,  0x22,  0x7D,  0xFE,  0x10, 	/* 339F0 */
+	0x00,  0x13,  0xFF,  0x10,  0x20,  0x1C,  0x40,  0x73,  0xFE,  0x12,  0x52,  0x12,  0x52,  0x12,  0x52,  0x12, 	/* 33A00 */
+	0x52,  0x12,  0x52,  0x32,  0x06,  0xA9,  0x11,  0x10,  0x11,  0x10,  0x11,  0x12,  0x11,  0xDC,  0x7D,  0x10, 	/* 33A10 */
+	0x11,  0x11,  0x11,  0xCF,  0x17,  0x20,  0x18,  0x40,  0x71,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x11,  0x04, 	/* 33A20 */
+	0x11,  0x04,  0x11,  0xFC,  0x30,  0x00,  0xAE,  0x10,  0x00,  0x13,  0xFE,  0x12,  0x22,  0x12,  0x22,  0x7D, 	/* 33A30 */
+	0xFE,  0x10,  0x20,  0x11,  0xFC,  0x11,  0x24,  0x1D,  0xFC,  0x71,  0x24,  0x11,  0x24,  0x11,  0xFC,  0x10, 	/* 33A40 */
+	0x20,  0x17,  0xFF,  0x10,  0x20,  0x30,  0x20,  0xB4,  0x10,  0x0C,  0x13,  0xF0,  0x11,  0x44,  0x7C,  0xA4, 	/* 33A50 */
+	0x10,  0xA8,  0x13,  0xFE,  0x10,  0x40,  0x13,  0xFF,  0x1C,  0x40,  0x70,  0xFC,  0x11,  0x84,  0x16,  0xC8, 	/* 33A60 */
+	0x10,  0x30,  0x10,  0x50,  0x11,  0x8C,  0x36,  0x03,  0xB6,  0x10,  0x00,  0x17,  0xFE,  0x12,  0x52,  0x12, 	/* 33A70 */
+	0x52,  0x7E,  0x54,  0x13,  0xD8,  0x12,  0x54,  0x12,  0x52,  0x1B,  0xD2,  0x72,  0x51,  0x12,  0x51,  0x12, 	/* 33A80 */
+	0x59,  0x13,  0xD6,  0x16,  0x50,  0x10,  0x50,  0x30,  0x50,  0xBA,  0x10,  0x06,  0x10,  0x18,  0x13,  0xE2, 	/* 33A90 */
+	0x11,  0x22,  0x7C,  0x94,  0x10,  0x94,  0x11,  0xFE,  0x10,  0x20,  0x10,  0x20,  0x1F,  0xFF,  0x70,  0x20, 	/* 33AA0 */
+	0x11,  0x22,  0x11,  0x22,  0x11,  0x22,  0x11,  0xFE,  0x31,  0x02,  0x86,  0x10,  0x88,  0x10,  0x88,  0x13, 	/* 33AB0 */
+	0xFE,  0x10,  0x88,  0x7D,  0xFE,  0x10,  0x88,  0x17,  0xFF,  0x10,  0x20,  0x1D,  0xFC,  0x71,  0x24,  0x11, 	/* 33AC0 */
+	0xFC,  0x11,  0x24,  0x17,  0xFF,  0x11,  0x04,  0x11,  0x04,  0x31,  0x0C,  0x8D,  0x10,  0x00,  0x13,  0xFC, 	/* 33AD0 */
+	0x12,  0x04,  0x12,  0x04,  0x7F,  0xFC,  0x10,  0x00,  0x13,  0xFC,  0x12,  0x04,  0x1F,  0xFC,  0x72,  0x04, 	/* 33AE0 */
+	0x13,  0xFC,  0x12,  0x04,  0x13,  0xFC,  0x10,  0x88,  0x13,  0x04,  0x3C,  0x02,  0x8F,  0x10,  0x24,  0x10, 	/* 33AF0 */
+	0x22,  0x13,  0xFF,  0x10,  0x20,  0x7D,  0xFC,  0x11,  0x24,  0x11,  0xFC,  0x11,  0x24,  0x1D,  0xFC,  0x71, 	/* 33B00 */
+	0x24,  0x11,  0x2C,  0x10,  0x08,  0x17,  0xFF,  0x11,  0x08,  0x10,  0x88,  0x30,  0x18,  0x93,  0x11,  0x04, 	/* 33B10 */
+	0x10,  0x88,  0x13,  0xFE,  0x10,  0x20,  0x7C,  0x20,  0x11,  0xFC,  0x10,  0x20,  0x1F,  0xFF,  0x10,  0x40, 	/* 33B20 */
+	0x70,  0x40,  0x10,  0xFE,  0x11,  0x10,  0x12,  0x10,  0x1C,  0x10,  0x11,  0xFF,  0x30,  0x00,  0x96,  0x10, 	/* 33B30 */
+	0x20,  0x10,  0x7C,  0x10,  0xC4,  0x13,  0x28,  0x7C,  0x90,  0x10,  0x60,  0x11,  0x80,  0x16,  0xFC,  0x19, 	/* 33B40 */
+	0x20,  0x72,  0x20,  0x17,  0xFF,  0x10,  0x20,  0x12,  0x24,  0x12,  0x24,  0x13,  0xFC,  0x30,  0x00,  0x97, 	/* 33B50 */
+	0x10,  0x20,  0x10,  0x40,  0x11,  0xF8,  0x11,  0x08,  0x7D,  0xF8,  0x11,  0x08,  0x11,  0xF8,  0x11,  0x00, 	/* 33B60 */
+	0x1D,  0xFF,  0x71,  0x00,  0x11,  0xFE,  0x10,  0x82,  0x14,  0x92,  0x14,  0x92,  0x17,  0xF2,  0x30,  0x0C, 	/* 33B70 */
+	0x9C,  0x10,  0x20,  0x10,  0x60,  0x11,  0xAE,  0x11,  0x22,  0x7D,  0x22,  0x11,  0xAE,  0x11,  0x22,  0x11, 	/* 33B80 */
+	0x22,  0x1D,  0xFE,  0x70,  0x20,  0x13,  0xFE,  0x10,  0x84,  0x10,  0x48,  0x10,  0x30,  0x10,  0xCC,  0x37, 	/* 33B90 */
+	0x03,  0xA6,  0x10,  0x00,  0x17,  0xDE,  0x10,  0x42,  0x7C,  0x42,  0x13,  0xDE,  0x12,  0x10,  0x12,  0x10, 	/* 33BA0 */
+	0x13,  0xDE,  0x1C,  0xC6,  0x71,  0x4A,  0x12,  0x52,  0x10,  0xC6,  0x11,  0x4A,  0x12,  0x52,  0x10,  0x82, 	/* 33BB0 */
+	0x33,  0x0C,  0xA8,  0x10,  0x00,  0x11,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x7D,  0x04,  0x11,  0xFC,  0x10, 	/* 33BC0 */
+	0x00,  0x13,  0xDE,  0x1C,  0xC6,  0x71,  0x4A,  0x16,  0x72,  0x10,  0xC6,  0x11,  0x4A,  0x16,  0x72,  0x10, 	/* 33BD0 */
+	0x42,  0x30,  0xC6,  0xAC,  0x10,  0x80,  0x11,  0x1C,  0x13,  0xD4,  0x12,  0x55,  0x7B,  0x55,  0x12,  0xE3, 	/* 33BE0 */
+	0x12,  0x40,  0x17,  0xFE,  0x1A,  0x52,  0x73,  0x52,  0x12,  0xCA,  0x12,  0xCC,  0x12,  0x44,  0x14,  0x4C, 	/* 33BF0 */
+	0x14,  0x52,  0x38,  0xE1,  0xAD,  0x10,  0x88,  0x10,  0x88,  0x17,  0xFF,  0x10,  0x88,  0x7C,  0x20,  0x10, 	/* 33C00 */
+	0x20,  0x10,  0x50,  0x10,  0x88,  0x11,  0xFC,  0x1E,  0x03,  0x70,  0x00,  0x11,  0xFC,  0x11,  0x04,  0x11, 	/* 33C10 */
+	0x04,  0x11,  0xFC,  0x30,  0x00,  0xB4,  0x00,  0x80,  0x3F,  0xFE,  0x22,  0x22,  0x2F,  0xFA,  0x02,  0x20, 	/* 33C20 */
+	0x0F,  0xF8,  0x02,  0x20,  0x7F,  0xFF,  0x04,  0x30,  0x1B,  0xCC,  0x60,  0x83,  0x0F,  0xF8,  0x00,  0x80, 	/* 33C30 */
+	0x7F,  0xFF,  0x00,  0x80,  0x01,  0x80,  0xB6,  0x10,  0x20,  0x10,  0x20,  0x10,  0x50,  0x7C,  0x88,  0x11, 	/* 33C40 */
+	0xFC,  0x12,  0x02,  0x15,  0xFD,  0x11,  0x04,  0x1D,  0xFC,  0x71,  0x04,  0x11,  0xFC,  0x11,  0x00,  0x12, 	/* 33C50 */
+	0xFE,  0x12,  0x82,  0x14,  0xFE,  0x30,  0x00,  0xBA,  0x10,  0x88,  0x10,  0x90,  0x11,  0xFE,  0x13,  0x10, 	/* 33C60 */
+	0x7D,  0xFC,  0x11,  0x10,  0x11,  0xFC,  0x11,  0x10,  0x1D,  0xFE,  0x70,  0x00,  0x17,  0xF8,  0x10,  0x48, 	/* 33C70 */
+	0x10,  0x4E,  0x10,  0x82,  0x11,  0x02,  0x36,  0x0C,  0xBE,  0x10,  0x40,  0x10,  0x40,  0x13,  0xFE,  0x12, 	/* 33C80 */
+	0x92,  0x7E,  0x92,  0x10,  0x91,  0x11,  0x0F,  0x12,  0x80,  0x1C,  0xFF,  0x71,  0x20,  0x11,  0x3E,  0x12, 	/* 33C90 */
+	0x20,  0x14,  0x3E,  0x10,  0x20,  0x10,  0x20,  0x30,  0x20,  0x82,  0x10,  0x00,  0x13,  0xFE,  0x10,  0x88, 	/* 33CA0 */
+	0x10,  0xF8,  0x7C,  0x88,  0x10,  0xF8,  0x10,  0x88,  0x10,  0xFE,  0x1F,  0x08,  0x70,  0x04,  0x11,  0x88, 	/* 33CB0 */
+	0x10,  0x50,  0x10,  0x00,  0x10,  0x58,  0x11,  0x84,  0x36,  0x02,  0x8E,  0x10,  0x00,  0x13,  0xDE,  0x11, 	/* 33CC0 */
+	0x4A,  0x12,  0x52,  0x7C,  0xC6,  0x11,  0x4A,  0x16,  0x72,  0x10,  0x56,  0x1C,  0x88,  0x71,  0x24,  0x16, 	/* 33CD0 */
+	0x4B,  0x11,  0x90,  0x10,  0x64,  0x13,  0x88,  0x10,  0x30,  0x33,  0xC0,  0x98,  0x10,  0x20,  0x10,  0x20, 	/* 33CE0 */
+	0x13,  0xFF,  0x10,  0x88,  0x7C,  0x50,  0x13,  0xFE,  0x12,  0x22,  0x12,  0x22,  0x1F,  0xFE,  0x72,  0x22, 	/* 33CF0 */
+	0x12,  0xFA,  0x12,  0x8A,  0x12,  0x8A,  0x12,  0xFA,  0x12,  0x02,  0x32,  0x06,  0xA7,  0x10,  0x20,  0x11, 	/* 33D00 */
+	0x22,  0x11,  0x22,  0x11,  0xFE,  0x7C,  0x88,  0x10,  0x90,  0x11,  0xFE,  0x13,  0x10,  0x1D,  0x10,  0x71, 	/* 33D10 */
+	0xFE,  0x11,  0x10,  0x11,  0xFE,  0x11,  0x10,  0x11,  0x10,  0x11,  0xFF,  0x30,  0x00,  0xA9,  0x00,  0x80, 	/* 33D20 */
+	0x00,  0x80,  0x1F,  0xFE,  0x11,  0x08,  0x1F,  0xFE,  0x13,  0x1C,  0x15,  0xAA,  0x19,  0x49,  0x11,  0x18, 	/* 33D30 */
+	0x13,  0xE0,  0x10,  0x40,  0x17,  0xFE,  0x20,  0x40,  0x3F,  0xFF,  0x40,  0x40,  0x00,  0xC0,  0xAF,  0x04, 	/* 33D40 */
+	0x10,  0x3F,  0x10,  0x04,  0x7C,  0x7F,  0x94,  0x12,  0x54,  0x7F,  0x24,  0x04,  0x55,  0x3F,  0x95,  0x04, 	/* 33D50 */
+	0x33,  0x07,  0xC0,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x01,  0x80,  0xB6, 	/* 33D60 */
+	0x10,  0x28,  0x10,  0x24,  0x13,  0xFF,  0x10,  0x20,  0x7D,  0xFC,  0x11,  0x24,  0x11,  0xFC,  0x11,  0x24, 	/* 33D70 */
+	0x1D,  0xFC,  0x71,  0x24,  0x11,  0x24,  0x10,  0x08,  0x17,  0xFF,  0x11,  0x08,  0x10,  0x88,  0x30,  0x18, 	/* 33D80 */
+	0xB8,  0x10,  0x48,  0x10,  0x48,  0x13,  0xFF,  0x10,  0x48,  0x7C,  0x48,  0x10,  0xFC,  0x10,  0x84,  0x10, 	/* 33D90 */
+	0xFC,  0x10,  0x84,  0x1C,  0xFC,  0x70,  0x20,  0x13,  0xFF,  0x10,  0x20,  0x10,  0x50,  0x10,  0x8C,  0x33, 	/* 33DA0 */
+	0x03,  0xBA,  0x10,  0x00,  0x17,  0xFE,  0x12,  0x52,  0x11,  0x4A,  0x7C,  0xC6,  0x11,  0x4A,  0x16,  0x72, 	/* 33DB0 */
+	0x10,  0xC6,  0x1C,  0x20,  0x71,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x11,  0xFC, 	/* 33DC0 */
+	0x30,  0x00,  0x83,  0x08,  0x3C,  0x7F,  0xA5,  0x29,  0x25,  0x3F,  0x43,  0x29,  0xFC,  0x3F,  0x24,  0x08, 	/* 33DD0 */
+	0x18,  0x7F,  0xA4,  0x08,  0x53,  0x07,  0xE0,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x00, 	/* 33DE0 */
+	0x80,  0x01,  0x80,  0x88,  0x10,  0x88,  0x12,  0xAA,  0x12,  0xAA,  0x14,  0x8C,  0x7D,  0x54,  0x11,  0x22, 	/* 33DF0 */
+	0x12,  0x01,  0x17,  0xFE,  0x1C,  0x02,  0x74,  0x42,  0x13,  0xFC,  0x10,  0x44,  0x10,  0x44,  0x10,  0x84, 	/* 33E00 */
+	0x11,  0x04,  0x36,  0x18,  0x92,  0x12,  0x90,  0x12,  0x90,  0x17,  0xD0,  0x12,  0x9F,  0x7A,  0x94,  0x17, 	/* 33E10 */
+	0xF4,  0x10,  0x24,  0x13,  0xD4,  0x1E,  0x54,  0x73,  0xD4,  0x12,  0x48,  0x13,  0xCC,  0x12,  0x54,  0x12, 	/* 33E20 */
+	0x52,  0x12,  0x62,  0x32,  0xC1,  0x93,  0x10,  0x20,  0x10,  0xF8,  0x10,  0x20,  0x13,  0xFE,  0x7C,  0x00, 	/* 33E30 */
+	0x10,  0x84,  0x13,  0xFF,  0x10,  0x84,  0x1C,  0xE4,  0x73,  0x9F,  0x10,  0x00,  0x13,  0xFF,  0x10,  0x48, 	/* 33E40 */
+	0x10,  0x49,  0x10,  0x89,  0x37,  0x07,  0x95,  0x12,  0x42,  0x12,  0x44,  0x17,  0xF8,  0x12,  0x50,  0x7A, 	/* 33E50 */
+	0x50,  0x13,  0xDF,  0x12,  0x52,  0x12,  0x52,  0x1B,  0xD2,  0x72,  0x52,  0x12,  0x52,  0x17,  0xF2,  0x10, 	/* 33E60 */
+	0x92,  0x12,  0x62,  0x12,  0x42,  0x34,  0x02,  0x9A,  0x11,  0x08,  0x11,  0x0A,  0x11,  0xC9,  0x11,  0x7F, 	/* 33E70 */
+	0x7D,  0x48,  0x12,  0xC8,  0x12,  0x4C,  0x15,  0x94,  0x10,  0x92,  0x19,  0x22,  0x72,  0x41,  0x14,  0x00, 	/* 33E80 */
+	0x11,  0x52,  0x11,  0x52,  0x12,  0x49,  0x34,  0x49,  0x9E,  0x10,  0x20,  0x10,  0x20,  0x13,  0xFE,  0x10, 	/* 33E90 */
+	0x88,  0x7F,  0xFF,  0x10,  0x00,  0x11,  0xFC,  0x11,  0x24,  0x11,  0xFC,  0x1D,  0x24,  0x71,  0xFC,  0x10, 	/* 33EA0 */
+	0x20,  0x11,  0xFC,  0x10,  0x20,  0x17,  0xFF,  0x30,  0x00,  0xA4,  0x11,  0x08,  0x11,  0x08,  0x17,  0xE8, 	/* 33EB0 */
+	0x11,  0x8F,  0x7D,  0x54,  0x12,  0x54,  0x17,  0xA4,  0x10,  0x14,  0x13,  0xD4,  0x1E,  0x54,  0x73,  0xC8, 	/* 33EC0 */
+	0x12,  0x48,  0x13,  0xCC,  0x12,  0x54,  0x12,  0x62,  0x32,  0xC1,  0xA5,  0x10,  0x12,  0x13,  0xD4,  0x10, 	/* 33ED0 */
+	0x59,  0x10,  0x8A,  0x7C,  0x8C,  0x11,  0x04,  0x13,  0xBA,  0x14,  0xA9,  0x10,  0xAA,  0x77,  0xC6,  0x14, 	/* 33EE0 */
+	0x7C,  0x17,  0xA4,  0x10,  0xA8,  0x10,  0x98,  0x10,  0xA4,  0x33,  0x43,  0xA9,  0x10,  0x20,  0x10,  0x20, 	/* 33EF0 */
+	0x13,  0xFF,  0x10,  0x50,  0x7D,  0x4A,  0x10,  0x84,  0x11,  0xFE,  0x13,  0x05,  0x1D,  0xFC,  0x71,  0x04, 	/* 33F00 */
+	0x11,  0xFC,  0x10,  0x28,  0x10,  0xA4,  0x11,  0x22,  0x12,  0x22,  0x30,  0x60,  0xAB,  0x10,  0x80,  0x10, 	/* 33F10 */
+	0x80,  0x11,  0xFF,  0x13,  0x54,  0x7D,  0x54,  0x11,  0x54,  0x13,  0xFF,  0x11,  0x54,  0x11,  0x54,  0x1D, 	/* 33F20 */
+	0x54,  0x73,  0xFF,  0x10,  0x00,  0x11,  0x04,  0x11,  0x92,  0x12,  0x49,  0x34,  0x49,  0xAD,  0x10,  0x0C, 	/* 33F30 */
+	0x11,  0xF0,  0x11,  0x24,  0x7C,  0xA8,  0x17,  0xFF,  0x10,  0x70,  0x10,  0xA8,  0x11,  0x24,  0x1F,  0xFE, 	/* 33F40 */
+	0x71,  0x25,  0x11,  0x24,  0x11,  0xFC,  0x11,  0x24,  0x11,  0x24,  0x11,  0xFC,  0x30,  0x00,  0xAE,  0x10, 	/* 33F50 */
+	0x00,  0x11,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x7D,  0x04,  0x11,  0xFC,  0x10,  0x00,  0x17,  0xFF,  0x1E, 	/* 33F60 */
+	0x40,  0x73,  0xFE,  0x12,  0x52,  0x13,  0xD4,  0x12,  0x6C,  0x13,  0xCA,  0x16,  0x71,  0x30,  0x40,  0xB0, 	/* 33F70 */
+	0x10,  0x00,  0x13,  0xDE,  0x10,  0x42,  0x13,  0xDE,  0x7E,  0x10,  0x12,  0x31,  0x11,  0xEF,  0x10,  0x00, 	/* 33F80 */
+	0x1C,  0x88,  0x73,  0xFE,  0x10,  0x88,  0x10,  0x88,  0x17,  0xFF,  0x10,  0x88,  0x11,  0x04,  0x36,  0x02, 	/* 33F90 */
+	0xB2,  0x10,  0x50,  0x12,  0x52,  0x11,  0x54,  0x10,  0x50,  0x7F,  0xFF,  0x10,  0x88,  0x10,  0x50,  0x13, 	/* 33FA0 */
+	0xFE,  0x1C,  0x20,  0x71,  0xFC,  0x10,  0x20,  0x13,  0xFF,  0x10,  0x50,  0x10,  0x88,  0x13,  0x04,  0x3C, 	/* 33FB0 */
+	0x03,  0xB9,  0x12,  0x44,  0x11,  0x24,  0x11,  0x28,  0x17,  0xFE,  0x7C,  0x02,  0x15,  0xFA,  0x11,  0x08, 	/* 33FC0 */
+	0x11,  0xF8,  0x1D,  0x08,  0x71,  0xF8,  0x11,  0x08,  0x11,  0xF8,  0x10,  0x50,  0x10,  0x91,  0x13,  0x11, 	/* 33FD0 */
+	0x3C,  0x0F,  0xBB,  0x10,  0x10,  0x12,  0x10,  0x11,  0x7C,  0x11,  0x10,  0x7C,  0xFF,  0x12,  0x44,  0x12, 	/* 33FE0 */
+	0x28,  0x10,  0xFF,  0x17,  0x10,  0x19,  0x7E,  0x71,  0x10,  0x11,  0x7E,  0x11,  0x10,  0x12,  0x90,  0x14, 	/* 33FF0 */
+	0x60,  0x38,  0x1F,  0xBC,  0x10,  0x14,  0x10,  0x12,  0x13,  0xFF,  0x12,  0x10,  0x7B,  0xF2,  0x12,  0x0A, 	/* 34000 */
+	0x12,  0xEC,  0x12,  0xAC,  0x1E,  0xF5,  0x72,  0x23,  0x14,  0xD1,  0x11,  0x08,  0x11,  0x4A,  0x12,  0x41, 	/* 34010 */
+	0x14,  0x45,  0x30,  0x3C,  0x81,  0x10,  0x40,  0x10,  0x40,  0x17,  0xFF,  0x11,  0x12,  0x7D,  0x14,  0x11, 	/* 34020 */
+	0x3F,  0x16,  0xE4,  0x12,  0xA4,  0x19,  0x3E,  0x71,  0xA4,  0x12,  0xA4,  0x17,  0xBE,  0x10,  0xA4,  0x11, 	/* 34030 */
+	0x24,  0x11,  0x3F,  0x32,  0x20,  0x82,  0x10,  0x00,  0x11,  0xFE,  0x10,  0x20,  0x13,  0xFF,  0x7E,  0x21, 	/* 34040 */
+	0x13,  0xAD,  0x12,  0x21,  0x11,  0xAC,  0x1C,  0x00,  0x71,  0xFE,  0x11,  0x22,  0x11,  0xFE,  0x11,  0x22, 	/* 34050 */
+	0x11,  0x22,  0x11,  0xFE,  0x30,  0x00,  0x85,  0x10,  0x20,  0x13,  0xFF,  0x10,  0x00,  0x11,  0xFE,  0x7D, 	/* 34060 */
+	0x7A,  0x11,  0x4A,  0x11,  0x7A,  0x11,  0x02,  0x1D,  0xFE,  0x70,  0x84,  0x10,  0xFC,  0x10,  0x84,  0x10, 	/* 34070 */
+	0xFC,  0x10,  0x00,  0x17,  0xFF,  0x30,  0x00,  0x87,  0x10,  0x00,  0x13,  0xFE,  0x12,  0x92,  0x13,  0xFE, 	/* 34080 */
+	0x7C,  0x20,  0x11,  0xFC,  0x10,  0x20,  0x17,  0xFF,  0x1D,  0x08,  0x70,  0x90,  0x13,  0xFE,  0x10,  0x20, 	/* 34090 */
+	0x13,  0xFE,  0x10,  0x20,  0x10,  0x20,  0x30,  0x20,  0x8D,  0x10,  0x00,  0x10,  0xF8,  0x10,  0x88,  0x10, 	/* 340A0 */
+	0x88,  0x7C,  0xF8,  0x13,  0xDE,  0x12,  0x52,  0x12,  0x52,  0x1F,  0xDE,  0x70,  0x20,  0x17,  0xFE,  0x10, 	/* 340B0 */
+	0x70,  0x10,  0xA8,  0x11,  0x24,  0x16,  0x22,  0x30,  0x20,  0x92,  0x10,  0x20,  0x10,  0x20,  0x10,  0x50, 	/* 340C0 */
+	0x7D,  0xAC,  0x17,  0xFF,  0x11,  0x54,  0x11,  0x24,  0x11,  0x54,  0x1D,  0xFC,  0x70,  0x20,  0x13,  0xFE, 	/* 340D0 */
+	0x12,  0x22,  0x12,  0x5A,  0x13,  0xF6,  0x12,  0x02,  0x32,  0x06,  0x94,  0x10,  0x40,  0x10,  0xF8,  0x11, 	/* 340E0 */
+	0x10,  0x13,  0xFF,  0x7E,  0x48,  0x12,  0x47,  0x12,  0xBC,  0x13,  0x00,  0x1F,  0xFF,  0x72,  0x00,  0x12, 	/* 340F0 */
+	0x7C,  0x12,  0x00,  0x14,  0xFE,  0x14,  0x82,  0x18,  0xFE,  0x30,  0x00,  0x98,  0x00,  0x08,  0x1F,  0x7E, 	/* 34100 */
+	0x11,  0x24,  0x1F,  0x28,  0x10,  0xFF,  0x1F,  0x08,  0x29,  0x7E,  0x2F,  0x08,  0x40,  0x28,  0x07,  0xC0, 	/* 34110 */
+	0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x01,  0x80,  0x9A,  0x10,  0x20,  0x10, 	/* 34120 */
+	0x3E,  0x10,  0x20,  0x13,  0xFF,  0x7E,  0x4A,  0x13,  0xF0,  0x12,  0x44,  0x12,  0x3C,  0x1F,  0xFF,  0x72, 	/* 34130 */
+	0x62,  0x13,  0xB4,  0x12,  0x58,  0x15,  0xB4,  0x14,  0x52,  0x1B,  0x91,  0x30,  0x30,  0xA0,  0x10,  0x20, 	/* 34140 */
+	0x10,  0x20,  0x17,  0xFF,  0x10,  0x51,  0x7F,  0xAE,  0x12,  0xAA,  0x12,  0xAA,  0x15,  0xAD,  0x18,  0x00, 	/* 34150 */
+	0x71,  0x04,  0x11,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x11,  0x04,  0x12,  0x04,  0x34,  0x04,  0xA1,  0x10, 	/* 34160 */
+	0x20,  0x17,  0xFF,  0x10,  0x20,  0x13,  0xFE,  0x7D,  0x04,  0x11,  0xFC,  0x10,  0x00,  0x17,  0xFF,  0x14, 	/* 34170 */
+	0x01,  0x1F,  0xFE,  0x70,  0x98,  0x13,  0xF4,  0x10,  0x20,  0x11,  0xFC,  0x10,  0x20,  0x37,  0xFF,  0xA2, 	/* 34180 */
+	0x10,  0x00,  0x13,  0xDE,  0x10,  0x42,  0x13,  0xDE,  0x7C,  0x42,  0x13,  0xDE,  0x10,  0x88,  0x10,  0x90, 	/* 34190 */
+	0x1D,  0xFE,  0x73,  0x20,  0x15,  0xFC,  0x11,  0x20,  0x11,  0xFC,  0x11,  0x20,  0x11,  0xFF,  0x30,  0x00, 	/* 341A0 */
+	0xA3,  0x10,  0x20,  0x13,  0xFE,  0x10,  0x20,  0x11,  0xFC,  0x7C,  0x00,  0x17,  0xFF,  0x10,  0x02,  0x11, 	/* 341B0 */
+	0xFC,  0x18,  0x20,  0x77,  0xFF,  0x10,  0x04,  0x13,  0xFF,  0x12,  0x64,  0x12,  0x54,  0x13,  0xC4,  0x30, 	/* 341C0 */
+	0x0C,  0xA6,  0x10,  0x20,  0x10,  0x20,  0x13,  0xFF,  0x12,  0x81,  0x7E,  0xFF,  0x11,  0x52,  0x16,  0xCC, 	/* 341D0 */
+	0x11,  0x94,  0x1D,  0x22,  0x72,  0xFD,  0x14,  0x00,  0x13,  0xFE,  0x10,  0xA4,  0x11,  0x22,  0x16,  0x21, 	/* 341E0 */
+	0x30,  0x60,  0xA7,  0x02,  0x80,  0x1C,  0xDC,  0x10,  0x84,  0x1C,  0xDC,  0x10,  0x44,  0x1D,  0x5C,  0x11, 	/* 341F0 */
+	0x44,  0x7F,  0xFF,  0x08,  0x28,  0x13,  0xC4,  0x20,  0x82,  0x4F,  0xF9,  0x00,  0x80,  0x3F,  0xFE,  0x00, 	/* 34200 */
+	0x80,  0x01,  0x80,  0xAC,  0x12,  0x00,  0x12,  0x7E,  0x13,  0x82,  0x12,  0x14,  0x7A,  0x48,  0x11,  0xFF, 	/* 34210 */
+	0x12,  0x09,  0x13,  0xCA,  0x15,  0x28,  0x79,  0x2E,  0x17,  0xE8,  0x11,  0x28,  0x11,  0xB8,  0x12,  0x68, 	/* 34220 */
+	0x14,  0x44,  0x38,  0x83,  0xAF,  0x10,  0x20,  0x13,  0xFF,  0x12,  0x01,  0x11,  0xFE,  0x7C,  0xA4,  0x11, 	/* 34230 */
+	0x28,  0x16,  0x70,  0x10,  0xFC,  0x19,  0x84,  0x76,  0xFC,  0x10,  0x84,  0x10,  0xFC,  0x10,  0x84,  0x10, 	/* 34240 */
+	0xFC,  0x10,  0xC4,  0x33,  0x02,  0xB1,  0x10,  0x00,  0x13,  0xDE,  0x12,  0x52,  0x13,  0xDE,  0x7E,  0x52, 	/* 34250 */
+	0x13,  0xDE,  0x12,  0x22,  0x12,  0x3A,  0x1E,  0x4A,  0x72,  0xB2,  0x12,  0x4A,  0x12,  0xFE,  0x13,  0x4A, 	/* 34260 */
+	0x12,  0x4A,  0x12,  0x7A,  0x32,  0x06,  0xB2,  0x11,  0x60,  0x11,  0x2E,  0x13,  0xEA,  0x14,  0x9A,  0x7B, 	/* 34270 */
+	0xEA,  0x12,  0xAC,  0x13,  0x6C,  0x12,  0x2A,  0x1B,  0xE9,  0x72,  0x29,  0x13,  0xE9,  0x10,  0x89,  0x17, 	/* 34280 */
+	0xFE,  0x11,  0x48,  0x12,  0x28,  0x34,  0x08,  0xB4,  0x10,  0x10,  0x10,  0x10,  0x13,  0xFF,  0x12,  0x48, 	/* 34290 */
+	0x7F,  0xFE,  0x12,  0x48,  0x12,  0x78,  0x13,  0xFF,  0x1E,  0x10,  0x72,  0xFE,  0x12,  0x92,  0x12,  0xFE, 	/* 342A0 */
+	0x12,  0x92,  0x12,  0xFE,  0x14,  0x66,  0x31,  0x81,  0xB6,  0x11,  0x08,  0x11,  0x08,  0x11,  0xEF,  0x12, 	/* 342B0 */
+	0x94,  0x7C,  0x22,  0x10,  0x88,  0x17,  0xFF,  0x10,  0x00,  0x13,  0xD2,  0x1E,  0x52,  0x73,  0xD2,  0x12, 	/* 342C0 */
+	0x52,  0x13,  0xD2,  0x12,  0x52,  0x12,  0x42,  0x32,  0xC6,  0xBA,  0x10,  0x00,  0x13,  0xFE,  0x12,  0x52, 	/* 342D0 */
+	0x13,  0xFE,  0x7C,  0x90,  0x11,  0x52,  0x17,  0xBC,  0x10,  0x10,  0x1F,  0xD1,  0x72,  0x4F,  0x13,  0xD0, 	/* 342E0 */
+	0x12,  0x52,  0x13,  0xDC,  0x12,  0x50,  0x12,  0x51,  0x32,  0xCF,  0xBD,  0x11,  0x22,  0x11,  0x42,  0x12, 	/* 342F0 */
+	0xFD,  0x12,  0xCD,  0x7D,  0x7A,  0x11,  0x4A,  0x13,  0x4E,  0x12,  0xFD,  0x1B,  0xAF,  0x70,  0x20,  0x13, 	/* 34300 */
+	0xFF,  0x10,  0x68,  0x10,  0xA4,  0x11,  0x22,  0x16,  0x21,  0x30,  0x20,  0xBE,  0x10,  0x00,  0x13,  0xFF, 	/* 34310 */
+	0x10,  0x20,  0x10,  0xFC,  0x7C,  0x84,  0x10,  0xFC,  0x10,  0x84,  0x13,  0xFF,  0x1E,  0x55,  0x71,  0x4A, 	/* 34320 */
+	0x12,  0x7D,  0x14,  0x89,  0x13,  0x50,  0x10,  0x30,  0x10,  0xCC,  0x37,  0x03,  0x80,  0x08,  0x48,  0x3F, 	/* 34330 */
+	0x7F,  0x08,  0x8C,  0x1D,  0x5A,  0x2B,  0x69,  0x48,  0x88,  0x0B,  0x48,  0x7F,  0xFF,  0x02,  0x30,  0x0F, 	/* 34340 */
+	0xCC,  0x70,  0x83,  0x0F,  0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x01,  0x80,  0x85,  0x10,  0x84, 	/* 34350 */
+	0x13,  0xFF,  0x10,  0x84,  0x13,  0xFF,  0x7C,  0x84,  0x11,  0x4A,  0x12,  0x31,  0x11,  0xFC,  0x1D,  0x04, 	/* 34360 */
+	0x71,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x10,  0xCC,  0x37,  0x03,  0x98,  0x10, 	/* 34370 */
+	0x20,  0x13,  0xFF,  0x10,  0x00,  0x11,  0xCE,  0x7D,  0x4A,  0x11,  0xCE,  0x10,  0x48,  0x11,  0xFE,  0x1C, 	/* 34380 */
+	0x48,  0x71,  0xFE,  0x10,  0x48,  0x13,  0xFF,  0x10,  0xD2,  0x17,  0x8C,  0x10,  0xE4,  0x33,  0x83,  0x9C, 	/* 34390 */
+	0x11,  0x12,  0x11,  0x12,  0x11,  0xFE,  0x10,  0x88,  0x7D,  0xFE,  0x13,  0x10,  0x11,  0xFE,  0x11,  0x10, 	/* 343A0 */
+	0x1D,  0xFE,  0x71,  0x10,  0x13,  0xFF,  0x12,  0x52,  0x12,  0xFE,  0x13,  0x52,  0x12,  0x72,  0x32,  0x06, 	/* 343B0 */
+	0x9D,  0x10,  0x00,  0x13,  0xFE,  0x10,  0x88,  0x7C,  0xF8,  0x10,  0x88,  0x10,  0xFE,  0x13,  0x88,  0x10, 	/* 343C0 */
+	0x08,  0x1F,  0xFF,  0x72,  0x52,  0x13,  0xDE,  0x12,  0x52,  0x13,  0xDE,  0x12,  0x53,  0x17,  0xFE,  0x30, 	/* 343D0 */
+	0x42,  0xA3,  0x08,  0x84,  0x0B,  0xF4,  0x74,  0x1A,  0x15,  0xEA,  0x0A,  0x05,  0x7F,  0xFF,  0x09,  0x24, 	/* 343E0 */
+	0x2D,  0xF6,  0x2A,  0x15,  0x49,  0xE4,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80, 	/* 343F0 */
+	0x01,  0x80,  0xA4,  0x12,  0x88,  0x1F,  0xEA,  0x12,  0x92,  0x13,  0x9F,  0x79,  0x34,  0x17,  0xD4,  0x15, 	/* 34400 */
+	0x54,  0x17,  0xDF,  0x19,  0x14,  0x77,  0xF4,  0x11,  0x1F,  0x1F,  0xF4,  0x12,  0x94,  0x12,  0x54,  0x14, 	/* 34410 */
+	0x5F,  0x38,  0x00,  0xAA,  0x10,  0x40,  0x11,  0xDC,  0x11,  0x24,  0x11,  0xDC,  0x7D,  0x24,  0x11,  0xDC, 	/* 34420 */
+	0x17,  0xFF,  0x14,  0x01,  0x1D,  0xFD,  0x71,  0x04,  0x11,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x10,  0x50, 	/* 34430 */
+	0x11,  0x91,  0x36,  0x0F,  0xAB,  0x13,  0xDE,  0x12,  0x52,  0x13,  0xDE,  0x12,  0x52,  0x7F,  0xDE,  0x12, 	/* 34440 */
+	0x52,  0x13,  0xFE,  0x13,  0x10,  0x1D,  0xFC,  0x71,  0x10,  0x11,  0xFC,  0x11,  0x10,  0x13,  0xFE,  0x10, 	/* 34450 */
+	0xC8,  0x10,  0x30,  0x37,  0xCF,  0xAC,  0x10,  0x08,  0x13,  0xEF,  0x12,  0x90,  0x13,  0xEF,  0x7E,  0x40, 	/* 34460 */
+	0x13,  0xDF,  0x12,  0x95,  0x13,  0xFF,  0x1D,  0x04,  0x71,  0xF4,  0x11,  0x7C,  0x11,  0x04,  0x11,  0xFC, 	/* 34470 */
+	0x10,  0x51,  0x11,  0x91,  0x36,  0x0F,  0xAF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00, 	/* 34480 */
+	0x80,  0x00,  0x80,  0x1F,  0xF0,  0x04,  0x10,  0x04,  0x10,  0x02,  0x20,  0x01,  0x40,  0x00,  0x80,  0x01, 	/* 34490 */
+	0x40,  0x02,  0x20,  0x0C,  0x18,  0x70,  0x07,  0xB4,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0xFF, 	/* 344A0 */
+	0x00,  0x80,  0x00,  0x80,  0x3F,  0xF8,  0x04,  0x08,  0x02,  0x10,  0x02,  0x10,  0x01,  0x20,  0x00,  0xC0, 	/* 344B0 */
+	0x00,  0xC0,  0x03,  0x20,  0x0C,  0x18,  0x70,  0x07,  0xB5,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x07, 	/* 344C0 */
+	0xFF,  0x08,  0x10,  0x08,  0x10,  0x12,  0x10,  0x22,  0x10,  0x41,  0x20,  0x01,  0x20,  0x00,  0xC0,  0x00, 	/* 344D0 */
+	0xC0,  0x01,  0x20,  0x02,  0x10,  0x0C,  0x0C,  0x70,  0x03,  0xB6,  0x02,  0x40,  0x02,  0x40,  0x12,  0x40, 	/* 344E0 */
+	0x12,  0x7F,  0x12,  0x44,  0x12,  0x84,  0x12,  0xC4,  0x13,  0x44,  0x12,  0x48,  0x12,  0x28,  0x1E,  0x10, 	/* 344F0 */
+	0x62,  0x18,  0x02,  0x28,  0x02,  0x44,  0x03,  0x82,  0x02,  0x01,  0xB7,  0x00,  0x40,  0x7F,  0x40,  0x08, 	/* 34500 */
+	0x40,  0x08,  0x7F,  0x10,  0x44,  0x10,  0x84,  0x3E,  0xC4,  0x23,  0x44,  0x02,  0x28,  0x02,  0x28,  0x02, 	/* 34510 */
+	0x10,  0x02,  0x18,  0x04,  0x28,  0x04,  0x44,  0x04,  0x82,  0x1B,  0x01,  0xB8,  0x04,  0x40,  0x04,  0x40, 	/* 34520 */
+	0x04,  0x40,  0x0A,  0x7F,  0x0A,  0x44,  0x12,  0x84,  0x12,  0x84,  0x33,  0x24,  0x52,  0x28,  0x12,  0x38, 	/* 34530 */
+	0x12,  0x10,  0x12,  0x18,  0x12,  0x28,  0x10,  0x44,  0x11,  0x82,  0x16,  0x01,  0xB9,  0x00,  0x40,  0x00, 	/* 34540 */
+	0x40,  0x7E,  0x40,  0x02,  0x7F,  0x02,  0x44,  0x02,  0x44,  0x7E,  0xA4,  0x42,  0xA4,  0x41,  0x28,  0x40, 	/* 34550 */
+	0x28,  0x40,  0x10,  0x42,  0x18,  0x42,  0x28,  0x3E,  0x44,  0x00,  0x82,  0x03,  0x01,  0xBB,  0x00,  0x40, 	/* 34560 */
+	0x00,  0x40,  0x00,  0x40,  0x7E,  0x7F,  0x08,  0x84,  0x08,  0x84,  0x09,  0x44,  0x0A,  0x44,  0x08,  0x28, 	/* 34570 */
+	0x08,  0x28,  0x0E,  0x10,  0x18,  0x30,  0x60,  0x48,  0x00,  0x84,  0x01,  0x02,  0x06,  0x01,  0xBE,  0x08, 	/* 34580 */
+	0x20,  0x08,  0x20,  0x08,  0x20,  0x7F,  0xA0,  0x08,  0x7F,  0x08,  0x44,  0x0F,  0x44,  0x09,  0xA4,  0x09, 	/* 34590 */
+	0x24,  0x09,  0x14,  0x09,  0x18,  0x11,  0x08,  0x11,  0x14,  0x21,  0x24,  0x41,  0xC2,  0x06,  0x01,  0xBF, 	/* 345A0 */
+	0x00,  0x20,  0x00,  0x20,  0x7F,  0xA0,  0x04,  0x3F,  0x04,  0x44,  0x04,  0x44,  0x14,  0xC4,  0x17,  0x44, 	/* 345B0 */
+	0x14,  0x28,  0x14,  0x28,  0x14,  0x10,  0x15,  0x90,  0x16,  0x28,  0x18,  0x44,  0x61,  0x82,  0x06,  0x01, 	/* 345C0 */
+	0x85,  0x08,  0x40,  0x08,  0x40,  0x08,  0x40,  0x7F,  0x7F,  0x08,  0x44,  0x08,  0x84,  0x08,  0xC4,  0x09, 	/* 345D0 */
+	0x44,  0x3E,  0x28,  0x22,  0x28,  0x22,  0x10,  0x22,  0x18,  0x22,  0x28,  0x3E,  0xC4,  0x03,  0x02,  0x00, 	/* 345E0 */
+	0x01,  0x88,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x7F,  0xBF,  0x12,  0x44,  0x11,  0x44,  0x23,  0x44, 	/* 345F0 */
+	0x2A,  0xA4,  0x4A,  0xA8,  0x04,  0x38,  0x06,  0x10,  0x09,  0x18,  0x11,  0x28,  0x20,  0x44,  0x41,  0x82, 	/* 34600 */
+	0x06,  0x01,  0x8D,  0x04,  0x10,  0x04,  0x10,  0x0A,  0x1F,  0x0A,  0x10,  0x11,  0x10,  0x3F,  0xFC,  0x44, 	/* 34610 */
+	0x04,  0x04,  0x24,  0x7F,  0xA4,  0x04,  0x24,  0x15,  0x18,  0x14,  0x88,  0x24,  0x98,  0x44,  0x24,  0x04, 	/* 34620 */
+	0x42,  0x0D,  0x81,  0x8F,  0x10,  0x20,  0x10,  0x20,  0x1F,  0xA0,  0x20,  0x3F,  0x3F,  0x24,  0x55,  0x44, 	/* 34630 */
+	0x15,  0x44,  0x15,  0xA4,  0x7F,  0xA4,  0x25,  0x18,  0x25,  0x18,  0x25,  0x08,  0x3F,  0x94,  0x01,  0x24, 	/* 34640 */
+	0x02,  0x42,  0x0C,  0x81,  0x91,  0x05,  0x20,  0x04,  0xA0,  0x04,  0x20,  0x7F,  0xBF,  0x04,  0x24,  0x44, 	/* 34650 */
+	0xA4,  0x25,  0x44,  0x25,  0x44,  0x0E,  0xA4,  0x0E,  0x28,  0x15,  0x18,  0x15,  0x10,  0x24,  0xA8,  0x44, 	/* 34660 */
+	0x44,  0x04,  0x82,  0x0D,  0x01,  0x95,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xA0,  0x04,  0x3F,  0x04,  0x44, 	/* 34670 */
+	0x3F,  0x44,  0x25,  0x44,  0x25,  0xA4,  0x3F,  0x28,  0x04,  0x38,  0x0E,  0x10,  0x15,  0x18,  0x24,  0x28, 	/* 34680 */
+	0x44,  0x44,  0x05,  0x82,  0x06,  0x01,  0x96,  0x04,  0x20,  0x04,  0x20,  0x3F,  0x20,  0x04,  0x3F,  0x7F, 	/* 34690 */
+	0xC4,  0x04,  0x44,  0x04,  0x44,  0x7F,  0xA4,  0x08,  0x28,  0x0F,  0x38,  0x09,  0x10,  0x09,  0x18,  0x11, 	/* 346A0 */
+	0x28,  0x11,  0x44,  0x21,  0x82,  0x46,  0x01,  0x97,  0x00,  0x40,  0x3E,  0x40,  0x22,  0x40,  0x22,  0x7F, 	/* 346B0 */
+	0x3E,  0x44,  0x22,  0x44,  0x22,  0xC4,  0x3E,  0xA4,  0x23,  0x28,  0x22,  0x28,  0x22,  0x10,  0x3E,  0x18, 	/* 346C0 */
+	0x14,  0x28,  0x12,  0x44,  0x22,  0x82,  0x41,  0x01,  0x98,  0x04,  0x20,  0x04,  0x20,  0x0A,  0x20,  0x0A, 	/* 346D0 */
+	0x3F,  0x11,  0x44,  0x3F,  0xC4,  0x44,  0x44,  0x04,  0xA4,  0x7F,  0xA4,  0x04,  0x14,  0x15,  0x18,  0x14, 	/* 346E0 */
+	0x88,  0x24,  0x98,  0x44,  0x24,  0x04,  0x42,  0x0D,  0x81,  0x99,  0x04,  0x20,  0x04,  0xA0,  0x3F,  0xA0, 	/* 346F0 */
+	0x04,  0xA0,  0x05,  0x3F,  0x7F,  0xE2,  0x02,  0x22,  0x3F,  0x62,  0x09,  0x54,  0x12,  0x94,  0x64,  0x08, 	/* 34700 */
+	0x07,  0x88,  0x7C,  0x14,  0x04,  0x24,  0x04,  0xC2,  0x0F,  0x01,  0x9D,  0x08,  0x10,  0x08,  0x10,  0x2A, 	/* 34710 */
+	0x10,  0x29,  0x1F,  0x49,  0x14,  0x08,  0x24,  0x7F,  0xA4,  0x48,  0xD4,  0x6A,  0x94,  0x6A,  0x94,  0x6A, 	/* 34720 */
+	0x88,  0x6A,  0x88,  0x48,  0x94,  0x48,  0xA2,  0x48,  0xC2,  0x41,  0x81,  0x9E,  0x08,  0x20,  0x08,  0x20, 	/* 34730 */
+	0x2A,  0x20,  0x29,  0x3F,  0x49,  0x24,  0x08,  0x44,  0x7F,  0x44,  0x41,  0xA4,  0x5D,  0x24,  0x55,  0x28, 	/* 34740 */
+	0x55,  0x18,  0x55,  0x10,  0x5D,  0x28,  0x41,  0x44,  0x41,  0x82,  0x43,  0x01,  0xA2,  0x00,  0x20,  0x3F, 	/* 34750 */
+	0xA0,  0x04,  0x20,  0x04,  0x3F,  0x7F,  0xA4,  0x11,  0x44,  0x11,  0x64,  0x1F,  0xA4,  0x11,  0x14,  0x1F, 	/* 34760 */
+	0x14,  0x11,  0x18,  0x11,  0x88,  0x1F,  0x14,  0x71,  0x24,  0x01,  0x42,  0x01,  0x81,  0xA3,  0x12,  0x20, 	/* 34770 */
+	0x12,  0x20,  0x7F,  0x20,  0x12,  0x3F,  0x12,  0x24,  0x7F,  0xC4,  0x00,  0x44,  0x3E,  0xA4,  0x22,  0x24, 	/* 34780 */
+	0x3E,  0x28,  0x22,  0x18,  0x3E,  0x10,  0x22,  0x28,  0x22,  0x44,  0x22,  0x82,  0x27,  0x01,  0xA6,  0x04, 	/* 34790 */
+	0x20,  0x04,  0x20,  0x7F,  0xA0,  0x00,  0x3F,  0x1F,  0x24,  0x11,  0x44,  0x1F,  0x44,  0x00,  0xA4,  0x3F, 	/* 347A0 */
+	0x24,  0x02,  0x14,  0x04,  0x18,  0x07,  0x88,  0x7C,  0x14,  0x04,  0x24,  0x04,  0x42,  0x0D,  0x81,  0xAC, 	/* 347B0 */
+	0x12,  0x20,  0x12,  0x20,  0x7F,  0xA0,  0x12,  0x3F,  0x12,  0x24,  0x10,  0x44,  0x1F,  0xC4,  0x21,  0x24, 	/* 347C0 */
+	0x3D,  0x28,  0x65,  0x18,  0x25,  0x10,  0x25,  0x28,  0x3D,  0x28,  0x01,  0x44,  0x02,  0x82,  0x0D,  0x01, 	/* 347D0 */
+	0xB0,  0x04,  0xA0,  0x24,  0xA0,  0x15,  0x20,  0x15,  0x3F,  0x7F,  0xA4,  0x0E,  0x44,  0x15,  0xA4,  0x24, 	/* 347E0 */
+	0xA4,  0x44,  0x14,  0x7F,  0x98,  0x09,  0x08,  0x11,  0x18,  0x3E,  0x14,  0x06,  0x24,  0x19,  0x42,  0x60, 	/* 347F0 */
+	0x81,  0xB2,  0x08,  0x10,  0x08,  0x10,  0x7F,  0x9F,  0x00,  0x10,  0x3E,  0x10,  0x22,  0xFC,  0x3E,  0x44, 	/* 34800 */
+	0x00,  0x44,  0x7F,  0x44,  0x41,  0x28,  0x5D,  0x28,  0x55,  0x10,  0x55,  0x18,  0x5D,  0x24,  0x41,  0x42, 	/* 34810 */
+	0x43,  0x81,  0xB4,  0x04,  0x20,  0x7F,  0xA0,  0x04,  0x3F,  0x3F,  0x64,  0x25,  0x54,  0x3F,  0x94,  0x0E, 	/* 34820 */
+	0x08,  0x15,  0x34,  0x64,  0xC2,  0x04,  0x01,  0x1F,  0xFC,  0x00,  0x80,  0x08,  0xF8,  0x08,  0x80,  0x7F, 	/* 34830 */
+	0xFF,  0x00,  0x00,  0xB5,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xD0,  0x11,  0x1F,  0x0A,  0x24,  0x3F,  0xA4, 	/* 34840 */
+	0x24,  0xD4,  0x24,  0x94,  0x3F,  0x94,  0x24,  0x88,  0x2E,  0x88,  0x2A,  0x94,  0x2A,  0x94,  0x2E,  0xA2, 	/* 34850 */
+	0x20,  0xC2,  0x21,  0x81,  0xB7,  0x0A,  0x20,  0x09,  0x20,  0x7F,  0xA0,  0x08,  0x3F,  0x3F,  0x44,  0x29, 	/* 34860 */
+	0x44,  0x3F,  0xA4,  0x29,  0x24,  0x3F,  0x24,  0x08,  0x18,  0x7F,  0x88,  0x08,  0x18,  0x0E,  0x14,  0x12, 	/* 34870 */
+	0x24,  0x22,  0x42,  0x4D,  0x81,  0xB8,  0x04,  0x10,  0x1F,  0x90,  0x14,  0x90,  0x7F,  0xDF,  0x14,  0xA4, 	/* 34880 */
+	0x1F,  0xA4,  0x04,  0x24,  0x1F,  0xD4,  0x14,  0x94,  0x1F,  0x98,  0x04,  0x08,  0x7F,  0xC8,  0x09,  0x14, 	/* 34890 */
+	0x1E,  0x24,  0x05,  0x42,  0x38,  0x81,  0x82,  0x04,  0x10,  0x04,  0x10,  0x0A,  0x10,  0x11,  0x1F,  0x20, 	/* 348A0 */
+	0xA4,  0x5F,  0x24,  0x00,  0x24,  0x3B,  0xD4,  0x2A,  0x94,  0x2A,  0x98,  0x3B,  0x88,  0x11,  0x08,  0x19, 	/* 348B0 */
+	0x94,  0x15,  0x64,  0x22,  0x42,  0x44,  0x81,  0x83,  0x08,  0x20,  0x2A,  0x20,  0x49,  0x3F,  0x3F,  0x44, 	/* 348C0 */
+	0x29,  0xA8,  0x2D,  0x10,  0x3B,  0x2C,  0x29,  0xC3,  0x2B,  0x00,  0x7F,  0xFF,  0x04,  0x40,  0x0F,  0x4C, 	/* 348D0 */
+	0x71,  0x70,  0x0A,  0x42,  0x0C,  0x42,  0x70,  0x3E,  0x87,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F, 	/* 348E0 */
+	0xFF,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x02,  0x20,  0x02,  0x20,  0x01,  0x40,  0x00,  0x80,  0x00, 	/* 348F0 */
+	0x80,  0x01,  0x40,  0x02,  0x20,  0x0C,  0x18,  0x70,  0x07,  0x88,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF, 	/* 34900 */
+	0x02,  0x10,  0x01,  0x20,  0x00,  0xC0,  0x03,  0x60,  0x0C,  0x18,  0x70,  0x07,  0x0F,  0xF0,  0x00,  0x60, 	/* 34910 */
+	0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x01,  0x80,  0x89,  0x00,  0x80,  0x00,  0x80,  0x7F, 	/* 34920 */
+	0xFF,  0x02,  0x10,  0x01,  0x20,  0x00,  0xC0,  0x03,  0x30,  0x0C,  0x0C,  0x77,  0xFB,  0x04,  0x08,  0x04, 	/* 34930 */
+	0x08,  0x07,  0xF8,  0x04,  0x08,  0x08,  0x08,  0x08,  0x08,  0x10,  0x08,  0x8C,  0x08,  0x08,  0x08,  0xEC, 	/* 34940 */
+	0x08,  0x0A,  0x7F,  0x0A,  0x05,  0xFF,  0x24,  0x28,  0x14,  0x28,  0x14,  0xA8,  0x08,  0xB8,  0x0C,  0xA4, 	/* 34950 */
+	0x14,  0xA4,  0x12,  0xA4,  0x12,  0xAD,  0x20,  0xB3,  0x41,  0xC3,  0x00,  0x01,  0x8E,  0x00,  0x80,  0x00, 	/* 34960 */
+	0x80,  0x7F,  0xFF,  0x04,  0x10,  0x02,  0x20,  0x01,  0xC0,  0x03,  0x60,  0x0C,  0x18,  0x7B,  0xEF,  0x08, 	/* 34970 */
+	0x08,  0x0F,  0xF8,  0x08,  0x88,  0x0A,  0xC8,  0x12,  0xA8,  0x14,  0xA8,  0x21,  0x88,  0x90,  0x02,  0x20, 	/* 34980 */
+	0x02,  0x20,  0x7E,  0x3F,  0x02,  0x20,  0x3E,  0x3E,  0x02,  0x20,  0x7C,  0x3F,  0x04,  0xA0,  0x08,  0x80, 	/* 34990 */
+	0x7F,  0xFF,  0x02,  0x20,  0x02,  0x20,  0x01,  0x40,  0x01,  0xC0,  0x06,  0x30,  0x38,  0x0E,  0x91,  0x01, 	/* 349A0 */
+	0x00,  0x7D,  0x3F,  0x11,  0x08,  0x17,  0xE8,  0x10,  0x48,  0x12,  0x48,  0x7D,  0x48,  0x11,  0x7E,  0x11, 	/* 349B0 */
+	0x88,  0x10,  0x88,  0x10,  0x88,  0x15,  0x48,  0x1A,  0x48,  0x64,  0x08,  0x08,  0x7F,  0x00,  0x00,  0x97, 	/* 349C0 */
+	0x00,  0x10,  0x00,  0x10,  0x0C,  0x10,  0x03,  0x10,  0x00,  0x10,  0x00,  0x10,  0x18,  0x10,  0x06,  0x10, 	/* 349D0 */
+	0x00,  0x10,  0x00,  0x10,  0x00,  0x1F,  0x03,  0xF0,  0x7C,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10, 	/* 349E0 */
+	0x99,  0x08,  0x04,  0x49,  0x44,  0x29,  0x24,  0x2A,  0x14,  0x0C,  0x14,  0x7F,  0x84,  0x08,  0x44,  0x0C, 	/* 349F0 */
+	0x24,  0x1A,  0x24,  0x19,  0x07,  0x29,  0x3C,  0x28,  0xC4,  0x48,  0x04,  0x08,  0x04,  0x08,  0x04,  0x08, 	/* 34A00 */
+	0x04,  0x9B,  0x08,  0x04,  0x0E,  0x44,  0x12,  0x24,  0x24,  0x24,  0x7F,  0x04,  0x25,  0x84,  0x25,  0x44, 	/* 34A10 */
+	0x3F,  0x44,  0x25,  0x04,  0x25,  0x07,  0x3F,  0x1C,  0x21,  0xE4,  0x21,  0x04,  0x21,  0x04,  0x21,  0x04, 	/* 34A20 */
+	0x43,  0x04,  0x9C,  0x04,  0x04,  0x04,  0x44,  0x0A,  0x24,  0x09,  0x24,  0x11,  0x04,  0x3F,  0x44,  0x44, 	/* 34A30 */
+	0x24,  0x04,  0x24,  0x7F,  0x84,  0x04,  0x07,  0x16,  0x3C,  0x15,  0xC4,  0x25,  0x04,  0x44,  0x84,  0x04, 	/* 34A40 */
+	0x04,  0x0C,  0x04,  0x9F,  0x11,  0x04,  0x11,  0x04,  0x7F,  0xA4,  0x11,  0x14,  0x1F,  0x14,  0x11,  0x04, 	/* 34A50 */
+	0x1F,  0x44,  0x11,  0x24,  0x11,  0x24,  0x7F,  0xC4,  0x2A,  0x07,  0x2A,  0x9C,  0x33,  0xE4,  0x20,  0x04, 	/* 34A60 */
+	0x3F,  0xC4,  0x00,  0x04,  0xA1,  0x08,  0x10,  0x08,  0x10,  0x7F,  0x28,  0x08,  0x28,  0x3E,  0x44,  0x22, 	/* 34A70 */
+	0xCA,  0x23,  0x29,  0x3E,  0x28,  0x22,  0x88,  0x22,  0x48,  0x3E,  0x48,  0x08,  0x0F,  0x7F,  0x38,  0x09, 	/* 34A80 */
+	0xC8,  0x08,  0x08,  0x08,  0x08,  0xA4,  0x00,  0x08,  0x00,  0x30,  0x0F,  0xC0,  0x08,  0x00,  0x08,  0x00, 	/* 34A90 */
+	0x08,  0x00,  0x0F,  0xFF,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x10,  0x20,  0x10,  0x20, 	/* 34AA0 */
+	0x20,  0x20,  0x40,  0x20,  0x00,  0x20,  0xA5,  0x00,  0x10,  0x00,  0x60,  0x0F,  0x80,  0x08,  0x00,  0x08, 	/* 34AB0 */
+	0x00,  0x0F,  0xFF,  0x08,  0x40,  0x08,  0x40,  0x0F,  0x40,  0x08,  0xF0,  0x10,  0x4C,  0x10,  0x42,  0x20, 	/* 34AC0 */
+	0x40,  0x40,  0x40,  0x00,  0x40,  0x00,  0x40,  0xA7,  0x02,  0x40,  0x04,  0x20,  0x1C,  0x38,  0x62,  0x46, 	/* 34AD0 */
+	0x01,  0x80,  0x02,  0x60,  0x0C,  0x18,  0x70,  0x67,  0x0F,  0x80,  0x08,  0x00,  0x0F,  0xFE,  0x08,  0x40, 	/* 34AE0 */
+	0x10,  0x40,  0x20,  0x40,  0x40,  0x40,  0x00,  0x40,  0xAB,  0x00,  0x04,  0x7F,  0x98,  0x08,  0x60,  0x08, 	/* 34AF0 */
+	0x40,  0x08,  0x40,  0x10,  0x7F,  0x1E,  0x44,  0x12,  0x44,  0x32,  0x44,  0x32,  0x44,  0x52,  0x44,  0x12, 	/* 34B00 */
+	0x44,  0x1E,  0x84,  0x00,  0x84,  0x01,  0x04,  0x00,  0x04,  0xAC,  0x04,  0x02,  0x04,  0x0C,  0x7F,  0xF0, 	/* 34B10 */
+	0x04,  0x20,  0x3F,  0xA0,  0x24,  0xBF,  0x24,  0xA4,  0x3F,  0xA4,  0x24,  0xA4,  0x24,  0xA4,  0x3F,  0xA4, 	/* 34B20 */
+	0x04,  0x24,  0x7F,  0xC4,  0x04,  0x44,  0x04,  0x84,  0x04,  0x04,  0xAD,  0x04,  0x02,  0x44,  0x0C,  0x65, 	/* 34B30 */
+	0x70,  0x55,  0x40,  0x56,  0x40,  0x44,  0x40,  0x7F,  0x7F,  0x44,  0x44,  0x4E,  0x44,  0x4D,  0x44,  0x55, 	/* 34B40 */
+	0x44,  0x64,  0x44,  0x44,  0x84,  0x44,  0x84,  0x7F,  0x04,  0x00,  0x04,  0xAF,  0x11,  0x02,  0x11,  0x0C, 	/* 34B50 */
+	0x7F,  0xF0,  0x11,  0x20,  0x11,  0x20,  0x1F,  0x3F,  0x11,  0x24,  0x11,  0x24,  0x1F,  0x24,  0x11,  0x24, 	/* 34B60 */
+	0x11,  0x24,  0x7F,  0xE4,  0x12,  0x44,  0x11,  0x44,  0x21,  0x84,  0x40,  0x04,  0xB0,  0x04,  0x02,  0x04, 	/* 34B70 */
+	0x0C,  0x7F,  0x70,  0x22,  0x40,  0x12,  0x40,  0x14,  0x7F,  0x7F,  0xC4,  0x08,  0x44,  0x08,  0x44,  0x7F, 	/* 34B80 */
+	0x44,  0x0C,  0x44,  0x1A,  0x44,  0x19,  0x84,  0x28,  0x84,  0x49,  0x04,  0x08,  0x04,  0xB7,  0x09,  0x02, 	/* 34B90 */
+	0x52,  0x04,  0x56,  0xB8,  0x49,  0x20,  0x56,  0xA0,  0x5F,  0xBF,  0x40,  0x24,  0x7F,  0xA4,  0x49,  0x24, 	/* 34BA0 */
+	0x56,  0xA4,  0x49,  0x24,  0x56,  0xA4,  0x5F,  0xA4,  0x40,  0x24,  0x7F,  0xC4,  0x00,  0x84,  0xB9,  0x00, 	/* 34BB0 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0xF8,  0x01, 	/* 34BC0 */
+	0x08,  0x01,  0x08,  0x02,  0x08,  0x02,  0x08,  0x04,  0x08,  0x04,  0x08,  0x08,  0x08,  0x10,  0x70,  0xBC, 	/* 34BD0 */
+	0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x7F,  0x28,  0x10,  0x28,  0x10,  0x44,  0x1E,  0x64,  0x12,  0xA2, 	/* 34BE0 */
+	0x13,  0x11,  0x12,  0x10,  0x12,  0x40,  0x12,  0x20,  0x22,  0x10,  0x22,  0x10,  0x42,  0x08,  0x0C,  0x08, 	/* 34BF0 */
+	0xBD,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x7F,  0x7F,  0x10,  0x48,  0x10,  0x88,  0x1F,  0x4E,  0x12, 	/* 34C00 */
+	0x7A,  0x13,  0xCA,  0x12,  0x4A,  0x12,  0x4C,  0x12,  0x48,  0x22,  0x48,  0x22,  0x41,  0x42,  0x21,  0x0C, 	/* 34C10 */
+	0x1F,  0x81,  0x01,  0x00,  0x01,  0x00,  0x3F,  0xFC,  0x08,  0x20,  0x04,  0x40,  0x7F,  0xFE,  0x41,  0x02, 	/* 34C20 */
+	0x41,  0x02,  0x3F,  0xFC,  0x02,  0x00,  0x03,  0xF0,  0x02,  0x10,  0x04,  0x10,  0x04,  0x10,  0x18,  0x10, 	/* 34C30 */
+	0x60,  0x60,  0x83,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x7F,  0x7F,  0x10,  0x40,  0x10,  0x80,  0x1F, 	/* 34C40 */
+	0x7C,  0x12,  0x54,  0x12,  0x54,  0x12,  0x54,  0x13,  0xFF,  0x22,  0x44,  0x22,  0x44,  0x42,  0x44,  0x02, 	/* 34C50 */
+	0x44,  0x0C,  0x4C,  0x84,  0x08,  0x40,  0x08,  0x40,  0x08,  0x40,  0x7E,  0xFF,  0x10,  0x82,  0x11,  0x0C, 	/* 34C60 */
+	0x1E,  0xF0,  0x12,  0x20,  0x12,  0xFC,  0x12,  0x20,  0x12,  0x20,  0x23,  0xFE,  0x22,  0x20,  0x42,  0x21, 	/* 34C70 */
+	0x02,  0x11,  0x0C,  0x0F,  0x85,  0x08,  0x40,  0x08,  0x40,  0x08,  0x40,  0x7F,  0x7F,  0x08,  0x90,  0x08, 	/* 34C80 */
+	0x92,  0x09,  0x22,  0x0F,  0x34,  0x09,  0x74,  0x09,  0xA8,  0x09,  0x28,  0x11,  0x24,  0x11,  0x24,  0x21, 	/* 34C90 */
+	0x22,  0x41,  0x21,  0x06,  0x20,  0x86,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x7F,  0x7F,  0x10,  0x50, 	/* 34CA0 */
+	0x10,  0x90,  0x1E,  0xFF,  0x13,  0x10,  0x12,  0x10,  0x12,  0xFE,  0x12,  0x92,  0x22,  0x92,  0x22,  0x92, 	/* 34CB0 */
+	0x42,  0x9C,  0x02,  0x10,  0x0C,  0x10,  0x8B,  0x08,  0x40,  0x08,  0x40,  0x08,  0x7F,  0x7F,  0x80,  0x10, 	/* 34CC0 */
+	0x80,  0x11,  0x7E,  0x1E,  0x12,  0x12,  0x14,  0x12,  0x50,  0x12,  0x50,  0x12,  0x5E,  0x12,  0x50,  0x22, 	/* 34CD0 */
+	0x50,  0x22,  0xB0,  0x42,  0x98,  0x0D,  0x07,  0x8C,  0x08,  0x40,  0x08,  0x40,  0x08,  0x40,  0x7E,  0xFF, 	/* 34CE0 */
+	0x10,  0x80,  0x11,  0x50,  0x1E,  0x50,  0x12,  0x7E,  0x12,  0x90,  0x13,  0x10,  0x12,  0x7E,  0x12,  0x10, 	/* 34CF0 */
+	0x22,  0x10,  0x42,  0x10,  0x03,  0xFF,  0x0C,  0x00,  0x8F,  0x08,  0x40,  0x08,  0x40,  0x08,  0x7F,  0x7F, 	/* 34D00 */
+	0x50,  0x10,  0x90,  0x10,  0xBE,  0x1F,  0x28,  0x12,  0x48,  0x12,  0x88,  0x12,  0xFF,  0x12,  0x08,  0x12, 	/* 34D10 */
+	0x14,  0x22,  0x14,  0x22,  0x24,  0x42,  0x42,  0x0C,  0x81,  0x92,  0x08,  0x40,  0x08,  0x40,  0x08,  0x40, 	/* 34D20 */
+	0x7E,  0xFF,  0x10,  0x90,  0x11,  0x10,  0x1E,  0xFF,  0x12,  0x24,  0x12,  0xFA,  0x12,  0x45,  0x12,  0x54, 	/* 34D30 */
+	0x12,  0x54,  0x22,  0x54,  0x42,  0x55,  0x02,  0x85,  0x0D,  0x03,  0x97,  0x08,  0x40,  0x08,  0x40,  0x08, 	/* 34D40 */
+	0x7F,  0x7E,  0x80,  0x11,  0x44,  0x13,  0xFF,  0x10,  0x44,  0x1E,  0x7C,  0x12,  0x44,  0x12,  0x7C,  0x12, 	/* 34D50 */
+	0x44,  0x13,  0xFF,  0x22,  0x08,  0x22,  0x24,  0x42,  0x42,  0x0D,  0x82,  0x99,  0x08,  0x04,  0x08,  0x18, 	/* 34D60 */
+	0x09,  0xF2,  0x7E,  0x92,  0x10,  0x54,  0x11,  0xFF,  0x1E,  0x38,  0x12,  0x54,  0x12,  0x92,  0x13,  0xFF, 	/* 34D70 */
+	0x12,  0x92,  0x22,  0xFE,  0x22,  0x92,  0x42,  0x92,  0x02,  0xFE,  0x0C,  0x00,  0x9B,  0x08,  0x20,  0x08, 	/* 34D80 */
+	0x20,  0x08,  0x7F,  0x7F,  0x82,  0x10,  0xFC,  0x10,  0x92,  0x1E,  0x54,  0x13,  0xFF,  0x12,  0x54,  0x12, 	/* 34D90 */
+	0x92,  0x13,  0xFF,  0x22,  0x92,  0x22,  0xFE,  0x42,  0x92,  0x02,  0xFE,  0x0C,  0x00,  0xA0,  0x00,  0x00, 	/* 34DA0 */
+	0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0xC0, 	/* 34DB0 */
+	0x01,  0x40,  0x01,  0x40,  0x02,  0x40,  0x04,  0x41,  0x08,  0x41,  0x10,  0x21,  0x60,  0x1F,  0xA1,  0x00, 	/* 34DC0 */
+	0x00,  0x1F,  0xF8,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x07,  0xFF,  0x00, 	/* 34DD0 */
+	0x40,  0x00,  0x60,  0x00,  0xA0,  0x01,  0x20,  0x02,  0x21,  0x04,  0x21,  0x18,  0x11,  0x60,  0x0F,  0xA2, 	/* 34DE0 */
+	0x00,  0x00,  0x3E,  0xFE,  0x22,  0x48,  0x22,  0x48,  0x3E,  0x48,  0x22,  0x48,  0x22,  0x48,  0x3F,  0xFF, 	/* 34DF0 */
+	0x20,  0x18,  0x24,  0x18,  0x22,  0x18,  0x22,  0x28,  0x2D,  0x28,  0x31,  0x49,  0x60,  0x89,  0x03,  0x07, 	/* 34E00 */
+	0xA5,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x0F, 	/* 34E10 */
+	0xF8,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00, 	/* 34E20 */
+	0x00,  0xA6,  0x00,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0, 	/* 34E30 */
+	0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x00,  0x00,  0x00,  0x00,  0x7F,  0xFE, 	/* 34E40 */
+	0x00,  0x00,  0xA7,  0x20,  0x00,  0x23,  0xFC,  0x22,  0x04,  0x22,  0x04,  0x22,  0x04,  0x22,  0x04,  0x22, 	/* 34E50 */
+	0x04,  0x23,  0xFC,  0x22,  0x04,  0x22,  0x04,  0x22,  0x04,  0x22,  0x04,  0x22,  0x04,  0x22,  0x04,  0x23, 	/* 34E60 */
+	0xFC,  0x20,  0x00,  0xA8,  0x10,  0x00,  0x10,  0x0C,  0x10,  0xF0,  0x1F,  0x00,  0x10,  0x02,  0x10,  0x02, 	/* 34E70 */
+	0x0F,  0xFE,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08, 	/* 34E80 */
+	0x0F,  0xF8,  0x00,  0x00,  0xA9,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x08, 	/* 34E90 */
+	0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 34EA0 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0xAC,  0x04,  0x00,  0x04,  0x00,  0x07,  0xFE,  0x08,  0x02,  0x08,  0x02, 	/* 34EB0 */
+	0x17,  0xE2,  0x24,  0x22,  0x44,  0x22,  0x07,  0xE2,  0x04,  0x22,  0x04,  0x22,  0x04,  0x22,  0x07,  0xE2, 	/* 34EC0 */
+	0x00,  0x02,  0x00,  0x04,  0x00,  0x18,  0xAD,  0x08,  0x00,  0x08,  0x7C,  0x08,  0x44,  0x08,  0x44,  0x7F, 	/* 34ED0 */
+	0x44,  0x09,  0x44,  0x09,  0x7C,  0x09,  0x44,  0x09,  0x44,  0x09,  0x44,  0x09,  0x44,  0x09,  0x7C,  0x11, 	/* 34EE0 */
+	0x00,  0x11,  0x01,  0x20,  0x81,  0x40,  0x7F,  0xB1,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08, 	/* 34EF0 */
+	0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80, 	/* 34F00 */
+	0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0xBA,  0x00,  0x00,  0x7D,  0xFE,  0x44,  0x20,  0x44, 	/* 34F10 */
+	0x20,  0x44,  0x20,  0x44,  0x20,  0x7C,  0x20,  0x45,  0xFE,  0x44,  0x20,  0x44,  0x20,  0x44,  0x20,  0x44, 	/* 34F20 */
+	0x20,  0x7C,  0x20,  0x00,  0x20,  0x07,  0xFF,  0x00,  0x00,  0xBB,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08, 	/* 34F30 */
+	0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x04,  0x10,  0x02,  0x20, 	/* 34F40 */
+	0x01,  0x40,  0x00,  0x80,  0x03,  0x60,  0x0C,  0x18,  0x70,  0x07,  0x82,  0x00,  0x00,  0x0F,  0xF8,  0x08, 	/* 34F50 */
+	0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x02,  0x00,  0x3C,  0x7E,  0x20,  0x42,  0x20, 	/* 34F60 */
+	0x42,  0x23,  0x42,  0x2C,  0x42,  0x70,  0x4C,  0x00,  0x40,  0x00,  0x40,  0x83,  0x00,  0x00,  0x0F,  0xFC, 	/* 34F70 */
+	0x08,  0x04,  0x0F,  0xFC,  0x08,  0x04,  0x0F,  0xFC,  0x00,  0x00,  0x1F,  0xFF,  0x10,  0x40,  0x10,  0x40, 	/* 34F80 */
+	0x10,  0x40,  0x10,  0x40,  0x20,  0xA0,  0x21,  0x10,  0x46,  0x0C,  0x18,  0x03,  0x86,  0x00,  0x00,  0x1F, 	/* 34F90 */
+	0xF8,  0x10,  0x08,  0x10,  0x08,  0x1F,  0xF8,  0x10,  0x08,  0x10,  0x08,  0x1F,  0xF8,  0x10,  0x40,  0x10, 	/* 34FA0 */
+	0x40,  0x10,  0x4C,  0x1F,  0x70,  0x10,  0x40,  0x10,  0x42,  0x1F,  0x42,  0x70,  0x3E,  0x87,  0x00,  0x00, 	/* 34FB0 */
+	0x0F,  0xFC,  0x08,  0x04,  0x0F,  0xFC,  0x08,  0x04,  0x08,  0x04,  0x0F,  0xFC,  0x01,  0x10,  0x0E,  0x10, 	/* 34FC0 */
+	0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x04,  0x10,  0x04,  0x10,  0x08,  0x10,  0x8A,  0x00, 	/* 34FD0 */
+	0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x7F, 	/* 34FE0 */
+	0xFF,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x01,  0x20,  0x02,  0x10,  0x0C,  0x0C,  0x70,  0x03,  0x8C, 	/* 34FF0 */
+	0x00,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x00,  0x00, 	/* 35000 */
+	0x3F,  0xFC,  0x20,  0x04,  0x20,  0x04,  0x3F,  0xFC,  0x20,  0x04,  0x20,  0x04,  0x3F,  0xFC,  0x00,  0x00, 	/* 35010 */
+	0x8E,  0x00,  0x00,  0x3E,  0x7E,  0x22,  0x42,  0x22,  0x42,  0x22,  0x42,  0x22,  0x7E,  0x3E,  0x42,  0x22, 	/* 35020 */
+	0x42,  0x22,  0x42,  0x22,  0x7E,  0x22,  0x42,  0x3E,  0x42,  0x00,  0x82,  0x00,  0x82,  0x01,  0x02,  0x02, 	/* 35030 */
+	0x06,  0x8F,  0x00,  0x10,  0x00,  0x60,  0x0F,  0xC0,  0x08,  0x40,  0x0F,  0xFE,  0x08,  0x40,  0x08,  0x22, 	/* 35040 */
+	0x0F,  0x12,  0x70,  0x0E,  0x0F,  0xFA,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8, 	/* 35050 */
+	0x00,  0x00,  0x93,  0x00,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x08, 	/* 35060 */
+	0x10,  0x0F,  0xF0,  0x02,  0x00,  0x07,  0xFC,  0x18,  0x94,  0x61,  0x14,  0x06,  0x24,  0x18,  0x44,  0x01, 	/* 35070 */
+	0x88,  0x00,  0x30,  0x94,  0x02,  0x20,  0x02,  0x20,  0x1F,  0xFC,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20, 	/* 35080 */
+	0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08, 	/* 35090 */
+	0x0F,  0xF8,  0x00,  0x00,  0x9C,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08, 	/* 350A0 */
+	0x08,  0x0F,  0xF8,  0x00,  0x00,  0x7F,  0xFF,  0x02,  0x00,  0x07,  0xFE,  0x18,  0x92,  0x61,  0x12,  0x06, 	/* 350B0 */
+	0x22,  0x18,  0x42,  0x01,  0x8C,  0x9F,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08, 	/* 350C0 */
+	0x08,  0x08,  0x0F,  0xF8,  0x04,  0x80,  0x04,  0x80,  0x0F,  0xFC,  0x10,  0x80,  0x2F,  0xFC,  0x00,  0x80, 	/* 350D0 */
+	0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0xA0,  0x00,  0x20,  0x00,  0x20,  0x78,  0x20,  0x49,  0xFC,  0x49, 	/* 350E0 */
+	0x24,  0x49,  0x24,  0x79,  0x24,  0x49,  0x24,  0x4F,  0xFF,  0x48,  0x20,  0x48,  0x50,  0x78,  0x50,  0x48, 	/* 350F0 */
+	0x88,  0x01,  0x04,  0x02,  0x02,  0x0C,  0x01,  0xA5,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80, 	/* 35100 */
+	0x1F,  0xFC,  0x01,  0x40,  0x7F,  0xFF,  0x02,  0x20,  0x04,  0x10,  0x1F,  0xFC,  0x64,  0x13,  0x07,  0xF0, 	/* 35110 */
+	0x04,  0x10,  0x04,  0x10,  0x07,  0xF0,  0x00,  0x00,  0xA7,  0x00,  0x20,  0x00,  0x20,  0x7C,  0x20,  0x47, 	/* 35120 */
+	0xFE,  0x44,  0x20,  0x44,  0x20,  0x44,  0x20,  0x7F,  0xFF,  0x44,  0x70,  0x44,  0x70,  0x44,  0xA8,  0x44, 	/* 35130 */
+	0xA4,  0x7D,  0x22,  0x42,  0x21,  0x04,  0x20,  0x00,  0x20,  0xA8,  0x00,  0x40,  0x00,  0x40,  0x3E,  0x40, 	/* 35140 */
+	0x22,  0x7F,  0x22,  0x50,  0x22,  0x90,  0x22,  0x90,  0x3F,  0x1E,  0x22,  0x10,  0x22,  0x10,  0x22,  0x10, 	/* 35150 */
+	0x22,  0x1E,  0x3E,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0xAD,  0x00,  0x00,  0x03,  0xFE,  0x7C, 	/* 35160 */
+	0x22,  0x44,  0x22,  0x44,  0x42,  0x44,  0x42,  0x44,  0x82,  0x7D,  0x0C,  0x46,  0x00,  0x44,  0xFE,  0x44, 	/* 35170 */
+	0x82,  0x44,  0x82,  0x7C,  0x82,  0x00,  0x82,  0x00,  0xFE,  0x00,  0x00,  0xAF,  0x00,  0x00,  0x07,  0xF8, 	/* 35180 */
+	0x04,  0x08,  0x07,  0xF8,  0x04,  0x08,  0x04,  0x08,  0x07,  0xF8,  0x00,  0x00,  0x7F,  0xFF,  0x04,  0x80, 	/* 35190 */
+	0x04,  0x80,  0x04,  0xFC,  0x0A,  0x80,  0x09,  0x80,  0x10,  0x60,  0x20,  0x1F,  0xB4,  0x00,  0x00,  0x0F, 	/* 351A0 */
+	0xFC,  0x08,  0x04,  0x0F,  0xFC,  0x08,  0x04,  0x08,  0x04,  0x0F,  0xFC,  0x03,  0x00,  0x1C,  0x3E,  0x11, 	/* 351B0 */
+	0x22,  0x11,  0x22,  0x11,  0x22,  0x1F,  0x22,  0x72,  0x3C,  0x02,  0x20,  0x0C,  0x20,  0xB5,  0x00,  0x00, 	/* 351C0 */
+	0x01,  0xFE,  0x79,  0x02,  0x49,  0x02,  0x49,  0x02,  0x49,  0xFE,  0x49,  0x00,  0x79,  0x40,  0x49,  0x42, 	/* 351D0 */
+	0x49,  0x4C,  0x49,  0x70,  0x4A,  0x40,  0x7A,  0x41,  0x04,  0x41,  0x08,  0x21,  0x00,  0x1F,  0xB6,  0x00, 	/* 351E0 */
+	0x00,  0x3F,  0x00,  0x00,  0x7E,  0x00,  0x42,  0x3C,  0x42,  0x04,  0xC2,  0x04,  0xFE,  0x77,  0x42,  0x16, 	/* 351F0 */
+	0x42,  0x16,  0x42,  0x15,  0x42,  0x25,  0x7E,  0x24,  0x80,  0x44,  0x60,  0x04,  0x1F,  0x0C,  0x00,  0xBC, 	/* 35200 */
+	0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x10,  0x10,  0x10,  0x17,  0xE8, 	/* 35210 */
+	0x24,  0x28,  0x27,  0xE4,  0x44,  0x22,  0x04,  0x20,  0x07,  0xE0,  0x00,  0x00,  0x7F,  0xFE,  0x00,  0x00, 	/* 35220 */
+	0xBF,  0x00,  0x10,  0x00,  0x10,  0x78,  0x10,  0x49,  0xFF,  0x49,  0x00,  0x49,  0x10,  0x49,  0x10,  0x79, 	/* 35230 */
+	0x10,  0x49,  0x10,  0x49,  0x10,  0x49,  0x14,  0x4A,  0x22,  0x7A,  0x22,  0x04,  0x4F,  0x09,  0xF1,  0x00, 	/* 35240 */
+	0x01,  0x81,  0x00,  0x00,  0x1F,  0xF8,  0x10,  0x08,  0x1F,  0xF8,  0x10,  0x08,  0x1F,  0xF8,  0x00,  0x00, 	/* 35250 */
+	0x12,  0x44,  0x0A,  0x44,  0x0A,  0x48,  0x02,  0x60,  0x1A,  0x58,  0x62,  0x46,  0x04,  0x41,  0x18,  0x41, 	/* 35260 */
+	0x60,  0x3F,  0x82,  0x00,  0x20,  0x00,  0x20,  0x7D,  0xFE,  0x44,  0x20,  0x44,  0x20,  0x44,  0x20,  0x47, 	/* 35270 */
+	0xFF,  0x7C,  0x04,  0x44,  0x04,  0x47,  0xFF,  0x45,  0x04,  0x44,  0x84,  0x7C,  0x84,  0x00,  0x04,  0x00, 	/* 35280 */
+	0x04,  0x00,  0x0C,  0x83,  0x00,  0x00,  0x1F,  0xF8,  0x10,  0x08,  0x1F,  0xF8,  0x10,  0x08,  0x1F,  0xF8, 	/* 35290 */
+	0x08,  0x88,  0x04,  0x90,  0x04,  0xA0,  0x7F,  0xFF,  0x02,  0x40,  0x02,  0x40,  0x02,  0x40,  0x04,  0x42, 	/* 352A0 */
+	0x18,  0x22,  0x60,  0x1E,  0x84,  0x00,  0x20,  0x00,  0x22,  0x7E,  0x22,  0x45,  0x24,  0x44,  0xA4,  0x44, 	/* 352B0 */
+	0xA8,  0x44,  0x20,  0x7F,  0xFF,  0x44,  0x48,  0x44,  0x48,  0x44,  0x48,  0x44,  0x48,  0x7C,  0x88,  0x00, 	/* 352C0 */
+	0x89,  0x03,  0x09,  0x0C,  0x07,  0x89,  0x00,  0x00,  0x3F,  0xFE,  0x04,  0x10,  0x05,  0x14,  0x09,  0xA6, 	/* 352D0 */
+	0x3E,  0x79,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08, 	/* 352E0 */
+	0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x8B,  0x00,  0x00,  0x3F,  0xFE,  0x02,  0x20,  0x12,  0x24,  0x0A, 	/* 352F0 */
+	0x24,  0x0A,  0x28,  0x02,  0x20,  0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08, 	/* 35300 */
+	0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x8F,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8, 	/* 35310 */
+	0x08,  0x08,  0x0F,  0xF8,  0x00,  0x80,  0x3F,  0xFE,  0x20,  0x02,  0x21,  0x02,  0x7F,  0xFF,  0x02,  0x10, 	/* 35320 */
+	0x07,  0x10,  0x00,  0xE0,  0x03,  0x98,  0x3C,  0x04,  0x92,  0x00,  0x00,  0x07,  0xFF,  0x78,  0x50,  0x48, 	/* 35330 */
+	0x50,  0x48,  0x50,  0x4B,  0xFE,  0x4A,  0x52,  0x7A,  0x52,  0x4A,  0x52,  0x4A,  0x52,  0x4A,  0x9E,  0x4B, 	/* 35340 */
+	0x02,  0x7A,  0x02,  0x02,  0x02,  0x03,  0xFE,  0x00,  0x00,  0x9D,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x84, 	/* 35350 */
+	0x7F,  0xFF,  0x00,  0x84,  0x1F,  0xFC,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x08,  0x08, 	/* 35360 */
+	0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x7F,  0xFF,  0x9E,  0x00,  0x04,  0x01,  0xC8,  0x78, 	/* 35370 */
+	0x30,  0x48,  0x68,  0x4B,  0x84,  0x48,  0x40,  0x4F,  0xFF,  0x78,  0xA0,  0x49,  0x20,  0x4B,  0xFC,  0x4D, 	/* 35380 */
+	0x24,  0x49,  0x24,  0x79,  0x24,  0x01,  0x38,  0x01,  0x20,  0x00,  0x20,  0x9F,  0x00,  0x00,  0x1F,  0xFC, 	/* 35390 */
+	0x10,  0x04,  0x1F,  0xFC,  0x10,  0x04,  0x1F,  0xFC,  0x00,  0x50,  0x00,  0x48,  0x1F,  0xFE,  0x10,  0x44, 	/* 353A0 */
+	0x1F,  0x24,  0x11,  0x28,  0x11,  0x10,  0x21,  0x29,  0x2E,  0x45,  0x41,  0x83,  0xA2,  0x08,  0x04,  0x08, 	/* 353B0 */
+	0x78,  0x7F,  0x40,  0x08,  0x40,  0x08,  0x7F,  0x0E,  0x48,  0x78,  0x88,  0x08,  0x88,  0x19,  0x08,  0x0F, 	/* 353C0 */
+	0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0xA4,  0x00,  0x00, 	/* 353D0 */
+	0x03,  0xFE,  0x78,  0x40,  0x48,  0x40,  0x4B,  0xF8,  0x48,  0x88,  0x48,  0x88,  0x78,  0x88,  0x4F,  0xFF, 	/* 353E0 */
+	0x48,  0x00,  0x49,  0xFC,  0x49,  0x04,  0x79,  0x04,  0x01,  0x04,  0x01,  0xFC,  0x00,  0x00,  0xA6,  0x00, 	/* 353F0 */
+	0x80,  0x00,  0x80,  0x78,  0xFF,  0x49,  0x00,  0x49,  0x00,  0x4A,  0xFC,  0x4C,  0xA4,  0x78,  0xA4,  0x4F, 	/* 35400 */
+	0xFF,  0x49,  0x24,  0x49,  0x24,  0x49,  0x24,  0x7B,  0xFF,  0x02,  0x04,  0x00,  0x08,  0x00,  0x30,  0xA7, 	/* 35410 */
+	0x00,  0x20,  0x00,  0xA0,  0x3C,  0xA0,  0x25,  0xFE,  0x25,  0x20,  0x26,  0x20,  0x24,  0x20,  0x3F,  0xFF, 	/* 35420 */
+	0x24,  0x20,  0x24,  0x00,  0x25,  0xFC,  0x25,  0x04,  0x3D,  0x04,  0x01,  0x04,  0x01,  0xFC,  0x00,  0x00, 	/* 35430 */
+	0xA8,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x1F, 	/* 35440 */
+	0xFE,  0x10,  0x00,  0x17,  0xFC,  0x10,  0x00,  0x1F,  0xFF,  0x22,  0x44,  0x22,  0x28,  0x43,  0x98,  0x0E, 	/* 35450 */
+	0x07,  0xA9,  0x00,  0x40,  0x7C,  0x78,  0x44,  0x88,  0x45,  0x10,  0x46,  0x20,  0x45,  0xFC,  0x7D,  0x24, 	/* 35460 */
+	0x45,  0x24,  0x45,  0x24,  0x45,  0xFC,  0x44,  0x50,  0x7C,  0x50,  0x00,  0x90,  0x01,  0x11,  0x02,  0x11, 	/* 35470 */
+	0x04,  0x0F,  0xAE,  0x10,  0x10,  0x08,  0x10,  0x04,  0x20,  0x3F,  0xFC,  0x12,  0x48,  0x0A,  0x48,  0x0A, 	/* 35480 */
+	0x50,  0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10,  0x0F, 	/* 35490 */
+	0xF0,  0x00,  0x00,  0xAF,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8, 	/* 354A0 */
+	0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x02,  0xB0,  0x0C,  0x8C, 	/* 354B0 */
+	0x30,  0x82,  0x01,  0x80,  0xB0,  0x01,  0x02,  0x01,  0x0C,  0x79,  0x30,  0x4F,  0xE0,  0x49,  0x20,  0x49, 	/* 354C0 */
+	0x3F,  0x49,  0xA4,  0x7B,  0x64,  0x4B,  0x24,  0x4D,  0x24,  0x49,  0x24,  0x49,  0x24,  0x79,  0x44,  0x01, 	/* 354D0 */
+	0x44,  0x01,  0x84,  0x01,  0x04,  0xB4,  0x00,  0x20,  0x00,  0x20,  0x3D,  0xFE,  0x24,  0x20,  0x25,  0xFC, 	/* 354E0 */
+	0x24,  0x20,  0x3F,  0xFF,  0x24,  0x00,  0x24,  0xFC,  0x24,  0x84,  0x24,  0xFC,  0x3C,  0x84,  0x00,  0xFC, 	/* 354F0 */
+	0x00,  0x84,  0x00,  0x84,  0x00,  0x8C,  0xB6,  0x00,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10,  0x0F, 	/* 35500 */
+	0xF0,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x42,  0x42,  0x7E, 	/* 35510 */
+	0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x00,  0x00,  0xBA,  0x10,  0x00,  0x1F,  0xBE,  0x14,  0x22,  0x24,  0x22, 	/* 35520 */
+	0x7F,  0xE2,  0x06,  0x22,  0x05,  0x3E,  0x08,  0x80,  0x10,  0x00,  0x6F,  0xF8,  0x08,  0x08,  0x0F,  0xF8, 	/* 35530 */
+	0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x81,  0x00,  0x20,  0x00,  0x20,  0x79,  0xFC,  0x48, 	/* 35540 */
+	0x20,  0x48,  0xA8,  0x48,  0x88,  0x4F,  0xFF,  0x78,  0x88,  0x48,  0x88,  0x48,  0x00,  0x4B,  0xFE,  0x48, 	/* 35550 */
+	0x90,  0x78,  0x90,  0x01,  0x11,  0x02,  0x11,  0x0C,  0x0F,  0x83,  0x00,  0x00,  0x1F,  0xF8,  0x10,  0x08, 	/* 35560 */
+	0x1F,  0xF8,  0x10,  0x08,  0x1F,  0xF8,  0x00,  0x40,  0x02,  0x40,  0x3E,  0x7E,  0x02,  0x40,  0x3E,  0x7E, 	/* 35570 */
+	0x02,  0x40,  0x0E,  0x7F,  0x74,  0x40,  0x08,  0x40,  0x10,  0x40,  0x84,  0x00,  0x20,  0x00,  0x20,  0x7B, 	/* 35580 */
+	0xFF,  0x4A,  0x01,  0x4A,  0xFD,  0x48,  0x00,  0x48,  0xFC,  0x78,  0x84,  0x48,  0x84,  0x48,  0xFC,  0x48, 	/* 35590 */
+	0x84,  0x48,  0x84,  0x78,  0xFC,  0x00,  0x00,  0x03,  0xFF,  0x00,  0x00,  0x87,  0x00,  0x00,  0x03,  0xDE, 	/* 355A0 */
+	0x7A,  0x42,  0x4A,  0x42,  0x4A,  0x42,  0x4B,  0xDE,  0x4A,  0x00,  0x7A,  0x3E,  0x4B,  0xE2,  0x4A,  0x14, 	/* 355B0 */
+	0x4A,  0x14,  0x4A,  0x08,  0x7B,  0xC8,  0x02,  0x14,  0x02,  0x22,  0x02,  0x41,  0x88,  0x0F,  0xF8,  0x08, 	/* 355C0 */
+	0x08,  0x0F,  0xF8,  0x08,  0x08,  0x7F,  0xFE,  0x40,  0x82,  0x5F,  0xFC,  0x00,  0x80,  0x0F,  0xF8,  0x08, 	/* 355D0 */
+	0x88,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x89,  0x00,  0x00, 	/* 355E0 */
+	0x03,  0xFE,  0x7A,  0x02,  0x4A,  0x22,  0x49,  0xFC,  0x48,  0x20,  0x49,  0xFC,  0x79,  0x24,  0x49,  0xFC, 	/* 355F0 */
+	0x49,  0x24,  0x49,  0x24,  0x49,  0xFC,  0x78,  0x20,  0x07,  0xFF,  0x00,  0x20,  0x00,  0x20,  0x8E,  0x00, 	/* 35600 */
+	0x88,  0x00,  0x88,  0x7B,  0xFF,  0x48,  0x88,  0x48,  0x88,  0x48,  0x20,  0x49,  0xFC,  0x79,  0x24,  0x49, 	/* 35610 */
+	0x24,  0x49,  0x24,  0x4F,  0xFF,  0x48,  0x20,  0x78,  0x50,  0x00,  0x88,  0x03,  0x04,  0x0C,  0x03,  0x91, 	/* 35620 */
+	0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x0A,  0x0F,  0xFA,  0x00,  0x84,  0x1F,  0xF8, 	/* 35630 */
+	0x00,  0x90,  0x7F,  0xFF,  0x01,  0x00,  0x07,  0xF8,  0x1C,  0x08,  0x67,  0xF8,  0x04,  0x08,  0x07,  0xF8, 	/* 35640 */
+	0x96,  0x00,  0x04,  0x00,  0x1A,  0x3D,  0xE2,  0x24,  0x24,  0x24,  0x94,  0x24,  0x58,  0x25,  0xFE,  0x3C, 	/* 35650 */
+	0x40,  0x27,  0xFF,  0x24,  0x40,  0x24,  0x7C,  0x24,  0xA4,  0x3C,  0x98,  0x01,  0x10,  0x02,  0x6C,  0x01, 	/* 35660 */
+	0x83,  0x97,  0x00,  0x20,  0x00,  0x20,  0x7F,  0xFE,  0x44,  0x88,  0x44,  0x48,  0x44,  0x50,  0x47,  0xFF, 	/* 35670 */
+	0x7C,  0x00,  0x44,  0xFC,  0x44,  0x84,  0x44,  0x84,  0x44,  0xFC,  0x7C,  0x84,  0x00,  0x84,  0x00,  0xFC, 	/* 35680 */
+	0x00,  0x00,  0x98,  0x00,  0x00,  0x01,  0xF8,  0x79,  0x08,  0x49,  0xF8,  0x49,  0x08,  0x49,  0x08,  0x49, 	/* 35690 */
+	0xF8,  0x78,  0x00,  0x4F,  0xFF,  0x48,  0x80,  0x49,  0xFE,  0x4E,  0x52,  0x78,  0x92,  0x03,  0x22,  0x00, 	/* 356A0 */
+	0x42,  0x01,  0x9C,  0x9D,  0x00,  0x00,  0x03,  0xFF,  0x7A,  0x01,  0x4A,  0xFD,  0x48,  0x84,  0x48,  0x84, 	/* 356B0 */
+	0x48,  0xFC,  0x78,  0x84,  0x48,  0x84,  0x48,  0xFC,  0x48,  0x20,  0x4B,  0xFF,  0x78,  0x00,  0x00,  0x48, 	/* 356C0 */
+	0x01,  0x84,  0x06,  0x02,  0xA2,  0x10,  0x00,  0x10,  0xF8,  0x10,  0x88,  0x7E,  0xF8,  0x52,  0x88,  0x52, 	/* 356D0 */
+	0x88,  0x7E,  0xF8,  0x52,  0x00,  0x53,  0xFF,  0x52,  0x40,  0x7E,  0xFE,  0x13,  0x4A,  0x10,  0x92,  0x13, 	/* 356E0 */
+	0x22,  0x10,  0x42,  0x11,  0x8C,  0xA6,  0x00,  0x00,  0x1F,  0xFF,  0x11,  0x08,  0x11,  0x08,  0x1F,  0xFF, 	/* 356F0 */
+	0x13,  0x9C,  0x15,  0x6A,  0x19,  0x49,  0x11,  0x08,  0x17,  0xFC,  0x14,  0x04,  0x17,  0xFC,  0x24,  0x04, 	/* 35700 */
+	0x24,  0x04,  0x47,  0xFC,  0x00,  0x00,  0xAB,  0x04,  0x02,  0x7F,  0xCC,  0x04,  0x30,  0x3F,  0xA0,  0x24, 	/* 35710 */
+	0xBF,  0x3F,  0xA4,  0x24,  0xA4,  0x7F,  0xC4,  0x04,  0x44,  0x04,  0x84,  0x0F,  0xF8,  0x08,  0x08,  0x0F, 	/* 35720 */
+	0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0xAE,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x20,  0x0F,  0xF8, 	/* 35730 */
+	0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x01,  0x00,  0x7F,  0xFF,  0x02,  0x10,  0x1F,  0xFC, 	/* 35740 */
+	0x64,  0x13,  0x07,  0xF0,  0x04,  0x10,  0x07,  0xF0,  0xB4,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F, 	/* 35750 */
+	0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x02,  0x20,  0x1F,  0xFC,  0x02,  0x20,  0x7F,  0xFF,  0x04,  0x88,  0x18, 	/* 35760 */
+	0x96,  0x65,  0xE1,  0x06,  0xB0,  0x38,  0x8E,  0x01,  0x80,  0xB8,  0x00,  0x20,  0x00,  0x20,  0x7B,  0xFF, 	/* 35770 */
+	0x48,  0x50,  0x4A,  0x8A,  0x49,  0x04,  0x4B,  0xFE,  0x7D,  0x05,  0x49,  0xFC,  0x49,  0x04,  0x49,  0xFC, 	/* 35780 */
+	0x49,  0x20,  0x79,  0x24,  0x02,  0x22,  0x04,  0x22,  0x00,  0x60,  0xB9,  0x10,  0x00,  0x09,  0xFC,  0x09, 	/* 35790 */
+	0x04,  0x01,  0xFC,  0x21,  0x04,  0x11,  0xFC,  0x10,  0x90,  0x01,  0xFE,  0x7B,  0x20,  0x0D,  0xFC,  0x09, 	/* 357A0 */
+	0x20,  0x09,  0xFC,  0x15,  0x20,  0x13,  0xFE,  0x21,  0x80,  0x40,  0x7F,  0xBC,  0x08,  0x20,  0x2A,  0x20, 	/* 357B0 */
+	0x49,  0x3F,  0x7F,  0x44,  0x49,  0x64,  0x5D,  0x98,  0x6B,  0x18,  0x49,  0x24,  0x4B,  0x43,  0x1F,  0xF8, 	/* 357C0 */
+	0x10,  0x08,  0x1F,  0xF8,  0x10,  0x08,  0x10,  0x08,  0x1F,  0xF8,  0x00,  0x00,  0xBE,  0x01,  0x08,  0x01, 	/* 357D0 */
+	0x08,  0x7F,  0xE8,  0x48,  0x0F,  0x4B,  0xD2,  0x4A,  0x52,  0x4B,  0xE2,  0x78,  0x0A,  0x4F,  0xCA,  0x48, 	/* 357E0 */
+	0x8C,  0x49,  0x04,  0x49,  0xCC,  0x7F,  0x0C,  0x01,  0x12,  0x01,  0x22,  0x03,  0x41,  0x81,  0x08,  0x00, 	/* 357F0 */
+	0x3F,  0x7E,  0x21,  0x48,  0x3F,  0x48,  0x21,  0xFF,  0x3F,  0x18,  0x26,  0x28,  0x3D,  0x49,  0x6F,  0xFF, 	/* 35800 */
+	0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x00,  0x84,  0x00, 	/* 35810 */
+	0x88,  0x00,  0x88,  0x7B,  0xFF,  0x48,  0x88,  0x4B,  0xFE,  0x49,  0x24,  0x49,  0x24,  0x7F,  0xFF,  0x49, 	/* 35820 */
+	0x24,  0x49,  0x24,  0x4B,  0xFE,  0x48,  0x20,  0x78,  0x20,  0x07,  0xFF,  0x00,  0x20,  0x00,  0x20,  0x87, 	/* 35830 */
+	0x00,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x3F,  0xFC,  0x01,  0x00,  0x7F,  0xFE, 	/* 35840 */
+	0x5D,  0x7A,  0x41,  0x02,  0x1F,  0xF8,  0x00,  0x00,  0x7F,  0xFE,  0x02,  0x20,  0x04,  0xD8,  0x3F,  0x04, 	/* 35850 */
+	0x89,  0x00,  0x20,  0x01,  0xFC,  0x78,  0x20,  0x4B,  0xFE,  0x48,  0x00,  0x48,  0x84,  0x7B,  0xFF,  0x48, 	/* 35860 */
+	0x84,  0x48,  0xE4,  0x4F,  0x1F,  0x48,  0x00,  0x7B,  0xFF,  0x00,  0x48,  0x00,  0x89,  0x03,  0x09,  0x0C, 	/* 35870 */
+	0x07,  0x96,  0x00,  0x0C,  0x03,  0xF4,  0x79,  0x44,  0x48,  0xA8,  0x4F,  0xFF,  0x4C,  0xA5,  0x4A,  0x8A, 	/* 35880 */
+	0x7A,  0x79,  0x4C,  0x41,  0x48,  0x7C,  0x48,  0x84,  0x49,  0x68,  0x7E,  0x10,  0x00,  0x70,  0x01,  0x8C, 	/* 35890 */
+	0x0E,  0x03,  0x99,  0x00,  0x00,  0x07,  0xFE,  0x04,  0x92,  0x7F,  0xFE,  0x48,  0x42,  0x4B,  0xFC,  0x48, 	/* 358A0 */
+	0x48,  0x7F,  0xFF,  0x48,  0x60,  0x49,  0xFC,  0x4B,  0x04,  0x4D,  0xFC,  0x79,  0x04,  0x01,  0x04,  0x01, 	/* 358B0 */
+	0xFC,  0x00,  0x00,  0x9A,  0x00,  0x88,  0x07,  0xFF,  0x78,  0x88,  0x4B,  0xFE,  0x4A,  0x02,  0x4A,  0xFA, 	/* 358C0 */
+	0x48,  0x00,  0x7F,  0xFF,  0x48,  0x40,  0x48,  0xAA,  0x4B,  0x5A,  0x48,  0x94,  0x7B,  0x34,  0x00,  0xD2, 	/* 358D0 */
+	0x07,  0x11,  0x00,  0x60,  0x9C,  0x00,  0x00,  0x03,  0xDE,  0x78,  0x42,  0x4B,  0xDE,  0x48,  0x42,  0x4B, 	/* 358E0 */
+	0xDE,  0x48,  0x88,  0x78,  0x90,  0x49,  0xFE,  0x4B,  0x10,  0x4D,  0xFC,  0x49,  0x10,  0x79,  0xFC,  0x01, 	/* 358F0 */
+	0x10,  0x01,  0xFF,  0x00,  0x00,  0x9D,  0x00,  0xFC,  0x3C,  0x84,  0x24,  0xFC,  0x24,  0x84,  0x24,  0xFC, 	/* 35900 */
+	0x24,  0x48,  0x3D,  0xFE,  0x24,  0x48,  0x27,  0xFF,  0x24,  0x48,  0x24,  0xA4,  0x25,  0xAB,  0x3E,  0x70, 	/* 35910 */
+	0x00,  0xA8,  0x01,  0x26,  0x00,  0x60,  0xA0,  0x00,  0x20,  0x00,  0x20,  0x7B,  0xFF,  0x4A,  0x48,  0x4B, 	/* 35920 */
+	0xFF,  0x4A,  0x48,  0x7A,  0x78,  0x4B,  0xFF,  0x4A,  0x10,  0x4A,  0xFE,  0x4A,  0x92,  0x7C,  0xFE,  0x04, 	/* 35930 */
+	0x92,  0x08,  0xFE,  0x10,  0x66,  0x03,  0x81,  0xA6,  0x01,  0x04,  0x00,  0x88,  0x7B,  0xFE,  0x48,  0x20, 	/* 35940 */
+	0x49,  0xFC,  0x48,  0x20,  0x4F,  0xFF,  0x78,  0x44,  0x4B,  0x8A,  0x48,  0x88,  0x4F,  0xFF,  0x49,  0xCA, 	/* 35950 */
+	0x7A,  0xA4,  0x05,  0xD5,  0x00,  0x4B,  0x01,  0x91,  0xA9,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08, 	/* 35960 */
+	0x08,  0x0F,  0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x09,  0x48,  0x0F,  0x78,  0x02,  0x20,  0x0F,  0xF8,  0x02, 	/* 35970 */
+	0x20,  0x7F,  0xFF,  0x0C,  0x48,  0x77,  0x30,  0x0C,  0x0E,  0xB0,  0x00,  0x00,  0x3F,  0xFC,  0x20,  0x04, 	/* 35980 */
+	0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x3F,  0xC4,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04, 	/* 35990 */
+	0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x3F,  0xFC,  0x00,  0x00,  0xB2,  0x02,  0x20,  0x02,  0x20,  0x02, 	/* 359A0 */
+	0x20,  0x02,  0x20,  0x3F,  0xFE,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x3F,  0xFE,  0x22, 	/* 359B0 */
+	0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x3F,  0xFE,  0x00,  0x00,  0xB3,  0x01,  0x00,  0x01,  0x00, 	/* 359C0 */
+	0x1F,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x1F,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x11,  0x0C,  0x1F,  0xF8, 	/* 359D0 */
+	0x01,  0x10,  0x00,  0xE0,  0x01,  0x82,  0x0E,  0x42,  0x70,  0x32,  0x00,  0x0E,  0xB4,  0x00,  0x00,  0x7F, 	/* 359E0 */
+	0xFF,  0x00,  0x80,  0x1F,  0xF8,  0x10,  0x88,  0x10,  0x88,  0x1F,  0xF8,  0x10,  0x88,  0x10,  0x88,  0x1F, 	/* 359F0 */
+	0xF8,  0x04,  0x80,  0x02,  0x80,  0x01,  0x00,  0x02,  0xC0,  0x0C,  0x38,  0x70,  0x07,  0xB5,  0x01,  0x00, 	/* 35A00 */
+	0x01,  0x10,  0x01,  0x08,  0x1F,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x1F,  0xE4,  0x11,  0x04,  0x11,  0x04, 	/* 35A10 */
+	0x1F,  0xFC,  0x01,  0x10,  0x00,  0xA0,  0x00,  0xC1,  0x07,  0x21,  0x78,  0x19,  0x00,  0x07,  0xB7,  0x00, 	/* 35A20 */
+	0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x02,  0x00,  0x07, 	/* 35A30 */
+	0xFC,  0x08,  0x84,  0x18,  0xC4,  0x69,  0x24,  0x0A,  0x04,  0x0F,  0xF4,  0x00,  0x04,  0x00,  0x18,  0xB8, 	/* 35A40 */
+	0x00,  0x80,  0x1F,  0xFC,  0x00,  0x84,  0x7F,  0xFF,  0x00,  0x84,  0x1F,  0xFC,  0x00,  0x80,  0x1F,  0xFC, 	/* 35A50 */
+	0x00,  0x80,  0x7F,  0xFF,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00, 	/* 35A60 */
+	0xB9,  0x02,  0x40,  0x02,  0x40,  0x7F,  0xFE,  0x02,  0x40,  0x3F,  0xFC,  0x22,  0x44,  0x3F,  0xFC,  0x22, 	/* 35A70 */
+	0x44,  0x3F,  0xFC,  0x00,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x00, 	/* 35A80 */
+	0x00,  0xBC,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00, 	/* 35A90 */
+	0x3F,  0xFE,  0x22,  0x22,  0x3F,  0xFE,  0x00,  0x00,  0x3F,  0xF8,  0x06,  0x20,  0x01,  0xC0,  0x07,  0x38, 	/* 35AA0 */
+	0x78,  0x07,  0xBD,  0x08,  0x10,  0x04,  0x20,  0x3F,  0xFC,  0x21,  0x04,  0x21,  0x04,  0x3F,  0xFC,  0x21, 	/* 35AB0 */
+	0x04,  0x3F,  0xFC,  0x00,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10,  0x0F, 	/* 35AC0 */
+	0xF0,  0x00,  0x00,  0xBE,  0x07,  0xF0,  0x00,  0x10,  0x08,  0x08,  0x1F,  0xFC,  0x30,  0x96,  0x54,  0x95, 	/* 35AD0 */
+	0x12,  0xA4,  0x1F,  0xFC,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08, 	/* 35AE0 */
+	0x0F,  0xF8,  0x00,  0x00,  0xBF,  0x04,  0x10,  0x04,  0x10,  0x3F,  0x7E,  0x04,  0x10,  0x04,  0x10,  0x7F, 	/* 35AF0 */
+	0xFF,  0x0A,  0x28,  0x11,  0x44,  0x20,  0x82,  0x4F,  0xF1,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x08, 	/* 35B00 */
+	0x10,  0x08,  0x10,  0x0F,  0xF0,  0x80,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08, 	/* 35B10 */
+	0x0F,  0xF8,  0x00,  0x00,  0x7F,  0xFF,  0x11,  0x00,  0x1F,  0x7C,  0x11,  0x44,  0x1F,  0x28,  0x11,  0x18, 	/* 35B20 */
+	0x1F,  0x24,  0x61,  0xC2,  0x01,  0x01,  0x83,  0x00,  0x80,  0x00,  0x80,  0x01,  0x40,  0x06,  0x30,  0x18, 	/* 35B30 */
+	0x0C,  0x7F,  0xFF,  0x14,  0x94,  0x12,  0xA4,  0x1F,  0xFC,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F, 	/* 35B40 */
+	0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x88,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08, 	/* 35B50 */
+	0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08, 	/* 35B60 */
+	0x10,  0x08,  0x10,  0x08,  0x20,  0x08,  0x40,  0x38,  0x89,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFF,  0x02, 	/* 35B70 */
+	0x00,  0x02,  0x00,  0x07,  0xF8,  0x0C,  0x08,  0x0C,  0x08,  0x17,  0xF8,  0x24,  0x08,  0x44,  0x08,  0x07, 	/* 35B80 */
+	0xF8,  0x04,  0x08,  0x04,  0x08,  0x04,  0x08,  0x04,  0x18,  0x8B,  0x00,  0x00,  0x1F,  0x3E,  0x11,  0x22, 	/* 35B90 */
+	0x11,  0x22,  0x11,  0x22,  0x1F,  0x3E,  0x11,  0x22,  0x11,  0x22,  0x11,  0x22,  0x1F,  0x3E,  0x11,  0x22, 	/* 35BA0 */
+	0x11,  0x22,  0x11,  0x22,  0x21,  0x42,  0x21,  0x42,  0x43,  0x86,  0x8D,  0x00,  0x00,  0x3E,  0xFE,  0x22, 	/* 35BB0 */
+	0x82,  0x22,  0x82,  0x22,  0x8C,  0x3E,  0x80,  0x22,  0x80,  0x22,  0xFE,  0x22,  0xA2,  0x3E,  0xA4,  0x22, 	/* 35BC0 */
+	0x94,  0x22,  0x98,  0x22,  0x88,  0x22,  0x94,  0x22,  0xA2,  0x46,  0xC1,  0x8F,  0x00,  0x10,  0x3E,  0x10, 	/* 35BD0 */
+	0x22,  0x92,  0x22,  0x92,  0x22,  0x92,  0x3E,  0x92,  0x22,  0xFE,  0x22,  0x10,  0x22,  0x10,  0x3E,  0x92, 	/* 35BE0 */
+	0x22,  0x92,  0x22,  0x92,  0x22,  0x92,  0x22,  0x92,  0x22,  0xFE,  0x46,  0x00,  0x94,  0x21,  0x00,  0x11, 	/* 35BF0 */
+	0x3E,  0x12,  0x22,  0x7F,  0xA2,  0x04,  0x22,  0x04,  0x3E,  0x25,  0x22,  0x25,  0x22,  0x25,  0x22,  0x25, 	/* 35C00 */
+	0x3E,  0x3F,  0x22,  0x25,  0x22,  0x08,  0x42,  0x08,  0x42,  0x10,  0x82,  0x21,  0x06,  0x95,  0x00,  0x84, 	/* 35C10 */
+	0x3E,  0x44,  0x22,  0x48,  0x22,  0x10,  0x22,  0xFE,  0x3E,  0x10,  0x22,  0x10,  0x22,  0x10,  0x23,  0xFF, 	/* 35C20 */
+	0x3E,  0x10,  0x22,  0x28,  0x22,  0x28,  0x22,  0x44,  0x22,  0x44,  0x22,  0x82,  0x47,  0x01,  0x96,  0x00, 	/* 35C30 */
+	0x10,  0x3E,  0x10,  0x22,  0xFC,  0x22,  0x84,  0x22,  0x84,  0x3E,  0xFC,  0x22,  0x84,  0x22,  0x84,  0x22, 	/* 35C40 */
+	0xFE,  0x3E,  0x92,  0x22,  0x94,  0x22,  0x88,  0x22,  0x88,  0x22,  0xB4,  0x22,  0xC2,  0x47,  0x01,  0x97, 	/* 35C50 */
+	0x08,  0x00,  0x08,  0x3E,  0x3F,  0x22,  0x21,  0x22,  0x21,  0x22,  0x3F,  0x3E,  0x21,  0x22,  0x21,  0x22, 	/* 35C60 */
+	0x3F,  0x22,  0x20,  0x3E,  0x24,  0x22,  0x22,  0x22,  0x22,  0x42,  0x2D,  0x42,  0x30,  0x82,  0x61,  0x06, 	/* 35C70 */
+	0x9B,  0x08,  0x00,  0x08,  0x3E,  0x7F,  0xA2,  0x10,  0x3E,  0x10,  0x22,  0x10,  0x3E,  0x10,  0x22,  0x0F, 	/* 35C80 */
+	0x42,  0x00,  0x84,  0x3F,  0xFE,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00, 	/* 35C90 */
+	0x00,  0x9D,  0x08,  0x00,  0x08,  0x3E,  0x7F,  0xA2,  0x08,  0x22,  0x3F,  0x22,  0x21,  0x3E,  0x21,  0x22, 	/* 35CA0 */
+	0x3F,  0x22,  0x21,  0x22,  0x21,  0x3E,  0x3F,  0x22,  0x08,  0x22,  0x7F,  0xA2,  0x08,  0x42,  0x08,  0x42, 	/* 35CB0 */
+	0x08,  0x86,  0x9E,  0x04,  0x10,  0x3F,  0xFE,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x07,  0xF0,  0x04, 	/* 35CC0 */
+	0x10,  0x7F,  0xFF,  0x08,  0x08,  0x17,  0xF4,  0x24,  0x12,  0x47,  0xF1,  0x04,  0x10,  0x07,  0xF0,  0x04, 	/* 35CD0 */
+	0x10,  0x04,  0x30,  0x9F,  0x11,  0x00,  0x11,  0x3E,  0x7F,  0xE2,  0x11,  0x22,  0x11,  0x22,  0x1F,  0x3E, 	/* 35CE0 */
+	0x11,  0x22,  0x11,  0x22,  0x1F,  0x22,  0x11,  0x3E,  0x11,  0x22,  0x7F,  0xE2,  0x12,  0x22,  0x11,  0x42, 	/* 35CF0 */
+	0x21,  0x42,  0x40,  0x86,  0xA6,  0x00,  0x48,  0x3D,  0xFF,  0x24,  0x48,  0x25,  0xFE,  0x25,  0x02,  0x3D, 	/* 35D00 */
+	0x7A,  0x24,  0x00,  0x27,  0xFF,  0x24,  0x40,  0x3C,  0xAA,  0x27,  0x5A,  0x24,  0x94,  0x27,  0x34,  0x24, 	/* 35D10 */
+	0x52,  0x25,  0x91,  0x4C,  0x60,  0xA7,  0x00,  0x88,  0x3C,  0x88,  0x27,  0xFF,  0x25,  0x28,  0x24,  0xCF, 	/* 35D20 */
+	0x3F,  0xF1,  0x24,  0x0F,  0x25,  0xE8,  0x25,  0x2E,  0x3D,  0xE8,  0x25,  0x2E,  0x25,  0xE8,  0x25,  0x2E, 	/* 35D30 */
+	0x25,  0x29,  0x25,  0x29,  0x4D,  0x67,  0xA8,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F, 	/* 35D40 */
+	0xFF,  0x01,  0xC0,  0x01,  0xC0,  0x02,  0xA0,  0x02,  0xA0,  0x04,  0x90,  0x08,  0x88,  0x10,  0x84,  0x20, 	/* 35D50 */
+	0x82,  0x40,  0x81,  0x00,  0x80,  0x00,  0x80,  0xAA,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC, 	/* 35D60 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0xC0,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C, 	/* 35D70 */
+	0x60,  0x83,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0xAB,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F, 	/* 35D80 */
+	0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x01,  0xC0,  0x02,  0xA0,  0x04, 	/* 35D90 */
+	0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0x00,  0x80,  0xAC,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80, 	/* 35DA0 */
+	0x00,  0x80,  0x7F,  0xFF,  0x01,  0xC0,  0x02,  0xA0,  0x02,  0xA0,  0x04,  0x90,  0x08,  0x88,  0x10,  0x84, 	/* 35DB0 */
+	0x27,  0xF2,  0x40,  0x81,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0xAD,  0x08,  0x40,  0x08,  0x40,  0x08, 	/* 35DC0 */
+	0x40,  0x7F,  0x40,  0x08,  0x40,  0x08,  0x40,  0x1C,  0x40,  0x1A,  0x40,  0x19,  0x40,  0x28,  0x40,  0x28, 	/* 35DD0 */
+	0x40,  0x48,  0x42,  0x08,  0x42,  0x08,  0x22,  0x08,  0x1E,  0x08,  0x00,  0xAE,  0x00,  0x88,  0x00,  0x84, 	/* 35DE0 */
+	0x00,  0x84,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x04,  0x90,  0x04,  0x90,  0x04,  0x90,  0x04,  0x90, 	/* 35DF0 */
+	0x04,  0x90,  0x08,  0x90,  0x08,  0x91,  0x10,  0x91,  0x20,  0x8F,  0x00,  0x80,  0xB1,  0x00,  0x80,  0x04, 	/* 35E00 */
+	0x80,  0x04,  0x80,  0x0F,  0xFC,  0x08,  0x80,  0x10,  0x80,  0x20,  0x80,  0x7F,  0xFF,  0x01,  0xC0,  0x02, 	/* 35E10 */
+	0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0xB4,  0x08,  0x20, 	/* 35E20 */
+	0x08,  0x20,  0x08,  0x20,  0x7F,  0x20,  0x08,  0x20,  0x08,  0x30,  0x1C,  0x28,  0x1A,  0x24,  0x19,  0x22, 	/* 35E30 */
+	0x29,  0x22,  0x28,  0x20,  0x48,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0xB6,  0x00, 	/* 35E40 */
+	0x00,  0x3F,  0xF0,  0x01,  0x10,  0x01,  0x10,  0x02,  0x3E,  0x04,  0x02,  0x08,  0x02,  0x30,  0x8C,  0x00, 	/* 35E50 */
+	0x80,  0x7F,  0xFF,  0x01,  0xC0,  0x02,  0xA0,  0x0C,  0x98,  0x70,  0x87,  0x00,  0x80,  0x00,  0x80,  0xB7, 	/* 35E60 */
+	0x08,  0x00,  0x09,  0xFE,  0x08,  0x22,  0x7F,  0x22,  0x08,  0x22,  0x08,  0x22,  0x1C,  0x22,  0x1A,  0x22, 	/* 35E70 */
+	0x1A,  0x22,  0x28,  0x42,  0x28,  0x42,  0x48,  0x42,  0x08,  0x82,  0x08,  0x82,  0x09,  0x02,  0x0A,  0x0C, 	/* 35E80 */
+	0xB8,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x7F,  0x20,  0x09,  0xFE,  0x08,  0x22,  0x1C,  0x22,  0x1A, 	/* 35E90 */
+	0x22,  0x1A,  0x22,  0x28,  0x42,  0x28,  0x42,  0x48,  0x42,  0x08,  0x82,  0x08,  0x82,  0x09,  0x02,  0x0A, 	/* 35EA0 */
+	0x0C,  0xBA,  0x08,  0x00,  0x08,  0x78,  0x08,  0x48,  0x7F,  0x48,  0x08,  0x48,  0x08,  0x48,  0x1C,  0x48, 	/* 35EB0 */
+	0x1A,  0x48,  0x1A,  0x48,  0x28,  0x48,  0x28,  0x88,  0x48,  0x88,  0x09,  0x08,  0x09,  0x09,  0x0A,  0x09, 	/* 35EC0 */
+	0x0C,  0x07,  0xBD,  0x08,  0x00,  0x0B,  0xFF,  0x08,  0x20,  0x7E,  0x20,  0x08,  0x20,  0x08,  0x40,  0x1C, 	/* 35ED0 */
+	0x7C,  0x1A,  0x84,  0x1A,  0x84,  0x28,  0x04,  0x28,  0x04,  0x48,  0x04,  0x08,  0x04,  0x08,  0x04,  0x08, 	/* 35EE0 */
+	0x08,  0x08,  0x30,  0xBF,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC, 	/* 35EF0 */
+	0x10,  0x84,  0x10,  0x84,  0x11,  0xC4,  0x11,  0xC4,  0x12,  0xB8,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83, 	/* 35F00 */
+	0x00,  0x80,  0x00,  0x80,  0x81,  0x08,  0x00,  0x08,  0x70,  0x08,  0x10,  0x7F,  0x10,  0x08,  0x10,  0x08, 	/* 35F10 */
+	0x10,  0x1C,  0x10,  0x1A,  0x10,  0x19,  0x18,  0x28,  0x28,  0x28,  0x28,  0x48,  0x48,  0x08,  0x44,  0x08, 	/* 35F20 */
+	0x84,  0x09,  0x02,  0x0A,  0x01,  0x86,  0x08,  0x00,  0x08,  0xFE,  0x08,  0x10,  0x7E,  0x10,  0x08,  0x10, 	/* 35F30 */
+	0x08,  0x10,  0x18,  0x10,  0x1D,  0xFF,  0x1A,  0x10,  0x2A,  0x10,  0x28,  0x10,  0x48,  0x10,  0x08,  0x10, 	/* 35F40 */
+	0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x89,  0x08,  0x08,  0x08,  0x08,  0x08,  0x10,  0x7F,  0x90,  0x08, 	/* 35F50 */
+	0x24,  0x08,  0x44,  0x1C,  0x08,  0x1A,  0x08,  0x19,  0x12,  0x29,  0x22,  0x28,  0x44,  0x48,  0x04,  0x08, 	/* 35F60 */
+	0x08,  0x08,  0x10,  0x08,  0x20,  0x08,  0xC0,  0x8E,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0xC0, 	/* 35F70 */
+	0x02,  0xA0,  0x0C,  0x98,  0x70,  0x87,  0x00,  0x80,  0x0F,  0xF0,  0x00,  0x20,  0x00,  0xC0,  0x7F,  0xFF, 	/* 35F80 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x01,  0x80,  0x8F,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F, 	/* 35F90 */
+	0xFF,  0x01,  0xC0,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x0F,  0xF8,  0x08,  0x08,  0x08, 	/* 35FA0 */
+	0x08,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x90,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08, 	/* 35FB0 */
+	0x7F,  0xFF,  0x08,  0x08,  0x08,  0x18,  0x1C,  0x18,  0x1A,  0x28,  0x19,  0x28,  0x29,  0x48,  0x28,  0x48, 	/* 35FC0 */
+	0x48,  0x88,  0x09,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x18,  0x91,  0x08,  0x04,  0x08,  0x04,  0x08, 	/* 35FD0 */
+	0x04,  0x7F,  0xFF,  0x08,  0x04,  0x08,  0x04,  0x1C,  0x84,  0x1A,  0x44,  0x19,  0x24,  0x29,  0x24,  0x28, 	/* 35FE0 */
+	0x04,  0x48,  0x04,  0x08,  0x04,  0x08,  0x04,  0x08,  0x04,  0x08,  0x0C,  0x93,  0x08,  0x40,  0x08,  0x40, 	/* 35FF0 */
+	0x08,  0x40,  0x7F,  0x7E,  0x08,  0x82,  0x08,  0x82,  0x19,  0x02,  0x1C,  0x42,  0x1A,  0x22,  0x2A,  0x22, 	/* 36000 */
+	0x2A,  0x02,  0x48,  0x02,  0x08,  0x02,  0x08,  0x02,  0x08,  0x04,  0x08,  0x18,  0x96,  0x08,  0x10,  0x08, 	/* 36010 */
+	0x10,  0x08,  0x10,  0x7F,  0xFF,  0x08,  0x10,  0x08,  0x90,  0x18,  0x90,  0x1C,  0x50,  0x1A,  0x50,  0x2A, 	/* 36020 */
+	0x20,  0x28,  0x20,  0x48,  0x30,  0x08,  0x50,  0x08,  0x88,  0x09,  0x04,  0x0A,  0x03,  0x99,  0x08,  0x24, 	/* 36030 */
+	0x08,  0x22,  0x08,  0x22,  0x7F,  0x20,  0x09,  0xFF,  0x08,  0x20,  0x1C,  0x20,  0x1A,  0x20,  0x1A,  0x10, 	/* 36040 */
+	0x28,  0x10,  0x28,  0x10,  0x48,  0x08,  0x08,  0x09,  0x08,  0x05,  0x08,  0x03,  0x08,  0x01,  0x9C,  0x08, 	/* 36050 */
+	0x10,  0x08,  0x10,  0x08,  0x10,  0x7F,  0x10,  0x08,  0x10,  0x08,  0xFE,  0x1C,  0x10,  0x1A,  0x10,  0x19, 	/* 36060 */
+	0x10,  0x29,  0x10,  0x28,  0x10,  0x48,  0x10,  0x08,  0x10,  0x09,  0xFF,  0x08,  0x00,  0x08,  0x00,  0x9E, 	/* 36070 */
+	0x08,  0x00,  0x08,  0xFE,  0x08,  0x02,  0x7F,  0x02,  0x08,  0x02,  0x08,  0x02,  0x1C,  0xFE,  0x1A,  0x80, 	/* 36080 */
+	0x1A,  0x80,  0x28,  0x80,  0x28,  0x80,  0x48,  0x81,  0x08,  0x81,  0x08,  0x41,  0x08,  0x3F,  0x08,  0x00, 	/* 36090 */
+	0x9F,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x10,  0x84,  0x10, 	/* 360A0 */
+	0x84,  0x10,  0x84,  0x1F,  0xFC,  0x01,  0xC0,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00, 	/* 360B0 */
+	0x80,  0xA0,  0x08,  0x00,  0x08,  0x00,  0x09,  0xFE,  0x7E,  0x10,  0x08,  0x10,  0x08,  0x10,  0x1C,  0x10, 	/* 360C0 */
+	0x1A,  0x10,  0x1A,  0x10,  0x28,  0x10,  0x28,  0x10,  0x48,  0x10,  0x08,  0x10,  0x0B,  0xFF,  0x08,  0x00, 	/* 360D0 */
+	0x08,  0x00,  0xA1,  0x00,  0x80,  0x00,  0x80,  0x01,  0xF8,  0x02,  0x10,  0x0D,  0x20,  0x30,  0xC0,  0x03, 	/* 360E0 */
+	0x20,  0x0C,  0x98,  0x70,  0x87,  0x1F,  0xFC,  0x01,  0xC0,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60, 	/* 360F0 */
+	0x83,  0x00,  0x80,  0xA2,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0xC0,  0x02,  0xA0,  0x04,  0x90, 	/* 36100 */
+	0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0x00,  0x00,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80, 	/* 36110 */
+	0x7F,  0xFF,  0x00,  0x00,  0xA3,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x7F,  0x10,  0x08,  0x10,  0x08, 	/* 36120 */
+	0x92,  0x1C,  0x92,  0x1A,  0x92,  0x1A,  0x92,  0x28,  0x92,  0x28,  0x92,  0x48,  0x92,  0x08,  0x92,  0x08, 	/* 36130 */
+	0x92,  0x08,  0xFE,  0x08,  0x00,  0xA4,  0x08,  0x00,  0x0B,  0xFF,  0x08,  0x40,  0x7F,  0x40,  0x08,  0x40, 	/* 36140 */
+	0x08,  0x7C,  0x1C,  0x44,  0x1A,  0x44,  0x1A,  0x44,  0x28,  0x44,  0x28,  0x44,  0x48,  0x84,  0x08,  0x84, 	/* 36150 */
+	0x08,  0x84,  0x09,  0x04,  0x0A,  0x18,  0xA5,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x88,  0x08, 	/* 36160 */
+	0x88,  0x04,  0x90,  0x04,  0xA0,  0x7F,  0xFF,  0x00,  0x80,  0x01,  0xC0,  0x02,  0xA0,  0x04,  0x90,  0x18, 	/* 36170 */
+	0x8C,  0x60,  0x83,  0x00,  0x80,  0x00,  0x80,  0xAA,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x7E,  0x28, 	/* 36180 */
+	0x08,  0xA4,  0x08,  0xA2,  0x18,  0xA2,  0x1D,  0x21,  0x1A,  0x25,  0x2A,  0x24,  0x28,  0x68,  0x48,  0x08, 	/* 36190 */
+	0x08,  0x10,  0x08,  0x20,  0x08,  0xC0,  0x0B,  0x00,  0xAD,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x7F, 	/* 361A0 */
+	0xFF,  0x08,  0x00,  0x08,  0x00,  0x1C,  0x78,  0x1A,  0x48,  0x19,  0x48,  0x29,  0x48,  0x28,  0x48,  0x48, 	/* 361B0 */
+	0x48,  0x08,  0x89,  0x08,  0x89,  0x09,  0x07,  0x0A,  0x00,  0xAF,  0x08,  0x00,  0x09,  0xFF,  0x08,  0x10, 	/* 361C0 */
+	0x7F,  0x10,  0x08,  0x10,  0x08,  0x20,  0x1C,  0x28,  0x1A,  0x64,  0x1A,  0x64,  0x28,  0xA2,  0x29,  0x22, 	/* 361D0 */
+	0x48,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0xB0,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 361E0 */
+	0x80,  0x7F,  0xFF,  0x01,  0xC0,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0x00, 	/* 361F0 */
+	0x80,  0x00,  0x00,  0x14,  0x44,  0x12,  0x22,  0x21,  0x11,  0x41,  0x11,  0xB1,  0x00,  0x80,  0x00,  0x80, 	/* 36200 */
+	0x7F,  0xFF,  0x00,  0x80,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x10,  0x84,  0x1F,  0xFC, 	/* 36210 */
+	0x01,  0xC0,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0xB2,  0x00,  0x00,  0x0F, 	/* 36220 */
+	0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x80,  0x7F, 	/* 36230 */
+	0xFF,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0x00,  0x80,  0xB3,  0x00,  0x80, 	/* 36240 */
+	0x00,  0x80,  0x7F,  0xFF,  0x01,  0xC0,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x0F,  0xF8, 	/* 36250 */
+	0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0xB5,  0x08, 	/* 36260 */
+	0x40,  0x08,  0x40,  0x08,  0x40,  0x7E,  0x7E,  0x08,  0x90,  0x08,  0x90,  0x1D,  0x10,  0x1A,  0x10,  0x1B, 	/* 36270 */
+	0xFF,  0x28,  0x10,  0x28,  0x10,  0x48,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0xB7, 	/* 36280 */
+	0x08,  0x00,  0x09,  0xFC,  0x09,  0x24,  0x7F,  0x24,  0x09,  0x24,  0x09,  0x24,  0x1D,  0x24,  0x1B,  0xFC, 	/* 36290 */
+	0x1B,  0x00,  0x29,  0x00,  0x29,  0x00,  0x49,  0x02,  0x09,  0x02,  0x08,  0x82,  0x08,  0x7E,  0x08,  0x00, 	/* 362A0 */
+	0xBC,  0x08,  0x00,  0x09,  0xFE,  0x08,  0x04,  0x7E,  0xC8,  0x08,  0x30,  0x08,  0x10,  0x1B,  0xFF,  0x1C, 	/* 362B0 */
+	0x12,  0x1A,  0x14,  0x2A,  0x10,  0x28,  0x10,  0x48,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08, 	/* 362C0 */
+	0x30,  0xBE,  0x08,  0x38,  0x08,  0x08,  0x08,  0x48,  0x7F,  0x48,  0x08,  0x44,  0x08,  0x54,  0x1C,  0x92, 	/* 362D0 */
+	0x1A,  0x92,  0x19,  0x11,  0x2A,  0x20,  0x28,  0x28,  0x48,  0x24,  0x08,  0x44,  0x08,  0x7A,  0x0B,  0xC2, 	/* 362E0 */
+	0x08,  0x02,  0xBF,  0x08,  0x00,  0x08,  0xFF,  0x08,  0x80,  0x7F,  0x80,  0x08,  0x80,  0x08,  0xFE,  0x0C, 	/* 362F0 */
+	0xA2,  0x1A,  0xA2,  0x1A,  0xA4,  0x18,  0x94,  0x28,  0x98,  0x28,  0x88,  0x48,  0x94,  0x09,  0x24,  0x09, 	/* 36300 */
+	0x42,  0x0A,  0x81,  0x85,  0x08,  0x00,  0x09,  0xFF,  0x08,  0x44,  0x7F,  0x44,  0x08,  0x44,  0x08,  0x44, 	/* 36310 */
+	0x19,  0xFF,  0x1C,  0x44,  0x1A,  0x44,  0x2A,  0x44,  0x28,  0x44,  0x48,  0x44,  0x08,  0x84,  0x08,  0x84, 	/* 36320 */
+	0x09,  0x04,  0x0A,  0x04,  0x87,  0x09,  0x10,  0x09,  0x10,  0x09,  0x10,  0x7F,  0x10,  0x09,  0x12,  0x09, 	/* 36330 */
+	0x12,  0x1D,  0xF4,  0x1B,  0x18,  0x1B,  0x10,  0x29,  0x10,  0x29,  0x10,  0x49,  0x10,  0x09,  0x11,  0x09, 	/* 36340 */
+	0x51,  0x09,  0x8F,  0x0E,  0x00,  0x89,  0x08,  0x00,  0x09,  0xFE,  0x08,  0x20,  0x7F,  0x20,  0x08,  0x20, 	/* 36350 */
+	0x08,  0x20,  0x1C,  0x20,  0x1A,  0xFC,  0x1A,  0x20,  0x28,  0x20,  0x28,  0x20,  0x48,  0x20,  0x08,  0x20, 	/* 36360 */
+	0x08,  0x20,  0x0B,  0xFF,  0x08,  0x00,  0x8B,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x7F,  0xFF,  0x08, 	/* 36370 */
+	0x40,  0x08,  0x40,  0x1C,  0x40,  0x1A,  0x7C,  0x19,  0x44,  0x28,  0x44,  0x28,  0x44,  0x48,  0x44,  0x08, 	/* 36380 */
+	0x84,  0x08,  0x84,  0x09,  0x04,  0x0A,  0x18,  0x8C,  0x08,  0x78,  0x08,  0x08,  0x08,  0x48,  0x7E,  0x84, 	/* 36390 */
+	0x08,  0x84,  0x09,  0x02,  0x1A,  0x01,  0x1C,  0xFC,  0x1A,  0x24,  0x2A,  0x24,  0x28,  0x24,  0x48,  0x24, 	/* 363A0 */
+	0x08,  0x44,  0x08,  0x44,  0x08,  0x84,  0x09,  0x18,  0x90,  0x08,  0x04,  0x08,  0x18,  0x08,  0xE0,  0x7F, 	/* 363B0 */
+	0x80,  0x08,  0x80,  0x08,  0xFF,  0x1C,  0x88,  0x1A,  0x88,  0x1A,  0x88,  0x28,  0x88,  0x28,  0x88,  0x48, 	/* 363C0 */
+	0x88,  0x09,  0x08,  0x09,  0x08,  0x0A,  0x08,  0x08,  0x08,  0x95,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20, 	/* 363D0 */
+	0x7F,  0xFE,  0x09,  0x22,  0x09,  0x22,  0x1C,  0x20,  0x1A,  0x30,  0x1A,  0x30,  0x28,  0x50,  0x28,  0x50, 	/* 363E0 */
+	0x48,  0x50,  0x08,  0x90,  0x08,  0x91,  0x09,  0x11,  0x0A,  0x0F,  0x97,  0x08,  0x10,  0x08,  0x10,  0x08, 	/* 363F0 */
+	0x10,  0x7F,  0xFF,  0x08,  0x10,  0x08,  0x10,  0x1C,  0x38,  0x1A,  0x38,  0x19,  0x54,  0x28,  0x54,  0x28, 	/* 36400 */
+	0x92,  0x49,  0x11,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x9A,  0x08,  0x40,  0x08,  0x40, 	/* 36410 */
+	0x08,  0x40,  0x08,  0x40,  0x7F,  0xFF,  0x08,  0x84,  0x08,  0xC4,  0x1D,  0x44,  0x1A,  0x28,  0x19,  0x28, 	/* 36420 */
+	0x29,  0x10,  0x28,  0x10,  0x48,  0x28,  0x08,  0x44,  0x08,  0x82,  0x0B,  0x01,  0x9C,  0x00,  0x00,  0x1F, 	/* 36430 */
+	0xF8,  0x11,  0x08,  0x11,  0x08,  0x1F,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x1F,  0xF8,  0x01,  0x00,  0x7F, 	/* 36440 */
+	0xFE,  0x03,  0x80,  0x05,  0x40,  0x09,  0x20,  0x11,  0x18,  0x61,  0x06,  0x01,  0x00,  0x9D,  0x08,  0x10, 	/* 36450 */
+	0x08,  0x10,  0x08,  0x10,  0x7F,  0xFF,  0x08,  0x10,  0x08,  0x10,  0x1D,  0xFC,  0x1C,  0x44,  0x1A,  0x44, 	/* 36460 */
+	0x2A,  0x28,  0x2A,  0x28,  0x48,  0x10,  0x08,  0x28,  0x08,  0x44,  0x08,  0x82,  0x0B,  0x01,  0xA0,  0x08, 	/* 36470 */
+	0x20,  0x08,  0x20,  0x09,  0xF8,  0x7E,  0x28,  0x08,  0x28,  0x0C,  0x49,  0x1A,  0x49,  0x1A,  0x87,  0x19, 	/* 36480 */
+	0x20,  0x28,  0x20,  0x2B,  0xFE,  0x48,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0xA1, 	/* 36490 */
+	0x08,  0x24,  0x08,  0x44,  0x09,  0xC4,  0x7E,  0x44,  0x08,  0x44,  0x08,  0x44,  0x19,  0xFF,  0x1C,  0x44, 	/* 364A0 */
+	0x1A,  0x44,  0x2A,  0x44,  0x28,  0x44,  0x48,  0x44,  0x08,  0x84,  0x08,  0x84,  0x09,  0x04,  0x0A,  0x04, 	/* 364B0 */
+	0xA2,  0x08,  0x00,  0x09,  0xFE,  0x09,  0x00,  0x7F,  0x04,  0x09,  0x04,  0x09,  0x44,  0x1D,  0x28,  0x1B, 	/* 364C0 */
+	0x18,  0x1B,  0x08,  0x29,  0x14,  0x29,  0x24,  0x49,  0x44,  0x09,  0x80,  0x09,  0x00,  0x09,  0xFF,  0x08, 	/* 364D0 */
+	0x00,  0xA6,  0x08,  0x00,  0x09,  0xFF,  0x08,  0x00,  0x7F,  0x00,  0x08,  0xFE,  0x08,  0x82,  0x1C,  0x82, 	/* 364E0 */
+	0x1A,  0x82,  0x1A,  0xFE,  0x28,  0x80,  0x28,  0x80,  0x48,  0x80,  0x08,  0x80,  0x09,  0x00,  0x09,  0x00, 	/* 364F0 */
+	0x0A,  0x00,  0xA9,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0xC0,  0x06,  0xB0,  0x18,  0x8C,  0x60, 	/* 36500 */
+	0x83,  0x02,  0xE0,  0x02,  0x20,  0x04,  0x90,  0x18,  0x8C,  0x61,  0x03,  0x01,  0x40,  0x02,  0x30,  0x04, 	/* 36510 */
+	0xE8,  0x3F,  0x04,  0xAF,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x7F,  0x20,  0x09,  0xFE,  0x08,  0x20, 	/* 36520 */
+	0x1C,  0x20,  0x1A,  0x20,  0x1A,  0xFC,  0x28,  0x84,  0x28,  0x84,  0x48,  0x84,  0x08,  0x84,  0x08,  0x84, 	/* 36530 */
+	0x08,  0xFC,  0x08,  0x00,  0xB3,  0x08,  0x00,  0x08,  0x7E,  0x08,  0x42,  0x7F,  0x42,  0x08,  0x42,  0x08, 	/* 36540 */
+	0x42,  0x1C,  0x42,  0x1A,  0x42,  0x19,  0x7E,  0x28,  0x00,  0x28,  0x00,  0x48,  0x44,  0x08,  0x42,  0x08, 	/* 36550 */
+	0x82,  0x09,  0x01,  0x0A,  0x01,  0xB4,  0x08,  0x00,  0x08,  0xFC,  0x08,  0x84,  0x7F,  0x84,  0x08,  0x84, 	/* 36560 */
+	0x08,  0xFC,  0x1C,  0x00,  0x1A,  0x00,  0x19,  0xFE,  0x28,  0x22,  0x28,  0x22,  0x48,  0x22,  0x08,  0x42, 	/* 36570 */
+	0x08,  0x42,  0x08,  0x82,  0x09,  0x0C,  0xB6,  0x08,  0x00,  0x08,  0x7C,  0x7F,  0x44,  0x09,  0x44,  0x09, 	/* 36580 */
+	0x44,  0x11,  0x44,  0x11,  0x7C,  0x26,  0x00,  0x41,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x03,  0x40,  0x05, 	/* 36590 */
+	0x20,  0x19,  0x18,  0x61,  0x06,  0x01,  0x00,  0xB7,  0x11,  0x00,  0x11,  0x00,  0x11,  0x1E,  0x7D,  0x12, 	/* 365A0 */
+	0x17,  0xD2,  0x11,  0x52,  0x39,  0x52,  0x39,  0x52,  0x35,  0x52,  0x51,  0x52,  0x51,  0x52,  0x12,  0x52, 	/* 365B0 */
+	0x12,  0x52,  0x14,  0x5E,  0x18,  0x40,  0x11,  0x80,  0xB8,  0x08,  0x80,  0x08,  0x80,  0x08,  0x80,  0x7E, 	/* 365C0 */
+	0xFE,  0x09,  0x02,  0x09,  0x02,  0x1A,  0xF2,  0x1C,  0x92,  0x1A,  0x92,  0x2A,  0x92,  0x28,  0x92,  0x48, 	/* 365D0 */
+	0xF2,  0x08,  0x02,  0x08,  0x02,  0x08,  0x04,  0x08,  0x18,  0xB9,  0x08,  0x40,  0x08,  0x40,  0x08,  0x7E, 	/* 365E0 */
+	0x7E,  0x42,  0x08,  0x82,  0x08,  0xF2,  0x19,  0x92,  0x1C,  0x92,  0x1A,  0x92,  0x2A,  0xF2,  0x28,  0x84, 	/* 365F0 */
+	0x48,  0x98,  0x08,  0x80,  0x08,  0x81,  0x08,  0x81,  0x08,  0x7F,  0x81,  0x08,  0x10,  0x08,  0x10,  0x08, 	/* 36600 */
+	0x10,  0x7F,  0xFF,  0x09,  0x01,  0x09,  0x41,  0x1C,  0x40,  0x1A,  0x44,  0x1A,  0x58,  0x28,  0x60,  0x28, 	/* 36610 */
+	0x40,  0x48,  0x40,  0x08,  0x40,  0x08,  0x42,  0x08,  0x22,  0x08,  0x1E,  0x84,  0x08,  0x00,  0x0B,  0xFF, 	/* 36620 */
+	0x08,  0x20,  0x7E,  0x20,  0x08,  0x20,  0x09,  0xFE,  0x1D,  0x22,  0x1B,  0x22,  0x19,  0x32,  0x29,  0x52, 	/* 36630 */
+	0x29,  0x4A,  0x49,  0x86,  0x09,  0x02,  0x09,  0x02,  0x09,  0x02,  0x09,  0x06,  0x86,  0x08,  0x20,  0x08, 	/* 36640 */
+	0x20,  0x08,  0x20,  0x7F,  0xFE,  0x08,  0x00,  0x08,  0x84,  0x1C,  0x84,  0x1A,  0x44,  0x1A,  0x44,  0x28, 	/* 36650 */
+	0x48,  0x28,  0x48,  0x48,  0x48,  0x08,  0x10,  0x08,  0x10,  0x0B,  0xFF,  0x08,  0x00,  0x8A,  0x08,  0x40, 	/* 36660 */
+	0x08,  0x40,  0x08,  0x7C,  0x7E,  0x44,  0x08,  0xC8,  0x09,  0x28,  0x1C,  0x10,  0x1A,  0x28,  0x18,  0xC4, 	/* 36670 */
+	0x2B,  0x03,  0x28,  0x60,  0x48,  0x10,  0x08,  0x00,  0x08,  0xE0,  0x08,  0x18,  0x08,  0x04,  0x8E,  0x08, 	/* 36680 */
+	0x44,  0x08,  0x44,  0x08,  0x44,  0x7E,  0x84,  0x08,  0xFF,  0x09,  0x84,  0x1D,  0x84,  0x1A,  0xA4,  0x18, 	/* 36690 */
+	0x94,  0x28,  0x94,  0x28,  0x84,  0x48,  0x84,  0x08,  0x84,  0x08,  0x84,  0x08,  0x84,  0x08,  0x8C,  0x8F, 	/* 366A0 */
+	0x08,  0x10,  0x08,  0x10,  0x08,  0x20,  0x7F,  0xFE,  0x08,  0x82,  0x08,  0x82,  0x1C,  0x82,  0x1A,  0x82, 	/* 366B0 */
+	0x1A,  0xFE,  0x28,  0x82,  0x28,  0x82,  0x48,  0x82,  0x08,  0x82,  0x08,  0x82,  0x08,  0xFE,  0x08,  0x00, 	/* 366C0 */
+	0x90,  0x04,  0x10,  0x04,  0x10,  0x3F,  0xFF,  0x04,  0x10,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x04, 	/* 366D0 */
+	0x10,  0x07,  0xF0,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0xA0,  0x02,  0x90,  0x0C,  0x8C,  0x70,  0x83,  0x00, 	/* 366E0 */
+	0x80,  0x91,  0x08,  0x44,  0x08,  0x44,  0x08,  0x44,  0x7F,  0x44,  0x09,  0xFF,  0x08,  0x44,  0x1C,  0x44, 	/* 366F0 */
+	0x1A,  0x44,  0x19,  0x44,  0x29,  0x7C,  0x28,  0x44,  0x48,  0x44,  0x08,  0x44,  0x08,  0x44,  0x08,  0x7C, 	/* 36700 */
+	0x08,  0x00,  0x93,  0x00,  0x40,  0x18,  0x40,  0x05,  0xF8,  0x60,  0x48,  0x10,  0x48,  0x00,  0x48,  0x04, 	/* 36710 */
+	0x8A,  0x19,  0x0A,  0x62,  0x06,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60, 	/* 36720 */
+	0x83,  0x00,  0x80,  0x94,  0x00,  0x00,  0x1F,  0xF8,  0x06,  0x20,  0x01,  0x40,  0x3F,  0xFE,  0x01,  0x44, 	/* 36730 */
+	0x02,  0x48,  0x0C,  0x40,  0x30,  0xC0,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C, 	/* 36740 */
+	0x60,  0x83,  0x00,  0x80,  0x98,  0x08,  0x00,  0x09,  0xFE,  0x08,  0x20,  0x7F,  0x20,  0x08,  0x20,  0x08, 	/* 36750 */
+	0x40,  0x1C,  0x40,  0x1A,  0xFC,  0x18,  0x84,  0x29,  0x84,  0x2A,  0x84,  0x48,  0x84,  0x08,  0x84,  0x08, 	/* 36760 */
+	0x84,  0x08,  0xFC,  0x08,  0x00,  0x9A,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x7F,  0x10,  0x08,  0xFE, 	/* 36770 */
+	0x08,  0x92,  0x1C,  0x92,  0x1A,  0x92,  0x1A,  0x92,  0x29,  0xFE,  0x29,  0x92,  0x48,  0x92,  0x08,  0x92, 	/* 36780 */
+	0x08,  0x92,  0x08,  0xFE,  0x08,  0x00,  0x9D,  0x08,  0x02,  0x08,  0x0C,  0x08,  0xF0,  0x7F,  0x80,  0x08, 	/* 36790 */
+	0x80,  0x08,  0xFF,  0x1C,  0x88,  0x1A,  0x88,  0x1A,  0x88,  0x28,  0xB8,  0x28,  0x8C,  0x48,  0x8A,  0x09, 	/* 367A0 */
+	0x09,  0x09,  0x08,  0x0A,  0x08,  0x08,  0x08,  0x9E,  0x08,  0x40,  0x08,  0x40,  0x08,  0x40,  0x7F,  0x7F, 	/* 367B0 */
+	0x08,  0x90,  0x08,  0x90,  0x1D,  0x10,  0x1A,  0x1E,  0x1A,  0x10,  0x28,  0x10,  0x28,  0x10,  0x48,  0x1E, 	/* 367C0 */
+	0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0xA2,  0x08,  0x04,  0x08,  0x18,  0x08,  0xF0,  0x7F, 	/* 367D0 */
+	0x90,  0x08,  0x90,  0x08,  0x90,  0x1C,  0xFF,  0x1A,  0x88,  0x1A,  0x88,  0x28,  0x88,  0x28,  0x88,  0x48, 	/* 367E0 */
+	0xE4,  0x0B,  0x85,  0x08,  0x05,  0x0B,  0xF3,  0x08,  0x01,  0xA4,  0x08,  0x00,  0x08,  0xFC,  0x08,  0x84, 	/* 367F0 */
+	0x7F,  0x84,  0x08,  0x84,  0x08,  0xFC,  0x1C,  0x84,  0x1A,  0x84,  0x1A,  0x84,  0x28,  0xFC,  0x28,  0x84, 	/* 36800 */
+	0x48,  0x84,  0x08,  0x84,  0x08,  0x84,  0x0B,  0xFF,  0x08,  0x00,  0xA7,  0x08,  0x04,  0x08,  0x18,  0x08, 	/* 36810 */
+	0xE4,  0x7E,  0x84,  0x08,  0xA4,  0x08,  0xA4,  0x1C,  0xA4,  0x1A,  0xA4,  0x1A,  0xA4,  0x28,  0xA4,  0x28, 	/* 36820 */
+	0xA4,  0x48,  0xB4,  0x08,  0xAC,  0x09,  0x3A,  0x09,  0xEA,  0x0A,  0x05,  0xA9,  0x08,  0x00,  0x09,  0xFF, 	/* 36830 */
+	0x09,  0x10,  0x7F,  0x10,  0x09,  0x1C,  0x09,  0x24,  0x1D,  0x24,  0x1B,  0x48,  0x19,  0x88,  0x29,  0x14, 	/* 36840 */
+	0x29,  0x14,  0x49,  0x22,  0x09,  0x42,  0x09,  0x80,  0x09,  0xFF,  0x08,  0x00,  0xAC,  0x00,  0x80,  0x00, 	/* 36850 */
+	0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x14,  0x94,  0x12,  0xA4,  0x12,  0x84,  0x1F, 	/* 36860 */
+	0xFC,  0x01,  0xC0,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0xAE,  0x08,  0x10, 	/* 36870 */
+	0x08,  0x10,  0x08,  0x92,  0x7F,  0x92,  0x08,  0x92,  0x08,  0x92,  0x1C,  0xFE,  0x1A,  0x10,  0x1A,  0x10, 	/* 36880 */
+	0x28,  0x92,  0x28,  0x92,  0x48,  0x92,  0x08,  0x92,  0x08,  0x92,  0x08,  0xFE,  0x08,  0x00,  0xAF,  0x08, 	/* 36890 */
+	0x00,  0x09,  0xFF,  0x08,  0x04,  0x7F,  0x04,  0x08,  0xF4,  0x08,  0x94,  0x1C,  0x94,  0x1A,  0x94,  0x1A, 	/* 368A0 */
+	0x94,  0x28,  0xF4,  0x28,  0x04,  0x48,  0x04,  0x08,  0x04,  0x08,  0x04,  0x08,  0x04,  0x08,  0x0C,  0xB1, 	/* 368B0 */
+	0x08,  0x40,  0x08,  0x20,  0x08,  0x20,  0x7E,  0x00,  0x09,  0xFE,  0x08,  0x20,  0x1C,  0x20,  0x1A,  0x20, 	/* 368C0 */
+	0x1A,  0x20,  0x29,  0xFC,  0x28,  0x20,  0x48,  0x20,  0x08,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x08,  0x00, 	/* 368D0 */
+	0xB3,  0x08,  0x20,  0x08,  0x40,  0x09,  0x9E,  0x7D,  0x52,  0x09,  0x52,  0x0D,  0x52,  0x1B,  0x52,  0x1B, 	/* 368E0 */
+	0x52,  0x29,  0x52,  0x29,  0x52,  0x49,  0x52,  0x0B,  0xD2,  0x0C,  0x5C,  0x08,  0x90,  0x08,  0x90,  0x09, 	/* 368F0 */
+	0x10,  0xB4,  0x04,  0x40,  0x14,  0x44,  0x17,  0xC8,  0x14,  0x70,  0x14,  0x42,  0x17,  0xC2,  0x1C,  0x3E, 	/* 36900 */
+	0x60,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0xC0,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83, 	/* 36910 */
+	0x00,  0x80,  0xB5,  0x08,  0x00,  0x09,  0xFE,  0x09,  0x52,  0x7F,  0x52,  0x09,  0x52,  0x09,  0x52,  0x1D, 	/* 36920 */
+	0x52,  0x1B,  0xFF,  0x19,  0x52,  0x29,  0x52,  0x29,  0x52,  0x49,  0x52,  0x09,  0x52,  0x09,  0x52,  0x09, 	/* 36930 */
+	0x52,  0x09,  0x06,  0xBB,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0xC0,  0x02,  0xA0,  0x04,  0x90, 	/* 36940 */
+	0x18,  0x8C,  0x6F,  0xFB,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08, 	/* 36950 */
+	0x7F,  0xFF,  0x00,  0x00,  0xBE,  0x08,  0x00,  0x09,  0xFE,  0x08,  0x10,  0x7F,  0x10,  0x08,  0x10,  0x08, 	/* 36960 */
+	0x90,  0x1C,  0x90,  0x1A,  0x9E,  0x1A,  0x90,  0x28,  0x90,  0x28,  0x90,  0x48,  0x90,  0x08,  0x90,  0x08, 	/* 36970 */
+	0x90,  0x0B,  0xFF,  0x08,  0x00,  0xBF,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x7F,  0xFF,  0x08,  0x20, 	/* 36980 */
+	0x08,  0x20,  0x19,  0xFE,  0x1D,  0x22,  0x1B,  0x22,  0x29,  0x22,  0x29,  0x22,  0x49,  0x22,  0x09,  0x2C, 	/* 36990 */
+	0x09,  0x20,  0x08,  0x20,  0x08,  0x20,  0x82,  0x08,  0x00,  0x08,  0xFC,  0x08,  0x84,  0x7E,  0xA4,  0x08, 	/* 369A0 */
+	0x94,  0x08,  0x94,  0x1C,  0x84,  0x1B,  0xFF,  0x19,  0x04,  0x29,  0x24,  0x29,  0x14,  0x49,  0x14,  0x09, 	/* 369B0 */
+	0xFE,  0x08,  0x04,  0x08,  0x08,  0x08,  0x30,  0x83,  0x08,  0x04,  0x08,  0x18,  0x08,  0xE0,  0x7E,  0x80, 	/* 369C0 */
+	0x08,  0xFF,  0x08,  0x90,  0x1C,  0x90,  0x1A,  0x9E,  0x1A,  0x92,  0x28,  0x92,  0x28,  0x92,  0x49,  0x22, 	/* 369D0 */
+	0x09,  0x22,  0x0A,  0x42,  0x0C,  0x82,  0x08,  0x0C,  0x84,  0x22,  0x08,  0x11,  0x08,  0x08,  0x90,  0x08, 	/* 369E0 */
+	0xA0,  0x7F,  0xFE,  0x40,  0x02,  0x41,  0x02,  0x01,  0x00,  0x7F,  0xFE,  0x03,  0x80,  0x05,  0x40,  0x09, 	/* 369F0 */
+	0x20,  0x11,  0x18,  0x61,  0x06,  0x01,  0x00,  0x01,  0x00,  0x93,  0x08,  0x20,  0x08,  0x30,  0x08,  0x50, 	/* 36A00 */
+	0x7F,  0x48,  0x08,  0x84,  0x09,  0x02,  0x1A,  0xFD,  0x1C,  0x20,  0x1A,  0x20,  0x2A,  0x20,  0x29,  0xFC, 	/* 36A10 */
+	0x48,  0x20,  0x08,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x08,  0x00,  0x96,  0x08,  0x00,  0x0B,  0xFE,  0x08, 	/* 36A20 */
+	0x50,  0x7E,  0x50,  0x09,  0xFE,  0x09,  0x52,  0x1D,  0x52,  0x1B,  0x52,  0x19,  0x52,  0x29,  0x8E,  0x29, 	/* 36A30 */
+	0x02,  0x49,  0x02,  0x09,  0x02,  0x09,  0x02,  0x09,  0xFE,  0x08,  0x00,  0x97,  0x00,  0x00,  0x7F,  0xFF, 	/* 36A40 */
+	0x02,  0x20,  0x02,  0x20,  0x1F,  0xFC,  0x12,  0x24,  0x12,  0x24,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF, 	/* 36A50 */
+	0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0x00,  0x80,  0x9E,  0x00,  0x00,  0x3E, 	/* 36A60 */
+	0x3E,  0x08,  0x08,  0x08,  0x08,  0x7F,  0x7F,  0x08,  0x08,  0x08,  0x08,  0x08,  0x88,  0x00,  0x80,  0x7F, 	/* 36A70 */
+	0xFF,  0x01,  0xC0,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0xA1,  0x08,  0x10, 	/* 36A80 */
+	0x08,  0x10,  0x08,  0x10,  0x7F,  0xFF,  0x08,  0x44,  0x08,  0x44,  0x1C,  0x42,  0x1A,  0xA5,  0x19,  0x25, 	/* 36A90 */
+	0x29,  0x28,  0x28,  0x10,  0x48,  0x10,  0x08,  0x28,  0x08,  0x44,  0x08,  0x82,  0x0B,  0x01,  0xA2,  0x08, 	/* 36AA0 */
+	0x00,  0x0B,  0xFF,  0x08,  0x20,  0x7E,  0x20,  0x08,  0x40,  0x08,  0xFC,  0x1C,  0x84,  0x1A,  0x84,  0x1A, 	/* 36AB0 */
+	0x84,  0x28,  0xFC,  0x28,  0x84,  0x48,  0x84,  0x08,  0x84,  0x08,  0x84,  0x08,  0xFC,  0x08,  0x00,  0xA9, 	/* 36AC0 */
+	0x08,  0x00,  0x09,  0xEE,  0x08,  0x22,  0x7E,  0x66,  0x08,  0x66,  0x08,  0xAA,  0x1C,  0xAA,  0x1B,  0x32, 	/* 36AD0 */
+	0x2A,  0x66,  0x28,  0x66,  0x48,  0xAA,  0x08,  0xAA,  0x09,  0x32,  0x0A,  0x22,  0x08,  0x22,  0x08,  0x66, 	/* 36AE0 */
+	0xAA,  0x08,  0x10,  0x08,  0x90,  0x08,  0x90,  0x7E,  0x90,  0x09,  0xFE,  0x09,  0x10,  0x1D,  0x10,  0x1A, 	/* 36AF0 */
+	0x10,  0x1B,  0xFF,  0x28,  0x30,  0x28,  0x58,  0x48,  0x58,  0x08,  0x94,  0x09,  0x12,  0x0A,  0x11,  0x08, 	/* 36B00 */
+	0x10,  0xAB,  0x08,  0x20,  0x08,  0x20,  0x09,  0xFF,  0x7E,  0x20,  0x08,  0x20,  0x08,  0x7E,  0x1C,  0x42, 	/* 36B10 */
+	0x1A,  0x84,  0x18,  0x88,  0x29,  0xFF,  0x2A,  0x88,  0x48,  0x88,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88, 	/* 36B20 */
+	0x08,  0x98,  0xB2,  0x08,  0x20,  0x08,  0x22,  0x09,  0xFE,  0x7E,  0x24,  0x08,  0x28,  0x0B,  0xFF,  0x1C, 	/* 36B30 */
+	0x20,  0x1A,  0x40,  0x18,  0xFC,  0x29,  0x40,  0x2A,  0x40,  0x48,  0x7C,  0x08,  0x04,  0x08,  0x04,  0x08, 	/* 36B40 */
+	0x04,  0x08,  0x18,  0xB4,  0x08,  0x40,  0x08,  0x40,  0x08,  0x7F,  0x7E,  0x80,  0x09,  0x00,  0x0A,  0xFE, 	/* 36B50 */
+	0x18,  0x92,  0x1C,  0x92,  0x1A,  0x92,  0x2A,  0x92,  0x29,  0xFF,  0x48,  0x82,  0x08,  0x82,  0x08,  0x82, 	/* 36B60 */
+	0x08,  0x82,  0x08,  0x86,  0xB8,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x7F,  0xFF,  0x08,  0x20,  0x08, 	/* 36B70 */
+	0x28,  0x19,  0xC8,  0x1C,  0x52,  0x1A,  0x24,  0x28,  0x24,  0x28,  0x48,  0x49,  0x90,  0x08,  0x28,  0x08, 	/* 36B80 */
+	0x44,  0x08,  0x82,  0x0B,  0x02,  0xB9,  0x08,  0x00,  0x08,  0xFC,  0x08,  0x84,  0x7F,  0x84,  0x08,  0x84, 	/* 36B90 */
+	0x08,  0xFC,  0x1C,  0x84,  0x1A,  0x84,  0x1A,  0xFE,  0x2A,  0xA2,  0x28,  0x94,  0x48,  0x98,  0x08,  0x88, 	/* 36BA0 */
+	0x08,  0xA4,  0x08,  0xC2,  0x0B,  0x01,  0xBC,  0x08,  0x40,  0x08,  0x40,  0x08,  0x7C,  0x7F,  0x84,  0x08, 	/* 36BB0 */
+	0xC8,  0x08,  0xA8,  0x1D,  0x30,  0x1A,  0x28,  0x1A,  0x44,  0x28,  0x82,  0x29,  0xFD,  0x4A,  0x84,  0x08, 	/* 36BC0 */
+	0x84,  0x08,  0x84,  0x08,  0xFC,  0x08,  0x00,  0xBD,  0x04,  0x20,  0x04,  0x28,  0x3F,  0xA4,  0x04,  0x24, 	/* 36BD0 */
+	0x04,  0x20,  0x7F,  0xFF,  0x00,  0x20,  0x04,  0x24,  0x04,  0x24,  0x7F,  0xD4,  0x0C,  0x18,  0x0E,  0x18, 	/* 36BE0 */
+	0x15,  0x2A,  0x24,  0xAA,  0x44,  0x46,  0x04,  0x82,  0x80,  0x04,  0x08,  0x04,  0x08,  0x0F,  0x7E,  0x09, 	/* 36BF0 */
+	0x48,  0x11,  0x48,  0x6A,  0x48,  0x04,  0xFF,  0x18,  0x08,  0x60,  0x88,  0x00,  0x80,  0x7F,  0xFF,  0x02, 	/* 36C00 */
+	0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0x81,  0x08,  0x40,  0x08,  0x5E,  0x08,  0x40, 	/* 36C10 */
+	0x7E,  0x80,  0x08,  0x80,  0x09,  0x20,  0x1C,  0x3F,  0x1A,  0x44,  0x18,  0x44,  0x28,  0x84,  0x29,  0x84, 	/* 36C20 */
+	0x4A,  0x84,  0x08,  0x84,  0x08,  0x84,  0x08,  0x84,  0x08,  0x8C,  0x82,  0x08,  0x20,  0x08,  0x20,  0x09, 	/* 36C30 */
+	0xFC,  0x7E,  0x20,  0x08,  0x20,  0x08,  0x20,  0x1D,  0xFF,  0x1A,  0x00,  0x1A,  0x20,  0x28,  0x20,  0x29, 	/* 36C40 */
+	0xFC,  0x48,  0x20,  0x08,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x08,  0x00,  0x83,  0x08,  0x48,  0x08,  0x48, 	/* 36C50 */
+	0x08,  0x4A,  0x7E,  0x4A,  0x09,  0x4C,  0x08,  0xC8,  0x1C,  0x48,  0x1A,  0x48,  0x1A,  0xCC,  0x29,  0x4A, 	/* 36C60 */
+	0x2A,  0x49,  0x48,  0x49,  0x08,  0x88,  0x08,  0x89,  0x09,  0x09,  0x0A,  0x07,  0x86,  0x08,  0x00,  0x09, 	/* 36C70 */
+	0xFF,  0x09,  0x00,  0x7F,  0xFE,  0x09,  0x10,  0x09,  0x10,  0x1D,  0x10,  0x1B,  0x7C,  0x19,  0x10,  0x29, 	/* 36C80 */
+	0x10,  0x29,  0x10,  0x49,  0xFE,  0x09,  0x00,  0x09,  0x00,  0x09,  0xFF,  0x08,  0x00,  0x88,  0x00,  0x80, 	/* 36C90 */
+	0x00,  0x80,  0x7F,  0xFE,  0x41,  0x02,  0x5F,  0xFA,  0x02,  0x20,  0x0E,  0x20,  0x01,  0xC0,  0x06,  0x38, 	/* 36CA0 */
+	0x18,  0x84,  0x7F,  0xFF,  0x01,  0xC0,  0x02,  0xA0,  0x0C,  0x98,  0x70,  0x86,  0x00,  0x80,  0x8D,  0x08, 	/* 36CB0 */
+	0x20,  0x08,  0x20,  0x09,  0xFF,  0x7E,  0x30,  0x08,  0x48,  0x08,  0xFC,  0x19,  0x02,  0x1C,  0x01,  0x1B, 	/* 36CC0 */
+	0xFE,  0x2A,  0x40,  0x28,  0x40,  0x48,  0xFC,  0x08,  0x84,  0x08,  0x04,  0x08,  0x04,  0x08,  0x18,  0x8E, 	/* 36CD0 */
+	0x08,  0x00,  0x0B,  0xFF,  0x08,  0x20,  0x7E,  0x20,  0x08,  0x48,  0x08,  0x84,  0x1D,  0xFA,  0x1A,  0x00, 	/* 36CE0 */
+	0x1A,  0x20,  0x28,  0x20,  0x29,  0xFC,  0x48,  0x20,  0x08,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x08,  0x00, 	/* 36CF0 */
+	0x90,  0x08,  0x00,  0x09,  0xFE,  0x09,  0x02,  0x7F,  0x02,  0x09,  0xFE,  0x09,  0x02,  0x1D,  0x02,  0x1B, 	/* 36D00 */
+	0x7A,  0x19,  0x4A,  0x29,  0x4A,  0x29,  0x4A,  0x49,  0x7A,  0x09,  0x02,  0x09,  0x02,  0x09,  0x02,  0x09, 	/* 36D10 */
+	0x06,  0x91,  0x00,  0x00,  0x0F,  0xF0,  0x02,  0x20,  0x01,  0xC0,  0x06,  0x30,  0x7F,  0x7E,  0x12,  0x24, 	/* 36D20 */
+	0x0C,  0x98,  0x72,  0xE7,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83, 	/* 36D30 */
+	0x00,  0x80,  0x93,  0x08,  0x00,  0x09,  0xFE,  0x08,  0x00,  0x7E,  0x00,  0x08,  0xFC,  0x08,  0x84,  0x1C, 	/* 36D40 */
+	0x84,  0x1A,  0xFC,  0x1A,  0x84,  0x28,  0x84,  0x28,  0x84,  0x48,  0xFC,  0x08,  0x00,  0x08,  0x00,  0x0B, 	/* 36D50 */
+	0xFF,  0x08,  0x00,  0x94,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x7F,  0xFF,  0x08,  0x20,  0x08,  0x20, 	/* 36D60 */
+	0x1C,  0x20,  0x1B,  0xFE,  0x1A,  0x00,  0x28,  0x00,  0x28,  0xFC,  0x48,  0x84,  0x08,  0x84,  0x08,  0x84, 	/* 36D70 */
+	0x08,  0xFC,  0x08,  0x00,  0x99,  0x08,  0x20,  0x08,  0x28,  0x08,  0x44,  0x7E,  0x8E,  0x09,  0xF1,  0x08, 	/* 36D80 */
+	0x00,  0x1C,  0x50,  0x1A,  0x50,  0x18,  0xFE,  0x29,  0x10,  0x28,  0x10,  0x4B,  0xFF,  0x08,  0x10,  0x08, 	/* 36D90 */
+	0x10,  0x08,  0x10,  0x08,  0x10,  0x9C,  0x08,  0x22,  0x09,  0x12,  0x08,  0x92,  0x7E,  0x94,  0x08,  0x84, 	/* 36DA0 */
+	0x08,  0x08,  0x1C,  0x20,  0x1A,  0x20,  0x19,  0xFF,  0x28,  0x24,  0x28,  0x44,  0x48,  0x48,  0x08,  0xF8, 	/* 36DB0 */
+	0x08,  0x28,  0x08,  0xC4,  0x0B,  0x02,  0x9D,  0x11,  0x04,  0x11,  0x04,  0x11,  0x04,  0x7D,  0xC4,  0x11, 	/* 36DC0 */
+	0x5E,  0x11,  0x54,  0x32,  0x54,  0x3A,  0x54,  0x35,  0x54,  0x50,  0x94,  0x50,  0xBF,  0x10,  0x84,  0x11, 	/* 36DD0 */
+	0x04,  0x11,  0x04,  0x12,  0x04,  0x14,  0x04,  0x9F,  0x08,  0x14,  0x08,  0x12,  0x08,  0x12,  0x7F,  0x1E, 	/* 36DE0 */
+	0x08,  0xF0,  0x08,  0x1E,  0x1C,  0xF0,  0x1A,  0x1F,  0x19,  0xF4,  0x29,  0x14,  0x28,  0x08,  0x48,  0x18, 	/* 36DF0 */
+	0x08,  0x29,  0x08,  0xC5,  0x0B,  0x03,  0x08,  0x01,  0xA3,  0x08,  0x10,  0x09,  0x12,  0x08,  0x92,  0x7E, 	/* 36E00 */
+	0x94,  0x08,  0x98,  0x08,  0x10,  0x1D,  0xFE,  0x1A,  0x02,  0x1A,  0x02,  0x28,  0x02,  0x28,  0xFE,  0x48, 	/* 36E10 */
+	0x02,  0x08,  0x02,  0x08,  0x02,  0x09,  0xFE,  0x08,  0x00,  0xA7,  0x08,  0x20,  0x08,  0x20,  0x08,  0x50, 	/* 36E20 */
+	0x7E,  0x48,  0x08,  0x84,  0x09,  0x02,  0x1A,  0xFD,  0x1C,  0x00,  0x1A,  0x00,  0x2B,  0xFF,  0x28,  0x20, 	/* 36E30 */
+	0x48,  0x28,  0x08,  0x44,  0x08,  0x9C,  0x0B,  0xE2,  0x08,  0x02,  0xB4,  0x08,  0x04,  0x08,  0x18,  0x09, 	/* 36E40 */
+	0xE4,  0x7E,  0xA2,  0x08,  0x92,  0x09,  0x11,  0x1C,  0xFD,  0x1A,  0x04,  0x1A,  0x08,  0x28,  0x10,  0x29, 	/* 36E50 */
+	0xFF,  0x48,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x30,  0xB6,  0x08,  0x00,  0x09,  0xFC, 	/* 36E60 */
+	0x08,  0x08,  0x7E,  0x50,  0x08,  0x20,  0x09,  0xFE,  0x1D,  0x22,  0x1B,  0x22,  0x29,  0xFE,  0x29,  0x22, 	/* 36E70 */
+	0x49,  0x22,  0x09,  0xFE,  0x09,  0x22,  0x09,  0x22,  0x09,  0x22,  0x09,  0x06,  0xB7,  0x08,  0x40,  0x08, 	/* 36E80 */
+	0x78,  0x08,  0x48,  0x7E,  0x90,  0x09,  0xFE,  0x08,  0x92,  0x1C,  0x92,  0x1A,  0xFE,  0x1A,  0x92,  0x28, 	/* 36E90 */
+	0x92,  0x28,  0xFE,  0x48,  0x82,  0x08,  0x82,  0x09,  0x02,  0x09,  0x02,  0x0A,  0x06,  0xBE,  0x08,  0x00, 	/* 36EA0 */
+	0x08,  0xFC,  0x08,  0x24,  0x7E,  0x24,  0x09,  0xFF,  0x08,  0x24,  0x1C,  0x24,  0x1A,  0xFC,  0x1A,  0x40, 	/* 36EB0 */
+	0x28,  0x40,  0x28,  0xFE,  0x48,  0xC2,  0x09,  0x42,  0x0A,  0x42,  0x08,  0x7E,  0x08,  0x00,  0xBF,  0x08, 	/* 36EC0 */
+	0x00,  0x08,  0xFC,  0x08,  0x84,  0x7E,  0xFC,  0x08,  0x84,  0x08,  0x84,  0x1C,  0xFC,  0x1A,  0x00,  0x1A, 	/* 36ED0 */
+	0xFE,  0x28,  0x10,  0x28,  0x10,  0x4B,  0xFF,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x81, 	/* 36EE0 */
+	0x00,  0x00,  0x37,  0xF8,  0x08,  0x48,  0x02,  0x4A,  0x62,  0x49,  0x14,  0x89,  0x01,  0x08,  0x0A,  0x30, 	/* 36EF0 */
+	0x30,  0x80,  0x40,  0x80,  0x7F,  0xFF,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80, 	/* 36F00 */
+	0x83,  0x08,  0x02,  0x08,  0x0C,  0x0B,  0xF8,  0x7E,  0x48,  0x08,  0x88,  0x09,  0x08,  0x19,  0xFF,  0x1C, 	/* 36F10 */
+	0x48,  0x2A,  0x48,  0x2A,  0x48,  0x49,  0x48,  0x08,  0xC8,  0x08,  0xBE,  0x09,  0x40,  0x09,  0x30,  0x0A, 	/* 36F20 */
+	0x0F,  0x85,  0x08,  0x40,  0x08,  0x40,  0x08,  0x7F,  0x7E,  0x80,  0x08,  0x80,  0x09,  0xFC,  0x1C,  0xA4, 	/* 36F30 */
+	0x1A,  0xA4,  0x18,  0xA4,  0x2B,  0xFF,  0x29,  0x24,  0x49,  0x24,  0x0B,  0xFF,  0x0A,  0x04,  0x08,  0x08, 	/* 36F40 */
+	0x08,  0x30,  0x8D,  0x08,  0x10,  0x08,  0x20,  0x08,  0xFC,  0x7E,  0x84,  0x08,  0x84,  0x08,  0xFC,  0x1C, 	/* 36F50 */
+	0x84,  0x1A,  0x84,  0x1A,  0xFC,  0x28,  0x20,  0x28,  0x27,  0x48,  0x38,  0x0B,  0xE0,  0x08,  0x21,  0x08, 	/* 36F60 */
+	0x21,  0x08,  0x1F,  0x8F,  0x08,  0x10,  0x08,  0x90,  0x08,  0x90,  0x7E,  0xFE,  0x08,  0x90,  0x09,  0x10, 	/* 36F70 */
+	0x1C,  0x10,  0x1B,  0xFF,  0x1A,  0x10,  0x28,  0x00,  0x28,  0xFE,  0x48,  0x82,  0x08,  0x82,  0x08,  0x82, 	/* 36F80 */
+	0x08,  0xFE,  0x08,  0x00,  0x93,  0x08,  0x20,  0x08,  0x20,  0x09,  0xFE,  0x7E,  0x08,  0x08,  0x88,  0x08, 	/* 36F90 */
+	0x48,  0x1C,  0x50,  0x1B,  0xFF,  0x1A,  0x20,  0x28,  0x20,  0x28,  0x20,  0x49,  0xFE,  0x08,  0x20,  0x08, 	/* 36FA0 */
+	0x20,  0x08,  0x20,  0x08,  0x20,  0x94,  0x08,  0x04,  0x08,  0x18,  0x08,  0xE0,  0x7E,  0x80,  0x08,  0xFF, 	/* 36FB0 */
+	0x08,  0x80,  0x1C,  0xFE,  0x1A,  0xD2,  0x1A,  0xD2,  0x28,  0xD2,  0x28,  0xFE,  0x49,  0x40,  0x09,  0x40, 	/* 36FC0 */
+	0x0A,  0x41,  0x0C,  0x21,  0x08,  0x1F,  0x97,  0x08,  0x00,  0x0B,  0xFF,  0x08,  0x20,  0x7D,  0xFC,  0x09, 	/* 36FD0 */
+	0x24,  0x09,  0x24,  0x1D,  0xFC,  0x1B,  0x24,  0x1B,  0x24,  0x29,  0xFC,  0x28,  0xA0,  0x48,  0x60,  0x08, 	/* 36FE0 */
+	0x20,  0x08,  0x50,  0x08,  0x8C,  0x0B,  0x03,  0x9B,  0x08,  0x00,  0x0B,  0xEF,  0x08,  0xA9,  0x7E,  0xAA, 	/* 36FF0 */
+	0x08,  0xAA,  0x0B,  0xEC,  0x1C,  0xAA,  0x1A,  0xA9,  0x28,  0xA9,  0x2B,  0xE9,  0x48,  0xA9,  0x08,  0xA9, 	/* 37000 */
+	0x09,  0x2E,  0x09,  0x28,  0x0A,  0x28,  0x08,  0xC8,  0x9D,  0x04,  0x40,  0x04,  0x40,  0x04,  0x7F,  0x08, 	/* 37010 */
+	0x84,  0x09,  0x24,  0x12,  0x28,  0x12,  0x10,  0x32,  0x6C,  0x53,  0x93,  0x12,  0x10,  0x13,  0xFF,  0x12, 	/* 37020 */
+	0x38,  0x12,  0x54,  0x10,  0x92,  0x11,  0x11,  0x10,  0x10,  0x9F,  0x01,  0x00,  0x1F,  0xF8,  0x10,  0x08, 	/* 37030 */
+	0x1F,  0xF8,  0x10,  0x08,  0x1F,  0xFF,  0x10,  0x00,  0x1F,  0xFE,  0x00,  0x02,  0x00,  0x82,  0x00,  0x8C, 	/* 37040 */
+	0x7F,  0xFF,  0x02,  0xA0,  0x0C,  0x98,  0x70,  0x87,  0x00,  0x80,  0xA0,  0x08,  0x00,  0x08,  0xFC,  0x08, 	/* 37050 */
+	0x84,  0x7F,  0x84,  0x08,  0x84,  0x08,  0x84,  0x1C,  0xFC,  0x1A,  0x20,  0x19,  0x20,  0x28,  0x40,  0x29, 	/* 37060 */
+	0xFE,  0x49,  0x02,  0x09,  0x02,  0x09,  0x02,  0x09,  0xFE,  0x08,  0x00,  0xA2,  0x08,  0x10,  0x08,  0x92, 	/* 37070 */
+	0x08,  0x52,  0x7F,  0x54,  0x08,  0x10,  0x08,  0x7E,  0x1C,  0x42,  0x1A,  0x42,  0x19,  0x7E,  0x29,  0x42, 	/* 37080 */
+	0x28,  0x42,  0x48,  0x7E,  0x08,  0x42,  0x08,  0x42,  0x08,  0x42,  0x08,  0x46,  0xA6,  0x04,  0x08,  0x04, 	/* 37090 */
+	0x08,  0x7F,  0xFF,  0x0E,  0x0C,  0x0D,  0x1C,  0x14,  0xAA,  0x24,  0x49,  0x44,  0x88,  0x01,  0xF8,  0x02, 	/* 370A0 */
+	0x08,  0x0D,  0x10,  0x30,  0xA0,  0x00,  0x40,  0x01,  0x80,  0x06,  0x00,  0x38,  0x00,  0xA7,  0x08,  0x00, 	/* 370B0 */
+	0x09,  0xFE,  0x08,  0x20,  0x7F,  0x20,  0x08,  0xF8,  0x08,  0x48,  0x1C,  0x48,  0x1A,  0x48,  0x1B,  0xFF, 	/* 370C0 */
+	0x28,  0x00,  0x28,  0xFC,  0x48,  0x84,  0x08,  0x84,  0x08,  0x84,  0x08,  0xFC,  0x08,  0x00,  0xA8,  0x03, 	/* 370D0 */
+	0x02,  0x3C,  0x22,  0x04,  0x22,  0x7F,  0xA2,  0x04,  0x22,  0x0E,  0x22,  0x15,  0x22,  0x64,  0x02,  0x04, 	/* 370E0 */
+	0x86,  0x04,  0x80,  0x7F,  0xFF,  0x01,  0xC0,  0x02,  0xA0,  0x0C,  0x98,  0x70,  0x87,  0x00,  0x80,  0xAD, 	/* 370F0 */
+	0x08,  0x20,  0x08,  0x28,  0x08,  0x44,  0x7F,  0xFA,  0x08,  0x48,  0x08,  0x49,  0x1C,  0x87,  0x1B,  0x40, 	/* 37100 */
+	0x1A,  0x78,  0x28,  0x88,  0x29,  0x88,  0x4A,  0x50,  0x08,  0x20,  0x08,  0x50,  0x09,  0x8C,  0x0E,  0x03, 	/* 37110 */
+	0xAF,  0x08,  0x84,  0x08,  0x48,  0x09,  0xFE,  0x7E,  0x22,  0x08,  0x22,  0x09,  0xFE,  0x1D,  0x20,  0x1B, 	/* 37120 */
+	0x20,  0x19,  0xFE,  0x28,  0x22,  0x28,  0x62,  0x48,  0xA2,  0x09,  0x22,  0x0E,  0x2C,  0x08,  0x20,  0x08, 	/* 37130 */
+	0x20,  0xB0,  0x08,  0x10,  0x08,  0x14,  0x08,  0x12,  0x7F,  0xFF,  0x08,  0x10,  0x09,  0x52,  0x19,  0x52, 	/* 37140 */
+	0x1D,  0x52,  0x1B,  0xF4,  0x29,  0x54,  0x29,  0x4C,  0x49,  0x48,  0x0A,  0x5A,  0x0A,  0x26,  0x0C,  0x46, 	/* 37150 */
+	0x08,  0x82,  0xB1,  0x08,  0x00,  0x09,  0xFE,  0x09,  0x02,  0x7F,  0x22,  0x09,  0x22,  0x09,  0xFE,  0x1D, 	/* 37160 */
+	0x22,  0x1B,  0x72,  0x19,  0x72,  0x29,  0xAA,  0x29,  0xAA,  0x49,  0x26,  0x09,  0x22,  0x09,  0x02,  0x09, 	/* 37170 */
+	0xFE,  0x08,  0x00,  0xB3,  0x08,  0x10,  0x08,  0x10,  0x09,  0xFF,  0x7E,  0x20,  0x08,  0x2C,  0x08,  0x4A, 	/* 37180 */
+	0x1D,  0xF1,  0x1A,  0x00,  0x1A,  0xA4,  0x28,  0xA4,  0x28,  0xA4,  0x48,  0xA4,  0x08,  0xA4,  0x09,  0x25, 	/* 37190 */
+	0x09,  0x05,  0x0A,  0x03,  0xB5,  0x08,  0x10,  0x08,  0x10,  0x7F,  0xFF,  0x0C,  0x38,  0x1A,  0x34,  0x19, 	/* 371A0 */
+	0x52,  0x28,  0x91,  0x49,  0x10,  0x00,  0x00,  0x07,  0xF0,  0x04,  0x10,  0x05,  0x10,  0x04,  0x92,  0x08, 	/* 371B0 */
+	0x92,  0x10,  0x12,  0x60,  0x0E,  0xB6,  0x08,  0x00,  0x09,  0xFE,  0x09,  0x02,  0x7F,  0x02,  0x09,  0xFE, 	/* 371C0 */
+	0x09,  0x04,  0x1D,  0x18,  0x1B,  0xE0,  0x19,  0x20,  0x29,  0xFE,  0x29,  0x20,  0x49,  0xFF,  0x0A,  0x20, 	/* 371D0 */
+	0x0A,  0x21,  0x0C,  0x21,  0x08,  0x1F,  0xB9,  0x08,  0x04,  0x08,  0x18,  0x08,  0xE0,  0x7E,  0x80,  0x08, 	/* 371E0 */
+	0xFE,  0x08,  0x88,  0x1C,  0x88,  0x1A,  0x88,  0x18,  0x88,  0x28,  0x88,  0x2B,  0xFF,  0x48,  0x00,  0x08, 	/* 371F0 */
+	0x88,  0x08,  0x84,  0x09,  0x02,  0x0A,  0x02,  0xBA,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x0E,  0x38, 	/* 37200 */
+	0x0D,  0x34,  0x14,  0x52,  0x24,  0x91,  0x04,  0x10,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0xE0, 	/* 37210 */
+	0x00,  0x98,  0x00,  0x84,  0x00,  0x80,  0x00,  0x80,  0xBC,  0x08,  0x20,  0x08,  0x20,  0x09,  0xFE,  0x7E, 	/* 37220 */
+	0x20,  0x08,  0xFC,  0x08,  0x20,  0x1D,  0xFF,  0x1A,  0x40,  0x18,  0x44,  0x29,  0xFF,  0x28,  0x44,  0x48, 	/* 37230 */
+	0xA4,  0x08,  0x94,  0x09,  0x14,  0x0A,  0x04,  0x08,  0x0C,  0x84,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x30, 	/* 37240 */
+	0x02,  0x0C,  0x1F,  0xFA,  0x08,  0x88,  0x7F,  0xFF,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x80,  0x7F,  0xFF, 	/* 37250 */
+	0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0x86,  0x08,  0x10,  0x08,  0x10,  0x08, 	/* 37260 */
+	0x28,  0x7F,  0x44,  0x08,  0x82,  0x09,  0x7D,  0x1C,  0x00,  0x1A,  0x00,  0x19,  0xFE,  0x28,  0xAA,  0x28, 	/* 37270 */
+	0xAA,  0x48,  0xFE,  0x08,  0xAA,  0x08,  0xAA,  0x08,  0xAA,  0x08,  0x86,  0x89,  0x08,  0x10,  0x08,  0x20, 	/* 37280 */
+	0x08,  0xFC,  0x7E,  0x84,  0x08,  0xFC,  0x08,  0x84,  0x1C,  0x84,  0x1A,  0xFC,  0x1A,  0x20,  0x29,  0xFE, 	/* 37290 */
+	0x29,  0x22,  0x49,  0x22,  0x09,  0x22,  0x09,  0x2C,  0x08,  0x20,  0x08,  0x20,  0x8A,  0x04,  0x10,  0x3F, 	/* 372A0 */
+	0xFE,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x90,  0x08, 	/* 372B0 */
+	0x88,  0x17,  0xF4,  0x61,  0xC3,  0x02,  0xA0,  0x0C,  0x98,  0x30,  0x86,  0x00,  0x80,  0x8B,  0x08,  0x44, 	/* 372C0 */
+	0x08,  0x44,  0x09,  0xFF,  0x7F,  0x44,  0x08,  0x44,  0x08,  0x7C,  0x1C,  0x44,  0x1A,  0x44,  0x19,  0x7C, 	/* 372D0 */
+	0x28,  0x44,  0x28,  0x44,  0x4B,  0xFF,  0x08,  0x08,  0x08,  0x44,  0x08,  0x82,  0x0B,  0x02,  0x8D,  0x08, 	/* 372E0 */
+	0x00,  0x08,  0xFC,  0x08,  0x84,  0x7F,  0x84,  0x08,  0xFC,  0x08,  0x84,  0x1C,  0x84,  0x1A,  0xFC,  0x1A, 	/* 372F0 */
+	0x00,  0x29,  0x10,  0x29,  0x12,  0x49,  0xDC,  0x09,  0x10,  0x09,  0x11,  0x09,  0xD1,  0x0B,  0x0F,  0x92, 	/* 37300 */
+	0x08,  0x20,  0x08,  0x20,  0x0B,  0xFE,  0x7E,  0x20,  0x09,  0xFC,  0x08,  0x50,  0x1F,  0xFF,  0x1A,  0x88, 	/* 37310 */
+	0x19,  0x24,  0x2A,  0x23,  0x29,  0xFC,  0x48,  0x20,  0x0B,  0xFE,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20, 	/* 37320 */
+	0x94,  0x08,  0x06,  0x08,  0xF8,  0x08,  0x90,  0x7F,  0x90,  0x08,  0xFF,  0x08,  0x88,  0x1C,  0x88,  0x1A, 	/* 37330 */
+	0xE5,  0x1B,  0x83,  0x28,  0xFD,  0x28,  0x84,  0x48,  0xFC,  0x08,  0x84,  0x08,  0x84,  0x08,  0xFC,  0x08, 	/* 37340 */
+	0x00,  0x95,  0x08,  0x10,  0x08,  0x10,  0x09,  0xFF,  0x7F,  0x01,  0x09,  0x01,  0x08,  0xFE,  0x1C,  0x00, 	/* 37350 */
+	0x1A,  0x00,  0x19,  0xFF,  0x28,  0x10,  0x28,  0x54,  0x48,  0x52,  0x08,  0x92,  0x09,  0x11,  0x08,  0x10, 	/* 37360 */
+	0x08,  0x30,  0x97,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80,  0x1F,  0xFC,  0x11,  0xC4,  0x16,  0xB4,  0x38, 	/* 37370 */
+	0x8E,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x1F,  0xFC,  0x11,  0xC4,  0x12,  0xAC,  0x0C,  0x98,  0x70, 	/* 37380 */
+	0x87,  0x00,  0x80,  0x98,  0x08,  0x10,  0x08,  0x10,  0x7F,  0x7F,  0x08,  0x10,  0x08,  0x10,  0x3F,  0x7E, 	/* 37390 */
+	0x29,  0x52,  0x29,  0x52,  0x2B,  0x56,  0x28,  0x50,  0x1C,  0x38,  0x1A,  0x34,  0x29,  0x52,  0x48,  0x91, 	/* 373A0 */
+	0x08,  0x10,  0x08,  0x10,  0x9A,  0x10,  0x00,  0x13,  0xDE,  0x12,  0x52,  0x7E,  0x52,  0x12,  0x52,  0x13, 	/* 373B0 */
+	0xDE,  0x3A,  0x52,  0x36,  0x52,  0x32,  0x52,  0x53,  0xDE,  0x52,  0x52,  0x12,  0x52,  0x12,  0x52,  0x12, 	/* 373C0 */
+	0x52,  0x14,  0x62,  0x18,  0xC6,  0x9F,  0x08,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x7E,  0x20,  0x09,  0xFC, 	/* 373D0 */
+	0x09,  0x24,  0x1D,  0xFC,  0x1B,  0x24,  0x1B,  0x24,  0x29,  0xFC,  0x28,  0x70,  0x48,  0x68,  0x08,  0xA4, 	/* 373E0 */
+	0x09,  0x22,  0x0A,  0x21,  0x08,  0x20,  0xA0,  0x08,  0x88,  0x04,  0x88,  0x04,  0x90,  0x3F,  0xFE,  0x20, 	/* 373F0 */
+	0x02,  0x27,  0xF2,  0x04,  0x10,  0x04,  0x10,  0x07,  0xF0,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0xA0,  0x04, 	/* 37400 */
+	0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0xA1,  0x08,  0x00,  0x09,  0xFE,  0x09,  0x02,  0x7F,  0x8A, 	/* 37410 */
+	0x09,  0x4A,  0x09,  0x52,  0x1D,  0xFE,  0x1B,  0x22,  0x2B,  0x22,  0x29,  0xAA,  0x49,  0xAA,  0x09,  0xAA, 	/* 37420 */
+	0x09,  0xFA,  0x09,  0x02,  0x09,  0x02,  0x09,  0x06,  0xA3,  0x08,  0x20,  0x08,  0x20,  0x09,  0xFC,  0x7E, 	/* 37430 */
+	0x24,  0x09,  0xFF,  0x08,  0x24,  0x1C,  0x24,  0x1B,  0xFC,  0x18,  0x22,  0x2A,  0x32,  0x29,  0x34,  0x49, 	/* 37440 */
+	0x68,  0x09,  0xA4,  0x0E,  0x22,  0x08,  0x21,  0x08,  0x60,  0xA7,  0x08,  0x28,  0x08,  0x24,  0x08,  0x3E, 	/* 37450 */
+	0x7F,  0xD0,  0x08,  0x16,  0x08,  0x18,  0x1C,  0x65,  0x1B,  0xA3,  0x1A,  0x29,  0x28,  0x24,  0x28,  0x1E, 	/* 37460 */
+	0x4B,  0xF0,  0x08,  0x14,  0x08,  0x19,  0x08,  0x67,  0x0B,  0x81,  0xAE,  0x00,  0x80,  0x00,  0x80,  0x1F, 	/* 37470 */
+	0xFC,  0x01,  0xC0,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x04,  0x90,  0x04,  0x10,  0x7F,  0xFF,  0x0C, 	/* 37480 */
+	0x10,  0x0E,  0x38,  0x15,  0x34,  0x24,  0x52,  0x44,  0x91,  0x04,  0x10,  0xAF,  0x08,  0x20,  0x08,  0x20, 	/* 37490 */
+	0x08,  0x50,  0x7E,  0x88,  0x09,  0x04,  0x0A,  0xFA,  0x1C,  0x01,  0x1A,  0xFC,  0x1A,  0x08,  0x28,  0x10, 	/* 374A0 */
+	0x28,  0x20,  0x49,  0x50,  0x09,  0x52,  0x0A,  0x45,  0x0C,  0x45,  0x08,  0x3C,  0xB2,  0x08,  0x20,  0x08, 	/* 374B0 */
+	0x20,  0x09,  0xFF,  0x7E,  0x20,  0x09,  0xFC,  0x08,  0x24,  0x19,  0xFF,  0x1C,  0x24,  0x1B,  0xFC,  0x28, 	/* 374C0 */
+	0x20,  0x2B,  0xFF,  0x48,  0x48,  0x08,  0x88,  0x09,  0xF0,  0x08,  0x28,  0x09,  0xC4,  0xB9,  0x08,  0x20, 	/* 374D0 */
+	0x08,  0x20,  0x08,  0x3E,  0x7F,  0x20,  0x08,  0x20,  0x08,  0xFC,  0x1C,  0x84,  0x1A,  0xFC,  0x1A,  0x84, 	/* 374E0 */
+	0x28,  0x84,  0x28,  0xFC,  0x48,  0x20,  0x0B,  0xFF,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0xBA,  0x08, 	/* 374F0 */
+	0x20,  0x08,  0x20,  0x0B,  0xFE,  0x7E,  0x02,  0x0A,  0x02,  0x08,  0xFA,  0x1C,  0x88,  0x1A,  0x88,  0x1A, 	/* 37500 */
+	0xF8,  0x28,  0x80,  0x28,  0x80,  0x48,  0xFC,  0x08,  0x84,  0x08,  0x84,  0x08,  0xFC,  0x08,  0x00,  0x80, 	/* 37510 */
+	0x08,  0x10,  0x08,  0x10,  0x09,  0xFF,  0x7F,  0x01,  0x09,  0x41,  0x08,  0x4E,  0x1C,  0xFA,  0x1A,  0x9A, 	/* 37520 */
+	0x1A,  0x9A,  0x29,  0x2A,  0x2A,  0xAA,  0x48,  0x4C,  0x08,  0x48,  0x08,  0x89,  0x09,  0x09,  0x0A,  0x07, 	/* 37530 */
+	0x81,  0x08,  0x10,  0x08,  0x10,  0x09,  0xFF,  0x7E,  0x00,  0x08,  0x7C,  0x08,  0x44,  0x1C,  0x7C,  0x1A, 	/* 37540 */
+	0x00,  0x19,  0xFC,  0x28,  0x08,  0x28,  0x10,  0x49,  0xFF,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08, 	/* 37550 */
+	0x30,  0x84,  0x08,  0x10,  0x08,  0x10,  0x08,  0xFE,  0x7F,  0x44,  0x08,  0x24,  0x08,  0x28,  0x1D,  0xFF, 	/* 37560 */
+	0x1A,  0x20,  0x18,  0x20,  0x29,  0xFF,  0x28,  0x24,  0x48,  0x44,  0x08,  0xE8,  0x08,  0x18,  0x08,  0x64, 	/* 37570 */
+	0x09,  0x82,  0x85,  0x08,  0x20,  0x08,  0x20,  0x09,  0xFE,  0x7E,  0x20,  0x08,  0x50,  0x08,  0x48,  0x1C, 	/* 37580 */
+	0x84,  0x1B,  0xFF,  0x1A,  0x04,  0x29,  0xE4,  0x29,  0x24,  0x49,  0x24,  0x09,  0xE4,  0x08,  0x04,  0x08, 	/* 37590 */
+	0x04,  0x08,  0x0C,  0x88,  0x08,  0x40,  0x08,  0x40,  0x08,  0x7E,  0x7E,  0x82,  0x08,  0xA2,  0x09,  0x2A, 	/* 375A0 */
+	0x18,  0xB2,  0x1D,  0xFA,  0x1A,  0x22,  0x28,  0x72,  0x28,  0x6A,  0x48,  0xA6,  0x09,  0x22,  0x08,  0x22, 	/* 375B0 */
+	0x08,  0x04,  0x08,  0x18,  0x8B,  0x08,  0x10,  0x08,  0x10,  0x09,  0xFF,  0x7F,  0x00,  0x08,  0x00,  0x08, 	/* 375C0 */
+	0x7C,  0x1C,  0x44,  0x1A,  0x44,  0x19,  0x44,  0x28,  0x7C,  0x28,  0x10,  0x48,  0x94,  0x08,  0x92,  0x09, 	/* 375D0 */
+	0x11,  0x0A,  0x11,  0x08,  0x30,  0x8C,  0x08,  0x10,  0x08,  0x10,  0x09,  0xFF,  0x7F,  0x29,  0x09,  0x29, 	/* 375E0 */
+	0x08,  0x4A,  0x1C,  0x46,  0x1A,  0x80,  0x19,  0x00,  0x28,  0xFE,  0x28,  0x10,  0x48,  0x10,  0x08,  0x10, 	/* 375F0 */
+	0x08,  0x10,  0x09,  0xFF,  0x08,  0x00,  0x8D,  0x08,  0x10,  0x08,  0x10,  0x08,  0xFF,  0x7F,  0x10,  0x08, 	/* 37600 */
+	0x7C,  0x09,  0x44,  0x1D,  0x44,  0x1B,  0x7C,  0x1B,  0x44,  0x29,  0x7C,  0x29,  0x44,  0x49,  0x44,  0x09, 	/* 37610 */
+	0x7C,  0x09,  0x00,  0x09,  0xFF,  0x08,  0x00,  0x8E,  0x08,  0x44,  0x08,  0x44,  0x08,  0x88,  0x7E,  0xFE, 	/* 37620 */
+	0x09,  0x88,  0x09,  0x88,  0x1C,  0x88,  0x1A,  0xFE,  0x1A,  0x88,  0x28,  0x88,  0x28,  0xFE,  0x48,  0x88, 	/* 37630 */
+	0x08,  0x88,  0x08,  0x88,  0x08,  0xFF,  0x08,  0x00,  0x8F,  0x08,  0x00,  0x09,  0xFF,  0x08,  0x28,  0x7E, 	/* 37640 */
+	0x28,  0x08,  0x28,  0x08,  0xEE,  0x1C,  0x82,  0x1A,  0x82,  0x1A,  0x82,  0x28,  0xEE,  0x28,  0x28,  0x48, 	/* 37650 */
+	0x28,  0x08,  0x28,  0x08,  0x28,  0x09,  0xFF,  0x08,  0x00,  0x92,  0x10,  0x80,  0x10,  0x9E,  0x10,  0x82, 	/* 37660 */
+	0x7E,  0xF2,  0x10,  0x92,  0x10,  0x92,  0x38,  0x8A,  0x37,  0xEA,  0x30,  0x8C,  0x52,  0xC4,  0x52,  0xA4, 	/* 37670 */
+	0x12,  0xAC,  0x12,  0x8A,  0x14,  0x92,  0x10,  0xA1,  0x11,  0xC1,  0x99,  0x08,  0x00,  0x08,  0xFC,  0x08, 	/* 37680 */
+	0x84,  0x7E,  0x84,  0x08,  0xFC,  0x08,  0x84,  0x1C,  0x84,  0x1A,  0xFC,  0x1A,  0x00,  0x29,  0xFE,  0x29, 	/* 37690 */
+	0x02,  0x49,  0x02,  0x09,  0xFE,  0x09,  0x02,  0x09,  0xFE,  0x08,  0x00,  0x9A,  0x10,  0x00,  0x13,  0xDE, 	/* 376A0 */
+	0x12,  0x52,  0x7F,  0xDE,  0x12,  0x52,  0x13,  0xDE,  0x3A,  0x02,  0x36,  0x02,  0x32,  0x02,  0x52,  0x02, 	/* 376B0 */
+	0x52,  0x02,  0x12,  0x02,  0x12,  0x02,  0x12,  0x02,  0x12,  0x02,  0x12,  0x06,  0x9B,  0x08,  0x88,  0x08, 	/* 376C0 */
+	0x88,  0x0B,  0xFF,  0x7E,  0x88,  0x08,  0x88,  0x08,  0x50,  0x1C,  0x50,  0x1A,  0x92,  0x18,  0x94,  0x29, 	/* 376D0 */
+	0x98,  0x2A,  0x90,  0x48,  0x90,  0x08,  0x90,  0x08,  0x91,  0x08,  0x91,  0x08,  0x8F,  0x9C,  0x08,  0x20, 	/* 376E0 */
+	0x08,  0x20,  0x08,  0x50,  0x7E,  0x88,  0x09,  0x04,  0x0B,  0xFE,  0x18,  0x21,  0x1D,  0xFC,  0x1B,  0x24, 	/* 376F0 */
+	0x29,  0x24,  0x29,  0xFC,  0x48,  0x30,  0x08,  0x30,  0x08,  0x48,  0x09,  0x84,  0x0E,  0x02,  0xA1,  0x10, 	/* 37700 */
+	0x02,  0x17,  0xF2,  0x10,  0x8A,  0x7C,  0x8A,  0x11,  0x4A,  0x11,  0x6A,  0x37,  0xAA,  0x38,  0x8A,  0x34, 	/* 37710 */
+	0x8A,  0x53,  0xEA,  0x50,  0x8A,  0x10,  0x82,  0x10,  0xE2,  0x11,  0x82,  0x16,  0x02,  0x10,  0x06,  0xA2, 	/* 37720 */
+	0x10,  0x00,  0x13,  0xFE,  0x12,  0x02,  0x7F,  0xFE,  0x12,  0x22,  0x12,  0x22,  0x3A,  0x22,  0x36,  0xFA, 	/* 37730 */
+	0x32,  0x22,  0x52,  0x32,  0x52,  0x2A,  0x12,  0x22,  0x13,  0xFE,  0x12,  0x02,  0x13,  0xFE,  0x10,  0x00, 	/* 37740 */
+	0xA3,  0x08,  0x50,  0x08,  0x50,  0x08,  0x50,  0x7F,  0xFE,  0x09,  0x52,  0x09,  0x52,  0x1D,  0x52,  0x1B, 	/* 37750 */
+	0xFE,  0x29,  0x52,  0x29,  0x52,  0x49,  0x52,  0x0B,  0xFF,  0x08,  0x00,  0x08,  0x48,  0x08,  0x84,  0x0B, 	/* 37760 */
+	0x02,  0xA5,  0x12,  0x00,  0x12,  0x00,  0x12,  0x1E,  0x7B,  0xD2,  0x15,  0x12,  0x15,  0x12,  0x39,  0x12, 	/* 37770 */
+	0x37,  0xF2,  0x31,  0x12,  0x51,  0x12,  0x51,  0x92,  0x11,  0x92,  0x12,  0x52,  0x12,  0x52,  0x14,  0x1E, 	/* 37780 */
+	0x18,  0x00,  0xA6,  0x08,  0x20,  0x08,  0xA8,  0x09,  0x24,  0x7E,  0xFA,  0x08,  0x20,  0x08,  0x50,  0x1D, 	/* 37790 */
+	0xFF,  0x1A,  0x48,  0x18,  0xA4,  0x29,  0x22,  0x2B,  0xFD,  0x48,  0x24,  0x08,  0x44,  0x08,  0x44,  0x08, 	/* 377A0 */
+	0x84,  0x09,  0x18,  0xA8,  0x08,  0x20,  0x08,  0x20,  0x09,  0xFF,  0x7F,  0x00,  0x09,  0x24,  0x09,  0x24, 	/* 377B0 */
+	0x1D,  0x3F,  0x1B,  0x44,  0x29,  0x64,  0x29,  0xD4,  0x49,  0x54,  0x09,  0x44,  0x0A,  0x44,  0x0A,  0x44, 	/* 377C0 */
+	0x0C,  0x44,  0x08,  0x4C,  0xAA,  0x08,  0x84,  0x08,  0x44,  0x08,  0x48,  0x7E,  0x00,  0x09,  0xFE,  0x0C, 	/* 377D0 */
+	0x48,  0x1A,  0x4A,  0x18,  0x4A,  0x19,  0x4A,  0x28,  0xCC,  0x28,  0xCC,  0x48,  0x48,  0x08,  0x48,  0x08, 	/* 377E0 */
+	0x48,  0x0B,  0xFF,  0x08,  0x00,  0xB0,  0x08,  0x00,  0x0B,  0xFF,  0x09,  0x29,  0x7F,  0x2A,  0x09,  0x2A, 	/* 377F0 */
+	0x09,  0xEC,  0x1D,  0x2A,  0x1B,  0x2A,  0x29,  0xE9,  0x29,  0x29,  0x49,  0x29,  0x09,  0x39,  0x09,  0xEE, 	/* 37800 */
+	0x0B,  0x28,  0x08,  0x28,  0x08,  0x28,  0xB4,  0x10,  0x40,  0x10,  0xBC,  0x13,  0x24,  0x7E,  0x24,  0x12, 	/* 37810 */
+	0x25,  0x13,  0xA5,  0x3A,  0x43,  0x36,  0x80,  0x33,  0xFC,  0x52,  0x24,  0x52,  0x24,  0x13,  0x98,  0x16, 	/* 37820 */
+	0x08,  0x12,  0x14,  0x12,  0x22,  0x12,  0xC1,  0xB6,  0x08,  0x8A,  0x08,  0xEA,  0x08,  0x92,  0x7E,  0xAA, 	/* 37830 */
+	0x08,  0xC2,  0x08,  0xFE,  0x1C,  0x48,  0x1A,  0x89,  0x19,  0x27,  0x2A,  0x3C,  0x28,  0x44,  0x48,  0xA8, 	/* 37840 */
+	0x09,  0x18,  0x08,  0x30,  0x08,  0xCC,  0x0B,  0x03,  0xB9,  0x08,  0x44,  0x08,  0x44,  0x09,  0xFF,  0x7F, 	/* 37850 */
+	0x44,  0x08,  0x7C,  0x08,  0x44,  0x1C,  0x7C,  0x1A,  0x44,  0x18,  0x44,  0x2B,  0xFF,  0x29,  0x28,  0x49, 	/* 37860 */
+	0x28,  0x09,  0x4F,  0x09,  0x80,  0x09,  0xFF,  0x08,  0x00,  0xBD,  0x08,  0x20,  0x08,  0x3E,  0x08,  0x44, 	/* 37870 */
+	0x7E,  0xF8,  0x08,  0x08,  0x09,  0xFF,  0x1C,  0x22,  0x1A,  0x52,  0x19,  0x94,  0x28,  0x28,  0x28,  0x4C, 	/* 37880 */
+	0x49,  0x9C,  0x08,  0x2A,  0x08,  0x49,  0x09,  0x88,  0x08,  0x30,  0xBF,  0x08,  0x20,  0x08,  0x20,  0x0B, 	/* 37890 */
+	0xFE,  0x7E,  0x20,  0x09,  0xFC,  0x08,  0x50,  0x1B,  0xFF,  0x1C,  0x48,  0x1A,  0x84,  0x29,  0xFA,  0x2A, 	/* 378A0 */
+	0x89,  0x4C,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x08,  0xF8,  0x08,  0x00,  0x8A,  0x08,  0x00,  0x08,  0x7C, 	/* 378B0 */
+	0x08,  0x44,  0x7F,  0x7C,  0x08,  0x44,  0x08,  0x44,  0x1C,  0x7C,  0x1A,  0x00,  0x19,  0xFF,  0x28,  0x40, 	/* 378C0 */
+	0x28,  0xFE,  0x49,  0x2A,  0x0A,  0x4A,  0x08,  0x92,  0x08,  0x22,  0x08,  0x4C,  0x93,  0x10,  0x00,  0x13, 	/* 378D0 */
+	0xFC,  0x12,  0x0C,  0x7E,  0x34,  0x13,  0xC4,  0x12,  0x44,  0x3B,  0xF4,  0x37,  0x54,  0x33,  0x54,  0x53, 	/* 378E0 */
+	0xF4,  0x52,  0x44,  0x12,  0x64,  0x14,  0x55,  0x14,  0x75,  0x1B,  0x8B,  0x10,  0x01,  0x94,  0x10,  0x80, 	/* 378F0 */
+	0x10,  0xBE,  0x13,  0xEA,  0x7C,  0x8A,  0x10,  0x8A,  0x13,  0xEA,  0x38,  0x92,  0x34,  0xD2,  0x53,  0xA2, 	/* 37900 */
+	0x50,  0xAC,  0x10,  0x20,  0x17,  0xFF,  0x10,  0x20,  0x10,  0x50,  0x11,  0x8C,  0x16,  0x03,  0x95,  0x08, 	/* 37910 */
+	0x20,  0x08,  0x20,  0x09,  0xFF,  0x7E,  0x40,  0x08,  0x7E,  0x08,  0x90,  0x1D,  0x7F,  0x1A,  0x00,  0x1A, 	/* 37920 */
+	0xFC,  0x28,  0x84,  0x28,  0xFC,  0x48,  0x84,  0x08,  0xFC,  0x08,  0x84,  0x08,  0x84,  0x08,  0x8C,  0x99, 	/* 37930 */
+	0x10,  0x04,  0x13,  0xE4,  0x10,  0x24,  0x7D,  0x5F,  0x10,  0x84,  0x18,  0x84,  0x37,  0xEE,  0x34,  0xAE, 	/* 37940 */
+	0x31,  0xD5,  0x51,  0x95,  0x52,  0xA4,  0x12,  0x84,  0x14,  0x84,  0x10,  0x84,  0x10,  0x84,  0x11,  0x84, 	/* 37950 */
+	0x9A,  0x04,  0x08,  0x04,  0x08,  0x7F,  0xFF,  0x0C,  0x1C,  0x16,  0x2A,  0x15,  0x29,  0x24,  0x48,  0x44, 	/* 37960 */
+	0x08,  0x00,  0x00,  0x3F,  0xFE,  0x08,  0x84,  0x08,  0x80,  0x0C,  0xFC,  0x12,  0x80,  0x21,  0xC0,  0x40, 	/* 37970 */
+	0x3F,  0x9C,  0x10,  0x80,  0x10,  0x9E,  0x10,  0x92,  0x7C,  0x92,  0x17,  0xF2,  0x10,  0x9E,  0x38,  0x92, 	/* 37980 */
+	0x34,  0x92,  0x33,  0xD2,  0x52,  0x5E,  0x52,  0x52,  0x12,  0x52,  0x13,  0xD2,  0x10,  0x22,  0x10,  0x22, 	/* 37990 */
+	0x10,  0x46,  0x9D,  0x08,  0x10,  0x08,  0x10,  0x09,  0xFF,  0x7E,  0x10,  0x08,  0x10,  0x08,  0xFE,  0x1C, 	/* 379A0 */
+	0x96,  0x1A,  0xDA,  0x2A,  0xB2,  0x28,  0xFE,  0x48,  0x18,  0x08,  0x34,  0x08,  0x52,  0x08,  0x91,  0x09, 	/* 379B0 */
+	0x10,  0x08,  0x10,  0x9E,  0x08,  0x00,  0x09,  0xFF,  0x09,  0x29,  0x7F,  0x29,  0x09,  0xFF,  0x08,  0x10, 	/* 379C0 */
+	0x1C,  0x10,  0x1B,  0xFF,  0x2A,  0x20,  0x28,  0x20,  0x48,  0x3C,  0x08,  0x24,  0x08,  0x44,  0x08,  0x44, 	/* 379D0 */
+	0x08,  0x84,  0x09,  0x18,  0xA0,  0x08,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x7C,  0x20,  0x08,  0x20,  0x09, 	/* 379E0 */
+	0xFE,  0x19,  0x8A,  0x1D,  0x52,  0x1B,  0xFA,  0x29,  0x22,  0x29,  0x22,  0x49,  0xFA,  0x09,  0x22,  0x09, 	/* 379F0 */
+	0x22,  0x09,  0x22,  0x09,  0x26,  0xA1,  0x08,  0x30,  0x08,  0x10,  0x08,  0x28,  0x7E,  0x44,  0x08,  0xFA, 	/* 37A00 */
+	0x09,  0x01,  0x1B,  0xEA,  0x1D,  0x2A,  0x2B,  0xAA,  0x29,  0x74,  0x49,  0x34,  0x09,  0xB4,  0x09,  0x6A, 	/* 37A10 */
+	0x09,  0x2A,  0x09,  0x2A,  0x09,  0x2A,  0xA2,  0x08,  0x84,  0x08,  0x44,  0x08,  0x48,  0x0B,  0xFF,  0x7E, 	/* 37A20 */
+	0x48,  0x08,  0x48,  0x09,  0xFE,  0x1D,  0x4A,  0x1B,  0x4A,  0x29,  0x8E,  0x29,  0x02,  0x49,  0xFE,  0x09, 	/* 37A30 */
+	0x02,  0x09,  0x02,  0x09,  0xFE,  0x08,  0x00,  0xAA,  0x08,  0xA4,  0x08,  0xA4,  0x0B,  0xFF,  0x7E,  0xA4, 	/* 37A40 */
+	0x08,  0xA4,  0x08,  0xBC,  0x1C,  0x80,  0x1A,  0xFE,  0x28,  0x20,  0x2B,  0xFF,  0x48,  0x70,  0x08,  0x68, 	/* 37A50 */
+	0x08,  0xA4,  0x09,  0x22,  0x0A,  0x21,  0x08,  0x20,  0xAB,  0x08,  0x00,  0x08,  0xFE,  0x08,  0x82,  0x7E, 	/* 37A60 */
+	0x82,  0x08,  0xFE,  0x08,  0x00,  0x1D,  0xFF,  0x1A,  0x82,  0x1A,  0xFE,  0x28,  0x82,  0x28,  0xFE,  0x48, 	/* 37A70 */
+	0x82,  0x08,  0x83,  0x08,  0xFE,  0x0B,  0x82,  0x08,  0x02,  0xAD,  0x01,  0x20,  0x09,  0x24,  0x05,  0x28, 	/* 37A80 */
+	0x7F,  0xFF,  0x04,  0x08,  0x02,  0x10,  0x3F,  0xFF,  0x00,  0x80,  0x1F,  0xFE,  0x00,  0x80,  0x7F,  0xFF, 	/* 37A90 */
+	0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0xAE,  0x08,  0x20,  0x08,  0x24,  0x08, 	/* 37AA0 */
+	0xFE,  0x7F,  0x24,  0x08,  0x28,  0x08,  0x30,  0x1D,  0xFF,  0x1A,  0x24,  0x1A,  0x42,  0x28,  0xFE,  0x29, 	/* 37AB0 */
+	0x42,  0x48,  0x7E,  0x08,  0x42,  0x08,  0x42,  0x08,  0x7E,  0x08,  0x00,  0xAF,  0x08,  0x04,  0x08,  0x18, 	/* 37AC0 */
+	0x09,  0xF0,  0x7F,  0x10,  0x09,  0xFF,  0x09,  0x10,  0x1D,  0x7E,  0x1B,  0x42,  0x1B,  0x42,  0x29,  0x7E, 	/* 37AD0 */
+	0x29,  0x42,  0x49,  0x7E,  0x0A,  0x42,  0x0A,  0x42,  0x0C,  0x7E,  0x08,  0x00,  0xB3,  0x08,  0x44,  0x08, 	/* 37AE0 */
+	0x44,  0x09,  0xFF,  0x7E,  0x44,  0x08,  0x7C,  0x08,  0x44,  0x1C,  0x44,  0x1A,  0x7C,  0x1A,  0x10,  0x29, 	/* 37AF0 */
+	0xFF,  0x28,  0x38,  0x48,  0x34,  0x08,  0x54,  0x08,  0x92,  0x09,  0x11,  0x08,  0x10,  0xB4,  0x08,  0x20, 	/* 37B00 */
+	0x08,  0x20,  0x09,  0xFF,  0x7E,  0x84,  0x08,  0x44,  0x08,  0x48,  0x1D,  0xFF,  0x1B,  0x11,  0x19,  0x11, 	/* 37B10 */
+	0x28,  0xFE,  0x28,  0x92,  0x48,  0x92,  0x08,  0x92,  0x08,  0x9C,  0x08,  0x10,  0x08,  0x10,  0xB5,  0x10, 	/* 37B20 */
+	0x00,  0x13,  0xFE,  0x10,  0x40,  0x7E,  0x40,  0x10,  0xE0,  0x10,  0x3E,  0x1B,  0xA2,  0x36,  0xAA,  0x32, 	/* 37B30 */
+	0xA4,  0x53,  0xA4,  0x52,  0xAA,  0x10,  0x31,  0x10,  0xC0,  0x10,  0x00,  0x17,  0xFF,  0x10,  0x00,  0xB7, 	/* 37B40 */
+	0x09,  0x10,  0x09,  0x10,  0x09,  0x12,  0x7F,  0xDC,  0x09,  0x11,  0x09,  0x31,  0x19,  0xCF,  0x1F,  0x20, 	/* 37B50 */
+	0x1A,  0x40,  0x29,  0xFC,  0x29,  0x04,  0x49,  0x04,  0x09,  0xFC,  0x09,  0x04,  0x09,  0xFC,  0x08,  0x00, 	/* 37B60 */
+	0xB8,  0x10,  0x28,  0x10,  0x48,  0x13,  0x88,  0x7C,  0x8A,  0x10,  0x9A,  0x10,  0x9A,  0x3B,  0xFC,  0x34, 	/* 37B70 */
+	0xA8,  0x30,  0xC8,  0x51,  0xAC,  0x51,  0x8C,  0x12,  0x94,  0x12,  0x94,  0x14,  0x92,  0x10,  0xA2,  0x10, 	/* 37B80 */
+	0xC1,  0xB9,  0x08,  0x00,  0x09,  0xFC,  0x08,  0x84,  0x7E,  0x84,  0x08,  0xF6,  0x0C,  0xD2,  0x1A,  0xA2, 	/* 37B90 */
+	0x19,  0x52,  0x1A,  0x8C,  0x28,  0x00,  0x29,  0xFE,  0x49,  0x4A,  0x09,  0x4A,  0x09,  0x4A,  0x0B,  0xFF, 	/* 37BA0 */
+	0x08,  0x00,  0xBC,  0x08,  0x10,  0x08,  0x92,  0x08,  0x54,  0x7F,  0xFF,  0x08,  0x38,  0x08,  0x54,  0x1C, 	/* 37BB0 */
+	0x92,  0x1A,  0x11,  0x1A,  0x20,  0x29,  0xFF,  0x29,  0x24,  0x48,  0x44,  0x08,  0xE8,  0x08,  0x18,  0x08, 	/* 37BC0 */
+	0x64,  0x09,  0x82,  0xBD,  0x00,  0x40,  0x20,  0x82,  0x13,  0xE2,  0x0A,  0x24,  0x0A,  0x28,  0x03,  0xE0, 	/* 37BD0 */
+	0x02,  0x28,  0x0E,  0x26,  0x33,  0xE1,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0xC0,  0x02,  0xA0,  0x0C,  0x98, 	/* 37BE0 */
+	0x70,  0x87,  0x00,  0x80,  0xBE,  0x08,  0x10,  0x08,  0x10,  0x08,  0xFC,  0x7F,  0x84,  0x08,  0xFC,  0x08, 	/* 37BF0 */
+	0x84,  0x1C,  0x84,  0x1A,  0xFC,  0x1A,  0x12,  0x29,  0xD2,  0x28,  0x5C,  0x48,  0x94,  0x09,  0x12,  0x0A, 	/* 37C00 */
+	0x11,  0x08,  0x10,  0x08,  0x30,  0x81,  0x08,  0x10,  0x08,  0x10,  0x09,  0xFF,  0x7F,  0x01,  0x09,  0x01, 	/* 37C10 */
+	0x08,  0xFE,  0x1C,  0x28,  0x1A,  0x44,  0x1B,  0xFA,  0x28,  0x10,  0x28,  0x10,  0x48,  0xFE,  0x08,  0x10, 	/* 37C20 */
+	0x08,  0x10,  0x0B,  0xFF,  0x08,  0x00,  0x82,  0x10,  0x00,  0x13,  0xFF,  0x12,  0x44,  0x12,  0x54,  0x7F, 	/* 37C30 */
+	0xD4,  0x12,  0x54,  0x12,  0x54,  0x3B,  0xFF,  0x37,  0x04,  0x32,  0x8C,  0x52,  0x8C,  0x12,  0x4C,  0x12, 	/* 37C40 */
+	0xD4,  0x13,  0x55,  0x1C,  0x25,  0x10,  0x43,  0x8A,  0x09,  0x08,  0x09,  0x08,  0x09,  0x08,  0x7F,  0xFE, 	/* 37C50 */
+	0x08,  0x6A,  0x08,  0xAA,  0x1C,  0xBE,  0x1D,  0x2A,  0x19,  0xAA,  0x2B,  0x6A,  0x2D,  0x3E,  0x49,  0x08, 	/* 37C60 */
+	0x09,  0x08,  0x09,  0x08,  0x09,  0x08,  0x09,  0x08,  0x8E,  0x08,  0x00,  0x0B,  0xFF,  0x08,  0x20,  0x7E, 	/* 37C70 */
+	0xFC,  0x08,  0x84,  0x08,  0xFC,  0x1C,  0x84,  0x1A,  0xFC,  0x1A,  0x84,  0x29,  0xFC,  0x28,  0x20,  0x48, 	/* 37C80 */
+	0x7C,  0x09,  0xC8,  0x08,  0x30,  0x08,  0xCC,  0x0B,  0x03,  0x91,  0x08,  0x24,  0x08,  0x22,  0x0B,  0xFF, 	/* 37C90 */
+	0x7E,  0x20,  0x09,  0xFC,  0x09,  0x24,  0x1D,  0xFC,  0x1B,  0x24,  0x29,  0xFC,  0x29,  0x24,  0x48,  0x08, 	/* 37CA0 */
+	0x0B,  0xFF,  0x08,  0x88,  0x08,  0x48,  0x08,  0x08,  0x08,  0x18,  0x94,  0x10,  0x80,  0x10,  0x9E,  0x13, 	/* 37CB0 */
+	0xD2,  0x7E,  0x52,  0x12,  0x54,  0x13,  0xD8,  0x3A,  0x54,  0x36,  0x52,  0x33,  0xD2,  0x52,  0x11,  0x52, 	/* 37CC0 */
+	0x91,  0x12,  0x59,  0x12,  0xD6,  0x13,  0x30,  0x16,  0x30,  0x10,  0x10,  0x95,  0x08,  0x10,  0x08,  0x10, 	/* 37CD0 */
+	0x09,  0xFF,  0x7F,  0x09,  0x09,  0x45,  0x08,  0x52,  0x18,  0x92,  0x1C,  0x28,  0x1A,  0x44,  0x28,  0x82, 	/* 37CE0 */
+	0x29,  0x01,  0x4A,  0xFE,  0x08,  0x82,  0x08,  0x82,  0x08,  0xFE,  0x08,  0x00,  0x9B,  0x08,  0x20,  0x09, 	/* 37CF0 */
+	0xFE,  0x08,  0x20,  0x7F,  0xFC,  0x08,  0x50,  0x0D,  0xFF,  0x1A,  0x88,  0x19,  0x14,  0x1A,  0xE2,  0x2C, 	/* 37D00 */
+	0x21,  0x2B,  0xFE,  0x48,  0x70,  0x08,  0xA8,  0x09,  0x24,  0x0A,  0x22,  0x08,  0x20,  0x9C,  0x08,  0x20, 	/* 37D10 */
+	0x08,  0x20,  0x0B,  0xFF,  0x7E,  0x84,  0x08,  0x48,  0x09,  0xFE,  0x19,  0x02,  0x1D,  0x22,  0x2A,  0x20, 	/* 37D20 */
+	0x2B,  0xFF,  0x48,  0x40,  0x08,  0x7C,  0x08,  0x44,  0x08,  0x84,  0x09,  0x04,  0x0A,  0x18,  0xA0,  0x08, 	/* 37D30 */
+	0x00,  0x09,  0xFF,  0x09,  0x01,  0x7F,  0x7D,  0x08,  0x44,  0x08,  0x44,  0x1C,  0x7C,  0x1A,  0x44,  0x1A, 	/* 37D40 */
+	0x44,  0x28,  0x7C,  0x28,  0x10,  0x4B,  0xFF,  0x08,  0x00,  0x08,  0x24,  0x08,  0xC2,  0x0B,  0x01,  0xA7, 	/* 37D50 */
+	0x08,  0x00,  0x09,  0xFF,  0x09,  0x14,  0x7F,  0x14,  0x09,  0x77,  0x09,  0x14,  0x1D,  0x74,  0x1B,  0x17, 	/* 37D60 */
+	0x29,  0x3C,  0x29,  0xD4,  0x49,  0x27,  0x09,  0x24,  0x09,  0x44,  0x09,  0x00,  0x09,  0xFF,  0x08,  0x00, 	/* 37D70 */
+	0xAE,  0x04,  0x10,  0x15,  0x52,  0x16,  0x54,  0x26,  0x98,  0x09,  0x24,  0x30,  0xC0,  0x7F,  0xFE,  0x40, 	/* 37D80 */
+	0x02,  0x40,  0x82,  0x00,  0x80,  0x7F,  0xFE,  0x01,  0xC0,  0x02,  0xA0,  0x0C,  0x98,  0x70,  0x87,  0x00, 	/* 37D90 */
+	0x80,  0xB1,  0x08,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x7E,  0x00,  0x08,  0xFC,  0x08,  0x84,  0x1B,  0xFF, 	/* 37DA0 */
+	0x1C,  0x84,  0x1A,  0xFC,  0x2A,  0x32,  0x28,  0xD2,  0x4B,  0x8C,  0x08,  0x88,  0x08,  0x84,  0x08,  0xE2, 	/* 37DB0 */
+	0x0B,  0x81,  0xB2,  0x08,  0x00,  0x08,  0xFC,  0x08,  0xA4,  0x7F,  0xA4,  0x08,  0xB4,  0x08,  0xCC,  0x1C, 	/* 37DC0 */
+	0xC4,  0x1A,  0xFC,  0x1A,  0x00,  0x29,  0xFE,  0x29,  0x52,  0x49,  0x52,  0x09,  0x52,  0x09,  0x52,  0x0B, 	/* 37DD0 */
+	0xFF,  0x08,  0x00,  0xB4,  0x08,  0x40,  0x08,  0x5F,  0x09,  0x85,  0x7F,  0x05,  0x09,  0x45,  0x09,  0x29, 	/* 37DE0 */
+	0x1D,  0xD1,  0x1B,  0x26,  0x1A,  0x00,  0x28,  0xFE,  0x28,  0x92,  0x48,  0xFE,  0x08,  0x92,  0x08,  0x92, 	/* 37DF0 */
+	0x08,  0xFE,  0x08,  0x00,  0xBB,  0x08,  0x00,  0x08,  0xFC,  0x08,  0x84,  0x7E,  0xFC,  0x08,  0x84,  0x08, 	/* 37E00 */
+	0xFC,  0x1C,  0x00,  0x1B,  0xFE,  0x2A,  0xAA,  0x28,  0xAA,  0x49,  0x76,  0x0A,  0x66,  0x08,  0xAA,  0x09, 	/* 37E10 */
+	0x32,  0x08,  0x22,  0x08,  0x66,  0xBE,  0x08,  0x00,  0x08,  0xFC,  0x08,  0x84,  0x7E,  0xBC,  0x08,  0xA4, 	/* 37E20 */
+	0x08,  0xA4,  0x1B,  0xFF,  0x1A,  0x01,  0x2C,  0xFC,  0x2A,  0x84,  0x48,  0xFC,  0x08,  0x84,  0x08,  0xFC, 	/* 37E30 */
+	0x08,  0x84,  0x08,  0x84,  0x08,  0x8C,  0xBF,  0x10,  0x20,  0x11,  0x22,  0x11,  0x22,  0x7D,  0xFE,  0x10, 	/* 37E40 */
+	0x00,  0x13,  0xFE,  0x38,  0x00,  0x35,  0xFC,  0x35,  0x04,  0x51,  0x04,  0x51,  0xFC,  0x10,  0x88,  0x10, 	/* 37E50 */
+	0x48,  0x10,  0x50,  0x17,  0xFF,  0x10,  0x00,  0x81,  0x08,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x7E,  0x00, 	/* 37E60 */
+	0x08,  0xFC,  0x08,  0x84,  0x1C,  0xFC,  0x1A,  0x00,  0x1B,  0xFE,  0x29,  0x02,  0x29,  0x7A,  0x49,  0x4A, 	/* 37E70 */
+	0x09,  0x4A,  0x09,  0x7A,  0x09,  0x02,  0x09,  0x06,  0x83,  0x04,  0x00,  0x1F,  0x3C,  0x19,  0x24,  0x15, 	/* 37E80 */
+	0x25,  0x17,  0x43,  0x79,  0xFC,  0x15,  0x24,  0x25,  0x18,  0x43,  0x64,  0x00,  0x82,  0x7F,  0xFF,  0x02, 	/* 37E90 */
+	0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0x87,  0x08,  0x82,  0x08,  0xFC,  0x08,  0x81, 	/* 37EA0 */
+	0x7F,  0x7F,  0x08,  0x00,  0x09,  0x7C,  0x1D,  0x44,  0x1B,  0x7C,  0x19,  0x44,  0x29,  0x7C,  0x29,  0x44, 	/* 37EB0 */
+	0x49,  0x7C,  0x09,  0x00,  0x09,  0xFF,  0x08,  0xCC,  0x0B,  0x02,  0x8A,  0x11,  0x00,  0x0A,  0x3E,  0x7F, 	/* 37EC0 */
+	0xA2,  0x04,  0x3E,  0x24,  0xA2,  0x24,  0xBE,  0x3F,  0xA2,  0x04,  0x22,  0x08,  0x46,  0x10,  0x80,  0x7F, 	/* 37ED0 */
+	0xFF,  0x01,  0xC0,  0x02,  0xA0,  0x0C,  0x98,  0x70,  0x87,  0x00,  0x80,  0x8B,  0x08,  0x48,  0x08,  0x48, 	/* 37EE0 */
+	0x09,  0xFF,  0x7E,  0x48,  0x09,  0xFE,  0x08,  0x48,  0x1B,  0xFF,  0x1C,  0x20,  0x1B,  0xFC,  0x29,  0x24, 	/* 37EF0 */
+	0x29,  0xFC,  0x49,  0x24,  0x0F,  0xFF,  0x09,  0x04,  0x09,  0x04,  0x09,  0x0C,  0x8C,  0x10,  0x08,  0x11, 	/* 37F00 */
+	0x10,  0x10,  0xBE,  0x7E,  0xA2,  0x10,  0x22,  0x10,  0x3E,  0x18,  0x20,  0x37,  0xA0,  0x34,  0xBE,  0x50, 	/* 37F10 */
+	0xA2,  0x50,  0xA2,  0x10,  0xA2,  0x10,  0xBE,  0x11,  0x60,  0x12,  0x30,  0x14,  0x0F,  0x8D,  0x08,  0x20, 	/* 37F20 */
+	0x08,  0x20,  0x08,  0x50,  0x7E,  0x88,  0x09,  0xFC,  0x0A,  0x02,  0x1C,  0xFD,  0x1A,  0x84,  0x1A,  0xFC, 	/* 37F30 */
+	0x28,  0x84,  0x28,  0xFC,  0x49,  0x00,  0x09,  0xFC,  0x0A,  0x84,  0x0C,  0xFC,  0x08,  0x00,  0x8E,  0x08, 	/* 37F40 */
+	0x88,  0x08,  0x50,  0x09,  0xFE,  0x7E,  0x20,  0x08,  0x20,  0x09,  0xFC,  0x1C,  0x20,  0x1A,  0x20,  0x1B, 	/* 37F50 */
+	0xFF,  0x28,  0x40,  0x28,  0x40,  0x48,  0xFE,  0x09,  0x10,  0x0A,  0x10,  0x09,  0xFF,  0x08,  0x00,  0x90, 	/* 37F60 */
+	0x08,  0x20,  0x08,  0x40,  0x09,  0xFC,  0x7F,  0x24,  0x09,  0x24,  0x09,  0xFC,  0x1D,  0x24,  0x1B,  0x24, 	/* 37F70 */
+	0x19,  0xFE,  0x28,  0x52,  0x28,  0x52,  0x48,  0x55,  0x08,  0x9F,  0x08,  0x91,  0x09,  0x11,  0x0A,  0x0F, 	/* 37F80 */
+	0x93,  0x08,  0x00,  0x08,  0xFE,  0x08,  0x10,  0x7E,  0x10,  0x09,  0xFF,  0x08,  0x00,  0x1C,  0xFE,  0x1A, 	/* 37F90 */
+	0x82,  0x1A,  0xFE,  0x28,  0x82,  0x28,  0xFE,  0x48,  0x82,  0x08,  0xFE,  0x08,  0x24,  0x08,  0xC2,  0x0B, 	/* 37FA0 */
+	0x01,  0x98,  0x08,  0x84,  0x08,  0x48,  0x09,  0xFE,  0x7E,  0x10,  0x09,  0xFC,  0x08,  0x10,  0x1C,  0x10, 	/* 37FB0 */
+	0x1B,  0xFF,  0x1A,  0x12,  0x28,  0x9C,  0x28,  0x58,  0x48,  0x74,  0x08,  0x92,  0x0B,  0x11,  0x08,  0x10, 	/* 37FC0 */
+	0x08,  0x30,  0x99,  0x08,  0x10,  0x08,  0x10,  0x0B,  0xFF,  0x7E,  0x10,  0x08,  0xFC,  0x08,  0x84,  0x1C, 	/* 37FD0 */
+	0xFC,  0x1A,  0x84,  0x1A,  0xFC,  0x28,  0x84,  0x28,  0xFC,  0x48,  0x00,  0x09,  0xFF,  0x08,  0x48,  0x08, 	/* 37FE0 */
+	0x86,  0x0B,  0x01,  0x9D,  0x08,  0x20,  0x08,  0x40,  0x08,  0xFC,  0x7F,  0x84,  0x08,  0xFC,  0x08,  0x84, 	/* 37FF0 */
+	0x1C,  0xFC,  0x1A,  0x80,  0x1A,  0xFF,  0x28,  0x80,  0x28,  0xFE,  0x4A,  0x42,  0x0A,  0x4A,  0x0B,  0xFA, 	/* 38000 */
+	0x08,  0x02,  0x08,  0x0C,  0x9E,  0x08,  0x20,  0x08,  0x20,  0x09,  0xFC,  0x7E,  0x88,  0x08,  0x50,  0x0B, 	/* 38010 */
+	0xFF,  0x1C,  0x00,  0x1B,  0xFC,  0x1B,  0x24,  0x29,  0x24,  0x29,  0xFC,  0x49,  0x24,  0x09,  0xFC,  0x08, 	/* 38020 */
+	0x21,  0x08,  0x21,  0x08,  0x1F,  0xA7,  0x04,  0x02,  0x04,  0x0C,  0x7F,  0xB0,  0x25,  0x20,  0x3F,  0x3F, 	/* 38030 */
+	0x25,  0x24,  0x3F,  0x24,  0x04,  0x24,  0x7F,  0xC4,  0x04,  0x84,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0xA0, 	/* 38040 */
+	0x0C,  0x98,  0x70,  0x87,  0x00,  0x80,  0xA8,  0x10,  0x80,  0x10,  0x9E,  0x17,  0xF2,  0x7C,  0x12,  0x13, 	/* 38050 */
+	0xD4,  0x12,  0x54,  0x3B,  0xD8,  0x34,  0x14,  0x33,  0xD4,  0x50,  0x52,  0x50,  0x92,  0x10,  0xF2,  0x17, 	/* 38060 */
+	0x92,  0x10,  0x9C,  0x10,  0x90,  0x11,  0x90,  0xAB,  0x08,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x7E,  0x20, 	/* 38070 */
+	0x09,  0xFC,  0x09,  0x24,  0x1D,  0xFC,  0x1B,  0x24,  0x29,  0xFC,  0x28,  0x22,  0x4B,  0xFD,  0x08,  0x08, 	/* 38080 */
+	0x0B,  0xFF,  0x08,  0x88,  0x08,  0x48,  0x08,  0x18,  0xAD,  0x08,  0x08,  0x08,  0x0A,  0x08,  0x09,  0x7F, 	/* 38090 */
+	0xFF,  0x09,  0x08,  0x09,  0x48,  0x1D,  0x7A,  0x1B,  0x4A,  0x29,  0xFA,  0x29,  0x4A,  0x49,  0x6C,  0x09, 	/* 380A0 */
+	0xD4,  0x0A,  0xD5,  0x0B,  0x4B,  0x0C,  0xD3,  0x08,  0x21,  0xB2,  0x11,  0x02,  0x11,  0xC2,  0x11,  0x52, 	/* 380B0 */
+	0x7A,  0x8A,  0x17,  0xEA,  0x12,  0xA2,  0x3A,  0xB2,  0x37,  0xEA,  0x32,  0xAA,  0x52,  0xA2,  0x53,  0xE3, 	/* 380C0 */
+	0x12,  0x2E,  0x12,  0x32,  0x12,  0x22,  0x12,  0x22,  0x14,  0x62,  0xB9,  0x08,  0x20,  0x08,  0x40,  0x08, 	/* 380D0 */
+	0xFC,  0x7E,  0x84,  0x08,  0xFC,  0x0C,  0x84,  0x1A,  0xFC,  0x18,  0x00,  0x1B,  0xAE,  0x28,  0x20,  0x2B, 	/* 380E0 */
+	0xAE,  0x48,  0x20,  0x0F,  0xFF,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0xBB,  0x08,  0x80,  0x08,  0x9E, 	/* 380F0 */
+	0x0B,  0xF2,  0x7E,  0x92,  0x08,  0x9E,  0x08,  0x92,  0x1B,  0xF2,  0x1C,  0x9E,  0x2A,  0x92,  0x28,  0xD2, 	/* 38100 */
+	0x49,  0x5E,  0x09,  0x2C,  0x0A,  0x0C,  0x0A,  0x15,  0x0C,  0x25,  0x08,  0xC3,  0xBD,  0x08,  0x48,  0x08, 	/* 38110 */
+	0x48,  0x09,  0xFF,  0x7E,  0x48,  0x09,  0xFE,  0x09,  0x4A,  0x1D,  0xFE,  0x1B,  0x4A,  0x19,  0xFE,  0x28, 	/* 38120 */
+	0x00,  0x28,  0xFC,  0x48,  0x84,  0x08,  0xFC,  0x08,  0x84,  0x08,  0xFC,  0x08,  0x00,  0xBF,  0x08,  0x44, 	/* 38130 */
+	0x08,  0x44,  0x09,  0xFF,  0x7E,  0x44,  0x08,  0x7C,  0x08,  0x10,  0x1C,  0xFE,  0x1A,  0x92,  0x1A,  0xFE, 	/* 38140 */
+	0x28,  0x10,  0x28,  0xFE,  0x48,  0x10,  0x08,  0xFE,  0x08,  0x10,  0x0B,  0xFF,  0x08,  0x00,  0x82,  0x08, 	/* 38150 */
+	0x44,  0x08,  0x84,  0x0B,  0xE5,  0x75,  0x3A,  0x15,  0x2A,  0x09,  0xE4,  0x09,  0x24,  0x15,  0x2A,  0x7B, 	/* 38160 */
+	0xFD,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0x85, 	/* 38170 */
+	0x11,  0x22,  0x11,  0x22,  0x11,  0x22,  0x7E,  0x55,  0x12,  0x49,  0x10,  0x80,  0x38,  0x88,  0x35,  0x08, 	/* 38180 */
+	0x31,  0x28,  0x53,  0x2E,  0x55,  0x28,  0x11,  0x28,  0x11,  0x28,  0x11,  0x58,  0x11,  0x48,  0x11,  0x87, 	/* 38190 */
+	0x8A,  0x08,  0x44,  0x09,  0x44,  0x7E,  0x9F,  0x09,  0x44,  0x1C,  0x0E,  0x1A,  0x4E,  0x29,  0x95,  0x48, 	/* 381A0 */
+	0xA5,  0x09,  0x44,  0x0A,  0x84,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x40,  0x02,  0x20,  0x0C,  0x18,  0x70, 	/* 381B0 */
+	0x07,  0x8B,  0x10,  0x00,  0x12,  0x7C,  0x11,  0x04,  0x7D,  0x28,  0x10,  0x10,  0x10,  0x7E,  0x38,  0x52, 	/* 381C0 */
+	0x37,  0x7E,  0x35,  0x52,  0x51,  0x7E,  0x51,  0x52,  0x11,  0x52,  0x11,  0x52,  0x12,  0xC6,  0x14,  0x60, 	/* 381D0 */
+	0x18,  0x1F,  0x8C,  0x08,  0x00,  0x08,  0xFC,  0x08,  0xA4,  0x7F,  0xFF,  0x09,  0x28,  0x09,  0xF8,  0x1C, 	/* 381E0 */
+	0x00,  0x1B,  0xFC,  0x1B,  0x04,  0x29,  0xFC,  0x29,  0x04,  0x49,  0xFC,  0x09,  0x04,  0x09,  0xFC,  0x08, 	/* 381F0 */
+	0x8C,  0x0B,  0x02,  0x92,  0x08,  0x10,  0x08,  0x10,  0x09,  0xFF,  0x7F,  0x25,  0x09,  0x15,  0x0C,  0xA8, 	/* 38200 */
+	0x1A,  0xAA,  0x19,  0x31,  0x2A,  0x62,  0x29,  0x9E,  0x48,  0x10,  0x09,  0x11,  0x09,  0x11,  0x09,  0x11, 	/* 38210 */
+	0x09,  0xFF,  0x08,  0x00,  0x93,  0x08,  0x20,  0x09,  0xFC,  0x09,  0x24,  0x7F,  0xFF,  0x09,  0x24,  0x09, 	/* 38220 */
+	0xFC,  0x1C,  0x20,  0x1B,  0xFC,  0x19,  0x24,  0x29,  0xFC,  0x28,  0x40,  0x4B,  0xFF,  0x08,  0x48,  0x09, 	/* 38230 */
+	0xC8,  0x08,  0x38,  0x09,  0xC4,  0x94,  0x08,  0x49,  0x09,  0xB6,  0x08,  0x92,  0x7F,  0x49,  0x08,  0xFE, 	/* 38240 */
+	0x08,  0x92,  0x1C,  0xFE,  0x1A,  0x92,  0x1A,  0xFE,  0x28,  0x10,  0x29,  0xFF,  0x48,  0x38,  0x08,  0x54, 	/* 38250 */
+	0x08,  0x92,  0x0B,  0x11,  0x08,  0x10,  0x97,  0x08,  0x00,  0x08,  0xFE,  0x08,  0x10,  0x7F,  0xFF,  0x09, 	/* 38260 */
+	0x11,  0x09,  0xDD,  0x19,  0x11,  0x1C,  0xDC,  0x1A,  0x00,  0x28,  0xFC,  0x28,  0x00,  0x49,  0xFF,  0x08, 	/* 38270 */
+	0x20,  0x08,  0x3C,  0x08,  0x44,  0x08,  0x0C,  0x99,  0x08,  0x00,  0x09,  0xFF,  0x08,  0x28,  0x7F,  0xFE, 	/* 38280 */
+	0x08,  0xAA,  0x08,  0xAA,  0x1C,  0xFE,  0x1A,  0x00,  0x1A,  0xFC,  0x28,  0x00,  0x2B,  0xFF,  0x48,  0x50, 	/* 38290 */
+	0x08,  0x54,  0x08,  0x92,  0x09,  0x11,  0x08,  0x30,  0x9B,  0x08,  0x00,  0x0B,  0xDE,  0x08,  0xC6,  0x7F, 	/* 382A0 */
+	0x5A,  0x08,  0xC6,  0x09,  0x5A,  0x1C,  0x62,  0x1A,  0x30,  0x18,  0x48,  0x28,  0x94,  0x2B,  0x23,  0x48, 	/* 382B0 */
+	0xC8,  0x08,  0x32,  0x09,  0xC4,  0x08,  0x18,  0x09,  0xE0,  0x9E,  0x08,  0x00,  0x09,  0xFF,  0x09,  0x00, 	/* 382C0 */
+	0x7F,  0x3C,  0x09,  0x24,  0x09,  0x24,  0x1D,  0x3C,  0x1B,  0x00,  0x19,  0xEE,  0x29,  0xAA,  0x29,  0xAA, 	/* 382D0 */
+	0x49,  0xAA,  0x09,  0xEE,  0x09,  0x00,  0x09,  0xFF,  0x08,  0x00,  0x9F,  0x08,  0x20,  0x08,  0x20,  0x09, 	/* 382E0 */
+	0xFE,  0x7E,  0x88,  0x08,  0x50,  0x0B,  0xFF,  0x1C,  0x00,  0x1B,  0xFC,  0x19,  0x04,  0x29,  0xFC,  0x29, 	/* 382F0 */
+	0x04,  0x49,  0xFC,  0x08,  0x20,  0x0B,  0xFF,  0x08,  0x20,  0x08,  0x20,  0xA1,  0x08,  0x48,  0x08,  0x48, 	/* 38300 */
+	0x0B,  0xFF,  0x7E,  0x48,  0x08,  0x48,  0x08,  0xFC,  0x1C,  0x84,  0x1A,  0xFC,  0x1A,  0x84,  0x28,  0xFC, 	/* 38310 */
+	0x28,  0x20,  0x4B,  0xFF,  0x08,  0x20,  0x08,  0x50,  0x08,  0x8C,  0x0B,  0x03,  0xA2,  0x08,  0x20,  0x08, 	/* 38320 */
+	0x40,  0x08,  0xFC,  0x7E,  0x84,  0x08,  0xFC,  0x08,  0x84,  0x1C,  0xFC,  0x1A,  0x80,  0x1A,  0xFF,  0x28, 	/* 38330 */
+	0x80,  0x28,  0xFE,  0x48,  0x2A,  0x09,  0x96,  0x09,  0x52,  0x0A,  0x42,  0x08,  0x0C,  0xA3,  0x08,  0x84, 	/* 38340 */
+	0x08,  0x48,  0x09,  0xFE,  0x7E,  0x10,  0x08,  0xFC,  0x08,  0x10,  0x1B,  0xFF,  0x1C,  0x20,  0x1A,  0x18, 	/* 38350 */
+	0x28,  0x72,  0x28,  0x1A,  0x49,  0xDC,  0x08,  0x54,  0x08,  0x92,  0x0B,  0x11,  0x08,  0x30,  0xA9,  0x08, 	/* 38360 */
+	0x80,  0x08,  0x80,  0x08,  0xFE,  0x7F,  0x20,  0x09,  0x20,  0x0B,  0xFF,  0x18,  0x48,  0x1C,  0x50,  0x1A, 	/* 38370 */
+	0xFE,  0x28,  0x90,  0x29,  0xFE,  0x4A,  0x90,  0x08,  0xFE,  0x08,  0x90,  0x08,  0xFF,  0x08,  0x00,  0xAA, 	/* 38380 */
+	0x08,  0x88,  0x08,  0x88,  0x0B,  0xFE,  0x7E,  0x88,  0x08,  0x88,  0x0B,  0xFF,  0x1C,  0x20,  0x1B,  0xFC, 	/* 38390 */
+	0x19,  0x24,  0x29,  0xFC,  0x29,  0x24,  0x49,  0x24,  0x09,  0xFC,  0x08,  0x90,  0x09,  0x0C,  0x0E,  0x02, 	/* 383A0 */
+	0xAB,  0x10,  0x00,  0x13,  0xC0,  0x12,  0xBE,  0x7E,  0x92,  0x13,  0xD2,  0x12,  0x4C,  0x1B,  0xC8,  0x36, 	/* 383B0 */
+	0x94,  0x32,  0xA2,  0x33,  0xC1,  0x50,  0x20,  0x11,  0xFC,  0x10,  0x20,  0x10,  0x20,  0x17,  0xFF,  0x10, 	/* 383C0 */
+	0x00,  0xAE,  0x08,  0x00,  0x0B,  0xFF,  0x08,  0x50,  0x7E,  0x50,  0x09,  0xFE,  0x09,  0x52,  0x1D,  0x52, 	/* 383D0 */
+	0x1B,  0xFE,  0x29,  0x00,  0x28,  0x22,  0x48,  0xA2,  0x08,  0xA4,  0x09,  0x30,  0x08,  0x48,  0x09,  0x84, 	/* 383E0 */
+	0x0E,  0x02,  0xB5,  0x08,  0x44,  0x08,  0x48,  0x08,  0xFF,  0x7E,  0x90,  0x09,  0x90,  0x08,  0xFE,  0x18, 	/* 383F0 */
+	0x90,  0x1C,  0x90,  0x1A,  0xFE,  0x2A,  0x90,  0x28,  0x90,  0x48,  0xFF,  0x08,  0x00,  0x09,  0x52,  0x09, 	/* 38400 */
+	0x29,  0x0A,  0x29,  0xB6,  0x08,  0x00,  0x08,  0xFC,  0x08,  0x84,  0x7E,  0xFC,  0x08,  0x84,  0x08,  0xFC, 	/* 38410 */
+	0x1B,  0xFF,  0x1D,  0x20,  0x2B,  0xFE,  0x29,  0x2A,  0x49,  0xEA,  0x09,  0x24,  0x09,  0x24,  0x09,  0xEA, 	/* 38420 */
+	0x0B,  0x31,  0x08,  0x20,  0xB8,  0x08,  0x28,  0x08,  0xAA,  0x08,  0x6C,  0x7F,  0x28,  0x09,  0xFF,  0x08, 	/* 38430 */
+	0x44,  0x1C,  0x28,  0x1A,  0xFE,  0x29,  0x10,  0x28,  0x7C,  0x48,  0x10,  0x09,  0xFF,  0x08,  0x10,  0x08, 	/* 38440 */
+	0x28,  0x08,  0xC4,  0x0B,  0x03,  0xB9,  0x10,  0x84,  0x10,  0x84,  0x13,  0xE4,  0x7C,  0x84,  0x17,  0xFF, 	/* 38450 */
+	0x10,  0x04,  0x3B,  0xC4,  0x36,  0x64,  0x36,  0x54,  0x53,  0xD4,  0x50,  0x44,  0x12,  0x44,  0x11,  0xB4, 	/* 38460 */
+	0x11,  0xC4,  0x17,  0x04,  0x10,  0x0C,  0xBA,  0x08,  0x48,  0x08,  0x48,  0x0B,  0xFF,  0x7C,  0x48,  0x0B, 	/* 38470 */
+	0xFE,  0x08,  0xA4,  0x1C,  0xA4,  0x1B,  0xFF,  0x18,  0xA4,  0x28,  0xA4,  0x2B,  0xFE,  0x48,  0x20,  0x0B, 	/* 38480 */
+	0xFF,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0xBD,  0x08,  0x84,  0x08,  0x48,  0x09,  0xFF,  0x7E,  0x50, 	/* 38490 */
+	0x09,  0xFC,  0x09,  0x54,  0x1D,  0x9C,  0x1B,  0x04,  0x1B,  0xFC,  0x29,  0x04,  0x29,  0xFC,  0x48,  0x08, 	/* 384A0 */
+	0x0B,  0xFF,  0x08,  0x88,  0x08,  0x48,  0x08,  0x18,  0x84,  0x10,  0x08,  0x13,  0xE8,  0x11,  0x08,  0x7D, 	/* 384B0 */
+	0x0F,  0x17,  0xF2,  0x12,  0x52,  0x3A,  0x6A,  0x37,  0xCA,  0x32,  0x4A,  0x52,  0x4C,  0x53,  0xC4,  0x12, 	/* 384C0 */
+	0x44,  0x12,  0x4A,  0x13,  0xD2,  0x16,  0x61,  0x10,  0x41,  0x87,  0x08,  0x08,  0x09,  0xF0,  0x08,  0x20, 	/* 384D0 */
+	0x7E,  0x3C,  0x09,  0xE0,  0x08,  0x3C,  0x1D,  0xE2,  0x1A,  0x1E,  0x28,  0x44,  0x2B,  0xB8,  0x49,  0xCF, 	/* 384E0 */
+	0x0F,  0x38,  0x09,  0xCF,  0x0F,  0x38,  0x09,  0x29,  0x08,  0xE7,  0x88,  0x08,  0x20,  0x08,  0xFC,  0x08, 	/* 384F0 */
+	0x20,  0x7F,  0xFE,  0x08,  0x00,  0x0C,  0x44,  0x1B,  0xFF,  0x1A,  0x44,  0x28,  0x64,  0x29,  0x9F,  0x48, 	/* 38500 */
+	0x00,  0x0B,  0xFF,  0x08,  0x48,  0x08,  0x49,  0x08,  0x89,  0x0B,  0x07,  0x8B,  0x08,  0x0C,  0x09,  0xF0, 	/* 38510 */
+	0x08,  0x20,  0x7F,  0xFF,  0x08,  0x48,  0x08,  0xFC,  0x19,  0x4B,  0x1C,  0x78,  0x2A,  0x00,  0x2B,  0xFE, 	/* 38520 */
+	0x49,  0x02,  0x09,  0x7A,  0x09,  0x4A,  0x09,  0x7A,  0x09,  0x02,  0x09,  0x06,  0x98,  0x08,  0x00,  0x08, 	/* 38530 */
+	0xFC,  0x08,  0x48,  0x7E,  0x30,  0x09,  0xFE,  0x08,  0x54,  0x18,  0x90,  0x1D,  0x30,  0x1B,  0xFE,  0x29, 	/* 38540 */
+	0x52,  0x29,  0x56,  0x49,  0x9E,  0x09,  0x7A,  0x09,  0x4A,  0x09,  0x7A,  0x09,  0x06,  0x99,  0x08,  0xEA, 	/* 38550 */
+	0x08,  0x2C,  0x09,  0x29,  0x7E,  0xC6,  0x08,  0x44,  0x08,  0xFA,  0x1D,  0x01,  0x1A,  0xFC,  0x1A,  0x84, 	/* 38560 */
+	0x28,  0x84,  0x28,  0xFC,  0x48,  0x84,  0x08,  0x44,  0x08,  0x48,  0x0B,  0xFF,  0x08,  0x00,  0x9F,  0x08, 	/* 38570 */
+	0xA4,  0x08,  0xA4,  0x0B,  0x78,  0x7C,  0xA4,  0x08,  0xAA,  0x09,  0x7D,  0x1B,  0xE4,  0x1C,  0x22,  0x1B, 	/* 38580 */
+	0xFF,  0x28,  0x94,  0x28,  0x94,  0x48,  0xC8,  0x09,  0x29,  0x09,  0x15,  0x0A,  0x23,  0x0C,  0x41,  0xA1, 	/* 38590 */
+	0x08,  0x40,  0x08,  0x70,  0x08,  0x90,  0x7F,  0x20,  0x09,  0xFC,  0x09,  0x24,  0x1D,  0x24,  0x1B,  0xFC, 	/* 385A0 */
+	0x1A,  0x22,  0x28,  0xC4,  0x2B,  0x28,  0x48,  0xD8,  0x0B,  0x34,  0x08,  0xD2,  0x0B,  0x11,  0x08,  0x60, 	/* 385B0 */
+	0xA2,  0x10,  0x10,  0x13,  0x90,  0x12,  0xFF,  0x7E,  0x90,  0x13,  0x3E,  0x13,  0x48,  0x3A,  0xBF,  0x36, 	/* 385C0 */
+	0x80,  0x32,  0xBE,  0x52,  0xA2,  0x52,  0xBE,  0x13,  0xA2,  0x12,  0x3E,  0x12,  0x22,  0x12,  0x22,  0x12, 	/* 385D0 */
+	0x26,  0xA6,  0x08,  0x10,  0x08,  0xFE,  0x08,  0x44,  0x7F,  0x28,  0x09,  0xFF,  0x08,  0x00,  0x1C,  0xFE, 	/* 385E0 */
+	0x1A,  0x92,  0x1A,  0xFE,  0x28,  0x92,  0x28,  0xFE,  0x48,  0x10,  0x08,  0xFE,  0x08,  0x10,  0x0B,  0xFF, 	/* 385F0 */
+	0x08,  0x00,  0xB2,  0x08,  0x10,  0x09,  0xFF,  0x08,  0x10,  0x7E,  0xFE,  0x08,  0x00,  0x08,  0xFE,  0x1C, 	/* 38600 */
+	0x82,  0x1A,  0xFE,  0x1A,  0x44,  0x28,  0x28,  0x29,  0xFF,  0x48,  0x00,  0x08,  0xFE,  0x08,  0x82,  0x08, 	/* 38610 */
+	0xFE,  0x08,  0x00,  0xB8,  0x08,  0x00,  0x08,  0xFC,  0x08,  0x84,  0x7F,  0x84,  0x08,  0xFC,  0x08,  0x84, 	/* 38620 */
+	0x1C,  0xFC,  0x1A,  0x00,  0x28,  0x00,  0x2B,  0xDF,  0x4A,  0x51,  0x0B,  0xDF,  0x0A,  0x51,  0x0A,  0x51, 	/* 38630 */
+	0x0B,  0xDF,  0x08,  0x00,  0xBF,  0x08,  0x00,  0x0B,  0xFF,  0x08,  0x00,  0x7F,  0xFC,  0x09,  0x24,  0x19, 	/* 38640 */
+	0xFC,  0x1D,  0x24,  0x1B,  0xFF,  0x2A,  0x00,  0x29,  0xFC,  0x49,  0x24,  0x09,  0xFC,  0x09,  0x24,  0x09, 	/* 38650 */
+	0xFC,  0x08,  0x00,  0x0B,  0xFF,  0x80,  0x08,  0x20,  0x0B,  0xFF,  0x08,  0x00,  0x7F,  0xFE,  0x09,  0x7A, 	/* 38660 */
+	0x09,  0x4A,  0x1D,  0x7A,  0x1B,  0x02,  0x1B,  0xFE,  0x28,  0x84,  0x28,  0xFC,  0x48,  0x84,  0x08,  0xFC, 	/* 38670 */
+	0x08,  0x84,  0x0B,  0xFF,  0x08,  0x00,  0x84,  0x10,  0x88,  0x11,  0x08,  0x13,  0xC8,  0x7E,  0x4F,  0x13, 	/* 38680 */
+	0xD2,  0x12,  0x52,  0x33,  0xEA,  0x39,  0x0A,  0x37,  0xEA,  0x51,  0x0C,  0x51,  0xC4,  0x11,  0x44,  0x12, 	/* 38690 */
+	0x4E,  0x12,  0x4A,  0x14,  0x52,  0x11,  0xA1,  0x8D,  0x08,  0x20,  0x08,  0x20,  0x09,  0xFE,  0x7E,  0x84, 	/* 386A0 */
+	0x08,  0x48,  0x0B,  0xFF,  0x1C,  0x00,  0x1A,  0xFC,  0x1A,  0x84,  0x28,  0xFC,  0x28,  0x84,  0x48,  0xFC, 	/* 386B0 */
+	0x09,  0x50,  0x09,  0x4A,  0x0A,  0x45,  0x08,  0x3C,  0x8E,  0x08,  0x20,  0x08,  0x20,  0x08,  0x50,  0x7E, 	/* 386C0 */
+	0xA8,  0x09,  0xFC,  0x1B,  0x57,  0x1D,  0x24,  0x19,  0x54,  0x29,  0xFC,  0x28,  0x20,  0x4B,  0xFE,  0x0A, 	/* 386D0 */
+	0x22,  0x0A,  0x52,  0x0B,  0xEA,  0x0A,  0x02,  0x0A,  0x06,  0x90,  0x08,  0x40,  0x08,  0x78,  0x08,  0x90, 	/* 386E0 */
+	0x7F,  0xFF,  0x09,  0x2A,  0x09,  0xC6,  0x1D,  0x3C,  0x1B,  0x00,  0x29,  0xFF,  0x29,  0x00,  0x49,  0x7C, 	/* 386F0 */
+	0x09,  0x00,  0x0A,  0x7E,  0x0A,  0x42,  0x0C,  0x7E,  0x08,  0x00,  0x97,  0x00,  0x08,  0x1F,  0x08,  0x11, 	/* 38700 */
+	0x7E,  0x11,  0x22,  0x1F,  0x14,  0x10,  0x7F,  0x2F,  0x08,  0x29,  0x7E,  0x49,  0x08,  0x0F,  0x08,  0x00, 	/* 38710 */
+	0x80,  0x7F,  0xFF,  0x02,  0xA0,  0x0C,  0x98,  0x70,  0x87,  0x00,  0x80,  0x9C,  0x08,  0x20,  0x08,  0x30, 	/* 38720 */
+	0x08,  0x48,  0x7E,  0xF4,  0x0B,  0x03,  0x09,  0xFE,  0x1D,  0xA6,  0x1B,  0x6A,  0x19,  0xFE,  0x28,  0x00, 	/* 38730 */
+	0x28,  0xFC,  0x48,  0x84,  0x08,  0xFC,  0x08,  0x84,  0x08,  0xFC,  0x08,  0x00,  0xA0,  0x12,  0x10,  0x7F, 	/* 38740 */
+	0x90,  0x12,  0x3F,  0x1F,  0x24,  0x21,  0x44,  0x5D,  0x94,  0x15,  0x08,  0x1D,  0x34,  0x01,  0x42,  0x06, 	/* 38750 */
+	0x81,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0xA0,  0x0C,  0x98,  0x70,  0x87,  0x00,  0x80,  0xA2,  0x08,  0x10, 	/* 38760 */
+	0x08,  0x30,  0x08,  0x28,  0x7F,  0x48,  0x08,  0x84,  0x09,  0xFA,  0x1C,  0x01,  0x1B,  0xDE,  0x29,  0x52, 	/* 38770 */
+	0x29,  0x52,  0x49,  0xDE,  0x08,  0x88,  0x08,  0x88,  0x08,  0xCC,  0x09,  0x32,  0x0A,  0x22,  0xA3,  0x08, 	/* 38780 */
+	0x20,  0x08,  0x20,  0x0B,  0xFF,  0x7E,  0xA4,  0x08,  0xA6,  0x08,  0xE5,  0x1D,  0x28,  0x1B,  0xFF,  0x28, 	/* 38790 */
+	0x00,  0x29,  0xFE,  0x49,  0x7A,  0x09,  0x4A,  0x09,  0x7A,  0x09,  0x02,  0x09,  0xFE,  0x08,  0x00,  0xAA, 	/* 387A0 */
+	0x08,  0x10,  0x09,  0x21,  0x08,  0xBA,  0x7E,  0xAA,  0x08,  0x2C,  0x08,  0x78,  0x1C,  0xAC,  0x1A,  0xAA, 	/* 387B0 */
+	0x2B,  0x39,  0x28,  0x10,  0x49,  0xFF,  0x08,  0x38,  0x08,  0x54,  0x08,  0x92,  0x09,  0x11,  0x08,  0x10, 	/* 387C0 */
+	0xAC,  0x08,  0x48,  0x09,  0xFF,  0x08,  0x48,  0x7F,  0xFE,  0x09,  0x02,  0x19,  0x7A,  0x1C,  0x00,  0x1B, 	/* 387D0 */
+	0xFF,  0x2A,  0x40,  0x28,  0xAA,  0x4B,  0x6A,  0x08,  0x94,  0x0B,  0x34,  0x08,  0x52,  0x09,  0x91,  0x08, 	/* 387E0 */
+	0x30,  0xAE,  0x08,  0x20,  0x09,  0xFE,  0x08,  0x20,  0x7E,  0xFC,  0x08,  0x00,  0x09,  0xFF,  0x1C,  0x02, 	/* 387F0 */
+	0x1A,  0xF8,  0x18,  0x20,  0x2B,  0xFF,  0x28,  0x04,  0x4B,  0xFF,  0x09,  0x64,  0x09,  0x54,  0x09,  0xC4, 	/* 38800 */
+	0x08,  0x0C,  0xB3,  0x08,  0x20,  0x09,  0xFF,  0x09,  0x01,  0x7E,  0xFE,  0x08,  0xA4,  0x08,  0xA8,  0x19, 	/* 38810 */
+	0x30,  0x1C,  0xFC,  0x2B,  0x84,  0x2A,  0xFC,  0x48,  0x84,  0x08,  0xFC,  0x08,  0x84,  0x08,  0xFC,  0x08, 	/* 38820 */
+	0xCC,  0x0B,  0x02,  0xB8,  0x08,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x7E,  0x21,  0x09,  0x55,  0x19,  0x4A, 	/* 38830 */
+	0x1A,  0x39,  0x1D,  0xFD,  0x29,  0x54,  0x29,  0xFC,  0x48,  0x00,  0x0B,  0xFF,  0x08,  0x20,  0x08,  0x20, 	/* 38840 */
+	0x08,  0x20,  0x08,  0x60,  0xBB,  0x08,  0x04,  0x09,  0xE4,  0x09,  0x44,  0x7F,  0x4F,  0x09,  0xE8,  0x09, 	/* 38850 */
+	0x30,  0x1D,  0xE0,  0x1B,  0x5F,  0x29,  0x40,  0x29,  0xF0,  0x48,  0x00,  0x09,  0xFE,  0x09,  0x52,  0x09, 	/* 38860 */
+	0x52,  0x0B,  0xFF,  0x08,  0x00,  0x81,  0x08,  0x10,  0x08,  0x10,  0x09,  0xFF,  0x7F,  0x25,  0x09,  0x95, 	/* 38870 */
+	0x08,  0xAA,  0x19,  0x31,  0x1A,  0x62,  0x29,  0x9E,  0x28,  0x10,  0x48,  0xFE,  0x08,  0x92,  0x08,  0xFE, 	/* 38880 */
+	0x08,  0x14,  0x08,  0x3E,  0x0B,  0xC1,  0x82,  0x08,  0x00,  0x0B,  0xDE,  0x09,  0x4A,  0x7E,  0xD6,  0x09, 	/* 38890 */
+	0x4A,  0x0A,  0x52,  0x18,  0x48,  0x1C,  0x50,  0x2A,  0xFE,  0x29,  0x90,  0x4A,  0xFE,  0x08,  0x90,  0x08, 	/* 388A0 */
+	0xFE,  0x08,  0x90,  0x08,  0xFF,  0x08,  0x00,  0x83,  0x10,  0x00,  0x13,  0xFF,  0x12,  0x20,  0x7E,  0xFC, 	/* 388B0 */
+	0x12,  0xA4,  0x12,  0xFC,  0x3A,  0x20,  0x37,  0xFF,  0x32,  0x84,  0x52,  0xFC,  0x12,  0x84,  0x12,  0xFC, 	/* 388C0 */
+	0x12,  0x44,  0x13,  0x82,  0x13,  0xFF,  0x10,  0x00,  0x91,  0x08,  0x00,  0x08,  0xFC,  0x08,  0xA4,  0x7E, 	/* 388D0 */
+	0xFC,  0x08,  0xA4,  0x18,  0xA4,  0x1C,  0xFC,  0x1A,  0x00,  0x2B,  0xFF,  0x2A,  0xB5,  0x4A,  0xB5,  0x0B, 	/* 388E0 */
+	0xFF,  0x0A,  0xB5,  0x0A,  0xB5,  0x0B,  0xFF,  0x08,  0x00,  0x93,  0x08,  0x10,  0x08,  0x3C,  0x08,  0x48, 	/* 388F0 */
+	0x7F,  0xFE,  0x08,  0x92,  0x08,  0xFE,  0x1C,  0x92,  0x1A,  0xFE,  0x18,  0xAA,  0x29,  0x15,  0x28,  0xFE, 	/* 38900 */
+	0x48,  0x82,  0x08,  0xFE,  0x08,  0x82,  0x08,  0xFE,  0x08,  0x00,  0x9A,  0x10,  0x00,  0x13,  0xDE,  0x12, 	/* 38910 */
+	0x52,  0x7F,  0xDE,  0x12,  0x52,  0x13,  0xDE,  0x3A,  0x02,  0x36,  0xFA,  0x52,  0x8A,  0x52,  0xFA,  0x12, 	/* 38920 */
+	0x42,  0x12,  0xFA,  0x12,  0x8A,  0x12,  0xFA,  0x12,  0x02,  0x12,  0x06,  0x9B,  0x11,  0x10,  0x11,  0x10, 	/* 38930 */
+	0x11,  0xDF,  0x7A,  0xA8,  0x12,  0x44,  0x14,  0x00,  0x33,  0xDE,  0x3A,  0x52,  0x37,  0xD2,  0x52,  0x52, 	/* 38940 */
+	0x53,  0xD2,  0x12,  0x12,  0x12,  0x92,  0x13,  0xDC,  0x16,  0x50,  0x10,  0x50,  0x9E,  0x11,  0x08,  0x11, 	/* 38950 */
+	0x0E,  0x11,  0x12,  0x7E,  0x5C,  0x12,  0x84,  0x19,  0x7F,  0x35,  0x10,  0x32,  0xAA,  0x3F,  0xCA,  0x51, 	/* 38960 */
+	0x14,  0x55,  0x2C,  0x15,  0x4E,  0x15,  0x56,  0x15,  0x65,  0x19,  0x04,  0x11,  0x18,  0x9F,  0x08,  0x92, 	/* 38970 */
+	0x08,  0xA2,  0x08,  0xBA,  0x7F,  0x6D,  0x09,  0x6D,  0x08,  0xBA,  0x1C,  0xAA,  0x1B,  0x7D,  0x29,  0xD7, 	/* 38980 */
+	0x28,  0x10,  0x49,  0xFF,  0x08,  0x38,  0x08,  0x54,  0x08,  0x92,  0x09,  0x11,  0x08,  0x10,  0xA8,  0x10, 	/* 38990 */
+	0x20,  0x10,  0x3C,  0x10,  0x20,  0x13,  0xFE,  0x7E,  0x44,  0x13,  0xF8,  0x12,  0x42,  0x3A,  0xFE,  0x36, 	/* 389A0 */
+	0xA4,  0x32,  0xFC,  0x52,  0xA4,  0x54,  0xFC,  0x15,  0xFE,  0x19,  0x52,  0x17,  0xFF,  0x10,  0x00,  0xAA, 	/* 389B0 */
+	0x08,  0x00,  0x09,  0xFF,  0x09,  0x12,  0x7F,  0x6C,  0x09,  0x24,  0x0D,  0xFF,  0x1D,  0x34,  0x1B,  0x6E, 	/* 389C0 */
+	0x29,  0xB5,  0x29,  0x24,  0x49,  0x48,  0x0A,  0x4F,  0x0A,  0x48,  0x0C,  0x48,  0x09,  0xFF,  0x08,  0x00, 	/* 389D0 */
+	0xBA,  0x08,  0x00,  0x09,  0xFE,  0x08,  0x10,  0x7F,  0xFF,  0x09,  0x11,  0x09,  0xDD,  0x1D,  0x11,  0x1A, 	/* 389E0 */
+	0xDC,  0x28,  0x10,  0x28,  0x00,  0x49,  0xFF,  0x09,  0x6D,  0x09,  0x6D,  0x09,  0x6D,  0x09,  0xFF,  0x08, 	/* 389F0 */
+	0x00,  0xBB,  0x10,  0x00,  0x13,  0xDE,  0x12,  0x52,  0x7F,  0xDE,  0x12,  0x52,  0x13,  0xDE,  0x3A,  0x52, 	/* 38A00 */
+	0x37,  0xDE,  0x35,  0x54,  0x52,  0x22,  0x50,  0x40,  0x17,  0xFF,  0x10,  0x88,  0x11,  0xF0,  0x10,  0xD8, 	/* 38A10 */
+	0x17,  0x04,  0x84,  0x10,  0x00,  0x13,  0xDE,  0x12,  0x52,  0x7F,  0xDE,  0x12,  0x52,  0x13,  0xDE,  0x3A, 	/* 38A20 */
+	0x22,  0x37,  0xFE,  0x52,  0xAA,  0x52,  0xFA,  0x12,  0xAA,  0x12,  0xFA,  0x12,  0x72,  0x12,  0xAA,  0x13, 	/* 38A30 */
+	0x22,  0x12,  0x26,  0x85,  0x08,  0x20,  0x08,  0x76,  0x08,  0xA2,  0x7E,  0xF6,  0x08,  0xAA,  0x08,  0xEE, 	/* 38A40 */
+	0x1D,  0xFF,  0x1A,  0xCC,  0x19,  0x72,  0x2A,  0x11,  0x28,  0xFE,  0x48,  0x10,  0x09,  0xFF,  0x08,  0x10, 	/* 38A50 */
+	0x08,  0x10,  0x08,  0x30,  0x8A,  0x08,  0x48,  0x0B,  0xFF,  0x08,  0x48,  0x7F,  0xEF,  0x09,  0x29,  0x09, 	/* 38A60 */
+	0xEF,  0x1C,  0x48,  0x1A,  0x90,  0x29,  0xFF,  0x2A,  0x90,  0x48,  0xFE,  0x08,  0x90,  0x08,  0xFE,  0x08, 	/* 38A70 */
+	0x90,  0x08,  0xFF,  0x08,  0x00,  0x92,  0x10,  0x04,  0x13,  0xC4,  0x68,  0x1A,  0x17,  0xE4,  0x28,  0x0A, 	/* 38A80 */
+	0x7F,  0xDF,  0x10,  0x04,  0x3B,  0xD6,  0x56,  0x65,  0x13,  0xC4,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0xA0, 	/* 38A90 */
+	0x0C,  0x98,  0x70,  0x87,  0x00,  0x80,  0x96,  0x13,  0xE8,  0x12,  0x8F,  0x13,  0xD0,  0x7E,  0x6E,  0x13, 	/* 38AA0 */
+	0xDF,  0x12,  0x95,  0x3B,  0xFF,  0x35,  0x04,  0x31,  0xFC,  0x51,  0x04,  0x51,  0xFC,  0x11,  0x04,  0x11, 	/* 38AB0 */
+	0xFC,  0x10,  0x51,  0x11,  0x91,  0x16,  0x0F,  0x9D,  0x12,  0x48,  0x7D,  0xBF,  0x12,  0x4C,  0x39,  0x9A, 	/* 38AC0 */
+	0x56,  0x69,  0x3F,  0xFC,  0x24,  0x44,  0x3F,  0xFC,  0x1E,  0x08,  0x12,  0xFF,  0x1E,  0x08,  0x12,  0x88, 	/* 38AD0 */
+	0x1E,  0x48,  0x14,  0x08,  0x1A,  0x08,  0x61,  0x18,  0x9F,  0x11,  0x40,  0x11,  0x5E,  0x17,  0xF2,  0x79, 	/* 38AE0 */
+	0x52,  0x13,  0xFE,  0x1A,  0xB2,  0x37,  0xFE,  0x31,  0x52,  0x53,  0xF2,  0x56,  0x9E,  0x13,  0xCC,  0x12, 	/* 38AF0 */
+	0x8C,  0x13,  0xD4,  0x12,  0x95,  0x13,  0xE5,  0x10,  0x43,  0xA0,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00, 	/* 38B00 */
+	0x08,  0x00,  0x0F,  0xFF,  0x10,  0x82,  0x10,  0x84,  0x20,  0x88,  0x40,  0x80,  0x01,  0x40,  0x01,  0x40, 	/* 38B10 */
+	0x02,  0x20,  0x02,  0x10,  0x04,  0x08,  0x18,  0x04,  0x60,  0x03,  0xA1,  0x01,  0x00,  0x01,  0x00,  0x21, 	/* 38B20 */
+	0x00,  0x21,  0x00,  0x11,  0xFF,  0x11,  0x21,  0x02,  0x22,  0x02,  0x24,  0x14,  0x20,  0x10,  0x20,  0x20, 	/* 38B30 */
+	0x50,  0x20,  0x50,  0x40,  0x88,  0x41,  0x04,  0x46,  0x02,  0x18,  0x01,  0xA3,  0x02,  0x20,  0x04,  0x20, 	/* 38B40 */
+	0x38,  0x20,  0x20,  0x3F,  0x20,  0x42,  0x3F,  0x54,  0x24,  0x90,  0x25,  0x10,  0x24,  0x10,  0x24,  0x18, 	/* 38B50 */
+	0x24,  0x28,  0x24,  0x28,  0x24,  0x24,  0x24,  0x44,  0x44,  0x82,  0x07,  0x01,  0xA7,  0x00,  0x20,  0x3F, 	/* 38B60 */
+	0xA0,  0x21,  0x20,  0x21,  0x3F,  0x31,  0x51,  0x2A,  0x52,  0x26,  0x94,  0x22,  0x10,  0x26,  0x10,  0x25, 	/* 38B70 */
+	0x30,  0x29,  0x28,  0x29,  0x28,  0x30,  0x44,  0x3F,  0xC4,  0x00,  0x82,  0x01,  0x01,  0xB2,  0x0A,  0x20, 	/* 38B80 */
+	0x0A,  0x20,  0x09,  0x20,  0x11,  0x3F,  0x15,  0x52,  0x24,  0x54,  0x0A,  0x98,  0x0A,  0x10,  0x11,  0x10, 	/* 38B90 */
+	0x20,  0x90,  0x5F,  0x28,  0x11,  0x28,  0x11,  0x24,  0x11,  0x44,  0x1F,  0x82,  0x01,  0x01,  0xB7,  0x01, 	/* 38BA0 */
+	0x20,  0x32,  0x20,  0x0C,  0x20,  0x1A,  0x3F,  0x65,  0x41,  0x04,  0x52,  0x7F,  0x94,  0x08,  0x10,  0x18, 	/* 38BB0 */
+	0x10,  0x3F,  0x10,  0x69,  0x28,  0x29,  0x28,  0x29,  0x24,  0x2A,  0x44,  0x08,  0x82,  0x09,  0x01,  0xB8, 	/* 38BC0 */
+	0x08,  0x20,  0x0A,  0x20,  0x09,  0x20,  0x12,  0xFF,  0x7C,  0x41,  0x08,  0x92,  0x0F,  0x94,  0x14,  0x10, 	/* 38BD0 */
+	0x24,  0x10,  0x7F,  0x90,  0x04,  0x28,  0x06,  0x28,  0x09,  0x24,  0x09,  0x44,  0x10,  0x82,  0x21,  0x01, 	/* 38BE0 */
+	0xB9,  0x04,  0x20,  0x04,  0x20,  0x3F,  0x20,  0x04,  0x3F,  0x0A,  0x41,  0x31,  0x52,  0x00,  0x94,  0x7F, 	/* 38BF0 */
+	0x90,  0x01,  0x10,  0x3D,  0x10,  0x25,  0x28,  0x25,  0x28,  0x3D,  0x24,  0x01,  0x44,  0x01,  0x42,  0x03, 	/* 38C00 */
+	0x81,  0xBA,  0x11,  0x20,  0x11,  0x20,  0x7F,  0xA0,  0x11,  0x3F,  0x11,  0x22,  0x1F,  0x54,  0x11,  0x50, 	/* 38C10 */
+	0x11,  0x90,  0x1F,  0x10,  0x11,  0x10,  0x11,  0x18,  0x7F,  0xA8,  0x12,  0x24,  0x11,  0x44,  0x20,  0x82, 	/* 38C20 */
+	0x43,  0x01,  0xBD,  0x08,  0x40,  0x08,  0x40,  0x14,  0x40,  0x12,  0x7F,  0x21,  0x42,  0x7E,  0x94,  0x08, 	/* 38C30 */
+	0x90,  0x09,  0x10,  0x7F,  0x10,  0x08,  0x18,  0x4A,  0x18,  0x2C,  0x28,  0x29,  0x24,  0x0E,  0x44,  0x18, 	/* 38C40 */
+	0x82,  0x63,  0x01,  0xBE,  0x08,  0x20,  0x08,  0x20,  0x7F,  0x20,  0x08,  0x3F,  0x08,  0x42,  0x3F,  0x54, 	/* 38C50 */
+	0x00,  0x90,  0x3F,  0x10,  0x00,  0x10,  0x7F,  0x90,  0x08,  0x28,  0x2A,  0x28,  0x29,  0x24,  0x49,  0x44, 	/* 38C60 */
+	0x08,  0x82,  0x19,  0x01,  0x83,  0x00,  0xA0,  0x03,  0x20,  0x3C,  0x20,  0x04,  0x7F,  0x04,  0x42,  0x7F, 	/* 38C70 */
+	0x54,  0x04,  0x90,  0x0C,  0x10,  0x35,  0x90,  0x24,  0x98,  0x24,  0x98,  0x35,  0xA8,  0x24,  0xA4,  0x24, 	/* 38C80 */
+	0xC4,  0x3F,  0xC2,  0x00,  0x81,  0x87,  0x00,  0x20,  0x3E,  0x20,  0x22,  0x20,  0x3E,  0x7F,  0x22,  0x42, 	/* 38C90 */
+	0x22,  0x54,  0x3E,  0x90,  0x08,  0x10,  0x1F,  0x10,  0x29,  0x18,  0x6D,  0x18,  0x2B,  0x28,  0x31,  0x24, 	/* 38CA0 */
+	0x3D,  0x44,  0x02,  0x42,  0x0C,  0x81,  0x89,  0x09,  0x10,  0x12,  0x10,  0x7F,  0xD0,  0x0A,  0x1F,  0x3F, 	/* 38CB0 */
+	0xA1,  0x0A,  0xAA,  0x7F,  0xCC,  0x0A,  0x88,  0x3F,  0x88,  0x0A,  0x08,  0x1B,  0x0C,  0x1A,  0x94,  0x2A, 	/* 38CC0 */
+	0x94,  0x4A,  0x22,  0x0A,  0x42,  0x0A,  0x81,  0x8C,  0x00,  0x40,  0x7F,  0xC0,  0x02,  0x40,  0x3A,  0x7F, 	/* 38CD0 */
+	0x2A,  0x52,  0x2A,  0x54,  0x3A,  0x90,  0x06,  0x90,  0x7F,  0x10,  0x02,  0x10,  0x3A,  0x28,  0x2A,  0x28, 	/* 38CE0 */
+	0x2A,  0x44,  0x3A,  0x44,  0x02,  0x82,  0x07,  0x01,  0x8E,  0x12,  0x20,  0x7F,  0xA0,  0x12,  0x20,  0x10, 	/* 38CF0 */
+	0x3F,  0x3F,  0x22,  0x29,  0x54,  0x29,  0x50,  0x3F,  0x90,  0x08,  0x10,  0x3F,  0x10,  0x08,  0x18,  0x7F, 	/* 38D00 */
+	0xA8,  0x0C,  0x24,  0x12,  0x44,  0x20,  0x82,  0x41,  0x01,  0x90,  0x00,  0x10,  0x3F,  0x90,  0x20,  0x10, 	/* 38D10 */
+	0x2F,  0x1F,  0x29,  0x21,  0x29,  0x2A,  0x2F,  0x48,  0x20,  0x08,  0x3D,  0xC8,  0x35,  0x48,  0x35,  0x54, 	/* 38D20 */
+	0x35,  0x54,  0x3D,  0xD4,  0x20,  0x22,  0x3F,  0xC2,  0x00,  0x81,  0x93,  0x10,  0x20,  0x10,  0x20,  0x1F, 	/* 38D30 */
+	0xA0,  0x24,  0x3F,  0x44,  0x21,  0x7F,  0xD2,  0x09,  0x54,  0x12,  0x90,  0x1F,  0x90,  0x32,  0x10,  0x5F, 	/* 38D40 */
+	0x28,  0x12,  0x28,  0x1F,  0x24,  0x12,  0x44,  0x1F,  0x82,  0x01,  0x01,  0x94,  0x04,  0x10,  0x07,  0x10, 	/* 38D50 */
+	0x04,  0x10,  0x3F,  0xBF,  0x25,  0x21,  0x3E,  0xAA,  0x24,  0xCC,  0x23,  0x88,  0x24,  0x08,  0x35,  0x48, 	/* 38D60 */
+	0x35,  0x4C,  0x3D,  0xD4,  0x25,  0x14,  0x25,  0xA2,  0x46,  0x42,  0x18,  0x81,  0x99,  0x04,  0x10,  0x0A, 	/* 38D70 */
+	0x10,  0x11,  0x10,  0x6E,  0xDF,  0x00,  0x11,  0x1F,  0x2A,  0x11,  0x2A,  0x1F,  0x48,  0x00,  0x08,  0x7F, 	/* 38D80 */
+	0x88,  0x19,  0x8C,  0x6E,  0x94,  0x19,  0x94,  0x6E,  0xA2,  0x08,  0xC2,  0x19,  0x81,  0x9B,  0x04,  0x10, 	/* 38D90 */
+	0x04,  0x10,  0x0A,  0x10,  0x09,  0x1F,  0x10,  0xA1,  0x3E,  0xAA,  0x40,  0x4C,  0x3B,  0x88,  0x2A,  0x88, 	/* 38DA0 */
+	0x2A,  0x88,  0x3B,  0x8C,  0x11,  0x14,  0x11,  0x94,  0x1A,  0x62,  0x26,  0x42,  0x44,  0x81,  0x9F,  0x14, 	/* 38DB0 */
+	0x10,  0x15,  0x90,  0x26,  0x90,  0x24,  0x9F,  0x35,  0xB1,  0x26,  0xAA,  0x2A,  0xEC,  0x3B,  0x88,  0x2A, 	/* 38DC0 */
+	0x88,  0x2A,  0x88,  0x2A,  0x94,  0x7F,  0xD4,  0x00,  0x14,  0x0A,  0x22,  0x11,  0x42,  0x60,  0x81,  0xA1, 	/* 38DD0 */
+	0x11,  0x10,  0x7F,  0xD0,  0x11,  0x10,  0x3B,  0x9F,  0x2A,  0xA1,  0x3B,  0xAA,  0x10,  0x4C,  0x12,  0x88, 	/* 38DE0 */
+	0x3F,  0x88,  0x64,  0x08,  0x3F,  0x8C,  0x24,  0x14,  0x3F,  0x94,  0x24,  0x22,  0x3F,  0xC2,  0x00,  0x81, 	/* 38DF0 */
+	0xA2,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x08,  0x80,  0x08,  0x80,  0x08,  0xFC,  0x08, 	/* 38E00 */
+	0x80,  0x08,  0x80,  0x08,  0x80,  0x08,  0x80,  0x08,  0x80,  0x08,  0x80,  0x08,  0x80,  0x7F,  0xFF,  0x00, 	/* 38E10 */
+	0x00,  0xA3,  0x00,  0x00,  0x3F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x08,  0x80, 	/* 38E20 */
+	0x08,  0xFC,  0x08,  0x80,  0x08,  0x80,  0x08,  0x80,  0x08,  0x80,  0x08,  0x80,  0x08,  0x80,  0x7F,  0xFF, 	/* 38E30 */
+	0x00,  0x00,  0xA4,  0x04,  0x40,  0x04,  0x40,  0x04,  0x40,  0x24,  0x40,  0x24,  0x44,  0x24,  0x44,  0x27, 	/* 38E40 */
+	0xC8,  0x24,  0x50,  0x24,  0x60,  0x24,  0x40,  0x24,  0x40,  0x24,  0x42,  0x24,  0xC2,  0x27,  0x42,  0x3C, 	/* 38E50 */
+	0x3E,  0x60,  0x00,  0xA6,  0x00,  0x24,  0x1F,  0xA2,  0x00,  0x22,  0x00,  0x20,  0x7F,  0xFF,  0x02,  0x20, 	/* 38E60 */
+	0x02,  0x20,  0x12,  0x20,  0x13,  0xE0,  0x12,  0x10,  0x12,  0x10,  0x12,  0x10,  0x13,  0xCA,  0x1E,  0x0A, 	/* 38E70 */
+	0x70,  0x06,  0x00,  0x02,  0xA9,  0x00,  0x80,  0x08,  0x80,  0x08,  0xFC,  0x08,  0x80,  0x08,  0x80,  0x7F, 	/* 38E80 */
+	0xFF,  0x00,  0x80,  0x04,  0x90,  0x04,  0x88,  0x08,  0x84,  0x10,  0x8A,  0x21,  0x92,  0x00,  0x20,  0x00, 	/* 38E90 */
+	0xC0,  0x03,  0x00,  0x1C,  0x00,  0xAA,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x40,  0x00,  0x80,  0x03,  0xF0, 	/* 38EA0 */
+	0x0C,  0x8C,  0x70,  0x82,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x08,  0x80,  0x08,  0xF8,  0x08,  0x80, 	/* 38EB0 */
+	0x08,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0xAF,  0x00,  0x80,  0x08,  0x80,  0x08,  0xFC,  0x08,  0x80,  0x08, 	/* 38EC0 */
+	0x80,  0x7F,  0xFF,  0x14,  0x94,  0x12,  0xA4,  0x10,  0x84,  0x1F,  0xFC,  0x11,  0xC4,  0x12,  0xA4,  0x14, 	/* 38ED0 */
+	0x94,  0x10,  0x84,  0x1F,  0xFC,  0x00,  0x00,  0xB3,  0x00,  0x80,  0x08,  0x80,  0x08,  0xFE,  0x08,  0x80, 	/* 38EE0 */
+	0x7F,  0xFF,  0x00,  0x24,  0x00,  0x22,  0x1F,  0xFE,  0x10,  0x20,  0x17,  0xD2,  0x11,  0x14,  0x15,  0x88, 	/* 38EF0 */
+	0x15,  0x4D,  0x29,  0x15,  0x23,  0x23,  0x40,  0xC1,  0xB4,  0x00,  0x00,  0x1F,  0xFF,  0x11,  0x08,  0x11, 	/* 38F00 */
+	0x08,  0x1F,  0xFF,  0x13,  0x8C,  0x15,  0x5A,  0x19,  0x29,  0x11,  0x08,  0x11,  0x48,  0x12,  0x40,  0x12, 	/* 38F10 */
+	0x7E,  0x22,  0x40,  0x22,  0x40,  0x5F,  0xFF,  0x00,  0x00,  0xB8,  0x04,  0x00,  0x08,  0x7C,  0x3E,  0x04, 	/* 38F20 */
+	0x22,  0xFF,  0x3E,  0x04,  0x20,  0x7C,  0x3E,  0x00,  0x22,  0xFF,  0x3E,  0x91,  0x08,  0x91,  0x28,  0x7E, 	/* 38F30 */
+	0x2E,  0x52,  0x28,  0x52,  0x2E,  0x5C,  0x38,  0x50,  0x60,  0x10,  0xB9,  0x00,  0x00,  0x7F,  0xFF,  0x01, 	/* 38F40 */
+	0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0xF8,  0x02,  0x08,  0x02,  0x08,  0x05,  0x90,  0x08,  0x50,  0x10, 	/* 38F50 */
+	0x20,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x03,  0x00,  0x0C,  0x00,  0xBB,  0x00,  0x00,  0x7F,  0xFF, 	/* 38F60 */
+	0x08,  0x40,  0x08,  0x40,  0x0F,  0x44,  0x09,  0x44,  0x11,  0x48,  0x11,  0x50,  0x2A,  0x60,  0x46,  0x40, 	/* 38F70 */
+	0x04,  0x40,  0x04,  0x40,  0x08,  0x42,  0x10,  0x42,  0x20,  0x3E,  0x40,  0x00,  0xBF,  0x00,  0x20,  0x7F, 	/* 38F80 */
+	0x20,  0x10,  0x3E,  0x10,  0x22,  0x10,  0x42,  0x1E,  0x42,  0x12,  0x8C,  0x22,  0x00,  0x33,  0xFC,  0x4C, 	/* 38F90 */
+	0x44,  0x04,  0x44,  0x08,  0x28,  0x08,  0x10,  0x10,  0x28,  0x20,  0xC4,  0x43,  0x03,  0x80,  0x00,  0x04, 	/* 38FA0 */
+	0x7F,  0x18,  0x10,  0xF0,  0x10,  0x10,  0x10,  0x10,  0x1E,  0x10,  0x13,  0xFF,  0x22,  0x10,  0x32,  0x10, 	/* 38FB0 */
+	0x4C,  0x28,  0x04,  0x28,  0x08,  0x28,  0x08,  0x44,  0x10,  0x44,  0x20,  0x82,  0x41,  0x01,  0x83,  0x00, 	/* 38FC0 */
+	0x10,  0x7F,  0x10,  0x10,  0x10,  0x10,  0xFE,  0x10,  0x92,  0x1E,  0x92,  0x12,  0x92,  0x22,  0x92,  0x33, 	/* 38FD0 */
+	0xFF,  0x4C,  0x10,  0x04,  0x18,  0x08,  0x28,  0x08,  0x24,  0x10,  0x44,  0x21,  0x82,  0x46,  0x01,  0x84, 	/* 38FE0 */
+	0x00,  0x10,  0x7F,  0x10,  0x10,  0x28,  0x10,  0x28,  0x10,  0x44,  0x1E,  0x8A,  0x13,  0x11,  0x22,  0x20, 	/* 38FF0 */
+	0x32,  0xC4,  0x4C,  0x08,  0x04,  0x31,  0x09,  0xC2,  0x08,  0x04,  0x10,  0x18,  0x20,  0x60,  0x41,  0x80, 	/* 39000 */
+	0x86,  0x00,  0x20,  0x7F,  0x20,  0x10,  0x20,  0x10,  0x48,  0x1E,  0x44,  0x12,  0x44,  0x12,  0x9E,  0x33, 	/* 39010 */
+	0xE2,  0x2A,  0x02,  0x44,  0xFC,  0x04,  0x84,  0x08,  0x84,  0x08,  0x84,  0x10,  0x84,  0x20,  0xFC,  0x40, 	/* 39020 */
+	0x00,  0x89,  0x00,  0x40,  0x7F,  0x40,  0x10,  0x7E,  0x10,  0x42,  0x10,  0x82,  0x1E,  0xF2,  0x13,  0x92, 	/* 39030 */
+	0x22,  0x92,  0x32,  0xF2,  0x4C,  0x92,  0x04,  0x92,  0x08,  0xF2,  0x08,  0x02,  0x10,  0x02,  0x20,  0x04, 	/* 39040 */
+	0x40,  0x18,  0x8A,  0x00,  0x10,  0x7F,  0x50,  0x10,  0x50,  0x10,  0x7E,  0x1E,  0x90,  0x12,  0x90,  0x13, 	/* 39050 */
+	0x10,  0x33,  0xFF,  0x2A,  0x38,  0x44,  0x38,  0x04,  0x54,  0x04,  0x54,  0x08,  0x92,  0x09,  0x11,  0x10, 	/* 39060 */
+	0x10,  0x20,  0x10,  0x8B,  0x00,  0x20,  0x7F,  0x24,  0x10,  0x22,  0x10,  0x22,  0x11,  0xFF,  0x1E,  0x20, 	/* 39070 */
+	0x12,  0xFE,  0x22,  0x20,  0x32,  0x20,  0x4D,  0xFF,  0x04,  0x12,  0x08,  0x0C,  0x08,  0x19,  0x10,  0x25, 	/* 39080 */
+	0x20,  0xC3,  0x43,  0x01,  0x8D,  0x00,  0x02,  0x7F,  0x0C,  0x10,  0xF4,  0x10,  0xA2,  0x10,  0x91,  0x1F, 	/* 39090 */
+	0x11,  0x12,  0xFE,  0x22,  0x04,  0x32,  0x08,  0x4C,  0x10,  0x05,  0xFF,  0x08,  0x10,  0x08,  0x10,  0x10, 	/* 390A0 */
+	0x10,  0x20,  0x10,  0x40,  0x30,  0x95,  0x00,  0x20,  0x7F,  0x20,  0x11,  0xFE,  0x10,  0x84,  0x10,  0x44, 	/* 390B0 */
+	0x1E,  0x48,  0x12,  0x48,  0x23,  0xFF,  0x32,  0x00,  0x4C,  0x00,  0x04,  0xFC,  0x08,  0x84,  0x08,  0x84, 	/* 390C0 */
+	0x10,  0x84,  0x20,  0xFC,  0x40,  0x00,  0x96,  0x00,  0x08,  0x7F,  0x08,  0x08,  0xFF,  0x08,  0x08,  0x08, 	/* 390D0 */
+	0x3E,  0x1E,  0xA2,  0x12,  0xA2,  0x12,  0xBE,  0x2A,  0xA2,  0x44,  0xBE,  0x04,  0xA2,  0x08,  0xA2,  0x08, 	/* 390E0 */
+	0xBE,  0x10,  0x80,  0x20,  0xFF,  0x40,  0x00,  0x98,  0x00,  0x28,  0x7F,  0x24,  0x10,  0x3E,  0x11,  0xE0, 	/* 390F0 */
+	0x10,  0x14,  0x1E,  0x39,  0x13,  0xC7,  0x22,  0x21,  0x32,  0x28,  0x4C,  0x24,  0x04,  0x3E,  0x0B,  0xD0, 	/* 39100 */
+	0x08,  0x14,  0x10,  0x19,  0x20,  0x67,  0x43,  0x81,  0x9E,  0x00,  0x00,  0x7F,  0xFE,  0x10,  0x82,  0x10, 	/* 39110 */
+	0x82,  0x10,  0xFE,  0x1E,  0x00,  0x12,  0xFE,  0x22,  0x82,  0x32,  0xFE,  0x4C,  0x82,  0x04,  0xFE,  0x08, 	/* 39120 */
+	0x82,  0x08,  0xFE,  0x10,  0x24,  0x20,  0xC2,  0x43,  0x01,  0xA4,  0x00,  0x40,  0x7F,  0x7E,  0x10,  0x80, 	/* 39130 */
+	0x11,  0x7C,  0x10,  0x44,  0x1E,  0x7C,  0x12,  0x44,  0x22,  0x7C,  0x32,  0x00,  0x4D,  0xFF,  0x04,  0x40, 	/* 39140 */
+	0x08,  0xFE,  0x09,  0x4A,  0x10,  0x92,  0x21,  0x22,  0x40,  0x4C,  0xAA,  0x00,  0x10,  0x7F,  0xFF,  0x10, 	/* 39150 */
+	0x10,  0x10,  0xFE,  0x10,  0x00,  0x1E,  0xFF,  0x12,  0x81,  0x22,  0xFD,  0x32,  0x00,  0x4C,  0xFE,  0x04, 	/* 39160 */
+	0x82,  0x08,  0xFE,  0x08,  0x44,  0x10,  0x28,  0x21,  0xFF,  0x40,  0x00,  0xAB,  0x00,  0x00,  0x7F,  0xEF, 	/* 39170 */
+	0x11,  0x29,  0x11,  0xEF,  0x10,  0x00,  0x1E,  0xFE,  0x12,  0x92,  0x22,  0xFE,  0x32,  0x92,  0x4C,  0x92, 	/* 39180 */
+	0x04,  0xFE,  0x08,  0x10,  0x09,  0xFF,  0x10,  0x10,  0x20,  0x10,  0x40,  0x10,  0xAF,  0x00,  0x10,  0x7F, 	/* 39190 */
+	0xFF,  0x11,  0x01,  0x10,  0xFE,  0x10,  0x12,  0x1E,  0x54,  0x13,  0x98,  0x22,  0x7E,  0x32,  0xC2,  0x4D, 	/* 391A0 */
+	0x7E,  0x04,  0x42,  0x08,  0x7E,  0x08,  0x42,  0x10,  0x7E,  0x20,  0x26,  0x41,  0xC1,  0xB1,  0x00,  0x88, 	/* 391B0 */
+	0x7E,  0x8C,  0x13,  0xEA,  0x10,  0x8A,  0x10,  0x88,  0x1F,  0xFF,  0x15,  0x48,  0x27,  0x6A,  0x25,  0x4A, 	/* 391C0 */
+	0x5B,  0x6A,  0x09,  0x44,  0x0B,  0x6C,  0x11,  0x4D,  0x11,  0xF5,  0x27,  0x23,  0x40,  0x41,  0xB2,  0x01, 	/* 391D0 */
+	0x28,  0x7F,  0x2C,  0x11,  0xAA,  0x12,  0x5A,  0x12,  0x88,  0x1F,  0xFF,  0x15,  0x48,  0x27,  0x6A,  0x25, 	/* 391E0 */
+	0x4A,  0x5B,  0x6A,  0x09,  0x44,  0x0B,  0x6C,  0x11,  0x4D,  0x11,  0xF5,  0x27,  0x23,  0x40,  0x41,  0xB3, 	/* 391F0 */
+	0x00,  0x00,  0x07,  0xE0,  0x04,  0x20,  0x04,  0x22,  0x04,  0x22,  0x08,  0x22,  0x10,  0x1E,  0x20,  0x00, 	/* 39200 */
+	0x0F,  0xF0,  0x02,  0x10,  0x02,  0x20,  0x01,  0x40,  0x00,  0x80,  0x03,  0x60,  0x0C,  0x18,  0x70,  0x07, 	/* 39210 */
+	0xB4,  0x00,  0x00,  0x3F,  0xBC,  0x21,  0x24,  0x21,  0x24,  0x32,  0x25,  0x2A,  0x45,  0x26,  0x83,  0x22, 	/* 39220 */
+	0xFC,  0x26,  0x44,  0x25,  0x44,  0x29,  0x28,  0x29,  0x28,  0x30,  0x10,  0x3F,  0xA8,  0x00,  0xC4,  0x03, 	/* 39230 */
+	0x03,  0xB5,  0x02,  0x00,  0x04,  0xF8,  0x38,  0x88,  0x20,  0x88,  0x20,  0x8A,  0x3C,  0x8A,  0x21,  0x06, 	/* 39240 */
+	0x22,  0x00,  0x3D,  0xF8,  0x20,  0x88,  0x20,  0x88,  0x3E,  0x50,  0x60,  0x20,  0x20,  0x50,  0x21,  0x8C, 	/* 39250 */
+	0x26,  0x03,  0xB7,  0x02,  0x00,  0x1C,  0x3C,  0x10,  0x24,  0x1F,  0x24,  0x11,  0x25,  0x1F,  0x25,  0x11, 	/* 39260 */
+	0x43,  0x11,  0x80,  0x1F,  0x7C,  0x10,  0x24,  0x1F,  0x24,  0x21,  0x14,  0x21,  0x08,  0x41,  0x14,  0x02, 	/* 39270 */
+	0x62,  0x0D,  0x81,  0xBA,  0x02,  0x00,  0x22,  0xF8,  0x14,  0x88,  0x08,  0x88,  0x14,  0x8A,  0x62,  0x8A, 	/* 39280 */
+	0x09,  0x06,  0x0A,  0x00,  0x7F,  0xF8,  0x08,  0x48,  0x1C,  0x48,  0x1A,  0x28,  0x2A,  0x10,  0x48,  0x28, 	/* 39290 */
+	0x08,  0xC4,  0x0B,  0x03,  0xBB,  0x08,  0x00,  0x08,  0x3C,  0x7F,  0x24,  0x08,  0x24,  0x08,  0x25,  0x3E, 	/* 392A0 */
+	0x45,  0x00,  0x83,  0x7F,  0xFC,  0x40,  0x84,  0x5E,  0xA4,  0x12,  0x24,  0x12,  0x18,  0x12,  0x88,  0x13, 	/* 392B0 */
+	0x14,  0x22,  0x62,  0x41,  0x81,  0xBC,  0x08,  0x00,  0x08,  0x3C,  0x7F,  0xA4,  0x08,  0x24,  0x3F,  0x25, 	/* 392C0 */
+	0x00,  0x45,  0x7F,  0x83,  0x40,  0x80,  0x3F,  0x7E,  0x00,  0x22,  0x1E,  0x24,  0x12,  0x14,  0x12,  0x88, 	/* 392D0 */
+	0x13,  0x14,  0x22,  0x62,  0x41,  0x81,  0xBF,  0x00,  0x00,  0x3F,  0x3C,  0x21,  0x24,  0x21,  0x24,  0x3F, 	/* 392E0 */
+	0x25,  0x2A,  0x25,  0x2A,  0x23,  0x3F,  0x40,  0x2A,  0xFC,  0x2A,  0x24,  0x3F,  0x94,  0x20,  0x18,  0x2A, 	/* 392F0 */
+	0x08,  0x49,  0x14,  0x11,  0x22,  0x20,  0xC1,  0x80,  0x08,  0x00,  0x33,  0x3C,  0x21,  0x24,  0x21,  0x25, 	/* 39300 */
+	0x3B,  0x25,  0x21,  0x43,  0x21,  0x80,  0x3F,  0xFC,  0x04,  0x04,  0x04,  0x24,  0x3F,  0x24,  0x04,  0x18, 	/* 39310 */
+	0x04,  0x18,  0x07,  0x24,  0x1C,  0xC2,  0x63,  0x01,  0x85,  0x04,  0x00,  0x04,  0x3C,  0x3F,  0xA4,  0x11, 	/* 39320 */
+	0x24,  0x0A,  0x25,  0x7F,  0xA5,  0x08,  0x43,  0x14,  0x80,  0x25,  0x7C,  0x0B,  0x24,  0x13,  0x24,  0x26, 	/* 39330 */
+	0x94,  0x0A,  0x48,  0x12,  0x14,  0x22,  0x62,  0x0D,  0x81,  0x86,  0x00,  0x00,  0x3F,  0xBC,  0x20,  0x24, 	/* 39340 */
+	0x27,  0x24,  0x25,  0x25,  0x25,  0x45,  0x27,  0x83,  0x20,  0x00,  0x3D,  0xFE,  0x35,  0x52,  0x35,  0x52, 	/* 39350 */
+	0x35,  0x4C,  0x3D,  0xCC,  0x20,  0x14,  0x3F,  0xA2,  0x00,  0xC1,  0x8B,  0x00,  0x00,  0x0F,  0xF8,  0x08, 	/* 39360 */
+	0x88,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x7F,  0xFF,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x08, 	/* 39370 */
+	0x88,  0x08,  0x88,  0x1F,  0xFF,  0x10,  0x08,  0x00,  0x10,  0x00,  0x60,  0x8D,  0x00,  0x00,  0x07,  0xF8, 	/* 39380 */
+	0x04,  0x08,  0x05,  0x08,  0x04,  0x88,  0x04,  0x88,  0x04,  0x08,  0x7F,  0xFF,  0x09,  0x08,  0x08,  0x88, 	/* 39390 */
+	0x08,  0x48,  0x08,  0x48,  0x1F,  0xFE,  0x10,  0x10,  0x00,  0x10,  0x00,  0x60,  0x8E,  0x08,  0x00,  0x08, 	/* 393A0 */
+	0x00,  0x0F,  0xFE,  0x10,  0x00,  0x17,  0xF8,  0x24,  0x88,  0x44,  0x88,  0x04,  0x88,  0x7F,  0xFF,  0x08, 	/* 393B0 */
+	0x88,  0x08,  0x88,  0x08,  0x88,  0x1F,  0xFC,  0x10,  0x08,  0x00,  0x10,  0x00,  0x60,  0x92,  0x00,  0x80, 	/* 393C0 */
+	0x1F,  0xFC,  0x00,  0x80,  0x0F,  0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x07,  0xF8,  0x04,  0x88, 	/* 393D0 */
+	0x04,  0x88,  0x7F,  0xFF,  0x08,  0x88,  0x08,  0x88,  0x1F,  0xFE,  0x10,  0x10,  0x00,  0x60,  0x93,  0x10, 	/* 393E0 */
+	0x10,  0x10,  0x10,  0x3F,  0xFF,  0x20,  0x28,  0x5F,  0x24,  0x11,  0x4E,  0x19,  0xF1,  0x15,  0x00,  0x7F, 	/* 393F0 */
+	0x54,  0x29,  0x54,  0x25,  0x54,  0x25,  0x54,  0x7F,  0x54,  0x42,  0x55,  0x02,  0x95,  0x0D,  0x03,  0x94, 	/* 39400 */
+	0x10,  0x40,  0x10,  0x40,  0x10,  0x40,  0x10,  0x44,  0x10,  0x44,  0x10,  0x48,  0x1F,  0x50,  0x10,  0x60, 	/* 39410 */
+	0x10,  0x40,  0x10,  0x40,  0x10,  0x40,  0x10,  0x40,  0x11,  0x40,  0x16,  0x41,  0x18,  0x21,  0x60,  0x1F, 	/* 39420 */
+	0x98,  0x00,  0x00,  0x1F,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x1F,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x1F, 	/* 39430 */
+	0xF8,  0x00,  0x00,  0x10,  0x44,  0x10,  0x48,  0x1F,  0x70,  0x10,  0x40,  0x10,  0x42,  0x1F,  0x42,  0x70, 	/* 39440 */
+	0x3E,  0x9B,  0x00,  0x10,  0x00,  0x60,  0x1F,  0x80,  0x01,  0x00,  0x01,  0x00,  0x01,  0x1C,  0x03,  0xE0, 	/* 39450 */
+	0x3D,  0x00,  0x01,  0x00,  0x01,  0x0F,  0x07,  0xF0,  0x79,  0x00,  0x01,  0x00,  0x01,  0x02,  0x00,  0x82, 	/* 39460 */
+	0x00,  0x7E,  0x9F,  0x00,  0x80,  0x02,  0x90,  0x04,  0x8C,  0x18,  0x82,  0x61,  0x91,  0x00,  0x60,  0x03, 	/* 39470 */
+	0x80,  0x7C,  0x18,  0x07,  0xE0,  0x00,  0x80,  0x00,  0xF8,  0x1F,  0x80,  0x00,  0xFE,  0x3F,  0x81,  0x00, 	/* 39480 */
+	0x81,  0x00,  0x7F,  0xAB,  0x01,  0x00,  0x7F,  0xFE,  0x00,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0, 	/* 39490 */
+	0x00,  0x00,  0x7F,  0xFE,  0x40,  0x22,  0x4F,  0xC2,  0x01,  0x00,  0x01,  0xF8,  0x3F,  0x00,  0x01,  0xFD, 	/* 394A0 */
+	0x7F,  0x01,  0x00,  0xFF,  0xAC,  0x02,  0x10,  0x0C,  0x14,  0x78,  0x12,  0x09,  0xFF,  0x08,  0x10,  0x0F, 	/* 394B0 */
+	0x92,  0x78,  0x52,  0x08,  0x5C,  0x08,  0x18,  0x0F,  0x34,  0x78,  0x52,  0x09,  0x91,  0x08,  0x10,  0x08, 	/* 394C0 */
+	0x31,  0x04,  0x01,  0x03,  0xFF,  0xAF,  0x02,  0x10,  0x0C,  0x52,  0x78,  0x52,  0x08,  0xAC,  0x08,  0x28, 	/* 394D0 */
+	0x0F,  0x44,  0x78,  0x82,  0x08,  0x10,  0x08,  0x52,  0x0F,  0x52,  0x78,  0xAC,  0x08,  0x28,  0x08,  0x44, 	/* 394E0 */
+	0x08,  0x83,  0x04,  0x01,  0x03,  0xFF,  0xB3,  0x00,  0x20,  0x0F,  0xC0,  0x02,  0x00,  0x03,  0xF0,  0x3E, 	/* 394F0 */
+	0x00,  0x03,  0xF4,  0x3E,  0x04,  0x01,  0xFC,  0x02,  0x08,  0x3C,  0x70,  0x0F,  0x1C,  0x78,  0x70,  0x0F, 	/* 39500 */
+	0x1E,  0x78,  0xF1,  0x08,  0x91,  0x07,  0x8F,  0x88,  0x04,  0x02,  0x7F,  0xC4,  0x2E,  0xB8,  0x2A,  0x90, 	/* 39510 */
+	0x2E,  0x90,  0x20,  0x9E,  0x3F,  0xF0,  0x00,  0x10,  0x1F,  0x10,  0x11,  0x1F,  0x1F,  0xF0,  0x11,  0x10, 	/* 39520 */
+	0x1F,  0x10,  0x00,  0x11,  0x7F,  0xD1,  0x00,  0x0F,  0x8F,  0x00,  0x08,  0x00,  0x70,  0x0F,  0xC0,  0x08, 	/* 39530 */
+	0x40,  0x08,  0x40,  0x08,  0x40,  0x08,  0x5E,  0x0F,  0xE0,  0x08,  0x40,  0x08,  0x20,  0x08,  0x20,  0x08, 	/* 39540 */
+	0x10,  0x08,  0x09,  0x0B,  0x85,  0x1C,  0x03,  0x60,  0x01,  0x91,  0x00,  0x00,  0x1F,  0xFC,  0x10,  0x04, 	/* 39550 */
+	0x10,  0x04,  0x10,  0x04,  0x1F,  0xFC,  0x10,  0x80,  0x10,  0x80,  0x1F,  0xFF,  0x10,  0x40,  0x10,  0x40, 	/* 39560 */
+	0x10,  0x20,  0x10,  0x20,  0x13,  0x12,  0x1C,  0x0A,  0x60,  0x06,  0x93,  0x08,  0x00,  0x08,  0xFE,  0x08, 	/* 39570 */
+	0x82,  0x3F,  0x82,  0x20,  0x82,  0x20,  0xFE,  0x20,  0x88,  0x20,  0x88,  0x20,  0xFF,  0x20,  0x88,  0x22, 	/* 39580 */
+	0x88,  0x22,  0x88,  0x1E,  0x85,  0x00,  0xB5,  0x00,  0xC3,  0x03,  0x01,  0x94,  0x08,  0x00,  0x08,  0x00, 	/* 39590 */
+	0x0F,  0xFE,  0x10,  0x00,  0x17,  0xF8,  0x20,  0x00,  0x40,  0x00,  0x1F,  0xF8,  0x00,  0x08,  0x00,  0x08, 	/* 395A0 */
+	0x00,  0x08,  0x00,  0x08,  0x00,  0x05,  0x00,  0x05,  0x00,  0x03,  0x00,  0x01,  0x97,  0x08,  0x00,  0x08, 	/* 395B0 */
+	0x00,  0x0F,  0xFE,  0x10,  0x00,  0x17,  0xF8,  0x20,  0x00,  0x40,  0x00,  0x1F,  0xF8,  0x00,  0x48,  0x0C, 	/* 395C0 */
+	0x48,  0x02,  0x88,  0x01,  0x88,  0x02,  0x45,  0x04,  0x25,  0x18,  0x03,  0x60,  0x01,  0x9B,  0x08,  0x00, 	/* 395D0 */
+	0x08,  0x00,  0x0F,  0xFE,  0x10,  0x00,  0x17,  0xF8,  0x20,  0x00,  0x5F,  0xF8,  0x03,  0xC8,  0x08,  0x48, 	/* 395E0 */
+	0x08,  0x28,  0x17,  0xD8,  0x22,  0x58,  0x42,  0x45,  0x04,  0x45,  0x08,  0x43,  0x11,  0x81,  0xA3,  0x08, 	/* 395F0 */
+	0x00,  0x08,  0x00,  0x0F,  0xFE,  0x10,  0x00,  0x1F,  0xF8,  0x20,  0x00,  0x5F,  0xF8,  0x02,  0x08,  0x12, 	/* 39600 */
+	0x48,  0x0A,  0x88,  0x7F,  0xF8,  0x07,  0x08,  0x0A,  0x85,  0x12,  0x45,  0x22,  0x23,  0x02,  0x01,  0xA4, 	/* 39610 */
+	0x08,  0x00,  0x08,  0x00,  0x0F,  0xFE,  0x10,  0x00,  0x17,  0xF8,  0x20,  0x00,  0x5F,  0xF8,  0x00,  0x08, 	/* 39620 */
+	0x3F,  0xE8,  0x22,  0x28,  0x3F,  0xE8,  0x22,  0x28,  0x25,  0x25,  0x28,  0xA5,  0x3F,  0xE3,  0x00,  0x01, 	/* 39630 */
+	0xB4,  0x00,  0x80,  0x00,  0x80,  0x00,  0x84,  0x00,  0x84,  0x00,  0x88,  0x7E,  0xD0,  0x02,  0xE0,  0x02, 	/* 39640 */
+	0xC0,  0x04,  0xA0,  0x04,  0xA0,  0x08,  0x90,  0x10,  0x88,  0x20,  0x84,  0x40,  0x83,  0x00,  0x80,  0x01, 	/* 39650 */
+	0x80,  0xB7,  0x00,  0x80,  0x00,  0x80,  0x10,  0x82,  0x08,  0x82,  0x04,  0x84,  0x00,  0xC8,  0x7E,  0xD0, 	/* 39660 */
+	0x02,  0xA0,  0x04,  0xA0,  0x04,  0x90,  0x08,  0x88,  0x10,  0x84,  0x20,  0x82,  0x40,  0x81,  0x00,  0x80, 	/* 39670 */
+	0x01,  0x80,  0xB8,  0x03,  0x00,  0x00,  0x80,  0x00,  0x40,  0x07,  0x80,  0x00,  0x84,  0x00,  0x84,  0x3E, 	/* 39680 */
+	0xC8,  0x02,  0xD0,  0x02,  0xA0,  0x04,  0xA0,  0x04,  0x90,  0x08,  0x88,  0x10,  0x84,  0x60,  0x83,  0x00, 	/* 39690 */
+	0x80,  0x01,  0x80,  0xBE,  0x10,  0x00,  0x09,  0xFC,  0x09,  0x04,  0x01,  0x04,  0x41,  0x04,  0x21,  0x04, 	/* 396A0 */
+	0x21,  0x04,  0x01,  0x04,  0x05,  0x18,  0x05,  0x00,  0x09,  0x00,  0x09,  0x00,  0x11,  0x01,  0x10,  0x81, 	/* 396B0 */
+	0x20,  0x7F,  0x20,  0x00,  0x80,  0x10,  0x00,  0x08,  0x00,  0x0B,  0xFF,  0x00,  0x10,  0x00,  0x10,  0x40, 	/* 396C0 */
+	0x10,  0x20,  0x10,  0x20,  0x10,  0x08,  0x10,  0x08,  0x10,  0x10,  0x10,  0x10,  0x10,  0x20,  0x10,  0x20, 	/* 396D0 */
+	0x10,  0x40,  0x10,  0x40,  0x30,  0x81,  0x10,  0x20,  0x08,  0x20,  0x08,  0x20,  0x00,  0x20,  0x00,  0x20, 	/* 396E0 */
+	0x40,  0x20,  0x27,  0xFF,  0x20,  0x20,  0x08,  0x20,  0x08,  0x20,  0x10,  0x20,  0x10,  0x20,  0x20,  0x20, 	/* 396F0 */
+	0x20,  0x20,  0x40,  0x20,  0x40,  0x20,  0x82,  0x00,  0x90,  0x00,  0x88,  0x00,  0x88,  0x7F,  0xFF,  0x00, 	/* 39700 */
+	0x80,  0x10,  0x84,  0x08,  0xC4,  0x04,  0xC4,  0x04,  0xA8,  0x00,  0xA8,  0x01,  0x90,  0x02,  0x88,  0x04, 	/* 39710 */
+	0x84,  0x18,  0x82,  0x60,  0x81,  0x01,  0x80,  0x8E,  0x10,  0x00,  0x09,  0xF8,  0x09,  0x08,  0x01,  0x08, 	/* 39720 */
+	0x41,  0x08,  0x21,  0x88,  0x21,  0x48,  0x05,  0x48,  0x05,  0x28,  0x09,  0x28,  0x09,  0x08,  0x11,  0x08, 	/* 39730 */
+	0x12,  0x08,  0x22,  0x09,  0x24,  0x09,  0x28,  0x07,  0x90,  0x10,  0x20,  0x08,  0x20,  0x08,  0x20,  0x00, 	/* 39740 */
+	0x3E,  0x40,  0x42,  0x20,  0x42,  0x20,  0x82,  0x01,  0x44,  0x0A,  0x24,  0x08,  0x18,  0x10,  0x08,  0x10, 	/* 39750 */
+	0x10,  0x20,  0x20,  0x20,  0x40,  0x41,  0x80,  0x46,  0x00,  0x95,  0x10,  0x20,  0x08,  0x20,  0x08,  0x20, 	/* 39760 */
+	0x00,  0x20,  0x02,  0x22,  0x42,  0x22,  0x22,  0x22,  0x22,  0x22,  0x0A,  0x22,  0x0A,  0x22,  0x12,  0x22, 	/* 39770 */
+	0x12,  0x22,  0x22,  0x22,  0x22,  0x22,  0x43,  0xFE,  0x40,  0x00,  0x97,  0x10,  0x00,  0x0B,  0xFE,  0x08, 	/* 39780 */
+	0x20,  0x00,  0x20,  0x00,  0x20,  0x40,  0x20,  0x20,  0x20,  0x27,  0xFF,  0x08,  0x20,  0x08,  0x20,  0x10, 	/* 39790 */
+	0x20,  0x10,  0x20,  0x20,  0x20,  0x20,  0x20,  0x40,  0x20,  0x40,  0x20,  0x9A,  0x10,  0x00,  0x0B,  0xFC, 	/* 397A0 */
+	0x08,  0x40,  0x00,  0x40,  0x00,  0x40,  0x4F,  0xFF,  0x20,  0x80,  0x20,  0x80,  0x08,  0x80,  0x09,  0xFC, 	/* 397B0 */
+	0x11,  0x04,  0x10,  0x04,  0x20,  0x04,  0x20,  0x04,  0x40,  0x08,  0x40,  0x30,  0x9D,  0x10,  0x40,  0x08, 	/* 397C0 */
+	0x40,  0x08,  0x40,  0x00,  0x40,  0x4F,  0xFF,  0x20,  0x88,  0x20,  0x88,  0x00,  0x88,  0x09,  0x08,  0x09, 	/* 397D0 */
+	0x10,  0x13,  0xD0,  0x12,  0x20,  0x20,  0x50,  0x20,  0x88,  0x43,  0x04,  0x4C,  0x02,  0x9E,  0x00,  0x00, 	/* 397E0 */
+	0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x00,  0x80,  0x00,  0x84,  0x3E,  0xC4, 	/* 397F0 */
+	0x02,  0xC8,  0x04,  0xB0,  0x04,  0x90,  0x08,  0x8C,  0x10,  0x83,  0x60,  0x80,  0x01,  0x80,  0x9F,  0x10, 	/* 39800 */
+	0x00,  0x08,  0x00,  0x0B,  0xFC,  0x00,  0x20,  0x40,  0x20,  0x20,  0x20,  0x20,  0x20,  0x00,  0x20,  0x08, 	/* 39810 */
+	0x20,  0x08,  0x20,  0x10,  0x20,  0x10,  0x20,  0x20,  0x20,  0x2F,  0xFE,  0x40,  0x00,  0x40,  0x00,  0xA0, 	/* 39820 */
+	0x10,  0x10,  0x08,  0x90,  0x08,  0x90,  0x00,  0x92,  0x00,  0x9E,  0x40,  0xF2,  0x27,  0x92,  0x20,  0x92, 	/* 39830 */
+	0x08,  0x92,  0x08,  0x92,  0x10,  0x9C,  0x10,  0x90,  0x20,  0x80,  0x20,  0x81,  0x40,  0x41,  0x40,  0x3F, 	/* 39840 */
+	0xA2,  0x10,  0x20,  0x08,  0x20,  0x08,  0x20,  0x00,  0x20,  0x00,  0x20,  0x40,  0x20,  0x23,  0xFE,  0x20, 	/* 39850 */
+	0x20,  0x08,  0x20,  0x08,  0x20,  0x10,  0x20,  0x10,  0x20,  0x20,  0x20,  0x20,  0x20,  0x47,  0xFF,  0x40, 	/* 39860 */
+	0x00,  0xA8,  0x10,  0x00,  0x0B,  0xFC,  0x0A,  0x04,  0x02,  0x04,  0x02,  0x04,  0x42,  0x04,  0x22,  0x04, 	/* 39870 */
+	0x23,  0xFC,  0x0A,  0x04,  0x0A,  0x04,  0x12,  0x04,  0x12,  0x04,  0x22,  0x04,  0x22,  0x04,  0x43,  0xFC, 	/* 39880 */
+	0x40,  0x00,  0xAA,  0x10,  0x00,  0x0B,  0xFE,  0x08,  0x20,  0x00,  0x20,  0x00,  0x20,  0x40,  0x20,  0x20, 	/* 39890 */
+	0x20,  0x21,  0xFC,  0x08,  0x20,  0x08,  0x20,  0x10,  0x20,  0x10,  0x20,  0x20,  0x20,  0x20,  0x20,  0x47, 	/* 398A0 */
+	0xFF,  0x40,  0x00,  0xB0,  0x10,  0x40,  0x08,  0x40,  0x08,  0x40,  0x00,  0x40,  0x00,  0x40,  0x4F,  0xFF, 	/* 398B0 */
+	0x20,  0x60,  0x20,  0xA0,  0x08,  0xA0,  0x08,  0x90,  0x11,  0x10,  0x11,  0x88,  0x21,  0x48,  0x22,  0x44, 	/* 398C0 */
+	0x44,  0x02,  0x48,  0x01,  0xB2,  0x10,  0x00,  0x0B,  0xF8,  0x08,  0x88,  0x00,  0x88,  0x40,  0x90,  0x20, 	/* 398D0 */
+	0x9C,  0x20,  0x84,  0x00,  0xC4,  0x09,  0x48,  0x09,  0x28,  0x11,  0x30,  0x11,  0x10,  0x22,  0x28,  0x22, 	/* 398E0 */
+	0x44,  0x44,  0x82,  0x4B,  0x01,  0xB3,  0x10,  0x00,  0x09,  0xFE,  0x09,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 398F0 */
+	0x41,  0xFC,  0x21,  0x44,  0x21,  0x44,  0x09,  0x48,  0x09,  0x28,  0x11,  0x30,  0x12,  0x10,  0x22,  0x28, 	/* 39900 */
+	0x24,  0x44,  0x49,  0x82,  0x46,  0x01,  0xBA,  0x10,  0x40,  0x08,  0x40,  0x08,  0x40,  0x07,  0xFC,  0x40, 	/* 39910 */
+	0x44,  0x20,  0x44,  0x20,  0x44,  0x00,  0x44,  0x0F,  0xFF,  0x08,  0x40,  0x10,  0xA0,  0x10,  0xA0,  0x21, 	/* 39920 */
+	0x10,  0x22,  0x08,  0x44,  0x04,  0x48,  0x03,  0xBD,  0x11,  0x00,  0x09,  0x00,  0x09,  0xFE,  0x02,  0x00, 	/* 39930 */
+	0x02,  0xF8,  0x44,  0x00,  0x20,  0x00,  0x27,  0xF8,  0x00,  0x08,  0x08,  0x08,  0x10,  0x08,  0x10,  0x08, 	/* 39940 */
+	0x20,  0x05,  0x20,  0x05,  0x40,  0x03,  0x40,  0x01,  0xBE,  0x10,  0x78,  0x08,  0x08,  0x08,  0x88,  0x00, 	/* 39950 */
+	0x88,  0x00,  0x84,  0x41,  0x04,  0x22,  0x02,  0x25,  0xFD,  0x00,  0x24,  0x08,  0x24,  0x10,  0x24,  0x10, 	/* 39960 */
+	0x44,  0x20,  0x44,  0x20,  0x84,  0x41,  0x04,  0x42,  0x18,  0x81,  0x10,  0x80,  0x08,  0x40,  0x08,  0x20, 	/* 39970 */
+	0x00,  0x20,  0x40,  0x80,  0x20,  0x80,  0x20,  0x80,  0x00,  0x88,  0x0A,  0x84,  0x0A,  0x82,  0x12,  0x81, 	/* 39980 */
+	0x14,  0x81,  0x24,  0x84,  0x28,  0x84,  0x40,  0x44,  0x40,  0x3C,  0x82,  0x10,  0x04,  0x08,  0x18,  0x09, 	/* 39990 */
+	0xE0,  0x01,  0x00,  0x01,  0x00,  0x41,  0x00,  0x21,  0xFF,  0x21,  0x08,  0x09,  0x08,  0x09,  0x08,  0x11, 	/* 399A0 */
+	0x08,  0x11,  0x08,  0x22,  0x08,  0x22,  0x08,  0x44,  0x08,  0x40,  0x08,  0x83,  0x10,  0x04,  0x08,  0x18, 	/* 399B0 */
+	0x0B,  0xE0,  0x00,  0x20,  0x00,  0x20,  0x40,  0x20,  0x27,  0xFF,  0x20,  0x20,  0x08,  0x30,  0x08,  0x50, 	/* 399C0 */
+	0x10,  0x50,  0x10,  0x88,  0x20,  0x88,  0x21,  0x04,  0x42,  0x02,  0x44,  0x01,  0x88,  0x10,  0x40,  0x08, 	/* 399D0 */
+	0x40,  0x08,  0x40,  0x07,  0xFE,  0x04,  0x42,  0x44,  0x42,  0x24,  0x42,  0x20,  0x60,  0x08,  0x60,  0x08, 	/* 399E0 */
+	0xA0,  0x10,  0xA0,  0x11,  0x20,  0x21,  0x20,  0x22,  0x21,  0x44,  0x11,  0x48,  0x0F,  0x8C,  0x10,  0x40, 	/* 399F0 */
+	0x08,  0x44,  0x08,  0x58,  0x07,  0xE0,  0x00,  0x40,  0x42,  0x44,  0x22,  0x44,  0x22,  0x44,  0x0A,  0x44, 	/* 39A00 */
+	0x0A,  0x44,  0x13,  0xFC,  0x10,  0x40,  0x20,  0x40,  0x20,  0x42,  0x40,  0x22,  0x40,  0x1E,  0x8D,  0x10, 	/* 39A10 */
+	0x00,  0x0B,  0xFE,  0x08,  0x80,  0x00,  0x80,  0x00,  0x80,  0x40,  0xF8,  0x20,  0x88,  0x20,  0x88,  0x09, 	/* 39A20 */
+	0x08,  0x09,  0x08,  0x11,  0xF0,  0x10,  0x10,  0x20,  0x10,  0x20,  0x10,  0x4F,  0xFF,  0x40,  0x00,  0x90, 	/* 39A30 */
+	0x10,  0x20,  0x08,  0x20,  0x08,  0x20,  0x00,  0x20,  0x07,  0xFF,  0x40,  0x30,  0x20,  0x70,  0x20,  0x68, 	/* 39A40 */
+	0x08,  0xA8,  0x08,  0xA4,  0x11,  0x24,  0x12,  0x22,  0x24,  0x21,  0x20,  0x20,  0x40,  0x20,  0x40,  0x20, 	/* 39A50 */
+	0x92,  0x10,  0x80,  0x08,  0x80,  0x08,  0xFC,  0x00,  0x84,  0x01,  0x04,  0x41,  0x04,  0x22,  0x18,  0x20, 	/* 39A60 */
+	0x00,  0x0B,  0xF8,  0x08,  0x88,  0x10,  0x88,  0x10,  0x50,  0x20,  0x20,  0x20,  0x50,  0x41,  0x8C,  0x46, 	/* 39A70 */
+	0x03,  0x93,  0x00,  0x80,  0x00,  0x84,  0x3E,  0xC8,  0x02,  0xD0,  0x04,  0xA0,  0x08,  0x90,  0x10,  0x8C, 	/* 39A80 */
+	0x61,  0x83,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8, 	/* 39A90 */
+	0x00,  0x00,  0x96,  0x10,  0x20,  0x08,  0x20,  0x08,  0x20,  0x03,  0xFE,  0x42,  0x22,  0x22,  0x22,  0x22, 	/* 39AA0 */
+	0x22,  0x02,  0x22,  0x0B,  0xFE,  0x08,  0x20,  0x10,  0x20,  0x10,  0x20,  0x20,  0x20,  0x20,  0x20,  0x40, 	/* 39AB0 */
+	0x20,  0x40,  0x20,  0x99,  0x10,  0x20,  0x08,  0x20,  0x08,  0x20,  0x01,  0x28,  0x41,  0x24,  0x21,  0x22, 	/* 39AC0 */
+	0x22,  0x22,  0x02,  0x21,  0x0C,  0x25,  0x08,  0x64,  0x10,  0x08,  0x10,  0x10,  0x20,  0x20,  0x20,  0x40, 	/* 39AD0 */
+	0x41,  0x80,  0x4E,  0x00,  0x9A,  0x10,  0x20,  0x08,  0x20,  0x08,  0x20,  0x00,  0x20,  0x01,  0x20,  0x41, 	/* 39AE0 */
+	0x20,  0x21,  0x3E,  0x21,  0x20,  0x09,  0x20,  0x09,  0x20,  0x11,  0x20,  0x11,  0x20,  0x21,  0x20,  0x21, 	/* 39AF0 */
+	0x20,  0x4F,  0xFF,  0x40,  0x00,  0x9B,  0x10,  0x40,  0x08,  0x40,  0x08,  0x40,  0x0F,  0xFF,  0x00,  0x40, 	/* 39B00 */
+	0x40,  0x40,  0x23,  0xFC,  0x22,  0x44,  0x0A,  0x44,  0x0A,  0x44,  0x12,  0x44,  0x12,  0x44,  0x22,  0x58, 	/* 39B10 */
+	0x20,  0x40,  0x40,  0x40,  0x40,  0x40,  0xA1,  0x10,  0x00,  0x09,  0xF0,  0x09,  0x10,  0x01,  0x12,  0x01, 	/* 39B20 */
+	0x12,  0x41,  0x12,  0x22,  0x0E,  0x24,  0x00,  0x03,  0xF8,  0x08,  0x88,  0x10,  0x90,  0x10,  0x50,  0x20, 	/* 39B30 */
+	0x20,  0x20,  0x50,  0x41,  0x8C,  0x46,  0x03,  0xA2,  0x10,  0x00,  0x09,  0xFC,  0x09,  0x04,  0x01,  0x04, 	/* 39B40 */
+	0x41,  0x04,  0x21,  0x04,  0x21,  0xFC,  0x01,  0x20,  0x09,  0x20,  0x09,  0x20,  0x11,  0x10,  0x12,  0x10, 	/* 39B50 */
+	0x22,  0x08,  0x24,  0x04,  0x48,  0x02,  0x50,  0x01,  0xAB,  0x10,  0x20,  0x08,  0x20,  0x08,  0x20,  0x07, 	/* 39B60 */
+	0xFF,  0x00,  0x20,  0x40,  0x20,  0x20,  0x20,  0x23,  0xFE,  0x08,  0x70,  0x08,  0x70,  0x10,  0xA8,  0x10, 	/* 39B70 */
+	0xA8,  0x21,  0x24,  0x22,  0x22,  0x44,  0x21,  0x40,  0x20,  0xAE,  0x10,  0x00,  0x08,  0xFC,  0x08,  0x84, 	/* 39B80 */
+	0x00,  0x84,  0x00,  0x84,  0x40,  0xFC,  0x20,  0x84,  0x20,  0x84,  0x08,  0x84,  0x08,  0xFC,  0x10,  0x84, 	/* 39B90 */
+	0x10,  0x84,  0x20,  0x84,  0x20,  0x84,  0x47,  0xFF,  0x40,  0x00,  0xB1,  0x10,  0x20,  0x08,  0x20,  0x08, 	/* 39BA0 */
+	0x20,  0x07,  0xFF,  0x04,  0x01,  0x44,  0x01,  0x20,  0x80,  0x20,  0x84,  0x08,  0x98,  0x08,  0xE0,  0x10, 	/* 39BB0 */
+	0x80,  0x10,  0x80,  0x20,  0x82,  0x20,  0x82,  0x40,  0x42,  0x40,  0x3E,  0xB3,  0x10,  0x00,  0x0B,  0xFF, 	/* 39BC0 */
+	0x08,  0x04,  0x00,  0x04,  0x43,  0xE4,  0x22,  0x24,  0x22,  0x24,  0x02,  0x24,  0x0A,  0x24,  0x0B,  0xE4, 	/* 39BD0 */
+	0x10,  0x04,  0x10,  0x04,  0x20,  0x04,  0x20,  0x04,  0x40,  0x04,  0x40,  0x0C,  0xB8,  0x10,  0x90,  0x08, 	/* 39BE0 */
+	0x90,  0x0B,  0xFC,  0x00,  0x94,  0x40,  0x94,  0x23,  0xFC,  0x22,  0x90,  0x02,  0x90,  0x0B,  0xFE,  0x08, 	/* 39BF0 */
+	0x92,  0x10,  0x92,  0x10,  0x92,  0x21,  0x12,  0x21,  0x1C,  0x42,  0x10,  0x44,  0x10,  0xB9,  0x10,  0x20, 	/* 39C00 */
+	0x08,  0x20,  0x08,  0x20,  0x00,  0x20,  0x43,  0xFE,  0x22,  0x22,  0x22,  0x22,  0x02,  0x22,  0x0A,  0x22, 	/* 39C10 */
+	0x0B,  0xFE,  0x12,  0x22,  0x12,  0x22,  0x22,  0x22,  0x22,  0x22,  0x43,  0xFE,  0x40,  0x00,  0xBA,  0x10, 	/* 39C20 */
+	0x00,  0x0B,  0xFE,  0x0A,  0x22,  0x02,  0x22,  0x42,  0x22,  0x22,  0x22,  0x22,  0x22,  0x03,  0xFE,  0x0A, 	/* 39C30 */
+	0x22,  0x0A,  0x22,  0x12,  0x22,  0x12,  0x22,  0x22,  0x22,  0x22,  0x22,  0x43,  0xFE,  0x40,  0x00,  0xBB, 	/* 39C40 */
+	0x10,  0x40,  0x08,  0x40,  0x08,  0x40,  0x00,  0x90,  0x00,  0x88,  0x41,  0x04,  0x21,  0x3C,  0x27,  0xC2, 	/* 39C50 */
+	0x08,  0x02,  0x09,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x21,  0x04,  0x21,  0x04,  0x41,  0xFC,  0x40,  0x00, 	/* 39C60 */
+	0xBC,  0x10,  0x00,  0x0B,  0xFE,  0x08,  0x22,  0x00,  0x22,  0x40,  0x42,  0x20,  0x42,  0x20,  0x82,  0x01, 	/* 39C70 */
+	0x0C,  0x0A,  0x00,  0x09,  0xFE,  0x11,  0x02,  0x11,  0x02,  0x21,  0x02,  0x21,  0x02,  0x41,  0xFE,  0x40, 	/* 39C80 */
+	0x00,  0xBD,  0x10,  0x20,  0x08,  0x20,  0x08,  0x20,  0x00,  0x20,  0x07,  0xFF,  0x40,  0x20,  0x20,  0x20, 	/* 39C90 */
+	0x20,  0x20,  0x08,  0x20,  0x09,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x21,  0x04,  0x21,  0x04,  0x41,  0xFC, 	/* 39CA0 */
+	0x40,  0x00,  0xBE,  0x10,  0x20,  0x08,  0x20,  0x08,  0x20,  0x00,  0x20,  0x00,  0x3F,  0x40,  0x20,  0x20, 	/* 39CB0 */
+	0x20,  0x20,  0x20,  0x08,  0x20,  0x09,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x21,  0x04,  0x21,  0x04,  0x41, 	/* 39CC0 */
+	0xFC,  0x40,  0x00,  0xBF,  0x10,  0x78,  0x08,  0x08,  0x08,  0x88,  0x00,  0x88,  0x40,  0x84,  0x21,  0x04, 	/* 39CD0 */
+	0x21,  0x02,  0x02,  0x01,  0x0D,  0xFC,  0x09,  0x04,  0x11,  0x04,  0x11,  0x04,  0x21,  0x04,  0x21,  0x04, 	/* 39CE0 */
+	0x41,  0xFC,  0x40,  0x00,  0x81,  0x10,  0x00,  0x0B,  0xFC,  0x0A,  0x04,  0x02,  0x04,  0x42,  0x04,  0x22, 	/* 39CF0 */
+	0x04,  0x23,  0xFC,  0x00,  0x90,  0x08,  0x90,  0x08,  0x90,  0x10,  0x90,  0x11,  0x10,  0x21,  0x10,  0x22, 	/* 39D00 */
+	0x11,  0x44,  0x11,  0x48,  0x0F,  0x84,  0x10,  0x00,  0x0A,  0x48,  0x0A,  0x48,  0x02,  0x48,  0x02,  0x48, 	/* 39D10 */
+	0x4F,  0xFF,  0x22,  0x48,  0x22,  0x48,  0x0A,  0x48,  0x0A,  0x48,  0x12,  0x78,  0x12,  0x00,  0x22,  0x00, 	/* 39D20 */
+	0x22,  0x00,  0x43,  0xFE,  0x40,  0x00,  0x85,  0x20,  0x00,  0x17,  0xFE,  0x14,  0x42,  0x04,  0x42,  0x04, 	/* 39D30 */
+	0x42,  0x44,  0x42,  0x24,  0x42,  0x24,  0x62,  0x0C,  0xA2,  0x0C,  0xA2,  0x14,  0x92,  0x15,  0x12,  0x26, 	/* 39D40 */
+	0x0A,  0x24,  0x02,  0x47,  0xFE,  0x40,  0x00,  0x89,  0x00,  0x40,  0x00,  0x80,  0x0F,  0xF8,  0x08,  0x08, 	/* 39D50 */
+	0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xFA,  0x00,  0x82,  0x3E,  0xC4,  0x02,  0xA8, 	/* 39D60 */
+	0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x01,  0x80,  0x8A,  0x10,  0x40,  0x08,  0x40,  0x08,  0x80,  0x03, 	/* 39D70 */
+	0xFC,  0x02,  0x04,  0x42,  0x04,  0x22,  0x04,  0x22,  0x04,  0x0B,  0xFC,  0x0A,  0x04,  0x12,  0x04,  0x12, 	/* 39D80 */
+	0x04,  0x22,  0x04,  0x22,  0x04,  0x43,  0xFC,  0x40,  0x00,  0x8C,  0x10,  0x80,  0x08,  0x40,  0x08,  0x20, 	/* 39D90 */
+	0x00,  0xA4,  0x40,  0x84,  0x20,  0x84,  0x20,  0x88,  0x02,  0x8C,  0x0A,  0x92,  0x0A,  0x91,  0x14,  0xA1, 	/* 39DA0 */
+	0x14,  0xC0,  0x28,  0x82,  0x21,  0x42,  0x42,  0x3E,  0x4C,  0x00,  0x93,  0x10,  0x08,  0x0F,  0x88,  0x08, 	/* 39DB0 */
+	0x88,  0x00,  0x88,  0x00,  0x88,  0x47,  0x88,  0x24,  0x08,  0x24,  0x08,  0x0F,  0x90,  0x08,  0x90,  0x10, 	/* 39DC0 */
+	0x94,  0x10,  0x92,  0x20,  0x92,  0x20,  0xA6,  0x41,  0x79,  0x46,  0x01,  0x95,  0x10,  0x20,  0x08,  0x20, 	/* 39DD0 */
+	0x08,  0x20,  0x03,  0xFE,  0x40,  0x20,  0x20,  0x20,  0x20,  0x20,  0x07,  0xFF,  0x08,  0x40,  0x08,  0x40, 	/* 39DE0 */
+	0x10,  0x48,  0x10,  0x84,  0x20,  0x9C,  0x27,  0xE2,  0x40,  0x02,  0x40,  0x02,  0x97,  0x20,  0x00,  0x10, 	/* 39DF0 */
+	0x00,  0x17,  0xFE,  0x04,  0x92,  0x04,  0x92,  0x44,  0x92,  0x24,  0x92,  0x24,  0x96,  0x0D,  0x16,  0x0D, 	/* 39E00 */
+	0x0E,  0x16,  0x02,  0x14,  0x02,  0x24,  0x02,  0x24,  0x02,  0x47,  0xFE,  0x40,  0x00,  0x99,  0x10,  0x00, 	/* 39E10 */
+	0x0B,  0xFE,  0x08,  0x20,  0x01,  0x28,  0x01,  0x24,  0x41,  0x22,  0x22,  0x22,  0x20,  0x20,  0x07,  0xFF, 	/* 39E20 */
+	0x08,  0x20,  0x10,  0x20,  0x10,  0x20,  0x20,  0x20,  0x20,  0x20,  0x40,  0x20,  0x40,  0x20,  0x9B,  0x10, 	/* 39E30 */
+	0x02,  0x08,  0x0C,  0x0B,  0xF0,  0x00,  0x40,  0x00,  0x40,  0x40,  0x40,  0x27,  0xFC,  0x20,  0x04,  0x08, 	/* 39E40 */
+	0x08,  0x08,  0x08,  0x10,  0x10,  0x12,  0x20,  0x22,  0xC0,  0x23,  0x00,  0x44,  0xC0,  0x48,  0x3F,  0x9D, 	/* 39E50 */
+	0x10,  0x04,  0x08,  0x18,  0x09,  0xE0,  0x01,  0x00,  0x01,  0x00,  0x41,  0xFF,  0x21,  0x08,  0x21,  0x08, 	/* 39E60 */
+	0x09,  0x38,  0x09,  0x0C,  0x11,  0x0A,  0x11,  0x09,  0x22,  0x08,  0x22,  0x08,  0x44,  0x08,  0x40,  0x08, 	/* 39E70 */
+	0xA1,  0x11,  0x00,  0x09,  0x00,  0x09,  0xFE,  0x01,  0x02,  0x42,  0x02,  0x23,  0xF2,  0x22,  0x12,  0x04, 	/* 39E80 */
+	0x12,  0x00,  0x12,  0x0B,  0xF2,  0x12,  0x04,  0x12,  0x18,  0x22,  0x00,  0x22,  0x01,  0x41,  0x01,  0x40, 	/* 39E90 */
+	0xFF,  0xA2,  0x10,  0x20,  0x08,  0x20,  0x08,  0x20,  0x03,  0xFE,  0x42,  0x22,  0x22,  0x24,  0x22,  0x20, 	/* 39EA0 */
+	0x03,  0xFC,  0x0A,  0x04,  0x0A,  0x88,  0x12,  0x88,  0x12,  0x50,  0x22,  0x20,  0x24,  0x50,  0x44,  0x8C, 	/* 39EB0 */
+	0x4B,  0x03,  0xA3,  0x10,  0x20,  0x10,  0x20,  0x08,  0x20,  0x0B,  0xFE,  0x40,  0x08,  0x41,  0x08,  0x21, 	/* 39EC0 */
+	0x08,  0x20,  0x88,  0x00,  0x88,  0x08,  0x88,  0x10,  0x90,  0x10,  0x90,  0x20,  0x90,  0x20,  0x20,  0x47, 	/* 39ED0 */
+	0xFF,  0x40,  0x00,  0xA5,  0x10,  0x00,  0x09,  0xFE,  0x09,  0x02,  0x01,  0x02,  0x41,  0x02,  0x21,  0xFE, 	/* 39EE0 */
+	0x21,  0x00,  0x01,  0x40,  0x09,  0x44,  0x09,  0x48,  0x12,  0x70,  0x12,  0x40,  0x24,  0x40,  0x24,  0x42, 	/* 39EF0 */
+	0x48,  0x22,  0x40,  0x1E,  0xA8,  0x10,  0x40,  0x08,  0x20,  0x08,  0x20,  0x00,  0x00,  0x03,  0xFE,  0x40, 	/* 39F00 */
+	0x20,  0x20,  0x20,  0x20,  0x20,  0x08,  0x20,  0x09,  0xFC,  0x10,  0x20,  0x10,  0x20,  0x20,  0x20,  0x20, 	/* 39F10 */
+	0x20,  0x47,  0xFF,  0x40,  0x00,  0xAA,  0x10,  0x00,  0x09,  0xFC,  0x09,  0x04,  0x01,  0x04,  0x01,  0x04, 	/* 39F20 */
+	0x41,  0xFC,  0x21,  0x04,  0x21,  0x04,  0x09,  0x04,  0x09,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x21,  0x04, 	/* 39F30 */
+	0x21,  0x04,  0x41,  0xFC,  0x40,  0x00,  0xAF,  0x10,  0x00,  0x0B,  0xFC,  0x0A,  0x04,  0x02,  0x04,  0x02, 	/* 39F40 */
+	0x04,  0x43,  0xFC,  0x22,  0x10,  0x22,  0x10,  0x0B,  0xFF,  0x0A,  0x10,  0x12,  0x10,  0x12,  0x08,  0x22, 	/* 39F50 */
+	0x09,  0x22,  0xC5,  0x43,  0x03,  0x4C,  0x01,  0xB0,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80, 	/* 39F60 */
+	0x1F,  0xFC,  0x01,  0x40,  0x02,  0x20,  0x7F,  0xFF,  0x08,  0x90,  0x10,  0x8C,  0x6C,  0xCB,  0x03,  0xD0, 	/* 39F70 */
+	0x02,  0xA0,  0x0C,  0x90,  0x30,  0x8C,  0x01,  0x80,  0xB1,  0x10,  0x40,  0x08,  0x40,  0x08,  0x40,  0x03, 	/* 39F80 */
+	0xFC,  0x02,  0x44,  0x42,  0x44,  0x22,  0x44,  0x22,  0x44,  0x0F,  0xFF,  0x08,  0x40,  0x10,  0x60,  0x10, 	/* 39F90 */
+	0xA0,  0x20,  0x90,  0x21,  0x08,  0x42,  0x04,  0x4C,  0x03,  0xB3,  0x10,  0xC0,  0x08,  0x20,  0x08,  0x10, 	/* 39FA0 */
+	0x00,  0x00,  0x41,  0xE2,  0x20,  0x22,  0x20,  0x24,  0x07,  0xB4,  0x00,  0xB8,  0x00,  0xB0,  0x11,  0x28, 	/* 39FB0 */
+	0x11,  0x28,  0x22,  0x24,  0x24,  0x22,  0x48,  0x21,  0x40,  0x60,  0x8B,  0x11,  0x04,  0x08,  0x84,  0x08, 	/* 39FC0 */
+	0x88,  0x0B,  0xFE,  0x40,  0x20,  0x20,  0x20,  0x20,  0x20,  0x21,  0xFC,  0x08,  0x20,  0x08,  0x20,  0x10, 	/* 39FD0 */
+	0x20,  0x17,  0xFF,  0x20,  0x20,  0x20,  0x20,  0x40,  0x20,  0x40,  0x20,  0x8C,  0x20,  0x02,  0x17,  0xF2, 	/* 39FE0 */
+	0x11,  0x12,  0x01,  0x12,  0x01,  0x12,  0x43,  0xD2,  0x22,  0x52,  0x22,  0x52,  0x05,  0x52,  0x10,  0x92, 	/* 39FF0 */
+	0x10,  0x92,  0x21,  0x02,  0x21,  0x02,  0x22,  0x02,  0x44,  0x02,  0x48,  0x06,  0x92,  0x10,  0x00,  0x0F, 	/* 3A000 */
+	0xFF,  0x08,  0x50,  0x00,  0x50,  0x00,  0x50,  0x43,  0xFE,  0x22,  0x52,  0x2A,  0x52,  0x0A,  0x52,  0x0A, 	/* 3A010 */
+	0x96,  0x12,  0x8E,  0x13,  0x02,  0x22,  0x02,  0x22,  0x02,  0x43,  0xFE,  0x40,  0x00,  0x97,  0x10,  0x20, 	/* 3A020 */
+	0x09,  0x20,  0x09,  0x20,  0x01,  0xFE,  0x41,  0x20,  0x22,  0x20,  0x24,  0x20,  0x07,  0xFF,  0x00,  0x50, 	/* 3A030 */
+	0x08,  0x50,  0x10,  0x50,  0x10,  0x90,  0x20,  0x90,  0x21,  0x11,  0x42,  0x09,  0x44,  0x07,  0x99,  0x10, 	/* 3A040 */
+	0x20,  0x09,  0x20,  0x09,  0x20,  0x01,  0xFE,  0x01,  0x20,  0x42,  0x20,  0x24,  0x20,  0x27,  0xFF,  0x00, 	/* 3A050 */
+	0x70,  0x08,  0x70,  0x10,  0xA8,  0x11,  0x24,  0x22,  0x22,  0x24,  0x21,  0x40,  0x20,  0x40,  0x20,  0x9B, 	/* 3A060 */
+	0x10,  0x80,  0x08,  0x80,  0x08,  0xF8,  0x01,  0x08,  0x41,  0x88,  0x22,  0x50,  0x24,  0x20,  0x00,  0x50, 	/* 3A070 */
+	0x08,  0x88,  0x09,  0x04,  0x13,  0xFB,  0x15,  0x08,  0x21,  0x08,  0x21,  0x08,  0x41,  0xF8,  0x40,  0x00, 	/* 3A080 */
+	0x9E,  0x10,  0x00,  0x0B,  0xFE,  0x0A,  0x02,  0x02,  0x02,  0x43,  0xFE,  0x22,  0x02,  0x22,  0x02,  0x02, 	/* 3A090 */
+	0xFA,  0x0A,  0x8A,  0x0A,  0x8A,  0x12,  0x8A,  0x12,  0xFA,  0x22,  0x02,  0x22,  0x02,  0x42,  0x02,  0x42, 	/* 3A0A0 */
+	0x06,  0x9F,  0x10,  0x40,  0x08,  0x40,  0x0F,  0xFF,  0x00,  0x40,  0x07,  0xFC,  0x40,  0x44,  0x23,  0xFC, 	/* 3A0B0 */
+	0x22,  0x40,  0x0A,  0x40,  0x0B,  0xFE,  0x10,  0x42,  0x10,  0x62,  0x20,  0xAC,  0x21,  0x10,  0x42,  0x0C, 	/* 3A0C0 */
+	0x4C,  0x03,  0xA5,  0x10,  0x40,  0x08,  0x40,  0x0B,  0xFC,  0x00,  0x44,  0x00,  0x44,  0x4F,  0xFF,  0x20, 	/* 3A0D0 */
+	0x44,  0x23,  0xFC,  0x08,  0x40,  0x08,  0x40,  0x13,  0xFC,  0x10,  0x40,  0x20,  0x40,  0x2F,  0xFF,  0x40, 	/* 3A0E0 */
+	0x40,  0x40,  0x40,  0xA9,  0x10,  0x40,  0x08,  0x40,  0x0B,  0xFC,  0x0A,  0x44,  0x42,  0x44,  0x23,  0xFC, 	/* 3A0F0 */
+	0x22,  0x44,  0x22,  0x44,  0x0B,  0xFE,  0x08,  0x44,  0x10,  0x48,  0x10,  0x30,  0x20,  0x20,  0x20,  0xD1, 	/* 3A100 */
+	0x4F,  0x0D,  0x40,  0x03,  0xAA,  0x10,  0x88,  0x08,  0x88,  0x08,  0x88,  0x0B,  0xFE,  0x40,  0x88,  0x20, 	/* 3A110 */
+	0x88,  0x20,  0x88,  0x20,  0x88,  0x08,  0x88,  0x0F,  0xFF,  0x10,  0x00,  0x10,  0x90,  0x20,  0x88,  0x21, 	/* 3A120 */
+	0x08,  0x42,  0x04,  0x44,  0x04,  0xAB,  0x10,  0x40,  0x08,  0x40,  0x08,  0x80,  0x03,  0xFC,  0x02,  0xA4, 	/* 3A130 */
+	0x42,  0xA4,  0x22,  0xA4,  0x22,  0xA4,  0x0A,  0xA4,  0x0A,  0xA4,  0x12,  0xA4,  0x12,  0xA4,  0x22,  0xA4, 	/* 3A140 */
+	0x2F,  0xFF,  0x40,  0x00,  0x40,  0x00,  0xB2,  0x11,  0x02,  0x09,  0x22,  0x09,  0x22,  0x01,  0x22,  0x41, 	/* 3A150 */
+	0x22,  0x25,  0xB2,  0x25,  0x6A,  0x05,  0x6A,  0x09,  0x22,  0x01,  0x22,  0x11,  0x22,  0x11,  0x22,  0x22, 	/* 3A160 */
+	0x22,  0x22,  0x22,  0x44,  0x02,  0x48,  0x02,  0xB3,  0x21,  0x00,  0x11,  0x00,  0x11,  0x1E,  0x01,  0x12, 	/* 3A170 */
+	0x0F,  0xD2,  0x42,  0x52,  0x22,  0x52,  0x22,  0x52,  0x04,  0x52,  0x14,  0x92,  0x1F,  0x92,  0x20,  0xD2, 	/* 3A180 */
+	0x21,  0x52,  0x22,  0x1E,  0x4C,  0x00,  0x40,  0x00,  0xB5,  0x11,  0x00,  0x09,  0x00,  0x09,  0xFE,  0x01, 	/* 3A190 */
+	0x02,  0x02,  0x02,  0x43,  0xF2,  0x25,  0x12,  0x21,  0x12,  0x09,  0xF2,  0x09,  0x12,  0x11,  0x12,  0x11, 	/* 3A1A0 */
+	0x12,  0x21,  0xF2,  0x20,  0x02,  0x40,  0x04,  0x40,  0x18,  0xB6,  0x11,  0x00,  0x09,  0x00,  0x09,  0xFE, 	/* 3A1B0 */
+	0x01,  0x02,  0x02,  0x02,  0x42,  0x22,  0x24,  0x2A,  0x23,  0xAA,  0x0A,  0x4A,  0x0A,  0x6A,  0x12,  0x9A, 	/* 3A1C0 */
+	0x13,  0x0A,  0x23,  0xFA,  0x20,  0x02,  0x40,  0x04,  0x40,  0x18,  0xB8,  0x10,  0x20,  0x08,  0x24,  0x0A, 	/* 3A1D0 */
+	0x24,  0x01,  0x24,  0x01,  0x28,  0x41,  0x20,  0x20,  0x20,  0x27,  0xFF,  0x08,  0x90,  0x08,  0x90,  0x10, 	/* 3A1E0 */
+	0x90,  0x10,  0x90,  0x20,  0x90,  0x21,  0x11,  0x42,  0x11,  0x4C,  0x0F,  0xBB,  0x10,  0x04,  0x08,  0x18, 	/* 3A1F0 */
+	0x09,  0xE0,  0x00,  0x20,  0x00,  0x20,  0x40,  0x20,  0x27,  0xFF,  0x20,  0x20,  0x08,  0x20,  0x08,  0x20, 	/* 3A200 */
+	0x11,  0xFC,  0x11,  0x04,  0x21,  0x04,  0x21,  0x04,  0x41,  0xFC,  0x40,  0x00,  0xBD,  0x10,  0x20,  0x08, 	/* 3A210 */
+	0x20,  0x08,  0x50,  0x00,  0x50,  0x00,  0x88,  0x41,  0x04,  0x22,  0xFA,  0x24,  0x01,  0x00,  0x00,  0x09, 	/* 3A220 */
+	0xFC,  0x11,  0x04,  0x11,  0x04,  0x21,  0x04,  0x21,  0x04,  0x41,  0xFC,  0x40,  0x00,  0xBE,  0x10,  0x08, 	/* 3A230 */
+	0x08,  0x30,  0x0B,  0xC0,  0x02,  0x04,  0x42,  0x18,  0x22,  0x60,  0x22,  0x44,  0x02,  0x44,  0x0A,  0x68, 	/* 3A240 */
+	0x0A,  0x60,  0x12,  0x50,  0x12,  0x50,  0x24,  0x48,  0x24,  0x44,  0x48,  0x42,  0x40,  0x40,  0x81,  0x10, 	/* 3A250 */
+	0x20,  0x08,  0x20,  0x0F,  0xFF,  0x00,  0x50,  0x00,  0x48,  0x40,  0x84,  0x23,  0xFA,  0x20,  0x02,  0x09, 	/* 3A260 */
+	0x48,  0x09,  0x48,  0x11,  0x48,  0x11,  0x48,  0x22,  0x48,  0x22,  0x49,  0x44,  0x09,  0x48,  0x07,  0x84, 	/* 3A270 */
+	0x10,  0x40,  0x08,  0x78,  0x08,  0x88,  0x01,  0x10,  0x40,  0x20,  0x23,  0xFC,  0x20,  0x24,  0x00,  0x24, 	/* 3A280 */
+	0x0F,  0xFF,  0x08,  0x24,  0x10,  0x24,  0x13,  0xFC,  0x20,  0x20,  0x20,  0x20,  0x40,  0x20,  0x40,  0x60, 	/* 3A290 */
+	0x85,  0x10,  0x48,  0x08,  0x44,  0x08,  0x7C,  0x03,  0xC0,  0x40,  0x40,  0x20,  0x7C,  0x23,  0xC0,  0x00, 	/* 3A2A0 */
+	0x20,  0x08,  0x3E,  0x0B,  0xE4,  0x10,  0x24,  0x10,  0x18,  0x20,  0x12,  0x20,  0x6A,  0x43,  0x86,  0x40, 	/* 3A2B0 */
+	0x02,  0x99,  0x22,  0x02,  0x12,  0x0C,  0x12,  0x30,  0x02,  0x20,  0x0F,  0xA0,  0x42,  0x3F,  0x22,  0x24, 	/* 3A2C0 */
+	0x22,  0x24,  0x13,  0xA4,  0x1E,  0x24,  0x12,  0x24,  0x22,  0x24,  0x22,  0x44,  0x22,  0x44,  0x42,  0x84, 	/* 3A2D0 */
+	0x46,  0x04,  0x9A,  0x10,  0x40,  0x08,  0x90,  0x09,  0x0C,  0x07,  0xFA,  0x00,  0x90,  0x40,  0x91,  0x21, 	/* 3A2E0 */
+	0x0F,  0x26,  0x40,  0x08,  0x78,  0x08,  0x88,  0x11,  0x88,  0x16,  0x50,  0x20,  0x20,  0x20,  0x50,  0x41, 	/* 3A2F0 */
+	0x8C,  0x46,  0x03,  0x9C,  0x10,  0x08,  0x10,  0x30,  0x09,  0xC0,  0x09,  0x00,  0x41,  0x00,  0x41,  0xFE, 	/* 3A300 */
+	0x21,  0x10,  0x21,  0x10,  0x09,  0x10,  0x09,  0x10,  0x0F,  0xFF,  0x10,  0x00,  0x11,  0x10,  0x21,  0x08, 	/* 3A310 */
+	0x22,  0x04,  0x44,  0x04,  0xA3,  0x20,  0x40,  0x10,  0x40,  0x17,  0xFE,  0x04,  0x02,  0x04,  0x02,  0x41, 	/* 3A320 */
+	0xF8,  0x20,  0x00,  0x20,  0x00,  0x0F,  0xFE,  0x08,  0x90,  0x10,  0x90,  0x10,  0x90,  0x21,  0x10,  0x21, 	/* 3A330 */
+	0x12,  0x42,  0x12,  0x44,  0x0E,  0xA4,  0x10,  0x40,  0x08,  0x40,  0x0F,  0xFE,  0x04,  0x02,  0x04,  0x42, 	/* 3A340 */
+	0x40,  0x40,  0x27,  0xFF,  0x20,  0x40,  0x00,  0x80,  0x10,  0xA0,  0x11,  0x20,  0x21,  0x48,  0x22,  0x44, 	/* 3A350 */
+	0x24,  0x9C,  0x4B,  0xE2,  0x40,  0x02,  0xA6,  0x10,  0x24,  0x08,  0x22,  0x0F,  0xFF,  0x00,  0x20,  0x40, 	/* 3A360 */
+	0x20,  0x23,  0xFE,  0x22,  0x22,  0x02,  0x22,  0x0B,  0xFE,  0x0A,  0x22,  0x12,  0x22,  0x13,  0xFE,  0x22, 	/* 3A370 */
+	0x22,  0x22,  0x22,  0x42,  0x22,  0x42,  0x26,  0xA9,  0x10,  0x20,  0x09,  0x20,  0x09,  0x20,  0x01,  0xFE, 	/* 3A380 */
+	0x02,  0x20,  0x42,  0x20,  0x24,  0x20,  0x27,  0xFF,  0x00,  0x00,  0x08,  0x00,  0x11,  0xFC,  0x11,  0x04, 	/* 3A390 */
+	0x21,  0x04,  0x21,  0x04,  0x41,  0xFC,  0x40,  0x00,  0xAA,  0x10,  0x20,  0x08,  0x20,  0x09,  0xFC,  0x01, 	/* 3A3A0 */
+	0x04,  0x41,  0x04,  0x21,  0xFC,  0x21,  0x04,  0x01,  0x04,  0x09,  0xFC,  0x09,  0x22,  0x11,  0x22,  0x11, 	/* 3A3B0 */
+	0x14,  0x21,  0x18,  0x21,  0x48,  0x41,  0x84,  0x46,  0x03,  0xAC,  0x10,  0x00,  0x0B,  0xFC,  0x0A,  0x24, 	/* 3A3C0 */
+	0x02,  0x24,  0x43,  0xFC,  0x22,  0x24,  0x22,  0x24,  0x02,  0x24,  0x0B,  0xFC,  0x08,  0x20,  0x10,  0x20, 	/* 3A3D0 */
+	0x17,  0xFE,  0x20,  0x20,  0x20,  0x20,  0x4F,  0xFF,  0x40,  0x00,  0xAE,  0x10,  0x08,  0x08,  0x30,  0x0F, 	/* 3A3E0 */
+	0xC4,  0x02,  0x44,  0x01,  0x28,  0x41,  0x28,  0x23,  0xFC,  0x20,  0x08,  0x08,  0x10,  0x08,  0x20,  0x17, 	/* 3A3F0 */
+	0xFF,  0x10,  0x20,  0x20,  0x20,  0x20,  0x20,  0x40,  0x20,  0x40,  0x60,  0xB4,  0x10,  0x88,  0x08,  0x84, 	/* 3A400 */
+	0x09,  0x04,  0x01,  0x22,  0x42,  0x22,  0x20,  0x50,  0x20,  0x50,  0x00,  0x88,  0x09,  0x04,  0x0B,  0xFE, 	/* 3A410 */
+	0x15,  0x05,  0x11,  0x04,  0x21,  0x04,  0x21,  0x04,  0x41,  0xFC,  0x40,  0x00,  0xB7,  0x10,  0x80,  0x08, 	/* 3A420 */
+	0x80,  0x08,  0xFE,  0x01,  0x00,  0x41,  0x00,  0x23,  0xFC,  0x24,  0xA4,  0x00,  0xA4,  0x0F,  0xFF,  0x09, 	/* 3A430 */
+	0x24,  0x11,  0x24,  0x11,  0x24,  0x23,  0xFF,  0x22,  0x04,  0x40,  0x08,  0x40,  0x30,  0xB8,  0x10,  0x00, 	/* 3A440 */
+	0x09,  0xF8,  0x08,  0x08,  0x01,  0xF8,  0x40,  0x08,  0x21,  0xF8,  0x20,  0x00,  0x07,  0xFE,  0x04,  0x02, 	/* 3A450 */
+	0x0F,  0xFA,  0x10,  0x88,  0x10,  0x50,  0x20,  0x20,  0x20,  0x50,  0x41,  0x8C,  0x46,  0x03,  0xB9,  0x10, 	/* 3A460 */
+	0x20,  0x08,  0x20,  0x0F,  0xFF,  0x00,  0x20,  0x01,  0x24,  0x41,  0x24,  0x21,  0x24,  0x21,  0xA6,  0x0A, 	/* 3A470 */
+	0x69,  0x0C,  0x31,  0x10,  0x50,  0x10,  0x48,  0x20,  0x88,  0x21,  0x04,  0x42,  0x02,  0x44,  0x01,  0x85, 	/* 3A480 */
+	0x10,  0x00,  0x09,  0xFC,  0x09,  0x04,  0x01,  0x04,  0x01,  0xFC,  0x41,  0x04,  0x21,  0x04,  0x21,  0xFC, 	/* 3A490 */
+	0x08,  0x20,  0x08,  0x20,  0x13,  0xFE,  0x10,  0x20,  0x20,  0x20,  0x20,  0x20,  0x47,  0xFF,  0x40,  0x00, 	/* 3A4A0 */
+	0x88,  0x10,  0x20,  0x0A,  0x22,  0x09,  0x22,  0x00,  0xA4,  0x40,  0xA8,  0x21,  0xFC,  0x21,  0x04,  0x01, 	/* 3A4B0 */
+	0x04,  0x09,  0xFC,  0x09,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x21,  0x04,  0x21,  0x04,  0x41,  0x04,  0x41, 	/* 3A4C0 */
+	0x0C,  0x8C,  0x10,  0x00,  0x0B,  0xFC,  0x08,  0x08,  0x00,  0xD0,  0x40,  0x20,  0x23,  0xFE,  0x22,  0x22, 	/* 3A4D0 */
+	0x02,  0x22,  0x0B,  0xFE,  0x0A,  0x22,  0x12,  0x22,  0x13,  0xFE,  0x22,  0x22,  0x22,  0x22,  0x42,  0x22, 	/* 3A4E0 */
+	0x42,  0x26,  0x8E,  0x20,  0x02,  0x1F,  0x8C,  0x11,  0x78,  0x02,  0x08,  0x02,  0x08,  0x44,  0x48,  0x27, 	/* 3A4F0 */
+	0x4E,  0x21,  0x48,  0x05,  0x48,  0x15,  0x48,  0x15,  0x48,  0x12,  0x48,  0x22,  0x7F,  0x25,  0x00,  0x48, 	/* 3A500 */
+	0xC0,  0x50,  0x3F,  0x93,  0x10,  0x00,  0x0B,  0xFC,  0x0A,  0x04,  0x02,  0x04,  0x03,  0xFC,  0x40,  0x00, 	/* 3A510 */
+	0x23,  0xFC,  0x22,  0x04,  0x0A,  0x04,  0x0B,  0xFC,  0x12,  0x04,  0x12,  0x04,  0x23,  0xFC,  0x22,  0x04, 	/* 3A520 */
+	0x42,  0x04,  0x42,  0x0C,  0x95,  0x11,  0x04,  0x08,  0x88,  0x0B,  0xFE,  0x00,  0x22,  0x00,  0x22,  0x43, 	/* 3A530 */
+	0xFE,  0x22,  0x20,  0x22,  0x20,  0x0B,  0xFE,  0x08,  0x62,  0x10,  0x62,  0x10,  0xA2,  0x21,  0x22,  0x22, 	/* 3A540 */
+	0x2C,  0x44,  0x20,  0x40,  0x20,  0x99,  0x10,  0x00,  0x0B,  0xFF,  0x08,  0x00,  0x03,  0xFE,  0x42,  0x02, 	/* 3A550 */
+	0x22,  0x02,  0x23,  0xFE,  0x02,  0x20,  0x0A,  0x20,  0x0B,  0xFF,  0x12,  0x20,  0x12,  0x30,  0x24,  0x50, 	/* 3A560 */
+	0x24,  0x48,  0x48,  0x84,  0x43,  0x03,  0x9B,  0x10,  0x40,  0x08,  0x40,  0x0F,  0xFE,  0x00,  0x40,  0x03, 	/* 3A570 */
+	0xFC,  0x40,  0x40,  0x27,  0xFF,  0x20,  0x80,  0x08,  0x88,  0x0F,  0xFF,  0x11,  0x08,  0x11,  0x48,  0x22, 	/* 3A580 */
+	0x28,  0x24,  0x28,  0x48,  0x08,  0x40,  0x18,  0x9C,  0x10,  0x20,  0x08,  0x20,  0x0F,  0xFF,  0x00,  0x20, 	/* 3A590 */
+	0x40,  0x20,  0x23,  0xFE,  0x20,  0x00,  0x03,  0xFE,  0x0A,  0x02,  0x0A,  0x92,  0x10,  0x90,  0x10,  0x90, 	/* 3A5A0 */
+	0x20,  0x90,  0x21,  0x11,  0x42,  0x11,  0x44,  0x0F,  0xAF,  0x10,  0x00,  0x0B,  0xFE,  0x0A,  0x10,  0x02, 	/* 3A5B0 */
+	0x10,  0x42,  0xFE,  0x22,  0x10,  0x22,  0x10,  0x03,  0xFF,  0x0A,  0x10,  0x0A,  0x10,  0x12,  0xFE,  0x12, 	/* 3A5C0 */
+	0x10,  0x24,  0x10,  0x24,  0x10,  0x4B,  0xFF,  0x40,  0x00,  0xB2,  0x10,  0x20,  0x08,  0x20,  0x0F,  0xFF, 	/* 3A5D0 */
+	0x00,  0x90,  0x40,  0x90,  0x21,  0x1C,  0x21,  0x24,  0x03,  0x34,  0x0D,  0x6C,  0x09,  0x54,  0x11,  0x88, 	/* 3A5E0 */
+	0x11,  0x18,  0x21,  0x14,  0x21,  0x24,  0x41,  0x42,  0x41,  0x81,  0xB5,  0x10,  0x00,  0x0F,  0xFF,  0x08, 	/* 3A5F0 */
+	0x80,  0x00,  0x80,  0x00,  0xE0,  0x44,  0x26,  0x26,  0x2A,  0x25,  0x3A,  0x05,  0x72,  0x0C,  0xAA,  0x17, 	/* 3A600 */
+	0x2A,  0x14,  0x26,  0x24,  0xC2,  0x24,  0x02,  0x47,  0xFE,  0x40,  0x00,  0xB8,  0x10,  0x00,  0x0B,  0xFE, 	/* 3A610 */
+	0x0A,  0x02,  0x02,  0x22,  0x02,  0x22,  0x43,  0xFE,  0x22,  0x22,  0x22,  0x22,  0x0A,  0xFA,  0x0A,  0x8A, 	/* 3A620 */
+	0x12,  0x8A,  0x12,  0xFA,  0x22,  0x02,  0x22,  0x02,  0x43,  0xFE,  0x40,  0x00,  0xBC,  0x10,  0x20,  0x08, 	/* 3A630 */
+	0x20,  0x0F,  0xFF,  0x00,  0x00,  0x40,  0x00,  0x21,  0xFC,  0x21,  0x04,  0x01,  0x04,  0x09,  0x04,  0x09, 	/* 3A640 */
+	0xFC,  0x10,  0x20,  0x11,  0x28,  0x21,  0x24,  0x22,  0x22,  0x44,  0x22,  0x40,  0x60,  0x80,  0x10,  0x20, 	/* 3A650 */
+	0x08,  0x20,  0x0B,  0xFF,  0x02,  0x01,  0x42,  0x01,  0x21,  0xFE,  0x20,  0x20,  0x00,  0x20,  0x09,  0x20, 	/* 3A660 */
+	0x09,  0x3E,  0x11,  0x20,  0x11,  0x20,  0x22,  0xA0,  0x22,  0x60,  0x44,  0x30,  0x48,  0x0F,  0x85,  0x21, 	/* 3A670 */
+	0x02,  0x11,  0x0C,  0x11,  0x30,  0x0F,  0xE0,  0x01,  0x20,  0x41,  0x3F,  0x23,  0x24,  0x23,  0xA4,  0x05, 	/* 3A680 */
+	0x64,  0x15,  0x24,  0x19,  0x24,  0x21,  0x24,  0x21,  0x44,  0x21,  0x44,  0x41,  0x84,  0x41,  0x04,  0x86, 	/* 3A690 */
+	0x10,  0x04,  0x09,  0x98,  0x08,  0x60,  0x03,  0x98,  0x40,  0x44,  0x2F,  0xFF,  0x20,  0x80,  0x00,  0xFC, 	/* 3A6A0 */
+	0x09,  0x84,  0x0A,  0xFC,  0x14,  0x84,  0x10,  0xFC,  0x20,  0x84,  0x20,  0x84,  0x40,  0x84,  0x40,  0x8C, 	/* 3A6B0 */
+	0x87,  0x11,  0x08,  0x09,  0x08,  0x0F,  0xFE,  0x01,  0x08,  0x01,  0x08,  0x41,  0xF8,  0x21,  0x08,  0x21, 	/* 3A6C0 */
+	0x08,  0x09,  0xF8,  0x09,  0x08,  0x11,  0x08,  0x17,  0xFF,  0x20,  0x00,  0x20,  0x88,  0x43,  0x04,  0x4C, 	/* 3A6D0 */
+	0x02,  0x8B,  0x11,  0x08,  0x09,  0x08,  0x09,  0x08,  0x07,  0xFF,  0x41,  0x08,  0x21,  0x08,  0x23,  0x9C, 	/* 3A6E0 */
+	0x03,  0x5C,  0x05,  0x2A,  0x05,  0x2A,  0x19,  0x49,  0x11,  0x08,  0x21,  0x08,  0x21,  0x08,  0x41,  0x08, 	/* 3A6F0 */
+	0x41,  0x08,  0x8C,  0x10,  0x20,  0x08,  0xA8,  0x08,  0xA4,  0x01,  0x22,  0x02,  0x22,  0x40,  0x20,  0x23, 	/* 3A700 */
+	0xFE,  0x22,  0x02,  0x0A,  0x02,  0x0A,  0xFA,  0x12,  0x8A,  0x12,  0x8A,  0x22,  0xFA,  0x22,  0x02,  0x42, 	/* 3A710 */
+	0x02,  0x42,  0x06,  0x91,  0x11,  0x00,  0x09,  0x3E,  0x09,  0x02,  0x01,  0xE2,  0x41,  0x12,  0x21,  0x12, 	/* 3A720 */
+	0x21,  0x12,  0x0F,  0xF2,  0x01,  0x0A,  0x11,  0x0C,  0x15,  0x44,  0x25,  0x2C,  0x25,  0x2A,  0x29,  0x12, 	/* 3A730 */
+	0x51,  0x21,  0x43,  0x41,  0x92,  0x10,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x00,  0x20,  0x01,  0xFC,  0x40, 	/* 3A740 */
+	0x24,  0x27,  0xFF,  0x20,  0x24,  0x09,  0xFC,  0x08,  0x40,  0x13,  0xFF,  0x10,  0x48,  0x20,  0x88,  0x21, 	/* 3A750 */
+	0xF0,  0x40,  0x48,  0x47,  0x84,  0x95,  0x10,  0x20,  0x08,  0x20,  0x0B,  0xFE,  0x00,  0x20,  0x00,  0x20, 	/* 3A760 */
+	0x47,  0xFF,  0x20,  0x90,  0x20,  0x92,  0x09,  0x0E,  0x0A,  0x20,  0x10,  0x20,  0x11,  0xFC,  0x20,  0x20, 	/* 3A770 */
+	0x20,  0x20,  0x47,  0xFF,  0x40,  0x00,  0x98,  0x11,  0x00,  0x09,  0x00,  0x09,  0xFE,  0x02,  0x82,  0x02, 	/* 3A780 */
+	0x82,  0x45,  0xFA,  0x21,  0x42,  0x22,  0x42,  0x0B,  0xFE,  0x08,  0x42,  0x12,  0x4A,  0x12,  0x4A,  0x23, 	/* 3A790 */
+	0xFA,  0x20,  0x02,  0x40,  0x04,  0x40,  0x18,  0x99,  0x10,  0x20,  0x08,  0x20,  0x0B,  0xFE,  0x02,  0x02, 	/* 3A7A0 */
+	0x02,  0x02,  0x40,  0xF8,  0x20,  0x00,  0x20,  0x00,  0x0B,  0xFF,  0x08,  0x20,  0x10,  0xA8,  0x10,  0xA4, 	/* 3A7B0 */
+	0x21,  0x22,  0x22,  0x22,  0x44,  0x20,  0x40,  0x60,  0x9E,  0x22,  0x3C,  0x12,  0x04,  0x12,  0x24,  0x0F, 	/* 3A7C0 */
+	0xA4,  0x42,  0x24,  0x22,  0x24,  0x27,  0x42,  0x07,  0x52,  0x16,  0x91,  0x1A,  0x10,  0x2A,  0x18,  0x22, 	/* 3A7D0 */
+	0x24,  0x22,  0x24,  0x22,  0x4E,  0x42,  0xF2,  0x42,  0x02,  0xA1,  0x10,  0x40,  0x09,  0x44,  0x09,  0x44, 	/* 3A7E0 */
+	0x0A,  0x48,  0x44,  0xA0,  0x20,  0x90,  0x21,  0x08,  0x26,  0x46,  0x08,  0x40,  0x09,  0x44,  0x11,  0x44, 	/* 3A7F0 */
+	0x12,  0xA8,  0x24,  0xA0,  0x21,  0x10,  0x42,  0x0C,  0x4C,  0x03,  0xA4,  0x21,  0x08,  0x11,  0x08,  0x11, 	/* 3A800 */
+	0x08,  0x0F,  0xD4,  0x02,  0x14,  0x42,  0x22,  0x23,  0xA2,  0x22,  0xD1,  0x0A,  0x88,  0x0A,  0x88,  0x12, 	/* 3A810 */
+	0x80,  0x14,  0xA0,  0x24,  0x90,  0x24,  0x88,  0x48,  0x84,  0x43,  0x04,  0xA6,  0x10,  0x20,  0x08,  0x20, 	/* 3A820 */
+	0x08,  0x50,  0x00,  0x50,  0x00,  0x88,  0x41,  0x04,  0x26,  0xFB,  0x20,  0x20,  0x00,  0x20,  0x0F,  0xFF, 	/* 3A830 */
+	0x10,  0x20,  0x11,  0x24,  0x20,  0xA4,  0x20,  0xA8,  0x47,  0xFE,  0x40,  0x00,  0xA8,  0x10,  0x06,  0x08, 	/* 3A840 */
+	0x38,  0x0B,  0xC4,  0x01,  0x22,  0x01,  0x22,  0x42,  0x02,  0x25,  0xFC,  0x20,  0x24,  0x08,  0x24,  0x0F, 	/* 3A850 */
+	0xFF,  0x10,  0x24,  0x13,  0xFC,  0x20,  0x20,  0x20,  0x20,  0x40,  0x20,  0x40,  0x60,  0xAA,  0x10,  0x20, 	/* 3A860 */
+	0x08,  0x20,  0x08,  0x50,  0x00,  0x88,  0x01,  0x04,  0x46,  0xFB,  0x20,  0x00,  0x20,  0x00,  0x0B,  0xFE, 	/* 3A870 */
+	0x0A,  0x52,  0x12,  0x52,  0x13,  0xFE,  0x22,  0x52,  0x22,  0x52,  0x42,  0x52,  0x42,  0x06,  0xAB,  0x10, 	/* 3A880 */
+	0x04,  0x08,  0x18,  0x0B,  0xE2,  0x42,  0x42,  0x21,  0x24,  0x21,  0x28,  0x00,  0x0C,  0x01,  0xF0,  0x08, 	/* 3A890 */
+	0x20,  0x08,  0x20,  0x17,  0xFF,  0x10,  0x20,  0x20,  0x20,  0x20,  0x20,  0x43,  0xFE,  0x40,  0x00,  0xAC, 	/* 3A8A0 */
+	0x10,  0x20,  0x08,  0x20,  0x0B,  0xFE,  0x00,  0x84,  0x00,  0x84,  0x40,  0xC6,  0x21,  0x2A,  0x21,  0x11, 	/* 3A8B0 */
+	0x0A,  0x20,  0x08,  0x20,  0x17,  0xFF,  0x10,  0x20,  0x20,  0x20,  0x20,  0x20,  0x40,  0x20,  0x40,  0x20, 	/* 3A8C0 */
+	0xAE,  0x10,  0x44,  0x08,  0x44,  0x08,  0x88,  0x01,  0xFF,  0x03,  0x10,  0x45,  0x10,  0x21,  0x10,  0x21, 	/* 3A8D0 */
+	0xFE,  0x09,  0x10,  0x09,  0x10,  0x11,  0xFE,  0x11,  0x10,  0x21,  0x10,  0x21,  0x10,  0x41,  0xFF,  0x40, 	/* 3A8E0 */
+	0x00,  0xB1,  0x10,  0x00,  0x0B,  0xFF,  0x0A,  0x51,  0x02,  0x51,  0x40,  0x92,  0x20,  0x8E,  0x23,  0x20, 	/* 3A8F0 */
+	0x00,  0x20,  0x07,  0xFF,  0x08,  0x20,  0x08,  0x70,  0x10,  0xA8,  0x11,  0x24,  0x26,  0x23,  0x20,  0x20, 	/* 3A900 */
+	0x40,  0x20,  0xB3,  0x10,  0x20,  0x08,  0x20,  0x0F,  0xFE,  0x00,  0x00,  0x41,  0xF8,  0x21,  0x08,  0x21, 	/* 3A910 */
+	0xF8,  0x00,  0x00,  0x0B,  0xFC,  0x08,  0x10,  0x10,  0x20,  0x17,  0xFF,  0x20,  0x20,  0x20,  0x20,  0x40, 	/* 3A920 */
+	0x20,  0x40,  0x60,  0xB5,  0x12,  0x02,  0x0A,  0x52,  0x0A,  0x52,  0x02,  0x52,  0x43,  0xDE,  0x22,  0x02, 	/* 3A930 */
+	0x22,  0x02,  0x03,  0xFE,  0x0A,  0x02,  0x0A,  0x02,  0x13,  0xDE,  0x12,  0x52,  0x22,  0x52,  0x24,  0x52, 	/* 3A940 */
+	0x44,  0x52,  0x48,  0x52,  0xB7,  0x10,  0x00,  0x0B,  0xF8,  0x0A,  0x08,  0x02,  0x08,  0x03,  0xF8,  0x42, 	/* 3A950 */
+	0x08,  0x22,  0x08,  0x23,  0xF8,  0x0A,  0x20,  0x0A,  0x24,  0x12,  0x28,  0x13,  0xF0,  0x22,  0x20,  0x22, 	/* 3A960 */
+	0x22,  0x43,  0xA2,  0x4E,  0x1E,  0xB9,  0x10,  0x40,  0x08,  0x40,  0x0F,  0xFF,  0x00,  0xA0,  0x01,  0x50, 	/* 3A970 */
+	0x42,  0x48,  0x27,  0xFC,  0x2A,  0x4A,  0x02,  0x49,  0x13,  0xF8,  0x12,  0x48,  0x12,  0x48,  0x23,  0xF8, 	/* 3A980 */
+	0x20,  0x42,  0x40,  0x42,  0x40,  0x3E,  0xBA,  0x10,  0x50,  0x08,  0x48,  0x08,  0x7E,  0x07,  0xC4,  0x00, 	/* 3A990 */
+	0x28,  0x40,  0x30,  0x20,  0xCD,  0x27,  0x13,  0x08,  0x48,  0x08,  0x5E,  0x17,  0xE4,  0x10,  0x28,  0x20, 	/* 3A9A0 */
+	0x10,  0x20,  0x69,  0x43,  0x87,  0x40,  0x01,  0xBB,  0x10,  0x08,  0x08,  0x30,  0x0B,  0xC0,  0x00,  0x40, 	/* 3A9B0 */
+	0x40,  0x40,  0x2F,  0xFF,  0x20,  0xA0,  0x01,  0x10,  0x0A,  0x8C,  0x0C,  0x83,  0x10,  0xC8,  0x14,  0xA4, 	/* 3A9C0 */
+	0x24,  0x92,  0x24,  0x92,  0x48,  0x80,  0x41,  0x80,  0x85,  0x10,  0x20,  0x08,  0x20,  0x0B,  0xFE,  0x00, 	/* 3A9D0 */
+	0x20,  0x01,  0xFC,  0x40,  0x20,  0x27,  0xFF,  0x20,  0x00,  0x09,  0xFC,  0x09,  0x04,  0x11,  0xFC,  0x11, 	/* 3A9E0 */
+	0x04,  0x21,  0xFC,  0x21,  0x04,  0x41,  0x04,  0x41,  0x0C,  0x87,  0x10,  0x00,  0x09,  0xF8,  0x09,  0x08, 	/* 3A9F0 */
+	0x01,  0xF8,  0x41,  0x08,  0x21,  0x08,  0x21,  0xF8,  0x00,  0x40,  0x08,  0xFE,  0x09,  0x12,  0x13,  0x22, 	/* 3AA00 */
+	0x15,  0xC2,  0x21,  0x0A,  0x20,  0xFA,  0x40,  0x04,  0x40,  0x18,  0x88,  0x10,  0x20,  0x08,  0x20,  0x0F, 	/* 3AA10 */
+	0xFF,  0x01,  0x08,  0x40,  0x90,  0x20,  0x60,  0x20,  0xD0,  0x01,  0x0C,  0x0F,  0x0B,  0x09,  0xF8,  0x09, 	/* 3AA20 */
+	0x08,  0x11,  0xF8,  0x11,  0x08,  0x21,  0x08,  0x22,  0x08,  0x44,  0x08,  0x89,  0x10,  0x20,  0x09,  0x20, 	/* 3AA30 */
+	0x09,  0x3E,  0x01,  0x20,  0x41,  0x20,  0x27,  0xFF,  0x20,  0x28,  0x01,  0x24,  0x09,  0x24,  0x11,  0x22, 	/* 3AA40 */
+	0x12,  0x2A,  0x14,  0x68,  0x20,  0x10,  0x20,  0x20,  0x40,  0xC0,  0x47,  0x00,  0x8A,  0x12,  0x02,  0x0A, 	/* 3AA50 */
+	0x22,  0x0B,  0x2A,  0x02,  0xAA,  0x02,  0xB2,  0x42,  0x22,  0x23,  0xFE,  0x22,  0x22,  0x0A,  0x72,  0x0A, 	/* 3AA60 */
+	0x72,  0x12,  0xAA,  0x13,  0x26,  0x24,  0x22,  0x24,  0x22,  0x48,  0x22,  0x50,  0x02,  0x8B,  0x20,  0x20, 	/* 3AA70 */
+	0x10,  0x20,  0x11,  0x20,  0x01,  0x3E,  0x41,  0x20,  0x21,  0x20,  0x21,  0x20,  0x07,  0xFF,  0x08,  0x00, 	/* 3AA80 */
+	0x0A,  0x04,  0x11,  0x08,  0x10,  0x90,  0x20,  0x00,  0x20,  0x98,  0x43,  0x06,  0x4C,  0x01,  0x93,  0x10, 	/* 3AA90 */
+	0x04,  0x08,  0x18,  0x0B,  0xE2,  0x00,  0x42,  0x42,  0x24,  0x21,  0x28,  0x21,  0x00,  0x00,  0x20,  0x09, 	/* 3AAA0 */
+	0xFC,  0x08,  0x20,  0x10,  0x20,  0x17,  0xFF,  0x20,  0x50,  0x20,  0x88,  0x41,  0x04,  0x46,  0x03,  0x95, 	/* 3AAB0 */
+	0x20,  0x42,  0x14,  0x52,  0x12,  0x92,  0x02,  0x12,  0x0F,  0xF2,  0x41,  0x12,  0x21,  0x12,  0x2F,  0xF2, 	/* 3AAC0 */
+	0x01,  0x12,  0x11,  0x92,  0x11,  0x52,  0x22,  0x32,  0x22,  0x22,  0x24,  0x02,  0x48,  0x02,  0x40,  0x06, 	/* 3AAD0 */
+	0x99,  0x10,  0x40,  0x08,  0x78,  0x08,  0x90,  0x03,  0x20,  0x0F,  0xFE,  0x42,  0x52,  0x22,  0x52,  0x22, 	/* 3AAE0 */
+	0x56,  0x0A,  0x8E,  0x0B,  0x02,  0x12,  0x22,  0x17,  0xFF,  0x20,  0x50,  0x20,  0x88,  0x43,  0x04,  0x4C, 	/* 3AAF0 */
+	0x03,  0x9A,  0x10,  0x40,  0x08,  0x44,  0x0B,  0xFC,  0x00,  0x48,  0x00,  0x50,  0x47,  0xFF,  0x20,  0x20, 	/* 3AB00 */
+	0x20,  0x40,  0x09,  0xF8,  0x0B,  0x08,  0x15,  0x08,  0x11,  0xF8,  0x21,  0x08,  0x21,  0x08,  0x41,  0xF8, 	/* 3AB10 */
+	0x40,  0x00,  0x9B,  0x10,  0x14,  0x08,  0x12,  0x08,  0x12,  0x03,  0xFF,  0x42,  0x10,  0x23,  0xF2,  0x22, 	/* 3AB20 */
+	0x12,  0x03,  0xD2,  0x0B,  0x54,  0x0B,  0x5C,  0x13,  0x48,  0x13,  0xD8,  0x25,  0x25,  0x24,  0x45,  0x48, 	/* 3AB30 */
+	0x83,  0x51,  0x01,  0x9D,  0x10,  0xE0,  0x08,  0x20,  0x08,  0x50,  0x00,  0x88,  0x01,  0xF4,  0x46,  0x03, 	/* 3AB40 */
+	0x23,  0xCA,  0x22,  0x4A,  0x0B,  0x4A,  0x0A,  0xD4,  0x12,  0x54,  0x13,  0x54,  0x22,  0xCA,  0x22,  0x4A, 	/* 3AB50 */
+	0x42,  0x4A,  0x42,  0xCA,  0x9F,  0x10,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x00,  0x00,  0x01,  0xFC,  0x41, 	/* 3AB60 */
+	0x04,  0x21,  0xFC,  0x20,  0x00,  0x0B,  0xFF,  0x0A,  0x01,  0x13,  0xFD,  0x10,  0x20,  0x20,  0x20,  0x20, 	/* 3AB70 */
+	0x20,  0x40,  0x20,  0x40,  0x60,  0xA0,  0x00,  0x00,  0x19,  0xFE,  0x05,  0x00,  0x31,  0xFC,  0x09,  0x04, 	/* 3AB80 */
+	0x01,  0x04,  0x05,  0xFC,  0x19,  0x00,  0x61,  0xFE,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0xC0,  0x02,  0xA0, 	/* 3AB90 */
+	0x0C,  0x98,  0x70,  0x87,  0x00,  0x80,  0xA1,  0x10,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x0A,  0x44,  0x42, 	/* 3ABA0 */
+	0x44,  0x23,  0xFF,  0x22,  0x44,  0x22,  0x7C,  0x0A,  0x00,  0x0B,  0xFC,  0x12,  0x44,  0x12,  0x48,  0x24, 	/* 3ABB0 */
+	0x28,  0x24,  0x30,  0x48,  0xCC,  0x53,  0x03,  0xA3,  0x10,  0x20,  0x08,  0x20,  0x0F,  0xFF,  0x00,  0x70, 	/* 3ABC0 */
+	0x00,  0xA8,  0x41,  0x24,  0x22,  0x22,  0x25,  0xFD,  0x09,  0x04,  0x09,  0xFC,  0x11,  0x04,  0x11,  0xFC, 	/* 3ABD0 */
+	0x21,  0x04,  0x21,  0x04,  0x47,  0xFF,  0x40,  0x00,  0xA4,  0x11,  0x08,  0x0F,  0xC8,  0x09,  0x08,  0x01, 	/* 3ABE0 */
+	0x08,  0x0F,  0xFE,  0x48,  0x2A,  0x28,  0x2A,  0x27,  0xCA,  0x08,  0x8A,  0x09,  0x0A,  0x11,  0xEA,  0x1F, 	/* 3ABF0 */
+	0x12,  0x21,  0x12,  0x21,  0x12,  0x41,  0x22,  0x43,  0x4C,  0xA5,  0x10,  0x00,  0x13,  0xFE,  0x0A,  0x02, 	/* 3AC00 */
+	0x4A,  0x02,  0x43,  0xFE,  0x22,  0x00,  0x23,  0xFE,  0x02,  0x28,  0x0A,  0x44,  0x0B,  0xFA,  0x12,  0x22, 	/* 3AC10 */
+	0x15,  0xFC,  0x24,  0x20,  0x28,  0x20,  0x57,  0xFF,  0x40,  0x00,  0xA6,  0x10,  0x00,  0x09,  0xF8,  0x09, 	/* 3AC20 */
+	0x08,  0x01,  0x08,  0x01,  0x78,  0x41,  0x48,  0x21,  0x48,  0x23,  0xFE,  0x0A,  0x02,  0x0A,  0xF2,  0x12, 	/* 3AC30 */
+	0x92,  0x12,  0x92,  0x22,  0xF2,  0x22,  0x02,  0x42,  0x02,  0x42,  0x06,  0xA9,  0x10,  0x00,  0x09,  0xFC, 	/* 3AC40 */
+	0x09,  0x04,  0x01,  0xFC,  0x41,  0x04,  0x21,  0x04,  0x21,  0xFC,  0x00,  0x00,  0x08,  0x00,  0x0B,  0xFE, 	/* 3AC50 */
+	0x12,  0x52,  0x12,  0x52,  0x22,  0x52,  0x22,  0x52,  0x4F,  0xFF,  0x40,  0x00,  0xAB,  0x11,  0x24,  0x09, 	/* 3AC60 */
+	0x24,  0x0F,  0xFF,  0x01,  0x24,  0x01,  0x24,  0x41,  0x3C,  0x21,  0x00,  0x21,  0xFE,  0x08,  0x20,  0x08, 	/* 3AC70 */
+	0x20,  0x17,  0xFF,  0x10,  0x70,  0x20,  0xA8,  0x23,  0x24,  0x4C,  0x23,  0x40,  0x20,  0xAC,  0x20,  0x02, 	/* 3AC80 */
+	0x17,  0xD2,  0x14,  0x52,  0x04,  0x52,  0x44,  0x52,  0x27,  0xD2,  0x24,  0x52,  0x04,  0x52,  0x17,  0xD2, 	/* 3AC90 */
+	0x14,  0x52,  0x14,  0x52,  0x27,  0xD2,  0x22,  0x92,  0x42,  0x42,  0x44,  0x42,  0x48,  0x06,  0xAD,  0x10, 	/* 3ACA0 */
+	0x00,  0x0B,  0xFE,  0x0A,  0x22,  0x03,  0xFE,  0x02,  0x22,  0x42,  0x22,  0x23,  0xFE,  0x20,  0x00,  0x09, 	/* 3ACB0 */
+	0xFC,  0x09,  0x04,  0x11,  0xFC,  0x11,  0x04,  0x21,  0xFC,  0x21,  0x04,  0x41,  0x04,  0x41,  0x0C,  0xAE, 	/* 3ACC0 */
+	0x10,  0x88,  0x08,  0x88,  0x0F,  0xFF,  0x00,  0x88,  0x00,  0x88,  0x40,  0x00,  0x27,  0xFF,  0x20,  0x04, 	/* 3ACD0 */
+	0x09,  0xE4,  0x09,  0x24,  0x11,  0x24,  0x11,  0x24,  0x21,  0xE4,  0x20,  0x04,  0x40,  0x04,  0x40,  0x0C, 	/* 3ACE0 */
+	0xAF,  0x10,  0x88,  0x08,  0x88,  0x0B,  0xFE,  0x00,  0x88,  0x00,  0x88,  0x47,  0xFF,  0x20,  0x88,  0x21, 	/* 3ACF0 */
+	0x04,  0x09,  0xFC,  0x0A,  0x0A,  0x14,  0x09,  0x11,  0xF8,  0x21,  0x00,  0x21,  0x04,  0x41,  0x04,  0x40, 	/* 3AD00 */
+	0xFC,  0xB8,  0x21,  0x08,  0x11,  0x08,  0x11,  0x08,  0x0F,  0xEF,  0x01,  0x10,  0x41,  0x10,  0x21,  0x3E, 	/* 3AD10 */
+	0x21,  0xC2,  0x09,  0x44,  0x09,  0x44,  0x12,  0x7F,  0x12,  0x44,  0x22,  0x44,  0x24,  0x44,  0x48,  0x44, 	/* 3AD20 */
+	0x41,  0x8C,  0xBA,  0x20,  0x08,  0x17,  0x88,  0x14,  0x88,  0x04,  0xAA,  0x07,  0xAA,  0x44,  0xA9,  0x24, 	/* 3AD30 */
+	0xA9,  0x24,  0xC8,  0x0F,  0x8A,  0x0C,  0x9A,  0x14,  0x84,  0x14,  0x84,  0x27,  0x88,  0x20,  0x10,  0x40, 	/* 3AD40 */
+	0x60,  0x41,  0x80,  0xBE,  0x10,  0x00,  0x0B,  0xFF,  0x0A,  0x21,  0x02,  0x21,  0x07,  0xFE,  0x40,  0x20, 	/* 3AD50 */
+	0x21,  0xFE,  0x21,  0x22,  0x09,  0xFE,  0x09,  0x22,  0x11,  0x22,  0x11,  0xFE,  0x20,  0x20,  0x27,  0xFF, 	/* 3AD60 */
+	0x40,  0x20,  0x40,  0x20,  0x83,  0x10,  0x40,  0x09,  0xBF,  0x0F,  0x08,  0x01,  0x08,  0x01,  0x3E,  0x47, 	/* 3AD70 */
+	0x88,  0x21,  0x08,  0x21,  0x3E,  0x09,  0x08,  0x09,  0xC8,  0x17,  0x08,  0x11,  0x7F,  0x22,  0x08,  0x22, 	/* 3AD80 */
+	0x08,  0x44,  0x08,  0x48,  0x08,  0x8A,  0x10,  0x20,  0x08,  0x20,  0x0B,  0xFE,  0x00,  0x20,  0x41,  0xFC, 	/* 3AD90 */
+	0x20,  0x50,  0x27,  0xFF,  0x00,  0x88,  0x09,  0x04,  0x0B,  0xFE,  0x14,  0x21,  0x11,  0xFE,  0x20,  0x20, 	/* 3ADA0 */
+	0x20,  0x50,  0x41,  0x8C,  0x46,  0x03,  0x8D,  0x10,  0x20,  0x0A,  0x22,  0x0A,  0x22,  0x02,  0x22,  0x03, 	/* 3ADB0 */
+	0xFE,  0x40,  0x00,  0x2F,  0xFF,  0x20,  0x40,  0x08,  0x80,  0x0B,  0xFE,  0x12,  0x52,  0x12,  0x52,  0x22, 	/* 3ADC0 */
+	0x52,  0x22,  0x52,  0x42,  0x52,  0x42,  0x06,  0x8E,  0x10,  0x00,  0x0F,  0xFF,  0x08,  0x40,  0x00,  0x40, 	/* 3ADD0 */
+	0x00,  0x80,  0x47,  0xFE,  0x24,  0x92,  0x24,  0x92,  0x0C,  0xF2,  0x0C,  0x92,  0x14,  0x92,  0x14,  0xF2, 	/* 3ADE0 */
+	0x24,  0x92,  0x24,  0x92,  0x47,  0xFE,  0x40,  0x00,  0x96,  0x21,  0x00,  0x11,  0x1E,  0x11,  0x12,  0x01, 	/* 3ADF0 */
+	0x12,  0x0F,  0xF2,  0x41,  0x1E,  0x21,  0x12,  0x21,  0x12,  0x07,  0xD2,  0x14,  0x5E,  0x14,  0x52,  0x24, 	/* 3AE00 */
+	0x52,  0x27,  0xD2,  0x20,  0x12,  0x40,  0x22,  0x40,  0x46,  0x98,  0x21,  0x00,  0x11,  0x3E,  0x11,  0x22, 	/* 3AE10 */
+	0x01,  0x22,  0x0F,  0xE2,  0x41,  0x3E,  0x21,  0x22,  0x23,  0xA2,  0x03,  0x62,  0x15,  0x7E,  0x15,  0x22, 	/* 3AE20 */
+	0x19,  0x22,  0x21,  0x22,  0x21,  0x22,  0x41,  0x3E,  0x41,  0x00,  0x9B,  0x10,  0x84,  0x0B,  0xFF,  0x08, 	/* 3AE30 */
+	0x84,  0x00,  0x84,  0x40,  0xFC,  0x20,  0x84,  0x20,  0xFC,  0x00,  0x84,  0x08,  0x84,  0x0F,  0xFF,  0x12, 	/* 3AE40 */
+	0x50,  0x12,  0x52,  0x22,  0x8E,  0x23,  0x00,  0x43,  0xFF,  0x40,  0x00,  0x9F,  0x10,  0x20,  0x08,  0x40, 	/* 3AE50 */
+	0x09,  0xFC,  0x01,  0x04,  0x01,  0xFC,  0x41,  0x04,  0x21,  0x04,  0x21,  0xFC,  0x08,  0x00,  0x0B,  0xFE, 	/* 3AE60 */
+	0x10,  0x20,  0x11,  0xFC,  0x20,  0x20,  0x20,  0x20,  0x4F,  0xFF,  0x40,  0x00,  0xA7,  0x10,  0x00,  0x0B, 	/* 3AE70 */
+	0xFC,  0x08,  0xC8,  0x00,  0x30,  0x41,  0xFC,  0x21,  0x24,  0x21,  0xFC,  0x01,  0x24,  0x09,  0x24,  0x09, 	/* 3AE80 */
+	0xFC,  0x10,  0x20,  0x17,  0xFE,  0x20,  0x22,  0x20,  0x42,  0x41,  0x82,  0x46,  0x0C,  0xAB,  0x20,  0x90, 	/* 3AE90 */
+	0x13,  0x10,  0x1E,  0x12,  0x02,  0x12,  0x02,  0x32,  0x4F,  0xB4,  0x22,  0x34,  0x22,  0x50,  0x07,  0x10, 	/* 3AEA0 */
+	0x16,  0x98,  0x2A,  0x28,  0x2A,  0x28,  0x32,  0x24,  0x42,  0x44,  0x42,  0x82,  0x43,  0x01,  0xAE,  0x10, 	/* 3AEB0 */
+	0x00,  0x0F,  0xFF,  0x08,  0x50,  0x00,  0x50,  0x03,  0xFE,  0x42,  0x52,  0x22,  0x52,  0x22,  0x52,  0x0B, 	/* 3AEC0 */
+	0xFE,  0x08,  0x20,  0x10,  0x20,  0x11,  0xFC,  0x20,  0x20,  0x20,  0x20,  0x4F,  0xFF,  0x40,  0x00,  0xAF, 	/* 3AED0 */
+	0x10,  0x00,  0x09,  0xFC,  0x09,  0x04,  0x01,  0xFC,  0x01,  0x04,  0x41,  0x04,  0x21,  0xFC,  0x20,  0x00, 	/* 3AEE0 */
+	0x0F,  0xFF,  0x08,  0x80,  0x09,  0xFE,  0x12,  0x4A,  0x14,  0x8A,  0x21,  0x12,  0x22,  0x22,  0x40,  0x4C, 	/* 3AEF0 */
+	0xB2,  0x10,  0x04,  0x08,  0x18,  0x0B,  0xE4,  0x01,  0x12,  0x01,  0x11,  0x42,  0x01,  0x25,  0xFE,  0x20, 	/* 3AF00 */
+	0x40,  0x0F,  0xFF,  0x08,  0x40,  0x10,  0xFC,  0x10,  0xA4,  0x21,  0x18,  0x22,  0x30,  0x44,  0xCC,  0x43, 	/* 3AF10 */
+	0x03,  0xB6,  0x10,  0x20,  0x08,  0x40,  0x09,  0xFC,  0x01,  0x04,  0x01,  0xFC,  0x41,  0x04,  0x21,  0x04, 	/* 3AF20 */
+	0x21,  0xFC,  0x08,  0x22,  0x08,  0x32,  0x17,  0xB4,  0x10,  0xA8,  0x21,  0x24,  0x22,  0x23,  0x44,  0x20, 	/* 3AF30 */
+	0x40,  0x60,  0xBE,  0x10,  0x20,  0x08,  0x20,  0x0F,  0xFF,  0x00,  0x90,  0x42,  0x94,  0x22,  0x92,  0x24, 	/* 3AF40 */
+	0xB2,  0x01,  0x00,  0x0B,  0xF8,  0x08,  0x08,  0x13,  0xF8,  0x12,  0x00,  0x23,  0xFC,  0x20,  0x04,  0x40, 	/* 3AF50 */
+	0x04,  0x40,  0x38,  0xBF,  0x10,  0x00,  0x0B,  0xFC,  0x0A,  0x04,  0x02,  0x04,  0x03,  0xFC,  0x42,  0x04, 	/* 3AF60 */
+	0x22,  0x04,  0x23,  0xFC,  0x08,  0x00,  0x08,  0x92,  0x14,  0x92,  0x12,  0x94,  0x22,  0x94,  0x20,  0x90, 	/* 3AF70 */
+	0x4F,  0xFF,  0x40,  0x00,  0x80,  0x00,  0x88,  0x10,  0x88,  0x0B,  0xFE,  0x08,  0x88,  0x00,  0x88,  0x47, 	/* 3AF80 */
+	0xFF,  0x20,  0x20,  0x23,  0xFE,  0x0A,  0x22,  0x0A,  0xAA,  0x12,  0xAA,  0x12,  0xAA,  0x22,  0xFA,  0x22, 	/* 3AF90 */
+	0x8A,  0x42,  0x02,  0x42,  0x06,  0x82,  0x21,  0x02,  0x11,  0x12,  0x1F,  0xF2,  0x01,  0x12,  0x07,  0xD2, 	/* 3AFA0 */
+	0x05,  0x52,  0x45,  0x52,  0x25,  0x52,  0x27,  0xD2,  0x01,  0x12,  0x13,  0x92,  0x13,  0x42,  0x25,  0x22, 	/* 3AFB0 */
+	0x25,  0x02,  0x49,  0x02,  0x41,  0x06,  0x8C,  0x11,  0xD0,  0x08,  0x54,  0x0A,  0x59,  0x01,  0x8A,  0x40, 	/* 3AFC0 */
+	0x84,  0x21,  0x02,  0x23,  0xFD,  0x04,  0x90,  0x00,  0x90,  0x08,  0x90,  0x17,  0xFF,  0x10,  0x90,  0x20, 	/* 3AFD0 */
+	0x90,  0x21,  0x11,  0x42,  0x11,  0x44,  0x0F,  0x8F,  0x10,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x02,  0x20, 	/* 3AFE0 */
+	0x03,  0xFC,  0x42,  0x24,  0x23,  0xFF,  0x22,  0x24,  0x0A,  0x24,  0x0B,  0xFC,  0x12,  0x20,  0x15,  0xFC, 	/* 3AFF0 */
+	0x25,  0x04,  0x29,  0x04,  0x51,  0xFC,  0x40,  0x00,  0x90,  0x10,  0x00,  0x0B,  0xFE,  0x0A,  0x10,  0x02, 	/* 3B000 */
+	0x20,  0x42,  0xFC,  0x22,  0x84,  0x22,  0x84,  0x02,  0xFC,  0x0A,  0x84,  0x0A,  0xFC,  0x12,  0x20,  0x12, 	/* 3B010 */
+	0xA8,  0x24,  0xA4,  0x25,  0x22,  0x4A,  0x22,  0x40,  0x60,  0x96,  0x10,  0x88,  0x08,  0x90,  0x49,  0xFE, 	/* 3B020 */
+	0x23,  0x20,  0x23,  0xFC,  0x05,  0x20,  0x05,  0xFC,  0x09,  0x20,  0x11,  0x20,  0x21,  0xFE,  0x00,  0x80, 	/* 3B030 */
+	0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x98,  0x10,  0x40,  0x08,  0x40,  0x0B, 	/* 3B040 */
+	0xFC,  0x00,  0x40,  0x00,  0x40,  0x47,  0xFE,  0x20,  0x50,  0x20,  0x88,  0x09,  0x34,  0x0F,  0xC2,  0x10, 	/* 3B050 */
+	0x00,  0x17,  0xFC,  0x24,  0xA4,  0x24,  0xA4,  0x5F,  0xFF,  0x40,  0x00,  0x9C,  0x10,  0x40,  0x0B,  0xBE, 	/* 3B060 */
+	0x0A,  0x0A,  0x02,  0x8A,  0x02,  0x52,  0x42,  0x52,  0x23,  0xEC,  0x26,  0x40,  0x01,  0xFC,  0x09,  0x24, 	/* 3B070 */
+	0x09,  0x24,  0x11,  0xFC,  0x11,  0x24,  0x21,  0x24,  0x21,  0xFC,  0x40,  0x00,  0x9D,  0x10,  0x88,  0x08, 	/* 3B080 */
+	0x88,  0x0B,  0xFE,  0x00,  0x88,  0x03,  0xFE,  0x40,  0x88,  0x27,  0xFF,  0x20,  0x20,  0x09,  0xFC,  0x09, 	/* 3B090 */
+	0x24,  0x11,  0xFC,  0x11,  0x24,  0x27,  0xFF,  0x21,  0x04,  0x41,  0x04,  0x41,  0x0C,  0x9F,  0x20,  0x00, 	/* 3B0A0 */
+	0x17,  0xFF,  0x14,  0x01,  0x05,  0xFD,  0x01,  0x04,  0x41,  0x04,  0x21,  0xFC,  0x21,  0x04,  0x09,  0x04, 	/* 3B0B0 */
+	0x09,  0xFC,  0x10,  0x20,  0x17,  0xFF,  0x20,  0x00,  0x20,  0x88,  0x43,  0x06,  0x4C,  0x01,  0xA2,  0x12, 	/* 3B0C0 */
+	0x04,  0x09,  0x08,  0x09,  0x08,  0x0F,  0xFF,  0x40,  0x90,  0x21,  0x08,  0x21,  0x08,  0x02,  0x04,  0x04, 	/* 3B0D0 */
+	0x02,  0x1B,  0xFD,  0x12,  0xA4,  0x12,  0xA4,  0x22,  0xA4,  0x22,  0xA4,  0x4F,  0xFF,  0x40,  0x00,  0xA5, 	/* 3B0E0 */
+	0x10,  0x44,  0x08,  0x42,  0x0F,  0xFF,  0x00,  0x40,  0x03,  0xFC,  0x42,  0x44,  0x23,  0xFC,  0x22,  0x44, 	/* 3B0F0 */
+	0x0B,  0xFC,  0x0A,  0x44,  0x10,  0x08,  0x17,  0xFF,  0x21,  0x08,  0x20,  0x88,  0x40,  0x88,  0x40,  0x18, 	/* 3B100 */
+	0xAA,  0x10,  0x04,  0x08,  0x38,  0x0B,  0xC8,  0x01,  0x24,  0x01,  0x22,  0x42,  0x02,  0x24,  0x4A,  0x21, 	/* 3B110 */
+	0x90,  0x08,  0xA8,  0x08,  0x46,  0x13,  0xF9,  0x10,  0x20,  0x27,  0xFF,  0x20,  0x50,  0x41,  0x8C,  0x46, 	/* 3B120 */
+	0x03,  0xAF,  0x24,  0x40,  0x12,  0x5E,  0x12,  0x92,  0x0F,  0xF2,  0x01,  0x12,  0x41,  0x1E,  0x25,  0x52, 	/* 3B130 */
+	0x25,  0x52,  0x05,  0x52,  0x15,  0x5E,  0x17,  0xD2,  0x21,  0x12,  0x21,  0x12,  0x22,  0x22,  0x44,  0x22, 	/* 3B140 */
+	0x40,  0x46,  0xB2,  0x10,  0xA0,  0x08,  0xA0,  0x0B,  0x2C,  0x02,  0x24,  0x02,  0x24,  0x43,  0xAC,  0x22, 	/* 3B150 */
+	0x24,  0x22,  0x24,  0x0B,  0xAC,  0x08,  0x20,  0x17,  0xFC,  0x11,  0x08,  0x20,  0x90,  0x20,  0x60,  0x41, 	/* 3B160 */
+	0x98,  0x46,  0x07,  0xB6,  0x10,  0x20,  0x08,  0x20,  0x0B,  0xFE,  0x02,  0x02,  0x42,  0x92,  0x20,  0x88, 	/* 3B170 */
+	0x20,  0xA4,  0x01,  0x24,  0x0A,  0x50,  0x08,  0x88,  0x11,  0x04,  0x13,  0xFE,  0x25,  0x05,  0x21,  0x04, 	/* 3B180 */
+	0x41,  0xFC,  0x40,  0x00,  0xB7,  0x20,  0x00,  0x17,  0xFE,  0x14,  0x02,  0x07,  0xFE,  0x04,  0x42,  0x44, 	/* 3B190 */
+	0x8A,  0x27,  0x4A,  0x24,  0x52,  0x0C,  0xB2,  0x0F,  0x2A,  0x14,  0x6A,  0x14,  0xA6,  0x27,  0x22,  0x24, 	/* 3B1A0 */
+	0x62,  0x47,  0xFE,  0x44,  0x02,  0xBA,  0x20,  0x00,  0x1F,  0xBE,  0x10,  0x82,  0x00,  0x82,  0x47,  0x9E, 	/* 3B1B0 */
+	0x24,  0x10,  0x24,  0x10,  0x07,  0x9E,  0x10,  0x82,  0x18,  0xA2,  0x14,  0x92,  0x21,  0x86,  0x26,  0x9A, 	/* 3B1C0 */
+	0x28,  0xA2,  0x41,  0x04,  0x46,  0x18,  0xBD,  0x10,  0x00,  0x0B,  0xFF,  0x0A,  0x00,  0x02,  0xFE,  0x02, 	/* 3B1D0 */
+	0x00,  0x43,  0xFF,  0x22,  0xA2,  0x22,  0x94,  0x04,  0xEC,  0x1B,  0x03,  0x10,  0x04,  0x17,  0xFF,  0x21, 	/* 3B1E0 */
+	0x04,  0x20,  0x84,  0x40,  0x84,  0x40,  0x0C,  0x82,  0x10,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x01,  0x04, 	/* 3B1F0 */
+	0x00,  0x88,  0x47,  0xFF,  0x24,  0x01,  0x24,  0x21,  0x00,  0x20,  0x17,  0xFF,  0x10,  0x40,  0x20,  0x7C, 	/* 3B200 */
+	0x20,  0x44,  0x20,  0x84,  0x43,  0x04,  0x4C,  0x18,  0x84,  0x10,  0x20,  0x08,  0x20,  0x08,  0x50,  0x00, 	/* 3B210 */
+	0x88,  0x01,  0x74,  0x42,  0x02,  0x25,  0xFD,  0x21,  0x04,  0x09,  0xFC,  0x09,  0x04,  0x11,  0xFC,  0x12, 	/* 3B220 */
+	0x00,  0x22,  0xFE,  0x24,  0x82,  0x48,  0xFE,  0x40,  0x00,  0x85,  0x10,  0x0C,  0x08,  0x0A,  0x08,  0x08, 	/* 3B230 */
+	0x03,  0xFF,  0x42,  0x08,  0x23,  0xFA,  0x22,  0x4A,  0x03,  0x5A,  0x0A,  0xEA,  0x0A,  0xCC,  0x12,  0x44, 	/* 3B240 */
+	0x12,  0xAC,  0x24,  0x95,  0x25,  0x15,  0x46,  0x23,  0x48,  0x41,  0x89,  0x10,  0x00,  0x09,  0xFC,  0x09, 	/* 3B250 */
+	0x04,  0x01,  0xFC,  0x01,  0x04,  0x41,  0xFC,  0x22,  0x24,  0x21,  0x24,  0x09,  0x28,  0x0F,  0xFF,  0x10, 	/* 3B260 */
+	0x90,  0x10,  0x90,  0x20,  0x90,  0x21,  0x11,  0x46,  0x11,  0x58,  0x0F,  0x8B,  0x21,  0x04,  0x10,  0x84, 	/* 3B270 */
+	0x10,  0x88,  0x07,  0xFF,  0x00,  0x84,  0x40,  0x84,  0x21,  0x08,  0x21,  0x48,  0x0E,  0x72,  0x09,  0x4A, 	/* 3B280 */
+	0x10,  0x84,  0x10,  0x84,  0x21,  0x4A,  0x22,  0x52,  0x4F,  0xFF,  0x40,  0x21,  0x8C,  0x11,  0x20,  0x09, 	/* 3B290 */
+	0x20,  0x09,  0x7F,  0x02,  0x44,  0x02,  0xA4,  0x45,  0x18,  0x2D,  0x18,  0x25,  0x24,  0x05,  0xC3,  0x15, 	/* 3B2A0 */
+	0x10,  0x25,  0xFF,  0x25,  0x18,  0x25,  0x34,  0x44,  0x52,  0x44,  0x91,  0x44,  0x10,  0x91,  0x10,  0x00, 	/* 3B2B0 */
+	0x09,  0xF8,  0x09,  0x08,  0x01,  0x38,  0x01,  0x28,  0x47,  0xFE,  0x24,  0x02,  0x25,  0xFA,  0x01,  0x08, 	/* 3B2C0 */
+	0x09,  0xF8,  0x11,  0x08,  0x11,  0xF8,  0x21,  0x08,  0x21,  0x08,  0x41,  0x08,  0x41,  0x18,  0x93,  0x10, 	/* 3B2D0 */
+	0x20,  0x08,  0x20,  0x0B,  0xFF,  0x02,  0x01,  0x02,  0x21,  0x43,  0xFE,  0x20,  0x84,  0x20,  0x48,  0x0F, 	/* 3B2E0 */
+	0xFF,  0x08,  0x20,  0x10,  0x20,  0x13,  0xFE,  0x20,  0x20,  0x20,  0x20,  0x40,  0x20,  0x40,  0x20,  0x94, 	/* 3B2F0 */
+	0x10,  0x02,  0x08,  0x1C,  0x0B,  0xE8,  0x00,  0x44,  0x02,  0x22,  0x42,  0x22,  0x24,  0x00,  0x20,  0x40, 	/* 3B300 */
+	0x0B,  0x9E,  0x0A,  0x02,  0x12,  0x02,  0x13,  0xDE,  0x22,  0x02,  0x22,  0x02,  0x43,  0xFE,  0x40,  0x00, 	/* 3B310 */
+	0x95,  0x00,  0x20,  0x3C,  0xA8,  0x25,  0x24,  0x27,  0xFE,  0x24,  0x20,  0x3C,  0x50,  0x27,  0xFF,  0x24, 	/* 3B320 */
+	0x88,  0x24,  0xA4,  0x3D,  0x26,  0x26,  0xB5,  0x24,  0xB8,  0x24,  0x68,  0x24,  0xA4,  0x27,  0x22,  0x4C, 	/* 3B330 */
+	0x60,  0x9D,  0x10,  0x40,  0x08,  0x40,  0x0B,  0xFE,  0x01,  0x08,  0x40,  0x90,  0x27,  0xFF,  0x20,  0x00, 	/* 3B340 */
+	0x03,  0xFC,  0x0A,  0x44,  0x0A,  0x44,  0x13,  0xFC,  0x12,  0x44,  0x23,  0xFC,  0x22,  0x41,  0x40,  0x41, 	/* 3B350 */
+	0x40,  0x3F,  0x9E,  0x11,  0x24,  0x09,  0x24,  0x0F,  0xFF,  0x01,  0x24,  0x41,  0x24,  0x21,  0xFC,  0x20, 	/* 3B360 */
+	0x00,  0x07,  0xFF,  0x04,  0x21,  0x0C,  0x21,  0x11,  0xFE,  0x11,  0x22,  0x21,  0x22,  0x21,  0x2C,  0x41, 	/* 3B370 */
+	0x20,  0x40,  0x20,  0xAC,  0x10,  0x00,  0x0F,  0xFF,  0x08,  0x00,  0x03,  0xFE,  0x02,  0x02,  0x43,  0xFE, 	/* 3B380 */
+	0x22,  0x00,  0x22,  0xFC,  0x0A,  0x84,  0x0A,  0xFC,  0x12,  0x00,  0x13,  0xFE,  0x25,  0x22,  0x25,  0xFE, 	/* 3B390 */
+	0x49,  0x01,  0x40,  0xFF,  0xAF,  0x11,  0x54,  0x09,  0x54,  0x0F,  0xFF,  0x01,  0x54,  0x01,  0x55,  0x41, 	/* 3B3A0 */
+	0x73,  0x22,  0x01,  0x27,  0xFE,  0x0A,  0x22,  0x0A,  0x22,  0x11,  0xFC,  0x11,  0x24,  0x21,  0x24,  0x21, 	/* 3B3B0 */
+	0x38,  0x41,  0x20,  0x40,  0x20,  0xB2,  0x10,  0x20,  0x08,  0x58,  0x0B,  0xF4,  0x00,  0x84,  0x01,  0x4A, 	/* 3B3C0 */
+	0x47,  0xBD,  0x20,  0x20,  0x27,  0xFF,  0x08,  0x50,  0x08,  0x98,  0x13,  0x64,  0x1D,  0x8B,  0x20,  0x32, 	/* 3B3D0 */
+	0x21,  0xCC,  0x40,  0x30,  0x43,  0xC0,  0xB4,  0x10,  0x20,  0x08,  0x20,  0x0F,  0xFF,  0x01,  0x04,  0x40, 	/* 3B3E0 */
+	0x88,  0x23,  0xFE,  0x22,  0x22,  0x02,  0x22,  0x0B,  0xFE,  0x0A,  0x22,  0x12,  0xFA,  0x12,  0x8A,  0x22, 	/* 3B3F0 */
+	0x8A,  0x22,  0xFA,  0x42,  0x02,  0x42,  0x06,  0xB7,  0x10,  0x40,  0x08,  0x40,  0x08,  0x7F,  0x00,  0x40, 	/* 3B400 */
+	0x00,  0x40,  0x47,  0xFE,  0x24,  0x8A,  0x24,  0x4A,  0x0D,  0x92,  0x0C,  0x5A,  0x16,  0x26,  0x15,  0x52, 	/* 3B410 */
+	0x24,  0x8A,  0x25,  0x2A,  0x47,  0xFE,  0x40,  0x00,  0xB8,  0x20,  0x10,  0x17,  0x90,  0x10,  0x10,  0x1F, 	/* 3B420 */
+	0xFE,  0x00,  0x28,  0x47,  0xC8,  0x20,  0x08,  0x20,  0x7F,  0x07,  0x88,  0x10,  0x08,  0x17,  0x88,  0x24, 	/* 3B430 */
+	0x88,  0x24,  0x88,  0x44,  0x88,  0x47,  0x88,  0x40,  0x08,  0xBE,  0x10,  0x20,  0x08,  0x20,  0x0F,  0xFF, 	/* 3B440 */
+	0x00,  0x48,  0x01,  0x86,  0x46,  0x01,  0x21,  0xFC,  0x21,  0x04,  0x09,  0x04,  0x09,  0xFE,  0x10,  0xA2, 	/* 3B450 */
+	0x11,  0x24,  0x27,  0x18,  0x21,  0x28,  0x41,  0xC4,  0x47,  0x03,  0xBF,  0x10,  0x88,  0x08,  0x88,  0x0F, 	/* 3B460 */
+	0xFF,  0x00,  0x88,  0x00,  0x88,  0x40,  0xF8,  0x20,  0x20,  0x23,  0xFE,  0x0A,  0x22,  0x0B,  0xBA,  0x12, 	/* 3B470 */
+	0xAA,  0x12,  0xAA,  0x23,  0x76,  0x23,  0x32,  0x42,  0x22,  0x42,  0x26,  0x81,  0x10,  0x40,  0x08,  0x40, 	/* 3B480 */
+	0x08,  0xF8,  0x01,  0x10,  0x06,  0x20,  0x41,  0xFC,  0x21,  0x24,  0x21,  0x24,  0x09,  0xFC,  0x09,  0x24, 	/* 3B490 */
+	0x11,  0x24,  0x11,  0xFC,  0x22,  0x00,  0x22,  0x92,  0x44,  0x49,  0x48,  0x49,  0x82,  0x10,  0x00,  0x0F, 	/* 3B4A0 */
+	0xFF,  0x08,  0x90,  0x0B,  0xFC,  0x42,  0x94,  0x22,  0x94,  0x23,  0xFC,  0x00,  0x00,  0x09,  0xFC,  0x08, 	/* 3B4B0 */
+	0x00,  0x17,  0xFF,  0x11,  0x28,  0x21,  0x24,  0x22,  0x22,  0x44,  0x22,  0x40,  0x60,  0x86,  0x10,  0x20, 	/* 3B4C0 */
+	0x08,  0x20,  0x0F,  0xFF,  0x08,  0x70,  0x41,  0xAC,  0x26,  0x23,  0x20,  0x20,  0x00,  0x50,  0x09,  0xAC, 	/* 3B4D0 */
+	0x0E,  0x23,  0x11,  0x24,  0x10,  0xA8,  0x20,  0xF0,  0x21,  0xAC,  0x46,  0x23,  0x40,  0x60,  0x89,  0x20, 	/* 3B4E0 */
+	0x20,  0x10,  0x20,  0x17,  0xFF,  0x04,  0x90,  0x44,  0x90,  0x27,  0xFE,  0x24,  0x92,  0x04,  0x92,  0x07, 	/* 3B4F0 */
+	0xFE,  0x15,  0x10,  0x15,  0x10,  0x25,  0xF2,  0x29,  0x1C,  0x29,  0x10,  0x51,  0xD1,  0x46,  0x0F,  0x8F, 	/* 3B500 */
+	0x10,  0x00,  0x0B,  0xFE,  0x0A,  0x02,  0x02,  0x02,  0x43,  0xFE,  0x22,  0x00,  0x23,  0xFF,  0x02,  0x20, 	/* 3B510 */
+	0x0B,  0xFE,  0x0B,  0xB2,  0x15,  0x6A,  0x15,  0x22,  0x25,  0xB2,  0x29,  0x6A,  0x51,  0x22,  0x41,  0x26, 	/* 3B520 */
+	0x91,  0x22,  0x00,  0x12,  0x3E,  0x17,  0x84,  0x04,  0xA4,  0x44,  0xA4,  0x27,  0xA4,  0x24,  0xA4,  0x04, 	/* 3B530 */
+	0xFF,  0x07,  0x88,  0x14,  0x0C,  0x17,  0x8C,  0x24,  0x14,  0x24,  0x14,  0x27,  0xA5,  0x44,  0x45,  0x44, 	/* 3B540 */
+	0x83,  0x93,  0x10,  0x20,  0x08,  0x20,  0x0F,  0xFF,  0x00,  0x10,  0x01,  0xD4,  0x41,  0x24,  0x21,  0x54, 	/* 3B550 */
+	0x21,  0x84,  0x09,  0xFC,  0x08,  0x20,  0x13,  0xFE,  0x12,  0x42,  0x22,  0x92,  0x23,  0xEA,  0x42,  0x02, 	/* 3B560 */
+	0x42,  0x06,  0x94,  0x10,  0x20,  0x08,  0x20,  0x0F,  0xFF,  0x04,  0x01,  0x07,  0xFE,  0x40,  0x20,  0x23, 	/* 3B570 */
+	0xFE,  0x22,  0x22,  0x02,  0x22,  0x13,  0xFE,  0x12,  0x22,  0x22,  0x22,  0x23,  0xFE,  0x20,  0x8C,  0x41, 	/* 3B580 */
+	0x02,  0x46,  0x01,  0x95,  0x10,  0x50,  0x08,  0x50,  0x0F,  0xFF,  0x00,  0x50,  0x43,  0xFE,  0x22,  0x52, 	/* 3B590 */
+	0x23,  0xFE,  0x02,  0x52,  0x0B,  0xFE,  0x08,  0x00,  0x11,  0xFC,  0x11,  0x04,  0x21,  0xFC,  0x21,  0x04, 	/* 3B5A0 */
+	0x41,  0xFC,  0x40,  0x00,  0xA0,  0x10,  0x88,  0x08,  0x88,  0x0F,  0xFF,  0x00,  0x88,  0x40,  0x88,  0x21, 	/* 3B5B0 */
+	0xFC,  0x21,  0x04,  0x01,  0xFC,  0x09,  0x04,  0x09,  0xFC,  0x10,  0x20,  0x17,  0xFF,  0x20,  0x20,  0x20, 	/* 3B5C0 */
+	0x50,  0x41,  0x8C,  0x46,  0x03,  0xA2,  0x10,  0x88,  0x08,  0x88,  0x0F,  0xFF,  0x00,  0x88,  0x40,  0x00, 	/* 3B5D0 */
+	0x23,  0xFE,  0x22,  0x22,  0x02,  0x22,  0x0B,  0xFE,  0x08,  0x20,  0x13,  0xFC,  0x10,  0x20,  0x27,  0xFF, 	/* 3B5E0 */
+	0x20,  0x50,  0x41,  0x8C,  0x46,  0x03,  0xA3,  0x20,  0x10,  0x14,  0x10,  0x13,  0xFF,  0x02,  0x10,  0x40, 	/* 3B5F0 */
+	0xFE,  0x20,  0x92,  0x20,  0x92,  0x0E,  0xFE,  0x02,  0x92,  0x12,  0x92,  0x12,  0xFE,  0x22,  0x10,  0x23, 	/* 3B600 */
+	0xFF,  0x25,  0x10,  0x48,  0xD0,  0x50,  0x3F,  0xAB,  0x10,  0x00,  0x09,  0xF8,  0x09,  0x08,  0x01,  0xF8, 	/* 3B610 */
+	0x41,  0x08,  0x21,  0xF8,  0x20,  0x00,  0x0B,  0xFE,  0x0A,  0x52,  0x0B,  0xFE,  0x10,  0x00,  0x17,  0xFC, 	/* 3B620 */
+	0x20,  0x88,  0x20,  0x70,  0x41,  0x98,  0x4E,  0x07,  0xAC,  0x10,  0x20,  0x0B,  0xFE,  0x08,  0x20,  0x01, 	/* 3B630 */
+	0xFC,  0x00,  0x20,  0x47,  0xFF,  0x20,  0x00,  0x21,  0xFC,  0x09,  0x04,  0x09,  0xFC,  0x11,  0x04,  0x11, 	/* 3B640 */
+	0xFC,  0x21,  0x04,  0x21,  0xFC,  0x40,  0x98,  0x47,  0x06,  0xB1,  0x21,  0x10,  0x11,  0x10,  0x1F,  0xF0, 	/* 3B650 */
+	0x01,  0x1F,  0x07,  0xE2,  0x45,  0x6C,  0x25,  0x48,  0x25,  0x48,  0x07,  0xC8,  0x11,  0x0C,  0x13,  0x8C, 	/* 3B660 */
+	0x23,  0x54,  0x25,  0x54,  0x49,  0x22,  0x41,  0x42,  0x41,  0x81,  0xB2,  0x20,  0x00,  0x1F,  0x3E,  0x11, 	/* 3B670 */
+	0x20,  0x01,  0x3C,  0x01,  0x20,  0x47,  0x3C,  0x24,  0x20,  0x24,  0x20,  0x04,  0xFF,  0x17,  0x32,  0x11, 	/* 3B680 */
+	0x32,  0x21,  0x2C,  0x21,  0x28,  0x41,  0x24,  0x42,  0x32,  0x4C,  0xC1,  0xB8,  0x21,  0x02,  0x11,  0x0C, 	/* 3B690 */
+	0x1F,  0xF0,  0x01,  0x10,  0x47,  0xD0,  0x25,  0x5F,  0x25,  0x54,  0x07,  0xD4,  0x05,  0x54,  0x15,  0x54, 	/* 3B6A0 */
+	0x17,  0xD4,  0x21,  0x24,  0x2F,  0xE4,  0x21,  0x44,  0x41,  0x04,  0x41,  0x04,  0xBE,  0x11,  0x04,  0x08, 	/* 3B6B0 */
+	0x88,  0x0B,  0xFE,  0x00,  0x20,  0x01,  0xFC,  0x40,  0x20,  0x27,  0xFF,  0x20,  0x40,  0x08,  0x22,  0x0B, 	/* 3B6C0 */
+	0xE2,  0x10,  0x34,  0x17,  0xA8,  0x20,  0xA4,  0x21,  0x22,  0x46,  0x21,  0x40,  0x60,  0xBF,  0x04,  0x20, 	/* 3B6D0 */
+	0x24,  0x7E,  0x25,  0x94,  0x3C,  0x58,  0x04,  0x60,  0x7D,  0x84,  0x17,  0xFF,  0x14,  0x44,  0x24,  0x24, 	/* 3B6E0 */
+	0x44,  0x2C,  0x00,  0x88,  0x3E,  0xD0,  0x04,  0xA0,  0x18,  0x98,  0x60,  0x87,  0x01,  0x80,  0x81,  0x20, 	/* 3B6F0 */
+	0x00,  0x20,  0xFF,  0x26,  0x10,  0x38,  0x20,  0x21,  0x7E,  0x21,  0x42,  0x1F,  0x42,  0x04,  0x7E,  0x04, 	/* 3B700 */
+	0xC2,  0x75,  0x7E,  0x16,  0x42,  0x16,  0x42,  0x25,  0x7E,  0x24,  0xA4,  0x44,  0x42,  0x0D,  0x81,  0x85, 	/* 3B710 */
+	0x21,  0x00,  0x11,  0x00,  0x11,  0xFE,  0x01,  0x40,  0x42,  0x40,  0x23,  0xFF,  0x24,  0x88,  0x01,  0x10, 	/* 3B720 */
+	0x03,  0xFE,  0x0D,  0x10,  0x11,  0xFC,  0x11,  0x10,  0x21,  0xFC,  0x21,  0x10,  0x41,  0xFF,  0x40,  0x00, 	/* 3B730 */
+	0x94,  0x21,  0x00,  0x17,  0xDE,  0x11,  0x0A,  0x07,  0xCA,  0x01,  0x12,  0x41,  0xA2,  0x26,  0x4C,  0x20, 	/* 3B740 */
+	0x20,  0x09,  0xC8,  0x08,  0x58,  0x10,  0x26,  0x17,  0xFD,  0x21,  0x28,  0x21,  0x24,  0x42,  0x22,  0x44, 	/* 3B750 */
+	0x20,  0x98,  0x10,  0x04,  0x08,  0x18,  0x0B,  0xE0,  0x01,  0x24,  0x00,  0xA8,  0x47,  0xFF,  0x20,  0x70, 	/* 3B760 */
+	0x20,  0xA8,  0x01,  0x24,  0x0B,  0xFE,  0x15,  0x25,  0x11,  0xFC,  0x21,  0x24,  0x21,  0x24,  0x41,  0xFC, 	/* 3B770 */
+	0x40,  0x00,  0x9B,  0x20,  0x84,  0x17,  0xFE,  0x12,  0x94,  0x02,  0x94,  0x07,  0xFF,  0x41,  0x8C,  0x21, 	/* 3B780 */
+	0xCD,  0x22,  0x97,  0x04,  0x20,  0x11,  0xFC,  0x11,  0x04,  0x21,  0xFC,  0x21,  0x04,  0x21,  0x04,  0x41, 	/* 3B790 */
+	0xFC,  0x40,  0x00,  0x9C,  0x11,  0x04,  0x09,  0x04,  0x0F,  0xDF,  0x01,  0x04,  0x07,  0xDF,  0x41,  0x04, 	/* 3B7A0 */
+	0x22,  0x8A,  0x24,  0x51,  0x08,  0x00,  0x09,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x21,  0x04,  0x21,  0x04, 	/* 3B7B0 */
+	0x41,  0xFC,  0x40,  0x00,  0x9F,  0x10,  0x40,  0x08,  0x80,  0x0B,  0x38,  0x02,  0x08,  0x43,  0xB8,  0x22, 	/* 3B7C0 */
+	0x08,  0x22,  0x08,  0x03,  0xF8,  0x08,  0x80,  0x08,  0xFE,  0x11,  0x02,  0x16,  0x12,  0x23,  0x4A,  0x22, 	/* 3B7D0 */
+	0xA2,  0x44,  0x82,  0x48,  0x0C,  0xA4,  0x10,  0x00,  0x0B,  0xDE,  0x0A,  0x52,  0x03,  0xDE,  0x02,  0x52, 	/* 3B7E0 */
+	0x43,  0xDE,  0x22,  0x02,  0x26,  0xFA,  0x0A,  0x22,  0x0A,  0x22,  0x12,  0xFA,  0x12,  0x22,  0x22,  0x22, 	/* 3B7F0 */
+	0x22,  0xFA,  0x42,  0x02,  0x42,  0x06,  0xA6,  0x10,  0x20,  0x08,  0x20,  0x0F,  0xFF,  0x00,  0x88,  0x02, 	/* 3B800 */
+	0x8A,  0x41,  0x04,  0x23,  0xFE,  0x25,  0x05,  0x01,  0xFC,  0x09,  0x04,  0x11,  0xFC,  0x10,  0x20,  0x21, 	/* 3B810 */
+	0x24,  0x22,  0x22,  0x44,  0x21,  0x40,  0x60,  0xAD,  0x10,  0x00,  0x0F,  0xFF,  0x08,  0x50,  0x03,  0xFE, 	/* 3B820 */
+	0x02,  0x52,  0x43,  0xFE,  0x20,  0x00,  0x21,  0xFC,  0x09,  0x04,  0x09,  0xFC,  0x11,  0x04,  0x11,  0xFC, 	/* 3B830 */
+	0x20,  0x20,  0x27,  0xFF,  0x40,  0x20,  0x40,  0x20,  0xAE,  0x21,  0x00,  0x11,  0x1E,  0x1F,  0xF2,  0x01, 	/* 3B840 */
+	0x12,  0x47,  0xD2,  0x24,  0x5E,  0x24,  0x52,  0x07,  0xD2,  0x04,  0x52,  0x14,  0x5E,  0x17,  0xD2,  0x21, 	/* 3B850 */
+	0x12,  0x2F,  0xF2,  0x21,  0x12,  0x41,  0x22,  0x41,  0x46,  0xAF,  0x10,  0x00,  0x09,  0xFC,  0x08,  0x04, 	/* 3B860 */
+	0x03,  0xFF,  0x00,  0x04,  0x41,  0xFC,  0x20,  0x00,  0x23,  0xDE,  0x08,  0x92,  0x08,  0xFE,  0x13,  0x04, 	/* 3B870 */
+	0x17,  0xFF,  0x20,  0x84,  0x20,  0x44,  0x40,  0x44,  0x40,  0x0C,  0xB0,  0x10,  0x20,  0x09,  0xFC,  0x09, 	/* 3B880 */
+	0x24,  0x01,  0xFC,  0x40,  0x20,  0x27,  0xFF,  0x20,  0x00,  0x01,  0xFC,  0x09,  0x04,  0x09,  0xFC,  0x11, 	/* 3B890 */
+	0x04,  0x11,  0xFC,  0x21,  0x04,  0x21,  0xFC,  0x40,  0x8C,  0x47,  0x03,  0xB4,  0x24,  0x10,  0x12,  0x92, 	/* 3B8A0 */
+	0x12,  0xFE,  0x01,  0x14,  0x01,  0x14,  0x43,  0x18,  0x25,  0xFF,  0x29,  0x14,  0x03,  0x22,  0x13,  0x7E, 	/* 3B8B0 */
+	0x15,  0xA2,  0x19,  0x3E,  0x21,  0x22,  0x21,  0x22,  0x41,  0x3E,  0x46,  0x00,  0xB8,  0x10,  0x88,  0x08, 	/* 3B8C0 */
+	0x88,  0x0F,  0xFF,  0x00,  0x88,  0x02,  0xAA,  0x42,  0xAA,  0x24,  0xAB,  0x20,  0x00,  0x09,  0xFC,  0x09, 	/* 3B8D0 */
+	0x04,  0x11,  0xFC,  0x11,  0x04,  0x21,  0xFC,  0x21,  0x04,  0x41,  0x04,  0x42,  0x0C,  0xBA,  0x10,  0x00, 	/* 3B8E0 */
+	0x0B,  0xFE,  0x0A,  0x02,  0x03,  0xFE,  0x02,  0x00,  0x42,  0xFC,  0x22,  0x08,  0x23,  0xFE,  0x0A,  0x10, 	/* 3B8F0 */
+	0x0A,  0x30,  0x13,  0xEF,  0x12,  0x42,  0x24,  0xE4,  0x27,  0x9F,  0x48,  0x84,  0x51,  0x8C,  0xBC,  0x10, 	/* 3B900 */
+	0x20,  0x08,  0x20,  0x0B,  0xFE,  0x00,  0x88,  0x07,  0xFF,  0x40,  0x00,  0x21,  0xFC,  0x21,  0x24,  0x09, 	/* 3B910 */
+	0xFC,  0x09,  0x24,  0x11,  0xFC,  0x10,  0x20,  0x23,  0xFE,  0x20,  0x20,  0x47,  0xFF,  0x40,  0x00,  0x80, 	/* 3B920 */
+	0x20,  0x00,  0x17,  0xFE,  0x11,  0x4A,  0x05,  0x6A,  0x05,  0x6A,  0x4A,  0x52,  0x22,  0x52,  0x25,  0xAC, 	/* 3B930 */
+	0x00,  0x00,  0x08,  0x84,  0x12,  0xF7,  0x12,  0x94,  0x22,  0x94,  0x22,  0xD4,  0x43,  0xBF,  0x4E,  0x00, 	/* 3B940 */
+	0x81,  0x10,  0x10,  0x08,  0x90,  0x08,  0x9E,  0x00,  0x90,  0x00,  0x90,  0x43,  0xFF,  0x20,  0x00,  0x20, 	/* 3B950 */
+	0x84,  0x0A,  0x94,  0x0A,  0x94,  0x12,  0xF7,  0x12,  0x94,  0x22,  0x94,  0x22,  0xD4,  0x43,  0xBF,  0x46, 	/* 3B960 */
+	0x00,  0x82,  0x21,  0x08,  0x15,  0x48,  0x15,  0x48,  0x05,  0x5F,  0x07,  0xD4,  0x40,  0x24,  0x27,  0xC4, 	/* 3B970 */
+	0x20,  0x14,  0x07,  0xD4,  0x11,  0x14,  0x17,  0xC8,  0x21,  0x08,  0x21,  0x54,  0x21,  0x94,  0x46,  0x22, 	/* 3B980 */
+	0x40,  0x41,  0x84,  0x11,  0xD2,  0x08,  0x54,  0x0A,  0x89,  0x02,  0x8A,  0x01,  0x04,  0x43,  0xFE,  0x24, 	/* 3B990 */
+	0x01,  0x21,  0xF8,  0x09,  0x08,  0x09,  0x08,  0x11,  0xF8,  0x11,  0x08,  0x20,  0x88,  0x20,  0x90,  0x4F, 	/* 3B9A0 */
+	0xFF,  0x40,  0x00,  0x86,  0x10,  0x20,  0x09,  0xFC,  0x08,  0x20,  0x03,  0xFE,  0x00,  0x00,  0x40,  0x84, 	/* 3B9B0 */
+	0x23,  0xDF,  0x20,  0x84,  0x08,  0xE4,  0x0B,  0x1F,  0x10,  0x00,  0x17,  0xFF,  0x20,  0x90,  0x20,  0x91, 	/* 3B9C0 */
+	0x43,  0x11,  0x4C,  0x0F,  0x8E,  0x10,  0x84,  0x08,  0x84,  0x0F,  0xF4,  0x00,  0x88,  0x03,  0xE8,  0x40, 	/* 3B9D0 */
+	0x12,  0x23,  0xE2,  0x22,  0x24,  0x0B,  0xE4,  0x08,  0x09,  0x12,  0x21,  0x11,  0x22,  0x21,  0x52,  0x20, 	/* 3B9E0 */
+	0xE4,  0x47,  0x08,  0x40,  0x10,  0x91,  0x10,  0x00,  0x0F,  0xFF,  0x08,  0x50,  0x03,  0xDE,  0x02,  0x52, 	/* 3B9F0 */
+	0x42,  0x52,  0x23,  0xDE,  0x20,  0x50,  0x0B,  0xFE,  0x0A,  0x22,  0x12,  0x22,  0x13,  0xFE,  0x22,  0x22, 	/* 3BA00 */
+	0x22,  0x22,  0x43,  0xFE,  0x40,  0x00,  0x97,  0x10,  0x00,  0x0B,  0xDE,  0x0A,  0x52,  0x03,  0xDE,  0x42, 	/* 3BA10 */
+	0x52,  0x22,  0x52,  0x23,  0xDE,  0x02,  0x02,  0x0A,  0xFA,  0x0A,  0x8A,  0x12,  0xFA,  0x12,  0x8A,  0x22, 	/* 3BA20 */
+	0x8A,  0x22,  0xFA,  0x42,  0x02,  0x42,  0x06,  0xA1,  0x10,  0x00,  0x08,  0xF8,  0x08,  0x88,  0x00,  0x88, 	/* 3BA30 */
+	0x00,  0xF8,  0x43,  0xDE,  0x22,  0x52,  0x22,  0x52,  0x0B,  0xDE,  0x08,  0x20,  0x17,  0xFF,  0x10,  0xA8, 	/* 3BA40 */
+	0x21,  0x24,  0x22,  0x22,  0x44,  0x21,  0x40,  0x20,  0xA3,  0x22,  0x08,  0x12,  0x08,  0x1F,  0xD4,  0x02, 	/* 3BA50 */
+	0x14,  0x07,  0xA2,  0x44,  0xC1,  0x24,  0xBE,  0x27,  0x88,  0x0C,  0x88,  0x0C,  0x88,  0x17,  0xFF,  0x12, 	/* 3BA60 */
+	0x08,  0x2F,  0xC8,  0x22,  0x08,  0x42,  0x08,  0x42,  0x08,  0xA4,  0x10,  0x00,  0x09,  0xFE,  0x09,  0x52, 	/* 3BA70 */
+	0x01,  0xFE,  0x00,  0x20,  0x43,  0xFE,  0x20,  0x20,  0x27,  0xFF,  0x08,  0x88,  0x08,  0x50,  0x17,  0xFF, 	/* 3BA80 */
+	0x10,  0x20,  0x21,  0xFC,  0x20,  0x20,  0x40,  0x20,  0x40,  0x20,  0xAA,  0x10,  0x00,  0x0B,  0xFE,  0x08, 	/* 3BA90 */
+	0x20,  0x07,  0xFF,  0x04,  0x21,  0x45,  0xAD,  0x24,  0x21,  0x21,  0xAC,  0x08,  0x50,  0x09,  0x8C,  0x16, 	/* 3BAA0 */
+	0x73,  0x10,  0x00,  0x23,  0xFE,  0x20,  0x22,  0x40,  0x2C,  0x40,  0x20,  0xB1,  0x20,  0x00,  0x17,  0xDC, 	/* 3BAB0 */
+	0x14,  0x54,  0x04,  0x55,  0x47,  0xD5,  0x25,  0x53,  0x25,  0x60,  0x07,  0xC0,  0x05,  0x7E,  0x15,  0x52, 	/* 3BAC0 */
+	0x17,  0xEA,  0x24,  0x0C,  0x29,  0x84,  0x29,  0x4C,  0x52,  0x12,  0x44,  0x61,  0xB3,  0x10,  0x20,  0x08, 	/* 3BAD0 */
+	0x40,  0x0B,  0xFE,  0x02,  0x12,  0x02,  0xE2,  0x42,  0xAA,  0x22,  0x72,  0x23,  0xFE,  0x0A,  0x6A,  0x0B, 	/* 3BAE0 */
+	0xA6,  0x10,  0x20,  0x17,  0xFF,  0x20,  0x50,  0x20,  0x88,  0x43,  0x04,  0x4C,  0x03,  0xB9,  0x10,  0x40, 	/* 3BAF0 */
+	0x08,  0xF8,  0x09,  0x10,  0x07,  0xFF,  0x02,  0x29,  0x42,  0xC7,  0x23,  0x7C,  0x22,  0x00,  0x0B,  0xFF, 	/* 3BB00 */
+	0x0A,  0x00,  0x12,  0x7C,  0x12,  0x00,  0x24,  0xFE,  0x24,  0x82,  0x48,  0xFE,  0x40,  0x00,  0x80,  0x21, 	/* 3BB10 */
+	0x10,  0x12,  0x10,  0x17,  0x90,  0x04,  0x9F,  0x07,  0x94,  0x44,  0xA4,  0x27,  0xA4,  0x21,  0x54,  0x0F, 	/* 3BB20 */
+	0xD4,  0x12,  0x18,  0x13,  0x88,  0x12,  0x88,  0x24,  0x94,  0x24,  0x94,  0x4B,  0x22,  0x50,  0x41,  0x81, 	/* 3BB30 */
+	0x10,  0x00,  0x0F,  0xFC,  0x0C,  0xA4,  0x04,  0xA4,  0x47,  0xFC,  0x21,  0x00,  0x21,  0xFE,  0x01,  0x42, 	/* 3BB40 */
+	0x0B,  0xFA,  0x0B,  0x4A,  0x15,  0xFA,  0x10,  0x62,  0x20,  0x52,  0x20,  0xFA,  0x47,  0x0A,  0x40,  0x0C, 	/* 3BB50 */
+	0x82,  0x10,  0x10,  0x08,  0x10,  0x0B,  0xFF,  0x02,  0x24,  0x02,  0x48,  0x43,  0xFF,  0x22,  0x28,  0x22, 	/* 3BB60 */
+	0xFE,  0x0A,  0x2A,  0x0B,  0xFF,  0x12,  0x2A,  0x12,  0xFE,  0x24,  0x6C,  0x24,  0xAA,  0x49,  0x29,  0x40, 	/* 3BB70 */
+	0x28,  0x83,  0x10,  0x50,  0x0B,  0xFE,  0x0A,  0x52,  0x03,  0xFE,  0x42,  0x52,  0x23,  0xFE,  0x20,  0x00, 	/* 3BB80 */
+	0x03,  0xFF,  0x0A,  0x00,  0x0A,  0xFE,  0x12,  0x00,  0x13,  0xFF,  0x24,  0xA2,  0x24,  0x94,  0x48,  0xCC, 	/* 3BB90 */
+	0x53,  0x03,  0x86,  0x10,  0x20,  0x09,  0xFE,  0x08,  0x20,  0x00,  0x88,  0x07,  0xFF,  0x40,  0x88,  0x20, 	/* 3BBA0 */
+	0x00,  0x21,  0xFC,  0x09,  0x04,  0x09,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x21,  0x04,  0x21,  0xFC,  0x40, 	/* 3BBB0 */
+	0xCC,  0x47,  0x02,  0x94,  0x10,  0x00,  0x0B,  0xFF,  0x09,  0x24,  0x02,  0x22,  0x07,  0xFF,  0x4A,  0x66, 	/* 3BBC0 */
+	0x23,  0xBA,  0x22,  0xAA,  0x0B,  0x76,  0x0A,  0x22,  0x12,  0x66,  0x13,  0xBA,  0x22,  0xAA,  0x23,  0x76, 	/* 3BBD0 */
+	0x42,  0x22,  0x42,  0x26,  0x95,  0x10,  0x00,  0x09,  0xFE,  0x09,  0x02,  0x01,  0xFE,  0x01,  0x02,  0x41, 	/* 3BBE0 */
+	0xFE,  0x20,  0x84,  0x20,  0x84,  0x0B,  0x5A,  0x08,  0x84,  0x11,  0x4A,  0x13,  0xFF,  0x20,  0x21,  0x22, 	/* 3BBF0 */
+	0x92,  0x42,  0x49,  0x44,  0x49,  0x98,  0x10,  0x20,  0x08,  0x20,  0x0F,  0xFF,  0x04,  0xA1,  0x06,  0x8A, 	/* 3BC00 */
+	0x42,  0x79,  0x24,  0x01,  0x23,  0xFE,  0x0A,  0x92,  0x0B,  0xFE,  0x10,  0x00,  0x17,  0xFF,  0x20,  0x20, 	/* 3BC10 */
+	0x20,  0x20,  0x40,  0x20,  0x40,  0x60,  0x9B,  0x10,  0x50,  0x0F,  0xFF,  0x08,  0x50,  0x03,  0xFE,  0x02, 	/* 3BC20 */
+	0x02,  0x42,  0xFA,  0x20,  0x00,  0x27,  0xFF,  0x08,  0x42,  0x08,  0xAC,  0x13,  0x28,  0x10,  0xD4,  0x23, 	/* 3BC30 */
+	0x34,  0x20,  0xD2,  0x47,  0x11,  0x40,  0x60,  0x9F,  0x10,  0x20,  0x08,  0x20,  0x0F,  0xFF,  0x00,  0x51, 	/* 3BC40 */
+	0x07,  0xAE,  0x42,  0xAA,  0x22,  0xAA,  0x25,  0xAD,  0x00,  0x20,  0x09,  0x04,  0x11,  0xFC,  0x11,  0x04, 	/* 3BC50 */
+	0x21,  0xFC,  0x21,  0x04,  0x42,  0x04,  0x44,  0x04,  0xA0,  0x10,  0x20,  0x0F,  0xFF,  0x08,  0x00,  0x01, 	/* 3BC60 */
+	0xFC,  0x41,  0x04,  0x21,  0xFC,  0x20,  0x00,  0x03,  0xFF,  0x0A,  0x01,  0x0A,  0xFD,  0x10,  0x22,  0x10, 	/* 3BC70 */
+	0xD4,  0x23,  0x38,  0x20,  0xD4,  0x47,  0x13,  0x40,  0x30,  0xA1,  0x20,  0x00,  0x13,  0xFC,  0x10,  0x40, 	/* 3BC80 */
+	0x07,  0xFE,  0x44,  0x42,  0x25,  0xDA,  0x24,  0x42,  0x01,  0xD8,  0x08,  0x00,  0x0F,  0xFF,  0x10,  0x40, 	/* 3BC90 */
+	0x13,  0xFE,  0x22,  0x52,  0x22,  0x52,  0x42,  0x52,  0x42,  0x06,  0xA4,  0x10,  0x20,  0x0B,  0xFE,  0x08, 	/* 3BCA0 */
+	0x20,  0x01,  0xFC,  0x00,  0x00,  0x47,  0xFF,  0x20,  0x02,  0x21,  0xF8,  0x08,  0x20,  0x0F,  0xFF,  0x10, 	/* 3BCB0 */
+	0x04,  0x13,  0xFF,  0x22,  0x64,  0x22,  0x54,  0x43,  0xC4,  0x40,  0x0C,  0xAB,  0x20,  0x10,  0x17,  0xD0, 	/* 3BCC0 */
+	0x15,  0x10,  0x07,  0xDF,  0x04,  0x60,  0x47,  0xC0,  0x25,  0x1E,  0x25,  0x00,  0x0F,  0xC0,  0x08,  0x00, 	/* 3BCD0 */
+	0x13,  0xFC,  0x12,  0x94,  0x22,  0x94,  0x22,  0x94,  0x4F,  0xFF,  0x40,  0x00,  0xAC,  0x10,  0x20,  0x08, 	/* 3BCE0 */
+	0x3E,  0x08,  0x20,  0x07,  0xFF,  0x04,  0x01,  0x45,  0xFD,  0x21,  0x24,  0x22,  0x52,  0x09,  0xFC,  0x0B, 	/* 3BCF0 */
+	0x06,  0x15,  0xFD,  0x11,  0x04,  0x21,  0xFC,  0x21,  0x04,  0x41,  0xFC,  0x40,  0x00,  0xAE,  0x21,  0x28, 	/* 3BD00 */
+	0x11,  0xA9,  0x11,  0x6A,  0x02,  0x28,  0x03,  0xFF,  0x46,  0x44,  0x26,  0x28,  0x2B,  0xFF,  0x02,  0x10, 	/* 3BD10 */
+	0x12,  0xFE,  0x12,  0x10,  0x23,  0xFF,  0x22,  0x18,  0x22,  0x24,  0x42,  0xC2,  0x43,  0x01,  0xAF,  0x10, 	/* 3BD20 */
+	0x00,  0x0F,  0xDF,  0x08,  0x41,  0x03,  0xCF,  0x40,  0x41,  0x27,  0xDF,  0x20,  0x88,  0x00,  0x90,  0x09, 	/* 3BD30 */
+	0xFE,  0x0B,  0x20,  0x15,  0xFC,  0x11,  0x20,  0x21,  0xFC,  0x21,  0x20,  0x41,  0xFF,  0x40,  0x00,  0xB1, 	/* 3BD40 */
+	0x10,  0x20,  0x0B,  0xFE,  0x0A,  0x02,  0x01,  0xFE,  0x00,  0xA4,  0x41,  0x28,  0x22,  0x70,  0x21,  0xFC, 	/* 3BD50 */
+	0x07,  0x04,  0x11,  0xFC,  0x11,  0x04,  0x21,  0xFC,  0x21,  0x04,  0x21,  0xFC,  0x40,  0xCC,  0x47,  0x02, 	/* 3BD60 */
+	0xB3,  0x21,  0x08,  0x15,  0x28,  0x17,  0xFE,  0x05,  0x28,  0x01,  0x08,  0x4F,  0xFF,  0x22,  0x94,  0x22, 	/* 3BD70 */
+	0xD5,  0x04,  0xA7,  0x0B,  0xFC,  0x12,  0x04,  0x13,  0xFC,  0x22,  0x04,  0x22,  0x04,  0x43,  0xFC,  0x40, 	/* 3BD80 */
+	0x00,  0xB6,  0x20,  0x00,  0x17,  0xBE,  0x14,  0xA2,  0x07,  0xBE,  0x04,  0xA2,  0x47,  0xBE,  0x24,  0x0A, 	/* 3BD90 */
+	0x24,  0xF2,  0x04,  0x22,  0x0D,  0xFE,  0x14,  0x22,  0x14,  0xFA,  0x24,  0x8A,  0x24,  0x8A,  0x44,  0xFA, 	/* 3BDA0 */
+	0x44,  0x06,  0xBA,  0x20,  0x14,  0x17,  0x92,  0x14,  0x97,  0x04,  0xF8,  0x07,  0x8A,  0x44,  0x9D,  0x24, 	/* 3BDB0 */
+	0xE3,  0x27,  0x95,  0x04,  0x92,  0x14,  0x8F,  0x17,  0xF8,  0x20,  0x0A,  0x25,  0x0C,  0x24,  0xB5,  0x48, 	/* 3BDC0 */
+	0xC3,  0x50,  0x01,  0xBE,  0x10,  0x20,  0x08,  0x3E,  0x08,  0x20,  0x03,  0xFF,  0x02,  0x5A,  0x43,  0xE2, 	/* 3BDD0 */
+	0x22,  0x7E,  0x22,  0xFC,  0x0A,  0xA4,  0x0A,  0xFC,  0x12,  0xA4,  0x12,  0xFC,  0x23,  0x52,  0x25,  0x51, 	/* 3BDE0 */
+	0x46,  0x45,  0x48,  0x3C,  0x81,  0x10,  0x88,  0x08,  0x50,  0x0B,  0xFE,  0x00,  0x20,  0x01,  0xFC,  0x40, 	/* 3BDF0 */
+	0x20,  0x27,  0xFF,  0x20,  0xA8,  0x09,  0xFC,  0x0B,  0x0A,  0x15,  0xF9,  0x11,  0x08,  0x21,  0xFA,  0x21, 	/* 3BE00 */
+	0x24,  0x41,  0xD8,  0x47,  0x07,  0x89,  0x10,  0x20,  0x08,  0x20,  0x0F,  0xFF,  0x04,  0x41,  0x05,  0x9D, 	/* 3BE10 */
+	0x41,  0x04,  0x21,  0xDC,  0x21,  0x04,  0x09,  0xFC,  0x08,  0x80,  0x11,  0xFE,  0x16,  0x12,  0x23,  0x4A, 	/* 3BE20 */
+	0x22,  0xAA,  0x44,  0xA2,  0x40,  0x0C,  0x8B,  0x10,  0x20,  0x08,  0x20,  0x0F,  0xFF,  0x04,  0x0D,  0x07, 	/* 3BE30 */
+	0xF1,  0x41,  0x24,  0x20,  0xA8,  0x27,  0xFF,  0x00,  0xA8,  0x09,  0x24,  0x17,  0xFF,  0x12,  0x22,  0x23, 	/* 3BE40 */
+	0xFE,  0x22,  0x22,  0x43,  0xFE,  0x40,  0x00,  0x8F,  0x21,  0x02,  0x16,  0x7A,  0x14,  0x2A,  0x05,  0x2A, 	/* 3BE50 */
+	0x07,  0x4A,  0x44,  0x9A,  0x21,  0x4A,  0x22,  0x2A,  0x05,  0xDA,  0x10,  0x8A,  0x13,  0xEA,  0x24,  0xA2, 	/* 3BE60 */
+	0x22,  0xC2,  0x22,  0xE2,  0x41,  0x82,  0x46,  0x06,  0x91,  0x10,  0x00,  0x09,  0xFC,  0x09,  0x04,  0x01, 	/* 3BE70 */
+	0xFC,  0x01,  0x04,  0x41,  0xFC,  0x20,  0x88,  0x23,  0xFE,  0x08,  0x88,  0x0F,  0xFF,  0x11,  0x24,  0x13, 	/* 3BE80 */
+	0x2A,  0x24,  0xF1,  0x20,  0xA8,  0x43,  0x26,  0x40,  0x60,  0x95,  0x21,  0x00,  0x11,  0x7F,  0x15,  0x08, 	/* 3BE90 */
+	0x05,  0xD0,  0x45,  0x3E,  0x25,  0x22,  0x2F,  0xE2,  0x01,  0x3E,  0x05,  0xA2,  0x15,  0x7E,  0x15,  0x22, 	/* 3BEA0 */
+	0x2B,  0xA2,  0x20,  0xBE,  0x21,  0x14,  0x42,  0x22,  0x4C,  0xC1,  0x98,  0x10,  0x20,  0x08,  0x3E,  0x08, 	/* 3BEB0 */
+	0x20,  0x03,  0xFF,  0x02,  0x5A,  0x43,  0xE2,  0x22,  0xFE,  0x22,  0xA4,  0x0A,  0xFC,  0x0A,  0xA4,  0x12, 	/* 3BEC0 */
+	0xFC,  0x12,  0x00,  0x22,  0xFE,  0x24,  0xAA,  0x47,  0xFF,  0x48,  0x00,  0x9A,  0x22,  0x08,  0x12,  0x08, 	/* 3BED0 */
+	0x1F,  0xD4,  0x02,  0x14,  0x07,  0xA2,  0x44,  0xC1,  0x24,  0xFE,  0x27,  0x92,  0x04,  0xB6,  0x14,  0xDA, 	/* 3BEE0 */
+	0x17,  0x92,  0x22,  0x36,  0x3F,  0xB6,  0x22,  0x5A,  0x42,  0x12,  0x42,  0x36,  0x9B,  0x20,  0x20,  0x17, 	/* 3BEF0 */
+	0xFF,  0x12,  0x00,  0x01,  0xFE,  0x40,  0x00,  0x21,  0xFC,  0x21,  0x04,  0x01,  0xFC,  0x10,  0x40,  0x17, 	/* 3BF00 */
+	0x4E,  0x15,  0xFA,  0x27,  0x6A,  0x25,  0xAE,  0x27,  0xCA,  0x45,  0x6B,  0x49,  0x91,  0x9D,  0x10,  0x00, 	/* 3BF10 */
+	0x0B,  0xFF,  0x0A,  0x22,  0x02,  0xCC,  0x02,  0x44,  0x43,  0xFF,  0x22,  0x44,  0x22,  0xEE,  0x0B,  0x55, 	/* 3BF20 */
+	0x0A,  0x54,  0x12,  0x90,  0x14,  0x9E,  0x24,  0x90,  0x28,  0x90,  0x43,  0xFF,  0x40,  0x00,  0x9E,  0x22, 	/* 3BF30 */
+	0x10,  0x12,  0x1C,  0x1F,  0xA4,  0x02,  0x48,  0x4F,  0xBE,  0x22,  0x0A,  0x3F,  0xCA,  0x00,  0x7F,  0x07, 	/* 3BF40 */
+	0x8A,  0x14,  0x8A,  0x17,  0xBE,  0x24,  0x88,  0x27,  0x88,  0x24,  0x88,  0x44,  0x88,  0x45,  0x98,  0x9F, 	/* 3BF50 */
+	0x10,  0x88,  0x0F,  0xFF,  0x08,  0xA8,  0x01,  0xFC,  0x00,  0x24,  0x47,  0xFF,  0x20,  0x24,  0x21,  0xFC, 	/* 3BF60 */
+	0x08,  0x20,  0x0A,  0xAA,  0x12,  0xAA,  0x13,  0xFE,  0x22,  0x22,  0x23,  0xAE,  0x42,  0xAA,  0x44,  0xAA, 	/* 3BF70 */
+	0xA6,  0x20,  0x12,  0x1F,  0xD2,  0x12,  0x7E,  0x02,  0x14,  0x05,  0x54,  0x49,  0x98,  0x23,  0xFF,  0x25, 	/* 3BF80 */
+	0x10,  0x09,  0x7C,  0x03,  0xA4,  0x13,  0xA4,  0x15,  0x7C,  0x29,  0x64,  0x21,  0x24,  0x41,  0x3C,  0x46, 	/* 3BF90 */
+	0x00,  0xA7,  0x21,  0x10,  0x11,  0x10,  0x1F,  0xFF,  0x04,  0x50,  0x02,  0x9E,  0x4F,  0xE2,  0x20,  0x1E, 	/* 3BFA0 */
+	0x27,  0xD0,  0x04,  0x5F,  0x17,  0xD0,  0x14,  0x5F,  0x27,  0xD0,  0x24,  0x5F,  0x24,  0x50,  0x44,  0x51, 	/* 3BFB0 */
+	0x44,  0xCF,  0xAC,  0x21,  0x00,  0x11,  0x3F,  0x11,  0x04,  0x0F,  0xE8,  0x41,  0x1E,  0x27,  0xD2,  0x25, 	/* 3BFC0 */
+	0x52,  0x05,  0x5E,  0x15,  0x52,  0x17,  0xDE,  0x11,  0x12,  0x23,  0x92,  0x23,  0x5E,  0x25,  0x14,  0x49, 	/* 3BFD0 */
+	0x22,  0x41,  0x41,  0xB0,  0x20,  0x00,  0x1F,  0xFF,  0x12,  0x54,  0x02,  0x52,  0x02,  0xFF,  0x4F,  0xB6, 	/* 3BFE0 */
+	0x28,  0xB6,  0x28,  0xDA,  0x08,  0xB6,  0x0E,  0x92,  0x12,  0xB6,  0x12,  0xB6,  0x22,  0xDA,  0x22,  0xB6, 	/* 3BFF0 */
+	0x42,  0x92,  0x4C,  0x96,  0xB2,  0x21,  0x08,  0x11,  0x08,  0x12,  0x88,  0x04,  0x5F,  0x4B,  0x94,  0x20, 	/* 3C000 */
+	0x24,  0x2F,  0xC4,  0x0B,  0x54,  0x0B,  0x54,  0x1F,  0xD4,  0x10,  0x08,  0x24,  0x88,  0x24,  0x94,  0x26, 	/* 3C010 */
+	0xD4,  0x49,  0x22,  0x52,  0x41,  0xBE,  0x20,  0x00,  0x17,  0xBE,  0x14,  0xA2,  0x07,  0xBE,  0x04,  0xA2, 	/* 3C020 */
+	0x47,  0xBE,  0x24,  0x42,  0x25,  0xFA,  0x0C,  0x42,  0x0D,  0xFA,  0x15,  0xDA,  0x15,  0x6A,  0x25,  0xFA, 	/* 3C030 */
+	0x24,  0xD2,  0x45,  0x4A,  0x44,  0x46,  0x8C,  0x20,  0x88,  0x17,  0xFF,  0x10,  0x88,  0x03,  0xDE,  0x02, 	/* 3C040 */
+	0x52,  0x43,  0xDE,  0x20,  0x88,  0x20,  0x90,  0x09,  0xFE,  0x0B,  0x20,  0x15,  0xFC,  0x11,  0x20,  0x21, 	/* 3C050 */
+	0xFC,  0x21,  0x20,  0x41,  0xFE,  0x40,  0x00,  0x91,  0x27,  0xBE,  0x10,  0x00,  0x17,  0x9E,  0x04,  0x92, 	/* 3C060 */
+	0x45,  0x96,  0x20,  0x20,  0x27,  0xFF,  0x04,  0x50,  0x07,  0xFE,  0x0C,  0x52,  0x17,  0xFE,  0x15,  0x12, 	/* 3C070 */
+	0x25,  0xFC,  0x29,  0x10,  0x49,  0xD1,  0x53,  0x0F,  0x98,  0x12,  0x8A,  0x0A,  0x8A,  0x0F,  0xF4,  0x02, 	/* 3C080 */
+	0x9F,  0x47,  0xD4,  0x25,  0x74,  0x25,  0x54,  0x07,  0xDF,  0x01,  0x14,  0x17,  0xD4,  0x11,  0x1F,  0x2F, 	/* 3C090 */
+	0xF4,  0x22,  0x94,  0x22,  0x54,  0x44,  0x1F,  0x48,  0x00,  0xA3,  0x22,  0x22,  0x12,  0xFA,  0x1D,  0x05, 	/* 3C0A0 */
+	0x02,  0x72,  0x45,  0x05,  0x2F,  0x7F,  0x22,  0x52,  0x0B,  0x7B,  0x0A,  0x02,  0x03,  0xF8,  0x10,  0x08, 	/* 3C0B0 */
+	0x13,  0xF8,  0x22,  0x00,  0x23,  0xFC,  0x40,  0x04,  0x40,  0x38,  0xAB,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 3C0C0 */
+	0x84,  0x00,  0x84,  0x08,  0x84,  0x08,  0x88,  0x08,  0x88,  0x08,  0x90,  0x10,  0x80,  0x21,  0x40,  0x01, 	/* 3C0D0 */
+	0x40,  0x02,  0x20,  0x02,  0x10,  0x04,  0x08,  0x18,  0x04,  0x60,  0x03,  0xAF,  0x04,  0x00,  0x04,  0x00, 	/* 3C0E0 */
+	0x04,  0xFF,  0x04,  0x88,  0x14,  0x88,  0x15,  0x08,  0x15,  0x08,  0x24,  0x08,  0x04,  0x08,  0x06,  0x08, 	/* 3C0F0 */
+	0x09,  0x08,  0x09,  0x08,  0x10,  0x88,  0x10,  0x88,  0x20,  0x08,  0x40,  0x18,  0xB0,  0x00,  0x00,  0x1F, 	/* 3C100 */
+	0xFE,  0x10,  0x00,  0x10,  0x40,  0x10,  0x44,  0x12,  0x44,  0x12,  0x44,  0x12,  0x48,  0x14,  0x50,  0x14, 	/* 3C110 */
+	0x40,  0x10,  0xA0,  0x10,  0xA0,  0x21,  0x10,  0x22,  0x08,  0x4C,  0x04,  0x30,  0x03,  0xB8,  0x02,  0x00, 	/* 3C120 */
+	0x03,  0xF0,  0x04,  0x20,  0x18,  0x40,  0x00,  0xC0,  0x03,  0x20,  0x0C,  0x18,  0x70,  0x87,  0x04,  0x88, 	/* 3C130 */
+	0x04,  0x88,  0x08,  0x90,  0x11,  0x40,  0x02,  0x20,  0x04,  0x10,  0x18,  0x0C,  0x60,  0x03,  0xBC,  0x08, 	/* 3C140 */
+	0x40,  0x08,  0x40,  0x08,  0x40,  0x0A,  0x7E,  0x2A,  0x42,  0x2A,  0x82,  0x2C,  0x82,  0x29,  0x22,  0x48, 	/* 3C150 */
+	0x12,  0x08,  0x12,  0x0C,  0x02,  0x0A,  0x02,  0x11,  0x02,  0x11,  0x02,  0x20,  0x04,  0x40,  0x18,  0xBD, 	/* 3C160 */
+	0x08,  0x42,  0x08,  0x42,  0x10,  0x84,  0x21,  0x08,  0x10,  0x84,  0x08,  0x42,  0x08,  0x42,  0x00,  0x84, 	/* 3C170 */
+	0x08,  0x84,  0x08,  0x88,  0x09,  0x50,  0x11,  0x40,  0x02,  0x20,  0x04,  0x10,  0x08,  0x0C,  0x70,  0x03, 	/* 3C180 */
+	0x89,  0x08,  0x00,  0x08,  0xFF,  0x08,  0x00,  0x09,  0x00,  0x29,  0x7E,  0x2A,  0x42,  0x2A,  0x42,  0x28, 	/* 3C190 */
+	0x7E,  0x48,  0x40,  0x08,  0x40,  0x0C,  0x40,  0x0A,  0x40,  0x11,  0x80,  0x10,  0x80,  0x21,  0x00,  0x42, 	/* 3C1A0 */
+	0x00,  0x8A,  0x08,  0x40,  0x08,  0x40,  0x08,  0x40,  0x0A,  0x7F,  0x2A,  0x42,  0x2A,  0x94,  0x2C,  0x90, 	/* 3C1B0 */
+	0x29,  0x10,  0x48,  0x10,  0x0C,  0x18,  0x0A,  0x28,  0x09,  0x28,  0x11,  0x24,  0x10,  0x44,  0x20,  0x82, 	/* 3C1C0 */
+	0x41,  0x01,  0x8E,  0x01,  0x00,  0x09,  0x10,  0x09,  0x10,  0x11,  0x20,  0x22,  0x80,  0x04,  0x40,  0x18, 	/* 3C1D0 */
+	0x30,  0x61,  0x0C,  0x01,  0x10,  0x09,  0x10,  0x09,  0x20,  0x12,  0x80,  0x22,  0x40,  0x04,  0x20,  0x18, 	/* 3C1E0 */
+	0x18,  0x60,  0x06,  0x92,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x0A,  0x54,  0x2A,  0x52,  0x2C,  0x52, 	/* 3C1F0 */
+	0x2C,  0x91,  0x28,  0x91,  0x49,  0x14,  0x08,  0x14,  0x0C,  0x34,  0x0A,  0x08,  0x11,  0x08,  0x11,  0x10, 	/* 3C200 */
+	0x20,  0x60,  0x41,  0x80,  0x99,  0x00,  0x40,  0x00,  0xFC,  0x03,  0x08,  0x3C,  0x90,  0x02,  0x60,  0x01, 	/* 3C210 */
+	0x80,  0x0E,  0x00,  0x70,  0x00,  0x00,  0x84,  0x08,  0x84,  0x08,  0x88,  0x09,  0x50,  0x11,  0x40,  0x22, 	/* 3C220 */
+	0x20,  0x0C,  0x18,  0x70,  0x07,  0xAC,  0x08,  0x00,  0x08,  0xFF,  0x08,  0x80,  0x0A,  0x80,  0x0A,  0x80, 	/* 3C230 */
+	0x2C,  0xFE,  0x2C,  0x82,  0x28,  0x82,  0x48,  0x82,  0x08,  0xFE,  0x0C,  0x80,  0x0A,  0x80,  0x11,  0x80, 	/* 3C240 */
+	0x10,  0x80,  0x20,  0xFF,  0x40,  0x00,  0xAD,  0x00,  0x80,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x00, 	/* 3C250 */
+	0x00,  0x1F,  0xFF,  0x10,  0x00,  0x10,  0x44,  0x12,  0x44,  0x12,  0x48,  0x12,  0x50,  0x14,  0x40,  0x20, 	/* 3C260 */
+	0xA0,  0x21,  0x10,  0x46,  0x0C,  0x18,  0x03,  0xAE,  0x08,  0x40,  0x08,  0x40,  0x08,  0x7E,  0x0A,  0x42, 	/* 3C270 */
+	0x2A,  0x82,  0x2C,  0xF2,  0x2D,  0x92,  0x28,  0x92,  0x48,  0x92,  0x08,  0xF2,  0x0C,  0x84,  0x0A,  0x98, 	/* 3C280 */
+	0x12,  0x81,  0x10,  0x81,  0x20,  0x41,  0x40,  0x3F,  0xAF,  0x08,  0x00,  0x09,  0xFE,  0x09,  0x02,  0x0B, 	/* 3C290 */
+	0x02,  0x2B,  0x02,  0x2D,  0x7A,  0x2D,  0x4A,  0x29,  0x4A,  0x49,  0x4A,  0x09,  0x4A,  0x0D,  0x7A,  0x0D, 	/* 3C2A0 */
+	0x02,  0x13,  0x02,  0x13,  0x02,  0x21,  0x02,  0x41,  0x06,  0xB3,  0x08,  0x00,  0x09,  0xFF,  0x08,  0x10, 	/* 3C2B0 */
+	0x0A,  0x10,  0x0A,  0xFE,  0x2C,  0x92,  0x2C,  0x92,  0x28,  0x9A,  0x48,  0xAA,  0x08,  0xA6,  0x0C,  0xC2, 	/* 3C2C0 */
+	0x0A,  0x82,  0x12,  0x82,  0x11,  0x82,  0x20,  0x82,  0x40,  0x86,  0xB8,  0x08,  0x40,  0x08,  0x40,  0x08, 	/* 3C2D0 */
+	0x40,  0x0A,  0x7F,  0x0A,  0x50,  0x2C,  0x90,  0x2C,  0x90,  0x29,  0x1E,  0x28,  0x10,  0x48,  0x10,  0x0C, 	/* 3C2E0 */
+	0x10,  0x0A,  0x1E,  0x11,  0x10,  0x10,  0x10,  0x20,  0x10,  0x40,  0x10,  0xB9,  0x00,  0x80,  0x00,  0x80, 	/* 3C2F0 */
+	0x00,  0x80,  0x00,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08, 	/* 3C300 */
+	0x0F,  0xF8,  0x00,  0x00,  0x10,  0x08,  0x12,  0x44,  0x21,  0x22,  0x41,  0x22,  0xBA,  0x10,  0x80,  0x08, 	/* 3C310 */
+	0x80,  0x08,  0x80,  0x3F,  0xF8,  0x01,  0x08,  0x01,  0x10,  0x03,  0xFC,  0x02,  0x04,  0x04,  0x04,  0x0F, 	/* 3C320 */
+	0xFF,  0x08,  0x01,  0x14,  0x91,  0x32,  0x49,  0x49,  0x29,  0x09,  0x21,  0x08,  0x06,  0x88,  0x00,  0x04, 	/* 3C330 */
+	0x7F,  0xA4,  0x08,  0x24,  0x08,  0x24,  0x0F,  0x24,  0x11,  0x24,  0x12,  0x24,  0x2A,  0x24,  0x44,  0x24, 	/* 3C340 */
+	0x08,  0x04,  0x10,  0x04,  0x20,  0x0C,  0x10,  0x00,  0x14,  0x44,  0x22,  0x22,  0x42,  0x21,  0x8B,  0x08, 	/* 3C350 */
+	0x40,  0x08,  0x40,  0x08,  0x40,  0x1F,  0xFE,  0x10,  0xE0,  0x30,  0xE0,  0x51,  0x50,  0x12,  0x48,  0x14, 	/* 3C360 */
+	0x44,  0x18,  0x42,  0x10,  0x40,  0x00,  0x00,  0x10,  0x04,  0x12,  0x22,  0x21,  0x11,  0x41,  0x11,  0x8F, 	/* 3C370 */
+	0x00,  0x80,  0x01,  0x00,  0x1F,  0xF0,  0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x1F,  0xF0,  0x10,  0x00, 	/* 3C380 */
+	0x1F,  0xFF,  0x10,  0x00,  0x1F,  0xFE,  0x00,  0x22,  0x29,  0x12,  0x24,  0x92,  0x24,  0x84,  0x40,  0x18, 	/* 3C390 */
+	0x99,  0x08,  0x20,  0x08,  0x20,  0x08,  0x7C,  0x0A,  0x44,  0x2A,  0xA8,  0x2D,  0x10,  0x28,  0x28,  0x48, 	/* 3C3A0 */
+	0x44,  0x08,  0x83,  0x0D,  0xFC,  0x16,  0x84,  0x12,  0x84,  0x12,  0x84,  0x20,  0x84,  0x20,  0xFC,  0x40, 	/* 3C3B0 */
+	0x00,  0x9D,  0x00,  0x00,  0x1F,  0xF0,  0x00,  0x20,  0x00,  0xC4,  0x3E,  0x84,  0x02,  0xC8,  0x04,  0xA0, 	/* 3C3C0 */
+	0x18,  0x98,  0x60,  0x87,  0x01,  0x80,  0x00,  0x00,  0x7F,  0xFF,  0x10,  0x00,  0x12,  0x22,  0x21,  0x11, 	/* 3C3D0 */
+	0x41,  0x11,  0x9F,  0x08,  0x00,  0x09,  0xFE,  0x09,  0x02,  0x0B,  0x22,  0x0B,  0x22,  0x2D,  0xFE,  0x2D, 	/* 3C3E0 */
+	0x22,  0x29,  0x22,  0x49,  0x32,  0x09,  0x52,  0x0D,  0x4A,  0x0B,  0x86,  0x13,  0x02,  0x11,  0x02,  0x21, 	/* 3C3F0 */
+	0xFE,  0x40,  0x00,  0xB1,  0x08,  0x00,  0x09,  0xFE,  0x09,  0x2A,  0x0B,  0x2A,  0x2B,  0x2A,  0x2D,  0x4E, 	/* 3C400 */
+	0x2D,  0x42,  0x29,  0x82,  0x49,  0x7A,  0x09,  0x4A,  0x0D,  0x4A,  0x0D,  0x4A,  0x13,  0x7A,  0x13,  0x02, 	/* 3C410 */
+	0x21,  0x02,  0x41,  0x06,  0xB9,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x07,  0xF0,  0x04, 	/* 3C420 */
+	0x10,  0x07,  0xF0,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x30,  0x00,  0xC0,  0x00,  0x80,  0x11,  0x88,  0x12, 	/* 3C430 */
+	0x24,  0x21,  0x12,  0x41,  0x12,  0xBD,  0x08,  0x20,  0x08,  0x3C,  0x08,  0x44,  0x0A,  0xC8,  0x0B,  0x30, 	/* 3C440 */
+	0x2A,  0x28,  0x2C,  0xC4,  0x2B,  0x13,  0x28,  0x10,  0x48,  0xFE,  0x0C,  0x10,  0x0A,  0xFE,  0x12,  0x10, 	/* 3C450 */
+	0x11,  0xFF,  0x20,  0x10,  0x40,  0x10,  0x89,  0x00,  0x00,  0x3F,  0xFE,  0x00,  0x80,  0x08,  0x80,  0x08, 	/* 3C460 */
+	0xFC,  0x08,  0x80,  0x08,  0x80,  0x7F,  0xFF,  0x04,  0x00,  0x07,  0xFC,  0x04,  0x00,  0x07,  0xFE,  0x29, 	/* 3C470 */
+	0x22,  0x24,  0x92,  0x24,  0x82,  0x40,  0x0C,  0x94,  0x08,  0x20,  0x08,  0x20,  0x08,  0x3C,  0x0A,  0x44, 	/* 3C480 */
+	0x2A,  0x48,  0x2A,  0x88,  0x2C,  0x10,  0x29,  0x3E,  0x49,  0x22,  0x0D,  0x22,  0x15,  0x22,  0x13,  0x3E, 	/* 3C490 */
+	0x13,  0x22,  0x21,  0x22,  0x21,  0x3E,  0x41,  0x22,  0x99,  0x08,  0x20,  0x08,  0x20,  0x09,  0xFE,  0x0A, 	/* 3C4A0 */
+	0x84,  0x2A,  0x44,  0x2C,  0x48,  0x28,  0x48,  0x4B,  0xFF,  0x08,  0x00,  0x08,  0x00,  0x14,  0xFC,  0x12, 	/* 3C4B0 */
+	0x84,  0x12,  0x84,  0x20,  0x84,  0x20,  0xFC,  0x40,  0x00,  0x9A,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF, 	/* 3C4C0 */
+	0x04,  0x10,  0x0E,  0x38,  0x15,  0x54,  0x24,  0x92,  0x44,  0x11,  0x00,  0x80,  0x08,  0x88,  0x08,  0x88, 	/* 3C4D0 */
+	0x10,  0x90,  0x21,  0x40,  0x02,  0x20,  0x0C,  0x18,  0x70,  0x07,  0x9C,  0x08,  0x00,  0x08,  0xFE,  0x08, 	/* 3C4E0 */
+	0x82,  0x0A,  0x82,  0x2A,  0xFE,  0x2A,  0x82,  0x2C,  0x82,  0x28,  0xFE,  0x48,  0x00,  0x08,  0x88,  0x0C, 	/* 3C4F0 */
+	0x8A,  0x0A,  0xEC,  0x12,  0x88,  0x10,  0x89,  0x20,  0xE9,  0x41,  0x87,  0xA1,  0x08,  0x00,  0x08,  0x00, 	/* 3C500 */
+	0x0F,  0xFE,  0x19,  0x48,  0x19,  0x48,  0x29,  0x48,  0x7F,  0xFE,  0x09,  0x48,  0x09,  0x48,  0x09,  0x48, 	/* 3C510 */
+	0x7F,  0xFF,  0x00,  0x00,  0x12,  0x48,  0x12,  0x24,  0x21,  0x12,  0x41,  0x12,  0xA6,  0x04,  0x40,  0x04, 	/* 3C520 */
+	0x80,  0x0F,  0xFC,  0x08,  0x80,  0x18,  0x80,  0x2F,  0xF8,  0x48,  0x80,  0x0F,  0xF8,  0x08,  0x80,  0x08, 	/* 3C530 */
+	0x80,  0x0F,  0xFC,  0x00,  0x00,  0x10,  0x08,  0x12,  0x44,  0x21,  0x22,  0x41,  0x22,  0xB6,  0x04,  0x10, 	/* 3C540 */
+	0x04,  0x14,  0x0F,  0x92,  0x08,  0x92,  0x11,  0xFF,  0x25,  0x10,  0x52,  0x28,  0x0A,  0x28,  0x04,  0x44, 	/* 3C550 */
+	0x18,  0x82,  0x63,  0x01,  0x00,  0x00,  0x12,  0x48,  0x11,  0x24,  0x21,  0x22,  0x40,  0x02,  0xBC,  0x08, 	/* 3C560 */
+	0x10,  0x08,  0x10,  0x08,  0xFE,  0x0A,  0x10,  0x2A,  0x54,  0x2A,  0x44,  0x2D,  0xFF,  0x28,  0x44,  0x48, 	/* 3C570 */
+	0x44,  0x08,  0x00,  0x0D,  0xFF,  0x0A,  0x28,  0x12,  0x28,  0x10,  0x49,  0x20,  0x89,  0x41,  0x07,  0x89, 	/* 3C580 */
+	0x08,  0x10,  0x08,  0x10,  0x09,  0xFF,  0x0A,  0x10,  0x2A,  0xFE,  0x2C,  0x92,  0x28,  0xFE,  0x28,  0x92, 	/* 3C590 */
+	0x48,  0x92,  0x08,  0xFE,  0x0C,  0x38,  0x0A,  0x54,  0x11,  0x52,  0x10,  0x91,  0x21,  0x10,  0x40,  0x10, 	/* 3C5A0 */
+	0x8C,  0x08,  0x20,  0x08,  0x40,  0x08,  0xFC,  0x0A,  0x84,  0x0A,  0xFC,  0x2A,  0x84,  0x2C,  0x84,  0x28, 	/* 3C5B0 */
+	0xFC,  0x28,  0x00,  0x49,  0xFE,  0x0C,  0x20,  0x0A,  0xFC,  0x12,  0x20,  0x10,  0x20,  0x23,  0xFF,  0x40, 	/* 3C5C0 */
+	0x00,  0x8E,  0x04,  0x08,  0x02,  0x10,  0x7F,  0xFF,  0x00,  0x00,  0x1F,  0x22,  0x11,  0x22,  0x1F,  0x22, 	/* 3C5D0 */
+	0x11,  0x22,  0x1F,  0x22,  0x11,  0x02,  0x11,  0x02,  0x13,  0x06,  0x00,  0x00,  0x12,  0x24,  0x21,  0x12, 	/* 3C5E0 */
+	0x41,  0x11,  0x95,  0x00,  0x00,  0x3F,  0xBE,  0x22,  0x22,  0x2A,  0x22,  0x2B,  0xA2,  0x28,  0xA2,  0x28, 	/* 3C5F0 */
+	0xBE,  0x2B,  0xA0,  0x2A,  0x21,  0x22,  0x21,  0x3F,  0x9F,  0x00,  0x00,  0x10,  0x00,  0x12,  0x44,  0x21, 	/* 3C600 */
+	0x22,  0x41,  0x21,  0x96,  0x08,  0x04,  0x08,  0x18,  0x09,  0xE4,  0x08,  0x52,  0x0A,  0x49,  0x2A,  0x89, 	/* 3C610 */
+	0x2D,  0xFC,  0x2C,  0x40,  0x29,  0xFF,  0x48,  0x40,  0x0C,  0x7C,  0x0A,  0xA4,  0x12,  0x98,  0x11,  0x10, 	/* 3C620 */
+	0x22,  0x6C,  0x41,  0x83,  0x99,  0x08,  0x00,  0x0B,  0xFE,  0x08,  0x50,  0x0A,  0x50,  0x2B,  0xFC,  0x2B, 	/* 3C630 */
+	0x54,  0x2D,  0x54,  0x29,  0x54,  0x49,  0xFC,  0x08,  0x20,  0x0C,  0x20,  0x14,  0xFC,  0x12,  0x20,  0x12, 	/* 3C640 */
+	0x20,  0x23,  0xFF,  0x40,  0x00,  0xA2,  0x08,  0x10,  0x2A,  0x54,  0x2A,  0x54,  0x4C,  0x98,  0x12,  0x24, 	/* 3C650 */
+	0x20,  0x40,  0x7F,  0xFE,  0x40,  0x02,  0x40,  0x02,  0x3F,  0xF8,  0x02,  0x08,  0x02,  0x08,  0x3F,  0xE8, 	/* 3C660 */
+	0x02,  0x09,  0x02,  0x05,  0x02,  0x03,  0xA4,  0x08,  0x44,  0x08,  0x44,  0x09,  0xFF,  0x0A,  0x44,  0x2A, 	/* 3C670 */
+	0x7C,  0x2A,  0x44,  0x2C,  0x44,  0x28,  0x7C,  0x48,  0x10,  0x09,  0xFF,  0x0C,  0x38,  0x0A,  0x34,  0x11, 	/* 3C680 */
+	0x54,  0x10,  0x92,  0x21,  0x11,  0x40,  0x10,  0xA5,  0x08,  0x20,  0x08,  0x38,  0x08,  0x48,  0x0A,  0x90, 	/* 3C690 */
+	0x0B,  0xFE,  0x2A,  0xAA,  0x2C,  0xAA,  0x28,  0xAA,  0x28,  0xCE,  0x48,  0x92,  0x0C,  0x10,  0x0B,  0xFF, 	/* 3C6A0 */
+	0x12,  0x28,  0x10,  0x44,  0x20,  0x82,  0x43,  0x01,  0xA6,  0x00,  0x80,  0x3C,  0x80,  0x24,  0xFE,  0x25, 	/* 3C6B0 */
+	0x02,  0x25,  0x02,  0x3E,  0xF2,  0x24,  0x92,  0x24,  0x92,  0x24,  0xF2,  0x24,  0x02,  0x3C,  0x02,  0x00, 	/* 3C6C0 */
+	0x0C,  0x10,  0x00,  0x12,  0x24,  0x21,  0x12,  0x41,  0x11,  0xA7,  0x00,  0x00,  0x3F,  0xFE,  0x22,  0x22, 	/* 3C6D0 */
+	0x22,  0x22,  0x22,  0x42,  0x3E,  0x8C,  0x23,  0x00,  0x22,  0xFE,  0x22,  0x82,  0x22,  0x82,  0x3E,  0x82, 	/* 3C6E0 */
+	0x00,  0xFE,  0x10,  0x00,  0x12,  0x24,  0x21,  0x12,  0x41,  0x11,  0xA9,  0x08,  0x00,  0x09,  0xFF,  0x08, 	/* 3C6F0 */
+	0x10,  0x0A,  0x20,  0x2A,  0xFE,  0x2A,  0x82,  0x2C,  0x82,  0x48,  0xFE,  0x08,  0x82,  0x0C,  0xFE,  0x14, 	/* 3C700 */
+	0x82,  0x12,  0x82,  0x12,  0xFE,  0x20,  0x24,  0x20,  0xC2,  0x43,  0x01,  0xAC,  0x08,  0x00,  0x08,  0xF8, 	/* 3C710 */
+	0x08,  0x88,  0x0A,  0xF8,  0x2A,  0x88,  0x2C,  0x88,  0x2C,  0xF8,  0x28,  0x00,  0x4B,  0xFF,  0x08,  0x40, 	/* 3C720 */
+	0x0C,  0xFE,  0x0B,  0x2A,  0x12,  0x4A,  0x10,  0x92,  0x21,  0x22,  0x40,  0x0C,  0xAE,  0x00,  0x82,  0x00, 	/* 3C730 */
+	0x82,  0x1F,  0xFC,  0x00,  0x88,  0x00,  0xB0,  0x7F,  0xFF,  0x01,  0x00,  0x07,  0xF8,  0x1C,  0x08,  0x67, 	/* 3C740 */
+	0xF8,  0x04,  0x08,  0x07,  0xF8,  0x10,  0x08,  0x12,  0x44,  0x21,  0x22,  0x41,  0x22,  0xBD,  0x08,  0x00, 	/* 3C750 */
+	0x0B,  0xFF,  0x08,  0x00,  0x0A,  0xFE,  0x2A,  0x82,  0x2A,  0x82,  0x2C,  0xFE,  0x48,  0x80,  0x08,  0xFF, 	/* 3C760 */
+	0x0C,  0x91,  0x0A,  0x99,  0x13,  0x55,  0x11,  0x33,  0x12,  0x55,  0x24,  0x99,  0x40,  0x33,  0x84,  0x08, 	/* 3C770 */
+	0x20,  0x08,  0x40,  0x08,  0xFE,  0x0A,  0x82,  0x2A,  0xFE,  0x2A,  0x82,  0x2C,  0xFE,  0x28,  0x82,  0x48, 	/* 3C780 */
+	0x82,  0x08,  0xFE,  0x0C,  0x10,  0x0A,  0xA8,  0x12,  0xAA,  0x11,  0x21,  0x22,  0x25,  0x40,  0x1C,  0x88, 	/* 3C790 */
+	0x00,  0x00,  0x27,  0xDE,  0x25,  0x12,  0x25,  0x12,  0x27,  0xD2,  0x24,  0x52,  0x24,  0x5E,  0x27,  0xD0, 	/* 3C7A0 */
+	0x25,  0x11,  0x25,  0x11,  0x27,  0xCF,  0x40,  0x00,  0x10,  0x04,  0x12,  0x22,  0x21,  0x11,  0x41,  0x11, 	/* 3C7B0 */
+	0x8A,  0x08,  0x40,  0x12,  0x44,  0x7F,  0x78,  0x00,  0xC2,  0x3E,  0x42,  0x22,  0x3E,  0x3E,  0x00,  0x22, 	/* 3C7C0 */
+	0x44,  0x3E,  0x78,  0x22,  0x42,  0x22,  0x42,  0x26,  0x3E,  0x10,  0x08,  0x14,  0x44,  0x22,  0x22,  0x42, 	/* 3C7D0 */
+	0x22,  0x8F,  0x00,  0x18,  0x0F,  0xE0,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x0F,  0xF8,  0x0C,  0x98, 	/* 3C7E0 */
+	0x0A,  0xA8,  0x0A,  0xC8,  0x0F,  0xF8,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x12,  0x24, 	/* 3C7F0 */
+	0x21,  0x12,  0x94,  0x08,  0x10,  0x08,  0x10,  0x09,  0xFF,  0x09,  0x01,  0x0B,  0x49,  0x2A,  0x44,  0x2C, 	/* 3C800 */
+	0x92,  0x29,  0x12,  0x48,  0x28,  0x08,  0x44,  0x0C,  0x82,  0x0B,  0xFD,  0x12,  0x84,  0x10,  0x84,  0x20, 	/* 3C810 */
+	0xFC,  0x40,  0x84,  0x95,  0x08,  0x00,  0x08,  0xFE,  0x08,  0x10,  0x0A,  0x10,  0x2B,  0xFF,  0x2A,  0x00, 	/* 3C820 */
+	0x2C,  0x7E,  0x28,  0x42,  0x48,  0x7E,  0x08,  0x42,  0x0C,  0x7E,  0x0A,  0x42,  0x12,  0x7E,  0x10,  0x24, 	/* 3C830 */
+	0x20,  0xC2,  0x43,  0x01,  0x99,  0x00,  0x00,  0x3F,  0xBE,  0x24,  0x22,  0x24,  0x22,  0x2F,  0x22,  0x29, 	/* 3C840 */
+	0x22,  0x29,  0x3E,  0x2F,  0x20,  0x24,  0x20,  0x24,  0x21,  0x3F,  0xA1,  0x00,  0x1F,  0x14,  0x44,  0x12, 	/* 3C850 */
+	0x22,  0x21,  0x11,  0x41,  0x11,  0x9F,  0x04,  0x10,  0x7F,  0x90,  0x1E,  0x10,  0x12,  0xFC,  0x1E,  0x14, 	/* 3C860 */
+	0x00,  0x94,  0x3E,  0x54,  0x05,  0x24,  0x0E,  0x25,  0x74,  0x55,  0x04,  0x93,  0x0D,  0x01,  0x10,  0x04, 	/* 3C870 */
+	0x14,  0x42,  0x22,  0x21,  0x42,  0x21,  0xA8,  0x00,  0x04,  0x1F,  0x84,  0x10,  0x84,  0x1F,  0xFF,  0x10, 	/* 3C880 */
+	0x04,  0x1F,  0xA4,  0x10,  0x14,  0x2F,  0x94,  0x2B,  0x04,  0x52,  0x8C,  0x06,  0x00,  0x00,  0x88,  0x04, 	/* 3C890 */
+	0x90,  0x19,  0x40,  0x06,  0x30,  0x78,  0x0F,  0xAC,  0x04,  0x10,  0x04,  0x10,  0x3F,  0x1F,  0x04,  0x24, 	/* 3C8A0 */
+	0x3F,  0x24,  0x04,  0x54,  0x7F,  0x94,  0x08,  0x08,  0x0F,  0x08,  0x11,  0x14,  0x21,  0x22,  0x46,  0xC1, 	/* 3C8B0 */
+	0x10,  0x00,  0x14,  0x44,  0x22,  0x22,  0x42,  0x21,  0xB1,  0x04,  0x10,  0x04,  0x10,  0x3F,  0x90,  0x04, 	/* 3C8C0 */
+	0x7C,  0x7F,  0x94,  0x12,  0x14,  0x25,  0x74,  0x5F,  0x94,  0x04,  0x2C,  0x07,  0xC5,  0x78,  0x83,  0x00, 	/* 3C8D0 */
+	0x00,  0x14,  0x88,  0x12,  0x44,  0x21,  0x22,  0x41,  0x22,  0xB9,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80, 	/* 3C8E0 */
+	0x0F,  0xF8,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x02,  0x20,  0x7F,  0xFF,  0x00,  0x00, 	/* 3C8F0 */
+	0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xFC,  0x12,  0x22,  0x61,  0x11,  0xBE,  0x08,  0x88,  0x08,  0x8C,  0x0B, 	/* 3C900 */
+	0xEA,  0x0A,  0x2A,  0x2D,  0x28,  0x2D,  0x48,  0x2F,  0xFF,  0x28,  0x0A,  0x49,  0xEA,  0x09,  0x2A,  0x0D, 	/* 3C910 */
+	0x2C,  0x0B,  0xE5,  0x11,  0x2D,  0x11,  0x2B,  0x21,  0xF3,  0x40,  0x21,  0x83,  0x09,  0x08,  0x09,  0x0A, 	/* 3C920 */
+	0x09,  0xC9,  0x09,  0x7F,  0x29,  0x48,  0x2A,  0xC8,  0x2E,  0x8C,  0x29,  0x94,  0x49,  0x12,  0x0A,  0x22, 	/* 3C930 */
+	0x0C,  0x41,  0x0A,  0x00,  0x13,  0x52,  0x11,  0x52,  0x22,  0x49,  0x44,  0x49,  0x88,  0x09,  0xD4,  0x08, 	/* 3C940 */
+	0x54,  0x0A,  0x49,  0x09,  0x8A,  0x2C,  0x84,  0x2D,  0xFA,  0x2A,  0x01,  0x4D,  0xFC,  0x09,  0x04,  0x09, 	/* 3C950 */
+	0x04,  0x0D,  0xFC,  0x14,  0x88,  0x12,  0x48,  0x10,  0x50,  0x23,  0xFF,  0x40,  0x00,  0x89,  0x10,  0x88, 	/* 3C960 */
+	0x10,  0x88,  0x17,  0xE8,  0x10,  0x1F,  0x35,  0xD2,  0x35,  0x6A,  0x39,  0x4A,  0x51,  0xCA,  0x50,  0x0A, 	/* 3C970 */
+	0x13,  0xE4,  0x18,  0x44,  0x14,  0xEC,  0x17,  0x8C,  0x24,  0x92,  0x20,  0xA2,  0x41,  0xC1,  0x8E,  0x08, 	/* 3C980 */
+	0x10,  0x08,  0x10,  0x09,  0xFF,  0x0A,  0x28,  0x2A,  0xAA,  0x2C,  0x44,  0x2C,  0xFE,  0x29,  0x45,  0x4A, 	/* 3C990 */
+	0x7C,  0x08,  0x44,  0x0C,  0x7C,  0x0A,  0x90,  0x12,  0x94,  0x11,  0x12,  0x22,  0x11,  0x40,  0x30,  0x90, 	/* 3C9A0 */
+	0x08,  0x92,  0x08,  0x52,  0x08,  0x54,  0x0B,  0xFF,  0x2A,  0x38,  0x2A,  0x54,  0x2D,  0x93,  0x28,  0x90, 	/* 3C9B0 */
+	0x48,  0x84,  0x08,  0xDF,  0x0D,  0x54,  0x0B,  0x54,  0x12,  0xBF,  0x10,  0x84,  0x21,  0x04,  0x42,  0x04, 	/* 3C9C0 */
+	0x92,  0x08,  0x10,  0x08,  0xFC,  0x08,  0x10,  0x0B,  0xFF,  0x2A,  0x44,  0x2C,  0x44,  0x2D,  0xEF,  0x28, 	/* 3C9D0 */
+	0x44,  0x48,  0x64,  0x09,  0x9F,  0x0C,  0x00,  0x0B,  0xFF,  0x12,  0x48,  0x10,  0x49,  0x20,  0x89,  0x43, 	/* 3C9E0 */
+	0x07,  0x94,  0x08,  0x04,  0x08,  0x18,  0x09,  0xE4,  0x0A,  0xA4,  0x2A,  0x68,  0x2B,  0xFF,  0x2C,  0x68, 	/* 3C9F0 */
+	0x28,  0xA4,  0x49,  0xFE,  0x0A,  0xA5,  0x0C,  0xA4,  0x0A,  0xFC,  0x12,  0xA4,  0x10,  0xA4,  0x20,  0xFC, 	/* 3CA00 */
+	0x40,  0x00,  0x95,  0x02,  0x20,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x20,  0x0B,  0xE8,  0x08,  0x0A,  0x7B, 	/* 3CA10 */
+	0xEA,  0x0A,  0x2C,  0x0A,  0x28,  0x1A,  0x29,  0x6B,  0xE9,  0x08,  0x07,  0x00,  0x00,  0x12,  0x24,  0x21, 	/* 3CA20 */
+	0x12,  0x41,  0x11,  0x97,  0x10,  0x00,  0x13,  0xDE,  0x12,  0x52,  0x13,  0xDE,  0x16,  0x52,  0x36,  0x52, 	/* 3CA30 */
+	0x3B,  0xDE,  0x32,  0x02,  0x52,  0x7A,  0x52,  0x4A,  0x12,  0x7A,  0x1A,  0x4A,  0x16,  0x7A,  0x22,  0x4A, 	/* 3CA40 */
+	0x22,  0x9A,  0x42,  0x06,  0x9F,  0x08,  0x10,  0x2A,  0x54,  0x2A,  0x54,  0x54,  0xA8,  0x22,  0x44,  0x7F, 	/* 3CA50 */
+	0xFE,  0x40,  0x02,  0x4F,  0xF2,  0x08,  0x10,  0x0F,  0xF0,  0x01,  0x00,  0x1F,  0xF8,  0x10,  0x08,  0x10, 	/* 3CA60 */
+	0x08,  0x1F,  0xF8,  0x00,  0x00,  0xA0,  0x08,  0x10,  0x08,  0x20,  0x08,  0xFE,  0x0A,  0x8A,  0x2A,  0xF6, 	/* 3CA70 */
+	0x2C,  0xDA,  0x2C,  0xFE,  0x28,  0x92,  0x48,  0xBA,  0x08,  0xD6,  0x0C,  0x10,  0x0B,  0xFF,  0x12,  0x10, 	/* 3CA80 */
+	0x10,  0x28,  0x20,  0xC4,  0x43,  0x03,  0xA5,  0x08,  0x00,  0x08,  0x78,  0x08,  0x48,  0x0A,  0x48,  0x2A, 	/* 3CA90 */
+	0x78,  0x2B,  0xDE,  0x2D,  0x52,  0x29,  0x52,  0x49,  0xDE,  0x0C,  0x20,  0x15,  0xFE,  0x12,  0x70,  0x12, 	/* 3CAA0 */
+	0xA8,  0x21,  0x24,  0x22,  0x22,  0x40,  0x20,  0xA6,  0x11,  0x00,  0x11,  0xDE,  0x11,  0x02,  0x15,  0xD4, 	/* 3CAB0 */
+	0x16,  0x48,  0x35,  0x54,  0x38,  0xA2,  0x51,  0x25,  0x56,  0xA4,  0x10,  0xA8,  0x1B,  0xFF,  0x14,  0x70, 	/* 3CAC0 */
+	0x14,  0xA8,  0x21,  0x24,  0x22,  0x23,  0x40,  0x20,  0xA7,  0x12,  0x3C,  0x11,  0x24,  0x11,  0x24,  0x14, 	/* 3CAD0 */
+	0x42,  0x16,  0xFD,  0x35,  0x22,  0x39,  0xD2,  0x38,  0x2C,  0x57,  0x4C,  0x51,  0x1A,  0x11,  0x2A,  0x19, 	/* 3CAE0 */
+	0x49,  0x15,  0x88,  0x22,  0xB0,  0x22,  0x60,  0x44,  0x1F,  0xAC,  0x10,  0x80,  0x11,  0x1C,  0x13,  0xD4, 	/* 3CAF0 */
+	0x16,  0x55,  0x37,  0xD5,  0x3A,  0x63,  0x3A,  0x40,  0x53,  0xFE,  0x50,  0x92,  0x10,  0x92,  0x13,  0xD4, 	/* 3CB00 */
+	0x18,  0x8C,  0x14,  0xC8,  0x21,  0x94,  0x26,  0x22,  0x40,  0x41,  0xAD,  0x08,  0x00,  0x09,  0xFE,  0x09, 	/* 3CB10 */
+	0x52,  0x09,  0x52,  0x2B,  0xFE,  0x2A,  0x80,  0x2C,  0xFE,  0x29,  0x22,  0x49,  0xFA,  0x0A,  0xAA,  0x08, 	/* 3CB20 */
+	0xFA,  0x14,  0x32,  0x12,  0x2A,  0x20,  0x3A,  0x21,  0xC6,  0x40,  0x0C,  0xAE,  0x10,  0x04,  0x13,  0xC4, 	/* 3CB30 */
+	0x34,  0x0D,  0x37,  0xED,  0x38,  0x0E,  0x53,  0xD4,  0x18,  0x06,  0x17,  0xCA,  0x22,  0x4A,  0x23,  0xD1, 	/* 3CB40 */
+	0x40,  0x20,  0x3F,  0xF8,  0x06,  0x30,  0x01,  0xC0,  0x07,  0x30,  0x78,  0x0F,  0xB5,  0x12,  0x10,  0x11, 	/* 3CB50 */
+	0x10,  0x11,  0x7E,  0x14,  0x10,  0x16,  0xFF,  0x35,  0x44,  0x39,  0x28,  0x30,  0x7E,  0x57,  0x10,  0x51, 	/* 3CB60 */
+	0x7E,  0x11,  0x10,  0x19,  0xFF,  0x15,  0x10,  0x22,  0x90,  0x24,  0x60,  0x48,  0x1F,  0xB9,  0x00,  0x00, 	/* 3CB70 */
+	0x7F,  0x7F,  0x08,  0x08,  0x11,  0x11,  0x6A,  0x6A,  0x16,  0x16,  0x6D,  0x6D,  0x15,  0x15,  0x64,  0x64, 	/* 3CB80 */
+	0x18,  0x98,  0x00,  0x80,  0x08,  0x88,  0x09,  0x50,  0x12,  0x20,  0x0C,  0x18,  0x70,  0x07,  0xBB,  0x08, 	/* 3CB90 */
+	0x04,  0x08,  0xF8,  0x08,  0x20,  0x0B,  0xFF,  0x0A,  0x20,  0x2A,  0xFC,  0x2C,  0xAC,  0x28,  0xEC,  0x28, 	/* 3CBA0 */
+	0xB4,  0x48,  0xFC,  0x0C,  0x20,  0x0A,  0xFE,  0x12,  0x20,  0x13,  0xFF,  0x21,  0x52,  0x42,  0x29,  0xBC, 	/* 3CBB0 */
+	0x08,  0x10,  0x08,  0xFE,  0x08,  0x12,  0x0B,  0xFF,  0x2A,  0x12,  0x2C,  0xFE,  0x2C,  0x10,  0x29,  0xFF, 	/* 3CBC0 */
+	0x48,  0xAA,  0x09,  0x15,  0x0C,  0x00,  0x0A,  0xFE,  0x12,  0xAA,  0x10,  0xAA,  0x23,  0xFF,  0x40,  0x00, 	/* 3CBD0 */
+	0xBF,  0x08,  0x00,  0x09,  0xFE,  0x08,  0x22,  0x08,  0xEE,  0x0A,  0x22,  0x2B,  0xFE,  0x2C,  0x44,  0x28, 	/* 3CBE0 */
+	0x88,  0x29,  0xFE,  0x4A,  0x90,  0x0C,  0xFC,  0x0A,  0x90,  0x12,  0xFC,  0x10,  0x90,  0x20,  0xFF,  0x40, 	/* 3CBF0 */
+	0x00,  0x86,  0x08,  0xFC,  0x08,  0x84,  0x08,  0xFC,  0x0A,  0x84,  0x2A,  0xFC,  0x2A,  0x48,  0x2D,  0xFE, 	/* 3CC00 */
+	0x28,  0x48,  0x4B,  0xFF,  0x08,  0x48,  0x14,  0xA4,  0x13,  0xAB,  0x12,  0x70,  0x20,  0xA8,  0x23,  0x26, 	/* 3CC10 */
+	0x40,  0x60,  0x8D,  0x08,  0x92,  0x08,  0xA2,  0x08,  0xBA,  0x09,  0x2C,  0x0B,  0x6D,  0x2A,  0xBA,  0x2C, 	/* 3CC20 */
+	0xAA,  0x29,  0x7D,  0x49,  0xD7,  0x08,  0x10,  0x09,  0xFF,  0x0C,  0x38,  0x12,  0x54,  0x10,  0x93,  0x21, 	/* 3CC30 */
+	0x10,  0x40,  0x10,  0x90,  0x08,  0x10,  0x08,  0x1E,  0x08,  0x10,  0x09,  0xFF,  0x0B,  0x3A,  0x2B,  0xE2, 	/* 3CC40 */
+	0x2D,  0x7E,  0x29,  0x54,  0x29,  0x7C,  0x49,  0x54,  0x0D,  0x7C,  0x0B,  0x00,  0x12,  0xFE,  0x12,  0xAA, 	/* 3CC50 */
+	0x25,  0xFF,  0x40,  0x00,  0x9B,  0x10,  0x00,  0x13,  0xDE,  0x12,  0x52,  0x13,  0xDE,  0x16,  0x52,  0x37, 	/* 3CC60 */
+	0xDE,  0x3A,  0x22,  0x33,  0xFE,  0x52,  0x22,  0x52,  0xFA,  0x1A,  0xEA,  0x16,  0xBA,  0x12,  0xFA,  0x22, 	/* 3CC70 */
+	0x72,  0x22,  0xAA,  0x42,  0x26,  0xA8,  0x0B,  0xEE,  0x32,  0x22,  0x3F,  0xEE,  0x23,  0x62,  0x3B,  0xEE, 	/* 3CC80 */
+	0x22,  0x26,  0x7F,  0xFF,  0x44,  0x11,  0x3F,  0x7E,  0x16,  0x34,  0x25,  0x52,  0x7F,  0xFF,  0x0C,  0x98, 	/* 3CC90 */
+	0x73,  0x67,  0x06,  0x30,  0x38,  0x0E,  0xAA,  0x00,  0x08,  0x00,  0x70,  0x1F,  0x80,  0x10,  0x10,  0x11, 	/* 3CCA0 */
+	0x10,  0x11,  0x10,  0x11,  0x10,  0x11,  0x10,  0x11,  0x10,  0x11,  0x10,  0x11,  0x10,  0x11,  0x08,  0x11, 	/* 3CCB0 */
+	0x08,  0x21,  0x04,  0x21,  0x04,  0x41,  0x02,  0xAC,  0x01,  0x00,  0x02,  0x00,  0x3C,  0x7E,  0x22,  0x52, 	/* 3CCC0 */
+	0x2A,  0x52,  0x2A,  0x52,  0x2A,  0x7E,  0x2A,  0x40,  0x2A,  0x40,  0x2A,  0x40,  0x29,  0x42,  0x29,  0x22, 	/* 3CCD0 */
+	0x28,  0x9E,  0x48,  0x40,  0x48,  0x30,  0x88,  0x0F,  0xAD,  0x00,  0x08,  0x00,  0x70,  0x1F,  0x84,  0x08, 	/* 3CCE0 */
+	0x42,  0x08,  0x42,  0x17,  0xF8,  0x20,  0x88,  0x00,  0x88,  0x7F,  0xFF,  0x00,  0x88,  0x00,  0x88,  0x0F, 	/* 3CCF0 */
+	0xF8,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x01,  0x80,  0xB0,  0x00,  0x08,  0x00,  0x70,  0x1F,  0x84, 	/* 3CD00 */
+	0x08,  0x42,  0x08,  0x42,  0x17,  0xFC,  0x21,  0x00,  0x01,  0x00,  0x7F,  0xFF,  0x01,  0x00,  0x03,  0xF8, 	/* 3CD10 */
+	0x06,  0x10,  0x19,  0xA0,  0x60,  0xE0,  0x03,  0x18,  0x1C,  0x07,  0xB2,  0x00,  0x10,  0x00,  0xE0,  0x3F, 	/* 3CD20 */
+	0x08,  0x10,  0x84,  0x10,  0x82,  0x27,  0xE2,  0x44,  0x20,  0x07,  0xF8,  0x04,  0x08,  0x04,  0x08,  0x0F, 	/* 3CD30 */
+	0xFE,  0x08,  0x12,  0x12,  0x4A,  0x29,  0x2A,  0x49,  0x22,  0x10,  0x0C,  0xB5,  0x00,  0x0C,  0x7F,  0xF0, 	/* 3CD40 */
+	0x11,  0x04,  0x08,  0x88,  0x3F,  0xFE,  0x22,  0x22,  0x3F,  0xFE,  0x00,  0x04,  0x3F,  0x04,  0x21,  0x7F, 	/* 3CD50 */
+	0x3F,  0x04,  0x21,  0x24,  0x3F,  0x14,  0x22,  0x04,  0x3D,  0x04,  0x60,  0x8C,  0xB6,  0x02,  0x20,  0x02, 	/* 3CD60 */
+	0x10,  0x04,  0x08,  0x04,  0x04,  0x08,  0x04,  0x14,  0x12,  0x64,  0x10,  0x02,  0x10,  0x02,  0x20,  0x01, 	/* 3CD70 */
+	0x20,  0x01,  0x40,  0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x0C,  0x18,  0x70,  0x07,  0xBA,  0x02,  0x20, 	/* 3CD80 */
+	0x0C,  0x18,  0x32,  0x26,  0x01,  0xC0,  0x07,  0x60,  0x78,  0x1F,  0x00,  0x00,  0x7F,  0xFE,  0x11,  0x22, 	/* 3CD90 */
+	0x1F,  0x24,  0x11,  0x28,  0x1F,  0x24,  0x11,  0x22,  0x1F,  0x32,  0x71,  0x2C,  0x01,  0x20,  0xBB,  0x00, 	/* 3CDA0 */
+	0x10,  0x1C,  0x20,  0x03,  0x40,  0x00,  0xC0,  0x01,  0x30,  0x06,  0x08,  0x18,  0x04,  0x60,  0x10,  0x04, 	/* 3CDB0 */
+	0x10,  0x04,  0x20,  0x02,  0x20,  0x01,  0x40,  0x00,  0x80,  0x03,  0x60,  0x0C,  0x18,  0x70,  0x07,  0xBC, 	/* 3CDC0 */
+	0x02,  0x00,  0x02,  0x7C,  0x34,  0x44,  0x0C,  0x44,  0x0C,  0x44,  0x12,  0x7C,  0x21,  0x44,  0x40,  0x44, 	/* 3CDD0 */
+	0x02,  0x44,  0x02,  0x7C,  0x34,  0x44,  0x0C,  0x44,  0x0C,  0x44,  0x12,  0x44,  0x23,  0xFF,  0x40,  0x00, 	/* 3CDE0 */
+	0xBD,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0x82,  0x1A,  0x9A,  0x04,  0x84,  0x3A,  0xBA,  0x00, 	/* 3CDF0 */
+	0x80,  0x1A,  0x9A,  0x04,  0x84,  0x0D,  0x4C,  0x33,  0x72,  0x02,  0x20,  0x04,  0x10,  0x18,  0x0C,  0x60, 	/* 3CE00 */
+	0x03,  0xBE,  0x00,  0x00,  0x7F,  0xFF,  0x08,  0x88,  0x10,  0x84,  0x7F,  0xFF,  0x20,  0x82,  0x2A,  0xAA, 	/* 3CE10 */
+	0x24,  0x92,  0x3A,  0xEA,  0x20,  0x82,  0x22,  0x8A,  0x3A,  0xEA,  0x24,  0x92,  0x2A,  0xAA,  0x30,  0xC2, 	/* 3CE20 */
+	0x20,  0x86,  0xBF,  0x00,  0x08,  0x04,  0x08,  0x04,  0x08,  0x04,  0x08,  0x04,  0x08,  0x07,  0xF8,  0x00, 	/* 3CE30 */
+	0x08,  0x00,  0x08,  0x3F,  0xF8,  0x02,  0x08,  0x02,  0x08,  0x02,  0x08,  0x04,  0x08,  0x04,  0x08,  0x08, 	/* 3CE40 */
+	0x08,  0x10,  0x08,  0x80,  0x04,  0x20,  0x24,  0x20,  0x24,  0x20,  0x24,  0x20,  0x27,  0xFF,  0x3C,  0x20, 	/* 3CE50 */
+	0x04,  0x70,  0x04,  0x70,  0x7C,  0xA8,  0x24,  0xA8,  0x25,  0x24,  0x26,  0x22,  0x24,  0x21,  0x44,  0x20, 	/* 3CE60 */
+	0x04,  0x20,  0x04,  0x20,  0x86,  0x04,  0x20,  0x04,  0x20,  0x25,  0xFF,  0x24,  0xA4,  0x24,  0xA4,  0x3D, 	/* 3CE70 */
+	0x6A,  0x07,  0xFF,  0x04,  0x00,  0x7D,  0xFE,  0x25,  0x02,  0x25,  0x7A,  0x25,  0x4A,  0x25,  0x7A,  0x45, 	/* 3CE80 */
+	0x02,  0x05,  0xFE,  0x04,  0x00,  0x87,  0x08,  0x40,  0x08,  0x40,  0x08,  0x40,  0x08,  0x40,  0x0F,  0xFE, 	/* 3CE90 */
+	0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10,  0x10,  0x10,  0x10,  0x10, 	/* 3CEA0 */
+	0x20,  0x10,  0x40,  0x10,  0x00,  0x10,  0x88,  0x12,  0x00,  0x12,  0x7F,  0x12,  0x40,  0x12,  0x40,  0x12, 	/* 3CEB0 */
+	0x40,  0x1F,  0xFE,  0x10,  0x62,  0x10,  0x62,  0x1E,  0x52,  0x12,  0x54,  0x12,  0x54,  0x12,  0x48,  0x12, 	/* 3CEC0 */
+	0x4C,  0x22,  0x94,  0x22,  0xA2,  0x43,  0x41,  0x8B,  0x24,  0x28,  0x24,  0x24,  0x24,  0x1E,  0x25,  0xF0, 	/* 3CED0 */
+	0x24,  0x14,  0x3E,  0x19,  0x20,  0x67,  0x21,  0xA9,  0x3C,  0x24,  0x24,  0x3F,  0x25,  0xD2,  0x24,  0x14, 	/* 3CEE0 */
+	0x24,  0x19,  0x24,  0x65,  0x25,  0x83,  0x44,  0x01,  0x8C,  0x12,  0x10,  0x12,  0x20,  0x12,  0xFE,  0x12, 	/* 3CEF0 */
+	0x92,  0x12,  0x92,  0x1F,  0xFE,  0x10,  0x92,  0x10,  0x92,  0x10,  0xFE,  0x1E,  0x24,  0x12,  0x44,  0x13, 	/* 3CF00 */
+	0xFF,  0x12,  0x04,  0x22,  0x04,  0x22,  0x04,  0x42,  0x04,  0x92,  0x24,  0x94,  0x24,  0x94,  0x25,  0xFF, 	/* 3CF10 */
+	0x24,  0x94,  0x24,  0x94,  0x3E,  0x9C,  0x20,  0x80,  0x20,  0xFE,  0x3C,  0x20,  0x27,  0xFF,  0x24,  0x70, 	/* 3CF20 */
+	0x24,  0x68,  0x24,  0xA4,  0x25,  0x22,  0x26,  0x21,  0x44,  0x20,  0x98,  0x24,  0x10,  0x25,  0xFF,  0x24, 	/* 3CF30 */
+	0x10,  0x24,  0xFE,  0x24,  0x00,  0x3F,  0xFF,  0x21,  0x29,  0x21,  0xFF,  0x3C,  0x82,  0x24,  0xFE,  0x24, 	/* 3CF40 */
+	0x82,  0x24,  0xFE,  0x24,  0x82,  0x24,  0xFE,  0x24,  0x46,  0x45,  0x81,  0x99,  0x00,  0x00,  0x07,  0xFC, 	/* 3CF50 */
+	0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x00,  0x50,  0x00,  0x90, 	/* 3CF60 */
+	0x01,  0x10,  0x02,  0x10,  0x04,  0x10,  0x18,  0x10,  0x60,  0x10,  0x00,  0x30,  0x9B,  0x00,  0x80,  0x04, 	/* 3CF70 */
+	0x80,  0x04,  0x80,  0x04,  0x80,  0x0F,  0xFC,  0x08,  0x80,  0x10,  0x80,  0x20,  0x80,  0x00,  0x80,  0x7F, 	/* 3CF80 */
+	0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x9D,  0x04,  0x40, 	/* 3CF90 */
+	0x14,  0x40,  0x14,  0x40,  0x14,  0x44,  0x1F,  0x44,  0x24,  0x48,  0x24,  0x50,  0x44,  0x60,  0x07,  0x40, 	/* 3CFA0 */
+	0x0C,  0x40,  0x74,  0x40,  0x04,  0x40,  0x04,  0x42,  0x04,  0x42,  0x04,  0x22,  0x04,  0x1E,  0x9F,  0x01, 	/* 3CFB0 */
+	0x00,  0x01,  0x20,  0x02,  0x18,  0x3F,  0xF4,  0x00,  0x82,  0x08,  0x80,  0x08,  0x80,  0x0F,  0xF8,  0x10, 	/* 3CFC0 */
+	0x80,  0x20,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0xA1, 	/* 3CFD0 */
+	0x04,  0x10,  0x14,  0x10,  0x14,  0x10,  0x14,  0x10,  0x1F,  0x10,  0x14,  0xFE,  0x24,  0x10,  0x44,  0x10, 	/* 3CFE0 */
+	0x04,  0x10,  0x07,  0x10,  0x3C,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x05,  0xFF,  0x04,  0x00, 	/* 3CFF0 */
+	0xA2,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x49,  0x02,  0x09,  0x00,  0x09,  0x00,  0x1F, 	/* 3D000 */
+	0xFC,  0x11,  0x00,  0x21,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01, 	/* 3D010 */
+	0x00,  0xA7,  0x04,  0x40,  0x14,  0x40,  0x14,  0x40,  0x14,  0x7F,  0x1F,  0x44,  0x24,  0x44,  0x44,  0x84, 	/* 3D020 */
+	0x04,  0x84,  0x07,  0x28,  0x1C,  0x28,  0x64,  0x10,  0x04,  0x10,  0x04,  0x28,  0x04,  0x44,  0x04,  0x82, 	/* 3D030 */
+	0x05,  0x01,  0xA9,  0x04,  0x40,  0x14,  0x40,  0x14,  0x40,  0x14,  0x7E,  0x1F,  0xAA,  0x24,  0xAA,  0x24, 	/* 3D040 */
+	0xAA,  0x45,  0x2A,  0x05,  0x4A,  0x06,  0x52,  0x3C,  0x92,  0x05,  0x22,  0x04,  0x22,  0x04,  0x42,  0x04, 	/* 3D050 */
+	0x04,  0x04,  0x18,  0xB2,  0x04,  0x10,  0x14,  0x90,  0x14,  0x90,  0x14,  0x90,  0x1E,  0xFE,  0x24,  0x90, 	/* 3D060 */
+	0x25,  0x10,  0x45,  0x10,  0x06,  0x10,  0x0D,  0xFE,  0x34,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10, 	/* 3D070 */
+	0x07,  0xFF,  0x04,  0x00,  0xB4,  0x08,  0x02,  0x28,  0x0C,  0x28,  0xF8,  0x28,  0x88,  0x3E,  0x88,  0x28, 	/* 3D080 */
+	0x88,  0x48,  0xFF,  0x08,  0x88,  0x0E,  0x88,  0x18,  0x88,  0x68,  0x84,  0x08,  0xE5,  0x0B,  0x05,  0x08, 	/* 3D090 */
+	0x03,  0x0B,  0xFB,  0x08,  0x01,  0xB9,  0x04,  0x10,  0x24,  0x10,  0x25,  0xFE,  0x24,  0x10,  0x3F,  0x10, 	/* 3D0A0 */
+	0x24,  0x10,  0x27,  0xFF,  0x44,  0x04,  0x06,  0x04,  0x1D,  0xFF,  0x64,  0x44,  0x04,  0x24,  0x04,  0x24, 	/* 3D0B0 */
+	0x04,  0x04,  0x04,  0x04,  0x04,  0x0C,  0xBD,  0x01,  0x00,  0x01,  0x00,  0x3F,  0xFC,  0x06,  0x60,  0x03, 	/* 3D0C0 */
+	0x80,  0x7F,  0xFE,  0x42,  0x42,  0x44,  0x32,  0x1F,  0xE8,  0x09,  0x00,  0x0F,  0xF0,  0x11,  0x00,  0x21, 	/* 3D0D0 */
+	0x00,  0x7F,  0xFE,  0x01,  0x00,  0x01,  0x00,  0xBE,  0x08,  0x00,  0x0B,  0xFF,  0x28,  0x20,  0x28,  0x20, 	/* 3D0E0 */
+	0x3E,  0xFC,  0x28,  0x44,  0x48,  0x44,  0x08,  0x44,  0x0B,  0xFF,  0x0C,  0x00,  0x18,  0xFC,  0x68,  0x84, 	/* 3D0F0 */
+	0x08,  0x84,  0x08,  0x84,  0x08,  0xFC,  0x08,  0x00,  0x80,  0x00,  0x00,  0x1F,  0xFE,  0x10,  0x02,  0x10, 	/* 3D100 */
+	0x02,  0x1F,  0xFE,  0x10,  0x40,  0x17,  0x5C,  0x10,  0x40,  0x17,  0x5C,  0x10,  0x00,  0x12,  0x40,  0x13, 	/* 3D110 */
+	0xFC,  0x24,  0x40,  0x2F,  0xFF,  0x40,  0x40,  0x00,  0x40,  0x81,  0x01,  0x04,  0x3E,  0x24,  0x04,  0x24, 	/* 3D120 */
+	0x04,  0x24,  0x7F,  0xA4,  0x0E,  0x24,  0x15,  0x04,  0x24,  0x04,  0x44,  0x8C,  0x04,  0x80,  0x07,  0xF8, 	/* 3D130 */
+	0x08,  0x80,  0x10,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x82,  0x01,  0x20,  0x3E,  0x20,  0x04, 	/* 3D140 */
+	0x3E,  0x7F,  0x4A,  0x04,  0x8A,  0x0E,  0x12,  0x15,  0x22,  0x24,  0x42,  0x04,  0x0C,  0x08,  0x80,  0x0F, 	/* 3D150 */
+	0xFC,  0x08,  0x80,  0x10,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x87,  0x04,  0x80,  0x04,  0x80, 	/* 3D160 */
+	0x0F,  0xF8,  0x10,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x28,  0xA8,  0x28,  0x28,  0x3E,  0x3E, 	/* 3D170 */
+	0x48,  0x48,  0x08,  0x08,  0x0F,  0xFF,  0x78,  0x08,  0x08,  0x08,  0x08,  0x08,  0x92,  0x08,  0x20,  0x28, 	/* 3D180 */
+	0x20,  0x2B,  0xFF,  0x28,  0x00,  0x3E,  0xFC,  0x28,  0x84,  0x48,  0xFC,  0x08,  0x00,  0x0F,  0xFE,  0x19, 	/* 3D190 */
+	0x02,  0x69,  0x7A,  0x09,  0x4A,  0x09,  0x4A,  0x09,  0x7A,  0x09,  0x02,  0x09,  0x06,  0x96,  0x08,  0x10, 	/* 3D1A0 */
+	0x2A,  0x54,  0x2A,  0x54,  0x4C,  0x98,  0x12,  0x24,  0x20,  0x40,  0x7F,  0xFE,  0x40,  0x82,  0x48,  0x82, 	/* 3D1B0 */
+	0x0F,  0xF8,  0x10,  0x80,  0x20,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0xA0,  0x08, 	/* 3D1C0 */
+	0x84,  0x08,  0x48,  0x29,  0xFE,  0x28,  0x20,  0x3E,  0xFC,  0x28,  0x20,  0x2B,  0xFF,  0x48,  0x24,  0x09, 	/* 3D1D0 */
+	0xCA,  0x0C,  0x48,  0x1B,  0xFF,  0x68,  0x4A,  0x08,  0x64,  0x0B,  0xCD,  0x08,  0x73,  0x08,  0xC1,  0xA2, 	/* 3D1E0 */
+	0x08,  0x20,  0x0B,  0xFF,  0x28,  0x20,  0x29,  0xFC,  0x3E,  0x00,  0x2B,  0xFE,  0x4A,  0x52,  0x0B,  0xFE, 	/* 3D1F0 */
+	0x0D,  0x04,  0x19,  0xFC,  0x69,  0x04,  0x09,  0xFC,  0x09,  0x04,  0x09,  0xFC,  0x08,  0xCC,  0x0F,  0x03, 	/* 3D200 */
+	0xA7,  0x08,  0x84,  0x28,  0x48,  0x29,  0xFE,  0x28,  0x20,  0x3E,  0xFC,  0x28,  0x20,  0x4B,  0xFF,  0x08, 	/* 3D210 */
+	0x24,  0x0D,  0xCA,  0x18,  0x88,  0x6B,  0xFF,  0x09,  0x4A,  0x0B,  0x24,  0x0D,  0xC5,  0x08,  0x4B,  0x08, 	/* 3D220 */
+	0xD1,  0xAC,  0x00,  0x80,  0x00,  0x90,  0x00,  0x88,  0x00,  0x84,  0x00,  0x84,  0x7F,  0xFF,  0x00,  0x80, 	/* 3D230 */
+	0x00,  0x80,  0x01,  0x40,  0x01,  0x40,  0x02,  0x20,  0x02,  0x20,  0x04,  0x10,  0x08,  0x08,  0x10,  0x04, 	/* 3D240 */
+	0x60,  0x03,  0xAF,  0x04,  0x00,  0x44,  0xFC,  0x28,  0x84,  0x10,  0x84,  0x10,  0x84,  0x28,  0x84,  0x48, 	/* 3D250 */
+	0x84,  0x0C,  0x84,  0x14,  0x98,  0x14,  0x80,  0x24,  0x80,  0x44,  0x80,  0x04,  0x81,  0x04,  0x81,  0x34, 	/* 3D260 */
+	0x7F,  0x08,  0x00,  0xB2,  0x04,  0x08,  0x44,  0x08,  0x28,  0x08,  0x10,  0x08,  0x13,  0xFF,  0x28,  0x18, 	/* 3D270 */
+	0x48,  0x18,  0x08,  0x28,  0x18,  0x28,  0x18,  0x48,  0x28,  0x48,  0x48,  0x88,  0x09,  0x08,  0x0A,  0x08, 	/* 3D280 */
+	0x68,  0x08,  0x10,  0x18,  0xB6,  0x04,  0x20,  0x04,  0x24,  0x24,  0x22,  0x24,  0x22,  0x14,  0x20,  0x17, 	/* 3D290 */
+	0xFF,  0x04,  0x20,  0x04,  0x20,  0x0C,  0x50,  0x14,  0x50,  0x14,  0x50,  0x24,  0x88,  0x44,  0x88,  0x05, 	/* 3D2A0 */
+	0x04,  0x06,  0x02,  0x04,  0x01,  0xB9,  0x04,  0x48,  0x44,  0x44,  0x28,  0x44,  0x10,  0x40,  0x17,  0xFF, 	/* 3D2B0 */
+	0x28,  0x40,  0x48,  0x40,  0x08,  0x60,  0x18,  0xA0,  0x18,  0xA0,  0x28,  0xA0,  0x48,  0xA0,  0x09,  0x21, 	/* 3D2C0 */
+	0x09,  0x21,  0x1A,  0x11,  0x74,  0x0F,  0x82,  0x04,  0x00,  0x45,  0xFE,  0x28,  0x20,  0x10,  0x20,  0x10, 	/* 3D2D0 */
+	0x20,  0x28,  0x20,  0x48,  0x20,  0x09,  0xFC,  0x18,  0x20,  0x18,  0x20,  0x28,  0x20,  0x48,  0x20,  0x08, 	/* 3D2E0 */
+	0x20,  0x08,  0x20,  0x6F,  0xFF,  0x10,  0x00,  0x83,  0x04,  0x00,  0x45,  0xF8,  0x28,  0x88,  0x10,  0x88, 	/* 3D2F0 */
+	0x10,  0x88,  0x28,  0x88,  0x48,  0x88,  0x0B,  0xFF,  0x18,  0x88,  0x18,  0x88,  0x28,  0x88,  0x48,  0x88, 	/* 3D300 */
+	0x08,  0x88,  0x08,  0x88,  0x6F,  0xFF,  0x10,  0x00,  0x84,  0x04,  0x20,  0x44,  0x20,  0x28,  0x22,  0x11, 	/* 3D310 */
+	0x22,  0x11,  0x22,  0x29,  0x24,  0x49,  0x24,  0x09,  0x20,  0x1A,  0x30,  0x18,  0x30,  0x28,  0x50,  0x48, 	/* 3D320 */
+	0x48,  0x08,  0x88,  0x08,  0x84,  0x69,  0x02,  0x16,  0x01,  0x86,  0x04,  0x20,  0x44,  0x20,  0x28,  0x20, 	/* 3D330 */
+	0x10,  0x20,  0x13,  0xFE,  0x2A,  0x22,  0x4A,  0x22,  0x0A,  0x22,  0x1A,  0x22,  0x1B,  0xFE,  0x28,  0x20, 	/* 3D340 */
+	0x48,  0x20,  0x08,  0x20,  0x08,  0x20,  0x68,  0x20,  0x10,  0x20,  0x8E,  0x04,  0x00,  0x45,  0xFE,  0x29, 	/* 3D350 */
+	0x22,  0x11,  0x22,  0x11,  0x22,  0x29,  0xFE,  0x49,  0x22,  0x09,  0x22,  0x19,  0x22,  0x19,  0xFE,  0x28, 	/* 3D360 */
+	0x20,  0x48,  0x20,  0x08,  0x20,  0x08,  0x20,  0x68,  0x20,  0x10,  0x20,  0x90,  0x04,  0x02,  0x44,  0x0C, 	/* 3D370 */
+	0x29,  0xF4,  0x11,  0x04,  0x11,  0x24,  0x29,  0x24,  0x49,  0x24,  0x09,  0x24,  0x19,  0x24,  0x29,  0x24, 	/* 3D380 */
+	0x49,  0x34,  0x09,  0x34,  0x09,  0x2A,  0x0A,  0x3A,  0x6A,  0xC6,  0x14,  0x01,  0x92,  0x04,  0x90,  0x44, 	/* 3D390 */
+	0x90,  0x2B,  0xFE,  0x10,  0x92,  0x10,  0x92,  0x2B,  0xFE,  0x4A,  0x90,  0x0A,  0x90,  0x1B,  0xFE,  0x18, 	/* 3D3A0 */
+	0x92,  0x28,  0x92,  0x48,  0x92,  0x09,  0x12,  0x09,  0x1C,  0x6A,  0x10,  0x14,  0x10,  0x97,  0x04,  0x80, 	/* 3D3B0 */
+	0x44,  0x80,  0x28,  0x80,  0x11,  0xFE,  0x29,  0x02,  0x4A,  0x02,  0x04,  0xF2,  0x0C,  0x92,  0x14,  0x92, 	/* 3D3C0 */
+	0x24,  0x92,  0x44,  0x92,  0x04,  0xF2,  0x04,  0x02,  0x08,  0x02,  0x68,  0x04,  0x10,  0x18,  0x99,  0x04, 	/* 3D3D0 */
+	0x00,  0x44,  0xFC,  0x28,  0x84,  0x10,  0x84,  0x10,  0x84,  0x28,  0xFC,  0x48,  0x84,  0x08,  0x84,  0x18, 	/* 3D3E0 */
+	0x84,  0x18,  0xFC,  0x28,  0x84,  0x48,  0x84,  0x08,  0x84,  0x08,  0x84,  0x6B,  0xFF,  0x10,  0x00,  0x9B, 	/* 3D3F0 */
+	0x04,  0x20,  0x44,  0x20,  0x28,  0x20,  0x10,  0x40,  0x11,  0xFC,  0x29,  0x04,  0x49,  0x04,  0x09,  0x04, 	/* 3D400 */
+	0x19,  0x04,  0x19,  0xFC,  0x29,  0x04,  0x49,  0x04,  0x09,  0x04,  0x09,  0x04,  0x69,  0xFC,  0x10,  0x00, 	/* 3D410 */
+	0xA0,  0x04,  0x00,  0x44,  0xFC,  0x28,  0x84,  0x10,  0x84,  0x10,  0xFC,  0x28,  0x84,  0x48,  0x84,  0x08, 	/* 3D420 */
+	0x84,  0x18,  0xFE,  0x18,  0xA2,  0x28,  0x94,  0x48,  0x94,  0x08,  0x88,  0x08,  0x84,  0x68,  0xE2,  0x13, 	/* 3D430 */
+	0x81,  0xA1,  0x04,  0x20,  0x44,  0x20,  0x28,  0x20,  0x13,  0xFF,  0x10,  0x88,  0x28,  0x84,  0x49,  0x04, 	/* 3D440 */
+	0x09,  0x8A,  0x1A,  0x8A,  0x18,  0x50,  0x28,  0x50,  0x48,  0x20,  0x08,  0x50,  0x08,  0x88,  0x69,  0x04, 	/* 3D450 */
+	0x16,  0x03,  0xA2,  0x04,  0x40,  0x44,  0x40,  0x28,  0xF8,  0x10,  0x88,  0x11,  0x88,  0x29,  0x50,  0x4A, 	/* 3D460 */
+	0x20,  0x08,  0x50,  0x19,  0x8C,  0x1E,  0x03,  0x29,  0xFC,  0x49,  0x04,  0x09,  0x04,  0x09,  0x04,  0x69, 	/* 3D470 */
+	0xFC,  0x10,  0x00,  0xA9,  0x04,  0x20,  0x44,  0x20,  0x2B,  0xFF,  0x12,  0x01,  0x12,  0x01,  0x28,  0x08, 	/* 3D480 */
+	0x48,  0x08,  0x0B,  0xFF,  0x18,  0x08,  0x18,  0x88,  0x28,  0x48,  0x48,  0x48,  0x08,  0x08,  0x08,  0x08, 	/* 3D490 */
+	0x68,  0x08,  0x10,  0x18,  0xAC,  0x04,  0x20,  0x44,  0x20,  0x28,  0x20,  0x13,  0xFC,  0x12,  0x24,  0x2A, 	/* 3D4A0 */
+	0x24,  0x4A,  0x24,  0x0A,  0x24,  0x1B,  0xFC,  0x18,  0x20,  0x28,  0x20,  0x48,  0x28,  0x08,  0x24,  0x08, 	/* 3D4B0 */
+	0x3E,  0x17,  0xC2,  0x60,  0x02,  0xAD,  0x04,  0x20,  0x44,  0x20,  0x2B,  0xFE,  0x10,  0x20,  0x32,  0x24, 	/* 3D4C0 */
+	0x51,  0x24,  0x08,  0xA4,  0x08,  0xA8,  0x1F,  0xFF,  0x18,  0x20,  0x28,  0x50,  0x48,  0x50,  0x08,  0x88, 	/* 3D4D0 */
+	0x09,  0x04,  0x6A,  0x02,  0x14,  0x01,  0xB7,  0x04,  0x00,  0x45,  0xFC,  0x29,  0x04,  0x11,  0x04,  0x11, 	/* 3D4E0 */
+	0xFC,  0x28,  0x00,  0x49,  0xFC,  0x09,  0x04,  0x19,  0x04,  0x19,  0xFC,  0x29,  0x04,  0x49,  0x04,  0x09, 	/* 3D4F0 */
+	0xFC,  0x09,  0x04,  0x69,  0x04,  0x11,  0x0C,  0xB8,  0x04,  0x00,  0x47,  0xFC,  0x29,  0x24,  0x11,  0x24, 	/* 3D500 */
+	0x11,  0xFC,  0x29,  0x24,  0x49,  0x24,  0x09,  0x24,  0x19,  0xFC,  0x18,  0x20,  0x28,  0x20,  0x4B,  0xFE, 	/* 3D510 */
+	0x08,  0x20,  0x08,  0x20,  0x6F,  0xFF,  0x10,  0x00,  0xB9,  0x04,  0x20,  0x44,  0x20,  0x2F,  0xFF,  0x10, 	/* 3D520 */
+	0x20,  0x11,  0x24,  0x29,  0x24,  0x49,  0x24,  0x09,  0xAA,  0x1A,  0xAA,  0x1A,  0x51,  0x2C,  0x50,  0x48, 	/* 3D530 */
+	0x88,  0x08,  0x88,  0x09,  0x04,  0x6A,  0x02,  0x14,  0x01,  0xBC,  0x04,  0x20,  0x44,  0x20,  0x29,  0xF8, 	/* 3D540 */
+	0x11,  0x08,  0x11,  0x08,  0x29,  0xF8,  0x49,  0x08,  0x09,  0x08,  0x19,  0xFA,  0x19,  0x22,  0x29,  0x24, 	/* 3D550 */
+	0x49,  0x10,  0x09,  0x08,  0x09,  0x64,  0x69,  0x82,  0x16,  0x01,  0xBD,  0x04,  0x00,  0x45,  0xFC,  0x29, 	/* 3D560 */
+	0x04,  0x11,  0x04,  0x11,  0x04,  0x29,  0xFC,  0x49,  0x04,  0x09,  0x04,  0x19,  0xFC,  0x19,  0x04,  0x29, 	/* 3D570 */
+	0x04,  0x49,  0x04,  0x09,  0xFC,  0x08,  0x88,  0x69,  0x04,  0x16,  0x02,  0x8A,  0x04,  0x20,  0x44,  0x40, 	/* 3D580 */
+	0x29,  0x9E,  0x11,  0x02,  0x11,  0x02,  0x29,  0xCE,  0x49,  0x02,  0x09,  0x02,  0x19,  0xFE,  0x18,  0x50, 	/* 3D590 */
+	0x28,  0x50,  0x48,  0x50,  0x08,  0x90,  0x08,  0x91,  0x69,  0x11,  0x12,  0x0F,  0x96,  0x04,  0x00,  0x45, 	/* 3D5A0 */
+	0xFC,  0x29,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x29,  0x04,  0x49,  0xFC,  0x08,  0x00,  0x1B,  0xFE,  0x1A, 	/* 3D5B0 */
+	0x02,  0x2A,  0x02,  0x4B,  0xFE,  0x0A,  0x02,  0x0A,  0x02,  0x6B,  0xFE,  0x10,  0x00,  0x97,  0x04,  0x20, 	/* 3D5C0 */
+	0x44,  0x20,  0x2B,  0xFE,  0x10,  0x30,  0x10,  0x48,  0x29,  0x84,  0x48,  0x00,  0x0F,  0xFF,  0x18,  0x04, 	/* 3D5D0 */
+	0x19,  0xE4,  0x29,  0x24,  0x49,  0x24,  0x09,  0xE4,  0x08,  0x04,  0x68,  0x04,  0x10,  0x0C,  0x9B,  0x04, 	/* 3D5E0 */
+	0x00,  0x45,  0xFC,  0x28,  0x08,  0x10,  0x10,  0x10,  0x20,  0x2F,  0xFF,  0x48,  0x20,  0x08,  0x20,  0x18, 	/* 3D5F0 */
+	0x60,  0x18,  0x00,  0x2B,  0xFE,  0x4A,  0x52,  0x0A,  0x52,  0x0A,  0x52,  0x6F,  0xFF,  0x10,  0x00,  0x9C, 	/* 3D600 */
+	0x04,  0x20,  0x44,  0x20,  0x2B,  0xFE,  0x10,  0x20,  0x11,  0xFC,  0x28,  0x20,  0x4F,  0xFF,  0x08,  0x00, 	/* 3D610 */
+	0x19,  0xFC,  0x19,  0x24,  0x29,  0x24,  0x49,  0xFC,  0x09,  0x04,  0x09,  0x04,  0x69,  0x04,  0x11,  0x0C, 	/* 3D620 */
+	0x9D,  0x04,  0x20,  0x44,  0x20,  0x2B,  0xFE,  0x10,  0x88,  0x10,  0x88,  0x28,  0xCC,  0x49,  0x12,  0x0A, 	/* 3D630 */
+	0x20,  0x18,  0x20,  0x1F,  0xFF,  0x28,  0x20,  0x48,  0x20,  0x08,  0x20,  0x08,  0x20,  0x68,  0x20,  0x10, 	/* 3D640 */
+	0x20,  0x9F,  0x04,  0x44,  0x46,  0x24,  0x29,  0x28,  0x11,  0x10,  0x11,  0xFC,  0x29,  0x24,  0x49,  0x24, 	/* 3D650 */
+	0x09,  0xFC,  0x19,  0x24,  0x19,  0x24,  0x29,  0xFC,  0x49,  0x24,  0x09,  0x24,  0x0A,  0x25,  0x6A,  0x25, 	/* 3D660 */
+	0x14,  0x23,  0xA5,  0x04,  0x00,  0x45,  0xFC,  0x29,  0x24,  0x11,  0x24,  0x11,  0xFC,  0x29,  0x24,  0x49, 	/* 3D670 */
+	0x24,  0x09,  0xFC,  0x18,  0x00,  0x1F,  0xFF,  0x29,  0x44,  0x49,  0x44,  0x09,  0x28,  0x09,  0x10,  0x69, 	/* 3D680 */
+	0xCC,  0x17,  0x03,  0xA9,  0x04,  0x00,  0x45,  0xFC,  0x29,  0x04,  0x11,  0xFC,  0x11,  0x04,  0x29,  0x04, 	/* 3D690 */
+	0x49,  0xFC,  0x08,  0x20,  0x19,  0x20,  0x19,  0xFE,  0x2A,  0x20,  0x4D,  0xFC,  0x08,  0x20,  0x08,  0x20, 	/* 3D6A0 */
+	0x6F,  0xFF,  0x10,  0x00,  0xAA,  0x04,  0x20,  0x44,  0x24,  0x29,  0xFE,  0x10,  0x24,  0x10,  0x24,  0x28, 	/* 3D6B0 */
+	0x28,  0x4B,  0xFF,  0x08,  0x20,  0x18,  0xFC,  0x19,  0x84,  0x2A,  0x84,  0x48,  0xFC,  0x08,  0x84,  0x08, 	/* 3D6C0 */
+	0x84,  0x68,  0xFC,  0x10,  0x00,  0xAB,  0x04,  0x88,  0x44,  0x88,  0x2F,  0xFF,  0x10,  0x88,  0x10,  0x88, 	/* 3D6D0 */
+	0x28,  0x00,  0x4B,  0xFE,  0x0A,  0x22,  0x1A,  0x22,  0x1A,  0x22,  0x2B,  0xFE,  0x4A,  0x22,  0x0A,  0x22, 	/* 3D6E0 */
+	0x0A,  0x22,  0x6B,  0xFE,  0x10,  0x00,  0xAE,  0x04,  0x08,  0x04,  0x08,  0x7F,  0xCA,  0x04,  0x09,  0x04, 	/* 3D6F0 */
+	0x09,  0x3F,  0xFF,  0x32,  0x88,  0x2A,  0x88,  0x2C,  0x88,  0x3F,  0x94,  0x24,  0x94,  0x3F,  0x94,  0x24, 	/* 3D700 */
+	0xA4,  0x24,  0xA2,  0x24,  0xC2,  0x21,  0x81,  0xAF,  0x04,  0x20,  0x45,  0x22,  0x29,  0x22,  0x11,  0x22, 	/* 3D710 */
+	0x11,  0xFE,  0x28,  0x00,  0x4B,  0xFF,  0x08,  0x20,  0x18,  0x40,  0x19,  0xFE,  0x29,  0x52,  0x49,  0x52, 	/* 3D720 */
+	0x09,  0x52,  0x09,  0x52,  0x69,  0x52,  0x11,  0x06,  0xB4,  0x44,  0x80,  0x24,  0xBC,  0x14,  0x84,  0x19, 	/* 3D730 */
+	0x04,  0x11,  0xFF,  0x1B,  0x20,  0x2D,  0x20,  0x49,  0x7E,  0x19,  0x90,  0x19,  0x10,  0x29,  0xFF,  0x49, 	/* 3D740 */
+	0x18,  0x09,  0x28,  0x09,  0x24,  0x69,  0x42,  0x11,  0x81,  0xB6,  0x05,  0x04,  0x44,  0x84,  0x28,  0x88, 	/* 3D750 */
+	0x13,  0xFF,  0x10,  0x50,  0x28,  0x50,  0x49,  0xFE,  0x09,  0x52,  0x19,  0x52,  0x19,  0x9E,  0x29,  0x02, 	/* 3D760 */
+	0x49,  0xFE,  0x09,  0x02,  0x09,  0x02,  0x69,  0xFE,  0x11,  0x02,  0xB7,  0x21,  0x10,  0x11,  0x14,  0x12, 	/* 3D770 */
+	0x12,  0x7F,  0xD2,  0x0A,  0x10,  0x0A,  0x7F,  0x3F,  0x90,  0x2A,  0x90,  0x2A,  0x90,  0x2B,  0x90,  0x30, 	/* 3D780 */
+	0xA8,  0x20,  0xA8,  0x3F,  0xA4,  0x20,  0xC4,  0x3F,  0xC2,  0x20,  0x81,  0xBE,  0x04,  0x00,  0x44,  0xFC, 	/* 3D790 */
+	0x28,  0x84,  0x10,  0xBC,  0x10,  0xA4,  0x28,  0xA4,  0x4B,  0xFF,  0x0A,  0x01,  0x1A,  0xFD,  0x18,  0x84, 	/* 3D7A0 */
+	0x28,  0xFC,  0x48,  0x84,  0x08,  0xFC,  0x08,  0x84,  0x68,  0x84,  0x10,  0x8C,  0xBF,  0x08,  0x20,  0x48, 	/* 3D7B0 */
+	0x20,  0x29,  0xFC,  0x10,  0x20,  0x17,  0xFF,  0x28,  0x00,  0x49,  0xFC,  0x09,  0x04,  0x19,  0x04,  0x19, 	/* 3D7C0 */
+	0xFC,  0x28,  0xA2,  0x49,  0x92,  0x0E,  0x94,  0x08,  0x88,  0x68,  0xE4,  0x13,  0x03,  0x84,  0x08,  0x08, 	/* 3D7D0 */
+	0x4B,  0xCC,  0x28,  0x0A,  0x17,  0xEA,  0x10,  0x08,  0x2B,  0xFF,  0x48,  0x08,  0x0B,  0xC8,  0x18,  0x08, 	/* 3D7E0 */
+	0x18,  0x0C,  0x2B,  0xD4,  0x4A,  0x54,  0x0A,  0x54,  0x0A,  0x62,  0x6B,  0xC2,  0x10,  0x81,  0x85,  0x09, 	/* 3D7F0 */
+	0x00,  0x4A,  0x7F,  0x2B,  0x88,  0x32,  0x88,  0x12,  0xBE,  0x12,  0xAA,  0x33,  0xAA,  0x4A,  0x2A,  0x1B, 	/* 3D800 */
+	0xAA,  0x1A,  0xAA,  0x2A,  0xAA,  0x4A,  0xAA,  0x0B,  0xAE,  0x0A,  0xA8,  0x6A,  0x08,  0x10,  0x08,  0x8E, 	/* 3D810 */
+	0x04,  0x10,  0x24,  0x3E,  0x25,  0xCA,  0x3C,  0x2C,  0x05,  0xF0,  0x7C,  0x04,  0x17,  0xFF,  0x14,  0x84, 	/* 3D820 */
+	0x24,  0x44,  0x44,  0x9C,  0x00,  0x88,  0x7F,  0xFF,  0x01,  0x40,  0x02,  0x20,  0x0C,  0x18,  0x70,  0x07, 	/* 3D830 */
+	0x8F,  0x04,  0x88,  0x44,  0x88,  0x2B,  0xFF,  0x10,  0x88,  0x10,  0x00,  0x29,  0xFC,  0x49,  0x04,  0x09, 	/* 3D840 */
+	0xFC,  0x19,  0x04,  0x19,  0xFC,  0x28,  0x20,  0x4F,  0xFF,  0x08,  0x20,  0x08,  0x50,  0x69,  0x8C,  0x16, 	/* 3D850 */
+	0x03,  0x97,  0x10,  0x00,  0x17,  0xFF,  0x56,  0x28,  0x25,  0x28,  0x25,  0x5F,  0x57,  0xFA,  0x14,  0x8C, 	/* 3D860 */
+	0x16,  0xA8,  0x36,  0xA8,  0x36,  0xA8,  0x56,  0xAC,  0x17,  0xF4,  0x14,  0x94,  0x19,  0x14,  0x11,  0x22, 	/* 3D870 */
+	0x62,  0x41,  0xA3,  0x11,  0x10,  0x49,  0x14,  0x2A,  0x12,  0x3F,  0x12,  0x29,  0x10,  0x3F,  0xFF,  0x29, 	/* 3D880 */
+	0x10,  0x3F,  0x10,  0x00,  0x10,  0x7F,  0xA8,  0x00,  0x28,  0x3F,  0x28,  0x21,  0x44,  0x21,  0x44,  0x3F, 	/* 3D890 */
+	0x82,  0x01,  0x01,  0xA8,  0x04,  0x00,  0x47,  0xFE,  0x2A,  0x52,  0x12,  0x52,  0x13,  0xFE,  0x28,  0x80, 	/* 3D8A0 */
+	0x48,  0xFE,  0x09,  0x42,  0x1B,  0xF2,  0x1D,  0x52,  0x29,  0x52,  0x49,  0xF2,  0x08,  0x52,  0x08,  0x6A, 	/* 3D8B0 */
+	0x6B,  0x84,  0x10,  0x18,  0xAA,  0x04,  0x20,  0x44,  0x50,  0x28,  0x88,  0x11,  0xFC,  0x16,  0x03,  0x2B, 	/* 3D8C0 */
+	0xFE,  0x4B,  0x26,  0x0A,  0xAA,  0x1B,  0xFE,  0x18,  0x00,  0x29,  0xFC,  0x49,  0x04,  0x09,  0xFC,  0x09, 	/* 3D8D0 */
+	0x04,  0x69,  0xFC,  0x10,  0x00,  0xB0,  0x04,  0x20,  0x44,  0x20,  0x2B,  0xFF,  0x12,  0x21,  0x10,  0x91, 	/* 3D8E0 */
+	0x2A,  0x8A,  0x4C,  0x79,  0x08,  0x01,  0x1B,  0xFE,  0x1A,  0x52,  0x2B,  0xFE,  0x48,  0x00,  0x0B,  0xFF, 	/* 3D8F0 */
+	0x08,  0x20,  0x68,  0x20,  0x10,  0x60,  0xB2,  0x04,  0x48,  0x47,  0xFF,  0x28,  0x48,  0x10,  0x90,  0x11, 	/* 3D900 */
+	0xFE,  0x29,  0x10,  0x4B,  0xFC,  0x19,  0x10,  0x15,  0xFC,  0x25,  0x10,  0x47,  0xFE,  0x04,  0x88,  0x04, 	/* 3D910 */
+	0x50,  0x08,  0x20,  0x28,  0xD8,  0x13,  0x06,  0xB5,  0x09,  0x24,  0x4A,  0x48,  0x29,  0x24,  0x13,  0xFC, 	/* 3D920 */
+	0x12,  0x54,  0x2A,  0x24,  0x4A,  0xD4,  0x0B,  0xFC,  0x18,  0x00,  0x1B,  0x34,  0x2A,  0xAC,  0x4B,  0x34, 	/* 3D930 */
+	0x0A,  0xAD,  0x0A,  0x25,  0x6B,  0xBB,  0x16,  0x61,  0xB8,  0x3B,  0x90,  0x2A,  0x94,  0x3B,  0x92,  0x00, 	/* 3D940 */
+	0x12,  0x3F,  0x10,  0x25,  0xFF,  0x3F,  0x10,  0x25,  0x10,  0x3F,  0x10,  0x00,  0x18,  0x7F,  0xA8,  0x00, 	/* 3D950 */
+	0x28,  0x3F,  0x44,  0x21,  0x44,  0x3F,  0x82,  0x01,  0x01,  0xBA,  0x11,  0x00,  0x51,  0x3E,  0x2F,  0xCA, 	/* 3D960 */
+	0x21,  0x12,  0x31,  0x26,  0x57,  0xC0,  0x15,  0x7E,  0x15,  0x62,  0x15,  0x7E,  0x37,  0xE2,  0x31,  0xBE, 	/* 3D970 */
+	0x53,  0x62,  0x13,  0x3E,  0x15,  0x14,  0x19,  0x22,  0x61,  0x41,  0xBB,  0x04,  0x08,  0x07,  0x8C,  0x04, 	/* 3D980 */
+	0x0A,  0x3F,  0xEA,  0x27,  0x48,  0x3C,  0x3F,  0x2F,  0xC8,  0x28,  0x88,  0x2F,  0x88,  0x20,  0x0C,  0x3F, 	/* 3D990 */
+	0xD4,  0x35,  0x54,  0x39,  0xD4,  0x57,  0x52,  0x52,  0x62,  0x12,  0xC1,  0x84,  0x00,  0x80,  0x00,  0x80, 	/* 3D9A0 */
+	0x00,  0x80,  0x7F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x01,  0x10,  0x0E,  0x10,  0x01,  0x20,  0x01,  0x40, 	/* 3D9B0 */
+	0x00,  0x80,  0x01,  0x10,  0x02,  0x08,  0x04,  0x7C,  0x3F,  0x82,  0x00,  0x02,  0x87,  0x00,  0x80,  0x00, 	/* 3D9C0 */
+	0x80,  0x3F,  0xFE,  0x10,  0x84,  0x0B,  0x28,  0x05,  0x40,  0x00,  0x90,  0x0D,  0x2C,  0x33,  0xF2,  0x00, 	/* 3D9D0 */
+	0x90,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x89,  0x00,  0x00, 	/* 3D9E0 */
+	0x3F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80, 	/* 3D9F0 */
+	0x00,  0x80,  0x00,  0x90,  0x00,  0x88,  0x00,  0x88,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x8B,  0x00, 	/* 3DA00 */
+	0x00,  0x3F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00, 	/* 3DA10 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x96, 	/* 3DA20 */
+	0x00,  0x40,  0x00,  0x40,  0x7C,  0x78,  0x10,  0x88,  0x10,  0x88,  0x11,  0x08,  0x12,  0x10,  0x7C,  0x10, 	/* 3DA30 */
+	0x10,  0x20,  0x10,  0x20,  0x10,  0x50,  0x12,  0x48,  0x1C,  0x84,  0x71,  0x04,  0x02,  0x02,  0x0C,  0x02, 	/* 3DA40 */
+	0xA9,  0x00,  0x00,  0x00,  0xFC,  0x7E,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x13,  0xFF,  0x7C, 	/* 3DA50 */
+	0x48,  0x10,  0x48,  0x10,  0x48,  0x10,  0x48,  0x16,  0x48,  0x18,  0x88,  0x60,  0x89,  0x01,  0x07,  0x02, 	/* 3DA60 */
+	0x00,  0xB2,  0x00,  0x20,  0x7E,  0x20,  0x10,  0x50,  0x10,  0x48,  0x10,  0x84,  0x11,  0xFA,  0x7E,  0x01, 	/* 3DA70 */
+	0x10,  0x00,  0x11,  0xFC,  0x10,  0x44,  0x14,  0x44,  0x18,  0x44,  0x60,  0x44,  0x00,  0x58,  0x00,  0x40, 	/* 3DA80 */
+	0x00,  0x40,  0xB3,  0x00,  0x90,  0x00,  0x94,  0x7C,  0x92,  0x11,  0x12,  0x11,  0x10,  0x13,  0x1F,  0x15, 	/* 3DA90 */
+	0xF0,  0x79,  0x10,  0x11,  0x10,  0x11,  0x08,  0x11,  0x08,  0x15,  0x08,  0x19,  0x05,  0x61,  0x05,  0x01, 	/* 3DAA0 */
+	0x03,  0x01,  0x01,  0xBB,  0x00,  0x20,  0x00,  0x20,  0x7C,  0x20,  0x11,  0xFF,  0x11,  0x22,  0x11,  0x24, 	/* 3DAB0 */
+	0x7D,  0x20,  0x11,  0xFC,  0x11,  0x04,  0x11,  0x44,  0x17,  0x48,  0x19,  0x30,  0x62,  0x30,  0x02,  0x48, 	/* 3DAC0 */
+	0x04,  0x84,  0x0B,  0x03,  0x80,  0x00,  0x20,  0x00,  0x20,  0x7C,  0x40,  0x11,  0xFC,  0x11,  0x04,  0x11, 	/* 3DAD0 */
+	0x04,  0x11,  0x04,  0x7D,  0x04,  0x11,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x17,  0x04,  0x19,  0x04,  0x61, 	/* 3DAE0 */
+	0x04,  0x01,  0xFC,  0x00,  0x00,  0x82,  0x00,  0x00,  0x7F,  0xFF,  0x10,  0x04,  0x10,  0x04,  0x11,  0xE4, 	/* 3DAF0 */
+	0x11,  0x24,  0x7D,  0x24,  0x11,  0x24,  0x11,  0x24,  0x11,  0x24,  0x11,  0xE4,  0x10,  0x04,  0x1C,  0x04, 	/* 3DB00 */
+	0x70,  0x04,  0x00,  0x04,  0x00,  0x0C,  0x88,  0x01,  0x00,  0x01,  0x00,  0x7D,  0x00,  0x11,  0x1E,  0x17, 	/* 3DB10 */
+	0xD2,  0x11,  0x52,  0x11,  0x52,  0x7D,  0x52,  0x11,  0x52,  0x11,  0x52,  0x16,  0x52,  0x1A,  0x52,  0x62, 	/* 3DB20 */
+	0x52,  0x04,  0x5E,  0x08,  0x52,  0x01,  0x80,  0x8A,  0x00,  0x00,  0x7D,  0xFC,  0x11,  0x54,  0x11,  0x54, 	/* 3DB30 */
+	0x11,  0x54,  0x11,  0x54,  0x7D,  0x54,  0x17,  0xFF,  0x11,  0x54,  0x11,  0x54,  0x11,  0x54,  0x11,  0x54, 	/* 3DB40 */
+	0x1D,  0x54,  0x71,  0x54,  0x01,  0x54,  0x01,  0x0C,  0x8D,  0x00,  0x20,  0x00,  0x20,  0x7E,  0x50,  0x10, 	/* 3DB50 */
+	0x50,  0x10,  0x88,  0x11,  0x14,  0x12,  0x22,  0x7C,  0x45,  0x11,  0x88,  0x10,  0x10,  0x10,  0x62,  0x11, 	/* 3DB60 */
+	0x84,  0x1E,  0x08,  0x70,  0x10,  0x00,  0x60,  0x01,  0x80,  0x8E,  0x00,  0x40,  0x00,  0x40,  0x7C,  0x40, 	/* 3DB70 */
+	0x10,  0xFF,  0x10,  0x90,  0x11,  0x10,  0x12,  0x10,  0x7C,  0x14,  0x10,  0x94,  0x10,  0x92,  0x10,  0x92, 	/* 3DB80 */
+	0x10,  0x92,  0x1D,  0x12,  0x72,  0x10,  0x00,  0x10,  0x00,  0x30,  0x9E,  0x00,  0x40,  0x00,  0x40,  0x7C, 	/* 3DB90 */
+	0xFC,  0x10,  0x84,  0x11,  0x48,  0x12,  0x30,  0x10,  0x30,  0x7C,  0x48,  0x11,  0x84,  0x16,  0x03,  0x11, 	/* 3DBA0 */
+	0xFC,  0x15,  0x04,  0x19,  0x04,  0x61,  0x04,  0x01,  0xFC,  0x00,  0x00,  0xA0,  0x00,  0x20,  0x00,  0xA0, 	/* 3DBB0 */
+	0x7C,  0xA0,  0x10,  0xFE,  0x11,  0x20,  0x12,  0x20,  0x7C,  0x20,  0x13,  0xFF,  0x10,  0x70,  0x10,  0x70, 	/* 3DBC0 */
+	0x10,  0xA8,  0x1D,  0x24,  0x72,  0x22,  0x04,  0x21,  0x00,  0x20,  0x00,  0x20,  0xA5,  0x00,  0x00,  0x03, 	/* 3DBD0 */
+	0xFF,  0x7C,  0x84,  0x10,  0x84,  0x10,  0xFC,  0x10,  0x84,  0x7C,  0x84,  0x10,  0x84,  0x10,  0xFC,  0x10, 	/* 3DBE0 */
+	0x84,  0x14,  0x84,  0x18,  0x87,  0x60,  0xFC,  0x03,  0x84,  0x00,  0x04,  0x00,  0x04,  0xAA,  0x00,  0x20, 	/* 3DBF0 */
+	0x7C,  0x20,  0x11,  0xFC,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x7F,  0xFF,  0x10,  0x00,  0x10,  0x20, 	/* 3DC00 */
+	0x10,  0x20,  0x11,  0xFC,  0x1C,  0x20,  0x60,  0x20,  0x00,  0x20,  0x07,  0xFF,  0x00,  0x00,  0xAD,  0x00, 	/* 3DC10 */
+	0x40,  0x7C,  0x7F,  0x12,  0x48,  0x12,  0x48,  0x12,  0x48,  0x12,  0x48,  0x7E,  0x48,  0x12,  0x7E,  0x12, 	/* 3DC20 */
+	0x48,  0x12,  0x48,  0x10,  0x48,  0x14,  0x48,  0x18,  0x88,  0x10,  0x88,  0x61,  0x3F,  0x02,  0x00,  0xAE, 	/* 3DC30 */
+	0x00,  0x00,  0x03,  0xFC,  0x7E,  0x04,  0x12,  0x04,  0x12,  0xFC,  0x12,  0x24,  0x7E,  0x24,  0x12,  0xFC, 	/* 3DC40 */
+	0x12,  0xAC,  0x12,  0xAC,  0x16,  0xAC,  0x1A,  0xBC,  0x62,  0xA5,  0x04,  0x25,  0x04,  0x23,  0x08,  0x01, 	/* 3DC50 */
+	0xB1,  0x00,  0x42,  0x02,  0x22,  0x7D,  0x22,  0x11,  0x24,  0x11,  0x04,  0x10,  0x48,  0x10,  0x40,  0x7C, 	/* 3DC60 */
+	0x40,  0x17,  0xFF,  0x10,  0x88,  0x10,  0x88,  0x15,  0xE8,  0x19,  0x10,  0x60,  0x28,  0x00,  0xC4,  0x07, 	/* 3DC70 */
+	0x02,  0xB8,  0x00,  0x00,  0x03,  0xFF,  0x7C,  0x20,  0x10,  0x20,  0x11,  0xFC,  0x10,  0x44,  0x7C,  0x44, 	/* 3DC80 */
+	0x10,  0x44,  0x13,  0xFF,  0x10,  0x00,  0x14,  0xFC,  0x18,  0x84,  0x60,  0x84,  0x00,  0x84,  0x00,  0xFC, 	/* 3DC90 */
+	0x00,  0x00,  0xBE,  0x00,  0x00,  0x01,  0xFC,  0x7D,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x11,  0x04,  0x7D, 	/* 3DCA0 */
+	0xFC,  0x11,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x10,  0x50,  0x1C,  0x50,  0x60,  0x90,  0x01,  0x11,  0x06, 	/* 3DCB0 */
+	0x11,  0x18,  0x0F,  0x83,  0x00,  0x24,  0x00,  0x22,  0x7C,  0x22,  0x13,  0xFF,  0x10,  0x20,  0x12,  0x22, 	/* 3DCC0 */
+	0x11,  0x32,  0x7C,  0xB4,  0x10,  0xB4,  0x10,  0x28,  0x12,  0x68,  0x14,  0xA4,  0x19,  0x22,  0x66,  0x21, 	/* 3DCD0 */
+	0x00,  0x20,  0x00,  0x60,  0x85,  0x00,  0x20,  0x00,  0x20,  0x7E,  0xFC,  0x08,  0x84,  0x08,  0x84,  0x08, 	/* 3DCE0 */
+	0xFC,  0x08,  0x84,  0x7E,  0x84,  0x08,  0xFE,  0x08,  0x92,  0x08,  0x94,  0x0E,  0x88,  0x18,  0x88,  0x60, 	/* 3DCF0 */
+	0xA4,  0x00,  0xC2,  0x03,  0x01,  0x86,  0x00,  0x00,  0x01,  0xFE,  0x7F,  0x22,  0x11,  0x22,  0x11,  0xFE, 	/* 3DD00 */
+	0x11,  0x22,  0x7D,  0x22,  0x11,  0x22,  0x11,  0xFE,  0x10,  0x20,  0x14,  0x20,  0x19,  0xFE,  0x60,  0x20, 	/* 3DD10 */
+	0x00,  0x20,  0x07,  0xFF,  0x00,  0x00,  0x89,  0x00,  0x20,  0x7C,  0x20,  0x13,  0xFF,  0x10,  0x20,  0x10, 	/* 3DD20 */
+	0x58,  0x10,  0x8C,  0x7D,  0xF2,  0x10,  0x00,  0x10,  0xA4,  0x10,  0xA4,  0x12,  0xA4,  0x1C,  0xA4,  0x70, 	/* 3DD30 */
+	0xA4,  0x01,  0x25,  0x01,  0x05,  0x02,  0x03,  0xA2,  0x00,  0x00,  0x7F,  0xFF,  0x10,  0x40,  0x10,  0x44, 	/* 3DD40 */
+	0x10,  0xA4,  0x13,  0x24,  0x7C,  0x28,  0x10,  0x58,  0x10,  0x98,  0x13,  0x34,  0x10,  0x34,  0x1C,  0x52, 	/* 3DD50 */
+	0x70,  0x91,  0x03,  0x10,  0x00,  0x10,  0x00,  0x60,  0xA5,  0x00,  0x20,  0x00,  0x3E,  0x7C,  0x20,  0x11, 	/* 3DD60 */
+	0xFF,  0x11,  0x02,  0x11,  0x20,  0x7D,  0x3C,  0x11,  0xE0,  0x11,  0x22,  0x11,  0x1E,  0x15,  0x48,  0x1A, 	/* 3DD70 */
+	0x48,  0x62,  0x48,  0x04,  0x89,  0x09,  0x09,  0x02,  0x07,  0xB2,  0x00,  0x48,  0x00,  0x48,  0x7C,  0x48, 	/* 3DD80 */
+	0x13,  0xCF,  0x10,  0x48,  0x10,  0x48,  0x7C,  0x48,  0x13,  0xCF,  0x10,  0x48,  0x10,  0x48,  0x14,  0x48, 	/* 3DD90 */
+	0x19,  0xCF,  0x66,  0x88,  0x00,  0x88,  0x01,  0x08,  0x02,  0x08,  0xB3,  0x00,  0x88,  0x7C,  0x88,  0x10, 	/* 3DDA0 */
+	0x88,  0x13,  0xFF,  0x10,  0x88,  0x10,  0x88,  0x7D,  0xDC,  0x11,  0xBC,  0x12,  0xAA,  0x12,  0xAA,  0x14, 	/* 3DDB0 */
+	0xC9,  0x10,  0x88,  0x1C,  0x88,  0x60,  0x88,  0x00,  0x88,  0x00,  0x88,  0xB4,  0x00,  0x00,  0x7F,  0x7E, 	/* 3DDC0 */
+	0x08,  0x08,  0x3E,  0x7E,  0x08,  0x08,  0x0B,  0x88,  0x1C,  0xBF,  0x61,  0x40,  0x02,  0x20,  0x0C,  0x18, 	/* 3DDD0 */
+	0x73,  0xE7,  0x00,  0x00,  0x0F,  0xF0,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0xB5,  0x00,  0x00,  0x7F, 	/* 3DDE0 */
+	0x7E,  0x08,  0x10,  0x08,  0x10,  0x3E,  0x7C,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xFE,  0x70,  0x40,  0x10, 	/* 3DDF0 */
+	0x40,  0x10,  0x4C,  0x1F,  0x70,  0x10,  0x40,  0x10,  0x42,  0x1F,  0x42,  0x70,  0x3E,  0xB6,  0x00,  0x00, 	/* 3DE00 */
+	0x7F,  0x7F,  0x08,  0x08,  0x3E,  0x3E,  0x08,  0x08,  0x0F,  0x7F,  0x70,  0x00,  0x1F,  0xF8,  0x10,  0x88, 	/* 3DE10 */
+	0x10,  0x88,  0x10,  0x88,  0x1F,  0xF8,  0x10,  0x00,  0x10,  0x02,  0x08,  0x02,  0x07,  0xFE,  0xBA,  0x01, 	/* 3DE20 */
+	0x10,  0x00,  0x90,  0x7C,  0x90,  0x10,  0x7E,  0x12,  0x10,  0x11,  0x10,  0x11,  0x10,  0x7C,  0xFF,  0x10, 	/* 3DE30 */
+	0x10,  0x11,  0x10,  0x11,  0x18,  0x15,  0x24,  0x1A,  0x24,  0x62,  0x4E,  0x04,  0xF2,  0x04,  0x02,  0xBF, 	/* 3DE40 */
+	0x00,  0x00,  0x03,  0xFE,  0x7E,  0x02,  0x12,  0x20,  0x13,  0xFE,  0x10,  0x20,  0x11,  0xFC,  0x7D,  0x24, 	/* 3DE50 */
+	0x11,  0xFC,  0x11,  0x24,  0x11,  0x24,  0x15,  0xFC,  0x18,  0x20,  0x63,  0xFF,  0x00,  0x20,  0x00,  0x20, 	/* 3DE60 */
+	0x81,  0x00,  0x00,  0x03,  0xFE,  0x7E,  0x02,  0x12,  0xFA,  0x12,  0x02,  0x12,  0xFA,  0x7A,  0x02,  0x10, 	/* 3DE70 */
+	0x00,  0x11,  0xFC,  0x11,  0x04,  0x15,  0xFC,  0x19,  0x04,  0x61,  0xFC,  0x01,  0x04,  0x01,  0xFC,  0x00, 	/* 3DE80 */
+	0x00,  0x95,  0x00,  0x00,  0x03,  0xDE,  0x7E,  0x42,  0x12,  0x42,  0x12,  0x42,  0x13,  0xDE,  0x7E,  0x00, 	/* 3DE90 */
+	0x12,  0x3E,  0x13,  0xD2,  0x12,  0x12,  0x12,  0x14,  0x1E,  0x08,  0x73,  0xCC,  0x02,  0x14,  0x02,  0x22, 	/* 3DEA0 */
+	0x02,  0x41,  0x99,  0x00,  0x92,  0x7C,  0x92,  0x13,  0x6C,  0x11,  0x24,  0x10,  0x92,  0x10,  0x20,  0x7C, 	/* 3DEB0 */
+	0x40,  0x13,  0xFE,  0x12,  0x12,  0x12,  0xD2,  0x16,  0x22,  0x1A,  0x32,  0x62,  0x4A,  0x02,  0x82,  0x03, 	/* 3DEC0 */
+	0xFE,  0x00,  0x00,  0x9A,  0x01,  0x00,  0x01,  0x1E,  0x7D,  0x12,  0x17,  0xF2,  0x11,  0x12,  0x11,  0x1E, 	/* 3DED0 */
+	0x11,  0x12,  0x7F,  0xD2,  0x12,  0x52,  0x12,  0x5E,  0x12,  0x52,  0x12,  0x52,  0x17,  0xD2,  0x1A,  0x22, 	/* 3DEE0 */
+	0x60,  0x22,  0x00,  0x46,  0x9B,  0x00,  0x88,  0x00,  0x88,  0x7F,  0xFF,  0x10,  0x88,  0x10,  0xA8,  0x10, 	/* 3DEF0 */
+	0x20,  0x11,  0xFC,  0x7D,  0x24,  0x11,  0x24,  0x11,  0x24,  0x17,  0xFF,  0x10,  0x30,  0x1C,  0x48,  0x70, 	/* 3DF00 */
+	0x84,  0x03,  0x02,  0x0C,  0x01,  0x9C,  0x00,  0x60,  0x00,  0x20,  0x7C,  0x50,  0x10,  0x88,  0x11,  0xF4, 	/* 3DF10 */
+	0x16,  0x03,  0x13,  0xCA,  0x7E,  0x4A,  0x13,  0x4A,  0x12,  0xD4,  0x12,  0x54,  0x17,  0x54,  0x1A,  0xCA, 	/* 3DF20 */
+	0x62,  0x4A,  0x02,  0x4A,  0x02,  0xCA,  0x9E,  0x00,  0x20,  0x01,  0x22,  0x7D,  0x22,  0x11,  0x22,  0x11, 	/* 3DF30 */
+	0xFE,  0x10,  0x00,  0x13,  0xFF,  0x7C,  0x20,  0x10,  0x40,  0x11,  0xFE,  0x11,  0x4A,  0x11,  0x4A,  0x1D, 	/* 3DF40 */
+	0x4A,  0x71,  0x4A,  0x01,  0x4A,  0x01,  0x06,  0x9F,  0x00,  0x00,  0x7F,  0x7F,  0x08,  0x08,  0x08,  0x08, 	/* 3DF50 */
+	0x3E,  0x3E,  0x08,  0x08,  0x08,  0x08,  0x0F,  0x7F,  0x70,  0x00,  0x03,  0x20,  0x00,  0xA0,  0x12,  0x44, 	/* 3DF60 */
+	0x12,  0x42,  0x22,  0x89,  0x43,  0x09,  0x0D,  0xF8,  0xA0,  0x00,  0x40,  0x7F,  0xBE,  0x12,  0x0A,  0x12, 	/* 3DF70 */
+	0x8A,  0x12,  0x52,  0x12,  0x52,  0x7B,  0xA2,  0x16,  0x4C,  0x10,  0x00,  0x11,  0xFE,  0x11,  0x22,  0x15, 	/* 3DF80 */
+	0xFE,  0x19,  0x22,  0x61,  0x22,  0x01,  0xFE,  0x00,  0x00,  0xA3,  0x00,  0x20,  0x7C,  0xA8,  0x10,  0xA4, 	/* 3DF90 */
+	0x11,  0x22,  0x13,  0xFE,  0x11,  0x04,  0x7D,  0x04,  0x11,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x15,  0x04, 	/* 3DFA0 */
+	0x19,  0x04,  0x61,  0xFC,  0x00,  0x48,  0x01,  0x84,  0x06,  0x02,  0xA4,  0x00,  0x10,  0x00,  0x1E,  0x7C, 	/* 3DFB0 */
+	0x62,  0x13,  0x94,  0x10,  0x48,  0x10,  0x30,  0x7C,  0xC0,  0x13,  0x7E,  0x10,  0xD0,  0x11,  0x10,  0x17, 	/* 3DFC0 */
+	0xFF,  0x18,  0x10,  0x61,  0x12,  0x01,  0x12,  0x01,  0xFE,  0x00,  0x00,  0xA9,  0x04,  0x10,  0x15,  0x54, 	/* 3DFD0 */
+	0x15,  0x54,  0x26,  0x98,  0x09,  0x24,  0x10,  0x40,  0x3F,  0xFE,  0x20,  0x02,  0x20,  0x02,  0x1F,  0xFC, 	/* 3DFE0 */
+	0x00,  0x80,  0x0F,  0xF8,  0x00,  0x90,  0x00,  0x88,  0x7F,  0xFF,  0x00,  0x00,  0xAA,  0x00,  0x00,  0x01, 	/* 3DFF0 */
+	0xFE,  0x7D,  0x20,  0x11,  0x20,  0x11,  0xFC,  0x11,  0x20,  0x11,  0xFC,  0x7D,  0x20,  0x11,  0x20,  0x11, 	/* 3E000 */
+	0xFE,  0x10,  0x12,  0x14,  0x4A,  0x1B,  0x2A,  0x62,  0xA2,  0x04,  0x82,  0x08,  0x0C,  0xAF,  0x00,  0x80, 	/* 3E010 */
+	0x7C,  0x9E,  0x13,  0xD2,  0x12,  0x52,  0x12,  0x54,  0x13,  0xD8,  0x7E,  0x54,  0x12,  0x54,  0x13,  0xD2, 	/* 3E020 */
+	0x12,  0x12,  0x12,  0x92,  0x1E,  0x52,  0x72,  0x5C,  0x03,  0xB0,  0x06,  0x30,  0x00,  0x10,  0xB0,  0x00, 	/* 3E030 */
+	0x20,  0x00,  0x40,  0x7D,  0xFC,  0x11,  0x24,  0x11,  0x24,  0x11,  0xFC,  0x11,  0x24,  0x7D,  0x24,  0x11, 	/* 3E040 */
+	0xFC,  0x10,  0x52,  0x14,  0x52,  0x18,  0x55,  0x60,  0x9F,  0x01,  0x10,  0x02,  0x11,  0x0C,  0x0F,  0xB3, 	/* 3E050 */
+	0x01,  0x04,  0x00,  0x88,  0x7F,  0xFE,  0x10,  0x20,  0x10,  0x20,  0x11,  0xFC,  0x7C,  0x20,  0x10,  0x20, 	/* 3E060 */
+	0x13,  0xFF,  0x10,  0x80,  0x10,  0x80,  0x1D,  0x7E,  0x72,  0x10,  0x04,  0x10,  0x09,  0xFF,  0x00,  0x00, 	/* 3E070 */
+	0xB6,  0x00,  0x04,  0x00,  0x38,  0x7D,  0xC4,  0x11,  0x22,  0x11,  0x21,  0x11,  0x01,  0x12,  0xFE,  0x7C, 	/* 3E080 */
+	0x20,  0x10,  0x20,  0x17,  0xFF,  0x10,  0x20,  0x16,  0x22,  0x1A,  0x22,  0x62,  0x22,  0x03,  0xFE,  0x00, 	/* 3E090 */
+	0x00,  0xBE,  0x00,  0x88,  0x00,  0x88,  0x7F,  0xFF,  0x10,  0x88,  0x10,  0x00,  0x11,  0xFC,  0x11,  0x24, 	/* 3E0A0 */
+	0x7D,  0x24,  0x11,  0xFC,  0x10,  0x20,  0x11,  0xFC,  0x14,  0x20,  0x19,  0xFC,  0x60,  0x20,  0x07,  0xFF, 	/* 3E0B0 */
+	0x00,  0x00,  0x83,  0x00,  0x20,  0x00,  0x20,  0x7F,  0xFF,  0x10,  0x10,  0x11,  0xD4,  0x11,  0x24,  0x7D, 	/* 3E0C0 */
+	0x54,  0x11,  0x8C,  0x11,  0xFC,  0x10,  0x20,  0x13,  0xFE,  0x1E,  0x32,  0x72,  0x4A,  0x03,  0xF6,  0x02, 	/* 3E0D0 */
+	0x02,  0x02,  0x06,  0x8B,  0x00,  0x20,  0x00,  0x20,  0x7F,  0xFE,  0x10,  0x84,  0x10,  0x48,  0x13,  0xFF, 	/* 3E0E0 */
+	0x7C,  0x00,  0x10,  0xFC,  0x10,  0x84,  0x10,  0xFC,  0x14,  0x84,  0x18,  0xFC,  0x60,  0x20,  0x07,  0xFF, 	/* 3E0F0 */
+	0x00,  0x20,  0x00,  0x20,  0x9E,  0x00,  0x50,  0x02,  0x52,  0x7D,  0x54,  0x10,  0x50,  0x13,  0xFF,  0x10, 	/* 3E100 */
+	0x88,  0x7C,  0x50,  0x13,  0xFE,  0x10,  0x20,  0x11,  0xFC,  0x14,  0x20,  0x1B,  0xFF,  0x60,  0x50,  0x00, 	/* 3E110 */
+	0x88,  0x03,  0x04,  0x0C,  0x03,  0xA2,  0x00,  0x00,  0x07,  0xFF,  0x7C,  0x50,  0x11,  0xDC,  0x11,  0x54, 	/* 3E120 */
+	0x11,  0x54,  0x7D,  0xDC,  0x10,  0x50,  0x11,  0xFE,  0x11,  0x22,  0x15,  0x22,  0x19,  0xFE,  0x61,  0x22, 	/* 3E130 */
+	0x01,  0x22,  0x01,  0xFE,  0x00,  0x00,  0xA7,  0x00,  0x08,  0x1F,  0x08,  0x11,  0x7F,  0x11,  0x22,  0x1F, 	/* 3E140 */
+	0x14,  0x10,  0x7F,  0x2F,  0x08,  0x29,  0x7F,  0x4F,  0x08,  0x00,  0x08,  0x1F,  0xFC,  0x00,  0x80,  0x1F, 	/* 3E150 */
+	0xFC,  0x00,  0x88,  0x7F,  0xFF,  0x00,  0x00,  0xB0,  0x00,  0x00,  0x01,  0xFC,  0x7F,  0x54,  0x11,  0x54, 	/* 3E160 */
+	0x11,  0xFC,  0x10,  0x00,  0x17,  0xFF,  0x7C,  0x00,  0x11,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x14,  0xE2, 	/* 3E170 */
+	0x19,  0x54,  0x76,  0x4C,  0x00,  0x43,  0x00,  0x40,  0xBD,  0x00,  0x00,  0x7F,  0xFF,  0x10,  0x84,  0x3F, 	/* 3E180 */
+	0xFE,  0x6A,  0xAB,  0x24,  0x92,  0x2A,  0xAA,  0x24,  0x92,  0x2A,  0xAE,  0x00,  0x00,  0x3F,  0xFE,  0x00, 	/* 3E190 */
+	0x80,  0x1F,  0xFC,  0x00,  0x90,  0x7F,  0xFF,  0x00,  0x00,  0x8A,  0x00,  0x20,  0x00,  0x78,  0x7D,  0x90, 	/* 3E1A0 */
+	0x13,  0xFE,  0x12,  0x22,  0x12,  0xD2,  0x7D,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x11,  0x04,  0x15,  0xFC, 	/* 3E1B0 */
+	0x18,  0x40,  0x61,  0xFC,  0x06,  0x88,  0x00,  0x70,  0x07,  0x8F,  0x8F,  0x00,  0x90,  0x00,  0x90,  0x7F, 	/* 3E1C0 */
+	0xFF,  0x12,  0x50,  0x11,  0x9E,  0x17,  0xE2,  0x10,  0x1E,  0x7F,  0xD0,  0x12,  0x5E,  0x13,  0xD0,  0x12, 	/* 3E1D0 */
+	0x5E,  0x17,  0xD0,  0x1A,  0x5E,  0x62,  0x50,  0x02,  0x51,  0x02,  0xCF,  0x94,  0x00,  0x00,  0x03,  0xDE, 	/* 3E1E0 */
+	0x7E,  0x52,  0x13,  0xDE,  0x12,  0x52,  0x13,  0xDE,  0x7E,  0x52,  0x13,  0xDE,  0x11,  0x54,  0x12,  0x22, 	/* 3E1F0 */
+	0x14,  0x40,  0x1B,  0xFF,  0x60,  0x88,  0x01,  0xD0,  0x00,  0x78,  0x07,  0x86,  0x9C,  0x00,  0x08,  0x00, 	/* 3E200 */
+	0x70,  0x1F,  0x80,  0x10,  0x10,  0x11,  0x10,  0x11,  0x10,  0x11,  0x10,  0x11,  0x10,  0x11,  0x10,  0x11, 	/* 3E210 */
+	0x08,  0x11,  0x48,  0x11,  0x28,  0x11,  0x28,  0x21,  0xF4,  0x2E,  0x14,  0x40,  0x12,  0xA0,  0x08,  0x04, 	/* 3E220 */
+	0x08,  0x18,  0x7F,  0xE4,  0x08,  0x84,  0x14,  0xA4,  0x12,  0xA4,  0x3D,  0xA4,  0x40,  0xA4,  0x00,  0xA4, 	/* 3E230 */
+	0x7F,  0xA4,  0x10,  0xA4,  0x1E,  0xB4,  0x12,  0xAA,  0x02,  0xAA,  0x02,  0xF6,  0x1D,  0x05,  0xA2,  0x00, 	/* 3E240 */
+	0x02,  0x7F,  0x0C,  0x14,  0x74,  0x7F,  0x54,  0x55,  0x54,  0x55,  0x54,  0x7F,  0x54,  0x00,  0x54,  0x3E, 	/* 3E250 */
+	0x54,  0x00,  0x54,  0x7F,  0x54,  0x08,  0x54,  0x2A,  0x55,  0x2A,  0x9D,  0x48,  0xE3,  0x19,  0x01,  0xA3, 	/* 3E260 */
+	0x10,  0x24,  0x13,  0xC4,  0x7E,  0x3F,  0x2A,  0xAA,  0x2A,  0xAA,  0x2A,  0xAA,  0x7E,  0xBF,  0x12,  0xA4, 	/* 3E270 */
+	0x12,  0xA4,  0x1E,  0xBF,  0x72,  0xA4,  0x12,  0xE4,  0x12,  0xA4,  0x24,  0xA4,  0x27,  0xD4,  0x48,  0x0C, 	/* 3E280 */
+	0xA6,  0x00,  0x00,  0x3F,  0xFE,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x03,  0xF0,  0x02,  0x10,  0x02, 	/* 3E290 */
+	0x10,  0x03,  0x10,  0x02,  0x90,  0x04,  0x90,  0x04,  0x10,  0x04,  0x10,  0x05,  0xD2,  0x0E,  0x12,  0x70, 	/* 3E2A0 */
+	0x0E,  0xA7,  0x00,  0x10,  0x7F,  0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x10,  0x1E,  0xFF,  0x12,  0x10, 	/* 3E2B0 */
+	0x12,  0x10,  0x1A,  0x10,  0x16,  0x10,  0x16,  0x10,  0x12,  0x10,  0x12,  0x10,  0x16,  0x01,  0x19,  0x01, 	/* 3E2C0 */
+	0x60,  0xFF,  0xA9,  0x00,  0x04,  0x7F,  0x18,  0x10,  0xF0,  0x10,  0x10,  0x10,  0x10,  0x1E,  0x10,  0x12, 	/* 3E2D0 */
+	0x10,  0x12,  0xFF,  0x1A,  0x10,  0x16,  0x10,  0x16,  0x10,  0x12,  0x10,  0x12,  0x10,  0x16,  0x11,  0x19, 	/* 3E2E0 */
+	0x01,  0x60,  0xFF,  0xAE,  0x02,  0xE0,  0x02,  0x20,  0x04,  0x90,  0x18,  0x8C,  0x61,  0x43,  0x02,  0x30, 	/* 3E2F0 */
+	0x0F,  0xC8,  0x00,  0x00,  0x7F,  0xFF,  0x04,  0x00,  0x07,  0xF0,  0x05,  0x10,  0x04,  0x90,  0x08,  0x11, 	/* 3E300 */
+	0x0F,  0xD1,  0x78,  0x0F,  0xB0,  0x00,  0x3C,  0x7F,  0x04,  0x10,  0x24,  0x10,  0x24,  0x10,  0x42,  0x1E, 	/* 3E310 */
+	0x42,  0x12,  0xFD,  0x13,  0x24,  0x1A,  0x24,  0x16,  0x24,  0x16,  0x24,  0x12,  0x44,  0x12,  0x84,  0x16, 	/* 3E320 */
+	0x19,  0x19,  0x01,  0x60,  0xFF,  0xB1,  0x00,  0x04,  0x7F,  0x18,  0x11,  0xE0,  0x10,  0x40,  0x10,  0x40, 	/* 3E330 */
+	0x1E,  0x7C,  0x13,  0xC0,  0x12,  0x40,  0x1A,  0x7E,  0x17,  0xC0,  0x16,  0x44,  0x12,  0x44,  0x12,  0x3C, 	/* 3E340 */
+	0x16,  0x01,  0x19,  0x01,  0x60,  0xFF,  0xB2,  0x00,  0x20,  0x7F,  0x24,  0x10,  0x38,  0x11,  0xE0,  0x10, 	/* 3E350 */
+	0x20,  0x1E,  0xA4,  0x12,  0xA4,  0x12,  0xA4,  0x1A,  0xFC,  0x16,  0x20,  0x16,  0x22,  0x12,  0x22,  0x12, 	/* 3E360 */
+	0x1E,  0x16,  0x01,  0x19,  0x01,  0x60,  0xFF,  0xB6,  0x21,  0x00,  0x11,  0xFF,  0x12,  0x20,  0x14,  0x20, 	/* 3E370 */
+	0x7F,  0xA0,  0x12,  0x3C,  0x12,  0x24,  0x12,  0x24,  0x7F,  0xB4,  0x12,  0x2C,  0x12,  0x2C,  0x12,  0x24, 	/* 3E380 */
+	0x12,  0x24,  0x22,  0x25,  0x22,  0x35,  0x42,  0xC3,  0xB7,  0x00,  0x40,  0x3C,  0x7E,  0x00,  0x52,  0x00, 	/* 3E390 */
+	0x94,  0x05,  0x10,  0x18,  0x28,  0x60,  0xC4,  0x03,  0x03,  0x7F,  0xFF,  0x04,  0x00,  0x07,  0xF0,  0x05, 	/* 3E3A0 */
+	0x10,  0x04,  0x90,  0x08,  0x11,  0x0F,  0xD1,  0x78,  0x0F,  0xB8,  0x00,  0x00,  0x7F,  0xFE,  0x10,  0x10, 	/* 3E3B0 */
+	0x10,  0x20,  0x10,  0x7C,  0x1E,  0x44,  0x12,  0x44,  0x12,  0x44,  0x1A,  0x7C,  0x16,  0x44,  0x16,  0x44, 	/* 3E3C0 */
+	0x12,  0x44,  0x12,  0x7C,  0x16,  0x01,  0x19,  0x01,  0x60,  0xFF,  0x83,  0x02,  0x10,  0x3C,  0x12,  0x08, 	/* 3E3D0 */
+	0x52,  0x7F,  0x54,  0x0C,  0x50,  0x1A,  0x98,  0x29,  0x28,  0x48,  0x44,  0x08,  0x82,  0x7F,  0xFF,  0x04, 	/* 3E3E0 */
+	0x00,  0x07,  0xF0,  0x05,  0x10,  0x08,  0x91,  0x0F,  0xD1,  0x7C,  0x0F,  0x84,  0x00,  0x00,  0x7F,  0xFF, 	/* 3E3F0 */
+	0x0A,  0x20,  0x0A,  0x20,  0x3F,  0xA0,  0x2A,  0xBC,  0x2A,  0xA4,  0x3F,  0xA4,  0x04,  0x34,  0x04,  0x2C, 	/* 3E400 */
+	0x3F,  0xAC,  0x04,  0x24,  0x04,  0x24,  0x07,  0xA5,  0x0C,  0x3D,  0x70,  0xC3,  0x85,  0x00,  0x00,  0x7D, 	/* 3E410 */
+	0xFE,  0x21,  0x00,  0x21,  0x7C,  0x21,  0x54,  0x3D,  0x7C,  0x25,  0x54,  0x25,  0x7C,  0x35,  0x10,  0x2D, 	/* 3E420 */
+	0x7C,  0x2D,  0x10,  0x26,  0x10,  0x24,  0xFE,  0x24,  0x01,  0x3A,  0x01,  0x61,  0xFF,  0x8C,  0x00,  0x00, 	/* 3E430 */
+	0x7F,  0xFF,  0x40,  0x20,  0x4E,  0x20,  0x4A,  0x20,  0x4A,  0x3C,  0x4E,  0x24,  0x40,  0x24,  0x5F,  0xA4, 	/* 3E440 */
+	0x56,  0xB4,  0x56,  0xAC,  0x56,  0xA4,  0x5F,  0xA4,  0x40,  0x25,  0x7F,  0xB5,  0x00,  0xC3,  0x8D,  0x04, 	/* 3E450 */
+	0x10,  0x7F,  0xFF,  0x04,  0x10,  0x1F,  0xFC,  0x12,  0x24,  0x1F,  0xFC,  0x00,  0x00,  0x7F,  0xFE,  0x40, 	/* 3E460 */
+	0x02,  0x5F,  0xFA,  0x02,  0x00,  0x03,  0xF0,  0x02,  0x90,  0x04,  0x51,  0x07,  0xD1,  0x7C,  0x0F,  0x8E, 	/* 3E470 */
+	0x04,  0x00,  0x7F,  0xFF,  0x04,  0x20,  0x3F,  0x20,  0x25,  0x20,  0x3F,  0x3C,  0x25,  0x24,  0x3F,  0x24, 	/* 3E480 */
+	0x04,  0xB4,  0x7F,  0xAC,  0x02,  0x64,  0x7F,  0xA4,  0x22,  0x24,  0x12,  0x25,  0x12,  0x35,  0x06,  0xC3, 	/* 3E490 */
+	0x91,  0x22,  0x00,  0x14,  0xFF,  0x7F,  0x20,  0x49,  0x20,  0x49,  0x20,  0x7F,  0x3C,  0x49,  0x24,  0x7F, 	/* 3E4A0 */
+	0x24,  0x00,  0x34,  0x3E,  0x2C,  0x22,  0x24,  0x3E,  0x24,  0x22,  0x24,  0x22,  0x25,  0x3E,  0x75,  0x01, 	/* 3E4B0 */
+	0x83,  0x93,  0x00,  0x08,  0x1F,  0x7F,  0x11,  0x22,  0x1F,  0x14,  0x10,  0xFF,  0x1F,  0x08,  0x19,  0x7F, 	/* 3E4C0 */
+	0x29,  0x08,  0x4F,  0x08,  0x00,  0x08,  0x7F,  0xFF,  0x02,  0x00,  0x03,  0xF0,  0x04,  0x91,  0x07,  0xD1, 	/* 3E4D0 */
+	0x7C,  0x0F,  0x95,  0x00,  0x80,  0x7F,  0xFF,  0x08,  0x44,  0x0A,  0x48,  0x72,  0xFE,  0x15,  0x90,  0x0E, 	/* 3E4E0 */
+	0xFE,  0x72,  0x90,  0x04,  0xFF,  0x08,  0x00,  0x7F,  0xFF,  0x02,  0x00,  0x03,  0xF8,  0x04,  0x89,  0x07, 	/* 3E4F0 */
+	0xE9,  0x78,  0x07,  0x98,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10, 	/* 3E500 */
+	0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10, 	/* 3E510 */
+	0x07,  0xF0,  0x00,  0x00,  0x9A,  0x04,  0x10,  0x1F,  0xFE,  0x04,  0x10,  0x04,  0x10,  0x07,  0xF0,  0x04, 	/* 3E520 */
+	0x10,  0x07,  0xF0,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x11,  0x40,  0x12,  0x44,  0x1C,  0x3C,  0x10, 	/* 3E530 */
+	0x00,  0x1F,  0xFE,  0x00,  0x00,  0x9C,  0x01,  0x44,  0x06,  0x44,  0x38,  0x44,  0x08,  0x44,  0x09,  0xFF, 	/* 3E540 */
+	0x08,  0x44,  0x7F,  0x44,  0x08,  0x44,  0x08,  0x44,  0x08,  0x7C,  0x3E,  0x44,  0x22,  0x44,  0x22,  0x44, 	/* 3E550 */
+	0x22,  0x44,  0x3E,  0x7C,  0x00,  0x00,  0x9E,  0x21,  0x08,  0x11,  0x08,  0x11,  0x10,  0x7F,  0xFE,  0x40, 	/* 3E560 */
+	0x02,  0x4F,  0xF2,  0x08,  0x10,  0x0F,  0xF0,  0x00,  0x00,  0x08,  0x10,  0x7F,  0xFF,  0x08,  0x10,  0x0F, 	/* 3E570 */
+	0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x00,  0x00,  0x9F,  0x00,  0x80,  0x08,  0x80,  0x08,  0x80,  0x08,  0x80, 	/* 3E580 */
+	0x0F,  0xFE,  0x10,  0x80,  0x10,  0x80,  0x20,  0x80,  0x40,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80, 	/* 3E590 */
+	0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0xA3,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x04, 	/* 3E5A0 */
+	0x10,  0x02,  0x10,  0x02,  0x20,  0x1F,  0xFF,  0x12,  0x40,  0x12,  0x40,  0x17,  0xFC,  0x14,  0x40,  0x18, 	/* 3E5B0 */
+	0x40,  0x27,  0xFC,  0x20,  0x40,  0x40,  0x40,  0x1F,  0xFF,  0xA5,  0x08,  0x00,  0x09,  0xFC,  0x29,  0x24, 	/* 3E5C0 */
+	0x29,  0x24,  0x3F,  0xFC,  0x29,  0x24,  0x49,  0x24,  0x09,  0xFC,  0x3E,  0x20,  0x0B,  0xFE,  0x08,  0x22, 	/* 3E5D0 */
+	0x08,  0x42,  0x0E,  0x42,  0x70,  0x82,  0x01,  0x02,  0x06,  0x0C,  0xA6,  0x00,  0x08,  0x7F,  0xA8,  0x04, 	/* 3E5E0 */
+	0x28,  0x04,  0x28,  0x3F,  0x7F,  0x25,  0x48,  0x3F,  0x88,  0x25,  0x08,  0x25,  0x7E,  0x3F,  0x08,  0x14, 	/* 3E5F0 */
+	0x08,  0x28,  0x08,  0x0C,  0xFF,  0x12,  0x00,  0x21,  0x80,  0x40,  0x7F,  0xA8,  0x00,  0x00,  0x1F,  0xFC, 	/* 3E600 */
+	0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC, 	/* 3E610 */
+	0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x20,  0x84,  0x20,  0x84,  0x40,  0x8C,  0xAB,  0x00,  0x88,  0x00, 	/* 3E620 */
+	0x84,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x10, 	/* 3E630 */
+	0x84,  0x10,  0x84,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x8C,  0xAC,  0x00,  0x00, 	/* 3E640 */
+	0x1F,  0xF8,  0x00,  0x10,  0x06,  0x60,  0x01,  0x80,  0x3F,  0xFC,  0x21,  0x04,  0x21,  0x04,  0x3F,  0xFC, 	/* 3E650 */
+	0x21,  0x04,  0x21,  0x04,  0x3F,  0xFC,  0x21,  0x04,  0x21,  0x04,  0x21,  0x04,  0x21,  0x0C,  0xB0,  0x00, 	/* 3E660 */
+	0x00,  0x3F,  0xFE,  0x20,  0x82,  0x20,  0x82,  0x20,  0x82,  0x20,  0x82,  0x20,  0x82,  0x3F,  0xFE,  0x20, 	/* 3E670 */
+	0x82,  0x20,  0x82,  0x20,  0x82,  0x20,  0x82,  0x20,  0x82,  0x20,  0x82,  0x3F,  0xFE,  0x00,  0x00,  0xB1, 	/* 3E680 */
+	0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x3F,  0xFC,  0x21,  0x04,  0x21,  0x04,  0x21,  0x04, 	/* 3E690 */
+	0x3F,  0xFC,  0x21,  0x04,  0x21,  0x04,  0x21,  0x04,  0x21,  0x04,  0x21,  0x04,  0x3F,  0xFC,  0x00,  0x00, 	/* 3E6A0 */
+	0xB2,  0x00,  0x00,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x10,  0x84,  0x10, 	/* 3E6B0 */
+	0x84,  0x10,  0x84,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 3E6C0 */
+	0x80,  0xB3,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84, 	/* 3E6D0 */
+	0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80, 	/* 3E6E0 */
+	0x00,  0x80,  0xB7,  0x00,  0x00,  0x1F,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x1F,  0xF8,  0x11,  0x08,  0x11, 	/* 3E6F0 */
+	0x08,  0x1F,  0xF8,  0x01,  0x00,  0x01,  0x00,  0x3F,  0xFC,  0x01,  0x04,  0x02,  0x04,  0x04,  0x04,  0x18, 	/* 3E700 */
+	0x04,  0x60,  0x18,  0xB8,  0x04,  0x00,  0x04,  0x00,  0x07,  0xFE,  0x08,  0x02,  0x0F,  0xF2,  0x19,  0x12, 	/* 3E710 */
+	0x29,  0x12,  0x49,  0x12,  0x0F,  0xF2,  0x09,  0x12,  0x09,  0x12,  0x09,  0x12,  0x0F,  0xF2,  0x00,  0x02, 	/* 3E720 */
+	0x00,  0x04,  0x00,  0x38,  0xBA,  0x00,  0x00,  0x3F,  0x80,  0x24,  0xFF,  0x24,  0x88,  0x24,  0x88,  0x3F, 	/* 3E730 */
+	0x88,  0x24,  0x88,  0x24,  0x88,  0x24,  0x88,  0x24,  0x88,  0x3F,  0x88,  0x00,  0x08,  0x00,  0x08,  0x00, 	/* 3E740 */
+	0x08,  0x00,  0x08,  0x00,  0x18,  0xBB,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x27,  0xF2, 	/* 3E750 */
+	0x24,  0x92,  0x24,  0x92,  0x24,  0x92,  0x27,  0xF2,  0x24,  0x92,  0x24,  0x92,  0x24,  0x92,  0x27,  0xF2, 	/* 3E760 */
+	0x20,  0x02,  0x3F,  0xFE,  0x00,  0x00,  0xBC,  0x00,  0x00,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84,  0x1F, 	/* 3E770 */
+	0xFC,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x00,  0x00,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x80,  0x00, 	/* 3E780 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x01,  0x80,  0x84,  0x04,  0x04,  0x42,  0x04,  0x21,  0x08,  0x11,  0x08, 	/* 3E790 */
+	0x10,  0x10,  0x00,  0x20,  0x3F,  0xF8,  0x21,  0x08,  0x21,  0x08,  0x21,  0x08,  0x3F,  0xF8,  0x21,  0x08, 	/* 3E7A0 */
+	0x21,  0x08,  0x21,  0x08,  0x3F,  0xF8,  0x00,  0x00,  0x86,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x7F, 	/* 3E7B0 */
+	0x90,  0x00,  0x10,  0x00,  0x10,  0x3F,  0x10,  0x29,  0x10,  0x29,  0x10,  0x29,  0x24,  0x3F,  0x24,  0x29, 	/* 3E7C0 */
+	0x22,  0x29,  0x42,  0x29,  0x4E,  0x3F,  0xF1,  0x00,  0x01,  0x89,  0x00,  0x20,  0x00,  0x20,  0x7C,  0x20, 	/* 3E7D0 */
+	0x55,  0xFE,  0x54,  0x20,  0x54,  0x20,  0x54,  0x20,  0x7F,  0xFF,  0x54,  0x20,  0x54,  0x30,  0x54,  0x50, 	/* 3E7E0 */
+	0x54,  0x48,  0x7C,  0x88,  0x01,  0x04,  0x02,  0x02,  0x0C,  0x01,  0x8A,  0x00,  0x48,  0x00,  0x48,  0x7C, 	/* 3E7F0 */
+	0x48,  0x55,  0xFE,  0x54,  0x48,  0x54,  0x48,  0x54,  0x48,  0x7C,  0x48,  0x54,  0x48,  0x57,  0xFF,  0x54, 	/* 3E800 */
+	0x48,  0x54,  0x88,  0x7C,  0x88,  0x01,  0x08,  0x02,  0x08,  0x04,  0x08,  0x8B,  0x00,  0x40,  0x00,  0x40, 	/* 3E810 */
+	0x7E,  0x40,  0x52,  0x7F,  0x52,  0x44,  0x52,  0x84,  0x52,  0xC4,  0x7F,  0x44,  0x52,  0x48,  0x52,  0x28, 	/* 3E820 */
+	0x52,  0x10,  0x52,  0x18,  0x7E,  0x28,  0x00,  0x44,  0x01,  0x82,  0x06,  0x01,  0x8C,  0x00,  0x00,  0x1F, 	/* 3E830 */
+	0xFC,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x01,  0x40,  0x06, 	/* 3E840 */
+	0x30,  0x1A,  0x1C,  0x62,  0x13,  0x04,  0x10,  0x04,  0x10,  0x08,  0x10,  0x10,  0x10,  0x8D,  0x00,  0x20, 	/* 3E850 */
+	0x00,  0x20,  0x7C,  0x50,  0x54,  0x50,  0x54,  0x88,  0x55,  0x8C,  0x56,  0x8A,  0x7C,  0x89,  0x54,  0x88, 	/* 3E860 */
+	0x54,  0x88,  0x54,  0x88,  0x54,  0x88,  0x7D,  0x08,  0x01,  0x08,  0x02,  0x08,  0x04,  0x08,  0x8F,  0x00, 	/* 3E870 */
+	0x00,  0x1F,  0xF8,  0x10,  0x88,  0x10,  0x88,  0x1F,  0xF8,  0x10,  0x88,  0x10,  0x88,  0x1F,  0xF8,  0x00, 	/* 3E880 */
+	0x00,  0x7F,  0xFF,  0x09,  0x04,  0x08,  0x88,  0x08,  0x50,  0x0B,  0x20,  0x0C,  0x18,  0x30,  0x07,  0x91, 	/* 3E890 */
+	0x08,  0x00,  0x08,  0xFE,  0x08,  0x92,  0x0A,  0x92,  0x0A,  0x92,  0x2A,  0x92,  0x2C,  0x92,  0x28,  0xFE, 	/* 3E8A0 */
+	0x28,  0x92,  0x48,  0x92,  0x0C,  0x92,  0x0A,  0x92,  0x11,  0x92,  0x10,  0x92,  0x20,  0xFE,  0x40,  0x00, 	/* 3E8B0 */
+	0x94,  0x00,  0x20,  0x7C,  0x22,  0x55,  0x22,  0x54,  0xA4,  0x54,  0xA8,  0x54,  0x20,  0x7D,  0xFE,  0x54, 	/* 3E8C0 */
+	0x20,  0x54,  0x20,  0x54,  0x20,  0x57,  0xFF,  0x54,  0x20,  0x7C,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00, 	/* 3E8D0 */
+	0x20,  0x99,  0x06,  0x00,  0x38,  0xFE,  0x20,  0x12,  0x24,  0x12,  0x22,  0x12,  0x26,  0x22,  0x39,  0x42, 	/* 3E8E0 */
+	0x60,  0x8C,  0x1F,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x1F,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x1F,  0xF8, 	/* 3E8F0 */
+	0x00,  0x00,  0x9A,  0x01,  0x00,  0x01,  0x20,  0x02,  0x18,  0x1F,  0xF4,  0x01,  0x00,  0x7F,  0xFF,  0x02, 	/* 3E900 */
+	0x20,  0x04,  0x10,  0x1F,  0xFC,  0x68,  0x8B,  0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x0F, 	/* 3E910 */
+	0xF8,  0x00,  0x00,  0x9B,  0x00,  0x20,  0x00,  0x20,  0x7C,  0x50,  0x54,  0x48,  0x54,  0x84,  0x55,  0x12, 	/* 3E920 */
+	0x56,  0x21,  0x7C,  0x40,  0x55,  0x88,  0x54,  0x10,  0x54,  0x62,  0x55,  0x84,  0x7C,  0x08,  0x00,  0x10, 	/* 3E930 */
+	0x00,  0x60,  0x03,  0x80,  0x9C,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0x40,  0x02,  0x50,  0x1C, 	/* 3E940 */
+	0x88,  0x03,  0x3C,  0x7F,  0xC4,  0x00,  0x02,  0x1F,  0xFA,  0x10,  0x88,  0x1F,  0xF8,  0x10,  0x88,  0x10, 	/* 3E950 */
+	0x88,  0x1F,  0xF8,  0x00,  0x00,  0x9D,  0x08,  0x20,  0x08,  0x20,  0x08,  0x3C,  0x7F,  0xA4,  0x00,  0x24, 	/* 3E960 */
+	0x3F,  0x44,  0x29,  0x44,  0x29,  0x88,  0x29,  0x08,  0x3F,  0x08,  0x29,  0x14,  0x29,  0x14,  0x29,  0x22, 	/* 3E970 */
+	0x3F,  0x42,  0x00,  0x81,  0x01,  0x01,  0xA0,  0x00,  0x80,  0x01,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x0F, 	/* 3E980 */
+	0xF0,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x00,  0x00,  0x3F,  0xFC,  0x20,  0x84,  0x3F,  0xFC,  0x20, 	/* 3E990 */
+	0x84,  0x20,  0x84,  0x3F,  0xFC,  0x00,  0x00,  0xA2,  0x00,  0x00,  0x1F,  0xFC,  0x10,  0x84,  0x1F,  0xFC, 	/* 3E9A0 */
+	0x10,  0x84,  0x1F,  0xFC,  0x08,  0x88,  0x08,  0x88,  0x7F,  0xFF,  0x08,  0x88,  0x08,  0x88,  0x3F,  0xFE, 	/* 3E9B0 */
+	0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0xA4,  0x00,  0x20,  0x00,  0x20,  0x7D,  0xFC,  0x54, 	/* 3E9C0 */
+	0x20,  0x54,  0x20,  0x54,  0x20,  0x57,  0xFF,  0x7C,  0x08,  0x54,  0x08,  0x57,  0xFF,  0x54,  0x08,  0x54, 	/* 3E9D0 */
+	0x88,  0x7C,  0x48,  0x00,  0x48,  0x00,  0x08,  0x00,  0x18,  0xA5,  0x00,  0x40,  0x00,  0x40,  0x7C,  0x7C, 	/* 3E9E0 */
+	0x54,  0x84,  0x54,  0x88,  0x55,  0x50,  0x56,  0x30,  0x7C,  0x48,  0x54,  0x84,  0x55,  0x02,  0x56,  0xFD, 	/* 3E9F0 */
+	0x54,  0x84,  0x54,  0x84,  0x7C,  0x84,  0x00,  0xFC,  0x00,  0x00,  0xA6,  0x00,  0x20,  0x00,  0x20,  0x7D, 	/* 3EA00 */
+	0xFC,  0x54,  0x20,  0x54,  0x20,  0x54,  0x20,  0x57,  0xFF,  0x7C,  0x20,  0x54,  0x20,  0x54,  0x20,  0x55, 	/* 3EA10 */
+	0xFC,  0x54,  0x20,  0x7C,  0x20,  0x44,  0x20,  0x03,  0xFF,  0x00,  0x00,  0xA7,  0x00,  0x00,  0x1F,  0xFC, 	/* 3EA20 */
+	0x10,  0x84,  0x1F,  0xFC,  0x10,  0x84,  0x1F,  0xFC,  0x01,  0x00,  0x03,  0xF8,  0x0E,  0x10,  0x31,  0xE0, 	/* 3EA30 */
+	0x06,  0x1C,  0x7F,  0xFB,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0xA9,  0x00,  0x20,  0x00, 	/* 3EA40 */
+	0x20,  0x7C,  0x20,  0x57,  0xFF,  0x54,  0x20,  0x54,  0x22,  0x54,  0x52,  0x7C,  0x54,  0x54,  0x94,  0x55, 	/* 3EA50 */
+	0x98,  0x56,  0x90,  0x54,  0x88,  0x7C,  0x88,  0x00,  0xB4,  0x00,  0xC2,  0x03,  0x01,  0xAA,  0x00,  0x08, 	/* 3EA60 */
+	0x00,  0x70,  0x1F,  0x84,  0x08,  0x88,  0x04,  0x90,  0x7F,  0xFF,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C, 	/* 3EA70 */
+	0x6F,  0xFB,  0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x00,  0xAB,  0x00, 	/* 3EA80 */
+	0x80,  0x1F,  0xFC,  0x00,  0x84,  0x7F,  0xFF,  0x00,  0x84,  0x1F,  0xFC,  0x00,  0x80,  0x1F,  0xFE,  0x00, 	/* 3EA90 */
+	0x80,  0x7F,  0xFF,  0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x7F,  0xFF,  0x00,  0x00,  0xAD, 	/* 3EAA0 */
+	0x00,  0x10,  0x00,  0x10,  0x7C,  0x28,  0x54,  0x28,  0x54,  0x44,  0x54,  0x82,  0x55,  0x7D,  0x7E,  0x10, 	/* 3EAB0 */
+	0x54,  0x10,  0x55,  0xFF,  0x54,  0x10,  0x54,  0x94,  0x7C,  0x92,  0x01,  0x11,  0x02,  0x10,  0x00,  0x30, 	/* 3EAC0 */
+	0xB0,  0x00,  0x00,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84,  0x1F, 	/* 3EAD0 */
+	0xFC,  0x02,  0x20,  0x1F,  0xFC,  0x02,  0x20,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x30,  0x0C,  0x0C,  0x30, 	/* 3EAE0 */
+	0x02,  0xB3,  0x00,  0x00,  0x1F,  0xF8,  0x11,  0x08,  0x1F,  0xF8,  0x11,  0x08,  0x1F,  0xF8,  0x00,  0x00, 	/* 3EAF0 */
+	0x7F,  0xFE,  0x40,  0x02,  0x4F,  0xF2,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10, 	/* 3EB00 */
+	0x7F,  0xFE,  0xB4,  0x00,  0x20,  0x7C,  0x20,  0x55,  0xFE,  0x54,  0x20,  0x54,  0xFC,  0x54,  0x20,  0x7F, 	/* 3EB10 */
+	0xFF,  0x54,  0x40,  0x54,  0x44,  0x57,  0xFF,  0x54,  0x84,  0x7C,  0x84,  0x01,  0x44,  0x02,  0x44,  0x04, 	/* 3EB20 */
+	0x04,  0x00,  0x0C,  0xB6,  0x11,  0x10,  0x09,  0x10,  0x09,  0x20,  0x7F,  0xFE,  0x40,  0x02,  0x4F,  0xE2, 	/* 3EB30 */
+	0x08,  0x20,  0x0F,  0xE0,  0x00,  0x00,  0x3F,  0xF8,  0x21,  0x08,  0x3F,  0xF8,  0x21,  0x08,  0x21,  0x08, 	/* 3EB40 */
+	0x3F,  0xF8,  0x00,  0x00,  0xB7,  0x00,  0x00,  0x03,  0xDE,  0x7C,  0x42,  0x55,  0x4A,  0x54,  0x84,  0x54, 	/* 3EB50 */
+	0xC6,  0x55,  0x4A,  0x7E,  0x10,  0x54,  0x00,  0x57,  0xFE,  0x54,  0x52,  0x55,  0x4A,  0x7C,  0x84,  0x01, 	/* 3EB60 */
+	0x4C,  0x02,  0x52,  0x0C,  0x21,  0xB8,  0x00,  0x20,  0x00,  0x20,  0x7F,  0xFE,  0x54,  0x30,  0x54,  0x48, 	/* 3EB70 */
+	0x55,  0x84,  0x54,  0x00,  0x7F,  0xFF,  0x54,  0x04,  0x55,  0xE4,  0x55,  0x24,  0x55,  0x24,  0x7D,  0x24, 	/* 3EB80 */
+	0x01,  0xE4,  0x00,  0x04,  0x00,  0x0C,  0xBF,  0x08,  0x90,  0x0A,  0x94,  0x32,  0xE4,  0x0C,  0x98,  0x04, 	/* 3EB90 */
+	0x88,  0x0A,  0x94,  0x3E,  0xBE,  0x01,  0x52,  0x7F,  0xFF,  0x1F,  0x48,  0x15,  0x48,  0x1F,  0x30,  0x15, 	/* 3EBA0 */
+	0x12,  0x15,  0x2A,  0x1F,  0x46,  0x01,  0x82,  0x82,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88, 	/* 3EBB0 */
+	0x3F,  0xFE,  0x0C,  0x18,  0x03,  0x60,  0x1C,  0x1C,  0x7F,  0xFF,  0x20,  0x02,  0x27,  0xF2,  0x04,  0x10, 	/* 3EBC0 */
+	0x07,  0xF0,  0x04,  0x10,  0x7F,  0xFF,  0x00,  0x00,  0x86,  0x00,  0x00,  0x7D,  0xFF,  0x04,  0x92,  0x04, 	/* 3EBD0 */
+	0xFE,  0x3C,  0x92,  0x20,  0xFE,  0x20,  0x00,  0x3D,  0xFF,  0x04,  0xFE,  0x14,  0x92,  0x7C,  0xFE,  0x14, 	/* 3EBE0 */
+	0x92,  0x1C,  0xFE,  0x64,  0x00,  0x0B,  0xFF,  0x30,  0x00,  0x87,  0x00,  0x20,  0x03,  0xFE,  0x7C,  0x20, 	/* 3EBF0 */
+	0x54,  0xFC,  0x54,  0x00,  0x57,  0xFF,  0x54,  0x02,  0x7C,  0xF8,  0x54,  0x20,  0x57,  0xFF,  0x54,  0x04, 	/* 3EC00 */
+	0x55,  0xFF,  0x7D,  0x64,  0x01,  0x54,  0x01,  0xC4,  0x00,  0x0C,  0x89,  0x07,  0xF0,  0x04,  0x90,  0x07, 	/* 3EC10 */
+	0xF0,  0x04,  0x90,  0x3F,  0xFE,  0x2A,  0x2A,  0x3E,  0x3E,  0x2A,  0x2A,  0x3E,  0xBE,  0x00,  0x80,  0x3F, 	/* 3EC20 */
+	0xFE,  0x21,  0x02,  0x03,  0xF8,  0x0D,  0x10,  0x00,  0xA0,  0x7F,  0xFF,  0x8A,  0x07,  0xF0,  0x04,  0x90, 	/* 3EC30 */
+	0x07,  0xF0,  0x04,  0x90,  0x3F,  0xFE,  0x29,  0x52,  0x3F,  0x7E,  0x29,  0x52,  0x7F,  0xFF,  0x40,  0x01, 	/* 3EC40 */
+	0x47,  0xF1,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x7F,  0xFF,  0x00,  0x00,  0x8B,  0x00,  0x00,  0x7F, 	/* 3EC50 */
+	0xFE,  0x00,  0x82,  0x00,  0x84,  0x00,  0x88,  0x08,  0x80,  0x08,  0x80,  0x08,  0xFC,  0x08,  0x80,  0x08, 	/* 3EC60 */
+	0x80,  0x08,  0x80,  0x08,  0x80,  0x14,  0x80,  0x12,  0x80,  0x21,  0x80,  0x40,  0x7F,  0x8E,  0x00,  0x10, 	/* 3EC70 */
+	0x3F,  0x10,  0x01,  0xFF,  0x02,  0x10,  0x04,  0x10,  0x14,  0xFE,  0x14,  0x92,  0x17,  0x92,  0x14,  0xFE, 	/* 3EC80 */
+	0x14,  0x10,  0x14,  0x38,  0x14,  0x54,  0x17,  0x92,  0x1D,  0x11,  0x60,  0x10,  0x00,  0x10,  0x8F,  0x00, 	/* 3EC90 */
+	0x10,  0x3F,  0x10,  0x01,  0xFF,  0x02,  0x10,  0x04,  0x28,  0x14,  0x46,  0x14,  0xFD,  0x17,  0x00,  0x14, 	/* 3ECA0 */
+	0x54,  0x14,  0x54,  0x14,  0x54,  0x14,  0x54,  0x17,  0x54,  0x1C,  0x95,  0x60,  0x85,  0x01,  0x03,  0x91, 	/* 3ECB0 */
+	0x20,  0x00,  0x22,  0x7E,  0x3C,  0x24,  0x21,  0x18,  0x21,  0x08,  0x1F,  0xFF,  0x10,  0x12,  0x1F,  0x14, 	/* 3ECC0 */
+	0x24,  0x50,  0x44,  0x5E,  0x3F,  0xD0,  0x04,  0x50,  0x0A,  0x70,  0x09,  0x90,  0x10,  0x8C,  0x21,  0x03, 	/* 3ECD0 */
+	0x94,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48,  0x00,  0x28,  0x00,  0x28,  0x00,  0x0B,  0xFF,  0x08, 	/* 3ECE0 */
+	0x20,  0x18,  0x20,  0x28,  0x20,  0x48,  0x20,  0x10,  0x20,  0x10,  0x20,  0x20,  0x20,  0x40,  0x20,  0x00, 	/* 3ECF0 */
+	0x60,  0x9A,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48,  0x40,  0x28,  0x40,  0x28,  0x78,  0x08,  0x88, 	/* 3ED00 */
+	0x08,  0x88,  0x19,  0x10,  0x2A,  0x10,  0x48,  0x20,  0x10,  0x30,  0x10,  0x48,  0x20,  0x84,  0x43,  0x02, 	/* 3ED10 */
+	0x0C,  0x02,  0x9D,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48,  0x00,  0x28,  0x20,  0x28,  0x20,  0x08, 	/* 3ED20 */
+	0x20,  0x0A,  0x22,  0x1A,  0x22,  0x2A,  0x22,  0x4A,  0x22,  0x12,  0x22,  0x12,  0x22,  0x22,  0x22,  0x43, 	/* 3ED30 */
+	0xFE,  0x00,  0x00,  0xA3,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48,  0x00,  0x28,  0x48,  0x28,  0x44, 	/* 3ED40 */
+	0x08,  0x44,  0x0F,  0xFF,  0x18,  0x40,  0x28,  0x40,  0x48,  0x60,  0x10,  0xA0,  0x10,  0xA1,  0x21,  0x21, 	/* 3ED50 */
+	0x46,  0x21,  0x18,  0x1F,  0xA5,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48,  0x20,  0x28,  0x20,  0x28, 	/* 3ED60 */
+	0x50,  0x08,  0x88,  0x09,  0x04,  0x1E,  0x8B,  0x28,  0x88,  0x48,  0x88,  0x10,  0x88,  0x11,  0x08,  0x21, 	/* 3ED70 */
+	0x08,  0x42,  0x08,  0x04,  0x08,  0xAB,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48,  0x00,  0x29,  0xF0, 	/* 3ED80 */
+	0x29,  0x12,  0x09,  0x12,  0x09,  0x0E,  0x1A,  0x00,  0x2F,  0xF8,  0x48,  0x88,  0x10,  0x90,  0x10,  0x60, 	/* 3ED90 */
+	0x20,  0x50,  0x41,  0x88,  0x0E,  0x06,  0xB1,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48,  0x80,  0x28, 	/* 3EDA0 */
+	0x80,  0x29,  0xFC,  0x09,  0x04,  0x0B,  0xE4,  0x1D,  0x24,  0x29,  0x24,  0x49,  0xE4,  0x11,  0x08,  0x11, 	/* 3EDB0 */
+	0x30,  0x21,  0x02,  0x41,  0x02,  0x00,  0xFE,  0xB2,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48,  0x20, 	/* 3EDC0 */
+	0x28,  0x20,  0x2B,  0xFE,  0x0A,  0x22,  0x0A,  0x24,  0x1B,  0xF8,  0x2A,  0x88,  0x4A,  0x88,  0x12,  0x50, 	/* 3EDD0 */
+	0x14,  0x20,  0x24,  0x50,  0x49,  0x8C,  0x16,  0x03,  0xB3,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48, 	/* 3EDE0 */
+	0x00,  0x29,  0x08,  0x29,  0x08,  0x0F,  0xFF,  0x09,  0x08,  0x19,  0x08,  0x29,  0x08,  0x49,  0xF8,  0x11, 	/* 3EDF0 */
+	0x08,  0x11,  0x08,  0x21,  0x08,  0x41,  0xF8,  0x00,  0x00,  0xB5,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF, 	/* 3EE00 */
+	0x48,  0x00,  0x28,  0x90,  0x28,  0x90,  0x0A,  0x92,  0x0A,  0x92,  0x1A,  0xF4,  0x2A,  0x98,  0x4A,  0x90, 	/* 3EE10 */
+	0x12,  0x90,  0x12,  0x90,  0x22,  0xF1,  0x43,  0x11,  0x0C,  0x0F,  0xB8,  0x00,  0x40,  0x00,  0x40,  0x0F, 	/* 3EE20 */
+	0xFF,  0x48,  0x00,  0x28,  0x00,  0x29,  0xF8,  0x09,  0x08,  0x09,  0x08,  0x19,  0xF8,  0x29,  0x08,  0x49, 	/* 3EE30 */
+	0x08,  0x11,  0x08,  0x11,  0xF8,  0x20,  0x00,  0x5F,  0xFF,  0x00,  0x00,  0xB9,  0x00,  0x40,  0x00,  0x40, 	/* 3EE40 */
+	0x0F,  0xFF,  0x08,  0x40,  0x48,  0x60,  0x28,  0x90,  0x29,  0x0C,  0x0E,  0x23,  0x18,  0xC8,  0x2B,  0x10, 	/* 3EE50 */
+	0x48,  0x20,  0x10,  0xC4,  0x13,  0x08,  0x20,  0x30,  0x40,  0xC0,  0x07,  0x00,  0xBC,  0x00,  0x40,  0x00, 	/* 3EE60 */
+	0x40,  0x0F,  0xFF,  0x48,  0x80,  0x28,  0xF8,  0x29,  0x08,  0x0E,  0xD0,  0x08,  0x60,  0x18,  0x90,  0x29, 	/* 3EE70 */
+	0x0C,  0x4E,  0x63,  0x10,  0x10,  0x10,  0x00,  0x21,  0xE0,  0x40,  0x18,  0x00,  0x04,  0xBD,  0x00,  0x80, 	/* 3EE80 */
+	0x00,  0x80,  0x0F,  0xFF,  0x48,  0x00,  0x28,  0x00,  0x29,  0xF8,  0x09,  0x08,  0x09,  0x08,  0x19,  0xF8, 	/* 3EE90 */
+	0x29,  0x08,  0x49,  0x08,  0x11,  0xF8,  0x11,  0x08,  0x21,  0x08,  0x5F,  0xFF,  0x00,  0x00,  0xBE,  0x00, 	/* 3EEA0 */
+	0x20,  0x00,  0x20,  0x0F,  0xFF,  0x48,  0x80,  0x28,  0x80,  0x29,  0xFE,  0x09,  0x20,  0x0A,  0x20,  0x18, 	/* 3EEB0 */
+	0x20,  0x2F,  0xFF,  0x48,  0x30,  0x10,  0x50,  0x10,  0x48,  0x20,  0x84,  0x43,  0x02,  0x0C,  0x01,  0x82, 	/* 3EEC0 */
+	0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x49,  0x00,  0x29,  0x00,  0x29,  0x1E,  0x0F,  0xD2,  0x09,  0x52, 	/* 3EED0 */
+	0x19,  0x52,  0x29,  0x52,  0x49,  0x52,  0x12,  0x52,  0x12,  0x52,  0x24,  0x5E,  0x48,  0x40,  0x11,  0x80, 	/* 3EEE0 */
+	0x83,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48,  0x20,  0x28,  0x20,  0x2F,  0xFF,  0x08,  0x40,  0x08, 	/* 3EEF0 */
+	0x40,  0x18,  0x90,  0x2B,  0x10,  0x48,  0xA0,  0x10,  0x48,  0x10,  0x84,  0x21,  0x3C,  0x4F,  0xC2,  0x00, 	/* 3EF00 */
+	0x02,  0x85,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48,  0x00,  0x28,  0x00,  0x2F,  0xFF,  0x08,  0x20, 	/* 3EF10 */
+	0x08,  0x20,  0x1B,  0xFE,  0x2A,  0x22,  0x4A,  0x62,  0x12,  0x52,  0x12,  0x8A,  0x23,  0x0A,  0x42,  0x02, 	/* 3EF20 */
+	0x02,  0x06,  0x87,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48,  0x00,  0x28,  0x00,  0x2F,  0xFE,  0x08, 	/* 3EF30 */
+	0x20,  0x08,  0x20,  0x19,  0x20,  0x29,  0x3C,  0x49,  0x20,  0x11,  0x20,  0x11,  0x20,  0x21,  0x20,  0x5F, 	/* 3EF40 */
+	0xFF,  0x00,  0x00,  0x8A,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48,  0x20,  0x28,  0x20,  0x28,  0x50, 	/* 3EF50 */
+	0x09,  0x8C,  0x0E,  0x03,  0x1B,  0xFE,  0x28,  0x20,  0x48,  0x20,  0x13,  0xFE,  0x10,  0x20,  0x20,  0x20, 	/* 3EF60 */
+	0x4F,  0xFF,  0x00,  0x00,  0x8D,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48,  0x40,  0x2F,  0xFF,  0x28, 	/* 3EF70 */
+	0x40,  0x0F,  0xFC,  0x08,  0x44,  0x1B,  0xFC,  0x2A,  0x40,  0x4B,  0xFE,  0x10,  0x42,  0x10,  0xAC,  0x21, 	/* 3EF80 */
+	0x10,  0x46,  0x0C,  0x18,  0x03,  0x92,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x49,  0x08,  0x28,  0x88, 	/* 3EF90 */
+	0x28,  0x90,  0x0F,  0xFE,  0x08,  0x20,  0x18,  0x20,  0x2B,  0xFC,  0x48,  0x20,  0x10,  0x20,  0x17,  0xFF, 	/* 3EFA0 */
+	0x20,  0x20,  0x40,  0x20,  0x00,  0x20,  0x94,  0x00,  0x20,  0x00,  0x20,  0x0F,  0xFF,  0x08,  0x20,  0x49, 	/* 3EFB0 */
+	0xFC,  0x28,  0x20,  0x28,  0x20,  0x0F,  0xFF,  0x08,  0x04,  0x18,  0x04,  0x2B,  0xFF,  0x49,  0x04,  0x10, 	/* 3EFC0 */
+	0x84,  0x10,  0x84,  0x20,  0x04,  0x40,  0x0C,  0x95,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48,  0x00, 	/* 3EFD0 */
+	0x29,  0xF8,  0x29,  0x08,  0x09,  0x08,  0x09,  0xF8,  0x19,  0x08,  0x29,  0x08,  0x49,  0xFA,  0x09,  0x44, 	/* 3EFE0 */
+	0x11,  0x28,  0x11,  0x10,  0x23,  0xCC,  0x4C,  0x03,  0x98,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48, 	/* 3EFF0 */
+	0x00,  0x2F,  0xFE,  0x28,  0x00,  0x0B,  0xFC,  0x0A,  0x04,  0x1A,  0x04,  0x2A,  0x04,  0x4B,  0xFC,  0x11, 	/* 3F000 */
+	0x08,  0x10,  0x88,  0x20,  0x90,  0x5F,  0xFF,  0x00,  0x00,  0x99,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF, 	/* 3F010 */
+	0x48,  0x00,  0x2F,  0xFE,  0x29,  0x24,  0x0A,  0x48,  0x0C,  0x90,  0x1A,  0x48,  0x29,  0x24,  0x48,  0x00, 	/* 3F020 */
+	0x13,  0xFE,  0x10,  0x20,  0x20,  0x20,  0x4F,  0xFF,  0x00,  0x00,  0x9B,  0x00,  0x40,  0x00,  0x40,  0x0F, 	/* 3F030 */
+	0xFF,  0x48,  0x00,  0x2B,  0xFC,  0x28,  0x88,  0x08,  0x50,  0x0B,  0xFE,  0x1A,  0x22,  0x2B,  0xFE,  0x4A, 	/* 3F040 */
+	0x22,  0x12,  0x22,  0x13,  0xFE,  0x22,  0x22,  0x42,  0x22,  0x02,  0x26,  0x9E,  0x00,  0x40,  0x00,  0x40, 	/* 3F050 */
+	0x0F,  0xFF,  0x48,  0x00,  0x2F,  0xFE,  0x28,  0x20,  0x08,  0x70,  0x09,  0xAC,  0x1E,  0x22,  0x28,  0x20, 	/* 3F060 */
+	0x48,  0x20,  0x13,  0xFC,  0x12,  0x04,  0x22,  0x04,  0x43,  0xFC,  0x00,  0x00,  0xA2,  0x00,  0x40,  0x00, 	/* 3F070 */
+	0x40,  0x0F,  0xFF,  0x48,  0x00,  0x28,  0x42,  0x2F,  0x92,  0x09,  0x12,  0x09,  0x12,  0x1F,  0xD2,  0x29, 	/* 3F080 */
+	0x12,  0x4B,  0x92,  0x13,  0x52,  0x15,  0x12,  0x29,  0x02,  0x41,  0x02,  0x01,  0x06,  0xA3,  0x00,  0x80, 	/* 3F090 */
+	0x00,  0x80,  0x0F,  0xFF,  0x48,  0x40,  0x28,  0x40,  0x2F,  0xFE,  0x08,  0x40,  0x08,  0x40,  0x1B,  0xFC, 	/* 3F0A0 */
+	0x28,  0x80,  0x48,  0x40,  0x11,  0x24,  0x15,  0x22,  0x25,  0x09,  0x49,  0x09,  0x10,  0xF8,  0xA9,  0x00, 	/* 3F0B0 */
+	0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48,  0x40,  0x2B,  0xFC,  0x2A,  0x44,  0x0B,  0xFC,  0x0A,  0x44,  0x1B, 	/* 3F0C0 */
+	0xFC,  0x28,  0x40,  0x4F,  0xF8,  0x11,  0x08,  0x10,  0x90,  0x20,  0x60,  0x41,  0x98,  0x1E,  0x07,  0xB0, 	/* 3F0D0 */
+	0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48,  0x24,  0x29,  0x24,  0x29,  0x28,  0x0A,  0x20,  0x08,  0x50, 	/* 3F0E0 */
+	0x18,  0x88,  0x2B,  0x26,  0x48,  0x24,  0x11,  0x24,  0x11,  0x28,  0x22,  0x50,  0x41,  0x88,  0x06,  0x07, 	/* 3F0F0 */
+	0xB2,  0x00,  0x20,  0x00,  0x20,  0x0F,  0xFF,  0x48,  0x00,  0x28,  0x88,  0x28,  0x88,  0x0F,  0xFF,  0x08, 	/* 3F100 */
+	0x88,  0x1A,  0xAA,  0x2A,  0xAA,  0x4A,  0xAA,  0x12,  0xAA,  0x12,  0xAA,  0x24,  0xAB,  0x48,  0xA8,  0x00, 	/* 3F110 */
+	0x88,  0xB3,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48,  0x00,  0x29,  0x08,  0x29,  0x08,  0x0F,  0xFF, 	/* 3F120 */
+	0x09,  0x08,  0x19,  0x08,  0x2B,  0x9C,  0x4B,  0x5C,  0x15,  0x2A,  0x15,  0x2A,  0x29,  0x49,  0x41,  0x08, 	/* 3F130 */
+	0x01,  0x08,  0xB4,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x4A,  0x00,  0x2A,  0x00,  0x2B,  0xDE,  0x2D, 	/* 3F140 */
+	0x12,  0x0D,  0x12,  0x19,  0x12,  0x2F,  0xF2,  0x49,  0x12,  0x12,  0x92,  0x12,  0x92,  0x24,  0x5E,  0x44, 	/* 3F150 */
+	0x00,  0x08,  0x00,  0xBA,  0x00,  0x20,  0x00,  0x20,  0x0F,  0xFF,  0x48,  0x20,  0x28,  0x40,  0x2B,  0xFC, 	/* 3F160 */
+	0x0A,  0x44,  0x0B,  0xFC,  0x1A,  0x44,  0x2B,  0xFC,  0x48,  0x90,  0x11,  0x10,  0x1F,  0xFF,  0x20,  0x10, 	/* 3F170 */
+	0x40,  0x10,  0x00,  0x10,  0xBC,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48,  0x00,  0x2B,  0xFE,  0x2A, 	/* 3F180 */
+	0x22,  0x0A,  0x22,  0x0B,  0xFE,  0x1A,  0x22,  0x2A,  0xFA,  0x4A,  0x8A,  0x12,  0x8A,  0x12,  0xFA,  0x22, 	/* 3F190 */
+	0x02,  0x43,  0xFE,  0x00,  0x00,  0xBE,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48,  0x00,  0x2B,  0xBF, 	/* 3F1A0 */
+	0x2A,  0x82,  0x0A,  0x82,  0x0B,  0x3A,  0x1A,  0xAA,  0x2A,  0xAA,  0x4A,  0xAA,  0x12,  0xBA,  0x13,  0x82, 	/* 3F1B0 */
+	0x22,  0x02,  0x42,  0x02,  0x02,  0x06,  0xBF,  0x00,  0x80,  0x00,  0x80,  0x0F,  0xFF,  0x48,  0x04,  0x29, 	/* 3F1C0 */
+	0xF8,  0x28,  0x20,  0x0F,  0xFF,  0x09,  0xAC,  0x1E,  0x23,  0x28,  0x60,  0x4F,  0xFF,  0x18,  0x88,  0x11, 	/* 3F1D0 */
+	0xC8,  0x20,  0x30,  0x40,  0xC8,  0x07,  0x04,  0x81,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48,  0x20, 	/* 3F1E0 */
+	0x28,  0x20,  0x2F,  0xFE,  0x09,  0x08,  0x09,  0x08,  0x19,  0x8C,  0x2A,  0x52,  0x4C,  0x20,  0x17,  0xFF, 	/* 3F1F0 */
+	0x10,  0x20,  0x20,  0x20,  0x40,  0x20,  0x00,  0x20,  0x89,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48, 	/* 3F200 */
+	0x20,  0x28,  0x50,  0x29,  0x8C,  0x0E,  0x03,  0x09,  0xFC,  0x18,  0x0A,  0x2B,  0xCA,  0x4B,  0x52,  0x12, 	/* 3F210 */
+	0xD4,  0x13,  0x54,  0x22,  0xCA,  0x42,  0x4A,  0x02,  0xCA,  0x8B,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF, 	/* 3F220 */
+	0x48,  0x00,  0x2B,  0xFC,  0x2A,  0x14,  0x0B,  0xE4,  0x0A,  0x44,  0x1B,  0xF4,  0x2B,  0x54,  0x4B,  0x54, 	/* 3F230 */
+	0x13,  0xF4,  0x12,  0x55,  0x24,  0x73,  0x47,  0x8B,  0x08,  0x09,  0x8D,  0x00,  0x40,  0x00,  0x40,  0x0F, 	/* 3F240 */
+	0xFF,  0x48,  0x00,  0x29,  0xF8,  0x29,  0x08,  0x09,  0xF8,  0x09,  0x08,  0x19,  0xF8,  0x28,  0x00,  0x4F, 	/* 3F250 */
+	0xFF,  0x11,  0x00,  0x13,  0xFE,  0x24,  0x92,  0x49,  0x22,  0x02,  0x4C,  0x9F,  0x00,  0x40,  0x00,  0x40, 	/* 3F260 */
+	0x0F,  0xFF,  0x48,  0x00,  0x2B,  0xF8,  0x2A,  0x48,  0x0A,  0x48,  0x0A,  0xA8,  0x1B,  0xF8,  0x28,  0x00, 	/* 3F270 */
+	0x4F,  0xFC,  0x14,  0xA4,  0x14,  0xA4,  0x24,  0xA4,  0x5F,  0xFF,  0x00,  0x00,  0xA0,  0x00,  0x40,  0x00, 	/* 3F280 */
+	0x40,  0x0F,  0xFF,  0x48,  0x00,  0x2B,  0xAE,  0x28,  0x20,  0x0B,  0xDE,  0x08,  0x88,  0x19,  0x04,  0x2B, 	/* 3F290 */
+	0xFE,  0x4D,  0x05,  0x11,  0xFC,  0x11,  0x04,  0x21,  0xFC,  0x41,  0x04,  0x01,  0x0C,  0xA1,  0x00,  0x40, 	/* 3F2A0 */
+	0x00,  0x40,  0x0F,  0xFF,  0x48,  0x20,  0x28,  0x50,  0x28,  0xF8,  0x09,  0x04,  0x0B,  0xFA,  0x1D,  0x09, 	/* 3F2B0 */
+	0x29,  0xF8,  0x49,  0x08,  0x13,  0xF8,  0x12,  0x00,  0x25,  0xFC,  0x49,  0x04,  0x11,  0xFC,  0xA2,  0x00, 	/* 3F2C0 */
+	0x40,  0x00,  0x40,  0x0F,  0xFF,  0x49,  0x00,  0x2A,  0x1C,  0x2B,  0xD5,  0x0A,  0x55,  0x0B,  0x53,  0x1A, 	/* 3F2D0 */
+	0xE0,  0x2B,  0xFE,  0x4E,  0x52,  0x12,  0x54,  0x13,  0x4C,  0x25,  0x54,  0x44,  0x62,  0x08,  0xC1,  0xA4, 	/* 3F2E0 */
+	0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48,  0x40,  0x2B,  0x9F,  0x2A,  0x09,  0x0A,  0x89,  0x0A,  0xD1, 	/* 3F2F0 */
+	0x1F,  0x26,  0x28,  0x00,  0x4B,  0xFE,  0x12,  0x22,  0x13,  0xFE,  0x22,  0x22,  0x43,  0xFE,  0x00,  0x00, 	/* 3F300 */
+	0xA7,  0x00,  0x40,  0x00,  0x40,  0x4F,  0xFF,  0x28,  0x3C,  0x28,  0x20,  0x0B,  0xFF,  0x0A,  0x9A,  0x0B, 	/* 3F310 */
+	0xE4,  0x1A,  0x7C,  0x2A,  0x00,  0x4A,  0xFC,  0x14,  0x80,  0x17,  0xFE,  0x28,  0x80,  0x50,  0xFE,  0x00, 	/* 3F320 */
+	0x00,  0xB0,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48,  0x00,  0x2B,  0xFC,  0x2A,  0x44,  0x0B,  0xFC, 	/* 3F330 */
+	0x0A,  0x44,  0x1B,  0xFC,  0x28,  0xD0,  0x4B,  0x28,  0x10,  0xC4,  0x17,  0xFA,  0x23,  0x50,  0x4C,  0x4C, 	/* 3F340 */
+	0x00,  0x42,  0xB4,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48,  0x20,  0x2B,  0xFE,  0x28,  0x88,  0x0F, 	/* 3F350 */
+	0xFF,  0x08,  0x00,  0x19,  0xFC,  0x29,  0x04,  0x49,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x20,  0x20,  0x4F, 	/* 3F360 */
+	0xFF,  0x00,  0x20,  0xBB,  0x00,  0x40,  0x0F,  0xFF,  0x48,  0x20,  0x2B,  0xFC,  0x2A,  0x24,  0x0F,  0xFF, 	/* 3F370 */
+	0x0A,  0x24,  0x1B,  0xFC,  0x28,  0x20,  0x4B,  0xFC,  0x12,  0x24,  0x1F,  0xFF,  0x10,  0x88,  0x23,  0x10, 	/* 3F380 */
+	0x40,  0xF0,  0x0F,  0x0C,  0x82,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48,  0x40,  0x2F,  0xFE,  0x2A, 	/* 3F390 */
+	0x94,  0x09,  0x08,  0x0B,  0xFC,  0x1D,  0x0A,  0x29,  0xF9,  0x49,  0x08,  0x09,  0xF8,  0x11,  0x58,  0x12, 	/* 3F3A0 */
+	0x44,  0x2C,  0x42,  0x40,  0xC0,  0x86,  0x00,  0x20,  0x00,  0x20,  0x0F,  0xFF,  0x48,  0x88,  0x2A,  0xAA, 	/* 3F3B0 */
+	0x2C,  0xAC,  0x09,  0x52,  0x0A,  0x20,  0x1F,  0xFF,  0x2C,  0x01,  0x4C,  0x41,  0x13,  0xFC,  0x10,  0x44, 	/* 3F3C0 */
+	0x20,  0x84,  0x41,  0x04,  0x06,  0x38,  0x87,  0x00,  0x80,  0x00,  0x80,  0x0F,  0xFF,  0x48,  0x00,  0x2B, 	/* 3F3D0 */
+	0xDE,  0x3A,  0x52,  0x0B,  0xDE,  0x0A,  0x52,  0x1B,  0xDE,  0x2A,  0x7A,  0x4A,  0x4A,  0x12,  0x7A,  0x12, 	/* 3F3E0 */
+	0x4A,  0x22,  0x7A,  0x42,  0x4A,  0x02,  0x06,  0x88,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x48,  0x12, 	/* 3F3F0 */
+	0x2F,  0xD4,  0x28,  0x49,  0x0A,  0x86,  0x09,  0xDE,  0x1A,  0x55,  0x2C,  0x56,  0x4B,  0xE0,  0x12,  0x3E, 	/* 3F400 */
+	0x13,  0xD4,  0x20,  0x48,  0x40,  0x94,  0x07,  0x23,  0x8C,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFE,  0x48, 	/* 3F410 */
+	0x00,  0x29,  0xF8,  0x29,  0x08,  0x09,  0xF8,  0x08,  0x00,  0x1F,  0x9E,  0x2C,  0x92,  0x4F,  0xDE,  0x10, 	/* 3F420 */
+	0x40,  0x14,  0x44,  0x24,  0x44,  0x47,  0xFC,  0x00,  0x00,  0x92,  0x00,  0x40,  0x0F,  0xFF,  0x08,  0x20, 	/* 3F430 */
+	0x48,  0x50,  0x29,  0xFC,  0x2E,  0x03,  0x0B,  0xD2,  0x0A,  0x52,  0x1B,  0xD2,  0x2A,  0x52,  0x4B,  0xD2, 	/* 3F440 */
+	0x12,  0x46,  0x11,  0x40,  0x29,  0x24,  0x49,  0x0A,  0x10,  0xF9,  0x96,  0x00,  0x80,  0x00,  0x80,  0x0F, 	/* 3F450 */
+	0xFF,  0x48,  0x08,  0x2B,  0xFE,  0x2A,  0x62,  0x0A,  0x52,  0x0B,  0xD4,  0x1A,  0x7F,  0x2A,  0x08,  0x4B, 	/* 3F460 */
+	0xC8,  0x0E,  0x7F,  0x16,  0x48,  0x2A,  0x48,  0x53,  0xC8,  0x02,  0x48,  0x98,  0x00,  0x40,  0x00,  0x40, 	/* 3F470 */
+	0x0F,  0xFF,  0x48,  0x90,  0x2F,  0xFE,  0x28,  0x90,  0x0B,  0xFC,  0x0A,  0x44,  0x1B,  0xFC,  0x2A,  0x44, 	/* 3F480 */
+	0x4B,  0xFC,  0x10,  0x40,  0x17,  0xFE,  0x24,  0x52,  0x47,  0xEA,  0x04,  0x06,  0x9C,  0x00,  0x40,  0x00, 	/* 3F490 */
+	0x40,  0x1F,  0xFF,  0x10,  0x00,  0x57,  0xDC,  0x34,  0x54,  0x17,  0xD5,  0x15,  0x13,  0x37,  0xE1,  0x35, 	/* 3F4A0 */
+	0x5E,  0x55,  0x4A,  0x17,  0xEA,  0x28,  0x04,  0x29,  0x44,  0x52,  0x2A,  0x04,  0x31,  0xA1,  0x00,  0x20, 	/* 3F4B0 */
+	0x00,  0x20,  0x0F,  0xFF,  0x48,  0x00,  0x2A,  0xBE,  0x2B,  0x14,  0x0A,  0x48,  0x09,  0xC8,  0x1A,  0x3F, 	/* 3F4C0 */
+	0x2B,  0xCA,  0x4D,  0x28,  0x17,  0xEE,  0x11,  0x28,  0x22,  0xB8,  0x44,  0xA8,  0x08,  0x47,  0xA2,  0x00, 	/* 3F4D0 */
+	0x20,  0x00,  0x20,  0x0F,  0xFF,  0x48,  0x88,  0x2B,  0xFE,  0x28,  0x20,  0x09,  0xFC,  0x08,  0x20,  0x1F, 	/* 3F4E0 */
+	0xFF,  0x29,  0x08,  0x4B,  0xFC,  0x15,  0x0B,  0x19,  0xFA,  0x21,  0x24,  0x41,  0xD8,  0x07,  0x07,  0xA7, 	/* 3F4F0 */
+	0x00,  0x20,  0x00,  0x20,  0x0F,  0xFF,  0x48,  0x00,  0x2B,  0xFF,  0x2A,  0xEE,  0x0A,  0x44,  0x0B,  0xFF, 	/* 3F500 */
+	0x1A,  0xEE,  0x2B,  0x55,  0x4A,  0x44,  0x12,  0x90,  0x14,  0x9E,  0x24,  0x90,  0x4B,  0xFF,  0x00,  0x00, 	/* 3F510 */
+	0xA8,  0x00,  0x20,  0x0F,  0xFF,  0x08,  0x00,  0x4B,  0xFE,  0x28,  0x20,  0x2F,  0xFF,  0x0C,  0x21,  0x0D, 	/* 3F520 */
+	0xAD,  0x18,  0x88,  0x29,  0x10,  0x4B,  0xFE,  0x15,  0x10,  0x11,  0xFE,  0x21,  0x10,  0x41,  0xFE,  0x00, 	/* 3F530 */
+	0x00,  0xA9,  0x00,  0x20,  0x00,  0x20,  0x0F,  0xFF,  0x49,  0x00,  0x29,  0x3F,  0x2F,  0xC9,  0x09,  0x13, 	/* 3F540 */
+	0x0F,  0xFE,  0x1D,  0x52,  0x2F,  0xDE,  0x49,  0x12,  0x13,  0x9E,  0x13,  0x52,  0x25,  0x5E,  0x49,  0x12, 	/* 3F550 */
+	0x01,  0x61,  0xAA,  0x00,  0x20,  0x00,  0x20,  0x0F,  0xFF,  0x48,  0x48,  0x29,  0xBE,  0x2F,  0x08,  0x09, 	/* 3F560 */
+	0x3E,  0x09,  0x08,  0x1F,  0xFF,  0x29,  0x92,  0x4B,  0x5E,  0x13,  0x52,  0x15,  0x1E,  0x21,  0x12,  0x41, 	/* 3F570 */
+	0x1E,  0x01,  0x61,  0xAC,  0x00,  0x20,  0x00,  0x20,  0x0F,  0xFF,  0x49,  0x02,  0x29,  0xCA,  0x2A,  0x44, 	/* 3F580 */
+	0x0A,  0x9F,  0x0F,  0xE4,  0x1A,  0xA4,  0x2B,  0xFE,  0x4A,  0xA4,  0x13,  0xE4,  0x10,  0xBF,  0x26,  0x54, 	/* 3F590 */
+	0x45,  0x44,  0x09,  0x04,  0xB0,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x4A,  0xA0,  0x2D,  0x4A,  0x2A, 	/* 3F5A0 */
+	0xAA,  0x08,  0x1F,  0x0B,  0xF4,  0x1A,  0x54,  0x2B,  0xDF,  0x48,  0x14,  0x17,  0xDF,  0x15,  0x54,  0x27, 	/* 3F5B0 */
+	0xD4,  0x44,  0x3F,  0x03,  0xE0,  0xB2,  0x00,  0x40,  0x00,  0x40,  0x0F,  0xFF,  0x4A,  0x40,  0x2B,  0xBF, 	/* 3F5C0 */
+	0x2A,  0x24,  0x0B,  0xE8,  0x0D,  0x5E,  0x1D,  0xD2,  0x2D,  0x5E,  0x4D,  0xD2,  0x15,  0x5E,  0x15,  0xD2, 	/* 3F5D0 */
+	0x27,  0xFE,  0x42,  0x52,  0x0C,  0x21,  0xB6,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0F,  0x48,  0x01, 	/* 3F5E0 */
+	0x48,  0x01,  0x50,  0x12,  0x22,  0x0A,  0x22,  0x04,  0x14,  0x08,  0x08,  0x10,  0x04,  0x60,  0x03,  0x00, 	/* 3F5F0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xB8,  0x0F,  0x48,  0x01,  0x48,  0x01,  0x50,  0x12,  0x22, 	/* 3F600 */
+	0x0A,  0x22,  0x04,  0x14,  0x0F,  0xF8,  0x10,  0x84,  0x60,  0x83,  0x00,  0x80,  0x7F,  0xFE,  0x00,  0x80, 	/* 3F610 */
+	0x01,  0x40,  0x02,  0x20,  0x0C,  0x18,  0x30,  0x06,  0xBA,  0x0F,  0x24,  0x01,  0x24,  0x01,  0x18,  0x12, 	/* 3F620 */
+	0x11,  0x0A,  0x09,  0x04,  0x0A,  0x0F,  0xFC,  0x12,  0x22,  0x62,  0x21,  0x02,  0x20,  0x7F,  0xFF,  0x02, 	/* 3F630 */
+	0x20,  0x02,  0x20,  0x04,  0x21,  0x18,  0x21,  0x60,  0x1F,  0xBB,  0x00,  0x20,  0x0F,  0x24,  0x01,  0x18, 	/* 3F640 */
+	0x22,  0x11,  0x14,  0x0A,  0x0F,  0xFC,  0x10,  0x02,  0x67,  0xF9,  0x04,  0x08,  0x04,  0x08,  0x07,  0xF8, 	/* 3F650 */
+	0x02,  0x10,  0x01,  0x10,  0x01,  0x20,  0x3F,  0xFF,  0x00,  0x00,  0xBC,  0x0F,  0x48,  0x01,  0x4A,  0x12, 	/* 3F660 */
+	0x32,  0x0C,  0x14,  0x18,  0x0C,  0x6E,  0x7B,  0x02,  0x48,  0x02,  0x49,  0x1E,  0x47,  0x10,  0xFC,  0x11, 	/* 3F670 */
+	0x44,  0x1E,  0x28,  0x02,  0x28,  0x02,  0x10,  0x04,  0x6C,  0x19,  0x83,  0xBD,  0x01,  0x00,  0x01,  0x00, 	/* 3F680 */
+	0x02,  0x00,  0x1F,  0xF8,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x1F,  0xF8,  0x10,  0x08, 	/* 3F690 */
+	0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x1F,  0xF8,  0x00,  0x00,  0xBE,  0x00,  0x00,  0x7F, 	/* 3F6A0 */
+	0xFE,  0x01,  0x00,  0x01,  0x00,  0x02,  0x00,  0x1F,  0xF8,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x1F, 	/* 3F6B0 */
+	0xF8,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x1F,  0xF8,  0x00,  0x00,  0x80,  0x01,  0x00, 	/* 3F6C0 */
+	0x02,  0x00,  0x1F,  0xF8,  0x10,  0x08,  0x10,  0x08,  0x1F,  0xF8,  0x10,  0x08,  0x10,  0x08,  0x1F,  0xF8, 	/* 3F6D0 */
+	0x00,  0x00,  0x10,  0x0C,  0x10,  0xF0,  0x1F,  0x00,  0x10,  0x02,  0x10,  0x02,  0x0F,  0xFE,  0x83,  0x00, 	/* 3F6E0 */
+	0x40,  0x00,  0x80,  0x0F,  0xFC,  0x08,  0x04,  0x08,  0x04,  0x0F,  0xFC,  0x08,  0x04,  0x08,  0x04,  0x0F, 	/* 3F6F0 */
+	0xFC,  0x01,  0x20,  0x01,  0x20,  0x02,  0x20,  0x02,  0x20,  0x04,  0x21,  0x18,  0x21,  0x60,  0x1F,  0x84, 	/* 3F700 */
+	0x08,  0x40,  0x08,  0x40,  0x10,  0x40,  0x3E,  0x7E,  0x22,  0x42,  0x22,  0x82,  0x22,  0xC2,  0x23,  0x22, 	/* 3F710 */
+	0x3E,  0x12,  0x22,  0x12,  0x22,  0x02,  0x22,  0x02,  0x22,  0x02,  0x3E,  0x02,  0x00,  0x04,  0x00,  0x18, 	/* 3F720 */
+	0x86,  0x10,  0x20,  0x10,  0x26,  0x1F,  0xB8,  0x10,  0x20,  0x10,  0x21,  0x13,  0x21,  0x1C,  0x9F,  0x61, 	/* 3F730 */
+	0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00, 	/* 3F740 */
+	0x00,  0x87,  0x00,  0x80,  0x01,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8, 	/* 3F750 */
+	0x00,  0x00,  0x3F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF, 	/* 3F760 */
+	0x00,  0x00,  0x88,  0x10,  0x00,  0x10,  0xFF,  0x20,  0x80,  0x7C,  0x80,  0x44,  0x80,  0x44,  0xFC,  0x44, 	/* 3F770 */
+	0x84,  0x7C,  0xA4,  0x44,  0xA4,  0x44,  0xA8,  0x45,  0x18,  0x7D,  0x10,  0x02,  0x28,  0x04,  0x44,  0x09, 	/* 3F780 */
+	0x82,  0x06,  0x01,  0x8B,  0x00,  0x80,  0x01,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08, 	/* 3F790 */
+	0x0F,  0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x40,  0x02,  0xA0,  0x0C,  0x98,  0x70,  0x87,  0x0F,  0xF8, 	/* 3F7A0 */
+	0x00,  0x80,  0x00,  0x80,  0x8E,  0x08,  0x10,  0x08,  0x10,  0x13,  0xFF,  0x7C,  0x48,  0x44,  0x44,  0x44, 	/* 3F7B0 */
+	0x84,  0x44,  0x8A,  0x7D,  0x4A,  0x44,  0x48,  0x44,  0x50,  0x44,  0x30,  0x44,  0x30,  0x7C,  0x48,  0x00, 	/* 3F7C0 */
+	0x84,  0x03,  0x02,  0x0C,  0x01,  0x90,  0x00,  0x80,  0x01,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8, 	/* 3F7D0 */
+	0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x1E,  0xBC,  0x00,  0x80,  0x1E,  0xBC,  0x00,  0x80,  0x7F,  0xFF, 	/* 3F7E0 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x93,  0x10,  0x10,  0x10,  0x90,  0x20,  0x90,  0x7C,  0xFE,  0x45, 	/* 3F7F0 */
+	0x10,  0x46,  0x10,  0x44,  0x10,  0x7F,  0xFF,  0x44,  0x00,  0x44,  0x00,  0x44,  0xFC,  0x44,  0x84,  0x7C, 	/* 3F800 */
+	0x84,  0x00,  0x84,  0x00,  0xFC,  0x00,  0x00,  0x96,  0x10,  0x10,  0x10,  0x10,  0x21,  0xFF,  0x7D,  0x01, 	/* 3F810 */
+	0x45,  0x01,  0x44,  0xFE,  0x44,  0x00,  0x7C,  0x00,  0x47,  0xFF,  0x44,  0x48,  0x44,  0x48,  0x44,  0x48, 	/* 3F820 */
+	0x7C,  0x48,  0x00,  0x89,  0x03,  0x09,  0x0C,  0x07,  0x99,  0x08,  0x04,  0x08,  0x78,  0x7F,  0x40,  0x08, 	/* 3F830 */
+	0x7F,  0x1C,  0x48,  0x1A,  0x48,  0x28,  0x88,  0x49,  0x08,  0x09,  0x00,  0x1F,  0xF8,  0x10,  0x08,  0x1F, 	/* 3F840 */
+	0xF8,  0x10,  0x08,  0x10,  0x08,  0x1F,  0xF8,  0x00,  0x00,  0x9A,  0x10,  0x20,  0x12,  0x22,  0x22,  0x22, 	/* 3F850 */
+	0x7B,  0xFE,  0x48,  0x00,  0x4F,  0xFF,  0x48,  0x00,  0x79,  0xFC,  0x49,  0x04,  0x49,  0x04,  0x49,  0xFC, 	/* 3F860 */
+	0x48,  0x88,  0x78,  0x48,  0x00,  0x50,  0x07,  0xFF,  0x00,  0x00,  0xAE,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 3F870 */
+	0x80,  0x1F,  0xFE,  0x10,  0x82,  0x10,  0x84,  0x10,  0x80,  0x1F,  0xF8,  0x12,  0x10,  0x12,  0x10,  0x11, 	/* 3F880 */
+	0x20,  0x10,  0xC0,  0x20,  0xC0,  0x21,  0x20,  0x46,  0x18,  0x18,  0x06,  0xB0,  0x04,  0x20,  0x04,  0x20, 	/* 3F890 */
+	0x3F,  0xFE,  0x25,  0x42,  0x24,  0x82,  0x25,  0x7A,  0x3E,  0x4A,  0x22,  0x4A,  0x2A,  0x7A,  0x24,  0x42, 	/* 3F8A0 */
+	0x24,  0x44,  0x2A,  0x58,  0x29,  0x40,  0x51,  0x41,  0x20,  0x21,  0x40,  0x1F,  0xB4,  0x08,  0x08,  0x0A, 	/* 3F8B0 */
+	0x08,  0x11,  0x08,  0x7E,  0xFF,  0x14,  0x49,  0x15,  0x4A,  0x27,  0x48,  0x48,  0x7E,  0x0E,  0x52,  0x12, 	/* 3F8C0 */
+	0x52,  0x34,  0x54,  0x4C,  0x4C,  0x0A,  0x88,  0x12,  0x94,  0x21,  0x22,  0x40,  0x41,  0xB7,  0x08,  0x10, 	/* 3F8D0 */
+	0x08,  0x10,  0x7F,  0x10,  0x08,  0xFF,  0x3E,  0x92,  0x00,  0x94,  0x3E,  0x90,  0x22,  0xFC,  0x22,  0xA4, 	/* 3F8E0 */
+	0x3E,  0xA4,  0x24,  0x94,  0x14,  0x98,  0x1A,  0x88,  0x0D,  0x14,  0x12,  0x62,  0x61,  0x81,  0xB8,  0x00, 	/* 3F8F0 */
+	0x08,  0x7F,  0x08,  0x41,  0x08,  0x49,  0x7F,  0x3E,  0x49,  0x08,  0x4A,  0x3F,  0x48,  0x29,  0x7E,  0x3F, 	/* 3F900 */
+	0x52,  0x29,  0x52,  0x3F,  0x54,  0x08,  0x4C,  0x7F,  0x88,  0x08,  0x94,  0x09,  0x22,  0x08,  0x41,  0xB9, 	/* 3F910 */
+	0x04,  0x00,  0x04,  0xFF,  0x3F,  0x81,  0x26,  0x91,  0x24,  0x7E,  0x24,  0x10,  0x3E,  0x7E,  0x22,  0x52, 	/* 3F920 */
+	0x2A,  0x7E,  0x24,  0x52,  0x24,  0x52,  0x2A,  0x7E,  0x29,  0x10,  0x51,  0xFF,  0x20,  0x10,  0x40,  0x10, 	/* 3F930 */
+	0xBA,  0x10,  0x08,  0x1F,  0x08,  0x21,  0x08,  0x55,  0x7F,  0x55,  0x49,  0x7D,  0x4A,  0x11,  0x48,  0x26, 	/* 3F940 */
+	0x7E,  0x10,  0x52,  0x1F,  0x52,  0x21,  0x54,  0x55,  0x4C,  0x55,  0x88,  0x7D,  0x94,  0x11,  0x22,  0x26, 	/* 3F950 */
+	0x41,  0xBF,  0x00,  0x00,  0x00,  0x00,  0x1F,  0xFC,  0x12,  0x24,  0x12,  0x24,  0x12,  0x24,  0x12,  0x24, 	/* 3F960 */
+	0x12,  0x24,  0x12,  0x24,  0x12,  0x24,  0x12,  0x24,  0x12,  0x24,  0x12,  0x24,  0x7F,  0xFF,  0x00,  0x00, 	/* 3F970 */
+	0x00,  0x00,  0x82,  0x00,  0x00,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00, 	/* 3F980 */
+	0x80,  0x00,  0x80,  0x01,  0x80,  0x00,  0x00,  0x1F,  0xFC,  0x12,  0x24,  0x12,  0x24,  0x12,  0x24,  0x7F, 	/* 3F990 */
+	0xFF,  0x00,  0x00,  0x83,  0x00,  0x00,  0x3F,  0xFE,  0x00,  0x40,  0x00,  0x80,  0x03,  0xB8,  0x0C,  0x86, 	/* 3F9A0 */
+	0x70,  0x81,  0x00,  0x80,  0x00,  0x80,  0x00,  0x00,  0x1F,  0xFC,  0x12,  0x24,  0x12,  0x24,  0x12,  0x24, 	/* 3F9B0 */
+	0x7F,  0xFF,  0x00,  0x00,  0x86,  0x02,  0xF0,  0x02,  0x10,  0x04,  0x08,  0x18,  0x04,  0x6F,  0xFB,  0x00, 	/* 3F9C0 */
+	0x88,  0x01,  0x08,  0x06,  0x08,  0x38,  0x30,  0x00,  0x00,  0x1F,  0xFC,  0x12,  0x24,  0x12,  0x24,  0x12, 	/* 3F9D0 */
+	0x24,  0x7F,  0xFF,  0x00,  0x00,  0x88,  0x00,  0x00,  0x3F,  0xF8,  0x04,  0x08,  0x04,  0x08,  0x07,  0xEE, 	/* 3F9E0 */
+	0x0A,  0x22,  0x09,  0x42,  0x10,  0x82,  0x23,  0x5C,  0x4C,  0x30,  0x1F,  0xFC,  0x12,  0x24,  0x12,  0x24, 	/* 3F9F0 */
+	0x12,  0x24,  0x7F,  0xFF,  0x00,  0x00,  0x8A,  0x08,  0x10,  0x04,  0x10,  0x02,  0x20,  0x02,  0x40,  0x7F, 	/* 3FA00 */
+	0xFF,  0x04,  0x10,  0x04,  0x10,  0x08,  0x08,  0x10,  0x04,  0x2F,  0xFA,  0x49,  0x48,  0x09,  0x48,  0x09, 	/* 3FA10 */
+	0x48,  0x09,  0x48,  0x7F,  0xFE,  0x00,  0x00,  0x8D,  0x00,  0x80,  0x00,  0x80,  0x0F,  0xF8,  0x00,  0x80, 	/* 3FA20 */
+	0x00,  0x80,  0x7F,  0xFF,  0x01,  0x20,  0x01,  0x18,  0x02,  0x74,  0x1F,  0x82,  0x00,  0x00,  0x1F,  0xFC, 	/* 3FA30 */
+	0x12,  0x24,  0x12,  0x24,  0x7F,  0xFF,  0x00,  0x00,  0x92,  0x00,  0x80,  0x00,  0x80,  0x01,  0x40,  0x06, 	/* 3FA40 */
+	0x30,  0x18,  0x0C,  0x67,  0xF3,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x1F, 	/* 3FA50 */
+	0xFC,  0x12,  0x24,  0x12,  0x24,  0x7F,  0xFF,  0x00,  0x00,  0x96,  0x04,  0x10,  0x02,  0x10,  0x02,  0x20, 	/* 3FA60 */
+	0x3F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00, 	/* 3FA70 */
+	0x1F,  0xFC,  0x12,  0x24,  0x12,  0x24,  0x7F,  0xFF,  0x00,  0x00,  0x97,  0x00,  0x80,  0x10,  0x80,  0x08, 	/* 3FA80 */
+	0xFE,  0x09,  0x22,  0x01,  0x24,  0x02,  0x60,  0x08,  0x50,  0x10,  0x8C,  0x21,  0x03,  0x22,  0x00,  0x1F, 	/* 3FA90 */
+	0xFC,  0x12,  0x24,  0x12,  0x24,  0x12,  0x24,  0x7F,  0xFF,  0x00,  0x00,  0x9B,  0x00,  0x28,  0x00,  0x24, 	/* 3FAA0 */
+	0x1F,  0xFE,  0x10,  0x20,  0x1F,  0x24,  0x11,  0x18,  0x11,  0x12,  0x21,  0x2A,  0x26,  0xC6,  0x40,  0x02, 	/* 3FAB0 */
+	0x1F,  0xF8,  0x12,  0x48,  0x12,  0x48,  0x12,  0x48,  0x7F,  0xFE,  0x00,  0x00,  0x9C,  0x08,  0x40,  0x04, 	/* 3FAC0 */
+	0x40,  0x44,  0xFF,  0x20,  0x92,  0x21,  0x14,  0x0A,  0x10,  0x08,  0x28,  0x10,  0xC4,  0x23,  0x03,  0x40, 	/* 3FAD0 */
+	0x00,  0x1F,  0xFC,  0x12,  0x24,  0x12,  0x24,  0x12,  0x24,  0x7F,  0xFF,  0x00,  0x00,  0x9E,  0x01,  0x10, 	/* 3FAE0 */
+	0x7F,  0xFE,  0x00,  0x48,  0x01,  0xF2,  0x1E,  0x1E,  0x01,  0x02,  0x7F,  0xFF,  0x00,  0x48,  0x01,  0xF2, 	/* 3FAF0 */
+	0x3E,  0x0E,  0x00,  0x02,  0x1F,  0xFC,  0x12,  0x24,  0x12,  0x24,  0x7F,  0xFF,  0x00,  0x00,  0x9F,  0x00, 	/* 3FB00 */
+	0x00,  0x3E,  0x7E,  0x22,  0x42,  0x22,  0x7E,  0x3E,  0x42,  0x22,  0x7E,  0x22,  0x42,  0x3E,  0x42,  0x22, 	/* 3FB10 */
+	0x82,  0x01,  0x06,  0x1F,  0xFC,  0x12,  0x24,  0x12,  0x24,  0x12,  0x24,  0x7F,  0xFF,  0x00,  0x00,  0xA1, 	/* 3FB20 */
+	0x00,  0x80,  0x1F,  0xFC,  0x00,  0x84,  0x7F,  0xFF,  0x00,  0x84,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF, 	/* 3FB30 */
+	0x12,  0x24,  0x11,  0x12,  0x20,  0x01,  0x5F,  0xFC,  0x12,  0x24,  0x12,  0x24,  0x7F,  0xFF,  0x00,  0x00, 	/* 3FB40 */
+	0xA3,  0x00,  0x20,  0x3F,  0x20,  0x24,  0x20,  0x24,  0x3F,  0x3F,  0x40,  0x21,  0x40,  0x3F,  0xBE,  0x24, 	/* 3FB50 */
+	0x00,  0x3F,  0x00,  0x00,  0x00,  0x1F,  0xFC,  0x12,  0x24,  0x12,  0x24,  0x12,  0x24,  0x7F,  0xFF,  0x00, 	/* 3FB60 */
+	0x00,  0xA4,  0x04,  0x00,  0x1F,  0x3C,  0x19,  0x25,  0x15,  0x23,  0x17,  0x40,  0x79,  0xFE,  0x15,  0x14, 	/* 3FB70 */
+	0x15,  0x08,  0x11,  0x14,  0x23,  0x63,  0x40,  0x00,  0x1F,  0xFC,  0x12,  0x24,  0x12,  0x24,  0x7F,  0xFF, 	/* 3FB80 */
+	0x00,  0x00,  0xA5,  0x04,  0x00,  0x38,  0x8E,  0x20,  0xA2,  0x38,  0xAE,  0x27,  0xC2,  0x22,  0xC2,  0x3A, 	/* 3FB90 */
+	0xAE,  0x24,  0x92,  0x21,  0x82,  0x20,  0x02,  0x1F,  0xFC,  0x12,  0x44,  0x12,  0x44,  0x12,  0x44,  0x7F, 	/* 3FBA0 */
+	0xFF,  0x00,  0x00,  0xA7,  0x00,  0x80,  0x00,  0xF8,  0x00,  0x80,  0x1F,  0xFF,  0x11,  0x72,  0x1F,  0x84, 	/* 3FBB0 */
+	0x13,  0xFC,  0x12,  0x48,  0x13,  0xF8,  0x12,  0x48,  0x13,  0xF8,  0x10,  0x00,  0x27,  0xFC,  0x24,  0xA4, 	/* 3FBC0 */
+	0x5F,  0xFF,  0x00,  0x00,  0xAA,  0x10,  0x00,  0x08,  0xF8,  0x08,  0x88,  0x40,  0xF8,  0x20,  0x88,  0x27, 	/* 3FBD0 */
+	0xFF,  0x00,  0x80,  0x11,  0xFE,  0x22,  0x52,  0x24,  0x92,  0x41,  0x2C,  0x1F,  0xFC,  0x12,  0x24,  0x12, 	/* 3FBE0 */
+	0x24,  0x7F,  0xFF,  0x00,  0x00,  0xAE,  0x00,  0x00,  0x1F,  0xF8,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08, 	/* 3FBF0 */
+	0x1F,  0xF8,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x1F,  0xF8,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08, 	/* 3FC00 */
+	0x10,  0x08,  0x1F,  0xF8,  0x00,  0x00,  0xB2,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x10,  0x00,  0x10, 	/* 3FC10 */
+	0x00,  0x0F,  0xFC,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08, 	/* 3FC20 */
+	0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0xB4,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80, 	/* 3FC30 */
+	0x07,  0xF8,  0x24,  0x08,  0x24,  0x08,  0x27,  0xF8,  0x24,  0x08,  0x27,  0xF8,  0x24,  0x08,  0x24,  0x08, 	/* 3FC40 */
+	0x27,  0xF8,  0x20,  0x00,  0x3F,  0xFF,  0x00,  0x00,  0xB8,  0x08,  0x00,  0x08,  0xFE,  0x08,  0x82,  0x7F, 	/* 3FC50 */
+	0x82,  0x08,  0x82,  0x08,  0xFE,  0x1C,  0x82,  0x1A,  0x82,  0x19,  0x82,  0x28,  0xFE,  0x28,  0x82,  0x48, 	/* 3FC60 */
+	0x82,  0x08,  0x82,  0x08,  0x82,  0x08,  0xFE,  0x08,  0x00,  0xBB,  0x00,  0x78,  0x78,  0x08,  0x48,  0x88, 	/* 3FC70 */
+	0x48,  0x84,  0x49,  0x04,  0x7B,  0xFE,  0x4C,  0x41,  0x48,  0x40,  0x48,  0x40,  0x78,  0xFC,  0x48,  0x84, 	/* 3FC80 */
+	0x48,  0x04,  0x48,  0x04,  0x78,  0x04,  0x00,  0x04,  0x00,  0x18,  0xBE,  0x00,  0x04,  0x00,  0x38,  0x1F, 	/* 3FC90 */
+	0xC0,  0x10,  0x40,  0x1F,  0xFF,  0x10,  0x40,  0x13,  0xF8,  0x12,  0x08,  0x12,  0x08,  0x13,  0xF8,  0x12, 	/* 3FCA0 */
+	0x08,  0x13,  0xF8,  0x22,  0x08,  0x22,  0x08,  0x43,  0xF8,  0x00,  0x00,  0x81,  0x00,  0x80,  0x00,  0x90, 	/* 3FCB0 */
+	0x04,  0x8C,  0x18,  0x92,  0x61,  0xA1,  0x00,  0xC0,  0x0F,  0xF8,  0x78,  0x08,  0x08,  0x08,  0x0F,  0xF8, 	/* 3FCC0 */
+	0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x84,  0x00,  0x00,  0x7B, 	/* 3FCD0 */
+	0xFF,  0x48,  0x20,  0x48,  0x20,  0x49,  0x20,  0x79,  0x3E,  0x49,  0x22,  0x49,  0x22,  0x49,  0x22,  0x79, 	/* 3FCE0 */
+	0x22,  0x49,  0xFE,  0x48,  0x02,  0x48,  0x02,  0x78,  0x02,  0x00,  0x04,  0x00,  0x18,  0x87,  0x00,  0x20, 	/* 3FCF0 */
+	0x78,  0x20,  0x48,  0x20,  0x48,  0xA4,  0x48,  0xA2,  0x78,  0xA2,  0x49,  0x21,  0x4A,  0x25,  0x4C,  0x24, 	/* 3FD00 */
+	0x78,  0x68,  0x48,  0x08,  0x48,  0x10,  0x48,  0x20,  0x78,  0x40,  0x01,  0x80,  0x06,  0x00,  0x88,  0x00, 	/* 3FD10 */
+	0x20,  0x78,  0x20,  0x48,  0x20,  0x4B,  0xFE,  0x4A,  0x22,  0x7A,  0x22,  0x4A,  0x22,  0x48,  0x30,  0x78, 	/* 3FD20 */
+	0x30,  0x48,  0x50,  0x48,  0x50,  0x48,  0x50,  0x78,  0x90,  0x01,  0x11,  0x02,  0x11,  0x04,  0x0F,  0x89, 	/* 3FD30 */
+	0x00,  0x00,  0x1F,  0xFE,  0x10,  0x42,  0x10,  0x42,  0x1F,  0xFE,  0x10,  0x00,  0x13,  0xFC,  0x12,  0x04, 	/* 3FD40 */
+	0x12,  0x04,  0x13,  0xFC,  0x12,  0x04,  0x13,  0xFC,  0x22,  0x04,  0x22,  0x04,  0x43,  0xFC,  0x00,  0x00, 	/* 3FD50 */
+	0x8B,  0x00,  0x08,  0x00,  0x70,  0x0F,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x01,  0x00,  0x7F,  0xFF,  0x02, 	/* 3FD60 */
+	0x00,  0x07,  0xF8,  0x0A,  0x08,  0x13,  0xF8,  0x22,  0x08,  0x03,  0xF8,  0x02,  0x08,  0x03,  0xF8,  0x00, 	/* 3FD70 */
+	0x00,  0x8C,  0x00,  0x00,  0x07,  0xF8,  0x24,  0x08,  0x24,  0x08,  0x27,  0xF8,  0x24,  0x08,  0x27,  0xF8, 	/* 3FD80 */
+	0x24,  0x08,  0x24,  0x08,  0x27,  0xF8,  0x20,  0x00,  0x3F,  0xFF,  0x04,  0xB0,  0x18,  0x8C,  0x60,  0x82, 	/* 3FD90 */
+	0x00,  0x80,  0x9B,  0x00,  0x20,  0x78,  0x20,  0x48,  0x20,  0x4B,  0xFE,  0x48,  0x20,  0x78,  0x20,  0x48, 	/* 3FDA0 */
+	0x20,  0x4F,  0xFF,  0x48,  0x70,  0x78,  0x70,  0x48,  0xA8,  0x48,  0xA4,  0x49,  0x22,  0x7A,  0x21,  0x04, 	/* 3FDB0 */
+	0x20,  0x00,  0x20,  0x9E,  0x08,  0x30,  0x0F,  0xC4,  0x08,  0x04,  0x07,  0xFC,  0x20,  0x00,  0x27,  0xF8, 	/* 3FDC0 */
+	0x24,  0x08,  0x27,  0xF8,  0x24,  0x08,  0x27,  0xF8,  0x24,  0x08,  0x27,  0xF8,  0x20,  0x00,  0x3F,  0xFF, 	/* 3FDD0 */
+	0x06,  0x18,  0x78,  0x06,  0x9F,  0x01,  0x00,  0x01,  0x00,  0x3F,  0xFC,  0x01,  0x00,  0x0F,  0xF0,  0x08, 	/* 3FDE0 */
+	0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x00,  0x00,  0x7F,  0xFE,  0x04, 	/* 3FDF0 */
+	0x60,  0x18,  0x18,  0x60,  0x04,  0xA0,  0x00,  0x00,  0x79,  0xFC,  0x49,  0x04,  0x49,  0x04,  0x49,  0x04, 	/* 3FE00 */
+	0x79,  0xFC,  0x49,  0x10,  0x49,  0x10,  0x79,  0xFF,  0x49,  0x10,  0x49,  0x10,  0x49,  0x08,  0x49,  0x0A, 	/* 3FE10 */
+	0x79,  0x6A,  0x01,  0x86,  0x06,  0x02,  0xA4,  0x00,  0x00,  0x79,  0xFE,  0x49,  0x02,  0x49,  0x02,  0x49, 	/* 3FE20 */
+	0x02,  0x79,  0xFE,  0x49,  0x00,  0x49,  0x40,  0x79,  0x44,  0x49,  0x48,  0x49,  0x70,  0x49,  0x40,  0x7A, 	/* 3FE30 */
+	0x41,  0x02,  0x41,  0x04,  0x3F,  0x08,  0x00,  0xA5,  0x04,  0x20,  0x14,  0x22,  0x17,  0xBC,  0x14,  0x20, 	/* 3FE40 */
+	0x14,  0x21,  0x15,  0xA1,  0x1E,  0x1F,  0x70,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08, 	/* 3FE50 */
+	0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0xA6,  0x00,  0x88,  0x78,  0x88,  0x48,  0x88,  0x4A, 	/* 3FE60 */
+	0x88,  0x4A,  0x88,  0x7A,  0x89,  0x4A,  0xEA,  0x4A,  0x8C,  0x4A,  0x88,  0x7A,  0x88,  0x4A,  0x88,  0x4A, 	/* 3FE70 */
+	0x88,  0x4A,  0x88,  0x7A,  0xE9,  0x03,  0x89,  0x0C,  0x07,  0xA9,  0x00,  0x20,  0x78,  0x20,  0x48,  0x20, 	/* 3FE80 */
+	0x4B,  0xFF,  0x48,  0x20,  0x78,  0x20,  0x48,  0x24,  0x49,  0xC4,  0x48,  0x48,  0x78,  0x28,  0x48,  0x30, 	/* 3FE90 */
+	0x48,  0x28,  0x48,  0x44,  0x79,  0x9E,  0x07,  0xE2,  0x00,  0x02,  0xB7,  0x04,  0x90,  0x04,  0x88,  0x08, 	/* 3FEA0 */
+	0x84,  0x17,  0xFC,  0x00,  0x80,  0x01,  0x40,  0x7F,  0xFF,  0x02,  0x20,  0x07,  0xF0,  0x1C,  0x1C,  0x67, 	/* 3FEB0 */
+	0xF3,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x07,  0xF0,  0x00,  0x00,  0xB8,  0x00,  0x40,  0x78,  0x50, 	/* 3FEC0 */
+	0x48,  0x88,  0x49,  0x34,  0x4B,  0xC2,  0x78,  0x20,  0x49,  0x20,  0x49,  0x20,  0x4B,  0xFE,  0x7C,  0x20, 	/* 3FED0 */
+	0x48,  0x20,  0x4F,  0xFF,  0x48,  0x20,  0x78,  0x20,  0x00,  0x20,  0x00,  0x20,  0xBA,  0x00,  0x90,  0x78, 	/* 3FEE0 */
+	0x90,  0x48,  0x90,  0x4C,  0x94,  0x4A,  0x94,  0x7A,  0x98,  0x4A,  0x90,  0x48,  0x90,  0x79,  0x98,  0x4A, 	/* 3FEF0 */
+	0x94,  0x4C,  0x92,  0x48,  0x90,  0x79,  0x11,  0x01,  0x11,  0x02,  0x0F,  0x04,  0x00,  0xBC,  0x00,  0x00, 	/* 3FF00 */
+	0x3C,  0xFC,  0x24,  0x84,  0x24,  0x84,  0x24,  0xFC,  0x3C,  0x84,  0x24,  0x84,  0x24,  0xFE,  0x3C,  0x92, 	/* 3FF10 */
+	0x24,  0x94,  0x24,  0x94,  0x24,  0x88,  0x3C,  0x88,  0x00,  0xB4,  0x00,  0xC2,  0x03,  0x81,  0x80,  0x04, 	/* 3FF20 */
+	0x10,  0x02,  0x20,  0x3F,  0xFE,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x04,  0x00,  0x07, 	/* 3FF30 */
+	0xF8,  0x0C,  0x08,  0x0F,  0xF8,  0x14,  0x08,  0x27,  0xF8,  0x44,  0x08,  0x07,  0xF8,  0x00,  0x00,  0x87, 	/* 3FF40 */
+	0x01,  0x04,  0x78,  0x84,  0x48,  0x48,  0x4B,  0xFE,  0x48,  0x22,  0x78,  0x22,  0x4B,  0xFE,  0x4A,  0x20, 	/* 3FF50 */
+	0x4A,  0x20,  0x7B,  0xFE,  0x48,  0x62,  0x48,  0xA2,  0x49,  0x22,  0x7A,  0x2C,  0x04,  0x20,  0x00,  0x20, 	/* 3FF60 */
+	0x9A,  0x00,  0x00,  0x7B,  0xFF,  0x4A,  0x00,  0x4A,  0x10,  0x7A,  0xFE,  0x4A,  0x10,  0x4A,  0x10,  0x4B, 	/* 3FF70 */
+	0xFF,  0x7A,  0x00,  0x4A,  0x10,  0x4A,  0xFE,  0x4A,  0x10,  0x7C,  0x10,  0x04,  0x10,  0x09,  0xFF,  0x00, 	/* 3FF80 */
+	0x00,  0x9B,  0x00,  0x20,  0x78,  0x20,  0x4B,  0xFE,  0x48,  0x20,  0x49,  0xFC,  0x78,  0x20,  0x4F,  0xFF, 	/* 3FF90 */
+	0x48,  0x00,  0x49,  0xFC,  0x79,  0x24,  0x49,  0x24,  0x49,  0xFC,  0x49,  0x04,  0x79,  0x04,  0x01,  0x04, 	/* 3FFA0 */
+	0x01,  0x0C,  0xA1,  0x00,  0x08,  0x00,  0x30,  0x7B,  0xE0,  0x48,  0x20,  0x4B,  0xFE,  0x79,  0x24,  0x49, 	/* 3FFB0 */
+	0x24,  0x49,  0x24,  0x7F,  0xFF,  0x49,  0x24,  0x49,  0x24,  0x4B,  0xFE,  0x78,  0x20,  0x00,  0x20,  0x07, 	/* 3FFC0 */
+	0xFF,  0x00,  0x00,  0xA3,  0x04,  0x00,  0x07,  0xFC,  0x04,  0x44,  0x7F,  0xA4,  0x16,  0x18,  0x15,  0x28, 	/* 3FFD0 */
+	0x25,  0x44,  0x4C,  0x83,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08, 	/* 3FFE0 */
+	0x0F,  0xF8,  0x00,  0x00,  0xA5,  0x00,  0x20,  0x78,  0x40,  0x4B,  0xFE,  0x4A,  0x22,  0x4A,  0x22,  0x7B, 	/* 3FFF0 */
+	0xFE,  0x4A,  0x22,  0x4A,  0x42,  0x4B,  0xFE,  0x78,  0x80,  0x49,  0x10,  0x4F,  0xFF,  0x48,  0x10,  0x78, 	/* 40000 */
+	0x10,  0x00,  0x10,  0x00,  0x10,  0xA6,  0x00,  0x20,  0x7C,  0x20,  0x45,  0xFC,  0x44,  0x20,  0x44,  0x20, 	/* 40010 */
+	0x7F,  0xFF,  0x44,  0x88,  0x44,  0x88,  0x7D,  0x27,  0x46,  0x20,  0x44,  0x20,  0x45,  0xFC,  0x7C,  0x20, 	/* 40020 */
+	0x00,  0x20,  0x07,  0xFF,  0x00,  0x00,  0xA8,  0x00,  0x20,  0x3C,  0x40,  0x25,  0x8E,  0x25,  0x02,  0x25, 	/* 40030 */
+	0x02,  0x3D,  0xDE,  0x25,  0x02,  0x25,  0x02,  0x3D,  0xFE,  0x24,  0x50,  0x24,  0x50,  0x24,  0x90,  0x3C, 	/* 40040 */
+	0x90,  0x01,  0x11,  0x02,  0x11,  0x04,  0x0F,  0xAB,  0x00,  0x20,  0x78,  0x20,  0x4F,  0xFF,  0x48,  0x20, 	/* 40050 */
+	0x49,  0xFC,  0x78,  0x24,  0x4F,  0xFF,  0x48,  0x24,  0x49,  0xFC,  0x78,  0x20,  0x49,  0x20,  0x49,  0x3E, 	/* 40060 */
+	0x49,  0xA0,  0x7A,  0x60,  0x04,  0x30,  0x08,  0x0F,  0xB9,  0x00,  0x20,  0x78,  0x24,  0x49,  0xFE,  0x48, 	/* 40070 */
+	0x24,  0x48,  0x28,  0x78,  0x30,  0x4B,  0xFF,  0x48,  0x48,  0x48,  0x84,  0x79,  0xFC,  0x4E,  0x84,  0x48, 	/* 40080 */
+	0xFC,  0x48,  0x84,  0x78,  0x84,  0x00,  0xFC,  0x00,  0x00,  0xBE,  0x01,  0x00,  0x1F,  0xFC,  0x12,  0x24, 	/* 40090 */
+	0x12,  0x24,  0x1F,  0xFC,  0x00,  0x80,  0x0F,  0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x04,  0x10,  0x02,  0x20, 	/* 400A0 */
+	0x1F,  0xFC,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0xBF,  0x01,  0x00,  0x01,  0xF8,  0x01, 	/* 400B0 */
+	0x00,  0x7F,  0xFE,  0x40,  0x02,  0x47,  0xEA,  0x11,  0x84,  0x66,  0x62,  0x1F,  0xF8,  0x68,  0x17,  0x0F, 	/* 400C0 */
+	0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x00,  0x00,  0x8B,  0x01,  0x04,  0x79,  0xF8, 	/* 400D0 */
+	0x49,  0x02,  0x48,  0xFE,  0x4A,  0x00,  0x7A,  0xFC,  0x4A,  0x84,  0x4A,  0xFC,  0x4A,  0x84,  0x7A,  0xFC, 	/* 400E0 */
+	0x4A,  0x84,  0x4A,  0xFC,  0x4A,  0x00,  0x7B,  0xFF,  0x01,  0x8C,  0x0E,  0x03,  0x8E,  0x00,  0x20,  0x78, 	/* 400F0 */
+	0x20,  0x4B,  0xFE,  0x4A,  0x22,  0x4A,  0x3A,  0x79,  0xE0,  0x48,  0x20,  0x49,  0xFC,  0x48,  0x20,  0x7F, 	/* 40100 */
+	0xFF,  0x48,  0x20,  0x49,  0xFC,  0x49,  0x04,  0x79,  0x04,  0x01,  0xFC,  0x00,  0x00,  0x91,  0x00,  0x00, 	/* 40110 */
+	0x7F,  0xFE,  0x4C,  0x02,  0x4D,  0xFA,  0x49,  0x08,  0x79,  0x08,  0x49,  0xF8,  0x49,  0x08,  0x49,  0x08, 	/* 40120 */
+	0x79,  0xF8,  0x48,  0x20,  0x4F,  0xFF,  0x48,  0x00,  0x78,  0x88,  0x01,  0x04,  0x06,  0x02,  0x9E,  0x00, 	/* 40130 */
+	0x88,  0x78,  0x88,  0x4F,  0xFF,  0x48,  0x88,  0x48,  0x88,  0x78,  0xF8,  0x48,  0x20,  0x4B,  0xFE,  0x4A, 	/* 40140 */
+	0x22,  0x7B,  0xBA,  0x4A,  0xAA,  0x4A,  0xAA,  0x4B,  0x76,  0x7B,  0x32,  0x02,  0x22,  0x02,  0x26,  0xA0, 	/* 40150 */
+	0x01,  0x24,  0x78,  0xA4,  0x48,  0xA8,  0x4B,  0xFF,  0x7A,  0x01,  0x4A,  0xFD,  0x48,  0x84,  0x48,  0x84, 	/* 40160 */
+	0x78,  0xFC,  0x48,  0x20,  0x48,  0x20,  0x49,  0xFE,  0x78,  0x20,  0x00,  0x20,  0x07,  0xFF,  0x00,  0x00, 	/* 40170 */
+	0xA5,  0x24,  0x90,  0x15,  0x1F,  0x3F,  0xA4,  0x24,  0xB4,  0x2E,  0xC8,  0x35,  0x94,  0x24,  0xA2,  0x25, 	/* 40180 */
+	0xC1,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00, 	/* 40190 */
+	0x00,  0xAC,  0x00,  0x04,  0x78,  0x18,  0x4B,  0xE4,  0x49,  0x44,  0x48,  0xA8,  0x7B,  0xFE,  0x4A,  0x8A, 	/* 401A0 */
+	0x4A,  0x8A,  0x79,  0xC8,  0x49,  0x7E,  0x49,  0x68,  0x4A,  0xE8,  0x7C,  0xA8,  0x48,  0xFF,  0x01,  0x08, 	/* 401B0 */
+	0x02,  0x08,  0xAD,  0x00,  0x20,  0x78,  0x20,  0x4F,  0xFF,  0x48,  0x50,  0x4A,  0x8A,  0x79,  0x04,  0x4B, 	/* 401C0 */
+	0xFE,  0x4D,  0x05,  0x79,  0xFC,  0x49,  0x04,  0x49,  0xFC,  0x48,  0x28,  0x79,  0x24,  0x4A,  0x22,  0x04, 	/* 401D0 */
+	0x22,  0x00,  0x60,  0xB0,  0x00,  0x08,  0x7B,  0xC8,  0x48,  0x88,  0x48,  0x9F,  0x4F,  0xD4,  0x7A,  0x64, 	/* 401E0 */
+	0x4A,  0x54,  0x4B,  0xD4,  0x7A,  0x54,  0x4B,  0xC8,  0x4A,  0x48,  0x4A,  0x48,  0x7B,  0xD4,  0x0E,  0x54, 	/* 401F0 */
+	0x00,  0x62,  0x00,  0x41,  0xB3,  0x00,  0x20,  0x7B,  0xFE,  0x48,  0x88,  0x48,  0x50,  0x4F,  0xFF,  0x78, 	/* 40200 */
+	0x00,  0x49,  0xFC,  0x49,  0x24,  0x79,  0xFC,  0x49,  0x24,  0x49,  0xFC,  0x48,  0x20,  0x79,  0xFC,  0x48, 	/* 40210 */
+	0x20,  0x07,  0xFF,  0x00,  0x00,  0xB6,  0x00,  0x20,  0x79,  0xFC,  0x49,  0x24,  0x49,  0xFC,  0x48,  0x20, 	/* 40220 */
+	0x7F,  0xFF,  0x48,  0x00,  0x49,  0xFC,  0x49,  0x04,  0x79,  0xFC,  0x49,  0x04,  0x49,  0xFC,  0x49,  0x04, 	/* 40230 */
+	0x79,  0xFC,  0x00,  0xCC,  0x07,  0x03,  0xB9,  0x00,  0x0C,  0x7B,  0xF2,  0x4A,  0x44,  0x49,  0x28,  0x4F, 	/* 40240 */
+	0xFF,  0x7C,  0x21,  0x48,  0x94,  0x4A,  0x92,  0x4A,  0x45,  0x7C,  0x3D,  0x48,  0x40,  0x48,  0xFC,  0x4B, 	/* 40250 */
+	0x48,  0x78,  0x30,  0x00,  0xCC,  0x0F,  0x03,  0xBB,  0x00,  0x20,  0x78,  0x7C,  0x49,  0x88,  0x4F,  0xFF, 	/* 40260 */
+	0x49,  0x2A,  0x79,  0x46,  0x49,  0xBC,  0x49,  0x00,  0x49,  0xFF,  0x79,  0x00,  0x49,  0x3C,  0x49,  0x00, 	/* 40270 */
+	0x4A,  0x7E,  0x7A,  0x42,  0x04,  0x7E,  0x00,  0x00,  0xBC,  0x00,  0x20,  0x78,  0x20,  0x48,  0x50,  0x48, 	/* 40280 */
+	0x88,  0x49,  0x04,  0x7A,  0xFA,  0x4C,  0x01,  0x4B,  0xDE,  0x4A,  0x52,  0x7A,  0x52,  0x4B,  0xDE,  0x49, 	/* 40290 */
+	0x08,  0x49,  0x08,  0x79,  0x8C,  0x02,  0x52,  0x04,  0x22,  0xBD,  0x08,  0x08,  0x7F,  0xFF,  0x08,  0x08, 	/* 402A0 */
+	0x7F,  0x7E,  0x22,  0x24,  0x3E,  0x18,  0x23,  0x94,  0x1C,  0x62,  0x6F,  0xF9,  0x08,  0x08,  0x0F,  0xF8, 	/* 402B0 */
+	0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0xBF,  0x1F,  0x3E,  0x11,  0x22,  0x1F, 	/* 402C0 */
+	0x3E,  0x11,  0x22,  0x1F,  0x3E,  0x11,  0x22,  0x1F,  0x3E,  0x04,  0x20,  0x0F,  0xFE,  0x18,  0x40,  0x6F, 	/* 402D0 */
+	0xFC,  0x08,  0x40,  0x0F,  0xFC,  0x08,  0x40,  0x0F,  0xFF,  0x00,  0x00,  0x87,  0x00,  0x48,  0x7B,  0xFF, 	/* 402E0 */
+	0x48,  0x48,  0x4B,  0xFF,  0x4A,  0x01,  0x7A,  0xFD,  0x48,  0x00,  0x4B,  0xFF,  0x48,  0x42,  0x78,  0xAC, 	/* 402F0 */
+	0x4B,  0x58,  0x48,  0x94,  0x4B,  0x34,  0x78,  0xD2,  0x03,  0x11,  0x00,  0x60,  0x8D,  0x1F,  0x3E,  0x11, 	/* 40300 */
+	0x22,  0x1F,  0x3E,  0x11,  0x22,  0x1F,  0x3E,  0x11,  0x22,  0x1F,  0xFF,  0x08,  0x40,  0x1F,  0xFC,  0x68, 	/* 40310 */
+	0x40,  0x0F,  0xFC,  0x08,  0x40,  0x3F,  0xFE,  0x06,  0x18,  0x01,  0xE0,  0x3E,  0x1F,  0x97,  0x00,  0x80, 	/* 40320 */
+	0x0F,  0xFC,  0x00,  0x80,  0x13,  0xF0,  0x12,  0x10,  0x13,  0xF0,  0x1F,  0xFE,  0x08,  0x08,  0x7F,  0x7F, 	/* 40330 */
+	0x08,  0x08,  0x5E,  0x5E,  0x52,  0x52,  0x5E,  0x5E,  0x52,  0x52,  0x7F,  0x7F,  0x00,  0x00,  0x9A,  0x00, 	/* 40340 */
+	0x00,  0x77,  0xFE,  0x54,  0x02,  0x57,  0xFE,  0x75,  0xE7,  0x54,  0x20,  0x55,  0xFE,  0x55,  0x4A,  0x75, 	/* 40350 */
+	0xFE,  0x54,  0x40,  0x54,  0xFE,  0x75,  0xAA,  0x0A,  0xFA,  0x08,  0x2A,  0x11,  0xF6,  0x00,  0x0C,  0x9B, 	/* 40360 */
+	0x00,  0x00,  0x1F,  0xF8,  0x00,  0x10,  0x03,  0x20,  0x00,  0xC0,  0x00,  0x40,  0x3F,  0xFE,  0x00,  0x42, 	/* 40370 */
+	0x00,  0xC4,  0x01,  0x48,  0x02,  0x40,  0x04,  0x40,  0x18,  0x40,  0x60,  0x40,  0x00,  0x40,  0x00,  0xC0, 	/* 40380 */
+	0x9C,  0x00,  0x10,  0x3F,  0x10,  0x01,  0x28,  0x1A,  0x28,  0x04,  0x44,  0x7F,  0x42,  0x05,  0xBD,  0x0D, 	/* 40390 */
+	0x00,  0x0E,  0x00,  0x14,  0xFC,  0x14,  0x04,  0x24,  0x04,  0x44,  0x08,  0x04,  0x08,  0x04,  0x10,  0x0C, 	/* 403A0 */
+	0x10,  0xA2,  0x04,  0x00,  0x04,  0x00,  0x07,  0xFE,  0x08,  0x80,  0x08,  0x80,  0x10,  0x80,  0x20,  0x80, 	/* 403B0 */
+	0x7F,  0xFF,  0x01,  0x40,  0x01,  0x40,  0x02,  0x20,  0x02,  0x20,  0x04,  0x10,  0x08,  0x08,  0x10,  0x04, 	/* 403C0 */
+	0x60,  0x03,  0xA3,  0x01,  0x00,  0x01,  0x20,  0x02,  0x18,  0x04,  0x74,  0x3F,  0x82,  0x04,  0x00,  0x04, 	/* 403D0 */
+	0x00,  0x0F,  0xFC,  0x08,  0x80,  0x10,  0x80,  0x7F,  0xFF,  0x01,  0x40,  0x02,  0x20,  0x04,  0x10,  0x18, 	/* 403E0 */
+	0x0C,  0x60,  0x03,  0xA5,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x1F,  0xFE,  0x24,  0x42,  0x24,  0x42, 	/* 403F0 */
+	0x44,  0x42,  0x04,  0x42,  0x7F,  0xC2,  0x04,  0x42,  0x0A,  0x42,  0x09,  0x42,  0x11,  0x7E,  0x10,  0x80, 	/* 40400 */
+	0x20,  0x80,  0x40,  0x00,  0xA7,  0x10,  0x02,  0x11,  0xF2,  0x10,  0x12,  0x3F,  0x12,  0x28,  0x12,  0x48, 	/* 40410 */
+	0xF2,  0x08,  0x82,  0x7F,  0x82,  0x08,  0x82,  0x08,  0xF2,  0x0C,  0x12,  0x12,  0x12,  0x12,  0x12,  0x21, 	/* 40420 */
+	0x12,  0x40,  0x22,  0x00,  0xC2,  0xA9,  0x10,  0x00,  0x10,  0xFE,  0x10,  0x80,  0x1F,  0x80,  0x28,  0x80, 	/* 40430 */
+	0x28,  0xFC,  0x48,  0x84,  0x08,  0x84,  0x7F,  0x84,  0x08,  0xFC,  0x14,  0x80,  0x12,  0x80,  0x12,  0x80, 	/* 40440 */
+	0x22,  0x80,  0x20,  0xFF,  0x40,  0x00,  0xAD,  0x00,  0x00,  0x11,  0xFE,  0x10,  0x00,  0x1F,  0x00,  0x28, 	/* 40450 */
+	0xFC,  0x28,  0x84,  0x48,  0x84,  0x08,  0x84,  0x7F,  0xFC,  0x08,  0x04,  0x08,  0x84,  0x14,  0x48,  0x12, 	/* 40460 */
+	0x48,  0x22,  0x10,  0x21,  0xFE,  0x40,  0x00,  0xAE,  0x10,  0x04,  0x10,  0x18,  0x1E,  0xF0,  0x28,  0x10, 	/* 40470 */
+	0x29,  0xFF,  0x48,  0x38,  0x08,  0x54,  0x7F,  0x93,  0x08,  0x30,  0x08,  0x20,  0x0D,  0xFF,  0x12,  0x24, 	/* 40480 */
+	0x12,  0x44,  0x22,  0x78,  0x40,  0x24,  0x01,  0xC2,  0xAF,  0x10,  0x0C,  0x11,  0xF0,  0x10,  0x20,  0x3F, 	/* 40490 */
+	0xFF,  0x28,  0x48,  0x48,  0xFC,  0x09,  0x4B,  0x7E,  0x78,  0x08,  0x00,  0x09,  0xFE,  0x15,  0x02,  0x13, 	/* 404A0 */
+	0x7A,  0x23,  0x4A,  0x21,  0x7A,  0x41,  0x02,  0x01,  0x06,  0xB3,  0x00,  0x00,  0x3F,  0xFF,  0x01,  0x00, 	/* 404B0 */
+	0x01,  0x00,  0x01,  0x00,  0x02,  0x00,  0x02,  0x00,  0x07,  0xFC,  0x04,  0x04,  0x0C,  0x04,  0x0C,  0x04, 	/* 404C0 */
+	0x14,  0x04,  0x24,  0x04,  0x44,  0x04,  0x07,  0xFC,  0x00,  0x00,  0xBC,  0x00,  0x00,  0x7E,  0xFE,  0x08, 	/* 404D0 */
+	0x10,  0x08,  0x10,  0x08,  0x10,  0x10,  0x10,  0x1E,  0x10,  0x12,  0x10,  0x32,  0x10,  0x52,  0x10,  0x12, 	/* 404E0 */
+	0x10,  0x12,  0x10,  0x1E,  0x10,  0x00,  0x10,  0x01,  0xFF,  0x00,  0x00,  0x82,  0x00,  0x10,  0x7F,  0x10, 	/* 404F0 */
+	0x08,  0x10,  0x08,  0x58,  0x08,  0x54,  0x08,  0x52,  0x1E,  0x92,  0x12,  0x91,  0x33,  0x15,  0x32,  0x14, 	/* 40500 */
+	0x52,  0x38,  0x12,  0x08,  0x1E,  0x10,  0x00,  0x20,  0x00,  0xC0,  0x03,  0x00,  0x8C,  0x01,  0x00,  0x7F, 	/* 40510 */
+	0x7E,  0x11,  0x12,  0x11,  0x52,  0x11,  0x92,  0x17,  0x12,  0x3D,  0x12,  0x25,  0x12,  0x65,  0x12,  0x25, 	/* 40520 */
+	0x52,  0x25,  0x52,  0x24,  0xE2,  0x3C,  0x22,  0x00,  0x42,  0x01,  0x82,  0x06,  0x0C,  0x92,  0x00,  0x88, 	/* 40530 */
+	0x7F,  0x88,  0x08,  0x88,  0x08,  0x88,  0x08,  0x89,  0x10,  0x89,  0x1E,  0xFA,  0x12,  0x8C,  0x32,  0x88, 	/* 40540 */
+	0x52,  0x88,  0x12,  0x88,  0x12,  0x88,  0x1E,  0x88,  0x00,  0xB9,  0x00,  0xC9,  0x03,  0x07,  0x94,  0x00, 	/* 40550 */
+	0x00,  0x7F,  0xFE,  0x08,  0x44,  0x08,  0x44,  0x08,  0x44,  0x08,  0x44,  0x10,  0x44,  0x1F,  0xFF,  0x12, 	/* 40560 */
+	0x44,  0x32,  0x44,  0x52,  0x44,  0x12,  0x44,  0x12,  0x44,  0x1E,  0x84,  0x00,  0x84,  0x01,  0x04,  0x95, 	/* 40570 */
+	0x00,  0x40,  0x7F,  0x40,  0x09,  0xF8,  0x08,  0x48,  0x08,  0x48,  0x08,  0x49,  0x1E,  0x89,  0x13,  0x27, 	/* 40580 */
+	0x32,  0x20,  0x32,  0x20,  0x53,  0xFE,  0x12,  0x20,  0x1E,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20, 	/* 40590 */
+	0xA0,  0x00,  0x00,  0x7F,  0x7C,  0x08,  0x44,  0x08,  0x44,  0x08,  0x44,  0x10,  0x7C,  0x1E,  0x44,  0x12, 	/* 405A0 */
+	0x44,  0x32,  0x44,  0x52,  0x7C,  0x12,  0x44,  0x12,  0x44,  0x1E,  0x44,  0x00,  0x44,  0x01,  0xFF,  0x00, 	/* 405B0 */
+	0x00,  0xA5,  0x00,  0x04,  0x7F,  0x18,  0x08,  0xF0,  0x08,  0x90,  0x08,  0x90,  0x08,  0x90,  0x1E,  0xFF, 	/* 405C0 */
+	0x12,  0x90,  0x32,  0x90,  0x32,  0x88,  0x52,  0x88,  0x12,  0xC8,  0x1F,  0x84,  0x02,  0x05,  0x01,  0xF3, 	/* 405D0 */
+	0x00,  0x01,  0xA6,  0x04,  0x20,  0x04,  0x22,  0x14,  0x24,  0x17,  0xB8,  0x14,  0x20,  0x14,  0x21,  0x17, 	/* 405E0 */
+	0xA1,  0x1C,  0x1F,  0x30,  0x00,  0x7F,  0xFF,  0x02,  0x00,  0x07,  0xFC,  0x0C,  0x04,  0x14,  0x04,  0x67, 	/* 405F0 */
+	0xFC,  0x00,  0x00,  0xA7,  0x00,  0x20,  0x7F,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x3E,  0x08,  0x20, 	/* 40600 */
+	0x1E,  0x20,  0x12,  0x20,  0x32,  0x20,  0x32,  0xFC,  0x52,  0x84,  0x12,  0x84,  0x1E,  0x84,  0x00,  0x84, 	/* 40610 */
+	0x00,  0xFC,  0x00,  0x00,  0xB2,  0x00,  0x40,  0x7F,  0x40,  0x08,  0x7E,  0x08,  0x42,  0x08,  0x82,  0x10, 	/* 40620 */
+	0xFA,  0x1F,  0x0A,  0x32,  0x0A,  0x32,  0x7A,  0x52,  0x42,  0x12,  0x4C,  0x12,  0x40,  0x12,  0x40,  0x1E, 	/* 40630 */
+	0x42,  0x00,  0x22,  0x00,  0x1E,  0xB4,  0x00,  0x10,  0x7F,  0x10,  0x08,  0x10,  0x08,  0xFF,  0x08,  0x92, 	/* 40640 */
+	0x10,  0x94,  0x1E,  0x90,  0x32,  0xFE,  0x32,  0xC4,  0x52,  0xC4,  0x12,  0xA4,  0x12,  0xA8,  0x1E,  0x90, 	/* 40650 */
+	0x01,  0x18,  0x01,  0x24,  0x02,  0x43,  0xBA,  0x00,  0x00,  0x7F,  0xFF,  0x08,  0x80,  0x08,  0x80,  0x08, 	/* 40660 */
+	0xFF,  0x08,  0x90,  0x1E,  0x90,  0x12,  0x9E,  0x32,  0x92,  0x32,  0x92,  0x52,  0x92,  0x12,  0xA2,  0x1F, 	/* 40670 */
+	0x22,  0x01,  0x22,  0x02,  0x42,  0x04,  0x8C,  0xBF,  0x00,  0x08,  0x7F,  0x08,  0x08,  0x08,  0x08,  0x7F, 	/* 40680 */
+	0x08,  0x40,  0x10,  0x48,  0x1E,  0x48,  0x32,  0x48,  0x32,  0x48,  0x52,  0x48,  0x12,  0x54,  0x12,  0x92, 	/* 40690 */
+	0x1E,  0x92,  0x12,  0xAF,  0x11,  0x71,  0x02,  0x01,  0x85,  0x00,  0x10,  0x7F,  0x10,  0x08,  0xFE,  0x08, 	/* 406A0 */
+	0x10,  0x08,  0x10,  0x10,  0x10,  0x1F,  0xFF,  0x12,  0x00,  0x32,  0x10,  0x52,  0x10,  0x12,  0xFE,  0x12, 	/* 406B0 */
+	0x10,  0x1E,  0x10,  0x00,  0x10,  0x03,  0xFF,  0x00,  0x00,  0x9D,  0x00,  0x10,  0x7F,  0x92,  0x08,  0x52, 	/* 406C0 */
+	0x08,  0x54,  0x08,  0x10,  0x10,  0x7E,  0x1E,  0x42,  0x32,  0x42,  0x32,  0x7E,  0x52,  0x42,  0x12,  0x42, 	/* 406D0 */
+	0x12,  0x7E,  0x12,  0x42,  0x1E,  0x42,  0x00,  0x42,  0x00,  0x46,  0xAB,  0x00,  0x20,  0x7E,  0x20,  0x09, 	/* 406E0 */
+	0xFF,  0x08,  0x20,  0x08,  0x58,  0x10,  0x8C,  0x1F,  0xF2,  0x32,  0x00,  0x32,  0xA4,  0x52,  0xA4,  0x12, 	/* 406F0 */
+	0xA4,  0x12,  0xA4,  0x1E,  0xA4,  0x01,  0x25,  0x01,  0x05,  0x02,  0x03,  0xAC,  0x00,  0x00,  0x7F,  0xFF, 	/* 40700 */
+	0x08,  0x10,  0x08,  0xFE,  0x08,  0x92,  0x10,  0x92,  0x1E,  0xFE,  0x12,  0x92,  0x32,  0x92,  0x52,  0xFE, 	/* 40710 */
+	0x12,  0x50,  0x12,  0x20,  0x1E,  0x20,  0x00,  0x50,  0x01,  0x8C,  0x06,  0x03,  0xAF,  0x00,  0x00,  0x7F, 	/* 40720 */
+	0xFE,  0x08,  0x42,  0x08,  0x42,  0x08,  0x7E,  0x10,  0x42,  0x1E,  0x42,  0x32,  0x7E,  0x32,  0x42,  0x52, 	/* 40730 */
+	0x42,  0x12,  0x7E,  0x12,  0x28,  0x1E,  0x28,  0x00,  0x49,  0x00,  0x89,  0x03,  0x07,  0xB2,  0x00,  0x44, 	/* 40740 */
+	0x7F,  0x44,  0x04,  0x42,  0x04,  0x52,  0x08,  0x92,  0x09,  0x28,  0x1E,  0x28,  0x12,  0x44,  0x32,  0x82, 	/* 40750 */
+	0x53,  0x7D,  0x12,  0x44,  0x12,  0x44,  0x1E,  0x44,  0x00,  0x44,  0x00,  0x7C,  0x00,  0x00,  0xB4,  0x00, 	/* 40760 */
+	0x48,  0x7F,  0x48,  0x09,  0xFF,  0x08,  0x48,  0x08,  0x48,  0x10,  0x28,  0x1E,  0x29,  0x12,  0x49,  0x32, 	/* 40770 */
+	0x4A,  0x52,  0xCC,  0x13,  0x48,  0x12,  0x48,  0x1E,  0x48,  0x00,  0x49,  0x00,  0x49,  0x00,  0x47,  0xBC, 	/* 40780 */
+	0x00,  0x00,  0x7F,  0xEE,  0x08,  0xAA,  0x08,  0xAA,  0x08,  0xAA,  0x10,  0xEE,  0x1E,  0xAA,  0x12,  0xAA, 	/* 40790 */
+	0x32,  0xAA,  0x52,  0xEE,  0x12,  0xAA,  0x12,  0xAA,  0x1E,  0xAA,  0x01,  0x32,  0x01,  0x22,  0x02,  0x66, 	/* 407A0 */
+	0x81,  0x04,  0x10,  0x04,  0x10,  0x3F,  0xFE,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x07,  0xF0,  0x04, 	/* 407B0 */
+	0x10,  0x7F,  0xFF,  0x04,  0x10,  0x0F,  0xF8,  0x11,  0x04,  0x63,  0xF3,  0x0E,  0x10,  0x33,  0xF0,  0x02, 	/* 407C0 */
+	0x10,  0x86,  0x10,  0x20,  0x08,  0x20,  0x49,  0xFF,  0x21,  0x22,  0x21,  0xFC,  0x09,  0x44,  0x12,  0x68, 	/* 407D0 */
+	0x22,  0x38,  0x44,  0x4C,  0x09,  0x83,  0x7F,  0xFE,  0x02,  0x00,  0x07,  0xFC,  0x1C,  0x04,  0x67,  0xFC, 	/* 407E0 */
+	0x00,  0x00,  0x87,  0x00,  0x10,  0x7F,  0x10,  0x09,  0xFE,  0x09,  0x02,  0x09,  0x02,  0x10,  0xFC,  0x1E, 	/* 407F0 */
+	0x10,  0x32,  0x10,  0x32,  0x50,  0x52,  0x5E,  0x12,  0x50,  0x12,  0x50,  0x1E,  0xD0,  0x00,  0xB0,  0x01, 	/* 40800 */
+	0x18,  0x02,  0x07,  0x8C,  0x00,  0x20,  0x7F,  0x3C,  0x08,  0x44,  0x08,  0x48,  0x08,  0xF8,  0x10,  0x08, 	/* 40810 */
+	0x1F,  0xFF,  0x12,  0x10,  0x32,  0x92,  0x52,  0x5A,  0x12,  0x5C,  0x12,  0x34,  0x1E,  0xD2,  0x03,  0x11, 	/* 40820 */
+	0x00,  0x10,  0x00,  0x30,  0x8D,  0x00,  0x00,  0x7F,  0x7C,  0x08,  0x44,  0x08,  0x7C,  0x08,  0x44,  0x10, 	/* 40830 */
+	0x44,  0x1E,  0x7C,  0x32,  0x00,  0x33,  0xFE,  0x52,  0x04,  0x13,  0xFF,  0x12,  0x84,  0x1E,  0x44,  0x00, 	/* 40840 */
+	0x44,  0x00,  0x04,  0x00,  0x0C,  0x8E,  0x00,  0x10,  0x7F,  0x10,  0x08,  0xFF,  0x08,  0x00,  0x08,  0x44, 	/* 40850 */
+	0x10,  0x44,  0x1E,  0x64,  0x12,  0x8A,  0x33,  0x10,  0x52,  0x10,  0x13,  0xFF,  0x12,  0x10,  0x1E,  0x10, 	/* 40860 */
+	0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x91,  0x00,  0x10,  0x3F,  0x20,  0x08,  0xFE,  0x08,  0x92,  0x08, 	/* 40870 */
+	0x92,  0x08,  0xFE,  0x1E,  0x92,  0x12,  0x92,  0x32,  0xFE,  0x52,  0x28,  0x12,  0x48,  0x13,  0xFF,  0x1E, 	/* 40880 */
+	0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x93,  0x00,  0x24,  0x00,  0x24,  0x7F,  0x48,  0x08,  0xFF, 	/* 40890 */
+	0x08,  0x88,  0x09,  0x88,  0x10,  0x88,  0x1E,  0xFE,  0x32,  0x88,  0x32,  0x88,  0x52,  0xFE,  0x12,  0x88, 	/* 408A0 */
+	0x12,  0x88,  0x1E,  0x88,  0x00,  0xFF,  0x00,  0x00,  0x95,  0x00,  0x20,  0x7F,  0x20,  0x08,  0xFE,  0x08, 	/* 408B0 */
+	0x50,  0x08,  0x88,  0x09,  0x04,  0x1E,  0x00,  0x13,  0xFF,  0x32,  0x04,  0x32,  0xE4,  0x52,  0xA4,  0x12, 	/* 408C0 */
+	0xA4,  0x12,  0xA4,  0x1E,  0xE4,  0x00,  0x04,  0x00,  0x0C,  0x97,  0x00,  0x10,  0x7F,  0x10,  0x09,  0xFF, 	/* 408D0 */
+	0x09,  0x01,  0x09,  0x41,  0x10,  0x4E,  0x1E,  0xFA,  0x32,  0x9A,  0x32,  0x9A,  0x53,  0x2A,  0x12,  0xAA, 	/* 408E0 */
+	0x12,  0x4C,  0x1E,  0x48,  0x00,  0x89,  0x01,  0x09,  0x06,  0x07,  0x9A,  0x00,  0x20,  0x7F,  0x20,  0x09, 	/* 408F0 */
+	0xFE,  0x08,  0x84,  0x08,  0x44,  0x10,  0x48,  0x1E,  0x48,  0x13,  0xFF,  0x32,  0x00,  0x52,  0x00,  0x12, 	/* 40900 */
+	0xFC,  0x12,  0x84,  0x1E,  0x84,  0x00,  0x84,  0x00,  0xFC,  0x00,  0x00,  0xA3,  0x00,  0x00,  0x7F,  0xFC, 	/* 40910 */
+	0x08,  0x84,  0x08,  0xFC,  0x08,  0x84,  0x10,  0x84,  0x1E,  0xFC,  0x12,  0x40,  0x32,  0x7E,  0x52,  0x92, 	/* 40920 */
+	0x13,  0x9A,  0x12,  0xAA,  0x1E,  0xC2,  0x00,  0xFA,  0x00,  0x02,  0x00,  0x0C,  0xA7,  0x00,  0x10,  0x7E, 	/* 40930 */
+	0x20,  0x08,  0xFC,  0x08,  0x84,  0x7E,  0x84,  0x08,  0xFC,  0x08,  0x84,  0x0E,  0x84,  0x70,  0xFC,  0x00, 	/* 40940 */
+	0x00,  0x7F,  0xFF,  0x01,  0x00,  0x07,  0xF8,  0x1C,  0x08,  0x64,  0x08,  0x07,  0xF8,  0xA9,  0x00,  0x00, 	/* 40950 */
+	0x7F,  0xFF,  0x04,  0x10,  0x04,  0x20,  0x08,  0x7E,  0x08,  0x42,  0x1F,  0x42,  0x11,  0x7E,  0x31,  0x42, 	/* 40960 */
+	0x51,  0x7E,  0x11,  0x42,  0x11,  0x42,  0x1F,  0x7E,  0x00,  0x24,  0x00,  0xC2,  0x03,  0x01,  0xAA,  0x00, 	/* 40970 */
+	0x44,  0x7F,  0x44,  0x09,  0xFF,  0x08,  0x44,  0x08,  0x7C,  0x10,  0x44,  0x1E,  0x7C,  0x12,  0x44,  0x32, 	/* 40980 */
+	0x44,  0x53,  0xFF,  0x12,  0xA8,  0x12,  0xAA,  0x1E,  0xC6,  0x00,  0x80,  0x00,  0xFF,  0x00,  0x00,  0xAF, 	/* 40990 */
+	0x00,  0x92,  0x7E,  0x92,  0x09,  0x24,  0x0B,  0x6C,  0x08,  0x92,  0x10,  0x92,  0x1E,  0x40,  0x12,  0xFE, 	/* 409A0 */
+	0x32,  0x8A,  0x52,  0xEA,  0x12,  0x92,  0x12,  0xAA,  0x1E,  0xC6,  0x00,  0x82,  0x00,  0xFE,  0x00,  0x00, 	/* 409B0 */
+	0xB5,  0x00,  0x10,  0x7F,  0x10,  0x08,  0x1F,  0x08,  0x10,  0x08,  0x7E,  0x10,  0x42,  0x1E,  0x42,  0x12, 	/* 409C0 */
+	0x7E,  0x32,  0x42,  0x52,  0x7E,  0x12,  0x42,  0x12,  0x42,  0x1E,  0x7E,  0x00,  0x24,  0x00,  0xC2,  0x03, 	/* 409D0 */
+	0x01,  0xBA,  0x00,  0x20,  0x7F,  0x20,  0x09,  0xFF,  0x09,  0x21,  0x09,  0x25,  0x08,  0x48,  0x1E,  0x7F, 	/* 409E0 */
+	0x12,  0xC8,  0x33,  0x48,  0x32,  0x7E,  0x52,  0x48,  0x12,  0x7E,  0x12,  0x48,  0x1E,  0x48,  0x00,  0x7F, 	/* 409F0 */
+	0x00,  0x00,  0xBC,  0x00,  0x00,  0x7F,  0xFF,  0x08,  0x90,  0x08,  0x90,  0x08,  0xFE,  0x10,  0x90,  0x1E, 	/* 40A00 */
+	0xFE,  0x12,  0x90,  0x32,  0x90,  0x52,  0xFE,  0x12,  0x0A,  0x13,  0xA6,  0x1F,  0x56,  0x01,  0x52,  0x02, 	/* 40A10 */
+	0x02,  0x00,  0x0C,  0xBE,  0x00,  0x00,  0x7F,  0xFE,  0x08,  0x82,  0x08,  0x82,  0x08,  0xFE,  0x10,  0xA8, 	/* 40A20 */
+	0x1E,  0xA8,  0x12,  0xFE,  0x32,  0xA8,  0x52,  0xA8,  0x12,  0xFF,  0x13,  0x52,  0x1F,  0x54,  0x02,  0x48, 	/* 40A30 */
+	0x04,  0x66,  0x01,  0x81,  0x81,  0x00,  0x84,  0x00,  0x44,  0x7E,  0x48,  0x13,  0xFF,  0x10,  0x88,  0x10, 	/* 40A40 */
+	0x88,  0x12,  0xA8,  0x3D,  0x32,  0x24,  0xAA,  0x64,  0xCC,  0x24,  0x44,  0x24,  0x88,  0x24,  0xCC,  0x3D, 	/* 40A50 */
+	0x32,  0x07,  0xFF,  0x00,  0x11,  0x85,  0x00,  0x10,  0x7F,  0x10,  0x09,  0xFF,  0x08,  0x44,  0x08,  0x28, 	/* 40A60 */
+	0x10,  0xFF,  0x1E,  0x81,  0x12,  0x91,  0x32,  0x10,  0x53,  0xFF,  0x12,  0x20,  0x12,  0x3C,  0x1E,  0x24, 	/* 40A70 */
+	0x00,  0x44,  0x00,  0x84,  0x03,  0x18,  0x86,  0x00,  0x00,  0x7F,  0x7C,  0x08,  0x44,  0x08,  0x5C,  0x08, 	/* 40A80 */
+	0x54,  0x10,  0x54,  0x1E,  0xFF,  0x12,  0x81,  0x32,  0xFD,  0x52,  0x44,  0x12,  0x7C,  0x12,  0x44,  0x1E, 	/* 40A90 */
+	0x7C,  0x00,  0x44,  0x00,  0x44,  0x00,  0x4C,  0x8A,  0x00,  0x00,  0x1F,  0xFE,  0x01,  0x00,  0x02,  0x00, 	/* 40AA0 */
+	0x07,  0xF8,  0x1A,  0x08,  0x02,  0x08,  0x03,  0xF8,  0x00,  0x00,  0x7F,  0xFF,  0x08,  0x10,  0x1F,  0x3E, 	/* 40AB0 */
+	0x31,  0x62,  0x51,  0xA2,  0x1F,  0x3E,  0x00,  0x00,  0x8B,  0x00,  0x42,  0x7F,  0x24,  0x09,  0xFF,  0x08, 	/* 40AC0 */
+	0x10,  0x08,  0xFE,  0x10,  0x10,  0x1E,  0x10,  0x13,  0xFF,  0x32,  0x20,  0x52,  0x20,  0x12,  0x7E,  0x12, 	/* 40AD0 */
+	0x88,  0x1F,  0x08,  0x02,  0x08,  0x00,  0xFF,  0x00,  0x00,  0x90,  0x04,  0x00,  0x1F,  0x3C,  0x11,  0x25, 	/* 40AE0 */
+	0x15,  0x47,  0x7F,  0x80,  0x11,  0x7C,  0x15,  0x24,  0x15,  0x18,  0x23,  0x24,  0x40,  0x43,  0x7F,  0xFF, 	/* 40AF0 */
+	0x02,  0x00,  0x07,  0xFC,  0x1C,  0x04,  0x67,  0xFC,  0x00,  0x00,  0x91,  0x00,  0x10,  0x7F,  0x92,  0x08, 	/* 40B00 */
+	0x92,  0x08,  0xFE,  0x08,  0x00,  0x11,  0xFF,  0x1E,  0x00,  0x12,  0xFE,  0x32,  0x82,  0x52,  0x82,  0x12, 	/* 40B10 */
+	0xFE,  0x12,  0x44,  0x1E,  0x24,  0x00,  0x28,  0x01,  0xFF,  0x00,  0x00,  0x94,  0x00,  0x84,  0x7F,  0xE4, 	/* 40B20 */
+	0x08,  0xBF,  0x09,  0xB4,  0x09,  0x54,  0x10,  0x54,  0x1E,  0xBF,  0x13,  0x04,  0x32,  0x04,  0x52,  0x10, 	/* 40B30 */
+	0x13,  0xFF,  0x12,  0x38,  0x1E,  0x54,  0x00,  0x92,  0x03,  0x11,  0x00,  0x10,  0x9A,  0x00,  0x20,  0x7F, 	/* 40B40 */
+	0x20,  0x09,  0xFF,  0x08,  0x20,  0x08,  0xFC,  0x10,  0xA4,  0x1E,  0xFC,  0x12,  0xA4,  0x32,  0xFC,  0x52, 	/* 40B50 */
+	0x22,  0x13,  0xFD,  0x12,  0x08,  0x1F,  0xFF,  0x00,  0x88,  0x00,  0x48,  0x00,  0x18,  0xA7,  0x00,  0x20, 	/* 40B60 */
+	0x7F,  0xFE,  0x08,  0x20,  0x08,  0xFC,  0x08,  0x20,  0x11,  0xFF,  0x1E,  0x00,  0x12,  0xFC,  0x32,  0x84, 	/* 40B70 */
+	0x52,  0xFC,  0x12,  0x84,  0x12,  0xFC,  0x1E,  0x84,  0x00,  0xFC,  0x00,  0xCC,  0x07,  0x02,  0xA8,  0x00, 	/* 40B80 */
+	0x40,  0x00,  0x40,  0x1F,  0xFE,  0x11,  0x08,  0x1F,  0xFE,  0x13,  0x88,  0x15,  0x5C,  0x19,  0x2A,  0x11, 	/* 40B90 */
+	0x09,  0x1F,  0xFE,  0x10,  0x80,  0x13,  0xF8,  0x26,  0x08,  0x3A,  0x08,  0x43,  0xF8,  0x00,  0x00,  0xAC, 	/* 40BA0 */
+	0x04,  0x00,  0x7F,  0xBC,  0x04,  0x24,  0x3F,  0x25,  0x00,  0x43,  0x3F,  0xFD,  0x25,  0x24,  0x3F,  0x18, 	/* 40BB0 */
+	0x20,  0x24,  0x40,  0xC3,  0x3F,  0xFE,  0x02,  0x00,  0x07,  0xF8,  0x1C,  0x08,  0x67,  0xF8,  0x00,  0x00, 	/* 40BC0 */
+	0xAF,  0x00,  0xA4,  0x7E,  0xA4,  0x13,  0x78,  0x10,  0xA4,  0x10,  0xAA,  0x11,  0x7D,  0x27,  0xE4,  0x3C, 	/* 40BD0 */
+	0x22,  0x27,  0xFF,  0x64,  0x94,  0x24,  0x94,  0x24,  0xC8,  0x3D,  0x29,  0x01,  0x15,  0x02,  0x23,  0x04, 	/* 40BE0 */
+	0x41,  0xB4,  0x00,  0xEA,  0x7F,  0x2C,  0x09,  0x29,  0x08,  0xC6,  0x08,  0x44,  0x10,  0xFE,  0x1F,  0x01, 	/* 40BF0 */
+	0x12,  0x7C,  0x32,  0x44,  0x52,  0x44,  0x12,  0x7C,  0x12,  0x00,  0x1E,  0x44,  0x00,  0x28,  0x03,  0xFF, 	/* 40C00 */
+	0x00,  0x00,  0xBD,  0x00,  0x10,  0x7F,  0x7E,  0x08,  0x10,  0x09,  0xFF,  0x08,  0x00,  0x10,  0x44,  0x1F, 	/* 40C10 */
+	0xFF,  0x12,  0x44,  0x32,  0x74,  0x53,  0xCF,  0x12,  0x00,  0x13,  0xFF,  0x1E,  0x48,  0x00,  0x49,  0x00, 	/* 40C20 */
+	0x89,  0x03,  0x07,  0x81,  0x00,  0x48,  0x7F,  0x50,  0x08,  0xFF,  0x09,  0x90,  0x0A,  0x90,  0x10,  0xFE, 	/* 40C30 */
+	0x1E,  0x90,  0x32,  0x90,  0x32,  0xFE,  0x52,  0x90,  0x12,  0x90,  0x12,  0xFF,  0x1E,  0x04,  0x01,  0x52, 	/* 40C40 */
+	0x01,  0x29,  0x02,  0x29,  0x87,  0x00,  0x20,  0x7E,  0x40,  0x11,  0xFE,  0x11,  0x0A,  0x11,  0x72,  0x11, 	/* 40C50 */
+	0xAA,  0x3D,  0x72,  0x25,  0xFE,  0x65,  0x72,  0x25,  0xAA,  0x24,  0x20,  0x27,  0xFF,  0x3C,  0x30,  0x00, 	/* 40C60 */
+	0x48,  0x01,  0x84,  0x06,  0x03,  0x8E,  0x00,  0x44,  0x7F,  0x44,  0x09,  0xFF,  0x08,  0x44,  0x08,  0xEE, 	/* 40C70 */
+	0x11,  0x55,  0x1E,  0x44,  0x12,  0x44,  0x33,  0xFF,  0x52,  0x12,  0x12,  0x90,  0x12,  0x9E,  0x1E,  0xD0, 	/* 40C80 */
+	0x00,  0xB0,  0x01,  0x18,  0x02,  0x07,  0x91,  0x01,  0x12,  0x00,  0x92,  0x7E,  0x94,  0x09,  0xFF,  0x09, 	/* 40C90 */
+	0x01,  0x09,  0x7D,  0x10,  0x44,  0x1E,  0x7C,  0x12,  0x00,  0x32,  0xFE,  0x52,  0x92,  0x12,  0x92,  0x12, 	/* 40CA0 */
+	0xFE,  0x1E,  0x92,  0x00,  0xFE,  0x00,  0x00,  0x92,  0x00,  0x42,  0x7E,  0x24,  0x09,  0xFE,  0x08,  0x10, 	/* 40CB0 */
+	0x08,  0xFE,  0x10,  0x10,  0x1F,  0xFF,  0x12,  0x24,  0x32,  0xCA,  0x52,  0x48,  0x13,  0xFF,  0x12,  0x4A, 	/* 40CC0 */
+	0x12,  0x6A,  0x1F,  0xC5,  0x00,  0x4B,  0x00,  0xD1,  0x99,  0x02,  0x00,  0x7E,  0x7E,  0x13,  0x82,  0x12, 	/* 40CD0 */
+	0x14,  0x12,  0x48,  0x11,  0xFF,  0x3A,  0x09,  0x2B,  0xCA,  0x2D,  0x28,  0x69,  0x2E,  0x2F,  0xE8,  0x29, 	/* 40CE0 */
+	0x28,  0x29,  0xA8,  0x39,  0x78,  0x02,  0x48,  0x04,  0x87,  0xA6,  0x00,  0x10,  0x7E,  0x10,  0x11,  0xFF, 	/* 40CF0 */
+	0x11,  0x24,  0x11,  0x7E,  0x11,  0x24,  0x3D,  0x3C,  0x25,  0xFF,  0x65,  0x10,  0x25,  0x7E,  0x25,  0x52, 	/* 40D00 */
+	0x25,  0x7E,  0x3E,  0x52,  0x02,  0x7E,  0x04,  0x62,  0x01,  0x81,  0xAA,  0x00,  0x00,  0x7F,  0xFF,  0x11, 	/* 40D10 */
+	0x24,  0x11,  0xFF,  0x11,  0x24,  0x11,  0x7E,  0x3D,  0x52,  0x25,  0x7E,  0x65,  0x52,  0x25,  0x7E,  0x25, 	/* 40D20 */
+	0x10,  0x25,  0xFF,  0x3E,  0x95,  0x02,  0x9B,  0x04,  0xE1,  0x00,  0x83,  0xAB,  0x00,  0x8A,  0x7E,  0x92, 	/* 40D30 */
+	0x08,  0xBA,  0x09,  0x6D,  0x0B,  0x6D,  0x10,  0xBA,  0x1E,  0xAA,  0x13,  0x7D,  0x33,  0x97,  0x52,  0x10, 	/* 40D40 */
+	0x13,  0xFF,  0x12,  0x38,  0x1E,  0x54,  0x00,  0x92,  0x03,  0x11,  0x00,  0x10,  0xAC,  0x09,  0x24,  0x08, 	/* 40D50 */
+	0xC4,  0x7F,  0x3F,  0x09,  0x24,  0x1C,  0xCE,  0x2B,  0x35,  0x48,  0x04,  0x00,  0x80,  0x7F,  0xFF,  0x02, 	/* 40D60 */
+	0x10,  0x1F,  0xEC,  0x61,  0x03,  0x07,  0xF8,  0x3A,  0x08,  0x03,  0xF8,  0x00,  0x00,  0xBA,  0x00,  0x00, 	/* 40D70 */
+	0x00,  0x00,  0x1F,  0xFC,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x80,  0x04,  0x90, 	/* 40D80 */
+	0x04,  0x88,  0x08,  0x84,  0x08,  0x84,  0x10,  0x82,  0x20,  0x82,  0x40,  0x80,  0x01,  0x80,  0xBC,  0x08, 	/* 40D90 */
+	0x40,  0x08,  0x40,  0x08,  0x40,  0x7E,  0x40,  0x02,  0x40,  0x04,  0x40,  0x04,  0x40,  0x08,  0x40,  0x0C, 	/* 40DA0 */
+	0x40,  0x1A,  0x40,  0x29,  0x40,  0x48,  0x42,  0x08,  0x42,  0x08,  0x42,  0x08,  0x3E,  0x08,  0x00,  0xBE, 	/* 40DB0 */
+	0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x7E,  0x10,  0x02,  0x10,  0x04,  0xFE,  0x04,  0x10,  0x08,  0x10, 	/* 40DC0 */
+	0x0C,  0x10,  0x1A,  0x10,  0x29,  0x10,  0x48,  0x10,  0x08,  0x10,  0x08,  0x10,  0x09,  0xFF,  0x08,  0x00, 	/* 40DD0 */
+	0x80,  0x00,  0x00,  0x3E,  0x7E,  0x00,  0x42,  0x00,  0x42,  0x00,  0x42,  0x7F,  0x42,  0x08,  0x42,  0x0A, 	/* 40DE0 */
+	0x7E,  0x2A,  0x40,  0x2A,  0x40,  0x2A,  0x40,  0x2A,  0x40,  0x2A,  0x41,  0x48,  0x41,  0x08,  0x3F,  0x08, 	/* 40DF0 */
+	0x00,  0x81,  0x08,  0x00,  0x08,  0x3E,  0x08,  0x22,  0x7F,  0x22,  0x01,  0x24,  0x02,  0x24,  0x04,  0x28, 	/* 40E00 */
+	0x0C,  0x24,  0x1A,  0x22,  0x29,  0x22,  0x48,  0xA1,  0x08,  0x31,  0x08,  0x29,  0x08,  0x26,  0x08,  0x20, 	/* 40E10 */
+	0x08,  0x20,  0x87,  0x08,  0x04,  0x08,  0x18,  0x08,  0xF0,  0x7E,  0x90,  0x02,  0x90,  0x04,  0x90,  0x04, 	/* 40E20 */
+	0x90,  0x08,  0xFF,  0x1C,  0x90,  0x2A,  0x88,  0x49,  0x88,  0x08,  0x88,  0x08,  0x84,  0x08,  0xB5,  0x08, 	/* 40E30 */
+	0xC3,  0x0B,  0x01,  0x88,  0x08,  0x04,  0x08,  0x18,  0x08,  0xE0,  0x7E,  0x80,  0x02,  0x80,  0x04,  0xFF, 	/* 40E40 */
+	0x04,  0x88,  0x08,  0x88,  0x1C,  0x88,  0x2A,  0x88,  0x49,  0x88,  0x08,  0x88,  0x09,  0x08,  0x09,  0x08, 	/* 40E50 */
+	0x0A,  0x08,  0x08,  0x08,  0x89,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x7E,  0x90,  0x02,  0x90,  0x04, 	/* 40E60 */
+	0x9E,  0x04,  0x90,  0x08,  0x90,  0x0C,  0x90,  0x1A,  0x90,  0x29,  0x90,  0x48,  0x90,  0x08,  0x90,  0x08, 	/* 40E70 */
+	0x90,  0x0B,  0xFF,  0x08,  0x00,  0x90,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x7F,  0xFF,  0x02,  0x20, 	/* 40E80 */
+	0x04,  0x20,  0x04,  0x20,  0x08,  0x40,  0x1C,  0x7E,  0x2A,  0xC2,  0x48,  0xC2,  0x09,  0x42,  0x0A,  0x42, 	/* 40E90 */
+	0x08,  0x42,  0x08,  0x7E,  0x08,  0x00,  0x93,  0x00,  0x24,  0x3E,  0x22,  0x00,  0x22,  0x01,  0xFF,  0x00, 	/* 40EA0 */
+	0x20,  0x7F,  0x20,  0x08,  0x32,  0x0A,  0x32,  0x2A,  0x54,  0x2A,  0x54,  0x2A,  0x48,  0x2A,  0x88,  0x29, 	/* 40EB0 */
+	0x14,  0x4A,  0x24,  0x08,  0x42,  0x08,  0x81,  0x95,  0x00,  0x20,  0x3F,  0x10,  0x00,  0x08,  0x00,  0x0A, 	/* 40EC0 */
+	0x00,  0x22,  0x7F,  0x22,  0x08,  0xA4,  0x08,  0xA4,  0x2A,  0xA8,  0x2A,  0xAA,  0x2B,  0x31,  0x2A,  0x21, 	/* 40ED0 */
+	0x2A,  0x60,  0x48,  0xA2,  0x09,  0x22,  0x0A,  0x1E,  0x96,  0x08,  0x00,  0x08,  0xFC,  0x08,  0x84,  0x7E, 	/* 40EE0 */
+	0x84,  0x02,  0x84,  0x04,  0xFC,  0x04,  0x84,  0x08,  0x84,  0x1C,  0x84,  0x2A,  0xFC,  0x49,  0x84,  0x08, 	/* 40EF0 */
+	0x84,  0x08,  0x84,  0x08,  0x84,  0x09,  0xFF,  0x08,  0x00,  0x97,  0x00,  0x04,  0x3E,  0x18,  0x00,  0xF0, 	/* 40F00 */
+	0x00,  0x90,  0x00,  0x90,  0x7F,  0x90,  0x08,  0xFF,  0x0A,  0x90,  0x2A,  0x90,  0x2A,  0x88,  0x2A,  0x88, 	/* 40F10 */
+	0x28,  0xE8,  0x2B,  0x85,  0x48,  0x05,  0x0B,  0xF3,  0x08,  0x01,  0x9A,  0x00,  0x20,  0x3E,  0x20,  0x00, 	/* 40F20 */
+	0x20,  0x00,  0x7F,  0x00,  0x50,  0x7F,  0x50,  0x08,  0x90,  0x0B,  0x1E,  0x2A,  0x10,  0x2A,  0x10,  0x2A, 	/* 40F30 */
+	0x10,  0x2A,  0x1E,  0x2A,  0x10,  0x48,  0x10,  0x08,  0x10,  0x08,  0x10,  0x9D,  0x08,  0x00,  0x08,  0xFE, 	/* 40F40 */
+	0x08,  0x82,  0x7E,  0x82,  0x02,  0x82,  0x04,  0x82,  0x04,  0xFE,  0x08,  0x28,  0x1C,  0x28,  0x2A,  0x28, 	/* 40F50 */
+	0x49,  0x28,  0x08,  0x48,  0x08,  0x48,  0x08,  0x89,  0x08,  0x89,  0x09,  0x07,  0x9E,  0x08,  0x10,  0x08, 	/* 40F60 */
+	0x10,  0x08,  0x10,  0x7F,  0xFE,  0x02,  0x92,  0x04,  0x92,  0x04,  0xFE,  0x08,  0x92,  0x1C,  0x92,  0x2A, 	/* 40F70 */
+	0x92,  0x49,  0xFE,  0x09,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x9F,  0x01,  0x00, 	/* 40F80 */
+	0x11,  0x08,  0x11,  0x08,  0x1F,  0xF8,  0x41,  0x02,  0x41,  0x02,  0x7F,  0xFE,  0x40,  0x02,  0x0F,  0xF0, 	/* 40F90 */
+	0x00,  0x00,  0x7F,  0xFE,  0x01,  0x00,  0x05,  0x30,  0x19,  0x0C,  0x61,  0x02,  0x03,  0x00,  0xA0,  0x00, 	/* 40FA0 */
+	0x00,  0x3D,  0xFE,  0x00,  0x02,  0x00,  0x02,  0x00,  0xFA,  0x7F,  0x02,  0x08,  0x02,  0x0A,  0xF2,  0x2A, 	/* 40FB0 */
+	0x92,  0x2A,  0x92,  0x2A,  0x92,  0x2A,  0xF2,  0x2A,  0x02,  0x48,  0x02,  0x08,  0x02,  0x08,  0x0C,  0xA2, 	/* 40FC0 */
+	0x08,  0x40,  0x08,  0x40,  0x08,  0x40,  0x7E,  0x7F,  0x02,  0x90,  0x04,  0x90,  0x05,  0x10,  0x08,  0x58, 	/* 40FD0 */
+	0x1C,  0x54,  0x2A,  0x54,  0x49,  0x52,  0x08,  0x92,  0x09,  0x12,  0x08,  0x10,  0x08,  0x10,  0x08,  0x30, 	/* 40FE0 */
+	0xA5,  0x08,  0x84,  0x08,  0x44,  0x08,  0x48,  0x7E,  0xFE,  0x02,  0x10,  0x04,  0x10,  0x04,  0x10,  0x08, 	/* 40FF0 */
+	0xFE,  0x1C,  0x10,  0x2A,  0x10,  0x49,  0x10,  0x09,  0xFF,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08, 	/* 41000 */
+	0x10,  0xA8,  0x00,  0x00,  0x7F,  0xFF,  0x02,  0x20,  0x1F,  0xFC,  0x12,  0x24,  0x12,  0x24,  0x1F,  0xFC, 	/* 41010 */
+	0x00,  0x00,  0x0F,  0xF8,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x80,  0x04,  0xB0,  0x18,  0x8C,  0x60,  0x82, 	/* 41020 */
+	0x01,  0x80,  0xAD,  0x04,  0x00,  0x07,  0xFC,  0x08,  0x84,  0x15,  0x28,  0x73,  0x10,  0x0A,  0x68,  0x04, 	/* 41030 */
+	0x84,  0x1B,  0xF3,  0x60,  0x00,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x80,  0x04,  0xB0,  0x18,  0x8C,  0x60, 	/* 41040 */
+	0x82,  0x01,  0x80,  0xB7,  0x10,  0x20,  0x10,  0x20,  0x13,  0xFE,  0x7C,  0x20,  0x05,  0xFC,  0x08,  0x20, 	/* 41050 */
+	0x0B,  0xFE,  0x10,  0x48,  0x18,  0x48,  0x37,  0xFF,  0x54,  0x88,  0x10,  0xC8,  0x11,  0x48,  0x12,  0x08, 	/* 41060 */
+	0x14,  0x08,  0x10,  0x18,  0xBA,  0x00,  0x44,  0x3E,  0x44,  0x01,  0xFF,  0x00,  0x44,  0x00,  0x44,  0x7F, 	/* 41070 */
+	0x7C,  0x08,  0x44,  0x08,  0x44,  0x2A,  0x7C,  0x2A,  0x44,  0x2A,  0x44,  0x2B,  0xFF,  0x2A,  0x00,  0x48, 	/* 41080 */
+	0x48,  0x08,  0x84,  0x0B,  0x02,  0xBF,  0x00,  0x20,  0x3C,  0x7C,  0x00,  0x48,  0x00,  0x88,  0x01,  0xF0, 	/* 41090 */
+	0x7C,  0x10,  0x0B,  0xFF,  0x08,  0x12,  0x2B,  0x12,  0x2A,  0x9C,  0x2A,  0x98,  0x2A,  0x34,  0x2A,  0x54, 	/* 410A0 */
+	0x48,  0x92,  0x0B,  0x11,  0x08,  0x30,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x08,  0x08,  0x0B,  0xE8,  0x0A, 	/* 410B0 */
+	0x28,  0x0B,  0xE8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x1F,  0xF8,  0x00,  0x00,  0x7F,  0xFF,  0x00, 	/* 410C0 */
+	0x80,  0x0C,  0x9C,  0x70,  0x83,  0x01,  0x80,  0x81,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x0C,  0x38, 	/* 410D0 */
+	0x0E,  0x34,  0x15,  0x54,  0x24,  0x92,  0x44,  0x11,  0x0F,  0xF8,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x80, 	/* 410E0 */
+	0x04,  0xB0,  0x18,  0x8C,  0x60,  0x82,  0x01,  0x80,  0x84,  0x08,  0x00,  0x08,  0xFC,  0x08,  0x04,  0x7E, 	/* 410F0 */
+	0xFC,  0x02,  0x04,  0x04,  0x04,  0x05,  0xFF,  0x08,  0x12,  0x1C,  0x92,  0x2A,  0x5C,  0x49,  0x38,  0x08, 	/* 41100 */
+	0x34,  0x08,  0xD2,  0x0B,  0x11,  0x08,  0x10,  0x08,  0x30,  0x85,  0x09,  0x22,  0x08,  0x92,  0x08,  0x94, 	/* 41110 */
+	0x7E,  0xFE,  0x02,  0x92,  0x04,  0x92,  0x04,  0xFE,  0x08,  0x92,  0x1C,  0xFE,  0x2A,  0x10,  0x49,  0x10, 	/* 41120 */
+	0x09,  0xFF,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x8A,  0x00,  0x80,  0x7B,  0xFE,  0x00, 	/* 41130 */
+	0x8A,  0x00,  0x8A,  0x03,  0xEA,  0x7C,  0x8A,  0x10,  0xF2,  0x17,  0x92,  0x54,  0xAC,  0x54,  0x20,  0x57, 	/* 41140 */
+	0xFF,  0x54,  0x60,  0x54,  0x50,  0x50,  0x88,  0x11,  0x04,  0x16,  0x03,  0x8D,  0x08,  0x00,  0x08,  0xFC, 	/* 41150 */
+	0x08,  0x84,  0x7E,  0xBC,  0x02,  0xA4,  0x04,  0xA4,  0x04,  0xA4,  0x09,  0xFE,  0x1D,  0x02,  0x2B,  0x7A, 	/* 41160 */
+	0x49,  0x4A,  0x09,  0x4A,  0x09,  0x7A,  0x09,  0x02,  0x09,  0x02,  0x09,  0x06,  0x8E,  0x08,  0x10,  0x08, 	/* 41170 */
+	0x10,  0x08,  0x1F,  0x7E,  0x10,  0x02,  0xFC,  0x04,  0x84,  0x04,  0x84,  0x08,  0xFC,  0x1C,  0x84,  0x2A, 	/* 41180 */
+	0xFC,  0x49,  0x84,  0x08,  0x84,  0x08,  0xFC,  0x08,  0x58,  0x08,  0x84,  0x0B,  0x02,  0x8F,  0x08,  0x00, 	/* 41190 */
+	0x08,  0xFE,  0x08,  0x00,  0x7E,  0x7C,  0x02,  0x44,  0x04,  0x44,  0x04,  0x7C,  0x08,  0x00,  0x1C,  0xFE, 	/* 411A0 */
+	0x2A,  0x92,  0x49,  0x92,  0x08,  0xFE,  0x08,  0x92,  0x08,  0x92,  0x08,  0xFE,  0x08,  0x00,  0x9D,  0x00, 	/* 411B0 */
+	0x00,  0x3E,  0xFE,  0x00,  0x92,  0x00,  0xFE,  0x00,  0x92,  0x7E,  0xFE,  0x08,  0x48,  0x0A,  0x49,  0x2A, 	/* 411C0 */
+	0x87,  0x2B,  0x20,  0x2A,  0x3C,  0x2A,  0x44,  0x2B,  0xA8,  0x48,  0x10,  0x08,  0x6C,  0x09,  0x83,  0xA6, 	/* 411D0 */
+	0x12,  0x00,  0x13,  0xDE,  0x2D,  0x12,  0x4F,  0xF2,  0x11,  0x12,  0x35,  0xD2,  0x55,  0x12,  0x15,  0xDC, 	/* 411E0 */
+	0x16,  0x10,  0x17,  0xF8,  0x00,  0x00,  0x3F,  0xFF,  0x02,  0xB0,  0x0C,  0x8C,  0x30,  0x82,  0x01,  0x80, 	/* 411F0 */
+	0xA7,  0x00,  0x10,  0x3F,  0xFF,  0x00,  0x10,  0x00,  0xFE,  0x00,  0x00,  0x7E,  0xFE,  0x08,  0x82,  0x08, 	/* 41200 */
+	0xFE,  0x2A,  0x44,  0x2A,  0x28,  0x2B,  0xFF,  0x2A,  0x00,  0x2A,  0xFE,  0x48,  0x82,  0x08,  0xFE,  0x08, 	/* 41210 */
+	0x00,  0xAA,  0x00,  0x00,  0x3D,  0xEF,  0x01,  0x29,  0x01,  0xEF,  0x00,  0x00,  0x7E,  0xFE,  0x08,  0x92, 	/* 41220 */
+	0x0A,  0xFE,  0x2A,  0x92,  0x2A,  0x92,  0x2A,  0xFE,  0x2A,  0x10,  0x2B,  0xFF,  0x48,  0x10,  0x08,  0x10, 	/* 41230 */
+	0x08,  0x10,  0xAE,  0x00,  0x48,  0x3D,  0xFE,  0x01,  0x4A,  0x01,  0xFE,  0x01,  0x4A,  0x7F,  0xFE,  0x08, 	/* 41240 */
+	0x00,  0x09,  0xFF,  0x2A,  0x00,  0x2A,  0xFC,  0x2A,  0x84,  0x2A,  0xFC,  0x2A,  0x48,  0x28,  0x30,  0x4B, 	/* 41250 */
+	0xFF,  0x08,  0x00,  0xB0,  0x10,  0x00,  0x13,  0xFF,  0x11,  0x24,  0x7E,  0x22,  0x07,  0xFF,  0x0A,  0x22, 	/* 41260 */
+	0x0B,  0x76,  0x12,  0xAA,  0x13,  0x76,  0x3A,  0x22,  0x57,  0x76,  0x12,  0xAA,  0x13,  0x76,  0x12,  0x22, 	/* 41270 */
+	0x12,  0x22,  0x12,  0x06,  0xB3,  0x00,  0x10,  0x3D,  0xFF,  0x00,  0x00,  0x00,  0xEE,  0x00,  0xAA,  0x7F, 	/* 41280 */
+	0xEE,  0x08,  0x28,  0x08,  0xFE,  0x2A,  0x28,  0x2A,  0xFE,  0x2A,  0x28,  0x2B,  0xFF,  0x2A,  0xD2,  0x4B, 	/* 41290 */
+	0x4C,  0x08,  0x74,  0x09,  0x83,  0xB9,  0x00,  0x04,  0x00,  0x38,  0x3F,  0xC0,  0x00,  0x80,  0x0F,  0xF8, 	/* 412A0 */
+	0x08,  0x88,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x80,  0x3F,  0xFE,  0x20,  0x82,  0x20,  0xA2,  0x20,  0xF2, 	/* 412B0 */
+	0x2F,  0x0A,  0x20,  0x02,  0x20,  0x06,  0xBA,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x0F, 	/* 412C0 */
+	0xF8,  0x08,  0x88,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x80,  0x3F,  0xFE,  0x20,  0x82,  0x20,  0xA2,  0x20, 	/* 412D0 */
+	0xF2,  0x2F,  0x0A,  0x20,  0x02,  0x20,  0x06,  0xBD,  0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x04,  0x90, 	/* 412E0 */
+	0x1F,  0xFC,  0x69,  0x4B,  0x08,  0x88,  0x0B,  0x68,  0x0F,  0xF8,  0x01,  0x00,  0x1F,  0xFC,  0x11,  0x44, 	/* 412F0 */
+	0x11,  0x24,  0x12,  0xD4,  0x1F,  0x04,  0x10,  0x0C,  0xBE,  0x00,  0x08,  0x00,  0x70,  0x1F,  0x80,  0x00, 	/* 41300 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x01,  0xC0,  0x02,  0xA0,  0x04,  0x90,  0x18, 	/* 41310 */
+	0x8C,  0x60,  0x83,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0xBF,  0x00,  0x18,  0x00,  0xE0,  0x3F,  0x80, 	/* 41320 */
+	0x00,  0x80,  0x7F,  0xFF,  0x01,  0xC0,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x02,  0x40, 	/* 41330 */
+	0x02,  0x40,  0x02,  0x40,  0x04,  0x42,  0x18,  0x22,  0x60,  0x1E,  0x80,  0x00,  0x08,  0x00,  0x70,  0x1F, 	/* 41340 */
+	0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0xC0,  0x02,  0xA0,  0x0C,  0x98,  0x70,  0x87,  0x1F,  0xF0,  0x01, 	/* 41350 */
+	0x10,  0x01,  0x1C,  0x01,  0x04,  0x02,  0x04,  0x0C,  0x04,  0x30,  0x18,  0x81,  0x01,  0x10,  0x06,  0x10, 	/* 41360 */
+	0x3C,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x7F,  0x90,  0x06,  0x20,  0x0D,  0x28,  0x0C,  0xA4, 	/* 41370 */
+	0x14,  0xA4,  0x14,  0x42,  0x24,  0x5E,  0x45,  0xE2,  0x04,  0x01,  0x04,  0x01,  0x89,  0x00,  0x08,  0x1F, 	/* 41380 */
+	0xF0,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x84,  0x7F,  0xFF,  0x00,  0x84,  0x1F, 	/* 41390 */
+	0xFC,  0x01,  0xC0,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0x8B,  0x02,  0x20, 	/* 413A0 */
+	0x0C,  0x20,  0x78,  0x24,  0x08,  0xA4,  0x08,  0xA4,  0x08,  0xA8,  0x7E,  0xA8,  0x08,  0xA0,  0x09,  0x20, 	/* 413B0 */
+	0x1C,  0x50,  0x1A,  0x50,  0x2A,  0x88,  0x28,  0x88,  0x49,  0x04,  0x0A,  0x02,  0x0C,  0x01,  0x91,  0x01, 	/* 413C0 */
+	0x04,  0x06,  0x44,  0x3C,  0x24,  0x04,  0x14,  0x04,  0x14,  0x04,  0x84,  0x7F,  0x44,  0x04,  0x24,  0x0E, 	/* 413D0 */
+	0x24,  0x0D,  0x07,  0x14,  0xBC,  0x15,  0xC4,  0x24,  0x04,  0x44,  0x04,  0x04,  0x04,  0x04,  0x04,  0x92, 	/* 413E0 */
+	0x02,  0x20,  0x0C,  0x20,  0x78,  0x20,  0x08,  0xA8,  0x08,  0xA4,  0x08,  0xA4,  0x7E,  0xA2,  0x09,  0x22, 	/* 413F0 */
+	0x0C,  0x26,  0x1A,  0x24,  0x19,  0x68,  0x28,  0x08,  0x28,  0x10,  0x48,  0x20,  0x08,  0xC0,  0x0B,  0x00, 	/* 41400 */
+	0x95,  0x02,  0x88,  0x0C,  0x88,  0x78,  0x88,  0x08,  0x88,  0x08,  0x8A,  0x08,  0x8A,  0x7E,  0xEC,  0x08, 	/* 41410 */
+	0x8C,  0x0C,  0x88,  0x1A,  0x88,  0x1A,  0x88,  0x28,  0x88,  0x28,  0x89,  0x48,  0x89,  0x08,  0xE9,  0x0B, 	/* 41420 */
+	0x87,  0x98,  0x01,  0x20,  0x06,  0x10,  0x38,  0x10,  0x08,  0x54,  0x08,  0x44,  0x7F,  0x44,  0x08,  0x48, 	/* 41430 */
+	0x09,  0x4A,  0x1D,  0x51,  0x1B,  0x51,  0x29,  0x61,  0x2A,  0xC0,  0x49,  0x42,  0x0A,  0x22,  0x0C,  0x1E, 	/* 41440 */
+	0x08,  0x00,  0x9F,  0x02,  0x00,  0x0C,  0xFC,  0x78,  0x84,  0x08,  0x84,  0x08,  0x84,  0x7E,  0xFC,  0x08, 	/* 41450 */
+	0x84,  0x08,  0x84,  0x1C,  0x84,  0x1A,  0xFC,  0x2A,  0x84,  0x28,  0x84,  0x48,  0x84,  0x08,  0x84,  0x0B, 	/* 41460 */
+	0xFF,  0x08,  0x00,  0xA1,  0x02,  0x24,  0x0C,  0x22,  0x78,  0x22,  0x09,  0xFF,  0x08,  0x20,  0x7E,  0x20, 	/* 41470 */
+	0x08,  0x32,  0x08,  0x32,  0x1C,  0x54,  0x1A,  0x54,  0x2A,  0x48,  0x28,  0x88,  0x49,  0x14,  0x0A,  0x24, 	/* 41480 */
+	0x08,  0x42,  0x08,  0x81,  0xA3,  0x02,  0x10,  0x0C,  0x10,  0x78,  0x10,  0x09,  0xFF,  0x08,  0x10,  0x7F, 	/* 41490 */
+	0x10,  0x08,  0x10,  0x09,  0xFE,  0x1C,  0x38,  0x1A,  0x38,  0x29,  0x54,  0x28,  0x54,  0x48,  0x92,  0x09, 	/* 414A0 */
+	0x11,  0x08,  0x10,  0x08,  0x10,  0xA4,  0x02,  0x00,  0x0D,  0xFE,  0x78,  0x24,  0x09,  0x24,  0x08,  0xA4, 	/* 414B0 */
+	0x08,  0xA8,  0x7E,  0xA0,  0x08,  0x20,  0x0B,  0xFF,  0x1C,  0x20,  0x1A,  0x20,  0x2A,  0x20,  0x28,  0x20, 	/* 414C0 */
+	0x48,  0x20,  0x08,  0x20,  0x08,  0x20,  0xA6,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80,  0x1F,  0xFC,  0x01, 	/* 414D0 */
+	0x40,  0x7F,  0xFF,  0x02,  0x10,  0x0C,  0x6C,  0x77,  0x83,  0x00,  0x80,  0x3F,  0xFE,  0x01,  0xC0,  0x02, 	/* 414E0 */
+	0xA0,  0x0C,  0x98,  0x30,  0x86,  0x00,  0x80,  0xA7,  0x02,  0x10,  0x0C,  0x10,  0x78,  0x10,  0x08,  0xFE, 	/* 414F0 */
+	0x08,  0x92,  0x08,  0x92,  0x7E,  0x92,  0x08,  0x92,  0x0D,  0xFF,  0x1A,  0x10,  0x1A,  0x10,  0x28,  0x28, 	/* 41500 */
+	0x28,  0x28,  0x48,  0x44,  0x09,  0x82,  0x0E,  0x01,  0xA9,  0x02,  0x10,  0x0C,  0x50,  0x78,  0x50,  0x08, 	/* 41510 */
+	0xFE,  0x08,  0x90,  0x7F,  0x10,  0x08,  0x10,  0x09,  0xFF,  0x1C,  0x10,  0x1A,  0x10,  0x29,  0x30,  0x28, 	/* 41520 */
+	0x28,  0x48,  0x48,  0x08,  0x84,  0x09,  0x02,  0x0A,  0x01,  0xAC,  0x02,  0x00,  0x0D,  0xFF,  0x78,  0x80, 	/* 41530 */
+	0x08,  0x80,  0x08,  0x80,  0x08,  0xFE,  0x7F,  0x82,  0x08,  0x82,  0x08,  0x82,  0x1C,  0xFE,  0x1A,  0x80, 	/* 41540 */
+	0x29,  0x80,  0x28,  0x80,  0x48,  0x80,  0x09,  0xFF,  0x08,  0x00,  0xB0,  0x02,  0x40,  0x0C,  0x40,  0x78, 	/* 41550 */
+	0x40,  0x08,  0x7F,  0x08,  0x90,  0x7E,  0x90,  0x09,  0x10,  0x18,  0x18,  0x1C,  0x54,  0x1A,  0x54,  0x2A, 	/* 41560 */
+	0x52,  0x28,  0x92,  0x49,  0x12,  0x08,  0x10,  0x08,  0x10,  0x08,  0x30,  0xBB,  0x01,  0x20,  0x06,  0x3E, 	/* 41570 */
+	0x38,  0x44,  0x08,  0x84,  0x09,  0x68,  0x7E,  0x10,  0x08,  0x20,  0x08,  0xC8,  0x1C,  0x0F,  0x1A,  0x11, 	/* 41580 */
+	0x29,  0x22,  0x28,  0xDA,  0x48,  0x04,  0x08,  0x08,  0x08,  0x30,  0x09,  0xC0,  0x80,  0x02,  0x04,  0x0C, 	/* 41590 */
+	0x64,  0x78,  0x18,  0x09,  0xE4,  0x08,  0x20,  0x7F,  0xFF,  0x08,  0x50,  0x1C,  0x50,  0x1A,  0xFE,  0x18, 	/* 415A0 */
+	0xD2,  0x29,  0x52,  0x2A,  0x52,  0x48,  0x52,  0x08,  0x5C,  0x08,  0x50,  0x08,  0x10,  0x88,  0x02,  0x00, 	/* 415B0 */
+	0x0C,  0xFC,  0x78,  0x84,  0x08,  0xFC,  0x08,  0x84,  0x08,  0x84,  0x7E,  0xFC,  0x08,  0x00,  0x09,  0xFE, 	/* 415C0 */
+	0x1C,  0x20,  0x1A,  0x20,  0x2B,  0xFF,  0x28,  0x20,  0x48,  0x20,  0x08,  0x20,  0x08,  0x20,  0x8B,  0x02, 	/* 415D0 */
+	0x00,  0x0C,  0xFC,  0x78,  0x84,  0x08,  0x84,  0x08,  0x84,  0x7F,  0xFC,  0x08,  0x00,  0x08,  0x00,  0x1C, 	/* 415E0 */
+	0xFE,  0x1A,  0x10,  0x2A,  0x10,  0x28,  0xFC,  0x48,  0x10,  0x08,  0x10,  0x09,  0xFF,  0x08,  0x00,  0x8D, 	/* 415F0 */
+	0x02,  0x10,  0x0C,  0x54,  0x78,  0x52,  0x08,  0x92,  0x09,  0x11,  0x7F,  0xFC,  0x08,  0x84,  0x08,  0x84, 	/* 41600 */
+	0x1C,  0xFC,  0x1A,  0x84,  0x2A,  0x84,  0x28,  0xFC,  0x48,  0x84,  0x08,  0x84,  0x08,  0x84,  0x08,  0x8C, 	/* 41610 */
+	0x8E,  0x02,  0x04,  0x0C,  0x84,  0x38,  0x48,  0x08,  0x50,  0x08,  0xFC,  0x7F,  0x84,  0x08,  0x84,  0x08, 	/* 41620 */
+	0x84,  0x1C,  0xFC,  0x1A,  0x28,  0x29,  0x28,  0x28,  0x28,  0x48,  0x48,  0x08,  0x49,  0x08,  0x89,  0x09, 	/* 41630 */
+	0x07,  0x94,  0x02,  0x20,  0x0C,  0x20,  0x78,  0x50,  0x08,  0x8C,  0x0B,  0xFB,  0x08,  0x00,  0x7F,  0xF8, 	/* 41640 */
+	0x08,  0x08,  0x1C,  0x10,  0x1A,  0x10,  0x2A,  0xA0,  0x29,  0x94,  0x49,  0x92,  0x0A,  0x8A,  0x0C,  0x8A, 	/* 41650 */
+	0x08,  0x78,  0x97,  0x02,  0x10,  0x0C,  0x20,  0x79,  0xFC,  0x09,  0x24,  0x09,  0x24,  0x7F,  0xFC,  0x09, 	/* 41660 */
+	0x24,  0x09,  0x24,  0x1D,  0xFC,  0x1A,  0x48,  0x28,  0x88,  0x2B,  0xFF,  0x48,  0x08,  0x08,  0x08,  0x08, 	/* 41670 */
+	0x08,  0x08,  0x08,  0x98,  0x02,  0x44,  0x0C,  0x44,  0x79,  0xFF,  0x08,  0x44,  0x08,  0x44,  0x08,  0x7C, 	/* 41680 */
+	0x7E,  0x44,  0x08,  0x44,  0x0C,  0x7C,  0x1A,  0x44,  0x1A,  0x44,  0x2B,  0xFF,  0x28,  0x00,  0x48,  0x48, 	/* 41690 */
+	0x08,  0x84,  0x0B,  0x02,  0x99,  0x02,  0x08,  0x0C,  0x08,  0x79,  0xFF,  0x08,  0x08,  0x08,  0x3E,  0x08, 	/* 416A0 */
+	0xA2,  0x7F,  0xA2,  0x08,  0xBE,  0x0C,  0xA2,  0x1A,  0xBE,  0x1A,  0xA2,  0x28,  0xA2,  0x28,  0xBE,  0x48, 	/* 416B0 */
+	0x80,  0x08,  0xFF,  0x08,  0x00,  0x9A,  0x02,  0x44,  0x0C,  0x44,  0x78,  0x88,  0x08,  0xFE,  0x09,  0x88, 	/* 416C0 */
+	0x0A,  0x88,  0x7E,  0x88,  0x08,  0xFE,  0x1C,  0x88,  0x1A,  0x88,  0x2A,  0xFE,  0x28,  0x88,  0x48,  0x88, 	/* 416D0 */
+	0x08,  0x88,  0x08,  0xFF,  0x08,  0x00,  0x9C,  0x02,  0x20,  0x0C,  0x20,  0x79,  0xFE,  0x08,  0x20,  0x0B, 	/* 416E0 */
+	0xFF,  0x7E,  0x50,  0x08,  0x52,  0x1C,  0x8E,  0x1B,  0x40,  0x2A,  0x78,  0x28,  0x88,  0x4B,  0x50,  0x08, 	/* 416F0 */
+	0x20,  0x08,  0x50,  0x09,  0x8C,  0x0E,  0x03,  0x9F,  0x00,  0x80,  0x7F,  0xFF,  0x08,  0x08,  0x0B,  0xE8, 	/* 41700 */
+	0x0A,  0x28,  0x0B,  0xE8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x1C,  0x1F,  0xE0,  0x00,  0x80,  0x7F,  0xFF, 	/* 41710 */
+	0x02,  0xC0,  0x0C,  0xB0,  0x70,  0x8F,  0x00,  0x80,  0xA0,  0x02,  0x00,  0x0C,  0xFE,  0x78,  0x92,  0x08, 	/* 41720 */
+	0x92,  0x08,  0xFE,  0x08,  0x92,  0x7E,  0x92,  0x08,  0xFE,  0x0C,  0x92,  0x1A,  0xBA,  0x1A,  0xAA,  0x28, 	/* 41730 */
+	0xAA,  0x28,  0xBA,  0x49,  0x02,  0x09,  0x02,  0x0A,  0x06,  0xAE,  0x02,  0x04,  0x0C,  0x18,  0x79,  0xE0, 	/* 41740 */
+	0x08,  0x20,  0x0B,  0xFF,  0x08,  0x20,  0x7F,  0xFC,  0x09,  0x24,  0x1D,  0xFC,  0x1B,  0x24,  0x29,  0xFC, 	/* 41750 */
+	0x28,  0x20,  0x49,  0xFE,  0x08,  0x20,  0x0F,  0xFF,  0x08,  0x00,  0xB1,  0x02,  0x04,  0x0C,  0x18,  0x79, 	/* 41760 */
+	0xE4,  0x08,  0x92,  0x08,  0x92,  0x09,  0x01,  0x7F,  0x11,  0x08,  0xFE,  0x0C,  0x92,  0x1A,  0xFE,  0x1A, 	/* 41770 */
+	0x92,  0x28,  0x92,  0x29,  0xFF,  0x48,  0x82,  0x08,  0x82,  0x08,  0x86,  0xB2,  0x02,  0x04,  0x0C,  0x18, 	/* 41780 */
+	0x38,  0xE0,  0x08,  0x02,  0x08,  0xA2,  0x7F,  0x54,  0x08,  0x54,  0x08,  0x08,  0x1C,  0xBE,  0x1A,  0xA2, 	/* 41790 */
+	0x2A,  0xA2,  0x28,  0xBE,  0x48,  0xA2,  0x08,  0xA2,  0x08,  0xBE,  0x08,  0x80,  0xB7,  0x02,  0x00,  0x0C, 	/* 417A0 */
+	0xFE,  0x78,  0x92,  0x08,  0xFE,  0x08,  0x92,  0x7E,  0xFE,  0x08,  0x48,  0x0C,  0x49,  0x1A,  0x87,  0x1B, 	/* 417B0 */
+	0x20,  0x28,  0x3C,  0x28,  0x44,  0x49,  0xA8,  0x08,  0x10,  0x08,  0x6C,  0x09,  0x83,  0xBB,  0x02,  0x04, 	/* 417C0 */
+	0x0C,  0x18,  0x79,  0xE4,  0x08,  0x92,  0x08,  0x92,  0x08,  0x81,  0x7F,  0x21,  0x08,  0x20,  0x08,  0xCE, 	/* 417D0 */
+	0x1C,  0x82,  0x1A,  0x82,  0x2A,  0xEE,  0x28,  0x82,  0x48,  0x82,  0x08,  0xFE,  0x08,  0x00,  0xBC,  0x02, 	/* 417E0 */
+	0x20,  0x0C,  0x20,  0x79,  0xFE,  0x09,  0x02,  0x09,  0x00,  0x09,  0xFC,  0x7E,  0x44,  0x08,  0x64,  0x19, 	/* 417F0 */
+	0xA8,  0x1C,  0x58,  0x1A,  0x94,  0x2B,  0x34,  0x28,  0x52,  0x49,  0x91,  0x08,  0x10,  0x08,  0x60,  0xBD, 	/* 41800 */
+	0x02,  0x24,  0x0C,  0x22,  0x79,  0xFF,  0x08,  0x30,  0x08,  0x51,  0x7E,  0x9F,  0x09,  0x44,  0x18,  0x78, 	/* 41810 */
+	0x1C,  0x42,  0x2A,  0x3E,  0x2A,  0x00,  0x48,  0xFE,  0x08,  0x82,  0x08,  0xFE,  0x08,  0x82,  0x08,  0xFE, 	/* 41820 */
+	0xBE,  0x01,  0x00,  0x7F,  0xFE,  0x04,  0x10,  0x07,  0xF0,  0x3F,  0xFE,  0x20,  0x02,  0x27,  0xF2,  0x24, 	/* 41830 */
+	0x12,  0x27,  0xF6,  0x00,  0x18,  0x1F,  0xE0,  0x00,  0x80,  0x7F,  0xFF,  0x06,  0xB0,  0x78,  0x8F,  0x00, 	/* 41840 */
+	0x80,  0xBF,  0x02,  0x10,  0x0C,  0x10,  0x79,  0xFF,  0x08,  0x00,  0x08,  0xFC,  0x7E,  0x84,  0x08,  0xFC, 	/* 41850 */
+	0x18,  0x00,  0x1D,  0xFE,  0x1B,  0x02,  0x29,  0x7A,  0x29,  0x4A,  0x49,  0x4A,  0x09,  0x7A,  0x09,  0x02, 	/* 41860 */
+	0x09,  0x06,  0x80,  0x08,  0x00,  0x08,  0x3C,  0x7F,  0x24,  0x08,  0x25,  0x3E,  0x25,  0x00,  0x43,  0x7F, 	/* 41870 */
+	0x80,  0x45,  0xFC,  0x79,  0x24,  0x08,  0x24,  0x7F,  0x14,  0x0C,  0x18,  0x1A,  0x08,  0x29,  0x14,  0x48, 	/* 41880 */
+	0x62,  0x09,  0x81,  0x82,  0x02,  0x10,  0x0C,  0x10,  0x79,  0xFF,  0x08,  0x10,  0x08,  0xFE,  0x7E,  0x92, 	/* 41890 */
+	0x08,  0xFE,  0x08,  0x92,  0x1C,  0x92,  0x1A,  0xFE,  0x2A,  0x20,  0x28,  0x10,  0x49,  0x52,  0x09,  0x41, 	/* 418A0 */
+	0x0A,  0x45,  0x08,  0x3C,  0x83,  0x02,  0x10,  0x0C,  0x10,  0x79,  0xFF,  0x09,  0x01,  0x09,  0x49,  0x08, 	/* 418B0 */
+	0x44,  0x7E,  0x92,  0x09,  0x12,  0x0C,  0x28,  0x1A,  0x44,  0x1A,  0xFE,  0x29,  0x45,  0x28,  0x44,  0x48, 	/* 418C0 */
+	0x44,  0x08,  0x7C,  0x08,  0x00,  0x86,  0x02,  0x10,  0x0C,  0x20,  0x78,  0xFC,  0x08,  0x84,  0x08,  0xFC, 	/* 418D0 */
+	0x7E,  0x84,  0x08,  0xFC,  0x0C,  0x10,  0x1A,  0x54,  0x19,  0x9B,  0x28,  0x34,  0x29,  0xC9,  0x48,  0x32, 	/* 418E0 */
+	0x08,  0xCC,  0x08,  0x30,  0x0B,  0xC0,  0x89,  0x02,  0x00,  0x0D,  0xFE,  0x79,  0x02,  0x09,  0xFE,  0x09, 	/* 418F0 */
+	0x00,  0x09,  0xD6,  0x7F,  0x10,  0x09,  0xD6,  0x0D,  0x00,  0x1B,  0x50,  0x19,  0x7E,  0x29,  0x50,  0x2A, 	/* 41900 */
+	0x90,  0x4B,  0xFF,  0x0C,  0x10,  0x08,  0x10,  0x8D,  0x02,  0x20,  0x0D,  0xFE,  0x78,  0x20,  0x09,  0xFC, 	/* 41910 */
+	0x08,  0x20,  0x7F,  0xFF,  0x08,  0x00,  0x08,  0xFC,  0x1C,  0x84,  0x1A,  0xFC,  0x2A,  0x84,  0x28,  0xFC, 	/* 41920 */
+	0x48,  0x84,  0x08,  0xFC,  0x08,  0x4C,  0x09,  0x82,  0x8E,  0x20,  0x00,  0x22,  0xFF,  0x3C,  0x10,  0x20, 	/* 41930 */
+	0x20,  0x21,  0x7E,  0x1F,  0x42,  0x00,  0x42,  0x03,  0x7E,  0x3C,  0x42,  0x04,  0x7E,  0x7F,  0xC2,  0x0E, 	/* 41940 */
+	0x42,  0x15,  0x7E,  0x24,  0xA4,  0x44,  0x42,  0x05,  0x81,  0x8F,  0x04,  0x04,  0x08,  0x38,  0x7B,  0xC2, 	/* 41950 */
+	0x09,  0x22,  0x08,  0xA4,  0x09,  0xFC,  0x7E,  0x04,  0x08,  0xFC,  0x1C,  0x04,  0x1A,  0xFC,  0x1A,  0x20, 	/* 41960 */
+	0x29,  0x54,  0x29,  0x52,  0x49,  0x55,  0x0A,  0x45,  0x08,  0x3C,  0x90,  0x02,  0x40,  0x0C,  0x78,  0x38, 	/* 41970 */
+	0x90,  0x09,  0xFC,  0x0A,  0xA4,  0x08,  0xFC,  0x7F,  0xA4,  0x0C,  0xFC,  0x1A,  0x20,  0x19,  0xFE,  0x29, 	/* 41980 */
+	0x22,  0x29,  0xFE,  0x49,  0x22,  0x09,  0xFE,  0x08,  0x21,  0x08,  0x1F,  0x97,  0x02,  0x10,  0x0C,  0x10, 	/* 41990 */
+	0x79,  0xFF,  0x08,  0x10,  0x08,  0xFE,  0x08,  0x92,  0x7E,  0xFE,  0x08,  0x92,  0x0C,  0xFE,  0x1A,  0x12, 	/* 419A0 */
+	0x1B,  0xFD,  0x28,  0x10,  0x28,  0xAA,  0x48,  0xA9,  0x09,  0x25,  0x08,  0x1C,  0xA1,  0x02,  0x10,  0x0C, 	/* 419B0 */
+	0x10,  0x79,  0xFF,  0x08,  0x94,  0x08,  0x94,  0x09,  0x5A,  0x7E,  0x11,  0x0B,  0xFF,  0x08,  0x00,  0x1D, 	/* 419C0 */
+	0xFE,  0x1B,  0x7A,  0x2B,  0x4A,  0x29,  0x7A,  0x49,  0x02,  0x09,  0xFE,  0x08,  0x00,  0xA2,  0x02,  0x20, 	/* 419D0 */
+	0x0C,  0xBE,  0x78,  0xA0,  0x0B,  0xFF,  0x08,  0x0A,  0x7E,  0x09,  0x09,  0xFF,  0x09,  0x08,  0x1D,  0xF9, 	/* 419E0 */
+	0x1B,  0x35,  0x29,  0x6E,  0x29,  0xB6,  0x49,  0x25,  0x0A,  0xCD,  0x0A,  0x13,  0x0C,  0x21,  0xA3,  0x02, 	/* 419F0 */
+	0x20,  0x0C,  0x20,  0x7B,  0xFF,  0x08,  0x48,  0x08,  0x84,  0x09,  0x4A,  0x7E,  0xFD,  0x08,  0x48,  0x1D, 	/* 41A00 */
+	0xFE,  0x1A,  0x48,  0x2B,  0xFF,  0x28,  0x52,  0x48,  0xD4,  0x0B,  0x48,  0x08,  0x64,  0x0B,  0x83,  0xA9, 	/* 41A10 */
+	0x02,  0x04,  0x0D,  0xF8,  0x78,  0xA4,  0x09,  0x12,  0x09,  0xFE,  0x7E,  0x20,  0x09,  0xFF,  0x08,  0x00, 	/* 41A20 */
+	0x1C,  0xFC,  0x1A,  0x04,  0x2B,  0xFE,  0x28,  0x04,  0x48,  0xFC,  0x09,  0x52,  0x09,  0x45,  0x0A,  0x3C, 	/* 41A30 */
+	0xAB,  0x02,  0x44,  0x05,  0xFF,  0x78,  0x48,  0x08,  0xFE,  0x08,  0x90,  0x09,  0xFE,  0x7E,  0x90,  0x08, 	/* 41A40 */
+	0xFE,  0x1C,  0x90,  0x1A,  0xFE,  0x2A,  0x00,  0x29,  0xFE,  0x48,  0x48,  0x08,  0x30,  0x08,  0x4C,  0x0B, 	/* 41A50 */
+	0x83,  0xB0,  0x02,  0x10,  0x0D,  0xFF,  0x78,  0x00,  0x08,  0xEE,  0x08,  0xAA,  0x08,  0xEE,  0x7F,  0x28, 	/* 41A60 */
+	0x08,  0xFE,  0x08,  0x28,  0x1C,  0xFE,  0x1A,  0x28,  0x2B,  0xFF,  0x28,  0x6A,  0x49,  0xA4,  0x08,  0x32, 	/* 41A70 */
+	0x09,  0xC1,  0xB4,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x40,  0x02,  0x43, 	/* 41A80 */
+	0xE2,  0x00,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x08,  0x10,  0x08,  0x10,  0x10,  0x08,  0x20, 	/* 41A90 */
+	0x04,  0x40,  0x02,  0xB6,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x44,  0x42,  0x44,  0x42,  0x04,  0x44, 	/* 41AA0 */
+	0x08,  0x3C,  0x11,  0x00,  0x21,  0x00,  0x1F,  0xE0,  0x01,  0x20,  0x02,  0x20,  0x02,  0x22,  0x04,  0x22, 	/* 41AB0 */
+	0x08,  0x22,  0x30,  0x1E,  0xB9,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFE,  0x42,  0x42,  0x44,  0x46,  0x18, 	/* 41AC0 */
+	0x3C,  0x60,  0x00,  0x0F,  0xF8,  0x00,  0x08,  0x0F,  0xF8,  0x08,  0x00,  0x0F,  0xFC,  0x00,  0x04,  0x00, 	/* 41AD0 */
+	0x04,  0x00,  0x04,  0x00,  0x38,  0xBA,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x44,  0x42,  0x44,  0x42, 	/* 41AE0 */
+	0x04,  0x44,  0x08,  0x44,  0x10,  0x3C,  0x20,  0x00,  0x1F,  0xF8,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 41AF0 */
+	0x01,  0x00,  0x7F,  0xFE,  0x00,  0x00,  0xBD,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x42,  0x22,  0x44, 	/* 41B00 */
+	0x26,  0x18,  0x1C,  0x60,  0x00,  0x04,  0x20,  0x3F,  0xFE,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFF,  0x04, 	/* 41B10 */
+	0x20,  0x08,  0x20,  0x10,  0x20,  0x20,  0x20,  0xBF,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x42,  0x42, 	/* 41B20 */
+	0x44,  0x46,  0x18,  0x3C,  0x60,  0x00,  0x3F,  0xFC,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFE,  0x00,  0xA0, 	/* 41B30 */
+	0x03,  0x20,  0x0C,  0x20,  0x70,  0x20,  0x00,  0x60,  0x81,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x44, 	/* 41B40 */
+	0x42,  0x44,  0x42,  0x04,  0x44,  0x09,  0x3C,  0x11,  0x00,  0x21,  0x00,  0x7F,  0xFF,  0x01,  0x80,  0x01, 	/* 41B50 */
+	0x40,  0x02,  0x20,  0x04,  0x10,  0x18,  0x0C,  0x60,  0x03,  0x83,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE, 	/* 41B60 */
+	0x42,  0x42,  0x42,  0x42,  0x04,  0x44,  0x18,  0x3C,  0x70,  0x00,  0x11,  0xFC,  0x1E,  0x44,  0x70,  0x44, 	/* 41B70 */
+	0x10,  0x44,  0x12,  0x84,  0x0E,  0x84,  0x01,  0x04,  0x06,  0x18,  0x84,  0x01,  0x00,  0x01,  0x00,  0x7F, 	/* 41B80 */
+	0xFE,  0x42,  0x42,  0x44,  0x42,  0x18,  0x44,  0x62,  0x3C,  0x02,  0x00,  0x07,  0xFE,  0x19,  0x00,  0x61, 	/* 41B90 */
+	0xFC,  0x01,  0x00,  0x01,  0xFC,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x88,  0x01,  0x00,  0x01,  0x00, 	/* 41BA0 */
+	0x7F,  0xFE,  0x42,  0x42,  0x42,  0x44,  0x0C,  0x3C,  0x70,  0x10,  0x08,  0x10,  0x09,  0x7E,  0x09,  0x12, 	/* 41BB0 */
+	0x72,  0x12,  0x0C,  0x12,  0x0A,  0x22,  0x17,  0x22,  0x79,  0x42,  0x00,  0x8C,  0x92,  0x01,  0x00,  0x7F, 	/* 41BC0 */
+	0xFE,  0x42,  0x42,  0x42,  0x46,  0x04,  0x7C,  0x18,  0x00,  0x7F,  0xFE,  0x02,  0x40,  0x04,  0x30,  0x1F, 	/* 41BD0 */
+	0xE8,  0x01,  0x04,  0x1F,  0xF8,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x00,  0x00,  0x93,  0x01,  0x00, 	/* 41BE0 */
+	0x01,  0x00,  0x7F,  0xFE,  0x44,  0x42,  0x44,  0x42,  0x09,  0x3E,  0x11,  0x00,  0x62,  0x60,  0x04,  0x18, 	/* 41BF0 */
+	0x1F,  0xE4,  0x01,  0x02,  0x12,  0x88,  0x12,  0x44,  0x22,  0x4A,  0x42,  0x0A,  0x01,  0xF8,  0x95,  0x01, 	/* 41C00 */
+	0x00,  0x01,  0x00,  0x7F,  0xFE,  0x42,  0x42,  0x44,  0x46,  0x18,  0x3C,  0x60,  0x00,  0x22,  0x44,  0x12, 	/* 41C10 */
+	0x48,  0x12,  0x50,  0x06,  0x40,  0x1A,  0x70,  0x62,  0x4C,  0x04,  0x41,  0x18,  0x41,  0x60,  0x3F,  0x96, 	/* 41C20 */
+	0x00,  0x80,  0x00,  0x80,  0x7F,  0xFE,  0x42,  0x42,  0x44,  0x46,  0x18,  0xBC,  0x68,  0x80,  0x0F,  0xF8, 	/* 41C30 */
+	0x10,  0x80,  0x20,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00, 	/* 41C40 */
+	0x97,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x42,  0x42,  0x44,  0x46,  0x19,  0x3C,  0x62,  0x00,  0x3F, 	/* 41C50 */
+	0xFC,  0x21,  0x04,  0x25,  0xE4,  0x22,  0x44,  0x25,  0x84,  0x23,  0x44,  0x2C,  0x24,  0x3F,  0xFC,  0x20, 	/* 41C60 */
+	0x04,  0x98,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x42,  0x42,  0x4C,  0x44,  0x70,  0x3C,  0x1F,  0xF8, 	/* 41C70 */
+	0x01,  0x08,  0x7F,  0xFF,  0x02,  0x08,  0x3F,  0xF8,  0x04,  0x00,  0x1F,  0xF8,  0x68,  0x08,  0x0F,  0xF8, 	/* 41C80 */
+	0x00,  0x00,  0x9F,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x42,  0x42,  0x4C,  0x7C,  0x30,  0x00,  0x1F, 	/* 41C90 */
+	0xFC,  0x10,  0x04,  0x1F,  0xFC,  0x14,  0x48,  0x14,  0x48,  0x17,  0xF8,  0x28,  0x44,  0x28,  0x44,  0x4F, 	/* 41CA0 */
+	0xFC,  0x00,  0x00,  0xA9,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x42,  0x42,  0x44,  0x46,  0x18,  0x3C, 	/* 41CB0 */
+	0x6F,  0xF0,  0x08,  0x10,  0x09,  0xF0,  0x09,  0x10,  0x3F,  0xFC,  0x20,  0x04,  0x27,  0xE4,  0x24,  0x24, 	/* 41CC0 */
+	0x27,  0xE4,  0x20,  0x0C,  0xAA,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x42,  0x42,  0x44,  0x46,  0x38, 	/* 41CD0 */
+	0x3C,  0x00,  0x20,  0x31,  0xFC,  0x08,  0x20,  0x63,  0xFE,  0x10,  0x20,  0x00,  0x20,  0x09,  0xFC,  0x10, 	/* 41CE0 */
+	0x20,  0x27,  0xFF,  0x40,  0x00,  0xAE,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x44,  0x42,  0x18,  0x7E, 	/* 41CF0 */
+	0x64,  0x00,  0x1F,  0x7C,  0x11,  0x04,  0x1F,  0x7C,  0x11,  0x40,  0x1F,  0x7C,  0x11,  0x04,  0x7F,  0x04, 	/* 41D00 */
+	0x05,  0x04,  0x19,  0x04,  0x63,  0x18,  0xAF,  0x01,  0x00,  0x7F,  0xFE,  0x44,  0x42,  0x04,  0x46,  0x18, 	/* 41D10 */
+	0x3C,  0x64,  0x20,  0x02,  0x40,  0x3F,  0xFE,  0x01,  0x00,  0x1F,  0xFC,  0x01,  0x00,  0x7F,  0xFF,  0x00, 	/* 41D20 */
+	0x00,  0x24,  0x48,  0x22,  0x24,  0x42,  0x22,  0xB0,  0x01,  0x00,  0x7F,  0xFE,  0x42,  0x42,  0x0C,  0x46, 	/* 41D30 */
+	0x71,  0x3C,  0x03,  0xF0,  0x3C,  0xA0,  0x03,  0xC0,  0x06,  0x00,  0x7B,  0xF8,  0x04,  0x80,  0x7F,  0xFF, 	/* 41D40 */
+	0x00,  0x80,  0x10,  0x84,  0x1F,  0xFC,  0x00,  0x00,  0xB6,  0x00,  0x80,  0x7F,  0xFE,  0x44,  0x22,  0x18, 	/* 41D50 */
+	0x9E,  0x6F,  0xF8,  0x08,  0x88,  0x7F,  0xFF,  0x08,  0x88,  0x0F,  0xF8,  0x04,  0x90,  0x07,  0xF0,  0x01, 	/* 41D60 */
+	0x00,  0x7F,  0xFF,  0x06,  0x10,  0x03,  0xE0,  0x3C,  0x18,  0xBA,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE, 	/* 41D70 */
+	0x42,  0x42,  0x4C,  0x7E,  0x30,  0x00,  0x08,  0xFC,  0x3E,  0x84,  0x08,  0xFC,  0x08,  0x84,  0x7F,  0xFC, 	/* 41D80 */
+	0x08,  0x84,  0x14,  0xFC,  0x12,  0x29,  0x20,  0xC9,  0x43,  0x07,  0xBF,  0x01,  0x00,  0x7F,  0xFE,  0x42, 	/* 41D90 */
+	0x22,  0x0C,  0x1F,  0x70,  0x40,  0x3C,  0xFC,  0x27,  0x48,  0x24,  0x30,  0x2B,  0xFC,  0x28,  0xA3,  0x25, 	/* 41DA0 */
+	0xFC,  0x26,  0x20,  0x24,  0xF8,  0x2C,  0x20,  0x23,  0xFE,  0x20,  0x00,  0x83,  0x01,  0x00,  0x7F,  0xFE, 	/* 41DB0 */
+	0x49,  0x22,  0x17,  0xDE,  0x61,  0x00,  0x7F,  0xFE,  0x09,  0x10,  0x0F,  0xF0,  0x09,  0x10,  0x1F,  0xF8, 	/* 41DC0 */
+	0x11,  0x08,  0x1F,  0xF8,  0x11,  0x08,  0x1F,  0xFA,  0x01,  0x02,  0x00,  0xFE,  0x84,  0x00,  0x80,  0x7F, 	/* 41DD0 */
+	0xFE,  0x42,  0x42,  0x1C,  0x3E,  0x61,  0x00,  0x3C,  0xF8,  0x20,  0x08,  0x3E,  0xF8,  0x20,  0x08,  0x3F, 	/* 41DE0 */
+	0xF8,  0x11,  0x10,  0x1D,  0xD0,  0x11,  0x0A,  0x1D,  0xCA,  0x11,  0x36,  0x7B,  0xC2,  0x85,  0x00,  0x80, 	/* 41DF0 */
+	0x7F,  0xFE,  0x42,  0x42,  0x1C,  0x24,  0x64,  0x1C,  0x1F,  0x20,  0x11,  0x3F,  0x1F,  0x24,  0x11,  0x44, 	/* 41E00 */
+	0x1F,  0xA4,  0x08,  0x24,  0x7F,  0x98,  0x08,  0x08,  0x0F,  0x14,  0x11,  0x22,  0x26,  0xC1,  0x87,  0x00, 	/* 41E10 */
+	0x80,  0x7F,  0xFE,  0x42,  0x42,  0x0C,  0x3F,  0x70,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x3F,  0xFE,  0x22, 	/* 41E20 */
+	0x22,  0x3F,  0xFE,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x06,  0x18,  0x78,  0x06,  0x88, 	/* 41E30 */
+	0x00,  0x80,  0x7F,  0xFE,  0x48,  0x92,  0x17,  0xEF,  0x60,  0x80,  0x7F,  0xFF,  0x11,  0x44,  0x1F,  0x7C, 	/* 41E40 */
+	0x01,  0x40,  0x3F,  0x7E,  0x21,  0x42,  0x3F,  0x7E,  0x21,  0x42,  0x3F,  0x7E,  0x01,  0x01,  0x00,  0xFF, 	/* 41E50 */
+	0x8A,  0x01,  0x00,  0x7F,  0xFE,  0x42,  0x42,  0x0C,  0x7F,  0x70,  0x10,  0x02,  0x1E,  0x3D,  0x10,  0x49, 	/* 41E60 */
+	0x7C,  0x2A,  0x54,  0x28,  0x6C,  0x7F,  0x44,  0x1C,  0xFE,  0x1A,  0x92,  0x29,  0xAA,  0x48,  0xF6,  0x08, 	/* 41E70 */
+	0x86,  0x8B,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x10,  0x08,  0x10,  0x08,  0x10, 	/* 41E80 */
+	0x04,  0x10,  0x04,  0x10,  0x04,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x40,  0x00,  0x40,  0x7F,  0xFF, 	/* 41E90 */
+	0x00,  0x00,  0x8D,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x7F,  0x90,  0x02,  0x10,  0x22,  0x10,  0x13, 	/* 41EA0 */
+	0xFF,  0x12,  0x10,  0x14,  0x10,  0x14,  0x10,  0x14,  0x10,  0x0B,  0x10,  0x0C,  0x10,  0x70,  0x10,  0x00, 	/* 41EB0 */
+	0x10,  0x00,  0x10,  0x8F,  0x08,  0x02,  0x08,  0x0C,  0x08,  0xF0,  0x7F,  0x10,  0x02,  0x10,  0x22,  0x10, 	/* 41EC0 */
+	0x12,  0x10,  0x13,  0xFF,  0x14,  0x10,  0x14,  0x10,  0x14,  0x10,  0x0B,  0x10,  0x0C,  0x10,  0x70,  0x10, 	/* 41ED0 */
+	0x00,  0x10,  0x00,  0x10,  0x92,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x04,  0x10,  0x02,  0x10,  0x02, 	/* 41EE0 */
+	0x20,  0x7F,  0xFF,  0x00,  0x08,  0x0F,  0xC8,  0x08,  0x48,  0x08,  0x48,  0x08,  0x48,  0x0F,  0xC8,  0x00, 	/* 41EF0 */
+	0x08,  0x00,  0x08,  0x00,  0x18,  0x93,  0x08,  0x02,  0x08,  0x0C,  0x08,  0xF0,  0x7E,  0x20,  0x00,  0x20, 	/* 41F00 */
+	0x44,  0x3E,  0x25,  0xE0,  0x24,  0x20,  0x24,  0x20,  0x28,  0x3F,  0x09,  0xE0,  0x16,  0x20,  0x18,  0x20, 	/* 41F10 */
+	0x60,  0x21,  0x00,  0x21,  0x00,  0x1F,  0x95,  0x08,  0x78,  0x08,  0x08,  0x08,  0x48,  0x7E,  0x48,  0x00, 	/* 41F20 */
+	0x84,  0x44,  0x84,  0x27,  0x02,  0x24,  0xFD,  0x24,  0x24,  0x28,  0x24,  0x08,  0x24,  0x16,  0x24,  0x18, 	/* 41F30 */
+	0x44,  0x60,  0x44,  0x00,  0x84,  0x01,  0x18,  0x99,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x7F,  0x20, 	/* 41F40 */
+	0x02,  0x3F,  0x22,  0x20,  0x12,  0x20,  0x12,  0x20,  0x14,  0x20,  0x14,  0xFC,  0x14,  0x84,  0x0B,  0x84, 	/* 41F50 */
+	0x0C,  0x84,  0x70,  0x84,  0x00,  0xFC,  0x00,  0x00,  0x9A,  0x08,  0x10,  0x08,  0x10,  0x08,  0xFF,  0x7F, 	/* 41F60 */
+	0x81,  0x02,  0x81,  0x22,  0x00,  0x13,  0xFF,  0x12,  0x10,  0x12,  0x10,  0x14,  0x10,  0x14,  0x10,  0x0B, 	/* 41F70 */
+	0x10,  0x0C,  0x10,  0x70,  0x10,  0x00,  0x10,  0x00,  0x30,  0x9C,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC, 	/* 41F80 */
+	0x04,  0x10,  0x02,  0x20,  0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x0F,  0xF8, 	/* 41F90 */
+	0x08,  0x88,  0x08,  0x88,  0x0F,  0xFA,  0x00,  0x82,  0x00,  0x7E,  0x9D,  0x08,  0x10,  0x08,  0x10,  0x08, 	/* 41FA0 */
+	0x10,  0x7F,  0xFE,  0x02,  0x04,  0x22,  0x84,  0x12,  0x84,  0x12,  0x44,  0x12,  0x44,  0x14,  0x48,  0x14, 	/* 41FB0 */
+	0x48,  0x0B,  0x48,  0x0C,  0x50,  0x70,  0x10,  0x01,  0xFF,  0x00,  0x00,  0x9F,  0x00,  0x80,  0x00,  0x80, 	/* 41FC0 */
+	0x1F,  0xFC,  0x04,  0x10,  0x02,  0x20,  0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8, 	/* 41FD0 */
+	0x08,  0x08,  0x0F,  0xF8,  0x01,  0x21,  0x02,  0x21,  0x0C,  0x21,  0x70,  0x1F,  0xA0,  0x00,  0x80,  0x00, 	/* 41FE0 */
+	0x80,  0x3F,  0xFE,  0x04,  0x10,  0x02,  0x20,  0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F, 	/* 41FF0 */
+	0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0xA1,  0x08,  0x00, 	/* 42000 */
+	0x09,  0xFF,  0x08,  0x10,  0x7F,  0x10,  0x02,  0x20,  0x22,  0x7E,  0x12,  0x42,  0x12,  0x42,  0x12,  0x42, 	/* 42010 */
+	0x14,  0x42,  0x14,  0x7E,  0x0B,  0x42,  0x0C,  0x42,  0x70,  0x42,  0x00,  0x7E,  0x00,  0x00,  0xA2,  0x08, 	/* 42020 */
+	0x20,  0x08,  0x28,  0x08,  0x24,  0x7F,  0x4E,  0x02,  0xF1,  0x22,  0x40,  0x12,  0x40,  0x12,  0x7E,  0x12, 	/* 42030 */
+	0x90,  0x15,  0x10,  0x14,  0xFF,  0x0B,  0x10,  0x0C,  0x18,  0x70,  0x24,  0x00,  0xC2,  0x03,  0x01,  0xA3, 	/* 42040 */
+	0x08,  0x20,  0x08,  0x28,  0x08,  0x44,  0x7F,  0xFA,  0x00,  0x48,  0x24,  0x49,  0x24,  0xA7,  0x15,  0x20, 	/* 42050 */
+	0x14,  0x7C,  0x14,  0x44,  0x08,  0x88,  0x0F,  0x50,  0x18,  0x20,  0x60,  0x50,  0x01,  0x8C,  0x06,  0x03, 	/* 42060 */
+	0xA5,  0x00,  0x80,  0x3F,  0xFE,  0x04,  0x10,  0x02,  0x20,  0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF8,  0x08, 	/* 42070 */
+	0x88,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x00, 	/* 42080 */
+	0x00,  0xA6,  0x08,  0x10,  0x08,  0x10,  0x09,  0xFF,  0x7F,  0x10,  0x02,  0x10,  0x22,  0xFE,  0x12,  0x92, 	/* 42090 */
+	0x12,  0x92,  0x14,  0x92,  0x14,  0xFE,  0x08,  0x38,  0x0E,  0x54,  0x18,  0x92,  0x63,  0x11,  0x00,  0x10, 	/* 420A0 */
+	0x00,  0x10,  0xAA,  0x00,  0x00,  0x3F,  0x7C,  0x24,  0x04,  0x3F,  0x44,  0x21,  0x28,  0x3F,  0x28,  0x24, 	/* 420B0 */
+	0x10,  0x3F,  0x28,  0x20,  0xC6,  0x00,  0x80,  0x3F,  0xFE,  0x04,  0x10,  0x02,  0x10,  0x02,  0x20,  0x7F, 	/* 420C0 */
+	0xFF,  0x00,  0x00,  0xAD,  0x08,  0x00,  0x08,  0xFC,  0x08,  0x84,  0x7E,  0xFC,  0x00,  0x84,  0x44,  0x84, 	/* 420D0 */
+	0x24,  0xFC,  0x24,  0x40,  0x24,  0x7E,  0x28,  0x92,  0x09,  0x9A,  0x16,  0xAA,  0x18,  0xC2,  0x60,  0xFA, 	/* 420E0 */
+	0x00,  0x02,  0x00,  0x0C,  0xAF,  0x00,  0x10,  0x08,  0x92,  0x08,  0x92,  0x08,  0x92,  0x08,  0xFE,  0x7F, 	/* 420F0 */
+	0x00,  0x05,  0xFF,  0x44,  0x20,  0x24,  0x40,  0x29,  0xFE,  0x29,  0x4A,  0x0B,  0x4A,  0x0D,  0x4A,  0x71, 	/* 42100 */
+	0x4A,  0x01,  0x4A,  0x01,  0x06,  0xB0,  0x08,  0x00,  0x09,  0xFF,  0x09,  0x00,  0x7F,  0x7E,  0x01,  0x52, 	/* 42110 */
+	0x45,  0x52,  0x25,  0x7E,  0x25,  0x52,  0x25,  0x7E,  0x29,  0x10,  0x09,  0x10,  0x15,  0xFE,  0x1A,  0x10, 	/* 42120 */
+	0x62,  0x10,  0x05,  0xFF,  0x00,  0x00,  0xB6,  0x04,  0x10,  0x04,  0x10,  0x3F,  0xFE,  0x11,  0x44,  0x0A, 	/* 42130 */
+	0x28,  0x7F,  0xFF,  0x00,  0x00,  0x1F,  0x7C,  0x11,  0x44,  0x11,  0x44,  0x1F,  0x7C,  0x0A,  0x28,  0x0A, 	/* 42140 */
+	0x28,  0x12,  0xA9,  0x23,  0x49,  0x42,  0x87,  0xB8,  0x08,  0x10,  0x3F,  0x7E,  0x12,  0x24,  0x12,  0x24, 	/* 42150 */
+	0x7F,  0xFF,  0x00,  0x00,  0x3E,  0x7C,  0x22,  0x44,  0x3E,  0x7C,  0x22,  0x44,  0x3E,  0x7C,  0x14,  0x28, 	/* 42160 */
+	0x15,  0x28,  0x16,  0x49,  0x2C,  0x89,  0x43,  0x07,  0xB9,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x0F, 	/* 42170 */
+	0xFF,  0x14,  0x48,  0x14,  0x48,  0x24,  0x88,  0x44,  0x08,  0x04,  0x08,  0x04,  0x08,  0x04,  0x08,  0x04, 	/* 42180 */
+	0x08,  0x04,  0x08,  0x04,  0x08,  0x04,  0x08,  0x04,  0x18,  0xBA,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10, 	/* 42190 */
+	0x0F,  0xBF,  0x14,  0x28,  0x12,  0x24,  0x22,  0x44,  0x40,  0x00,  0x00,  0x00,  0x1F,  0xF8,  0x00,  0x00, 	/* 421A0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x00,  0xBF,  0x08,  0x20,  0x08,  0x20,  0x1F, 	/* 421B0 */
+	0xBF,  0x24,  0x48,  0x42,  0x84,  0x00,  0x00,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F, 	/* 421C0 */
+	0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x82,  0x08,  0x20,  0x08,  0x20, 	/* 421D0 */
+	0x1F,  0x7F,  0x14,  0x48,  0x22,  0x84,  0x41,  0x00,  0x01,  0x00,  0x7F,  0xF8,  0x01,  0x08,  0x01,  0x08, 	/* 421E0 */
+	0x19,  0x08,  0x06,  0x08,  0x03,  0x08,  0x04,  0x89,  0x18,  0x49,  0x60,  0x07,  0x84,  0x08,  0x20,  0x08, 	/* 421F0 */
+	0x20,  0x1F,  0x7F,  0x14,  0x50,  0x22,  0x88,  0x40,  0x00,  0x1F,  0xFE,  0x02,  0x10,  0x02,  0x10,  0x02, 	/* 42200 */
+	0x10,  0x7F,  0xFF,  0x02,  0x10,  0x04,  0x10,  0x04,  0x10,  0x08,  0x10,  0x10,  0x10,  0x86,  0x08,  0x20, 	/* 42210 */
+	0x08,  0x20,  0x1F,  0x7F,  0x14,  0x48,  0x22,  0x84,  0x42,  0x04,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84, 	/* 42220 */
+	0x10,  0x84,  0x1F,  0xFC,  0x10,  0x00,  0x10,  0x02,  0x10,  0x02,  0x08,  0x02,  0x07,  0xFE,  0x88,  0x08, 	/* 42230 */
+	0x20,  0x08,  0x20,  0x1F,  0xBF,  0x14,  0x50,  0x22,  0x88,  0x40,  0x00,  0x3F,  0xF0,  0x02,  0x20,  0x02, 	/* 42240 */
+	0x78,  0x03,  0x08,  0x04,  0x90,  0x04,  0x60,  0x08,  0x60,  0x11,  0x90,  0x26,  0x0C,  0x58,  0x03,  0x8A, 	/* 42250 */
+	0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F,  0x14,  0x50,  0x22,  0x88,  0x40,  0x06,  0x00,  0x78,  0x0F,  0x88, 	/* 42260 */
+	0x08,  0x08,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x08,  0x84,  0x10,  0x84,  0x20,  0x82,  0x40,  0x01, 	/* 42270 */
+	0x8B,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F,  0x14,  0x50,  0x22,  0x88,  0x40,  0x00,  0x1F,  0xFC,  0x00, 	/* 42280 */
+	0x84,  0x7F,  0xFF,  0x00,  0x84,  0x00,  0x84,  0x1F,  0xFC,  0x00,  0x80,  0x01,  0x00,  0x06,  0x00,  0x18, 	/* 42290 */
+	0x00,  0x8F,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F,  0x14,  0x50,  0x22,  0x88,  0x44,  0x00,  0x04,  0x00, 	/* 422A0 */
+	0x07,  0xFE,  0x09,  0x12,  0x11,  0x12,  0x22,  0x22,  0x44,  0x22,  0x08,  0x42,  0x10,  0x82,  0x01,  0x04, 	/* 422B0 */
+	0x00,  0x18,  0x91,  0x08,  0x20,  0x08,  0x20,  0x0F,  0x7F,  0x14,  0x48,  0x22,  0x84,  0x40,  0x10,  0x00, 	/* 422C0 */
+	0x60,  0x1F,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x40,  0x02,  0x20,  0x04,  0x10,  0x18, 	/* 422D0 */
+	0x0C,  0x60,  0x03,  0x98,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F,  0x14,  0x50,  0x22,  0x88,  0x43,  0x08, 	/* 422E0 */
+	0x01,  0x00,  0x01,  0xFE,  0x01,  0x00,  0x01,  0x00,  0x1F,  0xF8,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08, 	/* 422F0 */
+	0x1F,  0xF8,  0x00,  0x00,  0x99,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F,  0x14,  0x48,  0x22,  0x84,  0x42, 	/* 42300 */
+	0x04,  0x08,  0x80,  0x08,  0x80,  0x1F,  0xFC,  0x10,  0x80,  0x20,  0x80,  0x0F,  0xFC,  0x00,  0x80,  0x00, 	/* 42310 */
+	0x80,  0x7F,  0xFF,  0x00,  0x00,  0x9B,  0x10,  0x20,  0x10,  0x20,  0x1F,  0xBF,  0x14,  0x50,  0x22,  0x88, 	/* 42320 */
+	0x23,  0x08,  0x41,  0x00,  0x1F,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x1F,  0xF8,  0x11,  0x08,  0x11,  0x08, 	/* 42330 */
+	0x11,  0x08,  0x1F,  0xF8,  0x00,  0x00,  0x9E,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F,  0x14,  0x48,  0x22, 	/* 42340 */
+	0x84,  0x41,  0x00,  0x01,  0x10,  0x02,  0x08,  0x04,  0xFC,  0x7F,  0x02,  0x00,  0x02,  0x1F,  0xF8,  0x10, 	/* 42350 */
+	0x08,  0x10,  0x08,  0x1F,  0xF8,  0x00,  0x00,  0xA0,  0x08,  0x10,  0x08,  0x10,  0x1F,  0xBF,  0x24,  0x28, 	/* 42360 */
+	0x42,  0x44,  0x02,  0x84,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x08,  0x08,  0x08,  0x04,  0x10,  0x02,  0x10, 	/* 42370 */
+	0x02,  0x20,  0x00,  0x40,  0x7F,  0xFF,  0x00,  0x00,  0xA5,  0x08,  0x20,  0x08,  0x20,  0x0F,  0xBF,  0x14, 	/* 42380 */
+	0x48,  0x22,  0x44,  0x40,  0x80,  0x7F,  0xFC,  0x00,  0x04,  0x1F,  0xF4,  0x00,  0x04,  0x0F,  0xE4,  0x08, 	/* 42390 */
+	0x24,  0x08,  0x24,  0x0F,  0xE4,  0x00,  0x04,  0x00,  0x38,  0xA6,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F, 	/* 423A0 */
+	0x14,  0x50,  0x22,  0x88,  0x45,  0x00,  0x04,  0x08,  0x08,  0x08,  0x0B,  0xFF,  0x18,  0x08,  0x29,  0x08, 	/* 423B0 */
+	0x48,  0x88,  0x08,  0x88,  0x08,  0x08,  0x08,  0x08,  0x08,  0x18,  0xA8,  0x08,  0x20,  0x08,  0x20,  0x1F, 	/* 423C0 */
+	0x7F,  0x14,  0x48,  0x22,  0x84,  0x42,  0x84,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0xC0,  0x02,  0xA0,  0x04, 	/* 423D0 */
+	0x90,  0x18,  0x8C,  0x67,  0xF3,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0xAC,  0x10,  0x20,  0x10,  0x20, 	/* 423E0 */
+	0x1F,  0xBF,  0x24,  0x50,  0x42,  0x88,  0x3F,  0xFC,  0x00,  0x84,  0x00,  0x84,  0x1F,  0xFC,  0x10,  0x80, 	/* 423F0 */
+	0x1F,  0xFE,  0x01,  0x82,  0x02,  0x82,  0x0C,  0x84,  0x70,  0x98,  0x00,  0x80,  0xB3,  0x08,  0x20,  0x08, 	/* 42400 */
+	0x20,  0x1F,  0x7F,  0x14,  0x50,  0x22,  0x88,  0x44,  0x08,  0x04,  0x00,  0x3F,  0xBE,  0x04,  0xA2,  0x04, 	/* 42410 */
+	0xA2,  0x04,  0xA2,  0x08,  0xA2,  0x08,  0xA2,  0x10,  0xA2,  0x21,  0x3E,  0x46,  0x00,  0xB5,  0x08,  0x20, 	/* 42420 */
+	0x08,  0x20,  0x1F,  0x7F,  0x14,  0x48,  0x22,  0x84,  0x42,  0x04,  0x08,  0x00,  0x04,  0xFC,  0x44,  0x84, 	/* 42430 */
+	0x20,  0x84,  0x20,  0x84,  0x08,  0x98,  0x08,  0x81,  0x10,  0x81,  0x20,  0x81,  0x40,  0x7F,  0xB6,  0x08, 	/* 42440 */
+	0x20,  0x08,  0x20,  0x1F,  0x7F,  0x14,  0x48,  0x22,  0x84,  0x42,  0x04,  0x04,  0x00,  0x07,  0xF8,  0x08, 	/* 42450 */
+	0x80,  0x10,  0x80,  0x7F,  0xFF,  0x01,  0x40,  0x02,  0x20,  0x04,  0x10,  0x18,  0x0C,  0x60,  0x03,  0xB9, 	/* 42460 */
+	0x08,  0x20,  0x08,  0x20,  0x1F,  0xBF,  0x14,  0x48,  0x22,  0x84,  0x42,  0x04,  0x08,  0x88,  0x08,  0x88, 	/* 42470 */
+	0x7F,  0xFF,  0x08,  0x88,  0x08,  0x88,  0x08,  0xF8,  0x08,  0x00,  0x08,  0x00,  0x0F,  0xFE,  0x00,  0x00, 	/* 42480 */
+	0x85,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F,  0x14,  0x48,  0x22,  0x84,  0x44,  0x80,  0x07,  0xF8,  0x08, 	/* 42490 */
+	0x80,  0x10,  0x80,  0x7F,  0xFF,  0x02,  0x40,  0x02,  0x40,  0x02,  0x40,  0x04,  0x42,  0x18,  0x42,  0x60, 	/* 424A0 */
+	0x3E,  0x86,  0x10,  0x20,  0x10,  0x20,  0x1F,  0x7E,  0x28,  0x90,  0x44,  0x88,  0x1F,  0xF8,  0x00,  0x88, 	/* 424B0 */
+	0x7F,  0xFF,  0x00,  0x88,  0x1F,  0xF8,  0x00,  0x80,  0x1F,  0xF8,  0x00,  0x80,  0x7F,  0xFE,  0x00,  0x80, 	/* 424C0 */
+	0x00,  0x80,  0x88,  0x08,  0x20,  0x08,  0x20,  0x0F,  0x7F,  0x14,  0x50,  0x22,  0x88,  0x40,  0x34,  0x0F, 	/* 424D0 */
+	0xC0,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F, 	/* 424E0 */
+	0xF8,  0x00,  0x00,  0x89,  0x10,  0x20,  0x10,  0x20,  0x1F,  0x7F,  0x28,  0x88,  0x44,  0x84,  0x1F,  0xFC, 	/* 424F0 */
+	0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x10,  0x00,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x02,  0x10, 	/* 42500 */
+	0x02,  0x10,  0x00,  0x30,  0x8B,  0x10,  0x20,  0x10,  0x20,  0x1F,  0x3F,  0x24,  0x48,  0x22,  0x44,  0x40, 	/* 42510 */
+	0xA0,  0x1E,  0x20,  0x12,  0xFE,  0x12,  0x22,  0x1E,  0x22,  0x12,  0x22,  0x12,  0x22,  0x1E,  0x42,  0x22, 	/* 42520 */
+	0x42,  0x22,  0x82,  0x47,  0x0C,  0x8C,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F,  0x14,  0x48,  0x22,  0x84, 	/* 42530 */
+	0x40,  0x80,  0x01,  0x40,  0x06,  0x30,  0x18,  0x0C,  0x6F,  0xFB,  0x00,  0x80,  0x0F,  0xF8,  0x00,  0x80, 	/* 42540 */
+	0x00,  0x80,  0x3F,  0xFE,  0x00,  0x00,  0x8D,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F,  0x14,  0x48,  0x22, 	/* 42550 */
+	0x84,  0x4A,  0x04,  0x08,  0x00,  0x1F,  0xFE,  0x10,  0x02,  0x27,  0xE2,  0x44,  0x22,  0x07,  0xE2,  0x04, 	/* 42560 */
+	0x22,  0x04,  0x22,  0x07,  0xE2,  0x00,  0x0C,  0x8F,  0x08,  0x10,  0x08,  0x10,  0x1F,  0xBF,  0x14,  0x28, 	/* 42570 */
+	0x22,  0x44,  0x44,  0x48,  0x04,  0x44,  0x08,  0x44,  0x13,  0xFF,  0x30,  0x20,  0x50,  0x22,  0x10,  0x14, 	/* 42580 */
+	0x10,  0x18,  0x10,  0x69,  0x13,  0x85,  0x10,  0x03,  0x90,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F,  0x14, 	/* 42590 */
+	0x48,  0x22,  0x84,  0x5F,  0xFE,  0x10,  0x00,  0x17,  0xFE,  0x10,  0x40,  0x13,  0xFC,  0x10,  0x40,  0x10, 	/* 425A0 */
+	0x40,  0x17,  0xFE,  0x10,  0x00,  0x1F,  0xFF,  0x00,  0x00,  0x91,  0x10,  0x20,  0x10,  0x20,  0x1F,  0x7F, 	/* 425B0 */
+	0x24,  0x48,  0x22,  0x84,  0x42,  0x04,  0x00,  0x00,  0x3E,  0x7C,  0x08,  0x44,  0x08,  0x64,  0x08,  0x54, 	/* 425C0 */
+	0x08,  0x54,  0x0E,  0x84,  0x18,  0x85,  0x61,  0x05,  0x02,  0x03,  0x92,  0x10,  0x20,  0x10,  0x20,  0x3F, 	/* 425D0 */
+	0x7E,  0x28,  0x90,  0x45,  0x08,  0x3F,  0xFC,  0x20,  0x04,  0x2F,  0xF4,  0x20,  0x04,  0x27,  0xE4,  0x24, 	/* 425E0 */
+	0x24,  0x24,  0x24,  0x27,  0xE4,  0x20,  0x04,  0x20,  0x04,  0x20,  0x0C,  0x94,  0x08,  0x20,  0x08,  0x20, 	/* 425F0 */
+	0x0F,  0x3F,  0x14,  0x50,  0x22,  0x88,  0x41,  0x40,  0x02,  0x20,  0x04,  0x10,  0x1F,  0xFC,  0x60,  0x03, 	/* 42600 */
+	0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x96,  0x08,  0x10,  0x08, 	/* 42610 */
+	0x10,  0x1F,  0xBF,  0x14,  0x28,  0x22,  0x44,  0x40,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x1F,  0xFC,  0x10, 	/* 42620 */
+	0x84,  0x11,  0xC4,  0x12,  0xAC,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0x9D,  0x08,  0x20, 	/* 42630 */
+	0x08,  0x20,  0x1F,  0x7F,  0x14,  0x88,  0x21,  0x04,  0x43,  0xF0,  0x0C,  0x20,  0x37,  0xFC,  0x00,  0x84, 	/* 42640 */
+	0x7F,  0xFF,  0x00,  0x84,  0x00,  0x84,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x01,  0x80,  0xA5,  0x08, 	/* 42650 */
+	0x20,  0x08,  0x20,  0x1F,  0x7F,  0x14,  0x48,  0x22,  0x84,  0x4F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F, 	/* 42660 */
+	0xF8,  0x00,  0x80,  0x01,  0x00,  0x1F,  0xFC,  0x10,  0x04,  0x10,  0x04,  0x1F,  0xFC,  0x00,  0x00,  0xA7, 	/* 42670 */
+	0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F,  0x14,  0x50,  0x22,  0x88,  0x4F,  0xF8,  0x08,  0x08,  0x0F,  0xF8, 	/* 42680 */
+	0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x01,  0x21,  0x02,  0x21,  0x0C,  0x21,  0x70,  0x1F, 	/* 42690 */
+	0xAC,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F,  0x14,  0x48,  0x22,  0xA4,  0x40,  0x28,  0x00,  0x24,  0x1F, 	/* 426A0 */
+	0xFF,  0x10,  0x20,  0x10,  0x24,  0x1F,  0x24,  0x11,  0x18,  0x11,  0x11,  0x21,  0x29,  0x26,  0x47,  0x40, 	/* 426B0 */
+	0x81,  0xAE,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F,  0x14,  0x48,  0x22,  0x84,  0x40,  0x00,  0x3F,  0xFE, 	/* 426C0 */
+	0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x0C,  0x8C,  0x12,  0x92,  0x20,  0xA0,  0x00,  0x80,  0x7F,  0xFF, 	/* 426D0 */
+	0x00,  0x00,  0xB0,  0x08,  0x10,  0x08,  0x10,  0x1F,  0xBF,  0x14,  0x28,  0x22,  0x44,  0x44,  0x40,  0x04, 	/* 426E0 */
+	0x40,  0x08,  0x7F,  0x18,  0xA0,  0x29,  0x20,  0x4A,  0x3E,  0x08,  0x20,  0x08,  0x20,  0x08,  0x3E,  0x08, 	/* 426F0 */
+	0x20,  0x08,  0x20,  0xB1,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F,  0x14,  0x48,  0x22,  0x84,  0x44,  0x20, 	/* 42700 */
+	0x04,  0x20,  0x09,  0x3F,  0x09,  0x44,  0x19,  0x64,  0x29,  0xA4,  0x49,  0x14,  0x09,  0x08,  0x09,  0x14, 	/* 42710 */
+	0x08,  0x62,  0x09,  0x81,  0xB4,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F,  0x14,  0x48,  0x22,  0x84,  0x40, 	/* 42720 */
+	0x80,  0x3F,  0xFE,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x15,  0x54,  0x13,  0x62,  0x22,  0x20,  0x04, 	/* 42730 */
+	0x10,  0x18,  0x0C,  0x60,  0x03,  0xB5,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F,  0x14,  0x50,  0x22,  0x88, 	/* 42740 */
+	0x40,  0x02,  0x7E,  0x0C,  0x05,  0xF0,  0x08,  0x10,  0x1C,  0x9E,  0x04,  0x90,  0x24,  0x90,  0x14,  0x90, 	/* 42750 */
+	0x08,  0xFE,  0x16,  0x00,  0x61,  0xFF,  0xBA,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F,  0x14,  0x48,  0x22, 	/* 42760 */
+	0x84,  0x7F,  0xFE,  0x20,  0x00,  0x27,  0xFC,  0x20,  0x40,  0x23,  0xF8,  0x20,  0x50,  0x20,  0x48,  0x2F, 	/* 42770 */
+	0xFE,  0x20,  0x00,  0x3F,  0xFE,  0x00,  0x00,  0x86,  0x10,  0x20,  0x10,  0x20,  0x3F,  0x7F,  0x28,  0x90, 	/* 42780 */
+	0x44,  0x88,  0x1F,  0xFC,  0x10,  0x84,  0x11,  0x44,  0x16,  0x34,  0x00,  0x0C,  0x10,  0x44,  0x1E,  0x48, 	/* 42790 */
+	0x10,  0x70,  0x10,  0x42,  0x1F,  0x42,  0x70,  0x3E,  0x87,  0x10,  0x20,  0x10,  0x20,  0x3F,  0xBF,  0x24, 	/* 427A0 */
+	0x50,  0x42,  0x88,  0x3F,  0xFC,  0x21,  0x04,  0x21,  0x04,  0x3F,  0xFC,  0x21,  0x04,  0x27,  0xE4,  0x24, 	/* 427B0 */
+	0x24,  0x27,  0xE4,  0x20,  0x04,  0x3F,  0xFC,  0x00,  0x00,  0x8B,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F, 	/* 427C0 */
+	0x24,  0x90,  0x42,  0x08,  0x00,  0x90,  0x3F,  0xFE,  0x00,  0x48,  0x00,  0xF2,  0x1F,  0x0E,  0x00,  0x90, 	/* 427D0 */
+	0x7F,  0xFF,  0x00,  0x4C,  0x00,  0xF1,  0x3F,  0x19,  0x00,  0x07,  0x8D,  0x08,  0x20,  0x08,  0x20,  0x1F, 	/* 427E0 */
+	0x7F,  0x14,  0x50,  0x2A,  0x88,  0x49,  0xFF,  0x09,  0x10,  0x7F,  0x10,  0x09,  0x7E,  0x09,  0x52,  0x0F, 	/* 427F0 */
+	0x52,  0x79,  0x56,  0x09,  0x10,  0x09,  0x10,  0x09,  0xFF,  0x18,  0x00,  0x8F,  0x08,  0x20,  0x08,  0x20, 	/* 42800 */
+	0x1F,  0x7F,  0x24,  0x48,  0x42,  0x9C,  0x1F,  0xE8,  0x08,  0x84,  0x08,  0x42,  0x17,  0xFC,  0x00,  0x84, 	/* 42810 */
+	0x7F,  0xFF,  0x00,  0x84,  0x0F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x01,  0x80,  0x92,  0x10,  0x20,  0x1F, 	/* 42820 */
+	0x3F,  0x24,  0x48,  0x42,  0x84,  0x0F,  0xF0,  0x00,  0x10,  0x1F,  0xFC,  0x00,  0x10,  0x0F,  0xF0,  0x00, 	/* 42830 */
+	0x00,  0x3F,  0xFE,  0x20,  0x82,  0x2F,  0xFA,  0x08,  0x88,  0x08,  0xB0,  0x00,  0x80,  0x94,  0x10,  0x40, 	/* 42840 */
+	0x10,  0x40,  0x1F,  0x7E,  0x28,  0x90,  0x25,  0x28,  0x40,  0x20,  0x30,  0x40,  0x09,  0xFC,  0x01,  0x04, 	/* 42850 */
+	0x61,  0x04,  0x11,  0xFC,  0x01,  0x04,  0x09,  0x04,  0x11,  0x04,  0x21,  0xFC,  0x40,  0x00,  0x95,  0x08, 	/* 42860 */
+	0x20,  0x08,  0x20,  0x1F,  0xBF,  0x14,  0x48,  0x22,  0x84,  0x44,  0x10,  0x3F,  0xFE,  0x04,  0x10,  0x07, 	/* 42870 */
+	0xF0,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x7F,  0xFF,  0x02,  0x30,  0x0C,  0x0C,  0x30,  0x02,  0x97, 	/* 42880 */
+	0x10,  0x20,  0x10,  0x20,  0x1F,  0x7F,  0x24,  0x90,  0x22,  0x08,  0x4F,  0xF8,  0x08,  0x08,  0x0F,  0xF8, 	/* 42890 */
+	0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x02,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x08,  0x20, 	/* 428A0 */
+	0x98,  0x10,  0x20,  0x10,  0x20,  0x3F,  0x7F,  0x24,  0x48,  0x42,  0x84,  0x3F,  0xFE,  0x20,  0x22,  0x23, 	/* 428B0 */
+	0xC2,  0x20,  0x82,  0x3F,  0xFE,  0x21,  0xC2,  0x26,  0xB2,  0x38,  0x8E,  0x20,  0x82,  0x3F,  0xFE,  0x00, 	/* 428C0 */
+	0x00,  0x99,  0x10,  0x20,  0x10,  0x20,  0x3F,  0x7F,  0x24,  0x48,  0x42,  0x84,  0x3E,  0x7E,  0x22,  0x42, 	/* 428D0 */
+	0x22,  0x44,  0x3E,  0x7E,  0x22,  0x52,  0x22,  0x52,  0x3E,  0x4C,  0x22,  0x44,  0x22,  0x4C,  0x22,  0x52, 	/* 428E0 */
+	0x46,  0x61,  0x9A,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x3F,  0x14,  0x48,  0x22,  0x84,  0x44,  0x02,  0x06, 	/* 428F0 */
+	0x12,  0x09,  0x12,  0x1F,  0x92,  0x20,  0x52,  0x5F,  0xB2,  0x10,  0x92,  0x10,  0x92,  0x10,  0x82,  0x1F, 	/* 42900 */
+	0x82,  0x00,  0x06,  0x9C,  0x10,  0x20,  0x10,  0x20,  0x3F,  0x7F,  0x24,  0x50,  0x42,  0x88,  0x3F,  0xFE, 	/* 42910 */
+	0x21,  0x42,  0x22,  0x46,  0x0C,  0x3C,  0x70,  0x00,  0x1F,  0xF8,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 42920 */
+	0x7F,  0xFE,  0x00,  0x00,  0x9D,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F,  0x14,  0x48,  0x22,  0x84,  0x42, 	/* 42930 */
+	0x00,  0x08,  0x44,  0x08,  0x44,  0x7E,  0xFF,  0x08,  0x44,  0x08,  0x44,  0x0E,  0x7C,  0x78,  0x44,  0x08, 	/* 42940 */
+	0x44,  0x08,  0x7C,  0x18,  0x00,  0x9F,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F,  0x14,  0x48,  0x22,  0x84, 	/* 42950 */
+	0x4F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x20,  0x08,  0x22,  0x0F,  0xBC, 	/* 42960 */
+	0x08,  0x21,  0x0F,  0xA1,  0x78,  0x1F,  0xA1,  0x08,  0x10,  0x08,  0x10,  0x1F,  0xBF,  0x24,  0x48,  0x42, 	/* 42970 */
+	0x84,  0x7F,  0xFE,  0x40,  0x02,  0x4F,  0xF2,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x00,  0x0F, 	/* 42980 */
+	0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0xAA,  0x10,  0x10,  0x10,  0x10,  0x1F,  0xBF,  0x22,  0x50, 	/* 42990 */
+	0x29,  0x08,  0x44,  0x88,  0x04,  0x90,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8, 	/* 429A0 */
+	0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0xAD,  0x10,  0x20,  0x10,  0x20,  0x3F,  0x7F,  0x24, 	/* 429B0 */
+	0x50,  0x44,  0x88,  0x02,  0x10,  0x7F,  0xFF,  0x00,  0x00,  0x1F,  0x24,  0x11,  0x24,  0x1F,  0x24,  0x11, 	/* 429C0 */
+	0x24,  0x1F,  0x24,  0x11,  0x24,  0x11,  0x24,  0x13,  0x0C,  0xB1,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F, 	/* 429D0 */
+	0x14,  0x48,  0x22,  0x84,  0x44,  0x00,  0x04,  0x7E,  0x7F,  0x42,  0x0C,  0x42,  0x0E,  0x7E,  0x15,  0x42, 	/* 429E0 */
+	0x24,  0xFE,  0x24,  0x42,  0x44,  0x42,  0x04,  0x7E,  0x04,  0x00,  0xB4,  0x08,  0x20,  0x08,  0x20,  0x1F, 	/* 429F0 */
+	0x7F,  0x14,  0x48,  0x22,  0x94,  0x40,  0x14,  0x1F,  0xFF,  0x10,  0x10,  0x17,  0xD2,  0x10,  0x12,  0x17, 	/* 42A00 */
+	0xD4,  0x14,  0x4C,  0x14,  0x49,  0x27,  0xD5,  0x20,  0x23,  0x40,  0x41,  0xB8,  0x08,  0x20,  0x08,  0x20, 	/* 42A10 */
+	0x1F,  0x7F,  0x14,  0x50,  0x22,  0x88,  0x5F,  0xFC,  0x00,  0x88,  0x00,  0x90,  0x7F,  0xFF,  0x00,  0x80, 	/* 42A20 */
+	0x07,  0xF8,  0x1C,  0x08,  0x67,  0xF8,  0x04,  0x08,  0x04,  0x08,  0x07,  0xF8,  0x80,  0x10,  0x40,  0x10, 	/* 42A30 */
+	0x40,  0x3F,  0x7E,  0x28,  0xA0,  0x45,  0x10,  0x00,  0x00,  0x3F,  0x7C,  0x21,  0x44,  0x3F,  0x44,  0x21, 	/* 42A40 */
+	0x44,  0x3F,  0x44,  0x24,  0x44,  0x22,  0x44,  0x3D,  0x58,  0x61,  0x40,  0x00,  0x40,  0x81,  0x08,  0x20, 	/* 42A50 */
+	0x08,  0x20,  0x1F,  0x7F,  0x14,  0x50,  0x22,  0x88,  0x4F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08, 	/* 42A60 */
+	0x0F,  0xF8,  0x3F,  0xFE,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x84,  0x08, 	/* 42A70 */
+	0x20,  0x08,  0x20,  0x1F,  0xFF,  0x14,  0x50,  0x22,  0x88,  0x44,  0x00,  0x3F,  0xBE,  0x04,  0x22,  0x1F, 	/* 42A80 */
+	0xA2,  0x14,  0xA2,  0x1F,  0xA2,  0x14,  0xAC,  0x1F,  0xA0,  0x04,  0x21,  0x3F,  0xA1,  0x04,  0x1F,  0x86, 	/* 42A90 */
+	0x08,  0x20,  0x1F,  0x7F,  0x14,  0x48,  0x22,  0x84,  0x43,  0xF0,  0x04,  0x10,  0x0F,  0xE0,  0x00,  0x20, 	/* 42AA0 */
+	0x7F,  0xFF,  0x03,  0x04,  0x3C,  0x98,  0x03,  0x50,  0x3C,  0xA8,  0x03,  0x24,  0x7C,  0x23,  0x00,  0xC0, 	/* 42AB0 */
+	0x87,  0x10,  0x20,  0x1F,  0x3F,  0x24,  0x48,  0x42,  0x84,  0x7F,  0xFF,  0x00,  0x00,  0x1F,  0xFC,  0x10, 	/* 42AC0 */
+	0x04,  0x1F,  0xFC,  0x10,  0x00,  0x1F,  0xFC,  0x19,  0x24,  0x2F,  0xFC,  0x29,  0x24,  0x49,  0x24,  0x08, 	/* 42AD0 */
+	0x0C,  0x89,  0x10,  0x20,  0x10,  0x20,  0x3F,  0x7F,  0x24,  0x90,  0x42,  0x08,  0x3F,  0x7C,  0x08,  0x44, 	/* 42AE0 */
+	0x08,  0x64,  0x0F,  0x55,  0x70,  0x93,  0x00,  0x80,  0x7F,  0xFE,  0x01,  0xC0,  0x0E,  0xB8,  0x70,  0x87, 	/* 42AF0 */
+	0x00,  0x80,  0x8B,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F,  0x24,  0x48,  0x42,  0x84,  0x3F,  0xFE,  0x20, 	/* 42B00 */
+	0x80,  0x2F,  0xFC,  0x24,  0x90,  0x24,  0x90,  0x2A,  0xA8,  0x31,  0x44,  0x22,  0x30,  0x2C,  0x0C,  0x3F, 	/* 42B10 */
+	0xFE,  0x20,  0x00,  0x8C,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F,  0x14,  0x48,  0x22,  0x84,  0x44,  0x00, 	/* 42B20 */
+	0x04,  0xF8,  0x08,  0x08,  0x13,  0xFF,  0x30,  0x80,  0x50,  0xFC,  0x11,  0x10,  0x13,  0xFF,  0x10,  0x28, 	/* 42B30 */
+	0x10,  0xC4,  0x13,  0x03,  0x8F,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F,  0x14,  0x48,  0x22,  0x84,  0x40, 	/* 42B40 */
+	0x20,  0x11,  0x20,  0x11,  0x3F,  0x7F,  0xA1,  0x11,  0x4A,  0x11,  0x88,  0x1F,  0x18,  0x11,  0x14,  0x11, 	/* 42B50 */
+	0x24,  0x1F,  0x42,  0x01,  0x81,  0x9D,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F,  0x14,  0x90,  0x22,  0x28, 	/* 42B60 */
+	0x5F,  0xFC,  0x02,  0x20,  0x1F,  0xFC,  0x02,  0x20,  0x7F,  0xFF,  0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88, 	/* 42B70 */
+	0x7F,  0xFF,  0x08,  0x08,  0x08,  0x18,  0xA0,  0x10,  0x40,  0x1F,  0x7F,  0x24,  0x50,  0x22,  0x88,  0x44, 	/* 42B80 */
+	0x40,  0x04,  0x7F,  0x0C,  0xA4,  0x0F,  0x18,  0x14,  0x34,  0x35,  0xC3,  0x54,  0x10,  0x15,  0xFF,  0x14, 	/* 42B90 */
+	0x38,  0x14,  0x54,  0x11,  0x93,  0x10,  0x10,  0xA4,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xBF,  0x14,  0x48, 	/* 42BA0 */
+	0x22,  0x84,  0x4F,  0xFC,  0x08,  0x80,  0x0F,  0xF8,  0x08,  0x80,  0x0F,  0xF8,  0x08,  0x80,  0x0F,  0xFE, 	/* 42BB0 */
+	0x24,  0x92,  0x22,  0x4A,  0x22,  0x42,  0x40,  0x0C,  0xA5,  0x10,  0x20,  0x10,  0x20,  0x3F,  0x7F,  0x24, 	/* 42BC0 */
+	0x50,  0x42,  0x88,  0x3F,  0xFE,  0x02,  0x20,  0x1F,  0xFC,  0x12,  0x24,  0x1F,  0xFC,  0x00,  0x80,  0x7F, 	/* 42BD0 */
+	0xFF,  0x02,  0xA0,  0x0C,  0x98,  0x70,  0x87,  0x00,  0x80,  0xA6,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F, 	/* 42BE0 */
+	0x24,  0x48,  0x42,  0x84,  0x0F,  0xFC,  0x09,  0x24,  0x08,  0xC4,  0x09,  0x24,  0x0F,  0xFC,  0x00,  0x00, 	/* 42BF0 */
+	0x08,  0x22,  0x0F,  0xBC,  0x08,  0x21,  0x0F,  0xA1,  0x78,  0x1F,  0xA9,  0x08,  0x20,  0x08,  0x20,  0x1F, 	/* 42C00 */
+	0x7F,  0x24,  0x50,  0x42,  0x88,  0x08,  0x00,  0x3E,  0xFF,  0x22,  0x10,  0x22,  0x7E,  0x3E,  0x52,  0x20, 	/* 42C10 */
+	0x52,  0x3E,  0x52,  0x22,  0x52,  0x22,  0x56,  0x3E,  0x10,  0x00,  0x10,  0xAD,  0x10,  0x20,  0x1F,  0xBF, 	/* 42C20 */
+	0x14,  0x48,  0x22,  0x84,  0x40,  0x80,  0x1F,  0xFC,  0x02,  0x20,  0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF8, 	/* 42C30 */
+	0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xFA,  0x00,  0x82,  0x00,  0x7E,  0xB3,  0x10,  0x20,  0x1F, 	/* 42C40 */
+	0x3F,  0x24,  0x50,  0x42,  0x88,  0x1F,  0xFC,  0x10,  0x84,  0x1F,  0xFC,  0x10,  0x84,  0x1F,  0xFC,  0x7F, 	/* 42C50 */
+	0xFF,  0x04,  0x90,  0x3F,  0xFE,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0xB6,  0x10,  0x20, 	/* 42C60 */
+	0x10,  0x20,  0x3F,  0x7F,  0x24,  0x48,  0x42,  0x84,  0x3F,  0xFE,  0x00,  0x80,  0x08,  0xF8,  0x08,  0x80, 	/* 42C70 */
+	0x7F,  0xFF,  0x08,  0x00,  0x0F,  0xFC,  0x08,  0x00,  0x2F,  0xFE,  0x24,  0x92,  0x42,  0x5C,  0xB7,  0x10, 	/* 42C80 */
+	0x20,  0x1F,  0x3F,  0x24,  0x48,  0x42,  0xA4,  0x10,  0x7C,  0x09,  0xC8,  0x08,  0x30,  0x20,  0x6C,  0x13, 	/* 42C90 */
+	0x93,  0x79,  0xFC,  0x08,  0x10,  0x08,  0xFC,  0x08,  0x10,  0x1F,  0xFF,  0x22,  0x10,  0x41,  0xFF,  0x80, 	/* 42CA0 */
+	0x10,  0x20,  0x1F,  0x3F,  0x14,  0x48,  0x22,  0x84,  0x5F,  0xFE,  0x00,  0x80,  0x0F,  0xF8,  0x00,  0x80, 	/* 42CB0 */
+	0x7F,  0xFF,  0x08,  0x08,  0x0F,  0xE8,  0x0B,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x06,  0x18,  0x38,  0x06, 	/* 42CC0 */
+	0x87,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F,  0x14,  0x48,  0x22,  0xA4,  0x48,  0x20,  0x08,  0x7E,  0x7F, 	/* 42CD0 */
+	0x40,  0x10,  0xA0,  0x1E,  0x3E,  0x12,  0x48,  0x12,  0x08,  0x22,  0xFF,  0x22,  0x14,  0x42,  0x22,  0x0C, 	/* 42CE0 */
+	0xC1,  0x8D,  0x10,  0x20,  0x1F,  0x3F,  0x24,  0x50,  0x42,  0x88,  0x1F,  0xFC,  0x10,  0x84,  0x7F,  0xFF, 	/* 42CF0 */
+	0x10,  0x84,  0x1F,  0xFC,  0x08,  0x88,  0x0F,  0xF8,  0x01,  0x00,  0x7F,  0xFF,  0x06,  0x10,  0x01,  0xF0, 	/* 42D00 */
+	0x3E,  0x0C,  0x91,  0x10,  0x20,  0x10,  0x20,  0x3F,  0x7F,  0x24,  0x50,  0x42,  0x88,  0x3F,  0xFE,  0x00, 	/* 42D10 */
+	0x00,  0x0F,  0xF8,  0x08,  0x08,  0x7F,  0xFF,  0x08,  0x08,  0x0F,  0xFA,  0x02,  0x44,  0x0C,  0x28,  0x77, 	/* 42D20 */
+	0x98,  0x0C,  0x07,  0x92,  0x10,  0x20,  0x1F,  0x3F,  0x24,  0x44,  0x4F,  0xF8,  0x08,  0x08,  0x0F,  0xE8, 	/* 42D30 */
+	0x0B,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x01,  0x00,  0x7F,  0xFF,  0x05,  0x10,  0x1A,  0x8C,  0x64,  0xA3, 	/* 42D40 */
+	0x19,  0x10,  0x07,  0xE8,  0x93,  0x08,  0x20,  0x08,  0x20,  0x1F,  0x7F,  0x14,  0x50,  0x22,  0x8C,  0x5F, 	/* 42D50 */
+	0xC4,  0x12,  0x48,  0x17,  0x4A,  0x12,  0x54,  0x1F,  0xC5,  0x12,  0x49,  0x17,  0x52,  0x15,  0x42,  0x27, 	/* 42D60 */
+	0x44,  0x20,  0x48,  0x40,  0xD0,  0x94,  0x10,  0x20,  0x10,  0x20,  0x3F,  0x7F,  0x24,  0x48,  0x42,  0x88, 	/* 42D70 */
+	0x3F,  0xFE,  0x00,  0x00,  0x1F,  0xFC,  0x04,  0x08,  0x7F,  0xFF,  0x04,  0x08,  0x1F,  0xFC,  0x02,  0x42, 	/* 42D80 */
+	0x0C,  0x24,  0x77,  0x98,  0x0C,  0x07,  0x97,  0x10,  0x20,  0x1F,  0x3F,  0x24,  0x48,  0x42,  0x84,  0x18, 	/* 42D90 */
+	0xFC,  0x04,  0x24,  0x31,  0x26,  0x09,  0x45,  0x1A,  0x44,  0x60,  0x98,  0x00,  0x80,  0x7F,  0xFF,  0x02, 	/* 42DA0 */
+	0xA0,  0x0C,  0x9C,  0x70,  0x83,  0x00,  0x80,  0x9F,  0x10,  0x20,  0x1F,  0x3F,  0x24,  0x48,  0x42,  0x84, 	/* 42DB0 */
+	0x7F,  0xFF,  0x02,  0x20,  0x1F,  0xFC,  0x12,  0x24,  0x1F,  0xFC,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08, 	/* 42DC0 */
+	0x0F,  0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0xA1,  0x10,  0x20,  0x1F,  0xBF,  0x24,  0x50,  0x42, 	/* 42DD0 */
+	0x88,  0x3F,  0x7E,  0x21,  0x42,  0x3F,  0x7E,  0x21,  0x42,  0x3F,  0x7E,  0x20,  0x02,  0x27,  0xE2,  0x24, 	/* 42DE0 */
+	0x22,  0x27,  0xE2,  0x24,  0x22,  0x27,  0xE2,  0x20,  0x06,  0xA3,  0x10,  0x20,  0x1F,  0x7F,  0x24,  0x48, 	/* 42DF0 */
+	0x42,  0x84,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x0F,  0xF8,  0x08,  0x08, 	/* 42E00 */
+	0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x06,  0x18,  0x38,  0x06,  0xA7,  0x10,  0x20,  0x1F,  0x3F,  0x24, 	/* 42E10 */
+	0x48,  0x42,  0xA4,  0x3F,  0xFE,  0x02,  0x20,  0x03,  0xE0,  0x7F,  0xFF,  0x00,  0x80,  0x0F,  0xF8,  0x08, 	/* 42E20 */
+	0x88,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x06,  0x18,  0x38,  0x06,  0xAA,  0x10,  0x20,  0x1F,  0x3F, 	/* 42E30 */
+	0x24,  0x48,  0x42,  0x84,  0x1F,  0x3E,  0x12,  0x24,  0x7F,  0x7F,  0x06,  0x8C,  0x1B,  0x35,  0x62,  0xC7, 	/* 42E40 */
+	0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0xAB,  0x10,  0x20,  0x1F, 	/* 42E50 */
+	0x7F,  0x24,  0x48,  0x42,  0x84,  0x1F,  0xFC,  0x00,  0x84,  0x7F,  0xFF,  0x00,  0x84,  0x1F,  0xFC,  0x04, 	/* 42E60 */
+	0x90,  0x14,  0x94,  0x1F,  0xFC,  0x10,  0x84,  0x1C,  0xBC,  0x24,  0xA4,  0x44,  0xA4,  0xB7,  0x10,  0x20, 	/* 42E70 */
+	0x1F,  0x7F,  0x24,  0x90,  0x43,  0xE8,  0x04,  0x40,  0x1F,  0xFF,  0x71,  0x11,  0x12,  0xEA,  0x1F,  0xFE, 	/* 42E80 */
+	0x10,  0x00,  0x13,  0xF8,  0x10,  0x00,  0x27,  0xFC,  0x24,  0x04,  0x47,  0xFC,  0x00,  0x00,  0xB8,  0x10, 	/* 42E90 */
+	0x20,  0x10,  0x20,  0x3F,  0x7F,  0x28,  0x50,  0x44,  0x88,  0x12,  0x08,  0x7F,  0xFF,  0x12,  0x4A,  0x1E, 	/* 42EA0 */
+	0x48,  0x12,  0x7E,  0x1E,  0x52,  0x12,  0x52,  0x7F,  0xCC,  0x12,  0x8C,  0x21,  0x12,  0x42,  0x61,  0xBD, 	/* 42EB0 */
+	0x10,  0x20,  0x10,  0x20,  0x3F,  0x7F,  0x28,  0x48,  0x44,  0x84,  0x01,  0x40,  0x02,  0x30,  0x0F,  0xEC, 	/* 42EC0 */
+	0x70,  0x03,  0x1F,  0x7C,  0x11,  0x44,  0x1F,  0x7C,  0x04,  0x10,  0x06,  0x18,  0x09,  0x24,  0x30,  0x44, 	/* 42ED0 */
+	0xBE,  0x10,  0x20,  0x1F,  0xBF,  0x28,  0x50,  0x44,  0x88,  0x1F,  0xFE,  0x12,  0x10,  0x11,  0x20,  0x1F, 	/* 42EE0 */
+	0xFE,  0x11,  0x24,  0x1F,  0xFF,  0x11,  0x24,  0x17,  0xFC,  0x23,  0x30,  0x25,  0x2C,  0x59,  0x23,  0x01, 	/* 42EF0 */
+	0x20,  0xBF,  0x10,  0x20,  0x10,  0x20,  0x1F,  0x7F,  0x24,  0x90,  0x42,  0x24,  0x27,  0xFF,  0x10,  0x20, 	/* 42F00 */
+	0x11,  0xFC,  0x41,  0x24,  0x21,  0xFC,  0x21,  0x24,  0x09,  0xFC,  0x08,  0x08,  0x17,  0xFF,  0x21,  0x08, 	/* 42F10 */
+	0x40,  0x98,  0x80,  0x10,  0x20,  0x10,  0x20,  0x3F,  0x7F,  0x24,  0x88,  0x52,  0x20,  0x11,  0xDE,  0x11, 	/* 42F20 */
+	0x0A,  0x7D,  0x4A,  0x11,  0xB2,  0x16,  0x26,  0x19,  0xFC,  0x71,  0x24,  0x11,  0xFC,  0x11,  0x24,  0x11, 	/* 42F30 */
+	0xFC,  0x30,  0x00,  0x83,  0x10,  0x20,  0x1F,  0x3F,  0x24,  0x50,  0x42,  0x88,  0x3F,  0x90,  0x24,  0x1F, 	/* 42F40 */
+	0x3F,  0x20,  0x21,  0x40,  0x3F,  0x1E,  0x24,  0x00,  0x3F,  0x80,  0x1F,  0xFC,  0x12,  0x24,  0x12,  0x24, 	/* 42F50 */
+	0x7F,  0xFF,  0x00,  0x00,  0x8C,  0x10,  0x20,  0x1F,  0x7F,  0x24,  0x88,  0x5F,  0xFC,  0x00,  0x80,  0x0F, 	/* 42F60 */
+	0xF8,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x82,  0x0F,  0xF8,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x04,  0x1F, 	/* 42F70 */
+	0x7F,  0x11,  0x24,  0x1F,  0x0C,  0x8D,  0x10,  0x20,  0x1F,  0xBF,  0x24,  0x48,  0x42,  0x84,  0x08,  0x24, 	/* 42F80 */
+	0x3E,  0xFF,  0x08,  0x24,  0x3E,  0x24,  0x08,  0xFF,  0x7F,  0x00,  0x08,  0x7E,  0x1C,  0x42,  0x1A,  0x7E, 	/* 42F90 */
+	0x29,  0x42,  0x48,  0x7E,  0x08,  0x00,  0x8F,  0x10,  0x20,  0x1F,  0x3F,  0x24,  0x50,  0x42,  0x88,  0x08, 	/* 42FA0 */
+	0x40,  0x08,  0xFF,  0x7F,  0x24,  0x10,  0xFF,  0x10,  0x24,  0x1E,  0x3C,  0x12,  0x24,  0x12,  0x3C,  0x22, 	/* 42FB0 */
+	0x24,  0x22,  0xFF,  0x42,  0x24,  0x0C,  0xC2,  0x90,  0x10,  0x10,  0x1F,  0xBF,  0x24,  0x28,  0x42,  0x44, 	/* 42FC0 */
+	0x00,  0x54,  0x3C,  0x92,  0x25,  0x7E,  0x24,  0x28,  0x3D,  0xFF,  0x24,  0x48,  0x24,  0x94,  0x3D,  0x57, 	/* 42FD0 */
+	0x24,  0x38,  0x24,  0x54,  0x25,  0x93,  0x4C,  0x30,  0x94,  0x10,  0x20,  0x1F,  0x3F,  0x24,  0x50,  0x42, 	/* 42FE0 */
+	0x88,  0x1F,  0x10,  0x15,  0x1F,  0x7F,  0xA4,  0x15,  0x24,  0x1F,  0x44,  0x15,  0x94,  0x1F,  0x14,  0x7F, 	/* 42FF0 */
+	0xC8,  0x0A,  0x0C,  0x32,  0x14,  0x0E,  0x62,  0x71,  0x81,  0x96,  0x10,  0x20,  0x1F,  0x3F,  0x24,  0x50, 	/* 43000 */
+	0x42,  0x94,  0x3F,  0xD2,  0x02,  0x10,  0x7F,  0xFF,  0x09,  0x10,  0x39,  0xD2,  0x09,  0x12,  0x39,  0xDC, 	/* 43010 */
+	0x09,  0x0C,  0x39,  0xC8,  0x09,  0x15,  0x0F,  0xA3,  0x70,  0x41,  0x98,  0x10,  0x10,  0x1F,  0xBF,  0x24, 	/* 43020 */
+	0x28,  0x42,  0x44,  0x00,  0x54,  0x3C,  0x92,  0x25,  0x7E,  0x24,  0x28,  0x3D,  0xFF,  0x24,  0x54,  0x24, 	/* 43030 */
+	0x92,  0x3D,  0x69,  0x24,  0x14,  0x25,  0xFE,  0x24,  0x54,  0x4D,  0x92,  0x9F,  0x10,  0x20,  0x1F,  0x3F, 	/* 43040 */
+	0x24,  0x48,  0x42,  0x84,  0x08,  0x00,  0x7F,  0x7F,  0x08,  0x09,  0x3F,  0x1F,  0x29,  0x62,  0x29,  0x3E, 	/* 43050 */
+	0x3F,  0x22,  0x0C,  0x3E,  0x1A,  0x22,  0x29,  0x3E,  0x48,  0x32,  0x08,  0xC1,  0xA0,  0x10,  0x20,  0x1F, 	/* 43060 */
+	0x3F,  0x28,  0x48,  0x44,  0x84,  0x04,  0x20,  0x3F,  0xBE,  0x11,  0x20,  0x7F,  0xFE,  0x00,  0x02,  0x1F, 	/* 43070 */
+	0x3E,  0x11,  0x20,  0x1F,  0x3E,  0x11,  0x20,  0x1F,  0x3E,  0x11,  0x21,  0x13,  0x1F,  0xA4,  0x10,  0x20, 	/* 43080 */
+	0x1F,  0x3F,  0x24,  0x50,  0x4A,  0x94,  0x08,  0x92,  0x15,  0x50,  0x7F,  0xFF,  0x09,  0x10,  0x39,  0xD2, 	/* 43090 */
+	0x09,  0x12,  0x39,  0xDC,  0x09,  0x0C,  0x39,  0xC8,  0x09,  0x15,  0x0F,  0xA3,  0x70,  0x41,  0xA5,  0x10, 	/* 430A0 */
+	0x10,  0x1F,  0x1F,  0x24,  0xA8,  0x41,  0x44,  0x02,  0x20,  0x0F,  0xF8,  0x70,  0x07,  0x3D,  0xDE,  0x25, 	/* 430B0 */
+	0x52,  0x3D,  0xDE,  0x00,  0x00,  0x1F,  0xFC,  0x12,  0x24,  0x1F,  0xFC,  0x12,  0x24,  0x12,  0x2C,  0xAC, 	/* 430C0 */
+	0x10,  0x20,  0x1F,  0x3F,  0x24,  0x48,  0x42,  0x84,  0x04,  0x12,  0x7F,  0x94,  0x0A,  0x3F,  0x25,  0x64, 	/* 430D0 */
+	0x2B,  0x24,  0x3F,  0x3E,  0x04,  0x24,  0x7F,  0xBE,  0x4A,  0xA4,  0x5D,  0xA4,  0x40,  0xBF,  0x41,  0x80, 	/* 430E0 */
+	0xB3,  0x00,  0x80,  0x10,  0x88,  0x08,  0x88,  0x04,  0x90,  0x04,  0xA0,  0x00,  0x80,  0x7F,  0xFF,  0x01, 	/* 430F0 */
+	0xC0,  0x02,  0xA0,  0x02,  0xA0,  0x04,  0x90,  0x08,  0x88,  0x10,  0x84,  0x20,  0x82,  0x00,  0x80,  0x00, 	/* 43100 */
+	0x80,  0xB5,  0x08,  0x10,  0x09,  0x10,  0x49,  0x10,  0x2A,  0x10,  0x28,  0x10,  0x08,  0x10,  0x7F,  0xFF, 	/* 43110 */
+	0x08,  0x10,  0x1C,  0x10,  0x1A,  0x10,  0x29,  0x10,  0x28,  0x10,  0x48,  0x10,  0x08,  0x10,  0x08,  0x10, 	/* 43120 */
+	0x08,  0x10,  0xBE,  0x08,  0x00,  0x08,  0xFE,  0x4A,  0x12,  0x2A,  0x12,  0x2C,  0x92,  0x08,  0x52,  0x7F, 	/* 43130 */
+	0x32,  0x08,  0x12,  0x1C,  0x12,  0x1A,  0x32,  0x29,  0x2A,  0x28,  0x2A,  0x48,  0x42,  0x08,  0x42,  0x08, 	/* 43140 */
+	0x84,  0x09,  0x18,  0x81,  0x08,  0x04,  0x0A,  0x18,  0x4A,  0xF0,  0x2A,  0x10,  0x2C,  0x10,  0x08,  0x10, 	/* 43150 */
+	0x7F,  0x10,  0x09,  0xFF,  0x1C,  0x10,  0x1A,  0x10,  0x29,  0x10,  0x28,  0x10,  0x48,  0x10,  0x08,  0x10, 	/* 43160 */
+	0x08,  0x10,  0x08,  0x10,  0x82,  0x01,  0x00,  0x03,  0xF0,  0x0C,  0x20,  0x30,  0x40,  0x00,  0xA0,  0x03, 	/* 43170 */
+	0x10,  0x0C,  0x8C,  0x78,  0x93,  0x04,  0x90,  0x04,  0xA0,  0x7F,  0xFF,  0x02,  0xA0,  0x04,  0x90,  0x18, 	/* 43180 */
+	0x8C,  0x60,  0x83,  0x00,  0x80,  0x83,  0x08,  0x90,  0x0A,  0x90,  0x4A,  0x90,  0x2A,  0x92,  0x2C,  0x92, 	/* 43190 */
+	0x08,  0xF2,  0x7E,  0x94,  0x08,  0x98,  0x1C,  0x90,  0x1A,  0x90,  0x2A,  0x90,  0x28,  0x90,  0x48,  0x90, 	/* 431A0 */
+	0x08,  0xB1,  0x08,  0xD1,  0x0B,  0x0F,  0x89,  0x08,  0x48,  0x4A,  0x48,  0x2A,  0x48,  0x2A,  0x48,  0x2C, 	/* 431B0 */
+	0x84,  0x08,  0x84,  0x7F,  0x02,  0x0A,  0xFD,  0x1C,  0x24,  0x1A,  0x24,  0x2A,  0x24,  0x2A,  0x24,  0x48, 	/* 431C0 */
+	0x44,  0x08,  0x44,  0x08,  0x88,  0x09,  0x30,  0x8B,  0x08,  0x20,  0x09,  0x20,  0x49,  0xFC,  0x2A,  0x24, 	/* 431D0 */
+	0x2A,  0x24,  0x08,  0x25,  0x7F,  0x45,  0x08,  0x93,  0x1C,  0x10,  0x1A,  0x10,  0x2B,  0xFE,  0x28,  0x10, 	/* 431E0 */
+	0x48,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x8D,  0x08,  0x04,  0x0A,  0x18,  0x4A,  0xE0,  0x2C, 	/* 431F0 */
+	0x20,  0x28,  0x20,  0x08,  0x3E,  0x7F,  0xE0,  0x08,  0x20,  0x1C,  0x20,  0x1A,  0x3E,  0x2B,  0xE0,  0x28, 	/* 43200 */
+	0x20,  0x48,  0x21,  0x08,  0x21,  0x08,  0x1F,  0x08,  0x00,  0x90,  0x08,  0x00,  0x09,  0xFF,  0x4A,  0x00, 	/* 43210 */
+	0x2A,  0x00,  0x2C,  0x7E,  0x08,  0x42,  0x7F,  0x42,  0x08,  0x42,  0x1C,  0x7E,  0x1A,  0x40,  0x2A,  0x40, 	/* 43220 */
+	0x28,  0x40,  0x48,  0x80,  0x08,  0x80,  0x09,  0x00,  0x0A,  0x00,  0x92,  0x08,  0x20,  0x0A,  0x20,  0x4A, 	/* 43230 */
+	0x20,  0x2B,  0xFE,  0x2C,  0x00,  0x08,  0x84,  0x7F,  0x84,  0x08,  0x84,  0x1C,  0x44,  0x1A,  0x48,  0x2A, 	/* 43240 */
+	0x48,  0x28,  0x48,  0x48,  0x50,  0x08,  0x10,  0x09,  0xFF,  0x08,  0x00,  0x95,  0x08,  0x10,  0x4A,  0x10, 	/* 43250 */
+	0x2A,  0x20,  0x2C,  0xFE,  0x28,  0x82,  0x08,  0x82,  0x7F,  0x82,  0x08,  0x82,  0x1C,  0xFE,  0x1A,  0x82, 	/* 43260 */
+	0x2A,  0x82,  0x28,  0x82,  0x48,  0x82,  0x08,  0x82,  0x08,  0xFE,  0x08,  0x00,  0x97,  0x08,  0x00,  0x4A, 	/* 43270 */
+	0xFC,  0x2A,  0x84,  0x2C,  0x84,  0x08,  0x84,  0x7F,  0xFC,  0x08,  0x84,  0x08,  0x84,  0x1C,  0x84,  0x1A, 	/* 43280 */
+	0xFC,  0x2A,  0x84,  0x28,  0x84,  0x48,  0x84,  0x08,  0x84,  0x0B,  0xFF,  0x08,  0x00,  0x98,  0x08,  0x20, 	/* 43290 */
+	0x4A,  0x20,  0x2A,  0x20,  0x2C,  0x20,  0x28,  0x3F,  0x08,  0x20,  0x7F,  0x20,  0x08,  0x20,  0x1C,  0x20, 	/* 432A0 */
+	0x1A,  0xFC,  0x29,  0x84,  0x28,  0x84,  0x48,  0x84,  0x08,  0x84,  0x08,  0xFC,  0x08,  0x00,  0x9B,  0x00, 	/* 432B0 */
+	0x80,  0x1F,  0xFC,  0x00,  0x84,  0x7F,  0xFF,  0x00,  0x84,  0x1F,  0xFC,  0x00,  0x80,  0x14,  0x94,  0x12, 	/* 432C0 */
+	0xA4,  0x1F,  0xFC,  0x10,  0x84,  0x11,  0xC4,  0x12,  0xA4,  0x2C,  0x9C,  0x20,  0x84,  0x40,  0x84,  0x9F, 	/* 432D0 */
+	0x00,  0x00,  0x7F,  0xFF,  0x02,  0x20,  0x1F,  0xFC,  0x12,  0x24,  0x12,  0x24,  0x1F,  0xFC,  0x08,  0x88, 	/* 432E0 */
+	0x04,  0x88,  0x02,  0x90,  0x7F,  0xFF,  0x01,  0xC0,  0x02,  0xA0,  0x0C,  0x98,  0x70,  0x86,  0x00,  0x80, 	/* 432F0 */
+	0xA1,  0x08,  0x00,  0x08,  0xFE,  0x4A,  0x82,  0x2A,  0x82,  0x2C,  0xFE,  0x08,  0x82,  0x7F,  0x82,  0x08, 	/* 43300 */
+	0xBA,  0x1C,  0xAA,  0x1A,  0xAA,  0x2A,  0xAA,  0x28,  0xBA,  0x48,  0x82,  0x08,  0x82,  0x08,  0x82,  0x08, 	/* 43310 */
+	0x86,  0xA2,  0x00,  0x80,  0x00,  0x80,  0x79,  0xFE,  0x01,  0x22,  0x02,  0x24,  0x08,  0x50,  0x10,  0x88, 	/* 43320 */
+	0x61,  0x04,  0x0A,  0x8B,  0x04,  0x88,  0x04,  0x90,  0x7F,  0xFF,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C, 	/* 43330 */
+	0x60,  0x83,  0xA4,  0x00,  0x80,  0x01,  0x00,  0x1F,  0xFC,  0x14,  0x94,  0x12,  0xA4,  0x1F,  0xFC,  0x11, 	/* 43340 */
+	0xC4,  0x12,  0xA4,  0x14,  0x94,  0x1F,  0xFC,  0x00,  0x00,  0x7F,  0xFF,  0x02,  0x00,  0x07,  0xF8,  0x04, 	/* 43350 */
+	0x08,  0x00,  0x30,  0xA5,  0x00,  0x00,  0x78,  0x9E,  0x0C,  0xA2,  0x0A,  0xA2,  0x0A,  0xC2,  0x38,  0x8E, 	/* 43360 */
+	0x27,  0xF8,  0x20,  0x88,  0x39,  0xCE,  0x09,  0xC2,  0x0A,  0xA2,  0x0A,  0xA2,  0x0C,  0x92,  0x08,  0x82, 	/* 43370 */
+	0x10,  0x84,  0x60,  0x18,  0xA7,  0x08,  0x10,  0x4A,  0x10,  0x2A,  0x10,  0x2C,  0xFF,  0x28,  0x80,  0x08, 	/* 43380 */
+	0x90,  0x7E,  0x90,  0x08,  0x90,  0x1C,  0xFE,  0x1A,  0x90,  0x2A,  0x90,  0x28,  0x90,  0x49,  0x10,  0x09, 	/* 43390 */
+	0x10,  0x0A,  0xFF,  0x08,  0x00,  0xA8,  0x08,  0x00,  0x09,  0xFF,  0x4A,  0x20,  0x2A,  0x20,  0x2C,  0x40, 	/* 433A0 */
+	0x08,  0xFE,  0x7E,  0x82,  0x08,  0x82,  0x1C,  0x82,  0x1A,  0xFE,  0x2A,  0x82,  0x28,  0x82,  0x48,  0x82, 	/* 433B0 */
+	0x08,  0x82,  0x08,  0xFE,  0x08,  0x00,  0xAB,  0x08,  0x00,  0x09,  0xFF,  0x4A,  0x10,  0x2A,  0x10,  0x2C, 	/* 433C0 */
+	0x20,  0x08,  0xFE,  0x7E,  0xAA,  0x08,  0xAA,  0x1C,  0xAA,  0x1A,  0xAA,  0x2A,  0xAA,  0x28,  0xAA,  0x48, 	/* 433D0 */
+	0xAA,  0x08,  0xAA,  0x08,  0xAA,  0x08,  0x86,  0xAD,  0x08,  0x20,  0x0A,  0x20,  0x4A,  0x50,  0x2A,  0x50, 	/* 433E0 */
+	0x2C,  0x88,  0x08,  0x84,  0x7F,  0x7A,  0x0A,  0x01,  0x18,  0x00,  0x1C,  0x00,  0x2A,  0xFC,  0x2A,  0x84, 	/* 433F0 */
+	0x48,  0x84,  0x08,  0x84,  0x08,  0xFC,  0x08,  0x00,  0xAE,  0x08,  0x20,  0x0A,  0x20,  0x4A,  0xFC,  0x2C, 	/* 43400 */
+	0x84,  0x2C,  0x84,  0x08,  0xFC,  0x7F,  0x84,  0x08,  0x84,  0x1C,  0xFE,  0x1A,  0xA2,  0x2A,  0xA4,  0x28, 	/* 43410 */
+	0x94,  0x48,  0x88,  0x08,  0x84,  0x08,  0xE2,  0x0B,  0x01,  0xB1,  0x08,  0x00,  0x05,  0xF8,  0x40,  0x48, 	/* 43420 */
+	0x22,  0x4A,  0x02,  0x49,  0x0C,  0x89,  0x11,  0x08,  0x22,  0xB0,  0x48,  0x88,  0x04,  0x90,  0x7F,  0xFF, 	/* 43430 */
+	0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0xB2,  0x02,  0x00,  0x03,  0xC0,  0x0A, 	/* 43440 */
+	0x3C,  0x1F,  0x84,  0x71,  0x28,  0x0A,  0x10,  0x0C,  0x6C,  0x71,  0x83,  0x08,  0x88,  0x04,  0x90,  0x7F, 	/* 43450 */
+	0xFF,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0xB3,  0x08,  0x00,  0x09,  0xFF, 	/* 43460 */
+	0x4A,  0x10,  0x2A,  0x10,  0x2C,  0xFE,  0x08,  0x92,  0x7E,  0xFE,  0x08,  0x92,  0x1C,  0x92,  0x1A,  0xFE, 	/* 43470 */
+	0x2A,  0x10,  0x28,  0x50,  0x48,  0x20,  0x08,  0x50,  0x09,  0x8C,  0x0E,  0x03,  0xB9,  0x08,  0x10,  0x0A, 	/* 43480 */
+	0x10,  0x4A,  0xFE,  0x2C,  0x44,  0x28,  0x44,  0x08,  0x44,  0x7E,  0xAA,  0x08,  0xAA,  0x19,  0x10,  0x18, 	/* 43490 */
+	0x10,  0x2B,  0xFF,  0x28,  0x10,  0x48,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0xBD,  0x08,  0x10, 	/* 434A0 */
+	0x0A,  0x10,  0x4A,  0xFE,  0x2C,  0x82,  0x2C,  0x82,  0x08,  0xFC,  0x7F,  0x00,  0x08,  0x00,  0x19,  0xFE, 	/* 434B0 */
+	0x1C,  0x10,  0x2A,  0x94,  0x28,  0x92,  0x48,  0x91,  0x09,  0x11,  0x0A,  0x10,  0x08,  0x30,  0xBE,  0x08, 	/* 434C0 */
+	0x20,  0x4A,  0x20,  0x2B,  0xFE,  0x2A,  0x20,  0x2C,  0xFC,  0x08,  0x20,  0x7F,  0xFF,  0x08,  0x00,  0x1C, 	/* 434D0 */
+	0xFC,  0x1A,  0x84,  0x2A,  0xFC,  0x28,  0x84,  0x48,  0xFC,  0x08,  0x84,  0x08,  0x84,  0x08,  0x8C,  0x80, 	/* 434E0 */
+	0x08,  0x48,  0x0A,  0x48,  0x4B,  0xFF,  0x2C,  0x48,  0x28,  0x48,  0x08,  0x20,  0x7F,  0x2A,  0x08,  0x4A, 	/* 434F0 */
+	0x1C,  0x4A,  0x1A,  0xCC,  0x29,  0x48,  0x28,  0x48,  0x48,  0x49,  0x08,  0x49,  0x08,  0x49,  0x08,  0x47, 	/* 43500 */
+	0x82,  0x08,  0x44,  0x0A,  0x44,  0x4B,  0xFF,  0x2C,  0x44,  0x28,  0x7C,  0x08,  0x44,  0x7F,  0x7C,  0x08, 	/* 43510 */
+	0x44,  0x1C,  0x44,  0x1B,  0xFF,  0x28,  0xA8,  0x28,  0xAA,  0x48,  0xC6,  0x08,  0x80,  0x08,  0xFF,  0x08, 	/* 43520 */
+	0x00,  0x85,  0x08,  0x00,  0x0A,  0xFE,  0x4A,  0x04,  0x2C,  0x38,  0x28,  0x10,  0x09,  0xFF,  0x7E,  0x32, 	/* 43530 */
+	0x08,  0x54,  0x1D,  0x90,  0x1A,  0x30,  0x2B,  0xFF,  0x28,  0x38,  0x48,  0x54,  0x08,  0x92,  0x0B,  0x11, 	/* 43540 */
+	0x08,  0x10,  0x8A,  0x10,  0x80,  0x14,  0x9E,  0x54,  0x92,  0x34,  0x92,  0x3B,  0xF2,  0x10,  0x9E,  0x7C, 	/* 43550 */
+	0x92,  0x10,  0x92,  0x1B,  0xD2,  0x36,  0x5E,  0x32,  0x52,  0x52,  0x52,  0x53,  0xD2,  0x10,  0x22,  0x10, 	/* 43560 */
+	0x22,  0x10,  0x46,  0x8E,  0x08,  0x00,  0x49,  0xFF,  0x2B,  0x00,  0x2D,  0x7E,  0x09,  0x52,  0x7F,  0x52, 	/* 43570 */
+	0x09,  0x7E,  0x19,  0x52,  0x1D,  0x52,  0x2B,  0x7E,  0x29,  0x10,  0x49,  0x7E,  0x09,  0x10,  0x0A,  0x10, 	/* 43580 */
+	0x0B,  0xFF,  0x0C,  0x00,  0x92,  0x08,  0x48,  0x0A,  0x48,  0x4B,  0xFF,  0x2C,  0x48,  0x28,  0x00,  0x09, 	/* 43590 */
+	0xFF,  0x7F,  0x00,  0x09,  0x7E,  0x1D,  0x52,  0x1B,  0x7E,  0x29,  0x52,  0x29,  0x52,  0x49,  0x7E,  0x0A, 	/* 435A0 */
+	0x52,  0x0C,  0x52,  0x08,  0x56,  0x96,  0x08,  0x20,  0x0A,  0x20,  0x4B,  0xFF,  0x2D,  0x10,  0x29,  0x7E, 	/* 435B0 */
+	0x09,  0x12,  0x7F,  0xFF,  0x09,  0x12,  0x19,  0x12,  0x1D,  0x7E,  0x2B,  0x00,  0x29,  0x7E,  0x4A,  0x42, 	/* 435C0 */
+	0x0A,  0x42,  0x0C,  0x7E,  0x08,  0x00,  0x98,  0x08,  0x10,  0x0A,  0x10,  0x4A,  0xFF,  0x2C,  0x81,  0x28, 	/* 435D0 */
+	0x81,  0x08,  0x7E,  0x7F,  0x22,  0x08,  0x52,  0x1D,  0x9C,  0x1A,  0x2C,  0x2A,  0x4A,  0x29,  0x9A,  0x48, 	/* 435E0 */
+	0x29,  0x08,  0x48,  0x09,  0x88,  0x08,  0x30,  0x9C,  0x00,  0x40,  0x00,  0x40,  0x1F,  0xFF,  0x11,  0x08, 	/* 435F0 */
+	0x1F,  0xFF,  0x11,  0x08,  0x15,  0xAA,  0x15,  0xAA,  0x19,  0x6B,  0x12,  0x44,  0x11,  0x48,  0x1F,  0xFF, 	/* 43600 */
+	0x21,  0x50,  0x26,  0x4C,  0x58,  0x43,  0x00,  0x40,  0x9E,  0x08,  0x88,  0x04,  0x90,  0x7F,  0xFF,  0x02, 	/* 43610 */
+	0xA0,  0x04,  0x90,  0x1F,  0xFC,  0x68,  0x8B,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x02,  0x20,  0x3F, 	/* 43620 */
+	0xFE,  0x02,  0x20,  0x7F,  0xFF,  0x06,  0x18,  0x38,  0x04,  0x9F,  0x08,  0x48,  0x0A,  0x48,  0x4B,  0xFF, 	/* 43630 */
+	0x2C,  0x48,  0x29,  0xFE,  0x09,  0x4A,  0x7F,  0xFE,  0x09,  0x4A,  0x1D,  0xFE,  0x1A,  0x00,  0x1A,  0xFC, 	/* 43640 */
+	0x28,  0x84,  0x28,  0xFC,  0x48,  0x84,  0x08,  0xFC,  0x08,  0x00,  0xA0,  0x08,  0x10,  0x0A,  0x10,  0x4B, 	/* 43650 */
+	0xFF,  0x2D,  0x10,  0x29,  0x7E,  0x09,  0x12,  0x7F,  0xFF,  0x09,  0x12,  0x09,  0x7E,  0x1D,  0x91,  0x1B, 	/* 43660 */
+	0x5A,  0x29,  0x74,  0x2A,  0x54,  0x4B,  0x92,  0x0C,  0x11,  0x08,  0x30,  0xA2,  0x08,  0x48,  0x0A,  0x48, 	/* 43670 */
+	0x4B,  0xFF,  0x2C,  0x48,  0x28,  0x48,  0x08,  0xFC,  0x7E,  0x84,  0x08,  0xFC,  0x18,  0x84,  0x1C,  0xFC, 	/* 43680 */
+	0x2A,  0x20,  0x2B,  0xFF,  0x48,  0x30,  0x08,  0x48,  0x09,  0x84,  0x0E,  0x03,  0xA7,  0x08,  0x00,  0x4A, 	/* 43690 */
+	0xFC,  0x2A,  0x84,  0x2C,  0xFC,  0x08,  0x84,  0x7F,  0xFF,  0x08,  0x00,  0x08,  0xFC,  0x1C,  0xA4,  0x1A, 	/* 436A0 */
+	0xFC,  0x2A,  0xA4,  0x28,  0xFC,  0x48,  0x20,  0x09,  0xFE,  0x08,  0x20,  0x0F,  0xFF,  0xAF,  0x08,  0x00, 	/* 436B0 */
+	0x0A,  0xFE,  0x4A,  0x10,  0x2D,  0xFF,  0x29,  0x11,  0x09,  0xDD,  0x7F,  0x11,  0x08,  0xDC,  0x1C,  0x00, 	/* 436C0 */
+	0x1B,  0xFF,  0x28,  0x20,  0x29,  0xFE,  0x49,  0x4A,  0x09,  0x4A,  0x09,  0x4A,  0x09,  0x06,  0xB2,  0x08, 	/* 436D0 */
+	0x00,  0x0B,  0xFF,  0x4B,  0x24,  0x2D,  0xFF,  0x29,  0x24,  0x09,  0x7E,  0x7F,  0x52,  0x09,  0x7E,  0x1D, 	/* 436E0 */
+	0x52,  0x1B,  0x7E,  0x29,  0x10,  0x29,  0xFF,  0x4A,  0x99,  0x0A,  0x95,  0x0C,  0xFB,  0x08,  0x83,  0xB4, 	/* 436F0 */
+	0x38,  0x00,  0x08,  0xFF,  0x08,  0x33,  0x08,  0xDD,  0x14,  0x33,  0x14,  0xDD,  0x22,  0x14,  0x48,  0x28, 	/* 43700 */
+	0x2A,  0x7F,  0x1C,  0xC8,  0x08,  0x7E,  0x7F,  0x48,  0x1C,  0x7E,  0x2A,  0x48,  0x49,  0x7F,  0x08,  0x00, 	/* 43710 */
+	0xB6,  0x08,  0x00,  0x2A,  0xFF,  0x2A,  0x33,  0x3E,  0xDD,  0x08,  0x33,  0x2A,  0xDD,  0x2A,  0x14,  0x3E, 	/* 43720 */
+	0x28,  0x08,  0x7F,  0x2A,  0xC8,  0x1C,  0x7E,  0x7F,  0x48,  0x1C,  0x7E,  0x2A,  0x48,  0x49,  0x7F,  0x08, 	/* 43730 */
+	0x00,  0xB8,  0x01,  0x00,  0x01,  0x00,  0x01,  0x20,  0x02,  0x20,  0x1C,  0x40,  0x06,  0x80,  0x01,  0x20, 	/* 43740 */
+	0x02,  0x18,  0x7F,  0xF4,  0x01,  0x02,  0x09,  0x20,  0x09,  0x10,  0x09,  0x10,  0x11,  0x08,  0x21,  0x08, 	/* 43750 */
+	0x01,  0x00,  0xBA,  0x08,  0x40,  0x08,  0x40,  0x12,  0x40,  0x62,  0x40,  0x14,  0x40,  0x08,  0x40,  0x0C, 	/* 43760 */
+	0x40,  0x12,  0x40,  0x7D,  0x40,  0x09,  0x40,  0x28,  0x40,  0x2A,  0x40,  0x29,  0x41,  0x29,  0x21,  0x48, 	/* 43770 */
+	0x1F,  0x08,  0x00,  0xBB,  0x00,  0x0C,  0x00,  0xF0,  0x7F,  0x00,  0x02,  0x20,  0x02,  0x40,  0x1C,  0x40, 	/* 43780 */
+	0x02,  0x80,  0x01,  0x20,  0x02,  0x18,  0x7F,  0xF4,  0x01,  0x02,  0x05,  0x20,  0x09,  0x18,  0x11,  0x04, 	/* 43790 */
+	0x61,  0x02,  0x01,  0x00,  0xBE,  0x08,  0x08,  0x08,  0x48,  0x0A,  0x48,  0x72,  0x48,  0x14,  0x48,  0x08, 	/* 437A0 */
+	0x48,  0x0C,  0x48,  0x12,  0x48,  0x7D,  0x48,  0x08,  0x4F,  0x2C,  0x78,  0x2B,  0xC8,  0x2A,  0x08,  0x2A, 	/* 437B0 */
+	0x08,  0x48,  0x08,  0x08,  0x08,  0x80,  0x08,  0x00,  0x08,  0x7E,  0x0A,  0x02,  0x72,  0x02,  0x14,  0x02, 	/* 437C0 */
+	0x08,  0x02,  0x0C,  0x7E,  0x12,  0x40,  0x7D,  0x40,  0x09,  0x40,  0x28,  0x40,  0x2A,  0x40,  0x29,  0x41, 	/* 437D0 */
+	0x29,  0x21,  0x48,  0x1F,  0x08,  0x00,  0x82,  0x08,  0x04,  0x08,  0x04,  0x0A,  0x04,  0x72,  0x04,  0x14, 	/* 437E0 */
+	0xFF,  0x08,  0x04,  0x0C,  0x04,  0x12,  0x44,  0x7D,  0x24,  0x09,  0x24,  0x28,  0x04,  0x2A,  0x04,  0x29, 	/* 437F0 */
+	0x04,  0x29,  0x04,  0x48,  0x04,  0x08,  0x0C,  0x84,  0x08,  0x40,  0x08,  0x40,  0x0A,  0x40,  0x72,  0x7E, 	/* 43800 */
+	0x14,  0x82,  0x08,  0x82,  0x0D,  0x02,  0x12,  0x42,  0x7D,  0x22,  0x09,  0x12,  0x28,  0x12,  0x2A,  0x02, 	/* 43810 */
+	0x29,  0x02,  0x29,  0x02,  0x48,  0x04,  0x08,  0x18,  0x85,  0x08,  0x00,  0x08,  0x00,  0x0A,  0xFE,  0x72, 	/* 43820 */
+	0x10,  0x14,  0x10,  0x08,  0x10,  0x0C,  0x10,  0x12,  0x10,  0x7D,  0x10,  0x09,  0x10,  0x2C,  0x10,  0x2A, 	/* 43830 */
+	0x10,  0x2A,  0x10,  0x2B,  0xFF,  0x48,  0x00,  0x08,  0x00,  0x86,  0x08,  0x00,  0x08,  0xFE,  0x0A,  0x10, 	/* 43840 */
+	0x72,  0x10,  0x14,  0x10,  0x08,  0x10,  0x0C,  0x10,  0x12,  0xFF,  0x7D,  0x10,  0x09,  0x10,  0x28,  0x10, 	/* 43850 */
+	0x2A,  0x10,  0x29,  0x10,  0x29,  0x10,  0x48,  0x10,  0x08,  0x30,  0x8A,  0x00,  0x80,  0x00,  0x80,  0x7F, 	/* 43860 */
+	0xFF,  0x02,  0x10,  0x01,  0x20,  0x00,  0xC0,  0x07,  0x38,  0x78,  0x87,  0x01,  0x20,  0x0E,  0x50,  0x01, 	/* 43870 */
+	0x8C,  0x7F,  0xFA,  0x02,  0xB1,  0x0C,  0x8C,  0x30,  0x82,  0x00,  0x80,  0x8B,  0x08,  0x10,  0x08,  0x10, 	/* 43880 */
+	0x0A,  0x10,  0x73,  0xFF,  0x14,  0x44,  0x08,  0x44,  0x0C,  0x44,  0x12,  0x28,  0x7D,  0x28,  0x09,  0x10, 	/* 43890 */
+	0x28,  0x10,  0x2A,  0x18,  0x29,  0x28,  0x29,  0x44,  0x48,  0x82,  0x0B,  0x01,  0x8D,  0x08,  0x10,  0x08, 	/* 438A0 */
+	0x10,  0x0A,  0x10,  0x72,  0xFE,  0x14,  0x92,  0x08,  0x92,  0x0C,  0x92,  0x12,  0xAA,  0x7D,  0xAA,  0x09, 	/* 438B0 */
+	0xAA,  0x2C,  0xC6,  0x2A,  0x82,  0x2A,  0x82,  0x2A,  0x82,  0x48,  0x82,  0x08,  0x86,  0x90,  0x08,  0x00, 	/* 438C0 */
+	0x09,  0xFC,  0x0A,  0x24,  0x72,  0x24,  0x14,  0x24,  0x08,  0x24,  0x0A,  0x24,  0x12,  0xFE,  0x7F,  0x44, 	/* 438D0 */
+	0x09,  0x44,  0x2C,  0x44,  0x2A,  0x44,  0x2A,  0x44,  0x2A,  0x44,  0x49,  0xFF,  0x08,  0x00,  0x94,  0x08, 	/* 438E0 */
+	0x10,  0x08,  0x13,  0x12,  0x1C,  0x63,  0xF0,  0x14,  0x10,  0x08,  0x52,  0x0C,  0x52,  0x12,  0x52,  0x7D, 	/* 438F0 */
+	0x52,  0x09,  0x52,  0x28,  0x7E,  0x2A,  0x10,  0x29,  0x10,  0x29,  0x11,  0x48,  0x11,  0x08,  0x0F,  0x95, 	/* 43900 */
+	0x08,  0x88,  0x08,  0x88,  0x0A,  0x88,  0x72,  0x88,  0x14,  0x88,  0x08,  0x89,  0x0C,  0xEA,  0x12,  0x8C, 	/* 43910 */
+	0x7D,  0x88,  0x09,  0x88,  0x2C,  0x88,  0x2A,  0x88,  0x2A,  0x88,  0x2A,  0xB9,  0x48,  0xC9,  0x0B,  0x07, 	/* 43920 */
+	0x97,  0x08,  0x10,  0x08,  0x10,  0x0A,  0x10,  0x72,  0x54,  0x14,  0x52,  0x08,  0x52,  0x0A,  0x51,  0x12, 	/* 43930 */
+	0x95,  0x7F,  0x14,  0x09,  0x34,  0x28,  0x08,  0x2A,  0x08,  0x29,  0x10,  0x29,  0x20,  0x48,  0xC0,  0x0B, 	/* 43940 */
+	0x00,  0x98,  0x08,  0x20,  0x08,  0x20,  0x0A,  0x20,  0x73,  0xFF,  0x14,  0x20,  0x08,  0x28,  0x0C,  0x28, 	/* 43950 */
+	0x12,  0x28,  0x7D,  0x48,  0x08,  0x48,  0x2C,  0x50,  0x2A,  0x94,  0x2A,  0x92,  0x29,  0x2E,  0x48,  0xF1, 	/* 43960 */
+	0x08,  0x01,  0x99,  0x08,  0x02,  0x08,  0x0C,  0x0A,  0x78,  0x72,  0x48,  0x14,  0x48,  0x08,  0x48,  0x0C, 	/* 43970 */
+	0x48,  0x12,  0x7F,  0x7D,  0x48,  0x09,  0x48,  0x28,  0x48,  0x2A,  0x44,  0x29,  0x44,  0x29,  0x55,  0x48, 	/* 43980 */
+	0x63,  0x09,  0x81,  0x9A,  0x08,  0x00,  0x09,  0xFC,  0x0A,  0x44,  0x72,  0x48,  0x14,  0x48,  0x08,  0x5E, 	/* 43990 */
+	0x0C,  0x62,  0x12,  0x62,  0x7D,  0x54,  0x08,  0x54,  0x2C,  0x98,  0x2A,  0x88,  0x2A,  0x94,  0x29,  0x24, 	/* 439A0 */
+	0x4A,  0x42,  0x08,  0x81,  0x9B,  0x08,  0x48,  0x08,  0x48,  0x0A,  0x48,  0x72,  0x48,  0x14,  0x84,  0x08, 	/* 439B0 */
+	0x84,  0x0B,  0x02,  0x12,  0xFD,  0x7F,  0x24,  0x09,  0x24,  0x2C,  0x24,  0x2A,  0x24,  0x29,  0x44,  0x29, 	/* 439C0 */
+	0x44,  0x48,  0x88,  0x09,  0x30,  0x9C,  0x08,  0x00,  0x08,  0x00,  0x0A,  0x7E,  0x72,  0x00,  0x14,  0x00, 	/* 439D0 */
+	0x08,  0x00,  0x0A,  0xFF,  0x12,  0x10,  0x7F,  0x10,  0x09,  0x10,  0x28,  0x28,  0x2A,  0x24,  0x29,  0x24, 	/* 439E0 */
+	0x29,  0x4E,  0x48,  0xF2,  0x08,  0x02,  0xA0,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80,  0x0F,  0xF8,  0x00, 	/* 439F0 */
+	0x80,  0x7F,  0xFF,  0x00,  0x80,  0x03,  0x20,  0x0C,  0x58,  0x03,  0x84,  0x3F,  0xFA,  0x00,  0x80,  0x04, 	/* 43A00 */
+	0xB0,  0x18,  0x8C,  0x60,  0x82,  0x00,  0x80,  0xA1,  0x08,  0x10,  0x08,  0x10,  0x0A,  0x10,  0x73,  0xFF, 	/* 43A10 */
+	0x14,  0x20,  0x08,  0x20,  0x0A,  0x20,  0x12,  0x3C,  0x7F,  0x24,  0x09,  0x24,  0x2C,  0x24,  0x2A,  0x44, 	/* 43A20 */
+	0x29,  0x44,  0x29,  0x44,  0x48,  0x84,  0x09,  0x18,  0xA2,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x01, 	/* 43A30 */
+	0x00,  0x01,  0x00,  0x7F,  0xFE,  0x42,  0x22,  0x4C,  0x42,  0x02,  0xB0,  0x01,  0x0C,  0x7F,  0xF2,  0x01, 	/* 43A40 */
+	0x00,  0x09,  0x30,  0x11,  0x08,  0x61,  0x04,  0x01,  0x00,  0xAB,  0x04,  0x20,  0x14,  0x22,  0x17,  0xA4, 	/* 43A50 */
+	0x14,  0x38,  0x14,  0x21,  0x17,  0xA1,  0x1C,  0x9F,  0x60,  0x80,  0x0F,  0x10,  0x02,  0x60,  0x01,  0x8C, 	/* 43A60 */
+	0x7F,  0xF6,  0x02,  0xB1,  0x0C,  0x8C,  0x30,  0x82,  0x00,  0x80,  0xAC,  0x08,  0x10,  0x08,  0x10,  0x0A, 	/* 43A70 */
+	0x10,  0x72,  0x10,  0x14,  0xFE,  0x08,  0x92,  0x0C,  0x92,  0x12,  0x92,  0x7D,  0x92,  0x08,  0xFE,  0x2C, 	/* 43A80 */
+	0x92,  0x2A,  0x92,  0x2A,  0x92,  0x2A,  0x92,  0x48,  0xFE,  0x08,  0x00,  0xAE,  0x04,  0x20,  0x04,  0x20, 	/* 43A90 */
+	0x7F,  0xA0,  0x0E,  0x20,  0x15,  0x20,  0x24,  0x21,  0x44,  0xA1,  0x04,  0x9F,  0x0F,  0x20,  0x02,  0x50, 	/* 43AA0 */
+	0x01,  0x8C,  0x7F,  0xFA,  0x02,  0xB1,  0x0C,  0x8C,  0x30,  0x82,  0x00,  0x80,  0xAF,  0x00,  0x00,  0x1F, 	/* 43AB0 */
+	0xFC,  0x10,  0x84,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x01,  0x90,  0x0E,  0x28,  0x01, 	/* 43AC0 */
+	0x44,  0x7F,  0xFA,  0x00,  0x80,  0x04,  0xB0,  0x18,  0x8C,  0x60,  0x82,  0x00,  0x80,  0xB0,  0x08,  0x00, 	/* 43AD0 */
+	0x08,  0xFE,  0x0A,  0x92,  0x72,  0x92,  0x14,  0x92,  0x08,  0x92,  0x0C,  0x92,  0x12,  0xFE,  0x7D,  0x92, 	/* 43AE0 */
+	0x08,  0x92,  0x2C,  0x92,  0x2A,  0x92,  0x2A,  0x92,  0x2A,  0x92,  0x48,  0xFE,  0x08,  0x00,  0xB2,  0x08, 	/* 43AF0 */
+	0x54,  0x08,  0x54,  0x0A,  0x54,  0x72,  0x54,  0x14,  0xFF,  0x08,  0x54,  0x0C,  0x54,  0x12,  0x54,  0x7D, 	/* 43B00 */
+	0x54,  0x09,  0x54,  0x28,  0x5C,  0x2A,  0x40,  0x29,  0x40,  0x29,  0x40,  0x48,  0x7F,  0x08,  0x00,  0xB3, 	/* 43B10 */
+	0x08,  0x10,  0x08,  0x10,  0x0A,  0x10,  0x72,  0xFE,  0x14,  0x92,  0x08,  0x92,  0x0C,  0x92,  0x12,  0xFE, 	/* 43B20 */
+	0x7D,  0x92,  0x09,  0x92,  0x28,  0xFE,  0x2A,  0x10,  0x29,  0x10,  0x29,  0x10,  0x48,  0x10,  0x08,  0x10, 	/* 43B30 */
+	0xB5,  0x08,  0x10,  0x08,  0x10,  0x0A,  0xFE,  0x72,  0x82,  0x14,  0x82,  0x08,  0x00,  0x0C,  0xFF,  0x12, 	/* 43B40 */
+	0x10,  0x7D,  0x10,  0x09,  0x10,  0x28,  0x10,  0x2A,  0x10,  0x29,  0x10,  0x29,  0x10,  0x48,  0x10,  0x08, 	/* 43B50 */
+	0x30,  0xB9,  0x08,  0x00,  0x08,  0xFE,  0x0A,  0x22,  0x72,  0x22,  0x14,  0x22,  0x08,  0x42,  0x0A,  0x42, 	/* 43B60 */
+	0x12,  0x8C,  0x7F,  0x00,  0x09,  0x7E,  0x2C,  0x42,  0x2A,  0x42,  0x29,  0x42,  0x29,  0x42,  0x48,  0x7E, 	/* 43B70 */
+	0x08,  0x00,  0xBA,  0x08,  0x44,  0x08,  0x44,  0x0A,  0x44,  0x73,  0xFF,  0x14,  0x44,  0x08,  0x44,  0x0C, 	/* 43B80 */
+	0x44,  0x12,  0x44,  0x7D,  0x7C,  0x09,  0x44,  0x28,  0x44,  0x2A,  0x44,  0x29,  0x44,  0x29,  0x44,  0x48, 	/* 43B90 */
+	0x7C,  0x08,  0x00,  0xBF,  0x08,  0x10,  0x08,  0x10,  0x0A,  0x10,  0x72,  0x24,  0x14,  0x22,  0x08,  0x4E, 	/* 43BA0 */
+	0x0B,  0xF1,  0x12,  0x01,  0x7F,  0x00,  0x09,  0x7E,  0x28,  0x42,  0x2A,  0x42,  0x29,  0x42,  0x29,  0x42, 	/* 43BB0 */
+	0x48,  0x7E,  0x08,  0x00,  0x82,  0x08,  0x20,  0x08,  0x20,  0x12,  0x3C,  0x62,  0x44,  0x14,  0x48,  0x08, 	/* 43BC0 */
+	0xA8,  0x0D,  0x18,  0x12,  0x24,  0x7D,  0x42,  0x09,  0x81,  0x28,  0x38,  0x2A,  0x04,  0x29,  0x00,  0x29, 	/* 43BD0 */
+	0x70,  0x48,  0x0C,  0x08,  0x02,  0x83,  0x08,  0x10,  0x08,  0x10,  0x0A,  0x10,  0x73,  0xFF,  0x14,  0x10, 	/* 43BE0 */
+	0x08,  0x10,  0x0A,  0x24,  0x12,  0xC4,  0x7F,  0x28,  0x09,  0x28,  0x2C,  0x10,  0x2A,  0x14,  0x2A,  0x22, 	/* 43BF0 */
+	0x28,  0x4E,  0x49,  0xF1,  0x08,  0x01,  0x84,  0x08,  0x00,  0x08,  0x7C,  0x0A,  0x44,  0x72,  0x44,  0x14, 	/* 43C00 */
+	0x44,  0x08,  0x7C,  0x0C,  0x44,  0x12,  0x44,  0x7D,  0x44,  0x09,  0x7C,  0x28,  0x44,  0x2A,  0x44,  0x29, 	/* 43C10 */
+	0x44,  0x29,  0x44,  0x49,  0xFF,  0x08,  0x00,  0x85,  0x08,  0x00,  0x08,  0xFE,  0x0A,  0x82,  0x72,  0x82, 	/* 43C20 */
+	0x14,  0x82,  0x08,  0xBA,  0x0C,  0xAA,  0x12,  0xAA,  0x7E,  0xAA,  0x09,  0xAA,  0x2C,  0xBA,  0x2A,  0x82, 	/* 43C30 */
+	0x2A,  0x82,  0x28,  0x82,  0x48,  0x82,  0x08,  0x86,  0x86,  0x08,  0x10,  0x08,  0x54,  0x0A,  0x52,  0x72, 	/* 43C40 */
+	0x92,  0x14,  0x10,  0x08,  0xFE,  0x0C,  0x10,  0x12,  0x10,  0x7D,  0x10,  0x09,  0xFF,  0x28,  0x10,  0x2A, 	/* 43C50 */
+	0x10,  0x29,  0x10,  0x29,  0x10,  0x48,  0x10,  0x08,  0x10,  0x8B,  0x08,  0x10,  0x08,  0x10,  0x0A,  0x10, 	/* 43C60 */
+	0x72,  0xFF,  0x14,  0x90,  0x08,  0x90,  0x0C,  0x90,  0x12,  0x90,  0x7D,  0x90,  0x08,  0x98,  0x2C,  0xA4, 	/* 43C70 */
+	0x2A,  0xA4,  0x2A,  0xA2,  0x29,  0x4E,  0x4A,  0xF1,  0x08,  0x01,  0x8C,  0x08,  0x00,  0x08,  0xFC,  0x0A, 	/* 43C80 */
+	0x44,  0x72,  0x24,  0x14,  0x28,  0x08,  0x18,  0x0C,  0x24,  0x12,  0xC3,  0x7D,  0x10,  0x09,  0x10,  0x28, 	/* 43C90 */
+	0xFE,  0x2A,  0x10,  0x29,  0x10,  0x29,  0x10,  0x49,  0xFF,  0x08,  0x00,  0x8E,  0x08,  0x40,  0x08,  0x5E, 	/* 43CA0 */
+	0x0A,  0x80,  0x72,  0x80,  0x15,  0x00,  0x08,  0x40,  0x0C,  0x7F,  0x12,  0x84,  0x7E,  0x84,  0x09,  0x84, 	/* 43CB0 */
+	0x28,  0x84,  0x2C,  0x84,  0x2A,  0x84,  0x2A,  0x84,  0x48,  0x84,  0x08,  0x8C,  0x8F,  0x08,  0x20,  0x08, 	/* 43CC0 */
+	0x20,  0x0A,  0xFC,  0x72,  0xA4,  0x14,  0xA4,  0x08,  0xFC,  0x0C,  0xA4,  0x12,  0xA4,  0x7D,  0xFC,  0x09, 	/* 43CD0 */
+	0x12,  0x28,  0x14,  0x2A,  0x08,  0x29,  0x19,  0x29,  0x65,  0x49,  0x83,  0x08,  0x01,  0x90,  0x08,  0x10, 	/* 43CE0 */
+	0x08,  0x10,  0x12,  0x10,  0x65,  0xFF,  0x14,  0x10,  0x08,  0x10,  0x0C,  0x10,  0x12,  0xFE,  0x7D,  0x00, 	/* 43CF0 */
+	0x09,  0x00,  0x28,  0x7E,  0x2A,  0x42,  0x29,  0x42,  0x29,  0x42,  0x48,  0x7E,  0x08,  0x00,  0x96,  0x08, 	/* 43D00 */
+	0x10,  0x08,  0x12,  0x0A,  0x92,  0x72,  0x54,  0x14,  0x54,  0x08,  0x10,  0x0C,  0x10,  0x12,  0xFF,  0x7D, 	/* 43D10 */
+	0x28,  0x08,  0x28,  0x28,  0x28,  0x2A,  0x28,  0x29,  0x48,  0x29,  0x49,  0x48,  0x89,  0x09,  0x07,  0x9B, 	/* 43D20 */
+	0x04,  0x40,  0x04,  0x40,  0x04,  0xFF,  0x09,  0x44,  0x0A,  0x28,  0x14,  0x10,  0x14,  0x6C,  0x37,  0x93, 	/* 43D30 */
+	0x54,  0x28,  0x14,  0xEC,  0x14,  0x12,  0x15,  0xFF,  0x14,  0x58,  0x14,  0x96,  0x13,  0x11,  0x10,  0x10, 	/* 43D40 */
+	0x9E,  0x08,  0x10,  0x08,  0x10,  0x0A,  0x10,  0x73,  0xFF,  0x14,  0x48,  0x08,  0x44,  0x0C,  0x44,  0x12, 	/* 43D50 */
+	0x8A,  0x7D,  0x4A,  0x09,  0x28,  0x2C,  0x30,  0x2A,  0x10,  0x2A,  0x30,  0x2A,  0x48,  0x48,  0x84,  0x09, 	/* 43D60 */
+	0x03,  0xA1,  0x08,  0x20,  0x08,  0x20,  0x12,  0x7C,  0x64,  0x44,  0x14,  0xC8,  0x09,  0x28,  0x0C,  0x10, 	/* 43D70 */
+	0x12,  0x28,  0x7D,  0x44,  0x08,  0x82,  0x2D,  0xFD,  0x2A,  0x84,  0x2A,  0x84,  0x2A,  0x84,  0x48,  0xFC, 	/* 43D80 */
+	0x08,  0x00,  0xA2,  0x08,  0x40,  0x08,  0x40,  0x0A,  0x40,  0x72,  0x7E,  0x16,  0x82,  0x08,  0x82,  0x0B, 	/* 43D90 */
+	0x7A,  0x12,  0x4A,  0x7F,  0x4A,  0x09,  0x7A,  0x28,  0x4A,  0x2A,  0x4A,  0x29,  0x7A,  0x29,  0x02,  0x48, 	/* 43DA0 */
+	0x04,  0x08,  0x18,  0xA3,  0x08,  0x44,  0x08,  0x24,  0x0A,  0x28,  0x72,  0xFF,  0x14,  0x24,  0x08,  0x24, 	/* 43DB0 */
+	0x0C,  0x24,  0x12,  0x24,  0x7D,  0xFF,  0x09,  0x24,  0x28,  0x24,  0x2A,  0x24,  0x29,  0x24,  0x29,  0x44, 	/* 43DC0 */
+	0x48,  0x44,  0x08,  0x84,  0xA6,  0x08,  0x10,  0x08,  0x10,  0x0A,  0x28,  0x72,  0x28,  0x14,  0x44,  0x08, 	/* 43DD0 */
+	0x82,  0x0D,  0x7D,  0x12,  0x00,  0x7D,  0x00,  0x09,  0x7C,  0x28,  0x44,  0x2A,  0x44,  0x29,  0x44,  0x29, 	/* 43DE0 */
+	0x44,  0x48,  0x7C,  0x08,  0x00,  0xA8,  0x08,  0x08,  0x08,  0x0C,  0x0A,  0x0A,  0x72,  0x0A,  0x15,  0xFF, 	/* 43DF0 */
+	0x08,  0x08,  0x0C,  0x28,  0x12,  0x2A,  0x7D,  0xFA,  0x08,  0x2A,  0x2C,  0x24,  0x2A,  0x45,  0x2A,  0x4D, 	/* 43E00 */
+	0x2A,  0x93,  0x48,  0x23,  0x08,  0xC1,  0xAE,  0x08,  0x00,  0x08,  0x3E,  0x7F,  0xA2,  0x09,  0x22,  0x11, 	/* 43E10 */
+	0x22,  0x3E,  0x22,  0x05,  0xBE,  0x18,  0x80,  0x67,  0x10,  0x02,  0x60,  0x01,  0x8C,  0x7F,  0xF6,  0x02, 	/* 43E20 */
+	0xB1,  0x0C,  0x8C,  0x30,  0x82,  0x00,  0x80,  0xB1,  0x08,  0x20,  0x08,  0x20,  0x0B,  0xFE,  0x72,  0x20, 	/* 43E30 */
+	0x14,  0x48,  0x08,  0x9C,  0x0D,  0xE2,  0x12,  0x2A,  0x7D,  0x28,  0x08,  0x28,  0x2C,  0x48,  0x2A,  0x48, 	/* 43E40 */
+	0x2A,  0x88,  0x2A,  0x89,  0x49,  0x09,  0x0A,  0x07,  0xB2,  0x08,  0x10,  0x08,  0x10,  0x0A,  0x14,  0x72, 	/* 43E50 */
+	0xE4,  0x14,  0x28,  0x08,  0x10,  0x0C,  0x18,  0x12,  0x24,  0x7D,  0xFA,  0x09,  0x12,  0x08,  0x10,  0x2A, 	/* 43E60 */
+	0x54,  0x29,  0x54,  0x29,  0x52,  0x48,  0x92,  0x08,  0x10,  0xB3,  0x08,  0x20,  0x08,  0x20,  0x0A,  0x3E, 	/* 43E70 */
+	0x72,  0x42,  0x14,  0xA4,  0x09,  0x18,  0x0C,  0x24,  0x12,  0x43,  0x7D,  0x88,  0x08,  0x7E,  0x2C,  0x48, 	/* 43E80 */
+	0x2A,  0x48,  0x2B,  0xFF,  0x2A,  0x08,  0x48,  0x08,  0x08,  0x08,  0xB5,  0x08,  0x10,  0x08,  0x10,  0x0A, 	/* 43E90 */
+	0x28,  0x72,  0x28,  0x14,  0x44,  0x08,  0x82,  0x0D,  0x7D,  0x12,  0x00,  0x7E,  0x00,  0x09,  0xFE,  0x2C, 	/* 43EA0 */
+	0x20,  0x2A,  0x28,  0x2A,  0x44,  0x2A,  0x5C,  0x49,  0xE2,  0x08,  0x02,  0xB6,  0x08,  0x20,  0x08,  0x3C, 	/* 43EB0 */
+	0x0A,  0x48,  0x72,  0x48,  0x14,  0x90,  0x09,  0xFE,  0x0C,  0x92,  0x12,  0x92,  0x7D,  0x92,  0x08,  0xFE, 	/* 43EC0 */
+	0x2C,  0x80,  0x2A,  0x80,  0x2A,  0x81,  0x2A,  0x41,  0x48,  0x3F,  0x08,  0x00,  0xB9,  0x08,  0x00,  0x08, 	/* 43ED0 */
+	0x7E,  0x0A,  0x42,  0x72,  0x42,  0x14,  0x7E,  0x08,  0x00,  0x0A,  0x7E,  0x12,  0x42,  0x7F,  0x42,  0x09, 	/* 43EE0 */
+	0x7E,  0x2C,  0x42,  0x2A,  0x42,  0x2A,  0x7E,  0x29,  0x42,  0x48,  0x42,  0x08,  0x46,  0xBD,  0x08,  0x00, 	/* 43EF0 */
+	0x08,  0x7E,  0x0A,  0x42,  0x72,  0x42,  0x14,  0x42,  0x08,  0x7E,  0x0C,  0x10,  0x12,  0x10,  0x7D,  0x20, 	/* 43F00 */
+	0x09,  0x7E,  0x28,  0x42,  0x2A,  0x42,  0x29,  0x42,  0x29,  0x42,  0x48,  0x7E,  0x08,  0x00,  0x89,  0x08, 	/* 43F10 */
+	0x04,  0x08,  0x18,  0x0A,  0xF0,  0x72,  0x10,  0x15,  0xFF,  0x08,  0x38,  0x08,  0x54,  0x12,  0x92,  0x7F, 	/* 43F20 */
+	0x11,  0x09,  0xF8,  0x28,  0x28,  0x2A,  0x2E,  0x29,  0x22,  0x29,  0x42,  0x48,  0x82,  0x09,  0x0C,  0x8F, 	/* 43F30 */
+	0x08,  0x04,  0x08,  0x18,  0x0A,  0xE8,  0x72,  0x24,  0x14,  0x92,  0x08,  0x92,  0x09,  0x00,  0x14,  0x20, 	/* 43F40 */
+	0x7F,  0xFF,  0x08,  0x24,  0x28,  0x44,  0x2C,  0xE8,  0x2A,  0x98,  0x2A,  0x24,  0x48,  0x42,  0x09,  0x82, 	/* 43F50 */
+	0x93,  0x08,  0x00,  0x09,  0xFE,  0x0A,  0x00,  0x72,  0x54,  0x14,  0x54,  0x08,  0xA8,  0x0C,  0xA8,  0x12, 	/* 43F60 */
+	0x54,  0x7D,  0x54,  0x08,  0x00,  0x2C,  0xFE,  0x2A,  0x10,  0x2A,  0x10,  0x28,  0x10,  0x49,  0xFF,  0x08, 	/* 43F70 */
+	0x00,  0x99,  0x08,  0x88,  0x08,  0xCA,  0x0A,  0xAA,  0x72,  0xAC,  0x14,  0x88,  0x08,  0xFF,  0x0C,  0x88, 	/* 43F80 */
+	0x12,  0x9C,  0x7D,  0x9C,  0x08,  0xAA,  0x2C,  0xAA,  0x2A,  0xC9,  0x2A,  0x88,  0x2A,  0x88,  0x48,  0xFF, 	/* 43F90 */
+	0x08,  0x80,  0x9A,  0x08,  0x10,  0x08,  0x10,  0x0B,  0xFF,  0x72,  0x10,  0x14,  0x10,  0x08,  0xFE,  0x0C, 	/* 43FA0 */
+	0x00,  0x12,  0xFF,  0x7D,  0x81,  0x09,  0xA9,  0x28,  0x28,  0x2A,  0x28,  0x29,  0x48,  0x29,  0x49,  0x48, 	/* 43FB0 */
+	0x89,  0x09,  0x07,  0x9B,  0x08,  0x00,  0x08,  0xFE,  0x0A,  0x12,  0x72,  0x12,  0x14,  0xD2,  0x08,  0x32, 	/* 43FC0 */
+	0x0C,  0x2A,  0x12,  0x42,  0x7E,  0x8C,  0x09,  0x10,  0x2C,  0x08,  0x2A,  0xA8,  0x2A,  0xA2,  0x28,  0xA5, 	/* 43FD0 */
+	0x49,  0x25,  0x08,  0x1C,  0x9C,  0x08,  0x10,  0x08,  0x10,  0x0A,  0xFF,  0x72,  0x81,  0x14,  0x81,  0x08, 	/* 43FE0 */
+	0xFE,  0x0C,  0x00,  0x12,  0x00,  0x7D,  0xFF,  0x08,  0x10,  0x2C,  0x14,  0x2A,  0x52,  0x2A,  0x52,  0x2A, 	/* 43FF0 */
+	0x91,  0x49,  0x10,  0x08,  0x30,  0x9F,  0x08,  0x00,  0x09,  0xFF,  0x0A,  0x00,  0x72,  0xFE,  0x14,  0x82, 	/* 44000 */
+	0x08,  0x82,  0x0C,  0xFE,  0x12,  0x90,  0x7D,  0x90,  0x08,  0xFF,  0x2C,  0x90,  0x2A,  0x98,  0x2B,  0x28, 	/* 44010 */
+	0x29,  0x24,  0x4A,  0x42,  0x08,  0x81,  0xA2,  0x08,  0x00,  0x08,  0xFE,  0x0A,  0x82,  0x72,  0x92,  0x14, 	/* 44020 */
+	0xFE,  0x08,  0x92,  0x0C,  0x92,  0x12,  0xFE,  0x7D,  0x92,  0x08,  0xBA,  0x28,  0xAA,  0x2C,  0xAA,  0x2A, 	/* 44030 */
+	0xBA,  0x2A,  0x82,  0x49,  0x02,  0x0A,  0x06,  0xA3,  0x08,  0x10,  0x08,  0x54,  0x0A,  0x92,  0x72,  0xFE, 	/* 44040 */
+	0x14,  0x10,  0x04,  0x28,  0x0D,  0xFF,  0x12,  0x28,  0x7D,  0x44,  0x08,  0xFE,  0x2D,  0x09,  0x2A,  0x08, 	/* 44050 */
+	0x2A,  0x78,  0x2A,  0x44,  0x48,  0x44,  0x08,  0x3C,  0xAB,  0x08,  0x28,  0x08,  0x24,  0x0A,  0x2E,  0x73, 	/* 44060 */
+	0xF2,  0x14,  0x14,  0x08,  0x18,  0x08,  0x65,  0x15,  0xAB,  0x7E,  0x24,  0x08,  0x2F,  0x2D,  0xF2,  0x2A, 	/* 44070 */
+	0x14,  0x2A,  0x18,  0x28,  0x65,  0x49,  0x83,  0x08,  0x01,  0xAC,  0x08,  0x04,  0x08,  0x18,  0x0B,  0xE2, 	/* 44080 */
+	0x72,  0x92,  0x14,  0x54,  0x09,  0xFE,  0x0D,  0x02,  0x13,  0x02,  0x7D,  0xFC,  0x09,  0x44,  0x2C,  0x44, 	/* 44090 */
+	0x2A,  0x28,  0x2A,  0x10,  0x2A,  0x30,  0x48,  0x4C,  0x09,  0x83,  0xAD,  0x08,  0x20,  0x08,  0x24,  0x0A, 	/* 440A0 */
+	0x24,  0x72,  0x48,  0x14,  0x7F,  0x08,  0xC8,  0x0B,  0x48,  0x12,  0x7E,  0x7F,  0x48,  0x09,  0x48,  0x2C, 	/* 440B0 */
+	0x7E,  0x2A,  0x48,  0x29,  0x48,  0x29,  0x48,  0x48,  0x7F,  0x08,  0x40,  0xAE,  0x00,  0x10,  0x3F,  0x90, 	/* 440C0 */
+	0x00,  0x3F,  0x1F,  0x44,  0x11,  0xA4,  0x1F,  0x18,  0x10,  0x18,  0x21,  0x64,  0x41,  0x23,  0x0E,  0x50, 	/* 440D0 */
+	0x01,  0x8C,  0x7F,  0xFA,  0x02,  0xB1,  0x0C,  0x8C,  0x30,  0x82,  0x00,  0x80,  0xAF,  0x08,  0x40,  0x08, 	/* 440E0 */
+	0x40,  0x0A,  0xFE,  0x72,  0x82,  0x15,  0x42,  0x08,  0x7A,  0x0C,  0xA2,  0x12,  0x22,  0x7D,  0xFE,  0x08, 	/* 440F0 */
+	0x22,  0x2C,  0xAA,  0x2A,  0xAA,  0x2A,  0xFA,  0x2A,  0x02,  0x48,  0x04,  0x08,  0x18,  0xB0,  0x08,  0x10, 	/* 44100 */
+	0x08,  0x10,  0x0A,  0xFF,  0x72,  0x81,  0x14,  0x81,  0x08,  0x7C,  0x0C,  0x44,  0x12,  0x44,  0x7D,  0x7C, 	/* 44110 */
+	0x09,  0x40,  0x28,  0x40,  0x2A,  0x7E,  0x29,  0x42,  0x29,  0x42,  0x48,  0x7E,  0x08,  0x00,  0xB1,  0x08, 	/* 44120 */
+	0x00,  0x08,  0xFE,  0x0A,  0x82,  0x72,  0xCA,  0x14,  0xAA,  0x08,  0x92,  0x0C,  0xFE,  0x12,  0x92,  0x7E, 	/* 44130 */
+	0x92,  0x09,  0xD6,  0x0C,  0xD6,  0x2A,  0xFE,  0x2A,  0x82,  0x2A,  0x82,  0x48,  0x82,  0x08,  0x86,  0xB2, 	/* 44140 */
+	0x08,  0x00,  0x09,  0xFE,  0x0B,  0x02,  0x73,  0x46,  0x15,  0x2A,  0x09,  0xFE,  0x0D,  0x12,  0x13,  0x12, 	/* 44150 */
+	0x7F,  0xFE,  0x0B,  0x22,  0x29,  0x22,  0x2D,  0x22,  0x2B,  0x1E,  0x2B,  0x02,  0x49,  0x02,  0x09,  0x06, 	/* 44160 */
+	0xB4,  0x08,  0x00,  0x09,  0xFE,  0x0A,  0x22,  0x72,  0xAA,  0x14,  0x44,  0x08,  0xAA,  0x0D,  0x11,  0x12, 	/* 44170 */
+	0x00,  0x7D,  0xFE,  0x08,  0x22,  0x2C,  0xAA,  0x2A,  0xCC,  0x2A,  0x44,  0x28,  0xAC,  0x49,  0x12,  0x0A, 	/* 44180 */
+	0x21,  0xB5,  0x08,  0x04,  0x08,  0x18,  0x0A,  0xE8,  0x72,  0x24,  0x14,  0x92,  0x08,  0x92,  0x0D,  0x00, 	/* 44190 */
+	0x12,  0x10,  0x7D,  0x10,  0x09,  0xFF,  0x2C,  0x38,  0x2A,  0x34,  0x2A,  0x52,  0x2A,  0x91,  0x49,  0x10, 	/* 441A0 */
+	0x08,  0x10,  0xB8,  0x08,  0x10,  0x08,  0x10,  0x0A,  0x28,  0x72,  0x44,  0x14,  0x82,  0x09,  0x79,  0x0C, 	/* 441B0 */
+	0x00,  0x12,  0x00,  0x7D,  0xFE,  0x08,  0xAA,  0x2C,  0xAA,  0x2A,  0xFE,  0x2A,  0xAA,  0x2A,  0xAA,  0x48, 	/* 441C0 */
+	0xAA,  0x08,  0x86,  0xBA,  0x08,  0x10,  0x08,  0x10,  0x0B,  0xFE,  0x72,  0x10,  0x14,  0x28,  0x08,  0xC4, 	/* 441D0 */
+	0x0D,  0x00,  0x12,  0xFF,  0x7D,  0x04,  0x09,  0x74,  0x28,  0x54,  0x2A,  0x54,  0x29,  0x74,  0x29,  0x04, 	/* 441E0 */
+	0x48,  0x04,  0x08,  0x0C,  0xBB,  0x08,  0x10,  0x08,  0x10,  0x0A,  0xFF,  0x72,  0x81,  0x14,  0x81,  0x08, 	/* 441F0 */
+	0xFE,  0x0C,  0x10,  0x12,  0x10,  0x7D,  0x50,  0x08,  0x5E,  0x2C,  0x50,  0x2A,  0x50,  0x2A,  0x50,  0x2A, 	/* 44200 */
+	0xB0,  0x48,  0x98,  0x09,  0x07,  0xBD,  0x08,  0x10,  0x08,  0x10,  0x0A,  0x1F,  0x72,  0x10,  0x14,  0x7E, 	/* 44210 */
+	0x08,  0x42,  0x0C,  0x7E,  0x12,  0x42,  0x7D,  0x42,  0x09,  0x7E,  0x28,  0x10,  0x2A,  0x10,  0x29,  0xFF, 	/* 44220 */
+	0x29,  0x10,  0x48,  0x10,  0x08,  0x10,  0xBE,  0x08,  0x20,  0x08,  0x20,  0x0B,  0xFC,  0x72,  0x20,  0x17, 	/* 44230 */
+	0xFF,  0x08,  0x50,  0x0A,  0x52,  0x12,  0x8E,  0x7F,  0x40,  0x0A,  0x7C,  0x2C,  0x88,  0x2B,  0x50,  0x2A, 	/* 44240 */
+	0x20,  0x2A,  0x50,  0x49,  0x8C,  0x0A,  0x03,  0xBF,  0x08,  0x10,  0x08,  0x20,  0x0A,  0x7C,  0x72,  0x44, 	/* 44250 */
+	0x14,  0x7C,  0x08,  0x44,  0x0C,  0x44,  0x12,  0x7C,  0x7D,  0x10,  0x08,  0xFE,  0x2C,  0x92,  0x2A,  0x92, 	/* 44260 */
+	0x2A,  0x92,  0x2A,  0x9C,  0x48,  0x10,  0x08,  0x10,  0x87,  0x08,  0x49,  0x08,  0x49,  0x0A,  0x92,  0x73, 	/* 44270 */
+	0x24,  0x14,  0x92,  0x08,  0x49,  0x0A,  0x00,  0x12,  0xFE,  0x7F,  0x92,  0x09,  0x92,  0x28,  0x92,  0x2C, 	/* 44280 */
+	0xFE,  0x2A,  0x92,  0x2A,  0x92,  0x48,  0xFE,  0x08,  0x00,  0x8A,  0x00,  0x00,  0x3F,  0xFC,  0x24,  0x44, 	/* 44290 */
+	0x3F,  0x24,  0x21,  0x28,  0x3F,  0x10,  0x24,  0x28,  0x3F,  0xC6,  0x01,  0x20,  0x0E,  0x50,  0x01,  0x8C, 	/* 442A0 */
+	0x7F,  0xFA,  0x05,  0x30,  0x19,  0x0C,  0x61,  0x02,  0x01,  0x00,  0x8B,  0x08,  0x28,  0x08,  0x28,  0x0A, 	/* 442B0 */
+	0x28,  0x72,  0xEE,  0x14,  0x28,  0x08,  0x28,  0x0C,  0x28,  0x12,  0xEE,  0x7D,  0x28,  0x08,  0x28,  0x2C, 	/* 442C0 */
+	0x68,  0x2B,  0xAF,  0x2A,  0x48,  0x2A,  0x48,  0x48,  0x88,  0x09,  0x08,  0x8F,  0x08,  0x3C,  0x08,  0x04, 	/* 442D0 */
+	0x0A,  0x44,  0x72,  0x52,  0x14,  0x92,  0x09,  0x29,  0x0C,  0x44,  0x12,  0xFC,  0x7D,  0x12,  0x08,  0x08, 	/* 442E0 */
+	0x2C,  0xA8,  0x2A,  0xAA,  0x2A,  0xA1,  0x29,  0x25,  0x4A,  0x25,  0x08,  0x1C,  0x91,  0x08,  0x00,  0x08, 	/* 442F0 */
+	0xFC,  0x0A,  0x04,  0x72,  0xFC,  0x14,  0x04,  0x08,  0x04,  0x0D,  0xFF,  0x12,  0x10,  0x7D,  0x92,  0x09, 	/* 44300 */
+	0x52,  0x2C,  0x5C,  0x2A,  0x38,  0x2A,  0x54,  0x28,  0x92,  0x4B,  0x11,  0x08,  0x30,  0x92,  0x08,  0x20, 	/* 44310 */
+	0x08,  0x24,  0x0A,  0xFC,  0x72,  0x28,  0x14,  0x28,  0x08,  0x30,  0x0D,  0xFF,  0x12,  0x20,  0x7D,  0x7C, 	/* 44320 */
+	0x08,  0x44,  0x2C,  0xC4,  0x2B,  0x7C,  0x2A,  0x44,  0x2A,  0x44,  0x48,  0x7C,  0x08,  0x00,  0x95,  0x08, 	/* 44330 */
+	0x10,  0x08,  0x10,  0x0B,  0xFF,  0x72,  0x44,  0x14,  0x28,  0x08,  0x10,  0x0C,  0x6C,  0x12,  0xC7,  0x7D, 	/* 44340 */
+	0x44,  0x08,  0x7C,  0x2C,  0x44,  0x2A,  0x7C,  0x2A,  0x84,  0x28,  0x84,  0x49,  0x04,  0x0A,  0x04,  0x98, 	/* 44350 */
+	0x08,  0x08,  0x08,  0x0A,  0x0A,  0x09,  0x72,  0xFF,  0x14,  0x88,  0x08,  0xF8,  0x0C,  0x8A,  0x12,  0x8A, 	/* 44360 */
+	0x7D,  0xFA,  0x08,  0xDA,  0x2C,  0xDC,  0x2A,  0xF5,  0x2A,  0x8D,  0x29,  0x13,  0x49,  0x23,  0x0A,  0x41, 	/* 44370 */
+	0x9A,  0x08,  0x10,  0x08,  0x20,  0x0A,  0xFC,  0x72,  0x84,  0x14,  0xFC,  0x08,  0x84,  0x0C,  0x84,  0x12, 	/* 44380 */
+	0xFC,  0x7D,  0x10,  0x08,  0x12,  0x2D,  0xFC,  0x2A,  0x58,  0x2A,  0x54,  0x2A,  0x92,  0x49,  0x11,  0x08, 	/* 44390 */
+	0x30,  0x9C,  0x08,  0x06,  0x10,  0xF8,  0x3E,  0x10,  0x22,  0x10,  0x22,  0x64,  0x3E,  0x28,  0x22,  0x14, 	/* 443A0 */
+	0x22,  0x22,  0x3E,  0xFE,  0x08,  0x11,  0x7F,  0x14,  0x49,  0x54,  0x49,  0x52,  0x49,  0x52,  0x4B,  0x92, 	/* 443B0 */
+	0x08,  0x10,  0x9D,  0x08,  0x00,  0x08,  0xFC,  0x0A,  0x84,  0x72,  0x84,  0x14,  0xFC,  0x08,  0x00,  0x0D, 	/* 443C0 */
+	0xFF,  0x12,  0x84,  0x7D,  0xFC,  0x08,  0x84,  0x28,  0xFC,  0x2C,  0x84,  0x2A,  0x87,  0x2A,  0xFC,  0x4B, 	/* 443D0 */
+	0x84,  0x08,  0x04,  0x9E,  0x08,  0x20,  0x09,  0xDC,  0x0B,  0x14,  0x73,  0x15,  0x15,  0xD5,  0x19,  0x27, 	/* 443E0 */
+	0x09,  0x40,  0x15,  0xFE,  0x7F,  0x12,  0x09,  0x12,  0x2D,  0x14,  0x2D,  0xC8,  0x2B,  0x0C,  0x29,  0x14, 	/* 443F0 */
+	0x49,  0x22,  0x09,  0x41,  0xA0,  0x08,  0x10,  0x08,  0x10,  0x0A,  0xFE,  0x72,  0x44,  0x14,  0x24,  0x08, 	/* 44400 */
+	0x28,  0x0D,  0xFF,  0x13,  0x11,  0x7D,  0x11,  0x08,  0xFE,  0x2C,  0x92,  0x2A,  0x92,  0x2A,  0x92,  0x2A, 	/* 44410 */
+	0x9C,  0x48,  0x10,  0x08,  0x10,  0xA1,  0x08,  0x00,  0x08,  0xFE,  0x0A,  0x82,  0x72,  0xFE,  0x14,  0x88, 	/* 44420 */
+	0x08,  0xFF,  0x0C,  0x88,  0x12,  0x85,  0x7E,  0xE3,  0x09,  0x01,  0x2C,  0xFE,  0x2A,  0x82,  0x2A,  0xFE, 	/* 44430 */
+	0x2A,  0x82,  0x48,  0xFE,  0x08,  0x00,  0xA4,  0x08,  0x94,  0x08,  0x94,  0x0B,  0xFF,  0x72,  0x94,  0x14, 	/* 44440 */
+	0x94,  0x08,  0x9C,  0x0C,  0x80,  0x12,  0xFE,  0x7D,  0x10,  0x09,  0xFF,  0x0C,  0x10,  0x2A,  0x38,  0x2A, 	/* 44450 */
+	0x54,  0x28,  0x92,  0x4B,  0x11,  0x08,  0x10,  0xA8,  0x08,  0x00,  0x09,  0xFF,  0x0A,  0x00,  0x72,  0xFE, 	/* 44460 */
+	0x14,  0x82,  0x08,  0x82,  0x0C,  0xFE,  0x12,  0x80,  0x7D,  0xFF,  0x08,  0xD5,  0x2C,  0xD5,  0x2A,  0xFF, 	/* 44470 */
+	0x29,  0x55,  0x29,  0x55,  0x4A,  0x55,  0x08,  0x43,  0xA9,  0x08,  0x04,  0x08,  0x1A,  0x0B,  0xE2,  0x72, 	/* 44480 */
+	0x24,  0x14,  0x94,  0x08,  0x58,  0x0D,  0xFE,  0x12,  0x40,  0x7D,  0xFF,  0x08,  0x40,  0x2C,  0x7C,  0x2A, 	/* 44490 */
+	0xA4,  0x2A,  0x98,  0x2B,  0x10,  0x48,  0x6C,  0x09,  0x83,  0xAC,  0x08,  0x00,  0x09,  0xFF,  0x0A,  0x20, 	/* 444A0 */
+	0x72,  0x40,  0x15,  0xFE,  0x09,  0x4A,  0x0D,  0x4A,  0x13,  0x7A,  0x7D,  0x4A,  0x09,  0x4A,  0x29,  0x7A, 	/* 444B0 */
+	0x2D,  0x4A,  0x2B,  0x4A,  0x49,  0x4A,  0x09,  0xFE,  0x09,  0x02,  0xAF,  0x08,  0x10,  0x08,  0xFC,  0x0A, 	/* 444C0 */
+	0x24,  0x72,  0x24,  0x17,  0xFF,  0x08,  0x00,  0x0A,  0x7E,  0x12,  0x42,  0x7F,  0x7E,  0x09,  0x08,  0x2C, 	/* 444D0 */
+	0x7E,  0x2A,  0x48,  0x2A,  0x48,  0x29,  0xFF,  0x48,  0x08,  0x08,  0x08,  0xB2,  0x10,  0x08,  0x13,  0x88, 	/* 444E0 */
+	0x16,  0x88,  0x66,  0xAA,  0x2B,  0xAA,  0x12,  0xA9,  0x1A,  0xA9,  0x26,  0xC8,  0x7B,  0x8A,  0x12,  0x9A, 	/* 444F0 */
+	0x32,  0x84,  0x3A,  0x84,  0x37,  0x88,  0x54,  0x10,  0x10,  0x20,  0x10,  0x40,  0xB4,  0x08,  0x10,  0x08, 	/* 44500 */
+	0x10,  0x13,  0xFF,  0x72,  0x10,  0x14,  0xFE,  0x08,  0x92,  0x0C,  0xFE,  0x12,  0x92,  0x7D,  0x92,  0x08, 	/* 44510 */
+	0xFE,  0x2C,  0x38,  0x2A,  0x54,  0x2A,  0x54,  0x2A,  0x92,  0x49,  0x11,  0x08,  0x10,  0xBB,  0x10,  0x10, 	/* 44520 */
+	0x13,  0xF0,  0x14,  0x90,  0x64,  0x9F,  0x19,  0x54,  0x11,  0x24,  0x17,  0xE4,  0x28,  0x94,  0x7C,  0x94, 	/* 44530 */
+	0x13,  0xD4,  0x38,  0x88,  0x34,  0xA8,  0x34,  0xD4,  0x53,  0x14,  0x10,  0x22,  0x10,  0x41,  0x81,  0x08, 	/* 44540 */
+	0x00,  0x08,  0xF8,  0x0A,  0x08,  0x72,  0xF8,  0x14,  0x08,  0x09,  0xFF,  0x0A,  0x20,  0x12,  0x52,  0x7F, 	/* 44550 */
+	0x94,  0x09,  0x38,  0x2C,  0x58,  0x2A,  0xB4,  0x2A,  0x52,  0x2B,  0x91,  0x48,  0x10,  0x08,  0x60,  0x84, 	/* 44560 */
+	0x08,  0x00,  0x08,  0xFC,  0x0A,  0x94,  0x72,  0xFC,  0x14,  0x94,  0x08,  0x94,  0x0A,  0xFC,  0x12,  0x10, 	/* 44570 */
+	0x7F,  0xFE,  0x09,  0x92,  0x2C,  0xFE,  0x2A,  0x92,  0x2A,  0x92,  0x4A,  0xFE,  0x48,  0x11,  0x08,  0x0F, 	/* 44580 */
+	0x85,  0x08,  0x0C,  0x08,  0x0A,  0x0A,  0x08,  0x73,  0xFF,  0x15,  0x08,  0x09,  0xF8,  0x0D,  0x0A,  0x13, 	/* 44590 */
+	0x2A,  0x7F,  0xFA,  0x09,  0x5A,  0x2D,  0x54,  0x2B,  0xE4,  0x2B,  0x35,  0x49,  0x4B,  0x09,  0x13,  0x0A, 	/* 445A0 */
+	0x21,  0x89,  0x08,  0x00,  0x08,  0xFF,  0x0A,  0x44,  0x72,  0x44,  0x14,  0x44,  0x08,  0xAA,  0x0D,  0xDD, 	/* 445B0 */
+	0x12,  0x00,  0x7D,  0xFF,  0x08,  0x00,  0x2C,  0xFE,  0x2A,  0x82,  0x2A,  0xFE,  0x2A,  0x82,  0x48,  0xFE, 	/* 445C0 */
+	0x08,  0x00,  0x8A,  0x08,  0x58,  0x08,  0x48,  0x0A,  0x48,  0x72,  0xBC,  0x14,  0x84,  0x09,  0x7A,  0x0E, 	/* 445D0 */
+	0x09,  0x14,  0x84,  0x7E,  0x84,  0x09,  0xFE,  0x2B,  0x55,  0x2D,  0x54,  0x2D,  0x54,  0x29,  0x54,  0x4B, 	/* 445E0 */
+	0xFF,  0x08,  0x00,  0x8B,  0x09,  0x08,  0x08,  0x90,  0x10,  0xBE,  0x64,  0x22,  0x16,  0x22,  0x19,  0x3E, 	/* 445F0 */
+	0x09,  0x20,  0x14,  0x20,  0x7F,  0xBE,  0x08,  0xA2,  0x2C,  0xA2,  0x2A,  0xA2,  0x2A,  0xBE,  0x29,  0x40, 	/* 44600 */
+	0x4A,  0x30,  0x0C,  0x0F,  0x92,  0x08,  0x84,  0x08,  0x48,  0x0A,  0xFE,  0x72,  0x20,  0x14,  0x20,  0x09, 	/* 44610 */
+	0xFC,  0x0C,  0x20,  0x12,  0x20,  0x7F,  0xFE,  0x0A,  0x40,  0x28,  0x80,  0x2C,  0xFE,  0x2B,  0x10,  0x2A, 	/* 44620 */
+	0x10,  0x49,  0xFF,  0x08,  0x00,  0x9B,  0x08,  0x14,  0x08,  0x12,  0x0B,  0xFF,  0x72,  0x10,  0x14,  0xFE, 	/* 44630 */
+	0x08,  0x92,  0x0C,  0xFE,  0x12,  0x92,  0x7D,  0xFE,  0x09,  0x04,  0x2C,  0xFF,  0x2A,  0x44,  0x2A,  0x24, 	/* 44640 */
+	0x2A,  0x24,  0x48,  0x04,  0x08,  0x0C,  0x9E,  0x08,  0x10,  0x08,  0x10,  0x0A,  0xFF,  0x72,  0x00,  0x14, 	/* 44650 */
+	0x7C,  0x08,  0x44,  0x0C,  0x7C,  0x12,  0x00,  0x7D,  0xFE,  0x09,  0x82,  0x2C,  0xBA,  0x2A,  0xAA,  0x2A, 	/* 44660 */
+	0xAA,  0x2A,  0xBA,  0x48,  0x82,  0x08,  0x86,  0x9F,  0x08,  0x00,  0x08,  0xFF,  0x0A,  0x80,  0x72,  0xBE, 	/* 44670 */
+	0x14,  0x80,  0x08,  0xFF,  0x08,  0xB2,  0x14,  0xAC,  0x7D,  0x24,  0x0A,  0x63,  0x2C,  0x04,  0x2A,  0xFF, 	/* 44680 */
+	0x2A,  0x44,  0x2A,  0x24,  0x48,  0x24,  0x08,  0x0C,  0xA1,  0x08,  0x10,  0x08,  0x10,  0x0A,  0xFF,  0x72, 	/* 44690 */
+	0x81,  0x14,  0x90,  0x09,  0xFF,  0x0C,  0x44,  0x12,  0x28,  0x7D,  0xFF,  0x09,  0x10,  0x28,  0x10,  0x2A, 	/* 446A0 */
+	0xFE,  0x29,  0x10,  0x29,  0x10,  0x48,  0x10,  0x08,  0x10,  0xA2,  0x00,  0x20,  0x3C,  0xA8,  0x25,  0x24, 	/* 446B0 */
+	0x25,  0xFE,  0x24,  0x50,  0x3F,  0xFF,  0x24,  0x48,  0x24,  0xA4,  0x25,  0x2A,  0x3E,  0xD1,  0x24,  0x2C, 	/* 446C0 */
+	0x25,  0xFA,  0x24,  0x20,  0x24,  0xAC,  0x27,  0x22,  0x4C,  0x20,  0xA3,  0x00,  0x02,  0x1E,  0xFC,  0x52, 	/* 446D0 */
+	0x10,  0x5E,  0x14,  0x52,  0xE4,  0x5E,  0x28,  0x52,  0x10,  0x52,  0x24,  0x5E,  0xFE,  0x40,  0x11,  0x7F, 	/* 446E0 */
+	0x98,  0x08,  0x54,  0x2A,  0x52,  0x29,  0x52,  0x49,  0x90,  0x08,  0x10,  0xA6,  0x08,  0x22,  0x08,  0x52, 	/* 446F0 */
+	0x0A,  0x54,  0x72,  0x94,  0x14,  0xFF,  0x09,  0x08,  0x0C,  0x48,  0x14,  0x68,  0x7A,  0xA8,  0x08,  0xAE, 	/* 44700 */
+	0x2D,  0x28,  0x2B,  0x28,  0x29,  0x58,  0x29,  0x48,  0x49,  0x84,  0x09,  0x03,  0xAB,  0x08,  0x10,  0x08, 	/* 44710 */
+	0x1E,  0x0A,  0x22,  0x72,  0x54,  0x15,  0x08,  0x09,  0x14,  0x0C,  0x63,  0x13,  0x88,  0x7E,  0xBE,  0x0A, 	/* 44720 */
+	0x88,  0x28,  0xBE,  0x2C,  0x88,  0x2A,  0xFF,  0x49,  0x48,  0x09,  0x30,  0x0A,  0x0F,  0xAE,  0x08,  0x10, 	/* 44730 */
+	0x08,  0x10,  0x0A,  0xFE,  0x72,  0x82,  0x14,  0xC2,  0x08,  0x7E,  0x0A,  0x48,  0x12,  0x90,  0x7F,  0xBE, 	/* 44740 */
+	0x09,  0xA2,  0x28,  0xA2,  0x2C,  0xBE,  0x2A,  0xA2,  0x4A,  0xA2,  0x08,  0xBE,  0x08,  0x80,  0xB1,  0x08, 	/* 44750 */
+	0x92,  0x08,  0x92,  0x10,  0x92,  0x75,  0x35,  0x15,  0x2D,  0x0A,  0x48,  0x08,  0x00,  0x14,  0x88,  0x7E, 	/* 44760 */
+	0xA8,  0x09,  0x2E,  0x2B,  0x28,  0x2D,  0x28,  0x2D,  0x28,  0x4D,  0x58,  0x09,  0x48,  0x09,  0x87,  0xB2, 	/* 44770 */
+	0x08,  0x00,  0x08,  0xFE,  0x0A,  0x92,  0x72,  0xFE,  0x14,  0x92,  0x08,  0xFE,  0x0C,  0x10,  0x12,  0x24, 	/* 44780 */
+	0x7D,  0xE8,  0x08,  0x12,  0x2D,  0xFD,  0x2A,  0x50,  0x2A,  0x54,  0x2A,  0x92,  0x49,  0x11,  0x08,  0x10, 	/* 44790 */
+	0xB5,  0x08,  0x00,  0x08,  0x7C,  0x0A,  0x44,  0x72,  0x7C,  0x14,  0x44,  0x08,  0x7C,  0x0C,  0x00,  0x12, 	/* 447A0 */
+	0xFF,  0x7D,  0xA9,  0x08,  0xFF,  0x2C,  0x00,  0x2A,  0xFE,  0x2A,  0x24,  0x2A,  0x18,  0x48,  0x6C,  0x09, 	/* 447B0 */
+	0x83,  0xB7,  0x08,  0x10,  0x08,  0xFE,  0x0A,  0x92,  0x73,  0xFF,  0x14,  0x92,  0x08,  0xFE,  0x0C,  0x10, 	/* 447C0 */
+	0x12,  0xFE,  0x7D,  0x92,  0x08,  0xFE,  0x2C,  0x20,  0x2B,  0xFF,  0x2A,  0x44,  0x2A,  0xF8,  0x48,  0x2C, 	/* 447D0 */
+	0x09,  0xC2,  0xB9,  0x08,  0x00,  0x08,  0xFF,  0x0A,  0x28,  0x72,  0xFE,  0x14,  0xAA,  0x08,  0xAA,  0x0A, 	/* 447E0 */
+	0xFE,  0x12,  0x00,  0x7F,  0x7E,  0x09,  0x00,  0x2C,  0xFF,  0x2A,  0x50,  0x2A,  0x54,  0x2A,  0x92,  0x49, 	/* 447F0 */
+	0x11,  0x08,  0x30,  0xBA,  0x08,  0x08,  0x08,  0x88,  0x10,  0x7F,  0x64,  0x48,  0x14,  0x3E,  0x09,  0x2A, 	/* 44800 */
+	0x08,  0xAA,  0x14,  0xBE,  0x7E,  0x2A,  0x09,  0xAA,  0x2C,  0xBE,  0x2A,  0x88,  0x2A,  0xFF,  0x28,  0x88, 	/* 44810 */
+	0x49,  0x48,  0x0A,  0x3F,  0xBB,  0x00,  0x80,  0x1F,  0xFF,  0x11,  0x08,  0x1F,  0xFF,  0x11,  0x08,  0x15, 	/* 44820 */
+	0xAA,  0x15,  0xAA,  0x19,  0x4B,  0x11,  0x48,  0x10,  0x90,  0x13,  0x28,  0x10,  0xC6,  0x2F,  0xFD,  0x20, 	/* 44830 */
+	0x50,  0x43,  0x4C,  0x0C,  0x42,  0xBD,  0x08,  0x10,  0x08,  0x20,  0x0A,  0xFE,  0x72,  0x92,  0x14,  0xDE, 	/* 44840 */
+	0x08,  0xA6,  0x0C,  0xEA,  0x12,  0x92,  0x7D,  0xAA,  0x08,  0xC6,  0x2C,  0xFE,  0x2A,  0x90,  0x2A,  0xAA, 	/* 44850 */
+	0x28,  0xA1,  0x49,  0x25,  0x08,  0x1C,  0xBE,  0x08,  0x10,  0x09,  0xFF,  0x0A,  0x10,  0x72,  0xFE,  0x14, 	/* 44860 */
+	0x10,  0x09,  0xFF,  0x0C,  0x00,  0x12,  0x7C,  0x7D,  0x44,  0x09,  0x7C,  0x28,  0x44,  0x2A,  0x7C,  0x29, 	/* 44870 */
+	0x44,  0x29,  0x7C,  0x48,  0x4C,  0x09,  0x82,  0x81,  0x10,  0x20,  0x1F,  0xA0,  0x10,  0x3F,  0x3F,  0x24, 	/* 44880 */
+	0x55,  0x64,  0x1F,  0x98,  0x25,  0x08,  0x3F,  0x94,  0x20,  0xE3,  0x03,  0x20,  0x0E,  0x50,  0x01,  0x8C, 	/* 44890 */
+	0x7F,  0xFA,  0x04,  0xB0,  0x18,  0x8C,  0x60,  0x82,  0x83,  0x08,  0x10,  0x08,  0x92,  0x0A,  0x92,  0x72, 	/* 448A0 */
+	0xFE,  0x14,  0x00,  0x08,  0xEE,  0x0C,  0xAA,  0x12,  0xAA,  0x7E,  0xEE,  0x09,  0xAA,  0x2C,  0xAA,  0x2A, 	/* 448B0 */
+	0xEE,  0x2A,  0xAA,  0x2A,  0xAA,  0x48,  0xAA,  0x09,  0x36,  0x86,  0x08,  0x00,  0x09,  0xFE,  0x0A,  0x66, 	/* 448C0 */
+	0x72,  0xAA,  0x14,  0x66,  0x09,  0xBA,  0x0C,  0x26,  0x12,  0x30,  0x7E,  0x4C,  0x09,  0x93,  0x2C,  0xE4, 	/* 448D0 */
+	0x2A,  0x18,  0x2A,  0x62,  0x2A,  0x04,  0x48,  0x18,  0x08,  0xE0,  0x8A,  0x08,  0x88,  0x08,  0x8C,  0x0B, 	/* 448E0 */
+	0xEA,  0x72,  0x8A,  0x14,  0x88,  0x0B,  0xFF,  0x09,  0x48,  0x15,  0x4A,  0x7F,  0x5A,  0x09,  0x6A,  0x2D, 	/* 448F0 */
+	0x4C,  0x2B,  0x44,  0x29,  0x4D,  0x29,  0xF5,  0x4F,  0x23,  0x08,  0x41,  0x8B,  0x04,  0x00,  0x7F,  0xBC, 	/* 44900 */
+	0x04,  0x25,  0x3F,  0x25,  0x25,  0x43,  0x3F,  0xFC,  0x25,  0x24,  0x3F,  0x18,  0x04,  0xA4,  0x7F,  0xA3, 	/* 44910 */
+	0x07,  0x50,  0x01,  0x8C,  0x7F,  0xFA,  0x05,  0x21,  0x19,  0x18,  0x61,  0x04,  0x8D,  0x08,  0x10,  0x08, 	/* 44920 */
+	0xFC,  0x0A,  0x14,  0x73,  0xFF,  0x14,  0x14,  0x08,  0xFC,  0x0C,  0x12,  0x14,  0x92,  0x7E,  0xD6,  0x0A, 	/* 44930 */
+	0xBA,  0x2C,  0xFE,  0x2A,  0x92,  0x2A,  0xBA,  0x29,  0x56,  0x49,  0x92,  0x0A,  0x12,  0x94,  0x10,  0x88, 	/* 44940 */
+	0x10,  0x8C,  0x17,  0xFA,  0x66,  0x2A,  0x29,  0x28,  0x11,  0x48,  0x1B,  0xFF,  0x24,  0x0A,  0x7D,  0xEA, 	/* 44950 */
+	0x15,  0x2A,  0x39,  0xE4,  0x35,  0x2C,  0x35,  0x2D,  0x51,  0xF5,  0x10,  0x13,  0x10,  0x21,  0x95,  0x08, 	/* 44960 */
+	0x82,  0x08,  0x44,  0x0A,  0xFF,  0x72,  0x10,  0x14,  0x7E,  0x08,  0x10,  0x0D,  0xFF,  0x12,  0x92,  0x7D, 	/* 44970 */
+	0x54,  0x09,  0xFF,  0x28,  0x00,  0x2A,  0x7E,  0x29,  0x42,  0x29,  0x42,  0x48,  0x7E,  0x08,  0x00,  0x96, 	/* 44980 */
+	0x09,  0x48,  0x09,  0x48,  0x13,  0xE8,  0x65,  0x4F,  0x15,  0x52,  0x0B,  0xF2,  0x08,  0x2A,  0x15,  0xEA, 	/* 44990 */
+	0x7F,  0x2A,  0x09,  0xE4,  0x2D,  0x24,  0x2B,  0xE4,  0x2B,  0x2A,  0x29,  0x2A,  0x49,  0x32,  0x09,  0x61, 	/* 449A0 */
+	0x99,  0x08,  0x02,  0x08,  0xFC,  0x0A,  0x92,  0x72,  0x54,  0x05,  0xFF,  0x08,  0x38,  0x0C,  0x54,  0x12, 	/* 449B0 */
+	0x92,  0x7D,  0xFF,  0x08,  0x92,  0x2C,  0x92,  0x2A,  0xFE,  0x2A,  0x92,  0x2A,  0x92,  0x48,  0xFE,  0x08, 	/* 449C0 */
+	0x00,  0x9A,  0x08,  0x10,  0x08,  0x10,  0x0B,  0xFF,  0x72,  0x28,  0x14,  0xAA,  0x08,  0x44,  0x0C,  0xFE, 	/* 449D0 */
+	0x13,  0x45,  0x7E,  0x7C,  0x08,  0x44,  0x2C,  0x7C,  0x2A,  0x10,  0x2A,  0x94,  0x28,  0x92,  0x49,  0x11, 	/* 449E0 */
+	0x08,  0x30,  0x9D,  0x08,  0x00,  0x09,  0xEE,  0x13,  0x2A,  0x65,  0xEE,  0x15,  0x2A,  0x09,  0xEE,  0x09, 	/* 449F0 */
+	0x02,  0x15,  0x7A,  0x7F,  0x4A,  0x09,  0x7A,  0x2D,  0x4A,  0x2B,  0x7A,  0x2B,  0x4A,  0x29,  0x4A,  0x49, 	/* 44A00 */
+	0x5A,  0x09,  0x06,  0x9E,  0x08,  0x10,  0x08,  0x7C,  0x0A,  0x10,  0x72,  0xFE,  0x14,  0x00,  0x08,  0x44, 	/* 44A10 */
+	0x0D,  0xFF,  0x12,  0x44,  0x7D,  0x74,  0x09,  0xCF,  0x2C,  0x00,  0x2B,  0xFF,  0x2A,  0x48,  0x2A,  0x49, 	/* 44A20 */
+	0x48,  0x89,  0x09,  0x07,  0xA6,  0x08,  0x00,  0x0B,  0xDE,  0x10,  0x52,  0x74,  0x52,  0x14,  0x5E,  0x09, 	/* 44A30 */
+	0xC8,  0x0D,  0x3E,  0x15,  0x2A,  0x7F,  0xEA,  0x08,  0x6A,  0x0C,  0x7E,  0x2A,  0x4C,  0x2A,  0x4A,  0x28, 	/* 44A40 */
+	0x4A,  0x48,  0x8F,  0x0B,  0x71,  0xA7,  0x08,  0x00,  0x08,  0xFE,  0x0A,  0x10,  0x73,  0xFF,  0x15,  0x11, 	/* 44A50 */
+	0x09,  0xDD,  0x0D,  0x11,  0x12,  0xDC,  0x7D,  0x00,  0x08,  0xFE,  0x2C,  0x00,  0x2B,  0xFF,  0x2A,  0x20, 	/* 44A60 */
+	0x2A,  0x48,  0x49,  0xFC,  0x08,  0x02,  0xA9,  0x08,  0x00,  0x09,  0xFE,  0x09,  0x52,  0x73,  0x52,  0x15, 	/* 44A70 */
+	0xDE,  0x08,  0x50,  0x0C,  0x50,  0x13,  0xDE,  0x7D,  0x52,  0x09,  0x52,  0x2D,  0xDE,  0x2B,  0x52,  0x2B, 	/* 44A80 */
+	0x52,  0x29,  0xDE,  0x48,  0x41,  0x08,  0x3F,  0xAA,  0x08,  0x10,  0x08,  0x10,  0x0A,  0x28,  0x72,  0xFC, 	/* 44A90 */
+	0x17,  0x03,  0x09,  0xFE,  0x0D,  0xA6,  0x13,  0x6A,  0x7D,  0xFE,  0x08,  0x00,  0x2C,  0xFC,  0x2A,  0x84, 	/* 44AA0 */
+	0x2A,  0xFC,  0x2A,  0x84,  0x48,  0xFC,  0x08,  0x00,  0xAD,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x00, 	/* 44AB0 */
+	0x00,  0x3F,  0xFE,  0x24,  0x92,  0x38,  0x92,  0x2A,  0xFE,  0x24,  0xD6,  0x2A,  0xD6,  0x3F,  0xFE,  0x24, 	/* 44AC0 */
+	0x9A,  0x2E,  0x96,  0x2D,  0x9E,  0x34,  0xE2,  0x24,  0x86,  0xB0,  0x08,  0x00,  0x08,  0x7C,  0x0A,  0x44, 	/* 44AD0 */
+	0x72,  0x44,  0x14,  0x7C,  0x09,  0xEF,  0x0D,  0x29,  0x13,  0x29,  0x7D,  0xEF,  0x08,  0x10,  0x2D,  0xFF, 	/* 44AE0 */
+	0x2A,  0x38,  0x2A,  0x54,  0x2A,  0x92,  0x49,  0x11,  0x08,  0x10,  0xB9,  0x08,  0x00,  0x09,  0xFE,  0x09, 	/* 44AF0 */
+	0x2A,  0x73,  0xFE,  0x14,  0x10,  0x08,  0xFE,  0x0C,  0x10,  0x13,  0xFF,  0x7D,  0x44,  0x08,  0x28,  0x2A, 	/* 44B00 */
+	0xFF,  0x29,  0x10,  0x29,  0xFE,  0x29,  0x10,  0x48,  0x10,  0x08,  0x10,  0xBB,  0x08,  0x00,  0x08,  0xFE, 	/* 44B10 */
+	0x0A,  0x10,  0x73,  0xFF,  0x15,  0x11,  0x09,  0xDD,  0x08,  0x11,  0x14,  0xDC,  0x7E,  0x00,  0x0B,  0xFF, 	/* 44B20 */
+	0x28,  0x20,  0x2D,  0xFE,  0x2B,  0x4A,  0x2B,  0x4A,  0x49,  0x4A,  0x09,  0x06,  0xBC,  0x08,  0x24,  0x09, 	/* 44B30 */
+	0x5A,  0x09,  0x24,  0x75,  0x5A,  0x15,  0xED,  0x09,  0x00,  0x0D,  0xFF,  0x13,  0x24,  0x7D,  0x24,  0x09, 	/* 44B40 */
+	0x5A,  0x2D,  0x24,  0x2B,  0x5A,  0x2B,  0xED,  0x29,  0x00,  0x49,  0xFF,  0x08,  0x00,  0xBD,  0x08,  0x20, 	/* 44B50 */
+	0x09,  0xFF,  0x0B,  0x01,  0x72,  0xFE,  0x14,  0xA4,  0x08,  0xA8,  0x0D,  0x30,  0x12,  0x7C,  0x7E,  0xC4, 	/* 44B60 */
+	0x09,  0x7C,  0x28,  0x44,  0x2C,  0x7C,  0x2A,  0x44,  0x2A,  0x7C,  0x48,  0x66,  0x0B,  0x81,  0xBF,  0x08, 	/* 44B70 */
+	0x04,  0x09,  0xF4,  0x0B,  0x47,  0x75,  0x48,  0x15,  0xF0,  0x09,  0x10,  0x0D,  0xF7,  0x13,  0x40,  0x7D, 	/* 44B80 */
+	0xF0,  0x08,  0x00,  0x2C,  0xFE,  0x2A,  0xAA,  0x2A,  0xAA,  0x2A,  0xAA,  0x49,  0xFF,  0x08,  0x00,  0x82, 	/* 44B90 */
+	0x10,  0x20,  0x1F,  0xBF,  0x22,  0x48,  0x47,  0xF0,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x07,  0xF0, 	/* 44BA0 */
+	0x04,  0x10,  0x7F,  0xFF,  0x04,  0xB0,  0x1B,  0x4C,  0x61,  0xB3,  0x1F,  0xEC,  0x04,  0xB0,  0x18,  0x88, 	/* 44BB0 */
+	0x83,  0x08,  0x10,  0x08,  0x10,  0x0B,  0xFF,  0x74,  0x28,  0x17,  0xD7,  0x09,  0x56,  0x09,  0x55,  0x16, 	/* 44BC0 */
+	0xD5,  0x7C,  0x00,  0x0A,  0x82,  0x28,  0xFE,  0x2C,  0x82,  0x2A,  0xFE,  0x29,  0x02,  0x49,  0x02,  0x0A, 	/* 44BD0 */
+	0x02,  0x88,  0x08,  0x80,  0x08,  0xBF,  0x08,  0x84,  0x77,  0xE8,  0x14,  0x9E,  0x18,  0x92,  0x0B,  0xD2, 	/* 44BE0 */
+	0x14,  0x1E,  0x7E,  0x12,  0x09,  0xDE,  0x2D,  0x52,  0x2D,  0x52,  0x2B,  0x5E,  0x29,  0xC4,  0x48,  0x12, 	/* 44BF0 */
+	0x08,  0x21,  0x89,  0x08,  0x44,  0x09,  0xFF,  0x0A,  0x44,  0x73,  0xFF,  0x14,  0x44,  0x08,  0xAA,  0x0D, 	/* 44C00 */
+	0x01,  0x12,  0xFC,  0x7D,  0x84,  0x08,  0xFC,  0x2C,  0x84,  0x2A,  0xFC,  0x2A,  0x84,  0x28,  0xFC,  0x48, 	/* 44C10 */
+	0xCC,  0x0B,  0x02,  0x8C,  0x08,  0x10,  0x09,  0xFF,  0x0A,  0x10,  0x72,  0xFE,  0x14,  0x00,  0x08,  0xFF, 	/* 44C20 */
+	0x0C,  0xA5,  0x12,  0xFF,  0x7D,  0x42,  0x09,  0x7E,  0x28,  0x42,  0x2A,  0x7E,  0x29,  0x42,  0x29,  0x7E, 	/* 44C30 */
+	0x48,  0x26,  0x09,  0xC1,  0x8E,  0x10,  0x88,  0x10,  0x8A,  0x13,  0xE9,  0x68,  0x89,  0x28,  0x88,  0x17, 	/* 44C40 */
+	0xFF,  0x11,  0x48,  0x2B,  0x6A,  0x7D,  0x4A,  0x13,  0x6A,  0x31,  0x44,  0x3B,  0x64,  0x35,  0x5D,  0x55, 	/* 44C50 */
+	0xEB,  0x17,  0x13,  0x10,  0x21,  0x8F,  0x08,  0x10,  0x08,  0xFF,  0x0A,  0x80,  0x74,  0xFE,  0x14,  0xD2, 	/* 44C60 */
+	0x08,  0xFE,  0x0C,  0xD2,  0x12,  0xFE,  0x7E,  0x90,  0x0A,  0xFF,  0x2C,  0xA8,  0x2A,  0xD7,  0x2B,  0x10, 	/* 44C70 */
+	0x49,  0x7C,  0x0A,  0x10,  0x09,  0xFF,  0x90,  0x08,  0x80,  0x08,  0xBF,  0x10,  0x84,  0x67,  0xE8,  0x15, 	/* 44C80 */
+	0x5E,  0x19,  0x52,  0x0A,  0x32,  0x15,  0x5E,  0x7D,  0x52,  0x08,  0x9E,  0x28,  0x92,  0x2D,  0x52,  0x2D, 	/* 44C90 */
+	0x5E,  0x2A,  0x14,  0x48,  0x22,  0x08,  0xC1,  0x92,  0x08,  0x00,  0x09,  0xFF,  0x0B,  0x00,  0x75,  0x7E, 	/* 44CA0 */
+	0x15,  0x52,  0x09,  0x7E,  0x0D,  0x52,  0x13,  0x7E,  0x7D,  0x10,  0x09,  0xFF,  0x2D,  0x6A,  0x2B,  0x91, 	/* 44CB0 */
+	0x2A,  0x7E,  0x2A,  0x10,  0x4D,  0xFF,  0x08,  0x00,  0x93,  0x08,  0x00,  0x09,  0xEF,  0x09,  0x29,  0x75, 	/* 44CC0 */
+	0xEF,  0x15,  0x29,  0x19,  0xEF,  0x09,  0x29,  0x15,  0xEF,  0x7E,  0xAA,  0x09,  0x11,  0x2C,  0x20,  0x2B, 	/* 44CD0 */
+	0xFF,  0x2A,  0x44,  0x28,  0xE8,  0x48,  0x3C,  0x09,  0xC2,  0x94,  0x08,  0x78,  0x08,  0x90,  0x09,  0xFE, 	/* 44CE0 */
+	0x76,  0x82,  0x14,  0xFE,  0x08,  0x88,  0x0C,  0xEE,  0x12,  0x89,  0x7F,  0xEF,  0x0A,  0x00,  0x28,  0xFE, 	/* 44CF0 */
+	0x2C,  0x92,  0x2A,  0xFE,  0x2A,  0x2A,  0x48,  0x49,  0x0B,  0x87,  0x96,  0x11,  0x28,  0x11,  0x2A,  0x12, 	/* 44D00 */
+	0xD9,  0x6A,  0x49,  0x2C,  0x88,  0x13,  0xFF,  0x11,  0x48,  0x2B,  0x6A,  0x7D,  0x4A,  0x13,  0x6A,  0x31, 	/* 44D10 */
+	0x44,  0x3B,  0x64,  0x35,  0x5D,  0x55,  0xEB,  0x17,  0x13,  0x10,  0x21,  0x9B,  0x00,  0x80,  0x1F,  0xFC, 	/* 44D20 */
+	0x00,  0x80,  0x7F,  0xFF,  0x04,  0x90,  0x3F,  0xFE,  0x09,  0x10,  0x0F,  0xFC,  0x00,  0x20,  0x5F,  0x68, 	/* 44D30 */
+	0x51,  0x12,  0x5F,  0x74,  0x51,  0x0A,  0x7F,  0xFF,  0x25,  0x2A,  0x44,  0xC9,  0x9C,  0x09,  0xE8,  0x09, 	/* 44D40 */
+	0x4F,  0x0B,  0xF0,  0x73,  0x2E,  0x15,  0xFF,  0x09,  0x55,  0x0D,  0xFF,  0x12,  0x42,  0x7D,  0x7E,  0x08, 	/* 44D50 */
+	0x42,  0x2C,  0x7E,  0x2A,  0x42,  0x2A,  0x7E,  0x2A,  0x29,  0x48,  0xC9,  0x0B,  0x07,  0xB6,  0x08,  0x00, 	/* 44D60 */
+	0x08,  0x00,  0x08,  0x00,  0x0F,  0xFC,  0x10,  0x80,  0x10,  0x80,  0x20,  0x80,  0x40,  0x80,  0x7F,  0xFF, 	/* 44D70 */
+	0x00,  0x80,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x00,  0x00,  0xB8,  0x10, 	/* 44D80 */
+	0x00,  0x10,  0xFE,  0x1F,  0x10,  0x28,  0x10,  0x28,  0x10,  0x48,  0x10,  0x7F,  0x90,  0x08,  0x10,  0x08, 	/* 44D90 */
+	0x10,  0x29,  0x10,  0x29,  0x10,  0x29,  0x10,  0x29,  0x10,  0x3F,  0x10,  0x01,  0xFF,  0x00,  0x00,  0xBA, 	/* 44DA0 */
+	0x10,  0x20,  0x10,  0x20,  0x1E,  0x20,  0x28,  0xFC,  0x28,  0x24,  0x48,  0x24,  0x7F,  0x24,  0x08,  0x24, 	/* 44DB0 */
+	0x09,  0xFF,  0x2A,  0x30,  0x2A,  0x30,  0x2A,  0x28,  0x2A,  0x48,  0x3E,  0x44,  0x00,  0x82,  0x01,  0x01, 	/* 44DC0 */
+	0x85,  0x10,  0x10,  0x10,  0x1E,  0x3E,  0x10,  0x28,  0xFF,  0x48,  0x92,  0x08,  0x9C,  0x7F,  0xF1,  0x08, 	/* 44DD0 */
+	0x8F,  0x08,  0x84,  0x2A,  0xF8,  0x2A,  0xAA,  0x2A,  0x9C,  0x2A,  0xFF,  0x3F,  0x08,  0x22,  0x08,  0x00, 	/* 44DE0 */
+	0x18,  0x8C,  0x00,  0x00,  0x3F,  0x7E,  0x21,  0x42,  0x3D,  0x7A,  0x2F,  0x5E,  0x21,  0x42,  0x3F,  0x7E, 	/* 44DF0 */
+	0x12,  0x24,  0x29,  0x42,  0x0F,  0xFC,  0x10,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x10,  0x84,  0x1F,  0xFC, 	/* 44E00 */
+	0x00,  0x00,  0x8D,  0x07,  0xF0,  0x04,  0x90,  0x07,  0xF0,  0x04,  0x90,  0x3F,  0xFE,  0x29,  0x52,  0x3F, 	/* 44E10 */
+	0x7E,  0x29,  0x52,  0x3F,  0x7E,  0x08,  0x00,  0x0F,  0xF8,  0x10,  0x80,  0x7F,  0xFF,  0x10,  0x84,  0x1F, 	/* 44E20 */
+	0xFC,  0x00,  0x00,  0x8E,  0x10,  0x00,  0x10,  0xFC,  0x1E,  0x84,  0x28,  0xFC,  0x28,  0x84,  0x49,  0xFE, 	/* 44E30 */
+	0x7E,  0x10,  0x0B,  0xFF,  0x0A,  0xDD,  0x08,  0x10,  0x2A,  0xFE,  0x2A,  0x00,  0x2B,  0xFF,  0x3E,  0x28, 	/* 44E40 */
+	0x00,  0x5C,  0x01,  0xE2,  0x90,  0x10,  0x44,  0x11,  0xFF,  0x1E,  0x44,  0x28,  0xEE,  0x28,  0xAA,  0x48, 	/* 44E50 */
+	0xEE,  0x7F,  0x24,  0x08,  0x48,  0x08,  0x7E,  0x2A,  0xC8,  0x2B,  0x7E,  0x2A,  0x48,  0x2A,  0x7E,  0x3E, 	/* 44E60 */
+	0x48,  0x00,  0x7F,  0x00,  0x00,  0x91,  0x00,  0x00,  0x3F,  0xFE,  0x22,  0x12,  0x22,  0x12,  0x22,  0x12, 	/* 44E70 */
+	0x3A,  0xD2,  0x24,  0x22,  0x26,  0x32,  0x26,  0x32,  0x25,  0x2A,  0x29,  0x4A,  0x28,  0x42,  0x30,  0x82, 	/* 44E80 */
+	0x20,  0x02,  0x20,  0x02,  0x20,  0x06,  0x94,  0x00,  0x00,  0x3F,  0xFE,  0x24,  0x22,  0x22,  0x22,  0x22, 	/* 44E90 */
+	0x42,  0x3F,  0xFE,  0x21,  0x02,  0x21,  0x02,  0x3F,  0xFA,  0x22,  0x02,  0x22,  0x02,  0x22,  0x02,  0x22, 	/* 44EA0 */
+	0x02,  0x21,  0xF2,  0x20,  0x02,  0x20,  0x06,  0x95,  0x00,  0x00,  0x7F,  0xFE,  0x42,  0x42,  0x42,  0x42, 	/* 44EB0 */
+	0x04,  0x44,  0x18,  0x3C,  0x60,  0x00,  0x00,  0x00,  0x1F,  0xF8,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF, 	/* 44EC0 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x98,  0x00,  0x00,  0x3F,  0xFE,  0x22,  0x22,  0x22, 	/* 44ED0 */
+	0x22,  0x3F,  0xFE,  0x00,  0x00,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x40,  0x01,  0xA0,  0x02,  0x90,  0x0C, 	/* 44EE0 */
+	0x8C,  0x70,  0x83,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x9F,  0x00,  0x00,  0x3F,  0xFE,  0x22,  0x22, 	/* 44EF0 */
+	0x22,  0x22,  0x3F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x0F,  0xF8, 	/* 44F00 */
+	0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0xA0,  0x00,  0x00,  0x3F,  0xFE,  0x22, 	/* 44F10 */
+	0x22,  0x22,  0x22,  0x3F,  0xFE,  0x00,  0x00,  0x1F,  0xFC,  0x10,  0x04,  0x1F,  0xFC,  0x10,  0x40,  0x10, 	/* 44F20 */
+	0x40,  0x1F,  0xFF,  0x10,  0x20,  0x11,  0x92,  0x1E,  0x0A,  0x70,  0x06,  0xA7,  0x00,  0x00,  0x3F,  0xFE, 	/* 44F30 */
+	0x22,  0x22,  0x22,  0x22,  0x3F,  0xFE,  0x00,  0x00,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10, 	/* 44F40 */
+	0x0E,  0x38,  0x0D,  0x34,  0x15,  0x52,  0x24,  0x91,  0x45,  0x10,  0x04,  0x10,  0xA8,  0x00,  0x00,  0x3F, 	/* 44F50 */
+	0xFE,  0x22,  0x22,  0x22,  0x22,  0x3F,  0xFE,  0x01,  0x00,  0x7F,  0xFF,  0x02,  0x20,  0x04,  0x90,  0x1F, 	/* 44F60 */
+	0xFC,  0x68,  0x8B,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF9,  0x00,  0x81,  0x00,  0x7F,  0xA9,  0x00,  0x00, 	/* 44F70 */
+	0x3F,  0xFE,  0x22,  0x22,  0x3F,  0xFE,  0x00,  0x80,  0x00,  0xFC,  0x00,  0x80,  0x0F,  0xF8,  0x08,  0x08, 	/* 44F80 */
+	0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0xAA,  0x00, 	/* 44F90 */
+	0x00,  0x3F,  0xFE,  0x22,  0x22,  0x22,  0x22,  0x3F,  0xFE,  0x00,  0x20,  0x02,  0x20,  0x3E,  0x3E,  0x02, 	/* 44FA0 */
+	0x20,  0x3E,  0x3E,  0x02,  0x20,  0x0E,  0x20,  0x74,  0x3F,  0x04,  0x20,  0x08,  0x20,  0x10,  0x20,  0xAB, 	/* 44FB0 */
+	0x00,  0x00,  0x3F,  0xFE,  0x22,  0x22,  0x22,  0x22,  0x3F,  0xFE,  0x02,  0x10,  0x1F,  0x90,  0x02,  0x10, 	/* 44FC0 */
+	0x02,  0x18,  0x7F,  0xD4,  0x02,  0x12,  0x1F,  0x91,  0x02,  0x10,  0x03,  0xD0,  0x7C,  0x10,  0x00,  0x10, 	/* 44FD0 */
+	0xAE,  0x00,  0x00,  0x3F,  0xFC,  0x22,  0x44,  0x3F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x27, 	/* 44FE0 */
+	0xF0,  0x24,  0x10,  0x27,  0xF0,  0x24,  0x10,  0x27,  0xF0,  0x24,  0x10,  0x27,  0xF0,  0x3F,  0xFF,  0x00, 	/* 44FF0 */
+	0x00,  0xB0,  0x00,  0x00,  0x3F,  0xFC,  0x22,  0x44,  0x22,  0x44,  0x3F,  0xFC,  0x00,  0x02,  0x3F,  0x22, 	/* 45000 */
+	0x00,  0x22,  0x7F,  0xA2,  0x00,  0x22,  0x3F,  0x22,  0x00,  0x22,  0x3F,  0x02,  0x21,  0x02,  0x3F,  0x02, 	/* 45010 */
+	0x00,  0x06,  0xB2,  0x00,  0x00,  0x1F,  0xFC,  0x12,  0x24,  0x1F,  0xFC,  0x00,  0x88,  0x1F,  0xFC,  0x00, 	/* 45020 */
+	0x90,  0x7F,  0xFF,  0x01,  0x80,  0x07,  0xF8,  0x0C,  0x08,  0x37,  0xF8,  0x04,  0x08,  0x04,  0x08,  0x07, 	/* 45030 */
+	0xF8,  0x00,  0x00,  0xB5,  0x00,  0x00,  0x3F,  0xFE,  0x22,  0x22,  0x3F,  0xFE,  0x00,  0x00,  0x0F,  0xFC, 	/* 45040 */
+	0x08,  0x80,  0x0F,  0xF0,  0x08,  0x80,  0x0F,  0xF0,  0x08,  0x80,  0x0F,  0xFE,  0x10,  0x92,  0x14,  0x4A, 	/* 45050 */
+	0x22,  0x4A,  0x42,  0x1C,  0xB7,  0x00,  0x00,  0x3F,  0xFE,  0x22,  0x22,  0x3F,  0xFE,  0x0C,  0x20,  0x13, 	/* 45060 */
+	0x26,  0x7E,  0xB8,  0x00,  0x20,  0x3F,  0x21,  0x21,  0x1F,  0x3F,  0x00,  0x21,  0x26,  0x3F,  0x38,  0x21, 	/* 45070 */
+	0x20,  0x21,  0x21,  0x23,  0x1F,  0xB8,  0x00,  0x00,  0x3F,  0xFE,  0x22,  0x42,  0x22,  0x42,  0x3F,  0xFE, 	/* 45080 */
+	0x00,  0x04,  0x3F,  0x04,  0x00,  0xFF,  0x7F,  0x04,  0x00,  0x44,  0x3F,  0x24,  0x00,  0x24,  0x3F,  0x04, 	/* 45090 */
+	0x21,  0x04,  0x3F,  0x04,  0x00,  0x0C,  0xB9,  0x00,  0x00,  0x3F,  0xFE,  0x22,  0x22,  0x22,  0x22,  0x3F, 	/* 450A0 */
+	0xFE,  0x08,  0x48,  0x08,  0x50,  0x08,  0xFF,  0x2D,  0x90,  0x2A,  0xFE,  0x28,  0x90,  0x48,  0xFE,  0x08, 	/* 450B0 */
+	0x90,  0x08,  0x90,  0x08,  0xFF,  0x08,  0x00,  0x82,  0x00,  0x00,  0x3F,  0xFE,  0x22,  0x22,  0x3F,  0xFE, 	/* 450C0 */
+	0x08,  0x00,  0x08,  0x7E,  0x72,  0x42,  0x14,  0x7E,  0x0C,  0x00,  0x12,  0x7E,  0x7D,  0x42,  0x08,  0x7E, 	/* 450D0 */
+	0x2A,  0x42,  0x29,  0x7E,  0x49,  0x42,  0x08,  0x46,  0x83,  0x00,  0x00,  0x3F,  0xFE,  0x22,  0x22,  0x3F, 	/* 450E0 */
+	0xFE,  0x04,  0x10,  0x7F,  0xFF,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x01,  0x00,  0x7F,  0xFF,  0x04, 	/* 450F0 */
+	0x90,  0x1F,  0xFC,  0x68,  0x8B,  0x08,  0xB0,  0x00,  0x80,  0x85,  0x00,  0x00,  0x3F,  0xFE,  0x22,  0x22, 	/* 45100 */
+	0x22,  0x22,  0x3F,  0xFE,  0x08,  0x24,  0x08,  0x28,  0x72,  0x7F,  0x14,  0xC8,  0x0A,  0x7E,  0x7D,  0x48, 	/* 45110 */
+	0x08,  0x7E,  0x2A,  0x48,  0x29,  0x48,  0x49,  0x7F,  0x08,  0x40,  0x86,  0x00,  0x00,  0x3F,  0xFE,  0x22, 	/* 45120 */
+	0x22,  0x3F,  0xFE,  0x08,  0x24,  0x11,  0x38,  0x7F,  0xA2,  0x11,  0x1E,  0x1F,  0x20,  0x11,  0x24,  0x1F, 	/* 45130 */
+	0x38,  0x11,  0x22,  0x13,  0x1E,  0x20,  0x04,  0x22,  0x22,  0x41,  0x11,  0x87,  0x00,  0x00,  0x3F,  0xFE, 	/* 45140 */
+	0x22,  0x22,  0x3F,  0xFE,  0x12,  0x08,  0x7F,  0x08,  0x12,  0x7E,  0x1E,  0x14,  0x08,  0x22,  0x3F,  0xFF, 	/* 45150 */
+	0x29,  0x02,  0x3F,  0x3A,  0x08,  0x2A,  0x7F,  0xBA,  0x08,  0x02,  0x08,  0x06,  0x88,  0x00,  0x00,  0x3F, 	/* 45160 */
+	0xFE,  0x22,  0x22,  0x3F,  0xFE,  0x12,  0x00,  0x7F,  0x7E,  0x12,  0x48,  0x1E,  0x7C,  0x08,  0x48,  0x3F, 	/* 45170 */
+	0x7C,  0x29,  0x48,  0x3F,  0x7E,  0x08,  0x12,  0x7F,  0xCA,  0x08,  0xAA,  0x09,  0x26,  0x8A,  0x04,  0x10, 	/* 45180 */
+	0x02,  0x10,  0x02,  0x20,  0x3F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80, 	/* 45190 */
+	0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x8C,  0x04, 	/* 451A0 */
+	0x10,  0x02,  0x10,  0x02,  0x20,  0x3F,  0xFE,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x7F, 	/* 451B0 */
+	0xFF,  0x01,  0x20,  0x01,  0x20,  0x01,  0x20,  0x02,  0x20,  0x04,  0x21,  0x18,  0x21,  0x60,  0x1F,  0x8E, 	/* 451C0 */
+	0x04,  0x10,  0x02,  0x10,  0x02,  0x20,  0x3F,  0xFF,  0x00,  0x80,  0x0F,  0xFC,  0x00,  0x80,  0x00,  0x80, 	/* 451D0 */
+	0x1F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFF,  0x01,  0x40,  0x02,  0x20,  0x0C,  0x18,  0x70,  0x07, 	/* 451E0 */
+	0x94,  0x04,  0x10,  0x02,  0x10,  0x02,  0x20,  0x3F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00, 	/* 451F0 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x10,  0x04,  0x12,  0x22,  0x21,  0x11,  0x41, 	/* 45200 */
+	0x11,  0x9A,  0x02,  0x10,  0x22,  0x10,  0x12,  0x28,  0x14,  0x28,  0x7F,  0x44,  0x08,  0xBA,  0x09,  0x01, 	/* 45210 */
+	0x3E,  0x00,  0x08,  0xFE,  0x0E,  0x22,  0x78,  0x22,  0x08,  0x22,  0x10,  0x2C,  0x10,  0x20,  0x20,  0x20, 	/* 45220 */
+	0x40,  0x20,  0x9D,  0x02,  0x02,  0x22,  0x0C,  0x12,  0x78,  0x14,  0x48,  0x7F,  0x48,  0x08,  0x48,  0x08, 	/* 45230 */
+	0x7F,  0x3E,  0x48,  0x08,  0x48,  0x0F,  0x48,  0x78,  0x48,  0x08,  0x64,  0x11,  0x85,  0x10,  0x05,  0x21, 	/* 45240 */
+	0xF3,  0x40,  0x01,  0x9E,  0x04,  0x08,  0x02,  0x10,  0x3F,  0xFE,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80, 	/* 45250 */
+	0x00,  0x80,  0x7F,  0xFF,  0x04,  0x00,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xFF,  0x10,  0x88,  0x20,  0x88, 	/* 45260 */
+	0x5F,  0xFF,  0x00,  0x00,  0xA3,  0x00,  0x00,  0x1F,  0xF8,  0x01,  0x08,  0x7F,  0xFF,  0x02,  0x08,  0x1F, 	/* 45270 */
+	0xF8,  0x07,  0xFC,  0x1C,  0x04,  0x67,  0xFC,  0x02,  0x20,  0x1F,  0xFC,  0x00,  0x80,  0x0F,  0xF8,  0x00, 	/* 45280 */
+	0x80,  0x7F,  0xFF,  0x00,  0x80,  0xA4,  0x00,  0x22,  0x3F,  0x12,  0x09,  0x14,  0x09,  0x7F,  0x7F,  0x88, 	/* 45290 */
+	0x09,  0x08,  0x09,  0x08,  0x3F,  0x3E,  0x08,  0x08,  0x10,  0x08,  0x1F,  0x08,  0x31,  0xFF,  0x31,  0x08, 	/* 452A0 */
+	0x51,  0x08,  0x1F,  0x08,  0x00,  0x08,  0xA8,  0x04,  0x10,  0x02,  0x20,  0x3F,  0xFE,  0x00,  0x80,  0x1F, 	/* 452B0 */
+	0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x10,  0x80,  0x08,  0xFE,  0x09,  0x24,  0x42,  0x28,  0x20,  0x30,  0x24, 	/* 452C0 */
+	0x50,  0x08,  0x88,  0x11,  0x04,  0x66,  0x03,  0xA9,  0x04,  0x10,  0x02,  0x20,  0x3F,  0xFE,  0x00,  0x80, 	/* 452D0 */
+	0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x03,  0x28,  0x3C,  0x24,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x12, 	/* 452E0 */
+	0x07,  0x94,  0x7C,  0x09,  0x04,  0x35,  0x0C,  0xC3,  0xAE,  0x04,  0x10,  0x02,  0x20,  0x3F,  0xFE,  0x00, 	/* 452F0 */
+	0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x12,  0x24,  0x20,  0x02,  0x1F,  0xFC,  0x00,  0x80,  0x1F, 	/* 45300 */
+	0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x03,  0x30,  0x7C,  0x0F,  0xAF,  0x02,  0x00,  0x22,  0xFC,  0x12,  0x84, 	/* 45310 */
+	0x14,  0xFC,  0x7F,  0x84,  0x08,  0x84,  0x08,  0xFC,  0x3E,  0x40,  0x08,  0x7E,  0x0F,  0x52,  0x78,  0x9A, 	/* 45320 */
+	0x09,  0xAA,  0x12,  0xC2,  0x10,  0xFA,  0x20,  0x02,  0x40,  0x0C,  0xB2,  0x02,  0x10,  0x3F,  0xFE,  0x00, 	/* 45330 */
+	0x80,  0x1F,  0xFE,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x00,  0x3E,  0x24,  0x04,  0x22,  0x7F,  0xFF,  0x15, 	/* 45340 */
+	0x20,  0x3E,  0x92,  0x48,  0x14,  0x1E,  0x09,  0x12,  0x35,  0x04,  0xC3,  0xB6,  0x04,  0x20,  0x27,  0xFF, 	/* 45350 */
+	0x15,  0x7A,  0x19,  0x4A,  0x7F,  0x7A,  0x09,  0x02,  0x09,  0xFE,  0x3E,  0x00,  0x08,  0xFC,  0x0E,  0x84, 	/* 45360 */
+	0x78,  0xFC,  0x08,  0x84,  0x10,  0xFC,  0x10,  0x00,  0x23,  0xFF,  0x40,  0x00,  0xB8,  0x00,  0x80,  0x1F, 	/* 45370 */
+	0xFF,  0x10,  0x00,  0x0F,  0xFC,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x01,  0x40,  0x3C, 	/* 45380 */
+	0x9C,  0x27,  0xF4,  0x3C,  0x94,  0x25,  0xDC,  0x3C,  0x95,  0x27,  0xF5,  0x4C,  0xA3,  0xB9,  0x02,  0x20, 	/* 45390 */
+	0x3F,  0xFE,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x11,  0x24,  0x24,  0x12,  0x02,  0x20, 	/* 453A0 */
+	0x3F,  0xFE,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x03,  0x30,  0x7C,  0x0F,  0xBD,  0x00, 	/* 453B0 */
+	0x00,  0x3F,  0x7E,  0x01,  0x02,  0x01,  0x02,  0x11,  0x22,  0x09,  0x12,  0x09,  0x12,  0x01,  0x02,  0x03, 	/* 453C0 */
+	0x06,  0x05,  0x0A,  0x19,  0x32,  0x61,  0xC2,  0x01,  0x02,  0x01,  0x02,  0x01,  0x02,  0x03,  0x06,  0x81, 	/* 453D0 */
+	0x05,  0xF0,  0x04,  0x10,  0x08,  0x88,  0x10,  0x84,  0x61,  0x63,  0x02,  0x18,  0x3F,  0xE4,  0x00,  0x00, 	/* 453E0 */
+	0x3F,  0xFC,  0x11,  0x24,  0x09,  0x14,  0x03,  0x0C,  0x0D,  0x34,  0x31,  0xC4,  0x01,  0x04,  0x03,  0x0C, 	/* 453F0 */
+	0x85,  0x08,  0x00,  0x0B,  0xFE,  0x08,  0x22,  0x7E,  0x66,  0x08,  0x66,  0x08,  0xAA,  0x7F,  0x32,  0x22, 	/* 45400 */
+	0x26,  0x22,  0x66,  0x14,  0x6A,  0x14,  0xB2,  0x09,  0x22,  0x0C,  0x22,  0x12,  0x66,  0x21,  0x80,  0x40, 	/* 45410 */
+	0x7F,  0x86,  0x00,  0x00,  0x7F,  0x7E,  0x09,  0x12,  0x73,  0x66,  0x0D,  0x1A,  0x71,  0x62,  0x01,  0x06, 	/* 45420 */
+	0x3F,  0xE0,  0x01,  0x22,  0x06,  0x22,  0x38,  0x9E,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80, 	/* 45430 */
+	0x00,  0x80,  0x8A,  0x10,  0x00,  0x11,  0xFE,  0x10,  0x22,  0x7E,  0x22,  0x04,  0x66,  0x44,  0x66,  0x24, 	/* 45440 */
+	0xAA,  0x25,  0x32,  0x24,  0x22,  0x28,  0x66,  0x08,  0x66,  0x10,  0xAA,  0x0D,  0x32,  0x70,  0x22,  0x00, 	/* 45450 */
+	0x22,  0x00,  0x66,  0x8C,  0x00,  0x00,  0x7F,  0xFE,  0x11,  0x22,  0x09,  0x12,  0x03,  0x06,  0x05,  0x0A, 	/* 45460 */
+	0x19,  0x32,  0x03,  0x86,  0x00,  0x80,  0x1F,  0xFC,  0x04,  0x10,  0x02,  0x10,  0x02,  0x20,  0x02,  0x20, 	/* 45470 */
+	0x7F,  0xFF,  0x00,  0x00,  0x92,  0x00,  0x00,  0x7F,  0xFE,  0x21,  0x42,  0x11,  0x22,  0x13,  0x26,  0x05, 	/* 45480 */
+	0x1A,  0x19,  0x62,  0x60,  0x86,  0x01,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08, 	/* 45490 */
+	0x08,  0x0F,  0xF8,  0x00,  0x00,  0x94,  0x04,  0x00,  0x27,  0xFE,  0x14,  0x22,  0x18,  0x22,  0x7F,  0x32, 	/* 454A0 */
+	0x08,  0xAA,  0x08,  0xAA,  0x3E,  0x22,  0x08,  0x22,  0x0F,  0x66,  0x78,  0x66,  0x08,  0xAA,  0x11,  0x32, 	/* 454B0 */
+	0x12,  0x22,  0x20,  0x22,  0x40,  0x66,  0x95,  0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x0C,  0x18,  0x77, 	/* 454C0 */
+	0xF7,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x7F,  0x7E,  0x09,  0x12,  0x33, 	/* 454D0 */
+	0x66,  0x0D,  0x1A,  0x31,  0x62,  0x03,  0x06,  0xA0,  0x00,  0x00,  0x7F,  0xFE,  0x11,  0x22,  0x0B,  0x16, 	/* 454E0 */
+	0x0D,  0x1A,  0x73,  0x66,  0x00,  0x80,  0x1F,  0xFC,  0x04,  0x10,  0x06,  0x30,  0x09,  0xA8,  0x10,  0xC4, 	/* 454F0 */
+	0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0xA1,  0x02,  0x20,  0x7E,  0x3F,  0x02,  0x20,  0x3E, 	/* 45500 */
+	0x3E,  0x02,  0x20,  0x7E,  0x3F,  0x04,  0x20,  0x08,  0x20,  0x7F,  0x7E,  0x03,  0x06,  0x0D,  0x1A,  0x71, 	/* 45510 */
+	0x62,  0x03,  0x06,  0x0D,  0x1A,  0x71,  0x62,  0x03,  0x06,  0xA6,  0x02,  0x10,  0x7F,  0xFF,  0x00,  0x04, 	/* 45520 */
+	0x1F,  0x24,  0x19,  0x24,  0x17,  0x24,  0x19,  0x24,  0x17,  0x24,  0x11,  0x0C,  0x00,  0x00,  0x7F,  0x7E, 	/* 45530 */
+	0x09,  0x12,  0x33,  0x66,  0x0D,  0x1A,  0x31,  0x62,  0x03,  0x06,  0xA9,  0x00,  0x00,  0x7F,  0xEE,  0x00, 	/* 45540 */
+	0x22,  0x3F,  0x22,  0x21,  0x26,  0x21,  0x66,  0x3F,  0x6A,  0x20,  0xB2,  0x3F,  0x22,  0x35,  0x66,  0x35, 	/* 45550 */
+	0x66,  0x35,  0xAA,  0x5F,  0x2A,  0x55,  0x32,  0x15,  0x22,  0x13,  0x66,  0xAB,  0x00,  0x00,  0x7F,  0xBE, 	/* 45560 */
+	0x08,  0x80,  0x4C,  0x80,  0x2A,  0x80,  0x19,  0x80,  0x6E,  0xFF,  0x19,  0x94,  0x08,  0x14,  0x3F,  0x14, 	/* 45570 */
+	0x21,  0x14,  0x3F,  0x14,  0x21,  0x14,  0x21,  0x25,  0x3F,  0x25,  0x00,  0x43,  0xB0,  0x08,  0x10,  0x08, 	/* 45580 */
+	0x10,  0x7F,  0x28,  0x08,  0x44,  0x3E,  0x82,  0x23,  0xFF,  0x22,  0x22,  0x3F,  0x32,  0x22,  0xAA,  0x22, 	/* 45590 */
+	0xAA,  0x3E,  0x22,  0x08,  0x66,  0x7F,  0xAA,  0x09,  0x32,  0x08,  0x22,  0x08,  0x66,  0xB3,  0x00,  0x00, 	/* 455A0 */
+	0x3F,  0xBC,  0x24,  0x24,  0x27,  0xA5,  0x2A,  0x43,  0x3F,  0xBC,  0x25,  0x14,  0x28,  0x88,  0x3F,  0x94, 	/* 455B0 */
+	0x00,  0x23,  0x7F,  0x7E,  0x09,  0x12,  0x33,  0x66,  0x0D,  0x1A,  0x31,  0x62,  0x03,  0x06,  0xB9,  0x08, 	/* 455C0 */
+	0x00,  0x08,  0xEE,  0x3E,  0x22,  0x08,  0x66,  0x7F,  0x66,  0x12,  0xAA,  0x3F,  0x32,  0x12,  0x66,  0x1A, 	/* 455D0 */
+	0x66,  0x67,  0xAA,  0x00,  0xB2,  0x7F,  0x22,  0x14,  0x66,  0x14,  0x01,  0x24,  0x01,  0x43,  0xFF,  0xBB, 	/* 455E0 */
+	0x02,  0x00,  0x0D,  0xFE,  0x7A,  0x22,  0x2A,  0x22,  0x1C,  0x22,  0x7F,  0x32,  0x0C,  0xAA,  0x1A,  0xAA, 	/* 455F0 */
+	0x29,  0x22,  0x7E,  0x66,  0x2A,  0xAA,  0x3F,  0x32,  0x2A,  0x22,  0x2A,  0x22,  0x3E,  0x22,  0x22,  0x66, 	/* 45600 */
+	0xBC,  0x00,  0x00,  0x7F,  0xFE,  0x11,  0x22,  0x0B,  0x16,  0x0D,  0x1A,  0x31,  0x62,  0x03,  0x06,  0x0F, 	/* 45610 */
+	0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88,  0x1F,  0xFC,  0x02,  0x20,  0x7F,  0xFF,  0x04,  0x18,  0x18, 	/* 45620 */
+	0x04,  0x80,  0x08,  0x00,  0x09,  0xFE,  0x4A,  0x22,  0x2A,  0xEE,  0x2C,  0x22,  0x09,  0xFE,  0x7E,  0x48, 	/* 45630 */
+	0x14,  0x90,  0x14,  0xFE,  0x15,  0x90,  0x15,  0xFE,  0x16,  0x90,  0x14,  0xFE,  0x24,  0x90,  0x20,  0xFF, 	/* 45640 */
+	0x40,  0x80,  0x81,  0x00,  0x80,  0x00,  0x84,  0x1F,  0xFC,  0x00,  0x88,  0x00,  0x90,  0x00,  0xA0,  0x7F, 	/* 45650 */
+	0xFF,  0x00,  0xC0,  0x00,  0x80,  0x03,  0x08,  0x0E,  0x30,  0x73,  0xC0,  0x02,  0x00,  0x02,  0x04,  0x01, 	/* 45660 */
+	0x04,  0x00,  0xFC,  0x83,  0x00,  0x80,  0x00,  0x84,  0x1F,  0xFC,  0x00,  0x88,  0x00,  0x90,  0x7F,  0xFF, 	/* 45670 */
+	0x00,  0x40,  0x00,  0x80,  0x03,  0xFC,  0x0E,  0x00,  0x72,  0x00,  0x03,  0xF8,  0x02,  0x08,  0x00,  0x08, 	/* 45680 */
+	0x00,  0x08,  0x00,  0x30,  0x84,  0x02,  0x08,  0x1F,  0xF0,  0x02,  0x20,  0x7F,  0xFF,  0x01,  0x00,  0x07, 	/* 45690 */
+	0xF8,  0x79,  0x02,  0x00,  0xFE,  0x00,  0x10,  0x1F,  0xE0,  0x01,  0x00,  0x01,  0xF8,  0x3F,  0x00,  0x01, 	/* 456A0 */
+	0xFD,  0x7F,  0x01,  0x00,  0xFF,  0x85,  0x00,  0x80,  0x00,  0x84,  0x1F,  0xF8,  0x00,  0x90,  0x00,  0xA0, 	/* 456B0 */
+	0x00,  0xC0,  0x7F,  0xFF,  0x01,  0x00,  0x03,  0xF8,  0x06,  0x08,  0x1A,  0x08,  0x63,  0xF8,  0x02,  0x08, 	/* 456C0 */
+	0x02,  0x08,  0x03,  0xF8,  0x00,  0x00,  0x86,  0x00,  0x88,  0x0F,  0xFC,  0x00,  0x90,  0x00,  0xA0,  0x7F, 	/* 456D0 */
+	0xFF,  0x03,  0x08,  0x0F,  0xF2,  0x72,  0x02,  0x01,  0xFE,  0x00,  0x00,  0x0F,  0xFC,  0x08,  0x04,  0x0F, 	/* 456E0 */
+	0xFC,  0x08,  0x04,  0x0F,  0xFC,  0x00,  0x00,  0x8B,  0x01,  0x08,  0x1F,  0xF0,  0x01,  0x20,  0x7F,  0xFF, 	/* 456F0 */
+	0x01,  0x08,  0x0F,  0xF0,  0x72,  0x04,  0x01,  0xFC,  0x3F,  0xFE,  0x02,  0x30,  0x0F,  0xE8,  0x00,  0x80, 	/* 45700 */
+	0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x8C,  0x00,  0x00,  0x7F,  0xFE,  0x01,  0x00,  0x01, 	/* 45710 */
+	0x00,  0x02,  0x00,  0x3F,  0xFC,  0x22,  0x44,  0x22,  0x44,  0x22,  0x44,  0x22,  0x44,  0x22,  0x44,  0x22, 	/* 45720 */
+	0x44,  0x22,  0x44,  0x22,  0x44,  0x22,  0x44,  0x20,  0x0C,  0x90,  0x00,  0x04,  0x7F,  0xC4,  0x04,  0x04, 	/* 45730 */
+	0x04,  0x04,  0x08,  0x7F,  0x3F,  0x84,  0x2A,  0x84,  0x2A,  0xA4,  0x2A,  0x94,  0x2A,  0x94,  0x2A,  0x84, 	/* 45740 */
+	0x2A,  0x84,  0x2A,  0x84,  0x2A,  0x84,  0x2A,  0x84,  0x21,  0x8C,  0x92,  0x00,  0x80,  0x00,  0x86,  0x3F, 	/* 45750 */
+	0xF8,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0xC0,  0x02, 	/* 45760 */
+	0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0x00,  0x80,  0x95,  0x08,  0x24,  0x08,  0x24, 	/* 45770 */
+	0x7F,  0x24,  0x08,  0xFF,  0x08,  0x24,  0x3E,  0x24,  0x08,  0x24,  0x08,  0x24,  0x7F,  0x24,  0x08,  0xFF, 	/* 45780 */
+	0x1C,  0x24,  0x1A,  0x24,  0x29,  0x24,  0x48,  0x44,  0x08,  0x44,  0x08,  0x84,  0x97,  0x08,  0x04,  0x08, 	/* 45790 */
+	0x18,  0x7F,  0xE0,  0x08,  0x20,  0x08,  0x20,  0x3E,  0x2E,  0x08,  0xF0,  0x7F,  0x20,  0x08,  0x20,  0x1C, 	/* 457A0 */
+	0x2F,  0x1B,  0xF0,  0x29,  0x20,  0x48,  0x20,  0x08,  0x22,  0x08,  0x22,  0x08,  0x1E,  0x98,  0x08,  0x00, 	/* 457B0 */
+	0x0B,  0x7E,  0x7C,  0x00,  0x08,  0x00,  0x08,  0x00,  0x3E,  0x00,  0x08,  0xFF,  0x08,  0x10,  0x7F,  0x10, 	/* 457C0 */
+	0x08,  0x10,  0x1C,  0x28,  0x1A,  0x24,  0x29,  0x24,  0x48,  0x4E,  0x09,  0xF2,  0x08,  0x02,  0x99,  0x08, 	/* 457D0 */
+	0x00,  0x0B,  0x7E,  0x7C,  0x4A,  0x08,  0x4A,  0x08,  0x4A,  0x3E,  0x4A,  0x08,  0x4A,  0x08,  0x7E,  0x7F, 	/* 457E0 */
+	0x40,  0x08,  0x40,  0x1C,  0x40,  0x1A,  0x40,  0x29,  0x41,  0x48,  0x41,  0x08,  0x3F,  0x08,  0x00,  0x9C, 	/* 457F0 */
+	0x08,  0x00,  0x0B,  0x7C,  0x7C,  0x44,  0x08,  0x44,  0x08,  0x44,  0x3E,  0x44,  0x08,  0x7C,  0x08,  0x40, 	/* 45800 */
+	0x7F,  0xC0,  0x08,  0x7E,  0x1C,  0x42,  0x1A,  0x42,  0x29,  0x42,  0x48,  0x42,  0x08,  0x7E,  0x08,  0x00, 	/* 45810 */
+	0xA1,  0x08,  0x08,  0x0F,  0xE8,  0x79,  0x28,  0x09,  0x28,  0x09,  0x3E,  0x3D,  0xEA,  0x09,  0x2A,  0x09, 	/* 45820 */
+	0x2A,  0x7F,  0xEA,  0x09,  0x2A,  0x1D,  0x2A,  0x1B,  0x32,  0x29,  0xD2,  0x4B,  0x12,  0x08,  0x22,  0x08, 	/* 45830 */
+	0x4C,  0xA8,  0x08,  0x00,  0x0B,  0xFF,  0x7C,  0x80,  0x08,  0xBE,  0x08,  0x80,  0x3E,  0xFE,  0x08,  0xA9, 	/* 45840 */
+	0x08,  0xAA,  0x7F,  0xB4,  0x08,  0xE3,  0x1C,  0x84,  0x1A,  0xFF,  0x29,  0x44,  0x49,  0x24,  0x0A,  0x04, 	/* 45850 */
+	0x08,  0x0C,  0xB3,  0x00,  0x00,  0x7F,  0xFF,  0x04,  0x10,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x04, 	/* 45860 */
+	0x10,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x04,  0x10,  0x04,  0x1F,  0x07,  0xF0,  0x78,  0x10,  0x00, 	/* 45870 */
+	0x10,  0x00,  0x10,  0xB6,  0x00,  0x00,  0x7F,  0xBE,  0x11,  0x22,  0x11,  0x24,  0x11,  0x24,  0x1F,  0x28, 	/* 45880 */
+	0x11,  0x24,  0x11,  0x22,  0x1F,  0x22,  0x11,  0x21,  0x11,  0x31,  0x11,  0xA9,  0x1F,  0x26,  0x71,  0x20, 	/* 45890 */
+	0x01,  0x20,  0x01,  0x20,  0xBB,  0x00,  0x08,  0x7F,  0x08,  0x12,  0x08,  0x12,  0x08,  0x12,  0x48,  0x1E, 	/* 458A0 */
+	0x4F,  0x12,  0x48,  0x12,  0x48,  0x1E,  0x48,  0x12,  0x48,  0x12,  0x48,  0x13,  0x48,  0x1E,  0x48,  0x62, 	/* 458B0 */
+	0x48,  0x03,  0xFF,  0x02,  0x00,  0xBD,  0x00,  0x10,  0x7F,  0x90,  0x12,  0x10,  0x12,  0xFF,  0x12,  0x91, 	/* 458C0 */
+	0x1E,  0x91,  0x12,  0x90,  0x12,  0x18,  0x1E,  0x18,  0x12,  0x18,  0x12,  0x28,  0x13,  0x28,  0x1E,  0x28, 	/* 458D0 */
+	0x72,  0x49,  0x02,  0x89,  0x03,  0x07,  0xBF,  0x00,  0x10,  0x7F,  0x10,  0x12,  0x12,  0x12,  0x52,  0x1E, 	/* 458E0 */
+	0x52,  0x12,  0x54,  0x12,  0x54,  0x12,  0x90,  0x1E,  0x98,  0x12,  0x28,  0x12,  0x28,  0x13,  0x28,  0x1E, 	/* 458F0 */
+	0x44,  0x62,  0x44,  0x02,  0x82,  0x03,  0x01,  0x86,  0x00,  0x10,  0x7F,  0x90,  0x12,  0x28,  0x12,  0x44, 	/* 45900 */
+	0x12,  0x82,  0x1F,  0x7D,  0x12,  0x00,  0x12,  0x00,  0x1E,  0xFE,  0x12,  0x22,  0x12,  0x22,  0x12,  0x22, 	/* 45910 */
+	0x1E,  0x22,  0x62,  0x2C,  0x02,  0x20,  0x02,  0x20,  0x8A,  0x00,  0x20,  0x7F,  0x20,  0x12,  0xCE,  0x12, 	/* 45920 */
+	0xAA,  0x12,  0xAA,  0x1E,  0xAA,  0x12,  0xAA,  0x12,  0xAA,  0x1E,  0xAA,  0x12,  0xAA,  0x12,  0xAA,  0x13, 	/* 45930 */
+	0xEA,  0x1E,  0x2C,  0x62,  0x48,  0x02,  0x48,  0x02,  0x88,  0x92,  0x00,  0x04,  0x7F,  0x18,  0x12,  0xF0, 	/* 45940 */
+	0x12,  0x10,  0x12,  0x10,  0x1E,  0x10,  0x13,  0xFF,  0x12,  0x10,  0x1E,  0x10,  0x12,  0x10,  0x12,  0xFE, 	/* 45950 */
+	0x12,  0x82,  0x1E,  0x82,  0x62,  0x82,  0x02,  0xFE,  0x02,  0x00,  0x96,  0x00,  0x00,  0x7F,  0xFE,  0x11, 	/* 45960 */
+	0x22,  0x1F,  0x22,  0x11,  0x22,  0x1F,  0x22,  0x11,  0x22,  0x1F,  0x3E,  0x71,  0x00,  0x01,  0x00,  0x3F, 	/* 45970 */
+	0xFE,  0x00,  0x80,  0x1F,  0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x98,  0x00,  0x10,  0x7F,  0x10, 	/* 45980 */
+	0x12,  0xFE,  0x12,  0x92,  0x1E,  0xFE,  0x12,  0x92,  0x12,  0x92,  0x12,  0xFE,  0x1E,  0x00,  0x13,  0xFF, 	/* 45990 */
+	0x12,  0x20,  0x13,  0x3C,  0x1E,  0x04,  0x62,  0x04,  0x02,  0x04,  0x02,  0x18,  0x9A,  0x00,  0x00,  0x7F, 	/* 459A0 */
+	0xFC,  0x11,  0x24,  0x1F,  0x24,  0x11,  0x18,  0x1F,  0x10,  0x11,  0xAC,  0x1F,  0x43,  0x71,  0x10,  0x00, 	/* 459B0 */
+	0x60,  0x0B,  0x82,  0x10,  0xDC,  0x62,  0xA0,  0x0C,  0x98,  0x70,  0x87,  0x00,  0x80,  0x9E,  0x00,  0x00, 	/* 459C0 */
+	0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x40,  0x02,  0x5F,  0xFA,  0x44,  0x22, 	/* 459D0 */
+	0x47,  0xE2,  0x44,  0x22,  0x47,  0xE2,  0x44,  0x22,  0x47,  0xE2,  0x5C,  0x22,  0x40,  0x26,  0x9F,  0x10, 	/* 459E0 */
+	0x00,  0x1F,  0xBE,  0x24,  0x22,  0x7F,  0xE2,  0x0A,  0x22,  0x09,  0x22,  0x11,  0x3E,  0x20,  0x00,  0x7F, 	/* 459F0 */
+	0xFF,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x1F,  0x7F,  0xF0,  0x00,  0x10,  0xA1, 	/* 45A00 */
+	0x00,  0x1C,  0x7F,  0x24,  0x12,  0x24,  0x12,  0x52,  0x12,  0x92,  0x1F,  0x19,  0x12,  0x24,  0x12,  0x2C, 	/* 45A10 */
+	0x1E,  0xF2,  0x12,  0x12,  0x12,  0x08,  0x13,  0xA8,  0x1E,  0xA2,  0x72,  0xA5,  0x03,  0x25,  0x02,  0x1C, 	/* 45A20 */
+	0xA2,  0x00,  0x10,  0x7F,  0x10,  0x12,  0xFF,  0x12,  0x81,  0x12,  0x81,  0x1E,  0x7E,  0x12,  0x10,  0x12, 	/* 45A30 */
+	0x10,  0x1E,  0x50,  0x12,  0x5E,  0x12,  0x50,  0x12,  0x50,  0x1E,  0xD0,  0x62,  0xB0,  0x03,  0x18,  0x02, 	/* 45A40 */
+	0x07,  0xA8,  0x00,  0x44,  0x7E,  0x44,  0x25,  0x99,  0x24,  0xAA,  0x3C,  0x44,  0x24,  0x44,  0x24,  0xAA, 	/* 45A50 */
+	0x25,  0xDD,  0x3C,  0x00,  0x24,  0x48,  0x24,  0x48,  0x27,  0xFF,  0x3C,  0x48,  0x64,  0x48,  0x04,  0x88, 	/* 45A60 */
+	0x05,  0x08,  0xAF,  0x00,  0x44,  0x7E,  0x44,  0x25,  0xBA,  0x24,  0xAA,  0x24,  0x44,  0x3C,  0x44,  0x24, 	/* 45A70 */
+	0xAA,  0x25,  0xFF,  0x3C,  0x00,  0x25,  0x2A,  0x25,  0x2A,  0x25,  0xEA,  0x3D,  0x2E,  0x65,  0x4A,  0x04, 	/* 45A80 */
+	0x48,  0x04,  0x88,  0xB0,  0x00,  0x08,  0x7E,  0x10,  0x24,  0xFE,  0x24,  0x92,  0x24,  0xDE,  0x3C,  0xAA, 	/* 45A90 */
+	0x24,  0xD2,  0x24,  0x9A,  0x3C,  0xA6,  0x24,  0xC2,  0x24,  0xFE,  0x26,  0x90,  0x3C,  0xAA,  0x65,  0x21, 	/* 45AA0 */
+	0x06,  0x25,  0x04,  0x1C,  0xB2,  0x04,  0x3C,  0x7F,  0xA4,  0x04,  0x25,  0x3F,  0x43,  0x00,  0x7C,  0x1F, 	/* 45AB0 */
+	0xA4,  0x15,  0x18,  0x1F,  0x24,  0x20,  0x43,  0x5F,  0xFF,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x07, 	/* 45AC0 */
+	0xFF,  0x7C,  0x10,  0x00,  0x10,  0xB3,  0x10,  0x88,  0x11,  0x54,  0x2B,  0xFE,  0x49,  0x20,  0x11,  0x3C, 	/* 45AD0 */
+	0x31,  0xA0,  0x52,  0x7F,  0x14,  0x00,  0x7F,  0xFF,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x07,  0xF0, 	/* 45AE0 */
+	0x04,  0x1F,  0x7F,  0xF0,  0x00,  0x10,  0xB4,  0x00,  0x20,  0x7F,  0x20,  0x25,  0xFE,  0x24,  0x20,  0x3C, 	/* 45AF0 */
+	0x20,  0x25,  0xFC,  0x25,  0x54,  0x25,  0x54,  0x3D,  0x54,  0x25,  0xFC,  0x24,  0x20,  0x25,  0x50,  0x3D, 	/* 45B00 */
+	0x52,  0x65,  0x45,  0x06,  0x45,  0x04,  0x3C,  0xB6,  0x00,  0x00,  0x3F,  0xFC,  0x04,  0x20,  0x07,  0xE0, 	/* 45B10 */
+	0x04,  0x20,  0x07,  0xF8,  0x3C,  0x20,  0x00,  0x20,  0x7F,  0xFF,  0x11,  0x22,  0x1F,  0x3E,  0x11,  0x22, 	/* 45B20 */
+	0x1F,  0x3E,  0x11,  0xA3,  0x7F,  0x7E,  0x01,  0x02,  0xB7,  0x00,  0x88,  0x7E,  0x8C,  0x27,  0xFA,  0x26, 	/* 45B30 */
+	0x2A,  0x25,  0x28,  0x3D,  0x48,  0x27,  0xFF,  0x24,  0x0A,  0x3D,  0xEA,  0x25,  0x2A,  0x25,  0xE4,  0x27, 	/* 45B40 */
+	0x2C,  0x3D,  0x2C,  0x65,  0xF5,  0x04,  0x13,  0x04,  0x21,  0xB9,  0x00,  0x10,  0x7E,  0x10,  0x25,  0xFF, 	/* 45B50 */
+	0x25,  0x11,  0x3D,  0xA9,  0x24,  0xA2,  0x25,  0x1D,  0x24,  0xFE,  0x3C,  0xAA,  0x24,  0xFE,  0x24,  0x00, 	/* 45B60 */
+	0x25,  0xFF,  0x3C,  0x10,  0x64,  0x10,  0x04,  0x10,  0x04,  0x30,  0xBD,  0x00,  0x10,  0x7E,  0x10,  0x13, 	/* 45B70 */
+	0xFF,  0x1E,  0x10,  0x12,  0xFE,  0x1E,  0xAA,  0x12,  0xAA,  0x7E,  0xFE,  0x02,  0x00,  0x7B,  0xFF,  0x12, 	/* 45B80 */
+	0x10,  0x3A,  0x28,  0x12,  0xAA,  0x1A,  0xA1,  0x63,  0x25,  0x02,  0x1C,  0xBE,  0x04,  0x20,  0x3F,  0xBF, 	/* 45B90 */
+	0x0A,  0x20,  0x7F,  0xFE,  0x11,  0x02,  0x1F,  0x3E,  0x11,  0x20,  0x1F,  0x3E,  0x11,  0x20,  0x13,  0x21, 	/* 45BA0 */
+	0x7F,  0xFF,  0x04,  0x08,  0x07,  0xF8,  0x04,  0x0E,  0x7F,  0xF8,  0x00,  0x08,  0xBF,  0x00,  0x80,  0x00, 	/* 45BB0 */
+	0x80,  0x1F,  0xFC,  0x00,  0x84,  0x7F,  0xFF,  0x00,  0x84,  0x00,  0x84,  0x1F,  0xFC,  0x00,  0x80,  0x1F, 	/* 45BC0 */
+	0xFC,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x84,  0x20,  0x10, 	/* 45BD0 */
+	0x22,  0x10,  0x3C,  0xFE,  0x20,  0x12,  0x23,  0xFF,  0x1E,  0x12,  0x10,  0xFE,  0x1F,  0x10,  0x24,  0x10, 	/* 45BE0 */
+	0x44,  0xFE,  0x3F,  0x10,  0x0C,  0x10,  0x0A,  0xFF,  0x11,  0x10,  0x21,  0x10,  0x40,  0x10,  0x85,  0x00, 	/* 45BF0 */
+	0x80,  0x1F,  0xFC,  0x00,  0x84,  0x7F,  0xFF,  0x00,  0x84,  0x1F,  0xFC,  0x02,  0xA0,  0x12,  0xA4,  0x1E, 	/* 45C00 */
+	0xBC,  0x10,  0x84,  0x1F,  0xFC,  0x10,  0x84,  0x1E,  0xBC,  0x12,  0xA4,  0x22,  0xA4,  0x40,  0x84,  0x86, 	/* 45C10 */
+	0x00,  0x10,  0x1F,  0x10,  0x10,  0xFE,  0x1E,  0x12,  0x11,  0xFF,  0x1E,  0x12,  0x10,  0xFE,  0x10,  0x10, 	/* 45C20 */
+	0x7F,  0x10,  0x10,  0xFE,  0x14,  0x10,  0x12,  0x10,  0x12,  0xFF,  0x1D,  0x10,  0x61,  0x10,  0x00,  0x10, 	/* 45C30 */
+	0x87,  0x00,  0x10,  0x3F,  0xDF,  0x0F,  0x24,  0x09,  0x54,  0x0F,  0x08,  0x10,  0x96,  0x2F,  0xF8,  0x00, 	/* 45C40 */
+	0x88,  0x3F,  0xFF,  0x00,  0x88,  0x0F,  0xF8,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x00, 	/* 45C50 */
+	0x80,  0x89,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x20,  0x82,  0x20,  0x82,  0x21,  0x42,  0x21,  0x22, 	/* 45C60 */
+	0x22,  0x92,  0x24,  0x92,  0x28,  0x82,  0x21,  0x42,  0x21,  0x22,  0x22,  0x12,  0x24,  0x12,  0x28,  0x02, 	/* 45C70 */
+	0x20,  0x06,  0x8B,  0x00,  0x20,  0x3E,  0x20,  0x22,  0x20,  0x22,  0x20,  0x23,  0xFE,  0x3E,  0x22,  0x22, 	/* 45C80 */
+	0x22,  0x22,  0x22,  0x22,  0x22,  0x3E,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x42,  0x22,  0x42,  0x22, 	/* 45C90 */
+	0x84,  0x47,  0x18,  0x8C,  0x00,  0x00,  0x3E,  0x78,  0x22,  0x48,  0x22,  0x48,  0x22,  0x48,  0x3E,  0x48, 	/* 45CA0 */
+	0x22,  0x48,  0x22,  0x48,  0x22,  0x48,  0x3E,  0x48,  0x22,  0x48,  0x22,  0x48,  0x22,  0x88,  0x22,  0x89, 	/* 45CB0 */
+	0x23,  0x09,  0x46,  0x07,  0x93,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFF,  0x10,  0x00,  0x10,  0x00,  0x0F, 	/* 45CC0 */
+	0xFC,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08, 	/* 45CD0 */
+	0x08,  0x08,  0x08,  0x08,  0x18,  0x96,  0x10,  0x84,  0x08,  0x84,  0x04,  0x88,  0x04,  0x90,  0x00,  0x80, 	/* 45CE0 */
+	0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08, 	/* 45CF0 */
+	0x08,  0x08,  0x08,  0x08,  0x08,  0x18,  0x98,  0x00,  0x08,  0x3E,  0x08,  0x22,  0x08,  0x22,  0x08,  0x23, 	/* 45D00 */
+	0xFF,  0x3E,  0x08,  0x22,  0x08,  0x22,  0x88,  0x22,  0x48,  0x3E,  0x48,  0x22,  0x08,  0x22,  0x08,  0x22, 	/* 45D10 */
+	0x08,  0x22,  0x08,  0x22,  0x08,  0x46,  0x18,  0x9A,  0x00,  0x10,  0x3E,  0x10,  0x22,  0x10,  0x22,  0x10, 	/* 45D20 */
+	0x22,  0x10,  0x3E,  0xFE,  0x22,  0x10,  0x22,  0x10,  0x22,  0x10,  0x3E,  0x10,  0x22,  0x10,  0x22,  0x10, 	/* 45D30 */
+	0x22,  0x10,  0x22,  0x10,  0x23,  0xFF,  0x46,  0x00,  0x9B,  0x00,  0x00,  0x3E,  0x00,  0x22,  0xFE,  0x22, 	/* 45D40 */
+	0x10,  0x22,  0x10,  0x3E,  0x10,  0x22,  0x10,  0x22,  0x10,  0x22,  0x10,  0x3E,  0x10,  0x22,  0x10,  0x22, 	/* 45D50 */
+	0x10,  0x22,  0x10,  0x22,  0x10,  0x23,  0xFF,  0x46,  0x00,  0x9D,  0x00,  0x00,  0x3E,  0xFE,  0x22,  0x10, 	/* 45D60 */
+	0x22,  0x10,  0x22,  0x10,  0x3E,  0x10,  0x22,  0x10,  0x23,  0xFF,  0x22,  0x10,  0x3E,  0x10,  0x22,  0x10, 	/* 45D70 */
+	0x22,  0x10,  0x22,  0x10,  0x22,  0x10,  0x22,  0x10,  0x46,  0x10,  0xA1,  0x00,  0x00,  0x3C,  0xF0,  0x24, 	/* 45D80 */
+	0x90,  0x24,  0x92,  0x24,  0x92,  0x3C,  0x8E,  0x25,  0x00,  0x27,  0xF8,  0x24,  0x88,  0x3C,  0x88,  0x24, 	/* 45D90 */
+	0x50,  0x24,  0x50,  0x24,  0x20,  0x24,  0x50,  0x25,  0x8C,  0x4E,  0x03,  0xA2,  0x00,  0x10,  0x3E,  0x10, 	/* 45DA0 */
+	0x22,  0x10,  0x23,  0xFF,  0x22,  0x10,  0x3E,  0x10,  0x22,  0xFC,  0x22,  0x44,  0x22,  0x44,  0x3E,  0x28, 	/* 45DB0 */
+	0x22,  0x28,  0x22,  0x10,  0x22,  0x30,  0x22,  0x48,  0x22,  0x84,  0x47,  0x03,  0xA5,  0x00,  0x00,  0x3E, 	/* 45DC0 */
+	0xFC,  0x22,  0xA4,  0x22,  0xA4,  0x22,  0xA4,  0x3E,  0xA4,  0x22,  0xA4,  0x22,  0xFC,  0x22,  0x80,  0x3E, 	/* 45DD0 */
+	0x80,  0x22,  0x80,  0x22,  0x80,  0x22,  0x82,  0x22,  0x82,  0x22,  0x7E,  0x46,  0x00,  0xA9,  0x00,  0x00, 	/* 45DE0 */
+	0x7F,  0xFF,  0x00,  0x00,  0x1F,  0xFC,  0x10,  0x04,  0x10,  0x04,  0x1F,  0xFC,  0x10,  0x00,  0x17,  0xF8, 	/* 45DF0 */
+	0x14,  0x08,  0x17,  0xF8,  0x24,  0x08,  0x27,  0xF8,  0x44,  0x08,  0x04,  0x08,  0x04,  0x18,  0xAA,  0x00, 	/* 45E00 */
+	0x10,  0x3E,  0x10,  0x22,  0x10,  0x23,  0xFF,  0x22,  0x20,  0x3E,  0x20,  0x22,  0x20,  0x22,  0x3C,  0x22, 	/* 45E10 */
+	0x24,  0x3E,  0x24,  0x22,  0x24,  0x22,  0x24,  0x22,  0x44,  0x22,  0x44,  0x22,  0x84,  0x47,  0x18,  0xAC, 	/* 45E20 */
+	0x00,  0x24,  0x3E,  0x22,  0x22,  0x22,  0x22,  0x20,  0x23,  0xFF,  0x3E,  0x20,  0x22,  0x20,  0x22,  0x30, 	/* 45E30 */
+	0x22,  0x30,  0x3E,  0x50,  0x22,  0x50,  0x22,  0x50,  0x22,  0x91,  0x22,  0x91,  0x23,  0x0F,  0x46,  0x00, 	/* 45E40 */
+	0xAD,  0x00,  0xE0,  0x3C,  0x20,  0x24,  0x20,  0x25,  0xFE,  0x25,  0x22,  0x3D,  0x22,  0x25,  0x22,  0x25, 	/* 45E50 */
+	0x52,  0x25,  0x52,  0x3D,  0x4A,  0x25,  0x86,  0x25,  0x02,  0x25,  0x02,  0x25,  0x02,  0x25,  0x02,  0x4D, 	/* 45E60 */
+	0x06,  0xAF,  0x00,  0x80,  0x08,  0x80,  0x08,  0xFC,  0x08,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF0, 	/* 45E70 */
+	0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10, 	/* 45E80 */
+	0x08,  0x30,  0xB1,  0x00,  0x20,  0x3E,  0x20,  0x22,  0x20,  0x23,  0xFF,  0x22,  0x20,  0x3E,  0x28,  0x22, 	/* 45E90 */
+	0x28,  0x22,  0x48,  0x22,  0x48,  0x3E,  0x48,  0x22,  0x90,  0x22,  0x94,  0x23,  0x12,  0x22,  0x26,  0x22, 	/* 45EA0 */
+	0xF9,  0x46,  0x01,  0xB2,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0x20,  0x04,  0x18,  0x0F,  0xE4, 	/* 45EB0 */
+	0x70,  0x02,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08, 	/* 45EC0 */
+	0x08,  0x08,  0x08,  0x18,  0xB4,  0x00,  0x08,  0x0F,  0x30,  0x00,  0xC0,  0x07,  0x30,  0x3A,  0x08,  0x7F, 	/* 45ED0 */
+	0xFE,  0x02,  0x00,  0x04,  0x00,  0x07,  0xF8,  0x0C,  0x08,  0x17,  0xF8,  0x24,  0x08,  0x47,  0xF8,  0x04, 	/* 45EE0 */
+	0x08,  0x04,  0x08,  0x04,  0x18,  0xBA,  0x00,  0x20,  0x3C,  0x20,  0x24,  0x20,  0x27,  0xFF,  0x24,  0x20, 	/* 45EF0 */
+	0x3C,  0x20,  0x25,  0xFE,  0x25,  0x22,  0x25,  0x22,  0x3D,  0x22,  0x25,  0x22,  0x25,  0x22,  0x25,  0x2C, 	/* 45F00 */
+	0x24,  0x20,  0x24,  0x20,  0x4C,  0x20,  0x83,  0x00,  0x00,  0x3F,  0xFC,  0x21,  0x04,  0x21,  0x04,  0x3F, 	/* 45F10 */
+	0xFC,  0x21,  0x04,  0x3F,  0xFC,  0x00,  0x00,  0x1F,  0xF8,  0x10,  0x08,  0x1F,  0xF8,  0x10,  0x08,  0x1F, 	/* 45F20 */
+	0xF8,  0x10,  0x08,  0x10,  0x08,  0x10,  0x18,  0x84,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x20,  0x82, 	/* 45F30 */
+	0x3F,  0xFE,  0x20,  0x82,  0x3F,  0xFE,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08, 	/* 45F40 */
+	0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x08,  0x18,  0x86,  0x00,  0x00,  0x3E,  0x7C,  0x22,  0x44,  0x22, 	/* 45F50 */
+	0x44,  0x22,  0x44,  0x3E,  0x44,  0x22,  0x7C,  0x22,  0x44,  0x22,  0x44,  0x3E,  0x44,  0x22,  0x44,  0x22, 	/* 45F60 */
+	0x7C,  0x22,  0x00,  0x22,  0x00,  0x23,  0xFF,  0x46,  0x00,  0x8C,  0x02,  0x40,  0x02,  0x46,  0x7E,  0x78, 	/* 45F70 */
+	0x02,  0x40,  0x02,  0x41,  0x0E,  0x41,  0x72,  0x3F,  0x02,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0, 	/* 45F80 */
+	0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10,  0x08,  0x30,  0x8E,  0x00,  0x20,  0x3E,  0x20,  0x22, 	/* 45F90 */
+	0x20,  0x22,  0x48,  0x22,  0x44,  0x3E,  0x8E,  0x23,  0xF2,  0x22,  0x01,  0x22,  0x01,  0x3E,  0xFC,  0x22, 	/* 45FA0 */
+	0x84,  0x22,  0x84,  0x22,  0x84,  0x22,  0x84,  0x22,  0xFC,  0x46,  0x00,  0x96,  0x00,  0x20,  0x3C,  0xA8, 	/* 45FB0 */
+	0x24,  0xA4,  0x25,  0x24,  0x24,  0x20,  0x3D,  0xFE,  0x24,  0x20,  0x24,  0x20,  0x24,  0x20,  0x3F,  0xFF, 	/* 45FC0 */
+	0x24,  0x20,  0x24,  0x20,  0x24,  0x20,  0x24,  0x20,  0x24,  0x20,  0x4C,  0x20,  0x99,  0x00,  0x40,  0x3E, 	/* 45FD0 */
+	0x40,  0x22,  0x40,  0x22,  0x7F,  0x22,  0x90,  0x3E,  0x90,  0x23,  0x10,  0x22,  0x1E,  0x22,  0x10,  0x3E, 	/* 45FE0 */
+	0x10,  0x22,  0x10,  0x22,  0x1E,  0x22,  0x10,  0x22,  0x10,  0x22,  0x10,  0x46,  0x10,  0x9A,  0x00,  0x00, 	/* 45FF0 */
+	0x3D,  0xFE,  0x24,  0x10,  0x24,  0x10,  0x24,  0x20,  0x3C,  0x20,  0x24,  0x68,  0x24,  0xA4,  0x25,  0x22, 	/* 46000 */
+	0x3E,  0x21,  0x24,  0x20,  0x24,  0x20,  0x24,  0x20,  0x24,  0x00,  0x27,  0xFF,  0x4C,  0x00,  0x9B,  0x00, 	/* 46010 */
+	0x00,  0x3E,  0xFE,  0x22,  0x92,  0x22,  0x92,  0x22,  0x92,  0x3E,  0xFE,  0x22,  0x92,  0x22,  0x92,  0x22, 	/* 46020 */
+	0x92,  0x3E,  0xFE,  0x22,  0x10,  0x22,  0x10,  0x22,  0x10,  0x22,  0x10,  0x22,  0x10,  0x46,  0x10,  0x9D, 	/* 46030 */
+	0x00,  0x02,  0x3E,  0x0C,  0x22,  0x78,  0x22,  0x48,  0x22,  0x48,  0x3E,  0x48,  0x22,  0x7F,  0x22,  0x48, 	/* 46040 */
+	0x22,  0x48,  0x3E,  0x48,  0x22,  0x44,  0x22,  0x75,  0x23,  0xC5,  0x22,  0x03,  0x23,  0xF3,  0x46,  0x01, 	/* 46050 */
+	0x9E,  0x00,  0x40,  0x3E,  0x40,  0x22,  0x7E,  0x22,  0x42,  0x22,  0x42,  0x3E,  0xF2,  0x22,  0x92,  0x23, 	/* 46060 */
+	0x12,  0x22,  0x12,  0x3E,  0xF2,  0x22,  0x8C,  0x22,  0x80,  0x22,  0x80,  0x22,  0x81,  0x22,  0x41,  0x46, 	/* 46070 */
+	0x3F,  0xA1,  0x04,  0x00,  0x04,  0x3E,  0x04,  0x22,  0x7F,  0xE2,  0x04,  0x22,  0x04,  0x3E,  0x04,  0x22, 	/* 46080 */
+	0x04,  0x22,  0x1F,  0x22,  0x11,  0x3E,  0x11,  0x22,  0x11,  0x22,  0x11,  0x22,  0x1F,  0x42,  0x00,  0x42, 	/* 46090 */
+	0x00,  0x86,  0xA4,  0x10,  0x84,  0x10,  0x84,  0x17,  0x24,  0x11,  0x44,  0x10,  0x84,  0x11,  0x34,  0x1F, 	/* 460A0 */
+	0xEC,  0x10,  0x04,  0x13,  0xE4,  0x12,  0x24,  0x13,  0xE4,  0x12,  0x24,  0x13,  0xE4,  0x22,  0x25,  0x22, 	/* 460B0 */
+	0x25,  0x42,  0x63,  0xA5,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x82,  0x08,  0xF4,  0x08,  0x80,  0x16,  0x80, 	/* 460C0 */
+	0x21,  0xFF,  0x40,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08, 	/* 460D0 */
+	0x08,  0x08,  0x08,  0x18,  0xAF,  0x00,  0x20,  0x3C,  0x20,  0x27,  0xFF,  0x24,  0x50,  0x24,  0x88,  0x3D, 	/* 460E0 */
+	0x04,  0x26,  0xFA,  0x24,  0x01,  0x27,  0xFC,  0x3C,  0x40,  0x24,  0x40,  0x24,  0xFC,  0x24,  0x84,  0x24, 	/* 460F0 */
+	0x04,  0x24,  0x04,  0x4C,  0x18,  0xB1,  0x00,  0x20,  0x3C,  0x20,  0x25,  0x24,  0x24,  0xA4,  0x24,  0xA4, 	/* 46100 */
+	0x3C,  0xA8,  0x24,  0x20,  0x27,  0xFF,  0x24,  0x50,  0x3C,  0x50,  0x24,  0x50,  0x24,  0x50,  0x24,  0x90, 	/* 46110 */
+	0x24,  0x92,  0x25,  0x0A,  0x4E,  0x06,  0xB4,  0x00,  0x00,  0x3D,  0xFE,  0x25,  0x02,  0x25,  0x02,  0x25, 	/* 46120 */
+	0xFE,  0x3D,  0x02,  0x25,  0x02,  0x25,  0x7A,  0x25,  0x4A,  0x3D,  0x4A,  0x25,  0x4A,  0x25,  0x7A,  0x25, 	/* 46130 */
+	0x02,  0x25,  0x02,  0x25,  0x02,  0x4D,  0x06,  0xB8,  0x00,  0x80,  0x3C,  0x80,  0x24,  0x80,  0x24,  0xFE, 	/* 46140 */
+	0x25,  0x12,  0x3D,  0x92,  0x27,  0x6A,  0x25,  0x2A,  0x25,  0x5A,  0x3D,  0x5A,  0x25,  0x8A,  0x25,  0x0A, 	/* 46150 */
+	0x25,  0xFA,  0x24,  0x02,  0x24,  0x04,  0x4C,  0x18,  0xBC,  0x00,  0x84,  0x3C,  0x44,  0x24,  0x48,  0x24, 	/* 46160 */
+	0x00,  0x25,  0xFE,  0x3C,  0x48,  0x24,  0x48,  0x24,  0x48,  0x27,  0xFF,  0x3C,  0x48,  0x24,  0x48,  0x24, 	/* 46170 */
+	0x48,  0x24,  0x88,  0x24,  0x88,  0x25,  0x08,  0x4E,  0x08,  0xBD,  0x08,  0x20,  0x08,  0x20,  0x12,  0x26, 	/* 46180 */
+	0x11,  0x38,  0x7E,  0xA0,  0x00,  0xA1,  0x3F,  0x21,  0x21,  0x1F,  0x21,  0x20,  0x3F,  0x20,  0x21,  0x26, 	/* 46190 */
+	0x21,  0x38,  0x3F,  0x20,  0x21,  0x21,  0x21,  0x21,  0x23,  0x1F,  0x82,  0x00,  0x80,  0x3E,  0x84,  0x22, 	/* 461A0 */
+	0x98,  0x22,  0xE0,  0x22,  0x82,  0x3E,  0x82,  0x22,  0x7E,  0x22,  0x00,  0x22,  0xFC,  0x3E,  0x84,  0x22, 	/* 461B0 */
+	0x84,  0x22,  0xFC,  0x22,  0x84,  0x22,  0x84,  0x22,  0xFC,  0x46,  0x00,  0x85,  0x00,  0x80,  0x0F,  0xF0, 	/* 461C0 */
+	0x03,  0x10,  0x1C,  0x60,  0x08,  0x10,  0x7F,  0xFE,  0x11,  0x22,  0x66,  0xCC,  0x0F,  0xF8,  0x08,  0x08, 	/* 461D0 */
+	0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x08,  0x18,  0x86,  0x00,  0x40,  0x3C, 	/* 461E0 */
+	0x78,  0x24,  0x90,  0x25,  0x20,  0x27,  0xFF,  0x3D,  0x00,  0x25,  0x00,  0x25,  0x7C,  0x25,  0x44,  0x3D, 	/* 461F0 */
+	0x44,  0x25,  0x44,  0x25,  0x58,  0x25,  0x42,  0x26,  0x42,  0x24,  0x42,  0x4C,  0x3E,  0x87,  0x00,  0x40, 	/* 46200 */
+	0x3C,  0x40,  0x25,  0xFC,  0x24,  0x44,  0x24,  0x44,  0x3C,  0x44,  0x24,  0x98,  0x25,  0x00,  0x25,  0x08, 	/* 46210 */
+	0x3F,  0xFE,  0x25,  0x4A,  0x25,  0x4A,  0x25,  0x4A,  0x25,  0x52,  0x26,  0x62,  0x4C,  0xCC,  0x88,  0x00, 	/* 46220 */
+	0x04,  0x3C,  0x18,  0x24,  0xE2,  0x24,  0x84,  0x24,  0xB8,  0x3C,  0xA2,  0x24,  0xA2,  0x24,  0xB4,  0x24, 	/* 46230 */
+	0xB4,  0x3C,  0xB8,  0x24,  0xA8,  0x24,  0xA8,  0x25,  0x24,  0x25,  0x24,  0x26,  0x22,  0x4C,  0x21,  0x89, 	/* 46240 */
+	0x00,  0x20,  0x3C,  0x10,  0x24,  0x08,  0x24,  0x00,  0x24,  0xF0,  0x3C,  0x11,  0x24,  0x19,  0x25,  0xDA, 	/* 46250 */
+	0x24,  0x5A,  0x3C,  0x54,  0x24,  0x94,  0x24,  0x92,  0x25,  0x12,  0x26,  0x11,  0x24,  0x10,  0x4C,  0x30, 	/* 46260 */
+	0x8A,  0x00,  0x80,  0x00,  0x80,  0x3D,  0x5E,  0x01,  0x40,  0x3A,  0x2E,  0x04,  0x10,  0x1F,  0xFC,  0x64, 	/* 46270 */
+	0x13,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x04,  0x10,  0x04, 	/* 46280 */
+	0x30,  0x9A,  0x00,  0x80,  0x3C,  0x9E,  0x24,  0x92,  0x27,  0xF2,  0x24,  0x92,  0x3C,  0x92,  0x24,  0x92, 	/* 46290 */
+	0x27,  0xF2,  0x24,  0x92,  0x3C,  0x92,  0x24,  0xD2,  0x25,  0x52,  0x25,  0x7C,  0x27,  0xB0,  0x24,  0x30, 	/* 462A0 */
+	0x4C,  0x10,  0x9B,  0x00,  0x00,  0x3D,  0xFE,  0x24,  0x00,  0x25,  0x24,  0x25,  0x24,  0x3E,  0x48,  0x26, 	/* 462B0 */
+	0x48,  0x25,  0x24,  0x25,  0x24,  0x3C,  0x00,  0x25,  0xFE,  0x24,  0x20,  0x24,  0x20,  0x24,  0x20,  0x27, 	/* 462C0 */
+	0xFF,  0x4C,  0x00,  0xA3,  0x00,  0x00,  0x1F,  0xFE,  0x10,  0x00,  0x17,  0xFC,  0x10,  0x00,  0x1F,  0xFE, 	/* 462D0 */
+	0x22,  0x24,  0x23,  0x98,  0x5C,  0x07,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8, 	/* 462E0 */
+	0x08,  0x08,  0x08,  0x18,  0xA9,  0x04,  0x80,  0x04,  0x80,  0x04,  0xFF,  0x09,  0x88,  0x09,  0x50,  0x16, 	/* 462F0 */
+	0x30,  0x14,  0xCC,  0x37,  0x03,  0x54,  0xFC,  0x14,  0x84,  0x14,  0xFC,  0x14,  0x84,  0x14,  0xFC,  0x14, 	/* 46300 */
+	0x84,  0x10,  0x84,  0x10,  0x8C,  0xAF,  0x00,  0x24,  0x3C,  0x22,  0x27,  0xFF,  0x24,  0x20,  0x24,  0x20, 	/* 46310 */
+	0x3D,  0xFE,  0x25,  0x22,  0x25,  0x22,  0x25,  0xFE,  0x3D,  0x22,  0x25,  0x22,  0x25,  0xFE,  0x25,  0x22, 	/* 46320 */
+	0x25,  0x22,  0x25,  0x22,  0x4D,  0x26,  0xB1,  0x00,  0x44,  0x1E,  0x24,  0x12,  0x28,  0x12,  0x7E,  0x12, 	/* 46330 */
+	0x42,  0x1E,  0x42,  0x12,  0x42,  0x12,  0x42,  0x12,  0x7E,  0x1E,  0x28,  0x12,  0x28,  0x12,  0x28,  0x12, 	/* 46340 */
+	0x48,  0x22,  0x49,  0x22,  0x89,  0x47,  0x07,  0xB3,  0x00,  0x22,  0x3D,  0x12,  0x24,  0x92,  0x24,  0x94, 	/* 46350 */
+	0x24,  0x84,  0x3C,  0x08,  0x24,  0x86,  0x24,  0xCA,  0x24,  0xAA,  0x3C,  0x92,  0x24,  0x9A,  0x24,  0xAA, 	/* 46360 */
+	0x24,  0xA6,  0x24,  0xC2,  0x24,  0xFE,  0x4C,  0x00,  0xB9,  0x00,  0x00,  0x3C,  0xFE,  0x24,  0x80,  0x24, 	/* 46370 */
+	0xFC,  0x24,  0x80,  0x3C,  0xFC,  0x24,  0x80,  0x24,  0x80,  0x27,  0xFF,  0x3C,  0xA2,  0x24,  0x94,  0x24, 	/* 46380 */
+	0x98,  0x24,  0x88,  0x24,  0xA4,  0x24,  0xC2,  0x4F,  0x01,  0xBE,  0x00,  0x20,  0x3C,  0x40,  0x25,  0xFC, 	/* 46390 */
+	0x25,  0x24,  0x25,  0x24,  0x3D,  0xFC,  0x25,  0x24,  0x25,  0x24,  0x25,  0xFC,  0x3C,  0x50,  0x24,  0x90, 	/* 463A0 */
+	0x27,  0xFF,  0x24,  0x10,  0x24,  0x10,  0x24,  0x10,  0x4C,  0x10,  0x86,  0x00,  0x50,  0x3C,  0x50,  0x24, 	/* 463B0 */
+	0x50,  0x25,  0xFC,  0x25,  0x54,  0x3D,  0x54,  0x25,  0x54,  0x25,  0xFC,  0x25,  0x54,  0x3D,  0x54,  0x25, 	/* 463C0 */
+	0x54,  0x27,  0xFF,  0x24,  0x00,  0x24,  0x58,  0x25,  0x84,  0x4E,  0x02,  0x8B,  0x00,  0x20,  0x3C,  0x20, 	/* 463D0 */
+	0x27,  0xFF,  0x24,  0x90,  0x24,  0x90,  0x3C,  0x9E,  0x25,  0x12,  0x25,  0x32,  0x27,  0x2A,  0x3D,  0x64, 	/* 463E0 */
+	0x25,  0x94,  0x25,  0x08,  0x25,  0x18,  0x25,  0x24,  0x25,  0x42,  0x4D,  0x81,  0x8E,  0x00,  0x00,  0x7F, 	/* 463F0 */
+	0xFC,  0x48,  0x44,  0x7E,  0x24,  0x42,  0x28,  0x7E,  0x18,  0x48,  0x64,  0x7F,  0x83,  0x40,  0x00,  0x0F, 	/* 46400 */
+	0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x30,  0x90,  0x00,  0x80, 	/* 46410 */
+	0x00,  0x80,  0x1F,  0xFF,  0x11,  0x08,  0x12,  0xFF,  0x16,  0x88,  0x1A,  0x48,  0x12,  0x18,  0x10,  0x40, 	/* 46420 */
+	0x17,  0xFC,  0x14,  0xA4,  0x15,  0x54,  0x24,  0x44,  0x24,  0xA4,  0x45,  0x14,  0x04,  0x0C,  0x91,  0x00, 	/* 46430 */
+	0x10,  0x3C,  0x10,  0x25,  0xFF,  0x25,  0x20,  0x25,  0x24,  0x3D,  0x24,  0x25,  0x7F,  0x25,  0x44,  0x25, 	/* 46440 */
+	0xE4,  0x3D,  0x54,  0x25,  0x54,  0x25,  0x44,  0x25,  0x44,  0x25,  0x44,  0x26,  0x44,  0x4C,  0x4C,  0x93, 	/* 46450 */
+	0x00,  0x28,  0x3C,  0x28,  0x24,  0x28,  0x25,  0xEF,  0x24,  0x28,  0x3C,  0x28,  0x24,  0x28,  0x25,  0xEF, 	/* 46460 */
+	0x24,  0x28,  0x3C,  0x28,  0x24,  0xE8,  0x27,  0x2F,  0x24,  0x48,  0x24,  0x48,  0x24,  0x88,  0x4D,  0x08, 	/* 46470 */
+	0x94,  0x00,  0x20,  0x3C,  0x20,  0x27,  0xFE,  0x26,  0x52,  0x26,  0x52,  0x3C,  0x50,  0x24,  0x9E,  0x25, 	/* 46480 */
+	0x00,  0x26,  0x00,  0x3D,  0xFC,  0x24,  0x20,  0x24,  0x20,  0x24,  0x20,  0x24,  0x20,  0x27,  0xFF,  0x4C, 	/* 46490 */
+	0x00,  0x95,  0x00,  0x10,  0x3C,  0x10,  0x25,  0xFF,  0x25,  0x01,  0x25,  0x41,  0x3C,  0x4E,  0x24,  0xFA, 	/* 464A0 */
+	0x24,  0x9A,  0x24,  0x9A,  0x3D,  0x2A,  0x26,  0xAA,  0x24,  0x4C,  0x24,  0x48,  0x24,  0x89,  0x25,  0x09, 	/* 464B0 */
+	0x4E,  0x07,  0x9F,  0x00,  0x20,  0x3C,  0x20,  0x27,  0xFF,  0x26,  0x01,  0x26,  0x01,  0x3D,  0xFE,  0x24, 	/* 464C0 */
+	0x20,  0x24,  0x4C,  0x25,  0xFA,  0x3C,  0x20,  0x24,  0x20,  0x25,  0xFE,  0x24,  0x20,  0x24,  0x20,  0x27, 	/* 464D0 */
+	0xFF,  0x4C,  0x00,  0xA5,  0x00,  0x00,  0x3C,  0xFC,  0x24,  0x84,  0x24,  0xFC,  0x24,  0x84,  0x3C,  0x84, 	/* 464E0 */
+	0x24,  0xFC,  0x24,  0x10,  0x24,  0x90,  0x3C,  0xFE,  0x25,  0x10,  0x26,  0xFE,  0x24,  0x10,  0x24,  0x10, 	/* 464F0 */
+	0x27,  0xFF,  0x4C,  0x00,  0xA6,  0x00,  0x92,  0x3C,  0x92,  0x27,  0x6C,  0x25,  0x24,  0x24,  0x92,  0x3C, 	/* 46500 */
+	0x92,  0x24,  0x20,  0x25,  0xFE,  0x25,  0x0A,  0x3D,  0xCA,  0x25,  0x32,  0x25,  0x12,  0x25,  0x2A,  0x25, 	/* 46510 */
+	0x42,  0x25,  0xFE,  0x4C,  0x00,  0xAB,  0x00,  0x04,  0x3C,  0x18,  0x25,  0xE0,  0x24,  0x20,  0x27,  0xFF, 	/* 46520 */
+	0x3C,  0x20,  0x25,  0xFC,  0x25,  0x24,  0x25,  0xFC,  0x3D,  0x24,  0x25,  0xFC,  0x24,  0x20,  0x25,  0xFC, 	/* 46530 */
+	0x24,  0x20,  0x27,  0xFF,  0x4C,  0x00,  0xAE,  0x00,  0x00,  0x3C,  0xFE,  0x24,  0x92,  0x24,  0x92,  0x24, 	/* 46540 */
+	0xFE,  0x3C,  0x92,  0x24,  0x92,  0x24,  0x92,  0x24,  0xFE,  0x3C,  0x00,  0x25,  0x50,  0x25,  0x48,  0x25, 	/* 46550 */
+	0x4A,  0x26,  0x41,  0x24,  0x45,  0x4C,  0x3C,  0xB0,  0x00,  0x00,  0x3F,  0xFE,  0x24,  0x50,  0x24,  0x50, 	/* 46560 */
+	0x25,  0xFC,  0x3D,  0x54,  0x25,  0x54,  0x25,  0xFC,  0x24,  0x20,  0x3F,  0xFF,  0x24,  0x48,  0x24,  0x88, 	/* 46570 */
+	0x25,  0xD0,  0x24,  0x30,  0x24,  0x48,  0x4D,  0x84,  0xB1,  0x00,  0x10,  0x38,  0x10,  0x2F,  0xFE,  0x28, 	/* 46580 */
+	0x92,  0x29,  0x7F,  0x39,  0x12,  0x2A,  0x12,  0x2B,  0xFE,  0x28,  0x90,  0x3A,  0xFE,  0x2A,  0x90,  0x29, 	/* 46590 */
+	0xFF,  0x29,  0x10,  0x2A,  0x90,  0x2C,  0x60,  0x58,  0x1F,  0xB4,  0x00,  0x20,  0x3C,  0x60,  0x25,  0xAC, 	/* 465A0 */
+	0x25,  0x24,  0x25,  0x24,  0x3D,  0xAC,  0x25,  0x24,  0x25,  0x24,  0x25,  0xFC,  0x3C,  0x20,  0x24,  0x50, 	/* 465B0 */
+	0x24,  0x50,  0x24,  0x88,  0x24,  0x84,  0x25,  0x02,  0x4E,  0x01,  0xB8,  0x00,  0x00,  0x3C,  0xFC,  0x24, 	/* 465C0 */
+	0x84,  0x24,  0xFC,  0x24,  0x84,  0x3C,  0x84,  0x24,  0xFC,  0x24,  0x00,  0x27,  0xFF,  0x3C,  0x80,  0x25, 	/* 465D0 */
+	0xFE,  0x26,  0x52,  0x24,  0x92,  0x25,  0x22,  0x24,  0x42,  0x4C,  0x8C,  0xB9,  0x00,  0x40,  0x3E,  0x40, 	/* 465E0 */
+	0x22,  0x7F,  0x22,  0x80,  0x22,  0xFC,  0x3F,  0x44,  0x22,  0x7C,  0x22,  0x44,  0x22,  0x7C,  0x3E,  0x20, 	/* 465F0 */
+	0x22,  0x7C,  0x22,  0xC4,  0x23,  0x28,  0x22,  0x18,  0x22,  0x64,  0x47,  0x83,  0xBA,  0x00,  0x10,  0x3C, 	/* 46600 */
+	0x20,  0x24,  0xFC,  0x24,  0x84,  0x24,  0xFC,  0x3C,  0x84,  0x24,  0x84,  0x24,  0xFC,  0x24,  0x22,  0x3C, 	/* 46610 */
+	0x22,  0x27,  0xF4,  0x24,  0xA8,  0x25,  0x24,  0x26,  0x22,  0x24,  0x21,  0x4C,  0x60,  0xBF,  0x00,  0x00, 	/* 46620 */
+	0x3C,  0x3E,  0x25,  0x22,  0x24,  0xA2,  0x24,  0xBE,  0x3C,  0x22,  0x24,  0x22,  0x27,  0xBE,  0x24,  0xA9, 	/* 46630 */
+	0x3C,  0xAA,  0x24,  0xA4,  0x24,  0xA4,  0x25,  0xB2,  0x25,  0x61,  0x26,  0x30,  0x4C,  0x0F,  0x80,  0x00, 	/* 46640 */
+	0x20,  0x3C,  0x20,  0x25,  0xFE,  0x24,  0x84,  0x24,  0x48,  0x3F,  0xFF,  0x26,  0x01,  0x26,  0x21,  0x24, 	/* 46650 */
+	0x20,  0x3F,  0xFF,  0x24,  0x40,  0x24,  0x7C,  0x24,  0x44,  0x24,  0x84,  0x25,  0x04,  0x4E,  0x18,  0x82, 	/* 46660 */
+	0x08,  0x20,  0x7F,  0x3F,  0x10,  0x40,  0x1E,  0xBE,  0x13,  0x29,  0x12,  0x26,  0x22,  0x34,  0x4C,  0xE2, 	/* 46670 */
+	0x00,  0x01,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x18, 	/* 46680 */
+	0x83,  0x00,  0x00,  0x3C,  0xFC,  0x24,  0xA4,  0x24,  0xA4,  0x24,  0xB4,  0x3C,  0xAC,  0x24,  0xC4,  0x24, 	/* 46690 */
+	0xFC,  0x24,  0x00,  0x3D,  0xFE,  0x25,  0x52,  0x25,  0x52,  0x25,  0x52,  0x25,  0x52,  0x27,  0xFF,  0x4C, 	/* 466A0 */
+	0x00,  0x88,  0x00,  0x00,  0x3F,  0xFF,  0x24,  0x00,  0x24,  0xFC,  0x24,  0x84,  0x3C,  0xFC,  0x24,  0x00, 	/* 466B0 */
+	0x25,  0xFE,  0x25,  0x52,  0x3D,  0x52,  0x25,  0x9E,  0x25,  0xFA,  0x25,  0x22,  0x25,  0x22,  0x25,  0x22, 	/* 466C0 */
+	0x4D,  0x06,  0x8A,  0x00,  0x24,  0x3C,  0x22,  0x27,  0xFF,  0x24,  0x20,  0x25,  0xFC,  0x3D,  0x24,  0x25, 	/* 466D0 */
+	0xFC,  0x25,  0x24,  0x25,  0xFC,  0x3D,  0x24,  0x24,  0x08,  0x27,  0xFF,  0x24,  0x88,  0x24,  0x48,  0x24, 	/* 466E0 */
+	0x08,  0x4C,  0x18,  0x8F,  0x00,  0x80,  0x7F,  0xFE,  0x08,  0x10,  0x0F,  0xF0,  0x00,  0x00,  0x7F,  0xFE, 	/* 466F0 */
+	0x48,  0x12,  0x4F,  0xF2,  0x00,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0, 	/* 46700 */
+	0x08,  0x10,  0x08,  0x30,  0x93,  0x00,  0x80,  0x3C,  0xFE,  0x25,  0x00,  0x25,  0xFC,  0x26,  0x84,  0x3C, 	/* 46710 */
+	0xFC,  0x24,  0x84,  0x24,  0xFC,  0x24,  0x00,  0x3F,  0xFF,  0x24,  0x40,  0x24,  0xFE,  0x27,  0x4A,  0x24, 	/* 46720 */
+	0x92,  0x25,  0x22,  0x4C,  0x4C,  0x95,  0x00,  0x00,  0x3B,  0xFE,  0x2A,  0x22,  0x2A,  0x2A,  0x2B,  0xFE, 	/* 46730 */
+	0x3A,  0x22,  0x2B,  0xEA,  0x2B,  0x6A,  0x2B,  0x52,  0x3B,  0xD2,  0x2A,  0x76,  0x2B,  0xAE,  0x2A,  0x46, 	/* 46740 */
+	0x2A,  0x82,  0x4B,  0xFE,  0x58,  0x00,  0x9A,  0x00,  0x80,  0x00,  0xFC,  0x00,  0x80,  0x1F,  0xFF,  0x11, 	/* 46750 */
+	0x1A,  0x1F,  0xE0,  0x10,  0x82,  0x17,  0xFE,  0x14,  0x44,  0x17,  0xFC,  0x12,  0x08,  0x13,  0xF8,  0x22, 	/* 46760 */
+	0x08,  0x23,  0xF8,  0x42,  0x08,  0x02,  0x18,  0x9C,  0x00,  0x48,  0x3C,  0x48,  0x27,  0xFF,  0x24,  0x48, 	/* 46770 */
+	0x24,  0x48,  0x3C,  0xFC,  0x24,  0x84,  0x24,  0xFC,  0x24,  0x84,  0x3C,  0xFC,  0x24,  0x20,  0x27,  0xFF, 	/* 46780 */
+	0x24,  0x20,  0x24,  0x50,  0x25,  0x8C,  0x4E,  0x03,  0x9D,  0x00,  0x20,  0x3C,  0x20,  0x27,  0xFF,  0x24, 	/* 46790 */
+	0x70,  0x24,  0xAC,  0x3F,  0x23,  0x24,  0x50,  0x24,  0x8C,  0x27,  0x23,  0x3D,  0x24,  0x24,  0xA8,  0x24, 	/* 467A0 */
+	0xF0,  0x25,  0xAC,  0x26,  0x23,  0x24,  0x20,  0x4C,  0x60,  0xA0,  0x00,  0x00,  0x3F,  0xDE,  0x24,  0xC6, 	/* 467B0 */
+	0x27,  0x5A,  0x24,  0xC6,  0x3F,  0x5A,  0x24,  0x62,  0x24,  0x50,  0x24,  0x8C,  0x3F,  0x23,  0x24,  0x48, 	/* 467C0 */
+	0x25,  0x92,  0x24,  0x64,  0x25,  0x88,  0x24,  0x30,  0x4D,  0xC0,  0xA3,  0x00,  0x10,  0x3C,  0x10,  0x25, 	/* 467D0 */
+	0xFF,  0x25,  0x29,  0x24,  0x4A,  0x3D,  0x86,  0x25,  0xFF,  0x24,  0x28,  0x24,  0x46,  0x3D,  0xFD,  0x24, 	/* 467E0 */
+	0x10,  0x24,  0xFE,  0x24,  0x10,  0x24,  0x10,  0x27,  0xFF,  0x4C,  0x00,  0xA4,  0x00,  0x00,  0x3C,  0xFE, 	/* 467F0 */
+	0x24,  0x10,  0x25,  0xFF,  0x25,  0x11,  0x3D,  0xDD,  0x25,  0x11,  0x24,  0xDC,  0x24,  0x00,  0x3C,  0xFC, 	/* 46800 */
+	0x24,  0x04,  0x27,  0xFF,  0x24,  0x04,  0x24,  0x04,  0x24,  0xFC,  0x4C,  0x00,  0xA8,  0x00,  0x84,  0x3C, 	/* 46810 */
+	0x84,  0x27,  0xE4,  0x24,  0x88,  0x24,  0x88,  0x3F,  0xF2,  0x24,  0x02,  0x25,  0xE4,  0x25,  0x24,  0x3D, 	/* 46820 */
+	0xE9,  0x26,  0x31,  0x25,  0x22,  0x25,  0x42,  0x24,  0xE4,  0x27,  0x08,  0x4C,  0x30,  0xA9,  0x00,  0x0C, 	/* 46830 */
+	0x3C,  0x0A,  0x24,  0x08,  0x27,  0xFF,  0x24,  0x08,  0x3D,  0xE8,  0x24,  0x08,  0x27,  0xF8,  0x25,  0x28, 	/* 46840 */
+	0x3D,  0xE8,  0x25,  0x24,  0x25,  0xE4,  0x25,  0x25,  0x25,  0xE5,  0x24,  0xA3,  0x4F,  0x11,  0xB0,  0x00, 	/* 46850 */
+	0x0C,  0x3D,  0xF0,  0x25,  0x24,  0x24,  0xA8,  0x27,  0xFF,  0x3C,  0x70,  0x24,  0xA8,  0x25,  0x24,  0x27, 	/* 46860 */
+	0xFE,  0x3D,  0x25,  0x25,  0x24,  0x25,  0xFC,  0x25,  0x24,  0x25,  0x24,  0x25,  0xFC,  0x4C,  0x00,  0xB3, 	/* 46870 */
+	0x01,  0x02,  0x3C,  0x84,  0x27,  0xFE,  0x24,  0x20,  0x25,  0xFC,  0x3C,  0x20,  0x27,  0xFF,  0x25,  0x24, 	/* 46880 */
+	0x24,  0xA8,  0x3F,  0xFF,  0x24,  0x00,  0x25,  0xFC,  0x25,  0x04,  0x25,  0x04,  0x25,  0xFC,  0x4C,  0x00, 	/* 46890 */
+	0xB5,  0x00,  0x88,  0x3C,  0x88,  0x27,  0xFF,  0x24,  0x88,  0x24,  0x20,  0x3F,  0xFE,  0x24,  0x84,  0x24, 	/* 468A0 */
+	0x84,  0x25,  0x4C,  0x3E,  0x52,  0x24,  0x20,  0x27,  0xFF,  0x24,  0x20,  0x24,  0x20,  0x24,  0x20,  0x4C, 	/* 468B0 */
+	0x20,  0xB8,  0x00,  0x10,  0x3D,  0x7F,  0x24,  0x90,  0x24,  0xBE,  0x26,  0x48,  0x3D,  0x3F,  0x25,  0x00, 	/* 468C0 */
+	0x24,  0x3E,  0x27,  0xA2,  0x3C,  0xBE,  0x24,  0xA2,  0x24,  0xBE,  0x24,  0xA2,  0x25,  0x66,  0x26,  0x20, 	/* 468D0 */
+	0x4C,  0x1F,  0xBA,  0x00,  0x40,  0x1F,  0xFF,  0x11,  0x48,  0x12,  0xFE,  0x17,  0x90,  0x1A,  0xFE,  0x12, 	/* 468E0 */
+	0x90,  0x12,  0xFF,  0x10,  0x00,  0x13,  0xFC,  0x12,  0x04,  0x13,  0xFC,  0x22,  0x04,  0x23,  0xFC,  0x42, 	/* 468F0 */
+	0x04,  0x02,  0x0C,  0xBD,  0x00,  0x20,  0x3C,  0x7C,  0x25,  0x88,  0x27,  0xFF,  0x25,  0x29,  0x3D,  0xC7, 	/* 46900 */
+	0x25,  0x7C,  0x25,  0x00,  0x25,  0xFF,  0x3D,  0x00,  0x25,  0x7E,  0x25,  0x00,  0x25,  0x7E,  0x25,  0x42, 	/* 46910 */
+	0x26,  0x7E,  0x4C,  0x00,  0xBE,  0x00,  0x20,  0x3C,  0x50,  0x24,  0x88,  0x25,  0x74,  0x26,  0x03,  0x3D, 	/* 46920 */
+	0xFE,  0x25,  0xA6,  0x25,  0x6A,  0x25,  0xFE,  0x3C,  0x00,  0x24,  0xFC,  0x24,  0x84,  0x24,  0xFC,  0x24, 	/* 46930 */
+	0x84,  0x24,  0xFC,  0x4C,  0x00,  0xBF,  0x00,  0x50,  0x3D,  0xFE,  0x25,  0x52,  0x25,  0xFE,  0x25,  0x52, 	/* 46940 */
+	0x3D,  0xFE,  0x24,  0x00,  0x25,  0xFE,  0x25,  0x00,  0x3D,  0x7E,  0x25,  0x00,  0x25,  0xFF,  0x25,  0x52, 	/* 46950 */
+	0x25,  0x4C,  0x26,  0x64,  0x4D,  0x83,  0x80,  0x00,  0x00,  0x3F,  0x3C,  0x21,  0x24,  0x3F,  0x25,  0x2A, 	/* 46960 */
+	0x43,  0x3F,  0xBC,  0x2A,  0x24,  0x5F,  0x98,  0x11,  0x24,  0x2F,  0xFB,  0x08,  0x08,  0x0F,  0xF8,  0x08, 	/* 46970 */
+	0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x18,  0x82,  0x00,  0x10,  0x1F,  0xFE,  0x11,  0x44,  0x1F,  0x28, 	/* 46980 */
+	0x10,  0xFF,  0x1F,  0x10,  0x29,  0x7E,  0x2F,  0x10,  0x40,  0x10,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8, 	/* 46990 */
+	0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x18,  0x86,  0x00,  0x20,  0x3C,  0x20,  0x27,  0xFE,  0x24, 	/* 469A0 */
+	0x84,  0x24,  0x48,  0x3F,  0xFF,  0x24,  0x00,  0x24,  0xFC,  0x24,  0x84,  0x3C,  0xFC,  0x24,  0x84,  0x24, 	/* 469B0 */
+	0xFC,  0x25,  0x20,  0x25,  0x56,  0x26,  0x45,  0x4C,  0x3C,  0x88,  0x00,  0x48,  0x3F,  0xFF,  0x24,  0x48, 	/* 469C0 */
+	0x24,  0xFC,  0x24,  0x84,  0x3C,  0xFC,  0x24,  0x84,  0x24,  0xFC,  0x24,  0x40,  0x3C,  0xFE,  0x25,  0x92, 	/* 469D0 */
+	0x26,  0x9A,  0x24,  0xA6,  0x24,  0xFA,  0x24,  0x02,  0x4C,  0x0C,  0x89,  0x00,  0x20,  0x3C,  0x20,  0x24, 	/* 469E0 */
+	0x50,  0x24,  0x88,  0x25,  0x04,  0x3E,  0xFA,  0x24,  0x01,  0x27,  0xDE,  0x26,  0x52,  0x3E,  0x52,  0x27, 	/* 469F0 */
+	0xDE,  0x24,  0x84,  0x24,  0x84,  0x24,  0xC6,  0x25,  0x29,  0x4E,  0x10,  0x8D,  0x00,  0x20,  0x3C,  0x20, 	/* 46A00 */
+	0x27,  0xFF,  0x24,  0x51,  0x27,  0xAE,  0x3D,  0xAA,  0x26,  0xAA,  0x25,  0xAD,  0x24,  0x00,  0x3C,  0x82, 	/* 46A10 */
+	0x24,  0xFE,  0x24,  0x82,  0x24,  0xFE,  0x24,  0x82,  0x24,  0x82,  0x4D,  0x02,  0x91,  0x00,  0x00,  0x3D, 	/* 46A20 */
+	0xFE,  0x24,  0x10,  0x25,  0xFF,  0x25,  0x11,  0x3D,  0xDD,  0x25,  0x11,  0x24,  0xDC,  0x24,  0x00,  0x3F, 	/* 46A30 */
+	0xFF,  0x24,  0x20,  0x24,  0xFE,  0x24,  0xAA,  0x24,  0xAA,  0x24,  0xAA,  0x4C,  0x86,  0x93,  0x00,  0x88, 	/* 46A40 */
+	0x3B,  0xFF,  0x28,  0x88,  0x28,  0x8A,  0x28,  0x09,  0x3B,  0xFF,  0x2A,  0x08,  0x2A,  0xFA,  0x3A,  0xAA, 	/* 46A50 */
+	0x2A,  0xFA,  0x2A,  0x94,  0x2A,  0xF4,  0x2A,  0xA5,  0x2A,  0xFB,  0x2C,  0x13,  0x58,  0x21,  0x98,  0x00, 	/* 46A60 */
+	0x92,  0x3B,  0x24,  0x28,  0x92,  0x2B,  0xFC,  0x2A,  0x54,  0x3A,  0x24,  0x2A,  0xD4,  0x2B,  0xFC,  0x28, 	/* 46A70 */
+	0x00,  0x3B,  0x34,  0x2A,  0xAC,  0x2B,  0x34,  0x2A,  0xAC,  0x2A,  0x25,  0x2B,  0xB5,  0x5E,  0x43,  0x99, 	/* 46A80 */
+	0x00,  0x48,  0x3C,  0x48,  0x27,  0xFF,  0x24,  0x48,  0x24,  0x78,  0x3C,  0x84,  0x27,  0xF5,  0x24,  0xD6, 	/* 46A90 */
+	0x24,  0xD4,  0x3C,  0xD4,  0x25,  0xF5,  0x26,  0x83,  0x24,  0x00,  0x25,  0x52,  0x25,  0x49,  0x4E,  0x49, 	/* 46AA0 */
+	0x9A,  0x00,  0x10,  0x3C,  0x1E,  0x24,  0x10,  0x25,  0xFF,  0x25,  0x39,  0x3D,  0xE2,  0x25,  0x7E,  0x25, 	/* 46AB0 */
+	0x54,  0x25,  0x7C,  0x3D,  0x54,  0x25,  0x7C,  0x25,  0x00,  0x25,  0xFE,  0x26,  0xAA,  0x25,  0xFF,  0x4C, 	/* 46AC0 */
+	0x00,  0x9F,  0x00,  0x48,  0x3B,  0xFF,  0x28,  0x48,  0x28,  0x4A,  0x2A,  0x09,  0x3A,  0xFF,  0x2A,  0x88, 	/* 46AD0 */
+	0x2B,  0xF8,  0x28,  0xA8,  0x3B,  0xF4,  0x2A,  0x94,  0x2A,  0xF5,  0x2D,  0xA5,  0x29,  0xFB,  0x4A,  0x0B, 	/* 46AE0 */
+	0x5C,  0x31,  0xA0,  0x10,  0x04,  0x13,  0xC4,  0x68,  0x1A,  0x17,  0xE4,  0x28,  0x0A,  0x7F,  0xDF,  0x12, 	/* 46AF0 */
+	0x44,  0x5B,  0xD5,  0x54,  0x15,  0x10,  0x84,  0x1F,  0xFC,  0x11,  0x44,  0x16,  0xB4,  0x11,  0x44,  0x16, 	/* 46B00 */
+	0x34,  0x10,  0x0C,  0xA3,  0x00,  0x00,  0x3F,  0xFE,  0x20,  0x80,  0x20,  0x80,  0x20,  0x80,  0x3F,  0xF8, 	/* 46B10 */
+	0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x3F,  0xF8,  0x20,  0x80,  0x20,  0x80,  0x20,  0x80,  0x20,  0x80, 	/* 46B20 */
+	0x3F,  0xFE,  0x00,  0x00,  0xA5,  0x00,  0x10,  0x3F,  0x90,  0x24,  0x10,  0x24,  0x10,  0x24,  0x10,  0x3F, 	/* 46B30 */
+	0x10,  0x21,  0x10,  0x21,  0x28,  0x21,  0x28,  0x3F,  0x28,  0x24,  0x28,  0x24,  0x44,  0x24,  0x44,  0x3F, 	/* 46B40 */
+	0x84,  0x01,  0x02,  0x02,  0x01,  0xA7,  0x00,  0x14,  0x00,  0x12,  0x20,  0x12,  0x2F,  0xFF,  0x28,  0x10, 	/* 46B50 */
+	0x3B,  0xF2,  0x2A,  0x92,  0x0A,  0x92,  0x7B,  0xEC,  0x2A,  0x2C,  0x2B,  0xE8,  0x2A,  0x89,  0x52,  0x95, 	/* 46B60 */
+	0x13,  0xF5,  0x20,  0x23,  0x40,  0x41,  0xA8,  0x00,  0x40,  0x7E,  0x40,  0x48,  0xFE,  0x48,  0x80,  0x49, 	/* 46B70 */
+	0xF8,  0x7E,  0x88,  0x42,  0x88,  0x42,  0xF8,  0x7E,  0x00,  0x48,  0x00,  0x4B,  0xDE,  0x4A,  0x52,  0x4A, 	/* 46B80 */
+	0x52,  0x7E,  0x52,  0x03,  0xDE,  0x00,  0x00,  0xAA,  0x01,  0x00,  0x01,  0x00,  0x02,  0x00,  0x1F,  0xFC, 	/* 46B90 */
+	0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x1F,  0xFC,  0x10,  0x04,  0x10,  0x04,  0x1F,  0xFC,  0x10,  0x04, 	/* 46BA0 */
+	0x10,  0x04,  0x10,  0x04,  0x1F,  0xFC,  0x00,  0x00,  0xAD,  0x00,  0x80,  0x01,  0x00,  0x0F,  0xF8,  0x08, 	/* 46BB0 */
+	0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x80,  0x7F, 	/* 46BC0 */
+	0xFF,  0x01,  0x40,  0x02,  0x20,  0x0C,  0x18,  0x70,  0x07,  0xB3,  0x00,  0x00,  0x7F,  0xFF,  0x01,  0x20, 	/* 46BD0 */
+	0x01,  0x10,  0x02,  0x08,  0x04,  0x78,  0x1F,  0x84,  0x00,  0x04,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC, 	/* 46BE0 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0xB4,  0x00,  0x40,  0x7F,  0x40,  0x08, 	/* 46BF0 */
+	0x40,  0x08,  0x7F,  0x14,  0x44,  0x12,  0x84,  0x26,  0xA4,  0x79,  0x24,  0x09,  0x28,  0x08,  0x18,  0x3E, 	/* 46C00 */
+	0x10,  0x08,  0x18,  0x0B,  0x28,  0x0C,  0x44,  0x70,  0x82,  0x03,  0x01,  0xBA,  0x00,  0x80,  0x3F,  0xFE, 	/* 46C10 */
+	0x00,  0x80,  0x1F,  0xFC,  0x07,  0xF0,  0x04,  0x10,  0x3F,  0xFE,  0x20,  0x02,  0x3F,  0xFA,  0x02,  0x20, 	/* 46C20 */
+	0x0F,  0xD0,  0x00,  0x88,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0xBB,  0x00,  0x10,  0x7F, 	/* 46C30 */
+	0x10,  0x08,  0xFF,  0x08,  0x10,  0x14,  0xFE,  0x12,  0x28,  0x7D,  0xFF,  0x08,  0x24,  0x08,  0x4A,  0x3E, 	/* 46C40 */
+	0xF1,  0x09,  0x10,  0x08,  0xFF,  0x0E,  0x38,  0x18,  0x54,  0x60,  0x92,  0x00,  0x10,  0xBC,  0x00,  0x80, 	/* 46C50 */
+	0x03,  0x00,  0x1C,  0x7C,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x1E,  0x7C, 	/* 46C60 */
+	0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x1F,  0xFC,  0x00,  0x00,  0xBE,  0x02, 	/* 46C70 */
+	0x80,  0x02,  0x80,  0x1C,  0xBC,  0x10,  0x84,  0x10,  0x84,  0x1E,  0xBC,  0x10,  0x84,  0x10,  0x84,  0x10, 	/* 46C80 */
+	0x84,  0x1E,  0xBC,  0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x04,  0x10,  0x18,  0x0C,  0x60,  0x03,  0x81, 	/* 46C90 */
+	0x01,  0x00,  0x0E,  0x3C,  0x08,  0x04,  0x08,  0x04,  0x0F,  0x3C,  0x08,  0x04,  0x08,  0x04,  0x0F,  0xFC, 	/* 46CA0 */
+	0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x02,  0x10,  0x02,  0x10,  0x04,  0x10,  0x18,  0x10, 	/* 46CB0 */
+	0x82,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80,  0x1F,  0xFC,  0x01,  0x40,  0x7F,  0xFF,  0x02, 	/* 46CC0 */
+	0x20,  0x04,  0x90,  0x19,  0x0C,  0x6E,  0x7B,  0x08,  0x08,  0x0F,  0x38,  0x08,  0x08,  0x0F,  0xF8,  0x00, 	/* 46CD0 */
+	0x00,  0x85,  0x01,  0x00,  0x1E,  0x3C,  0x10,  0x04,  0x1F,  0x3C,  0x10,  0x04,  0x1F,  0xFC,  0x00,  0x00, 	/* 46CE0 */
+	0x1F,  0xFC,  0x1F,  0xFC,  0x10,  0x84,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFE,  0x01,  0x02,  0x06,  0x02, 	/* 46CF0 */
+	0x38,  0x0C,  0x87,  0x01,  0x00,  0x05,  0x00,  0x05,  0xDC,  0x19,  0x04,  0x11,  0x04,  0x1D,  0xDC,  0x10, 	/* 46D00 */
+	0x44,  0x10,  0x44,  0x1D,  0x5C,  0x11,  0x44,  0x11,  0x44,  0x11,  0x44,  0x7F,  0xFF,  0x04,  0x30,  0x18, 	/* 46D10 */
+	0x0C,  0x60,  0x02,  0x88,  0x04,  0x00,  0x08,  0x00,  0x37,  0xFE,  0x24,  0x12,  0x27,  0xF2,  0x3C,  0x1E, 	/* 46D20 */
+	0x25,  0xD2,  0x25,  0x52,  0x3D,  0x5E,  0x25,  0xD2,  0x25,  0x52,  0x24,  0x12,  0x7F,  0xFF,  0x04,  0x30, 	/* 46D30 */
+	0x18,  0x0C,  0x60,  0x02,  0x89,  0x02,  0x80,  0x1C,  0xDC,  0x10,  0x84,  0x1C,  0xDC,  0x10,  0x44,  0x1D, 	/* 46D40 */
+	0x5C,  0x11,  0x44,  0x7F,  0xFF,  0x08,  0x88,  0x10,  0x84,  0x27,  0xF2,  0x40,  0x81,  0x00,  0x80,  0x3F, 	/* 46D50 */
+	0xFE,  0x00,  0x80,  0x00,  0x80,  0x8A,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x08,  0x20,  0x1F,  0xFC, 	/* 46D60 */
+	0x68,  0x40,  0x0F,  0xF0,  0x08,  0x40,  0x0F,  0xFC,  0x01,  0x00,  0x1E,  0x3C,  0x10,  0x04,  0x1F,  0x3C, 	/* 46D70 */
+	0x10,  0x04,  0x1F,  0xFC,  0x00,  0x00,  0x8C,  0x00,  0x18,  0x00,  0xE0,  0x1F,  0x80,  0x00,  0x80,  0x00, 	/* 46D80 */
+	0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x0F,  0xF8,  0x08,  0x08,  0x08, 	/* 46D90 */
+	0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x8D,  0x00,  0x80,  0x00,  0x80,  0x01,  0x40,  0x02,  0x20, 	/* 46DA0 */
+	0x04,  0x10,  0x1F,  0xFC,  0x60,  0x83,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x0F,  0xF8, 	/* 46DB0 */
+	0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x8E,  0x00,  0x80,  0x00,  0x80,  0x01,  0x40,  0x02, 	/* 46DC0 */
+	0x20,  0x04,  0x90,  0x18,  0x8C,  0x6F,  0xFB,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x0F, 	/* 46DD0 */
+	0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x90,  0x02,  0x02,  0x04,  0x0C,  0x78,  0xF0, 	/* 46DE0 */
+	0x08,  0x90,  0x08,  0x90,  0x08,  0x90,  0x7F,  0x90,  0x08,  0xFF,  0x08,  0x90,  0x3E,  0x88,  0x22,  0x88, 	/* 46DF0 */
+	0x22,  0x88,  0x22,  0x85,  0x3E,  0x85,  0x00,  0xE3,  0x01,  0x81,  0x92,  0x08,  0x00,  0x08,  0xFC,  0x14, 	/* 46E00 */
+	0x04,  0x12,  0x48,  0x21,  0x30,  0x7E,  0x10,  0x09,  0xFF,  0x08,  0x12,  0x7F,  0x14,  0x08,  0x18,  0x08, 	/* 46E10 */
+	0x10,  0x3E,  0x10,  0x22,  0x10,  0x22,  0x10,  0x3E,  0x10,  0x00,  0x30,  0x96,  0x08,  0x14,  0x08,  0x12, 	/* 46E20 */
+	0x15,  0xFF,  0x22,  0x10,  0x7F,  0x10,  0x08,  0xFE,  0x08,  0x92,  0x7F,  0x92,  0x08,  0xFE,  0x08,  0x92, 	/* 46E30 */
+	0x3E,  0x92,  0x22,  0xFE,  0x22,  0x92,  0x22,  0x92,  0x3E,  0x92,  0x00,  0x96,  0x97,  0x08,  0x14,  0x08, 	/* 46E40 */
+	0x12,  0x15,  0xFF,  0x12,  0x10,  0x29,  0x10,  0x48,  0xFE,  0x3E,  0x92,  0x08,  0x92,  0x08,  0xFE,  0x7F, 	/* 46E50 */
+	0x92,  0x00,  0x92,  0x3E,  0xFE,  0x22,  0x92,  0x22,  0x92,  0x3E,  0x92,  0x00,  0x96,  0x98,  0x08,  0x10, 	/* 46E60 */
+	0x08,  0x10,  0x15,  0xFF,  0x13,  0x01,  0x21,  0x01,  0x5E,  0x7C,  0x08,  0x44,  0x08,  0x44,  0x7F,  0x7C, 	/* 46E70 */
+	0x08,  0x40,  0x3E,  0x40,  0x22,  0x7E,  0x22,  0x42,  0x22,  0x42,  0x3E,  0x7E,  0x00,  0x00,  0x9B,  0x08, 	/* 46E80 */
+	0x04,  0x08,  0x04,  0x0F,  0x04,  0x09,  0x04,  0x11,  0x7F,  0x11,  0x44,  0x2A,  0x44,  0x46,  0x44,  0x02, 	/* 46E90 */
+	0x44,  0x04,  0x44,  0x05,  0xFF,  0x08,  0x04,  0x08,  0x04,  0x10,  0x04,  0x20,  0x04,  0x40,  0x04,  0x9C, 	/* 46EA0 */
+	0x00,  0x10,  0x00,  0xE4,  0x7F,  0x04,  0x11,  0x08,  0x08,  0x90,  0x7F,  0xFE,  0x44,  0x02,  0x44,  0x0A, 	/* 46EB0 */
+	0x0F,  0xFE,  0x09,  0x48,  0x11,  0x48,  0x6A,  0x48,  0x07,  0xFF,  0x04,  0x08,  0x18,  0x08,  0x60,  0x08, 	/* 46EC0 */
+	0x9E,  0x08,  0x00,  0x08,  0x00,  0x1F,  0xFE,  0x19,  0x48,  0x29,  0x48,  0x7F,  0xFF,  0x09,  0x48,  0x09, 	/* 46ED0 */
+	0x48,  0x7F,  0xFF,  0x08,  0x08,  0x0F,  0xFE,  0x11,  0x48,  0x6A,  0x48,  0x05,  0xFF,  0x18,  0x08,  0x60, 	/* 46EE0 */
+	0x08,  0x9F,  0x00,  0x40,  0x00,  0x80,  0x07,  0xF8,  0x04,  0x08,  0x05,  0x08,  0x04,  0x88,  0x04,  0x88, 	/* 46EF0 */
+	0x04,  0x08,  0x7F,  0xFF,  0x04,  0x08,  0x05,  0x08,  0x04,  0x88,  0x08,  0x88,  0x08,  0x88,  0x10,  0x08, 	/* 46F00 */
+	0x20,  0x18,  0xA9,  0x04,  0x38,  0x08,  0x08,  0x1E,  0x48,  0x12,  0x48,  0x12,  0x44,  0x1A,  0x84,  0x16, 	/* 46F10 */
+	0xA2,  0x17,  0x21,  0x1A,  0x20,  0x72,  0x20,  0x1A,  0x48,  0x16,  0x48,  0x16,  0x44,  0x22,  0x9C,  0x23, 	/* 46F20 */
+	0xE2,  0x46,  0x02,  0xAA,  0x02,  0x10,  0x04,  0x10,  0x1F,  0x10,  0x11,  0xFF,  0x19,  0x00,  0x15,  0x3C, 	/* 46F30 */
+	0x15,  0x24,  0x13,  0xA4,  0x1D,  0x24,  0x71,  0x24,  0x19,  0x24,  0x15,  0x24,  0x15,  0x24,  0x21,  0x45, 	/* 46F40 */
+	0x21,  0x45,  0x43,  0x83,  0xAB,  0x04,  0x20,  0x08,  0x20,  0x1E,  0x20,  0x13,  0xFF,  0x12,  0x20,  0x1A, 	/* 46F50 */
+	0x20,  0x16,  0x20,  0x17,  0x3C,  0x1A,  0x24,  0x72,  0x24,  0x1A,  0x44,  0x16,  0x44,  0x16,  0x44,  0x22, 	/* 46F60 */
+	0x84,  0x23,  0x04,  0x46,  0x18,  0xAC,  0x04,  0x00,  0x08,  0x78,  0x1F,  0x48,  0x11,  0x48,  0x19,  0x4A, 	/* 46F70 */
+	0x15,  0x4A,  0x15,  0x86,  0x13,  0xFC,  0x1D,  0x44,  0x71,  0x44,  0x19,  0x28,  0x15,  0x28,  0x15,  0x10, 	/* 46F80 */
+	0x21,  0x28,  0x21,  0x44,  0x43,  0x83,  0xAE,  0x04,  0x00,  0x08,  0xFF,  0x1E,  0x00,  0x12,  0x00,  0x12, 	/* 46F90 */
+	0x7E,  0x1A,  0x42,  0x16,  0x42,  0x17,  0x42,  0x1A,  0x7E,  0x72,  0x40,  0x1A,  0x40,  0x16,  0x40,  0x16, 	/* 46FA0 */
+	0x40,  0x22,  0x80,  0x22,  0x80,  0x47,  0x00,  0xB3,  0x04,  0x10,  0x08,  0x10,  0x1E,  0x10,  0x12,  0x10, 	/* 46FB0 */
+	0x12,  0xFE,  0x1A,  0x92,  0x16,  0x92,  0x16,  0x92,  0x1A,  0x92,  0x72,  0xFE,  0x1A,  0x92,  0x16,  0x92, 	/* 46FC0 */
+	0x16,  0x92,  0x22,  0x92,  0x22,  0xFE,  0x46,  0x00,  0xB5,  0x04,  0x10,  0x08,  0x10,  0x1F,  0x10,  0x11, 	/* 46FD0 */
+	0xFF,  0x19,  0xA1,  0x15,  0xA1,  0x15,  0x20,  0x13,  0xA4,  0x1D,  0x24,  0x71,  0x28,  0x19,  0x30,  0x15, 	/* 46FE0 */
+	0x20,  0x15,  0x21,  0x21,  0x21,  0x21,  0x11,  0x43,  0x0F,  0xB6,  0x04,  0x10,  0x08,  0x10,  0x1F,  0x20, 	/* 46FF0 */
+	0x11,  0x7E,  0x19,  0x42,  0x15,  0x42,  0x15,  0x42,  0x13,  0xC2,  0x1D,  0x7E,  0x71,  0x42,  0x19,  0x42, 	/* 47000 */
+	0x15,  0x42,  0x15,  0x42,  0x21,  0x42,  0x21,  0x7E,  0x43,  0x00,  0xB7,  0x04,  0x10,  0x08,  0x10,  0x1F, 	/* 47010 */
+	0x10,  0x11,  0xFF,  0x19,  0x08,  0x15,  0x08,  0x15,  0x10,  0x7F,  0x74,  0x11,  0x14,  0x19,  0x08,  0x15, 	/* 47020 */
+	0x08,  0x15,  0x14,  0x15,  0x12,  0x21,  0x2E,  0x21,  0xF1,  0x43,  0x01,  0xB8,  0x04,  0x00,  0x09,  0xFF, 	/* 47030 */
+	0x1E,  0x04,  0x12,  0x04,  0x12,  0xF4,  0x1A,  0x94,  0x16,  0x94,  0x17,  0x94,  0x1A,  0x94,  0x72,  0x94, 	/* 47040 */
+	0x1A,  0xF4,  0x16,  0x04,  0x16,  0x04,  0x22,  0x04,  0x22,  0x04,  0x46,  0x0C,  0xB9,  0x04,  0x3C,  0x08, 	/* 47050 */
+	0x04,  0x1F,  0x24,  0x11,  0x24,  0x19,  0x24,  0x15,  0x44,  0x15,  0x42,  0x13,  0x82,  0x1D,  0x7D,  0x71, 	/* 47060 */
+	0x44,  0x19,  0x44,  0x15,  0x44,  0x15,  0x44,  0x21,  0x44,  0x21,  0x7C,  0x43,  0x00,  0x80,  0x04,  0x04, 	/* 47070 */
+	0x08,  0x18,  0x1E,  0xE4,  0x12,  0xA2,  0x12,  0x92,  0x1B,  0x11,  0x16,  0xFD,  0x16,  0x04,  0x1A,  0x08, 	/* 47080 */
+	0x72,  0x10,  0x1B,  0xFF,  0x16,  0x10,  0x16,  0x10,  0x22,  0x10,  0x22,  0x10,  0x46,  0x30,  0x87,  0x04, 	/* 47090 */
+	0x02,  0x09,  0xCC,  0x1E,  0x78,  0x12,  0x48,  0x12,  0x88,  0x1A,  0x88,  0x17,  0xFF,  0x16,  0x48,  0x1B, 	/* 470A0 */
+	0x48,  0x73,  0x48,  0x1A,  0xC8,  0x16,  0x48,  0x16,  0xFF,  0x22,  0xA0,  0x23,  0x18,  0x46,  0x07,  0x98, 	/* 470B0 */
+	0x04,  0x10,  0x08,  0x30,  0x1E,  0xD6,  0x12,  0x92,  0x12,  0x92,  0x1A,  0xD6,  0x16,  0x92,  0x16,  0x92, 	/* 470C0 */
+	0x1A,  0xD6,  0x72,  0x10,  0x1B,  0xFC,  0x16,  0x44,  0x16,  0x28,  0x22,  0x30,  0x22,  0xCC,  0x47,  0x03, 	/* 470D0 */
+	0x99,  0x04,  0x10,  0x08,  0x30,  0x1E,  0x28,  0x12,  0x44,  0x12,  0xFE,  0x1B,  0x01,  0x16,  0x7C,  0x17, 	/* 470E0 */
+	0x44,  0x1A,  0x7C,  0x72,  0x44,  0x1A,  0x7C,  0x16,  0x40,  0x16,  0xBE,  0x22,  0xA2,  0x23,  0x3E,  0x46, 	/* 470F0 */
+	0x00,  0x9A,  0x04,  0x28,  0x08,  0x28,  0x1E,  0xFF,  0x12,  0x28,  0x12,  0xFE,  0x1A,  0xAA,  0x16,  0xFE, 	/* 47100 */
+	0x17,  0xAA,  0x1A,  0xFE,  0x72,  0x00,  0x1A,  0x7E,  0x16,  0x42,  0x16,  0x7E,  0x22,  0x42,  0x22,  0x7E, 	/* 47110 */
+	0x46,  0x00,  0x9D,  0x04,  0x00,  0x08,  0xFE,  0x1E,  0x10,  0x13,  0xFF,  0x13,  0x11,  0x1B,  0xDD,  0x17, 	/* 47120 */
+	0x11,  0x16,  0xCC,  0x1A,  0x00,  0x72,  0xFC,  0x1A,  0x04,  0x17,  0xFF,  0x16,  0x04,  0x22,  0x04,  0x22, 	/* 47130 */
+	0xFC,  0x46,  0x00,  0x9F,  0x04,  0x10,  0x08,  0xFE,  0x1E,  0x44,  0x12,  0x28,  0x13,  0xFF,  0x1A,  0x00, 	/* 47140 */
+	0x16,  0xFE,  0x16,  0x92,  0x1A,  0xFE,  0x72,  0x92,  0x1A,  0xFE,  0x16,  0x10,  0x16,  0xFE,  0x22,  0x10, 	/* 47150 */
+	0x23,  0xFF,  0x46,  0x00,  0xA2,  0x04,  0x10,  0x08,  0x10,  0x1F,  0xFF,  0x12,  0x94,  0x12,  0xD6,  0x1B, 	/* 47160 */
+	0x39,  0x16,  0x10,  0x17,  0xFF,  0x1A,  0x00,  0x72,  0xFE,  0x1A,  0xBA,  0x16,  0xAA,  0x16,  0xBA,  0x22, 	/* 47170 */
+	0x82,  0x22,  0xFE,  0x46,  0x00,  0xA4,  0x04,  0x82,  0x08,  0x44,  0x1F,  0xFF,  0x12,  0x10,  0x12,  0xFE, 	/* 47180 */
+	0x1A,  0x10,  0x16,  0xFF,  0x16,  0x24,  0x1A,  0xCA,  0x72,  0x48,  0x1B,  0xFF,  0x16,  0x4A,  0x16,  0x64, 	/* 47190 */
+	0x23,  0xC5,  0x22,  0x4B,  0x46,  0xD1,  0xA6,  0x04,  0x04,  0x08,  0xF4,  0x1E,  0xA4,  0x12,  0xA7,  0x12, 	/* 471A0 */
+	0xF8,  0x1A,  0x90,  0x16,  0xF0,  0x17,  0xAF,  0x1A,  0xF0,  0x72,  0x00,  0x1A,  0xFE,  0x16,  0xAA,  0x16, 	/* 471B0 */
+	0xAA,  0x22,  0xAA,  0x23,  0xFF,  0x46,  0x00,  0xA8,  0x04,  0x48,  0x09,  0xFF,  0x1E,  0x48,  0x12,  0xFE, 	/* 471C0 */
+	0x12,  0x82,  0x1A,  0x7A,  0x16,  0x00,  0x17,  0xFF,  0x1A,  0x42,  0x72,  0xAA,  0x1B,  0x5C,  0x16,  0x94, 	/* 471D0 */
+	0x17,  0x32,  0x22,  0x51,  0x22,  0x90,  0x46,  0x60,  0xAA,  0x04,  0x20,  0x08,  0x78,  0x1E,  0x90,  0x13, 	/* 471E0 */
+	0xFE,  0x12,  0x92,  0x1A,  0xFE,  0x16,  0x92,  0x17,  0xFE,  0x1A,  0xAA,  0x73,  0x15,  0x1A,  0xFE,  0x16, 	/* 471F0 */
+	0x82,  0x16,  0xFE,  0x22,  0x82,  0x22,  0xFE,  0x46,  0x00,  0xAB,  0x04,  0x10,  0x08,  0x1E,  0x1E,  0x10, 	/* 47200 */
+	0x12,  0xFF,  0x12,  0x9A,  0x1A,  0xF1,  0x16,  0xBF,  0x17,  0xAA,  0x1A,  0xBE,  0x72,  0xAA,  0x1A,  0xBE, 	/* 47210 */
+	0x16,  0x80,  0x16,  0xFE,  0x23,  0x6A,  0x22,  0xFF,  0x46,  0x00,  0xAE,  0x00,  0x00,  0x0F,  0xF8,  0x08, 	/* 47220 */
+	0x08,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xFA,  0x08,  0x84,  0x08, 	/* 47230 */
+	0x48,  0x08,  0x50,  0x08,  0x20,  0x0B,  0x10,  0x0C,  0x0C,  0x30,  0x03,  0xAF,  0x01,  0x00,  0x01,  0x00, 	/* 47240 */
+	0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF4,  0x09,  0x04, 	/* 47250 */
+	0x08,  0x88,  0x08,  0x50,  0x08,  0x20,  0x0B,  0x10,  0x0C,  0x0C,  0x70,  0x03,  0xB1,  0x12,  0x00,  0x12, 	/* 47260 */
+	0x7C,  0x7F,  0xC4,  0x12,  0x44,  0x1E,  0x7C,  0x08,  0x44,  0x3F,  0x44,  0x29,  0x7C,  0x3F,  0x52,  0x08, 	/* 47270 */
+	0x52,  0x3F,  0x4C,  0x08,  0x48,  0x7F,  0xC4,  0x14,  0x54,  0x22,  0x62,  0x41,  0x81,  0xB2,  0x02,  0x00, 	/* 47280 */
+	0x03,  0xF0,  0x04,  0x20,  0x08,  0x40,  0x10,  0x80,  0x7F,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x11,  0x08, 	/* 47290 */
+	0x1F,  0xF8,  0x10,  0x00,  0x10,  0x00,  0x10,  0x02,  0x10,  0x02,  0x10,  0x02,  0x0F,  0xFE,  0xB6,  0x0A, 	/* 472A0 */
+	0x10,  0x3F,  0x9E,  0x2A,  0xA4,  0x3F,  0xA4,  0x2A,  0xC8,  0x3F,  0xFE,  0x00,  0x4A,  0x7F,  0xCA,  0x00, 	/* 472B0 */
+	0x4A,  0x3F,  0x7E,  0x21,  0x40,  0x3F,  0x40,  0x12,  0x40,  0x0C,  0x41,  0x7F,  0xA1,  0x00,  0x1F,  0xB7, 	/* 472C0 */
+	0x56,  0x88,  0x56,  0x8E,  0x7F,  0x92,  0x56,  0xA4,  0x7F,  0xFE,  0x56,  0xAA,  0x7F,  0xAA,  0x00,  0x2A, 	/* 472D0 */
+	0x7F,  0xAA,  0x00,  0x3E,  0x3F,  0x20,  0x21,  0x20,  0x3F,  0x20,  0x12,  0x21,  0x7F,  0xA1,  0x00,  0x1F, 	/* 472E0 */
+	0xB8,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x29,  0x52,  0x29,  0x52,  0x29,  0x52,  0x29,  0x52,  0x29, 	/* 472F0 */
+	0x52,  0x29,  0x52,  0x3F,  0x7E,  0x08,  0x10,  0x08,  0x10,  0x10,  0x10,  0x10,  0x10,  0x20,  0x10,  0x40, 	/* 47300 */
+	0x10,  0xBE,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x04,  0x10,  0x00,  0x00,  0x04,  0x10, 	/* 47310 */
+	0x04,  0x10,  0x04,  0x10,  0x02,  0x20,  0x02,  0x20,  0x01,  0x40,  0x00,  0x80,  0x03,  0x60,  0x0C,  0x18, 	/* 47320 */
+	0x70,  0x07,  0x8B,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x02,  0x10,  0x00,  0x00,  0x1F, 	/* 47330 */
+	0xFC,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 47340 */
+	0x80,  0x01,  0x80,  0x8D,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x0C,  0x20,  0x08,  0x00, 	/* 47350 */
+	0x0F,  0xFC,  0x10,  0x04,  0x10,  0x04,  0x22,  0x04,  0x41,  0x04,  0x00,  0x84,  0x00,  0x84,  0x00,  0x04, 	/* 47360 */
+	0x00,  0x04,  0x00,  0x38,  0x92,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x04,  0x90,  0x00, 	/* 47370 */
+	0x80,  0x00,  0x80,  0x7F,  0xFF,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x04, 	/* 47380 */
+	0x00,  0x03,  0xFE,  0x00,  0x00,  0x99,  0x04,  0x08,  0x04,  0x08,  0x7F,  0xFF,  0x04,  0x08,  0x04,  0x88, 	/* 47390 */
+	0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x40,  0x02,  0x20, 	/* 473A0 */
+	0x04,  0x10,  0x18,  0x0C,  0x60,  0x03,  0x9D,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x04, 	/* 473B0 */
+	0x90,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x08,  0x00,  0x10,  0x00,  0x20,  0x08,  0x40,  0x09,  0x80,  0x0E, 	/* 473C0 */
+	0x00,  0x09,  0x00,  0x10,  0xE0,  0x20,  0x1F,  0x9F,  0x04,  0x08,  0x04,  0x08,  0x7F,  0xFF,  0x04,  0x08, 	/* 473D0 */
+	0x03,  0xF0,  0x02,  0x10,  0x02,  0x12,  0x04,  0x12,  0x18,  0x0E,  0x07,  0xF0,  0x02,  0x10,  0x01,  0x20, 	/* 473E0 */
+	0x00,  0xC0,  0x01,  0xC0,  0x0E,  0x30,  0x70,  0x0F,  0xA5,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04, 	/* 473F0 */
+	0x10,  0x04,  0x90,  0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x04,  0x10,  0x1A,  0x1C,  0x62,  0x13,  0x02, 	/* 47400 */
+	0x10,  0x02,  0x10,  0x04,  0x10,  0x04,  0x10,  0x08,  0x10,  0xA6,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF, 	/* 47410 */
+	0x02,  0x10,  0x00,  0x00,  0x3F,  0xFE,  0x00,  0x00,  0x0F,  0xFC,  0x08,  0x04,  0x08,  0x04,  0x0F,  0xFC, 	/* 47420 */
+	0x08,  0x00,  0x10,  0x00,  0x10,  0x00,  0x20,  0x00,  0x40,  0x00,  0xAB,  0x04,  0x10,  0x04,  0x10,  0x7F, 	/* 47430 */
+	0xFF,  0x04,  0x10,  0x00,  0x00,  0x0F,  0xF8,  0x00,  0x00,  0x00,  0x00,  0x7F,  0xFF,  0x01,  0x20,  0x01, 	/* 47440 */
+	0x20,  0x01,  0x20,  0x02,  0x22,  0x04,  0x22,  0x18,  0x22,  0x60,  0x1E,  0xAC,  0x04,  0x20,  0x04,  0x20, 	/* 47450 */
+	0x7F,  0xFF,  0x04,  0x20,  0x03,  0xF0,  0x00,  0x10,  0x02,  0x10,  0x04,  0x08,  0x18,  0x04,  0x67,  0xF3, 	/* 47460 */
+	0x01,  0x10,  0x01,  0x10,  0x02,  0x10,  0x02,  0x10,  0x04,  0x10,  0x08,  0x60,  0xAD,  0x02,  0x10,  0x02, 	/* 47470 */
+	0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00,  0x00,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x1F, 	/* 47480 */
+	0xFC,  0x10,  0x00,  0x10,  0x00,  0x10,  0x00,  0x10,  0x02,  0x08,  0x02,  0x07,  0xFE,  0xAF,  0x04,  0x10, 	/* 47490 */
+	0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x04,  0x10,  0x00,  0x80,  0x00,  0x40,  0x02,  0x20,  0x02,  0x20, 	/* 474A0 */
+	0x12,  0x04,  0x12,  0x02,  0x12,  0x01,  0x22,  0x09,  0x22,  0x08,  0x41,  0x08,  0x00,  0xF8,  0xB1,  0x04, 	/* 474B0 */
+	0x20,  0x04,  0x20,  0x7F,  0xFE,  0x04,  0x20,  0x06,  0x20,  0x02,  0x40,  0x04,  0x44,  0x04,  0x44,  0x08, 	/* 474C0 */
+	0x48,  0x18,  0x50,  0x28,  0x60,  0x48,  0x40,  0x08,  0x40,  0x08,  0x41,  0x08,  0x41,  0x08,  0x3F,  0xB3, 	/* 474D0 */
+	0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x04,  0x90,  0x00,  0x80,  0x3F,  0xFE,  0x01,  0x00, 	/* 474E0 */
+	0x01,  0x00,  0x01,  0xF8,  0x01,  0x08,  0x02,  0x08,  0x02,  0x08,  0x04,  0x08,  0x18,  0x08,  0x60,  0x30, 	/* 474F0 */
+	0xB8,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x02,  0x10,  0x00,  0x00,  0x1F,  0xFC,  0x00, 	/* 47500 */
+	0x00,  0x00,  0x00,  0x7F,  0xFF,  0x01,  0x00,  0x01,  0x20,  0x02,  0x10,  0x04,  0xF8,  0x3F,  0x04,  0x00, 	/* 47510 */
+	0x04,  0xB9,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00,  0x20,  0x07,  0xC0,  0x04,  0x00, 	/* 47520 */
+	0x04,  0x00,  0x07,  0xFF,  0x04,  0x20,  0x04,  0x20,  0x08,  0x20,  0x08,  0x20,  0x10,  0x20,  0x20,  0x20, 	/* 47530 */
+	0x00,  0x20,  0xBB,  0x04,  0x00,  0x07,  0xFE,  0x08,  0x82,  0x18,  0x8A,  0x68,  0x8A,  0x0F,  0xFA,  0x02, 	/* 47540 */
+	0x02,  0x0C,  0x06,  0x32,  0x00,  0x03,  0xFE,  0x04,  0x82,  0x1C,  0x8A,  0x64,  0x8A,  0x07,  0xFA,  0x03, 	/* 47550 */
+	0x02,  0x1C,  0x0C,  0xBD,  0x02,  0x20,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x20,  0x00,  0x00,  0x1F,  0xFC, 	/* 47560 */
+	0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFF,  0x00,  0x60,  0x00,  0xA0,  0x03,  0x20,  0x0C,  0x20, 	/* 47570 */
+	0x70,  0x20,  0x00,  0x60,  0x85,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x02,  0x12,  0x01, 	/* 47580 */
+	0x02,  0x31,  0x22,  0x09,  0x22,  0x06,  0x22,  0x02,  0x22,  0x05,  0x22,  0x05,  0x22,  0x08,  0x82,  0x10, 	/* 47590 */
+	0x82,  0x20,  0x82,  0x40,  0x06,  0x91,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x02,  0x10, 	/* 475A0 */
+	0x08,  0x00,  0x0F,  0xBE,  0x08,  0xA2,  0x10,  0xA2,  0x19,  0x22,  0x25,  0x22,  0x42,  0x2C,  0x02,  0x20, 	/* 475B0 */
+	0x04,  0x21,  0x08,  0x11,  0x30,  0x0F,  0x92,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x05, 	/* 475C0 */
+	0x20,  0x01,  0x00,  0x1F,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x1F,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x7F, 	/* 475D0 */
+	0xFF,  0x10,  0x08,  0x10,  0x08,  0x10,  0x18,  0x93,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x90, 	/* 475E0 */
+	0x04,  0x90,  0x01,  0x40,  0x06,  0x20,  0x1B,  0xF8,  0x60,  0x07,  0x00,  0x00,  0x1F,  0xF8,  0x01,  0x08, 	/* 475F0 */
+	0x01,  0x08,  0x01,  0x30,  0x01,  0x00,  0x01,  0x00,  0x94,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04, 	/* 47600 */
+	0x10,  0x01,  0x00,  0x01,  0x20,  0x02,  0x18,  0x04,  0xF4,  0x7F,  0x02,  0x00,  0x00,  0x0F,  0xF8,  0x08, 	/* 47610 */
+	0x08,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x97,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF, 	/* 47620 */
+	0x04,  0x10,  0x04,  0x10,  0x00,  0x00,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC, 	/* 47630 */
+	0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x00,  0x00,  0x99,  0x04,  0x10,  0x04,  0x10,  0x7F, 	/* 47640 */
+	0xFF,  0x04,  0x10,  0x04,  0x10,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x08,  0x04,  0x08,  0x02, 	/* 47650 */
+	0x08,  0x02,  0x10,  0x02,  0x10,  0x00,  0x20,  0x7F,  0xFF,  0x00,  0x00,  0x9B,  0x02,  0x10,  0x02,  0x10, 	/* 47660 */
+	0x7F,  0xFF,  0x02,  0x10,  0x02,  0x10,  0x00,  0x00,  0x7F,  0xFE,  0x00,  0x08,  0x0F,  0xC8,  0x08,  0x48, 	/* 47670 */
+	0x08,  0x48,  0x08,  0x48,  0x0F,  0xC8,  0x00,  0x08,  0x00,  0x08,  0x00,  0x18,  0x9C,  0x04,  0x10,  0x04, 	/* 47680 */
+	0x10,  0x7F,  0xFF,  0x04,  0x10,  0x04,  0x10,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F, 	/* 47690 */
+	0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x9E,  0x02,  0x10, 	/* 476A0 */
+	0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x04,  0x00,  0x07,  0xFC,  0x08,  0x04,  0x0F,  0xE4,  0x18,  0x24, 	/* 476B0 */
+	0x28,  0x24,  0x4F,  0xE4,  0x08,  0x08,  0x08,  0x32,  0x08,  0x02,  0x08,  0x02,  0x07,  0xFE,  0x9F,  0x02, 	/* 476C0 */
+	0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x0A,  0x10,  0x08,  0x00,  0x0F,  0xFE,  0x10,  0x02,  0x17, 	/* 476D0 */
+	0xE2,  0x24,  0x22,  0x44,  0x22,  0x04,  0x22,  0x07,  0xE2,  0x00,  0x02,  0x00,  0x02,  0x00,  0x0C,  0xA1, 	/* 476E0 */
+	0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x04,  0x10,  0x00,  0x00,  0x08,  0x08,  0x09,  0x08, 	/* 476F0 */
+	0x08,  0x88,  0x08,  0x48,  0x08,  0x48,  0x08,  0x08,  0x08,  0x0C,  0x0E,  0x14,  0x18,  0x62,  0x61,  0x81, 	/* 47700 */
+	0xA3,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00,  0x00,  0x1F,  0xFE,  0x10,  0x00,  0x10, 	/* 47710 */
+	0x00,  0x1F,  0xFC,  0x10,  0x04,  0x10,  0x04,  0x1F,  0xFC,  0x10,  0x00,  0x10,  0x00,  0x1F,  0xFF,  0x00, 	/* 47720 */
+	0x00,  0xA5,  0x08,  0x10,  0x08,  0x10,  0x7F,  0xFE,  0x08,  0x10,  0x09,  0x10,  0x01,  0x00,  0x01,  0x00, 	/* 47730 */
+	0x7F,  0xFE,  0x02,  0x00,  0x04,  0x00,  0x07,  0xF8,  0x0C,  0x08,  0x14,  0x08,  0x24,  0x08,  0x47,  0xF8, 	/* 47740 */
+	0x00,  0x00,  0xA6,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x04,  0x90,  0x00,  0x80,  0x7F, 	/* 47750 */
+	0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x0F, 	/* 47760 */
+	0xF8,  0x00,  0x00,  0xA7,  0x08,  0x10,  0x08,  0x10,  0x7F,  0xFF,  0x08,  0x90,  0x00,  0x80,  0x3F,  0xFE, 	/* 47770 */
+	0x20,  0x02,  0x20,  0x02,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80, 	/* 47780 */
+	0x00,  0x80,  0x01,  0x80,  0xAB,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x04,  0x90,  0x00, 	/* 47790 */
+	0x80,  0x00,  0x80,  0x00,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xF8,  0x10,  0x08,  0x10,  0x08,  0x10, 	/* 477A0 */
+	0x08,  0x1F,  0xF8,  0x00,  0x00,  0xB1,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x04,  0x90, 	/* 477B0 */
+	0x00,  0x80,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84,  0x10,  0x84,  0x7F,  0xFF,  0x01,  0x40,  0x02,  0x20, 	/* 477C0 */
+	0x04,  0x10,  0x18,  0x0C,  0x60,  0x03,  0xB3,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x01, 	/* 477D0 */
+	0x00,  0x01,  0xF8,  0x06,  0x10,  0x39,  0x20,  0x00,  0xC0,  0x03,  0x20,  0x0D,  0x98,  0x70,  0x47,  0x00, 	/* 477E0 */
+	0x00,  0x00,  0x30,  0x01,  0xC0,  0x0E,  0x00,  0xB4,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10, 	/* 477F0 */
+	0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8, 	/* 47800 */
+	0x08,  0x08,  0x08,  0x08,  0x7F,  0xFF,  0x00,  0x00,  0xB9,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02, 	/* 47810 */
+	0x10,  0x00,  0x00,  0x3F,  0xFE,  0x00,  0x90,  0x04,  0x90,  0x04,  0x88,  0x08,  0x88,  0x00,  0x80,  0x7F, 	/* 47820 */
+	0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0xBA,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFF, 	/* 47830 */
+	0x04,  0x20,  0x00,  0x00,  0x0F,  0xF8,  0x09,  0x08,  0x08,  0x88,  0x08,  0x88,  0x7F,  0xFF,  0x11,  0x08, 	/* 47840 */
+	0x10,  0x88,  0x10,  0x88,  0x1F,  0xFE,  0x00,  0x10,  0x00,  0xE0,  0xBB,  0x02,  0x10,  0x02,  0x10,  0x7F, 	/* 47850 */
+	0xFF,  0x02,  0x10,  0x02,  0x10,  0x04,  0x08,  0x04,  0x08,  0x09,  0xFF,  0x08,  0x08,  0x19,  0x08,  0x28, 	/* 47860 */
+	0x88,  0x48,  0x88,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x18,  0x82,  0x04,  0x20,  0x04,  0x20, 	/* 47870 */
+	0x7F,  0xFF,  0x04,  0x20,  0x04,  0xA8,  0x00,  0x84,  0x1F,  0xFE,  0x10,  0x80,  0x10,  0x84,  0x10,  0x48, 	/* 47880 */
+	0x10,  0x50,  0x10,  0x20,  0x10,  0x62,  0x21,  0x92,  0x2E,  0x0A,  0x40,  0x06,  0x83,  0x04,  0x20,  0x04, 	/* 47890 */
+	0x20,  0x7F,  0xFF,  0x04,  0x20,  0x04,  0x20,  0x10,  0x00,  0x08,  0xFE,  0x08,  0x82,  0x40,  0x82,  0x20, 	/* 478A0 */
+	0x82,  0x20,  0x82,  0x04,  0x8C,  0x08,  0x80,  0x10,  0x81,  0x20,  0x81,  0x40,  0x7F,  0x84,  0x04,  0x20, 	/* 478B0 */
+	0x04,  0x20,  0x7F,  0xFE,  0x04,  0x20,  0x04,  0x20,  0x08,  0x00,  0x08,  0x7C,  0x7F,  0x44,  0x09,  0x44, 	/* 478C0 */
+	0x09,  0x44,  0x09,  0x44,  0x09,  0x44,  0x11,  0x44,  0x11,  0x7C,  0x21,  0x00,  0x46,  0x00,  0x85,  0x02, 	/* 478D0 */
+	0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x0F,  0xF8,  0x00,  0x10,  0x03,  0x20,  0x00,  0xC0,  0x7F, 	/* 478E0 */
+	0xFE,  0x00,  0xC4,  0x01,  0x48,  0x02,  0x40,  0x04,  0x40,  0x18,  0x40,  0x60,  0x40,  0x00,  0xC0,  0x86, 	/* 478F0 */
+	0x04,  0x20,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x01,  0x00,  0x02,  0x3E,  0x1C,  0x22,  0x11,  0x22, 	/* 47900 */
+	0x11,  0x22,  0x11,  0x22,  0x11,  0x22,  0x1F,  0x22,  0x61,  0x2C,  0x02,  0x20,  0x0C,  0x20,  0x30,  0x20, 	/* 47910 */
+	0x89,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x04,  0x90,  0x00,  0x80,  0x3F,  0xFE,  0x00, 	/* 47920 */
+	0x80,  0x00,  0x80,  0x1F,  0xFC,  0x01,  0xC0,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00, 	/* 47930 */
+	0x80,  0x8E,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00,  0x00,  0x1F,  0xF8,  0x04,  0x10, 	/* 47940 */
+	0x03,  0x20,  0x00,  0xC0,  0x07,  0xB8,  0x78,  0x87,  0x0F,  0xF8,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFE, 	/* 47950 */
+	0x00,  0x00,  0x96,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x01,  0x00,  0x03,  0xF0,  0x0C, 	/* 47960 */
+	0x10,  0x33,  0x20,  0x00,  0xC0,  0x03,  0x20,  0x0C,  0x18,  0x7F,  0xFF,  0x08,  0x08,  0x08,  0x08,  0x0F, 	/* 47970 */
+	0xF8,  0x00,  0x00,  0x97,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x01,  0x00,  0x03,  0xF0, 	/* 47980 */
+	0x04,  0x10,  0x0E,  0x20,  0x31,  0x40,  0x00,  0x80,  0x03,  0xFC,  0x0E,  0x04,  0x72,  0x04,  0x02,  0x04, 	/* 47990 */
+	0x03,  0xFC,  0x00,  0x00,  0x98,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x0F,  0xF8,  0x00, 	/* 479A0 */
+	0x88,  0x01,  0x08,  0x02,  0x08,  0x0C,  0x30,  0x00,  0x00,  0x7F,  0x7E,  0x09,  0x12,  0x09,  0x12,  0x11, 	/* 479B0 */
+	0x22,  0x21,  0x42,  0x46,  0x8C,  0x9C,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFE,  0x04,  0x20,  0x00,  0x00, 	/* 479C0 */
+	0x7F,  0xFE,  0x02,  0x40,  0x02,  0x40,  0x3F,  0xFC,  0x22,  0x44,  0x22,  0x44,  0x24,  0x3C,  0x28,  0x04, 	/* 479D0 */
+	0x30,  0x04,  0x3F,  0xFC,  0x00,  0x00,  0xA3,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00, 	/* 479E0 */
+	0x00,  0x13,  0xF8,  0x12,  0x08,  0x12,  0x08,  0x13,  0xF8,  0x10,  0x00,  0x1F,  0xF8,  0x01,  0x08,  0x7F, 	/* 479F0 */
+	0xFF,  0x02,  0x40,  0x0C,  0x30,  0x70,  0x0E,  0xA8,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10, 	/* 47A00 */
+	0x02,  0x90,  0x10,  0x80,  0x08,  0xFE,  0x08,  0xA2,  0x01,  0x24,  0x01,  0x20,  0x0A,  0x30,  0x08,  0x28, 	/* 47A10 */
+	0x10,  0x48,  0x20,  0x84,  0x43,  0x02,  0x0C,  0x01,  0xAB,  0x02,  0x20,  0x02,  0x20,  0x7F,  0xFF,  0x02, 	/* 47A20 */
+	0x20,  0x10,  0x10,  0x08,  0x10,  0x08,  0xFF,  0x40,  0x80,  0x20,  0x80,  0x20,  0x80,  0x04,  0x80,  0x04, 	/* 47A30 */
+	0x80,  0x08,  0x80,  0x10,  0x40,  0x20,  0x3E,  0x40,  0x00,  0xAF,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF, 	/* 47A40 */
+	0x02,  0x10,  0x0A,  0x08,  0x08,  0x24,  0x08,  0x24,  0x10,  0x20,  0x17,  0xFF,  0x30,  0x50,  0x50,  0x50, 	/* 47A50 */
+	0x10,  0x88,  0x10,  0x88,  0x11,  0x04,  0x12,  0x02,  0x14,  0x01,  0xB1,  0x02,  0x10,  0x02,  0x10,  0x7F, 	/* 47A60 */
+	0xFF,  0x02,  0x10,  0x04,  0x80,  0x04,  0x80,  0x07,  0xFC,  0x08,  0x80,  0x10,  0x80,  0x7F,  0xFF,  0x02, 	/* 47A70 */
+	0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0x00,  0x80,  0xB2,  0x02,  0x10,  0x02,  0x10, 	/* 47A80 */
+	0x7F,  0xFF,  0x02,  0x10,  0x02,  0x10,  0x04,  0x08,  0x04,  0x08,  0x05,  0x0A,  0x39,  0x72,  0x0A,  0x14, 	/* 47A90 */
+	0x04,  0x08,  0x06,  0x0C,  0x0A,  0x14,  0x11,  0x22,  0x7F,  0xFE,  0x01,  0x02,  0xB4,  0x04,  0x10,  0x04, 	/* 47AA0 */
+	0x10,  0x7F,  0xFF,  0x04,  0x10,  0x00,  0x00,  0x3F,  0xFE,  0x20,  0x02,  0x20,  0x02,  0x27,  0xF2,  0x24, 	/* 47AB0 */
+	0x12,  0x24,  0x12,  0x27,  0xF2,  0x20,  0x02,  0x20,  0x02,  0x3F,  0xFE,  0x00,  0x00,  0xB5,  0x04,  0x10, 	/* 47AC0 */
+	0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x00,  0x00,  0x3F,  0xFE,  0x20,  0x82,  0x20,  0x82,  0x2F,  0xFA, 	/* 47AD0 */
+	0x20,  0x82,  0x21,  0x42,  0x26,  0x32,  0x38,  0x0E,  0x20,  0x02,  0x3F,  0xFE,  0x00,  0x00,  0xB6,  0x04, 	/* 47AE0 */
+	0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x90,  0x04,  0x90,  0x01,  0x40,  0x02,  0x20,  0x04,  0x10,  0x18, 	/* 47AF0 */
+	0x8C,  0x6F,  0xFB,  0x00,  0x80,  0x02,  0xA0,  0x04,  0x98,  0x08,  0x84,  0x30,  0x82,  0x00,  0x80,  0xB8, 	/* 47B00 */
+	0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x00,  0x00,  0x7F,  0xFF,  0x04,  0x10,  0x04,  0x10, 	/* 47B10 */
+	0x07,  0xF0,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x04,  0x1E,  0x07,  0xF0,  0x7C,  0x10,  0x00,  0x10, 	/* 47B20 */
+	0xB9,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x04,  0x20,  0x04,  0x00,  0x04,  0x3E,  0x7F, 	/* 47B30 */
+	0xA2,  0x09,  0x22,  0x09,  0x22,  0x11,  0x22,  0x3E,  0x22,  0x23,  0x22,  0x04,  0xBE,  0x18,  0x80,  0x60, 	/* 47B40 */
+	0x00,  0x80,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x08,  0x00,  0x0F,  0xFC,  0x08,  0x04, 	/* 47B50 */
+	0x10,  0x04,  0x17,  0xE4,  0x24,  0x24,  0x47,  0xE4,  0x04,  0x24,  0x04,  0x24,  0x07,  0xE4,  0x00,  0x04, 	/* 47B60 */
+	0x00,  0x38,  0x85,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x04,  0x90,  0x00,  0x80,  0x01, 	/* 47B70 */
+	0x40,  0x06,  0x30,  0x1B,  0xEC,  0x60,  0x03,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F, 	/* 47B80 */
+	0xF8,  0x00,  0x00,  0x89,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00,  0x00,  0x0F,  0xF8, 	/* 47B90 */
+	0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80, 	/* 47BA0 */
+	0x00,  0x80,  0x00,  0x80,  0x8A,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00,  0x02,  0x3F, 	/* 47BB0 */
+	0xD2,  0x09,  0x12,  0x09,  0x12,  0x09,  0x12,  0x7F,  0xF2,  0x09,  0x12,  0x09,  0x12,  0x09,  0x12,  0x09, 	/* 47BC0 */
+	0x02,  0x11,  0x02,  0x21,  0x06,  0x8F,  0x02,  0x20,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x20,  0x02,  0x20, 	/* 47BD0 */
+	0x04,  0x04,  0x04,  0x18,  0x09,  0xF0,  0x08,  0x10,  0x18,  0x10,  0x2B,  0xFF,  0x48,  0x10,  0x08,  0x10, 	/* 47BE0 */
+	0x08,  0x10,  0x09,  0xFE,  0x08,  0x00,  0x90,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x05,  0x10,  0x01, 	/* 47BF0 */
+	0x00,  0x7F,  0xFF,  0x02,  0x00,  0x04,  0x00,  0x07,  0xF8,  0x08,  0x10,  0x18,  0x20,  0x2F,  0xFF,  0x48, 	/* 47C00 */
+	0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x60,  0x92,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFE,  0x04,  0x20, 	/* 47C10 */
+	0x01,  0x00,  0x7F,  0xFE,  0x08,  0x00,  0x08,  0x00,  0x07,  0xF0,  0x00,  0x00,  0x09,  0x10,  0x09,  0x10, 	/* 47C20 */
+	0x09,  0x12,  0x11,  0x12,  0x21,  0x12,  0x40,  0x0E,  0x98,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02, 	/* 47C30 */
+	0x10,  0x00,  0x00,  0x04,  0x10,  0x24,  0x10,  0x14,  0x10,  0x17,  0xFF,  0x04,  0x10,  0x0C,  0x10,  0x34, 	/* 47C40 */
+	0x10,  0x44,  0x10,  0x04,  0x10,  0x05,  0xFE,  0x04,  0x00,  0xB3,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF, 	/* 47C50 */
+	0x04,  0x10,  0x00,  0x00,  0x3F,  0xFE,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8, 	/* 47C60 */
+	0x04,  0x10,  0x02,  0x10,  0x02,  0x20,  0x7F,  0xFF,  0x00,  0x00,  0xB5,  0x02,  0x10,  0x02,  0x10,  0x7F, 	/* 47C70 */
+	0xFF,  0x02,  0x10,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x84,  0x0F,  0x04,  0x03,  0x84,  0x0C,  0x58,  0x30, 	/* 47C80 */
+	0x80,  0x12,  0x44,  0x12,  0x42,  0x22,  0x09,  0x41,  0x09,  0x00,  0xF8,  0xB7,  0x02,  0x10,  0x02,  0x10, 	/* 47C90 */
+	0x7F,  0xFF,  0x02,  0x10,  0x02,  0x10,  0x04,  0x00,  0x07,  0xFF,  0x08,  0x04,  0x09,  0xE4,  0x19,  0x24, 	/* 47CA0 */
+	0x29,  0x24,  0x49,  0x24,  0x09,  0xE4,  0x08,  0x04,  0x08,  0x04,  0x08,  0x0C,  0xBB,  0x02,  0x10,  0x02, 	/* 47CB0 */
+	0x10,  0x7F,  0xFF,  0x02,  0x10,  0x04,  0x00,  0x24,  0x10,  0x18,  0x12,  0x08,  0x92,  0x14,  0x94,  0x24, 	/* 47CC0 */
+	0x90,  0x0D,  0x10,  0x14,  0x28,  0x24,  0x28,  0x04,  0x44,  0x05,  0x82,  0x1E,  0x01,  0xBC,  0x04,  0x10, 	/* 47CD0 */
+	0x04,  0x10,  0x7F,  0xFF,  0x04,  0x90,  0x04,  0x90,  0x01,  0x40,  0x06,  0x30,  0x18,  0x0C,  0x67,  0xF3, 	/* 47CE0 */
+	0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x04,  0xB0,  0x18,  0x8C,  0x60,  0x82,  0x01,  0x80,  0x85,  0x02, 	/* 47CF0 */
+	0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x04,  0x00,  0x04,  0x20,  0x04,  0x20,  0x0B,  0xFF,  0x08, 	/* 47D00 */
+	0x04,  0x19,  0x04,  0x28,  0x84,  0x48,  0x88,  0x08,  0x88,  0x08,  0x10,  0x0F,  0xFF,  0x08,  0x00,  0x87, 	/* 47D10 */
+	0x04,  0x20,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x00,  0x10,  0x1F,  0x10,  0x11,  0xFE,  0x11,  0x12, 	/* 47D20 */
+	0x1F,  0x12,  0x11,  0x12,  0x1F,  0x12,  0x11,  0x22,  0x11,  0xA2,  0x1E,  0x42,  0x60,  0x8C,  0x01,  0x00, 	/* 47D30 */
+	0x89,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00,  0x82,  0x03,  0x22,  0x3C,  0x22,  0x04, 	/* 47D40 */
+	0x22,  0x04,  0x22,  0x7F,  0xE2,  0x0E,  0x22,  0x0D,  0x22,  0x14,  0xA2,  0x24,  0x02,  0x44,  0x02,  0x04, 	/* 47D50 */
+	0x06,  0x8A,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x02,  0x00,  0x22,  0x10,  0x22,  0x10, 	/* 47D60 */
+	0x3E,  0x10,  0x03,  0xFF,  0x02,  0x10,  0x7E,  0x10,  0x12,  0x10,  0x12,  0x10,  0x12,  0x10,  0x22,  0xFE, 	/* 47D70 */
+	0x42,  0x00,  0x8E,  0x02,  0x20,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x20,  0x10,  0x00,  0x08,  0x20,  0x08, 	/* 47D80 */
+	0x24,  0x41,  0x22,  0x21,  0x22,  0x21,  0x21,  0x0A,  0x25,  0x0C,  0x64,  0x10,  0x08,  0x10,  0x10,  0x20, 	/* 47D90 */
+	0x60,  0x43,  0x80,  0x93,  0x02,  0x20,  0x02,  0x20,  0x7F,  0xFF,  0x0A,  0x20,  0x08,  0x00,  0x0F,  0xFF, 	/* 47DA0 */
+	0x10,  0x00,  0x17,  0xFC,  0x24,  0x84,  0x04,  0x44,  0x7F,  0xFF,  0x08,  0x84,  0x08,  0x44,  0x0F,  0xFF, 	/* 47DB0 */
+	0x00,  0x08,  0x00,  0x30,  0x96,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00,  0x00,  0x1F, 	/* 47DC0 */
+	0xFC,  0x04,  0x44,  0x08,  0x88,  0x11,  0x10,  0x08,  0x88,  0x04,  0x44,  0x1F,  0xFC,  0x00,  0x80,  0x00, 	/* 47DD0 */
+	0x80,  0x7F,  0xFF,  0x00,  0x00,  0x9A,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x00,  0x0C, 	/* 47DE0 */
+	0x7D,  0xF0,  0x08,  0x20,  0x11,  0x20,  0x3D,  0x3C,  0x05,  0x20,  0x25,  0x20,  0x19,  0x20,  0x09,  0xFE, 	/* 47DF0 */
+	0x14,  0x00,  0x23,  0x00,  0x40,  0xFF,  0x9E,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x00, 	/* 47E00 */
+	0x80,  0x7F,  0xFE,  0x40,  0x02,  0x4F,  0xF2,  0x00,  0x00,  0x00,  0x00,  0x7F,  0xFE,  0x02,  0x40,  0x02, 	/* 47E10 */
+	0x40,  0x04,  0x42,  0x18,  0x42,  0x60,  0x3E,  0x9F,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x90, 	/* 47E20 */
+	0x01,  0x40,  0x02,  0x30,  0x0D,  0xEC,  0x70,  0x03,  0x1F,  0xF8,  0x00,  0x20,  0x00,  0x40,  0x0F,  0xFC, 	/* 47E30 */
+	0x08,  0x04,  0x08,  0x04,  0x0F,  0xFC,  0x00,  0x00,  0xA0,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02, 	/* 47E40 */
+	0x10,  0x00,  0x30,  0x0F,  0xC0,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0xA0,  0x0C,  0x98,  0x77,  0xF7,  0x00, 	/* 47E50 */
+	0x90,  0x00,  0x9C,  0x01,  0x04,  0x06,  0x04,  0x18,  0x18,  0xA2,  0x04,  0x08,  0x04,  0x08,  0x7F,  0xFF, 	/* 47E60 */
+	0x04,  0x88,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x08,  0x88,  0x08,  0x88,  0x08,  0x94,  0x15,  0x54, 	/* 47E70 */
+	0x13,  0x62,  0x22,  0x20,  0x04,  0x10,  0x18,  0x0C,  0x60,  0x03,  0xA8,  0x02,  0x10,  0x02,  0x10,  0x7F, 	/* 47E80 */
+	0xFF,  0x02,  0x10,  0x00,  0x80,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F, 	/* 47E90 */
+	0xFA,  0x08,  0x44,  0x08,  0x28,  0x09,  0x90,  0x0E,  0x0C,  0x30,  0x03,  0xAA,  0x02,  0x10,  0x02,  0x10, 	/* 47EA0 */
+	0x7F,  0xFF,  0x02,  0x10,  0x01,  0x20,  0x06,  0x24,  0x3C,  0x22,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x10, 	/* 47EB0 */
+	0x05,  0x14,  0x0E,  0x08,  0x74,  0x19,  0x04,  0x65,  0x05,  0x83,  0x0C,  0x01,  0xAB,  0x02,  0x20,  0x02, 	/* 47EC0 */
+	0x20,  0x7F,  0xFF,  0x02,  0x20,  0x02,  0x20,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F, 	/* 47ED0 */
+	0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x40,  0x02,  0x20,  0x0C,  0x18,  0x70,  0x07,  0xB1,  0x02,  0x10, 	/* 47EE0 */
+	0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00,  0x80,  0x3F,  0xFE,  0x08,  0x88,  0x04,  0x90,  0x04,  0x80, 	/* 47EF0 */
+	0x7F,  0xFF,  0x01,  0xC0,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0xB5,  0x04, 	/* 47F00 */
+	0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x00,  0x80,  0x01,  0x00,  0x1F,  0xFC,  0x10,  0x84,  0x10, 	/* 47F10 */
+	0x84,  0x1F,  0xFC,  0x01,  0x40,  0x02,  0x50,  0x02,  0x49,  0x04,  0x49,  0x18,  0x41,  0x60,  0x3F,  0xBD, 	/* 47F20 */
+	0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x01,  0x00,  0x3F,  0xFE,  0x01,  0x40,  0x02,  0x20, 	/* 47F30 */
+	0x0C,  0x18,  0x74,  0x17,  0x04,  0x10,  0x3F,  0xFE,  0x04,  0x10,  0x08,  0x10,  0x10,  0x10,  0x20,  0x10, 	/* 47F40 */
+	0x81,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80,  0x1F,  0xFC,  0x00, 	/* 47F50 */
+	0x80,  0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x0F,  0xF8,  0x08,  0x08,  0x08, 	/* 47F60 */
+	0x18,  0x85,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00,  0x80,  0x3F,  0xFE,  0x20,  0x02, 	/* 47F70 */
+	0x27,  0xF2,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x00,  0x07,  0xF8,  0x04,  0x08,  0x04,  0x08,  0x07,  0xF8, 	/* 47F80 */
+	0x00,  0x00,  0x8A,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x08,  0x00,  0x0F,  0xFE,  0x19, 	/* 47F90 */
+	0x02,  0x15,  0x22,  0x25,  0x42,  0x7F,  0xFA,  0x03,  0x82,  0x05,  0x42,  0x09,  0x22,  0x31,  0x12,  0x01, 	/* 47FA0 */
+	0x04,  0x00,  0x18,  0x8C,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x3F,  0xFE,  0x20,  0x12, 	/* 47FB0 */
+	0x20,  0xE2,  0x27,  0x82,  0x20,  0x82,  0x3F,  0xFE,  0x22,  0xA2,  0x24,  0x92,  0x28,  0x8A,  0x20,  0x82, 	/* 47FC0 */
+	0x3F,  0xFE,  0x20,  0x02,  0x8E,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00,  0x00,  0x0F, 	/* 47FD0 */
+	0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x20,  0x08,  0x22,  0x0F,  0xBC,  0x08, 	/* 47FE0 */
+	0x21,  0x0F,  0xA1,  0x70,  0x1F,  0x93,  0x02,  0x20,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x20,  0x0F,  0xF8, 	/* 47FF0 */
+	0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0xA0,  0x04,  0x90, 	/* 48000 */
+	0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0x96,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFE,  0x04,  0x20,  0x0F, 	/* 48010 */
+	0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x00,  0x00,  0x3F,  0xFC,  0x20,  0x04,  0x3F, 	/* 48020 */
+	0xFC,  0x20,  0x04,  0x3F,  0xFC,  0x00,  0x00,  0x98,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20, 	/* 48030 */
+	0x08,  0x78,  0x08,  0x08,  0x08,  0x48,  0x7E,  0x44,  0x08,  0x84,  0x18,  0xA2,  0x1D,  0x21,  0x2A,  0x28, 	/* 48040 */
+	0x2A,  0x44,  0x48,  0x84,  0x09,  0xFE,  0x08,  0x02,  0x9C,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02, 	/* 48050 */
+	0x10,  0x02,  0x18,  0x1F,  0xE4,  0x00,  0x84,  0x08,  0x48,  0x04,  0x50,  0x00,  0x80,  0x7F,  0xFF,  0x01, 	/* 48060 */
+	0xC0,  0x02,  0xA0,  0x0C,  0x98,  0x70,  0x87,  0x00,  0x80,  0x9F,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF, 	/* 48070 */
+	0x05,  0x10,  0x01,  0xF0,  0x02,  0x20,  0x04,  0x40,  0x1F,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x0F,  0xF8, 	/* 48080 */
+	0x02,  0x50,  0x02,  0x48,  0x04,  0x4A,  0x18,  0x22,  0x60,  0x1E,  0xA0,  0x04,  0x20,  0x04,  0x20,  0x7F, 	/* 48090 */
+	0xFF,  0x04,  0x20,  0x10,  0x10,  0x08,  0x10,  0x09,  0xFF,  0x41,  0x12,  0x21,  0x10,  0x21,  0xFC,  0x05, 	/* 480A0 */
+	0x44,  0x09,  0x44,  0x0A,  0x28,  0x12,  0x10,  0x24,  0x6C,  0x41,  0x83,  0xA9,  0x04,  0x10,  0x04,  0x10, 	/* 480B0 */
+	0x7F,  0xFF,  0x04,  0x10,  0x00,  0x80,  0x3F,  0xFE,  0x04,  0x10,  0x02,  0x10,  0x02,  0x20,  0x7F,  0xFF, 	/* 480C0 */
+	0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0xAB,  0x02,  0x10,  0x7F, 	/* 480D0 */
+	0xFF,  0x02,  0x10,  0x00,  0x00,  0x3F,  0xFE,  0x00,  0x80,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x00, 	/* 480E0 */
+	0x80,  0x1F,  0xFC,  0x00,  0x80,  0x0F,  0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0xAF,  0x04,  0x10, 	/* 480F0 */
+	0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x1F,  0xFC,  0x08,  0x88,  0x08,  0x88,  0x7F,  0xFF,  0x08,  0x88, 	/* 48100 */
+	0x08,  0x88,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0xB0,  0x02, 	/* 48110 */
+	0x20,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x20,  0x00,  0x02,  0x7C,  0x0C,  0x05,  0xF0,  0x09,  0x28,  0x11, 	/* 48120 */
+	0x28,  0x13,  0x28,  0x1D,  0x28,  0x71,  0x34,  0x11,  0x2C,  0x12,  0x3A,  0x13,  0xCA,  0x34,  0x01,  0xB1, 	/* 48130 */
+	0x04,  0x10,  0x7F,  0xFF,  0x04,  0x90,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0x20, 	/* 48140 */
+	0x05,  0x22,  0x19,  0x1E,  0x63,  0xF0,  0x06,  0x10,  0x39,  0x20,  0x00,  0xC0,  0x07,  0x30,  0x78,  0x0E, 	/* 48150 */
+	0xB2,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00,  0x00,  0x02,  0x20,  0x3E,  0x3E,  0x02, 	/* 48160 */
+	0x20,  0x02,  0x20,  0x3E,  0x3E,  0x03,  0x20,  0x0E,  0x20,  0x72,  0x3F,  0x04,  0x20,  0x18,  0x20,  0x60, 	/* 48170 */
+	0x20,  0xB4,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x01,  0x00,  0x7F,  0xFF,  0x02,  0x20, 	/* 48180 */
+	0x04,  0x90,  0x1F,  0xFC,  0x68,  0x8B,  0x0F,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x0F,  0xF9,  0x00,  0x81, 	/* 48190 */
+	0x00,  0x7F,  0xB7,  0x04,  0x20,  0x7F,  0xFE,  0x04,  0x20,  0x0F,  0xF0,  0x00,  0x10,  0x3F,  0xFC,  0x00, 	/* 481A0 */
+	0x10,  0x0F,  0xF0,  0x00,  0x00,  0x7F,  0xFE,  0x41,  0x02,  0x5F,  0xFA,  0x11,  0x08,  0x11,  0x08,  0x11, 	/* 481B0 */
+	0x30,  0x01,  0x00,  0xBB,  0x02,  0x20,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x20,  0x00,  0x00,  0x04,  0x10, 	/* 481C0 */
+	0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x0E,  0x38,  0x0D,  0x34,  0x14,  0xD2,  0x24,  0x51,  0x44,  0x90, 	/* 481D0 */
+	0x04,  0x10,  0x04,  0x10,  0xBD,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x00,  0x00,  0x04, 	/* 481E0 */
+	0x00,  0x07,  0xFE,  0x04,  0x22,  0x04,  0x22,  0x7F,  0xD4,  0x04,  0x14,  0x15,  0x08,  0x14,  0x88,  0x24, 	/* 481F0 */
+	0x94,  0x44,  0x22,  0x0C,  0xC1,  0x83,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x90,  0x00,  0x80, 	/* 48200 */
+	0x3F,  0xFE,  0x04,  0x10,  0x04,  0x10,  0x0A,  0x28,  0x09,  0xA4,  0x10,  0xC0,  0x7F,  0xFF,  0x00,  0x80, 	/* 48210 */
+	0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x84,  0x02,  0x20,  0x02,  0x20,  0x7F,  0xFF,  0x0A,  0x20,  0x08, 	/* 48220 */
+	0x00,  0x0F,  0xFE,  0x12,  0x02,  0x13,  0xF2,  0x24,  0x82,  0x4F,  0xFA,  0x10,  0x82,  0x08,  0x92,  0x08, 	/* 48230 */
+	0x92,  0x0F,  0xF2,  0x00,  0x04,  0x00,  0x18,  0x87,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10, 	/* 48240 */
+	0x07,  0xF8,  0x04,  0x00,  0x07,  0xF0,  0x04,  0x00,  0x07,  0xF0,  0x04,  0x00,  0x7F,  0xFF,  0x04,  0x84, 	/* 48250 */
+	0x04,  0x48,  0x05,  0xB0,  0x0E,  0x0C,  0x30,  0x03,  0x8B,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x00, 	/* 48260 */
+	0x80,  0x3F,  0xFE,  0x00,  0x80,  0x0F,  0xF8,  0x00,  0x88,  0x7F,  0xFF,  0x00,  0x88,  0x0F,  0xF8,  0x01, 	/* 48270 */
+	0x00,  0x7F,  0xFF,  0x02,  0x10,  0x01,  0xE0,  0x1E,  0x18,  0x8C,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF, 	/* 48280 */
+	0x02,  0x10,  0x00,  0x00,  0x3E,  0x7E,  0x22,  0x42,  0x22,  0x42,  0x3E,  0x7E,  0x22,  0x42,  0x22,  0x42, 	/* 48290 */
+	0x22,  0x7E,  0x3E,  0x42,  0x00,  0x42,  0x00,  0x82,  0x01,  0x06,  0x8D,  0x04,  0x20,  0x04,  0x20,  0x7F, 	/* 482A0 */
+	0xFF,  0x04,  0x20,  0x10,  0x00,  0x0B,  0xFE,  0x08,  0x28,  0x00,  0xA4,  0x40,  0xA4,  0x21,  0x20,  0x27, 	/* 482B0 */
+	0xFF,  0x08,  0x20,  0x08,  0x20,  0x10,  0x20,  0x20,  0x20,  0x40,  0x20,  0x8E,  0x02,  0x10,  0x7F,  0xFF, 	/* 482C0 */
+	0x02,  0x10,  0x00,  0x38,  0x1F,  0xC0,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0xA0,  0x0C,  0x98,  0x30,  0x86, 	/* 482D0 */
+	0x7F,  0xFF,  0x02,  0x20,  0x04,  0x20,  0x1F,  0xC0,  0x03,  0x30,  0x3C,  0x0C,  0x93,  0x04,  0x10,  0x04, 	/* 482E0 */
+	0x10,  0x7F,  0xFF,  0x04,  0x10,  0x00,  0x80,  0x3F,  0xFE,  0x20,  0x02,  0x27,  0xF2,  0x04,  0x10,  0x07, 	/* 482F0 */
+	0xF0,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x00,  0x00,  0xA0,  0x02,  0x10, 	/* 48300 */
+	0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00,  0x00,  0x1F,  0x3E,  0x11,  0x22,  0x11,  0x22,  0x1D,  0x3A, 	/* 48310 */
+	0x13,  0x26,  0x11,  0x22,  0x1D,  0x3A,  0x13,  0x26,  0x11,  0x22,  0x21,  0x42,  0x43,  0x86,  0xA2,  0x04, 	/* 48320 */
+	0x20,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x10,  0x80,  0x08,  0x80,  0x08,  0xFE,  0x01,  0x02,  0x41, 	/* 48330 */
+	0xF2,  0x22,  0x12,  0x24,  0x12,  0x09,  0xF4,  0x09,  0x18,  0x11,  0x01,  0x21,  0x01,  0x40,  0xFF,  0xA9, 	/* 48340 */
+	0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x02,  0x00,  0x0C,  0x10,  0x38,  0x12,  0x08,  0x52, 	/* 48350 */
+	0x7F,  0x54,  0x08,  0x50,  0x1C,  0x90,  0x1A,  0x28,  0x2A,  0x28,  0x48,  0x44,  0x08,  0x82,  0x09,  0x01, 	/* 48360 */
+	0xAA,  0x02,  0x20,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x20,  0x01,  0x00,  0x06,  0x24,  0x3C,  0x14,  0x04, 	/* 48370 */
+	0x14,  0x7F,  0x44,  0x0E,  0x24,  0x0D,  0x24,  0x14,  0x87,  0x24,  0x1C,  0x44,  0xE4,  0x04,  0x04,  0x04, 	/* 48380 */
+	0x04,  0xAC,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8, 	/* 48390 */
+	0x08,  0x88,  0x0F,  0xF8,  0x00,  0x80,  0x3F,  0xFE,  0x20,  0xA2,  0x20,  0x92,  0x20,  0xEA,  0x2F,  0x0A, 	/* 483A0 */
+	0x20,  0x06,  0xB1,  0x08,  0x20,  0x08,  0x20,  0x7F,  0xFE,  0x08,  0x20,  0x01,  0x00,  0x7F,  0xFE,  0x40, 	/* 483B0 */
+	0x02,  0x5F,  0xFA,  0x00,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x00, 	/* 483C0 */
+	0x00,  0x7F,  0xFE,  0xB5,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x0F,  0xF8,  0x08,  0x08, 	/* 483D0 */
+	0x08,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x3F,  0xFE,  0x20,  0x02,  0x23,  0xE2,  0x22,  0x22,  0x22,  0x22, 	/* 483E0 */
+	0x23,  0xE2,  0x20,  0x06,  0xB8,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x02,  0x80,  0x1C, 	/* 483F0 */
+	0xBC,  0x10,  0x84,  0x1E,  0xBC,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x00,  0x80,  0x01,  0x40,  0x02, 	/* 48400 */
+	0x20,  0x0C,  0x18,  0x70,  0x07,  0xBC,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x02,  0x10,  0x1F,  0x7C, 	/* 48410 */
+	0x11,  0x44,  0x1F,  0x7C,  0x00,  0x00,  0x0F,  0xF8,  0x00,  0x00,  0x7F,  0xFF,  0x02,  0x00,  0x07,  0xF8, 	/* 48420 */
+	0x04,  0x08,  0x00,  0x08,  0x00,  0x30,  0xBD,  0x02,  0x20,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0xA0,  0x10, 	/* 48430 */
+	0x80,  0x08,  0xFC,  0x08,  0x88,  0x41,  0x50,  0x22,  0x20,  0x20,  0xD8,  0x09,  0x04,  0x0F,  0xFF,  0x11, 	/* 48440 */
+	0x04,  0x11,  0x04,  0x21,  0xFC,  0x20,  0x00,  0x86,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10, 	/* 48450 */
+	0x00,  0x00,  0x04,  0xFC,  0x04,  0x84,  0x08,  0x84,  0x08,  0xFC,  0x18,  0x10,  0x2B,  0xFF,  0x48,  0x58, 	/* 48460 */
+	0x08,  0x94,  0x09,  0x12,  0x0A,  0x11,  0x08,  0x10,  0x89,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x04, 	/* 48470 */
+	0x90,  0x3F,  0xFE,  0x04,  0x90,  0x04,  0xF0,  0x04,  0x00,  0x07,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x01, 	/* 48480 */
+	0xC0,  0x02,  0xA0,  0x0C,  0x98,  0x70,  0x87,  0x00,  0x80,  0x8E,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF, 	/* 48490 */
+	0x04,  0x10,  0x08,  0x20,  0x09,  0xFC,  0x10,  0x24,  0x27,  0xFF,  0x44,  0x24,  0x09,  0xFC,  0x10,  0x20, 	/* 484A0 */
+	0x31,  0xFE,  0x50,  0x20,  0x17,  0xFF,  0x10,  0x20,  0x10,  0x20,  0x97,  0x04,  0x10,  0x04,  0x10,  0x7F, 	/* 484B0 */
+	0xFE,  0x04,  0x90,  0x00,  0x90,  0x1F,  0xF8,  0x00,  0xA0,  0x7F,  0xFE,  0x00,  0x80,  0x07,  0xF8,  0x0C, 	/* 484C0 */
+	0x08,  0x37,  0xF8,  0x04,  0x08,  0x04,  0x08,  0x07,  0xF8,  0x00,  0x00,  0x9B,  0x04,  0x20,  0x04,  0x20, 	/* 484D0 */
+	0x7F,  0xFE,  0x04,  0x20,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x02,  0x00, 	/* 484E0 */
+	0x07,  0xFE,  0x1C,  0x62,  0x67,  0x82,  0x04,  0x12,  0x03,  0xF2,  0x00,  0x0C,  0xA1,  0x04,  0x20,  0x7F, 	/* 484F0 */
+	0xFF,  0x04,  0x20,  0x08,  0x00,  0x0F,  0xFE,  0x08,  0xA2,  0x1F,  0xFA,  0x20,  0x82,  0x4F,  0xF2,  0x08, 	/* 48500 */
+	0x92,  0x0F,  0xF2,  0x08,  0x92,  0x0F,  0xF2,  0x08,  0x92,  0x08,  0x34,  0x00,  0x18,  0xA2,  0x02,  0x20, 	/* 48510 */
+	0x02,  0x20,  0x7F,  0xFF,  0x02,  0x20,  0x00,  0x80,  0x3F,  0xFE,  0x01,  0x40,  0x02,  0x20,  0x0D,  0x18, 	/* 48520 */
+	0x70,  0x87,  0x00,  0x00,  0x1F,  0xFC,  0x12,  0x24,  0x12,  0x24,  0x7F,  0xFF,  0x00,  0x00,  0xA3,  0x02, 	/* 48530 */
+	0x10,  0x7F,  0xFF,  0x02,  0x18,  0x0F,  0xE0,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x0F,  0xF8,  0x08, 	/* 48540 */
+	0x88,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0xA6, 	/* 48550 */
+	0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x01,  0x00,  0x0F,  0xF8,  0x02,  0x08,  0x7F,  0xFF,  0x00,  0x00, 	/* 48560 */
+	0x07,  0xF8,  0x04,  0x08,  0x07,  0xF8,  0x00,  0x40,  0x0F,  0xFC,  0x08,  0x40,  0x7F,  0xFF,  0x00,  0x40, 	/* 48570 */
+	0xA9,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x08,  0x00,  0x10,  0x7E,  0x3E,  0x4A,  0x22, 	/* 48580 */
+	0x4A,  0x22,  0x4A,  0x3E,  0x4A,  0x22,  0x7E,  0x22,  0x40,  0x22,  0x40,  0x3E,  0x41,  0x00,  0x41,  0x00, 	/* 48590 */
+	0x3F,  0xAB,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x08,  0x00,  0x08,  0x3E,  0x7F,  0xA2, 	/* 485A0 */
+	0x08,  0x22,  0x08,  0x3E,  0x08,  0x22,  0x3E,  0x22,  0x22,  0x3E,  0x22,  0x22,  0x22,  0x22,  0x3E,  0x42, 	/* 485B0 */
+	0x00,  0x86,  0xAC,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x7F,  0xFF,  0x02,  0x22,  0x07, 	/* 485C0 */
+	0xA4,  0x38,  0xB8,  0x05,  0x20,  0x06,  0x22,  0x3A,  0x1E,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x04, 	/* 485D0 */
+	0x10,  0x18,  0x10,  0xAD,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00,  0x00,  0x3F,  0x7E, 	/* 485E0 */
+	0x21,  0x02,  0x21,  0x02,  0x3F,  0x7E,  0x20,  0x00,  0x20,  0xFE,  0x3F,  0x44,  0x20,  0x28,  0x3F,  0x10, 	/* 485F0 */
+	0x20,  0x6C,  0x21,  0x83,  0xAE,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x03,  0x00,  0x02, 	/* 48600 */
+	0x7C,  0x1C,  0x45,  0x10,  0x45,  0x1E,  0x83,  0x11,  0x00,  0x1E,  0xFC,  0x10,  0x44,  0x10,  0x28,  0x1E, 	/* 48610 */
+	0x30,  0x70,  0xCC,  0x13,  0x03,  0xAF,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x08,  0x20, 	/* 48620 */
+	0x0A,  0x20,  0x72,  0x3E,  0x14,  0x42,  0x08,  0x42,  0x12,  0xA2,  0x7F,  0x12,  0x09,  0x12,  0x2A,  0x02, 	/* 48630 */
+	0x29,  0x02,  0x49,  0x02,  0x08,  0x0C,  0xB1,  0x02,  0x20,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x20,  0x04, 	/* 48640 */
+	0x00,  0x07,  0xFC,  0x09,  0x24,  0x17,  0xA4,  0x22,  0x74,  0x04,  0x44,  0x08,  0x98,  0x12,  0x40,  0x12, 	/* 48650 */
+	0x42,  0x22,  0x09,  0x41,  0x09,  0x00,  0xF8,  0xB5,  0x02,  0x20,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x20, 	/* 48660 */
+	0x0F,  0x48,  0x21,  0x52,  0x12,  0x24,  0x0C,  0x18,  0x17,  0xFC,  0x60,  0x83,  0x00,  0x80,  0x3F,  0xFE, 	/* 48670 */
+	0x01,  0x40,  0x02,  0x20,  0x0C,  0x18,  0x30,  0x06,  0xB7,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00, 	/* 48680 */
+	0x00,  0x3F,  0xFE,  0x20,  0x82,  0x2F,  0xFA,  0x00,  0x80,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x08, 	/* 48690 */
+	0x88,  0x0F,  0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0xB9,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF, 	/* 486A0 */
+	0x02,  0x10,  0x08,  0x20,  0x08,  0x3F,  0x7E,  0x48,  0x10,  0xAA,  0x11,  0x2E,  0x1E,  0x3A,  0x12,  0xEA, 	/* 486B0 */
+	0x12,  0x2E,  0x12,  0x28,  0x22,  0x21,  0x22,  0x21,  0x4C,  0x1F,  0xBA,  0x02,  0x20,  0x7F,  0xFE,  0x02, 	/* 486C0 */
+	0x20,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x7F,  0xFE,  0x04,  0x10,  0x07,  0xF0,  0x04, 	/* 486D0 */
+	0x10,  0x07,  0xF0,  0x04,  0x1C,  0x07,  0xF0,  0x38,  0x10,  0x00,  0x10,  0x82,  0x04,  0x10,  0x04,  0x10, 	/* 486E0 */
+	0x7F,  0xFF,  0x04,  0x10,  0x00,  0x80,  0x3F,  0xFE,  0x04,  0x10,  0x02,  0x20,  0x3F,  0xFE,  0x20,  0x82, 	/* 486F0 */
+	0x20,  0x80,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84,  0x10,  0x98,  0x00,  0x80,  0x84,  0x04,  0x20,  0x04, 	/* 48700 */
+	0x20,  0x7F,  0xFF,  0x04,  0x20,  0x00,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x1F,  0x04,  0x00,  0x7F,  0x7F, 	/* 48710 */
+	0xA4,  0x0A,  0x14,  0x0A,  0x14,  0x12,  0x04,  0x12,  0x0D,  0x22,  0x01,  0x41,  0xFF,  0x8B,  0x04,  0x20, 	/* 48720 */
+	0x04,  0x20,  0x7F,  0xFF,  0x04,  0x24,  0x08,  0x18,  0x09,  0xE2,  0x49,  0x12,  0x28,  0x94,  0x28,  0x88, 	/* 48730 */
+	0x08,  0x08,  0x1B,  0xFF,  0x28,  0x88,  0x48,  0x48,  0x08,  0x48,  0x08,  0x08,  0x08,  0x18,  0x90,  0x04, 	/* 48740 */
+	0x20,  0x04,  0x20,  0x7F,  0xFE,  0x04,  0xA0,  0x01,  0x00,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x08, 	/* 48750 */
+	0x88,  0x08,  0x88,  0x0F,  0xF8,  0x01,  0x48,  0x02,  0x54,  0x04,  0x5E,  0x18,  0x42,  0x60,  0x3E,  0x94, 	/* 48760 */
+	0x04,  0x10,  0x04,  0x10,  0x7F,  0xFE,  0x04,  0x10,  0x00,  0x20,  0x3D,  0xFC,  0x24,  0x20,  0x24,  0x20, 	/* 48770 */
+	0x27,  0xFF,  0x3C,  0x08,  0x25,  0xFE,  0x24,  0x88,  0x24,  0x48,  0x3C,  0x48,  0x00,  0x08,  0x00,  0x18, 	/* 48780 */
+	0x99,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x20,  0x3F,  0xFE,  0x20,  0x02,  0x27,  0xF2,  0x00,  0x00,  0x7F, 	/* 48790 */
+	0xFE,  0x01,  0x04,  0x06,  0xA4,  0x39,  0x68,  0x06,  0xD0,  0x39,  0x48,  0x06,  0x44,  0x78,  0x43,  0x01, 	/* 487A0 */
+	0x80,  0x9C,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x00,  0x00,  0x1F,  0x3E,  0x00,  0x00, 	/* 487B0 */
+	0x00,  0x00,  0x7F,  0xFF,  0x04,  0x08,  0x15,  0x2A,  0x15,  0x2A,  0x14,  0xA9,  0x24,  0xC9,  0x44,  0x88, 	/* 487C0 */
+	0x0C,  0x18,  0x9F,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x08,  0x20,  0x08,  0x20,  0x7F, 	/* 487D0 */
+	0x3E,  0x02,  0x42,  0x22,  0xFA,  0x12,  0x4A,  0x14,  0x4A,  0x14,  0x4A,  0x0B,  0x7A,  0x1C,  0x02,  0x60, 	/* 487E0 */
+	0x02,  0x00,  0x0C,  0xA1,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00,  0x80,  0x3F,  0xFE,  0x04,  0x10, 	/* 487F0 */
+	0x02,  0x20,  0x3F,  0xFE,  0x20,  0x82,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x00,  0x01,  0xF8,  0x02,  0x08, 	/* 48800 */
+	0x0C,  0x08,  0x30,  0x30,  0xAD,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x04,  0x00,  0x07,  0xFE,  0x08, 	/* 48810 */
+	0x82,  0x14,  0x92,  0x27,  0xF2,  0x01,  0x0C,  0x1E,  0x00,  0x07,  0xFE,  0x08,  0x82,  0x14,  0x92,  0x07, 	/* 48820 */
+	0xF2,  0x03,  0x02,  0x1C,  0x0C,  0xB2,  0x02,  0x20,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x28,  0x18,  0x24, 	/* 48830 */
+	0x07,  0xFE,  0x00,  0x20,  0x61,  0xFC,  0x11,  0x24,  0x01,  0xFC,  0x09,  0x24,  0x09,  0xFC,  0x11,  0x24, 	/* 48840 */
+	0x11,  0x24,  0x21,  0x24,  0x41,  0x2C,  0xB8,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00,  0x00,  0x0F, 	/* 48850 */
+	0xF4,  0x00,  0x24,  0x3E,  0x48,  0x02,  0xB0,  0x04,  0x90,  0x18,  0x8C,  0x61,  0x83,  0x00,  0x00,  0x7F, 	/* 48860 */
+	0xFF,  0x12,  0x24,  0x31,  0x12,  0x41,  0x11,  0xB9,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x20,  0x01,  0x10, 	/* 48870 */
+	0x06,  0x60,  0x3F,  0xFE,  0x01,  0x40,  0x1F,  0xFC,  0x01,  0x44,  0x7F,  0xFF,  0x01,  0x44,  0x1F,  0xFC, 	/* 48880 */
+	0x05,  0x50,  0x19,  0x4C,  0x61,  0x43,  0x01,  0x40,  0xBB,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00, 	/* 48890 */
+	0x00,  0x3F,  0x7E,  0x01,  0x02,  0x01,  0x02,  0x1F,  0x3E,  0x10,  0x20,  0x1F,  0x3E,  0x09,  0x12,  0x33, 	/* 488A0 */
+	0x66,  0x05,  0x0A,  0x19,  0x32,  0x01,  0x02,  0x0E,  0x1C,  0xBC,  0x04,  0x08,  0x7F,  0xFF,  0x04,  0x88, 	/* 488B0 */
+	0x05,  0x48,  0x02,  0x20,  0x07,  0xF0,  0x18,  0x0C,  0x67,  0xF3,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10, 	/* 488C0 */
+	0x07,  0xF0,  0x08,  0x00,  0x0F,  0xF8,  0x14,  0x08,  0x27,  0xF8,  0xBF,  0x04,  0x10,  0x7F,  0xFF,  0x04, 	/* 488D0 */
+	0x10,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x00,  0x07,  0xF0,  0x04,  0x10,  0x07,  0xF0,  0x00,  0x00,  0x3F, 	/* 488E0 */
+	0xFE,  0x20,  0x02,  0x27,  0xF2,  0x24,  0x12,  0x27,  0xF2,  0x20,  0x06,  0x81,  0x02,  0x10,  0x7F,  0xFF, 	/* 488F0 */
+	0x02,  0x10,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x0F,  0xF8,  0x01,  0x40,  0x3F,  0xFE,  0x04,  0x30, 	/* 48900 */
+	0x1B,  0xCC,  0x60,  0x83,  0x1F,  0xFC,  0x06,  0xB0,  0x38,  0x8E,  0x00,  0x80,  0x84,  0x04,  0x08,  0x04, 	/* 48910 */
+	0x08,  0x7F,  0xFF,  0x04,  0x88,  0x3F,  0xFF,  0x01,  0x90,  0x07,  0x28,  0x01,  0xCC,  0x7F,  0xF2,  0x00, 	/* 48920 */
+	0x01,  0x0F,  0xFC,  0x08,  0x44,  0x0F,  0xFC,  0x08,  0x44,  0x0F,  0xFC,  0x00,  0x00,  0x86,  0x02,  0x10, 	/* 48930 */
+	0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00,  0x40,  0x1F,  0xFF,  0x11,  0x10,  0x1F,  0xFE,  0x11,  0x10, 	/* 48940 */
+	0x11,  0xF0,  0x10,  0x40,  0x17,  0xFE,  0x24,  0x42,  0x24,  0x42,  0x44,  0x4C,  0x00,  0x40,  0x89,  0x04, 	/* 48950 */
+	0x10,  0x7F,  0xFF,  0x04,  0x90,  0x00,  0x80,  0x3F,  0xFE,  0x22,  0x22,  0x22,  0x92,  0x04,  0x88,  0x09, 	/* 48960 */
+	0x48,  0x06,  0x30,  0x18,  0x0C,  0x6F,  0xFB,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x8A, 	/* 48970 */
+	0x02,  0x20,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x20,  0x05,  0xE0,  0x09,  0x18,  0x71,  0x47,  0x02,  0x30, 	/* 48980 */
+	0x1F,  0xC8,  0x00,  0x00,  0x7F,  0x7E,  0x09,  0x12,  0x33,  0x66,  0x0D,  0x1A,  0x31,  0x62,  0x03,  0x06, 	/* 48990 */
+	0x8B,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x90,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x02, 	/* 489A0 */
+	0x20,  0x04,  0x18,  0x3F,  0xF4,  0x00,  0x02,  0x1F,  0xF8,  0x12,  0x48,  0x12,  0x48,  0x7F,  0xFF,  0x00, 	/* 489B0 */
+	0x00,  0x8D,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x90,  0x00,  0x88,  0x1F,  0xFC,  0x00,  0xA0,  0x7F,  0xFF, 	/* 489C0 */
+	0x02,  0x18,  0x0F,  0xE0,  0x74,  0x02,  0x0F,  0xFE,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8, 	/* 489D0 */
+	0x00,  0x00,  0x90,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x1F,  0xFE,  0x10,  0x00,  0x17,  0xFC,  0x10, 	/* 489E0 */
+	0x00,  0x1F,  0xFF,  0x12,  0x24,  0x13,  0x98,  0x1C,  0x07,  0x10,  0x08,  0x2F,  0xFF,  0x21,  0x08,  0x40, 	/* 489F0 */
+	0x88,  0x00,  0x18,  0x91,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x00, 	/* 48A00 */
+	0x07,  0xF0,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x07,  0xF0,  0x01,  0x44,  0x06,  0x28,  0x7C,  0x10, 	/* 48A10 */
+	0x07,  0x8C,  0x1C,  0x03,  0x96,  0x04,  0x08,  0x7F,  0xFF,  0x04,  0x88,  0x01,  0x00,  0x0F,  0xF8,  0x08, 	/* 48A20 */
+	0x28,  0x0B,  0x28,  0x08,  0xC8,  0x08,  0xA8,  0x0B,  0x08,  0x0F,  0xF8,  0x08,  0x22,  0x0F,  0xBC,  0x08, 	/* 48A30 */
+	0x21,  0x0F,  0xA1,  0x78,  0x1F,  0x99,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00,  0x40, 	/* 48A40 */
+	0x1F,  0xFF,  0x11,  0x24,  0x11,  0x24,  0x11,  0xAA,  0x12,  0x71,  0x14,  0x20,  0x13,  0xFE,  0x20,  0x20, 	/* 48A50 */
+	0x20,  0x20,  0x4F,  0xFF,  0x00,  0x00,  0x9A,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x08, 	/* 48A60 */
+	0x20,  0x08,  0x3F,  0x08,  0x44,  0x14,  0xA8,  0x15,  0x10,  0x34,  0x6C,  0x55,  0x93,  0x14,  0x64,  0x14, 	/* 48A70 */
+	0x1A,  0x14,  0xE4,  0x10,  0x18,  0x11,  0xE0,  0xAC,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x20,  0x00,  0x20, 	/* 48A80 */
+	0x20,  0x7C,  0x13,  0xC8,  0x10,  0x30,  0x00,  0xCC,  0x03,  0x23,  0x79,  0xFE,  0x08,  0x20,  0x08,  0xFC, 	/* 48A90 */
+	0x08,  0x20,  0x17,  0xFF,  0x23,  0x20,  0x40,  0xFF,  0xAE,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x00, 	/* 48AA0 */
+	0x20,  0x13,  0xFE,  0x08,  0x20,  0x09,  0xFC,  0x01,  0x24,  0x01,  0xFC,  0x79,  0x24,  0x09,  0xFC,  0x08, 	/* 48AB0 */
+	0x20,  0x0B,  0xFE,  0x14,  0x20,  0x23,  0x20,  0x40,  0xFF,  0xB4,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x90, 	/* 48AC0 */
+	0x3F,  0xFE,  0x00,  0x80,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x84, 	/* 48AD0 */
+	0x3F,  0xFA,  0x00,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00,  0x30,  0xBC,  0x02,  0x10,  0x7F,  0xFF,  0x02, 	/* 48AE0 */
+	0x10,  0x3F,  0x7E,  0x09,  0x12,  0x33,  0x66,  0x0D,  0x9A,  0x31,  0x46,  0x02,  0x20,  0x0C,  0x98,  0x73, 	/* 48AF0 */
+	0x27,  0x0C,  0xC8,  0x03,  0x10,  0x0C,  0x60,  0x01,  0x80,  0x1E,  0x00,  0xBF,  0x04,  0x10,  0x04,  0x10, 	/* 48B00 */
+	0x7F,  0xFF,  0x04,  0x90,  0x00,  0x80,  0x3F,  0xFE,  0x20,  0x02,  0x2B,  0xFE,  0x08,  0x40,  0x11,  0xFC, 	/* 48B10 */
+	0x31,  0x04,  0x51,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x10,  0x00,  0x80,  0x02,  0x10,  0x02, 	/* 48B20 */
+	0x10,  0x7F,  0xFF,  0x02,  0x10,  0x08,  0x00,  0x7F,  0xBC,  0x21,  0x24,  0x11,  0x28,  0x12,  0x38,  0x7F, 	/* 48B30 */
+	0xA4,  0x00,  0x22,  0x3F,  0x22,  0x21,  0x22,  0x21,  0x3C,  0x3F,  0x20,  0x00,  0x20,  0x86,  0x04,  0x20, 	/* 48B40 */
+	0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x10,  0x20,  0x09,  0xFC,  0x08,  0x20,  0x47,  0xFF,  0x20,  0x88, 	/* 48B50 */
+	0x21,  0x0F,  0x0E,  0x40,  0x08,  0xF8,  0x13,  0x88,  0x10,  0x70,  0x20,  0xD8,  0x47,  0x07,  0x91,  0x02, 	/* 48B60 */
+	0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x0F,  0xFC,  0x09,  0x24,  0x09,  0x24,  0x0F,  0xFC,  0x00, 	/* 48B70 */
+	0x28,  0x1F,  0xFF,  0x10,  0x24,  0x16,  0x28,  0x11,  0x12,  0x10,  0x2A,  0x20,  0xC6,  0x43,  0x02,  0x93, 	/* 48B80 */
+	0x04,  0x20,  0x7F,  0xFE,  0x04,  0x20,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x3F,  0xFC, 	/* 48B90 */
+	0x22,  0x24,  0x3F,  0xFC,  0x00,  0x00,  0x1F,  0xF8,  0x06,  0x20,  0x01,  0xC0,  0x06,  0x30,  0x78,  0x0F, 	/* 48BA0 */
+	0x94,  0x02,  0x20,  0x7F,  0xFF,  0x12,  0x20,  0x1F,  0xFE,  0x10,  0x02,  0x3F,  0xFA,  0x27,  0xE2,  0x44, 	/* 48BB0 */
+	0x22,  0x07,  0xE2,  0x00,  0x02,  0x1F,  0xF2,  0x11,  0x12,  0x1F,  0xF2,  0x11,  0x12,  0x1F,  0xF4,  0x00, 	/* 48BC0 */
+	0x18,  0x95,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x20,  0x09,  0x48,  0x7F,  0xFF,  0x09,  0x4A,  0x11,  0xC6, 	/* 48BD0 */
+	0x20,  0x00,  0x3F,  0xFE,  0x20,  0x82,  0x2F,  0xFA,  0x08,  0x88,  0x08,  0x88,  0x08,  0xB0,  0x00,  0x80, 	/* 48BE0 */
+	0x00,  0x80,  0x97,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00,  0x40,  0x1F,  0xFF,  0x11, 	/* 48BF0 */
+	0x08,  0x11,  0x08,  0x1F,  0xFF,  0x11,  0x08,  0x11,  0x08,  0x11,  0xF8,  0x20,  0x00,  0x25,  0x24,  0x48, 	/* 48C00 */
+	0x92,  0x10,  0x91,  0x98,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x90,  0x01,  0x20,  0x07,  0xF8,  0x05,  0x14, 	/* 48C10 */
+	0x1E,  0xBA,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0x60,  0x0D,  0x98,  0x76,  0x27,  0x00,  0xC8,  0x0F,  0x30, 	/* 48C20 */
+	0x00,  0xC0,  0x1F,  0x00,  0x9A,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x00,  0x04,  0x3F, 	/* 48C30 */
+	0x84,  0x20,  0x84,  0x3F,  0xFF,  0x20,  0x04,  0x2F,  0x44,  0x20,  0x24,  0x3F,  0xA4,  0x2B,  0x04,  0x2A, 	/* 48C40 */
+	0x84,  0x52,  0x84,  0x06,  0x0C,  0x9F,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x08,  0x40, 	/* 48C50 */
+	0x08,  0x7E,  0x7E,  0x40,  0x10,  0xA0,  0x11,  0x3E,  0x1E,  0x48,  0x12,  0x08,  0x12,  0xFF,  0x12,  0x08, 	/* 48C60 */
+	0x22,  0x14,  0x22,  0x62,  0x4D,  0x81,  0xA1,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x04,  0x00,  0x0F, 	/* 48C70 */
+	0x7E,  0x19,  0x24,  0x66,  0x18,  0x14,  0x28,  0x1B,  0xC4,  0x60,  0x03,  0x1F,  0xFC,  0x00,  0x80,  0x04, 	/* 48C80 */
+	0x98,  0x18,  0x86,  0x60,  0x81,  0x01,  0x80,  0xA6,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x90,  0x01,  0x00, 	/* 48C90 */
+	0x07,  0xF8,  0x04,  0x08,  0x07,  0xF8,  0x04,  0x08,  0x07,  0xF8,  0x04,  0x00,  0x07,  0xFF,  0x04,  0x00, 	/* 48CA0 */
+	0x17,  0xFE,  0x14,  0x92,  0x22,  0x4A,  0x40,  0x0C,  0xAC,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x02, 	/* 48CB0 */
+	0x10,  0x00,  0x00,  0x7E,  0xFF,  0x04,  0x28,  0x08,  0x44,  0x28,  0xFE,  0x2E,  0x01,  0x28,  0x54,  0x28, 	/* 48CC0 */
+	0x54,  0x28,  0x54,  0x2E,  0x95,  0x38,  0x95,  0x61,  0x03,  0xAD,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10, 	/* 48CD0 */
+	0x02,  0x20,  0x3C,  0x30,  0x24,  0x48,  0x28,  0xF4,  0x33,  0x03,  0x28,  0xF8,  0x24,  0x10,  0x25,  0xFC, 	/* 48CE0 */
+	0x24,  0x00,  0x3B,  0xFE,  0x20,  0x48,  0x20,  0x94,  0x21,  0xE2,  0xB5,  0x02,  0x10,  0x02,  0x10,  0x7F, 	/* 48CF0 */
+	0xFF,  0x02,  0x14,  0x00,  0x12,  0x1F,  0xFF,  0x10,  0x10,  0x17,  0xF2,  0x14,  0x92,  0x17,  0xF4,  0x14, 	/* 48D00 */
+	0x2C,  0x17,  0xE8,  0x14,  0x95,  0x27,  0xF5,  0x20,  0x23,  0x40,  0x41,  0xBD,  0x04,  0x20,  0x04,  0x20, 	/* 48D10 */
+	0x7F,  0xFF,  0x04,  0x20,  0x08,  0x00,  0x49,  0x20,  0x29,  0x3E,  0x2A,  0x24,  0x7F,  0x44,  0x49,  0x54, 	/* 48D20 */
+	0x49,  0x98,  0x5D,  0x08,  0x6B,  0x14,  0x49,  0x24,  0x49,  0x42,  0x4B,  0x81,  0x80,  0x02,  0x20,  0x02, 	/* 48D30 */
+	0x20,  0x7F,  0xFF,  0x02,  0x20,  0x08,  0x10,  0x7F,  0x7F,  0x08,  0x10,  0x3F,  0x7E,  0x29,  0x52,  0x29, 	/* 48D40 */
+	0x52,  0x2B,  0x56,  0x1C,  0x38,  0x1A,  0x34,  0x29,  0x52,  0x48,  0x91,  0x08,  0x10,  0x81,  0x02,  0x10, 	/* 48D50 */
+	0x7F,  0xFF,  0x02,  0x10,  0x0F,  0xF8,  0x00,  0x08,  0x1F,  0xFE,  0x00,  0x08,  0x07,  0xF8,  0x3F,  0x7E, 	/* 48D60 */
+	0x08,  0x42,  0x7F,  0x7E,  0x00,  0x08,  0x7F,  0xFF,  0x04,  0x08,  0x02,  0x08,  0x00,  0x18,  0x83,  0x02, 	/* 48D70 */
+	0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00,  0x08,  0x1F,  0xF0,  0x08,  0x88,  0x04,  0x90,  0x7F,  0xFF,  0x02, 	/* 48D80 */
+	0xA0,  0x04,  0x90,  0x1F,  0xFC,  0x68,  0x8B,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x00,  0x88, 	/* 48D90 */
+	0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00,  0x00,  0x3F,  0xFE,  0x02,  0x20,  0x1F,  0xFC,  0x12,  0x24, 	/* 48DA0 */
+	0x1F,  0xFC,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80, 	/* 48DB0 */
+	0x89,  0x02,  0x20,  0x02,  0x20,  0x7F,  0xFF,  0x0A,  0x20,  0x08,  0x40,  0x1F,  0xFC,  0x28,  0x40,  0x4F, 	/* 48DC0 */
+	0xF8,  0x08,  0x40,  0x0F,  0xF8,  0x08,  0x40,  0x0F,  0xFC,  0x10,  0x08,  0x12,  0x44,  0x21,  0x22,  0x41, 	/* 48DD0 */
+	0x22,  0x8A,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x90,  0x04,  0x50,  0x12,  0x40,  0x12,  0x04, 	/* 48DE0 */
+	0x12,  0x12,  0x21,  0xF2,  0x04,  0x08,  0x02,  0x04,  0x0A,  0x14,  0x28,  0x91,  0x28,  0xB1,  0x49,  0x52, 	/* 48DF0 */
+	0x07,  0x0E,  0x8B,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x00,  0x80,  0x04,  0x80,  0x04,  0xF8,  0x04, 	/* 48E00 */
+	0x80,  0x04,  0x80,  0x7F,  0xFE,  0x00,  0x00,  0x04,  0x08,  0x17,  0x2E,  0x14,  0x28,  0x14,  0x28,  0x1F, 	/* 48E10 */
+	0xA8,  0x70,  0xFF,  0x8E,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x20,  0x0F,  0xF8,  0x00,  0x80,  0x7F,  0xFF, 	/* 48E20 */
+	0x02,  0x20,  0x07,  0xF0,  0x1A,  0x2C,  0x63,  0xE3,  0x00,  0x00,  0x1F,  0xFC,  0x13,  0xE4,  0x12,  0x24, 	/* 48E30 */
+	0x13,  0xE4,  0x10,  0x0C,  0x95,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x44,  0x78,  0x29, 	/* 48E40 */
+	0x08,  0x11,  0xFC,  0x32,  0x52,  0x4B,  0xFD,  0x1D,  0x54,  0x19,  0x5C,  0x29,  0x84,  0x49,  0xFC,  0x09, 	/* 48E50 */
+	0x04,  0x69,  0xFC,  0x10,  0x00,  0x97,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x00,  0x20, 	/* 48E60 */
+	0x3E,  0x3C,  0x22,  0x24,  0x22,  0x68,  0x3E,  0x98,  0x08,  0x24,  0x2E,  0x42,  0x29,  0xFD,  0x28,  0x44, 	/* 48E70 */
+	0x2E,  0x44,  0x38,  0x7C,  0x60,  0x00,  0x98,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00,  0x80,  0x0F, 	/* 48E80 */
+	0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x08,  0x10,  0x3E,  0x7C,  0x0B,  0x10,  0x7C,  0xFF,  0x00,  0x00,  0x3F, 	/* 48E90 */
+	0xFE,  0x02,  0x20,  0x0C,  0x21,  0x70,  0x1F,  0x9A,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x07,  0xF0, 	/* 48EA0 */
+	0x04,  0x10,  0x3F,  0xFE,  0x22,  0x22,  0x3E,  0x3E,  0x00,  0x00,  0x0F,  0xF8,  0x00,  0x00,  0x7F,  0xFF, 	/* 48EB0 */
+	0x02,  0x00,  0x07,  0xF8,  0x04,  0x08,  0x00,  0x30,  0xA3,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00, 	/* 48EC0 */
+	0x18,  0x0F,  0xE0,  0x11,  0x08,  0x08,  0x90,  0x3F,  0xFE,  0x24,  0x0A,  0x27,  0x0A,  0x09,  0x7C,  0x11, 	/* 48ED0 */
+	0x48,  0x2A,  0x48,  0x05,  0xFF,  0x18,  0x08,  0x60,  0x08,  0xA8,  0x02,  0x10,  0x3F,  0xFF,  0x02,  0x10, 	/* 48EE0 */
+	0x00,  0x00,  0x1F,  0xFF,  0x14,  0x90,  0x13,  0x10,  0x1F,  0xDF,  0x12,  0x2A,  0x1A,  0xAC,  0x1A,  0xC8, 	/* 48EF0 */
+	0x1A,  0x8C,  0x2F,  0x94,  0x22,  0x92,  0x44,  0x22,  0x08,  0x41,  0xA9,  0x02,  0x10,  0x7F,  0xFF,  0x02, 	/* 48F00 */
+	0x10,  0x10,  0xFC,  0x08,  0x84,  0x08,  0xFC,  0x40,  0x84,  0x20,  0xFC,  0x20,  0x00,  0x03,  0xFF,  0x08, 	/* 48F10 */
+	0x80,  0x11,  0xFE,  0x12,  0x4A,  0x24,  0x92,  0x21,  0x22,  0x40,  0x0C,  0xAA,  0x02,  0x20,  0x02,  0x20, 	/* 48F20 */
+	0x7F,  0xFF,  0x0A,  0x20,  0x08,  0x00,  0x1F,  0xFE,  0x29,  0x48,  0x49,  0x48,  0x7F,  0xFF,  0x09,  0x48, 	/* 48F30 */
+	0x09,  0x48,  0x7F,  0xFF,  0x10,  0x00,  0x14,  0x44,  0x22,  0x22,  0x42,  0x21,  0xAD,  0x02,  0x10,  0x7F, 	/* 48F40 */
+	0xFF,  0x02,  0x10,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x84,  0x7F,  0xFF,  0x00,  0x84,  0x1F,  0xFC,  0x04, 	/* 48F50 */
+	0x90,  0x14,  0x94,  0x1F,  0xFC,  0x10,  0x84,  0x1C,  0x9C,  0x24,  0x94,  0x44,  0x94,  0xB7,  0x02,  0x10, 	/* 48F60 */
+	0x7F,  0xFF,  0x02,  0x10,  0x00,  0x00,  0x3E,  0xFF,  0x02,  0x10,  0x14,  0x20,  0x08,  0x7E,  0x7F,  0x42, 	/* 48F70 */
+	0x09,  0x7E,  0x0A,  0x42,  0x0C,  0x7E,  0x08,  0x42,  0x08,  0x7E,  0x08,  0x26,  0x19,  0xC1,  0xBE,  0x02, 	/* 48F80 */
+	0x20,  0x7F,  0xFF,  0x02,  0x20,  0x1F,  0xFC,  0x00,  0x80,  0x3F,  0xFE,  0x20,  0x82,  0x2E,  0xBA,  0x27, 	/* 48F90 */
+	0x9C,  0x00,  0x00,  0x1F,  0xFC,  0x10,  0x84,  0x1F,  0xFC,  0x10,  0x84,  0x1F,  0xFC,  0x00,  0x00,  0x80, 	/* 48FA0 */
+	0x04,  0x20,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x11,  0xF8,  0x09,  0x48,  0x09,  0x68,  0x41,  0x98, 	/* 48FB0 */
+	0x21,  0xF8,  0x28,  0x00,  0x0B,  0xFE,  0x12,  0x92,  0x12,  0x92,  0x22,  0x92,  0x2F,  0xFF,  0x40,  0x00, 	/* 48FC0 */
+	0x84,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x28,  0x10,  0x24,  0x0B,  0xFF,  0x08,  0x20,  0x41,  0xFC,  0x21, 	/* 48FD0 */
+	0x24,  0x21,  0xFC,  0x01,  0x24,  0x11,  0xFC,  0x10,  0x08,  0x27,  0xFF,  0x21,  0x08,  0x40,  0x88,  0x40, 	/* 48FE0 */
+	0x18,  0x87,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x11,  0x10,  0x15,  0x50,  0x25,  0x5F, 	/* 48FF0 */
+	0x4F,  0xE4,  0x08,  0x24,  0x17,  0xD4,  0x30,  0x14,  0x53,  0xA8,  0x12,  0xC8,  0x14,  0x94,  0x18,  0x22, 	/* 49000 */
+	0x10,  0xC1,  0x88,  0x04,  0x10,  0x7F,  0xFF,  0x05,  0x50,  0x03,  0xE0,  0x04,  0x10,  0x1F,  0xFC,  0x74, 	/* 49010 */
+	0x97,  0x12,  0xA4,  0x1F,  0xFC,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F, 	/* 49020 */
+	0xF8,  0x00,  0x00,  0x8A,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x04,  0x12,  0x0F,  0x02,  0x12,  0x12, 	/* 49030 */
+	0x7F,  0x92,  0x24,  0x92,  0x3F,  0x92,  0x24,  0x92,  0x24,  0x92,  0x3F,  0x82,  0x0A,  0x42,  0x25,  0x42, 	/* 49040 */
+	0x25,  0x02,  0x40,  0x06,  0x90,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x02,  0x10,  0x0C,  0xFE,  0x78, 	/* 49050 */
+	0x10,  0x08,  0x10,  0x09,  0xFF,  0x7E,  0x48,  0x08,  0xAF,  0x1D,  0x20,  0x1A,  0x7C,  0x29,  0xC8,  0x48, 	/* 49060 */
+	0x30,  0x08,  0xCC,  0x0B,  0x03,  0x91,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x3F,  0xFE,  0x08,  0x88, 	/* 49070 */
+	0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x3F,  0xFE,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8, 	/* 49080 */
+	0x08,  0x88,  0x7F,  0xFF,  0x00,  0x00,  0x94,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x90,  0x3F,  0xFE,  0x04, 	/* 49090 */
+	0x88,  0x0C,  0x98,  0x12,  0xA4,  0x7F,  0xFF,  0x00,  0x00,  0x1F,  0xF8,  0x13,  0xC8,  0x12,  0x48,  0x13, 	/* 490A0 */
+	0xC8,  0x10,  0x08,  0x1F,  0xF8,  0x10,  0x08,  0x97,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x3F,  0xFE, 	/* 490B0 */
+	0x20,  0x82,  0x27,  0xF2,  0x20,  0x82,  0x3F,  0xFE,  0x24,  0x22,  0x27,  0xE2,  0x23,  0x92,  0x25,  0x62, 	/* 490C0 */
+	0x39,  0x32,  0x21,  0x0E,  0x3F,  0xFE,  0x00,  0x00,  0x99,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFF,  0x04, 	/* 490D0 */
+	0x20,  0x10,  0x24,  0x10,  0x48,  0x1F,  0x7F,  0x28,  0xC8,  0x48,  0x48,  0x7F,  0x7E,  0x08,  0x48,  0x0C, 	/* 490E0 */
+	0x7E,  0x12,  0x48,  0x11,  0x48,  0x21,  0x7F,  0x40,  0x40,  0x9B,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x20, 	/* 490F0 */
+	0x08,  0x10,  0x10,  0x10,  0x3E,  0xFE,  0x22,  0x44,  0x22,  0x24,  0x3E,  0x28,  0x21,  0xFF,  0x20,  0x10, 	/* 49100 */
+	0x3E,  0x10,  0x22,  0xFE,  0x22,  0x10,  0x3E,  0x10,  0x00,  0x10,  0x9C,  0x02,  0x20,  0x7F,  0xFF,  0x02, 	/* 49110 */
+	0x20,  0x00,  0x10,  0x1F,  0x10,  0x11,  0xFE,  0x11,  0x44,  0x1F,  0x24,  0x10,  0x28,  0x10,  0xFF,  0x2F, 	/* 49120 */
+	0x10,  0x29,  0x10,  0x49,  0xFE,  0x09,  0x10,  0x0F,  0x10,  0x00,  0x10,  0xA4,  0x04,  0x20,  0x04,  0x20, 	/* 49130 */
+	0x7F,  0xFF,  0x04,  0x20,  0x00,  0x28,  0x7E,  0xEE,  0x08,  0x28,  0x08,  0x28,  0x1E,  0xEE,  0x12,  0x28, 	/* 49140 */
+	0x34,  0x28,  0x4C,  0xEE,  0x08,  0x28,  0x10,  0x28,  0x21,  0xFF,  0x40,  0x00,  0xA6,  0x04,  0x08,  0x7F, 	/* 49150 */
+	0xFE,  0x04,  0x08,  0x00,  0x40,  0x1F,  0xFE,  0x11,  0x20,  0x1F,  0xFC,  0x11,  0x24,  0x1F,  0xFC,  0x12, 	/* 49160 */
+	0x00,  0x13,  0xFF,  0x12,  0x00,  0x23,  0xFE,  0x28,  0x92,  0x4A,  0x4A,  0x11,  0x0C,  0xA8,  0x02,  0x20, 	/* 49170 */
+	0x7F,  0xFF,  0x02,  0x20,  0x1F,  0xFC,  0x11,  0x24,  0x1F,  0xFC,  0x00,  0x00,  0x7F,  0xFE,  0x40,  0x02, 	/* 49180 */
+	0x5F,  0xFA,  0x04,  0x40,  0x0F,  0x48,  0x31,  0x70,  0x0A,  0x42,  0x0C,  0x42,  0x70,  0x3E,  0xA9,  0x04, 	/* 49190 */
+	0x20,  0x7F,  0xFF,  0x04,  0x20,  0x00,  0x10,  0x3D,  0xFE,  0x24,  0x84,  0x24,  0x48,  0x2B,  0xFF,  0x32, 	/* 491A0 */
+	0x90,  0x2A,  0xFE,  0x26,  0x90,  0x27,  0x7E,  0x3A,  0x10,  0x24,  0x10,  0x25,  0xFF,  0x28,  0x00,  0xAA, 	/* 491B0 */
+	0x04,  0x20,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x04,  0x04,  0x3F,  0xB8,  0x11,  0x20,  0x0A,  0x20, 	/* 491C0 */
+	0x7F,  0xBF,  0x04,  0x24,  0x7F,  0xA4,  0x0E,  0x24,  0x15,  0x44,  0x24,  0x44,  0x44,  0x84,  0x04,  0x04, 	/* 491D0 */
+	0xAB,  0x04,  0x10,  0x3F,  0xFE,  0x04,  0x18,  0x1F,  0xE0,  0x00,  0x80,  0x7F,  0xFF,  0x08,  0x88,  0x0F, 	/* 491E0 */
+	0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x0A,  0x44,  0x31, 	/* 491F0 */
+	0x22,  0xAC,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00,  0x82,  0x33,  0xF2,  0x0A,  0x14,  0x07,  0xF8, 	/* 49200 */
+	0x0A,  0x16,  0x33,  0xF1,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83, 	/* 49210 */
+	0x00,  0x80,  0xAE,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x24,  0xA0,  0x15,  0x20,  0x7F,  0xBF,  0x16, 	/* 49220 */
+	0x24,  0x25,  0x44,  0x44,  0xA4,  0x08,  0x14,  0x7F,  0xD4,  0x09,  0x08,  0x19,  0x0C,  0x06,  0x14,  0x19, 	/* 49230 */
+	0x22,  0x60,  0xC1,  0xAF,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x1F,  0xFC,  0x12,  0x24,  0x1F,  0xFC, 	/* 49240 */
+	0x00,  0x88,  0x1F,  0xFE,  0x00,  0xA0,  0x7F,  0xFF,  0x03,  0xF8,  0x04,  0x08,  0x1F,  0xF8,  0x64,  0x08, 	/* 49250 */
+	0x07,  0xF8,  0x00,  0x00,  0xB9,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x90,  0x3F,  0xFE,  0x00,  0x80,  0x1F, 	/* 49260 */
+	0xFC,  0x07,  0xF0,  0x04,  0x10,  0x3F,  0xFE,  0x20,  0x02,  0x2F,  0xFC,  0x02,  0x30,  0x0F,  0xE8,  0x00, 	/* 49270 */
+	0x80,  0x7F,  0xFF,  0x00,  0x00,  0xBA,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00,  0x80,  0x7F,  0xFF, 	/* 49280 */
+	0x02,  0x22,  0x7D,  0x5C,  0x14,  0x94,  0x2C,  0x92,  0x48,  0x89,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08, 	/* 49290 */
+	0x0F,  0xF8,  0x10,  0x08,  0x20,  0x08,  0x81,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x90,  0x3F,  0xFE,  0x04, 	/* 492A0 */
+	0x10,  0x07,  0xF0,  0x00,  0x00,  0x3F,  0xFE,  0x22,  0x22,  0x23,  0xE6,  0x00,  0x80,  0x7F,  0xFF,  0x02, 	/* 492B0 */
+	0xA0,  0x0C,  0x98,  0x70,  0x87,  0x00,  0x80,  0x89,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x08,  0x24, 	/* 492C0 */
+	0x0A,  0x7E,  0x3C,  0x24,  0x08,  0x24,  0x3E,  0xFF,  0x08,  0x00,  0x7F,  0x7E,  0x08,  0x42,  0x1C,  0x7E, 	/* 492D0 */
+	0x1A,  0x42,  0x2A,  0x42,  0x48,  0x7E,  0x08,  0x00,  0x8D,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x3F, 	/* 492E0 */
+	0x90,  0x24,  0x3F,  0x3F,  0x20,  0x21,  0x40,  0x3F,  0xBE,  0x24,  0x00,  0x3F,  0x80,  0x00,  0x00,  0x1F, 	/* 492F0 */
+	0xFC,  0x12,  0x24,  0x12,  0x24,  0x7F,  0xFF,  0x00,  0x00,  0x8F,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFF, 	/* 49300 */
+	0x04,  0x24,  0x00,  0x12,  0x2F,  0xFF,  0x28,  0x10,  0x2B,  0xD2,  0x3A,  0x92,  0x0B,  0xD4,  0x7A,  0x4C, 	/* 49310 */
+	0x2B,  0xC8,  0x2A,  0x95,  0x4B,  0xF7,  0x10,  0x23,  0x20,  0x41,  0x90,  0x02,  0x10,  0x7F,  0xFF,  0x02, 	/* 49320 */
+	0x10,  0x08,  0x10,  0x15,  0x20,  0x62,  0xFE,  0x14,  0x82,  0x08,  0xFE,  0x74,  0x82,  0x04,  0xFE,  0x1A, 	/* 49330 */
+	0x28,  0x62,  0x28,  0x06,  0x28,  0x1A,  0x49,  0x62,  0x89,  0x0D,  0x07,  0x95,  0x02,  0x10,  0x02,  0x10, 	/* 49340 */
+	0x7F,  0xFF,  0x02,  0x10,  0x0A,  0x00,  0x3C,  0xFC,  0x08,  0xA4,  0x3E,  0xFC,  0x08,  0xA4,  0x7F,  0xFC, 	/* 49350 */
+	0x08,  0x20,  0x1D,  0xFE,  0x1B,  0x2A,  0x2B,  0x36,  0x49,  0xC2,  0x09,  0x06,  0x9C,  0x02,  0x20,  0x7F, 	/* 49360 */
+	0xFF,  0x02,  0x20,  0x06,  0x20,  0x38,  0x3E,  0x08,  0x52,  0x7F,  0x92,  0x1C,  0x22,  0x2A,  0x82,  0x4B, 	/* 49370 */
+	0x4C,  0x0C,  0xB0,  0x74,  0x8F,  0x03,  0xD0,  0x06,  0xB0,  0x38,  0x8E,  0x01,  0x80,  0x9D,  0x02,  0x20, 	/* 49380 */
+	0x7F,  0xFF,  0x02,  0x20,  0x04,  0x10,  0x3F,  0x10,  0x04,  0x7C,  0x7F,  0x94,  0x15,  0x54,  0x2F,  0xB4, 	/* 49390 */
+	0x44,  0x14,  0x07,  0x2D,  0x38,  0xC3,  0x00,  0x00,  0x7F,  0xFF,  0x04,  0x30,  0x1F,  0xC8,  0xA4,  0x02, 	/* 493A0 */
+	0x20,  0x7F,  0xFE,  0x02,  0x20,  0x00,  0x20,  0x3D,  0x24,  0x24,  0xA8,  0x25,  0xFC,  0x3C,  0x50,  0x25, 	/* 493B0 */
+	0xFE,  0x24,  0xA8,  0x3D,  0x24,  0x26,  0xAA,  0x24,  0x70,  0x24,  0xA8,  0x25,  0x26,  0x4C,  0x60,  0xA5, 	/* 493C0 */
+	0x04,  0x10,  0x7F,  0xFF,  0x04,  0x90,  0x11,  0x04,  0x13,  0xC4,  0x6A,  0x5A,  0x33,  0xCC,  0x12,  0x44, 	/* 493D0 */
+	0x2A,  0x4A,  0x77,  0xDD,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0xA0,  0x0C,  0x98,  0x70,  0x87,  0x00,  0x80, 	/* 493E0 */
+	0xA9,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0x0C,  0x13,  0xF0,  0x09,  0x24,  0x08,  0xA8,  0x47, 	/* 493F0 */
+	0xFF,  0x20,  0x68,  0x20,  0xA4,  0x01,  0xFE,  0x0B,  0x25,  0x09,  0xFC,  0x11,  0x24,  0x21,  0xFC,  0x41, 	/* 49400 */
+	0x04,  0xAA,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x20,  0x04,  0x10,  0x1F,  0x90,  0x14,  0x9F,  0x7F,  0xD4, 	/* 49410 */
+	0x14,  0xA4,  0x3F,  0xA4,  0x24,  0xD4,  0x3F,  0x88,  0x04,  0x08,  0x7F,  0x94,  0x09,  0x14,  0x0E,  0x22, 	/* 49420 */
+	0x31,  0x41,  0xB7,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x3E,  0x12,  0x00,  0x7E,  0x7F, 	/* 49430 */
+	0x14,  0x00,  0x18,  0x3F,  0xFF,  0x00,  0x10,  0x3E,  0x7E,  0x01,  0xA2,  0x3E,  0x3E,  0x22,  0x22,  0x3E, 	/* 49440 */
+	0x3E,  0x00,  0x00,  0xB9,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x00,  0x00,  0x3E,  0xFC,  0x00,  0x84, 	/* 49450 */
+	0x7F,  0xFC,  0x00,  0x84,  0x3E,  0xFC,  0x00,  0x40,  0x3E,  0xFE,  0x01,  0x92,  0x3E,  0x9A,  0x22,  0xA2, 	/* 49460 */
+	0x3E,  0xFA,  0x00,  0x0C,  0xBA,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x3F,  0x3E,  0x21,  0x22,  0x3F, 	/* 49470 */
+	0x3E,  0x21,  0x22,  0x3F,  0x3E,  0x22,  0x42,  0x27,  0xFA,  0x2C,  0x42,  0x37,  0xF2,  0x27,  0xF2,  0x24, 	/* 49480 */
+	0x42,  0x27,  0xFA,  0x20,  0x06,  0xBB,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x10,  0xF8, 	/* 49490 */
+	0x08,  0x88,  0x48,  0xF8,  0x23,  0xDE,  0x22,  0x52,  0x03,  0xDE,  0x08,  0x20,  0x17,  0xFF,  0x10,  0x70, 	/* 494A0 */
+	0x21,  0xAC,  0x26,  0x23,  0x40,  0x20,  0xBE,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x20,  0x08,  0x00,  0x7F, 	/* 494B0 */
+	0xFF,  0x08,  0x11,  0x08,  0x23,  0x3F,  0xFE,  0x29,  0x42,  0x29,  0x7E,  0x3F,  0x42,  0x0C,  0x7E,  0x1A, 	/* 494C0 */
+	0x42,  0x29,  0x7E,  0x48,  0x22,  0x09,  0xC1,  0x82,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x90,  0x09,  0x48, 	/* 494D0 */
+	0x09,  0x14,  0x14,  0xF4,  0x0A,  0x2A,  0x28,  0xA9,  0x29,  0xA5,  0x47,  0x1C,  0x00,  0x80,  0x7F,  0xFF, 	/* 494E0 */
+	0x02,  0xA0,  0x0C,  0x98,  0x70,  0x87,  0x00,  0x80,  0x86,  0x04,  0x10,  0x7F,  0xFF,  0x04,  0xF8,  0x00, 	/* 494F0 */
+	0x80,  0x1F,  0xFF,  0x10,  0xB2,  0x17,  0xC4,  0x13,  0xFC,  0x12,  0x48,  0x13,  0xF8,  0x12,  0x48,  0x13, 	/* 49500 */
+	0xF8,  0x20,  0x00,  0x27,  0xFC,  0x44,  0xA4,  0x1F,  0xFF,  0x87,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20, 	/* 49510 */
+	0x10,  0x04,  0x1E,  0x18,  0x24,  0xF0,  0x7F,  0x10,  0x29,  0xFF,  0x3F,  0x18,  0x29,  0x38,  0x29,  0x34, 	/* 49520 */
+	0x3F,  0x54,  0x15,  0x92,  0x2A,  0x91,  0x2A,  0x10,  0x40,  0x10,  0x8A,  0x02,  0x20,  0x02,  0x20,  0x7F, 	/* 49530 */
+	0xFF,  0x0A,  0x20,  0x08,  0x00,  0x10,  0xFC,  0x72,  0xA4,  0x0C,  0xB4,  0x08,  0xCC,  0x12,  0xFC,  0x7D, 	/* 49540 */
+	0x00,  0x08,  0xFE,  0x2C,  0xAA,  0x2A,  0xAA,  0x4B,  0xFF,  0x08,  0x00,  0x8B,  0x02,  0x10,  0x7F,  0xFF, 	/* 49550 */
+	0x02,  0x10,  0x04,  0x00,  0x14,  0xFF,  0x17,  0x08,  0x14,  0x10,  0x7F,  0xFE,  0x04,  0x42,  0x15,  0x7E, 	/* 49560 */
+	0x15,  0x42,  0x2E,  0x7E,  0x42,  0x42,  0x04,  0x7E,  0x08,  0x22,  0x30,  0xC1,  0x93,  0x02,  0x20,  0x7F, 	/* 49570 */
+	0xFF,  0x02,  0x20,  0x00,  0x20,  0x06,  0x3C,  0x38,  0x48,  0x08,  0x90,  0x09,  0xFE,  0x7E,  0x92,  0x08, 	/* 49580 */
+	0xFE,  0x1C,  0x92,  0x1A,  0x92,  0x2A,  0xFE,  0x49,  0x04,  0x09,  0x52,  0x0A,  0x29,  0x96,  0x02,  0x10, 	/* 49590 */
+	0x7F,  0xFF,  0x02,  0x10,  0x08,  0x08,  0x3F,  0x7F,  0x21,  0x22,  0x3F,  0x14,  0x20,  0x7F,  0x3F,  0x08, 	/* 495A0 */
+	0x21,  0x7E,  0x3F,  0x08,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0xA0,  0x0C,  0x98,  0x70,  0x87,  0x97,  0x02, 	/* 495B0 */
+	0x10,  0x7F,  0xFF,  0x02,  0x10,  0x1F,  0x7E,  0x11,  0x24,  0x1F,  0x18,  0x10,  0xFF,  0x3F,  0x08,  0x51, 	/* 495C0 */
+	0x7E,  0x1F,  0x08,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0xA0,  0x0C,  0x98,  0x70,  0x87,  0x00,  0x80,  0x9A, 	/* 495D0 */
+	0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x10,  0x00,  0x1E,  0x22,  0x24,  0x14,  0x7F,  0x7F,  0x29,  0x08, 	/* 495E0 */
+	0x3F,  0x08,  0x29,  0x3E,  0x29,  0x08,  0x3F,  0x08,  0x01,  0x7F,  0x34,  0x88,  0x2A,  0x08,  0x40,  0x08, 	/* 495F0 */
+	0xA2,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x04,  0x20,  0x3F,  0xBF,  0x11,  0x20,  0x7F,  0xFE,  0x00, 	/* 49600 */
+	0x02,  0x1F,  0x3E,  0x11,  0x20,  0x1F,  0x3E,  0x11,  0x20,  0x1F,  0x3E,  0x11,  0x20,  0x11,  0x21,  0x13, 	/* 49610 */
+	0x1F,  0xAD,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x3E,  0x7E,  0x22,  0x42,  0x3E,  0x7E,  0x3E,  0x7E, 	/* 49620 */
+	0x20,  0x82,  0x2F,  0xFA,  0x24,  0x92,  0x27,  0xF2,  0x24,  0x92,  0x27,  0xF2,  0x22,  0xA2,  0x24,  0x92, 	/* 49630 */
+	0x20,  0x06,  0xAF,  0x02,  0x10,  0x7F,  0xFF,  0x02,  0x10,  0x18,  0xF8,  0x04,  0x88,  0x60,  0xF8,  0x10, 	/* 49640 */
+	0x88,  0x07,  0xFF,  0x10,  0x80,  0x21,  0xFE,  0x22,  0x52,  0x40,  0xA6,  0x1F,  0xFC,  0x12,  0x24,  0x7F, 	/* 49650 */
+	0xFF,  0x00,  0x00,  0xB0,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x20,  0x08,  0x7C,  0x08,  0x44,  0x32,  0x7C, 	/* 49660 */
+	0x14,  0x44,  0x08,  0xFE,  0x12,  0xAA,  0x7F,  0xFE,  0x09,  0x00,  0x2C,  0xFC,  0x2A,  0x24,  0x2A,  0x18, 	/* 49670 */
+	0x48,  0x64,  0x09,  0x83,  0xBF,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20,  0x1F,  0xFC,  0x12,  0x44,  0x1F, 	/* 49680 */
+	0xFC,  0x08,  0x22,  0x32,  0x24,  0x14,  0x7F,  0x0A,  0xC8,  0x7F,  0x7E,  0x08,  0x48,  0x2A,  0x7E,  0x29, 	/* 49690 */
+	0x48,  0x49,  0x7F,  0x08,  0x00,  0x8D,  0x00,  0x80,  0x00,  0x80,  0x00,  0xFC,  0x00,  0x80,  0x00,  0x80, 	/* 496A0 */
+	0x1F,  0xFF,  0x10,  0x02,  0x10,  0x84,  0x10,  0x8E,  0x10,  0xF0,  0x1F,  0x80,  0x10,  0x80,  0x20,  0x80, 	/* 496B0 */
+	0x20,  0x81,  0x40,  0x41,  0x00,  0x3F,  0x8E,  0x00,  0x80,  0x00,  0xF8,  0x00,  0x80,  0x1F,  0xFE,  0x11, 	/* 496C0 */
+	0x04,  0x11,  0x18,  0x11,  0xE0,  0x1F,  0x00,  0x11,  0x04,  0x10,  0xFC,  0x11,  0x20,  0x11,  0x20,  0x21, 	/* 496D0 */
+	0x20,  0x22,  0x22,  0x44,  0x12,  0x18,  0x0E,  0x90,  0x00,  0x40,  0x00,  0x7E,  0x00,  0x40,  0x1F,  0xFE, 	/* 496E0 */
+	0x11,  0x04,  0x11,  0xF8,  0x1F,  0x02,  0x11,  0xFE,  0x10,  0x00,  0x17,  0xFC,  0x14,  0x00,  0x17,  0xFC, 	/* 496F0 */
+	0x24,  0x00,  0x24,  0x00,  0x47,  0xFE,  0x04,  0x00,  0x94,  0x00,  0x80,  0x00,  0xFC,  0x00,  0x80,  0x1F, 	/* 49700 */
+	0xFF,  0x11,  0x02,  0x11,  0xF8,  0x1F,  0x00,  0x11,  0x02,  0x10,  0xFE,  0x10,  0x40,  0x1F,  0xFF,  0x11, 	/* 49710 */
+	0x08,  0x20,  0x90,  0x20,  0x60,  0x41,  0x98,  0x1E,  0x07,  0x95,  0x00,  0x80,  0x00,  0xFC,  0x00,  0x80, 	/* 49720 */
+	0x1F,  0xFF,  0x10,  0x91,  0x10,  0xE2,  0x17,  0x88,  0x10,  0xF8,  0x14,  0x00,  0x17,  0xBC,  0x14,  0xA4, 	/* 49730 */
+	0x19,  0x24,  0x35,  0x25,  0x23,  0x47,  0x44,  0x80,  0x18,  0x7F,  0x9A,  0x00,  0x80,  0x00,  0xFE,  0x00, 	/* 49740 */
+	0x80,  0x1F,  0xFF,  0x11,  0x02,  0x11,  0x34,  0x1F,  0xC0,  0x11,  0x02,  0x10,  0xFE,  0x11,  0x20,  0x19, 	/* 49750 */
+	0x24,  0x15,  0x24,  0x25,  0x28,  0x21,  0x20,  0x5F,  0xFF,  0x00,  0x00,  0x9C,  0x00,  0x80,  0x00,  0xFE, 	/* 49760 */
+	0x00,  0x80,  0x1F,  0xFF,  0x10,  0x9A,  0x1F,  0xE0,  0x10,  0x82,  0x17,  0xFE,  0x14,  0x48,  0x17,  0xF8, 	/* 49770 */
+	0x14,  0x48,  0x17,  0xF8,  0x2F,  0xFE,  0x20,  0x82,  0x43,  0x02,  0x0C,  0x0C,  0x9E,  0x00,  0x80,  0x00, 	/* 49780 */
+	0xFC,  0x00,  0x80,  0x1F,  0xFF,  0x11,  0x1A,  0x1F,  0xE0,  0x11,  0x02,  0x10,  0xFE,  0x12,  0x84,  0x12, 	/* 49790 */
+	0xFC,  0x12,  0x00,  0x13,  0xF8,  0x20,  0x08,  0x2F,  0xFF,  0x43,  0x18,  0x1C,  0x06,  0x9F,  0x00,  0x08, 	/* 497A0 */
+	0x3E,  0x0E,  0x22,  0x08,  0x22,  0x7F,  0x22,  0x42,  0x3E,  0x48,  0x00,  0x4E,  0x7F,  0x78,  0x10,  0x49, 	/* 497B0 */
+	0x10,  0x47,  0x3E,  0x54,  0x22,  0x54,  0x02,  0x54,  0x02,  0x95,  0x04,  0xA5,  0x19,  0x43,  0xA7,  0x04, 	/* 497C0 */
+	0x00,  0x07,  0xBE,  0x04,  0x08,  0x3F,  0xC8,  0x25,  0x88,  0x3E,  0x7F,  0x23,  0xD0,  0x24,  0x90,  0x2F, 	/* 497D0 */
+	0xD0,  0x39,  0x1E,  0x2F,  0xC2,  0x29,  0x02,  0x2F,  0xC2,  0x29,  0x02,  0x4F,  0xC4,  0x00,  0x18,  0xAB, 	/* 497E0 */
+	0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x1F,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x11,  0x08,  0x11,  0x08, 	/* 497F0 */
+	0x1F,  0xF8,  0x01,  0x00,  0x01,  0x10,  0x01,  0x08,  0x01,  0x3C,  0x07,  0xC4,  0x78,  0x02,  0x00,  0x02, 	/* 49800 */
+	0xB1,  0x00,  0x00,  0x7F,  0xF8,  0x00,  0x28,  0x00,  0xC8,  0x3F,  0x08,  0x02,  0x08,  0x1F,  0xC8,  0x12, 	/* 49810 */
+	0x48,  0x12,  0x48,  0x12,  0x48,  0x1F,  0xC8,  0x02,  0x08,  0x02,  0x45,  0x03,  0xE5,  0x7C,  0x13,  0x00, 	/* 49820 */
+	0x01,  0xB9,  0x08,  0x00,  0x08,  0x00,  0x08,  0xFE,  0x3F,  0x10,  0x29,  0x10,  0x29,  0x10,  0x29,  0x10, 	/* 49830 */
+	0x29,  0x10,  0x3F,  0x10,  0x08,  0x10,  0x0A,  0x10,  0x09,  0x10,  0x09,  0x10,  0x0F,  0xFF,  0x70,  0x80, 	/* 49840 */
+	0x00,  0x80,  0xBB,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x3F,  0x08,  0x29,  0xFF,  0x29,  0x20,  0x29, 	/* 49850 */
+	0x20,  0x29,  0x20,  0x3F,  0x20,  0x08,  0x20,  0x08,  0x20,  0x0A,  0x20,  0x09,  0x20,  0x0F,  0x20,  0x78, 	/* 49860 */
+	0x9E,  0x00,  0x80,  0x8A,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x3F,  0xFF,  0x29,  0x44,  0x29,  0x44, 	/* 49870 */
+	0x29,  0x44,  0x29,  0x44,  0x3F,  0x28,  0x08,  0x28,  0x0C,  0x10,  0x0A,  0x10,  0x0A,  0x28,  0x0D,  0x48, 	/* 49880 */
+	0x70,  0x84,  0x01,  0x02,  0x8B,  0x08,  0x30,  0x08,  0x10,  0x08,  0x10,  0x08,  0xFE,  0x3E,  0x92,  0x2A, 	/* 49890 */
+	0x92,  0x2A,  0x92,  0x2A,  0xAA,  0x3E,  0xAA,  0x08,  0xA6,  0x08,  0xC2,  0x0C,  0x82,  0x0A,  0x82,  0x0E, 	/* 498A0 */
+	0x82,  0x71,  0x82,  0x00,  0x86,  0x8C,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x7E,  0x3F,  0x10, 	/* 498B0 */
+	0x29,  0x10,  0x29,  0x10,  0x29,  0x7E,  0x3F,  0x10,  0x08,  0x10,  0x0A,  0x10,  0x09,  0xFF,  0x09,  0x10, 	/* 498C0 */
+	0x0E,  0x90,  0x70,  0x90,  0x00,  0x90,  0x93,  0x08,  0x02,  0x08,  0xFA,  0x08,  0x0A,  0x08,  0x0A,  0x3F, 	/* 498D0 */
+	0x0A,  0x29,  0x7A,  0x29,  0x42,  0x29,  0x42,  0x3F,  0x42,  0x08,  0x7A,  0x08,  0x0A,  0x0A,  0x0A,  0x09, 	/* 498E0 */
+	0x0A,  0x0E,  0x8A,  0x70,  0x92,  0x00,  0x62,  0x95,  0x00,  0x00,  0x7F,  0xFE,  0x01,  0x00,  0x01,  0x00, 	/* 498F0 */
+	0x3F,  0xFC,  0x01,  0x80,  0x02,  0x40,  0x0D,  0x30,  0x71,  0x0E,  0x1F,  0xF0,  0x11,  0x10,  0x11,  0x10, 	/* 49900 */
+	0x1F,  0xF0,  0x01,  0x18,  0x01,  0xF4,  0x7E,  0x02,  0xA3,  0x08,  0x78,  0x08,  0x08,  0x08,  0x48,  0x08, 	/* 49910 */
+	0x48,  0x3F,  0x44,  0x29,  0x84,  0x29,  0xA2,  0x29,  0x21,  0x3F,  0x20,  0x08,  0x20,  0x0C,  0x28,  0x0A, 	/* 49920 */
+	0x44,  0x0A,  0x44,  0x0F,  0x4E,  0x71,  0xF2,  0x01,  0x02,  0xA4,  0x00,  0x00,  0x3F,  0xFC,  0x04,  0x88, 	/* 49930 */
+	0x22,  0x50,  0x11,  0x20,  0x10,  0xC0,  0x01,  0xA0,  0x06,  0x98,  0x78,  0x87,  0x0F,  0xF8,  0x08,  0x88, 	/* 49940 */
+	0x08,  0x88,  0x0F,  0xF8,  0x00,  0x8C,  0x00,  0xFA,  0x7F,  0x01,  0xA9,  0x00,  0x80,  0x20,  0x82,  0x20, 	/* 49950 */
+	0x82,  0x3F,  0xFE,  0x01,  0x00,  0x02,  0x00,  0x7F,  0xFF,  0x00,  0x80,  0x0F,  0xF8,  0x08,  0x88,  0x08, 	/* 49960 */
+	0x88,  0x0F,  0xF8,  0x00,  0x88,  0x00,  0x84,  0x00,  0xFA,  0x7F,  0x02,  0xAA,  0x08,  0x04,  0x08,  0x24, 	/* 49970 */
+	0x08,  0x14,  0x08,  0x14,  0x3F,  0x04,  0x29,  0x04,  0x29,  0x44,  0x29,  0x24,  0x3F,  0x24,  0x08,  0x07, 	/* 49980 */
+	0x0A,  0x1C,  0x09,  0x64,  0x09,  0x04,  0x0F,  0x84,  0x70,  0x84,  0x00,  0x84,  0xAB,  0x08,  0x20,  0x08, 	/* 49990 */
+	0x20,  0x08,  0x3E,  0x3F,  0x42,  0x29,  0x42,  0x29,  0xF2,  0x29,  0x52,  0x29,  0x52,  0x3F,  0x52,  0x08, 	/* 499A0 */
+	0x72,  0x0C,  0x44,  0x0A,  0x58,  0x0A,  0x40,  0x0F,  0x41,  0x71,  0x41,  0x00,  0x3F,  0xAF,  0x08,  0x02, 	/* 499B0 */
+	0x08,  0x0C,  0x08,  0x70,  0x08,  0x40,  0x3F,  0x40,  0x29,  0x40,  0x29,  0x7F,  0x29,  0x44,  0x3F,  0x44, 	/* 499C0 */
+	0x08,  0x44,  0x0C,  0x44,  0x0A,  0x44,  0x0A,  0x44,  0x0F,  0x44,  0x71,  0xFF,  0x01,  0x00,  0xB0,  0x08, 	/* 499D0 */
+	0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x3F,  0x7E,  0x29,  0x52,  0x29,  0x52,  0x29,  0x52,  0x3F, 	/* 499E0 */
+	0x52,  0x08,  0x7E,  0x0C,  0x52,  0x0A,  0x52,  0x0A,  0x52,  0x0F,  0x52,  0x71,  0x7E,  0x00,  0x00,  0xB6, 	/* 499F0 */
+	0x08,  0x44,  0x08,  0x44,  0x08,  0x44,  0x08,  0x44,  0x3F,  0xFF,  0x29,  0x44,  0x29,  0x44,  0x29,  0x44, 	/* 49A00 */
+	0x3F,  0x44,  0x08,  0x7C,  0x0A,  0x44,  0x09,  0x44,  0x09,  0x44,  0x0F,  0x44,  0x70,  0xFC,  0x00,  0x80, 	/* 49A10 */
+	0x84,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x3F,  0xFF,  0x29,  0x10,  0x29,  0x10,  0x29, 	/* 49A20 */
+	0x10,  0x3F,  0x10,  0x08,  0x7E,  0x0C,  0x42,  0x0A,  0x42,  0x0A,  0x42,  0x0F,  0x42,  0x71,  0x7E,  0x00, 	/* 49A30 */
+	0x00,  0x86,  0x08,  0x00,  0x08,  0x7C,  0x08,  0x44,  0x08,  0x44,  0x3F,  0x44,  0x29,  0x7C,  0x29,  0x44, 	/* 49A40 */
+	0x29,  0x44,  0x3F,  0x44,  0x08,  0x44,  0x0C,  0x7C,  0x0A,  0x44,  0x0A,  0x44,  0x0F,  0x44,  0x71,  0xFF, 	/* 49A50 */
+	0x01,  0x00,  0x87,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x3F,  0x7F,  0x25,  0x41,  0x25,  0x41,  0x25, 	/* 49A60 */
+	0x20,  0x25,  0x24,  0x3F,  0x24,  0x04,  0x28,  0x06,  0x30,  0x05,  0x20,  0x05,  0x20,  0x0F,  0xA1,  0x70, 	/* 49A70 */
+	0xA1,  0x00,  0x1F,  0x89,  0x08,  0x10,  0x08,  0x10,  0x08,  0x28,  0x08,  0x44,  0x3F,  0x82,  0x29,  0x7D, 	/* 49A80 */
+	0x29,  0x00,  0x29,  0x00,  0x3F,  0x7E,  0x08,  0x12,  0x0A,  0x12,  0x09,  0x12,  0x09,  0x12,  0x0F,  0x9C, 	/* 49A90 */
+	0x70,  0x90,  0x00,  0x90,  0x8B,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x82,  0x08,  0x80,  0x08,  0xFC,  0x0C, 	/* 49AA0 */
+	0x80,  0x13,  0x80,  0x20,  0xFF,  0x40,  0x80,  0x0F,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x0F,  0xF8,  0x00, 	/* 49AB0 */
+	0x8C,  0x00,  0xFA,  0x7F,  0x01,  0x8D,  0x02,  0x08,  0x11,  0x08,  0x09,  0x10,  0x08,  0x20,  0x7F,  0xFE, 	/* 49AC0 */
+	0x41,  0x02,  0x41,  0x02,  0x1F,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x11,  0x08,  0x1F,  0xF8,  0x01,  0x10, 	/* 49AD0 */
+	0x01,  0x0C,  0x01,  0xF2,  0x7E,  0x01,  0x8E,  0x08,  0x00,  0x08,  0xFF,  0x08,  0x80,  0x3E,  0x80,  0x2A, 	/* 49AE0 */
+	0xFF,  0x2A,  0x90,  0x2A,  0x90,  0x2A,  0x9E,  0x3E,  0x92,  0x08,  0x92,  0x0C,  0x92,  0x0A,  0x92,  0x0F, 	/* 49AF0 */
+	0x22,  0x19,  0x22,  0x62,  0x42,  0x04,  0x8C,  0x94,  0x08,  0x00,  0x08,  0x7E,  0x08,  0x42,  0x08,  0x42, 	/* 49B00 */
+	0x3F,  0x42,  0x29,  0x7A,  0x29,  0x6A,  0x29,  0x6A,  0x3F,  0x6A,  0x08,  0x6A,  0x0C,  0x7A,  0x0A,  0x42, 	/* 49B10 */
+	0x0A,  0x42,  0x0F,  0x42,  0x71,  0x7E,  0x01,  0x00,  0x99,  0x08,  0x10,  0x08,  0x10,  0x08,  0x7E,  0x3F, 	/* 49B20 */
+	0x10,  0x29,  0x10,  0x29,  0x10,  0x29,  0xFF,  0x29,  0x00,  0x3F,  0x10,  0x08,  0x10,  0x0C,  0xFE,  0x0A, 	/* 49B30 */
+	0x10,  0x0E,  0x10,  0x19,  0x10,  0x61,  0xFF,  0x00,  0x00,  0x9B,  0x08,  0x08,  0x08,  0x28,  0x08,  0x28, 	/* 49B40 */
+	0x08,  0x28,  0x3F,  0x7E,  0x29,  0x48,  0x29,  0x88,  0x29,  0x08,  0x3F,  0xFF,  0x08,  0x08,  0x0C,  0x1C, 	/* 49B50 */
+	0x0A,  0x1C,  0x0A,  0x2A,  0x0F,  0x49,  0x71,  0x88,  0x01,  0x08,  0x9E,  0x08,  0x02,  0x08,  0x0C,  0x08, 	/* 49B60 */
+	0x70,  0x08,  0x10,  0x3F,  0x10,  0x29,  0xFF,  0x29,  0x10,  0x29,  0x10,  0x3F,  0x10,  0x08,  0x7E,  0x0C, 	/* 49B70 */
+	0x42,  0x0A,  0x42,  0x0A,  0x42,  0x0F,  0x42,  0x71,  0x7E,  0x01,  0x00,  0x9F,  0x08,  0x10,  0x08,  0x10, 	/* 49B80 */
+	0x08,  0x10,  0x09,  0xFF,  0x3F,  0x24,  0x29,  0x22,  0x29,  0x42,  0x29,  0xA5,  0x3F,  0x24,  0x08,  0x14, 	/* 49B90 */
+	0x0C,  0x18,  0x0A,  0x08,  0x0A,  0x14,  0x0F,  0x24,  0x71,  0x42,  0x01,  0x81,  0xA4,  0x08,  0x10,  0x08, 	/* 49BA0 */
+	0x10,  0x08,  0x28,  0x3F,  0x28,  0x29,  0x24,  0x29,  0x42,  0x29,  0x7D,  0x29,  0x80,  0x3F,  0x00,  0x08, 	/* 49BB0 */
+	0x7C,  0x0C,  0x44,  0x0A,  0x44,  0x0A,  0x44,  0x0F,  0x44,  0x71,  0x7C,  0x00,  0x00,  0xA9,  0x00,  0x00, 	/* 49BC0 */
+	0x7E,  0xF8,  0x08,  0x88,  0x08,  0xC8,  0x08,  0xA8,  0x0E,  0xA9,  0x19,  0x09,  0x62,  0x87,  0x00,  0x80, 	/* 49BD0 */
+	0x0F,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x84,  0x00,  0xFA,  0x7F,  0x02,  0xAC,  0x02, 	/* 49BE0 */
+	0x10,  0x02,  0x10,  0x3F,  0xFE,  0x02,  0x10,  0x02,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x08,  0x88,  0x1F, 	/* 49BF0 */
+	0xFC,  0x68,  0x8B,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x90,  0x00,  0x88,  0x00,  0xF4,  0x3F,  0x02,  0xAD, 	/* 49C00 */
+	0x08,  0x00,  0x09,  0xFF,  0x08,  0x10,  0x08,  0x10,  0x3F,  0x2C,  0x29,  0x46,  0x29,  0xF9,  0x29,  0x00, 	/* 49C10 */
+	0x3F,  0x10,  0x08,  0x10,  0x0A,  0x7E,  0x09,  0x10,  0x0B,  0x10,  0x1C,  0x90,  0x60,  0xFF,  0x00,  0x80, 	/* 49C20 */
+	0xAE,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0x20,  0x12,  0x28,  0x12,  0x24,  0x24,  0xA2,  0x48, 	/* 49C30 */
+	0x82,  0x1F,  0xF8,  0x10,  0x88,  0x10,  0x88,  0x1F,  0xF8,  0x00,  0x88,  0x00,  0x84,  0x01,  0xFE,  0x7E, 	/* 49C40 */
+	0x02,  0xAF,  0x08,  0x22,  0x08,  0x22,  0x08,  0xFE,  0x08,  0x24,  0x3F,  0x24,  0x29,  0x28,  0x29,  0xFF, 	/* 49C50 */
+	0x29,  0x10,  0x3F,  0x20,  0x08,  0x64,  0x0C,  0xA8,  0x0B,  0x30,  0x0A,  0x20,  0x0F,  0x22,  0x71,  0x22, 	/* 49C60 */
+	0x00,  0x1E,  0xB8,  0x08,  0x10,  0x08,  0x92,  0x08,  0x52,  0x08,  0x54,  0x3F,  0x10,  0x29,  0x7E,  0x29, 	/* 49C70 */
+	0x42,  0x29,  0x42,  0x3F,  0x7E,  0x28,  0x42,  0x0C,  0x42,  0x0A,  0x7E,  0x09,  0x42,  0x0F,  0x42,  0x71, 	/* 49C80 */
+	0x42,  0x00,  0x46,  0xB9,  0x08,  0x00,  0x09,  0xFE,  0x08,  0x44,  0x08,  0x28,  0x3F,  0x10,  0x29,  0xFE, 	/* 49C90 */
+	0x29,  0x92,  0x29,  0x92,  0x3F,  0xFE,  0x08,  0x92,  0x0C,  0x92,  0x0A,  0xFE,  0x0A,  0x92,  0x0F,  0x92, 	/* 49CA0 */
+	0x71,  0x92,  0x00,  0x96,  0xBB,  0x08,  0x58,  0x08,  0x48,  0x08,  0x44,  0x08,  0x84,  0x3E,  0xFE,  0x2B, 	/* 49CB0 */
+	0x85,  0x2A,  0x84,  0x2A,  0x84,  0x3E,  0xFC,  0x08,  0x28,  0x0C,  0x28,  0x0A,  0x28,  0x0A,  0x48,  0x0F, 	/* 49CC0 */
+	0x49,  0x71,  0x89,  0x01,  0x07,  0xBE,  0x08,  0x28,  0x08,  0x48,  0x09,  0xCC,  0x3E,  0x4A,  0x2A,  0x4A, 	/* 49CD0 */
+	0x2B,  0xFF,  0x2A,  0x48,  0x2A,  0x4A,  0x3E,  0x4A,  0x08,  0x64,  0x0D,  0xC4,  0x0A,  0x4C,  0x0A,  0x4D, 	/* 49CE0 */
+	0x1F,  0x53,  0x61,  0x63,  0x00,  0xC1,  0x80,  0x00,  0x00,  0x3F,  0xFE,  0x22,  0x22,  0x22,  0x22,  0x3F, 	/* 49CF0 */
+	0xFE,  0x08,  0x00,  0x0F,  0xFE,  0x11,  0x02,  0x2F,  0xE2,  0x49,  0x22,  0x09,  0x22,  0x0F,  0xE2,  0x01, 	/* 49D00 */
+	0x12,  0x01,  0xEA,  0x3F,  0x04,  0x00,  0x18,  0x82,  0x08,  0x20,  0x08,  0x3C,  0x08,  0x44,  0x3E,  0xA8, 	/* 49D10 */
+	0x2B,  0x10,  0x2A,  0x28,  0x2A,  0xD4,  0x2B,  0x13,  0x3F,  0xFE,  0x08,  0x10,  0x0C,  0xFC,  0x0A,  0x10, 	/* 49D20 */
+	0x0B,  0xFF,  0x0E,  0x10,  0x71,  0x10,  0x01,  0x10,  0x83,  0x00,  0x00,  0x1F,  0xFE,  0x10,  0x00,  0x17, 	/* 49D30 */
+	0xFC,  0x10,  0x00,  0x1F,  0xFF,  0x12,  0x44,  0x23,  0xA8,  0x2E,  0x18,  0x40,  0x87,  0x0F,  0xF8,  0x08, 	/* 49D40 */
+	0x88,  0x0F,  0xF8,  0x00,  0x8C,  0x00,  0xFA,  0x3F,  0x81,  0x86,  0x08,  0x00,  0x08,  0x7E,  0x08,  0x42, 	/* 49D50 */
+	0x08,  0x42,  0x3F,  0x7E,  0x29,  0x42,  0x29,  0x42,  0x29,  0x7E,  0x3F,  0x42,  0x08,  0x42,  0x0C,  0x7E, 	/* 49D60 */
+	0x0A,  0x18,  0x0A,  0x28,  0x0F,  0x29,  0x71,  0x49,  0x00,  0x87,  0x88,  0x08,  0x00,  0x08,  0x5E,  0x08, 	/* 49D70 */
+	0x52,  0x08,  0x52,  0x3F,  0x52,  0x29,  0x5E,  0x29,  0x40,  0x29,  0x40,  0x3F,  0x7E,  0x08,  0x02,  0x0C, 	/* 49D80 */
+	0x12,  0x0A,  0xFF,  0x0A,  0x10,  0x0F,  0x28,  0x71,  0x44,  0x00,  0x83,  0x89,  0x08,  0x04,  0x08,  0x18, 	/* 49D90 */
+	0x08,  0xE4,  0x08,  0x52,  0x3F,  0x49,  0x29,  0x89,  0x29,  0x00,  0x29,  0x7C,  0x3F,  0x04,  0x08,  0x08, 	/* 49DA0 */
+	0x0C,  0x10,  0x0B,  0xFF,  0x0A,  0x10,  0x0D,  0x10,  0x71,  0x10,  0x00,  0x30,  0x8A,  0x08,  0x12,  0x08, 	/* 49DB0 */
+	0x62,  0x09,  0xCA,  0x08,  0x4A,  0x3E,  0x4A,  0x2B,  0xFA,  0x2A,  0x4A,  0x2A,  0x4A,  0x3E,  0xEA,  0x08, 	/* 49DC0 */
+	0xDA,  0x0D,  0x4A,  0x0D,  0x4A,  0x0A,  0x42,  0x0E,  0x42,  0x72,  0x42,  0x00,  0x46,  0x8D,  0x08,  0x10, 	/* 49DD0 */
+	0x08,  0x10,  0x08,  0x28,  0x08,  0x28,  0x3F,  0x44,  0x29,  0x82,  0x29,  0x7D,  0x29,  0x10,  0x3F,  0x10, 	/* 49DE0 */
+	0x09,  0xFF,  0x0C,  0x10,  0x0A,  0x54,  0x0A,  0x54,  0x0F,  0x92,  0x71,  0x12,  0x00,  0x30,  0x91,  0x00, 	/* 49DF0 */
+	0x02,  0x7D,  0xFC,  0x08,  0x10,  0x10,  0x9E,  0x3C,  0x90,  0x04,  0x90,  0x15,  0xFE,  0x0E,  0x00,  0x11, 	/* 49E00 */
+	0xFF,  0x60,  0x80,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x84,  0x00,  0xFE,  0x7F,  0x01,  0x92, 	/* 49E10 */
+	0x08,  0x01,  0x0B,  0xC6,  0x08,  0x5C,  0x3E,  0x44,  0x2A,  0x84,  0x2A,  0x94,  0x2B,  0xD7,  0x2A,  0x54, 	/* 49E20 */
+	0x3E,  0x54,  0x09,  0x54,  0x0D,  0x54,  0x0A,  0x94,  0x0A,  0x9F,  0x0E,  0xC0,  0x71,  0x30,  0x02,  0x0F, 	/* 49E30 */
+	0x98,  0x11,  0x00,  0x11,  0x00,  0x11,  0x1E,  0x13,  0xF2,  0x7C,  0x92,  0x54,  0x92,  0x54,  0x92,  0x57, 	/* 49E40 */
+	0xF2,  0x7C,  0x92,  0x10,  0x92,  0x18,  0x92,  0x15,  0x52,  0x15,  0x5E,  0x1A,  0x20,  0x64,  0x20,  0x08, 	/* 49E50 */
+	0x00,  0x9A,  0x02,  0x20,  0x7E,  0x3F,  0x02,  0x20,  0x3E,  0x3E,  0x03,  0x20,  0x0E,  0x3F,  0x74,  0x20, 	/* 49E60 */
+	0x08,  0xA0,  0x10,  0x80,  0x0F,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x84,  0x00,  0xFA, 	/* 49E70 */
+	0x7F,  0x01,  0x9C,  0x01,  0x00,  0x01,  0x00,  0x7F,  0xFE,  0x41,  0x02,  0x44,  0xA2,  0x24,  0x48,  0x25, 	/* 49E80 */
+	0x94,  0x46,  0x12,  0x1B,  0xF2,  0x61,  0x00,  0x1F,  0xF0,  0x11,  0x10,  0x1F,  0xF0,  0x01,  0x18,  0x01, 	/* 49E90 */
+	0xF4,  0x7E,  0x02,  0xA5,  0x08,  0x42,  0x08,  0x4C,  0x08,  0x48,  0x08,  0x48,  0x3F,  0xF8,  0x2A,  0x4F, 	/* 49EA0 */
+	0x2A,  0xCA,  0x2A,  0xEA,  0x3E,  0xDA,  0x09,  0x4A,  0x0D,  0x4A,  0x0A,  0x4A,  0x0A,  0x52,  0x0F,  0x52, 	/* 49EB0 */
+	0x71,  0x62,  0x00,  0x42,  0xA9,  0x08,  0x00,  0x08,  0xFE,  0x08,  0x82,  0x08,  0x92,  0x3E,  0xFE,  0x2A, 	/* 49EC0 */
+	0x92,  0x2A,  0x92,  0x2A,  0xFE,  0x3E,  0x92,  0x08,  0xBA,  0x0C,  0xAA,  0x0A,  0xAA,  0x0A,  0xBA,  0x0F, 	/* 49ED0 */
+	0x02,  0x71,  0x02,  0x02,  0x06,  0xB4,  0x08,  0x00,  0x08,  0x7C,  0x08,  0x44,  0x3F,  0x44,  0x29,  0x7C, 	/* 49EE0 */
+	0x29,  0x44,  0x29,  0x44,  0x29,  0x7C,  0x3F,  0x20,  0x08,  0x7E,  0x0C,  0xAA,  0x0A,  0x2A,  0x0A,  0x52, 	/* 49EF0 */
+	0x0F,  0x92,  0x79,  0x22,  0x00,  0x4C,  0xB7,  0x08,  0x54,  0x08,  0x52,  0x08,  0x92,  0x09,  0x7E,  0x3E, 	/* 49F00 */
+	0x10,  0x2A,  0x28,  0x2A,  0xFF,  0x2A,  0x28,  0x3E,  0x44,  0x08,  0xFA,  0x0D,  0x49,  0x0A,  0x48,  0x0A, 	/* 49F10 */
+	0x78,  0x0F,  0x42,  0x71,  0x42,  0x00,  0x3E,  0xBB,  0x08,  0x10,  0x08,  0x10,  0x08,  0xFF,  0x08,  0x10, 	/* 49F20 */
+	0x3F,  0x7E,  0x29,  0x10,  0x29,  0xFF,  0x29,  0x00,  0x3F,  0x7E,  0x08,  0x52,  0x0C,  0x52,  0x0A,  0x7E, 	/* 49F30 */
+	0x0A,  0x42,  0x0F,  0x42,  0x71,  0x42,  0x00,  0x46,  0xBF,  0x08,  0x10,  0x08,  0x10,  0x09,  0xFF,  0x09, 	/* 49F40 */
+	0x01,  0x3F,  0x41,  0x2A,  0x40,  0x2A,  0x6E,  0x2A,  0xAA,  0x3E,  0xAA,  0x08,  0xAA,  0x0D,  0x6A,  0x0A, 	/* 49F50 */
+	0x4E,  0x0A,  0x48,  0x0D,  0x49,  0x71,  0x89,  0x01,  0x07,  0x89,  0x08,  0x22,  0x08,  0x92,  0x08,  0x54, 	/* 49F60 */
+	0x08,  0x7E,  0x3F,  0x52,  0x29,  0x52,  0x29,  0x7E,  0x29,  0x52,  0x3F,  0x52,  0x08,  0x7E,  0x0C,  0x10, 	/* 49F70 */
+	0x0A,  0x10,  0x09,  0xFF,  0x0F,  0x10,  0x70,  0x90,  0x00,  0x10,  0x8B,  0x08,  0x42,  0x09,  0x22,  0x08, 	/* 49F80 */
+	0xA4,  0x08,  0x88,  0x3E,  0xFC,  0x2A,  0xA4,  0x2A,  0xA4,  0x2A,  0xFC,  0x3E,  0xA4,  0x08,  0xA4,  0x0C, 	/* 49F90 */
+	0xFC,  0x0A,  0xA4,  0x0A,  0xA4,  0x0D,  0x25,  0x71,  0x25,  0x02,  0x23,  0x8C,  0x08,  0x22,  0x08,  0x42, 	/* 49FA0 */
+	0x09,  0xD2,  0x08,  0x4A,  0x3E,  0x4A,  0x2B,  0xE2,  0x2A,  0x52,  0x2A,  0x4A,  0x3E,  0xEA,  0x08,  0xD3, 	/* 49FB0 */
+	0x0D,  0x46,  0x0A,  0x5A,  0x0A,  0x42,  0x0F,  0x42,  0x71,  0x42,  0x00,  0x42,  0x8E,  0x08,  0x00,  0x08, 	/* 49FC0 */
+	0x7C,  0x08,  0x44,  0x08,  0x7C,  0x3F,  0x44,  0x29,  0x44,  0x29,  0x7C,  0x29,  0x20,  0x3F,  0x7E,  0x08, 	/* 49FD0 */
+	0xD2,  0x0D,  0x52,  0x0A,  0x5A,  0x0A,  0x66,  0x0F,  0x7A,  0x71,  0x02,  0x00,  0x0C,  0x93,  0x08,  0x70, 	/* 49FE0 */
+	0x08,  0x10,  0x08,  0x28,  0x08,  0x44,  0x3E,  0xFA,  0x2B,  0x01,  0x2A,  0xEA,  0x2A,  0xAA,  0x3E,  0xAA, 	/* 49FF0 */
+	0x08,  0xF4,  0x0C,  0xB4,  0x0A,  0xB4,  0x0A,  0xEA,  0x0F,  0xAA,  0x71,  0xAA,  0x00,  0xAA,  0x95,  0x08, 	/* 4A000 */
+	0x10,  0x08,  0x10,  0x14,  0x10,  0x12,  0xFE,  0x29,  0x92,  0x7E,  0x92,  0x22,  0x92,  0x3E,  0x92,  0x22, 	/* 4A010 */
+	0xFE,  0x22,  0x10,  0x3E,  0x18,  0x28,  0x14,  0x24,  0x12,  0x2E,  0x1E,  0x32,  0x71,  0x61,  0x81,  0x97, 	/* 4A020 */
+	0x08,  0x10,  0x08,  0x20,  0x08,  0x7C,  0x08,  0x44,  0x3F,  0x7C,  0x29,  0x44,  0x29,  0x44,  0x29,  0x7C, 	/* 4A030 */
+	0x3F,  0x00,  0x08,  0xFF,  0x0C,  0x10,  0x0A,  0x7E,  0x0A,  0x10,  0x0F,  0x10,  0x71,  0xFF,  0x00,  0x00, 	/* 4A040 */
+	0x99,  0x08,  0x00,  0x09,  0xFF,  0x08,  0x00,  0x3E,  0xFC,  0x2A,  0x84,  0x2A,  0x84,  0x2A,  0xFC,  0x2A, 	/* 4A050 */
+	0x80,  0x3E,  0xFE,  0x08,  0xAA,  0x09,  0xAA,  0x0D,  0xFE,  0x0A,  0xAA,  0x0E,  0xAA,  0x72,  0xAA,  0x00, 	/* 4A060 */
+	0x86,  0x9F,  0x08,  0x00,  0x08,  0xFF,  0x08,  0x91,  0x08,  0xFF,  0x3F,  0x91,  0x29,  0x91,  0x29,  0xFF, 	/* 4A070 */
+	0x29,  0x00,  0x3F,  0x7E,  0x08,  0x42,  0x0C,  0x7E,  0x0A,  0x42,  0x0A,  0x7E,  0x0F,  0x42,  0x71,  0x42, 	/* 4A080 */
+	0x00,  0x46,  0xA0,  0x08,  0x00,  0x09,  0xFF,  0x08,  0x00,  0x08,  0x7C,  0x3F,  0x44,  0x29,  0x7C,  0x29, 	/* 4A090 */
+	0x00,  0x29,  0x00,  0x3F,  0xFE,  0x08,  0x92,  0x0C,  0x92,  0x0A,  0xFE,  0x0A,  0x92,  0x0F,  0x92,  0x71, 	/* 4A0A0 */
+	0xFE,  0x01,  0x00,  0xA3,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x0B,  0xEF,  0x3E,  0x90,  0x2A,  0xA0, 	/* 4A0B0 */
+	0x2A,  0x9F,  0x2A,  0xE2,  0x3E,  0xA4,  0x08,  0xA4,  0x0C,  0xBF,  0x0A,  0xA4,  0x0B,  0x24,  0x0D,  0x24, 	/* 4A0C0 */
+	0x72,  0x24,  0x00,  0xCC,  0xA6,  0x08,  0x00,  0x08,  0xEE,  0x08,  0xA2,  0x08,  0xA2,  0x3E,  0xA2,  0x2A, 	/* 4A0D0 */
+	0xEE,  0x2A,  0x80,  0x2A,  0x9E,  0x3E,  0xEA,  0x08,  0x8A,  0x08,  0x8A,  0x0C,  0xE4,  0x0A,  0x84,  0x0E, 	/* 4A0E0 */
+	0x8A,  0x72,  0x92,  0x01,  0xA1,  0xA8,  0x00,  0x00,  0x7F,  0xF8,  0x02,  0x08,  0x02,  0x08,  0x7F,  0xE5, 	/* 4A0F0 */
+	0x04,  0x05,  0x18,  0x03,  0x60,  0x11,  0x08,  0x10,  0x3E,  0x7C,  0x2A,  0x54,  0x2A,  0x54,  0x3E,  0x7C, 	/* 4A100 */
+	0x0A,  0x14,  0x0D,  0x1A,  0x70,  0xE1,  0xAA,  0x08,  0x00,  0x08,  0xFC,  0x08,  0x84,  0x3E,  0xFC,  0x2A, 	/* 4A110 */
+	0x84,  0x2A,  0x84,  0x2A,  0xFC,  0x2A,  0x00,  0x3F,  0xFF,  0x08,  0x40,  0x08,  0xFE,  0x0D,  0x2A,  0x0A, 	/* 4A120 */
+	0x4A,  0x0D,  0x92,  0x71,  0x22,  0x00,  0x4C,  0xAE,  0x08,  0x40,  0x08,  0x40,  0x08,  0x7F,  0x08,  0x80, 	/* 4A130 */
+	0x3F,  0x7C,  0x29,  0x44,  0x29,  0x7C,  0x29,  0x44,  0x3F,  0x7C,  0x08,  0x20,  0x0C,  0x7C,  0x0A,  0xC4, 	/* 4A140 */
+	0x0B,  0x28,  0x0D,  0x18,  0x71,  0x64,  0x01,  0x83,  0xB4,  0x08,  0x40,  0x08,  0x4E,  0x08,  0x4A,  0x08, 	/* 4A150 */
+	0x4A,  0x3F,  0xFA,  0x2A,  0x4E,  0x2A,  0x4A,  0x2A,  0x4A,  0x3E,  0xEA,  0x08,  0xAE,  0x08,  0xAA,  0x0C, 	/* 4A160 */
+	0xAA,  0x0A,  0xEA,  0x1E,  0x12,  0x71,  0x12,  0x01,  0x26,  0xB6,  0x08,  0x54,  0x08,  0x54,  0x09,  0xFF, 	/* 4A170 */
+	0x3E,  0x54,  0x2A,  0x54,  0x2A,  0x5C,  0x2A,  0x40,  0x2A,  0x7E,  0x3E,  0x10,  0x09,  0xFF,  0x0C,  0x18, 	/* 4A180 */
+	0x0A,  0x34,  0x0A,  0x52,  0x0F,  0x91,  0x71,  0x10,  0x01,  0x10,  0xB8,  0x08,  0x00,  0x08,  0x7C,  0x08, 	/* 4A190 */
+	0x44,  0x08,  0x5C,  0x3F,  0x54,  0x29,  0x54,  0x29,  0x54,  0x29,  0xFE,  0x3F,  0x82,  0x08,  0xBA,  0x0C, 	/* 4A1A0 */
+	0xAA,  0x0A,  0xAA,  0x0A,  0xBA,  0x0F,  0x82,  0x71,  0x82,  0x00,  0x86,  0xBF,  0x08,  0x00,  0x08,  0xFE, 	/* 4A1B0 */
+	0x08,  0x92,  0x08,  0xFE,  0x3E,  0x92,  0x2A,  0x92,  0x2A,  0xFE,  0x2A,  0x10,  0x3E,  0xFE,  0x08,  0x92, 	/* 4A1C0 */
+	0x0C,  0xFE,  0x0A,  0x92,  0x0A,  0x92,  0x0F,  0xFE,  0x71,  0x11,  0x01,  0x0F,  0x82,  0x08,  0x40,  0x08, 	/* 4A1D0 */
+	0x4E,  0x08,  0xEA,  0x08,  0xAA,  0x3E,  0xAA,  0x2A,  0xEC,  0x2A,  0xAC,  0x2A,  0xAA,  0x3E,  0xEA,  0x08, 	/* 4A1E0 */
+	0x9A,  0x0C,  0xDA,  0x0C,  0xAA,  0x0A,  0xAE,  0x0E,  0xD8,  0x73,  0x18,  0x00,  0x08,  0x8D,  0x00,  0x10, 	/* 4A1F0 */
+	0x7F,  0x10,  0x00,  0x10,  0x3E,  0x7E,  0x22,  0x52,  0x3E,  0x52,  0x00,  0x52,  0x7F,  0x52,  0x55,  0x7E, 	/* 4A200 */
+	0x55,  0x10,  0x63,  0x10,  0x5D,  0x14,  0x49,  0x12,  0x49,  0x1E,  0x49,  0xE1,  0x4B,  0x01,  0x9F,  0x08, 	/* 4A210 */
+	0x00,  0x09,  0xFF,  0x09,  0x01,  0x08,  0x7D,  0x3F,  0x44,  0x29,  0x44,  0x29,  0x7C,  0x29,  0x44,  0x3F, 	/* 4A220 */
+	0x44,  0x08,  0x7C,  0x0C,  0x10,  0x0B,  0xFF,  0x0A,  0x00,  0x0D,  0x44,  0x71,  0x42,  0x00,  0x82,  0xA2, 	/* 4A230 */
+	0x08,  0x10,  0x2A,  0x54,  0x2A,  0x54,  0x54,  0xA8,  0x22,  0x44,  0x40,  0x80,  0x7F,  0xFE,  0x40,  0x02, 	/* 4A240 */
+	0x41,  0x02,  0x1F,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x1F,  0xF8,  0x01,  0x08,  0x01,  0xFC,  0x7F,  0x02, 	/* 4A250 */
+	0xAB,  0x04,  0x10,  0x3F,  0x90,  0x04,  0x1F,  0x7F,  0xA2,  0x0A,  0x22,  0x2B,  0x54,  0x4A,  0x88,  0x12, 	/* 4A260 */
+	0x14,  0x26,  0x63,  0x00,  0x80,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x84,  0x00,  0xFE,  0x7F, 	/* 4A270 */
+	0x01,  0xAF,  0x04,  0x10,  0x04,  0x10,  0x3F,  0xBF,  0x04,  0x24,  0x7F,  0xD4,  0x04,  0x14,  0x0F,  0x88, 	/* 4A280 */
+	0x10,  0x94,  0x23,  0x62,  0x00,  0x81,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x84,  0x00,  0xFE, 	/* 4A290 */
+	0x7F,  0x01,  0xB3,  0x08,  0x92,  0x08,  0x52,  0x08,  0x54,  0x09,  0xFF,  0x3F,  0x01,  0x2B,  0x7D,  0x2A, 	/* 4A2A0 */
+	0x44,  0x2A,  0x44,  0x3E,  0x7C,  0x08,  0x10,  0x0C,  0x10,  0x0A,  0xFE,  0x0A,  0x10,  0x0F,  0x10,  0x71, 	/* 4A2B0 */
+	0xFF,  0x00,  0x00,  0xBA,  0x08,  0x00,  0x08,  0xFE,  0x08,  0x92,  0x3E,  0xFE,  0x2A,  0x92,  0x2A,  0xFE, 	/* 4A2C0 */
+	0x2A,  0x10,  0x2A,  0x24,  0x3E,  0xE8,  0x08,  0x18,  0x0C,  0x26,  0x0B,  0xFD,  0x0A,  0x94,  0x0E,  0x92, 	/* 4A2D0 */
+	0x71,  0x12,  0x00,  0x10,  0xBB,  0x08,  0x10,  0x08,  0x7E,  0x08,  0x52,  0x08,  0xFF,  0x3F,  0x52,  0x29, 	/* 4A2E0 */
+	0x7E,  0x29,  0x10,  0x29,  0x7E,  0x3F,  0x52,  0x08,  0x7E,  0x0C,  0x10,  0x0A,  0xFF,  0x0A,  0x24,  0x0F, 	/* 4A2F0 */
+	0x68,  0x71,  0x1C,  0x00,  0xE2,  0xBD,  0x00,  0x80,  0x01,  0xF8,  0x07,  0x10,  0x38,  0xA0,  0x01,  0xC0, 	/* 4A300 */
+	0x07,  0x38,  0x78,  0xC7,  0x00,  0x20,  0x0B,  0xD0,  0x08,  0x30,  0x3E,  0x7C,  0x2A,  0x54,  0x3E,  0x7C, 	/* 4A310 */
+	0x0A,  0x14,  0x0F,  0x1E,  0x70,  0xE1,  0x80,  0x08,  0x08,  0x08,  0x08,  0x08,  0xFF,  0x08,  0x08,  0x3F, 	/* 4A320 */
+	0x52,  0x29,  0xB5,  0x29,  0x0C,  0x29,  0x4A,  0x3F,  0x95,  0x08,  0x7E,  0x0C,  0x08,  0x0A,  0xFF,  0x09, 	/* 4A330 */
+	0x08,  0x0F,  0x08,  0x70,  0x88,  0x00,  0x08,  0x84,  0x04,  0x10,  0x3F,  0x10,  0x04,  0x7C,  0x7F,  0x94, 	/* 4A340 */
+	0x11,  0x74,  0x7F,  0xA4,  0x04,  0x54,  0x3F,  0x95,  0x04,  0x83,  0x00,  0x80,  0x1F,  0xF8,  0x10,  0x88, 	/* 4A350 */
+	0x1F,  0xF8,  0x00,  0x84,  0x00,  0xFE,  0x7F,  0x01,  0x86,  0x08,  0x24,  0x08,  0x24,  0x09,  0xFF,  0x08, 	/* 4A360 */
+	0x24,  0x3F,  0x24,  0x29,  0x7E,  0x29,  0x42,  0x29,  0x7E,  0x3F,  0x42,  0x08,  0x7E,  0x0C,  0x10,  0x0B, 	/* 4A370 */
+	0xFF,  0x0A,  0x18,  0x0F,  0x24,  0x71,  0x42,  0x01,  0x81,  0x87,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x20, 	/* 4A380 */
+	0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x01,  0x00,  0x7F,  0xFF,  0x04,  0x90, 	/* 4A390 */
+	0x1F,  0xFC,  0x64,  0x93,  0x07,  0xF0,  0x00,  0x8C,  0x3F,  0xF2,  0x8B,  0x08,  0x02,  0x08,  0x7C,  0x08, 	/* 4A3A0 */
+	0x92,  0x08,  0x54,  0x3F,  0xFF,  0x29,  0x38,  0x29,  0x54,  0x29,  0x92,  0x3F,  0x11,  0x08,  0x20,  0x0C, 	/* 4A3B0 */
+	0x10,  0x0A,  0xAA,  0x0A,  0xA9,  0x0E,  0xA1,  0x71,  0x25,  0x00,  0x1C,  0x90,  0x08,  0x92,  0x08,  0x52, 	/* 4A3C0 */
+	0x08,  0x54,  0x09,  0xFF,  0x3F,  0x01,  0x2B,  0x7D,  0x2A,  0x44,  0x2A,  0x44,  0x3E,  0x7C,  0x08,  0x10, 	/* 4A3D0 */
+	0x0C,  0xFE,  0x0A,  0x92,  0x0A,  0x92,  0x0F,  0x9C,  0x71,  0x10,  0x00,  0x10,  0x92,  0x08,  0x24,  0x08, 	/* 4A3E0 */
+	0x24,  0x09,  0xFF,  0x08,  0x24,  0x3E,  0x10,  0x2A,  0xFF,  0x2A,  0x18,  0x2A,  0x24,  0x3E,  0xC3,  0x08, 	/* 4A3F0 */
+	0x24,  0x0C,  0x24,  0x0B,  0xFF,  0x0A,  0x24,  0x0D,  0x24,  0x71,  0x44,  0x00,  0x84,  0xA0,  0x08,  0x02, 	/* 4A400 */
+	0x08,  0x0C,  0x09,  0xF0,  0x08,  0x92,  0x3E,  0x54,  0x2A,  0xFF,  0x2A,  0x34,  0x2A,  0x52,  0x3E,  0x91, 	/* 4A410 */
+	0x09,  0xFE,  0x0C,  0x92,  0x0A,  0xFE,  0x0A,  0x92,  0x0F,  0x92,  0x71,  0xFE,  0x00,  0x80,  0xAF,  0x08, 	/* 4A420 */
+	0x10,  0x08,  0x7C,  0x08,  0x10,  0x08,  0xFE,  0x3E,  0x00,  0x2A,  0x44,  0x2B,  0xFF,  0x2A,  0x44,  0x3E, 	/* 4A430 */
+	0x74,  0x09,  0x9F,  0x0C,  0x00,  0x0A,  0xFF,  0x0A,  0x28,  0x0F,  0x29,  0x71,  0x49,  0x01,  0x87,  0xB2, 	/* 4A440 */
+	0x00,  0x80,  0x0F,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x90,  0x00,  0xFC,  0x3F,  0x02, 	/* 4A450 */
+	0x08,  0x10,  0x3E,  0x7C,  0x2A,  0x54,  0x2A,  0x54,  0x3E,  0x7C,  0x09,  0x14,  0x0E,  0x9A,  0x70,  0xE1, 	/* 4A460 */
+	0xB6,  0x08,  0x00,  0x09,  0xF0,  0x08,  0xAF,  0x08,  0xE9,  0x3E,  0xA9,  0x2A,  0xE9,  0x2A,  0xAF,  0x2B, 	/* 4A470 */
+	0xE0,  0x3E,  0x22,  0x08,  0xFC,  0x0C,  0x10,  0x0A,  0x7C,  0x0A,  0x10,  0x0D,  0x10,  0x71,  0xFF,  0x00, 	/* 4A480 */
+	0x00,  0xB7,  0x08,  0x92,  0x08,  0x52,  0x08,  0x54,  0x09,  0xFF,  0x3F,  0x01,  0x2B,  0x7D,  0x2A,  0x44, 	/* 4A490 */
+	0x2A,  0x7C,  0x3E,  0x00,  0x08,  0xFE,  0x0C,  0x92,  0x0A,  0xFE,  0x0A,  0x92,  0x0F,  0x92,  0x71,  0xFE, 	/* 4A4A0 */
+	0x00,  0x00,  0xB9,  0x10,  0x00,  0x1E,  0xFE,  0x24,  0x22,  0x7F,  0x46,  0x29,  0xA8,  0x3F,  0x3E,  0x29, 	/* 4A4B0 */
+	0x48,  0x3F,  0xFF,  0x21,  0x08,  0x43,  0x08,  0x1F,  0xF0,  0x11,  0x10,  0x1F,  0xF0,  0x01,  0x08,  0x01, 	/* 4A4C0 */
+	0xFC,  0x7E,  0x02,  0xBB,  0x08,  0x44,  0x08,  0x28,  0x08,  0xFE,  0x08,  0x10,  0x3E,  0xFE,  0x2A,  0x10, 	/* 4A4D0 */
+	0x2B,  0xFF,  0x2A,  0x2C,  0x3F,  0xCA,  0x08,  0x48,  0x0D,  0xFF,  0x0A,  0x4A,  0x0A,  0x6A,  0x0F,  0xC5, 	/* 4A4E0 */
+	0x79,  0x4B,  0x00,  0xD1,  0xBE,  0x08,  0x20,  0x08,  0x3C,  0x08,  0x48,  0x09,  0xFF,  0x3E,  0x94,  0x2A, 	/* 4A4F0 */
+	0xE3,  0x2A,  0x9C,  0x2A,  0x80,  0x3E,  0xFF,  0x08,  0x80,  0x0C,  0x9C,  0x0A,  0x80,  0x0A,  0xBE,  0x0D, 	/* 4A500 */
+	0x22,  0x71,  0x3E,  0x02,  0x00,  0x85,  0x08,  0x00,  0x08,  0xFE,  0x08,  0xAA,  0x3E,  0xAA,  0x2A,  0xEE, 	/* 4A510 */
+	0x2A,  0x28,  0x2A,  0x68,  0x2A,  0xAE,  0x3E,  0xAA,  0x08,  0xAA,  0x0C,  0xEE,  0x0A,  0xAA,  0x0A,  0xAA, 	/* 4A520 */
+	0x0F,  0xEE,  0x71,  0x21,  0x00,  0x1F,  0x8D,  0x10,  0x08,  0x11,  0xC8,  0x11,  0x48,  0x11,  0xCF,  0x7D, 	/* 4A530 */
+	0x55,  0x55,  0x56,  0x55,  0xE4,  0x54,  0x84,  0x7D,  0xE4,  0x11,  0x24,  0x1B,  0x64,  0x15,  0xAA,  0x15, 	/* 4A540 */
+	0x2A,  0x1E,  0xF2,  0x62,  0x22,  0x00,  0xC1,  0x8E,  0x08,  0x24,  0x08,  0x24,  0x09,  0xFF,  0x08,  0x24, 	/* 4A550 */
+	0x3E,  0x10,  0x2A,  0xFF,  0x2A,  0x18,  0x2A,  0x64,  0x3F,  0x93,  0x08,  0x3C,  0x0C,  0x54,  0x0A,  0x44, 	/* 4A560 */
+	0x0B,  0xFF,  0x0D,  0x44,  0x71,  0x44,  0x00,  0x84,  0x8F,  0x08,  0x40,  0x08,  0x7F,  0x08,  0xA5,  0x09, 	/* 4A570 */
+	0x45,  0x3F,  0xF5,  0x2B,  0x59,  0x2B,  0x53,  0x2B,  0xF0,  0x3F,  0x5A,  0x09,  0x5F,  0x09,  0xFA,  0x0D, 	/* 4A580 */
+	0x12,  0x0B,  0x1F,  0x0D,  0x12,  0x71,  0x12,  0x02,  0x32,  0x91,  0x08,  0x44,  0x08,  0x55,  0x09,  0x55, 	/* 4A590 */
+	0x09,  0x6A,  0x3E,  0xA9,  0x2B,  0x10,  0x2B,  0xFF,  0x2B,  0x01,  0x3E,  0x10,  0x09,  0xFF,  0x0C,  0x10, 	/* 4A5A0 */
+	0x0A,  0x38,  0x0A,  0x54,  0x0D,  0x92,  0x71,  0x11,  0x00,  0x10,  0x95,  0x08,  0x00,  0x08,  0xFE,  0x08, 	/* 4A5B0 */
+	0x08,  0x08,  0xFF,  0x3E,  0x89,  0x2A,  0xED,  0x2A,  0x89,  0x2A,  0x6C,  0x2A,  0x00,  0x3F,  0xFF,  0x08, 	/* 4A5C0 */
+	0x10,  0x0C,  0xFE,  0x0A,  0xAA,  0x0E,  0xAA,  0x71,  0xAA,  0x00,  0x86,  0x96,  0x08,  0x24,  0x08,  0xFF, 	/* 4A5D0 */
+	0x08,  0x24,  0x08,  0x48,  0x3E,  0x7F,  0x2A,  0xC8,  0x2B,  0x7E,  0x2A,  0x48,  0x3E,  0x7E,  0x08,  0x48, 	/* 4A5E0 */
+	0x0C,  0x7F,  0x0A,  0x00,  0x0A,  0xFE,  0x0F,  0x24,  0x71,  0x18,  0x00,  0xE7,  0xA1,  0x02,  0x00,  0x03, 	/* 4A5F0 */
+	0xF0,  0x04,  0x20,  0x7F,  0xFF,  0x03,  0x08,  0x1C,  0xB0,  0x03,  0x50,  0x1C,  0xCC,  0x03,  0x43,  0x3C, 	/* 4A600 */
+	0xC0,  0x08,  0x10,  0x3E,  0x7C,  0x2A,  0x54,  0x3E,  0x7C,  0x0B,  0x16,  0x7E,  0xFD,  0xA2,  0x00,  0x80, 	/* 4A610 */
+	0x3F,  0xFE,  0x01,  0x00,  0x1F,  0xFC,  0x02,  0x20,  0x7F,  0xFF,  0x04,  0x10,  0x1F,  0xFC,  0x64,  0x13, 	/* 4A620 */
+	0x07,  0xF0,  0x08,  0x10,  0x3E,  0x7C,  0x2A,  0x54,  0x3E,  0x7C,  0x0B,  0x16,  0x7E,  0xFD,  0xA3,  0x08, 	/* 4A630 */
+	0x00,  0x08,  0xFF,  0x08,  0xA4,  0x08,  0xFF,  0x3E,  0xA4,  0x2A,  0xBE,  0x2A,  0xAA,  0x2A,  0xBE,  0x3E, 	/* 4A640 */
+	0xAA,  0x08,  0xBE,  0x0C,  0x88,  0x0A,  0xFF,  0x0A,  0xCB,  0x1D,  0x5D,  0x61,  0x41,  0x02,  0x43,  0xA7, 	/* 4A650 */
+	0x01,  0x00,  0x7F,  0xFE,  0x01,  0x00,  0x1F,  0xF8,  0x00,  0x00,  0x7F,  0xFE,  0x42,  0x02,  0x0F,  0xF8, 	/* 4A660 */
+	0x74,  0x08,  0x07,  0xF8,  0x08,  0x10,  0x3F,  0x7C,  0x29,  0x54,  0x3F,  0x7C,  0x0B,  0x16,  0x7C,  0xF9, 	/* 4A670 */
+	0xB1,  0x00,  0x80,  0x07,  0xF0,  0x04,  0x90,  0x07,  0xF0,  0x00,  0x88,  0x1F,  0xF4,  0x3E,  0x7C,  0x2A, 	/* 4A680 */
+	0x54,  0x3E,  0x7C,  0x0B,  0x16,  0x7E,  0xFD,  0x00,  0x00,  0x1F,  0xFC,  0x12,  0x44,  0x7F,  0xFF,  0x00, 	/* 4A690 */
+	0x00,  0xB6,  0x00,  0x00,  0x3F,  0x7E,  0x12,  0x24,  0x7F,  0xFF,  0x0A,  0x14,  0x13,  0x25,  0x6F,  0xF3, 	/* 4A6A0 */
+	0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x3E,  0x7C,  0x2A,  0x54,  0x3E,  0x7C,  0x0B,  0x16, 	/* 4A6B0 */
+	0x7E,  0xFD,  0xB9,  0x00,  0x80,  0x3F,  0xFC,  0x00,  0x80,  0x0F,  0xF8,  0x08,  0x88,  0x7F,  0xFE,  0x42, 	/* 4A6C0 */
+	0x02,  0x0F,  0xF8,  0x34,  0x08,  0x07,  0xF8,  0x08,  0x10,  0x3E,  0x7C,  0x2A,  0x54,  0x3E,  0x7C,  0x09, 	/* 4A6D0 */
+	0x16,  0x7E,  0xFD,  0xBB,  0x11,  0x04,  0x13,  0xE4,  0x68,  0x1A,  0x13,  0xC4,  0x28,  0x0A,  0x7F,  0xDF, 	/* 4A6E0 */
+	0x10,  0x04,  0x57,  0xD5,  0x56,  0x55,  0x13,  0xC4,  0x00,  0x80,  0x1F,  0xF8,  0x10,  0x88,  0x1F,  0xF8, 	/* 4A6F0 */
+	0x00,  0x86,  0x7F,  0xF9,  0x80,  0x01,  0x00,  0x01,  0x00,  0x02,  0x00,  0x1F,  0xFC,  0x12,  0x44,  0x12, 	/* 4A700 */
+	0x44,  0x12,  0x44,  0x12,  0x44,  0x12,  0x44,  0x12,  0x44,  0x12,  0x44,  0x12,  0x44,  0x12,  0x44,  0x7F, 	/* 4A710 */
+	0xFF,  0x00,  0x00,  0x00,  0x00,  0x82,  0x04,  0x00,  0x04,  0xFE,  0x08,  0x12,  0x3F,  0x92,  0x2A,  0x92, 	/* 4A720 */
+	0x2A,  0xD2,  0x2A,  0xB2,  0x2A,  0x92,  0x2A,  0x9A,  0x2A,  0x96,  0x2A,  0xE3,  0x2B,  0x22,  0x3C,  0x42, 	/* 4A730 */
+	0x60,  0x82,  0x01,  0x02,  0x02,  0x0C,  0x84,  0x04,  0x00,  0x04,  0x7E,  0x08,  0x12,  0x3F,  0x92,  0x2A, 	/* 4A740 */
+	0x92,  0x2A,  0x92,  0x2A,  0x92,  0x2A,  0xFF,  0x2A,  0x92,  0x2A,  0x92,  0x2A,  0xD2,  0x2B,  0x12,  0x3C, 	/* 4A750 */
+	0x12,  0x60,  0x12,  0x00,  0xFF,  0x00,  0x00,  0x86,  0x00,  0x80,  0x01,  0x00,  0x1F,  0xFC,  0x12,  0x24, 	/* 4A760 */
+	0x12,  0x24,  0x7F,  0xFF,  0x00,  0x20,  0x04,  0x44,  0x09,  0x84,  0x36,  0xA8,  0x00,  0x90,  0x04,  0x88, 	/* 4A770 */
+	0x08,  0x84,  0x10,  0x83,  0x60,  0x80,  0x00,  0x80,  0x8C,  0x04,  0x00,  0x04,  0xFE,  0x08,  0x00,  0x08, 	/* 4A780 */
+	0x00,  0x12,  0x00,  0x22,  0x00,  0x05,  0xFF,  0x04,  0x08,  0x08,  0x08,  0x18,  0x08,  0x28,  0x08,  0x48, 	/* 4A790 */
+	0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x18,  0x8D,  0x08,  0x00,  0x08,  0x9E,  0x10,  0x40, 	/* 4A7A0 */
+	0x14,  0x40,  0x24,  0x00,  0x49,  0x3F,  0x08,  0x84,  0x10,  0x84,  0x10,  0x04,  0x30,  0x44,  0x50,  0x84, 	/* 4A7B0 */
+	0x10,  0x84,  0x11,  0x04,  0x11,  0x04,  0x12,  0x04,  0x12,  0x0C,  0x92,  0x08,  0x80,  0x08,  0x9F,  0x10, 	/* 4A7C0 */
+	0x80,  0x17,  0xF0,  0x24,  0x80,  0x44,  0x9F,  0x08,  0x84,  0x0F,  0x24,  0x11,  0x44,  0x30,  0xC4,  0x50, 	/* 4A7D0 */
+	0x84,  0x10,  0xC4,  0x11,  0x24,  0x12,  0x64,  0x17,  0x94,  0x10,  0x0C,  0x93,  0x08,  0x80,  0x08,  0xDE, 	/* 4A7E0 */
+	0x10,  0xA0,  0x14,  0xA0,  0x24,  0x80,  0x47,  0xFF,  0x08,  0x84,  0x08,  0xC4,  0x12,  0xA4,  0x32,  0xA4, 	/* 4A7F0 */
+	0x52,  0x94,  0x12,  0x94,  0x12,  0x94,  0x14,  0x84,  0x10,  0x84,  0x10,  0x8C,  0x97,  0x09,  0x00,  0x09, 	/* 4A800 */
+	0x1E,  0x17,  0xE0,  0x11,  0x00,  0x21,  0x00,  0x49,  0x00,  0x0F,  0xFF,  0x11,  0x04,  0x11,  0x04,  0x37, 	/* 4A810 */
+	0xE4,  0x51,  0x04,  0x11,  0x04,  0x11,  0x64,  0x13,  0x84,  0x1C,  0x04,  0x10,  0x0C,  0x99,  0x08,  0x00, 	/* 4A820 */
+	0x0F,  0xEE,  0x10,  0x80,  0x10,  0x80,  0x27,  0xC0,  0x49,  0x5F,  0x09,  0x44,  0x11,  0x44,  0x17,  0xF4, 	/* 4A830 */
+	0x30,  0x04,  0x53,  0xE4,  0x12,  0x24,  0x12,  0x24,  0x12,  0x24,  0x13,  0xE4,  0x10,  0x0C,  0x9B,  0x09, 	/* 4A840 */
+	0x00,  0x0B,  0xEE,  0x11,  0x20,  0x11,  0x20,  0x27,  0xF0,  0x44,  0x00,  0x0B,  0xFF,  0x0A,  0x24,  0x13, 	/* 4A850 */
+	0xE4,  0x30,  0x44,  0x57,  0xF4,  0x11,  0x44,  0x11,  0x44,  0x17,  0xF4,  0x10,  0x44,  0x10,  0x4C,  0x9D, 	/* 4A860 */
+	0x08,  0x60,  0x0B,  0x9E,  0x10,  0x80,  0x17,  0xF0,  0x20,  0x80,  0x4B,  0xE0,  0x0A,  0xBF,  0x13,  0xE4, 	/* 4A870 */
+	0x12,  0xA4,  0x33,  0xE4,  0x50,  0x84,  0x13,  0xE4,  0x10,  0x84,  0x10,  0xF4,  0x17,  0x04,  0x10,  0x0C, 	/* 4A880 */
+	0x9E,  0x08,  0x80,  0x0B,  0xEE,  0x11,  0x20,  0x17,  0xF0,  0x20,  0x00,  0x4B,  0xFF,  0x0A,  0x24,  0x13, 	/* 4A890 */
+	0xE4,  0x10,  0x04,  0x37,  0xF4,  0x50,  0x84,  0x13,  0xE4,  0x12,  0xA4,  0x12,  0xA4,  0x12,  0xE4,  0x10, 	/* 4A8A0 */
+	0x8C,  0xA1,  0x09,  0x00,  0x09,  0xDE,  0x12,  0x40,  0x14,  0x80,  0x23,  0xE0,  0x4A,  0xBF,  0x0B,  0xE4, 	/* 4A8B0 */
+	0x12,  0xA4,  0x12,  0xA4,  0x33,  0xE4,  0x50,  0x84,  0x17,  0xF4,  0x10,  0xC4,  0x11,  0x24,  0x12,  0x24, 	/* 4A8C0 */
+	0x14,  0x0C,  0xA2,  0x17,  0x70,  0x15,  0x5E,  0x27,  0x70,  0x25,  0x50,  0x4F,  0x70,  0x0D,  0x5F,  0x17, 	/* 4A8D0 */
+	0x74,  0x12,  0x44,  0x37,  0xF4,  0x5C,  0x84,  0x17,  0xE4,  0x14,  0x84,  0x17,  0xE4,  0x14,  0x84,  0x17, 	/* 4A8E0 */
+	0xF4,  0x10,  0x0C,  0xA3,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x80, 	/* 4A8F0 */
+	0x02,  0x84,  0x02,  0x44,  0x04,  0x48,  0x1C,  0x30,  0x64,  0x20,  0x04,  0x10,  0x04,  0x08,  0x05,  0xC4, 	/* 4A900 */
+	0x0E,  0x02,  0x30,  0x01,  0xA8,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x1F, 	/* 4A910 */
+	0xFC,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0x84,  0x0C,  0x48,  0x74,  0x50,  0x04,  0x20,  0x04, 	/* 4A920 */
+	0x10,  0x07,  0x0C,  0x38,  0x03,  0xAB,  0x08,  0x08,  0x08,  0x08,  0x08,  0x10,  0x7E,  0x20,  0x02,  0xC4, 	/* 4A930 */
+	0x04,  0x04,  0x04,  0x08,  0x09,  0x10,  0x1A,  0x22,  0x2C,  0xC2,  0x4A,  0x04,  0x09,  0x04,  0x08,  0x08, 	/* 4A940 */
+	0x08,  0x10,  0x08,  0x60,  0x09,  0x80,  0xB0,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x00,  0x0F, 	/* 4A950 */
+	0xF8,  0x08,  0x08,  0x7F,  0xFF,  0x08,  0x08,  0x0F,  0xFC,  0x02,  0x84,  0x06,  0x88,  0x1A,  0x50,  0x62, 	/* 4A960 */
+	0x20,  0x02,  0x10,  0x03,  0x8C,  0x1C,  0x03,  0xB2,  0x08,  0x70,  0x08,  0x10,  0x08,  0x10,  0x7E,  0x10, 	/* 4A970 */
+	0x02,  0xFE,  0x04,  0x92,  0x04,  0x92,  0x0A,  0x92,  0x1A,  0xAA,  0x2C,  0xAA,  0x4A,  0xC6,  0x09,  0x82, 	/* 4A980 */
+	0x08,  0x82,  0x08,  0x82,  0x08,  0x82,  0x08,  0x86,  0xB5,  0x08,  0x00,  0x08,  0x7E,  0x08,  0x42,  0x7E, 	/* 4A990 */
+	0x42,  0x02,  0x42,  0x04,  0x42,  0x08,  0x42,  0x09,  0x7E,  0x1A,  0x42,  0x2C,  0x42,  0x4A,  0x42,  0x09, 	/* 4A9A0 */
+	0x42,  0x08,  0x42,  0x08,  0x42,  0x08,  0x7E,  0x08,  0x00,  0xB7,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF, 	/* 4A9B0 */
+	0x00,  0x80,  0x0F,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x0F,  0xFC,  0x02,  0x84,  0x06,  0x48, 	/* 4A9C0 */
+	0x1A,  0x50,  0x62,  0x20,  0x02,  0x10,  0x03,  0x8C,  0x1C,  0x03,  0xBD,  0x08,  0x02,  0x08,  0x0C,  0x08, 	/* 4A9D0 */
+	0xF0,  0x7E,  0x10,  0x02,  0x10,  0x04,  0x10,  0x08,  0x10,  0x09,  0xFF,  0x1A,  0x10,  0x2C,  0x10,  0x4A, 	/* 4A9E0 */
+	0x10,  0x09,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0xFE,  0x08,  0x00,  0xBE,  0x00,  0x80,  0x01,  0x40, 	/* 4A9F0 */
+	0x02,  0x20,  0x0C,  0x18,  0x77,  0xE7,  0x00,  0x00,  0x1F,  0xF8,  0x00,  0x10,  0x00,  0xA0,  0x00,  0x80, 	/* 4AA00 */
+	0x7F,  0xFF,  0x02,  0x44,  0x0C,  0x28,  0x74,  0x10,  0x07,  0x8C,  0x3C,  0x03,  0xBF,  0x08,  0x10,  0x08, 	/* 4AA10 */
+	0x10,  0x08,  0x28,  0x7E,  0x28,  0x02,  0x44,  0x05,  0x82,  0x05,  0x7D,  0x09,  0x00,  0x1E,  0x00,  0x2A, 	/* 4AA20 */
+	0x7C,  0x49,  0x04,  0x08,  0x04,  0x08,  0x08,  0x08,  0x08,  0x08,  0x10,  0x08,  0x20,  0x81,  0x00,  0x80, 	/* 4AA30 */
+	0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08, 	/* 4AA40 */
+	0x0F,  0xFA,  0x01,  0x42,  0x06,  0x24,  0x1C,  0x28,  0x64,  0x10,  0x07,  0x8C,  0x1C,  0x03,  0x82,  0x08, 	/* 4AA50 */
+	0x20,  0x08,  0x20,  0x08,  0x20,  0x7E,  0xFC,  0x02,  0x24,  0x04,  0x24,  0x04,  0x24,  0x0A,  0x24,  0x1B, 	/* 4AA60 */
+	0xFF,  0x2C,  0x20,  0x4A,  0x30,  0x09,  0x50,  0x08,  0x48,  0x08,  0x84,  0x09,  0x02,  0x0A,  0x01,  0x88, 	/* 4AA70 */
+	0x04,  0x00,  0x04,  0x3E,  0x7F,  0xA2,  0x04,  0xA2,  0x08,  0xA2,  0x08,  0xA2,  0x13,  0x3E,  0x20,  0x80, 	/* 4AA80 */
+	0x00,  0x80,  0x7F,  0xFF,  0x02,  0x84,  0x0C,  0x48,  0x74,  0x30,  0x04,  0x10,  0x07,  0x8C,  0x3C,  0x03, 	/* 4AA90 */
+	0x8B,  0x04,  0x28,  0x04,  0x24,  0x0B,  0xFE,  0x18,  0x20,  0x28,  0x20,  0x48,  0x12,  0x08,  0x0A,  0x08, 	/* 4AAA0 */
+	0x86,  0x00,  0x82,  0x7F,  0xFF,  0x02,  0x88,  0x04,  0x48,  0x1C,  0x30,  0x64,  0x90,  0x07,  0x0C,  0x38, 	/* 4AAB0 */
+	0x03,  0x8D,  0x08,  0x40,  0x08,  0x40,  0x08,  0x7E,  0x7E,  0x82,  0x02,  0x82,  0x04,  0xF2,  0x05,  0x92, 	/* 4AAC0 */
+	0x08,  0x92,  0x1A,  0x92,  0x2C,  0xF2,  0x4A,  0x8C,  0x08,  0x80,  0x08,  0x80,  0x08,  0x81,  0x08,  0x41, 	/* 4AAD0 */
+	0x08,  0x3F,  0x92,  0x08,  0x00,  0x08,  0x7C,  0x08,  0x44,  0x7E,  0x44,  0x02,  0x44,  0x04,  0x44,  0x04, 	/* 4AAE0 */
+	0x7C,  0x09,  0x44,  0x1A,  0x44,  0x2C,  0x44,  0x4A,  0x44,  0x09,  0x7C,  0x08,  0x00,  0x08,  0x00,  0x09, 	/* 4AAF0 */
+	0xFF,  0x08,  0x00,  0x96,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x7E,  0x10,  0x02,  0xFE,  0x04,  0x92, 	/* 4AB00 */
+	0x04,  0x92,  0x09,  0x92,  0x1E,  0x92,  0x2A,  0xFE,  0x49,  0x92,  0x08,  0x92,  0x08,  0x92,  0x08,  0x92, 	/* 4AB10 */
+	0x08,  0xFE,  0x08,  0x00,  0x97,  0x08,  0x10,  0x08,  0x10,  0x08,  0x28,  0x7E,  0x28,  0x02,  0x44,  0x04, 	/* 4AB20 */
+	0x8A,  0x05,  0x11,  0x08,  0x20,  0x1A,  0xC4,  0x2C,  0x08,  0x4A,  0x30,  0x08,  0xC2,  0x08,  0x04,  0x08, 	/* 4AB30 */
+	0x18,  0x08,  0x60,  0x09,  0x80,  0x99,  0x08,  0x10,  0x08,  0x10,  0x08,  0x20,  0x7E,  0x7E,  0x02,  0x42, 	/* 4AB40 */
+	0x04,  0x42,  0x08,  0x42,  0x09,  0x42,  0x1A,  0x7E,  0x2C,  0x42,  0x4A,  0x42,  0x09,  0x42,  0x08,  0x42, 	/* 4AB50 */
+	0x08,  0x42,  0x08,  0x7E,  0x08,  0x00,  0x9E,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0xF0,  0x04, 	/* 4AB60 */
+	0x10,  0x18,  0x0C,  0x6F,  0xFB,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xFA,  0x01,  0x42,  0x06,  0x44,  0x1C, 	/* 4AB70 */
+	0x28,  0x64,  0x10,  0x07,  0x8C,  0x1C,  0x03,  0xA2,  0x08,  0x10,  0x08,  0x10,  0x08,  0x54,  0x7E,  0x52, 	/* 4AB80 */
+	0x02,  0x92,  0x04,  0x10,  0x04,  0xFE,  0x08,  0x10,  0x1A,  0x10,  0x2C,  0x10,  0x4B,  0xFF,  0x09,  0x10, 	/* 4AB90 */
+	0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0xA4,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x1F, 	/* 4ABA0 */
+	0xF8,  0x03,  0x20,  0x00,  0xC0,  0x7F,  0xFE,  0x01,  0x44,  0x06,  0x48,  0x38,  0xC0,  0x00,  0x84,  0x03, 	/* 4ABB0 */
+	0x44,  0x0C,  0x28,  0x74,  0x10,  0x07,  0x8C,  0x3C,  0x03,  0xAB,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10, 	/* 4ABC0 */
+	0x7E,  0xFE,  0x02,  0x92,  0x04,  0x94,  0x05,  0x90,  0x0A,  0xFC,  0x1C,  0xC4,  0x2A,  0xA4,  0x49,  0xA8, 	/* 4ABD0 */
+	0x08,  0x98,  0x09,  0x18,  0x09,  0x24,  0x0A,  0x42,  0x09,  0x81,  0xAE,  0x08,  0x40,  0x08,  0x40,  0x08, 	/* 4ABE0 */
+	0x40,  0x7E,  0x7F,  0x02,  0x88,  0x04,  0x88,  0x05,  0x08,  0x08,  0x2C,  0x1A,  0x2A,  0x2C,  0x2A,  0x4A, 	/* 4ABF0 */
+	0x49,  0x08,  0x49,  0x08,  0x88,  0x08,  0x08,  0x08,  0x08,  0x08,  0x18,  0xB0,  0x00,  0x00,  0x0F,  0xF8, 	/* 4AC00 */
+	0x08,  0x88,  0x08,  0x48,  0x7F,  0xFF,  0x11,  0x08,  0x10,  0x88,  0x1F,  0xFE,  0x00,  0x08,  0x00,  0xB0, 	/* 4AC10 */
+	0x7F,  0xFF,  0x01,  0x44,  0x06,  0x28,  0x7C,  0x10,  0x07,  0x8C,  0x38,  0x03,  0xB1,  0x10,  0x48,  0x10, 	/* 4AC20 */
+	0x4A,  0x10,  0x49,  0x7C,  0x89,  0x04,  0x88,  0x09,  0xFF,  0x0A,  0x88,  0x10,  0x88,  0x34,  0x88,  0x58, 	/* 4AC30 */
+	0x94,  0x14,  0x94,  0x12,  0x94,  0x10,  0xA4,  0x10,  0xA2,  0x10,  0xC2,  0x10,  0x81,  0xB4,  0x08,  0x10, 	/* 4AC40 */
+	0x08,  0x10,  0x09,  0xFF,  0x7E,  0x28,  0x02,  0x24,  0x04,  0x42,  0x05,  0xFD,  0x09,  0x00,  0x1E,  0xFE, 	/* 4AC50 */
+	0x2A,  0x10,  0x49,  0x10,  0x09,  0x3E,  0x08,  0x22,  0x08,  0x02,  0x08,  0x02,  0x08,  0x0C,  0xB5,  0x10, 	/* 4AC60 */
+	0x42,  0x10,  0x4C,  0x10,  0x78,  0x7C,  0x88,  0x04,  0x88,  0x09,  0x88,  0x0A,  0x88,  0x10,  0xFF,  0x1A, 	/* 4AC70 */
+	0x88,  0x34,  0x88,  0x52,  0x88,  0x10,  0x88,  0x10,  0x88,  0x10,  0x88,  0x10,  0xBF,  0x10,  0x80,  0xB7, 	/* 4AC80 */
+	0x08,  0x10,  0x08,  0x10,  0x08,  0x30,  0x7E,  0x28,  0x02,  0x48,  0x04,  0x44,  0x04,  0x84,  0x0A,  0xFA, 	/* 4AC90 */
+	0x1B,  0x01,  0x2C,  0x00,  0x4A,  0xFC,  0x09,  0x84,  0x08,  0x84,  0x08,  0x84,  0x08,  0xFC,  0x08,  0x00, 	/* 4ACA0 */
+	0xBF,  0x08,  0x10,  0x08,  0x10,  0x08,  0xFE,  0x7E,  0x10,  0x02,  0x10,  0x04,  0x10,  0x04,  0xFF,  0x09, 	/* 4ACB0 */
+	0x00,  0x1A,  0x10,  0x2C,  0x10,  0x4A,  0xFE,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x09,  0xFF,  0x08, 	/* 4ACC0 */
+	0x00,  0x81,  0x04,  0x20,  0x04,  0x24,  0x3F,  0xA2,  0x04,  0x22,  0x04,  0x20,  0x7F,  0xFF,  0x04,  0x20, 	/* 4ACD0 */
+	0x7F,  0xA2,  0x08,  0x12,  0x14,  0x94,  0x35,  0x14,  0x52,  0x08,  0x11,  0x1A,  0x14,  0xA6,  0x18,  0x46, 	/* 4ACE0 */
+	0x30,  0x82,  0x82,  0x00,  0x02,  0x3F,  0xD2,  0x04,  0x12,  0x07,  0x92,  0x08,  0x92,  0x35,  0x12,  0x02, 	/* 4ACF0 */
+	0x12,  0x0C,  0x02,  0x70,  0x86,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x88,  0x06,  0x50,  0x7C,  0x20,  0x07, 	/* 4AD00 */
+	0x18,  0x18,  0x07,  0x83,  0x08,  0x10,  0x08,  0x10,  0x08,  0x1E,  0x7E,  0x10,  0x02,  0x10,  0x04,  0xFF, 	/* 4AD10 */
+	0x04,  0x00,  0x09,  0x00,  0x1A,  0xFF,  0x2C,  0x10,  0x4A,  0x10,  0x09,  0x1C,  0x08,  0x12,  0x08,  0x10, 	/* 4AD20 */
+	0x08,  0x10,  0x08,  0x10,  0x84,  0x10,  0x40,  0x10,  0x5E,  0x10,  0x80,  0x7C,  0x80,  0x05,  0x00,  0x08, 	/* 4AD30 */
+	0x40,  0x08,  0x7F,  0x12,  0x84,  0x34,  0x84,  0x59,  0x84,  0x16,  0x84,  0x14,  0x84,  0x10,  0x84,  0x10, 	/* 4AD40 */
+	0x84,  0x10,  0x84,  0x10,  0x8C,  0x85,  0x04,  0x20,  0x24,  0x20,  0x17,  0xFE,  0x14,  0x20,  0x04,  0x20, 	/* 4AD50 */
+	0x1C,  0x20,  0x65,  0xFC,  0x04,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0x48,  0x0C,  0x48,  0x74,  0x30, 	/* 4AD60 */
+	0x04,  0x10,  0x07,  0x8C,  0x38,  0x03,  0x8F,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x00,  0x0F,  0xF8,  0x08, 	/* 4AD70 */
+	0x88,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x02, 	/* 4AD80 */
+	0x42,  0x7C,  0x24,  0x07,  0x98,  0x1C,  0x07,  0x94,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x44, 	/* 4AD90 */
+	0x0E,  0x28,  0x74,  0x10,  0x07,  0x8C,  0x3C,  0x03,  0x00,  0x00,  0x3F,  0xFE,  0x22,  0x22,  0x24,  0x3E, 	/* 4ADA0 */
+	0x3B,  0xE2,  0x22,  0x22,  0x23,  0xE2,  0x20,  0x06,  0x95,  0x08,  0x48,  0x08,  0x44,  0x08,  0x44,  0x7E, 	/* 4ADB0 */
+	0x92,  0x02,  0x92,  0x04,  0x28,  0x05,  0x28,  0x09,  0x44,  0x1E,  0x82,  0x2A,  0x7D,  0x49,  0x44,  0x08, 	/* 4ADC0 */
+	0x44,  0x08,  0x44,  0x08,  0x44,  0x08,  0x7C,  0x08,  0x00,  0x98,  0x00,  0x90,  0x00,  0x88,  0x7F,  0xFF, 	/* 4ADD0 */
+	0x10,  0x84,  0x08,  0xC8,  0x09,  0xA0,  0x06,  0x98,  0x38,  0x87,  0x01,  0x80,  0x00,  0x80,  0x7F,  0xFF, 	/* 4ADE0 */
+	0x01,  0x44,  0x0E,  0x28,  0x74,  0x10,  0x07,  0x8C,  0x3C,  0x03,  0x99,  0x08,  0x00,  0x08,  0xFC,  0x08, 	/* 4ADF0 */
+	0x24,  0x7E,  0x24,  0x03,  0xFF,  0x04,  0x24,  0x04,  0x24,  0x08,  0xFC,  0x1A,  0x40,  0x2C,  0x40,  0x4A, 	/* 4AE00 */
+	0xFE,  0x08,  0xC2,  0x09,  0x42,  0x0A,  0x42,  0x08,  0x7E,  0x08,  0x00,  0x9C,  0x08,  0x14,  0x08,  0x12, 	/* 4AE10 */
+	0x09,  0xFF,  0x7E,  0x10,  0x02,  0x10,  0x04,  0xFE,  0x04,  0x92,  0x09,  0x92,  0x1A,  0xFE,  0x2C,  0x92, 	/* 4AE20 */
+	0x4A,  0x92,  0x09,  0xFE,  0x08,  0x92,  0x08,  0x92,  0x08,  0x92,  0x08,  0x86,  0x9D,  0x22,  0x10,  0x22, 	/* 4AE30 */
+	0x10,  0x3F,  0xFF,  0x02,  0x10,  0x7E,  0x10,  0x12,  0x10,  0x12,  0xFE,  0x22,  0x80,  0x00,  0x80,  0x7F, 	/* 4AE40 */
+	0xFF,  0x01,  0x84,  0x06,  0x48,  0x7C,  0x30,  0x04,  0x10,  0x07,  0x8C,  0x3C,  0x03,  0x9F,  0x30,  0x20, 	/* 4AE50 */
+	0x08,  0xA8,  0x00,  0xA4,  0x61,  0x22,  0x12,  0x2A,  0x00,  0x68,  0x0C,  0x10,  0x30,  0x60,  0x43,  0x80, 	/* 4AE60 */
+	0x00,  0x80,  0x7F,  0xFF,  0x02,  0x88,  0x0C,  0x50,  0x74,  0x20,  0x07,  0x18,  0x38,  0x07,  0xA1,  0x08, 	/* 4AE70 */
+	0x00,  0x08,  0xFE,  0x08,  0x92,  0x7E,  0x92,  0x02,  0xFE,  0x04,  0x92,  0x08,  0x92,  0x09,  0xFE,  0x1A, 	/* 4AE80 */
+	0x10,  0x2C,  0x10,  0x4A,  0xFE,  0x09,  0x10,  0x08,  0x10,  0x08,  0x10,  0x0B,  0xFF,  0x08,  0x00,  0xA8, 	/* 4AE90 */
+	0x08,  0x08,  0x08,  0x10,  0x08,  0xFE,  0x7E,  0x92,  0x02,  0x92,  0x04,  0xFE,  0x04,  0x92,  0x08,  0x92, 	/* 4AEA0 */
+	0x1A,  0xFE,  0x2C,  0x28,  0x4A,  0x48,  0x09,  0xFF,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08, 	/* 4AEB0 */
+	0xB2,  0x08,  0x00,  0x0B,  0xFF,  0x08,  0x10,  0x7E,  0x10,  0x03,  0xFE,  0x05,  0x12,  0x05,  0x12,  0x09, 	/* 4AEC0 */
+	0xDE,  0x1B,  0x56,  0x2D,  0x56,  0x4B,  0x56,  0x09,  0xBA,  0x09,  0x12,  0x09,  0x12,  0x09,  0x12,  0x09, 	/* 4AED0 */
+	0x16,  0xB3,  0x11,  0x08,  0x09,  0x10,  0x7F,  0xFE,  0x40,  0x02,  0x4F,  0xF2,  0x08,  0x10,  0x08,  0x10, 	/* 4AEE0 */
+	0x0F,  0xF0,  0x01,  0x00,  0x7F,  0xFE,  0x02,  0x84,  0x04,  0x88,  0x1C,  0x50,  0x64,  0x20,  0x07,  0x18, 	/* 4AEF0 */
+	0x38,  0x06,  0xB4,  0x02,  0x20,  0x02,  0x20,  0x7E,  0x3F,  0x02,  0x20,  0x3E,  0x3E,  0x03,  0x20,  0x7C, 	/* 4AF00 */
+	0x3F,  0x04,  0x20,  0x08,  0xA0,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0x84,  0x0C,  0x48,  0x74,  0x30,  0x07, 	/* 4AF10 */
+	0x98,  0x3C,  0x07,  0xB8,  0x08,  0x00,  0x08,  0xFE,  0x08,  0x92,  0x7E,  0x92,  0x02,  0xFE,  0x04,  0x92, 	/* 4AF20 */
+	0x04,  0x92,  0x0A,  0xFE,  0x1A,  0x10,  0x2D,  0xFF,  0x4A,  0x38,  0x09,  0x54,  0x08,  0x92,  0x0B,  0x11, 	/* 4AF30 */
+	0x08,  0x10,  0x08,  0x10,  0xB9,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x88,  0x0F, 	/* 4AF40 */
+	0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x09,  0x48,  0x32,  0x44,  0x0C,  0x2B,  0x74, 	/* 4AF50 */
+	0x10,  0x07,  0xCC,  0x1C,  0x03,  0xBC,  0x08,  0x00,  0x08,  0xFC,  0x08,  0x84,  0x7E,  0x84,  0x02,  0xFC, 	/* 4AF60 */
+	0x04,  0x84,  0x04,  0x84,  0x0A,  0xFC,  0x1A,  0x40,  0x2C,  0x7E,  0x4A,  0xAA,  0x09,  0x2A,  0x08,  0x52, 	/* 4AF70 */
+	0x08,  0x92,  0x08,  0x22,  0x08,  0x4C,  0xBD,  0x14,  0x04,  0x1F,  0xA4,  0x24,  0x24,  0x3F,  0xA4,  0x44, 	/* 4AF80 */
+	0x24,  0x3F,  0xA4,  0x24,  0xA4,  0x25,  0x8C,  0x04,  0x80,  0x7F,  0xFF,  0x02,  0x88,  0x0C,  0x50,  0x74, 	/* 4AF90 */
+	0x20,  0x04,  0x10,  0x0F,  0x0C,  0x30,  0x03,  0xBE,  0x10,  0x00,  0x10,  0xFE,  0x10,  0x82,  0x7C,  0x82, 	/* 4AFA0 */
+	0x04,  0xFE,  0x08,  0x90,  0x0A,  0x90,  0x12,  0xFF,  0x1C,  0x90,  0x34,  0x90,  0x52,  0xFE,  0x10,  0xC2, 	/* 4AFB0 */
+	0x11,  0x42,  0x11,  0x42,  0x12,  0x7E,  0x10,  0x00,  0x82,  0x10,  0x44,  0x10,  0x44,  0x11,  0xF4,  0x7C, 	/* 4AFC0 */
+	0x44,  0x04,  0x44,  0x08,  0x44,  0x0B,  0xFE,  0x10,  0x05,  0x14,  0x45,  0x38,  0x44,  0x55,  0xF4,  0x10, 	/* 4AFD0 */
+	0x44,  0x10,  0x5C,  0x10,  0x64,  0x13,  0x84,  0x10,  0x04,  0x84,  0x08,  0x10,  0x08,  0x10,  0x09,  0xFF, 	/* 4AFE0 */
+	0x7E,  0x10,  0x02,  0xFE,  0x04,  0x12,  0x05,  0xFF,  0x0A,  0x12,  0x1A,  0xFE,  0x2C,  0x10,  0x4B,  0xFF, 	/* 4AFF0 */
+	0x0A,  0x24,  0x08,  0x44,  0x08,  0x78,  0x08,  0x1C,  0x09,  0xE2,  0x87,  0x08,  0x40,  0x08,  0x40,  0x08, 	/* 4B000 */
+	0x7F,  0x7E,  0x80,  0x03,  0x7C,  0x04,  0x44,  0x04,  0x7C,  0x09,  0x44,  0x0A,  0x7C,  0x1C,  0x20,  0x2A, 	/* 4B010 */
+	0x7C,  0x48,  0xC4,  0x0B,  0x28,  0x08,  0x18,  0x08,  0x64,  0x09,  0x83,  0x8A,  0x08,  0x00,  0x09,  0xFF, 	/* 4B020 */
+	0x08,  0x00,  0x7E,  0xFE,  0x02,  0x82,  0x04,  0x82,  0x0A,  0xFE,  0x0A,  0x80,  0x1C,  0xFE,  0x2B,  0xAA, 	/* 4B030 */
+	0x49,  0xAA,  0x0A,  0xFE,  0x0A,  0xAA,  0x0C,  0xAA,  0x08,  0xAA,  0x08,  0x86,  0x8C,  0x08,  0x00,  0x09, 	/* 4B040 */
+	0xFF,  0x09,  0x01,  0x7F,  0x11,  0x02,  0xFE,  0x04,  0x10,  0x04,  0xFE,  0x0A,  0x92,  0x1A,  0xFE,  0x2C, 	/* 4B050 */
+	0x92,  0x4A,  0x92,  0x09,  0xFE,  0x08,  0x10,  0x09,  0xFF,  0x08,  0x10,  0x08,  0x10,  0x90,  0x08,  0x00, 	/* 4B060 */
+	0x08,  0xFC,  0x08,  0x84,  0x7E,  0xFC,  0x02,  0x84,  0x04,  0x84,  0x04,  0xFC,  0x0A,  0x20,  0x1A,  0x3E, 	/* 4B070 */
+	0x2C,  0x4A,  0x4A,  0xD2,  0x0B,  0x62,  0x08,  0x4A,  0x08,  0x3A,  0x08,  0x02,  0x08,  0x0C,  0x92,  0x00, 	/* 4B080 */
+	0x80,  0x00,  0x80,  0x7F,  0xFF,  0x04,  0xFC,  0x04,  0x84,  0x08,  0xFC,  0x18,  0x20,  0x2B,  0xFF,  0x48, 	/* 4B090 */
+	0xEC,  0x0B,  0x23,  0x08,  0x20,  0x02,  0x88,  0x04,  0x50,  0x7C,  0x20,  0x07,  0x98,  0x1C,  0x07,  0x93, 	/* 4B0A0 */
+	0x10,  0x40,  0x10,  0x7E,  0x10,  0x62,  0x7C,  0xA2,  0x04,  0xA2,  0x09,  0xBE,  0x09,  0x88,  0x16,  0x88, 	/* 4B0B0 */
+	0x34,  0xFF,  0x58,  0x9C,  0x14,  0x9C,  0x12,  0xAA,  0x10,  0xCA,  0x10,  0x89,  0x10,  0x88,  0x10,  0x88, 	/* 4B0C0 */
+	0x9D,  0x09,  0x22,  0x08,  0x92,  0x08,  0x94,  0x7E,  0xFC,  0x02,  0xA4,  0x04,  0xA4,  0x04,  0xFC,  0x0A, 	/* 4B0D0 */
+	0xA4,  0x1A,  0xA4,  0x2C,  0xFC,  0x4A,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x08,  0x20,  0x08,  0x20,  0x08, 	/* 4B0E0 */
+	0x20,  0x9E,  0x08,  0x00,  0x08,  0xFC,  0x08,  0xA4,  0x7E,  0xA4,  0x02,  0xB4,  0x04,  0xCC,  0x04,  0x84, 	/* 4B0F0 */
+	0x0A,  0xFC,  0x1A,  0x00,  0x2D,  0xFE,  0x4B,  0x4A,  0x09,  0x4A,  0x09,  0x4A,  0x09,  0x4A,  0x0B,  0xFF, 	/* 4B100 */
+	0x08,  0x00,  0xA5,  0x08,  0x00,  0x08,  0xFF,  0x08,  0x80,  0x7E,  0xBE,  0x02,  0x80,  0x04,  0xFF,  0x04, 	/* 4B110 */
+	0xA9,  0x08,  0xAA,  0x1A,  0xA4,  0x2C,  0xBA,  0x4A,  0xE5,  0x09,  0x04,  0x09,  0xFF,  0x0A,  0x44,  0x0C, 	/* 4B120 */
+	0x24,  0x08,  0x0C,  0xAA,  0x10,  0x00,  0x11,  0x3E,  0x10,  0xA2,  0x7C,  0xA2,  0x06,  0x3E,  0x09,  0x22, 	/* 4B130 */
+	0x09,  0x22,  0x14,  0x3E,  0x37,  0xA9,  0x58,  0xAA,  0x14,  0xA4,  0x10,  0xA4,  0x10,  0xB2,  0x11,  0x41, 	/* 4B140 */
+	0x12,  0x30,  0x14,  0x0F,  0xAB,  0x08,  0x02,  0x08,  0x1C,  0x08,  0xE8,  0x7E,  0x8E,  0x02,  0x88,  0x04, 	/* 4B150 */
+	0xBF,  0x04,  0xAA,  0x0A,  0xAC,  0x1A,  0xB9,  0x2C,  0xA7,  0x4A,  0xAC,  0x08,  0xAC,  0x09,  0x4C,  0x09, 	/* 4B160 */
+	0x55,  0x0A,  0x55,  0x08,  0xA3,  0xB6,  0x08,  0x00,  0x0B,  0xEF,  0x08,  0xA5,  0x7F,  0x7B,  0x02,  0xA5, 	/* 4B170 */
+	0x05,  0x29,  0x04,  0x63,  0x08,  0x10,  0x1A,  0x20,  0x2C,  0xFE,  0x4A,  0x82,  0x08,  0x82,  0x08,  0xFE, 	/* 4B180 */
+	0x08,  0x82,  0x08,  0xFE,  0x08,  0x00,  0xB8,  0x08,  0x10,  0x08,  0xFE,  0x08,  0x92,  0x7F,  0xFF,  0x02, 	/* 4B190 */
+	0x92,  0x04,  0xFE,  0x04,  0x10,  0x0A,  0xFE,  0x1A,  0x92,  0x2C,  0xFE,  0x4A,  0x10,  0x09,  0xFF,  0x08, 	/* 4B1A0 */
+	0x44,  0x08,  0xE8,  0x08,  0x3C,  0x09,  0xC2,  0xBB,  0x01,  0x00,  0x7F,  0xFF,  0x04,  0x10,  0x1F,  0x10, 	/* 4B1B0 */
+	0x04,  0x7C,  0x7F,  0x94,  0x15,  0x35,  0x25,  0x95,  0x5E,  0x2B,  0x07,  0xA9,  0x7C,  0x40,  0x01,  0x84, 	/* 4B1C0 */
+	0x0E,  0x48,  0x74,  0x30,  0x07,  0x98,  0x1C,  0x07,  0x81,  0x10,  0x08,  0x13,  0xCC,  0x10,  0x52,  0x7C, 	/* 4B1D0 */
+	0x7D,  0x04,  0x49,  0x09,  0xC8,  0x09,  0x3E,  0x11,  0x2A,  0x35,  0x2A,  0x59,  0xEA,  0x14,  0x7E,  0x12, 	/* 4B1E0 */
+	0x4C,  0x10,  0x4A,  0x10,  0x4A,  0x10,  0x8F,  0x13,  0x71,  0x83,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00, 	/* 4B1F0 */
+	0x06,  0x7C,  0x38,  0x44,  0x20,  0x7C,  0x3E,  0x10,  0x21,  0xFF,  0x20,  0x7C,  0x3D,  0x93,  0x20,  0x10, 	/* 4B200 */
+	0x01,  0x44,  0x0E,  0x28,  0x74,  0x10,  0x07,  0x0C,  0x78,  0x03,  0x84,  0x00,  0x80,  0x00,  0x80,  0x7F, 	/* 4B210 */
+	0xFF,  0x11,  0x44,  0x1F,  0x7C,  0x02,  0x20,  0x0F,  0xF8,  0x02,  0x20,  0x0F,  0xF8,  0x02,  0x20,  0x7F, 	/* 4B220 */
+	0xFF,  0x03,  0x44,  0x0C,  0x28,  0x74,  0x10,  0x07,  0x8C,  0x1C,  0x03,  0x8C,  0x08,  0x00,  0x08,  0xEE, 	/* 4B230 */
+	0x08,  0xAA,  0x7E,  0xEE,  0x02,  0x00,  0x04,  0xFC,  0x04,  0xA4,  0x0A,  0xA4,  0x1A,  0xFC,  0x2C,  0xA4, 	/* 4B240 */
+	0x4A,  0xFC,  0x08,  0x20,  0x0B,  0xFF,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x8D,  0x08,  0x24,  0x08, 	/* 4B250 */
+	0x28,  0x08,  0x7F,  0x7E,  0x48,  0x02,  0xFE,  0x05,  0x48,  0x04,  0x7E,  0x0A,  0x48,  0x1C,  0x7F,  0x2A, 	/* 4B260 */
+	0x10,  0x49,  0xFF,  0x09,  0x38,  0x08,  0x54,  0x09,  0x93,  0x08,  0x10,  0x08,  0x10,  0x96,  0x10,  0x20, 	/* 4B270 */
+	0x10,  0x40,  0x11,  0xFC,  0x7D,  0x24,  0x05,  0xAC,  0x09,  0x74,  0x09,  0xFC,  0x15,  0x24,  0x15,  0x74, 	/* 4B280 */
+	0x39,  0xAC,  0x55,  0x24,  0x13,  0xFF,  0x10,  0x20,  0x10,  0x50,  0x11,  0x88,  0x16,  0x06,  0x9E,  0x00, 	/* 4B290 */
+	0x08,  0x1F,  0xFF,  0x10,  0xA2,  0x1F,  0x94,  0x10,  0x7F,  0x1F,  0x08,  0x29,  0x7F,  0x29,  0x08,  0x4F, 	/* 4B2A0 */
+	0x88,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0x44,  0x0C,  0x28,  0x74,  0x10,  0x07,  0x8C,  0x38,  0x03,  0x9F, 	/* 4B2B0 */
+	0x10,  0x88,  0x10,  0x88,  0x13,  0xFF,  0x7C,  0x88,  0x05,  0xDC,  0x09,  0xAA,  0x0A,  0x89,  0x16,  0x88, 	/* 4B2C0 */
+	0x18,  0xFC,  0x34,  0x00,  0x53,  0xFF,  0x10,  0xA8,  0x10,  0xA4,  0x11,  0x22,  0x12,  0x22,  0x10,  0x60, 	/* 4B2D0 */
+	0xA0,  0x08,  0x92,  0x08,  0x52,  0x08,  0x54,  0x7F,  0xFF,  0x03,  0x01,  0x05,  0x7D,  0x04,  0x44,  0x0A, 	/* 4B2E0 */
+	0x7C,  0x1A,  0x00,  0x2C,  0xFE,  0x4A,  0x92,  0x08,  0x92,  0x08,  0xFE,  0x08,  0x92,  0x08,  0xFE,  0x08, 	/* 4B2F0 */
+	0x00,  0xA4,  0x10,  0x04,  0x11,  0xF4,  0x11,  0x44,  0x7D,  0x4F,  0x05,  0xE8,  0x09,  0x30,  0x09,  0xE0, 	/* 4B300 */
+	0x13,  0x4F,  0x1D,  0x40,  0x35,  0xF0,  0x52,  0x00,  0x10,  0xFE,  0x10,  0xAA,  0x10,  0xAA,  0x13,  0xFF, 	/* 4B310 */
+	0x10,  0x00,  0xA6,  0x08,  0x00,  0x08,  0xFE,  0x08,  0x10,  0x7D,  0xFF,  0x05,  0x11,  0x05,  0xDD,  0x09, 	/* 4B320 */
+	0x11,  0x08,  0xDC,  0x1A,  0x00,  0x2D,  0xFF,  0x4A,  0x20,  0x09,  0xFE,  0x09,  0x4A,  0x09,  0x4A,  0x09, 	/* 4B330 */
+	0x4A,  0x09,  0x06,  0xAA,  0x10,  0x88,  0x13,  0xFF,  0x10,  0x88,  0x7C,  0x00,  0x05,  0xFE,  0x09,  0x52, 	/* 4B340 */
+	0x11,  0xFE,  0x14,  0x14,  0x38,  0x12,  0x55,  0xFF,  0x13,  0x10,  0x11,  0x12,  0x11,  0xD4,  0x11,  0x09, 	/* 4B350 */
+	0x12,  0x35,  0x14,  0xC3,  0xAD,  0x10,  0x80,  0x10,  0xBF,  0x10,  0x84,  0x7F,  0xE8,  0x04,  0x9E,  0x08, 	/* 4B360 */
+	0x92,  0x0B,  0xD2,  0x10,  0x1E,  0x14,  0x12,  0x3B,  0xDE,  0x56,  0x52,  0x12,  0x52,  0x12,  0x5E,  0x13, 	/* 4B370 */
+	0xCC,  0x10,  0x12,  0x10,  0x61,  0xAF,  0x10,  0x80,  0x10,  0x9E,  0x13,  0xF2,  0x7E,  0x52,  0x05,  0x5E, 	/* 4B380 */
+	0x09,  0x92,  0x0B,  0xF2,  0x10,  0x9E,  0x34,  0x92,  0x5B,  0xF2,  0x14,  0x9E,  0x11,  0xCC,  0x12,  0xB4, 	/* 4B390 */
+	0x14,  0x95,  0x10,  0xA5,  0x10,  0xC3,  0xB2,  0x04,  0x40,  0x3F,  0x7E,  0x12,  0x40,  0x7F,  0xFC,  0x11, 	/* 4B3A0 */
+	0x04,  0x1F,  0x7C,  0x11,  0x40,  0x1F,  0x7C,  0x11,  0x42,  0x13,  0x3E,  0x11,  0x00,  0x7F,  0xFF,  0x02, 	/* 4B3B0 */
+	0x84,  0x7C,  0x48,  0x07,  0x30,  0x38,  0x0E,  0xB4,  0x10,  0x00,  0x13,  0xDE,  0x12,  0x52,  0x7F,  0xDE, 	/* 4B3C0 */
+	0x06,  0x52,  0x0B,  0xDE,  0x0A,  0x22,  0x12,  0xFA,  0x36,  0x22,  0x5A,  0xFA,  0x16,  0xEA,  0x12,  0xBA, 	/* 4B3D0 */
+	0x12,  0xFA,  0x12,  0x72,  0x12,  0xAA,  0x12,  0x26,  0xB7,  0x08,  0x30,  0x08,  0xDE,  0x08,  0x9A,  0x7E, 	/* 4B3E0 */
+	0xEE,  0x02,  0xAA,  0x05,  0xFF,  0x04,  0x44,  0x0A,  0x8A,  0x1B,  0x71,  0x2C,  0x10,  0x4A,  0xFE,  0x08, 	/* 4B3F0 */
+	0x10,  0x09,  0xFF,  0x08,  0x10,  0x08,  0x10,  0x08,  0x30,  0xBE,  0x00,  0x00,  0x7F,  0xFF,  0x02,  0x20, 	/* 4B400 */
+	0x02,  0x20,  0x02,  0x20,  0x3F,  0xFE,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22, 	/* 4B410 */
+	0x23,  0xE2,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x02,  0xBF,  0x00,  0x00,  0x7F,  0xFF,  0x02, 	/* 4B420 */
+	0x20,  0x02,  0x20,  0x02,  0x20,  0x3F,  0xFE,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x24,  0x22,  0x24, 	/* 4B430 */
+	0x1E,  0x28,  0x02,  0x30,  0x02,  0x20,  0x02,  0x3F,  0xFE,  0x00,  0x00,  0x81,  0x00,  0x00,  0x7F,  0xFE, 	/* 4B440 */
+	0x02,  0x40,  0x02,  0x40,  0x1F,  0xF8,  0x12,  0x48,  0x12,  0x48,  0x1F,  0xF8,  0x01,  0x00,  0x7F,  0xFF, 	/* 4B450 */
+	0x02,  0x20,  0x04,  0x20,  0x0F,  0x40,  0x00,  0xE0,  0x03,  0x18,  0x3C,  0x04,  0x83,  0x00,  0x00,  0x7F, 	/* 4B460 */
+	0xFF,  0x02,  0x20,  0x1F,  0xFC,  0x12,  0x24,  0x13,  0xE4,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F, 	/* 4B470 */
+	0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x86,  0x00,  0x00, 	/* 4B480 */
+	0x7F,  0xFF,  0x02,  0x40,  0x3F,  0xFC,  0x22,  0x44,  0x3F,  0xFC,  0x08,  0x80,  0x10,  0xFE,  0x25,  0x84, 	/* 4B490 */
+	0x46,  0xFC,  0x08,  0x20,  0x18,  0x7C,  0x2B,  0xC8,  0x48,  0x30,  0x08,  0xCC,  0x0B,  0x03,  0x87,  0x00, 	/* 4B4A0 */
+	0x00,  0x7F,  0xFF,  0x02,  0x20,  0x3F,  0xFE,  0x22,  0x22,  0x3F,  0xFE,  0x11,  0x00,  0x7F,  0xBE,  0x11, 	/* 4B4B0 */
+	0x22,  0x1F,  0x22,  0x04,  0x3E,  0x3F,  0xA2,  0x24,  0xBE,  0x7F,  0xE2,  0x04,  0x22,  0x04,  0x46,  0x88, 	/* 4B4C0 */
+	0x00,  0x00,  0x7F,  0xFF,  0x02,  0x20,  0x3F,  0xFE,  0x22,  0x22,  0x23,  0xE2,  0x08,  0x10,  0x1F,  0x1F, 	/* 4B4D0 */
+	0x11,  0x24,  0x1F,  0x64,  0x11,  0x14,  0x7F,  0xD8,  0x08,  0x0C,  0x0F,  0x14,  0x11,  0x62,  0x26,  0x81, 	/* 4B4E0 */
+	0x8A,  0x00,  0x00,  0x7F,  0xFF,  0x02,  0x20,  0x3F,  0xFE,  0x22,  0x22,  0x23,  0xE2,  0x14,  0x00,  0x7F, 	/* 4B4F0 */
+	0x7F,  0x14,  0x48,  0x1C,  0x7E,  0x3E,  0x48,  0x2A,  0x7F,  0x3E,  0x09,  0x08,  0xD5,  0x7E,  0xA9,  0x09, 	/* 4B500 */
+	0x06,  0x8B,  0x00,  0x00,  0x07,  0xF8,  0x04,  0x08,  0x04,  0x08,  0x07,  0xF8,  0x04,  0x08,  0x04,  0x08, 	/* 4B510 */
+	0x07,  0xF8,  0x04,  0x08,  0x04,  0x08,  0x07,  0xF8,  0x01,  0x20,  0x01,  0x20,  0x02,  0x21,  0x0C,  0x21, 	/* 4B520 */
+	0x70,  0x1F,  0x8F,  0x08,  0x00,  0x08,  0xFC,  0x08,  0x84,  0x3F,  0x84,  0x08,  0xFC,  0x08,  0x84,  0x08, 	/* 4B530 */
+	0x84,  0x7F,  0xFC,  0x08,  0x84,  0x0C,  0x84,  0x14,  0xFC,  0x12,  0x50,  0x12,  0x50,  0x20,  0x91,  0x21, 	/* 4B540 */
+	0x09,  0x46,  0x07,  0x93,  0x00,  0x0C,  0x00,  0x70,  0x1F,  0x88,  0x08,  0x44,  0x08,  0x44,  0x17,  0xFA, 	/* 4B550 */
+	0x14,  0x0A,  0x27,  0xF8,  0x04,  0x08,  0x07,  0xF8,  0x04,  0x08,  0x07,  0xF8,  0x01,  0x20,  0x02,  0x21, 	/* 4B560 */
+	0x0C,  0x21,  0x70,  0x1F,  0x96,  0x08,  0x00,  0x08,  0xFC,  0x08,  0x84,  0x7E,  0x84,  0x02,  0xFC,  0x04, 	/* 4B570 */
+	0x84,  0x04,  0x84,  0x08,  0xFC,  0x0C,  0x84,  0x1A,  0x84,  0x29,  0xFC,  0x48,  0x28,  0x08,  0x28,  0x08, 	/* 4B580 */
+	0x49,  0x08,  0x89,  0x09,  0x07,  0x97,  0x00,  0x00,  0x7F,  0x7E,  0x01,  0x42,  0x01,  0x42,  0x7F,  0x7E, 	/* 4B590 */
+	0x01,  0x42,  0x3D,  0x42,  0x25,  0x7E,  0x25,  0x42,  0x25,  0x42,  0x3D,  0x7E,  0x01,  0x28,  0x01,  0x28, 	/* 4B5A0 */
+	0x01,  0x29,  0x01,  0x49,  0x06,  0x87,  0x98,  0x10,  0x00,  0x10,  0xFC,  0x10,  0x84,  0x1F,  0x84,  0x10, 	/* 4B5B0 */
+	0xFC,  0x10,  0x84,  0x10,  0x84,  0x10,  0xFC,  0x7E,  0x84,  0x42,  0x84,  0x42,  0xFC,  0x42,  0x28,  0x7E, 	/* 4B5C0 */
+	0x28,  0x00,  0x49,  0x01,  0x89,  0x06,  0x07,  0x9A,  0x11,  0x08,  0x08,  0x88,  0x08,  0x90,  0x7F,  0xFE, 	/* 4B5D0 */
+	0x40,  0x02,  0x4F,  0xF2,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0, 	/* 4B5E0 */
+	0x02,  0x40,  0x04,  0x41,  0x18,  0x41,  0x60,  0x3F,  0xA1,  0x00,  0x00,  0x7F,  0x7E,  0x08,  0x42,  0x08, 	/* 4B5F0 */
+	0x42,  0x2A,  0x7E,  0x2A,  0x42,  0x2A,  0x42,  0x2D,  0x7E,  0x59,  0x42,  0x48,  0x42,  0x08,  0x7E,  0x0F, 	/* 4B600 */
+	0x28,  0x18,  0x28,  0x60,  0x49,  0x01,  0x89,  0x06,  0x07,  0xA6,  0x04,  0x00,  0x04,  0x3E,  0x0A,  0x22, 	/* 4B610 */
+	0x09,  0x22,  0x10,  0xBE,  0x3F,  0x62,  0x40,  0x22,  0x3A,  0xBE,  0x2A,  0xA2,  0x3A,  0xA2,  0x2D,  0x3E, 	/* 4B620 */
+	0x2D,  0x18,  0x3D,  0x28,  0x2A,  0xA9,  0x2A,  0xC9,  0x2A,  0x87,  0xA7,  0x3F,  0x90,  0x24,  0x1F,  0x3F, 	/* 4B630 */
+	0x20,  0x21,  0x40,  0x3F,  0x3E,  0x24,  0x00,  0x3F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F, 	/* 4B640 */
+	0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x02,  0x21,  0x0C,  0x21,  0x70,  0x1F,  0xA9,  0x08,  0x00,  0x09,  0x7E, 	/* 4B650 */
+	0x3F,  0x42,  0x0A,  0x42,  0x0A,  0x7E,  0x0C,  0x42,  0x7F,  0xC2,  0x0A,  0x7E,  0x11,  0x42,  0x1F,  0x42, 	/* 4B660 */
+	0x31,  0x7E,  0x5F,  0x18,  0x11,  0x28,  0x11,  0x29,  0x1F,  0x49,  0x01,  0x87,  0xAA,  0x08,  0x00,  0x08, 	/* 4B670 */
+	0x7E,  0x7F,  0x42,  0x22,  0x42,  0x12,  0x7E,  0x14,  0x42,  0x7F,  0x42,  0x08,  0x7E,  0x08,  0x42,  0x7F, 	/* 4B680 */
+	0x42,  0x1C,  0x7E,  0x1A,  0x28,  0x29,  0x28,  0x48,  0x49,  0x08,  0x89,  0x0B,  0x07,  0xAC,  0x08,  0x00, 	/* 4B690 */
+	0x29,  0x7E,  0x29,  0x42,  0x3F,  0x42,  0x00,  0x7E,  0x7F,  0xC2,  0x00,  0x42,  0x3F,  0x7E,  0x21,  0x42, 	/* 4B6A0 */
+	0x3F,  0x42,  0x02,  0x7E,  0x22,  0x28,  0x14,  0x28,  0x13,  0x49,  0x1C,  0x89,  0x61,  0x07,  0xAF,  0x12, 	/* 4B6B0 */
+	0x00,  0x3F,  0xBE,  0x12,  0x22,  0x3F,  0xA2,  0x12,  0x3E,  0x7F,  0xE2,  0x04,  0x22,  0x1F,  0x3E,  0x15, 	/* 4B6C0 */
+	0x22,  0x1F,  0x22,  0x15,  0x3E,  0x15,  0x14,  0x7F,  0xD4,  0x11,  0x25,  0x11,  0x45,  0x13,  0x83,  0xB2, 	/* 4B6D0 */
+	0x12,  0x00,  0x12,  0x7E,  0x7F,  0xC2,  0x12,  0x42,  0x1E,  0x7E,  0x00,  0x42,  0x3F,  0x42,  0x25,  0x7E, 	/* 4B6E0 */
+	0x3F,  0x42,  0x04,  0x42,  0x3F,  0x7E,  0x04,  0x18,  0x3F,  0x28,  0x04,  0x29,  0x07,  0x49,  0x79,  0x87, 	/* 4B6F0 */
+	0xB3,  0x10,  0x00,  0x10,  0x7E,  0x3F,  0x42,  0x28,  0x42,  0x48,  0x7E,  0x7F,  0xC2,  0x12,  0x42,  0x14, 	/* 4B700 */
+	0x7E,  0x3F,  0x42,  0x64,  0x42,  0x3F,  0x7E,  0x24,  0x28,  0x3F,  0x28,  0x24,  0x49,  0x3F,  0x89,  0x21, 	/* 4B710 */
+	0x07,  0xBA,  0x05,  0x5C,  0x18,  0x84,  0x1D,  0x5C,  0x10,  0x84,  0x1D,  0x5C,  0x10,  0x04,  0x3F,  0xFE, 	/* 4B720 */
+	0x24,  0x12,  0x27,  0xF2,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x07,  0xF0,  0x01,  0x21,  0x06,  0x21, 	/* 4B730 */
+	0x78,  0x1F,  0xBD,  0x00,  0x10,  0x3F,  0x9F,  0x24,  0x20,  0x3F,  0x5E,  0x21,  0x00,  0x3F,  0x7F,  0x24, 	/* 4B740 */
+	0x55,  0x3F,  0xFF,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF9,  0x06, 	/* 4B750 */
+	0x21,  0x78,  0x3F,  0xBF,  0x04,  0x00,  0x7F,  0xBE,  0x04,  0x22,  0x3F,  0xA2,  0x00,  0x3E,  0x7F,  0xA2, 	/* 4B760 */
+	0x52,  0xA2,  0x7F,  0xBE,  0x21,  0x22,  0x3F,  0x22,  0x21,  0x3E,  0x3F,  0x14,  0x21,  0x14,  0x3F,  0x25, 	/* 4B770 */
+	0x11,  0x45,  0x60,  0x83,  0x80,  0x11,  0x00,  0x7F,  0xFE,  0x11,  0x22,  0x3B,  0xA2,  0x2A,  0xBE,  0x3B, 	/* 4B780 */
+	0xA2,  0x10,  0x22,  0x12,  0x3E,  0x1F,  0xA2,  0x24,  0x22,  0x7F,  0x3E,  0x24,  0x14,  0x3F,  0x14,  0x24, 	/* 4B790 */
+	0x25,  0x3F,  0xC5,  0x00,  0x83,  0x92,  0x02,  0x00,  0x03,  0xE0,  0x04,  0x20,  0x18,  0x40,  0x7F,  0xFC, 	/* 4B7A0 */
+	0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x10,  0x04,  0x10,  0x04, 	/* 4B7B0 */
+	0x20,  0x04,  0x20,  0x04,  0x40,  0x0C,  0x9A,  0x08,  0x02,  0x0E,  0x0C,  0x12,  0x78,  0x24,  0x44,  0x7E, 	/* 4B7C0 */
+	0x54,  0x2A,  0x54,  0x2A,  0x54,  0x3E,  0x54,  0x2A,  0x54,  0x2A,  0x54,  0x3E,  0x54,  0x22,  0x5A,  0x22, 	/* 4B7D0 */
+	0x56,  0x22,  0x7A,  0x22,  0x82,  0x47,  0x01,  0x9C,  0x04,  0x20,  0x14,  0x22,  0x17,  0xA4,  0x14,  0x38, 	/* 4B7E0 */
+	0x14,  0x21,  0x1F,  0xA1,  0x71,  0x1F,  0x03,  0xE0,  0x0C,  0x40,  0x3F,  0xFC,  0x08,  0x44,  0x0F,  0xFC, 	/* 4B7F0 */
+	0x08,  0x44,  0x0F,  0xFC,  0x10,  0x04,  0x20,  0x0C,  0x9D,  0x08,  0x02,  0x0E,  0x0C,  0x12,  0x78,  0x24, 	/* 4B800 */
+	0x48,  0x7F,  0x48,  0x29,  0x48,  0x29,  0x7F,  0x3F,  0x48,  0x29,  0x48,  0x29,  0x48,  0x3F,  0x48,  0x21, 	/* 4B810 */
+	0x65,  0x21,  0xC5,  0x21,  0x03,  0x21,  0xF3,  0x43,  0x01,  0xA3,  0x08,  0x00,  0x0E,  0xFE,  0x12,  0x12, 	/* 4B820 */
+	0x24,  0x12,  0x7F,  0x22,  0x29,  0x4C,  0x29,  0x90,  0x3F,  0x50,  0x29,  0x7E,  0x29,  0x90,  0x3F,  0x10, 	/* 4B830 */
+	0x21,  0xFF,  0x21,  0x10,  0x21,  0x10,  0x21,  0x10,  0x43,  0x10,  0xA6,  0x08,  0x10,  0x0F,  0x10,  0x12, 	/* 4B840 */
+	0x10,  0x24,  0x7E,  0x5F,  0x52,  0x15,  0x52,  0x15,  0x52,  0x1F,  0x52,  0x15,  0x7E,  0x15,  0x10,  0x1F, 	/* 4B850 */
+	0x10,  0x11,  0x14,  0x11,  0x12,  0x21,  0x1E,  0x21,  0xF1,  0x43,  0x01,  0xA7,  0x08,  0x44,  0x0E,  0x24, 	/* 4B860 */
+	0x12,  0x28,  0x24,  0xFF,  0x7F,  0x10,  0x29,  0x10,  0x29,  0x10,  0x3F,  0x7E,  0x29,  0x10,  0x29,  0x10, 	/* 4B870 */
+	0x3F,  0x10,  0x21,  0xFF,  0x21,  0x10,  0x21,  0x10,  0x21,  0x10,  0x43,  0x10,  0xB4,  0x08,  0x20,  0x0E, 	/* 4B880 */
+	0x3F,  0x12,  0x40,  0x24,  0xBC,  0x7F,  0x24,  0x29,  0x3C,  0x29,  0x24,  0x3F,  0x3C,  0x29,  0x00,  0x29, 	/* 4B890 */
+	0xFF,  0x3F,  0x20,  0x21,  0x7E,  0x21,  0xAA,  0x21,  0x4A,  0x21,  0x92,  0x43,  0x24,  0xB8,  0x08,  0x00, 	/* 4B8A0 */
+	0x0E,  0xFE,  0x12,  0xAA,  0x24,  0xAA,  0x7E,  0xFE,  0x2A,  0x40,  0x2A,  0x7E,  0x3E,  0xA2,  0x2B,  0xFA, 	/* 4B8B0 */
+	0x2A,  0xAA,  0x3E,  0xFA,  0x22,  0x32,  0x22,  0x2A,  0x23,  0xFA,  0x22,  0x06,  0x46,  0x0C,  0x80,  0x00, 	/* 4B8C0 */
+	0x00,  0x07,  0xF0,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF8,  0x00,  0x00,  0x00,  0x00,  0x0F, 	/* 4B8D0 */
+	0xF8,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x82, 	/* 4B8E0 */
+	0x00,  0x00,  0x1E,  0x00,  0x00,  0xFF,  0x7F,  0x88,  0x00,  0x08,  0x3F,  0x08,  0x00,  0x08,  0x00,  0x08, 	/* 4B8F0 */
+	0x3F,  0x08,  0x00,  0x08,  0x3F,  0x08,  0x21,  0x08,  0x21,  0x08,  0x21,  0x08,  0x3F,  0x08,  0x00,  0x18, 	/* 4B900 */
+	0x83,  0x00,  0x10,  0x3F,  0x10,  0x00,  0x10,  0x7F,  0x90,  0x00,  0x10,  0x3F,  0x18,  0x00,  0x14,  0x00, 	/* 4B910 */
+	0x12,  0x3F,  0x11,  0x00,  0x11,  0x3F,  0x10,  0x21,  0x10,  0x21,  0x10,  0x21,  0x10,  0x3F,  0x10,  0x00, 	/* 4B920 */
+	0x10,  0x88,  0x00,  0x10,  0x3F,  0x10,  0x00,  0x10,  0x7F,  0x90,  0x00,  0x10,  0x3F,  0x10,  0x00,  0xFF, 	/* 4B930 */
+	0x00,  0x10,  0x3F,  0x10,  0x00,  0x10,  0x3F,  0x10,  0x21,  0x10,  0x21,  0x10,  0x21,  0x10,  0x3F,  0x10, 	/* 4B940 */
+	0x00,  0x10,  0x8A,  0x00,  0x00,  0x3E,  0xF8,  0x00,  0x48,  0x7F,  0x48,  0x00,  0x48,  0x3E,  0x48,  0x00, 	/* 4B950 */
+	0x48,  0x3E,  0x78,  0x01,  0xC8,  0x00,  0x48,  0x3E,  0x48,  0x22,  0x48,  0x22,  0x89,  0x22,  0x85,  0x3F, 	/* 4B960 */
+	0x05,  0x02,  0x03,  0x8C,  0x00,  0x00,  0x3E,  0x00,  0x00,  0xFE,  0x7F,  0x10,  0x00,  0x10,  0x3E,  0x10, 	/* 4B970 */
+	0x00,  0x10,  0x00,  0x10,  0x3E,  0x10,  0x00,  0x10,  0x3E,  0x10,  0x22,  0x10,  0x22,  0x10,  0x22,  0x10, 	/* 4B980 */
+	0x3F,  0xFF,  0x00,  0x00,  0x8E,  0x00,  0x04,  0x3E,  0x04,  0x00,  0x04,  0x7F,  0x04,  0x00,  0xFF,  0x3E, 	/* 4B990 */
+	0x04,  0x00,  0x04,  0x00,  0x84,  0x3E,  0x44,  0x00,  0x44,  0x3E,  0x04,  0x22,  0x04,  0x22,  0x04,  0x22, 	/* 4B9A0 */
+	0x04,  0x3E,  0x04,  0x00,  0x0C,  0x90,  0x00,  0x00,  0x3E,  0xFE,  0x00,  0x10,  0x7F,  0x10,  0x00,  0x10, 	/* 4B9B0 */
+	0x3E,  0x10,  0x00,  0x10,  0x01,  0xFF,  0x3E,  0x10,  0x00,  0x10,  0x3E,  0x10,  0x22,  0x10,  0x22,  0x10, 	/* 4B9C0 */
+	0x22,  0x10,  0x3E,  0x10,  0x00,  0x10,  0x93,  0x00,  0x02,  0x3E,  0x42,  0x00,  0x52,  0x7F,  0x52,  0x00, 	/* 4B9D0 */
+	0x52,  0x3E,  0x52,  0x00,  0x52,  0x00,  0x52,  0x3E,  0x52,  0x00,  0x52,  0x3E,  0x52,  0x22,  0x52,  0x22, 	/* 4B9E0 */
+	0x52,  0x22,  0x82,  0x3E,  0x82,  0x01,  0x02,  0x96,  0x00,  0x20,  0x3E,  0x20,  0x00,  0x20,  0x7F,  0x7F, 	/* 4B9F0 */
+	0x00,  0x40,  0x3E,  0x40,  0x00,  0xBE,  0x01,  0x04,  0x3E,  0x08,  0x00,  0x10,  0x3E,  0x20,  0x22,  0x20, 	/* 4BA00 */
+	0x22,  0x40,  0x22,  0x41,  0x3E,  0x41,  0x00,  0x3F,  0x97,  0x00,  0x04,  0x3E,  0x18,  0x00,  0xE0,  0x7F, 	/* 4BA10 */
+	0x20,  0x00,  0x20,  0x3E,  0x20,  0x00,  0x27,  0x01,  0xF8,  0x3E,  0x20,  0x00,  0x20,  0x3E,  0x20,  0x22, 	/* 4BA20 */
+	0x20,  0x22,  0x22,  0x22,  0x22,  0x3E,  0x1E,  0x00,  0x00,  0x98,  0x00,  0x00,  0x3E,  0x7E,  0x00,  0x02, 	/* 4BA30 */
+	0x7F,  0x82,  0x00,  0x02,  0x3F,  0x02,  0x00,  0x7E,  0x3F,  0x40,  0x00,  0x40,  0x00,  0x40,  0x3F,  0x40, 	/* 4BA40 */
+	0x21,  0x40,  0x21,  0x41,  0x21,  0x21,  0x3F,  0x1F,  0x00,  0x00,  0x9B,  0x00,  0x50,  0x3E,  0x50,  0x00, 	/* 4BA50 */
+	0x50,  0x7F,  0x92,  0x00,  0x92,  0x3D,  0x94,  0x02,  0x94,  0x00,  0x98,  0x3C,  0xB0,  0x00,  0x90,  0x3E, 	/* 4BA60 */
+	0x90,  0x22,  0x91,  0x22,  0x91,  0x22,  0x91,  0x3E,  0x8F,  0x00,  0x80,  0x9D,  0x00,  0x00,  0x3E,  0x7E, 	/* 4BA70 */
+	0x00,  0x44,  0x7F,  0x44,  0x00,  0x44,  0x3E,  0x44,  0x00,  0x44,  0x01,  0xFF,  0x3E,  0x0C,  0x00,  0x14, 	/* 4BA80 */
+	0x3E,  0x14,  0x22,  0x24,  0x22,  0x44,  0x22,  0x84,  0x3F,  0x04,  0x00,  0x0C,  0x9F,  0x00,  0x38,  0x3E, 	/* 4BA90 */
+	0x08,  0x00,  0x48,  0x7F,  0x48,  0x00,  0x44,  0x3E,  0x84,  0x00,  0xA2,  0x01,  0x21,  0x3E,  0x20,  0x00, 	/* 4BAA0 */
+	0x30,  0x3E,  0x28,  0x22,  0x48,  0x22,  0x44,  0x22,  0x8C,  0x3F,  0xF2,  0x00,  0x02,  0xA3,  0x00,  0x20, 	/* 4BAB0 */
+	0x3E,  0x20,  0x00,  0x20,  0x7F,  0xFC,  0x00,  0x24,  0x3E,  0x24,  0x00,  0x24,  0x00,  0x24,  0x3F,  0xFF, 	/* 4BAC0 */
+	0x00,  0x20,  0x3E,  0x30,  0x22,  0x30,  0x22,  0x48,  0x22,  0x44,  0x3E,  0x82,  0x03,  0x01,  0xA5,  0x00, 	/* 4BAD0 */
+	0x30,  0x3C,  0x10,  0x00,  0x10,  0x7F,  0xFE,  0x00,  0x92,  0x3E,  0x92,  0x00,  0x92,  0x00,  0xAA,  0x3E, 	/* 4BAE0 */
+	0xAA,  0x00,  0xA6,  0x3E,  0xC2,  0x22,  0x82,  0x22,  0x82,  0x22,  0x82,  0x3E,  0x82,  0x00,  0x86,  0xAA, 	/* 4BAF0 */
+	0x00,  0x10,  0x3E,  0x10,  0x00,  0x10,  0x7F,  0xFF,  0x00,  0x20,  0x3E,  0x20,  0x00,  0x20,  0x3E,  0x3E, 	/* 4BB00 */
+	0x00,  0x22,  0x00,  0x22,  0x3E,  0x22,  0x22,  0x42,  0x22,  0x42,  0x22,  0x82,  0x3F,  0x04,  0x02,  0x18, 	/* 4BB10 */
+	0xAD,  0x00,  0x00,  0x3E,  0x7C,  0x00,  0x44,  0x7F,  0x44,  0x00,  0x45,  0x3E,  0x85,  0x01,  0x03,  0x3E, 	/* 4BB20 */
+	0x00,  0x01,  0xFC,  0x00,  0x44,  0x3E,  0x48,  0x22,  0x28,  0x22,  0x10,  0x22,  0x28,  0x3E,  0xC4,  0x03, 	/* 4BB30 */
+	0x03,  0xB1,  0x00,  0x40,  0x3E,  0x40,  0x00,  0x40,  0x7F,  0x7E,  0x00,  0x90,  0x3E,  0x90,  0x01,  0x10, 	/* 4BB40 */
+	0x3E,  0x10,  0x03,  0xFF,  0x00,  0x10,  0x3E,  0x10,  0x22,  0x10,  0x22,  0x10,  0x22,  0x10,  0x3E,  0x10, 	/* 4BB50 */
+	0x00,  0x10,  0xB3,  0x00,  0x00,  0x3E,  0x7E,  0x00,  0x42,  0x7F,  0x42,  0x00,  0x42,  0x3E,  0x42,  0x00, 	/* 4BB60 */
+	0x7E,  0x00,  0x50,  0x3E,  0x50,  0x00,  0x50,  0x3E,  0x48,  0x22,  0x48,  0x22,  0x84,  0x22,  0x84,  0x3E, 	/* 4BB70 */
+	0x82,  0x01,  0x01,  0xB4,  0x00,  0x04,  0x3E,  0x18,  0x00,  0xE0,  0x7F,  0x80,  0x00,  0x80,  0x3E,  0xFF, 	/* 4BB80 */
+	0x00,  0x88,  0x00,  0x88,  0x3E,  0x88,  0x00,  0xB8,  0x3E,  0x8E,  0x22,  0x89,  0x22,  0x88,  0x22,  0x88, 	/* 4BB90 */
+	0x3F,  0x08,  0x02,  0x08,  0xB6,  0x00,  0x00,  0x3D,  0xFF,  0x00,  0x04,  0x7F,  0x04,  0x00,  0x04,  0x3E, 	/* 4BBA0 */
+	0xF4,  0x00,  0x94,  0x00,  0x94,  0x3E,  0x94,  0x00,  0x94,  0x3E,  0xF4,  0x22,  0x04,  0x22,  0x04,  0x22, 	/* 4BBB0 */
+	0x04,  0x3E,  0x04,  0x00,  0x0C,  0xBA,  0x00,  0x10,  0x3E,  0x10,  0x00,  0x28,  0x7F,  0x28,  0x00,  0x44, 	/* 4BBC0 */
+	0x3E,  0x92,  0x01,  0x21,  0x00,  0xC4,  0x3E,  0x08,  0x00,  0x30,  0x3E,  0xC2,  0x22,  0x04,  0x22,  0x08, 	/* 4BBD0 */
+	0x22,  0x30,  0x3E,  0xC0,  0x03,  0x00,  0xBB,  0x00,  0x20,  0x3E,  0x10,  0x00,  0x10,  0x7F,  0xFE,  0x00, 	/* 4BBE0 */
+	0x10,  0x3E,  0x10,  0x00,  0x10,  0x00,  0x10,  0x3E,  0xFE,  0x00,  0x10,  0x3E,  0x10,  0x22,  0x10,  0x22, 	/* 4BBF0 */
+	0x10,  0x22,  0x10,  0x3F,  0xFF,  0x00,  0x00,  0xBC,  0x00,  0x00,  0x3E,  0xFE,  0x00,  0x10,  0x7F,  0x10, 	/* 4BC00 */
+	0x00,  0x10,  0x3E,  0x90,  0x00,  0x90,  0x00,  0x9E,  0x3E,  0x90,  0x00,  0x90,  0x3E,  0x90,  0x22,  0x90, 	/* 4BC10 */
+	0x22,  0x90,  0x22,  0x90,  0x3F,  0xFF,  0x00,  0x00,  0x81,  0x00,  0x10,  0x3E,  0x10,  0x00,  0x10,  0x7F, 	/* 4BC20 */
+	0x10,  0x01,  0xFF,  0x3E,  0x10,  0x00,  0x10,  0x00,  0x10,  0x3E,  0x10,  0x00,  0xFC,  0x3E,  0x84,  0x22, 	/* 4BC30 */
+	0x84,  0x22,  0x84,  0x22,  0x84,  0x3E,  0xFC,  0x00,  0x00,  0x86,  0x00,  0x02,  0x3C,  0x0C,  0x00,  0x78, 	/* 4BC40 */
+	0x7F,  0x48,  0x00,  0x48,  0x3E,  0x48,  0x00,  0x7F,  0x00,  0x48,  0x3E,  0x48,  0x00,  0x44,  0x3E,  0x44, 	/* 4BC50 */
+	0x22,  0x75,  0x22,  0xC5,  0x22,  0x03,  0x3E,  0xFB,  0x00,  0x01,  0x88,  0x00,  0x00,  0x3F,  0xFE,  0x22, 	/* 4BC60 */
+	0x22,  0x22,  0x22,  0x3F,  0xFE,  0x00,  0x00,  0x0F,  0xF8,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x00,  0x0F, 	/* 4BC70 */
+	0xF8,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x90,  0x00,  0x40,  0x3E,  0x40, 	/* 4BC80 */
+	0x00,  0x40,  0x7F,  0x7F,  0x00,  0x90,  0x3E,  0x90,  0x01,  0x10,  0x00,  0x1E,  0x3E,  0x10,  0x00,  0x10, 	/* 4BC90 */
+	0x3E,  0x10,  0x22,  0x1E,  0x22,  0x10,  0x22,  0x10,  0x3E,  0x10,  0x00,  0x10,  0x91,  0x00,  0x10,  0x3E, 	/* 4BCA0 */
+	0x10,  0x00,  0x10,  0x7F,  0xFF,  0x00,  0x81,  0x3E,  0x81,  0x00,  0x40,  0x00,  0x44,  0x3E,  0x48,  0x00, 	/* 4BCB0 */
+	0x70,  0x3E,  0x40,  0x22,  0x40,  0x22,  0x40,  0x22,  0x42,  0x3E,  0x22,  0x00,  0x1E,  0x92,  0x00,  0x10, 	/* 4BCC0 */
+	0x3E,  0x10,  0x00,  0x10,  0x7F,  0x24,  0x00,  0x22,  0x3E,  0x4E,  0x01,  0xF1,  0x00,  0x01,  0x3E,  0x00, 	/* 4BCD0 */
+	0x00,  0x7E,  0x3E,  0x42,  0x22,  0x42,  0x22,  0x42,  0x22,  0x42,  0x3E,  0x7E,  0x00,  0x00,  0x94,  0x00, 	/* 4BCE0 */
+	0x00,  0x3D,  0xFE,  0x00,  0x22,  0x7F,  0x22,  0x00,  0x22,  0x3E,  0x42,  0x00,  0x42,  0x3E,  0x8C,  0x01, 	/* 4BCF0 */
+	0x00,  0x00,  0x7E,  0x3E,  0x42,  0x22,  0x42,  0x22,  0x42,  0x22,  0x42,  0x3E,  0x7E,  0x00,  0x00,  0x95, 	/* 4BD00 */
+	0x00,  0x00,  0x3E,  0xFE,  0x00,  0x12,  0x7F,  0x92,  0x00,  0x94,  0x3E,  0x54,  0x00,  0x58,  0x00,  0x50, 	/* 4BD10 */
+	0x3F,  0xFF,  0x00,  0x10,  0x3E,  0x10,  0x22,  0x10,  0x22,  0x10,  0x22,  0x10,  0x3E,  0x10,  0x00,  0x10, 	/* 4BD20 */
+	0x9B,  0x00,  0x00,  0x3E,  0x7C,  0x00,  0x44,  0x7F,  0x44,  0x00,  0x44,  0x3E,  0x7C,  0x00,  0x44,  0x00, 	/* 4BD30 */
+	0x44,  0x3E,  0x44,  0x00,  0x44,  0x3E,  0x7C,  0x22,  0x44,  0x22,  0x44,  0x22,  0x44,  0x3F,  0xFF,  0x00, 	/* 4BD40 */
+	0x00,  0x9E,  0x00,  0x00,  0x3E,  0xFE,  0x00,  0x02,  0x7F,  0x02,  0x00,  0xFA,  0x3E,  0x02,  0x00,  0x02, 	/* 4BD50 */
+	0x00,  0xF2,  0x3E,  0x92,  0x00,  0x92,  0x3E,  0x92,  0x22,  0xF2,  0x22,  0x02,  0x22,  0x02,  0x3E,  0x02, 	/* 4BD60 */
+	0x00,  0x0C,  0xA0,  0x00,  0x40,  0x3C,  0x20,  0x00,  0x10,  0x7E,  0x02,  0x00,  0xE2,  0x3C,  0x22,  0x00, 	/* 4BD70 */
+	0x34,  0x03,  0xF4,  0x3C,  0x68,  0x00,  0x68,  0x3C,  0xA4,  0x24,  0xA4,  0x25,  0x22,  0x26,  0x21,  0x3C, 	/* 4BD80 */
+	0x20,  0x00,  0x60,  0xA2,  0x00,  0x20,  0x3E,  0x20,  0x00,  0x3E,  0x7F,  0x42,  0x00,  0x82,  0x3F,  0xF2, 	/* 4BD90 */
+	0x00,  0x92,  0x00,  0x92,  0x3E,  0xF2,  0x00,  0x92,  0x3E,  0x92,  0x22,  0xF2,  0x22,  0x02,  0x22,  0x02, 	/* 4BDA0 */
+	0x3E,  0x04,  0x00,  0x18,  0xA3,  0x00,  0x40,  0x3E,  0x46,  0x00,  0x78,  0x7F,  0x40,  0x00,  0x41,  0x3E, 	/* 4BDB0 */
+	0x41,  0x00,  0x3F,  0x00,  0x00,  0x3E,  0x7E,  0x00,  0x42,  0x3E,  0x42,  0x22,  0x7E,  0x22,  0x42,  0x22, 	/* 4BDC0 */
+	0x42,  0x3E,  0x7E,  0x00,  0x00,  0xA6,  0x00,  0x08,  0x3E,  0x0C,  0x00,  0x0A,  0x7F,  0x08,  0x00,  0xFF, 	/* 4BDD0 */
+	0x3E,  0x08,  0x00,  0x08,  0x01,  0xF8,  0x3E,  0x48,  0x00,  0x48,  0x3E,  0x48,  0x22,  0x54,  0x22,  0x65, 	/* 4BDE0 */
+	0x23,  0x85,  0x3E,  0x03,  0x00,  0x01,  0xA9,  0x00,  0x10,  0x3E,  0x10,  0x00,  0xFE,  0x7F,  0x10,  0x00, 	/* 4BDF0 */
+	0x10,  0x3E,  0x10,  0x01,  0xFF,  0x00,  0x04,  0x3E,  0x04,  0x01,  0xFF,  0x3E,  0x84,  0x22,  0x44,  0x22, 	/* 4BE00 */
+	0x44,  0x22,  0x04,  0x3E,  0x04,  0x00,  0x0C,  0xAB,  0x00,  0x10,  0x3E,  0x10,  0x01,  0xFF,  0x7F,  0x01, 	/* 4BE10 */
+	0x01,  0x05,  0x3E,  0x18,  0x01,  0xE0,  0x00,  0x20,  0x3E,  0x20,  0x00,  0x3F,  0x3F,  0xE0,  0x22,  0x20, 	/* 4BE20 */
+	0x22,  0x20,  0x22,  0x21,  0x3E,  0x11,  0x00,  0x0F,  0xAC,  0x00,  0x02,  0x3E,  0x0C,  0x00,  0xF0,  0x7F, 	/* 4BE30 */
+	0x80,  0x00,  0x80,  0x3E,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x3E,  0xBE,  0x00,  0xA2,  0x3E,  0xA2,  0x22, 	/* 4BE40 */
+	0xA2,  0x23,  0x22,  0x22,  0x22,  0x3E,  0x3E,  0x00,  0x00,  0xAD,  0x00,  0x20,  0x3C,  0x3C,  0x00,  0x48, 	/* 4BE50 */
+	0x7E,  0x90,  0x01,  0xFF,  0x3C,  0x80,  0x00,  0x80,  0x00,  0xBC,  0x3C,  0xA4,  0x00,  0xA4,  0x3C,  0xA4, 	/* 4BE60 */
+	0x24,  0xAC,  0x25,  0x20,  0x25,  0x21,  0x3E,  0x21,  0x00,  0x1F,  0xAE,  0x00,  0x10,  0x3E,  0x10,  0x00, 	/* 4BE70 */
+	0x28,  0x7F,  0x44,  0x00,  0x82,  0x3F,  0x01,  0x00,  0xFE,  0x00,  0x10,  0x3E,  0x10,  0x00,  0x10,  0x3E, 	/* 4BE80 */
+	0xFE,  0x22,  0x10,  0x22,  0x10,  0x22,  0x10,  0x3F,  0xFF,  0x00,  0x00,  0xB0,  0x00,  0x20,  0x3E,  0x20, 	/* 4BE90 */
+	0x00,  0x20,  0x7F,  0xFF,  0x00,  0x20,  0x3E,  0x20,  0x00,  0x20,  0x01,  0xFE,  0x3E,  0x00,  0x00,  0x00, 	/* 4BEA0 */
+	0x3E,  0xFC,  0x22,  0x84,  0x22,  0x84,  0x22,  0x84,  0x3E,  0xFC,  0x00,  0x00,  0xB1,  0x00,  0x04,  0x3E, 	/* 4BEB0 */
+	0x18,  0x00,  0xF0,  0x7F,  0x10,  0x00,  0x10,  0x3E,  0x10,  0x01,  0xFF,  0x3E,  0x10,  0x00,  0x10,  0x00, 	/* 4BEC0 */
+	0x10,  0x3E,  0xFE,  0x22,  0x82,  0x22,  0x82,  0x22,  0x82,  0x3E,  0xFE,  0x00,  0x00,  0xB2,  0x00,  0x10, 	/* 4BED0 */
+	0x3E,  0x10,  0x00,  0x10,  0x7F,  0xFF,  0x00,  0x10,  0x3E,  0x14,  0x00,  0xE4,  0x00,  0x28,  0x3E,  0x1A, 	/* 4BEE0 */
+	0x00,  0x12,  0x3E,  0x24,  0x22,  0x44,  0x22,  0x88,  0x22,  0x14,  0x3E,  0x62,  0x01,  0x82,  0xB3,  0x00, 	/* 4BEF0 */
+	0x84,  0x3E,  0x44,  0x00,  0x48,  0x7F,  0xFE,  0x00,  0x10,  0x3E,  0x10,  0x00,  0x10,  0x00,  0xFE,  0x3E, 	/* 4BF00 */
+	0x10,  0x00,  0x10,  0x3E,  0x10,  0x23,  0xFF,  0x22,  0x10,  0x22,  0x10,  0x3E,  0x10,  0x00,  0x10,  0xBC, 	/* 4BF10 */
+	0x00,  0x40,  0x3E,  0x40,  0x01,  0xFF,  0x7E,  0x48,  0x00,  0x4A,  0x3E,  0x5A,  0x00,  0x5A,  0x00,  0x5C, 	/* 4BF20 */
+	0x3E,  0x68,  0x00,  0x48,  0x3E,  0x8C,  0x22,  0x94,  0x23,  0x14,  0x22,  0x14,  0x3E,  0x22,  0x00,  0x41, 	/* 4BF30 */
+	0x82,  0x00,  0x50,  0x3C,  0x50,  0x00,  0x52,  0x7E,  0x52,  0x01,  0x54,  0x3D,  0x54,  0x00,  0x50,  0x00, 	/* 4BF40 */
+	0x58,  0x3C,  0xD4,  0x01,  0x52,  0x3E,  0x50,  0x24,  0x50,  0x24,  0x91,  0x24,  0x91,  0x3D,  0x0F,  0x06, 	/* 4BF50 */
+	0x00,  0x84,  0x00,  0x10,  0x3E,  0x12,  0x00,  0xFC,  0x7F,  0x10,  0x00,  0x10,  0x3E,  0xFE,  0x00,  0x10, 	/* 4BF60 */
+	0x00,  0x10,  0x3F,  0xFF,  0x00,  0x38,  0x3E,  0x34,  0x22,  0x54,  0x22,  0x52,  0x22,  0x91,  0x3F,  0x10, 	/* 4BF70 */
+	0x00,  0x10,  0x85,  0x00,  0x10,  0x3E,  0x50,  0x00,  0x50,  0x7F,  0x7E,  0x00,  0x90,  0x3E,  0x90,  0x01, 	/* 4BF80 */
+	0x10,  0x01,  0xFF,  0x3E,  0x38,  0x00,  0x38,  0x3E,  0x54,  0x22,  0x54,  0x22,  0x92,  0x23,  0x11,  0x3E, 	/* 4BF90 */
+	0x10,  0x00,  0x10,  0x87,  0x00,  0x10,  0x3E,  0x10,  0x00,  0xFF,  0x7F,  0x28,  0x00,  0x24,  0x3E,  0x42, 	/* 4BFA0 */
+	0x00,  0xFD,  0x01,  0x00,  0x3E,  0xFF,  0x00,  0x10,  0x3E,  0x10,  0x22,  0x3E,  0x22,  0x22,  0x22,  0x02, 	/* 4BFB0 */
+	0x3E,  0x02,  0x00,  0x0C,  0x89,  0x11,  0x08,  0x08,  0x90,  0x7F,  0xFF,  0x08,  0x10,  0x0B,  0xD0,  0x08, 	/* 4BFC0 */
+	0x08,  0x1F,  0xFC,  0x10,  0x02,  0x27,  0xE1,  0x40,  0x00,  0x07,  0xE0,  0x00,  0x00,  0x0F,  0xF0,  0x08, 	/* 4BFD0 */
+	0x10,  0x0F,  0xF0,  0x08,  0x10,  0x8C,  0x00,  0x10,  0x3E,  0x10,  0x00,  0x10,  0x7F,  0xFF,  0x00,  0x10, 	/* 4BFE0 */
+	0x3E,  0x10,  0x00,  0x10,  0x00,  0xFE,  0x3E,  0x10,  0x00,  0x08,  0x3E,  0xA8,  0x22,  0xA2,  0x22,  0xA1, 	/* 4BFF0 */
+	0x22,  0xA5,  0x3F,  0x24,  0x02,  0x1C,  0x8D,  0x00,  0x00,  0x3E,  0xFE,  0x00,  0x12,  0x7F,  0x52,  0x00, 	/* 4C000 */
+	0x22,  0x3E,  0x32,  0x00,  0x52,  0x01,  0x8C,  0x3E,  0x20,  0x00,  0x10,  0x3E,  0x28,  0x22,  0xAA,  0x22, 	/* 4C010 */
+	0xA1,  0x22,  0xA5,  0x3F,  0x25,  0x02,  0x1C,  0x91,  0x02,  0x40,  0x3D,  0x7F,  0x01,  0xC8,  0x7E,  0x88, 	/* 4C020 */
+	0x00,  0x88,  0x3D,  0x88,  0x01,  0x48,  0x02,  0x7E,  0x3C,  0x48,  0x00,  0xC8,  0x3D,  0x48,  0x26,  0x48, 	/* 4C030 */
+	0x24,  0x48,  0x24,  0x48,  0x3C,  0xBF,  0x03,  0x00,  0x93,  0x08,  0x0C,  0x7E,  0xF0,  0x08,  0x80,  0x0C, 	/* 4C040 */
+	0xFF,  0x78,  0x88,  0x09,  0x08,  0x1B,  0xE8,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x00,  0x07,  0xF0,  0x00, 	/* 4C050 */
+	0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x95,  0x00,  0x01,  0x3D,  0xC6,  0x00,  0x5C, 	/* 4C060 */
+	0x7E,  0x44,  0x00,  0x84,  0x3D,  0x14,  0x03,  0xD7,  0x00,  0x54,  0x3C,  0x54,  0x02,  0x54,  0x3D,  0x54, 	/* 4C070 */
+	0x24,  0x94,  0x24,  0xFF,  0x25,  0x20,  0x3E,  0x18,  0x04,  0x07,  0x98,  0x00,  0x02,  0x3C,  0x1C,  0x00, 	/* 4C080 */
+	0xF0,  0x7E,  0x10,  0x01,  0xFF,  0x3E,  0x38,  0x00,  0x54,  0x3E,  0x92,  0x01,  0x11,  0x00,  0xF8,  0x3E, 	/* 4C090 */
+	0x28,  0x22,  0x2E,  0x22,  0x22,  0x22,  0x42,  0x3E,  0x42,  0x00,  0x8C,  0x9A,  0x00,  0x10,  0x3E,  0x54, 	/* 4C0A0 */
+	0x00,  0x52,  0x7F,  0x92,  0x00,  0x91,  0x3D,  0x7F,  0x00,  0x42,  0x00,  0x42,  0x3E,  0x7E,  0x00,  0x42, 	/* 4C0B0 */
+	0x3E,  0x42,  0x22,  0x7E,  0x22,  0x42,  0x22,  0x42,  0x3E,  0x42,  0x00,  0x46,  0x9E,  0x00,  0x00,  0x3E, 	/* 4C0C0 */
+	0xFE,  0x00,  0x10,  0x7F,  0x10,  0x00,  0xFC,  0x3E,  0x24,  0x00,  0x24,  0x3E,  0x24,  0x01,  0xFF,  0x00, 	/* 4C0D0 */
+	0x00,  0x3E,  0x7E,  0x22,  0x42,  0x22,  0x42,  0x22,  0x42,  0x3E,  0x7E,  0x00,  0x00,  0xA0,  0x00,  0x08, 	/* 4C0E0 */
+	0x3E,  0x0A,  0x00,  0x09,  0x7F,  0xFF,  0x00,  0x88,  0x3E,  0x88,  0x00,  0xEA,  0x00,  0xAA,  0x3E,  0xAA, 	/* 4C0F0 */
+	0x00,  0xAC,  0x3E,  0xA4,  0x22,  0xA4,  0x22,  0xED,  0x22,  0x95,  0x3F,  0x23,  0x02,  0x41,  0xA1,  0x00, 	/* 4C100 */
+	0x14,  0x3C,  0x12,  0x00,  0x10,  0x7F,  0xFF,  0x00,  0x10,  0x3D,  0x52,  0x01,  0x52,  0x01,  0x52,  0x3F, 	/* 4C110 */
+	0xF4,  0x01,  0x4C,  0x3D,  0x48,  0x25,  0x48,  0x25,  0x55,  0x26,  0x25,  0x3C,  0x43,  0x00,  0x01,  0xA3, 	/* 4C120 */
+	0x00,  0x00,  0x3C,  0x00,  0x01,  0xFE,  0x7E,  0x20,  0x00,  0xA4,  0x3C,  0xA4,  0x00,  0xA4,  0x00,  0xA4, 	/* 4C130 */
+	0x3D,  0x6A,  0x01,  0x6A,  0x3E,  0x31,  0x24,  0x20,  0x24,  0x20,  0x24,  0x20,  0x3D,  0xFF,  0x00,  0x00, 	/* 4C140 */
+	0xA4,  0x00,  0x00,  0x3E,  0xBC,  0x00,  0xA4,  0x7F,  0xA4,  0x00,  0xA4,  0x3E,  0xBC,  0x00,  0x80,  0x00, 	/* 4C150 */
+	0x80,  0x3E,  0xFC,  0x00,  0x04,  0x3E,  0x04,  0x23,  0xFF,  0x22,  0x08,  0x22,  0x44,  0x3E,  0x42,  0x00, 	/* 4C160 */
+	0x82,  0xA5,  0x00,  0x10,  0x3E,  0x50,  0x00,  0x50,  0x7F,  0x7E,  0x00,  0x90,  0x3D,  0x10,  0x00,  0x10, 	/* 4C170 */
+	0x01,  0xFF,  0x3E,  0x10,  0x00,  0x00,  0x3E,  0x7E,  0x22,  0x42,  0x22,  0x42,  0x22,  0x42,  0x3E,  0x7E, 	/* 4C180 */
+	0x00,  0x00,  0xA6,  0x00,  0x00,  0x3E,  0xFE,  0x00,  0x04,  0x7F,  0x68,  0x00,  0x10,  0x3E,  0xFE,  0x00, 	/* 4C190 */
+	0x92,  0x00,  0x92,  0x3E,  0xFE,  0x00,  0x92,  0x3E,  0x92,  0x22,  0xFE,  0x22,  0x92,  0x22,  0x92,  0x3E, 	/* 4C1A0 */
+	0x92,  0x00,  0x96,  0xA8,  0x00,  0x40,  0x3C,  0x40,  0x00,  0xFE,  0x7E,  0x80,  0x01,  0x00,  0x3E,  0xFC, 	/* 4C1B0 */
+	0x00,  0xA4,  0x00,  0x94,  0x3F,  0xFF,  0x01,  0x04,  0x3D,  0x44,  0x25,  0x24,  0x25,  0xFF,  0x24,  0x04, 	/* 4C1C0 */
+	0x3C,  0x08,  0x00,  0x30,  0xAC,  0x00,  0x84,  0x1C,  0x44,  0x00,  0x44,  0x7F,  0x28,  0x00,  0xFC,  0x3E, 	/* 4C1D0 */
+	0x84,  0x00,  0x84,  0x3E,  0x84,  0x00,  0xFC,  0x00,  0x28,  0x3E,  0x28,  0x22,  0x28,  0x22,  0x48,  0x22, 	/* 4C1E0 */
+	0x49,  0x3E,  0x89,  0x01,  0x07,  0xAD,  0x00,  0x10,  0x3E,  0x10,  0x01,  0xFF,  0x7E,  0x10,  0x00,  0x10, 	/* 4C1F0 */
+	0x3E,  0xFE,  0x00,  0x00,  0x00,  0xFF,  0x3E,  0x81,  0x00,  0xA9,  0x3E,  0x28,  0x22,  0x28,  0x22,  0x48, 	/* 4C200 */
+	0x22,  0x49,  0x3E,  0x89,  0x03,  0x07,  0xB0,  0x00,  0x24,  0x3E,  0x24,  0x00,  0x48,  0x7F,  0x7F,  0x00, 	/* 4C210 */
+	0xC8,  0x3E,  0xC8,  0x01,  0x48,  0x00,  0x7E,  0x3E,  0x48,  0x00,  0x48,  0x3E,  0x7E,  0x22,  0x48,  0x22, 	/* 4C220 */
+	0x48,  0x22,  0x48,  0x3E,  0x7F,  0x00,  0x00,  0xB2,  0x00,  0x00,  0x3E,  0xFE,  0x00,  0x92,  0x7F,  0x92, 	/* 4C230 */
+	0x00,  0xFE,  0x3E,  0x92,  0x00,  0x92,  0x00,  0xFE,  0x3E,  0x10,  0x01,  0xFF,  0x3E,  0x38,  0x22,  0x54, 	/* 4C240 */
+	0x22,  0x54,  0x22,  0x92,  0x3F,  0x11,  0x00,  0x10,  0xB9,  0x00,  0x48,  0x3C,  0x48,  0x00,  0x48,  0x7F, 	/* 4C250 */
+	0xCF,  0x00,  0x48,  0x3C,  0x48,  0x00,  0x48,  0x01,  0xCF,  0x3C,  0x48,  0x00,  0x48,  0x3C,  0xC8,  0x27, 	/* 4C260 */
+	0x4F,  0x24,  0x48,  0x24,  0x88,  0x3C,  0x88,  0x01,  0x08,  0xBC,  0x00,  0x20,  0x3C,  0x20,  0x01,  0xFE, 	/* 4C270 */
+	0x7F,  0x02,  0x01,  0x02,  0x3C,  0xFC,  0x00,  0x84,  0x00,  0x84,  0x3C,  0xFC,  0x00,  0x84,  0x3C,  0x84, 	/* 4C280 */
+	0x24,  0xFC,  0x24,  0x84,  0x24,  0x84,  0x3F,  0xFF,  0x00,  0x00,  0xBF,  0x00,  0x00,  0x3E,  0xFE,  0x00, 	/* 4C290 */
+	0x92,  0x7F,  0x92,  0x00,  0xFE,  0x3E,  0x92,  0x00,  0x92,  0x00,  0xFE,  0x3E,  0x82,  0x00,  0xBA,  0x3E, 	/* 4C2A0 */
+	0xAA,  0x22,  0xAA,  0x22,  0xBA,  0x23,  0x02,  0x3F,  0x02,  0x02,  0x06,  0x82,  0x00,  0x20,  0x3E,  0x20, 	/* 4C2B0 */
+	0x00,  0x3E,  0x7F,  0x42,  0x00,  0x42,  0x3E,  0x82,  0x01,  0x0C,  0x00,  0x20,  0x3E,  0x20,  0x00,  0xCE, 	/* 4C2C0 */
+	0x3E,  0x82,  0x22,  0xEE,  0x22,  0x82,  0x22,  0x82,  0x3E,  0xFE,  0x00,  0x00,  0x84,  0x00,  0x10,  0x3E, 	/* 4C2D0 */
+	0x10,  0x00,  0xFF,  0x7F,  0x00,  0x00,  0x7C,  0x3E,  0x44,  0x00,  0x7C,  0x00,  0x00,  0x3E,  0xFC,  0x00, 	/* 4C2E0 */
+	0x08,  0x3E,  0x10,  0x23,  0xFF,  0x22,  0x10,  0x22,  0x10,  0x3E,  0x10,  0x00,  0x30,  0x87,  0x00,  0x10, 	/* 4C2F0 */
+	0x3E,  0x52,  0x00,  0x52,  0x7F,  0x54,  0x00,  0xA8,  0x3E,  0x28,  0x00,  0x44,  0x3E,  0x92,  0x00,  0x11, 	/* 4C300 */
+	0x00,  0x52,  0x3E,  0x52,  0x22,  0x9C,  0x22,  0x28,  0x22,  0x44,  0x3E,  0x82,  0x03,  0x01,  0x8B,  0x00, 	/* 4C310 */
+	0x10,  0x3E,  0x10,  0x00,  0xFE,  0x7F,  0x10,  0x00,  0xFE,  0x3E,  0x10,  0x01,  0xFF,  0x00,  0x00,  0x3E, 	/* 4C320 */
+	0x7C,  0x00,  0x44,  0x3E,  0x7C,  0x22,  0x44,  0x22,  0x7C,  0x22,  0x44,  0x3E,  0x44,  0x00,  0x4C,  0x8C, 	/* 4C330 */
+	0x00,  0x10,  0x3C,  0x10,  0x01,  0xFF,  0x7F,  0x10,  0x00,  0xFC,  0x3E,  0x94,  0x00,  0x94,  0x00,  0xFC, 	/* 4C340 */
+	0x3E,  0x94,  0x00,  0x94,  0x3E,  0xFC,  0x22,  0x38,  0x22,  0x54,  0x22,  0x92,  0x3F,  0x11,  0x22,  0x10, 	/* 4C350 */
+	0x8D,  0x00,  0x04,  0x3C,  0x18,  0x01,  0xE4,  0x7E,  0x92,  0x00,  0x91,  0x3D,  0xFD,  0x02,  0x24,  0x00, 	/* 4C360 */
+	0x24,  0x3D,  0xFF,  0x00,  0x24,  0x3C,  0x24,  0x24,  0xFC,  0x24,  0x20,  0x24,  0x20,  0x3C,  0x20,  0x00, 	/* 4C370 */
+	0x60,  0x8F,  0x00,  0x00,  0x3F,  0xFF,  0x01,  0x20,  0x7F,  0x20,  0x01,  0x3E,  0x3D,  0xF2,  0x01,  0x32, 	/* 4C380 */
+	0x01,  0x2A,  0x3D,  0xEA,  0x01,  0x2C,  0x3D,  0x24,  0x25,  0x24,  0x25,  0xEA,  0x27,  0x32,  0x3C,  0x21, 	/* 4C390 */
+	0x00,  0x20,  0x92,  0x00,  0x10,  0x3E,  0x10,  0x01,  0xFF,  0x7F,  0x00,  0x00,  0x00,  0x3E,  0x7C,  0x00, 	/* 4C3A0 */
+	0x44,  0x00,  0x44,  0x3E,  0x44,  0x00,  0x7C,  0x3E,  0x10,  0x22,  0x58,  0x22,  0x54,  0x22,  0x92,  0x3F, 	/* 4C3B0 */
+	0x12,  0x00,  0x30,  0x96,  0x00,  0x20,  0x3C,  0x20,  0x00,  0x50,  0x7E,  0x50,  0x00,  0x88,  0x3D,  0xFC, 	/* 4C3C0 */
+	0x02,  0x02,  0x00,  0x01,  0x3D,  0xFC,  0x01,  0x54,  0x3D,  0x54,  0x25,  0xFC,  0x25,  0x54,  0x25,  0x54, 	/* 4C3D0 */
+	0x3D,  0x54,  0x25,  0x0C,  0x9A,  0x00,  0x10,  0x3C,  0x10,  0x01,  0xFF,  0x7F,  0x01,  0x01,  0x01,  0x3C, 	/* 4C3E0 */
+	0xFE,  0x00,  0x10,  0x00,  0x10,  0x3C,  0x90,  0x00,  0x9E,  0x3C,  0x90,  0x24,  0x90,  0x24,  0x90,  0x25, 	/* 4C3F0 */
+	0x50,  0x3D,  0x30,  0x02,  0x0F,  0x9B,  0x00,  0x10,  0x3E,  0x30,  0x00,  0xD6,  0x7F,  0x92,  0x00,  0x92, 	/* 4C400 */
+	0x3E,  0xD6,  0x00,  0x92,  0x00,  0x92,  0x3E,  0xFE,  0x00,  0x10,  0x3E,  0x18,  0x22,  0x28,  0x22,  0x24, 	/* 4C410 */
+	0x22,  0x44,  0x3E,  0x82,  0x01,  0x01,  0x9C,  0x00,  0x54,  0x3E,  0x54,  0x01,  0xFF,  0x7F,  0x54,  0x00, 	/* 4C420 */
+	0x54,  0x3E,  0x5C,  0x00,  0x40,  0x00,  0x7F,  0x3E,  0x10,  0x00,  0xFF,  0x3E,  0x38,  0x22,  0x34,  0x22, 	/* 4C430 */
+	0x52,  0x22,  0x91,  0x3F,  0x10,  0x22,  0x10,  0x9E,  0x00,  0x00,  0x3D,  0xFF,  0x00,  0x00,  0x7E,  0xFC, 	/* 4C440 */
+	0x00,  0x84,  0x3C,  0x84,  0x00,  0xFC,  0x00,  0x80,  0x3C,  0xFE,  0x01,  0xAA,  0x3D,  0xAA,  0x26,  0xFE, 	/* 4C450 */
+	0x24,  0xAA,  0x24,  0xAA,  0x3C,  0xAA,  0x00,  0x86,  0xA0,  0x00,  0x10,  0x3E,  0x10,  0x00,  0xFF,  0x7F, 	/* 4C460 */
+	0x81,  0x00,  0x81,  0x3E,  0x7E,  0x00,  0x00,  0x00,  0x7E,  0x3E,  0x42,  0x00,  0x42,  0x3E,  0x7E,  0x22, 	/* 4C470 */
+	0x42,  0x22,  0x7E,  0x22,  0x00,  0x3F,  0xFF,  0x00,  0x00,  0xA1,  0x00,  0x58,  0x3C,  0x48,  0x00,  0x44, 	/* 4C480 */
+	0x7E,  0xFC,  0x00,  0xA2,  0x3D,  0x21,  0x02,  0x7C,  0x00,  0x44,  0x3C,  0x04,  0x00,  0x08,  0x3C,  0x30, 	/* 4C490 */
+	0x24,  0xFE,  0x24,  0xAA,  0x24,  0xAA,  0x3F,  0xFF,  0x00,  0x00,  0xA2,  0x00,  0x00,  0x1E,  0xFF,  0x00, 	/* 4C4A0 */
+	0x81,  0x7E,  0x91,  0x01,  0xFE,  0x3E,  0x10,  0x00,  0xFE,  0x00,  0x92,  0x3E,  0xFE,  0x00,  0x92,  0x3E, 	/* 4C4B0 */
+	0x92,  0x22,  0xFE,  0x22,  0x10,  0x23,  0xFF,  0x3E,  0x10,  0x00,  0x10,  0xA4,  0x00,  0x00,  0x3E,  0xEE, 	/* 4C4C0 */
+	0x00,  0xAA,  0x7F,  0xAA,  0x00,  0xEE,  0x3E,  0x00,  0x00,  0xFE,  0x00,  0x00,  0x3F,  0xFF,  0x00,  0x20, 	/* 4C4D0 */
+	0x00,  0x20,  0x3E,  0x7C,  0x22,  0x44,  0x22,  0x04,  0x3E,  0x04,  0x00,  0x18,  0xA6,  0x00,  0x10,  0x3E, 	/* 4C4E0 */
+	0x10,  0x00,  0xFF,  0x7F,  0x44,  0x00,  0x24,  0x3E,  0x28,  0x01,  0xFF,  0x01,  0x11,  0x3F,  0x11,  0x00, 	/* 4C4F0 */
+	0xFE,  0x3E,  0x92,  0x22,  0x92,  0x22,  0x92,  0x22,  0x9C,  0x3E,  0x10,  0x00,  0x10,  0xA7,  0x00,  0x88, 	/* 4C500 */
+	0x3C,  0x89,  0x00,  0xEA,  0x7E,  0x8C,  0x00,  0x89,  0x3C,  0x89,  0x00,  0xE7,  0x03,  0x10,  0x3C,  0x20, 	/* 4C510 */
+	0x00,  0xFC,  0x3C,  0x84,  0x24,  0x84,  0x24,  0xFC,  0x24,  0x84,  0x3C,  0xFC,  0x00,  0x00,  0xAB,  0x00, 	/* 4C520 */
+	0x10,  0x3C,  0x10,  0x01,  0xFF,  0x7E,  0x10,  0x00,  0xFE,  0x3C,  0x92,  0x00,  0xD6,  0x00,  0xBA,  0x3C, 	/* 4C530 */
+	0x92,  0x00,  0xFE,  0x3C,  0x38,  0x24,  0x58,  0x24,  0x94,  0x25,  0x12,  0x3E,  0x11,  0x00,  0x10,  0xAD, 	/* 4C540 */
+	0x00,  0x10,  0x3C,  0x30,  0x00,  0x28,  0x7E,  0x44,  0x00,  0xFE,  0x3D,  0x01,  0x03,  0xE2,  0x01,  0x2A, 	/* 4C550 */
+	0x3D,  0x2A,  0x01,  0xEA,  0x3D,  0x2A,  0x25,  0x2A,  0x25,  0xE2,  0x25,  0x22,  0x3D,  0x22,  0x01,  0x66, 	/* 4C560 */
+	0xAE,  0x00,  0x10,  0x3F,  0x10,  0x00,  0x9F,  0x7F,  0xAA,  0x00,  0x48,  0x3E,  0x08,  0x00,  0x54,  0x00, 	/* 4C570 */
+	0x94,  0x3F,  0x22,  0x00,  0x41,  0x3E,  0xFE,  0x22,  0x42,  0x22,  0x42,  0x22,  0x42,  0x3E,  0x7E,  0x00, 	/* 4C580 */
+	0x00,  0xB1,  0x00,  0x20,  0x3E,  0xFC,  0x00,  0x24,  0x7F,  0x24,  0x01,  0xFF,  0x3E,  0x00,  0x00,  0x7E, 	/* 4C590 */
+	0x00,  0x42,  0x3E,  0x7E,  0x00,  0x08,  0x3E,  0x7E,  0x22,  0x48,  0x22,  0x48,  0x23,  0xFF,  0x3E,  0x08, 	/* 4C5A0 */
+	0x00,  0x08,  0xB3,  0x00,  0x20,  0x3C,  0x20,  0x01,  0xFE,  0x7E,  0x84,  0x00,  0x44,  0x3C,  0x48,  0x03, 	/* 4C5B0 */
+	0xFF,  0x00,  0x00,  0x3C,  0xFC,  0x00,  0x84,  0x3C,  0x84,  0x24,  0xFC,  0x24,  0x84,  0x24,  0x84,  0x3C, 	/* 4C5C0 */
+	0xFC,  0x00,  0x00,  0xB7,  0x00,  0x00,  0x3D,  0xFC,  0x01,  0x04,  0x7F,  0x1C,  0x01,  0xE4,  0x3D,  0x24, 	/* 4C5D0 */
+	0x01,  0xFC,  0x01,  0xAC,  0x3D,  0xAC,  0x01,  0xFC,  0x3D,  0x24,  0x25,  0x35,  0x25,  0x2B,  0x26,  0x3B, 	/* 4C5E0 */
+	0x3E,  0xC5,  0x04,  0x01,  0xB8,  0x00,  0x20,  0x3E,  0x24,  0x00,  0xFC,  0x7F,  0x24,  0x00,  0x28,  0x3E, 	/* 4C5F0 */
+	0x28,  0x01,  0xFF,  0x00,  0x20,  0x3E,  0x7C,  0x00,  0x44,  0x3E,  0xC4,  0x23,  0x7C,  0x22,  0x44,  0x22, 	/* 4C600 */
+	0x44,  0x3E,  0x7C,  0x00,  0x00,  0xBA,  0x00,  0x10,  0x3C,  0x10,  0x01,  0xFF,  0x7E,  0x44,  0x00,  0x28, 	/* 4C610 */
+	0x3C,  0xFF,  0x00,  0x84,  0x00,  0x88,  0x3C,  0xB2,  0x00,  0x84,  0x3C,  0x88,  0x24,  0xB1,  0x25,  0x02, 	/* 4C620 */
+	0x25,  0x0C,  0x3E,  0x30,  0x24,  0xC0,  0xBE,  0x00,  0x44,  0x3E,  0x44,  0x01,  0xFF,  0x7F,  0x44,  0x00, 	/* 4C630 */
+	0x54,  0x3E,  0x10,  0x00,  0x10,  0x01,  0xFF,  0x3E,  0x20,  0x00,  0x20,  0x3E,  0x7E,  0x22,  0xA2,  0x23, 	/* 4C640 */
+	0x22,  0x22,  0x22,  0x3E,  0x3E,  0x00,  0x00,  0x80,  0x00,  0x44,  0x3E,  0x44,  0x00,  0xFF,  0x7F,  0x44, 	/* 4C650 */
+	0x00,  0x7C,  0x3E,  0x44,  0x00,  0x44,  0x00,  0x7C,  0x3E,  0x10,  0x01,  0xFF,  0x3E,  0x38,  0x22,  0x38, 	/* 4C660 */
+	0x22,  0x54,  0x22,  0x92,  0x3F,  0x11,  0x02,  0x10,  0x81,  0x00,  0x00,  0x3C,  0xFC,  0x00,  0x84,  0x7F, 	/* 4C670 */
+	0xFC,  0x00,  0x84,  0x3E,  0x84,  0x00,  0xFC,  0x00,  0x40,  0x3E,  0x7E,  0x00,  0xCA,  0x3E,  0xD2,  0x23, 	/* 4C680 */
+	0x62,  0x22,  0x4A,  0x22,  0x3A,  0x3E,  0x02,  0x00,  0x0C,  0x82,  0x00,  0x00,  0x3E,  0xFE,  0x00,  0x92, 	/* 4C690 */
+	0x7F,  0xFE,  0x00,  0x92,  0x3E,  0x92,  0x00,  0xFE,  0x00,  0x00,  0x3E,  0x7E,  0x00,  0x42,  0x3E,  0x7E, 	/* 4C6A0 */
+	0x22,  0x42,  0x22,  0x7E,  0x22,  0x42,  0x3E,  0x42,  0x22,  0x46,  0x84,  0x01,  0x44,  0x3C,  0xA8,  0x27, 	/* 4C6B0 */
+	0xFE,  0x24,  0x50,  0x27,  0xFF,  0x3C,  0x88,  0x25,  0x74,  0x26,  0x02,  0x27,  0xFD,  0x3C,  0x00,  0x24, 	/* 4C6C0 */
+	0xF8,  0x24,  0x00,  0x25,  0xFC,  0x25,  0x04,  0x25,  0xFC,  0x4C,  0x00,  0x87,  0x00,  0x80,  0x7F,  0xFE, 	/* 4C6D0 */
+	0x42,  0x22,  0x5F,  0xFA,  0x02,  0x20,  0x0F,  0xF8,  0x02,  0x20,  0x7F,  0xFF,  0x05,  0xD0,  0x08,  0x08, 	/* 4C6E0 */
+	0x17,  0xF4,  0x60,  0x03,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x8C,  0x00,  0x00,  0x3D, 	/* 4C6F0 */
+	0xFF,  0x00,  0x04,  0x7E,  0xF4,  0x00,  0x94,  0x3E,  0x94,  0x00,  0xF4,  0x00,  0x0C,  0x3E,  0xFF,  0x00, 	/* 4C700 */
+	0x04,  0x3E,  0xF4,  0x22,  0x94,  0x22,  0x94,  0x22,  0xF4,  0x3E,  0x04,  0x00,  0x0C,  0x8E,  0x00,  0x08, 	/* 4C710 */
+	0x3C,  0x4A,  0x00,  0x2A,  0x7F,  0x2A,  0x00,  0x8C,  0x3C,  0xFF,  0x00,  0x08,  0x03,  0x9C,  0x3C,  0x9C, 	/* 4C720 */
+	0x00,  0xAA,  0x3C,  0xAA,  0x24,  0xC9,  0x25,  0x48,  0x25,  0x28,  0x3E,  0x18,  0x00,  0x07,  0x90,  0x00, 	/* 4C730 */
+	0x20,  0x3C,  0x10,  0x00,  0x50,  0x7E,  0x48,  0x01,  0x52,  0x3D,  0x51,  0x02,  0x65,  0x00,  0x44,  0x3D, 	/* 4C740 */
+	0xBC,  0x00,  0x00,  0x3C,  0xFE,  0x24,  0xAA,  0x24,  0xAA,  0x24,  0xAA,  0x3D,  0xFF,  0x00,  0x00,  0x94, 	/* 4C750 */
+	0x00,  0x10,  0x3E,  0x1E,  0x00,  0x10,  0x7E,  0xFF,  0x00,  0xA6,  0x3E,  0xB8,  0x00,  0xE0,  0x00,  0xA2, 	/* 4C760 */
+	0x3E,  0x9E,  0x00,  0x80,  0x3E,  0xBE,  0x22,  0xA0,  0x23,  0x7F,  0x23,  0x20,  0x3E,  0x3F,  0x00,  0x00, 	/* 4C770 */
+	0x96,  0x00,  0x00,  0x3E,  0xFE,  0x00,  0x92,  0x7F,  0xFE,  0x00,  0x92,  0x3E,  0xFE,  0x00,  0x48,  0x00, 	/* 4C780 */
+	0x49,  0x3E,  0x87,  0x01,  0x20,  0x3E,  0x3C,  0x22,  0xC4,  0x23,  0x28,  0x22,  0x30,  0x3E,  0xCC,  0x03, 	/* 4C790 */
+	0x03,  0x97,  0x00,  0x10,  0x3E,  0x10,  0x01,  0xFF,  0x7E,  0x44,  0x00,  0x28,  0x3F,  0xFF,  0x01,  0x01, 	/* 4C7A0 */
+	0x01,  0x21,  0x3E,  0x20,  0x01,  0xFF,  0x3E,  0x20,  0x22,  0x3C,  0x22,  0x24,  0x22,  0x44,  0x3E,  0x84, 	/* 4C7B0 */
+	0x03,  0x18,  0x99,  0x01,  0x04,  0x3C,  0x88,  0x03,  0xFF,  0x7E,  0x50,  0x01,  0xFC,  0x3C,  0x54,  0x00, 	/* 4C7C0 */
+	0x54,  0x03,  0xFF,  0x3C,  0x54,  0x01,  0xFC,  0x3C,  0x50,  0x24,  0xD8,  0x24,  0xD4,  0x25,  0x52,  0x3E, 	/* 4C7D0 */
+	0x51,  0x24,  0x50,  0x9A,  0x00,  0x58,  0x3E,  0x48,  0x00,  0x44,  0x7E,  0xFC,  0x00,  0x82,  0x3F,  0x59, 	/* 4C7E0 */
+	0x00,  0x48,  0x00,  0x84,  0x3E,  0x82,  0x01,  0x01,  0x3E,  0xFE,  0x22,  0xAA,  0x22,  0xAA,  0x22,  0xAA, 	/* 4C7F0 */
+	0x3F,  0xFF,  0x00,  0x00,  0x9B,  0x00,  0x48,  0x3C,  0x48,  0x01,  0xFF,  0x7E,  0x48,  0x00,  0xFE,  0x3C, 	/* 4C800 */
+	0x48,  0x03,  0xFF,  0x00,  0x10,  0x3C,  0xFE,  0x00,  0x92,  0x3C,  0xFE,  0x24,  0x92,  0x27,  0xFF,  0x24, 	/* 4C810 */
+	0x82,  0x3C,  0x82,  0x00,  0x86,  0x9D,  0x00,  0x42,  0x3C,  0x82,  0x01,  0xE2,  0x7F,  0x22,  0x01,  0x3F, 	/* 4C820 */
+	0x3D,  0xE2,  0x01,  0x22,  0x01,  0xF2,  0x3D,  0x2A,  0x01,  0x2A,  0x3F,  0xE2,  0x24,  0x62,  0x24,  0xA2, 	/* 4C830 */
+	0x25,  0x22,  0x3E,  0x22,  0x00,  0x66,  0xA0,  0x00,  0x10,  0x3C,  0x1E,  0x00,  0x22,  0x7E,  0x54,  0x01, 	/* 4C840 */
+	0xA8,  0x3C,  0x10,  0x00,  0x60,  0x01,  0xFE,  0x3C,  0x50,  0x00,  0x90,  0x3D,  0xFF,  0x24,  0x10,  0x24, 	/* 4C850 */
+	0x92,  0x24,  0x92,  0x3C,  0xFE,  0x00,  0x00,  0xA1,  0x00,  0x04,  0x3C,  0x18,  0x00,  0xE2,  0x7E,  0x92, 	/* 4C860 */
+	0x00,  0x54,  0x3C,  0x48,  0x00,  0x00,  0x00,  0xFE,  0x3C,  0x10,  0x00,  0x10,  0x3F,  0xFF,  0x24,  0x10, 	/* 4C870 */
+	0x24,  0x92,  0x24,  0x92,  0x3C,  0xFE,  0x00,  0x00,  0xA6,  0x04,  0x00,  0x7F,  0xBC,  0x04,  0x25,  0x3F, 	/* 4C880 */
+	0x43,  0x15,  0xFD,  0x1F,  0x24,  0x20,  0x18,  0x20,  0x64,  0x47,  0xF3,  0x00,  0x00,  0x7F,  0xFF,  0x00, 	/* 4C890 */
+	0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0xA8,  0x00,  0x24,  0x3E,  0x24,  0x00,  0xFF, 	/* 4C8A0 */
+	0x7F,  0x24,  0x00,  0x24,  0x3E,  0x7E,  0x00,  0x42,  0x00,  0x7E,  0x3E,  0x42,  0x00,  0x7E,  0x3E,  0x10, 	/* 4C8B0 */
+	0x23,  0xFF,  0x22,  0x18,  0x22,  0x24,  0x3E,  0xC2,  0x03,  0x01,  0xAB,  0x00,  0x10,  0x3C,  0x10,  0x01, 	/* 4C8C0 */
+	0xFF,  0x7F,  0x44,  0x00,  0x28,  0x3E,  0xFE,  0x00,  0x92,  0x00,  0x92,  0x3E,  0xFE,  0x00,  0x92,  0x3E, 	/* 4C8D0 */
+	0xBA,  0x22,  0xAA,  0x22,  0xAA,  0x22,  0xBA,  0x3E,  0x82,  0x00,  0x86,  0xAC,  0x00,  0x00,  0x3F,  0xFE, 	/* 4C8E0 */
+	0x01,  0x32,  0x7C,  0xAA,  0x00,  0x66,  0x3C,  0xAA,  0x03,  0x76,  0x00,  0x50,  0x3C,  0x9C,  0x03,  0x23, 	/* 4C8F0 */
+	0x3C,  0x48,  0x25,  0x92,  0x24,  0x64,  0x25,  0x88,  0x3C,  0x30,  0x25,  0xC0,  0xB3,  0x00,  0x00,  0x3D, 	/* 4C900 */
+	0xFF,  0x01,  0x00,  0x7F,  0x7C,  0x01,  0x44,  0x3D,  0x44,  0x01,  0x7C,  0x01,  0x00,  0x3D,  0xEE,  0x01, 	/* 4C910 */
+	0xAA,  0x3D,  0xAA,  0x25,  0xAA,  0x25,  0xEE,  0x25,  0x00,  0x3D,  0xFF,  0x00,  0x00,  0xB9,  0x00,  0x44, 	/* 4C920 */
+	0x3E,  0x44,  0x01,  0xFF,  0x7E,  0x44,  0x00,  0xFE,  0x3E,  0x92,  0x00,  0x92,  0x00,  0xFE,  0x3E,  0x10, 	/* 4C930 */
+	0x00,  0xFE,  0x3E,  0x10,  0x22,  0xFE,  0x22,  0x10,  0x22,  0x10,  0x3F,  0xFF,  0x00,  0x00,  0xBE,  0x00, 	/* 4C940 */
+	0x00,  0x3E,  0x7C,  0x00,  0x44,  0x7F,  0x7C,  0x00,  0x44,  0x3E,  0x7C,  0x00,  0x00,  0x01,  0xFF,  0x3F, 	/* 4C950 */
+	0x29,  0x01,  0xFF,  0x00,  0x00,  0x3F,  0xFE,  0x22,  0x44,  0x22,  0x38,  0x3E,  0x6C,  0x01,  0x83,  0x81, 	/* 4C960 */
+	0x00,  0x48,  0x3C,  0x48,  0x03,  0xFF,  0x7E,  0x48,  0x01,  0xFE,  0x3C,  0xA4,  0x00,  0xA4,  0x03,  0xFF, 	/* 4C970 */
+	0x3C,  0xA4,  0x00,  0xA4,  0x3D,  0xFE,  0x24,  0x20,  0x27,  0xFF,  0x24,  0x20,  0x3C,  0x20,  0x00,  0x20, 	/* 4C980 */
+	0x89,  0x01,  0xEA,  0x3C,  0x2C,  0x00,  0xC9,  0x7E,  0x46,  0x00,  0x84,  0x3D,  0x7A,  0x02,  0x01,  0x00, 	/* 4C990 */
+	0xFC,  0x3C,  0x84,  0x00,  0x84,  0x3C,  0xFC,  0x24,  0x88,  0x24,  0x48,  0x24,  0x50,  0x3F,  0xFF,  0x00, 	/* 4C9A0 */
+	0x00,  0x8C,  0x00,  0x04,  0x3D,  0xF8,  0x00,  0xA2,  0x7E,  0x92,  0x01,  0xF9,  0x3E,  0x89,  0x00,  0x88, 	/* 4C9B0 */
+	0x00,  0xFC,  0x3C,  0x84,  0x01,  0x04,  0x3D,  0xFE,  0x25,  0x12,  0x26,  0xCA,  0x24,  0xAA,  0x3C,  0xA2, 	/* 4C9C0 */
+	0x01,  0x0C,  0x8E,  0x00,  0x00,  0x3D,  0xFC,  0x00,  0x48,  0x7E,  0x30,  0x03,  0xFE,  0x3C,  0x54,  0x00, 	/* 4C9D0 */
+	0x90,  0x01,  0x30,  0x3F,  0xFE,  0x01,  0x52,  0x3D,  0x56,  0x25,  0x8E,  0x25,  0x7A,  0x25,  0x4A,  0x3D, 	/* 4C9E0 */
+	0x7A,  0x01,  0x06,  0x8F,  0x00,  0x52,  0x3C,  0x52,  0x01,  0xBC,  0x7E,  0xD2,  0x00,  0x55,  0x3C,  0xBF, 	/* 4C9F0 */
+	0x01,  0xF4,  0x00,  0x12,  0x3D,  0xFF,  0x00,  0x94,  0x3C,  0x94,  0x24,  0xC8,  0x25,  0x29,  0x26,  0x15, 	/* 4CA00 */
+	0x3C,  0x23,  0x00,  0x41,  0x96,  0x00,  0x22,  0x3D,  0xEF,  0x00,  0xAA,  0x7E,  0xAA,  0x01,  0xFF,  0x3C, 	/* 4CA10 */
+	0x66,  0x00,  0xAA,  0x01,  0x33,  0x3C,  0xFC,  0x00,  0x84,  0x3C,  0x84,  0x24,  0xFC,  0x24,  0x84,  0x24, 	/* 4CA20 */
+	0x84,  0x3C,  0xFC,  0x00,  0x00,  0x98,  0x00,  0x88,  0x3C,  0x8C,  0x03,  0xFA,  0x7D,  0x2A,  0x00,  0xA8, 	/* 4CA30 */
+	0x3C,  0xA8,  0x03,  0xFF,  0x00,  0x08,  0x3D,  0xEA,  0x01,  0x2A,  0x3D,  0xEC,  0x25,  0x24,  0x25,  0x2D, 	/* 4CA40 */
+	0x25,  0xEB,  0x3C,  0x13,  0x00,  0x21,  0x9A,  0x00,  0x00,  0x3D,  0xFF,  0x00,  0x28,  0x7E,  0xFE,  0x00, 	/* 4CA50 */
+	0xAA,  0x3E,  0xFE,  0x00,  0x00,  0x00,  0x7C,  0x3E,  0x44,  0x00,  0x7C,  0x3E,  0x44,  0x22,  0x7C,  0x22, 	/* 4CA60 */
+	0x10,  0x23,  0xFF,  0x3E,  0x10,  0x00,  0x10,  0x9B,  0x00,  0x84,  0x3C,  0x84,  0x01,  0xFF,  0x7E,  0x84, 	/* 4CA70 */
+	0x01,  0xFF,  0x3C,  0x84,  0x01,  0x4A,  0x02,  0x31,  0x3C,  0xFC,  0x00,  0x84,  0x3C,  0x84,  0x24,  0xFC, 	/* 4CA80 */
+	0x24,  0x84,  0x24,  0x84,  0x3C,  0xFC,  0x00,  0x00,  0x9C,  0x00,  0x84,  0x3C,  0x44,  0x00,  0x48,  0x7F, 	/* 4CA90 */
+	0xFE,  0x00,  0x4A,  0x3D,  0x4A,  0x00,  0xCC,  0x03,  0xFF,  0x3C,  0x00,  0x00,  0xFC,  0x3C,  0x84,  0x24, 	/* 4CAA0 */
+	0xFC,  0x24,  0x84,  0x24,  0x84,  0x3C,  0xFC,  0x00,  0x00,  0x9F,  0x00,  0x00,  0x3C,  0x7C,  0x00,  0x44, 	/* 4CAB0 */
+	0x7E,  0x44,  0x00,  0x7C,  0x3D,  0xEF,  0x01,  0x29,  0x01,  0x29,  0x3D,  0xEF,  0x00,  0x10,  0x3D,  0xFF, 	/* 4CAC0 */
+	0x24,  0x38,  0x24,  0x54,  0x24,  0x92,  0x3D,  0x11,  0x00,  0x10,  0xA6,  0x12,  0x20,  0x7F,  0xA0,  0x12, 	/* 4CAD0 */
+	0x7F,  0x1F,  0xC4,  0x3D,  0x28,  0x55,  0x10,  0x1D,  0x6C,  0x07,  0x83,  0x00,  0x00,  0x7F,  0xFE,  0x00, 	/* 4CAE0 */
+	0x00,  0x07,  0xE0,  0x00,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0xAB,  0x00,  0x20,  0x3C,  0x7C, 	/* 4CAF0 */
+	0x00,  0x88,  0x7F,  0xFF,  0x01,  0x25,  0x3D,  0xC3,  0x01,  0x3C,  0x01,  0x00,  0x3D,  0xFF,  0x01,  0x00, 	/* 4CB00 */
+	0x01,  0x3C,  0x3D,  0x00,  0x25,  0x7E,  0x25,  0x42,  0x3E,  0x7E,  0x04,  0x00,  0xAC,  0x1F,  0x10,  0x11, 	/* 4CB10 */
+	0xFE,  0x1F,  0x44,  0x10,  0xFF,  0x2F,  0x10,  0x29,  0xFE,  0x4F,  0x10,  0x00,  0x80,  0x7F,  0xFF,  0x00, 	/* 4CB20 */
+	0x00,  0x0F,  0xF8,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0xAF,  0x00,  0x00, 	/* 4CB30 */
+	0x3E,  0xFE,  0x00,  0xAA,  0x7F,  0xFE,  0x00,  0x10,  0x3E,  0xFE,  0x00,  0x10,  0x01,  0xFF,  0x3E,  0x44, 	/* 4CB40 */
+	0x00,  0x28,  0x3F,  0xFF,  0x22,  0x10,  0x22,  0xFE,  0x22,  0x10,  0x3E,  0x10,  0x00,  0x10,  0xB0,  0x00, 	/* 4CB50 */
+	0x44,  0x3C,  0x28,  0x00,  0xFE,  0x7E,  0x10,  0x00,  0xFC,  0x3C,  0x10,  0x03,  0xFF,  0x00,  0x2C,  0x3D, 	/* 4CB60 */
+	0xCA,  0x00,  0x48,  0x3D,  0xFF,  0x24,  0x4A,  0x24,  0x6A,  0x25,  0xC5,  0x3C,  0x4B,  0x00,  0xD1,  0xB1, 	/* 4CB70 */
+	0x04,  0x20,  0x3F,  0xFE,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x1C,  0x9C, 	/* 4CB80 */
+	0x00,  0x80,  0x7E,  0xBF,  0x1C,  0x9C,  0x00,  0x80,  0x3E,  0xBE,  0x22,  0xA2,  0x3E,  0xBE,  0x00,  0x80, 	/* 4CB90 */
+	0xB2,  0x00,  0x10,  0x3C,  0x10,  0x01,  0xFF,  0x7E,  0x44,  0x00,  0xAA,  0x3D,  0x29,  0x00,  0xFE,  0x00, 	/* 4CBA0 */
+	0x28,  0x3C,  0xFE,  0x00,  0x28,  0x3D,  0xFF,  0x24,  0x2A,  0x24,  0x4A,  0x25,  0xC4,  0x3C,  0x72,  0x01, 	/* 4CBB0 */
+	0x81,  0xB4,  0x00,  0x08,  0x3D,  0x3E,  0x00,  0xAA,  0x7E,  0xBE,  0x00,  0x08,  0x3E,  0x7F,  0x01,  0x00, 	/* 4CBC0 */
+	0x01,  0x3E,  0x3C,  0x22,  0x03,  0xBE,  0x3C,  0xA0,  0x24,  0xBE,  0x24,  0xA2,  0x25,  0x7E,  0x3E,  0x20, 	/* 4CBD0 */
+	0x04,  0x1F,  0xB7,  0x00,  0x48,  0x3E,  0xFE,  0x00,  0x48,  0x7F,  0x7E,  0x00,  0x90,  0x3E,  0xFC,  0x01, 	/* 4CBE0 */
+	0x90,  0x00,  0xFC,  0x3E,  0x90,  0x00,  0xFE,  0x3E,  0x00,  0x23,  0xFC,  0x22,  0xC8,  0x22,  0x30,  0x3E, 	/* 4CBF0 */
+	0x68,  0x03,  0x87,  0xBD,  0x05,  0x00,  0x19,  0xDC,  0x11,  0x04,  0x1D,  0xDC,  0x1C,  0x5C,  0x11,  0x44, 	/* 4CC00 */
+	0x7F,  0xFF,  0x04,  0x90,  0x0F,  0xF8,  0x10,  0x04,  0x67,  0xF3,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08, 	/* 4CC10 */
+	0x0F,  0xF8,  0x00,  0x00,  0x80,  0x00,  0x10,  0x3D,  0xFF,  0x00,  0x10,  0x7E,  0xFC,  0x00,  0x00,  0x3D, 	/* 4CC20 */
+	0xFE,  0x01,  0x4A,  0x01,  0xFE,  0x3C,  0x84,  0x00,  0xFC,  0x3C,  0x84,  0x24,  0xFC,  0x24,  0x84,  0x24, 	/* 4CC30 */
+	0xFC,  0x3C,  0x44,  0x01,  0x82,  0x83,  0x00,  0x44,  0x3D,  0xEF,  0x00,  0x44,  0x7F,  0xEF,  0x00,  0x44, 	/* 4CC40 */
+	0x3E,  0xAA,  0x01,  0x01,  0x00,  0x7C,  0x3E,  0x44,  0x00,  0x7C,  0x00,  0x44,  0x3E,  0x7C,  0x22,  0x44, 	/* 4CC50 */
+	0x22,  0x7C,  0x3E,  0x24,  0x22,  0xC2,  0x8A,  0x10,  0x04,  0x11,  0xC4,  0x68,  0x1A,  0x13,  0xE4,  0x28, 	/* 4CC60 */
+	0x0A,  0x7D,  0xDF,  0x14,  0x05,  0x31,  0xD4,  0x39,  0x56,  0x55,  0xE5,  0x12,  0x04,  0x07,  0xFC,  0x1A, 	/* 4CC70 */
+	0x10,  0x61,  0xE0,  0x07,  0x30,  0x78,  0x0F,  0x8C,  0x00,  0x48,  0x3C,  0x48,  0x01,  0xFF,  0x7E,  0x48, 	/* 4CC80 */
+	0x00,  0x78,  0x3C,  0x85,  0x03,  0xF5,  0x00,  0xD6,  0x3C,  0xD4,  0x01,  0xD5,  0x3E,  0xF5,  0x24,  0x83, 	/* 4CC90 */
+	0x24,  0x00,  0x25,  0x52,  0x3D,  0x49,  0x02,  0x49,  0x8E,  0x12,  0x05,  0x12,  0xE5,  0x24,  0x0A,  0x3F, 	/* 4CCA0 */
+	0xEF,  0x68,  0x1A,  0x29,  0xEA,  0x28,  0x0A,  0x3C,  0x0F,  0x29,  0xEA,  0x28,  0x0A,  0x3D,  0xEF,  0x29, 	/* 4CCB0 */
+	0x2A,  0x29,  0x2A,  0x29,  0x2A,  0x3D,  0xEF,  0x00,  0x00,  0x90,  0x12,  0x24,  0x3F,  0xBF,  0x64,  0xC8, 	/* 4CCC0 */
+	0x3F,  0x7E,  0x24,  0x48,  0x3F,  0x7E,  0x24,  0x48,  0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF8,  0x00,  0x00, 	/* 4CCD0 */
+	0x0F,  0xF8,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x92,  0x00,  0x20,  0x3C,  0x78,  0x00, 	/* 4CCE0 */
+	0x90,  0x7F,  0xFC,  0x00,  0x84,  0x3C,  0xFD,  0x00,  0x89,  0x01,  0xE7,  0x3C,  0x78,  0x00,  0x90,  0x3D, 	/* 4CCF0 */
+	0xFE,  0x24,  0x92,  0x24,  0xFE,  0x24,  0x35,  0x3C,  0xD1,  0x03,  0x0F,  0x93,  0x00,  0x10,  0x3D,  0xFF, 	/* 4CD00 */
+	0x00,  0x00,  0x7E,  0xEE,  0x00,  0xAA,  0x3C,  0xEE,  0x00,  0x28,  0x00,  0xFE,  0x3C,  0x28,  0x00,  0xFE, 	/* 4CD10 */
+	0x3C,  0x28,  0x25,  0xFF,  0x24,  0x32,  0x25,  0xCC,  0x3C,  0x64,  0x01,  0xC3,  0x96,  0x01,  0x28,  0x39, 	/* 4CD20 */
+	0x2A,  0x02,  0xD9,  0x7E,  0x49,  0x00,  0x88,  0x3B,  0xFF,  0x01,  0x48,  0x03,  0x6A,  0x39,  0x4A,  0x03, 	/* 4CD30 */
+	0x6A,  0x39,  0x44,  0x2B,  0x64,  0x29,  0x5D,  0x29,  0xEB,  0x3F,  0x13,  0x00,  0x21,  0x99,  0x00,  0x48, 	/* 4CD40 */
+	0x3D,  0xFF,  0x00,  0x48,  0x7E,  0xEE,  0x00,  0xAA,  0x3C,  0xEE,  0x00,  0x44,  0x00,  0x48,  0x3C,  0xFE, 	/* 4CD50 */
+	0x01,  0x90,  0x3E,  0xFC,  0x24,  0x90,  0x24,  0xFC,  0x24,  0x90,  0x3C,  0xFF,  0x00,  0x00,  0x9A,  0x01, 	/* 4CD60 */
+	0x4A,  0x3D,  0xEF,  0x02,  0x52,  0x7F,  0xFF,  0x01,  0x4A,  0x3D,  0x6A,  0x02,  0x53,  0x00,  0xFC,  0x3C, 	/* 4CD70 */
+	0x84,  0x00,  0xFC,  0x3C,  0x84,  0x24,  0xFC,  0x24,  0x84,  0x24,  0xFC,  0x3C,  0x44,  0x01,  0x82,  0xB7, 	/* 4CD80 */
+	0x04,  0x10,  0x04,  0x08,  0x08,  0x08,  0x08,  0x84,  0x10,  0x84,  0x21,  0x40,  0x02,  0x20,  0x04,  0x10, 	/* 4CD90 */
+	0x18,  0x0C,  0x6F,  0xFB,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00, 	/* 4CDA0 */
+	0xBA,  0x12,  0x00,  0x12,  0x3E,  0x11,  0x24,  0x20,  0xA4,  0x48,  0x24,  0x08,  0x24,  0x14,  0x24,  0x12, 	/* 4CDB0 */
+	0xFF,  0x21,  0x0C,  0x40,  0x94,  0x3E,  0x14,  0x22,  0x24,  0x22,  0x44,  0x22,  0x84,  0x3F,  0x04,  0x00, 	/* 4CDC0 */
+	0x0C,  0xBF,  0x02,  0x28,  0x3C,  0x24,  0x2A,  0x24,  0x2A,  0x42,  0x41,  0x92,  0x09,  0x18,  0x0A,  0x28, 	/* 4CDD0 */
+	0x34,  0x24,  0x0A,  0x42,  0x7D,  0x81,  0x09,  0x7C,  0x7F,  0x44,  0x18,  0x44,  0x14,  0x44,  0x22,  0x7C, 	/* 4CDE0 */
+	0x40,  0x00,  0x81,  0x08,  0x28,  0x08,  0x24,  0x7F,  0x24,  0x41,  0x42,  0x49,  0x92,  0x3E,  0x18,  0x08, 	/* 4CDF0 */
+	0x28,  0x3E,  0x24,  0x08,  0x42,  0x7E,  0x81,  0x09,  0x7C,  0x3E,  0x44,  0x22,  0x44,  0x22,  0x44,  0x3E, 	/* 4CE00 */
+	0x7C,  0x00,  0x00,  0x86,  0x00,  0x00,  0x3F,  0xFE,  0x00,  0x00,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08, 	/* 4CE10 */
+	0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x04,  0x10,  0x02,  0x10,  0x02,  0x20,  0x00,  0x40, 	/* 4CE20 */
+	0x7F,  0xFF,  0x00,  0x00,  0x88,  0x00,  0x80,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x00,  0x00,  0x7F, 	/* 4CE30 */
+	0xFF,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x04,  0x10,  0x02,  0x10,  0x02, 	/* 4CE40 */
+	0x20,  0x7F,  0xFF,  0x00,  0x00,  0x8A,  0x02,  0x20,  0x1F,  0xFC,  0x12,  0x24,  0x1F,  0xFC,  0x12,  0x24, 	/* 4CE50 */
+	0x1F,  0xFC,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x04,  0x10, 	/* 4CE60 */
+	0x02,  0x20,  0x7F,  0xFF,  0x00,  0x00,  0x8C,  0x00,  0x10,  0x7F,  0x10,  0x00,  0xFF,  0x00,  0x81,  0x3E, 	/* 4CE70 */
+	0xA0,  0x22,  0x3E,  0x22,  0x5A,  0x3E,  0x5A,  0x00,  0xDA,  0x22,  0xAA,  0x23,  0x2A,  0x14,  0x2C,  0x16, 	/* 4CE80 */
+	0x48,  0x18,  0x49,  0x60,  0x89,  0x01,  0x07,  0x8E,  0x00,  0x00,  0x3F,  0x7E,  0x24,  0x22,  0x3F,  0x14, 	/* 4CE90 */
+	0x21,  0x18,  0x3F,  0x64,  0x24,  0x02,  0x3F,  0xFD,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8, 	/* 4CEA0 */
+	0x04,  0x10,  0x02,  0x20,  0x7F,  0xFF,  0x00,  0x00,  0x90,  0x04,  0x90,  0x2E,  0xBA,  0x24,  0x92,  0x2E, 	/* 4CEB0 */
+	0xBA,  0x24,  0x92,  0x2E,  0xBA,  0x3F,  0xFE,  0x00,  0x00,  0x3F,  0xFE,  0x00,  0x00,  0x0F,  0xF8,  0x08, 	/* 4CEC0 */
+	0x08,  0x0F,  0xF8,  0x04,  0x10,  0x7F,  0xFF,  0x00,  0x00,  0x95,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x80, 	/* 4CED0 */
+	0x01,  0x20,  0x02,  0x22,  0x06,  0x24,  0x19,  0x18,  0x61,  0x90,  0x02,  0x88,  0x0C,  0x48,  0x70,  0xC4, 	/* 4CEE0 */
+	0x01,  0x44,  0x02,  0x42,  0x0C,  0x41,  0x70,  0x40,  0x01,  0x80,  0x9A,  0x00,  0x00,  0x3D,  0xFF,  0x24, 	/* 4CEF0 */
+	0x40,  0x24,  0x22,  0x24,  0x62,  0x3C,  0x54,  0x24,  0x94,  0x25,  0x28,  0x24,  0x4C,  0x3C,  0x9C,  0x25, 	/* 4CF00 */
+	0x1A,  0x24,  0x2A,  0x24,  0x49,  0x24,  0x88,  0x25,  0x08,  0x4C,  0x30,  0xA1,  0x02,  0x00,  0x03,  0xE0, 	/* 4CF10 */
+	0x04,  0x40,  0x18,  0x80,  0x7F,  0xF8,  0x10,  0x88,  0x10,  0x88,  0x1F,  0xF8,  0x02,  0x02,  0x05,  0x44, 	/* 4CF20 */
+	0x39,  0xD8,  0x06,  0xA0,  0x39,  0x90,  0x06,  0x8C,  0x78,  0x83,  0x01,  0x80,  0xA2,  0x04,  0x90,  0x08, 	/* 4CF30 */
+	0x88,  0x1F,  0xFC,  0x01,  0x40,  0x7F,  0xFF,  0x02,  0x20,  0x04,  0x10,  0x1F,  0xEC,  0x61,  0x07,  0x06, 	/* 4CF40 */
+	0x88,  0x19,  0xD0,  0x06,  0x60,  0x18,  0xD8,  0x03,  0x44,  0x3C,  0x42,  0x01,  0x80,  0xAA,  0x00,  0x80, 	/* 4CF50 */
+	0x7F,  0xFF,  0x00,  0x00,  0x07,  0xF8,  0x04,  0x08,  0x07,  0xF8,  0x00,  0x00,  0x3F,  0xFE,  0x20,  0x02, 	/* 4CF60 */
+	0x2F,  0xFA,  0x1C,  0x84,  0x03,  0x68,  0x3C,  0xD0,  0x03,  0x4C,  0x3C,  0x43,  0x00,  0xC0,  0xAB,  0x00, 	/* 4CF70 */
+	0x20,  0x3E,  0x38,  0x02,  0x48,  0x14,  0x90,  0x09,  0xFE,  0x08,  0x92,  0x7E,  0x92,  0x0A,  0xFE,  0x0C, 	/* 4CF80 */
+	0x62,  0x08,  0xA2,  0x0B,  0x54,  0x08,  0xB8,  0x0B,  0x54,  0x08,  0x92,  0x0B,  0x11,  0x18,  0x30,  0xAC, 	/* 4CF90 */
+	0x00,  0x20,  0x7F,  0x22,  0x08,  0xFE,  0x11,  0x24,  0x31,  0x24,  0x4A,  0x28,  0x0D,  0xFF,  0x16,  0x14, 	/* 4CFA0 */
+	0x26,  0x22,  0x4D,  0x7E,  0x0C,  0xC2,  0x15,  0x7E,  0x24,  0x42,  0x44,  0x42,  0x04,  0x7E,  0x18,  0x00, 	/* 4CFB0 */
+	0xB8,  0x00,  0x20,  0x00,  0xC0,  0x1F,  0x84,  0x04,  0x58,  0x02,  0x60,  0x03,  0x80,  0x3C,  0x40,  0x00, 	/* 4CFC0 */
+	0xA0,  0x01,  0x20,  0x06,  0x50,  0x38,  0x90,  0x01,  0x10,  0x06,  0x10,  0x38,  0x20,  0x00,  0x20,  0x00, 	/* 4CFD0 */
+	0xC0,  0xB9,  0x04,  0x40,  0x18,  0x40,  0x65,  0x40,  0x12,  0x7E,  0x0C,  0x82,  0x18,  0x82,  0x65,  0x02, 	/* 4CFE0 */
+	0x04,  0x22,  0x0A,  0x12,  0x12,  0x12,  0x66,  0x02,  0x0A,  0x02,  0x12,  0x02,  0x62,  0x02,  0x04,  0x04, 	/* 4CFF0 */
+	0x18,  0x18,  0xBA,  0x04,  0x04,  0x18,  0x04,  0x65,  0x04,  0x12,  0x04,  0x0C,  0xFF,  0x18,  0x0C,  0x64, 	/* 4D000 */
+	0x0C,  0x04,  0x14,  0x0A,  0x14,  0x12,  0x24,  0x66,  0x24,  0x0A,  0x44,  0x12,  0x84,  0x62,  0x04,  0x02, 	/* 4D010 */
+	0x04,  0x0C,  0x0C,  0xBC,  0x04,  0x48,  0x18,  0x48,  0x65,  0x48,  0x12,  0x48,  0x0C,  0x49,  0x18,  0x49, 	/* 4D020 */
+	0x64,  0x7A,  0x04,  0x4C,  0x0A,  0x48,  0x12,  0x48,  0x66,  0x48,  0x0A,  0x48,  0x12,  0x48,  0x62,  0x49, 	/* 4D030 */
+	0x02,  0x69,  0x0D,  0x87,  0x82,  0x04,  0x00,  0x18,  0xFE,  0x65,  0x22,  0x12,  0x22,  0x0C,  0x22,  0x18, 	/* 4D040 */
+	0x42,  0x64,  0x42,  0x04,  0x8C,  0x0B,  0x00,  0x12,  0x7E,  0x66,  0x42,  0x0A,  0x42,  0x12,  0x42,  0x62, 	/* 4D050 */
+	0x42,  0x02,  0x7E,  0x0C,  0x00,  0x85,  0x04,  0x48,  0x18,  0x48,  0x65,  0x48,  0x12,  0x88,  0x0C,  0xFF, 	/* 4D060 */
+	0x19,  0x88,  0x66,  0x88,  0x04,  0x9C,  0x0A,  0x9C,  0x12,  0xAA,  0x66,  0xAA,  0x0A,  0xC9,  0x12,  0x88, 	/* 4D070 */
+	0x62,  0x88,  0x02,  0x88,  0x0C,  0x88,  0x89,  0x04,  0x20,  0x18,  0x20,  0x65,  0x3C,  0x12,  0x44,  0x0C, 	/* 4D080 */
+	0xA8,  0x19,  0x28,  0x64,  0x10,  0x04,  0x28,  0x0A,  0x44,  0x12,  0x82,  0x67,  0x7D,  0x0A,  0x44,  0x12, 	/* 4D090 */
+	0x44,  0x62,  0x44,  0x02,  0x7C,  0x0C,  0x00,  0x8A,  0x04,  0x00,  0x19,  0xFF,  0x65,  0x10,  0x12,  0x10, 	/* 4D0A0 */
+	0x0C,  0x20,  0x18,  0x7E,  0x64,  0x42,  0x04,  0x42,  0x0A,  0x42,  0x12,  0x7E,  0x66,  0x42,  0x0A,  0x42, 	/* 4D0B0 */
+	0x12,  0x42,  0x62,  0x42,  0x02,  0x7E,  0x0C,  0x00,  0x8C,  0x04,  0x10,  0x08,  0x20,  0x15,  0xFE,  0x62, 	/* 4D0C0 */
+	0x82,  0x14,  0x82,  0x08,  0xFE,  0x14,  0x82,  0x64,  0x82,  0x0A,  0xFE,  0x12,  0x28,  0x66,  0x28,  0x0A, 	/* 4D0D0 */
+	0x28,  0x12,  0x48,  0x62,  0x49,  0x04,  0x89,  0x19,  0x07,  0x8D,  0x04,  0x00,  0x18,  0xFE,  0x65,  0x92, 	/* 4D0E0 */
+	0x12,  0x92,  0x0C,  0xFE,  0x18,  0x92,  0x64,  0x92,  0x04,  0xFE,  0x0A,  0x10,  0x12,  0x10,  0x66,  0xFE, 	/* 4D0F0 */
+	0x0A,  0x10,  0x12,  0x10,  0x62,  0x10,  0x03,  0xFF,  0x0C,  0x00,  0x8E,  0x04,  0x10,  0x08,  0x20,  0x15, 	/* 4D100 */
+	0xCC,  0x62,  0x84,  0x14,  0x84,  0x08,  0xEC,  0x14,  0x84,  0x64,  0x84,  0x0A,  0xFC,  0x12,  0x28,  0x66, 	/* 4D110 */
+	0x28,  0x0A,  0x28,  0x12,  0x48,  0x62,  0x49,  0x02,  0x89,  0x0D,  0x07,  0x94,  0x04,  0x10,  0x18,  0x20, 	/* 4D120 */
+	0x65,  0xFE,  0x12,  0x8A,  0x0C,  0xEA,  0x18,  0x92,  0x64,  0xAA,  0x04,  0xC2,  0x0A,  0xFE,  0x12,  0x00, 	/* 4D130 */
+	0x66,  0x88,  0x0A,  0xE9,  0x12,  0x8E,  0x62,  0x88,  0x02,  0xE9,  0x0D,  0x87,  0x98,  0x04,  0x48,  0x18, 	/* 4D140 */
+	0x48,  0x65,  0xFF,  0x12,  0x48,  0x0C,  0x48,  0x18,  0xFC,  0x64,  0x84,  0x04,  0xFC,  0x0A,  0x84,  0x12, 	/* 4D150 */
+	0xFC,  0x66,  0x10,  0x0B,  0xFF,  0x12,  0x10,  0x62,  0x28,  0x02,  0x44,  0x0D,  0x83,  0x9D,  0x00,  0x00, 	/* 4D160 */
+	0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08, 	/* 4D170 */
+	0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x02,  0x30,  0x0C,  0x08,  0x30,  0x04,  0x9E,  0x01, 	/* 4D180 */
+	0x00,  0x01,  0x00,  0x01,  0xF8,  0x01,  0x00,  0x1F,  0xF0,  0x10,  0x10,  0x10,  0x10,  0x1F,  0xF0,  0x10, 	/* 4D190 */
+	0x10,  0x1F,  0xF0,  0x10,  0x10,  0x10,  0x10,  0x1F,  0xF0,  0x04,  0x60,  0x18,  0x18,  0x60,  0x04,  0xA0, 	/* 4D1A0 */
+	0x02,  0x00,  0x03,  0xF0,  0x04,  0x20,  0x08,  0x40,  0x1F,  0xF8,  0x28,  0x08,  0x08,  0x08,  0x0F,  0xF8, 	/* 4D1B0 */
+	0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x02,  0x30,  0x0C,  0x08,  0x30,  0x04, 	/* 4D1C0 */
+	0xA1,  0x00,  0x08,  0x3E,  0x08,  0x22,  0x08,  0x22,  0x08,  0x3F,  0xFF,  0x22,  0x08,  0x22,  0x18,  0x3E, 	/* 4D1D0 */
+	0x18,  0x22,  0x28,  0x22,  0x28,  0x22,  0x48,  0x3E,  0x88,  0x15,  0x08,  0x12,  0x08,  0x22,  0x08,  0x40, 	/* 4D1E0 */
+	0x18,  0xA2,  0x00,  0x00,  0x1F,  0xF8,  0x00,  0x80,  0x7F,  0xFE,  0x00,  0x00,  0x0F,  0xF0,  0x08,  0x10, 	/* 4D1F0 */
+	0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x02,  0x60,  0x0C,  0x18, 	/* 4D200 */
+	0x30,  0x04,  0xA7,  0x02,  0x20,  0x04,  0x10,  0x1F,  0xF8,  0x61,  0x17,  0x02,  0x10,  0x0C,  0x60,  0x30, 	/* 4D210 */
+	0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x04, 	/* 4D220 */
+	0x18,  0x38,  0x06,  0xA8,  0x02,  0x40,  0x04,  0x44,  0x0C,  0x78,  0x14,  0x40,  0x64,  0x42,  0x04,  0x3E, 	/* 4D230 */
+	0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8, 	/* 4D240 */
+	0x0C,  0x18,  0x30,  0x04,  0xA9,  0x00,  0x00,  0x3E,  0x7F,  0x22,  0x40,  0x22,  0x40,  0x3E,  0x40,  0x22, 	/* 4D250 */
+	0x7E,  0x22,  0x62,  0x22,  0x62,  0x3E,  0x52,  0x22,  0x54,  0x22,  0x4C,  0x3E,  0x48,  0x14,  0x94,  0x12, 	/* 4D260 */
+	0x94,  0x21,  0x22,  0x41,  0x41,  0xAA,  0x00,  0x80,  0x01,  0x40,  0x06,  0x30,  0x1B,  0xEC,  0x60,  0x03, 	/* 4D270 */
+	0x0F,  0xF8,  0x00,  0x20,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08, 	/* 4D280 */
+	0x0F,  0xF8,  0x06,  0x30,  0x38,  0x0C,  0xAB,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x88,  0x7F,  0xFF,  0x11, 	/* 4D290 */
+	0x10,  0x1F,  0xF0,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08, 	/* 4D2A0 */
+	0x08,  0x0F,  0xF8,  0x04,  0x18,  0x38,  0x06,  0xAC,  0x00,  0x80,  0x1F,  0xFE,  0x00,  0x80,  0x0F,  0xFC, 	/* 4D2B0 */
+	0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x07,  0xF8,  0x04,  0x08,  0x07,  0xF8,  0x04,  0x08,  0x07,  0xF8, 	/* 4D2C0 */
+	0x04,  0x08,  0x07,  0xF8,  0x02,  0x30,  0x1C,  0x0E,  0xAD,  0x00,  0x04,  0x00,  0x38,  0x1F,  0xC0,  0x10, 	/* 4D2D0 */
+	0x40,  0x1F,  0xFF,  0x10,  0x40,  0x13,  0xFC,  0x12,  0x04,  0x13,  0xFC,  0x12,  0x04,  0x13,  0xFC,  0x12, 	/* 4D2E0 */
+	0x04,  0x23,  0xFC,  0x20,  0x90,  0x43,  0x0C,  0x0C,  0x02,  0xAE,  0x00,  0x14,  0x00,  0x12,  0x00,  0x12, 	/* 4D2F0 */
+	0x7F,  0xFF,  0x00,  0x10,  0x1F,  0xD0,  0x10,  0x50,  0x1F,  0xD0,  0x10,  0x48,  0x1F,  0xC8,  0x10,  0x48, 	/* 4D300 */
+	0x10,  0x48,  0x1F,  0xC5,  0x04,  0x85,  0x18,  0x43,  0x60,  0x21,  0xAF,  0x00,  0x10,  0x3E,  0x10,  0x22, 	/* 4D310 */
+	0xFE,  0x22,  0x82,  0x3E,  0x82,  0x22,  0x00,  0x22,  0xFF,  0x3E,  0x10,  0x22,  0x10,  0x22,  0x10,  0x22, 	/* 4D320 */
+	0x10,  0x3E,  0x10,  0x14,  0x10,  0x12,  0x10,  0x22,  0x10,  0x40,  0x30,  0xB0,  0x09,  0x10,  0x7F,  0xFF, 	/* 4D330 */
+	0x09,  0x10,  0x09,  0xF0,  0x08,  0x00,  0x0F,  0xFC,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8, 	/* 4D340 */
+	0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x06,  0x30,  0x38,  0x0C,  0xB2,  0x04,  0x20,  0x14, 	/* 4D350 */
+	0x26,  0x17,  0xB8,  0x14,  0x21,  0x14,  0x21,  0x17,  0x9F,  0x78,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F, 	/* 4D360 */
+	0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x06,  0x18,  0x38,  0x06,  0xB3,  0x00,  0x14, 	/* 4D370 */
+	0x00,  0x12,  0x00,  0x12,  0x7F,  0xFF,  0x00,  0x10,  0x1F,  0xD0,  0x00,  0x10,  0x7F,  0xF0,  0x10,  0x48, 	/* 4D380 */
+	0x1F,  0xC8,  0x10,  0x48,  0x1F,  0xC8,  0x10,  0x45,  0x1F,  0xC5,  0x0C,  0xC3,  0x70,  0x21,  0xB4,  0x00, 	/* 4D390 */
+	0x80,  0x0F,  0xF0,  0x08,  0x90,  0x0F,  0xF0,  0x00,  0x80,  0x7F,  0xFE,  0x00,  0x00,  0x0F,  0xF0,  0x08, 	/* 4D3A0 */
+	0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x06,  0x18,  0x38,  0x04,  0xB6, 	/* 4D3B0 */
+	0x00,  0x02,  0x3E,  0x0C,  0x22,  0xF0,  0x22,  0x10,  0x3E,  0x10,  0x22,  0x10,  0x22,  0xFC,  0x3E,  0x04, 	/* 4D3C0 */
+	0x22,  0x04,  0x22,  0x08,  0x22,  0x08,  0x3E,  0x90,  0x14,  0xA0,  0x12,  0xC0,  0x21,  0x30,  0x42,  0x0F, 	/* 4D3D0 */
+	0xB7,  0x00,  0x00,  0x3F,  0xFE,  0x22,  0x22,  0x22,  0x22,  0x3F,  0xFE,  0x00,  0x00,  0x0F,  0xF8,  0x08, 	/* 4D3E0 */
+	0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x02,  0x30,  0x0C,  0x0C,  0x30, 	/* 4D3F0 */
+	0x02,  0xB8,  0x04,  0x48,  0x04,  0x44,  0x0B,  0xFF,  0x18,  0x20,  0x28,  0x12,  0x48,  0x0A,  0x0F,  0xFE, 	/* 4D400 */
+	0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x02,  0x30,  0x0C,  0x0C, 	/* 4D410 */
+	0x30,  0x02,  0xBB,  0x02,  0x20,  0x3F,  0xFC,  0x02,  0x24,  0x3F,  0xFC,  0x22,  0x20,  0x3F,  0xFE,  0x04, 	/* 4D420 */
+	0x22,  0x0F,  0xFC,  0x38,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x06, 	/* 4D430 */
+	0x38,  0x38,  0x06,  0xBC,  0x00,  0x10,  0x3E,  0x10,  0x22,  0x10,  0x22,  0x10,  0x3E,  0x1F,  0x22,  0x10, 	/* 4D440 */
+	0x22,  0x10,  0x3E,  0x10,  0x22,  0x10,  0x22,  0x7E,  0x22,  0x42,  0x3E,  0x42,  0x14,  0x42,  0x12,  0x42, 	/* 4D450 */
+	0x22,  0x7E,  0x40,  0x00,  0xBD,  0x00,  0x10,  0x3E,  0x10,  0x22,  0x10,  0x22,  0x24,  0x3E,  0x22,  0x22, 	/* 4D460 */
+	0x4F,  0x23,  0xF1,  0x3E,  0x00,  0x22,  0x00,  0x22,  0x7E,  0x22,  0x42,  0x3E,  0x42,  0x14,  0x42,  0x12, 	/* 4D470 */
+	0x42,  0x22,  0x7E,  0x40,  0x00,  0xBF,  0x01,  0x00,  0x1E,  0x7E,  0x10,  0x12,  0x12,  0x12,  0x11,  0x22, 	/* 4D480 */
+	0x1F,  0x42,  0x71,  0x8C,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08, 	/* 4D490 */
+	0x0F,  0xF8,  0x06,  0x18,  0x38,  0x06,  0x80,  0x08,  0x00,  0x08,  0x7E,  0x7F,  0x42,  0x09,  0x42,  0x09, 	/* 4D4A0 */
+	0x42,  0x11,  0x7E,  0x26,  0x00,  0x4F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08, 	/* 4D4B0 */
+	0x08,  0x0F,  0xF8,  0x06,  0x18,  0x38,  0x06,  0x81,  0x00,  0x80,  0x0F,  0xF8,  0x00,  0x80,  0x04,  0x10, 	/* 4D4C0 */
+	0x7F,  0xFF,  0x04,  0x10,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8, 	/* 4D4D0 */
+	0x08,  0x08,  0x0F,  0xF8,  0x06,  0x18,  0x38,  0x06,  0x82,  0x00,  0x20,  0x3E,  0x20,  0x22,  0x3C,  0x22, 	/* 4D4E0 */
+	0x44,  0x3E,  0x48,  0x22,  0xA8,  0x23,  0x10,  0x22,  0x28,  0x3E,  0x44,  0x22,  0x82,  0x23,  0x7D,  0x3E, 	/* 4D4F0 */
+	0x44,  0x14,  0x44,  0x12,  0x44,  0x22,  0x7C,  0x40,  0x00,  0x83,  0x04,  0x18,  0x09,  0xE0,  0x10,  0x20, 	/* 4D500 */
+	0x77,  0xFF,  0x10,  0x20,  0x13,  0xFC,  0x10,  0x00,  0x1F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10, 	/* 4D510 */
+	0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x04,  0x30,  0x38,  0x0C,  0x84,  0x00,  0x10,  0x3E,  0x10,  0x23, 	/* 4D520 */
+	0xFF,  0x22,  0x10,  0x3E,  0x20,  0x22,  0x3E,  0x22,  0x62,  0x3E,  0x62,  0x22,  0xBE,  0x23,  0x22,  0x22, 	/* 4D530 */
+	0x22,  0x3E,  0x3E,  0x14,  0x22,  0x12,  0x22,  0x22,  0x22,  0x40,  0x26,  0x87,  0x20,  0x80,  0x18,  0xFE, 	/* 4D540 */
+	0x01,  0x22,  0x06,  0x24,  0x18,  0xD0,  0x63,  0x0C,  0x0F,  0xFA,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08, 	/* 4D550 */
+	0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x02,  0x30,  0x0C,  0x08,  0x30,  0x04,  0x88,  0x00,  0x00,  0x7F, 	/* 4D560 */
+	0xFF,  0x02,  0x20,  0x3F,  0xFE,  0x22,  0x22,  0x3F,  0xFE,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F, 	/* 4D570 */
+	0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x06,  0x18,  0x38,  0x06,  0x8A,  0x00,  0x10, 	/* 4D580 */
+	0x3E,  0x14,  0x22,  0x12,  0x22,  0x12,  0x3F,  0xFF,  0x22,  0x10,  0x22,  0x52,  0x3E,  0x52,  0x23,  0xF2, 	/* 4D590 */
+	0x22,  0x4C,  0x22,  0x4C,  0x3E,  0x48,  0x14,  0x55,  0x12,  0x15,  0x22,  0x23,  0x41,  0x41,  0x8D,  0x00, 	/* 4D5A0 */
+	0x08,  0x3E,  0x08,  0x22,  0x08,  0x22,  0xFF,  0x3E,  0x80,  0x22,  0x88,  0x22,  0x88,  0x3E,  0x88,  0x22, 	/* 4D5B0 */
+	0xBE,  0x22,  0x88,  0x22,  0x88,  0x3E,  0x88,  0x15,  0x08,  0x12,  0x08,  0x22,  0xFF,  0x40,  0x00,  0x8E, 	/* 4D5C0 */
+	0x00,  0x28,  0x3E,  0x24,  0x22,  0x20,  0x22,  0x2E,  0x3E,  0xF0,  0x22,  0x2E,  0x22,  0xF0,  0x3E,  0x17, 	/* 4D5D0 */
+	0x22,  0x18,  0x23,  0xF4,  0x22,  0x14,  0x3E,  0x08,  0x14,  0x1A,  0x12,  0x66,  0x23,  0x86,  0x40,  0x02, 	/* 4D5E0 */
+	0x91,  0x00,  0x00,  0x3E,  0xFF,  0x22,  0x80,  0x22,  0x80,  0x3E,  0xBC,  0x22,  0x80,  0x22,  0x80,  0x3E, 	/* 4D5F0 */
+	0xFE,  0x22,  0xB0,  0x22,  0xB2,  0x22,  0xAA,  0x3E,  0xAC,  0x18,  0xA4,  0x15,  0x24,  0x21,  0x32,  0x42, 	/* 4D600 */
+	0xC1,  0x93,  0x01,  0x00,  0x7F,  0xFE,  0x40,  0x02,  0x5F,  0xFA,  0x05,  0x10,  0x19,  0x68,  0x63,  0x86, 	/* 4D610 */
+	0x0F,  0xF0,  0x78,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x06,  0x18, 	/* 4D620 */
+	0x78,  0x06,  0x9A,  0x00,  0x80,  0x7F,  0xFF,  0x08,  0x88,  0x0C,  0x8C,  0x15,  0xD2,  0x22,  0xA0,  0x04, 	/* 4D630 */
+	0x90,  0x1F,  0xFC,  0x68,  0x0B,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x06, 	/* 4D640 */
+	0x18,  0x38,  0x06,  0x9B,  0x04,  0x10,  0x3F,  0x7E,  0x04,  0x10,  0x7F,  0xFF,  0x0A,  0x28,  0x11,  0x44, 	/* 4D650 */
+	0x6F,  0xFB,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x02,  0x30, 	/* 4D660 */
+	0x0C,  0x0C,  0x30,  0x02,  0x9C,  0x00,  0x00,  0x3E,  0xFC,  0x22,  0x84,  0x22,  0x84,  0x3E,  0xFC,  0x22, 	/* 4D670 */
+	0x84,  0x22,  0x84,  0x3E,  0xFC,  0x22,  0x40,  0x22,  0xFE,  0x23,  0x2A,  0x3E,  0x4A,  0x14,  0x92,  0x12, 	/* 4D680 */
+	0x22,  0x22,  0x42,  0x40,  0x0C,  0x9E,  0x11,  0x10,  0x09,  0x20,  0x7F,  0xFE,  0x40,  0x02,  0x47,  0xE2, 	/* 4D690 */
+	0x04,  0x20,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10, 	/* 4D6A0 */
+	0x0F,  0xF0,  0x06,  0x30,  0x38,  0x0C,  0xA0,  0x00,  0x20,  0x3E,  0x20,  0x23,  0xFE,  0x22,  0x84,  0x22, 	/* 4D6B0 */
+	0x44,  0x3E,  0x48,  0x22,  0x48,  0x23,  0xFF,  0x3E,  0x00,  0x22,  0x00,  0x22,  0xFC,  0x3E,  0x84,  0x14, 	/* 4D6C0 */
+	0x84,  0x12,  0x84,  0x22,  0xFC,  0x40,  0x00,  0xA2,  0x00,  0x00,  0x3F,  0xFC,  0x24,  0x44,  0x3F,  0x28, 	/* 4D6D0 */
+	0x21,  0x10,  0x3F,  0x28,  0x24,  0xC6,  0x3F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0, 	/* 4D6E0 */
+	0x08,  0x10,  0x0F,  0xF0,  0x06,  0x30,  0x38,  0x0C,  0xA3,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x1F, 	/* 4D6F0 */
+	0xFC,  0x00,  0x00,  0x3F,  0xFE,  0x22,  0x22,  0x3F,  0xFE,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F, 	/* 4D700 */
+	0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x06,  0x18,  0x38,  0x06,  0xA4,  0x00,  0x28,  0x3E,  0x24,  0x22,  0x2E, 	/* 4D710 */
+	0x22,  0xF2,  0x3E,  0x14,  0x22,  0x18,  0x22,  0x65,  0x3F,  0xAB,  0x22,  0x24,  0x22,  0x2F,  0x22,  0xF2, 	/* 4D720 */
+	0x3E,  0x14,  0x14,  0x18,  0x12,  0x65,  0x23,  0x83,  0x40,  0x01,  0xA6,  0x00,  0x08,  0x3D,  0xEC,  0x24, 	/* 4D730 */
+	0x0A,  0x24,  0x0A,  0x3F,  0xFF,  0x24,  0x48,  0x24,  0x48,  0x25,  0x48,  0x3D,  0x78,  0x25,  0x48,  0x25, 	/* 4D740 */
+	0x48,  0x3D,  0x44,  0x19,  0x75,  0x15,  0xC5,  0x27,  0x03,  0x40,  0x01,  0xAA,  0x02,  0x04,  0x3C,  0x78, 	/* 4D750 */
+	0x20,  0x40,  0x3F,  0x7F,  0x24,  0x48,  0x24,  0x88,  0x4F,  0xF8,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10, 	/* 4D760 */
+	0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x02,  0x60,  0x0C,  0x18,  0x30,  0x04,  0xAD,  0x00,  0x22,  0x3E, 	/* 4D770 */
+	0x22,  0x22,  0xFC,  0x22,  0x24,  0x3E,  0x28,  0x22,  0x28,  0x23,  0xFF,  0x3E,  0x20,  0x22,  0x7C,  0x22, 	/* 4D780 */
+	0xC4,  0x23,  0x44,  0x3E,  0x7C,  0x14,  0x44,  0x12,  0x44,  0x22,  0x7C,  0x40,  0x00,  0xBA,  0x00,  0x12, 	/* 4D790 */
+	0x3E,  0xEC,  0x22,  0x28,  0x23,  0xFF,  0x3E,  0x28,  0x22,  0xFE,  0x22,  0x2A,  0x3F,  0xFF,  0x22,  0x2A, 	/* 4D7A0 */
+	0x22,  0xFE,  0x22,  0x28,  0x3E,  0x2C,  0x14,  0x6C,  0x12,  0xAA,  0x23,  0x29,  0x40,  0x28,  0xBB,  0x00, 	/* 4D7B0 */
+	0x24,  0x3C,  0x22,  0x27,  0xFF,  0x24,  0x20,  0x3D,  0xFC,  0x25,  0x24,  0x25,  0xFC,  0x25,  0x24,  0x3D, 	/* 4D7C0 */
+	0xFC,  0x25,  0x24,  0x24,  0x08,  0x3F,  0xFF,  0x14,  0x88,  0x12,  0x48,  0x22,  0x08,  0x40,  0x18,  0xBC, 	/* 4D7D0 */
+	0x00,  0x48,  0x3C,  0x48,  0x25,  0xFE,  0x24,  0x48,  0x3D,  0xFE,  0x24,  0x48,  0x27,  0xFF,  0x24,  0x20, 	/* 4D7E0 */
+	0x3C,  0xFC,  0x24,  0xA4,  0x24,  0xFC,  0x3C,  0xA4,  0x1B,  0xFF,  0x14,  0x84,  0x24,  0x84,  0x40,  0x8C, 	/* 4D7F0 */
+	0xBD,  0x01,  0x00,  0x7F,  0xFE,  0x44,  0x22,  0x5F,  0xFA,  0x04,  0x20,  0x1F,  0xF8,  0x04,  0x20,  0x7F, 	/* 4D800 */
+	0xFF,  0x04,  0x20,  0x1F,  0xF8,  0x68,  0x16,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x06,  0x30,  0x38, 	/* 4D810 */
+	0x0C,  0x84,  0x04,  0x10,  0x1F,  0x10,  0x04,  0x7C,  0x7F,  0x94,  0x0A,  0x34,  0x3F,  0x94,  0x04,  0x2D, 	/* 4D820 */
+	0x1F,  0x43,  0x04,  0x81,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x06,  0x18, 	/* 4D830 */
+	0x38,  0x06,  0x85,  0x04,  0x20,  0x3F,  0x20,  0x04,  0x3F,  0x7F,  0x64,  0x04,  0xB4,  0x0F,  0x08,  0x11, 	/* 4D840 */
+	0x34,  0x2F,  0xFB,  0x48,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x06, 	/* 4D850 */
+	0x30,  0x38,  0x0E,  0x87,  0x04,  0xEA,  0x04,  0x09,  0x7F,  0xFF,  0x12,  0x28,  0x0A,  0xB4,  0x0C,  0xA5, 	/* 4D860 */
+	0x12,  0xF3,  0x6F,  0xF9,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8, 	/* 4D870 */
+	0x04,  0x10,  0x38,  0x0E,  0x88,  0x00,  0x42,  0x3E,  0x24,  0x22,  0xFF,  0x22,  0x91,  0x22,  0x91,  0x3E, 	/* 4D880 */
+	0xFF,  0x22,  0x91,  0x22,  0xFF,  0x3E,  0x00,  0x22,  0x7E,  0x22,  0x42,  0x3E,  0x7E,  0x14,  0x42,  0x12, 	/* 4D890 */
+	0x42,  0x22,  0x7E,  0x40,  0x00,  0x8A,  0x14,  0x28,  0x1F,  0x3E,  0x24,  0x48,  0x7F,  0xFF,  0x0A,  0x14, 	/* 4D8A0 */
+	0x0A,  0x95,  0x13,  0x23,  0x6F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08, 	/* 4D8B0 */
+	0x0F,  0xF8,  0x06,  0x18,  0x38,  0x06,  0x8B,  0x00,  0x00,  0x1F,  0xFE,  0x12,  0x48,  0x12,  0xFE,  0x15, 	/* 4D8C0 */
+	0x90,  0x1E,  0xFC,  0x14,  0x90,  0x17,  0xFF,  0x12,  0x08,  0x13,  0xF8,  0x12,  0x08,  0x13,  0xF8,  0x22, 	/* 4D8D0 */
+	0x08,  0x23,  0xF8,  0x43,  0x18,  0x1C,  0x06,  0x8D,  0x00,  0x20,  0x3E,  0x7C,  0x22,  0x88,  0x23,  0xFF, 	/* 4D8E0 */
+	0x3E,  0x95,  0x22,  0xE3,  0x22,  0x9C,  0x3E,  0x80,  0x22,  0xFF,  0x22,  0x80,  0x22,  0x9C,  0x3E,  0x80, 	/* 4D8F0 */
+	0x15,  0x3E,  0x13,  0x22,  0x22,  0x3E,  0x40,  0x00,  0x8F,  0x00,  0x80,  0x3F,  0xFF,  0x10,  0x00,  0x0F, 	/* 4D900 */
+	0xFC,  0x04,  0x08,  0x07,  0xF8,  0x04,  0x08,  0x07,  0xF8,  0x00,  0x00,  0x3D,  0xDE,  0x25,  0x52,  0x3D, 	/* 4D910 */
+	0xDA,  0x25,  0x56,  0x3D,  0xD2,  0x24,  0x92,  0x4D,  0x63,  0x90,  0x00,  0x10,  0x3E,  0xFE,  0x22,  0x12, 	/* 4D920 */
+	0x23,  0xFF,  0x3E,  0x12,  0x22,  0xFE,  0x22,  0x10,  0x3F,  0xFF,  0x22,  0xAA,  0x23,  0x15,  0x22,  0x00, 	/* 4D930 */
+	0x3E,  0xFE,  0x14,  0xAA,  0x12,  0xAA,  0x23,  0xFF,  0x40,  0x00,  0x93,  0x00,  0x08,  0x3C,  0x0A,  0x24, 	/* 4D940 */
+	0x09,  0x26,  0xFF,  0x3E,  0x88,  0x26,  0xFA,  0x27,  0xAA,  0x3C,  0xFA,  0x24,  0x9A,  0x27,  0xFA,  0x26, 	/* 4D950 */
+	0xAC,  0x3E,  0xA5,  0x1A,  0xF5,  0x14,  0x8B,  0x21,  0x13,  0x42,  0x21,  0x94,  0x00,  0x00,  0x07,  0xF0, 	/* 4D960 */
+	0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x07,  0xF0,  0x02,  0x30,  0x0C,  0x08,  0x3F,  0x7E,  0x21,  0x42, 	/* 4D970 */
+	0x3D,  0x7A,  0x2F,  0x5E,  0x21,  0x42,  0x3F,  0x7E,  0x12,  0x26,  0x61,  0xC1,  0x96,  0x00,  0x10,  0x3E, 	/* 4D980 */
+	0xFF,  0x22,  0x10,  0x22,  0x7E,  0x3E,  0x00,  0x22,  0xFF,  0x22,  0xA5,  0x3E,  0xFF,  0x22,  0x42,  0x22, 	/* 4D990 */
+	0x7E,  0x22,  0x42,  0x3E,  0x7E,  0x14,  0x42,  0x12,  0x7E,  0x22,  0x62,  0x41,  0x81,  0xA4,  0x00,  0x80, 	/* 4D9A0 */
+	0x00,  0x80,  0x0F,  0xF8,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0x20,  0x09,  0x28, 	/* 4D9B0 */
+	0x09,  0x24,  0x09,  0x24,  0x11,  0x22,  0x22,  0x22,  0x02,  0x20,  0x04,  0x20,  0x08,  0x60,  0xA6,  0x04, 	/* 4D9C0 */
+	0x20,  0x04,  0x20,  0x3F,  0xA0,  0x04,  0x3F,  0x04,  0x44,  0x04,  0x44,  0x7F,  0x84,  0x0A,  0x24,  0x0A, 	/* 4D9D0 */
+	0x28,  0x2B,  0x28,  0x2A,  0x98,  0x2A,  0x98,  0x4A,  0x94,  0x12,  0x24,  0x12,  0x42,  0x26,  0x81,  0xA7, 	/* 4D9E0 */
+	0x04,  0x00,  0x04,  0x7E,  0x3F,  0x42,  0x04,  0x42,  0x04,  0x42,  0x04,  0x7E,  0x7F,  0xC0,  0x0A,  0x40, 	/* 4D9F0 */
+	0x0A,  0x7E,  0x2B,  0x52,  0x2A,  0xD4,  0x2A,  0xCC,  0x4A,  0xC8,  0x12,  0x54,  0x12,  0x62,  0x26,  0x41, 	/* 4DA00 */
+	0xAB,  0x04,  0x10,  0x04,  0x10,  0x3F,  0x7E,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x7F,  0xFF,  0x0A, 	/* 4DA10 */
+	0x28,  0x0B,  0x2C,  0x2A,  0xAC,  0x2A,  0xEA,  0x2A,  0x6A,  0x4A,  0xAA,  0x12,  0x48,  0x12,  0x48,  0x26, 	/* 4DA20 */
+	0x98,  0xAD,  0x04,  0x10,  0x04,  0x12,  0x3F,  0x7E,  0x04,  0x14,  0x04,  0x14,  0x04,  0x18,  0x7F,  0xFF, 	/* 4DA30 */
+	0x0A,  0x14,  0x0A,  0x22,  0x2B,  0x7E,  0x2A,  0xA2,  0x2A,  0xBE,  0x4A,  0xA2,  0x12,  0x22,  0x12,  0x3E, 	/* 4DA40 */
+	0x26,  0x00,  0xB0,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x7F, 	/* 4DA50 */
+	0xFF,  0x00,  0x80,  0x08,  0x80,  0x08,  0x80,  0x08,  0xFC,  0x08,  0x80,  0x14,  0x80,  0x12,  0x80,  0x21, 	/* 4DA60 */
+	0xC0,  0x40,  0x3E,  0xB1,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80, 	/* 4DA70 */
+	0x7F,  0xFE,  0x08,  0x08,  0x04,  0x10,  0x04,  0x20,  0x00,  0x40,  0x11,  0x80,  0x1A,  0x00,  0x16,  0x00, 	/* 4DA80 */
+	0x21,  0xC0,  0x40,  0x3F,  0xB3,  0x04,  0x04,  0x04,  0x04,  0x3F,  0x24,  0x04,  0x24,  0x04,  0x24,  0x04, 	/* 4DA90 */
+	0x24,  0x7F,  0xA4,  0x04,  0x24,  0x14,  0x24,  0x17,  0x27,  0x14,  0x3C,  0x1C,  0xC4,  0x14,  0x04,  0x22, 	/* 4DAA0 */
+	0x04,  0x21,  0x80,  0x40,  0x7F,  0xB4,  0x04,  0x10,  0x04,  0x10,  0x3F,  0x90,  0x04,  0x10,  0x04,  0x10, 	/* 4DAB0 */
+	0x04,  0x18,  0x7F,  0xD4,  0x04,  0x12,  0x14,  0x12,  0x17,  0x90,  0x14,  0x10,  0x1C,  0x10,  0x14,  0x10, 	/* 4DAC0 */
+	0x23,  0x10,  0x20,  0xE0,  0x40,  0x1F,  0xB7,  0x04,  0x00,  0x04,  0x3E,  0x3F,  0x82,  0x04,  0x02,  0x04, 	/* 4DAD0 */
+	0x02,  0x04,  0x02,  0x7F,  0xFE,  0x04,  0x20,  0x14,  0x20,  0x17,  0xA0,  0x14,  0x21,  0x1C,  0x11,  0x14, 	/* 4DAE0 */
+	0x0F,  0x26,  0x00,  0x21,  0xC0,  0x40,  0x3F,  0x81,  0x04,  0x10,  0x04,  0x10,  0x3F,  0x28,  0x04,  0x28, 	/* 4DAF0 */
+	0x04,  0x44,  0x04,  0x8A,  0x7F,  0x31,  0x04,  0xC4,  0x14,  0x08,  0x17,  0x32,  0x14,  0xC4,  0x1C,  0x08, 	/* 4DB00 */
+	0x14,  0x30,  0x22,  0xC0,  0x21,  0x80,  0x40,  0x7F,  0x85,  0x04,  0x00,  0x04,  0xFE,  0x3F,  0x22,  0x04, 	/* 4DB10 */
+	0x22,  0x04,  0x22,  0x04,  0x42,  0x7F,  0x4C,  0x04,  0x80,  0x14,  0x7E,  0x17,  0x42,  0x14,  0x42,  0x1C, 	/* 4DB20 */
+	0x42,  0x14,  0x7E,  0x22,  0x00,  0x21,  0x80,  0x40,  0x7F,  0x8A,  0x04,  0x14,  0x04,  0x12,  0x04,  0x10, 	/* 4DB30 */
+	0x1F,  0x7F,  0x04,  0x50,  0x04,  0x52,  0x3F,  0xD2,  0x04,  0x52,  0x14,  0x54,  0x17,  0x4C,  0x14,  0x69, 	/* 4DB40 */
+	0x15,  0x95,  0x1C,  0x23,  0x24,  0xC1,  0x23,  0x00,  0x40,  0xFF,  0x99,  0x04,  0x10,  0x04,  0x54,  0x3F, 	/* 4DB50 */
+	0x52,  0x04,  0x92,  0x04,  0x7C,  0x04,  0x44,  0x7F,  0xC4,  0x04,  0x7C,  0x14,  0x44,  0x17,  0x44,  0x14, 	/* 4DB60 */
+	0x7C,  0x1C,  0x44,  0x14,  0x44,  0x22,  0x4C,  0x21,  0x80,  0x40,  0x7F,  0xA3,  0x08,  0x00,  0x09,  0xFE, 	/* 4DB70 */
+	0x08,  0xA0,  0x3E,  0xBE,  0x08,  0xE2,  0x08,  0xAA,  0x7F,  0xAA,  0x08,  0xEC,  0x28,  0xA4,  0x2E,  0xA4, 	/* 4DB80 */
+	0x28,  0xEA,  0x3B,  0x32,  0x28,  0x21,  0x24,  0x20,  0x23,  0x00,  0x40,  0xFF,  0xA8,  0x04,  0x40,  0x04, 	/* 4DB90 */
+	0x7E,  0x04,  0xA2,  0x3F,  0xAA,  0x04,  0xFA,  0x04,  0x22,  0x7F,  0x8C,  0x04,  0x40,  0x14,  0x7E,  0x17, 	/* 4DBA0 */
+	0xA2,  0x14,  0xAA,  0x15,  0xFA,  0x1C,  0x22,  0x24,  0xCC,  0x23,  0x00,  0x40,  0xFF,  0xB3,  0x00,  0x00, 	/* 4DBB0 */
+	0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x80,  0x10,  0x80, 	/* 4DBC0 */
+	0x10,  0x80,  0x10,  0xFC,  0x18,  0x80,  0x14,  0x80,  0x23,  0x80,  0x20,  0xC0,  0x40,  0x3F,  0xBA,  0x00, 	/* 4DBD0 */
+	0x10,  0x3E,  0x10,  0x22,  0x10,  0x22,  0xFE,  0x22,  0x10,  0x3E,  0x10,  0x08,  0x10,  0x08,  0x10,  0x29, 	/* 4DBE0 */
+	0xFF,  0x2E,  0x10,  0x28,  0x28,  0x28,  0x28,  0x28,  0x44,  0x2E,  0x44,  0x38,  0x82,  0x61,  0x01,  0xBE, 	/* 4DBF0 */
+	0x00,  0x10,  0x3E,  0x10,  0x22,  0x10,  0x22,  0x10,  0x22,  0x90,  0x3E,  0x90,  0x08,  0x9E,  0x08,  0x90, 	/* 4DC00 */
+	0x28,  0x90,  0x2E,  0x90,  0x28,  0x90,  0x28,  0x90,  0x28,  0x90,  0x2E,  0x90,  0x3B,  0xFF,  0x60,  0x00, 	/* 4DC10 */
+	0x82,  0x00,  0x10,  0x3E,  0x10,  0x22,  0x10,  0x23,  0xFF,  0x22,  0x10,  0x3E,  0x10,  0x08,  0xFC,  0x08, 	/* 4DC20 */
+	0x44,  0x28,  0x44,  0x2E,  0x24,  0x28,  0x28,  0x28,  0x10,  0x28,  0x18,  0x2E,  0x24,  0x38,  0xC2,  0x63, 	/* 4DC30 */
+	0x01,  0x8B,  0x00,  0x28,  0x3E,  0x24,  0x22,  0x24,  0x23,  0xFF,  0x22,  0x20,  0x3E,  0x22,  0x08,  0x22, 	/* 4DC40 */
+	0x08,  0x32,  0x28,  0x54,  0x2E,  0x54,  0x28,  0x48,  0x28,  0x88,  0x28,  0x94,  0x2F,  0x14,  0x3A,  0x22, 	/* 4DC50 */
+	0x60,  0x41,  0x8C,  0x00,  0x10,  0x3E,  0x50,  0x22,  0x50,  0x22,  0x50,  0x22,  0xFE,  0x3E,  0x90,  0x09, 	/* 4DC60 */
+	0x10,  0x08,  0x10,  0x29,  0xFF,  0x2E,  0x10,  0x28,  0x28,  0x28,  0x28,  0x28,  0x44,  0x2E,  0x44,  0x38, 	/* 4DC70 */
+	0x82,  0x61,  0x01,  0x8F,  0x00,  0x80,  0x3C,  0x80,  0x24,  0x8E,  0x24,  0x8A,  0x27,  0xEA,  0x3C,  0xAA, 	/* 4DC80 */
+	0x08,  0xAA,  0x08,  0xAA,  0x28,  0xAA,  0x2E,  0xAA,  0x28,  0xAA,  0x29,  0x2A,  0x29,  0x2A,  0x2D,  0x2E, 	/* 4DC90 */
+	0x3A,  0x20,  0x64,  0xC0,  0x96,  0x00,  0x00,  0x3F,  0xFF,  0x22,  0x20,  0x22,  0x20,  0x22,  0x20,  0x3E, 	/* 4DCA0 */
+	0x40,  0x08,  0x40,  0x08,  0x7C,  0x28,  0xC4,  0x2E,  0xC4,  0x29,  0x44,  0x28,  0x44,  0x28,  0x44,  0x2E, 	/* 4DCB0 */
+	0x44,  0x38,  0x7C,  0x60,  0x00,  0x9A,  0x00,  0x00,  0x3E,  0xFE,  0x22,  0xAA,  0x22,  0xAA,  0x22,  0xAA, 	/* 4DCC0 */
+	0x3E,  0xAA,  0x08,  0xAA,  0x09,  0xFF,  0x28,  0xAA,  0x2E,  0xAA,  0x28,  0xAA,  0x28,  0xAA,  0x28,  0xAA, 	/* 4DCD0 */
+	0x2E,  0xAA,  0x38,  0xAA,  0x60,  0x86,  0x9B,  0x00,  0x10,  0x3E,  0x10,  0x22,  0x10,  0x22,  0xFF,  0x22, 	/* 4DCE0 */
+	0x91,  0x3E,  0x92,  0x08,  0x90,  0x08,  0xFC,  0x28,  0xA4,  0x2E,  0xA4,  0x28,  0x94,  0x28,  0x98,  0x29, 	/* 4DCF0 */
+	0x18,  0x2F,  0x24,  0x3A,  0x42,  0x61,  0x81,  0x9D,  0x00,  0x00,  0x3E,  0xFE,  0x22,  0x80,  0x22,  0x80, 	/* 4DD00 */
+	0x22,  0x80,  0x22,  0xFC,  0x3E,  0x84,  0x08,  0x84,  0x28,  0x84,  0x2E,  0xFC,  0x28,  0x80,  0x28,  0x80, 	/* 4DD10 */
+	0x28,  0x80,  0x2F,  0x80,  0x38,  0xFF,  0x60,  0x00,  0x9F,  0x00,  0x00,  0x3E,  0xFC,  0x22,  0x84,  0x22, 	/* 4DD20 */
+	0x84,  0x22,  0xFC,  0x3E,  0x84,  0x08,  0x84,  0x08,  0xFC,  0x28,  0xA2,  0x2E,  0xA2,  0x28,  0x94,  0x28, 	/* 4DD30 */
+	0x94,  0x28,  0x88,  0x2E,  0xA4,  0x38,  0xC2,  0x63,  0x01,  0xA1,  0x00,  0x10,  0x3E,  0x10,  0x22,  0x10, 	/* 4DD40 */
+	0x23,  0xFF,  0x22,  0x28,  0x22,  0x28,  0x3E,  0x28,  0x08,  0xAC,  0x28,  0xAA,  0x2E,  0xAA,  0x29,  0x29, 	/* 4DD50 */
+	0x2A,  0x29,  0x28,  0x48,  0x2E,  0x48,  0x38,  0x88,  0x61,  0x18,  0xA3,  0x00,  0x10,  0x3E,  0x50,  0x22, 	/* 4DD60 */
+	0x50,  0x22,  0x7E,  0x22,  0x90,  0x3E,  0x90,  0x09,  0x10,  0x09,  0xFF,  0x28,  0x28,  0x2E,  0x28,  0x28, 	/* 4DD70 */
+	0x28,  0x28,  0x48,  0x28,  0x48,  0x2E,  0x89,  0x39,  0x09,  0x62,  0x07,  0xA8,  0x00,  0x10,  0x3E,  0x10, 	/* 4DD80 */
+	0x23,  0xFF,  0x22,  0x28,  0x22,  0x24,  0x22,  0x42,  0x3E,  0xFD,  0x09,  0x00,  0x28,  0xFE,  0x2F,  0x10, 	/* 4DD90 */
+	0x28,  0x10,  0x28,  0x3E,  0x28,  0x22,  0x2E,  0x02,  0x38,  0x02,  0x60,  0x0C,  0xAA,  0x00,  0x20,  0x3E, 	/* 4DDA0 */
+	0x3C,  0x22,  0x48,  0x22,  0x90,  0x23,  0xFF,  0x3E,  0x80,  0x08,  0x80,  0x08,  0xBC,  0x28,  0xA4,  0x2E, 	/* 4DDB0 */
+	0xA4,  0x28,  0xA4,  0x28,  0xAC,  0x28,  0xA0,  0x2F,  0x21,  0x39,  0x21,  0x62,  0x1F,  0xAB,  0x00,  0x00, 	/* 4DDC0 */
+	0x3E,  0xFC,  0x08,  0x84,  0x08,  0xA4,  0x08,  0x94,  0x0E,  0x95,  0x71,  0x03,  0x02,  0x01,  0x0F,  0xF8, 	/* 4DDD0 */
+	0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x04,  0x80,  0x0C,  0xFC,  0x13,  0x80,  0x60,  0xFF,  0xAF,  0x00, 	/* 4DDE0 */
+	0x40,  0x3E,  0x40,  0x22,  0x7C,  0x22,  0x44,  0x22,  0xC8,  0x3E,  0xA8,  0x09,  0x10,  0x28,  0x28,  0x28, 	/* 4DDF0 */
+	0x44,  0x2E,  0x82,  0x29,  0x7D,  0x28,  0x44,  0x29,  0x44,  0x2E,  0x44,  0x38,  0x7C,  0x60,  0x00,  0xB3, 	/* 4DE00 */
+	0x00,  0x28,  0x3E,  0x28,  0x22,  0x2A,  0x23,  0x2A,  0x22,  0xAC,  0x22,  0xAC,  0x3E,  0x28,  0x08,  0x68, 	/* 4DE10 */
+	0x28,  0x6C,  0x2E,  0xAA,  0x29,  0x29,  0x28,  0x48,  0x28,  0x48,  0x2E,  0x89,  0x39,  0x09,  0x62,  0x07, 	/* 4DE20 */
+	0xB5,  0x00,  0x28,  0x3E,  0x24,  0x22,  0x20,  0x22,  0x3E,  0x22,  0xE0,  0x22,  0x3E,  0x3E,  0xE0,  0x08, 	/* 4DE30 */
+	0x1F,  0x28,  0xF0,  0x2E,  0x14,  0x28,  0x14,  0x28,  0x08,  0x29,  0x1A,  0x2E,  0x66,  0x39,  0x86,  0x60, 	/* 4DE40 */
+	0x02,  0xBC,  0x00,  0x00,  0x3E,  0xFE,  0x22,  0x82,  0x22,  0x82,  0x22,  0xFE,  0x3E,  0x80,  0x08,  0x80, 	/* 4DE50 */
+	0x08,  0xFE,  0x28,  0x82,  0x2E,  0xBA,  0x28,  0xAA,  0x28,  0xAA,  0x28,  0xAA,  0x2F,  0x3A,  0x39,  0x02, 	/* 4DE60 */
+	0x62,  0x0C,  0xBF,  0x00,  0x10,  0x3E,  0x10,  0x22,  0xFE,  0x22,  0x10,  0x22,  0x10,  0x3E,  0x10,  0x09, 	/* 4DE70 */
+	0xFF,  0x08,  0x10,  0x28,  0x10,  0x2E,  0x50,  0x28,  0x5E,  0x28,  0x50,  0x28,  0xD0,  0x2E,  0xB0,  0x39, 	/* 4DE80 */
+	0x18,  0x62,  0x07,  0x88,  0x00,  0x10,  0x3E,  0x10,  0x23,  0xFF,  0x22,  0x10,  0x22,  0xFE,  0x3E,  0x92, 	/* 4DE90 */
+	0x08,  0x92,  0x08,  0x92,  0x28,  0xFE,  0x2E,  0x10,  0x28,  0x38,  0x28,  0x38,  0x28,  0x54,  0x2E,  0x92, 	/* 4DEA0 */
+	0x39,  0x11,  0x60,  0x10,  0x89,  0x00,  0x10,  0x3E,  0x10,  0x22,  0xFC,  0x22,  0x84,  0x22,  0x84,  0x3E, 	/* 4DEB0 */
+	0xFC,  0x08,  0x84,  0x08,  0x84,  0x28,  0xFC,  0x2E,  0x92,  0x28,  0x92,  0x28,  0x8C,  0x28,  0x88,  0x2E, 	/* 4DEC0 */
+	0xA4,  0x38,  0xC2,  0x63,  0x01,  0x8A,  0x00,  0x00,  0x3E,  0xFE,  0x22,  0x04,  0x22,  0x68,  0x22,  0x10, 	/* 4DED0 */
+	0x3E,  0xFE,  0x08,  0x92,  0x28,  0x92,  0x28,  0xFE,  0x2E,  0x92,  0x28,  0x92,  0x28,  0xFE,  0x28,  0x92, 	/* 4DEE0 */
+	0x2E,  0x92,  0x38,  0x92,  0x60,  0x96,  0x8F,  0x00,  0x10,  0x3E,  0x12,  0x23,  0xF4,  0x22,  0x58,  0x22, 	/* 4DEF0 */
+	0x58,  0x22,  0x94,  0x3F,  0x12,  0x08,  0x31,  0x28,  0x00,  0x2E,  0xFC,  0x28,  0x84,  0x28,  0xFC,  0x28, 	/* 4DF00 */
+	0x84,  0x2E,  0x84,  0x38,  0xFC,  0x60,  0x00,  0x90,  0x00,  0x28,  0x3E,  0x24,  0x22,  0x2E,  0x23,  0xF2, 	/* 4DF10 */
+	0x22,  0x14,  0x3E,  0x18,  0x08,  0x65,  0x09,  0xAB,  0x28,  0x24,  0x2E,  0x2F,  0x29,  0xF2,  0x28,  0x14, 	/* 4DF20 */
+	0x28,  0x18,  0x2E,  0x65,  0x39,  0x83,  0x60,  0x01,  0x9D,  0x00,  0x00,  0x3E,  0xFE,  0x22,  0x92,  0x22, 	/* 4DF30 */
+	0x92,  0x22,  0xFE,  0x3E,  0x92,  0x08,  0x92,  0x08,  0xFE,  0x28,  0x10,  0x2E,  0xFF,  0x28,  0x10,  0x28, 	/* 4DF40 */
+	0x38,  0x28,  0x54,  0x2E,  0x92,  0x39,  0x11,  0x60,  0x10,  0x9E,  0x00,  0x00,  0x3E,  0xFE,  0x22,  0x82, 	/* 4DF50 */
+	0x22,  0x82,  0x22,  0xFE,  0x3E,  0x88,  0x08,  0x88,  0x08,  0xFF,  0x28,  0x88,  0x2E,  0x88,  0x28,  0xBE, 	/* 4DF60 */
+	0x28,  0xA2,  0x29,  0x22,  0x2F,  0x22,  0x3A,  0x3E,  0x60,  0x00,  0x9F,  0x01,  0x00,  0x3D,  0x00,  0x25, 	/* 4DF70 */
+	0x00,  0x25,  0xFE,  0x26,  0x92,  0x3C,  0x92,  0x08,  0x92,  0x0B,  0xF2,  0x28,  0x92,  0x2E,  0x92,  0x28, 	/* 4DF80 */
+	0x92,  0x28,  0xD2,  0x29,  0x32,  0x2D,  0x1E,  0x32,  0x00,  0x64,  0x00,  0xAA,  0x00,  0x10,  0x3E,  0x10, 	/* 4DF90 */
+	0x22,  0xFF,  0x22,  0x81,  0x22,  0x81,  0x3E,  0x7E,  0x08,  0x00,  0x08,  0x00,  0x29,  0xFF,  0x2E,  0x10, 	/* 4DFA0 */
+	0x28,  0x54,  0x28,  0x52,  0x28,  0x92,  0x2E,  0x91,  0x39,  0x11,  0x60,  0x30,  0xB0,  0x00,  0x70,  0x3E, 	/* 4DFB0 */
+	0x10,  0x22,  0x28,  0x22,  0x44,  0x22,  0xBA,  0x3F,  0x01,  0x09,  0xEA,  0x09,  0x2A,  0x29,  0xAA,  0x2F, 	/* 4DFC0 */
+	0x74,  0x29,  0x34,  0x29,  0xB4,  0x29,  0x6A,  0x2F,  0x2A,  0x39,  0x2A,  0x61,  0x6A,  0xB4,  0x00,  0x00, 	/* 4DFD0 */
+	0x3E,  0xFE,  0x22,  0x24,  0x22,  0x18,  0x22,  0xFE,  0x3E,  0x92,  0x08,  0xFE,  0x08,  0x92,  0x28,  0x92, 	/* 4DFE0 */
+	0x2E,  0xFE,  0x28,  0x10,  0x29,  0xFE,  0x28,  0x12,  0x2E,  0x22,  0x38,  0xC2,  0x63,  0x0C,  0xB5,  0x00, 	/* 4DFF0 */
+	0x04,  0x3E,  0x18,  0x22,  0xF0,  0x22,  0x10,  0x23,  0xFF,  0x3E,  0x10,  0x08,  0xFE,  0x08,  0x92,  0x28, 	/* 4E000 */
+	0xFE,  0x2E,  0x92,  0x28,  0xFE,  0x28,  0x10,  0x28,  0xFE,  0x2E,  0x10,  0x39,  0xFF,  0x60,  0x00,  0x82, 	/* 4E010 */
+	0x00,  0x00,  0x3E,  0xFE,  0x22,  0x24,  0x22,  0x18,  0x23,  0xFF,  0x3E,  0x32,  0x08,  0x54,  0x08,  0x90, 	/* 4E020 */
+	0x28,  0x30,  0x2E,  0x10,  0x29,  0xFF,  0x28,  0x38,  0x28,  0x54,  0x2E,  0x92,  0x39,  0x11,  0x60,  0x10, 	/* 4E030 */
+	0x84,  0x00,  0x10,  0x3E,  0x10,  0x22,  0xFE,  0x22,  0x44,  0x22,  0x24,  0x22,  0x28,  0x3F,  0xFF,  0x09, 	/* 4E040 */
+	0x11,  0x29,  0x11,  0x2E,  0xFE,  0x28,  0x92,  0x28,  0x92,  0x28,  0x92,  0x2E,  0x9C,  0x38,  0x10,  0x60, 	/* 4E050 */
+	0x10,  0x87,  0x01,  0x00,  0x7F,  0xFE,  0x44,  0x22,  0x5F,  0xFA,  0x04,  0x20,  0x1F,  0xF8,  0x04,  0x20, 	/* 4E060 */
+	0x7F,  0xFF,  0x08,  0x10,  0x17,  0xFC,  0x64,  0x13,  0x07,  0xF0,  0x04,  0x80,  0x06,  0xFC,  0x19,  0x80, 	/* 4E070 */
+	0x60,  0x7F,  0x88,  0x00,  0x02,  0x3E,  0x0C,  0x22,  0xF4,  0x22,  0x22,  0x22,  0x92,  0x3E,  0x91,  0x09, 	/* 4E080 */
+	0x11,  0x08,  0x20,  0x28,  0xCE,  0x2E,  0x82,  0x28,  0x82,  0x28,  0xEE,  0x28,  0x82,  0x2E,  0x82,  0x38, 	/* 4E090 */
+	0xFE,  0x60,  0x00,  0x89,  0x00,  0x84,  0x3E,  0x48,  0x23,  0xFE,  0x22,  0x20,  0x22,  0x20,  0x3E,  0xFC, 	/* 4E0A0 */
+	0x08,  0x20,  0x08,  0x20,  0x29,  0xFF,  0x2E,  0x40,  0x28,  0x7E,  0x28,  0x90,  0x29,  0x10,  0x2E,  0x10, 	/* 4E0B0 */
+	0x39,  0xFF,  0x60,  0x00,  0x8A,  0x00,  0x04,  0x3E,  0x18,  0x22,  0xE4,  0x22,  0x92,  0x22,  0x92,  0x3E, 	/* 4E0C0 */
+	0x81,  0x09,  0x11,  0x08,  0x24,  0x28,  0xE8,  0x2E,  0x16,  0x29,  0xFD,  0x28,  0x10,  0x29,  0xFF,  0x2E, 	/* 4E0D0 */
+	0x28,  0x38,  0x44,  0x61,  0x83,  0x8C,  0x00,  0x10,  0x3E,  0x10,  0x22,  0x28,  0x22,  0x28,  0x22,  0x7C, 	/* 4E0E0 */
+	0x22,  0x82,  0x3F,  0x7D,  0x08,  0x44,  0x28,  0x7C,  0x2E,  0x44,  0x28,  0x7C,  0x28,  0x80,  0x2A,  0xFE, 	/* 4E0F0 */
+	0x2D,  0x42,  0x32,  0x7E,  0x60,  0x00,  0x90,  0x00,  0x10,  0x3E,  0x10,  0x23,  0xD7,  0x22,  0x10,  0x23, 	/* 4E100 */
+	0xAB,  0x3E,  0x28,  0x08,  0x44,  0x08,  0x44,  0x28,  0xFE,  0x2F,  0x45,  0x28,  0x7C,  0x28,  0x44,  0x28, 	/* 4E110 */
+	0x7C,  0x2E,  0x44,  0x38,  0x44,  0x60,  0x4C,  0x95,  0x00,  0x00,  0x3E,  0xFE,  0x22,  0x92,  0x22,  0xFE, 	/* 4E120 */
+	0x22,  0x92,  0x3E,  0x92,  0x08,  0xFE,  0x08,  0x54,  0x29,  0xFF,  0x2E,  0x54,  0x28,  0x54,  0x28,  0xFE, 	/* 4E130 */
+	0x28,  0x10,  0x2E,  0xFE,  0x38,  0x10,  0x60,  0x10,  0x99,  0x00,  0x28,  0x00,  0x24,  0x1F,  0xFF,  0x12, 	/* 4E140 */
+	0x20,  0x13,  0x92,  0x12,  0x14,  0x1F,  0xC8,  0x2A,  0x95,  0x2A,  0x63,  0x57,  0xF9,  0x04,  0x08,  0x07, 	/* 4E150 */
+	0xF8,  0x02,  0x40,  0x03,  0x7C,  0x0C,  0xC0,  0x70,  0x3F,  0x9F,  0x00,  0x10,  0x3E,  0xFE,  0x22,  0x10, 	/* 4E160 */
+	0x22,  0xFE,  0x22,  0x10,  0x23,  0xFF,  0x3E,  0x00,  0x08,  0x7C,  0x28,  0x44,  0x2F,  0x7C,  0x28,  0x44, 	/* 4E170 */
+	0x28,  0x7C,  0x29,  0x44,  0x2E,  0x7C,  0x38,  0x46,  0x61,  0x81,  0xA0,  0x00,  0x10,  0x3E,  0x10,  0x22, 	/* 4E180 */
+	0xFF,  0x22,  0x80,  0x22,  0xA4,  0x3E,  0xA4,  0x08,  0xFF,  0x08,  0xA4,  0x28,  0xA4,  0x2E,  0xA4,  0x28, 	/* 4E190 */
+	0xBC,  0x29,  0x00,  0x29,  0x00,  0x2E,  0xAA,  0x38,  0x95,  0x61,  0x01,  0xA3,  0x00,  0x48,  0x3E,  0x48, 	/* 4E1A0 */
+	0x23,  0xFF,  0x22,  0x48,  0x22,  0x48,  0x3E,  0x78,  0x08,  0x10,  0x09,  0xFE,  0x29,  0x12,  0x2F,  0xDE, 	/* 4E1B0 */
+	0x29,  0x56,  0x29,  0x56,  0x29,  0xBA,  0x2F,  0x12,  0x39,  0x12,  0x61,  0x16,  0xA4,  0x00,  0x92,  0x3C, 	/* 4E1C0 */
+	0x92,  0x25,  0x12,  0x25,  0x2D,  0x26,  0x24,  0x3C,  0xC8,  0x08,  0x88,  0x09,  0x08,  0x29,  0x28,  0x2F, 	/* 4E1D0 */
+	0x2E,  0x29,  0x28,  0x29,  0x28,  0x29,  0x28,  0x2D,  0x58,  0x31,  0x48,  0x41,  0x87,  0xB2,  0x00,  0x1C, 	/* 4E1E0 */
+	0x3E,  0x44,  0x22,  0x44,  0x22,  0xFE,  0x23,  0x29,  0x3E,  0xFE,  0x08,  0xAA,  0x08,  0xCE,  0x28,  0xFE, 	/* 4E1F0 */
+	0x2E,  0x82,  0x28,  0xFE,  0x28,  0x04,  0x29,  0xFF,  0x2E,  0x44,  0x38,  0x24,  0x60,  0x0C,  0xB4,  0x00, 	/* 4E200 */
+	0x88,  0x3C,  0x8C,  0x24,  0x8A,  0x27,  0xEA,  0x24,  0x3F,  0x25,  0xC8,  0x3D,  0x48,  0x09,  0x4C,  0x09, 	/* 4E210 */
+	0x4C,  0x2F,  0xCC,  0x28,  0x94,  0x29,  0xD4,  0x29,  0xB4,  0x2A,  0x95,  0x3C,  0xA5,  0x61,  0xC3,  0xB6, 	/* 4E220 */
+	0x00,  0x00,  0x7B,  0xFF,  0x4A,  0x00,  0x4B,  0x14,  0x4A,  0xA4,  0x7B,  0xF7,  0x12,  0x59,  0x13,  0x5E, 	/* 4E230 */
+	0x53,  0x54,  0x5F,  0x54,  0x53,  0xF4,  0x52,  0x44,  0x52,  0x4A,  0x5C,  0x8A,  0x64,  0x92,  0x49,  0x21, 	/* 4E240 */
+	0xBC,  0x00,  0x28,  0x3E,  0xAA,  0x22,  0x6C,  0x22,  0x28,  0x23,  0xFF,  0x3E,  0x44,  0x08,  0x28,  0x08, 	/* 4E250 */
+	0xFE,  0x28,  0x10,  0x2E,  0xFE,  0x28,  0x10,  0x29,  0xFF,  0x28,  0x28,  0x2E,  0x44,  0x38,  0x82,  0x63, 	/* 4E260 */
+	0x01,  0x81,  0x00,  0x00,  0x3E,  0x7C,  0x22,  0x44,  0x22,  0x44,  0x22,  0x7C,  0x3F,  0xEF,  0x09,  0x29, 	/* 4E270 */
+	0x09,  0x29,  0x29,  0xEF,  0x2E,  0x10,  0x29,  0xFF,  0x28,  0x38,  0x28,  0x54,  0x2E,  0x92,  0x39,  0x11, 	/* 4E280 */
+	0x60,  0x10,  0x84,  0x00,  0x08,  0x1F,  0xFF,  0x10,  0xA2,  0x1F,  0x94,  0x10,  0x7F,  0x2F,  0x88,  0x28, 	/* 4E290 */
+	0xBE,  0x4F,  0x88,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x04,  0x80,  0x06,  0xFC,  0x19, 	/* 4E2A0 */
+	0x80,  0x60,  0x7F,  0x85,  0x00,  0x00,  0x3E,  0xFE,  0x22,  0xAA,  0x22,  0xAA,  0x22,  0xFE,  0x3E,  0x40, 	/* 4E2B0 */
+	0x08,  0x7E,  0x08,  0xA2,  0x29,  0xFA,  0x2E,  0xAA,  0x28,  0xAA,  0x28,  0xFA,  0x28,  0x2A,  0x2E,  0x36, 	/* 4E2C0 */
+	0x39,  0xC2,  0x60,  0x0C,  0x87,  0x00,  0x44,  0x3E,  0x44,  0x23,  0xFF,  0x22,  0x44,  0x22,  0x12,  0x3E, 	/* 4E2D0 */
+	0xFE,  0x08,  0x14,  0x09,  0xFF,  0x28,  0x18,  0x2E,  0x24,  0x28,  0x7E,  0x29,  0xA2,  0x28,  0x3E,  0x2E, 	/* 4E2E0 */
+	0x22,  0x38,  0x3E,  0x60,  0x00,  0x8A,  0x00,  0x20,  0x3F,  0xFE,  0x22,  0x20,  0x22,  0xFC,  0x22,  0x00, 	/* 4E2F0 */
+	0x3F,  0xFF,  0x08,  0x02,  0x08,  0xF8,  0x2E,  0x20,  0x29,  0xFF,  0x28,  0x04,  0x2B,  0xFF,  0x29,  0x64, 	/* 4E300 */
+	0x2F,  0x54,  0x39,  0xC4,  0x60,  0x0C,  0x8B,  0x00,  0x10,  0x3E,  0x10,  0x23,  0xFF,  0x22,  0x29,  0x23, 	/* 4E310 */
+	0xD6,  0x3E,  0xD6,  0x09,  0x55,  0x0A,  0xD5,  0x28,  0x00,  0x2E,  0x82,  0x28,  0xFE,  0x28,  0x82,  0x28, 	/* 4E320 */
+	0xFE,  0x2E,  0x82,  0x38,  0x82,  0x61,  0x02,  0x8D,  0x00,  0x00,  0x3F,  0xFE,  0x22,  0x22,  0x22,  0xEE, 	/* 4E330 */
+	0x22,  0x22,  0x3F,  0xFE,  0x08,  0x44,  0x08,  0x48,  0x28,  0xFF,  0x2F,  0x88,  0x28,  0xFE,  0x28,  0x88, 	/* 4E340 */
+	0x28,  0xFE,  0x2E,  0x88,  0x38,  0xFF,  0x60,  0x80,  0x91,  0x01,  0xC0,  0x79,  0x4E,  0x4A,  0x2A,  0x4B, 	/* 4E350 */
+	0xEA,  0x4D,  0x5A,  0x7B,  0xEC,  0x12,  0xAC,  0x13,  0x6A,  0x53,  0xE9,  0x5E,  0x29,  0x53,  0xE9,  0x50, 	/* 4E360 */
+	0x89,  0x57,  0xFE,  0x58,  0xC8,  0x71,  0x28,  0x42,  0x08,  0x93,  0x00,  0x11,  0x3E,  0xEE,  0x22,  0x88, 	/* 4E370 */
+	0x22,  0xFF,  0x22,  0xAA,  0x3E,  0xB2,  0x09,  0x22,  0x08,  0xFC,  0x28,  0x84,  0x2E,  0xFC,  0x28,  0x84, 	/* 4E380 */
+	0x28,  0xFC,  0x28,  0x84,  0x2E,  0xFC,  0x38,  0x6C,  0x63,  0x82,  0x94,  0x00,  0x10,  0x3D,  0xFF,  0x25, 	/* 4E390 */
+	0x00,  0x25,  0x7E,  0x25,  0x52,  0x3D,  0x7E,  0x09,  0x52,  0x09,  0x7E,  0x2F,  0x10,  0x29,  0xFF,  0x29, 	/* 4E3A0 */
+	0x25,  0x29,  0xD3,  0x2B,  0x7E,  0x2D,  0x10,  0x32,  0xFF,  0x64,  0x00,  0x99,  0x00,  0x00,  0x3D,  0xDE, 	/* 4E3B0 */
+	0x25,  0x52,  0x25,  0xDE,  0x25,  0x52,  0x3D,  0xDE,  0x09,  0x02,  0x09,  0x52,  0x29,  0x7A,  0x2D,  0xD2, 	/* 4E3C0 */
+	0x29,  0x7A,  0x29,  0x52,  0x29,  0x7A,  0x2F,  0x52,  0x39,  0x7A,  0x61,  0x06,  0xA1,  0x00,  0x00,  0x3F, 	/* 4E3D0 */
+	0xFE,  0x22,  0x48,  0x22,  0x78,  0x22,  0x48,  0x3E,  0x7E,  0x09,  0xC8,  0x08,  0x08,  0x29,  0xFF,  0x2E, 	/* 4E3E0 */
+	0xAA,  0x28,  0xEE,  0x28,  0xAA,  0x28,  0xEE,  0x2E,  0xAB,  0x39,  0xFE,  0x60,  0x22,  0xAA,  0x00,  0x48, 	/* 4E3F0 */
+	0x3F,  0xFF,  0x24,  0x48,  0x25,  0xDE,  0x25,  0x52,  0x25,  0xDE,  0x3D,  0xDE,  0x09,  0x4A,  0x2D,  0x7A, 	/* 4E400 */
+	0x29,  0xD2,  0x29,  0x7A,  0x29,  0x52,  0x29,  0x7A,  0x2F,  0x52,  0x39,  0x7A,  0x61,  0x06,  0xAB,  0x00, 	/* 4E410 */
+	0x80,  0x01,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x11,  0x0F,  0xF2,  0x08, 	/* 4E420 */
+	0x14,  0x08,  0x18,  0x0F,  0xF0,  0x78,  0x30,  0x00,  0xD0,  0x03,  0x10,  0x3C,  0x10,  0x00,  0x30,  0xAC, 	/* 4E430 */
+	0x02,  0x00,  0x04,  0x7E,  0x1F,  0x02,  0x11,  0x02,  0x11,  0x02,  0x1F,  0x7E,  0x11,  0x40,  0x1F,  0x40, 	/* 4E440 */
+	0x11,  0x40,  0x11,  0xFE,  0x1F,  0x02,  0x73,  0x02,  0x05,  0x02,  0x19,  0x02,  0x61,  0x04,  0x07,  0x18, 	/* 4E450 */
+	0xAF,  0x08,  0x00,  0x10,  0xFE,  0x3E,  0x80,  0x22,  0x84,  0x3E,  0x84,  0x22,  0xA4,  0x3E,  0x98,  0x22, 	/* 4E460 */
+	0x88,  0x23,  0x8C,  0x3E,  0x94,  0x62,  0x92,  0x06,  0xA2,  0x0A,  0xC0,  0x12,  0x80,  0x62,  0xFF,  0x06, 	/* 4E470 */
+	0x80,  0xB0,  0x04,  0x10,  0x08,  0x10,  0x1E,  0x10,  0x12,  0x10,  0x13,  0xFF,  0x1E,  0x10,  0x12,  0x38, 	/* 4E480 */
+	0x1E,  0x38,  0x12,  0x54,  0x12,  0x54,  0x1E,  0x92,  0x67,  0x11,  0x0A,  0x7C,  0x12,  0x10,  0x62,  0x10, 	/* 4E490 */
+	0x06,  0x10,  0xB1,  0x04,  0x00,  0x09,  0xF8,  0x1E,  0x48,  0x12,  0x4E,  0x12,  0x42,  0x1E,  0x42,  0x12, 	/* 4E4A0 */
+	0x82,  0x1F,  0x1C,  0x12,  0x10,  0x13,  0xFF,  0x1E,  0x38,  0x66,  0x54,  0x0A,  0x92,  0x13,  0x11,  0x62, 	/* 4E4B0 */
+	0x10,  0x06,  0x10,  0xBE,  0x04,  0x44,  0x08,  0x28,  0x1E,  0xFF,  0x12,  0x10,  0x12,  0xFE,  0x1E,  0x10, 	/* 4E4C0 */
+	0x12,  0x10,  0x1F,  0xFF,  0x12,  0x10,  0x12,  0x10,  0x1F,  0xFF,  0x66,  0x18,  0x0A,  0x28,  0x12,  0x44, 	/* 4E4D0 */
+	0x62,  0x82,  0x07,  0x01,  0x85,  0x08,  0x00,  0x11,  0xFF,  0x3D,  0x20,  0x25,  0x2A,  0x25,  0x54,  0x3D, 	/* 4E4E0 */
+	0x5F,  0x25,  0xD4,  0x3D,  0x74,  0x25,  0x5E,  0x27,  0x54,  0x7D,  0x54,  0x0D,  0x5E,  0x15,  0x54,  0x26, 	/* 4E4F0 */
+	0x54,  0x44,  0x5F,  0x0C,  0x40,  0x86,  0x04,  0x28,  0x08,  0xFE,  0x1E,  0xAA,  0x12,  0xFE,  0x12,  0xAA, 	/* 4E500 */
+	0x1E,  0xFE,  0x12,  0x00,  0x1F,  0xFF,  0x12,  0x00,  0x12,  0xFE,  0x1E,  0x82,  0x66,  0xFE,  0x0A,  0x44, 	/* 4E510 */
+	0x12,  0x28,  0x63,  0xFF,  0x06,  0x00,  0x88,  0x08,  0x08,  0x11,  0xFF,  0x3D,  0x22,  0x25,  0x24,  0x25, 	/* 4E520 */
+	0x5F,  0x3D,  0xF4,  0x25,  0x5E,  0x3D,  0x54,  0x25,  0x5E,  0x27,  0x54,  0x7D,  0x5F,  0x0D,  0x10,  0x16, 	/* 4E530 */
+	0xAA,  0x24,  0xA9,  0x45,  0x25,  0x0C,  0x1C,  0x8A,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80, 	/* 4E540 */
+	0x0F,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x80, 	/* 4E550 */
+	0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x8B,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xA0,  0x04, 	/* 4E560 */
+	0x20,  0x3F,  0xA0,  0x24,  0xA0,  0x24,  0xA0,  0x3F,  0xA0,  0x24,  0xA0,  0x24,  0xA0,  0x3F,  0xA0,  0x04, 	/* 4E570 */
+	0x21,  0x7F,  0xE1,  0x04,  0x11,  0x04,  0x0F,  0x04,  0x00,  0x8C,  0x04,  0x20,  0x04,  0x20,  0x7F,  0xA0, 	/* 4E580 */
+	0x04,  0x20,  0x3F,  0xFC,  0x25,  0x24,  0x25,  0x24,  0x3F,  0x24,  0x25,  0x24,  0x25,  0x24,  0x3F,  0x24, 	/* 4E590 */
+	0x04,  0x24,  0x7F,  0xC4,  0x04,  0x45,  0x04,  0x85,  0x05,  0x03,  0x8D,  0x00,  0x00,  0x3F,  0xFE,  0x20, 	/* 4E5A0 */
+	0x82,  0x20,  0x82,  0x1F,  0xFC,  0x00,  0x80,  0x1F,  0xFC,  0x10,  0x84,  0x1F,  0xFC,  0x10,  0x84,  0x10, 	/* 4E5B0 */
+	0x84,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x92,  0x04,  0x00,  0x04,  0x7E, 	/* 4E5C0 */
+	0x7F,  0x90,  0x04,  0x10,  0x3F,  0x10,  0x25,  0x10,  0x25,  0x10,  0x3F,  0xFF,  0x25,  0x10,  0x25,  0x10, 	/* 4E5D0 */
+	0x3F,  0x10,  0x04,  0x10,  0x7F,  0x90,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x9B,  0x08,  0x00,  0x08, 	/* 4E5E0 */
+	0x7F,  0x7F,  0x40,  0x08,  0x40,  0x3E,  0x5E,  0x2A,  0x52,  0x2A,  0x52,  0x3E,  0x52,  0x2A,  0x52,  0x2A, 	/* 4E5F0 */
+	0x52,  0x3E,  0x5C,  0x08,  0x50,  0x7F,  0x90,  0x08,  0x91,  0x09,  0x11,  0x08,  0x0F,  0x9F,  0x08,  0x20, 	/* 4E600 */
+	0x08,  0x20,  0x7F,  0xA0,  0x08,  0x20,  0x3F,  0x7E,  0x29,  0x52,  0x29,  0x54,  0x3F,  0x90,  0x29,  0x10, 	/* 4E610 */
+	0x29,  0x10,  0x3F,  0x28,  0x08,  0x28,  0x7F,  0xC4,  0x08,  0x44,  0x08,  0x82,  0x09,  0x01,  0xA2,  0x04, 	/* 4E620 */
+	0x00,  0x04,  0x3E,  0x7F,  0xC0,  0x04,  0x00,  0x3F,  0x00,  0x25,  0x00,  0x25,  0xFF,  0x3F,  0x10,  0x25, 	/* 4E630 */
+	0x10,  0x25,  0x10,  0x3F,  0x24,  0x04,  0x24,  0x7F,  0xA2,  0x04,  0x4E,  0x05,  0xF1,  0x04,  0x01,  0xA3, 	/* 4E640 */
+	0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8, 	/* 4E650 */
+	0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x18,  0x0C,  0x06,  0x30,  0x00,  0x00,  0x0E,  0x38,  0x70,  0x07, 	/* 4E660 */
+	0xAB,  0x08,  0x10,  0x08,  0x10,  0x7F,  0x28,  0x08,  0x28,  0x3E,  0x44,  0x2A,  0x92,  0x2B,  0x11,  0x3E, 	/* 4E670 */
+	0x24,  0x2A,  0x44,  0x2A,  0x88,  0x3E,  0x12,  0x08,  0x22,  0x7F,  0x44,  0x08,  0x08,  0x08,  0x30,  0x08, 	/* 4E680 */
+	0xC0,  0xB8,  0x04,  0x08,  0x04,  0x08,  0x7F,  0xC8,  0x04,  0x08,  0x3F,  0x7F,  0x25,  0x49,  0x25,  0x49, 	/* 4E690 */
+	0x3F,  0x49,  0x25,  0x7F,  0x25,  0x49,  0x3F,  0x49,  0x04,  0x49,  0x7F,  0xC9,  0x04,  0x49,  0x04,  0x7F, 	/* 4E6A0 */
+	0x04,  0x00,  0xBB,  0x08,  0x00,  0x09,  0xFF,  0x7F,  0x04,  0x08,  0x04,  0x3E,  0xF4,  0x2A,  0x94,  0x2A, 	/* 4E6B0 */
+	0x94,  0x3E,  0x94,  0x2A,  0x94,  0x2A,  0xF4,  0x3E,  0x04,  0x08,  0x04,  0x7F,  0x04,  0x08,  0x04,  0x08, 	/* 4E6C0 */
+	0x04,  0x08,  0x0C,  0xBC,  0x08,  0x10,  0x08,  0x50,  0x7F,  0x50,  0x08,  0x7E,  0x3E,  0x50,  0x2A,  0x90, 	/* 4E6D0 */
+	0x2A,  0x10,  0x3E,  0xFF,  0x2A,  0x10,  0x2A,  0x10,  0x3E,  0x18,  0x08,  0x28,  0x7F,  0x24,  0x08,  0x44, 	/* 4E6E0 */
+	0x08,  0x82,  0x09,  0x01,  0xBD,  0x08,  0x00,  0x08,  0xFE,  0x7F,  0x42,  0x08,  0x24,  0x3E,  0x28,  0x2A, 	/* 4E6F0 */
+	0x10,  0x2A,  0x6C,  0x3F,  0x83,  0x2A,  0x10,  0x2A,  0x10,  0x3E,  0xFE,  0x08,  0x10,  0x7F,  0x10,  0x08, 	/* 4E700 */
+	0x10,  0x09,  0xFF,  0x08,  0x00,  0xBE,  0x08,  0x0A,  0x08,  0x09,  0x7F,  0x09,  0x08,  0x08,  0x3E,  0xFF, 	/* 4E710 */
+	0x2A,  0x08,  0x2A,  0x08,  0x3E,  0xF8,  0x2A,  0x48,  0x2A,  0x48,  0x3E,  0x48,  0x08,  0x44,  0x7F,  0x75, 	/* 4E720 */
+	0x09,  0xC5,  0x08,  0x03,  0x08,  0x01,  0x83,  0x08,  0x10,  0x08,  0x10,  0x7F,  0x10,  0x09,  0xFF,  0x3E, 	/* 4E730 */
+	0x44,  0x2A,  0x44,  0x2A,  0x82,  0x3F,  0x45,  0x2A,  0x44,  0x2A,  0x28,  0x3E,  0x28,  0x08,  0x10,  0x7F, 	/* 4E740 */
+	0x28,  0x08,  0x44,  0x08,  0x82,  0x09,  0x01,  0x85,  0x08,  0x20,  0x08,  0x20,  0x7F,  0x3C,  0x08,  0x44, 	/* 4E750 */
+	0x3E,  0xA8,  0x2B,  0x10,  0x2A,  0x30,  0x3E,  0x48,  0x2A,  0x84,  0x2B,  0x02,  0x3E,  0xFD,  0x08,  0x84, 	/* 4E760 */
+	0x7F,  0x84,  0x08,  0x84,  0x08,  0xFC,  0x08,  0x00,  0x89,  0x04,  0x28,  0x04,  0x24,  0x3F,  0xA4,  0x04, 	/* 4E770 */
+	0x20,  0x7F,  0xFF,  0x04,  0x20,  0x7F,  0xE4,  0x04,  0x24,  0x3F,  0xA8,  0x24,  0x98,  0x3F,  0x90,  0x24, 	/* 4E780 */
+	0x98,  0x3F,  0xAA,  0x04,  0x2A,  0x7F,  0xC6,  0x04,  0x82,  0x8A,  0x08,  0x00,  0x08,  0xFF,  0x7F,  0x10, 	/* 4E790 */
+	0x08,  0x10,  0x3E,  0x24,  0x2A,  0x4E,  0x2B,  0xF1,  0x3E,  0x00,  0x2A,  0x10,  0x2A,  0x10,  0x3E,  0xFE, 	/* 4E7A0 */
+	0x08,  0x10,  0x7F,  0x10,  0x08,  0x10,  0x09,  0xFF,  0x08,  0x00,  0x8C,  0x08,  0x00,  0x08,  0xFF,  0x7F, 	/* 4E7B0 */
+	0x10,  0x08,  0x10,  0x3E,  0xFE,  0x2A,  0x92,  0x2A,  0x92,  0x3E,  0xD6,  0x2A,  0xD6,  0x2A,  0xD6,  0x3E, 	/* 4E7C0 */
+	0xD6,  0x08,  0xFE,  0x7F,  0x82,  0x08,  0x82,  0x08,  0x82,  0x08,  0x86,  0x92,  0x08,  0x00,  0x0B,  0xFF, 	/* 4E7D0 */
+	0x7E,  0xA8,  0x08,  0xA8,  0x3E,  0xE8,  0x2A,  0xA8,  0x2A,  0xA8,  0x3E,  0xA8,  0x2A,  0xE8,  0x2A,  0xA8, 	/* 4E7E0 */
+	0x3E,  0xA8,  0x08,  0xA8,  0x7E,  0xE8,  0x09,  0xA9,  0x08,  0x29,  0x08,  0x27,  0x93,  0x08,  0x10,  0x08, 	/* 4E7F0 */
+	0x1C,  0x7F,  0x24,  0x08,  0x48,  0x3E,  0x90,  0x2A,  0xFE,  0x2A,  0x92,  0x3E,  0x92,  0x2A,  0xA2,  0x2A, 	/* 4E800 */
+	0xFE,  0x3E,  0x28,  0x08,  0x28,  0x7F,  0x48,  0x08,  0x49,  0x08,  0x89,  0x0B,  0x07,  0x94,  0x08,  0x14, 	/* 4E810 */
+	0x08,  0x12,  0x7F,  0xFF,  0x08,  0x10,  0x3F,  0x10,  0x29,  0x7E,  0x29,  0x52,  0x3F,  0x52,  0x29,  0x7E, 	/* 4E820 */
+	0x29,  0x52,  0x3F,  0x52,  0x08,  0x7E,  0x7F,  0x52,  0x08,  0x52,  0x08,  0x52,  0x08,  0x56,  0x95,  0x08, 	/* 4E830 */
+	0x00,  0x08,  0xFF,  0x7F,  0x80,  0x08,  0x2A,  0x3E,  0x2A,  0x2A,  0x54,  0x2A,  0xD4,  0x3E,  0x2A,  0x2A, 	/* 4E840 */
+	0x2A,  0x2A,  0x00,  0x3E,  0x7E,  0x08,  0x10,  0x7F,  0x10,  0x08,  0x10,  0x08,  0xFF,  0x08,  0x00,  0x99, 	/* 4E850 */
+	0x08,  0x00,  0x09,  0xFF,  0x7E,  0xA0,  0x08,  0xA0,  0x3E,  0xFE,  0x2A,  0xAA,  0x2A,  0xAA,  0x3E,  0xAA, 	/* 4E860 */
+	0x2A,  0xEA,  0x2A,  0xAC,  0x3E,  0xA4,  0x08,  0xA4,  0x7E,  0xEA,  0x09,  0xB2,  0x08,  0x21,  0x08,  0x20, 	/* 4E870 */
+	0x9B,  0x08,  0x00,  0x09,  0xFF,  0x7E,  0x20,  0x08,  0x20,  0x3F,  0xFE,  0x2B,  0x22,  0x2B,  0x22,  0x3F, 	/* 4E880 */
+	0xFA,  0x2B,  0x6A,  0x2B,  0x6A,  0x3F,  0x6A,  0x09,  0xB6,  0x7F,  0x22,  0x09,  0x22,  0x09,  0x22,  0x09, 	/* 4E890 */
+	0x26,  0x9C,  0x08,  0x92,  0x08,  0x92,  0x7F,  0x24,  0x09,  0x6C,  0x3E,  0x92,  0x2A,  0x92,  0x2A,  0x00, 	/* 4E8A0 */
+	0x3E,  0xFE,  0x2A,  0x92,  0x2A,  0x92,  0x3E,  0xFE,  0x08,  0x92,  0x7F,  0x92,  0x08,  0x92,  0x08,  0xFE, 	/* 4E8B0 */
+	0x08,  0x00,  0x9D,  0x08,  0x00,  0x08,  0xFF,  0x4A,  0x91,  0x2A,  0x91,  0x2A,  0xFE,  0x2C,  0x10,  0x08, 	/* 4E8C0 */
+	0x7E,  0x7F,  0x52,  0x14,  0x7E,  0x14,  0x52,  0x14,  0x52,  0x15,  0x7E,  0x26,  0x10,  0x25,  0xFF,  0x40, 	/* 4E8D0 */
+	0x10,  0x00,  0x10,  0x9F,  0x08,  0x00,  0x09,  0xFE,  0x7E,  0xAA,  0x08,  0xAA,  0x3E,  0x44,  0x2A,  0xAA, 	/* 4E8E0 */
+	0x2B,  0x11,  0x3E,  0x00,  0x2B,  0xFE,  0x2A,  0x22,  0x3E,  0xAA,  0x08,  0xAA,  0x7E,  0x44,  0x08,  0xC4, 	/* 4E8F0 */
+	0x09,  0x2A,  0x0A,  0x11,  0xA6,  0x08,  0x08,  0x3E,  0x3E,  0x08,  0x08,  0x7F,  0x7F,  0x14,  0x14,  0x22, 	/* 4E900 */
+	0xA2,  0x5F,  0xFD,  0x00,  0x80,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x00, 	/* 4E910 */
+	0x80,  0x7F,  0xFF,  0x00,  0x80,  0xA9,  0x02,  0x20,  0x7E,  0x3F,  0x02,  0x20,  0x3E,  0x3E,  0x02,  0x20, 	/* 4E920 */
+	0x7E,  0x3F,  0x04,  0x20,  0x08,  0xA0,  0x7F,  0xFF,  0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8, 	/* 4E930 */
+	0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0xAA,  0x08,  0x10,  0x08,  0x10,  0x7F,  0x28,  0x08,  0x24,  0x3E, 	/* 4E940 */
+	0x42,  0x2A,  0xFD,  0x2B,  0x00,  0x3E,  0xFE,  0x2A,  0xAA,  0x2A,  0xAA,  0x3E,  0xFE,  0x08,  0xAA,  0x7F, 	/* 4E950 */
+	0xAA,  0x08,  0xAA,  0x08,  0xAA,  0x08,  0x86,  0xAF,  0x08,  0x00,  0x08,  0x7C,  0x7F,  0x44,  0x08,  0x7C, 	/* 4E960 */
+	0x3E,  0x00,  0x2B,  0xFF,  0x2A,  0x44,  0x3E,  0x44,  0x2A,  0x7C,  0x2A,  0x44,  0x3E,  0x7C,  0x08,  0x44, 	/* 4E970 */
+	0x7F,  0x47,  0x08,  0x7C,  0x09,  0xC4,  0x08,  0x04,  0xB3,  0x08,  0x20,  0x08,  0x20,  0x7F,  0xFC,  0x08, 	/* 4E980 */
+	0x20,  0x3E,  0xFC,  0x2A,  0x50,  0x2B,  0xFF,  0x3E,  0x88,  0x2B,  0xFC,  0x2A,  0x22,  0x3E,  0x21,  0x09, 	/* 4E990 */
+	0xFE,  0x7F,  0x20,  0x08,  0x50,  0x08,  0x8C,  0x0B,  0x03,  0xB8,  0x08,  0x10,  0x08,  0x10,  0x7F,  0x28, 	/* 4E9A0 */
+	0x08,  0x44,  0x3E,  0xFE,  0x2B,  0x01,  0x2A,  0xEA,  0x3E,  0xAA,  0x2A,  0xAA,  0x2A,  0xEA,  0x3E,  0xAA, 	/* 4E9B0 */
+	0x08,  0xAA,  0x7F,  0xEA,  0x08,  0xAA,  0x08,  0xA2,  0x08,  0xA6,  0xB9,  0x08,  0x20,  0x08,  0x20,  0x7F, 	/* 4E9C0 */
+	0x3F,  0x08,  0x40,  0x3E,  0xFC,  0x2B,  0x44,  0x2A,  0x7C,  0x3E,  0x44,  0x2A,  0x7C,  0x2A,  0x20,  0x3E, 	/* 4E9D0 */
+	0x7C,  0x08,  0xC4,  0x7F,  0x28,  0x08,  0x30,  0x08,  0xCC,  0x0B,  0x03,  0xBB,  0x08,  0x00,  0x08,  0xFF, 	/* 4E9E0 */
+	0x7F,  0x00,  0x08,  0x7C,  0x3E,  0x44,  0x2A,  0x44,  0x2A,  0x7C,  0x3E,  0x00,  0x2A,  0xFE,  0x2A,  0x92, 	/* 4E9F0 */
+	0x3E,  0x92,  0x08,  0xFE,  0x7F,  0x92,  0x08,  0x92,  0x08,  0xFE,  0x08,  0x00,  0xBE,  0x08,  0x00,  0x08, 	/* 4EA00 */
+	0xFE,  0x7F,  0x82,  0x08,  0x82,  0x3E,  0xFE,  0x2A,  0x80,  0x2A,  0xA4,  0x3E,  0xFF,  0x2A,  0xA4,  0x2A, 	/* 4EA10 */
+	0xA4,  0x3E,  0xFF,  0x08,  0xA9,  0x7F,  0x2A,  0x09,  0x24,  0x0A,  0x32,  0x08,  0xC1,  0xBF,  0x04,  0x00, 	/* 4EA20 */
+	0x38,  0x9E,  0x27,  0xF2,  0x20,  0x82,  0x3B,  0xEE,  0x22,  0xA2,  0x23,  0xE2,  0x22,  0xA2,  0x3B,  0xEE, 	/* 4EA30 */
+	0x20,  0x82,  0x27,  0xF2,  0x20,  0x82,  0x7F,  0xFF,  0x04,  0x30,  0x18,  0x0C,  0x60,  0x02,  0x82,  0x08, 	/* 4EA40 */
+	0x00,  0x7F,  0x3C,  0x08,  0x24,  0x3E,  0x24,  0x00,  0x25,  0x7F,  0x25,  0x41,  0x43,  0x3E,  0x80,  0x08, 	/* 4EA50 */
+	0x7C,  0x7F,  0x24,  0x2A,  0x24,  0x3E,  0x18,  0x2A,  0x08,  0x7F,  0x94,  0x08,  0x22,  0x08,  0x41,  0x84, 	/* 4EA60 */
+	0x08,  0x10,  0x08,  0x10,  0x7F,  0xFE,  0x08,  0x82,  0x3E,  0x92,  0x2A,  0xFE,  0x2A,  0x10,  0x3E,  0x7C, 	/* 4EA70 */
+	0x2A,  0x10,  0x2A,  0xFF,  0x3E,  0x00,  0x08,  0x7C,  0x7F,  0x44,  0x08,  0x44,  0x08,  0x7C,  0x08,  0x00, 	/* 4EA80 */
+	0x85,  0x08,  0x10,  0x08,  0x10,  0x7F,  0x7E,  0x08,  0x10,  0x3E,  0xFF,  0x2A,  0x00,  0x2A,  0x7E,  0x3E, 	/* 4EA90 */
+	0x42,  0x2A,  0x42,  0x2A,  0x7E,  0x3E,  0x19,  0x08,  0x2A,  0x7F,  0x64,  0x08,  0xA4,  0x08,  0x32,  0x08, 	/* 4EAA0 */
+	0xC1,  0x86,  0x08,  0x08,  0x08,  0x08,  0x7E,  0xFF,  0x08,  0x94,  0x3E,  0x94,  0x2A,  0xFF,  0x2A,  0x95, 	/* 4EAB0 */
+	0x3E,  0x95,  0x2A,  0xFF,  0x2A,  0xA4,  0x3E,  0xA5,  0x08,  0xBE,  0x7F,  0x24,  0x09,  0x24,  0x0A,  0x3D, 	/* 4EAC0 */
+	0x08,  0xC3,  0x89,  0x08,  0x10,  0x08,  0x10,  0x7F,  0xFF,  0x08,  0x10,  0x3E,  0xFE,  0x2A,  0x92,  0x2A, 	/* 4EAD0 */
+	0xFE,  0x3E,  0x92,  0x2A,  0xFE,  0x2A,  0x12,  0x3E,  0xFD,  0x08,  0x04,  0x7F,  0xFF,  0x08,  0x44,  0x08, 	/* 4EAE0 */
+	0x24,  0x08,  0x0C,  0x8C,  0x08,  0x00,  0x08,  0xFE,  0x7E,  0x10,  0x09,  0xFF,  0x3F,  0x11,  0x2B,  0xDD, 	/* 4EAF0 */
+	0x2B,  0x11,  0x3E,  0xCC,  0x2A,  0x00,  0x2A,  0xFC,  0x3E,  0x04,  0x08,  0x04,  0x7E,  0xFF,  0x08,  0x04, 	/* 4EB00 */
+	0x08,  0xFC,  0x08,  0x00,  0x8D,  0x11,  0x08,  0x11,  0x08,  0x7F,  0xE8,  0x11,  0x8F,  0x7D,  0x54,  0x56, 	/* 4EB10 */
+	0x54,  0x57,  0xA4,  0x7C,  0x14,  0x57,  0xD4,  0x56,  0x54,  0x7F,  0xC8,  0x12,  0x48,  0x13,  0xCC,  0x7E, 	/* 4EB20 */
+	0x54,  0x12,  0x62,  0x12,  0xC1,  0x8E,  0x08,  0x0C,  0x08,  0xF0,  0x7F,  0x10,  0x09,  0xFF,  0x3E,  0x48, 	/* 4EB30 */
+	0x2A,  0xFC,  0x2B,  0x4B,  0x3E,  0x78,  0x2A,  0x00,  0x2A,  0xFE,  0x3E,  0x82,  0x08,  0xBA,  0x7F,  0xAA, 	/* 4EB40 */
+	0x08,  0xBA,  0x08,  0x82,  0x08,  0x86,  0x97,  0x08,  0x0C,  0x08,  0x0A,  0x7E,  0xFF,  0x08,  0x88,  0x3E, 	/* 4EB50 */
+	0xFA,  0x2A,  0x8A,  0x2A,  0xF4,  0x3E,  0xD4,  0x2A,  0xF5,  0x2A,  0x8B,  0x3F,  0x11,  0x08,  0x28,  0x7E, 	/* 4EB60 */
+	0xAA,  0x08,  0xA1,  0x09,  0x25,  0x08,  0x1C,  0x9C,  0x08,  0x00,  0x08,  0xFE,  0x7F,  0x10,  0x08,  0xFF, 	/* 4EB70 */
+	0x3E,  0x91,  0x2A,  0xFD,  0x2A,  0x91,  0x3E,  0x6C,  0x2A,  0x00,  0x2A,  0xFF,  0x3E,  0x10,  0x08,  0xFE, 	/* 4EB80 */
+	0x7F,  0xAA,  0x08,  0xAA,  0x08,  0xAA,  0x08,  0x86,  0x9F,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x07, 	/* 4EB90 */
+	0xF0,  0x04,  0x90,  0x07,  0xF0,  0x04,  0x90,  0x3F,  0xFE,  0x00,  0x80,  0x08,  0x10,  0x7F,  0xFE,  0x2A, 	/* 4EBA0 */
+	0x54,  0x3E,  0x7C,  0x2A,  0x54,  0x7F,  0xFF,  0x08,  0x10,  0xA1,  0x10,  0x84,  0x13,  0xE4,  0x68,  0x9A, 	/* 4EBB0 */
+	0x13,  0xE4,  0x2A,  0xAA,  0x7F,  0xFF,  0x12,  0xA4,  0x3B,  0xEE,  0x34,  0x8D,  0x53,  0xF4,  0x10,  0x84, 	/* 4EBC0 */
+	0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0xA2,  0x08,  0x8A,  0x08,  0x92,  0x7E, 	/* 4EBD0 */
+	0xBA,  0x09,  0x6D,  0x3F,  0x6D,  0x2A,  0xBA,  0x2A,  0xAA,  0x3F,  0x7D,  0x2B,  0xC7,  0x2A,  0x10,  0x3E, 	/* 4EBE0 */
+	0xFF,  0x08,  0x38,  0x7F,  0x54,  0x08,  0x92,  0x09,  0x11,  0x08,  0x10,  0xA3,  0x08,  0x00,  0x08,  0xFF, 	/* 4EBF0 */
+	0x7E,  0x89,  0x08,  0xB6,  0x3E,  0x92,  0x2A,  0xFF,  0x2A,  0x9A,  0x3E,  0xB6,  0x2A,  0xDB,  0x2A,  0x9A, 	/* 4EC00 */
+	0x3E,  0xA8,  0x08,  0xAE,  0x7F,  0x28,  0x09,  0x28,  0x0A,  0xFF,  0x08,  0x00,  0xA4,  0x08,  0x10,  0x08, 	/* 4EC10 */
+	0x1E,  0x7F,  0x10,  0x08,  0xFF,  0x3E,  0x9A,  0x2A,  0xF1,  0x2A,  0xBF,  0x3E,  0xAA,  0x2A,  0xBE,  0x2A, 	/* 4EC20 */
+	0xAA,  0x3F,  0x3E,  0x09,  0x00,  0x7E,  0xFE,  0x08,  0xAA,  0x09,  0xFF,  0x08,  0x00,  0x9B,  0x00,  0x80, 	/* 4EC30 */
+	0x00,  0x80,  0x1F,  0xFC,  0x04,  0x10,  0x02,  0x10,  0x02,  0x20,  0x02,  0x20,  0x7F,  0xFF,  0x00,  0x80, 	/* 4EC40 */
+	0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x9C,  0x00, 	/* 4EC50 */
+	0x80,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x80,  0x1F, 	/* 4EC60 */
+	0xFC,  0x04,  0x10,  0x02,  0x20,  0x7F,  0xFF,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x9E, 	/* 4EC70 */
+	0x02,  0x10,  0x0C,  0x10,  0x79,  0xFE,  0x08,  0x84,  0x08,  0x44,  0x08,  0x44,  0x7F,  0x48,  0x09,  0xFF, 	/* 4EC80 */
+	0x08,  0x10,  0x3E,  0x10,  0x22,  0xFE,  0x22,  0x10,  0x22,  0x10,  0x22,  0x10,  0x3E,  0x10,  0x00,  0x10, 	/* 4EC90 */
+	0x9F,  0x00,  0x10,  0x1F,  0x10,  0x11,  0xFE,  0x11,  0x44,  0x11,  0x24,  0x1F,  0x28,  0x10,  0x28,  0x11, 	/* 4ECA0 */
+	0xFF,  0x10,  0x10,  0x1F,  0x10,  0x29,  0xFE,  0x29,  0x10,  0x49,  0x10,  0x09,  0x10,  0x0F,  0x10,  0x00, 	/* 4ECB0 */
+	0x10,  0xA3,  0x08,  0x10,  0x08,  0x10,  0x7F,  0xFF,  0x22,  0x10,  0x12,  0x10,  0x14,  0xFE,  0x7F,  0x92, 	/* 4ECC0 */
+	0x08,  0x92,  0x08,  0x92,  0x0E,  0xFE,  0x78,  0x38,  0x08,  0x54,  0x10,  0x92,  0x11,  0x11,  0x20,  0x10, 	/* 4ECD0 */
+	0x00,  0x10,  0xA7,  0x10,  0x08,  0x10,  0x08,  0x7F,  0xFE,  0x25,  0x52,  0x25,  0x52,  0x29,  0x54,  0x7D, 	/* 4ECE0 */
+	0x7F,  0x11,  0x48,  0x11,  0x48,  0x7D,  0x7F,  0x11,  0x48,  0x12,  0x48,  0x12,  0x48,  0x24,  0x48,  0x28, 	/* 4ECF0 */
+	0x48,  0x41,  0x88,  0xA8,  0x08,  0x48,  0x09,  0x48,  0x7F,  0x7F,  0x23,  0x62,  0x15,  0x52,  0x15,  0x54, 	/* 4ED00 */
+	0x7F,  0x7F,  0x09,  0x48,  0x09,  0x48,  0x7F,  0x7F,  0x09,  0x48,  0x08,  0x48,  0x10,  0x88,  0x10,  0x88, 	/* 4ED10 */
+	0x21,  0x08,  0x42,  0x08,  0xAD,  0x03,  0x08,  0x7C,  0x08,  0x25,  0x7F,  0x24,  0xA2,  0x40,  0x92,  0x3F, 	/* 4ED20 */
+	0x14,  0x0A,  0x14,  0x7F,  0xFF,  0x52,  0x88,  0x7D,  0x88,  0x40,  0xFF,  0x7E,  0x88,  0x52,  0x88,  0x4C, 	/* 4ED30 */
+	0x88,  0x52,  0x88,  0x61,  0x88,  0xAE,  0x10,  0x84,  0x10,  0x84,  0x7C,  0x9F,  0x2B,  0x4A,  0x29,  0x4A, 	/* 4ED40 */
+	0x28,  0x8A,  0x7C,  0xDF,  0x11,  0x24,  0x13,  0xE4,  0x7C,  0x9F,  0x12,  0x84,  0x12,  0xC4,  0x12,  0xA4, 	/* 4ED50 */
+	0x22,  0xA4,  0x24,  0x84,  0x40,  0x84,  0xAF,  0x08,  0x04,  0x09,  0xE4,  0x7E,  0x1F,  0x15,  0xFA,  0x14, 	/* 4ED60 */
+	0x0A,  0x15,  0xEA,  0x7E,  0x1F,  0x09,  0xE4,  0x08,  0x04,  0x0E,  0x1F,  0x79,  0xE4,  0x09,  0x24,  0x11, 	/* 4ED70 */
+	0x24,  0x11,  0x24,  0x21,  0xE4,  0x40,  0x04,  0xB0,  0x00,  0x00,  0x1F,  0xFE,  0x10,  0x00,  0x10,  0x00, 	/* 4ED80 */
+	0x17,  0xFC,  0x10,  0x00,  0x10,  0x00,  0x1F,  0xFF,  0x12,  0x84,  0x12,  0x84,  0x12,  0x48,  0x12,  0x50, 	/* 4ED90 */
+	0x22,  0x20,  0x22,  0x90,  0x43,  0x0C,  0x1C,  0x03,  0xB1,  0x00,  0x00,  0x1F,  0xFE,  0x10,  0x00,  0x1F, 	/* 4EDA0 */
+	0xFC,  0x10,  0x00,  0x1F,  0xFF,  0x14,  0x88,  0x24,  0x50,  0x27,  0xB0,  0x5C,  0x0E,  0x00,  0x10,  0x7F, 	/* 4EDB0 */
+	0xFF,  0x04,  0x10,  0x02,  0x10,  0x02,  0x10,  0x00,  0x30,  0xB2,  0x02,  0x20,  0x1F,  0xFC,  0x12,  0x24, 	/* 4EDC0 */
+	0x1F,  0xFC,  0x12,  0x24,  0x1F,  0xFC,  0x00,  0x00,  0x1F,  0xFE,  0x10,  0x00,  0x17,  0xFC,  0x10,  0x00, 	/* 4EDD0 */
+	0x1F,  0xFF,  0x24,  0x88,  0x24,  0x50,  0x47,  0x30,  0x1C,  0x0F,  0xB7,  0x10,  0x00,  0x08,  0x00,  0x08, 	/* 4EDE0 */
+	0x00,  0x00,  0x00,  0x20,  0x00,  0x10,  0x00,  0x13,  0xFF,  0x00,  0x00,  0x78,  0x00,  0x08,  0x00,  0x08, 	/* 4EDF0 */
+	0x00,  0x08,  0x00,  0x08,  0x00,  0x14,  0x00,  0x23,  0x00,  0x40,  0xFF,  0xBA,  0x00,  0x00,  0x20,  0x00, 	/* 4EE00 */
+	0x13,  0xFE,  0x10,  0x42,  0x00,  0x42,  0x00,  0x42,  0x00,  0x42,  0x78,  0x42,  0x08,  0x82,  0x08,  0x82, 	/* 4EE10 */
+	0x09,  0x02,  0x0A,  0x02,  0x0C,  0x04,  0x14,  0x18,  0x23,  0x00,  0x40,  0xFF,  0xBB,  0x00,  0x20,  0x20, 	/* 4EE20 */
+	0x20,  0x10,  0x20,  0x10,  0x20,  0x00,  0x20,  0x03,  0xFE,  0x00,  0x20,  0x78,  0x20,  0x08,  0x20,  0x08, 	/* 4EE30 */
+	0x20,  0x08,  0x20,  0x08,  0x20,  0x0C,  0x20,  0x14,  0x20,  0x23,  0x00,  0x40,  0xFF,  0xBC,  0x00,  0x00, 	/* 4EE40 */
+	0x20,  0xE0,  0x10,  0x20,  0x10,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x78,  0x50,  0x08,  0x50, 	/* 4EE50 */
+	0x08,  0x88,  0x09,  0x04,  0x0A,  0x02,  0x0C,  0x01,  0x14,  0x00,  0x23,  0x00,  0x40,  0xFF,  0xBF,  0x00, 	/* 4EE60 */
+	0x20,  0x20,  0x20,  0x10,  0x20,  0x11,  0x24,  0x01,  0x24,  0x01,  0x24,  0x01,  0x24,  0x79,  0x24,  0x09, 	/* 4EE70 */
+	0x24,  0x09,  0x24,  0x09,  0x24,  0x09,  0x24,  0x0D,  0xFC,  0x14,  0x00,  0x23,  0x00,  0x40,  0xFF,  0x82, 	/* 4EE80 */
+	0x00,  0x00,  0x23,  0xFC,  0x10,  0x20,  0x10,  0x20,  0x00,  0x20,  0x00,  0x20,  0x07,  0xFE,  0x78,  0x20, 	/* 4EE90 */
+	0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x0C,  0x20,  0x14,  0x60,  0x23,  0x00,  0x40,  0xFF, 	/* 4EEA0 */
+	0x84,  0x01,  0x00,  0x21,  0x00,  0x11,  0xFF,  0x11,  0x00,  0x02,  0x00,  0x03,  0xFC,  0x04,  0x10,  0x78, 	/* 4EEB0 */
+	0x20,  0x08,  0x40,  0x08,  0x80,  0x08,  0x80,  0x09,  0x02,  0x0D,  0x02,  0x14,  0xFE,  0x23,  0x00,  0x40, 	/* 4EEC0 */
+	0xFF,  0x85,  0x00,  0x00,  0x27,  0xF8,  0x10,  0x08,  0x10,  0x88,  0x00,  0x88,  0x00,  0x88,  0x00,  0x88, 	/* 4EED0 */
+	0x7B,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x08,  0x85,  0x08,  0x85,  0x0C,  0x83,  0x14,  0x01,  0x23,  0x00, 	/* 4EEE0 */
+	0x40,  0xFF,  0x8E,  0x00,  0x20,  0x20,  0x40,  0x11,  0x9E,  0x11,  0x12,  0x01,  0x12,  0x01,  0x12,  0x01, 	/* 4EEF0 */
+	0x12,  0x79,  0x12,  0x09,  0x12,  0x09,  0x52,  0x09,  0x92,  0x0B,  0x1C,  0x0C,  0x10,  0x16,  0x10,  0x21, 	/* 4EF00 */
+	0x00,  0x40,  0xFF,  0x91,  0x00,  0x04,  0x20,  0x18,  0x11,  0xE0,  0x11,  0x00,  0x01,  0x00,  0x01,  0xFE, 	/* 4EF10 */
+	0x01,  0x10,  0x79,  0x10,  0x09,  0x10,  0x09,  0x10,  0x0A,  0x10,  0x0A,  0x10,  0x0C,  0x10,  0x14,  0x10, 	/* 4EF20 */
+	0x23,  0x00,  0x40,  0xFF,  0x94,  0x00,  0x00,  0x21,  0xFF,  0x11,  0x00,  0x11,  0x00,  0x01,  0x00,  0x01, 	/* 4EF30 */
+	0xFC,  0x01,  0x44,  0x79,  0x44,  0x09,  0x28,  0x09,  0x18,  0x0A,  0x10,  0x0A,  0x68,  0x0D,  0x84,  0x14, 	/* 4EF40 */
+	0x02,  0x23,  0x00,  0x40,  0xFF,  0x9A,  0x10,  0x20,  0x08,  0x20,  0x08,  0x20,  0x03,  0xFE,  0x22,  0x22, 	/* 4EF50 */
+	0x12,  0x22,  0x12,  0x22,  0x02,  0x22,  0x7B,  0xFE,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20, 	/* 4EF60 */
+	0x14,  0x20,  0x23,  0x00,  0x40,  0xFF,  0xA2,  0x10,  0x00,  0x0B,  0xFE,  0x08,  0x42,  0x00,  0x42,  0x20, 	/* 4EF70 */
+	0x42,  0x10,  0x82,  0x11,  0x1C,  0x02,  0x00,  0x79,  0xFC,  0x09,  0x04,  0x09,  0x04,  0x09,  0x04,  0x0D, 	/* 4EF80 */
+	0xFC,  0x14,  0x00,  0x23,  0x00,  0x40,  0xFF,  0xA5,  0x10,  0x00,  0x0B,  0xFE,  0x0A,  0x02,  0x02,  0x02, 	/* 4EF90 */
+	0x22,  0xFA,  0x12,  0x8A,  0x12,  0x8A,  0x02,  0x8A,  0x7A,  0x8A,  0x0A,  0xFA,  0x0A,  0x02,  0x0A,  0x02, 	/* 4EFA0 */
+	0x0A,  0x02,  0x16,  0x06,  0x23,  0x00,  0x40,  0xFF,  0xA6,  0x01,  0x00,  0x21,  0x00,  0x11,  0x1E,  0x17, 	/* 4EFB0 */
+	0xD2,  0x01,  0x52,  0x01,  0x52,  0x01,  0x52,  0x79,  0x52,  0x09,  0x52,  0x0A,  0x52,  0x0A,  0x52,  0x0C, 	/* 4EFC0 */
+	0x5E,  0x09,  0x80,  0x14,  0x00,  0x23,  0x00,  0x40,  0xFF,  0xA9,  0x01,  0x00,  0x21,  0x00,  0x11,  0xFE, 	/* 4EFD0 */
+	0x11,  0x20,  0x02,  0x20,  0x02,  0x20,  0x04,  0xA8,  0x78,  0xA4,  0x09,  0x24,  0x09,  0x22,  0x0A,  0x22, 	/* 4EFE0 */
+	0x08,  0x22,  0x0C,  0x20,  0x14,  0x60,  0x23,  0x00,  0x40,  0xFF,  0xAA,  0x10,  0x20,  0x08,  0x20,  0x08, 	/* 4EFF0 */
+	0x20,  0x00,  0x20,  0x21,  0xFE,  0x11,  0x22,  0x11,  0x22,  0x01,  0x22,  0x79,  0xFE,  0x09,  0x22,  0x09, 	/* 4F000 */
+	0x22,  0x09,  0x22,  0x0D,  0xFE,  0x14,  0x00,  0x23,  0x00,  0x40,  0xFF,  0xAB,  0x00,  0x20,  0x20,  0x20, 	/* 4F010 */
+	0x10,  0x40,  0x11,  0xFC,  0x01,  0x04,  0x01,  0x04,  0x01,  0x04,  0x79,  0xFC,  0x09,  0x04,  0x09,  0x04, 	/* 4F020 */
+	0x09,  0x04,  0x09,  0x04,  0x0D,  0xFC,  0x14,  0x00,  0x23,  0x00,  0x40,  0xFF,  0xAD,  0x00,  0x20,  0x20, 	/* 4F030 */
+	0xA0,  0x10,  0xA0,  0x11,  0xFE,  0x01,  0x20,  0x02,  0x20,  0x00,  0x20,  0x7F,  0xFF,  0x08,  0x20,  0x08, 	/* 4F040 */
+	0x50,  0x08,  0x90,  0x08,  0x88,  0x15,  0x04,  0x12,  0x02,  0x21,  0x80,  0x40,  0x7F,  0xAF,  0x10,  0x88, 	/* 4F050 */
+	0x08,  0x88,  0x08,  0xE8,  0x01,  0x28,  0x21,  0x28,  0x11,  0xA8,  0x12,  0xAC,  0x04,  0x4A,  0x78,  0x49, 	/* 4F060 */
+	0x08,  0x88,  0x08,  0x88,  0x09,  0x08,  0x0E,  0x08,  0x14,  0x08,  0x23,  0x00,  0x40,  0xFF,  0xB0,  0x00, 	/* 4F070 */
+	0x28,  0x20,  0x24,  0x10,  0x24,  0x10,  0x20,  0x07,  0xFF,  0x00,  0x20,  0x00,  0x20,  0x79,  0x28,  0x09, 	/* 4F080 */
+	0x24,  0x09,  0x24,  0x09,  0x22,  0x0A,  0x22,  0x0C,  0x20,  0x14,  0x20,  0x23,  0x00,  0x40,  0xFF,  0xB4, 	/* 4F090 */
+	0x10,  0x00,  0x09,  0xFE,  0x09,  0x02,  0x01,  0x02,  0x21,  0x7A,  0x11,  0x4A,  0x11,  0x4A,  0x01,  0x4A, 	/* 4F0A0 */
+	0x79,  0x4A,  0x09,  0x7A,  0x09,  0x02,  0x09,  0x02,  0x0D,  0xFE,  0x14,  0x00,  0x23,  0x00,  0x40,  0xFF, 	/* 4F0B0 */
+	0xB7,  0x00,  0x20,  0x21,  0x24,  0x10,  0xA4,  0x10,  0xA8,  0x00,  0x20,  0x07,  0xFF,  0x00,  0x70,  0x78, 	/* 4F0C0 */
+	0x70,  0x08,  0xA8,  0x08,  0xA8,  0x09,  0x24,  0x0A,  0x22,  0x08,  0x20,  0x14,  0x20,  0x23,  0x00,  0x40, 	/* 4F0D0 */
+	0xFF,  0xB8,  0x10,  0x84,  0x08,  0x44,  0x08,  0x48,  0x03,  0xFE,  0x20,  0x48,  0x10,  0x48,  0x10,  0x48, 	/* 4F0E0 */
+	0x03,  0xFF,  0x78,  0x48,  0x08,  0x48,  0x08,  0x48,  0x08,  0x48,  0x0C,  0x88,  0x15,  0x08,  0x23,  0x00, 	/* 4F0F0 */
+	0x40,  0xFF,  0xB9,  0x10,  0x20,  0x08,  0x20,  0x08,  0x20,  0x07,  0xFE,  0x20,  0x50,  0x10,  0x50,  0x11, 	/* 4F100 */
+	0x54,  0x01,  0x54,  0x79,  0x52,  0x09,  0x52,  0x0A,  0x52,  0x08,  0x92,  0x0C,  0x90,  0x15,  0x30,  0x23, 	/* 4F110 */
+	0x00,  0x40,  0xFF,  0xBA,  0x10,  0x00,  0x0B,  0xFF,  0x08,  0x50,  0x00,  0x50,  0x20,  0x50,  0x11,  0xFE, 	/* 4F120 */
+	0x11,  0x52,  0x01,  0x52,  0x79,  0x56,  0x09,  0x8E,  0x09,  0x02,  0x09,  0x02,  0x0D,  0xFE,  0x14,  0x00, 	/* 4F130 */
+	0x23,  0x00,  0x40,  0xFF,  0xBD,  0x00,  0x20,  0x20,  0x40,  0x11,  0xF8,  0x11,  0x08,  0x01,  0x08,  0x01, 	/* 4F140 */
+	0x08,  0x01,  0xF8,  0x79,  0x00,  0x09,  0xFC,  0x09,  0x04,  0x09,  0x04,  0x09,  0x04,  0x0D,  0xFC,  0x14, 	/* 4F150 */
+	0x00,  0x23,  0x00,  0x40,  0xFF,  0x80,  0x00,  0x00,  0x21,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x01,  0xF8, 	/* 4F160 */
+	0x01,  0x08,  0x01,  0x08,  0x79,  0xFA,  0x09,  0x24,  0x09,  0x28,  0x09,  0x10,  0x09,  0xC8,  0x0F,  0x04, 	/* 4F170 */
+	0x14,  0x02,  0x23,  0x00,  0x40,  0xFF,  0x81,  0x01,  0x08,  0x20,  0x88,  0x10,  0x90,  0x10,  0x20,  0x03, 	/* 4F180 */
+	0xFE,  0x00,  0x20,  0x00,  0x20,  0x78,  0x20,  0x0F,  0xFF,  0x08,  0x30,  0x08,  0x48,  0x08,  0x84,  0x0D, 	/* 4F190 */
+	0x02,  0x14,  0x02,  0x23,  0x00,  0x40,  0xFF,  0x83,  0x00,  0xA0,  0x20,  0xA0,  0x14,  0xA4,  0x12,  0xA4, 	/* 4F1A0 */
+	0x02,  0xA8,  0x00,  0xB0,  0x01,  0xA0,  0x7A,  0xA8,  0x0C,  0xA4,  0x08,  0xA4,  0x09,  0x20,  0x09,  0x22, 	/* 4F1B0 */
+	0x0E,  0x22,  0x14,  0x1E,  0x23,  0x00,  0x40,  0xFF,  0x85,  0x10,  0x04,  0x08,  0x18,  0x09,  0xE0,  0x01, 	/* 4F1C0 */
+	0x00,  0x21,  0x00,  0x11,  0xFF,  0x11,  0x00,  0x01,  0x00,  0x79,  0xFC,  0x09,  0x84,  0x0A,  0x84,  0x0A, 	/* 4F1D0 */
+	0x84,  0x0C,  0xFC,  0x14,  0x00,  0x23,  0x00,  0x40,  0xFF,  0x86,  0x01,  0x08,  0x20,  0x88,  0x10,  0x90, 	/* 4F1E0 */
+	0x17,  0xFF,  0x00,  0x20,  0x01,  0x24,  0x01,  0x24,  0x79,  0x24,  0x09,  0x24,  0x09,  0xFC,  0x09,  0x24, 	/* 4F1F0 */
+	0x08,  0x20,  0x0C,  0x40,  0x14,  0x80,  0x23,  0x00,  0x40,  0xFF,  0x8B,  0x10,  0x24,  0x08,  0x22,  0x0B, 	/* 4F200 */
+	0xFF,  0x00,  0x20,  0x21,  0xFE,  0x11,  0x22,  0x11,  0x22,  0x01,  0xFE,  0x79,  0x22,  0x09,  0x22,  0x09, 	/* 4F210 */
+	0xFE,  0x09,  0x22,  0x0D,  0x22,  0x15,  0x06,  0x23,  0x00,  0x40,  0xFF,  0x8D,  0x10,  0x20,  0x08,  0xA8, 	/* 4F220 */
+	0x08,  0xA4,  0x01,  0x22,  0x23,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x01,  0xFC,  0x79,  0x04,  0x09,  0x04, 	/* 4F230 */
+	0x09,  0xFC,  0x09,  0x04,  0x0D,  0x04,  0x15,  0x0C,  0x23,  0x00,  0x40,  0xFF,  0x8E,  0x10,  0x00,  0x0B, 	/* 4F240 */
+	0xFF,  0x08,  0x50,  0x00,  0x50,  0x21,  0xFE,  0x11,  0x52,  0x11,  0x56,  0x01,  0x5E,  0x79,  0x82,  0x09, 	/* 4F250 */
+	0x02,  0x09,  0xFE,  0x09,  0x02,  0x0D,  0xFE,  0x14,  0x00,  0x23,  0x00,  0x40,  0xFF,  0x8F,  0x00,  0x04, 	/* 4F260 */
+	0x20,  0x18,  0x11,  0xE0,  0x10,  0x20,  0x07,  0xFF,  0x00,  0x70,  0x00,  0xA8,  0x79,  0x24,  0x0B,  0xFB, 	/* 4F270 */
+	0x08,  0x48,  0x08,  0x4C,  0x08,  0x44,  0x0C,  0x84,  0x15,  0x18,  0x23,  0x00,  0x40,  0xFF,  0x90,  0x00, 	/* 4F280 */
+	0x00,  0x27,  0xFF,  0x10,  0x40,  0x10,  0x62,  0x01,  0xA2,  0x06,  0x34,  0x00,  0x54,  0x78,  0x98,  0x0B, 	/* 4F290 */
+	0x38,  0x08,  0x54,  0x08,  0x92,  0x0B,  0x11,  0x0C,  0x10,  0x14,  0x60,  0x23,  0x00,  0x40,  0xFF,  0x91, 	/* 4F2A0 */
+	0x10,  0x20,  0x08,  0x24,  0x08,  0x22,  0x03,  0xFF,  0x20,  0x20,  0x12,  0x22,  0x11,  0x32,  0x01,  0x34, 	/* 4F2B0 */
+	0x78,  0x68,  0x08,  0xA8,  0x09,  0x24,  0x0E,  0x22,  0x08,  0x21,  0x14,  0x60,  0x23,  0x00,  0x40,  0xFF, 	/* 4F2C0 */
+	0x93,  0x00,  0x04,  0x10,  0x38,  0x09,  0xD0,  0x09,  0x10,  0x01,  0xFF,  0x01,  0x10,  0x01,  0xFF,  0x79, 	/* 4F2D0 */
+	0x10,  0x09,  0x7E,  0x09,  0x52,  0x09,  0x52,  0x0A,  0x52,  0x0C,  0x5C,  0x14,  0x10,  0x23,  0x10,  0x40, 	/* 4F2E0 */
+	0xFF,  0x94,  0x00,  0x20,  0x20,  0x20,  0x10,  0x50,  0x10,  0x50,  0x00,  0x88,  0x01,  0xFC,  0x02,  0x22, 	/* 4F2F0 */
+	0x78,  0x21,  0x0B,  0xFE,  0x08,  0xA8,  0x08,  0xA4,  0x09,  0x22,  0x0E,  0x22,  0x14,  0x60,  0x23,  0x00, 	/* 4F300 */
+	0x40,  0xFF,  0x95,  0x10,  0x00,  0x0B,  0xFE,  0x09,  0x24,  0x02,  0x48,  0x26,  0xD8,  0x11,  0x24,  0x11, 	/* 4F310 */
+	0x24,  0x00,  0x00,  0x7B,  0xFE,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x0F,  0xFF,  0x14,  0x00,  0x23, 	/* 4F320 */
+	0x00,  0x40,  0xFF,  0x96,  0x10,  0x48,  0x0A,  0x48,  0x09,  0x8A,  0x01,  0x8A,  0x21,  0x2C,  0x12,  0xAC, 	/* 4F330 */
+	0x14,  0xA8,  0x00,  0xC8,  0x79,  0x8C,  0x0A,  0x94,  0x0C,  0x94,  0x08,  0x92,  0x0B,  0x22,  0x14,  0x41, 	/* 4F340 */
+	0x23,  0x00,  0x40,  0xFF,  0x97,  0x00,  0x00,  0x27,  0xFE,  0x10,  0x00,  0x11,  0xF8,  0x01,  0x08,  0x01, 	/* 4F350 */
+	0x08,  0x01,  0x08,  0x79,  0xF8,  0x08,  0x00,  0x09,  0x08,  0x08,  0x88,  0x08,  0x90,  0x0F,  0xFE,  0x14, 	/* 4F360 */
+	0x00,  0x23,  0x00,  0x40,  0xFF,  0x99,  0x00,  0x00,  0x21,  0xFC,  0x10,  0x00,  0x17,  0xFF,  0x00,  0x00, 	/* 4F370 */
+	0x01,  0xFC,  0x00,  0x00,  0x79,  0xFC,  0x08,  0x00,  0x09,  0xFC,  0x09,  0x04,  0x09,  0x04,  0x15,  0xFC, 	/* 4F380 */
+	0x13,  0x04,  0x21,  0x80,  0x40,  0x7F,  0x9A,  0x00,  0x00,  0x23,  0xFC,  0x10,  0x88,  0x10,  0x50,  0x01, 	/* 4F390 */
+	0xFE,  0x01,  0x22,  0x01,  0x22,  0x79,  0xFE,  0x09,  0x22,  0x09,  0x22,  0x09,  0xFE,  0x09,  0x22,  0x0D, 	/* 4F3A0 */
+	0x22,  0x15,  0x26,  0x23,  0x00,  0x40,  0xFF,  0x9D,  0x01,  0x04,  0x21,  0x38,  0x11,  0x20,  0x11,  0x20, 	/* 4F3B0 */
+	0x07,  0xFF,  0x01,  0x24,  0x01,  0x24,  0x79,  0xE4,  0x0F,  0x24,  0x09,  0x24,  0x09,  0x44,  0x09,  0x84, 	/* 4F3C0 */
+	0x17,  0x04,  0x12,  0x04,  0x21,  0x80,  0x40,  0x7F,  0x9E,  0x10,  0x00,  0x09,  0xFC,  0x09,  0x04,  0x01, 	/* 4F3D0 */
+	0x04,  0x21,  0xFC,  0x10,  0x00,  0x13,  0xFE,  0x00,  0x20,  0x78,  0x20,  0x09,  0xFC,  0x08,  0x20,  0x08, 	/* 4F3E0 */
+	0x20,  0x0B,  0xFE,  0x14,  0x00,  0x23,  0x00,  0x40,  0xFF,  0x9F,  0x00,  0x20,  0x20,  0x20,  0x17,  0xFF, 	/* 4F3F0 */
+	0x10,  0x20,  0x00,  0x20,  0x03,  0xFE,  0x02,  0x22,  0x7A,  0x22,  0x0B,  0xFE,  0x08,  0x70,  0x08,  0xA8, 	/* 4F400 */
+	0x09,  0x24,  0x0E,  0x23,  0x14,  0x20,  0x23,  0x00,  0x40,  0xFF,  0xA0,  0x00,  0x20,  0x21,  0x20,  0x11, 	/* 4F410 */
+	0x20,  0x11,  0xFE,  0x02,  0x20,  0x02,  0x20,  0x07,  0xFF,  0x78,  0x00,  0x09,  0xFC,  0x09,  0x04,  0x09, 	/* 4F420 */
+	0x04,  0x09,  0x04,  0x0D,  0xFC,  0x14,  0x00,  0x23,  0x00,  0x40,  0xFF,  0xA1,  0x10,  0x20,  0x08,  0x28, 	/* 4F430 */
+	0x08,  0x46,  0x03,  0xF9,  0x20,  0x28,  0x10,  0x49,  0x10,  0x87,  0x03,  0x20,  0x78,  0x7C,  0x08,  0xC4, 	/* 4F440 */
+	0x0B,  0x28,  0x08,  0x30,  0x0C,  0x4C,  0x15,  0x83,  0x23,  0x00,  0x40,  0xFF,  0xA2,  0x00,  0x80,  0x20, 	/* 4F450 */
+	0xFC,  0x11,  0x08,  0x16,  0x90,  0x00,  0x60,  0x00,  0xD8,  0x07,  0x07,  0x78,  0x20,  0x0B,  0xFC,  0x08, 	/* 4F460 */
+	0x20,  0x09,  0xFC,  0x08,  0x20,  0x0F,  0xFE,  0x14,  0x20,  0x23,  0x20,  0x40,  0xFF,  0xA3,  0x00,  0x20, 	/* 4F470 */
+	0x20,  0x20,  0x17,  0xFF,  0x10,  0x20,  0x01,  0xFC,  0x01,  0x24,  0x01,  0x24,  0x79,  0xFC,  0x09,  0x24, 	/* 4F480 */
+	0x09,  0x24,  0x09,  0xFC,  0x08,  0x20,  0x0F,  0xFF,  0x14,  0x20,  0x23,  0x20,  0x40,  0xFF,  0xA7,  0x10, 	/* 4F490 */
+	0x48,  0x08,  0x44,  0x08,  0x84,  0x01,  0x22,  0x22,  0x22,  0x10,  0x50,  0x10,  0x88,  0x01,  0x04,  0x7A, 	/* 4F4A0 */
+	0xFE,  0x0C,  0x85,  0x08,  0x84,  0x08,  0x84,  0x0C,  0xFC,  0x14,  0x00,  0x23,  0x00,  0x40,  0xFF,  0xAE, 	/* 4F4B0 */
+	0x00,  0x20,  0x20,  0x20,  0x13,  0xFC,  0x10,  0x24,  0x07,  0xFF,  0x00,  0x24,  0x03,  0xFC,  0x7A,  0x24, 	/* 4F4C0 */
+	0x09,  0x24,  0x09,  0x28,  0x08,  0x70,  0x09,  0xAC,  0x0E,  0x23,  0x14,  0x60,  0x23,  0x00,  0x40,  0xFF, 	/* 4F4D0 */
+	0xB1,  0x00,  0x00,  0x21,  0xFE,  0x11,  0x22,  0x11,  0x22,  0x01,  0xFA,  0x01,  0x22,  0x01,  0xFE,  0x79, 	/* 4F4E0 */
+	0x02,  0x09,  0x7A,  0x09,  0x4A,  0x09,  0x4A,  0x0A,  0x7A,  0x0C,  0x02,  0x14,  0x06,  0x23,  0x00,  0x40, 	/* 4F4F0 */
+	0xFF,  0xB2,  0x00,  0x88,  0x20,  0x88,  0x11,  0x10,  0x11,  0xFE,  0x03,  0x10,  0x05,  0x10,  0x01,  0xFC, 	/* 4F500 */
+	0x39,  0x10,  0x09,  0x10,  0x09,  0xFC,  0x09,  0x10,  0x09,  0x10,  0x15,  0xFE,  0x13,  0x00,  0x21,  0x80, 	/* 4F510 */
+	0x40,  0x7F,  0xB5,  0x10,  0x20,  0x08,  0x20,  0x09,  0xFE,  0x00,  0x20,  0x20,  0x20,  0x13,  0xFF,  0x10, 	/* 4F520 */
+	0x48,  0x00,  0x49,  0x78,  0xA7,  0x0B,  0x20,  0x09,  0xFC,  0x08,  0x20,  0x0C,  0x20,  0x15,  0xFE,  0x23, 	/* 4F530 */
+	0x00,  0x40,  0xFF,  0xB6,  0x10,  0x04,  0x08,  0x18,  0x09,  0xE0,  0x00,  0x20,  0x23,  0xFF,  0x10,  0x70, 	/* 4F540 */
+	0x10,  0xAC,  0x03,  0x23,  0x78,  0x20,  0x0B,  0xFF,  0x08,  0x48,  0x08,  0xC8,  0x0C,  0x38,  0x14,  0xC4, 	/* 4F550 */
+	0x23,  0x00,  0x40,  0xFF,  0xB8,  0x00,  0x40,  0x20,  0x78,  0x10,  0x88,  0x11,  0x10,  0x07,  0xFC,  0x01, 	/* 4F560 */
+	0x24,  0x01,  0x24,  0x79,  0x24,  0x09,  0xFC,  0x08,  0x50,  0x08,  0x50,  0x08,  0x91,  0x15,  0x11,  0x12, 	/* 4F570 */
+	0x0F,  0x21,  0x80,  0x40,  0x7F,  0xB9,  0x10,  0x20,  0x08,  0x20,  0x09,  0xFE,  0x00,  0x20,  0x20,  0x20, 	/* 4F580 */
+	0x17,  0xFF,  0x10,  0x88,  0x00,  0x50,  0x7B,  0xFE,  0x08,  0x20,  0x08,  0x20,  0x0B,  0xFE,  0x0C,  0x20, 	/* 4F590 */
+	0x14,  0x20,  0x23,  0x00,  0x40,  0xFF,  0xBC,  0x00,  0x00,  0x27,  0xFF,  0x10,  0x00,  0x10,  0xFC,  0x00, 	/* 4F5A0 */
+	0x84,  0x00,  0xFC,  0x00,  0x00,  0x79,  0xFE,  0x09,  0x22,  0x09,  0x22,  0x09,  0xFE,  0x09,  0x22,  0x17, 	/* 4F5B0 */
+	0x22,  0x13,  0xFE,  0x21,  0x80,  0x40,  0x7F,  0xBE,  0x10,  0xE0,  0x08,  0x20,  0x08,  0x50,  0x01,  0x8C, 	/* 4F5C0 */
+	0x26,  0xFB,  0x10,  0x00,  0x13,  0xCA,  0x02,  0x4A,  0x7B,  0x4A,  0x0A,  0xD4,  0x0B,  0x54,  0x0A,  0xCA, 	/* 4F5D0 */
+	0x0E,  0x4A,  0x14,  0xCA,  0x23,  0x00,  0x40,  0xFF,  0x81,  0x00,  0x04,  0x20,  0x18,  0x13,  0xF0,  0x12, 	/* 4F5E0 */
+	0x10,  0x03,  0xFF,  0x02,  0x10,  0x02,  0xFC,  0x7A,  0x84,  0x0A,  0xFC,  0x0A,  0x84,  0x0A,  0xFC,  0x0A, 	/* 4F5F0 */
+	0x84,  0x0C,  0x84,  0x14,  0xFC,  0x23,  0x00,  0x40,  0xFF,  0x82,  0x01,  0x08,  0x20,  0x88,  0x10,  0x90, 	/* 4F600 */
+	0x17,  0xFE,  0x00,  0x44,  0x00,  0xA4,  0x03,  0x28,  0x78,  0x58,  0x08,  0x94,  0x0B,  0x34,  0x08,  0x52, 	/* 4F610 */
+	0x09,  0x91,  0x0C,  0x10,  0x14,  0x60,  0x23,  0x00,  0x40,  0xFF,  0x85,  0x00,  0x00,  0x21,  0xFE,  0x11, 	/* 4F620 */
+	0x02,  0x11,  0x02,  0x01,  0xFE,  0x01,  0x44,  0x01,  0x28,  0x79,  0xFE,  0x09,  0x10,  0x09,  0xFE,  0x0A, 	/* 4F630 */
+	0x10,  0x0A,  0xFF,  0x14,  0x10,  0x12,  0x10,  0x21,  0x90,  0x40,  0x7F,  0x87,  0x00,  0x00,  0x21,  0xFC, 	/* 4F640 */
+	0x11,  0x24,  0x11,  0xFC,  0x01,  0x24,  0x01,  0x24,  0x01,  0xFC,  0x78,  0x20,  0x0B,  0xFE,  0x0A,  0x22, 	/* 4F650 */
+	0x0A,  0x2A,  0x0A,  0x3A,  0x16,  0xCA,  0x12,  0x06,  0x21,  0x80,  0x40,  0x7F,  0x89,  0x10,  0x20,  0x08, 	/* 4F660 */
+	0x20,  0x08,  0x3E,  0x00,  0x20,  0x21,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x01,  0x04,  0x79,  0xFC,  0x09, 	/* 4F670 */
+	0x04,  0x09,  0x04,  0x09,  0xFC,  0x0C,  0x84,  0x15,  0x02,  0x23,  0x00,  0x40,  0xFF,  0x8A,  0x01,  0x08, 	/* 4F680 */
+	0x01,  0x08,  0x21,  0x08,  0x17,  0xFF,  0x11,  0x10,  0x01,  0x3E,  0x01,  0xC2,  0x79,  0x44,  0x09,  0x48, 	/* 4F690 */
+	0x0A,  0x7F,  0x0A,  0x48,  0x0C,  0x48,  0x08,  0x48,  0x15,  0x98,  0x23,  0x00,  0x40,  0xFF,  0x8B,  0x00, 	/* 4F6A0 */
+	0x00,  0x27,  0xFE,  0x14,  0x22,  0x14,  0x22,  0x03,  0xFC,  0x00,  0x20,  0x03,  0xFC,  0x7A,  0x24,  0x0B, 	/* 4F6B0 */
+	0xFC,  0x0A,  0x24,  0x0B,  0xFC,  0x08,  0x20,  0x17,  0xFE,  0x12,  0x20,  0x21,  0x80,  0x40,  0x7F,  0x8D, 	/* 4F6C0 */
+	0x00,  0x00,  0x23,  0xFF,  0x10,  0x00,  0x11,  0xFE,  0x01,  0x02,  0x01,  0xFE,  0x01,  0x00,  0x79,  0xFE, 	/* 4F6D0 */
+	0x09,  0xAA,  0x09,  0xAA,  0x0A,  0xFE,  0x0A,  0xAA,  0x0C,  0xAA,  0x14,  0xAA,  0x23,  0x86,  0x40,  0xFF, 	/* 4F6E0 */
+	0x8E,  0x00,  0x00,  0x21,  0xFC,  0x11,  0x04,  0x11,  0x3C,  0x01,  0x24,  0x01,  0x24,  0x03,  0xFE,  0x7A, 	/* 4F6F0 */
+	0x02,  0x0A,  0xFA,  0x0A,  0x8A,  0x0A,  0x8A,  0x0A,  0xFA,  0x0A,  0x02,  0x14,  0x06,  0x23,  0x00,  0x40, 	/* 4F700 */
+	0xFF,  0x8F,  0x10,  0x00,  0x09,  0xFC,  0x09,  0x04,  0x01,  0xFC,  0x21,  0x04,  0x11,  0xFC,  0x10,  0x80, 	/* 4F710 */
+	0x01,  0xFE,  0x7B,  0x22,  0x0D,  0x32,  0x09,  0x4A,  0x09,  0x82,  0x0D,  0xFA,  0x14,  0x0C,  0x23,  0x00, 	/* 4F720 */
+	0x40,  0xFF,  0x90,  0x10,  0x00,  0x09,  0xEE,  0x09,  0x22,  0x01,  0x22,  0x21,  0x22,  0x11,  0xEE,  0x11, 	/* 4F730 */
+	0x00,  0x01,  0xFE,  0x79,  0x12,  0x09,  0x0A,  0x09,  0xCC,  0x09,  0x04,  0x0D,  0x1A,  0x15,  0x61,  0x23, 	/* 4F740 */
+	0x00,  0x40,  0xFF,  0x91,  0x10,  0x10,  0x08,  0x20,  0x08,  0xFC,  0x00,  0x84,  0x20,  0xFC,  0x10,  0x84, 	/* 4F750 */
+	0x10,  0xFC,  0x00,  0x00,  0x79,  0xFE,  0x08,  0x10,  0x08,  0xFC,  0x08,  0x10,  0x0C,  0x10,  0x15,  0xFF, 	/* 4F760 */
+	0x22,  0x00,  0x41,  0xFF,  0x92,  0x10,  0x78,  0x08,  0x48,  0x08,  0x84,  0x01,  0xFE,  0x22,  0x51,  0x11, 	/* 4F770 */
+	0xFE,  0x11,  0x52,  0x01,  0x56,  0x79,  0x5E,  0x09,  0x82,  0x09,  0xFE,  0x09,  0x02,  0x0D,  0xFE,  0x14, 	/* 4F780 */
+	0x00,  0x23,  0x00,  0x40,  0xFF,  0x93,  0x01,  0x04,  0x20,  0x88,  0x17,  0xFF,  0x10,  0x40,  0x00,  0x80, 	/* 4F790 */
+	0x01,  0xFC,  0x01,  0x04,  0x79,  0xFC,  0x09,  0x04,  0x09,  0xFC,  0x09,  0x04,  0x09,  0x04,  0x0D,  0xFC, 	/* 4F7A0 */
+	0x14,  0x00,  0x23,  0x00,  0x40,  0xFF,  0x94,  0x00,  0x20,  0x20,  0x20,  0x11,  0xFC,  0x10,  0x20,  0x07, 	/* 4F7B0 */
+	0xFF,  0x00,  0x88,  0x00,  0x50,  0x7B,  0xFE,  0x08,  0x20,  0x09,  0xFC,  0x08,  0x20,  0x0B,  0xFE,  0x0C, 	/* 4F7C0 */
+	0x20,  0x14,  0x20,  0x23,  0x20,  0x40,  0xFF,  0x95,  0x00,  0x20,  0x23,  0xFC,  0x10,  0x44,  0x10,  0x44, 	/* 4F7D0 */
+	0x07,  0xFF,  0x00,  0x00,  0x01,  0xFC,  0x79,  0x04,  0x09,  0xFC,  0x08,  0x10,  0x09,  0xFE,  0x09,  0x10, 	/* 4F7E0 */
+	0x0F,  0xFF,  0x14,  0x10,  0x23,  0x10,  0x40,  0xFF,  0x96,  0x10,  0x20,  0x08,  0x20,  0x0B,  0xFF,  0x00, 	/* 4F7F0 */
+	0x20,  0x20,  0x20,  0x11,  0xFE,  0x11,  0x8A,  0x01,  0x52,  0x79,  0xFA,  0x09,  0x22,  0x09,  0xFA,  0x09, 	/* 4F800 */
+	0x22,  0x0D,  0x22,  0x15,  0x26,  0x23,  0x00,  0x40,  0xFF,  0x98,  0x10,  0x88,  0x0B,  0xFE,  0x08,  0x88, 	/* 4F810 */
+	0x03,  0xFE,  0x20,  0x88,  0x17,  0xFF,  0x10,  0x20,  0x01,  0xFC,  0x79,  0x24,  0x09,  0xFC,  0x09,  0x24, 	/* 4F820 */
+	0x0B,  0xFF,  0x0D,  0x04,  0x15,  0x0C,  0x23,  0x00,  0x40,  0xFF,  0x99,  0x10,  0x10,  0x08,  0x3E,  0x08, 	/* 4F830 */
+	0xC4,  0x03,  0x28,  0x20,  0xB0,  0x10,  0xC0,  0x17,  0x40,  0x00,  0xFE,  0x79,  0x20,  0x08,  0x20,  0x0F, 	/* 4F840 */
+	0xFF,  0x09,  0x22,  0x0D,  0x22,  0x15,  0xFE,  0x23,  0x00,  0x40,  0xFF,  0x9C,  0x00,  0x02,  0x27,  0x8C, 	/* 4F850 */
+	0x10,  0xF8,  0x11,  0x08,  0x01,  0x32,  0x01,  0x14,  0x01,  0x4C,  0x79,  0x92,  0x0F,  0x7D,  0x09,  0x08, 	/* 4F860 */
+	0x09,  0x2C,  0x09,  0x2A,  0x09,  0x49,  0x17,  0x08,  0x22,  0x00,  0x41,  0xFF,  0x9E,  0x10,  0x02,  0x08, 	/* 4F870 */
+	0x0C,  0x09,  0xF0,  0x01,  0x1E,  0x21,  0x10,  0x11,  0xFF,  0x11,  0xA2,  0x01,  0xB8,  0x79,  0xE2,  0x0A, 	/* 4F880 */
+	0xBE,  0x0A,  0x98,  0x0C,  0xA9,  0x09,  0x29,  0x14,  0x47,  0x23,  0x80,  0x40,  0xFF,  0xA0,  0x00,  0x40, 	/* 4F890 */
+	0x20,  0x40,  0x13,  0xFC,  0x10,  0x40,  0x07,  0xFE,  0x00,  0x00,  0x03,  0xFC,  0x7A,  0x04,  0x0B,  0xFC, 	/* 4F8A0 */
+	0x08,  0xC4,  0x09,  0x68,  0x0A,  0x50,  0x0C,  0x4C,  0x14,  0x43,  0x23,  0x00,  0x40,  0xFF,  0xA1,  0x02, 	/* 4F8B0 */
+	0x20,  0x21,  0x3E,  0x11,  0x52,  0x13,  0xF2,  0x00,  0x9E,  0x02,  0xB2,  0x02,  0xB2,  0x7A,  0xB2,  0x0B, 	/* 4F8C0 */
+	0xFE,  0x0A,  0x92,  0x08,  0x92,  0x09,  0x12,  0x16,  0x22,  0x12,  0x46,  0x21,  0x80,  0x40,  0xFF,  0xA3, 	/* 4F8D0 */
+	0x00,  0x20,  0x21,  0xFC,  0x11,  0x24,  0x11,  0xFC,  0x00,  0x20,  0x07,  0xFF,  0x00,  0x00,  0x79,  0xF8, 	/* 4F8E0 */
+	0x09,  0x08,  0x09,  0xF8,  0x09,  0x00,  0x09,  0xFC,  0x15,  0x04,  0x13,  0xFC,  0x21,  0x80,  0x40,  0x7F, 	/* 4F8F0 */
+	0xA5,  0x00,  0x0C,  0x23,  0xF0,  0x10,  0x84,  0x12,  0x44,  0x01,  0x48,  0x01,  0x10,  0x03,  0xFC,  0x78, 	/* 4F900 */
+	0x20,  0x08,  0x20,  0x0F,  0xFE,  0x09,  0x24,  0x09,  0x24,  0x15,  0xFC,  0x13,  0x04,  0x21,  0x80,  0x40, 	/* 4F910 */
+	0x7F,  0xA8,  0x01,  0x08,  0x21,  0x08,  0x37,  0xC8,  0x11,  0x1F,  0x07,  0xD2,  0x01,  0x12,  0x0F,  0xEA, 	/* 4F920 */
+	0x01,  0x0A,  0x79,  0xC4,  0x09,  0x4C,  0x0A,  0x4C,  0x0C,  0x52,  0x08,  0x62,  0x15,  0x81,  0x23,  0x00, 	/* 4F930 */
+	0x40,  0xFF,  0xA9,  0x00,  0x20,  0x20,  0x20,  0x13,  0xFF,  0x10,  0x84,  0x00,  0x48,  0x01,  0xFE,  0x01, 	/* 4F940 */
+	0x22,  0x79,  0xFE,  0x09,  0x22,  0x09,  0x7A,  0x09,  0x4A,  0x09,  0x7A,  0x15,  0x02,  0x13,  0x06,  0x21, 	/* 4F950 */
+	0x80,  0x40,  0x7F,  0xAD,  0x00,  0x50,  0x27,  0xFF,  0x10,  0x50,  0x13,  0xFE,  0x02,  0x52,  0x03,  0xFE, 	/* 4F960 */
+	0x02,  0x52,  0x7B,  0xFE,  0x08,  0x00,  0x09,  0xFC,  0x09,  0x04,  0x09,  0xFC,  0x15,  0x04,  0x13,  0xFC, 	/* 4F970 */
+	0x21,  0x80,  0x40,  0x7F,  0xAE,  0x00,  0x10,  0x20,  0x10,  0x11,  0xFF,  0x11,  0x00,  0x01,  0x24,  0x01, 	/* 4F980 */
+	0xFF,  0x01,  0x24,  0x79,  0x24,  0x09,  0x3C,  0x09,  0x24,  0x0A,  0x00,  0x0C,  0x54,  0x14,  0xAA,  0x13, 	/* 4F990 */
+	0x29,  0x21,  0x80,  0x40,  0x7F,  0xAF,  0x10,  0x00,  0x09,  0xFF,  0x09,  0x48,  0x01,  0x48,  0x21,  0xD9, 	/* 4F9A0 */
+	0x11,  0x65,  0x11,  0x4E,  0x01,  0x54,  0x79,  0xE6,  0x09,  0x4E,  0x09,  0x55,  0x0A,  0x65,  0x0C,  0x44, 	/* 4F9B0 */
+	0x14,  0xD8,  0x23,  0x00,  0x40,  0xFF,  0xB2,  0x10,  0x00,  0x09,  0xFE,  0x09,  0x02,  0x01,  0xFE,  0x21, 	/* 4F9C0 */
+	0x00,  0x11,  0xD6,  0x11,  0x10,  0x01,  0xD6,  0x79,  0x50,  0x09,  0x7C,  0x0A,  0x90,  0x0A,  0xFF,  0x0D, 	/* 4F9D0 */
+	0x10,  0x14,  0x10,  0x23,  0x00,  0x40,  0xFF,  0xB5,  0x01,  0x04,  0x20,  0x88,  0x17,  0xFF,  0x10,  0x90, 	/* 4F9E0 */
+	0x03,  0xFC,  0x02,  0x94,  0x03,  0x1C,  0x7B,  0xFC,  0x0A,  0x04,  0x0B,  0xFC,  0x08,  0x08,  0x0F,  0xFF, 	/* 4F9F0 */
+	0x14,  0x88,  0x12,  0x48,  0x21,  0x98,  0x40,  0xFF,  0xB6,  0x10,  0x10,  0x08,  0xFC,  0x08,  0x10,  0x01, 	/* 4FA00 */
+	0xFE,  0x20,  0x84,  0x13,  0xFF,  0x10,  0x84,  0x00,  0xE4,  0x7B,  0x1F,  0x08,  0x00,  0x09,  0xFE,  0x08, 	/* 4FA10 */
+	0x28,  0x0C,  0x49,  0x15,  0x87,  0x23,  0x00,  0x40,  0xFF,  0xB7,  0x00,  0x00,  0x17,  0xFE,  0x08,  0x90, 	/* 4FA20 */
+	0x0B,  0xFC,  0x02,  0x94,  0x03,  0xFC,  0x00,  0x40,  0x7F,  0xFF,  0x08,  0x88,  0x09,  0xF4,  0x0A,  0x13, 	/* 4FA30 */
+	0x0D,  0xF4,  0x09,  0x04,  0x14,  0xFC,  0x23,  0x00,  0x40,  0xFF,  0xB8,  0x00,  0x00,  0x27,  0xBC,  0x10, 	/* 4FA40 */
+	0x84,  0x17,  0xBC,  0x04,  0x20,  0x04,  0x62,  0x03,  0xDE,  0x71,  0x10,  0x17,  0xFC,  0x11,  0x10,  0x11, 	/* 4FA50 */
+	0x10,  0x1F,  0xFE,  0x10,  0xA0,  0x2B,  0x18,  0x26,  0x04,  0x41,  0xFF,  0xBA,  0x00,  0x20,  0x21,  0xF8, 	/* 4FA60 */
+	0x11,  0x28,  0x11,  0xF8,  0x00,  0x20,  0x07,  0xFE,  0x00,  0x00,  0x79,  0xF8,  0x09,  0x08,  0x09,  0xF8, 	/* 4FA70 */
+	0x09,  0x08,  0x09,  0xF8,  0x0D,  0x08,  0x15,  0xF8,  0x23,  0x04,  0x40,  0xFF,  0xBC,  0x00,  0x20,  0x20, 	/* 4FA80 */
+	0x20,  0x17,  0xFF,  0x12,  0x4A,  0x01,  0x84,  0x01,  0xFE,  0x02,  0x85,  0x7C,  0xFC,  0x08,  0x84,  0x08, 	/* 4FA90 */
+	0xFC,  0x09,  0x24,  0x09,  0x22,  0x0A,  0x22,  0x14,  0x60,  0x23,  0x00,  0x40,  0xFF,  0xBD,  0x10,  0x10, 	/* 4FAA0 */
+	0x08,  0x1E,  0x08,  0x10,  0x21,  0xFF,  0x11,  0x2A,  0x11,  0xF0,  0x01,  0x24,  0x79,  0xFF,  0x09,  0x21, 	/* 4FAB0 */
+	0x09,  0xD6,  0x0A,  0x2C,  0x0A,  0xDA,  0x0C,  0x2A,  0x14,  0xC9,  0x23,  0x18,  0x40,  0xFF,  0xBF,  0x00, 	/* 4FAC0 */
+	0x08,  0x23,  0xC8,  0x12,  0x7E,  0x12,  0x44,  0x02,  0x54,  0x03,  0xC8,  0x02,  0x7F,  0x7A,  0x08,  0x0B, 	/* 4FAD0 */
+	0xC8,  0x0B,  0x7E,  0x0D,  0x48,  0x09,  0x48,  0x0D,  0xC8,  0x14,  0x08,  0x23,  0x00,  0x40,  0xFF,  0x80, 	/* 4FAE0 */
+	0x10,  0x48,  0x08,  0x88,  0x0B,  0xC8,  0x02,  0x4F,  0x23,  0xD2,  0x12,  0x62,  0x13,  0xD2,  0x00,  0x94, 	/* 4FAF0 */
+	0x7F,  0xF4,  0x08,  0x8C,  0x09,  0xC8,  0x09,  0x54,  0x0A,  0x52,  0x14,  0xE1,  0x23,  0x00,  0x40,  0xFF, 	/* 4FB00 */
+	0x81,  0x10,  0x88,  0x0B,  0xFF,  0x08,  0x88,  0x01,  0xFC,  0x21,  0x24,  0x11,  0xFC,  0x11,  0x24,  0x01, 	/* 4FB10 */
+	0xFC,  0x78,  0x20,  0x0B,  0xFE,  0x0A,  0x2A,  0x0A,  0x36,  0x0A,  0xC2,  0x16,  0x06,  0x23,  0x00,  0x40, 	/* 4FB20 */
+	0xFF,  0x82,  0x21,  0x00,  0x11,  0xFE,  0x12,  0x4A,  0x04,  0x8A,  0x27,  0xD2,  0x15,  0x66,  0x17,  0xD0, 	/* 4FB30 */
+	0x05,  0x5E,  0x75,  0x68,  0x17,  0xC8,  0x14,  0x7F,  0x14,  0x48,  0x14,  0x48,  0x2C,  0xC8,  0x26,  0x00, 	/* 4FB40 */
+	0x41,  0xFF,  0x83,  0x10,  0x20,  0x0B,  0xFE,  0x0A,  0x4A,  0x01,  0x87,  0x26,  0x48,  0x13,  0xFE,  0x10, 	/* 4FB50 */
+	0x40,  0x00,  0xA2,  0x7B,  0x6C,  0x08,  0x98,  0x0B,  0x34,  0x08,  0xD2,  0x17,  0x11,  0x12,  0x60,  0x21, 	/* 4FB60 */
+	0x80,  0x40,  0x7F,  0x84,  0x00,  0x00,  0x23,  0xFC,  0x12,  0x94,  0x13,  0xFC,  0x00,  0x00,  0x0F,  0xFF, 	/* 4FB70 */
+	0x00,  0x00,  0x79,  0xF8,  0x09,  0x08,  0x09,  0xF8,  0x08,  0xC2,  0x09,  0x64,  0x16,  0x58,  0x12,  0x47, 	/* 4FB80 */
+	0x21,  0xC0,  0x40,  0x7F,  0x87,  0x10,  0x00,  0x0B,  0xFF,  0x08,  0xA4,  0x01,  0x22,  0x23,  0xFF,  0x11, 	/* 4FB90 */
+	0x22,  0x11,  0x76,  0x01,  0xAA,  0x79,  0x76,  0x09,  0x76,  0x09,  0xAA,  0x09,  0x76,  0x0D,  0x22,  0x15, 	/* 4FBA0 */
+	0x26,  0x22,  0x00,  0x41,  0xFF,  0x89,  0x10,  0x20,  0x08,  0xFC,  0x08,  0x84,  0x00,  0xFC,  0x20,  0x84, 	/* 4FBB0 */
+	0x10,  0xFC,  0x10,  0x84,  0x03,  0xFF,  0x7A,  0x01,  0x0A,  0x59,  0x08,  0x84,  0x09,  0xFE,  0x0E,  0x85, 	/* 4FBC0 */
+	0x14,  0xFC,  0x23,  0x00,  0x40,  0xFF,  0x8A,  0x10,  0x20,  0x08,  0xFC,  0x08,  0x84,  0x00,  0xFC,  0x20, 	/* 4FBD0 */
+	0x84,  0x10,  0xFC,  0x10,  0x84,  0x03,  0xFF,  0x7A,  0x49,  0x0B,  0xA7,  0x08,  0xFC,  0x08,  0x20,  0x0C, 	/* 4FBE0 */
+	0x7C,  0x14,  0x44,  0x23,  0x98,  0x40,  0xFF,  0x8F,  0x10,  0x00,  0x0B,  0xFE,  0x0A,  0x52,  0x03,  0xFE, 	/* 4FBF0 */
+	0x21,  0x00,  0x11,  0x12,  0x16,  0x9F,  0x01,  0x34,  0x7A,  0x9E,  0x0F,  0xD4,  0x09,  0x1E,  0x0B,  0x94, 	/* 4FC00 */
+	0x0D,  0x54,  0x15,  0x1F,  0x23,  0x00,  0x40,  0xFF,  0x91,  0x00,  0x00,  0x0F,  0xE0,  0x08,  0x20,  0x08, 	/* 4FC10 */
+	0x20,  0x0F,  0xE0,  0x00,  0x00,  0x3F,  0xF8,  0x21,  0x08,  0x21,  0x08,  0x21,  0x08,  0x3F,  0xF8,  0x20, 	/* 4FC20 */
+	0x00,  0x20,  0x00,  0x20,  0x02,  0x10,  0x02,  0x0F,  0xFE,  0xA3,  0x00,  0x00,  0x7F,  0x3E,  0x09,  0x22, 	/* 4FC30 */
+	0x09,  0x24,  0x09,  0x28,  0x3F,  0x38,  0x09,  0x24,  0x09,  0x22,  0x09,  0x22,  0x3F,  0x21,  0x09,  0x31, 	/* 4FC40 */
+	0x09,  0x29,  0x11,  0x26,  0x11,  0x20,  0x21,  0x20,  0x43,  0x20,  0xA6,  0x04,  0x00,  0x04,  0x3C,  0x3F, 	/* 4FC50 */
+	0xA4,  0x04,  0x24,  0x04,  0x28,  0x3F,  0xB0,  0x04,  0x28,  0x04,  0x24,  0x04,  0x22,  0x7F,  0xA2,  0x04, 	/* 4FC60 */
+	0x22,  0x04,  0x22,  0x08,  0x32,  0x08,  0x2C,  0x10,  0x20,  0x20,  0x20,  0xA8,  0x08,  0x00,  0x08,  0xBE, 	/* 4FC70 */
+	0x0B,  0x22,  0x7C,  0x24,  0x08,  0x24,  0x29,  0x28,  0x29,  0x24,  0x29,  0x22,  0x29,  0x22,  0x29,  0x21, 	/* 4FC80 */
+	0x3F,  0x21,  0x08,  0x31,  0x08,  0xAE,  0x08,  0xA0,  0x07,  0xA0,  0x00,  0x20,  0xAA,  0x00,  0x00,  0x3F, 	/* 4FC90 */
+	0x7C,  0x12,  0x44,  0x12,  0x44,  0x12,  0x48,  0x12,  0x50,  0x7F,  0xC8,  0x06,  0x44,  0x06,  0x44,  0x0A, 	/* 4FCA0 */
+	0x42,  0x0A,  0x42,  0x12,  0x62,  0x22,  0x5C,  0x42,  0x40,  0x02,  0x40,  0x06,  0x40,  0xAF,  0x11,  0x00, 	/* 4FCB0 */
+	0x11,  0x3E,  0x11,  0x22,  0x11,  0x24,  0x7F,  0xE4,  0x11,  0x28,  0x11,  0x24,  0x11,  0x22,  0x11,  0x22, 	/* 4FCC0 */
+	0x1F,  0x21,  0x11,  0x21,  0x11,  0x31,  0x11,  0x2E,  0x11,  0x20,  0x1F,  0x20,  0x00,  0x20,  0xB1,  0x01, 	/* 4FCD0 */
+	0x00,  0x06,  0x3E,  0x18,  0x22,  0x10,  0x24,  0x10,  0x24,  0x1F,  0xA8,  0x11,  0x24,  0x11,  0x22,  0x11, 	/* 4FCE0 */
+	0x22,  0x11,  0x21,  0x11,  0x21,  0x11,  0xF1,  0x1E,  0x2E,  0x60,  0x20,  0x00,  0x20,  0x00,  0x20,  0xB5, 	/* 4FCF0 */
+	0x00,  0x00,  0x7F,  0xBE,  0x08,  0xA2,  0x08,  0xA4,  0x10,  0xA4,  0x10,  0xA8,  0x20,  0xA4,  0x43,  0x22, 	/* 4FD00 */
+	0x00,  0x22,  0x3F,  0x21,  0x21,  0x21,  0x21,  0x31,  0x21,  0x2E,  0x21,  0x20,  0x3F,  0x20,  0x00,  0x20, 	/* 4FD10 */
+	0xB8,  0x01,  0x00,  0x06,  0x3E,  0x38,  0x22,  0x24,  0x24,  0x24,  0x24,  0x24,  0x28,  0x3F,  0xA4,  0x24, 	/* 4FD20 */
+	0x22,  0x24,  0x22,  0x24,  0x21,  0x22,  0x21,  0x3A,  0xB9,  0x62,  0xA6,  0x01,  0xA0,  0x7D,  0xA0,  0x00, 	/* 4FD30 */
+	0xA0,  0x81,  0x04,  0x00,  0x04,  0x1E,  0x7F,  0xF2,  0x04,  0x12,  0x08,  0x14,  0x0F,  0x98,  0x18,  0x94, 	/* 4FD40 */
+	0x18,  0x92,  0x2F,  0x91,  0x48,  0x91,  0x08,  0x91,  0x0F,  0x99,  0x08,  0x96,  0x08,  0x90,  0x08,  0x90, 	/* 4FD50 */
+	0x09,  0x90,  0x8A,  0x08,  0x00,  0x08,  0x3C,  0x08,  0x24,  0x7F,  0xA4,  0x12,  0x28,  0x11,  0x30,  0x22, 	/* 4FD60 */
+	0xA8,  0x52,  0xA4,  0x0A,  0x22,  0x0C,  0x22,  0x04,  0x22,  0x0A,  0x22,  0x09,  0x32,  0x11,  0x2C,  0x20, 	/* 4FD70 */
+	0x20,  0x40,  0x20,  0x8E,  0x08,  0x00,  0x08,  0x3C,  0x3F,  0x24,  0x21,  0x24,  0x21,  0x24,  0x3F,  0x28, 	/* 4FD80 */
+	0x21,  0x30,  0x21,  0x28,  0x3F,  0x24,  0x24,  0x22,  0x22,  0x22,  0x21,  0x22,  0x27,  0x32,  0x38,  0xAC, 	/* 4FD90 */
+	0x60,  0xA0,  0x00,  0x20,  0x9B,  0x00,  0x80,  0x03,  0x3E,  0x3D,  0x22,  0x28,  0xA4,  0x24,  0x64,  0x44, 	/* 4FDA0 */
+	0x68,  0x3F,  0x24,  0x01,  0x22,  0x02,  0x22,  0x04,  0xA1,  0x07,  0x21,  0x7C,  0x31,  0x04,  0x2E,  0x04, 	/* 4FDB0 */
+	0x20,  0x04,  0x20,  0x0C,  0x20,  0xA1,  0x00,  0x00,  0x3F,  0x3C,  0x09,  0x24,  0x09,  0x24,  0x7F,  0xA8, 	/* 4FDC0 */
+	0x09,  0x30,  0x09,  0x28,  0x3F,  0x24,  0x08,  0x24,  0x10,  0x22,  0x1F,  0x22,  0x31,  0x22,  0x31,  0x32, 	/* 4FDD0 */
+	0x51,  0x2C,  0x1F,  0x20,  0x00,  0x20,  0xA2,  0x00,  0x00,  0x3F,  0x3E,  0x21,  0x22,  0x21,  0x24,  0x3F, 	/* 4FDE0 */
+	0x24,  0x00,  0x28,  0x00,  0x24,  0x7F,  0xA2,  0x04,  0x22,  0x04,  0x21,  0x3F,  0x21,  0x04,  0x31,  0x05, 	/* 4FDF0 */
+	0xAE,  0x0E,  0x20,  0x70,  0x20,  0x00,  0x20,  0xA4,  0x04,  0x00,  0x06,  0x3E,  0x09,  0x22,  0x08,  0xA4, 	/* 4FE00 */
+	0x14,  0xA4,  0x24,  0x28,  0x0A,  0x24,  0x09,  0x22,  0x10,  0xA2,  0x20,  0x61,  0x5F,  0xA1,  0x10,  0xB1, 	/* 4FE10 */
+	0x10,  0xAE,  0x10,  0xA0,  0x1F,  0xA0,  0x00,  0x20,  0xA8,  0x08,  0x00,  0x08,  0x3E,  0x7F,  0xA2,  0x21, 	/* 4FE20 */
+	0x22,  0x12,  0x24,  0x12,  0x24,  0x14,  0x28,  0xFF,  0xA4,  0x00,  0x22,  0x00,  0x22,  0x3F,  0x21,  0x21, 	/* 4FE30 */
+	0x31,  0x21,  0x29,  0x21,  0x26,  0x3F,  0x20,  0x00,  0x20,  0xAD,  0x04,  0x00,  0x04,  0x3E,  0x7F,  0xE2, 	/* 4FE40 */
+	0x00,  0x22,  0x1F,  0xA4,  0x10,  0xA4,  0x1F,  0xA8,  0x00,  0x24,  0x3F,  0xA2,  0x01,  0x22,  0x02,  0x21, 	/* 4FE50 */
+	0x03,  0xB1,  0x7E,  0x29,  0x02,  0x26,  0x02,  0x20,  0x06,  0x20,  0xB5,  0x00,  0x80,  0x03,  0x3C,  0x3C, 	/* 4FE60 */
+	0x24,  0x04,  0x24,  0x3F,  0xE8,  0x14,  0xB0,  0x14,  0xA8,  0x7F,  0xE4,  0x14,  0xA2,  0x14,  0xA2,  0x3F, 	/* 4FE70 */
+	0xE2,  0x04,  0x32,  0x04,  0x2C,  0x05,  0xA0,  0x0E,  0x20,  0x30,  0x20,  0xB7,  0x08,  0x00,  0x0B,  0xDE, 	/* 4FE80 */
+	0x12,  0x52,  0x16,  0x52,  0x67,  0xD4,  0x1A,  0x58,  0x0A,  0x54,  0x0F,  0xD2,  0x16,  0x11,  0x26,  0x91, 	/* 4FE90 */
+	0x7A,  0x51,  0x0A,  0x59,  0x12,  0xB6,  0x13,  0x30,  0x26,  0x10,  0x40,  0x10,  0xBD,  0x04,  0x00,  0x04, 	/* 4FEA0 */
+	0x9E,  0x3F,  0x92,  0x04,  0x92,  0x05,  0x14,  0x05,  0x14,  0x7F,  0xF8,  0x04,  0x14,  0x0F,  0x92,  0x08, 	/* 4FEB0 */
+	0x91,  0x18,  0x91,  0x2F,  0x91,  0x48,  0x99,  0x08,  0x96,  0x0F,  0x90,  0x00,  0x10,  0x82,  0x00,  0x00, 	/* 4FEC0 */
+	0x3B,  0xBE,  0x2A,  0xA2,  0x2A,  0xA4,  0x3B,  0xA4,  0x00,  0x28,  0x3F,  0x24,  0x00,  0x22,  0x7F,  0xA2, 	/* 4FED0 */
+	0x08,  0x21,  0x08,  0x21,  0x1F,  0x31,  0x11,  0x2E,  0x01,  0x20,  0x01,  0x20,  0x06,  0x20,  0x92,  0x10, 	/* 4FEE0 */
+	0x00,  0x1F,  0xBE,  0x28,  0xA2,  0x6A,  0xA4,  0x2A,  0xA4,  0x3E,  0xA8,  0x10,  0xA4,  0x23,  0x22,  0x10, 	/* 4FEF0 */
+	0x22,  0x1F,  0xA1,  0x28,  0xA1,  0x6A,  0xB1,  0x2A,  0xAE,  0x3E,  0xA0,  0x10,  0xA0,  0x23,  0x20,  0x99, 	/* 4FF00 */
+	0x00,  0x00,  0x1F,  0x3E,  0x11,  0x22,  0x11,  0x24,  0x1F,  0x24,  0x04,  0x28,  0x7F,  0xE4,  0x00,  0x22, 	/* 4FF10 */
+	0x3F,  0xA2,  0x20,  0xA1,  0x2E,  0xA1,  0x2A,  0xB1,  0x2E,  0xAE,  0x20,  0xA0,  0x3F,  0xA0,  0x00,  0x20, 	/* 4FF20 */
+	0xAD,  0x11,  0x00,  0x0A,  0x1E,  0x7F,  0xD2,  0x0A,  0x12,  0x3F,  0x94,  0x2A,  0x98,  0x33,  0x94,  0x20, 	/* 4FF30 */
+	0x92,  0x3F,  0x92,  0x20,  0x91,  0x3F,  0x91,  0x04,  0x19,  0x7F,  0xD6,  0x0A,  0x10,  0x11,  0x10,  0x60, 	/* 4FF40 */
+	0x10,  0xB0,  0x04,  0x00,  0x24,  0xBE,  0x15,  0x22,  0x7F,  0xE4,  0x0E,  0x24,  0x15,  0x28,  0x64,  0xA4, 	/* 4FF50 */
+	0x14,  0x22,  0x18,  0xA2,  0x2B,  0xE1,  0x2A,  0xA1,  0x5A,  0xB1,  0x17,  0xEE,  0x10,  0xA0,  0x20,  0xA0, 	/* 4FF60 */
+	0x40,  0xA0,  0xB2,  0x00,  0x00,  0x3B,  0xBE,  0x2A,  0xA2,  0x3B,  0xA4,  0x00,  0x24,  0x3F,  0xA8,  0x24, 	/* 4FF70 */
+	0xA4,  0x24,  0xA2,  0x3F,  0xA2,  0x24,  0xA1,  0x3F,  0xA1,  0x04,  0x31,  0x7F,  0xEE,  0x04,  0x20,  0x04, 	/* 4FF80 */
+	0x20,  0x04,  0x20,  0x89,  0x00,  0x00,  0x7F,  0xFE,  0x02,  0x40,  0x02,  0x40,  0x3F,  0xFC,  0x22,  0x44, 	/* 4FF90 */
+	0x22,  0x44,  0x24,  0x4C,  0x28,  0x3C,  0x30,  0x04,  0x20,  0x04,  0x3F,  0xFC,  0x20,  0x04,  0x20,  0x04, 	/* 4FFA0 */
+	0x3F,  0xFC,  0x00,  0x00,  0x8A,  0x00,  0x00,  0x7F,  0xFF,  0x0A,  0x08,  0x0A,  0x08,  0x3F,  0x88,  0x2A, 	/* 4FFB0 */
+	0x88,  0x2A,  0x88,  0x2A,  0x88,  0x33,  0x88,  0x20,  0x88,  0x20,  0x88,  0x3F,  0x88,  0x20,  0x88,  0x20, 	/* 4FFC0 */
+	0x88,  0x3F,  0x88,  0x00,  0x18,  0x8B,  0x08,  0x10,  0x04,  0x10,  0x04,  0x20,  0x7F,  0xFE,  0x02,  0x40, 	/* 4FFD0 */
+	0x02,  0x40,  0x3F,  0xFC,  0x22,  0x44,  0x24,  0x4C,  0x28,  0x3C,  0x30,  0x04,  0x3F,  0xFC,  0x20,  0x04, 	/* 4FFE0 */
+	0x20,  0x04,  0x3F,  0xFC,  0x00,  0x00,  0x8C,  0x00,  0x20,  0x7F,  0xA0,  0x0C,  0x20,  0x0C,  0x3E,  0x3F, 	/* 4FFF0 */
+	0x42,  0x2D,  0x42,  0x2D,  0x82,  0x35,  0x22,  0x37,  0x12,  0x21,  0x12,  0x21,  0x02,  0x3F,  0x02,  0x21, 	/* 50000 */
+	0x02,  0x21,  0x02,  0x3F,  0x04,  0x00,  0x18,  0x8D,  0x00,  0x00,  0x7F,  0xFE,  0x0A,  0x02,  0x0A,  0x02, 	/* 50010 */
+	0x3F,  0x82,  0x2A,  0x82,  0x2A,  0xBE,  0x2A,  0xA0,  0x33,  0xA0,  0x30,  0xA0,  0x20,  0xA0,  0x3F,  0xA0, 	/* 50020 */
+	0x20,  0xA1,  0x20,  0xA1,  0x3F,  0x91,  0x00,  0x0F,  0x8E,  0x00,  0x04,  0x7F,  0xC4,  0x0A,  0x04,  0x0A, 	/* 50030 */
+	0x04,  0x3F,  0xFF,  0x2A,  0x84,  0x2A,  0x84,  0x2A,  0xA4,  0x2B,  0x94,  0x30,  0x94,  0x20,  0x84,  0x3F, 	/* 50040 */
+	0x84,  0x20,  0x84,  0x20,  0x84,  0x3F,  0x84,  0x00,  0x0C,  0x92,  0x10,  0x00,  0x0F,  0xFF,  0x08,  0x50, 	/* 50050 */
+	0x00,  0x50,  0x43,  0xFE,  0x22,  0x52,  0x22,  0x52,  0x02,  0x52,  0x0A,  0x92,  0x0A,  0x8E,  0x13,  0x02, 	/* 50060 */
+	0x13,  0xFE,  0x22,  0x02,  0x22,  0x02,  0x43,  0xFE,  0x40,  0x00,  0x94,  0x00,  0x20,  0x7F,  0x20,  0x0C, 	/* 50070 */
+	0xFC,  0x0C,  0x24,  0x3F,  0x24,  0x2D,  0x25,  0x2D,  0x45,  0x35,  0x93,  0x37,  0x10,  0x31,  0x10,  0x21, 	/* 50080 */
+	0xFF,  0x3F,  0x10,  0x21,  0x10,  0x21,  0x10,  0x3F,  0x10,  0x21,  0x10,  0x96,  0x00,  0x10,  0x7F,  0x90, 	/* 50090 */
+	0x0C,  0x10,  0x0C,  0xFF,  0x3F,  0x91,  0x2D,  0x91,  0x2D,  0x10,  0x2D,  0x18,  0x37,  0x18,  0x31,  0x18, 	/* 500A0 */
+	0x21,  0x28,  0x3F,  0x28,  0x21,  0x29,  0x21,  0x49,  0x3F,  0x89,  0x01,  0x07,  0x98,  0x00,  0x00,  0x7F, 	/* 500B0 */
+	0xBC,  0x0C,  0x24,  0x0C,  0x24,  0x3F,  0x25,  0x2D,  0x45,  0x2D,  0x83,  0x2D,  0x7C,  0x37,  0x04,  0x31, 	/* 500C0 */
+	0x24,  0x21,  0x24,  0x3F,  0x18,  0x21,  0x18,  0x21,  0x24,  0x3F,  0x42,  0x01,  0x81,  0xA2,  0x00,  0x20, 	/* 500D0 */
+	0x7F,  0xA0,  0x0C,  0x20,  0x0C,  0x3F,  0x3F,  0x50,  0x2D,  0x50,  0x2D,  0x90,  0x35,  0x1E,  0x37,  0x10, 	/* 500E0 */
+	0x21,  0x10,  0x21,  0x10,  0x3F,  0x1E,  0x21,  0x10,  0x21,  0x10,  0x3F,  0x10,  0x00,  0x10,  0xA3,  0x00, 	/* 500F0 */
+	0x24,  0x7F,  0xA4,  0x0C,  0x24,  0x0C,  0xFF,  0x3F,  0x24,  0x2D,  0x24,  0x2D,  0x24,  0x35,  0x24,  0x37, 	/* 50100 */
+	0x3C,  0x31,  0x24,  0x21,  0x24,  0x3F,  0x24,  0x21,  0x24,  0x21,  0x24,  0x3F,  0x3C,  0x00,  0x00,  0xA5, 	/* 50110 */
+	0x00,  0x02,  0x7F,  0x8C,  0x0C,  0x78,  0x0C,  0x08,  0x3F,  0x08,  0x2D,  0xFF,  0x2D,  0x08,  0x2D,  0x1C, 	/* 50120 */
+	0x37,  0x1C,  0x31,  0x2C,  0x21,  0x2A,  0x3F,  0x4A,  0x21,  0x89,  0x21,  0x08,  0x3F,  0x08,  0x00,  0x08, 	/* 50130 */
+	0xA9,  0x00,  0x08,  0x7F,  0x88,  0x0C,  0x1E,  0x0C,  0x12,  0x3F,  0x22,  0x2D,  0x64,  0x2D,  0x94,  0x2D, 	/* 50140 */
+	0x08,  0x37,  0x10,  0x31,  0x3E,  0x21,  0x22,  0x3F,  0x62,  0x21,  0xA2,  0x21,  0x22,  0x3F,  0x3E,  0x00, 	/* 50150 */
+	0x00,  0xAA,  0x00,  0x20,  0x7F,  0xA0,  0x0C,  0x3C,  0x0C,  0x24,  0x3F,  0x44,  0x2D,  0xA8,  0x2D,  0x18, 	/* 50160 */
+	0x35,  0x18,  0x37,  0x24,  0x21,  0x42,  0x21,  0xFD,  0x3F,  0x44,  0x21,  0x44,  0x21,  0x44,  0x3F,  0x7C, 	/* 50170 */
+	0x00,  0x00,  0xAC,  0x00,  0x02,  0x7F,  0xD2,  0x0C,  0x52,  0x0C,  0x52,  0x3F,  0x52,  0x2D,  0x5A,  0x2D, 	/* 50180 */
+	0xD6,  0x35,  0xF2,  0x37,  0x52,  0x21,  0x52,  0x21,  0x52,  0x3F,  0x52,  0x21,  0x52,  0x21,  0x42,  0x3F, 	/* 50190 */
+	0x82,  0x01,  0x02,  0xB2,  0x00,  0x00,  0x7F,  0xBE,  0x0A,  0x22,  0x0A,  0x22,  0x3F,  0xA2,  0x2A,  0xBE, 	/* 501A0 */
+	0x2A,  0x80,  0x2A,  0x82,  0x2B,  0xBC,  0x30,  0x88,  0x20,  0x88,  0x3F,  0xBE,  0x20,  0x88,  0x20,  0x88, 	/* 501B0 */
+	0x3F,  0xFF,  0x00,  0x00,  0xB3,  0x00,  0x08,  0x7F,  0xC8,  0x0A,  0x32,  0x0A,  0x14,  0x3F,  0x8C,  0x2A, 	/* 501C0 */
+	0x92,  0x2A,  0xFD,  0x2A,  0x81,  0x33,  0xBE,  0x20,  0xA2,  0x20,  0xBE,  0x3F,  0xA2,  0x20,  0xBE,  0x20, 	/* 501D0 */
+	0xA2,  0x3F,  0xA2,  0x00,  0x26,  0xB5,  0x00,  0x10,  0x7F,  0x92,  0x0C,  0xFE,  0x0C,  0x14,  0x3F,  0x18, 	/* 501E0 */
+	0x2D,  0xFF,  0x2D,  0x10,  0x35,  0x20,  0x37,  0x7C,  0x21,  0x84,  0x21,  0x08,  0x3F,  0xFF,  0x21,  0x08, 	/* 501F0 */
+	0x21,  0x08,  0x3F,  0x08,  0x00,  0x18,  0xB7,  0x00,  0x10,  0x7F,  0x50,  0x0C,  0x50,  0x0C,  0x7E,  0x3F, 	/* 50200 */
+	0x90,  0x2D,  0x10,  0x2D,  0x10,  0x2D,  0xFF,  0x37,  0x00,  0x31,  0x00,  0x21,  0x7C,  0x3F,  0x44,  0x21, 	/* 50210 */
+	0x44,  0x21,  0x44,  0x3F,  0x7C,  0x00,  0x00,  0xB8,  0x00,  0x10,  0x7F,  0x98,  0x0C,  0x26,  0x0C,  0xFD, 	/* 50220 */
+	0x3F,  0x28,  0x2D,  0x2A,  0x2D,  0x46,  0x35,  0xA0,  0x37,  0x3C,  0x31,  0x44,  0x21,  0x54,  0x3F,  0x98, 	/* 50230 */
+	0x21,  0x08,  0x21,  0x14,  0x3F,  0x22,  0x00,  0xC1,  0x82,  0x00,  0x24,  0x7F,  0xA4,  0x0C,  0x24,  0x0C, 	/* 50240 */
+	0xFF,  0x3F,  0x24,  0x2D,  0x24,  0x2D,  0x34,  0x35,  0x6E,  0x37,  0x6E,  0x31,  0xB5,  0x21,  0xA5,  0x3F, 	/* 50250 */
+	0x24,  0x21,  0x24,  0x21,  0x24,  0x3F,  0x24,  0x00,  0x24,  0x87,  0x00,  0x10,  0x7F,  0x10,  0x0C,  0xFF, 	/* 50260 */
+	0x0C,  0x00,  0x3F,  0x7C,  0x2D,  0x44,  0x2D,  0x7C,  0x35,  0x00,  0x37,  0x7C,  0x21,  0x08,  0x21,  0x10, 	/* 50270 */
+	0x3F,  0xFF,  0x21,  0x10,  0x21,  0x10,  0x3F,  0x10,  0x00,  0x30,  0x89,  0x00,  0x08,  0x7F,  0x88,  0x0C, 	/* 50280 */
+	0xFF,  0x0C,  0x24,  0x3F,  0x24,  0x2D,  0x24,  0x2D,  0x36,  0x35,  0x49,  0x37,  0x88,  0x31,  0xFF,  0x21, 	/* 50290 */
+	0x08,  0x3F,  0x08,  0x21,  0x08,  0x21,  0x08,  0x3F,  0x08,  0x00,  0x08,  0x8B,  0x00,  0x24,  0x7F,  0xA4, 	/* 502A0 */
+	0x0C,  0x24,  0x0C,  0xFF,  0x3F,  0x24,  0x2D,  0x24,  0x2D,  0xFF,  0x35,  0x00,  0x37,  0x3E,  0x31,  0x22, 	/* 502B0 */
+	0x21,  0x22,  0x3F,  0x3E,  0x21,  0x22,  0x21,  0x22,  0x3F,  0x3E,  0x00,  0x00,  0x8D,  0x00,  0x00,  0x7F, 	/* 502C0 */
+	0xFC,  0x0C,  0x44,  0x0C,  0x7C,  0x3F,  0x44,  0x2D,  0x44,  0x2D,  0x7C,  0x35,  0x00,  0x37,  0xFF,  0x21, 	/* 502D0 */
+	0x10,  0x21,  0x50,  0x3F,  0x5E,  0x21,  0x50,  0x21,  0x70,  0x3F,  0x98,  0x21,  0x07,  0x90,  0x00,  0x40, 	/* 502E0 */
+	0x7F,  0x4E,  0x14,  0x4A,  0x14,  0x4A,  0x15,  0xFA,  0x3E,  0x4E,  0x2A,  0x4A,  0x2A,  0x4A,  0x37,  0xEA, 	/* 502F0 */
+	0x33,  0x2E,  0x23,  0x2A,  0x3F,  0x2A,  0x23,  0xEA,  0x22,  0x12,  0x3E,  0x12,  0x00,  0x26,  0x92,  0x00, 	/* 50300 */
+	0x00,  0x7F,  0xFE,  0x0C,  0x42,  0x0C,  0x7E,  0x3F,  0x42,  0x2D,  0x42,  0x2D,  0x7E,  0x35,  0x10,  0x37, 	/* 50310 */
+	0x50,  0x21,  0x7E,  0x21,  0x90,  0x3F,  0x7E,  0x21,  0x10,  0x21,  0x10,  0x3F,  0xFF,  0x00,  0x00,  0x97, 	/* 50320 */
+	0x00,  0xE8,  0x7F,  0x2A,  0x0C,  0xAC,  0x0C,  0x65,  0x3F,  0x46,  0x2D,  0x42,  0x2D,  0xFD,  0x35,  0x28, 	/* 50330 */
+	0x37,  0x28,  0x31,  0x28,  0x21,  0xFF,  0x3F,  0x28,  0x21,  0x28,  0x21,  0x49,  0x3F,  0x49,  0x21,  0x87, 	/* 50340 */
+	0x9C,  0x00,  0x08,  0x7F,  0x90,  0x0C,  0x7E,  0x0C,  0x52,  0x3F,  0x52,  0x2D,  0x7E,  0x2D,  0x52,  0x35, 	/* 50350 */
+	0x52,  0x37,  0x7E,  0x31,  0x14,  0x21,  0x34,  0x3F,  0x3A,  0x21,  0x5E,  0x21,  0x51,  0x3F,  0x91,  0x01, 	/* 50360 */
+	0x0F,  0xA2,  0x00,  0x10,  0x7F,  0x10,  0x0C,  0xFF,  0x0C,  0x20,  0x3F,  0x20,  0x2D,  0x7E,  0x2D,  0xA2, 	/* 50370 */
+	0x35,  0x22,  0x37,  0x3E,  0x31,  0x00,  0x21,  0x7E,  0x3F,  0x6A,  0x21,  0x6A,  0x21,  0x6A,  0x3F,  0xFF, 	/* 50380 */
+	0x00,  0x00,  0xA4,  0x24,  0x0C,  0x15,  0xF4,  0x05,  0x44,  0x0C,  0xA8,  0x17,  0xFF,  0x24,  0x88,  0x04, 	/* 50390 */
+	0x18,  0x7F,  0xFF,  0x01,  0x20,  0x1F,  0xFC,  0x12,  0x24,  0x1C,  0x3C,  0x1F,  0xFC,  0x10,  0x04,  0x1F, 	/* 503A0 */
+	0xFC,  0x10,  0x04,  0xAA,  0x00,  0x00,  0x7F,  0xEE,  0x0C,  0x66,  0x0C,  0xBA,  0x3F,  0x66,  0x2D,  0xAA, 	/* 503B0 */
+	0x2D,  0x10,  0x2D,  0x28,  0x37,  0x4C,  0x31,  0xB2,  0x21,  0x05,  0x3F,  0x18,  0x21,  0x62,  0x21,  0x04, 	/* 503C0 */
+	0x3F,  0x18,  0x00,  0xE0,  0xAB,  0x00,  0x00,  0x3F,  0xBD,  0x27,  0xA5,  0x2A,  0x43,  0x3F,  0xFC,  0x25, 	/* 503D0 */
+	0x14,  0x28,  0x88,  0x3F,  0xB4,  0x00,  0xC2,  0x7F,  0xFF,  0x01,  0x40,  0x1F,  0xFC,  0x12,  0x4C,  0x1C, 	/* 503E0 */
+	0x3C,  0x1F,  0xFC,  0x00,  0x00,  0xAF,  0x00,  0x10,  0x7F,  0x90,  0x0C,  0xFE,  0x0C,  0x10,  0x3F,  0x24, 	/* 503F0 */
+	0x2D,  0xFA,  0x2D,  0x45,  0x35,  0x54,  0x37,  0x54,  0x31,  0x55,  0x21,  0x83,  0x3F,  0x7E,  0x21,  0x6A, 	/* 50400 */
+	0x21,  0x6A,  0x3F,  0xFF,  0x00,  0x00,  0xB4,  0x00,  0x28,  0x7F,  0xFE,  0x0C,  0xAA,  0x0C,  0xFE,  0x3F, 	/* 50410 */
+	0xAA,  0x2D,  0xFE,  0x2D,  0x00,  0x2D,  0xFF,  0x37,  0x00,  0x31,  0x7E,  0x21,  0x42,  0x3F,  0x7E,  0x21, 	/* 50420 */
+	0x24,  0x21,  0x18,  0x3F,  0xFF,  0x00,  0x00,  0xB5,  0x00,  0x08,  0x7F,  0x8F,  0x0C,  0x08,  0x0C,  0x7F, 	/* 50430 */
+	0x3F,  0x52,  0x2D,  0x5C,  0x2D,  0x71,  0x2D,  0x4F,  0x37,  0x40,  0x31,  0x7F,  0x21,  0x68,  0x3F,  0x55, 	/* 50440 */
+	0x21,  0x6E,  0x21,  0x96,  0x3F,  0x25,  0x00,  0x0C,  0xB8,  0x00,  0x10,  0x7F,  0x10,  0x0D,  0xFF,  0x0C, 	/* 50450 */
+	0x44,  0x3F,  0xAA,  0x2D,  0x29,  0x2D,  0xFE,  0x35,  0x28,  0x37,  0xFE,  0x21,  0x28,  0x21,  0xFF,  0x3F, 	/* 50460 */
+	0x28,  0x21,  0x4A,  0x21,  0xC4,  0x3F,  0x72,  0x01,  0x81,  0xBA,  0x00,  0x02,  0x7F,  0x7C,  0x0C,  0x10, 	/* 50470 */
+	0x0D,  0xFF,  0x3F,  0x10,  0x2D,  0x7E,  0x2D,  0x76,  0x35,  0x5A,  0x37,  0x7E,  0x31,  0x10,  0x21,  0xFE, 	/* 50480 */
+	0x3F,  0x10,  0x21,  0xFF,  0x21,  0x00,  0x3F,  0xAA,  0x01,  0x25,  0x80,  0x00,  0x10,  0x7F,  0xFF,  0x0C, 	/* 50490 */
+	0x00,  0x0C,  0xEE,  0x3F,  0xAA,  0x2D,  0xEE,  0x2D,  0x24,  0x2D,  0x7E,  0x37,  0x24,  0x31,  0x7E,  0x21, 	/* 504A0 */
+	0x24,  0x3F,  0xFF,  0x21,  0x32,  0x21,  0xCC,  0x3F,  0x74,  0x00,  0xC3,  0x81,  0x1B,  0xEE,  0x22,  0x22, 	/* 504B0 */
+	0x3B,  0xEE,  0x23,  0x62,  0x7F,  0xFF,  0x41,  0x41,  0x5F,  0xFD,  0x12,  0x24,  0x1F,  0xFC,  0x10,  0x04, 	/* 504C0 */
+	0x1F,  0xFC,  0x08,  0x08,  0x17,  0xF4,  0x61,  0x13,  0x06,  0x10,  0x18,  0x60,  0x86,  0x00,  0x04,  0x00, 	/* 504D0 */
+	0x78,  0x3F,  0x88,  0x08,  0x88,  0x04,  0x90,  0x04,  0xA0,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0xC0,  0x02, 	/* 504E0 */
+	0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x87,  0x00,  0x04, 	/* 504F0 */
+	0x00,  0x38,  0x1F,  0xC0,  0x00,  0x84,  0x08,  0x44,  0x04,  0x48,  0x04,  0x90,  0x00,  0x80,  0x7F,  0xFF, 	/* 50500 */
+	0x01,  0xC0,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x60,  0x83,  0x00,  0x80,  0x00,  0x80,  0x88,  0x01, 	/* 50510 */
+	0x00,  0x06,  0x7E,  0x78,  0x42,  0x09,  0x42,  0x49,  0x42,  0x2A,  0x42,  0x28,  0x7E,  0x7F,  0x50,  0x08, 	/* 50520 */
+	0x50,  0x18,  0x50,  0x1C,  0x48,  0x2A,  0x48,  0x28,  0x44,  0x48,  0x84,  0x08,  0x82,  0x09,  0x01,  0x89, 	/* 50530 */
+	0x02,  0x10,  0x0C,  0x10,  0x78,  0x10,  0x0A,  0x10,  0x4A,  0xFE,  0x2C,  0x92,  0x28,  0x92,  0x7F,  0x92, 	/* 50540 */
+	0x08,  0x92,  0x1C,  0xFE,  0x1A,  0x92,  0x2A,  0x92,  0x28,  0x92,  0x48,  0x92,  0x08,  0xFE,  0x08,  0x00, 	/* 50550 */
+	0x8B,  0x02,  0x00,  0x0C,  0xFE,  0x78,  0xAA,  0x0A,  0xFE,  0x4A,  0x10,  0x2C,  0xFE,  0x28,  0x10,  0x7F, 	/* 50560 */
+	0xFF,  0x08,  0x44,  0x1C,  0x28,  0x1B,  0xFF,  0x2A,  0x10,  0x28,  0xFE,  0x48,  0x10,  0x08,  0x10,  0x08, 	/* 50570 */
+	0x10,  0x8C,  0x00,  0x00,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84,  0x1F,  0xFC,  0x10,  0x84,  0x10,  0x84, 	/* 50580 */
+	0x10,  0x84,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF, 	/* 50590 */
+	0x00,  0x00,  0x8D,  0x00,  0x18,  0x1F,  0xE0,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x0F,  0xF8,  0x08, 	/* 505A0 */
+	0x88,  0x0F,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F, 	/* 505B0 */
+	0xFF,  0x00,  0x00,  0x8E,  0x00,  0x00,  0x3F,  0xFE,  0x29,  0x04,  0x29,  0x48,  0x3F,  0x30,  0x29,  0x10, 	/* 505C0 */
+	0x29,  0xFF,  0x3F,  0x12,  0x08,  0x14,  0x08,  0x18,  0x7F,  0x10,  0x08,  0x10,  0x08,  0x10,  0x0F,  0x10, 	/* 505D0 */
+	0x70,  0x10,  0x00,  0x30,  0x8F,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x7F, 	/* 505E0 */
+	0xFF,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x80,  0x1F, 	/* 505F0 */
+	0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x90,  0x04,  0x10,  0x04,  0x10,  0x3F,  0xBF,  0x04,  0x24,  0x7F,  0xD4, 	/* 50600 */
+	0x15,  0x08,  0x24,  0x94,  0x44,  0x63,  0x1F,  0xFF,  0x12,  0x48,  0x13,  0xF8,  0x12,  0x48,  0x17,  0xFE, 	/* 50610 */
+	0x20,  0x40,  0x5F,  0xFF,  0x00,  0x00,  0x91,  0x00,  0x80,  0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x04, 	/* 50620 */
+	0x10,  0x18,  0x0C,  0x67,  0xF3,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFE,  0x00,  0x80,  0x08,  0x88,  0x04, 	/* 50630 */
+	0x88,  0x04,  0x90,  0x3F,  0xFE,  0x00,  0x00,  0x96,  0x04,  0x00,  0x04,  0xFE,  0x0A,  0x12,  0x09,  0x12, 	/* 50640 */
+	0x10,  0x92,  0x3F,  0x12,  0x44,  0x12,  0x04,  0x12,  0x7F,  0x12,  0x04,  0x12,  0x25,  0x12,  0x16,  0x22, 	/* 50650 */
+	0x14,  0x22,  0x07,  0x42,  0x18,  0x82,  0x61,  0x0C,  0x98,  0x04,  0x00,  0x04,  0x00,  0x0A,  0xFF,  0x09, 	/* 50660 */
+	0x08,  0x10,  0x88,  0x3F,  0x08,  0x44,  0x08,  0x04,  0x08,  0x3F,  0x88,  0x04,  0x08,  0x25,  0x08,  0x15, 	/* 50670 */
+	0x08,  0x16,  0x08,  0x05,  0x88,  0x0E,  0x08,  0x70,  0x18,  0x9B,  0x04,  0x10,  0x04,  0x10,  0x0A,  0x10, 	/* 50680 */
+	0x09,  0x10,  0x10,  0xFE,  0x3F,  0x12,  0x44,  0x12,  0x04,  0x12,  0x7F,  0x12,  0x04,  0x12,  0x25,  0x12, 	/* 50690 */
+	0x16,  0x22,  0x14,  0x22,  0x07,  0x42,  0x18,  0x82,  0x61,  0x0C,  0x9C,  0x02,  0x20,  0x04,  0x18,  0x0A, 	/* 506A0 */
+	0x24,  0x31,  0x42,  0x00,  0x80,  0x03,  0x60,  0x0C,  0x18,  0x77,  0xF7,  0x00,  0x80,  0x00,  0x80,  0x7F, 	/* 506B0 */
+	0xFF,  0x08,  0x88,  0x04,  0x88,  0x04,  0x90,  0x3F,  0xFE,  0x00,  0x00,  0x9D,  0x04,  0x10,  0x04,  0x10, 	/* 506C0 */
+	0x0C,  0x10,  0x0A,  0x10,  0x11,  0x10,  0x3F,  0x90,  0x44,  0xFF,  0x04,  0x10,  0x7F,  0x90,  0x04,  0x10, 	/* 506D0 */
+	0x25,  0x10,  0x16,  0x10,  0x14,  0x10,  0x07,  0x10,  0x1C,  0x10,  0x60,  0x10,  0x9F,  0x08,  0x78,  0x08, 	/* 506E0 */
+	0x08,  0x14,  0x48,  0x12,  0x48,  0x21,  0x48,  0x7E,  0x48,  0x08,  0x48,  0x08,  0x48,  0x7F,  0x48,  0x08, 	/* 506F0 */
+	0x44,  0x4A,  0x84,  0x2C,  0x84,  0x28,  0x84,  0x0F,  0x02,  0x19,  0x02,  0x62,  0x01,  0xA1,  0x04,  0x20, 	/* 50700 */
+	0x04,  0x90,  0x04,  0x88,  0x09,  0x44,  0x12,  0x24,  0x04,  0x10,  0x18,  0x0C,  0x67,  0xF3,  0x00,  0x80, 	/* 50710 */
+	0x00,  0x80,  0x3F,  0xFE,  0x08,  0x88,  0x04,  0x88,  0x04,  0x90,  0x7F,  0xFF,  0x00,  0x00,  0xA3,  0x04, 	/* 50720 */
+	0x20,  0x04,  0x20,  0x0C,  0x20,  0x0A,  0x3E,  0x11,  0x42,  0x3F,  0x42,  0x44,  0x42,  0x04,  0xA2,  0x7F, 	/* 50730 */
+	0x12,  0x04,  0x12,  0x25,  0x12,  0x16,  0x02,  0x14,  0x02,  0x07,  0x02,  0x18,  0x04,  0x60,  0x18,  0xA6, 	/* 50740 */
+	0x04,  0x00,  0x04,  0x00,  0x0A,  0x7E,  0x09,  0x42,  0x10,  0xC2,  0x3F,  0x42,  0x44,  0x42,  0x04,  0x42, 	/* 50750 */
+	0x7F,  0xC2,  0x04,  0x42,  0x25,  0x42,  0x16,  0x42,  0x14,  0xC2,  0x07,  0x7E,  0x1C,  0x00,  0x60,  0x00, 	/* 50760 */
+	0xA7,  0x08,  0x02,  0x08,  0x52,  0x14,  0x52,  0x12,  0x52,  0x21,  0x52,  0x7E,  0x52,  0x08,  0x52,  0x08, 	/* 50770 */
+	0x52,  0x7F,  0x52,  0x08,  0x52,  0x4A,  0x52,  0x2C,  0x52,  0x28,  0x92,  0x0E,  0x82,  0x19,  0x02,  0x62, 	/* 50780 */
+	0x02,  0xB5,  0x08,  0x00,  0x09,  0xFC,  0x14,  0x84,  0x12,  0xA4,  0x21,  0x94,  0x7E,  0x54,  0x08,  0x44, 	/* 50790 */
+	0x08,  0x48,  0x7F,  0x28,  0x08,  0x30,  0x4A,  0x10,  0x2C,  0x28,  0x28,  0x28,  0x0E,  0x44,  0x18,  0x82, 	/* 507A0 */
+	0x63,  0x01,  0xB6,  0x08,  0x10,  0x08,  0x10,  0x14,  0x50,  0x12,  0x52,  0x21,  0x5E,  0x7E,  0x72,  0x09, 	/* 507B0 */
+	0xD2,  0x08,  0x52,  0x7F,  0x52,  0x08,  0x5C,  0x4A,  0x50,  0x2C,  0x51,  0x29,  0x41,  0x0E,  0x41,  0x18, 	/* 507C0 */
+	0x3F,  0x60,  0x00,  0xBC,  0x04,  0x00,  0x04,  0xFE,  0x0A,  0x12,  0x09,  0x12,  0x10,  0x12,  0x3F,  0x52, 	/* 507D0 */
+	0x44,  0x32,  0x04,  0x12,  0x7F,  0x1A,  0x04,  0x16,  0x25,  0x13,  0x16,  0x22,  0x14,  0x22,  0x07,  0x42, 	/* 507E0 */
+	0x18,  0x82,  0x61,  0x0C,  0xBF,  0x04,  0x04,  0x04,  0x18,  0x0A,  0x60,  0x09,  0x40,  0x10,  0xC0,  0x3F, 	/* 507F0 */
+	0x7F,  0x44,  0x44,  0x04,  0x44,  0x3F,  0x44,  0x04,  0x44,  0x25,  0x44,  0x16,  0x44,  0x14,  0x84,  0x06, 	/* 50800 */
+	0x84,  0x19,  0x04,  0x60,  0x04,  0x8D,  0x08,  0x20,  0x08,  0x22,  0x14,  0x2C,  0x13,  0xF0,  0x22,  0x20, 	/* 50810 */
+	0x7E,  0xA4,  0x08,  0xA4,  0x08,  0xA4,  0x7E,  0xA4,  0x08,  0xA4,  0x4A,  0xFC,  0x2C,  0x20,  0x28,  0x20, 	/* 50820 */
+	0x0E,  0x21,  0x18,  0x11,  0x60,  0x0F,  0x8E,  0x08,  0x20,  0x08,  0x20,  0x14,  0x20,  0x12,  0x3E,  0x21, 	/* 50830 */
+	0x42,  0x7E,  0x62,  0x08,  0xA2,  0x09,  0x22,  0x7F,  0x32,  0x08,  0x4A,  0x4A,  0x7A,  0x2C,  0xCA,  0x28, 	/* 50840 */
+	0x02,  0x0B,  0x02,  0x1C,  0x04,  0x60,  0x18,  0x91,  0x08,  0x00,  0x08,  0x7F,  0x14,  0x40,  0x12,  0x40, 	/* 50850 */
+	0x21,  0x40,  0x7E,  0x7E,  0x08,  0x42,  0x08,  0x52,  0x7E,  0x52,  0x08,  0x54,  0x4A,  0x4C,  0x2A,  0x48, 	/* 50860 */
+	0x28,  0x8C,  0x0E,  0x94,  0x19,  0x22,  0x62,  0xC1,  0x94,  0x08,  0x10,  0x08,  0x10,  0x14,  0x10,  0x12, 	/* 50870 */
+	0x54,  0x21,  0x52,  0x7F,  0x52,  0x08,  0x51,  0x08,  0x51,  0x7E,  0x94,  0x09,  0x14,  0x4A,  0x34,  0x2C, 	/* 50880 */
+	0x08,  0x28,  0x08,  0x0E,  0x10,  0x18,  0x60,  0x61,  0x80,  0x95,  0x08,  0x00,  0x08,  0xFC,  0x14,  0x24, 	/* 50890 */
+	0x12,  0x24,  0x21,  0x24,  0x7E,  0x24,  0x08,  0x24,  0x08,  0xFF,  0x7F,  0x24,  0x08,  0x24,  0x4A,  0x24, 	/* 508A0 */
+	0x2C,  0x24,  0x28,  0x24,  0x0E,  0x24,  0x19,  0xFF,  0x60,  0x00,  0x9E,  0x08,  0x40,  0x08,  0x40,  0x14, 	/* 508B0 */
+	0x40,  0x12,  0x7E,  0x21,  0x82,  0x7E,  0x82,  0x09,  0x02,  0x08,  0x7A,  0x7F,  0x02,  0x08,  0x0A,  0x4A, 	/* 508C0 */
+	0x12,  0x2C,  0x62,  0x28,  0x02,  0x0E,  0x02,  0x18,  0x04,  0x60,  0x18,  0xA9,  0x08,  0x00,  0x08,  0xFF, 	/* 508D0 */
+	0x14,  0x00,  0x12,  0x00,  0x21,  0x7E,  0x3E,  0x42,  0x48,  0x42,  0x08,  0x42,  0x7F,  0x7E,  0x08,  0x40, 	/* 508E0 */
+	0x4A,  0x40,  0x2C,  0x40,  0x28,  0x40,  0x0E,  0x80,  0x18,  0x80,  0x61,  0x00,  0xAC,  0x08,  0x00,  0x08, 	/* 508F0 */
+	0x7E,  0x14,  0x42,  0x12,  0x42,  0x21,  0x42,  0x7E,  0x42,  0x08,  0x7E,  0x08,  0x48,  0x7F,  0x48,  0x08, 	/* 50900 */
+	0x48,  0x4A,  0x48,  0x2C,  0x44,  0x28,  0x84,  0x0E,  0x84,  0x19,  0x02,  0x62,  0x01,  0xB4,  0x08,  0x10, 	/* 50910 */
+	0x08,  0x10,  0x14,  0x28,  0x12,  0x44,  0x21,  0x82,  0x7F,  0x7D,  0x08,  0x00,  0x08,  0x00,  0x7F,  0xFC, 	/* 50920 */
+	0x08,  0x24,  0x4A,  0x24,  0x2C,  0x24,  0x28,  0x24,  0x0E,  0x38,  0x18,  0x20,  0x60,  0x20,  0xB7,  0x08, 	/* 50930 */
+	0x10,  0x08,  0x10,  0x14,  0x10,  0x12,  0x10,  0x21,  0xFF,  0x7E,  0x10,  0x08,  0x10,  0x08,  0x10,  0x7F, 	/* 50940 */
+	0x10,  0x08,  0xFC,  0x4A,  0x84,  0x2C,  0x84,  0x28,  0x84,  0x0F,  0x84,  0x18,  0xFC,  0x60,  0x00,  0xBF, 	/* 50950 */
+	0x08,  0x00,  0x08,  0xFE,  0x14,  0x92,  0x12,  0x92,  0x21,  0x92,  0x7E,  0x92,  0x08,  0x92,  0x08,  0xFE, 	/* 50960 */
+	0x7E,  0x92,  0x08,  0x92,  0x4A,  0x92,  0x2C,  0x92,  0x28,  0x92,  0x0E,  0x92,  0x18,  0xFE,  0x60,  0x00, 	/* 50970 */
+	0x84,  0x08,  0x10,  0x08,  0x50,  0x14,  0x50,  0x12,  0x7E,  0x21,  0x90,  0x7E,  0x90,  0x09,  0x10,  0x08, 	/* 50980 */
+	0xFF,  0x7F,  0x10,  0x08,  0x10,  0x4A,  0x18,  0x2C,  0x28,  0x28,  0x24,  0x0E,  0x44,  0x18,  0x82,  0x63, 	/* 50990 */
+	0x01,  0x85,  0x08,  0x00,  0x08,  0xFF,  0x14,  0x40,  0x12,  0x40,  0x21,  0x40,  0x7E,  0x7E,  0x08,  0x42, 	/* 509A0 */
+	0x08,  0x42,  0x7F,  0x42,  0x08,  0x7E,  0x4A,  0x40,  0x2C,  0x40,  0x28,  0x40,  0x0E,  0x40,  0x19,  0xFF, 	/* 509B0 */
+	0x60,  0x00,  0x88,  0x08,  0x10,  0x08,  0x10,  0x14,  0x10,  0x12,  0xFF,  0x21,  0x81,  0x7E,  0x81,  0x08, 	/* 509C0 */
+	0x44,  0x08,  0x44,  0x7F,  0x48,  0x08,  0x50,  0x4A,  0x60,  0x2C,  0x40,  0x28,  0x41,  0x0E,  0x41,  0x18, 	/* 509D0 */
+	0x3F,  0x60,  0x00,  0x89,  0x08,  0x10,  0x08,  0x10,  0x14,  0x10,  0x13,  0xFF,  0x21,  0x10,  0x7E,  0x10, 	/* 509E0 */
+	0x08,  0x24,  0x08,  0xC4,  0x7E,  0x28,  0x08,  0x28,  0x4A,  0x10,  0x2C,  0x14,  0x28,  0x22,  0x0E,  0x4E, 	/* 509F0 */
+	0x19,  0xF1,  0x60,  0x01,  0x8B,  0x08,  0x40,  0x08,  0x40,  0x14,  0x7E,  0x12,  0x82,  0x21,  0x02,  0x7E, 	/* 50A00 */
+	0xF2,  0x08,  0x92,  0x08,  0x92,  0x7F,  0x92,  0x08,  0xF2,  0x4A,  0x9C,  0x2C,  0x80,  0x28,  0x80,  0x0B, 	/* 50A10 */
+	0x82,  0x1C,  0x42,  0x60,  0x3E,  0x90,  0x08,  0x00,  0x09,  0xFF,  0x14,  0x10,  0x12,  0x10,  0x21,  0x10, 	/* 50A20 */
+	0x7E,  0x20,  0x08,  0x20,  0x08,  0x7E,  0x7F,  0x62,  0x08,  0xA2,  0x4A,  0x22,  0x2C,  0x22,  0x28,  0x22, 	/* 50A30 */
+	0x0E,  0x22,  0x18,  0x3E,  0x60,  0x00,  0x97,  0x08,  0x44,  0x08,  0x44,  0x14,  0x44,  0x13,  0xFF,  0x21, 	/* 50A40 */
+	0x44,  0x7E,  0x44,  0x08,  0x44,  0x08,  0x44,  0x7F,  0x44,  0x08,  0x7C,  0x4A,  0x44,  0x2C,  0x44,  0x28, 	/* 50A50 */
+	0x44,  0x0E,  0x44,  0x18,  0x7C,  0x60,  0x00,  0x9A,  0x08,  0x20,  0x08,  0x20,  0x14,  0xCE,  0x12,  0xAA, 	/* 50A60 */
+	0x21,  0xAA,  0x7E,  0xAA,  0x08,  0xAA,  0x08,  0xAA,  0x7E,  0xAA,  0x08,  0xAA,  0x4A,  0xAA,  0x2C,  0xEA, 	/* 50A70 */
+	0x29,  0xAC,  0x0E,  0x48,  0x18,  0x48,  0x60,  0x88,  0x9B,  0x08,  0x3C,  0x08,  0x04,  0x14,  0x24,  0x12, 	/* 50A80 */
+	0x24,  0x22,  0x44,  0x7F,  0x42,  0x08,  0x82,  0x09,  0x01,  0x7E,  0x7C,  0x08,  0x44,  0x4A,  0x44,  0x2C, 	/* 50A90 */
+	0x44,  0x29,  0x44,  0x0E,  0x44,  0x18,  0x7C,  0x60,  0x00,  0x9E,  0x08,  0x10,  0x08,  0x14,  0x14,  0x12, 	/* 50AA0 */
+	0x12,  0x10,  0x21,  0xFF,  0x7E,  0x90,  0x08,  0x92,  0x08,  0x92,  0x7E,  0x92,  0x08,  0x94,  0x4A,  0x8C, 	/* 50AB0 */
+	0x2C,  0x88,  0x28,  0xED,  0x0D,  0x95,  0x1A,  0x23,  0x60,  0x41,  0xA2,  0x08,  0x10,  0x08,  0x10,  0x14, 	/* 50AC0 */
+	0x10,  0x12,  0x10,  0x21,  0xFF,  0x7E,  0x38,  0x08,  0x38,  0x08,  0x54,  0x7F,  0x54,  0x08,  0x92,  0x4A, 	/* 50AD0 */
+	0x91,  0x2D,  0x7C,  0x28,  0x10,  0x0E,  0x10,  0x18,  0x10,  0x60,  0x10,  0xA4,  0x08,  0x40,  0x08,  0x40, 	/* 50AE0 */
+	0x14,  0x40,  0x12,  0x7E,  0x21,  0x82,  0x7E,  0x82,  0x09,  0x7A,  0x08,  0x4A,  0x7F,  0x4A,  0x08,  0x4A, 	/* 50AF0 */
+	0x4A,  0x4A,  0x2C,  0x7A,  0x28,  0x02,  0x0E,  0x02,  0x18,  0x02,  0x60,  0x0C,  0xA6,  0x08,  0x00,  0x08, 	/* 50B00 */
+	0xFE,  0x14,  0x10,  0x12,  0x10,  0x21,  0x10,  0x7E,  0x50,  0x08,  0x50,  0x08,  0x5E,  0x7F,  0x50,  0x08, 	/* 50B10 */
+	0x50,  0x4A,  0x50,  0x2C,  0x50,  0x28,  0x50,  0x0E,  0x50,  0x1B,  0xFF,  0x60,  0x00,  0xB1,  0x08,  0x10, 	/* 50B20 */
+	0x08,  0x10,  0x14,  0x10,  0x12,  0x7F,  0x21,  0x40,  0x7E,  0x48,  0x08,  0x48,  0x08,  0x48,  0x7F,  0x48, 	/* 50B30 */
+	0x08,  0x48,  0x4A,  0x50,  0x2C,  0x54,  0x29,  0x92,  0x0E,  0xAE,  0x19,  0x71,  0x62,  0x01,  0xBE,  0x08, 	/* 50B40 */
+	0x10,  0x08,  0x10,  0x14,  0x28,  0x12,  0x44,  0x21,  0xFE,  0x7E,  0x02,  0x08,  0x50,  0x08,  0x50,  0x7E, 	/* 50B50 */
+	0xFE,  0x09,  0x10,  0x4A,  0x10,  0x2D,  0xFF,  0x28,  0x10,  0x0E,  0x10,  0x18,  0x10,  0x60,  0x10,  0x80, 	/* 50B60 */
+	0x04,  0x00,  0x04,  0x7C,  0x0C,  0x44,  0x0A,  0x44,  0x11,  0x7C,  0x3F,  0xC4,  0x44,  0x44,  0x04,  0x7C, 	/* 50B70 */
+	0x7F,  0x52,  0x04,  0x52,  0x25,  0x54,  0x16,  0x48,  0x14,  0x48,  0x07,  0x54,  0x18,  0x62,  0x61,  0x81, 	/* 50B80 */
+	0x83,  0x08,  0x20,  0x08,  0x20,  0x14,  0x20,  0x13,  0xFF,  0x21,  0x20,  0x7E,  0x50,  0x08,  0x8C,  0x09, 	/* 50B90 */
+	0xFA,  0x7F,  0x50,  0x08,  0x50,  0x4A,  0x50,  0x2C,  0x50,  0x28,  0x92,  0x0E,  0x92,  0x19,  0x12,  0x62, 	/* 50BA0 */
+	0x0E,  0x85,  0x08,  0x00,  0x08,  0xFE,  0x14,  0x82,  0x12,  0x82,  0x20,  0xFE,  0x7E,  0x82,  0x08,  0x82, 	/* 50BB0 */
+	0x08,  0xBA,  0x7F,  0xAA,  0x08,  0xAA,  0x4A,  0xAA,  0x2A,  0xBA,  0x2C,  0x82,  0x0E,  0x82,  0x18,  0x82, 	/* 50BC0 */
+	0x60,  0x86,  0x91,  0x08,  0x10,  0x08,  0x50,  0x14,  0x50,  0x12,  0x7E,  0x21,  0x90,  0x7E,  0x90,  0x09, 	/* 50BD0 */
+	0x10,  0x08,  0xFF,  0x7F,  0x28,  0x08,  0x28,  0x4A,  0x28,  0x2C,  0x48,  0x28,  0x49,  0x0E,  0x89,  0x19, 	/* 50BE0 */
+	0x09,  0x62,  0x07,  0x93,  0x08,  0x10,  0x08,  0x10,  0x14,  0x28,  0x12,  0x44,  0x21,  0x82,  0x7F,  0x01, 	/* 50BF0 */
+	0x08,  0xFE,  0x08,  0x10,  0x7F,  0x10,  0x08,  0x10,  0x4A,  0x7C,  0x2C,  0x10,  0x28,  0x10,  0x0E,  0x10, 	/* 50C00 */
+	0x19,  0xFF,  0x60,  0x00,  0x95,  0x08,  0x10,  0x08,  0x10,  0x15,  0xFF,  0x12,  0x10,  0x21,  0xFE,  0x7E, 	/* 50C10 */
+	0x12,  0x08,  0x12,  0x08,  0xFE,  0x7F,  0x90,  0x08,  0xFF,  0x4A,  0x11,  0x2C,  0x29,  0x28,  0x2E,  0x0E, 	/* 50C20 */
+	0x44,  0x19,  0x82,  0x66,  0x01,  0x96,  0x08,  0x10,  0x08,  0x50,  0x14,  0x50,  0x12,  0x7E,  0x21,  0x50, 	/* 50C30 */
+	0x7E,  0x90,  0x08,  0x10,  0x09,  0xFF,  0x7E,  0x38,  0x08,  0x38,  0x4A,  0x54,  0x2C,  0x54,  0x28,  0x92, 	/* 50C40 */
+	0x0F,  0x11,  0x18,  0x10,  0x60,  0x10,  0x98,  0x08,  0x20,  0x08,  0x20,  0x14,  0x3C,  0x12,  0x44,  0x20, 	/* 50C50 */
+	0x44,  0x7F,  0xC8,  0x09,  0x28,  0x08,  0x10,  0x7E,  0x20,  0x08,  0x7E,  0x4A,  0xC2,  0x2D,  0x42,  0x28, 	/* 50C60 */
+	0x42,  0x0E,  0x42,  0x18,  0x7E,  0x60,  0x00,  0x9A,  0x08,  0x28,  0x08,  0x28,  0x14,  0x2A,  0x12,  0xAA, 	/* 50C70 */
+	0x21,  0x6C,  0x7E,  0x68,  0x08,  0x28,  0x08,  0x28,  0x7F,  0x6C,  0x08,  0xAA,  0x4B,  0x29,  0x2C,  0x28, 	/* 50C80 */
+	0x28,  0x48,  0x0E,  0x49,  0x18,  0x89,  0x63,  0x07,  0x9B,  0x08,  0x02,  0x08,  0x0C,  0x14,  0xF0,  0x12, 	/* 50C90 */
+	0x10,  0x21,  0x10,  0x7E,  0x10,  0x09,  0xFF,  0x08,  0x10,  0x7F,  0x10,  0x08,  0x10,  0x4A,  0x7E,  0x2C, 	/* 50CA0 */
+	0x42,  0x28,  0x42,  0x0E,  0x42,  0x18,  0x7E,  0x60,  0x00,  0x9C,  0x08,  0x80,  0x08,  0x8F,  0x11,  0x40, 	/* 50CB0 */
+	0x11,  0x20,  0x22,  0x10,  0x4B,  0xE0,  0x0C,  0x9F,  0x10,  0x84,  0x17,  0xF4,  0x30,  0x84,  0x54,  0xA4, 	/* 50CC0 */
+	0x12,  0xC4,  0x12,  0xE4,  0x11,  0x84,  0x16,  0x04,  0x10,  0x0C,  0xAD,  0x08,  0x28,  0x08,  0x24,  0x14, 	/* 50CD0 */
+	0x20,  0x12,  0x3E,  0x21,  0xE0,  0x7E,  0x3E,  0x09,  0xE0,  0x08,  0x2F,  0x7E,  0x34,  0x09,  0xE4,  0x4A, 	/* 50CE0 */
+	0x18,  0x2C,  0x10,  0x29,  0x1A,  0x0E,  0x2A,  0x18,  0xC6,  0x63,  0x02,  0xB7,  0x04,  0x10,  0x04,  0x54, 	/* 50CF0 */
+	0x0A,  0x52,  0x09,  0x52,  0x10,  0x91,  0x3F,  0x7F,  0x44,  0x42,  0x04,  0x42,  0x3F,  0x7E,  0x04,  0x42, 	/* 50D00 */
+	0x25,  0x42,  0x16,  0x7E,  0x14,  0x42,  0x07,  0x42,  0x1C,  0x42,  0x60,  0x46,  0xB9,  0x08,  0x04,  0x08, 	/* 50D10 */
+	0x18,  0x14,  0xF0,  0x12,  0x10,  0x21,  0xFF,  0x7E,  0x38,  0x08,  0x54,  0x09,  0x93,  0x7E,  0x10,  0x08, 	/* 50D20 */
+	0xF8,  0x4A,  0x28,  0x2C,  0x2E,  0x28,  0x22,  0x0E,  0x42,  0x18,  0x82,  0x61,  0x0C,  0x8F,  0x08,  0x10, 	/* 50D30 */
+	0x08,  0x10,  0x15,  0xFF,  0x12,  0x10,  0x21,  0x54,  0x7E,  0x54,  0x08,  0x54,  0x08,  0xB6,  0x7E,  0x99, 	/* 50D40 */
+	0x09,  0x10,  0x4A,  0x28,  0x2C,  0x28,  0x28,  0x24,  0x0E,  0x44,  0x18,  0x82,  0x61,  0x01,  0x92,  0x08, 	/* 50D50 */
+	0x20,  0x08,  0x3C,  0x14,  0x24,  0x12,  0x48,  0x21,  0xB0,  0x7E,  0x18,  0x08,  0x64,  0x09,  0x93,  0x7E, 	/* 50D60 */
+	0xFE,  0x08,  0x10,  0x4A,  0x7C,  0x2C,  0x10,  0x29,  0xFF,  0x0E,  0x10,  0x18,  0x10,  0x60,  0x10,  0xA4, 	/* 50D70 */
+	0x08,  0x08,  0x09,  0xC8,  0x15,  0x48,  0x13,  0x48,  0x21,  0x7E,  0x7F,  0xCA,  0x09,  0x4A,  0x09,  0x4A, 	/* 50D80 */
+	0x7F,  0x4A,  0x09,  0xCA,  0x4B,  0x4A,  0x2D,  0x4A,  0x29,  0xF2,  0x0F,  0x12,  0x18,  0x22,  0x60,  0x4C, 	/* 50D90 */
+	0xA9,  0x08,  0x44,  0x08,  0x44,  0x15,  0xFF,  0x12,  0x44,  0x21,  0x44,  0x7E,  0x10,  0x08,  0x10,  0x09, 	/* 50DA0 */
+	0xFF,  0x7F,  0x40,  0x08,  0x40,  0x4A,  0x40,  0x2C,  0x40,  0x28,  0x40,  0x0E,  0x40,  0x18,  0x3E,  0x60, 	/* 50DB0 */
+	0x00,  0xAA,  0x08,  0x14,  0x08,  0x12,  0x15,  0xFF,  0x12,  0x10,  0x21,  0x10,  0x7E,  0xFE,  0x08,  0x92, 	/* 50DC0 */
+	0x08,  0x92,  0x7F,  0xFE,  0x08,  0x92,  0x4A,  0x92,  0x2C,  0xFE,  0x28,  0x92,  0x0F,  0x92,  0x18,  0x92, 	/* 50DD0 */
+	0x60,  0x96,  0xAD,  0x08,  0x44,  0x08,  0x24,  0x14,  0x28,  0x12,  0x7E,  0x21,  0x42,  0x7E,  0x42,  0x08, 	/* 50DE0 */
+	0x42,  0x08,  0x42,  0x7F,  0x7E,  0x08,  0x28,  0x4A,  0x28,  0x2A,  0x28,  0x2C,  0x48,  0x0B,  0x49,  0x1C, 	/* 50DF0 */
+	0x89,  0x61,  0x07,  0xB2,  0x08,  0x08,  0x08,  0x10,  0x14,  0x60,  0x12,  0x40,  0x21,  0x40,  0x7E,  0x7E, 	/* 50E00 */
+	0x08,  0x44,  0x08,  0x44,  0x7F,  0x44,  0x08,  0x44,  0x4B,  0xFF,  0x2C,  0x00,  0x28,  0x48,  0x0E,  0x44, 	/* 50E10 */
+	0x18,  0x82,  0x61,  0x02,  0xB3,  0x08,  0x20,  0x08,  0x20,  0x14,  0xFE,  0x12,  0x20,  0x20,  0xFC,  0x7E, 	/* 50E20 */
+	0x20,  0x09,  0xFF,  0x08,  0x24,  0x7E,  0x24,  0x09,  0xFF,  0x4A,  0x44,  0x2C,  0x44,  0x28,  0xA4,  0x0F, 	/* 50E30 */
+	0x24,  0x1A,  0x04,  0x60,  0x0C,  0xB8,  0x08,  0x00,  0x08,  0xFE,  0x14,  0x82,  0x12,  0x82,  0x20,  0xFE, 	/* 50E40 */
+	0x7E,  0x88,  0x08,  0x88,  0x08,  0xFF,  0x7F,  0x88,  0x08,  0x88,  0x4A,  0xBE,  0x2C,  0xA2,  0x28,  0xA2, 	/* 50E50 */
+	0x0F,  0x22,  0x19,  0x3E,  0x62,  0x00,  0xBA,  0x08,  0x10,  0x08,  0x10,  0x15,  0xFF,  0x13,  0x01,  0x21, 	/* 50E60 */
+	0x01,  0x7E,  0x80,  0x08,  0xEE,  0x08,  0xAA,  0x7E,  0xAA,  0x09,  0x2A,  0x4A,  0xAE,  0x2C,  0x48,  0x28, 	/* 50E70 */
+	0x48,  0x0E,  0x49,  0x18,  0x89,  0x61,  0x07,  0xBC,  0x08,  0x00,  0x08,  0xFE,  0x14,  0x82,  0x12,  0xCA, 	/* 50E80 */
+	0x21,  0xAA,  0x7E,  0x92,  0x08,  0xFE,  0x08,  0x92,  0x7F,  0x92,  0x08,  0xD6,  0x4A,  0xD6,  0x2C,  0xFE, 	/* 50E90 */
+	0x29,  0x82,  0x0E,  0x82,  0x18,  0x82,  0x60,  0x86,  0x86,  0x08,  0x20,  0x08,  0x20,  0x17,  0xFE,  0x12, 	/* 50EA0 */
+	0x20,  0x22,  0xFC,  0x7E,  0x20,  0x09,  0xFF,  0x08,  0x00,  0x7F,  0xFC,  0x08,  0x84,  0x4A,  0xFC,  0x2A, 	/* 50EB0 */
+	0x84,  0x2C,  0xFC,  0x0E,  0x84,  0x18,  0x84,  0x60,  0x8C,  0x8F,  0x08,  0x00,  0x0D,  0xFE,  0x16,  0x28, 	/* 50EC0 */
+	0x12,  0x28,  0x20,  0x28,  0x7E,  0xEE,  0x08,  0x82,  0x08,  0x82,  0x7E,  0x82,  0x08,  0xEE,  0x4A,  0x28, 	/* 50ED0 */
+	0x2C,  0x28,  0x28,  0x28,  0x0E,  0x28,  0x1B,  0xFF,  0x60,  0x00,  0x90,  0x08,  0x24,  0x08,  0x24,  0x14, 	/* 50EE0 */
+	0x48,  0x12,  0xFF,  0x21,  0x48,  0x7E,  0x48,  0x08,  0x48,  0x08,  0x7E,  0x7F,  0x48,  0x08,  0x48,  0x4A, 	/* 50EF0 */
+	0x7E,  0x2C,  0x48,  0x28,  0x48,  0x0E,  0x48,  0x18,  0x7F,  0x60,  0x00,  0x98,  0x08,  0x04,  0x08,  0x18, 	/* 50F00 */
+	0x14,  0xF0,  0x12,  0x10,  0x21,  0xFE,  0x7E,  0x54,  0x08,  0x54,  0x09,  0xFF,  0x7E,  0x54,  0x08,  0x54, 	/* 50F10 */
+	0x4A,  0x54,  0x2C,  0xFE,  0x28,  0x10,  0x0E,  0x10,  0x19,  0xFF,  0x60,  0x00,  0x99,  0x08,  0x49,  0x08, 	/* 50F20 */
+	0x49,  0x14,  0x92,  0x13,  0xB6,  0x23,  0x49,  0x7E,  0x49,  0x08,  0x00,  0x08,  0xFE,  0x7E,  0x92,  0x08, 	/* 50F30 */
+	0x92,  0x4A,  0xFE,  0x2C,  0x92,  0x28,  0x92,  0x0E,  0x92,  0x18,  0xFE,  0x60,  0x00,  0x9A,  0x08,  0x04, 	/* 50F40 */
+	0x08,  0x18,  0x14,  0xE4,  0x12,  0x52,  0x20,  0x89,  0x7F,  0x7E,  0x08,  0x12,  0x08,  0x12,  0x7F,  0xFF, 	/* 50F50 */
+	0x08,  0x12,  0x4A,  0x12,  0x2C,  0xFE,  0x28,  0x10,  0x0E,  0x10,  0x18,  0x10,  0x60,  0x30,  0xA0,  0x08, 	/* 50F60 */
+	0x10,  0x08,  0x10,  0x15,  0xFF,  0x13,  0x01,  0x21,  0x01,  0x7E,  0xFE,  0x08,  0x10,  0x08,  0x10,  0x7F, 	/* 50F70 */
+	0x90,  0x08,  0x9E,  0x4A,  0x90,  0x2C,  0x90,  0x28,  0xD0,  0x0E,  0xB0,  0x19,  0x18,  0x62,  0x07,  0xA2, 	/* 50F80 */
+	0x08,  0x28,  0x08,  0x24,  0x14,  0x2E,  0x13,  0xF2,  0x20,  0x14,  0x7E,  0x18,  0x08,  0x65,  0x09,  0xAB, 	/* 50F90 */
+	0x7E,  0x24,  0x08,  0x2F,  0x4B,  0xF2,  0x2C,  0x14,  0x28,  0x18,  0x0E,  0x65,  0x19,  0x83,  0x60,  0x01, 	/* 50FA0 */
+	0xA3,  0x08,  0x00,  0x09,  0xFE,  0x14,  0x22,  0x12,  0xAA,  0x20,  0x44,  0x7E,  0xAA,  0x09,  0x10,  0x08, 	/* 50FB0 */
+	0x00,  0x7F,  0xFE,  0x08,  0x22,  0x4A,  0xAA,  0x2C,  0xCC,  0x28,  0x44,  0x0E,  0xAC,  0x19,  0x12,  0x62, 	/* 50FC0 */
+	0x21,  0xA6,  0x04,  0x10,  0x04,  0x20,  0x0C,  0x7C,  0x0A,  0x44,  0x11,  0x7C,  0x3F,  0x44,  0x44,  0x44, 	/* 50FD0 */
+	0x04,  0x7C,  0x7F,  0x10,  0x04,  0xFE,  0x25,  0x92,  0x16,  0x92,  0x14,  0x92,  0x07,  0x9C,  0x18,  0x90, 	/* 50FE0 */
+	0x60,  0x10,  0xA8,  0x08,  0x44,  0x08,  0x44,  0x15,  0xFF,  0x12,  0x44,  0x21,  0x44,  0x7E,  0x00,  0x08, 	/* 50FF0 */
+	0x00,  0x08,  0xFE,  0x7F,  0x92,  0x08,  0x92,  0x4A,  0xFE,  0x2C,  0x92,  0x28,  0x92,  0x0E,  0x92,  0x18, 	/* 51000 */
+	0xFE,  0x60,  0x00,  0xAB,  0x08,  0x00,  0x08,  0xFC,  0x14,  0x84,  0x12,  0x84,  0x21,  0xFC,  0x7E,  0x84, 	/* 51010 */
+	0x08,  0x84,  0x08,  0xFC,  0x7F,  0x20,  0x08,  0x7E,  0x4A,  0xAA,  0x2D,  0x2A,  0x28,  0x4A,  0x0E,  0x92, 	/* 51020 */
+	0x18,  0x22,  0x60,  0x4C,  0xAC,  0x08,  0x10,  0x08,  0x10,  0x15,  0xFF,  0x12,  0x10,  0x20,  0xFE,  0x7E, 	/* 51030 */
+	0x92,  0x08,  0xFE,  0x08,  0x92,  0x7F,  0x92,  0x08,  0xFE,  0x4A,  0x38,  0x2C,  0x34,  0x28,  0x52,  0x0E, 	/* 51040 */
+	0x91,  0x19,  0x10,  0x60,  0x10,  0xAE,  0x08,  0x00,  0x08,  0xFE,  0x14,  0x92,  0x12,  0x92,  0x21,  0x92, 	/* 51050 */
+	0x7E,  0xFE,  0x08,  0x92,  0x08,  0x92,  0x7F,  0xBA,  0x08,  0xAA,  0x4A,  0xAA,  0x2C,  0xBA,  0x28,  0x82, 	/* 51060 */
+	0x0E,  0x82,  0x18,  0xFE,  0x60,  0x00,  0xAF,  0x08,  0x28,  0x08,  0x28,  0x14,  0x28,  0x12,  0xFE,  0x21, 	/* 51070 */
+	0x28,  0x7E,  0x28,  0x09,  0xFF,  0x08,  0x00,  0x7F,  0x7C,  0x08,  0x44,  0x4A,  0x44,  0x2C,  0x7C,  0x29, 	/* 51080 */
+	0x44,  0x0E,  0x44,  0x18,  0x7C,  0x60,  0x00,  0xB2,  0x04,  0x00,  0x04,  0xFC,  0x0C,  0x04,  0x0A,  0xFC, 	/* 51090 */
+	0x11,  0x04,  0x3F,  0x04,  0x44,  0xFF,  0x04,  0x12,  0x7F,  0x92,  0x04,  0x5C,  0x25,  0x38,  0x16,  0x34, 	/* 510A0 */
+	0x14,  0xD2,  0x07,  0x11,  0x18,  0x10,  0x60,  0x30,  0xB5,  0x08,  0x44,  0x08,  0x44,  0x15,  0xFF,  0x12, 	/* 510B0 */
+	0x44,  0x21,  0x44,  0x7E,  0x28,  0x08,  0x28,  0x08,  0x4A,  0x7E,  0x4A,  0x08,  0xCC,  0x4B,  0x48,  0x2C, 	/* 510C0 */
+	0x48,  0x28,  0x48,  0x0E,  0x49,  0x18,  0x49,  0x60,  0x47,  0xBA,  0x08,  0x44,  0x08,  0x44,  0x17,  0xFF, 	/* 510D0 */
+	0x12,  0x44,  0x21,  0x54,  0x7E,  0x10,  0x09,  0xFF,  0x08,  0x20,  0x7F,  0x20,  0x08,  0x3C,  0x4A,  0x24, 	/* 510E0 */
+	0x2C,  0x24,  0x28,  0x44,  0x0E,  0x44,  0x18,  0x84,  0x61,  0x18,  0xBB,  0x08,  0x08,  0x08,  0x0C,  0x14, 	/* 510F0 */
+	0xEA,  0x12,  0x08,  0x21,  0xFF,  0x7E,  0x08,  0x08,  0x28,  0x08,  0xA8,  0x7E,  0xB8,  0x08,  0xA8,  0x4A, 	/* 51100 */
+	0xA8,  0x2C,  0xA4,  0x28,  0xBD,  0x0E,  0xE5,  0x19,  0x83,  0x60,  0x01,  0x84,  0x08,  0x10,  0x08,  0x10, 	/* 51110 */
+	0x14,  0x10,  0x12,  0xFF,  0x21,  0x00,  0x7E,  0x7C,  0x08,  0x44,  0x08,  0x44,  0x7F,  0x44,  0x08,  0x7C, 	/* 51120 */
+	0x4A,  0x10,  0x2C,  0x58,  0x28,  0x54,  0x0E,  0x92,  0x19,  0x12,  0x60,  0x30,  0x8B,  0x08,  0x00,  0x08, 	/* 51130 */
+	0xFC,  0x14,  0x84,  0x12,  0xBC,  0x22,  0xA4,  0x7E,  0xA4,  0x08,  0xA4,  0x09,  0xFE,  0x7F,  0x02,  0x09, 	/* 51140 */
+	0x7A,  0x4B,  0x4A,  0x2D,  0x4A,  0x29,  0x7A,  0x0F,  0x02,  0x19,  0x02,  0x61,  0x06,  0x8D,  0x08,  0x10, 	/* 51150 */
+	0x08,  0x10,  0x14,  0xFF,  0x12,  0xA4,  0x20,  0xA4,  0x7E,  0xFF,  0x08,  0xA4,  0x08,  0xBC,  0x7F,  0x80, 	/* 51160 */
+	0x08,  0xFE,  0x4A,  0xA4,  0x2C,  0x94,  0x28,  0x88,  0x0F,  0x14,  0x19,  0x22,  0x62,  0xC1,  0x94,  0x08, 	/* 51170 */
+	0x00,  0x08,  0xEE,  0x14,  0xAA,  0x12,  0xAA,  0x21,  0xEE,  0x7E,  0x00,  0x08,  0xFE,  0x08,  0x00,  0x7F, 	/* 51180 */
+	0xFF,  0x08,  0x20,  0x4A,  0x20,  0x2C,  0x7C,  0x28,  0x44,  0x0E,  0x04,  0x18,  0x04,  0x60,  0x18,  0x96, 	/* 51190 */
+	0x08,  0x44,  0x08,  0x44,  0x15,  0xFF,  0x12,  0x44,  0x21,  0x7C,  0x7E,  0x44,  0x08,  0x7C,  0x08,  0x44, 	/* 511A0 */
+	0x7E,  0x44,  0x09,  0xFF,  0x4A,  0xA8,  0x2C,  0xAA,  0x28,  0xC6,  0x0E,  0x80,  0x18,  0xFF,  0x60,  0x00, 	/* 511B0 */
+	0x9B,  0x08,  0x40,  0x09,  0xBC,  0x15,  0x24,  0x13,  0x24,  0x21,  0xE5,  0x7F,  0x23,  0x09,  0x40,  0x09, 	/* 511C0 */
+	0xC0,  0x7F,  0x3E,  0x09,  0x02,  0x4B,  0x14,  0x2D,  0xD4,  0x29,  0x08,  0x0F,  0x14,  0x19,  0x22,  0x61, 	/* 511D0 */
+	0x41,  0x9C,  0x08,  0x00,  0x09,  0xEE,  0x15,  0x22,  0x13,  0x22,  0x21,  0x22,  0x7F,  0xEE,  0x09,  0x00, 	/* 511E0 */
+	0x09,  0x1E,  0x7F,  0xEA,  0x09,  0x0A,  0x4B,  0x0A,  0x2D,  0xE4,  0x29,  0x04,  0x0F,  0x0A,  0x19,  0x12, 	/* 511F0 */
+	0x61,  0x21,  0xA0,  0x08,  0x10,  0x08,  0x20,  0x14,  0x7C,  0x12,  0x44,  0x21,  0x7C,  0x7E,  0x44,  0x08, 	/* 51200 */
+	0x44,  0x08,  0x7C,  0x7E,  0x00,  0x08,  0xFE,  0x4A,  0x10,  0x2C,  0xFE,  0x28,  0x10,  0x0E,  0x10,  0x19, 	/* 51210 */
+	0xFF,  0x60,  0x00,  0xAC,  0x08,  0x28,  0x08,  0x48,  0x15,  0xC8,  0x12,  0x4A,  0x21,  0x5A,  0x7E,  0x5A, 	/* 51220 */
+	0x09,  0xEA,  0x08,  0x4C,  0x7F,  0x68,  0x08,  0xD8,  0x4A,  0xCC,  0x2D,  0x54,  0x28,  0x54,  0x0E,  0x52, 	/* 51230 */
+	0x18,  0x62,  0x60,  0x41,  0xAE,  0x08,  0x70,  0x08,  0x10,  0x14,  0x28,  0x12,  0x44,  0x20,  0xFA,  0x7F, 	/* 51240 */
+	0x01,  0x09,  0xEA,  0x09,  0x2A,  0x7F,  0xAA,  0x09,  0x74,  0x49,  0x34,  0x2D,  0xB4,  0x29,  0x6A,  0x0D, 	/* 51250 */
+	0x2A,  0x19,  0x2A,  0x61,  0x6A,  0xB5,  0x10,  0x10,  0x10,  0x10,  0x1B,  0xFC,  0x28,  0x94,  0x25,  0xFF, 	/* 51260 */
+	0x79,  0x14,  0x12,  0x14,  0x13,  0xFC,  0x7C,  0x90,  0x12,  0xFC,  0x56,  0x90,  0x39,  0x7E,  0x31,  0x90, 	/* 51270 */
+	0x15,  0x50,  0x1A,  0x30,  0x64,  0x0F,  0xBC,  0x08,  0x08,  0x08,  0x0A,  0x14,  0x09,  0x13,  0xFF,  0x21, 	/* 51280 */
+	0x08,  0x7F,  0x0A,  0x09,  0xFA,  0x09,  0x0A,  0x7F,  0x7A,  0x09,  0x5C,  0x4B,  0x54,  0x2D,  0x75,  0x29, 	/* 51290 */
+	0x0D,  0x0E,  0x13,  0x1A,  0x23,  0x64,  0x41,  0xBE,  0x08,  0x04,  0x08,  0x18,  0x14,  0xF0,  0x12,  0x10, 	/* 512A0 */
+	0x21,  0xFF,  0x7E,  0x10,  0x08,  0xFE,  0x08,  0x92,  0x7F,  0xFE,  0x08,  0x92,  0x4A,  0xFE,  0x2C,  0x10, 	/* 512B0 */
+	0x28,  0xFE,  0x0E,  0x10,  0x1B,  0xFF,  0x60,  0x00,  0x8C,  0x08,  0x88,  0x08,  0x50,  0x17,  0xFF,  0x12, 	/* 512C0 */
+	0x50,  0x21,  0xFC,  0x7E,  0x54,  0x08,  0x54,  0x09,  0xFF,  0x7E,  0x54,  0x09,  0xFC,  0x48,  0x58,  0x2C, 	/* 512D0 */
+	0xD4,  0x28,  0xD2,  0x0F,  0x51,  0x1A,  0x50,  0x60,  0x50,  0x94,  0x08,  0x10,  0x08,  0x10,  0x15,  0xFF, 	/* 512E0 */
+	0x13,  0x01,  0x21,  0x49,  0x7E,  0x44,  0x08,  0x52,  0x08,  0x92,  0x7E,  0x28,  0x08,  0x44,  0x4A,  0xFE, 	/* 512F0 */
+	0x2D,  0x45,  0x28,  0x44,  0x0E,  0x44,  0x18,  0x7C,  0x60,  0x00,  0x96,  0x08,  0x10,  0x08,  0x92,  0x14, 	/* 51300 */
+	0x52,  0x12,  0x54,  0x21,  0x7E,  0x7E,  0x42,  0x08,  0x42,  0x08,  0x7E,  0x7F,  0x42,  0x08,  0x7E,  0x4A, 	/* 51310 */
+	0x42,  0x2C,  0x42,  0x28,  0x7E,  0x0F,  0x14,  0x18,  0x62,  0x61,  0x81,  0x97,  0x08,  0x10,  0x08,  0x10, 	/* 51320 */
+	0x14,  0x28,  0x12,  0x44,  0x21,  0xFE,  0x7F,  0x01,  0x08,  0x7C,  0x08,  0x44,  0x7F,  0x7C,  0x08,  0x44, 	/* 51330 */
+	0x4A,  0x7C,  0x2C,  0x80,  0x28,  0xFE,  0x0F,  0x42,  0x1A,  0x7E,  0x60,  0x00,  0x9A,  0x08,  0x08,  0x09, 	/* 51340 */
+	0x10,  0x14,  0xBE,  0x12,  0xA2,  0x20,  0x22,  0x7E,  0x3E,  0x08,  0x20,  0x0B,  0xA0,  0x7E,  0xBE,  0x08, 	/* 51350 */
+	0xA2,  0x4A,  0xA2,  0x2C,  0xA2,  0x28,  0xFE,  0x0F,  0x20,  0x19,  0x18,  0x62,  0x07,  0xA7,  0x08,  0x10, 	/* 51360 */
+	0x08,  0x92,  0x14,  0x92,  0x12,  0xFE,  0x21,  0x00,  0x7E,  0xFF,  0x08,  0x00,  0x08,  0x7C,  0x7F,  0x44, 	/* 51370 */
+	0x08,  0x44,  0x4A,  0x7C,  0x2C,  0x44,  0x28,  0x24,  0x0E,  0x28,  0x19,  0xFF,  0x60,  0x00,  0xAC,  0x08, 	/* 51380 */
+	0x10,  0x08,  0x10,  0x15,  0xFF,  0x12,  0x00,  0x21,  0x7C,  0x7E,  0x44,  0x08,  0x7C,  0x08,  0x00,  0x7F, 	/* 51390 */
+	0xFE,  0x08,  0x82,  0x4A,  0xBA,  0x2C,  0xAA,  0x28,  0xAA,  0x0E,  0xBA,  0x18,  0x82,  0x60,  0x86,  0xAD, 	/* 513A0 */
+	0x08,  0x42,  0x08,  0x7C,  0x14,  0x41,  0x12,  0x3F,  0x21,  0x00,  0x7E,  0xBE,  0x08,  0xA2,  0x08,  0xBE, 	/* 513B0 */
+	0x7F,  0xA2,  0x08,  0xBE,  0x4A,  0xA2,  0x2C,  0xBE,  0x28,  0x80,  0x0E,  0xFF,  0x18,  0x66,  0x63,  0x81, 	/* 513C0 */
+	0xAE,  0x08,  0x10,  0x08,  0x10,  0x15,  0xFF,  0x12,  0x10,  0x21,  0x7C,  0x7E,  0x44,  0x08,  0x7C,  0x08, 	/* 513D0 */
+	0x44,  0x7F,  0xFC,  0x08,  0x44,  0x4A,  0x7C,  0x2C,  0x00,  0x29,  0xFF,  0x0E,  0x24,  0x18,  0xC2,  0x63, 	/* 513E0 */
+	0x01,  0xB0,  0x08,  0x78,  0x08,  0x08,  0x14,  0x48,  0x12,  0x74,  0x20,  0x84,  0x7E,  0xBA,  0x09,  0x09, 	/* 513F0 */
+	0x08,  0x44,  0x7E,  0x84,  0x08,  0xFE,  0x4B,  0x55,  0x2C,  0x54,  0x28,  0x54,  0x0E,  0x54,  0x19,  0xFF, 	/* 51400 */
+	0x60,  0x00,  0xB9,  0x08,  0x1C,  0x09,  0x04,  0x14,  0x92,  0x12,  0xA1,  0x20,  0x7E,  0x7F,  0x08,  0x08, 	/* 51410 */
+	0x88,  0x08,  0xBF,  0x7E,  0x08,  0x09,  0xD4,  0x4A,  0x54,  0x2C,  0x62,  0x28,  0x41,  0x0E,  0xA0,  0x19, 	/* 51420 */
+	0x18,  0x62,  0x07,  0x83,  0x08,  0x48,  0x08,  0x48,  0x14,  0x48,  0x13,  0xFF,  0x20,  0x90,  0x7E,  0xA8, 	/* 51430 */
+	0x08,  0xEF,  0x08,  0xB4,  0x7E,  0xA4,  0x08,  0xA4,  0x4A,  0xBF,  0x2C,  0xA4,  0x29,  0x2A,  0x0D,  0x2A, 	/* 51440 */
+	0x1A,  0x32,  0x60,  0xC1,  0x88,  0x09,  0x08,  0x08,  0x88,  0x14,  0xFF,  0x12,  0x08,  0x21,  0x3E,  0x7E, 	/* 51450 */
+	0xAA,  0x08,  0xAA,  0x08,  0x3E,  0x7E,  0x2A,  0x09,  0xAA,  0x4A,  0xBE,  0x2C,  0x88,  0x28,  0xBF,  0x0E, 	/* 51460 */
+	0xC8,  0x19,  0x28,  0x62,  0x1F,  0x90,  0x08,  0x00,  0x09,  0xFE,  0x14,  0xAA,  0x13,  0x32,  0x20,  0x66, 	/* 51470 */
+	0x7E,  0xAA,  0x08,  0x76,  0x08,  0x10,  0x7F,  0x28,  0x08,  0x4C,  0x49,  0x93,  0x2C,  0x64,  0x28,  0x1A, 	/* 51480 */
+	0x0E,  0x64,  0x18,  0x18,  0x60,  0xE0,  0x91,  0x08,  0x10,  0x08,  0x10,  0x14,  0xFF,  0x12,  0x44,  0x21, 	/* 51490 */
+	0x28,  0x7E,  0xFE,  0x08,  0x82,  0x08,  0x92,  0x7F,  0xFE,  0x08,  0x92,  0x4A,  0xBA,  0x2C,  0xAA,  0x28, 	/* 514A0 */
+	0xAA,  0x0E,  0xBA,  0x18,  0x82,  0x60,  0x86,  0x96,  0x01,  0x00,  0x1F,  0xFE,  0x12,  0x40,  0x1F,  0xFC, 	/* 514B0 */
+	0x12,  0x44,  0x1F,  0xFC,  0x14,  0x24,  0x27,  0xB8,  0x44,  0x22,  0x1E,  0x9E,  0x03,  0x60,  0x0C,  0x98, 	/* 514C0 */
+	0x77,  0xF7,  0x02,  0xA0,  0x7F,  0xFF,  0x00,  0x00,  0x97,  0x08,  0x00,  0x09,  0xFE,  0x15,  0x4A,  0x13, 	/* 514D0 */
+	0x4A,  0x21,  0xEA,  0x7F,  0x24,  0x09,  0xE4,  0x09,  0x4A,  0x7F,  0x51,  0x09,  0xE0,  0x4A,  0x10,  0x2C, 	/* 514E0 */
+	0xFE,  0x28,  0x10,  0x0E,  0x10,  0x19,  0xFF,  0x60,  0x00,  0x98,  0x08,  0x48,  0x09,  0x4E,  0x15,  0x52, 	/* 514F0 */
+	0x15,  0x5A,  0x23,  0x64,  0x7F,  0xD4,  0x08,  0x48,  0x08,  0x52,  0x7E,  0x62,  0x0B,  0xFF,  0x49,  0x42, 	/* 51500 */
+	0x2D,  0x52,  0x29,  0x4A,  0x0D,  0x4A,  0x1A,  0x42,  0x60,  0x46,  0x9D,  0x08,  0x00,  0x08,  0x7C,  0x14, 	/* 51510 */
+	0x44,  0x12,  0x7C,  0x21,  0x44,  0x7E,  0x7C,  0x08,  0x00,  0x09,  0xFF,  0x7F,  0x29,  0x09,  0xFF,  0x4A, 	/* 51520 */
+	0x00,  0x2C,  0xFC,  0x28,  0x48,  0x0E,  0x30,  0x18,  0xCC,  0x63,  0x03,  0xA1,  0x08,  0x10,  0x08,  0x10, 	/* 51530 */
+	0x15,  0xFE,  0x12,  0x84,  0x20,  0x48,  0x7F,  0xFF,  0x08,  0x00,  0x08,  0xFC,  0x7F,  0x84,  0x08,  0xFC, 	/* 51540 */
+	0x4A,  0x84,  0x2C,  0xFC,  0x28,  0x28,  0x0E,  0x49,  0x18,  0x89,  0x63,  0x07,  0xA4,  0x08,  0x10,  0x08, 	/* 51550 */
+	0xFE,  0x14,  0x92,  0x12,  0xFF,  0x21,  0x92,  0x7E,  0xFE,  0x08,  0x10,  0x08,  0xFE,  0x7E,  0x92,  0x08, 	/* 51560 */
+	0xFE,  0x4A,  0x20,  0x2D,  0xFF,  0x28,  0x48,  0x0E,  0xE8,  0x18,  0x38,  0x61,  0xC6,  0xA5,  0x08,  0x20, 	/* 51570 */
+	0x08,  0x20,  0x15,  0xFE,  0x13,  0x02,  0x21,  0x42,  0x7E,  0x7F,  0x08,  0x48,  0x08,  0x90,  0x7F,  0xBE, 	/* 51580 */
+	0x08,  0xA2,  0x4A,  0xA2,  0x2C,  0xBE,  0x28,  0xA2,  0x0E,  0xA2,  0x18,  0xBE,  0x60,  0x80,  0xA8,  0x08, 	/* 51590 */
+	0x06,  0x7F,  0xB8,  0x08,  0x20,  0x3F,  0x3F,  0x29,  0x24,  0x3F,  0x24,  0x29,  0x44,  0x7F,  0x84,  0x08, 	/* 515A0 */
+	0x84,  0x0B,  0x64,  0x0F,  0xF8,  0x70,  0x87,  0x0F,  0xF8,  0x04,  0x90,  0x7F,  0xFF,  0x00,  0x00,  0x83, 	/* 515B0 */
+	0x08,  0x10,  0x08,  0x7C,  0x14,  0x10,  0x12,  0xFE,  0x21,  0x00,  0x7E,  0x44,  0x09,  0xFF,  0x08,  0x44, 	/* 515C0 */
+	0x7E,  0x64,  0x09,  0x9F,  0x4A,  0x00,  0x2D,  0xFF,  0x28,  0x48,  0x0E,  0x49,  0x18,  0x89,  0x63,  0x07, 	/* 515D0 */
+	0x87,  0x08,  0x06,  0x08,  0xF8,  0x14,  0x92,  0x12,  0x54,  0x21,  0xFF,  0x7E,  0x38,  0x08,  0x54,  0x08, 	/* 515E0 */
+	0x92,  0x7F,  0xFF,  0x08,  0x92,  0x4A,  0x92,  0x2C,  0xFE,  0x28,  0x92,  0x0E,  0x92,  0x18,  0xFE,  0x60, 	/* 515F0 */
+	0x00,  0x90,  0x08,  0x10,  0x08,  0x10,  0x15,  0xFF,  0x12,  0x28,  0x20,  0xAA,  0x7E,  0x44,  0x08,  0xFE, 	/* 51600 */
+	0x09,  0x45,  0x7E,  0x7C,  0x08,  0x44,  0x4A,  0x7C,  0x2C,  0x10,  0x28,  0x54,  0x0E,  0x92,  0x19,  0x11, 	/* 51610 */
+	0x60,  0x30,  0x93,  0x08,  0x88,  0x08,  0x88,  0x1B,  0xE8,  0x14,  0x0F,  0x23,  0xD4,  0x7D,  0x54,  0x09, 	/* 51620 */
+	0xE4,  0x08,  0x04,  0x7F,  0xD4,  0x08,  0x54,  0x4C,  0x94,  0x28,  0xE8,  0x2B,  0x8C,  0x0C,  0x94,  0x30, 	/* 51630 */
+	0xA2,  0x41,  0xC1,  0x94,  0x08,  0x00,  0x0B,  0xFF,  0x14,  0x48,  0x13,  0xFE,  0x21,  0x4A,  0x7F,  0xFE, 	/* 51640 */
+	0x08,  0x00,  0x08,  0xFC,  0x7E,  0x84,  0x08,  0xFC,  0x4A,  0x84,  0x2C,  0xFC,  0x28,  0x20,  0x0F,  0xFF, 	/* 51650 */
+	0x18,  0x20,  0x60,  0x20,  0x98,  0x08,  0x10,  0x08,  0x10,  0x15,  0xFF,  0x12,  0x44,  0x21,  0xFF,  0x7F, 	/* 51660 */
+	0x00,  0x08,  0xFE,  0x08,  0x92,  0x7E,  0xFE,  0x08,  0x92,  0x4A,  0xFE,  0x2C,  0x10,  0x28,  0xFE,  0x0E, 	/* 51670 */
+	0x10,  0x19,  0xFF,  0x60,  0x00,  0x99,  0x08,  0xEA,  0x08,  0x2C,  0x14,  0xA9,  0x12,  0x66,  0x21,  0x44, 	/* 51680 */
+	0x7E,  0x82,  0x09,  0x7D,  0x08,  0x00,  0x7F,  0x7C,  0x08,  0x44,  0x4A,  0x44,  0x2C,  0x7C,  0x28,  0x44, 	/* 51690 */
+	0x0E,  0x28,  0x19,  0xFF,  0x60,  0x00,  0x9A,  0x08,  0x00,  0x09,  0xFF,  0x14,  0x28,  0x12,  0x28,  0x21, 	/* 516A0 */
+	0xEE,  0x7E,  0x82,  0x08,  0x82,  0x08,  0xEE,  0x7E,  0x28,  0x09,  0xFF,  0x4A,  0x10,  0x2C,  0xA8,  0x28, 	/* 516B0 */
+	0xAA,  0x0D,  0x25,  0x1A,  0x25,  0x60,  0x1C,  0xA1,  0x08,  0x48,  0x08,  0x4A,  0x19,  0xE9,  0x14,  0x48, 	/* 516C0 */
+	0x23,  0xFF,  0x3E,  0x08,  0x48,  0xEA,  0x08,  0xAA,  0x7E,  0xAA,  0x08,  0xEA,  0x4B,  0x2C,  0x2C,  0xA5, 	/* 516D0 */
+	0x28,  0x5D,  0x0E,  0xCB,  0x1B,  0x13,  0x60,  0x21,  0xAB,  0x08,  0x48,  0x08,  0x50,  0x14,  0xFF,  0x12, 	/* 516E0 */
+	0x90,  0x21,  0xFE,  0x7E,  0x90,  0x08,  0xFE,  0x08,  0x90,  0x7F,  0xFF,  0x08,  0x00,  0x4A,  0xEE,  0x2C, 	/* 516F0 */
+	0xAA,  0x28,  0xAA,  0x0E,  0xBA,  0x18,  0x82,  0x60,  0x86,  0xB5,  0x08,  0x4A,  0x09,  0xE9,  0x18,  0x48, 	/* 51700 */
+	0x17,  0xFF,  0x22,  0x08,  0x3F,  0xE8,  0x48,  0xAA,  0x08,  0xEA,  0x7E,  0x0A,  0x09,  0xFA,  0x4A,  0x4C, 	/* 51710 */
+	0x2D,  0xF5,  0x28,  0x4D,  0x0E,  0xEB,  0x1B,  0x13,  0x60,  0x21,  0xB6,  0x08,  0x00,  0x08,  0xFE,  0x14, 	/* 51720 */
+	0xAA,  0x12,  0xAA,  0x21,  0xFE,  0x7E,  0x00,  0x09,  0xFF,  0x08,  0x00,  0x7E,  0xFE,  0x08,  0x82,  0x4A, 	/* 51730 */
+	0xFE,  0x2C,  0x32,  0x28,  0x54,  0x0F,  0xC8,  0x18,  0x64,  0x61,  0x83,  0xB8,  0x08,  0x00,  0x08,  0xFE, 	/* 51740 */
+	0x14,  0xAA,  0x12,  0xAA,  0x20,  0xFE,  0x7E,  0x10,  0x08,  0xFE,  0x08,  0x10,  0x7F,  0xFF,  0x08,  0x44, 	/* 51750 */
+	0x4A,  0x28,  0x2D,  0xFF,  0x28,  0x10,  0x0E,  0xFE,  0x18,  0x10,  0x60,  0x10,  0xBA,  0x08,  0x92,  0x08, 	/* 51760 */
+	0x52,  0x14,  0x54,  0x13,  0xFF,  0x21,  0x01,  0x7F,  0x7D,  0x08,  0x44,  0x08,  0x7C,  0x7F,  0x00,  0x08, 	/* 51770 */
+	0xFE,  0x4A,  0x92,  0x2C,  0xFE,  0x28,  0x92,  0x0E,  0x92,  0x18,  0xFE,  0x60,  0x00,  0x81,  0x08,  0x00, 	/* 51780 */
+	0x08,  0x96,  0x14,  0xC6,  0x12,  0xAA,  0x21,  0x9A,  0x7E,  0xA6,  0x08,  0xD2,  0x08,  0xFE,  0x7F,  0x29, 	/* 51790 */
+	0x08,  0x47,  0x4A,  0xA0,  0x2C,  0x7C,  0x29,  0xA4,  0x0E,  0x18,  0x18,  0x6C,  0x63,  0x83,  0x84,  0x08, 	/* 517A0 */
+	0x10,  0x09,  0xFF,  0x14,  0x10,  0x12,  0x7E,  0x20,  0x00,  0x7F,  0xFF,  0x08,  0x02,  0x08,  0xFC,  0x7E, 	/* 517B0 */
+	0x10,  0x09,  0xFF,  0x4A,  0x02,  0x2C,  0xFF,  0x28,  0xB2,  0x0E,  0xAA,  0x18,  0xE2,  0x60,  0x06,  0x91, 	/* 517C0 */
+	0x08,  0x04,  0x08,  0xF4,  0x14,  0xA4,  0x12,  0xA7,  0x20,  0xF8,  0x7E,  0x90,  0x08,  0xF0,  0x08,  0xAF, 	/* 517D0 */
+	0x7F,  0xF0,  0x08,  0x00,  0x4A,  0xFE,  0x2C,  0xAA,  0x29,  0xAA,  0x0E,  0xAA,  0x19,  0xFF,  0x60,  0x00, 	/* 517E0 */
+	0x92,  0x00,  0x20,  0x3F,  0x7F,  0x24,  0x80,  0x3E,  0x7C,  0x22,  0x00,  0x3E,  0xFE,  0x24,  0xAA,  0x3F, 	/* 517F0 */
+	0xFE,  0x00,  0x80,  0x03,  0x60,  0x0F,  0xF8,  0x70,  0x87,  0x0F,  0xF8,  0x04,  0x90,  0x7F,  0xFF,  0x00, 	/* 51800 */
+	0x00,  0x93,  0x08,  0x08,  0x08,  0x3E,  0x14,  0x2A,  0x15,  0x3E,  0x22,  0x88,  0x7E,  0xFF,  0x08,  0x00, 	/* 51810 */
+	0x08,  0x3E,  0x7F,  0xA2,  0x08,  0xBE,  0x4A,  0xA0,  0x2C,  0xBE,  0x28,  0xA2,  0x0D,  0x7E,  0x19,  0x30, 	/* 51820 */
+	0x62,  0x0F,  0x9A,  0x08,  0x44,  0x09,  0xEF,  0x14,  0x44,  0x13,  0xFF,  0x21,  0x44,  0x7E,  0xAA,  0x09, 	/* 51830 */
+	0x01,  0x08,  0xFC,  0x7F,  0x84,  0x08,  0xFC,  0x4A,  0x84,  0x2C,  0xFC,  0x28,  0x84,  0x0E,  0xFC,  0x18, 	/* 51840 */
+	0xC4,  0x63,  0x02,  0x9B,  0x08,  0x08,  0x08,  0x08,  0x14,  0xFF,  0x12,  0x94,  0x21,  0xFF,  0x7E,  0x94, 	/* 51850 */
+	0x08,  0x9C,  0x08,  0xFF,  0x7E,  0x88,  0x08,  0xBE,  0x4A,  0xAA,  0x2C,  0xBE,  0x28,  0xAA,  0x0F,  0x3E, 	/* 51860 */
+	0x19,  0x12,  0x62,  0x61,  0x9E,  0x08,  0x92,  0x09,  0x24,  0x14,  0x92,  0x13,  0xFC,  0x21,  0x54,  0x7F, 	/* 51870 */
+	0x24,  0x09,  0x54,  0x09,  0xFC,  0x7E,  0x00,  0x09,  0xB4,  0x4D,  0x6C,  0x29,  0xB4,  0x2B,  0x6D,  0x1D, 	/* 51880 */
+	0x25,  0x11,  0xB3,  0x66,  0x61,  0xA0,  0x08,  0x8A,  0x08,  0x92,  0x15,  0x7D,  0x13,  0x6D,  0x20,  0xAA, 	/* 51890 */
+	0x7E,  0xBA,  0x09,  0x6D,  0x09,  0x7D,  0x7F,  0xD7,  0x08,  0x10,  0x4B,  0xFF,  0x2C,  0x38,  0x28,  0x54, 	/* 518A0 */
+	0x0E,  0x92,  0x19,  0x11,  0x60,  0x10,  0xA2,  0x08,  0x10,  0x08,  0x1E,  0x14,  0x10,  0x12,  0xFF,  0x21, 	/* 518B0 */
+	0x92,  0x7E,  0xFC,  0x08,  0x91,  0x08,  0xBF,  0x7F,  0xAA,  0x08,  0xBE,  0x4A,  0xAA,  0x2C,  0xBE,  0x28, 	/* 518C0 */
+	0xB0,  0x0F,  0x6A,  0x19,  0xA5,  0x62,  0x1C,  0xAA,  0x08,  0x10,  0x08,  0x1E,  0x14,  0x10,  0x12,  0xFF, 	/* 518D0 */
+	0x21,  0x9A,  0x7E,  0xF1,  0x08,  0xBF,  0x08,  0xAA,  0x7E,  0xBE,  0x08,  0xAA,  0x4A,  0xBE,  0x2C,  0x80, 	/* 518E0 */
+	0x29,  0xFE,  0x0E,  0xAA,  0x19,  0xFF,  0x62,  0x00,  0xB0,  0x08,  0x10,  0x08,  0x10,  0x14,  0x28,  0x12, 	/* 518F0 */
+	0x44,  0x21,  0xBB,  0x7E,  0x00,  0x09,  0xFF,  0x09,  0x6D,  0x7F,  0xFF,  0x08,  0x00,  0x4A,  0xFE,  0x2C, 	/* 51900 */
+	0xAA,  0x28,  0xFE,  0x0E,  0xAA,  0x18,  0xAA,  0x60,  0x86,  0xB5,  0x08,  0x44,  0x0B,  0xFF,  0x14,  0x44, 	/* 51910 */
+	0x12,  0xEE,  0x21,  0xAA,  0x7E,  0xEE,  0x08,  0x44,  0x08,  0x48,  0x7E,  0xFE,  0x09,  0x90,  0x4A,  0xFE, 	/* 51920 */
+	0x2C,  0x90,  0x28,  0xFE,  0x0E,  0x90,  0x18,  0xFF,  0x60,  0x00,  0xB7,  0x08,  0x00,  0x09,  0xFE,  0x14, 	/* 51930 */
+	0x48,  0x12,  0x78,  0x21,  0x48,  0x7E,  0x7E,  0x09,  0xC8,  0x08,  0x08,  0x3F,  0xFF,  0x08,  0xAA,  0x4A, 	/* 51940 */
+	0xEE,  0x2C,  0xAA,  0x28,  0xEE,  0x0E,  0xAB,  0x19,  0xFE,  0x60,  0x22,  0xBC,  0x08,  0x00,  0x09,  0xFE, 	/* 51950 */
+	0x15,  0x4A,  0x15,  0xFE,  0x22,  0x08,  0x7E,  0x92,  0x08,  0xBF,  0x0B,  0x54,  0x7E,  0x94,  0x09,  0x5F, 	/* 51960 */
+	0x4B,  0xF4,  0x2C,  0x9F,  0x29,  0xD4,  0x0D,  0xB4,  0x1A,  0x9F,  0x60,  0x80,  0xBD,  0x09,  0x8C,  0x09, 	/* 51970 */
+	0xEF,  0x16,  0x94,  0x13,  0xFF,  0x20,  0xC6,  0x7D,  0x6A,  0x0A,  0x53,  0x08,  0xFC,  0x7F,  0x84,  0x08, 	/* 51980 */
+	0xFC,  0x4A,  0x84,  0x2C,  0xFC,  0x28,  0x84,  0x0E,  0xFC,  0x18,  0xCC,  0x63,  0x02,  0xBE,  0x08,  0xC4, 	/* 51990 */
+	0x0B,  0xF4,  0x34,  0x0A,  0x09,  0xE4,  0x14,  0x0A,  0x7F,  0xFF,  0x09,  0x24,  0x2D,  0xF5,  0x4A,  0x95, 	/* 519A0 */
+	0x03,  0x60,  0x0F,  0xF8,  0x70,  0x87,  0x0F,  0xF8,  0x04,  0x90,  0x7F,  0xFF,  0x00,  0x00,  0xBF,  0x0A, 	/* 519B0 */
+	0x3C,  0x2B,  0x24,  0x7F,  0xA5,  0x12,  0x43,  0x3F,  0x81,  0x14,  0x7C,  0x25,  0x24,  0x37,  0x18,  0x25, 	/* 519C0 */
+	0x28,  0x3F,  0xC4,  0x03,  0x63,  0x0C,  0x98,  0x77,  0xF7,  0x02,  0xA0,  0x7F,  0xFF,  0x00,  0x00,  0x81, 	/* 519D0 */
+	0x09,  0xEF,  0x09,  0x29,  0x15,  0xEF,  0x13,  0x29,  0x21,  0xEF,  0x7E,  0x48,  0x08,  0xFF,  0x09,  0x90, 	/* 519E0 */
+	0x7E,  0xFE,  0x08,  0x90,  0x4A,  0xFE,  0x2C,  0x90,  0x2B,  0xFF,  0x0C,  0x44,  0x10,  0x38,  0x61,  0xC7, 	/* 519F0 */
+	0xB7,  0x00,  0x00,  0x07,  0xFC,  0x04,  0x00,  0x07,  0xF8,  0x04,  0x00,  0x07,  0xF8,  0x04,  0x00,  0x04, 	/* 51A00 */
+	0x00,  0x7F,  0xFF,  0x05,  0x08,  0x04,  0x88,  0x04,  0x50,  0x04,  0x20,  0x05,  0x90,  0x0E,  0x0C,  0x30, 	/* 51A10 */
+	0x03,  0x80,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42,  0x42,  0x42,  0x7E,  0x7E, 	/* 51A20 */
+	0x40,  0x02,  0x40,  0x02,  0x40,  0x02,  0x40,  0x02,  0x40,  0x02,  0x40,  0x02,  0x40,  0x02,  0x40,  0x02, 	/* 51A30 */
+	0x40,  0x06,  0x82,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42,  0x42,  0x42,  0x7E, 	/* 51A40 */
+	0x7E,  0x40,  0x02,  0x40,  0x02,  0x40,  0x02,  0x4F,  0xF2,  0x40,  0x02,  0x40,  0x02,  0x40,  0x02,  0x40, 	/* 51A50 */
+	0x02,  0x40,  0x06,  0x83,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E, 	/* 51A60 */
+	0x41,  0x02,  0x41,  0x02,  0x41,  0x02,  0x41,  0x82,  0x42,  0x82,  0x42,  0x42,  0x44,  0x22,  0x48,  0x12, 	/* 51A70 */
+	0x40,  0x02,  0x40,  0x06,  0x87,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42,  0x42, 	/* 51A80 */
+	0x42,  0x7E,  0x7E,  0x40,  0x02,  0x4F,  0xF2,  0x41,  0x02,  0x41,  0x82,  0x41,  0x42,  0x41,  0x22,  0x41, 	/* 51A90 */
+	0x02,  0x41,  0x02,  0x40,  0x06,  0x89,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42, 	/* 51AA0 */
+	0x42,  0x42,  0x7E,  0x7E,  0x40,  0x82,  0x40,  0x82,  0x4F,  0xF2,  0x41,  0x82,  0x42,  0x82,  0x44,  0x82, 	/* 51AB0 */
+	0x58,  0x82,  0x41,  0x82,  0x40,  0x06,  0x8A,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42, 	/* 51AC0 */
+	0x42,  0x42,  0x42,  0x7E,  0x7E,  0x41,  0x02,  0x41,  0x02,  0x49,  0x12,  0x49,  0x12,  0x49,  0x12,  0x49, 	/* 51AD0 */
+	0x12,  0x4F,  0xF2,  0x40,  0x02,  0x40,  0x06,  0x8B,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E, 	/* 51AE0 */
+	0x42,  0x42,  0x42,  0x42,  0x7E,  0x7E,  0x40,  0x02,  0x4F,  0xF2,  0x42,  0x42,  0x42,  0x42,  0x7F,  0xFA, 	/* 51AF0 */
+	0x42,  0x42,  0x44,  0x42,  0x48,  0x42,  0x40,  0x06,  0x8F,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E, 	/* 51B00 */
+	0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x40,  0x02,  0x4F,  0xF2,  0x41,  0x02,  0x41,  0x02,  0x47,  0xE2,  0x41, 	/* 51B10 */
+	0x02,  0x41,  0x02,  0x5F,  0xFA,  0x40,  0x02,  0x40,  0x06,  0x91,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42, 	/* 51B20 */
+	0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x41,  0x02,  0x41,  0x02,  0x5F,  0xF2,  0x41,  0x02,  0x43,  0x82, 	/* 51B30 */
+	0x45,  0x42,  0x49,  0x22,  0x51,  0x12,  0x41,  0x02,  0x40,  0x06,  0x93,  0x00,  0x00,  0x7E,  0x7E,  0x42, 	/* 51B40 */
+	0x42,  0x7E,  0x7E,  0x42,  0x42,  0x42,  0x42,  0x7E,  0x7E,  0x40,  0x02,  0x47,  0xE2,  0x44,  0x22,  0x47, 	/* 51B50 */
+	0xE2,  0x44,  0x22,  0x44,  0x22,  0x47,  0xE2,  0x40,  0x02,  0x40,  0x06,  0x94,  0x00,  0x00,  0x7E,  0x7E, 	/* 51B60 */
+	0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42,  0x42,  0x42,  0x7F,  0x7E,  0x41,  0x02,  0x5F,  0xF2,  0x44,  0x42, 	/* 51B70 */
+	0x44,  0x42,  0x42,  0x82,  0x41,  0x02,  0x46,  0xC2,  0x58,  0x32,  0x40,  0x06,  0x96,  0x00,  0x00,  0x7E, 	/* 51B80 */
+	0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42,  0x42,  0x42,  0x7E,  0x7E,  0x41,  0x02,  0x41,  0x12,  0x5D, 	/* 51B90 */
+	0x92,  0x45,  0xA2,  0x45,  0x42,  0x49,  0x22,  0x51,  0x1A,  0x43,  0x02,  0x40,  0x06,  0x98,  0x00,  0x00, 	/* 51BA0 */
+	0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x40,  0x02,  0x4F,  0xE2,  0x49,  0x22, 	/* 51BB0 */
+	0x4F,  0xE2,  0x49,  0x22,  0x4F,  0xE2,  0x41,  0x02,  0x41,  0x02,  0x41,  0x02,  0x41,  0x06,  0x99,  0x00, 	/* 51BC0 */
+	0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x41,  0x02,  0x41,  0x02,  0x5F, 	/* 51BD0 */
+	0xFA,  0x41,  0x02,  0x4F,  0xF2,  0x49,  0x12,  0x49,  0x12,  0x49,  0x62,  0x41,  0x02,  0x41,  0x06,  0xA0, 	/* 51BE0 */
+	0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42,  0x42,  0x42,  0x7E,  0x7E,  0x40,  0x02, 	/* 51BF0 */
+	0x4F,  0xF2,  0x41,  0x02,  0x41,  0x02,  0x47,  0xE2,  0x41,  0x42,  0x41,  0x22,  0x4F,  0xF2,  0x40,  0x06, 	/* 51C00 */
+	0xA2,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x44,  0x22,  0x42, 	/* 51C10 */
+	0x42,  0x4F,  0xF2,  0x41,  0x02,  0x41,  0x02,  0x5F,  0xFA,  0x41,  0x42,  0x42,  0x22,  0x44,  0x12,  0x48, 	/* 51C20 */
+	0x06,  0xA3,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x41,  0x02, 	/* 51C30 */
+	0x43,  0xE2,  0x4E,  0x42,  0x41,  0x82,  0x46,  0x62,  0x58,  0x1A,  0x47,  0xE2,  0x44,  0x22,  0x47,  0xE2, 	/* 51C40 */
+	0x40,  0x06,  0xA4,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x40, 	/* 51C50 */
+	0x82,  0x41,  0x42,  0x46,  0x22,  0x5B,  0xDA,  0x40,  0x02,  0x47,  0xE2,  0x44,  0x22,  0x44,  0x22,  0x47, 	/* 51C60 */
+	0xE2,  0x40,  0x06,  0xA5,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E, 	/* 51C70 */
+	0x42,  0x22,  0x42,  0x52,  0x47,  0xFA,  0x48,  0x42,  0x58,  0x52,  0x68,  0x62,  0x48,  0xAA,  0x4B,  0x1A, 	/* 51C80 */
+	0x48,  0x0A,  0x40,  0x06,  0xA7,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42,  0x7E, 	/* 51C90 */
+	0x7E,  0x40,  0x02,  0x42,  0x42,  0x4F,  0xF2,  0x42,  0x42,  0x42,  0x42,  0x5F,  0xFA,  0x42,  0x42,  0x44, 	/* 51CA0 */
+	0x22,  0x58,  0x12,  0x40,  0x06,  0xA8,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42, 	/* 51CB0 */
+	0x7E,  0x7E,  0x41,  0x02,  0x4F,  0xE2,  0x41,  0x02,  0x5F,  0xF2,  0x41,  0x02,  0x4F,  0xE2,  0x41,  0x02, 	/* 51CC0 */
+	0x5F,  0xF2,  0x40,  0x02,  0x40,  0x06,  0xAD,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42, 	/* 51CD0 */
+	0x42,  0x7E,  0x7E,  0x40,  0x02,  0x47,  0xE2,  0x44,  0x22,  0x47,  0xE2,  0x41,  0x02,  0x4F,  0xF2,  0x48, 	/* 51CE0 */
+	0x12,  0x48,  0x12,  0x4F,  0xF2,  0x40,  0x06,  0xB2,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E, 	/* 51CF0 */
+	0x42,  0x42,  0x7E,  0x7E,  0x44,  0x42,  0x42,  0x82,  0x4F,  0xE2,  0x48,  0x22,  0x48,  0x22,  0x4F,  0xE2, 	/* 51D00 */
+	0x42,  0x82,  0x42,  0x92,  0x44,  0x72,  0x48,  0x06,  0xB9,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E, 	/* 51D10 */
+	0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x41,  0x02,  0x5F,  0xFA,  0x43,  0x42,  0x47,  0xE2,  0x4D,  0x32,  0x57, 	/* 51D20 */
+	0xEA,  0x45,  0x22,  0x47,  0xE2,  0x41,  0x12,  0x40,  0xF6,  0xBB,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42, 	/* 51D30 */
+	0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x02,  0x43,  0xC2,  0x44,  0x42,  0x49,  0x82,  0x57,  0x72, 	/* 51D40 */
+	0x44,  0x12,  0x47,  0x72,  0x44,  0x12,  0x47,  0xF2,  0x40,  0x06,  0xBC,  0x00,  0x00,  0x7E,  0x7E,  0x42, 	/* 51D50 */
+	0x42,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x44,  0x22,  0x5F,  0xA2,  0x44,  0x52,  0x47,  0x8A,  0x45, 	/* 51D60 */
+	0x22,  0x45,  0x12,  0x45,  0x42,  0x49,  0x22,  0x53,  0x12,  0x40,  0x06,  0xBE,  0x00,  0x00,  0x7E,  0x7E, 	/* 51D70 */
+	0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x40,  0xA2,  0x5F,  0xFA,  0x4E,  0x82,  0x4A,  0x92, 	/* 51D80 */
+	0x4E,  0x52,  0x41,  0x62,  0x46,  0xAA,  0x59,  0x1A,  0x46,  0x0A,  0x40,  0x06,  0x83,  0x00,  0x00,  0x7E, 	/* 51D90 */
+	0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x47,  0xE2,  0x44,  0x22,  0x47,  0xE2,  0x44, 	/* 51DA0 */
+	0x22,  0x47,  0xE2,  0x41,  0x12,  0x5F,  0xFA,  0x42,  0x42,  0x4C,  0x32,  0x40,  0x06,  0x87,  0x00,  0x00, 	/* 51DB0 */
+	0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42,  0x42,  0x42,  0x7E,  0x7E,  0x41,  0x02,  0x4F,  0xF2, 	/* 51DC0 */
+	0x42,  0x42,  0x5F,  0xFA,  0x44,  0x22,  0x47,  0xE2,  0x44,  0x22,  0x47,  0xE2,  0x40,  0x06,  0x8A,  0x00, 	/* 51DD0 */
+	0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x48,  0x32,  0x45,  0xC2,  0x40, 	/* 51DE0 */
+	0x42,  0x53,  0xFA,  0x48,  0x42,  0x41,  0xF2,  0x45,  0x12,  0x49,  0x12,  0x51,  0xF2,  0x40,  0x06,  0x8C, 	/* 51DF0 */
+	0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x40,  0x82,  0x5F,  0xFA, 	/* 51E00 */
+	0x46,  0xB2,  0x45,  0xD2,  0x47,  0xF2,  0x41,  0xC2,  0x42,  0xA2,  0x4C,  0x9A,  0x40,  0x82,  0x40,  0x06, 	/* 51E10 */
+	0x8D,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x41,  0x22,  0x4F, 	/* 51E20 */
+	0xE2,  0x41,  0x42,  0x5F,  0xFA,  0x43,  0xE2,  0x46,  0x22,  0x4B,  0xE2,  0x52,  0x22,  0x43,  0xE2,  0x40, 	/* 51E30 */
+	0x06,  0x94,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x41,  0x02, 	/* 51E40 */
+	0x4F,  0xE2,  0x41,  0x02,  0x5F,  0xFA,  0x42,  0x62,  0x4F,  0x92,  0x47,  0xF2,  0x45,  0x52,  0x5F,  0xFA, 	/* 51E50 */
+	0x40,  0x06,  0x95,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x51, 	/* 51E60 */
+	0x02,  0x4A,  0x42,  0x5F,  0x7E,  0x44,  0x4A,  0x55,  0xA2,  0x5F,  0x22,  0x44,  0x52,  0x44,  0x92,  0x49, 	/* 51E70 */
+	0x0A,  0x40,  0x06,  0x96,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E, 	/* 51E80 */
+	0x40,  0x02,  0x47,  0xF2,  0x44,  0x82,  0x47,  0xF2,  0x44,  0x82,  0x47,  0xFA,  0x4D,  0x2A,  0x4A,  0x8A, 	/* 51E90 */
+	0x52,  0x32,  0x40,  0x06,  0x98,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42,  0x7E, 	/* 51EA0 */
+	0x7E,  0x40,  0x02,  0x5F,  0x12,  0x40,  0xFE,  0x5F,  0x12,  0x51,  0x92,  0x5F,  0x52,  0x4A,  0x12,  0x47, 	/* 51EB0 */
+	0x12,  0x5C,  0x32,  0x40,  0x06,  0x9C,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42,  0x42, 	/* 51EC0 */
+	0x7E,  0x7E,  0x44,  0x22,  0x5A,  0xD2,  0x44,  0x22,  0x4A,  0x52,  0x5D,  0xEA,  0x42,  0x42,  0x52,  0x4A, 	/* 51ED0 */
+	0x5E,  0x7A,  0x44,  0x42,  0x48,  0x46,  0xA1,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x42, 	/* 51EE0 */
+	0x42,  0x7E,  0x7E,  0x40,  0x02,  0x4E,  0x72,  0x4A,  0x52,  0x4F,  0xF2,  0x45,  0x22,  0x47,  0xE2,  0x45, 	/* 51EF0 */
+	0x22,  0x5F,  0xFA,  0x41,  0x02,  0x41,  0x06,  0xA2,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E,  0x7E, 	/* 51F00 */
+	0x42,  0x42,  0x7E,  0x7E,  0x40,  0x22,  0x5E,  0xFA,  0x52,  0x52,  0x5E,  0x52,  0x51,  0xFA,  0x5E,  0x22, 	/* 51F10 */
+	0x5A,  0xFA,  0x6A,  0x22,  0x4E,  0x22,  0x40,  0x06,  0xA5,  0x00,  0x00,  0x7E,  0x7E,  0x42,  0x42,  0x7E, 	/* 51F20 */
+	0x7E,  0x42,  0x42,  0x7E,  0x7E,  0x49,  0xF2,  0x44,  0x42,  0x53,  0xFA,  0x48,  0xA2,  0x5D,  0xFA,  0x44, 	/* 51F30 */
+	0x42,  0x44,  0xF2,  0x4A,  0x42,  0x51,  0xFA,  0x40,  0x06,  0x9C,  0x00,  0x80,  0x01,  0x00,  0x0F,  0xF0, 	/* 51F40 */
+	0x08,  0x10,  0x0F,  0xF0,  0x08,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x80, 	/* 51F50 */
+	0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0xA1,  0x00,  0x04,  0x3C,  0x18,  0x24, 	/* 51F60 */
+	0xF0,  0x24,  0x10,  0x28,  0x10,  0x30,  0x10,  0x28,  0x10,  0x25,  0xFF,  0x24,  0x10,  0x22,  0x10,  0x22, 	/* 51F70 */
+	0x10,  0x32,  0x10,  0x2C,  0x10,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0xA8,  0x00,  0x00,  0x3D,  0xFF, 	/* 51F80 */
+	0x25,  0x00,  0x29,  0x00,  0x29,  0x7C,  0x31,  0x44,  0x29,  0x44,  0x25,  0x44,  0x25,  0x44,  0x25,  0x44, 	/* 51F90 */
+	0x25,  0x58,  0x26,  0x40,  0x3A,  0x42,  0x24,  0x42,  0x28,  0x3E,  0x20,  0x00,  0xAA,  0x00,  0x00,  0x3C, 	/* 51FA0 */
+	0xFF,  0x24,  0x80,  0x24,  0x80,  0x28,  0x80,  0x30,  0xFE,  0x28,  0xA2,  0x24,  0xA2,  0x24,  0xA4,  0x24, 	/* 51FB0 */
+	0x94,  0x24,  0x98,  0x39,  0x08,  0x21,  0x14,  0x22,  0x24,  0x24,  0xC2,  0x23,  0x01,  0xAE,  0x00,  0x00, 	/* 51FC0 */
+	0x3C,  0xFC,  0x24,  0x00,  0x28,  0x00,  0x28,  0x00,  0x33,  0xFF,  0x28,  0x48,  0x28,  0x48,  0x24,  0x48, 	/* 51FD0 */
+	0x24,  0x48,  0x24,  0x48,  0x24,  0x48,  0x38,  0x88,  0x20,  0x89,  0x21,  0x09,  0x22,  0x07,  0xAF,  0x00, 	/* 51FE0 */
+	0x10,  0x3C,  0x10,  0x24,  0x10,  0x24,  0x10,  0x28,  0x90,  0x30,  0x90,  0x28,  0x9E,  0x28,  0x90,  0x24, 	/* 51FF0 */
+	0x90,  0x24,  0x90,  0x24,  0x90,  0x24,  0x90,  0x38,  0x90,  0x20,  0x90,  0x23,  0xFF,  0x20,  0x00,  0xB2, 	/* 52000 */
+	0x00,  0x20,  0x3C,  0x20,  0x24,  0x20,  0x27,  0xFF,  0x28,  0x20,  0x30,  0x20,  0x28,  0x20,  0x24,  0x3E, 	/* 52010 */
+	0x22,  0x42,  0x22,  0x42,  0x22,  0x42,  0x22,  0x82,  0x3C,  0x82,  0x21,  0x02,  0x22,  0x04,  0x24,  0x18, 	/* 52020 */
+	0xBB,  0x00,  0x00,  0x3C,  0xFC,  0x24,  0x84,  0x24,  0x84,  0x28,  0x84,  0x30,  0xFC,  0x28,  0x84,  0x24, 	/* 52030 */
+	0x84,  0x22,  0x84,  0x22,  0xFC,  0x22,  0x84,  0x32,  0x84,  0x2C,  0x84,  0x20,  0x84,  0x23,  0xFF,  0x20, 	/* 52040 */
+	0x00,  0xBF,  0x00,  0x00,  0x3F,  0xFF,  0x24,  0x04,  0x24,  0x04,  0x29,  0xE4,  0x31,  0x24,  0x29,  0x24, 	/* 52050 */
+	0x25,  0x24,  0x25,  0x24,  0x25,  0x24,  0x25,  0xE4,  0x24,  0x04,  0x38,  0x04,  0x20,  0x04,  0x20,  0x04, 	/* 52060 */
+	0x20,  0x0C,  0x80,  0x00,  0x10,  0x3E,  0x10,  0x22,  0x10,  0x25,  0xFF,  0x29,  0x01,  0x29,  0x41,  0x24, 	/* 52070 */
+	0x40,  0x22,  0x44,  0x22,  0x58,  0x22,  0x60,  0x22,  0x40,  0x22,  0x40,  0x2C,  0x40,  0x20,  0x41,  0x20, 	/* 52080 */
+	0x21,  0x20,  0x1F,  0x82,  0x00,  0x10,  0x3C,  0x10,  0x24,  0x10,  0x25,  0xFF,  0x29,  0x12,  0x31,  0x14, 	/* 52090 */
+	0x29,  0x10,  0x29,  0xFC,  0x25,  0x44,  0x25,  0x44,  0x25,  0x28,  0x25,  0x28,  0x3A,  0x10,  0x22,  0x28, 	/* 520A0 */
+	0x24,  0xC4,  0x23,  0x03,  0x84,  0x00,  0x44,  0x3C,  0x44,  0x24,  0x44,  0x24,  0x84,  0x28,  0xFF,  0x30, 	/* 520B0 */
+	0x84,  0x29,  0x84,  0x26,  0xA4,  0x24,  0x94,  0x24,  0x94,  0x24,  0x84,  0x24,  0x84,  0x38,  0x84,  0x20, 	/* 520C0 */
+	0x84,  0x20,  0x84,  0x20,  0x8C,  0x8B,  0x00,  0x00,  0x3C,  0xFF,  0x24,  0x10,  0x29,  0x10,  0x29,  0x7E, 	/* 520D0 */
+	0x31,  0x52,  0x29,  0x52,  0x29,  0x5A,  0x25,  0x6A,  0x25,  0x66,  0x25,  0x42,  0x25,  0x42,  0x39,  0x46, 	/* 520E0 */
+	0x21,  0x00,  0x21,  0xFF,  0x20,  0x00,  0x8C,  0x00,  0x00,  0x3D,  0xFF,  0x24,  0x10,  0x24,  0x10,  0x28, 	/* 520F0 */
+	0x20,  0x30,  0xFE,  0x28,  0x82,  0x24,  0x82,  0x22,  0x82,  0x22,  0xFE,  0x22,  0x82,  0x32,  0x82,  0x2C, 	/* 52100 */
+	0x82,  0x20,  0x82,  0x20,  0xFE,  0x20,  0x00,  0x8D,  0x00,  0x20,  0x3C,  0x20,  0x24,  0x7C,  0x24,  0xC4, 	/* 52110 */
+	0x2B,  0x28,  0x30,  0x30,  0x28,  0xCC,  0x2B,  0x13,  0x24,  0x10,  0x25,  0xFE,  0x24,  0x90,  0x24,  0x90, 	/* 52120 */
+	0x3B,  0xFF,  0x20,  0x10,  0x20,  0x10,  0x20,  0x10,  0x8F,  0x00,  0x20,  0x3C,  0x20,  0x27,  0xFF,  0x24, 	/* 52130 */
+	0x20,  0x28,  0x20,  0x30,  0x7E,  0x28,  0x42,  0x24,  0xC2,  0x22,  0xFE,  0x23,  0x42,  0x22,  0x42,  0x32, 	/* 52140 */
+	0x7E,  0x2C,  0x42,  0x20,  0x42,  0x20,  0x42,  0x20,  0x46,  0x90,  0x00,  0x00,  0x3C,  0xFC,  0x24,  0x84, 	/* 52150 */
+	0x24,  0x84,  0x28,  0xFC,  0x30,  0x84,  0x28,  0x84,  0x24,  0xFE,  0x22,  0xA2,  0x22,  0x94,  0x22,  0x94, 	/* 52160 */
+	0x32,  0x88,  0x2C,  0x88,  0x20,  0xA4,  0x20,  0xC2,  0x23,  0x01,  0x9B,  0x01,  0x10,  0x3D,  0x10,  0x25, 	/* 52170 */
+	0x12,  0x25,  0xFC,  0x29,  0x10,  0x31,  0x10,  0x29,  0x11,  0x29,  0xCF,  0x27,  0x00,  0x24,  0x20,  0x24, 	/* 52180 */
+	0x20,  0x25,  0xFC,  0x38,  0x20,  0x20,  0x20,  0x27,  0xFF,  0x20,  0x00,  0x9C,  0x00,  0x20,  0x3C,  0x20, 	/* 52190 */
+	0x25,  0xFF,  0x28,  0x20,  0x28,  0xA4,  0x30,  0xA4,  0x28,  0xA4,  0x29,  0x6A,  0x25,  0x32,  0x26,  0x20, 	/* 521A0 */
+	0x24,  0x30,  0x24,  0x50,  0x38,  0x48,  0x20,  0x84,  0x23,  0x02,  0x2C,  0x01,  0x9D,  0x00,  0x20,  0x3C, 	/* 521B0 */
+	0x20,  0x27,  0xFF,  0x24,  0x20,  0x2B,  0x2C,  0x31,  0x24,  0x29,  0x24,  0x29,  0xA4,  0x25,  0x6A,  0x26, 	/* 521C0 */
+	0x31,  0x24,  0x50,  0x24,  0x50,  0x38,  0x88,  0x21,  0x04,  0x22,  0x02,  0x24,  0x01,  0x9E,  0x00,  0x24, 	/* 521D0 */
+	0x3C,  0x44,  0x25,  0xC4,  0x28,  0x44,  0x28,  0x44,  0x33,  0xFF,  0x28,  0x44,  0x28,  0x84,  0x24,  0x84, 	/* 521E0 */
+	0x25,  0x24,  0x24,  0x20,  0x25,  0xFE,  0x38,  0x20,  0x20,  0x20,  0x27,  0xFF,  0x20,  0x00,  0x9F,  0x00, 	/* 521F0 */
+	0x10,  0x3C,  0x90,  0x24,  0x9E,  0x28,  0x90,  0x28,  0x90,  0x33,  0xFF,  0x28,  0x10,  0x28,  0x50,  0x24, 	/* 52200 */
+	0x52,  0x24,  0x92,  0x25,  0x14,  0x24,  0x34,  0x38,  0x08,  0x20,  0x10,  0x20,  0x60,  0x23,  0x80,  0xA2, 	/* 52210 */
+	0x00,  0x10,  0x3C,  0x10,  0x25,  0xFF,  0x25,  0x01,  0x29,  0x01,  0x30,  0xFE,  0x28,  0x00,  0x24,  0x00, 	/* 52220 */
+	0x27,  0xFF,  0x24,  0x48,  0x24,  0x48,  0x34,  0x48,  0x28,  0x88,  0x20,  0x89,  0x21,  0x09,  0x22,  0x07, 	/* 52230 */
+	0xA3,  0x00,  0x20,  0x3C,  0x20,  0x27,  0xFF,  0x24,  0x20,  0x29,  0xFC,  0x31,  0x24,  0x29,  0x24,  0x25, 	/* 52240 */
+	0xFC,  0x25,  0x24,  0x25,  0x24,  0x25,  0xFC,  0x24,  0x20,  0x3B,  0xFF,  0x20,  0x20,  0x20,  0x20,  0x20, 	/* 52250 */
+	0x20,  0xA4,  0x00,  0x20,  0x3C,  0x20,  0x24,  0x50,  0x24,  0x50,  0x28,  0x88,  0x31,  0x04,  0x2A,  0xFA, 	/* 52260 */
+	0x28,  0x21,  0x24,  0x20,  0x27,  0xFE,  0x24,  0x20,  0x24,  0xA8,  0x38,  0xA4,  0x21,  0x22,  0x22,  0x22, 	/* 52270 */
+	0x20,  0x60,  0xA5,  0x00,  0x20,  0x3C,  0x20,  0x24,  0x3C,  0x24,  0x44,  0x28,  0x48,  0x30,  0x88,  0x28, 	/* 52280 */
+	0x10,  0x29,  0x3E,  0x25,  0x22,  0x25,  0x22,  0x25,  0x3E,  0x25,  0x22,  0x39,  0x22,  0x21,  0x22,  0x21, 	/* 52290 */
+	0x3E,  0x21,  0x00,  0xA6,  0x00,  0x20,  0x3C,  0x20,  0x27,  0xFE,  0x24,  0x20,  0x29,  0xFC,  0x30,  0x20, 	/* 522A0 */
+	0x2B,  0xFF,  0x28,  0x40,  0x24,  0x44,  0x27,  0xFF,  0x24,  0x84,  0x24,  0xC4,  0x39,  0x24,  0x22,  0x24, 	/* 522B0 */
+	0x24,  0x04,  0x20,  0x0C,  0xAA,  0x00,  0x20,  0x3C,  0x20,  0x25,  0xFE,  0x24,  0x84,  0x28,  0x44,  0x28, 	/* 522C0 */
+	0x48,  0x38,  0x48,  0x25,  0xFF,  0x22,  0x00,  0x22,  0x00,  0x22,  0xFC,  0x22,  0x84,  0x3C,  0x84,  0x20, 	/* 522D0 */
+	0x84,  0x20,  0xFC,  0x20,  0x00,  0xAC,  0x00,  0x00,  0x3F,  0xFF,  0x2A,  0x40,  0x2A,  0x40,  0x2A,  0x7E, 	/* 522E0 */
+	0x33,  0xD2,  0x2A,  0x52,  0x2A,  0x54,  0x27,  0xD4,  0x26,  0x4C,  0x26,  0x48,  0x26,  0x48,  0x3B,  0xD4, 	/* 522F0 */
+	0x26,  0x54,  0x20,  0x62,  0x20,  0x41,  0xB0,  0x00,  0x20,  0x3C,  0x20,  0x24,  0x50,  0x24,  0x88,  0x29, 	/* 52300 */
+	0x74,  0x32,  0x03,  0x29,  0xF8,  0x24,  0x10,  0x24,  0x20,  0x25,  0xFC,  0x24,  0x00,  0x27,  0xFF,  0x38, 	/* 52310 */
+	0x50,  0x20,  0x88,  0x27,  0xFC,  0x20,  0x04,  0xB2,  0x00,  0x08,  0x3C,  0x30,  0x25,  0xE0,  0x24,  0x20, 	/* 52320 */
+	0x2B,  0xFE,  0x31,  0x24,  0x29,  0x24,  0x29,  0x24,  0x27,  0xFF,  0x25,  0x24,  0x25,  0x24,  0x27,  0xFE, 	/* 52330 */
+	0x38,  0x20,  0x20,  0x20,  0x27,  0xFF,  0x20,  0x00,  0xB3,  0x00,  0x20,  0x3C,  0x20,  0x27,  0xFF,  0x24, 	/* 52340 */
+	0x20,  0x29,  0xFC,  0x31,  0x24,  0x29,  0xFC,  0x25,  0x24,  0x25,  0x24,  0x25,  0xFC,  0x24,  0x70,  0x24, 	/* 52350 */
+	0xA8,  0x39,  0x24,  0x22,  0x22,  0x24,  0x21,  0x20,  0x20,  0xB5,  0x00,  0x20,  0x3C,  0x20,  0x25,  0xFE, 	/* 52360 */
+	0x24,  0x20,  0x27,  0xFF,  0x28,  0x50,  0x30,  0x52,  0x28,  0x8E,  0x27,  0x40,  0x24,  0x78,  0x24,  0x88, 	/* 52370 */
+	0x27,  0x50,  0x38,  0x20,  0x20,  0x50,  0x21,  0x8C,  0x26,  0x03,  0xB6,  0x00,  0x80,  0x3C,  0x80,  0x24, 	/* 52380 */
+	0xFE,  0x25,  0x42,  0x29,  0x42,  0x32,  0xFA,  0x29,  0x22,  0x26,  0x22,  0x27,  0xFE,  0x24,  0x22,  0x25, 	/* 52390 */
+	0x2A,  0x39,  0x2A,  0x21,  0xFA,  0x20,  0x02,  0x20,  0x04,  0x20,  0x18,  0xB7,  0x00,  0x40,  0x3C,  0x40, 	/* 523A0 */
+	0x24,  0x7E,  0x24,  0x42,  0x28,  0x82,  0x30,  0x82,  0x29,  0x0C,  0x28,  0x20,  0x24,  0x40,  0x25,  0x9E, 	/* 523B0 */
+	0x25,  0x02,  0x25,  0xCE,  0x39,  0x02,  0x21,  0x02,  0x21,  0xFE,  0x20,  0x00,  0xB8,  0x00,  0x20,  0x3C, 	/* 523C0 */
+	0x20,  0x25,  0xFC,  0x24,  0x20,  0x24,  0x20,  0x2B,  0xFF,  0x30,  0x90,  0x28,  0x92,  0x25,  0x2E,  0x22, 	/* 523D0 */
+	0x20,  0x22,  0x20,  0x23,  0xFE,  0x3C,  0x20,  0x20,  0x20,  0x23,  0xFF,  0x20,  0x00,  0xBA,  0x00,  0x20, 	/* 523E0 */
+	0x3C,  0x20,  0x24,  0x50,  0x24,  0x88,  0x29,  0x04,  0x33,  0xFE,  0x28,  0x21,  0x29,  0xFC,  0x25,  0x24, 	/* 523F0 */
+	0x25,  0x24,  0x25,  0xFC,  0x24,  0x20,  0x38,  0x50,  0x20,  0x88,  0x21,  0x04,  0x26,  0x03,  0xBD,  0x00, 	/* 52400 */
+	0x00,  0x3D,  0xF8,  0x25,  0x08,  0x25,  0xF8,  0x29,  0x08,  0x31,  0x08,  0x29,  0xF8,  0x24,  0x00,  0x27, 	/* 52410 */
+	0xFF,  0x24,  0x80,  0x25,  0xFE,  0x26,  0x52,  0x38,  0x92,  0x21,  0x22,  0x20,  0x44,  0x20,  0x98,  0x85, 	/* 52420 */
+	0x00,  0x00,  0x3D,  0xFC,  0x25,  0x24,  0x25,  0x24,  0x29,  0xFC,  0x31,  0x24,  0x29,  0x24,  0x25,  0xFC, 	/* 52430 */
+	0x24,  0x20,  0x27,  0xFE,  0x26,  0x22,  0x26,  0x2A,  0x3A,  0x36,  0x22,  0xE6,  0x22,  0x02,  0x22,  0x06, 	/* 52440 */
+	0x86,  0x00,  0x40,  0x3C,  0x40,  0x24,  0xFC,  0x25,  0x08,  0x2A,  0x90,  0x34,  0x60,  0x28,  0xD8,  0x27, 	/* 52450 */
+	0x87,  0x24,  0xA0,  0x25,  0xFE,  0x26,  0x20,  0x25,  0xFC,  0x38,  0x20,  0x20,  0x20,  0x23,  0xFF,  0x20, 	/* 52460 */
+	0x00,  0x88,  0x00,  0x00,  0x3D,  0xFC,  0x25,  0x24,  0x25,  0x24,  0x29,  0xFC,  0x31,  0x24,  0x29,  0x24, 	/* 52470 */
+	0x29,  0xFC,  0x24,  0x00,  0x27,  0xFF,  0x25,  0x44,  0x25,  0x28,  0x39,  0x10,  0x21,  0x08,  0x21,  0xC4, 	/* 52480 */
+	0x27,  0x03,  0x8A,  0x01,  0x08,  0x3C,  0x88,  0x24,  0x90,  0x27,  0xFF,  0x28,  0x40,  0x30,  0xA2,  0x2B, 	/* 52490 */
+	0x2A,  0x28,  0x5C,  0x24,  0x98,  0x27,  0x34,  0x24,  0x54,  0x24,  0x92,  0x3B,  0x11,  0x20,  0x10,  0x20, 	/* 524A0 */
+	0x20,  0x20,  0xC0,  0x8B,  0x00,  0x20,  0x3C,  0x20,  0x27,  0xFF,  0x24,  0x40,  0x28,  0xFE,  0x31,  0x10, 	/* 524B0 */
+	0x2A,  0xFF,  0x24,  0x00,  0x24,  0xFC,  0x24,  0x84,  0x24,  0xFC,  0x24,  0x84,  0x38,  0xFC,  0x20,  0x84, 	/* 524C0 */
+	0x20,  0x84,  0x20,  0x8C,  0x8D,  0x00,  0x10,  0x3C,  0x20,  0x25,  0xFC,  0x29,  0x04,  0x29,  0xFC,  0x31, 	/* 524D0 */
+	0x04,  0x29,  0x04,  0x29,  0xFC,  0x24,  0x00,  0x25,  0xFE,  0x24,  0x20,  0x25,  0xFC,  0x38,  0x20,  0x20, 	/* 524E0 */
+	0x20,  0x27,  0xFF,  0x20,  0x00,  0x8E,  0x01,  0x10,  0x3D,  0x12,  0x25,  0xFC,  0x25,  0x10,  0x29,  0x10, 	/* 524F0 */
+	0x31,  0x11,  0x29,  0xCF,  0x27,  0x20,  0x24,  0xFE,  0x24,  0x82,  0x24,  0x82,  0x24,  0xFE,  0x38,  0x82, 	/* 52500 */
+	0x20,  0x82,  0x20,  0xFE,  0x20,  0x00,  0x8F,  0x00,  0x08,  0x3D,  0x08,  0x24,  0xFF,  0x24,  0x90,  0x28, 	/* 52510 */
+	0x10,  0x30,  0x1E,  0x28,  0x32,  0x27,  0xB2,  0x24,  0xDE,  0x24,  0x92,  0x24,  0x9E,  0x24,  0x92,  0x38, 	/* 52520 */
+	0xD2,  0x21,  0x56,  0x22,  0x30,  0x24,  0x0F,  0x94,  0x00,  0x00,  0x3D,  0xFE,  0x24,  0x00,  0x24,  0xFC, 	/* 52530 */
+	0x28,  0x84,  0x30,  0xFC,  0x28,  0x00,  0x25,  0xFE,  0x25,  0x2A,  0x25,  0x2A,  0x25,  0x4E,  0x25,  0x82, 	/* 52540 */
+	0x39,  0xFE,  0x21,  0x12,  0x21,  0x12,  0x21,  0x16,  0x95,  0x00,  0x00,  0x3D,  0xFC,  0x25,  0x04,  0x25, 	/* 52550 */
+	0x04,  0x29,  0xFC,  0x30,  0x00,  0x29,  0xFC,  0x25,  0x04,  0x25,  0xFC,  0x25,  0x04,  0x25,  0xFC,  0x25, 	/* 52560 */
+	0x04,  0x39,  0xFC,  0x20,  0x98,  0x23,  0x04,  0x2C,  0x02,  0x97,  0x00,  0x20,  0x3C,  0x40,  0x25,  0xFC, 	/* 52570 */
+	0x29,  0x24,  0x29,  0x24,  0x31,  0xFC,  0x29,  0x24,  0x29,  0x24,  0x25,  0xFC,  0x24,  0x52,  0x24,  0x52, 	/* 52580 */
+	0x24,  0x55,  0x38,  0x9F,  0x20,  0x90,  0x21,  0x11,  0x26,  0x0F,  0x98,  0x00,  0xB8,  0x3C,  0x88,  0x24, 	/* 52590 */
+	0x88,  0x24,  0xF4,  0x29,  0x02,  0x32,  0xB9,  0x28,  0x88,  0x29,  0x04,  0x26,  0x02,  0x25,  0xFD,  0x25, 	/* 525A0 */
+	0x54,  0x25,  0x54,  0x39,  0x54,  0x21,  0x54,  0x27,  0xFF,  0x20,  0x00,  0x99,  0x00,  0x20,  0x3C,  0xA8, 	/* 525B0 */
+	0x24,  0xA4,  0x25,  0x22,  0x2E,  0x20,  0x31,  0xFC,  0x29,  0x04,  0x29,  0xFC,  0x25,  0x04,  0x25,  0xFC, 	/* 525C0 */
+	0x24,  0x20,  0x24,  0xA8,  0x38,  0xA4,  0x21,  0x22,  0x22,  0x22,  0x20,  0x60,  0x9B,  0x00,  0x80,  0x3C, 	/* 525D0 */
+	0xFE,  0x25,  0x22,  0x25,  0xB4,  0x2A,  0x48,  0x35,  0x58,  0x28,  0xA4,  0x25,  0xFA,  0x26,  0x01,  0x24, 	/* 525E0 */
+	0x00,  0x27,  0xFE,  0x38,  0x20,  0x21,  0x28,  0x21,  0x24,  0x22,  0x22,  0x20,  0x60,  0x9C,  0x00,  0x20, 	/* 525F0 */
+	0x3C,  0x20,  0x25,  0xFE,  0x24,  0x84,  0x28,  0x48,  0x37,  0xFF,  0x28,  0x00,  0x29,  0xFC,  0x25,  0x04, 	/* 52600 */
+	0x25,  0xFC,  0x25,  0x04,  0x25,  0xFC,  0x38,  0x20,  0x23,  0xFF,  0x20,  0x20,  0x20,  0x20,  0xA0,  0x00, 	/* 52610 */
+	0x06,  0x3C,  0x1A,  0x27,  0xE2,  0x25,  0x24,  0x28,  0x98,  0x31,  0xFE,  0x28,  0x02,  0x24,  0xFE,  0x24, 	/* 52620 */
+	0x02,  0x25,  0xFE,  0x24,  0x10,  0x25,  0x4A,  0x39,  0x49,  0x21,  0x41,  0x22,  0x25,  0x20,  0x1C,  0xA3, 	/* 52630 */
+	0x00,  0x20,  0x3D,  0x24,  0x24,  0xA8,  0x27,  0xFE,  0x28,  0x70,  0x30,  0xAC,  0x2B,  0x23,  0x25,  0x24, 	/* 52640 */
+	0x25,  0xC4,  0x25,  0x7F,  0x26,  0x54,  0x25,  0x94,  0x38,  0xFF,  0x21,  0x04,  0x22,  0x04,  0x24,  0x04, 	/* 52650 */
+	0xA7,  0x00,  0x3C,  0x3A,  0x24,  0x29,  0x24,  0x29,  0x7A,  0x28,  0x91,  0x34,  0x32,  0x2A,  0xDA,  0x2A, 	/* 52660 */
+	0x2C,  0x28,  0xCC,  0x2F,  0x1A,  0x29,  0x6A,  0x29,  0x09,  0x32,  0x88,  0x22,  0x70,  0x24,  0x20,  0x28, 	/* 52670 */
+	0x1F,  0xA8,  0x00,  0x10,  0x7A,  0xFF,  0x49,  0x20,  0x51,  0x3E,  0x54,  0x48,  0x62,  0xBF,  0x52,  0x00, 	/* 52680 */
+	0x50,  0x3E,  0x4F,  0x22,  0x49,  0x3E,  0x49,  0x22,  0x49,  0x3E,  0x71,  0x22,  0x42,  0xA6,  0x44,  0x60, 	/* 52690 */
+	0x48,  0x1F,  0xAA,  0x00,  0x20,  0x3C,  0x20,  0x24,  0x50,  0x28,  0x88,  0x29,  0x04,  0x32,  0xFA,  0x28, 	/* 526A0 */
+	0x01,  0x2B,  0xDE,  0x26,  0x52,  0x26,  0x52,  0x27,  0xDE,  0x25,  0x08,  0x39,  0x08,  0x21,  0x8C,  0x22, 	/* 526B0 */
+	0x52,  0x24,  0x20,  0xB0,  0x00,  0x00,  0x3D,  0xFE,  0x25,  0x02,  0x2D,  0xFE,  0x29,  0x02,  0x31,  0xFE, 	/* 526C0 */
+	0x28,  0x84,  0x28,  0x84,  0x27,  0x5A,  0x24,  0x84,  0x25,  0x4A,  0x27,  0xFF,  0x38,  0x00,  0x21,  0x52, 	/* 526D0 */
+	0x21,  0x49,  0x22,  0x49,  0xB1,  0x00,  0x06,  0x3D,  0xF8,  0x24,  0x94,  0x24,  0x92,  0x2D,  0xFD,  0x2A, 	/* 526E0 */
+	0x20,  0x2F,  0xFF,  0x24,  0xFC,  0x24,  0x04,  0x27,  0xFF,  0x24,  0x04,  0x38,  0xFC,  0x22,  0xA0,  0x22, 	/* 526F0 */
+	0x96,  0x24,  0x85,  0x28,  0x7C,  0xB2,  0x00,  0x20,  0x3C,  0x24,  0x24,  0xA2,  0x28,  0xA6,  0x29,  0x69, 	/* 52700 */
+	0x32,  0x31,  0x28,  0xFE,  0x2B,  0x90,  0x24,  0xFC,  0x24,  0x90,  0x24,  0xFC,  0x24,  0x90,  0x38,  0xFE, 	/* 52710 */
+	0x22,  0x92,  0x22,  0x4A,  0x24,  0x0C,  0xB4,  0x00,  0x88,  0x3C,  0x88,  0x27,  0xFF,  0x29,  0x28,  0x29, 	/* 52720 */
+	0x4F,  0x37,  0xF1,  0x28,  0x0F,  0x29,  0xE8,  0x25,  0x2F,  0x25,  0xE8,  0x25,  0x2F,  0x25,  0xE8,  0x39, 	/* 52730 */
+	0x2F,  0x21,  0x28,  0x21,  0x29,  0x21,  0x67,  0xB6,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x84, 	/* 52740 */
+	0x7F,  0xFF,  0x00,  0x84,  0x00,  0x84,  0x1F,  0xFC,  0x20,  0x84,  0x10,  0xC4,  0x09,  0xC8,  0x0A,  0xB0, 	/* 52750 */
+	0x0C,  0x90,  0x70,  0x8C,  0x00,  0x83,  0x01,  0x80,  0xB7,  0x08,  0x10,  0x08,  0x10,  0x7F,  0x10,  0x08, 	/* 52760 */
+	0xFE,  0x3E,  0x12,  0x01,  0xFF,  0x3E,  0x12,  0x00,  0xFE,  0x7F,  0x10,  0x08,  0x92,  0x2C,  0x5C,  0x2A, 	/* 52770 */
+	0x78,  0x2A,  0x54,  0x4B,  0x92,  0x08,  0x11,  0x18,  0x30,  0xB8,  0x08,  0x10,  0x08,  0x10,  0x7E,  0xFE, 	/* 52780 */
+	0x08,  0x12,  0x1C,  0xFF,  0x2A,  0x12,  0x48,  0xFE,  0x00,  0x10,  0x3E,  0x92,  0x00,  0x54,  0x7F,  0x5C, 	/* 52790 */
+	0x08,  0x38,  0x2A,  0x54,  0x29,  0x92,  0x49,  0x11,  0x18,  0x30,  0xB9,  0x04,  0x20,  0x04,  0x20,  0x08, 	/* 527A0 */
+	0x40,  0x1F,  0xFE,  0x10,  0x80,  0x30,  0x80,  0x50,  0x80,  0x1F,  0xFC,  0x10,  0x80,  0x10,  0x80,  0x1F, 	/* 527B0 */
+	0xFC,  0x10,  0x80,  0x10,  0x80,  0x10,  0x80,  0x1F,  0xFF,  0x00,  0x00,  0xBB,  0x08,  0x20,  0x08,  0x40, 	/* 527C0 */
+	0x1F,  0xFC,  0x10,  0x80,  0x3F,  0xF8,  0x50,  0x80,  0x1F,  0xF8,  0x10,  0x80,  0x1F,  0xFE,  0x00,  0x00, 	/* 527D0 */
+	0x3F,  0xF8,  0x04,  0x10,  0x03,  0x60,  0x01,  0x80,  0x06,  0x70,  0x78,  0x0F,  0xBC,  0x04,  0x20,  0x04, 	/* 527E0 */
+	0x20,  0x08,  0x40,  0x0F,  0xFC,  0x18,  0x40,  0x2F,  0xF8,  0x48,  0x40,  0x0F,  0xF8,  0x08,  0x40,  0x0F, 	/* 527F0 */
+	0xFC,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x80,  0x00,  0x80, 	/* 52800 */
+	0x04,  0x88,  0x04,  0x84,  0x08,  0xA2,  0x10,  0xA2,  0x61,  0xC0,  0x00,  0x90,  0x03,  0x20,  0x0F,  0xFE, 	/* 52810 */
+	0x78,  0x40,  0x0F,  0xFC,  0x08,  0x40,  0x0F,  0xFC,  0x08,  0x40,  0x0F,  0xFE,  0x00,  0x00,  0x81,  0x00, 	/* 52820 */
+	0x00,  0x1F,  0xFF,  0x11,  0x20,  0x11,  0x24,  0x11,  0x48,  0x12,  0x7E,  0x12,  0xC8,  0x17,  0x48,  0x1A, 	/* 52830 */
+	0x7E,  0x12,  0x48,  0x12,  0x48,  0x12,  0x7E,  0x22,  0x48,  0x22,  0x48,  0x42,  0x7F,  0x02,  0x00,  0x84, 	/* 52840 */
+	0x08,  0x24,  0x08,  0x24,  0x08,  0x28,  0x7F,  0xFF,  0x08,  0x48,  0x0A,  0xC8,  0x0B,  0x48,  0x0A,  0x7E, 	/* 52850 */
+	0x12,  0x48,  0x14,  0x48,  0x16,  0x7E,  0x25,  0x48,  0x29,  0x48,  0x4E,  0xC8,  0x38,  0xFF,  0x00,  0x40, 	/* 52860 */
+	0x85,  0x00,  0x24,  0x3F,  0x24,  0x12,  0x48,  0x12,  0x7F,  0x12,  0xC8,  0x12,  0x48,  0x7F,  0xC8,  0x0A, 	/* 52870 */
+	0x7E,  0x0A,  0x48,  0x0A,  0x48,  0x0A,  0x7E,  0x12,  0x48,  0x12,  0x48,  0x22,  0x48,  0x42,  0x7F,  0x06, 	/* 52880 */
+	0x40,  0x86,  0x08,  0x20,  0x08,  0x40,  0x0F,  0xFE,  0x18,  0x40,  0x1F,  0xFC,  0x28,  0x40,  0x4F,  0xFC, 	/* 52890 */
+	0x08,  0x40,  0x0F,  0xFE,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0xC0,  0x02,  0xA0,  0x0C,  0x98,  0x70,  0x87, 	/* 528A0 */
+	0x00,  0x80,  0x87,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x00,  0x1F,  0xFC,  0x10,  0x04,  0x1F,  0xFC,  0x12, 	/* 528B0 */
+	0x10,  0x12,  0x20,  0x17,  0xFE,  0x14,  0x20,  0x1F,  0xFC,  0x14,  0x20,  0x27,  0xFC,  0x24,  0x20,  0x47, 	/* 528C0 */
+	0xFE,  0x04,  0x00,  0x89,  0x10,  0x22,  0x10,  0x22,  0x1F,  0x44,  0x28,  0x7F,  0x28,  0xC8,  0x49,  0x48, 	/* 528D0 */
+	0x08,  0x48,  0x7F,  0x7E,  0x08,  0x48,  0x0C,  0x48,  0x14,  0x7E,  0x12,  0x48,  0x22,  0x48,  0x22,  0x48, 	/* 528E0 */
+	0x40,  0x7F,  0x00,  0x00,  0x8B,  0x04,  0x20,  0x08,  0x40,  0x1F,  0xFE,  0x30,  0x40,  0x5F,  0xFC,  0x10, 	/* 528F0 */
+	0x40,  0x1F,  0xFC,  0x10,  0x40,  0x1F,  0xFF,  0x00,  0x00,  0x3E,  0x3E,  0x22,  0x22,  0x22,  0x22,  0x23, 	/* 52900 */
+	0xE2,  0x20,  0x02,  0x20,  0x06,  0x8C,  0x0A,  0x24,  0x0A,  0x24,  0x0A,  0x48,  0x2A,  0x7F,  0x2A,  0xC8, 	/* 52910 */
+	0x2A,  0x48,  0x2E,  0xC8,  0x2B,  0x7E,  0x2A,  0x48,  0x2A,  0x48,  0x2A,  0x7E,  0x2A,  0x48,  0x2A,  0x48, 	/* 52920 */
+	0x2E,  0x48,  0x3A,  0x7F,  0x61,  0xC0,  0x8D,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x04,  0x24,  0x04, 	/* 52930 */
+	0x28,  0x08,  0x7F,  0x32,  0xC8,  0x0E,  0x48,  0x05,  0x7E,  0x09,  0x48,  0x1F,  0x48,  0x72,  0x7E,  0x02, 	/* 52940 */
+	0x48,  0x04,  0x48,  0x08,  0x7F,  0x10,  0x00,  0x8E,  0x00,  0x24,  0x3C,  0x24,  0x24,  0x48,  0x24,  0xFF, 	/* 52950 */
+	0x25,  0x88,  0x3E,  0x88,  0x24,  0x88,  0x24,  0xFE,  0x24,  0x88,  0x3C,  0x88,  0x24,  0xFE,  0x24,  0x88, 	/* 52960 */
+	0x26,  0x88,  0x38,  0x88,  0x60,  0xFF,  0x00,  0x00,  0x91,  0x08,  0x24,  0x08,  0x24,  0x7E,  0x28,  0x0A, 	/* 52970 */
+	0x7F,  0x0A,  0x48,  0x12,  0xC8,  0x11,  0xC8,  0x28,  0x7E,  0x08,  0x48,  0x7F,  0xC8,  0x0C,  0x7E,  0x1A, 	/* 52980 */
+	0x48,  0x19,  0x48,  0x28,  0x48,  0x48,  0x7F,  0x08,  0x00,  0x95,  0x00,  0x12,  0x3F,  0x92,  0x20,  0xA4, 	/* 52990 */
+	0x24,  0xBF,  0x3E,  0xE4,  0x24,  0xA4,  0x24,  0xA4,  0x3F,  0xBE,  0x24,  0xA4,  0x2E,  0xA4,  0x2A,  0xBE, 	/* 529A0 */
+	0x2A,  0xA4,  0x2E,  0xA4,  0x20,  0xA4,  0x20,  0xBF,  0x41,  0x80,  0x96,  0x00,  0x24,  0x3F,  0x24,  0x21, 	/* 529B0 */
+	0x48,  0x21,  0x7F,  0x3F,  0xC8,  0x09,  0x48,  0x08,  0x48,  0x3F,  0x7E,  0x29,  0x48,  0x29,  0x48,  0x3F, 	/* 529C0 */
+	0x7E,  0x0A,  0x48,  0x09,  0x48,  0x09,  0x48,  0x0F,  0xFF,  0x70,  0x80,  0x99,  0x09,  0x24,  0x12,  0x28, 	/* 529D0 */
+	0x3F,  0xFF,  0x52,  0x48,  0x1F,  0x7E,  0x12,  0x48,  0x1F,  0x7E,  0x12,  0x48,  0x1F,  0xFF,  0x00,  0x00, 	/* 529E0 */
+	0x3F,  0xF8,  0x02,  0x10,  0x01,  0x20,  0x00,  0xC0,  0x07,  0x30,  0x78,  0x0F,  0x9B,  0x10,  0x24,  0x1F, 	/* 529F0 */
+	0x24,  0x31,  0x48,  0x55,  0x7F,  0x55,  0xC8,  0x7D,  0x48,  0x11,  0x48,  0x26,  0x7E,  0x10,  0x48,  0x1F, 	/* 52A00 */
+	0x48,  0x31,  0x7E,  0x55,  0x48,  0x55,  0x48,  0x7D,  0x48,  0x11,  0x7F,  0x26,  0x40,  0x9C,  0x08,  0x22, 	/* 52A10 */
+	0x08,  0x22,  0x7F,  0x24,  0x12,  0x7F,  0x12,  0xC8,  0x1A,  0x48,  0x25,  0x48,  0x48,  0x7E,  0x08,  0x48, 	/* 52A20 */
+	0x7F,  0x48,  0x08,  0x7E,  0x1C,  0x48,  0x1A,  0x48,  0x29,  0x48,  0x48,  0x7F,  0x08,  0x00,  0xA2,  0x08, 	/* 52A30 */
+	0x24,  0x08,  0x24,  0x7F,  0x48,  0x26,  0x7F,  0x3A,  0xC8,  0x2B,  0x48,  0x36,  0x48,  0x3E,  0x7E,  0x08, 	/* 52A40 */
+	0x48,  0x7F,  0x48,  0x49,  0x7E,  0x55,  0x48,  0x7B,  0x48,  0x41,  0x48,  0x41,  0x7F,  0x43,  0x40,  0xA3, 	/* 52A50 */
+	0x12,  0x24,  0x7F,  0xA4,  0x12,  0x28,  0x12,  0x7F,  0x3F,  0x48,  0x25,  0xC8,  0x25,  0x48,  0x3F,  0x7E, 	/* 52A60 */
+	0x04,  0x48,  0x3F,  0xC8,  0x04,  0x7E,  0x7F,  0xC8,  0x0A,  0x48,  0x09,  0x48,  0x10,  0xFF,  0x60,  0x00, 	/* 52A70 */
+	0xA8,  0x00,  0x00,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x20,  0x82,  0x28,  0xA2,  0x24, 	/* 52A80 */
+	0x92,  0x24,  0x92,  0x20,  0x82,  0x28,  0xA2,  0x24,  0x92,  0x24,  0x92,  0x20,  0x82,  0x20,  0x82,  0x20, 	/* 52A90 */
+	0x06,  0xAA,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x80,  0x7F,  0xFE,  0x40,  0x82,  0x5C,  0xBA,  0x40,  0x82, 	/* 52AA0 */
+	0x1C,  0xB8,  0x00,  0x00,  0x1F,  0xF8,  0x00,  0x08,  0x0F,  0xF8,  0x00,  0x08,  0x00,  0x08,  0x1F,  0xF8, 	/* 52AB0 */
+	0x00,  0x00,  0xAB,  0x00,  0x00,  0x3F,  0xFC,  0x01,  0x00,  0x7F,  0xFE,  0x41,  0x02,  0x5D,  0x7A,  0x41, 	/* 52AC0 */
+	0x02,  0x1D,  0x78,  0x00,  0x00,  0x7F,  0xFE,  0x01,  0x00,  0x01,  0xC0,  0x01,  0x30,  0x01,  0x08,  0x01, 	/* 52AD0 */
+	0x00,  0x01,  0x00,  0xB0,  0x00,  0x00,  0x3F,  0xFC,  0x01,  0x00,  0x7F,  0xFE,  0x41,  0x02,  0x5D,  0x7A, 	/* 52AE0 */
+	0x41,  0x02,  0x1D,  0x78,  0x07,  0xE0,  0x04,  0x20,  0x08,  0x10,  0x1F,  0xE8,  0x61,  0x26,  0x02,  0x20, 	/* 52AF0 */
+	0x04,  0x20,  0x18,  0xC0,  0xB2,  0x00,  0x00,  0x3F,  0xFC,  0x01,  0x00,  0x7F,  0xFE,  0x41,  0x02,  0x5D, 	/* 52B00 */
+	0x7A,  0x41,  0x02,  0x1D,  0x78,  0x00,  0x00,  0x1F,  0xF8,  0x00,  0x00,  0x7F,  0xFE,  0x02,  0x40,  0x04, 	/* 52B10 */
+	0x30,  0x3F,  0xC8,  0x00,  0x04,  0xB6,  0x00,  0x00,  0x3F,  0xFC,  0x01,  0x00,  0x7F,  0xFE,  0x41,  0x02, 	/* 52B20 */
+	0x5D,  0x7A,  0x41,  0x02,  0x1D,  0x78,  0x02,  0x80,  0x04,  0x40,  0x1F,  0xF0,  0x60,  0x0E,  0x1F,  0xF0, 	/* 52B30 */
+	0x01,  0x10,  0x01,  0x60,  0x01,  0x00,  0xB7,  0x00,  0x00,  0x3F,  0xFC,  0x01,  0x00,  0x7F,  0xFE,  0x41, 	/* 52B40 */
+	0x02,  0x5F,  0x7A,  0x41,  0x02,  0x1F,  0x78,  0x00,  0x00,  0x3F,  0xFC,  0x21,  0x04,  0x21,  0x04,  0x3F, 	/* 52B50 */
+	0xFC,  0x21,  0x04,  0x3F,  0xFC,  0x00,  0x00,  0xB9,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x80,  0x7F,  0xFE, 	/* 52B60 */
+	0x40,  0x82,  0x5C,  0xBA,  0x4E,  0x9E,  0x08,  0x00,  0x0F,  0xFC,  0x10,  0x04,  0x1F,  0xC4,  0x28,  0x44, 	/* 52B70 */
+	0x4F,  0xD8,  0x08,  0x02,  0x08,  0x02,  0x07,  0xFE,  0xBB,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x80,  0x7F, 	/* 52B80 */
+	0xFE,  0x40,  0x82,  0x5E,  0xFA,  0x40,  0x82,  0x1E,  0xF8,  0x00,  0x00,  0x1F,  0xF8,  0x10,  0x88,  0x1F, 	/* 52B90 */
+	0xF8,  0x10,  0x88,  0x1F,  0xF9,  0x00,  0x81,  0x00,  0x7F,  0x80,  0x00,  0x00,  0x3F,  0xFC,  0x01,  0x00, 	/* 52BA0 */
+	0x7F,  0xFE,  0x41,  0x02,  0x5D,  0x7A,  0x41,  0x02,  0x1D,  0x78,  0x00,  0x00,  0x7F,  0xFE,  0x01,  0x00, 	/* 52BB0 */
+	0x3F,  0xFC,  0x22,  0x44,  0x22,  0x44,  0x22,  0x44,  0x20,  0x0C,  0x84,  0x00,  0x00,  0x3F,  0xFC,  0x00, 	/* 52BC0 */
+	0x80,  0x7F,  0xFE,  0x40,  0x82,  0x5C,  0xBA,  0x4E,  0x9E,  0x02,  0xA0,  0x04,  0x98,  0x1F,  0xF4,  0x64, 	/* 52BD0 */
+	0x12,  0x07,  0xF0,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x04,  0x30,  0x86,  0x00,  0x00,  0x3F,  0xFC, 	/* 52BE0 */
+	0x00,  0x80,  0x7F,  0xFE,  0x40,  0x82,  0x5C,  0xBA,  0x4E,  0x9E,  0x00,  0x04,  0x7C,  0x18,  0x09,  0xE0, 	/* 52BF0 */
+	0x1C,  0x20,  0x47,  0xFE,  0x24,  0x20,  0x19,  0xFC,  0x16,  0x00,  0x61,  0xFF,  0x87,  0x00,  0x00,  0x3F, 	/* 52C00 */
+	0xFC,  0x01,  0x00,  0x7F,  0xFE,  0x41,  0x02,  0x5D,  0x72,  0x4F,  0x3A,  0x01,  0x00,  0x1F,  0xFC,  0x10, 	/* 52C10 */
+	0x00,  0x1F,  0xF8,  0x10,  0x00,  0x1F,  0xFF,  0x24,  0x48,  0x27,  0x30,  0x5C,  0x0E,  0x88,  0x00,  0x00, 	/* 52C20 */
+	0x3F,  0xFC,  0x00,  0x80,  0x7F,  0xFE,  0x40,  0x82,  0x5C,  0xBA,  0x4E,  0x9E,  0x00,  0x20,  0x30,  0x20, 	/* 52C30 */
+	0x0B,  0xFF,  0x60,  0x20,  0x11,  0xFC,  0x05,  0x24,  0x09,  0x24,  0x11,  0x2C,  0x60,  0x20,  0x8A,  0x00, 	/* 52C40 */
+	0x00,  0x3F,  0xFC,  0x01,  0x00,  0x7F,  0xFE,  0x41,  0x02,  0x7D,  0x7A,  0x4F,  0x3E,  0x00,  0x00,  0x1F, 	/* 52C50 */
+	0xF8,  0x00,  0x00,  0x7F,  0xFE,  0x02,  0x48,  0x12,  0x48,  0x0A,  0x50,  0x7F,  0xFE,  0x00,  0x00,  0x8D, 	/* 52C60 */
+	0x00,  0x00,  0x3F,  0xFC,  0x00,  0x80,  0x7F,  0xFE,  0x40,  0x82,  0x5C,  0xBA,  0x4E,  0x9E,  0x04,  0x20, 	/* 52C70 */
+	0x0F,  0xFE,  0x18,  0x40,  0x2F,  0xFC,  0x48,  0x40,  0x0F,  0xFC,  0x08,  0x40,  0x0F,  0xFE,  0x00,  0x00, 	/* 52C80 */
+	0x8E,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x80,  0x7F,  0xFE,  0x40,  0x82,  0x5C,  0xBA,  0x0E,  0x9C,  0x00, 	/* 52C90 */
+	0x80,  0x1F,  0xF8,  0x04,  0x20,  0x7F,  0xFF,  0x01,  0x00,  0x3F,  0xFE,  0x06,  0x20,  0x03,  0xC0,  0x3C, 	/* 52CA0 */
+	0x38,  0x8F,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x80,  0x7F,  0xFE,  0x40,  0x82,  0x5E,  0xFA,  0x40,  0x82, 	/* 52CB0 */
+	0x1E,  0xBC,  0x02,  0x40,  0x3E,  0x7E,  0x02,  0x40,  0x3E,  0x7E,  0x07,  0x40,  0x7A,  0x7F,  0x04,  0x40, 	/* 52CC0 */
+	0x18,  0x40,  0x91,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x80,  0x7F,  0xFE,  0x40,  0x82,  0x5E,  0xFA,  0x40, 	/* 52CD0 */
+	0x82,  0x0E,  0xBC,  0x18,  0x20,  0x04,  0x3F,  0x60,  0x20,  0x11,  0xFC,  0x05,  0x04,  0x09,  0x04,  0x11, 	/* 52CE0 */
+	0xFC,  0x60,  0x00,  0x93,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x80,  0x7F,  0xFE,  0x40,  0x82,  0x5C,  0xB2, 	/* 52CF0 */
+	0x4E,  0x9E,  0x01,  0x00,  0x0E,  0x70,  0x08,  0x10,  0x0F,  0x70,  0x08,  0x10,  0x0F,  0xF2,  0x02,  0x42, 	/* 52D00 */
+	0x0C,  0x42,  0x70,  0x3E,  0x96,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x80,  0x7F,  0xFE,  0x40,  0x82,  0x5C, 	/* 52D10 */
+	0xFA,  0x40,  0x82,  0x1E,  0xBC,  0x08,  0x10,  0x7E,  0xFF,  0x0C,  0x30,  0x1A,  0x38,  0x19,  0x54,  0x28, 	/* 52D20 */
+	0x92,  0x49,  0x11,  0x08,  0x10,  0x99,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x80,  0x7F,  0xFE,  0x40,  0x82, 	/* 52D30 */
+	0x5E,  0xBA,  0x4F,  0x9E,  0x04,  0x20,  0x7F,  0xFE,  0x04,  0xA0,  0x0F,  0xF8,  0x08,  0x88,  0x7F,  0xFF, 	/* 52D40 */
+	0x01,  0x40,  0x06,  0x30,  0x78,  0x0F,  0x9C,  0x00,  0x00,  0x3F,  0xFC,  0x01,  0x00,  0x7F,  0xFE,  0x41, 	/* 52D50 */
+	0x02,  0x7D,  0x72,  0x5F,  0x3E,  0x01,  0x00,  0x08,  0x7C,  0x7F,  0x44,  0x08,  0x7C,  0x1C,  0x44,  0x1A, 	/* 52D60 */
+	0x7C,  0x29,  0x44,  0x48,  0x7C,  0x08,  0x00,  0x9E,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x80,  0x7F,  0xFE, 	/* 52D70 */
+	0x40,  0x82,  0x5C,  0xBA,  0x4E,  0x9E,  0x00,  0x00,  0x3E,  0xFC,  0x22,  0x04,  0x3E,  0xFC,  0x20,  0x00, 	/* 52D80 */
+	0x3E,  0xF8,  0x20,  0x48,  0x3E,  0x30,  0x21,  0xCE,  0xA4,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x80,  0x7F, 	/* 52D90 */
+	0xFE,  0x40,  0x82,  0x5E,  0xFA,  0x42,  0x82,  0x1C,  0xFC,  0x12,  0x24,  0x11,  0x44,  0x1F,  0xFC,  0x68, 	/* 52DA0 */
+	0x88,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x00,  0xA7,  0x00,  0x00,  0x3F,  0xFC,  0x01,  0x00, 	/* 52DB0 */
+	0x7F,  0xFE,  0x41,  0x02,  0x7D,  0x7A,  0x5F,  0x3E,  0x01,  0x40,  0x3F,  0x7E,  0x0A,  0x48,  0x04,  0xB0, 	/* 52DC0 */
+	0x7F,  0x2E,  0x0D,  0xFC,  0x16,  0x24,  0x64,  0x44,  0x0C,  0x98,  0xAA,  0x00,  0x00,  0x3F,  0xFC,  0x01, 	/* 52DD0 */
+	0x00,  0x7F,  0xFE,  0x41,  0x02,  0x5D,  0x7A,  0x41,  0x02,  0x18,  0x1C,  0x05,  0xE4,  0x60,  0x92,  0x11, 	/* 52DE0 */
+	0x7E,  0x00,  0x10,  0x07,  0xFF,  0x08,  0x10,  0x11,  0xFE,  0x60,  0x00,  0xB0,  0x00,  0x00,  0x3F,  0xFC, 	/* 52DF0 */
+	0x00,  0x80,  0x7F,  0xFE,  0x40,  0x82,  0x5E,  0xBA,  0x0F,  0x1C,  0x00,  0x20,  0x11,  0x20,  0x7F,  0xBF, 	/* 52E00 */
+	0x11,  0x64,  0x7F,  0xD4,  0x11,  0x08,  0x1F,  0x14,  0x11,  0x62,  0x13,  0x81,  0xB2,  0x00,  0x00,  0x3F, 	/* 52E10 */
+	0xFC,  0x01,  0x00,  0x7F,  0xFE,  0x41,  0x02,  0x7D,  0x7A,  0x5F,  0x3E,  0x01,  0x10,  0x3E,  0x3C,  0x22, 	/* 52E20 */
+	0x44,  0x3E,  0xA8,  0x08,  0x18,  0x2E,  0x64,  0x29,  0xFF,  0x2E,  0x44,  0x70,  0x7C,  0xB8,  0x00,  0x00, 	/* 52E30 */
+	0x3F,  0xFC,  0x01,  0x00,  0x7F,  0xFE,  0x41,  0x02,  0x7D,  0x7A,  0x0F,  0x3C,  0x12,  0x00,  0x7F,  0xBE, 	/* 52E40 */
+	0x12,  0x22,  0x3F,  0x3E,  0x25,  0x22,  0x3F,  0x3E,  0x04,  0x22,  0x7F,  0xC2,  0x04,  0x86,  0xB9,  0x00, 	/* 52E50 */
+	0x00,  0x3F,  0xFC,  0x00,  0x80,  0x7F,  0xFE,  0x40,  0x82,  0x5C,  0xBA,  0x4E,  0x9E,  0x00,  0x10,  0x1F, 	/* 52E60 */
+	0xFE,  0x11,  0x44,  0x1F,  0x28,  0x10,  0xFF,  0x2F,  0x10,  0x29,  0x7E,  0x4F,  0x10,  0x00,  0x10,  0xBD, 	/* 52E70 */
+	0x00,  0x00,  0x3F,  0xFC,  0x00,  0x80,  0x7F,  0xFE,  0x40,  0x82,  0x5C,  0xBA,  0x00,  0x80,  0x7F,  0xFE, 	/* 52E80 */
+	0x02,  0x44,  0x7D,  0xB8,  0x24,  0xA4,  0x4C,  0xB2,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x10,  0x10, 	/* 52E90 */
+	0xBE,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x80,  0x7F,  0xFE,  0x40,  0x82,  0x5C,  0xBA,  0x4E,  0x9C,  0x08, 	/* 52EA0 */
+	0x00,  0x72,  0xFC,  0x2C,  0xA4,  0x70,  0xFC,  0x18,  0xA4,  0x6D,  0xFE,  0x14,  0x20,  0x67,  0xFF,  0x18, 	/* 52EB0 */
+	0x00,  0x82,  0x00,  0x00,  0x3F,  0xFC,  0x01,  0x00,  0x7F,  0xFE,  0x41,  0x02,  0x5D,  0x7A,  0x00,  0x00, 	/* 52EC0 */
+	0x1F,  0xFE,  0x17,  0x38,  0x12,  0x10,  0x1F,  0xFE,  0x17,  0x34,  0x1A,  0xD2,  0x24,  0x7C,  0x24,  0x40, 	/* 52ED0 */
+	0x5F,  0xFF,  0x84,  0x00,  0x00,  0x3F,  0xFC,  0x01,  0x00,  0x7F,  0xFE,  0x41,  0x02,  0x5D,  0x7A,  0x01, 	/* 52EE0 */
+	0x00,  0x3E,  0x7C,  0x00,  0x44,  0x7F,  0x7C,  0x00,  0x20,  0x3E,  0xFE,  0x01,  0x52,  0x3E,  0x6A,  0x22, 	/* 52EF0 */
+	0x7A,  0x3E,  0x0C,  0x86,  0x00,  0x08,  0x7F,  0x08,  0x08,  0xBE,  0x7F,  0x4A,  0x49,  0x7F,  0x6D,  0x0A, 	/* 52F00 */
+	0x49,  0xBE,  0x2C,  0x49,  0x00,  0x4E,  0x3E,  0x2C,  0x01,  0xDA,  0x7F,  0x6A,  0x08,  0x49,  0x14,  0x58, 	/* 52F10 */
+	0x7A,  0xA0,  0x03,  0x1F,  0x88,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x80,  0x7F,  0xFE,  0x40,  0x82,  0x5C, 	/* 52F20 */
+	0xBA,  0x4E,  0x9C,  0x00,  0x00,  0x7B,  0xDE,  0x4A,  0x52,  0x7B,  0xDE,  0x00,  0x00,  0x3F,  0xFC,  0x08, 	/* 52F30 */
+	0x90,  0x14,  0xA8,  0x7F,  0xFF,  0x89,  0x00,  0x02,  0x7F,  0x3C,  0x08,  0x4A,  0x7F,  0x24,  0x49,  0xFF, 	/* 52F40 */
+	0x6D,  0x91,  0x49,  0x2A,  0x2C,  0xA5,  0x01,  0x1D,  0x3E,  0x10,  0x00,  0x3C,  0x7F,  0x44,  0x08,  0xA8, 	/* 52F50 */
+	0x14,  0x18,  0x7A,  0x64,  0x03,  0x83,  0x92,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFE,  0x00,  0x80,  0x1F, 	/* 52F60 */
+	0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x07,  0xF8,  0x04,  0x08,  0x07,  0xF8,  0x04,  0x08,  0x07, 	/* 52F70 */
+	0xF8,  0x04,  0x08,  0x04,  0x08,  0x04,  0x18,  0x96,  0x00,  0x10,  0x08,  0x10,  0x09,  0xFE,  0x08,  0x10, 	/* 52F80 */
+	0x7F,  0xFC,  0x02,  0x10,  0x23,  0xFF,  0x12,  0x00,  0x12,  0xFC,  0x14,  0x84,  0x14,  0xFC,  0x0B,  0x84, 	/* 52F90 */
+	0x1C,  0xFC,  0x60,  0x84,  0x00,  0x84,  0x00,  0x8C,  0x99,  0x08,  0x20,  0x08,  0x38,  0x7F,  0x48,  0x08, 	/* 52FA0 */
+	0x90,  0x3F,  0x20,  0x08,  0xFC,  0x7F,  0x24,  0x00,  0x24,  0x3F,  0xFF,  0x22,  0x24,  0x3E,  0x24,  0x22, 	/* 52FB0 */
+	0xFC,  0x3E,  0x20,  0x22,  0x20,  0x22,  0x20,  0x26,  0x60,  0x9C,  0x08,  0x04,  0x08,  0xF8,  0x7F,  0x64, 	/* 52FC0 */
+	0x08,  0x52,  0x3E,  0x92,  0x09,  0x02,  0x7F,  0xFC,  0x00,  0x14,  0x3E,  0xFF,  0x2A,  0x14,  0x2A,  0x14, 	/* 52FD0 */
+	0x3E,  0xFC,  0x22,  0x10,  0x22,  0x10,  0x22,  0x10,  0x26,  0x30,  0x9E,  0x02,  0x20,  0x02,  0x20,  0x02, 	/* 52FE0 */
+	0x20,  0x3E,  0x3E,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x3E,  0x3E,  0x02,  0x20,  0x02,  0x20,  0x0E, 	/* 52FF0 */
+	0x20,  0x72,  0x3F,  0x04,  0x20,  0x04,  0x20,  0x08,  0x20,  0x10,  0x20,  0xA0,  0x08,  0x80,  0x0F,  0xFC, 	/* 53000 */
+	0x10,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x01,  0x20,  0x3F,  0x3E, 	/* 53010 */
+	0x01,  0x20,  0x3F,  0x3E,  0x03,  0xA0,  0x7E,  0x3F,  0x04,  0x20,  0x18,  0x20,  0xA1,  0x00,  0x80,  0x1F, 	/* 53020 */
+	0xFF,  0x11,  0x08,  0x1F,  0xFF,  0x11,  0x4A,  0x15,  0x5A,  0x15,  0x5B,  0x19,  0x28,  0x10,  0xA0,  0x1F, 	/* 53030 */
+	0xBE,  0x10,  0xA0,  0x17,  0xBC,  0x20,  0xA0,  0x3F,  0x3F,  0x41,  0x20,  0x02,  0x20,  0xA2,  0x00,  0x00, 	/* 53040 */
+	0x7F,  0xFF,  0x01,  0x00,  0x01,  0x00,  0x02,  0x00,  0x3F,  0xFE,  0x22,  0x22,  0x22,  0x22,  0x23,  0xE2, 	/* 53050 */
+	0x22,  0x22,  0x23,  0xE2,  0x22,  0x22,  0x22,  0x22,  0x22,  0x22,  0x3F,  0xFE,  0x00,  0x00,  0xA4,  0x00, 	/* 53060 */
+	0x20,  0x7F,  0x20,  0x08,  0x7E,  0x08,  0x42,  0x10,  0x82,  0x7F,  0xF2,  0x55,  0x52,  0x55,  0x52,  0x5D, 	/* 53070 */
+	0x52,  0x55,  0x72,  0x55,  0x42,  0x5D,  0x4C,  0x55,  0x40,  0x55,  0x41,  0x7F,  0x21,  0x00,  0x1F,  0xA6, 	/* 53080 */
+	0x00,  0x00,  0x7F,  0xFE,  0x04,  0x22,  0x04,  0x22,  0x08,  0x3E,  0x3F,  0xA2,  0x2A,  0xA2,  0x2A,  0xBE, 	/* 53090 */
+	0x2E,  0xA2,  0x2A,  0xA2,  0x2A,  0xBE,  0x2E,  0x94,  0x2A,  0x94,  0x2A,  0xA5,  0x3F,  0xC5,  0x00,  0x83, 	/* 530A0 */
+	0xA8,  0x00,  0x00,  0x1F,  0xFF,  0x18,  0x94,  0x1F,  0x92,  0x14,  0xFF,  0x17,  0x98,  0x24,  0x94,  0x27, 	/* 530B0 */
+	0xA2,  0x44,  0xC0,  0x7F,  0xFF,  0x01,  0x00,  0x1F,  0xFC,  0x13,  0xE4,  0x12,  0x24,  0x1F,  0xFC,  0x00, 	/* 530C0 */
+	0x00,  0xA9,  0x02,  0x20,  0x02,  0x20,  0x3F,  0xFE,  0x02,  0x20,  0x02,  0x20,  0x03,  0xE0,  0x00,  0x80, 	/* 530D0 */
+	0x0F,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x00,  0x80, 	/* 530E0 */
+	0x00,  0x80,  0xAB,  0x12,  0x00,  0x12,  0x7E,  0x7F,  0x82,  0x12,  0x32,  0x12,  0x2A,  0x1E,  0x2A,  0x08, 	/* 530F0 */
+	0x22,  0x3F,  0x24,  0x29,  0x14,  0x29,  0x18,  0x3F,  0x08,  0x08,  0x18,  0x7F,  0x94,  0x08,  0x24,  0x08, 	/* 53100 */
+	0xC2,  0x0B,  0x01,  0xAD,  0x12,  0x00,  0x12,  0xFE,  0x7F,  0x92,  0x12,  0x12,  0x12,  0x12,  0x1E,  0x12, 	/* 53110 */
+	0x08,  0x72,  0x3F,  0x1A,  0x29,  0x16,  0x29,  0x12,  0x3F,  0x12,  0x08,  0x22,  0x7F,  0xA2,  0x08,  0x42, 	/* 53120 */
+	0x08,  0x84,  0x09,  0x18,  0xB1,  0x12,  0x00,  0x12,  0xFE,  0x7F,  0x12,  0x12,  0x12,  0x12,  0x52,  0x1E, 	/* 53130 */
+	0x32,  0x08,  0x12,  0x3F,  0x1A,  0x29,  0x16,  0x29,  0x13,  0x3F,  0x12,  0x08,  0x22,  0x7F,  0xA2,  0x08, 	/* 53140 */
+	0x42,  0x08,  0x82,  0x09,  0x0C,  0xB4,  0x12,  0x30,  0x12,  0x30,  0x7F,  0xB0,  0x12,  0x52,  0x12,  0x52, 	/* 53150 */
+	0x1E,  0x54,  0x08,  0xD8,  0x3F,  0x50,  0x29,  0x50,  0x29,  0x50,  0x3F,  0x50,  0x08,  0x51,  0x7F,  0xD1, 	/* 53160 */
+	0x08,  0x51,  0x08,  0x4F,  0x08,  0x40,  0xB9,  0x12,  0x30,  0x12,  0x10,  0x7F,  0x90,  0x12,  0x7E,  0x12, 	/* 53170 */
+	0x52,  0x1E,  0x52,  0x08,  0x52,  0x3F,  0x52,  0x29,  0x6A,  0x29,  0x6A,  0x3F,  0x46,  0x08,  0x42,  0x7F, 	/* 53180 */
+	0x42,  0x08,  0x42,  0x08,  0x42,  0x08,  0x46,  0xBA,  0x12,  0x10,  0x12,  0x10,  0x7F,  0x90,  0x12,  0xFF, 	/* 53190 */
+	0x12,  0x10,  0x1E,  0x10,  0x08,  0x10,  0x3F,  0x7E,  0x29,  0x10,  0x29,  0x38,  0x3F,  0x38,  0x08,  0x54, 	/* 531A0 */
+	0x7F,  0xD2,  0x08,  0x91,  0x09,  0x10,  0x08,  0x10,  0xBC,  0x12,  0x00,  0x12,  0x3E,  0x7F,  0xA2,  0x12, 	/* 531B0 */
+	0x22,  0x12,  0x22,  0x1E,  0x3E,  0x08,  0x22,  0x3F,  0x22,  0x29,  0x22,  0x29,  0x22,  0x3F,  0x3E,  0x08, 	/* 531C0 */
+	0x00,  0x7F,  0x80,  0x08,  0x00,  0x08,  0xFF,  0x08,  0x00,  0x81,  0x14,  0x10,  0x14,  0x10,  0x7F,  0x10, 	/* 531D0 */
+	0x14,  0xFF,  0x14,  0x91,  0x1C,  0x92,  0x08,  0x90,  0x3E,  0xFE,  0x2A,  0xA2,  0x2A,  0xA2,  0x3E,  0x94, 	/* 531E0 */
+	0x08,  0x98,  0x7F,  0x88,  0x09,  0x14,  0x09,  0x22,  0x0A,  0xC1,  0x84,  0x12,  0x20,  0x12,  0x20,  0x7F, 	/* 531F0 */
+	0x20,  0x12,  0x7E,  0x12,  0x42,  0x1E,  0x7A,  0x08,  0x8A,  0x3F,  0x0A,  0x29,  0x7A,  0x29,  0x42,  0x3F, 	/* 53200 */
+	0x42,  0x08,  0x4C,  0x7F,  0xC0,  0x08,  0x41,  0x08,  0x41,  0x08,  0x3F,  0x85,  0x12,  0x10,  0x12,  0x10, 	/* 53210 */
+	0x7F,  0x90,  0x12,  0x7E,  0x12,  0x52,  0x1E,  0x52,  0x08,  0x52,  0x3F,  0x52,  0x29,  0xFF,  0x29,  0x10, 	/* 53220 */
+	0x3F,  0x18,  0x08,  0x28,  0x7F,  0x24,  0x08,  0x44,  0x08,  0x82,  0x09,  0x01,  0x86,  0x12,  0x00,  0x12, 	/* 53230 */
+	0xFF,  0x7F,  0x90,  0x12,  0x10,  0x12,  0x10,  0x1E,  0x7E,  0x08,  0x52,  0x3F,  0x52,  0x29,  0x52,  0x29, 	/* 53240 */
+	0x6A,  0x3F,  0x6A,  0x08,  0x46,  0x7F,  0x42,  0x08,  0x42,  0x08,  0x42,  0x08,  0x46,  0x8B,  0x12,  0x08, 	/* 53250 */
+	0x12,  0x08,  0x7F,  0xBE,  0x12,  0x08,  0x12,  0x08,  0x1E,  0x08,  0x08,  0xFF,  0x3F,  0x00,  0x29,  0x08, 	/* 53260 */
+	0x29,  0x08,  0x3F,  0x7E,  0x08,  0x08,  0x7F,  0x08,  0x08,  0x08,  0x08,  0xFF,  0x08,  0x00,  0x8D,  0x12, 	/* 53270 */
+	0x10,  0x12,  0x10,  0x7F,  0xFE,  0x12,  0x82,  0x12,  0xA2,  0x1E,  0x20,  0x08,  0x20,  0x3F,  0xFF,  0x29, 	/* 53280 */
+	0x24,  0x29,  0x24,  0x3F,  0x44,  0x08,  0x68,  0x7F,  0x98,  0x08,  0x24,  0x08,  0x42,  0x09,  0x82,  0x8F, 	/* 53290 */
+	0x00,  0x00,  0x7F,  0x7C,  0x08,  0x44,  0x08,  0x65,  0x0E,  0x55,  0x70,  0x93,  0x02,  0x21,  0x3F,  0xFE, 	/* 532A0 */
+	0x02,  0x20,  0x03,  0xE0,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80, 	/* 532B0 */
+	0x90,  0x12,  0x10,  0x12,  0x10,  0x7F,  0x90,  0x12,  0x1E,  0x12,  0x10,  0x1E,  0x10,  0x08,  0xFF,  0x3F, 	/* 532C0 */
+	0x00,  0x29,  0x00,  0x29,  0xFF,  0x3F,  0x10,  0x08,  0x18,  0x7F,  0x94,  0x08,  0x12,  0x08,  0x10,  0x08, 	/* 532D0 */
+	0x10,  0x98,  0x12,  0x10,  0x12,  0x92,  0x7F,  0x52,  0x12,  0x54,  0x1E,  0x10,  0x08,  0x7E,  0x3F,  0x42, 	/* 532E0 */
+	0x29,  0x42,  0x29,  0x7E,  0x3F,  0x42,  0x08,  0x42,  0x7F,  0xFE,  0x08,  0x42,  0x08,  0x42,  0x08,  0x42, 	/* 532F0 */
+	0x08,  0x46,  0x9C,  0x12,  0x10,  0x12,  0x12,  0x7F,  0xFC,  0x12,  0x38,  0x12,  0x34,  0x1E,  0x52,  0x08, 	/* 53300 */
+	0x91,  0x3F,  0x30,  0x29,  0x00,  0x29,  0x7C,  0x3F,  0x44,  0x08,  0x44,  0x7F,  0x7C,  0x08,  0x44,  0x08, 	/* 53310 */
+	0x7C,  0x08,  0x00,  0xA0,  0x14,  0x40,  0x14,  0x40,  0x7E,  0xFE,  0x14,  0x82,  0x15,  0x2A,  0x1E,  0xAA, 	/* 53320 */
+	0x08,  0xB2,  0x3F,  0xFE,  0x2A,  0x22,  0x2A,  0x72,  0x3E,  0x6A,  0x08,  0xA6,  0x7F,  0xA2,  0x09,  0x22, 	/* 53330 */
+	0x08,  0x24,  0x08,  0x18,  0xA3,  0x14,  0x00,  0x14,  0x7E,  0x7F,  0x24,  0x14,  0x18,  0x15,  0xFF,  0x1C, 	/* 53340 */
+	0x32,  0x08,  0x54,  0x3E,  0x90,  0x2A,  0x30,  0x2A,  0x10,  0x3F,  0xFF,  0x08,  0x38,  0x7F,  0x54,  0x08, 	/* 53350 */
+	0x92,  0x09,  0x11,  0x08,  0x10,  0xA6,  0x14,  0x28,  0x14,  0xC8,  0x7F,  0x88,  0x14,  0x8A,  0x14,  0x8A, 	/* 53360 */
+	0x1D,  0xFC,  0x08,  0x9C,  0x3E,  0xD8,  0x2A,  0xC8,  0x2B,  0xAC,  0x3E,  0x94,  0x08,  0x94,  0x7F,  0xA4, 	/* 53370 */
+	0x08,  0xA2,  0x08,  0xC2,  0x08,  0x81,  0xA8,  0x12,  0x00,  0x12,  0x7C,  0x7F,  0x44,  0x12,  0x7C,  0x12, 	/* 53380 */
+	0x44,  0x1E,  0x44,  0x08,  0x7C,  0x3F,  0x20,  0x29,  0x3E,  0x29,  0x52,  0x3F,  0xDA,  0x08,  0x6A,  0x7F, 	/* 53390 */
+	0x42,  0x08,  0x7A,  0x08,  0x02,  0x08,  0x0C,  0xAB,  0x14,  0x40,  0x14,  0x40,  0x7E,  0xFE,  0x14,  0x82, 	/* 533A0 */
+	0x15,  0x7A,  0x1C,  0x02,  0x08,  0xFE,  0x3E,  0x02,  0x2A,  0x7A,  0x2A,  0x02,  0x3E,  0x7A,  0x08,  0x02, 	/* 533B0 */
+	0x7F,  0x7A,  0x08,  0x4A,  0x08,  0x7A,  0x08,  0x0C,  0xAD,  0x14,  0x40,  0x14,  0x7F,  0x7F,  0x48,  0x14, 	/* 533C0 */
+	0x7E,  0x14,  0xAA,  0x1C,  0xAA,  0x09,  0xBE,  0x3E,  0xAA,  0x2A,  0xAA,  0x2A,  0xBE,  0x3E,  0x88,  0x08, 	/* 533D0 */
+	0xA8,  0x7F,  0x98,  0x08,  0x94,  0x08,  0xA2,  0x08,  0xC1,  0xB3,  0x14,  0x44,  0x14,  0x44,  0x7F,  0xFF, 	/* 533E0 */
+	0x14,  0x54,  0x14,  0x10,  0x1C,  0x28,  0x08,  0x44,  0x3E,  0xFA,  0x2B,  0x01,  0x2A,  0x00,  0x3E,  0xFC, 	/* 533F0 */
+	0x08,  0x84,  0x7F,  0x84,  0x08,  0x84,  0x08,  0xFC,  0x08,  0x00,  0xB4,  0x14,  0x24,  0x14,  0x24,  0x7F, 	/* 53400 */
+	0xFF,  0x14,  0x24,  0x14,  0x00,  0x1C,  0xFF,  0x08,  0x80,  0x3E,  0xFE,  0x2A,  0xD2,  0x2A,  0xFE,  0x3E, 	/* 53410 */
+	0xD2,  0x08,  0xD2,  0x7F,  0x7E,  0x09,  0x52,  0x0A,  0x52,  0x08,  0x56,  0x83,  0x14,  0x08,  0x15,  0x08, 	/* 53420 */
+	0x7E,  0xBE,  0x14,  0x88,  0x14,  0x7F,  0x1D,  0x22,  0x08,  0x94,  0x3E,  0xFE,  0x2A,  0x08,  0x2B,  0xBE, 	/* 53430 */
+	0x3E,  0x88,  0x08,  0xFF,  0x7E,  0x88,  0x09,  0x48,  0x09,  0x30,  0x0A,  0x0F,  0x86,  0x14,  0x00,  0x15, 	/* 53440 */
+	0x7F,  0x7E,  0x94,  0x14,  0xBE,  0x14,  0x2A,  0x1D,  0x3E,  0x08,  0x90,  0x3E,  0xFF,  0x2A,  0x14,  0x2B, 	/* 53450 */
+	0xBE,  0x3E,  0xC5,  0x08,  0x9C,  0x7E,  0x92,  0x09,  0x4E,  0x09,  0x30,  0x0A,  0x0F,  0x88,  0x14,  0x44, 	/* 53460 */
+	0x14,  0x44,  0x7F,  0xFF,  0x14,  0x44,  0x14,  0xFE,  0x1C,  0xAA,  0x08,  0xFE,  0x3E,  0x0C,  0x2A,  0x0A, 	/* 53470 */
+	0x2A,  0xFF,  0x3E,  0x88,  0x08,  0xCA,  0x7F,  0xA4,  0x08,  0xAD,  0x09,  0x13,  0x0A,  0x21,  0x8B,  0x01, 	/* 53480 */
+	0x00,  0x1F,  0xF8,  0x02,  0x08,  0x02,  0x08,  0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F, 	/* 53490 */
+	0xF8,  0x00,  0x20,  0x0F,  0xFE,  0x08,  0x20,  0x08,  0x20,  0x7F,  0xFF,  0x00,  0x20,  0x00,  0x20,  0x93, 	/* 534A0 */
+	0x08,  0x10,  0x08,  0xFC,  0x7F,  0x24,  0x08,  0x24,  0x3F,  0xFF,  0x22,  0x00,  0x22,  0xFC,  0x3E,  0x84, 	/* 534B0 */
+	0x22,  0xFE,  0x22,  0x08,  0x3E,  0x7E,  0x08,  0x48,  0x7F,  0x48,  0x09,  0xFF,  0x08,  0x08,  0x08,  0x08, 	/* 534C0 */
+	0x9C,  0x04,  0x02,  0x3F,  0x0C,  0x09,  0x74,  0x09,  0x52,  0x7F,  0xC9,  0x00,  0x89,  0x1F,  0x00,  0x11, 	/* 534D0 */
+	0x10,  0x1F,  0x66,  0x02,  0x42,  0x1F,  0xC2,  0x12,  0x76,  0x12,  0x42,  0x7F,  0xC2,  0x02,  0x7E,  0x02, 	/* 534E0 */
+	0x00,  0xAD,  0x02,  0x20,  0x02,  0x20,  0x3E,  0x3E,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x3E,  0x3E, 	/* 534F0 */
+	0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x3E,  0x3E,  0x02,  0x20,  0x02,  0x20,  0x02,  0x20,  0x7F,  0xFF, 	/* 53500 */
+	0x00,  0x00,  0xAE,  0x02,  0x20,  0x02,  0x20,  0x7F,  0xFF,  0x02,  0x20,  0x00,  0x00,  0x02,  0x20,  0x3E, 	/* 53510 */
+	0x3E,  0x02,  0x20,  0x3E,  0x3E,  0x02,  0x20,  0x02,  0x20,  0x3E,  0x3E,  0x02,  0x20,  0x02,  0x20,  0x7F, 	/* 53520 */
+	0xFF,  0x00,  0x00,  0xB2,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0x22,  0x7D,  0x5C,  0x14,  0x94,  0x24,  0x92, 	/* 53530 */
+	0x4C,  0x19,  0x01,  0x20,  0x3F,  0x3E,  0x01,  0x20,  0x1F,  0x3C,  0x01,  0x20,  0x1F,  0x3C,  0x01,  0x20, 	/* 53540 */
+	0x7F,  0xFF,  0x00,  0x00,  0xB3,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x04,  0x10,  0x02,  0x10,  0x02, 	/* 53550 */
+	0x20,  0x7F,  0xFF,  0x00,  0x00,  0x07,  0xF0,  0x04,  0x10,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x04, 	/* 53560 */
+	0x10,  0x07,  0xF0,  0x00,  0x00,  0xB5,  0x08,  0x20,  0x08,  0x20,  0x7F,  0xA0,  0x22,  0x3E,  0x12,  0x42, 	/* 53570 */
+	0x14,  0x42,  0x7F,  0xBA,  0x00,  0x02,  0x3E,  0x02,  0x22,  0x0A,  0x22,  0x32,  0x3E,  0xC2,  0x22,  0x02, 	/* 53580 */
+	0x22,  0x02,  0x3E,  0x04,  0x00,  0x18,  0xB6,  0x08,  0x00,  0x08,  0xFE,  0x7F,  0x12,  0x22,  0x12,  0x12, 	/* 53590 */
+	0x12,  0x14,  0x22,  0x7F,  0xA2,  0x00,  0x4C,  0x3E,  0x80,  0x22,  0x7E,  0x22,  0x42,  0x3E,  0x42,  0x22, 	/* 535A0 */
+	0x42,  0x22,  0x42,  0x3E,  0x7E,  0x00,  0x00,  0xBB,  0x08,  0x00,  0x08,  0xFC,  0x7F,  0x84,  0x22,  0x84, 	/* 535B0 */
+	0x12,  0xFC,  0x14,  0x00,  0x7F,  0xFC,  0x00,  0x84,  0x3E,  0xFC,  0x22,  0x84,  0x22,  0xFC,  0x3E,  0x84, 	/* 535C0 */
+	0x22,  0xFC,  0x22,  0x48,  0x3E,  0x84,  0x03,  0x02,  0xBF,  0x11,  0xEE,  0x65,  0x2A,  0x29,  0xEA,  0x11, 	/* 535D0 */
+	0x2C,  0x1D,  0xEA,  0x65,  0x49,  0x09,  0xE9,  0x13,  0x2E,  0x20,  0x88,  0x5F,  0xFE,  0x02,  0x20,  0x7F, 	/* 535E0 */
+	0xFF,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x07,  0xF0,  0x81,  0x00,  0x00,  0x7F,  0xFE,  0x01,  0x00, 	/* 535F0 */
+	0x02,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10, 	/* 53600 */
+	0x08,  0x10,  0x0F,  0xF0,  0x02,  0x20,  0x0C,  0x18,  0x30,  0x04,  0x82,  0x00,  0x00,  0x03,  0xFF,  0x7E, 	/* 53610 */
+	0x20,  0x10,  0x40,  0x11,  0xFC,  0x11,  0x04,  0x11,  0x04,  0x11,  0xFC,  0x11,  0x04,  0x11,  0xFC,  0x11, 	/* 53620 */
+	0x04,  0x11,  0x04,  0x11,  0xFC,  0x10,  0x48,  0x31,  0x84,  0x06,  0x02,  0x83,  0x00,  0x00,  0x23,  0xFF, 	/* 53630 */
+	0x20,  0x20,  0x20,  0x40,  0x26,  0xFE,  0x38,  0x82,  0x20,  0x82,  0x20,  0xFE,  0x20,  0x82,  0x20,  0xFE, 	/* 53640 */
+	0x22,  0x82,  0x22,  0x82,  0x1E,  0xFE,  0x00,  0x44,  0x01,  0x82,  0x06,  0x01,  0x85,  0x00,  0x00,  0x03, 	/* 53650 */
+	0xFF,  0x00,  0x10,  0x7E,  0x20,  0x08,  0xFE,  0x08,  0x82,  0x08,  0x82,  0x08,  0xFE,  0x08,  0x82,  0x0A, 	/* 53660 */
+	0xFE,  0x0C,  0x82,  0x18,  0x82,  0x60,  0xFE,  0x00,  0x4C,  0x01,  0x82,  0x06,  0x01,  0x86,  0x00,  0x00, 	/* 53670 */
+	0x2B,  0xFF,  0x2A,  0x10,  0x2A,  0x20,  0x2A,  0x7E,  0x2A,  0x42,  0x2A,  0x42,  0x2A,  0x7E,  0x2A,  0x42, 	/* 53680 */
+	0x2A,  0x7E,  0x2A,  0x42,  0x2A,  0x42,  0x2A,  0x7E,  0x22,  0x2C,  0x22,  0xC2,  0x43,  0x01,  0x88,  0x08, 	/* 53690 */
+	0x00,  0x0B,  0xFF,  0x10,  0x10,  0x20,  0x20,  0x44,  0xFE,  0x04,  0x82,  0x08,  0x82,  0x08,  0xFE,  0x12, 	/* 536A0 */
+	0x82,  0x22,  0xFE,  0x44,  0x82,  0x04,  0x82,  0x08,  0xFE,  0x10,  0x24,  0x20,  0xC2,  0x43,  0x01,  0x8C, 	/* 536B0 */
+	0x0E,  0x00,  0x02,  0xFF,  0x12,  0x10,  0x12,  0x20,  0x11,  0x7E,  0x21,  0x42,  0x28,  0xC2,  0x48,  0x7E, 	/* 536C0 */
+	0x08,  0x42,  0x0C,  0x7E,  0x0A,  0x42,  0x12,  0x42,  0x15,  0x7E,  0x79,  0x24,  0x00,  0xC2,  0x03,  0x01, 	/* 536D0 */
+	0x8F,  0x08,  0x00,  0x08,  0xFF,  0x08,  0x10,  0x7F,  0xA0,  0x00,  0x7E,  0x1E,  0x42,  0x12,  0x42,  0x12, 	/* 536E0 */
+	0x7E,  0x12,  0x42,  0x12,  0x7E,  0x12,  0x42,  0x12,  0xC2,  0x11,  0xFE,  0x20,  0xA4,  0x40,  0x42,  0x01, 	/* 536F0 */
+	0x81,  0x90,  0x00,  0x00,  0x7F,  0xFF,  0x02,  0x10,  0x34,  0x20,  0x08,  0x7E,  0x08,  0x42,  0x7F,  0x42, 	/* 53700 */
+	0x09,  0x7E,  0x0A,  0x42,  0x0C,  0x7E,  0x08,  0x42,  0x08,  0x42,  0x08,  0x7E,  0x08,  0x14,  0x08,  0x62, 	/* 53710 */
+	0x19,  0x81,  0x91,  0x00,  0x00,  0x01,  0xFF,  0x3E,  0x10,  0x00,  0x20,  0x00,  0xFE,  0x00,  0x82,  0x7F, 	/* 53720 */
+	0x82,  0x14,  0xFE,  0x14,  0x82,  0x14,  0xFE,  0x14,  0x82,  0x15,  0x82,  0x26,  0xFE,  0x24,  0x24,  0x40, 	/* 53730 */
+	0xC2,  0x03,  0x01,  0x92,  0x00,  0x00,  0x0E,  0xFF,  0x02,  0x10,  0x12,  0x20,  0x11,  0x7E,  0x11,  0x42, 	/* 53740 */
+	0x20,  0xC2,  0x3F,  0x7E,  0x49,  0x42,  0x09,  0x7E,  0x09,  0x42,  0x11,  0x42,  0x11,  0x7E,  0x21,  0x24, 	/* 53750 */
+	0x46,  0x42,  0x01,  0x81,  0x93,  0x08,  0x00,  0x09,  0xFF,  0x0F,  0x10,  0x78,  0x20,  0x08,  0x7E,  0x2A, 	/* 53760 */
+	0x42,  0x2A,  0x7E,  0x2A,  0x42,  0x2A,  0x42,  0x2A,  0x7E,  0x3E,  0x42,  0x08,  0x42,  0x08,  0x7E,  0x09, 	/* 53770 */
+	0x24,  0x07,  0x42,  0x01,  0x81,  0x97,  0x04,  0x00,  0x04,  0xFF,  0x04,  0x10,  0x3F,  0xA0,  0x25,  0x7E, 	/* 53780 */
+	0x24,  0x42,  0x3F,  0x42,  0x29,  0x7E,  0x29,  0x42,  0x25,  0x7E,  0x26,  0x42,  0x22,  0x42,  0x25,  0x7E, 	/* 53790 */
+	0x49,  0x24,  0x10,  0x42,  0x21,  0x81,  0x98,  0x08,  0x00,  0x08,  0xFF,  0x14,  0x10,  0x12,  0x20,  0x21, 	/* 537A0 */
+	0x7E,  0x5E,  0x42,  0x00,  0x7E,  0x00,  0x42,  0x7E,  0x42,  0x12,  0x7E,  0x12,  0x42,  0x12,  0x42,  0x12, 	/* 537B0 */
+	0x7E,  0x14,  0x24,  0x10,  0x42,  0x11,  0x81,  0x9A,  0x00,  0x00,  0x7E,  0xFF,  0x22,  0x10,  0x14,  0x20, 	/* 537C0 */
+	0x08,  0x7E,  0x08,  0x42,  0x14,  0x42,  0x22,  0x7E,  0x49,  0x42,  0x08,  0x7E,  0x3E,  0x42,  0x08,  0x42, 	/* 537D0 */
+	0x09,  0x7E,  0x0E,  0x24,  0x70,  0x42,  0x01,  0x81,  0xA1,  0x08,  0x00,  0x09,  0xFF,  0x08,  0x10,  0x7F, 	/* 537E0 */
+	0x20,  0x08,  0x7E,  0x08,  0x42,  0x3E,  0x42,  0x00,  0x7E,  0x00,  0x42,  0x3E,  0x7E,  0x22,  0x42,  0x22, 	/* 537F0 */
+	0x42,  0x22,  0x7E,  0x3E,  0x24,  0x00,  0xC2,  0x03,  0x01,  0xA4,  0x00,  0x00,  0x3F,  0xFF,  0x22,  0x08, 	/* 53800 */
+	0x22,  0x10,  0x2A,  0x3E,  0x2B,  0x22,  0x29,  0x22,  0x29,  0x3E,  0x29,  0x22,  0x2B,  0x3E,  0x2A,  0x22, 	/* 53810 */
+	0x22,  0x22,  0x22,  0x3E,  0x3F,  0x94,  0x00,  0x22,  0x00,  0xC1,  0xAC,  0x04,  0x00,  0x04,  0xFF,  0x3F, 	/* 53820 */
+	0x10,  0x04,  0x20,  0x25,  0x7E,  0x15,  0x42,  0x16,  0x42,  0x04,  0x7E,  0x7F,  0xC2,  0x04,  0x7E,  0x04, 	/* 53830 */
+	0x42,  0x0A,  0x42,  0x09,  0x7E,  0x11,  0x24,  0x20,  0x42,  0x40,  0x81,  0xAD,  0x00,  0x00,  0x7F,  0xFE, 	/* 53840 */
+	0x00,  0x20,  0x00,  0x40,  0x3E,  0xFC,  0x22,  0x84,  0x22,  0x84,  0x22,  0xFC,  0x3E,  0x84,  0x02,  0xFC, 	/* 53850 */
+	0x22,  0x84,  0x14,  0x84,  0x15,  0xFC,  0x0E,  0x48,  0x70,  0x84,  0x03,  0x02,  0xB4,  0x20,  0x00,  0x22, 	/* 53860 */
+	0xFF,  0x3C,  0x10,  0x20,  0x20,  0x21,  0x7E,  0x1F,  0x42,  0x00,  0x42,  0x1E,  0x7E,  0x00,  0x42,  0x7F, 	/* 53870 */
+	0xFE,  0x04,  0x42,  0x16,  0x42,  0x15,  0x7E,  0x25,  0x24,  0x44,  0x42,  0x0D,  0x81,  0xB7,  0x04,  0x00, 	/* 53880 */
+	0x04,  0xFF,  0x0A,  0x10,  0x11,  0x20,  0x3E,  0xFE,  0x40,  0x42,  0x3F,  0x42,  0x01,  0x7E,  0x02,  0x42, 	/* 53890 */
+	0x04,  0x7E,  0x3F,  0x42,  0x21,  0x42,  0x21,  0x7E,  0x3F,  0x24,  0x00,  0xC2,  0x03,  0x01,  0xB8,  0x00, 	/* 538A0 */
+	0x00,  0x7F,  0x7F,  0x00,  0x08,  0x15,  0x10,  0x15,  0x7E,  0x2A,  0x42,  0x5A,  0x42,  0x25,  0x7E,  0x15, 	/* 538B0 */
+	0x42,  0x00,  0x7E,  0x7F,  0x42,  0x04,  0x42,  0x04,  0x7E,  0x07,  0x24,  0x18,  0xC2,  0x63,  0x01,  0xBB, 	/* 538C0 */
+	0x04,  0x00,  0x14,  0xFF,  0x17,  0x10,  0x14,  0x20,  0x14,  0x7E,  0x7F,  0xC2,  0x08,  0x42,  0x2A,  0x7E, 	/* 538D0 */
+	0x29,  0x42,  0x2B,  0x7E,  0x4A,  0xC2,  0x1C,  0x42,  0x04,  0x7E,  0x08,  0x24,  0x10,  0xC2,  0x63,  0x01, 	/* 538E0 */
+	0xBC,  0x08,  0x00,  0x08,  0xFF,  0x7F,  0x10,  0x08,  0x20,  0x08,  0x7E,  0x3F,  0x42,  0x29,  0x7E,  0x29, 	/* 538F0 */
+	0x42,  0x3F,  0x42,  0x28,  0x7E,  0x1C,  0x42,  0x1A,  0x42,  0x29,  0x7E,  0x28,  0x24,  0x48,  0x42,  0x09, 	/* 53900 */
+	0x81,  0xBD,  0x01,  0x00,  0x06,  0xFF,  0x3C,  0x10,  0x04,  0x20,  0x7F,  0xFE,  0x0E,  0x42,  0x15,  0x42, 	/* 53910 */
+	0x24,  0xFE,  0x44,  0x42,  0x1E,  0x7E,  0x12,  0x42,  0x12,  0x42,  0x12,  0xFE,  0x13,  0x24,  0x22,  0x42, 	/* 53920 */
+	0x41,  0x81,  0x86,  0x00,  0x00,  0x3F,  0xFF,  0x29,  0x10,  0x29,  0x20,  0x3F,  0x7E,  0x29,  0x42,  0x29, 	/* 53930 */
+	0x42,  0x3F,  0x7E,  0x08,  0x42,  0x7F,  0xFE,  0x0C,  0x42,  0x1A,  0x42,  0x29,  0x7E,  0x48,  0x24,  0x08, 	/* 53940 */
+	0x42,  0x09,  0x81,  0x8B,  0x00,  0x00,  0x3F,  0x7F,  0x29,  0x08,  0x29,  0x10,  0x3F,  0x3E,  0x29,  0x22, 	/* 53950 */
+	0x29,  0x22,  0x29,  0x3E,  0x3F,  0x22,  0x04,  0x3E,  0x22,  0x22,  0x2A,  0xA2,  0x28,  0x7E,  0x29,  0x54, 	/* 53960 */
+	0x49,  0x62,  0x07,  0x81,  0x8C,  0x00,  0x00,  0x3F,  0xFF,  0x22,  0x10,  0x3E,  0x20,  0x22,  0x7E,  0x22, 	/* 53970 */
+	0x42,  0x3E,  0x7E,  0x00,  0x42,  0x7F,  0xFE,  0x08,  0x42,  0x28,  0x42,  0x2F,  0x7E,  0x38,  0x14,  0x28, 	/* 53980 */
+	0x22,  0x26,  0x42,  0x41,  0xFF,  0x8D,  0x08,  0x00,  0x08,  0xFF,  0x7F,  0x10,  0x41,  0x20,  0x49,  0x7E, 	/* 53990 */
+	0x1E,  0x42,  0x22,  0x42,  0x54,  0x7E,  0x0C,  0x42,  0x0A,  0x7E,  0x11,  0x42,  0x3E,  0xC2,  0x52,  0x7E, 	/* 539A0 */
+	0x12,  0x24,  0x1E,  0xC2,  0x13,  0x01,  0x8E,  0x00,  0x00,  0x77,  0xFF,  0x55,  0x10,  0x55,  0x20,  0x77, 	/* 539B0 */
+	0x7E,  0x00,  0x42,  0x3E,  0x7E,  0x00,  0x42,  0x7F,  0x42,  0x10,  0x7E,  0x10,  0x42,  0x3E,  0x42,  0x22, 	/* 539C0 */
+	0x7E,  0x02,  0x24,  0x02,  0x62,  0x0C,  0xC1,  0x8F,  0x04,  0x00,  0x7F,  0xFF,  0x12,  0x10,  0x0C,  0x20, 	/* 539D0 */
+	0x12,  0x7E,  0x3F,  0xC2,  0x24,  0x42,  0x24,  0x7E,  0x2A,  0x42,  0x32,  0x7E,  0x24,  0x42,  0x29,  0x42, 	/* 539E0 */
+	0x52,  0x7E,  0x44,  0x24,  0x18,  0x42,  0x61,  0x81,  0x94,  0x08,  0x00,  0x08,  0xFF,  0x7F,  0x10,  0x22, 	/* 539F0 */
+	0x20,  0x14,  0x7E,  0x3F,  0x42,  0x22,  0x42,  0x24,  0x7E,  0x29,  0x42,  0x22,  0x7E,  0x24,  0x42,  0x28, 	/* 53A00 */
+	0xC2,  0x21,  0x7E,  0x42,  0x24,  0x0C,  0x42,  0x31,  0x81,  0x95,  0x00,  0x00,  0x3F,  0xFF,  0x22,  0x10, 	/* 53A10 */
+	0x22,  0x20,  0x3E,  0x7E,  0x22,  0x42,  0x22,  0x42,  0x3E,  0x7E,  0x14,  0x42,  0x15,  0x7E,  0x55,  0x42, 	/* 53A20 */
+	0x36,  0x42,  0x34,  0x7E,  0x17,  0x24,  0x1C,  0x42,  0x71,  0x81,  0x98,  0x00,  0x00,  0x3F,  0xFF,  0x22, 	/* 53A30 */
+	0x08,  0x24,  0x10,  0x2F,  0xBE,  0x28,  0xA2,  0x2F,  0xA2,  0x28,  0xBE,  0x28,  0xA2,  0x2F,  0xBE,  0x22, 	/* 53A40 */
+	0x22,  0x2B,  0x22,  0x2A,  0xBE,  0x4A,  0x54,  0x52,  0x22,  0x06,  0xC1,  0x9B,  0x08,  0x00,  0x08,  0xFF, 	/* 53A50 */
+	0x7F,  0x90,  0x08,  0x20,  0x3E,  0x7E,  0x22,  0x42,  0x3E,  0x42,  0x22,  0x7E,  0x3E,  0x42,  0x22,  0x7E, 	/* 53A60 */
+	0x3E,  0x42,  0x00,  0x42,  0x7F,  0xFE,  0x0A,  0x24,  0x11,  0x42,  0x61,  0x81,  0x9E,  0x08,  0x00,  0x49, 	/* 53A70 */
+	0xFF,  0x29,  0x10,  0x2A,  0x20,  0x7F,  0x7E,  0x1C,  0x42,  0x1A,  0x42,  0x2A,  0x7E,  0x48,  0x42,  0x08, 	/* 53A80 */
+	0x7E,  0x7F,  0x42,  0x08,  0x42,  0x14,  0x7E,  0x12,  0x24,  0x22,  0x42,  0x41,  0x81,  0xA7,  0x00,  0x00, 	/* 53A90 */
+	0x7F,  0xFF,  0x00,  0x10,  0x3F,  0x20,  0x21,  0x7E,  0x3F,  0x42,  0x25,  0x42,  0x2A,  0x7E,  0x2F,  0x42, 	/* 53AA0 */
+	0x3A,  0x7E,  0x2F,  0x42,  0x2A,  0x42,  0x2F,  0x7E,  0x4A,  0x14,  0x4F,  0xA2,  0x08,  0xC1,  0xAB,  0x04, 	/* 53AB0 */
+	0x00,  0x7F,  0xFF,  0x20,  0x88,  0x2E,  0x90,  0x2A,  0xBE,  0x2E,  0xA2,  0x3F,  0xA2,  0x00,  0x3E,  0x1F, 	/* 53AC0 */
+	0x22,  0x11,  0x3E,  0x1F,  0x22,  0x11,  0x22,  0x1F,  0x3E,  0x00,  0x14,  0x7F,  0xA2,  0x00,  0xC1,  0xAF, 	/* 53AD0 */
+	0x00,  0x00,  0x3F,  0x7F,  0x21,  0x08,  0x3F,  0x10,  0x21,  0x3E,  0x3F,  0x22,  0x11,  0x3E,  0x11,  0x22, 	/* 53AE0 */
+	0x6E,  0xA2,  0x11,  0x3E,  0x2A,  0xA2,  0x7F,  0xE2,  0x00,  0x3E,  0x2D,  0x14,  0x2A,  0xA2,  0x4A,  0xC1, 	/* 53AF0 */
+	0xB0,  0x04,  0x00,  0x17,  0xFF,  0x14,  0x08,  0x7F,  0xBE,  0x14,  0x22,  0x14,  0xBE,  0x2D,  0x22,  0x42, 	/* 53B00 */
+	0x3E,  0x0F,  0xFA,  0x78,  0x89,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x01,  0x20,  0x7F,  0xFF,  0x00, 	/* 53B10 */
+	0x20,  0xB1,  0x04,  0x00,  0x07,  0xBF,  0x04,  0x08,  0x3F,  0xD0,  0x25,  0xBE,  0x3E,  0x22,  0x2F,  0xE2, 	/* 53B20 */
+	0x2A,  0xBE,  0x2F,  0xA2,  0x2A,  0xBE,  0x2F,  0xA2,  0x20,  0x22,  0x3F,  0xBE,  0x5A,  0x94,  0x7F,  0xE2, 	/* 53B30 */
+	0x40,  0x41,  0xB3,  0x00,  0x00,  0x3F,  0xFF,  0x11,  0x08,  0x1F,  0x10,  0x11,  0x3E,  0x1F,  0xA2,  0x31, 	/* 53B40 */
+	0x22,  0x01,  0x3E,  0x7F,  0xE2,  0x2A,  0xBE,  0x3B,  0xA2,  0x2A,  0xA2,  0x3B,  0xBE,  0x2A,  0x94,  0x7F, 	/* 53B50 */
+	0xA2,  0x08,  0xC1,  0xB4,  0x12,  0x00,  0x7F,  0xFF,  0x12,  0x08,  0x3B,  0x90,  0x2A,  0xBE,  0x3B,  0xA2, 	/* 53B60 */
+	0x12,  0x22,  0x14,  0x3E,  0x3F,  0xA2,  0x64,  0x3E,  0x3F,  0x22,  0x24,  0x22,  0x3F,  0x3E,  0x24,  0x14, 	/* 53B70 */
+	0x3F,  0xA2,  0x00,  0xC1,  0xA8,  0x00,  0x00,  0x1F,  0xF8,  0x10,  0x28,  0x10,  0xC8,  0x1F,  0x08,  0x11, 	/* 53B80 */
+	0x08,  0x17,  0xE8,  0x15,  0x28,  0x15,  0x28,  0x17,  0xE8,  0x11,  0x08,  0x11,  0x48,  0x11,  0x25,  0x21, 	/* 53B90 */
+	0xF5,  0x3E,  0x13,  0x40,  0x01,  0xAA,  0x00,  0x00,  0x3F,  0xFF,  0x00,  0x80,  0x00,  0xFE,  0x00,  0x80, 	/* 53BA0 */
+	0x1F,  0xFC,  0x10,  0x64,  0x17,  0x84,  0x10,  0x84,  0x17,  0xF4,  0x14,  0x94,  0x17,  0xF5,  0x10,  0xA5, 	/* 53BB0 */
+	0x20,  0x95,  0x2F,  0xFB,  0x40,  0x09,  0xAF,  0x08,  0x00,  0x09,  0xFE,  0x09,  0x02,  0x7F,  0x0A,  0x05, 	/* 53BC0 */
+	0xF2,  0x45,  0x22,  0x25,  0xFA,  0x25,  0xAA,  0x25,  0xAA,  0x29,  0xFA,  0x09,  0x22,  0x17,  0x32,  0x19, 	/* 53BD0 */
+	0x2B,  0x62,  0x3B,  0x03,  0xC5,  0x04,  0x01,  0xB1,  0x00,  0x08,  0x3F,  0xC8,  0x20,  0xC8,  0x23,  0x4A, 	/* 53BE0 */
+	0x3C,  0x52,  0x24,  0x57,  0x3F,  0x79,  0x35,  0x41,  0x35,  0x5E,  0x3F,  0x52,  0x24,  0x52,  0x26,  0x52, 	/* 53BF0 */
+	0x25,  0x5E,  0x27,  0x41,  0x38,  0xA1,  0x40,  0x1F,  0xB6,  0x00,  0x00,  0x3F,  0xBE,  0x21,  0xA2,  0x22, 	/* 53C00 */
+	0xBE,  0x3C,  0xA2,  0x24,  0xBE,  0x3F,  0xA2,  0x35,  0xBE,  0x35,  0xA2,  0x3F,  0xFF,  0x24,  0x94,  0x26, 	/* 53C10 */
+	0xA2,  0x25,  0xC1,  0x27,  0x40,  0x39,  0x21,  0x40,  0x1F,  0x83,  0x00,  0x00,  0x3F,  0xFF,  0x23,  0x14, 	/* 53C20 */
+	0x25,  0x7F,  0x3D,  0x55,  0x25,  0x7F,  0x3F,  0x00,  0x35,  0x3E,  0x35,  0x00,  0x3F,  0x7F,  0x25,  0x08, 	/* 53C30 */
+	0x27,  0x2A,  0x25,  0x49,  0x26,  0x98,  0x39,  0x41,  0x41,  0x3F,  0x84,  0x00,  0x00,  0x7F,  0x7E,  0x14, 	/* 53C40 */
+	0x42,  0x7F,  0x46,  0x55,  0x7A,  0x55,  0x52,  0x7F,  0x7E,  0x00,  0x56,  0x3E,  0x56,  0x00,  0x7E,  0x7F, 	/* 53C50 */
+	0x52,  0x08,  0x5B,  0x2C,  0x57,  0x2A,  0x9D,  0x48,  0xE3,  0x19,  0x01,  0x86,  0x14,  0x00,  0x12,  0xFE, 	/* 53C60 */
+	0x10,  0x86,  0x7E,  0x8A,  0x18,  0xF2,  0x14,  0xA2,  0x22,  0xFA,  0x40,  0xAA,  0x35,  0xAA,  0x2C,  0xFA, 	/* 53C70 */
+	0x7F,  0xA2,  0x24,  0xB2,  0x34,  0xAA,  0x2A,  0xFB,  0x4A,  0x85,  0x41,  0x05,  0x9B,  0x00,  0x00,  0x1F, 	/* 53C80 */
+	0xF2,  0x01,  0x1C,  0x03,  0x14,  0x0D,  0x0A,  0x39,  0x0A,  0x09,  0x06,  0x7F,  0xF2,  0x09,  0x12,  0x09, 	/* 53C90 */
+	0x14,  0x09,  0x18,  0x11,  0x14,  0x11,  0x0A,  0x21,  0x09,  0x41,  0x05,  0x01,  0x03,  0x9C,  0x02,  0x01, 	/* 53CA0 */
+	0x0C,  0xFD,  0x78,  0x26,  0x49,  0x55,  0x2A,  0xD4,  0x7F,  0x55,  0x1C,  0x53,  0x2A,  0x50,  0x49,  0xFD, 	/* 53CB0 */
+	0x3E,  0x55,  0x2A,  0x56,  0x3E,  0x55,  0x2A,  0x54,  0x2A,  0x95,  0x3E,  0x93,  0x01,  0x11,  0x9F,  0x00, 	/* 53CC0 */
+	0x80,  0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x04,  0x90,  0x1F,  0xFC,  0x64,  0x13,  0x07,  0xF0,  0x04, 	/* 53CD0 */
+	0x10,  0x04,  0x10,  0x07,  0xF4,  0x04,  0x88,  0x04,  0x50,  0x04,  0x20,  0x07,  0x98,  0x38,  0x07,  0xA2, 	/* 53CE0 */
+	0x04,  0x00,  0x04,  0x78,  0x0A,  0x48,  0x09,  0x48,  0x14,  0xC8,  0x3F,  0x48,  0x51,  0x48,  0x1F,  0x48, 	/* 53CF0 */
+	0x11,  0x48,  0x11,  0x48,  0x1F,  0x48,  0x14,  0x48,  0x12,  0x49,  0x13,  0x49,  0x1C,  0x87,  0x31,  0x00, 	/* 53D00 */
+	0xA9,  0x08,  0x10,  0x08,  0x12,  0x14,  0x1C,  0x12,  0xF0,  0x3D,  0x10,  0x40,  0x10,  0x3E,  0x92,  0x22, 	/* 53D10 */
+	0x92,  0x3E,  0x92,  0x22,  0x92,  0x3E,  0xFE,  0x20,  0x10,  0x3E,  0x10,  0x20,  0x11,  0x3F,  0x11,  0x20, 	/* 53D20 */
+	0x0F,  0xAB,  0x08,  0x04,  0x08,  0x18,  0x14,  0xF0,  0x12,  0x10,  0x3D,  0x10,  0x40,  0x10,  0x3F,  0xFF, 	/* 53D30 */
+	0x22,  0x10,  0x3E,  0x10,  0x22,  0x18,  0x3E,  0x28,  0x20,  0x28,  0x3E,  0x44,  0x20,  0x44,  0x3E,  0x82, 	/* 53D40 */
+	0x21,  0x01,  0xAD,  0x08,  0x40,  0x08,  0x40,  0x14,  0x40,  0x1E,  0x7F,  0x21,  0x80,  0x7E,  0x90,  0x23, 	/* 53D50 */
+	0x10,  0x3E,  0xFE,  0x22,  0x12,  0x22,  0x12,  0x3E,  0x12,  0x20,  0x12,  0x3E,  0x22,  0x20,  0x22,  0x3F, 	/* 53D60 */
+	0x42,  0x20,  0x8C,  0xAE,  0x08,  0x20,  0x08,  0x20,  0x14,  0x20,  0x12,  0x3F,  0x3D,  0x42,  0x60,  0x54, 	/* 53D70 */
+	0x3E,  0x90,  0x22,  0x10,  0x3E,  0x10,  0x22,  0x18,  0x3E,  0x18,  0x20,  0x28,  0x3E,  0x24,  0x20,  0x44, 	/* 53D80 */
+	0x3E,  0x82,  0x21,  0x01,  0xAF,  0x08,  0x00,  0x08,  0x7F,  0x14,  0x40,  0x12,  0x40,  0x29,  0x40,  0x7E, 	/* 53D90 */
+	0x7E,  0x22,  0x42,  0x3E,  0x52,  0x22,  0x52,  0x22,  0x52,  0x3E,  0x54,  0x28,  0x4C,  0x24,  0x48,  0x26, 	/* 53DA0 */
+	0x94,  0x3A,  0xA2,  0x61,  0x41,  0xB2,  0x08,  0x20,  0x08,  0x20,  0x14,  0x20,  0x1A,  0x20,  0x29,  0x7F, 	/* 53DB0 */
+	0x7E,  0x51,  0x22,  0x52,  0x3E,  0x94,  0x23,  0x10,  0x22,  0x10,  0x3E,  0x28,  0x28,  0x28,  0x24,  0x44, 	/* 53DC0 */
+	0x26,  0x44,  0x3A,  0x82,  0x61,  0x01,  0xB4,  0x08,  0x20,  0x08,  0x20,  0x14,  0x20,  0x12,  0x48,  0x29, 	/* 53DD0 */
+	0x44,  0x7E,  0x8E,  0x23,  0xF2,  0x3E,  0x02,  0x22,  0x00,  0x22,  0x7C,  0x3E,  0x44,  0x24,  0x44,  0x22, 	/* 53DE0 */
+	0x44,  0x26,  0x44,  0x39,  0x7C,  0x60,  0x00,  0xBC,  0x08,  0x00,  0x08,  0xFE,  0x14,  0x02,  0x12,  0x02, 	/* 53DF0 */
+	0x29,  0xFA,  0x7E,  0x02,  0x22,  0x02,  0x3E,  0xF2,  0x22,  0x92,  0x22,  0x92,  0x3E,  0x92,  0x28,  0xF2, 	/* 53E00 */
+	0x24,  0x02,  0x26,  0x02,  0x3A,  0x02,  0x61,  0x0C,  0xBD,  0x08,  0x40,  0x08,  0x40,  0x14,  0x7E,  0x12, 	/* 53E10 */
+	0x42,  0x29,  0x82,  0x7E,  0xFA,  0x22,  0x8A,  0x3F,  0x0A,  0x22,  0x0A,  0x22,  0x7A,  0x3E,  0x4C,  0x28, 	/* 53E20 */
+	0x40,  0x24,  0x40,  0x24,  0x41,  0x3A,  0x21,  0x61,  0x1F,  0xBE,  0x08,  0x40,  0x08,  0x40,  0x14,  0x40, 	/* 53E30 */
+	0x12,  0x7F,  0x28,  0x90,  0x7E,  0x90,  0x23,  0x7E,  0x3E,  0x52,  0x22,  0x52,  0x22,  0x52,  0x3E,  0x52, 	/* 53E40 */
+	0x28,  0x52,  0x24,  0x5C,  0x26,  0x50,  0x3A,  0x10,  0x61,  0x10,  0x83,  0x08,  0x10,  0x08,  0x10,  0x14, 	/* 53E50 */
+	0x10,  0x12,  0xFF,  0x3D,  0x24,  0x40,  0x22,  0x3E,  0x42,  0x22,  0xA5,  0x3E,  0x24,  0x22,  0x14,  0x3E, 	/* 53E60 */
+	0x18,  0x20,  0x18,  0x3E,  0x28,  0x20,  0x44,  0x3E,  0x82,  0x21,  0x01,  0x85,  0x08,  0x42,  0x08,  0x22, 	/* 53E70 */
+	0x14,  0x24,  0x12,  0x00,  0x29,  0xFF,  0x7E,  0x24,  0x22,  0x24,  0x3E,  0x24,  0x22,  0xFF,  0x22,  0x24, 	/* 53E80 */
+	0x3E,  0x24,  0x28,  0x24,  0x24,  0x24,  0x2E,  0x44,  0x31,  0x44,  0x60,  0x84,  0x89,  0x08,  0x10,  0x08, 	/* 53E90 */
+	0x10,  0x14,  0x20,  0x12,  0xFE,  0x3D,  0x82,  0x40,  0x82,  0x3E,  0xBA,  0x22,  0xAA,  0x3E,  0xAA,  0x22, 	/* 53EA0 */
+	0xAA,  0x3E,  0xBA,  0x20,  0x82,  0x3E,  0x82,  0x20,  0x82,  0x3E,  0x82,  0x20,  0x86,  0x8A,  0x04,  0x10, 	/* 53EB0 */
+	0x02,  0x20,  0x3F,  0xFE,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0xA0,  0x07,  0xF0, 	/* 53EC0 */
+	0x1C,  0x1C,  0x67,  0xF3,  0x04,  0x10,  0x07,  0xF4,  0x04,  0x48,  0x07,  0xB0,  0x38,  0x0F,  0x8C,  0x08, 	/* 53ED0 */
+	0x00,  0x09,  0xFF,  0x14,  0x44,  0x12,  0x44,  0x29,  0x44,  0x7E,  0x7C,  0x22,  0x44,  0x3E,  0x44,  0x22, 	/* 53EE0 */
+	0x7C,  0x22,  0x44,  0x3E,  0x44,  0x24,  0x47,  0x22,  0x7C,  0x26,  0xC4,  0x39,  0x04,  0x61,  0x04,  0x90, 	/* 53EF0 */
+	0x04,  0x00,  0x07,  0xFE,  0x04,  0x22,  0x0F,  0x14,  0x79,  0x88,  0x06,  0xB4,  0x19,  0x43,  0x62,  0xA0, 	/* 53F00 */
+	0x0F,  0xF8,  0x74,  0x17,  0x07,  0xF0,  0x04,  0x10,  0x07,  0xF4,  0x04,  0x88,  0x07,  0x70,  0x38,  0x0F, 	/* 53F10 */
+	0x92,  0x08,  0x04,  0x08,  0x18,  0x14,  0xE4,  0x12,  0x52,  0x3D,  0x52,  0x40,  0x91,  0x3F,  0x01,  0x22, 	/* 53F20 */
+	0x10,  0x3F,  0xFF,  0x22,  0x24,  0x3E,  0x24,  0x20,  0x64,  0x3E,  0x18,  0x20,  0x14,  0x3E,  0x62,  0x21, 	/* 53F30 */
+	0x82,  0x93,  0x08,  0x28,  0x08,  0x4C,  0x15,  0xCA,  0x1A,  0x4A,  0x28,  0x48,  0x7F,  0xFF,  0x22,  0x48, 	/* 53F40 */
+	0x3E,  0x4A,  0x22,  0x6A,  0x22,  0x4A,  0x3E,  0xC4,  0x29,  0x44,  0x24,  0x4D,  0x2C,  0x4B,  0x32,  0x53, 	/* 53F50 */
+	0x62,  0xE1,  0x94,  0x08,  0x14,  0x08,  0x12,  0x15,  0xFF,  0x12,  0x10,  0x3D,  0x10,  0x40,  0xFE,  0x3E, 	/* 53F60 */
+	0x92,  0x22,  0x92,  0x3E,  0xFE,  0x22,  0x92,  0x3E,  0x92,  0x20,  0xFE,  0x3E,  0x92,  0x20,  0x92,  0x3E, 	/* 53F70 */
+	0x92,  0x20,  0x96,  0x98,  0x08,  0x10,  0x08,  0x10,  0x14,  0x28,  0x12,  0x28,  0x3D,  0x44,  0x40,  0x42, 	/* 53F80 */
+	0x3E,  0xFD,  0x23,  0x10,  0x3E,  0x10,  0x22,  0xFE,  0x3E,  0x10,  0x20,  0x54,  0x3E,  0x54,  0x20,  0x92, 	/* 53F90 */
+	0x3F,  0x12,  0x20,  0x30,  0x9D,  0x08,  0x44,  0x08,  0x44,  0x15,  0xFF,  0x12,  0x44,  0x3D,  0x54,  0x40, 	/* 53FA0 */
+	0x10,  0x3F,  0xFF,  0x22,  0x20,  0x3E,  0x20,  0x22,  0x3C,  0x3E,  0x24,  0x20,  0x24,  0x3E,  0x44,  0x20, 	/* 53FB0 */
+	0x44,  0x3E,  0x84,  0x21,  0x18,  0x9E,  0x08,  0x28,  0x08,  0x24,  0x14,  0x2F,  0x12,  0xF2,  0x3D,  0x14, 	/* 53FC0 */
+	0x40,  0x08,  0x3E,  0x75,  0x23,  0x83,  0x3E,  0x28,  0x22,  0x24,  0x3E,  0x3F,  0x20,  0xD2,  0x3E,  0x14, 	/* 53FD0 */
+	0x20,  0x39,  0x3F,  0xC5,  0x20,  0x03,  0xA0,  0x08,  0x22,  0x08,  0x22,  0x14,  0x44,  0x13,  0xFF,  0x3D, 	/* 53FE0 */
+	0x44,  0x40,  0x44,  0x3E,  0x44,  0x22,  0x54,  0x3E,  0x64,  0x22,  0xDF,  0x3F,  0x44,  0x20,  0x44,  0x3E, 	/* 53FF0 */
+	0x44,  0x20,  0x84,  0x3E,  0x84,  0x21,  0x04,  0xA1,  0x08,  0x20,  0x08,  0x20,  0x14,  0x3E,  0x12,  0x22, 	/* 54000 */
+	0x3D,  0x22,  0x40,  0x42,  0x3E,  0x4C,  0x22,  0x80,  0x3E,  0x20,  0x22,  0xCE,  0x3E,  0x82,  0x20,  0xEE, 	/* 54010 */
+	0x3E,  0x82,  0x20,  0x82,  0x3E,  0xFE,  0x20,  0x00,  0xA4,  0x08,  0x10,  0x08,  0x92,  0x14,  0x92,  0x12, 	/* 54020 */
+	0xAC,  0x3D,  0x28,  0x40,  0x44,  0x3E,  0x82,  0x23,  0x11,  0x3E,  0x10,  0x22,  0x92,  0x3E,  0x92,  0x20, 	/* 54030 */
+	0xAC,  0x3F,  0x28,  0x20,  0x44,  0x3E,  0x82,  0x21,  0x01,  0xA8,  0x08,  0x10,  0x08,  0x10,  0x14,  0xFF, 	/* 54040 */
+	0x12,  0x81,  0x29,  0x81,  0x7E,  0x7C,  0x22,  0x44,  0x3E,  0x44,  0x22,  0x7C,  0x22,  0x40,  0x3E,  0x40, 	/* 54050 */
+	0x24,  0x7E,  0x22,  0x42,  0x26,  0x42,  0x39,  0x7E,  0x60,  0x00,  0xAC,  0x08,  0x80,  0x08,  0x9E,  0x14, 	/* 54060 */
+	0x92,  0x14,  0x92,  0x3B,  0xF2,  0x40,  0x9E,  0x3C,  0x92,  0x24,  0x92,  0x3D,  0xD2,  0x25,  0x5E,  0x3D, 	/* 54070 */
+	0x52,  0x21,  0x52,  0x3D,  0x52,  0x21,  0xD2,  0x3C,  0x22,  0x20,  0x46,  0xAE,  0x00,  0x10,  0x7F,  0x98, 	/* 54080 */
+	0x04,  0x2C,  0x0F,  0x72,  0x11,  0x89,  0x6A,  0x34,  0x04,  0x88,  0x19,  0x70,  0x63,  0xE0,  0x0C,  0x18, 	/* 54090 */
+	0x77,  0xF7,  0x04,  0x10,  0x07,  0xF8,  0x04,  0x90,  0x07,  0x60,  0x3C,  0x1F,  0xBD,  0x08,  0x10,  0x08, 	/* 540A0 */
+	0x20,  0x14,  0xFC,  0x12,  0xA4,  0x3D,  0xA4,  0x40,  0xFC,  0x3E,  0xA4,  0x22,  0xA4,  0x3E,  0xFC,  0x22, 	/* 540B0 */
+	0x32,  0x3E,  0x32,  0x20,  0x55,  0x3E,  0x5F,  0x20,  0x90,  0x3F,  0x11,  0x22,  0x0F,  0xBE,  0x08,  0x10, 	/* 540C0 */
+	0x08,  0xEF,  0x14,  0x85,  0x12,  0x85,  0x3D,  0xA5,  0x40,  0xA9,  0x3E,  0xEB,  0x23,  0x90,  0x3E,  0x00, 	/* 540D0 */
+	0x22,  0xFE,  0x3E,  0x92,  0x20,  0xFE,  0x3E,  0x92,  0x20,  0x92,  0x3E,  0xFE,  0x20,  0x00,  0x82,  0x08, 	/* 540E0 */
+	0x00,  0x08,  0x7E,  0x14,  0x52,  0x12,  0x52,  0x3D,  0x5A,  0x40,  0x56,  0x3E,  0x62,  0x22,  0x7E,  0x3E, 	/* 540F0 */
+	0x00,  0x22,  0xFE,  0x3E,  0xAA,  0x20,  0xAA,  0x3E,  0xAA,  0x20,  0xAA,  0x3F,  0xFF,  0x20,  0x00,  0x85, 	/* 54100 */
+	0x08,  0x00,  0x08,  0x7C,  0x14,  0x44,  0x12,  0x7C,  0x3D,  0x44,  0x40,  0x7C,  0x3E,  0x00,  0x22,  0xFF, 	/* 54110 */
+	0x3E,  0xA5,  0x22,  0xFF,  0x3E,  0x00,  0x20,  0xFE,  0x3E,  0x24,  0x20,  0x18,  0x3E,  0x64,  0x21,  0x83, 	/* 54120 */
+	0x89,  0x08,  0x44,  0x08,  0x44,  0x15,  0xFF,  0x12,  0x44,  0x3D,  0x7C,  0x40,  0x00,  0x3E,  0xFE,  0x22, 	/* 54130 */
+	0x92,  0x3E,  0xFE,  0x22,  0x10,  0x3E,  0xFE,  0x20,  0x10,  0x3E,  0xFE,  0x20,  0x10,  0x3F,  0xFF,  0x20, 	/* 54140 */
+	0x00,  0x8B,  0x08,  0x10,  0x08,  0x7E,  0x14,  0x52,  0x12,  0x7E,  0x3D,  0x10,  0x40,  0xFF,  0x3E,  0x00, 	/* 54150 */
+	0x22,  0x7E,  0x3E,  0x42,  0x22,  0x7E,  0x3E,  0x42,  0x20,  0x7E,  0x3E,  0x42,  0x20,  0x7E,  0x3E,  0x22, 	/* 54160 */
+	0x21,  0xC1,  0x8C,  0x08,  0x00,  0x08,  0xEE,  0x14,  0xAA,  0x12,  0xEE,  0x3D,  0x88,  0x40,  0x99,  0x3E, 	/* 54170 */
+	0x77,  0x22,  0x00,  0x3E,  0x24,  0x22,  0xFE,  0x3E,  0x24,  0x20,  0x24,  0x3F,  0xFF,  0x20,  0x24,  0x3E, 	/* 54180 */
+	0x42,  0x21,  0x81,  0x90,  0x08,  0x10,  0x09,  0xFF,  0x14,  0x10,  0x12,  0x7E,  0x3D,  0x00,  0x40,  0xFF, 	/* 54190 */
+	0x3E,  0x81,  0x22,  0x7D,  0x3E,  0x00,  0x22,  0x7E,  0x3E,  0x42,  0x20,  0x7E,  0x3E,  0x42,  0x20,  0x24, 	/* 541A0 */
+	0x3F,  0xFF,  0x20,  0x00,  0x91,  0x08,  0x52,  0x08,  0x52,  0x15,  0xBC,  0x12,  0xD2,  0x3C,  0x55,  0x40, 	/* 541B0 */
+	0xBF,  0x3D,  0xF4,  0x24,  0x12,  0x3D,  0xFF,  0x24,  0x94,  0x3C,  0x94,  0x20,  0xC8,  0x3D,  0x29,  0x21, 	/* 541C0 */
+	0x15,  0x3E,  0x23,  0x20,  0x41,  0x92,  0x08,  0x10,  0x08,  0x7C,  0x14,  0x10,  0x12,  0xFE,  0x3D,  0x00, 	/* 541D0 */
+	0x40,  0x44,  0x3E,  0xFF,  0x22,  0x44,  0x3E,  0x74,  0x23,  0x8F,  0x3E,  0x00,  0x21,  0xFF,  0x3C,  0x28, 	/* 541E0 */
+	0x20,  0x29,  0x3E,  0xC9,  0x23,  0x07,  0x95,  0x00,  0x08,  0x3E,  0x0E,  0x22,  0x08,  0x3E,  0x7F,  0x7F, 	/* 541F0 */
+	0xDA,  0x10,  0x74,  0x1E,  0x4F,  0x02,  0x54,  0x1C,  0x95,  0x03,  0x63,  0x0C,  0x18,  0x77,  0xF7,  0x04, 	/* 54200 */
+	0x10,  0x07,  0xF4,  0x04,  0x68,  0x3E,  0x1F,  0x97,  0x11,  0xEE,  0x65,  0x2A,  0x29,  0xEA,  0x11,  0x2C, 	/* 54210 */
+	0x1D,  0xEA,  0x65,  0x49,  0x0B,  0xEF,  0x10,  0xA8,  0x61,  0x48,  0x03,  0xF0,  0x0C,  0x1C,  0x77,  0xF3, 	/* 54220 */
+	0x04,  0x10,  0x07,  0xF4,  0x04,  0xE8,  0x7F,  0x1E,  0x96,  0x10,  0x10,  0x08,  0x10,  0x04,  0x20,  0x7F, 	/* 54230 */
+	0xFE,  0x01,  0x00,  0x02,  0x00,  0x1F,  0xF8,  0x10,  0x08,  0x10,  0x08,  0x1F,  0xF8,  0x10,  0x08,  0x1F, 	/* 54240 */
+	0xF8,  0x10,  0x08,  0x10,  0x08,  0x1F,  0xF8,  0x00,  0x00,  0x97,  0x10,  0x44,  0x10,  0x28,  0x11,  0xFF, 	/* 54250 */
+	0x10,  0x20,  0x7E,  0x7C,  0x12,  0x44,  0x12,  0x44,  0x12,  0x7C,  0x12,  0x44,  0x12,  0x7C,  0x12,  0x44, 	/* 54260 */
+	0x12,  0x44,  0x12,  0x7D,  0x22,  0x01,  0x21,  0x01,  0x40,  0xFF,  0x98,  0x22,  0x0A,  0x12,  0x09,  0x14, 	/* 54270 */
+	0x08,  0x7F,  0xFF,  0x08,  0x08,  0x3E,  0x08,  0x22,  0xEA,  0x22,  0xAA,  0x3E,  0xAA,  0x22,  0xEC,  0x22, 	/* 54280 */
+	0x04,  0x3E,  0x6D,  0x23,  0x95,  0x22,  0x23,  0x3E,  0x43,  0x00,  0x01,  0x99,  0x00,  0x08,  0x00,  0x70, 	/* 54290 */
+	0x1F,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x01,  0xC0,  0x02,  0xA0,  0x04,  0x90,  0x18,  0x8C,  0x6F,  0xFB, 	/* 542A0 */
+	0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0xA5,  0x02,  0x20,  0x04, 	/* 542B0 */
+	0x20,  0x38,  0x3F,  0x08,  0x40,  0x7F,  0xFC,  0x0C,  0x44,  0x1A,  0x7C,  0x29,  0x44,  0x48,  0x7C,  0x3E, 	/* 542C0 */
+	0x20,  0x22,  0x3C,  0x3E,  0x44,  0x23,  0xA8,  0x22,  0x30,  0x3E,  0xCC,  0x03,  0x03,  0xA8,  0x04,  0x3C, 	/* 542D0 */
+	0x3F,  0x25,  0x04,  0x47,  0x7F,  0xFC,  0x25,  0x24,  0x3F,  0x18,  0x20,  0x64,  0x4F,  0x83,  0x00,  0x80, 	/* 542E0 */
+	0x7F,  0xFF,  0x02,  0xA0,  0x07,  0xF0,  0x1C,  0x1C,  0x67,  0xF3,  0x04,  0x10,  0x07,  0xF0,  0xAC,  0x00, 	/* 542F0 */
+	0x00,  0x0F,  0xFC,  0x08,  0x80,  0x08,  0x80,  0x0F,  0xF8,  0x08,  0x80,  0x08,  0x80,  0x0F,  0xF8,  0x08, 	/* 54300 */
+	0x80,  0x08,  0x80,  0x0F,  0xFE,  0x00,  0x22,  0x14,  0x92,  0x12,  0x52,  0x22,  0x42,  0x40,  0x0C,  0xAD, 	/* 54310 */
+	0x00,  0x00,  0x3F,  0xFC,  0x24,  0x24,  0x24,  0x24,  0x3F,  0x24,  0x24,  0x24,  0x3F,  0x24,  0x24,  0x14, 	/* 54320 */
+	0x24,  0x14,  0x3F,  0x98,  0x04,  0x88,  0x32,  0x98,  0x2A,  0x94,  0x28,  0xA4,  0x41,  0x42,  0x06,  0x81, 	/* 54330 */
+	0xAE,  0x00,  0x00,  0x01,  0xFE,  0x21,  0x20,  0x11,  0x20,  0x11,  0xFC,  0x01,  0x20,  0x01,  0xFC,  0x09, 	/* 54340 */
+	0x20,  0x09,  0x20,  0x11,  0xFE,  0x10,  0x12,  0x25,  0x4A,  0x24,  0xAA,  0x44,  0xA2,  0x48,  0x02,  0x00, 	/* 54350 */
+	0x0C,  0xB3,  0x00,  0x08,  0x3F,  0xA8,  0x24,  0x28,  0x24,  0x2E,  0x3F,  0x2A,  0x24,  0x3A,  0x3F,  0xEA, 	/* 54360 */
+	0x24,  0x2A,  0x24,  0x2A,  0x3F,  0xAA,  0x04,  0xAE,  0x12,  0xA8,  0x2A,  0xA8,  0x28,  0xA1,  0x40,  0xA1, 	/* 54370 */
+	0x03,  0x1F,  0xB4,  0x00,  0x22,  0x3F,  0xAA,  0x24,  0x2A,  0x24,  0x2A,  0x3F,  0x2A,  0x24,  0x2A,  0x3F, 	/* 54380 */
+	0x2A,  0x24,  0x2A,  0x24,  0x2A,  0x3F,  0xAA,  0x02,  0xAA,  0x35,  0xAA,  0x2A,  0xAA,  0x2A,  0xA2,  0x41, 	/* 54390 */
+	0x42,  0x06,  0x82,  0xBC,  0x00,  0x08,  0x3F,  0x88,  0x24,  0x08,  0x24,  0xFF,  0x3F,  0x22,  0x24,  0x22, 	/* 543A0 */
+	0x3F,  0x22,  0x24,  0x14,  0x24,  0x14,  0x3F,  0x88,  0x04,  0x88,  0x32,  0x98,  0x2A,  0x94,  0x28,  0xA4, 	/* 543B0 */
+	0x41,  0x42,  0x06,  0x81,  0x81,  0x00,  0x04,  0x3F,  0xC4,  0x24,  0x24,  0x24,  0x18,  0x3F,  0x08,  0x24, 	/* 543C0 */
+	0x14,  0x3F,  0x22,  0x24,  0x40,  0x24,  0x02,  0x3F,  0xA2,  0x04,  0x94,  0x12,  0x8C,  0x2A,  0x88,  0x28, 	/* 543D0 */
+	0x94,  0x41,  0x22,  0x06,  0xC1,  0x84,  0x00,  0x10,  0x3F,  0x90,  0x24,  0x10,  0x24,  0xFF,  0x3F,  0x10, 	/* 543E0 */
+	0x24,  0x10,  0x3F,  0x10,  0x24,  0x18,  0x24,  0x28,  0x3F,  0xA8,  0x04,  0xA8,  0x32,  0xA8,  0x2A,  0xE4, 	/* 543F0 */
+	0x28,  0x94,  0x40,  0x92,  0x03,  0x01,  0x85,  0x00,  0x00,  0x3F,  0xBE,  0x24,  0x22,  0x24,  0x22,  0x3F, 	/* 54400 */
+	0x22,  0x24,  0x22,  0x3F,  0x3E,  0x24,  0x30,  0x24,  0x28,  0x3F,  0xA8,  0x14,  0xA8,  0x2A,  0xA8,  0x2A, 	/* 54410 */
+	0xA4,  0x28,  0xC4,  0x41,  0x42,  0x06,  0x81,  0x86,  0x00,  0x00,  0x3F,  0x7F,  0x24,  0x40,  0x24,  0x42, 	/* 54420 */
+	0x3F,  0x42,  0x24,  0x52,  0x3F,  0x4C,  0x24,  0x44,  0x24,  0x44,  0x3F,  0xCA,  0x04,  0xCA,  0x32,  0xD2, 	/* 54430 */
+	0x2A,  0xE0,  0x28,  0xC0,  0x41,  0x7F,  0x06,  0x40,  0x88,  0x00,  0x04,  0x3F,  0x88,  0x24,  0x30,  0x24, 	/* 54440 */
+	0x20,  0x3F,  0x20,  0x24,  0x3F,  0x3F,  0x24,  0x24,  0x24,  0x24,  0x24,  0x3F,  0xA4,  0x04,  0xA4,  0x32, 	/* 54450 */
+	0xA4,  0x2A,  0xA4,  0x28,  0xA4,  0x40,  0xFF,  0x03,  0x00,  0x90,  0x00,  0x10,  0x3F,  0x88,  0x24,  0x08, 	/* 54460 */
+	0x24,  0x7F,  0x3F,  0x88,  0x24,  0x08,  0x3F,  0x88,  0x24,  0x08,  0x24,  0x7E,  0x3F,  0x88,  0x04,  0x88, 	/* 54470 */
+	0x12,  0x88,  0x2A,  0x88,  0x28,  0x88,  0x40,  0xFF,  0x03,  0x00,  0x91,  0x04,  0x00,  0x7F,  0xFC,  0x09, 	/* 54480 */
+	0x44,  0x12,  0x28,  0x3C,  0x10,  0x0A,  0x6C,  0x11,  0x83,  0x6F,  0xF8,  0x08,  0x80,  0x0F,  0xF8,  0x08, 	/* 54490 */
+	0x80,  0x0F,  0xFC,  0x00,  0x44,  0x29,  0x24,  0x24,  0x84,  0x40,  0x18,  0x92,  0x00,  0x20,  0x3F,  0x20, 	/* 544A0 */
+	0x24,  0x3E,  0x24,  0x22,  0x3F,  0x42,  0x24,  0x7A,  0x3F,  0xAA,  0x25,  0x2A,  0x24,  0x2A,  0x3F,  0xAA, 	/* 544B0 */
+	0x04,  0xBA,  0x32,  0x82,  0x2A,  0x82,  0x28,  0x82,  0x40,  0x84,  0x03,  0x18,  0x95,  0x08,  0x00,  0x7F, 	/* 544C0 */
+	0x7E,  0x09,  0x42,  0x09,  0x42,  0x11,  0x7E,  0x26,  0x00,  0x4F,  0xF8,  0x08,  0x80,  0x0F,  0xF0,  0x08, 	/* 544D0 */
+	0x80,  0x0F,  0xF0,  0x08,  0x80,  0x0F,  0xFE,  0x29,  0x22,  0x24,  0x92,  0x40,  0x0C,  0x98,  0x00,  0x10, 	/* 544E0 */
+	0x3F,  0x90,  0x24,  0x10,  0x24,  0x14,  0x3F,  0x22,  0x24,  0x26,  0x3F,  0xF9,  0x24,  0x01,  0x24,  0x01, 	/* 544F0 */
+	0x3F,  0xBE,  0x04,  0xA2,  0x32,  0xA2,  0x2A,  0xA2,  0x28,  0xA2,  0x40,  0xBE,  0x03,  0x00,  0x9B,  0x00, 	/* 54500 */
+	0x08,  0x3F,  0x88,  0x24,  0x08,  0x24,  0x7E,  0x3F,  0x4A,  0x24,  0x4A,  0x3F,  0x4A,  0x24,  0x7E,  0x24, 	/* 54510 */
+	0x08,  0x3F,  0xA8,  0x04,  0xA8,  0x32,  0x90,  0x2A,  0x98,  0x28,  0xA8,  0x40,  0xC4,  0x03,  0x03,  0x9D, 	/* 54520 */
+	0x00,  0x08,  0x3F,  0x88,  0x24,  0x08,  0x24,  0x7F,  0x3F,  0x41,  0x24,  0x51,  0x3F,  0x10,  0x24,  0x11, 	/* 54530 */
+	0x24,  0x12,  0x3F,  0x9C,  0x04,  0x90,  0x32,  0x90,  0x2A,  0x90,  0x28,  0x91,  0x40,  0x91,  0x03,  0x0F, 	/* 54540 */
+	0x9F,  0x00,  0x00,  0x3F,  0x7E,  0x24,  0x5A,  0x24,  0x5A,  0x3F,  0x5A,  0x24,  0x5A,  0x3F,  0x5A,  0x24, 	/* 54550 */
+	0x6A,  0x24,  0x6E,  0x3F,  0x62,  0x05,  0x42,  0x13,  0x42,  0x2B,  0x42,  0x29,  0x42,  0x41,  0x7E,  0x06, 	/* 54560 */
+	0x00,  0xA2,  0x00,  0x42,  0x3F,  0x22,  0x24,  0x24,  0x24,  0xFF,  0x3F,  0x24,  0x24,  0x24,  0x3F,  0x24, 	/* 54570 */
+	0x24,  0xFF,  0x24,  0x24,  0x3F,  0xA4,  0x04,  0xA4,  0x32,  0xA4,  0x2A,  0xA4,  0x28,  0xA4,  0x41,  0x44, 	/* 54580 */
+	0x06,  0x84,  0xAD,  0x00,  0x08,  0x3F,  0x88,  0x24,  0x08,  0x24,  0x7F,  0x3F,  0x10,  0x24,  0x14,  0x3F, 	/* 54590 */
+	0xE4,  0x24,  0x28,  0x24,  0x1A,  0x3F,  0x92,  0x04,  0xA4,  0x32,  0xC8,  0x2A,  0x98,  0x28,  0xA4,  0x41, 	/* 545A0 */
+	0x42,  0x06,  0x81,  0xAE,  0x00,  0x08,  0x3F,  0x88,  0x24,  0x7F,  0x24,  0x24,  0x3F,  0x22,  0x24,  0x22, 	/* 545B0 */
+	0x3F,  0x45,  0x24,  0x95,  0x24,  0x14,  0x3F,  0x94,  0x04,  0x88,  0x32,  0x88,  0x2A,  0x94,  0x28,  0xA4, 	/* 545C0 */
+	0x41,  0x42,  0x06,  0x81,  0xB1,  0x00,  0x10,  0x3F,  0x90,  0x24,  0x1C,  0x24,  0x24,  0x3F,  0x64,  0x24, 	/* 545D0 */
+	0x98,  0x3F,  0x08,  0x24,  0x14,  0x24,  0x22,  0x3F,  0xC1,  0x04,  0xBE,  0x32,  0xA2,  0x2A,  0xA2,  0x28, 	/* 545E0 */
+	0xA2,  0x41,  0x3E,  0x06,  0x00,  0xB2,  0x00,  0x22,  0x3F,  0x2A,  0x24,  0x2A,  0x24,  0x2A,  0x3F,  0x2A, 	/* 545F0 */
+	0x24,  0x2A,  0x3F,  0x7A,  0x24,  0x7E,  0x24,  0xAE,  0x3F,  0x2A,  0x05,  0x2A,  0x33,  0x2A,  0x2B,  0x4A, 	/* 54600 */
+	0x29,  0x4A,  0x42,  0x82,  0x0D,  0x02,  0xB8,  0x00,  0x00,  0x3F,  0xBE,  0x24,  0x02,  0x24,  0x7F,  0x3F, 	/* 54610 */
+	0x02,  0x24,  0x3E,  0x3F,  0x00,  0x24,  0x7F,  0x24,  0x41,  0x3F,  0xFD,  0x04,  0xA4,  0x32,  0x94,  0x2A, 	/* 54620 */
+	0x88,  0x28,  0x94,  0x41,  0x22,  0x06,  0xC1,  0xBB,  0x00,  0x00,  0x3F,  0xBE,  0x24,  0x22,  0x24,  0x22, 	/* 54630 */
+	0x3F,  0x3E,  0x24,  0x22,  0x3F,  0x22,  0x24,  0x3E,  0x24,  0x00,  0x3F,  0xBE,  0x04,  0x88,  0x32,  0x88, 	/* 54640 */
+	0x2A,  0xFF,  0x28,  0x88,  0x40,  0x88,  0x03,  0x08,  0xBF,  0x00,  0x10,  0x3F,  0x98,  0x24,  0x26,  0x24, 	/* 54650 */
+	0xFD,  0x3F,  0x28,  0x24,  0x29,  0x3F,  0x47,  0x24,  0x90,  0x24,  0x1C,  0x3F,  0xA4,  0x04,  0xE4,  0x12, 	/* 54660 */
+	0xA8,  0x2A,  0x90,  0x28,  0xA8,  0x41,  0x44,  0x06,  0x83,  0x81,  0x00,  0x10,  0x3F,  0x10,  0x24,  0x7E, 	/* 54670 */
+	0x24,  0x52,  0x3F,  0x7E,  0x24,  0x52,  0x3F,  0x7E,  0x24,  0x00,  0x24,  0xFF,  0x3F,  0x90,  0x04,  0x90, 	/* 54680 */
+	0x32,  0xBE,  0x2A,  0xA2,  0x28,  0x82,  0x40,  0x82,  0x03,  0x0C,  0x85,  0x00,  0x12,  0x3F,  0x92,  0x24, 	/* 54690 */
+	0x14,  0x24,  0x3F,  0x3F,  0x24,  0x24,  0x64,  0x3F,  0xA4,  0x24,  0x3F,  0x24,  0x24,  0x3F,  0xA4,  0x04, 	/* 546A0 */
+	0xBF,  0x32,  0xA4,  0x2A,  0xA4,  0x28,  0xA4,  0x40,  0xBF,  0x03,  0x00,  0x8E,  0x00,  0x10,  0x3F,  0x10, 	/* 546B0 */
+	0x24,  0xFE,  0x24,  0x10,  0x3F,  0x28,  0x24,  0x44,  0x24,  0x80,  0x3F,  0xFF,  0x24,  0x02,  0x24,  0x3A, 	/* 546C0 */
+	0x3F,  0xAA,  0x14,  0xAA,  0x2A,  0xBA,  0x2A,  0x82,  0x20,  0x82,  0x43,  0x06,  0x8F,  0x00,  0x24,  0x3F, 	/* 546D0 */
+	0xA4,  0x24,  0x7F,  0x24,  0x24,  0x3F,  0x24,  0x24,  0x3C,  0x3F,  0x24,  0x24,  0x24,  0x24,  0x3C,  0x3F, 	/* 546E0 */
+	0xA4,  0x04,  0xA4,  0x32,  0xFF,  0x2A,  0x80,  0x28,  0xA4,  0x40,  0xA2,  0x03,  0x42,  0x92,  0x00,  0x00, 	/* 546F0 */
+	0x3F,  0xFC,  0x24,  0x44,  0x24,  0x28,  0x3F,  0x10,  0x24,  0x2C,  0x3F,  0xD3,  0x24,  0x10,  0x24,  0x7C, 	/* 54700 */
+	0x3F,  0x54,  0x05,  0x54,  0x2B,  0x7C,  0x2B,  0x18,  0x29,  0x14,  0x41,  0x1E,  0x06,  0xE1,  0x93,  0x00, 	/* 54710 */
+	0x10,  0x3F,  0x90,  0x24,  0x28,  0x24,  0x24,  0x3F,  0x7E,  0x24,  0x91,  0x3F,  0x7E,  0x24,  0x52,  0x24, 	/* 54720 */
+	0x52,  0x3F,  0x7E,  0x05,  0x10,  0x2B,  0x18,  0x2B,  0x28,  0x29,  0x24,  0x41,  0x42,  0x06,  0x81,  0x99, 	/* 54730 */
+	0x00,  0x00,  0x3F,  0xFF,  0x24,  0x00,  0x24,  0x7E,  0x3F,  0x42,  0x24,  0x42,  0x3F,  0x7E,  0x24,  0x40, 	/* 54740 */
+	0x24,  0x7F,  0x3E,  0xD5,  0x0A,  0xD5,  0x36,  0xFF,  0x2B,  0x55,  0x2A,  0x55,  0x42,  0x55,  0x0C,  0x43, 	/* 54750 */
+	0xA8,  0x00,  0x91,  0x3F,  0x49,  0x24,  0x4A,  0x24,  0x7E,  0x3F,  0x4A,  0x24,  0x4A,  0x3F,  0x7E,  0x24, 	/* 54760 */
+	0x4A,  0x24,  0x4A,  0x3F,  0xFE,  0x04,  0x88,  0x32,  0xFF,  0x2A,  0x88,  0x28,  0x88,  0x41,  0x08,  0x06, 	/* 54770 */
+	0x08,  0xAB,  0x00,  0x80,  0x3F,  0xFE,  0x22,  0x22,  0x0F,  0xF8,  0x02,  0x20,  0x0F,  0xF8,  0x02,  0x20, 	/* 54780 */
+	0x7F,  0xFF,  0x04,  0x10,  0x0F,  0xF8,  0x14,  0x84,  0x67,  0xF3,  0x04,  0x80,  0x17,  0xFC,  0x14,  0x94, 	/* 54790 */
+	0x22,  0x58,  0xB0,  0x01,  0x24,  0x3C,  0xA8,  0x25,  0xFE,  0x24,  0x50,  0x27,  0xFF,  0x3C,  0x88,  0x25, 	/* 547A0 */
+	0xFC,  0x26,  0x92,  0x24,  0xFD,  0x3C,  0x90,  0x24,  0xFC,  0x24,  0x90,  0x24,  0xFE,  0x25,  0x52,  0x25, 	/* 547B0 */
+	0x2A,  0x4E,  0x0C,  0xB7,  0x00,  0x00,  0x3F,  0xFE,  0x24,  0x2A,  0x24,  0x24,  0x3E,  0x94,  0x24,  0x48, 	/* 547C0 */
+	0x3E,  0x14,  0x24,  0x2A,  0x24,  0x49,  0x3F,  0xBE,  0x00,  0xAA,  0x34,  0xBE,  0x2A,  0x8C,  0x2A,  0x8A, 	/* 547D0 */
+	0x40,  0xFD,  0x03,  0x01,  0xBE,  0x00,  0x00,  0x3F,  0x7E,  0x24,  0x52,  0x24,  0x7E,  0x3F,  0x52,  0x24, 	/* 547E0 */
+	0x7E,  0x3F,  0x10,  0x24,  0x64,  0x24,  0x18,  0x3F,  0x36,  0x05,  0xFD,  0x33,  0x08,  0x2B,  0x2C,  0x29, 	/* 547F0 */
+	0x2A,  0x41,  0x49,  0x06,  0x08,  0x80,  0x02,  0x20,  0x3F,  0xFF,  0x02,  0x20,  0x0F,  0xF8,  0x08,  0x08, 	/* 54800 */
+	0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x01,  0x00,  0x7F,  0xFF,  0x0C,  0x88,  0x17,  0xF4,  0x64,  0x83, 	/* 54810 */
+	0x17,  0xFC,  0x12,  0x54,  0x21,  0x18,  0x82,  0x00,  0x10,  0x3F,  0xA8,  0x24,  0x7C,  0x24,  0x44,  0x3E, 	/* 54820 */
+	0xAA,  0x24,  0xFF,  0x3E,  0x10,  0x24,  0x28,  0x24,  0x24,  0x3F,  0x4B,  0x05,  0xB4,  0x33,  0x08,  0x2B, 	/* 54830 */
+	0x72,  0x29,  0x04,  0x41,  0x18,  0x06,  0xE0,  0x83,  0x00,  0x00,  0x3F,  0xFF,  0x24,  0x14,  0x24,  0x7F, 	/* 54840 */
+	0x3F,  0x55,  0x24,  0x55,  0x3F,  0x7F,  0x24,  0x00,  0x24,  0x3E,  0x3F,  0x80,  0x04,  0xFF,  0x12,  0x88, 	/* 54850 */
+	0x2A,  0xAC,  0x28,  0xAA,  0x41,  0x49,  0x06,  0x18,  0x85,  0x00,  0x00,  0x3F,  0x7F,  0x24,  0x40,  0x24, 	/* 54860 */
+	0x5C,  0x3F,  0x54,  0x24,  0x54,  0x3F,  0x5C,  0x24,  0x40,  0x24,  0x7E,  0x3F,  0x6A,  0x05,  0x6A,  0x33, 	/* 54870 */
+	0x7E,  0x2B,  0x40,  0x29,  0x40,  0x41,  0x7F,  0x06,  0x00,  0x8D,  0x00,  0x10,  0x3F,  0x7C,  0x24,  0x10, 	/* 54880 */
+	0x24,  0xFE,  0x3F,  0x00,  0x24,  0x44,  0x3F,  0xFF,  0x24,  0x44,  0x24,  0x74,  0x3F,  0xCF,  0x05,  0x00, 	/* 54890 */
+	0x33,  0xFF,  0x2B,  0x28,  0x29,  0x29,  0x42,  0x49,  0x0D,  0x87,  0x95,  0x00,  0x04,  0x3F,  0xF8,  0x28, 	/* 548A0 */
+	0x10,  0x28,  0xFF,  0x3E,  0x24,  0x28,  0x7E,  0x3E,  0xA5,  0x28,  0x3C,  0x28,  0x00,  0x3E,  0xFE,  0x0A, 	/* 548B0 */
+	0x82,  0x36,  0xBA,  0x2A,  0xAA,  0x2A,  0xBA,  0x42,  0x82,  0x0C,  0x86,  0x97,  0x00,  0x10,  0x3F,  0x90, 	/* 548C0 */
+	0x24,  0x28,  0x24,  0x24,  0x3F,  0x42,  0x24,  0xBD,  0x3F,  0x00,  0x24,  0xEE,  0x24,  0xAA,  0x3F,  0xAA, 	/* 548D0 */
+	0x05,  0xEE,  0x33,  0x44,  0x2B,  0x44,  0x29,  0x66,  0x42,  0x99,  0x0D,  0x10,  0x9A,  0x0A,  0x20,  0x3F, 	/* 548E0 */
+	0xBF,  0x0A,  0x24,  0x1F,  0xD4,  0x1E,  0x98,  0x2A,  0x88,  0x4E,  0x94,  0x03,  0x22,  0x0F,  0xF9,  0x08, 	/* 548F0 */
+	0x80,  0x0F,  0xF8,  0x08,  0x80,  0x0F,  0xFC,  0x29,  0x24,  0x24,  0x94,  0x40,  0x18,  0x9B,  0x00,  0x00, 	/* 54900 */
+	0x3F,  0xFE,  0x24,  0xAA,  0x24,  0xFE,  0x3F,  0x10,  0x24,  0x7C,  0x3F,  0x10,  0x24,  0xFF,  0x24,  0x44, 	/* 54910 */
+	0x3F,  0x28,  0x05,  0xFF,  0x33,  0x10,  0x2B,  0xFE,  0x29,  0x10,  0x41,  0x10,  0x06,  0x10,  0x9F,  0x00, 	/* 54920 */
+	0x00,  0x3F,  0xF0,  0x24,  0xBE,  0x24,  0xE2,  0x3E,  0xAA,  0x24,  0xE4,  0x3E,  0xA4,  0x25,  0xEA,  0x24, 	/* 54930 */
+	0x31,  0x3E,  0x48,  0x02,  0x52,  0x2A,  0x94,  0x2A,  0x58,  0x2A,  0x54,  0x42,  0x93,  0x0C,  0x10,  0xA2, 	/* 54940 */
+	0x00,  0x10,  0x3F,  0x1E,  0x24,  0x10,  0x24,  0xFF,  0x3E,  0x9A,  0x24,  0xF1,  0x3E,  0xBF,  0x24,  0xAA, 	/* 54950 */
+	0x24,  0xBE,  0x3E,  0xAA,  0x02,  0xBE,  0x2A,  0x80,  0x2A,  0xFE,  0x23,  0x5A,  0x43,  0xFF,  0x0C,  0x00, 	/* 54960 */
+	0xA4,  0x00,  0x10,  0x3F,  0xFF,  0x24,  0x00,  0x24,  0xEE,  0x3E,  0xAA,  0x24,  0xEE,  0x3E,  0x28,  0x24, 	/* 54970 */
+	0xFE,  0x24,  0x28,  0x3F,  0xFE,  0x05,  0x28,  0x33,  0xFF,  0x2B,  0x6A,  0x29,  0xA4,  0x41,  0x32,  0x06, 	/* 54980 */
+	0xC1,  0xA5,  0x00,  0x15,  0x3F,  0x76,  0x24,  0x14,  0x24,  0x35,  0x3F,  0xC3,  0x24,  0x7E,  0x3F,  0x4A, 	/* 54990 */
+	0x24,  0x7E,  0x24,  0x4A,  0x3F,  0x7E,  0x05,  0x24,  0x33,  0x7E,  0x2B,  0x24,  0x29,  0xFF,  0x41,  0x24, 	/* 549A0 */
+	0x06,  0x42,  0xA9,  0x00,  0x24,  0x3F,  0xFF,  0x24,  0x24,  0x24,  0xEE,  0x3F,  0xAA,  0x24,  0xEE,  0x3F, 	/* 549B0 */
+	0x12,  0x24,  0x24,  0x24,  0x7F,  0x3F,  0x48,  0x05,  0xFE,  0x33,  0x48,  0x2B,  0x7E,  0x29,  0x48,  0x41, 	/* 549C0 */
+	0x7F,  0x06,  0x00,  0xAA,  0x00,  0x00,  0x3F,  0xEF,  0x24,  0x00,  0x25,  0xEF,  0x3F,  0x29,  0x24,  0x10, 	/* 549D0 */
+	0x3E,  0xFF,  0x24,  0xA8,  0x24,  0xFE,  0x3E,  0xAA,  0x02,  0xFE,  0x2A,  0xA4,  0x2A,  0xBF,  0x2B,  0x24, 	/* 549E0 */
+	0x42,  0x35,  0x0C,  0xC3,  0xAB,  0x00,  0x00,  0x07,  0xF8,  0x04,  0x80,  0x07,  0xF0,  0x04,  0x80,  0x17, 	/* 549F0 */
+	0xF8,  0x12,  0xA8,  0x20,  0x18,  0x1F,  0xBF,  0x14,  0x28,  0x1F,  0x3E,  0x14,  0x28,  0x1F,  0xBF,  0x2A, 	/* 54A00 */
+	0xD5,  0x28,  0xD1,  0x43,  0x06,  0xA8,  0x00,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x09,  0xF0,  0x09,  0x10, 	/* 54A10 */
+	0x7F,  0xFE,  0x40,  0x02,  0x4F,  0xF2,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10, 	/* 54A20 */
+	0x08,  0x10,  0x08,  0x10,  0x08,  0x30,  0xAD,  0x00,  0x00,  0x3F,  0x3E,  0x21,  0x08,  0x2F,  0x08,  0x29, 	/* 54A30 */
+	0x08,  0x29,  0x08,  0x7F,  0x88,  0x40,  0xFF,  0x5F,  0x88,  0x11,  0x08,  0x1F,  0x08,  0x11,  0x08,  0x1F, 	/* 54A40 */
+	0x08,  0x11,  0x08,  0x11,  0x08,  0x13,  0x08,  0xB0,  0x00,  0x00,  0x3F,  0x3C,  0x21,  0x24,  0x2F,  0x25, 	/* 54A50 */
+	0x29,  0x25,  0x29,  0x25,  0x7F,  0xC3,  0x40,  0x80,  0x1F,  0x7C,  0x11,  0x24,  0x1F,  0x24,  0x11,  0x14, 	/* 54A60 */
+	0x1F,  0x08,  0x11,  0x14,  0x11,  0x22,  0x13,  0xC1,  0xB8,  0x00,  0x10,  0x3E,  0x10,  0x22,  0x10,  0x2E, 	/* 54A70 */
+	0xFF,  0x2A,  0x10,  0x2A,  0x14,  0x7F,  0x64,  0x41,  0x28,  0x7F,  0x12,  0x62,  0x12,  0x3E,  0x24,  0x22, 	/* 54A80 */
+	0xC4,  0x3E,  0x08,  0x22,  0x14,  0x22,  0x22,  0x26,  0xC2,  0xBC,  0x00,  0x10,  0x3F,  0x10,  0x21,  0x3C, 	/* 54A90 */
+	0x2F,  0x24,  0x29,  0x44,  0x29,  0xA8,  0x7F,  0x90,  0x40,  0xA8,  0x5F,  0x44,  0x11,  0x82,  0x1F,  0x7D, 	/* 54AA0 */
+	0x11,  0x44,  0x1F,  0x44,  0x11,  0x44,  0x11,  0x7C,  0x13,  0x00,  0x80,  0x00,  0x10,  0x3E,  0x20,  0x22, 	/* 54AB0 */
+	0x7E,  0x2E,  0x52,  0x2A,  0x52,  0x2A,  0x7E,  0x7F,  0x52,  0x41,  0x52,  0x3F,  0x7E,  0x22,  0x28,  0x3E, 	/* 54AC0 */
+	0x48,  0x23,  0xFF,  0x3E,  0x08,  0x22,  0x08,  0x22,  0x08,  0x26,  0x08,  0x84,  0x00,  0x08,  0x3E,  0x08, 	/* 54AD0 */
+	0x22,  0x7F,  0x2E,  0x88,  0x2A,  0x50,  0x7F,  0x5E,  0x41,  0x32,  0x7E,  0x3E,  0x23,  0xD2,  0x3E,  0x52, 	/* 54AE0 */
+	0x22,  0x5E,  0x3E,  0x52,  0x22,  0x52,  0x22,  0xB6,  0x23,  0x10,  0x26,  0x0F,  0x8F,  0x00,  0x10,  0x3E, 	/* 54AF0 */
+	0x7E,  0x22,  0x52,  0x2E,  0xFF,  0x2A,  0x52,  0x2A,  0x7E,  0x7F,  0x10,  0x41,  0x7E,  0x3E,  0x52,  0x22, 	/* 54B00 */
+	0x7E,  0x3E,  0x10,  0x23,  0xFF,  0x3E,  0x24,  0x22,  0x68,  0x22,  0x1C,  0x26,  0xE2,  0x91,  0x00,  0x00, 	/* 54B10 */
+	0x3E,  0xFE,  0x22,  0xAA,  0x2E,  0xAA,  0x2A,  0xFE,  0x2A,  0x40,  0x7F,  0x7E,  0x41,  0xA2,  0x3F,  0xFA, 	/* 54B20 */
+	0x22,  0xAA,  0x3E,  0xFA,  0x22,  0x32,  0x3E,  0x2A,  0x23,  0xF6,  0x22,  0x02,  0x26,  0x0C,  0x93,  0x00, 	/* 54B30 */
+	0x10,  0x3F,  0x7F,  0x22,  0x90,  0x2E,  0x9E,  0x2A,  0x24,  0x2B,  0x5F,  0x7E,  0x80,  0x42,  0x9E,  0x3E, 	/* 54B40 */
+	0x12,  0x25,  0xDE,  0x3C,  0x52,  0x24,  0x5E,  0x3C,  0x52,  0x24,  0xB6,  0x24,  0x98,  0x2D,  0x07,  0x94, 	/* 54B50 */
+	0x00,  0x28,  0x3E,  0xFE,  0x22,  0xAA,  0x2E,  0xFE,  0x2A,  0xAA,  0x2A,  0xFE,  0x7F,  0x00,  0x41,  0xFF, 	/* 54B60 */
+	0x3F,  0x00,  0x22,  0x7C,  0x3E,  0x44,  0x22,  0x7C,  0x3E,  0x44,  0x22,  0x28,  0x23,  0xFF,  0x26,  0x00, 	/* 54B70 */
+	0x98,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x07,  0xF0,  0x04,  0x10,  0x07,  0xF0,  0x00, 	/* 54B80 */
+	0x00,  0x3F,  0xFE,  0x20,  0x02,  0x27,  0xF2,  0x24,  0x12,  0x24,  0x12,  0x27,  0xF2,  0x20,  0x02,  0x20, 	/* 54B90 */
+	0x06,  0x9E,  0x08,  0x00,  0x08,  0x7C,  0x7F,  0x44,  0x00,  0x44,  0x3E,  0x7C,  0x22,  0xEE,  0x3E,  0xAA, 	/* 54BA0 */
+	0x00,  0xAA,  0x7F,  0xEE,  0x41,  0x10,  0x5D,  0xFF,  0x55,  0x38,  0x55,  0x54,  0x5D,  0x92,  0x41,  0x11, 	/* 54BB0 */
+	0x43,  0x10,  0x9F,  0x00,  0x04,  0x1F,  0x84,  0x10,  0x08,  0x1F,  0x08,  0x10,  0x12,  0x10,  0x22,  0x1F, 	/* 54BC0 */
+	0x44,  0x10,  0x04,  0x10,  0x09,  0x7F,  0xD1,  0x14,  0x22,  0x12,  0x02,  0x11,  0x04,  0x23,  0x08,  0x7C, 	/* 54BD0 */
+	0x90,  0x00,  0xA0,  0xA2,  0x00,  0x04,  0x1F,  0x18,  0x10,  0x62,  0x1E,  0x0C,  0x10,  0x31,  0x7F,  0xC2, 	/* 54BE0 */
+	0x12,  0x0C,  0x1D,  0x30,  0x70,  0xC0,  0x04,  0x44,  0x04,  0x7C,  0x07,  0xC4,  0x7C,  0x44,  0x04,  0x59, 	/* 54BF0 */
+	0x04,  0x01,  0x03,  0xFF,  0xA3,  0x00,  0x04,  0x1F,  0x18,  0x10,  0x62,  0x1E,  0x04,  0x10,  0x19,  0x7F, 	/* 54C00 */
+	0xE2,  0x12,  0x04,  0x1D,  0x18,  0x70,  0xE0,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x80,  0x01,  0xF8,  0x02, 	/* 54C10 */
+	0x08,  0x0C,  0x08,  0x30,  0x70,  0xA6,  0x00,  0x04,  0x1F,  0x18,  0x10,  0x62,  0x1E,  0x0C,  0x10,  0x31, 	/* 54C20 */
+	0x7F,  0xC6,  0x12,  0x18,  0x7D,  0x60,  0x00,  0x10,  0x0F,  0xE0,  0x02,  0x00,  0x3F,  0xF8,  0x02,  0x00, 	/* 54C30 */
+	0x7F,  0xFE,  0x02,  0x04,  0x01,  0xFC,  0xAA,  0x00,  0x04,  0x1F,  0x98,  0x10,  0x60,  0x1F,  0x02,  0x10, 	/* 54C40 */
+	0x0C,  0x7F,  0x71,  0x12,  0x02,  0x1D,  0x0C,  0x21,  0x70,  0x7F,  0xFF,  0x01,  0x00,  0x03,  0xF0,  0x0E, 	/* 54C50 */
+	0x20,  0x71,  0xC0,  0x03,  0x60,  0x3C,  0x1E,  0xAB,  0x00,  0x04,  0x1F,  0x18,  0x10,  0x62,  0x1E,  0x0C, 	/* 54C60 */
+	0x10,  0x31,  0x7F,  0xC6,  0x12,  0x18,  0x7D,  0x60,  0x00,  0x00,  0x3F,  0xFC,  0x01,  0x04,  0x06,  0x0C, 	/* 54C70 */
+	0x38,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0xAD,  0x00,  0x04,  0x1F,  0x98,  0x10,  0x62,  0x1F, 	/* 54C80 */
+	0x0C,  0x10,  0x31,  0x7F,  0xC2,  0x0A,  0x0C,  0x13,  0x70,  0x3C,  0x80,  0x04,  0x20,  0x24,  0x22,  0x27, 	/* 54C90 */
+	0xEC,  0x24,  0x30,  0x25,  0xA1,  0x2E,  0x21,  0x70,  0x1F,  0xAE,  0x00,  0x04,  0x1F,  0x18,  0x10,  0x62, 	/* 54CA0 */
+	0x1E,  0x0C,  0x10,  0x31,  0x7F,  0xC6,  0x12,  0x18,  0x7D,  0x60,  0x00,  0x88,  0x00,  0x84,  0x7F,  0xFF, 	/* 54CB0 */
+	0x01,  0x08,  0x02,  0x90,  0x0C,  0x60,  0x71,  0x98,  0x0E,  0x07,  0xAF,  0x00,  0x04,  0x1F,  0x18,  0x10, 	/* 54CC0 */
+	0x62,  0x1E,  0x0C,  0x10,  0x31,  0x7F,  0xC6,  0x12,  0x18,  0x7D,  0x60,  0x00,  0x80,  0x0F,  0xF8,  0x08, 	/* 54CD0 */
+	0x88,  0x0F,  0xF8,  0x08,  0x88,  0x7F,  0xFF,  0x08,  0x08,  0x08,  0x18,  0xB1,  0x00,  0x04,  0x1F,  0x18, 	/* 54CE0 */
+	0x10,  0x62,  0x1E,  0x0C,  0x10,  0x31,  0x7F,  0xC6,  0x12,  0x18,  0x7D,  0x60,  0x02,  0x20,  0x03,  0xFC, 	/* 54CF0 */
+	0x04,  0x04,  0x1F,  0xE4,  0x64,  0x24,  0x07,  0xF9,  0x04,  0x01,  0x03,  0xFF,  0xB4,  0x00,  0x04,  0x1F, 	/* 54D00 */
+	0x18,  0x10,  0x62,  0x1E,  0x0C,  0x10,  0x31,  0x7F,  0xC6,  0x12,  0x18,  0x7D,  0x60,  0x1F,  0xFC,  0x02, 	/* 54D10 */
+	0x24,  0x1F,  0xFC,  0x12,  0x20,  0x1F,  0xFE,  0x02,  0x22,  0x04,  0x2C,  0x08,  0x20,  0xB7,  0x00,  0x04, 	/* 54D20 */
+	0x1F,  0x18,  0x10,  0x62,  0x1E,  0x0C,  0x10,  0x31,  0x7F,  0xC6,  0x12,  0x18,  0x7D,  0x60,  0x02,  0x20, 	/* 54D30 */
+	0x1F,  0xFC,  0x12,  0x24,  0x1F,  0xFC,  0x12,  0x24,  0x12,  0x24,  0x1F,  0xFC,  0x00,  0x00,  0xBB,  0x00, 	/* 54D40 */
+	0x04,  0x1F,  0x18,  0x10,  0x62,  0x1E,  0x0C,  0x10,  0x31,  0x7F,  0xC6,  0x12,  0x18,  0x7D,  0x60,  0x00, 	/* 54D50 */
+	0x80,  0x7F,  0xFF,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x86, 	/* 54D60 */
+	0x00,  0x04,  0x1F,  0x18,  0x10,  0x62,  0x1E,  0x0C,  0x10,  0x31,  0x7F,  0xC6,  0x12,  0x18,  0x7D,  0x60, 	/* 54D70 */
+	0x08,  0x5C,  0x7F,  0x44,  0x08,  0x54,  0x1C,  0x92,  0x1B,  0x31,  0x28,  0x48,  0x49,  0xFC,  0x08,  0x02, 	/* 54D80 */
+	0x98,  0x00,  0x04,  0x1F,  0x18,  0x10,  0x62,  0x1E,  0x0C,  0x10,  0x31,  0x7F,  0xC6,  0x12,  0x18,  0x7D, 	/* 54D90 */
+	0x60,  0x07,  0xF0,  0x04,  0x10,  0x1F,  0xFC,  0x12,  0x24,  0x7F,  0xFC,  0x06,  0x30,  0x01,  0xC0,  0x7E, 	/* 54DA0 */
+	0x3F,  0x9A,  0x00,  0x04,  0x1F,  0x18,  0x10,  0x62,  0x1E,  0x0C,  0x10,  0x31,  0x7F,  0xC6,  0x12,  0x18, 	/* 54DB0 */
+	0x7D,  0x60,  0x04,  0xFF,  0x18,  0x10,  0x62,  0x7E,  0x0C,  0x42,  0x31,  0x7E,  0x02,  0x42,  0x0C,  0x7E, 	/* 54DC0 */
+	0x71,  0xC1,  0x9F,  0x00,  0x04,  0x1F,  0x18,  0x10,  0x62,  0x1E,  0x0C,  0x10,  0x31,  0x7F,  0xC6,  0x12, 	/* 54DD0 */
+	0x18,  0x7D,  0x60,  0x0F,  0xFC,  0x09,  0x24,  0x7F,  0xFF,  0x04,  0x10,  0x07,  0xF4,  0x01,  0x48,  0x3E, 	/* 54DE0 */
+	0x30,  0x03,  0x0F,  0xA2,  0x00,  0x04,  0x1F,  0x18,  0x10,  0x62,  0x1E,  0x0C,  0x10,  0x31,  0x7F,  0xC6, 	/* 54DF0 */
+	0x12,  0x18,  0x7D,  0x60,  0x3F,  0xFE,  0x29,  0x22,  0x33,  0xF0,  0x0C,  0x10,  0x77,  0xF0,  0x04,  0x10, 	/* 54E00 */
+	0x07,  0xF0,  0x1C,  0x0C,  0xA3,  0x1F,  0x0C,  0x10,  0xF0,  0x1E,  0x06,  0x10,  0x78,  0x7F,  0x03,  0x12, 	/* 54E10 */
+	0x3C,  0x7D,  0x48,  0x04,  0x90,  0x3F,  0xFC,  0x25,  0x24,  0x3F,  0xFC,  0x10,  0x88,  0x1E,  0xE8,  0x10, 	/* 54E20 */
+	0x89,  0x1E,  0xE5,  0x71,  0x83,  0xA5,  0x00,  0x00,  0x5F,  0x7A,  0x44,  0x22,  0x5F,  0x7A,  0x44,  0x22, 	/* 54E30 */
+	0x5F,  0x7A,  0x40,  0x02,  0x40,  0x02,  0x40,  0x02,  0x40,  0x02,  0x40,  0x02,  0x40,  0x02,  0x40,  0x02, 	/* 54E40 */
+	0x40,  0x02,  0x40,  0x02,  0x40,  0x06,  0xA7,  0x00,  0x00,  0x5F,  0x7A,  0x44,  0x22,  0x5E,  0x7A,  0x44, 	/* 54E50 */
+	0x22,  0x5F,  0x7A,  0x40,  0x02,  0x41,  0x02,  0x5F,  0xFA,  0x41,  0x02,  0x4F,  0xF2,  0x49,  0x12,  0x49, 	/* 54E60 */
+	0x12,  0x49,  0x62,  0x49,  0x02,  0x41,  0x06,  0xA8,  0x00,  0x00,  0x5F,  0x7A,  0x44,  0x22,  0x5E,  0x7A, 	/* 54E70 */
+	0x44,  0x22,  0x5F,  0x7A,  0x40,  0x02,  0x42,  0x42,  0x4F,  0xF2,  0x42,  0x42,  0x42,  0x42,  0x5F,  0xFA, 	/* 54E80 */
+	0x42,  0x42,  0x44,  0x22,  0x58,  0x12,  0x40,  0x06,  0xA9,  0x00,  0x00,  0x5F,  0x7A,  0x44,  0x22,  0x5E, 	/* 54E90 */
+	0x7A,  0x44,  0x22,  0x5F,  0x7A,  0x41,  0x02,  0x4E,  0x72,  0x48,  0x12,  0x4E,  0x72,  0x48,  0x12,  0x4F, 	/* 54EA0 */
+	0xF2,  0x41,  0x42,  0x46,  0x4A,  0x58,  0x3A,  0x40,  0x06,  0xAA,  0x00,  0x00,  0x5F,  0x7A,  0x44,  0x12, 	/* 54EB0 */
+	0x5E,  0x7A,  0x44,  0x12,  0x5F,  0x7A,  0x40,  0x02,  0x5F,  0x92,  0x40,  0x12,  0x4F,  0xFE,  0x49,  0x92, 	/* 54EC0 */
+	0x4F,  0x52,  0x51,  0x12,  0x4A,  0x12,  0x47,  0x12,  0x58,  0x32,  0xAE,  0x00,  0x00,  0x5F,  0x7A,  0x44, 	/* 54ED0 */
+	0x12,  0x4E,  0x7A,  0x44,  0x12,  0x5F,  0x7A,  0x43,  0xC2,  0x4C,  0x82,  0x5F,  0xFA,  0x45,  0x6A,  0x5D, 	/* 54EE0 */
+	0x5A,  0x45,  0x6A,  0x5F,  0xFA,  0x45,  0x42,  0x5D,  0x4A,  0x41,  0x3A,  0xAF,  0x01,  0x00,  0x20,  0xA4, 	/* 54EF0 */
+	0x26,  0x24,  0x21,  0x44,  0x30,  0x94,  0x29,  0x4C,  0x22,  0x24,  0x2D,  0x24,  0x20,  0x84,  0x3F,  0xFC, 	/* 54F00 */
+	0x08,  0x08,  0x08,  0x30,  0x0F,  0xC0,  0x08,  0x02,  0x08,  0x02,  0x07,  0xFE,  0xB1,  0x09,  0x08,  0x09, 	/* 54F10 */
+	0xE8,  0x7E,  0x9F,  0x19,  0xEC,  0x2E,  0xBA,  0x4B,  0xE9,  0x08,  0x08,  0x7F,  0xFE,  0x4A,  0x82,  0x24, 	/* 54F20 */
+	0x8A,  0x2A,  0xF0,  0x3F,  0x84,  0x12,  0x78,  0x1C,  0x02,  0x11,  0x0C,  0x0F,  0x70,  0xB2,  0x00,  0x00, 	/* 54F30 */
+	0x7F,  0xFF,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0x3F,  0xFE,  0x22,  0x22, 	/* 54F40 */
+	0x22,  0x26,  0x24,  0x1E,  0x2B,  0xF2,  0x30,  0x82,  0x20,  0x82,  0x20,  0x82,  0x20,  0x06,  0xBB,  0x78, 	/* 54F50 */
+	0x9E,  0x0A,  0xA2,  0x39,  0xCE,  0x27,  0xF8,  0x39,  0xCE,  0x0A,  0xA2,  0x30,  0x8C,  0x7F,  0xFF,  0x08, 	/* 54F60 */
+	0x08,  0x0F,  0xF8,  0x00,  0x00,  0x3F,  0xFE,  0x22,  0x26,  0x2C,  0x1E,  0x23,  0xE2,  0x20,  0x86,  0xBC, 	/* 54F70 */
+	0x01,  0x00,  0x02,  0x00,  0x1F,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x1F,  0xF8,  0x11,  0x08,  0x11,  0x08, 	/* 54F80 */
+	0x1F,  0xF8,  0x02,  0x90,  0x02,  0x90,  0x04,  0xA8,  0x04,  0xF8,  0x08,  0x8A,  0x10,  0x42,  0x60,  0x3E, 	/* 54F90 */
+	0x81,  0x08,  0x04,  0x10,  0x44,  0x3F,  0x24,  0x25,  0x14,  0x25,  0x94,  0x3F,  0x44,  0x25,  0x24,  0x25, 	/* 54FA0 */
+	0x24,  0x3F,  0x07,  0x0C,  0xFC,  0x0C,  0x84,  0x0D,  0x44,  0x17,  0xC4,  0x14,  0x06,  0x22,  0x02,  0x41, 	/* 54FB0 */
+	0xFE,  0x82,  0x00,  0x20,  0x00,  0x40,  0x3D,  0xFC,  0x01,  0x24,  0x01,  0x24,  0x01,  0xFC,  0x7F,  0x24, 	/* 54FC0 */
+	0x09,  0x24,  0x09,  0xFC,  0x08,  0x54,  0x14,  0x54,  0x12,  0x5A,  0x1E,  0x5E,  0x62,  0x91,  0x03,  0x11, 	/* 54FD0 */
+	0x0C,  0x0F,  0x83,  0x08,  0x20,  0x08,  0x24,  0x10,  0x22,  0x3E,  0xFF,  0x2A,  0x20,  0x2A,  0x24,  0x3E, 	/* 54FE0 */
+	0x24,  0x2A,  0x34,  0x2A,  0x54,  0x3F,  0x58,  0x15,  0x48,  0x16,  0xC8,  0x17,  0x94,  0x14,  0xA2,  0x23, 	/* 54FF0 */
+	0x41,  0x41,  0xFF,  0x84,  0x08,  0x20,  0x08,  0x40,  0x11,  0xFC,  0x3D,  0x24,  0x25,  0x24,  0x25,  0xFC, 	/* 55000 */
+	0x25,  0x24,  0x3D,  0x24,  0x25,  0xFC,  0x24,  0x54,  0x24,  0x54,  0x24,  0x5A,  0x3C,  0x9E,  0x00,  0x91, 	/* 55010 */
+	0x01,  0x11,  0x06,  0x0F,  0x85,  0x08,  0x08,  0x10,  0x08,  0x3F,  0x08,  0x29,  0x7E,  0x29,  0x08,  0x3F, 	/* 55020 */
+	0x08,  0x29,  0xFF,  0x29,  0x08,  0x3F,  0x9C,  0x14,  0x9C,  0x14,  0xAA,  0x15,  0x49,  0x15,  0x48,  0x27, 	/* 55030 */
+	0xA9,  0x22,  0x01,  0x41,  0xFF,  0x8D,  0x08,  0x00,  0x08,  0xFE,  0x10,  0x82,  0x3E,  0xC6,  0x2A,  0xAA, 	/* 55040 */
+	0x2A,  0xFE,  0x3E,  0x92,  0x2A,  0x92,  0x2A,  0xBE,  0x3E,  0xA2,  0x15,  0xA2,  0x16,  0x9A,  0x17,  0x82, 	/* 55050 */
+	0x14,  0x86,  0x22,  0x01,  0x41,  0xFF,  0x8E,  0x08,  0x00,  0x09,  0xFF,  0x10,  0x10,  0x3E,  0x10,  0x2A, 	/* 55060 */
+	0xFE,  0x2A,  0x92,  0x3E,  0x92,  0x2A,  0xFE,  0x2A,  0xB6,  0x3E,  0xB6,  0x15,  0xDA,  0x16,  0x92,  0x17, 	/* 55070 */
+	0x92,  0x14,  0x86,  0x22,  0x01,  0x41,  0xFF,  0x8F,  0x02,  0x10,  0x04,  0x20,  0x38,  0x7E,  0x08,  0x52, 	/* 55080 */
+	0x7F,  0x52,  0x1C,  0x7E,  0x2A,  0x52,  0x49,  0x52,  0x08,  0x7E,  0x7F,  0xAA,  0x12,  0x2A,  0x12,  0x2D, 	/* 55090 */
+	0x3C,  0x4F,  0x06,  0x48,  0x09,  0x89,  0x31,  0x07,  0x91,  0x08,  0x10,  0x09,  0xFF,  0x10,  0x6C,  0x3E, 	/* 550A0 */
+	0x54,  0x2A,  0x6C,  0x2A,  0x7C,  0x3E,  0x10,  0x2A,  0xFE,  0x2A,  0x92,  0x3E,  0xAA,  0x15,  0xFE,  0x16, 	/* 550B0 */
+	0x86,  0x17,  0x82,  0x14,  0x86,  0x22,  0x01,  0x41,  0xFF,  0x94,  0x00,  0x40,  0x1F,  0xFF,  0x11,  0x08, 	/* 550C0 */
+	0x1F,  0xFF,  0x11,  0x8C,  0x13,  0x5A,  0x15,  0x29,  0x1B,  0xFC,  0x12,  0x44,  0x13,  0xFC,  0x12,  0x44, 	/* 550D0 */
+	0x13,  0xFC,  0x20,  0xAA,  0x21,  0x2E,  0x46,  0x21,  0x18,  0x1F,  0x98,  0x00,  0x00,  0x1F,  0xFF,  0x14, 	/* 550E0 */
+	0x94,  0x17,  0x92,  0x14,  0xFF,  0x17,  0x98,  0x14,  0x94,  0x15,  0xA2,  0x14,  0x41,  0x13,  0xF8,  0x12, 	/* 550F0 */
+	0x48,  0x13,  0xF8,  0x22,  0x4C,  0x23,  0xF9,  0x41,  0x2D,  0x1E,  0x3F,  0x9A,  0x02,  0x00,  0x02,  0x00, 	/* 55100 */
+	0x03,  0xF0,  0x04,  0x20,  0x18,  0x40,  0x6F,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88, 	/* 55110 */
+	0x08,  0x88,  0x0F,  0xF8,  0x10,  0x08,  0x14,  0x44,  0x22,  0x22,  0x42,  0x22,  0xAF,  0x02,  0x00,  0x07, 	/* 55120 */
+	0xE0,  0x18,  0x40,  0x7F,  0xFC,  0x10,  0x84,  0x1F,  0xFC,  0x10,  0x84,  0x1F,  0xFC,  0x14,  0x48,  0x22, 	/* 55130 */
+	0x24,  0x4F,  0xFA,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x00,  0x00,  0xB4,  0x10,  0x10, 	/* 55140 */
+	0x1E,  0x10,  0x12,  0x10,  0x24,  0xFF,  0x7F,  0x10,  0x29,  0x10,  0x29,  0x1E,  0x3F,  0x12,  0x29,  0x12, 	/* 55150 */
+	0x29,  0x12,  0x3F,  0x12,  0x05,  0x22,  0x32,  0xA2,  0x2A,  0x42,  0x28,  0x84,  0x41,  0x18,  0x83,  0x08, 	/* 55160 */
+	0x00,  0x0E,  0xFE,  0x12,  0x10,  0x24,  0x54,  0x7F,  0x54,  0x29,  0x52,  0x29,  0x92,  0x3F,  0x10,  0x29, 	/* 55170 */
+	0xFF,  0x29,  0x10,  0x3F,  0x10,  0x05,  0x10,  0x32,  0x90,  0x2A,  0x10,  0x28,  0x10,  0x40,  0x10,  0x8E, 	/* 55180 */
+	0x08,  0x10,  0x0E,  0x10,  0x12,  0x10,  0x24,  0x10,  0x7F,  0x1F,  0x29,  0x10,  0x29,  0x10,  0x3F,  0x10, 	/* 55190 */
+	0x29,  0x10,  0x29,  0x7E,  0x3F,  0x42,  0x02,  0x42,  0x15,  0x42,  0x2A,  0x42,  0x2A,  0x7E,  0x40,  0x00, 	/* 551A0 */
+	0x91,  0x08,  0x20,  0x0E,  0x20,  0x12,  0x3E,  0x24,  0x42,  0x7F,  0x42,  0x29,  0xFA,  0x29,  0x4A,  0x3F, 	/* 551B0 */
+	0x4A,  0x29,  0x7A,  0x29,  0x42,  0x3F,  0x5C,  0x05,  0x40,  0x32,  0xC1,  0x2A,  0x41,  0x28,  0x3F,  0x40, 	/* 551C0 */
+	0x00,  0x92,  0x08,  0x12,  0x0E,  0x12,  0x12,  0x12,  0x24,  0x22,  0x7F,  0x3F,  0x29,  0x62,  0x29,  0xB2, 	/* 551D0 */
+	0x3F,  0x2A,  0x29,  0x2A,  0x29,  0x2A,  0x3F,  0x22,  0x05,  0x22,  0x32,  0xA2,  0x2A,  0x22,  0x28,  0x22, 	/* 551E0 */
+	0x40,  0x26,  0x93,  0x08,  0x20,  0x0E,  0x20,  0x12,  0x20,  0x24,  0x3F,  0x7F,  0x50,  0x29,  0x50,  0x29, 	/* 551F0 */
+	0x90,  0x3F,  0x1E,  0x29,  0x10,  0x29,  0x10,  0x3F,  0x10,  0x05,  0x1E,  0x32,  0x90,  0x2A,  0x10,  0x28, 	/* 55200 */
+	0x10,  0x40,  0x10,  0x96,  0x08,  0x00,  0x0F,  0xFF,  0x12,  0x10,  0x24,  0x10,  0x7F,  0x10,  0x29,  0x20, 	/* 55210 */
+	0x29,  0x20,  0x3F,  0x7E,  0x29,  0x62,  0x29,  0xA2,  0x3F,  0x22,  0x05,  0x22,  0x32,  0xA2,  0x2A,  0x22, 	/* 55220 */
+	0x28,  0x3E,  0x40,  0x00,  0x97,  0x08,  0x20,  0x0E,  0x20,  0x12,  0x3C,  0x24,  0x44,  0x7F,  0x48,  0x29, 	/* 55230 */
+	0xA8,  0x29,  0x10,  0x3F,  0x28,  0x29,  0x44,  0x29,  0xB2,  0x3F,  0x09,  0x05,  0x00,  0x32,  0xA0,  0x2A, 	/* 55240 */
+	0x18,  0x28,  0x04,  0x40,  0x02,  0x9F,  0x08,  0x10,  0x0E,  0x10,  0x12,  0xFE,  0x24,  0x82,  0x7F,  0x92, 	/* 55250 */
+	0x29,  0x10,  0x29,  0xFF,  0x3F,  0x24,  0x29,  0x24,  0x29,  0x24,  0x3F,  0x48,  0x05,  0x78,  0x32,  0x98, 	/* 55260 */
+	0x2A,  0x24,  0x28,  0x42,  0x41,  0x82,  0xA0,  0x08,  0x20,  0x0E,  0x3C,  0x12,  0x44,  0x24,  0x88,  0x7F, 	/* 55270 */
+	0x7F,  0x29,  0x40,  0x29,  0x40,  0x3F,  0x5E,  0x29,  0x52,  0x29,  0x52,  0x3F,  0x52,  0x05,  0x56,  0x32, 	/* 55280 */
+	0xD0,  0x2A,  0x91,  0x28,  0x91,  0x41,  0x0F,  0xA8,  0x08,  0x40,  0x0E,  0x44,  0x12,  0x78,  0x24,  0x40, 	/* 55290 */
+	0x7F,  0x41,  0x29,  0x41,  0x29,  0x3F,  0x3F,  0x00,  0x29,  0x3E,  0x29,  0x22,  0x3F,  0x22,  0x05,  0x3E, 	/* 552A0 */
+	0x32,  0xA2,  0x2A,  0x22,  0x28,  0x3E,  0x40,  0x00,  0xAA,  0x08,  0x10,  0x0E,  0x10,  0x13,  0xFF,  0x24, 	/* 552B0 */
+	0x10,  0x7F,  0x10,  0x29,  0x20,  0x29,  0x3E,  0x3F,  0x62,  0x29,  0xA2,  0x29,  0x3E,  0x3F,  0x22,  0x05, 	/* 552C0 */
+	0x3E,  0x32,  0xA2,  0x2A,  0x22,  0x28,  0x22,  0x40,  0x26,  0xAB,  0x08,  0x10,  0x0E,  0x10,  0x12,  0x10, 	/* 552D0 */
+	0x24,  0xFF,  0x7F,  0x24,  0x29,  0x22,  0x29,  0x46,  0x3F,  0xA5,  0x29,  0x24,  0x29,  0x14,  0x3F,  0x18, 	/* 552E0 */
+	0x05,  0x08,  0x32,  0x94,  0x2A,  0x24,  0x28,  0x42,  0x41,  0x81,  0xAD,  0x08,  0x10,  0x0E,  0x10,  0x12, 	/* 552F0 */
+	0xFE,  0x24,  0x10,  0x7F,  0x10,  0x29,  0x10,  0x29,  0xFF,  0x3F,  0x00,  0x29,  0x10,  0x29,  0x10,  0x3F, 	/* 55300 */
+	0xFE,  0x02,  0x10,  0x35,  0x10,  0x2A,  0x10,  0x2B,  0xFF,  0x40,  0x00,  0xAE,  0x08,  0x44,  0x0E,  0x24, 	/* 55310 */
+	0x12,  0x28,  0x24,  0xFF,  0x7F,  0x10,  0x29,  0x10,  0x29,  0x7E,  0x3F,  0x10,  0x29,  0x10,  0x29,  0x10, 	/* 55320 */
+	0x3F,  0xFF,  0x02,  0x10,  0x15,  0x10,  0x2A,  0x90,  0x2A,  0x10,  0x40,  0x10,  0xB4,  0x08,  0x48,  0x0E, 	/* 55330 */
+	0x48,  0x12,  0x48,  0x24,  0x48,  0x7E,  0x7F,  0x2A,  0x88,  0x2A,  0x88,  0x3F,  0x9C,  0x2A,  0x9C,  0x2A, 	/* 55340 */
+	0xAA,  0x3E,  0xAA,  0x04,  0xC9,  0x32,  0x88,  0x2A,  0x88,  0x28,  0x88,  0x40,  0x88,  0xB9,  0x08,  0x10, 	/* 55350 */
+	0x0E,  0x54,  0x12,  0x52,  0x24,  0x92,  0x7F,  0x91,  0x29,  0x7E,  0x29,  0x42,  0x3F,  0x42,  0x29,  0x7E, 	/* 55360 */
+	0x29,  0x42,  0x3F,  0x42,  0x05,  0x7E,  0x32,  0xC2,  0x2A,  0x42,  0x28,  0x42,  0x40,  0x46,  0x80,  0x08, 	/* 55370 */
+	0x02,  0x0E,  0xFC,  0x12,  0x10,  0x24,  0x14,  0x7F,  0xE4,  0x29,  0x38,  0x29,  0x10,  0x3F,  0x24,  0x29, 	/* 55380 */
+	0xFE,  0x29,  0x11,  0x3F,  0x10,  0x04,  0x54,  0x32,  0x52,  0x2A,  0x92,  0x29,  0x11,  0x40,  0x10,  0x86, 	/* 55390 */
+	0x08,  0x14,  0x0E,  0x12,  0x12,  0xFF,  0x24,  0x10,  0x7F,  0x10,  0x29,  0x7E,  0x29,  0x52,  0x3F,  0x52, 	/* 553A0 */
+	0x29,  0x7E,  0x29,  0x52,  0x3F,  0x52,  0x05,  0x7E,  0x32,  0xD2,  0x2A,  0x52,  0x28,  0x52,  0x40,  0x56, 	/* 553B0 */
+	0x89,  0x08,  0x00,  0x0F,  0x7E,  0x12,  0x52,  0x24,  0x52,  0x7F,  0x7E,  0x29,  0x52,  0x29,  0x52,  0x3F, 	/* 553C0 */
+	0x52,  0x29,  0x7E,  0x29,  0x10,  0x3F,  0x10,  0x05,  0x7E,  0x32,  0x90,  0x2A,  0x10,  0x28,  0xFF,  0x40, 	/* 553D0 */
+	0x00,  0x8A,  0x18,  0x10,  0x04,  0x54,  0x60,  0x92,  0x11,  0x35,  0x04,  0x18,  0x19,  0xE0,  0x61,  0x00, 	/* 553E0 */
+	0x03,  0xE0,  0x0C,  0x40,  0x3F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x12,  0x22, 	/* 553F0 */
+	0x61,  0x11,  0x8F,  0x08,  0x12,  0x0E,  0x62,  0x13,  0xCA,  0x24,  0x4A,  0x7E,  0x4A,  0x2B,  0xFA,  0x2A, 	/* 55400 */
+	0x4A,  0x3E,  0x4A,  0x2A,  0xEA,  0x2A,  0xDA,  0x3F,  0x4A,  0x05,  0x4A,  0x32,  0x42,  0x2A,  0x42,  0x28, 	/* 55410 */
+	0x42,  0x40,  0x46,  0x91,  0x08,  0x08,  0x0E,  0x68,  0x12,  0x18,  0x24,  0x24,  0x7F,  0x50,  0x29,  0xFF, 	/* 55420 */
+	0x29,  0x20,  0x3F,  0x50,  0x29,  0x7E,  0x29,  0xD2,  0x3F,  0x52,  0x05,  0x52,  0x32,  0xD2,  0x2A,  0x5C, 	/* 55430 */
+	0x28,  0x50,  0x40,  0x10,  0x92,  0x08,  0x00,  0x0E,  0x7E,  0x12,  0x04,  0x24,  0x28,  0x7F,  0x10,  0x29, 	/* 55440 */
+	0x7E,  0x29,  0x52,  0x3F,  0x52,  0x29,  0x7E,  0x29,  0x52,  0x3F,  0x52,  0x05,  0x7E,  0x32,  0xD2,  0x2A, 	/* 55450 */
+	0x52,  0x28,  0x52,  0x40,  0x56,  0x94,  0x08,  0x92,  0x0E,  0x92,  0x13,  0x24,  0x25,  0x24,  0x7E,  0x92, 	/* 55460 */
+	0x2A,  0x92,  0x2A,  0x00,  0x3E,  0xFE,  0x2A,  0x92,  0x2A,  0x92,  0x3E,  0xFE,  0x05,  0x92,  0x32,  0x92, 	/* 55470 */
+	0x2A,  0x92,  0x28,  0xFE,  0x40,  0x00,  0x96,  0x08,  0x10,  0x0E,  0x10,  0x12,  0xFE,  0x24,  0x10,  0x7F, 	/* 55480 */
+	0xFE,  0x29,  0x10,  0x29,  0xFF,  0x3F,  0x00,  0x29,  0x7C,  0x29,  0x44,  0x3F,  0x7C,  0x05,  0x44,  0x32, 	/* 55490 */
+	0xFC,  0x2A,  0x44,  0x28,  0x44,  0x40,  0x4C,  0x9B,  0x08,  0x00,  0x0E,  0x7E,  0x12,  0x52,  0x24,  0x52, 	/* 554A0 */
+	0x7F,  0x7E,  0x29,  0x52,  0x29,  0x52,  0x3F,  0x7E,  0x29,  0x42,  0x29,  0x7A,  0x3F,  0x6A,  0x05,  0x6A, 	/* 554B0 */
+	0x32,  0xFA,  0x2A,  0xAA,  0x28,  0x82,  0x41,  0x06,  0xA1,  0x08,  0x24,  0x0E,  0x24,  0x12,  0x24,  0x24, 	/* 554C0 */
+	0xE7,  0x7F,  0x24,  0x29,  0x24,  0x29,  0x24,  0x3F,  0xE7,  0x29,  0x24,  0x29,  0x24,  0x3F,  0x64,  0x05, 	/* 554D0 */
+	0xA7,  0x32,  0x24,  0x2A,  0x44,  0x28,  0x44,  0x40,  0x84,  0xA2,  0x08,  0x10,  0x0E,  0x20,  0x12,  0x4E, 	/* 554E0 */
+	0x24,  0x42,  0x7F,  0x42,  0x29,  0x6E,  0x29,  0x42,  0x3F,  0x42,  0x29,  0x7E,  0x29,  0x28,  0x3F,  0x28, 	/* 554F0 */
+	0x05,  0x28,  0x32,  0xC8,  0x2A,  0x49,  0x28,  0x89,  0x41,  0x07,  0xA3,  0x08,  0x00,  0x0E,  0x7C,  0x12, 	/* 55500 */
+	0x44,  0x24,  0x44,  0x7F,  0x7C,  0x29,  0x44,  0x29,  0x44,  0x3F,  0x7C,  0x29,  0x20,  0x29,  0x7E,  0x3F, 	/* 55510 */
+	0xAA,  0x05,  0x2A,  0x32,  0x52,  0x2A,  0x92,  0x28,  0x22,  0x40,  0x0C,  0xA4,  0x08,  0x00,  0x0E,  0x7E, 	/* 55520 */
+	0x12,  0x42,  0x24,  0x42,  0x7F,  0x7E,  0x29,  0x42,  0x29,  0x42,  0x3F,  0x7E,  0x29,  0x00,  0x29,  0x48, 	/* 55530 */
+	0x3F,  0x4A,  0x05,  0x7C,  0x32,  0xC8,  0x2A,  0x49,  0x28,  0x79,  0x41,  0x87,  0xA8,  0x08,  0x10,  0x0E, 	/* 55540 */
+	0x10,  0x12,  0xFF,  0x24,  0x00,  0x7F,  0x7C,  0x29,  0x44,  0x29,  0x44,  0x3F,  0x44,  0x29,  0x7C,  0x29, 	/* 55550 */
+	0x10,  0x3F,  0x58,  0x02,  0x54,  0x35,  0x52,  0x2A,  0x92,  0x2A,  0x10,  0x40,  0x30,  0xB0,  0x08,  0x10, 	/* 55560 */
+	0x0E,  0x10,  0x12,  0x28,  0x24,  0x44,  0x7F,  0xBA,  0x29,  0x01,  0x29,  0xFC,  0x3F,  0x04,  0x29,  0x08, 	/* 55570 */
+	0x29,  0x10,  0x3F,  0x08,  0x04,  0x2A,  0x32,  0xA1,  0x2A,  0xA5,  0x29,  0x25,  0x40,  0x1C,  0xB1,  0x08, 	/* 55580 */
+	0x10,  0x0E,  0x1E,  0x12,  0x10,  0x24,  0xFF,  0x7E,  0x96,  0x2A,  0x98,  0x2A,  0xF0,  0x3E,  0x91,  0x2A, 	/* 55590 */
+	0x8F,  0x2A,  0x80,  0x3E,  0xA8,  0x05,  0xA8,  0x32,  0xA8,  0x29,  0x49,  0x2A,  0x49,  0x40,  0x87,  0xB2, 	/* 555A0 */
+	0x08,  0x84,  0x0E,  0x84,  0x12,  0x84,  0x25,  0xEA,  0x7E,  0x8A,  0x2A,  0x8A,  0x2A,  0xF1,  0x3E,  0xA8, 	/* 555B0 */
+	0x2A,  0xA4,  0x2A,  0xA4,  0x3E,  0xA0,  0x05,  0x30,  0x33,  0x28,  0x2A,  0x24,  0x28,  0x22,  0x40,  0xC2, 	/* 555C0 */
+	0xB5,  0x08,  0x10,  0x0E,  0x18,  0x12,  0x24,  0x24,  0xFA,  0x7F,  0x10,  0x29,  0xFF,  0x29,  0x28,  0x3F, 	/* 555D0 */
+	0x4C,  0x29,  0x93,  0x29,  0x64,  0x3F,  0x08,  0x05,  0x32,  0x32,  0xC4,  0x2A,  0x08,  0x28,  0x30,  0x40, 	/* 555E0 */
+	0xC0,  0x84,  0x08,  0x08,  0x0E,  0x0A,  0x12,  0x09,  0x24,  0xFF,  0x7E,  0x88,  0x2A,  0xF8,  0x2A,  0xAA, 	/* 555F0 */
+	0x3E,  0xAA,  0x2A,  0xFA,  0x2A,  0xDA,  0x3E,  0xE4,  0x05,  0xB4,  0x32,  0xAD,  0x2B,  0x4B,  0x29,  0x13, 	/* 55600 */
+	0x42,  0x21,  0x86,  0x08,  0x10,  0x0E,  0x10,  0x12,  0xFE,  0x24,  0x10,  0x7F,  0xFE,  0x29,  0x28,  0x29, 	/* 55610 */
+	0xFF,  0x3F,  0x44,  0x29,  0x82,  0x29,  0x7D,  0x3F,  0x44,  0x05,  0x7C,  0x32,  0xC4,  0x2A,  0x44,  0x28, 	/* 55620 */
+	0x7C,  0x40,  0x00,  0x88,  0x08,  0x94,  0x0E,  0x94,  0x13,  0xFF,  0x24,  0x94,  0x7E,  0x9C,  0x2A,  0x80, 	/* 55630 */
+	0x2A,  0xFE,  0x3E,  0x10,  0x2A,  0x10,  0x2B,  0xFF,  0x3E,  0x38,  0x05,  0x38,  0x32,  0x54,  0x2A,  0x92, 	/* 55640 */
+	0x29,  0x11,  0x40,  0x10,  0x89,  0x08,  0x10,  0x0E,  0x20,  0x12,  0x7C,  0x24,  0x44,  0x7F,  0x7C,  0x29, 	/* 55650 */
+	0x44,  0x29,  0x44,  0x3F,  0x7C,  0x29,  0x00,  0x29,  0x7E,  0x3F,  0x10,  0x05,  0x7E,  0x32,  0x90,  0x2A, 	/* 55660 */
+	0x10,  0x28,  0xFF,  0x40,  0x00,  0x8A,  0x08,  0x10,  0x0E,  0x10,  0x13,  0xFF,  0x24,  0x10,  0x7E,  0x10, 	/* 55670 */
+	0x2A,  0xFE,  0x2A,  0x96,  0x3E,  0xDA,  0x2A,  0xB2,  0x2A,  0xFE,  0x3E,  0x38,  0x05,  0x34,  0x32,  0x54, 	/* 55680 */
+	0x2A,  0x92,  0x29,  0x11,  0x40,  0x10,  0x8C,  0x08,  0x2C,  0x0E,  0x24,  0x12,  0x24,  0x25,  0x7E,  0x7F, 	/* 55690 */
+	0x5A,  0x29,  0x99,  0x29,  0x7E,  0x3F,  0x5A,  0x29,  0x6A,  0x29,  0x6E,  0x3F,  0x42,  0x05,  0x7E,  0x32, 	/* 556A0 */
+	0xC2,  0x2A,  0x42,  0x28,  0x7E,  0x40,  0x00,  0x8D,  0x08,  0x28,  0x0E,  0x48,  0x13,  0x88,  0x24,  0x8A, 	/* 556B0 */
+	0x7E,  0x9A,  0x2B,  0xFA,  0x2A,  0x9C,  0x3E,  0xA8,  0x2A,  0xC8,  0x2B,  0xC8,  0x3E,  0xAC,  0x02,  0x94, 	/* 556C0 */
+	0x34,  0x94,  0x2A,  0xA2,  0x2A,  0xC2,  0x40,  0x81,  0x90,  0x08,  0x00,  0x0E,  0xEE,  0x12,  0xAA,  0x24, 	/* 556D0 */
+	0xAA,  0x7F,  0xEE,  0x29,  0x00,  0x29,  0x7E,  0x3F,  0x00,  0x29,  0xFF,  0x29,  0x10,  0x3F,  0x10,  0x05, 	/* 556E0 */
+	0x3E,  0x32,  0xA2,  0x2A,  0x02,  0x28,  0x02,  0x40,  0x0C,  0x92,  0x08,  0x20,  0x0E,  0x20,  0x12,  0x7F, 	/* 556F0 */
+	0x24,  0x40,  0x7F,  0xFC,  0x29,  0x44,  0x29,  0x7C,  0x3F,  0x44,  0x29,  0x7C,  0x29,  0x20,  0x3F,  0x3C, 	/* 55700 */
+	0x05,  0x44,  0x32,  0xA8,  0x2A,  0x10,  0x28,  0x6C,  0x41,  0x83,  0x93,  0x08,  0x00,  0x0E,  0x7E,  0x12, 	/* 55710 */
+	0x52,  0x24,  0x52,  0x7F,  0x7E,  0x29,  0x52,  0x29,  0x52,  0x3F,  0x52,  0x29,  0x7E,  0x29,  0x10,  0x3F, 	/* 55720 */
+	0x08,  0x04,  0xA8,  0x32,  0xA2,  0x2A,  0xA1,  0x29,  0x25,  0x40,  0x1C,  0x94,  0x08,  0x08,  0x0E,  0x0A, 	/* 55730 */
+	0x12,  0x09,  0x24,  0xFF,  0x7E,  0x88,  0x2A,  0x88,  0x2A,  0xFA,  0x3E,  0x8A,  0x2A,  0xFA,  0x2A,  0xDA, 	/* 55740 */
+	0x3E,  0xD4,  0x05,  0xF4,  0x32,  0x8D,  0x2B,  0x0B,  0x29,  0x13,  0x42,  0x21,  0x95,  0x08,  0x00,  0x0E, 	/* 55750 */
+	0xEE,  0x12,  0xA2,  0x24,  0xA2,  0x7E,  0xA2,  0x2A,  0xEE,  0x2A,  0x80,  0x3E,  0x9E,  0x2A,  0xEA,  0x2A, 	/* 55760 */
+	0x8A,  0x3E,  0x8A,  0x04,  0xE4,  0x32,  0x84,  0x2A,  0x8A,  0x28,  0x92,  0x40,  0xA1,  0x9B,  0x08,  0x00, 	/* 55770 */
+	0x0E,  0x7C,  0x12,  0x44,  0x24,  0x44,  0x7F,  0x7C,  0x29,  0x44,  0x29,  0x44,  0x3F,  0x7C,  0x29,  0x00, 	/* 55780 */
+	0x29,  0xFE,  0x3F,  0xAA,  0x05,  0xAA,  0x32,  0xAA,  0x2A,  0xAA,  0x29,  0xFF,  0x40,  0x00,  0xA1,  0x08, 	/* 55790 */
+	0x20,  0x0E,  0xCF,  0x12,  0x85,  0x24,  0x85,  0x7E,  0xA5,  0x2A,  0x95,  0x2A,  0xF9,  0x3F,  0x96,  0x2A, 	/* 557A0 */
+	0x00,  0x2A,  0x7E,  0x3E,  0x52,  0x05,  0x7E,  0x32,  0x52,  0x2A,  0x52,  0x28,  0x7E,  0x40,  0x00,  0xA4, 	/* 557B0 */
+	0x08,  0x20,  0x0E,  0x5F,  0x12,  0xE4,  0x24,  0xA4,  0x7E,  0xBF,  0x2A,  0xB5,  0x2A,  0xF5,  0x3E,  0x95, 	/* 557C0 */
+	0x2A,  0x95,  0x2A,  0xF5,  0x3E,  0xB5,  0x05,  0xB5,  0x32,  0xB7,  0x2A,  0xF4,  0x28,  0x94,  0x40,  0x84, 	/* 557D0 */
+	0xA5,  0x08,  0x00,  0x0E,  0xFE,  0x12,  0xAA,  0x24,  0xAA,  0x7F,  0xAA,  0x29,  0xFE,  0x29,  0x00,  0x3F, 	/* 557E0 */
+	0x54,  0x29,  0x54,  0x29,  0x52,  0x3F,  0x91,  0x05,  0x54,  0x32,  0x54,  0x2A,  0x92,  0x29,  0x11,  0x40, 	/* 557F0 */
+	0x10,  0xAD,  0x08,  0x20,  0x0E,  0x22,  0x12,  0xFC,  0x24,  0x28,  0x7F,  0xFF,  0x29,  0x20,  0x29,  0xCC, 	/* 55800 */
+	0x3F,  0x70,  0x29,  0x42,  0x29,  0x3E,  0x3F,  0x00,  0x05,  0x7C,  0x32,  0xC4,  0x2A,  0x7C,  0x28,  0x44, 	/* 55810 */
+	0x40,  0x7C,  0xAE,  0x08,  0x00,  0x0E,  0xFC,  0x12,  0xA4,  0x24,  0xA4,  0x7E,  0xB4,  0x2A,  0xAC,  0x2A, 	/* 55820 */
+	0xC4,  0x3E,  0xFC,  0x2A,  0x00,  0x2A,  0xFE,  0x3E,  0xAA,  0x05,  0xAA,  0x32,  0xAA,  0x2A,  0xAA,  0x29, 	/* 55830 */
+	0xFF,  0x40,  0x00,  0xAF,  0x08,  0x00,  0x0F,  0xFE,  0x12,  0x22,  0x24,  0x22,  0x7E,  0xEE,  0x2A,  0x88, 	/* 55840 */
+	0x2A,  0x88,  0x3E,  0xEE,  0x2A,  0x32,  0x2A,  0xAA,  0x3E,  0xAA,  0x02,  0x66,  0x35,  0xAA,  0x2B,  0x32, 	/* 55850 */
+	0x2A,  0x22,  0x40,  0xCC,  0xB0,  0x08,  0x04,  0x0E,  0xE4,  0x12,  0x04,  0x24,  0x1F,  0x7E,  0x15,  0x2B, 	/* 55860 */
+	0xF5,  0x2A,  0x5F,  0x3E,  0x55,  0x2B,  0x55,  0x2B,  0x55,  0x3F,  0x5F,  0x05,  0x54,  0x32,  0x54,  0x2A, 	/* 55870 */
+	0x44,  0x28,  0x44,  0x40,  0x44,  0xB2,  0x04,  0x10,  0x3F,  0x9F,  0x04,  0x24,  0x7F,  0xD4,  0x08,  0x14, 	/* 55880 */
+	0x0F,  0x08,  0x09,  0x14,  0x13,  0xE2,  0x24,  0x81,  0x1F,  0xF8,  0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88, 	/* 55890 */
+	0x1F,  0xF8,  0x22,  0x22,  0x41,  0x11,  0xB9,  0x08,  0x00,  0x0E,  0xF0,  0x12,  0xBE,  0x24,  0xAA,  0x7E, 	/* 558A0 */
+	0xFA,  0x2A,  0x9A,  0x2A,  0xF4,  0x3E,  0xA6,  0x2A,  0xAA,  0x2A,  0xF1,  0x3E,  0x10,  0x05,  0x7C,  0x32, 	/* 558B0 */
+	0x90,  0x2A,  0x10,  0x29,  0xFF,  0x40,  0x00,  0xBA,  0x08,  0x10,  0x0E,  0x28,  0x12,  0xFC,  0x24,  0x42, 	/* 558C0 */
+	0x7E,  0xA5,  0x2B,  0xEF,  0x2A,  0x10,  0x3E,  0x28,  0x2A,  0x44,  0x2B,  0x93,  0x3E,  0x20,  0x05,  0xC8, 	/* 558D0 */
+	0x32,  0x32,  0x2A,  0xC4,  0x28,  0x18,  0x40,  0xE0,  0xBB,  0x08,  0x00,  0x0E,  0x7C,  0x12,  0x44,  0x24, 	/* 558E0 */
+	0x7C,  0x7F,  0x44,  0x29,  0x7C,  0x29,  0x00,  0x3F,  0xFE,  0x29,  0xAA,  0x29,  0xFE,  0x3F,  0x00,  0x05, 	/* 558F0 */
+	0xFC,  0x32,  0x48,  0x2A,  0x30,  0x28,  0x6C,  0x41,  0x83,  0xBE,  0x08,  0x00,  0x0F,  0xFF,  0x12,  0x28, 	/* 55900 */
+	0x24,  0xFE,  0x7E,  0xAA,  0x2A,  0xAA,  0x2A,  0xFE,  0x3E,  0x00,  0x2A,  0x7C,  0x2A,  0x00,  0x3F,  0xFF, 	/* 55910 */
+	0x05,  0x50,  0x32,  0x54,  0x2A,  0x92,  0x29,  0x11,  0x40,  0x30,  0x86,  0x08,  0x10,  0x0E,  0x10,  0x12, 	/* 55920 */
+	0xFE,  0x24,  0x44,  0x7F,  0x28,  0x29,  0xFF,  0x29,  0x00,  0x3F,  0x7C,  0x29,  0x44,  0x29,  0x7C,  0x3F, 	/* 55930 */
+	0x44,  0x05,  0x7C,  0x32,  0x90,  0x2A,  0xFF,  0x28,  0x10,  0x40,  0x10,  0x87,  0x08,  0x08,  0x0E,  0x08, 	/* 55940 */
+	0x12,  0xFF,  0x24,  0x88,  0x7E,  0xBE,  0x2A,  0x8A,  0x2A,  0xFF,  0x3E,  0x8A,  0x2A,  0xBE,  0x2A,  0xC8, 	/* 55950 */
+	0x3E,  0xAA,  0x04,  0xAA,  0x33,  0x1C,  0x29,  0x2A,  0x2A,  0xC9,  0x40,  0x18,  0x88,  0x10,  0x00,  0x1E, 	/* 55960 */
+	0xFE,  0x12,  0x10,  0x25,  0xFF,  0x7F,  0x11,  0x29,  0xDD,  0x29,  0x11,  0x3F,  0xDC,  0x29,  0x00,  0x29, 	/* 55970 */
+	0xFC,  0x3F,  0x04,  0x05,  0x04,  0x32,  0xFC,  0x2A,  0x04,  0x28,  0xFC,  0x40,  0x00,  0x92,  0x08,  0x42, 	/* 55980 */
+	0x0E,  0x24,  0x12,  0xFF,  0x24,  0x18,  0x7F,  0x7E,  0x29,  0x5A,  0x29,  0x6A,  0x3F,  0x7E,  0x29,  0x42, 	/* 55990 */
+	0x29,  0x7E,  0x3F,  0x04,  0x05,  0xFF,  0x32,  0x44,  0x2A,  0x24,  0x28,  0x04,  0x40,  0x0C,  0x97,  0x08, 	/* 559A0 */
+	0x10,  0x0E,  0x92,  0x12,  0x54,  0x24,  0xFF,  0x7E,  0x38,  0x2A,  0x54,  0x2A,  0x92,  0x3F,  0x51,  0x2A, 	/* 559B0 */
+	0x52,  0x2A,  0x6F,  0x3E,  0xAA,  0x05,  0xAA,  0x32,  0x7F,  0x2A,  0x42,  0x28,  0x82,  0x41,  0x02,  0x9A, 	/* 559C0 */
+	0x08,  0x10,  0x0E,  0xFF,  0x12,  0x10,  0x24,  0x7E,  0x7F,  0x00,  0x29,  0x7E,  0x29,  0x42,  0x3F,  0x7E, 	/* 559D0 */
+	0x29,  0x44,  0x29,  0x28,  0x3F,  0xFF,  0x05,  0x00,  0x32,  0xFE,  0x2A,  0x42,  0x28,  0x7E,  0x40,  0x00, 	/* 559E0 */
+	0xA0,  0x08,  0x10,  0x0E,  0x10,  0x12,  0x28,  0x24,  0x7C,  0x7E,  0x82,  0x2B,  0xFF,  0x2A,  0x92,  0x3E, 	/* 559F0 */
+	0xD6,  0x2A,  0xFE,  0x2A,  0x00,  0x3E,  0x7C,  0x05,  0x44,  0x32,  0x7C,  0x2A,  0x44,  0x28,  0x7C,  0x40, 	/* 55A00 */
+	0x00,  0xA7,  0x08,  0x28,  0x0E,  0x28,  0x12,  0xFE,  0x24,  0xAA,  0x7E,  0xFE,  0x2A,  0xAA,  0x2A,  0xFE, 	/* 55A10 */
+	0x3E,  0x00,  0x2B,  0xFF,  0x2A,  0x00,  0x3E,  0xFE,  0x04,  0x82,  0x32,  0xFE,  0x2A,  0x24,  0x29,  0xFF, 	/* 55A20 */
+	0x40,  0x00,  0xB6,  0x08,  0x44,  0x0E,  0x28,  0x12,  0xFE,  0x24,  0x10,  0x7E,  0xFE,  0x2A,  0x10,  0x2B, 	/* 55A30 */
+	0xFF,  0x3E,  0x54,  0x2A,  0xFE,  0x2B,  0x45,  0x3E,  0x7C,  0x05,  0x44,  0x32,  0x7D,  0x2A,  0x52,  0x28, 	/* 55A40 */
+	0x6C,  0x41,  0x83,  0xB8,  0x08,  0x10,  0x0E,  0x1E,  0x12,  0x10,  0x24,  0xFF,  0x7E,  0x9A,  0x2A,  0xF1, 	/* 55A50 */
+	0x2A,  0xBF,  0x3E,  0xAA,  0x2A,  0xBE,  0x2A,  0xAA,  0x3F,  0x3E,  0x05,  0x00,  0x32,  0xFE,  0x28,  0xAA, 	/* 55A60 */
+	0x29,  0xFF,  0x40,  0x00,  0xA5,  0x00,  0x80,  0x01,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08, 	/* 55A70 */
+	0x10,  0x0F,  0xF0,  0x08,  0x00,  0x0F,  0xFF,  0x08,  0x00,  0x0F,  0xFE,  0x10,  0x22,  0x14,  0x92,  0x12, 	/* 55A80 */
+	0x52,  0x22,  0x42,  0x40,  0x0C,  0xA7,  0x01,  0x00,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10, 	/* 55A90 */
+	0x08,  0x10,  0x0F,  0xFF,  0x08,  0x00,  0x0F,  0xFE,  0x29,  0x22,  0x24,  0x92,  0x40,  0x0C,  0x03,  0xF0, 	/* 55AA0 */
+	0x02,  0x11,  0x0C,  0x11,  0x70,  0x0F,  0xA9,  0x10,  0x20,  0x10,  0x40,  0x10,  0xFC,  0x7C,  0x84,  0x14, 	/* 55AB0 */
+	0xFC,  0x14,  0x84,  0x14,  0xFC,  0x14,  0x80,  0x14,  0xFF,  0x15,  0x80,  0x15,  0xFE,  0x23,  0x0A,  0x20, 	/* 55AC0 */
+	0xA6,  0x41,  0x52,  0x01,  0x52,  0x02,  0x0C,  0xAB,  0x00,  0x00,  0x1F,  0xFF,  0x10,  0x80,  0x13,  0xF8, 	/* 55AD0 */
+	0x12,  0x08,  0x13,  0xF8,  0x12,  0x08,  0x13,  0xF8,  0x12,  0x00,  0x13,  0xFF,  0x12,  0x00,  0x13,  0xFE, 	/* 55AE0 */
+	0x20,  0x0A,  0x25,  0x26,  0x44,  0x92,  0x08,  0x0C,  0xAC,  0x01,  0x00,  0x1F,  0xF0,  0x10,  0x10,  0x1F, 	/* 55AF0 */
+	0xF0,  0x10,  0x10,  0x1F,  0xF0,  0x10,  0x00,  0x1F,  0xFF,  0x10,  0x00,  0x1F,  0xFE,  0x00,  0x02,  0x07, 	/* 55B00 */
+	0xE2,  0x04,  0x2C,  0x04,  0x21,  0x18,  0x21,  0x60,  0x1F,  0xB0,  0x00,  0x20,  0x00,  0x40,  0x38,  0xFC, 	/* 55B10 */
+	0x08,  0x84,  0x08,  0xFC,  0x08,  0x84,  0x08,  0xFC,  0x0C,  0x80,  0x14,  0xFF,  0x14,  0x80,  0x12,  0xFE, 	/* 55B20 */
+	0x22,  0x2A,  0x21,  0x96,  0x41,  0x52,  0x02,  0x42,  0x00,  0x0C,  0xB3,  0x00,  0x00,  0x1F,  0xFC,  0x10, 	/* 55B30 */
+	0x04,  0x1F,  0xFC,  0x11,  0x04,  0x17,  0xE4,  0x14,  0x24,  0x17,  0xE4,  0x14,  0x24,  0x17,  0xFC,  0x14, 	/* 55B40 */
+	0x04,  0x17,  0xF4,  0x11,  0x54,  0x2C,  0xB5,  0x2A,  0x13,  0x50,  0x61,  0xB4,  0x00,  0x20,  0x00,  0x40, 	/* 55B50 */
+	0x79,  0xF8,  0x49,  0x08,  0x49,  0xF8,  0x49,  0x08,  0x49,  0xF8,  0x49,  0x00,  0x49,  0xFF,  0x49,  0x00, 	/* 55B60 */
+	0x79,  0xFE,  0x49,  0x52,  0x02,  0xAA,  0x02,  0xAA,  0x04,  0x84,  0x08,  0x18,  0xB6,  0x01,  0x10,  0x01, 	/* 55B70 */
+	0x08,  0x7F,  0xFF,  0x00,  0x80,  0x02,  0x61,  0x04,  0x19,  0x0F,  0xF7,  0x08,  0x10,  0x0F,  0xF0,  0x08, 	/* 55B80 */
+	0x10,  0x0F,  0xFF,  0x08,  0x00,  0x0F,  0xFE,  0x29,  0x22,  0x24,  0x92,  0x44,  0x0C,  0x83,  0x04,  0x10, 	/* 55B90 */
+	0x08,  0x10,  0x3E,  0x10,  0x22,  0x7E,  0x3E,  0x12,  0x22,  0x12,  0x3E,  0x12,  0x20,  0x12,  0x3F,  0xFF, 	/* 55BA0 */
+	0x20,  0x10,  0x3F,  0x98,  0x04,  0xA8,  0x32,  0xA8,  0x2A,  0xC4,  0x28,  0x82,  0x43,  0x01,  0x86,  0x08, 	/* 55BB0 */
+	0x10,  0x08,  0x20,  0x08,  0xFC,  0x7E,  0x84,  0x4A,  0xFC,  0x4A,  0x84,  0x08,  0xFC,  0x08,  0x80,  0x0C, 	/* 55BC0 */
+	0xFF,  0x14,  0x80,  0x14,  0xFE,  0x15,  0x12,  0x16,  0xCA,  0x24,  0xAA,  0x41,  0x22,  0x00,  0x0C,  0x87, 	/* 55BD0 */
+	0x20,  0x10,  0x24,  0x20,  0x38,  0xFC,  0x20,  0x84,  0x20,  0xFC,  0x22,  0x84,  0x1E,  0xFC,  0x08,  0x80, 	/* 55BE0 */
+	0x08,  0xFF,  0x08,  0x80,  0x7F,  0xFE,  0x08,  0x2A,  0x09,  0x96,  0x09,  0x52,  0x09,  0x42,  0x0A,  0x0C, 	/* 55BF0 */
+	0x88,  0x00,  0x00,  0x1F,  0xFF,  0x12,  0x20,  0x12,  0xFC,  0x12,  0x84,  0x14,  0xFC,  0x14,  0x84,  0x1C, 	/* 55C00 */
+	0xFC,  0x14,  0x80,  0x14,  0xFF,  0x14,  0x80,  0x14,  0xFE,  0x24,  0x2A,  0x25,  0x96,  0x45,  0x52,  0x06, 	/* 55C10 */
+	0x44,  0x89,  0x00,  0x10,  0x3E,  0x20,  0x24,  0xFC,  0x24,  0x84,  0x24,  0xFC,  0x24,  0x84,  0x24,  0xFC, 	/* 55C20 */
+	0x7F,  0x80,  0x0C,  0xFF,  0x0C,  0x80,  0x14,  0xFE,  0x14,  0x2A,  0x25,  0x96,  0x45,  0x52,  0x06,  0x42, 	/* 55C30 */
+	0x0C,  0x0C,  0x8E,  0x00,  0x20,  0x7F,  0x40,  0x42,  0xFC,  0x42,  0x84,  0x62,  0xFC,  0x54,  0x84,  0x4C, 	/* 55C40 */
+	0xFC,  0x44,  0x80,  0x4C,  0xFF,  0x4A,  0x80,  0x52,  0xFE,  0x52,  0x2A,  0x61,  0x96,  0x7F,  0x52,  0x01, 	/* 55C50 */
+	0x42,  0x02,  0x0C,  0x92,  0x08,  0x10,  0x08,  0x20,  0x14,  0xFC,  0x12,  0x84,  0x21,  0xFC,  0x7E,  0x84, 	/* 55C60 */
+	0x00,  0xFC,  0x00,  0x80,  0x7E,  0xFF,  0x12,  0x80,  0x12,  0xFE,  0x12,  0x2A,  0x1D,  0x96,  0x11,  0x52, 	/* 55C70 */
+	0x12,  0x42,  0x10,  0x0C,  0x95,  0x04,  0x08,  0x08,  0x08,  0x3E,  0xFE,  0x22,  0x82,  0x3E,  0xA2,  0x22, 	/* 55C80 */
+	0x20,  0x3E,  0x20,  0x20,  0x24,  0x3F,  0xA4,  0x20,  0x28,  0x3F,  0xB0,  0x04,  0xA0,  0x32,  0xA1,  0x2A, 	/* 55C90 */
+	0xA1,  0x28,  0xA1,  0x43,  0x1F,  0x9B,  0x08,  0x00,  0x0F,  0xFC,  0x31,  0x44,  0x0A,  0x58,  0x0D,  0x42, 	/* 55CA0 */
+	0x72,  0x3E,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xFF,  0x08,  0x00,  0x0F,  0xFE, 	/* 55CB0 */
+	0x29,  0x22,  0x24,  0x92,  0x40,  0x0C,  0x9F,  0x01,  0x10,  0x02,  0x20,  0x3C,  0x7C,  0x24,  0x44,  0x24, 	/* 55CC0 */
+	0x7C,  0x24,  0x44,  0x3F,  0x7C,  0x24,  0x40,  0x24,  0x7F,  0x24,  0x40,  0x22,  0xFE,  0x3A,  0x92,  0x61, 	/* 55CD0 */
+	0xAA,  0x00,  0xAA,  0x7D,  0x02,  0x00,  0x0C,  0xA3,  0x08,  0x10,  0x08,  0x20,  0x08,  0xFC,  0x7F,  0x84, 	/* 55CE0 */
+	0x08,  0xFC,  0x08,  0x84,  0x08,  0xFC,  0x3E,  0x80,  0x22,  0xFF,  0x22,  0x80,  0x22,  0xFE,  0x22,  0x0A, 	/* 55CF0 */
+	0x3F,  0x56,  0x01,  0x52,  0x02,  0x02,  0x00,  0x0C,  0xA6,  0x00,  0x80,  0x1F,  0xFE,  0x10,  0x82,  0x7F, 	/* 55D00 */
+	0xFF,  0x02,  0x90,  0x0C,  0x8C,  0x77,  0xFB,  0x04,  0x08,  0x07,  0xF8,  0x04,  0x08,  0x07,  0xFF,  0x04, 	/* 55D10 */
+	0x00,  0x07,  0xFE,  0x14,  0x92,  0x12,  0x4A,  0x20,  0x0C,  0xA8,  0x00,  0x20,  0x7E,  0x40,  0x4A,  0xFC, 	/* 55D20 */
+	0x4A,  0x84,  0x4A,  0xFC,  0x7E,  0x84,  0x4A,  0xFC,  0x4A,  0x80,  0x4A,  0xFF,  0x7E,  0x80,  0x08,  0xFE, 	/* 55D30 */
+	0x08,  0x2A,  0x09,  0x96,  0x09,  0x52,  0x0A,  0x42,  0x0C,  0x0C,  0xAA,  0x08,  0x10,  0x08,  0x20,  0x08, 	/* 55D40 */
+	0xFC,  0x7E,  0x84,  0x42,  0xFC,  0x42,  0x84,  0x1C,  0xFC,  0x04,  0x80,  0x14,  0xFF,  0x12,  0x80,  0x12, 	/* 55D50 */
+	0xFE,  0x21,  0x2A,  0x21,  0x96,  0x41,  0x52,  0x02,  0x42,  0x00,  0x0C,  0xAB,  0x00,  0x20,  0x00,  0x40, 	/* 55D60 */
+	0x7D,  0xF8,  0x55,  0x08,  0x55,  0xF8,  0x55,  0x08,  0x7D,  0xF8,  0x55,  0x00,  0x55,  0xFF,  0x55,  0x00, 	/* 55D70 */
+	0x55,  0xFE,  0x7C,  0x52,  0x02,  0xAA,  0x02,  0xA2,  0x04,  0x02,  0x00,  0x0C,  0xAC,  0x11,  0x08,  0x08, 	/* 55D80 */
+	0x90,  0x7F,  0xFE,  0x42,  0x02,  0x4F,  0xF2,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xF0,  0x08, 	/* 55D90 */
+	0x00,  0x0F,  0xFE,  0x08,  0x00,  0x0F,  0xFC,  0x29,  0x24,  0x24,  0x94,  0x40,  0x18,  0xBB,  0x20,  0x08, 	/* 55DA0 */
+	0x10,  0x10,  0x10,  0x7C,  0x0F,  0xC4,  0x42,  0x7C,  0x22,  0x44,  0x22,  0x7C,  0x02,  0x40,  0x0A,  0x7F, 	/* 55DB0 */
+	0x0A,  0x40,  0x13,  0x7E,  0x1C,  0x0A,  0x21,  0x56,  0x21,  0x2A,  0x42,  0x22,  0x40,  0x0C,  0xBE,  0x08, 	/* 55DC0 */
+	0x10,  0x08,  0x20,  0x14,  0xFC,  0x22,  0x84,  0x7D,  0xFC,  0x09,  0x84,  0x28,  0xFC,  0x3E,  0x80,  0x48, 	/* 55DD0 */
+	0xFF,  0x08,  0x80,  0x7F,  0xFE,  0x08,  0x2A,  0x09,  0x56,  0x09,  0x52,  0x0A,  0x02,  0x08,  0x0C,  0xBF, 	/* 55DE0 */
+	0x08,  0x10,  0x08,  0x20,  0x14,  0xFC,  0x14,  0x84,  0x22,  0xFC,  0x7D,  0x84,  0x00,  0xFC,  0x00,  0x80, 	/* 55DF0 */
+	0x3E,  0xFF,  0x22,  0x80,  0x22,  0xFE,  0x22,  0x2A,  0x3F,  0x96,  0x01,  0x52,  0x02,  0x42,  0x00,  0x0C, 	/* 55E00 */
+	0x81,  0x08,  0x10,  0x08,  0x20,  0x7F,  0xFC,  0x14,  0x84,  0x12,  0xFC,  0x22,  0x84,  0x45,  0xFC,  0x14, 	/* 55E10 */
+	0x80,  0x14,  0xFF,  0x08,  0x80,  0x0C,  0xFE,  0x12,  0x2A,  0x11,  0x96,  0x21,  0x52,  0x42,  0x42,  0x00, 	/* 55E20 */
+	0x0C,  0x84,  0x00,  0x10,  0x7F,  0x20,  0x08,  0xFC,  0x08,  0x84,  0x14,  0xFC,  0x22,  0x84,  0x7D,  0xFC, 	/* 55E30 */
+	0x09,  0x80,  0x08,  0xFF,  0x3E,  0x80,  0x08,  0xFE,  0x08,  0x2A,  0x0F,  0x96,  0x19,  0x52,  0x62,  0x42, 	/* 55E40 */
+	0x00,  0x0C,  0x86,  0x08,  0x80,  0x09,  0x0F,  0x13,  0xE0,  0x12,  0x20,  0x27,  0xE0,  0x46,  0x3F,  0x0B, 	/* 55E50 */
+	0xE4,  0x0A,  0x04,  0x13,  0xFC,  0x32,  0x04,  0x53,  0xF4,  0x10,  0x94,  0x16,  0x54,  0x15,  0x54,  0x19, 	/* 55E60 */
+	0x14,  0x10,  0x64,  0x88,  0x00,  0x10,  0x7F,  0x20,  0x12,  0xFC,  0x12,  0x84,  0x1E,  0xFC,  0x12,  0x84, 	/* 55E70 */
+	0x12,  0xFC,  0x12,  0x80,  0x1E,  0xFF,  0x12,  0x80,  0x12,  0xFE,  0x12,  0x12,  0x1E,  0xCA,  0x72,  0xAA, 	/* 55E80 */
+	0x03,  0x22,  0x02,  0x0C,  0x90,  0x00,  0x10,  0x7F,  0x20,  0x08,  0xFC,  0x08,  0x84,  0x2A,  0xFC,  0x2A, 	/* 55E90 */
+	0x84,  0x2A,  0xFC,  0x2D,  0x80,  0x5C,  0xFF,  0x48,  0x80,  0x08,  0xFE,  0x08,  0x2A,  0x0F,  0x96,  0x19, 	/* 55EA0 */
+	0x52,  0x62,  0x42,  0x00,  0x0C,  0x91,  0x00,  0x10,  0x3E,  0x20,  0x22,  0xFC,  0x22,  0x84,  0x3E,  0xFC, 	/* 55EB0 */
+	0x00,  0x84,  0x3E,  0xFC,  0x22,  0x80,  0x22,  0xFF,  0x3E,  0x80,  0x22,  0xFE,  0x22,  0x12,  0x3E,  0xCA, 	/* 55EC0 */
+	0x22,  0xAA,  0x23,  0x22,  0x26,  0x0C,  0x99,  0x00,  0x10,  0x3E,  0x20,  0x22,  0xFC,  0x22,  0x84,  0x3E, 	/* 55ED0 */
+	0xFC,  0x22,  0x84,  0x22,  0xFC,  0x22,  0x80,  0x3E,  0xFF,  0x22,  0x80,  0x22,  0xFE,  0x3E,  0x12,  0x14, 	/* 55EE0 */
+	0xCA,  0x12,  0xAA,  0x21,  0x22,  0x40,  0x0C,  0x9C,  0x22,  0x10,  0x12,  0x20,  0x14,  0x7C,  0x7F,  0x44, 	/* 55EF0 */
+	0x09,  0x7C,  0x3F,  0x44,  0x28,  0x7C,  0x28,  0x40,  0x3F,  0x7F,  0x09,  0x40,  0x19,  0x7E,  0x19,  0x52, 	/* 55F00 */
+	0x2E,  0xAA,  0x48,  0xAA,  0x09,  0x02,  0x08,  0x0C,  0x9D,  0x08,  0x10,  0x14,  0x20,  0x36,  0x7C,  0x55, 	/* 55F10 */
+	0x44,  0x14,  0x7C,  0x7F,  0xC4,  0x14,  0x7C,  0x15,  0x40,  0x1D,  0x7F,  0x16,  0x40,  0x36,  0x7E,  0x55, 	/* 55F20 */
+	0x2A,  0x17,  0x56,  0x1B,  0x56,  0x11,  0x82,  0x31,  0x1C,  0x9E,  0x03,  0x24,  0x3C,  0x22,  0x04,  0x10, 	/* 55F30 */
+	0x7F,  0xFF,  0x07,  0x14,  0x3C,  0x1A,  0x04,  0xE6,  0x05,  0x02,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xFF, 	/* 55F40 */
+	0x08,  0x00,  0x0F,  0xFE,  0x24,  0x92,  0x22,  0x4A,  0x42,  0x0C,  0xA0,  0x08,  0x10,  0x28,  0x20,  0x28, 	/* 55F50 */
+	0xFC,  0x3E,  0x84,  0x28,  0xFC,  0x48,  0x84,  0x08,  0xFC,  0x7F,  0x80,  0x00,  0xFF,  0x3E,  0x80,  0x22, 	/* 55F60 */
+	0xFE,  0x22,  0x52,  0x22,  0xAA,  0x22,  0xAA,  0x3F,  0x02,  0x02,  0x0C,  0xA1,  0x02,  0x10,  0x3B,  0x20, 	/* 55F70 */
+	0x02,  0xFC,  0x02,  0x44,  0x7F,  0xFC,  0x02,  0x44,  0x0A,  0x7C,  0x2A,  0x40,  0x2E,  0x7F,  0x2A,  0x40, 	/* 55F80 */
+	0x2A,  0x7E,  0x29,  0x0A,  0x2F,  0x56,  0x39,  0x56,  0x61,  0x82,  0x00,  0x8C,  0xA4,  0x08,  0x10,  0x0E, 	/* 55F90 */
+	0x20,  0x12,  0xFC,  0x24,  0x84,  0x7E,  0xFC,  0x2A,  0x84,  0x2A,  0xFC,  0x3E,  0x80,  0x2A,  0xFF,  0x2A, 	/* 55FA0 */
+	0x80,  0x3E,  0xFE,  0x22,  0x12,  0x22,  0xCA,  0x22,  0xAA,  0x23,  0x22,  0x46,  0x0C,  0xAC,  0x00,  0x08, 	/* 55FB0 */
+	0x3B,  0x90,  0x2A,  0xBC,  0x2A,  0xA4,  0x2A,  0xBC,  0x3B,  0xA4,  0x2A,  0xBC,  0x2A,  0xA0,  0x2A,  0xBF, 	/* 55FC0 */
+	0x3B,  0xA0,  0x2A,  0xBE,  0x2A,  0x92,  0x2A,  0xAA,  0x2A,  0xAA,  0x2C,  0xC2,  0x59,  0x8C,  0xAF,  0x08, 	/* 55FD0 */
+	0x10,  0x10,  0x20,  0x3E,  0xFC,  0x2A,  0x84,  0x2A,  0xFC,  0x3E,  0x84,  0x2A,  0xFC,  0x2A,  0x80,  0x3E, 	/* 55FE0 */
+	0xFF,  0x14,  0x80,  0x24,  0xFE,  0x7F,  0x12,  0x04,  0xCA,  0x04,  0xAA,  0x05,  0x22,  0x04,  0x0C,  0xB2, 	/* 55FF0 */
+	0x14,  0x10,  0x14,  0x20,  0x7E,  0xFC,  0x14,  0x84,  0x14,  0xFC,  0x14,  0x84,  0x7F,  0xFC,  0x00,  0x80, 	/* 56000 */
+	0x3E,  0xFF,  0x22,  0x80,  0x22,  0xFE,  0x3E,  0x12,  0x22,  0xCA,  0x22,  0xAA,  0x3F,  0x22,  0x00,  0x0C, 	/* 56010 */
+	0xBA,  0x04,  0x08,  0x04,  0x10,  0x7F,  0xFC,  0x0A,  0x44,  0x0A,  0x7C,  0x13,  0xC4,  0x32,  0xFC,  0x36, 	/* 56020 */
+	0xC0,  0x55,  0x7F,  0x1B,  0x40,  0x11,  0x7E,  0x12,  0x92,  0x14,  0x4A,  0x18,  0xAA,  0x11,  0x22,  0x10, 	/* 56030 */
+	0x0C,  0x87,  0x08,  0x10,  0x08,  0x20,  0x7F,  0xFC,  0x08,  0x44,  0x3F,  0x7C,  0x29,  0x44,  0x3F,  0x7C, 	/* 56040 */
+	0x29,  0x40,  0x3F,  0x7F,  0x08,  0x40,  0x1C,  0x7E,  0x1A,  0x12,  0x29,  0xCA,  0x48,  0xAA,  0x09,  0x22, 	/* 56050 */
+	0x08,  0x0C,  0x89,  0x08,  0x10,  0x08,  0x20,  0x7F,  0xFC,  0x00,  0x84,  0x3E,  0xFC,  0x22,  0x84,  0x3E, 	/* 56060 */
+	0xFC,  0x00,  0x80,  0x3E,  0xFF,  0x04,  0x80,  0x08,  0xFE,  0x0F,  0x0A,  0x79,  0xA6,  0x09,  0x52,  0x09, 	/* 56070 */
+	0x52,  0x1A,  0x0C,  0x8F,  0x06,  0x10,  0x79,  0x20,  0x11,  0xFC,  0x4A,  0x84,  0x2A,  0xFC,  0x24,  0x84, 	/* 56080 */
+	0x08,  0xFC,  0x3E,  0x80,  0x08,  0xFF,  0x08,  0x80,  0x7F,  0xFE,  0x08,  0x52,  0x14,  0xAA,  0x12,  0xAA, 	/* 56090 */
+	0x23,  0x02,  0x40,  0x0C,  0x9A,  0x00,  0x10,  0x77,  0x20,  0x55,  0xFC,  0x55,  0x84,  0x77,  0xFC,  0x00, 	/* 560A0 */
+	0x84,  0x3E,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x08,  0x80,  0x08,  0xFE,  0x1E,  0x12,  0x12,  0xCA,  0x02, 	/* 560B0 */
+	0xAA,  0x03,  0x22,  0x0C,  0x0C,  0xA4,  0x00,  0x10,  0x7F,  0x20,  0x41,  0xFC,  0x08,  0x84,  0x7F,  0xFC, 	/* 560C0 */
+	0x08,  0x84,  0x3E,  0xFC,  0x2A,  0x80,  0x3E,  0xFF,  0x2A,  0x80,  0x3E,  0xFE,  0x08,  0x2A,  0x7F,  0x96, 	/* 560D0 */
+	0x08,  0x92,  0x09,  0x02,  0x08,  0x0C,  0xA9,  0x3E,  0x20,  0x14,  0x3F,  0x08,  0x24,  0x7F,  0x54,  0x1A, 	/* 560E0 */
+	0x88,  0x2C,  0x14,  0x48,  0xA2,  0x1F,  0xF1,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x07,  0xFF,  0x04, 	/* 560F0 */
+	0x00,  0x27,  0xFC,  0x29,  0x24,  0x44,  0x98,  0xAB,  0x08,  0x10,  0x08,  0x20,  0x7F,  0xFC,  0x08,  0x44, 	/* 56100 */
+	0x7F,  0x7C,  0x4B,  0x44,  0x6D,  0x7C,  0x59,  0x40,  0x7F,  0x7F,  0x08,  0x40,  0x1C,  0x7E,  0x1A,  0x12, 	/* 56110 */
+	0x29,  0xCA,  0x48,  0xAA,  0x09,  0x22,  0x08,  0x0C,  0xAF,  0x08,  0x10,  0x2A,  0x54,  0x14,  0x28,  0x22, 	/* 56120 */
+	0x44,  0x7F,  0xFE,  0x41,  0x02,  0x4F,  0xF2,  0x08,  0x10,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xFF,  0x08, 	/* 56130 */
+	0x00,  0x0F,  0xFE,  0x29,  0x22,  0x24,  0x92,  0x40,  0x0C,  0xB2,  0x1E,  0x10,  0x02,  0x20,  0x12,  0x7C, 	/* 56140 */
+	0x29,  0x44,  0x4C,  0xFC,  0x12,  0x44,  0x3E,  0x7C,  0x00,  0x40,  0x7F,  0x7F,  0x33,  0x40,  0x55,  0x7E, 	/* 56150 */
+	0x11,  0x2A,  0x13,  0x56,  0x35,  0x52,  0x51,  0x82,  0x13,  0x04,  0xB4,  0x08,  0x10,  0x08,  0x20,  0x7F, 	/* 56160 */
+	0x7C,  0x49,  0x44,  0x52,  0x7C,  0x14,  0x44,  0x3F,  0x7C,  0x24,  0x40,  0x64,  0x7F,  0x3F,  0x40,  0x24, 	/* 56170 */
+	0x7E,  0x3F,  0x2A,  0x24,  0x56,  0x24,  0x52,  0x3F,  0x82,  0x01,  0x0C,  0xB8,  0x00,  0x08,  0x7F,  0x10, 	/* 56180 */
+	0x11,  0x7C,  0x11,  0x44,  0x77,  0x7C,  0x44,  0x44,  0x44,  0x7C,  0x77,  0x40,  0x33,  0x7F,  0x55,  0x40, 	/* 56190 */
+	0x11,  0x7E,  0x33,  0x2A,  0x55,  0x56,  0x11,  0x52,  0x11,  0x82,  0x66,  0x0C,  0xBA,  0x08,  0x10,  0x08, 	/* 561A0 */
+	0x20,  0x6B,  0xFC,  0x08,  0x84,  0x6B,  0xFC,  0x14,  0x84,  0x14,  0xFC,  0x22,  0x80,  0x7F,  0xFF,  0x22, 	/* 561B0 */
+	0x80,  0x3E,  0xFE,  0x22,  0x2A,  0x3E,  0x96,  0x22,  0x92,  0x23,  0x02,  0x26,  0x0C,  0xBB,  0x00,  0x10, 	/* 561C0 */
+	0x3E,  0x20,  0x22,  0xFC,  0x2E,  0x84,  0x2A,  0xFC,  0x7F,  0x84,  0x41,  0xFC,  0x7E,  0x80,  0x22,  0xFF, 	/* 561D0 */
+	0x3E,  0x80,  0x22,  0xFE,  0x3E,  0x12,  0x22,  0xAA,  0x22,  0xAA,  0x23,  0x02,  0x26,  0x0C,  0x81,  0x17, 	/* 561E0 */
+	0x08,  0x11,  0x10,  0x11,  0x3C,  0x2E,  0xA4,  0x40,  0x7C,  0x17,  0x24,  0x11,  0x3C,  0x20,  0xA0,  0x7F, 	/* 561F0 */
+	0xFF,  0x2A,  0xA0,  0x2A,  0xBE,  0x2B,  0xCA,  0x3E,  0x56,  0x60,  0x52,  0x00,  0x82,  0x00,  0x0C,  0x82, 	/* 56200 */
+	0x04,  0x10,  0x0F,  0x20,  0x11,  0xFC,  0x6A,  0x84,  0x14,  0xFC,  0x18,  0x84,  0x68,  0xFC,  0x1F,  0x80, 	/* 56210 */
+	0x24,  0xFF,  0x04,  0x80,  0x7F,  0xFE,  0x04,  0x0A,  0x25,  0x56,  0x25,  0x52,  0x3F,  0x82,  0x00,  0x0C, 	/* 56220 */
+	0x84,  0x02,  0x10,  0x7C,  0x20,  0x0A,  0xFC,  0x29,  0x84,  0x21,  0xFC,  0x48,  0x84,  0x0A,  0xFC,  0x34, 	/* 56230 */
+	0x80,  0x0A,  0xFF,  0x7E,  0x80,  0x08,  0xFE,  0x3E,  0x12,  0x09,  0xCA,  0x14,  0xAA,  0x23,  0x22,  0x40, 	/* 56240 */
+	0x0C,  0x86,  0x22,  0x10,  0x3C,  0x20,  0x21,  0xFC,  0x1F,  0x84,  0x00,  0xFC,  0x5E,  0x84,  0x52,  0xFC, 	/* 56250 */
+	0x5E,  0x80,  0x52,  0xFF,  0x5E,  0x80,  0x52,  0xFE,  0x5E,  0x12,  0x40,  0xCA,  0x7F,  0xAA,  0x15,  0x22, 	/* 56260 */
+	0x62,  0x0C,  0x8F,  0x08,  0x10,  0x08,  0x20,  0x7F,  0xFC,  0x08,  0x84,  0x3E,  0xFC,  0x22,  0x84,  0x3E, 	/* 56270 */
+	0xFC,  0x22,  0x80,  0x3E,  0xFF,  0x22,  0x80,  0x3E,  0xFE,  0x00,  0x12,  0x7E,  0xCA,  0x14,  0xAA,  0x22, 	/* 56280 */
+	0xA2,  0xC1,  0x0C,  0x93,  0x04,  0x10,  0x04,  0x20,  0x3F,  0xFC,  0x20,  0x84,  0x2A,  0xFC,  0x2A,  0x84, 	/* 56290 */
+	0x3F,  0xFC,  0x2A,  0x80,  0x2A,  0xFF,  0x2A,  0x80,  0x2E,  0xFE,  0x42,  0x0A,  0x15,  0x56,  0x15,  0x52, 	/* 562A0 */
+	0x20,  0x82,  0x40,  0x0C,  0x99,  0x04,  0x10,  0x3F,  0x10,  0x04,  0x7C,  0x7F,  0x94,  0x12,  0x54,  0x3F, 	/* 562B0 */
+	0x35,  0x04,  0x2D,  0x3F,  0x43,  0x04,  0x80,  0x07,  0xF0,  0x04,  0x10,  0x07,  0xFF,  0x04,  0x00,  0x27, 	/* 562C0 */
+	0xFC,  0x29,  0x24,  0x44,  0x98,  0xA6,  0x12,  0x10,  0x14,  0x20,  0x3F,  0xFC,  0x64,  0x84,  0x3E,  0xFC, 	/* 562D0 */
+	0x24,  0x84,  0x24,  0xFC,  0x3E,  0x80,  0x24,  0xFF,  0x24,  0x80,  0x3F,  0xFE,  0x04,  0x12,  0x32,  0xCA, 	/* 562E0 */
+	0x2A,  0xAA,  0x29,  0x22,  0x40,  0x0C,  0xAD,  0x02,  0x10,  0x7C,  0x20,  0x49,  0xFC,  0x2A,  0x84,  0x7F, 	/* 562F0 */
+	0xFC,  0x1C,  0x84,  0x2A,  0xFC,  0x49,  0x80,  0x3E,  0xFF,  0x2A,  0x80,  0x2A,  0xFE,  0x3E,  0x12,  0x2A, 	/* 56300 */
+	0xCA,  0x2A,  0xAA,  0x3F,  0x22,  0x00,  0x0C,  0xAF,  0x04,  0x10,  0x04,  0x20,  0x7F,  0xFC,  0x04,  0x44, 	/* 56310 */
+	0x4A,  0xFC,  0x29,  0x44,  0x1F,  0x7C,  0x31,  0xC0,  0x5F,  0x7F,  0x11,  0x40,  0x1F,  0x7E,  0x04,  0x0A, 	/* 56320 */
+	0x16,  0x56,  0x25,  0x52,  0x45,  0x82,  0x0C,  0x0C,  0xB2,  0x08,  0x14,  0x7F,  0x12,  0x22,  0xFF,  0x3E, 	/* 56330 */
+	0x18,  0x0A,  0x28,  0x29,  0x2A,  0x29,  0x4A,  0x5A,  0x86,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xFE,  0x08, 	/* 56340 */
+	0x00,  0x0F,  0xFE,  0x29,  0x22,  0x24,  0x92,  0x40,  0x0C,  0xB8,  0x00,  0x10,  0x3F,  0x20,  0x0A,  0x7C, 	/* 56350 */
+	0x04,  0x44,  0x7F,  0xFC,  0x15,  0x44,  0x24,  0x7C,  0x44,  0x40,  0x0C,  0x7F,  0x7F,  0x40,  0x55,  0x7E, 	/* 56360 */
+	0x67,  0x0A,  0x5D,  0x56,  0x55,  0x52,  0x5D,  0x82,  0x43,  0x0C,  0xB9,  0x00,  0x40,  0x1F,  0xFF,  0x12, 	/* 56370 */
+	0x48,  0x12,  0xFE,  0x15,  0x90,  0x1E,  0xFE,  0x14,  0x90,  0x14,  0xFF,  0x11,  0x00,  0x13,  0xF8,  0x12, 	/* 56380 */
+	0x08,  0x13,  0xFF,  0x22,  0x00,  0x2B,  0xFE,  0x4A,  0xAA,  0x11,  0x4C,  0xBA,  0x00,  0x20,  0x3E,  0x3C, 	/* 56390 */
+	0x22,  0xE4,  0x3E,  0x18,  0x08,  0x64,  0x2F,  0xFF,  0x28,  0x44,  0x3D,  0x7C,  0x67,  0xF0,  0x04,  0x10, 	/* 563A0 */
+	0x07,  0xFC,  0x04,  0x00,  0x07,  0xFE,  0x29,  0x22,  0x24,  0x92,  0x40,  0x0C,  0xBD,  0x06,  0x40,  0x19, 	/* 563B0 */
+	0x98,  0x12,  0x48,  0x19,  0x98,  0x12,  0x48,  0x7F,  0xFE,  0x41,  0x02,  0x4F,  0xF2,  0x08,  0x10,  0x0F, 	/* 563C0 */
+	0xF0,  0x08,  0x10,  0x0F,  0xFF,  0x08,  0x00,  0x2F,  0xFC,  0x29,  0x24,  0x44,  0x98,  0x9A,  0x00,  0x10, 	/* 563D0 */
+	0x3B,  0xA0,  0x2A,  0xBC,  0x3B,  0xA4,  0x2A,  0xBC,  0x3B,  0xA4,  0x2A,  0xBC,  0x3B,  0xA0,  0x4C,  0xFF, 	/* 563E0 */
+	0x08,  0x20,  0x7F,  0xBE,  0x0A,  0x0A,  0x12,  0x56,  0x1C,  0x52,  0x0A,  0x82,  0x31,  0x0C,  0x9B,  0x12, 	/* 563F0 */
+	0x10,  0x7F,  0xA0,  0x12,  0x7C,  0x77,  0x44,  0x55,  0x7C,  0x77,  0x44,  0x12,  0x7C,  0x14,  0x40,  0x3F, 	/* 56400 */
+	0x7F,  0x64,  0x40,  0x3E,  0x7E,  0x24,  0x52,  0x3E,  0xAA,  0x24,  0xAA,  0x3F,  0x02,  0x00,  0x0C,  0x9E, 	/* 56410 */
+	0x11,  0x84,  0x17,  0xE4,  0x68,  0x1A,  0x13,  0xC4,  0x28,  0x0A,  0x7F,  0xDF,  0x12,  0x44,  0x5B,  0xD5, 	/* 56420 */
+	0x54,  0x15,  0x0F,  0xF0,  0x08,  0x10,  0x0F,  0xFF,  0x08,  0x00,  0x2F,  0xFC,  0x29,  0x24,  0x44,  0x98, 	/* 56430 */
+	0xB5,  0x01,  0x00,  0x01,  0x00,  0x01,  0xFE,  0x01,  0x00,  0x01,  0x00,  0x3F,  0xFC,  0x21,  0x04,  0x2C, 	/* 56440 */
+	0x94,  0x22,  0x24,  0x31,  0x54,  0x28,  0x8C,  0x23,  0x44,  0x2C,  0x24,  0x20,  0x84,  0x3F,  0xFC,  0x00, 	/* 56450 */
+	0x00,  0xB8,  0x08,  0x10,  0x08,  0x10,  0x0F,  0x28,  0x08,  0x24,  0x08,  0x7E,  0x7F,  0x91,  0x49,  0x7E, 	/* 56460 */
+	0x45,  0x52,  0x55,  0x52,  0x4B,  0x7E,  0x6D,  0x10,  0x4B,  0x18,  0x51,  0x28,  0x49,  0x24,  0x7F,  0x42, 	/* 56470 */
+	0x01,  0x81,  0xB9,  0x08,  0x0A,  0x08,  0x09,  0x0F,  0x08,  0x08,  0x7F,  0x08,  0x48,  0x7F,  0x4A,  0x49, 	/* 56480 */
+	0x7A,  0x41,  0x4A,  0x55,  0x7A,  0x6B,  0x54,  0x49,  0x54,  0x55,  0x74,  0x41,  0x4D,  0x49,  0x53,  0x7F, 	/* 56490 */
+	0xA3,  0x01,  0x01,  0xBD,  0x00,  0x20,  0x3F,  0xBF,  0x24,  0x50,  0x24,  0x9E,  0x3F,  0x10,  0x21,  0x7E, 	/* 564A0 */
+	0x3F,  0x4A,  0x24,  0x6A,  0x24,  0x56,  0x3F,  0x6A,  0x00,  0x7E,  0x1F,  0xFC,  0x12,  0x44,  0x12,  0x44, 	/* 564B0 */
+	0x7F,  0xFF,  0x00,  0x00,  0xBF,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFF,  0x11,  0x20,  0x11,  0x20,  0x1F, 	/* 564C0 */
+	0xFE,  0x11,  0x22,  0x11,  0x22,  0x1F,  0xFE,  0x14,  0x20,  0x14,  0x24,  0x17,  0xB8,  0x24,  0x20,  0x24, 	/* 564D0 */
+	0x22,  0x47,  0xA2,  0x1C,  0x1E,  0x81,  0x00,  0x80,  0x01,  0xF0,  0x07,  0x20,  0x18,  0xC0,  0x7F,  0xFE, 	/* 564E0 */
+	0x11,  0x20,  0x1F,  0xFE,  0x11,  0x22,  0x11,  0x22,  0x1F,  0xFE,  0x14,  0x20,  0x14,  0x24,  0x27,  0xB8, 	/* 564F0 */
+	0x24,  0x22,  0x47,  0xA2,  0x1C,  0x1E,  0x88,  0x00,  0x40,  0x1F,  0xFF,  0x11,  0x20,  0x1F,  0xFE,  0x11, 	/* 56500 */
+	0x22,  0x1F,  0xFE,  0x17,  0xA2,  0x14,  0x3C,  0x17,  0xE1,  0x1C,  0x5F,  0x17,  0xFC,  0x10,  0x40,  0x23, 	/* 56510 */
+	0xF8,  0x20,  0x40,  0x5F,  0xFF,  0x00,  0x00,  0x8B,  0x00,  0x40,  0x1F,  0xFF,  0x11,  0x20,  0x1F,  0xFE, 	/* 56520 */
+	0x11,  0x22,  0x1F,  0xFE,  0x14,  0x20,  0x27,  0xBC,  0x24,  0x21,  0x4F,  0x1F,  0x10,  0x88,  0x08,  0x90, 	/* 56530 */
+	0x7F,  0xFF,  0x02,  0xA0,  0x0C,  0x98,  0x70,  0x87,  0x8C,  0x00,  0x40,  0x1F,  0xFF,  0x11,  0x20,  0x1F, 	/* 56540 */
+	0xFE,  0x11,  0x22,  0x1F,  0xFE,  0x14,  0x24,  0x37,  0xB8,  0x24,  0x21,  0x57,  0xFF,  0x12,  0x10,  0x1F, 	/* 56550 */
+	0xFC,  0x00,  0x04,  0x7F,  0xFF,  0x03,  0x18,  0x1C,  0x06,  0x91,  0x00,  0x40,  0x1F,  0xFF,  0x11,  0x20, 	/* 56560 */
+	0x1F,  0xFE,  0x11,  0x22,  0x1F,  0xFE,  0x14,  0x24,  0x27,  0xB8,  0x24,  0xA1,  0x47,  0x3F,  0x1C,  0x08, 	/* 56570 */
+	0x07,  0xB8,  0x04,  0x08,  0x07,  0xF9,  0x01,  0x21,  0x7E,  0x1F,  0x92,  0x04,  0x24,  0x04,  0x24,  0x3F, 	/* 56580 */
+	0xFF,  0x2A,  0x24,  0x2A,  0x24,  0x3F,  0xBC,  0x2A,  0xA4,  0x2A,  0xA4,  0x3F,  0xBC,  0x20,  0x24,  0x2A, 	/* 56590 */
+	0xA4,  0x2E,  0xFF,  0x2B,  0x00,  0x2A,  0x94,  0x4E,  0xA2,  0x19,  0xC2,  0x93,  0x08,  0x08,  0x7F,  0x7F, 	/* 565A0 */
+	0x1C,  0x1C,  0x2A,  0x2A,  0x48,  0x49,  0x00,  0x80,  0x1F,  0xFF,  0x11,  0x20,  0x1F,  0xFE,  0x11,  0x22, 	/* 565B0 */
+	0x1F,  0xFE,  0x14,  0x24,  0x27,  0xB8,  0x24,  0x22,  0x47,  0xE2,  0x1C,  0x1E,  0x95,  0x00,  0x40,  0x1F, 	/* 565C0 */
+	0xFF,  0x11,  0x10,  0x1F,  0xFE,  0x11,  0x12,  0x1F,  0xFE,  0x15,  0xBC,  0x26,  0x22,  0x5F,  0xFE,  0x10, 	/* 565D0 */
+	0x64,  0x13,  0x84,  0x1F,  0xFC,  0x12,  0xA4,  0x14,  0x94,  0x1F,  0xFC,  0x00,  0x00,  0x97,  0x3F,  0x7E, 	/* 565E0 */
+	0x00,  0x00,  0x1F,  0x7C,  0x11,  0x44,  0x15,  0x54,  0x00,  0x80,  0x1F,  0xFE,  0x11,  0x20,  0x1F,  0xFC, 	/* 565F0 */
+	0x11,  0x24,  0x1F,  0xFC,  0x14,  0x24,  0x27,  0xB8,  0x24,  0x22,  0x47,  0xA2,  0x38,  0x1E,  0x9D,  0x00, 	/* 56600 */
+	0x40,  0x1F,  0xFF,  0x11,  0x20,  0x1F,  0xFE,  0x11,  0x22,  0x1F,  0xFE,  0x24,  0x22,  0x27,  0xBC,  0x44, 	/* 56610 */
+	0x21,  0x1F,  0x9F,  0x11,  0x04,  0x1F,  0xFF,  0x11,  0x44,  0x7F,  0x24,  0x09,  0x04,  0x73,  0x0C,  0x9F, 	/* 56620 */
+	0x04,  0x0A,  0x04,  0x2A,  0x3F,  0x9C,  0x2A,  0x7F,  0x3F,  0x9C,  0x2A,  0xAA,  0x2A,  0xC9,  0x3F,  0xA8, 	/* 56630 */
+	0x20,  0x22,  0x2A,  0x3A,  0x2A,  0xAF,  0x2F,  0x6A,  0x2A,  0x9A,  0x2A,  0x9F,  0x4E,  0xA2,  0x11,  0xC2, 	/* 56640 */
+	0xA5,  0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x08,  0x88,  0x08,  0x88,  0x0C,  0x8C,  0x13,  0x52,  0x22, 	/* 56650 */
+	0x20,  0x0D,  0x18,  0x71,  0xF7,  0x02,  0x10,  0x05,  0xA0,  0x18,  0x40,  0x01,  0xB0,  0x06,  0x08,  0x78, 	/* 56660 */
+	0x04,  0xA6,  0x00,  0x80,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF, 	/* 56670 */
+	0x01,  0x00,  0x01,  0xF0,  0x02,  0x10,  0x0E,  0x20,  0x31,  0x40,  0x01,  0xC0,  0x02,  0x20,  0x0C,  0x18, 	/* 56680 */
+	0x70,  0x07,  0xA9,  0x08,  0x10,  0x08,  0x10,  0x7F,  0x10,  0x2A,  0x7E,  0x2A,  0x10,  0x3D,  0x10,  0x4C, 	/* 56690 */
+	0x10,  0x1A,  0x7F,  0x69,  0x90,  0x0E,  0x10,  0x12,  0x18,  0x34,  0x28,  0x4C,  0x24,  0x12,  0x42,  0x21, 	/* 566A0 */
+	0x80,  0x40,  0x7F,  0xAA,  0x08,  0x00,  0x08,  0xFF,  0x7F,  0x10,  0x2A,  0x10,  0x2A,  0x5E,  0x3D,  0x52, 	/* 566B0 */
+	0x4C,  0x52,  0x1A,  0x52,  0x69,  0x52,  0x0E,  0x52,  0x12,  0x7E,  0x34,  0x42,  0x4C,  0x02,  0x12,  0x0C, 	/* 566C0 */
+	0x21,  0x80,  0x40,  0x7F,  0xAD,  0x08,  0x20,  0x08,  0x20,  0x7F,  0x20,  0x2A,  0x3E,  0x2A,  0x42,  0x3D, 	/* 566D0 */
+	0x72,  0x4C,  0xD2,  0x1A,  0x52,  0x69,  0x72,  0x0E,  0x4C,  0x12,  0x40,  0x34,  0x42,  0x4C,  0x42,  0x12, 	/* 566E0 */
+	0x3E,  0x21,  0x80,  0x40,  0x7F,  0xB8,  0x08,  0x10,  0x08,  0x10,  0x7F,  0x10,  0x08,  0x7E,  0x3E,  0x10, 	/* 566F0 */
+	0x08,  0x10,  0x7F,  0x10,  0x08,  0xFF,  0x0E,  0x10,  0x12,  0x18,  0x32,  0x28,  0x4C,  0x24,  0x0C,  0x42, 	/* 56700 */
+	0x12,  0x81,  0x21,  0x80,  0x40,  0x7F,  0xB9,  0x08,  0x40,  0x08,  0x40,  0x3E,  0xFE,  0x08,  0xA2,  0x3F, 	/* 56710 */
+	0x2A,  0x08,  0xB2,  0x7F,  0x62,  0x10,  0xFA,  0x1E,  0x22,  0x12,  0x72,  0x34,  0xAA,  0x4D,  0x22,  0x0A, 	/* 56720 */
+	0x24,  0x11,  0x18,  0x20,  0xC0,  0x40,  0x3F,  0xBA,  0x08,  0x00,  0x09,  0xFF,  0x7F,  0x10,  0x08,  0x20, 	/* 56730 */
+	0x3E,  0xFE,  0x08,  0xAA,  0x7F,  0xBA,  0x08,  0xAA,  0x0E,  0xAA,  0x12,  0xBA,  0x2A,  0xAA,  0x44,  0xAA, 	/* 56740 */
+	0x0C,  0xFE,  0x12,  0x00,  0x21,  0x80,  0x40,  0x7F,  0xBB,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFE,  0x12, 	/* 56750 */
+	0x10,  0x12,  0x10,  0x12,  0x10,  0x1F,  0xFE,  0x12,  0x10,  0x16,  0x38,  0x17,  0x38,  0x16,  0xD4,  0x1A, 	/* 56760 */
+	0x54,  0x2A,  0x92,  0x32,  0x10,  0x42,  0x10,  0x02,  0x10,  0xBC,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFF, 	/* 56770 */
+	0x11,  0x08,  0x1F,  0xFF,  0x11,  0x08,  0x15,  0x5A,  0x15,  0x5A,  0x19,  0x5B,  0x10,  0x88,  0x10,  0x90, 	/* 56780 */
+	0x17,  0x20,  0x21,  0x48,  0x20,  0x84,  0x5F,  0xFA,  0x00,  0x02,  0xBE,  0x00,  0x40,  0x1F,  0xFF,  0x11, 	/* 56790 */
+	0x08,  0x1F,  0xFF,  0x11,  0x08,  0x15,  0xAA,  0x15,  0xAA,  0x1D,  0x4B,  0x10,  0x30,  0x13,  0xC0,  0x10, 	/* 567A0 */
+	0x78,  0x17,  0xC0,  0x20,  0x7E,  0x2F,  0xC1,  0x40,  0x41,  0x00,  0x3F,  0xBF,  0x00,  0x80,  0x00,  0x80, 	/* 567B0 */
+	0x1F,  0xFF,  0x12,  0x08,  0x1F,  0xFF,  0x13,  0x1C,  0x16,  0xAA,  0x1A,  0x49,  0x13,  0xF8,  0x12,  0x08, 	/* 567C0 */
+	0x13,  0xF8,  0x10,  0x40,  0x27,  0xFC,  0x24,  0x04,  0x47,  0xFC,  0x00,  0x00,  0x84,  0x02,  0x20,  0x02, 	/* 567D0 */
+	0x20,  0x1F,  0xFC,  0x02,  0x20,  0x02,  0x20,  0x7F,  0xFF,  0x00,  0x80,  0x0F,  0xF8,  0x08,  0x88,  0x08, 	/* 567E0 */
+	0x88,  0x0F,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x0F,  0xF8,  0x04,  0x18,  0x38,  0x06,  0x8C,  0x06,  0x40, 	/* 567F0 */
+	0x19,  0x98,  0x12,  0x48,  0x19,  0x98,  0x12,  0x48,  0x7F,  0xFE,  0x42,  0x42,  0x5F,  0xFA,  0x02,  0x40, 	/* 56800 */
+	0x7F,  0xFE,  0x11,  0x08,  0x1F,  0xF8,  0x11,  0x08,  0x1F,  0xF8,  0x0C,  0x30,  0x70,  0x0C,  0x8D,  0x00, 	/* 56810 */
+	0x08,  0x00,  0x70,  0x1F,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0xA0,  0x0C,  0x98,  0x71,  0x47,  0x02, 	/* 56820 */
+	0x20,  0x0C,  0x98,  0x74,  0x8F,  0x02,  0x90,  0x03,  0xE0,  0x0C,  0x98,  0x30,  0x86,  0x01,  0x80,  0x8E, 	/* 56830 */
+	0x01,  0x10,  0x06,  0x10,  0x3C,  0x3E,  0x04,  0x2A,  0x7F,  0xCA,  0x0E,  0x12,  0x15,  0x22,  0x64,  0x8C, 	/* 56840 */
+	0x05,  0x40,  0x02,  0x20,  0x0C,  0x98,  0x78,  0xB7,  0x05,  0xC0,  0x06,  0xB0,  0x38,  0x8E,  0x01,  0x80, 	/* 56850 */
+	0x8F,  0x01,  0x10,  0x06,  0x10,  0x3C,  0x10,  0x04,  0x10,  0x7F,  0xDF,  0x0E,  0x10,  0x15,  0x10,  0x64, 	/* 56860 */
+	0x90,  0x0A,  0x10,  0x11,  0x7E,  0x74,  0xC2,  0x15,  0x42,  0x0E,  0x42,  0x35,  0x42,  0x44,  0xFE,  0x0C, 	/* 56870 */
+	0x00,  0x90,  0x02,  0x10,  0x0C,  0x10,  0x79,  0xFF,  0x08,  0x08,  0x7F,  0x4C,  0x1C,  0x74,  0x2A,  0x5C, 	/* 56880 */
+	0x48,  0x64,  0x14,  0x7C,  0x12,  0x20,  0x29,  0xFE,  0x6A,  0x92,  0x1C,  0x9A,  0x2A,  0xF6,  0x49,  0x82, 	/* 56890 */
+	0x18,  0x86,  0x92,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x88,  0x08,  0x88,  0x0F,  0xF8,  0x08,  0x88,  0x08, 	/* 568A0 */
+	0x88,  0x0F,  0xF8,  0x00,  0x80,  0x1F,  0xFC,  0x00,  0x80,  0x7F,  0xFF,  0x00,  0x00,  0x12,  0x24,  0x21, 	/* 568B0 */
+	0x12,  0x41,  0x11,  0x94,  0x00,  0x10,  0x3F,  0x10,  0x29,  0x10,  0x2B,  0x28,  0x3B,  0x28,  0x3D,  0x44, 	/* 568C0 */
+	0x29,  0xBE,  0x3F,  0x01,  0x08,  0x00,  0x3F,  0x7C,  0x08,  0x04,  0x0B,  0x84,  0x7D,  0x08,  0x22,  0x88, 	/* 568D0 */
+	0x2A,  0x10,  0x48,  0x10,  0x98,  0x00,  0x08,  0x3F,  0x8A,  0x24,  0x89,  0x25,  0x89,  0x35,  0x88,  0x2E, 	/* 568E0 */
+	0xFF,  0x2C,  0x88,  0x3F,  0x88,  0x04,  0x0C,  0x3F,  0x0C,  0x04,  0x14,  0x07,  0x94,  0x7D,  0x14,  0x32, 	/* 568F0 */
+	0xA2,  0x2A,  0x42,  0x48,  0x81,  0x99,  0x00,  0x10,  0x3F,  0x14,  0x29,  0x12,  0x3F,  0x10,  0x29,  0xFF, 	/* 56900 */
+	0x29,  0x10,  0x3F,  0x28,  0x08,  0x28,  0x3F,  0x24,  0x08,  0x44,  0x0E,  0x82,  0x79,  0x01,  0x10,  0x08, 	/* 56910 */
+	0x14,  0x44,  0x22,  0x22,  0x42,  0x22,  0x9B,  0x04,  0x28,  0x08,  0x24,  0x1B,  0xFF,  0x68,  0x20,  0x08, 	/* 56920 */
+	0x11,  0x0F,  0xFD,  0x08,  0x8B,  0x0F,  0xF9,  0x08,  0x88,  0x0F,  0xF8,  0x00,  0x80,  0x1F,  0xFC,  0x00, 	/* 56930 */
+	0x80,  0x7F,  0xFF,  0x12,  0x24,  0x61,  0x13,  0x9C,  0x00,  0x10,  0x3F,  0x52,  0x29,  0x52,  0x2B,  0x52, 	/* 56940 */
+	0x3B,  0x52,  0x3D,  0x52,  0x29,  0x7E,  0x3F,  0x10,  0x08,  0x10,  0x3F,  0x52,  0x08,  0x52,  0x0B,  0xD2, 	/* 56950 */
+	0x7D,  0x52,  0x22,  0xD2,  0x2A,  0xFE,  0x48,  0x00,  0x9D,  0x00,  0x48,  0x3E,  0x48,  0x2A,  0x48,  0x2E, 	/* 56960 */
+	0x7E,  0x3E,  0x4A,  0x3B,  0x8A,  0x2B,  0x2A,  0x3E,  0xAA,  0x08,  0x4A,  0x3E,  0x4A,  0x08,  0xAA,  0x0B, 	/* 56970 */
+	0x32,  0x7D,  0xD2,  0x22,  0x22,  0x2A,  0x42,  0x48,  0x8C,  0x9E,  0x00,  0x10,  0x3F,  0x10,  0x29,  0x10, 	/* 56980 */
+	0x2B,  0x1F,  0x3B,  0x10,  0x3D,  0x10,  0x29,  0x10,  0x3F,  0x10,  0x08,  0x7E,  0x3F,  0x42,  0x08,  0x42, 	/* 56990 */
+	0x0B,  0xC2,  0x7D,  0x42,  0x22,  0xC2,  0x2A,  0x7E,  0x48,  0x00,  0xA0,  0x00,  0x10,  0x3F,  0x10,  0x29, 	/* 569A0 */
+	0x10,  0x2B,  0xFF,  0x3B,  0x10,  0x3D,  0x10,  0x29,  0x10,  0x3F,  0x7E,  0x08,  0x00,  0x3F,  0x7C,  0x08, 	/* 569B0 */
+	0x44,  0x0B,  0xC4,  0x7D,  0x44,  0x22,  0xC4,  0x2A,  0x7C,  0x48,  0x00,  0xA5,  0x00,  0x10,  0x3F,  0x10, 	/* 569C0 */
+	0x29,  0xFF,  0x2B,  0x00,  0x3B,  0x7C,  0x3D,  0x44,  0x29,  0x44,  0x3F,  0x44,  0x08,  0x7C,  0x3F,  0x10, 	/* 569D0 */
+	0x08,  0x58,  0x0B,  0x54,  0x7D,  0x52,  0x22,  0x92,  0x2B,  0x10,  0x48,  0x30,  0xA8,  0x08,  0x90,  0x04, 	/* 569E0 */
+	0xA0,  0x7F,  0xFE,  0x40,  0x02,  0x4F,  0xF2,  0x08,  0x10,  0x0F,  0xF0,  0x00,  0x00,  0x1F,  0xF8,  0x14, 	/* 569F0 */
+	0xA8,  0x12,  0xC8,  0x3F,  0xFE,  0x00,  0x80,  0x7F,  0xFF,  0x14,  0x44,  0x62,  0x22,  0xAF,  0x00,  0x10, 	/* 56A00 */
+	0x3F,  0x10,  0x29,  0xFF,  0x2B,  0x44,  0x3B,  0x24,  0x3D,  0x28,  0x29,  0xFF,  0x3F,  0x00,  0x08,  0x7C, 	/* 56A10 */
+	0x3F,  0x44,  0x08,  0x44,  0x0B,  0xFC,  0x7D,  0x44,  0x22,  0xC4,  0x2A,  0x7C,  0x48,  0x00,  0xB4,  0x0D, 	/* 56A20 */
+	0x48,  0x0D,  0x48,  0x17,  0xC8,  0x10,  0x0F,  0x27,  0xD2,  0x4D,  0xD2,  0x0F,  0x5A,  0x15,  0x6A,  0x17, 	/* 56A30 */
+	0xCA,  0x31,  0x0C,  0x57,  0xC4,  0x11,  0x6C,  0x1F,  0x8A,  0x16,  0x52,  0x15,  0x22,  0x18,  0x41,  0xB6, 	/* 56A40 */
+	0x00,  0x00,  0x1F,  0xFF,  0x14,  0x4A,  0x17,  0xFF,  0x14,  0x48,  0x17,  0xCC,  0x14,  0x54,  0x24,  0xE2, 	/* 56A50 */
+	0x2F,  0xF9,  0x4C,  0x98,  0x0A,  0xA8,  0x3F,  0xFE,  0x00,  0x80,  0x7F,  0xFF,  0x12,  0x26,  0x61,  0x11, 	/* 56A60 */
+	0xB7,  0x00,  0x08,  0x3F,  0xFF,  0x29,  0x08,  0x2B,  0x7E,  0x3B,  0x00,  0x3D,  0x7F,  0x29,  0x55,  0x3F, 	/* 56A70 */
+	0x7F,  0x08,  0x22,  0x3F,  0x3E,  0x08,  0x22,  0x0B,  0xBE,  0x7D,  0x22,  0x22,  0xBE,  0x2A,  0x32,  0x48, 	/* 56A80 */
+	0xC1,  0xB9,  0x11,  0x44,  0x09,  0x44,  0x09,  0x48,  0x7F,  0xFF,  0x08,  0x88,  0x08,  0x84,  0x10,  0x82, 	/* 56A90 */
+	0x3F,  0xFD,  0x50,  0x85,  0x12,  0xA4,  0x12,  0xA4,  0x12,  0xA4,  0x12,  0xA4,  0x12,  0xA4,  0x14,  0xA4, 	/* 56AA0 */
+	0x10,  0x8C,  0xBB,  0x0A,  0x14,  0x2A,  0x92,  0x1B,  0x12,  0x7F,  0xFF,  0x15,  0x10,  0x24,  0x92,  0x44, 	/* 56AB0 */
+	0x12,  0x3F,  0xAA,  0x24,  0xAA,  0x2D,  0xAC,  0x2D,  0xA4,  0x2D,  0xCC,  0x2D,  0xCD,  0x34,  0x93,  0x24, 	/* 56AC0 */
+	0xA3,  0x25,  0x81,  0xBC,  0x0A,  0x08,  0x2A,  0x8C,  0x1B,  0x0A,  0x7F,  0xFF,  0x15,  0x08,  0x24,  0xBE, 	/* 56AD0 */
+	0x44,  0x2A,  0x3F,  0xAA,  0x24,  0xBE,  0x2D,  0xAA,  0x2D,  0xAA,  0x2D,  0xBE,  0x2D,  0xAA,  0x34,  0xAA, 	/* 56AE0 */
+	0x24,  0xAA,  0x25,  0xA6,  0xBD,  0x00,  0x00,  0x3F,  0xFC,  0x22,  0x44,  0x22,  0x44,  0x3E,  0x7C,  0x02, 	/* 56AF0 */
+	0x40,  0x3E,  0x7C,  0x22,  0x44,  0x22,  0x44,  0x3E,  0x7C,  0x22,  0x44,  0x22,  0x44,  0x3E,  0x7D,  0x02, 	/* 56B00 */
+	0x01,  0x02,  0x01,  0x01,  0xFF,  0x87,  0x04,  0x20,  0x3F,  0x3F,  0x04,  0x24,  0x7F,  0xB4,  0x08,  0x48, 	/* 56B10 */
+	0x1F,  0x14,  0x21,  0x22,  0x5F,  0xF9,  0x12,  0x48,  0x3E,  0x7C,  0x22,  0x44,  0x3E,  0x7C,  0x22,  0x44, 	/* 56B20 */
+	0x3E,  0x7D,  0x02,  0x01,  0x01,  0xFF,  0x88,  0x1A,  0x10,  0x29,  0x1F,  0x7F,  0xA4,  0x48,  0xD4,  0x5A, 	/* 56B30 */
+	0x88,  0x6A,  0x94,  0x49,  0xA2,  0x5F,  0xF9,  0x12,  0x48,  0x3E,  0x7C,  0x22,  0x44,  0x3E,  0x7C,  0x22, 	/* 56B40 */
+	0x44,  0x3E,  0x7D,  0x02,  0x01,  0x01,  0xFF,  0x8E,  0x00,  0x00,  0x17,  0xF4,  0x14,  0x14,  0x17,  0xF4, 	/* 56B50 */
+	0x14,  0x14,  0x17,  0xF4,  0x14,  0x14,  0x17,  0xF4,  0x10,  0x04,  0x3F,  0x7C,  0x01,  0x40,  0x7F,  0x7F, 	/* 56B60 */
+	0x09,  0x44,  0x09,  0x44,  0x11,  0x44,  0x21,  0x44,  0x93,  0x08,  0x10,  0x08,  0x10,  0x7F,  0xFF,  0x08, 	/* 56B70 */
+	0x10,  0x3E,  0x10,  0x00,  0xFC,  0x3E,  0x44,  0x22,  0x44,  0x22,  0x44,  0x3E,  0x28,  0x02,  0x28,  0x24, 	/* 56B80 */
+	0x10,  0x11,  0x28,  0x16,  0x44,  0x18,  0x82,  0x61,  0x01,  0x95,  0x04,  0x08,  0x7F,  0xC8,  0x04,  0x7F, 	/* 56B90 */
+	0x3F,  0x88,  0x11,  0x7E,  0x1F,  0x24,  0x12,  0x18,  0x0F,  0x94,  0x70,  0xA3,  0x01,  0xF0,  0x07,  0x10, 	/* 56BA0 */
+	0x18,  0xE0,  0x03,  0xD8,  0x7C,  0x27,  0x03,  0x80,  0x00,  0x70,  0xA0,  0x02,  0x00,  0x1C,  0xF8,  0x10, 	/* 56BB0 */
+	0x08,  0x1E,  0x78,  0x10,  0x08,  0x1F,  0xF8,  0x00,  0x00,  0x14,  0xC8,  0x12,  0xA8,  0x10,  0x88,  0x14, 	/* 56BC0 */
+	0xC8,  0x12,  0xA8,  0x10,  0x85,  0x16,  0xB5,  0x18,  0xC3,  0x63,  0x01,  0xA1,  0x02,  0x08,  0x21,  0x08, 	/* 56BD0 */
+	0x11,  0x10,  0x10,  0x20,  0x00,  0x40,  0x1F,  0xF8,  0x11,  0x08,  0x11,  0x08,  0x1F,  0xF8,  0x11,  0x08, 	/* 56BE0 */
+	0x11,  0x08,  0x1F,  0xF8,  0x11,  0x09,  0x21,  0x05,  0x21,  0x03,  0x41,  0x01,  0xAC,  0x08,  0x10,  0x33, 	/* 56BF0 */
+	0x10,  0x21,  0x10,  0x3B,  0x7E,  0x21,  0x52,  0x21,  0x52,  0x3F,  0x52,  0x00,  0x7E,  0x25,  0x52,  0x37, 	/* 56C00 */
+	0x52,  0x25,  0x52,  0x25,  0x7E,  0x37,  0x00,  0x24,  0x81,  0x37,  0x61,  0x6C,  0x1F,  0xBB,  0x01,  0x00, 	/* 56C10 */
+	0x07,  0xF0,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x1F,  0xFC,  0x10,  0x84, 	/* 56C20 */
+	0x1F,  0xFC,  0x10,  0x84,  0x1F,  0xFC,  0x02,  0x10,  0x7F,  0xFF,  0x04,  0x10,  0x08,  0x10,  0xBE,  0x04, 	/* 56C30 */
+	0x00,  0x1F,  0x7E,  0x11,  0x08,  0x1F,  0x08,  0x11,  0x08,  0x1F,  0x08,  0x11,  0x08,  0x3F,  0xFF,  0x24, 	/* 56C40 */
+	0x88,  0x3F,  0x88,  0x24,  0x88,  0x3F,  0x88,  0x00,  0x08,  0x7F,  0xC8,  0x09,  0x08,  0x11,  0x08,  0x8A, 	/* 56C50 */
+	0x00,  0x80,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0x22,  0x7D,  0x5C,  0x14,  0x94,  0x14,  0x94,  0x2C,  0x9A, 	/* 56C60 */
+	0x40,  0x81,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x0F,  0xF8,  0x08,  0x08,  0x10,  0x08,  0x20,  0x08, 	/* 56C70 */
+	0x8B,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0x22,  0x7D,  0x5C,  0x14,  0x94,  0x14,  0x92,  0x2C,  0x99,  0x48, 	/* 56C80 */
+	0x04,  0x0F,  0xFC,  0x08,  0x04,  0x0F,  0xFC,  0x08,  0x84,  0x0A,  0xA4,  0x12,  0x94,  0x14,  0x94,  0x21, 	/* 56C90 */
+	0x84,  0x8E,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0x22,  0x3D,  0x5C,  0x14,  0x94,  0x2C,  0x9A,  0x50,  0x05, 	/* 56CA0 */
+	0x1F,  0xFC,  0x10,  0x04,  0x1F,  0xFC,  0x14,  0x14,  0x17,  0xF4,  0x14,  0x14,  0x17,  0xF4,  0x22,  0x24, 	/* 56CB0 */
+	0x44,  0x14,  0x8F,  0x00,  0x80,  0x7F,  0xFF,  0x02,  0x22,  0x7D,  0x5C,  0x14,  0x94,  0x2C,  0x9A,  0x48, 	/* 56CC0 */
+	0x85,  0x0F,  0xFC,  0x08,  0x04,  0x0F,  0xFC,  0x09,  0x24,  0x0F,  0x3C,  0x0F,  0x3C,  0x11,  0x24,  0x17, 	/* 56CD0 */
+	0xFC,  0x20,  0x04,  0x92,  0x00,  0x80,  0x08,  0x80,  0x08,  0xFC,  0x08,  0x80,  0x08,  0x80,  0x7F,  0xFF, 	/* 56CE0 */
+	0x12,  0x24,  0x12,  0x24,  0x15,  0x54,  0x1F,  0xFC,  0x12,  0x24,  0x12,  0x24,  0x15,  0x54,  0x10,  0x04, 	/* 56CF0 */
+	0x1F,  0xFC,  0x00,  0x00,  0x94,  0x04,  0x20,  0x14,  0x20,  0x17,  0xA0,  0x14,  0x22,  0x14,  0x22,  0x7F, 	/* 56D00 */
+	0xE4,  0x2A,  0xA8,  0x2A,  0xB0,  0x35,  0xA0,  0x3F,  0xA0,  0x2A,  0xA0,  0x2A,  0xA0,  0x35,  0xA1,  0x20, 	/* 56D10 */
+	0xA1,  0x3F,  0x9F,  0x00,  0x00,  0x9F,  0x04,  0x00,  0x14,  0x3E,  0x17,  0xA2,  0x14,  0x22,  0x14,  0x22, 	/* 56D20 */
+	0x7F,  0xBE,  0x2A,  0xA2,  0x2A,  0xA2,  0x35,  0xA2,  0x3F,  0xBE,  0x2A,  0xA2,  0x2A,  0xA2,  0x35,  0xA2, 	/* 56D30 */
+	0x20,  0xA2,  0x3F,  0xFF,  0x00,  0x00,  0xA0,  0x04,  0x00,  0x14,  0x7E,  0x17,  0x92,  0x14,  0x12,  0x14, 	/* 56D40 */
+	0x12,  0x7F,  0xD2,  0x2A,  0xA2,  0x2A,  0xAC,  0x35,  0xC0,  0x3F,  0xBE,  0x2A,  0xA2,  0x2A,  0xA2,  0x35, 	/* 56D50 */
+	0xA2,  0x20,  0xA2,  0x3F,  0xBE,  0x00,  0x00,  0xA1,  0x04,  0x08,  0x14,  0x08,  0x17,  0x94,  0x14,  0x14, 	/* 56D60 */
+	0x14,  0x22,  0x7F,  0xFD,  0x2A,  0x80,  0x2A,  0x80,  0x35,  0xFE,  0x3F,  0x92,  0x2A,  0x92,  0x2A,  0x92, 	/* 56D70 */
+	0x35,  0x9C,  0x20,  0x90,  0x3F,  0x90,  0x00,  0x10,  0xA2,  0x04,  0x10,  0x14,  0x10,  0x17,  0xA8,  0x14, 	/* 56D80 */
+	0x28,  0x14,  0x44,  0x7F,  0xBA,  0x25,  0x81,  0x36,  0x80,  0x2C,  0xFE,  0x3F,  0x92,  0x24,  0x92,  0x2E, 	/* 56D90 */
+	0x92,  0x35,  0x9C,  0x24,  0x90,  0x3F,  0x90,  0x00,  0x10,  0xA3,  0x04,  0x20,  0x14,  0x20,  0x17,  0xBE, 	/* 56DA0 */
+	0x14,  0x22,  0x14,  0x42,  0x7F,  0xFA,  0x2A,  0xAA,  0x2A,  0xAA,  0x35,  0xAA,  0x3F,  0xAA,  0x2A,  0xBA, 	/* 56DB0 */
+	0x2A,  0x82,  0x35,  0x82,  0x20,  0x82,  0x3F,  0x82,  0x00,  0x0C,  0xA6,  0x04,  0x00,  0x14,  0x3E,  0x17, 	/* 56DC0 */
+	0xA2,  0x14,  0x22,  0x14,  0x3E,  0x7F,  0xA2,  0x2A,  0xA2,  0x2A,  0xBE,  0x35,  0xA9,  0x3F,  0xAA,  0x2A, 	/* 56DD0 */
+	0xAC,  0x2A,  0xA8,  0x35,  0xA4,  0x20,  0xAC,  0x3F,  0xB2,  0x00,  0x61,  0xA7,  0x04,  0x00,  0x3F,  0x7E, 	/* 56DE0 */
+	0x04,  0x12,  0x3F,  0x12,  0x04,  0x22,  0x07,  0x4C,  0x7C,  0xFC,  0x04,  0x80,  0x7F,  0xFF,  0x12,  0x24, 	/* 56DF0 */
+	0x15,  0x54,  0x1F,  0xFC,  0x12,  0x24,  0x15,  0x54,  0x1F,  0xFC,  0x00,  0x00,  0xAA,  0x04,  0x00,  0x14, 	/* 56E00 */
+	0x3E,  0x17,  0xA2,  0x14,  0x22,  0x14,  0x22,  0x7F,  0xE2,  0x2A,  0xBE,  0x2A,  0x88,  0x35,  0xA8,  0x3F, 	/* 56E10 */
+	0xA8,  0x2A,  0xAF,  0x2A,  0xA8,  0x35,  0xA8,  0x20,  0xB8,  0x3F,  0xC8,  0x00,  0x87,  0xAC,  0x04,  0x00, 	/* 56E20 */
+	0x14,  0x7F,  0x17,  0x88,  0x14,  0x08,  0x14,  0x3E,  0x7F,  0xD2,  0x2A,  0x92,  0x2A,  0x92,  0x35,  0xFF, 	/* 56E30 */
+	0x3F,  0x80,  0x2A,  0xBE,  0x2A,  0xA2,  0x35,  0xA2,  0x20,  0xA2,  0x3F,  0xBE,  0x00,  0x00,  0xB2,  0x04, 	/* 56E40 */
+	0x04,  0x14,  0x78,  0x17,  0x90,  0x14,  0x7E,  0x14,  0x52,  0x7F,  0xD2,  0x2B,  0x7E,  0x2B,  0x10,  0x35, 	/* 56E50 */
+	0x7E,  0x3F,  0x52,  0x2B,  0x52,  0x2B,  0x6A,  0x35,  0x7E,  0x21,  0x42,  0x3F,  0x42,  0x00,  0x46,  0xB6, 	/* 56E60 */
+	0x04,  0x00,  0x14,  0x77,  0x17,  0xD5,  0x14,  0x55,  0x14,  0x77,  0x7F,  0xC0,  0x2A,  0xBE,  0x2A,  0x80, 	/* 56E70 */
+	0x35,  0xFF,  0x3F,  0x88,  0x2A,  0x88,  0x2A,  0x9E,  0x35,  0x92,  0x20,  0x82,  0x3F,  0x82,  0x00,  0x0C, 	/* 56E80 */
+	0xB7,  0x04,  0x00,  0x14,  0x7E,  0x17,  0x42,  0x14,  0x42,  0x14,  0x7E,  0x7F,  0xC0,  0x2B,  0x7F,  0x2B, 	/* 56E90 */
+	0x48,  0x35,  0x56,  0x3F,  0x7D,  0x2B,  0x48,  0x2B,  0x7E,  0x35,  0x48,  0x21,  0x88,  0x3F,  0xBF,  0x01, 	/* 56EA0 */
+	0x00,  0x8D,  0x04,  0x20,  0x04,  0x20,  0x3F,  0xBF,  0x11,  0x20,  0x0A,  0x3E,  0x7F,  0xC2,  0x00,  0x3E, 	/* 56EB0 */
+	0x1F,  0x20,  0x11,  0x3E,  0x1F,  0x20,  0x11,  0x3E,  0x1F,  0x20,  0x11,  0x3E,  0x11,  0x21,  0x11,  0x11, 	/* 56EC0 */
+	0x13,  0x0F,  0x95,  0x00,  0x80,  0x01,  0x40,  0x06,  0x30,  0x1F,  0xFC,  0x68,  0x0B,  0x0F,  0xF8,  0x04, 	/* 56ED0 */
+	0x20,  0x3F,  0xBF,  0x12,  0x20,  0x7F,  0xFE,  0x11,  0x02,  0x1F,  0x3E,  0x11,  0x20,  0x1F,  0x3E,  0x11, 	/* 56EE0 */
+	0x21,  0x13,  0x1F,  0x9C,  0x02,  0x00,  0x0F,  0xE0,  0x70,  0x40,  0x0F,  0xF8,  0x09,  0x48,  0x0F,  0x78, 	/* 56EF0 */
+	0x3D,  0x40,  0x7F,  0xFE,  0x05,  0x4A,  0x3D,  0x6A,  0x01,  0x52,  0x3D,  0x6A,  0x7F,  0xFE,  0x05,  0x01, 	/* 56F00 */
+	0x3D,  0x01,  0x00,  0xFF,  0x9D,  0x04,  0x40,  0x18,  0xF8,  0x71,  0x10,  0x17,  0xFC,  0x12,  0x54,  0x7B, 	/* 56F10 */
+	0xDC,  0x17,  0x50,  0x17,  0xFE,  0x39,  0x5A,  0x37,  0x56,  0x30,  0x5A,  0x57,  0x56,  0x57,  0xFE,  0x11, 	/* 56F20 */
+	0x41,  0x17,  0x41,  0x10,  0x3F,  0xA0,  0x00,  0x80,  0x01,  0x40,  0x02,  0x20,  0x0F,  0xF8,  0x70,  0x07, 	/* 56F30 */
+	0x1D,  0xEE,  0x15,  0x2A,  0x1D,  0xEE,  0x00,  0x00,  0x0F,  0xFC,  0x09,  0x24,  0x09,  0x24,  0x0F,  0xFC, 	/* 56F40 */
+	0x09,  0x24,  0x09,  0x24,  0x09,  0x2C,  0x81,  0x00,  0x00,  0x01,  0x80,  0x01,  0x80,  0x01,  0x80,  0x01, 	/* 56F50 */
+	0x80,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x00,  0x00,  0x00, 	/* 56F60 */
+	0x00,  0x01,  0x00,  0x01,  0x00,  0x00,  0x00,  0x83,  0x02,  0x10,  0x02,  0x10,  0x02,  0x10,  0x02,  0x10, 	/* 56F70 */
+	0x1F,  0xFC,  0x1F,  0xFC,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x3F,  0xF8,  0x3F,  0xF8, 	/* 56F80 */
+	0x08,  0x40,  0x08,  0x40,  0x08,  0x40,  0x08,  0x40,  0x84,  0x00,  0x00,  0x02,  0x80,  0x07,  0xC0,  0x0A, 	/* 56F90 */
+	0xA0,  0x12,  0x90,  0x12,  0x90,  0x0A,  0x80,  0x07,  0x80,  0x02,  0xE0,  0x02,  0x90,  0x12,  0x88,  0x12, 	/* 56FA0 */
+	0x88,  0x0A,  0x90,  0x07,  0xE0,  0x02,  0x80,  0x00,  0x00,  0x85,  0x00,  0x00,  0x38,  0x02,  0x64,  0x04, 	/* 56FB0 */
+	0x44,  0x08,  0x44,  0x10,  0x44,  0x20,  0x4C,  0x40,  0x38,  0x80,  0x01,  0x38,  0x02,  0x64,  0x04,  0x44, 	/* 56FC0 */
+	0x08,  0x44,  0x10,  0x44,  0x20,  0x4C,  0x40,  0x38,  0x00,  0x00,  0x86,  0x00,  0x00,  0x0F,  0x00,  0x10, 	/* 56FD0 */
+	0x80,  0x10,  0x80,  0x10,  0x80,  0x09,  0x00,  0x06,  0x10,  0x04,  0x10,  0x0A,  0x10,  0x11,  0x20,  0x20, 	/* 56FE0 */
+	0xA0,  0x20,  0x40,  0x20,  0xA0,  0x11,  0x12,  0x0E,  0x0C,  0x00,  0x00,  0x88,  0x00,  0x00,  0x00,  0x08, 	/* 56FF0 */
+	0x00,  0x10,  0x00,  0x20,  0x00,  0x40,  0x00,  0x40,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80, 	/* 57000 */
+	0x00,  0x80,  0x00,  0x40,  0x00,  0x40,  0x00,  0x20,  0x00,  0x10,  0x00,  0x08,  0x89,  0x00,  0x00,  0x10, 	/* 57010 */
+	0x00,  0x08,  0x00,  0x04,  0x00,  0x02,  0x00,  0x02,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01, 	/* 57020 */
+	0x00,  0x01,  0x00,  0x02,  0x00,  0x02,  0x00,  0x04,  0x00,  0x08,  0x00,  0x10,  0x00,  0x8A,  0x00,  0x00, 	/* 57030 */
+	0x00,  0x00,  0x00,  0x00,  0x01,  0x00,  0x01,  0x00,  0x19,  0x30,  0x0D,  0x60,  0x03,  0x80,  0x01,  0x00, 	/* 57040 */
+	0x03,  0x80,  0x0D,  0x60,  0x19,  0x30,  0x01,  0x00,  0x01,  0x00,  0x00,  0x00,  0x00,  0x00,  0x8B,  0x00, 	/* 57050 */
+	0x00,  0x00,  0x00,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x1F,  0xFC,  0x00, 	/* 57060 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x00,  0x00,  0x00,  0x8C, 	/* 57070 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 57080 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x60,  0x00,  0x60,  0x00,  0x20,  0x00,  0x40,  0x00, 	/* 57090 */
+	0x8D,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x3F, 	/* 570A0 */
+	0xFC,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 570B0 */
+	0x00,  0x8E,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 570C0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x60,  0x00,  0x60,  0x00,  0x00,  0x00, 	/* 570D0 */
+	0x00,  0x00,  0x8F,  0x00,  0x01,  0x00,  0x02,  0x00,  0x04,  0x00,  0x08,  0x00,  0x10,  0x00,  0x20,  0x00, 	/* 570E0 */
+	0x40,  0x00,  0x80,  0x01,  0x00,  0x02,  0x00,  0x04,  0x00,  0x08,  0x00,  0x10,  0x00,  0x20,  0x00,  0x40, 	/* 570F0 */
+	0x00,  0x80,  0x00,  0x90,  0x00,  0x00,  0x03,  0xC0,  0x04,  0x20,  0x08,  0x10,  0x08,  0x10,  0x10,  0x08, 	/* 57100 */
+	0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x08,  0x10,  0x08,  0x10,  0x04,  0x20, 	/* 57110 */
+	0x03,  0xC0,  0x00,  0x00,  0x91,  0x00,  0x00,  0x00,  0x80,  0x00,  0x80,  0x01,  0x80,  0x02,  0x80,  0x00, 	/* 57120 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 57130 */
+	0x80,  0x01,  0xC0,  0x00,  0x00,  0x92,  0x00,  0x00,  0x03,  0xE0,  0x04,  0x10,  0x08,  0x08,  0x08,  0x08, 	/* 57140 */
+	0x00,  0x08,  0x00,  0x10,  0x00,  0x20,  0x00,  0x40,  0x00,  0x80,  0x01,  0x00,  0x02,  0x00,  0x04,  0x00, 	/* 57150 */
+	0x04,  0x00,  0x0F,  0xF8,  0x00,  0x00,  0x93,  0x00,  0x00,  0x03,  0xC0,  0x0C,  0x20,  0x10,  0x10,  0x00, 	/* 57160 */
+	0x10,  0x00,  0x20,  0x00,  0x40,  0x03,  0xE0,  0x00,  0x10,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x10, 	/* 57170 */
+	0x10,  0x0C,  0x60,  0x03,  0x80,  0x00,  0x00,  0x94,  0x00,  0x00,  0x00,  0x20,  0x00,  0x20,  0x00,  0x60, 	/* 57180 */
+	0x00,  0xA0,  0x01,  0x20,  0x02,  0x20,  0x04,  0x20,  0x08,  0x20,  0x10,  0x20,  0x1F,  0xFC,  0x00,  0x20, 	/* 57190 */
+	0x00,  0x20,  0x00,  0x20,  0x00,  0x70,  0x00,  0x00,  0x95,  0x00,  0x00,  0x0F,  0xF8,  0x08,  0x00,  0x08, 	/* 571A0 */
+	0x00,  0x08,  0x00,  0x08,  0x00,  0x0B,  0xE0,  0x0C,  0x10,  0x08,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00, 	/* 571B0 */
+	0x08,  0x00,  0x10,  0x0C,  0x60,  0x03,  0x80,  0x00,  0x00,  0x96,  0x00,  0x00,  0x00,  0xE0,  0x03,  0x00, 	/* 571C0 */
+	0x04,  0x00,  0x08,  0x00,  0x08,  0x00,  0x13,  0xC0,  0x14,  0x20,  0x18,  0x10,  0x10,  0x08,  0x10,  0x08, 	/* 571D0 */
+	0x10,  0x08,  0x08,  0x10,  0x04,  0x20,  0x03,  0xC0,  0x00,  0x00,  0x97,  0x00,  0x00,  0x1F,  0xF8,  0x10, 	/* 571E0 */
+	0x08,  0x10,  0x10,  0x10,  0x10,  0x00,  0x20,  0x00,  0x20,  0x00,  0x40,  0x00,  0x40,  0x00,  0x80,  0x00, 	/* 571F0 */
+	0x80,  0x00,  0x80,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x00,  0x00,  0x98,  0x00,  0x00,  0x03,  0xC0, 	/* 57200 */
+	0x0C,  0x30,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x0C,  0x30,  0x03,  0xC0,  0x04,  0x20,  0x08,  0x10, 	/* 57210 */
+	0x10,  0x08,  0x10,  0x08,  0x18,  0x18,  0x0C,  0x30,  0x03,  0xC0,  0x00,  0x00,  0x99,  0x00,  0x00,  0x03, 	/* 57220 */
+	0xC0,  0x04,  0x20,  0x08,  0x10,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x08,  0x18,  0x04,  0x28,  0x03, 	/* 57230 */
+	0xC8,  0x00,  0x10,  0x00,  0x10,  0x00,  0x20,  0x00,  0xC0,  0x07,  0x00,  0x00,  0x00,  0x9A,  0x00,  0x00, 	/* 57240 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x01,  0x80,  0x01,  0x80,  0x00,  0x00,  0x00,  0x00, 	/* 57250 */
+	0x00,  0x00,  0x00,  0x00,  0x01,  0x80,  0x01,  0x80,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x9B,  0x00, 	/* 57260 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x01,  0x80,  0x01,  0x80,  0x00,  0x00,  0x00, 	/* 57270 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x01,  0x80,  0x01,  0x80,  0x00,  0x80,  0x01,  0x00,  0x00,  0x00,  0x9C, 	/* 57280 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x18,  0x00,  0x60,  0x01,  0x80,  0x02,  0x00,  0x0C,  0x00,  0x30,  0x00, 	/* 57290 */
+	0x0C,  0x00,  0x02,  0x00,  0x01,  0x80,  0x00,  0x60,  0x00,  0x18,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 572A0 */
+	0x9D,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x00,  0x00, 	/* 572B0 */
+	0x00,  0x00,  0x00,  0x3F,  0xFC,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 572C0 */
+	0x00,  0x9E,  0x00,  0x00,  0x00,  0x00,  0x18,  0x00,  0x06,  0x00,  0x01,  0x80,  0x00,  0x40,  0x00,  0x30, 	/* 572D0 */
+	0x00,  0x0C,  0x00,  0x30,  0x00,  0x40,  0x01,  0x80,  0x06,  0x00,  0x18,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 572E0 */
+	0x00,  0x00,  0x9F,  0x00,  0x00,  0x03,  0xC0,  0x04,  0x20,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x04, 	/* 572F0 */
+	0x20,  0x00,  0x40,  0x00,  0x80,  0x01,  0x00,  0x01,  0x00,  0x00,  0x00,  0x00,  0x00,  0x01,  0x00,  0x01, 	/* 57300 */
+	0x00,  0x00,  0x00,  0xA0,  0x00,  0x00,  0x00,  0x00,  0x03,  0xC0,  0x0C,  0x30,  0x10,  0x08,  0x11,  0xA8, 	/* 57310 */
+	0x22,  0x64,  0x24,  0x44,  0x24,  0x44,  0x24,  0xE8,  0x13,  0x70,  0x10,  0x04,  0x0C,  0x18,  0x03,  0xE0, 	/* 57320 */
+	0x00,  0x00,  0x00,  0x00,  0xA1,  0x00,  0x00,  0x00,  0x80,  0x00,  0x80,  0x01,  0x40,  0x01,  0x40,  0x02, 	/* 57330 */
+	0x20,  0x02,  0x20,  0x04,  0x10,  0x07,  0xF0,  0x04,  0x10,  0x08,  0x08,  0x08,  0x08,  0x10,  0x04,  0x38, 	/* 57340 */
+	0x0E,  0x00,  0x00,  0x00,  0x00,  0xA2,  0x00,  0x00,  0x3F,  0xE0,  0x08,  0x10,  0x08,  0x08,  0x08,  0x08, 	/* 57350 */
+	0x08,  0x10,  0x0F,  0xE0,  0x08,  0x10,  0x08,  0x08,  0x08,  0x04,  0x08,  0x04,  0x08,  0x08,  0x08,  0x30, 	/* 57360 */
+	0x3F,  0xC0,  0x00,  0x00,  0x00,  0x00,  0xA3,  0x00,  0x00,  0x03,  0xC8,  0x0C,  0x28,  0x18,  0x18,  0x10, 	/* 57370 */
+	0x08,  0x20,  0x08,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x10,  0x08,  0x18,  0x18,  0x0C, 	/* 57380 */
+	0x30,  0x03,  0xC0,  0x00,  0x00,  0x00,  0x00,  0xA4,  0x00,  0x00,  0x3F,  0x80,  0x08,  0x60,  0x08,  0x10, 	/* 57390 */
+	0x08,  0x08,  0x08,  0x08,  0x08,  0x04,  0x08,  0x04,  0x08,  0x04,  0x08,  0x08,  0x08,  0x08,  0x08,  0x10, 	/* 573A0 */
+	0x08,  0x60,  0x3F,  0x80,  0x00,  0x00,  0x00,  0x00,  0xA5,  0x00,  0x00,  0x3F,  0xF8,  0x08,  0x08,  0x08, 	/* 573B0 */
+	0x04,  0x08,  0x00,  0x08,  0x00,  0x08,  0x40,  0x0F,  0xC0,  0x08,  0x40,  0x08,  0x00,  0x08,  0x00,  0x08, 	/* 573C0 */
+	0x04,  0x08,  0x08,  0x3F,  0xF8,  0x00,  0x00,  0x00,  0x00,  0xA6,  0x00,  0x00,  0x1F,  0xF8,  0x04,  0x08, 	/* 573D0 */
+	0x04,  0x04,  0x04,  0x00,  0x04,  0x00,  0x04,  0x20,  0x07,  0xE0,  0x04,  0x20,  0x04,  0x00,  0x04,  0x00, 	/* 573E0 */
+	0x04,  0x00,  0x04,  0x00,  0x1F,  0x00,  0x00,  0x00,  0x00,  0x00,  0xA7,  0x00,  0x00,  0x03,  0xC8,  0x0C, 	/* 573F0 */
+	0x38,  0x18,  0x08,  0x10,  0x08,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x3E,  0x20,  0x08,  0x10, 	/* 57400 */
+	0x08,  0x18,  0x18,  0x0C,  0x68,  0x03,  0x88,  0x00,  0x00,  0x00,  0x00,  0xA8,  0x00,  0x00,  0x38,  0x1C, 	/* 57410 */
+	0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x1F,  0xF8,  0x10,  0x08,  0x10,  0x08, 	/* 57420 */
+	0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x38,  0x1C,  0x00,  0x00,  0x00,  0x00,  0xA9,  0x00,  0x00,  0x03, 	/* 57430 */
+	0x80,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01, 	/* 57440 */
+	0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x03,  0x80,  0x00,  0x00,  0x00,  0x00,  0xAA,  0x00,  0x00, 	/* 57450 */
+	0x00,  0x70,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20, 	/* 57460 */
+	0x00,  0x20,  0x00,  0x20,  0x08,  0x20,  0x04,  0x40,  0x03,  0x80,  0x00,  0x00,  0x00,  0x00,  0xAB,  0x00, 	/* 57470 */
+	0x00,  0x1C,  0x1C,  0x08,  0x10,  0x08,  0x20,  0x08,  0x40,  0x08,  0x80,  0x09,  0x00,  0x0B,  0x00,  0x0C, 	/* 57480 */
+	0x80,  0x08,  0x40,  0x08,  0x20,  0x08,  0x10,  0x08,  0x08,  0x1C,  0x0E,  0x00,  0x00,  0x00,  0x00,  0xAC, 	/* 57490 */
+	0x00,  0x00,  0x0E,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00, 	/* 574A0 */
+	0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x04,  0x04,  0x04,  0x0F,  0xFC,  0x00,  0x00,  0x00,  0x00, 	/* 574B0 */
+	0xAD,  0x00,  0x00,  0x60,  0x0C,  0x20,  0x08,  0x30,  0x18,  0x30,  0x18,  0x28,  0x28,  0x28,  0x28,  0x24, 	/* 574C0 */
+	0x48,  0x24,  0x48,  0x24,  0x48,  0x22,  0x88,  0x22,  0x88,  0x21,  0x08,  0x71,  0x1C,  0x00,  0x00,  0x00, 	/* 574D0 */
+	0x00,  0xAE,  0x00,  0x00,  0x38,  0x1C,  0x18,  0x08,  0x14,  0x08,  0x14,  0x08,  0x12,  0x08,  0x11,  0x08, 	/* 574E0 */
+	0x11,  0x08,  0x10,  0x88,  0x10,  0x48,  0x10,  0x48,  0x10,  0x28,  0x10,  0x18,  0x38,  0x08,  0x00,  0x00, 	/* 574F0 */
+	0x00,  0x00,  0xAF,  0x00,  0x00,  0x03,  0xC0,  0x0C,  0x30,  0x18,  0x18,  0x10,  0x08,  0x20,  0x04,  0x20, 	/* 57500 */
+	0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x10,  0x08,  0x18,  0x18,  0x0C,  0x30,  0x03,  0xC0,  0x00, 	/* 57510 */
+	0x00,  0x00,  0x00,  0xB0,  0x00,  0x00,  0x1F,  0xE0,  0x04,  0x18,  0x04,  0x04,  0x04,  0x04,  0x04,  0x04, 	/* 57520 */
+	0x04,  0x18,  0x07,  0xE0,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x0E,  0x00, 	/* 57530 */
+	0x00,  0x00,  0x00,  0x00,  0xB1,  0x00,  0x00,  0x03,  0xC0,  0x0C,  0x30,  0x18,  0x18,  0x10,  0x08,  0x20, 	/* 57540 */
+	0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x20,  0x04,  0x11,  0x88,  0x1A,  0x50,  0x0C,  0x20,  0x03, 	/* 57550 */
+	0xD2,  0x00,  0x0C,  0x00,  0x00,  0xB2,  0x00,  0x00,  0x3F,  0xC0,  0x08,  0x30,  0x08,  0x08,  0x08,  0x08, 	/* 57560 */
+	0x08,  0x08,  0x08,  0x30,  0x0F,  0xC0,  0x08,  0x20,  0x08,  0x20,  0x08,  0x10,  0x08,  0x10,  0x08,  0x08, 	/* 57570 */
+	0x1C,  0x1C,  0x00,  0x00,  0x00,  0x00,  0xB3,  0x00,  0x00,  0x03,  0xD0,  0x04,  0x30,  0x08,  0x10,  0x08, 	/* 57580 */
+	0x00,  0x08,  0x00,  0x04,  0x00,  0x03,  0xC0,  0x00,  0x30,  0x00,  0x08,  0x10,  0x08,  0x18,  0x08,  0x14, 	/* 57590 */
+	0x10,  0x03,  0xE0,  0x00,  0x00,  0x00,  0x00,  0xB4,  0x00,  0x00,  0x3F,  0xF8,  0x21,  0x08,  0x41,  0x04, 	/* 575A0 */
+	0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 575B0 */
+	0x01,  0x00,  0x03,  0x80,  0x00,  0x00,  0x00,  0x00,  0xB5,  0x00,  0x00,  0x38,  0x1C,  0x10,  0x08,  0x10, 	/* 575C0 */
+	0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x08, 	/* 575D0 */
+	0x10,  0x04,  0x20,  0x03,  0xC0,  0x00,  0x00,  0x00,  0x00,  0xB6,  0x00,  0x00,  0x38,  0x1C,  0x10,  0x08, 	/* 575E0 */
+	0x10,  0x08,  0x08,  0x10,  0x08,  0x10,  0x08,  0x20,  0x04,  0x20,  0x04,  0x40,  0x04,  0x40,  0x02,  0x80, 	/* 575F0 */
+	0x02,  0x80,  0x01,  0x00,  0x01,  0x00,  0x00,  0x00,  0x00,  0x00,  0xB7,  0x00,  0x00,  0x71,  0x8E,  0x21, 	/* 57600 */
+	0x84,  0x21,  0x84,  0x21,  0x84,  0x22,  0x44,  0x12,  0x48,  0x12,  0x48,  0x14,  0x28,  0x14,  0x28,  0x0C, 	/* 57610 */
+	0x28,  0x0C,  0x30,  0x08,  0x10,  0x08,  0x10,  0x00,  0x00,  0x00,  0x00,  0xB8,  0x00,  0x00,  0x38,  0x38, 	/* 57620 */
+	0x10,  0x10,  0x08,  0x20,  0x04,  0x40,  0x04,  0x40,  0x02,  0x80,  0x01,  0x00,  0x02,  0x80,  0x04,  0x40, 	/* 57630 */
+	0x04,  0x40,  0x08,  0x20,  0x10,  0x10,  0x38,  0x38,  0x00,  0x00,  0x00,  0x00,  0xB9,  0x00,  0x00,  0x38, 	/* 57640 */
+	0x38,  0x10,  0x10,  0x08,  0x20,  0x08,  0x20,  0x04,  0x40,  0x04,  0x40,  0x02,  0x80,  0x01,  0x00,  0x01, 	/* 57650 */
+	0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x03,  0x80,  0x00,  0x00,  0x00,  0x00,  0xBA,  0x00,  0x00, 	/* 57660 */
+	0x0F,  0xF8,  0x08,  0x10,  0x10,  0x20,  0x00,  0x40,  0x00,  0x40,  0x00,  0x80,  0x01,  0x00,  0x01,  0x00, 	/* 57670 */
+	0x02,  0x00,  0x04,  0x00,  0x04,  0x08,  0x08,  0x08,  0x1F,  0xF8,  0x00,  0x00,  0x00,  0x00,  0xBB,  0x00, 	/* 57680 */
+	0xF8,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 57690 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0xF8,  0xBC, 	/* 576A0 */
+	0x80,  0x00,  0x40,  0x00,  0x20,  0x00,  0x10,  0x00,  0x08,  0x00,  0x04,  0x00,  0x02,  0x00,  0x01,  0x00, 	/* 576B0 */
+	0x00,  0x80,  0x00,  0x40,  0x00,  0x20,  0x00,  0x10,  0x00,  0x08,  0x00,  0x04,  0x00,  0x02,  0x00,  0x01, 	/* 576C0 */
+	0xBD,  0x1F,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01, 	/* 576D0 */
+	0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x1F, 	/* 576E0 */
+	0x00,  0xBE,  0x01,  0x00,  0x02,  0x80,  0x04,  0x40,  0x08,  0x20,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 576F0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 57700 */
+	0x00,  0x00,  0xBF,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 57710 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 57720 */
+	0x00,  0xFF,  0xFF,  0x80,  0x02,  0x00,  0x02,  0x00,  0x01,  0x00,  0x00,  0x80,  0x00,  0x00,  0x00,  0x00, 	/* 57730 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 57740 */
+	0x00,  0x00,  0x00,  0x00,  0x81,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x03, 	/* 57750 */
+	0xC0,  0x04,  0x20,  0x00,  0x20,  0x03,  0xA0,  0x04,  0x60,  0x08,  0x20,  0x08,  0x60,  0x08,  0xA8,  0x07, 	/* 57760 */
+	0x18,  0x00,  0x00,  0x00,  0x00,  0x82,  0x00,  0x00,  0x0C,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00, 	/* 57770 */
+	0x04,  0x00,  0x05,  0xC0,  0x06,  0x20,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x06,  0x20, 	/* 57780 */
+	0x05,  0xC0,  0x00,  0x00,  0x00,  0x00,  0x83,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 57790 */
+	0x00,  0x03,  0x80,  0x04,  0x40,  0x08,  0x20,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x20,  0x04, 	/* 577A0 */
+	0x40,  0x03,  0x80,  0x00,  0x00,  0x00,  0x00,  0x84,  0x00,  0x00,  0x00,  0x60,  0x00,  0x20,  0x00,  0x20, 	/* 577B0 */
+	0x00,  0x20,  0x00,  0x20,  0x03,  0xA0,  0x04,  0x60,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20, 	/* 577C0 */
+	0x04,  0x60,  0x03,  0xB0,  0x00,  0x00,  0x00,  0x00,  0x85,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 577D0 */
+	0x00,  0x00,  0x00,  0x03,  0x80,  0x04,  0x40,  0x08,  0x20,  0x08,  0x20,  0x0F,  0xE0,  0x08,  0x00,  0x08, 	/* 577E0 */
+	0x00,  0x04,  0x20,  0x03,  0xC0,  0x00,  0x00,  0x00,  0x00,  0x86,  0x00,  0x00,  0x00,  0xF0,  0x01,  0x90, 	/* 577F0 */
+	0x01,  0x00,  0x01,  0x00,  0x0F,  0xF0,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 57800 */
+	0x01,  0x00,  0x01,  0x00,  0x03,  0x80,  0x00,  0x00,  0x00,  0x00,  0x87,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 57810 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x03,  0xD0,  0x06,  0x20,  0x04,  0x20,  0x04,  0x20,  0x03,  0xC0,  0x04, 	/* 57820 */
+	0x00,  0x07,  0xE0,  0x08,  0x18,  0x08,  0x08,  0x04,  0x18,  0x03,  0xE0,  0x88,  0x00,  0x00,  0x0C,  0x00, 	/* 57830 */
+	0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x05,  0xC0,  0x06,  0x20,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10, 	/* 57840 */
+	0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x0E,  0x38,  0x00,  0x00,  0x00,  0x00,  0x89,  0x00,  0x00,  0x01, 	/* 57850 */
+	0x80,  0x01,  0x80,  0x00,  0x00,  0x00,  0x00,  0x01,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 57860 */
+	0x80,  0x00,  0x80,  0x00,  0x80,  0x00,  0x80,  0x01,  0xC0,  0x00,  0x00,  0x00,  0x00,  0x8A,  0x00,  0x00, 	/* 57870 */
+	0x00,  0xC0,  0x00,  0xC0,  0x00,  0x00,  0x00,  0x00,  0x00,  0xC0,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40, 	/* 57880 */
+	0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0x00,  0x40,  0x08,  0x80,  0x07,  0x00,  0x8B,  0x00, 	/* 57890 */
+	0x00,  0x18,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x00,  0x08,  0x70,  0x08,  0x40,  0x09,  0x80,  0x0E, 	/* 578A0 */
+	0x00,  0x09,  0x00,  0x08,  0x80,  0x08,  0x40,  0x08,  0x20,  0x1C,  0x78,  0x00,  0x00,  0x00,  0x00,  0x8C, 	/* 578B0 */
+	0x00,  0x00,  0x03,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 578C0 */
+	0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x03,  0x80,  0x00,  0x00,  0x00,  0x00, 	/* 578D0 */
+	0x8D,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x17,  0x30,  0x09,  0xC8,  0x08, 	/* 578E0 */
+	0x88,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x08,  0x88,  0x1D,  0xDC,  0x00,  0x00,  0x00, 	/* 578F0 */
+	0x00,  0x8E,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0C,  0xE0,  0x05,  0x30, 	/* 57900 */
+	0x06,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x0E,  0x38,  0x00,  0x00, 	/* 57910 */
+	0x00,  0x00,  0x8F,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x03,  0xC0,  0x04, 	/* 57920 */
+	0x20,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x08,  0x10,  0x04,  0x20,  0x03,  0xC0,  0x00, 	/* 57930 */
+	0x00,  0x00,  0x00,  0x90,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0D,  0xC0, 	/* 57940 */
+	0x06,  0x20,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x06,  0x20,  0x05,  0xC0,  0x04,  0x00, 	/* 57950 */
+	0x04,  0x00,  0x0E,  0x00,  0x91,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x03, 	/* 57960 */
+	0xB0,  0x04,  0x60,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x08,  0x20,  0x04,  0x60,  0x03,  0xA0,  0x00, 	/* 57970 */
+	0x20,  0x00,  0x20,  0x00,  0x70,  0x92,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 57980 */
+	0x06,  0x70,  0x02,  0x90,  0x03,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00, 	/* 57990 */
+	0x07,  0x00,  0x00,  0x00,  0x00,  0x00,  0x93,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 579A0 */
+	0x00,  0x03,  0xD0,  0x04,  0x30,  0x04,  0x10,  0x03,  0x00,  0x00,  0xC0,  0x00,  0x20,  0x04,  0x10,  0x06, 	/* 579B0 */
+	0x10,  0x05,  0xE0,  0x00,  0x00,  0x00,  0x00,  0x94,  0x00,  0x00,  0x00,  0x00,  0x02,  0x00,  0x02,  0x00, 	/* 579C0 */
+	0x02,  0x00,  0x1F,  0xE0,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00,  0x02,  0x00, 	/* 579D0 */
+	0x03,  0x40,  0x01,  0xC0,  0x00,  0x00,  0x00,  0x00,  0x95,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 579E0 */
+	0x00,  0x00,  0x00,  0x0C,  0x30,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04,  0x10,  0x04, 	/* 579F0 */
+	0x10,  0x02,  0x30,  0x01,  0xD8,  0x00,  0x00,  0x00,  0x00,  0x96,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 57A00 */
+	0x00,  0x00,  0x00,  0x00,  0x1C,  0x70,  0x08,  0x20,  0x08,  0x20,  0x04,  0x40,  0x04,  0x40,  0x02,  0x80, 	/* 57A10 */
+	0x02,  0x80,  0x01,  0x00,  0x01,  0x00,  0x00,  0x00,  0x00,  0x00,  0x97,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 57A20 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x39,  0x1C,  0x11,  0x08,  0x11,  0x88,  0x11,  0x88,  0x0A,  0x50,  0x0A, 	/* 57A30 */
+	0x50,  0x0A,  0x50,  0x04,  0x20,  0x04,  0x20,  0x00,  0x00,  0x00,  0x00,  0x98,  0x00,  0x00,  0x00,  0x00, 	/* 57A40 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0C,  0x30,  0x04,  0x20,  0x02,  0x40,  0x01,  0x80,  0x01,  0x80, 	/* 57A50 */
+	0x02,  0x40,  0x04,  0x20,  0x08,  0x10,  0x1C,  0x38,  0x00,  0x00,  0x00,  0x00,  0x99,  0x00,  0x00,  0x00, 	/* 57A60 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0E,  0x38,  0x04,  0x10,  0x04,  0x10,  0x02,  0x20,  0x02, 	/* 57A70 */
+	0x20,  0x01,  0x40,  0x01,  0x40,  0x00,  0x80,  0x00,  0x80,  0x09,  0x00,  0x06,  0x00,  0x9A,  0x00,  0x00, 	/* 57A80 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x0F,  0xF0,  0x08,  0x20,  0x00,  0x40,  0x00,  0x80, 	/* 57A90 */
+	0x00,  0x80,  0x01,  0x00,  0x02,  0x10,  0x04,  0x10,  0x0F,  0xF0,  0x00,  0x00,  0x00,  0x00,  0x9B,  0x00, 	/* 57AA0 */
+	0x08,  0x00,  0x10,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0xC0,  0x00, 	/* 57AB0 */
+	0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x20,  0x00,  0x10,  0x00,  0x08,  0x9C, 	/* 57AC0 */
+	0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 57AD0 */
+	0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 57AE0 */
+	0x9D,  0x10,  0x00,  0x08,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x03, 	/* 57AF0 */
+	0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x08,  0x00,  0x10, 	/* 57B00 */
+	0x00,  0x9E,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x1C,  0x00, 	/* 57B10 */
+	0x23,  0x02,  0x40,  0xC4,  0x00,  0x38,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 57B20 */
+	0x00,  0x00,  0xA0,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x20,  0x03, 	/* 57B30 */
+	0xC0,  0x04,  0x60,  0x08,  0x50,  0x08,  0x80,  0x08,  0x80,  0x09,  0x10,  0x05,  0x20,  0x03,  0xC0,  0x02, 	/* 57B40 */
+	0x00,  0x04,  0x00,  0xA1,  0x00,  0x00,  0x00,  0xE0,  0x01,  0x10,  0x01,  0x00,  0x01,  0x00,  0x01,  0x00, 	/* 57B50 */
+	0x01,  0x00,  0x01,  0x00,  0x3F,  0xF8,  0x01,  0x00,  0x01,  0x00,  0x1E,  0x00,  0x23,  0x02,  0x22,  0xC4, 	/* 57B60 */
+	0x1C,  0x38,  0x00,  0x00,  0xA2,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 57B70 */
+	0x00,  0x3F,  0xFC,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x04,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 57B80 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0xA3,  0xFF,  0xFF,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 57B90 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 	/* 57BA0 */
+	0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xA5,  0x00,  0x00,  0x1C,  0x1C,  0x08,  0x08,  0x04,  0x10,  0x04, 	/* 57BB0 */
+	0x10,  0x3F,  0xFE,  0x02,  0x20,  0x01,  0x40,  0x00,  0x80,  0x3F,  0xFE,  0x00,  0x80,  0x00,  0x80,  0x00, 	/* 57BC0 */
+	0x80,  0x00,  0x80,  0x01,  0xC0,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00  	/* 57BD0 */
+};
+
+#endif
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/ui/stfont_disp/Makefile.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/ui/stfont_disp/Makefile.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/ui/stfont_disp/Makefile.config	(revision 453)
@@ -0,0 +1,56 @@
+#
+#   TOPPERS/ASP Kernel
+#       Toyohashi Open Platform for Embedded Real-Time Systems/
+#       Advanced Standard Profile Kernel
+#
+#   Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                               Toyohashi Univ. of Technology, JAPAN
+#   Copyright (C) 2003-2008 by Ryosuke Takeuchi
+#                Platform Development Center RICOH COMPANY,LTD. JAPAN
+#   Copyright (C) 2017-2018 by TOPPERS PROJECT Educational Working Group.
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+ 
+#
+#  Makefile のプロセッサ依存 (stfont_disp用)
+#
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/ui/stfont_disp -I$(SRCDIR)/stmcube/Utilities/Fonts
+
+#
+#  プログラムに関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR):$(SRCDIR)/ui/stfont_disp
+SYSSVC_COBJS := $(SYSSVC_COBJS) glcd_disp.o
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/ui/stfont_disp/glcd_disp.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/ui/stfont_disp/glcd_disp.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/ui/stfont_disp/glcd_disp.c	(revision 453)
@@ -0,0 +1,212 @@
+/*
+ *  TOPPERS/ASP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+ *                              Toyohashi Univ. of Technology, JAPAN
+ *  Copyright (C) 2004-2012 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  $Id$
+ */
+
+/* 
+ *  GRAPHIC-LCDテキスト表示プログラムの本体
+ */
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <target_syssvc.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#include "glcd_disp.h"
+#include "font24.c"
+#include "font20.c"
+#include "font16.c"
+#include "font12.c"
+#include "font8.c"
+
+/*
+ *  文字描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x0: 文字描画 X座標始点
+ *  param3  y0: 文字描画 Y座標始点
+ *  param4  c:  文字イメージへのポインタ
+ */
+#ifndef MAX_FONT_IMAGE
+static void
+DrawChar(LCD_DrawProp_t *pDrawProp, uint16_t x0, uint16_t y0, const uint8_t *c)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	sFONT    *pFont = pDrawProp->pFont;
+	uint32_t h, w, stride;
+	uint8_t  *pchar;
+
+	stride = ((pFont->Width + 7)/8);
+	for(h = 0 ; h < pFont->Height ; h++){
+		pchar = ((uint8_t *)c + stride * h);
+		for(w = 0; w < pFont->Width ; w++){
+			if(pchar[w/8] & (1 << (7 - (w % 8)))){
+				lcd_drawPixel(hlcd, (x0 + w), (y0 + h), pDrawProp->TextColor);
+			}
+			else{
+				lcd_drawPixel(hlcd, (x0 + w), (y0 + h), pDrawProp->BackColor);
+			}
+		}
+	}
+}
+#else
+static void
+DrawChar(LCD_DrawProp_t *pDrawProp, uint16_t x0, uint16_t y0, const uint8_t *c)
+{
+	LCD_Handler_t *hlcd = pDrawProp->hlcd;
+	sFONT    *pFont = pDrawProp->pFont;
+	uint32_t h, w, stride;
+	const uint8_t  *pchar;
+	color_t  image[MAX_FONT_IMAGE];
+
+	stride = ((pFont->Width + 7)/8);
+	for(h = 0 ; h < pFont->Height ; h++){
+		pchar = ((uint8_t *)c + stride * h);
+		for(w = 0; w < pFont->Width ; w++){
+			if(pchar[w/8] & (1 << (7 - (w % 8)))){
+				image[w] = pDrawProp->TextColor;
+			}
+			else{
+				image[w] = pDrawProp->BackColor;
+			}
+		}
+		lcd_drawImageHLine(hlcd, x0, (y0 + h), pFont->Width, image);
+	}
+}
+#endif
+
+/*
+ *  文字列表示ラインクリア
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  ライン番号
+ */
+void
+lcd_clearStringLine(LCD_DrawProp_t *pDrawProp, uint16_t Line)
+{
+	sFONT    *pFont = pDrawProp->pFont;
+	lcd_fillRect(pDrawProp->hlcd, 0, (Line * pFont->Height), pDrawProp->hlcd->_width, pFont->Height, pDrawProp->BackColor);
+}
+
+/*
+ *  一文字描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x0: 文字描画 X座標始点
+ *  param3  y0: 文字描画 Y座標始点
+ *  param4  描画アスキーコード(範囲は0x20から0x7Eまで)
+ */
+void
+lcd_DisplayChar(LCD_DrawProp_t *pDrawProp, uint16_t x0, uint16_t y0, uint8_t Ascii)
+{
+	sFONT    *pFont = pDrawProp->pFont;
+	DrawChar(pDrawProp, x0, y0, &pFont->table[(Ascii-' ') * pFont->Height * ((pFont->Width + 7) / 8)]);
+}
+
+/*
+ *  文字列描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param1  x0: 文字列描画 X座標始点
+ *  param2  y0: 文字列描画 Y座標始点
+ *  param3  Text: 描画文字列へのポインタ
+ */
+void
+lcd_DisplayStringAt(LCD_DrawProp_t *pDrawProp, uint16_t x0, uint16_t y0, uint8_t *Text, Line_ModeTypdef Mode)
+{
+	sFONT    *pFont = pDrawProp->pFont;
+	uint16_t ref_column = 1, i = 0;
+	uint32_t size = 0, xsize = 0; 
+	uint8_t  *ptr = (uint8_t *)Text;
+
+	/* Get the text size */
+	while (*ptr++) size++;
+
+	/* Characters number per line */
+	xsize = (pDrawProp->hlcd->_width / pFont->Width);
+
+	switch(Mode){
+	case CENTER_MODE:
+		ref_column = x0 + ((xsize - size) * pFont->Width) / 2;
+		break;
+	case LEFT_MODE:
+		ref_column = x0;
+		break;
+	case RIGHT_MODE:
+		ref_column =  - x0 + ((xsize - size) * pFont->Width);
+		break;
+	default:
+		ref_column = x0;
+		break;
+	}
+
+	/*
+	 *  開始カラム位置をスクリーン内に収める
+	 */
+	if((ref_column < 1) || (ref_column >= 0x8000)){
+		ref_column = 1;
+	}
+
+	/*
+	 *  一文字描画を使って文字列を描画する
+	 */
+	while((*Text != 0) & (((pDrawProp->hlcd->_width - (i*pFont->Width)) & 0xFFFF) >= pFont->Width)){
+		lcd_DisplayChar(pDrawProp, ref_column, y0, *Text);
+		ref_column += pFont->Width;		/* 次のカラムに移動 */
+		Text++;							/* 次の文字に移動 */
+		i++;
+	}
+}
+
+/*
+ *  文字列描画
+ *  param1  pDrawProp: Pointer to Draw Prop
+ *  param2  x0: 文字列描画 X座標始点
+ *  param3  y0: 文字列描画 Y座標始点
+ *  param4  Text: 描画文字列へのポインタ
+ */
+void
+lcd_DisplayStringAtLine(LCD_DrawProp_t *pDrawProp, uint16_t Line, uint8_t *ptr)
+{
+	sFONT    *pFont = pDrawProp->pFont;
+
+	lcd_DisplayStringAt(pDrawProp, 0, Line * pFont->Height, ptr, LEFT_MODE);
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/ui/stfont_disp/glcd_disp.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/ui/stfont_disp/glcd_disp.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/ui/stfont_disp/glcd_disp.h	(revision 453)
@@ -0,0 +1,114 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+#ifndef _GLCD_DISP_H_
+#define _GLCD_DISP_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif 
+
+#include "glcd_core.h"
+#include "fonts.h"
+
+/*
+ *  テキスト表示ラインモード定義
+ */
+typedef enum
+{
+	CENTER_MODE = 0x01,	/* Center mode */
+	RIGHT_MODE,			/* Right mode  */
+	LEFT_MODE			/* Left mode   */
+}Line_ModeTypdef;
+
+
+/*
+ *  BSP表示関数変換定義
+ */
+#define BSP_LCD_Init()                  lcd_init(pHLCD, LCD_ORIENTATION_LANDSCAPE)
+#define BSP_LCD_DeInit()                lcd_deinit(pHLCD)
+#define BSP_LCD_LayerDefaultInit(a, b)  lcd_layerdefaultinit(pHLCD, pDRAWPROP, (a), (b))
+#define BSP_LCD_SetLayerWindow(i, x, y, w, h) lcd_setAddrWindow(pHLCD, (i), (x), (y), (w), (h))
+
+#define BSP_LCD_Clear(c)                lcd_clear(pHLCD, (c))
+#define BSP_LCD_ReadPixel(x, y)         lcd_readPixel(pHLCD, (x), (y))
+#define BSP_LCD_DrawPixel(x, y, c)      lcd_drawPixel(pHLCD, (x), (y), (c))
+#define BSP_LCD_DrawHLine(x, y, w)      lcd_drawFastHLine(pHLCD, (x), (y), (w), pDRAWPROP->TextColor)
+#define BSP_LCD_DrawVLine(x, y, h)      lcd_drawFastVLine(pHLCD, (x), (y), (h), pDRAWPROP->TextColor)
+#define BSP_LCD_DrawBitmap(x, y, p)     lcd_drawBitmap(pHLCD, (x), (y), (p))
+#define BSP_LCD_DrawRGBImage(x, y, xs, ys, p) lcd_drawRGBImage(pHLCD, (x), (y), (xs), (xy), (p))
+#define BSP_LCD_DisplayOn()             lcd_displayOn(pHLCD)
+#define BSP_LCD_DisplayOff()            lcd_displayOff(pHLCD)
+#define BSP_LCD_FillRect(x, y, w,h)     lcd_fillRect(pHLCD, (x), (y), (w), (h), pDRAWPROP->TextColor)
+
+#define BSP_LCD_DrawLine(x, y, x2, y2)  lcd_drawLine(pDRAWPROP, (x), (y), (x2), (y2))
+#define BSP_LCD_DrawRect(x, y, w, h)    lcd_drawRect(pDRAWPROP, (x), (y), (w), (h))
+#define BSP_LCD_DrawCircle(x, y, r)     lcd_DrawCircle(pDRAWPROP, (x), (y), (r))
+#define BSP_LCD_DrawEllipse(x, y, xr, yr) lcd_DrawEllipse(pDRAWPROP, (x), (y), (xr), (yr))
+#define BSP_LCD_DrawPolygon(a, b)       lcd_drawPolygon(pDRAWPROP, (a), (b))
+#define BSP_LCD_FillCircle(x, y, r)     lcd_fillCircle(pDRAWPROP, (x), (y), (r))
+#define BSP_LCD_FillEllipse(x, y, xr, yr) lcd_fillEllipse(pDRAWPROP, (x), (y), (xr), (yr))
+#define BSP_LCD_FillPolygon(a, b)       lcd_fillPolygon(pDRAWPROP, (a), (b))
+
+#define BSP_LCD_ClearStringLine(l)      lcd_clearStringLine(pDRAWPROP, (l))
+#define BSP_LCD_DisplayChar(x, y, a)    lcd_DisplayChar(pDRAWPROP, (x), (y), (a))
+#define BSP_LCD_DisplayStringAt(x, y, t, m) lcd_DisplayStringAt(pDRAWPROP, (x), (y), (t), (m))
+#define BSP_LCD_DisplayStringAtLine(l, p) lcd_DisplayStringAtLine(pDRAWPROP, (l), (p))
+
+#define BSP_LCD_SelectLayer(a)          pHLCD->layer = (a)
+#define BSP_LCD_GetXSize()              pHLCD->_width
+#define BSP_LCD_GetYSize()              pHLCD->_height
+#define BSP_LCD_SetTextColor(c)         pDRAWPROP->TextColor = (c)
+#define BSP_LCD_GetTextColor()          pDRAWPROP->TextColor
+#define BSP_LCD_SetBackColor(c)         pDRAWPROP->BackColor = (c)
+#define BSP_LCD_GetBackColor()          pDRAWPROP->BackColor
+#define BSP_LCD_SetFont(f)              pDRAWPROP->pFont = (f)
+#define BSP_LCD_GetFont()               ((sFONT *)pDRAWPROP->pFont)
+
+
+extern void lcd_clearStringLine(LCD_DrawProp_t *pDrawProp, uint16_t Line);
+extern void lcd_DisplayChar(LCD_DrawProp_t *pDrawProp, uint16_t Xpos, uint16_t Ypos, uint8_t Ascii);
+extern void lcd_DisplayStringAt(LCD_DrawProp_t *pDrawProp, uint16_t Xpos, uint16_t Ypos, uint8_t *Text, Line_ModeTypdef Mode);
+extern void lcd_DisplayStringAtLine(LCD_DrawProp_t *pDrawProp, uint16_t Line, uint8_t *ptr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GLCD_DISP_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/Makefile.config
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/Makefile.config	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/Makefile.config	(revision 453)
@@ -0,0 +1,77 @@
+#
+#   TOPPERS/ASP/FMP Kernel
+#       Toyohashi Open Platform for Embedded Real-Time Systems/
+#       Advanced Standard Profile Kernel
+#
+#   Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                               Toyohashi Univ. of Technology, JAPAN
+#   Copyright (C) 2003-2008 by Ryosuke Takeuchi
+#                Platform Development Center RICOH COMPANY,LTD. JAPAN
+#   Copyright (C) 2015-2018 by TOPPERS PROJECT Educational Working Group.
+#
+#   上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+#   によって公表されている GNU General Public License の Version 2 に記
+#   述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+#   を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+#   利用と呼ぶ）することを無償で許諾する．
+#   (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+#       権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+#       スコード中に含まれていること．
+#   (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+#       用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+#       者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+#       の無保証規定を掲載すること．
+#   (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+#       用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+#       と．
+#     (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+#         作権表示，この利用条件および下記の無保証規定を掲載すること．
+#     (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+#         報告すること．
+#   (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+#       害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+#
+#   本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+#   よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+#   含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+#   接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+#
+#  @(#) $Id$
+#
+ 
+#
+#  Makefile のプロセッサ依存 (usb用)
+#
+
+ifeq ($(USB_OTG_MODE),)
+USB_OTG_MODE = USB_OTG_MODE_DEVICE
+endif
+
+#
+#  コンパイルオプション
+#
+INCLUDES := $(INCLUDES) -I$(SRCDIR)/usb/host/HID \
+		-I$(SRCDIR)/usb/host \
+		-I$(SRCDIR)/usb/host/MSC \
+		-I$(SRCDIR)/usb/host/SERIAL \
+		-I$(SRCDIR)/usb/host/PRT \
+		-I$(SRCDIR)/usb/host/BLUETOOTH \
+		-I$(SRCDIR)/usb/host/HUB \
+		-I$(SRCDIR)/usb/device \
+		-I$(SRCDIR)/usb 
+
+CDEFS := $(CDEFS) -DUSB_OTG_MODE=$(USB_OTG_MODE)
+
+#
+#  USBミドルウェアに関する定義
+#
+SYSSVC_DIR := $(SYSSVC_DIR):\
+		$(SRCDIR)/usb/host:$(SRCDIR)/usb/host/HID:$(SRCDIR)/usb/host/MSC:$(SRCDIR)/usb/host/SERIAL:$(SRCDIR)/usb/host/PRT:\
+		$(SRCDIR)/usb/host/BLUETOOTH:$(SRCDIR)/usb/host/HUB:\
+		$(SRCDIR)/usb/device:$(SRCDIR)/usb/device/HID:$(SRCDIR)/usb/device/SERIAL:$(SRCDIR)/usb
+ifneq ($(USB_OTG_MODE),USB_OTG_MODE_DEVICE)
+SYSSVC_COBJS := $(SYSSVC_COBJS) tusb_rtos.o tusbh_base.o tusbh_request.o 
+endif
+ifneq ($(USB_OTG_MODE),USB_OTG_MODE_HOST)
+SYSSVC_COBJS := $(SYSSVC_COBJS) tusbd_base.o tusbd_request.o 
+endif
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/HID/tusbd_device.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/HID/tusbd_device.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/HID/tusbd_device.h	(revision 453)
@@ -0,0 +1,69 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2017 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  TOPPERS USB DEVICE CLASS CONFIGURATION インクルードファイル
+ */
+
+#ifndef _TUSBD_DEVICE_H_
+#define _TUSBD_DEVICE_H_
+
+#define tusbdClassInit                tusbdHidInit
+#define tusbdClassDeInit              tusbdHidDeInit
+#define tusbdClassSuspend(a)
+#define tusbdClassResume(a)
+#define tusbdClassEp0RxReady(a)
+#define tusbdClassEp0TxSent(a)
+#define tusbdClassSetup               tusbdHidSetup
+#define tusbdClassDataIn              tusbdHidDataIn
+#define tusbdClassDataOut(a, b)
+#define tusbdClassInIncomlete(a, b)
+#define tusbdClassOutIncomlete(a, b)
+#define USBD_HID_SendReport           tusbdHidSendData
+
+#define TUSBD_HS_CONFIG_DESCRIPTOR    configurationHidDescriptor
+#define TUSBD_HS_CONFIG_DESC_LENGTH   TOTAL_HID_DESCRIPTOR_LENGTH
+#define TUSBD_FS_CONFIG_DESCRIPTOR    configurationHidDescriptor
+#define TUSBD_FS_CONFIG_DESC_LENGTH   TOTAL_HID_DESCRIPTOR_LENGTH
+#define TUSBD_OTR_CONFIG_DESCRIPTOR   configurationHidOtherDescriptor
+#define TUSBD_OTR_CONFIG_DESC_LENGTH  TOTAL_HID_DESCRIPTOR_LENGTH
+
+#include "tusbd_hid.h"
+
+
+#endif /* _TUSBD_DEVICE_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/HID/tusbd_hid.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/HID/tusbd_hid.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/HID/tusbd_hid.c	(revision 453)
@@ -0,0 +1,375 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2017 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  USB Device HID CLASS部
+ */
+
+#include "tusbd_hid.h"
+
+
+
+#define HID_VERSION_1_11    (0x0111)
+
+#define HID_INTERVAL_TIME    10
+
+#ifndef HID_INTERFCAE_PROTOCOL
+#define HID_INTERFCAE_PROTOCOL    0x02		/* 2:mouse 1:keyboard */
+#endif
+
+
+
+/*
+ *  REPORT DESCRIPTOR
+ */
+static uint8_t reportDescriptor[]  __attribute__ ((aligned (USB_DATA_ALIGN))) = {
+
+	USAGE_PAGE(1),   0x01,
+	USAGE(1),   0x02,
+
+	COLLECTION(1),   0x01,
+	USAGE(1),   0x01,
+
+	COLLECTION(1),   0x00,
+	USAGE_PAGE(1),   0x09,
+	USAGE_MINIMUM(1),   0x01,
+	USAGE_MAXIMUM(1),   0x03,
+	LOGICAL_MINIMUM(1),   0x00,
+	LOGICAL_MAXIMUM(1),   0x01,
+	REPORT_COUNT(1),   0x03,
+	REPORT_SIZE(1),   0x01,
+	INPUT(1),   0x02,
+	REPORT_COUNT(1),   0x01,
+	REPORT_SIZE(1),   0x05,
+	INPUT(1),   0x01,
+	USAGE_PAGE(1),   0x01,
+	USAGE(1),   0x30,
+	USAGE(1),   0x31,
+	USAGE(1),   0x38,
+
+	LOGICAL_MINIMUM(1),   0x81,
+	LOGICAL_MAXIMUM(1),   0x7F,
+	REPORT_SIZE(1),  0x08,
+	REPORT_COUNT(1), 0x03,
+
+	INPUT(1),   0x06,
+	END_COLLECTION(0),
+
+	USAGE(1), 0x3c,
+	USAGE_PAGE(1), 0xff,
+	USAGE(1), 0x01,
+	LOGICAL_MINIMUM(1), 0x00,
+	LOGICAL_MAXIMUM(1), 0x01,
+	REPORT_SIZE(1), 0x01,
+	REPORT_COUNT(1), 0x02,
+	FEATURE(1), 0x22,
+	REPORT_SIZE(1), 0x06,
+	REPORT_COUNT(1), 0x01,
+	FEATURE(1), 0x01,
+	END_COLLECTION(0)
+};
+
+/*
+ *  USB HID DEVICE CONFIGURATION DESCRIPTOR
+ */
+uint8_t configurationHidDescriptor[TOTAL_HID_DESCRIPTOR_LENGTH]  __attribute__ ((aligned (USB_DATA_ALIGN))) =
+{
+	CONFIGURATION_DESCRIPTOR_LENGTH,    // bLength
+	CONFIGURATION_DESCRIPTOR,           // bDescriptorType
+	(TOTAL_HID_DESCRIPTOR_LENGTH & 0xFF),   // wTotalLength (LSB)
+	(TOTAL_HID_DESCRIPTOR_LENGTH >> 8),     // wTotalLength (MSB)
+ 	0x01,                               // bNumInterfaces
+	0x01,                               // bConfigurationValue
+	0x00,                               // iConfiguration
+	C_RESERVED | C_SELF_POWERED | C_REMOTE_WAKEUP,	// bmAttributes
+	C_POWER(100),                       // bMaxPower
+
+	INTERFACE_DESCRIPTOR_LENGTH,        // bLength
+	INTERFACE_DESCRIPTOR,               // bDescriptorType
+	0x00,                               // bInterfaceNumber
+	0x00,                               // bAlternateSetting
+	0x01,                               // bNumEndpoints
+	HID_CLASS,                          // bInterfaceClass
+	0x01,                               // bInterfaceSubClass : 1=BOOT, 0=no boot
+	HID_INTERFCAE_PROTOCOL,             // bInterfaceProtocol
+	0x00,                               // iInterface
+
+	HID_DESCRIPTOR_LENGTH,              // bLength
+	HID_DESCRIPTOR,                     // bDescriptorType
+	(HID_VERSION_1_11 & 0xFF),          // bcdHID (LSB)
+	(HID_VERSION_1_11 >> 8),            // bcdHID (MSB)
+	0x00,                               // bCountryCode
+	0x01,                               // bNumDescriptors
+	0x22,                               // bDescriptorType
+	(sizeof(reportDescriptor) & 0xFF),  // wDescriptorLength (LSB)
+	(sizeof(reportDescriptor) >> 8),    // wDescriptorLength (MSB)
+
+	ENDPOINT_DESCRIPTOR_LENGTH,         // bLength
+	ENDPOINT_DESCRIPTOR,                // bDescriptorType
+	EPIN_ADDR,                          // bEndpointAddress
+	USB_EP_TYPE_INTR,                   // bmAttributes
+	(EPIN_SIZE & 0xFF),                 // wMaxPacketSize (LSB)
+	(EPIN_SIZE >> 8),                   // wMaxPacketSize (MSB)
+	HID_INTERVAL_TIME                   // bInterval (milliseconds)
+};
+
+/*
+ *  USB HID DEVICE OTHER CONFIGURATION DESCRIPTOR
+ */
+uint8_t configurationHidOtherDescriptor[TOTAL_HID_DESCRIPTOR_LENGTH]  __attribute__ ((aligned (USB_DATA_ALIGN))) =
+{
+	CONFIGURATION_DESCRIPTOR_LENGTH,    // bLength
+	OTHER_SPEED_CONFIGURATION_DESC,     // bDescriptorType
+	(TOTAL_HID_DESCRIPTOR_LENGTH & 0xFF),   // wTotalLength (LSB)
+	(TOTAL_HID_DESCRIPTOR_LENGTH >> 8),     // wTotalLength (MSB)
+ 	0x01,                               // bNumInterfaces
+	0x01,                               // bConfigurationValue
+	0x00,                               // iConfiguration
+	C_RESERVED | C_SELF_POWERED | C_REMOTE_WAKEUP,	// bmAttributes
+	C_POWER(100),                       // bMaxPower
+
+	INTERFACE_DESCRIPTOR_LENGTH,        // bLength
+	INTERFACE_DESCRIPTOR,               // bDescriptorType
+	0x00,                               // bInterfaceNumber
+	0x00,                               // bAlternateSetting
+	0x01,                               // bNumEndpoints
+	HID_CLASS,                          // bInterfaceClass
+	0x01,                               // bInterfaceSubClass : 1=BOOT, 0=no boot*/
+	0x02,                               // bInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
+	0x00,                               // iInterface
+
+	HID_DESCRIPTOR_LENGTH,              // bLength
+	HID_DESCRIPTOR,                     // bDescriptorType
+	(HID_VERSION_1_11 & 0xFF),          // bcdHID (LSB)
+	(HID_VERSION_1_11 >> 8),            // bcdHID (MSB)
+	0x00,                               // bCountryCode
+	0x01,                               // bNumDescriptors
+	0x22,                               // bDescriptorType
+	(sizeof(reportDescriptor) & 0xFF),  // wDescriptorLength (LSB)
+	(sizeof(reportDescriptor) >> 8),    // wDescriptorLength (MSB)
+
+	ENDPOINT_DESCRIPTOR_LENGTH,         // bLength
+	ENDPOINT_DESCRIPTOR,                // bDescriptorType
+	EPIN_ADDR,                          // bEndpointAddress
+	USB_EP_TYPE_INTR,                   // bmAttributes
+	(EPIN_SIZE & 0xFF),                 // wMaxPacketSize (LSB)
+	(EPIN_SIZE >> 8),                   // wMaxPacketSize (MSB)
+	HID_INTERVAL_TIME                   // bInterval (milliseconds)
+};
+
+static TUSBD_HID_Handle_t HID_CLASS_DATA __attribute__ ((aligned (USB_DATA_ALIGN)));
+
+
+/*
+ *  USB DEVICE HID初期化
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  parameter2 idx:      Configuration index
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+tusbdHidInit(TUSBD_Handle_t *pdevice, uint8_t idx)
+{
+	tusbdDriverOpenEp(pdevice, EPIN_ADDR, USB_EP_TYPE_INTR, EPIN_SIZE);
+	memset(&HID_CLASS_DATA, 0, sizeof(TUSBD_HID_Handle_t));
+	HID_CLASS_DATA.datastate = HID_DATA_IDLE;
+
+	pdevice->pClassData = &HID_CLASS_DATA;
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB DEVICE HIDクラス終了
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  parameter2 idx:      Configuration index
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+tusbdHidDeInit(TUSBD_Handle_t *pdevice, uint8_t idx)
+{
+	tusbdDriverCloseEp(pdevice, EPIN_ADDR);
+	pdevice->pClassData = NULL;
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB DEVICE HIDクラスセットアップ
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  parameter2 req:      usb control requests
+ *  return     TUSBD_ERCODE
+ */
+void
+tusbdHidSetup(TUSBD_Handle_t *pdevice, UsbSetupRequest *req)
+{
+	TUSBD_HID_Handle_t *hhid = (TUSBD_HID_Handle_t*) pdevice->pClassData;
+	uint16_t len = 0;
+	volatile uint8_t  *pbuf = NULL;
+	uint8_t  *p;
+	uint32_t i;
+
+	switch (req->bmRequest & USB_REQUEST_TYPE_MASK){
+	case USB_REQUEST_TYPE_STANDARD:
+		switch (req->bRequest){
+		case GET_DESCRIPTOR:
+			if((req->wValue >> 8) == HID_REPORT_DESCRIPTOR){
+				len = sizeof(reportDescriptor);
+				pbuf = reportDescriptor;
+			}
+			else if((req->wValue >> 8) == HID_DESCRIPTOR){
+				pbuf = tusbdFindDescriptor(pdevice, HID_DESCRIPTOR);
+				if(pbuf != NULL){
+					p   = pdevice->devData;
+					len = pbuf[0];
+					for(i = 0 ; i < len && i < 32 ; i++)
+						*p++ = *pbuf++;
+					pbuf = pdevice->devData;
+				}
+			}
+			if(len > 0){
+				if(len > req->wLength)
+					len = req->wLength;
+				tusbdControlSendData(pdevice, (uint8_t *)pbuf, len);
+			}
+			break;
+		case GET_INTERFACE:
+			pdevice->devData[0] = hhid->AltSetting;
+			tusbdControlSendData(pdevice, (uint8_t *)pdevice->devData, 1);
+			break;
+		case SET_INTERFACE:
+			hhid->AltSetting = (uint8_t)(req->wValue);
+			break;
+		}
+		break;
+	case USB_REQUEST_TYPE_CLASS:
+		switch (req->bRequest){
+		case USB_SET_PROTOCOL:
+			hhid->Protocol = (uint8_t)(req->wValue);
+			break;
+		case USB_GET_PROTOCOL:
+			pdevice->devData[0] = hhid->Protocol;
+			tusbdControlSendData(pdevice, (uint8_t *)pdevice->devData, 1);
+			break;
+		case USB_SET_IDLE:
+			hhid->IdleState = (uint8_t)(req->wValue >> 8);
+			break;
+		case USB_GET_IDLE:
+			pdevice->devData[0] = hhid->IdleState;
+			tusbdControlSendData(pdevice, (uint8_t *)pdevice->devData, 1);
+			break;
+		case USB_GET_REPORT:
+			len = sizeof(reportDescriptor);
+			pbuf = reportDescriptor;
+			if(len > req->wLength)
+				len = req->wLength;
+			tusbdControlSendData(pdevice, (uint8_t *)pbuf, len);
+			break;
+		case USB_SET_REPORT:
+			if(hhid->devReportLength > 0){
+				hhid->devReport[0] = req->wValue & 0xff;
+				len = hhid->devReportLength;
+				if(len > (req->wLength + 1))
+					len = req->wLength + 1;
+				p = pdevice->devData;
+				for(i = 0 ; i < len && i < 32 ; i++)
+					*p++ = hhid->devReport[i+1];
+				tusbdControlSendData(pdevice, pdevice->devData, len);
+				break;
+			}
+		default:
+			tusbdControlSendStall(pdevice, req);
+			return;
+		}
+		break;
+	}
+}
+
+/*
+ *  USB DEVICE HIDクラスデータイン
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  parameter2 epnum:    Endpoint#
+ *  return     TUSBD_ERCODE
+ */
+void
+tusbdHidDataIn(TUSBD_Handle_t *pdevice, uint8_t epnum)
+{
+	((TUSBD_HID_Handle_t *)pdevice->pClassData)->datastate = HID_DATA_IDLE;
+}
+
+/*
+ *  USB DEVICE HIDクラスデータ送信
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  parameter2 pdata:    送信データ
+ *  parameter3 len:      送信データ長
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+tusbdHidSendData(TUSBD_Handle_t *pdevice, uint8_t *pdata, uint16_t len)
+{
+	TUSBD_HID_Handle_t *hhid = (TUSBD_HID_Handle_t*)pdevice->pClassData;
+    uint32_t i;
+
+	if(pdevice->dev_state == TUSBD_STATE_CONFIGURED){
+		if(hhid->datastate == HID_DATA_IDLE){
+			hhid->datastate = HID_DATA_BUSY;
+			for(i = 0 ; i < len && i < 32 ; i++)
+				hhid->hidData[i] = *pdata++;
+			tusbdDriverStartTransmit(pdevice, EPIN_ADDR, hhid->hidData, i);
+			return TUSBD_E_OK;
+		}
+	}
+	return TUSBD_E_BUSY;
+}
+
+/*
+ *  USB DEVICE SETUP REPORT
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  parameter2 report:   送信リポートデータ
+ *  parameter3 len:      送信リポートデータ長
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+tusbdHidSetupReport(TUSBD_Handle_t *pdevice, uint8_t *report, uint16_t len)
+{
+	TUSBD_HID_Handle_t *hhid = (TUSBD_HID_Handle_t*)pdevice->pClassData;
+	uint32_t i;
+
+	for(i = 0 ; i < len && i < (NUM_MAX_OUTREPORT-1) ; i++)
+		hhid->devReport[i+1] = *report++;
+	hhid->devReportLength = i;
+	return 0;
+}
+
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/HID/tusbd_hid.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/HID/tusbd_hid.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/HID/tusbd_hid.h	(revision 453)
@@ -0,0 +1,159 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2017 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ *  USB Device HID CLASSS部定義
+ */
+
+#ifndef _TUSBD_HID_H_
+#define _TUSBD_HID_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include  "tusbd_base.h"
+
+
+#define EPIN_ADDR                 0x81
+#define EPIN_SIZE                 0x04
+
+#define TOTAL_HID_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \
+                               + (1 * INTERFACE_DESCRIPTOR_LENGTH) \
+                               + (1 * HID_DESCRIPTOR_LENGTH) \
+                               + (1 * ENDPOINT_DESCRIPTOR_LENGTH))
+
+#define NUM_MAX_OUTREPORT         128
+
+#define USB_GET_REPORT            0x1
+#define USB_GET_IDLE              0x2
+#define USB_GET_PROTOCOL          0x3
+#define USB_SET_REPORT            0x9
+#define USB_SET_IDLE              0xA
+#define USB_SET_PROTOCOL          0xB
+
+
+/* Main items */
+#define INPUT(size)               (0x80 | size)
+#define OUTPUT(size)              (0x90 | size)
+#define FEATURE(size)             (0xb0 | size)
+#define COLLECTION(size)          (0xa0 | size)
+#define END_COLLECTION(size)      (0xc0 | size)
+
+/* Global items */
+#define USAGE_PAGE(size)          (0x04 | size)
+#define LOGICAL_MINIMUM(size)     (0x14 | size)
+#define LOGICAL_MAXIMUM(size)     (0x24 | size)
+#define PHYSICAL_MINIMUM(size)    (0x34 | size)
+#define PHYSICAL_MAXIMUM(size)    (0x44 | size)
+#define UNIT_EXPONENT(size)       (0x54 | size)
+#define UNIT(size)                (0x64 | size)
+#define REPORT_SIZE(size)         (0x74 | size)
+#define REPORT_ID(size)           (0x84 | size)
+#define REPORT_COUNT(size)        (0x94 | size)
+#define PUSH(size)                (0xa4 | size)
+#define POP(size)                 (0xb4 | size)
+
+/* Local items */
+#define USAGE(size)               (0x08 | size)
+#define USAGE_MINIMUM(size)       (0x18 | size)
+#define USAGE_MAXIMUM(size)       (0x28 | size)
+#define DESIGNATOR_INDEX(size)    (0x38 | size)
+#define DESIGNATOR_MINIMUM(size)  (0x48 | size)
+#define DESIGNATOR_MAXIMUM(size)  (0x58 | size)
+#define STRING_INDEX(size)        (0x78 | size)
+#define STRING_MINIMUM(size)      (0x88 | size)
+#define STRING_MAXIMUM(size)      (0x98 | size)
+#define DELIMITER(size)           (0xa8 | size)
+
+/*
+ *  HIDデータ状態定義
+ */
+#define HID_DATA_IDLE             0
+#define HID_DATA_BUSY             1
+
+
+
+typedef struct
+{
+	uint8_t             hidData[32];
+	uint8_t             devReport[NUM_MAX_OUTREPORT];
+	uint16_t            devReportLength;
+	uint8_t             Protocol;
+	uint8_t             IdleState;
+	uint8_t             AltSetting;
+	uint8_t             datastate;
+} TUSBD_HID_Handle_t; 
+
+
+extern uint8_t configurationHidDescriptor[];
+extern uint8_t configurationHidOtherDescriptor[];
+
+
+TUSBD_ERCODE tusbdHidSendData(TUSBD_Handle_t *pdevice, uint8_t *pdata, uint16_t len);
+TUSBD_ERCODE tusbdHidSetupReport(TUSBD_Handle_t *pdevice, uint8_t *report, uint16_t len);
+
+TUSBD_ERCODE tusbdHidInit(TUSBD_Handle_t *pdevice, uint8_t idx);
+TUSBD_ERCODE tusbdHidDeInit(TUSBD_Handle_t *pdevice, uint8_t idx);
+void         tusbdHidSetup(TUSBD_Handle_t *pdevice, UsbSetupRequest *req);
+void         tusbdHidDataIn(TUSBD_Handle_t *pdevice, uint8_t epnum);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TUSBD_HID_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/SERIAL/tusbd_device.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/SERIAL/tusbd_device.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/SERIAL/tusbd_device.h	(revision 453)
@@ -0,0 +1,68 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2017 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  TOPPERS USB DEVICE CLASS CONFIGURATION インクルードファイル
+ */
+
+#ifndef _TUSBD_DEVICE_H_
+#define _TUSBD_DEVICE_H_
+
+#define tusbdClassInit                tusbdCdcInit
+#define tusbdClassDeInit              tusbdCdcDeInit
+#define tusbdClassSuspend(a)
+#define tusbdClassResume(a)
+#define tusbdClassEp0RxReady          tusbdCdcEP0RxReady
+#define tusbdClassEp0TxSent(a)
+#define tusbdClassSetup               tusbdCdcSetup
+#define tusbdClassDataIn              tusbdCdcDataIn
+#define tusbdClassDataOut             tusbdCdcDataOut
+#define tusbdClassInIncomlete(a, b)
+#define tusbdClassOutIncomlete(a, b)
+
+#define TUSBD_HS_CONFIG_DESCRIPTOR    configurationCdcHsDescriptor
+#define TUSBD_HS_CONFIG_DESC_LENGTH   TOTAL_CDC_DESCRIPTOR_LENGTH
+#define TUSBD_FS_CONFIG_DESCRIPTOR    configurationCdcFsDescriptor
+#define TUSBD_FS_CONFIG_DESC_LENGTH   TOTAL_CDC_DESCRIPTOR_LENGTH
+#define TUSBD_OTR_CONFIG_DESCRIPTOR   configurationCdcOtrDescriptor
+#define TUSBD_OTR_CONFIG_DESC_LENGTH  TOTAL_CDC_DESCRIPTOR_LENGTH
+
+#include "tusbd_serial.h"
+
+
+#endif /* _TUSBD_DEVICE_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/SERIAL/tusbd_serial.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/SERIAL/tusbd_serial.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/SERIAL/tusbd_serial.c	(revision 453)
@@ -0,0 +1,498 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2017 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  USB Device Middleware CDC:SERIAL CLASS部
+ */
+
+#include "tusbd_serial.h"
+
+
+#define CDC_INTERVAL_TIME    16
+
+/*
+ *  USB CDC HS DEVICE CONFIGURATION DESCRIPTOR
+ */
+uint8_t configurationCdcHsDescriptor[TOTAL_CDC_DESCRIPTOR_LENGTH] __attribute__ ((aligned (USB_DATA_ALIGN))) =
+{
+	CONFIGURATION_DESCRIPTOR_LENGTH,	// bLength
+	CONFIGURATION_DESCRIPTOR,			// bDescriptorType
+	(TOTAL_CDC_DESCRIPTOR_LENGTH & 0xFF),   // wTotalLength (LSB)
+	(TOTAL_CDC_DESCRIPTOR_LENGTH >> 8),     // wTotalLength (MSB)
+	0x02,                               // bNumInterfaces
+	0x01,                               // bConfigurationValue
+	0x00,                               // iConfiguration
+	C_RESERVED | C_SELF_POWERED,        // bmAttributes
+	C_POWER(100),                       // bMaxPower
+
+	INTERFACE_DESCRIPTOR_LENGTH,        // bLength
+	INTERFACE_DESCRIPTOR,               // bDescriptorType
+	0x00,                               // bInterfaceNumber
+	0x00,                               // bAlternateSetting
+	0x01,                               // bNumEndpoints
+	CDC_CLASS,                          // bInterfaceClass
+	0x02,                               // bInterfaceSubClass
+	0x01,                               // bInterfaceProtocol
+	0x00,                               // iInterface
+
+	/* CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26 */
+ 	0x05,                               // bFunctionLength
+	0x24,                               // bDescriptorType
+	0x00,                               // bDescriptorSubtype
+	0x10, 0x01,                         // bcdCDC
+	/* Call Management Functional Descriptor, CDC Spec 5.2.3.2, Table 27 */
+	0x05,                               // bFunctionLength
+	0x24,                               // bDescriptorType
+	0x01,                               // bDescriptorSubtype
+	0x03,                               // bmCapabilities
+	0x01,                               // bDataInterface
+	/* Abstract Control Management Functional Descriptor, CDC Spec 5.2.3.3, Table 28 */
+	0x04,                               // bFunctionLength
+	0x24,                               // bDescriptorType
+	0x02,                               // bDescriptorSubtype
+	0x06,                               // bmCapabilities
+	/* Union Functional Descriptor, CDC Spec 5.2.3.8, Table 33 */
+	0x05,                               // bFunctionLength
+	0x24,                               // bDescriptorType
+	0x06,                               // bDescriptorSubtype
+	0x00,                               // bMasterInterface
+	0x01,                               // bSlaveInterface0
+
+	ENDPOINT_DESCRIPTOR_LENGTH,         // bLength
+	ENDPOINT_DESCRIPTOR,                // bDescriptorType
+	CDC_EPINT_ADDR,                     // bEndpointAddress
+	USB_EP_TYPE_INTR,                   // bmAttributes
+	(CDC_PACKET_SIZE_EPINT & 0xFF),     // wMaxPacketSize (LSB)
+	(CDC_PACKET_SIZE_EPINT >> 8),       // wMaxPacketSize (MSB)
+	CDC_INTERVAL_TIME,                  // bInterval
+
+	INTERFACE_DESCRIPTOR_LENGTH,        // bLength
+	INTERFACE_DESCRIPTOR,               // bDescriptorType
+	0x01,                               // bInterfaceNumber
+	0x00,                               // bAlternateSetting
+	0x02,                               // bNumEndpoints
+	DATA_INTERFACE_CLASS,               // bInterfaceClass
+	0x00,                               // bInterfaceSubClass
+	0x00,                               // bInterfaceProtocol
+	0x00,                               // iInterface
+
+	ENDPOINT_DESCRIPTOR_LENGTH,         // bLength
+	ENDPOINT_DESCRIPTOR,                // bDescriptorType
+	CDC_EPBULKOUT_ADDR,                 // bEndpointAddress
+	USB_EP_TYPE_BULK,                   // bmAttributes
+	(MAX_PACKET_SIZE_HS_EPBULK & 0xFF), // wMaxPacketSize (LSB)
+	(MAX_PACKET_SIZE_HS_EPBULK >> 8),   // wMaxPacketSize (MSB)
+	0x00,                               // bInterval (milliseconds)
+
+	ENDPOINT_DESCRIPTOR_LENGTH,         // bLength
+	ENDPOINT_DESCRIPTOR,                // bDescriptorType
+	CDC_EPBULKIN_ADDR,                  // bEndpointAddress
+	USB_EP_TYPE_BULK,                   // bmAttributes
+	(MAX_PACKET_SIZE_HS_EPBULK & 0xFF), // wMaxPacketSize (LSB)
+	(MAX_PACKET_SIZE_HS_EPBULK >> 8),   // wMaxPacketSize (MSB)
+	0x00                                // bInterval (milliseconds)
+};
+
+/*
+ *  USB CDC FS DEVICE CONFIGURATION DESCRIPTOR
+ */
+uint8_t configurationCdcFsDescriptor[TOTAL_CDC_DESCRIPTOR_LENGTH] __attribute__ ((aligned (USB_DATA_ALIGN))) =
+{
+  /*Configuration Descriptor*/
+	CONFIGURATION_DESCRIPTOR_LENGTH,	// bLength
+	CONFIGURATION_DESCRIPTOR,			// bDescriptorType
+	(TOTAL_CDC_DESCRIPTOR_LENGTH & 0xFF),   // wTotalLength (LSB)
+	(TOTAL_CDC_DESCRIPTOR_LENGTH >> 8),     // wTotalLength (MSB)
+	0x02,                               // bNumInterfaces
+	0x01,                               // bConfigurationValue
+	0x00,                               // iConfiguration
+	C_RESERVED | C_SELF_POWERED,        // bmAttributes
+	C_POWER(100),                       // bMaxPower
+
+	INTERFACE_DESCRIPTOR_LENGTH,        // bLength
+	INTERFACE_DESCRIPTOR,               // bDescriptorType
+	0x00,                               // bInterfaceNumber
+	0x00,                               // bAlternateSetting
+	0x01,                               // bNumEndpoints
+	CDC_CLASS,                          // bInterfaceClass
+	0x02,                               // bInterfaceSubClass
+	0x01,                               // bInterfaceProtocol
+	0x00,                               // iInterface
+
+	/* CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26 */
+ 	0x05,                               // bFunctionLength
+	0x24,                               // bDescriptorType
+	0x00,                               // bDescriptorSubtype
+	0x10, 0x01,                         // bcdCDC
+	/* Call Management Functional Descriptor, CDC Spec 5.2.3.2, Table 27 */
+	0x05,                               // bFunctionLength
+	0x24,                               // bDescriptorType
+	0x01,                               // bDescriptorSubtype
+	0x03,                               // bmCapabilities
+	0x01,                               // bDataInterface
+	/* Abstract Control Management Functional Descriptor, CDC Spec 5.2.3.3, Table 28 */
+	0x04,                               // bFunctionLength
+	0x24,                               // bDescriptorType
+	0x02,                               // bDescriptorSubtype
+	0x06,                               // bmCapabilities
+	/* Union Functional Descriptor, CDC Spec 5.2.3.8, Table 33 */
+	0x05,                               // bFunctionLength
+	0x24,                               // bDescriptorType
+	0x06,                               // bDescriptorSubtype
+	0x00,                               // bMasterInterface
+	0x01,                               // bSlaveInterface0
+
+	ENDPOINT_DESCRIPTOR_LENGTH,         // bLength
+	ENDPOINT_DESCRIPTOR,                // bDescriptorType
+	CDC_EPINT_ADDR,                     // bEndpointAddress
+	USB_EP_TYPE_INTR,                   // bmAttributes
+	(CDC_PACKET_SIZE_EPINT & 0xFF),     // wMaxPacketSize (LSB)
+	(CDC_PACKET_SIZE_EPINT >> 8),       // wMaxPacketSize (MSB)
+	CDC_INTERVAL_TIME,                  // bInterval
+
+	INTERFACE_DESCRIPTOR_LENGTH,        // bLength
+	INTERFACE_DESCRIPTOR,               // bDescriptorType
+	0x01,                               // bInterfaceNumber
+	0x00,                               // bAlternateSetting
+	0x02,                               // bNumEndpoints
+	DATA_INTERFACE_CLASS,               // bInterfaceClass
+	0x00,                               // bInterfaceSubClass
+	0x00,                               // bInterfaceProtocol
+	0x00,                               // iInterface
+
+	ENDPOINT_DESCRIPTOR_LENGTH,         // bLength
+	ENDPOINT_DESCRIPTOR,                // bDescriptorType
+	CDC_EPBULKOUT_ADDR,                 // bEndpointAddress
+	USB_EP_TYPE_BULK,                   // bmAttributes
+	(MAX_PACKET_SIZE_FS_EPBULK & 0xFF), // wMaxPacketSize (LSB)
+	(MAX_PACKET_SIZE_FS_EPBULK >> 8),   // wMaxPacketSize (MSB)
+	0x00,                               // bInterval (milliseconds)
+
+	ENDPOINT_DESCRIPTOR_LENGTH,         // bLength
+	ENDPOINT_DESCRIPTOR,                // bDescriptorType
+	CDC_EPBULKIN_ADDR,                  // bEndpointAddress
+	USB_EP_TYPE_BULK,                   // bmAttributes
+	(MAX_PACKET_SIZE_FS_EPBULK & 0xFF), // wMaxPacketSize (LSB)
+	(MAX_PACKET_SIZE_FS_EPBULK >> 8),   // wMaxPacketSize (MSB)
+	0x00                                // bInterval (milliseconds)
+} ;
+
+/*
+ *  USB CDC OTHER DEVICE CONFIGURATION DESCRIPTOR
+ */
+uint8_t configurationCdcOtrDescriptor[TOTAL_CDC_DESCRIPTOR_LENGTH] __attribute__ ((aligned (USB_DATA_ALIGN))) =
+{
+	CONFIGURATION_DESCRIPTOR_LENGTH,	// bLength
+	OTHER_SPEED_CONFIGURATION_DESC,     // bDescriptorType
+	(TOTAL_CDC_DESCRIPTOR_LENGTH & 0xFF),   // wTotalLength (LSB)
+	(TOTAL_CDC_DESCRIPTOR_LENGTH >> 8),     // wTotalLength (MSB)
+	0x02,                               // bNumInterfaces
+	0x01,                               // bConfigurationValue
+	0x04,                               // iConfiguration
+	C_RESERVED | C_SELF_POWERED,        // bmAttributes
+	C_POWER(100),                       // bMaxPower
+
+	INTERFACE_DESCRIPTOR_LENGTH,        // bLength
+	INTERFACE_DESCRIPTOR,               // bDescriptorType
+	0x00,                               // bInterfaceNumber
+	0x00,                               // bAlternateSetting
+	0x01,                               // bNumEndpoints
+	CDC_CLASS,                          // bInterfaceClass
+	0x02,                               // bInterfaceSubClass
+	0x01,                               // bInterfaceProtocol
+	0x00,                               // iInterface
+
+	/* CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26 */
+ 	0x05,                               // bFunctionLength
+	0x24,                               // bDescriptorType
+	0x00,                               // bDescriptorSubtype
+	0x10, 0x01,                         // bcdCDC
+	/* Call Management Functional Descriptor, CDC Spec 5.2.3.2, Table 27 */
+	0x05,                               // bFunctionLength
+	0x24,                               // bDescriptorType
+	0x01,                               // bDescriptorSubtype
+	0x03,                               // bmCapabilities
+	0x01,                               // bDataInterface
+	/* Abstract Control Management Functional Descriptor, CDC Spec 5.2.3.3, Table 28 */
+	0x04,                               // bFunctionLength
+	0x24,                               // bDescriptorType
+	0x02,                               // bDescriptorSubtype
+	0x06,                               // bmCapabilities
+	/* Union Functional Descriptor, CDC Spec 5.2.3.8, Table 33 */
+	0x05,                               // bFunctionLength
+	0x24,                               // bDescriptorType
+	0x06,                               // bDescriptorSubtype
+	0x00,                               // bMasterInterface
+	0x01,                               // bSlaveInterface0
+
+	ENDPOINT_DESCRIPTOR_LENGTH,         // bLength
+	ENDPOINT_DESCRIPTOR,                // bDescriptorType
+	CDC_EPINT_ADDR,                     // bEndpointAddress
+	USB_EP_TYPE_INTR,                   // bmAttributes
+	(CDC_PACKET_SIZE_EPINT & 0xFF),     // wMaxPacketSize (LSB)
+	(CDC_PACKET_SIZE_EPINT >> 8),       // wMaxPacketSize (MSB)
+	CDC_INTERVAL_TIME,                  // bInterval
+
+	INTERFACE_DESCRIPTOR_LENGTH,        // bLength
+	INTERFACE_DESCRIPTOR,               // bDescriptorType
+	0x01,                               // bInterfaceNumber
+	0x00,                               // bAlternateSetting
+	0x02,                               // bNumEndpoints
+	DATA_INTERFACE_CLASS,               // bInterfaceClass
+	0x00,                               // bInterfaceSubClass
+	0x00,                               // bInterfaceProtocol
+	0x00,                               // iInterface
+
+	ENDPOINT_DESCRIPTOR_LENGTH,         // bLength
+	ENDPOINT_DESCRIPTOR,                // bDescriptorType
+	CDC_EPBULKOUT_ADDR,                 // bEndpointAddress
+	USB_EP_TYPE_BULK,                   // bmAttributes
+	(MAX_PACKET_SIZE_FS_EPBULK & 0xFF), // wMaxPacketSize (LSB)
+	(MAX_PACKET_SIZE_FS_EPBULK >> 8),   // wMaxPacketSize (MSB)
+	0x00,                               // bInterval (milliseconds)
+
+	ENDPOINT_DESCRIPTOR_LENGTH,         // bLength
+	ENDPOINT_DESCRIPTOR,                // bDescriptorType
+	CDC_EPBULKIN_ADDR,                  // bEndpointAddress
+	USB_EP_TYPE_BULK,                   // bmAttributes
+	(MAX_PACKET_SIZE_FS_EPBULK & 0xFF), // wMaxPacketSize (LSB)
+	(MAX_PACKET_SIZE_FS_EPBULK >> 8),   // wMaxPacketSize (MSB)
+	0x00                                // bInterval (milliseconds)
+};
+
+static TUSBD_CDC_Handle_t CDC_CLASS_DATA  __attribute__ ((aligned (USB_DATA_ALIGN)));
+
+
+/*
+ *  USB DEVICE CDC初期化
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  parameter2 idx:      Configuration index
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+tusbdCdcInit(TUSBD_Handle_t *pdevice, uint8_t idx)
+{
+	TUSBD_CDC_Handle_t *hcdc;
+
+	memset(&CDC_CLASS_DATA, 0, sizeof(TUSBD_CDC_Handle_t));
+	pdevice->pClassData = &CDC_CLASS_DATA;
+	hcdc = (TUSBD_CDC_Handle_t*) pdevice->pClassData;
+	if(pdevice->dev_speed == USB_DEVICE_SPEED_HIGH)
+		hcdc->packetsize = MAX_PACKET_SIZE_HS_EPBULK;
+	else
+		hcdc->packetsize = MAX_PACKET_SIZE_FS_EPBULK;
+	hcdc->TxState = 0;
+	hcdc->CmdCode = 0xFF;
+
+	/*
+	 *  ENDPOINT OPEN
+	 */
+	tusbdDriverOpenEp(pdevice, CDC_EPBULKIN_ADDR, USB_EP_TYPE_BULK, hcdc->packetsize);
+	tusbdDriverOpenEp(pdevice, CDC_EPBULKOUT_ADDR, USB_EP_TYPE_BULK, hcdc->packetsize);
+	tusbdDriverOpenEp(pdevice, CDC_EPINT_ADDR, USB_EP_TYPE_INTR, CDC_PACKET_SIZE_EPINT);
+
+	/*
+	 *  SETUP RECEIVED PACKET AREA
+	 */
+	tusbdCdcSetReceivePacket(pdevice);
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB DEVICE HIDクラス終了
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  parameter2 idx:      Configuration index
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+tusbdCdcDeInit(TUSBD_Handle_t *pdevice, uint8_t cfgidx)
+{
+	/*
+	 * ENDPOINT CLOSE
+	 */
+	tusbdDriverCloseEp(pdevice, CDC_EPBULKIN_ADDR);
+	tusbdDriverCloseEp(pdevice, CDC_EPBULKOUT_ADDR);
+	tusbdDriverCloseEp(pdevice, CDC_EPINT_ADDR);
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB DEVICE CDCクラス EP0受信READY
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  return     TUSBD_ERCODE
+ */
+void
+tusbdCdcEP0RxReady(TUSBD_Handle_t *pdevice)
+{
+	TUSBD_CDC_Handle_t *hcdc = (TUSBD_CDC_Handle_t*)pdevice->pClassData;
+	void (*func)(TUSBD_CDC_Handle_t *, uint8_t, uint32_t);
+
+	if(((func = pdevice->pUsrData) != NULL) && (hcdc->CmdCode != 0xFF)){
+		func(hcdc, hcdc->CmdCode, hcdc->CmdLength);
+		hcdc->CmdCode = 0xFF;
+	}
+}
+
+/*
+ *  USB DEVICE CDCクラスセットアップ
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  parameter2 req:      usb control requests
+ *  return     TUSBD_ERCODE
+ */
+void
+tusbdCdcSetup(TUSBD_Handle_t *pdevice, UsbSetupRequest *req)
+{
+	TUSBD_CDC_Handle_t *hcdc = (TUSBD_CDC_Handle_t*) pdevice->pClassData;
+	void (*func)(TUSBD_CDC_Handle_t *, uint8_t, uint32_t);
+
+	func = pdevice->pUsrData;
+	switch (req->bmRequest & USB_REQUEST_TYPE_MASK){
+	case USB_REQUEST_TYPE_CLASS:
+		if(req->wLength){
+			if(req->bmRequest & USB_DEVICE_TO_HOST){
+				if(func != NULL)
+					func(hcdc, req->bRequest, req->wLength);
+				tusbdControlSendData(pdevice, (uint8_t *)hcdc->cmddata, req->wLength);
+			}
+			else{
+				hcdc->CmdCode   = req->bRequest;
+				hcdc->CmdLength = req->wLength;
+				tusbdControlReceiveStart(pdevice, (uint8_t *)hcdc->cmddata, req->wLength);
+			}
+		}
+		else if(func != NULL)
+			func(hcdc, req->bRequest, 0);
+		break;
+	case USB_REQUEST_TYPE_STANDARD:
+		switch(req->bRequest){
+		case GET_INTERFACE:
+			pdevice->devData[0] = 0;
+			tusbdControlSendData(pdevice, (uint8_t *)pdevice->devData, 1);
+			break;
+		case SET_INTERFACE:
+		default:
+			break;
+		}
+	default:
+		break;
+	}
+}
+
+/*
+ *  USB DEVICE CDCクラスデータイン
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  parameter2 epnum:    Endpoint#
+ *  return     TUSBD_ERCODE
+ */
+void
+tusbdCdcDataIn(TUSBD_Handle_t *pdevice, uint8_t epnum)
+{
+	TUSBD_CDC_Handle_t *hcdc = (TUSBD_CDC_Handle_t*) pdevice->pClassData;
+
+	if(pdevice->pClassData != NULL){
+		hcdc->TxState = 0;
+	}
+}
+
+/*
+ *  USB DEVICE CDCクラスデータアウト
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  parameter2 epnum:    Endpoint#
+ *  return     TUSBD_ERCODE
+ */
+void
+tusbdCdcDataOut(TUSBD_Handle_t *pdevice, uint8_t epnum)
+{
+	TUSBD_CDC_Handle_t *hcdc = (TUSBD_CDC_Handle_t*) pdevice->pClassData;
+	void (*func)(TUSBD_CDC_Handle_t *, uint8_t, uint32_t);
+
+	hcdc->RxLength = tusbdDriverGetRxDataSize(pdevice, epnum);
+	if((func = pdevice->pUsrData) != NULL){
+		func(hcdc, CDC_RECEIVED, hcdc->RxLength);
+	}
+}
+
+/*
+ *  USB DEVICE CDC START SENS DATA
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  parameter2 pbuff:    送信データ
+ *  parameter2 length:   送信データ長
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+tusbdCdcStartTransmit(TUSBD_Handle_t *pdevice, uint8_t *pbuff, uint32_t length)
+{
+	TUSBD_CDC_Handle_t *hcdc = (TUSBD_CDC_Handle_t*)pdevice->pClassData;
+
+	if(pdevice->pClassData != NULL){
+		if(hcdc->TxState == 0){
+			hcdc->TxState = 1;
+			hcdc->TxBuffer = pbuff;
+			hcdc->TxLength = length;
+
+			tusbCpuLock();
+			tusbdDriverStartTransmit(pdevice, CDC_EPBULKIN_ADDR, hcdc->TxBuffer, hcdc->TxLength);
+			tusbCpuUnLock();
+			return TUSBD_E_OK;
+		}
+		else
+			return TUSBD_E_BUSY;
+	}
+	else
+		return TUSBD_E_ERR;
+}
+
+/*
+ *  USB DEVICE CDC SETUP RECEVE PACKET
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+tusbdCdcSetReceivePacket(TUSBD_Handle_t *pdevice)
+{
+	TUSBD_CDC_Handle_t *hcdc = (TUSBD_CDC_Handle_t*)pdevice->pClassData;
+
+	if(pdevice->pClassData != NULL){
+		tusbCpuLock();
+		tusbdDriverSetupReceive(pdevice, CDC_EPBULKOUT_ADDR, hcdc->rxdata, hcdc->packetsize);
+		tusbCpuUnLock();
+		return TUSBD_E_OK;
+	}
+	else
+		return TUSBD_E_ERR;
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/SERIAL/tusbd_serial.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/SERIAL/tusbd_serial.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/SERIAL/tusbd_serial.h	(revision 453)
@@ -0,0 +1,133 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2017 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ *  USB Device CDC SERIAL CLASSS部定義
+ */
+
+#ifndef _TUSBD_SERIAL_H_
+#define _TUSBD_SERIAL_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include  "tusbd_base.h"
+
+
+#define CDC_EPBULKIN_ADDR                           0x81
+#define CDC_EPBULKOUT_ADDR                          0x01
+#define CDC_EPINT_ADDR                              0x82
+
+#define TOTAL_CDC_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \
+                               + (2 * INTERFACE_DESCRIPTOR_LENGTH) \
+                               + (5 + 5 + 5 + 4) \
+                               + (3 * ENDPOINT_DESCRIPTOR_LENGTH))
+
+#define CDC_PACKET_SIZE_EPINT                       8
+#define CDC_LINE_CODE_SIZE                          7
+
+/*
+ *  CDC要求定義
+ */
+#define CDC_SEND_ENCAPSULATED_COMMAND               0x00
+#define CDC_GET_ENCAPSULATED_RESPONSE               0x01
+#define CDC_SET_COMM_FEATURE                        0x02
+#define CDC_GET_COMM_FEATURE                        0x03
+#define CDC_CLEAR_COMM_FEATURE                      0x04
+#define CDC_SET_LINE_CODING                         0x20
+#define CDC_GET_LINE_CODING                         0x21
+#define CDC_SET_CONTROL_LINE_STATE                  0x22
+#define CDC_SEND_BREAK                              0x23
+
+#define CDC_RECEIVED                                0x40
+
+
+typedef struct
+{
+	uint8_t  rxdata[MAX_PACKET_SIZE_HS_EPBULK];
+	uint8_t  cmddata[64];
+	uint8_t  CmdCode;
+	uint8_t  CmdLength;
+	uint16_t packetsize;
+	uint32_t RxLength;
+	uint8_t  *TxBuffer;
+	uint32_t TxLength;
+	volatile uint32_t TxState;
+} TUSBD_CDC_Handle_t;
+
+extern uint8_t configurationCdcHsDescriptor[];
+extern uint8_t configurationCdcFsDescriptor[];
+extern uint8_t configurationCdcOtrDescriptor[];
+
+
+TUSBD_ERCODE tusbdCdcSetReceivePacket(TUSBD_Handle_t *pdevice);
+TUSBD_ERCODE tusbdCdcStartTransmit(TUSBD_Handle_t *pdevice, uint8_t *pbuff, uint32_t length);
+
+
+TUSBD_ERCODE tusbdCdcInit(TUSBD_Handle_t *pdevice, uint8_t idx);
+TUSBD_ERCODE tusbdCdcDeInit(TUSBD_Handle_t *pdevice, uint8_t idx);
+void         tusbdCdcEP0RxReady(TUSBD_Handle_t *pdevice);
+void         tusbdCdcSetup(TUSBD_Handle_t *pdevice, UsbSetupRequest *req);
+void         tusbdCdcDataIn(TUSBD_Handle_t *pdevice, uint8_t epnum);
+void         tusbdCdcDataOut(TUSBD_Handle_t *pdevice, uint8_t epnum);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TUSBD_SERIAL_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/tusbd_base.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/tusbd_base.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/tusbd_base.c	(revision 453)
@@ -0,0 +1,811 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2017 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  USB Device Middleware BASE部
+ */
+
+#include "tusbd_base.h"
+#include "tusbd_device.h"
+
+
+#define NUM_MAX_REQUEST      13
+#define NUM_STRING_TABLE     7
+
+static void DeviceGetStatus(TUSBD_Handle_t *pdevice, UsbSetupRequest *req);
+static void DeviceClearFeature(TUSBD_Handle_t *pdevice, UsbSetupRequest *req);
+static void DeviceSetFeature(TUSBD_Handle_t *pdevice, UsbSetupRequest *req);
+static void DeviceGetDescriptor(TUSBD_Handle_t *pdevice, UsbSetupRequest *req);
+static void DeviceSetAddress(TUSBD_Handle_t *pdevice, UsbSetupRequest *req);
+static void DeviceGetConfiguration(TUSBD_Handle_t *pdevice, UsbSetupRequest *req);
+static void DeviceSetConfiguration(TUSBD_Handle_t *pdevice, UsbSetupRequest *req);
+static void EndpointGetStatus(TUSBD_Handle_t *pdevice, UsbSetupRequest *req);
+static void EndpointClearFeature(TUSBD_Handle_t *pdevice, UsbSetupRequest *req);
+static void EndpointSetFeature(TUSBD_Handle_t *pdevice, UsbSetupRequest *req);
+
+
+/*
+ *  DEVICE REQUEST関数テーブル
+ */
+static void (*usb_pbRequestDev[NUM_MAX_REQUEST])(TUSBD_Handle_t *pdevice, UsbSetupRequest *req) = {
+	DeviceGetStatus,        DeviceClearFeature,     tusbdControlSendStall, DeviceSetFeature,
+	tusbdControlSendStall,  DeviceSetAddress,       DeviceGetDescriptor,   tusbdControlSendStall,
+	DeviceGetConfiguration, DeviceSetConfiguration, tusbdControlSendStall, tusbdControlSendStall,
+	tusbdControlSendStall
+};
+
+/*
+ *  ENDPOINT REQUEST関数テーブル
+ */
+static void (*usb_pbRequestEp[NUM_MAX_REQUEST])(TUSBD_Handle_t *pdevice, UsbSetupRequest *req) = {
+	EndpointGetStatus,      EndpointClearFeature,   tusbdControlSendStall, EndpointSetFeature,
+	tusbdControlSendStall,  tusbdControlSendStall,  tusbdControlSendStall, tusbdControlSendStall,
+	tusbdControlSendStall,  tusbdControlSendStall,  tusbdControlSendStall, tusbdControlSendStall,
+	tusbdControlSendStall
+};
+
+static uint8_t *usb_string_table[NUM_STRING_TABLE] = {
+	TUSBD_LANGUAGEID_DESCRIPTOR,
+	TUSBD_MANUFACTURER_STRING,
+	TUSBD_PRODUCT_STRING,
+	TUSBD_SERIAL_STRING,
+	TUSBD_CONFIGURATION_STRING,
+	TUSBD_INTERFACE_STRING,
+	TUSBD_USER_STRING
+};
+
+
+/*
+ *  DEVICE REQUEST GET STATUS
+ */
+static void
+DeviceGetStatus(TUSBD_Handle_t *pdevice, UsbSetupRequest *req)
+{
+	switch (pdevice->dev_state){
+	case TUSBD_STATE_ADDRESSED:
+	case TUSBD_STATE_CONFIGURED:
+		pdevice->devData[0] = TUSBD_CONFIG_SELF_POWERED;
+		pdevice->devData[1] = 0;
+		if(pdevice->dev_remote_wakeup)
+			pdevice->devData[0] |= TUSBD_CONFIG_REMOTE_WAKEUP;
+		tusbdControlSendData(pdevice, (uint8_t *)pdevice->devData, 2);
+		break;
+	default:
+		tusbdControlSendStall(pdevice, req);
+		break;
+	}
+}
+
+/*
+ *  DEVICE REQUEST CLEAR FEATURE
+ */
+static void
+DeviceClearFeature(TUSBD_Handle_t *pdevice, UsbSetupRequest *req)
+{
+	switch (pdevice->dev_state){
+	case TUSBD_STATE_ADDRESSED:
+	case TUSBD_STATE_CONFIGURED:
+		if(req->wValue == USB_FEATURE_REMOTE_WAKEUP){
+			pdevice->dev_remote_wakeup = 0;
+			tusbdClassSetup(pdevice, req);
+			tusbdControlSendStatus(pdevice);
+		}
+		break;
+	default:
+		tusbdControlSendStall(pdevice, req);
+		break;
+	}
+}
+
+/*
+ *  DEVICE REQUEST SET FEATURE
+ */
+static void
+DeviceSetFeature(TUSBD_Handle_t *pdevice, UsbSetupRequest *req)
+{
+	if(req->wValue == USB_FEATURE_REMOTE_WAKEUP){
+		pdevice->dev_remote_wakeup = 1;
+		tusbdClassSetup(pdevice, req);
+		tusbdControlSendStatus(pdevice);
+	}
+}
+
+/*
+ *  DEVICE REQUEST GET DESCRIPTOR
+ */
+static void
+DeviceGetDescriptor(TUSBD_Handle_t *pdevice, UsbSetupRequest *req)
+{
+	uint16_t len;
+	uint8_t *pbuf;
+
+	switch (req->wValue >> 8){
+#if defined(TUSBD_BOS_DESCRIPTOR)
+	case BOS_DESCRIPTOR:
+		pbuf = TUSBD_BOS_DESCRIPTOR;
+		len  = TUSBD_BOS_DESCRIPTOR[0];
+		break;
+#endif
+	case DEVICE_DESCRIPTOR:
+		pbuf = TUSBD_DEVICE_DESCRIPTOR;
+		len  = TUSBD_DEVICE_DESCRIPTOR[0];
+		break;
+	case CONFIGURATION_DESCRIPTOR:
+		if(pdevice->dev_speed == USB_DEVICE_SPEED_HIGH){
+			pbuf = TUSBD_HS_CONFIG_DESCRIPTOR;
+			len  = TUSBD_HS_CONFIG_DESC_LENGTH;
+		}
+		else{
+			pbuf = TUSBD_FS_CONFIG_DESCRIPTOR;
+			len  = TUSBD_FS_CONFIG_DESC_LENGTH;
+		}
+		break;
+	case STRING_DESCRIPTOR:
+		if(((uint8_t)req->wValue) < NUM_STRING_TABLE){
+			pbuf = usb_string_table[(uint8_t)req->wValue];
+			if(pbuf == NULL){
+				tusbdControlSendStall(pdevice, req);
+				return;
+			}
+			len  = pbuf[0];
+		}
+		else{
+			tusbdControlSendStall(pdevice, req);
+			return;
+		}
+		break;
+	case DEVICE_QUALIFIER_DESCRIPTOR:
+		if(pdevice->dev_speed == USB_DEVICE_SPEED_HIGH){
+			pbuf = TUSBD_DEVICE_QUALIFIER_DESCRIPTOR;
+			len  = TUSBD_DEVICE_QUALIFIER_DESCRIPTOR[0];
+			break;
+		}
+		else{
+			tusbdControlSendStall(pdevice, req);
+			return;
+		}
+	case OTHER_SPEED_CONFIGURATION_DESC:
+		if(pdevice->dev_speed == USB_DEVICE_SPEED_HIGH){
+			pbuf = TUSBD_OTR_CONFIG_DESCRIPTOR;
+			len  = TUSBD_OTR_CONFIG_DESC_LENGTH;
+			break;
+		}
+		else{
+			tusbdControlSendStall(pdevice, req);
+			return;
+		}
+	default:
+		tusbdControlSendStall(pdevice, req);
+		return;
+	}
+
+	if(len != 0 && req->wLength != 0){
+		if(len > req->wLength)
+			len = req->wLength;
+		tusbdControlSendData(pdevice, pbuf, len);
+	}
+}
+
+/*
+ *  DEVICE REQUEST SET ADDRESS
+ */
+static void
+DeviceSetAddress(TUSBD_Handle_t *pdevice, UsbSetupRequest *req)
+{
+	uint8_t  dev_addr; 
+
+	if(req->wIndex == 0 && req->wLength == 0){
+		dev_addr = (uint8_t)(req->wValue) & 0x7F;
+		if(pdevice->dev_state == TUSBD_STATE_CONFIGURED){
+			tusbdControlSendStall(pdevice , req);
+		}
+		else{
+			pdevice->dev_address = dev_addr;
+			tusbdDriverSetUSBAddress(pdevice, dev_addr);
+			tusbdControlSendStatus(pdevice);
+			if(dev_addr != 0){
+				pdevice->dev_state = TUSBD_STATE_ADDRESSED;
+			}
+			else{
+				pdevice->dev_state = TUSBD_STATE_INIT;
+			}
+		}
+	}
+	else{
+		tusbdControlSendStall(pdevice, req);
+	}
+}
+
+/*
+ *  DEVICE REQUEST GET CONFIGURATION
+ */
+static void
+DeviceGetConfiguration(TUSBD_Handle_t *pdevice, UsbSetupRequest *req)
+{
+	if(req->wLength != 1){
+		tusbdControlSendStall(pdevice , req);
+	}
+	else{
+		switch (pdevice->dev_state){
+		case TUSBD_STATE_ADDRESSED:
+			pdevice->devData[0] = 0;
+			tusbdControlSendData(pdevice, (uint8_t *)pdevice->devData, 1);
+			break;
+		case TUSBD_STATE_CONFIGURED:
+			pdevice->devData[0] = pdevice->dev_config;
+			tusbdControlSendData(pdevice, (uint8_t *)pdevice->devData, 1);
+			break;
+		default:
+			tusbdControlSendStall(pdevice, req);
+			break;
+		}
+	}
+}
+
+/*
+ *  DEVICE REQUEST SET CONFIGURATION
+ */
+static void
+DeviceSetConfiguration(TUSBD_Handle_t *pdevice, UsbSetupRequest *req)
+{
+	uint8_t  cfgidx;
+
+	cfgidx = (uint8_t)(req->wValue);
+	if(cfgidx > TUSBD_MAX_NUM_CONFIGURATION){
+		tusbdControlSendStall(pdevice , req);
+		return;
+	}
+
+	switch (pdevice->dev_state){
+	case TUSBD_STATE_ADDRESSED:
+		if(cfgidx){
+			pdevice->dev_config = cfgidx;
+			pdevice->dev_state = TUSBD_STATE_CONFIGURED;
+			if(tusbdClassInit(pdevice, cfgidx) != TUSBD_E_OK){
+				tusbdControlSendStall(pdevice , req);
+				return;
+			}
+			tusbdControlSendStatus(pdevice);
+		}
+		else{
+			tusbdControlSendStatus(pdevice);
+		}
+		break;
+	case TUSBD_STATE_CONFIGURED:
+		if(cfgidx == 0){
+			pdevice->dev_state = TUSBD_STATE_ADDRESSED;
+			pdevice->dev_config = cfgidx;
+			tusbdClassDeInit(pdevice, cfgidx);
+			tusbdControlSendStatus(pdevice);
+		}
+		else if(cfgidx != pdevice->dev_config){
+			/*
+			 *  古いCONFIGURATIONをリセット
+			 */
+			tusbdClassDeInit(pdevice, cfgidx);
+
+			/*
+			 *  新しいCONFIGURATIONで初期化
+			 */
+			pdevice->dev_config = cfgidx;
+			if(tusbdClassInit(pdevice, cfgidx) != TUSBD_E_OK){
+				tusbdControlSendStall(pdevice , req);
+				return;
+			}
+			tusbdControlSendStatus(pdevice);
+		}
+		else{
+			tusbdControlSendStatus(pdevice);
+		}
+		break;
+	default:
+		tusbdControlSendStall(pdevice, req);
+		break;
+	}
+}
+
+/*
+ *  ENDPOINT REQUEST GET STATUS
+ */
+static void
+EndpointGetStatus(TUSBD_Handle_t *pdevice, UsbSetupRequest *req)
+{
+	TUSBD_Endpoint_t *pep;
+	uint8_t ep_addr = req->wIndex & 0xFF;
+
+	switch (pdevice->dev_state){
+	case TUSBD_STATE_ADDRESSED:
+		if((ep_addr & 0x7F) != 0x00){
+			tusbdDriverStallEp(pdevice , ep_addr);
+		}
+		break;
+	case TUSBD_STATE_CONFIGURED:
+		pep = ((ep_addr & USB_DEVICE_TO_HOST) != 0) ? &pdevice->ep_in[ep_addr & 0x7F] : &pdevice->ep_out[ep_addr & 0x7F];
+		if(tusbdDriverStallConditionEp(pdevice, ep_addr)){
+			pep->status = 0x0001;
+		}
+		else{
+			pep->status = 0x0000;
+		}
+		tusbdControlSendData(pdevice, (uint8_t *)&pep->status, 2);
+		break;
+	default:
+		tusbdControlSendStall(pdevice, req);
+		break;
+	}
+}
+
+/*
+ *  ENDPOINT REQUEST CLEAR FEATURE
+ */
+static void
+EndpointClearFeature(TUSBD_Handle_t *pdevice, UsbSetupRequest *req)
+{
+	uint8_t ep_addr = req->wIndex & 0xFF;
+
+	switch (pdevice->dev_state){
+	case TUSBD_STATE_ADDRESSED:
+		if((ep_addr & 0x7F) != 0x00){
+			tusbdDriverStallEp(pdevice , ep_addr);
+		}
+		break;
+	case TUSBD_STATE_CONFIGURED:
+		if(req->wValue == USB_FEATURE_EP_HALT){
+			if((ep_addr & 0x7F) != 0x00){
+				tusbdDriverClearStallEp(pdevice , ep_addr);
+				tusbdClassSetup(pdevice, req);
+			}
+			tusbdControlSendStatus(pdevice);
+		}
+		break;
+	default:
+		tusbdControlSendStall(pdevice, req);
+		break;
+	}
+}
+
+/*
+ *  ENDPOINT REQUEST SET FEATURE
+ */
+static void
+EndpointSetFeature(TUSBD_Handle_t *pdevice, UsbSetupRequest *req)
+{
+	uint8_t ep_addr = req->wIndex & 0xFF;
+
+	switch (pdevice->dev_state){
+	case TUSBD_STATE_ADDRESSED:
+		if((ep_addr & 0x7F) != 0x00){
+			tusbdDriverStallEp(pdevice , ep_addr);
+		}
+		break;
+	case TUSBD_STATE_CONFIGURED:
+		if(req->wValue == USB_FEATURE_EP_HALT){
+			if((ep_addr & 0x7F) != 0x00){
+				tusbdDriverStallEp(pdevice , ep_addr);
+			}
+		}
+		tusbdClassSetup(pdevice, req);
+		tusbdControlSendStatus(pdevice);
+		break;
+	default:
+		tusbdControlSendStall(pdevice, req);
+		break;
+	}
+}
+
+
+/*
+ *  USB DEVICE初期化
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  parameter2 id:    デバイスID
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+tusbdInit(TUSBD_Handle_t *pdevice, uint8_t id)
+{
+	if(pdevice == NULL)
+		return TUSBD_E_ERR;
+
+	/*
+	 *  ハンドラ初期化
+	 */
+	pdevice->dev_state = TUSBD_STATE_INIT;
+	pdevice->id = id;
+
+	/*
+	 *  ハードウェア初期化
+	 */
+	return tusbdDriverInit(pdevice);
+}
+
+/*
+ *  USB DEVICE終了
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  return    TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+tusbdDeInit(TUSBD_Handle_t *pdevice)
+{
+	/*
+	 *  デバイス状態をリセットに
+	 */
+	pdevice->dev_state = TUSBD_STATE_RESET;
+
+	/*
+	 *  ドライバクラスを停止
+	 */
+	tusbdClassDeInit(pdevice, pdevice->dev_config);
+
+	/*
+	 *  ハードウェアを終了
+	 */
+	return tusbdDriverDeInit(pdevice);
+}
+
+/*
+ *  USB DEVICE開始
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  return    TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+tusbdStart(TUSBD_Handle_t *pdevice)
+{
+	pdevice->ep0_state = TUSBD_EP0_IDLE;
+	/*
+	 *  USB DEVICEドライバ開始
+	 */
+	return tusbdDriverStart(pdevice);
+}
+
+/*
+ *  USB DEVICE 停止
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  return    TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+tusbdStop(TUSBD_Handle_t *pdevice)
+{
+	/*
+	 *  ドライバクラス停止
+	 */
+	tusbdClassDeInit(pdevice, pdevice->dev_config);
+
+	/*
+	 *  USB DEVICEドライバ停止
+	 */
+	tusbdDriverStop(pdevice);
+	return TUSBD_E_OK;
+}
+
+
+/*
+ *  USB DEVICE EP0 SETUP STAGE処理
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  parameter2 psetup:セットアップデータ
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+tusbdSetupStage(TUSBD_Handle_t *pdevice, uint8_t *psetup)
+{
+	UsbSetupRequest  *req = &pdevice->request;
+	volatile uint8_t *p = psetup;
+
+	req->bmRequest     = p[0];
+	req->bRequest      = p[1];
+	req->wValue        = p[2] | (p[3] << 8);
+	req->wIndex        = p[4] | (p[5] << 8);
+	req->wLength       = p[6] | (p[7] << 8);
+
+	pdevice->ep0_state = TUSBD_EP0_SETUP;
+	pdevice->ep0_data_len = pdevice->request.wLength;
+
+	switch (pdevice->request.bmRequest & 0x1F){
+	case USB_RECIPIENT_DEVICE:
+		if(req->bRequest < NUM_MAX_REQUEST)
+			usb_pbRequestDev[req->bRequest](pdevice, req);
+		else
+			tusbdControlSendStall(pdevice, req);
+		break;
+	case USB_RECIPIENT_INTERFACE:
+		if(pdevice->dev_state == TUSBD_STATE_CONFIGURED){
+			if((req->wIndex & 0xFF) <= TUSBD_MAX_NUM_INTERFACES){
+				tusbdClassSetup(pdevice, req);
+				if(req->wLength == 0){
+					tusbdControlSendStatus(pdevice);
+				}
+			}
+		}
+		else
+			tusbdControlSendStall(pdevice, req);
+		break;
+	case USB_RECIPIENT_ENDPOINT:
+		if((req->bmRequest & USB_REQUEST_TYPE_MASK) == USB_REQUEST_TYPE_CLASS){
+			tusbdClassSetup(pdevice, req);
+		}
+		else{
+			if(req->bRequest < NUM_MAX_REQUEST)
+				usb_pbRequestEp[req->bRequest](pdevice, req);
+			else
+				tusbdControlSendStall(pdevice, req);
+		}
+		break;
+	default:
+		tusbdControlSendStall(pdevice, req);
+		break;
+	}
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB DEVICE DATAOUT(受信) STAGE処理
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  parameter2 epnum: エンドポイント番号
+ *  parameter3 pdata: 現在の受信データポインタ
+ *  return    TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+tusbdDataOutStage(TUSBD_Handle_t *pdevice, uint8_t epnum, uint8_t *pdata)
+{
+	if(epnum == 0){	/* エンドポイント#0 */
+		TUSBD_Endpoint_t *pep = &pdevice->ep_out[0];
+		if(pdevice->ep0_state == TUSBD_EP0_DATAOUT){
+			if(pep->remlength > pep->maxpacket){
+				pep->remlength -=  pep->maxpacket;
+				if(pep->remlength < pep->maxpacket)
+					tusbdControlContinueReceive(pdevice, pdata, pep->remlength);
+				else
+					tusbdControlContinueReceive(pdevice, pdata, pep->maxpacket);
+			}
+			else{
+				if(pdevice->dev_state == TUSBD_STATE_CONFIGURED){
+					tusbdClassEp0RxReady(pdevice);
+				}
+				tusbdControlSendStatus(pdevice);
+			}
+		}
+	}
+	else if(pdevice->dev_state == TUSBD_STATE_CONFIGURED){
+		tusbdClassDataOut(pdevice, epnum);
+	}
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB DEVICE DATAIN(送信) STAGE処理
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  parameter2 epnum: エンドポイント番号
+ *  parameter3 pdata: 現在の送信データポインタ
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+tusbdDataInStage(TUSBD_Handle_t *pdevice, uint8_t epnum, uint8_t *pdata)
+{
+	if(epnum == 0){	/* エンドポイント#0 */
+		TUSBD_Endpoint_t *pep = &pdevice->ep_in[0];
+		if(pdevice->ep0_state == TUSBD_EP0_DATAIN){
+			if(pep->remlength > pep->maxpacket){
+				pep->remlength -=  pep->maxpacket;
+				tusbdControlContinueSendData(pdevice, pdata, pep->remlength);
+				/*
+				 *  受信設定初期化
+				 */
+				tusbdDriverSetupReceive(pdevice, 0, NULL, 0);
+			}
+			else{ /* ZERO LENGTH PACKET送信処理 */
+				if((pep->xfersize % pep->maxpacket) == 0 && pep->xfersize >= pep->maxpacket
+						&& pep->xfersize < pdevice->ep0_data_len){
+					tusbdControlContinueSendData(pdevice , NULL, 0);
+					pdevice->ep0_data_len = 0;
+					/*
+					 *  受信設定初期化
+					 */
+					tusbdDriverSetupReceive(pdevice, 0, NULL, 0);
+				}
+				else{
+					if(pdevice->dev_state == TUSBD_STATE_CONFIGURED){
+						tusbdClassEp0TxSent(pdevice);
+					}
+					tusbdControlReceiveStatus(pdevice);
+				}
+			}
+		}
+		if(pdevice->dev_test_mode == 1){
+			tusbdDriverTestMode(pdevice);
+			pdevice->dev_test_mode = 0;
+		}
+	}
+	else if(pdevice->dev_state == TUSBD_STATE_CONFIGURED){
+		tusbdClassDataIn(pdevice, epnum);
+	}
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB DEVICE RESET処理
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  return    TUSBD_ERCODE
+ */
+
+TUSBD_ERCODE
+tusbdReset(TUSBD_Handle_t  *pdevice)
+{
+	/*
+	 *  エンドポイント#0 オープン
+	 */
+	tusbdDriverOpenEp(pdevice, 0x00, USB_EP_TYPE_CTRL, USB_MAX_EP0_SIZE);
+	pdevice->ep_out[0].maxpacket = USB_MAX_EP0_SIZE;
+	tusbdDriverOpenEp(pdevice, 0x80, USB_EP_TYPE_CTRL, USB_MAX_EP0_SIZE);
+	pdevice->ep_in[0].maxpacket = USB_MAX_EP0_SIZE;
+
+	/*
+	 *  デバイスユーザーステートをデフォルトに
+	 */
+	pdevice->dev_state = TUSBD_STATE_INIT;
+
+	/*
+	 *  デバイスクラスをリセット
+	 */
+	return tusbdClassDeInit(pdevice, pdevice->dev_config);
+}
+
+
+/*
+ *  USB DEVICE SETUP SPEED処理
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  parameter2 speed: デバイススピード
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+tusbdSetSpeed(TUSBD_Handle_t  *pdevice, uint8_t speed)
+{
+	pdevice->dev_speed = speed & 3;
+	if(pdevice->makeDescriptor != NULL)
+		pdevice->makeDescriptor(pdevice->dev_speed);
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB DEVICE SUSPEND REQUEST処理
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+tusbdSuspend(TUSBD_Handle_t *pdevice)
+{
+	pdevice->dev_old_state =  pdevice->dev_state;
+	pdevice->dev_state  = TUSBD_STATE_SUSPENDED;
+	tusbdClassSuspend(pdevice);
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB DEVICE RESUME REQUEST処理
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  return     TUSBD_ERCODE
+ */
+
+TUSBD_ERCODE
+tusbdResume(TUSBD_Handle_t *pdevice)
+{
+	pdevice->dev_state = pdevice->dev_old_state;
+	tusbdClassResume(pdevice);
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB DEVICE ISOIN INCOMPLETE処理
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  parameter2 epnum: エンドポイント番号
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+tusbdIsoInIncomplete(TUSBD_Handle_t *pdevice, uint8_t epnum)
+{
+	tusbdClassInIncomlete(pdevice, epnum);
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB DEVICE ISOOUT INCOMPLETE処理
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  parameter2 epnum: エンドポイント番号
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+tusbdIsoOutIncomplete(TUSBD_Handle_t *pdevice, uint8_t epnum)
+{
+	tusbdClassOutIncomlete(pdevice, epnum);
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB DEVICE CONNECTED処理
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+tusbdDeviceConnected(TUSBD_Handle_t *pdevice)
+{
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB DEVICE DISCONNECTED処理
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+tusbdDeviceDisconnected(TUSBD_Handle_t *pdevice)
+{
+	/* Free Class Resources */
+	pdevice->dev_state = TUSBD_STATE_INIT;
+	tusbdClassDeInit(pdevice, pdevice->dev_config);
+	return TUSBD_E_OK;
+}
+
+/*
+ *  USB DEVICE SEARCH DIECRIPTOR
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  parameter2 type:     検索DESCRIPTORタイプ
+ *  return     DESCRIPTORポインタ
+ */
+uint8_t *
+tusbdFindDescriptor(TUSBD_Handle_t *pdevice, uint8_t type)
+{
+	uint16_t wTotalLength;
+	uint8_t *cptr = TUSBD_FS_CONFIG_DESCRIPTOR;
+	uint8_t *dptr;
+
+    if(cptr == NULL)
+		return NULL;
+	if(cptr[0] != CONFIGURATION_DESCRIPTOR_LENGTH || cptr[1] != CONFIGURATION_DESCRIPTOR)
+		return NULL;
+
+	wTotalLength = cptr[2] | (cptr[3] << 8);
+    if(wTotalLength <= (CONFIGURATION_DESCRIPTOR_LENGTH+2))
+		return NULL;
+
+	dptr = cptr + CONFIGURATION_DESCRIPTOR_LENGTH;
+    do{
+		if(dptr[1] == type)
+			return dptr;
+		dptr += dptr[0];	/* bLength */
+	}while(dptr < (cptr + wTotalLength));
+    return NULL;
+}
+
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/tusbd_base.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/tusbd_base.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/tusbd_base.h	(revision 453)
@@ -0,0 +1,183 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2017 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  USB Device Middleware BASE部定義
+ */
+
+#ifndef _TUSBD_BASE_H_
+#define _TUSBD_BASE_H_
+
+#include "tusb_rtos.h"
+#include "tusb_types.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#ifndef TUSBD_NUM_ENDPOINT
+#define TUSBD_NUM_ENDPOINT                    15
+#endif
+
+#define USB_REQUEST_TYPE_MASK                 0x60
+
+#define TUSBD_CONFIG_REMOTE_WAKEUP            0x02
+
+#define USB_FEATURE_EP_HALT                   0
+#define USB_FEATURE_REMOTE_WAKEUP             1
+#define USB_FEATURE_TEST_MODE                 2
+
+
+
+#define USB_HS_MAX_PACKET_SIZE                512
+#define USB_FS_MAX_PACKET_SIZE                64
+#define USB_MAX_EP0_SIZE                      USB_FS_MAX_PACKET_SIZE
+
+/*
+ *  デバイス状態定義
+ */
+#define TUSBD_STATE_RESET                     0		/* 未実行状態 */
+#define TUSBD_STATE_INIT                      1		/* 初期化状態 */
+#define TUSBD_STATE_ADDRESSED                 2		/* アドレス設定済み状態 */
+#define TUSBD_STATE_CONFIGURED                3		/* エナミュレーション終了状態 */
+#define TUSBD_STATE_SUSPENDED                 4		/* サスペンド状態 */
+
+/*
+ *  エンドポイント#0状態
+ */
+#define TUSBD_EP0_IDLE                        0		/* アイドル状態 */
+#define TUSBD_EP0_SETUP                       1		/* SETUP状態 */
+#define TUSBD_EP0_DATAIN                      2		/* DATAIN状態 */
+#define TUSBD_EP0_DATAOUT                     3		/* DATAOUT状態 */
+#define TUSBD_EP0_STATUSIN                    4		/* STATUSIN状態 */
+#define TUSBD_EP0_STATUSOUT                   5		/* STATUSOUT状態 */
+
+/* bmAttributes in configuration descriptor */
+/* C_RESERVED must always be set */
+#define C_RESERVED                            (1<<7)
+#define C_SELF_POWERED                        (1<<6)
+#define C_REMOTE_WAKEUP                       (1<<5)
+
+/* bMaxPower in configuration descriptor */
+#define C_POWER(mA)                           ((mA)/2)
+
+/*
+ *  エンドポイント管理型
+ */
+typedef struct
+{
+	uint16_t                   status;
+	uint16_t                   maxpacket;
+	uint32_t                   xfersize;
+	uint32_t                   remlength;
+} TUSBD_Endpoint_t;
+
+/*
+ *  USBデバイスハンドラ
+ */
+typedef struct
+{
+	uint8_t                    devData[32];
+	uint8_t                    id;
+	uint8_t                    dev_speed;
+	uint8_t                    dev_address;
+	uint8_t                    dev_config;
+	uint8_t                    dev_test_mode;
+	uint8_t                    dev_remote_wakeup;
+	uint8_t                    ep0_state;
+	uint16_t                   ep0_data_len;
+	uint8_t                    dev_state;
+	uint8_t                    dev_old_state;
+	TUSBD_Endpoint_t           ep_in[TUSBD_NUM_ENDPOINT];
+	TUSBD_Endpoint_t           ep_out[TUSBD_NUM_ENDPOINT];
+
+	UsbSetupRequest            request;
+	void                       *pClassData;
+	void                       *pSysData;
+	void                       *pUsrData;
+	void                       (*makeDescriptor)(uint8_t speed);
+} TUSBD_Handle_t;
+
+#include "tusbd_conf.h"
+
+#ifndef MAX_PACKET_SIZE_HS_EPBULK
+#define MAX_PACKET_SIZE_HS_EPBULK             512
+#endif
+#ifndef MAX_PACKET_SIZE_FS_EPBULK
+#define MAX_PACKET_SIZE_FS_EPBULK             64
+#endif
+
+
+/*
+ *  関数プロトタイプ宣言
+ */
+TUSBD_ERCODE tusbdInit(TUSBD_Handle_t *pdevice, uint8_t id);
+TUSBD_ERCODE tusbdDeInit(TUSBD_Handle_t *pdevice);
+TUSBD_ERCODE tusbdStart(TUSBD_Handle_t *pdevice);
+TUSBD_ERCODE tusbdStop(TUSBD_Handle_t *pdevice);
+
+TUSBD_ERCODE tusbdSetupStage(TUSBD_Handle_t *pdevice, uint8_t *psetup);
+TUSBD_ERCODE tusbdDataOutStage(TUSBD_Handle_t *pdevice, uint8_t epnum, uint8_t *pdata);
+TUSBD_ERCODE tusbdDataInStage(TUSBD_Handle_t *pdevice, uint8_t epnum, uint8_t *pdata);
+
+TUSBD_ERCODE tusbdReset(TUSBD_Handle_t *pdevice);
+TUSBD_ERCODE tusbdSetSpeed(TUSBD_Handle_t *pdevice, uint8_t speed);
+TUSBD_ERCODE tusbdSuspend(TUSBD_Handle_t *pdevice);
+TUSBD_ERCODE tusbdResume(TUSBD_Handle_t *pdevice);
+TUSBD_ERCODE tusbdIsoInIncomplete(TUSBD_Handle_t *pdevice, uint8_t epnum);
+TUSBD_ERCODE tusbdIsoOutIncomplete(TUSBD_Handle_t *pdevice, uint8_t epnum);
+
+TUSBD_ERCODE tusbdDeviceConnected(TUSBD_Handle_t *pdevice);
+TUSBD_ERCODE tusbdDeviceDisconnected(TUSBD_Handle_t *pdevice);
+
+TUSBD_ERCODE tusbdControlSendData(TUSBD_Handle_t *pdevice, uint8_t *buf, uint16_t len);
+TUSBD_ERCODE tusbdControlReceiveStart(TUSBD_Handle_t *pdevice, uint8_t *pbuf, uint16_t len);
+TUSBD_ERCODE tusbdControlSendStatus(TUSBD_Handle_t *pdevice);
+TUSBD_ERCODE tusbdControlReceiveStatus(TUSBD_Handle_t *pdevice);
+void         tusbdControlSendStall(TUSBD_Handle_t *pdevice, UsbSetupRequest *req);
+
+#define tusbdControlContinueSendData(d, b, l)   tusbdDriverStartTransmit((d), 0x00, (b), (l))
+#define tusbdControlContinueReceive(d, b, l) tusbdDriverSetupReceive((d), 0x00, (b), (l))
+
+uint8_t      *tusbdFindDescriptor(TUSBD_Handle_t *pdevice, uint8_t type);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TUSBD_BASE_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/tusbd_request.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/tusbd_request.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/device/tusbd_request.c	(revision 453)
@@ -0,0 +1,115 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2017 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  USB Device Middleware REQUEST部
+ */
+
+#include "tusbd_base.h"
+
+
+/*
+ *  USB DEVICE コントロール通信 送信開始
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  parameter2 pbuf:     送信バッファ
+ *  parameter3 len:      送信データ長
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+tusbdControlSendData(TUSBD_Handle_t *pdevice, uint8_t *pbuf, uint16_t len)
+{
+	pdevice->ep0_state          = TUSBD_EP0_DATAIN;
+	pdevice->ep_in[0].xfersize  = len;
+	pdevice->ep_in[0].remlength = len;
+	return tusbdDriverStartTransmit(pdevice, 0x00, pbuf, len);
+}
+
+/*
+ *  USB DEVICE コントロール通信 受信開始
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  parameter2 pbuf:     受信バッファ
+ *  parameter3 len:      受信データ長
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+tusbdControlReceiveStart(TUSBD_Handle_t *pdevice, uint8_t *pbuf, uint16_t len)
+{
+	pdevice->ep0_state = TUSBD_EP0_DATAOUT; 
+	pdevice->ep_out[0].xfersize  = len;
+	pdevice->ep_out[0].remlength = len;
+	return tusbdDriverSetupReceive(pdevice, 0, pbuf, len);
+}
+
+/*
+ *  USB DEVICE コントロール通信 ステータス送信
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+tusbdControlSendStatus(TUSBD_Handle_t *pdevice)
+{
+	pdevice->ep0_state = TUSBD_EP0_STATUSIN;
+	return tusbdDriverStartTransmit(pdevice, 0x00, NULL, 0);
+}
+
+/*
+ *  USB DEVICE コントロール通信 ステータス受信
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  return     TUSBD_ERCODE
+ */
+TUSBD_ERCODE
+tusbdControlReceiveStatus(TUSBD_Handle_t *pdevice)
+{
+	pdevice->ep0_state = TUSBD_EP0_STATUSOUT;
+	return tusbdDriverSetupReceive(pdevice, 0, NULL, 0);
+}
+
+/*
+ *  USB DEVICE コントロール通信 STALL送信
+ *  parameter1 pdevice:  USB DEVICEハンドラ
+ *  parameter2 req:      セットアップリクエスト
+ *  return     TUSBD_ERCODE
+ */
+
+void
+tusbdControlSendStall(TUSBD_Handle_t *pdevice, UsbSetupRequest *req)
+{
+	pdevice->ep0_state = TUSBD_EP0_IDLE;
+	tusbdDriverStallEp(pdevice, req->bmRequest & 0x80);
+}
+
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/BLUETOOTH/tusbh_bluetooth.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/BLUETOOTH/tusbh_bluetooth.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/BLUETOOTH/tusbh_bluetooth.c	(revision 453)
@@ -0,0 +1,493 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  USB Host Middleware BLUETOOTH CLASS部
+ */
+
+#include "tusbh_bluetooth.h"
+
+#define BLUETOOTH_SENDDATA(d, b, l)   tusbhControlRequest((d), (b), BLUETOOTH_DATA_TYPE, 0, 0, 0, (l))
+#define ORDER_MASK  (BT_INTERRUPT_ORDER | BT_CTLWRITE_ORDER | BT_BLKREAD_ORDER | BT_BLKWRITE_ORDER)
+
+static TUSBH_ERCODE tusbhBLUETOOTHInit(TUSBH_Device_t *pdevice);
+static TUSBH_ERCODE tusbhBLUETOOTHeInit(TUSBH_Device_t *pdevice);
+static TUSBH_ERCODE tusbhBLUETOOTHProcess(TUSBH_Device_t *pdevice, uint8_t *mes);
+
+static TUSBH_Class_t BLUETOOTH_Class = {
+	NULL,
+	"BLUETOOTH",
+	BLUETOOTH_CLASS,
+	tusbhBLUETOOTHInit,
+	tusbhBLUETOOTHeInit,
+	tusbhBLUETOOTHProcess,
+	NULL
+};
+
+/*
+ *  SERIALクラスセットアップ関数
+ */
+void tusbhLinkBLUETOOTH(TUSBH_Handle_t *phost)
+{
+	tusbhLinkClass(phost, &BLUETOOTH_Class);
+}
+
+/*
+ *  BLUETOOTHクラス初期設定
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  return     TUSBH_ERCODE
+ */
+static TUSBH_ERCODE
+tusbhBLUETOOTHInit(TUSBH_Device_t *pdevice)
+{
+	uint8_t interface = 0; 
+	BLUETOOTH_Handle_t *hblue;
+	TUSBH_Handle_t *phost = pdevice->pHost;
+	uint8_t max_ep, i;
+
+	interface = tusbhFindInterface(pdevice, pdevice->pClass->classCode, 0x01, 0x01);
+
+	if(interface == NO_INTERFACE){
+		syslog_1(LOG_ERROR, "[BLUETOOTH] Cannot Find the interface for %s class.", pdevice->pClass->Name);
+		return TUSBH_E_ERR;
+	}
+	tusbhSelectInterface(pdevice, interface);
+
+	hblue = (BLUETOOTH_Handle_t *)tusbmalloc(sizeof(BLUETOOTH_Handle_t));
+	pdevice->pData = hblue;
+	memset(hblue, 0, sizeof(BLUETOOTH_Handle_t));
+	max_ep = pdevice->ItfDesc[interface].bNumEndpoints;
+	if(max_ep < 3 || (pdevice->EpDesc[interface][0].bEndpointAddress & 0x80) == 0)
+		return TUSBH_E_ERR;
+
+	hblue->CommInEp     = pdevice->EpDesc[interface][0].bEndpointAddress;
+    hblue->CommInEpSize = pdevice->EpDesc[interface][0].wMaxPacketSize;
+	hblue->CommInPipe   = tusbhAllocPipe(phost, hblue->CommInEp);
+	hblue->poll         = pdevice->EpDesc[interface][0].bInterval;
+
+	if(hblue->poll < BT_MIN_POLL)
+		hblue->poll = BT_MIN_POLL;
+
+	for(i = 1 ; i < max_ep; i++){
+		if(pdevice->EpDesc[interface][i].bEndpointAddress & 0x80){
+			hblue->InEp     = (pdevice->EpDesc[interface][i].bEndpointAddress);
+			hblue->InEpSize = pdevice->EpDesc[interface][i].wMaxPacketSize;
+			hblue->InPipe = tusbhAllocPipe(phost, hblue->InEp);
+		}
+		else{
+			hblue->OutEp = (pdevice->EpDesc[interface][i].bEndpointAddress);
+			hblue->OutEpSize = pdevice->EpDesc[interface][i].wMaxPacketSize;
+			hblue->OutPipe = tusbhAllocPipe(phost, hblue->OutEp);
+		}
+	}
+
+	if(hblue->OutPipe == 0 || hblue->InPipe == 0)
+		return TUSBH_E_ERR;
+
+	hblue->state = BLUETOOTH_PROCESS_INIT;
+	hblue->timer = 0;
+	hblue->pDev = pdevice;
+
+	/*
+	 *  NSCチャネルオープン
+	 */
+	tusbhOpenPipe(pdevice, hblue->CommInPipe, hblue->CommInEp, USB_EP_TYPE_INTR, 64);
+	tusbhHDSetToggle(phost, hblue->CommInPipe, 0);
+	tusbhOpenPipe(pdevice, hblue->OutPipe, hblue->OutEp, USB_EP_TYPE_BULK, hblue->OutEpSize);
+	tusbhHDSetToggle(phost, hblue->OutPipe, 0);
+	tusbhOpenPipe(pdevice, hblue->InPipe, hblue->InEp, USB_EP_TYPE_BULK, hblue->InEpSize);
+	tusbhHDSetToggle(phost, hblue->InPipe, 0);
+
+	/* タイマースタート */
+	pdevice->timeid = pdevice->timecount = hblue->poll;
+	return TUSBH_E_OK;
+}
+
+/*
+ *  BLUETOOTHクラス終了設定
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  return     TUSBH_ERCODE
+ */
+static TUSBH_ERCODE
+tusbhBLUETOOTHeInit(TUSBH_Device_t *pdevice)
+{
+	BLUETOOTH_Handle_t *hblue;
+	TUSBH_Handle_t *phost = pdevice->pHost;
+
+	hblue = (BLUETOOTH_Handle_t *)pdevice->pData;
+	hblue->ifstate  &= ~ORDER_MASK;
+	if(hblue->CommInPipe != 0){
+		tusbhClosePipe(pdevice, hblue->CommInPipe);
+		tusbFreePipe(phost, hblue->CommInPipe);
+		hblue->CommInPipe = 0;
+	}
+
+	if(hblue->OutPipe != 0){
+		tusbhClosePipe(pdevice, hblue->OutPipe);
+		tusbFreePipe(phost, hblue->OutPipe);
+		hblue->OutPipe = 0;
+	}
+
+	if(hblue->InPipe != 0){
+		tusbhClosePipe(pdevice, hblue->InPipe);
+		tusbFreePipe(phost, hblue->InPipe);
+		hblue->InPipe = 0;
+	}
+
+	if(pdevice->pData != NULL){
+		tusbfree(pdevice->pData);
+		pdevice->pData = NULL;
+	}
+	return TUSBH_E_OK;
+}
+
+/*
+ *  BLUETOOTHクラスプロセス実行
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  parameter2 mes:      通信メッセージへのポインタ
+ *  return     TUSBH_ERCODE
+ */
+static TUSBH_ERCODE
+tusbhBLUETOOTHProcess(TUSBH_Device_t *pdevice, uint8_t *mes)
+{
+	BLUETOOTH_Handle_t *hblue  = (BLUETOOTH_Handle_t *)pdevice->pData;
+	TUSBH_Handle_t *phost = pdevice->pHost;
+	void (*func)(TUSBH_Device_t *, uint8_t, int16_t, uint8_t *) = pdevice->pClass->subfunc;
+	TUSBH_URBState_t URB_Status = mes[3];
+	TUSBH_ERCODE ercd = TUSBH_E_BUSY;
+	uint8_t mesreq = 0;
+	bool_t  timereq = false;
+
+	if(mes[0] == TUSBH_TIME_EVENT){
+		hblue->timer += mes[3];
+		pdevice->timeid = pdevice->timecount = hblue->poll;
+		timereq = true;
+	}
+	else if(mes[0] == TUSBH_CLASS_EVENT && mes[2] != 0)
+		hblue->state = mes[2];
+	switch (hblue->state){
+	case BLUETOOTH_PROCESS_INIT:
+		if(phost->usrcallback != NULL)
+			phost->usrcallback(phost, pdevice, HOST_USER_CLASS_ACTIVE);
+		hblue->state = BLUETOOTH_PROCESS_IDLE;
+	case BLUETOOTH_PROCESS_IDLE:
+		if(timereq && (hblue->ifstate & (BT_INTERRUPT_ORDER | BT_INTERRUPT_REQUEST)) == BT_INTERRUPT_ORDER){
+			tusbhInterruptRead(pdevice, &hblue->CommInBuf[0], hblue->CommInEpSize, hblue->CommInPipe);
+			hblue->ifstate |= BT_INTERRUPT_REQUEST;
+		}
+		if(mes[0] != TUSBH_URB_EVENT)
+			break;
+		if(mes[2] == hblue->CommInPipe){	/* interrupt */
+			if(URB_Status == TUSBH_URB_DONE){
+				if(func != NULL)
+					func(pdevice, HCI_EVENT_PACKET, hblue->CommInEpSize, &hblue->CommInBuf[0]);
+				hblue->ifstate &= ~BT_INTERRUPT_REQUEST;
+			}
+			else if(URB_Status == TUSBH_URB_STALL)
+				hblue->state = BLUETOOTH_PROCESS_ERROR;
+			else
+				hblue->ifstate &= ~BT_INTERRUPT_REQUEST;
+		}
+		else if(mes[2] == hblue->InPipe){	/* blk read */
+			if(URB_Status == TUSBH_URB_DONE){
+				if(func != NULL)
+					func(pdevice, HCI_ACL_DATA_PACKET, tusbhHDTrasLength(phost, hblue->InPipe), hblue->pBRecvBuff);
+			}
+			else if(URB_Status == TUSBH_URB_NOTREADY){
+				hblue->ifstate |= BT_BLKREAD_ORDER;
+				mesreq = BLUETOOTH_PROCESS_RECEIVE;
+			}
+			else if(URB_Status == TUSBH_URB_STALL)
+				hblue->state = BLUETOOTH_PROCESS_ERROR;
+			else{
+				if(func != NULL)
+					func(pdevice, HCI_ACL_DATA_PACKET, -1, hblue->pBRecvBuff);
+			}
+			hblue->ifstate &= ~BT_BLKREAD_REQUEST;
+		}
+		else if(mes[2] == hblue->OutPipe){	/* blk write */
+			if(URB_Status == TUSBH_URB_DONE){
+				hblue->BTrnLen += hblue->BTrnCLen;
+				if(hblue->BTrnLen >= hblue->BTrnSize){
+					if(func != NULL)
+						func(pdevice, HCI_SCO_DATA_PACKET, hblue->BTrnSize, NULL);
+					if((hblue->ifstate & (BT_CTLWRITE_ORDER | BT_CTLWRITE_REQUEST)) == BT_CTLWRITE_ORDER)
+						mesreq = BLUETOOTH_PROCESS_SEND;
+				}
+				else{
+					hblue->ifstate |= BT_BLKWRITE_ORDER;
+					mesreq = BLUETOOTH_PROCESS_SEND;
+				}
+			}
+			else if(URB_Status == TUSBH_URB_NOTREADY){
+				hblue->ifstate |= BT_BLKWRITE_ORDER;
+				mesreq = BLUETOOTH_PROCESS_SEND;
+			}
+			else if(URB_Status == TUSBH_URB_STALL)
+				hblue->state = BLUETOOTH_PROCESS_ERROR;
+			else{
+				if(func != NULL)
+					func(pdevice, HCI_SCO_DATA_PACKET, 0, NULL);
+				if((hblue->ifstate & (BT_CTLWRITE_ORDER | BT_CTLWRITE_REQUEST)) == BT_CTLWRITE_ORDER)
+					mesreq = BLUETOOTH_PROCESS_SEND;
+			}
+			hblue->ifstate &= ~BT_BLKWRITE_REQUEST;
+		}
+		else{								/* control write */
+			TUSBH_ERCODE status = tusbhControlWait(pdevice, mes);
+			if(status == TUSBH_E_OK){
+				hblue->ifstate &= ~BT_CTLWRITE_REQUEST;
+				if(func != NULL)
+					func(pdevice, HCI_COMMAND_DATA_PACKET, hblue->CTrnSize, hblue->pCTrnBuff);
+				if((hblue->ifstate & BT_INTERRUPT_STOP) == 0)
+					hblue->ifstate  |= BT_INTERRUPT_ORDER;
+				if((hblue->ifstate & (BT_BLKWRITE_ORDER | BT_BLKWRITE_REQUEST)) == BT_BLKWRITE_ORDER)
+					mesreq = BLUETOOTH_PROCESS_SEND;
+			}
+			else if(status != TUSBH_E_BUSY && status != TUSBH_E_BUSY_URB){
+				hblue->state = BLUETOOTH_PROCESS_ERROR;
+				hblue->ifstate  &= ~BT_CTLWRITE_REQUEST;
+			}
+		}
+		tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, mesreq, 0);
+		break;
+	case BLUETOOTH_PROCESS_SEND:
+		if((hblue->ifstate & (BT_CTLWRITE_ORDER | BT_CTLWRITE_REQUEST | BT_BLKWRITE_REQUEST)) == BT_CTLWRITE_ORDER){
+			BLUETOOTH_SENDDATA(pdevice, hblue->pCTrnBuff, hblue->CTrnSize);
+			hblue->ifstate |= BT_CTLWRITE_REQUEST;
+			hblue->ifstate &= ~BT_CTLWRITE_ORDER;
+		}
+		if((hblue->ifstate & (BT_BLKWRITE_ORDER | BT_BLKWRITE_REQUEST | BT_CTLWRITE_REQUEST)) == BT_BLKWRITE_ORDER){
+			hblue->BTrnCLen = hblue->BTrnSize - hblue->BTrnLen;
+			if(hblue->BTrnCLen > hblue->OutEpSize)
+				hblue->BTrnCLen = hblue->OutEpSize;
+			tusbhBulkWrite(pdevice, &hblue->pBTrnBuff[hblue->BTrnLen], hblue->BTrnCLen, hblue->OutPipe);
+			hblue->ifstate |= BT_BLKWRITE_REQUEST;
+			hblue->ifstate &= ~BT_BLKWRITE_ORDER;
+		}
+		hblue->state = BLUETOOTH_PROCESS_IDLE;
+		break;
+	case BLUETOOTH_PROCESS_RECEIVE:
+		if((hblue->ifstate & (BT_BLKREAD_ORDER | BT_BLKREAD_REQUEST)) == BT_BLKREAD_ORDER){
+			tusbhBulkRead(pdevice, hblue->pBRecvBuff, hblue->BRecvSize, hblue->InPipe);
+			hblue->ifstate &= ~BT_BLKREAD_ORDER;
+			hblue->ifstate |= BT_BLKREAD_REQUEST;
+		}
+		hblue->state = BLUETOOTH_PROCESS_IDLE;
+		break;
+	case BLUETOOTH_PROCESS_ERROR:
+		break;
+	default:
+		break;
+	}
+	return ercd;
+}
+
+
+/*
+ *  BLUETOOTH TRANSFAR READY
+ *  parameter1 phost:   ホストハンドラ
+ *  parameter2 unit:    UNIT#
+ *  parameter3 mode:    確認モード
+ *  return     bool
+ */
+bool_t
+tusbhBluetoothTransfarReady(TUSBH_Handle_t *phost, uint8_t unit, uint8_t mode)
+{
+	TUSBH_Device_t *pdevice = tusbhSearchDevice(phost, BLUETOOTH_Class.classCode, &unit);
+	BLUETOOTH_Handle_t *hblue;
+	bool_t result = false;
+
+	if(pdevice != NULL){
+		hblue = pdevice->pData;
+		if(pdevice->dstate != DEVICE_CLASS)
+			return false;
+		if(hblue->state == BLUETOOTH_PROCESS_ERROR)
+			return false;
+	}
+	else
+		return false;
+	switch(mode){
+	case HCI_COMMAND_DATA_PACKET:
+		result = (hblue->ifstate & (BT_CTLWRITE_ORDER | BT_CTLWRITE_REQUEST)) == 0;
+		break;
+	case HCI_ACL_DATA_PACKET:
+		result = (hblue->ifstate & (BT_BLKREAD_ORDER | BT_BLKREAD_REQUEST)) == 0;
+		break;
+	case HCI_SCO_DATA_PACKET:
+		result = (hblue->ifstate & (BT_BLKWRITE_ORDER | BT_BLKWRITE_REQUEST)) == 0;
+		break;
+	case HCI_EVENT_PACKET:
+		result = (hblue->ifstate & BT_INTERRUPT_REQUEST) == 0;
+		break;
+	default:
+		break;
+	}
+	return result;
+}
+
+/*
+ *  BLUETOOTH INTERRUPT POLL TIMING
+ *  parameter1 phost:   ホストハンドラ
+ *  parameter2 unit:    UNIT#
+ *  parameter3 mode:    確認モード
+ *  return     bool
+ */
+TUSBH_ERCODE
+tusbhBluetoothInterruptPollTiming(TUSBH_Handle_t *phost, uint8_t unit, uint32_t timing)
+{
+	TUSBH_Device_t *pdevice = tusbhSearchDevice(phost, BLUETOOTH_Class.classCode, &unit);
+	BLUETOOTH_Handle_t *hblue;
+
+	if(pdevice != NULL){
+		hblue = pdevice->pData;
+		if(pdevice->dstate != DEVICE_CLASS)
+			return TUSBH_E_OBJ;
+		if(hblue->state == BLUETOOTH_PROCESS_ERROR)
+			return TUSBH_E_ERR;
+	}
+	else
+		return TUSBH_E_OBJ;
+	if(timing == 0){
+		hblue->ifstate |= BT_INTERRUPT_STOP;
+		hblue->ifstate &= ~BT_INTERRUPT_ORDER;
+	}
+	else{
+		if(timing < BT_MIN_POLL)
+			hblue->poll = BT_MIN_POLL;
+		else
+			hblue->poll = timing;
+		hblue->ifstate &= ~BT_INTERRUPT_STOP;
+		hblue->ifstate |= BT_INTERRUPT_ORDER;
+	}
+	return TUSBH_E_OK;
+}
+
+/*
+ *  BLUETOOTH DATA SEND
+ *  parameter1 phost:   ホストハンドラ
+ *  parameter2 unit:    UNIT#
+ *  parameter3 mode:    パケットタイプ
+ *  parameter4 pbuf:    送信データ領域へのポインタ(cache aline)
+ *  parameter5 length:  送信データ長
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+tusbhBluetoothSend(TUSBH_Handle_t *phost, uint8_t unit, uint8_t mode, uint8_t *pbuf, uint16_t length)
+{
+	TUSBH_Device_t *pdevice = tusbhSearchDevice(phost, BLUETOOTH_Class.classCode, &unit);
+	BLUETOOTH_Handle_t *hblue;
+
+	if(pdevice != NULL){
+		hblue = pdevice->pData;
+		if(pdevice->dstate != DEVICE_CLASS)
+			return TUSBH_E_OBJ;
+		if(hblue->state == BLUETOOTH_PROCESS_ERROR)
+			return TUSBH_E_ERR;
+	}
+	else
+		return TUSBH_E_OBJ;
+
+    /*
+	 *  送信データ設定
+	 */
+	if(mode == HCI_COMMAND_DATA_PACKET){
+		if(length > BT_CONTROL_SIZE)
+			return TUSBH_E_PAR;
+		if((hblue->ifstate & BT_CTLWRITE_ORDER) != 0)
+			return TUSBH_E_OBJ;
+		hblue->CTrnSize  = length;
+		hblue->pCTrnBuff = pbuf;
+		hblue->ifstate |= BT_CTLWRITE_ORDER;
+	}
+	else if(mode == HCI_SCO_DATA_PACKET){
+		if((hblue->ifstate & BT_BLKWRITE_ORDER) != 0)
+			return TUSBH_E_OBJ;
+		hblue->BTrnSize   = length;
+		hblue->BTrnLen    = 0;
+		hblue->BTrnCLen   = 0;
+		hblue->pBTrnBuff  = pbuf;
+		hblue->ifstate |= BT_BLKWRITE_ORDER;
+	}
+	else
+		return TUSBH_E_PAR;
+	tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, BLUETOOTH_PROCESS_SEND, 0);
+	return TUSBH_E_OK;
+}
+
+/*
+ *  BLUETOOTH RECEIVE BULK IN
+ *  parameter1 phost:   ホストハンドラ
+ *  parameter2 unit:    UNIT#
+ *  parameter3 pbuf:    受信データ領域へのポインタ(cache aline)
+ *  parameter4 length:  受信データ長
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+tusbhBluetoothReceiveBulk(TUSBH_Handle_t *phost, uint8_t unit, uint8_t *pbuf, uint16_t length)
+{
+	TUSBH_Device_t *pdevice = tusbhSearchDevice(phost, BLUETOOTH_Class.classCode, &unit);
+	BLUETOOTH_Handle_t *hblue;
+
+	if(pdevice != NULL){
+		hblue = pdevice->pData;
+		if(pdevice->dstate != DEVICE_CLASS)
+			return TUSBH_E_OBJ;
+	}
+	else
+		return TUSBH_E_OBJ;
+	if(length < hblue->InEpSize)
+		return TUSBH_E_PAR;
+	hblue->BRecvSize  = length;
+	hblue->pBRecvBuff = pbuf;
+	hblue->ifstate |= BT_BLKREAD_ORDER;
+	tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, BLUETOOTH_PROCESS_RECEIVE, 0);
+	return TUSBH_E_OK;
+}
+
+/*
+ *  BLUETOOTHコールバック関数
+ *  parameter1 phost:   ホストハンドラ
+ *  parameter2 func:    関数ポインタ
+ */
+void
+tusbhSetBluetoothCallBack(TUSBH_Handle_t *phost, void (*func)(TUSBH_Device_t *p, uint8_t, int16_t, uint8_t *))
+{
+	BLUETOOTH_Class.subfunc = func;
+}
+
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/BLUETOOTH/tusbh_bluetooth.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/BLUETOOTH/tusbh_bluetooth.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/BLUETOOTH/tusbh_bluetooth.h	(revision 453)
@@ -0,0 +1,140 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  USB Host Middleware BLUETOOTH部定義
+ */
+
+#ifndef _HUSBH_BLUETOOTH_H_
+#define _HUSBH_BLUETOOTH_H_
+
+#include "tusbh_base.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+#define BLUETOOTH_DATA_TYPE             (USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_DEVICE)
+
+
+#define HCI_COMMAND_DATA_PACKET         0x01
+#define HCI_ACL_DATA_PACKET             0x02
+#define HCI_SCO_DATA_PACKET             0x03
+#define HCI_EVENT_PACKET                0x04
+
+/*
+ *  BLUETOOTHクラスの状態定義
+ */
+#define BT_INTERRUPT_REQUEST            (1<<0)
+#define BT_CTLWRITE_REQUEST             (1<<1)
+#define BT_BLKREAD_REQUEST              (1<<2)
+#define BT_BLKWRITE_REQUEST             (1<<3)
+
+#define BT_INTERRUPT_ORDER              (1<<8)
+#define BT_CTLWRITE_ORDER               (1<<9)
+#define BT_BLKREAD_ORDER                (1<<10)
+#define BT_BLKWRITE_ORDER               (1<<11)
+#define BT_INTERRUPT_STOP               (1<<12)
+
+#ifndef BT_MIN_POLL
+#define BT_MIN_POLL                     20
+#endif
+
+#define BT_CONTROL_SIZE                 64
+
+/*
+ *  BLUETOOTHプロセスの状態定義
+ */
+enum
+{
+	BLUETOOTH_PROCESS_INIT = 0,
+	BLUETOOTH_PROCESS_IDLE,
+	BLUETOOTH_PROCESS_SEND,
+	BLUETOOTH_PROCESS_RECEIVE,
+	BLUETOOTH_PROCESS_ERROR
+};
+
+/*
+ *  BLUTOOTHハンドラ定義
+ */
+typedef struct
+{
+	TUSBH_Device_t            *pDev;
+
+	uint8_t                   state;
+	uint8_t                   poll;
+	uint16_t                  ifstate;
+
+	uint8_t                   CommInPipe;
+	uint8_t                   CommInEp;
+	uint16_t                  CommInEpSize;
+	uint8_t                   InPipe;
+	uint8_t                   OutPipe;
+	uint8_t                   OutEp;
+	uint8_t                   InEp;
+	uint16_t                  OutEpSize;
+	uint16_t                  InEpSize;
+	uint16_t                  CTrnSize;
+	uint16_t                  BTrnSize;
+	uint16_t                  BTrnLen;
+	uint16_t                  BTrnCLen;
+	uint16_t                  BRecvSize;
+	uint16_t                  dummy;
+
+	uint8_t                   CommInBuf[BT_CONTROL_SIZE];
+	uint8_t                   *pBRecvBuff;
+	uint8_t                   *pBTrnBuff;
+	uint8_t                   *pCTrnBuff;
+	uint32_t                  timer;
+} BLUETOOTH_Handle_t;
+
+
+void         tusbhLinkBLUETOOTH(TUSBH_Handle_t *phost);
+bool_t       tusbhBluetoothTransfarReady(TUSBH_Handle_t *phost, uint8_t unit, uint8_t mode);
+TUSBH_ERCODE tusbhBluetoothInterruptPollTiming(TUSBH_Handle_t *phost, uint8_t unit, uint32_t timing);
+TUSBH_ERCODE tusbhBluetoothSend(TUSBH_Handle_t *phost, uint8_t unit, uint8_t mode, uint8_t *pbuf, uint16_t length);
+TUSBH_ERCODE tusbhBluetoothReceiveBulk(TUSBH_Handle_t *phost, uint8_t unit, uint8_t *pbuf, uint16_t length);
+void tusbhSetBluetoothCallBack(TUSBH_Handle_t *phost, void (*func)(TUSBH_Device_t *p, uint8_t, int16_t, uint8_t *));
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HUSBH_BLUETOOTH_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/HID/tusbh_hid.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/HID/tusbh_hid.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/HID/tusbh_hid.c	(revision 453)
@@ -0,0 +1,402 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2017 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  USB Host Middleware HID CLASS部
+ */
+
+#include "tusbh_hid.h"
+
+
+#define HID_SETIDLE(d, dur, rep)     tusbhControlRequest((d), NULL, HID_SET_TYPE, USB_HID_SET_IDLE, ((dur << 8) | (rep)), 0, 0)
+#define HID_SETPROTOCOL(d, p)        tusbhControlRequest((d), NULL, HID_SET_TYPE, USB_HID_SET_PROTOCOL, (((p) != 0) ? 0 : 1), 0, 0)
+#define HID_GETREPORT(d, t, i, b, l) tusbhControlRequest((d), (b), HID_GET_TYPE, USB_HID_GET_REPORT, ((t << 8 ) | i), 0, (l))
+#define HID_SETREPORT(d, t, i, b, l) tusbhControlRequest((d), (b), HID_SET_TYPE, USB_HID_SET_REPORT, ((t << 8 ) | i), 0, (l))
+
+static TUSBH_ERCODE tusbhHIDInit(TUSBH_Device_t *pdevice);
+static TUSBH_ERCODE tusbhHIDDeInit(TUSBH_Device_t *pdevice);
+static TUSBH_ERCODE tusbdHIDProcess(TUSBH_Device_t *pdevice, uint8_t *mes);
+
+TUSBH_Class_t HID_Class = {
+	NULL,
+	"HID",
+	HID_CLASS,
+	tusbhHIDInit,
+	tusbhHIDDeInit,
+	tusbdHIDProcess,
+	NULL
+};
+
+/*
+ *  HIDクラスセットアップ関数
+ */
+void tusbhLinkHID(TUSBH_Handle_t *phost)
+{
+	tusbhLinkClass(phost, &HID_Class);
+}
+
+/*
+ *  HIDクラス初期設定
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  return     TUSBH_ERCODE
+ */
+static TUSBH_ERCODE
+tusbhHIDInit(TUSBH_Device_t *pdevice)
+{
+	TUSBH_Handle_t *phost = pdevice->pHost;
+	uint8_t max_ep;
+	uint8_t interface;
+	TUSBH_ERCODE status = TUSBH_E_ERR;
+	HID_Handle_t *hhid;
+
+	interface = tusbhFindInterface(pdevice, pdevice->pClass->classCode, HID_BOOT_CODE, 0xFF);
+
+	if(interface == NO_INTERFACE){
+		syslog_1(LOG_ERROR, "[HID] Cannot Find the interface for %s class !", pdevice->pClass->Name);
+		return TUSBH_E_ERR;
+	}
+
+	tusbhSelectInterface(pdevice, interface);
+	pdevice->pData = tusbmalloc(sizeof(HID_Handle_t));
+	hhid = (HID_Handle_t *)pdevice->pData;
+	memset(hhid, 0, sizeof(HID_Handle_t));
+	hhid->state = THID_ERROR;
+
+	/*
+	 *  デバイスの検索
+	 */
+	if(pdevice->ItfDesc[pdevice->sel_interface].bInterfaceProtocol == HID_KEYBRD_BOOT_CODE){
+		syslog_0(LOG_NOTICE, "[HID] found KeyBoard device !"); 
+		hhid->type =  HID_KEYBOARD_TYPE;
+	}
+	else if(pdevice->ItfDesc[pdevice->sel_interface].bInterfaceProtocol == HID_MOUSE_BOOT_CODE){
+		syslog_0(LOG_NOTICE, "[HID] found Mouse device !");
+		hhid->type =  HID_MOUSE_TYPE;
+	}
+	else{
+		syslog_0(LOG_ERROR, "[HID] no device !");
+		return TUSBH_E_ERR;
+	}
+
+	hhid->ep_addr   = pdevice->EpDesc[pdevice->sel_interface][0].bEndpointAddress;
+	hhid->length    = pdevice->EpDesc[pdevice->sel_interface][0].wMaxPacketSize;
+	hhid->poll      = pdevice->EpDesc[pdevice->sel_interface][0].bInterval ;
+
+	if(hhid->poll < HID_MIN_POLL)
+		hhid->poll = HID_MIN_POLL;
+
+	max_ep = pdevice->ItfDesc[pdevice->sel_interface].bNumEndpoints;
+	if(max_ep == 0 || (pdevice->EpDesc[pdevice->sel_interface][0].bEndpointAddress & 0x80) == 0)
+		return TUSBH_E_ERR;
+
+#if 1	/* ROI DEBUG */
+	syslog_3(LOG_NOTICE, "## max_ep(%d) length(%d) poll(%d) ##", max_ep, hhid->length, hhid->poll);
+#endif	/* ROI DEBUG */
+	if(hhid->length > HID_MAX_REPORT_LENGTH)
+		hhid->length = HID_MAX_REPORT_LENGTH;
+
+	/*
+	 *  インターラプト インエンドポイント オープン
+	 */
+	hhid->InPipe  = tusbhAllocPipe(phost, hhid->ep_addr);
+	tusbhOpenPipe(pdevice, hhid->InPipe, hhid->ep_addr, USB_EP_TYPE_INTR, hhid->length);
+	tusbhHDSetToggle(phost, hhid->InPipe, 0);
+
+	/*
+	 *  HID DESCRIPTOR取得
+	 */
+	if(tusbhGetDescriptor(pdevice, (USB_RECIPIENT_INTERFACE | USB_REQUEST_TYPE_STANDARD),
+						((HID_DESCRIPTOR << 8) & 0xFF00), pdevice->Data, HID_DESCRIPTOR_LENGTH) != TUSBH_E_OK)
+		return TUSBH_E_ERR;
+	hhid->ReportDescLength  = (pdevice->Data[7] & 0xff) | (pdevice->Data[8] << 8);
+	syslog_1(LOG_NOTICE, "## hhid->DescLength(%d) ##", hhid->ReportDescLength);
+	if(hhid->ReportDescLength > 64)
+		hhid->ReportDescLength = 64;
+
+	/*
+	 *  HID REPORT DESCRIPTOR取得
+	 */
+	if(tusbhGetDescriptor(pdevice, (USB_RECIPIENT_INTERFACE | USB_REQUEST_TYPE_STANDARD),
+						((HID_REPORT_DESCRIPTOR << 8) & 0xFF00), pdevice->Data, hhid->ReportDescLength) != TUSBH_E_OK)
+		return TUSBH_E_ERR;
+	tusbmemcpy(hhid->ReportDesc, pdevice->Data, hhid->ReportDescLength);
+	syslog_1(LOG_NOTICE, "## hhid->ReportDesc[%08x] ##", hhid->ReportDesc);
+
+	/*
+	 *  IDEL設定
+	 */
+	status = HID_SETIDLE(pdevice, 0, 0);
+	if(status != TUSBH_E_OK && status != TUSBH_E_NOSPT)
+		return status;
+
+	/*
+	 *  PROTOCOL #0 設定
+	 */
+	if((status = HID_SETPROTOCOL(pdevice, 0)) != TUSBH_E_OK)
+		return status;
+
+	/* タイマースタート */
+	hhid->state     = THID_INIT;
+	pdevice->timeid = pdevice->timecount = hhid->poll;
+	return TUSBH_E_OK;
+}
+
+/*
+ *  HUBクラス終了設定
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  return     TUSBH_ERCODE
+ */
+static TUSBH_ERCODE
+tusbhHIDDeInit(TUSBH_Device_t *pdevice)
+{
+	TUSBH_Handle_t *phost = pdevice->pHost;
+	HID_Handle_t *hhid;
+
+	hhid =  (HID_Handle_t *)pdevice->pData;
+	if(hhid->InPipe != 0x00){
+		tusbhClosePipe(pdevice, hhid->InPipe);
+		tusbFreePipe(phost, hhid->InPipe);
+		hhid->InPipe = 0;
+	}
+
+	if(pdevice->pData != NULL){
+		tusbfree(pdevice->pData);
+		pdevice->pData = NULL;
+	}
+	return TUSBH_E_OK;
+}
+
+
+/*
+ *  HIDクラスプロセス実行
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  parameter2 mes:      通信メッセージへのポインタ
+ *  return     TUSBH_ERCODE
+ */
+static TUSBH_ERCODE
+tusbdHIDProcess(TUSBH_Device_t *pdevice, uint8_t *mes)
+{
+	TUSBH_ERCODE status = TUSBH_E_OK, status2;
+	HID_Handle_t *hhid = (HID_Handle_t *)pdevice->pData;
+	TUSBH_URBState_t URB_Status = mes[3];
+	TUSBH_Handle_t *phost = pdevice->pHost;
+	void (*func)(TUSBH_Device_t *, uint8_t, uint8_t *) = pdevice->pClass->subfunc;
+
+	switch (hhid->state){
+	case THID_INIT:
+		if(phost->usrcallback != NULL)
+			phost->usrcallback(phost, pdevice, HOST_USER_CLASS_ACTIVE);
+	case THID_IDLE:
+		hhid->ReportType = 0x01;
+		hhid->ReportId   = 0;
+		HID_GETREPORT(pdevice, hhid->ReportType, hhid->ReportId, hhid->buffer, hhid->length);
+		hhid->state = THID_GETREPORT_WAIT;
+		break;
+	case THID_GETREPORT_WAIT:
+		if((status2 = tusbhControlWait(pdevice, mes)) == TUSBH_E_OK){
+			hhid->ReportLength = hhid->length;
+			tusbmemcpy(hhid->Report, hhid->buffer, hhid->ReportLength);
+			if(func != NULL)
+				func(pdevice, 0, hhid->Report);
+			syslog_2(LOG_NOTICE, "## THID_GETREPORT_WAIT hhid->Report[%08x] (%d) ##", hhid->Report, hhid->ReportLength);
+			hhid->state = THID_GET_DATA;
+			pdevice->timeid    = hhid->poll;
+			pdevice->timecount = hhid->poll;
+		}
+		else if(status2 == TUSBH_E_NOSPT){
+			if(func != NULL)
+				func(pdevice, 0, 0);
+			hhid->state = THID_GET_DATA;
+			pdevice->timeid    = hhid->poll;
+			pdevice->timecount = hhid->poll;
+		}
+		else if(status2 != TUSBH_E_BUSY && status2 != TUSBH_E_BUSY_URB){
+			syslog_1(LOG_NOTICE, "## tusbdHIDProcess ERROR status(%d) ##", status2);
+			hhid->state = THID_ERROR;
+		}
+		break;
+	case THID_SETREPORT:
+		tusbmemcpy(hhid->buffer, hhid->Report, hhid->ReportLength);
+		HID_SETREPORT(pdevice, hhid->ReportType, hhid->ReportId, hhid->buffer, hhid->ReportLength);
+		hhid->state = THID_SETREPORT_WAIT;
+		break;
+	case THID_SETREPORT_WAIT:
+		if((status2 = tusbhControlWait(pdevice, mes)) == TUSBH_E_OK){
+			syslog_2(LOG_NOTICE, "## THID_SETREPORT_WAIT(1) hhid->Report[%08x] (%d) ##", hhid->Report, hhid->ReportLength);
+			hhid->state = THID_GET_DATA;
+			pdevice->timeid    = hhid->poll;
+			pdevice->timecount = hhid->poll;
+		}
+		else if(status2 == TUSBH_E_NOSPT){
+			syslog_2(LOG_NOTICE, "## THID_SETREPORT_WAIT(2) hhid->Report[%08x] (%d) ##", hhid->Report, hhid->ReportLength);
+			hhid->state = THID_GET_DATA;
+			pdevice->timeid    = hhid->poll;
+			pdevice->timecount = hhid->poll;
+		}
+		else if(status2 != TUSBH_E_BUSY && status2 != TUSBH_E_BUSY_URB){
+			syslog_1(LOG_NOTICE, "## tusbdHIDProcess ERROR status(%d) ##", status2);
+			hhid->state = THID_ERROR;
+		}
+		break;
+	case THID_GET_DATA:
+		if(pdevice->is_connected == 0)
+			break;
+		if(hhid->ReqReport == 0xFF){
+			hhid->state = THID_SETREPORT;
+			tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
+			break;
+		}
+		tusbhInterruptRead(pdevice, hhid->buffer, hhid->length, hhid->InPipe);
+		hhid->state = THID_POLL;
+		hhid->DataReady = 0;
+		break;
+	case THID_POLL:
+		if(mes[0] != TUSBH_URB_EVENT)
+			break;
+		if(URB_Status == TUSBH_URB_DONE){
+			if(hhid->DataReady == 0){
+        		hhid->DataReady = 1;
+				if(func != NULL)
+					func(pdevice, hhid->length, hhid->buffer);
+				pdevice->timeid    = hhid->poll;
+				pdevice->timecount = hhid->poll;
+				hhid->state = THID_GET_DATA;
+			}
+		}
+		else if(URB_Status == TUSBH_URB_STALL){
+			/*
+			 *  STALLならCLEAR FEATURE実行
+			 */
+			if(tusbhClearFeature(pdevice, hhid->ep_addr) == TUSBH_E_OK){
+				/* Change state to issue next IN token */
+				hhid->state =THID_CLEARFEATURE_WAIT;
+			}
+		}
+		else{
+			pdevice->timeid    = hhid->poll;
+			pdevice->timecount = hhid->poll;
+			hhid->state = THID_GET_DATA;
+		}
+		break;
+	case THID_CLEARFEATURE_WAIT:
+		if((status2 = tusbhControlWait(pdevice, mes)) == TUSBH_E_OK){
+			hhid->state = THID_GET_DATA;
+			pdevice->timeid    = hhid->poll;
+			pdevice->timecount = hhid->poll;
+		}
+		else if(status2 == TUSBH_E_NOSPT){
+			hhid->state = THID_GET_DATA;
+			pdevice->timeid    = hhid->poll;
+			pdevice->timecount = hhid->poll;
+		}
+		else if(status2 != TUSBH_E_BUSY && status2 != TUSBH_E_BUSY_URB){
+			syslog_1(LOG_ERROR, "tusbdHIDProcess ERROR status(%d) !", status2);
+			hhid->state = THID_ERROR;
+		}
+		break;
+
+	default:
+		break;
+	}
+	return status;
+}
+
+/*
+ *  HIDデバイスリポート設定
+ *  parameter1 hhid:    HIDハンドラ
+ *  parameter2 type:    report type
+ *  parameter3 id:      report id
+ *  parameter4 pbuf:    report data
+ *  parameter5 len:     report data length
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+tubhHidSetReport(HID_Handle_t *hhid, uint8_t type, uint8_t id, uint8_t* pbuf, uint8_t len)
+{
+	hhid->ReportType   = type;
+	hhid->ReportId     = id;
+	hhid->ReportLength = len;
+	tusbmemcpy(hhid->Report, pbuf, hhid->ReportLength);
+	hhid->ReqReport = 0xFF;
+	while(hhid->ReqReport == 0xFF){
+		tusbSleep(10);
+	}
+	return (TUSBH_ERCODE)hhid->ReqReport;
+}
+
+/*
+ *  HIDデバイスタイプ取得
+ *  parameter1 hhid:    HIDハンドラ
+ *  return     poll     デバイスタイプ
+ */
+uint8_t
+tusbhHidGetType(TUSBH_Device_t *pdevice)
+{
+	HID_Handle_t *hhid = (HID_Handle_t *)pdevice->pData;
+
+	if(hhid == NULL)
+		return HID_UNKNOWN_TYPE;
+	else
+		return hhid->type;
+}
+
+
+/*
+ *  HIDポーリングインターバル時間取得
+ *  parameter1 hhid:    HIDハンドラ
+ *  return     poll     インターバル時間(ms)
+ */
+uint8_t
+tusbhHidGetPollInterval(TUSBH_Device_t *pdevice)
+{
+	HID_Handle_t *hhid = (HID_Handle_t *)pdevice->pData;
+
+	if(hhid == NULL)
+		return 0;
+	else
+		return hhid->poll;
+}
+
+/*
+ *  HID コールバック関数設定
+ */
+void
+tusbhSetHidCallBack(TUSBH_Handle_t *phost, void (*func)(TUSBH_Device_t *pdevice, uint8_t, uint8_t *))
+{
+	HID_Class.subfunc = func;
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/HID/tusbh_hid.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/HID/tusbh_hid.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/HID/tusbh_hid.h	(revision 453)
@@ -0,0 +1,134 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2017 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  USB Host Middleware HID部定義
+ */
+
+#ifndef _HUSBH_HID_H_
+#define _HUSBH_HID_H_
+
+#include "tusbh_base.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+#define HID_MIN_POLL            10
+#define HID_MAX_REPORT_LENGTH   8
+
+#define HID_MOUSE_TYPE          1
+#define HID_KEYBOARD_TYPE       2
+#define HID_UNKNOWN_TYPE        0xFF
+
+/*
+ *  HID BOOT Interface Descriptor field values
+ */
+#define HID_BOOT_CODE           0x01
+#define HID_KEYBRD_BOOT_CODE    0x01
+#define HID_MOUSE_BOOT_CODE     0x02
+
+
+/*
+ *  HIDクラス要求ID
+ */
+#define USB_HID_GET_REPORT      0x01
+#define USB_HID_GET_IDLE        0x02
+#define USB_HID_GET_PROTOCOL    0x03
+#define USB_HID_SET_REPORT      0x09
+#define USB_HID_SET_IDLE        0x0A
+#define USB_HID_SET_PROTOCOL    0x0B
+
+#define HID_SET_TYPE            (USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE)
+#define HID_GET_TYPE            (USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE | USB_RECIPIENT_ENDPOINT)
+
+/*
+ *  HID状態定義
+ */
+enum {
+	THID_INIT = 0,
+	THID_IDLE,
+	THID_GETREPORT_WAIT,
+	THID_SETREPORT,
+	THID_SETREPORT_WAIT,
+	THID_GET_DATA,
+	THID_POLL,
+	THID_CLEARFEATURE_WAIT,
+	THID_ERROR
+};
+
+
+/*
+ *  HIDハンドラ定義
+ */
+typedef struct
+{
+	uint8_t                   buffer[32];
+	uint8_t                   type;
+	uint8_t                   InPipe;
+	uint8_t                   state;
+	uint8_t                   ep_addr;
+	uint8_t                   DataReady;
+	uint8_t                   ReqReport;
+	uint16_t                  length;
+	uint16_t                  poll;
+	uint32_t                  timer;
+	uint16_t                  ReportDescLength;
+	uint8_t                   ReportDesc[66];
+	uint8_t                   ReportType;
+	uint8_t                   ReportId;
+	uint16_t                  ReportLength;
+	uint8_t                   Report[32];
+} HID_Handle_t;
+
+
+void    tusbhLinkHID(TUSBH_Handle_t *phost);
+
+TUSBH_ERCODE tubhHidSetReport(HID_Handle_t *hhid, uint8_t type, uint8_t id, uint8_t* pbuf, uint8_t len);
+uint8_t tusbhHidGetType(TUSBH_Device_t *pdevice);
+uint8_t tusbhHidGetPollInterval(TUSBH_Device_t *hdevice);
+void    tusbhSetHidCallBack(TUSBH_Handle_t *phost, void (*func)(TUSBH_Device_t *, uint8_t, uint8_t *));
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HUSBH_HID_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/HUB/tusbh_hub.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/HUB/tusbh_hub.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/HUB/tusbh_hub.c	(revision 453)
@@ -0,0 +1,370 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2017 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  USB Host Middleware HUB CLASS部
+ */
+
+#include "tusbh_hub.h"
+
+#define CLASS_GETDESC_TYPE          (USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS)
+#define PORT_POWER_FEATURE(d, p)    tusbhControlRequest((d), NULL, PORT_SETFEATURE_TYPE, SET_FEATURE, PORT_POWERFEATURE, (p), 0)
+#define PORT_RESET_FEATURE(d, p)    tusbhControlRequest((d), NULL, PORT_SETFEATURE_TYPE, SET_FEATURE, PORT_RESETFEATURE, (p), 0)
+#define PORT_CLEAR_FEATURE(d, f, p) tusbhControlRequest((d), NULL, PORT_CLEARFEATURE_TYPE, CLEAR_FEATURE, (f), (p), 0)
+#define PORT_GET_STATUS(d, b, p)    tusbhControlRequest((d), (b), PORT_GETSTATUS_TYPE, GET_STATUS, 0, (p), 4)
+
+#define GET_PORT(i)                 (i+1)
+
+
+static TUSBH_ERCODE tusbhHUBInit(TUSBH_Device_t *pdevice);
+static TUSBH_ERCODE tusbhHUBDeInit(TUSBH_Device_t *pdevice);
+static TUSBH_ERCODE tusbhHUBProcess(TUSBH_Device_t *pdevice, uint8_t *mes);
+
+static TUSBH_Class_t HUB_Class = {
+	NULL,
+	"HUB",
+	HUB_CLASS,
+	tusbhHUBInit,
+	tusbhHUBDeInit,
+	tusbhHUBProcess,
+	NULL
+};
+
+/*
+ *  HUBクラスセットアップ関数
+ */
+void tusbhLinkHUB(TUSBH_Handle_t *phost)
+{
+	tusbhLinkClass(phost, &HUB_Class);
+}
+
+
+/*
+ *  HUBクラス初期設定
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  return     TUSBH_ERCODE
+ */
+static TUSBH_ERCODE
+tusbhHUBInit(TUSBH_Device_t *pdevice)
+{
+	uint8_t interface = 0; 
+	HUB_Handle_t *hhub;
+	TUSBH_Handle_t *phost = pdevice->pHost;
+	uint8_t max_ep, i;
+
+	interface = tusbhFindInterface(pdevice, pdevice->pClass->classCode, 0, 0);
+
+	if(interface == NO_INTERFACE){
+		syslog_1(LOG_ERROR, "[HUB] Cannot Find the interface for %s class.", pdevice->pClass->Name);
+		return TUSBH_E_ERR;
+	}
+
+	tusbhSelectInterface(pdevice, interface);
+	hhub = (HUB_Handle_t *)tusbmalloc(sizeof(HUB_Handle_t));
+	pdevice->pData = hhub;
+	memset(hhub, 0, sizeof(HUB_Handle_t));
+	hhub->hubid     = ++phost->numHub;
+	pdevice->hubid  = hhub->hubid;
+	hhub->state     = THUB_IDLE;
+	hhub->cstate    = THUB_CONNCET_IDEL;
+	hhub->ep_addr   = pdevice->EpDesc[pdevice->sel_interface][0].bEndpointAddress;
+	hhub->length    = pdevice->EpDesc[pdevice->sel_interface][0].wMaxPacketSize;
+	hhub->poll      = pdevice->EpDesc[pdevice->sel_interface][0].bInterval;
+
+	max_ep = pdevice->ItfDesc[pdevice->sel_interface].bNumEndpoints;
+	if(max_ep == 0 || (pdevice->EpDesc[pdevice->sel_interface][0].bEndpointAddress & 0x80) == 0)
+		return TUSBH_E_ERR;
+
+
+	syslog_4(LOG_NOTICE, "## max_ep(%d) length(%d) poll(%d) b(%d) ##", max_ep, hhub->length, hhub->poll, offsetof(HUB_Handle_t, buffer));
+	hhub->InPipe  = tusbhAllocPipe(phost, hhub->ep_addr);
+
+	/*
+	 *  IN ENDPOINT OPEN
+	 */
+	tusbhOpenPipe(pdevice, hhub->InPipe, hhub->ep_addr, USB_EP_TYPE_INTR, hhub->length);
+	tusbhHDSetToggle(phost, hhub->InPipe, 0);
+
+	if(tusbhGetDescriptor(pdevice, CLASS_GETDESC_TYPE, (0x29 << 8), hhub->buffer, sizeof(HubDescriptor)) != TUSBH_E_OK)
+		return TUSBH_E_ERR;
+	hhub->numport         = hhub->buffer[2];
+	hhub->characteristics = hhub->buffer[3];
+	hhub->starttime       = hhub->buffer[5] * 2;
+	syslog_1(LOG_NOTICE, "## hhub->numport(%d) ##", hhub->numport);
+
+	for(i = 0 ; i < hhub->numport ; i++){
+		PORT_POWER_FEATURE(pdevice, GET_PORT(i));
+	}
+
+	/* タイマースタート */
+	hhub->timer = 0;
+	pdevice->timeid = pdevice->timecount = hhub->poll;
+	return TUSBH_E_OK;
+}
+
+/*
+ *  HUBクラス終了設定
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  return     TUSBH_ERCODE
+ */
+static TUSBH_ERCODE
+tusbhHUBDeInit(TUSBH_Device_t *pdevice)
+{
+	HUB_Handle_t *hhub = (HUB_Handle_t *)pdevice->pData;
+	TUSBH_Handle_t *phost = pdevice->pHost;
+
+	if(hhub->InPipe != 0){
+		tusbhClosePipe(pdevice, hhub->InPipe);
+		tusbFreePipe(phost, hhub->InPipe);
+		hhub->InPipe = 0;
+	}
+	if(phost->numHub > 0)
+		phost->numHub--;
+
+	if(pdevice->pData != NULL){
+		tusbfree(pdevice->pData);
+		pdevice->pData = NULL;
+	}
+	return TUSBH_E_OK;
+}
+
+/*
+ *  HUBクラスプロセス実行
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  parameter2 mes:      通信メッセージへのポインタ
+ *  return     TUSBH_ERCODE
+ */
+static TUSBH_ERCODE
+tusbhHUBProcess(TUSBH_Device_t *pdevice, uint8_t *mes)
+{
+	HUB_Handle_t   *hhub;
+	TUSBH_Handle_t *phost = pdevice->pHost;
+	TUSBH_Device_t *pdevicep;
+	TUSBH_ERCODE   status = TUSBH_E_OK;
+	TUSBH_URBState_t URB_Status = mes[3];
+	uint32_t pstatus = 0;
+	uint32_t i;
+
+	hhub = (HUB_Handle_t *)pdevice->pData;
+	if(mes[0] == TUSBH_TIME_EVENT)
+		hhub->timer += mes[3];
+	else if(mes[0] == TUSBH_RESET_EVENT)
+		hhub->reset_portid = mes[3];
+	switch (hhub->state){
+	case THUB_IDLE:
+		if(phost->usrcallback != NULL)
+			phost->usrcallback(phost, pdevice, HOST_USER_CLASS_ACTIVE);
+		hhub->state = THUB_SYNC;
+	case THUB_SYNC:
+		if(hhub->timer < hhub->starttime){
+			pdevice->timecount = hhub->poll;
+			break;
+		}
+		hhub->portno = 0;
+		hhub->cstate = THUB_CONNCET_IDEL;
+		if(hhub->reset_portid > 0){
+			PORT_RESET_FEATURE(pdevice, hhub->reset_portid);
+			hhub->state = THUB_PORT_RESET_WAIT;
+			hhub->reset_portid = 0;
+		}
+	case THUB_GET_DATA:
+		tusbhInterruptRead(pdevice, hhub->buffer, hhub->length, hhub->InPipe);
+		hhub->state = THUB_POLL;
+		break;
+	case THUB_POLL:
+		if(mes[0] != TUSBH_URB_EVENT)
+			 break;
+		if(URB_Status == TUSBH_URB_DONE){
+			PORT_GET_STATUS(pdevice, hhub->buffer, GET_PORT(hhub->portno));
+			hhub->state = THUB_GET_STATUS_WAIT;
+		}
+		else if(URB_Status == TUSBH_URB_STALL){ /* IN Endpoint Stalled */
+			hhub->state = THUB_PORT_ERROR;
+			tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
+		}
+		else{
+			hhub->state = THUB_GET_DATA;
+			pdevice->timecount = hhub->poll;
+		}
+		break;
+	case THUB_GET_STATUS_WAIT:
+		if((status = tusbhControlWait(pdevice, mes)) == TUSBH_E_OK){
+			uint8_t speed;
+			pstatus  = hhub->buffer[0];
+			pstatus |= hhub->buffer[1] << 8;
+			pstatus |= hhub->buffer[2] << 16;
+			pstatus |= hhub->buffer[3] << 24;
+#if 1	/* ROI DEBUG */
+			if((pstatus & 0xffff0000) != 0)
+				syslog_2(LOG_NOTICE, "## PSTATUS port(%d) status[%08x] ##", hhub->portno, pstatus);
+#endif	/* ROI DEBUG */
+
+			if((pstatus & PORT_CHANGE_CONNECTION) != 0){
+				if((pstatus & PORT_STATUS_CONNECTION) != 0)
+					hhub->cstate = THUB_CONNECT_RESET;
+				else
+					tusbSendData(phost->connect_event, TUSBH_DISCONNECT_EVENT, hhub->hubid, GET_PORT(hhub->portno), 0);
+				PORT_CLEAR_FEATURE(pdevice, PORT_CLEAR_CONNECTION_FEATURE, GET_PORT(hhub->portno));
+				hhub->state = THUB_CLEAR_FEATURE_WAIT;
+			}
+			else if((pstatus & PORT_CHANGE_RESET) != 0){
+				PORT_CLEAR_FEATURE(pdevice, PORT_CLEAR_RESET_FEATURE, GET_PORT(hhub->portno));
+				hhub->state = THUB_CLEAR_FEATURE_WAIT;
+				if(hhub->cstate == THUB_CONNECT_RESET){
+					if((pstatus & (PORT_STATUS_CONNECTION | PORT_STATUS_ENABLE)) == (PORT_STATUS_CONNECTION | PORT_STATUS_ENABLE)){
+						hhub->cstate = THUB_CONNECT_ENABLE;
+						if((pstatus & PORT_STATUS_LOW_SPEED) != 0)
+							speed = USB_DEVICE_SPEED_LOW;
+						else
+							speed = USB_DEVICE_SPEED_FULL;
+						tusbSendData(phost->connect_event, TUSBH_CONNECT_EVENT, hhub->hubid, GET_PORT(hhub->portno), speed);
+					}
+				}
+			}
+			else if((pstatus & PORT_CHANGE_ENABLE) != 0){
+				PORT_CLEAR_FEATURE(pdevice, PORT_CLEAR_ENABLE_FEATURE, GET_PORT(hhub->portno));
+				hhub->state = THUB_CLEAR_FEATURE_WAIT;
+				if(hhub->cstate == THUB_CONNECT_RESET){
+					if((pstatus & (PORT_STATUS_CONNECTION | PORT_STATUS_ENABLE)) == (PORT_STATUS_CONNECTION | PORT_STATUS_ENABLE)){
+						hhub->cstate = THUB_CONNECT_ENABLE;
+						if((pstatus & PORT_STATUS_LOW_SPEED) != 0)
+							speed = USB_DEVICE_SPEED_LOW;
+						else
+							speed = USB_DEVICE_SPEED_FULL;
+						tusbSendData(phost->connect_event, TUSBH_CONNECT_EVENT, hhub->hubid, GET_PORT(hhub->portno), speed);
+					}
+				}
+			}
+			else if((pstatus & PORT_CHANGE_OVER_CURRENT) != 0){
+				tusbSendData(phost->connect_event, TUSBH_DISCONNECT_EVENT, hhub->hubid, GET_PORT(hhub->portno), 0);
+				PORT_CLEAR_FEATURE(pdevice, PORT_OVER_CURRENT_FEATURE, GET_PORT(hhub->portno));
+				hhub->state = THUB_CLEAR_FEATURE_WAIT;
+			}
+//			else if(hhub->connect != 0){
+			else if(hhub->cstate != THUB_CONNCET_IDEL){
+				hhub->state = THUB_GET_DATA;
+				pdevice->timecount = hhub->poll;
+			}
+			else if(++hhub->portno < hhub->numport){
+				PORT_GET_STATUS(pdevice, hhub->buffer, GET_PORT(hhub->portno));
+				hhub->state = THUB_GET_STATUS_WAIT;
+			}
+			else{
+				hhub->state = THUB_SYNC;
+				pdevice->timecount = hhub->poll;
+			}
+		}
+		else if(status != TUSBH_E_BUSY && status != TUSBH_E_BUSY_URB){
+			hhub->state = THUB_PORT_ERROR;
+			tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
+		}
+		break;
+	case THUB_CLEAR_FEATURE_WAIT:
+		if((status = tusbhControlWait(pdevice, mes)) == TUSBH_E_OK){
+			if(hhub->cstate == THUB_CONNECT_RESET){
+				PORT_RESET_FEATURE(pdevice, GET_PORT(hhub->portno));
+				hhub->state = THUB_PORT_RESET_WAIT;
+			}
+			else if(hhub->cstate == THUB_CONNECT_ENABLE){
+				hhub->state = THUB_CONNECT_WAIT;
+				pdevice->timecount = 50;
+			}
+			else if(++hhub->portno < hhub->numport){
+				PORT_GET_STATUS(pdevice, hhub->buffer, GET_PORT(hhub->portno));
+				hhub->state = THUB_GET_STATUS_WAIT;
+			}
+			else{
+				hhub->state = THUB_SYNC;
+				pdevice->timecount = hhub->poll;
+			}
+		}
+		else if(status != TUSBH_E_BUSY && status != TUSBH_E_BUSY_URB){
+			hhub->state = THUB_PORT_ERROR;
+			tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
+		}
+		break;
+	case THUB_PORT_RESET_WAIT:
+		if((status = tusbhControlWait(pdevice, mes)) == TUSBH_E_OK){
+			hhub->state = THUB_GET_DATA;
+			pdevice->timecount = hhub->poll;
+		}
+		else if(status != TUSBH_E_BUSY && status != TUSBH_E_BUSY_URB){
+			hhub->state = THUB_PORT_ERROR;
+			tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
+		}
+		break;
+	case THUB_CONNECT_WAIT:
+		pdevice->timecount = 200;
+		for(i = 0, pdevicep = phost->pDevice ; i < phost->numDevice && pdevicep != NULL ; i++){
+			if(pdevicep->hub == hhub->hubid && pdevicep->port == GET_PORT(hhub->portno)){
+				if(pdevicep->dstate >= DEVICE_CLASS){
+					if(pdevicep->pClass != NULL)
+						syslog_2(LOG_NOTICE, "[HUB] connected idx(%d) class[%s] !", pdevicep->idx, pdevicep->pClass->Name);
+					hhub->cstate  = THUB_CONNCET_IDEL;
+					if(++hhub->portno < hhub->numport){
+						PORT_GET_STATUS(pdevice, hhub->buffer, GET_PORT(hhub->portno));
+						hhub->state = THUB_GET_STATUS_WAIT;
+					}
+					else{
+						hhub->state = THUB_SYNC;
+						pdevice->timecount = hhub->poll;
+					}
+				}
+				break;
+			}
+			pdevicep = pdevicep->pNext;
+		}
+		break;
+	case THUB_PORT_ERROR:
+		tusbhClearFeature(pdevice, hhub->ep_addr);
+		hhub->state = THUB_PORT_ERROR_WAIT;
+		break;
+	case THUB_PORT_ERROR_WAIT:
+		if(tusbhControlWait(pdevice, mes) == TUSBH_E_OK){
+			hhub->state = THUB_SYNC;
+			pdevice->timecount = hhub->poll;
+		}
+		else if(status == TUSBH_E_BUSY_URB)
+			status = TUSBH_E_BUSY;
+		break;
+
+	default:
+		break;
+	}
+	return status;
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/HUB/tusbh_hub.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/HUB/tusbh_hub.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/HUB/tusbh_hub.h	(revision 453)
@@ -0,0 +1,144 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2017 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  USB Host Middleware HUB部定義
+ */
+
+#ifndef _HUSBH_HUB_H_
+#define _HUSBH_HUB_H_
+
+#include "tusbh_base.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+
+#define PORT_CONNECTION_FEATURE         (0x00)
+#define PORT_ENABLEFEATURE              (0x01)
+#define PORT_SUSPEND                    (0x02)
+#define PORT_OVER_CURRENT_FEATURE       (0x03)
+#define PORT_RESETFEATURE               (0x04)
+#define PORT_POWERFEATURE               (0x08)
+#define PORT_LOW_SPEED                  (0x09)
+
+#define PORT_CLEAR_CONNECTION_FEATURE   (0x10)
+#define PORT_CLEAR_ENABLE_FEATURE       (0x11)
+#define PORT_CLEAR_RESET_FEATURE        (0x14)
+
+#define PORT_SETFEATURE_TYPE            (USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE | USB_RECIPIENT_ENDPOINT)
+#define PORT_CLEARFEATURE_TYPE          (USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE | USB_RECIPIENT_ENDPOINT)
+#define PORT_GETSTATUS_TYPE             (USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE | USB_RECIPIENT_ENDPOINT)
+
+#define PORT_STATUS_CONNECTION          (1<<PORT_CONNECTION_FEATURE)
+#define PORT_STATUS_ENABLE              (1<<PORT_ENABLEFEATURE)
+#define PORT_STATUS_SUSPEND             (1<<PORT_SUSPEND)
+#define PORT_STATUS_OVER_CURRENT        (1<<PORT_OVER_CURRENT_FEATURE)
+#define PORT_STATUS_RESET               (1<<PORT_RESETFEATURE)
+#define PORT_STATUS_POWER               (1<<PORT_POWERFEATURE)
+#define PORT_STATUS_LOW_SPEED           (1<<PORT_LOW_SPEED)
+
+#define PORT_CHANGE_CONNECTION          (1<<16)
+#define PORT_CHANGE_ENABLE              (1<<17)
+#define PORT_CHANGE_SUSPEND             (1<<18)
+#define PORT_CHANGE_OVER_CURRENT        (1<<19)
+#define PORT_CHANGE_RESET               (1<<20)
+
+/*
+ * HUB状態定義
+ */
+enum
+{
+	THUB_IDLE = 0,
+	THUB_SYNC,
+	THUB_GET_DATA,
+	THUB_POLL,
+	THUB_GET_STATUS_WAIT,
+	THUB_CLEAR_FEATURE_WAIT,
+	THUB_PORT_RESET_WAIT,
+	THUB_CONNECT_WAIT,
+	THUB_PORT_ERROR,
+	THUB_PORT_ERROR_WAIT
+};
+
+/*
+ *  HUB CONNECT状態定義
+ */
+enum
+{
+	THUB_CONNCET_IDEL = 0,
+	THUB_CONNECT_RESET,
+	THUB_CONNECT_ENABLE,
+	THUB_CONNECT_ACTIVE
+};
+
+/*
+ *  HUBハンドラ定義
+ */
+typedef struct
+{
+	TUSBH_Device_t            *pDev;
+	uint8_t                   state;
+	uint8_t                   hubid;
+	uint8_t                   numport;
+	uint8_t                   characteristics;
+	uint32_t                  timer;
+	uint32_t                  starttime;
+
+	uint8_t                   InPipe;
+	uint8_t                   ep_addr;
+	uint8_t                   portno;
+	uint8_t                   cstate;
+	uint16_t                  length;
+	uint16_t                  poll; 
+	uint32_t                  reset_portid;
+	uint32_t                  dummy2;
+	uint8_t                   buffer[64];
+} HUB_Handle_t;
+
+
+void  tusbhLinkHUB(TUSBH_Handle_t *phost);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HUSBH_HUB_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/MSC/tusbh_msc.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/MSC/tusbh_msc.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/MSC/tusbh_msc.c	(revision 453)
@@ -0,0 +1,976 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2017 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  USB Host Middleware MSC CLASS部
+ */
+
+#include "tusbh_msc.h"
+
+
+typedef enum {
+	BOT_OK,
+	BOT_BUSY,
+	BOT_SENSE,
+	BOT_ERROR
+} BOT_TYPE;
+
+#define CBW_SIGNATURE               0x43425355
+#define CSW_SIGNATURE               0x53425355
+#define CBW_TAG                     0x20304050
+
+#define BOT_CBW_LENGTH              31			/* CBW送信パケット長 */
+#define BOT_CSW_LENGTH              13			/* CSW受信パケット長 */
+
+#define UNIT_READY_TIMEOUT          (10000)
+
+#define BOT_REQUEST_GETMAXLUN(d, b) tusbhControlRequest((d), (b), BOT_REQUEST_GETMAXLUN_TYPE, USB_REQ_GET_MAX_LUN, 0, 0, 1)
+#define BOT_REQUEST_RESET(d)        tusbhControlRequest((d), 0, BOT_REQUEST_RESET_TYPE, USB_REQ_BOT_RESET, 0, 0, 0)
+
+
+/*
+ *  SENSEデータ
+ */
+typedef struct
+{
+	uint8_t key;
+	uint8_t asc;
+	uint8_t ascq;
+} SCSI_Sense_t;
+
+
+static TUSBH_ERCODE tusbhMSCInit(TUSBH_Device_t *pdevice);
+static TUSBH_ERCODE tusbhMSCDeInit(TUSBH_Device_t *pdevice);
+static TUSBH_ERCODE tusbhMSCProcess(TUSBH_Device_t *pdevice, uint8_t *mes);
+
+static TUSBH_Class_t MSC_Class = {
+	NULL,
+	"MSC",
+	MSC_CLASS,
+	tusbhMSCInit,
+	tusbhMSCDeInit,
+	tusbhMSCProcess,
+	NULL
+};
+
+/*
+ *  MSCクラスセットアップ関数
+ */
+void tusbhLinkMSC(TUSBH_Handle_t *phost)
+{
+	tusbhLinkClass(phost, &MSC_Class);
+}
+
+/*
+ * MSC SCSI Inquiry要求
+ *  parameter1 hmcs:    MSCハンドラ
+ *  parameter2 lun:     LUN#
+ *  return     TUSBH_E_BUSY
+ */
+static TUSBH_ERCODE
+tusbhMscSCSIInquiry(MSC_Handle_t *hmsc, uint8_t lun)
+{
+	hmsc->hbot.cbw.DataTransferLength = DATA_LEN_INQUIRY;
+	hmsc->hbot.cbw.Flags = USB_DEVICE_TO_HOST;
+	hmsc->hbot.cbw.CBLength = CBW_LENGTH;
+
+	tusbmemset(hmsc->hbot.cbw.CB, 0, CBW_LENGTH);
+	hmsc->hbot.cbw.CB[0]  = OPCODE_INQUIRY;
+	hmsc->hbot.cbw.CB[1]  = (lun << 5);
+	hmsc->hbot.cbw.CB[2]  = 0;
+	hmsc->hbot.cbw.CB[3]  = 0;
+	hmsc->hbot.cbw.CB[4]  = 0x24;
+	hmsc->hbot.cbw.CB[5]  = 0;
+
+	hmsc->hbot.state = BOT_SEND_CBW;
+	hmsc->hbot.pbuf = (uint8_t *)hmsc->hbot.data;
+	return TUSBH_E_BUSY;
+}
+
+/*
+ * MSC SCSI Test Unit Ready要求
+ *  parameter1 hmcs:    MSCハンドラ
+ *  parameter2 lun:     LUN#
+ *  return     TUSBH_E_BUSY
+ */
+static TUSBH_ERCODE
+tusbhMscSCSITestUnitReady(MSC_Handle_t *hmsc, uint8_t lun)
+{
+	hmsc->hbot.cbw.DataTransferLength = DATA_LEN_MODE_TEST_UNIT_READY;
+	hmsc->hbot.cbw.Flags = USB_HOST_TO_DEVICE;
+	hmsc->hbot.cbw.CBLength = CBW_LENGTH;
+
+	tusbmemset(hmsc->hbot.cbw.CB, 0, CBW_CB_LENGTH);
+	hmsc->hbot.cbw.CB[0]  = OPCODE_TEST_UNIT_READY; 
+
+	hmsc->hbot.state = BOT_SEND_CBW;
+	return TUSBH_E_BUSY;
+}
+
+/*
+ * MSC SCSI Read Capacity要求
+ *  parameter1 hmcs:    MSCハンドラ
+ *  parameter2 lun:     LUN#
+ *  return     TUSBH_E_BUSY
+ */
+static TUSBH_ERCODE
+tusbhMscSCSIReadCapacity(MSC_Handle_t *hmsc, uint8_t lun)
+{
+	hmsc->hbot.cbw.DataTransferLength = DATA_LEN_READ_CAPACITY10;
+	hmsc->hbot.cbw.Flags = USB_DEVICE_TO_HOST;
+	hmsc->hbot.cbw.CBLength = CBW_LENGTH;
+
+	tusbmemset(hmsc->hbot.cbw.CB, 0, CBW_CB_LENGTH);
+	hmsc->hbot.cbw.CB[0]  = OPCODE_READ_CAPACITY10;
+
+	hmsc->hbot.state = BOT_SEND_CBW;
+    hmsc->hbot.pbuf = (uint8_t *)hmsc->hbot.data;
+	return TUSBH_E_BUSY;
+}
+
+/*
+ * MSC SCSI Request Sense要求
+ *  parameter1 hmcs:    MSCハンドラ
+ *  parameter2 lun:     LUN#
+ *  return     TUSBH_E_BUSY
+ */
+static TUSBH_ERCODE
+tusbhMscSCSIRequestSense(MSC_Handle_t *hmsc, uint8_t lun)
+{
+	hmsc->hbot.cbw.DataTransferLength = DATA_LEN_REQUEST_SENSE;
+	hmsc->hbot.cbw.Flags = USB_DEVICE_TO_HOST;
+	hmsc->hbot.cbw.CBLength = CBW_LENGTH;
+
+	tusbmemset(hmsc->hbot.cbw.CB, 0, CBW_CB_LENGTH);
+	hmsc->hbot.cbw.CB[0]  = OPCODE_REQUEST_SENSE;
+	hmsc->hbot.cbw.CB[1]  = (lun << 5);
+	hmsc->hbot.cbw.CB[2]  = 0;
+	hmsc->hbot.cbw.CB[3]  = 0;
+	hmsc->hbot.cbw.CB[4]  = DATA_LEN_REQUEST_SENSE;
+	hmsc->hbot.cbw.CB[5]  = 0;
+
+	hmsc->hbot.state = BOT_SEND_CBW;
+	hmsc->hbot.pbuf = (uint8_t *)hmsc->hbot.data;
+	return TUSBH_E_BUSY;
+}
+
+/*
+ *  SCCI データ転送
+ *  parameter1 hmcs:    MSCハンドラ
+ *  parameter2 mes:     メッセージへのポインタ
+ *  parameter3 lun:     LUN#
+ *  return     BOT_TYPE
+ */
+static BOT_TYPE
+tusbhMscSCSITransfer(MSC_Handle_t *hmsc, uint8_t *mes, uint8_t lun)
+{
+	TUSBH_Device_t *pdevice = hmsc->pDev;
+	TUSBH_Handle_t *phost;
+	BOT_TYPE       status = BOT_BUSY;
+	TUSBH_ERCODE   ercd  = TUSBH_E_BUSY;
+	TUSBH_URBState_t URB_Status = mes[3];
+	uint8_t toggle = 0;
+
+	phost = pdevice->pHost;
+	switch (hmsc->hbot.state){
+	case BOT_SEND_CBW:
+		hmsc->hbot.cbw.LUN = lun;
+		hmsc->hbot.state = BOT_SEND_CBW_WAIT;
+		tusbhBulkWrite(pdevice, (uint8_t *)&hmsc->hbot.cbw, BOT_CBW_LENGTH, hmsc->OutPipe);
+		break;
+
+	case BOT_SEND_CBW_WAIT:
+		if(mes[0] != TUSBH_URB_EVENT)
+			break;
+		if(URB_Status == TUSBH_URB_DONE){
+			if(hmsc->hbot.cbw.DataTransferLength != 0){
+				if(((hmsc->hbot.cbw.Flags) & USB_REQUEST_DIR_MASK) == USB_DEVICE_TO_HOST){
+					/*
+					 *  BOT DATA INケース
+					 */
+					tusbhBulkRead (pdevice, hmsc->hbot.pbuf, hmsc->InEpSize, hmsc->InPipe);
+					hmsc->hbot.state  = BOT_DATA_IN_WAIT;
+				}
+				else{
+					/*
+					 *  BOT DATA OUTケース
+					 */
+					tusbhBulkWrite(pdevice, hmsc->hbot.pbuf, hmsc->OutEpSize, hmsc->OutPipe);
+					hmsc->hbot.state  = BOT_DATA_OUT_WAIT;
+				}
+			}
+			else{
+				/*
+				 *  ステータス通信ケース
+				 */
+				tusbhBulkRead(pdevice, (uint8_t *)&hmsc->hbot.csw, BOT_CSW_LENGTH, hmsc->InPipe);
+				hmsc->hbot.state  = BOT_RECEIVE_CSW_WAIT;
+			}
+		}
+		else if(URB_Status == TUSBH_URB_NOTREADY){
+			/*
+			 * CBWを再送
+			 */
+			hmsc->hbot.state = BOT_SEND_CBW;
+			tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
+		}
+		else if(URB_Status == TUSBH_URB_STALL){
+			/*
+			 *  Clear Fuature Out Endpoint(CBWSTALL)
+			 */
+			ercd = tusbhClearFeature(pdevice, hmsc->OutEp);
+			if(ercd == TUSBH_E_OK){ 
+				toggle = tusbhHDGetToggle(phost, hmsc->OutPipe);
+				tusbhHDSetToggle(phost, hmsc->OutPipe, 1- toggle);
+				tusbhHDSetToggle(phost, hmsc->InPipe, 0);
+				/*
+				 *  Clear Fuature In Endpoint
+				 */
+				ercd = tusbhClearFeature(pdevice, hmsc->InEp);
+				if(ercd == TUSBH_E_OK){
+					tusbhBulkRead(pdevice, (uint8_t *)&hmsc->hbot.csw, BOT_CSW_LENGTH, hmsc->InPipe);
+					hmsc->hbot.state  = BOT_RECEIVE_CSW_WAIT;
+				}
+				else
+					hmsc->hbot.state = BOT_STATE_ERROR;
+			}
+			else
+				hmsc->hbot.state = BOT_STATE_ERROR;
+			tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
+		}
+		break;
+
+	case BOT_DATA_IN_WAIT:
+		if(mes[0] != TUSBH_URB_EVENT)
+			break;
+		if(URB_Status == TUSBH_URB_DONE){
+			/*
+			 *  受信データ長アップデート
+			 */
+			if(hmsc->hbot.cbw.DataTransferLength > hmsc->InEpSize){
+				hmsc->hbot.pbuf += hmsc->InEpSize;
+				hmsc->hbot.cbw.DataTransferLength -= hmsc->InEpSize;
+			}
+			else
+				hmsc->hbot.cbw.DataTransferLength = 0;
+			if(hmsc->hbot.cbw.DataTransferLength > 0){
+				/*
+				 *  次のパケット要求
+				 */
+				tusbhBulkRead(pdevice, hmsc->hbot.pbuf, hmsc->InEpSize, hmsc->InPipe);
+			}
+			else{
+				/*
+				 *  受信終了、CSW受信要求
+				 */
+				tusbhBulkRead(pdevice, (uint8_t *)&hmsc->hbot.csw, BOT_CSW_LENGTH, hmsc->InPipe);
+				hmsc->hbot.state  = BOT_RECEIVE_CSW_WAIT;
+			}
+		}
+		else if(URB_Status == TUSBH_URB_STALL){
+			/*
+			 *  Clear Fuature In Endpoint(受信STALL)
+			 */
+			ercd = tusbhClearFeature(pdevice, hmsc->InEp);
+			if(ercd == TUSBH_E_OK){
+				tusbhBulkRead(pdevice, (uint8_t *)&hmsc->hbot.csw, BOT_CSW_LENGTH, hmsc->InPipe);
+				hmsc->hbot.state  = BOT_RECEIVE_CSW_WAIT;
+			}
+			else
+				hmsc->hbot.state = BOT_STATE_ERROR;
+			tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
+		}
+		break;
+
+	case BOT_DATA_OUT_WAIT:
+		if(mes[0] != TUSBH_URB_EVENT)
+			break;
+		if(URB_Status == TUSBH_URB_DONE){
+			/*
+			 *  送信データ長アップデート
+			 */
+			if(hmsc->hbot.cbw.DataTransferLength > hmsc->OutEpSize){
+				hmsc->hbot.pbuf += hmsc->OutEpSize;
+				hmsc->hbot.cbw.DataTransferLength -= hmsc->OutEpSize; 
+			}
+			else
+				hmsc->hbot.cbw.DataTransferLength = 0;
+			if(hmsc->hbot.cbw.DataTransferLength > 0){
+				/*
+				 *  次のパケット送信
+				 */
+				tusbhBulkWrite(pdevice, hmsc->hbot.pbuf, hmsc->OutEpSize, hmsc->OutPipe);
+			}
+			else{
+				/*
+				 *  送信終了、CSW受信要求
+				 */
+				tusbhBulkRead(pdevice, (uint8_t *)&hmsc->hbot.csw, BOT_CSW_LENGTH, hmsc->InPipe);
+				hmsc->hbot.state  = BOT_RECEIVE_CSW_WAIT;
+			}
+		}
+		else if(URB_Status == TUSBH_URB_NOTREADY){
+			/*
+			 *  再送設定
+			 */
+			tusbhBulkWrite(pdevice, hmsc->hbot.pbuf, hmsc->OutEpSize, hmsc->OutPipe);
+			hmsc->hbot.state  = BOT_DATA_OUT_WAIT;
+		}
+		else if(URB_Status == TUSBH_URB_STALL){
+			/*
+			 *  Clear Fuature Out Endpoint(送信STALL)
+			 */
+			ercd = tusbhClearFeature(pdevice, hmsc->OutEp);
+			if(ercd == TUSBH_E_OK){ 
+				toggle = tusbhHDGetToggle(phost, hmsc->OutPipe);
+				tusbhHDSetToggle(phost, hmsc->OutPipe, 1- toggle);
+				tusbhHDSetToggle(phost, hmsc->InPipe, 0);
+				/*
+				 *  Clear Fuature In Endpoint
+				 */
+				ercd = tusbhClearFeature(pdevice, hmsc->InEp);
+				if(ercd == TUSBH_E_OK){
+					tusbhBulkRead(pdevice, (uint8_t *)&hmsc->hbot.csw, BOT_CSW_LENGTH, hmsc->InPipe);
+					hmsc->hbot.state  = BOT_RECEIVE_CSW_WAIT;
+				}
+				else
+					hmsc->hbot.state = BOT_STATE_ERROR;
+			}
+			else
+				hmsc->hbot.state = BOT_STATE_ERROR;
+			tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
+		}
+		break;
+
+	case BOT_RECEIVE_CSW_WAIT:
+		if(mes[0] != TUSBH_URB_EVENT)
+			break;
+		if(URB_Status == TUSBH_URB_DONE){
+			hmsc->hbot.state = BOT_SEND_CBW;
+			if(hmsc->hbot.csw.Signature != CSW_SIGNATURE)
+				status = BOT_ERROR;
+			else if(hmsc->hbot.csw.Status == 0)
+				status = BOT_OK;
+			else if(hmsc->hbot.csw.Status == 1){
+#if 1	/* ROI DEBUG */
+				syslog_1(LOG_NOTICE, "## SBH_MSC_BOT_Process BOT_RECEIVE_CSW_WAIT ERROR CSW_Status(%d) ##", hmsc->hbot.csw.Status);
+#endif	/* ROI DEBUG */
+				status = BOT_SENSE;
+			}
+			else
+				status = BOT_ERROR;
+			tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
+		}
+		else if(URB_Status == TUSBH_URB_STALL){
+			/*
+			 *  Clear Fuature In Endpoint(CSW-STALL)
+			 */
+			ercd = tusbhClearFeature(pdevice, hmsc->InEp);
+			if(ercd == TUSBH_E_OK){
+				tusbhBulkRead(pdevice, (uint8_t *)&hmsc->hbot.csw, BOT_CSW_LENGTH, hmsc->InPipe);
+				hmsc->hbot.state  = BOT_RECEIVE_CSW_WAIT;
+			}
+			else
+				hmsc->hbot.state = BOT_STATE_ERROR;
+			tusbSendData (phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
+		}
+		break;
+
+	case BOT_STATE_ERROR:
+		BOT_REQUEST_RESET(pdevice);
+		hmsc->hbot.state = BOT_STATE_ERROR_WAIT;
+		break;
+
+	case BOT_STATE_ERROR_WAIT:
+		if((ercd = tusbhControlWait(pdevice, mes)) == TUSBH_E_OK)
+			hmsc->hbot.state = BOT_SEND_CBW;
+		else if(ercd != TUSBH_E_BUSY && ercd != TUSBH_E_BUSY_URB)
+			status = BOT_ERROR;
+		break;
+
+	default:
+		break;
+	}
+	return status;
+}
+
+/*
+ * MSC SCSI Disk Initialize
+ *  parameter1 hmcs:    MSCハンドラ
+ *  parameter2 lun:     LUN#
+ *  return     TUSBH_E_BUSY
+ */
+static TUSBH_ERCODE
+tusbhMscSCSIDiskInitailize(MSC_Handle_t *hmsc, uint8_t *mes, uint8_t lun)
+{
+	MSC_Unit_t   *punit = &hmsc->unit[lun];
+	SCSI_Sense_t sense;
+	TUSBH_ERCODE status = TUSBH_E_OK;
+	BOT_TYPE bot_status = BOT_BUSY;
+
+	switch (punit->state){
+	case MSC_UNIT_INIT:
+		syslog_1(LOG_NOTICE, "[MSC]LUN : #%d", lun);
+		punit->state = MSC_UNIT_READ_INQUIRY_WAIT;
+		status = tusbhMscSCSIInquiry(hmsc, lun);
+	case MSC_UNIT_READ_INQUIRY_WAIT:
+		bot_status = tusbhMscSCSITransfer(hmsc, mes, lun);
+		if(bot_status == BOT_OK){
+			/*
+			 *  INQUIRY情報取得
+			 */
+			punit->DeviceType = hmsc->hbot.pbuf[0] & 0x1F;
+			punit->PeripheralQualifier = hmsc->hbot.pbuf[0] >> 5;  
+			punit->RemovableMedia = (hmsc->hbot.pbuf[1] & 0x80)== 0x80;
+			tusbmemcpy(punit->vendor_id, &hmsc->hbot.pbuf[8], 8);
+			tusbmemcpy(punit->product_id, &hmsc->hbot.pbuf[16], 16);
+			tusbmemcpy(punit->revision_id, &hmsc->hbot.pbuf[32], 4);
+
+			syslog_1(LOG_NOTICE, "[MSC]Inquiry Vendor  : %s", punit->vendor_id);
+			syslog_1(LOG_NOTICE, "[MSC]Inquiry Product : %s", punit->product_id);
+			syslog_1(LOG_NOTICE, "[MSC]Inquiry Version : %s", punit->revision_id);
+			punit->state = MSC_UNIT_TEST_UNIT_READY_WAIT;
+			status = tusbhMscSCSITestUnitReady(hmsc, lun);
+		}
+		else if(bot_status == BOT_SENSE){
+			punit->state = MSC_UNIT_REQUEST_SENSE_WAIT;
+			punit->pre_state = MSC_UNIT_READ_INQUIRY_WAIT;
+			status = tusbhMscSCSIRequestSense(hmsc, lun);
+		}
+		else if(bot_status == BOT_ERROR){
+			punit->state = MSC_UNIT_ERROR;
+		}
+		else{
+			dly_tsk(10);
+			if(++hmsc->urb_wait > 500)
+				punit->state = MSC_UNIT_ERROR;
+		}
+		break;
+	case MSC_UNIT_TEST_UNIT_READY_WAIT:
+		bot_status = tusbhMscSCSITransfer(hmsc, mes, lun);
+		if(bot_status == BOT_OK){
+			syslog_1(LOG_NOTICE, "[MSC] Device ready(%d) !", lun);
+			punit->state = MSC_UNIT_READ_CAPACITY_WAIT;
+			status = tusbhMscSCSIReadCapacity(hmsc, lun);
+		}
+		else if(bot_status == BOT_SENSE){
+			if(hmsc->timer >= UNIT_READY_TIMEOUT){
+				syslog_1(LOG_NOTICE, "[MSC] Device NOT ready(%d) !", lun);
+			}
+			punit->state = MSC_UNIT_REQUEST_SENSE_WAIT; 
+			punit->pre_state = MSC_UNIT_TEST_UNIT_READY_WAIT;
+			status = tusbhMscSCSIRequestSense(hmsc, lun);
+		}
+		else if(bot_status == BOT_ERROR){
+			punit->state = MSC_UNIT_ERROR;
+		}
+		else{
+			dly_tsk(10);
+			if(++hmsc->urb_wait > 500)
+				punit->state = MSC_UNIT_ERROR;
+		}
+		break;
+	case MSC_UNIT_READ_CAPACITY_WAIT:
+		bot_status = tusbhMscSCSITransfer(hmsc, mes, lun);
+		if(bot_status == BOT_OK){
+			/*
+			 *  ユニット容量を取得
+			 */
+			punit->num_block = hmsc->hbot.pbuf[3] | (hmsc->hbot.pbuf[2] << 8) |
+								 (hmsc->hbot.pbuf[1] << 16) | (hmsc->hbot.pbuf[0] << 24);
+			punit->block_size = hmsc->hbot.pbuf[7] | (hmsc->hbot.pbuf[6] << 8); 
+			syslog_1(LOG_NOTICE, "[MSC] Device capacity : %u Bytes", \
+				(uint32_t)(punit->num_block * punit->block_size));
+			syslog_1(LOG_NOTICE, "      Block number : %u", (uint32_t)(punit->num_block));
+			syslog_1(LOG_NOTICE, "      Block Size   : %u", (uint32_t)(punit->block_size));
+			punit->state = MSC_UNIT_IDLE;
+			hmsc->lun++;
+		}
+		else if(bot_status == BOT_SENSE){
+			punit->state = MSC_UNIT_REQUEST_SENSE_WAIT;
+			punit->pre_state = MSC_UNIT_READ_CAPACITY_WAIT;
+			status = tusbhMscSCSIRequestSense(hmsc, lun);
+		}
+		else if(bot_status == BOT_ERROR){
+			punit->state = MSC_UNIT_ERROR;
+		}
+		else{
+			dly_tsk(10);
+			if(++hmsc->urb_wait > 500)
+				punit->state = MSC_UNIT_ERROR;
+		}
+		break;
+	case MSC_UNIT_REQUEST_SENSE_WAIT:
+		bot_status = tusbhMscSCSITransfer(hmsc, mes, lun);
+		if(bot_status == BOT_OK){
+			sense.key  = hmsc->hbot.pbuf[2] & 0x0F;
+			sense.asc  = hmsc->hbot.pbuf[12];
+			sense.ascq = hmsc->hbot.pbuf[13];
+			if(sense.key == SCSI_SENSE_KEY_UNIT_ATTENTION || sense.key == SCSI_SENSE_KEY_NOT_READY){
+				if(hmsc->timer < UNIT_READY_TIMEOUT){
+					if(punit->pre_state == MSC_UNIT_READ_INQUIRY_WAIT){
+						punit->state = MSC_UNIT_READ_INQUIRY_WAIT;
+						status = tusbhMscSCSIInquiry(hmsc, lun);
+						break;
+					}
+					else if(punit->pre_state == MSC_UNIT_TEST_UNIT_READY_WAIT){
+						punit->state = MSC_UNIT_TEST_UNIT_READY_WAIT;
+						status = tusbhMscSCSITestUnitReady(hmsc, lun);
+						break;
+					}
+					else if(punit->pre_state == MSC_UNIT_READ_CAPACITY_WAIT){
+						punit->state = MSC_UNIT_READ_CAPACITY_WAIT;
+						status = tusbhMscSCSIReadCapacity(hmsc, lun);
+						break;
+					}
+				}
+			}
+			syslog_1(LOG_NOTICE, "[MSC] Sense Key  : %x", sense.key);
+			syslog_1(LOG_NOTICE, "[MSC] Additional Sense Code : %x", sense.asc);
+			syslog_1(LOG_NOTICE, "[MSC] Additional Sense Code Qualifier: %x", sense.ascq);
+			punit->state = MSC_UNIT_IDLE;
+			lun++;
+		}
+		else if(bot_status == BOT_SENSE || bot_status == BOT_ERROR){
+			punit->state = MSC_UNIT_ERROR;
+		}
+		else{
+			dly_tsk(10);
+			if(++hmsc->urb_wait > 500)
+				punit->state = MSC_UNIT_ERROR;
+		}
+		break;
+	case MSC_UNIT_ERROR:
+		hmsc->lun++;
+		break;
+	default:
+		break;
+	}
+	return status;
+}
+
+
+/*
+ *  MSCクラス初期設定
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  return     TUSBH_ERCODE
+ */
+static TUSBH_ERCODE
+tusbhMSCInit(TUSBH_Device_t *pdevice)
+{
+	uint8_t interface = 0; 
+	TUSBH_ERCODE status = TUSBH_E_ERR ;
+	MSC_Handle_t *hmsc;
+	TUSBH_Handle_t *phost = pdevice->pHost;
+	uint8_t max_ep, i;
+
+	interface = tusbhFindInterface(pdevice, pdevice->pClass->classCode, MSC_TRANSPARENT_SUBCLASS, MSC_BOT_PROTOCOL);
+
+	if(interface == NO_INTERFACE){
+		syslog_1(LOG_ERROR, "[MSC] Cannot Find the interface for %s class.", pdevice->pClass->Name);
+		return TUSBH_E_ERR;
+	}
+	tusbhSelectInterface(pdevice, interface);
+
+	hmsc = (MSC_Handle_t *)tusbmalloc(sizeof(MSC_Handle_t));
+	pdevice->pData = hmsc;
+	memset(hmsc, 0, sizeof(MSC_Handle_t));
+	max_ep = ((pdevice->ItfDesc[pdevice->sel_interface].bNumEndpoints <= 2) ?
+              pdevice->ItfDesc[pdevice->sel_interface].bNumEndpoints : 2);
+
+	for(i = 0 ; i < max_ep; i++){
+		if(pdevice->EpDesc[pdevice->sel_interface][i].bEndpointAddress & 0x80){
+			hmsc->InEp     = (pdevice->EpDesc[pdevice->sel_interface][i].bEndpointAddress);
+			hmsc->InEpSize = pdevice->EpDesc[pdevice->sel_interface][i].wMaxPacketSize;
+			hmsc->InPipe = tusbhAllocPipe(phost, hmsc->InEp);
+		}
+		else{
+			hmsc->OutEp = (pdevice->EpDesc[pdevice->sel_interface][i].bEndpointAddress);
+			hmsc->OutEpSize = pdevice->EpDesc[pdevice->sel_interface][i].wMaxPacketSize;
+			hmsc->OutPipe = tusbhAllocPipe(phost, hmsc->OutEp);
+		}
+	}
+	if(hmsc->OutPipe == 0 || hmsc->InPipe == 0)
+		return TUSBH_E_ERR;
+
+	hmsc->lun = 0;
+	hmsc->state = MSC_PROCESS_INIT;
+	hmsc->urb_wait = 0;
+	hmsc->timer = 0;
+	hmsc->pDev = pdevice;
+
+	hmsc->hbot.cbw.Signature = CBW_SIGNATURE;
+	hmsc->hbot.cbw.Tag = CBW_TAG;
+	hmsc->hbot.state = BOT_SEND_CBW;
+
+	/*
+	 *  NSCチャネルオープン
+	 */
+	tusbhOpenPipe(pdevice, hmsc->OutPipe, hmsc->OutEp, USB_EP_TYPE_BULK, hmsc->OutEpSize);
+	tusbhHDSetToggle(phost, hmsc->OutPipe, 0);
+	tusbhOpenPipe(pdevice, hmsc->InPipe, hmsc->InEp, USB_EP_TYPE_BULK, hmsc->InEpSize);
+	tusbhHDSetToggle(phost, hmsc->InPipe, 0);
+
+	/*
+	 *  最大LUNを取得
+	 */
+	status = BOT_REQUEST_GETMAXLUN(pdevice, ((uint8_t *)&hmsc->hbot.data));
+	hmsc->max_lun = hmsc->hbot.data[0];
+
+	/*
+	 *  NO SUPPORT受信の場合、0を設定
+	 */
+	if(status == TUSBH_E_NOSPT){
+		hmsc->max_lun = 0;
+		status = TUSBH_E_OK;
+	}
+
+	/*
+	 *  UNIT領域の初期化
+	 */
+	if(status == TUSBH_E_OK){
+		uint32_t i;
+		hmsc->max_lun = (uint8_t )(hmsc->max_lun) + 1;
+		syslog_1(LOG_NOTICE, "[MSC] Number of supported LUN: %d", (int32_t)(hmsc->max_lun));
+
+		for(i = 0; i < hmsc->max_lun; i++){
+			tusbmemset(&hmsc->unit[i], 0, sizeof(hmsc->unit));
+			hmsc->unit[i].state = MSC_UNIT_INIT;
+		}
+	}
+	pdevice->numUnit = hmsc->max_lun;
+	/* タイマースタート */
+	pdevice->timeid = pdevice->timecount = 100;
+	return TUSBH_E_OK;
+}
+
+/*
+ *  MSCクラス終了設定
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  return     TUSBH_ERCODE
+ */
+static TUSBH_ERCODE
+tusbhMSCDeInit(TUSBH_Device_t *pdevice)
+{
+	MSC_Handle_t *hmsc;
+	TUSBH_Handle_t *phost = pdevice->pHost;
+
+	hmsc = (MSC_Handle_t *)pdevice->pData;
+	if(hmsc->OutPipe != 0){
+		tusbhClosePipe(pdevice, hmsc->OutPipe);
+		tusbFreePipe(phost, hmsc->OutPipe);
+		hmsc->OutPipe = 0;
+	}
+
+	if(hmsc->InPipe != 0){
+		tusbhClosePipe(pdevice, hmsc->InPipe);
+		tusbFreePipe(phost, hmsc->InPipe);
+		hmsc->InPipe = 0;
+	}
+
+	if(pdevice->pData != NULL){
+		tusbfree(pdevice->pData);
+		pdevice->pData = NULL;
+	}
+	return TUSBH_E_OK;
+}
+
+/*
+ *  MSCクラスプロセス実行
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  parameter2 mes:      通信メッセージへのポインタ
+ *  return     TUSBH_ERCODE
+ */
+static TUSBH_ERCODE
+tusbhMSCProcess(TUSBH_Device_t *pdevice, uint8_t *mes)
+{
+	MSC_Handle_t   *hmsc;
+	MSC_Unit_t     *punit;
+	TUSBH_Handle_t *phost = pdevice->pHost;
+	TUSBH_ERCODE status = TUSBH_E_OK;
+	BOT_TYPE bot_status = BOT_BUSY;
+
+	hmsc = (MSC_Handle_t *)pdevice->pData;
+    if(mes[0] == TUSBH_URB_EVENT){
+		hmsc->urb_wait = 0;
+    }
+	else if(mes[0] == TUSBH_TIME_EVENT){
+		hmsc->timer += mes[3];
+		pdevice->timecount = mes[3];
+	}
+	switch (hmsc->state){
+	case MSC_PROCESS_INIT:
+		if(hmsc->lun < hmsc->max_lun){
+			status = tusbhMscSCSIDiskInitailize(hmsc, mes, hmsc->lun);
+			tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
+		}
+		else{
+			hmsc->lun = 0;
+			hmsc->state = MSC_PROCESS_IDLE;
+			if(phost->usrcallback != NULL)
+				phost->usrcallback(phost, pdevice, HOST_USER_CLASS_ACTIVE);
+		}
+		break;
+	case MSC_PROCESS_READ_WAIT:
+	case MSC_PROCESS_WRITE_WAIT:
+		if(hmsc->lun >= hmsc->max_lun)
+			break;
+		punit = &hmsc->unit[hmsc->lun];
+		if(punit->rw_status == TUSBH_E_BUSY){
+			bot_status = tusbhMscSCSITransfer(hmsc, mes, hmsc->lun);
+			if(bot_status == BOT_SENSE){
+				hmsc->state = MSC_PROCESS_REQUEST_SENSE_WAIT;
+				tusbhMscSCSIRequestSense(hmsc, hmsc->lun);
+				tusbSendData( phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
+			}
+			else if(bot_status == BOT_ERROR){
+				punit->rw_status = TUSBH_E_ERR;
+			}
+			else if(bot_status != BOT_BUSY){
+				punit->rw_status = TUSBH_E_OK;
+				if(punit->rw_taskid != 0)
+					tusbWakeup(punit->rw_taskid);
+			}
+		}
+		break;
+    case MSC_PROCESS_REQUEST_SENSE_WAIT:
+		if(hmsc->lun >= hmsc->max_lun)
+			break;
+		punit = &hmsc->unit[hmsc->lun];
+		if(punit->rw_status == TUSBH_E_BUSY){
+			bot_status = tusbhMscSCSITransfer(hmsc, mes, hmsc->lun);
+			if(bot_status == BOT_OK){
+				punit->rw_status = TUSBH_E_OK;
+				if(punit->rw_taskid != 0)
+					tusbWakeup(punit->rw_taskid);
+			}
+			else if(bot_status != BOT_BUSY){
+				punit->rw_status = TUSBH_E_ERR;
+			}
+		}
+		break;
+	case MSC_PROCESS_IDLE:
+		status = TUSBH_E_OK;
+		break;
+	default:
+		break;
+	}
+	return status;
+}
+
+/*
+ *  ユニット READY確認
+ *  parameter1 phost:   ホストハンドラ
+ *  parameter2 lun:     unit#
+ *  return     status:  (0: not ready / 1: ready)
+ */
+uint8_t
+tusbhMscUnitIsReady(TUSBH_Handle_t *phost, uint8_t lun)
+{
+	TUSBH_Device_t *pdevice = tusbhSearchDevice(phost, MSC_Class.classCode, &lun);
+	MSC_Handle_t *hmsc;
+
+	if(pdevice == NULL)
+		return 0;
+	hmsc = (MSC_Handle_t *)pdevice->pData;
+
+	if(pdevice->dstate == DEVICE_CLASS)
+		return (hmsc->unit[lun].state >= MSC_UNIT_IDLE);
+	else
+		return 0;
+}
+
+/*
+ *  ユニット情報を取得
+ *  parameter1 phost:   ホストハンドラ
+ *  parameter2 lun:     unit#
+ *  parameter3 info:    ユニット取得領域へのポインタ
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+tusbhMscGetLUNInfo(TUSBH_Handle_t *phost, uint8_t lun, MSC_Unit_t *info)
+{
+	TUSBH_Device_t *pdevice = tusbhSearchDevice(phost, MSC_Class.classCode, &lun);
+	MSC_Handle_t *hmsc;
+
+	if(pdevice == NULL)
+		return TUSBH_E_OBJ;
+	hmsc = (MSC_Handle_t *) pdevice->pData;
+
+	if(pdevice->dstate == DEVICE_CLASS){
+		tusbmemcpy(info, &hmsc->unit[lun], sizeof(MSC_Unit_t));
+		return TUSBH_E_OK;
+	}
+	else
+		return TUSBH_E_OBJ;
+}
+
+/*
+ *  MSC BLOCK READ
+ *  parameter1 phost:   ホストハンドラ
+ *  parameter2 lun:     unit#
+ *  parameter3 address: ユニットアドレス
+ *  parameter4 pbuf:    受信データ領域へのポインタ
+ *  parameter5 num:     受信ブロック数
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+tusbhMscRead(TUSBH_Handle_t *phost, uint8_t lun, uint32_t address, uint8_t *pbuf, uint32_t num)
+{
+	TUSBH_Device_t *pdevice = tusbhSearchDevice(phost, MSC_Class.classCode, &lun);
+	MSC_Handle_t *hmsc;
+	TUSBH_ERCODE status = TUSBH_E_BUSY;
+	uint32_t i;
+
+	if(pdevice != NULL){
+		hmsc = pdevice->pData;
+		if(pdevice->dstate != DEVICE_CLASS || hmsc->unit[lun].state != MSC_UNIT_IDLE)
+			return TUSBH_E_OBJ;
+	}
+	else
+		return TUSBH_E_OBJ;
+	if(lun >= hmsc->max_lun)
+		return TUSBH_E_PAR;
+
+	hmsc->state = MSC_PROCESS_READ_WAIT;
+	hmsc->unit[lun].rw_status = TUSBH_E_BUSY;
+	hmsc->unit[lun].rw_taskid = tusbGetTaskID();
+	hmsc->unit[lun].state = MSC_UNIT_READ_WAIT;
+	hmsc->lun = lun;
+
+    /*
+	 *  BLOCK READ CBW設定
+	 */
+	hmsc->hbot.cbw.DataTransferLength = num * 512;
+	hmsc->hbot.cbw.Flags = USB_DEVICE_TO_HOST;
+	hmsc->hbot.cbw.CBLength = CBW_LENGTH;
+	tusbmemset(hmsc->hbot.cbw.CB, 0, CBW_CB_LENGTH);
+	hmsc->hbot.cbw.CB[0]  = OPCODE_READ10; 
+
+	hmsc->hbot.cbw.CB[2]  = (address >> 24) & 0xff;
+	hmsc->hbot.cbw.CB[3]  = (address >> 16) & 0xff;
+	hmsc->hbot.cbw.CB[4]  = (address >> 8) & 0xff;
+	hmsc->hbot.cbw.CB[5]  = address & 0xff;
+
+	hmsc->hbot.cbw.CB[7]  = (num >> 8) & 0xff;
+	hmsc->hbot.cbw.CB[8]  = num & 0xff;
+
+    hmsc->hbot.state = BOT_SEND_CBW;
+    hmsc->hbot.pbuf = pbuf;
+    tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
+
+	for(i = 0 ; i < (num * 1000) ; i++){
+		tusbSleep(50);
+		if((status = hmsc->unit[lun].rw_status) != TUSBH_E_BUSY)
+			break;
+	}
+	if(status == TUSBH_E_BUSY)
+		status = TUSBH_E_TMOUT;
+	hmsc->unit[lun].rw_taskid = 0;
+	hmsc->unit[lun].state = MSC_UNIT_IDLE;
+	hmsc->state = MSC_PROCESS_IDLE;
+	return status;
+}
+
+/*
+ *  MSC BLOCK WRITE
+ *  parameter1 phost:   ホストハンドラ
+ *  parameter2 lun:     unit#
+ *  parameter3 address: ユニットアドレス
+ *  parameter4 pbuf:    送信データ領域へのポインタ
+ *  parameter5 num:     送信ブロック数
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+tusbhMscWrite(TUSBH_Handle_t *phost, uint8_t lun, uint32_t address, uint8_t *pbuf, uint32_t num)
+{
+	TUSBH_Device_t *pdevice = tusbhSearchDevice(phost, MSC_Class.classCode, &lun);
+	MSC_Handle_t *hmsc;
+	TUSBH_ERCODE status = TUSBH_E_BUSY;
+	uint32_t i;
+
+	if(pdevice != NULL){
+		hmsc = pdevice->pData;
+		if(pdevice->dstate != DEVICE_CLASS || hmsc->unit[lun].state != MSC_UNIT_IDLE)
+			return TUSBH_E_OBJ;
+	}
+	else
+		return TUSBH_E_OBJ;
+	if(lun >= hmsc->max_lun)
+		return TUSBH_E_PAR;
+
+	hmsc->state = MSC_PROCESS_WRITE_WAIT;
+	hmsc->unit[lun].rw_taskid = tusbGetTaskID();
+	hmsc->unit[lun].rw_status = TUSBH_E_BUSY;
+	hmsc->unit[lun].state = MSC_UNIT_WRITE_WAIT;
+	hmsc->lun = lun;
+
+    /*
+	 *  BLOCK WRITE CBW設定
+	 */
+	hmsc->hbot.cbw.DataTransferLength = num * 512;
+	hmsc->hbot.cbw.Flags = USB_HOST_TO_DEVICE;
+	hmsc->hbot.cbw.CBLength = CBW_LENGTH;
+	tusbmemset(hmsc->hbot.cbw.CB, 0, CBW_CB_LENGTH);
+	hmsc->hbot.cbw.CB[0]  = OPCODE_WRITE10; 
+
+	hmsc->hbot.cbw.CB[2]  = (address >> 24) & 0xff;
+	hmsc->hbot.cbw.CB[3]  = (address >> 16) & 0xff;
+	hmsc->hbot.cbw.CB[4]  = (address >> 8) & 0xff;
+	hmsc->hbot.cbw.CB[5]  = (((uint8_t*)&address)[0]);
+
+	hmsc->hbot.cbw.CB[7]  = (num >> 8) & 0xff;
+	hmsc->hbot.cbw.CB[8]  = num & 0xff;
+
+	hmsc->hbot.state = BOT_SEND_CBW;
+	hmsc->hbot.pbuf = pbuf;
+	tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
+
+	for(i = 0 ; i < (num * 1000) ; i++){
+		tusbSleep(50);
+		if((status = hmsc->unit[lun].rw_status) != TUSBH_E_BUSY)
+			break;
+	}
+	if(status == TUSBH_E_BUSY)
+		status = TUSBH_E_TMOUT;
+	hmsc->unit[lun].rw_taskid = 0;
+	hmsc->unit[lun].state = MSC_UNIT_IDLE;
+	hmsc->state = MSC_PROCESS_IDLE;
+	return status;
+}
+
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/MSC/tusbh_msc.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/MSC/tusbh_msc.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/MSC/tusbh_msc.h	(revision 453)
@@ -0,0 +1,238 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2017 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  USB Host Middleware MSC部定義
+ */
+
+#ifndef _HUSBH_MSC_H_
+#define _HUSBH_MSC_H_
+
+#include "tusbh_base.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+#ifndef NUM_MAX_MSC_UNIT
+#define NUM_MAX_MSC_UNIT                2
+#endif
+
+/*
+ *  MSCインターフェイス定義
+ */
+#define MSC_TRANSPARENT_SUBCLASS        0x06
+#define MSC_BOT_PROTOCOL                0x50
+
+/*
+ *  BOT通信パケット定義
+ */ 
+#define OPCODE_TEST_UNIT_READY          0x00
+#define OPCODE_READ_CAPACITY10          0x25
+#define OPCODE_READ10                   0x28
+#define OPCODE_WRITE10                  0x2A
+#define OPCODE_REQUEST_SENSE            0x03
+#define OPCODE_INQUIRY                  0x12
+
+#define DATA_LEN_MODE_TEST_UNIT_READY   0
+#define DATA_LEN_READ_CAPACITY10        8
+#define DATA_LEN_INQUIRY                36
+#define DATA_LEN_REQUEST_SENSE          14
+
+#define CBW_CB_LENGTH                   16
+#define CBW_LENGTH                      10
+
+/*
+ *  SENSE KEY定義
+ */
+#define SCSI_SENSE_KEY_NO_SENSE         0x00
+#define SCSI_SENSE_KEY_RECOVERED_ERROR  0x01
+#define SCSI_SENSE_KEY_NOT_READY        0x02
+#define SCSI_SENSE_KEY_MEDIUM_ERROR     0x03
+#define SCSI_SENSE_KEY_HARDWARE_ERROR   0x04
+#define SCSI_SENSE_KEY_ILLEGAL_REQUEST  0x05
+#define SCSI_SENSE_KEY_UNIT_ATTENTION   0x06
+#define SCSI_SENSE_KEY_DATA_PROTECT     0x07
+#define SCSI_SENSE_KEY_BLANK_CHECK      0x08
+#define SCSI_SENSE_KEY_VENDOR_SPECIFIC  0x09
+#define SCSI_SENSE_KEY_COPY_ABORTED     0x0A
+#define SCSI_SENSE_KEY_ABORTED_COMMAND  0x0B
+#define SCSI_SENSE_KEY_VOLUME_OVERFLOW  0x0D
+#define SCSI_SENSE_KEY_MISCOMPARE       0x0E
+
+/*
+ *  MSCコントロール通信定義
+ */
+#define USB_REQ_BOT_RESET               0xFF
+#define USB_REQ_GET_MAX_LUN             0xFE
+
+#define BOT_REQUEST_GETMAXLUN_TYPE      (USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE)
+#define BOT_REQUEST_RESET_TYPE          (USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE)
+
+/*
+ *  MSCプロセスの状態定義
+ */
+enum
+{
+	MSC_PROCESS_INIT = 0,
+	MSC_PROCESS_IDLE,
+	MSC_PROCESS_READ_WAIT,
+	MSC_PROCESS_WRITE_WAIT,
+	MSC_PROCESS_REQUEST_SENSE_WAIT
+};
+
+/*
+ *  MSCユニットの状態定義
+ */
+typedef enum
+{
+	MSC_UNIT_INIT = 0,
+	MSC_UNIT_TEST_UNIT_READY_WAIT,
+	MSC_UNIT_READ_CAPACITY_WAIT,
+	MSC_UNIT_READ_INQUIRY_WAIT,
+	MSC_UNIT_REQUEST_SENSE_WAIT,
+	MSC_UNIT_ERROR,
+	MSC_UNIT_IDLE,
+	MSC_UNIT_READ_WAIT,
+	MSC_UNIT_WRITE_WAIT,
+} MSC_UNIT_STATE_t;
+
+/*
+ *  BOT状態定義
+ */
+typedef enum {
+	BOT_SEND_CBW  = 1,
+	BOT_SEND_CBW_WAIT,
+	BOT_DATA_IN_WAIT,
+	BOT_DATA_OUT_WAIT,
+	BOT_RECEIVE_CSW_WAIT,
+	BOT_STATE_ERROR,
+	BOT_STATE_ERROR_WAIT
+} BOT_STATE_t;
+
+typedef struct
+{
+	uint32_t                 Signature;
+	uint32_t                 Tag;
+	uint32_t                 DataTransferLength;
+	uint8_t                  Flags;
+	uint8_t                  LUN;
+	uint8_t                  CBLength;
+	uint8_t                  CB[CBW_CB_LENGTH];
+} BOT_CBW_t;
+
+typedef struct
+{
+	uint32_t                 Signature;
+	uint32_t                 Tag;
+	uint32_t                 DataResidue;
+	uint8_t                  Status;
+} BOT_CSW_t;
+
+/*
+ *  BOTハンドラ型定義
+ */
+typedef struct
+{
+	uint32_t                 data[32];
+	BOT_CBW_t                cbw;
+	uint32_t                 dummy2[8];
+	BOT_CSW_t                csw;
+	uint8_t                  dummy3[12];
+	uint8_t                  *pbuf;
+	BOT_STATE_t              state;
+} BOT_Handle_t;
+
+/*
+ *  MSC ユニット定義
+ */
+typedef struct
+{
+	MSC_UNIT_STATE_t            state; 
+	MSC_UNIT_STATE_t            pre_state;
+	uint32_t                    num_block;
+	uint32_t                    block_size;
+	uint8_t                     DeviceType;
+	uint8_t                     PeripheralQualifier;
+	uint8_t                     RemovableMedia;
+	uint8_t                     vendor_id[12];
+	uint8_t                     product_id[20];
+	uint8_t                     revision_id[8];
+	TUSBH_ERCODE                rw_status;
+	int32_t                     rw_taskid;
+} MSC_Unit_t;
+
+/*
+ *  MSCハンドラ定義
+ */
+typedef struct
+{
+	TUSBH_Device_t            *pDev;
+	uint8_t                   state;
+	uint8_t                   max_lun;
+    uint8_t                   lun;
+	uint8_t                   dymmy1;
+
+	uint8_t                   InPipe;
+	uint8_t                   OutPipe;
+	uint8_t                   OutEp;
+	uint8_t                   InEp;
+	uint16_t                  OutEpSize;
+	uint16_t                  InEpSize;
+	uint32_t                  timer;
+	uint32_t                  urb_wait;
+	uint32_t                  dummy[2];
+	BOT_Handle_t              hbot;
+	MSC_Unit_t                unit[NUM_MAX_MSC_UNIT];
+} MSC_Handle_t;
+
+
+void         tusbhLinkMSC(TUSBH_Handle_t *phost);
+uint8_t      tusbhMscUnitIsReady(TUSBH_Handle_t *phost, uint8_t lun);
+TUSBH_ERCODE tusbhMscGetLUNInfo(TUSBH_Handle_t *phost, uint8_t lun, MSC_Unit_t *info);
+TUSBH_ERCODE tusbhMscRead(TUSBH_Handle_t *phost, uint8_t lun, uint32_t address, uint8_t *pbuf, uint32_t num);
+TUSBH_ERCODE tusbhMscWrite(TUSBH_Handle_t *phost, uint8_t lun, uint32_t address, uint8_t *pbuf, uint32_t num);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HUSBH_MSC_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/PRT/tusbh_prt.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/PRT/tusbh_prt.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/PRT/tusbh_prt.c	(revision 453)
@@ -0,0 +1,477 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  USB Host Middleware PRT CLASS部
+ */
+
+#include "tusbh_prt.h"
+
+
+#define CONTROL_STATUS                  1
+#define CONTROL_VENDER                  2
+
+
+#define PRT_REQUEST_VENDER(d, b, c, l)  tusbhControlRequest((d), (b), PRT_VENDER_SEND_TYPE, (c), 0, 0, (l))
+#define PRT_REQUEST_STATUS(d, b, c, l)  tusbhControlRequest((d), (b), PRT_REQUEST_STATUS_TYPE, (c), 0, 0, (l))
+
+
+static TUSBH_ERCODE tusbhPRTInit(TUSBH_Device_t *pdevice);
+static TUSBH_ERCODE tusbhPRTDeInit(TUSBH_Device_t *pdevice);
+static TUSBH_ERCODE tusbhPRTProcess(TUSBH_Device_t *pdevice, uint8_t *mes);
+
+static TUSBH_Class_t PRT_Class = {
+	NULL,
+	"PRT",
+	PRT_CLASS,
+	tusbhPRTInit,
+	tusbhPRTDeInit,
+	tusbhPRTProcess,
+	NULL
+};
+
+/*
+ *  PRTクラスセットアップ関数
+ */
+void tusbhLinkPRT(TUSBH_Handle_t *phost)
+{
+	tusbhLinkClass(phost, &PRT_Class);
+}
+
+/*
+ *  PRTクラス初期設定
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  return     TUSBH_ERCODE
+ */
+static TUSBH_ERCODE
+tusbhPRTInit(TUSBH_Device_t *pdevice)
+{
+	uint8_t interface = 0; 
+	PRT_Handle_t *hprt;
+	TUSBH_Handle_t *phost = pdevice->pHost;
+	uint8_t max_ep, i;
+
+	interface = tusbhFindInterface(pdevice, pdevice->pClass->classCode, 0x01, 0x02);
+
+	if(interface == NO_INTERFACE){
+		syslog_1(LOG_ERROR, "[PRT] Cannot Find the interface for %s class.", pdevice->pClass->Name);
+		return TUSBH_E_ERR;
+	}
+	tusbhSelectInterface(pdevice, interface);
+
+	hprt = (PRT_Handle_t *)tusbmalloc(sizeof(PRT_Handle_t));
+	pdevice->pData = hprt;
+	memset(hprt, 0, sizeof(PRT_Handle_t));
+	max_ep = ((pdevice->ItfDesc[interface].bNumEndpoints <= 2) ?
+              pdevice->ItfDesc[interface].bNumEndpoints : 2);
+#if 1	/* ROI DEBUG */
+	syslog_3(LOG_NOTICE, "## tusbhPRTInit hmsc[%08x] max_ep(%d) buffer(%d) ##", hprt, max_ep, offsetof(PRT_Handle_t, buffer));
+#endif	/* ROI DEBUG */
+
+	for(i = 0 ; i < max_ep; i++){
+		if(pdevice->EpDesc[interface][i].bEndpointAddress & 0x80){
+			hprt->InEp     = (pdevice->EpDesc[interface][i].bEndpointAddress);
+			hprt->InEpSize = pdevice->EpDesc[interface][i].wMaxPacketSize;
+			hprt->InPipe = tusbhAllocPipe(phost, hprt->InEp);
+		}
+		else{
+			hprt->OutEp = (pdevice->EpDesc[interface][i].bEndpointAddress);
+			hprt->OutEpSize = pdevice->EpDesc[interface][i].wMaxPacketSize;
+			hprt->OutPipe = tusbhAllocPipe(phost, hprt->OutEp);
+		}
+	}
+	if(hprt->OutPipe == 0 || hprt->InPipe == 0)
+		return TUSBH_E_ERR;
+
+	hprt->state = PRT_PROCESS_INIT;
+	hprt->timer = 0;
+	hprt->pDev = pdevice;
+
+	/*
+	 *  NSCチャネルオープン
+	 */
+	tusbhOpenPipe(pdevice, hprt->OutPipe, hprt->OutEp, USB_EP_TYPE_BULK, hprt->OutEpSize);
+	tusbhHDSetToggle(phost, hprt->OutPipe, 0);
+	tusbhOpenPipe(pdevice, hprt->InPipe, hprt->InEp, USB_EP_TYPE_BULK, hprt->InEpSize);
+	tusbhHDSetToggle(phost, hprt->InPipe, 0);
+
+	/* タイマースタート */
+	pdevice->timeid = pdevice->timecount = 100;
+	return TUSBH_E_OK;
+}
+
+/*
+ *  PRTクラス終了設定
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  return     TUSBH_ERCODE
+ */
+static TUSBH_ERCODE
+tusbhPRTDeInit(TUSBH_Device_t *pdevice)
+{
+	PRT_Handle_t *hprt;
+	TUSBH_Handle_t *phost = pdevice->pHost;
+
+	hprt = (PRT_Handle_t *)pdevice->pData;
+	if(hprt->OutPipe != 0){
+		tusbhClosePipe(pdevice, hprt->OutPipe);
+		tusbFreePipe(phost, hprt->OutPipe);
+		hprt->OutPipe = 0;
+	}
+
+	if(hprt->InPipe != 0){
+		tusbhClosePipe(pdevice, hprt->InPipe);
+		tusbFreePipe(phost, hprt->InPipe);
+		hprt->InPipe = 0;
+	}
+
+	if(pdevice->pData != NULL){
+		tusbfree(pdevice->pData);
+		pdevice->pData = NULL;
+	}
+	return TUSBH_E_OK;
+}
+
+/*
+ *  PRTクラスプロセス実行
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  parameter2 mes:      通信メッセージへのポインタ
+ *  return     TUSBH_ERCODE
+ */
+static TUSBH_ERCODE
+tusbhPRTProcess(TUSBH_Device_t *pdevice, uint8_t *mes)
+{
+	PRT_Handle_t   *hprt  = (PRT_Handle_t *)pdevice->pData;
+	TUSBH_Handle_t *phost = pdevice->pHost;
+	void (*func)(TUSBH_Device_t *, uint8_t, TUSBH_ERCODE, uint32_t) = pdevice->pClass->subfunc;
+	TUSBH_URBState_t URB_Status = mes[3];
+	TUSBH_ERCODE ercd = TUSBH_E_BUSY;
+	int32_t length;
+
+    if(mes[0] == TUSBH_URB_EVENT){
+		hprt->urb_wait = 0;
+    }
+	else if(mes[0] == TUSBH_TIME_EVENT){
+		hprt->timer += mes[3];
+		pdevice->timecount = mes[3];
+	}
+	else if(mes[0] == TUSBH_CLASS_EVENT && mes[2] != 0)
+		hprt->state = mes[2];
+	switch (hprt->state){
+	case PRT_PROCESS_INIT:
+		if(phost->usrcallback != NULL)
+			phost->usrcallback(phost, pdevice, HOST_USER_CLASS_ACTIVE);
+		hprt->state = PRT_PROCESS_IDLE;
+	case PRT_PROCESS_IDLE:
+		if(mes[0] != TUSBH_URB_EVENT){
+			ercd = TUSBH_E_OK;
+			break;
+		}
+		if(mes[2] == pdevice->cntl_pipe_in || mes[2] == pdevice->cntl_pipe_out){
+			ercd = tusbhControlWait(pdevice, mes);
+			if(ercd == TUSBH_E_OK){
+				hprt->state = PRT_PROCESS_IDLE;
+				hprt->controlType = 0;
+			}
+			else if(ercd != TUSBH_E_BUSY && ercd != TUSBH_E_BUSY_URB){
+				hprt->state = PRT_PROCESS_ERROR;
+				hprt->controlType = 0;
+			}
+			break;
+		}
+		else if(URB_Status == TUSBH_URB_DONE){
+			if(mes[2] == hprt->InPipe){
+				hprt->RxTrnPktSize = tusbhHDTrasLength(phost, hprt->InPipe);
+				hprt->RxTrnLength += hprt->RxTrnPktSize;
+				hprt->pRxTrnBuff += hprt->RxTrnPktSize;
+				hprt->rwr_status = TUSBH_E_OK;
+				if(func != NULL)
+					func(pdevice, PRT_LINE_STATUS_RECEIVED, TUSBH_E_OK, hprt->RxTrnLength);
+			}
+			else{
+				hprt->TxTrnLength += hprt->TxTrnPktSize;
+				hprt->pTxTrnBuff += hprt->TxTrnPktSize;
+				if(hprt->TxTrnSize > hprt->TxTrnLength)
+					hprt->state = PRT_PROCESS_SEND;
+				else{
+					hprt->rwt_status = TUSBH_E_OK;
+					if(func != NULL)
+						func(pdevice, PRT_LINE_STATUS_SENDED, TUSBH_E_OK, hprt->TxTrnLength);
+				}
+			}
+		}
+		else if(URB_Status == TUSBH_URB_NOTREADY){
+			if(mes[2] == hprt->InPipe)
+				hprt->state = PRT_PROCESS_RECEIVE;
+			else
+				hprt->state = PRT_PROCESS_SEND;
+		}
+		else{
+			hprt->state = PRT_PROCESS_ERROR;
+			if(mes[2] == hprt->InPipe)
+				hprt->rwr_status = TUSBH_E_ERR;
+			else
+				hprt->rwt_status = TUSBH_E_ERR;
+			if(func != NULL)
+				func(pdevice, PRT_LINE_STATUS_CHANGED, TUSBH_E_ERR, 0);
+		}
+		tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
+		break;
+	case PRT_PROCESS_CONTROL:
+		if(hprt->controlType == CONTROL_VENDER)
+			PRT_REQUEST_VENDER(pdevice, hprt->buffer, hprt->controlRequest, hprt->controlLength);
+		else
+			PRT_REQUEST_STATUS(pdevice, hprt->buffer, hprt->controlRequest, hprt->controlLength);
+		hprt->state = PRT_PROCESS_IDLE;
+		break;
+	case PRT_PROCESS_SEND:
+		length = hprt->TxTrnSize - hprt->TxTrnLength;
+		if(length > hprt->OutEpSize)
+			hprt->TxTrnPktSize = hprt->OutEpSize;
+		else
+			hprt->TxTrnPktSize = length;
+		tusbhBulkWrite(pdevice, hprt->pTxTrnBuff, hprt->TxTrnPktSize, hprt->OutPipe);
+		hprt->state = PRT_PROCESS_IDLE;
+		break;
+	case PRT_PROCESS_RECEIVE:
+		length = hprt->RxTrnSize - hprt->RxTrnLength;
+		if(length > hprt->InEpSize)
+			hprt->RxTrnPktSize = hprt->InEpSize;
+		else
+			hprt->RxTrnPktSize = length;
+		tusbhBulkRead(pdevice, hprt->pRxTrnBuff, hprt->RxTrnPktSize, hprt->InPipe);
+		hprt->state = PRT_PROCESS_IDLE;
+		break;
+	case PRT_PROCESS_ERROR:
+		tusbhClearFeature(pdevice, 0x00);
+		hprt->state = PRT_PROCESS_ERROR_WAIT;
+		break;
+	case PRT_PROCESS_ERROR_WAIT:
+		if(tusbhControlWait(pdevice, mes) == TUSBH_E_OK)
+			hprt->state = PRT_PROCESS_IDLE;
+		break;
+
+
+	default:
+		break;
+	}
+	return ercd;
+}
+
+/*
+ *  PRT SEND EOJ
+ *  parameter1 phost:   ホストハンドラ
+ *  parameter2 unit:    UNIT#
+ *  parameter3 cmd:     設定コマンド
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+tusbhPrtEOJ(TUSBH_Handle_t *phost, uint8_t unit, uint8_t cmd, uint8_t prm1, uint8_t prm2)
+{
+	TUSBH_Device_t *pdevice = tusbhSearchDevice(phost, PRT_Class.classCode, &unit);
+	PRT_Handle_t *hprt;
+
+	if(pdevice == NULL)
+		return TUSBH_E_OBJ;
+	hprt = (PRT_Handle_t *)pdevice->pData;
+	if(pdevice->dstate == DEVICE_CLASS){
+		hprt->buffer[0] = cmd;
+		hprt->buffer[1] = prm1;
+		hprt->buffer[2] = prm2;
+		hprt->controlType    = CONTROL_VENDER;
+		hprt->controlRequest  = PRT_VERNDER_REQUEST_EOJ;
+		hprt->controlLength  = 3;
+		hprt->state = PRT_PROCESS_CONTROL;
+		tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
+		while(hprt->controlType != 0){
+			tusbSleep(1);
+		}
+	}
+	return TUSBH_E_OK;
+}
+
+/*
+ *  PRT GET PORTID
+ *  parameter1 phost:   ホストハンドラ
+ *  parameter2 unit:    UNIT#
+ *  parameter3 cmd:     設定コマンド
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+tusbhPrtPortID(TUSBH_Handle_t *phost, uint8_t unit, uint8_t *buf)
+{
+	TUSBH_Device_t *pdevice = tusbhSearchDevice(phost, PRT_Class.classCode, &unit);
+	PRT_Handle_t *hprt;
+
+	if(pdevice == NULL)
+		return TUSBH_E_OBJ;
+	hprt = (PRT_Handle_t *)pdevice->pData;
+	if(pdevice->dstate == DEVICE_CLASS){
+		hprt->controlType    = CONTROL_STATUS;
+		hprt->controlRequest = PRT_REQUEST_DEVICEID;
+		hprt->controlLength  = 1;
+		tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, PRT_PROCESS_CONTROL, 0);
+		while(hprt->controlType != 0){
+			tusbSleep(1);
+		}
+		*buf = hprt->buffer[0];
+	}
+	return TUSBH_E_OK;
+}
+
+/*
+ *  PRT GET PRINT STATUS
+ *  parameter1 phost:   ホストハンドラ
+ *  parameter2 unit:    UNIT#
+ *  parameter3 cmd:     設定コマンド
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+tusbhPrtPortStatus(TUSBH_Handle_t *phost, uint8_t unit, uint8_t *buf, uint32_t length)
+{
+	TUSBH_Device_t *pdevice = tusbhSearchDevice(phost, PRT_Class.classCode, &unit);
+	PRT_Handle_t *hprt;
+	uint32_t trans_len, packet_len;
+
+	if(length > PRT_MAX_PORTSTATUS_SIZE)
+		trans_len = PRT_MAX_PORTSTATUS_SIZE;
+	else
+		trans_len = length;
+	if(pdevice == NULL)
+		return TUSBH_E_OBJ;
+	hprt = (PRT_Handle_t *)pdevice->pData;
+	if(pdevice->dstate == DEVICE_CLASS){
+		hprt->controlType    = CONTROL_STATUS;
+		hprt->controlRequest = PRT_REQUEST_PORTSTATUS;
+		hprt->controlLength  = trans_len;
+		tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, PRT_PROCESS_CONTROL, 0);
+		while(hprt->controlType != 0){
+			tusbSleep(1);
+		}
+		packet_len = (hprt->buffer[0] << 8) | hprt->buffer[1];
+		if(trans_len > (packet_len + 2))
+			trans_len = packet_len + 2;
+		tusbmemcpy(buf, hprt->buffer, trans_len);
+	}
+	return TUSBH_E_OK;
+}
+
+/*
+ *  PRT DATA RECEIVE
+ *  parameter1 phost:   ホストハンドラ
+ *  parameter2 unit:    UNIT#
+ *  parameter3 pbuf:    受信データ領域へのポインタ
+ *  parameter4 length:  受信ブロック長
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+tusbhPrtReceive(TUSBH_Handle_t *phost, uint8_t unit, uint8_t *pbuf, uint32_t length)
+{
+	TUSBH_Device_t *pdevice = tusbhSearchDevice(phost, PRT_Class.classCode, &unit);
+	PRT_Handle_t *hprt;
+
+	if(pdevice != NULL){
+		hprt = pdevice->pData;
+		if(pdevice->dstate != DEVICE_CLASS)
+			return TUSBH_E_OBJ;
+		if(hprt->state == PRT_PROCESS_ERROR)
+			return TUSBH_E_ERR;
+		if(hprt->rwr_status == TUSBH_E_BUSY)
+			return TUSBH_E_OBJ;
+	}
+	else
+		return TUSBH_E_OBJ;
+
+    /*
+	 *  受信データ設定
+	 */
+	hprt->RxTrnSize   = length;
+	hprt->RxTrnLength = 0;
+	hprt->pRxTrnBuff  = pbuf;
+	hprt->rwr_status  = TUSBH_E_BUSY;
+	tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, PRT_PROCESS_RECEIVE, 0);
+	return TUSBH_E_OK;
+}
+
+/*
+ *  PRT DATA SEND
+ *  parameter1 phost:   ホストハンドラ
+ *  parameter2 unit:    UNIT#
+ *  parameter3 pbuf:    送信データ領域へのポインタ
+ *  parameter4 length:  送信データ長
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+tusbhPrtSend(TUSBH_Handle_t *phost, uint8_t unit, uint8_t *pbuf, uint32_t length)
+{
+	TUSBH_Device_t *pdevice = tusbhSearchDevice(phost, PRT_Class.classCode, &unit);
+	PRT_Handle_t *hprt;
+
+	if(pdevice != NULL){
+		hprt = pdevice->pData;
+		if(pdevice->dstate != DEVICE_CLASS)
+			return TUSBH_E_OBJ;
+		if(hprt->state == PRT_PROCESS_ERROR)
+			return TUSBH_E_ERR;
+		if(hprt->rwt_status == TUSBH_E_BUSY)
+			return TUSBH_E_OBJ;
+	}
+	else
+		return TUSBH_E_OBJ;
+
+    /*
+	 *  送信データ設定
+	 */
+	hprt->TxTrnSize   = length;
+	hprt->TxTrnLength = 0;
+	hprt->pTxTrnBuff  = pbuf;
+	hprt->rwt_status  = TUSBH_E_BUSY;
+	tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, PRT_PROCESS_SEND, 0);
+	return TUSBH_E_OK;
+}
+
+/*
+ *  PRTコールバック関数
+ *  parameter1 phost:   ホストハンドラ
+ *  parameter2 func:    関数ポインタ
+ */
+void
+tusbhSetPrtCallBack(TUSBH_Handle_t *phost, void (*func)(TUSBH_Device_t *p, uint8_t, TUSBH_ERCODE, uint32_t))
+{
+	PRT_Class.subfunc = func;
+}
+
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/PRT/tusbh_prt.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/PRT/tusbh_prt.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/PRT/tusbh_prt.h	(revision 453)
@@ -0,0 +1,132 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  USB Host Middleware PRT部定義
+ */
+
+#ifndef _HUSBH_PRT_H_
+#define _HUSBH_PRT_H_
+
+#include "tusbh_base.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+#define PRT_VERNDER_REQUEST_EOJ     0
+#define PRT_REQUEST_PORTSTATUS      0
+#define PRT_REQUEST_DEVICEID        1
+#define PRT_REQUEST_SOFTRESET       2
+
+#define PRT_MAX_PORTSTATUS_SIZE     256
+
+#define PRT_REQUEST_STATUS_TYPE         (USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE)
+#define PRT_VENDER_SEND_TYPE            (USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_VENDOR | USB_RECIPIENT_INTERFACE)
+
+/*
+ *  PRTコールバックコード定義
+ */
+#define PRT_LINE_STATUS_CHANGED         1
+#define PRT_LINE_STATUS_SENDED          2
+#define PRT_LINE_STATUS_RECEIVED        3
+
+/*
+ *  PRTプロセスの状態定義
+ */
+enum
+{
+	PRT_PROCESS_INIT = 0,
+	PRT_PROCESS_IDLE,
+	PRT_PROCESS_CONTROL,
+	PRT_PROCESS_SEND,
+	PRT_PROCESS_RECEIVE,
+	PRT_PROCESS_ERROR,
+	PRT_PROCESS_ERROR_WAIT
+};
+
+/*
+ *  PRTハンドラ定義
+ */
+typedef struct
+{
+	TUSBH_Device_t            *pDev;
+	uint8_t                   state;
+	uint8_t                   cmd;
+	uint8_t                   dummy[2];
+	uint16_t                  TxTrnPktSize;
+	uint16_t                  RxTrnPktSize;
+
+	uint8_t                   InPipe;
+	uint8_t                   OutPipe;
+	uint8_t                   OutEp;
+	uint8_t                   InEp;
+	uint16_t                  OutEpSize;
+	uint16_t                  InEpSize;
+	uint8_t                   controlType;
+	uint8_t                   controlRequest;
+	uint16_t                  controlLength;
+	uint32_t                  TxTrnLength;
+	uint32_t                  TxTrnSize;
+	uint8_t                   *pTxTrnBuff;
+	uint32_t                  RxTrnLength;
+	uint32_t                  RxTrnSize;
+	uint8_t                   *pRxTrnBuff;
+	uint32_t                  timer;
+	uint32_t                  urb_wait;
+	uint32_t                  rwt_status;
+	uint32_t                  rwr_status;
+	uint8_t                   buffer[PRT_MAX_PORTSTATUS_SIZE];
+} PRT_Handle_t;
+
+
+void         tusbhLinkPRT(TUSBH_Handle_t *phost);
+TUSBH_ERCODE tusbhPrtEOJ(TUSBH_Handle_t *phost, uint8_t unit, uint8_t cmd, uint8_t prm1, uint8_t prm2);
+TUSBH_ERCODE tusbhPrtPortID(TUSBH_Handle_t *phost, uint8_t unit, uint8_t *buf);
+TUSBH_ERCODE tusbhPrtPortStatus(TUSBH_Handle_t *phost, uint8_t unit, uint8_t *buf, uint32_t length);
+TUSBH_ERCODE tusbhPrtSend(TUSBH_Handle_t *phost, uint8_t unit, uint8_t *pbuf, uint32_t length);
+TUSBH_ERCODE tusbhPrtReceive(TUSBH_Handle_t *phost, uint8_t unit, uint8_t *pbuf, uint32_t length);
+void tusbhSetPrtCallBack(TUSBH_Handle_t *phost, void (*func)(TUSBH_Device_t *p, uint8_t, TUSBH_ERCODE, uint32_t));
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HUSBH_PRT_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/SERIAL/tusbh_serial.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/SERIAL/tusbh_serial.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/SERIAL/tusbh_serial.c	(revision 453)
@@ -0,0 +1,498 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  USB Host Middleware CDC:SERIAL CLASS部
+ */
+
+#include "tusbh_serial.h"
+
+
+#define CDC_REQUEST_GETLINE(d, b)   tusbhControlRequest((d), (b), CDC_REQUEST_GETLINE_TYPE, CDC_GET_LINE_CODING, 0, 0, LINE_CODING_STRUCTURE_SIZE)
+#define CDC_REQUEST_SETLINE(d, b)   tusbhControlRequest((d), (b), CDC_REQUEST_SETLINE_TYPE, CDC_SET_LINE_CODING, 0, 0, LINE_CODING_STRUCTURE_SIZE)
+
+
+static TUSBH_ERCODE tusbhCDCInit(TUSBH_Device_t *pdevice);
+static TUSBH_ERCODE tusbhCDCDeInit(TUSBH_Device_t *pdevice);
+static TUSBH_ERCODE tusbhCDCProcess(TUSBH_Device_t *pdevice, uint8_t *mes);
+
+static TUSBH_Class_t SERAIL_Class = {
+	NULL,
+	"CDC",
+	CDC_CLASS,
+	tusbhCDCInit,
+	tusbhCDCDeInit,
+	tusbhCDCProcess,
+	NULL
+};
+
+/*
+ *  SERIALクラスセットアップ関数
+ */
+void tusbhLinkSERIAL(TUSBH_Handle_t *phost)
+{
+	tusbhLinkClass(phost, &SERAIL_Class);
+}
+
+/*
+ *  CDCクラス初期設定
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  return     TUSBH_ERCODE
+ */
+static TUSBH_ERCODE
+tusbhCDCInit(TUSBH_Device_t *pdevice)
+{
+	uint8_t interface = 0; 
+	CDC_Handle_t *hcdc;
+	TUSBH_Handle_t *phost = pdevice->pHost;
+	uint8_t max_ep, i;
+
+	interface = tusbhFindInterface(pdevice, pdevice->pClass->classCode, ABSTRACT_CONTROL_MODEL, CDC_ITU_T_V_250);
+
+	if(interface == NO_INTERFACE){
+		syslog_1(LOG_ERROR, "[CDC] Cannot Find the interface for %s class.", pdevice->pClass->Name);
+		return TUSBH_E_ERR;
+	}
+	tusbhSelectInterface(pdevice, interface);
+
+	hcdc = (CDC_Handle_t *)tusbmalloc(sizeof(CDC_Handle_t));
+	pdevice->pData = hcdc;
+	memset(hcdc, 0, sizeof(CDC_Handle_t));
+	max_ep = ((pdevice->ItfDesc[interface].bNumEndpoints <= 2) ?
+              pdevice->ItfDesc[interface].bNumEndpoints : 2);
+#if 1	/* ROI DEBUG */
+	syslog_3(LOG_NOTICE, "## tusbhCDCInit hmsc[%08x] max_ep(%d) csw(%d) ##", hcdc, max_ep, 0);
+#endif	/* ROI DEBUG */
+	if(max_ep == 0 || (pdevice->EpDesc[interface][0].bEndpointAddress & 0x80) == 0)
+		return TUSBH_E_ERR;
+
+	hcdc->CommInEp     = pdevice->EpDesc[interface][0].bEndpointAddress;
+    hcdc->CommInEpSize = pdevice->EpDesc[interface][0].wMaxPacketSize;
+	hcdc->CommInPipe   = tusbhAllocPipe(phost, hcdc->CommInEp);
+
+	/*
+	 *  COMMNUCATION IN ENDPOINT OPEN
+	 */
+	tusbhOpenPipe(pdevice, hcdc->CommInPipe, hcdc->CommInEp, USB_EP_TYPE_INTR, hcdc->CommInEpSize);
+	tusbhHDSetToggle(phost, hcdc->CommInPipe, 0);
+
+    interface = tusbhFindInterface(pdevice, DATA_INTERFACE_CLASS, 0x00, DIC_NO_SPECIFIC_PROTOCOL_CODE);
+	if(interface == NO_INTERFACE){
+		syslog_1(LOG_ERROR, "[CDC] Cannot Find the interface for %s class.", pdevice->pClass->Name);
+		return TUSBH_E_ERR;
+	}
+	max_ep = ((pdevice->ItfDesc[interface].bNumEndpoints <= 2) ?
+              pdevice->ItfDesc[interface].bNumEndpoints : 2);
+
+	for(i = 0 ; i < max_ep; i++){
+		if(pdevice->EpDesc[interface][i].bEndpointAddress & 0x80){
+			hcdc->InEp     = (pdevice->EpDesc[interface][i].bEndpointAddress);
+			hcdc->InEpSize = pdevice->EpDesc[interface][i].wMaxPacketSize;
+			hcdc->InPipe = tusbhAllocPipe(phost, hcdc->InEp);
+		}
+		else{
+			hcdc->OutEp = (pdevice->EpDesc[interface][i].bEndpointAddress);
+			hcdc->OutEpSize = pdevice->EpDesc[interface][i].wMaxPacketSize;
+			hcdc->OutPipe = tusbhAllocPipe(phost, hcdc->OutEp);
+		}
+	}
+	if(hcdc->OutPipe == 0 || hcdc->InPipe == 0)
+		return TUSBH_E_ERR;
+
+	hcdc->state = CDC_PROCESS_INIT;
+	hcdc->timer = 0;
+	hcdc->pDev = pdevice;
+
+	/*
+	 *  NSCチャネルオープン
+	 */
+	tusbhOpenPipe(pdevice, hcdc->OutPipe, hcdc->OutEp, USB_EP_TYPE_BULK, hcdc->OutEpSize);
+	tusbhHDSetToggle(phost, hcdc->OutPipe, 0);
+	tusbhOpenPipe(pdevice, hcdc->InPipe, hcdc->InEp, USB_EP_TYPE_BULK, hcdc->InEpSize);
+	tusbhHDSetToggle(phost, hcdc->InPipe, 0);
+
+	/* タイマースタート */
+	pdevice->timeid = pdevice->timecount = 100;
+	return TUSBH_E_OK;
+}
+
+/*
+ *  CDCクラス終了設定
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  return     TUSBH_ERCODE
+ */
+static TUSBH_ERCODE
+tusbhCDCDeInit(TUSBH_Device_t *pdevice)
+{
+	CDC_Handle_t *hcdc;
+	TUSBH_Handle_t *phost = pdevice->pHost;
+
+	hcdc = (CDC_Handle_t *)pdevice->pData;
+	if(hcdc->CommInPipe != 0){
+		tusbhClosePipe(pdevice, hcdc->CommInPipe);
+		tusbFreePipe(phost, hcdc->CommInPipe);
+		hcdc->CommInPipe = 0;
+	}
+
+	if(hcdc->OutPipe != 0){
+		tusbhClosePipe(pdevice, hcdc->OutPipe);
+		tusbFreePipe(phost, hcdc->OutPipe);
+		hcdc->OutPipe = 0;
+	}
+
+	if(hcdc->InPipe != 0){
+		tusbhClosePipe(pdevice, hcdc->InPipe);
+		tusbFreePipe(phost, hcdc->InPipe);
+		hcdc->InPipe = 0;
+	}
+
+	if(pdevice->pData != NULL){
+		tusbfree(pdevice->pData);
+		pdevice->pData = NULL;
+	}
+	return TUSBH_E_OK;
+}
+
+/*
+ *  CDCクラスプロセス実行
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  parameter2 mes:      通信メッセージへのポインタ
+ *  return     TUSBH_ERCODE
+ */
+static TUSBH_ERCODE
+tusbhCDCProcess(TUSBH_Device_t *pdevice, uint8_t *mes)
+{
+	CDC_Handle_t   *hcdc  = (CDC_Handle_t *)pdevice->pData;
+	TUSBH_Handle_t *phost = pdevice->pHost;
+	void (*func)(TUSBH_Device_t *, uint8_t) = pdevice->pClass->subfunc;
+	TUSBH_URBState_t URB_Status = mes[3];
+	TUSBH_ERCODE ercd = TUSBH_E_BUSY;
+	TUSBH_ERCODE status;
+	int32_t length;
+	uint8_t cmd = CDC_LINE_STATUS_CHANGED;
+
+    if(mes[0] == TUSBH_URB_EVENT)
+		hcdc->urb_wait = 0;
+	else if(mes[0] == TUSBH_TIME_EVENT){
+		hcdc->timer += mes[3];
+		pdevice->timecount = mes[3];
+	}
+	else if(mes[0] == TUSBH_CLASS_EVENT && mes[2] != 0)
+		hcdc->state  = mes[2];
+	switch (hcdc->state){
+	case CDC_PROCESS_INIT:
+		CDC_REQUEST_GETLINE(pdevice, (uint8_t *)(&hcdc->oLineCoding));
+		hcdc->state = CDC_PROCESS_INIT_WAIT;
+		break;
+	case CDC_PROCESS_INIT_WAIT:
+		status = tusbhControlWait(pdevice, mes);
+		if(status == TUSBH_E_OK){
+			if(phost->usrcallback != NULL)
+				phost->usrcallback(phost, pdevice, HOST_USER_CLASS_ACTIVE);
+			hcdc->state = CDC_PROCESS_IDLE;
+		}
+		else if(status != TUSBH_E_BUSY && status != TUSBH_E_BUSY_URB)
+			hcdc->state = CDC_PROCESS_ERROR;
+		break;
+	case CDC_PROCESS_IDLE:
+		if(mes[0] != TUSBH_URB_EVENT){
+			ercd = TUSBH_E_OK;
+			break;
+		}
+		if(mes[2] == pdevice->cntl_pipe_in || mes[2] == pdevice->cntl_pipe_out){
+			status = tusbhControlWait(pdevice, mes);
+			if(status == TUSBH_E_OK){
+				hcdc->state = CDC_PROCESS_IDLE;
+				if((hcdc->oLineCoding.stop_bits != hcdc->uLineCoding.stop_bits) ||
+					(hcdc->oLineCoding.data_bits != hcdc->uLineCoding.data_bits) ||
+					(hcdc->oLineCoding.parity != hcdc->uLineCoding.parity) ||
+					(hcdc->oLineCoding.baudrate != hcdc->uLineCoding.baudrate)){
+						if(func != NULL)
+							func(pdevice, CDC_LINE_STATUS_CHANGED);
+				}
+			}
+			else if(status != TUSBH_E_BUSY && status != TUSBH_E_BUSY_URB)
+				hcdc->state = CDC_PROCESS_ERROR;
+		}
+		else if(hcdc->rw_status != TUSBH_E_BUSY)
+			hcdc->state = CDC_PROCESS_ERROR;
+		else if(URB_Status == TUSBH_URB_DONE){
+			if(mes[2] == hcdc->InPipe){
+				hcdc->RxTrnPktSize = tusbhHDTrasLength(phost, hcdc->InPipe);
+				cmd = CDC_LINE_STATUS_RECEIVED;
+				hcdc->RxTrnLength += hcdc->RxTrnPktSize;
+				hcdc->pRxTrnBuff += hcdc->RxTrnPktSize;
+				hcdc->state = CDC_PROCESS_IDLE;
+			}
+			else{
+				cmd = CDC_LINE_STATUS_SENDED;
+				hcdc->TxTrnLength += hcdc->TxTrnPktSize;
+				hcdc->pTxTrnBuff += hcdc->TxTrnPktSize;
+				if(hcdc->TxTrnSize > hcdc->TxTrnLength)
+					hcdc->state = CDC_PROCESS_SEND;
+				else
+					hcdc->state = CDC_PROCESS_IDLE;
+			}
+			if(hcdc->state == CDC_PROCESS_IDLE){
+				hcdc->rw_status = TUSBH_E_OK;
+				if(func != NULL)
+					func(pdevice, cmd);
+				if(hcdc->rw_taskid != 0)
+					tusbWakeup(hcdc->rw_taskid);
+			}
+		}
+		else if(URB_Status == TUSBH_URB_NOTREADY){
+			if(mes[2] == hcdc->InPipe)
+				hcdc->state = CDC_PROCESS_RECEIVE;
+			else
+				hcdc->state = CDC_PROCESS_SEND;
+		}
+		else{
+			hcdc->state = CDC_PROCESS_ERROR;
+			hcdc->rw_status = TUSBH_E_ERR;
+			if(func != NULL)
+				func(pdevice, cmd);
+			if(hcdc->rw_taskid != 0)
+				tusbWakeup(hcdc->rw_taskid);
+		}
+		tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, 0, 0);
+		break;
+	case CDC_PROCESS_SET_LINE_CODING:
+		CDC_REQUEST_SETLINE(pdevice, (uint8_t *)&hcdc->uLineCoding);
+		hcdc->state = CDC_PROCESS_SET_LINE_CODING_WAIT;
+		break;
+	case CDC_PROCESS_SET_LINE_CODING_WAIT:
+		status = tusbhControlWait(pdevice, mes);
+		if(status == TUSBH_E_OK)
+			hcdc->state = CDC_PROCESS_GET_LINE_CODING;
+		else if(status != TUSBH_E_BUSY && status != TUSBH_E_BUSY_URB)
+			hcdc->state = CDC_PROCESS_ERROR;
+		break;
+	case CDC_PROCESS_GET_LINE_CODING:
+		CDC_REQUEST_GETLINE(pdevice, (uint8_t *)&hcdc->uLineCoding);
+		hcdc->state = CDC_PROCESS_IDLE;
+		break;
+	case CDC_PROCESS_SEND:
+		length = hcdc->TxTrnSize - hcdc->TxTrnLength;
+		if(length > hcdc->OutEpSize)
+			hcdc->TxTrnPktSize = hcdc->OutEpSize;
+		else
+			hcdc->TxTrnPktSize = length;
+		tusbhBulkWrite(pdevice, hcdc->pTxTrnBuff, hcdc->TxTrnPktSize, hcdc->OutPipe);
+		hcdc->state = CDC_PROCESS_IDLE;
+		break;
+	case CDC_PROCESS_RECEIVE:
+		length = hcdc->RxTrnSize - hcdc->RxTrnLength;
+		if(length > hcdc->InEpSize)
+			hcdc->RxTrnPktSize = hcdc->InEpSize;
+		else
+			hcdc->RxTrnPktSize = length;
+		tusbhBulkRead(pdevice, hcdc->pRxTrnBuff, hcdc->RxTrnPktSize, hcdc->InPipe);
+		hcdc->state = CDC_PROCESS_IDLE;
+		break;
+	case CDC_PROCESS_ERROR:
+		tusbhClearFeature(pdevice, 0x00);
+		hcdc->state = CDC_PROCESS_ERROR_WAIT;
+		break;
+	case CDC_PROCESS_ERROR_WAIT:
+		if(tusbhControlWait(pdevice, mes) == TUSBH_E_OK)
+			hcdc->state = CDC_PROCESS_IDLE;
+		break;
+	default:
+		break;
+	}
+	return ercd;
+}
+
+/*
+ *  SERIAL LINE CODINGデータ領域を設定
+ *  parameter1 phost:   ホストハンドラ
+ *  parameter2 unit:    UNIT#
+ *  parameter3 linecod: ユーザのLINE CODING格納領域へのポインタ
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+tusbhCdcSetLineCoding(TUSBH_Handle_t *phost, uint8_t unit, Line_Coding_t *linecod)
+{
+	TUSBH_Device_t *pdevice = tusbhSearchDevice(phost, SERAIL_Class.classCode, &unit);
+	CDC_Handle_t *hcdc;
+
+	if(pdevice == NULL)
+		return TUSBH_E_OBJ;
+	hcdc = (CDC_Handle_t *)pdevice->pData;
+	if(pdevice->dstate == DEVICE_CLASS){
+		tusbmemcpy(&hcdc->uLineCoding, linecod, sizeof(Line_Coding_t));
+		tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, CDC_PROCESS_SET_LINE_CODING, 0);
+	}
+	return TUSBH_E_OK;
+}
+
+/*
+ *  SERIAL LINE CODINGデータ取得
+ *  parameter1 phost:   ホストハンドラ
+ *  parameter2 unit:    UNIT#
+ *  parameter3 linecod: LINE CODING格納領域へのポインタ
+ *  return     TUSBH_ERCODE
+*/
+TUSBH_ERCODE
+tusbhCdcGetLineCoding(TUSBH_Handle_t *phost, uint8_t unit, Line_Coding_t *linecod)
+{
+	TUSBH_Device_t *pdevice = tusbhSearchDevice(phost, SERAIL_Class.classCode, &unit);
+	CDC_Handle_t *hcdc;
+
+	if(pdevice == NULL)
+		return TUSBH_E_OBJ;
+	hcdc = pdevice->pData;
+	*linecod = hcdc->oLineCoding;
+	return TUSBH_E_OK;
+}
+
+
+/*
+ *  CDC DATA RECEIVE
+ *  parameter1 phost:   ホストハンドラ
+ *  parameter2 unit:    UNIT#
+ *  parameter3 pbuf:    受信データ領域へのポインタ
+ *  parameter4 length:  受信ブロック長
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+tusbhCdcReceive(TUSBH_Handle_t *phost, uint8_t unit, uint8_t *pbuf, uint32_t *length, uint32_t timeout)
+{
+	TUSBH_Device_t *pdevice = tusbhSearchDevice(phost, SERAIL_Class.classCode, &unit);
+	CDC_Handle_t *hcdc;
+	TUSBH_ERCODE status = TUSBH_E_BUSY;
+	uint32_t i;
+
+	if(pdevice != NULL){
+		hcdc = pdevice->pData;
+		if(pdevice->dstate != DEVICE_CLASS)
+			return TUSBH_E_OBJ;
+		if(hcdc->state == CDC_PROCESS_ERROR)
+			return TUSBH_E_ERR;
+	}
+	else
+		return TUSBH_E_OBJ;
+
+    /*
+	 *  受信データ設定
+	 */
+	hcdc->RxTrnSize   = *length;
+	hcdc->RxTrnLength = 0;
+	hcdc->pRxTrnBuff  = pbuf;
+	hcdc->rw_status = TUSBH_E_BUSY;
+	hcdc->rw_taskid = tusbGetTaskID();
+	tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, CDC_PROCESS_RECEIVE, 0);
+
+	if(timeout != 0)
+		timeout += 9;
+	timeout /= 10;
+	for(i = 0 ; i < timeout ; i++){
+		tusbSleep(10);
+		if((status = hcdc->rw_status) != TUSBH_E_BUSY)
+			break;
+	}
+	if(status == TUSBH_E_BUSY){
+		hcdc->rw_status = TUSBH_E_TMOUT;
+		status = TUSBH_E_TMOUT;
+	}
+	*length = hcdc->RxTrnLength;
+	hcdc->rw_taskid = 0;
+	return status;
+}
+
+/*
+ *  CDC DATA SEND
+ *  parameter1 phost:   ホストハンドラ
+ *  parameter2 unit:    UNIT#
+ *  parameter3 pbuf:    送信データ領域へのポインタ
+ *  parameter4 length:  送信データ長
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+tusbhCdcSend(TUSBH_Handle_t *phost, uint8_t unit, uint8_t *pbuf, uint32_t length)
+{
+	TUSBH_Device_t *pdevice = tusbhSearchDevice(phost, SERAIL_Class.classCode, &unit);
+	CDC_Handle_t *hcdc;
+	TUSBH_ERCODE status = TUSBH_E_BUSY;
+	uint32_t i;
+
+	if(pdevice != NULL){
+		hcdc = pdevice->pData;
+		if(pdevice->dstate != DEVICE_CLASS)
+			return TUSBH_E_OBJ;
+		if(hcdc->state == CDC_PROCESS_ERROR)
+			return TUSBH_E_ERR;
+	}
+	else
+		return TUSBH_E_OBJ;
+
+    /*
+	 *  送信データ設定
+	 */
+	hcdc->TxTrnSize   = length;
+	hcdc->TxTrnLength = 0;
+	hcdc->pTxTrnBuff  = pbuf;
+	hcdc->rw_status = TUSBH_E_BUSY;
+	hcdc->rw_taskid = tusbGetTaskID();
+	tusbSendData(phost->process_event, TUSBH_CLASS_EVENT, pdevice->idx, CDC_PROCESS_SEND, 0);
+
+	for(i = 0 ; i < (length * 10) ; i++){
+		tusbSleep(50);
+		if((status = hcdc->rw_status) != TUSBH_E_BUSY)
+			break;
+	}
+	if(status == TUSBH_E_BUSY){
+		hcdc->rw_status = TUSBH_E_TMOUT;
+		status = TUSBH_E_TMOUT;
+	}
+	hcdc->rw_taskid = 0;
+	return status;
+}
+
+/*
+ *  SERIALコールバック関数
+ *  parameter1 phost:   ホストハンドラ
+ *  parameter2 func:    関数ポインタ
+ */
+void
+tusbhSetCdcCallBack(TUSBH_Handle_t *phost, void (*func)(TUSBH_Device_t *p, uint8_t))
+{
+	SERAIL_Class.subfunc = func;
+}
+
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/SERIAL/tusbh_serial.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/SERIAL/tusbh_serial.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/SERIAL/tusbh_serial.h	(revision 453)
@@ -0,0 +1,165 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  USB Host Middleware CDC:SERIAL部定義
+ */
+
+#ifndef _HUSBH_SERIAL_H_
+#define _HUSBH_SERIAL_H_
+
+#include "tusbh_base.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+/*
+ *  COMMUNCATION SUB CLASS CODE定義
+ */
+#define COMMUNICATIONS_INTERFACE_CLASS  0x00
+#define DIRECT_LINE_CONTROL_MODEL       0x01
+#define ABSTRACT_CONTROL_MODEL          0x02
+#define TELEPHONE_CONTROL_MODEL         0x03
+#define MULTICHANNEL_CONTROL_MODEL      0x04
+#define CAPI_CONTROL_MODEL              0x05
+#define ETHERNET_NETWORKING_CONTROL_MODEL 0x06
+#define ATM_NETWORKING_CONTROL_MODEL    0x07
+#define WIRELESS_HANDSET_CONTROL_MODEL  0x08
+#define MOBILE_DIRECT_LINE_MODEL        0x0A
+#define ETHERNET_EMULATION_MODEL        0x0C
+#define NETWORK_CONTROL_MODEL           0x0D
+
+
+/*
+ *  COMMUNICATION INTERFCAE CLASS 制御プロトコルコード定義
+ */
+#define CDC_NO_SPECIFIC_PROTOCOL_CODE   0x00
+#define CDC_ITU_T_V_250                 0x01
+#define CDC_VENDOR_SPECIFIC             0xFF
+
+/*
+ *  DATA INTERFCAE CLASS 制御プロトコルコード定義
+ */
+#define DIC_NO_SPECIFIC_PROTOCOL_CODE   0x00
+#define DIC_USBNCM_1_0                  0x01
+
+
+#define CDC_SET_LINE_CODING             0x20
+#define CDC_GET_LINE_CODING             0x21
+#define CDC_SET_CONTROL_LINE_STATE      0x22
+#define CDC_SEND_BREAK                  0x23
+
+#define CDC_REQUEST_GETLINE_TYPE        (USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE)
+#define CDC_REQUEST_SETLINE_TYPE        (USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE)
+
+#define LINE_CODING_STRUCTURE_SIZE      0x07
+
+/*
+ *  CDCコールバックコード定義
+ */
+#define CDC_LINE_STATUS_CHANGED         1
+#define CDC_LINE_STATUS_SENDED          2
+#define CDC_LINE_STATUS_RECEIVED        3
+
+/*
+ *  CDCプロセスの状態定義
+ */
+enum
+{
+	CDC_PROCESS_INIT = 0,
+	CDC_PROCESS_INIT_WAIT,
+	CDC_PROCESS_IDLE,
+	CDC_PROCESS_SET_LINE_CODING,
+	CDC_PROCESS_SET_LINE_CODING_WAIT,
+	CDC_PROCESS_GET_LINE_CODING,
+	CDC_PROCESS_SEND,
+	CDC_PROCESS_RECEIVE,
+	CDC_PROCESS_ERROR,
+	CDC_PROCESS_ERROR_WAIT
+};
+
+/*
+ *  CDCハンドラ定義
+ */
+typedef struct
+{
+	TUSBH_Device_t            *pDev;
+	uint8_t                   state;
+	uint8_t                   dummy;
+	uint16_t                  RxTrnPktSize;
+	uint16_t                  TxTrnPktSize;
+
+	uint8_t                   CommInPipe;
+	uint8_t                   CommInEp;
+	uint16_t                  CommInEpSize;
+	uint8_t                   InPipe;
+	uint8_t                   OutPipe;
+	uint8_t                   OutEp;
+	uint8_t                   InEp;
+	uint16_t                  OutEpSize;
+	uint16_t                  InEpSize;
+	uint32_t                  RxTrnLength;
+	uint32_t                  RxTrnSize;
+	uint8_t                   *pRxTrnBuff;
+	uint32_t                  TxTrnLength;
+	uint32_t                  TxTrnSize;
+	uint8_t                   *pTxTrnBuff;
+	uint32_t                  timer;
+	uint32_t                  urb_wait;
+	ID                        rw_taskid;
+	uint32_t                  rw_status;
+	Line_Coding_t             oLineCoding;
+	Line_Coding_t             uLineCoding;
+} CDC_Handle_t;
+
+
+void         tusbhLinkSERIAL(TUSBH_Handle_t *phost);
+TUSBH_ERCODE tusbhCdcSetLineCoding(TUSBH_Handle_t *phost, uint8_t unit, Line_Coding_t *linecod);
+TUSBH_ERCODE tusbhCdcGetLineCoding(TUSBH_Handle_t *phost, uint8_t unit, Line_Coding_t *linecod);
+TUSBH_ERCODE tusbhCdcSend(TUSBH_Handle_t *phost, uint8_t unit, uint8_t *pbuf, uint32_t length);
+TUSBH_ERCODE tusbhCdcReceive(TUSBH_Handle_t *phost, uint8_t unit, uint8_t *pbuf, uint32_t *length, uint32_t timeout);
+void tusbhSetCdcCallBack(TUSBH_Handle_t *phost, void (*func)(TUSBH_Device_t *p, uint8_t));
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HUSBH_SERIAL_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/tusbh.cfg
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/tusbh.cfg	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/tusbh.cfg	(revision 453)
@@ -0,0 +1,16 @@
+/*
+ *  @(#) $Id$
+ */
+
+/*
+ *  TUSBHミドルウェアのコンフィギュレーションファイル
+ */
+
+#include "tusbh_base.h"
+
+CRE_TSK(TUSBH_P_TASK, { TA_NULL, 0, tusbhProcessTask, TUSB_PROCESS_PRIO, TUSB_PROCESS_STACK_SIZE, NULL });
+CRE_TSK(TUSBH_E_TASK, { TA_NULL, 0, tusbhEventTask, TUSB_PROCESS_PRIO-1, TUSB_HANDLE_STACK_SIZE, NULL });
+CRE_DTQ(USBH_EVT1_DTQ,{ TA_NULL, NUM_USBH_EVT1, NULL});
+CRE_DTQ(USBH_EVT2_DTQ,{ TA_NULL, NUM_USBH_EVT2, NULL});
+CRE_CYC(TUSBH_CYC_HDR, { TA_NULL, 0, tusbhCyclicHandler, 1, 0 });
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/tusbh_base.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/tusbh_base.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/tusbh_base.c	(revision 453)
@@ -0,0 +1,1104 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2019 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  USB Host Middleware BASE部
+ */
+
+#include "tusbh_base.h"
+
+
+#define USBH_ADDRESS_DEFAULT            0
+#define USBH_MPS_DEFAULT                0x40
+#define USBH_DEVICE_ADDRESS(d)          ((d)->idx + 1)
+
+#define USBH_SET_CONFIGURATION(d, i)    tusbhControlRequest((d), 0, SET_CONFIGURATION_TYPE, SET_CONFIGURATION, (i), 0, 0)
+#define USBH_SET_ADDRESS(d, a)          tusbhControlRequest((d), 0, SET_ADDRESS_TYPE, SET_ADDRESS, (a), 0, 0)
+
+#ifndef CONNECT_WAIT_TIME
+#define CONNECT_WAIT_TIME               200
+#endif
+
+static TUSBH_Handle_t *usbh_arg;
+
+/*
+ *  デバイスハンドラ初期化
+ */
+static void
+tusbhInitDevice(TUSBH_Device_t *pdevice)
+{
+	memset(pdevice->Data, 0, TUSBH_MAX_DATA_BUFFER);
+
+	pdevice->cntl_pipe_size = USBH_MPS_DEFAULT;
+	pdevice->cntl_errcount  = 0;
+	pdevice->pClass  = NULL;
+	pdevice->address = USBH_ADDRESS_DEFAULT;
+	pdevice->speed   = USB_DEVICE_SPEED_FULL;
+	pdevice->dstate  = DEVICE_IDLE;
+}
+
+/*
+ *  アロケート・デバイスハンドラ
+ */
+static TUSBH_Device_t *
+tusbhAllocDevice(TUSBH_Handle_t *phost)
+{
+	TUSBH_Device_t *pdevice;
+	int i;
+
+	if(phost->numDevice >= MAX_DEVICE_CONNECTED)
+		return NULL;
+	if((pdevice = tusbmalloc(sizeof(TUSBH_Device_t))) == NULL)
+		return NULL;
+	memset(pdevice, 0, sizeof(TUSBH_Device_t));
+	if(phost->numDevice == 0)
+		phost->pDevice = pdevice;
+	else{
+		TUSBH_Device_t *pnext = phost->pDevice;
+		for(i = 1 ; i < phost->numDevice ; i++)
+			pnext = pnext->pNext;
+		pnext->pNext = pdevice;
+	}
+	pdevice->hub   = 0xff;
+	pdevice->port  = 0xff;
+	pdevice->pHost = phost;
+	pdevice->idx  = phost->numDevice++;
+	tusbhInitDevice(pdevice);
+	return pdevice;
+}
+
+/*
+ *  デバイスハンドラ検索
+ */
+static TUSBH_Device_t*
+tusbhFindDevice(TUSBH_Handle_t *phost, uint8_t idx)
+{
+	TUSBH_Device_t *pdevice = phost->pDevice;
+	uint8_t i;
+
+	for(i = 0 ; i < idx ; i++)
+		pdevice = pdevice->pNext;
+	return pdevice;
+}
+
+/*
+ *  有効デバイス数
+ */
+static uint8_t
+tusbActivateDevice(TUSBH_Handle_t *phost)
+{
+	TUSBH_Device_t *pdevice = phost->pDevice;
+	uint8_t i, actdevice = 0;
+
+	for(i = 0 ; i < phost->numDevice && pdevice != NULL ; i++){
+		if(pdevice->pClass != NULL)
+			actdevice++;
+		pdevice = pdevice->pNext;
+	}
+	return actdevice;
+}
+
+/*
+ *  SEARCH DEVICE
+ *  parameter1 phost:     ホストハンドラ
+ *  parameter2 classCide: クラスコード
+ *  parameter3 plun:      unit#
+ *  return     デバイスハンドラ
+ */
+TUSBH_Device_t *
+tusbhSearchDevice(TUSBH_Handle_t *phost, uint8_t classCode, uint8_t *plun)
+{
+	TUSBH_Device_t *pdevice = phost->pDevice;
+	uint8_t i;
+
+	for(i = 0 ; i < phost->numDevice && pdevice != NULL ; i++){
+		if(pdevice->type == classCode){
+			if(*plun < pdevice->numUnit)
+				break;
+			else
+				*plun -= pdevice->numUnit;
+		}
+		pdevice = pdevice->pNext;
+	}
+	return pdevice;
+}
+
+
+/*
+ *  HC-PIPEのアロケート
+ *  parameter1 pdevice: デバイスハンドラ
+ *  parameter2 ep_addr: エンドポイントアドレス
+ *  return     PIPE番号(0xFFでエラー)
+ */
+uint8_t
+tusbhAllocPipe(TUSBH_Handle_t *phost, uint8_t ep_addr)
+{
+	uint8_t idx = 0;
+
+	for(idx = 0 ; idx < phost->numPipes ; idx++){
+		if((phost->pipes[idx].attribute & PIPE_ACTIVATE) == 0 && tusbhHDCheckPipe(phost, idx)){
+			phost->pipes[idx].attribute = PIPE_ACTIVATE | ep_addr;
+			return idx;
+		}
+	}
+	syslog_2(LOG_ERROR, "tusbhAllocPipe no free pipe [%08x] ep(%d) !", phost, ep_addr);
+	return 0xFF;
+}
+
+/*
+ *  HC-PIPEの解放
+ *  parameter1 pdevice: デバイスハンドラ
+ *  parameter2 no:      PIPE番号
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+tusbFreePipe(TUSBH_Handle_t *phost, uint8_t no)
+{
+	if(no < phost->numPipes){
+		phost->pipes[no].attribute &= ~PIPE_ACTIVATE;
+	}
+	return TUSBH_E_OK;
+}
+
+
+/*
+ *  USBホスト初期化処理
+ *  parameter1 phost:   ホストハンドラ
+ *  parameter2 pufunc:ユーザポインタ関数
+ *  parameter3 id:      USBホストID
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+tusbhInit(TUSBH_Handle_t *phost, void (*pufunc)(TUSBH_Handle_t *phost, TUSBH_Device_t *pdevice, uint8_t ), uint8_t id)
+{
+	uint8_t i;
+
+	/*
+	 *  USBホスト構造体の確認
+	 */
+	if(phost == NULL){
+		syslog_0(LOG_ERROR, "Invalid Host handle !");
+		return TUSBH_E_PAR; 
+	}
+
+	/*
+	 *  ホストIDをセット
+	 */
+	phost->id = id;
+
+	/*
+	 *  リンクカウントを初期化
+	 */
+	phost->numClass = 0;
+	phost->numDevice = 0;
+	phost->numHub    = 0;
+
+	/*
+	 *  PIPEの初期化
+	 */
+	for(i = 0 ; i < MAX_EPS_PIPES; i++){
+		phost->pipes[i].attribute = 0;
+		phost->pipes[i].index     = 0;
+	}
+
+	/*
+	 *  ユーザー関数の保存
+	 */
+	if(pufunc != NULL)
+		phost->usrcallback = pufunc;
+
+	/*
+	 * タスク用にUSBホストハンドラを保存
+	 */
+	usbh_arg = phost;
+
+	/*
+	 *  LOWレベルドライバの初期化
+	 */
+	tusbhHDInit(phost);
+
+	/*
+	 *  タスクの起動
+	 */
+	tusbStartTask(phost->eventTaskID);
+	tusbStartTask(phost->processTaskID);
+	return TUSBH_E_OK;
+}
+
+/*
+ *  USBホスト終了処理
+ *  parameter1 phost:   ホストハンドラ
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+tusbhDeInit(TUSBH_Handle_t *phost)
+{
+	TUSBH_Device_t *pdevice;
+	uint8_t idx;
+
+	for(idx = 0, pdevice = phost->pDevice ; idx < phost->numDevice ; idx++){
+		tusbfree(pdevice);
+		pdevice = pdevice->pNext;
+	}
+	phost->pDevice = 0;
+
+	if(phost->pSysData != NULL){
+		tusbhHDStop(phost);
+	}
+	return TUSBH_E_OK;
+}
+
+/*
+ *  クラス実行モジュールのリンク
+ *  parameter1 phost:   ホストハンドラ
+ *  parameter2 pclass:  クラス構造体へのポインタ
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+tusbhLinkClass(TUSBH_Handle_t *phost, TUSBH_Class_t *pclass)
+{
+	if(pclass == NULL)
+		return TUSBH_E_ERR;
+	pclass->pNext = NULL;
+	if(phost->numClass == 0)
+		phost->pClass = pclass;
+	else{
+		TUSBH_Class_t *pnext = phost->pClass;
+		uint32_t i;
+		for(i = 1 ; i < phost->numClass ; i++)
+			pnext = pnext->pNext;
+		pnext->pNext = pclass;
+	}
+	phost->numClass++;
+	return TUSBH_E_OK;
+}
+
+/*
+ *  USBホスト開始
+ *  parameter1 phost:   ホストハンドラ
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+tusbhStart(TUSBH_Handle_t *phost)
+{
+	/*
+	 *  LOWレベルドライバをスタート
+	 */
+	tusbhHDStart(phost);
+
+	/*
+	 *  VBUSを有効化
+	 */
+	tusbhHDControlVBUS(phost, true);
+	return TUSBH_E_OK;
+}
+
+/*
+ *  USBホスト停止
+ *  parameter1 phost:   ホストハンドラ
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+tusbhStop(TUSBH_Handle_t *phost)
+{
+	TUSBH_Device_t *pdevice = phost->pDevice;
+	uint8_t i = 0;
+
+	/*
+	 *  LOWレベルドライバ停止
+	 */
+	tusbhHDStop(phost);
+
+	/*
+	 *  VBUSの停止
+	 */ 
+	tusbhHDControlVBUS(phost, false);
+
+	/*
+	 *  PIPEの解放
+	 */
+	for(i = 0 ; i < phost->numDevice && pdevice != NULL ; i++){
+		tusbFreePipe(phost, pdevice->cntl_pipe_in);
+		tusbFreePipe(phost, pdevice->cntl_pipe_out);
+		pdevice = pdevice->pNext;
+	}
+	return TUSBH_E_OK;
+}
+
+/*
+ *  HUBのリセット要求
+ *  parameter1 pdevice: デバイスハンドラ
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+tusbhResetHub(TUSBH_Device_t *pdevice)
+{
+	TUSBH_Handle_t *phost = pdevice->pHost;
+	TUSBH_Device_t *pdeviceh;
+	uint32_t idx;
+
+	syslog_2(LOG_ERROR, "tusbhResetHub hub(%d) port(%d) !", pdevice->hub, pdevice->port);
+	for(idx = 0, pdeviceh = phost->pDevice ; idx < phost->numDevice ; idx++){
+		if(pdevice->hub == pdeviceh->hubid){
+			tusbSendData(phost->process_event, TUSBH_RESET_EVENT, pdeviceh->idx, 0, pdevice->port);
+			break;
+		}
+		pdeviceh = pdeviceh->pNext;
+	}
+	return TUSBH_E_OK;
+}
+
+/*
+ *  デバイスにインターフェイスを設定
+ *  parameter1 pdevice: デバイスハンドラ
+ *  parameter2 interface: インターフェイス値
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+tusbhSelectInterface(TUSBH_Device_t *pdevice, uint8_t interface)
+{
+	TUSBH_ERCODE ercd = TUSBH_E_OK;
+
+	if(interface < pdevice->CfgDesc.bNumInterfaces){
+		pdevice->sel_interface = interface;
+		syslog_2(LOG_NOTICE, "Switching to Interface device(%d) (#%d)", pdevice->idx, interface);
+		syslog_1(LOG_NOTICE, "Class    : 0x%02x", pdevice->ItfDesc[interface].bInterfaceClass );
+		syslog_1(LOG_NOTICE, "SubClass : 0x%02x", pdevice->ItfDesc[interface].bInterfaceSubClass );
+		syslog_1(LOG_NOTICE, "Protocol : 0x%02x", pdevice->ItfDesc[interface].bInterfaceProtocol );
+	}
+	else{
+		syslog_1(LOG_ERROR, "Cannot Select This Interface (%d) !", pdevice->idx);
+		ercd = TUSBH_E_ERR; 
+	}
+	return ercd;
+}
+
+/*
+ *  クラス番号を取得
+ *  parameter1 pdevice: デバイスハンドラ
+ *  return     Class code
+ */
+uint8_t
+tusbhGetActiveClass(TUSBH_Device_t *pdevice)
+{
+	return (pdevice->ItfDesc[0].bInterfaceClass);
+}
+
+/*
+ *  クラス情報からインターフェイスのインデックスを返す
+ *  parameter1 pdevice: デバイスハンドラ
+ *  parameter2 Class:   Class code
+ *  parameter3 SubClass:Sub Class code
+ *  parameter4 Protocal:Protocol code
+ *  return     interface index(ない場合はNO_INTERFACE)
+ */
+uint8_t
+tusbhFindInterface(TUSBH_Device_t *pdevice, uint8_t Class, uint8_t SubClass, uint8_t Protocol)
+{
+	InterfaceDescriptor    *pif = NULL;
+	int8_t                 if_ix = 0;
+
+	while(if_ix < TUSBH_MAX_NUM_INTERFACES){
+		pif = &pdevice->ItfDesc[if_ix];
+		if((pif->bInterfaceClass == Class || Class == 0xFF) &&
+			(pif->bInterfaceSubClass == SubClass || SubClass == 0xFF) &&
+				(pif->bInterfaceProtocol == Protocol || Protocol == 0xFF)){
+			return  if_ix;
+		}
+		if_ix++;
+	}
+	return NO_INTERFACE;
+}
+
+/*
+ *  インターフェイス情報からインターフェイスのインデックスを返す
+ *  parameter1 pdevice: デバイスハンドラ
+ *  parameter2 interface: interface number
+ *  parameter3 altsetnum: alternate setting #
+ *  return     interface index(ない場合は0xff)
+ */
+uint8_t
+tusbhFindInterfacebynumber(TUSBH_Device_t *pdevice, uint8_t interface, uint8_t altsetno)
+{
+	InterfaceDescriptor    *pif = NULL;
+	int8_t                 if_ix = 0;
+
+	while (if_ix < TUSBH_MAX_NUM_INTERFACES){
+		pif = &pdevice->ItfDesc[if_ix];
+		if((pif->bInterfaceNumber == interface) && (pif->bAlternateSetting == altsetno)){
+			return  if_ix;
+		}
+		if_ix++;
+	}
+	return 0xFF;
+}
+
+/*
+ *  OPEN PIPE
+ *  parameter1 pdevice: デバイスハンドラ
+ *  parameter2 pipe:    PIPE#
+ *  parameter3 epnum:   EP番号
+ *  parameter5 type:    エンドポイントタイプ
+ *  parameter6 eps:     MAXパケットサイズ
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+tusbhOpenPipe(TUSBH_Device_t *pdevice, uint8_t pipe, uint8_t epnum, uint8_t type, uint16_t mps)
+{
+	TUSBH_Handle_t *phost = pdevice->pHost;
+
+	phost->pipes[pipe].type = type;
+	return tusbhHDOpenPipe(phost, pipe, epnum, pdevice->address, pdevice->speed, type, mps);
+}
+
+/*
+ *  CLOSE PIPE
+ *  parameter1 pdevice: デバイスハンドラ
+ *  parameter2 pipe:    PIPE#
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+tusbhClosePipe(TUSBH_Device_t *pdevice, uint8_t pipe)
+{
+	return tusbhHDClosePipe(pdevice->pHost, pipe);
+}
+
+/*
+ *  SUBMIT URB
+ *  parameter1 pdevice: デバイスハンドラ
+ *  parameter2 pipe:    パイプ番号
+ *  parameter3 type:    SUBMITタイプ
+ *  parameter4 eptype:  エンドポイントタイプ
+ *  parameter5 buff:    データ領域へのポインタ
+ *  parameter6 length:  データ長
+ *  return     TUSBH_ERCODE
+ */
+TUSBH_ERCODE
+tusbhSubmitURB(TUSBH_Device_t *pdevice, uint8_t pipe, uint16_t type, uint8_t eptype, uint8_t* buff, uint16_t length)
+{
+	TUSBH_Handle_t *phost = pdevice->pHost;
+	uint8_t dir, token;
+	uint8_t do_ping = 0;
+
+	phost->pipes[pipe].index = pdevice->idx;
+	if(eptype != phost->pipes[pipe].type){
+		syslog_3(LOG_ERROR, "tusbhSubmitURB EPTYPE ERROR pipe(%d) rtype(%d) ctype(%d) !", pipe, eptype, phost->pipes[pipe].type);
+		return TUSBH_E_ERR;
+	}
+	if(eptype == USB_EP_TYPE_BULK || eptype == USB_EP_TYPE_CTRL){
+		if(pdevice->speed == USB_DEVICE_SPEED_HIGH && type == SUBMIT_WRITE)
+			do_ping = 1;
+	}
+	dir   = type >> 8;
+	token = type & 0xff;
+	return tsubhHDSubmitURB(phost, pipe, dir, token, buff, length, do_ping);
+}
+
+/*
+ *  Device Descriporコマンドをデバイスに送信し取得する
+ *  parameter1 pdevice: デバイスハンドラ
+ *  parameter2 length:  Descripor長
+ *  return     TUSBH_ERCODE
+ */
+static TUSBH_ERCODE
+tusbhGetDeviceDescriptor(TUSBH_Device_t *pdevice, uint8_t length)
+{
+	TUSBH_ERCODE  ercd;
+	volatile uint8_t    *buff = pdevice->Data;
+	DeviceDescriptor *dev_desc = &pdevice->DevDesc;
+
+	if((ercd = tusbhGetDescriptor(pdevice,
+                                  USB_RECIPIENT_DEVICE | USB_REQUEST_TYPE_STANDARD,                          
+                                  ((DEVICE_DESCRIPTOR << 8) & 0xFF00),
+                                  (uint8_t *)buff,
+                                  length)) == TUSBH_E_OK){
+		/*
+		 *  DEVICE DESCRIPTER取得
+		 */
+		dev_desc->bLength            = buff[0];
+		dev_desc->bDescriptorType    = buff[1];
+		dev_desc->bcdUSB             = (buff[2] & 0xff) | (buff[3] << 8);
+		dev_desc->bDeviceClass       = buff[4];
+		dev_desc->bDeviceSubClass    = buff[5];
+		dev_desc->bDeviceProtocol    = buff[6];
+		dev_desc->bMaxPacketSize     = buff[7];
+
+		if(length > 8){ /* For 1st time after device connection, Host may issue only 8 bytes for   Device Descriptor Length  */
+			dev_desc->idVendor           = (buff[8]  & 0xff) | (buff[9]  << 8);
+			dev_desc->idProduct          = (buff[10] & 0xff) | (buff[11] << 8);
+			dev_desc->bcdDevice          = (buff[12] & 0xff) | (buff[12] << 8);
+			dev_desc->iManufacturer      = buff[14];
+			dev_desc->iProduct           = buff[15];
+			dev_desc->iSerialNumber      = buff[16];
+			dev_desc->bNumConfigurations = buff[17];
+		}
+	}
+	return ercd;
+}
+
+/*
+ *  Config Descriporコマンドをデバイスに送信し取得する
+ *  parameter1 pdevice: デバイスハンドラ
+ *  parameter2 length:  Descripor長
+ *  return     TUSBH_ERCODE
+ */
+static TUSBH_ERCODE
+tusbhGetConfigDescriptor(TUSBH_Device_t *pdevice, uint16_t length)
+{
+	ConfigurationDescriptor *cfg_desc = &pdevice->CfgDesc;
+	TUSBH_Handle_t     *phost = pdevice->pHost;
+	volatile uint8_t   *pdbuff;
+	TUSBH_ERCODE ercd;
+
+	if(phost->pCfgData != NULL)
+		pdbuff = (volatile uint8_t *)phost->pCfgData;
+	else
+		pdbuff = (volatile uint8_t *)pdevice->Data;
+	if((ercd = tusbhGetDescriptor(pdevice,
+                                  USB_RECIPIENT_DEVICE | USB_REQUEST_TYPE_STANDARD,
+                                  ((CONFIGURATION_DESCRIPTOR << 8) & 0xFF00),
+                                  (uint8_t *)pdbuff,
+                                  length)) == TUSBH_E_OK){
+
+		/*
+		 *  CONFIGURATION DESCRIPTOR設定
+		 */
+		cfg_desc->bLength             = pdbuff[0];
+		cfg_desc->bDescriptorType     = pdbuff[1];
+		cfg_desc->wTotalLength        = (pdbuff[2] & 0xff) | (pdbuff[3] << 8);
+		cfg_desc->bNumInterfaces      = pdbuff[4];
+		cfg_desc->bConfigurationValue = pdbuff[5];
+		cfg_desc->iConfiguration      = pdbuff[6];
+		cfg_desc->bmAttributes        = pdbuff[7];
+		cfg_desc->bMaxPower           = pdbuff[8];
+
+		if (length > CONFIGURATION_DESCRIPTOR_LENGTH){
+			uint16_t ptr = CONFIGURATION_DESCRIPTOR_LENGTH;
+			int8_t   if_ix = 0;
+			int8_t   ep_ix = 0;
+
+			while(if_ix < TUSBH_MAX_NUM_INTERFACES && ptr < cfg_desc->wTotalLength){
+				ptr += pdbuff[0];
+				pdbuff = (volatile uint8_t *)(pdbuff + pdbuff[0]);
+				if(pdbuff[1] == INTERFACE_DESCRIPTOR){
+					InterfaceDescriptor *pif = &pdevice->ItfDesc[if_ix];
+					/*
+					 *  INTERFACE DESCRIPTOR設定
+					 */
+  					pif->bLength            = pdbuff[0];
+					pif->bDescriptorType    = pdbuff[1];
+					pif->bInterfaceNumber   = pdbuff[2];
+					pif->bAlternateSetting  = pdbuff[3];
+					pif->bNumEndpoints      = pdbuff[4];
+					pif->bInterfaceClass    = pdbuff[5];
+					pif->bInterfaceSubClass = pdbuff[6];
+					pif->bInterfaceProtocol = pdbuff[7];
+					pif->iInterface         = pdbuff[8];
+
+					ep_ix = 0;
+					while ((ep_ix < pif->bNumEndpoints) && (ptr < cfg_desc->wTotalLength)){
+						ptr += pdbuff[0];
+						pdbuff = (volatile uint8_t *)(pdbuff + pdbuff[0]);
+						if(pdbuff[1] == ENDPOINT_DESCRIPTOR){
+							EndpointDescriptor *pep = &pdevice->EpDesc[if_ix][ep_ix];
+							/*
+							 *  ENDPOINT DESCRIPTOR設定
+							 */
+							pep->bLength          = pdbuff[0];
+							pep->bDescriptorType  = pdbuff[1];
+							pep->bEndpointAddress = pdbuff[2];
+							pep->bmAttributes     = pdbuff[3];
+							pep->wMaxPacketSize   = (pdbuff[4] & 0xff) | (pdbuff[5] << 8);
+							pep->bInterval        = pdbuff[6];
+							ep_ix++;
+						}
+					}
+					if_ix++;
+				}
+			}
+		}
+	}
+	return ercd;
+}
+
+/*
+ *  String Descriporコマンドをデバイスに送信
+ *  parameter1 pdevice: デバイスハンドラ
+ *  parameter2 string_index:  String index
+ *  parameter3 buff:          取り出し用のバッファ領域
+ *  parameter4 length:        Descripor長
+ *  return     TUSBH_ERCODE
+ */
+static TUSBH_ERCODE
+tusbhGetStringDescriptor(TUSBH_Device_t *pdevice,
+                                uint8_t string_index, 
+                                uint8_t *buff, 
+                                uint16_t length)
+{
+	uint8_t *psrc = pdevice->Data;
+	TUSBH_ERCODE ercd;
+
+	if((ercd = tusbhGetDescriptor(pdevice,
+                                  USB_RECIPIENT_DEVICE | USB_REQUEST_TYPE_STANDARD,
+                                  ((STRING_DESCRIPTOR << 8) & 0xFF00) | string_index, 
+                                  psrc,
+                                  length)) == TUSBH_E_OK){
+  		/*
+		 * UINCODEをアスキー文字列に変換
+		 */
+		if(psrc[1] == STRING_DESCRIPTOR){ /* String Typeならバッファにセット */
+			int strlength = psrc[0]-2;
+			uint32_t i;
+			for(i = 0 ; i < length && i < strlength ; i += 2){
+				*buff++ =  psrc[i+2];
+			}
+			*buff = 0;
+		}
+	}
+	return ercd;
+}
+
+/*
+ *  USBのエナミュレートを実行する
+ *  parameter1 pdevice: デバイスハンドラ
+ *  return     TUSBH_ERCODE
+ */
+static TUSBH_ERCODE
+tusbhEnumerate(TUSBH_Device_t *pdevice)
+{
+	TUSBH_ERCODE ercd = TUSBH_E_OK;
+
+	/*
+	 *  8バイトで Device Descriptorを取得
+	 */
+	if((ercd = tusbhGetDeviceDescriptor(pdevice, 8)) != TUSBH_E_OK)
+		return ercd;
+
+	/*
+	 *  bMaxPacketSizeでパイプを再オープン
+	 */
+	pdevice->cntl_pipe_size = pdevice->DevDesc.bMaxPacketSize;
+	tusbhOpenPipe(pdevice, pdevice->cntl_pipe_in, 0x80, USB_EP_TYPE_CTRL,
+				pdevice->cntl_pipe_size);
+
+	tusbhOpenPipe(pdevice, pdevice->cntl_pipe_out, 0x00, USB_EP_TYPE_CTRL,
+				pdevice->cntl_pipe_size);
+
+	/*
+	 *  フルサイズで Device Descriptorを取得
+	 */
+	if((ercd != tusbhGetDeviceDescriptor(pdevice, DEVICE_DESCRIPTOR_LENGTH)) != TUSBH_E_OK)
+		return ercd;
+
+	syslog_1(LOG_NOTICE, "VID: 0x%04x", pdevice->DevDesc.idVendor );
+	syslog_1(LOG_NOTICE, "PID: 0x%04x", pdevice->DevDesc.idProduct);
+
+	/*
+	 *  デバイスにデバイスアドレスをセット
+	 */
+	if((ercd = USBH_SET_ADDRESS(pdevice, USBH_DEVICE_ADDRESS(pdevice))) != TUSBH_E_OK)
+		return ercd;
+
+	/*
+	 *  設定アドレスでパイプを再オープン
+	 */
+	tusbDelay(2);
+	pdevice->address = USBH_DEVICE_ADDRESS(pdevice);
+	syslog_1(LOG_NOTICE, "Address (#%d) assigned.", pdevice->address);
+
+	tusbhOpenPipe(pdevice, pdevice->cntl_pipe_in, 0x80, USB_EP_TYPE_CTRL,
+				pdevice->cntl_pipe_size);
+
+	tusbhOpenPipe(pdevice, pdevice->cntl_pipe_out, 0x00, USB_EP_TYPE_CTRL,
+				pdevice->cntl_pipe_size);
+
+	/*
+	 *  スタンダードサイズで Configuration descriptorを取得
+	 */
+	if((ercd = tusbhGetConfigDescriptor(pdevice, CONFIGURATION_DESCRIPTOR_LENGTH)) != TUSBH_E_OK)
+		return ercd;
+
+	/*
+	 *  フルサイズでConfiguraion Descriptorを取得
+	 */
+	if((ercd = tusbhGetConfigDescriptor(pdevice, pdevice->CfgDesc.wTotalLength)) != TUSBH_E_OK)
+		return ercd;
+
+	/*
+	 *  Manufacturer文字列を取得
+	 */
+	if(pdevice->DevDesc.iManufacturer != 0){ /* Check that Manufacturer String is available */
+		if(tusbhGetStringDescriptor(pdevice, pdevice->DevDesc.iManufacturer, 
+				pdevice->Data , 0xff) == TUSBH_E_OK){
+			strncpy(pdevice->Manufacturer, (const char *)pdevice->Data, TUSBH_STR_LENGTH);
+			/*
+			 *  Manufacturingを表示
+			 */
+			syslog_1(LOG_NOTICE, "Manufacturer : %s",  pdevice->Manufacturer);
+		}
+	}
+	else
+		syslog_0(LOG_NOTICE, "Manufacturer : N/A");
+
+	/*
+	 *  Product文字列を取得
+	 */
+	if(pdevice->DevDesc.iProduct != 0){ /* Check that Product string is available */
+		if(tusbhGetStringDescriptor(pdevice, pdevice->DevDesc.iProduct, 
+						pdevice->Data, 0xff) == TUSBH_E_OK){
+			strncpy(pdevice->Prodeuct, (const char *)pdevice->Data, TUSBH_STR_LENGTH);
+			/* User callback for Product string */
+			syslog_1(LOG_NOTICE, "Product : %s",  pdevice->Prodeuct);
+		}
+	}
+	else
+		syslog_0(LOG_NOTICE, "Product : N/A");
+
+	/*
+	 *  シリアル番号取得
+	 */
+	if(pdevice->DevDesc.iSerialNumber != 0){ /* Check that Serial number string is available */    
+		if((ercd = tusbhGetStringDescriptor(pdevice, pdevice->DevDesc.iSerialNumber, 
+						pdevice->Data, 0xff)) == TUSBH_E_OK){
+			strncpy(pdevice->Serial, (const char *)pdevice->Data, TUSBH_STR_LENGTH);
+			/* User callback for Serial number string */
+			syslog_1(LOG_NOTICE, "Serial Number : %s",  pdevice->Serial);
+		}
+	}
+	else{
+		syslog_0(LOG_NOTICE, "Serial Number : N/A"); 
+		ercd = TUSBH_E_OK;
+	}
+	return ercd;
+}
+
+/*
+ *  USBホストプロセスタスク
+ */
+void
+tusbhProcessTask(intptr_t exinf)
+{
+	TUSBH_Handle_t *phost = usbh_arg;
+	TUSBH_Device_t *pdevice;
+	TUSBH_Class_t  *pnext;
+	TUSBH_ERCODE ercd = TUSBH_E_OK;
+	ER           rercd;
+	uint8_t mes[4];
+	uint32_t no;
+
+	for(;;){
+		rercd = tusbRecvData(phost->process_event, mes, 0);
+		if(rercd == E_OK){
+			if((pdevice = tusbhFindDevice(phost, mes[1])) == NULL){
+				syslog_1(LOG_NOTICE, "USBH no device message(%d) !", mes[1]);
+				continue;
+			}
+			pdevice = tusbhFindDevice(phost, mes[1]);
+			switch (pdevice->dstate){
+			case DEVICE_ATTACHED:
+				syslog_2(LOG_NOTICE, "USBH Device Attached(%d) speed(%d) !", pdevice->idx, pdevice->speed);
+				if(phost->usrcallback != NULL)
+					phost->usrcallback(phost, pdevice, HOST_USER_CONNECTION);
+
+				/*
+				 *  100ms待ちコントロール通信用PIPEをアサイン
+				 */
+				tusbDelay(100); 
+
+				pdevice->cntl_pipe_out = tusbhAllocPipe(phost, 0x00);
+				pdevice->cntl_pipe_in  = tusbhAllocPipe(phost, 0x80);
+
+				/*
+				 *  IN/OUTのPIPEをオープン
+				 */
+				tusbhOpenPipe(pdevice, pdevice->cntl_pipe_in, 0x80, USB_EP_TYPE_CTRL,
+								pdevice->cntl_pipe_size);
+
+				tusbhOpenPipe(pdevice, pdevice->cntl_pipe_out, 0x00, USB_EP_TYPE_CTRL,
+								pdevice->cntl_pipe_size);
+				pdevice->numUnit = 1;
+				pdevice->pre_connected = 0;
+
+				/*
+				 *  エナミュレーション実行
+				 */
+				if((ercd = tusbhEnumerate(pdevice)) == TUSBH_E_OK){
+					syslog_1(LOG_NOTICE, "Enumeration done(%d) !", pdevice->idx);
+					pdevice->sel_interface = 0;
+					if(pdevice->DevDesc.bNumConfigurations != 1){
+						if(phost->usrcallback != NULL)
+							phost->usrcallback(phost, pdevice, HOST_USER_SELECT_CONFIGURATION);
+					}
+					else
+						syslog_1(LOG_NOTICE, "This device has only 1 configuration(%d) !", pdevice->idx);
+					if(USBH_SET_CONFIGURATION(pdevice, pdevice->CfgDesc.bConfigurationValue) == TUSBH_E_OK){
+						pdevice->dstate  = DEVICE_CHECK_CLASS;
+						syslog_1(LOG_NOTICE, "Default configuration set(%d) !", pdevice->idx);
+					}
+					else if(ercd == TUSBH_E_ERR){
+						pdevice->dstate = DEVICE_DISCONNECTED;
+						syslog_1(LOG_ERROR, "Enumeration set configuraion error(%) !", pdevice->idx);
+						tusbSendData(phost->process_event, TUSBH_PORT_EVENT, pdevice->idx, 0, 0);
+					}
+				}
+				else{
+					pdevice->dstate = DEVICE_DISCONNECTED;
+					syslog_2(LOG_ERROR, "Enumeration sequence fail idx(%d) ercd(%d) !", pdevice->idx, ercd);
+					tusbSendData(phost->process_event, TUSBH_PORT_EVENT, pdevice->idx, 0, 0);
+				}
+				break;
+			case DEVICE_CHECK_CLASS:
+				pdevice->pClass = NULL;
+				for(no = 0, pnext = phost->pClass ; no < phost->numClass ; no++){
+					if(pnext->classCode == pdevice->ItfDesc[0].bInterfaceClass){
+						pdevice->pClass = pnext;
+						break;
+					}
+					pnext = pnext->pNext;
+				}
+				if(pdevice->pClass != NULL){
+					if((ercd = pdevice->pClass->Init(pdevice)) == TUSBH_E_OK){
+						syslog_2(LOG_NOTICE, "Class start[%s] (%d) !", pdevice->pClass->Name, pdevice->idx);
+						pdevice->dstate  = DEVICE_CLASS;
+						pdevice->type    = pdevice->pClass->classCode;
+						if(phost->usrcallback != NULL)
+							phost->usrcallback(phost, pdevice, HOST_USER_CLASS_SELECTED);
+						if(tusbActivateDevice(phost) == 1)
+							tusbTimerControl(1);
+					}
+					else{
+						pdevice->dstate  = DEVICE_ABORT_STATE;
+						syslog_3(LOG_ERROR, "Class[%s] initial error(%d) (%d) !", pdevice->pClass->Name, ercd, pdevice->idx);
+					}
+				}
+				else{
+					pdevice->dstate  = DEVICE_ABORT_STATE;
+					syslog_1(LOG_ERROR, "No registered class for this device(%d) !", pdevice->idx);
+				}
+				break;
+			case DEVICE_CLASS:
+				/*
+				 *  USB HOSTクラス処理
+				 */
+				if(pdevice->pClass != NULL)
+					pdevice->pClass->Process(pdevice, mes);
+				break;
+			case DEVICE_DISCONNECTED:
+				/*
+				 *  USB HOSTクラスの終了処理
+				 */
+				syslog_1(LOG_NOTICE, "USBH device disconnect(%d) !", pdevice->idx);
+				if(pdevice->pClass != NULL){
+					pdevice->pClass->DeInit(pdevice); 
+					pdevice->pClass = NULL;
+				}
+				tusbhInitDevice(pdevice);
+				if(tusbActivateDevice(phost) == 0)
+					tusbTimerControl(0);
+				pdevice->dstate = DEVICE_IDLE;
+				break;
+
+			case DEVICE_IDLE:
+			case DEVICE_ABORT_STATE:
+			default :
+				break;
+			}
+		}
+	}
+}
+
+/*
+ *  タイマハンドラ
+ */
+void
+tusbhCyclicHandler(intptr_t exinf)
+{
+	TUSBH_Handle_t *phost = usbh_arg;
+	TUSBH_Device_t *pdevice;
+	uint8_t i;
+
+	if(phost == NULL)
+		return;
+	pdevice = phost->pDevice;
+	for(i = 0 ; i < phost->numDevice && pdevice != NULL ; i++){
+		if(pdevice->pClass != NULL && pdevice->timecount > 0){
+			if(--pdevice->timecount == 0)
+				tusbiSendData(phost->process_event, TUSBH_TIME_EVENT, pdevice->idx, 0, pdevice->timeid);
+		}
+		pdevice = pdevice->pNext;
+	}
+}
+
+/*
+ *  USBデバイスコネクト処理
+ */
+static void
+tusbhHandleConnect(TUSBH_Handle_t *phost, uint8_t hub, uint8_t port, uint8_t prm)
+{
+	TUSBH_Device_t *pdevice;
+	uint32_t no;
+
+	for(no = 0, pdevice = phost->pDevice ; no < phost->numDevice && pdevice != NULL ; no++){
+		if(pdevice->activate != 0 && pdevice->hub == hub && pdevice->port == port){
+			break;
+		}
+		pdevice = pdevice->pNext;
+	}
+	if(pdevice == NULL){
+		pdevice = tusbhAllocDevice(phost);
+		if(pdevice == NULL || pdevice->idx != no){
+			syslog_2(LOG_ERROR, "usbh device allocation error (%d)(%d) !", no, pdevice->idx);
+			return;
+		}
+	}
+	if(phost->numClass == 0)
+		syslog_0(LOG_ERROR, "No Regist Class !");
+	else if(pdevice != NULL){
+		if(pdevice->pre_connected == 0){
+			syslog_4(LOG_INFO, "connect pdevice[%08x] hub(%d) port(%d) speed(%d) !", pdevice, hub, port, prm);
+			pdevice->hub  = hub;
+			pdevice->port = port;
+			pdevice->activate = 1;
+			pdevice->pre_connected = 1;
+
+			/*
+			 *  接続後 CONNECT_WAIT_TIME ms待ち
+			 */
+			tusbDelay(CONNECT_WAIT_TIME);
+			if(hub == 0){
+				tusbhHDResetPort(phost);
+				tusbDelay(100);
+				pdevice->speed = tusbhHDGetSpeed(phost);
+			}
+			else{
+				pdevice->speed = prm;
+				tusbDelay(200);
+			}
+			pdevice->is_connected = 1;
+			if(pdevice->dstate == DEVICE_IDLE){
+				pdevice->dstate = DEVICE_ATTACHED;
+				tusbSendData(phost->process_event, TUSBH_PORT_EVENT, pdevice->idx, 0, 0);
+			}
+		}
+		else if(pdevice->dstate == DEVICE_DISCONNECTED)
+			tusbSendData(phost->process_event, TUSBH_PORT_EVENT, pdevice->idx, 0, 0);
+	}
+}
+
+/*
+ *  USBデバイスディスコネクト処理
+ */
+static void
+tusbhHandleDisconnect(TUSBH_Handle_t *phost, uint8_t hub, uint8_t port, uint8_t prm)
+{
+	TUSBH_Device_t *pdevice = phost->pDevice;
+	uint32_t no;
+
+	for(no = 0 ; no < phost->numDevice ; no++, pdevice = pdevice->pNext){
+		if(pdevice == NULL)
+			return;
+		if(pdevice->activate != 0 && pdevice->hub == hub && pdevice->port == port)
+			break;
+	}
+	if(no >= phost->numDevice)
+		return;
+	if(pdevice->is_connected == 0)
+		return;
+
+	/*
+	 *  Hostペリフェラル停止
+	 */
+	if(hub == 0)
+		tusbhHDStop(phost);
+
+	/*
+	 *  コントロール通信用PIPEを解放
+	 */
+	tusbhClosePipe(pdevice, pdevice->cntl_pipe_in);
+	tusbFreePipe(phost, pdevice->cntl_pipe_in);
+	tusbhClosePipe(pdevice, pdevice->cntl_pipe_out);
+	tusbFreePipe(phost, pdevice->cntl_pipe_out);
+
+	pdevice->is_connected = 0;
+	pdevice->pre_connected = 0;
+
+	/*
+	 *  ユーザーへ通知
+	 */
+	if(phost->usrcallback != NULL)
+		phost->usrcallback(phost, pdevice, HOST_USER_DISCONNECTION);
+	syslog_4(LOG_NOTICE, "USB Device disconnected [%02x][%02x][%02x] device(%d) !", hub, port, prm, pdevice->idx); 
+
+	/*
+	 *  Hostペリフェラル再開
+	 */
+	if(hub == 0)
+		tusbhHDStart(phost);
+
+	pdevice->dstate = DEVICE_DISCONNECTED;
+	tusbSendData(phost->process_event, TUSBH_PORT_EVENT, pdevice->idx, 0, 0);
+}
+
+/*
+ *  USBホストイベントタスク
+ */
+void
+tusbhEventTask(intptr_t exinf)
+{
+	uint8_t       mes[4];
+	ER            ercd;
+
+	for(;;){
+		ercd = tusbRecvData(usbh_arg->connect_event, mes, 0);
+
+		if(ercd == E_OK){
+			syslog_4(LOG_INFO, "usbh_task evt(%d) [%02x][%02x][%02x] !", mes[0], mes[1], mes[2], mes[3]);
+			if(mes[0] == TUSBH_CONNECT_EVENT)
+				tusbhHandleConnect(usbh_arg, mes[1], mes[2], mes[3]);
+			else if(mes[0] == TUSBH_DISCONNECT_EVENT){
+				dly_tsk(200);
+				tusbhHandleDisconnect(usbh_arg, mes[1], mes[2], mes[3]);
+			}
+			else if(mes[0] == TUSBH_IDCHANGE_EVENT){
+				dly_tsk(200);
+				tusbhHDStart(usbh_arg);
+			}
+		}
+	}
+}
+
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/tusbh_base.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/tusbh_base.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/tusbh_base.h	(revision 453)
@@ -0,0 +1,293 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  USB Host Middleware BASE部定義
+ */
+
+#ifndef _HUSBH_BASE_H_
+#define _HUSBH_BASE_H_
+
+#include "tusb_rtos.h"
+#include "tusb_types.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#ifndef TUSBH_MAX_NUM_ENDPOINTS
+#define TUSBH_MAX_NUM_ENDPOINTS           3
+#endif
+#ifndef TUSBH_MAX_NUM_INTERFACES
+#define TUSBH_MAX_NUM_INTERFACES          2
+#endif
+#ifndef TUSBH_MAX_DATA_BUFFER
+#define TUSBH_MAX_DATA_BUFFER             0x200
+#endif
+
+/*
+ *  STMユーザーイベント
+ */
+#define HOST_USER_SELECT_CONFIGURATION    1
+#define HOST_USER_CLASS_ACTIVE            2
+#define HOST_USER_CLASS_SELECTED          3
+#define HOST_USER_CONNECTION              4
+#define HOST_USER_DISCONNECTION           5
+#define HOST_USER_UNRECOVERED_ERROR       6
+
+/*Standard Feature Selector for clear feature command*/
+#define FEATURE_SELECTOR_ENDPOINT         0X00
+#define FEATURE_SELECTOR_DEVICE           0X01
+
+/*
+ *  SUBMITタイプ
+ */
+#define SUBMIT_SETUP                      ((0<<8) | USB_PID_SETUP)
+#define SUBMIT_WRITE                      ((0<<8) | USB_PID_DATA)
+#define SUBMIT_READ                       ((1<<8) | USB_PID_DATA)
+
+/*
+ *  パイプ属性定義
+ */
+#define PIPE_ACTIVATE                     0x8000
+#define PIPE_ADDRESS                      0x00FF
+
+
+#define NO_INTERFACE                      0xFF
+
+
+/*
+ *  URBステート定義
+ */
+typedef enum {
+	TUSBH_URB_IDLE = 0,
+	TUSBH_URB_DONE,
+	TUSBH_URB_NOTREADY,
+	TUSBH_URB_NYET,
+	TUSBH_URB_ERROR,
+	TUSBH_URB_STALL
+} TUSBH_URBState_t;
+
+/*
+ *  プロセスイベント
+ */
+enum {
+	TUSBH_PORT_EVENT = 1,
+	TUSBH_URB_EVENT,
+	TUSBH_TIME_EVENT,
+	TUSBH_CLASS_EVENT,
+	TUSBH_RESET_EVENT
+};
+
+enum {
+	TUSBH_CONNECT_EVENT = 1,
+	TUSBH_DISCONNECT_EVENT,
+	TUSBH_IDCHANGE_EVENT,
+};
+
+/*
+ *  デバイス状態定義
+ */
+enum {
+	DEVICE_IDLE = 0,
+	DEVICE_ATTACHED,
+	DEVICE_DISCONNECTED,
+	DEVICE_CHECK_CLASS,
+	DEVICE_CLASS,
+	DEVICE_SUSPENDED,
+	DEVICE_ABORT_STATE,
+};
+
+/*
+ *  CONTROL通信状態
+ */
+enum {
+	CONTROL_IDLE = 0,
+	CONTROL_SETUP,
+	CONTROL_SETUP_WAIT,
+	CONTROL_DATA_IN_WAIT,
+	CONTROL_DATA_OUT_WAIT,
+	CONTROL_STATUS_IN_WAIT,
+	CONTROL_STATUS_OUT_WAIT,
+	CONTROL_ERROR
+};
+
+
+#define USBH_HandleTypeDef     TUSBH_Handle_t
+typedef struct _TUSBH_Handle_t TUSBH_Handle_t;
+typedef struct _TUSBH_Class_t  TUSBH_Class_t;
+typedef struct _TUSBH_Device_t TUSBH_Device_t;
+
+typedef struct
+{
+	uint16_t                   attribute;
+	uint8_t                    index;
+	uint8_t                    type;
+} USBH_Pipe_t;
+
+/*
+ *  USBホストクラス定義
+ */
+struct _TUSBH_Class_t
+{
+	TUSBH_Class_t              *pNext;
+	const char                 *Name;
+	uint32_t                   classCode;
+	TUSBH_ERCODE               (*Init)(TUSBH_Device_t *pdevice);
+	TUSBH_ERCODE               (*DeInit)(TUSBH_Device_t *pdevice);
+	TUSBH_ERCODE               (*Process)(TUSBH_Device_t *pdevice, uint8_t *mes);
+	void                       *subfunc;
+};
+
+/*
+ *  USBホストデバイスハンドラ
+ */
+struct _TUSBH_Device_t
+{
+	TUSBH_Device_t             *pNext;
+	TUSBH_Handle_t             *pHost;
+	TUSBH_Class_t              *pClass;
+	uint8_t                    activate;
+	uint8_t                    address;
+	uint8_t                    speed;
+	volatile uint8_t           is_connected;
+	uint8_t                    pre_connected;
+	uint8_t                    sel_interface;
+	uint8_t                    hub;
+	uint8_t                    port;
+	uint8_t                    idx;
+	volatile uint8_t           dstate;
+	uint16_t                   timeid;
+	uint32_t                   timecount;
+
+	uint8_t                    cntl_pipe_in;
+	uint8_t                    cntl_pipe_out;
+	uint8_t                    cntl_pipe_size;
+	uint8_t                    cntl_errcount;
+    uint8_t                    setupPacket[8];
+	uint32_t                   dummy[6];	/* dummy for cache */
+	uint8_t                    Data[TUSBH_MAX_DATA_BUFFER];
+	DeviceDescriptor           DevDesc;
+	ConfigurationDescriptor    CfgDesc;
+	InterfaceDescriptor        ItfDesc[TUSBH_MAX_NUM_INTERFACES];
+	EndpointDescriptor         EpDesc[TUSBH_MAX_NUM_INTERFACES][TUSBH_MAX_NUM_ENDPOINTS];
+
+	uint8_t                    type;
+	uint8_t                    hubid;
+	volatile uint8_t           cstate;
+	uint8_t                    numUnit;
+	void                       *pData;
+	uint8_t                    *cbuff;
+	char                       Manufacturer[TUSBH_STR_LENGTH];
+	char                       Prodeuct[TUSBH_STR_LENGTH];
+	char                       Serial[TUSBH_STR_LENGTH];
+};
+
+/*
+ *  USBホストハンドラ
+ */
+struct _TUSBH_Handle_t
+{
+	TUSBH_Device_t             *pDevice;
+	TUSBH_Class_t              *pClass;
+	USBH_Pipe_t                pipes[MAX_EPS_PIPES];
+	uint32_t                   numPipes;
+	void                       *pSysData;
+	uint8_t                    *pCfgData;
+	void                       (*usrcallback)(TUSBH_Handle_t *pHandle, TUSBH_Device_t *pdevice, uint8_t id);
+
+	uint8_t                    id;
+	uint8_t                    numDevice;
+	uint8_t                    numClass;
+	uint8_t                    numHub;
+	ID                         processTaskID;
+	ID                         eventTaskID;
+	ID                         process_event;
+	ID                         connect_event;
+};
+
+#include "tusbh_conf.h"
+
+/*
+ *  関数プロトタイプ宣言
+ */
+TUSBH_ERCODE tusbhInit(TUSBH_Handle_t *phost, void (*pufunc)(TUSBH_Handle_t*, TUSBH_Device_t *, uint8_t ), uint8_t id);
+TUSBH_ERCODE tusbhDeInit(TUSBH_Handle_t *phost);
+TUSBH_ERCODE tusbhLinkClass(TUSBH_Handle_t *phost, TUSBH_Class_t *pclass);
+TUSBH_ERCODE tusbhStart(TUSBH_Handle_t *phost);
+TUSBH_ERCODE tusbhStop(TUSBH_Handle_t *phost);
+
+TUSBH_ERCODE tusbhResetHub(TUSBH_Device_t *pdevice);
+TUSBH_ERCODE tusbhSelectInterface(TUSBH_Device_t *pdevice, uint8_t interface);
+uint8_t      tusbhFindInterface(TUSBH_Device_t *pdevice, uint8_t Class, uint8_t SubClass, uint8_t Protocol);
+uint8_t      tusbhGetActiveClass(TUSBH_Device_t *pdevice);
+uint8_t      tusbhFindInterfacebynumber(TUSBH_Device_t *pdevice, uint8_t interface, uint8_t altsetno);
+
+TUSBH_ERCODE tusbhControlRequest(TUSBH_Device_t *pdevice, uint8_t *buff, uint8_t type, uint8_t request, uint16_t value, uint16_t index, uint16_t length);
+TUSBH_ERCODE tusbhControlWait(TUSBH_Device_t *pdevice, uint8_t *mes);
+TUSBH_ERCODE tusbhGetDescriptor(TUSBH_Device_t *pdevice, uint8_t req_type, uint16_t value, uint8_t* buff, uint16_t length);
+TUSBH_ERCODE tusbhSetInterface(TUSBH_Device_t *pdevice, uint8_t ep_num, uint8_t interface);
+TUSBH_ERCODE tusbhClearFeature(TUSBH_Device_t *pdevice, uint8_t ep_num);
+
+TUSBH_ERCODE tusbhOpenPipe(TUSBH_Device_t *, uint8_t, uint8_t, uint8_t, uint16_t);
+TUSBH_ERCODE tusbhClosePipe(TUSBH_Device_t *, uint8_t pipe);
+TUSBH_ERCODE tusbhSubmitURB(TUSBH_Device_t *pdevice, uint8_t, uint16_t, uint8_t, uint8_t*, uint16_t);
+TUSBH_ERCODE tusbhControlSendSetup(TUSBH_Device_t *pdevice, uint8_t *buff, uint8_t pipe_num);
+TUSBH_ERCODE tusbhControlSendData(TUSBH_Device_t *pdevice, uint8_t *buff, uint16_t length, uint8_t pipe_num);
+TUSBH_ERCODE tusbhControlReceiveData(TUSBH_Device_t *pdevice, uint8_t* buff, uint16_t length, uint8_t pipe_num);
+TUSBH_ERCODE tusbhBulkWrite(TUSBH_Device_t *pdevice, uint8_t *buff, uint16_t length, uint8_t pipe_num);
+TUSBH_ERCODE tusbhBulkRead(TUSBH_Device_t *pdevice, uint8_t *buff, uint16_t length, uint8_t pipe_num);
+TUSBH_ERCODE tusbhInterruptWrite(TUSBH_Device_t *pdevice, uint8_t *buff, uint8_t length, uint8_t pipe_num);
+TUSBH_ERCODE tusbhInterruptRead(TUSBH_Device_t *pdevice, uint8_t *buff, uint8_t length, uint8_t pipe_num);
+TUSBH_ERCODE tusbhIsocWrite(TUSBH_Device_t *pdevice, uint8_t *buff, uint32_t length, uint8_t pipe_num);
+TUSBH_ERCODE tusbhIsocRead(TUSBH_Device_t *pdevice, uint8_t *buff, uint32_t length, uint8_t pipe_num);
+
+void tusbhProcessTask(intptr_t exinf);
+void tusbhEventTask(intptr_t exinf);
+void tusbhCyclicHandler(intptr_t exinf);
+
+TUSBH_Device_t *tusbhSearchDevice(TUSBH_Handle_t *phost, uint8_t classCode, uint8_t *plun);
+uint8_t tusbhAllocPipe(TUSBH_Handle_t *phost, uint8_t ep_addr);
+TUSBH_ERCODE tusbFreePipe(TUSBH_Handle_t *phost, uint8_t no);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HUSBH_BASE_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/tusbh_request.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/tusbh_request.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/host/tusbh_request.c	(revision 453)
@@ -0,0 +1,459 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2017 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  USB Host Middleware 通信リクエスト部
+ */
+
+#include "tusbh_base.h"
+
+
+/*
+ *  BULK通信：WRITE
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  parameter2 buff:     データ領域
+ *  parameter3 length:   データ長
+ *  parameter4 pipe_num: PIPE番号
+ *  return     TUSBH_ERCOCE
+ */
+TUSBH_ERCODE
+tusbhBulkWrite(TUSBH_Device_t *pdevice, uint8_t *buff, uint16_t length, uint8_t pipe_num)
+{ 
+	return tusbhSubmitURB(pdevice, pipe_num, SUBMIT_WRITE, USB_EP_TYPE_BULK, buff, length);
+}
+
+/*
+ *  BULK通信：READ
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  parameter2 buff:     データ領域
+ *  parameter3 length:   データ長
+ *  parameter4 pipe_num: PIPE番号
+ *  return     TUSBH_ERCOCE
+ */
+TUSBH_ERCODE
+tusbhBulkRead(TUSBH_Device_t *pdevice, uint8_t *buff, uint16_t length, uint8_t pipe_num)
+{
+	return tusbhSubmitURB(pdevice, pipe_num, SUBMIT_READ, USB_EP_TYPE_BULK, buff, length);
+}
+
+/*
+ *  INTERRUPT通信：WRITE
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  parameter2 buff:     データ領域
+ *  parameter3 length:   データ長
+ *  parameter4 pipe_num: PIPE番号
+ *  return     TUSBH_ERCOCE
+ */
+TUSBH_ERCODE
+tusbhInterruptWrite(TUSBH_Device_t *pdevice, uint8_t *buff, uint8_t length, uint8_t pipe_num)
+{
+	return tusbhSubmitURB(pdevice, pipe_num, SUBMIT_WRITE, USB_EP_TYPE_INTR, buff, length);
+}
+
+/*
+ *  INTERRUPT通信：READ
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  parameter2 buff:     データ領域
+ *  parameter3 length:   データ長
+ *  parameter4 pipe_num: PIPE番号
+ *  return     TUSBH_ERCOCE
+ */
+TUSBH_ERCODE
+tusbhInterruptRead(TUSBH_Device_t *pdevice, uint8_t *buff, uint8_t length, uint8_t pipe_num)
+{
+	return tusbhSubmitURB(pdevice, pipe_num, SUBMIT_READ, USB_EP_TYPE_INTR, buff, length);
+}
+
+/*
+ *  ISOC通信：WRITE
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  parameter2 buff:     データ領域
+ *  parameter3 length:   データ長
+ *  parameter4 pipe_num: PIPE番号
+ *  return     TUSBH_ERCOCE
+ */
+TUSBH_ERCODE
+tusbhIsocWrite(TUSBH_Device_t *pdevice, uint8_t *buff, uint32_t length, uint8_t pipe_num)
+{
+	return tusbhSubmitURB(pdevice, pipe_num, SUBMIT_WRITE, USB_EP_TYPE_ISOC, buff, length);
+}
+
+/**
+  * @brief  USBH_IsocReceiveData
+  *         Receives the Device Response to the Isochronous IN token
+  * @param  phost: Host Handle
+  * @param  buff: Buffer pointer in which the response needs to be copied
+  * @param  length: Length of the data to be received
+  * @param  pipe_num: Pipe Number
+  * @retval USBH Status. 
+  */
+TUSBH_ERCODE
+tusbhIsocRead(TUSBH_Device_t *pdevice, uint8_t *buff, uint32_t length, uint8_t pipe_num)
+{
+	return tusbhSubmitURB(pdevice, pipe_num, SUBMIT_READ, USB_EP_TYPE_ISOC, buff, length);
+}
+
+
+/*
+ *  コントロール通信：SETUP送信
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  parameter2 buff:     セットアップデータ領域
+ *  parameter3 pipe_num: PIPE番号
+ *  return     TUSBH_ERCOCE
+ */
+TUSBH_ERCODE
+tusbhControlSendSetup(TUSBH_Device_t *pdevice, uint8_t *buff, uint8_t pipe_num)
+{
+	return tusbhSubmitURB(pdevice, pipe_num, SUBMIT_SETUP, USB_EP_TYPE_CTRL, buff, SETUP_PKT_LENGTH);
+}
+
+/*
+ *  コントロール通信：データ送信
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  parameter2 buff:     データ領域
+ *  parameter3 length:   データ長
+ *  parameter4 pipe_num: パイプ番号
+ *  return     TUSBH_ERCOCE
+ */
+TUSBH_ERCODE
+tusbhControlSendData(TUSBH_Device_t *pdevice, uint8_t *buff, uint16_t length, uint8_t pipe_num)
+{
+	return tusbhSubmitURB(pdevice, pipe_num, SUBMIT_WRITE, USB_EP_TYPE_CTRL, buff, length);
+}
+
+/*
+ *  コントロール通信：データ受信
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  parameter2 buff:     データ領域
+ *  parameter3 length:   データ長
+ *  parameter4 pipe_num: パイプ番号
+ *  return     TUSBH_ERCOCE
+ */
+TUSBH_ERCODE
+tusbhControlReceiveData(TUSBH_Device_t *pdevice, uint8_t* buff, uint16_t length, uint8_t pipe_num)
+{
+	return tusbhSubmitURB(pdevice, pipe_num, SUBMIT_READ, USB_EP_TYPE_CTRL, buff, length);
+}
+
+/*
+ *  コントロール通信：DESCRIPTOR取得
+ *  parameter1 pdevice:  デバイスハンドラ
+ *  parameter2 req_type: DESCRIPTORタイプ
+ *  parameter3 value:    DESCRIPTOR要求値
+ *  parameter4 buff:     DESCRIPTO格納領域
+ *  parameter5 length:   DESCRIPTOR長
+ *  return     TUSBH_ERCOCE
+ */
+TUSBH_ERCODE
+tusbhGetDescriptor(TUSBH_Device_t *pdevice, uint8_t req_type, uint16_t value, uint8_t* buff, uint16_t length)
+{
+	uint16_t index;
+
+	if((value & 0xff00) == ((STRING_DESCRIPTOR << 8) & 0xFF00)){
+		index = 0x0409;
+	}
+	else
+		index = 0;
+	return tusbhControlRequest(pdevice, buff, (USB_DEVICE_TO_HOST | req_type), GET_DESCRIPTOR, value, index, length );
+}
+
+/*
+ *  コントロール通信：SET INTERFACEの送信
+ *  parameter1 pdevice: デバイスハンドラ
+ *  parameter2 ep_num:  エンドポイント番号
+ *  parameter3 interface: インタフェース値
+ *  return     TUSBH_ERCOCE
+ */
+TUSBH_ERCODE
+tusbhSetInterface(TUSBH_Device_t *pdevice, uint8_t ep_num, uint8_t interface)
+{
+	return tusbhControlRequest(pdevice, 0, SET_INTERFACE_TYPE, SET_INTERFACE, interface, ep_num, 0);
+}
+
+/*
+ *  コントロール通信：CLEAR FEATUREの送信
+ *  parameter1 pdevice: デバイスハンドラ
+ *  parameter2 ep_num:  エンドポイント番号
+ *  return     TUSBH_ERCOCE
+ */
+TUSBH_ERCODE
+tusbhClearFeature(TUSBH_Device_t *pdevice, uint8_t ep_num) 
+{
+	return tusbhControlRequest(pdevice, 0, CLEAR_FEATURE_TYPE, CLEAR_FEATURE, FEATURE_SELECTOR_ENDPOINT, ep_num, 0 );
+}
+
+
+/*
+ *  コントロール通信の要求
+ *  parameter1 pdevice: デバイスハンドラ
+ *  parameter2 buff:    通信バッファ
+ *  parameter3 type:    bmRequestType
+ *  parameter4 request: bRequest
+ *  parameter5 value:   wValue
+ *  parameter6 index:   wIndex
+ *  parameter7 length:  wLength
+ *  return     TUSBH_ERCOCE
+ */
+TUSBH_ERCODE
+tusbhControlRequest(TUSBH_Device_t *pdevice, uint8_t *buff, uint8_t type, uint8_t request, uint16_t value, uint16_t index, uint16_t length)
+{
+	TUSBH_Handle_t *phost = pdevice->pHost;
+	TUSBH_ERCODE ercd = TUSBH_E_BUSY;
+	uint8_t mes[4];
+
+	pdevice->cstate = CONTROL_SETUP;
+	pdevice->setupPacket[0] = type;
+	pdevice->setupPacket[1] = request;
+	pdevice->setupPacket[2] = (uint8_t)value;
+	pdevice->setupPacket[3] = (uint8_t)(value >> 8);
+	pdevice->setupPacket[4] = (uint8_t)index;
+	pdevice->setupPacket[5] = (uint8_t)(index >> 8);
+	pdevice->setupPacket[6] = (uint8_t)length; 
+	pdevice->setupPacket[7] = (uint8_t)(length >> 8); 
+	pdevice->cbuff          = buff;
+	mes[0]                  = TUSBH_PORT_EVENT;
+
+	do{
+		ercd = tusbhControlWait(pdevice, mes);
+		if(pdevice->dstate == DEVICE_CLASS)
+			return ercd;
+		while(ercd == TUSBH_E_BUSY_URB){
+			if(tusbRecvData(phost->process_event, mes, 4000) != E_OK){
+				syslog_1(LOG_ERROR, "tusbhControlRequest urb timeout state(%d) !", pdevice->cstate);
+				ercd = TUSBH_E_TMOUT;
+				break;
+			}
+			else if(mes[0] == TUSBH_URB_EVENT && mes[1] == pdevice->idx){
+				ercd = TUSBH_E_BUSY;
+			}
+			else if(mes[1] != pdevice->idx){
+				TUSBH_Device_t *pdevice2 = phost->pDevice;
+				uint8_t i;
+				for(i = 0 ; i < mes[1] ; i++)
+					pdevice2 = pdevice2->pNext;
+				if(pdevice2 != NULL && pdevice2->pClass != NULL && pdevice2->dstate == DEVICE_CLASS)
+					pdevice2->pClass->Process(pdevice2, mes);
+				else{
+#if 1	/* ROI DEBUG */
+					syslog_4(LOG_ERROR, "### tusbhControlRequest Can't EXEC [%02x][%02x][%02x][%02x] ###", mes[0], mes[1], mes[2], mes[3]);
+#endif	/* ROI DEBUG */
+					tusbDelay(10);
+					tusbSendData(phost->process_event, mes[0], mes[1], mes[2], mes[3]);
+				}
+			}
+		}
+	}while(ercd == TUSBH_E_BUSY);
+	return ercd;
+}
+
+/*
+ *  コントロール通信の待ち
+ *  parameter1 pdevice: デバイスハンドラ
+ *  parameter2 mes:     メッセージへのポインタ
+ *  return     TUSBH_ERCOCE
+ */
+TUSBH_ERCODE
+tusbhControlWait(TUSBH_Device_t *pdevice, uint8_t *mes)
+{
+	TUSBH_Handle_t *phost = pdevice->pHost;
+	TUSBH_ERCODE ercd = TUSBH_E_BUSY;
+	TUSBH_URBState_t URB_Status = mes[3];
+	uint8_t  type = pdevice->setupPacket[0];
+	uint16_t length = (pdevice->setupPacket[7] << 8) | (pdevice->setupPacket[6] & 0xFF);
+
+	switch(pdevice->cstate){
+	case CONTROL_SETUP:	/* PACKETセットアップ */
+		tusbhControlSendSetup(pdevice, (uint8_t *)&pdevice->setupPacket, pdevice->cntl_pipe_out); 
+		pdevice->cstate = CONTROL_SETUP_WAIT;
+		ercd = TUSBH_E_BUSY_URB;
+		break;
+	case CONTROL_SETUP_WAIT:	/* PACKETセットアップ URB待ち */
+		if(mes[0] != TUSBH_URB_EVENT)
+			break;
+		if(URB_Status == TUSBH_URB_DONE){	/* 正常終了 */
+			uint8_t direction = (type & USB_REQUEST_DIR_MASK);
+			if(length != 0 ){
+				if(direction == USB_DEVICE_TO_HOST){	/* データREAD */
+					tusbhControlReceiveData(pdevice, pdevice->cbuff, length, pdevice->cntl_pipe_in);
+					pdevice->cstate = CONTROL_DATA_IN_WAIT;
+				}
+				else{						/* データWRITE */
+					tusbhControlSendData(pdevice, pdevice->cbuff, length, pdevice->cntl_pipe_out);
+					pdevice->cstate = CONTROL_DATA_OUT_WAIT;
+				}
+			}
+			else{			/* ステータス通信 */
+				if(direction == USB_DEVICE_TO_HOST){	/* ステータス受信 */
+					tusbhControlSendData(pdevice, 0, 0, pdevice->cntl_pipe_out);
+					pdevice->cstate = CONTROL_STATUS_OUT_WAIT;
+				}
+				else{						/* ステータス送信 */
+					tusbhControlReceiveData(pdevice, 0, 0, pdevice->cntl_pipe_in);
+					pdevice->cstate = CONTROL_STATUS_IN_WAIT;
+				}
+			}
+			ercd = TUSBH_E_BUSY_URB;
+		}
+		else if(URB_Status == TUSBH_URB_ERROR)	/* USBエラー */
+			pdevice->cstate = CONTROL_ERROR;
+		else if(URB_Status == TUSBH_URB_NOTREADY){
+			syslog_0(LOG_NOTICE, "### tusbhControlRequest REAET STATE1 ###");
+			pdevice->cstate = CONTROL_SETUP;
+		}
+		else{
+			syslog_2(LOG_ERROR, "tusbhControlRequest urb error state(%d) urb[%02x] !", pdevice->cstate, URB_Status);
+			ercd = TUSBH_E_URB;
+		}
+		break;
+	case CONTROL_DATA_IN_WAIT:		/* データ受信待ち */
+		if(mes[0] != TUSBH_URB_EVENT)
+			break;
+		if(URB_Status == TUSBH_URB_DONE){	/* 正常終了 */
+			tusbhControlSendData(pdevice, 0, 0, pdevice->cntl_pipe_out);
+			pdevice->cstate = CONTROL_STATUS_OUT_WAIT;
+			ercd = TUSBH_E_BUSY_URB;
+		}
+		else if(URB_Status == TUSBH_URB_STALL){	/* ステール状態 */
+			pdevice->cstate = CONTROL_IDLE;
+			ercd = TUSBH_E_NOSPT;
+		}
+		else if(URB_Status == TUSBH_URB_ERROR)	/* URBエラー */
+			pdevice->cstate = CONTROL_ERROR;
+		else if(URB_Status == TUSBH_URB_NOTREADY){
+			syslog_0(LOG_NOTICE, "### tusbhControlRequest REAET STATE2 ###");
+			pdevice->cstate = CONTROL_SETUP;
+		}
+		else{
+			syslog_2(LOG_ERROR, "tusbhControlRequest urb error state(%d) urb[%02x] !", pdevice->cstate, URB_Status);
+			ercd = TUSBH_E_URB;
+		}
+		break;
+	case CONTROL_DATA_OUT_WAIT:	/* データ送信終了待ち */
+		if(mes[0] != TUSBH_URB_EVENT)
+			break;
+		if(URB_Status == TUSBH_URB_DONE){	/* 正常終了 */
+			tusbhControlReceiveData(pdevice, 0, 0, pdevice->cntl_pipe_in);
+			pdevice->cstate = CONTROL_STATUS_IN_WAIT;
+			ercd = TUSBH_E_BUSY_URB;
+		}
+		else if(URB_Status == TUSBH_URB_STALL){	/* ステール状態 */
+			pdevice->cstate = CONTROL_IDLE;
+			ercd = TUSBH_E_NOSPT;
+		}
+		else if(URB_Status == TUSBH_URB_NOTREADY){
+			/* Nack received from device */
+			tusbhControlSendData(pdevice, pdevice->cbuff, length, pdevice->cntl_pipe_out);
+			ercd = TUSBH_E_BUSY_URB;
+		}
+		else if(URB_Status == TUSBH_URB_ERROR)	/* USBエラー */
+			pdevice->cstate = CONTROL_ERROR;
+		else{
+			syslog_2(LOG_ERROR, "tusbhControlRequest urb error state(%d) urb[%02x] !", pdevice->cstate, URB_Status);
+			ercd = TUSBH_E_URB;
+		}
+		break;
+	case CONTROL_STATUS_IN_WAIT:	/* ステータス送信待ち */
+		if(mes[0] != TUSBH_URB_EVENT)
+			break;
+		if(URB_Status == TUSBH_URB_DONE){	/* 正常終了 */
+			pdevice->cstate = CONTROL_IDLE;
+			ercd = TUSBH_E_OK;
+			tusbSendData(phost->process_event, TUSBH_PORT_EVENT, pdevice->idx, 0, 0);
+		}
+		else if(URB_Status == TUSBH_URB_ERROR)	/* USBエラー */
+			pdevice->cstate = CONTROL_ERROR;
+		else if(URB_Status == TUSBH_URB_STALL){	/* ステール状態 */
+			pdevice->cstate = CONTROL_IDLE;
+			ercd = TUSBH_E_NOSPT;
+		}
+		else if(URB_Status == TUSBH_URB_NOTREADY){
+			syslog_0(LOG_NOTICE, "### tusbhControlRequest REAET STATE3 ###");
+			pdevice->cstate = CONTROL_SETUP;
+		}
+		else{
+			syslog_2(LOG_ERROR, "tusbhControlRequest urb error state(%d) urb[%02x] !", pdevice->cstate, URB_Status);
+			ercd = TUSBH_E_URB;
+		}
+		break;
+	case CONTROL_STATUS_OUT_WAIT:	/* ステータス受信待ち */
+		if(mes[0] != TUSBH_URB_EVENT)
+			break;
+		if(URB_Status == TUSBH_URB_DONE){
+			pdevice->cstate = CONTROL_IDLE;
+			ercd = TUSBH_E_OK;
+			tusbSendData(phost->process_event, TUSBH_PORT_EVENT, pdevice->idx, 0, 0);
+		}
+		else if(URB_Status == TUSBH_URB_NOTREADY){ 
+			tusbhControlSendData(pdevice, 0, 0, pdevice->cntl_pipe_out);
+			ercd = TUSBH_E_BUSY_URB;
+		}
+		else if(URB_Status == TUSBH_URB_ERROR)	/* USBエラー */
+			pdevice->cstate = CONTROL_ERROR;
+		else{
+			syslog_2(LOG_ERROR, "tusbhControlRequest urb error state(%d) urb[%02x] !", pdevice->cstate, URB_Status);
+			ercd = TUSBH_E_URB;
+		}
+		break;
+	case CONTROL_ERROR:
+		/*
+		 *  コントロール通信エラーケース
+		 *  エラーカウントが TUSBH_MAX_ERROR_COUNT以下ならばリトライする
+		 */
+		if(++pdevice->cntl_errcount <= TUSBH_MAX_ERROR_COUNT){
+			if(pdevice->hub == 0)
+				tusbhHDStop(phost);
+			else
+				tusbhResetHub(pdevice);
+			/*
+			 *  リトライする
+			 */
+			pdevice->cstate = CONTROL_SETUP;
+		}
+		else{
+			if(phost->usrcallback != NULL)
+				phost->usrcallback(phost, pdevice, HOST_USER_UNRECOVERED_ERROR);
+			pdevice->cntl_errcount = 0;
+			syslog_1(LOG_ERROR, "tusbhControlRequest error count(%d) !", pdevice->cntl_errcount);
+			ercd = TUSBH_E_ERR;
+		}
+		break;
+	default:
+		break;
+	}
+	return ercd;
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/mscdiskio.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/mscdiskio.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/mscdiskio.c	(revision 453)
@@ -0,0 +1,294 @@
+/*
+ *  TOPPERS/ASP/FMP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
+ *              Graduate School of Information Science, Nagoya Univ., JAPAN
+ *  Copyright (C) 2015-2017 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+ *  によって公表されている GNU General Public License の Version 2 に記
+ *  述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+ *  を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+ *  含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+ *  接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+/*
+ * ＭＳＣ専用ストレージ関数をサポートする
+ * 擬似的なストレージ関数郡であり、標準ライブラリィと分けての使用が望ましい。
+ * 1. msc_init                 この関数郡の初期化関数(bssがゼロ設定の場合この関数は不要)
+ * 2. msc_sense                MSCのセンスを行う
+ * 3. msc_diskstatus           MSCのステータス取得:なし
+ * 4. msc_diskread             MSCの読み込み:なし
+ * 5. msc_diskwrite            MSCの書き込み:なし
+ * 6. msc_iocil                MSCのIO制御:なし
+ *
+ */
+
+#include "kernel_impl.h"
+#include <stdlib.h>
+#include <string.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include "fcntl.h"
+#include "device.h"
+#include "storagedevice.h"
+#include "ff.h"
+#include "diskio.h"
+#include "usb_otg.h"
+#include "mscdiskio.h"
+#include "tusbh_msc.h"
+
+static int msc_sense(void *psdev, bool_t on);
+static int msc_diskstatus(void *psdev);
+static int msc_diskread(void *pif, BYTE *Buffer, DWORD SectorNumber, BYTE SectorCount);
+static int msc_diskwrite(void *pif, const BYTE *Buffer, DWORD SectorNumber, BYTE SectorCount);
+static int msc_diskioctl(void *pif, BYTE Func, void* Buffer);
+
+static const StorageDeviceFunc_t fatfsMscDeviceFunc = {
+	msc_sense,
+	msc_diskstatus,
+	msc_diskstatus,
+	(int(*)())msc_diskread,
+	(int(*)())msc_diskwrite,
+	(int(*)())msc_diskioctl
+};
+
+static MSC_Unit_t MSCLUNInfo;
+static FATFS ActiveFatFsObj __attribute__ ((aligned (32)));
+
+/*
+ *  FatFs用SDカードファイルドライバの初期化
+ */
+#if MSC_DEVNO == 0
+void sd_init(intptr_t exinf)
+#else
+void msc_init(intptr_t exinf)
+#endif
+{
+	StorageDevice_t *psdev;
+
+	SDMSetupDevice(MSC_DEVNO, &psdev);
+	psdev->pdevf            = (StorageDeviceFunc_t *)&fatfsMscDeviceFunc;
+	psdev->pdevff           = (StorageDeviceFileFunc_t *)&fatfsSDeviceFileFunc;
+	psdev->_sdev_secsize    = 512;
+	psdev->_sdev_port       = MSC_PORTID;
+#ifdef SDEV_INSWAIT_TIME
+	psdev->_sdev_inswait    = SDEV_INSWAIT_TIME;
+#else
+	psdev->_sdev_inswait    = 0;
+#endif
+	psdev->_sdev_attribute |= SDEV_INSERTCHK|SDEV_CHKREMOVE;
+	psdev->_sdev_local[0]   = &ActiveFatFsObj;
+	psdev->_sdev_local[1]   = NULL;
+}
+
+/*
+ *  MSCセンス関数
+ */
+static int msc_sense(void *pif, BOOL on)
+{
+	StorageDevice_t  *psdev = pif;
+	TUSBH_Handle_t   *husbh;
+	TUSBH_ERCODE     status;
+	bool_t   exist;
+	char     pdrv;
+	int      result = FR_DISK_ERR;
+
+	pdrv  = psdev->_sdev_port - MSC_PORTID;
+	husbh = (TUSBH_Handle_t *)psdev->_sdev_local[1];
+	if(husbh == NULL)
+		exist = 0;
+	else
+		exist = tusbhMscUnitIsReady(husbh, pdrv);
+	if(on && !exist){
+		f_mount(psdev->_sdev_devno, 0);
+		psdev->_sdev_attribute &= ~SDEV_DEVERROR;
+		return TRUE;
+	}
+	else if(!on && exist){
+		psdev->_sdev_instimer += SENSE_TIME;
+		status = tusbhMscGetLUNInfo(husbh, pdrv, &MSCLUNInfo);
+		if(status != TUSBH_E_OK)
+			psdev->_sdev_attribute |= SDEV_DEVERROR;
+		else
+			psdev->_sdev_maxsec = MSCLUNInfo.num_block;
+		if((psdev->_sdev_attribute & SDEV_DEVERROR) == 0)
+			result = f_mount(psdev->_sdev_devno, &ActiveFatFsObj);
+		if(result != FR_OK)
+			psdev->_sdev_attribute |= SDEV_DEVERROR;
+		else
+			psdev->_sdev_local[0]   = &ActiveFatFsObj;
+#if 1
+		syslog_3(LOG_NOTICE, "## attr[%04x] max(%d) result(%d) ##", psdev->_sdev_attribute, psdev->_sdev_maxsec, result);
+#endif
+		return TRUE;
+	}
+	else
+		return FALSE;
+}
+
+/*
+ *  FatFs用MSCステータス関数
+ */
+static int msc_diskstatus(void *pif)
+{
+	TUSBH_Handle_t  *husbh;
+	StorageDevice_t *psdev = pif;
+
+	if(psdev == NULL)
+		return STA_NODISK;
+	husbh = (TUSBH_Handle_t *)psdev->_sdev_local[1];
+	if((psdev->_sdev_attribute & (SDEV_EMPLOY|SDEV_NOTUSE)) != SDEV_EMPLOY || husbh == NULL)
+		return STA_NOINIT;
+	else
+		return 0;
+}
+
+/*
+ *  FatFs用MSC読み込み関数
+ */
+static int msc_diskread(void *pif, BYTE *Buffer, DWORD SectorNumber, BYTE SectorCount)
+{
+ 	StorageDevice_t   *psdev = pif;
+	USB_OTG_Handle_t  *husb;
+	TUSBH_Handle_t    *husbh;
+	TUSBH_ERCODE      status;
+	char              pdrv;
+	int               retry = 0;
+	uint8_t           *buff = NULL;
+	unsigned int      align = ((unsigned int)Buffer) & 3;
+	BYTE              *buffer = (BYTE *)Buffer;
+
+	husbh = (TUSBH_Handle_t *)psdev->_sdev_local[1];
+	husb  = (USB_OTG_Handle_t *)husbh->pSysData;
+	pdrv  = psdev->_sdev_port - MSC_PORTID;
+	if((psdev->_sdev_attribute & (SDEV_EMPLOY|SDEV_NOTUSE)) != SDEV_EMPLOY || husbh == NULL)
+		return RES_ERROR;
+	if(align != 0 && husb->Init.dma_enable == 1){
+		uint32_t *addr = malloc_cache(psdev->_sdev_secsize*SectorCount);
+		if(addr != NULL){
+			buff   = buffer;
+			buffer = (BYTE *)addr;
+		}
+	}
+	do{
+		status = tusbhMscRead(husbh, pdrv, SectorNumber, (uint8_t *)buffer, SectorCount);
+		if(status == TUSBH_E_SYS)
+			break;
+		retry++;
+	}while(status != TUSBH_E_OK && retry < RETRY_COUNT);
+	if(buff != NULL){
+		tusbmemcpy(buff, buffer, psdev->_sdev_secsize*SectorCount);
+		free_cache(buffer);
+	}
+	if(status == TUSBH_E_OK)
+		return RES_OK;
+	else if(status == TUSBH_E_SYS)
+		psdev->_sdev_attribute |= SDEV_DEVERROR;
+	return RES_ERROR;
+}
+
+/*
+ *  FatFs用MSC書き込み関数
+ */
+static int msc_diskwrite(void *pif, const BYTE *Buffer, DWORD SectorNumber, BYTE SectorCount)
+{
+ 	StorageDevice_t   *psdev = pif;
+	USB_OTG_Handle_t  *husb;
+	TUSBH_Handle_t    *husbh;
+	TUSBH_ERCODE      status;
+	char              pdrv;
+	int               retry = 0;
+	uint8_t           *buff = NULL;
+	unsigned int      align = ((unsigned int)Buffer) & 3;
+	BYTE              *buffer = (BYTE *)Buffer;
+
+	husbh = (TUSBH_Handle_t *)psdev->_sdev_local[1];
+	husb  = (USB_OTG_Handle_t *)husbh->pSysData;
+	pdrv  = psdev->_sdev_port - MSC_PORTID;
+	if((psdev->_sdev_attribute & (SDEV_EMPLOY|SDEV_NOTUSE)) != SDEV_EMPLOY || husbh == NULL)
+		return RES_ERROR;
+	if(align != 0 && husb->Init.dma_enable == 1){
+		uint32_t *addr = malloc_cache(psdev->_sdev_secsize*SectorCount);
+		if(addr != NULL){
+			buff   = (uint8_t *)buffer;
+			buffer = (BYTE *)addr;
+			tusbmemcpy(buffer, buff, psdev->_sdev_secsize*SectorCount);
+		}
+	}
+	do{
+		status = tusbhMscWrite(husbh, pdrv, SectorNumber, (uint8_t *)buffer, SectorCount);
+		if(status == TUSBH_E_SYS)
+			break;
+		retry++;
+	}while(status != TUSBH_E_OK && retry < RETRY_COUNT);
+	if(buff != NULL)
+		free_cache(buffer);
+	if(status == TUSBH_E_OK)
+		return RES_OK;
+	else if(status == TUSBH_E_SYS)
+		psdev->_sdev_attribute |= SDEV_DEVERROR;
+	return RES_ERROR;
+}
+
+
+/*
+ *  FatFs用MSC-DISKIO制御関数
+ */
+static int msc_diskioctl(void *pif, BYTE Func, void* Buffer)
+{
+	StorageDevice_t *psdev = (StorageDevice_t *)pif;
+	DRESULT         result;
+
+	if(psdev == NULL)
+		return RES_ERROR;
+	if((psdev->_sdev_attribute & (SDEV_EMPLOY|SDEV_NOTUSE)) != SDEV_EMPLOY)
+		return RES_ERROR;
+	switch(Func){
+	case CTRL_SYNC:
+		result = RES_OK;			/* no action */
+		break;
+	case GET_SECTOR_COUNT:
+		*((DWORD *)Buffer) = psdev->_sdev_maxsec;
+		syslog_2(LOG_NOTICE, "ioctl notuse (%d)(%d) ", (int)Func, psdev->_sdev_maxsec);
+		result = RES_OK;
+		break;
+	case GET_BLOCK_SIZE:
+		*((DWORD *)Buffer) = 135;	/* ERASE_BLK */
+		syslog_1(LOG_NOTICE, "call disk_ioctl(GET_BLOCK_SIZE, %08x)", (int)(*((DWORD *)Buffer)));
+		result = RES_OK;
+		break;
+	default:
+		syslog_2(LOG_NOTICE, "call disk_ioctl(%d, %08x)", (int)psdev->_sdev_devno, (int)Buffer);
+		slp_tsk();
+		result = RES_PARERR;
+		break;
+	}
+	return result;
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/mscdiskio.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/mscdiskio.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/mscdiskio.h	(revision 453)
@@ -0,0 +1,57 @@
+/*
+ *  TOPPERS/ASP/FMP Kernel
+ *      Toyohashi Open Platform for Embedded Real-Time Systems/
+ *      Advanced Standard Profile Kernel
+ * 
+ *  Copyright (C) 2012 by GT Development Center RICOH COMPANY,LTD. JAPAN
+ *  Copyright (C) 2015-2017 by TOPPERS PROJECT Educational Working Group.
+ * 
+ *  上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
+ *  によって公表されている GNU General Public License の Version 2 に記
+ *  述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
+ *  を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
+ *  利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
+ *  含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
+ *  接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+
+#ifndef _MSCDISKIO_H_
+#define _MSCDISKIO_H_
+
+#include "storagedevice.h"
+
+#define RETRY_COUNT    8
+
+#ifndef MSC_DEVNO
+#define MSC_DEVNO      0
+#endif
+#define MSC_PORTID     1
+
+extern StorageDeviceFileFunc_t fatfsSDeviceFileFunc;
+
+extern void sd_init(intptr_t exinf);
+extern void msc_init(intptr_t exinf);
+
+#endif
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/tusb_rtos.c
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/tusb_rtos.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/tusb_rtos.c	(revision 453)
@@ -0,0 +1,177 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2017 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  USB Middleware RTOS依存部
+ */
+
+#include "tusb_rtos.h"
+#include "kernel_cfg.h"
+
+
+/*
+ *  タスク状態でのメッセージ送信
+ */
+ER
+tusbSendData(ID qid, uint8_t evt, uint8_t prm1, uint8_t prm2, uint8_t prm3)
+{
+	intptr_t data;
+	ER       ercd;
+
+	data = (evt << 24) | (prm1 << 16) | (prm2 << 8) | prm3;
+	ercd = psnd_dtq(qid, data);
+	if(ercd != E_OK){
+		syslog_5(LOG_ERROR, "tusbSendData send(%d) error [%02x][%02x][%02x][%02x]", qid, evt, prm1, prm2, prm3);
+	}
+	return ercd;
+}
+
+/*
+ *  非タスク状態でのメッセージ送信
+ */
+ER
+tusbiSendData(ID qid, uint8_t evt, uint8_t prm1, uint8_t prm2, uint8_t prm3)
+{
+	intptr_t data;
+	ER       ercd;
+
+	data = (evt << 24) | (prm1 << 16) | (prm2 << 8) | prm3;
+	ercd = ipsnd_dtq(qid, data);
+	if(ercd != E_OK){
+		syslog_5(LOG_ERROR, "tusbiSendData send(%d) error [%02x][%02x][%02x][%02x]", qid, evt, prm1, prm2, prm3);
+	}
+	return ercd;
+}
+
+/*
+ *  タスク状態でのメッセージ受信
+ */
+ER
+tusbRecvData(ID qid, uint8_t *pmes, uint32_t timeout)
+{
+	intptr_t data;
+	ER       ercd;
+
+	if(timeout == 0)
+		ercd = rcv_dtq(qid, &data);
+	else
+		ercd = trcv_dtq(qid, &data, timeout);
+	if(ercd != E_OK){
+		syslog_1(LOG_ERROR, "tusbRecvData(%d) error !", qid);
+	}
+	else{
+		pmes[0] = (data >> 24) & 0xff;
+		pmes[1] = (data >> 16) & 0xff;
+		pmes[2] = (data >> 8) & 0xff;
+		pmes[3] = data & 0xff;
+	}
+	return ercd;
+}
+
+/*
+ *  タスクID取出し
+ */
+int32_t
+tusbGetTaskID(void)
+{
+	ER ercd;
+	ID tid = 0;
+
+	ercd = get_tid(&tid);
+	if(ercd != E_OK){
+		syslog_1(LOG_ERROR, "tusbhGetTaskID get fail(%d) !", ercd);
+		return 0;
+	}
+	else
+		return (int32_t)tid;
+}
+
+/*
+ *  タスク起動
+ */
+ER
+tusbStartTask(ID taskid)
+{
+	ER ercd = act_tsk(taskid);
+
+	if(ercd != E_OK)
+		syslog_2(LOG_ERROR, "tusbStartTask actvate error id(%d) error(%d) !", taskid, ercd);
+	return ercd;
+}
+
+/*
+ *  タイマー制御
+ */
+ER
+tusbTimerControl(uint8_t activate)
+{
+	ER ercd;
+
+	if(activate == 0)
+		ercd = stp_cyc(TUSBH_CYC_HDR);
+	else
+		ercd = sta_cyc(TUSBH_CYC_HDR);
+	return ercd;
+}
+
+/*
+ *  ローカルなmemset関数
+ */
+void
+tusbmemset(void *d, const char val, int len)
+{
+	char *dd = d;
+	int i;
+	for(i = 0 ; i < len ; i++){
+		*dd++ = val;
+	}
+}
+
+/*
+ *  ローカルなmemcpy関数
+ */
+void
+tusbmemcpy(void *d, void *s, int len)
+{
+	uint8_t *dd = d;
+	uint8_t *ss = s;
+	int i;
+	for(i = 0 ; i < len ; i++){
+		*dd++ = *ss++;
+	}
+}
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/tusb_rtos.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/tusb_rtos.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/tusb_rtos.h	(revision 453)
@@ -0,0 +1,96 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2017 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/*
+ *  USB Middleware RTOS依存部定義
+ */
+
+#ifndef _TUSB_RTOS_H_
+#define _TUSB_RTOS_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <kernel.h>
+#include <t_syslog.h>
+#include <t_stdlib.h>
+#include <sil.h>
+#include <target_syssvc.h>
+#include "syssvc/serial.h"
+#include "syssvc/syslog.h"
+#include "t_syslog.h"
+#include "device.h"
+
+#ifdef CACHE_LINE_SIZE
+#define USB_DATA_ALIGN      CACHE_LINE_SIZE
+#else
+#define USB_DATA_ALIGN      4
+#endif
+
+#define TUSB_PROCESS_PRIO       6
+#define TUSB_PROCESS_STACK_SIZE 4096
+#define TUSB_HANDLE_STACK_SIZE  1024
+
+/*
+ *  SYSSVCメモリ管理関数
+ */
+extern void *malloc_cache(uint32_t len);
+extern void free_cache(void *addr);
+
+
+extern ER tusbSendData(ID qid, uint8_t evt, uint8_t prm1, uint8_t prm2, uint8_t prm3);
+extern ER tusbiSendData(ID qid, uint8_t evt, uint8_t prm1, uint8_t prm2, uint8_t prm3);
+extern ER tusbRecvData(ID qid, uint8_t *pmes, uint32_t timeout);
+extern ER tusbStartTask(ID taskid);
+extern int32_t tusbGetTaskID(void);
+extern ER tusbTimerControl(uint8_t activate);
+
+#define tusbmalloc          malloc_cache
+#define tusbfree            free_cache
+extern void tusbmemset(void *d, const char val, int len);
+extern void tusbmemcpy(void *d, void *s, int len);
+
+#define tusbCpuLock         loc_cpu
+#define tusbCpuUnLock       unl_cpu
+#define tusbDelay(t)        dly_tsk((t))
+#define tusbSleep(t)        tslp_tsk((t))
+#define tusbWakeup(id)      wup_tsk((id))
+
+
+#endif /* _TUSB_RTOS_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/usb/tusb_types.h
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/usb/tusb_types.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/usb/tusb_types.h	(revision 453)
@@ -0,0 +1,255 @@
+/*
+ *  TOPPERS BASE PLATFORM MIDDLEWARE
+ * 
+ *  Copyright (C) 2017-2018 by TOPPERS PROJECT
+ *                             Educational Working Group.
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+/* mbed USBHost Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ *  USB Host/Device Middleware 型外部宣言
+ */
+
+#ifndef _TUSB_TYPES_H_
+#define _TUSB_TYPES_H_
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Control RequestType Fields */
+#define USB_DEVICE_TO_HOST         0x80
+#define USB_HOST_TO_DEVICE         0x00
+#define USB_REQUEST_DIR_MASK       USB_DEVICE_TO_HOST
+#define USB_REQUEST_TYPE_VENDOR    0x40
+#define USB_REQUEST_TYPE_CLASS     0x20
+#define USB_REQUEST_TYPE_STANDARD  0x00
+#define USB_RECIPIENT_OTHER        0x03
+#define USB_RECIPIENT_ENDPOINT     0x02
+#define USB_RECIPIENT_INTERFACE    0x01
+#define USB_RECIPIENT_DEVICE       0x00
+
+/* USB Standard Requests */
+#define GET_STATUS                 0x00
+#define CLEAR_FEATURE              0x01
+#define SET_FEATURE                0x03
+#define SET_ADDRESS                0x05
+#define GET_DESCRIPTOR             0x06
+#define SET_DESCRIPTOR             0x07
+#define GET_CONFIGURATION          0x08
+#define SET_CONFIGURATION          0x09
+#define GET_INTERFACE              0x0A
+#define SET_INTERFACE              0x0B
+
+/* Descriptor Types of USB Specifications */
+#define DEVICE_DESCRIPTOR              (1)
+#define CONFIGURATION_DESCRIPTOR       (2)
+#define STRING_DESCRIPTOR              (3)
+#define INTERFACE_DESCRIPTOR           (4)
+#define ENDPOINT_DESCRIPTOR            (5)
+#define DEVICE_QUALIFIER_DESCRIPTOR    (6)
+#define OTHER_SPEED_CONFIGURATION_DESC (7)
+#define BOS_DESCRIPTOR                 (15)
+#define HID_DESCRIPTOR                 (33)
+#define HID_REPORT_DESCRIPTOR          (34)
+
+#define SET_CONFIGURATION_TYPE 	   (USB_HOST_TO_DEVICE | USB_RECIPIENT_DEVICE | USB_REQUEST_TYPE_STANDARD)
+#define SET_ADDRESS_TYPE           (USB_HOST_TO_DEVICE | USB_RECIPIENT_DEVICE | USB_REQUEST_TYPE_STANDARD)
+#define SET_INTERFACE_TYPE         (USB_HOST_TO_DEVICE | USB_RECIPIENT_INTERFACE | USB_REQUEST_TYPE_STANDARD)
+#define CLEAR_FEATURE_TYPE         (USB_HOST_TO_DEVICE | USB_RECIPIENT_ENDPOINT | USB_REQUEST_TYPE_STANDARD)
+
+/* USB Descriptor Length */
+#define DEVICE_DESCRIPTOR_LENGTH        0x12
+#define CONFIGURATION_DESCRIPTOR_LENGTH 0x09
+#define INTERFACE_DESCRIPTOR_LENGTH     0x09
+#define ENDPOINT_DESCRIPTOR_LENGTH      0x07
+#define HID_DESCRIPTOR_LENGTH           0x09
+
+
+#define USB_EP_TYPE_CTRL           0x00
+#define USB_EP_TYPE_ISOC           0x01
+#define USB_EP_TYPE_BULK           0x02
+#define USB_EP_TYPE_INTR           0x03
+
+#define USB_PID_SETUP              0
+#define USB_PID_DATA               1
+
+/* Class code */
+#define AUDIO_CLASS                0x01
+#define CDC_CLASS                  0x02
+#define HID_CLASS                  0x03
+#define PRT_CLASS                  0x07
+#define MSC_CLASS                  0x08
+#define HUB_CLASS                  0x09
+#define DATA_INTERFACE_CLASS       0x0A
+#define BLUETOOTH_CLASS            0xE0
+
+/* usb speed */
+#define USB_DEVICE_SPEED_HIGH      0
+#define USB_DEVICE_SPEED_FULL      1
+#define USB_DEVICE_SPEED_LOW       2
+
+
+#define SETUP_PKT_LENGTH           8
+
+#define MAX_DEVICE_CONNECTED       4
+#ifndef MAX_EPS_PIPES
+#define MAX_EPS_PIPES              32
+#endif
+
+#define TUSBH_MAX_ERROR_COUNT      2
+#define TUSBH_STR_LENGTH           64
+
+typedef struct {
+    uint8_t   bLength;
+    uint8_t   bDescriptorType;
+    uint16_t  bcdUSB;
+    uint8_t   bDeviceClass;
+    uint8_t   bDeviceSubClass; 
+    uint8_t   bDeviceProtocol;
+    uint8_t   bMaxPacketSize;
+    uint16_t  idVendor;
+    uint16_t  idProduct;
+    uint16_t  bcdDevice;
+    uint8_t   iManufacturer;
+    uint8_t   iProduct;
+    uint8_t   iSerialNumber;
+    uint8_t   bNumConfigurations;
+} DeviceDescriptor;
+
+typedef struct {
+    uint8_t   bLength;
+    uint8_t   bDescriptorType;
+    uint16_t  wTotalLength;
+    uint8_t   bNumInterfaces;
+    uint8_t   bConfigurationValue;
+    uint8_t   iConfiguration;
+    uint8_t   bmAttributes;
+    uint8_t   bMaxPower;
+} ConfigurationDescriptor;
+
+typedef struct {
+	uint8_t   bLength;
+	uint8_t   bDescriptorType;
+	uint8_t   bInterfaceNumber;
+	uint8_t   bAlternateSetting;
+	uint8_t   bNumEndpoints;
+	uint8_t   bInterfaceClass;
+	uint8_t   bInterfaceSubClass;
+	uint8_t   bInterfaceProtocol;
+	uint8_t   iInterface;
+} InterfaceDescriptor;
+
+typedef struct {
+    uint8_t   bLength;
+    uint8_t   bDescriptorType;
+    uint8_t   bEndpointAddress;
+    uint8_t   bmAttributes;
+    uint16_t  wMaxPacketSize;
+    uint8_t   bInterval;
+} EndpointDescriptor;
+
+typedef struct {
+	uint8_t   bDescLength;
+	uint8_t   bDescriptorType;
+	uint8_t   bNbrPorts;
+	uint8_t   wHubCharacteristics[2];
+	uint8_t   bPwrOn2PwrGood;
+	uint8_t   bHubContrCurrent;
+	uint8_t   DeviceRemovable;
+	uint8_t   PortPweCtrlMak;
+} HubDescriptor;
+
+typedef struct {
+	uint8_t   bmRequest;
+	uint8_t   bRequest;
+	uint16_t  wValue;
+	uint16_t  wIndex;
+	uint16_t  wLength;
+} UsbSetupRequest;
+
+typedef struct {
+    uint32_t  baudrate;
+    uint8_t   stop_bits;	/* 0-1 Stop bit 1-1.5 Stop bits 2-2 Stop bits */
+    uint8_t   parity;		/* 0:None 1:Odd 2:Even 3:Mark 4:Space */
+    uint8_t   data_bits;
+} Line_Coding_t;
+
+
+/*
+ *  TUSBH ERROR CODE型
+ */
+typedef enum {
+	TUSBH_E_OK = 0,
+	TUSBH_E_BUSY,
+	TUSBH_E_BUSY_URB,
+	TUSBH_E_PAR,
+	TUSBH_E_OBJ,
+	TUSBH_E_ERR,
+	TUSBH_E_URB,
+	TUSBH_E_RTOS,
+	TUSBH_E_NOSPT,
+	TUSBH_E_TMOUT,
+	TUSBH_E_SYS,
+} TUSBH_ERCODE;
+
+/*
+ *  TUSBD ERROR CODE型
+ */
+typedef enum {
+	TUSBD_E_OK = 0,
+	TUSBD_E_BUSY,
+	TUSBD_E_ERR
+} TUSBD_ERCODE;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _TUSB_TYPES_H_ */
+
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/utils/applyrename
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/utils/applyrename	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/utils/applyrename	(revision 453)
@@ -0,0 +1,134 @@
+#! /usr/bin/perl
+#
+#  TOPPERS Software
+#      Toyohashi Open Platform for Embedded Real-Time Systems
+# 
+#  Copyright (C) 2003 by Embedded and Real-Time Systems Laboratory
+#                              Toyohashi Univ. of Technology, JAPAN
+#  Copyright (C) 2004-2011 by Embedded and Real-Time Systems Laboratory
+#              Graduate School of Information Science, Nagoya Univ., JAPAN
+# 
+#  ä¸è¨èä½æ¨©è
+ã¯ï¼ä»¥ä¸ã®(1)ï½(4)ã®æ¡ä»¶ãæºããå ´åã«éãï¼æ¬ã½ããã¦ã§
+#  ã¢ï¼æ¬ã½ããã¦ã§ã¢ãæ¹å¤ãããã®ãå«ãï¼ä»¥ä¸åãï¼ãä½¿ç¨ã»è¤è£½ã»æ¹
+#  å¤ã»åé
+å¸ï¼ä»¥ä¸ï¼å©ç¨ã¨å¼ã¶ï¼ãããã¨ãç¡åã§è¨±è«¾ããï¼
+#  (1) æ¬ã½ããã¦ã§ã¢ãã½ã¼ã¹ã³ã¼ãã®å½¢ã§å©ç¨ããå ´åã«ã¯ï¼ä¸è¨ã®èä½
+#      æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãï¼ãã®ã¾ã¾ã®å½¢ã§ã½ã¼
+#      ã¹ã³ã¼ãä¸­ã«å«ã¾ãã¦ãããã¨ï¼
+#  (2) æ¬ã½ããã¦ã§ã¢ãï¼ã©ã¤ãã©ãªå½¢å¼ãªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨
+#      è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®èä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨
+#      ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#  (3) æ¬ã½ããã¦ã§ã¢ãï¼æ©å¨ã«çµã¿è¾¼ããªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããªãå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼æ¬¡ã®ããããã®æ¡ä»¶ãæºããã
+#      ã¨ï¼
+#    (a) åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®è
+#        ä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#    (b) åé
+å¸ã®å½¢æ
+ãï¼å¥ã«å®ããæ¹æ³ã«ãã£ã¦ï¼TOPPERSãã­ã¸ã§ã¯ãã«
+#        å ±åãããã¨ï¼
+#  (4) æ¬ã½ããã¦ã§ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæ
+#      å®³ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ããå
+è²¬ãããã¨ï¼
+#      ã¾ãï¼æ¬ã½ããã¦ã§ã¢ã®ã¦ã¼ã¶ã¾ãã¯ã¨ã³ãã¦ã¼ã¶ããã®ãããªãç
+#      ç±ã«åºã¥ãè«æ±ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ãã
+#      å
+è²¬ãããã¨ï¼
+# 
+#  æ¬ã½ããã¦ã§ã¢ã¯ï¼ç¡ä¿è¨¼ã§æä¾ããã¦ãããã®ã§ããï¼ä¸è¨èä½æ¨©è
+ã
+#  ãã³TOPPERSãã­ã¸ã§ã¯ãã¯ï¼æ¬ã½ããã¦ã§ã¢ã«é¢ãã¦ï¼ç¹å®ã®ä½¿ç¨ç®ç
+#  ã«å¯¾ããé©åæ§ãå«ãã¦ï¼ãããªãä¿è¨¼ãè¡ããªãï¼ã¾ãï¼æ¬ã½ããã¦ã§
+#  ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæå®³ã«é¢ãã¦ãï¼ã
+#  ã®è²¬ä»»ãè² ããªãï¼
+# 
+#  @(#) $Id$
+# 
+
+#
+#  ãã¡ã¤ã«ã«ãªãã¼ã ãé©ç¨ãã
+#
+sub applyrename
+{
+	local($infile) = @_;
+	local($outfile) = $infile.".new";
+	local($line);
+
+	open(INFILE, "< ".$infile) || die;
+	open(OUTFILE, "> ".$outfile) || die;
+
+	while ($line = <INFILE>) {
+		$line =~ s/\b(_?)($syms)\b/$1_kernel_$2/gc;
+		print OUTFILE $line;
+	}
+
+	close(INFILE);
+	close(OUTFILE);
+
+	if (`cmp $infile $outfile`) {
+		rename($infile, $infile.".bak");
+		rename($outfile, $infile);
+		print STDERR "Modified: ",$infile,"\n";
+	}
+	else {
+		unlink($outfile);
+	}
+}
+
+#
+#  ã¨ã©ã¼ãã§ãã¯
+#
+if ($#ARGV < 1) {
+	die "Usage: appyrename <prefix> <filelist>\n";
+}
+
+#
+#  åæå
+#
+@syms = ();
+$name = $ARGV[0];
+
+#
+#  ã·ã³ãã«ãªã¹ããèª­ã¿è¾¼ã
+#
+$deffile = $name."_rename.def";
+open(INFILE, $deffile) || die "Cannot open $deffile";
+while ($line = <INFILE>) {
+	chomp $line;
+	if ($line =~ /^#(.*)$/) {
+		# do nothing
+	}
+	elsif ($line =~ /^INCLUDE[ \t]+(.*)$/) {
+		# do nothing
+	}
+	elsif ($line ne "") {
+		@syms = (@syms, $line)
+	}
+}
+close(INFILE);
+
+#
+#  æ­£è¦è¡¨ç¾ãä½ã
+#
+$syms = join("|", @syms);
+
+#
+#  ãã¡ã¤ã«ã«ãªãã¼ã ãé©ç¨ãã
+#
+shift @ARGV;
+foreach $infile (@ARGV) {
+	# ãã¡ã¤ã«ã§ãªããã°ã¹ã­ãã
+	next unless (-f $infile);
+
+	applyrename($infile) if ($infile ne $deffile);
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/utils/genoffset
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/utils/genoffset	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/utils/genoffset	(revision 453)
@@ -0,0 +1,287 @@
+#! /usr/bin/perl
+#
+#  TOPPERS Software
+#      Toyohashi Open Platform for Embedded Real-Time Systems
+# 
+#  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                              Toyohashi Univ. of Technology, JAPAN
+#  Copyright (C) 2004-2011 by Embedded and Real-Time Systems Laboratory
+#              Graduate School of Information Science, Nagoya Univ., JAPAN
+# 
+#  ä¸è¨èä½æ¨©è
+ã¯ï¼ä»¥ä¸ã®(1)ï½(4)ã®æ¡ä»¶ãæºããå ´åã«éãï¼æ¬ã½ããã¦ã§
+#  ã¢ï¼æ¬ã½ããã¦ã§ã¢ãæ¹å¤ãããã®ãå«ãï¼ä»¥ä¸åãï¼ãä½¿ç¨ã»è¤è£½ã»æ¹
+#  å¤ã»åé
+å¸ï¼ä»¥ä¸ï¼å©ç¨ã¨å¼ã¶ï¼ãããã¨ãç¡åã§è¨±è«¾ããï¼
+#  (1) æ¬ã½ããã¦ã§ã¢ãã½ã¼ã¹ã³ã¼ãã®å½¢ã§å©ç¨ããå ´åã«ã¯ï¼ä¸è¨ã®èä½
+#      æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãï¼ãã®ã¾ã¾ã®å½¢ã§ã½ã¼
+#      ã¹ã³ã¼ãä¸­ã«å«ã¾ãã¦ãããã¨ï¼
+#  (2) æ¬ã½ããã¦ã§ã¢ãï¼ã©ã¤ãã©ãªå½¢å¼ãªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨
+#      è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®èä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨
+#      ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#  (3) æ¬ã½ããã¦ã§ã¢ãï¼æ©å¨ã«çµã¿è¾¼ããªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããªãå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼æ¬¡ã®ããããã®æ¡ä»¶ãæºããã
+#      ã¨ï¼
+#    (a) åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®è
+#        ä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#    (b) åé
+å¸ã®å½¢æ
+ãï¼å¥ã«å®ããæ¹æ³ã«ãã£ã¦ï¼TOPPERSãã­ã¸ã§ã¯ãã«
+#        å ±åãããã¨ï¼
+#  (4) æ¬ã½ããã¦ã§ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæ
+#      å®³ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ããå
+è²¬ãããã¨ï¼
+#      ã¾ãï¼æ¬ã½ããã¦ã§ã¢ã®ã¦ã¼ã¶ã¾ãã¯ã¨ã³ãã¦ã¼ã¶ããã®ãããªãç
+#      ç±ã«åºã¥ãè«æ±ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ãã
+#      å
+è²¬ãããã¨ï¼
+# 
+#  æ¬ã½ããã¦ã§ã¢ã¯ï¼ç¡ä¿è¨¼ã§æä¾ããã¦ãããã®ã§ããï¼ä¸è¨èä½æ¨©è
+ã
+#  ãã³TOPPERSãã­ã¸ã§ã¯ãã¯ï¼æ¬ã½ããã¦ã§ã¢ã«é¢ãã¦ï¼ç¹å®ã®ä½¿ç¨ç®ç
+#  ã«å¯¾ããé©åæ§ãå«ãã¦ï¼ãããªãä¿è¨¼ãè¡ããªãï¼ã¾ãï¼æ¬ã½ããã¦ã§
+#  ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæå®³ã«é¢ãã¦ãï¼ã
+#  ã®è²¬ä»»ãè² ããªãï¼
+# 
+#  @(#) $Id$
+# 
+
+#
+#  åæå
+#
+$infile = $ARGV[0];
+$sil_endian = "";
+
+#
+#  è§£éã§ãããã£ã¬ã¯ãã£ãã®ãã¼ãã«
+#
+%directives = (
+	"long", "",
+	"dword", "",
+	"word", "",
+	"hword", "",
+	"int", "",
+	"short", "",
+	"half", "",
+	"byte", "",
+	"value", "",
+	"uaword", "",
+	"uashort", "",
+	"data32", 4,
+	"data16", 2,
+	"data8", 1,
+	"zero", -1,
+	"space", -1,
+	"globl", 0,
+	"global", 0,
+	"align", 0,
+	"p2align", 0,
+	"even", 0,
+	"data", 0,
+	"stabs", 0,
+	"type", 0,
+	"size", 0,
+	"section", 0,
+	"sdata", 0,
+	"code", 0,
+);
+
+#
+#  ãªãã»ããå¤ã®åºå
+#
+sub parse_offset {
+	my($label, $val) = @_;
+
+	printf "#define %s\t%d\n",$label,$val;
+}
+
+#
+#  ãã£ã¬ã¯ãã£ãã®èª­ã¿åã
+#
+sub ref_bit {
+	my($size) = @_;
+	my($dir, $directive);
+
+	while ($line = <INFILE>) {
+		chomp $line;
+		next if ($line =~ /^[ \t]*[#;].*$/);
+
+		if ($line =~ /[ \t]*\.([a-zA-Z0-9]+)[ \t]*([^ \t]*)[ \t]*/
+						&& defined($dir = $directives{$1})) {
+			$directive = $1;
+			if ($dir eq "") {
+				# ç»é²ãã¹ããã£ã¬ã¯ãã£ã
+				$directives{$directive} = $size;
+			}
+			last;
+		}
+		else {
+			# è§£æã§ããªãè¡
+			print STDERR "genoffset: cannot parse: $line\n";
+			$error = 1;
+		}
+	}
+}
+
+#
+#  ããããµã¼ã
+#
+sub search_bit {
+	my($val) = @_;
+	my($val_bit);
+
+	return(-1) if ($val == 0);
+
+	$val_bit = 0;
+	while (($val & 1) == 0) {
+		$val >>= 1;
+		$val_bit++;
+	}
+	return($val_bit);
+}
+
+#
+#  ãããä½ç½®ã®åºå
+#
+sub parse_bit {
+	my($endian, $size, $label) = @_;
+	my($offset, $dir, $val, $val_bit);
+
+	if ($sil_endian && $endian ne $sil_endian) {
+		# ã¨ã³ãã£ã¢ã³ã®ä¸ä¸è´
+		print STDERR "genoffset: endian mismatch: $line\n";
+		$error = 1;
+	}
+
+	$offset = 0;
+	while ($line = <INFILE>) {
+		chomp $line;
+		next if ($line =~ /^[ \t]*[#;].*$/);
+
+		if ($line =~ /[ \t]*\.([a-zA-Z0-9]+)[ \t]*([^ \t]*)[ \t]*/
+						&& defined($dir = $directives{$1})) {
+			$val = $2;
+
+			# 16é²æ°ã¨8é²æ°ã®æ°å¤ã¸ã®å¤æå¦ç
+			if ($val =~ /^0x(.+)$/) {
+				$val = hex($1);
+			}
+			elsif ($val =~ /^0(.+)$/) {
+				$val = oct($1);
+			}
+
+			if ($dir eq "") {
+				# ãµã¤ãºãç¥ããªããã£ã¬ã¯ãã£ã
+				print STDERR "genoffset: unknown directive: $line\n";
+				$error = 1;
+			}
+			elsif ($dir == 0) {
+				# èª­ã¿é£ã°ãã¹ããã£ã¬ã¯ãã£ã
+			}
+			elsif ($dir == -1) {
+				# .zeroãã£ã¬ã¯ãã£ãã®å¦ç
+				$offset += $val;
+			}
+			elsif ($val == 0) {
+				# å¤ã0ã®ãã£ã¼ã«ãã®å¦ç
+				$offset += $dir;
+			}
+			else {
+				# å¤ã0ã§ãªããã£ã¼ã«ããè¦ã¤ããã°ã«ã¼ããçµäº
+				last;
+			}
+		}
+		else {
+			# è§£æã§ããªãè¡
+			print STDERR "genoffset: cannot parse: $line\n";
+			$error = 1;
+		}
+	}
+
+	# ãããä½ç½®ãæ¢ã
+	$val_bit = search_bit($val);
+
+	# ãã¤ãåä½ã«æç®ãã
+	if ($endian eq "B") {
+		$offset += $dir - 1;
+		$offset -= $val_bit >> 3;
+	}
+	else {
+		$offset += $val_bit >> 3;
+	}
+	$val_bit &= 0x07;
+
+	# åºååä½ã«æç®ãã
+	if ($size eq "W") {
+		if ($endian eq "B") {
+			$val_bit += 24;
+			$val_bit -= ($offset & 0x03) << 3;
+		}
+		else {
+			$val_bit += ($offset & 0x03) << 3;
+		}
+		$offset &= ~0x03;
+	}
+	elsif ($size eq "H") {
+		if ($endian eq "B") {
+			$val_bit += 8;
+			$val_bit -= ($offset & 0x01) << 3;
+		}
+		else {
+			$val_bit += ($offset & 0x01) << 3;
+		}
+		$offset &= ~0x01;
+	}
+
+	# å®ç¾©ã®åºå
+	$label =~ s/^_//;
+	printf "#define %s\t%d\n",$label,$offset;
+	printf "#define %s_bit\t%d\n",$label,$val_bit;
+	printf "#define %s_mask\t0x%x\n",$label,(1 << $val_bit);
+}
+
+#
+#  ã¡ã¤ã³ã«ã¼ãã³
+#
+print "/* This file is generated by genoffset. */\n";
+print "\n";
+
+$error = 0;
+open(INFILE, $infile) || die "Cannot open $infile";
+while ($line = <INFILE>) {
+	chomp $line;
+
+	if ($line =~ /^[ \t]*OFFSET_DEF ([^ \t]+) = [#\$]?([^ \t]+)/) {
+		parse_offset($1, $2);
+	}
+	elsif ($line =~ /^[ \t]*_?BIT_REF_([0-9]+):/) {
+		ref_bit($1);
+	}
+	elsif ($line =~ /^[ \t]*SIL_ENDIAN = ([BL])/) {
+		$sil_endian = $1;
+	}
+}
+#
+#  ã³ã³ãã¤ã©ãã°ã­ã¼ãã«å¤æ°ã®é
+ç½®é åºãå¤æ´ããã¨ï¼BIT_REF_?ãä¸ã«ãª
+#  ãå¯è½æ§ãããããï¼é ­ããèª­ã¿ç´ãï¼
+#
+seek(INFILE, 0, SEEK_SET);
+while ($line = <INFILE>) {
+	chomp $line;
+
+	if ($line =~ /^[ \t]*_?BIT_([BL])([BHW])_([^ \t]+):/) {
+		parse_bit($1, $2, $3);
+	}
+}
+close(INFILE);
+exit($error);
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/utils/genrename
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/utils/genrename	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/utils/genrename	(revision 453)
@@ -0,0 +1,265 @@
+#! /usr/bin/perl
+#
+#  TOPPERS Software
+#      Toyohashi Open Platform for Embedded Real-Time Systems
+# 
+#  Copyright (C) 2003 by Embedded and Real-Time Systems Laboratory
+#                              Toyohashi Univ. of Technology, JAPAN
+#  Copyright (C) 2005-2011 by Embedded and Real-Time Systems Laboratory
+#              Graduate School of Information Science, Nagoya Univ., JAPAN
+# 
+#  ä¸è¨èä½æ¨©è
+ã¯ï¼ä»¥ä¸ã®(1)ï½(4)ã®æ¡ä»¶ãæºããå ´åã«éãï¼æ¬ã½ããã¦ã§
+#  ã¢ï¼æ¬ã½ããã¦ã§ã¢ãæ¹å¤ãããã®ãå«ãï¼ä»¥ä¸åãï¼ãä½¿ç¨ã»è¤è£½ã»æ¹
+#  å¤ã»åé
+å¸ï¼ä»¥ä¸ï¼å©ç¨ã¨å¼ã¶ï¼ãããã¨ãç¡åã§è¨±è«¾ããï¼
+#  (1) æ¬ã½ããã¦ã§ã¢ãã½ã¼ã¹ã³ã¼ãã®å½¢ã§å©ç¨ããå ´åã«ã¯ï¼ä¸è¨ã®èä½
+#      æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãï¼ãã®ã¾ã¾ã®å½¢ã§ã½ã¼
+#      ã¹ã³ã¼ãä¸­ã«å«ã¾ãã¦ãããã¨ï¼
+#  (2) æ¬ã½ããã¦ã§ã¢ãï¼ã©ã¤ãã©ãªå½¢å¼ãªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨
+#      è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®èä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨
+#      ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#  (3) æ¬ã½ããã¦ã§ã¢ãï¼æ©å¨ã«çµã¿è¾¼ããªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããªãå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼æ¬¡ã®ããããã®æ¡ä»¶ãæºããã
+#      ã¨ï¼
+#    (a) åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®è
+#        ä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#    (b) åé
+å¸ã®å½¢æ
+ãï¼å¥ã«å®ããæ¹æ³ã«ãã£ã¦ï¼TOPPERSãã­ã¸ã§ã¯ãã«
+#        å ±åãããã¨ï¼
+#  (4) æ¬ã½ããã¦ã§ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæ
+#      å®³ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ããå
+è²¬ãããã¨ï¼
+#      ã¾ãï¼æ¬ã½ããã¦ã§ã¢ã®ã¦ã¼ã¶ã¾ãã¯ã¨ã³ãã¦ã¼ã¶ããã®ãããªãç
+#      ç±ã«åºã¥ãè«æ±ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ãã
+#      å
+è²¬ãããã¨ï¼
+# 
+#  æ¬ã½ããã¦ã§ã¢ã¯ï¼ç¡ä¿è¨¼ã§æä¾ããã¦ãããã®ã§ããï¼ä¸è¨èä½æ¨©è
+ã
+#  ãã³TOPPERSãã­ã¸ã§ã¯ãã¯ï¼æ¬ã½ããã¦ã§ã¢ã«é¢ãã¦ï¼ç¹å®ã®ä½¿ç¨ç®ç
+#  ã«å¯¾ããé©åæ§ãå«ãã¦ï¼ãããªãä¿è¨¼ãè¡ããªãï¼ã¾ãï¼æ¬ã½ããã¦ã§
+#  ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæå®³ã«é¢ãã¦ãï¼ã
+#  ã®è²¬ä»»ãè² ããªãï¼
+# 
+#  @(#) $Id$
+# 
+
+#
+#  å
+é ­ã«ã¤ããæå­å
+#
+sub prefix_string {
+	local($sym) = @_;
+
+	if ($sym =~ /[a-z]/) {
+		return("_kernel_");
+	}
+	else {
+		return("_KERNEL_");
+	}
+}
+
+#
+#  ãªãã¼ã å®ç¾©ãçæãã
+#
+sub generate_define
+{
+	local($sym, $prefix) = @_;
+
+	print FILE "#define ",$prefix,$sym;
+	print FILE "\t" if (length($prefix.$sym) < 4);
+	print FILE "\t" if (length($prefix.$sym) < 8);
+	print FILE "\t" if (length($prefix.$sym) < 12);
+	print FILE "\t" if (length($prefix.$sym) < 16);
+	print FILE "\t" if (length($prefix.$sym) < 20);
+	print FILE "\t" if (length($prefix.$sym) < 24);
+	print FILE "\t",$prefix,prefix_string($sym),$sym,"\n";
+}
+
+#
+#  ãªãã¼ã è§£é¤ãçæãã
+#
+sub generate_undef
+{
+	local($sym, $prefix) = @_;
+
+	print FILE "#undef ",$prefix,$sym,"\n";
+}
+
+#
+#  ã¤ã³ã¯ã«ã¼ããã£ã¬ã¯ãã£ããçæãã
+#
+sub generate_include
+{
+	local($file, $prefix) = @_;
+
+	$file =~ s/([>"])$/_$prefix.h$1/;
+	$includes .= "#include ".$file."\n";
+}
+
+#
+#  ã¨ã©ã¼ãã§ãã¯
+#
+if ($#ARGV != 0) {
+	die "Usage: genrename <prefix>\n";
+}
+
+#
+#  åæå
+#
+@syms = ();
+$name = $ARGV[0];
+$NAME = $name; $NAME =~ y/a-z/A-Z/;
+
+$infile = $name."_rename.def";
+$header_defsym = "TOPPERS_".$NAME."_RENAME_H";
+
+#
+#  ã·ã³ãã«ãªã¹ããèª­ã¿è¾¼ã
+#
+open(INFILE, $infile) || die "Cannot open $infile";
+while ($line = <INFILE>) {
+	chomp $line;
+	@syms = (@syms, $line);
+}
+close(INFILE);
+
+#
+#  ???_rename.h ãçæãã
+#
+$includes = "";
+$file = $name."_rename.h";
+open(FILE, "> ".$file);
+
+print FILE <<END;
+/* This file is generated from $infile by genrename. */
+
+#ifndef $header_defsym
+#define $header_defsym
+
+END
+
+foreach $sym (@syms) {
+	if ($sym =~ /^#(.*)$/) {
+		print FILE "/*\n";
+		print FILE " * ",$1,"\n";
+		print FILE " */\n";
+	}
+	elsif ($sym =~ /^INCLUDE[ \t]+(.*)$/) {
+		generate_include($1, "rename");
+	}
+	elsif ($sym ne "") {
+		generate_define($sym, "");
+	}
+	else {
+		print FILE "\n";
+	}
+}
+
+print FILE <<END;
+
+#ifdef TOPPERS_LABEL_ASM
+
+END
+
+foreach $sym (@syms) {
+	if ($sym =~ /^#(.*)$/) {
+		print FILE "/*\n";
+		print FILE " * ",$1,"\n";
+		print FILE " */\n";
+	}
+	elsif ($sym =~ /^INCLUDE[ \t]+(.*)$/) {
+		# do nothing
+	}
+	elsif ($sym ne "") {
+		generate_define($sym, "_");
+	}
+	else {
+		print FILE "\n";
+	}
+}
+
+print FILE <<END;
+
+#endif /* TOPPERS_LABEL_ASM */
+
+$includes
+#endif /* $header_defsym */
+END
+
+#
+#  ???_unrename.h ãçæãã
+#
+$includes = "";
+$file = $name."_unrename.h";
+open(FILE, "> ".$file);
+
+print FILE <<END;
+/* This file is generated from $infile by genrename. */
+
+/* This file is included only when $name\_rename.h has been included. */
+#ifdef $header_defsym
+#undef $header_defsym
+
+END
+
+foreach $sym (@syms) {
+	if ($sym =~ /^#(.*)$/) {
+		print FILE "/*\n";
+		print FILE " * ",$1,"\n";
+		print FILE " */\n";
+	}
+	elsif ($sym =~ /^INCLUDE[ \t]+(.*)$/) {
+		generate_include($1, "unrename");
+	}
+	elsif ($sym ne "") {
+		generate_undef($sym, "");
+	}
+	else {
+		print FILE "\n";
+	}
+}
+
+print FILE <<END;
+
+#ifdef TOPPERS_LABEL_ASM
+
+END
+
+foreach $sym (@syms) {
+	if ($sym =~ /^#(.*)$/) {
+		print FILE "/*\n";
+		print FILE " * ",$1,"\n";
+		print FILE " */\n";
+	}
+	elsif ($sym =~ /^INCLUDE[ \t]+(.*)$/) {
+		# do nothing
+	}
+	elsif ($sym ne "") {
+		generate_undef($sym, "_");
+	}
+	else {
+		print FILE "\n";
+	}
+}
+
+print FILE <<END;
+
+#endif /* TOPPERS_LABEL_ASM */
+
+$includes
+#endif /* $header_defsym */
+END
+
+close(FILE);
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/utils/gentest
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/utils/gentest	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/utils/gentest	(revision 453)
@@ -0,0 +1,379 @@
+#! /usr/bin/perl
+#
+#  TOPPERS Software
+#      Toyohashi Open Platform for Embedded Real-Time Systems
+# 
+#  Copyright (C) 2007-2014 by Embedded and Real-Time Systems Laboratory
+#              Graduate School of Information Science, Nagoya Univ., JAPAN
+# 
+#  ä¸è¨èä½æ¨©è
+ã¯ï¼ä»¥ä¸ã®(1)ï½(4)ã®æ¡ä»¶ãæºããå ´åã«éãï¼æ¬ã½ããã¦ã§
+#  ã¢ï¼æ¬ã½ããã¦ã§ã¢ãæ¹å¤ãããã®ãå«ãï¼ä»¥ä¸åãï¼ãä½¿ç¨ã»è¤è£½ã»æ¹
+#  å¤ã»åé
+å¸ï¼ä»¥ä¸ï¼å©ç¨ã¨å¼ã¶ï¼ãããã¨ãç¡åã§è¨±è«¾ããï¼
+#  (1) æ¬ã½ããã¦ã§ã¢ãã½ã¼ã¹ã³ã¼ãã®å½¢ã§å©ç¨ããå ´åã«ã¯ï¼ä¸è¨ã®èä½
+#      æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãï¼ãã®ã¾ã¾ã®å½¢ã§ã½ã¼
+#      ã¹ã³ã¼ãä¸­ã«å«ã¾ãã¦ãããã¨ï¼
+#  (2) æ¬ã½ããã¦ã§ã¢ãï¼ã©ã¤ãã©ãªå½¢å¼ãªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨
+#      è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®èä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨
+#      ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#  (3) æ¬ã½ããã¦ã§ã¢ãï¼æ©å¨ã«çµã¿è¾¼ããªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããªãå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼æ¬¡ã®ããããã®æ¡ä»¶ãæºããã
+#      ã¨ï¼
+#    (a) åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®è
+#        ä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#    (b) åé
+å¸ã®å½¢æ
+ãï¼å¥ã«å®ããæ¹æ³ã«ãã£ã¦ï¼TOPPERSãã­ã¸ã§ã¯ãã«
+#        å ±åãããã¨ï¼
+#  (4) æ¬ã½ããã¦ã§ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæ
+#      å®³ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ããå
+è²¬ãããã¨ï¼
+#      ã¾ãï¼æ¬ã½ããã¦ã§ã¢ã®ã¦ã¼ã¶ã¾ãã¯ã¨ã³ãã¦ã¼ã¶ããã®ãããªãç
+#      ç±ã«åºã¥ãè«æ±ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ãã
+#      å
+è²¬ãããã¨ï¼
+# 
+#  æ¬ã½ããã¦ã§ã¢ã¯ï¼ç¡ä¿è¨¼ã§æä¾ããã¦ãããã®ã§ããï¼ä¸è¨èä½æ¨©è
+ã
+#  ãã³TOPPERSãã­ã¸ã§ã¯ãã¯ï¼æ¬ã½ããã¦ã§ã¢ã«é¢ãã¦ï¼ç¹å®ã®ä½¿ç¨ç®ç
+#  ã«å¯¾ããé©åæ§ãå«ãã¦ï¼ãããªãä¿è¨¼ãè¡ããªãï¼ã¾ãï¼æ¬ã½ããã¦ã§
+#  ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæå®³ã«é¢ãã¦ãï¼ã
+#  ã®è²¬ä»»ãè² ããªãï¼
+# 
+#  $Id$
+# 
+
+#
+#		ãã¹ããã­ã°ã©ã çæãã¼ã«
+#
+
+use open ":encoding(euc-jp)";
+use encoding "euc-jp";
+
+$infile = $ARGV[0];
+
+%parampos = (
+	"get_pri" => 2,
+	"get_inf" => 1,
+	"ref_tsk" => 2,
+	"ref_tex" => 2,
+	"ref_sem" => 2,
+	"ref_flg" => 2,
+	"ref_dtq" => 2,
+	"ref_pdq" => 2,
+	"ref_mbx" => 2,
+	"ref_mtx" => 2,
+	"ref_mbf" => 2,
+	"ref_mpf" => 2,
+	"get_tim" => 1,
+	"get_utm" => 1,
+	"ref_cyc" => 2,
+	"ref_alm" => 2,
+	"get_tid" => 1,
+	"iget_tid" => 1,
+	"get_ipm" => 1,
+);
+
+%paramtype = (
+	"get_pri" => "PRI",
+	"get_inf" => "intptr_t",
+	"ref_tsk" => "T_RTSK",
+	"ref_tex" => "T_RTEX",
+	"ref_sem" => "T_RSEM",
+	"ref_flg" => "T_RFLG",
+	"ref_dtq" => "T_RDTQ",
+	"ref_pdq" => "T_RPDQ",
+	"ref_mbx" => "T_RMBX",
+	"ref_mtx" => "T_RMTX",
+	"ref_mbf" => "T_RMBF",
+	"ref_mpf" => "T_RMPF",
+	"get_tim" => "SYSTIM",
+	"get_utm" => "SYSUTM",
+	"ref_cyc" => "T_RCYC",
+	"ref_alm" => "T_RALM",
+	"get_tid" => "ID",
+	"iget_tid" => "ID",
+	"get_ipm" => "PRI",
+);
+
+$last_check_point = 0;
+
+sub gen_var_def {
+	local($svc_call) = @_;
+	local($svcname, @params);
+	local($typename, $varname);
+
+	if ($svc_call =~ /^([a-z_]+)\((.*)\)$/) {
+		$svcname = $1;
+		@params = split(/\s*,\s*/, $2);
+
+		if ($parampos{$svcname}) {
+			$varname = $params[@parampos{$svcname} - 1];
+			$varname =~ s/^\&//;
+			$typename = $paramtype{$svcname};
+			${$TASKVAR{$tskid}}{$typename} = ${varname};
+		}
+	}
+}
+
+sub gen_svc_call {
+	local($svc_call, $error_code_string) = @_;
+	local($error_code);
+
+	${$TASKVAR{$tskid}}{"ER_UINT"} = "ercd";
+
+	push(@{$TASKCODE{$tskid}{$tskcnt}}, sprintf("\tercd = %s;", $svc_call));
+	gen_var_def($svc_call);
+
+	if ($error_code_string eq "") {
+		push(@{$TASKCODE{$tskid}{$tskcnt}},
+								sprintf("\tcheck_ercd(ercd, E_OK);"), "");
+	}
+	elsif ($error_code_string =~ /^\-\>\s*noreturn$/) {
+		push(@{$TASKCODE{$tskid}{$tskcnt}}, "");
+	}
+	else {
+		$error_code = $error_code_string;
+		$error_code =~ s/^\-\>\s*([A-Za-z0-9_]*)$/$1/;
+		push(@{$TASKCODE{$tskid}{$tskcnt}},
+						sprintf("\tcheck_ercd(ercd, %s);", $error_code), "");
+	}
+}
+
+sub parse_line {
+	local($line) = @_;
+
+	while ($line =~ s/\\$//) {
+		$line1 = <INFILE>;
+		$output_line .= $line1;
+		chomp $line1;
+		$line1 =~ s/^\s*\*\s*//;
+		$line1 =~ s/\s*\/\/.*$//;
+		$line1 =~ s/\s*\.\.\..*$//;
+		$line .= $line1;
+	}
+
+	if ($line =~ /^\.\./) {
+		# do nothing.
+	}
+	elsif ($line =~ /^==\s*((TASK|ALM|CPUEXC|EXTSVC)[0-9]*)(.*)$/) {
+		$procflag = 1;
+		$tskid = $1;
+		$line2 = $3;
+		if ($line2 =~ /^\-TEX(.*)$/) {
+			$tskid = $tskid."-TEX";
+			$line2 = $1;
+		}
+		if ($line2 =~ /^\-([0-9]+)(.*)$/) {
+			$tskcnt = $1;
+			if (!$TASKCOUNTVAR{$tskid}) {
+				if ($tskid =~ /^TASK([0-9]*)$/) {
+					$countvar = "task$1_count";
+				}
+				elsif ($tskid =~ /^TASK([0-9]*)-TEX$/) {
+					$countvar = "tex_task$1_count";
+				}
+				elsif ($tskid =~ /^ALM([0-9]*)$/) {
+					$countvar = "alarm$1_count";
+				}
+				elsif ($tskid =~ /^CPUEXC([0-9]*)$/) {
+					$countvar = "cpuexc$1_count";
+				}
+				elsif ($tskid =~ /^EXTSVC([0-9]*)$/) {
+					$countvar = "extsvc$1_count";
+				}
+				$TASKCOUNTVAR{$tskid} = $countvar;
+			}
+		}
+		else {
+			$tskcnt = "";
+		}
+		if ($startflag) {
+			push(@{$TASKCODE{$tskid}{$tskcnt}}, "\ttest_start(__FILE__);");
+			push(@{$TASKCODE{$tskid}{$tskcnt}}, "");
+			$startflag = 0;
+		}
+	}
+	elsif (!$procflag) {
+		# do nothing.
+	}
+	elsif ($line =~ /^([0-9]+\:)\s*END$/) {
+		$check_str = $1;
+		$check_no = ++$last_check_point;
+		push(@{$TASKCODE{$tskid}{$tskcnt}},
+								sprintf("\tcheck_finish(%d);", $check_no));
+		$procflag = 0;
+		$output_line =~ s/$check_str/$check_no:/;
+	}
+	else {
+		if ($line =~ /^([0-9]+\:)\s*(.*)/) {
+			$check_str = $1;
+			$line = $2;
+			$check_no = ++$last_check_point;
+			push(@{$TASKCODE{$tskid}{$tskcnt}},
+								sprintf("\tcheck_point(%d);", $check_no));
+			$output_line =~ s/$check_str/$check_no:/;
+		}
+		if ($line =~ /^(assert\(.*\))$/) {
+			$assert_string = $1;
+			push(@{$TASKCODE{$tskid}{$tskcnt}},
+								sprintf("\tcheck_%s;", $assert_string), "");
+		}
+		elsif ($line =~ /^(state(_i)?\(.*\))$/) {
+			$state_string = $1;
+			push(@{$TASKCODE{$tskid}{$tskcnt}},
+								sprintf("\tcheck_%s;", $state_string), "");
+		}
+		elsif ($line =~ /^call\((.*)\)$/ || $line =~ /^DO\((.*)\)$/) {
+			$call_string = $1;
+			push(@{$TASKCODE{$tskid}{$tskcnt}},
+									sprintf("\t%s;", $call_string), "");
+		}
+		elsif ($line =~ /^MISSING$/) {
+			push(@{$TASKCODE{$tskid}{$tskcnt}}, "");
+		}
+		elsif ($line =~ /^RETURN((\(.*\))?)$/) {
+			$return_string = $1;
+			push(@{$TASKCODE{$tskid}{$tskcnt}},
+									"\treturn".$return_string.";", "");
+		}
+		elsif ($line =~ /^GOTO\((.*)\)$/) {
+			$goto_string = $1;
+			push(@{$TASKCODE{$tskid}{$tskcnt}},
+									sprintf("\tgoto %s;", $goto_string), "");
+		}
+		elsif ($line =~ /^LABEL\((.*)\)$/) {
+			$label_string = $1;
+			$indent_string = $indentstr;
+			$indent_string =~ s/\t$//;
+			push(@{$TASKCODE{$tskid}{$tskcnt}},
+									sprintf("%s:", $label_string));
+		}
+		elsif ($line =~ /^([a-z_]+\(.*\))\s*(\-\>\s*[A-Za-z0-9_]*)?\s*$/) {
+			$svc_call = $1;
+			$error_code_string = $2;
+			gen_svc_call($svc_call, $error_code_string);
+		}
+		else {
+			print STDERR "Error: ",$line,"\n";
+		}
+	}
+}
+
+#
+#  ã¹ã¯ãªãããã¡ã¤ã«èª­è¾¼ã¿å¦ç
+#
+$procflag = 0;
+$startflag = 1;
+$outflag = 1;
+open(INFILE, $infile) || die "Cannot open $infile";
+while (($line = <INFILE>) && $outflag) {
+	$output_line = $line;
+	chomp $line;
+	$line =~ s/^\s*\*\s*//;
+	$line =~ s/\s*\/\/.*$//;
+	$line =~ s/\s*\.\.\..*$//;
+	if ($line) {
+		parse_line($line);
+	}
+	print $output_line;
+	if ($output_line =~ /DO NOT DELETE THIS LINE/) {
+		$outflag = 0;
+	}
+}
+close(INFILE);
+
+#
+#  ã¿ã¹ã¯ã®å¤æ°å®ç¾©ã®ã³ã¼ãåºå
+#
+sub output_task_vardef {
+	my($tskid) = @_;
+
+	foreach my $typename (keys(%{$TASKVAR{$tskid}})) {
+		print "\t",$typename, (length($typename) < 4 ? "\t\t" : "\t"),
+								${$TASKVAR{$tskid}}{$typename},";\n";
+	}
+}
+
+#
+#  ã¿ã¹ã¯æ¬ä½ã®ã³ã¼ãåºå
+#
+sub output_task_body {
+	my($tskid) = @_;
+
+	foreach my $tskcnt (sort {$a <=> $b} (keys(%{$TASKCODE{$tskid}}))) {
+		printf "\tcase %d:\n", $tskcnt;
+		foreach my $line (@{$TASKCODE{$tskid}{$tskcnt}}) {
+			print "\t",$line if ($line);
+			print "\n";
+		}
+		printf "\t\tcheck_point(0);\n\n";
+	}
+}
+
+#
+#  ã¿ã¹ã¯ã³ã¼ãã®åºå
+#
+sub output_task {
+	if ($TASKCOUNTVAR{$tskid}) {
+		printf "\nstatic uint_t\t%s = 0;\n", $TASKCOUNTVAR{$tskid};
+	}
+	if ($tskid =~ /^TASK([0-9]*)$/) {
+		print "\nvoid\n";
+		print "task$1(intptr_t exinf)\n";
+	}
+	elsif ($tskid =~ /^TASK([0-9]*)-TEX$/) {
+		print "\nvoid\n";
+		print "tex_task$1(TEXPTN texptn, intptr_t exinf)\n";
+	}
+	elsif ($tskid =~ /^ALM([0-9]*)$/) {
+		print "\nvoid\n";
+		print "alarm$1_handler(intptr_t exinf)\n";
+	}
+	elsif ($tskid =~ /^CPUEXC([0-9]*)$/) {
+		print "\nvoid\n";
+		print "cpuexc$1_handler(void *p_excinf)\n";
+	}
+	elsif ($tskid =~ /^EXTSVC([0-9]*)$/) {
+		print "\nER_UINT\n";
+		print "extsvc$1_routine(intptr_t par1, intptr_t par2, intptr_t par3,\n";
+		print "\t\t\t\t\t\t\t\tintptr_t par4, intptr_t par5, ID cdmid)\n";
+	}
+	print "{\n";
+	output_task_vardef($tskid);
+	print "\n";
+	if ($TASKCOUNTVAR{$tskid}) {
+		printf "\tswitch (++%s) {\n", $TASKCOUNTVAR{$tskid};
+		output_task_body($tskid);
+		printf "\tdefault:\n";
+		printf "\t\tcheck_point(0);\n";
+		printf "\t}\n";
+	}
+	else {
+		foreach my $line (@{$TASKCODE{$tskid}{""}}) {
+			print $line,"\n";
+		}
+	}
+	print "\tcheck_point(0);\n";
+	if ($tskid =~ /^EXTSVC([0-9]*)$/) {
+		print "\treturn(E_SYS);\n";
+	}
+	print "}\n";
+}
+
+#
+#  ãã¹ããã­ã°ã©ã åºåå¦ç
+#
+foreach $tskid (sort(keys(%TASKCODE))) {
+	output_task();
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/utils/makedep
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/utils/makedep	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/utils/makedep	(revision 453)
@@ -0,0 +1,194 @@
+#! /usr/bin/perl
+#
+#  TOPPERS Software
+#      Toyohashi Open Platform for Embedded Real-Time Systems
+# 
+#  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
+#                              Toyohashi Univ. of Technology, JAPAN
+#  Copyright (C) 2004-2013 by Embedded and Real-Time Systems Laboratory
+#              Graduate School of Information Science, Nagoya Univ., JAPAN
+# 
+#  ä¸è¨èä½æ¨©è
+ã¯ï¼ä»¥ä¸ã®(1)ï½(4)ã®æ¡ä»¶ãæºããå ´åã«éãï¼æ¬ã½ããã¦ã§
+#  ã¢ï¼æ¬ã½ããã¦ã§ã¢ãæ¹å¤ãããã®ãå«ãï¼ä»¥ä¸åãï¼ãä½¿ç¨ã»è¤è£½ã»æ¹
+#  å¤ã»åé
+å¸ï¼ä»¥ä¸ï¼å©ç¨ã¨å¼ã¶ï¼ãããã¨ãç¡åã§è¨±è«¾ããï¼
+#  (1) æ¬ã½ããã¦ã§ã¢ãã½ã¼ã¹ã³ã¼ãã®å½¢ã§å©ç¨ããå ´åã«ã¯ï¼ä¸è¨ã®èä½
+#      æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãï¼ãã®ã¾ã¾ã®å½¢ã§ã½ã¼
+#      ã¹ã³ã¼ãä¸­ã«å«ã¾ãã¦ãããã¨ï¼
+#  (2) æ¬ã½ããã¦ã§ã¢ãï¼ã©ã¤ãã©ãªå½¢å¼ãªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨
+#      è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®èä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨
+#      ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#  (3) æ¬ã½ããã¦ã§ã¢ãï¼æ©å¨ã«çµã¿è¾¼ããªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããªãå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼æ¬¡ã®ããããã®æ¡ä»¶ãæºããã
+#      ã¨ï¼
+#    (a) åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®è
+#        ä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#    (b) åé
+å¸ã®å½¢æ
+ãï¼å¥ã«å®ããæ¹æ³ã«ãã£ã¦ï¼TOPPERSãã­ã¸ã§ã¯ãã«
+#        å ±åãããã¨ï¼
+#  (4) æ¬ã½ããã¦ã§ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæ
+#      å®³ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ããå
+è²¬ãããã¨ï¼
+#      ã¾ãï¼æ¬ã½ããã¦ã§ã¢ã®ã¦ã¼ã¶ã¾ãã¯ã¨ã³ãã¦ã¼ã¶ããã®ãããªãç
+#      ç±ã«åºã¥ãè«æ±ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ãã
+#      å
+è²¬ãããã¨ï¼
+# 
+#  æ¬ã½ããã¦ã§ã¢ã¯ï¼ç¡ä¿è¨¼ã§æä¾ããã¦ãããã®ã§ããï¼ä¸è¨èä½æ¨©è
+ã
+#  ãã³TOPPERSãã­ã¸ã§ã¯ãã¯ï¼æ¬ã½ããã¦ã§ã¢ã«é¢ãã¦ï¼ç¹å®ã®ä½¿ç¨ç®ç
+#  ã«å¯¾ããé©åæ§ãå«ãã¦ï¼ãããªãä¿è¨¼ãè¡ããªãï¼ã¾ãï¼æ¬ã½ããã¦ã§
+#  ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæå®³ã«é¢ãã¦ãï¼ã
+#  ã®è²¬ä»»ãè² ããªãï¼
+# 
+#  @(#) $Id$
+# 
+
+use Getopt::Std;
+
+#  ãªãã·ã§ã³ã®å®ç¾©
+#
+#  -C <cc_path>		Cã³ã³ãã¤ã©ã®ã³ãã³ãå
+#  -O <cc_opts>		Cã³ã³ãã¤ã©/CPPã«æ¸¡ããªãã·ã§ã³
+#  -X				ã½ã¼ã¹ãã¡ã¤ã«ãå¼·å¶çã«Cããããã¡ã¤ã«ã¨è¦ãªã
+#
+#  -T <target>		ã¿ã¼ã²ããåï¼ã®ãªã¹ãï¼
+#  -D <t_dir>		ã¿ã¼ã²ããã®ãã£ã¬ã¯ããªåãæå®ããï¼-Tãç¨ããå ´
+#					åã¯ç¡å¹ï¼
+#  -d				ã¿ã¼ã²ããã®ãã£ã¬ã¯ããªé¨ãä¿æããï¼-Tãç¨ããå ´
+#					åã¯ç¡å¹ï¼
+#  -S				è¤æ°ã®ã¿ã¼ã²ãããããä¾å­ã«ã¼ã«ãï¼ã¿ã¼ã²ããæ¯ã«
+#					åå²ããï¼ããããªãã¨å¯¾å¿ã§ããªãmakeããããããï¼
+#
+#  -R <dirname>		Cygwinç°å¢ã«ãããã«ã¼ããã£ã¬ã¯ããªåãæå®ãã
+#					ï¼ããã©ã«ãã¯cygdriveï¼
+
+#
+#  ãªãã·ã§ã³ã®å¦ç
+#
+getopt("COTDR");
+
+$cc_path = $opt_C;
+$cc_opts = $opt_O;
+
+if ($opt_T) {
+	$target_name = $opt_T;
+}
+elsif ($opt_D) {
+	$target_dir = $opt_D;
+}
+elsif (!$opt_d) {
+	$target_dir = "";
+}
+
+if ($opt_R) {
+	$cygwin_root = $opt_R;
+}
+else {
+	$cygwin_root = "cygdrive";
+}
+
+#
+#  Cygwinç°å¢ã®å¤å¥
+#
+if ($^O eq 'cygwin') {
+	$cygwin = 1;
+}
+
+#
+#  %dependlist ã«ä½ãããä¾å­é¢ä¿ãåºåãã
+#
+sub output_dependlist {
+	local($target) = @_;
+	local($column, $len, $file);
+
+	print $target, ": ";
+	$column = length($target) + 2;
+
+	foreach $file (keys(%dependlist)) {
+		$len = length($file) + 1;
+		if ($column > 8 && $column + $len >= 70) {
+			print "\\\n\t";
+			$column = 8;
+		}
+		$column += $len;
+		print "$file ";
+	}
+	print "\n";
+}
+
+#
+#  $file ã®ä¾å­é¢ä¿ã %dependlist ã«ä½ã
+#
+sub makedepend_one {
+	local($file) = @_;
+	local($command, $input, $dir, $filename);
+
+	$command = "$cc_path -E $cc_opts";
+	if ($opt_X) {
+		$command .= " -x c-header";
+	}
+	unless (open(INPUT, "$command $file |")) {
+		print STDERR "makedep: can't open $file\n";
+		exit(1);
+	}
+	while ($line = <INPUT>) {
+		if ($line =~ /^\#[a-zA-Z]*\s*([0-9]+)\s*\"([^\"]+)\"/) {
+			$filename = $2;
+			$filename =~ s/ /\\ /g;
+			if ($filename !~ /^\<.*\>$/ && $filename !~ /\/$/) {
+				if ($cygwin) {
+					$filename =~ s/\\\\/\//g;
+					$filename =~ s/^([a-zA-Z]):/\/$cygwin_root\/$1/;
+				}
+				$dependlist{$filename} = 1;
+			}
+		}
+	}
+	unless (close(INPUT)) {
+		print STDERR "makedep: can't execute $command\n";
+		exit(1);
+	}
+}
+
+#
+#  ã¡ã¤ã³ã«ã¼ãã³
+#
+foreach $file (@ARGV) {
+	%dependlist = ();
+	makedepend_one($file);
+	if (%dependlist) {
+		if ($target_name) {
+			if ($opt_S) {
+				foreach $target (split(/[ \t]+/, $target_name)) {
+					output_dependlist($target);
+				}
+			}
+			else {
+				output_dependlist($target_name);
+			}
+		}
+		else {
+			$target = $file;
+			$target =~ s/(.*)\.(.*)/$1.o/;
+			if (defined($target_dir)) {
+				$target =~ s/^.*\/([^\/]+)$/$1/;
+				if ($target_dir) {
+					$target = $target_dir."/".$target;
+				}
+			}
+			output_dependlist($target);
+		}
+	}
+}
Index: azure_iot_hub_riscv/trunk/asp_baseplatform/utils/makerelease
===================================================================
--- azure_iot_hub_riscv/trunk/asp_baseplatform/utils/makerelease	(revision 453)
+++ azure_iot_hub_riscv/trunk/asp_baseplatform/utils/makerelease	(revision 453)
@@ -0,0 +1,171 @@
+#! /usr/bin/perl
+#
+#  TOPPERS Software
+#      Toyohashi Open Platform for Embedded Real-Time Systems
+# 
+#  Copyright (C) 2006-2011 by Embedded and Real-Time Systems Laboratory
+#              Graduate School of Information Science, Nagoya Univ., JAPAN
+# 
+#  ä¸è¨èä½æ¨©è
+ã¯ï¼ä»¥ä¸ã®(1)ï½(4)ã®æ¡ä»¶ãæºããå ´åã«éãï¼æ¬ã½ããã¦ã§
+#  ã¢ï¼æ¬ã½ããã¦ã§ã¢ãæ¹å¤ãããã®ãå«ãï¼ä»¥ä¸åãï¼ãä½¿ç¨ã»è¤è£½ã»æ¹
+#  å¤ã»åé
+å¸ï¼ä»¥ä¸ï¼å©ç¨ã¨å¼ã¶ï¼ãããã¨ãç¡åã§è¨±è«¾ããï¼
+#  (1) æ¬ã½ããã¦ã§ã¢ãã½ã¼ã¹ã³ã¼ãã®å½¢ã§å©ç¨ããå ´åã«ã¯ï¼ä¸è¨ã®èä½
+#      æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãï¼ãã®ã¾ã¾ã®å½¢ã§ã½ã¼
+#      ã¹ã³ã¼ãä¸­ã«å«ã¾ãã¦ãããã¨ï¼
+#  (2) æ¬ã½ããã¦ã§ã¢ãï¼ã©ã¤ãã©ãªå½¢å¼ãªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨
+#      è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®èä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨
+#      ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#  (3) æ¬ã½ããã¦ã§ã¢ãï¼æ©å¨ã«çµã¿è¾¼ããªã©ï¼ä»ã®ã½ããã¦ã§ã¢éçºã«ä½¿
+#      ç¨ã§ããªãå½¢ã§åé
+å¸ããå ´åã«ã¯ï¼æ¬¡ã®ããããã®æ¡ä»¶ãæºããã
+#      ã¨ï¼
+#    (a) åé
+å¸ã«ä¼´ããã­ã¥ã¡ã³ãï¼å©ç¨è
+ããã¥ã¢ã«ãªã©ï¼ã«ï¼ä¸è¨ã®è
+#        ä½æ¨©è¡¨ç¤ºï¼ãã®å©ç¨æ¡ä»¶ããã³ä¸è¨ã®ç¡ä¿è¨¼è¦å®ãæ²è¼ãããã¨ï¼
+#    (b) åé
+å¸ã®å½¢æ
+ãï¼å¥ã«å®ããæ¹æ³ã«ãã£ã¦ï¼TOPPERSãã­ã¸ã§ã¯ãã«
+#        å ±åãããã¨ï¼
+#  (4) æ¬ã½ããã¦ã§ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæ
+#      å®³ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ããå
+è²¬ãããã¨ï¼
+#      ã¾ãï¼æ¬ã½ããã¦ã§ã¢ã®ã¦ã¼ã¶ã¾ãã¯ã¨ã³ãã¦ã¼ã¶ããã®ãããªãç
+#      ç±ã«åºã¥ãè«æ±ãããï¼ä¸è¨èä½æ¨©è
+ããã³TOPPERSãã­ã¸ã§ã¯ãã
+#      å
+è²¬ãããã¨ï¼
+# 
+#  æ¬ã½ããã¦ã§ã¢ã¯ï¼ç¡ä¿è¨¼ã§æä¾ããã¦ãããã®ã§ããï¼ä¸è¨èä½æ¨©è
+ã
+#  ãã³TOPPERSãã­ã¸ã§ã¯ãã¯ï¼æ¬ã½ããã¦ã§ã¢ã«é¢ãã¦ï¼ç¹å®ã®ä½¿ç¨ç®ç
+#  ã«å¯¾ããé©åæ§ãå«ãã¦ï¼ãããªãä¿è¨¼ãè¡ããªãï¼ã¾ãï¼æ¬ã½ããã¦ã§
+#  ã¢ã®å©ç¨ã«ããç´æ¥çã¾ãã¯éæ¥çã«çãããããªãæå®³ã«é¢ãã¦ãï¼ã
+#  ã®è²¬ä»»ãè² ããªãï¼
+# 
+#  @(#) $Id$
+# 
+
+use Cwd;
+
+$cwd = getcwd();
+$cwd =~ s/^.*[\/\\]([^\/\\]+)$/$1/;
+$prefix = "./".$cwd;
+
+@file_list = ();
+%file_list = ();
+
+if ($#ARGV >= 0) {
+	$arg1 = $ARGV[0];
+	$arg1 =~ s/\.\///;
+}
+else {
+	$arg1 = "MANIFEST";
+}
+
+sub gen_path
+{
+	local($base, $path) = @_;
+
+	while ($path =~ /^..\/(.*)$/) {
+		$path = $1;
+		$base =~ s/(\/?)[^\/]*\/$/$1/;
+	}
+	return($base.$path);
+}
+
+sub read_file {
+	local($filename) = @_;
+	local($fh, $dirname);
+
+	if ($filename =~ /^(.*\/)[^\/]*$/) {
+		$dirname = $1;
+	}
+	else {
+		$dirname = "";
+	}
+
+	open($fh, $filename) || die "Cannot open $filename";
+	while ($line = <$fh>) {
+		chomp $line;
+		$line =~ s/\r$//;
+		$line =~ s/[ \t]*\#.*$//;
+		next if ($line =~ /^[ \t]*$/);
+
+		if ($line =~ /^E_PACKAGE[ \t]+(.*)$/) {
+			if ($package) {
+				die "Duplicated E_PACKAGE directive.";
+			}
+			else {
+				$package = $1;
+				$e_package = 1;
+			}
+		}
+		elsif ($line =~ /^PACKAGE[ \t]+(.*)$/) {
+			if ($package) {
+				if (!$e_package && $package != $1) {
+					die "Inconsistent PACKAGE directive.";
+				}
+			}
+			else {
+				$package = $1;
+			}
+		}
+		elsif ($line =~ /^VERSION[ \t]+(.*)$/) {
+			if ($version) {
+				if (!$e_package && $version != $1) {
+					die "Inconsistent VERSION directive.";
+				}
+			}
+			else {
+				$version = $1;
+				if ($version =~ /%date/) {
+					@current_time = localtime();
+					$vdate = sprintf("%04d%02d%02d", $current_time[5]+1900,
+										$current_time[4]+1, $current_time[3]);
+					$version =~ s/%date/$vdate/;
+				}
+			}
+		}
+		elsif ($line =~ /^INCLUDE[ \t]+(.*)$/) {
+			read_file(gen_path($dirname, $1));
+		}
+		else {
+			$filename = $prefix."/".$dirname.$line;
+			while ($filename =~ s|/[^/]+/\.\./|/|) {}
+			if ($file_list{$filename}) {
+				die "$filename is duplicated.";
+			}
+			else {
+				push(@file_list, $filename);
+				$file_list{$filename} = $filename;
+			}
+		}
+	}
+	close($fh);
+}
+
+read_file($arg1);
+unless ($package) {
+	die "PACKAGE/E_PACKAGE directive not found.";
+}
+unless ($version) {
+	die "VERSION directive not found.";
+}
+
+if (! -d "RELEASE") {
+	mkdir("RELEASE");
+}
+
+$archive_name = $package."-".$version.".tar.gz";
+$file_list = join(" ", @file_list);
+$command = "tar cvfz RELEASE/$archive_name -C .. $file_list\n";
+die if (system($command));
+print STDERR "== RELEASE/$archive_name is generated. ==\n";
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/.vscode/c_cpp_properties.json
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/.vscode/c_cpp_properties.json	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/.vscode/c_cpp_properties.json	(revision 453)
@@ -0,0 +1,34 @@
+{
+    "configurations": [
+        {
+            "name": "Sipeed Maix bit",
+            "includePath": [
+                "${workspaceFolder}/../asp_baseplatform/include",
+                "${workspaceFolder}/../asp_baseplatform/arch/gcc",
+                "${workspaceFolder}/../asp_baseplatform/arch/riscv_gcc",
+                "${workspaceFolder}/../asp_baseplatform/target/k210_gcc",
+                "${workspaceFolder}/../asp_baseplatform/OBJ/K210_GCC/DEMO",
+                "${workspaceFolder}/../azure_iot_sdk/c-utility/inc",
+                "${workspaceFolder}/../azure_iot_sdk/c-utility/pal/toppers",
+                "${workspaceFolder}/../azure_iot_sdk/iothub_client/inc",
+                "${workspaceFolder}/../azure_iot_sdk/iothub_client/inc/internal",
+                "${workspaceFolder}/../azure_iot_sdk/deps/parson",
+                "${workspaceFolder}/../azure_iot_sdk/umqtt/inc",
+                "${workspaceFolder}/../wolfssl-4.4.0/wolfssl",
+                "${workspaceFolder}/../wolfssl-4.4.0/wolfssl/wolfcrypt",
+                "${workspaceFolder}/../wolfssl-4.4.0",
+                "${workspaceFolder}/../zlib-1.2.11/src"
+            ],
+            "defines": [
+                "USE_WOLFSSL=1",
+                "get_time=azure_get_time"
+            ],
+            "windowsSdkVersion": "10.0.17763.0",
+            "compilerPath": "C:\\xpack-riscv-none-embed-gcc-8.3.0-1.2\\bin\\riscv-none-embed-gcc.exe",
+            "cStandard": "c11",
+            "cppStandard": "c++17",
+            "intelliSenseMode": "gcc-x64"
+        }
+    ],
+    "version": 4
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/.vscode/settings.json
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/.vscode/settings.json	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/.vscode/settings.json	(revision 453)
@@ -0,0 +1,17 @@
+// Place your settings in this file to overwrite default and user settings.
+{
+    "terminal.integrated.setLocaleVariables": true,
+    "terminal.integrated.shell.windows": "C:\\msys64\\usr\\bin\\bash.exe",
+    "terminal.integrated.shellArgs.windows": [
+        "--login",
+        "-i"
+    ],
+    "terminal.integrated.env.windows": {
+        "PATH": "C:\\xpack-riscv-none-embed-gcc-8.3.0-1.2\\bin",
+        "CHERE_INVOKING": "1",
+        "MSYS2_PATH_TYPE": "inherit",
+        "MSYSTEM": "MINGW64"
+    },
+    "C_Cpp.intelliSenseEngine": "Tag Parser",
+    "C_Cpp.default.intelliSenseMode": "gcc-x64"
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/.vscode/tasks.json
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/.vscode/tasks.json	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/.vscode/tasks.json	(revision 453)
@@ -0,0 +1,57 @@
+{
+    // See https://go.microsoft.com/fwlink/?LinkId=733558
+    // for the documentation about the tasks.json format
+    "version": "2.0.0",
+    "name": "make",
+    "type": "shell",
+    "problemMatcher": {
+        "owner": "cpp",
+        "fileLocation": [
+            "relative",
+            "${workspaceFolder}/Debug"
+        ],
+        "pattern": {
+            "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error|fatal error):\\s+(.*)$",
+            "file": 1,
+            "line": 2,
+            "column": 3,
+            "severity": 4,
+            "message": 5
+        }
+    },
+    "tasks": [
+        {
+            "label": "build azure_iot_sdk",
+            "args": [
+                "-j",
+                "all"
+            ],
+            "linux": {
+                "command": "make"
+            },
+            "osx": {
+                "command": "make"
+            },
+            "windows": {
+                "command": "make.exe"
+            },
+            "group": "build"
+        },
+        {
+            "label": "clean azure_iot_sdk",
+            "args": [
+                "clean"
+            ],
+            "linux": {
+                "command": "make"
+            },
+            "osx": {
+                "command": "make"
+            },
+            "windows": {
+                "command": "make.exe"
+            },
+            "group": "build"
+        }
+    ]
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/Makefile
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/Makefile	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/Makefile	(revision 453)
@@ -0,0 +1,307 @@
+# This file was automagically generated by mbed.org. For more information, 
+# see http://mbed.org/handbook/Exporting-to-GCC-ARM-Embedded
+
+###############################################################################
+# Boiler-plate
+
+# cross-platform directory manipulation
+ifeq ($(shell echo $$OS),$$OS)
+    MAKEDIR = if not exist "$(1)" mkdir "$(1)"
+    RM = rmdir /S /Q "$(1)"
+else
+    MAKEDIR = '$(SHELL)' -c "mkdir -p \"$(1)\""
+    RM = '$(SHELL)' -c "rm -rf \"$(1)\""
+endif
+
+OBJDIR := Debug
+# Move to the build directory
+ifeq (,$(filter $(OBJDIR),$(notdir $(CURDIR))))
+.SUFFIXES:
+mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
+MAKETARGET = '$(MAKE)' --no-print-directory -C $(OBJDIR) -f '$(mkfile_path)' \
+		'SRCDIR=$(CURDIR)' $(MAKECMDGOALS)
+.PHONY: $(OBJDIR) clean
+all:
+	+@$(call MAKEDIR,$(OBJDIR))
+	+@$(MAKETARGET)
+$(OBJDIR): all
+Makefile : ;
+% :: $(OBJDIR) ; :
+clean :
+	$(call RM,$(OBJDIR))
+
+else
+
+# trick rules into thinking we are in the root, when we are in the bulid dir
+VPATH = ../../azure_iot_sdk
+
+# Boiler-plate
+###############################################################################
+# Project settings
+
+PROJECT := azure_iot_sdk
+
+
+# Project settings
+###############################################################################
+# Objects and Paths
+
+OBJECTS += c-utility/adapters/agenttime_mbed.o
+OBJECTS += c-utility/adapters/httpapi_compact.o
+OBJECTS += c-utility/adapters/lock_toppers.o
+OBJECTS += c-utility/adapters/platform_toppers.o
+OBJECTS += c-utility/adapters/socketio_esp_at.o
+OBJECTS += c-utility/adapters/threadapi_toppers.o
+OBJECTS += c-utility/adapters/tickcounter_toppers.o
+OBJECTS += c-utility/adapters/tlsio_esp_at.o
+OBJECTS += c-utility/adapters/tlsio_wolfssl.o
+OBJECTS += c-utility/adapters/uniqueid_stub.o
+OBJECTS += c-utility/src/azure_base32.o
+OBJECTS += c-utility/src/azure_base64.o
+OBJECTS += c-utility/src/buffer.o
+OBJECTS += c-utility/src/connection_string_parser.o
+OBJECTS += c-utility/src/consolelogger.o
+OBJECTS += c-utility/src/constbuffer.o
+OBJECTS += c-utility/src/constmap.o
+OBJECTS += c-utility/src/crt_abstractions.o
+#OBJECTS += c-utility/src/dns_resolver_sync.o
+OBJECTS += c-utility/src/doublylinkedlist.o
+OBJECTS += c-utility/src/gb_rand.o
+OBJECTS += c-utility/src/gb_stdio.o
+OBJECTS += c-utility/src/gb_time.o
+OBJECTS += c-utility/src/gballoc.o
+OBJECTS += c-utility/src/hmac.o
+OBJECTS += c-utility/src/hmacsha256.o
+OBJECTS += c-utility/src/http_proxy_io.o
+OBJECTS += c-utility/src/httpapiex.o
+OBJECTS += c-utility/src/httpapiexsas.o
+OBJECTS += c-utility/src/httpheaders.o
+OBJECTS += c-utility/src/map.o
+OBJECTS += c-utility/src/optionhandler.o
+OBJECTS += c-utility/src/sastoken.o
+OBJECTS += c-utility/src/sha1.o
+OBJECTS += c-utility/src/sha224.o
+OBJECTS += c-utility/src/sha384-512.o
+OBJECTS += c-utility/src/singlylinkedlist.o
+OBJECTS += c-utility/src/string_token.o
+OBJECTS += c-utility/src/string_tokenizer.o
+OBJECTS += c-utility/src/strings.o
+OBJECTS += c-utility/src/urlencode.o
+OBJECTS += c-utility/src/usha.o
+OBJECTS += c-utility/src/utf8_checker.o
+OBJECTS += c-utility/src/uuid.o
+OBJECTS += c-utility/src/uws_client.o
+OBJECTS += c-utility/src/uws_frame_encoder.o
+OBJECTS += c-utility/src/vector.o
+OBJECTS += c-utility/src/wsio.o
+OBJECTS += c-utility/src/xio.o
+OBJECTS += c-utility/src/xlogging.o
+OBJECTS += certs/certs.o
+OBJECTS += deps/parson/parson.o
+OBJECTS += iothub_client/src/blob.o
+OBJECTS += iothub_client/src/iothub.o
+OBJECTS += iothub_client/src/iothub_client.o
+OBJECTS += iothub_client/src/iothub_client_authorization.o
+OBJECTS += iothub_client/src/iothub_client_core.o
+OBJECTS += iothub_client/src/iothub_client_core_ll.o
+OBJECTS += iothub_client/src/iothub_client_diagnostic.o
+OBJECTS += iothub_client/src/iothub_client_ll.o
+OBJECTS += iothub_client/src/iothub_client_ll_uploadtoblob.o
+OBJECTS += iothub_client/src/iothub_client_retry_control.o
+OBJECTS += iothub_client/src/iothub_device_client_ll.o
+OBJECTS += iothub_client/src/iothub_message.o
+OBJECTS += iothub_client/src/iothub_transport_ll_private.o
+OBJECTS += iothub_client/src/iothubtransport.o
+OBJECTS += iothub_client/src/iothubtransport_mqtt_common.o
+OBJECTS += iothub_client/src/iothubtransporthttp.o
+OBJECTS += iothub_client/src/iothubtransportmqtt.o
+OBJECTS += iothub_client/src/iothubtransportmqtt_websockets.o
+OBJECTS += iothub_client/src/version.o
+OBJECTS += provisioning_client/adapters/hsm_client_data.o
+OBJECTS += provisioning_client/adapters/hsm_client_key.o
+OBJECTS += provisioning_client/src/iothub_auth_client.o
+OBJECTS += provisioning_client/src/iothub_security_factory.o
+OBJECTS += provisioning_client/src/prov_auth_client.o
+OBJECTS += provisioning_client/src/prov_device_client.o
+OBJECTS += provisioning_client/src/prov_device_ll_client.o
+OBJECTS += provisioning_client/src/prov_security_factory.o
+OBJECTS += provisioning_client/src/prov_transport_http_client.o
+OBJECTS += provisioning_client/src/prov_transport_mqtt_client.o
+OBJECTS += provisioning_client/src/prov_transport_mqtt_common.o
+OBJECTS += provisioning_client/src/prov_transport_mqtt_ws_client.o
+OBJECTS += serializer/src/methodreturn.o
+OBJECTS += serializer/src/multitree.o
+OBJECTS += serializer/src/schema.o
+OBJECTS += serializer/src/schemalib.o
+OBJECTS += serializer/src/schemaserializer.o
+OBJECTS += serializer/src/datamarshaller.o
+OBJECTS += serializer/src/datapublisher.o
+OBJECTS += serializer/src/dataserializer.o
+OBJECTS += serializer/src/iotdevice.o
+OBJECTS += serializer/src/jsondecoder.o
+OBJECTS += serializer/src/jsonencoder.o
+OBJECTS += serializer/src/agenttypesystem.o
+OBJECTS += serializer/src/codefirst.o
+OBJECTS += serializer/src/commanddecoder.o
+OBJECTS += uhttp/src/uhttp.o
+OBJECTS += umqtt/src/mqtt_client.o
+OBJECTS += umqtt/src/mqtt_codec.o
+OBJECTS += umqtt/src/mqtt_message.o
+
+INCLUDE_PATHS += -I../../asp_baseplatform
+INCLUDE_PATHS += -I../../asp_baseplatform/include
+INCLUDE_PATHS += -I../../asp_baseplatform/arch
+INCLUDE_PATHS += -I../../asp_baseplatform/arch/riscv_gcc
+INCLUDE_PATHS += -I../../asp_baseplatform/target/k210_gcc
+INCLUDE_PATHS += -I../../asp_baseplatform/OBJ/K210_GCC/DEMO
+INCLUDE_PATHS += -I../../asp_baseplatform/monitor
+INCLUDE_PATHS += -I../../asp_baseplatform/files
+INCLUDE_PATHS += -I../../azure_iot_sdk/c-utility/inc
+INCLUDE_PATHS += -I../../azure_iot_sdk/c-utility/pal/toppers
+INCLUDE_PATHS += -I../../azure_iot_sdk/iothub_client/inc
+INCLUDE_PATHS += -I../../azure_iot_sdk/iothub_client/inc/internal
+INCLUDE_PATHS += -I../../azure_iot_sdk/provisioning_client/adapters
+INCLUDE_PATHS += -I../../azure_iot_sdk/provisioning_client/inc
+INCLUDE_PATHS += -I../../azure_iot_sdk/provisioning_client/inc/azure_prov_client/internal
+INCLUDE_PATHS += -I../../azure_iot_sdk/deps/parson
+INCLUDE_PATHS += -I../../azure_iot_sdk/deps/azure-macro-utils-c/inc
+INCLUDE_PATHS += -I../../azure_iot_sdk/deps/umock-c/inc
+INCLUDE_PATHS += -I../../azure_iot_sdk/serializer/inc
+INCLUDE_PATHS += -I../../azure_iot_sdk/uhttp/inc
+INCLUDE_PATHS += -I../../azure_iot_sdk/umqtt/inc
+INCLUDE_PATHS += -I../../wolfssl-4.4.0/wolfssl
+INCLUDE_PATHS += -I../../wolfssl-4.4.0/wolfssl/wolfcrypt
+INCLUDE_PATHS += -I../../wolfssl-4.4.0
+INCLUDE_PATHS += -I../../zlib-1.2.11/src
+
+# Objects and Paths
+###############################################################################
+# Tools and Flags
+
+AS      = riscv-none-embed-gcc
+CC      = riscv-none-embed-gcc
+CPP     = riscv-none-embed-g++
+AR      = riscv-none-embed-ar
+RANLIB  = riscv-none-embed-ranlib
+
+
+C_FLAGS += -std=gnu11
+C_FLAGS += -march=rv64imafdc
+C_FLAGS += -mabi=lp64d
+C_FLAGS += -mcmodel=medany
+C_FLAGS += -O2
+C_FLAGS += -fmessage-length=0
+C_FLAGS += -fsigned-char
+C_FLAGS += -ffunction-sections
+C_FLAGS += -fdata-sections
+C_FLAGS += -Wall
+C_FLAGS += -Wextra
+C_FLAGS += -Wno-unused-parameter
+C_FLAGS += -Wno-missing-field-initializers
+C_FLAGS += -Wnull-dereference
+
+C_FLAGS += -Wno-unused-variable
+C_FLAGS += -Wno-unused-function
+
+C_FLAGS += -g3
+C_FLAGS += -Wstack-usage=256
+
+C_FLAGS += -DWOLFSSL_USER_SETTINGS
+C_FLAGS += -DCYASSL_USER_SETTINGS
+C_FLAGS += -DUSE_WOLFSSL=1
+C_FLAGS += -DHSM_TYPE_SYMM_KEY
+C_FLAGS += -DUSE_PROV_MODULE
+C_FLAGS += -Dget_time=azure_get_time
+
+CXX_FLAGS += -std=gnu++11
+CXX_FLAGS += -march=rv64imafdc
+CXX_FLAGS += -mabi=lp64d
+CXX_FLAGS += -mcmodel=medany
+CXX_FLAGS += -O2
+CXX_FLAGS += -fmessage-length=0
+CXX_FLAGS += -fsigned-char
+CXX_FLAGS += -ffunction-sections
+CXX_FLAGS += -fdata-sections
+CXX_FLAGS += -Wall
+CXX_FLAGS += -Wextra
+CXX_FLAGS += -Wno-unused-parameter
+CXX_FLAGS += -Wno-missing-field-initializers
+CXX_FLAGS += -Wnull-dereference
+
+CXX_FLAGS += -g3
+CXX_FLAGS += -Wstack-usage=256
+
+CXX_FLAGS += -DWOLFSSL_USER_SETTINGS
+CXX_FLAGS += -DCYASSL_USER_SETTINGS
+CXX_FLAGS += -DUSE_WOLFSSL=1
+CXX_FLAGS += -DHSM_TYPE_SYMM_KEY
+CXX_FLAGS += -DUSE_PROV_MODULE
+CXX_FLAGS += -Dget_time=azure_get_time
+
+ASM_FLAGS += -x
+ASM_FLAGS += assembler-with-cpp
+ASM_FLAGS += -march=rv64imafdc
+ASM_FLAGS += -mabi=lp64d
+ASM_FLAGS += -mcmodel=medany
+ASM_FLAGS += -O2
+ASM_FLAGS += -fmessage-length=0
+ASM_FLAGS += -fsigned-char
+ASM_FLAGS += -ffunction-sections
+ASM_FLAGS += -fdata-sections
+ASM_FLAGS += -Wall
+ASM_FLAGS += -Wextra
+ASM_FLAGS += -Wno-unused-parameter
+ASM_FLAGS += -Wno-missing-field-initializers
+ASM_FLAGS += -Wnull-dereference
+ASM_FLAGS += -g3
+ASM_FLAGS += -Wstack-usage=256
+
+
+# Tools and Flags
+###############################################################################
+# Rules
+
+.PHONY: all lst size
+
+
+all: lib$(PROJECT).a
+
+
+.s.o:
+	+@$(call MAKEDIR,$(dir $@))
+	+@echo "Assemble: $(notdir $<)"
+	@$(AS) -c $(ASM_FLAGS) -o $@ $<
+
+
+.S.o:
+	+@$(call MAKEDIR,$(dir $@))
+	+@echo "Assemble: $(notdir $<)"
+	@$(AS) -c $(ASM_FLAGS) -o $@ $<
+
+.c.o:
+	+@$(call MAKEDIR,$(dir $@))
+	+@echo "Compile: $(notdir $<)"
+	@$(CC) $(C_FLAGS) $(INCLUDE_PATHS) -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -c -o "$@" "$<"
+
+.cpp.o:
+	+@$(call MAKEDIR,$(dir $@))
+	+@echo "Compile: $(notdir $<)"
+	@$(CPP) $(CXX_FLAGS) $(INCLUDE_PATHS) -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -c -o "$@" "$<"
+
+lib$(PROJECT).a: $(OBJECTS)
+	rm -f lib$(PROJECT).a
+	$(AR) -rcs lib$(PROJECT).a $(OBJECTS)
+	$(RANLIB) lib$(PROJECT).a
+
+
+
+# Rules
+###############################################################################
+# Dependencies
+
+DEPS = $(OBJECTS:.o=.d) $(SYS_OBJECTS:.o=.d)
+-include $(DEPS)
+endif
+
+# Dependencies
+###############################################################################
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/agenttime_mbed.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/agenttime_mbed.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/agenttime_mbed.c	(revision 453)
@@ -0,0 +1,28 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include "azure_c_shared_utility/agenttime.h"
+
+// mbed version of gmtime() returns NULL.
+// system RTC should be set to UTC as its localtime 
+
+time_t get_time(time_t* currentTime)
+{
+    return time(currentTime);
+}
+
+double get_difftime(time_t stopTime, time_t startTime)
+{
+    return difftime(stopTime, startTime);
+}
+
+
+struct tm* get_gmtime(time_t* currentTime)
+{
+    return localtime(currentTime);
+}
+
+char* get_ctime(time_t* timeToGet)
+{
+    return ctime(timeToGet);
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/httpapi_compact.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/httpapi_compact.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/httpapi_compact.c	(revision 453)
@@ -0,0 +1,1573 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <limits.h>
+
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/httpheaders.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/xio.h"
+#include "azure_c_shared_utility/platform.h"
+#include "azure_c_shared_utility/tlsio.h"
+#include "azure_c_shared_utility/threadapi.h"
+#include "azure_c_shared_utility/shared_util_options.h"
+#include "azure_c_shared_utility/http_proxy_io.h"
+
+#ifdef _MSC_VER
+#define snprintf _snprintf
+#endif
+
+/*Codes_SRS_HTTPAPI_COMPACT_21_001: [ The httpapi_compact shall implement the methods defined by the httpapi.h. ]*/
+/*Codes_SRS_HTTPAPI_COMPACT_21_002: [ The httpapi_compact shall support the http requests. ]*/
+/*Codes_SRS_HTTPAPI_COMPACT_21_003: [ The httpapi_compact shall return error codes defined by HTTPAPI_RESULT. ]*/
+#include "azure_c_shared_utility/httpapi.h"
+
+#define MAX_HOSTNAME     64
+#define TEMP_BUFFER_SIZE 1024
+
+/*Codes_SRS_HTTPAPI_COMPACT_21_077: [ The HTTPAPI_ExecuteRequest shall wait, at least, 10 seconds for the SSL open process. ]*/
+#define MAX_OPEN_RETRY   100
+/*Codes_SRS_HTTPAPI_COMPACT_21_084: [ The HTTPAPI_CloseConnection shall wait, at least, 10 seconds for the SSL close process. ]*/
+#define MAX_CLOSE_RETRY   100
+/*Codes_SRS_HTTPAPI_COMPACT_21_079: [ The HTTPAPI_ExecuteRequest shall wait, at least, 20 seconds to send a buffer using the SSL connection. ]*/
+#define MAX_SEND_RETRY   200
+/*Codes_SRS_HTTPAPI_COMPACT_21_081: [ The HTTPAPI_ExecuteRequest shall try to read the message with the response up to 20 seconds. ]*/
+#define MAX_RECEIVE_RETRY   200
+/*Codes_SRS_HTTPAPI_COMPACT_21_083: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
+#define RETRY_INTERVAL_IN_MICROSECONDS  100
+
+MU_DEFINE_ENUM_STRINGS(HTTPAPI_RESULT, HTTPAPI_RESULT_VALUES)
+
+typedef struct HTTP_HANDLE_DATA_TAG
+{
+    char*           hostName;
+    char*           certificate;
+    char*           x509ClientCertificate;
+    char*           x509ClientPrivateKey;
+    const char*     proxy_host;
+    int             proxy_port;
+    const char*     proxy_username;
+    const char*     proxy_password;
+    XIO_HANDLE      xio_handle;
+    size_t          received_bytes_count;
+    unsigned char*  received_bytes;
+    unsigned int    is_io_error : 1;
+    unsigned int    is_connected : 1;
+    unsigned int    send_completed : 1;
+} HTTP_HANDLE_DATA;
+
+/*the following function does the same as sscanf(pos2, "%d", &sec)*/
+/*this function only exists because some of platforms do not have sscanf. */
+static int ParseStringToDecimal(const char *src, int* dst)
+{
+    int result;
+    char* next;
+    long num = strtol(src, &next, 0);
+    if (src == next || num < INT_MIN || num > INT_MAX)
+    {
+        result = EOF;
+    }
+    else
+    {
+        result = 1;
+    }
+    if (num < INT_MIN) num = INT_MIN;
+    if (num > INT_MAX) num = INT_MAX;
+    *dst = (int)num;
+    return result;
+}
+
+/*the following function does the same as sscanf(pos2, "%x", &sec)*/
+/*this function only exists because some of platforms do not have sscanf. This is not a full implementation; it only works with well-defined x numbers. */
+#define HEXA_DIGIT_VAL(c)         (((c>='0') && (c<='9')) ? (c-'0') : ((c>='a') && (c<='f')) ? (c-'a'+10) : ((c>='A') && (c<='F')) ? (c-'A'+10) : -1)
+static int ParseStringToHexadecimal(const char *src, size_t* dst)
+{
+    int result;
+    int digitVal;
+    if (src == NULL)
+    {
+        result = EOF;
+    }
+    else if (HEXA_DIGIT_VAL(*src) == -1)
+    {
+        result = EOF;
+    }
+    else
+    {
+        (*dst) = 0;
+        while ((digitVal = HEXA_DIGIT_VAL(*src)) != -1)
+        {
+            (*dst) *= 0x10;
+            (*dst) += (size_t)digitVal;
+            src++;
+        }
+        result = 1;
+    }
+    return result;
+}
+
+/*the following function does the same as sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &ret) */
+/*this function only exists because some of platforms do not have sscanf. This is not a full implementation; it only works with well-defined HTTP response. */
+static int  ParseHttpResponse(const char* src, int* dst)
+{
+    int result;
+    static const char HTTPPrefix[] = "HTTP/";
+    bool fail;
+    const char* runPrefix;
+
+    if ((src == NULL) || (dst == NULL))
+    {
+        result = EOF;
+    }
+    else
+    {
+        fail = false;
+        runPrefix = HTTPPrefix;
+
+        while((*runPrefix) != '\0')
+        {
+            if ((*runPrefix) != (*src))
+            {
+                fail = true;
+                break;
+            }
+            src++;
+            runPrefix++;
+        }
+
+        if (!fail)
+        {
+            while ((*src) != '.')
+            {
+                if ((*src) == '\0')
+                {
+                    fail = true;
+                    break;
+                }
+                src++;
+            }
+        }
+
+        if (!fail)
+        {
+            while ((*src) != ' ')
+            {
+                if ((*src) == '\0')
+                {
+                    fail = true;
+                    break;
+                }
+                src++;
+            }
+        }
+
+        if (fail)
+        {
+            result = EOF;
+        }
+        else
+        {
+            result = ParseStringToDecimal(src, dst);
+        }
+    }
+
+    return result;
+}
+
+HTTPAPI_RESULT HTTPAPI_Init(void)
+{
+/*Codes_SRS_HTTPAPI_COMPACT_21_004: [ The HTTPAPI_Init shall allocate all memory to control the http protocol. ]*/
+/*Codes_SRS_HTTPAPI_COMPACT_21_007: [ If there is not enough memory to control the http protocol, the HTTPAPI_Init shall return HTTPAPI_ALLOC_FAILED. ]*/
+/**
+ * No memory is necessary.
+ */
+
+ /*Codes_SRS_HTTPAPI_COMPACT_21_006: [ If HTTPAPI_Init succeed allocating all the needed memory, it shall return HTTPAPI_OK. ]*/
+return HTTPAPI_OK;
+}
+
+void HTTPAPI_Deinit(void)
+{
+    /*Codes_SRS_HTTPAPI_COMPACT_21_009: [ The HTTPAPI_Init shall release all memory allocated by the httpapi_compact. ]*/
+    /**
+    * No memory was necessary.
+    */
+}
+
+/*Codes_SRS_HTTPAPI_COMPACT_21_011: [ The HTTPAPI_CreateConnection shall create an http connection to the host specified by the hostName parameter. ]*/
+HTTP_HANDLE HTTPAPI_CreateConnection(const char* hostName)
+{
+    HTTP_HANDLE_DATA* http_instance;
+
+    if (hostName == NULL)
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_014: [ If the hostName is NULL, the HTTPAPI_CreateConnection shall return NULL as the handle. ]*/
+        LogError("Invalid host name. Null hostName parameter.");
+        http_instance = NULL;
+    }
+    else if (*hostName == '\0')
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_015: [ If the hostName is empty, the HTTPAPI_CreateConnection shall return NULL as the handle. ]*/
+        LogError("Invalid host name. Empty string.");
+        http_instance = NULL;
+    }
+    else
+    {
+        http_instance = (HTTP_HANDLE_DATA*)malloc(sizeof(HTTP_HANDLE_DATA));
+        /*Codes_SRS_HTTPAPI_COMPACT_21_013: [ If there is not enough memory to control the http connection, the HTTPAPI_CreateConnection shall return NULL as the handle. ]*/
+        if (http_instance == NULL)
+        {
+            LogError("There is no memory to control the http connection");
+        }
+        else if(mallocAndStrcpy_s((char**)&(http_instance->hostName), hostName) != 0)
+        {
+            LogError("failure allocate host name");
+            free(http_instance);
+            http_instance = NULL;
+        }
+        else
+        {
+            http_instance->xio_handle = NULL;
+            http_instance->is_connected = 0;
+            http_instance->is_io_error = 0;
+            http_instance->received_bytes_count = 0;
+            http_instance->received_bytes = NULL;
+            http_instance->certificate = NULL;
+            http_instance->x509ClientCertificate = NULL;
+            http_instance->x509ClientPrivateKey = NULL;
+            http_instance->proxy_host = NULL;
+            http_instance->proxy_port = 0;
+            http_instance->proxy_username = NULL;
+            http_instance->proxy_password = NULL;
+        }
+    }
+
+    /*Codes_SRS_HTTPAPI_COMPACT_21_012: [ The HTTPAPI_CreateConnection shall return a non-NULL handle on success. ]*/
+    return (HTTP_HANDLE)http_instance;
+}
+
+static void on_io_close_complete(void* context)
+{
+    HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)context;
+
+    if (http_instance != NULL)
+    {
+        http_instance->is_connected = 0;
+    }
+}
+
+void HTTPAPI_CloseConnection(HTTP_HANDLE handle)
+{
+    HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)handle;
+
+    /*Codes_SRS_HTTPAPI_COMPACT_21_020: [ If the connection handle is NULL, the HTTPAPI_CloseConnection shall not do anything. ]*/
+    if (http_instance != NULL)
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_019: [ If there is no previous connection, the HTTPAPI_CloseConnection shall not do anything. ]*/
+        if (http_instance->xio_handle != NULL)
+        {
+            http_instance->is_io_error = 0;
+            /*Codes_SRS_HTTPAPI_COMPACT_21_017: [ The HTTPAPI_CloseConnection shall close the connection previously created in HTTPAPI_ExecuteRequest. ]*/
+            if (xio_close(http_instance->xio_handle, on_io_close_complete, http_instance) != 0)
+            {
+                LogError("The SSL got error closing the connection");
+                /*Codes_SRS_HTTPAPI_COMPACT_21_087: [ If the xio return anything different than 0, the HTTPAPI_CloseConnection shall destroy the connection anyway. ]*/
+                http_instance->is_connected = 0;
+            }
+            else
+            {
+                /*Codes_SRS_HTTPAPI_COMPACT_21_084: [ The HTTPAPI_CloseConnection shall wait, at least, 10 seconds for the SSL close process. ]*/
+                int countRetry = MAX_CLOSE_RETRY;
+                while (http_instance->is_connected == 1)
+                {
+                    xio_dowork(http_instance->xio_handle);
+                    if ((countRetry--) < 0)
+                    {
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_085: [ If the HTTPAPI_CloseConnection retries 10 seconds to close the connection without success, it shall destroy the connection anyway. ]*/
+                        LogError("Close timeout. The SSL didn't close the connection");
+                        http_instance->is_connected = 0;
+                    }
+                    else if (http_instance->is_io_error == 1)
+                    {
+                        LogError("The SSL got error closing the connection");
+                        http_instance->is_connected = 0;
+                    }
+                    else if (http_instance->is_connected == 1)
+                    {
+                        LogInfo("Waiting for TLS close connection");
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_086: [ The HTTPAPI_CloseConnection shall wait, at least, 100 milliseconds between retries. ]*/
+                        ThreadAPI_Sleep(RETRY_INTERVAL_IN_MICROSECONDS);
+                    }
+                }
+            }
+            /*Codes_SRS_HTTPAPI_COMPACT_21_076: [ After close the connection, The HTTPAPI_CloseConnection shall destroy the connection previously created in HTTPAPI_CreateConnection. ]*/
+            xio_destroy(http_instance->xio_handle);
+        }
+
+        if (http_instance->hostName != NULL)
+        {
+            free((void*)http_instance->hostName);
+        }
+
+#ifndef DO_NOT_COPY_TRUSTED_CERTS_STRING
+        /*Codes_SRS_HTTPAPI_COMPACT_21_018: [ If there is a certificate associated to this connection, the HTTPAPI_CloseConnection shall free all allocated memory for the certificate. ]*/
+        if (http_instance->certificate)
+        {
+            free(http_instance->certificate);
+        }
+#endif
+
+        /*Codes_SRS_HTTPAPI_COMPACT_06_001: [ If there is a x509 client certificate associated to this connection, the HTTAPI_CloseConnection shall free all allocated memory for the certificate. ]*/
+        if (http_instance->x509ClientCertificate)
+        {
+            free(http_instance->x509ClientCertificate);
+        }
+
+        /*Codes_SRS_HTTPAPI_COMPACT_06_002: [ If there is a x509 client private key associated to this connection, then HTTP_CloseConnection shall free all the allocated memory for the private key. ]*/
+        if (http_instance->x509ClientPrivateKey)
+        {
+            free(http_instance->x509ClientPrivateKey);
+        }
+
+        if (http_instance->proxy_host != NULL)
+        {
+            free((void*)http_instance->proxy_host);
+        }
+        if (http_instance->proxy_username != NULL)
+        {
+            free((void*)http_instance->proxy_username);
+        }
+        if (http_instance->proxy_password != NULL)
+        {
+            free((void*)http_instance->proxy_password);
+        }
+
+        free(http_instance);
+    }
+}
+
+static void on_io_open_complete(void* context, IO_OPEN_RESULT open_result)
+{
+    HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)context;
+
+    if (http_instance != NULL)
+    {
+        if (open_result == IO_OPEN_OK)
+        {
+            http_instance->is_connected = 1;
+            http_instance->is_io_error = 0;
+        }
+        else
+        {
+            http_instance->is_io_error = 1;
+        }
+    }
+}
+
+static void on_send_complete(void* context, IO_SEND_RESULT send_result)
+{
+    HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)context;
+
+    if (http_instance != NULL)
+    {
+        if (send_result == IO_SEND_OK)
+        {
+            http_instance->send_completed = 1;
+            http_instance->is_io_error = 0;
+        }
+        else
+        {
+            http_instance->is_io_error = 1;
+        }
+    }
+}
+
+#define TOLOWER(c) (((c>='A') && (c<='Z'))?c-'A'+'a':c)
+static int InternStrnicmp(const char* s1, const char* s2, size_t n)
+{
+    int result;
+
+    if (s1 == NULL) result = -1;
+    else if (s2 == NULL) result = 1;
+    else
+    {
+        result = 0;
+
+        while(n-- && result == 0)
+        {
+            if (*s1 == 0) result = -1;
+            else if (*s2 == 0) result = 1;
+            else
+            {
+
+                result = TOLOWER(*s1) - TOLOWER(*s2);
+                ++s1;
+                ++s2;
+            }
+        }
+    }
+
+    return result;
+}
+
+static void on_bytes_received(void* context, const unsigned char* buffer, size_t size)
+{
+    unsigned char* new_received_bytes;
+    HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)context;
+
+    if (http_instance != NULL)
+    {
+
+        if (buffer == NULL)
+        {
+            http_instance->is_io_error = 1;
+            LogError("NULL pointer error");
+        }
+        else
+        {
+            /* Here we got some bytes so we'll buffer them so the receive functions can consumer it */
+            new_received_bytes = (unsigned char*)realloc(http_instance->received_bytes, http_instance->received_bytes_count + size);
+            if (new_received_bytes == NULL)
+            {
+                http_instance->is_io_error = 1;
+                LogError("Error allocating memory for received data");
+            }
+            else
+            {
+                http_instance->received_bytes = new_received_bytes;
+                if (memcpy(http_instance->received_bytes + http_instance->received_bytes_count, buffer, size) == NULL)
+                {
+                    http_instance->is_io_error = 1;
+                    LogError("Error copping received data to the HTTP bufffer");
+                }
+                else
+                {
+                    http_instance->received_bytes_count += size;
+                }
+            }
+        }
+    }
+}
+
+static void on_io_error(void* context)
+{
+    HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)context;
+    if (http_instance != NULL)
+    {
+        http_instance->is_io_error = 1;
+        LogError("Error signalled by underlying IO");
+    }
+}
+
+static int conn_receive(HTTP_HANDLE_DATA* http_instance, char* buffer, int count)
+{
+    int result;
+
+    if ((http_instance == NULL) || (buffer == NULL) || (count < 0))
+    {
+        LogError("conn_receive: %s", ((http_instance == NULL) ? "Invalid HTTP instance" : "Invalid HTTP buffer"));
+        result = -1;
+    }
+    else
+    {
+        result = 0;
+        while (result < count)
+        {
+            xio_dowork(http_instance->xio_handle);
+
+            /* if any error was detected while receiving then simply break and report it */
+            if (http_instance->is_io_error != 0)
+            {
+                LogError("xio reported error on dowork");
+                result = -1;
+                break;
+            }
+
+            if (http_instance->received_bytes_count >= (size_t)count)
+            {
+                /* Consuming bytes from the receive buffer */
+                (void)memcpy(buffer, http_instance->received_bytes, count);
+                (void)memmove(http_instance->received_bytes, http_instance->received_bytes + count, http_instance->received_bytes_count - count);
+                http_instance->received_bytes_count -= count;
+
+                /* we're not reallocating at each consumption so that we don't trash due to byte by byte consumption */
+                if (http_instance->received_bytes_count == 0)
+                {
+                    free(http_instance->received_bytes);
+                    http_instance->received_bytes = NULL;
+                }
+
+                result = count;
+                break;
+            }
+
+            /*Codes_SRS_HTTPAPI_COMPACT_21_083: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
+            ThreadAPI_Sleep(RETRY_INTERVAL_IN_MICROSECONDS);
+        }
+    }
+
+    return result;
+}
+
+static void conn_receive_discard_buffer(HTTP_HANDLE_DATA* http_instance)
+{
+    if (http_instance != NULL)
+    {
+        if (http_instance->received_bytes != NULL)
+        {
+            free(http_instance->received_bytes);
+            http_instance->received_bytes = NULL;
+        }
+        http_instance->received_bytes_count = 0;
+    }
+}
+
+static int readLine(HTTP_HANDLE_DATA* http_instance, char* buf, const size_t maxBufSize)
+{
+    int resultLineSize;
+
+    if ((http_instance == NULL) || (buf == NULL) || (maxBufSize == 0))
+    {
+        LogError("%s", ((http_instance == NULL) ? "Invalid HTTP instance" : "Invalid HTTP buffer"));
+        resultLineSize = -1;
+    }
+    else
+    {
+        char* destByte = buf;
+        /*Codes_SRS_HTTPAPI_COMPACT_21_081: [ The HTTPAPI_ExecuteRequest shall try to read the message with the response up to 20 seconds. ]*/
+        int countRetry = MAX_RECEIVE_RETRY;
+        bool endOfSearch = false;
+        resultLineSize = -1;
+        while (!endOfSearch)
+        {
+            xio_dowork(http_instance->xio_handle);
+
+            /* if any error was detected while receiving then simply break and report it */
+            if (http_instance->is_io_error != 0)
+            {
+                LogError("xio reported error on dowork");
+                endOfSearch = true;
+            }
+            else
+            {
+                unsigned char* receivedByte = http_instance->received_bytes;
+                while (receivedByte < (http_instance->received_bytes + http_instance->received_bytes_count))
+                {
+                    if ((*receivedByte) != '\r')
+                    {
+                        (*destByte) = (*receivedByte);
+                        destByte++;
+                        receivedByte++;
+
+                        if (destByte >= (buf + maxBufSize - 1))
+                        {
+                            LogError("Received message is bigger than the http buffer");
+                            receivedByte = http_instance->received_bytes + http_instance->received_bytes_count;
+                            endOfSearch = true;
+                            break;
+                        }
+                    }
+                    else
+                    {
+                        receivedByte++;
+                        if ((receivedByte < (http_instance->received_bytes + http_instance->received_bytes_count)) && ((*receivedByte) == '\n'))
+                        {
+                            receivedByte++;
+                        }
+                        (*destByte) = '\0';
+                        resultLineSize = (int)(destByte - buf);
+                        endOfSearch = true;
+                        break;
+                    }
+                }
+
+                http_instance->received_bytes_count -= (receivedByte - http_instance->received_bytes);
+                if (http_instance->received_bytes_count != 0)
+                {
+                    (void)memmove(http_instance->received_bytes, receivedByte, http_instance->received_bytes_count);
+                }
+                else
+                {
+                    conn_receive_discard_buffer(http_instance);
+                }
+            }
+
+            if (!endOfSearch)
+            {
+                if ((countRetry--) > 0)
+                {
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_083: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
+                    ThreadAPI_Sleep(RETRY_INTERVAL_IN_MICROSECONDS);
+                }
+                else
+                {
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
+                    LogError("Receive timeout. The HTTP request is incomplete");
+                    endOfSearch = true;
+                }
+            }
+        }
+    }
+
+    return resultLineSize;
+}
+
+static int readChunk(HTTP_HANDLE_DATA* http_instance, char* buf, size_t size)
+{
+    int cur, offset;
+
+    // read content with specified length, even if it is received
+    // only in chunks due to fragmentation in the networking layer.
+    // returns -1 in case of error.
+    offset = 0;
+    while (size > (size_t)0)
+    {
+        cur = conn_receive(http_instance, buf + offset, (int)size);
+
+        // end of stream reached
+        if (cur == 0)
+        {
+            break;
+        }
+
+        // read cur bytes (might be less than requested)
+        size -= (size_t)cur;
+        offset += cur;
+    }
+
+    return offset;
+}
+
+static int skipN(HTTP_HANDLE_DATA* http_instance, size_t n)
+{
+    // read and abandon response content with specified length
+    // returns -1 in case of error.
+
+    int result;
+
+    if (http_instance == NULL)
+    {
+        LogError("Invalid HTTP instance");
+        result = -1;
+    }
+    else
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_081: [ The HTTPAPI_ExecuteRequest shall try to read the message with the response up to 20 seconds. ]*/
+        int countRetry = MAX_RECEIVE_RETRY;
+        result = (int)n;
+        while (n > 0)
+        {
+            xio_dowork(http_instance->xio_handle);
+
+            /* if any error was detected while receiving then simply break and report it */
+            if (http_instance->is_io_error != 0)
+            {
+                LogError("xio reported error on dowork");
+                result = -1;
+                n = 0;
+            }
+            else
+            {
+                if (http_instance->received_bytes_count <= n)
+                {
+                    n -= http_instance->received_bytes_count;
+                    http_instance->received_bytes_count = 0;
+                }
+                else
+                {
+                    http_instance->received_bytes_count -= n;
+                    (void)memmove(http_instance->received_bytes, http_instance->received_bytes + n, http_instance->received_bytes_count);
+                    n = 0;
+                }
+
+                if (n > 0)
+                {
+                    if ((countRetry--) > 0)
+                    {
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_083: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
+                        ThreadAPI_Sleep(RETRY_INTERVAL_IN_MICROSECONDS);
+                    }
+                    else
+                    {
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
+                        LogError("Receive timeout. The HTTP request is incomplete");
+                        n = 0;
+                        result = -1;
+                    }
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+
+/*Codes_SRS_HTTPAPI_COMPACT_21_021: [ The HTTPAPI_ExecuteRequest shall execute the http communtication with the provided host, sending a request and reciving the response. ]*/
+static HTTPAPI_RESULT OpenXIOConnection(HTTP_HANDLE_DATA* http_instance)
+{
+    HTTPAPI_RESULT result;
+    TLSIO_CONFIG tlsio_config;
+    HTTP_PROXY_IO_CONFIG http_proxy_io_config;
+
+    if (http_instance->is_connected != 0)
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+        result = HTTPAPI_OK;
+    }
+    else
+    {
+        http_instance->is_io_error = 0;
+        tlsio_config.hostname = http_instance->hostName;
+        tlsio_config.port = 443;
+
+        if (http_instance->proxy_host != NULL) {
+            tlsio_config.underlying_io_interface = http_proxy_io_get_interface_description();
+        }
+        else {
+            tlsio_config.underlying_io_interface = NULL;
+        }
+
+        if (tlsio_config.underlying_io_interface != NULL) {
+            tlsio_config.underlying_io_parameters = (void*)&http_proxy_io_config;
+
+            http_proxy_io_config.proxy_hostname = http_instance->proxy_host;
+            http_proxy_io_config.proxy_port = http_instance->proxy_port;
+            http_proxy_io_config.username = http_instance->proxy_username;
+            http_proxy_io_config.password = http_instance->proxy_password;
+            http_proxy_io_config.hostname = http_instance->hostName;
+            http_proxy_io_config.port = 443;
+        }
+        else {
+            tlsio_config.underlying_io_parameters = NULL;
+        }
+
+        http_instance->xio_handle = xio_create(platform_get_default_tlsio(), (void*)&tlsio_config);
+
+        if (http_instance->xio_handle == NULL)
+        {
+            LogError("Create connection failed");
+            free(http_instance);
+            http_instance = NULL;
+            result = HTTPAPI_ERROR;
+        }
+        /*Codes_SRS_HTTPAPI_COMPACT_21_022: [ If a Certificate was provided, the HTTPAPI_ExecuteRequest shall set this option on the transport layer. ]*/
+        else if ((http_instance->certificate != NULL) &&
+            (xio_setoption(http_instance->xio_handle, OPTION_TRUSTED_CERT, http_instance->certificate) != 0))
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_023: [ If the transport failed setting the Certificate, the HTTPAPI_ExecuteRequest shall not send any request and return HTTPAPI_SET_OPTION_FAILED. ]*/
+            result = HTTPAPI_SET_OPTION_FAILED;
+            LogInfo("Could not load certificate");
+        }
+        /*Codes_SRS_HTTPAPI_COMPACT_06_003: [ If the x509 client certificate is provided, the HTTPAPI_ExecuteRequest shall set this option on the transport layer. ]*/
+        else if ((http_instance->x509ClientCertificate != NULL) &&
+            (xio_setoption(http_instance->xio_handle, SU_OPTION_X509_CERT, http_instance->x509ClientCertificate) != 0))
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_06_005: [ If the transport failed setting the client certificate, the HTTPAPI_ExecuteRequest shall not send any request and return HTTPAPI_SET_OPTION_FAILED. ]*/
+            result = HTTPAPI_SET_OPTION_FAILED;
+            LogInfo("Could not load the client certificate");
+        }
+        else if ((http_instance->x509ClientPrivateKey != NULL) &&
+            (xio_setoption(http_instance->xio_handle, SU_OPTION_X509_PRIVATE_KEY, http_instance->x509ClientPrivateKey) != 0))
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_06_006: [ If the transport failed setting the client certificate private key, the HTTPAPI_ExecuteRequest shall not send any request and return HTTPAPI_SET_OPTION_FAILED. ] */
+            result = HTTPAPI_SET_OPTION_FAILED;
+            LogInfo("Could not load the client certificate private key");
+        }
+        else
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_024: [ The HTTPAPI_ExecuteRequest shall open the transport connection with the host to send the request. ]*/
+            if (xio_open(http_instance->xio_handle, on_io_open_complete, http_instance, on_bytes_received, http_instance, on_io_error, http_instance) != 0)
+            {
+                /*Codes_SRS_HTTPAPI_COMPACT_21_025: [ If the open process failed, the HTTPAPI_ExecuteRequest shall not send any request and return HTTPAPI_OPEN_REQUEST_FAILED. ]*/
+                result = HTTPAPI_OPEN_REQUEST_FAILED;
+            }
+            else
+            {
+                int countRetry;
+                /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+                result = HTTPAPI_OK;
+                /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ The HTTPAPI_ExecuteRequest shall wait, at least, 10 seconds for the SSL open process. ]*/
+                countRetry = MAX_OPEN_RETRY;
+                while ((http_instance->is_connected == 0) &&
+                    (http_instance->is_io_error == 0))
+                {
+                    xio_dowork(http_instance->xio_handle);
+                    //LogInfo("Waiting for TLS connection");
+                    if ((countRetry--) < 0)
+                    {
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_078: [ If the HTTPAPI_ExecuteRequest cannot open the connection in 10 seconds, it shall fail and return HTTPAPI_OPEN_REQUEST_FAILED. ]*/
+                        LogError("Open timeout. The HTTP request is incomplete");
+                        result = HTTPAPI_OPEN_REQUEST_FAILED;
+                        break;
+                    }
+                    else
+                    {
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_083: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
+                        ThreadAPI_Sleep(RETRY_INTERVAL_IN_MICROSECONDS);
+                    }
+                }
+            }
+        }
+    }
+
+    if ((http_instance->is_io_error != 0) && (result == HTTPAPI_OK))
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_025: [ If the open process failed, the HTTPAPI_ExecuteRequest shall not send any request and return HTTPAPI_OPEN_REQUEST_FAILED. ]*/
+        result = HTTPAPI_OPEN_REQUEST_FAILED;
+    }
+
+    return result;
+}
+
+static HTTPAPI_RESULT conn_send_all(HTTP_HANDLE_DATA* http_instance, const unsigned char* buf, size_t bufLen)
+{
+    HTTPAPI_RESULT result;
+
+    http_instance->send_completed = 0;
+    http_instance->is_io_error = 0;
+    if (xio_send(http_instance->xio_handle, buf, bufLen, on_send_complete, http_instance) != 0)
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_028: [ If the HTTPAPI_ExecuteRequest cannot send the request header, it shall return HTTPAPI_HTTP_HEADERS_FAILED. ]*/
+        result = HTTPAPI_SEND_REQUEST_FAILED;
+    }
+    else
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_079: [ The HTTPAPI_ExecuteRequest shall wait, at least, 20 seconds to send a buffer using the SSL connection. ]*/
+        int countRetry = MAX_SEND_RETRY;
+        /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+        result = HTTPAPI_OK;
+        while ((http_instance->send_completed == 0) && (result == HTTPAPI_OK))
+        {
+            xio_dowork(http_instance->xio_handle);
+            if (http_instance->is_io_error != 0)
+            {
+                /*Codes_SRS_HTTPAPI_COMPACT_21_028: [ If the HTTPAPI_ExecuteRequest cannot send the request header, it shall return HTTPAPI_HTTP_HEADERS_FAILED. ]*/
+                result = HTTPAPI_SEND_REQUEST_FAILED;
+            }
+            else if ((countRetry--) <= 0)
+            {
+                /*Codes_SRS_HTTPAPI_COMPACT_21_080: [ If the HTTPAPI_ExecuteRequest retries to send the message for 20 seconds without success, it shall fail and return HTTPAPI_SEND_REQUEST_FAILED. ]*/
+                LogError("Send timeout. The HTTP request is incomplete");
+                /*Codes_SRS_HTTPAPI_COMPACT_21_028: [ If the HTTPAPI_ExecuteRequest cannot send the request header, it shall return HTTPAPI_HTTP_HEADERS_FAILED. ]*/
+                result = HTTPAPI_SEND_REQUEST_FAILED;
+            }
+            else
+            {
+                /*Codes_SRS_HTTPAPI_COMPACT_21_083: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
+                ThreadAPI_Sleep(RETRY_INTERVAL_IN_MICROSECONDS);
+            }
+        }
+    }
+
+    return result;
+}
+
+/*Codes_SRS_HTTPAPI_COMPACT_21_035: [ The HTTPAPI_ExecuteRequest shall execute resquest for types GET, POST, PUT, DELETE, PATCH, HEAD. ]*/
+const char httpapiRequestString[6][7] = { "GET", "POST", "PUT", "DELETE", "PATCH", "HEAD" };
+const char* get_request_type(HTTPAPI_REQUEST_TYPE requestType)
+{
+    return (const char*)httpapiRequestString[requestType - HTTPAPI_REQUEST_GET];
+}
+
+/*Codes_SRS_HTTPAPI_COMPACT_21_026: [ If the open process succeed, the HTTPAPI_ExecuteRequest shall send the request message to the host. ]*/
+static HTTPAPI_RESULT SendHeadsToXIO(HTTP_HANDLE_DATA* http_instance, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath, HTTP_HEADERS_HANDLE httpHeadersHandle, size_t headersCount)
+{
+    HTTPAPI_RESULT result;
+    char    buf[TEMP_BUFFER_SIZE];
+    int     ret;
+
+    //Send request
+    /*Codes_SRS_HTTPAPI_COMPACT_21_038: [ The HTTPAPI_ExecuteRequest shall execute the resquest for the path in relativePath parameter. ]*/
+    /*Codes_SRS_HTTPAPI_COMPACT_21_036: [ The request type shall be provided in the parameter requestType. ]*/
+    if (((ret = snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\n", get_request_type(requestType), relativePath)) < 0) ||
+        ((size_t)ret >= sizeof(buf)))
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_027: [ If the HTTPAPI_ExecuteRequest cannot create a buffer to send the request, it shall not send any request and return HTTPAPI_STRING_PROCESSING_ERROR. ]*/
+        result = HTTPAPI_STRING_PROCESSING_ERROR;
+    }
+        /*Codes_SRS_HTTPAPI_COMPACT_21_028: [ If the HTTPAPI_ExecuteRequest cannot send the request header, it shall return HTTPAPI_HTTP_HEADERS_FAILED. ]*/
+    else if ((result = conn_send_all(http_instance, (const unsigned char*)buf, strlen(buf))) == HTTPAPI_OK)
+    {
+        size_t i;
+        //Send default headers
+        /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+        for (i = 0; ((i < headersCount) && (result == HTTPAPI_OK)); i++)
+        {
+            char* header;
+            if (HTTPHeaders_GetHeader(httpHeadersHandle, i, &header) != HTTP_HEADERS_OK)
+            {
+                /*Codes_SRS_HTTPAPI_COMPACT_21_027: [ If the HTTPAPI_ExecuteRequest cannot create a buffer to send the request, it shall not send any request and return HTTPAPI_STRING_PROCESSING_ERROR. ]*/
+                result = HTTPAPI_STRING_PROCESSING_ERROR;
+            }
+            else
+            {
+                if ((result = conn_send_all(http_instance, (const unsigned char*)header, strlen(header))) == HTTPAPI_OK)
+                {
+                    result = conn_send_all(http_instance, (const unsigned char*)"\r\n", (size_t)2);
+                }
+                free(header);
+            }
+        }
+
+        //Close headers
+        if (result == HTTPAPI_OK)
+        {
+            result = conn_send_all(http_instance, (const unsigned char*)"\r\n", (size_t)2);
+        }
+    }
+    return result;
+}
+
+/*Codes_SRS_HTTPAPI_COMPACT_21_042: [ The request can contain the a content message, provided in content parameter. ]*/
+static HTTPAPI_RESULT SendContentToXIO(HTTP_HANDLE_DATA* http_instance, const unsigned char* content, size_t contentLength)
+{
+    HTTPAPI_RESULT result;
+
+    //Send data (if available)
+    /*Codes_SRS_HTTPAPI_COMPACT_21_045: [ If the contentLength is lower than one, the HTTPAPI_ExecuteRequest shall send the request without content. ]*/
+    if (content && contentLength > 0)
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_044: [ If the content is not NULL, the number of bytes in the content shall be provided in contentLength parameter. ]*/
+        result = conn_send_all(http_instance, content, contentLength);
+    }
+    else
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_043: [ If the content is NULL, the HTTPAPI_ExecuteRequest shall send the request without content. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+        result = HTTPAPI_OK;
+    }
+    return result;
+}
+
+/*Codes_SRS_HTTPAPI_COMPACT_21_030: [ At the end of the transmission, the HTTPAPI_ExecuteRequest shall receive the response from the host. ]*/
+static HTTPAPI_RESULT ReceiveHeaderFromXIO(HTTP_HANDLE_DATA* http_instance, unsigned int* statusCode)
+{
+    HTTPAPI_RESULT result;
+    char    buf[TEMP_BUFFER_SIZE];
+    int     ret;
+
+    http_instance->is_io_error = 0;
+
+    //Receive response
+    if (readLine(http_instance, buf, TEMP_BUFFER_SIZE) < 0)
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
+        result = HTTPAPI_READ_DATA_FAILED;
+    }
+    //Parse HTTP response
+    else if (ParseHttpResponse(buf, &ret) != 1)
+    {
+        //Cannot match string, error
+        /*Codes_SRS_HTTPAPI_COMPACT_21_055: [ If the HTTPAPI_ExecuteRequest cannot parser the received message, it shall return HTTPAPI_RECEIVE_RESPONSE_FAILED. ]*/
+        LogInfo("Not a correct HTTP answer");
+        result = HTTPAPI_RECEIVE_RESPONSE_FAILED;
+    }
+    else
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_046: [ The HTTPAPI_ExecuteRequest shall return the http status reported by the host in the received response. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_048: [ If the statusCode is NULL, the HTTPAPI_ExecuteRequest shall report not report any status. ]*/
+        if (statusCode)
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_047: [ The HTTPAPI_ExecuteRequest shall report the status in the statusCode parameter. ]*/
+            *statusCode = ret;
+        }
+        /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+        result = HTTPAPI_OK;
+    }
+
+    return result;
+}
+
+static HTTPAPI_RESULT ReceiveContentInfoFromXIO(HTTP_HANDLE_DATA* http_instance, HTTP_HEADERS_HANDLE responseHeadersHandle, size_t* bodyLength, bool* chunked)
+{
+    HTTPAPI_RESULT result;
+    char    buf[TEMP_BUFFER_SIZE];
+    const char* substr;
+    char* whereIsColon;
+    int lengthInMsg;
+    const char ContentLength[] = "content-length:";
+    const size_t ContentLengthSize = sizeof(ContentLength) - 1;
+    const char TransferEncoding[] = "transfer-encoding:";
+    const size_t TransferEncodingSize = sizeof(TransferEncoding) - 1;
+    const char Chunked[] = "chunked";
+    const size_t ChunkedSize = sizeof(Chunked) - 1;
+
+    http_instance->is_io_error = 0;
+
+    //Read HTTP response headers
+    if (readLine(http_instance, buf, sizeof(buf)) < 0)
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
+        result = HTTPAPI_READ_DATA_FAILED;
+    }
+    else
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+        result = HTTPAPI_OK;
+
+        while (*buf && (result == HTTPAPI_OK))
+        {
+            if (InternStrnicmp(buf, ContentLength, ContentLengthSize) == 0)
+            {
+                substr = buf + ContentLengthSize;
+                if (ParseStringToDecimal(substr, &lengthInMsg) != 1)
+                {
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
+                    result = HTTPAPI_READ_DATA_FAILED;
+                }
+                else
+                {
+                    (*bodyLength) = (size_t)lengthInMsg;
+                }
+            }
+            else if (InternStrnicmp(buf, TransferEncoding, TransferEncodingSize) == 0)
+            {
+                substr = buf + TransferEncodingSize;
+
+                while (isspace(*substr)) substr++;
+
+                if (InternStrnicmp(substr, Chunked, ChunkedSize) == 0)
+                {
+                    (*chunked) = true;
+                }
+            }
+
+            if (result == HTTPAPI_OK)
+            {
+                whereIsColon = strchr((char*)buf, ':');
+                /*Codes_SRS_HTTPAPI_COMPACT_21_049: [ If responseHeadersHandle is provide, the HTTPAPI_ExecuteRequest shall prepare a Response Header usign the HTTPHeaders_AddHeaderNameValuePair. ]*/
+                if (whereIsColon && (responseHeadersHandle != NULL))
+                {
+                    *whereIsColon = '\0';
+                    HTTPHeaders_AddHeaderNameValuePair(responseHeadersHandle, buf, whereIsColon + 1);
+                }
+
+                if (readLine(http_instance, buf, sizeof(buf)) < 0)
+                {
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
+                    result = HTTPAPI_READ_DATA_FAILED;
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+static HTTPAPI_RESULT ReadHTTPResponseBodyFromXIO(HTTP_HANDLE_DATA* http_instance, size_t bodyLength, bool chunked, BUFFER_HANDLE responseContent)
+{
+    HTTPAPI_RESULT result;
+    char    buf[TEMP_BUFFER_SIZE];
+    const unsigned char* receivedContent;
+
+    http_instance->is_io_error = 0;
+
+    //Read HTTP response body
+    if (!chunked)
+    {
+        if (bodyLength)
+        {
+            if (responseContent != NULL)
+            {
+                if (BUFFER_pre_build(responseContent, bodyLength) != 0)
+                {
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
+                    result = HTTPAPI_ALLOC_FAILED;
+                }
+                else if (BUFFER_content(responseContent, &receivedContent) != 0)
+                {
+                    (void)BUFFER_unbuild(responseContent);
+
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
+                    result = HTTPAPI_ALLOC_FAILED;
+                }
+                else if (readChunk(http_instance, (char*)receivedContent, bodyLength) < 0)
+                {
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
+                    result = HTTPAPI_READ_DATA_FAILED;
+                }
+                else
+                {
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+                    result = HTTPAPI_OK;
+                }
+            }
+            else
+            {
+                /*Codes_SRS_HTTPAPI_COMPACT_21_051: [ If the responseContent is NULL, the HTTPAPI_ExecuteRequest shall ignore any content in the response. ]*/
+                if (skipN(http_instance, bodyLength) < 0)
+                {
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
+                    result = HTTPAPI_READ_DATA_FAILED;
+                }
+                else
+                {
+                    result = HTTPAPI_OK;
+                }
+            }
+        }
+        else
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+            result = HTTPAPI_OK;
+        }
+    }
+    else
+    {
+        size_t size = 0;
+        /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+        result = HTTPAPI_OK;
+        while (result == HTTPAPI_OK)
+        {
+            size_t chunkSize;
+            if (readLine(http_instance, buf, sizeof(buf)) < 0)    // read [length in hex]/r/n
+            {
+                /*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
+                /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
+                result = HTTPAPI_READ_DATA_FAILED;
+            }
+            else if (ParseStringToHexadecimal(buf, &chunkSize) != 1)     // chunkSize is length of next line (/r/n is not counted)
+            {
+                //Cannot match string, error
+                /*Codes_SRS_HTTPAPI_COMPACT_21_055: [ If the HTTPAPI_ExecuteRequest cannot parser the received message, it shall return HTTPAPI_RECEIVE_RESPONSE_FAILED. ]*/
+                result = HTTPAPI_RECEIVE_RESPONSE_FAILED;
+            }
+            else if (chunkSize == 0)
+            {
+                // 0 length means next line is just '\r\n' and end of chunks
+                if (readChunk(http_instance, (char*)buf, (size_t)2) < 0
+                    || buf[0] != '\r' || buf[1] != '\n') // skip /r/n
+                {
+                    (void)BUFFER_unbuild(responseContent);
+
+                    result = HTTPAPI_READ_DATA_FAILED;
+                }
+                break;
+            }
+            else
+            {
+                if (responseContent != NULL)
+                {
+                    if (BUFFER_enlarge(responseContent, chunkSize) != 0)
+                    {
+                        (void)BUFFER_unbuild(responseContent);
+
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
+                        result = HTTPAPI_ALLOC_FAILED;
+                    }
+                    else if (BUFFER_content(responseContent, &receivedContent) != 0)
+                    {
+                        (void)BUFFER_unbuild(responseContent);
+
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
+                        result = HTTPAPI_ALLOC_FAILED;
+                    }
+                    else if (readChunk(http_instance, (char*)receivedContent + size, chunkSize) < 0)
+                    {
+                        result = HTTPAPI_READ_DATA_FAILED;
+                    }
+                }
+                else
+                {
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_051: [ If the responseContent is NULL, the HTTPAPI_ExecuteRequest shall ignore any content in the response. ]*/
+                    if (skipN(http_instance, chunkSize) < 0)
+                    {
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
+                        result = HTTPAPI_READ_DATA_FAILED;
+                    }
+                }
+
+                if (result == HTTPAPI_OK)
+                {
+                    if (readChunk(http_instance, (char*)buf, (size_t)2) < 0
+                        || buf[0] != '\r' || buf[1] != '\n') // skip /r/n
+                    {
+                        result = HTTPAPI_READ_DATA_FAILED;
+                    }
+                    size += chunkSize;
+                }
+            }
+        }
+
+    }
+    return result;
+}
+
+
+/*Codes_SRS_HTTPAPI_COMPACT_21_037: [ If the request type is unknown, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
+static bool validRequestType(HTTPAPI_REQUEST_TYPE requestType)
+{
+    bool result;
+
+    if ((requestType == HTTPAPI_REQUEST_GET) ||
+        (requestType == HTTPAPI_REQUEST_POST) ||
+        (requestType == HTTPAPI_REQUEST_PUT) ||
+        (requestType == HTTPAPI_REQUEST_DELETE) ||
+        (requestType == HTTPAPI_REQUEST_PATCH) ||
+        (requestType == HTTPAPI_REQUEST_HEAD))
+    {
+        result = true;
+    }
+    else
+    {
+        result = false;
+    }
+
+    return result;
+}
+
+/*Codes_SRS_HTTPAPI_COMPACT_21_021: [ The HTTPAPI_ExecuteRequest shall execute the http communtication with the provided host, sending a request and reciving the response. ]*/
+/*Codes_SRS_HTTPAPI_COMPACT_21_050: [ If there is a content in the response, the HTTPAPI_ExecuteRequest shall copy it in the responseContent buffer. ]*/
+//Note: This function assumes that "Host:" and "Content-Length:" headers are setup
+//      by the caller of HTTPAPI_ExecuteRequest() (which is true for httptransport.c).
+HTTPAPI_RESULT HTTPAPI_ExecuteRequest(HTTP_HANDLE handle, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath,
+    HTTP_HEADERS_HANDLE httpHeadersHandle, const unsigned char* content,
+    size_t contentLength, unsigned int* statusCode,
+    HTTP_HEADERS_HANDLE responseHeadersHandle, BUFFER_HANDLE responseContent)
+{
+    HTTPAPI_RESULT result = HTTPAPI_ERROR;
+    size_t  headersCount;
+    size_t  bodyLength = 0;
+    bool    chunked = false;
+    HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)handle;
+
+    /*Codes_SRS_HTTPAPI_COMPACT_21_034: [ If there is no previous connection, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
+    /*Codes_SRS_HTTPAPI_COMPACT_21_037: [ If the request type is unknown, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
+    /*Codes_SRS_HTTPAPI_COMPACT_21_039: [ If the relativePath is NULL or invalid, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
+    /*Codes_SRS_HTTPAPI_COMPACT_21_041: [ If the httpHeadersHandle is NULL or invalid, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
+    /*Codes_SRS_HTTPAPI_COMPACT_21_053: [ The HTTPAPI_ExecuteRequest shall produce a set of http header to send to the host. ]*/
+    /*Codes_SRS_HTTPAPI_COMPACT_21_040: [ The request shall contain the http header provided in httpHeadersHandle parameter. ]*/
+    /*Codes_SRS_HTTPAPI_COMPACT_21_054: [ If Http header maker cannot provide the number of headers, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
+    if (http_instance == NULL ||
+        relativePath == NULL ||
+        httpHeadersHandle == NULL ||
+        !validRequestType(requestType) ||
+        HTTPHeaders_GetHeaderCount(httpHeadersHandle, &headersCount) != HTTP_HEADERS_OK)
+    {
+        result = HTTPAPI_INVALID_ARG;
+        LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
+    }
+    /*Codes_SRS_HTTPAPI_COMPACT_21_024: [ The HTTPAPI_ExecuteRequest shall open the transport connection with the host to send the request. ]*/
+    else if ((result = OpenXIOConnection(http_instance)) != HTTPAPI_OK)
+    {
+        LogError("Open HTTP connection failed (result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
+    }
+    /*Codes_SRS_HTTPAPI_COMPACT_21_026: [ If the open process succeed, the HTTPAPI_ExecuteRequest shall send the request message to the host. ]*/
+    else if ((result = SendHeadsToXIO(http_instance, requestType, relativePath, httpHeadersHandle, headersCount)) != HTTPAPI_OK)
+    {
+        LogError("Send heads to HTTP failed (result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
+    }
+    /*Codes_SRS_HTTPAPI_COMPACT_21_042: [ The request can contain the a content message, provided in content parameter. ]*/
+    else if ((result = SendContentToXIO(http_instance, content, contentLength)) != HTTPAPI_OK)
+    {
+        LogError("Send content to HTTP failed (result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
+    }
+    /*Codes_SRS_HTTPAPI_COMPACT_21_030: [ At the end of the transmission, the HTTPAPI_ExecuteRequest shall receive the response from the host. ]*/
+    /*Codes_SRS_HTTPAPI_COMPACT_21_073: [ The message received by the HTTPAPI_ExecuteRequest shall starts with a valid header. ]*/
+    else if ((result = ReceiveHeaderFromXIO(http_instance, statusCode)) != HTTPAPI_OK)
+    {
+        LogError("Receive header from HTTP failed (result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
+    }
+    /*Codes_SRS_HTTPAPI_COMPACT_21_074: [ After the header, the message received by the HTTPAPI_ExecuteRequest can contain addition information about the content. ]*/
+    else if ((result = ReceiveContentInfoFromXIO(http_instance, responseHeadersHandle, &bodyLength, &chunked)) != HTTPAPI_OK)
+    {
+        LogError("Receive content information from HTTP failed (result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
+    }
+    /*Codes_SRS_HTTPAPI_COMPACT_42_084: [ The message received by the HTTPAPI_ExecuteRequest should not contain http body. ]*/
+    else if (requestType != HTTPAPI_REQUEST_HEAD)
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_075: [ The message received by the HTTPAPI_ExecuteRequest can contain a body with the message content. ]*/
+        if ((result = ReadHTTPResponseBodyFromXIO(http_instance, bodyLength, chunked, responseContent)) != HTTPAPI_OK)
+        {
+            LogError("Read HTTP response body from HTTP failed (result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTPAPI_RESULT, result));
+        }
+    }
+
+    conn_receive_discard_buffer(http_instance);
+
+    return result;
+}
+
+/*Codes_SRS_HTTPAPI_COMPACT_21_056: [ The HTTPAPI_SetOption shall change the HTTP options. ]*/
+/*Codes_SRS_HTTPAPI_COMPACT_21_057: [ The HTTPAPI_SetOption shall receive a handle that identiry the HTTP connection. ]*/
+/*Codes_SRS_HTTPAPI_COMPACT_21_058: [ The HTTPAPI_SetOption shall receive the option as a pair optionName/value. ]*/
+HTTPAPI_RESULT HTTPAPI_SetOption(HTTP_HANDLE handle, const char* optionName, const void* value)
+{
+    HTTPAPI_RESULT result;
+    HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)handle;
+
+    if (
+        (http_instance == NULL) ||
+        (optionName == NULL) ||
+        (value == NULL)
+        )
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_059: [ If the handle is NULL, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_060: [ If the optionName is NULL, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_061: [ If the value is NULL, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/
+        result = HTTPAPI_INVALID_ARG;
+    }
+    else if (strcmp(OPTION_TRUSTED_CERT, optionName) == 0)
+    {
+#ifdef DO_NOT_COPY_TRUSTED_CERTS_STRING
+        result = HTTPAPI_OK;
+        http_instance->certificate = (char*)value;
+#else
+        int len;
+
+        if (http_instance->certificate)
+        {
+            free(http_instance->certificate);
+        }
+
+        len = (int)strlen((char*)value);
+        http_instance->certificate = (char*)malloc((len + 1) * sizeof(char));
+        if (http_instance->certificate == NULL)
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_062: [ If any memory allocation get fail, the HTTPAPI_SetOption shall return HTTPAPI_ALLOC_FAILED. ]*/
+            result = HTTPAPI_ALLOC_FAILED;
+            LogInfo("unable to allocate memory for the certificate in HTTPAPI_SetOption");
+        }
+        else
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_064: [ If the HTTPAPI_SetOption get success setting the option, it shall return HTTPAPI_OK. ]*/
+            (void)strcpy(http_instance->certificate, (const char*)value);
+            result = HTTPAPI_OK;
+        }
+#endif // DO_NOT_COPY_TRUSTED_CERTS_STRING
+    }
+    else if (strcmp(SU_OPTION_X509_CERT, optionName) == 0)
+    {
+        int len;
+        if (http_instance->x509ClientCertificate)
+        {
+            free(http_instance->x509ClientCertificate);
+        }
+
+        len = (int)strlen((char*)value);
+        http_instance->x509ClientCertificate = (char*)malloc((len + 1) * sizeof(char));
+        if (http_instance->x509ClientCertificate == NULL)
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_062: [ If any memory allocation get fail, the HTTPAPI_SetOption shall return HTTPAPI_ALLOC_FAILED. ]*/
+            result = HTTPAPI_ALLOC_FAILED;
+            LogInfo("unable to allocate memory for the client certificate in HTTPAPI_SetOption");
+        }
+        else
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_064: [ If the HTTPAPI_SetOption get success setting the option, it shall return HTTPAPI_OK. ]*/
+            (void)strcpy(http_instance->x509ClientCertificate, (const char*)value);
+            result = HTTPAPI_OK;
+        }
+    }
+    else if (strcmp(SU_OPTION_X509_PRIVATE_KEY, optionName) == 0)
+    {
+        int len;
+        if (http_instance->x509ClientPrivateKey)
+        {
+            free(http_instance->x509ClientPrivateKey);
+        }
+
+        len = (int)strlen((char*)value);
+        http_instance->x509ClientPrivateKey = (char*)malloc((len + 1) * sizeof(char));
+        if (http_instance->x509ClientPrivateKey == NULL)
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_062: [ If any memory allocation get fail, the HTTPAPI_SetOption shall return HTTPAPI_ALLOC_FAILED. ]*/
+            result = HTTPAPI_ALLOC_FAILED;
+            LogInfo("unable to allocate memory for the client private key in HTTPAPI_SetOption");
+        }
+        else
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_064: [ If the HTTPAPI_SetOption get success setting the option, it shall return HTTPAPI_OK. ]*/
+            (void)strcpy(http_instance->x509ClientPrivateKey, (const char*)value);
+            result = HTTPAPI_OK;
+        }
+    }
+    else if (strcmp(OPTION_HTTP_PROXY, optionName) == 0)
+    {
+        HTTP_PROXY_OPTIONS* proxy_data = (HTTP_PROXY_OPTIONS*)value;
+        if (proxy_data->host_address == NULL || proxy_data->port <= 0)
+        {
+            LogError("invalid proxy_data values ( host_address = %p, port = %d)", proxy_data->host_address, proxy_data->port);
+            result = HTTPAPI_ERROR;
+        }
+        else
+        {
+            if(http_instance->proxy_host != NULL)
+            {
+                free((void*)http_instance->proxy_host);
+                http_instance->proxy_host = NULL;
+            }
+            if(mallocAndStrcpy_s((char**)&(http_instance->proxy_host), (const char*)proxy_data->host_address) != 0)
+            {
+                LogError("failure allocate proxy host");
+                result = HTTPAPI_ERROR;
+            }
+            else
+            {
+                http_instance->proxy_port = proxy_data->port;
+
+                if (proxy_data->username != NULL && proxy_data->password != NULL)
+                {
+                    if(http_instance->proxy_username != NULL)
+                    {
+                        free((void*)http_instance->proxy_username);
+                        http_instance->proxy_username = NULL;
+                    }
+                    if(mallocAndStrcpy_s((char**)&(http_instance->proxy_username), (const char*)proxy_data->username) != 0)
+                    {
+                        LogError("failure allocate proxy username");
+                        free((void*)http_instance->proxy_host);
+                        http_instance->proxy_host = NULL;
+                        result = HTTPAPI_ERROR;
+                    }
+                    else
+                    {
+                        if(http_instance->proxy_password != NULL)
+                        {
+                          free((void*)http_instance->proxy_password);
+                          http_instance->proxy_password = NULL;
+                        }
+                        if(mallocAndStrcpy_s((char**)&(http_instance->proxy_password), (const char*)proxy_data->password) != 0)
+                        {
+                            LogError("failure allocate proxy password");
+                            free((void*)http_instance->proxy_host);
+                            http_instance->proxy_host = NULL;
+                            free((void*)http_instance->proxy_username);
+                            http_instance->proxy_username = NULL;
+                            result = HTTPAPI_ERROR;
+                        }
+                        else
+                        {
+                          result = HTTPAPI_OK;
+                        }
+                    }
+                }
+                else
+                {
+                    result = HTTPAPI_OK;
+                }
+            }
+        }
+    }
+    else
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_063: [ If the HTTP do not support the optionName, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/
+        result = HTTPAPI_INVALID_ARG;
+        LogInfo("unknown option %s", optionName);
+    }
+    return result;
+}
+
+/*Codes_SRS_HTTPAPI_COMPACT_21_065: [ The HTTPAPI_CloneOption shall provide the means to clone the HTTP option. ]*/
+/*Codes_SRS_HTTPAPI_COMPACT_21_066: [ The HTTPAPI_CloneOption shall return a clone of the value identified by the optionName. ]*/
+HTTPAPI_RESULT HTTPAPI_CloneOption(const char* optionName, const void* value, const void** savedValue)
+{
+    HTTPAPI_RESULT result;
+    size_t certLen;
+    char* tempCert;
+
+    if (
+        (optionName == NULL) ||
+        (value == NULL) ||
+        (savedValue == NULL)
+        )
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_067: [ If the optionName is NULL, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_068: [ If the value is NULL, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_069: [ If the savedValue is NULL, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/
+        result = HTTPAPI_INVALID_ARG;
+    }
+    else if (strcmp(OPTION_TRUSTED_CERT, optionName) == 0)
+    {
+#ifdef DO_NOT_COPY_TRUSTED_CERTS_STRING
+        *savedValue = (const void*)value;
+        result = HTTPAPI_OK;
+#else
+        certLen = strlen((const char*)value);
+        tempCert = (char*)malloc((certLen + 1) * sizeof(char));
+        if (tempCert == NULL)
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_070: [ If any memory allocation get fail, the HTTPAPI_CloneOption shall return HTTPAPI_ALLOC_FAILED. ]*/
+            result = HTTPAPI_ALLOC_FAILED;
+        }
+        else
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_072: [ If the HTTPAPI_CloneOption get success setting the option, it shall return HTTPAPI_OK. ]*/
+            (void)strcpy(tempCert, (const char*)value);
+            *savedValue = tempCert;
+            result = HTTPAPI_OK;
+        }
+#endif // DO_NOT_COPY_TRUSTED_CERTS_STRING
+    }
+    else if (strcmp(SU_OPTION_X509_CERT, optionName) == 0)
+    {
+        certLen = strlen((const char*)value);
+        tempCert = (char*)malloc((certLen + 1) * sizeof(char));
+        if (tempCert == NULL)
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_070: [ If any memory allocation get fail, the HTTPAPI_CloneOption shall return HTTPAPI_ALLOC_FAILED. ]*/
+            result = HTTPAPI_ALLOC_FAILED;
+        }
+        else
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_072: [ If the HTTPAPI_CloneOption get success setting the option, it shall return HTTPAPI_OK. ]*/
+            (void)strcpy(tempCert, (const char*)value);
+            *savedValue = tempCert;
+            result = HTTPAPI_OK;
+        }
+    }
+    else if (strcmp(SU_OPTION_X509_PRIVATE_KEY, optionName) == 0)
+    {
+        certLen = strlen((const char*)value);
+        tempCert = (char*)malloc((certLen + 1) * sizeof(char));
+        if (tempCert == NULL)
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_070: [ If any memory allocation get fail, the HTTPAPI_CloneOption shall return HTTPAPI_ALLOC_FAILED. ]*/
+            result = HTTPAPI_ALLOC_FAILED;
+        }
+        else
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_072: [ If the HTTPAPI_CloneOption get success setting the option, it shall return HTTPAPI_OK. ]*/
+            (void)strcpy(tempCert, (const char*)value);
+            *savedValue = tempCert;
+            result = HTTPAPI_OK;
+        }
+    }
+    else if (strcmp(OPTION_HTTP_PROXY, optionName) == 0)
+    {
+        HTTP_PROXY_OPTIONS* proxy_data = (HTTP_PROXY_OPTIONS*)value;
+
+        HTTP_PROXY_OPTIONS* new_proxy_info = malloc(sizeof(HTTP_PROXY_OPTIONS));
+        if (new_proxy_info == NULL)
+        {
+            LogError("unable to allocate proxy option information");
+            result = HTTPAPI_ERROR;
+        }
+        else
+        {
+            new_proxy_info->host_address = proxy_data->host_address;
+            new_proxy_info->port = proxy_data->port;
+            new_proxy_info->password = proxy_data->password;
+            new_proxy_info->username = proxy_data->username;
+            *savedValue = new_proxy_info;
+            result = HTTPAPI_OK;
+        }
+    }
+    else
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_071: [ If the HTTP do not support the optionName, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/
+        result = HTTPAPI_INVALID_ARG;
+        LogInfo("unknown option %s", optionName);
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/lock_toppers.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/lock_toppers.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/lock_toppers.c	(revision 453)
@@ -0,0 +1,216 @@
+/*
+ *  TOPPERS PROJECT Home Network Working Group Software
+ *
+ *  Copyright (C) 2019 Cores Co., Ltd. Japan
+ *
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ *
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ *
+ *  @(#) $Id$
+ */
+#include <stdint.h>
+#include <stdlib.h>
+#include <kernel.h>
+#include <t_stdlib.h>
+#include "azure_c_shared_utility/lock.h"
+#include "azure_c_shared_utility/xlogging.h"
+
+#ifdef TOPPERS_SUPPORT_DYNAMIC_CRE
+#define MAX_MUTEX 4
+#define TASK_PRIORITY ((TMAX_TPRI + TMIN_TPRI) / 2)
+
+typedef struct _mutex
+{
+	ID mtxid;
+	ID tskid;
+	int count;
+} toppersMutex;
+static toppersMutex mutexs[MAX_MUTEX] = {0};
+#endif
+
+LOCK_HANDLE Lock_Init(void)
+{
+#ifndef TOPPERS_SUPPORT_DYNAMIC_CRE
+	LogError("TOPPERS/ASP does not support lock function.");
+	return LOCK_ERROR;
+#else
+	ER_ID ret;
+	T_CMTX cmtx;
+	toppersMutex *mutex = NULL;
+
+	for (int i = 0; i < MAX_MUTEX; i++)
+	{
+		if (mutexs[i].mtxid == 0)
+		{
+			mutex = &mutexs[i];
+			break;
+		}
+	}
+
+	if (mutex == NULL)
+	{
+		LogError("Not enough memory.");
+	}
+	else
+	{
+		memset(&cmtx, 0, sizeof(cmtx));
+
+		cmtx.mtxatr = TA_TPRI;
+		cmtx.ceilpri = TASK_PRIORITY;
+
+		ret = acre_mtx(&cmtx);
+		if (ret < 0)
+		{
+			mutex->mtxid = 0;
+			mutex = NULL;
+			LogError("Failed acre_mtx(%d).", ret);
+		}
+		else
+		{
+			mutex->mtxid = (ID)ret;
+			mutex->count = 0;
+		}
+	}
+
+	return (LOCK_HANDLE *)mutex;
+#endif
+}
+
+LOCK_RESULT Lock(LOCK_HANDLE handle)
+{
+#ifndef TOPPERS_SUPPORT_DYNAMIC_CRE
+	LogError("TOPPERS/ASP does not support lock function.");
+	return LOCK_ERROR;
+#else
+	T_RMTX rmtx;
+	toppersMutex *mutex = (toppersMutex *)handle;
+	ID tskid = 0;
+	ER ret;
+
+	if (mutex == NULL)
+	{
+		LogError("Invalid argument; handle is NULL.");
+		return LOCK_ERROR;
+	}
+
+	ret = get_tid(&tskid);
+	if (ret < 0) {
+		LogError("Failed task.");
+		return LOCK_ERROR;
+	}
+
+	ret = loc_mtx(mutex->mtxid);
+	if (ret == E_OBJ)
+	{
+		mutex->count++;
+	}
+	else if (ret < 0)
+	{
+		LogError("Failed loc_mtx(%d).", mutex->mtxid);
+		return LOCK_ERROR;
+	}
+
+	mutex->tskid = tskid;
+
+	return LOCK_OK;
+#endif
+}
+
+LOCK_RESULT Unlock(LOCK_HANDLE handle)
+{
+#ifndef TOPPERS_SUPPORT_DYNAMIC_CRE
+	LogError("TOPPERS/ASP does not support lock function.");
+	return LOCK_ERROR;
+#else
+	toppersMutex *mutex = (toppersMutex *)handle;
+	ID tskid = 0;
+	ER ret;
+
+	if (mutex == NULL)
+	{
+		LogError("Invalid argument; handle is NULL.");
+		return LOCK_ERROR;
+	}
+
+	ret = get_tid(&tskid);
+	if (ret < 0) {
+		LogError("Failed task.");
+		return LOCK_ERROR;
+	}
+
+	loc_cpu();
+
+	if ((mutex->tskid == tskid) && (mutex->count > 0))
+	{
+		mutex->count--;
+		unl_cpu();
+	}
+	else
+	{
+		unl_cpu();
+
+		ret = unl_mtx(mutex->mtxid);
+		if (ret < 0)
+		{
+			LogError("Failed unl_mtx(%d).", mutex->mtxid);
+			return LOCK_ERROR;
+		}
+	}
+
+	return LOCK_OK;
+#endif
+}
+
+LOCK_RESULT Lock_Deinit(LOCK_HANDLE handle)
+{
+#ifndef TOPPERS_SUPPORT_DYNAMIC_CRE
+	LogError("TOPPERS/ASP does not support lock function.");
+	return LOCK_ERROR;
+#else
+	toppersMutex *mutex = (toppersMutex *)handle;
+	ER ret;
+
+	if (mutex == NULL)
+	{
+		LogError("Failed argument; handle is NULL.");
+		return LOCK_ERROR;
+	}
+
+	ret = del_mtx(mutex->mtxid);
+	if (ret < 0)
+	{
+		LogError("Failed del_mtx(%d).", mutex->mtxid);
+		return LOCK_ERROR;
+	}
+
+	mutex->mtxid = 0;
+
+	return LOCK_OK;
+#endif
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/platform_toppers.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/platform_toppers.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/platform_toppers.c	(revision 453)
@@ -0,0 +1,67 @@
+/*
+ *  TOPPERS PROJECT Home Network Working Group Software
+ * 
+ *  Copyright (C) 2019 Cores Co., Ltd. Japan
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+#include <stdint.h>
+#include <stdlib.h>
+#include <kernel.h>
+#include "azure_c_shared_utility/platform.h"
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/xio.h"
+#include "azure_c_shared_utility/tlsio_esp_at.h"
+#include "azure_c_shared_utility/tlsio_wolfssl.h"
+#include "target_syssvc.h"
+
+int platform_init(void)
+{
+	return 0;
+}
+
+const IO_INTERFACE_DESCRIPTION* platform_get_default_tlsio(void)
+{
+	//return tlsio_esp_at_get_interface_description();
+	return tlsio_wolfssl_get_interface_description();
+}
+
+STRING_HANDLE platform_get_platform_info(PLATFORM_INFO_OPTION options)
+{
+	// Expected format: "(<runtime name>; <operating system name>; <platform>)"
+
+	return STRING_construct("(native; TOPPERS/ASP; "TARGET_NAME")");
+}
+
+void platform_deinit(void)
+{
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/socketio_esp_at.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/socketio_esp_at.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/socketio_esp_at.c	(revision 453)
@@ -0,0 +1,496 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include "azure_c_shared_utility/socketio.h"
+#include "azure_c_shared_utility/singlylinkedlist.h"
+#include "azure_c_shared_utility/esp_at_socket.h"
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/xlogging.h"
+
+#define ESP_AT_XIO_RECEIVE_BUFFER_SIZE    128
+
+typedef enum IO_STATE_TAG
+{
+    IO_STATE_CLOSED,
+    IO_STATE_OPENING,
+    IO_STATE_OPEN,
+    IO_STATE_CLOSING,
+    IO_STATE_ERROR
+} IO_STATE;
+
+typedef struct PENDING_SOCKET_IO_TAG
+{
+    unsigned char* bytes;
+    size_t size;
+    ON_SEND_COMPLETE on_send_complete;
+    void* callback_context;
+    SINGLYLINKEDLIST_HANDLE pending_io_list;
+} PENDING_SOCKET_IO;
+
+typedef struct SOCKET_IO_INSTANCE_TAG
+{
+    ESP_AT_SOCKET_HANDLE tcp_socket_connection;
+    ON_BYTES_RECEIVED on_bytes_received;
+    ON_IO_ERROR on_io_error;
+    void* on_bytes_received_context;
+    void* on_io_error_context;
+    char* hostname;
+    int port;
+    IO_STATE io_state;
+    SINGLYLINKEDLIST_HANDLE pending_io_list;
+} SOCKET_IO_INSTANCE;
+
+/*this function will clone an option given by name and value*/
+static void* socketio_CloneOption(const char* name, const void* value)
+{
+    (void)name;
+    (void)value;
+    return NULL;
+}
+
+/*this function destroys an option previously created*/
+static void socketio_DestroyOption(const char* name, const void* value)
+{
+    (void)name;
+    (void)value;
+}
+
+static OPTIONHANDLER_HANDLE socketio_retrieveoptions(CONCRETE_IO_HANDLE socket_io)
+{
+    OPTIONHANDLER_HANDLE result;
+    (void)socket_io;
+    result = OptionHandler_Create(socketio_CloneOption, socketio_DestroyOption, socketio_setoption);
+    if (result == NULL)
+    {
+        /*return as is*/
+    }
+    else
+    {
+        /*insert here work to add the options to "result" handle*/
+    }
+    return result;
+}
+
+static const IO_INTERFACE_DESCRIPTION socket_io_interface_description =
+{
+    socketio_retrieveoptions,
+    socketio_create,
+    socketio_destroy,
+    socketio_open,
+    socketio_close,
+    socketio_send,
+    socketio_dowork,
+    socketio_setoption
+};
+
+static void indicate_error(SOCKET_IO_INSTANCE* socket_io_instance)
+{
+    if ((socket_io_instance->io_state == IO_STATE_CLOSED)
+        || (socket_io_instance->io_state == IO_STATE_ERROR))
+    {
+        return;
+    }
+    socket_io_instance->io_state = IO_STATE_ERROR;
+    if (socket_io_instance->on_io_error != NULL)
+    {
+        socket_io_instance->on_io_error(socket_io_instance->on_io_error_context);
+    }
+}
+
+static int add_pending_io(SOCKET_IO_INSTANCE* socket_io_instance, const unsigned char* buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void* callback_context)
+{
+    int result;
+    PENDING_SOCKET_IO* pending_socket_io = (PENDING_SOCKET_IO*)malloc(sizeof(PENDING_SOCKET_IO));
+    if (pending_socket_io == NULL)
+    {
+        LogError("Allocation Failure: Unable to allocate pending list.");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        pending_socket_io->bytes = (unsigned char*)malloc(size);
+        if (pending_socket_io->bytes == NULL)
+        {
+            LogError("Allocation Failure: Unable to allocate pending list.");
+            free(pending_socket_io);
+            result = MU_FAILURE;
+        }
+        else
+        {
+            pending_socket_io->size = size;
+            pending_socket_io->on_send_complete = on_send_complete;
+            pending_socket_io->callback_context = callback_context;
+            pending_socket_io->pending_io_list = socket_io_instance->pending_io_list;
+            (void)memcpy(pending_socket_io->bytes, buffer, size);
+            if (singlylinkedlist_add(socket_io_instance->pending_io_list, pending_socket_io) == NULL)
+            {
+                LogError("Failure: Unable to add socket to pending list.");
+                free(pending_socket_io->bytes);
+                free(pending_socket_io);
+                result = MU_FAILURE;
+            }
+            else
+            {
+                result = 0;
+            }
+        }
+    }
+
+    return result;
+}
+
+#define NSAPI_ERROR_WOULD_BLOCK   -3001
+
+static int retrieve_data(SOCKET_IO_INSTANCE* socket_io_instance)
+{
+    int received = 1;
+    int total_received = 0;
+
+    unsigned char* recv_bytes = malloc(ESP_AT_XIO_RECEIVE_BUFFER_SIZE);
+    if (recv_bytes == NULL)
+    {
+        LogError("Socketio_Failure: NULL allocating input buffer.");
+        indicate_error(socket_io_instance);
+        return -1;
+    }
+    
+    while (received > 0)
+    {
+        received = esp_at_socket_receive(socket_io_instance->tcp_socket_connection, (char*)recv_bytes, ESP_AT_XIO_RECEIVE_BUFFER_SIZE);
+        if (received > 0)
+        {
+            total_received += received;
+            if (socket_io_instance->on_bytes_received != NULL)
+            {
+                /* explictly ignoring here the result of the callback */
+                socket_io_instance->on_bytes_received(socket_io_instance->on_bytes_received_context, recv_bytes, received);
+            }
+        }
+        else if (received < 0)
+        {
+            if(received != NSAPI_ERROR_WOULD_BLOCK)     // NSAPI_ERROR_WOULD_BLOCK is not a real error but pending.
+            {
+                indicate_error(socket_io_instance);
+                LogError("Socketio_Failure: underlying IO error %d.", received);
+                free(recv_bytes);
+                return -1;
+            }
+        }
+    }
+    free(recv_bytes);
+    
+    return total_received;
+}
+
+static int send_queued_data(SOCKET_IO_INSTANCE* socket_io_instance)
+{
+    int errors = 0;
+    int sent = 0;
+    
+    LIST_ITEM_HANDLE first_pending_io = singlylinkedlist_get_head_item(socket_io_instance->pending_io_list);
+    while (first_pending_io != NULL)
+    {
+        PENDING_SOCKET_IO* pending_socket_io = (PENDING_SOCKET_IO*)singlylinkedlist_item_get_value(first_pending_io);
+        if (pending_socket_io == NULL)
+        {
+            indicate_error(socket_io_instance);
+            return -1;
+        }
+
+        int send_result = esp_at_socket_send(socket_io_instance->tcp_socket_connection, (const char*)pending_socket_io->bytes, pending_socket_io->size);
+        if (send_result != (int)pending_socket_io->size)
+        {
+            if (send_result == 0)
+            {
+                // The underlying network layer may encounter hardware / environment issues, 
+                // but the driver doesn't handle it properly. So here the send API always return 0, 
+                // this causes the program running into dead loop if not check it here.
+                if (errors++ >= 10)
+                {
+                    // Treat it as a network error after try 10 times.
+                    LogError("Socketio_Failure: encountered unknow connection issue, the connection will be restarted.");
+                    indicate_error(socket_io_instance);
+                    return -1;
+                }
+                ThreadAPI_Sleep(10);
+            }
+            else if (send_result < 0)
+            {
+                indicate_error(socket_io_instance);
+                return -1;
+            }
+            else
+            {
+                /* send something, wait for the rest */
+                memmove(pending_socket_io->bytes, pending_socket_io->bytes + send_result, pending_socket_io->size - send_result);
+                sent += send_result;
+            }
+        }
+        else
+        {
+            sent += send_result;
+            if (pending_socket_io->on_send_complete != NULL)
+            {
+                pending_socket_io->on_send_complete(pending_socket_io->callback_context, IO_SEND_OK);
+            }
+
+            free(pending_socket_io->bytes);
+            free(pending_socket_io);
+            if (singlylinkedlist_remove(socket_io_instance->pending_io_list, first_pending_io) != 0)
+            {
+                indicate_error(socket_io_instance);
+                return -1;
+            }
+            errors = 0;
+        }
+
+        first_pending_io = singlylinkedlist_get_head_item(socket_io_instance->pending_io_list);
+    }
+
+    return sent;
+}
+
+static void close_tcp_connection(SOCKET_IO_INSTANCE* socket_io_instance)
+{
+    if (socket_io_instance->io_state != IO_STATE_CLOSED)
+    {
+        if (socket_io_instance->tcp_socket_connection != NULL)
+        {
+            esp_at_socket_close(socket_io_instance->tcp_socket_connection);
+            esp_at_socket_destroy(socket_io_instance->tcp_socket_connection);
+            socket_io_instance->tcp_socket_connection = NULL;
+        }
+        socket_io_instance->io_state = IO_STATE_CLOSED;
+    }
+}
+
+CONCRETE_IO_HANDLE socketio_create(void* io_create_parameters)
+{
+    SOCKETIO_CONFIG* socket_io_config = io_create_parameters;
+    SOCKET_IO_INSTANCE* result;
+
+    if (socket_io_config == NULL)
+    {
+        result = NULL;
+    }
+    else
+    {    
+        result = (SOCKET_IO_INSTANCE*)malloc(sizeof(SOCKET_IO_INSTANCE));
+        if (result == NULL){
+            LogError("Socketio_Failure: NULL allocating socket io instance.");
+        }
+        else
+        {
+            result->pending_io_list = singlylinkedlist_create();
+            if (result->pending_io_list == NULL)
+            {
+                free(result);
+                result = NULL;
+            }
+            else
+            {
+                result->hostname = strdup(socket_io_config->hostname);
+                if (result->hostname == NULL)
+                {
+                    singlylinkedlist_destroy(result->pending_io_list);
+                    free(result);
+                    result = NULL;
+                }
+                else
+                {
+                    result->port = socket_io_config->port;
+                    result->on_bytes_received = NULL;
+                    result->on_io_error = NULL;
+                    result->on_bytes_received_context = NULL;
+                    result->on_io_error_context = NULL;
+                    result->io_state = IO_STATE_CLOSED;
+                    result->tcp_socket_connection = NULL;
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+void socketio_destroy(CONCRETE_IO_HANDLE socket_io)
+{
+    if (socket_io != NULL)
+    {
+        SOCKET_IO_INSTANCE* socket_io_instance = (SOCKET_IO_INSTANCE*)socket_io;
+
+        // Close the tcp connection
+        close_tcp_connection(socket_io_instance);
+    
+        // Clear all pending IOs
+        LIST_ITEM_HANDLE first_pending_io = singlylinkedlist_get_head_item(socket_io_instance->pending_io_list);
+        while (first_pending_io != NULL)
+        {
+            PENDING_SOCKET_IO* pending_socket_io = (PENDING_SOCKET_IO*)singlylinkedlist_item_get_value(first_pending_io);
+            if (pending_socket_io != NULL)
+            {
+                free(pending_socket_io->bytes);
+                free(pending_socket_io);
+            }
+
+            (void)singlylinkedlist_remove(socket_io_instance->pending_io_list, first_pending_io);
+            first_pending_io = singlylinkedlist_get_head_item(socket_io_instance->pending_io_list);
+        }
+        singlylinkedlist_destroy(socket_io_instance->pending_io_list);
+    
+        if(socket_io_instance->hostname != NULL)
+        {
+            free(socket_io_instance->hostname);
+            socket_io_instance->hostname = NULL;
+        }
+        free(socket_io);
+    }
+}
+
+int socketio_open(CONCRETE_IO_HANDLE socket_io, ON_IO_OPEN_COMPLETE on_io_open_complete, void* on_io_open_complete_context, ON_BYTES_RECEIVED on_bytes_received, void* on_bytes_received_context, ON_IO_ERROR on_io_error, void* on_io_error_context)
+{
+    int result;
+    SOCKET_IO_INSTANCE* socket_io_instance = (SOCKET_IO_INSTANCE*)socket_io;
+    
+
+    if (socket_io_instance == NULL ||
+        socket_io_instance->io_state != IO_STATE_CLOSED)
+    {
+        result = MU_FAILURE;
+    }
+    else
+    {
+        socket_io_instance->tcp_socket_connection = esp_at_socket_create(false);
+        if (socket_io_instance->tcp_socket_connection == NULL)
+        {
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if (esp_at_socket_connect(socket_io_instance->tcp_socket_connection, socket_io_instance->hostname, socket_io_instance->port) != 0)
+            {
+                esp_at_socket_destroy(socket_io_instance->tcp_socket_connection);
+                socket_io_instance->tcp_socket_connection = NULL;
+                result = MU_FAILURE;
+            }
+            else
+            {
+                esp_at_socket_set_blocking(socket_io_instance->tcp_socket_connection, false, 0);
+
+                socket_io_instance->on_bytes_received = on_bytes_received;
+                socket_io_instance->on_bytes_received_context = on_bytes_received_context;
+
+                socket_io_instance->on_io_error = on_io_error;
+                socket_io_instance->on_io_error_context = on_io_error_context;
+
+                socket_io_instance->io_state = IO_STATE_OPEN;
+
+                result = 0;
+            }
+        }
+    }
+    
+    if (on_io_open_complete != NULL)
+    {
+        on_io_open_complete(on_io_open_complete_context, result == 0 ? IO_OPEN_OK : IO_OPEN_ERROR);
+    }
+
+    return result;
+}
+
+int socketio_close(CONCRETE_IO_HANDLE socket_io, ON_IO_CLOSE_COMPLETE on_io_close_complete, void* callback_context)
+{
+    int result = 0;
+
+    if (socket_io == NULL)
+    {
+        result = MU_FAILURE;
+    }
+    else
+    {
+        SOCKET_IO_INSTANCE* socket_io_instance = (SOCKET_IO_INSTANCE*)socket_io;
+        if (socket_io_instance->io_state == IO_STATE_CLOSED || 
+            socket_io_instance->io_state == IO_STATE_ERROR)
+        {
+            result = MU_FAILURE;
+        }
+        else
+        {
+            close_tcp_connection(socket_io_instance);
+            if (on_io_close_complete != NULL)
+            {
+                on_io_close_complete(callback_context);
+            }
+            result = 0;
+        }
+    }
+    
+    return result;
+}
+
+int socketio_send(CONCRETE_IO_HANDLE socket_io, const void* buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void* callback_context)
+{
+    int result;
+
+    if ((socket_io == NULL) ||
+        (buffer == NULL) ||
+        (size == 0))
+    {
+        /* Invalid arguments */
+        result = MU_FAILURE;
+    }
+    else
+    {
+        result = 0;
+
+        SOCKET_IO_INSTANCE* socket_io_instance = (SOCKET_IO_INSTANCE*)socket_io;
+        if (socket_io_instance->io_state != IO_STATE_OPEN)
+        {
+            result = MU_FAILURE;
+        }
+        else
+        {
+            // Queue the data, and the socketio_dowork sends the package later
+            if (add_pending_io(socket_io_instance, buffer, size, on_send_complete, callback_context) != 0)
+            {
+                result = MU_FAILURE;
+            }
+        }
+    }
+
+    return result;
+}
+
+void socketio_dowork(CONCRETE_IO_HANDLE socket_io)
+{
+    if (socket_io != NULL)
+    {
+        SOCKET_IO_INSTANCE* socket_io_instance = (SOCKET_IO_INSTANCE*)socket_io;
+        if (socket_io_instance->io_state == IO_STATE_OPEN)
+        {
+            // Retrieve all data from IoT Hub
+            if (retrieve_data(socket_io_instance) < 0)
+            {
+                return;
+            }
+        
+            // Send all packages in the queue
+            send_queued_data(socket_io_instance);
+        }
+    }
+}
+
+int socketio_setoption(CONCRETE_IO_HANDLE socket_io, const char* optionName, const void* value)
+{
+    /* Not implementing any options, do nothing */
+    return OPTIONHANDLER_OK;
+}
+
+const IO_INTERFACE_DESCRIPTION* socketio_get_interface_description(void)
+{
+    return &socket_io_interface_description;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/socketio_lwip.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/socketio_lwip.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/socketio_lwip.c	(revision 453)
@@ -0,0 +1,1222 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef _BSD_SOURCE
+#define _BSD_SOURCE
+#define SOCKETIO_BERKELEY_UNDEF_BSD_SOURCE
+#endif
+
+#define _DEFAULT_SOURCE
+#include <net/if.h>
+#undef _DEFAULT_SOURCE
+
+#ifdef SOCKETIO_BERKELEY_UNDEF_BSD_SOURCE
+#undef _BSD_SOURCE
+#undef SOCKETIO_BERKELEY_UNDEF_BSD_SOURCE
+#endif
+
+#include <signal.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include "azure_c_shared_utility/socketio.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#ifdef TIZENRT
+#include <net/lwip/tcp.h>
+#else
+#include <lwip/tcp.h>
+#endif
+#include <netdb.h>
+#include <unistd.h>
+#include <errno.h>
+#include "azure_c_shared_utility/singlylinkedlist.h"
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/gbnetwork.h"
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/optionhandler.h"
+#include "azure_c_shared_utility/shared_util_options.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/const_defines.h"
+#include "azure_c_shared_utility/dns_resolver.h"
+//#include <sys/ioctl.h>
+//#include <netinet/in.h>
+//#include <arpa/inet.h>
+//#include <sys/un.h>
+
+#define SOCKET_SUCCESS                 0
+#define INVALID_SOCKET                 -1
+#define SOCKET_SEND_FAILURE            -1
+#define MAC_ADDRESS_STRING_LENGTH      18
+
+#ifndef IFREQ_BUFFER_SIZE
+#define IFREQ_BUFFER_SIZE              1024
+#endif
+
+// connect timeout in seconds
+#define CONNECT_TIMEOUT         10
+
+typedef enum IO_STATE_TAG
+{
+    IO_STATE_CLOSED,
+    IO_STATE_OPENING,
+    IO_STATE_OPEN,
+    IO_STATE_CLOSING,
+    IO_STATE_ERROR
+} IO_STATE;
+
+typedef struct PENDING_SOCKET_IO_TAG
+{
+    unsigned char* bytes;
+    size_t size;
+    ON_SEND_COMPLETE on_send_complete;
+    void* callback_context;
+    SINGLYLINKEDLIST_HANDLE pending_io_list;
+} PENDING_SOCKET_IO;
+
+typedef struct SOCKET_IO_INSTANCE_TAG
+{
+    int socket;
+    SOCKETIO_ADDRESS_TYPE address_type;
+    ON_BYTES_RECEIVED on_bytes_received;
+    ON_IO_ERROR on_io_error;
+    ON_IO_OPEN_COMPLETE on_io_open_complete;
+    void* on_bytes_received_context;
+    void* on_io_error_context;
+    void* on_io_open_complete_context;
+    char* hostname;
+    int port;
+    char* target_mac_address;
+    IO_STATE io_state;
+    SINGLYLINKEDLIST_HANDLE pending_io_list;
+    unsigned char recv_bytes[RECEIVE_BYTES_VALUE];
+    DNSRESOLVER_HANDLE dns_resolver;
+} SOCKET_IO_INSTANCE;
+
+typedef struct NETWORK_INTERFACE_DESCRIPTION_TAG
+{
+    char* name;
+    char* mac_address;
+    char* ip_address;
+    struct NETWORK_INTERFACE_DESCRIPTION_TAG* next;
+} NETWORK_INTERFACE_DESCRIPTION;
+
+/*this function will clone an option given by name and value*/
+static void* socketio_CloneOption(const char* name, const void* value)
+{
+    void* result;
+
+    if (name != NULL)
+    {
+        result = NULL;
+
+        if (strcmp(name, OPTION_NET_INT_MAC_ADDRESS) == 0)
+        {
+            if (value == NULL)
+            {
+                LogError("Failed cloning option %s (value is NULL)", name);
+            }
+            else
+            {
+                if ((result = malloc(sizeof(char) * (strlen((char*)value) + 1))) == NULL)
+                {
+                    LogError("Failed cloning option %s (malloc failed)", name);
+                }
+                else if (strcpy((char*)result, (char*)value) == NULL)
+                {
+                    LogError("Failed cloning option %s (strcpy failed)", name);
+                    free(result);
+                    result = NULL;
+                }
+            }
+        }
+        else
+        {
+            LogError("Cannot clone option %s (not suppported)", name);
+        }
+    }
+    else
+    {
+        result = NULL;
+    }
+    return result;
+}
+
+/*this function destroys an option previously created*/
+static void socketio_DestroyOption(const char* name, const void* value)
+{
+    if (name != NULL)
+    {
+        if (strcmp(name, OPTION_NET_INT_MAC_ADDRESS) == 0 && value != NULL)
+        {
+            free((void*)value);
+        }
+    }
+}
+
+static OPTIONHANDLER_HANDLE socketio_retrieveoptions(CONCRETE_IO_HANDLE handle)
+{
+    OPTIONHANDLER_HANDLE result;
+
+    if (handle == NULL)
+    {
+        LogError("failed retrieving options (handle is NULL)");
+        result = NULL;
+    }
+    else
+    {
+        SOCKET_IO_INSTANCE* socket_io_instance = (SOCKET_IO_INSTANCE*)handle;
+
+        result = OptionHandler_Create(socketio_CloneOption, socketio_DestroyOption, socketio_setoption);
+        if (result == NULL)
+        {
+            LogError("unable to OptionHandler_Create");
+        }
+        else if (socket_io_instance->target_mac_address != NULL &&
+            OptionHandler_AddOption(result, OPTION_NET_INT_MAC_ADDRESS, socket_io_instance->target_mac_address) != OPTIONHANDLER_OK)
+        {
+            LogError("failed retrieving options (failed adding net_interface_mac_address)");
+            OptionHandler_Destroy(result);
+            result = NULL;
+        }
+    }
+
+    return result;
+}
+
+static const IO_INTERFACE_DESCRIPTION socket_io_interface_description =
+{
+    socketio_retrieveoptions,
+    socketio_create,
+    socketio_destroy,
+    socketio_open,
+    socketio_close,
+    socketio_send,
+    socketio_dowork,
+    socketio_setoption
+};
+
+static void indicate_error(SOCKET_IO_INSTANCE* socket_io_instance)
+{
+    socket_io_instance->io_state = IO_STATE_ERROR;
+    if (socket_io_instance->on_io_error != NULL)
+    {
+        socket_io_instance->on_io_error(socket_io_instance->on_io_error_context);
+    }
+}
+
+static int add_pending_io(SOCKET_IO_INSTANCE* socket_io_instance, const unsigned char* buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void* callback_context)
+{
+    int result;
+    PENDING_SOCKET_IO* pending_socket_io = (PENDING_SOCKET_IO*)malloc(sizeof(PENDING_SOCKET_IO));
+    if (pending_socket_io == NULL)
+    {
+        result = MU_FAILURE;
+    }
+    else
+    {
+        pending_socket_io->bytes = (unsigned char*)malloc(size);
+        if (pending_socket_io->bytes == NULL)
+        {
+            LogError("Allocation Failure: Unable to allocate pending list.");
+            free(pending_socket_io);
+            result = MU_FAILURE;
+        }
+        else
+        {
+            pending_socket_io->size = size;
+            pending_socket_io->on_send_complete = on_send_complete;
+            pending_socket_io->callback_context = callback_context;
+            pending_socket_io->pending_io_list = socket_io_instance->pending_io_list;
+            (void)memcpy(pending_socket_io->bytes, buffer, size);
+
+            if (singlylinkedlist_add(socket_io_instance->pending_io_list, pending_socket_io) == NULL)
+            {
+                LogError("Failure: Unable to add socket to pending list.");
+                free(pending_socket_io->bytes);
+                free(pending_socket_io);
+                result = MU_FAILURE;
+            }
+            else
+            {
+                result = 0;
+            }
+        }
+    }
+    return result;
+}
+
+static STATIC_VAR_UNUSED void signal_callback(int signum)
+{
+    AZURE_UNREFERENCED_PARAMETER(signum);
+    LogError("Socket received signal %d.", signum);
+}
+
+static int lookup_address(SOCKET_IO_INSTANCE* socket_io_instance)
+{
+    int result = 0;
+
+    if (socket_io_instance->address_type == ADDRESS_TYPE_IP)
+    {
+        if (!dns_resolver_is_lookup_complete(socket_io_instance->dns_resolver))
+        {
+            socket_io_instance->io_state = IO_STATE_OPENING;
+        }
+        else
+        {
+            socket_io_instance->io_state = IO_STATE_OPEN;
+        }
+    }
+    else //ADDRESS_TYPE_DOMAIN_SOCKET
+    {
+        socket_io_instance->io_state = IO_STATE_OPEN;
+    }
+
+    return result;
+}
+
+static int initiate_socket_connection(SOCKET_IO_INSTANCE* socket_io_instance)
+{
+    int result;
+    int flags;
+    struct addrinfo* addr = NULL;
+    struct sockaddr* connect_addr = NULL;
+    struct sockaddr_un addrInfoUn;
+    socklen_t connect_addr_len;
+
+    if (socket_io_instance->address_type == ADDRESS_TYPE_IP)
+    {
+        if(!dns_resolver_is_lookup_complete(socket_io_instance->dns_resolver))
+        {
+            LogError("DNS did not resolve IP address");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            addr = dns_resolver_get_addrInfo(socket_io_instance->dns_resolver);
+
+            if (addr == NULL)
+            {
+                LogError("DNS resolution failed");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                connect_addr = addr->ai_addr;
+                connect_addr_len = sizeof(*addr->ai_addr);
+                result = 0;
+            }
+        }
+    }
+    else
+    {
+        size_t hostname_len = strlen(socket_io_instance->hostname);
+        if (hostname_len + 1 > sizeof(addrInfoUn.sun_path))
+        {
+            LogError("Hostname %s is too long for a unix socket (max len = %lu)", socket_io_instance->hostname, (unsigned long)sizeof(addrInfoUn.sun_path));
+            result = MU_FAILURE;
+        }
+        else
+        {
+            memset(&addrInfoUn, 0, sizeof(addrInfoUn));
+            addrInfoUn.sun_family = AF_UNIX;
+            // No need to add NULL terminator due to the above memset
+            (void)memcpy(addrInfoUn.sun_path, socket_io_instance->hostname, hostname_len);
+
+            connect_addr = (struct sockaddr*)&addrInfoUn;
+            connect_addr_len = sizeof(addrInfoUn);
+            result = 0;
+        }
+    }
+
+    if (result == 0)
+    {
+        if ((-1 == (flags = fcntl(socket_io_instance->socket, F_GETFL, 0))) ||
+            (fcntl(socket_io_instance->socket, F_SETFL, flags | O_NONBLOCK) == -1))
+        {
+            LogError("Failure: fcntl failure.");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            result = connect(socket_io_instance->socket, connect_addr, connect_addr_len);
+            if ((result != 0) && (errno != EINPROGRESS))
+            {
+                LogError("Failure: connect failure %d.", errno);
+                result = MU_FAILURE;
+            }
+            else
+            {
+                // Async connect will return -1.
+                result = 0;
+                if (socket_io_instance->on_io_open_complete != NULL)
+                {
+                    socket_io_instance->on_io_open_complete(socket_io_instance->on_io_open_complete_context, IO_OPEN_OK /*: IO_OPEN_ERROR*/);
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+static int lookup_address_and_initiate_socket_connection(SOCKET_IO_INSTANCE* socket_io_instance)
+{
+    int result;
+
+    result = lookup_address(socket_io_instance);
+
+    if(socket_io_instance->io_state == IO_STATE_OPEN)
+    {
+        if (result == 0)
+        {
+            result = initiate_socket_connection(socket_io_instance);
+        }
+    }
+
+    return result;
+}
+
+static int wait_for_connection(SOCKET_IO_INSTANCE* socket_io_instance)
+{
+    int result;
+    int err;
+    int retval;
+    int select_errno = 0;
+
+    fd_set fdset;
+    struct timeval tv;
+
+    FD_ZERO(&fdset);
+    FD_SET(socket_io_instance->socket, &fdset);
+    tv.tv_sec = CONNECT_TIMEOUT;
+    tv.tv_usec = 0;
+
+    do
+    {
+        retval = select(socket_io_instance->socket + 1, NULL, &fdset, NULL, &tv);
+
+        if (retval < 0)
+        {
+            select_errno = errno;
+        }
+    } while (retval < 0 && select_errno == EINTR);
+
+    if (retval != 1)
+    {
+        LogError("Failure: select failure.");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        int so_error = 0;
+        socklen_t len = sizeof(so_error);
+        err = getsockopt(socket_io_instance->socket, SOL_SOCKET, SO_ERROR, &so_error, &len);
+        if (err != 0)
+        {
+            LogError("Failure: getsockopt failure %d.", errno);
+            result = MU_FAILURE;
+        }
+        else if (so_error != 0)
+        {
+            err = so_error;
+            LogError("Failure: connect failure %d.", so_error);
+            result = MU_FAILURE;
+        }
+        else
+        {
+            result = 0;
+        }
+    }
+
+    return result;
+}
+
+
+
+#ifndef __APPLE__
+static void destroy_network_interface_descriptions(NETWORK_INTERFACE_DESCRIPTION* nid)
+{
+    if (nid != NULL)
+    {
+        if (nid->next != NULL)
+        {
+            destroy_network_interface_descriptions(nid->next);
+        }
+
+        if (nid->name != NULL)
+        {
+            free(nid->name);
+        }
+
+        if (nid->mac_address != NULL)
+        {
+            free(nid->mac_address);
+        }
+
+        if (nid->ip_address != NULL)
+        {
+            free(nid->ip_address);
+        }
+
+        free(nid);
+    }
+}
+
+static NETWORK_INTERFACE_DESCRIPTION* create_network_interface_description(struct ifreq *ifr, NETWORK_INTERFACE_DESCRIPTION* previous_nid)
+{
+    NETWORK_INTERFACE_DESCRIPTION* result;
+
+    if ((result = (NETWORK_INTERFACE_DESCRIPTION*)malloc(sizeof(NETWORK_INTERFACE_DESCRIPTION))) == NULL)
+    {
+        LogError("Failed allocating NETWORK_INTERFACE_DESCRIPTION");
+    }
+    else if ((result->name = (char*)malloc(sizeof(char) * (strlen(ifr->ifr_name) + 1))) == NULL)
+    {
+        LogError("failed setting interface description name (malloc failed)");
+        destroy_network_interface_descriptions(result);
+        result = NULL;
+    }
+    else if (strcpy(result->name, ifr->ifr_name) == NULL)
+    {
+        LogError("failed setting interface description name (strcpy failed)");
+        destroy_network_interface_descriptions(result);
+        result = NULL;
+    }
+    else
+    {
+        char* ip_address;
+        unsigned char* mac = (unsigned char*)ifr->ifr_hwaddr.sa_data;
+
+        if ((result->mac_address = (char*)malloc(sizeof(char) * MAC_ADDRESS_STRING_LENGTH)) == NULL)
+        {
+            LogError("failed formatting mac address (malloc failed)");
+            destroy_network_interface_descriptions(result);
+            result = NULL;
+        }
+        else if (sprintf(result->mac_address, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]) <= 0)
+        {
+            LogError("failed formatting mac address (sprintf failed)");
+            destroy_network_interface_descriptions(result);
+            result = NULL;
+        }
+        else if ((ip_address = inet_ntoa(((struct sockaddr_in*)&ifr->ifr_addr)->sin_addr)) == NULL)
+        {
+            LogError("failed setting the ip address (inet_ntoa failed)");
+            destroy_network_interface_descriptions(result);
+            result = NULL;
+        }
+        else if ((result->ip_address = (char*)malloc(sizeof(char) * (strlen(ip_address) + 1))) == NULL)
+        {
+            LogError("failed setting the ip address (malloc failed)");
+            destroy_network_interface_descriptions(result);
+            result = NULL;
+        }
+        else if (strcpy(result->ip_address, ip_address) == NULL)
+        {
+            LogError("failed setting the ip address (strcpy failed)");
+            destroy_network_interface_descriptions(result);
+            result = NULL;
+        }
+        else
+        {
+            result->next = NULL;
+
+            if (previous_nid != NULL)
+            {
+                previous_nid->next = result;
+            }
+        }
+    }
+
+    return result;
+}
+
+static int get_network_interface_descriptions(int socket, NETWORK_INTERFACE_DESCRIPTION** nid)
+{
+    int result;
+
+    struct ifreq ifr;
+    struct ifconf ifc;
+    char buf[IFREQ_BUFFER_SIZE];
+
+    ifc.ifc_len = sizeof(buf);
+    ifc.ifc_buf = buf;
+
+    if (ioctl(socket, SIOCGIFCONF, &ifc) == -1)
+    {
+        LogError("ioctl failed querying socket (SIOCGIFCONF, errno=%d)", errno);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        NETWORK_INTERFACE_DESCRIPTION* root_nid = NULL;
+        NETWORK_INTERFACE_DESCRIPTION* new_nid = NULL;
+
+        struct ifreq* it = ifc.ifc_req;
+        const struct ifreq* const end = it + (ifc.ifc_len / sizeof(struct ifreq));
+
+        result = 0;
+
+        for (; it != end; ++it)
+        {
+            strcpy(ifr.ifr_name, it->ifr_name);
+
+            if (ioctl(socket, SIOCGIFFLAGS, &ifr) != 0)
+            {
+                LogError("ioctl failed querying socket (SIOCGIFFLAGS, errno=%d)", errno);
+                result = MU_FAILURE;
+                break;
+            }
+            else if (ioctl(socket, SIOCGIFHWADDR, &ifr) != 0)
+            {
+                LogError("ioctl failed querying socket (SIOCGIFHWADDR, errno=%d)", errno);
+                result = MU_FAILURE;
+                break;
+            }
+            else if (ioctl(socket, SIOCGIFADDR, &ifr) != 0)
+            {
+                LogError("ioctl failed querying socket (SIOCGIFADDR, errno=%d)", errno);
+                result = MU_FAILURE;
+                break;
+            }
+            else if ((new_nid = create_network_interface_description(&ifr, new_nid)) == NULL)
+            {
+                LogError("Failed creating network interface description");
+                result = MU_FAILURE;
+                break;
+            }
+            else if (root_nid == NULL)
+            {
+                root_nid = new_nid;
+            }
+        }
+
+        if (result == 0)
+        {
+            *nid = root_nid;
+        }
+        else
+        {
+            destroy_network_interface_descriptions(root_nid);
+        }
+    }
+
+    return result;
+}
+
+static int set_target_network_interface(int socket, char* mac_address)
+{
+    int result;
+    NETWORK_INTERFACE_DESCRIPTION* nid;
+
+    if (get_network_interface_descriptions(socket, &nid) != 0)
+    {
+        LogError("Failed getting network interface descriptions");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        NETWORK_INTERFACE_DESCRIPTION* current_nid = nid;
+
+        while(current_nid != NULL)
+        {
+            if (strcmp(mac_address, current_nid->mac_address) == 0)
+            {
+                break;
+            }
+
+            current_nid = current_nid->next;
+        }
+
+        if (current_nid == NULL)
+        {
+            LogError("Did not find a network interface matching MAC ADDRESS");
+            result = MU_FAILURE;
+        }
+        else if (setsockopt(socket, SOL_SOCKET, SO_BINDTODEVICE, current_nid->name, strlen(current_nid->name)) != 0)
+        {
+            LogError("setsockopt failed (%d)", errno);
+            result = MU_FAILURE;
+        }
+        else
+        {
+            result = 0;
+        }
+
+        destroy_network_interface_descriptions(nid);
+    }
+
+    return result;
+}
+#endif //__APPLE__
+
+static void destroy_socket_io_instance(SOCKET_IO_INSTANCE* instance)
+{
+    if (instance->dns_resolver != NULL)
+    {
+        dns_resolver_destroy(instance->dns_resolver);
+    }
+
+    free(instance->hostname);
+    free(instance->target_mac_address);
+
+    if (instance->pending_io_list != NULL)
+    {
+        singlylinkedlist_destroy(instance->pending_io_list);
+    }
+
+    free(instance);
+}
+
+CONCRETE_IO_HANDLE socketio_create(void* io_create_parameters)
+{
+    SOCKETIO_CONFIG* socket_io_config = io_create_parameters;
+    SOCKET_IO_INSTANCE* result;
+
+    if (socket_io_config == NULL)
+    {
+        LogError("Invalid argument: socket_io_config is NULL");
+        result = NULL;
+    }
+    else
+    {
+        result = malloc(sizeof(SOCKET_IO_INSTANCE));
+        if (result != NULL)
+        {
+            (void)memset(result, 0, sizeof(SOCKET_IO_INSTANCE));
+
+            result->address_type = ADDRESS_TYPE_IP;
+            result->pending_io_list = singlylinkedlist_create();
+            if (result->pending_io_list == NULL)
+            {
+                LogError("Failure: singlylinkedlist_create unable to create pending list.");
+                destroy_socket_io_instance(result);
+                result = NULL;
+            }
+            else
+            {
+                if (socket_io_config->hostname != NULL)
+                {
+                    result->hostname = (char*)malloc(strlen(socket_io_config->hostname) + 1);
+                    if (result->hostname != NULL)
+                    {
+                        (void)strcpy(result->hostname, socket_io_config->hostname);
+                    }
+
+                    result->socket = INVALID_SOCKET;
+                }
+                else
+                {
+                    result->hostname = NULL;
+                    result->socket = *((int*)socket_io_config->accepted_socket);
+                }
+
+                if ((result->hostname == NULL) && (result->socket == INVALID_SOCKET))
+                {
+                    LogError("Failure: hostname == NULL and socket is invalid.");
+                    destroy_socket_io_instance(result);
+                    result = NULL;
+                }
+                else
+                {
+                    result->port = socket_io_config->port;
+                    result->on_io_open_complete = NULL;
+                    result->dns_resolver = dns_resolver_create(result->hostname, socket_io_config->port, NULL);
+                    result->target_mac_address = NULL;
+                    result->on_bytes_received = NULL;
+                    result->on_io_error = NULL;
+                    result->on_bytes_received_context = NULL;
+                    result->on_io_error_context = NULL;
+                    result->io_state = IO_STATE_CLOSED;
+                }
+            }
+        }
+        else
+        {
+            LogError("Allocation Failure: SOCKET_IO_INSTANCE");
+        }
+    }
+
+    return result;
+}
+
+void socketio_destroy(CONCRETE_IO_HANDLE socket_io)
+{
+    if (socket_io != NULL)
+    {
+        SOCKET_IO_INSTANCE* socket_io_instance = (SOCKET_IO_INSTANCE*)socket_io;
+        /* we cannot do much if the close fails, so just ignore the result */
+        if (socket_io_instance->socket != INVALID_SOCKET)
+        {
+            close(socket_io_instance->socket);
+        }
+
+        /* clear allpending IOs */
+        LIST_ITEM_HANDLE first_pending_io = singlylinkedlist_get_head_item(socket_io_instance->pending_io_list);
+        while (first_pending_io != NULL)
+        {
+            PENDING_SOCKET_IO* pending_socket_io = (PENDING_SOCKET_IO*)singlylinkedlist_item_get_value(first_pending_io);
+            if (pending_socket_io != NULL)
+            {
+                free(pending_socket_io->bytes);
+                free(pending_socket_io);
+            }
+
+            (void)singlylinkedlist_remove(socket_io_instance->pending_io_list, first_pending_io);
+            first_pending_io = singlylinkedlist_get_head_item(socket_io_instance->pending_io_list);
+        }
+
+        destroy_socket_io_instance(socket_io_instance);
+    }
+}
+
+int socketio_open(CONCRETE_IO_HANDLE socket_io, ON_IO_OPEN_COMPLETE on_io_open_complete, void* on_io_open_complete_context, ON_BYTES_RECEIVED on_bytes_received, void* on_bytes_received_context, ON_IO_ERROR on_io_error, void* on_io_error_context)
+{
+    int result;
+
+    SOCKET_IO_INSTANCE* socket_io_instance = (SOCKET_IO_INSTANCE*)socket_io;
+    if (socket_io == NULL)
+    {
+        LogError("Invalid argument: SOCKET_IO_INSTANCE is NULL");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        if (socket_io_instance->io_state != IO_STATE_CLOSED)
+        {
+            LogError("Failure: socket state is not closed.");
+            result = MU_FAILURE;
+        }
+        else if (socket_io_instance->socket != INVALID_SOCKET)
+        {
+            // Opening an accepted socket
+            socket_io_instance->on_bytes_received_context = on_bytes_received_context;
+            socket_io_instance->on_bytes_received = on_bytes_received;
+            socket_io_instance->on_io_error = on_io_error;
+            socket_io_instance->on_io_error_context = on_io_error_context;
+
+            socket_io_instance->io_state = IO_STATE_OPEN;
+
+            result = 0;
+        }
+        else
+        {
+            socket_io_instance->socket = socket (socket_io_instance->address_type == ADDRESS_TYPE_IP ? AF_INET : AF_UNIX, SOCK_STREAM, 0);
+            if (socket_io_instance->socket < SOCKET_SUCCESS)
+            {
+                LogError("Failure: socket create failure %d.", socket_io_instance->socket);
+                result = MU_FAILURE;
+            }
+#ifndef __APPLE__
+            else if (socket_io_instance->target_mac_address != NULL &&
+                     set_target_network_interface(socket_io_instance->socket, socket_io_instance->target_mac_address) != 0)
+            {
+                LogError("Failure: failed selecting target network interface (MACADDR=%s).", socket_io_instance->target_mac_address);
+                result = MU_FAILURE;
+            }
+#endif //__APPLE__
+            else if ((result = lookup_address_and_initiate_socket_connection(socket_io_instance)) != 0)
+            {
+                LogError("lookup_address_and_connect_socket failed");
+            }
+            else if ((result = wait_for_connection(socket_io_instance)) != 0)
+            {
+                LogError("wait_for_connection failed");
+            }
+
+            if (result == 0)
+            {
+                socket_io_instance->on_bytes_received = on_bytes_received;
+                socket_io_instance->on_bytes_received_context = on_bytes_received_context;
+
+                socket_io_instance->on_io_error = on_io_error;
+                socket_io_instance->on_io_error_context = on_io_error_context;
+
+                socket_io_instance->on_io_open_complete = on_io_open_complete;
+                socket_io_instance->on_io_open_complete_context = on_io_open_complete_context;
+            }
+            else
+            {
+                if (socket_io_instance->socket >= SOCKET_SUCCESS)
+                {
+                    close(socket_io_instance->socket);
+                }
+                socket_io_instance->socket = INVALID_SOCKET;
+            }
+        }
+    }
+
+    if (socket_io_instance->io_state != IO_STATE_OPENING)
+    {
+        if (on_io_open_complete != NULL)
+        {
+            on_io_open_complete(on_io_open_complete_context, result == 0 ? IO_OPEN_OK : IO_OPEN_ERROR);
+        }
+    }
+
+    return result;
+}
+
+int socketio_close(CONCRETE_IO_HANDLE socket_io, ON_IO_CLOSE_COMPLETE on_io_close_complete, void* callback_context)
+{
+    int result = 0;
+
+    if (socket_io == NULL)
+    {
+        result = MU_FAILURE;
+    }
+    else
+    {
+        SOCKET_IO_INSTANCE* socket_io_instance = (SOCKET_IO_INSTANCE*)socket_io;
+        if ((socket_io_instance->io_state != IO_STATE_CLOSED) && (socket_io_instance->io_state != IO_STATE_CLOSING))
+        {
+            // Only close if the socket isn't already in the closed or closing state
+            (void)shutdown(socket_io_instance->socket, SHUT_RDWR);
+            close(socket_io_instance->socket);
+            socket_io_instance->socket = INVALID_SOCKET;
+            socket_io_instance->io_state = IO_STATE_CLOSED;
+        }
+
+        if (on_io_close_complete != NULL)
+        {
+            on_io_close_complete(callback_context);
+        }
+
+        result = 0;
+    }
+
+    return result;
+}
+
+int socketio_send(CONCRETE_IO_HANDLE socket_io, const void* buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void* callback_context)
+{
+    int result;
+
+    if ((socket_io == NULL) ||
+        (buffer == NULL) ||
+        (size == 0))
+    {
+        /* Invalid arguments */
+        LogError("Invalid argument: send given invalid parameter");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        SOCKET_IO_INSTANCE* socket_io_instance = (SOCKET_IO_INSTANCE*)socket_io;
+        if (socket_io_instance->io_state != IO_STATE_OPEN)
+        {
+            LogError("Failure: socket state is not opened.");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            LIST_ITEM_HANDLE first_pending_io = singlylinkedlist_get_head_item(socket_io_instance->pending_io_list);
+            if (first_pending_io != NULL)
+            {
+                if (add_pending_io(socket_io_instance, buffer, size, on_send_complete, callback_context) != 0)
+                {
+                    LogError("Failure: add_pending_io failed.");
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    result = 0;
+                }
+            }
+            else
+            {
+                signal(SIGPIPE, SIG_IGN);
+
+                ssize_t send_result = send(socket_io_instance->socket, buffer, size, 0);
+                if ((size_t)send_result != size)
+                {
+                    if (send_result == SOCKET_SEND_FAILURE && errno != EAGAIN)
+                    {
+                        LogError("Failure: sending socket failed. errno=%d (%s).", errno, strerror(errno));
+                        result = MU_FAILURE;
+                    }
+                    else
+                    {
+                        /*send says "come back later" with EAGAIN - likely the socket buffer cannot accept more data*/
+                        /* queue data */
+                        size_t bytes_sent = (send_result < 0 ? 0 : send_result);
+
+                        if (add_pending_io(socket_io_instance, buffer + bytes_sent, size - bytes_sent, on_send_complete, callback_context) != 0)
+                        {
+                            LogError("Failure: add_pending_io failed.");
+                            result = MU_FAILURE;
+                        }
+                        else
+                        {
+                            result = 0;
+                        }
+                    }
+                }
+                else
+                {
+                    if (on_send_complete != NULL)
+                    {
+                        on_send_complete(callback_context, IO_SEND_OK);
+                    }
+
+                    result = 0;
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+void socketio_dowork(CONCRETE_IO_HANDLE socket_io)
+{
+    if (socket_io != NULL)
+    {
+        SOCKET_IO_INSTANCE* socket_io_instance = (SOCKET_IO_INSTANCE*)socket_io;
+        signal(SIGPIPE, SIG_IGN);
+
+        if (socket_io_instance->io_state == IO_STATE_OPEN)
+        {
+            LIST_ITEM_HANDLE first_pending_io = singlylinkedlist_get_head_item(socket_io_instance->pending_io_list);
+            while (first_pending_io != NULL)
+            {
+                PENDING_SOCKET_IO* pending_socket_io = (PENDING_SOCKET_IO*)singlylinkedlist_item_get_value(first_pending_io);
+                if (pending_socket_io == NULL)
+                {
+                    indicate_error(socket_io_instance);
+                    LogError("Failure: retrieving socket from list");
+                    break;
+                }
+
+                ssize_t send_result = send(socket_io_instance->socket, pending_socket_io->bytes, pending_socket_io->size, 0);
+                if ((send_result < 0) || ((size_t)send_result != pending_socket_io->size))
+                {
+                    if (send_result == INVALID_SOCKET)
+                    {
+                        if (errno == EAGAIN) /*send says "come back later" with EAGAIN - likely the socket buffer cannot accept more data*/
+                        {
+                            /*do nothing until next dowork */
+                            break;
+                        }
+                        else
+                        {
+                            free(pending_socket_io->bytes);
+                            free(pending_socket_io);
+                            (void)singlylinkedlist_remove(socket_io_instance->pending_io_list, first_pending_io);
+
+                            LogError("Failure: sending Socket information. errno=%d (%s).", errno, strerror(errno));
+                            indicate_error(socket_io_instance);
+                        }
+                    }
+                    else
+                    {
+                        /* simply wait until next dowork */
+                        (void)memmove(pending_socket_io->bytes, pending_socket_io->bytes + send_result, pending_socket_io->size - send_result);
+                        pending_socket_io->size -= send_result;
+                        break;
+                    }
+                }
+                else
+                {
+                    if (pending_socket_io->on_send_complete != NULL)
+                    {
+                        pending_socket_io->on_send_complete(pending_socket_io->callback_context, IO_SEND_OK);
+                    }
+
+                    free(pending_socket_io->bytes);
+                    free(pending_socket_io);
+                    if (singlylinkedlist_remove(socket_io_instance->pending_io_list, first_pending_io) != 0)
+                    {
+                        indicate_error(socket_io_instance);
+                        LogError("Failure: unable to remove socket from list");
+                    }
+                }
+
+                first_pending_io = singlylinkedlist_get_head_item(socket_io_instance->pending_io_list);
+            }
+
+            if (socket_io_instance->io_state == IO_STATE_OPEN)
+            {
+                ssize_t received = 0;
+                do
+                {
+                    received = recv(socket_io_instance->socket, socket_io_instance->recv_bytes, RECEIVE_BYTES_VALUE, 0);
+                    if (received > 0)
+                    {
+                        if (socket_io_instance->on_bytes_received != NULL)
+                        {
+                            /* Explicitly ignoring here the result of the callback */
+                            (void)socket_io_instance->on_bytes_received(socket_io_instance->on_bytes_received_context, socket_io_instance->recv_bytes, received);
+                        }
+                    }
+                    else if (received == 0)
+                    {
+                        // Do not log error here due to this is probably the socket being closed on the other end
+                        indicate_error(socket_io_instance);
+                    }
+                    else if (received < 0 && errno != EAGAIN)
+                    {
+                        LogError("Socketio_Failure: Receiving data from endpoint: errno=%d.", errno);
+                        indicate_error(socket_io_instance);
+                    }
+
+                } while (received > 0 && socket_io_instance->io_state == IO_STATE_OPEN);
+            }
+        }
+        else
+        {
+            if (socket_io_instance->io_state == IO_STATE_OPENING)
+            {
+                if(lookup_address(socket_io_instance) != 0)
+                {
+                    LogError("Socketio_Failure: lookup address failed");
+                    indicate_error(socket_io_instance);
+                }
+                else
+                {
+                    if(socket_io_instance->io_state == IO_STATE_OPEN)
+                    {
+                        initiate_socket_connection(socket_io_instance);
+                    }
+                }
+
+            }
+        }
+    }
+}
+
+// Edison is missing this from netinet/tcp.h, but this code still works if we manually define it.
+#ifndef SOL_TCP
+#define SOL_TCP 6
+#endif
+
+#ifndef __APPLE__
+static void strtoup(char* str)
+{
+    if (str != NULL)
+    {
+        while (*str != '\0')
+        {
+            if (isalpha((int)*str) && islower((int)*str))
+            {
+                *str = (char)toupper((int)*str);
+            }
+            str++;
+        }
+    }
+}
+#endif // __APPLE__
+
+static int socketio_setaddresstype_option(SOCKET_IO_INSTANCE* socket_io_instance, const char* addressType)
+{
+    int result;
+
+    if (socket_io_instance->io_state != IO_STATE_CLOSED)
+    {
+        LogError("Socket's type can only be changed when in state 'IO_STATE_CLOSED'.  Current state=%d", socket_io_instance->io_state);
+        result = MU_FAILURE;
+    }
+    else if (strcmp(addressType, OPTION_ADDRESS_TYPE_DOMAIN_SOCKET) == 0)
+    {
+        socket_io_instance->address_type = ADDRESS_TYPE_DOMAIN_SOCKET;
+        result = 0;
+    }
+    else if (strcmp(addressType, OPTION_ADDRESS_TYPE_IP_SOCKET) == 0)
+    {
+        socket_io_instance->address_type = ADDRESS_TYPE_IP;
+        result = 0;
+    }
+    else
+    {
+        LogError("Address type %s is not supported", addressType);
+        result = MU_FAILURE;
+    }
+
+    return result;
+}
+
+int socketio_setoption(CONCRETE_IO_HANDLE socket_io, const char* optionName, const void* value)
+{
+    int result;
+
+    if (socket_io == NULL ||
+        optionName == NULL ||
+        value == NULL)
+    {
+        result = MU_FAILURE;
+    }
+    else
+    {
+        SOCKET_IO_INSTANCE* socket_io_instance = (SOCKET_IO_INSTANCE*)socket_io;
+
+        if (strcmp(optionName, "tcp_keepalive") == 0)
+        {
+            result = setsockopt(socket_io_instance->socket, SOL_SOCKET, SO_KEEPALIVE, value, sizeof(int));
+            if (result == -1) result = errno;
+        }
+        else if (strcmp(optionName, "tcp_keepalive_time") == 0)
+        {
+#ifdef __APPLE__
+            result = setsockopt(socket_io_instance->socket, IPPROTO_TCP, TCP_KEEPALIVE, value, sizeof(int));
+#else
+            result = setsockopt(socket_io_instance->socket, SOL_TCP, TCP_KEEPIDLE, value, sizeof(int));
+#endif
+            if (result == -1) result = errno;
+        }
+        else if (strcmp(optionName, "tcp_keepalive_interval") == 0)
+        {
+            result = setsockopt(socket_io_instance->socket, SOL_TCP, TCP_KEEPINTVL, value, sizeof(int));
+            if (result == -1) result = errno;
+        }
+        else if (strcmp(optionName, OPTION_NET_INT_MAC_ADDRESS) == 0)
+        {
+#ifdef __APPLE__
+            LogError("option not supported.");
+            result = MU_FAILURE;
+#else
+            if (strlen(value) == 0)
+            {
+                LogError("option value must be a valid mac address");
+                result = MU_FAILURE;
+            }
+            else if ((socket_io_instance->target_mac_address = (char*)malloc(sizeof(char) * (strlen(value) + 1))) == NULL)
+            {
+                LogError("failed setting net_interface_mac_address option (malloc failed)");
+                result = MU_FAILURE;
+            }
+            else if (strcpy(socket_io_instance->target_mac_address, value) == NULL)
+            {
+                LogError("failed setting net_interface_mac_address option (strcpy failed)");
+                free(socket_io_instance->target_mac_address);
+                socket_io_instance->target_mac_address = NULL;
+                result = MU_FAILURE;
+            }
+            else
+            {
+                strtoup(socket_io_instance->target_mac_address);
+                result = 0;
+            }
+#endif
+        }
+        else if (strcmp(optionName, OPTION_ADDRESS_TYPE) == 0)
+        {
+            result = socketio_setaddresstype_option(socket_io_instance, (const char*)value);
+        }
+        else
+        {
+            result = MU_FAILURE;
+        }
+    }
+
+    return result;
+}
+
+const IO_INTERFACE_DESCRIPTION* socketio_get_interface_description(void)
+{
+    return &socket_io_interface_description;
+}
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/threadapi_toppers.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/threadapi_toppers.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/threadapi_toppers.c	(revision 453)
@@ -0,0 +1,189 @@
+/*
+ *  TOPPERS PROJECT Home Network Working Group Software
+ * 
+ *  Copyright (C) 2019 Cores Co., Ltd. Japan
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+#include <stdint.h>
+#include <stdlib.h>
+#include <kernel.h>
+#include <t_stdlib.h>
+#include "azure_c_shared_utility/threadapi.h"
+#include "azure_c_shared_utility/xlogging.h"
+
+MU_DEFINE_ENUM_STRINGS(THREADAPI_RESULT, THREADAPI_RESULT_VALUES);
+
+#ifdef TOPPERS_SUPPORT_DYNAMIC_CRE
+#define MAX_THREADS 4
+#define TASK_PRIORITY ((TMAX_TPRI + TMIN_TPRI) / 2)
+
+typedef struct _thread
+{
+	ID tskid;
+	int result;
+} toppersThread;
+static toppersThread threads[MAX_THREADS] = { 0 };
+#endif
+
+THREADAPI_RESULT ThreadAPI_Create(THREAD_HANDLE* threadHandle, THREAD_START_FUNC func, void* arg)
+{
+#ifndef TOPPERS_SUPPORT_DYNAMIC_CRE
+	LogError("TOPPERS/ASP does not support multi-thread function.");
+	return THREADAPI_ERROR;
+#else
+	THREADAPI_RESULT result;
+	if ((threadHandle == NULL) ||
+		(func == NULL))
+	{
+		result = THREADAPI_INVALID_ARG;
+		LogError("(result = %s)", MU_ENUM_TO_STRING(THREADAPI_RESULT, result));
+	}
+	else {
+		ER_ID ret;
+		T_CTSK ctsk;
+		toppersThread *thread = NULL;
+
+		for (int i = 0; i < MAX_THREADS; i++) {
+			if (threads[i].tskid == 0) {
+				thread = &threads[i];
+				break;
+			}
+		}
+
+		memset(&ctsk, 0, sizeof(ctsk));
+
+		ctsk.exinf = (intptr_t)arg;
+		ctsk.task = (TASK)func;
+		ctsk.itskpri = TASK_PRIORITY;
+
+		ret = acre_tsk(&ctsk);
+		if (ret > 0) {
+			if (thread == NULL) {
+				for (int i = 0; i < MAX_THREADS; i++) {
+					if (threads[i].tskid == ret) {
+						thread = &threads[i];
+						break;
+					}
+				}
+			}
+			if (thread != NULL) {
+				thread->result = 0;
+			}
+			if (act_tsk(ret) == E_OK) {
+				*threadHandle = (THREAD_HANDLE)(ret);
+				result = THREADAPI_OK;
+			}
+			else {
+				del_tsk(ret);
+				result = THREADAPI_ERROR;
+				LogError("(result = %s)", MU_ENUM_TO_STRING(THREADAPI_RESULT, result));
+			}
+		}
+		else {
+			result = THREADAPI_NO_MEMORY;
+			LogError("(result = %s)", MU_ENUM_TO_STRING(THREADAPI_RESULT, result));
+		}
+	}
+
+	return result;
+#endif
+}
+
+THREADAPI_RESULT ThreadAPI_Join(THREAD_HANDLE threadHandle, int *res)
+{
+#ifndef TOPPERS_SUPPORT_DYNAMIC_CRE
+	LogError("TOPPERS/ASP does not support multi-thread function.");
+	return THREADAPI_ERROR;
+#else
+	ID tskid = (ID)threadHandle;
+	T_RTSK rtsk;
+	toppersThread *thread = NULL;
+	ER ret;
+
+	for (;;) {
+		ret = ref_tsk(tskid, &rtsk);
+		if ((ret != E_OK) || (rtsk.tskstat == TTS_DMT))
+			break;
+
+		dly_tsk(10);
+	}
+
+	for (int i = 0; i < MAX_THREADS; i++) {
+		if (threads[i].tskid == ret) {
+			thread = &threads[i];
+			break;
+		}
+	}
+
+	if (thread != NULL) {
+		*res = thread->result;
+	}
+
+	return THREADAPI_OK;
+#endif
+}
+
+void ThreadAPI_Exit(int res)
+{
+	ER ret;
+#ifdef TOPPERS_SUPPORT_DYNAMIC_CRE
+	ID tskid;
+
+	ret = get_tid(&tskid);
+	if (ret != E_OK) {
+		LogError("get_tid error. %s", itron_strerror(ret));
+		return;
+	}
+
+	for (int i = 0; i < MAX_THREADS; i++) {
+		if (threads[i].tskid == tskid) {
+			threads[i].result = res;
+			break;
+		}
+	}
+#endif
+	ret = ext_tsk();
+	if (ret != E_OK) {
+		LogError("ext_tsk error. %s", itron_strerror(ret));
+	}
+}
+
+void ThreadAPI_Sleep(unsigned int milliseconds)
+{
+	ER ret;
+
+	ret = dly_tsk((RELTIM)milliseconds);
+	if (ret != E_OK) {
+		LogError("dly_tsk error. %s", itron_strerror(ret));
+	}
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/tickcounter_toppers.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/tickcounter_toppers.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/tickcounter_toppers.c	(revision 453)
@@ -0,0 +1,105 @@
+/*
+ *  TOPPERS PROJECT Home Network Working Group Software
+ * 
+ *  Copyright (C) 2019 Cores Co., Ltd. Japan
+ * 
+ *  上記著作権者は，以下の(1)～(4)の条件を満たす場合に限り，本ソフトウェ
+ *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
+ *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
+ *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
+ *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
+ *      スコード中に含まれていること．
+ *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
+ *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
+ *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
+ *      の無保証規定を掲載すること．
+ *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
+ *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
+ *      と．
+ *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
+ *        作権表示，この利用条件および下記の無保証規定を掲載すること．
+ *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
+ *        報告すること．
+ *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
+ *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
+ *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
+ *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
+ *      免責すること．
+ * 
+ *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
+ *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
+ *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
+ *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
+ *  の責任を負わない．
+ * 
+ *  @(#) $Id$
+ */
+#include <stdint.h>
+#include <stdlib.h>
+#include <kernel.h>
+#include <sil.h>
+#include "azure_c_shared_utility/tickcounter.h"
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/xlogging.h"
+
+typedef struct tick_counter_instance_tag
+{
+	SYSTIM last_clock_value;
+	tickcounter_ms_t current_ms;
+} TICK_COUNTER_INSTANCE_TAG;
+
+TICK_COUNTER_HANDLE tickcounter_create(void)
+{
+	ER ret;
+	SYSTIM now;
+	TICK_COUNTER_INSTANCE_TAG* result;
+
+	result = (TICK_COUNTER_INSTANCE_TAG *)malloc(sizeof(TICK_COUNTER_INSTANCE_TAG));
+
+	if (get_tim(&now) != E_OK) {
+		LogError("tickcounter failed: time return INVALID_TIME.");
+		free(result);
+		result = NULL;
+	}
+	else {
+		result->last_clock_value = now;
+		result->current_ms = 0;
+	}
+
+	return (TICK_COUNTER_HANDLE)result;
+}
+
+void tickcounter_destroy(TICK_COUNTER_HANDLE tick_counter)
+{
+	if (tick_counter != NULL)
+	{
+		free((TICK_COUNTER_INSTANCE_TAG *)tick_counter);
+	}
+}
+
+int tickcounter_get_current_ms(TICK_COUNTER_HANDLE tick_counter, tickcounter_ms_t * current_ms)
+{
+	ER ret;
+	SYSTIM now;
+	int result;
+
+	if (tick_counter == NULL || current_ms == NULL)
+	{
+		result = MU_FAILURE;
+	}
+	else
+	{
+		if (get_tim(&now) != E_OK) {
+			result = MU_FAILURE;
+		}
+		else {
+			TICK_COUNTER_INSTANCE_TAG* tick_counter_instance = (TICK_COUNTER_INSTANCE_TAG*)tick_counter;
+			tick_counter_instance->current_ms += (now - tick_counter_instance->last_clock_value);
+			tick_counter_instance->last_clock_value = now;
+			*current_ms = tick_counter_instance->current_ms;
+			result = 0;
+		}
+	}
+
+	return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/tlsio_esp_at.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/tlsio_esp_at.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/tlsio_esp_at.c	(revision 453)
@@ -0,0 +1,497 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include "azure_c_shared_utility/tlsio.h"
+#include "azure_c_shared_utility/tlsio_esp_at.h"
+#include "azure_c_shared_utility/singlylinkedlist.h"
+#include "azure_c_shared_utility/esp_at_socket.h"
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/xlogging.h"
+
+#define ESP_AT_XIO_RECEIVE_BUFFER_SIZE    128
+
+typedef enum IO_STATE_TAG
+{
+    IO_STATE_CLOSED,
+    IO_STATE_OPENING,
+    IO_STATE_OPEN,
+    IO_STATE_CLOSING,
+    IO_STATE_ERROR
+} IO_STATE;
+
+typedef struct PENDING_TLS_IO_TAG
+{
+    unsigned char* bytes;
+    size_t size;
+    ON_SEND_COMPLETE on_send_complete;
+    void* callback_context;
+    SINGLYLINKEDLIST_HANDLE pending_io_list;
+} PENDING_TLS_IO;
+
+typedef struct TLS_IO_INSTANCE_TAG
+{
+    ESP_AT_SOCKET_HANDLE tcp_socket_connection;
+    ON_BYTES_RECEIVED on_bytes_received;
+    ON_IO_ERROR on_io_error;
+    void* on_bytes_received_context;
+    void* on_io_error_context;
+    char* hostname;
+    int port;
+    IO_STATE io_state;
+    SINGLYLINKEDLIST_HANDLE pending_io_list;
+} TLS_IO_INSTANCE;
+
+/*this function will clone an option given by name and value*/
+static void* tlsio_esp_at_CloneOption(const char* name, const void* value)
+{
+    (void)name;
+    (void)value;
+    return NULL;
+}
+
+/*this function destroys an option previously created*/
+static void tlsio_esp_at_DestroyOption(const char* name, const void* value)
+{
+    (void)name;
+    (void)value;
+}
+
+static OPTIONHANDLER_HANDLE tlsio_esp_at_retrieveoptions(CONCRETE_IO_HANDLE tlsio_esp_at)
+{
+    OPTIONHANDLER_HANDLE result;
+    (void)tlsio_esp_at;
+    result = OptionHandler_Create(tlsio_esp_at_CloneOption, tlsio_esp_at_DestroyOption, tlsio_esp_at_setoption);
+    if (result == NULL)
+    {
+        /*return as is*/
+    }
+    else
+    {
+        /*insert here work to add the options to "result" handle*/
+    }
+    return result;
+}
+
+static const IO_INTERFACE_DESCRIPTION tlsio_esp_at_interface_description =
+{
+    tlsio_esp_at_retrieveoptions,
+    tlsio_esp_at_create,
+    tlsio_esp_at_destroy,
+    tlsio_esp_at_open,
+    tlsio_esp_at_close,
+    tlsio_esp_at_send,
+    tlsio_esp_at_dowork,
+    tlsio_esp_at_setoption
+};
+
+static void indicate_error(TLS_IO_INSTANCE* tlsio_esp_at_instance)
+{
+    if ((tlsio_esp_at_instance->io_state == IO_STATE_CLOSED)
+        || (tlsio_esp_at_instance->io_state == IO_STATE_ERROR))
+    {
+        return;
+    }
+    tlsio_esp_at_instance->io_state = IO_STATE_ERROR;
+    if (tlsio_esp_at_instance->on_io_error != NULL)
+    {
+        tlsio_esp_at_instance->on_io_error(tlsio_esp_at_instance->on_io_error_context);
+    }
+}
+
+static int add_pending_io(TLS_IO_INSTANCE* tlsio_esp_at_instance, const unsigned char* buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void* callback_context)
+{
+    int result;
+    PENDING_TLS_IO* pending_tlsio_esp_at = (PENDING_TLS_IO*)malloc(sizeof(PENDING_TLS_IO));
+    if (pending_tlsio_esp_at == NULL)
+    {
+        LogError("Allocation Failure: Unable to allocate pending list.");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        pending_tlsio_esp_at->bytes = (unsigned char*)malloc(size);
+        if (pending_tlsio_esp_at->bytes == NULL)
+        {
+            LogError("Allocation Failure: Unable to allocate pending list.");
+            free(pending_tlsio_esp_at);
+            result = MU_FAILURE;
+        }
+        else
+        {
+            pending_tlsio_esp_at->size = size;
+            pending_tlsio_esp_at->on_send_complete = on_send_complete;
+            pending_tlsio_esp_at->callback_context = callback_context;
+            pending_tlsio_esp_at->pending_io_list = tlsio_esp_at_instance->pending_io_list;
+            (void)memcpy(pending_tlsio_esp_at->bytes, buffer, size);
+            if (singlylinkedlist_add(tlsio_esp_at_instance->pending_io_list, pending_tlsio_esp_at) == NULL)
+            {
+                LogError("Failure: Unable to add socket to pending list.");
+                free(pending_tlsio_esp_at->bytes);
+                free(pending_tlsio_esp_at);
+                result = MU_FAILURE;
+            }
+            else
+            {
+                result = 0;
+            }
+        }
+    }
+
+    return result;
+}
+
+#define NSAPI_ERROR_WOULD_BLOCK   -3001
+
+static int retrieve_data(TLS_IO_INSTANCE* tlsio_esp_at_instance)
+{
+    int received = 1;
+    int total_received = 0;
+
+    unsigned char* recv_bytes = malloc(ESP_AT_XIO_RECEIVE_BUFFER_SIZE);
+    if (recv_bytes == NULL)
+    {
+        LogError("Socketio_Failure: NULL allocating input buffer.");
+        indicate_error(tlsio_esp_at_instance);
+        return -1;
+    }
+    
+    while (received > 0)
+    {
+        received = esp_at_socket_receive(tlsio_esp_at_instance->tcp_socket_connection, (char*)recv_bytes, ESP_AT_XIO_RECEIVE_BUFFER_SIZE);
+        if (received > 0)
+        {
+            total_received += received;
+            if (tlsio_esp_at_instance->on_bytes_received != NULL)
+            {
+                /* explictly ignoring here the result of the callback */
+                tlsio_esp_at_instance->on_bytes_received(tlsio_esp_at_instance->on_bytes_received_context, recv_bytes, received);
+            }
+        }
+        else if (received < 0)
+        {
+            if(received != NSAPI_ERROR_WOULD_BLOCK)     // NSAPI_ERROR_WOULD_BLOCK is not a real error but pending.
+            {
+                indicate_error(tlsio_esp_at_instance);
+                LogError("Socketio_Failure: underlying IO error %d.", received);
+                free(recv_bytes);
+                return -1;
+            }
+        }
+    }
+    free(recv_bytes);
+    
+    return total_received;
+}
+
+static int send_queued_data(TLS_IO_INSTANCE* tlsio_esp_at_instance)
+{
+    int errors = 0;
+    int sent = 0;
+    
+    LIST_ITEM_HANDLE first_pending_io = singlylinkedlist_get_head_item(tlsio_esp_at_instance->pending_io_list);
+    while (first_pending_io != NULL)
+    {
+        PENDING_TLS_IO* pending_tlsio_esp_at = (PENDING_TLS_IO*)singlylinkedlist_item_get_value(first_pending_io);
+        if (pending_tlsio_esp_at == NULL)
+        {
+            indicate_error(tlsio_esp_at_instance);
+            return -1;
+        }
+
+        int send_result = esp_at_socket_send(tlsio_esp_at_instance->tcp_socket_connection, (const char*)pending_tlsio_esp_at->bytes, pending_tlsio_esp_at->size);
+        if (send_result != (int)pending_tlsio_esp_at->size)
+        {
+            if (send_result == 0)
+            {
+                // The underlying network layer may encounter hardware / environment issues, 
+                // but the driver doesn't handle it properly. So here the send API always return 0, 
+                // this causes the program running into dead loop if not check it here.
+                if (errors++ >= 10)
+                {
+                    // Treat it as a network error after try 10 times.
+                    LogError("Socketio_Failure: encountered unknow connection issue, the connection will be restarted.");
+                    indicate_error(tlsio_esp_at_instance);
+                    return -1;
+                }
+                ThreadAPI_Sleep(10);
+            }
+            else if (send_result < 0)
+            {
+                indicate_error(tlsio_esp_at_instance);
+                return -1;
+            }
+            else
+            {
+                /* send something, wait for the rest */
+                memmove(pending_tlsio_esp_at->bytes, pending_tlsio_esp_at->bytes + send_result, pending_tlsio_esp_at->size - send_result);
+                sent += send_result;
+            }
+        }
+        else
+        {
+            sent += send_result;
+            if (pending_tlsio_esp_at->on_send_complete != NULL)
+            {
+                pending_tlsio_esp_at->on_send_complete(pending_tlsio_esp_at->callback_context, IO_SEND_OK);
+            }
+
+            free(pending_tlsio_esp_at->bytes);
+            free(pending_tlsio_esp_at);
+            if (singlylinkedlist_remove(tlsio_esp_at_instance->pending_io_list, first_pending_io) != 0)
+            {
+                indicate_error(tlsio_esp_at_instance);
+                return -1;
+            }
+            errors = 0;
+        }
+
+        first_pending_io = singlylinkedlist_get_head_item(tlsio_esp_at_instance->pending_io_list);
+    }
+
+    return sent;
+}
+
+static void close_tcp_connection(TLS_IO_INSTANCE* tlsio_esp_at_instance)
+{
+    if (tlsio_esp_at_instance->io_state != IO_STATE_CLOSED)
+    {
+        if (tlsio_esp_at_instance->tcp_socket_connection != NULL)
+        {
+            esp_at_socket_close(tlsio_esp_at_instance->tcp_socket_connection);
+            esp_at_socket_destroy(tlsio_esp_at_instance->tcp_socket_connection);
+            tlsio_esp_at_instance->tcp_socket_connection = NULL;
+        }
+        tlsio_esp_at_instance->io_state = IO_STATE_CLOSED;
+    }
+}
+
+CONCRETE_IO_HANDLE tlsio_esp_at_create(void* io_create_parameters)
+{
+    TLSIO_CONFIG* tlsio_esp_at_config = io_create_parameters;
+    TLS_IO_INSTANCE* result;
+
+    if (tlsio_esp_at_config == NULL)
+    {
+        result = NULL;
+    }
+    else
+    {    
+        result = (TLS_IO_INSTANCE*)malloc(sizeof(TLS_IO_INSTANCE));
+        if (result == NULL) {
+            LogError("Socketio_Failure: NULL allocating socket io instance.");
+        }
+        else
+        {
+            result->pending_io_list = singlylinkedlist_create();
+            if (result->pending_io_list == NULL)
+            {
+                free(result);
+                result = NULL;
+            }
+            else
+            {
+                result->hostname = strdup(tlsio_esp_at_config->hostname);
+                if (result->hostname == NULL)
+                {
+                    singlylinkedlist_destroy(result->pending_io_list);
+                    free(result);
+                    result = NULL;
+                }
+                else
+                {
+                    result->port = tlsio_esp_at_config->port;
+                    result->on_bytes_received = NULL;
+                    result->on_io_error = NULL;
+                    result->on_bytes_received_context = NULL;
+                    result->on_io_error_context = NULL;
+                    result->io_state = IO_STATE_CLOSED;
+                    result->tcp_socket_connection = NULL;
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+void tlsio_esp_at_destroy(CONCRETE_IO_HANDLE tlsio_esp_at)
+{
+    if (tlsio_esp_at != NULL)
+    {
+        TLS_IO_INSTANCE* tlsio_esp_at_instance = (TLS_IO_INSTANCE*)tlsio_esp_at;
+
+        // Close the tcp connection
+        close_tcp_connection(tlsio_esp_at_instance);
+    
+        // Clear all pending IOs
+        LIST_ITEM_HANDLE first_pending_io = singlylinkedlist_get_head_item(tlsio_esp_at_instance->pending_io_list);
+        while (first_pending_io != NULL)
+        {
+            PENDING_TLS_IO* pending_tlsio_esp_at = (PENDING_TLS_IO*)singlylinkedlist_item_get_value(first_pending_io);
+            if (pending_tlsio_esp_at != NULL)
+            {
+                free(pending_tlsio_esp_at->bytes);
+                free(pending_tlsio_esp_at);
+            }
+
+            (void)singlylinkedlist_remove(tlsio_esp_at_instance->pending_io_list, first_pending_io);
+            first_pending_io = singlylinkedlist_get_head_item(tlsio_esp_at_instance->pending_io_list);
+        }
+        singlylinkedlist_destroy(tlsio_esp_at_instance->pending_io_list);
+    
+        if(tlsio_esp_at_instance->hostname != NULL)
+        {
+            free(tlsio_esp_at_instance->hostname);
+            tlsio_esp_at_instance->hostname = NULL;
+        }
+        free(tlsio_esp_at);
+    }
+}
+
+int tlsio_esp_at_open(CONCRETE_IO_HANDLE tlsio_esp_at, ON_IO_OPEN_COMPLETE on_io_open_complete, void* on_io_open_complete_context, ON_BYTES_RECEIVED on_bytes_received, void* on_bytes_received_context, ON_IO_ERROR on_io_error, void* on_io_error_context)
+{
+    int result;
+    TLS_IO_INSTANCE* tlsio_esp_at_instance = (TLS_IO_INSTANCE*)tlsio_esp_at;
+    
+
+    if (tlsio_esp_at_instance == NULL ||
+        tlsio_esp_at_instance->io_state != IO_STATE_CLOSED)
+    {
+        result = MU_FAILURE;
+    }
+    else
+    {
+        tlsio_esp_at_instance->tcp_socket_connection = esp_at_socket_create(true);
+        if (tlsio_esp_at_instance->tcp_socket_connection == NULL)
+        {
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if (esp_at_socket_connect(tlsio_esp_at_instance->tcp_socket_connection, tlsio_esp_at_instance->hostname, tlsio_esp_at_instance->port) != 0)
+            {
+                esp_at_socket_destroy(tlsio_esp_at_instance->tcp_socket_connection);
+                tlsio_esp_at_instance->tcp_socket_connection = NULL;
+                result = MU_FAILURE;
+            }
+            else
+            {
+                esp_at_socket_set_blocking(tlsio_esp_at_instance->tcp_socket_connection, false, 0);
+
+                tlsio_esp_at_instance->on_bytes_received = on_bytes_received;
+                tlsio_esp_at_instance->on_bytes_received_context = on_bytes_received_context;
+
+                tlsio_esp_at_instance->on_io_error = on_io_error;
+                tlsio_esp_at_instance->on_io_error_context = on_io_error_context;
+
+                tlsio_esp_at_instance->io_state = IO_STATE_OPEN;
+
+                result = 0;
+            }
+        }
+    }
+    
+    if (on_io_open_complete != NULL)
+    {
+        on_io_open_complete(on_io_open_complete_context, result == 0 ? IO_OPEN_OK : IO_OPEN_ERROR);
+    }
+
+    return result;
+}
+
+int tlsio_esp_at_close(CONCRETE_IO_HANDLE tlsio_esp_at, ON_IO_CLOSE_COMPLETE on_io_close_complete, void* callback_context)
+{
+    int result = 0;
+
+    if (tlsio_esp_at == NULL)
+    {
+        result = MU_FAILURE;
+    }
+    else
+    {
+        TLS_IO_INSTANCE* tlsio_esp_at_instance = (TLS_IO_INSTANCE*)tlsio_esp_at;
+        if (tlsio_esp_at_instance->io_state == IO_STATE_CLOSED || 
+            tlsio_esp_at_instance->io_state == IO_STATE_ERROR)
+        {
+            result = MU_FAILURE;
+        }
+        else
+        {
+            close_tcp_connection(tlsio_esp_at_instance);
+            if (on_io_close_complete != NULL)
+            {
+                on_io_close_complete(callback_context);
+            }
+            result = 0;
+        }
+    }
+    
+    return result;
+}
+
+int tlsio_esp_at_send(CONCRETE_IO_HANDLE tlsio_esp_at, const void* buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void* callback_context)
+{
+    int result;
+
+    if ((tlsio_esp_at == NULL) ||
+        (buffer == NULL) ||
+        (size == 0))
+    {
+        /* Invalid arguments */
+        result = MU_FAILURE;
+    }
+    else
+    {
+        result = 0;
+
+        TLS_IO_INSTANCE* tlsio_esp_at_instance = (TLS_IO_INSTANCE*)tlsio_esp_at;
+        if (tlsio_esp_at_instance->io_state != IO_STATE_OPEN)
+        {
+            result = MU_FAILURE;
+        }
+        else
+        {
+            // Queue the data, and the tlsio_esp_at_dowork sends the package later
+            if (add_pending_io(tlsio_esp_at_instance, buffer, size, on_send_complete, callback_context) != 0)
+            {
+                result = MU_FAILURE;
+            }
+        }
+    }
+
+    return result;
+}
+
+void tlsio_esp_at_dowork(CONCRETE_IO_HANDLE tlsio_esp_at)
+{
+    if (tlsio_esp_at != NULL)
+    {
+        TLS_IO_INSTANCE* tlsio_esp_at_instance = (TLS_IO_INSTANCE*)tlsio_esp_at;
+        if (tlsio_esp_at_instance->io_state == IO_STATE_OPEN)
+        {
+            // Retrieve all data from IoT Hub
+            if (retrieve_data(tlsio_esp_at_instance) < 0)
+            {
+                return;
+            }
+        
+            // Send all packages in the queue
+            send_queued_data(tlsio_esp_at_instance);
+        }
+    }
+}
+
+int tlsio_esp_at_setoption(CONCRETE_IO_HANDLE tlsio_esp_at, const char* optionName, const void* value)
+{
+    /* Not implementing any options, do nothing */
+    return OPTIONHANDLER_OK;
+}
+
+const IO_INTERFACE_DESCRIPTION* tlsio_esp_at_get_interface_description(void)
+{
+    return &tlsio_esp_at_interface_description;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/tlsio_wolfssl.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/tlsio_wolfssl.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/tlsio_wolfssl.c	(revision 453)
@@ -0,0 +1,985 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#define WOLFSSL_OPTIONS_IGNORE_SYS
+#include "wolfssl/options.h"
+#include "wolfssl/ssl.h"
+#include "wolfssl/error-ssl.h"
+#include "wolfssl/wolfcrypt/types.h"
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/tlsio.h"
+#include "azure_c_shared_utility/tlsio_wolfssl.h"
+#include "azure_c_shared_utility/socketio.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/shared_util_options.h"
+#include "azure_c_shared_utility/threadapi.h"
+
+typedef enum TLSIO_STATE_ENUM_TAG
+{
+    TLSIO_STATE_NOT_OPEN,
+    TLSIO_STATE_OPENING_UNDERLYING_IO,
+    TLSIO_STATE_IN_HANDSHAKE,
+    TLSIO_STATE_OPEN,
+    TLSIO_STATE_CLOSING,
+    TLSIO_STATE_ERROR
+} TLSIO_STATE_ENUM;
+
+typedef struct TLS_IO_INSTANCE_TAG
+{
+    XIO_HANDLE socket_io;
+    ON_BYTES_RECEIVED on_bytes_received;
+    ON_IO_OPEN_COMPLETE on_io_open_complete;
+    ON_IO_CLOSE_COMPLETE on_io_close_complete;
+    ON_IO_ERROR on_io_error;
+    void* on_bytes_received_context;
+    void* on_io_open_complete_context;
+    void* on_io_close_complete_context;
+    void* on_io_error_context;
+    WOLFSSL* ssl;
+    WOLFSSL_CTX* ssl_context;
+    TLSIO_STATE_ENUM tlsio_state;
+    unsigned char* socket_io_read_bytes;
+    size_t socket_io_read_byte_count;
+    ON_SEND_COMPLETE on_send_complete;
+    void* on_send_complete_callback_context;
+    char* certificate;
+    char* x509certificate;
+    char* x509privatekey;
+    int wolfssl_device_id;
+    size_t socket_reads;
+} TLS_IO_INSTANCE;
+
+STATIC_VAR_UNUSED const char* const OPTION_WOLFSSL_SET_DEVICE_ID = "SetDeviceId";
+static const size_t SOCKET_READ_LIMIT = 10000; // 10,000 ms ?
+
+/*this function will clone an option given by name and value*/
+static void* tlsio_wolfssl_CloneOption(const char* name, const void* value)
+{
+    void* result;
+    if ((name == NULL) || (value == NULL))
+    {
+        LogError("invalid parameter detected: const char* name=%p, const void* value=%p", name, value);
+        result = NULL;
+    }
+    else
+    {
+        if (strcmp(name, OPTION_TRUSTED_CERT) == 0)
+        {
+            if (mallocAndStrcpy_s((char**)&result, value) != 0)
+            {
+                LogError("unable to mallocAndStrcpy_s TrustedCerts value");
+                result = NULL;
+            }
+            else
+            {
+                /*return as is*/
+            }
+        }
+        else if (strcmp(name, SU_OPTION_X509_CERT) == 0)
+        {
+            if (mallocAndStrcpy_s((char**)&result, value) != 0)
+            {
+                LogError("unable to mallocAndStrcpy_s x509certificate value");
+                result = NULL;
+            }
+            else
+            {
+                /*return as is*/
+            }
+        }
+        else if (strcmp(name, SU_OPTION_X509_PRIVATE_KEY) == 0)
+        {
+            if (mallocAndStrcpy_s((char**)&result, value) != 0)
+            {
+                LogError("unable to mallocAndStrcpy_s x509privatekey value");
+                result = NULL;
+            }
+            else
+            {
+                /*return as is*/
+            }
+        }
+        else
+        {
+            LogError("not handled option : %s", name);
+            result = NULL;
+        }
+    }
+    return result;
+}
+
+/*this function destroys an option previously created*/
+static void tlsio_wolfssl_DestroyOption(const char* name, const void* value)
+{
+    /*since all options for this layer are actually string copies., disposing of one is just calling free*/
+    if ((name == NULL) || (value == NULL))
+    {
+        LogError("invalid parameter detected: const char* name=%p, const void* value=%p", name, value);
+    }
+    else
+    {
+        if ((strcmp(name, OPTION_TRUSTED_CERT) == 0) ||
+            (strcmp(name, SU_OPTION_X509_CERT) == 0) ||
+            (strcmp(name, SU_OPTION_X509_PRIVATE_KEY) == 0))
+        {
+            free((void*)value);
+        }
+        else
+        {
+            LogError("not handled option : %s", name);
+        }
+    }
+}
+
+static OPTIONHANDLER_HANDLE tlsio_wolfssl_retrieveoptions(CONCRETE_IO_HANDLE tls_io)
+{
+    OPTIONHANDLER_HANDLE result;
+    if (tls_io == NULL)
+    {
+        LogError("NULL tls_io parameter");
+        result = NULL;
+    }
+    else
+    {
+        result = OptionHandler_Create(tlsio_wolfssl_CloneOption, tlsio_wolfssl_DestroyOption, tlsio_wolfssl_setoption);
+        if (result == NULL)
+        {
+            LogError("unable to OptionHandler_Create");
+            /*return as is*/
+        }
+        else
+        {
+            /*this layer cares about the certificates and the x509 credentials*/
+            TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
+            if (
+                (tls_io_instance->x509certificate != NULL) &&
+                (OptionHandler_AddOption(result, SU_OPTION_X509_CERT, tls_io_instance->x509certificate) != OPTIONHANDLER_OK)
+                )
+            {
+                LogError("unable to save x509certificate option");
+                OptionHandler_Destroy(result);
+                result = NULL;
+            }
+            else if (
+                (tls_io_instance->x509privatekey != NULL) &&
+                (OptionHandler_AddOption(result, SU_OPTION_X509_PRIVATE_KEY, tls_io_instance->x509privatekey) != OPTIONHANDLER_OK)
+                )
+            {
+                LogError("unable to save x509privatekey option");
+                OptionHandler_Destroy(result);
+                result = NULL;
+            }
+            else if (
+                (tls_io_instance->certificate != NULL) &&
+                (OptionHandler_AddOption(result, OPTION_TRUSTED_CERT, tls_io_instance->certificate) != OPTIONHANDLER_OK)
+                )
+            {
+                LogError("unable to save TrustedCerts option");
+                OptionHandler_Destroy(result);
+                result = NULL;
+            }
+            else
+            {
+                /*all is fine, all interesting options have been saved*/
+                /*return as is*/
+            }
+        }
+    }
+
+    return result;
+}
+
+static const IO_INTERFACE_DESCRIPTION tlsio_wolfssl_interface_description =
+{
+    tlsio_wolfssl_retrieveoptions,
+    tlsio_wolfssl_create,
+    tlsio_wolfssl_destroy,
+    tlsio_wolfssl_open,
+    tlsio_wolfssl_close,
+    tlsio_wolfssl_send,
+    tlsio_wolfssl_dowork,
+    tlsio_wolfssl_setoption
+};
+
+static void indicate_error(TLS_IO_INSTANCE* tls_io_instance)
+{
+    if (tls_io_instance->on_io_error != NULL)
+    {
+        tls_io_instance->on_io_error(tls_io_instance->on_io_error_context);
+    }
+}
+
+static void indicate_open_complete(TLS_IO_INSTANCE* tls_io_instance, IO_OPEN_RESULT open_result)
+{
+    if (tls_io_instance->on_io_open_complete != NULL)
+    {
+        tls_io_instance->on_io_open_complete(tls_io_instance->on_io_open_complete_context, open_result);
+    }
+}
+
+static int decode_ssl_received_bytes(TLS_IO_INSTANCE* tls_io_instance)
+{
+    int result = 0;
+    unsigned char buffer[64];
+
+    int rcv_bytes = 0;
+    do
+    {
+        rcv_bytes = wolfSSL_read(tls_io_instance->ssl, buffer, sizeof(buffer));
+        if (rcv_bytes > 0)
+        {
+            if (tls_io_instance->on_bytes_received != NULL)
+            {
+                tls_io_instance->on_bytes_received(tls_io_instance->on_bytes_received_context, buffer, rcv_bytes);
+            }
+        }
+    } while (rcv_bytes > 0);
+    return result;
+}
+
+static void on_underlying_io_open_complete(void* context, IO_OPEN_RESULT open_result)
+{
+    TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
+
+    if (open_result != IO_OPEN_OK)
+    {
+        LogError("Underlying IO open failed");
+        tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
+        indicate_open_complete(tls_io_instance, IO_OPEN_ERROR);
+    }
+    else
+    {
+        int res;
+        tls_io_instance->tlsio_state = TLSIO_STATE_IN_HANDSHAKE;
+        tls_io_instance->socket_reads = 0;
+
+        res = wolfSSL_connect(tls_io_instance->ssl);
+        if (res != SSL_SUCCESS)
+        {
+            LogError("WolfSSL connect failed");
+            indicate_open_complete(tls_io_instance, IO_OPEN_ERROR);
+            tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
+        }
+    }
+}
+
+static void on_underlying_io_bytes_received(void* context, const unsigned char* buffer, size_t size)
+{
+    if (context != NULL)
+    {
+        TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
+
+        unsigned char* new_socket_io_read_bytes = (unsigned char*)realloc(tls_io_instance->socket_io_read_bytes, tls_io_instance->socket_io_read_byte_count + size);
+        if (new_socket_io_read_bytes == NULL)
+        {
+            LogError("Failed allocating memory for received bytes");
+            tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
+            indicate_error(tls_io_instance);
+        }
+        else
+        {
+            tls_io_instance->socket_io_read_bytes = new_socket_io_read_bytes;
+            (void)memcpy(tls_io_instance->socket_io_read_bytes + tls_io_instance->socket_io_read_byte_count, buffer, size);
+            tls_io_instance->socket_io_read_byte_count += size;
+        }
+    }
+    else
+    {
+        LogInfo("Supplied context is NULL on bytes_received");
+    }
+}
+
+static void on_underlying_io_error(void* context)
+{
+    if (context != NULL)
+    {
+        TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
+
+        switch (tls_io_instance->tlsio_state)
+        {
+        default:
+            LogError("Unknown TLS IO WolfSSL state: %d", (int)tls_io_instance->tlsio_state);
+            break;
+
+        case TLSIO_STATE_NOT_OPEN:
+        case TLSIO_STATE_ERROR:
+            break;
+
+        case TLSIO_STATE_OPENING_UNDERLYING_IO:
+        case TLSIO_STATE_IN_HANDSHAKE:
+            tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
+            indicate_open_complete(tls_io_instance, IO_OPEN_ERROR);
+            break;
+
+        case TLSIO_STATE_OPEN:
+            tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
+            indicate_error(tls_io_instance);
+            break;
+        }
+    }
+    else
+    {
+        LogInfo("Supplied context is NULL on io_error");
+    }
+}
+
+static void on_underlying_io_close_complete(void* context)
+{
+    TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
+
+    if (tls_io_instance->tlsio_state != TLSIO_STATE_CLOSING)
+    {
+        LogError("on_underlying_io_close_complete called when not in CLOSING state");
+    }
+    else
+    {
+        if (tls_io_instance->on_io_close_complete != NULL)
+        {
+            tls_io_instance->on_io_close_complete(tls_io_instance->on_io_close_complete_context);
+        }
+        tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
+    }
+}
+
+static int on_io_recv(WOLFSSL *ssl, char *buf, int sz, void *context)
+{
+    int result;
+    if (context != NULL)
+    {
+        TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
+        unsigned char* new_socket_io_read_bytes;
+
+        AZURE_UNREFERENCED_PARAMETER(ssl);
+        if (tls_io_instance->socket_io_read_byte_count == 0)
+        {
+            if (tls_io_instance->socket_reads >= SOCKET_READ_LIMIT) {
+                return WOLFSSL_CBIO_ERR_TIMEOUT;
+            }
+            xio_dowork(tls_io_instance->socket_io);
+            if (tls_io_instance->tlsio_state == TLSIO_STATE_IN_HANDSHAKE)
+            {
+                tls_io_instance->socket_reads++;
+                ThreadAPI_Sleep(1);
+                return 0;
+            }
+        }
+
+        result = tls_io_instance->socket_io_read_byte_count;
+        if (result > sz)
+        {
+            result = sz;
+        }
+
+        if (result > 0)
+        {
+            (void)memcpy(buf, tls_io_instance->socket_io_read_bytes, result);
+            (void)memmove(tls_io_instance->socket_io_read_bytes, tls_io_instance->socket_io_read_bytes + result, tls_io_instance->socket_io_read_byte_count - result);
+            tls_io_instance->socket_io_read_byte_count -= result;
+            if (tls_io_instance->socket_io_read_byte_count > 0)
+            {
+                new_socket_io_read_bytes = (unsigned char*)realloc(tls_io_instance->socket_io_read_bytes, tls_io_instance->socket_io_read_byte_count);
+                if (new_socket_io_read_bytes != NULL)
+                {
+                    tls_io_instance->socket_io_read_bytes = new_socket_io_read_bytes;
+                }
+            }
+            else
+            {
+                free(tls_io_instance->socket_io_read_bytes);
+                tls_io_instance->socket_io_read_bytes = NULL;
+            }
+        }
+
+        if (tls_io_instance->tlsio_state == TLSIO_STATE_ERROR)
+        {
+            result = WOLFSSL_CBIO_ERR_GENERAL;
+        }
+        else if ( (result == 0) && (tls_io_instance->tlsio_state == TLSIO_STATE_OPEN))
+        {
+            result = WOLFSSL_CBIO_ERR_WANT_READ;
+        }
+        else if ((result == 0) && (tls_io_instance->tlsio_state == TLSIO_STATE_CLOSING || tls_io_instance->tlsio_state == TLSIO_STATE_NOT_OPEN))
+        {
+            result = WOLFSSL_CBIO_ERR_CONN_CLOSE;
+        }
+    }
+    else
+    {
+        result = WOLFSSL_CBIO_ERR_GENERAL;
+    }
+    return result;
+}
+
+static void on_send_complete(void* context, IO_SEND_RESULT send_result)
+{
+	TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
+	if ((tls_io_instance == NULL) || (tls_io_instance->on_send_complete == NULL))
+		return;
+
+	tls_io_instance->on_send_complete(tls_io_instance->on_send_complete_callback_context, send_result);
+
+	tls_io_instance->on_send_complete = NULL;
+	tls_io_instance->on_send_complete_callback_context = NULL;
+}
+
+static int on_io_send(WOLFSSL *ssl, char *buf, int sz, void *context)
+{
+    int result, ret;
+    AZURE_UNREFERENCED_PARAMETER(ssl);
+
+    TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
+
+    if ((ret = xio_send(tls_io_instance->socket_io, buf, sz, on_send_complete, tls_io_instance)) != 0)
+    {
+        LogError("Failed sending bytes through underlying IO %d", ret);
+        tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
+        indicate_error(tls_io_instance);
+        result = 0;
+    }
+    else
+    {
+        result = sz;
+    }
+
+    return result;
+}
+
+static int on_handshake_done(WOLFSSL* ssl, void* context)
+{
+    AZURE_UNREFERENCED_PARAMETER(ssl);
+    TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
+    if (tls_io_instance->tlsio_state == TLSIO_STATE_OPEN) {
+        LogInfo("on_handshake_done called in TLSIO_STATE_OPEN state");
+    }
+    else if (tls_io_instance->tlsio_state != TLSIO_STATE_IN_HANDSHAKE)
+    {
+        LogInfo("on_handshake_done called when not in IN_HANDSHAKE state");
+    }
+    else
+    {
+        tls_io_instance->tlsio_state = TLSIO_STATE_OPEN;
+        indicate_open_complete(tls_io_instance, IO_OPEN_OK);
+    }
+
+    return 0;
+}
+
+static int add_certificate_to_store(TLS_IO_INSTANCE* tls_io_instance)
+{
+    int result;
+    if (tls_io_instance->certificate != NULL)
+    {
+        int res = wolfSSL_CTX_load_verify_buffer(tls_io_instance->ssl_context, (const unsigned char*)tls_io_instance->certificate, strlen(tls_io_instance->certificate), SSL_FILETYPE_PEM);
+        if (res != SSL_SUCCESS)
+        {
+            LogError("wolfSSL_CTX_load_verify_buffer failed");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            result = 0;
+        }
+    }
+    else
+    {
+        result = 0;
+    }
+    return result;
+}
+
+static int x509_wolfssl_add_credentials(WOLFSSL* ssl, char* x509certificate, char* x509privatekey) {
+
+    int result;
+
+    if (wolfSSL_use_certificate_chain_buffer(ssl, (unsigned char*)x509certificate, strlen(x509certificate)) != SSL_SUCCESS)
+    {
+        LogError("unable to load x509 client certificate");
+        result = MU_FAILURE;
+    }
+    else if (wolfSSL_use_PrivateKey_buffer(ssl, (unsigned char*)x509privatekey, strlen(x509privatekey), SSL_FILETYPE_PEM) != SSL_SUCCESS)
+    {
+        LogError("unable to load x509 client private key");
+        result = MU_FAILURE;
+    }
+#ifdef HAVE_SECURE_RENEGOTIATION
+    else if (wolfSSL_UseSecureRenegotiation(ssl) != SSL_SUCCESS)
+    {
+        LogError("unable to enable secure renegotiation");
+        result = MU_FAILURE;
+    }
+#endif
+    else
+    {
+        result = 0;
+    }
+    return result;
+}
+
+static void destroy_wolfssl_instance(TLS_IO_INSTANCE* tls_io_instance)
+{
+    wolfSSL_free(tls_io_instance->ssl);
+    tls_io_instance->ssl = NULL;
+}
+
+static int create_wolfssl_instance(TLS_IO_INSTANCE* tls_io_instance)
+{
+    int result;
+    tls_io_instance->ssl = wolfSSL_new(tls_io_instance->ssl_context);
+    if (tls_io_instance->ssl == NULL)
+    {
+        LogError("Failed to add certificates to store");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        tls_io_instance->socket_io_read_bytes = NULL;
+        tls_io_instance->socket_io_read_byte_count = 0;
+        tls_io_instance->on_send_complete = NULL;
+        tls_io_instance->on_send_complete_callback_context = NULL;
+#ifdef INVALID_DEVID
+        tls_io_instance->wolfssl_device_id = INVALID_DEVID;
+#endif
+
+        wolfSSL_set_using_nonblock(tls_io_instance->ssl, 1);
+        wolfSSL_SetHsDoneCb(tls_io_instance->ssl, on_handshake_done, tls_io_instance);
+        wolfSSL_SetIOWriteCtx(tls_io_instance->ssl, tls_io_instance);
+        wolfSSL_SetIOReadCtx(tls_io_instance->ssl, tls_io_instance);
+
+        tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
+        result = 0;
+    }
+    return result;
+}
+
+static int prepare_wolfssl_open(TLS_IO_INSTANCE* tls_io_instance)
+{
+    int result;
+    if (add_certificate_to_store(tls_io_instance) != 0)
+    {
+        LogError("Failed to add certificates to store");
+        result = MU_FAILURE;
+    }
+    /*x509 authentication can only be build before underlying connection is realized*/
+    else if ((tls_io_instance->x509certificate != NULL) &&
+        (tls_io_instance->x509privatekey != NULL) &&
+        (x509_wolfssl_add_credentials(tls_io_instance->ssl, tls_io_instance->x509certificate, tls_io_instance->x509privatekey) != 0))
+    {
+        destroy_wolfssl_instance(tls_io_instance);
+        LogError("unable to use x509 authentication");
+        result = MU_FAILURE;
+    }
+#ifdef INVALID_DEVID
+    else if (tls_io_instance->wolfssl_device_id != INVALID_DEVID && wolfSSL_SetDevId(tls_io_instance->ssl, tls_io_instance->wolfssl_device_id) != WOLFSSL_SUCCESS)
+    {
+        LogError("Failure setting device id");
+        result = MU_FAILURE;
+    }
+#endif
+    else
+    {
+        result = 0;
+    }
+    return result;
+}
+
+int tlsio_wolfssl_init(void)
+{
+    (void)wolfSSL_library_init();
+    wolfSSL_load_error_strings();
+
+    return 0;
+}
+
+void tlsio_wolfssl_deinit(void)
+{
+}
+
+CONCRETE_IO_HANDLE tlsio_wolfssl_create(void* io_create_parameters)
+{
+    TLS_IO_INSTANCE* result;
+
+    if (io_create_parameters == NULL)
+    {
+        LogError("NULL io_create_parameters");
+        result = NULL;
+    }
+    else
+    {
+        TLSIO_CONFIG* tls_io_config = io_create_parameters;
+
+        result = (TLS_IO_INSTANCE*)malloc(sizeof(TLS_IO_INSTANCE));
+        if (result == NULL)
+        {
+            LogError("Failed allocating memory for the TLS IO instance.");
+        }
+        else
+        {
+            (void)memset(result, 0, sizeof(TLS_IO_INSTANCE));
+            result->tlsio_state = TLSIO_STATE_NOT_OPEN;
+
+            result->ssl_context = wolfSSL_CTX_new(wolfTLSv1_2_client_method());
+            if (result->ssl_context == NULL)
+            {
+                LogError("Cannot create the wolfSSL context");
+                free(result);
+                result = NULL;
+            }
+            else
+            {
+                // Set the recv and send function on the wolfssl context object
+                wolfSSL_SetIOSend(result->ssl_context, on_io_send);
+                wolfSSL_SetIORecv(result->ssl_context, on_io_recv);
+
+                SOCKETIO_CONFIG socketio_config;
+                const IO_INTERFACE_DESCRIPTION* underlying_io_interface;
+                void* io_interface_parameters;
+
+                if (tls_io_config->underlying_io_interface != NULL)
+                {
+                    underlying_io_interface = tls_io_config->underlying_io_interface;
+                    io_interface_parameters = tls_io_config->underlying_io_parameters;
+                }
+                else
+                {
+                    socketio_config.hostname = tls_io_config->hostname;
+                    socketio_config.port = tls_io_config->port;
+                    socketio_config.accepted_socket = NULL;
+
+                    underlying_io_interface = socketio_get_interface_description();
+                    io_interface_parameters = &socketio_config;
+                }
+
+                if (underlying_io_interface == NULL)
+                {
+                    LogError("Failed getting socket IO interface description.");
+                    wolfSSL_CTX_free(result->ssl_context);
+                    free(result);
+                    result = NULL;
+                }
+                else
+                {
+                    result->socket_io = xio_create(underlying_io_interface, io_interface_parameters);
+                    if (result->socket_io == NULL)
+                    {
+                        LogError("Failure connecting to underlying socket_io");
+                        wolfSSL_CTX_free(result->ssl_context);
+                        free(result);
+                        result = NULL;
+                    }
+                    else if (create_wolfssl_instance(result) != 0)
+                    {
+                        LogError("Failure connecting to underlying socket_io");
+                        wolfSSL_CTX_free(result->ssl_context);
+                        free(result);
+                        result = NULL;
+                    }
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+void tlsio_wolfssl_destroy(CONCRETE_IO_HANDLE tls_io)
+{
+    if (tls_io != NULL)
+    {
+        TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
+        if (tls_io_instance->socket_io_read_bytes != NULL)
+        {
+            free(tls_io_instance->socket_io_read_bytes);
+            tls_io_instance->socket_io_read_bytes = NULL;
+        }
+        if (tls_io_instance->certificate != NULL)
+        {
+            free(tls_io_instance->certificate);
+            tls_io_instance->certificate = NULL;
+        }
+        if (tls_io_instance->x509certificate != NULL)
+        {
+            free(tls_io_instance->x509certificate);
+            tls_io_instance->x509certificate = NULL;
+        }
+        if (tls_io_instance->x509privatekey != NULL)
+        {
+            free(tls_io_instance->x509privatekey);
+            tls_io_instance->x509privatekey = NULL;
+        }
+        destroy_wolfssl_instance(tls_io_instance);
+
+        wolfSSL_CTX_free(tls_io_instance->ssl_context);
+        tls_io_instance->ssl_context = NULL;
+
+        xio_destroy(tls_io_instance->socket_io);
+        free(tls_io);
+    }
+}
+
+int tlsio_wolfssl_open(CONCRETE_IO_HANDLE tls_io, ON_IO_OPEN_COMPLETE on_io_open_complete, void* on_io_open_complete_context, ON_BYTES_RECEIVED on_bytes_received, void* on_bytes_received_context, ON_IO_ERROR on_io_error, void* on_io_error_context)
+{
+    int result;
+
+    if (tls_io == NULL)
+    {
+        LogError("NULL tls_io instance");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
+
+        if (tls_io_instance->tlsio_state != TLSIO_STATE_NOT_OPEN)
+        {
+            LogError("Invalid state encountered.");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            tls_io_instance->on_bytes_received = on_bytes_received;
+            tls_io_instance->on_bytes_received_context = on_bytes_received_context;
+
+            tls_io_instance->on_io_open_complete = on_io_open_complete;
+            tls_io_instance->on_io_open_complete_context = on_io_open_complete_context;
+
+            tls_io_instance->on_io_error = on_io_error;
+            tls_io_instance->on_io_error_context = on_io_error_context;
+
+            tls_io_instance->tlsio_state = TLSIO_STATE_OPENING_UNDERLYING_IO;
+
+            if (prepare_wolfssl_open(tls_io_instance) != 0)
+            {
+                LogError("Cannot create wolfssl instance.");
+                tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
+                result = MU_FAILURE;
+            }
+            else if (xio_open(tls_io_instance->socket_io, on_underlying_io_open_complete, tls_io_instance, on_underlying_io_bytes_received, tls_io_instance, on_underlying_io_error, tls_io_instance) != 0)
+            {
+                LogError("Cannot open the underlying IO.");
+                tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
+                result = MU_FAILURE;
+            }
+            else
+            {
+                // The state can get changed in the on_underlying_io_open_complete
+                if (tls_io_instance->tlsio_state != TLSIO_STATE_OPEN)
+                {
+                    LogError("Failed to connect to server.  The certificates may not be correct.");
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    result = 0;
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+int tlsio_wolfssl_close(CONCRETE_IO_HANDLE tls_io, ON_IO_CLOSE_COMPLETE on_io_close_complete, void* callback_context)
+{
+    int result = 0;
+
+    if (tls_io == NULL)
+    {
+        LogError("NULL tls_io handle.");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
+
+        if ((tls_io_instance->tlsio_state == TLSIO_STATE_NOT_OPEN) ||
+            (tls_io_instance->tlsio_state == TLSIO_STATE_CLOSING))
+        {
+            LogError("Close called while not open.");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            tls_io_instance->tlsio_state = TLSIO_STATE_CLOSING;
+            tls_io_instance->on_io_close_complete = on_io_close_complete;
+            tls_io_instance->on_io_close_complete_context = callback_context;
+
+            if (xio_close(tls_io_instance->socket_io, on_underlying_io_close_complete, tls_io_instance) != 0)
+            {
+                LogError("xio_close failed.");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                result = 0;
+            }
+        }
+    }
+
+    return result;
+}
+
+int tlsio_wolfssl_send(CONCRETE_IO_HANDLE tls_io, const void* buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void* callback_context)
+{
+    int result;
+
+    if (tls_io == NULL || buffer == NULL || size == 0)
+    {
+        LogError("Invalid parameter specified tls_io: %p, buffer: %p, size: %ul", tls_io, buffer, (unsigned int)size);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
+
+        if (tls_io_instance->tlsio_state != TLSIO_STATE_OPEN)
+        {
+            LogError("send called while not open");
+            result = MU_FAILURE;
+        }
+        if (tls_io_instance->on_send_complete != NULL)
+        {
+            LogError("Error writing data");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            tls_io_instance->on_send_complete = on_send_complete;
+            tls_io_instance->on_send_complete_callback_context = callback_context;
+
+            int res = wolfSSL_write(tls_io_instance->ssl, buffer, size);
+            if ((res < 0) || ((size_t)res != size)) // Best way I can think of to safely compare an int to a size_t
+            {
+                LogError("Error writing data through WolfSSL");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                result = 0;
+            }
+        }
+    }
+
+    return result;
+}
+
+void tlsio_wolfssl_dowork(CONCRETE_IO_HANDLE tls_io)
+{
+    if (tls_io == NULL)
+    {
+        LogError("NULL tls_io");
+    }
+    else
+    {
+        TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
+
+        if ((tls_io_instance->tlsio_state != TLSIO_STATE_NOT_OPEN) &&
+            (tls_io_instance->tlsio_state != TLSIO_STATE_ERROR))
+        {
+            if (tls_io_instance->tlsio_state != TLSIO_STATE_OPENING_UNDERLYING_IO)
+                decode_ssl_received_bytes(tls_io_instance);
+            xio_dowork(tls_io_instance->socket_io);
+        }
+    }
+}
+
+
+static int process_option(char** destination, const char* name, const char* value)
+{
+    int result;
+    if (*destination != NULL)
+    {
+        free(*destination);
+        *destination = NULL;
+    }
+    if (mallocAndStrcpy_s(destination, value) != 0)
+    {
+        LogError("unable to process option %s",name);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        result = 0;
+    }
+    return result;
+}
+
+int tlsio_wolfssl_setoption(CONCRETE_IO_HANDLE tls_io, const char* optionName, const void* value)
+{
+    int result;
+
+    if (tls_io == NULL || optionName == NULL)
+    {
+        LogError("Bad arguments, tls_io = %p, optionName = %p", tls_io, optionName);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
+
+        if (strcmp(OPTION_TRUSTED_CERT, optionName) == 0)
+        {
+            result  = process_option(&tls_io_instance->certificate, optionName, value);
+        }
+        else if (strcmp(SU_OPTION_X509_CERT, optionName) == 0 || strcmp(OPTION_X509_ECC_CERT, optionName) == 0)
+        {
+            result = process_option(&tls_io_instance->x509certificate, optionName, value);
+        }
+        else if (strcmp(SU_OPTION_X509_PRIVATE_KEY, optionName) == 0 || strcmp(OPTION_X509_ECC_KEY, optionName) == 0)
+        {
+            result = process_option(&tls_io_instance->x509privatekey, optionName, value);
+        }
+        else if (strcmp(optionName, OPTION_SET_TLS_RENEGOTIATION) == 0)
+        {
+            // No need to do anything for WolfSSL
+            result = 0;
+        }
+#ifdef INVALID_DEVID
+        else if (strcmp(OPTION_WOLFSSL_SET_DEVICE_ID, optionName) == 0)
+        {
+            int device_id = *((int *)value);
+            if (tls_io_instance->ssl != NULL)
+            {
+                if (tls_io_instance->ssl != NULL && wolfSSL_SetDevId(tls_io_instance->ssl, device_id) != WOLFSSL_SUCCESS)
+                {
+                    LogError("Failure setting device id on ssl");
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    result = 0;
+                }
+            }
+            else
+            {
+                // Save the id till we create the ssl object
+                tls_io_instance->wolfssl_device_id = device_id;
+                result = 0;
+            }
+        }
+#endif
+        else
+        {
+            if (tls_io_instance->socket_io == NULL)
+            {
+                LogError("NULL underlying IO handle");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                result = xio_setoption(tls_io_instance->socket_io, optionName, value);
+            }
+        }
+    }
+
+    return result;
+}
+const IO_INTERFACE_DESCRIPTION* tlsio_wolfssl_get_interface_description(void)
+{
+    return &tlsio_wolfssl_interface_description;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/uniqueid_stub.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/uniqueid_stub.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/uniqueid_stub.c	(revision 453)
@@ -0,0 +1,76 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <stdint.h>
+#include "azure_c_shared_utility/uniqueid.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include <time.h>
+
+MU_DEFINE_ENUM_STRINGS(UNIQUEID_RESULT, UNIQUEID_RESULT_VALUES);
+
+static const char tochar[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+static void generate128BitUUID(unsigned char* arrayOfByte)
+{
+    size_t arrayIndex;
+
+    for (arrayIndex = 0; arrayIndex < 16; arrayIndex++)
+    {
+        arrayOfByte[arrayIndex] = (unsigned char)rand();
+    }
+
+    //
+    // Stick in the version field for random uuid.
+    //
+    arrayOfByte[7] &= 0x0f; //clear the bit field
+    arrayOfByte[7] |= 0x40; //set the ones we care about
+
+    //
+    // Stick in the variant field for the random uuid.
+    //
+    arrayOfByte[8] &= 0xf3; // Clear
+    arrayOfByte[8] |= 0x08; // Set
+
+}
+
+// TODO: The User will need to call srand before calling this function
+UNIQUEID_RESULT UniqueId_Generate(char* uid, size_t len)
+{
+    UNIQUEID_RESULT result;
+    unsigned char arrayOfChar[16];
+
+    /* Codes_SRS_UNIQUEID_07_002: [If uid is NULL then UniqueId_Generate shall return UNIQUEID_INVALID_ARG] */
+    /* Codes_SRS_UNIQUEID_07_003: [If len is less then 37 then UniqueId_Generate shall return UNIQUEID_INVALID_ARG] */
+    if (uid == NULL || len < 37)
+    {
+        result = UNIQUEID_INVALID_ARG;
+        LogError("Buffer Size is Null or length is less then 37 bytes");
+    }
+    else 
+    {
+        size_t arrayIndex;
+        size_t shiftCount;
+        size_t characterPosition = 0;
+
+        /* Codes_SRS_UNIQUEID_07_001: [UniqueId_Generate shall create a unique Id 36 character long string.] */
+        generate128BitUUID(arrayOfChar);
+        for (arrayIndex = 0; arrayIndex < 16; arrayIndex++)
+        {
+            for (shiftCount = 0; shiftCount <= 1; shiftCount++)
+            {
+                char hexChar = tochar[arrayOfChar[arrayIndex] & 0xf];
+                if ((characterPosition == 8) || (characterPosition == 13) || (characterPosition == 18) || (characterPosition == 23))
+                {
+                    uid[characterPosition] = '-';
+                    characterPosition++;
+                }
+                uid[characterPosition] = hexChar;
+                characterPosition++;
+                arrayOfChar[arrayIndex] = arrayOfChar[arrayIndex] >> 4;
+            }
+        }
+        uid[characterPosition] = 0;
+        result = UNIQUEID_OK;
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/agenttime.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/agenttime.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/agenttime.h	(revision 453)
@@ -0,0 +1,63 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/** @file agenttime.h
+*	@brief Function prototypes for time related functions.
+*
+*	@details These functions are implemented with C standard functions,
+*	and therefore they are platform independent. But then a platform
+*	can replace these functions with its own implementation as necessary.
+*/
+
+#ifndef AGENTTIME_H
+#define AGENTTIME_H
+
+#include <time.h>
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/** @brief Get current calendar time.
+*
+*	@details This function provides the same functionality as the
+*	standard C @c time() function.
+*/
+MOCKABLE_FUNCTION(, time_t, get_time, time_t*, currentTime);
+
+/** @brief Get UTC in @c tm struct.
+*
+*	@details This function provides the same functionality as the
+*	standard C @c gmtime() function.
+*/
+MOCKABLE_FUNCTION(, struct tm*, get_gmtime, time_t*, currentTime);
+
+/** @brief Get current time representation of the given calendar time.
+*
+*	@details This function provides the same functionality as the
+*	standard C @c mktime() function.
+*/
+MOCKABLE_FUNCTION(, time_t, get_mktime, struct tm*, cal_time);
+
+/** @brief Gets a C-string representation of the given time.
+*
+*	@details This function provides the same functionality as the
+*	standard C @c ctime() function.
+*/
+MOCKABLE_FUNCTION(, char*, get_ctime, time_t*, timeToGet);
+
+/** @brief Gets the difference in seconds between @c stopTime and
+*	@c startTime.
+*
+*	@details This function provides the same functionality as the
+*	standard C @c difftime() function.
+*/
+MOCKABLE_FUNCTION(, double, get_difftime, time_t, stopTime, time_t, startTime);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // AGENTTIME_H
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/azure_base32.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/azure_base32.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/azure_base32.h	(revision 453)
@@ -0,0 +1,63 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef AZURE_BASE32_H
+#define AZURE_BASE32_H
+
+#ifdef __cplusplus
+#include <cstddef>
+#else
+#include <stddef.h>
+#endif
+
+#include "azure_c_shared_utility/strings.h"
+#include "azure_c_shared_utility/buffer_.h"
+
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+* @brief Encodes the BUFFER_HANDLE to a base 32 STRING_HANDLE
+*
+* @param    input   BUFFER_HANDLE of the unsigned char* to be encoded
+*
+* @return   A base32 encoded STRING_HANDLE that will need to be deallocated
+*/
+MOCKABLE_FUNCTION(, STRING_HANDLE, Azure_Base32_Encode, BUFFER_HANDLE, input);
+
+/**
+* @brief    Encodes the BUFFER_HANDLE to a base 32 char*
+*
+* @param    source   An unsigned char* to be encoded
+* @param    size     The lenght in bytes of the source variable
+*
+* @return   A base32 encoded string that will need to be deallocated
+*/
+MOCKABLE_FUNCTION(, char*, Azure_Base32_Encode_Bytes, const unsigned char*, source, size_t, size);
+
+/**
+* @brief    Decodes a base32 encoded STRING_HANDLE to a BUFFER_HANDLE
+*
+* @param    handle   STRING_HANDLE of a base32 encode string
+*
+* @return   A BUFFER_HANDLE of the result of decoding the handle
+*/
+MOCKABLE_FUNCTION(, BUFFER_HANDLE, Azure_Base32_Decode, STRING_HANDLE, handle);
+
+/**
+* @brief    Decodes a base32 encoded char* to a BUFFER_HANDLE
+*
+* @param    source   char* of a base32 encode string
+*
+* @return   A BUFFER_HANDLE of the result of decoding the source
+*/
+MOCKABLE_FUNCTION(, BUFFER_HANDLE, Azure_Base32_Decode_String, const char*, source);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AZURE_BASE32_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/azure_base64.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/azure_base64.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/azure_base64.h	(revision 453)
@@ -0,0 +1,85 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/** @file azure_base64.h
+*    @brief Prototypes for functions related to encoding/decoding
+*    a @c buffer using standard base64 encoding.
+*/
+
+#ifndef AZURE_BASE64_H
+#define AZURE_BASE64_H
+
+#ifdef __cplusplus
+#include <cstddef>
+#else
+#include <stddef.h>
+#endif
+
+#include "azure_c_shared_utility/strings.h"
+#include "azure_c_shared_utility/buffer_.h"
+
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief    Base64 encodes a buffer and returns the resulting string.
+ *
+ * @param    input    The buffer that needs to be base64 encoded.
+ *
+ *             Azure_Base64_Encode takes as a parameter a pointer to a BUFFER. If @p input is @c NULL then
+ *             @c Azure_Base64_Encode returns @c NULL. The size of the BUFFER pointed to by @p input may
+ *             be zero. If when allocating memory to produce the encoding a failure occurs, then @c
+ *             Azure_Base64_Encode returns @c NULL. Otherwise
+ *             @c Azure_Base64_Encode returns a pointer to a STRING. That string contains the
+ *             base 64 encoding of the @p input. This encoding of @p input will not contain embedded
+ *             line feeds.
+ *
+ * @return    A @c STRING_HANDLE containing the base64 encoding of @p input.
+ */
+MOCKABLE_FUNCTION(, STRING_HANDLE, Azure_Base64_Encode, BUFFER_HANDLE, input);
+
+/**
+ * @brief    Base64 encodes the buffer pointed to by @p source and returns the resulting string.
+ *
+ * @param    source    The buffer that needs to be base64 encoded.
+ * @param    size      The size.
+ *
+ *             This function produces a @c STRING_HANDLE containing the base64 encoding of the
+ *             buffer pointed to by @p source, having the size as given by
+ *             @p size. If @p source is @c NULL then @c Azure_Base64_Encode_Bytes returns @c NULL
+ *             If @p source is not @c NULL and @p size is zero, then @c Azure_Base64_Encode_Bytes produces
+ *             an empty @c STRING_HANDLE. Otherwise, @c Azure_Base64_Encode_Bytes produces a
+ *             @c STRING_HANDLE containing the Base64 representation of the buffer. In case of
+ *             any errors, @c Azure_Base64_Encode_Bytes returns @c NULL.].
+ *
+ * @return    @c NULL in case an error occurs or a @c STRING_HANDLE containing the base64 encoding
+ *             of @p input.
+ *
+ */
+MOCKABLE_FUNCTION(, STRING_HANDLE, Azure_Base64_Encode_Bytes, const unsigned char*, source, size_t, size);
+
+/**
+ * @brief    Base64 decodes the buffer pointed to by @p source and returns the resulting buffer.
+ *
+ * @param    source    A base64 encoded string buffer.
+ *
+ *           This function decodes the string pointed at by @p source using base64 decoding and
+ *             returns the resulting buffer. If @p source is @c NULL then
+ *             @c Azure_Base64_Decode returns NULL. If the string pointed to by @p source is zero
+ *             length then the handle returned refers to a zero length buffer. If there is any
+ *             memory allocation failure during the decode or if the source string has an invalid
+ *             length for a base 64 encoded string then @c Azure_Base64_Decode returns @c NULL.
+ *
+ * @return    A @c BUFFER_HANDLE pointing to a buffer containing the result of base64 decoding @p
+ *             source.
+ */
+MOCKABLE_FUNCTION(, BUFFER_HANDLE, Azure_Base64_Decode, const char*, source);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AZURE_BASE64_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/buffer_.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/buffer_.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/buffer_.h	(revision 453)
@@ -0,0 +1,46 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef BUFFER__H
+#define BUFFER__H
+
+#ifdef __cplusplus
+#include <cstddef>
+#else
+#include <stddef.h>
+#include <stdbool.h>
+#endif
+
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef struct BUFFER_TAG* BUFFER_HANDLE;
+
+MOCKABLE_FUNCTION(, BUFFER_HANDLE, BUFFER_new);
+MOCKABLE_FUNCTION(, BUFFER_HANDLE, BUFFER_create, const unsigned char*, source, size_t, size);
+MOCKABLE_FUNCTION(, BUFFER_HANDLE, BUFFER_create_with_size, size_t, buff_size);
+MOCKABLE_FUNCTION(, void, BUFFER_delete, BUFFER_HANDLE, handle);
+MOCKABLE_FUNCTION(, int, BUFFER_pre_build, BUFFER_HANDLE, handle, size_t, size);
+MOCKABLE_FUNCTION(, int, BUFFER_build, BUFFER_HANDLE, handle, const unsigned char*, source, size_t, size);
+MOCKABLE_FUNCTION(, int, BUFFER_append_build, BUFFER_HANDLE, handle, const unsigned char*, source, size_t, size);
+MOCKABLE_FUNCTION(, int, BUFFER_unbuild, BUFFER_HANDLE, handle);
+MOCKABLE_FUNCTION(, int, BUFFER_enlarge, BUFFER_HANDLE, handle, size_t, enlargeSize);
+MOCKABLE_FUNCTION(, int, BUFFER_shrink, BUFFER_HANDLE, handle, size_t, decreaseSize, bool, fromEnd);
+MOCKABLE_FUNCTION(, int, BUFFER_content, BUFFER_HANDLE, handle, const unsigned char**, content);
+MOCKABLE_FUNCTION(, int, BUFFER_size, BUFFER_HANDLE, handle, size_t*, size);
+MOCKABLE_FUNCTION(, int, BUFFER_append, BUFFER_HANDLE, handle1, BUFFER_HANDLE, handle2);
+MOCKABLE_FUNCTION(, int, BUFFER_prepend, BUFFER_HANDLE, handle1, BUFFER_HANDLE, handle2);
+MOCKABLE_FUNCTION(, int, BUFFER_fill, BUFFER_HANDLE, handle, unsigned char, fill_char);
+MOCKABLE_FUNCTION(, unsigned char*, BUFFER_u_char, BUFFER_HANDLE, handle);
+MOCKABLE_FUNCTION(, size_t, BUFFER_length, BUFFER_HANDLE, handle);
+MOCKABLE_FUNCTION(, BUFFER_HANDLE, BUFFER_clone, BUFFER_HANDLE, handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* BUFFER__H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/condition.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/condition.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/condition.h	(revision 453)
@@ -0,0 +1,72 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef CONDITION_H
+#define CONDITION_H
+
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/lock.h"
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void* COND_HANDLE;
+
+#define COND_RESULT_VALUES \
+    COND_OK, \
+    COND_INVALID_ARG, \
+    COND_ERROR, \
+    COND_TIMEOUT \
+
+/**
+* @brief Enumeration specifying the lock status.
+*/
+MU_DEFINE_ENUM(COND_RESULT, COND_RESULT_VALUES);
+
+/**
+* @brief	This API creates and returns a valid condition handle.
+*
+* @return	A valid @c COND_HANDLE when successful or @c NULL otherwise.
+*/
+MOCKABLE_FUNCTION(, COND_HANDLE, Condition_Init);
+
+/**
+* @brief	unblock all currently working condition.
+*
+* @param	handle	A valid handle to the lock.
+*
+* @return	Returns @c COND_OK when the condition object has been
+* 			destroyed and @c COND_ERROR when an error occurs
+* 			and @c COND_TIMEOUT when the handle times out.
+*/
+MOCKABLE_FUNCTION(, COND_RESULT, Condition_Post, COND_HANDLE, handle);
+
+/**
+* @brief	block on the condition handle unti the thread is signalled
+*           or until the timeout_milliseconds is reached.
+*
+* @param	handle	A valid handle to the lock.
+*
+* @return	Returns @c COND_OK when the condition object has been
+* 			destroyed and @c COND_ERROR when an error occurs
+* 			and @c COND_TIMEOUT when the handle times out.
+*/
+MOCKABLE_FUNCTION(, COND_RESULT, Condition_Wait, COND_HANDLE, handle, LOCK_HANDLE, lock, int, timeout_milliseconds);
+
+/**
+* @brief	The condition instance is deinitialized.
+*
+* @param	handle	A valid handle to the condition.
+*
+* @return	Returns @c COND_OK when the condition object has been
+* 			destroyed and @c COND_ERROR when an error occurs.
+*/
+MOCKABLE_FUNCTION(, void, Condition_Deinit, COND_HANDLE, handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONDITION_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/connection_string_parser.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/connection_string_parser.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/connection_string_parser.h	(revision 453)
@@ -0,0 +1,26 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef CONNECTION_STRING_PARSER_H
+#define CONNECTION_STRING_PARSER_H
+
+#include "azure_c_shared_utility/map.h"
+#include "azure_c_shared_utility/strings.h"
+
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    MOCKABLE_FUNCTION(, MAP_HANDLE, connectionstringparser_parse_from_char, const char*, connection_string);
+    MOCKABLE_FUNCTION(, MAP_HANDLE, connectionstringparser_parse, STRING_HANDLE, connection_string);
+    MOCKABLE_FUNCTION(, int, connectionstringparser_splitHostName_from_char, const char*, hostName, STRING_HANDLE, nameString, STRING_HANDLE, suffixString);
+    MOCKABLE_FUNCTION(, int, connectionstringparser_splitHostName, STRING_HANDLE, hostNameString, STRING_HANDLE, nameString, STRING_HANDLE, suffixString);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONNECTION_STRING_PARSER_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/consolelogger.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/consolelogger.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/consolelogger.h	(revision 453)
@@ -0,0 +1,23 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef CONSOLELOGGER_H
+#define CONSOLELOGGER_H
+
+#include "azure_c_shared_utility/xlogging.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+    void consolelogger_log(LOG_CATEGORY log_category, const char* file, const char* func, int line, unsigned int options, const char* format, ...);
+
+#if (defined(_MSC_VER))
+    void consolelogger_log_with_GetLastError(const char* file, const char* func, int line, const char* format, ...);
+#endif
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* CONSOLELOGGER_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/const_defines.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/const_defines.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/const_defines.h	(revision 453)
@@ -0,0 +1,26 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef CONST_DEFINES_H
+#define CONST_DEFINES_H
+
+// Used to remove GCC warning unused
+#ifdef __GNUC__
+    #define STATIC_VAR_UNUSED __attribute__ ((unused))
+#else
+    #define STATIC_VAR_UNUSED
+#endif
+
+#ifndef AZURE_UNREFERENCED_PARAMETER
+#define AZURE_UNREFERENCED_PARAMETER(param)   (void)(param)
+#endif
+
+#ifdef _MSC_VER
+#define AZURE_DEPRECATED __declspec(deprecated)
+#elif defined(__GNUC__) | defined(__clang__)
+#define AZURE_DEPRECATED __attribute__((__deprecated__))
+#else
+#define AZURE_DEPRECATED
+#endif
+
+#endif // CONST_DEFINES
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/constbuffer.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/constbuffer.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/constbuffer.h	(revision 453)
@@ -0,0 +1,61 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef CONSTBUFFER_H
+#define CONSTBUFFER_H
+
+#ifdef __cplusplus
+#include <cstddef>
+#else
+#include <stddef.h>
+#include <stdbool.h>
+#endif
+
+#include "azure_c_shared_utility/buffer_.h"
+
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*this is the handle*/
+typedef struct CONSTBUFFER_HANDLE_DATA_TAG* CONSTBUFFER_HANDLE;
+
+/*this is what is returned when the content of the buffer needs access*/
+typedef struct CONSTBUFFER_TAG
+{
+    const unsigned char* buffer;
+    size_t size;
+} CONSTBUFFER;
+
+typedef void(*CONSTBUFFER_CUSTOM_FREE_FUNC)(void* context);
+
+MOCKABLE_INTERFACE(constbuffer,
+    /*this creates a new constbuffer from a memory area*/
+    FUNCTION(, CONSTBUFFER_HANDLE, CONSTBUFFER_Create, const unsigned char*, source, size_t, size),
+
+    /*this creates a new constbuffer from an existing BUFFER_HANDLE*/
+    FUNCTION(, CONSTBUFFER_HANDLE, CONSTBUFFER_CreateFromBuffer, BUFFER_HANDLE, buffer),
+
+    FUNCTION(, CONSTBUFFER_HANDLE, CONSTBUFFER_CreateWithMoveMemory, unsigned char*, source, size_t, size),
+
+    FUNCTION(, CONSTBUFFER_HANDLE, CONSTBUFFER_CreateWithCustomFree, const unsigned char*, source, size_t, size, CONSTBUFFER_CUSTOM_FREE_FUNC, customFreeFunc, void*, customFreeFuncContext),
+
+    FUNCTION(, CONSTBUFFER_HANDLE, CONSTBUFFER_CreateFromOffsetAndSize, CONSTBUFFER_HANDLE, handle, size_t, offset, size_t, size),
+
+    FUNCTION(, void, CONSTBUFFER_IncRef, CONSTBUFFER_HANDLE, constbufferHandle),
+
+    FUNCTION(, void, CONSTBUFFER_DecRef, CONSTBUFFER_HANDLE, constbufferHandle),
+
+    FUNCTION(, const CONSTBUFFER*, CONSTBUFFER_GetContent, CONSTBUFFER_HANDLE, constbufferHandle),
+
+    FUNCTION(, bool, CONSTBUFFER_HANDLE_contain_same, CONSTBUFFER_HANDLE, left, CONSTBUFFER_HANDLE, right)
+)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* CONSTBUFFER_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/constmap.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/constmap.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/constmap.h	(revision 453)
@@ -0,0 +1,134 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/** @file       constmap.h
+*    @brief        ConstMap is a module that implements a read-only dictionary
+*           of @c const char* keys to @c const char* values.
+*/
+
+#ifndef CONSTMAP_H
+#define CONSTMAP_H
+
+#ifdef __cplusplus
+#include <cstddef>
+#else
+#include <stddef.h>
+#endif
+
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/map.h"
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define CONSTMAP_RESULT_VALUES \
+    CONSTMAP_OK, \
+    CONSTMAP_ERROR, \
+    CONSTMAP_INVALIDARG, \
+    CONSTMAP_KEYNOTFOUND
+
+/** @brief Enumeration specifying the status of calls to various APIs in this
+ *  module.
+ */
+MU_DEFINE_ENUM(CONSTMAP_RESULT, CONSTMAP_RESULT_VALUES);
+
+typedef struct CONSTMAP_HANDLE_DATA_TAG* CONSTMAP_HANDLE;
+
+
+/**
+ * @brief   Creates a new read-only map from a map handle.
+ *
+ * @param   sourceMap   The map from which we will populate key,value
+ *                      into the read-only map.
+ *
+ * @return  A valid @c CONSTMAP_HANDLE or @c NULL in case an error occurs.
+ */
+MOCKABLE_FUNCTION(, CONSTMAP_HANDLE, ConstMap_Create, MAP_HANDLE, sourceMap);
+
+ /**
+  * @brief  Destroy a read-only map.  Deallocate memory associated with handle.
+  * @param  handle      Handle to a read-only map.
+  */
+MOCKABLE_FUNCTION(, void, ConstMap_Destroy, CONSTMAP_HANDLE, handle);
+
+ /**
+  * @brief  Clone a read-only map from another read-only map.
+  * @param  handle      Handle to a read-only map.
+  * @return A valid @c CONSTMAP_HANDLE or @c NULL in case an error occurs.
+  */
+MOCKABLE_FUNCTION(, CONSTMAP_HANDLE, ConstMap_Clone, CONSTMAP_HANDLE, handle);
+
+ /**
+  * @brief  Create a map handle populated from the read-only map.
+  * @param  handle      Handle to a read-only map.
+  * @return A valid @c MAP_HANDLE or @c NULL in case an error occurs.
+  *
+  * The new MAP_HANDLE needs to be destroyed when it is no longer needed.
+  */
+MOCKABLE_FUNCTION(, MAP_HANDLE, ConstMap_CloneWriteable, CONSTMAP_HANDLE, handle);
+
+/**
+ * @brief   This function returns a true if the map contains a key
+ *            with the same value the parameter @p key.
+ *
+ * @param   handle      The handle to an existing map.
+ * @param   key         The key that the caller wants checked.
+ *
+ * @return                The function returns @c true if the key exists
+ *                        in the map and @c false if key is not found or
+ *                        parameters are invalid.
+ */
+MOCKABLE_FUNCTION(, bool, ConstMap_ContainsKey, CONSTMAP_HANDLE, handle, const char*, key);
+
+/**
+ * @brief   This function returns @c true if at least one <key,value> pair
+ *            exists in the map where the entry's value is equal to the
+ *            parameter @c value.
+ *
+ * @param   handle          The handle to an existing map.
+ * @param   value           The value that the caller wants checked.
+ *
+ * @return                    The function returns @c true if the value exists
+ *                            in the map and @c false if value is not found or
+ *                            parameters are invalid.
+ */
+MOCKABLE_FUNCTION(, bool, ConstMap_ContainsValue, CONSTMAP_HANDLE, handle, const char*, value);
+
+/**
+ * @brief   Retrieves the value of a stored key.
+ *
+ * @param   handle  The handle to an existing map.
+ * @param   key     The key to be looked up in the map.
+ *
+ * @return  Returns @c NULL in case the input arguments are @c NULL or if the
+ *          requested key is not found in the map. Returns a pointer to the
+ *          key's value otherwise.
+ */
+MOCKABLE_FUNCTION(, const char*, ConstMap_GetValue, CONSTMAP_HANDLE, handle, const char*, key);
+
+ /**
+ * @brief   Retrieves the complete list of keys and values from the map
+ *          in @p values and @p keys. Also writes the size of the list
+ *          in @p count.
+ *
+ * @param   handle      The handle to an existing map.
+ * @param   keys        The location where the list of keys is to be written.
+ * @param   values      The location where the list of values is to be written.
+ * @param   count       The number of stored keys and values is written at the
+ *                      location indicated by this pointer.
+ *
+ * @return  Returns @c CONSTMAP_OK if the keys and values are retrieved
+ *                     and written successfully or an error code otherwise.
+ */
+MOCKABLE_FUNCTION(, CONSTMAP_RESULT, ConstMap_GetInternals, CONSTMAP_HANDLE, handle, const char*const**, keys, const char*const**, values, size_t*, count);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONSTMAP_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/crt_abstractions.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/crt_abstractions.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/crt_abstractions.h	(revision 453)
@@ -0,0 +1,135 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef CRT_ABSTRACTIONS_H
+#define CRT_ABSTRACTIONS_H
+
+#ifdef __cplusplus
+#include <cstdio>
+#include <cstring>
+#include <cerrno>
+#include <cmath>
+#else // __cplusplus
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#endif // __cplusplus
+
+#include "umock_c/umock_c_prod.h"
+
+#ifdef _MSC_VER
+
+#ifdef QUARKGALILEO
+#define HAS_STDBOOL
+#ifdef __cplusplus
+typedef bool _Bool;
+#else
+/*galileo apparently has _Bool and bool as built in types*/
+#endif
+#endif // QUARKGALILEO
+
+#define HAS_STDBOOL
+#ifdef __cplusplus
+/*because C++ doesn't do anything about _Bool... */
+#define _Bool bool
+#else // __cplusplus
+#include <stdbool.h>
+#endif // __cplusplus
+
+#else //  _MSC_VER
+
+#if defined __STDC_VERSION__
+#if ((__STDC_VERSION__  == 199901L) || (__STDC_VERSION__ == 201000L) || (__STDC_VERSION__ == 201112L) || (__STDC_VERSION__ == 201710L))
+/*C99, C11 (including GNU 4.6) or C18 compiler */
+#define HAS_STDBOOL
+#include <stdbool.h>
+#endif //  ((__STDC_VERSION__  == 199901L) || (__STDC_VERSION__ == 201000L) || (__STDC_VERSION__ == 201112L) || (__STDC_VERSION__ == 201710L))
+#endif // __STDC_VERSION__
+#endif //  _MSC_VER
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#ifndef HAS_STDBOOL
+#ifdef __cplusplus
+#define _Bool bool
+#else // __cplusplus
+typedef unsigned char _Bool;
+typedef unsigned char bool;
+#define false 0
+#define true 1
+#endif // __cplusplus
+#endif // HAS_STDBOOL
+
+
+/* Codes_SRS_CRT_ABSTRACTIONS_99_001:[The module shall not redefine the secure functions implemented by Microsoft CRT.] */
+/* Codes_SRS_CRT_ABSTRACTIONS_99_040 : [The module shall still compile when building on a Microsoft platform.] */
+/* Codes_SRS_CRT_ABSTRACTIONS_99_002: [CRTAbstractions module shall expose the following API]*/
+#if defined (_MSC_VER) || defined (MINGW_HAS_SECURE_API)
+#else // _MSC_VER || MINGW_HAS_SECURE_API
+
+/* Adding definitions from errno.h & crtdefs.h */
+#if !defined (_TRUNCATE)
+#define _TRUNCATE ((size_t)-1)
+#endif  /* !defined (_TRUNCATE) */
+
+#if !defined STRUNCATE
+#define STRUNCATE       80
+#endif  /* !defined (STRUNCATE) */
+
+int strcpy_s(char* dst, size_t dstSizeInBytes, const char* src);
+int strcat_s(char* dst, size_t dstSizeInBytes, const char* src);
+int strncpy_s(char* dst, size_t dstSizeInBytes, const char* src, size_t maxCount);
+int sprintf_s(char* dst, size_t dstSizeInBytes, const char* format, ...);
+#endif // _MSC_VER || MINGW_HAS_SECURE_API
+
+unsigned long long strtoull_s(const char* nptr, char** endPtr, int base);
+float strtof_s(const char* nptr, char** endPtr);
+long double strtold_s(const char* nptr, char** endPtr);
+
+#ifdef _MSC_VER
+#define stricmp _stricmp
+#endif // _MSC_VER
+
+MOCKABLE_FUNCTION(, int, mallocAndStrcpy_s, char**, destination, const char*, source);
+MOCKABLE_FUNCTION(, int, unsignedIntToString, char*, destination, size_t, destinationSize, unsigned int, value);
+MOCKABLE_FUNCTION(, int, size_tToString, char*, destination, size_t, destinationSize, size_t, value);
+
+/*following logic shall define the TOUPPER and ISDIGIT, we do that because the SDK is not happy with some Arduino implementation of it.*/
+#define TOUPPER(c)      ((((c)>='a') && ((c)<='z'))?(c)-'a'+'A':c)
+#define ISDIGIT(c)      ((((c)>='0') && ((c)<='9'))?1:0)
+
+/*following logic shall define the ISNAN macro*/
+/*if runing on Microsoft Visual C compiler, than ISNAN shall be _isnan*/
+/*else if running on C99 or C11, ISNAN shall be isnan*/
+/*else if running on C89 ... #error and inform user*/
+
+#ifdef _MSC_VER
+#define ISNAN _isnan
+#else // _MSC_VER
+#if defined __STDC_VERSION__
+#if ((__STDC_VERSION__  == 199901L) || (__STDC_VERSION__ == 201000L) || (__STDC_VERSION__ == 201112L) || (__STDC_VERSION__ == 201710L))
+/*C99, C11 (including GNU 4.6) or C18 compiler */
+#define ISNAN isnan
+#else //  ((__STDC_VERSION__  == 199901L) || (__STDC_VERSION__ == 201000L) || (__STDC_VERSION__ == 201112L) || (__STDC_VERSION__ == 201710L))
+#error update this file to contain the latest C standard.
+#endif // ((__STDC_VERSION__  == 199901L) || (__STDC_VERSION__ == 201000L) || (__STDC_VERSION__ == 201112L) || (__STDC_VERSION__ == 201710L))
+#else // __STDC_VERSION__
+#ifdef __cplusplus
+/*C++ defines isnan... in C11*/
+extern "C++" {
+#define ISNAN std::isnan
+}
+#else // __cplusplus
+#error unknown (or C89) compiler, provide ISNAN with the same meaning as isnan in C99 standard
+#endif // __cplusplus
+
+#endif // __STDC_VERSION__
+#endif // _MSC_VER
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif /* CRT_ABSTRACTIONS_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/dns_resolver.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/dns_resolver.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/dns_resolver.h	(revision 453)
@@ -0,0 +1,72 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/** @file ssl_socket.h
+ *    @brief     Implements socket creation for TLSIO adapters.
+ */
+
+#ifndef AZURE_IOT_DNS_H
+#define AZURE_IOT_DNS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "azure_macro_utils/macro_utils.h"
+#include "umock_c/umock_c_prod.h"
+
+    typedef void* DNSRESOLVER_HANDLE;
+
+    // If options are added in future, DNSRESOLVER_OPTIONS will become a struct containing the options
+    typedef void DNSRESOLVER_OPTIONS;
+
+    /**
+    * @brief    Begin the process of an asynchronous DNS lookup.
+    *
+    * @param   hostname    The url of the host to look up.
+    *
+    * @return    @c The newly created DNSRESOLVER_HANDLE.
+    */
+    MOCKABLE_FUNCTION(, DNSRESOLVER_HANDLE, dns_resolver_create, const char*, hostname, int, port, const DNSRESOLVER_OPTIONS*, options);
+
+    /**
+    * @brief    Continue the lookup process and report its completion state. Must be polled repeatedly for completion.
+    *
+    * @param   dns    The DNSRESOLVER_HANDLE.
+    *
+    * @return    @c A bool to indicate completion.
+    */
+    MOCKABLE_FUNCTION(, bool, dns_resolver_is_lookup_complete, DNSRESOLVER_HANDLE, dns);
+
+    /**
+    * @brief    Return the IPv4 of a completed lookup process. Call only after dns_resolver_is_lookup_complete indicates completion.
+    *
+    * @param   dns    The DNSRESOLVER_HANDLE.
+    *
+    * @return    @c A uint32_t IPv4 address. 0 indicates failure or not finished.
+    */
+    MOCKABLE_FUNCTION(, uint32_t, dns_resolver_get_ipv4, DNSRESOLVER_HANDLE, dns);
+
+    /**
+    * @brief    Return the addrInfo of a completed lookup process. Call only after dns_resolver_is_lookup_complete indicates completion.
+    *
+    * @param   dns    The DNSRESOLVER_HANDLE.
+    *
+    * @return    @c A struct addrinfo. 0 indicates failure or not finished.
+    */
+    MOCKABLE_FUNCTION(, struct addrinfo*, dns_resolver_get_addrInfo, DNSRESOLVER_HANDLE, dns);
+    
+
+    /**
+    * @brief    Destroy the module.
+    *
+    * @param   dns    The DNSRESOLVER_HANDLE.
+    */
+    MOCKABLE_FUNCTION(, void, dns_resolver_destroy, DNSRESOLVER_HANDLE, dns);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AZURE_IOT_DNS_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/doublylinkedlist.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/doublylinkedlist.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/doublylinkedlist.h	(revision 453)
@@ -0,0 +1,45 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef DOUBLYLINKEDLIST_H
+#define DOUBLYLINKEDLIST_H
+
+#ifdef __cplusplus
+#include <cstddef>
+#else
+#include <stddef.h>
+#endif
+
+#include <stdint.h>
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef struct DLIST_ENTRY_TAG
+{
+    struct DLIST_ENTRY_TAG *Flink;
+    struct DLIST_ENTRY_TAG *Blink;
+} DLIST_ENTRY, *PDLIST_ENTRY;
+
+MOCKABLE_FUNCTION(, void, DList_InitializeListHead, PDLIST_ENTRY, listHead);
+MOCKABLE_FUNCTION(, int, DList_IsListEmpty, const PDLIST_ENTRY, listHead);
+MOCKABLE_FUNCTION(, void, DList_InsertTailList, PDLIST_ENTRY, listHead, PDLIST_ENTRY, listEntry);
+MOCKABLE_FUNCTION(, void, DList_InsertHeadList, PDLIST_ENTRY, listHead, PDLIST_ENTRY, listEntry);
+MOCKABLE_FUNCTION(, void, DList_AppendTailList, PDLIST_ENTRY, listHead, PDLIST_ENTRY, ListToAppend);
+MOCKABLE_FUNCTION(, int, DList_RemoveEntryList, PDLIST_ENTRY, listEntry);
+MOCKABLE_FUNCTION(, PDLIST_ENTRY, DList_RemoveHeadList, PDLIST_ENTRY, listHead);
+
+//
+// Calculate the address of the base of the structure given its type, and an
+// address of a field within the structure.
+//
+#define containingRecord(address, type, field) ((type *)((uintptr_t)(address) - offsetof(type,field)))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DOUBLYLINKEDLIST_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/esp_at_socket.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/esp_at_socket.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/esp_at_socket.h	(revision 453)
@@ -0,0 +1,26 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef ESP_AT_SOCKET_H
+#define ESP_AT_SOCKET_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+	typedef void* ESP_AT_SOCKET_HANDLE;
+
+	ESP_AT_SOCKET_HANDLE esp_at_socket_create(bool ssl);
+	void esp_at_socket_set_blocking(ESP_AT_SOCKET_HANDLE espAtSocketHandle, bool blocking, unsigned int timeout);
+	void esp_at_socket_destroy(ESP_AT_SOCKET_HANDLE espAtSocketHandle);
+	int esp_at_socket_connect(ESP_AT_SOCKET_HANDLE espAtSocketHandle, const char* host, const int port);
+	bool esp_at_socket_is_connected(ESP_AT_SOCKET_HANDLE espAtSocketHandle);
+	void esp_at_socket_close(ESP_AT_SOCKET_HANDLE espAtSocketHandle);
+	int esp_at_socket_send(ESP_AT_SOCKET_HANDLE espAtSocketHandle, const char* data, int length);
+	int esp_at_socket_receive(ESP_AT_SOCKET_HANDLE espAtSocketHandle, char* data, int length);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ESP_AT_SOCKET_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/gb_rand.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/gb_rand.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/gb_rand.h	(revision 453)
@@ -0,0 +1,19 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef GB_RAND_H
+#define GB_RAND_H
+
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+MOCKABLE_FUNCTION(, int, gb_rand);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GB_RAND_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/gb_stdio.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/gb_stdio.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/gb_stdio.h	(revision 453)
@@ -0,0 +1,76 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef GB_STDIO_H
+#define GB_STDIO_H
+
+/*this file, if included instead of <stdio.h> has the following functionality:
+1) if GB_STDIO_INTERCEPT is defined then
+    a) some of the stdio.h symbols shall be redefined, for example: fopen => gb_fopen
+    b) all "code" using the fopen will actually (because of the preprocessor) call to gb_fopen
+    c) gb_fopen shall blindly call into fopen, thus realizing a passthrough
+
+    reason is: unittesting. fopen is comes with the C Run Time and cannot be mocked (that is, in the global namespace cannot exist a function called fopen
+
+2) if GB_STDIO_INTERCEPT is not defined then
+    a) it shall include <stdio.h> => no passthrough, just direct linking.
+*/
+
+#ifndef GB_STDIO_INTERCEPT
+#ifdef __cplusplus
+#include <cstdio>
+#else
+#include <stdio.h>
+#endif
+#else
+
+/*source level intercepting of function calls*/
+#define fopen           fopen_never_called_never_implemented_always_forgotten
+#define fclose          fclose_never_called_never_implemented_always_forgotten
+#define fseek           fseek_never_called_never_implemented_always_forgotten
+#define ftell           ftell_never_called_never_implemented_always_forgotten
+#define fprintf         fprintf_never_called_never_implemented_always_forgotten
+
+#ifdef __cplusplus
+#include <cstdio>
+#else
+#include <stdio.h>
+#endif
+
+#include "umock_c/umock_c_prod.h"
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#undef fopen
+#define fopen gb_fopen
+MOCKABLE_FUNCTION(, FILE*, gb_fopen, const char*, filename, const char*, mode);
+
+
+#undef fclose
+#define fclose gb_fclose
+MOCKABLE_FUNCTION(, int, fclose, FILE *, stream);
+
+#undef fseek
+#define fseek gb_fseek
+MOCKABLE_FUNCTION(, int, fseek, FILE *,stream, long int, offset, int, whence);
+
+#undef ftell
+#define ftell gb_ftell
+MOCKABLE_FUNCTION(, long int, ftell, FILE *, stream);
+
+#undef fprintf
+#define fprintf gb_fprintf
+extern int fprintf(FILE * stream, const char * format, ...);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*GB_STDIO_INTERCEPT*/
+
+#endif /* GB_STDIO_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/gb_time.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/gb_time.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/gb_time.h	(revision 453)
@@ -0,0 +1,64 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef GB_TIME_H
+#define GB_TIME_H
+
+/*this file, if included instead of <stdio.h> has the following functionality:
+1) if GB_TIME_INTERCEPT is defined then
+    a) some of the time.h symbols shall be redefined, for example: time => gb_time
+    b) all "code" using the time will actually (because of the preprocessor) call to gb_time
+    c) gb_time shall blindly call into time, thus realizing a passthrough
+
+    reason is: unittesting. time comes with the C Run Time and cannot be mocked (that is, in the global namespace cannot exist a function called time
+
+2) if GB_TIME_INTERCEPT is not defined then
+    a) it shall include <time.h> => no passthrough, just direct linking.
+*/
+
+#ifndef GB_TIME_INTERCEPT
+#ifdef __cplusplus
+#include <ctime>
+#else
+#include <time.h>
+#endif
+#else
+
+/*source level intercepting of function calls*/
+#define time                    time_never_called_never_implemented_always_forgotten
+#define localtime               localtime_never_called_never_implemented_always_forgotten
+#define strftime                strftime_never_called_never_implemented_always_forgotten
+
+#ifdef __cplusplus
+#include <ctime>
+#else
+#include <time.h>
+#endif
+
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#undef time
+#define time gb_time
+MOCKABLE_FUNCTION(, time_t, time, time_t *, timer);
+
+#undef localtime
+#define localtime gb_localtime
+MOCKABLE_FUNCTION(, struct tm *, localtime, const time_t *, timer);
+
+#undef strftime
+#define strftime gb_strftime
+MOCKABLE_FUNCTION(, size_t, strftime, char *, s, size_t, maxsize, const char *, format, const struct tm *, timeptr);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*GB_TIME_INTERCEPT*/
+
+#endif /* GB_TIME_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/gballoc.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/gballoc.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/gballoc.h	(revision 453)
@@ -0,0 +1,87 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef GBALLOC_H
+#define GBALLOC_H
+
+#ifdef __cplusplus
+#include <cstdlib>
+#else
+#include <stdlib.h>
+#endif
+
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+// GB_USE_CUSTOM_HEAP disables the implementations in gballoc.c and
+// requires that an external library implement the gballoc_malloc family
+// declared here.
+#if defined(GB_USE_CUSTOM_HEAP)
+MOCKABLE_FUNCTION(, void*, gballoc_malloc, size_t, size);
+MOCKABLE_FUNCTION(, void*, gballoc_calloc, size_t, nmemb, size_t, size);
+MOCKABLE_FUNCTION(, void*, gballoc_realloc, void*, ptr, size_t, size);
+MOCKABLE_FUNCTION(, void, gballoc_free, void*, ptr);
+
+#define malloc gballoc_malloc
+#define calloc gballoc_calloc
+#define realloc gballoc_realloc
+#define free gballoc_free
+
+/* all translation units that need memory measurement need to have GB_MEASURE_MEMORY_FOR_THIS defined */
+/* GB_DEBUG_ALLOC is the switch that turns the measurement on/off, so that it is not on always */
+#elif defined(GB_DEBUG_ALLOC)
+
+MOCKABLE_FUNCTION(, int, gballoc_init);
+MOCKABLE_FUNCTION(, void, gballoc_deinit);
+MOCKABLE_FUNCTION(, void*, gballoc_malloc, size_t, size);
+MOCKABLE_FUNCTION(, void*, gballoc_calloc, size_t, nmemb, size_t, size);
+MOCKABLE_FUNCTION(, void*, gballoc_realloc, void*, ptr, size_t, size);
+MOCKABLE_FUNCTION(, void, gballoc_free, void*, ptr);
+
+MOCKABLE_FUNCTION(, size_t, gballoc_getMaximumMemoryUsed);
+MOCKABLE_FUNCTION(, size_t, gballoc_getCurrentMemoryUsed);
+MOCKABLE_FUNCTION(, size_t, gballoc_getAllocationCount);
+MOCKABLE_FUNCTION(, void, gballoc_resetMetrics);
+
+/* if GB_MEASURE_MEMORY_FOR_THIS is defined then we want to redirect memory allocation functions to gballoc_xxx functions */
+#ifdef GB_MEASURE_MEMORY_FOR_THIS
+/* Unfortunately this is still needed here for things to still compile when using _CRTDBG_MAP_ALLOC.
+That is because there is a rogue component (most likely CppUnitTest) including crtdbg. */
+#if defined(_CRTDBG_MAP_ALLOC) && defined(_DEBUG)
+#undef _malloc_dbg
+#undef _calloc_dbg
+#undef _realloc_dbg
+#undef _free_dbg
+#define _malloc_dbg(size, ...) gballoc_malloc(size)
+#define _calloc_dbg(nmemb, size, ...) gballoc_calloc(nmemb, size)
+#define _realloc_dbg(ptr, size, ...) gballoc_realloc(ptr, size)
+#define _free_dbg(ptr, ...) gballoc_free(ptr)
+#else
+#define malloc gballoc_malloc
+#define calloc gballoc_calloc
+#define realloc gballoc_realloc
+#define free gballoc_free
+#endif
+#endif
+
+#else /* GB_DEBUG_ALLOC */
+
+#define gballoc_init() 0
+#define gballoc_deinit() ((void)0)
+
+#define gballoc_getMaximumMemoryUsed() SIZE_MAX
+#define gballoc_getCurrentMemoryUsed() SIZE_MAX
+#define gballoc_getAllocationCount() SIZE_MAX
+#define gballoc_resetMetrics() ((void)0)
+
+#endif /* GB_DEBUG_ALLOC */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GBALLOC_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/gbnetwork.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/gbnetwork.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/gbnetwork.h	(revision 453)
@@ -0,0 +1,75 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef GBNETWORK_H
+#define GBNETWORK_H
+
+#ifdef __cplusplus
+#include <cstdlib>
+#include <cstdint>
+#else
+#include <stdlib.h>
+#include <stdint.h>
+#endif
+
+#include "umock_c/umock_c_prod.h"
+
+#ifdef WIN32
+    #include <winsock2.h>
+#else
+    #include <sys/socket.h>
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* all translation units that need network measurement need to have GB_MEASURE_NETWORK_FOR_THIS defined */
+/* GB_DEBUG_NETWORK is the switch that turns the measurement on/off, so that it is not on always */
+#if defined(GB_DEBUG_NETWORK)
+
+MOCKABLE_FUNCTION(, int, gbnetwork_init);
+MOCKABLE_FUNCTION(, void, gbnetwork_deinit);
+
+#ifdef WIN32
+MOCKABLE_FUNCTION(, int, gbnetwork_send, SOCKET, sock, const char*, buf, int, len, int, flags);
+#else
+MOCKABLE_FUNCTION(, ssize_t, gbnetwork_send, int, sock, const void*, buf, size_t, len, int, flags);
+#endif
+
+#ifdef WIN32
+MOCKABLE_FUNCTION(, int, gbnetwork_recv, SOCKET, sock, char*, buf, int, len, int, flags);
+#else
+MOCKABLE_FUNCTION(, ssize_t, gbnetwork_recv, int, sock, void*, buf, size_t, len, int, flags);
+#endif
+
+MOCKABLE_FUNCTION(, uint64_t, gbnetwork_getBytesSent);
+MOCKABLE_FUNCTION(, uint64_t, gbnetwork_getNumSends);
+MOCKABLE_FUNCTION(, uint64_t, gbnetwork_getBytesRecv);
+MOCKABLE_FUNCTION(, uint64_t, gbnetwork_getNumRecv);
+MOCKABLE_FUNCTION(, void, gbnetwork_resetMetrics);
+
+/* if GB_MEASURE_NETWORK_FOR_THIS is defined then we want to redirect network send functions to gbnetwork_xxx functions */
+#ifdef GB_MEASURE_NETWORK_FOR_THIS
+#define send gbnetwork_send
+#define recv gbnetwork_recv
+#endif
+
+#else /* GB_DEBUG_NETWORK */
+
+#define gbnetwork_init() 0
+#define gbnetwork_deinit() ((void)0)
+#define gbnetwork_getBytesSent() 0
+#define gbnetwork_getNumSends() 0
+
+#define gbnetwork_getBytesRecv() 0
+#define gbnetwork_getNumRecv() 0
+
+#endif /* GB_DEBUG_NETWORK */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GBNETWORK_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/hmac.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/hmac.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/hmac.h	(revision 453)
@@ -0,0 +1,28 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef HMAC_H
+#define HMAC_H
+
+#ifdef __cplusplus
+#include <cstdint>
+#else
+#include <stdint.h>
+#endif
+
+#include "azure_c_shared_utility/sha.h"
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+    MOCKABLE_FUNCTION(, int, hmac, SHAversion, whichSha, const unsigned char *, text, int, text_len,
+    const unsigned char *, key, int, key_len,
+    uint8_t, digest[USHAMaxHashSize]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HMAC_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/hmacsha256.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/hmacsha256.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/hmacsha256.h	(revision 453)
@@ -0,0 +1,34 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef HMACSHA256_H
+#define HMACSHA256_H
+
+#ifdef __cplusplus
+#include <cstddef>
+#else
+#include <stddef.h>
+#endif
+
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/buffer_.h"
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define HMACSHA256_RESULT_VALUES              \
+    HMACSHA256_OK,                            \
+    HMACSHA256_INVALID_ARG,                   \
+    HMACSHA256_ERROR
+
+MU_DEFINE_ENUM(HMACSHA256_RESULT, HMACSHA256_RESULT_VALUES)
+
+MOCKABLE_FUNCTION(, HMACSHA256_RESULT, HMACSHA256_ComputeHash, const unsigned char*, key, size_t, keyLen, const unsigned char*, payload, size_t, payloadLen, BUFFER_HANDLE, hash);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HMACSHA256_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/http_proxy_io.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/http_proxy_io.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/http_proxy_io.h	(revision 453)
@@ -0,0 +1,30 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef HTTP_PROXY_IO_H
+#define HTTP_PROXY_IO_H
+
+#include "azure_c_shared_utility/xio.h"
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct HTTP_PROXY_IO_CONFIG_TAG
+{
+    const char* hostname;
+    int port;
+    const char* proxy_hostname;
+    int proxy_port;
+    const char* username;
+    const char* password;
+} HTTP_PROXY_IO_CONFIG;
+
+MOCKABLE_FUNCTION(, const IO_INTERFACE_DESCRIPTION*, http_proxy_io_get_interface_description);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* HTTP_PROXY_IO_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/httpapi.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/httpapi.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/httpapi.h	(revision 453)
@@ -0,0 +1,205 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/** @file httpapi.h
+ *    @brief     This module implements the standard HTTP API used by the C IoT client
+ *             library.
+ *
+ *    @details For example, on the Windows platform the HTTP API code uses
+ *             WinHTTP and for Linux it uses curl and so forth. HTTPAPI must support
+ *             HTTPs (HTTP+SSL).
+ */
+
+#ifndef HTTPAPI_H
+#define HTTPAPI_H
+
+#ifdef __cplusplus
+#include <cstddef>
+#else
+#include <stddef.h>
+#endif
+
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/httpheaders.h"
+#include "azure_c_shared_utility/buffer_.h"
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct HTTP_HANDLE_DATA_TAG* HTTP_HANDLE;
+
+#define AMBIGUOUS_STATUS_CODE           (300)
+
+#define HTTPAPI_RESULT_VALUES                \
+HTTPAPI_OK,                                  \
+HTTPAPI_INVALID_ARG,                         \
+HTTPAPI_ERROR,                               \
+HTTPAPI_OPEN_REQUEST_FAILED,                 \
+HTTPAPI_SET_OPTION_FAILED,                   \
+HTTPAPI_SEND_REQUEST_FAILED,                 \
+HTTPAPI_RECEIVE_RESPONSE_FAILED,             \
+HTTPAPI_QUERY_HEADERS_FAILED,                \
+HTTPAPI_QUERY_DATA_AVAILABLE_FAILED,         \
+HTTPAPI_READ_DATA_FAILED,                    \
+HTTPAPI_ALREADY_INIT,                        \
+HTTPAPI_NOT_INIT,                            \
+HTTPAPI_HTTP_HEADERS_FAILED,                 \
+HTTPAPI_STRING_PROCESSING_ERROR,             \
+HTTPAPI_ALLOC_FAILED,                        \
+HTTPAPI_INIT_FAILED,                         \
+HTTPAPI_INSUFFICIENT_RESPONSE_BUFFER,        \
+HTTPAPI_SET_X509_FAILURE,                    \
+HTTPAPI_SET_TIMEOUTS_FAILED                  \
+
+/** @brief Enumeration specifying the possible return values for the APIs in
+ *           this module.
+ */
+MU_DEFINE_ENUM(HTTPAPI_RESULT, HTTPAPI_RESULT_VALUES);
+
+#define HTTPAPI_REQUEST_TYPE_VALUES\
+    HTTPAPI_REQUEST_GET,            \
+    HTTPAPI_REQUEST_POST,           \
+    HTTPAPI_REQUEST_PUT,            \
+    HTTPAPI_REQUEST_DELETE,         \
+    HTTPAPI_REQUEST_PATCH,          \
+    HTTPAPI_REQUEST_HEAD            \
+
+
+/** @brief Enumeration specifying the HTTP request verbs accepted by
+ *    the HTTPAPI module.
+ */
+MU_DEFINE_ENUM(HTTPAPI_REQUEST_TYPE, HTTPAPI_REQUEST_TYPE_VALUES);
+
+#define MAX_HOSTNAME_LEN        65
+#define MAX_USERNAME_LEN        65
+#define MAX_PASSWORD_LEN        65
+
+/**
+ * @brief    Global initialization for the HTTP API component.
+ *
+ *            Platform specific implementations are expected to initialize
+ *            the underlying HTTP API stacks.
+ *
+ * @return    @c HTTPAPI_OK if initialization is successful or an error
+ *             code in case it fails.
+ */
+MOCKABLE_FUNCTION(, HTTPAPI_RESULT, HTTPAPI_Init);
+
+/** @brief    Free resources allocated in ::HTTPAPI_Init. */
+MOCKABLE_FUNCTION(, void, HTTPAPI_Deinit);
+
+/**
+ * @brief    Creates an HTTPS connection to the host specified by the @p
+ *             hostName parameter.
+ *
+ * @param    hostName    Name of the host.
+ *
+ *            This function returns a handle to the newly created connection.
+ *            You can use the handle in subsequent calls to execute specific
+ *            HTTP calls using ::HTTPAPI_ExecuteRequest.
+ *
+ * @return    A @c HTTP_HANDLE to the newly created connection or @c NULL in
+ *             case an error occurs.
+ */
+MOCKABLE_FUNCTION(, HTTP_HANDLE, HTTPAPI_CreateConnection, const char*, hostName);
+
+/**
+ * @brief    Closes a connection created with ::HTTPAPI_CreateConnection.
+ *
+ * @param    handle    The handle to the HTTP connection created via ::HTTPAPI_CreateConnection.
+ *
+ *             All resources allocated by ::HTTPAPI_CreateConnection should be
+ *             freed in ::HTTPAPI_CloseConnection.
+ */
+MOCKABLE_FUNCTION(, void, HTTPAPI_CloseConnection, HTTP_HANDLE, handle);
+
+/**
+ * @brief    Sends the HTTP request to the host and handles the response for
+ *             the HTTP call.
+ *
+ * @param    handle                     The handle to the HTTP connection created
+ *                                     via ::HTTPAPI_CreateConnection.
+ * @param    requestType                 Specifies which HTTP method is used (GET,
+ *                                     POST, DELETE, PUT, PATCH).
+ * @param    relativePath             Specifies the relative path of the URL
+ *                                     excluding the host name.
+ * @param    httpHeadersHandle         Specifies a set of HTTP headers (name-value
+ *                                     pairs) to be added to the
+ *                                     HTTP request. The @p httpHeadersHandle
+ *                                     handle can be created and setup with
+ *                                     the proper name-value pairs by using the
+ *                                     HTTPHeaders APIs available in @c
+ *                                     HTTPHeaders.h.
+ * @param    content                     Specifies a pointer to the request body.
+ *                                     This value is optional and can be @c NULL.
+ * @param    contentLength             Specifies the request body size (this is
+ *                                     typically added into the HTTP headers as
+ *                                     the Content-Length header). This value is
+ *                                     optional and can be 0.
+ * @param   statusCode               This is an out parameter, where
+ *                                     ::HTTPAPI_ExecuteRequest returns the status
+ *                                     code from the HTTP response (200, 201, 400,
+ *                                     401, etc.)
+ * @param    responseHeadersHandle    This is an HTTP headers handle to which
+ *                                     ::HTTPAPI_ExecuteRequest must add all the
+ *                                     HTTP response headers so that the caller of
+ *                                     ::HTTPAPI_ExecuteRequest can inspect them.
+ *                                     You can manipulate @p responseHeadersHandle
+ *                                     by using the HTTPHeaders APIs available in
+ *                                     @c HTTPHeaders.h
+ * @param    responseContent             This is a buffer that must be filled by
+ *                                     ::HTTPAPI_ExecuteRequest with the contents
+ *                                     of the HTTP response body. The buffer size
+ *                                     must be increased by the
+ *                                     ::HTTPAPI_ExecuteRequest implementation in
+ *                                     order to fit the response body.
+ *                                     ::HTTPAPI_ExecuteRequest must also handle
+ *                                     chunked transfer encoding for HTTP responses.
+ *                                     To manipulate the @p responseContent buffer,
+ *                                     use the APIs available in @c Strings.h.
+ *
+ * @return    @c HTTPAPI_OK if the API call is successful or an error
+ *             code in case it fails.
+ */
+MOCKABLE_FUNCTION(, HTTPAPI_RESULT, HTTPAPI_ExecuteRequest, HTTP_HANDLE, handle, HTTPAPI_REQUEST_TYPE, requestType, const char*, relativePath,
+                                             HTTP_HEADERS_HANDLE, httpHeadersHandle, const unsigned char*, content,
+                                             size_t, contentLength, unsigned int*, statusCode,
+                                             HTTP_HEADERS_HANDLE, responseHeadersHandle, BUFFER_HANDLE, responseContent);
+
+/**
+ * @brief    Sets the option named @p optionName bearing the value
+ *             @p value for the HTTP_HANDLE @p handle.
+ *
+ * @param    handle          The handle to the HTTP connection created via
+ *                         ::HTTPAPI_CreateConnection.
+ * @param    optionName    A @c NULL terminated string representing the name
+ *                         of the option.
+ * @param    value          A pointer to the value for the option.
+ *
+ * @return    @c HTTPAPI_OK if initialization is successful or an error
+ *             code in case it fails.
+ */
+MOCKABLE_FUNCTION(, HTTPAPI_RESULT, HTTPAPI_SetOption, HTTP_HANDLE, handle, const char*, optionName, const void*, value);
+
+/**
+ * @brief    Clones the option named @p optionName bearing the value @p value
+ *             into the pointer @p savedValue.
+ *
+ * @param    optionName    A @c NULL terminated string representing the name of
+ *                         the option
+ * @param    value          A pointer to the value of the option.
+ * @param    savedValue    This pointer receives the copy of the value of the
+ *                         option. The copy needs to be free-able.
+ *
+ * @return    @c HTTPAPI_OK if initialization is successful or an error
+ *             code in case it fails.
+ */
+MOCKABLE_FUNCTION(, HTTPAPI_RESULT, HTTPAPI_CloneOption, const char*, optionName, const void*, value, const void**, savedValue);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HTTPAPI_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/httpapiex.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/httpapiex.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/httpapiex.h	(revision 453)
@@ -0,0 +1,128 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/** @file httpapiex.h
+*    @brief        This is a utility module that provides HTTP requests with
+*                build-in retry capabilities.
+*
+*    @details    HTTAPIEX is a utility module that provides HTTP requests with build-in
+*                retry capability to an HTTP server. Features over "regular" HTTPAPI include:
+*                    - Optional parameters
+*                    - Implementation independent
+*                    - Retry mechanism
+*                    - Persistent options
+*/
+
+#ifndef HTTPAPIEX_H
+#define HTTPAPIEX_H
+
+#ifdef __cplusplus
+#include <cstddef>
+#else
+#include <stddef.h>
+#endif
+
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/httpapi.h"
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct HTTPAPIEX_HANDLE_DATA_TAG* HTTPAPIEX_HANDLE;
+
+#define HTTPAPIEX_RESULT_VALUES \
+    HTTPAPIEX_OK, \
+    HTTPAPIEX_ERROR, \
+    HTTPAPIEX_INVALID_ARG, \
+    HTTPAPIEX_RECOVERYFAILED
+/*to be continued*/
+
+/** @brief Enumeration specifying the status of calls to various APIs in this module.
+*/
+MU_DEFINE_ENUM(HTTPAPIEX_RESULT, HTTPAPIEX_RESULT_VALUES);
+
+/**
+ * @brief    Initialize the HTTPAPIEX.
+ *
+ *  This API shall be called only once before call any other HTTPAPIEX API. 
+ *  **This API is NOT thread safe**.
+ *
+ * @return    An @c HTTPAPIEX_RESULT indicating the status of the call.
+ */
+MOCKABLE_FUNCTION(, HTTPAPIEX_RESULT, HTTPAPIEX_Init);
+
+/**
+ * @brief    Deinitialize the HTTPAPIEX.
+ *
+ *  This API shall be called only once to release all HTTP resources. No other HTTPAPIEX 
+ *      API shall be called after call this API.
+ *  **This API is NOT thread safe**.
+ */
+MOCKABLE_FUNCTION(, void, HTTPAPIEX_Deinit);
+
+/**
+ * @brief    Creates an @c HTTPAPIEX_HANDLE that can be used in further calls.
+ *
+ * @param    hostName    Pointer to a null-terminated string that contains the host name
+ *                         of an HTTP server.
+ *
+ *            If @p hostName is @c NULL then @c HTTPAPIEX_Create returns @c NULL. The @p
+ *            hostName value is saved and associated with the returned handle. If creating
+ *            the handle fails for any reason, then @c HTTAPIEX_Create returns @c NULL.
+ *            Otherwise, @c HTTPAPIEX_Create returns an @c HTTAPIEX_HANDLE suitable for
+ *            further calls to the module.
+ *
+ * @return    An @c HTTAPIEX_HANDLE suitable for further calls to the module.
+ */
+MOCKABLE_FUNCTION(, HTTPAPIEX_HANDLE, HTTPAPIEX_Create, const char*, hostName);
+
+/**
+ * @brief    Tries to execute an HTTP request.
+ *
+ * @param    handle                         A valid @c HTTPAPIEX_HANDLE value.
+ * @param    requestType                     A value from the ::HTTPAPI_REQUEST_TYPE enum.
+ * @param    relativePath                 Relative path to send the request to on the server.
+ * @param    requestHttpHeadersHandle     Handle to the request HTTP headers.
+ * @param    requestContent                 The request content.
+ * @param     statusCode                     If non-null, the HTTP status code is written to this
+ *                                         pointer.
+ * @param    responseHttpHeadersHandle    Handle to the response HTTP headers.
+ * @param    responseContent                 The response content.
+ *
+ *             @c HTTPAPIEX_ExecuteRequest tries to execute an HTTP request of type @p
+ *             requestType, on the server's @p relativePath, pushing the request HTTP
+ *             headers @p requestHttpHeadersHandle, having the content of the request
+ *             as pointed to by @p requestContent. If successful,  @c HTTAPIEX_ExecuteRequest
+ *             writes in the out @p parameter statusCode the HTTP status, populates the @p
+ *             responseHeadersHandle with the response headers and copies the response body
+ *             to @p responseContent.
+ *
+ * @return    An @c HTTAPIEX_HANDLE suitable for further calls to the module.
+ */
+MOCKABLE_FUNCTION(, HTTPAPIEX_RESULT, HTTPAPIEX_ExecuteRequest, HTTPAPIEX_HANDLE, handle, HTTPAPI_REQUEST_TYPE, requestType, const char*, relativePath, HTTP_HEADERS_HANDLE, requestHttpHeadersHandle, BUFFER_HANDLE, requestContent, unsigned int*, statusCode, HTTP_HEADERS_HANDLE, responseHttpHeadersHandle, BUFFER_HANDLE, responseContent);
+
+/**
+ * @brief    Frees all resources used by the @c HTTPAPIEX_HANDLE object.
+ *
+ * @param    handle    The @c HTTPAPIEX_HANDLE object to be freed.
+ */
+MOCKABLE_FUNCTION(, void, HTTPAPIEX_Destroy, HTTPAPIEX_HANDLE, handle);
+
+/**
+ * @brief    Sets the option @p optionName to the value pointed to by @p value.
+ *
+ * @param    handle          The @c HTTPAPIEX_HANDLE representing this session.
+ * @param    optionName    Name of the option.
+ * @param    value          The value to be set for the option.
+ *
+ * @return    An @c HTTPAPIEX_RESULT indicating the status of the call.
+ */
+MOCKABLE_FUNCTION(, HTTPAPIEX_RESULT, HTTPAPIEX_SetOption, HTTPAPIEX_HANDLE, handle, const char*, optionName, const void*, value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HTTPAPIEX_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/httpapiexsas.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/httpapiexsas.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/httpapiexsas.h	(revision 453)
@@ -0,0 +1,31 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef HTTPAPIEX_SAS_H
+#define HTTPAPIEX_SAS_H
+
+#include "azure_c_shared_utility/strings.h"
+#include "azure_c_shared_utility/buffer_.h"
+#include "azure_c_shared_utility/httpheaders.h"
+#include "azure_c_shared_utility/httpapiex.h"
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+    
+typedef struct HTTPAPIEX_SAS_STATE_TAG* HTTPAPIEX_SAS_HANDLE;
+
+MOCKABLE_FUNCTION(, HTTPAPIEX_SAS_HANDLE, HTTPAPIEX_SAS_Create, STRING_HANDLE, key, STRING_HANDLE, uriResource, STRING_HANDLE, keyName);
+
+MOCKABLE_FUNCTION(, HTTPAPIEX_SAS_HANDLE, HTTPAPIEX_SAS_Create_From_String, const char*, key, const char*, uriResource, const char*, keyName);
+
+MOCKABLE_FUNCTION(, void, HTTPAPIEX_SAS_Destroy, HTTPAPIEX_SAS_HANDLE, handle);
+
+MOCKABLE_FUNCTION(, HTTPAPIEX_RESULT, HTTPAPIEX_SAS_ExecuteRequest, HTTPAPIEX_SAS_HANDLE, sasHandle, HTTPAPIEX_HANDLE, handle, HTTPAPI_REQUEST_TYPE, requestType, const char*, relativePath, HTTP_HEADERS_HANDLE, requestHttpHeadersHandle, BUFFER_HANDLE, requestContent, unsigned int*, statusCode, HTTP_HEADERS_HANDLE, responseHeadersHandle, BUFFER_HANDLE, responseContent);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HTTPAPIEX_SAS_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/httpheaders.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/httpheaders.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/httpheaders.h	(revision 453)
@@ -0,0 +1,161 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/** @file httpheaders.h
+*    @brief This is a utility module that handles HTTP message-headers.
+*
+*    @details An application would use ::HTTPHeaders_Alloc to create a new set of HTTP headers.
+*             After getting the handle, the application would build in several headers by
+*             consecutive calls to ::HTTPHeaders_AddHeaderNameValuePair. When the headers are
+*             constructed, the application can retrieve the stored data by calling one of the
+*             following functions:
+*                - ::HTTPHeaders_FindHeaderValue - when the name of the header is known and it
+*                  wants to know the value of that header
+*                - ::HTTPHeaders_GetHeaderCount - when the application needs to know the count
+*                  of all the headers
+*                - ::HTTPHeaders_GetHeader - when the application needs to retrieve the
+*                  <code>name + ": " + value</code> string based on an index.
+*/
+
+#ifndef HTTPHEADERS_H
+#define HTTPHEADERS_H
+
+#ifdef __cplusplus
+#include <cstddef>
+#else
+#include <stddef.h>
+#endif
+
+#include "azure_macro_utils/macro_utils.h"
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*Codes_SRS_HTTP_HEADERS_99_001:[ HttpHeaders shall have the following interface]*/
+
+#define HTTP_HEADERS_RESULT_VALUES \
+HTTP_HEADERS_OK,                  \
+HTTP_HEADERS_INVALID_ARG,         \
+HTTP_HEADERS_ALLOC_FAILED,        \
+HTTP_HEADERS_INSUFFICIENT_BUFFER, \
+HTTP_HEADERS_ERROR                \
+
+/** @brief Enumeration specifying the status of calls to various APIs in this module.
+*/
+MU_DEFINE_ENUM(HTTP_HEADERS_RESULT, HTTP_HEADERS_RESULT_VALUES);
+typedef struct HTTP_HEADERS_HANDLE_DATA_TAG* HTTP_HEADERS_HANDLE;
+
+/**
+ * @brief    Produces a @c HTTP_HANDLE that can later be used in subsequent calls to the module.
+ *
+ *            This function returns @c NULL in case an error occurs. After successful execution
+ *            ::HTTPHeaders_GetHeaderCount will report @c 0 existing headers.
+ *
+ * @return    A HTTP_HEADERS_HANDLE representing the newly created collection of HTTP headers.
+ */
+MOCKABLE_FUNCTION(, HTTP_HEADERS_HANDLE, HTTPHeaders_Alloc);
+
+/**
+ * @brief    De-allocates the data structures allocated by previous API calls to the same handle.
+ *
+ * @param    httpHeadersHandle    A valid @c HTTP_HEADERS_HANDLE value.
+ */
+MOCKABLE_FUNCTION(, void, HTTPHeaders_Free, HTTP_HEADERS_HANDLE, httpHeadersHandle);
+
+/**
+ * @brief    Adds a header record from the @p name and @p value parameters.
+ *
+ * @param    httpHeadersHandle    A valid @c HTTP_HEADERS_HANDLE value.
+ * @param    name                 The name of the HTTP header to add. It is invalid for
+ *                                 the name to include the ':' character or character codes
+ *                                 outside the range 33-126.
+ * @param    value                 The value to be assigned to the header.
+ *
+ *            The function stores the @c name:value pair in such a way that when later
+ *            retrieved by a call to ::HTTPHeaders_GetHeader it will return a string
+ *            that is @c strcmp equal to @c name+": "+value. If the name already exists
+ *            in the collection of headers, the function concatenates the new value
+ *            after the existing value, separated by a comma and a space as in:
+ *            <code>old-value+", "+new-value</code>.
+ *
+ * @return    Returns @c HTTP_HEADERS_OK when execution is successful or an error code from
+ *             the ::HTTPAPIEX_RESULT enum.
+ */
+MOCKABLE_FUNCTION(, HTTP_HEADERS_RESULT, HTTPHeaders_AddHeaderNameValuePair, HTTP_HEADERS_HANDLE, httpHeadersHandle, const char*, name, const char*, value);
+
+/**
+ * @brief    This API performs exactly the same as ::HTTPHeaders_AddHeaderNameValuePair
+ *             except that if the header name already exists then the already existing value
+ *             will be replaced as opposed to being concatenated to.
+ *
+ * @param    httpHeadersHandle    A valid @c HTTP_HEADERS_HANDLE value.
+ * @param    name                 The name of the HTTP header to add/replace. It is invalid for
+ *                                 the name to include the ':' character or character codes
+ *                                 outside the range 33-126.
+ * @param    value                 The value to be assigned to the header.
+ *
+ * @return    Returns @c HTTP_HEADERS_OK when execution is successful or an error code from
+ *             the ::HTTPAPIEX_RESULT enum.
+ */
+MOCKABLE_FUNCTION(, HTTP_HEADERS_RESULT, HTTPHeaders_ReplaceHeaderNameValuePair, HTTP_HEADERS_HANDLE, httpHeadersHandle, const char*, name, const char*, value);
+
+/**
+ * @brief    Retrieves the value for a previously stored name.
+ *
+ * @param    httpHeadersHandle    A valid @c HTTP_HEADERS_HANDLE value.
+ * @param    name                 The name of the HTTP header to find.
+ *
+ * @return    The return value points to a string that shall be @c strcmp equal
+ *             to the original stored string.
+ */
+MOCKABLE_FUNCTION(, const char*, HTTPHeaders_FindHeaderValue, HTTP_HEADERS_HANDLE, httpHeadersHandle, const char*, name);
+
+/**
+ * @brief    This API retrieves the number of stored headers.
+ *
+ * @param    httpHeadersHandle    A valid @c HTTP_HEADERS_HANDLE value.
+ * @param    headersCount        If non-null, the API writes the number of
+ *                                 into the memory pointed at by this parameter.
+ *
+ * @return    Returns @c HTTP_HEADERS_OK when execution is successful or
+ *             @c HTTP_HEADERS_ERROR when an error occurs.
+ */
+MOCKABLE_FUNCTION(, HTTP_HEADERS_RESULT, HTTPHeaders_GetHeaderCount, HTTP_HEADERS_HANDLE, httpHeadersHandle, size_t*, headersCount);
+
+/**
+ * @brief    This API retrieves the string name+": "+value for the header
+ *             element at the given @p index.
+ *
+ * @param    handle            A valid @c HTTP_HEADERS_HANDLE value.
+ * @param    index            Zero-based index of the item in the
+ *                             headers collection.
+ * @param   destination        If non-null, the header value is written into a
+ *                             new string a pointer to which is written into this
+ *                             parameters. It is the caller's responsibility to free
+ *                             this memory.
+ *
+ * @return    Returns @c HTTP_HEADERS_OK when execution is successful or
+ *             @c HTTP_HEADERS_ERROR when an error occurs.
+ */
+MOCKABLE_FUNCTION(, HTTP_HEADERS_RESULT, HTTPHeaders_GetHeader, HTTP_HEADERS_HANDLE, handle, size_t, index, char**, destination);
+
+/**
+ * @brief    This API produces a clone of the @p handle parameter.
+ *
+ * @param   handle  A valid @c HTTP_HEADERS_HANDLE value.
+ *
+ *            If @p handle is not @c NULL this function clones the content
+ *            of the handle to a new handle and returns it.
+ *
+ * @return    A @c HTTP_HEADERS_HANDLE containing a cloned copy of the
+ *             contents of @p handle.
+ */
+MOCKABLE_FUNCTION(, HTTP_HEADERS_HANDLE, HTTPHeaders_Clone, HTTP_HEADERS_HANDLE, handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HTTPHEADERS_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/lock.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/lock.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/lock.h	(revision 453)
@@ -0,0 +1,77 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/** @file lock.h  
+*	@brief		A minimalistic platform agnostic lock abstraction for thread
+*				synchronization.
+*	@details	The Lock component is implemented in order to achieve thread
+*				synchronization, as we may have a requirement to consume locks
+*				across different platforms. This component exposes some generic
+*				APIs so that it can be extended for platform specific
+*				implementations.
+*/
+
+#ifndef LOCK_H
+#define LOCK_H
+
+#include "azure_macro_utils/macro_utils.h"
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void* LOCK_HANDLE;
+
+#define LOCK_RESULT_VALUES \
+    LOCK_OK, \
+    LOCK_ERROR \
+
+/** @brief Enumeration specifying the lock status.
+*/
+MU_DEFINE_ENUM(LOCK_RESULT, LOCK_RESULT_VALUES);
+
+/**
+ * @brief	This API creates and returns a valid lock handle.
+ *
+ * @return	A valid @c LOCK_HANDLE when successful or @c NULL otherwise.
+ */
+MOCKABLE_FUNCTION(, LOCK_HANDLE, Lock_Init);
+
+/**
+ * @brief	Acquires a lock on the given lock handle. Uses platform
+ * 			specific mutex primitives in its implementation.
+ *
+ * @param	handle	A valid handle to the lock.
+ *
+ * @return	Returns @c LOCK_OK when a lock has been acquired and
+ * 			@c LOCK_ERROR when an error occurs.
+ */
+MOCKABLE_FUNCTION(, LOCK_RESULT, Lock, LOCK_HANDLE, handle);
+
+/**
+ * @brief	Releases the lock on the given lock handle. Uses platform
+ * 			specific mutex primitives in its implementation.
+ *
+ * @param	handle	A valid handle to the lock.
+ *
+ * @return	Returns @c LOCK_OK when the lock has been released and
+ * 			@c LOCK_ERROR when an error occurs.
+ */
+MOCKABLE_FUNCTION(, LOCK_RESULT, Unlock, LOCK_HANDLE, handle);
+
+/**
+ * @brief	The lock instance is destroyed.
+ *
+ * @param	handle	A valid handle to the lock.
+ *
+ * @return	Returns @c LOCK_OK when the lock object has been
+ * 			destroyed and @c LOCK_ERROR when an error occurs.
+ */
+MOCKABLE_FUNCTION(, LOCK_RESULT, Lock_Deinit, LOCK_HANDLE, handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LOCK_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/map.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/map.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/map.h	(revision 453)
@@ -0,0 +1,205 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/** @file       map.h
+*    @brief        Map is a module that implements a dictionary of @c STRING_HANDLE
+*               keys to @c STRING_HANDLE values.
+*/
+
+#ifndef MAP_H
+#define MAP_H
+
+#ifdef __cplusplus
+#include <cstddef>
+#else
+#include <stddef.h>
+#endif
+
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/strings.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define MAP_RESULT_VALUES \
+    MAP_OK, \
+    MAP_ERROR, \
+    MAP_INVALIDARG, \
+    MAP_KEYEXISTS, \
+    MAP_KEYNOTFOUND, \
+    MAP_FILTER_REJECT
+
+/** @brief Enumeration specifying the status of calls to various APIs in this
+ *  module.
+ */
+MU_DEFINE_ENUM(MAP_RESULT, MAP_RESULT_VALUES);
+
+typedef struct MAP_HANDLE_DATA_TAG* MAP_HANDLE;
+
+typedef int (*MAP_FILTER_CALLBACK)(const char* mapProperty, const char* mapValue);
+
+/**
+ * @brief   Creates a new, empty map.
+ *
+ * @param   mapFilterFunc   A callback function supplied by the caller that is
+ *                          invoked during calls to ::Map_Add and
+ *                          ::Map_AddOrUpdate to provide the caller an
+ *                          opportunity to indicate whether the new entry or
+ *                          the update to an existing entry can be made or not.
+ *                          The callback function can request that the operation
+ *                          be canceled by returning a non-zero value from the
+ *                          callback.
+ *
+ * @return  A valid @c MAP_HANDLE or @c NULL in case an error occurs.
+ */
+MOCKABLE_FUNCTION(, MAP_HANDLE, Map_Create, MAP_FILTER_CALLBACK, mapFilterFunc);
+
+/**
+ * @brief   Release all resources associated with the map.
+ *
+ * @param   handle  The handle to an existing map.
+ */
+MOCKABLE_FUNCTION(, void, Map_Destroy, MAP_HANDLE, handle);
+
+/**
+ * @brief   Creates a copy of the map indicated by @p handle and returns a
+ *          handle to it.
+ *
+ * @param   handle  The handle to an existing map.
+ *
+ * @return  A valid @c MAP_HANDLE to the cloned copy of the map or @c NULL
+ *          in case an error occurs.
+ */
+MOCKABLE_FUNCTION(, MAP_HANDLE, Map_Clone, MAP_HANDLE, handle);
+
+/**
+ * @brief   Adds a key/value pair to the map.
+ *
+ * @param   handle  The handle to an existing map.
+ * @param   key     The @c key to be used for this map entry.
+ * @param   value   The @c value to be associated with @p key.
+ *
+ *          If a non-NULL pointer to a callback function was supplied
+ *          via the @c mapFilterFunc parameter when ::Map_Create was
+ *          called then that callback is invoked when a new entry is
+ *          added and if the callback returns a non-zero value then
+ *          the function cancels the add operation and returns
+ *          @c MAP_FILTER_REJECT.
+ *
+ * @return  If any of the input parameters are @c NULL then this function
+ *          returns @c MAP_INVALID_ARG. If the key already exists in the
+ *          map then @c MAP_KEYEXISTS is returned. If the filter function
+ *          associated with the map rejects the entry then
+ *          @c MAP_FILTER_REJECT is returned. In case an error occurs when
+ *          the new key is added to the map the function returns @c MAP_ERROR.
+ *          If everything goes well then @c MAP_OK is returned.
+ */
+MOCKABLE_FUNCTION(, MAP_RESULT, Map_Add, MAP_HANDLE, handle, const char*, key, const char*, value);
+
+/**
+ * @brief   Adds/updates a key/value pair to the map.
+ *
+ * @param   handle  The handle to an existing map.
+ * @param   key     The @c key to be used for this map entry.
+ * @param   value   The @c value to be associated with @p key.
+ *
+ *          This function behaves exactly like ::Map_Add except that if the key
+ *          already exists in the map then it overwrites the value with the
+ *          supplied value instead of returning an error. If a non-NULL pointer
+ *          to a callback function was supplied via the @c mapFilterFunc parameter
+ *          when ::Map_Create was called then that callback is invoked when a new
+ *          entry is added or when an existing entry is updated and if the
+ *          callback returns a non-zero value then the function cancels the
+ *          add/update operation and returns @c MAP_FILTER_REJECT.
+ *
+ * @return  If any of the input parameters are @c NULL then this function
+ *          returns @c MAP_INVALID_ARG. If the filter function associated
+ *          with the map rejects the entry then @c MAP_FILTER_REJECT is
+ *          returned. In case an error occurs when the new key is
+ *          added/updated in the map the function returns @c MAP_ERROR. If
+ *          everything goes well then @c MAP_OK is returned.
+ */
+MOCKABLE_FUNCTION(, MAP_RESULT, Map_AddOrUpdate, MAP_HANDLE, handle, const char*, key, const char*, value);
+
+/**
+ * @brief   Removes a key and its associated value from the map.
+ *
+ * @param   handle  The handle to an existing map.
+ * @param   key     The @c key of the item to be deleted.
+ *
+ * @return  Returns @c MAP_OK if the key was deleted successfully or an
+ *          error code otherwise.
+ */
+MOCKABLE_FUNCTION(, MAP_RESULT, Map_Delete, MAP_HANDLE, handle, const char*, key);
+
+/**
+ * @brief   This function returns a boolean value in @p keyExists if the map
+ *          contains a key with the same value the parameter @p key.
+ *
+ * @param   handle      The handle to an existing map.
+ * @param   key         The key that the caller wants checked.
+ * @param   keyExists   The function writes @c true at the address pointed at
+ *                      by this parameter if the key exists in the map and
+ *                      @c false otherwise.
+ *
+ * @return  Returns @c MAP_OK if the check was performed successfully or an
+ *          error code otherwise.
+ */
+MOCKABLE_FUNCTION(, MAP_RESULT, Map_ContainsKey, MAP_HANDLE, handle, const char*, key, bool*, keyExists);
+
+/**
+ * @brief   This function returns @c true in @p valueExists if at
+ *          least one <key,value> pair exists in the map where the entry's
+ *          value is equal to the parameter @c value.
+ *
+ * @param   handle          The handle to an existing map.
+ * @param   value           The value that the caller wants checked.
+ * @param   valueExists     The function writes @c true at the address pointed at
+ *                          by this parameter if the value exists in the map and
+ *                          @c false otherwise.
+ *
+ * @return  Returns @c MAP_OK if the check was performed successfully or an
+ *          error code otherwise.
+ */
+MOCKABLE_FUNCTION(, MAP_RESULT, Map_ContainsValue, MAP_HANDLE, handle, const char*, value, bool*, valueExists);
+
+/**
+ * @brief   Retrieves the value of a stored key.
+ *
+ * @param   handle  The handle to an existing map.
+ * @param   key     The key to be looked up in the map.
+ *
+ * @return  Returns @c NULL in case the input arguments are @c NULL or if the
+ *          requested key is not found in the map. Returns a pointer to the
+ *          key's value otherwise.
+ */
+MOCKABLE_FUNCTION(, const char*, Map_GetValueFromKey, MAP_HANDLE, handle, const char*, key);
+
+/**
+ * @brief   Retrieves the complete list of keys and values from the map
+ *          in @p values and @p keys. Also writes the size of the list
+ *          in @p count.
+ *
+ * @param   handle      The handle to an existing map.
+ * @param   keys        The location where the list of keys is to be written.
+ * @param   values      The location where the list of values is to be written.
+ * @param   count       The number of stored keys and values is written at the
+ *                      location indicated by this pointer.
+ *
+ * @return  Returns @c MAP_OK if the keys and values are retrieved and written
+ *          successfully or an error code otherwise.
+ */
+MOCKABLE_FUNCTION(, MAP_RESULT, Map_GetInternals, MAP_HANDLE, handle, const char*const**, keys, const char*const**, values, size_t*, count);
+
+/*this API creates a JSON object from the content of the map*/
+MOCKABLE_FUNCTION(, STRING_HANDLE, Map_ToJSON, MAP_HANDLE, handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MAP_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/optimize_size.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/optimize_size.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/optimize_size.h	(revision 453)
@@ -0,0 +1,24 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef OPTIMIZE_SIZE_H
+#define OPTIMIZE_SIZE_H
+
+#if (defined __MSP430FR5969__)
+    #define OPTIMIZE_RETURN_CODES
+    #define NO_VERBOSE_OUTPUT
+    #ifdef DEBUG
+        #define MINIMAL_LOGERROR
+    #else
+        #define NO_LOGGING
+    #endif
+#endif
+
+#if (defined OPTIMIZE_RETURN_CODES)
+    #define MU_FAILURE 1
+#else
+    #define MU_FAILURE __LINE__
+#endif
+
+#endif // OPTIMIZE_SIZE_H
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/optionhandler.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/optionhandler.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/optionhandler.h	(revision 453)
@@ -0,0 +1,47 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef OPTIONHANDLER_H
+#define OPTIONHANDLER_H
+
+#include "azure_macro_utils/macro_utils.h"
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define OPTIONHANDLER_RESULT_VALUES \
+    OPTIONHANDLER_OK, \
+    OPTIONHANDLER_ERROR, \
+    OPTIONHANDLER_INVALIDARG
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(OPTIONHANDLER_RESULT, OPTIONHANDLER_RESULT_VALUES)
+
+typedef struct OPTIONHANDLER_HANDLE_DATA_TAG* OPTIONHANDLER_HANDLE;
+
+/*the following function pointer points to a function that produces a clone of the option specified by name and value (that is, a clone of void* value)*/
+/*returns NULL if it failed to produce a clone, otherwise returns a non-NULL value*/
+/*to be implemented by every module*/
+typedef void* (*pfCloneOption)(const char* name, const void* value);
+
+/*the following function pointer points to a function that frees resources allocated for an option*/
+/*to be implemented by every module*/
+typedef void (*pfDestroyOption)(const char* name, const void* value);
+
+/*the following function pointer points to a function that sets an option for a module*/
+/*to be implemented by every module*/
+/*returns 0 if _SetOption succeeded, any other value is error, if the option is not intended for that module, returns 0*/
+typedef int (*pfSetOption)(void* handle, const char* name, const void* value);
+
+MOCKABLE_FUNCTION(, OPTIONHANDLER_HANDLE, OptionHandler_Create, pfCloneOption, cloneOption, pfDestroyOption, destroyOption, pfSetOption, setOption);
+MOCKABLE_FUNCTION(, OPTIONHANDLER_HANDLE, OptionHandler_Clone, OPTIONHANDLER_HANDLE, handler);
+MOCKABLE_FUNCTION(, OPTIONHANDLER_RESULT, OptionHandler_AddOption, OPTIONHANDLER_HANDLE, handle, const char*, name, const void*, value);
+MOCKABLE_FUNCTION(, OPTIONHANDLER_RESULT, OptionHandler_FeedOptions, OPTIONHANDLER_HANDLE, handle, void*, destinationHandle);
+MOCKABLE_FUNCTION(, void, OptionHandler_Destroy, OPTIONHANDLER_HANDLE, handle);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /*OPTIONHANDLER*/
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/platform.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/platform.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/platform.h	(revision 453)
@@ -0,0 +1,32 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef PLATFORM_H
+#define PLATFORM_H
+
+#include "azure_c_shared_utility/strings.h"
+#include "azure_c_shared_utility/xio.h"
+#include "umock_c/umock_c_prod.h"
+
+#define GUID_LENGTH 64
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+    #define PLATFORM_INFO_OPTION_VALUES       \
+        PLATFORM_INFO_OPTION_DEFAULT,         \
+        PLATFORM_INFO_OPTION_RETRIEVE_SQM
+
+    MU_DEFINE_ENUM(PLATFORM_INFO_OPTION, PLATFORM_INFO_OPTION_VALUES);
+
+    MOCKABLE_FUNCTION(, int, platform_init);
+    MOCKABLE_FUNCTION(, void, platform_deinit);
+    MOCKABLE_FUNCTION(, const IO_INTERFACE_DESCRIPTION*, platform_get_default_tlsio);
+    MOCKABLE_FUNCTION(, STRING_HANDLE, platform_get_platform_info, PLATFORM_INFO_OPTION, options);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* PLATFORM_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/refcount.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/refcount.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/refcount.h	(revision 453)
@@ -0,0 +1,125 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+
+/*this header contains macros for ref_counting a variable.
+
+There are no upper bound checks related to uint32_t overflow because we expect that bigger issues are in
+the system when more than 4 billion references exist to the same variable. In the case when such an overflow
+occurs, the object's ref count will reach zero (while still having 0xFFFFFFFF references) and likely the
+controlling code will take the decision to free the object's resources. Then, any of the 0xFFFFFFFF references
+will interact with deallocated memory / resources resulting in an undefined behavior.
+*/
+
+#ifndef REFCOUNT_H
+#define REFCOUNT_H
+
+#ifdef __cplusplus
+#include <cstdlib>
+#include <cstdint>
+#else
+#include <stdlib.h>
+#include <stdint.h>
+#endif
+
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_macro_utils/macro_utils.h"
+
+// Include the platform-specific file that defines atomic functionality
+#include "refcount_os.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define REFCOUNT_TYPE(type) \
+struct MU_C2(MU_C2(REFCOUNT_, type), _TAG)
+
+#define REFCOUNT_SHORT_TYPE(type) \
+MU_C2(REFCOUNT_, type)
+
+#define REFCOUNT_TYPE_DECLARE_CREATE(type) MU_C2(REFCOUNT_SHORT_TYPE(type), _Create)
+#define REFCOUNT_TYPE_DECLARE_CREATE_WITH_EXTRA_SIZE(type) MU_C2(REFCOUNT_SHORT_TYPE(type), _Create_With_Extra_Size)
+#define REFCOUNT_TYPE_CREATE(type) MU_C2(REFCOUNT_SHORT_TYPE(type), _Create)()
+#define REFCOUNT_TYPE_CREATE_WITH_EXTRA_SIZE(type, size) MU_C2(REFCOUNT_SHORT_TYPE(type), _Create_With_Extra_Size)(size)
+#define REFCOUNT_TYPE_DECLARE_DESTROY(type) MU_C2(REFCOUNT_SHORT_TYPE(type), _Destroy)
+#define REFCOUNT_TYPE_DESTROY(type, var) MU_C2(REFCOUNT_SHORT_TYPE(type), _Destroy)(var)
+
+/*this introduces a new refcount'd type based on another type */
+/*and an initializer for that new type that also sets the ref count to 1. The type must not have a flexible array*/
+/*the newly allocated memory shall be free'd by free()*/
+/*and the ref counting is handled internally by the type in the _Create/ _Create_With_Extra_Size /_Clone /_Destroy functions */
+
+/* Codes_SRS_REFCOUNT_01_005: [ REFCOUNT_TYPE_CREATE_WITH_EXTRA_SIZE shall allocate memory for the type that is ref counted (type) plus extra memory enough to hold size bytes. ]*/
+/* Codes_SRS_REFCOUNT_01_006: [ On success it shall return a non-NULL handle to the allocated ref counted type type. ]*/
+/* Codes_SRS_REFCOUNT_01_007: [ If any error occurs, REFCOUNT_TYPE_CREATE_WITH_EXTRA_SIZE shall return NULL. ]*/
+#define DEFINE_CREATE_WITH_EXTRA_SIZE(type) \
+static type* REFCOUNT_TYPE_DECLARE_CREATE_WITH_EXTRA_SIZE(type)(size_t size) \
+{ \
+    REFCOUNT_TYPE(type)* ref_counted = (REFCOUNT_TYPE(type)*)malloc(sizeof(REFCOUNT_TYPE(type)) + size); \
+    type* result; \
+    if (ref_counted == NULL) \
+    { \
+        result = NULL; \
+    } \
+    else \
+    { \
+        result = &ref_counted->counted; \
+        INIT_REF(type, result); \
+    } \
+    return result; \
+} \
+
+/* Codes_SRS_REFCOUNT_01_002: [ REFCOUNT_TYPE_CREATE shall allocate memory for the type that is ref counted. ]*/
+/* Codes_SRS_REFCOUNT_01_003: [ On success it shall return a non-NULL handle to the allocated ref counted type type. ]*/
+/* Codes_SRS_REFCOUNT_01_004: [ If any error occurs, REFCOUNT_TYPE_CREATE shall return NULL. ]*/
+#define DEFINE_CREATE(type) \
+static type* REFCOUNT_TYPE_DECLARE_CREATE(type) (void) \
+{ \
+    return REFCOUNT_TYPE_DECLARE_CREATE_WITH_EXTRA_SIZE(type)(0); \
+} \
+
+/* Codes_SRS_REFCOUNT_01_008: [ REFCOUNT_TYPE_DESTROY shall free the memory allocated by REFCOUNT_TYPE_CREATE or REFCOUNT_TYPE_CREATE_WITH_EXTRA_SIZE. ]*/
+/* Codes_SRS_REFCOUNT_01_009: [ If counted_type is NULL, REFCOUNT_TYPE_DESTROY shall return. ]*/
+#define DEFINE_DESTROY(type) \
+static void REFCOUNT_TYPE_DECLARE_DESTROY(type)(type* counted_type) \
+{ \
+    void* ref_counted = (void*)((unsigned char*)counted_type - offsetof(REFCOUNT_TYPE(type), counted)); \
+    free(ref_counted); \
+}
+
+#define DEFINE_REFCOUNT_TYPE(type) \
+REFCOUNT_TYPE(type) \
+{ \
+    COUNT_TYPE count; \
+    type counted; \
+}; \
+DEFINE_CREATE_WITH_EXTRA_SIZE(type) \
+DEFINE_CREATE(type) \
+DEFINE_DESTROY(type) \
+
+#ifndef DEC_RETURN_ZERO
+#error refcount_os.h does not define DEC_RETURN_ZERO
+#endif // !DEC_RETURN_ZERO
+#ifndef INC_REF_VAR
+#error refcount_os.h does not define INC_REF_VAR
+#endif // !INC_REF
+#ifndef DEC_REF_VAR
+#error refcount_os.h does not define DEC_REF_VAR
+#endif // !DEC_REF
+#ifndef INIT_REF_VAR
+#error refcount_os.h does not define INIT_REF_VAR
+#endif // !INIT_REF
+
+#define INC_REF(type, var) INC_REF_VAR(((REFCOUNT_TYPE(type)*)((unsigned char*)var - offsetof(REFCOUNT_TYPE(type), counted)))->count)
+#define DEC_REF(type, var) DEC_REF_VAR(((REFCOUNT_TYPE(type)*)((unsigned char*)var - offsetof(REFCOUNT_TYPE(type), counted)))->count)
+#define INIT_REF(type, var) INIT_REF_VAR(((REFCOUNT_TYPE(type)*)((unsigned char*)var - offsetof(REFCOUNT_TYPE(type), counted)))->count)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*REFCOUNT_H*/
+
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/sastoken.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/sastoken.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/sastoken.h	(revision 453)
@@ -0,0 +1,27 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef SASTOKEN_H
+#define SASTOKEN_H
+
+#ifdef __cplusplus
+#else
+#include <stdbool.h>
+#endif
+
+#include "azure_c_shared_utility/strings.h"
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+    MOCKABLE_FUNCTION(, bool, SASToken_Validate, STRING_HANDLE, sasToken);
+    MOCKABLE_FUNCTION(, STRING_HANDLE, SASToken_Create, STRING_HANDLE, key, STRING_HANDLE, scope, STRING_HANDLE, keyName, size_t, expiry);
+    MOCKABLE_FUNCTION(, STRING_HANDLE, SASToken_CreateString, const char*, key, const char*, scope, const char*, keyName, size_t, expiry);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SASTOKEN_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/sha-private.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/sha-private.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/sha-private.h	(revision 453)
@@ -0,0 +1,33 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/*************************** sha-private.h ***************************/
+/********************** See RFC 4634 for details *********************/
+#ifndef _SHA_PRIVATE__H
+#define _SHA_PRIVATE__H
+/*
+* These definitions are defined in FIPS-180-2, section 4.1.
+* Ch() and Maj() are defined identically in sections 4.1.1,
+* 4.1.2 and 4.1.3.
+*
+* The definitions used in FIPS-180-2 are as follows:
+*/
+
+#ifndef USE_MODIFIED_MACROS
+#define SHA_Ch(x,y,z)        (((x) & (y)) ^ ((~(x)) & (z)))
+#define SHA_Maj(x,y,z)       (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+
+#else /* USE_MODIFIED_MACROS */
+/*
+* The following definitions are equivalent and potentially faster.
+*/
+
+#define SHA_Ch(x, y, z)      (((x) & ((y) ^ (z))) ^ (z))
+#define SHA_Maj(x, y, z)     (((x) & ((y) | (z))) | ((y) & (z)))
+
+#endif /* USE_MODIFIED_MACROS */
+
+#define SHA_Parity(x, y, z)  ((x) ^ (y) ^ (z))
+
+#endif /* _SHA_PRIVATE__H */
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/sha.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/sha.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/sha.h	(revision 453)
@@ -0,0 +1,260 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/**************************** sha.h ****************************/
+/******************* See RFC 4634 for details ******************/
+#ifndef _SHA_H_
+#define _SHA_H_
+
+/*
+ *  Description:
+ *      This file implements the Secure Hash Signature Standard
+ *      algorithms as defined in the National Institute of Standards
+ *      and Technology Federal Information Processing Standards
+ *      Publication (FIPS PUB) 180-1 published on April 17, 1995, 180-2
+ *      published on August 1, 2002, and the FIPS PUB 180-2 Change
+ *      Notice published on February 28, 2004.
+ *
+ *      A combined document showing all algorithms is available at
+ *              http://csrc.nist.gov/publications/fips/
+ *              fips180-2/fips180-2withchangenotice.pdf
+ *
+ *      The five hashes are defined in these sizes:
+ *              SHA-1           20 byte / 160 bit
+ *              SHA-224         28 byte / 224 bit
+ *              SHA-256         32 byte / 256 bit
+ *              SHA-384         48 byte / 384 bit
+ *              SHA-512         64 byte / 512 bit
+ */
+
+#ifdef __cplusplus
+#include <cstdint>
+#else
+#include <stdint.h>
+#endif
+
+/*
+ * If you do not have the ISO standard stdint.h header file, then you
+ * must typedef the following:
+ *    name              meaning
+ *  uint64_t         unsigned 64 bit integer
+ *  uint32_t         unsigned 32 bit integer
+ *  uint8_t          unsigned 8 bit integer (i.e., unsigned char)
+ *  int_least16_t    integer of >= 16 bits
+ *
+ */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#ifndef _SHA_enum_
+#define _SHA_enum_
+/*
+ *  All SHA functions return one of these values.
+ */
+enum {
+    shaSuccess = 0,
+    shaNull,            /* Null pointer parameter */
+    shaInputTooLong,    /* input data too long */
+    shaStateError,      /* called Input after FinalBits or Result */
+    shaBadParam         /* passed a bad parameter */
+};
+#endif /* _SHA_enum_ */
+
+/*
+ *  These constants hold size information for each of the SHA
+ *  hashing operations
+ */
+enum {
+    SHA1_Message_Block_Size = 64, SHA224_Message_Block_Size = 64,
+    SHA256_Message_Block_Size = 64, SHA384_Message_Block_Size = 128,
+    SHA512_Message_Block_Size = 128,
+    USHA_Max_Message_Block_Size = SHA512_Message_Block_Size,
+
+    SHA1HashSize = 20, SHA224HashSize = 28, SHA256HashSize = 32,
+    SHA384HashSize = 48, SHA512HashSize = 64,
+    USHAMaxHashSize = SHA512HashSize,
+
+    SHA1HashSizeBits = 160, SHA224HashSizeBits = 224,
+    SHA256HashSizeBits = 256, SHA384HashSizeBits = 384,
+    SHA512HashSizeBits = 512, USHAMaxHashSizeBits = SHA512HashSizeBits
+};
+
+/*
+ *  These constants are used in the USHA (unified sha) functions.
+ */
+typedef enum SHAversion {
+    SHA1, SHA224, SHA256, SHA384, SHA512
+} SHAversion;
+
+/*
+ *  This structure will hold context information for the SHA-1
+ *  hashing operation.
+ */
+typedef struct SHA1Context {
+    uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */
+
+    uint32_t Length_Low;                /* Message length in bits */
+    uint32_t Length_High;               /* Message length in bits */
+
+    int_least16_t Message_Block_Index;  /* Message_Block array index */
+                                        /* 512-bit message blocks */
+    uint8_t Message_Block[SHA1_Message_Block_Size];
+
+    int Computed;                       /* Is the digest computed? */
+    int Corrupted;                      /* Is the digest corrupted? */
+} SHA1Context;
+
+/*
+ *  This structure will hold context information for the SHA-256
+ *  hashing operation.
+ */
+typedef struct SHA256Context {
+    uint32_t Intermediate_Hash[SHA256HashSize/4]; /* Message Digest */
+
+    uint32_t Length_Low;                /* Message length in bits */
+    uint32_t Length_High;               /* Message length in bits */
+
+    int_least16_t Message_Block_Index;  /* Message_Block array index */
+                                        /* 512-bit message blocks */
+    uint8_t Message_Block[SHA256_Message_Block_Size];
+
+    int Computed;                       /* Is the digest computed? */
+    int Corrupted;                      /* Is the digest corrupted? */
+} SHA256Context;
+
+/*
+ *  This structure will hold context information for the SHA-512
+ *  hashing operation.
+ */
+typedef struct SHA512Context {
+#ifdef USE_32BIT_ONLY
+    uint32_t Intermediate_Hash[SHA512HashSize/4]; /* Message Digest  */
+    uint32_t Length[4];                 /* Message length in bits */
+#else /* !USE_32BIT_ONLY */
+    uint64_t Intermediate_Hash[SHA512HashSize/8]; /* Message Digest */
+    uint64_t Length_Low, Length_High;   /* Message length in bits */
+#endif /* USE_32BIT_ONLY */
+
+    int_least16_t Message_Block_Index;  /* Message_Block array index */
+                                        /* 1024-bit message blocks */
+    uint8_t Message_Block[SHA512_Message_Block_Size];
+
+    int Computed;                       /* Is the digest computed?*/
+    int Corrupted;                      /* Is the digest corrupted? */
+} SHA512Context;
+
+/*
+ *  This structure will hold context information for the SHA-224
+ *  hashing operation. It uses the SHA-256 structure for computation.
+ */
+typedef struct SHA256Context SHA224Context;
+
+/*
+ *  This structure will hold context information for the SHA-384
+ *  hashing operation. It uses the SHA-512 structure for computation.
+ */
+typedef struct SHA512Context SHA384Context;
+
+/*
+ *  This structure holds context information for all SHA
+ *  hashing operations.
+ */
+typedef struct USHAContext {
+    int whichSha;               /* which SHA is being used */
+    union {
+      SHA1Context sha1Context;
+      SHA224Context sha224Context; SHA256Context sha256Context;
+      SHA384Context sha384Context; SHA512Context sha512Context;
+    } ctx;
+} USHAContext;
+
+/*
+ *  This structure will hold context information for the HMAC
+ *  keyed hashing operation.
+ */
+typedef struct HMACContext {
+    int whichSha;               /* which SHA is being used */
+    int hashSize;               /* hash size of SHA being used */
+    int blockSize;              /* block size of SHA being used */
+    USHAContext shaContext;     /* SHA context */
+    unsigned char k_opad[USHA_Max_Message_Block_Size];
+                        /* outer padding - key XORd with opad */
+} HMACContext;
+
+
+/*
+ *  Function Prototypes
+ */
+
+/* SHA-1 */
+int SHA1Reset(SHA1Context *);
+int SHA1Input(SHA1Context *, const uint8_t *bytes, unsigned int bytecount);
+int SHA1FinalBits(SHA1Context *, const uint8_t bits, unsigned int bitcount);
+int SHA1Result(SHA1Context *, uint8_t Message_Digest[SHA1HashSize]);
+
+/* SHA-224 */
+int SHA224Reset(SHA224Context *);
+int SHA224Input(SHA224Context *, const uint8_t *bytes, unsigned int bytecount);
+int SHA224FinalBits(SHA224Context *, const uint8_t bits, unsigned int bitcount);
+int SHA224Result(SHA224Context *, uint8_t Message_Digest[SHA224HashSize]);
+
+/* SHA-256 */
+int SHA256Reset(SHA256Context *);
+int SHA256Input(SHA256Context *, const uint8_t *bytes, unsigned int bytecount);
+int SHA256FinalBits(SHA256Context *, const uint8_t bits, unsigned int bitcount);
+int SHA256Result(SHA256Context *, uint8_t Message_Digest[SHA256HashSize]);
+
+/* SHA-384 */
+int SHA384Reset(SHA384Context *);
+int SHA384Input(SHA384Context *, const uint8_t *bytes, unsigned int bytecount);
+int SHA384FinalBits(SHA384Context *, const uint8_t bits, unsigned int bitcount);
+int SHA384Result(SHA384Context *, uint8_t Message_Digest[SHA384HashSize]);
+
+/* SHA-512 */
+int SHA512Reset(SHA512Context *);
+int SHA512Input(SHA512Context *, const uint8_t *bytes, unsigned int bytecount);
+int SHA512FinalBits(SHA512Context *, const uint8_t bits, unsigned int bitcount);
+int SHA512Result(SHA512Context *, uint8_t Message_Digest[SHA512HashSize]);
+
+/* Unified SHA functions, chosen by whichSha */
+int USHAReset(USHAContext *, SHAversion whichSha);
+int USHAInput(USHAContext *, const uint8_t *bytes, unsigned int bytecount);
+int USHAFinalBits(USHAContext *, const uint8_t bits, unsigned int bitcount);
+int USHAResult(USHAContext *, uint8_t Message_Digest[USHAMaxHashSize]);
+int USHABlockSize(enum SHAversion whichSha);
+int USHAHashSize(enum SHAversion whichSha);
+int USHAHashSizeBits(enum SHAversion whichSha);
+
+/*
+ * HMAC Keyed-Hashing for Message Authentication, RFC2104,
+ * for all SHAs.
+ * This interface allows a fixed-length text input to be used.
+ */
+int hmac(SHAversion whichSha, /* which SHA algorithm to use */
+    const unsigned char *text,     /* pointer to data stream */
+    int text_len,                  /* length of data stream */
+    const unsigned char *key,      /* pointer to authentication key */
+    int key_len,                   /* length of authentication key */
+    uint8_t digest[USHAMaxHashSize]); /* caller digest to fill in */
+
+/*
+ * HMAC Keyed-Hashing for Message Authentication, RFC2104,
+ * for all SHAs.
+ * This interface allows any length of text input to be used.
+ */
+int hmacReset(HMACContext *ctx, enum SHAversion whichSha, const unsigned char *key, int key_len);
+int hmacInput(HMACContext *ctx, const unsigned char *text, int text_len);
+
+int hmacFinalBits(HMACContext *ctx, const uint8_t bits, unsigned int bitcount);
+int hmacResult(HMACContext *ctx, uint8_t digest[USHAMaxHashSize]);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SHA_H_ */
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/shared_util_options.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/shared_util_options.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/shared_util_options.h	(revision 453)
@@ -0,0 +1,59 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef SHARED_UTIL_OPTIONS_H
+#define SHARED_UTIL_OPTIONS_H
+
+#include "azure_c_shared_utility/const_defines.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    typedef struct HTTP_PROXY_OPTIONS_TAG
+    {
+        const char* host_address;
+        int port;
+        const char* username;
+        const char* password;
+    } HTTP_PROXY_OPTIONS;
+
+    static STATIC_VAR_UNUSED const char* const OPTION_HTTP_PROXY = "proxy_data";
+    static STATIC_VAR_UNUSED const char* const OPTION_HTTP_TIMEOUT = "timeout";
+
+    static STATIC_VAR_UNUSED const char* const OPTION_TRUSTED_CERT = "TrustedCerts";
+
+    // Clients should not use OPTION_OPENSSL_CIPHER_SUITE except for very specialized scenarios.
+    // They instead should rely on the underlying client TLS stack and service to negotiate an appropriate cipher.
+    static STATIC_VAR_UNUSED const char* const OPTION_OPENSSL_CIPHER_SUITE = "CipherSuite";
+
+    static STATIC_VAR_UNUSED const char* const SU_OPTION_X509_CERT = "x509certificate";
+    static STATIC_VAR_UNUSED const char* const SU_OPTION_X509_PRIVATE_KEY = "x509privatekey";
+
+    static STATIC_VAR_UNUSED const char* const OPTION_X509_ECC_CERT = "x509EccCertificate";
+    static STATIC_VAR_UNUSED const char* const OPTION_X509_ECC_KEY = "x509EccAliasKey";
+
+    static STATIC_VAR_UNUSED const char* const OPTION_CURL_LOW_SPEED_LIMIT = "CURLOPT_LOW_SPEED_LIMIT";
+    static STATIC_VAR_UNUSED const char* const OPTION_CURL_LOW_SPEED_TIME = "CURLOPT_LOW_SPEED_TIME";
+    static STATIC_VAR_UNUSED const char* const OPTION_CURL_FRESH_CONNECT = "CURLOPT_FRESH_CONNECT";
+    static STATIC_VAR_UNUSED const char* const OPTION_CURL_FORBID_REUSE = "CURLOPT_FORBID_REUSE";
+    static STATIC_VAR_UNUSED const char* const OPTION_CURL_VERBOSE = "CURLOPT_VERBOSE";
+
+    static STATIC_VAR_UNUSED const char* const OPTION_NET_INT_MAC_ADDRESS = "net_interface_mac_address";
+
+    static STATIC_VAR_UNUSED const char* const OPTION_SET_TLS_RENEGOTIATION = "tls_renegotiation";
+
+    // DEPRECATED: The underlying security library for your platform will use a secure TLS version 
+    // that in general  should not be overridden with OPTION_TLS_VERSION.
+    static STATIC_VAR_UNUSED const char* const OPTION_TLS_VERSION = "tls_version";
+
+    static STATIC_VAR_UNUSED const char* const OPTION_ADDRESS_TYPE = "ADDRESS_TYPE";
+    static STATIC_VAR_UNUSED const char* const OPTION_ADDRESS_TYPE_DOMAIN_SOCKET = "DOMAIN_SOCKET";
+    static STATIC_VAR_UNUSED const char* const OPTION_ADDRESS_TYPE_IP_SOCKET = "IP_SOCKET";
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SHARED_UTIL_OPTIONS_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/singlylinkedlist.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/singlylinkedlist.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/singlylinkedlist.h	(revision 453)
@@ -0,0 +1,60 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef SINGLYLINKEDLIST_H
+#define SINGLYLINKEDLIST_H
+
+#ifdef __cplusplus
+#else
+#include "stdbool.h"
+#endif /* __cplusplus */
+
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct SINGLYLINKEDLIST_INSTANCE_TAG* SINGLYLINKEDLIST_HANDLE;
+typedef struct LIST_ITEM_INSTANCE_TAG* LIST_ITEM_HANDLE;
+
+/**
+* @brief                        Function passed to singlylinkedlist_find, which returns whichever first list item that matches it.
+* @param list_item                Current list node being evaluated.
+* @param match_context            Context passed to singlylinkedlist_find.
+* @returns                        True to indicate that the current list node is the one to be returned, or false to continue traversing the list.
+*/
+typedef bool (*LIST_MATCH_FUNCTION)(LIST_ITEM_HANDLE list_item, const void* match_context);
+/**
+* @brief                        Function passed to singlylinkedlist_remove_if, which is used to define if an item of the list should be removed or not.
+* @param item                    Value of the current list node being evaluated for removal.
+* @param match_context            Context passed to singlylinkedlist_remove_if.
+* @param continue_processing    Indicates if singlylinkedlist_remove_if shall continue iterating through the next nodes of the list or stop.
+* @returns                        True to indicate that the current list node shall be removed, or false to not to.
+*/
+typedef bool (*LIST_CONDITION_FUNCTION)(const void* item, const void* match_context, bool* continue_processing);
+/**
+* @brief                        Function passed to singlylinkedlist_foreach, which is called for the value of each node of the list.
+* @param item                    Value of the current list node being processed.
+* @param action_context            Context passed to singlylinkedlist_foreach.
+* @param continue_processing    Indicates if singlylinkedlist_foreach shall continue iterating through the next nodes of the list or stop.
+*/
+typedef void (*LIST_ACTION_FUNCTION)(const void* item, const void* action_context, bool* continue_processing);
+
+MOCKABLE_FUNCTION(, SINGLYLINKEDLIST_HANDLE, singlylinkedlist_create);
+MOCKABLE_FUNCTION(, void, singlylinkedlist_destroy, SINGLYLINKEDLIST_HANDLE, list);
+MOCKABLE_FUNCTION(, LIST_ITEM_HANDLE, singlylinkedlist_add, SINGLYLINKEDLIST_HANDLE, list, const void*, item);
+MOCKABLE_FUNCTION(, LIST_ITEM_HANDLE, singlylinkedlist_add_head, SINGLYLINKEDLIST_HANDLE, list, const void*, item);
+MOCKABLE_FUNCTION(, int, singlylinkedlist_remove, SINGLYLINKEDLIST_HANDLE, list, LIST_ITEM_HANDLE, item_handle);
+MOCKABLE_FUNCTION(, LIST_ITEM_HANDLE, singlylinkedlist_get_head_item, SINGLYLINKEDLIST_HANDLE, list);
+MOCKABLE_FUNCTION(, LIST_ITEM_HANDLE, singlylinkedlist_get_next_item, LIST_ITEM_HANDLE, item_handle);
+MOCKABLE_FUNCTION(, LIST_ITEM_HANDLE, singlylinkedlist_find, SINGLYLINKEDLIST_HANDLE, list, LIST_MATCH_FUNCTION, match_function, const void*, match_context);
+MOCKABLE_FUNCTION(, const void*, singlylinkedlist_item_get_value, LIST_ITEM_HANDLE, item_handle);
+MOCKABLE_FUNCTION(, int, singlylinkedlist_remove_if, SINGLYLINKEDLIST_HANDLE, list, LIST_CONDITION_FUNCTION, condition_function, const void*, match_context);
+MOCKABLE_FUNCTION(, int, singlylinkedlist_foreach, SINGLYLINKEDLIST_HANDLE, list, LIST_ACTION_FUNCTION, action_function, const void*, action_context);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* SINGLYLINKEDLIST_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/socketio.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/socketio.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/socketio.h	(revision 453)
@@ -0,0 +1,52 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef SOCKETIO_H
+#define SOCKETIO_H
+
+#ifdef __cplusplus
+#include <cstddef>
+#else
+#include <stddef.h>
+#endif /* __cplusplus */
+
+#include "azure_c_shared_utility/xio.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct SOCKETIO_CONFIG_TAG
+{
+    const char* hostname;
+    int port;
+    void* accepted_socket;
+} SOCKETIO_CONFIG;
+
+typedef enum SOCKETIO_ADDRESS_TYPE_TAG
+{
+    ADDRESS_TYPE_IP,
+    ADDRESS_TYPE_DOMAIN_SOCKET
+} SOCKETIO_ADDRESS_TYPE;
+
+#ifndef XIO_RECEIVE_BUFFER_SIZE
+#define XIO_RECEIVE_BUFFER_SIZE     64
+#endif
+
+MOCKABLE_FUNCTION(, CONCRETE_IO_HANDLE, socketio_create, void*, io_create_parameters);
+MOCKABLE_FUNCTION(, void, socketio_destroy, CONCRETE_IO_HANDLE, socket_io);
+MOCKABLE_FUNCTION(, int, socketio_open, CONCRETE_IO_HANDLE, socket_io, ON_IO_OPEN_COMPLETE, on_io_open_complete, void*, on_io_open_complete_context, ON_BYTES_RECEIVED, on_bytes_received, void*, on_bytes_received_context, ON_IO_ERROR, on_io_error, void*, on_io_error_context);
+MOCKABLE_FUNCTION(, int, socketio_close, CONCRETE_IO_HANDLE, socket_io, ON_IO_CLOSE_COMPLETE, on_io_close_complete, void*, callback_context);
+MOCKABLE_FUNCTION(, int, socketio_send, CONCRETE_IO_HANDLE, socket_io, const void*, buffer, size_t, size, ON_SEND_COMPLETE, on_send_complete, void*, callback_context);
+MOCKABLE_FUNCTION(, void, socketio_dowork, CONCRETE_IO_HANDLE, socket_io);
+MOCKABLE_FUNCTION(, int, socketio_setoption, CONCRETE_IO_HANDLE, socket_io, const char*, optionName, const void*, value);
+
+MOCKABLE_FUNCTION(, const IO_INTERFACE_DESCRIPTION*, socketio_get_interface_description);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* SOCKETIO_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/string_token.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/string_token.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/string_token.h	(revision 453)
@@ -0,0 +1,95 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef STRING_TOKEN_H
+#define STRING_TOKEN_H
+
+#ifdef __cplusplus
+#include <cstddef>
+#else
+#include <stddef.h>
+#include <stdbool.h>
+#endif
+
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef struct STRING_TOKEN_TAG* STRING_TOKEN_HANDLE;
+
+/*
+*    @brief     Tries to identify the first token defined in source up to its length using the delimiters provided.
+*    @Remark    If no delimiter is found, the entire source string becomes the resulting token. Empty tokens (when delimiters occur side-by-side) can also detected.
+*    @param     source        The initial string to be tokenized.
+*    @param     length        The length of the source string, not including the null-terminator.
+*    @param     delimiters    Array with null-terminated strings to be used as token delimiters.
+*    @param     n_delims      Number of elements in delimiters array.
+*    @return    A STRING_TOKEN_HANDLE if no failures occur (arguments, memory allocation), or NULL otherwise.
+*/
+MOCKABLE_FUNCTION(, STRING_TOKEN_HANDLE, StringToken_GetFirst, const char*, source, size_t, length, const char**, delimiters, size_t, n_delims);
+
+/*
+*    @brief     Tries to identify the next token defined in source up to its length using the delimiters provided.
+*    @Remark    After StringToken_GetFirst is initially called, StringToken_GetNext shall be called for obtaining the next tokens.
+*               If no delimiter is found, the entire source string becomes the resulting token.
+*               Empty tokens (when delimiters occur side-by-side) can also detected.
+*    @param     token         The handle returned by StringToken_GetFirst.
+*    @param     delimiters    Array with null-terminated strings to be used as token delimiters.
+*    @param     n_delims      Number of elements in delimiters array.
+*    @return    True if a token could be identified, or false if the tokenizer already reached the end of the source string an no more tokens are available.
+*/
+MOCKABLE_FUNCTION(, bool, StringToken_GetNext, STRING_TOKEN_HANDLE, token, const char**, delimiters, size_t, n_delims);
+
+/*
+*    @brief     Gets the pointer to the beginning of the current token identified in the source string.
+*    @param     token         The handle returned by StringToken_GetFirst.
+*    @return    The pointer to the token identified in the last successfull call to StringToken_GetFirst or StringToken_GetNext.
+*               If the token string is empty (e.g., between two delimiters side-by-side or if a delimiter occurs at the end of the source string),
+*               NULL is returned instead of an empty string.
+*/
+MOCKABLE_FUNCTION(, const char*, StringToken_GetValue, STRING_TOKEN_HANDLE, token);
+
+/*
+*    @brief     Gets the length of the current token identified in the source string.
+*    @param     token         The handle returned by StringToken_GetFirst.
+*    @return    A non-zero value if the current token is not empty, zero otherwise.
+*/
+MOCKABLE_FUNCTION(, size_t, StringToken_GetLength, STRING_TOKEN_HANDLE, token);
+
+/*
+*    @brief     Gets a pointer to last delimiter identified (which defined the current token).
+*    @param     token         The handle returned by StringToken_GetFirst.
+*    @return    If a delimiter was identified in the previous search,
+*               the pointer returned is to the element in the delimiters array provided in the previous call to StringToken_GetFirst or StringToken_GetNext;
+*               it returns NULL if no delimiter was found in the previous call to those functions.
+*/
+MOCKABLE_FUNCTION(, const char*, StringToken_GetDelimiter, STRING_TOKEN_HANDLE, token);
+
+/*
+*    @brief     Splits a string into an array with all the tokens identified using the delimiters provided.
+*    @param     source           The string to be tokenized.
+*    @param     length           The length of the source string, not including the null-terminator.
+*    @param     delimiters       Array with null-terminated strings to be used as token delimiters.
+*    @param     n_delims         Number of elements in delimiters array.
+*    @param     include_empty    Indicates if empty strings shall be included (as NULL values) in the resulting array.
+*    @param     tokens           If no failures occur, the resulting array with the split tokens (dynamically allocated).
+*    @param     token_count      The number of elements in the tokens array.
+*    @return    Zero if no failures occur, or a non-zero value otherwise.
+*/
+MOCKABLE_FUNCTION(, int, StringToken_Split, const char*, source, size_t, length, const char**, delimiters, size_t, n_delims, bool, include_empty, char***, tokens, size_t*, token_count);
+
+/*
+*    @brief     Destroys the handle created when calling StringToken_GetFirst.
+*    @param     token         The handle returned by StringToken_GetFirst.
+*    @return    Nothing
+*/
+MOCKABLE_FUNCTION(, void, StringToken_Destroy, STRING_TOKEN_HANDLE, token);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /*STRING_TOKEN_H*/
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/string_tokenizer.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/string_tokenizer.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/string_tokenizer.h	(revision 453)
@@ -0,0 +1,25 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef STRING_TOKENIZER_H
+#define STRING_TOKENIZER_H
+
+#include "azure_c_shared_utility/strings.h"
+#include "umock_c/umock_c_prod.h"
+#include "azure_c_shared_utility/string_tokenizer_types.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+MOCKABLE_FUNCTION(, STRING_TOKENIZER_HANDLE, STRING_TOKENIZER_create, STRING_HANDLE, handle);
+MOCKABLE_FUNCTION(, STRING_TOKENIZER_HANDLE, STRING_TOKENIZER_create_from_char, const char*, input);
+MOCKABLE_FUNCTION(, int, STRING_TOKENIZER_get_next_token, STRING_TOKENIZER_HANDLE, t, STRING_HANDLE, output, const char*, delimiters);
+MOCKABLE_FUNCTION(, void, STRING_TOKENIZER_destroy, STRING_TOKENIZER_HANDLE, t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /*STRING_TOKENIZER_H*/
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/string_tokenizer_types.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/string_tokenizer_types.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/string_tokenizer_types.h	(revision 453)
@@ -0,0 +1,18 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef STRING_TOKENIZER_TYPES_H
+#define STRING_TOKENIZER_TYPES_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    typedef struct STRING_TOKEN_TAG* STRING_TOKENIZER_HANDLE;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /*STRING_TOKENIZER_TYPES_H*/
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/strings.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/strings.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/strings.h	(revision 453)
@@ -0,0 +1,48 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef STRINGS_H
+#define STRINGS_H
+
+#ifdef __cplusplus
+#include <cstddef>
+#else
+#include <stddef.h>
+#endif
+
+#include "umock_c/umock_c_prod.h"
+#include "azure_c_shared_utility/strings_types.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+MOCKABLE_FUNCTION(, STRING_HANDLE, STRING_new);
+MOCKABLE_FUNCTION(, STRING_HANDLE, STRING_clone, STRING_HANDLE, handle);
+MOCKABLE_FUNCTION(, STRING_HANDLE, STRING_construct, const char*, psz);
+MOCKABLE_FUNCTION(, STRING_HANDLE, STRING_construct_n, const char*, psz, size_t, n);
+MOCKABLE_FUNCTION(, STRING_HANDLE, STRING_new_with_memory, const char*, memory);
+MOCKABLE_FUNCTION(, STRING_HANDLE, STRING_new_quoted, const char*, source);
+MOCKABLE_FUNCTION(, STRING_HANDLE, STRING_new_JSON, const char*, source);
+MOCKABLE_FUNCTION(, STRING_HANDLE, STRING_from_byte_array, const unsigned char*, source, size_t, size);
+MOCKABLE_FUNCTION(, void, STRING_delete, STRING_HANDLE, handle);
+MOCKABLE_FUNCTION(, int, STRING_concat, STRING_HANDLE, handle, const char*, s2);
+MOCKABLE_FUNCTION(, int, STRING_concat_with_STRING, STRING_HANDLE, s1, STRING_HANDLE, s2);
+MOCKABLE_FUNCTION(, int, STRING_quote, STRING_HANDLE, handle);
+MOCKABLE_FUNCTION(, int, STRING_copy, STRING_HANDLE, s1, const char*, s2);
+MOCKABLE_FUNCTION(, int, STRING_copy_n, STRING_HANDLE, s1, const char*, s2, size_t, n);
+MOCKABLE_FUNCTION(, const char*, STRING_c_str, STRING_HANDLE, handle);
+MOCKABLE_FUNCTION(, int, STRING_empty, STRING_HANDLE, handle);
+MOCKABLE_FUNCTION(, size_t, STRING_length, STRING_HANDLE, handle);
+MOCKABLE_FUNCTION(, int, STRING_compare, STRING_HANDLE, s1, STRING_HANDLE, s2);
+MOCKABLE_FUNCTION(, int, STRING_replace, STRING_HANDLE, handle, char, target, char, replace);
+
+extern STRING_HANDLE STRING_construct_sprintf(const char* format, ...);
+extern int STRING_sprintf(STRING_HANDLE s1, const char* format, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /*STRINGS_H*/
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/strings_types.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/strings_types.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/strings_types.h	(revision 453)
@@ -0,0 +1,18 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef STRINGS_TYPES_H
+#define STRINGS_TYPES_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    typedef struct STRING_TAG* STRING_HANDLE;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /*STRINGS_TYPES_H*/
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/tcpsocketconnection_c.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/tcpsocketconnection_c.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/tcpsocketconnection_c.h	(revision 453)
@@ -0,0 +1,28 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef TCPSOCKETCONNECTION_C_H
+#define TCPSOCKETCONNECTION_C_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+	typedef void* TCPSOCKETCONNECTION_HANDLE;
+
+	TCPSOCKETCONNECTION_HANDLE tcpsocketconnection_create(void);
+	void tcpsocketconnection_set_blocking(TCPSOCKETCONNECTION_HANDLE tcpSocketConnectionHandle, bool blocking, unsigned int timeout);
+	void tcpsocketconnection_destroy(TCPSOCKETCONNECTION_HANDLE tcpSocketConnectionHandle);
+	int tcpsocketconnection_connect(TCPSOCKETCONNECTION_HANDLE tcpSocketConnectionHandle, const char* host, const int port);
+	bool tcpsocketconnection_is_connected(TCPSOCKETCONNECTION_HANDLE tcpSocketConnectionHandle);
+	void tcpsocketconnection_close(TCPSOCKETCONNECTION_HANDLE tcpSocketConnectionHandle);
+	int tcpsocketconnection_send(TCPSOCKETCONNECTION_HANDLE tcpSocketConnectionHandle, const char* data, int length);
+	int tcpsocketconnection_send_all(TCPSOCKETCONNECTION_HANDLE tcpSocketConnectionHandle, const char* data, int length);
+	int tcpsocketconnection_receive(TCPSOCKETCONNECTION_HANDLE tcpSocketConnectionHandle, char* data, int length);
+	int tcpsocketconnection_receive_all(TCPSOCKETCONNECTION_HANDLE tcpSocketConnectionHandle, char* data, int length);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TCPSOCKETCONNECTION_C_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/threadapi.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/threadapi.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/threadapi.h	(revision 453)
@@ -0,0 +1,90 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/** @file threadapi.h
+ *	@brief	 This module implements support for creating new threads,
+ *			 terminating threads and sleeping threads.
+ */
+
+#ifndef THREADAPI_H
+#define THREADAPI_H
+
+#include "azure_macro_utils/macro_utils.h"
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+    
+typedef int(*THREAD_START_FUNC)(void *);
+
+#define THREADAPI_RESULT_VALUES \
+    THREADAPI_OK,               \
+    THREADAPI_INVALID_ARG,      \
+    THREADAPI_NO_MEMORY,        \
+    THREADAPI_ERROR
+
+/** @brief Enumeration specifying the possible return values for the APIs in
+ *		   this module.
+ */
+MU_DEFINE_ENUM(THREADAPI_RESULT, THREADAPI_RESULT_VALUES);
+
+typedef void* THREAD_HANDLE;
+
+/**
+ * @brief	Creates a thread with the entry point specified by the @p func
+ * 			argument.
+ *
+ * @param   threadHandle	The handle to the new thread is returned in this
+ * 							pointer.
+ * @param	func			A function pointer that indicates the entry point
+ * 							to the new thread.
+ * @param   arg				A void pointer that must be passed to the function
+ * 							pointed to by @p func.
+ *
+ * @return	@c THREADAPI_OK if the API call is successful or an error
+ * 			code in case it fails.
+ */
+MOCKABLE_FUNCTION(, THREADAPI_RESULT, ThreadAPI_Create, THREAD_HANDLE*, threadHandle, THREAD_START_FUNC, func, void*, arg);
+
+/**
+ * @brief	Blocks the calling thread by waiting on the thread identified by
+ * 			the @p threadHandle argument to complete.
+ *
+ * @param	threadHandle	The handle of the thread to wait for completion.
+ * @param   res 			The result returned by the thread which is passed
+ * 							to the ::ThreadAPI_Exit function.
+ *
+ *			When the @p threadHandle thread completes, all resources associated
+ *			with the thread must be released and the thread handle will no
+ *			longer be valid.
+ * 
+ * @return	@c THREADAPI_OK if the API call is successful or an error
+ * 			code in case it fails.
+ */
+MOCKABLE_FUNCTION(, THREADAPI_RESULT, ThreadAPI_Join, THREAD_HANDLE, threadHandle, int*, res);
+
+/**
+ * @brief	This function is called by a thread when the thread exits.
+ *
+ * @param	res		An integer that represents the exit status of the thread.
+ * 				
+ * 			This function is called by a thread when the thread exits in order
+ * 			to return a result value to the caller of the ::ThreadAPI_Join
+ * 			function. The @p res value must be copied into the @p res out
+ * 			argument passed to the ::ThreadAPI_Join function.
+ */
+MOCKABLE_FUNCTION(, void, ThreadAPI_Exit, int, res);
+
+/**
+ * @brief	Sleeps the current thread for the given number of milliseconds.
+ *
+ * @param	milliseconds	The number of milliseconds to sleep.
+ */
+MOCKABLE_FUNCTION(, void, ThreadAPI_Sleep, unsigned int, milliseconds);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* THREADAPI_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/tickcounter.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/tickcounter.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/tickcounter.h	(revision 453)
@@ -0,0 +1,35 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef TICKCOUNTER_H
+#define TICKCOUNTER_H
+
+#ifdef __cplusplus
+#include <cstdint>
+#else
+#include <stdint.h>
+#endif
+
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#if defined(_WIN32) || defined(__MBED__) || defined(__APPLE__)
+    typedef uint_fast64_t tickcounter_ms_t; // Use 64-bit because of 32-bit is going to roll over back to zero after roughly 49.7 days that is not good for IoT devices which need keep running for months
+#else
+    typedef uint_fast32_t tickcounter_ms_t;
+#endif
+    typedef struct TICK_COUNTER_INSTANCE_TAG *TICK_COUNTER_HANDLE;
+
+    MOCKABLE_FUNCTION(, TICK_COUNTER_HANDLE, tickcounter_create);
+    MOCKABLE_FUNCTION(, void, tickcounter_destroy, TICK_COUNTER_HANDLE, tick_counter);
+    MOCKABLE_FUNCTION(, int, tickcounter_get_current_ms, TICK_COUNTER_HANDLE, tick_counter, tickcounter_ms_t *, current_ms);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* TICKCOUNTER_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/tlsio.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/tlsio.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/tlsio.h	(revision 453)
@@ -0,0 +1,25 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef TLSIO_H
+#define TLSIO_H
+
+#include "xio.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct TLSIO_CONFIG_TAG
+{
+    const char* hostname;
+    int port;
+    const IO_INTERFACE_DESCRIPTION* underlying_io_interface;
+    void* underlying_io_parameters;
+} TLSIO_CONFIG;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* TLSIO_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/tlsio_esp_at.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/tlsio_esp_at.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/tlsio_esp_at.h	(revision 453)
@@ -0,0 +1,33 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef TLSIO_ESP_AT_H
+#define TLSIO_ESP_AT_H
+
+#include "azure_c_shared_utility/xio.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "umock_c/umock_c_prod.h"
+#include "azure_c_shared_utility/const_defines.h"
+
+#ifdef __cplusplus
+extern "C" {
+#include <cstddef>
+#else
+#include <stddef.h>
+#endif /* __cplusplus */
+
+MOCKABLE_FUNCTION(, CONCRETE_IO_HANDLE, tlsio_esp_at_create, void*, io_create_parameters);
+MOCKABLE_FUNCTION(, void, tlsio_esp_at_destroy, CONCRETE_IO_HANDLE, tls_io);
+MOCKABLE_FUNCTION(, int, tlsio_esp_at_open, CONCRETE_IO_HANDLE, tls_io, ON_IO_OPEN_COMPLETE, on_io_open_complete, void*, on_io_open_complete_context, ON_BYTES_RECEIVED, on_bytes_received, void*, on_bytes_received_context, ON_IO_ERROR, on_io_error, void*, on_io_error_context);
+MOCKABLE_FUNCTION(, int, tlsio_esp_at_close, CONCRETE_IO_HANDLE, tls_io, ON_IO_CLOSE_COMPLETE, on_io_close_complete, void*, callback_context);
+MOCKABLE_FUNCTION(, int, tlsio_esp_at_send, CONCRETE_IO_HANDLE, tls_io, const void*, buffer, size_t, size, ON_SEND_COMPLETE, on_send_complete, void*, callback_context);
+MOCKABLE_FUNCTION(, void, tlsio_esp_at_dowork, CONCRETE_IO_HANDLE, tls_io);
+MOCKABLE_FUNCTION(, int, tlsio_esp_at_setoption, CONCRETE_IO_HANDLE, tls_io, const char*, optionName, const void*, value);
+
+MOCKABLE_FUNCTION(, const IO_INTERFACE_DESCRIPTION*, tlsio_esp_at_get_interface_description);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* TLSIO_ESP_AT_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/tlsio_mbedtls.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/tlsio_mbedtls.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/tlsio_mbedtls.h	(revision 453)
@@ -0,0 +1,33 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef TLSIO_MBEDTLS_H
+#define TLSIO_MBEDTLS_H
+
+#include "azure_c_shared_utility/xio.h"
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C" {
+#include <cstddef>
+#else
+#include <stddef.h>
+#endif /* __cplusplus */
+
+extern const IO_INTERFACE_DESCRIPTION* tlsio_mbedtls_get_interface_description(void);
+
+MOCKABLE_FUNCTION(, CONCRETE_IO_HANDLE, tlsio_mbedtls_create, void*, io_create_parameters);
+MOCKABLE_FUNCTION(, void, tlsio_mbedtls_destroy, CONCRETE_IO_HANDLE, tls_io);
+MOCKABLE_FUNCTION(, int, tlsio_mbedtls_open, CONCRETE_IO_HANDLE, tls_io, ON_IO_OPEN_COMPLETE, on_io_open_complete, void*, on_io_open_complete_context, ON_BYTES_RECEIVED, on_bytes_received, void*, on_bytes_received_context, ON_IO_ERROR, on_io_error, void*, on_io_error_context);
+MOCKABLE_FUNCTION(, int, tlsio_mbedtls_close, CONCRETE_IO_HANDLE, tls_io, ON_IO_CLOSE_COMPLETE, on_io_close_complete, void*, callback_context);
+MOCKABLE_FUNCTION(, int, tlsio_mbedtls_send, CONCRETE_IO_HANDLE, tls_io, const void*, buffer, size_t, size, ON_SEND_COMPLETE, on_send_complete, void*, callback_context);
+MOCKABLE_FUNCTION(, void, tlsio_mbedtls_dowork, CONCRETE_IO_HANDLE, tls_io);
+MOCKABLE_FUNCTION(, int, tlsio_mbedtls_setoption, CONCRETE_IO_HANDLE, tls_io, const char*, optionName, const void*, value);
+
+MOCKABLE_FUNCTION(, const IO_INTERFACE_DESCRIPTION*, tlsio_mbedtls_get_interface_description);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* TLSIO_MBEDTLS_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/tlsio_wolfssl.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/tlsio_wolfssl.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/tlsio_wolfssl.h	(revision 453)
@@ -0,0 +1,35 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef TLSIO_WOLFSSL_H
+#define TLSIO_WOLFSSL_H
+
+#include "azure_c_shared_utility/xio.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "umock_c/umock_c_prod.h"
+#include "azure_c_shared_utility/const_defines.h"
+
+#ifdef __cplusplus
+extern "C" {
+#include <cstddef>
+#else
+#include <stddef.h>
+#endif /* __cplusplus */
+
+extern const char* const OPTION_WOLFSSL_SET_DEVICE_ID;
+
+MOCKABLE_FUNCTION(, CONCRETE_IO_HANDLE, tlsio_wolfssl_create, void*, io_create_parameters);
+MOCKABLE_FUNCTION(, void, tlsio_wolfssl_destroy, CONCRETE_IO_HANDLE, tls_io);
+MOCKABLE_FUNCTION(, int, tlsio_wolfssl_open, CONCRETE_IO_HANDLE, tls_io, ON_IO_OPEN_COMPLETE, on_io_open_complete, void*, on_io_open_complete_context, ON_BYTES_RECEIVED, on_bytes_received, void*, on_bytes_received_context, ON_IO_ERROR, on_io_error, void*, on_io_error_context);
+MOCKABLE_FUNCTION(, int, tlsio_wolfssl_close, CONCRETE_IO_HANDLE, tls_io, ON_IO_CLOSE_COMPLETE, on_io_close_complete, void*, callback_context);
+MOCKABLE_FUNCTION(, int, tlsio_wolfssl_send, CONCRETE_IO_HANDLE, tls_io, const void*, buffer, size_t, size, ON_SEND_COMPLETE, on_send_complete, void*, callback_context);
+MOCKABLE_FUNCTION(, void, tlsio_wolfssl_dowork, CONCRETE_IO_HANDLE, tls_io);
+MOCKABLE_FUNCTION(, int, tlsio_wolfssl_setoption, CONCRETE_IO_HANDLE, tls_io, const char*, optionName, const void*, value);
+
+MOCKABLE_FUNCTION(, const IO_INTERFACE_DESCRIPTION*, tlsio_wolfssl_get_interface_description);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* TLSIO_WOLFSSL_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/uniqueid.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/uniqueid.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/uniqueid.h	(revision 453)
@@ -0,0 +1,33 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef UNIQUEID_H
+#define UNIQUEID_H
+
+#ifdef __cplusplus
+#include <cstddef>
+#else
+#include <stddef.h>
+#endif
+
+#include "azure_macro_utils/macro_utils.h"
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define UNIQUEID_RESULT_VALUES    \
+    UNIQUEID_OK,                  \
+    UNIQUEID_INVALID_ARG,         \
+    UNIQUEID_ERROR
+
+    MU_DEFINE_ENUM(UNIQUEID_RESULT, UNIQUEID_RESULT_VALUES)
+
+        MOCKABLE_FUNCTION(, UNIQUEID_RESULT, UniqueId_Generate, char*, uid, size_t, bufferSize);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UNIQUEID_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/urlencode.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/urlencode.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/urlencode.h	(revision 453)
@@ -0,0 +1,44 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef URLENCODE_H
+#define URLENCODE_H
+
+#include "azure_c_shared_utility/strings.h"
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+    /* @brief   URL Encode (aka percent encode) a string.
+    * Please note that while the URL encoder accepts the full range of 8-bit extended ASCII,
+    * it has unpredictable behavior beyond the 7-bit ASCII standard. This function does NOT
+    * guarantee correctness of output for characters outside this range.
+    *
+    * @param    URL Encode can be done on a const char* or a STRING_HANDLE, use the appropriate
+    * function depending on input type, they both behave the same way.
+    *
+    * @return   Returns a STRING_HANDLE with the encoded string, or NULL on failure.
+    */
+    MOCKABLE_FUNCTION(, STRING_HANDLE, URL_Encode, STRING_HANDLE, input);
+    MOCKABLE_FUNCTION(, STRING_HANDLE, URL_EncodeString, const char*, textEncode);
+
+    /* @brief   URL Decode (aka percent decode) a string.
+    * Please note that the URL decoder only supports decoding characters that fall within the
+    * 7-bit ASCII range. It does NOT support 8-bit extended ASCII, and will fail if you try.
+    *
+    * @param    URL Decode can be done on a const char* or a STRING_HANDLE, use the appropriate
+    * function depending on input type, they both behave the same way.
+    *
+    * @return   Returns a STRING_HANDLE with the decoded string, or NULL on failure.
+    */
+    MOCKABLE_FUNCTION(, STRING_HANDLE, URL_Decode, STRING_HANDLE, input);
+    MOCKABLE_FUNCTION(, STRING_HANDLE, URL_DecodeString, const char*, textDecode);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* URLENCODE_H */
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/utf8_checker.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/utf8_checker.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/utf8_checker.h	(revision 453)
@@ -0,0 +1,26 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef UTF8_CHECKER_H
+#define UTF8_CHECKER_H
+
+#ifdef __cplusplus
+#include <cstddef>
+#else
+#include <stdbool.h>
+#include <stddef.h>
+#endif
+
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+MOCKABLE_FUNCTION(, bool, utf8_checker_is_valid_utf8, const unsigned char*, utf8_str, size_t, length);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* UTF8_CHECKER_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/uuid.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/uuid.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/uuid.h	(revision 453)
@@ -0,0 +1,61 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef UUID_H
+#define UUID_H
+
+#ifdef __cplusplus
+#include <cstddef>
+#include <cstdint>
+#else
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+#endif /* __cplusplus */
+
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef unsigned char UUID_T[16];
+
+/* These 2 strings can be conveniently used directly in printf statements
+  Notice that PRI_UUID has to be used like any other print format specifier, meaning it
+  has to be preceded with % */
+#define PRI_UUID        "02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
+#define UUID_FORMAT_VALUES(uuid) \
+    (uuid)[0], (uuid)[1], (uuid)[2], (uuid)[3], (uuid)[4], (uuid)[5], (uuid)[6], (uuid)[7], \
+    (uuid)[8], (uuid)[9], (uuid)[10], (uuid)[11], (uuid)[12], (uuid)[13], (uuid)[14], (uuid)[15]
+
+#define UUID_FORMAT_VALUES_OR_NULL(uuid) \
+    ((uuid) == NULL) ? 0 : (uuid)[0], ((uuid) == NULL) ? 0 : (uuid)[1], ((uuid) == NULL) ? 0 : (uuid)[2], ((uuid) == NULL) ? 0 : (uuid)[3], \
+    ((uuid) == NULL) ? 0 : (uuid)[4], ((uuid) == NULL) ? 0 : (uuid)[5], ((uuid) == NULL) ? 0 : (uuid)[6], ((uuid) == NULL) ? 0 : (uuid)[7], \
+    ((uuid) == NULL) ? 0 : (uuid)[8], ((uuid) == NULL) ? 0 : (uuid)[9], ((uuid) == NULL) ? 0 : (uuid)[10], ((uuid) == NULL) ? 0 : (uuid)[11], \
+    ((uuid) == NULL) ? 0 : (uuid)[12], ((uuid) == NULL) ? 0 : (uuid)[13], ((uuid) == NULL) ? 0 : (uuid)[14], ((uuid) == NULL) ? 0 : (uuid)[15] \
+
+/* @brief               Generates a true UUID
+*  @param uuid          A pre-allocated buffer for the bytes of the generated UUID
+*  @returns             Zero if no failures occur, non-zero otherwise.
+*/
+MOCKABLE_FUNCTION(, int, UUID_generate, UUID_T*, uuid);
+
+/* @brief               Gets the UUID value (byte sequence) of an well-formed UUID string.
+*  @param uuid_string   A null-terminated well-formed UUID string (e.g., "7f907d75-5e13-44cf-a1a3-19a01a2b4528").
+*  @param uuid          Sequence of bytes representing an UUID.
+*  @returns             Zero if no failures occur, non-zero otherwise.
+*/
+MOCKABLE_FUNCTION(, int, UUID_from_string, const char*, uuid_string, UUID_T*, uuid);
+
+/* @brief               Gets the string representation of the UUID value.
+*  @param uuid          Sequence of bytes representing an UUID.
+*  @returns             A null-terminated string representation of the UUID value provided (e.g., "7f907d75-5e13-44cf-a1a3-19a01a2b4528").
+*/
+MOCKABLE_FUNCTION(, char*, UUID_to_string, const UUID_T*, uuid);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UUID_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/uws_client.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/uws_client.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/uws_client.h	(revision 453)
@@ -0,0 +1,121 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef UWS_CLIENT_H
+#define UWS_CLIENT_H
+
+#ifdef __cplusplus
+#include <cstddef>
+#include <cstdint>
+#else
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#endif
+
+#include "xio.h"
+#include "umock_c/umock_c_prod.h"
+#include "azure_c_shared_utility/optionhandler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct UWS_CLIENT_INSTANCE_TAG* UWS_CLIENT_HANDLE;
+
+#define WS_SEND_FRAME_RESULT_VALUES \
+    WS_SEND_FRAME_OK, \
+    WS_SEND_FRAME_ERROR, \
+    WS_SEND_FRAME_CANCELLED
+
+MU_DEFINE_ENUM(WS_SEND_FRAME_RESULT, WS_SEND_FRAME_RESULT_VALUES);
+
+#define WS_OPEN_RESULT_VALUES \
+    WS_OPEN_OK, \
+    WS_OPEN_ERROR_UNDERLYING_IO_OPEN_FAILED, \
+    WS_OPEN_ERROR_UNDERLYING_IO_OPEN_CANCELLED, \
+    WS_OPEN_ERROR_NOT_ENOUGH_MEMORY, \
+    WS_OPEN_ERROR_CANNOT_CONSTRUCT_UPGRADE_REQUEST, \
+    WS_OPEN_ERROR_CANNOT_SEND_UPGRADE_REQUEST, \
+    WS_OPEN_ERROR_MULTIPLE_UNDERLYING_IO_OPEN_EVENTS, \
+    WS_OPEN_ERROR_CONSTRUCTING_UPGRADE_REQUEST, \
+    WS_OPEN_ERROR_INVALID_BYTES_RECEIVED_ARGUMENTS, \
+    WS_OPEN_ERROR_BYTES_RECEIVED_BEFORE_UNDERLYING_OPEN, \
+    WS_OPEN_CANCELLED, \
+    WS_OPEN_ERROR_UNDERLYING_IO_ERROR, \
+    WS_OPEN_ERROR_BAD_UPGRADE_RESPONSE, \
+    WS_OPEN_ERROR_BAD_RESPONSE_STATUS, \
+    WS_OPEN_ERROR_BASE64_ENCODE_FAILED
+
+MU_DEFINE_ENUM(WS_OPEN_RESULT, WS_OPEN_RESULT_VALUES);
+
+#define WS_ERROR_VALUES \
+    WS_ERROR_NOT_ENOUGH_MEMORY, \
+    WS_ERROR_BAD_FRAME_RECEIVED, \
+    WS_ERROR_CANNOT_REMOVE_SENT_ITEM_FROM_LIST, \
+    WS_ERROR_UNDERLYING_IO_ERROR, \
+    WS_ERROR_CANNOT_CLOSE_UNDERLYING_IO
+
+MU_DEFINE_ENUM(WS_ERROR, WS_ERROR_VALUES);
+
+#define WS_FRAME_TYPE_UNKNOWN       0x00
+#define WS_FRAME_TYPE_TEXT          0x01
+#define WS_FRAME_TYPE_BINARY        0x02
+
+/* Codes_SRS_UWS_CLIENT_01_324: [ 1000 indicates a normal closure, meaning that the purpose for which the connection was established has been fulfilled. ]*/
+/* Codes_SRS_UWS_CLIENT_01_325: [ 1001 indicates that an endpoint is "going away", such as a server going down or a browser having navigated away from a page. ]*/
+/* Codes_SRS_UWS_CLIENT_01_326: [ 1002 indicates that an endpoint is terminating the connection due to a protocol error. ]*/
+/* Codes_SRS_UWS_CLIENT_01_327: [ 1003 indicates that an endpoint is terminating the connection because it has received a type of data it cannot accept (e.g., an endpoint that understands only text data MAY send this if it receives a binary message). ]*/
+/* Codes_SRS_UWS_CLIENT_01_328: [ Reserved.  The specific meaning might be defined in the future. ]*/
+/* Codes_SRS_UWS_CLIENT_01_329: [ 1005 is a reserved value and MUST NOT be set as a status code in a Close control frame by an endpoint. ]*/
+/* Codes_SRS_UWS_CLIENT_01_330: [ 1006 is a reserved value and MUST NOT be set as a status code in a Close control frame by an endpoint. ]*/
+/* Codes_SRS_UWS_CLIENT_01_331: [ 1007 indicates that an endpoint is terminating the connection because it has received data within a message that was not consistent with the type of the message (e.g., non-UTF-8 [RFC3629] data within a text message). ]*/
+/* Codes_SRS_UWS_CLIENT_01_332: [ 1008 indicates that an endpoint is terminating the connection because it has received a message that violates its policy. ]*/
+/* Codes_SRS_UWS_CLIENT_01_333: [ 1009 indicates that an endpoint is terminating the connection because it has received a message that is too big for it to process. ]*/
+/* Codes_SRS_UWS_CLIENT_01_334: [ 1010 indicates that an endpoint (client) is terminating the connection because it has expected the server to negotiate one or more extension, but the server didn't return them in the response message of the WebSocket handshake. ]*/
+/* Codes_SRS_UWS_CLIENT_01_336: [ 1011 indicates that a server is terminating the connection because it encountered an unexpected condition that prevented it from fulfilling the request. ]*/
+/* Codes_SRS_UWS_CLIENT_01_337: [ 1015 is a reserved value and MUST NOT be set as a status code in a Close control frame by an endpoint. ]*/
+/*  */
+#define CLOSE_NORMAL                        1000
+#define CLOSE_GOING_AWAY                    1001
+#define CLOSE_PROTOCOL_ERROR                1002
+#define CLOSE_CANNOT_ACCEPT_DATA_TYPE       1003
+#define CLOSE_UNDEFINED_1004                1004
+#define CLOSE_RESERVED_1005                 1005
+#define CLOSE_RESERVED_1006                 1006
+#define CLOSE_INCONSISTENT_DATA_IN_MESSAGE  1007
+#define CLOSE_POLICY_VIOLATION              1008
+#define CLOSE_MESSAGE_TOO_BIG               1009
+#define CLOSE_UNSUPPORTED_EXTENSION_LIST    1010
+#define CLOSE_UNEXPECTED_CONDITION          1011
+#define CLOSE_RESERVED_1015                 1015
+
+typedef void(*ON_WS_FRAME_RECEIVED)(void* context, unsigned char frame_type, const unsigned char* buffer, size_t size);
+typedef void(*ON_WS_SEND_FRAME_COMPLETE)(void* context, WS_SEND_FRAME_RESULT ws_send_frame_result);
+typedef void(*ON_WS_OPEN_COMPLETE)(void* context, WS_OPEN_RESULT ws_open_result);
+typedef void(*ON_WS_CLOSE_COMPLETE)(void* context);
+typedef void(*ON_WS_PEER_CLOSED)(void* context, uint16_t* close_code, const unsigned char* extra_data, size_t extra_data_length);
+typedef void(*ON_WS_ERROR)(void* context, WS_ERROR error_code);
+
+typedef struct WS_PROTOCOL_TAG
+{
+    const char* protocol;
+} WS_PROTOCOL;
+
+MOCKABLE_FUNCTION(, UWS_CLIENT_HANDLE, uws_client_create, const char*, hostname, unsigned int, port, const char*, resource_name, bool, use_ssl, const WS_PROTOCOL*, protocols, size_t, protocol_count);
+MOCKABLE_FUNCTION(, UWS_CLIENT_HANDLE, uws_client_create_with_io, const IO_INTERFACE_DESCRIPTION*, io_interface, void*, io_create_parameters, const char*, hostname, unsigned int, port, const char*, resource_name, const WS_PROTOCOL*, protocols, size_t, protocol_count)
+MOCKABLE_FUNCTION(, void, uws_client_destroy, UWS_CLIENT_HANDLE, uws_client);
+MOCKABLE_FUNCTION(, int, uws_client_open_async, UWS_CLIENT_HANDLE, uws_client, ON_WS_OPEN_COMPLETE, on_ws_open_complete, void*, on_ws_open_complete_context, ON_WS_FRAME_RECEIVED, on_ws_frame_received, void*, on_ws_frame_received_context, ON_WS_PEER_CLOSED, on_ws_peer_closed, void*, on_ws_peer_closed_context, ON_WS_ERROR, on_ws_error, void*, on_ws_error_context);
+MOCKABLE_FUNCTION(, int, uws_client_close_async, UWS_CLIENT_HANDLE, uws_client, ON_WS_CLOSE_COMPLETE, on_ws_close_complete, void*, on_ws_close_complete_context);
+MOCKABLE_FUNCTION(, int, uws_client_close_handshake_async, UWS_CLIENT_HANDLE, uws_client, uint16_t, close_code, const char*, close_reason, ON_WS_CLOSE_COMPLETE, on_ws_close_complete, void*, on_ws_close_complete_context);
+MOCKABLE_FUNCTION(, int, uws_client_send_frame_async, UWS_CLIENT_HANDLE, uws_client, unsigned char, frame_type, const unsigned char*, buffer, size_t, size, bool, is_final, ON_WS_SEND_FRAME_COMPLETE, on_ws_send_frame_complete, void*, callback_context);
+MOCKABLE_FUNCTION(, void, uws_client_dowork, UWS_CLIENT_HANDLE, uws_client);
+MOCKABLE_FUNCTION(, int, uws_client_set_request_header, UWS_CLIENT_HANDLE, uws_client, const char*, name, const char*, value);
+MOCKABLE_FUNCTION(, int, uws_client_set_option, UWS_CLIENT_HANDLE, uws_client, const char*, option_name, const void*, value);
+MOCKABLE_FUNCTION(, OPTIONHANDLER_HANDLE, uws_client_retrieve_options, UWS_CLIENT_HANDLE, uws_client);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* UWS_CLIENT_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/uws_frame_encoder.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/uws_frame_encoder.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/uws_frame_encoder.h	(revision 453)
@@ -0,0 +1,52 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef UWS_FRAME_ENCODER_H
+#define UWS_FRAME_ENCODER_H
+
+#ifdef __cplusplus
+#include <cstddef>
+#else
+#include <stdbool.h>
+#include <stddef.h>
+#endif
+
+#include "azure_c_shared_utility/buffer_.h"
+#include "umock_c/umock_c_prod.h"
+#include "azure_macro_utils/macro_utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define RESERVED_1  0x04
+#define RESERVED_2  0x02
+#define RESERVED_3  0x01
+
+#define WS_FRAME_TYPE_VALUES \
+    WS_CONTINUATION_FRAME, \
+    WS_TEXT_FRAME, \
+    WS_BINARY_FRAME, \
+    WS_RESERVED_NON_CONTROL_FRAME_3, \
+    WS_RESERVED_NON_CONTROL_FRAME_4, \
+    WS_RESERVED_NON_CONTROL_FRAME_5, \
+    WS_RESERVED_NON_CONTROL_FRAME_6, \
+    WS_RESERVED_NON_CONTROL_FRAME_7, \
+    WS_CLOSE_FRAME, \
+    WS_PING_FRAME, \
+    WS_PONG_FRAME, \
+    WS_RESERVED_CONTROL_FRAME_B, \
+    WS_RESERVED_CONTROL_FRAME_C, \
+    WS_RESERVED_CONTROL_FRAME_D, \
+    WS_RESERVED_CONTROL_FRAME_E, \
+    WS_RESERVED_CONTROL_FRAME_F
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(WS_FRAME_TYPE, WS_FRAME_TYPE_VALUES);
+
+MOCKABLE_FUNCTION(, BUFFER_HANDLE, uws_frame_encoder_encode, WS_FRAME_TYPE, opcode, const unsigned char*, payload, size_t, length, bool, is_masked, bool, is_final, unsigned char, reserved);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* UWS_FRAME_ENCODER_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/vector.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/vector.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/vector.h	(revision 453)
@@ -0,0 +1,49 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef VECTOR_H
+#define VECTOR_H
+
+#ifdef __cplusplus
+#include <cstddef>
+#else
+#include <stddef.h>
+#include <stdbool.h>
+#endif
+
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "umock_c/umock_c_prod.h"
+#include "azure_c_shared_utility/vector_types.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+MOCKABLE_INTERFACE(vector,
+    /* creation */
+    FUNCTION(, VECTOR_HANDLE, VECTOR_create, size_t, elementSize),
+    FUNCTION(, VECTOR_HANDLE, VECTOR_move, VECTOR_HANDLE, handle),
+    FUNCTION(, void, VECTOR_destroy, VECTOR_HANDLE, handle),
+
+    /* insertion */
+    FUNCTION(, int, VECTOR_push_back, VECTOR_HANDLE, handle, const void*, elements, size_t, numElements),
+
+    /* removal */
+    FUNCTION(, void, VECTOR_erase, VECTOR_HANDLE, handle, void*, elements, size_t, numElements),
+    FUNCTION(, void, VECTOR_clear, VECTOR_HANDLE, handle),
+
+    /* access */
+    FUNCTION(, void*, VECTOR_element, VECTOR_HANDLE, handle, size_t, index),
+    FUNCTION(, void*, VECTOR_front, VECTOR_HANDLE, handle),
+    FUNCTION(, void*, VECTOR_back, VECTOR_HANDLE, handle),
+    FUNCTION(, void*, VECTOR_find_if, VECTOR_HANDLE, handle, PREDICATE_FUNCTION, pred, const void*, value),
+
+    /* capacity */
+    FUNCTION(, size_t, VECTOR_size, VECTOR_HANDLE, handle)
+)
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* VECTOR_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/vector_types.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/vector_types.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/vector_types.h	(revision 453)
@@ -0,0 +1,25 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef VECTOR_TYPES_H
+#define VECTOR_TYPES_H
+
+#ifdef __cplusplus
+#else
+#include <stdbool.h>
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef struct VECTOR_TAG* VECTOR_HANDLE;
+
+typedef bool(*PREDICATE_FUNCTION)(const void* element, const void* value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* VECTOR_TYPES_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/vector_types_internal.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/vector_types_internal.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/vector_types_internal.h	(revision 453)
@@ -0,0 +1,29 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef VECTOR_TYPES_INTERNAL_H
+#define VECTOR_TYPES_INTERNAL_H
+
+#ifdef __cplusplus
+#include <cstddef>
+#else
+#include <stddef.h>
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    typedef struct VECTOR_TAG
+    {
+        void* storage;
+        size_t count;
+        size_t elementSize;
+    } VECTOR;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* VECTOR_TYPES_INTERNAL_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/wsio.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/wsio.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/wsio.h	(revision 453)
@@ -0,0 +1,38 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef WSIO_H
+#define WSIO_H
+
+#ifdef __cplusplus
+#include <cstddef>
+#else
+#include <stddef.h>
+#include <stdbool.h>
+#endif /* __cplusplus */
+
+#include "azure_c_shared_utility/xio.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct WSIO_CONFIG_TAG
+{
+    const IO_INTERFACE_DESCRIPTION* underlying_io_interface;
+    void* underlying_io_parameters;
+    const char* hostname;
+    int port;
+    const char* resource_name;
+    const char* protocol;
+} WSIO_CONFIG;
+
+MOCKABLE_FUNCTION(, const IO_INTERFACE_DESCRIPTION*, wsio_get_interface_description);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* WSIO_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/xio.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/xio.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/xio.h	(revision 453)
@@ -0,0 +1,80 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef XIO_H
+#define XIO_H
+
+#ifdef __cplusplus
+#include <cstddef>
+#else
+#include <stddef.h>
+#endif /* __cplusplus */
+
+#include "azure_c_shared_utility/optionhandler.h"
+
+#include "umock_c/umock_c_prod.h"
+#include "azure_macro_utils/macro_utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct XIO_INSTANCE_TAG* XIO_HANDLE;
+typedef void* CONCRETE_IO_HANDLE;
+
+#define IO_SEND_RESULT_VALUES \
+    IO_SEND_OK, \
+    IO_SEND_ERROR, \
+    IO_SEND_CANCELLED
+
+MU_DEFINE_ENUM(IO_SEND_RESULT, IO_SEND_RESULT_VALUES);
+
+#define IO_OPEN_RESULT_VALUES \
+    IO_OPEN_OK, \
+    IO_OPEN_ERROR, \
+    IO_OPEN_CANCELLED
+
+MU_DEFINE_ENUM(IO_OPEN_RESULT, IO_OPEN_RESULT_VALUES);
+
+typedef void(*ON_BYTES_RECEIVED)(void* context, const unsigned char* buffer, size_t size);
+typedef void(*ON_SEND_COMPLETE)(void* context, IO_SEND_RESULT send_result);
+typedef void(*ON_IO_OPEN_COMPLETE)(void* context, IO_OPEN_RESULT open_result);
+typedef void(*ON_IO_CLOSE_COMPLETE)(void* context);
+typedef void(*ON_IO_ERROR)(void* context);
+
+typedef OPTIONHANDLER_HANDLE (*IO_RETRIEVEOPTIONS)(CONCRETE_IO_HANDLE concrete_io);
+typedef CONCRETE_IO_HANDLE(*IO_CREATE)(void* io_create_parameters);
+typedef void(*IO_DESTROY)(CONCRETE_IO_HANDLE concrete_io);
+typedef int(*IO_OPEN)(CONCRETE_IO_HANDLE concrete_io, ON_IO_OPEN_COMPLETE on_io_open_complete, void* on_io_open_complete_context, ON_BYTES_RECEIVED on_bytes_received, void* on_bytes_received_context, ON_IO_ERROR on_io_error, void* on_io_error_context);
+typedef int(*IO_CLOSE)(CONCRETE_IO_HANDLE concrete_io, ON_IO_CLOSE_COMPLETE on_io_close_complete, void* callback_context);
+typedef int(*IO_SEND)(CONCRETE_IO_HANDLE concrete_io, const void* buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void* callback_context);
+typedef void(*IO_DOWORK)(CONCRETE_IO_HANDLE concrete_io);
+typedef int(*IO_SETOPTION)(CONCRETE_IO_HANDLE concrete_io, const char* optionName, const void* value);
+
+
+typedef struct IO_INTERFACE_DESCRIPTION_TAG
+{
+    IO_RETRIEVEOPTIONS concrete_io_retrieveoptions;
+    IO_CREATE concrete_io_create;
+    IO_DESTROY concrete_io_destroy;
+    IO_OPEN concrete_io_open;
+    IO_CLOSE concrete_io_close;
+    IO_SEND concrete_io_send;
+    IO_DOWORK concrete_io_dowork;
+    IO_SETOPTION concrete_io_setoption;
+} IO_INTERFACE_DESCRIPTION;
+
+MOCKABLE_FUNCTION(, XIO_HANDLE, xio_create, const IO_INTERFACE_DESCRIPTION*, io_interface_description, const void*, io_create_parameters);
+MOCKABLE_FUNCTION(, void, xio_destroy, XIO_HANDLE, xio);
+MOCKABLE_FUNCTION(, int, xio_open, XIO_HANDLE, xio, ON_IO_OPEN_COMPLETE, on_io_open_complete, void*, on_io_open_complete_context, ON_BYTES_RECEIVED, on_bytes_received, void*, on_bytes_received_context, ON_IO_ERROR, on_io_error, void*, on_io_error_context);
+MOCKABLE_FUNCTION(, int, xio_close, XIO_HANDLE, xio, ON_IO_CLOSE_COMPLETE, on_io_close_complete, void*, callback_context);
+MOCKABLE_FUNCTION(, int, xio_send, XIO_HANDLE, xio, const void*, buffer, size_t, size, ON_SEND_COMPLETE, on_send_complete, void*, callback_context);
+MOCKABLE_FUNCTION(, void, xio_dowork, XIO_HANDLE, xio);
+MOCKABLE_FUNCTION(, int, xio_setoption, XIO_HANDLE, xio, const char*, optionName, const void*, value);
+MOCKABLE_FUNCTION(, OPTIONHANDLER_HANDLE, xio_retrieveoptions, XIO_HANDLE, xio);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* XIO_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/xlogging.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/xlogging.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/xlogging.h	(revision 453)
@@ -0,0 +1,228 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef XLOGGING_H
+#define XLOGGING_H
+
+#ifdef __cplusplus
+#include <cstdlib>
+#else
+#include <stdlib.h>
+#endif
+
+#include "azure_macro_utils/macro_utils.h"
+
+#include "azure_c_shared_utility/agenttime.h"
+#include "azure_c_shared_utility/optimize_size.h"
+
+#ifdef LOGERROR_CAPTURES_STACK_TRACES
+#include "azure_c_shared_utility/logging_stacktrace.h"
+#endif
+
+#if defined(ESP8266_RTOS)
+#include "c_types.h"
+#endif
+
+#if defined(ARDUINO_ARCH_ESP8266)
+#include "esp8266/azcpgmspace.h"
+#endif
+
+#ifdef __cplusplus
+/* Some compilers do not want to play by the standard, specifically ARM CC */
+#ifdef MBED_BUILD_TIMESTAMP
+#include <stdio.h>
+#else
+#include <cstdio>
+#endif
+#else
+#include <stdio.h>
+#endif /* __cplusplus */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifdef TIZENRT
+#undef LOG_INFO
+#endif
+
+typedef enum LOG_CATEGORY_TAG
+{
+    AZ_LOG_ERROR,
+    AZ_LOG_INFO,
+    AZ_LOG_TRACE
+} LOG_CATEGORY;
+
+#if defined _MSC_VER
+#define FUNC_NAME __FUNCDNAME__
+#else
+#define FUNC_NAME __func__
+#endif
+
+typedef void(*LOGGER_LOG)(LOG_CATEGORY log_category, const char* file, const char* func, int line, unsigned int options, const char* format, ...);
+typedef void(*LOGGER_LOG_GETLASTERROR)(const char* file, const char* func, int line, const char* format, ...);
+
+#define TEMP_BUFFER_SIZE 1024
+#define MESSAGE_BUFFER_SIZE 260
+
+#define LOG_NONE 0x00
+#define LOG_LINE 0x01
+
+/*no logging is useful when time and fprintf are mocked*/
+#ifdef NO_LOGGING
+#define LOG(...)
+#define LogInfo(...)
+#define LogBinary(...)
+#define LogError(...)
+#define LogLastError(...)
+#define xlogging_get_log_function() NULL
+#define xlogging_set_log_function(...)
+#define LogErrorWinHTTPWithGetLastErrorAsString(...)
+#define UNUSED(x) (void)(x)
+#elif (defined MINIMAL_LOGERROR)
+#define LOG(...)
+#define LogInfo(...)
+#define LogBinary(...)
+#define LogError(...) printf("error %s: line %d\n",__FILE__,__LINE__);
+#define xlogging_get_log_function() NULL
+#define xlogging_set_log_function(...)
+#define LogErrorWinHTTPWithGetLastErrorAsString(...)
+#define UNUSED(x) (void)(x)
+
+#elif defined(ESP8266_RTOS)
+#define LogInfo(FORMAT, ...) do {    \
+        static const char flash_str[] ICACHE_RODATA_ATTR STORE_ATTR = FORMAT;  \
+        printf(flash_str, ##__VA_ARGS__);   \
+        printf("\n");\
+    } while((void)0,0)
+
+#define LogError LogInfo
+#define LOG(log_category, log_options, FORMAT, ...)  { \
+        static const char flash_str[] ICACHE_RODATA_ATTR STORE_ATTR = (FORMAT); \
+        printf(flash_str, ##__VA_ARGS__); \
+        printf("\r\n"); \
+}
+
+#else /* NOT ESP8266_RTOS */
+
+// In order to make sure that the compiler evaluates the arguments and issues an error if they do not conform to printf
+// specifications, we call printf with the format and __VA_ARGS__. Since C && operator is shortcircuiting no actual runtime call to printf is performed.
+#if defined _MSC_VER
+#ifndef LOGERROR_CAPTURES_STACK_TRACES
+// ignore warning C4127 
+#define LOG(log_category, log_options, format, ...) \
+{ \
+    (void)(0 && printf(format, __VA_ARGS__)); \
+    { \
+        LOGGER_LOG l = xlogging_get_log_function(); \
+        if (l != NULL) \
+        { \
+            l(log_category, __FILE__, FUNC_NAME, __LINE__, log_options, format, __VA_ARGS__); \
+        } \
+    } \
+}
+#else /*LOGERROR_CAPTURES_STACK_TRACES is defined*/ 
+#define STACK_PRINT_FORMAT "\nStack:\n%s"
+
+#define LOG(log_category, log_options, format, ...) MU_C3(LOG,_,log_category)(log_category, log_options, format, __VA_ARGS__)
+
+#define LOG_AZ_LOG_ERROR(log_category, log_options, format, ...)                                                                                                        \
+{                                                                                                                                                                       \
+    (void)(0 && printf(format, __VA_ARGS__));                                                                                                                           \
+    {                                                                                                                                                                   \
+        LOGGER_LOG l = xlogging_get_log_function();                                                                                                                     \
+        if (l != NULL)                                                                                                                                                  \
+        {                                                                                                                                                               \
+            char* stackAsString = getStackAsString();                                                                                                                   \
+            if (stackAsString == NULL)                                                                                                                                  \
+            {                                                                                                                                                           \
+                l(log_category, __FILE__, FUNC_NAME, __LINE__, log_options, format, __VA_ARGS__);                                                                       \
+            }                                                                                                                                                           \
+            else                                                                                                                                                        \
+            {                                                                                                                                                           \
+                size_t formatSize = strlen(format);                                                                                                                     \
+                char* formatWithStack = (char*)logging_malloc(formatSize + sizeof("STACK_PRINT_FORMAT"));                                                               \
+                if (formatWithStack == NULL)                                                                                                                            \
+                {                                                                                                                                                       \
+                    l(log_category, __FILE__, FUNC_NAME, __LINE__, log_options, format, __VA_ARGS__);                                                                   \
+                }                                                                                                                                                       \
+                else                                                                                                                                                    \
+                {                                                                                                                                                       \
+                    (void)memcpy(formatWithStack, format, formatSize);                                                                                                  \
+                    (void)memcpy(formatWithStack + formatSize, STACK_PRINT_FORMAT, sizeof(STACK_PRINT_FORMAT));                                                         \
+                    l(log_category, __FILE__, FUNC_NAME, __LINE__, log_options, formatWithStack, __VA_ARGS__, stackAsString);                                           \
+                    logging_free(formatWithStack);                                                                                                                      \
+                }                                                                                                                                                       \
+                logging_free(stackAsString);                                                                                                                            \
+            }                                                                                                                                                           \
+        }                                                                                                                                                               \
+    }                                                                                                                                                                   \
+}
+
+#define LOG_AZ_LOG_TRACE LOG_AZ_LOG_INFO
+
+#define LOG_AZ_LOG_INFO(log_category, log_options, format, ...)                                                                                                         \
+{                                                                                                                                                                       \
+    (void)(0 && printf(format, __VA_ARGS__));                                                                                                                           \
+    {                                                                                                                                                                   \
+        LOGGER_LOG l = xlogging_get_log_function();                                                                                                                     \
+        if (l != NULL)                                                                                                                                                  \
+        {                                                                                                                                                               \
+            l(log_category, __FILE__, FUNC_NAME, __LINE__, log_options, format, __VA_ARGS__);                                                                           \
+        }                                                                                                                                                               \
+    }                                                                                                                                                                   \
+}
+
+#endif /*LOGERROR_CAPTURES_STACK_TRACES*/
+#else
+#define LOG(log_category, log_options, format, ...) { (void)(0 && printf(format, ##__VA_ARGS__)); { LOGGER_LOG l = xlogging_get_log_function(); if (l != NULL) l(log_category, __FILE__, FUNC_NAME, __LINE__, log_options, format, ##__VA_ARGS__); } }
+#endif
+
+#if defined _MSC_VER
+#define LogInfo(FORMAT, ...) do{LOG(AZ_LOG_INFO, LOG_LINE, FORMAT, __VA_ARGS__); }while((void)0,0)
+#else
+#define LogInfo(FORMAT, ...) do{LOG(AZ_LOG_INFO, LOG_LINE, FORMAT, ##__VA_ARGS__); }while((void)0,0)
+#endif
+
+#ifdef WIN32
+extern void xlogging_LogErrorWinHTTPWithGetLastErrorAsStringFormatter(int errorMessageID);
+#endif
+
+#if defined _MSC_VER
+
+extern void xlogging_set_log_function_GetLastError(LOGGER_LOG_GETLASTERROR log_function);
+extern LOGGER_LOG_GETLASTERROR xlogging_get_log_function_GetLastError(void);
+#define LogLastError(FORMAT, ...) do{ LOGGER_LOG_GETLASTERROR l = xlogging_get_log_function_GetLastError(); if(l!=NULL) l(__FILE__, FUNC_NAME, __LINE__, FORMAT, __VA_ARGS__); }while((void)0,0)
+
+#define LogError(FORMAT, ...) do{ LOG(AZ_LOG_ERROR, LOG_LINE, FORMAT, __VA_ARGS__); }while((void)0,0)
+#define LogErrorWinHTTPWithGetLastErrorAsString(FORMAT, ...) do { \
+                int errorMessageID = GetLastError(); \
+                LogError(FORMAT, __VA_ARGS__); \
+                xlogging_LogErrorWinHTTPWithGetLastErrorAsStringFormatter(errorMessageID); \
+            } while((void)0,0)
+#else // _MSC_VER
+#define LogError(FORMAT, ...) do{ LOG(AZ_LOG_ERROR, LOG_LINE, FORMAT, ##__VA_ARGS__); }while((void)0,0)
+
+#ifdef WIN32
+// Included when compiling on Windows but not with MSVC, e.g. with MinGW.
+#define LogErrorWinHTTPWithGetLastErrorAsString(FORMAT, ...) do { \
+                int errorMessageID = GetLastError(); \
+                LogError(FORMAT, ##__VA_ARGS__); \
+                xlogging_LogErrorWinHTTPWithGetLastErrorAsStringFormatter(errorMessageID); \
+            } while((void)0,0)
+#endif // WIN32
+
+#endif // _MSC_VER
+
+extern void LogBinary(const char* comment, const void* data, size_t size);
+
+extern void xlogging_set_log_function(LOGGER_LOG log_function);
+extern LOGGER_LOG xlogging_get_log_function(void);
+
+#endif /* NOT ESP8266_RTOS */
+
+#ifdef __cplusplus
+}   // extern "C"
+#endif /* __cplusplus */
+
+#endif /* XLOGGING_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/pal/toppers/refcount_os.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/pal/toppers/refcount_os.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/pal/toppers/refcount_os.h	(revision 453)
@@ -0,0 +1,21 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+// This file gets included into refcount.h as a means of extending the behavior of
+// atomic increment, decrement, and test.
+//
+// The Azure IoT C SDK does not require thread-safe refcount operations, so
+// this file is appropriate for any device when using the Azure IoT C SDK.
+
+#ifndef REFCOUNT_OS_H__GENERIC
+#define REFCOUNT_OS_H__GENERIC
+
+#define COUNT_TYPE uint32_t
+
+#define DEC_RETURN_ZERO (0)
+
+#define INC_REF_VAR(count) ++(count)
+#define DEC_REF_VAR(count) --(count)
+#define INIT_REF_VAR(count) do { count = 1; } while((void)0,0)
+
+#endif // REFCOUNT_OS_H__GENERIC
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/pal/toppers/socket_async_os.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/pal/toppers/socket_async_os.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/pal/toppers/socket_async_os.h	(revision 453)
@@ -0,0 +1,14 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+//This file pulls in OS-specific header files to allow compilation of socket_async.c under
+// most OS's except for Windows.
+
+// For Linux systems
+#include <sys/types.h>
+//#include <lwip/sockets.h>
+#include <sys/select.h>
+#include <sys/errno.h>
+#include <unistd.h>
+//#include <netdb.h>
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/azure_base32.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/azure_base32.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/azure_base32.c	(revision 453)
@@ -0,0 +1,397 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <ctype.h>
+#include "azure_c_shared_utility/buffer_.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/strings.h"
+
+#include "azure_c_shared_utility/azure_base32.h"
+
+static const unsigned char BASE32_EQUAL_SIGN = 32;
+
+static const char BASE32_VALUES[] = "abcdefghijklmnopqrstuvwxyz234567=";
+#define TARGET_BLOCK_SIZE       5
+#define INVALID_CHAR_POS        260
+
+#define BASE32_INPUT_SIZE       8
+
+#define ASCII_VALUE_MAX         0x80
+
+static size_t base32_encoding_length(size_t src_len)
+{
+    return (((src_len + TARGET_BLOCK_SIZE - 1) / TARGET_BLOCK_SIZE) * 8);
+}
+
+static size_t base32_decoding_length(size_t src_len)
+{
+    return ((src_len*TARGET_BLOCK_SIZE) / 8);
+}
+
+static unsigned char convert_value_to_base32_char(unsigned char value)
+{
+    unsigned char result;
+
+    if (value >= 50 && value <= 55)
+    {
+        result = 0x1a+(value-50);
+    }
+    else if (value == 61)
+    {
+        result = 0x20;
+    }
+    else if ((value <= 49) || (value >= 56 && value <= 64))
+    {
+        result = 0xFF;
+    }
+    else if (value >= 65 && value <= 90)
+    {
+        result = 0x00 + (value - 65);
+    }
+    else if (value >= 91 && value <= 96)
+    {
+        result = 0xFF;
+    }
+    else if (value >= 97 && value <= 123)
+    {
+        result = 0x00 + (value - 97);
+    }
+    else // value > 123
+    {
+        result = 0xFF;
+    }
+    return result;
+}
+
+static char* base32_encode_impl(const unsigned char* source, size_t src_size)
+{
+    char* result;
+
+    // Allocate target buffer
+    size_t output_len = base32_encoding_length(src_size);
+    /* Codes_SRS_BASE32_07_009: [ base32_encode_impl shall allocate the buffer to the size of the encoding value. ] */
+    if ((result = (char*)malloc(output_len + 1)) == NULL)
+    {
+        LogError("Failure allocating output buffer");
+    }
+    else
+    {
+        const unsigned char* iterator = source;
+        size_t block_len = 0;
+        size_t result_len = 0;
+        unsigned char pos1 = 0;
+        unsigned char pos2 = 0;
+        unsigned char pos3 = 0;
+        unsigned char pos4 = 0;
+        unsigned char pos5 = 0;
+        unsigned char pos6 = 0;
+        unsigned char pos7 = 0;
+        unsigned char pos8 = 0;
+
+        memset(result, 0, output_len + 1);
+
+        // Go through the source buffer sectioning off blocks of 5
+        /* Codes_SRS_BASE32_07_010: [ base32_encode_impl shall look through source and separate each block into 5 bit chunks ] */
+        while (src_size >= 1 && result != NULL)
+        {
+            pos1 = pos2 = pos3 = pos4 = pos5 = pos6 = pos7 = pos8 = 0;
+            block_len = src_size > TARGET_BLOCK_SIZE ? TARGET_BLOCK_SIZE : src_size;
+            // Fall through switch block to process the 5 (or smaller) block
+            switch (block_len)
+            {
+            case 5:
+                pos8 = (iterator[4] & 0x1f);
+                pos7 = ((iterator[4] & 0xe0) >> 5);
+                // fall through
+            case 4:
+                pos7 |= ((iterator[3] & 0x03) << 3);
+                pos6 = ((iterator[3] & 0x7c) >> 2);
+                pos5 = ((iterator[3] & 0x80) >> 7);
+                // fall through
+            case 3:
+                pos5 |= ((iterator[2] & 0x0f) << 1);
+                pos4 = ((iterator[2] & 0xf0) >> 4);
+                // fall through
+            case 2:
+                pos4 |= ((iterator[1] & 0x01) << 4);
+                pos3 = ((iterator[1] & 0x3e) >> 1);
+                pos2 = ((iterator[1] & 0xc0) >> 6);
+                // fall through
+            case 1:
+                pos2 |= ((iterator[0] & 0x07) << 2);
+                pos1 = ((iterator[0] & 0xf8) >> 3);
+                break;
+            }
+            // Move the iterator the block size
+            iterator += block_len;
+            // and decrement the src_size;
+            src_size -= block_len;
+
+            /* Codes_SRS_BASE32_07_012: [ If the src_size is not divisible by 8, base32_encode_impl shall pad the remaining places with =. ] */
+            switch (block_len)
+            {
+                case 1: pos3 = pos4 = 32; // fall through
+                case 2: pos5 = 32; // fall through
+                case 3: pos6 = pos7 = 32; // fall through
+                case 4: pos8 = 32; // fall through
+                case 5:
+                    break;
+            }
+
+            /* Codes_SRS_BASE32_07_011: [ base32_encode_impl shall then map the 5 bit chunks into one of the BASE32 values (a-z,2,3,4,5,6,7) values. ] */
+            result[result_len++] = BASE32_VALUES[pos1];
+            result[result_len++] = BASE32_VALUES[pos2];
+            result[result_len++] = BASE32_VALUES[pos3];
+            result[result_len++] = BASE32_VALUES[pos4];
+            result[result_len++] = BASE32_VALUES[pos5];
+            result[result_len++] = BASE32_VALUES[pos6];
+            result[result_len++] = BASE32_VALUES[pos7];
+            result[result_len++] = BASE32_VALUES[pos8];
+        }
+    }
+    return result;
+}
+
+static BUFFER_HANDLE base32_decode_impl(const char* source)
+{
+    BUFFER_HANDLE result;
+
+    size_t src_length = strlen(source);
+    if (src_length % BASE32_INPUT_SIZE != 0)
+    {
+        /* Codes_SRS_BASE32_07_021: [ If the source length is not evenly divisible by 8, base32_decode_impl shall return NULL. ] */
+        LogError("Failure invalid input length %lu", (unsigned long)src_length);
+        result = NULL;
+    }
+    else
+    {
+        size_t dest_size = 0;
+        unsigned char* temp_buffer;
+        unsigned char* dest_buff;
+        bool continue_processing = true;
+        unsigned char input[8];
+        const char* iterator = source;
+
+        /* Codes_SRS_BASE32_07_022: [ base32_decode_impl shall allocate a temp buffer to store the in process value. ] */
+        size_t allocation_len = base32_decoding_length(src_length);
+        if ((temp_buffer = (unsigned char*)malloc(allocation_len)) == NULL)
+        {
+            /* Codes_SRS_BASE32_07_023: [ If an error is encountered, base32_decode_impl shall return NULL. ] */
+            LogError("Failure allocating buffer");
+            result = NULL;
+        }
+        else
+        {
+            dest_buff = temp_buffer;
+            while (*iterator != '\0')
+            {
+                size_t index = 0;
+                /* Codes_SRS_BASE32_07_024: [ base32_decode_impl shall loop through and collect 8 characters from the source variable. ] */
+                for (index = 0; index < BASE32_INPUT_SIZE; index++)
+                {
+                    input[index] = *iterator;
+                    iterator++;
+                    if (input[index] >= ASCII_VALUE_MAX)
+                    {
+                        LogError("Failure source encoding");
+                        continue_processing = false;
+                        break;
+                    }
+
+                    input[index] = convert_value_to_base32_char(input[index]);
+                }
+
+                if (!continue_processing)
+                {
+                    result = NULL;
+                    break;
+                }
+                else if ((dest_size + TARGET_BLOCK_SIZE) > allocation_len)
+                {
+                    LogError("Failure target length exceeded");
+                    result = NULL;
+                    continue_processing = false;
+                    break;
+                }
+                else
+                {
+                    // Codes_SRS_BASE32_07_025: [ base32_decode_impl shall group 5 bytes at a time into the temp buffer. ]
+                    *dest_buff++ = ((input[0] & 0x1f) << 3) | ((input[1] & 0x1c) >> 2);
+                    *dest_buff++ = ((input[1] & 0x03) << 6) | ((input[2] & 0x1f) << 1) | ((input[3] & 0x10) >> 4);
+                    *dest_buff++ = ((input[3] & 0x0f) << 4) | ((input[4] & 0x1e) >> 1);
+                    *dest_buff++ = ((input[4] & 0x01) << 7) | ((input[5] & 0x1f) << 2) | ((input[6] & 0x18) >> 3);
+                    *dest_buff++ = ((input[6] & 0x07) << 5) | (input[7] & 0x1f);
+                    dest_size += TARGET_BLOCK_SIZE;
+                    // If there is padding remove it
+                    // Because we are packing 5 bytes into an 8 byte variable we need to check every other
+                    // variable for padding
+                    if (input[7] == BASE32_EQUAL_SIGN)
+                    {
+                        --dest_size;
+                        if (input[5] == BASE32_EQUAL_SIGN)
+                        {
+                            --dest_size;
+                            if (input[4] == BASE32_EQUAL_SIGN)
+                            {
+                                --dest_size;
+                                if (input[2] == BASE32_EQUAL_SIGN)
+                                {
+                                    --dest_size;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            if (!continue_processing)
+            {
+                result = NULL;
+            }
+            else
+            {
+                /* Codes_SRS_BASE32_07_026: [ Once base32_decode_impl is complete it shall create a BUFFER with the temp buffer. ] */
+                result = BUFFER_create(temp_buffer, dest_size);
+                if (result == NULL)
+                {
+                    LogError("Failure: BUFFER_create failed to create decoded buffer");
+                }
+            }
+            free(temp_buffer);
+        }
+    }
+    return result;
+}
+
+BUFFER_HANDLE Azure_Base32_Decode(STRING_HANDLE handle)
+{
+    BUFFER_HANDLE result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_BASE32_07_016: [ If source is NULL Azure_Base32_Decode shall return NULL. ] */
+        LogError("invalid parameter handle");
+        result = NULL;
+    }
+    else
+    {
+        const char* str_source = STRING_c_str(handle);
+        if (str_source == NULL)
+        {
+            /* Codes_SRS_BASE32_07_027: [ If the string in source value is NULL, Azure_Base32_Decode shall return NULL. ] */
+            LogError("NULL value specified in string");
+            result = NULL;
+        }
+        else
+        {
+            /* Codes_SRS_BASE32_07_018: [ Azure_Base32_Decode shall call base32_decode_impl to decode the base64 value. ] */
+            result = base32_decode_impl(str_source);
+        }
+    }
+    /* Codes_SRS_BASE32_07_017: [ On success Azure_Base32_Decode shall return a BUFFER_HANDLE that contains the decoded bytes for source. ] */
+    return result;
+}
+
+BUFFER_HANDLE Azure_Base32_Decode_String(const char* source)
+{
+    BUFFER_HANDLE result;
+    if (source == NULL)
+    {
+        /* Codes_SRS_BASE32_07_008: [ If source is NULL Azure_Base32_Decode_String shall return NULL. ] */
+        LogError("invalid parameter source=NULL");
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_BASE32_07_020: [ Azure_Base32_Decode_String shall call base32_decode_impl to decode the base64 value. ] */
+        result = base32_decode_impl(source);
+    }
+    /* Codes_SRS_BASE32_07_019: [ On success Azure_Base32_Decode_String shall return a BUFFER_HANDLE that contains the decoded bytes for source. ] */
+    return result;
+}
+
+char* Azure_Base32_Encode_Bytes(const unsigned char* source, size_t size)
+{
+    char* result;
+    if (source == NULL)
+    {
+        /* Codes_SRS_BASE32_07_004: [ If source is NULL Azure_Base32_Encode_Bytes shall return NULL. ] */
+        result = NULL;
+        LogError("Failure: Invalid input parameter source");
+    }
+    else if (size == 0)
+    {
+        /* Codes_SRS_BASE32_07_005: [ If size is 0 Azure_Base32_Encode_Bytes shall return an empty string. ] */
+        if ((result = malloc(1)) != NULL)
+        {
+            strcpy(result, "");
+        }
+        else
+        {
+            LogError("unable to allocate memory for result");
+        }
+    }
+    else
+    {
+        /* Codes_SRS_BASE32_07_007: [ Azure_Base32_Encode_Bytes shall call into base32_Encode_impl to encode the source data. ] */
+        result = base32_encode_impl(source, size);
+        if (result == NULL)
+        {
+            /* Codes_SRS_BASE32_07_014: [ Upon failure Azure_Base32_Encode_Bytes shall return NULL. ] */
+            LogError("encoding of unsigned char failed.");
+        }
+    }
+    /* Codes_SRS_BASE32_07_006: [ If successful Azure_Base32_Encode_Bytes shall return the base32 value of input. ] */
+    return result;
+}
+
+STRING_HANDLE Azure_Base32_Encode(BUFFER_HANDLE source)
+{
+    STRING_HANDLE result;
+    if (source == NULL)
+    {
+        /* Codes_SRS_BASE32_07_001: [ If source is NULL Azure_Base32_Encode shall return NULL. ] */
+        result = NULL;
+        LogError("Failure: Invalid input parameter");
+    }
+    else
+    {
+        size_t input_len = BUFFER_length(source);
+        const unsigned char* input_value = BUFFER_u_char(source);
+        if (input_value == NULL || input_len == 0)
+        {
+            /* Codes_SRS_BASE32_07_015: [ If size is 0 Azure_Base32_Encode shall return an empty string. ] */
+            result = STRING_new();
+            if (result == NULL)
+            {
+                LogError("Failure constructing new string.");
+            }
+        }
+        else
+        {
+            /* Codes_SRS_BASE32_07_003: [ Azure_Base32_Encode shall call into base32_Encode_impl to encode the source data. ] */
+            char* encoded = base32_encode_impl(input_value, input_len);
+            if (encoded == NULL)
+            {
+                /* Codes_SRS_BASE32_07_014: [ Upon failure Azure_Base32_Encode shall return NULL. ] */
+                LogError("base32 encode implementation failed.");
+                result = NULL;
+            }
+            else
+            {
+                /* Codes_SRS_BASE32_07_012: [ Azure_Base32_Encode shall wrap the base32_Encode_impl result into a STRING_HANDLE. ] */
+                result = STRING_construct(encoded);
+                if (result == NULL)
+                {
+                    /* Codes_SRS_BASE32_07_014: [ Upon failure Azure_Base32_Encode shall return NULL. ] */
+                    LogError("string construction failed.");
+                }
+                free(encoded);
+            }
+        }
+    }
+    /* Codes_SRS_BASE32_07_002: [ If successful Azure_Base32_Encode shall return the base32 value of source. ] */
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/azure_base64.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/azure_base64.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/azure_base64.c	(revision 453)
@@ -0,0 +1,367 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <stdint.h>
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/azure_base64.h"
+#include "azure_c_shared_utility/xlogging.h"
+
+
+#define splitInt(intVal, bytePos)   (char)((intVal >> (bytePos << 3)) & 0xFF)
+#define joinChars(a, b, c, d) (uint32_t)((uint32_t)a + ((uint32_t)b << 8) + ((uint32_t)c << 16) + ((uint32_t)d << 24))
+
+static char base64char(unsigned char val)
+{
+    char result;
+
+    if (val < 26)
+    {
+        result = 'A' + (char)val;
+    }
+    else if (val < 52)
+    {
+        result = 'a' + ((char)val - 26);
+    }
+    else if (val < 62)
+    {
+        result = '0' + ((char)val - 52);
+    }
+    else if (val == 62)
+    {
+        result = '+';
+    }
+    else
+    {
+        result = '/';
+    }
+
+    return result;
+}
+
+static char base64b16(unsigned char val)
+{
+    const uint32_t base64b16values[4] = {
+        joinChars('A', 'E', 'I', 'M'),
+        joinChars('Q', 'U', 'Y', 'c'),
+        joinChars('g', 'k', 'o', 's'),
+        joinChars('w', '0', '4', '8')
+    };
+    return splitInt(base64b16values[val >> 2], (val & 0x03));
+}
+
+static char base64b8(unsigned char val)
+{
+    const uint32_t base64b8values = joinChars('A', 'Q', 'g', 'w');
+    return splitInt(base64b8values, val);
+}
+
+static int base64toValue(char base64character, unsigned char* value)
+{
+    int result = 0;
+    if (('A' <= base64character) && (base64character <= 'Z'))
+    {
+        *value = base64character - 'A';
+    }
+    else if (('a' <= base64character) && (base64character <= 'z'))
+    {
+        *value = ('Z' - 'A') + 1 + (base64character - 'a');
+    }
+    else if (('0' <= base64character) && (base64character <= '9'))
+    {
+        *value = ('Z' - 'A') + 1 + ('z' - 'a') + 1 + (base64character - '0');
+    }
+    else if ('+' == base64character)
+    {
+        *value = 62;
+    }
+    else if ('/' == base64character)
+    {
+        *value = 63;
+    }
+    else
+    {
+        *value = 0;
+        result = -1;
+    }
+    return result;
+}
+
+static size_t numberOfBase64Characters(const char* encodedString)
+{
+    size_t length = 0;
+    unsigned char junkChar;
+    while (base64toValue(encodedString[length],&junkChar) != -1)
+    {
+        length++;
+    }
+    return length;
+}
+
+/*returns the count of original bytes before being base64 encoded*/
+/*notice NO validation of the content of encodedString. Its length is validated to be a multiple of 4.*/
+static size_t Base64decode_len(const char *encodedString)
+{
+    size_t result;
+    size_t sourceLength = strlen(encodedString);
+
+    if (sourceLength == 0)
+    {
+        result = 0;
+    }
+    else
+    {
+        result = sourceLength / 4 * 3;
+        if (encodedString[sourceLength - 1] == '=')
+        {
+            if (encodedString[sourceLength - 2] == '=')
+            {
+                result --;
+            }
+            result--;
+        }
+    }
+    return result;
+}
+
+static void Base64decode(unsigned char *decodedString, const char *base64String)
+{
+
+    size_t numberOfEncodedChars;
+    size_t indexOfFirstEncodedChar;
+    size_t decodedIndex;
+
+    //
+    // We can only operate on individual bytes.  If we attempt to work
+    // on anything larger we could get an alignment fault on some
+    // architectures
+    //
+
+    numberOfEncodedChars = numberOfBase64Characters(base64String);
+    indexOfFirstEncodedChar = 0;
+    decodedIndex = 0;
+    while (numberOfEncodedChars >= 4)
+    {
+        unsigned char c1;
+        unsigned char c2;
+        unsigned char c3;
+        unsigned char c4;
+        (void)base64toValue(base64String[indexOfFirstEncodedChar], &c1);
+        (void)base64toValue(base64String[indexOfFirstEncodedChar + 1], &c2);
+        (void)base64toValue(base64String[indexOfFirstEncodedChar + 2], &c3);
+        (void)base64toValue(base64String[indexOfFirstEncodedChar + 3], &c4);
+        decodedString[decodedIndex] = (c1 << 2) | (c2 >> 4);
+        decodedIndex++;
+        decodedString[decodedIndex] = ((c2 & 0x0f) << 4) | (c3 >> 2);
+        decodedIndex++;
+        decodedString[decodedIndex] = ((c3 & 0x03) << 6) | c4;
+        decodedIndex++;
+        numberOfEncodedChars -= 4;
+        indexOfFirstEncodedChar += 4;
+
+    }
+
+    if (numberOfEncodedChars == 2)
+    {
+        unsigned char c1;
+        unsigned char c2;
+        (void)base64toValue(base64String[indexOfFirstEncodedChar], &c1);
+        (void)base64toValue(base64String[indexOfFirstEncodedChar + 1], &c2);
+        decodedString[decodedIndex] = (c1 << 2) | (c2 >> 4);
+    }
+    else if (numberOfEncodedChars == 3)
+    {
+        unsigned char c1;
+        unsigned char c2;
+        unsigned char c3;
+        (void)base64toValue(base64String[indexOfFirstEncodedChar], &c1);
+        (void)base64toValue(base64String[indexOfFirstEncodedChar + 1], &c2);
+        (void)base64toValue(base64String[indexOfFirstEncodedChar + 2], &c3);
+        decodedString[decodedIndex] = (c1 << 2) | (c2 >> 4);
+        decodedIndex++;
+        decodedString[decodedIndex] = ((c2 & 0x0f) << 4) | (c3 >> 2);
+    }
+}
+
+BUFFER_HANDLE Azure_Base64_Decode(const char* source)
+{
+    BUFFER_HANDLE result;
+    /*Codes_SRS_BASE64_06_008: [If source is NULL then Azure_Base64_Decode shall return NULL.]*/
+    if (source == NULL)
+    {
+        LogError("invalid parameter const char* source=%p", source);
+        result = NULL;
+    }
+    else
+    {
+        if ((strlen(source) % 4) != 0)
+        {
+            /*Codes_SRS_BASE64_06_011: [If the source string has an invalid length for a base 64 encoded string then Azure_Base64_Decode shall return NULL.]*/
+            LogError("Invalid length Base64 string!");
+            result = NULL;
+        }
+        else
+        {
+            if ((result = BUFFER_new()) == NULL)
+            {
+                /*Codes_SRS_BASE64_06_010: [If there is any memory allocation failure during the decode then Azure_Base64_Decode shall return NULL.]*/
+                LogError("Could not create a buffer to decoding.");
+            }
+            else
+            {
+                size_t sizeOfOutputBuffer = Base64decode_len(source);
+                /*Codes_SRS_BASE64_06_009: [If the string pointed to by source is zero length then the handle returned shall refer to a zero length buffer.]*/
+                if (sizeOfOutputBuffer > 0)
+                {
+                    if (BUFFER_pre_build(result, sizeOfOutputBuffer) != 0)
+                    {
+                        /*Codes_SRS_BASE64_06_010: [If there is any memory allocation failure during the decode then Azure_Base64_Decode shall return NULL.]*/
+                        LogError("Could not prebuild a buffer for base 64 decoding.");
+                        BUFFER_delete(result);
+                        result = NULL;
+                    }
+                    else
+                    {
+                        Base64decode(BUFFER_u_char(result), source);
+                    }
+                }
+            }
+        }
+    }
+    return result;
+}
+
+
+static STRING_HANDLE Base64_Encode_Internal(const unsigned char* source, size_t size)
+{
+    STRING_HANDLE result;
+    size_t neededSize = 0;
+    char* encoded;
+    size_t currentPosition = 0;
+    neededSize += (size == 0) ? (0) : ((((size - 1) / 3) + 1) * 4);
+    neededSize += 1; /*+1 because \0 at the end of the string*/
+    /*Codes_SRS_BASE64_06_006: [If when allocating memory to produce the encoding a failure occurs then Azure_Base64_Encode shall return NULL.]*/
+    encoded = (char*)malloc(neededSize);
+    if (encoded == NULL)
+    {
+        result = NULL;
+        LogError("Azure_Base64_Encode:: Allocation failed.");
+    }
+    else
+    {
+        /*b0            b1(+1)          b2(+2)
+        7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
+        |----c1---| |----c2---| |----c3---| |----c4---|
+        */
+
+        size_t destinationPosition = 0;
+        while (size - currentPosition >= 3)
+        {
+            char c1 = base64char(source[currentPosition] >> 2);
+            char c2 = base64char(
+                ((source[currentPosition] & 3) << 4) |
+                    (source[currentPosition + 1] >> 4)
+            );
+            char c3 = base64char(
+                ((source[currentPosition + 1] & 0x0F) << 2) |
+                    ((source[currentPosition + 2] >> 6) & 3)
+            );
+            char c4 = base64char(
+                source[currentPosition + 2] & 0x3F
+            );
+            currentPosition += 3;
+            encoded[destinationPosition++] = c1;
+            encoded[destinationPosition++] = c2;
+            encoded[destinationPosition++] = c3;
+            encoded[destinationPosition++] = c4;
+
+        }
+        if (size - currentPosition == 2)
+        {
+            char c1 = base64char(source[currentPosition] >> 2);
+            char c2 = base64char(
+                ((source[currentPosition] & 0x03) << 4) |
+                    (source[currentPosition + 1] >> 4)
+            );
+            char c3 = base64b16(source[currentPosition + 1] & 0x0F);
+            encoded[destinationPosition++] = c1;
+            encoded[destinationPosition++] = c2;
+            encoded[destinationPosition++] = c3;
+            encoded[destinationPosition++] = '=';
+        }
+        else if (size - currentPosition == 1)
+        {
+            char c1 = base64char(source[currentPosition] >> 2);
+            char c2 = base64b8(source[currentPosition] & 0x03);
+            encoded[destinationPosition++] = c1;
+            encoded[destinationPosition++] = c2;
+            encoded[destinationPosition++] = '=';
+            encoded[destinationPosition++] = '=';
+        }
+
+        /*null terminating the string*/
+        encoded[destinationPosition] = '\0';
+        /*Codes_SRS_BASE64_06_007: [Otherwise Azure_Base64_Encode shall return a pointer to STRING, that string contains the base 64 encoding of input.]*/
+        result = STRING_new_with_memory(encoded);
+        if (result == NULL)
+        {
+            free(encoded);
+            LogError("Azure_Base64_Encode:: Allocation failed for return value.");
+        }
+    }
+    return result;
+}
+
+STRING_HANDLE Azure_Base64_Encode_Bytes(const unsigned char* source, size_t size)
+{
+    STRING_HANDLE result;
+    /*Codes_SRS_BASE64_02_001: [If source is NULL then Azure_Base64_Encode_Bytes shall return NULL.] */
+    if (source == NULL)
+    {
+        result = NULL;
+    }
+    /*Codes_SRS_BASE64_02_002: [If source is not NULL and size is zero, then Azure_Base64_Encode_Bytes shall produce an empty STRING_HANDLE.] */
+    else if (size == 0)
+    {
+        result = STRING_new(); /*empty string*/
+    }
+    else
+    {
+        result = Base64_Encode_Internal(source, size);
+    }
+    return result;
+}
+
+STRING_HANDLE Azure_Base64_Encode(BUFFER_HANDLE input)
+{
+    STRING_HANDLE result;
+    /*the following will happen*/
+    /*1. the "data" of the binary shall be "eaten" 3 characters at a time and produce 4 base64 encoded characters for as long as there are more than 3 characters still to process*/
+    /*2. the remaining characters (1 or 2) shall be encoded.*/
+    /*there's a level of assumption that 'a' corresponds to 0b000000 and that '_' corresponds to 0b111111*/
+    /*the encoding will use the optional [=] or [==] at the end of the encoded string, so that other less standard aware libraries can do their work*/
+    /*these are the bits of the 3 normal bytes to be encoded*/
+
+    /*Codes_SRS_BASE64_06_001: [If input is NULL then Azure_Base64_Encode shall return NULL.]*/
+    if (input == NULL)
+    {
+        result = NULL;
+        LogError("Azure_Base64_Encode:: NULL input");
+    }
+    else
+    {
+        size_t inputSize;
+        const unsigned char* inputBinary;
+        if ((BUFFER_content(input, &inputBinary) != 0) ||
+            (BUFFER_size(input, &inputSize) != 0))
+        {
+            result = NULL;
+            LogError("Azure_Base64_Encode:: BUFFER_routines failure.");
+        }
+        else
+        {
+            result = Base64_Encode_Internal(inputBinary, inputSize);
+        }
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/buffer.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/buffer.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/buffer.c	(revision 453)
@@ -0,0 +1,667 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/buffer_.h"
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/xlogging.h"
+
+typedef struct BUFFER_TAG
+{
+    unsigned char* buffer;
+    size_t size;
+} BUFFER;
+
+/* Codes_SRS_BUFFER_07_001: [BUFFER_new shall allocate a BUFFER_HANDLE that will contain a NULL unsigned char*.] */
+BUFFER_HANDLE BUFFER_new(void)
+{
+    BUFFER* temp = (BUFFER*)calloc(1, sizeof(BUFFER));
+    /* Codes_SRS_BUFFER_07_002: [BUFFER_new shall return NULL on any error that occurs.] */
+    if (temp != NULL)
+    {
+        temp->buffer = NULL;
+        temp->size = 0;
+    }
+    return (BUFFER_HANDLE)temp;
+}
+
+static int BUFFER_safemalloc(BUFFER* handleptr, size_t size)
+{
+    int result;
+    size_t sizetomalloc = size;
+    if (size == 0)
+    {
+        sizetomalloc = 1;
+    }
+    handleptr->buffer = (unsigned char*)malloc(sizetomalloc);
+    if (handleptr->buffer == NULL)
+    {
+        /*Codes_SRS_BUFFER_02_003: [If allocating memory fails, then BUFFER_create shall return NULL.]*/
+        LogError("Failure allocating data");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        // we still consider the real buffer size is 0
+        handleptr->size = size;
+        result = 0;
+    }
+    return result;
+}
+
+BUFFER_HANDLE BUFFER_create(const unsigned char* source, size_t size)
+{
+    BUFFER* result;
+    /*Codes_SRS_BUFFER_02_001: [If source is NULL then BUFFER_create shall return NULL.]*/
+    if (source == NULL)
+    {
+        LogError("invalid parameter source: %p", source);
+        result = NULL;
+    }
+    else
+    {
+        /*Codes_SRS_BUFFER_02_002: [Otherwise, BUFFER_create shall allocate memory to hold size bytes and shall copy from source size bytes into the newly allocated memory.] */
+        result = (BUFFER*)calloc(1, sizeof(BUFFER));
+        if (result == NULL)
+        {
+            /*Codes_SRS_BUFFER_02_003: [If allocating memory fails, then BUFFER_create shall return NULL.] */
+            /*fallthrough*/
+            LogError("Failure allocating BUFFER structure");
+        }
+        else
+        {
+            /* Codes_SRS_BUFFER_02_005: [If size parameter is 0 then 1 byte of memory shall be allocated yet size of the buffer shall be set to 0.]*/
+            if (BUFFER_safemalloc(result, size) != 0)
+            {
+                LogError("unable to BUFFER_safemalloc ");
+                free(result);
+                result = NULL;
+            }
+            else
+            {
+                /*Codes_SRS_BUFFER_02_004: [Otherwise, BUFFER_create shall return a non-NULL handle.] */
+                (void)memcpy(result->buffer, source, size);
+            }
+        }
+    }
+    return (BUFFER_HANDLE)result;
+}
+
+// Codes_SRS_BUFFER_07_029: [ BUFFER_create_with_size shall create a BUFFER_HANDLE with a pre allocated underlying buffer size.]
+BUFFER_HANDLE BUFFER_create_with_size(size_t buff_size)
+{
+    BUFFER* result;
+    result = (BUFFER*)calloc(1, sizeof(BUFFER));
+    if (result != NULL)
+    {
+        if (buff_size == 0)
+        {
+            // Codes_SRS_BUFFER_07_030: [ If buff_size is 0 BUFFER_create_with_size shall create a valid non-NULL handle of zero size. ]
+            result->size = 0;
+            result->buffer = NULL;
+        }
+        else
+        {
+            // Codes_SRS_BUFFER_07_031: [ BUFFER_create_with_size shall allocate a buffer of buff_size. ]
+            result->size = buff_size;
+            if ((result->buffer = (unsigned char*)malloc(result->size)) == NULL)
+            {
+                // Codes_SRS_BUFFER_07_032: [ If allocating memory fails, then BUFFER_create_with_size shall return NULL. ]
+                LogError("unable to allocate buffer");
+                free(result);
+                result = NULL;
+            }
+        }
+    }
+    else
+    {
+        // Codes_SRS_BUFFER_07_032: [ If allocating memory fails, then BUFFER_create_with_size shall return NULL. ]
+        LogError("unable to allocate BUFFER");
+    }
+    // Codes_SRS_BUFFER_07_033: [ Otherwise, BUFFER_create_with_size shall return a non-NULL handle. ]
+    return (BUFFER_HANDLE)result;
+}
+
+/* Codes_SRS_BUFFER_07_003: [BUFFER_delete shall delete the data associated with the BUFFER_HANDLE along with the Buffer.] */
+void BUFFER_delete(BUFFER_HANDLE handle)
+{
+    /* Codes_SRS_BUFFER_07_004: [BUFFER_delete shall not delete any BUFFER_HANDLE that is NULL.] */
+    if (handle != NULL)
+    {
+        BUFFER* b = (BUFFER*)handle;
+        if (b->buffer != NULL)
+        {
+            /* Codes_SRS_BUFFER_07_003: [BUFFER_delete shall delete the data associated with the BUFFER_HANDLE along with the Buffer.] */
+            free(b->buffer);
+        }
+        free(b);
+    }
+}
+
+/*return 0 if the buffer was copied*/
+/*else return different than zero*/
+/* Codes_SRS_BUFFER_07_008: [BUFFER_build allocates size_t bytes, copies the unsigned char* into the buffer and returns zero on success.] */
+int BUFFER_build(BUFFER_HANDLE handle, const unsigned char* source, size_t size)
+{
+    int result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_BUFFER_07_009: [BUFFER_build shall return nonzero if handle is NULL ] */
+        result = MU_FAILURE;
+    }
+    /* Codes_SRS_BUFFER_01_002: [The size argument can be zero, in which case the underlying buffer held by the buffer instance shall be freed.] */
+    else if (size == 0)
+    {
+        /* Codes_SRS_BUFFER_01_003: [If size is zero, source can be NULL.] */
+        BUFFER* b = (BUFFER*)handle;
+        free(b->buffer);
+        b->buffer = NULL;
+        b->size = 0;
+
+        result = 0;
+    }
+    else
+    {
+        if (source == NULL)
+        {
+            /* Codes_SRS_BUFFER_01_001: [If size is positive and source is NULL, BUFFER_build shall return nonzero] */
+            result = MU_FAILURE;
+        }
+        else
+        {
+            BUFFER* b = (BUFFER*)handle;
+            /* Codes_SRS_BUFFER_07_011: [BUFFER_build shall overwrite previous contents if the buffer has been previously allocated.] */
+            unsigned char* newBuffer = (unsigned char*)realloc(b->buffer, size);
+            if (newBuffer == NULL)
+            {
+                /* Codes_SRS_BUFFER_07_010: [BUFFER_build shall return nonzero if any error is encountered.] */
+                LogError("Failure reallocating buffer");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                b->buffer = newBuffer;
+                b->size = size;
+                /* Codes_SRS_BUFFER_01_002: [The size argument can be zero, in which case nothing shall be copied from source.] */
+                (void)memcpy(b->buffer, source, size);
+
+                result = 0;
+            }
+        }
+    }
+
+    return result;
+}
+
+int BUFFER_append_build(BUFFER_HANDLE handle, const unsigned char* source, size_t size)
+{
+    int result;
+    if (handle == NULL || source == NULL || size == 0)
+    {
+        /* Codes_SRS_BUFFER_07_029: [ BUFFER_append_build shall return nonzero if handle or source are NULL or if size is 0. ] */
+        LogError("BUFFER_append_build failed invalid parameter handle: %p, source: %p, size: %lu", handle, source, (unsigned long)size);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        if (handle->buffer == NULL)
+        {
+            /* Codes_SRS_BUFFER_07_030: [ if handle->buffer is NULL BUFFER_append_build shall allocate the a buffer of size bytes... ] */
+            if (BUFFER_safemalloc(handle, size) != 0)
+            {
+                /* Codes_SRS_BUFFER_07_035: [ If any error is encountered BUFFER_append_build shall return a non-null value. ] */
+                LogError("Failure with BUFFER_safemalloc");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                /* Codes_SRS_BUFFER_07_031: [ ... and copy the contents of source to handle->buffer. ] */
+                (void)memcpy(handle->buffer, source, size);
+                /* Codes_SRS_BUFFER_07_034: [ On success BUFFER_append_build shall return 0 ] */
+                result = 0;
+            }
+        }
+        else
+        {
+            /* Codes_SRS_BUFFER_07_032: [ if handle->buffer is not NULL BUFFER_append_build shall realloc the buffer to be the handle->size + size ] */
+            unsigned char* temp = (unsigned char*)realloc(handle->buffer, handle->size + size);
+            if (temp == NULL)
+            {
+                /* Codes_SRS_BUFFER_07_035: [ If any error is encountered BUFFER_append_build shall return a non-null value. ] */
+                LogError("Failure reallocating temporary buffer");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                /* Codes_SRS_BUFFER_07_033: [ ... and copy the contents of source to the end of the buffer. ] */
+                handle->buffer = temp;
+                // Append the BUFFER
+                (void)memcpy(&handle->buffer[handle->size], source, size);
+                handle->size += size;
+                /* Codes_SRS_BUFFER_07_034: [ On success BUFFER_append_build shall return 0 ] */
+                result = 0;
+            }
+        }
+    }
+    return result;
+}
+
+/*return 0 if the buffer was pre-build(that is, had its space allocated)*/
+/*else return different than zero*/
+/* Codes_SRS_BUFFER_07_005: [BUFFER_pre_build allocates size_t bytes of BUFFER_HANDLE and returns zero on success.] */
+int BUFFER_pre_build(BUFFER_HANDLE handle, size_t size)
+{
+    int result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_BUFFER_07_006: [If handle is NULL or size is 0 then BUFFER_pre_build shall return a nonzero value.] */
+        result = MU_FAILURE;
+    }
+    else if (size == 0)
+    {
+        /* Codes_SRS_BUFFER_07_006: [If handle is NULL or size is 0 then BUFFER_pre_build shall return a nonzero value.] */
+        result = MU_FAILURE;
+    }
+    else
+    {
+        BUFFER* b = (BUFFER*)handle;
+        if (b->buffer != NULL)
+        {
+            /* Codes_SRS_BUFFER_07_007: [BUFFER_pre_build shall return nonzero if the buffer has been previously allocated and is not NULL.] */
+            LogError("Failure buffer data is NULL");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if ((b->buffer = (unsigned char*)malloc(size)) == NULL)
+            {
+                /* Codes_SRS_BUFFER_07_013: [BUFFER_pre_build shall return nonzero if any error is encountered.] */
+                LogError("Failure allocating buffer");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                b->size = size;
+                result = 0;
+            }
+        }
+    }
+    return result;
+}
+
+/* Codes_SRS_BUFFER_07_019: [BUFFER_content shall return the data contained within the BUFFER_HANDLE.] */
+int BUFFER_content(BUFFER_HANDLE handle, const unsigned char** content)
+{
+    int result;
+    if ((handle == NULL) || (content == NULL))
+    {
+        /* Codes_SRS_BUFFER_07_020: [If the handle and/or content*is NULL BUFFER_content shall return nonzero.] */
+        result = MU_FAILURE;
+    }
+    else
+    {
+        BUFFER* b = (BUFFER*)handle;
+        *content = b->buffer;
+        result = 0;
+    }
+    return result;
+}
+
+/*return 0 if everything went ok and whatever was built in the buffer was unbuilt*/
+/* Codes_SRS_BUFFER_07_012: [BUFFER_unbuild shall clear the underlying unsigned char* data associated with the BUFFER_HANDLE this will return zero on success.] */
+extern int BUFFER_unbuild(BUFFER_HANDLE handle)
+{
+    int result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_BUFFER_07_014: [BUFFER_unbuild shall return a nonzero value if BUFFER_HANDLE is NULL.] */
+        LogError("Failure: handle is invalid.");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        BUFFER* b = (BUFFER*)handle;
+        if (b->buffer != NULL)
+        {
+            free(b->buffer);
+            b->buffer = NULL;
+            b->size = 0;
+        
+        }
+
+        /* Codes_SRS_BUFFER_07_015: [BUFFER_unbuild shall always return success if the unsigned char* referenced by BUFFER_HANDLE is NULL.] */
+        result = 0;
+    }
+    return result;
+}
+
+/* Codes_SRS_BUFFER_07_016: [BUFFER_enlarge shall increase the size of the unsigned char* referenced by BUFFER_HANDLE.] */
+int BUFFER_enlarge(BUFFER_HANDLE handle, size_t enlargeSize)
+{
+    int result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_BUFFER_07_017: [BUFFER_enlarge shall return a nonzero result if any parameters are NULL or zero.] */
+        LogError("Failure: handle is invalid.");
+        result = MU_FAILURE;
+    }
+    else if (enlargeSize == 0)
+    {
+        /* Codes_SRS_BUFFER_07_017: [BUFFER_enlarge shall return a nonzero result if any parameters are NULL or zero.] */
+        LogError("Failure: enlargeSize size is 0.");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        BUFFER* b = (BUFFER*)handle;
+        unsigned char* temp = (unsigned char*)realloc(b->buffer, b->size + enlargeSize);
+        if (temp == NULL)
+        {
+            /* Codes_SRS_BUFFER_07_018: [BUFFER_enlarge shall return a nonzero result if any error is encountered.] */
+            LogError("Failure: allocating temp buffer.");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            b->buffer = temp;
+            b->size += enlargeSize;
+            result = 0;
+        }
+    }
+    return result;
+}
+
+int BUFFER_shrink(BUFFER_HANDLE handle, size_t decreaseSize, bool fromEnd)
+{
+    int result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_BUFFER_07_036: [ if handle is NULL, BUFFER_shrink shall return a non-null value ]*/
+        LogError("Failure: handle is invalid.");
+        result = MU_FAILURE;
+    }
+    else if (decreaseSize == 0)
+    {
+        /* Codes_SRS_BUFFER_07_037: [ If decreaseSize is equal zero, BUFFER_shrink shall return a non-null value ] */
+        LogError("Failure: decrease size is 0.");
+        result = MU_FAILURE;
+    }
+    else if (decreaseSize > handle->size)
+    {
+        /* Codes_SRS_BUFFER_07_038: [ If decreaseSize is less than the size of the buffer, BUFFER_shrink shall return a non-null value ] */
+        LogError("Failure: decrease size is less than buffer size.");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        /* Codes_SRS_BUFFER_07_039: [ BUFFER_shrink shall allocate a temporary buffer of existing buffer size minus decreaseSize. ] */
+        size_t alloc_size = handle->size - decreaseSize;
+        if (alloc_size == 0)
+        {
+            /* Codes_SRS_BUFFER_07_043: [ If the decreaseSize is equal the buffer size , BUFFER_shrink shall deallocate the buffer and set the size to zero. ] */
+            free(handle->buffer);
+            handle->buffer = NULL;
+            handle->size = 0;
+            result = 0;
+        }
+        else
+        {
+            unsigned char* tmp = malloc(alloc_size);
+            if (tmp == NULL)
+            {
+                /* Codes_SRS_BUFFER_07_042: [ If a failure is encountered, BUFFER_shrink shall return a non-null value ] */
+                LogError("Failure: allocating temp buffer.");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                if (fromEnd)
+                {
+                    /* Codes_SRS_BUFFER_07_040: [ if the fromEnd variable is true, BUFFER_shrink shall remove the end of the buffer of size decreaseSize. ] */
+                    memcpy(tmp, handle->buffer, alloc_size);
+                    free(handle->buffer);
+                    handle->buffer = tmp;
+                    handle->size = alloc_size;
+                    result = 0;
+                }
+                else
+                {
+                    /* Codes_SRS_BUFFER_07_041: [ if the fromEnd variable is false, BUFFER_shrink shall remove the beginning of the buffer of size decreaseSize. ] */
+                    memcpy(tmp, handle->buffer + decreaseSize, alloc_size);
+                    free(handle->buffer);
+                    handle->buffer = tmp;
+                    handle->size = alloc_size;
+                    result = 0;
+                }
+            }
+        }
+    }
+    return result;
+}
+
+/* Codes_SRS_BUFFER_07_021: [BUFFER_size shall place the size of the associated buffer in the size variable and return zero on success.] */
+int BUFFER_size(BUFFER_HANDLE handle, size_t* size)
+{
+    int result;
+    if ((handle == NULL) || (size == NULL))
+    {
+        /* Codes_SRS_BUFFER_07_022: [BUFFER_size shall return a nonzero value for any error that is encountered.] */
+        result = MU_FAILURE;
+    }
+    else
+    {
+        BUFFER* b = (BUFFER*)handle;
+        *size = b->size;
+        result = 0;
+    }
+    return result;
+}
+
+/* Codes_SRS_BUFFER_07_024: [BUFFER_append concatenates b2 onto b1 without modifying b2 and shall return zero on success.] */
+int BUFFER_append(BUFFER_HANDLE handle1, BUFFER_HANDLE handle2)
+{
+    int result;
+    if ( (handle1 == NULL) || (handle2 == NULL) || (handle1 == handle2) )
+    {
+        /* Codes_SRS_BUFFER_07_023: [BUFFER_append shall return a nonzero upon any error that is encountered.] */
+        result = MU_FAILURE;
+    }
+    else
+    {
+        BUFFER* b1 = (BUFFER*)handle1;
+        BUFFER* b2 = (BUFFER*)handle2;
+        if (b1->buffer == NULL)
+        {
+            /* Codes_SRS_BUFFER_07_023: [BUFFER_append shall return a nonzero upon any error that is encountered.] */
+            result = MU_FAILURE;
+        }
+        else if (b2->buffer == NULL)
+        {
+            /* Codes_SRS_BUFFER_07_023: [BUFFER_append shall return a nonzero upon any error that is encountered.] */
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if (b2->size ==0)
+            {
+                // b2->size = 0, whatever b1->size is, do nothing
+                result = 0;
+            }
+            else
+            {
+                // b2->size != 0, whatever b1->size is
+                unsigned char* temp = (unsigned char*)realloc(b1->buffer, b1->size + b2->size);
+                if (temp == NULL)
+                {
+                    /* Codes_SRS_BUFFER_07_023: [BUFFER_append shall return a nonzero upon any error that is encountered.] */
+                    LogError("Failure: allocating temp buffer.");
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    /* Codes_SRS_BUFFER_07_024: [BUFFER_append concatenates b2 onto b1 without modifying b2 and shall return zero on success.]*/
+                    b1->buffer = temp;
+                    // Append the BUFFER
+                    (void)memcpy(&b1->buffer[b1->size], b2->buffer, b2->size);
+                    b1->size += b2->size;
+                    result = 0;
+                }
+            }
+        }
+    }
+    return result;
+}
+
+int BUFFER_prepend(BUFFER_HANDLE handle1, BUFFER_HANDLE handle2)
+{
+    int result;
+    if ((handle1 == NULL) || (handle2 == NULL) || (handle1 == handle2))
+    {
+        /* Codes_SRS_BUFFER_01_005: [ BUFFER_prepend shall return a non-zero upon value any error that is encountered. ]*/
+        result = MU_FAILURE;
+    }
+    else
+    {
+        BUFFER* b1 = (BUFFER*)handle1;
+        BUFFER* b2 = (BUFFER*)handle2;
+        if (b1->buffer == NULL)
+        {
+            /* Codes_SRS_BUFFER_01_005: [ BUFFER_prepend shall return a non-zero upon value any error that is encountered. ]*/
+            result = MU_FAILURE;
+        }
+        else if (b2->buffer == NULL)
+        {
+            /* Codes_SRS_BUFFER_01_005: [ BUFFER_prepend shall return a non-zero upon value any error that is encountered. ]*/
+            result = MU_FAILURE;
+        }
+        else
+        {
+            //put b2 ahead of b1: [b2][b1], return b1
+            if (b2->size ==0)
+            {
+                // do nothing
+                result = 0;
+            }
+            else
+            {
+                // b2->size != 0
+                unsigned char* temp = (unsigned char*)malloc(b1->size + b2->size);
+                if (temp == NULL)
+                {
+                    /* Codes_SRS_BUFFER_01_005: [ BUFFER_prepend shall return a non-zero upon value any error that is encountered. ]*/
+                    LogError("Failure: allocating temp buffer.");
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    /* Codes_SRS_BUFFER_01_004: [ BUFFER_prepend concatenates handle1 onto handle2 without modifying handle1 and shall return zero on success. ]*/
+                    // Append the BUFFER
+                    (void)memcpy(temp, b2->buffer, b2->size);
+                    // start from b1->size to append b1
+                    (void)memcpy(&temp[b2->size], b1->buffer, b1->size);
+                    free(b1->buffer);
+                    b1->buffer = temp;
+                    b1->size += b2->size;
+                    result = 0;
+                }
+            }
+        }
+    }
+    return result;
+}
+
+int BUFFER_fill(BUFFER_HANDLE handle, unsigned char fill_char)
+{
+    int result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_BUFFER_07_002: [ If handle is NULL BUFFER_fill shall return a non-zero value. ] */
+        LogError("Invalid parameter specified, handle == NULL.");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        size_t index;
+        /* Codes_SRS_BUFFER_07_001: [ BUFFER_fill shall fill the supplied BUFFER_HANDLE with the supplied fill character. ] */
+        BUFFER* buffer_data = (BUFFER*)handle;
+        for (index = 0; index < buffer_data->size; index++)
+        {
+            buffer_data->buffer[index] = fill_char;
+        }
+        result = 0;
+    }
+    return result;
+}
+
+
+/* Codes_SRS_BUFFER_07_025: [BUFFER_u_char shall return a pointer to the underlying unsigned char*.] */
+unsigned char* BUFFER_u_char(BUFFER_HANDLE handle)
+{
+    BUFFER* handleData = (BUFFER*)handle;
+    unsigned char* result;
+    if (handle == NULL || handleData->size == 0)
+    {
+        /* Codes_SRS_BUFFER_07_026: [BUFFER_u_char shall return NULL for any error that is encountered.] */
+        /* Codes_SRS_BUFFER_07_029: [BUFFER_u_char shall return NULL if underlying buffer size is zero.] */
+        result = NULL;
+    }
+    else
+    {
+        result = handleData->buffer;
+    }
+    return result;
+}
+
+/* Codes_SRS_BUFFER_07_027: [BUFFER_length shall return the size of the underlying buffer.] */
+size_t BUFFER_length(BUFFER_HANDLE handle)
+{
+    size_t result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_BUFFER_07_028: [BUFFER_length shall return zero for any error that is encountered.] */
+        result = 0;
+    }
+    else
+    {
+        BUFFER* b = (BUFFER*)handle;
+        result = b->size;
+    }
+    return result;
+}
+
+BUFFER_HANDLE BUFFER_clone(BUFFER_HANDLE handle)
+{
+    BUFFER_HANDLE result;
+    if (handle == NULL)
+    {
+        result = NULL;
+    }
+    else
+    {
+        BUFFER* suppliedBuff = (BUFFER*)handle;
+        BUFFER* b = (BUFFER*)calloc(1, sizeof(BUFFER));
+        if (b != NULL)
+        {
+            if (BUFFER_safemalloc(b, suppliedBuff->size) != 0)
+            {
+                free(b);
+                LogError("Failure: allocating temp buffer.");
+                result = NULL;
+            }
+            else
+            {
+                (void)memcpy(b->buffer, suppliedBuff->buffer, suppliedBuff->size);
+                b->size = suppliedBuff->size;
+                result = (BUFFER_HANDLE)b;
+            }
+        }
+        else
+        {
+            result = NULL;
+        }
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/connection_string_parser.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/connection_string_parser.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/connection_string_parser.c	(revision 453)
@@ -0,0 +1,234 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdbool.h>
+#include "azure_c_shared_utility/connection_string_parser.h"
+#include "azure_c_shared_utility/map.h"
+#include "azure_c_shared_utility/strings.h"
+#include "azure_c_shared_utility/string_tokenizer.h"
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/xlogging.h"
+
+
+MAP_HANDLE connectionstringparser_parse_from_char(const char* connection_string)
+{
+    MAP_HANDLE result;
+    STRING_HANDLE connString = NULL;
+
+    /* Codes_SRS_CONNECTIONSTRINGPARSER_21_020: [connectionstringparser_parse_from_char shall create a STRING_HANDLE from the connection_string passed in as argument and parse it using the connectionstringparser_parse.]*/
+    if ((connString = STRING_construct(connection_string)) == NULL)
+    {
+        /* Codes_SRS_CONNECTIONSTRINGPARSER_21_021: [If connectionstringparser_parse_from_char get error creating a STRING_HANDLE, it shall return NULL.]*/
+        LogError("Error constructing connection String");
+        result = NULL;
+    }
+    else
+    {
+        result = connectionstringparser_parse(connString);
+        STRING_delete(connString);
+    }
+
+    return result;
+}
+
+/* Codes_SRS_CONNECTIONSTRINGPARSER_01_001: [connectionstringparser_parse shall parse all key value pairs from the connection_string passed in as argument and return a new map that holds the key/value pairs.] */
+MAP_HANDLE connectionstringparser_parse(STRING_HANDLE connection_string)
+{
+    MAP_HANDLE result;
+
+    if (connection_string == NULL)
+    {
+        /* Codes_SRS_CONNECTIONSTRINGPARSER_01_002: [If connection_string is NULL then connectionstringparser_parse shall fail and return NULL.] */
+        result = NULL;
+        LogError("NULL connection string passed to tokenizer.");
+    }
+    else
+    {
+        /* Codes_SRS_CONNECTIONSTRINGPARSER_01_003: [connectionstringparser_parse shall create a STRING tokenizer to be used for parsing the connection string, by calling STRING_TOKENIZER_create.] */
+        /* Codes_SRS_CONNECTIONSTRINGPARSER_01_004: [connectionstringparser_parse shall start scanning at the beginning of the connection string.] */
+        STRING_TOKENIZER_HANDLE tokenizer = STRING_TOKENIZER_create(connection_string);
+        if (tokenizer == NULL)
+        {
+            /* Codes_SRS_CONNECTIONSTRINGPARSER_01_015: [If STRING_TOKENIZER_create fails, connectionstringparser_parse shall fail and return NULL.] */
+            result = NULL;
+            LogError("Error creating STRING tokenizer.");
+        }
+        else
+        {
+            /* Codes_SRS_CONNECTIONSTRINGPARSER_01_016: [2 STRINGs shall be allocated in order to hold the to be parsed key and value tokens.] */
+            STRING_HANDLE token_key_string = STRING_new();
+            if (token_key_string == NULL)
+            {
+                /* Codes_SRS_CONNECTIONSTRINGPARSER_01_017: [If allocating the STRINGs fails connectionstringparser_parse shall fail and return NULL.] */
+                result = NULL;
+                LogError("Error creating key token STRING.");
+            }
+            else
+            {
+                STRING_HANDLE token_value_string = STRING_new();
+                if (token_value_string == NULL)
+                {
+                    /* Codes_SRS_CONNECTIONSTRINGPARSER_01_017: [If allocating the STRINGs fails connectionstringparser_parse shall fail and return NULL.] */
+                    result = NULL;
+                    LogError("Error creating value token STRING.");
+                }
+                else
+                {
+                    result = Map_Create(NULL);
+                    if (result == NULL)
+                    {
+                        /* Codes_SRS_CONNECTIONSTRINGPARSER_01_018: [If creating the result map fails, then connectionstringparser_parse shall return NULL.] */
+                        LogError("Error creating Map.");
+                    }
+                    else
+                    {
+                        /* Codes_SRS_CONNECTIONSTRINGPARSER_01_005: [The following actions shall be repeated until parsing is complete:] */
+                        /* Codes_SRS_CONNECTIONSTRINGPARSER_01_006: [connectionstringparser_parse shall find a token (the key of the key/value pair) delimited by the = character, by calling STRING_TOKENIZER_get_next_token.] */
+                        /* Codes_SRS_CONNECTIONSTRINGPARSER_01_007: [If STRING_TOKENIZER_get_next_token fails, parsing shall be considered complete.] */
+                        while (STRING_TOKENIZER_get_next_token(tokenizer, token_key_string, "=") == 0)
+                        {
+                            bool is_error = false;
+
+                            /* Codes_SRS_CONNECTIONSTRINGPARSER_01_008: [connectionstringparser_parse shall find a token (the value of the key/value pair) delimited by the ; character, by calling STRING_TOKENIZER_get_next_token.] */
+                            if (STRING_TOKENIZER_get_next_token(tokenizer, token_value_string, ";") != 0)
+                            {
+                                /* Codes_SRS_CONNECTIONSTRINGPARSER_01_009: [If STRING_TOKENIZER_get_next_token fails, connectionstringparser_parse shall fail and return NULL (freeing the allocated result map).] */
+                                is_error = true;
+                                LogError("Error reading value token from the connection string.");
+                            }
+                            else
+                            {
+                                /* Codes_SRS_CONNECTIONSTRINGPARSER_01_011: [The C strings for the key and value shall be extracted from the previously parsed STRINGs by using STRING_c_str.] */
+                                const char* token = STRING_c_str(token_key_string);
+                                /* Codes_SRS_CONNECTIONSTRINGPARSER_01_013: [If STRING_c_str fails then connectionstringparser_parse shall fail and return NULL (freeing the allocated result map).] */
+                                if ((token == NULL) ||
+                                    /* Codes_SRS_CONNECTIONSTRINGPARSER_01_019: [If the key length is zero then connectionstringparser_parse shall fail and return NULL (freeing the allocated result map).] */
+                                    (strlen(token) == 0))
+                                {
+                                    is_error = true;
+                                    LogError("The key token is NULL or empty.");
+                                }
+                                else
+                                {
+                                    /* Codes_SRS_CONNECTIONSTRINGPARSER_01_011: [The C strings for the key and value shall be extracted from the previously parsed STRINGs by using STRING_c_str.] */
+                                    const char* value = STRING_c_str(token_value_string);
+                                    if (value == NULL)
+                                    {
+                                        /* Codes_SRS_CONNECTIONSTRINGPARSER_01_013: [If STRING_c_str fails then connectionstringparser_parse shall fail and return NULL (freeing the allocated result map).] */
+                                        is_error = true;
+                                        LogError("Could not get C string for value token.");
+                                    }
+                                    else
+                                    {
+                                        /* Codes_SRS_CONNECTIONSTRINGPARSER_01_010: [The key and value shall be added to the result map by using Map_Add.] */
+                                        if (Map_Add(result, token, value) != MAP_OK)
+                                        {
+                                            /* Codes_SRS_CONNECTIONSTRINGPARSER_01_012: [If Map_Add fails connectionstringparser_parse shall fail and return NULL (freeing the allocated result map).] */
+                                            is_error = true;
+                                            LogError("Could not add the key/value pair to the result map.");
+                                        }
+                                    }
+                                }
+                            }
+
+                            if (is_error)
+                            {
+                                LogError("Error parsing connection string.");
+                                Map_Destroy(result);
+                                result = NULL;
+                                break;
+                            }
+                        }
+                    }
+
+                    STRING_delete(token_value_string);
+                }
+
+                STRING_delete(token_key_string);
+            }
+
+            /* Codes_SRS_CONNECTIONSTRINGPARSER_01_014: [After the parsing is complete the previously allocated STRINGs and STRING tokenizer shall be freed by calling STRING_TOKENIZER_destroy.] */
+            STRING_TOKENIZER_destroy(tokenizer);
+        }
+    }
+
+    return result;
+}
+
+/* Codes_SRS_CONNECTIONSTRINGPARSER_21_022: [connectionstringparser_splitHostName_from_char shall split the provided hostName in name and suffix.]*/
+int connectionstringparser_splitHostName_from_char(const char* hostName, STRING_HANDLE nameString, STRING_HANDLE suffixString)
+{
+    int result;
+    const char* runHostName = hostName;
+
+    if ((hostName == NULL) || ((*hostName) == '\0') || ((*hostName) == '.') || (nameString == NULL) || (suffixString == NULL))
+    {
+        /* Codes_SRS_CONNECTIONSTRINGPARSER_21_026: [If the hostName is NULL, connectionstringparser_splitHostName_from_char shall return MU_FAILURE.]*/
+        /* Codes_SRS_CONNECTIONSTRINGPARSER_21_027: [If the hostName is an empty string, connectionstringparser_splitHostName_from_char shall return MU_FAILURE.]*/
+        /* Codes_SRS_CONNECTIONSTRINGPARSER_21_028: [If the nameString is NULL, connectionstringparser_splitHostName_from_char shall return MU_FAILURE.]*/
+        /* Codes_SRS_CONNECTIONSTRINGPARSER_21_029: [If the suffixString is NULL, connectionstringparser_splitHostName_from_char shall return MU_FAILURE.]*/
+        /* Codes_SRS_CONNECTIONSTRINGPARSER_21_030: [If the hostName is not a valid host name, connectionstringparser_splitHostName_from_char shall return MU_FAILURE.]*/
+        result = MU_FAILURE;
+    }
+    else
+    {
+        while ((*runHostName) != '\0')
+        {
+            if ((*runHostName) == '.')
+            {
+                /* Codes_SRS_CONNECTIONSTRINGPARSER_21_023: [connectionstringparser_splitHostName_from_char shall copy all characters, from the beginning of the hostName to the first . to the nameString.]*/
+                /* Codes_SRS_CONNECTIONSTRINGPARSER_21_024: [connectionstringparser_splitHostName_from_char shall copy all characters, from the first . to the end of the hostName, to the suffixString.]*/
+                runHostName++;
+                break;
+            }
+            runHostName++;
+        }
+
+        if ((*runHostName) == '\0')
+        {
+            /* Codes_SRS_CONNECTIONSTRINGPARSER_21_030: [If the hostName is not a valid host name, connectionstringparser_splitHostName_from_char shall return MU_FAILURE.]*/
+            result = MU_FAILURE;
+        }
+        else
+        {
+            /* Codes_SRS_CONNECTIONSTRINGPARSER_21_023: [connectionstringparser_splitHostName_from_char shall copy all characters, from the beginning of the hostName to the first . to the nameString.]*/
+            if (STRING_copy_n(nameString, hostName, runHostName - hostName - 1) != 0)
+            {
+                /* Codes_SRS_CONNECTIONSTRINGPARSER_21_031: [If connectionstringparser_splitHostName_from_char get error copying the name to the nameString, it shall return MU_FAILURE.]*/
+                result = MU_FAILURE;
+            }
+            /* Codes_SRS_CONNECTIONSTRINGPARSER_21_024: [connectionstringparser_splitHostName_from_char shall copy all characters, from the first . to the end of the hostName, to the suffixString.]*/
+            else if (STRING_copy(suffixString, runHostName) != 0)
+            {
+                /* Codes_SRS_CONNECTIONSTRINGPARSER_21_032: [If connectionstringparser_splitHostName_from_char get error copying the suffix to the suffixString, it shall return MU_FAILURE.]*/
+                result = MU_FAILURE;
+            }
+            else
+            {
+                /* Codes_SRS_CONNECTIONSTRINGPARSER_21_025: [If connectionstringparser_splitHostName_from_char get success splitting the hostName, it shall return 0.]*/
+                result = 0;
+            }
+        }
+    }
+
+    return result;
+}
+
+
+int connectionstringparser_splitHostName(STRING_HANDLE hostNameString, STRING_HANDLE nameString, STRING_HANDLE suffixString)
+{
+    int result;
+
+    if (hostNameString == NULL)
+    {
+        /* Codes_SRS_CONNECTIONSTRINGPARSER_21_034: [If the hostNameString is NULL, connectionstringparser_splitHostName shall return MU_FAILURE.]*/
+        result = MU_FAILURE;
+    }
+    else
+    {
+        /* Codes_SRS_CONNECTIONSTRINGPARSER_21_033: [connectionstringparser_splitHostName shall convert the hostNameString to a connection_string passed in as argument, and call connectionstringparser_splitHostName_from_char.]*/
+        result = connectionstringparser_splitHostName_from_char(STRING_c_str(hostNameString), nameString, suffixString);
+    }
+
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/consolelogger.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/consolelogger.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/consolelogger.c	(revision 453)
@@ -0,0 +1,230 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <time.h>
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/consolelogger.h"
+
+#if (defined(_MSC_VER))
+#include "windows.h"
+
+/*returns a string as if printed by vprintf*/
+static char* vprintf_alloc(const char* format, va_list va)
+{
+    char* result;
+    int neededSize = vsnprintf(NULL, 0, format, va);
+    if (neededSize < 0)
+    {
+        result = NULL;
+    }
+    else
+    {
+        result = (char*)malloc(neededSize + 1);
+        if (result == NULL)
+        {
+            /*return as is*/
+        }
+        else
+        {
+            if (vsnprintf(result, neededSize + 1, format, va) != neededSize)
+            {
+                free(result);
+                result = NULL;
+            }
+        }
+    }
+    return result;
+}
+
+/*returns a string as if printed by printf*/
+static char* printf_alloc(const char* format, ...)
+{
+    char* result;
+    va_list va;
+    va_start(va, format);
+    result = vprintf_alloc(format, va);
+    va_end(va);
+    return result;
+}
+
+/*returns NULL if it fails*/
+static char* lastErrorToString(DWORD lastError)
+{
+    char* result;
+    if (lastError == 0)
+    {
+        result = printf_alloc(""); /*no error should appear*/
+        if (result == NULL)
+        {
+            (void)printf("failure in printf_alloc");
+        }
+        else
+        {
+            /*return as is*/
+        }
+    }
+    else
+    {
+        char temp[MESSAGE_BUFFER_SIZE];
+        if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, lastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), temp, MESSAGE_BUFFER_SIZE, NULL) == 0)
+        {
+            result = printf_alloc("GetLastError()=0X%x", lastError);
+            if (result == NULL)
+            {
+                (void)printf("failure in printf_alloc\n");
+                /*return as is*/
+            }
+            else
+            {
+                /*return as is*/
+            }
+        }
+        else
+        {
+            /*eliminate the \r or \n from the string*/
+            /*one replace of each is enough*/
+            char* whereAreThey;
+            if ((whereAreThey = strchr(temp, '\r')) != NULL)
+            {
+                *whereAreThey = '\0';
+            }
+            if ((whereAreThey = strchr(temp, '\n')) != NULL)
+            {
+                *whereAreThey = '\0';
+            }
+
+            result = printf_alloc("GetLastError()==0X%x (%s)", lastError, temp);
+
+            if (result == NULL)
+            {
+                (void)printf("failure in printf_alloc\n");
+                /*return as is*/
+            }
+            else
+            {
+                /*return as is*/
+            }
+        }
+    }
+    return result;
+}
+/*this function will use 1x printf (in the happy case) .*/
+/*more than 1x printf / function call can mean intermingled LogErrors in a multithreaded env*/
+/*the function will also attempt to produce some human readable strings for GetLastError*/
+void consolelogger_log_with_GetLastError(const char* file, const char* func, int line, const char* format, ...)
+{
+    DWORD lastError;
+    char* lastErrorAsString;
+    int lastErrorAsString_should_be_freed;
+    time_t t;
+    int systemMessage_should_be_freed;
+    char* systemMessage;
+    int userMessage_should_be_freed;
+    char* userMessage;
+
+    va_list args;
+    va_start(args, format);
+
+    /*this is what this case will do:
+    1. snip the last error
+    2. create a string with what that last error means
+    3. printf the system message (__FILE__, __LINE__ etc) + the last error + whatever the user wanted
+    */
+    /*1. snip the last error*/
+    lastError = GetLastError();
+
+    /*2. create a string with what that last error means*/
+    lastErrorAsString = lastErrorToString(lastError);
+    if (lastErrorAsString == NULL)
+    {
+        (void)printf("failure in lastErrorToString");
+        lastErrorAsString = "";
+        lastErrorAsString_should_be_freed = 0;
+    }
+    else
+    {
+        lastErrorAsString_should_be_freed = 1;
+    }
+
+    t = time(NULL);
+    systemMessage = printf_alloc("Error: Time:%.24s File:%s Func:%s Line:%d %s", ctime(&t), file, func, line, lastErrorAsString);
+
+    if (systemMessage == NULL)
+    {
+        systemMessage = "";
+        (void)printf("Error: [FAILED] Time:%.24s File : %s Func : %s Line : %d %s", ctime(&t), file, func, line, lastErrorAsString);
+        systemMessage_should_be_freed = 0;
+    }
+    else
+    {
+        systemMessage_should_be_freed = 1;
+    }
+
+    userMessage = vprintf_alloc(format, args);
+    if (userMessage == NULL)
+    {
+        (void)printf("[FAILED] ");
+        (void)vprintf(format, args);
+        (void)printf("\n");
+        userMessage_should_be_freed = 0;
+    }
+    else
+    {
+        /*3. printf the system message(__FILE__, __LINE__ etc) + the last error + whatever the user wanted*/
+        (void)printf("%s %s\n", systemMessage, userMessage);
+        userMessage_should_be_freed = 1;
+    }
+
+    if (userMessage_should_be_freed == 1)
+    {
+        free(userMessage);
+    }
+
+    if (systemMessage_should_be_freed == 1)
+    {
+        free(systemMessage);
+    }
+
+    if (lastErrorAsString_should_be_freed == 1)
+    {
+        free(lastErrorAsString);
+    }
+    va_end(args);
+}
+#endif
+
+#if defined(__GNUC__)
+__attribute__ ((format (printf, 6, 7)))
+#endif
+void consolelogger_log(LOG_CATEGORY log_category, const char* file, const char* func, int line, unsigned int options, const char* format, ...)
+{
+    time_t t;
+    va_list args;
+    va_start(args, format);
+
+    t = time(NULL);
+
+    switch (log_category)
+    {
+    case AZ_LOG_INFO:
+        (void)printf("Info: ");
+        break;
+    case AZ_LOG_ERROR:
+        (void)printf("Error: Time:%.24s File:%s Func:%s Line:%d ", ctime(&t), file, func, line);
+        break;
+    default:
+        break;
+    }
+
+    (void)vprintf(format, args);
+    va_end(args);
+
+    (void)log_category;
+    if (options & LOG_LINE)
+    {
+        (void)printf("\r\n");
+    }
+}
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/constbuffer.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/constbuffer.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/constbuffer.c	(revision 453)
@@ -0,0 +1,350 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/refcount.h"
+
+#include "azure_c_shared_utility/constbuffer.h"
+
+#define CONSTBUFFER_TYPE_VALUES \
+    CONSTBUFFER_TYPE_COPIED, \
+    CONSTBUFFER_TYPE_MEMORY_MOVED, \
+    CONSTBUFFER_TYPE_WITH_CUSTOM_FREE, \
+    CONSTBUFFER_TYPE_FROM_OFFSET_AND_SIZE
+
+MU_DEFINE_ENUM(CONSTBUFFER_TYPE, CONSTBUFFER_TYPE_VALUES)
+
+typedef struct CONSTBUFFER_HANDLE_DATA_TAG
+{
+    CONSTBUFFER alias;
+    COUNT_TYPE count;
+    CONSTBUFFER_TYPE buffer_type;
+    CONSTBUFFER_CUSTOM_FREE_FUNC custom_free_func;
+    void* custom_free_func_context;
+    CONSTBUFFER_HANDLE originalHandle; /*where the CONSTBUFFER_TYPE_FROM_OFFSET_AND_SIZE was build from*/
+} CONSTBUFFER_HANDLE_DATA;
+
+static CONSTBUFFER_HANDLE CONSTBUFFER_Create_Internal(const unsigned char* source, size_t size)
+{
+    CONSTBUFFER_HANDLE result;
+    /*Codes_SRS_CONSTBUFFER_02_005: [The non-NULL handle returned by CONSTBUFFER_Create shall have its ref count set to "1".]*/
+    /*Codes_SRS_CONSTBUFFER_02_010: [The non-NULL handle returned by CONSTBUFFER_CreateFromBuffer shall have its ref count set to "1".]*/
+    result = (CONSTBUFFER_HANDLE)calloc(1, (sizeof(CONSTBUFFER_HANDLE_DATA) + size));
+    if (result == NULL)
+    {
+        /*Codes_SRS_CONSTBUFFER_02_003: [If creating the copy fails then CONSTBUFFER_Create shall return NULL.]*/
+        /*Codes_SRS_CONSTBUFFER_02_008: [If copying the content fails, then CONSTBUFFER_CreateFromBuffer shall fail and return NULL.] */
+        LogError("unable to malloc");
+        /*return as is*/
+    }
+    else
+    {
+        INIT_REF_VAR(result->count);
+
+        /*Codes_SRS_CONSTBUFFER_02_002: [Otherwise, CONSTBUFFER_Create shall create a copy of the memory area pointed to by source having size bytes.]*/
+        result->alias.size = size;
+        if (size == 0)
+        {
+            result->alias.buffer = NULL;
+        }
+        else
+        {
+            unsigned char* temp = (unsigned char*)(result + 1);
+            /*Codes_SRS_CONSTBUFFER_02_004: [Otherwise CONSTBUFFER_Create shall return a non-NULL handle.]*/
+            /*Codes_SRS_CONSTBUFFER_02_007: [Otherwise, CONSTBUFFER_CreateFromBuffer shall copy the content of buffer.]*/
+            /*Codes_SRS_CONSTBUFFER_02_009: [Otherwise, CONSTBUFFER_CreateFromBuffer shall return a non-NULL handle.]*/
+            (void)memcpy(temp, source, size);
+            result->alias.buffer = temp;
+        }
+
+        result->buffer_type = CONSTBUFFER_TYPE_COPIED;
+    }
+    return result;
+}
+
+IMPLEMENT_MOCKABLE_FUNCTION(, CONSTBUFFER_HANDLE, CONSTBUFFER_Create, const unsigned char*, source, size_t, size)
+{
+    CONSTBUFFER_HANDLE result;
+    /*Codes_SRS_CONSTBUFFER_02_001: [If source is NULL and size is different than 0 then CONSTBUFFER_Create shall fail and return NULL.]*/
+    if (
+        (source == NULL) &&
+        (size != 0)
+        )
+    {
+        LogError("invalid arguments passes to CONSTBUFFER_Create");
+        result = NULL;
+    }
+    else
+    {
+        result = CONSTBUFFER_Create_Internal(source, size);
+    }
+    return result;
+}
+
+/*this creates a new constbuffer from an existing BUFFER_HANDLE*/
+IMPLEMENT_MOCKABLE_FUNCTION(, CONSTBUFFER_HANDLE, CONSTBUFFER_CreateFromBuffer, BUFFER_HANDLE, buffer)
+{
+    CONSTBUFFER_HANDLE result;
+    /*Codes_SRS_CONSTBUFFER_02_006: [If buffer is NULL then CONSTBUFFER_CreateFromBuffer shall fail and return NULL.]*/
+    if (buffer == NULL)
+    {
+        LogError("invalid arg passed to CONSTBUFFER_CreateFromBuffer");
+        result = NULL;
+    }
+    else
+    {
+        size_t length = BUFFER_length(buffer);
+        unsigned char* rawBuffer = BUFFER_u_char(buffer);
+        result = CONSTBUFFER_Create_Internal(rawBuffer, length);
+    }
+    return result;
+}
+
+IMPLEMENT_MOCKABLE_FUNCTION(, CONSTBUFFER_HANDLE, CONSTBUFFER_CreateWithMoveMemory, unsigned char*, source, size_t, size)
+{
+    CONSTBUFFER_HANDLE result;
+
+    /* Codes_SRS_CONSTBUFFER_01_001: [ If source is NULL and size is different than 0 then CONSTBUFFER_Create shall fail and return NULL. ]*/
+    if ((source == NULL) && (size > 0))
+    {
+        LogError("Invalid arguments: unsigned char* source=%p, size_t size=%u", source, (unsigned int)size);
+        result = NULL;
+    }
+    else
+    {
+        result = (CONSTBUFFER_HANDLE)calloc(1, sizeof(CONSTBUFFER_HANDLE_DATA));
+        if (result == NULL)
+        {
+            /* Codes_SRS_CONSTBUFFER_01_005: [ If any error occurs, CONSTBUFFER_CreateWithMoveMemory shall fail and return NULL. ]*/
+            LogError("malloc failed");
+        }
+        else
+        {
+            /* Codes_SRS_CONSTBUFFER_01_004: [ If source is non-NULL and size is 0, the source pointer shall be owned (and freed) by the newly created instance of const buffer. ]*/
+            /* Codes_SRS_CONSTBUFFER_01_002: [ CONSTBUFFER_CreateWithMoveMemory shall store the source and size and return a non-NULL handle to the newly created const buffer. ]*/
+            result->alias.buffer = source;
+            result->alias.size = size;
+            result->buffer_type = CONSTBUFFER_TYPE_MEMORY_MOVED;
+
+            /* Codes_SRS_CONSTBUFFER_01_003: [ The non-NULL handle returned by CONSTBUFFER_CreateWithMoveMemory shall have its ref count set to "1". ]*/
+            INIT_REF_VAR(result->count);
+        }
+    }
+
+    return result;
+}
+
+IMPLEMENT_MOCKABLE_FUNCTION(, CONSTBUFFER_HANDLE, CONSTBUFFER_CreateWithCustomFree, const unsigned char*, source, size_t, size, CONSTBUFFER_CUSTOM_FREE_FUNC, customFreeFunc, void*, customFreeFuncContext)
+{
+    CONSTBUFFER_HANDLE result;
+
+    /* Codes_SRS_CONSTBUFFER_01_014: [ customFreeFuncContext shall be allowed to be NULL. ]*/
+
+    if (
+        /* Codes_SRS_CONSTBUFFER_01_006: [ If source is NULL and size is different than 0 then CONSTBUFFER_CreateWithCustomFree shall fail and return NULL. ]*/
+        ((source == NULL) && (size > 0)) ||
+        /* Codes_SRS_CONSTBUFFER_01_013: [ If customFreeFunc is NULL, CONSTBUFFER_CreateWithCustomFree shall fail and return NULL. ]*/
+        (customFreeFunc == NULL)
+        )
+    {
+        LogError("Invalid arguments: unsigned char* source=%p, size_t size=%u, customFreeFunc=%p, customFreeFuncContext=%p",
+            source, (unsigned int)size, customFreeFunc, customFreeFuncContext);
+        result = NULL;
+    }
+    else
+    {
+        result = (CONSTBUFFER_HANDLE)calloc(1, sizeof(CONSTBUFFER_HANDLE_DATA));
+        if (result == NULL)
+        {
+            /* Codes_SRS_CONSTBUFFER_01_011: [ If any error occurs, CONSTBUFFER_CreateWithMoveMemory shall fail and return NULL. ]*/
+            LogError("malloc failed");
+        }
+        else
+        {
+            /* Codes_SRS_CONSTBUFFER_01_007: [ If source is non-NULL and size is 0, the source pointer shall be owned (and freed) by the newly created instance of const buffer. ]*/
+            /* Codes_SRS_CONSTBUFFER_01_008: [ CONSTBUFFER_CreateWithCustomFree shall store the source and size and return a non-NULL handle to the newly created const buffer. ]*/
+            result->alias.buffer = source;
+            result->alias.size = size;
+            result->buffer_type = CONSTBUFFER_TYPE_WITH_CUSTOM_FREE;
+
+            /* Codes_SRS_CONSTBUFFER_01_009: [ CONSTBUFFER_CreateWithCustomFree shall store customFreeFunc and customFreeFuncContext in order to use them to free the memory when the CONST buffer resources are freed. ]*/
+            result->custom_free_func = customFreeFunc;
+            result->custom_free_func_context = customFreeFuncContext;
+
+            /* Codes_SRS_CONSTBUFFER_01_010: [ The non-NULL handle returned by CONSTBUFFER_CreateWithCustomFree shall have its ref count set to 1. ]*/
+            INIT_REF_VAR(result->count);
+        }
+    }
+
+    return result;
+}
+
+IMPLEMENT_MOCKABLE_FUNCTION(, CONSTBUFFER_HANDLE, CONSTBUFFER_CreateFromOffsetAndSize, CONSTBUFFER_HANDLE, handle, size_t, offset, size_t, size)
+{
+    CONSTBUFFER_HANDLE result;
+
+    if (
+        /*Codes_SRS_CONSTBUFFER_02_025: [ If handle is NULL then CONSTBUFFER_CreateFromOffsetAndSize shall fail and return NULL. ]*/
+        (handle == NULL) ||
+        /*Codes_SRS_CONSTBUFFER_02_026: [ If offset is greater than or equal to handles's size then CONSTBUFFER_CreateFromOffsetAndSize shall fail and return NULL. ]*/
+        (offset > handle->alias.size) ||
+        /*Codes_SRS_CONSTBUFFER_02_032: [ If there are any failures then CONSTBUFFER_CreateFromOffsetAndSize shall fail and return NULL. ]*/
+        (offset > SIZE_MAX - size) ||
+        /*Codes_SRS_CONSTBUFFER_02_027: [ If offset + size exceed handles's size then CONSTBUFFER_CreateFromOffsetAndSize shall fail and return NULL. ]*/
+        (offset + size > handle->alias.size)
+        )
+    {
+        LogError("invalid arguments CONSTBUFFER_HANDLE handle=%p, size_t offset=%zu, size_t size=%zu",
+            handle, offset, size);
+        result = NULL;
+    }
+    else
+    {
+        /*Codes_SRS_CONSTBUFFER_02_028: [ CONSTBUFFER_CreateFromOffsetAndSize shall allocate memory for a new CONSTBUFFER_HANDLE's content. ]*/
+        result = (CONSTBUFFER_HANDLE)calloc(1, sizeof(CONSTBUFFER_HANDLE_DATA));
+        if (result == NULL)
+        {
+            /*Codes_SRS_CONSTBUFFER_02_032: [ If there are any failures then CONSTBUFFER_CreateFromOffsetAndSize shall fail and return NULL. ]*/
+            LogError("failure in malloc(sizeof(CONSTBUFFER_HANDLE_DATA)=%zu)", sizeof(CONSTBUFFER_HANDLE_DATA));
+            /*return as is*/
+        }
+        else
+        {
+            result->buffer_type = CONSTBUFFER_TYPE_FROM_OFFSET_AND_SIZE;
+            result->alias.buffer = handle->alias.buffer+offset;
+            result->alias.size = size;
+
+            /*Codes_SRS_CONSTBUFFER_02_030: [ CONSTBUFFER_CreateFromOffsetAndSize shall increment the reference count of handle. ]*/
+            INC_REF_VAR(handle->count);
+            result->originalHandle = handle;
+
+            /*Codes_SRS_CONSTBUFFER_02_029: [ CONSTBUFFER_CreateFromOffsetAndSize shall set the ref count of the newly created CONSTBUFFER_HANDLE to the initial value. ]*/
+            INIT_REF_VAR(result->count);
+
+            /*Codes_SRS_CONSTBUFFER_02_031: [ CONSTBUFFER_CreateFromOffsetAndSize shall succeed and return a non-NULL value. ]*/
+        }
+    }
+    return result;
+}
+
+IMPLEMENT_MOCKABLE_FUNCTION(, void, CONSTBUFFER_IncRef, CONSTBUFFER_HANDLE, constbufferHandle)
+{
+    if (constbufferHandle == NULL)
+    {
+        /*Codes_SRS_CONSTBUFFER_02_013: [If constbufferHandle is NULL then CONSTBUFFER_IncRef shall return.]*/
+        LogError("Invalid arguments: CONSTBUFFER_HANDLE constbufferHandle=%p", constbufferHandle);
+    }
+    else
+    {
+        /*Codes_SRS_CONSTBUFFER_02_014: [Otherwise, CONSTBUFFER_IncRef shall increment the reference count.]*/
+        INC_REF_VAR(constbufferHandle->count);
+    }
+}
+
+IMPLEMENT_MOCKABLE_FUNCTION(, const CONSTBUFFER*, CONSTBUFFER_GetContent, CONSTBUFFER_HANDLE, constbufferHandle)
+{
+    const CONSTBUFFER* result;
+    if (constbufferHandle == NULL)
+    {
+        /*Codes_SRS_CONSTBUFFER_02_011: [If constbufferHandle is NULL then CONSTBUFFER_GetContent shall return NULL.]*/
+        result = NULL;
+        LogError("invalid arg");
+    }
+    else
+    {
+        /*Codes_SRS_CONSTBUFFER_02_012: [Otherwise, CONSTBUFFER_GetContent shall return a const CONSTBUFFER* that matches byte by byte the original bytes used to created the const buffer and has the same length.]*/
+        result = &(constbufferHandle->alias);
+    }
+    return result;
+}
+
+static void CONSTBUFFER_DecRef_internal(CONSTBUFFER_HANDLE constbufferHandle)
+{
+    /*Codes_SRS_CONSTBUFFER_02_016: [Otherwise, CONSTBUFFER_DecRef shall decrement the refcount on the constbufferHandle handle.]*/
+    if (DEC_REF_VAR(constbufferHandle->count) == DEC_RETURN_ZERO)
+    {
+        if (constbufferHandle->buffer_type == CONSTBUFFER_TYPE_MEMORY_MOVED)
+        {
+            free((void*)constbufferHandle->alias.buffer);
+        }
+        else if (constbufferHandle->buffer_type == CONSTBUFFER_TYPE_WITH_CUSTOM_FREE)
+        {
+            /* Codes_SRS_CONSTBUFFER_01_012: [ If the buffer was created by calling CONSTBUFFER_CreateWithCustomFree, the customFreeFunc function shall be called to free the memory, while passed customFreeFuncContext as argument. ]*/
+            constbufferHandle->custom_free_func(constbufferHandle->custom_free_func_context);
+        }
+        /*Codes_SRS_CONSTBUFFER_02_024: [ If the constbufferHandle was created by calling CONSTBUFFER_CreateFromOffsetAndSize then CONSTBUFFER_DecRef shall decrement the ref count of the original handle passed to CONSTBUFFER_CreateFromOffsetAndSize. ]*/
+        else if (constbufferHandle->buffer_type == CONSTBUFFER_TYPE_FROM_OFFSET_AND_SIZE)
+        {
+            CONSTBUFFER_DecRef_internal(constbufferHandle->originalHandle);
+        }
+
+        /*Codes_SRS_CONSTBUFFER_02_017: [If the refcount reaches zero, then CONSTBUFFER_DecRef shall deallocate all resources used by the CONSTBUFFER_HANDLE.]*/
+        free(constbufferHandle);
+    }
+}
+
+IMPLEMENT_MOCKABLE_FUNCTION(, void, CONSTBUFFER_DecRef, CONSTBUFFER_HANDLE, constbufferHandle)
+{
+    if (constbufferHandle == NULL)
+    {
+        /*Codes_SRS_CONSTBUFFER_02_015: [If constbufferHandle is NULL then CONSTBUFFER_DecRef shall do nothing.]*/
+        LogError("Invalid arguments: CONSTBUFFER_HANDLE constbufferHandle=%p", constbufferHandle);
+    }
+    else
+    {
+        CONSTBUFFER_DecRef_internal(constbufferHandle);
+    }
+}
+
+
+IMPLEMENT_MOCKABLE_FUNCTION(, bool, CONSTBUFFER_HANDLE_contain_same, CONSTBUFFER_HANDLE, left, CONSTBUFFER_HANDLE, right)
+{
+    bool result;
+    if (left == NULL)
+    {
+        if (right == NULL)
+        {
+            /*Codes_SRS_CONSTBUFFER_02_018: [ If left is NULL and right is NULL then CONSTBUFFER_HANDLE_contain_same shall return true. ]*/
+            result = true;
+        }
+        else
+        {
+            /*Codes_SRS_CONSTBUFFER_02_019: [ If left is NULL and right is not NULL then CONSTBUFFER_HANDLE_contain_same shall return false. ]*/
+            result = false;
+        }
+    }
+    else
+    {
+        if (right == NULL)
+        {
+            /*Codes_SRS_CONSTBUFFER_02_020: [ If left is not NULL and right is NULL then CONSTBUFFER_HANDLE_contain_same shall return false. ]*/
+            result = false;
+        }
+        else
+        {
+            if (left->alias.size != right->alias.size)
+            {
+                /*Codes_SRS_CONSTBUFFER_02_021: [ If left's size is different than right's size then CONSTBUFFER_HANDLE_contain_same shall return false. ]*/
+                result = false;
+            }
+            else
+            {
+                if (memcmp(left->alias.buffer, right->alias.buffer, left->alias.size) != 0)
+                {
+                    /*Codes_SRS_CONSTBUFFER_02_022: [ If left's buffer is contains different bytes than rights's buffer then CONSTBUFFER_HANDLE_contain_same shall return false. ]*/
+                    result = false;
+                }
+                else
+                {
+                    /*Codes_SRS_CONSTBUFFER_02_023: [ CONSTBUFFER_HANDLE_contain_same shall return true. ]*/
+                    result = true;
+                }
+            }
+        }
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/constmap.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/constmap.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/constmap.c	(revision 453)
@@ -0,0 +1,226 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/map.h"
+#include "azure_c_shared_utility/constmap.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/refcount.h"
+
+MU_DEFINE_ENUM_STRINGS(CONSTMAP_RESULT, CONSTMAP_RESULT_VALUES);
+
+typedef struct CONSTMAP_HANDLE_DATA_TAG
+{
+    MAP_HANDLE map;
+} CONSTMAP_HANDLE_DATA;
+
+DEFINE_REFCOUNT_TYPE(CONSTMAP_HANDLE_DATA);
+
+#define LOG_CONSTMAP_ERROR(result) LogError("result = %" PRI_MU_ENUM "", MU_ENUM_VALUE(CONSTMAP_RESULT, (result)));
+
+CONSTMAP_HANDLE ConstMap_Create(MAP_HANDLE sourceMap)
+{
+    CONSTMAP_HANDLE_DATA* result = REFCOUNT_TYPE_CREATE(CONSTMAP_HANDLE_DATA);
+
+    if (result == NULL)
+    {
+        LOG_CONSTMAP_ERROR(CONSTMAP_INVALIDARG);
+    }
+    else
+    {
+        /*Codes_SRS_CONSTMAP_17_048: [ConstMap_Create shall accept any non-NULL MAP_HANDLE as input.]*/
+        /*Codes_SRS_CONSTMAP_17_001: [ConstMap_Create shall create an immutable map, populated by the key, value pairs in the source map.]*/
+        result->map = Map_Clone(sourceMap);
+        if (result->map == NULL)
+        {
+            LOG_CONSTMAP_ERROR(CONSTMAP_ERROR);
+            REFCOUNT_TYPE_DESTROY(CONSTMAP_HANDLE_DATA, result);
+            /*Codes_SRS_CONSTMAP_17_002: [If during creation there are any errors, then ConstMap_Create shall return NULL.]*/
+            result = NULL;
+        }
+    }
+    /*Codes_SRS_CONSTMAP_17_003: [Otherwise, it shall return a non-NULL handle that can be used in subsequent calls.]*/
+    return (CONSTMAP_HANDLE)result;
+}
+
+void ConstMap_Destroy(CONSTMAP_HANDLE handle)
+{
+    /*Codes_SRS_CONSTMAP_17_005: [If parameter handle is NULL then ConstMap_Destroy shall take no action.]*/
+    if (handle == NULL)
+    {
+        LOG_CONSTMAP_ERROR(CONSTMAP_INVALIDARG);
+    }
+    else
+    {
+        /*Codes_SRS_CONSTMAP_17_049: [ConstMap_Destroy shall decrement the internal reference count of the immutable map.]*/
+        if (DEC_REF(CONSTMAP_HANDLE_DATA, handle) == DEC_RETURN_ZERO)
+        {
+            /*Codes_SRS_CONSTMAP_17_004: [If the reference count is zero, ConstMap_Destroy shall release all resources associated with the immutable map.]*/
+            Map_Destroy(((CONSTMAP_HANDLE_DATA *)handle)->map);
+            REFCOUNT_TYPE_DESTROY(CONSTMAP_HANDLE_DATA, handle);
+        }
+
+    }
+}
+
+CONSTMAP_HANDLE ConstMap_Clone(CONSTMAP_HANDLE handle)
+{
+    /*Codes_SRS_CONSTMAP_17_038: [ConstMap_Clone returns NULL if parameter handle is NULL.] */
+    if (handle == NULL)
+    {
+        LOG_CONSTMAP_ERROR(CONSTMAP_INVALIDARG);
+    }
+    else
+    {
+        /*Codes_SRS_CONSTMAP_17_039: [ConstMap_Clone shall increase the internal reference count of the immutable map indicated by parameter handle]*/
+        /*Codes_SRS_CONSTMAP_17_050: [ConstMap_Clone shall return the non-NULL handle. ]*/
+        INC_REF(CONSTMAP_HANDLE_DATA, handle);
+    }
+    return (handle);
+}
+
+static CONSTMAP_RESULT ConstMap_ErrorConvert(MAP_RESULT mapResult)
+{
+    CONSTMAP_RESULT result;
+    switch (mapResult)
+    {
+        case MAP_OK:
+            result = CONSTMAP_OK;
+            break;
+        case MAP_INVALIDARG:
+            result = CONSTMAP_INVALIDARG;
+            break;
+        case MAP_KEYNOTFOUND:
+            result = CONSTMAP_KEYNOTFOUND;
+            break;
+        default:
+            result = CONSTMAP_ERROR;
+            break;
+    }
+    return result;
+}
+
+MAP_HANDLE ConstMap_CloneWriteable(CONSTMAP_HANDLE handle)
+{
+    MAP_HANDLE result = NULL;
+    if (handle == NULL)
+    {
+        /*Codes_SRS_CONSTMAP_17_051: [ConstMap_CloneWriteable returns NULL if parameter handle is NULL. ]*/
+        LOG_CONSTMAP_ERROR(CONSTMAP_INVALIDARG);
+    }
+    else
+    {
+        /*Codes_SRS_CONSTMAP_17_052: [ConstMap_CloneWriteable shall create a new, writeable map, populated by the key, value pairs in the parameter defined by handle.]*/
+        /*Codes_SRS_CONSTMAP_17_053: [If during cloning, any operation fails, then ConstMap_CloneWriteableap_Clone shall return NULL.]*/
+        /*Codes_SRS_CONSTMAP_17_054: [Otherwise, ConstMap_CloneWriteable shall return a non-NULL handle that can be used in subsequent calls.]*/
+        result = Map_Clone(((CONSTMAP_HANDLE_DATA *)handle)->map);
+    }
+    return result;
+}
+
+bool ConstMap_ContainsKey(CONSTMAP_HANDLE handle, const char* key )
+{
+    bool keyExists = false;
+    if (handle == NULL)
+    {
+        /*Codes_SRS_CONSTMAP_17_024: [If parameter handle or key are NULL then ConstMap_ContainsKey shall return false.]*/
+        LOG_CONSTMAP_ERROR(CONSTMAP_INVALIDARG);
+    }
+    else
+    {
+        if (key == NULL)
+        {
+            LOG_CONSTMAP_ERROR(CONSTMAP_INVALIDARG);
+        }
+        else
+        {
+            /*Codes_SRS_CONSTMAP_17_025: [Otherwise if a key exists then ConstMap_ContainsKey shall return true.]*/
+            MAP_RESULT mapResult = Map_ContainsKey(((CONSTMAP_HANDLE_DATA *)handle)->map, key, &keyExists);
+            if (mapResult != MAP_OK)
+            {
+                /*Codes_SRS_CONSTMAP_17_026: [If a key doesn't exist, then ConstMap_ContainsKey shall return false.]*/
+                keyExists = false;
+                LOG_CONSTMAP_ERROR(ConstMap_ErrorConvert(mapResult));
+            }
+        }
+    }
+    return keyExists;
+}
+
+bool ConstMap_ContainsValue(CONSTMAP_HANDLE handle, const char* value)
+{
+    bool valueExists = false;
+    if (handle == NULL)
+    {
+        /*Codes_SRS_CONSTMAP_17_027: [If parameter handle or value is NULL then ConstMap_ContainsValue shall return false.]*/
+        LOG_CONSTMAP_ERROR(CONSTMAP_INVALIDARG);
+    }
+    else
+    {
+        if (value == NULL)
+        {
+            LOG_CONSTMAP_ERROR(CONSTMAP_INVALIDARG);
+        }
+        else
+        {
+            /*Codes_SRS_CONSTMAP_17_028: [Otherwise, if a pair has its value equal to the parameter value, the ConstMap_ContainsValue shall return true.]*/
+            MAP_RESULT mapResult = Map_ContainsValue(((CONSTMAP_HANDLE_DATA *)handle)->map, value, &valueExists);
+            if (mapResult != MAP_OK)
+            {
+                /*Codes_SRS_CONSTMAP_17_029: [Otherwise, if such a does not exist, then ConstMap_ContainsValue shall return false.]*/
+                LOG_CONSTMAP_ERROR(ConstMap_ErrorConvert(mapResult));
+            }
+        }
+    }
+    return valueExists;
+}
+
+const char* ConstMap_GetValue(CONSTMAP_HANDLE handle, const char* key)
+{
+    const char* value = NULL;
+
+    if (handle == NULL)
+    {
+        /*Codes_SRS_CONSTMAP_17_040: [If parameter handle or key is NULL then ConstMap_GetValue returns NULL.]*/
+        LOG_CONSTMAP_ERROR(CONSTMAP_INVALIDARG);
+    }
+    else
+    {
+        if (key == NULL)
+        {
+            /*Codes_SRS_CONSTMAP_17_040: [If parameter handle or key is NULL then ConstMap_GetValue returns NULL.]*/
+            LOG_CONSTMAP_ERROR(CONSTMAP_INVALIDARG);
+        }
+        else
+        {
+            /*Codes_SRS_CONSTMAP_17_041: [If the key is not found, then ConstMap_GetValue returns NULL.]*/
+            /*Codes_SRS_CONSTMAP_17_042: [Otherwise, ConstMap_GetValue returns the key's value.]*/
+            value = Map_GetValueFromKey(((CONSTMAP_HANDLE_DATA *)handle)->map, key);
+        }
+    }
+    return value;
+}
+
+CONSTMAP_RESULT ConstMap_GetInternals(CONSTMAP_HANDLE handle, const char*const** keys, const char*const** values, size_t* count)
+{
+    CONSTMAP_RESULT result;
+    if (handle == NULL)
+    {
+        /*Codes_SRS_CONSTMAP_17_046: [If parameter handle, keys, values or count is NULL then ConstMap_GetInternals shall return CONSTMAP_INVALIDARG.]*/
+        result = CONSTMAP_INVALIDARG;
+        LOG_CONSTMAP_ERROR(result);
+    }
+    else
+    {
+        /*Codes_SRS_CONSTMAP_17_043: [ConstMap_GetInternals shall produce in *keys a pointer to an array of const char* having all the keys stored so far by the map.]
+         *Codes_SRS_CONSTMAP_17_044: [ConstMap_GetInternals shall produce in *values a pointer to an array of const char* having all the values stored so far by the map.]
+         *Codes_SRS_CONSTMAP_17_045: [ ConstMap_GetInternals shall produce in *count the number of stored keys and values.]
+         */
+        MAP_RESULT mapResult = Map_GetInternals(((CONSTMAP_HANDLE_DATA *)handle)->map, keys, values, count);
+        result = ConstMap_ErrorConvert(mapResult);
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/crt_abstractions.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/crt_abstractions.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/crt_abstractions.c	(revision 453)
@@ -0,0 +1,837 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#define __STDC_WANT_LIB_EXT1__ 1
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <limits.h>
+#include <float.h>
+#include <math.h>
+#include <errno.h>
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+
+// VS 2008 does not have INFINITY and all the nice goodies...
+#if defined (TIZENRT)
+#define DEFINE_INFINITY 1
+#else
+
+#if defined _MSC_VER
+#if _MSC_VER <= 1500
+#define DEFINE_INFINITY 1
+#endif
+#endif
+#endif
+
+#if defined DEFINE_INFINITY
+
+#pragma warning(disable:4756 4056) // warning C4756: overflow in constant arithmetic
+
+// These defines are missing in math.h for WEC2013 SDK
+#ifndef _HUGE_ENUF
+#define _HUGE_ENUF  1e+300  // _HUGE_ENUF*_HUGE_ENUF must overflow
+#endif
+
+#define INFINITY   ((float)(_HUGE_ENUF * _HUGE_ENUF))
+#define HUGE_VALF  ((float)INFINITY)
+#define HUGE_VALL  ((long double)INFINITY)
+#define NAN        ((float)(INFINITY * 0.0F))
+#endif
+
+#if defined (_MSC_VER) || defined (MINGW_HAS_SECURE_API)
+#else
+
+/*Codes_SRS_CRT_ABSTRACTIONS_99_008: [strcat_s shall append the src to dst and terminates the resulting string with a null character.]*/
+int strcat_s(char* dst, size_t dstSizeInBytes, const char* src)
+{
+    int result;
+    /*Codes_SRS_CRT_ABSTRACTIONS_99_004: [If dst is NULL or unterminated, the error code returned shall be EINVAL & dst shall not be modified.]*/
+    if (dst == NULL)
+    {
+        result = EINVAL;
+    }
+    /*Codes_SRS_CRT_ABSTRACTIONS_99_005: [If src is NULL, the error code returned shall be EINVAL and dst[0] shall be set to 0.]*/
+    else if (src == NULL)
+    {
+        dst[0] = '\0';
+        result = EINVAL;
+    }
+    else
+    {
+        /*Codes_SRS_CRT_ABSTRACTIONS_99_006: [If the dstSizeInBytes is 0 or smaller than the required size for dst & src, the error code returned shall be ERANGE & dst[0] set to 0.]*/
+        if (dstSizeInBytes == 0)
+        {
+            result = ERANGE;
+            dst[0] = '\0';
+        }
+        else
+        {
+            size_t dstStrLen = 0;
+            size_t src_len = strlen(src);
+#ifdef __STDC_LIB_EXT1__
+            dstStrLen = strnlen_s(dst, dstSizeInBytes);
+#else
+            size_t i;
+            for(i=0; (i < dstSizeInBytes) && (dst[i]!= '\0'); i++)
+            {
+            }
+            dstStrLen = i;
+#endif
+            /*Codes_SRS_CRT_ABSTRACTIONS_99_004: [If dst is NULL or unterminated, the error code returned shall be EINVAL & dst shall not be modified.]*/
+            if (dstSizeInBytes == dstStrLen) /* this means the dst string is not terminated*/
+            {
+                result = EINVAL;
+            }
+            // If we are instructed to write too much data to the buffer
+            // return ERANGE
+            else if ((src_len + dstStrLen) >= dstSizeInBytes)
+            {
+                dst[0] = '\0';
+                result = ERANGE;
+            }
+            else
+            {
+                // memcpy should at most copy the result of strlen(src) or there may be
+                // some issues with copying unwanted memory
+                size_t bytes_to_cpy = dstSizeInBytes - dstStrLen;
+                if (bytes_to_cpy > src_len)
+                {
+                    bytes_to_cpy = src_len;
+                }
+
+                /*Codes_SRS_CRT_ABSTRACTIONS_99_009: [The initial character of src shall overwrite the terminating null character of dst.]*/
+                if (memcpy(&dst[dstStrLen], src, bytes_to_cpy) == NULL)
+                /*Codes_SRS_CRT_ABSTRACTIONS_99_006: [If the dstSizeInBytes is 0 or smaller than the required size for dst & src, the error code returned shall be ERANGE & dst[0] set to 0.]*/
+                {
+                    dst[0] = '\0';
+                    result = ERANGE;
+                }
+                else
+                {
+                    /*Codes_SRS_CRT_ABSTRACTIONS_99_003: [strcat_s shall return Zero upon success.]*/
+                    dst[dstStrLen+bytes_to_cpy] = '\0';
+                    result = 0;
+                }
+            }
+        }
+    }
+    return result;
+}
+
+/*Codes_SRS_CRT_ABSTRACTIONS_99_025: [strncpy_s shall copy the first N characters of src to dst, where N is the lesser of MaxCount and the length of src.]*/
+int strncpy_s(char* dst, size_t dstSizeInBytes, const char* src, size_t maxCount)
+{
+    int result;
+    int truncationFlag = 0;
+    /*Codes_SRS_CRT_ABSTRACTIONS_99_020: [If dst is NULL, the error code returned shall be EINVAL and dst shall not be modified.]*/
+    if (dst == NULL)
+    {
+        result = EINVAL;
+    }
+    /*Codes_SRS_CRT_ABSTRACTIONS_99_021: [If src is NULL, the error code returned shall be EINVAL and dst[0] shall be set to 0.]*/
+    else if (src == NULL)
+    {
+        dst[0] = '\0';
+        result = EINVAL;
+    }
+    /*Codes_SRS_CRT_ABSTRACTIONS_99_022: [If the dstSizeInBytes is 0, the error code returned shall be EINVAL and dst shall not be modified.]*/
+    else if (dstSizeInBytes == 0)
+    {
+        result = EINVAL;
+    }
+    else
+    {
+        size_t srcLength = strlen(src);
+        if (maxCount != _TRUNCATE)
+        {
+            /*Codes_SRS_CRT_ABSTRACTIONS_99_041: [If those N characters will fit within dst (whose size is given as dstSizeInBytes) and still leave room for a null terminator, then those characters shall be copied and a terminating null is appended; otherwise, strDest[0] is set to the null character and ERANGE error code returned.]*/
+            if (srcLength > maxCount)
+            {
+                srcLength = maxCount;
+            }
+
+            /*Codes_SRS_CRT_ABSTRACTIONS_99_023: [If dst is not NULL & dstSizeInBytes is smaller than the required size for the src string, the error code returned shall be ERANGE and dst[0] shall be set to 0.]*/
+            if (srcLength + 1 > dstSizeInBytes)
+            {
+                dst[0] = '\0';
+                result = ERANGE;
+            }
+            else
+            {
+                (void)memcpy(dst, src, srcLength);
+                dst[srcLength] = '\0';
+                /*Codes_SRS_CRT_ABSTRACTIONS_99_018: [strncpy_s shall return Zero upon success]*/
+                result = 0;
+            }
+        }
+        /*Codes_SRS_CRT_ABSTRACTIONS_99_026: [If MaxCount is _TRUNCATE (defined as -1), then as much of src as will fit into dst shall be copied while still leaving room for the terminating null to be appended.]*/
+        else
+        {
+            if (srcLength + 1 > dstSizeInBytes )
+            {
+                srcLength = dstSizeInBytes - 1;
+                truncationFlag = 1;
+            }
+            (void)memcpy(dst, src, srcLength);
+            dst[srcLength] = '\0';
+            result = 0;
+        }
+    }
+
+    /*Codes_SRS_CRT_ABSTRACTIONS_99_019: [If truncation occurred as a result of the copy, the error code returned shall be STRUNCATE.]*/
+    if (truncationFlag == 1)
+    {
+        result = STRUNCATE;
+    }
+
+    return result;
+}
+
+/* Codes_SRS_CRT_ABSTRACTIONS_99_016: [strcpy_s shall copy the contents in the address of src, including the terminating null character, to the location that's specified by dst.]*/
+int strcpy_s(char* dst, size_t dstSizeInBytes, const char* src)
+{
+    int result;
+
+    /* Codes_SRS_CRT_ABSTRACTIONS_99_012: [If dst is NULL, the error code returned shall be EINVAL & dst shall not be modified.]*/
+    if (dst == NULL)
+    {
+        result = EINVAL;
+    }
+    /* Codes_SRS_CRT_ABSTRACTIONS_99_013: [If src is NULL, the error code returned shall be EINVAL and dst[0] shall be set to 0.]*/
+    else if (src == NULL)
+    {
+        dst[0] = '\0';
+        result = EINVAL;
+    }
+    /* Codes_SRS_CRT_ABSTRACTIONS_99_014: [If the dstSizeInBytes is 0 or smaller than the required size for the src string, the error code returned shall be ERANGE & dst[0] set to 0.]*/
+    else if (dstSizeInBytes == 0)
+    {
+        dst[0] = '\0';
+        result = ERANGE;
+    }
+    else
+    {
+        size_t neededBuffer = strlen(src);
+        /* Codes_SRS_CRT_ABSTRACTIONS_99_014: [If the dstSizeInBytes is 0 or smaller than the required size for the src string, the error code returned shall be ERANGE & dst[0] set to 0.]*/
+        if (neededBuffer + 1 > dstSizeInBytes)
+        {
+            dst[0] = '\0';
+            result = ERANGE;
+        }
+        else
+        {
+            (void)memcpy(dst, src, neededBuffer + 1);
+            /*Codes_SRS_CRT_ABSTRACTIONS_99_011: [strcpy_s shall return Zero upon success]*/
+            result = 0;
+        }
+    }
+
+    return result;
+}
+
+/*Codes_SRS_CRT_ABSTRACTIONS_99_029: [The sprintf_s function shall format and store series of characters and values in dst.  Each argument (if any) is converted and output according to the corresponding Format Specification in the format variable.]*/
+/*Codes_SRS_CRT_ABSTRACTIONS_99_031: [A null character is appended after the last character written.]*/
+int sprintf_s(char* dst, size_t dstSizeInBytes, const char* format, ...)
+{
+    int result;
+    /*Codes_SRS_CRT_ABSTRACTIONS_99_028: [If dst or format is a null pointer, sprintf_s shall return -1 and set errno to EINVAL]*/
+    if ((dst == NULL) ||
+        (format == NULL))
+    {
+        errno = EINVAL;
+        result = -1;
+    }
+    else
+    {
+        /*Codes_SRS_CRT_ABSTRACTIONS_99_033: [sprintf_s shall check the format string for valid formatting characters.  If the check fails, the function returns -1.]*/
+
+#if defined _MSC_VER
+#error crt_abstractions is not provided for Microsoft Compilers
+#else
+        /*not Microsoft compiler... */
+#if defined (__STDC_VERSION__) || (__cplusplus)
+#if ( \
+        ((__STDC_VERSION__  == 199901L) || (__STDC_VERSION__ == 201000L) || (__STDC_VERSION__ == 201112L) || (__STDC_VERSION__ == 201710L)) || \
+        (defined __cplusplus) \
+    )
+        /*C99 compiler*/
+        va_list args;
+        va_start(args, format);
+        /*Codes_SRS_CRT_ABSTRACTIONS_99_027: [sprintf_s shall return the number of characters stored in dst upon success.  This number shall not include the terminating null character.]*/
+        result = vsnprintf(dst, dstSizeInBytes, format, args);
+        va_end(args);
+
+        /*C99: Thus, the null-terminated output has been completely written if and only if the returned value is nonnegative and less than n*/
+        if (result < 0)
+        {
+            result = -1;
+        }
+        else if ((size_t)result >= dstSizeInBytes)
+        {
+            /*Codes_SRS_CRT_ABSTRACTIONS_99_034: [If the dst buffer is too small for the text being printed, then dst is set to an empty string and the function shall return -1.]*/
+            dst[0] = '\0';
+            result = -1;
+        }
+        else
+        {
+            /*do nothing, all is fine*/
+        }
+#else
+#error STDC_VERSION defined, but of unknown value; unable to sprinf_s, or provide own implementation
+#endif
+#else
+#error for STDC_VERSION undefined (assumed C89), provide own implementation of sprintf_s
+#endif
+#endif
+    }
+    return result;
+}
+#endif /* _MSC_VER || MINGW_HAS_SECURE_API */
+
+/*Codes_SRS_CRT_ABSTRACTIONS_21_006: [The strtoull_s must use the letters from a(or A) through z(or Z) to represent the numbers between 10 to 35.]*/
+/* returns the integer value that correspond to the character 'c'. If the character is invalid, it returns -1. */
+#define DIGIT_VAL(c)         (((c>='0') && (c<='9')) ? (c-'0') : ((c>='a') && (c<='z')) ? (c-'a'+10) : ((c>='A') && (c<='Z')) ? (c-'A'+10) : -1)
+#define IN_BASE_RANGE(d, b)  ((d >= 0) && (d < b))
+
+/*Codes_SRS_CRT_ABSTRACTIONS_21_010: [The white-space must be one of the characters ' ', '\f', '\n', '\r', '\t', '\v'.]*/
+#define IS_SPACE(c)           (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
+
+/*Codes_SRS_CRT_ABSTRACTIONS_21_001: [The strtoull_s must convert the initial portion of the string pointed to by nptr to unsigned long long int representation.]*/
+/*Codes_SRS_CRT_ABSTRACTIONS_21_002: [The strtoull_s must resembling an integer represented in some radix determined by the value of base.]*/
+/*Codes_SRS_CRT_ABSTRACTIONS_21_003: [The strtoull_s must return the integer that represents the value in the initial part of the string. If any.]*/
+unsigned long long strtoull_s(const char* nptr, char** endptr, int base)
+{
+    unsigned long long result = 0ULL;
+    bool validStr = true;
+    char* runner = (char*)nptr;
+    bool isNegative = false;
+    int digitVal;
+
+    /*Codes_SRS_CRT_ABSTRACTIONS_21_005: [The strtoull_s must convert number using base 2 to 36.]*/
+    /*Codes_SRS_CRT_ABSTRACTIONS_21_012: [If the subject sequence is empty or does not have the expected form, the strtoull_s must not perform any conversion; the value of nptr is stored in the object pointed to by endptr, provided that endptr is not a NULL pointer.]*/
+    /*Codes_SRS_CRT_ABSTRACTIONS_21_013: [If no conversion could be performed, the strtoull_s returns the value 0L.]*/
+    /*Codes_SRS_CRT_ABSTRACTIONS_21_035: [If the nptr is NULL, the strtoull_s must **not** perform any conversion and must returns 0L; endptr must receive NULL, provided that endptr is not a NULL pointer.]*/
+        if (((base >= 2) || (base == 0)) && (base <= 36) && (runner != NULL))
+    {
+        /*Codes_SRS_CRT_ABSTRACTIONS_21_011: [The valid sequence starts after the first non-white-space character, followed by an optional positive or negative sign, a number or a letter(depending of the base).]*/
+        /*Codes_SRS_CRT_ABSTRACTIONS_21_010: [The white-space must be one of the characters ' ', '\f', '\n', '\r', '\t', '\v'.]*/
+        while (IS_SPACE(*runner))
+        {
+            runner++;
+        }
+        if ((*runner) == '+')
+        {
+            runner++;
+        }
+        else if ((*runner) == '-')
+        {
+            /*Codes_SRS_CRT_ABSTRACTIONS_21_038: [If the subject sequence starts with a negative sign, the strtoull_s will convert it to the posive representation of the negative value.]*/
+            isNegative = true;
+            runner++;
+        }
+
+        if ((*runner) == '0')
+        {
+            if ((*(runner+1) == 'x') || (*(runner+1) == 'X'))
+            {
+                /*Codes_SRS_CRT_ABSTRACTIONS_21_008: [If the base is 0 and '0x' or '0X' precedes the number, strtoull_s must convert to a hexadecimal (base 16).]*/
+                /* hexadecimal... */
+                if ((base == 0) || (base == 16))
+                {
+                    base = 16;
+                    runner += 2;
+                }
+            }
+            else if((base == 0) || (base == 8))
+            {
+                /*Codes_SRS_CRT_ABSTRACTIONS_21_009: [If the base is 0 and '0' precedes the number, strtoull_s must convert to an octal (base 8).]*/
+                /* octal... */
+                base = 8;
+                runner++;
+            }
+        }
+
+        if(base == 0)
+        {
+            /*Codes_SRS_CRT_ABSTRACTIONS_21_007: [If the base is 0 and no special chars precedes the number, strtoull_s must convert to a decimal (base 10).]*/
+            /* decimal... */
+            base = 10;
+        }
+
+        digitVal = DIGIT_VAL(*runner);
+        if (validStr && IN_BASE_RANGE(digitVal, base))
+        {
+            errno = 0;
+            do
+            {
+                if (((ULLONG_MAX - digitVal) / base) < result)
+                {
+                    /*Codes_SRS_CRT_ABSTRACTIONS_21_014: [If the correct value is outside the range, the strtoull_s returns the value ULLONG_MAX, and errno will receive the value ERANGE.]*/
+                    /* overflow... */
+                    result = ULLONG_MAX;
+                    errno = ERANGE;
+                }
+                else
+                {
+                    result = result * base + digitVal;
+                }
+                runner++;
+                digitVal = DIGIT_VAL(*runner);
+            } while (IN_BASE_RANGE(digitVal, base));
+        }
+        else
+        {
+            runner = (char*)nptr;
+        }
+    }
+
+    /*Codes_SRS_CRT_ABSTRACTIONS_21_004: [The strtoull_s must return in endptr a final string of one or more unrecognized characters, including the terminating null character of the input string.]*/
+    if (endptr != NULL)
+    {
+        (*endptr) = (char*)runner;
+    }
+
+    /*Codes_SRS_CRT_ABSTRACTIONS_21_038: [If the subject sequence starts with a negative sign, the strtoull_s will convert it to the posive representation of the negative value.]*/
+    if (isNegative)
+    {
+        result = ULLONG_MAX - result + 1;
+    }
+
+    return result;
+}
+
+/*Codes_SRS_CRT_ABSTRACTIONS_21_023: [If the string is 'INF' of 'INFINITY' (ignoring case), the strtof_s must return the INFINITY value for float.]*/
+/*Codes_SRS_CRT_ABSTRACTIONS_21_024: [If the string is 'NAN' or 'NAN(...)' (ignoring case), the strtof_s must return 0.0f and points endptr to the first character after the 'NAN' sequence.]*/
+/*Codes_SRS_CRT_ABSTRACTIONS_21_033: [If the string is 'INF' of 'INFINITY' (ignoring case), the strtold_s must return the INFINITY value for long double.]*/
+/*Codes_SRS_CRT_ABSTRACTIONS_21_034: [If the string is 'NAN' or 'NAN(...)' (ignoring case), the strtold_s must return 0.0 and points endptr to the first character after the 'NAN' sequence.]*/
+static int substricmp(const char* nptr, const char* subsrt)
+{
+    int result = 0;
+    while (((*subsrt) != '\0') && (result == 0))
+    {
+        result = TOUPPER(*nptr) - TOUPPER(*subsrt);
+        nptr++;
+        subsrt++;
+    }
+    return result;
+}
+
+/*Codes_SRS_CRT_ABSTRACTIONS_21_023: [If the string is 'INF' of 'INFINITY' (ignoring case), the strtof_s must return the INFINITY value for float.]*/
+/*Codes_SRS_CRT_ABSTRACTIONS_21_033: [If the string is 'INF' of 'INFINITY' (ignoring case), the strtold_s must return the INFINITY value for long double.]*/
+static bool isInfinity(const char** endptr)
+{
+    bool result = false;
+    if (substricmp((*endptr), "INF") == 0)
+    {
+        (*endptr) += 3;
+        result = true;
+        if (substricmp((*endptr), "INITY") == 0)
+        {
+            (*endptr) += 5;
+        }
+    }
+    return result;
+}
+
+/*Codes_SRS_CRT_ABSTRACTIONS_21_024: [If the string is 'NAN' or 'NAN(...)' (ignoring case), the strtof_s must return 0.0f and points endptr to the first character after the 'NAN' sequence.]*/
+/*Codes_SRS_CRT_ABSTRACTIONS_21_034: [If the string is 'NAN' or 'NAN(...)' (ignoring case), the strtold_s must return 0.0 and points endptr to the first character after the 'NAN' sequence.]*/
+static bool isNaN(const char** endptr)
+{
+    const char* runner = (*endptr);
+    bool result = false;
+    if (substricmp(runner, "NAN") == 0)
+    {
+        runner += 3;
+        result = true;
+        if ((*runner) == '(')
+        {
+            do
+            {
+                runner++;
+            } while (((*runner) != '\0') && ((*runner) != ')'));
+            if ((*runner) == ')')
+                runner++;
+            else
+                result = false;
+        }
+    }
+    if (result)
+        (*endptr) = runner;
+    return result;
+}
+
+#define FLOAT_STRING_TYPE_VALUES    \
+            FST_INFINITY,           \
+            FST_NAN,                \
+            FST_NUMBER,             \
+            FST_OVERFLOW,           \
+            FST_ERROR
+
+MU_DEFINE_ENUM(FLOAT_STRING_TYPE, FLOAT_STRING_TYPE_VALUES);
+
+static FLOAT_STRING_TYPE splitFloatString(const char* nptr, char** endptr, int *signal, double *fraction, int *exponential)
+{
+    FLOAT_STRING_TYPE result = FST_ERROR;
+
+    unsigned long long ullInteger = 0;
+    unsigned long long ullFraction = 0;
+    int integerSize = 0;
+    int fractionSize = 0;
+    char* startptr;
+
+    (*endptr) = (char*)nptr;
+
+    /*Codes_SRS_CRT_ABSTRACTIONS_21_018: [The white-space for strtof_s must be one of the characters ' ', '\f', '\n', '\r', '\t', '\v'.]*/
+    /*Codes_SRS_CRT_ABSTRACTIONS_21_028: [The white-space for strtold_s must be one of the characters ' ', '\f', '\n', '\r', '\t', '\v'.]*/
+    while (IS_SPACE(**endptr))
+    {
+        (*endptr)++;
+    }
+
+    /*Codes_SRS_CRT_ABSTRACTIONS_21_019: [The valid sequence for strtof_s starts after the first non-white - space character, followed by an optional positive or negative sign, a number, 'INF', or 'NAN' (ignoring case).]*/
+    /*Codes_SRS_CRT_ABSTRACTIONS_21_029: [The valid sequence for strtold_s starts after the first non-white - space character, followed by an optional positive or negative sign, a number, 'INF', or 'NAN' (ignoring case).]*/
+    (*signal) = +1;
+    if ((**endptr) == '+')
+    {
+        (*endptr)++;
+    }
+    else if ((**endptr) == '-')
+    {
+        (*signal) = -1;
+        (*endptr)++;
+    }
+
+    /*Codes_SRS_CRT_ABSTRACTIONS_21_023: [If the string is 'INF' of 'INFINITY' (ignoring case), the strtof_s must return the INFINITY value for float.]*/
+    /*Codes_SRS_CRT_ABSTRACTIONS_21_033: [If the string is 'INF' of 'INFINITY' (ignoring case), the strtold_s must return the INFINITY value for long double.]*/
+    if (isInfinity((const char**)endptr))
+    {
+        result = FST_INFINITY;
+    }
+    /*Codes_SRS_CRT_ABSTRACTIONS_21_034: [If the string is 'NAN' or 'NAN(...)' (ignoring case), the strtold_s must return 0.0 and points endptr to the first character after the 'NAN' sequence.]*/
+    /*Codes_SRS_CRT_ABSTRACTIONS_21_024: [If the string is 'NAN' or 'NAN(...)' (ignoring case), the strtof_s must return 0.0f and points endptr to the first character after the 'NAN' sequence.]*/
+    else if (isNaN((const char**)endptr))
+    {
+        result = FST_NAN;
+    }
+    else if (IN_BASE_RANGE(DIGIT_VAL(**endptr), 10))
+    {
+        result = FST_NUMBER;
+        startptr = *endptr;
+        /* integers will go to the fraction and exponential. */
+        ullInteger = strtoull_s(startptr, endptr, 10);
+        integerSize = (int)((*endptr) - startptr);
+        if ((ullInteger == ULLONG_MAX) && (errno != 0))
+        {
+            result = FST_OVERFLOW;
+        }
+
+        /* get the real fraction part, if exist. */
+        if ((**endptr) == '.')
+        {
+            startptr = (*endptr) + 1;
+            ullFraction = strtoull_s(startptr, endptr, 10);
+            fractionSize = (int)((*endptr) - startptr);
+            if ((ullFraction == ULLONG_MAX) && (errno != 0))
+            {
+                result = FST_OVERFLOW;
+            }
+        }
+
+        if (((**endptr) == 'e') || ((**endptr) == 'E'))
+        {
+            startptr = (*endptr) + 1;
+            (*exponential) = (int)strtol(startptr, endptr, 10);
+            if (((*exponential) < (DBL_MAX_10_EXP * (-1))) || ((*exponential) > DBL_MAX_10_EXP))
+            {
+                result = FST_OVERFLOW;
+            }
+        }
+        else
+        {
+            (*exponential) = 0;
+        }
+
+        if (result == FST_NUMBER)
+        {
+            /* Add ullInteger to ullFraction. */
+            ullFraction += (ullInteger * (unsigned long long)(pow(10, (double)fractionSize)));
+            (*fraction) = ((double)ullFraction / (pow(10.0f, ((double)fractionSize + (double)integerSize - 1.00))));
+
+            /* Unify rest of integerSize and fractionSize in the exponential. */
+            (*exponential) += integerSize - 1;
+        }
+    }
+
+    return result;
+}
+
+/*Codes_SRS_CRT_ABSTRACTIONS_21_015: [The strtof_s must convert the initial portion of the string pointed to by nptr to float representation.]*/
+/*Codes_SRS_CRT_ABSTRACTIONS_21_016: [The strtof_s must return the float that represents the value in the initial part of the string. If any.]*/
+float strtof_s(const char* nptr, char** endptr)
+{
+    int signal = 1;
+    double fraction;
+    int exponential;
+    char* runner = (char*)nptr;
+    double val;
+
+    /*Codes_SRS_CRT_ABSTRACTIONS_21_021: [If no conversion could be performed, the strtof_s returns the value 0.0.]*/
+    float result = 0.0;
+
+    /*Codes_SRS_CRT_ABSTRACTIONS_21_036: [**If the nptr is NULL, the strtof_s must not perform any conversion and must returns 0.0f; endptr must receive NULL, provided that endptr is not a NULL pointer.]*/
+    if (nptr != NULL)
+    {
+        switch (splitFloatString(nptr, &runner, &signal, &fraction, &exponential))
+        {
+        case FST_INFINITY:
+            /*Codes_SRS_CRT_ABSTRACTIONS_21_023: [If the string is 'INF' of 'INFINITY' (ignoring case), the strtof_s must return the INFINITY value for float.]*/
+            result = INFINITY * (signal);
+            errno = 0;
+            break;
+        case FST_NAN:
+            /*Codes_SRS_CRT_ABSTRACTIONS_21_024: [If the string is 'NAN' or 'NAN(...)' (ignoring case), the strtof_s must return 0.0f and points endptr to the first character after the 'NAN' sequence.]*/
+            result = NAN;
+            break;
+        case FST_NUMBER:
+            val = fraction * pow(10.0, (double)exponential) * (double)signal;
+            if ((val >= (FLT_MAX * (-1.0f))) && (val <= FLT_MAX))
+            {
+                /*Codes_SRS_CRT_ABSTRACTIONS_21_016: [The strtof_s must return the float that represents the value in the initial part of the string. If any.]*/
+                result = (float)val;
+            }
+            else
+            {
+                /*Codes_SRS_CRT_ABSTRACTIONS_21_022: [If the correct value is outside the range, the strtof_s returns the value plus or minus HUGE_VALF, and errno will receive the value ERANGE.]*/
+                result = HUGE_VALF * (signal);
+                errno = ERANGE;
+            }
+            break;
+        case FST_OVERFLOW:
+            /*Codes_SRS_CRT_ABSTRACTIONS_21_022: [If the correct value is outside the range, the strtof_s returns the value plus or minus HUGE_VALF, and errno will receive the value ERANGE.]*/
+            result = HUGE_VALF * (signal);
+            errno = ERANGE;
+            break;
+        default:
+            /*Codes_SRS_CRT_ABSTRACTIONS_21_020: [If the subject sequence is empty or does not have the expected form, the strtof_s must not perform any conversion and must returns 0.0f; the value of nptr is stored in the object pointed to by endptr, provided that endptr is not a NULL pointer.]*/
+            runner = (char*)nptr;
+            break;
+        }
+    }
+
+    /*Codes_SRS_CRT_ABSTRACTIONS_21_017: [The strtof_s must return in endptr a final string of one or more unrecognized characters, including the terminating null character of the input string.]*/
+    if (endptr != NULL)
+    {
+        (*endptr) = runner;
+    }
+
+    return result;
+}
+
+/*Codes_SRS_CRT_ABSTRACTIONS_21_025: [The strtold_s must convert the initial portion of the string pointed to by nptr to long double representation.]*/
+/*Codes_SRS_CRT_ABSTRACTIONS_21_026: [The strtold_s must return the long double that represents the value in the initial part of the string. If any.]*/
+long double strtold_s(const char* nptr, char** endptr)
+{
+    int signal = 1;
+    double fraction;
+    int exponential;
+    char* runner = (char*)nptr;
+
+    /*Codes_SRS_CRT_ABSTRACTIONS_21_031: [If no conversion could be performed, the strtold_s returns the value 0.0.]*/
+    long double result = 0.0;
+
+    /*Codes_SRS_CRT_ABSTRACTIONS_21_037: [If the nptr is NULL, the strtold_s must not perform any conversion and must returns 0.0; endptr must receive NULL, provided that endptr is not a NULL pointer.]*/
+    if (nptr != NULL)
+    {
+        switch (splitFloatString(nptr, &runner, &signal, &fraction, &exponential))
+        {
+        case FST_INFINITY:
+            /*Codes_SRS_CRT_ABSTRACTIONS_21_033: [If the string is 'INF' of 'INFINITY' (ignoring case), the strtold_s must return the INFINITY value for long double.]*/
+            result = (long double)INFINITY * (long double)(signal);
+            errno = 0;
+            break;
+        case FST_NAN:
+            /*Codes_SRS_CRT_ABSTRACTIONS_21_034: [If the string is 'NAN' or 'NAN(...)' (ignoring case), the strtold_s must return 0.0 and points endptr to the first character after the 'NAN' sequence.]*/
+            result = (long double)NAN;
+            break;
+        case FST_NUMBER:
+            if ((exponential != DBL_MAX_10_EXP || (fraction <= 1.7976931348623158)) &&
+                (exponential != (DBL_MAX_10_EXP * (-1)) || (fraction <= 2.2250738585072014)))
+            {
+                /*Codes_SRS_CRT_ABSTRACTIONS_21_026: [The strtold_s must return the long double that represents the value in the initial part of the string. If any.]*/
+                result = fraction * pow(10.0, (double)exponential) * (double)signal;
+            }
+            else
+            {
+                /*Codes_SRS_CRT_ABSTRACTIONS_21_032: [If the correct value is outside the range, the strtold_s returns the value plus or minus HUGE_VALL, and errno will receive the value ERANGE.]*/
+                result = (long double)HUGE_VALF * (long double)(signal);
+                errno = ERANGE;
+            }
+            break;
+        case FST_OVERFLOW:
+            /*Codes_SRS_CRT_ABSTRACTIONS_21_032: [If the correct value is outside the range, the strtold_s returns the value plus or minus HUGE_VALL, and errno will receive the value ERANGE.]*/
+            result = (long double)HUGE_VALF * (long double)(signal);
+            errno = ERANGE;
+            break;
+        default:
+            /*Codes_SRS_CRT_ABSTRACTIONS_21_030: [If the subject sequence is empty or does not have the expected form, the strtold_s must not perform any conversion and must returns 0.0; the value of nptr is stored in the object pointed to by endptr, provided that endptr is not a NULL pointer.]*/
+            runner = (char*)nptr;
+            break;
+        }
+    }
+
+    /*Codes_SRS_CRT_ABSTRACTIONS_21_027: [The strtold_s must return in endptr a final string of one or more unrecognized characters, including the terminating null character of the input string.]*/
+    if (endptr != NULL)
+    {
+        (*endptr) = runner;
+    }
+
+    return result;
+}
+
+
+/*Codes_SRS_CRT_ABSTRACTIONS_99_038: [mallocAndstrcpy_s shall allocate memory for destination buffer to fit the string in the source parameter.]*/
+int mallocAndStrcpy_s(char** destination, const char* source)
+{
+    int result;
+    int copied_result;
+    /*Codes_SRS_CRT_ABSTRACTIONS_99_036: [destination parameter or source parameter is NULL, the error code returned shall be EINVAL and destination shall not be modified.]*/
+    if ((destination == NULL) || (source == NULL))
+    {
+        /*If strDestination or strSource is a NULL pointer[...]these functions return EINVAL */
+        result = EINVAL;
+    }
+    else
+    {
+        size_t l = strlen(source);
+        char* temp = (char*)malloc(l + 1);
+
+        /*Codes_SRS_CRT_ABSTRACTIONS_99_037: [Upon failure to allocate memory for the destination, the function will return ENOMEM.]*/
+        if (temp == NULL)
+        {
+            result = ENOMEM;
+        }
+        else
+        {
+            *destination = temp;
+            /*Codes_SRS_CRT_ABSTRACTIONS_99_039: [mallocAndstrcpy_s shall copy the contents in the address source, including the terminating null character into location specified by the destination pointer after the memory allocation.]*/
+            copied_result = strcpy_s(*destination, l + 1, source);
+            if (copied_result < 0) /*strcpy_s error*/
+            {
+                free(*destination);
+                *destination = NULL;
+                result = copied_result;
+            }
+            else
+            {
+                /*Codes_SRS_CRT_ABSTRACTIONS_99_035: [mallocAndstrcpy_s shall return Zero upon success]*/
+                result = 0;
+            }
+        }
+    }
+    return result;
+}
+
+/*takes "value" and transforms it into a decimal string*/
+/*10 => "10"*/
+/*return 0 when everything went ok*/
+/*Codes_SRS_CRT_ABSTRACTIONS_02_001: [unsignedIntToString shall convert the parameter value to its decimal representation as a string in the buffer indicated by parameter destination having the size indicated by parameter destinationSize.] */
+int unsignedIntToString(char* destination, size_t destinationSize, unsigned int value)
+{
+    int result;
+    size_t pos;
+    /*the below loop gets the number in reverse order*/
+    /*Codes_SRS_CRT_ABSTRACTIONS_02_003: [If destination is NULL then unsignedIntToString shall fail.] */
+    /*Codes_SRS_CRT_ABSTRACTIONS_02_002: [If the conversion fails for any reason (for example, insufficient buffer space), a non-zero return value shall be supplied and unsignedIntToString shall fail.] */
+    if (
+        (destination == NULL) ||
+        (destinationSize < 2) /*because the smallest number is '0\0' which requires 2 characters*/
+        )
+    {
+        result = MU_FAILURE;
+    }
+    else
+    {
+        pos = 0;
+        do
+        {
+            destination[pos++] = '0' + (value % 10);
+            value /= 10;
+        } while ((value > 0) && (pos < (destinationSize-1)));
+
+        if (value == 0)
+        {
+            size_t w;
+            destination[pos] = '\0';
+            /*all converted and they fit*/
+            for (w = 0; w <= (pos-1) >> 1; w++)
+            {
+                char temp;
+                temp = destination[w];
+                destination[w] = destination[pos - 1 - w];
+                destination[pos -1 - w] = temp;
+            }
+            /*Codes_SRS_CRT_ABSTRACTIONS_02_004: [If the conversion has been successfull then unsignedIntToString shall return 0.] */
+            result = 0;
+        }
+        else
+        {
+            /*Codes_SRS_CRT_ABSTRACTIONS_02_002: [If the conversion fails for any reason (for example, insufficient buffer space), a non-zero return value shall be supplied and unsignedIntToString shall fail.] */
+            result = MU_FAILURE;
+        }
+    }
+    return result;
+}
+
+/*takes "value" and transforms it into a decimal string*/
+/*10 => "10"*/
+/*return 0 when everything went ok*/
+/*Codes_SRS_CRT_ABSTRACTIONS_02_001: [unsignedIntToString shall convert the parameter value to its decimal representation as a string in the buffer indicated by parameter destination having the size indicated by parameter destinationSize.] */
+int size_tToString(char* destination, size_t destinationSize, size_t value)
+{
+    int result;
+    size_t pos;
+    /*the below loop gets the number in reverse order*/
+    /*Codes_SRS_CRT_ABSTRACTIONS_02_003: [If destination is NULL then unsignedIntToString shall fail.] */
+    /*Codes_SRS_CRT_ABSTRACTIONS_02_002: [If the conversion fails for any reason (for example, insufficient buffer space), a non-zero return value shall be supplied and unsignedIntToString shall fail.] */
+    if (
+        (destination == NULL) ||
+        (destinationSize < 2) /*because the smallest number is '0\0' which requires 2 characters*/
+        )
+    {
+        result = MU_FAILURE;
+    }
+    else
+    {
+        pos = 0;
+        do
+        {
+            destination[pos++] = '0' + (value % 10);
+            value /= 10;
+        } while ((value > 0) && (pos < (destinationSize - 1)));
+
+        if (value == 0)
+        {
+            size_t w;
+            destination[pos] = '\0';
+            /*all converted and they fit*/
+            for (w = 0; w <= (pos - 1) >> 1; w++)
+            {
+                char temp;
+                temp = destination[w];
+                destination[w] = destination[pos - 1 - w];
+                destination[pos - 1 - w] = temp;
+            }
+            /*Codes_SRS_CRT_ABSTRACTIONS_02_004: [If the conversion has been successfull then unsignedIntToString shall return 0.] */
+            result = 0;
+        }
+        else
+        {
+            /*Codes_SRS_CRT_ABSTRACTIONS_02_002: [If the conversion fails for any reason (for example, insufficient buffer space), a non-zero return value shall be supplied and unsignedIntToString shall fail.] */
+            result = MU_FAILURE;
+        }
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/dns_resolver_sync.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/dns_resolver_sync.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/dns_resolver_sync.c	(revision 453)
@@ -0,0 +1,255 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+// This file is OS-specific, and is identified by setting include directories
+// in the project
+#include "socket_async_os.h"
+
+#include "azure_c_shared_utility/dns_resolver.h"
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/xlogging.h"
+
+
+// EXTRACT_IPV4 pulls the uint32_t IPv4 address out of an addrinfo struct
+// This will not be needed for the asynchronous design
+// The default definition handles lwIP. Please add comments for other systems tested.
+#define EXTRACT_IPV4(ptr) ((struct sockaddr_in *) ptr->ai_addr)->sin_addr.s_addr
+
+typedef struct
+{
+    char* hostname;
+    int port;
+    uint32_t ip_v4;
+    bool is_complete;
+    bool is_failed;
+    struct addrinfo* addrInfo;
+} DNSRESOLVER_INSTANCE;
+
+DNSRESOLVER_HANDLE dns_resolver_create(const char* hostname, int port, const DNSRESOLVER_OPTIONS* options)
+{
+    /* Codes_SRS_dns_resolver_30_012: [ The optional options parameter shall be ignored. ]*/
+    DNSRESOLVER_INSTANCE* result;
+    (void)options;
+    if (hostname == NULL)
+    {
+        /* Codes_SRS_dns_resolver_30_011: [ If the hostname parameter is NULL, dns_resolver_create shall log an error and return NULL. ]*/
+        LogError("NULL hostname");
+        result = NULL;
+    }
+    else
+    {
+        result = malloc(sizeof(DNSRESOLVER_INSTANCE));
+        if (result == NULL)
+        {
+            /* Codes_SRS_dns_resolver_30_014: [ On any failure, dns_resolver_create shall log an error and return NULL. ]*/
+            LogError("malloc instance failed");
+            result = NULL;
+        }
+        else
+        {
+            int ms_result;
+            result->is_complete = false;
+            result->is_failed = false;
+            result->ip_v4 = 0;
+            result->port = port;
+            /* Codes_SRS_dns_resolver_30_010: [ dns_resolver_create shall make a copy of the hostname parameter to allow immediate deletion by the caller. ]*/
+            ms_result = mallocAndStrcpy_s(&result->hostname, hostname);
+            if (ms_result != 0)
+            {
+                /* Codes_SRS_dns_resolver_30_014: [ On any failure, dns_resolver_create shall log an error and return NULL. ]*/
+                free(result);
+                result = NULL;
+            }
+        }
+    }
+    return result;
+}
+
+/* Codes_SRS_dns_resolver_30_021: [ dns_resolver_is_create_complete shall perform the asynchronous work of DNS lookup and log any errors. ]*/
+bool dns_resolver_is_lookup_complete(DNSRESOLVER_HANDLE dns_in)
+{
+    DNSRESOLVER_INSTANCE* dns = (DNSRESOLVER_INSTANCE*)dns_in;
+
+    bool result;
+    if (dns == NULL)
+    {
+        /* Codes_SRS_dns_resolver_30_020: [ If the dns parameter is NULL, dns_resolver_is_create_complete shall log an error and return false. ]*/
+        LogError("NULL dns");
+        result = false;
+    }
+    else
+    {
+        if (dns->is_complete)
+        {
+            /* Codes_SRS_dns_resolver_30_024: [ If dns_resolver_is_create_complete has previously returned true, dns_resolver_is_create_complete shall do nothing and return true. ]*/
+            result = true;
+        }
+        else
+        {
+            char portString[16];
+            struct addrinfo *addrInfo = NULL;
+            struct addrinfo *ptr = NULL;
+            struct addrinfo hints;
+            int getAddrResult;
+
+            //--------------------------------
+            // Setup the hints address info structure
+            // which is passed to the getaddrinfo() function
+            memset(&hints, 0, sizeof(hints));
+            hints.ai_family = AF_INET;
+            hints.ai_socktype = SOCK_STREAM;
+            hints.ai_protocol = 0;
+
+            //--------------------------------
+            // Call getaddrinfo(). If the call succeeds,
+            // the result variable will hold a linked list
+            // of addrinfo structures containing response
+            // information
+            if (sprintf(portString, "%u", dns->port) < 0)
+            {
+                LogError("Failure: sprintf failed to encode the port.");
+                result = MU_FAILURE;
+            }
+
+            getAddrResult = getaddrinfo(dns->hostname, portString, &hints, &addrInfo);
+            if (getAddrResult == 0)
+            {
+                dns->addrInfo = addrInfo;
+                
+                // If we find the AF_INET address, use it as the return value
+                for (ptr = addrInfo; ptr != NULL; ptr = ptr->ai_next)
+                {
+                    switch (ptr->ai_family)
+                    {
+                    case AF_INET:
+                        /* Codes_SRS_dns_resolver_30_032: [ If dns_resolver_is_create_complete has returned true and the lookup process has succeeded, dns_resolver_get_ipv4 shall return the discovered IPv4 address. ]*/
+                        dns->ip_v4 = EXTRACT_IPV4(ptr);
+                        break;
+                    }
+                }
+                /* Codes_SRS_dns_resolver_30_033: [ If dns_resolver_is_create_complete has returned true and the lookup process has failed, dns_resolver_get_ipv4 shall return 0. ]*/
+                dns->is_failed = (dns->ip_v4 == 0);
+            }
+            else
+            {
+                /* Codes_SRS_dns_resolver_30_033: [ If dns_resolver_is_create_complete has returned true and the lookup process has failed, dns_resolver_get_ipv4 shall return 0. ]*/
+                LogInfo("Failed DNS lookup for %s: %d", dns->hostname, getAddrResult);
+                dns->is_failed = true;
+            }
+
+            /* Codes_SRS_dns_resolver_30_021: [ dns_resolver_is_create_complete shall perform the asynchronous work of DNS lookup and log any errors. ]*/
+            // Only make one attempt at lookup for this
+            // synchronous implementation
+            dns->is_complete = true;
+
+            // This synchronous implementation is incapable of being incomplete, so SRS_dns_resolver_30_023 does not ever happen
+            /* Codes_SRS_dns_resolver_30_023: [ If the DNS lookup process is not yet complete, dns_resolver_is_create_complete shall return false. ]*/
+            /* Codes_SRS_dns_resolver_30_022: [ If the DNS lookup process has completed, dns_resolver_is_create_complete shall return true. ]*/
+            result = true;
+        }
+    }
+
+    return result;
+}
+
+void dns_resolver_destroy(DNSRESOLVER_HANDLE dns_in)
+{
+    DNSRESOLVER_INSTANCE* dns = (DNSRESOLVER_INSTANCE*)dns_in;
+    if (dns == NULL)
+    {
+        /* Codes_SRS_dns_resolver_30_050: [ If the dns parameter is NULL, dns_resolver_destroy shall log an error and do nothing. ]*/
+        LogError("NULL dns");
+    }
+    else
+    {
+        /* Codes_SRS_dns_resolver_30_051: [ dns_resolver_destroy shall delete all acquired resources and delete the DNSRESOLVER_HANDLE. ]*/
+        if(dns->is_complete && !dns->is_failed && dns->addrInfo != NULL)
+        {
+            freeaddrinfo(dns->addrInfo);
+        }
+
+        if(dns->hostname != NULL)
+        {
+            free(dns->hostname);
+        }
+        
+        free(dns);
+        dns = NULL;
+    }
+}
+
+uint32_t dns_resolver_get_ipv4(DNSRESOLVER_HANDLE dns_in)
+{
+    DNSRESOLVER_INSTANCE* dns = (DNSRESOLVER_INSTANCE*)dns_in;
+    uint32_t result;
+    if (dns == NULL)
+    {
+        /* Codes_SRS_dns_resolver_30_030: [ If the dns parameter is NULL, dns_resolver_get_ipv4 shall log an error and return 0. ]*/
+        LogError("NULL dns");
+        result = 0;
+    }
+    else
+    {
+        if (dns->is_complete)
+        {
+            if (dns->is_failed)
+            {
+                /* Codes_SRS_dns_resolver_30_033: [ If dns_resolver_is_create_complete has returned true and the lookup process has failed, dns_resolver_get_ipv4 shall return 0. ]*/
+                result = 0;
+            }
+            else
+            {
+                /* Codes_SRS_dns_resolver_30_032: [ If dns_resolver_is_create_complete has returned true and the lookup process has succeeded, dns_resolver_get_ipv4 shall return the discovered IPv4 address. ]*/
+                result = dns->ip_v4;
+            }
+        }
+        else
+        {
+            /* Codes_SRS_dns_resolver_30_031: [ If dns_resolver_is_create_complete has not yet returned true, dns_resolver_get_ipv4 shall log an error and return 0. ]*/
+            LogError("dns_resolver_get_ipv4 when not complete");
+            result = 0;
+        }
+    }
+    return result;
+}
+
+struct addrinfo* dns_resolver_get_addrInfo(DNSRESOLVER_HANDLE dns_in)
+{
+    DNSRESOLVER_INSTANCE* dns = (DNSRESOLVER_INSTANCE*)dns_in;
+    struct addrinfo* result;
+    if (dns == NULL)
+    {
+        /* Codes_SRS_dns_resolver_30_030: [ If the dns parameter is NULL, dns_resolver_get_ipv4 shall log an error and return 0. ]*/
+        LogError("NULL dns");
+        result = NULL;
+    }
+    else
+    {
+        if (dns->is_complete)
+        {
+            if (dns->is_failed)
+            {
+                /* Codes_SRS_dns_resolver_30_033: [ If dns_resolver_is_create_complete has returned true and the lookup process has failed, dns_resolver_get_ipv4 shall return 0. ]*/
+                result = NULL;
+            }
+            else
+            {
+                /* Codes_SRS_dns_resolver_30_032: [ If dns_resolver_is_create_complete has returned true and the lookup process has succeeded, dns_resolver_get_ipv4 shall return the discovered IPv4 address. ]*/
+                result = dns->addrInfo;
+            }
+        }
+        else
+        {
+            /* Codes_SRS_dns_resolver_30_031: [ If dns_resolver_is_create_complete has not yet returned true, dns_resolver_get_ipv4 shall log an error and return 0. ]*/
+            LogError("dns_resolver_get_ipv4 when not complete");
+            result = NULL;
+        }
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/doublylinkedlist.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/doublylinkedlist.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/doublylinkedlist.c	(revision 453)
@@ -0,0 +1,107 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include "azure_c_shared_utility/doublylinkedlist.h"
+
+void
+DList_InitializeListHead(
+    PDLIST_ENTRY ListHead
+)
+{
+    /* Codes_SRS_DLIST_06_005: [DList_InitializeListHead will initialize the Flink & Blink to the address of the DLIST_ENTRY.] */
+    ListHead->Flink = ListHead->Blink = ListHead;
+    return;
+}
+
+int
+DList_IsListEmpty(
+    const PDLIST_ENTRY ListHead
+)
+{
+    /* Codes_SRS_DLIST_06_003: [DList_IsListEmpty shall return a non-zero value if there are no DLIST_ENTRY's on this list other than the list head.] */
+    /* Codes_SRS_DLIST_06_004: [DList_IsListEmpty shall return 0 if there is one or more items in the list.] */
+    return (ListHead->Flink == ListHead);
+}
+
+int
+DList_RemoveEntryList(
+    PDLIST_ENTRY Entry
+)
+{
+    /* Codes_SRS_DLIST_06_008: [DList_RemoveEntryList shall remove a listEntry from whatever list it is properly part of.] */
+    /* Codes_SRS_DLIST_06_009: [The remaining list is properly formed.] */
+    /* Codes_SRS_DLIST_06_010: [DList_RemoveEntryList shall return non-zero if the remaining list is empty.] */
+    /* Codes_SRS_DLIST_06_011: [DList_RemoveEntryList shall return zero if the remaining list is NOT empty.] */
+    PDLIST_ENTRY Blink;
+    PDLIST_ENTRY Flink;
+
+    Flink = Entry->Flink;
+    Blink = Entry->Blink;
+    Blink->Flink = Flink;
+    Flink->Blink = Blink;
+    return (Flink == Blink);
+}
+
+PDLIST_ENTRY
+DList_RemoveHeadList(
+    PDLIST_ENTRY ListHead
+)
+{
+    /* Codes_SRS_DLIST_06_012: [DList_RemoveHeadList removes the oldest entry from the list defined by the listHead parameter and returns a pointer to that entry.] */
+    /* Codes_SRS_DLIST_06_013: [DList_RemoveHeadList shall return listHead if that's the only item in the list.] */
+
+    PDLIST_ENTRY Flink;
+    PDLIST_ENTRY Entry;
+
+    Entry = ListHead->Flink;
+    Flink = Entry->Flink;
+    ListHead->Flink = Flink;
+    Flink->Blink = ListHead;
+    return Entry;
+}
+
+
+
+void
+DList_InsertTailList(
+    PDLIST_ENTRY ListHead,
+    PDLIST_ENTRY Entry
+)
+{
+    PDLIST_ENTRY Blink;
+
+    /* Codes_SRS_DLIST_06_006: [DListInsertTailList shall place the DLIST_ENTRY at the end of the list defined by the listHead parameter.] */
+    Blink = ListHead->Blink;
+    Entry->Flink = ListHead;
+    Entry->Blink = Blink;
+    Blink->Flink = Entry;
+    ListHead->Blink = Entry;
+    return;
+}
+
+
+void
+DList_AppendTailList(
+    PDLIST_ENTRY ListHead,
+    PDLIST_ENTRY ListToAppend
+)
+{
+    /* Codes_SRS_DLIST_06_007: [DList_AppendTailList shall place the list defined by listToAppend at the end of the list defined by the listHead parameter.] */
+    PDLIST_ENTRY ListEnd = ListHead->Blink;
+
+    ListHead->Blink->Flink = ListToAppend;
+    ListHead->Blink = ListToAppend->Blink;
+    ListToAppend->Blink->Flink = ListHead;
+    ListToAppend->Blink = ListEnd;
+    return;
+}
+
+
+/*Codes_SRS_DLIST_02_002: [DList_InsertHeadList inserts a singular entry in the list having as head listHead after "head".]*/
+void DList_InsertHeadList(PDLIST_ENTRY listHead, PDLIST_ENTRY entry)
+{
+    entry->Blink = listHead;
+    entry->Flink = listHead->Flink;
+    listHead->Flink->Blink = entry;
+    listHead->Flink = entry;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/gb_rand.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/gb_rand.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/gb_rand.c	(revision 453)
@@ -0,0 +1,16 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifdef __cplusplus
+#include <cstdlib>
+#else
+#include <stdlib.h>
+#endif
+
+#include "azure_c_shared_utility/gb_rand.h"
+
+/*this is rand*/
+int gb_rand(void)
+{
+    return rand();
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/gb_stdio.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/gb_stdio.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/gb_stdio.c	(revision 453)
@@ -0,0 +1,54 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/*depending if the symbol GB_STDIO_INTERCEPT is defined, this file does the following
+
+    a) if GB_STDIO_INTERCEPT is NOT defined, then the file shall be empty (almost:)
+    b) if GB_STDIO_INTERCEPT is defined, then the file shall call to the 'real' stdio.h functions from their gb_* synonyms*/
+#ifdef _MSC_VER
+/* compiler warning C4206: nonstandard extension used: translation unit is empty */
+/* linker warning 4221: This object file does not define any previously undefined public symbols, so it will not be used by any link operation that consumes this library */
+const int avoid_warnings_B9EB480E_6AE7_43B3_9249_47993776BA7B = 0;
+#endif
+#ifdef GB_STDIO_INTERCEPT
+
+#ifdef __cplusplus
+#include <cstdio>
+#include <cstdarg>
+#else
+#include <stdio.h>
+#include <stdarg.h>
+#endif
+
+#include "azure_c_shared_utility/gb_stdio.h"
+
+/*this is fopen*/
+FILE *gb_fopen(const char * filename, const char * mode)
+{
+    return fopen(filename, mode);
+}
+
+int gb_fclose(FILE *stream)
+{
+    return fclose(stream);
+}
+
+int gb_fseek(FILE *stream, long int offset, int whence)
+{
+    return fseek(stream, offset, whence);
+}
+
+long int gb_ftell(FILE *stream)
+{
+    return ftell(stream);
+}
+
+int fprintf(FILE * stream, const char * format, ...)
+{
+    va_list args;
+    va_start(args, format);
+    vfprintf(stream, format, args);
+    va_end(args);
+}
+
+#endif
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/gb_time.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/gb_time.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/gb_time.c	(revision 453)
@@ -0,0 +1,40 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/*depending if the symbol GB_TIME_INTERCEPT is defined, this file does the following
+
+    a) if GB_TIME_INTERCEPT is NOT defined, then the file shall be empty (almost:)
+    b) if GB_TIME_INTERCEPT is defined, then the file shall call to the 'real' time.h functions from their gb_* synonyms*/
+#ifdef _MSC_VER
+/* compiler warning C4206: nonstandard extension used: translation unit is empty */
+/* linker warning 4221: This object file does not define any previously undefined public symbols, so it will not be used by any link operation that consumes this library */
+const int avoid_warnings_0CA668EF_F2C4_49A8_A30D_7257C67173A4 = 0;
+#endif
+#ifdef GB_TIME_INTERCEPT
+
+#ifdef __cplusplus
+#include <ctime>
+#else
+#include <time.h>
+#endif
+
+#include "azure_c_shared_utility/gb_time.h"
+
+/*this is time*/
+time_t gb_time(time_t *timer);
+{
+    return time(timer);
+}
+
+/*this is localtime*/
+struct tm *gb_localtime(const time_t *timer)
+{
+    return gb_localtime(timer);
+}
+
+size_t gb_strftime(char * s, size_t maxsize, const char * format, const struct tm * timeptr)
+{
+    return strftime(s, maxsize, format, timeptr);
+}
+
+#endif
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/gballoc.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/gballoc.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/gballoc.c	(revision 453)
@@ -0,0 +1,444 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <stdint.h>
+#include "azure_c_shared_utility/lock.h"
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/xlogging.h"
+
+#ifndef GB_USE_CUSTOM_HEAP
+
+#ifndef SIZE_MAX
+#define SIZE_MAX ((size_t)~(size_t)0)
+#endif
+
+typedef struct ALLOCATION_TAG
+{
+    size_t size;
+    void* ptr;
+    void* next;
+} ALLOCATION;
+
+typedef enum GBALLOC_STATE_TAG
+{
+    GBALLOC_STATE_INIT,
+    GBALLOC_STATE_NOT_INIT
+} GBALLOC_STATE;
+
+static ALLOCATION* head = NULL;
+static size_t totalSize = 0;
+static size_t maxSize = 0;
+static size_t g_allocations = 0;
+static GBALLOC_STATE gballocState = GBALLOC_STATE_NOT_INIT;
+
+static LOCK_HANDLE gballocThreadSafeLock = NULL;
+
+int gballoc_init(void)
+{
+    int result;
+
+    if (gballocState != GBALLOC_STATE_NOT_INIT)
+    {
+        /* Codes_SRS_GBALLOC_01_025: [Init after Init shall fail and return a non-zero value.] */
+        result = MU_FAILURE;
+    }
+    /* Codes_SRS_GBALLOC_01_026: [gballoc_Init shall create a lock handle that will be used to make the other gballoc APIs thread-safe.] */
+    else if ((gballocThreadSafeLock = Lock_Init()) == NULL)
+    {
+        /* Codes_SRS_GBALLOC_01_027: [If the Lock creation fails, gballoc_init shall return a non-zero value.]*/
+        result = MU_FAILURE;
+    }
+    else
+    {
+        gballocState = GBALLOC_STATE_INIT;
+
+        /* Codes_ SRS_GBALLOC_01_002: [Upon initialization the total memory used and maximum total memory used tracked by the module shall be set to 0.] */
+        totalSize = 0;
+        maxSize = 0;
+        g_allocations = 0;
+
+        /* Codes_SRS_GBALLOC_01_024: [gballoc_init shall initialize the gballoc module and return 0 upon success.] */
+        result = 0;
+    }
+
+    return result;
+}
+
+void gballoc_deinit(void)
+{
+    if (gballocState == GBALLOC_STATE_INIT)
+    {
+        /* Codes_SRS_GBALLOC_01_028: [gballoc_deinit shall free all resources allocated by gballoc_init.] */
+        (void)Lock_Deinit(gballocThreadSafeLock);
+    }
+
+    gballocState = GBALLOC_STATE_NOT_INIT;
+}
+
+void* gballoc_malloc(size_t size)
+{
+    void* result;
+
+    if (gballocState != GBALLOC_STATE_INIT)
+    {
+        /* Codes_SRS_GBALLOC_01_039: [If gballoc was not initialized gballoc_malloc shall simply call malloc without any memory tracking being performed.] */
+        result = malloc(size);
+    }
+    /* Codes_SRS_GBALLOC_01_030: [gballoc_malloc shall ensure thread safety by using the lock created by gballoc_Init.] */
+    else if (LOCK_OK != Lock(gballocThreadSafeLock))
+    {
+        /* Codes_SRS_GBALLOC_01_048: [If acquiring the lock fails, gballoc_malloc shall return NULL.] */
+        LogError("Failed to get the Lock.");
+        result = NULL;
+    }
+    else
+    {
+        ALLOCATION* allocation = (ALLOCATION*)calloc(1, sizeof(ALLOCATION));
+        if (allocation == NULL)
+        {
+            result = NULL;
+        }
+        else
+        {
+            /* Codes_SRS_GBALLOC_01_003: [gb_malloc shall call the C99 malloc function and return its result.] */
+            result = malloc(size);
+            if (result == NULL)
+            {
+                /* Codes_SRS_GBALLOC_01_012: [When the underlying malloc call fails, gballoc_malloc shall return NULL and size should not be counted towards total memory used.] */
+                free(allocation);
+            }
+            else
+            {
+                /* Codes_SRS_GBALLOC_01_004: [If the underlying malloc call is successful, gb_malloc shall increment the total memory used with the amount indicated by size.] */
+                allocation->ptr = result;
+                allocation->size = size;
+                allocation->next = head;
+                head = allocation;
+
+                g_allocations++;
+                totalSize += size;
+                /* Codes_SRS_GBALLOC_01_011: [The maximum total memory used shall be the maximum of the total memory used at any point.] */
+                if (maxSize < totalSize)
+                {
+                    maxSize = totalSize;
+                }
+            }
+        }
+
+        (void)Unlock(gballocThreadSafeLock);
+    }
+
+    return result;
+}
+
+void* gballoc_calloc(size_t nmemb, size_t size)
+{
+    void* result;
+
+    if (gballocState != GBALLOC_STATE_INIT)
+    {
+        /* Codes_SRS_GBALLOC_01_040: [If gballoc was not initialized gballoc_calloc shall simply call calloc without any memory tracking being performed.] */
+        result = calloc(nmemb, size);
+    }
+    /* Codes_SRS_GBALLOC_01_031: [gballoc_calloc shall ensure thread safety by using the lock created by gballoc_Init]  */
+    else if (LOCK_OK != Lock(gballocThreadSafeLock))
+    {
+        /* Codes_SRS_GBALLOC_01_046: [If acquiring the lock fails, gballoc_calloc shall return NULL.] */
+        LogError("Failed to get the Lock.");
+        result = NULL;
+    }
+    else
+    {
+        ALLOCATION* allocation = (ALLOCATION*)calloc(1, sizeof(ALLOCATION));
+        if (allocation == NULL)
+        {
+            result = NULL;
+        }
+        else
+        {
+            /* Codes_SRS_GBALLOC_01_020: [gballoc_calloc shall call the C99 calloc function and return its result.] */
+            result = calloc(nmemb, size);
+            if (result == NULL)
+            {
+                /* Codes_SRS_GBALLOC_01_022: [When the underlying calloc call fails, gballoc_calloc shall return NULL and size should not be counted towards total memory used.] */
+                free(allocation);
+            }
+            else
+            {
+                /* Codes_SRS_GBALLOC_01_021: [If the underlying calloc call is successful, gballoc_calloc shall increment the total memory used with nmemb*size.] */
+                allocation->ptr = result;
+                allocation->size = nmemb * size;
+                allocation->next = head;
+                head = allocation;
+                g_allocations++;
+
+                totalSize += allocation->size;
+                /* Codes_SRS_GBALLOC_01_011: [The maximum total memory used shall be the maximum of the total memory used at any point.] */
+                if (maxSize < totalSize)
+                {
+                    maxSize = totalSize;
+                }
+            }
+        }
+
+        (void)Unlock(gballocThreadSafeLock);
+    }
+
+    return result;
+}
+
+void* gballoc_realloc(void* ptr, size_t size)
+{
+    ALLOCATION* curr;
+    void* result;
+    ALLOCATION* allocation = NULL;
+
+    if (gballocState != GBALLOC_STATE_INIT)
+    {
+        /* Codes_SRS_GBALLOC_01_041: [If gballoc was not initialized gballoc_realloc shall shall simply call realloc without any memory tracking being performed.] */
+        result = realloc(ptr, size);
+    }
+    /* Codes_SRS_GBALLOC_01_032: [gballoc_realloc shall ensure thread safety by using the lock created by gballoc_Init.] */
+    else if (LOCK_OK != Lock(gballocThreadSafeLock))
+    {
+        /* Codes_SRS_GBALLOC_01_047: [If acquiring the lock fails, gballoc_realloc shall return NULL.] */
+        LogError("Failed to get the Lock.");
+        result = NULL;
+    }
+    else
+    {
+        if (ptr == NULL)
+        {
+            /* Codes_SRS_GBALLOC_01_017: [When ptr is NULL, gballoc_realloc shall call the underlying realloc with ptr being NULL and the realloc result shall be tracked by gballoc.] */
+            allocation = (ALLOCATION*)calloc(1, sizeof(ALLOCATION));
+        }
+        else
+        {
+            curr = head;
+            while (curr != NULL)
+            {
+                if (curr->ptr == ptr)
+                {
+                    allocation = curr;
+                    break;
+                }
+                else
+                {
+                    curr = (ALLOCATION*)curr->next;
+                }
+            }
+        }
+
+        if (allocation == NULL)
+        {
+            /* Codes_SRS_GBALLOC_01_015: [When allocating memory used for tracking by gballoc_realloc fails, gballoc_realloc shall return NULL and no change should be made to the counted total memory usage.] */
+            /* Codes_SRS_GBALLOC_01_016: [When the ptr pointer cannot be found in the pointers tracked by gballoc, gballoc_realloc shall return NULL and the underlying realloc shall not be called.] */
+            result = NULL;
+        }
+        else
+        {
+            result = realloc(ptr, size);
+            if (result == NULL)
+            {
+                /* Codes_SRS_GBALLOC_01_014: [When the underlying realloc call fails, gballoc_realloc shall return NULL and no change should be made to the counted total memory usage.] */
+                if (ptr == NULL)
+                {
+                    free(allocation);
+                }
+            }
+            else
+            {
+                if (ptr != NULL)
+                {
+                    /* Codes_SRS_GBALLOC_01_006: [If the underlying realloc call is successful, gballoc_realloc shall look up the size associated with the pointer ptr and decrease the total memory used with that size.] */
+                    allocation->ptr = result;
+                    totalSize -= allocation->size;
+                    allocation->size = size;
+                }
+                else
+                {
+                    /* add block */
+                    allocation->ptr = result;
+                    allocation->size = size;
+                    allocation->next = head;
+                    head = allocation;
+                }
+
+                /* Codes_SRS_GBALLOC_01_007: [If realloc is successful, gballoc_realloc shall also increment the total memory used value tracked by this module.] */
+                totalSize += size;
+                g_allocations++;
+
+                /* Codes_SRS_GBALLOC_01_011: [The maximum total memory used shall be the maximum of the total memory used at any point.] */
+                if (maxSize < totalSize)
+                {
+                    maxSize = totalSize;
+                }
+            }
+        }
+
+        (void)Unlock(gballocThreadSafeLock);
+    }
+
+    return result;
+}
+
+void gballoc_free(void* ptr)
+{
+    ALLOCATION* curr = head;
+    ALLOCATION* prev = NULL;
+
+    if (gballocState != GBALLOC_STATE_INIT)
+    {
+        /* Codes_SRS_GBALLOC_01_042: [If gballoc was not initialized gballoc_free shall shall simply call free.] */
+        free(ptr);
+    }
+    /* Codes_SRS_GBALLOC_01_033: [gballoc_free shall ensure thread safety by using the lock created by gballoc_Init.] */
+    else if (LOCK_OK != Lock(gballocThreadSafeLock))
+    {
+        /* Codes_SRS_GBALLOC_01_049: [If acquiring the lock fails, gballoc_free shall do nothing.] */
+        LogError("Failed to get the Lock.");
+    }
+    else
+    {
+        /* Codes_SRS_GBALLOC_01_009: [gballoc_free shall also look up the size associated with the ptr pointer and decrease the total memory used with the associated size amount.] */
+        while (curr != NULL)
+        {
+            if (curr->ptr == ptr)
+            {
+                /* Codes_SRS_GBALLOC_01_008: [gballoc_free shall call the C99 free function.] */
+                free(ptr);
+                totalSize -= curr->size;
+                if (prev != NULL)
+                {
+                    prev->next = curr->next;
+                }
+                else
+                {
+                    head = (ALLOCATION*)curr->next;
+                }
+
+                free(curr);
+                break;
+            }
+
+            prev = curr;
+            curr = (ALLOCATION*)curr->next;
+        }
+
+        if ((curr == NULL) && (ptr != NULL))
+        {
+            /* Codes_SRS_GBALLOC_01_019: [When the ptr pointer cannot be found in the pointers tracked by gballoc, gballoc_free shall not free any memory.] */
+
+            /* could not find the allocation */
+            LogError("Could not free allocation for address %p (not found)", ptr);
+        }
+        (void)Unlock(gballocThreadSafeLock);
+    }
+}
+
+size_t gballoc_getMaximumMemoryUsed(void)
+{
+    size_t result;
+
+    /* Codes_SRS_GBALLOC_01_038: [If gballoc was not initialized gballoc_getMaximumMemoryUsed shall return MAX_INT_SIZE.] */
+    if (gballocState != GBALLOC_STATE_INIT)
+    {
+        LogError("gballoc is not initialized.");
+        result = SIZE_MAX;
+    }
+    /* Codes_SRS_GBALLOC_01_034: [gballoc_getMaximumMemoryUsed shall ensure thread safety by using the lock created by gballoc_Init.]  */
+    else if (LOCK_OK != Lock(gballocThreadSafeLock))
+    {
+        /* Codes_SRS_GBALLOC_01_050: [If the lock cannot be acquired, gballoc_getMaximumMemoryUsed shall return SIZE_MAX.]  */
+        LogError("Failed to get the Lock.");
+        result = SIZE_MAX;
+    }
+    else
+    {
+        /* Codes_SRS_GBALLOC_01_010: [gballoc_getMaximumMemoryUsed shall return the maximum amount of total memory used recorded since the module initialization.] */
+        result = maxSize;
+        (void)Unlock(gballocThreadSafeLock);
+    }
+
+    return result;
+}
+
+size_t gballoc_getCurrentMemoryUsed(void)
+{
+    size_t result;
+
+    /* Codes_SRS_GBALLOC_01_044: [If gballoc was not initialized gballoc_getCurrentMemoryUsed shall return SIZE_MAX.] */
+    if (gballocState != GBALLOC_STATE_INIT)
+    {
+        LogError("gballoc is not initialized.");
+        result = SIZE_MAX;
+    }
+    /* Codes_SRS_GBALLOC_01_036: [gballoc_getCurrentMemoryUsed shall ensure thread safety by using the lock created by gballoc_Init.]*/
+    else if (LOCK_OK != Lock(gballocThreadSafeLock))
+    {
+        /* Codes_SRS_GBALLOC_01_051: [If the lock cannot be acquired, gballoc_getCurrentMemoryUsed shall return SIZE_MAX.] */
+        LogError("Failed to get the Lock.");
+        result = SIZE_MAX;
+    }
+    else
+    {
+        /*Codes_SRS_GBALLOC_02_001: [gballoc_getCurrentMemoryUsed shall return the currently used memory size.] */
+        result = totalSize;
+        (void)Unlock(gballocThreadSafeLock);
+    }
+
+    return result;
+}
+
+size_t gballoc_getAllocationCount(void)
+{
+    size_t result;
+
+    /* Codes_SRS_GBALLOC_07_001: [ If gballoc was not initialized gballoc_getAllocationCount shall return 0. ] */
+    if (gballocState != GBALLOC_STATE_INIT)
+    {
+        LogError("gballoc is not initialized.");
+        result = 0;
+    }
+    /* Codes_SRS_GBALLOC_07_002: [ gballoc_getAllocationCount shall ensure thread safety by using the lock created by gballoc_Init ] */
+    else if (LOCK_OK != Lock(gballocThreadSafeLock))
+    {
+        /* Codes_SRS_GBALLOC_07_003: [ If the lock cannot be acquired, gballoc_getAllocationCount shall return 0. ] */
+        LogError("Failed to get the Lock.");
+        result = 0;
+    }
+    else
+    {
+        /* Codes_SRS_GBALLOC_07_004: [ gballoc_getAllocationCount shall return the currently number of allocations. ] */
+        result = g_allocations;
+        (void)Unlock(gballocThreadSafeLock);
+    }
+
+    return result;
+}
+
+void gballoc_resetMetrics()
+{
+    /* Codes_SRS_GBALLOC_07_005: [ If gballoc was not initialized gballoc_reset Metrics shall do nothing.] */
+    if (gballocState != GBALLOC_STATE_INIT)
+    {
+        LogError("gballoc is not initialized.");
+    }
+    /* Codes_SRS_GBALLOC_07_006: [ gballoc_resetMetrics shall ensure thread safety by using the lock created by gballoc_Init ]*/
+    else if (LOCK_OK != Lock(gballocThreadSafeLock))
+    {
+        /* Codes_SRS_GBALLOC_07_007: [ If the lock cannot be acquired, gballoc_reset Metrics shall do nothing.] */
+        LogError("Failed to get the Lock.");
+    }
+    else
+    {
+        /* Codes_SRS_GBALLOC_07_008: [ gballoc_resetMetrics shall reset the total allocation size, max allocation size and number of allocation to zero. ] */
+        totalSize = 0;
+        maxSize = 0;
+        g_allocations = 0;
+        (void)Unlock(gballocThreadSafeLock);
+    }
+}
+
+#endif // GB_USE_CUSTOM_HEAP
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/hmac.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/hmac.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/hmac.c	(revision 453)
@@ -0,0 +1,233 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/**************************** hmac.c ****************************/
+/******************** See RFC 4634 for details ******************/
+/*
+*  Description:
+*      This file implements the HMAC algorithm (Keyed-Hashing for
+*      Message Authentication, RFC2104), expressed in terms of the
+*      various SHA algorithms.
+*/
+
+#include "azure_c_shared_utility/sha.h"
+
+/*
+*  hmac
+*
+*  Description:
+*      This function will compute an HMAC message digest.
+*
+*  Parameters:
+*      whichSha: [in]
+*          One of SHA1, SHA224, SHA256, SHA384, SHA512
+*      key: [in]
+*          The secret shared key.
+*      key_len: [in]
+*          The length of the secret shared key.
+*      message_array: [in]
+*          An array of characters representing the message.
+*      length: [in]
+*          The length of the message in message_array
+*      digest: [out]
+*          Where the digest is returned.
+*          NOTE: The length of the digest is determined by
+*              the value of whichSha.
+*
+*  Returns:
+*      sha Error Code.
+*
+*/
+int hmac(SHAversion whichSha, const unsigned char *text, int text_len,
+    const unsigned char *key, int key_len,
+    uint8_t digest[USHAMaxHashSize])
+{
+    HMACContext ctx;
+    return hmacReset(&ctx, whichSha, key, key_len) ||
+        hmacInput(&ctx, text, text_len) ||
+        hmacResult(&ctx, digest);
+}
+
+/*
+*  hmacReset
+*
+*  Description:
+*      This function will initialize the hmacContext in preparation
+*      for computing a new HMAC message digest.
+*
+*  Parameters:
+*      context: [in/out]
+*          The context to reset.
+*      whichSha: [in]
+*          One of SHA1, SHA224, SHA256, SHA384, SHA512
+*      key: [in]
+*          The secret shared key.
+*      key_len: [in]
+*          The length of the secret shared key.
+*
+*  Returns:
+*      sha Error Code.
+*
+*/
+int hmacReset(HMACContext *ctx, enum SHAversion whichSha,
+    const unsigned char *key, int key_len)
+{
+    int i, blocksize, hashsize;
+
+    /* inner padding - key XORd with ipad */
+    unsigned char k_ipad[USHA_Max_Message_Block_Size];
+
+    /* temporary buffer when keylen > blocksize */
+    unsigned char tempkey[USHAMaxHashSize];
+
+    if (!ctx) return shaNull;
+
+    blocksize = ctx->blockSize = USHABlockSize(whichSha);
+    hashsize = ctx->hashSize = USHAHashSize(whichSha);
+
+    ctx->whichSha = whichSha;
+
+    /*
+    * If key is longer than the hash blocksize,
+    * reset it to key = HASH(key).
+    */
+    if (key_len > blocksize) {
+        USHAContext tctx;
+        int err = USHAReset(&tctx, whichSha) ||
+            USHAInput(&tctx, key, key_len) ||
+            USHAResult(&tctx, tempkey);
+        if (err != shaSuccess) return err;
+
+        key = tempkey;
+        key_len = hashsize;
+    }
+
+    /*
+    * The HMAC transform looks like:
+    *
+    * SHA(K XOR opad, SHA(K XOR ipad, text))
+    *
+    * where K is an n byte key.
+    * ipad is the byte 0x36 repeated blocksize times
+    * opad is the byte 0x5c repeated blocksize times
+    * and text is the data being protected.
+    */
+
+    /* store key into the pads, XOR'd with ipad and opad values */
+    for (i = 0; i < key_len; i++) {
+        k_ipad[i] = key[i] ^ 0x36;
+        ctx->k_opad[i] = key[i] ^ 0x5c;
+    }
+    /* remaining pad bytes are '\0' XOR'd with ipad and opad values */
+    for (; i < blocksize; i++) {
+        k_ipad[i] = 0x36;
+        ctx->k_opad[i] = 0x5c;
+    }
+
+    /* perform inner hash */
+    /* init context for 1st pass */
+    return USHAReset(&ctx->shaContext, whichSha) ||
+        /* and start with inner pad */
+        USHAInput(&ctx->shaContext, k_ipad, blocksize);
+}
+
+/*
+*  hmacInput
+*
+*  Description:
+*      This function accepts an array of octets as the next portion
+*      of the message.
+*
+*  Parameters:
+*      context: [in/out]
+*          The HMAC context to update
+*      message_array: [in]
+*          An array of characters representing the next portion of
+*          the message.
+*      length: [in]
+*          The length of the message in message_array
+*
+*  Returns:
+*      sha Error Code.
+*
+*/
+int hmacInput(HMACContext *ctx, const unsigned char *text,
+    int text_len)
+{
+    if (!ctx) return shaNull;
+    /* then text of datagram */
+    return USHAInput(&ctx->shaContext, text, text_len);
+}
+
+/*
+* HMACFinalBits
+*
+* Description:
+*   This function will add in any final bits of the message.
+*
+* Parameters:
+*   context: [in/out]
+*     The HMAC context to update
+*   message_bits: [in]
+*     The final bits of the message, in the upper portion of the
+*     byte. (Use 0b###00000 instead of 0b00000### to input the
+*     three bits ###.)
+*   length: [in]
+*     The number of bits in message_bits, between 1 and 7.
+*
+* Returns:
+*   sha Error Code.
+*/
+int hmacFinalBits(HMACContext *ctx,
+    const uint8_t bits,
+    unsigned int bitcount)
+{
+    if (!ctx) return shaNull;
+    /* then final bits of datagram */
+    return USHAFinalBits(&ctx->shaContext, bits, bitcount);
+}
+
+/*
+* HMACResult
+*
+* Description:
+*   This function will return the N-byte message digest into the
+*   Message_Digest array provided by the caller.
+*   NOTE: The first octet of hash is stored in the 0th element,
+*      the last octet of hash in the Nth element.
+*
+* Parameters:
+*   context: [in/out]
+*     The context to use to calculate the HMAC hash.
+*   digest: [out]
+*     Where the digest is returned.
+*   NOTE 2: The length of the hash is determined by the value of
+*      whichSha that was passed to hmacReset().
+*
+* Returns:
+*   sha Error Code.
+*
+*/
+int hmacResult(HMACContext *ctx, uint8_t *digest)
+{
+    if (!ctx) return shaNull;
+
+    /* finish up 1st pass */
+    /* (Use digest here as a temporary buffer.) */
+    return USHAResult(&ctx->shaContext, digest) ||
+
+        /* perform outer SHA */
+        /* init context for 2nd pass */
+        USHAReset(&ctx->shaContext, (SHAversion)ctx->whichSha) ||
+
+        /* start with outer pad */
+        USHAInput(&ctx->shaContext, ctx->k_opad, ctx->blockSize) ||
+
+        /* then results of 1st hash */
+        USHAInput(&ctx->shaContext, digest, ctx->hashSize) ||
+
+        /* finish up 2nd pass */
+        USHAResult(&ctx->shaContext, digest);
+}
+
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/hmacsha256.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/hmacsha256.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/hmacsha256.c	(revision 453)
@@ -0,0 +1,35 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stddef.h>
+#include "azure_c_shared_utility/hmacsha256.h"
+#include "azure_c_shared_utility/hmac.h"
+#include "azure_c_shared_utility/buffer_.h"
+
+HMACSHA256_RESULT HMACSHA256_ComputeHash(const unsigned char* key, size_t keyLen, const unsigned char* payload, size_t payloadLen, BUFFER_HANDLE hash)
+{
+    HMACSHA256_RESULT result;
+
+    if (key == NULL ||
+        keyLen == 0 ||
+        payload == NULL ||
+        payloadLen == 0 ||
+        hash == NULL)
+    {
+        result = HMACSHA256_INVALID_ARG;
+    }
+    else
+    {
+        if ((BUFFER_enlarge(hash, 32) != 0) ||
+            (hmac(SHA256, payload, (int)payloadLen, key, (int)keyLen, BUFFER_u_char(hash) ) != 0))
+        {
+            result = HMACSHA256_ERROR;
+        }
+        else
+        {
+            result = HMACSHA256_OK;
+        }
+    }
+
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/http_proxy_io.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/http_proxy_io.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/http_proxy_io.c	(revision 453)
@@ -0,0 +1,1048 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <limits.h>
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/xio.h"
+#include "azure_c_shared_utility/socketio.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/http_proxy_io.h"
+#include "azure_c_shared_utility/azure_base64.h"
+
+static const char* const OPTION_UNDERLYING_IO_OPTIONS = "underlying_io_options";
+
+typedef enum HTTP_PROXY_IO_STATE_TAG
+{
+    HTTP_PROXY_IO_STATE_CLOSED,
+    HTTP_PROXY_IO_STATE_OPENING_UNDERLYING_IO,
+    HTTP_PROXY_IO_STATE_WAITING_FOR_CONNECT_RESPONSE,
+    HTTP_PROXY_IO_STATE_OPEN,
+    HTTP_PROXY_IO_STATE_CLOSING,
+    HTTP_PROXY_IO_STATE_ERROR
+} HTTP_PROXY_IO_STATE;
+
+typedef struct HTTP_PROXY_IO_INSTANCE_TAG
+{
+    HTTP_PROXY_IO_STATE http_proxy_io_state;
+    ON_BYTES_RECEIVED on_bytes_received;
+    void* on_bytes_received_context;
+    ON_IO_ERROR on_io_error;
+    void* on_io_error_context;
+    ON_IO_OPEN_COMPLETE on_io_open_complete;
+    void* on_io_open_complete_context;
+    ON_IO_CLOSE_COMPLETE on_io_close_complete;
+    void* on_io_close_complete_context;
+    char* hostname;
+    int port;
+    char* proxy_hostname;
+    int proxy_port;
+    char* username;
+    char* password;
+    XIO_HANDLE underlying_io;
+    unsigned char* receive_buffer;
+    size_t receive_buffer_size;
+} HTTP_PROXY_IO_INSTANCE;
+
+static CONCRETE_IO_HANDLE http_proxy_io_create(void* io_create_parameters)
+{
+    HTTP_PROXY_IO_INSTANCE* result;
+
+    if (io_create_parameters == NULL)
+    {
+        /* Codes_SRS_HTTP_PROXY_IO_01_002: [ If io_create_parameters is NULL, http_proxy_io_create shall fail and return NULL. ]*/
+        result = NULL;
+        LogError("NULL io_create_parameters.");
+    }
+    else
+    {
+        /* Codes_SRS_HTTP_PROXY_IO_01_003: [ io_create_parameters shall be used as an HTTP_PROXY_IO_CONFIG*. ]*/
+        HTTP_PROXY_IO_CONFIG* http_proxy_io_config = (HTTP_PROXY_IO_CONFIG*)io_create_parameters;
+        if ((http_proxy_io_config->hostname == NULL) ||
+            (http_proxy_io_config->proxy_hostname == NULL))
+        {
+            /* Codes_SRS_HTTP_PROXY_IO_01_004: [ If the hostname or proxy_hostname member is NULL, then http_proxy_io_create shall fail and return NULL. ]*/
+            result = NULL;
+            LogError("Bad arguments: hostname = %p, proxy_hostname = %p",
+                http_proxy_io_config->hostname, http_proxy_io_config->proxy_hostname);
+        }
+        /* Codes_SRS_HTTP_PROXY_IO_01_095: [ If one of the fields username and password is non-NULL, then the other has to be also non-NULL, otherwise http_proxy_io_create shall fail and return NULL. ]*/
+        else if (((http_proxy_io_config->username == NULL) && (http_proxy_io_config->password != NULL)) ||
+            ((http_proxy_io_config->username != NULL) && (http_proxy_io_config->password == NULL)))
+        {
+            result = NULL;
+            LogError("Bad arguments: username = %p, password = %p",
+                http_proxy_io_config->username, http_proxy_io_config->password);
+        }
+        else
+        {
+            /* Codes_SRS_HTTP_PROXY_IO_01_001: [ http_proxy_io_create shall create a new instance of the HTTP proxy IO. ]*/
+            result = (HTTP_PROXY_IO_INSTANCE*)calloc(1, sizeof(HTTP_PROXY_IO_INSTANCE));
+            if (result == NULL)
+            {
+                /* Codes_SRS_HTTP_PROXY_IO_01_051: [ If allocating memory for the new instance fails, http_proxy_io_create shall fail and return NULL. ]*/
+                LogError("Failed allocating HTTP proxy IO instance.");
+            }
+            else
+            {
+                /* Codes_SRS_HTTP_PROXY_IO_01_005: [ http_proxy_io_create shall copy the hostname, port, username and password values for later use when the actual CONNECT is performed. ]*/
+                /* Codes_SRS_HTTP_PROXY_IO_01_006: [ hostname and proxy_hostname, username and password shall be copied by calling mallocAndStrcpy_s. ]*/
+                if (mallocAndStrcpy_s(&result->hostname, http_proxy_io_config->hostname) != 0)
+                {
+                    /* Codes_SRS_HTTP_PROXY_IO_01_007: [ If mallocAndStrcpy_s fails then http_proxy_io_create shall fail and return NULL. ]*/
+                    LogError("Failed to copy the hostname.");
+                    /* Codes_SRS_HTTP_PROXY_IO_01_008: [ When http_proxy_io_create fails, all allocated resources up to that point shall be freed. ]*/
+                    free(result);
+                    result = NULL;
+                }
+                else
+                {
+                    /* Codes_SRS_HTTP_PROXY_IO_01_006: [ hostname and proxy_hostname, username and password shall be copied by calling mallocAndStrcpy_s. ]*/
+                    if (mallocAndStrcpy_s(&result->proxy_hostname, http_proxy_io_config->proxy_hostname) != 0)
+                    {
+                        /* Codes_SRS_HTTP_PROXY_IO_01_007: [ If mallocAndStrcpy_s fails then http_proxy_io_create shall fail and return NULL. ]*/
+                        LogError("Failed to copy the proxy_hostname.");
+                        /* Codes_SRS_HTTP_PROXY_IO_01_008: [ When http_proxy_io_create fails, all allocated resources up to that point shall be freed. ]*/
+                        free(result->hostname);
+                        free(result);
+                        result = NULL;
+                    }
+                    else
+                    {
+                        result->username = NULL;
+                        result->password = NULL;
+
+                        /* Codes_SRS_HTTP_PROXY_IO_01_006: [ hostname and proxy_hostname, username and password shall be copied by calling mallocAndStrcpy_s. ]*/
+                        /* Codes_SRS_HTTP_PROXY_IO_01_094: [ username and password shall be optional. ]*/
+                        if ((http_proxy_io_config->username != NULL) && (mallocAndStrcpy_s(&result->username, http_proxy_io_config->username) != 0))
+                        {
+                            /* Codes_SRS_HTTP_PROXY_IO_01_007: [ If mallocAndStrcpy_s fails then http_proxy_io_create shall fail and return NULL. ]*/
+                            LogError("Failed to copy the username.");
+                            /* Codes_SRS_HTTP_PROXY_IO_01_008: [ When http_proxy_io_create fails, all allocated resources up to that point shall be freed. ]*/
+                            free(result->proxy_hostname);
+                            free(result->hostname);
+                            free(result);
+                            result = NULL;
+                        }
+                        else
+                        {
+                            /* Codes_SRS_HTTP_PROXY_IO_01_006: [ hostname and proxy_hostname, username and password shall be copied by calling mallocAndStrcpy_s. ]*/
+                            /* Codes_SRS_HTTP_PROXY_IO_01_094: [ username and password shall be optional. ]*/
+                            if ((http_proxy_io_config->password != NULL) && (mallocAndStrcpy_s(&result->password, http_proxy_io_config->password) != 0))
+                            {
+                                /* Codes_SRS_HTTP_PROXY_IO_01_007: [ If mallocAndStrcpy_s fails then http_proxy_io_create shall fail and return NULL. ]*/
+                                LogError("Failed to copy the passowrd.");
+                                /* Codes_SRS_HTTP_PROXY_IO_01_008: [ When http_proxy_io_create fails, all allocated resources up to that point shall be freed. ]*/
+                                free(result->username);
+                                free(result->proxy_hostname);
+                                free(result->hostname);
+                                free(result);
+                                result = NULL;
+                            }
+                            else
+                            {
+                                /* Codes_SRS_HTTP_PROXY_IO_01_010: [ - io_interface_description shall be set to the result of socketio_get_interface_description. ]*/
+                                const IO_INTERFACE_DESCRIPTION* underlying_io_interface = socketio_get_interface_description();
+                                if (underlying_io_interface == NULL)
+                                {
+                                    /* Codes_SRS_HTTP_PROXY_IO_01_050: [ If socketio_get_interface_description fails, http_proxy_io_create shall fail and return NULL. ]*/
+                                    LogError("Unable to get the socket IO interface description.");
+                                    /* Codes_SRS_HTTP_PROXY_IO_01_008: [ When http_proxy_io_create fails, all allocated resources up to that point shall be freed. ]*/
+                                    free(result->password);
+                                    free(result->username);
+                                    free(result->proxy_hostname);
+                                    free(result->hostname);
+                                    free(result);
+                                    result = NULL;
+                                }
+                                else
+                                {
+                                    SOCKETIO_CONFIG socket_io_config;
+
+                                    /* Codes_SRS_HTTP_PROXY_IO_01_011: [ - xio_create_parameters shall be set to a SOCKETIO_CONFIG* where hostname is set to the proxy_hostname member of io_create_parameters and port is set to the proxy_port member of io_create_parameters. ]*/
+                                    socket_io_config.hostname = http_proxy_io_config->proxy_hostname;
+                                    socket_io_config.port = http_proxy_io_config->proxy_port;
+                                    socket_io_config.accepted_socket = NULL;
+
+                                    /* Codes_SRS_HTTP_PROXY_IO_01_009: [ http_proxy_io_create shall create a new socket IO by calling xio_create with the arguments: ]*/
+                                    result->underlying_io = xio_create(underlying_io_interface, &socket_io_config);
+                                    if (result->underlying_io == NULL)
+                                    {
+                                        /* Codes_SRS_HTTP_PROXY_IO_01_012: [ If xio_create fails, http_proxy_io_create shall fail and return NULL. ]*/
+                                        LogError("Unable to create the underlying IO.");
+                                        /* Codes_SRS_HTTP_PROXY_IO_01_008: [ When http_proxy_io_create fails, all allocated resources up to that point shall be freed. ]*/
+                                        free(result->password);
+                                        free(result->username);
+                                        free(result->proxy_hostname);
+                                        free(result->hostname);
+                                        free(result);
+                                        result = NULL;
+                                    }
+                                    else
+                                    {
+                                        result->port = http_proxy_io_config->port;
+                                        result->proxy_port = http_proxy_io_config->proxy_port;
+                                        result->receive_buffer = NULL;
+                                        result->receive_buffer_size = 0;
+                                        result->http_proxy_io_state = HTTP_PROXY_IO_STATE_CLOSED;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+static void http_proxy_io_destroy(CONCRETE_IO_HANDLE http_proxy_io)
+{
+    if (http_proxy_io == NULL)
+    {
+        /* Codes_SRS_HTTP_PROXY_IO_01_014: [ If http_proxy_io is NULL, http_proxy_io_destroy shall do nothing. ]*/
+        LogError("NULL http_proxy_io.");
+    }
+    else
+    {
+        HTTP_PROXY_IO_INSTANCE* http_proxy_io_instance = (HTTP_PROXY_IO_INSTANCE*)http_proxy_io;
+
+        /* Codes_SRS_HTTP_PROXY_IO_01_013: [ http_proxy_io_destroy shall free the HTTP proxy IO instance indicated by http_proxy_io. ]*/
+        if (http_proxy_io_instance->receive_buffer != NULL)
+        {
+            free(http_proxy_io_instance->receive_buffer);
+        }
+
+        /* Codes_SRS_HTTP_PROXY_IO_01_016: [ http_proxy_io_destroy shall destroy the underlying IO created in http_proxy_io_create by calling xio_destroy. ]*/
+        xio_destroy(http_proxy_io_instance->underlying_io);
+        free(http_proxy_io_instance->hostname);
+        free(http_proxy_io_instance->proxy_hostname);
+        free(http_proxy_io_instance->username);
+        free(http_proxy_io_instance->password);
+        free(http_proxy_io_instance);
+    }
+}
+
+static void indicate_open_complete_error_and_close(HTTP_PROXY_IO_INSTANCE* http_proxy_io_instance)
+{
+    http_proxy_io_instance->http_proxy_io_state = HTTP_PROXY_IO_STATE_CLOSED;
+    (void)xio_close(http_proxy_io_instance->underlying_io, NULL, NULL);
+    http_proxy_io_instance->on_io_open_complete(http_proxy_io_instance->on_io_open_complete_context, IO_OPEN_ERROR);
+}
+
+// This callback usage needs to be either verified and commented or integrated into
+// the state machine.
+static void unchecked_on_send_complete(void* context, IO_SEND_RESULT send_result)
+{
+    (void)context;
+    (void)send_result;
+}
+
+static void on_underlying_io_open_complete(void* context, IO_OPEN_RESULT open_result)
+{
+    if (context == NULL)
+    {
+        /* Codes_SRS_HTTP_PROXY_IO_01_081: [ on_underlying_io_open_complete called with NULL context shall do nothing. ]*/
+        LogError("NULL context in on_underlying_io_open_complete");
+    }
+    else
+    {
+        HTTP_PROXY_IO_INSTANCE* http_proxy_io_instance = (HTTP_PROXY_IO_INSTANCE*)context;
+        switch (http_proxy_io_instance->http_proxy_io_state)
+        {
+        default:
+            LogError("on_underlying_io_open_complete called in an unexpected state.");
+            break;
+
+        case HTTP_PROXY_IO_STATE_CLOSING:
+        case HTTP_PROXY_IO_STATE_OPEN:
+            /* Codes_SRS_HTTP_PROXY_IO_01_077: [ When on_underlying_io_open_complete is called in after OPEN has completed, the on_io_error callback shall be triggered passing the on_io_error_context argument as context. ]*/
+            http_proxy_io_instance->on_io_error(http_proxy_io_instance->on_io_error_context);
+            break;
+
+        case HTTP_PROXY_IO_STATE_WAITING_FOR_CONNECT_RESPONSE:
+            /* Codes_SRS_HTTP_PROXY_IO_01_076: [ When on_underlying_io_open_complete is called while waiting for the CONNECT reply, the on_open_complete callback shall be triggered with IO_OPEN_ERROR, passing also the on_open_complete_context argument as context. ]*/
+            LogError("Open complete called again by underlying IO.");
+            indicate_open_complete_error_and_close(http_proxy_io_instance);
+            break;
+
+        case HTTP_PROXY_IO_STATE_OPENING_UNDERLYING_IO:
+            switch (open_result)
+            {
+            default:
+            case IO_OPEN_ERROR:
+                /* Codes_SRS_HTTP_PROXY_IO_01_078: [ When on_underlying_io_open_complete is called with IO_OPEN_ERROR, the on_open_complete callback shall be triggered with IO_OPEN_ERROR, passing also the on_open_complete_context argument as context. ]*/
+                LogError("Underlying IO open failed");
+                indicate_open_complete_error_and_close(http_proxy_io_instance);
+                break;
+
+            case IO_OPEN_CANCELLED:
+                /* Codes_SRS_HTTP_PROXY_IO_01_079: [ When on_underlying_io_open_complete is called with IO_OPEN_CANCELLED, the on_open_complete callback shall be triggered with IO_OPEN_CANCELLED, passing also the on_open_complete_context argument as context. ]*/
+                LogError("Underlying IO open failed");
+                http_proxy_io_instance->http_proxy_io_state = HTTP_PROXY_IO_STATE_CLOSED;
+                (void)xio_close(http_proxy_io_instance->underlying_io, NULL, NULL);
+                http_proxy_io_instance->on_io_open_complete(http_proxy_io_instance->on_io_open_complete_context, IO_OPEN_CANCELLED);
+                break;
+
+            case IO_OPEN_OK:
+            {
+                STRING_HANDLE encoded_auth_string;
+
+                /* Codes_SRS_HTTP_PROXY_IO_01_057: [ When on_underlying_io_open_complete is called, the http_proxy_io shall send the CONNECT request constructed per RFC 2817: ]*/
+                http_proxy_io_instance->http_proxy_io_state = HTTP_PROXY_IO_STATE_WAITING_FOR_CONNECT_RESPONSE;
+
+                if (http_proxy_io_instance->username != NULL)
+                {
+                    char* plain_auth_string_bytes;
+
+                    /* Codes_SRS_HTTP_PROXY_IO_01_060: [ - The value of Proxy-Authorization shall be the constructed according to RFC 2617. ]*/
+                    int plain_auth_string_length = (int)(strlen(http_proxy_io_instance->username)+1);
+                    if (http_proxy_io_instance->password != NULL)
+                    {
+                        plain_auth_string_length += (int)strlen(http_proxy_io_instance->password);
+                    }
+
+                    if (plain_auth_string_length < 0)
+                    {
+                        /* Codes_SRS_HTTP_PROXY_IO_01_062: [ If any failure is encountered while constructing the request, the on_open_complete callback shall be triggered with IO_OPEN_ERROR, passing also the on_open_complete_context argument as context. ]*/
+                        encoded_auth_string = NULL;
+                        indicate_open_complete_error_and_close(http_proxy_io_instance);
+                    }
+                    else
+                    {
+                        plain_auth_string_bytes = (char*)malloc(plain_auth_string_length + 1);
+                        if (plain_auth_string_bytes == NULL)
+                        {
+                            /* Codes_SRS_HTTP_PROXY_IO_01_062: [ If any failure is encountered while constructing the request, the on_open_complete callback shall be triggered with IO_OPEN_ERROR, passing also the on_open_complete_context argument as context. ]*/
+                            encoded_auth_string = NULL;
+                            indicate_open_complete_error_and_close(http_proxy_io_instance);
+                        }
+                        else
+                        {
+                            /* Codes_SRS_HTTP_PROXY_IO_01_091: [ To receive authorization, the client sends the userid and password, separated by a single colon (":") character, within a base64 [7] encoded string in the credentials. ]*/
+                            /* Codes_SRS_HTTP_PROXY_IO_01_092: [ A client MAY preemptively send the corresponding Authorization header with requests for resources in that space without receipt of another challenge from the server. ]*/
+                            /* Codes_SRS_HTTP_PROXY_IO_01_093: [ Userids might be case sensitive. ]*/
+                            if (sprintf(plain_auth_string_bytes, "%s:%s", http_proxy_io_instance->username, (http_proxy_io_instance->password == NULL) ? "" : http_proxy_io_instance->password) < 0)
+                            {
+                                /* Codes_SRS_HTTP_PROXY_IO_01_062: [ If any failure is encountered while constructing the request, the on_open_complete callback shall be triggered with IO_OPEN_ERROR, passing also the on_open_complete_context argument as context. ]*/
+                                encoded_auth_string = NULL;
+                                indicate_open_complete_error_and_close(http_proxy_io_instance);
+                            }
+                            else
+                            {
+                                /* Codes_SRS_HTTP_PROXY_IO_01_061: [ Encoding to Base64 shall be done by calling Azure_Base64_Encode_Bytes. ]*/
+                                encoded_auth_string = Azure_Base64_Encode_Bytes((const unsigned char*)plain_auth_string_bytes, plain_auth_string_length);
+                                if (encoded_auth_string == NULL)
+                                {
+                                    /* Codes_SRS_HTTP_PROXY_IO_01_062: [ If any failure is encountered while constructing the request, the on_open_complete callback shall be triggered with IO_OPEN_ERROR, passing also the on_open_complete_context argument as context. ]*/
+                                    LogError("Cannot Base64 encode auth string");
+                                    indicate_open_complete_error_and_close(http_proxy_io_instance);
+                                }
+                            }
+
+                            free(plain_auth_string_bytes);
+                        }
+                    }
+                }
+                else
+                {
+                    encoded_auth_string = NULL;
+                }
+
+                if ((http_proxy_io_instance->username != NULL) &&
+                    (encoded_auth_string == NULL))
+                {
+                    LogError("Cannot create authorization header");
+                }
+                else
+                {
+                    int connect_request_length;
+                    const char* auth_string_payload;
+                    /* Codes_SRS_HTTP_PROXY_IO_01_075: [ The Request-URI portion of the Request-Line is always an 'authority' as defined by URI Generic Syntax [2], which is to say the host name and port number destination of the requested connection separated by a colon: ]*/
+                    const char request_format[] = "CONNECT %s:%d HTTP/1.1\r\nHost:%s:%d%s%s\r\n\r\n";
+                    const char proxy_basic[] = "\r\nProxy-authorization: Basic ";
+                    if (http_proxy_io_instance->username != NULL)
+                    {
+                        auth_string_payload = STRING_c_str(encoded_auth_string);
+                    }
+                    else
+                    {
+                        auth_string_payload = "";
+                    }
+
+                    /* Codes_SRS_HTTP_PROXY_IO_01_059: [ - If username and password have been specified in the arguments passed to http_proxy_io_create, then the header Proxy-Authorization shall be added to the request. ]*/
+
+                    connect_request_length = (int)(strlen(request_format)+(strlen(http_proxy_io_instance->hostname)*2)+strlen(auth_string_payload)+10);
+                    if (http_proxy_io_instance->username != NULL)
+                    {
+                        connect_request_length += (int)strlen(proxy_basic);
+                    }
+
+                    if (connect_request_length < 0)
+                    {
+                        /* Codes_SRS_HTTP_PROXY_IO_01_062: [ If any failure is encountered while constructing the request, the on_open_complete callback shall be triggered with IO_OPEN_ERROR, passing also the on_open_complete_context argument as context. ]*/
+                        LogError("Cannot encode the CONNECT request");
+                        indicate_open_complete_error_and_close(http_proxy_io_instance);
+                    }
+                    else
+                    {
+                        char* connect_request = (char*)malloc(connect_request_length + 1);
+                        if (connect_request == NULL)
+                        {
+                            /* Codes_SRS_HTTP_PROXY_IO_01_062: [ If any failure is encountered while constructing the request, the on_open_complete callback shall be triggered with IO_OPEN_ERROR, passing also the on_open_complete_context argument as context. ]*/
+                            LogError("Cannot allocate memory for CONNECT request");
+                            indicate_open_complete_error_and_close(http_proxy_io_instance);
+                        }
+                        else
+                        {
+                            /* Codes_SRS_HTTP_PROXY_IO_01_059: [ - If username and password have been specified in the arguments passed to http_proxy_io_create, then the header Proxy-Authorization shall be added to the request. ]*/
+                            connect_request_length = sprintf(connect_request, request_format,
+                                http_proxy_io_instance->hostname,
+                                http_proxy_io_instance->port,
+                                http_proxy_io_instance->hostname,
+                                http_proxy_io_instance->port,
+                                (http_proxy_io_instance->username != NULL) ? proxy_basic : "",
+                                auth_string_payload);
+
+                            if (connect_request_length < 0)
+                            {
+                                /* Codes_SRS_HTTP_PROXY_IO_01_062: [ If any failure is encountered while constructing the request, the on_open_complete callback shall be triggered with IO_OPEN_ERROR, passing also the on_open_complete_context argument as context. ]*/
+                                LogError("Cannot encode the CONNECT request");
+                                indicate_open_complete_error_and_close(http_proxy_io_instance);
+                            }
+                            else
+                            {
+                                /* Codes_SRS_HTTP_PROXY_IO_01_063: [ The request shall be sent by calling xio_send and passing NULL as on_send_complete callback. ]*/
+                                if (xio_send(http_proxy_io_instance->underlying_io, connect_request, connect_request_length, unchecked_on_send_complete, NULL) != 0)
+                                {
+                                    /* Codes_SRS_HTTP_PROXY_IO_01_064: [ If xio_send fails, the on_open_complete callback shall be triggered with IO_OPEN_ERROR, passing also the on_open_complete_context argument as context. ]*/
+                                    LogError("Could not send CONNECT request");
+                                    indicate_open_complete_error_and_close(http_proxy_io_instance);
+                                }
+                            }
+
+                            free(connect_request);
+                        }
+                    }
+                }
+
+                if (encoded_auth_string != NULL)
+                {
+                    STRING_delete(encoded_auth_string);
+                }
+
+                break;
+            }
+            }
+
+            break;
+        }
+    }
+}
+
+static void on_underlying_io_error(void* context)
+{
+    if (context == NULL)
+    {
+        /* Codes_SRS_HTTP_PROXY_IO_01_088: [ on_underlying_io_error called with NULL context shall do nothing. ]*/
+        LogError("NULL context in on_underlying_io_error");
+    }
+    else
+    {
+        HTTP_PROXY_IO_INSTANCE* http_proxy_io_instance = (HTTP_PROXY_IO_INSTANCE*)context;
+
+        switch (http_proxy_io_instance->http_proxy_io_state)
+        {
+        default:
+            LogError("on_underlying_io_error in invalid state");
+            break;
+
+        case HTTP_PROXY_IO_STATE_OPENING_UNDERLYING_IO:
+        case HTTP_PROXY_IO_STATE_WAITING_FOR_CONNECT_RESPONSE:
+            /* Codes_SRS_HTTP_PROXY_IO_01_087: [ If the on_underlying_io_error callback is called while OPENING, the on_open_complete callback shall be triggered with IO_OPEN_ERROR, passing also the on_open_complete_context argument as context. ]*/
+            indicate_open_complete_error_and_close(http_proxy_io_instance);
+            break;
+
+        case HTTP_PROXY_IO_STATE_OPEN:
+            /* Codes_SRS_HTTP_PROXY_IO_01_089: [ If the on_underlying_io_error callback is called while the IO is OPEN, the on_io_error callback shall be called with the on_io_error_context argument as context. ]*/
+            http_proxy_io_instance->http_proxy_io_state = HTTP_PROXY_IO_STATE_ERROR;
+            http_proxy_io_instance->on_io_error(http_proxy_io_instance->on_io_error_context);
+            break;
+        }
+    }
+}
+
+static void on_underlying_io_close_complete(void* context)
+{
+    if (context == NULL)
+    {
+        /* Cdoes_SRS_HTTP_PROXY_IO_01_084: [ on_underlying_io_close_complete called with NULL context shall do nothing. ]*/
+        LogError("NULL context in on_underlying_io_open_complete");
+    }
+    else
+    {
+        HTTP_PROXY_IO_INSTANCE* http_proxy_io_instance = (HTTP_PROXY_IO_INSTANCE*)context;
+
+        switch (http_proxy_io_instance->http_proxy_io_state)
+        {
+        default:
+            LogError("on_underlying_io_close_complete called in an invalid state");
+            break;
+
+        case HTTP_PROXY_IO_STATE_CLOSING:
+            http_proxy_io_instance->http_proxy_io_state = HTTP_PROXY_IO_STATE_CLOSED;
+
+            /* Codes_SRS_HTTP_PROXY_IO_01_086: [ If the on_io_close_complete callback passed to http_proxy_io_close was NULL, no callback shall be triggered. ]*/
+            if (http_proxy_io_instance->on_io_close_complete != NULL)
+            {
+                /* Codes_SRS_HTTP_PROXY_IO_01_083: [ on_underlying_io_close_complete while CLOSING shall call the on_io_close_complete callback, passing to it the on_io_close_complete_context as context argument. ]*/
+                http_proxy_io_instance->on_io_close_complete(http_proxy_io_instance->on_io_close_complete_context);
+            }
+
+            break;
+        }
+    }
+}
+
+/*the following function does the same as sscanf(pos2, "%d", &sec)*/
+/*this function only exists because some of platforms do not have sscanf. */
+static int ParseStringToDecimal(const char *src, int* dst)
+{
+    int result;
+    char* next;
+
+    (*dst) = (int)strtol(src, &next, 0);
+    if ((src == next) || ((((*dst) == INT_MAX) || ((*dst) == INT_MIN)) && (errno != 0)))
+    {
+        result = __LINE__;
+    }
+    else
+    {
+        result = 0;
+    }
+
+    return result;
+}
+
+/*the following function does the same as sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &ret) */
+/*this function only exists because some of platforms do not have sscanf. This is not a full implementation; it only works with well-defined HTTP response. */
+static int ParseHttpResponse(const char* src, int* dst)
+{
+    int result;
+    static const char HTTPPrefix[] = "HTTP/";
+    bool fail;
+    const char* runPrefix;
+
+    if ((src == NULL) || (dst == NULL))
+    {
+        result = __LINE__;
+    }
+    else
+    {
+        fail = false;
+        runPrefix = HTTPPrefix;
+
+        while ((*runPrefix) != '\0')
+        {
+            if ((*runPrefix) != (*src))
+            {
+                fail = true;
+                break;
+            }
+            src++;
+            runPrefix++;
+        }
+
+        if (!fail)
+        {
+            while ((*src) != '.')
+            {
+                if ((*src) == '\0')
+                {
+                    fail = true;
+                    break;
+                }
+                src++;
+            }
+        }
+
+        if (!fail)
+        {
+            while ((*src) != ' ')
+            {
+                if ((*src) == '\0')
+                {
+                    fail = true;
+                    break;
+                }
+                src++;
+            }
+        }
+
+        if (fail)
+        {
+            result = __LINE__;
+        }
+        else
+        {
+            if (ParseStringToDecimal(src, dst) != 0)
+            {
+                result = __LINE__;
+            }
+            else
+            {
+                result = 0;
+            }
+        }
+    }
+
+    return result;
+}
+
+static void on_underlying_io_bytes_received(void* context, const unsigned char* buffer, size_t size)
+{
+    if (context == NULL)
+    {
+        /* Codes_SRS_HTTP_PROXY_IO_01_082: [ on_underlying_io_bytes_received called with NULL context shall do nothing. ]*/
+        LogError("NULL context in on_underlying_io_bytes_received");
+    }
+    else
+    {
+        HTTP_PROXY_IO_INSTANCE* http_proxy_io_instance = (HTTP_PROXY_IO_INSTANCE*)context;
+
+        switch (http_proxy_io_instance->http_proxy_io_state)
+        {
+        default:
+        case HTTP_PROXY_IO_STATE_CLOSING:
+            LogError("Bytes received in invalid state");
+            break;
+
+        case HTTP_PROXY_IO_STATE_OPENING_UNDERLYING_IO:
+            /* Codes_SRS_HTTP_PROXY_IO_01_080: [ If on_underlying_io_bytes_received is called while the underlying IO is being opened, the on_open_complete callback shall be triggered with IO_OPEN_ERROR, passing also the on_open_complete_context argument as context. ]*/
+            LogError("Bytes received while opening underlying IO");
+            indicate_open_complete_error_and_close(http_proxy_io_instance);
+            break;
+
+        case HTTP_PROXY_IO_STATE_WAITING_FOR_CONNECT_RESPONSE:
+        {
+            /* Codes_SRS_HTTP_PROXY_IO_01_065: [ When bytes are received and the response to the CONNECT request was not yet received, the bytes shall be accumulated until a double new-line is detected. ]*/
+            unsigned char* new_receive_buffer = (unsigned char*)realloc(http_proxy_io_instance->receive_buffer, http_proxy_io_instance->receive_buffer_size + size + 1);
+            if (new_receive_buffer == NULL)
+            {
+                /* Codes_SRS_HTTP_PROXY_IO_01_067: [ If allocating memory for the buffered bytes fails, the on_open_complete callback shall be triggered with IO_OPEN_ERROR, passing also the on_open_complete_context argument as context. ]*/
+                LogError("Cannot allocate memory for received data");
+                indicate_open_complete_error_and_close(http_proxy_io_instance);
+            }
+            else
+            {
+                http_proxy_io_instance->receive_buffer = new_receive_buffer;
+                memcpy(http_proxy_io_instance->receive_buffer + http_proxy_io_instance->receive_buffer_size, buffer, size);
+                http_proxy_io_instance->receive_buffer_size += size;
+            }
+
+            if (http_proxy_io_instance->receive_buffer_size >= 4)
+            {
+                const char* request_end_ptr;
+
+                http_proxy_io_instance->receive_buffer[http_proxy_io_instance->receive_buffer_size] = 0;
+
+                /* Codes_SRS_HTTP_PROXY_IO_01_066: [ When a double new-line is detected the response shall be parsed in order to extract the status code. ]*/
+                if ((http_proxy_io_instance->receive_buffer_size >= 4) &&
+                    ((request_end_ptr = strstr((const char*)http_proxy_io_instance->receive_buffer, "\r\n\r\n")) != NULL))
+                {
+                    int status_code;
+
+                    /* This part should really be done with the HTTPAPI, but that has to be done as a separate step
+                    as the HTTPAPI has to expose somehow the underlying IO and currently this would be a too big of a change. */
+
+                    if (ParseHttpResponse((const char*)http_proxy_io_instance->receive_buffer, &status_code) != 0)
+                    {
+                        /* Codes_SRS_HTTP_PROXY_IO_01_068: [ If parsing the CONNECT response fails, the on_open_complete callback shall be triggered with IO_OPEN_ERROR, passing also the on_open_complete_context argument as context. ]*/
+                        LogError("Cannot decode HTTP response");
+                        indicate_open_complete_error_and_close(http_proxy_io_instance);
+                    }
+                    /* Codes_SRS_HTTP_PROXY_IO_01_069: [ Any successful (2xx) response to a CONNECT request indicates that the proxy has established a connection to the requested host and port, and has switched to tunneling the current connection to that server connection. ]*/
+                    /* Codes_SRS_HTTP_PROXY_IO_01_090: [ Any successful (2xx) response to a CONNECT request indicates that the proxy has established a connection to the requested host and port, and has switched to tunneling the current connection to that server connection. ]*/
+                    else if ((status_code < 200) || (status_code > 299))
+                    {
+                        /* Codes_SRS_HTTP_PROXY_IO_01_071: [ If the status code is not successful, the on_open_complete callback shall be triggered with IO_OPEN_ERROR, passing also the on_open_complete_context argument as context. ]*/
+                        LogError("Bad status (%d) received in CONNECT response", status_code);
+                        indicate_open_complete_error_and_close(http_proxy_io_instance);
+                    }
+                    else
+                    {
+                        size_t length_remaining = http_proxy_io_instance->receive_buffer + http_proxy_io_instance->receive_buffer_size - ((const unsigned char *)request_end_ptr + 4);
+
+                        /* Codes_SRS_HTTP_PROXY_IO_01_073: [ Once a success status code was parsed, the IO shall be OPEN. ]*/
+                        http_proxy_io_instance->http_proxy_io_state = HTTP_PROXY_IO_STATE_OPEN;
+                        /* Codes_SRS_HTTP_PROXY_IO_01_070: [ When a success status code is parsed, the on_open_complete callback shall be triggered with IO_OPEN_OK, passing also the on_open_complete_context argument as context. ]*/
+                        http_proxy_io_instance->on_io_open_complete(http_proxy_io_instance->on_io_open_complete_context, IO_OPEN_OK);
+
+                        if (length_remaining > 0)
+                        {
+                            /* Codes_SRS_HTTP_PROXY_IO_01_072: [ Any bytes that are extra (not consumed by the CONNECT response), shall be indicated as received by calling the on_bytes_received callback and passing the on_bytes_received_context as context argument. ]*/
+                            http_proxy_io_instance->on_bytes_received(http_proxy_io_instance->on_bytes_received_context, (const unsigned char*)request_end_ptr + 4, length_remaining);
+                        }
+                    }
+                }
+            }
+            break;
+        }
+        case HTTP_PROXY_IO_STATE_OPEN:
+            /* Codes_SRS_HTTP_PROXY_IO_01_074: [ If on_underlying_io_bytes_received is called while OPEN, all bytes shall be indicated as received by calling the on_bytes_received callback and passing the on_bytes_received_context as context argument. ]*/
+            http_proxy_io_instance->on_bytes_received(http_proxy_io_instance->on_bytes_received_context, buffer, size);
+            break;
+        }
+    }
+}
+
+static int http_proxy_io_open(CONCRETE_IO_HANDLE http_proxy_io, ON_IO_OPEN_COMPLETE on_io_open_complete, void* on_io_open_complete_context, ON_BYTES_RECEIVED on_bytes_received, void* on_bytes_received_context, ON_IO_ERROR on_io_error, void* on_io_error_context)
+{
+    int result;
+
+    /* Codes_SRS_HTTP_PROXY_IO_01_051: [ The arguments on_io_open_complete_context, on_bytes_received_context and on_io_error_context shall be allowed to be NULL. ]*/
+    /* Codes_SRS_HTTP_PROXY_IO_01_018: [ If any of the arguments http_proxy_io, on_io_open_complete, on_bytes_received or on_io_error are NULL then http_proxy_io_open shall return a non-zero value. ]*/
+    if ((http_proxy_io == NULL) ||
+        (on_io_open_complete == NULL) ||
+        (on_bytes_received == NULL) ||
+        (on_io_error == NULL))
+    {
+        LogError("Bad arguments: http_proxy_io = %p, on_io_open_complete = %p, on_bytes_received = %p, on_io_error_context = %p.",
+            http_proxy_io,
+            on_io_open_complete,
+            on_bytes_received,
+            on_io_error);
+        result = __LINE__;
+    }
+    else
+    {
+        HTTP_PROXY_IO_INSTANCE* http_proxy_io_instance = (HTTP_PROXY_IO_INSTANCE*)http_proxy_io;
+
+        if (http_proxy_io_instance->http_proxy_io_state != HTTP_PROXY_IO_STATE_CLOSED)
+        {
+            LogError("Invalid tlsio_state. Expected state is HTTP_PROXY_IO_STATE_CLOSED.");
+            result = __LINE__;
+        }
+        else
+        {
+            http_proxy_io_instance->on_bytes_received = on_bytes_received;
+            http_proxy_io_instance->on_bytes_received_context = on_bytes_received_context;
+
+            http_proxy_io_instance->on_io_error = on_io_error;
+            http_proxy_io_instance->on_io_error_context = on_io_error_context;
+
+            http_proxy_io_instance->on_io_open_complete = on_io_open_complete;
+            http_proxy_io_instance->on_io_open_complete_context = on_io_open_complete_context;
+
+            http_proxy_io_instance->http_proxy_io_state = HTTP_PROXY_IO_STATE_OPENING_UNDERLYING_IO;
+
+            /* Codes_SRS_HTTP_PROXY_IO_01_019: [ http_proxy_io_open shall open the underlying IO by calling xio_open on the underlying IO handle created in http_proxy_io_create, while passing to it the callbacks on_underlying_io_open_complete, on_underlying_io_bytes_received and on_underlying_io_error. ]*/
+            if (xio_open(http_proxy_io_instance->underlying_io, on_underlying_io_open_complete, http_proxy_io_instance, on_underlying_io_bytes_received, http_proxy_io_instance, on_underlying_io_error, http_proxy_io_instance) != 0)
+            {
+                /* Codes_SRS_HTTP_PROXY_IO_01_020: [ If xio_open fails, then http_proxy_io_open shall return a non-zero value. ]*/
+                http_proxy_io_instance->http_proxy_io_state = HTTP_PROXY_IO_STATE_CLOSED;
+                LogError("Cannot open the underlying IO.");
+                result = __LINE__;
+            }
+            else
+            {
+                /* Codes_SRS_HTTP_PROXY_IO_01_017: [ http_proxy_io_open shall open the HTTP proxy IO and on success it shall return 0. ]*/
+                result = 0;
+            }
+        }
+    }
+
+    return result;
+}
+
+static int http_proxy_io_close(CONCRETE_IO_HANDLE http_proxy_io, ON_IO_CLOSE_COMPLETE on_io_close_complete, void* on_io_close_complete_context)
+{
+    int result = 0;
+
+    /* Codes_SRS_HTTP_PROXY_IO_01_052: [ on_io_close_complete_context shall be allowed to be NULL. ]*/
+    /* Codes_SRS_HTTP_PROXY_IO_01_028: [ on_io_close_complete shall be allowed to be NULL. ]*/
+    if (http_proxy_io == NULL)
+    {
+        /* Codes_SRS_HTTP_PROXY_IO_01_023: [ If the argument http_proxy_io is NULL, http_proxy_io_close shall fail and return a non-zero value. ]*/
+        result = __LINE__;
+        LogError("NULL http_proxy_io.");
+    }
+    else
+    {
+        HTTP_PROXY_IO_INSTANCE* http_proxy_io_instance = (HTTP_PROXY_IO_INSTANCE*)http_proxy_io;
+
+        /* Codes_SRS_HTTP_PROXY_IO_01_027: [ If http_proxy_io_close is called when not open, http_proxy_io_close shall fail and return a non-zero value. ]*/
+        if ((http_proxy_io_instance->http_proxy_io_state == HTTP_PROXY_IO_STATE_CLOSED) ||
+            /* Codes_SRS_HTTP_PROXY_IO_01_054: [ http_proxy_io_close while OPENING shall fail and return a non-zero value. ]*/
+            (http_proxy_io_instance->http_proxy_io_state == HTTP_PROXY_IO_STATE_CLOSING))
+        {
+            result = __LINE__;
+            LogError("Invalid tlsio_state. Expected state is HTTP_PROXY_IO_STATE_OPEN.");
+        }
+        else if ((http_proxy_io_instance->http_proxy_io_state == HTTP_PROXY_IO_STATE_OPENING_UNDERLYING_IO) ||
+            (http_proxy_io_instance->http_proxy_io_state == HTTP_PROXY_IO_STATE_WAITING_FOR_CONNECT_RESPONSE))
+        {
+            /* Codes_SRS_HTTP_PROXY_IO_01_053: [ http_proxy_io_close while OPENING shall trigger the on_io_open_complete callback with IO_OPEN_CANCELLED. ]*/
+            http_proxy_io_instance->http_proxy_io_state = HTTP_PROXY_IO_STATE_CLOSED;
+            (void)xio_close(http_proxy_io_instance->underlying_io, NULL, NULL);
+            http_proxy_io_instance->on_io_open_complete(http_proxy_io_instance->on_io_open_complete_context, IO_OPEN_CANCELLED);
+
+            /* Codes_SRS_HTTP_PROXY_IO_01_022: [ http_proxy_io_close shall close the HTTP proxy IO and on success it shall return 0. ]*/
+            result = 0;
+        }
+        else
+        {
+            HTTP_PROXY_IO_STATE previous_state = http_proxy_io_instance->http_proxy_io_state;
+
+            http_proxy_io_instance->http_proxy_io_state = HTTP_PROXY_IO_STATE_CLOSING;
+
+            /* Codes_SRS_HTTP_PROXY_IO_01_026: [ The on_io_close_complete and on_io_close_complete_context arguments shall be saved for later use. ]*/
+            http_proxy_io_instance->on_io_close_complete = on_io_close_complete;
+            http_proxy_io_instance->on_io_close_complete_context = on_io_close_complete_context;
+
+            /* Codes_SRS_HTTP_PROXY_IO_01_024: [ http_proxy_io_close shall close the underlying IO by calling xio_close on the IO handle create in http_proxy_io_create, while passing to it the on_underlying_io_close_complete callback. ]*/
+            if (xio_close(http_proxy_io_instance->underlying_io, on_underlying_io_close_complete, http_proxy_io_instance) != 0)
+            {
+                /* Codes_SRS_HTTP_PROXY_IO_01_025: [ If xio_close fails, http_proxy_io_close shall fail and return a non-zero value. ]*/
+                result = __LINE__;
+                http_proxy_io_instance->http_proxy_io_state = previous_state;
+                LogError("Cannot close underlying IO.");
+            }
+            else
+            {
+                /* Codes_SRS_HTTP_PROXY_IO_01_022: [ http_proxy_io_close shall close the HTTP proxy IO and on success it shall return 0. ]*/
+                result = 0;
+            }
+        }
+    }
+
+    return result;
+}
+
+static int http_proxy_io_send(CONCRETE_IO_HANDLE http_proxy_io, const void* buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void* on_send_complete_context)
+{
+    int result;
+
+    /* Codes_SRS_HTTP_PROXY_IO_01_032: [ on_send_complete shall be allowed to be NULL. ]*/
+    /* Codes_SRS_HTTP_PROXY_IO_01_030: [ If any of the arguments http_proxy_io or buffer is NULL, http_proxy_io_send shall fail and return a non-zero value. ]*/
+    if ((http_proxy_io == NULL) ||
+        (buffer == NULL) ||
+        /* Codes_SRS_HTTP_PROXY_IO_01_031: [ If size is 0, http_proxy_io_send shall fail and return a non-zero value. ]*/
+        (size == 0))
+    {
+        result = __LINE__;
+        LogError("Bad arguments: http_proxy_io = %p, buffer = %p.",
+            http_proxy_io, buffer);
+    }
+    else
+    {
+        HTTP_PROXY_IO_INSTANCE* http_proxy_io_instance = (HTTP_PROXY_IO_INSTANCE*)http_proxy_io;
+
+        /* Codes_SRS_HTTP_PROXY_IO_01_034: [ If http_proxy_io_send is called when the IO is not open, http_proxy_io_send shall fail and return a non-zero value. ]*/
+        /* Codes_SRS_HTTP_PROXY_IO_01_035: [ If the IO is in an error state (an error was reported through the on_io_error callback), http_proxy_io_send shall fail and return a non-zero value. ]*/
+        if (http_proxy_io_instance->http_proxy_io_state != HTTP_PROXY_IO_STATE_OPEN)
+        {
+            result = __LINE__;
+            LogError("Invalid HTTP proxy IO state. Expected state is HTTP_PROXY_IO_STATE_OPEN.");
+        }
+        else
+        {
+            /* Codes_SRS_HTTP_PROXY_IO_01_033: [ http_proxy_io_send shall send the bytes by calling xio_send on the underlying IO created in http_proxy_io_create and passing buffer and size as arguments. ]*/
+            if (xio_send(http_proxy_io_instance->underlying_io, buffer, size, on_send_complete, on_send_complete_context) != 0)
+            {
+                /* Codes_SRS_HTTP_PROXY_IO_01_055: [ If xio_send fails, http_proxy_io_send shall fail and return a non-zero value. ]*/
+                result = __LINE__;
+                LogError("Underlying xio_send failed.");
+            }
+            else
+            {
+                /* Codes_SRS_HTTP_PROXY_IO_01_029: [ http_proxy_io_send shall send the size bytes pointed to by buffer and on success it shall return 0. ]*/
+                result = 0;
+            }
+        }
+    }
+
+    return result;
+}
+
+static void http_proxy_io_dowork(CONCRETE_IO_HANDLE http_proxy_io)
+{
+    if (http_proxy_io == NULL)
+    {
+        /* Codes_SRS_HTTP_PROXY_IO_01_038: [ If the http_proxy_io argument is NULL, http_proxy_io_dowork shall do nothing. ]*/
+        LogError("NULL http_proxy_io.");
+    }
+    else
+    {
+        HTTP_PROXY_IO_INSTANCE* http_proxy_io_instance = (HTTP_PROXY_IO_INSTANCE*)http_proxy_io;
+
+        if (http_proxy_io_instance->http_proxy_io_state != HTTP_PROXY_IO_STATE_CLOSED)
+        {
+            /* Codes_SRS_HTTP_PROXY_IO_01_037: [ http_proxy_io_dowork shall call xio_dowork on the underlying IO created in http_proxy_io_create. ]*/
+            xio_dowork(http_proxy_io_instance->underlying_io);
+        }
+    }
+}
+
+static int http_proxy_io_set_option(CONCRETE_IO_HANDLE http_proxy_io, const char* option_name, const void* value)
+{
+    int result;
+
+    if ((http_proxy_io == NULL) || (option_name == NULL))
+    {
+        /* Codes_SRS_HTTP_PROXY_IO_01_040: [ If any of the arguments http_proxy_io or option_name is NULL, http_proxy_io_set_option shall return a non-zero value. ]*/
+        LogError("Bad arguments: http_proxy_io = %p, option_name = %p",
+            http_proxy_io, option_name);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        HTTP_PROXY_IO_INSTANCE* http_proxy_io_instance = (HTTP_PROXY_IO_INSTANCE*)http_proxy_io;
+
+        /* Codes_SRS_HTTP_PROXY_IO_01_045: [ None. ]*/
+
+        if (strcmp(option_name, OPTION_UNDERLYING_IO_OPTIONS) == 0)
+        {
+            if (OptionHandler_FeedOptions((OPTIONHANDLER_HANDLE)value, (void*)http_proxy_io_instance->underlying_io) != OPTIONHANDLER_OK)
+            {
+                LogError("failed feeding options to underlying I/O instance");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                result = 0;
+            }
+        }
+        /* Codes_SRS_HTTP_PROXY_IO_01_043: [ If the option_name argument indicates an option that is not handled by http_proxy_io_set_option, then xio_setoption shall be called on the underlying IO created in http_proxy_io_create, passing the option name and value to it. ]*/
+        /* Codes_SRS_HTTP_PROXY_IO_01_056: [ The value argument shall be allowed to be NULL. ]*/
+        else if (xio_setoption(http_proxy_io_instance->underlying_io, option_name, value) != 0)
+        {
+            /* Codes_SRS_HTTP_PROXY_IO_01_044: [ if xio_setoption fails, http_proxy_io_set_option shall return a non-zero value. ]*/
+            LogError("Unrecognized option %s", option_name);
+            result = MU_FAILURE;
+        }
+        else
+        {
+            /* Codes_SRS_HTTP_PROXY_IO_01_042: [ If the option was handled by http_proxy_io_set_option or the underlying IO, then http_proxy_io_set_option shall return 0. ]*/
+            result = 0;
+        }
+    }
+
+    return result;
+}
+
+/*this function will clone an option given by name and value*/
+static void* http_proxy_io_clone_option(const char* name, const void* value)
+{
+    void* result;
+    if (
+        (name == NULL) || (value == NULL)
+        )
+    {
+        LogError("invalid parameter detected: name=%p, value=%p", name, value);
+        result = NULL;
+    }
+    else
+    {
+        if (strcmp(name, OPTION_UNDERLYING_IO_OPTIONS) == 0)
+        {
+            result = (void*)value;
+        }
+        else
+        {
+            LogError("not handled option : %s", name);
+            result = NULL;
+        }
+    }
+
+    return result;
+}
+
+/*this function destroys an option previously created*/
+static void http_proxy_io_destroy_option(const char* name, const void* value)
+{
+    /*since all options for this layer are actually string copies., disposing of one is just calling free*/
+    if (
+        (name == NULL) || (value == NULL)
+        )
+    {
+        LogError("invalid parameter detected: const char* name=%p, const void* value=%p", name, value);
+    }
+    else
+    {
+        if (strcmp(name, OPTION_UNDERLYING_IO_OPTIONS) == 0)
+        {
+            OptionHandler_Destroy((OPTIONHANDLER_HANDLE)value);
+        }
+        else
+        {
+            LogError("not handled option : %s", name);
+        }
+    }
+}
+
+static OPTIONHANDLER_HANDLE http_proxy_io_retrieve_options(CONCRETE_IO_HANDLE http_proxy_io)
+{
+    OPTIONHANDLER_HANDLE result;
+
+    if (http_proxy_io == NULL)
+    {
+        /* Codes_SRS_HTTP_PROXY_IO_01_047: [ If the parameter http_proxy_io is NULL then http_proxy_io_retrieve_options shall fail and return NULL. ]*/
+        LogError("invalid parameter detected: CONCRETE_IO_HANDLE handle=%p", http_proxy_io);
+        result = NULL;
+    }
+    else
+    {
+        HTTP_PROXY_IO_INSTANCE* http_proxy_io_instance = (HTTP_PROXY_IO_INSTANCE*)http_proxy_io;
+
+        result = OptionHandler_Create(http_proxy_io_clone_option, http_proxy_io_destroy_option, http_proxy_io_set_option);
+
+        if (result == NULL)
+        {
+            LogError("OptionHandler_Create failed");
+        }
+        else
+        {
+            OPTIONHANDLER_HANDLE underlying_io_options;
+
+            /* Codes_SRS_HTTP_PROXY_IO_01_046: [ http_proxy_io_retrieve_options shall return an OPTIONHANDLER_HANDLE obtained by calling xio_retrieveoptions on the underlying IO created in http_proxy_io_create. ]*/
+            if ((underlying_io_options = xio_retrieveoptions(http_proxy_io_instance->underlying_io)) == NULL ||
+                OptionHandler_AddOption(result, OPTION_UNDERLYING_IO_OPTIONS, underlying_io_options) != OPTIONHANDLER_OK)
+            {
+                /* Codes_SRS_HTTP_PROXY_IO_01_048: [ If xio_retrieveoptions fails, http_proxy_io_retrieve_options shall return NULL. ]*/
+                LogError("unable to save underlying_io options");
+                OptionHandler_Destroy(underlying_io_options);
+                OptionHandler_Destroy(result);
+                result = NULL;
+            }
+            else
+            {
+                // All is fine.
+            }
+        }
+    }
+    return result;
+}
+
+static const IO_INTERFACE_DESCRIPTION http_proxy_io_interface_description =
+{
+    http_proxy_io_retrieve_options,
+    http_proxy_io_create,
+    http_proxy_io_destroy,
+    http_proxy_io_open,
+    http_proxy_io_close,
+    http_proxy_io_send,
+    http_proxy_io_dowork,
+    http_proxy_io_set_option
+};
+
+const IO_INTERFACE_DESCRIPTION* http_proxy_io_get_interface_description(void)
+{
+    /* Codes_SRS_HTTP_PROXY_IO_01_049: [ http_proxy_io_get_interface_description shall return a pointer to an IO_INTERFACE_DESCRIPTION structure that contains pointers to the functions: http_proxy_io_retrieve_options, http_proxy_io_retrieve_create, http_proxy_io_destroy, http_proxy_io_open, http_proxy_io_close, http_proxy_io_send and http_proxy_io_dowork. ]*/
+    return &http_proxy_io_interface_description;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/httpapiex.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/httpapiex.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/httpapiex.c	(revision 453)
@@ -0,0 +1,712 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/httpapiex.h"
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/strings.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/vector.h"
+
+typedef struct HTTPAPIEX_SAVED_OPTION_TAG
+{
+    const char* optionName;
+    const void* value;
+}HTTPAPIEX_SAVED_OPTION;
+
+typedef struct HTTPAPIEX_HANDLE_DATA_TAG
+{
+    STRING_HANDLE hostName;
+    int k;
+    HTTP_HANDLE httpHandle;
+    VECTOR_HANDLE savedOptions;
+}HTTPAPIEX_HANDLE_DATA;
+
+MU_DEFINE_ENUM_STRINGS(HTTPAPIEX_RESULT, HTTPAPIEX_RESULT_VALUES);
+
+#define LOG_HTTAPIEX_ERROR() LogError("error code = %" PRI_MU_ENUM "", MU_ENUM_VALUE(HTTPAPIEX_RESULT, result))
+
+static int useGlobalInitialization = 0;
+
+HTTPAPIEX_RESULT HTTPAPIEX_Init(void)
+{
+    HTTPAPIEX_RESULT result;
+
+    /*Codes_SRS_HTTPAPIEX_21_045: [If HTTPAPIEX_Init is calling more than once, it shall initialize the HTTP by calling HTTAPI_Init only once, and return success for all calls.] */
+    if (useGlobalInitialization == 0)
+    {
+        /*Codes_SRS_HTTPAPIEX_21_044: [HTTPAPIEX_Init shall initialize the HTTP by calling HTTAPI_Init.] */
+        if (HTTPAPI_Init() == HTTPAPI_OK)
+        {
+            useGlobalInitialization++;
+            result = HTTPAPIEX_OK;
+        }
+        else
+        {
+            /*Codes_SRS_HTTPAPIEX_21_046: [If HTTAPI_Init, HTTPAPIEX_Init shall return HTTPAPIEX_ERROR.] */
+            result = HTTPAPIEX_ERROR;
+        }
+    }
+    else
+    {
+        useGlobalInitialization++;
+        result = HTTPAPIEX_OK;
+    }
+
+    return result;
+}
+
+void HTTPAPIEX_Deinit(void)
+{
+    /*Codes_SRS_HTTPAPIEX_21_047: [HTTPAPIEX_Deinit shall de-initialize the HTTP by calling HTTAPI_Deinit.] */
+    useGlobalInitialization--;
+    if (useGlobalInitialization == 0)
+    {
+        HTTPAPI_Deinit();
+    }
+}
+
+HTTPAPIEX_HANDLE HTTPAPIEX_Create(const char* hostName)
+{
+    HTTPAPIEX_HANDLE result;
+    /*Codes_SRS_HTTPAPIEX_02_001: [If parameter hostName is NULL then HTTPAPIEX_Create shall return NULL.]*/
+    if (hostName == NULL)
+    {
+        LogError("invalid (NULL) parameter");
+        result = NULL;
+    }
+    else
+    {
+        /*Codes_SRS_HTTPAPIEX_02_005: [If creating the handle fails for any reason, then HTTAPIEX_Create shall return NULL.] */
+        HTTPAPIEX_HANDLE_DATA* handleData = (HTTPAPIEX_HANDLE_DATA*)calloc(1, sizeof(HTTPAPIEX_HANDLE_DATA));
+        if (handleData == NULL)
+        {
+            LogError("malloc failed.");
+            result = NULL;
+        }
+        else
+        {
+            /*Codes_SRS_HTTPAPIEX_02_002: [Parameter hostName shall be saved.]*/
+            handleData->hostName = STRING_construct(hostName);
+            if (handleData->hostName == NULL)
+            {
+                free(handleData);
+                LogError("unable to STRING_construct");
+                result = NULL;
+            }
+            else
+            {
+                /*Codes_SRS_HTTPAPIEX_02_004: [Otherwise, HTTPAPIEX_Create shall return a HTTAPIEX_HANDLE suitable for further calls to the module.] */
+                handleData->savedOptions = VECTOR_create(sizeof(HTTPAPIEX_SAVED_OPTION));
+                if (handleData->savedOptions == NULL)
+                {
+                    STRING_delete(handleData->hostName);
+                    free(handleData);
+                    result = NULL;
+                }
+                else
+                {
+                    handleData->k = -1;
+                    handleData->httpHandle = NULL;
+                    result = handleData;
+                }
+            }
+        }
+    }
+    return result;
+}
+
+/*this function builds the default request http headers if none are specified*/
+/*returns 0 if no error*/
+/*any other code is error*/
+static int buildRequestHttpHeadersHandle(HTTPAPIEX_HANDLE_DATA *handleData, BUFFER_HANDLE requestContent, HTTP_HEADERS_HANDLE originalRequestHttpHeadersHandle, bool* isOriginalRequestHttpHeadersHandle, HTTP_HEADERS_HANDLE* toBeUsedRequestHttpHeadersHandle)
+{
+    int result;
+
+
+    if (originalRequestHttpHeadersHandle != NULL)
+    {
+        *toBeUsedRequestHttpHeadersHandle = originalRequestHttpHeadersHandle;
+        *isOriginalRequestHttpHeadersHandle = true;
+
+    }
+    else
+    {
+        /*Codes_SRS_HTTPAPIEX_02_009: [If parameter requestHttpHeadersHandle is NULL then HTTPAPIEX_ExecuteRequest shall allocate a temporary internal instance of HTTPHEADERS, shall add to that instance the following headers
+        Host:{hostname} - as it was indicated by the call to HTTPAPIEX_Create API call
+        Content-Length:the size of the requestContent parameter, and use this instance to all the subsequent calls to HTTPAPI_ExecuteRequest as parameter httpHeadersHandle.]
+        */
+        *isOriginalRequestHttpHeadersHandle = false;
+        *toBeUsedRequestHttpHeadersHandle = HTTPHeaders_Alloc();
+    }
+
+    if (*toBeUsedRequestHttpHeadersHandle == NULL)
+    {
+        result = MU_FAILURE;
+        LogError("unable to HTTPHeaders_Alloc");
+    }
+    else
+    {
+        char temp[22] = { 0 };
+        (void)size_tToString(temp, 22, BUFFER_length(requestContent)); /*cannot fail, MAX_uint64 has 19 digits*/
+        /*Codes_SRS_HTTPAPIEX_02_011: [If parameter requestHttpHeadersHandle is not NULL then HTTPAPIEX_ExecuteRequest shall create or update the following headers of the request:
+        Host:{hostname}
+        Content-Length:the size of the requestContent parameter, and shall use the so constructed HTTPHEADERS object to all calls to HTTPAPI_ExecuteRequest as parameter httpHeadersHandle.]
+        */
+        /*Codes_SRS_HTTPAPIEX_02_009: [If parameter requestHttpHeadersHandle is NULL then HTTPAPIEX_ExecuteRequest shall allocate a temporary internal instance of HTTPHEADERS, shall add to that instance the following headers
+        Host:{hostname} - as it was indicated by the call to HTTPAPIEX_Create API call
+        Content-Length:the size of the requestContent parameter, and use this instance to all the subsequent calls to HTTPAPI_ExecuteRequest as parameter httpHeadersHandle.]
+        */
+        if (!(
+            (HTTPHeaders_ReplaceHeaderNameValuePair(*toBeUsedRequestHttpHeadersHandle, "Host", STRING_c_str(handleData->hostName)) == HTTP_HEADERS_OK) &&
+            (HTTPHeaders_ReplaceHeaderNameValuePair(*toBeUsedRequestHttpHeadersHandle, "Content-Length", temp) == HTTP_HEADERS_OK)
+            ))
+        {
+            if (! *isOriginalRequestHttpHeadersHandle)
+            {
+                HTTPHeaders_Free(*toBeUsedRequestHttpHeadersHandle);
+            }
+            *toBeUsedRequestHttpHeadersHandle = NULL;
+            result = MU_FAILURE;
+        }
+        else
+        {
+            result = 0;
+        }
+    }
+    return result;
+}
+
+static int buildResponseHttpHeadersHandle(HTTP_HEADERS_HANDLE originalResponsetHttpHeadersHandle, bool* isOriginalResponseHttpHeadersHandle, HTTP_HEADERS_HANDLE* toBeUsedResponsetHttpHeadersHandle)
+{
+    int result;
+    if (originalResponsetHttpHeadersHandle == NULL)
+    {
+        if ((*toBeUsedResponsetHttpHeadersHandle = HTTPHeaders_Alloc()) == NULL)
+        {
+            result = MU_FAILURE;
+        }
+        else
+        {
+            *isOriginalResponseHttpHeadersHandle = false;
+            result = 0;
+        }
+    }
+    else
+    {
+        *isOriginalResponseHttpHeadersHandle = true;
+        *toBeUsedResponsetHttpHeadersHandle = originalResponsetHttpHeadersHandle;
+        result = 0;
+    }
+    return result;
+}
+
+
+static int buildBufferIfNotExist(BUFFER_HANDLE originalRequestContent, bool* isOriginalRequestContent, BUFFER_HANDLE* toBeUsedRequestContent)
+{
+    int result;
+    if (originalRequestContent == NULL)
+    {
+        *toBeUsedRequestContent = BUFFER_new();
+        if (*toBeUsedRequestContent == NULL)
+        {
+            result = MU_FAILURE;
+        }
+        else
+        {
+            *isOriginalRequestContent = false;
+            result = 0;
+        }
+    }
+    else
+    {
+        *isOriginalRequestContent = true;
+        *toBeUsedRequestContent = originalRequestContent;
+        result = 0;
+    }
+    return result;
+}
+
+static unsigned int dummyStatusCode;
+
+static int buildAllRequests(HTTPAPIEX_HANDLE_DATA* handle, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath,
+    HTTP_HEADERS_HANDLE requestHttpHeadersHandle, BUFFER_HANDLE requestContent, unsigned int* statusCode,
+    HTTP_HEADERS_HANDLE responseHttpHeadersHandle, BUFFER_HANDLE responseContent,
+
+    const char** toBeUsedRelativePath,
+    HTTP_HEADERS_HANDLE *toBeUsedRequestHttpHeadersHandle, bool *isOriginalRequestHttpHeadersHandle,
+    BUFFER_HANDLE *toBeUsedRequestContent, bool *isOriginalRequestContent,
+    unsigned int** toBeUsedStatusCode,
+    HTTP_HEADERS_HANDLE *toBeUsedResponseHttpHeadersHandle, bool *isOriginalResponseHttpHeadersHandle,
+    BUFFER_HANDLE *toBeUsedResponseContent, bool *isOriginalResponseContent)
+{
+    int result;
+    (void)requestType;
+    /*Codes_SRS_HTTPAPIEX_02_013: [If requestContent is NULL then HTTPAPIEX_ExecuteRequest shall behave as if a buffer of zero size would have been used, that is, it shall call HTTPAPI_ExecuteRequest with parameter content = NULL and contentLength = 0.]*/
+    /*Codes_SRS_HTTPAPIEX_02_014: [If requestContent is not NULL then its content and its size shall be used for parameters content and contentLength of HTTPAPI_ExecuteRequest.] */
+    if (buildBufferIfNotExist(requestContent, isOriginalRequestContent, toBeUsedRequestContent) != 0)
+    {
+        LogError("unable to build the request content");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        if (buildRequestHttpHeadersHandle(handle, *toBeUsedRequestContent, requestHttpHeadersHandle, isOriginalRequestHttpHeadersHandle, toBeUsedRequestHttpHeadersHandle) != 0)
+        {
+            /*Codes_SRS_HTTPAPIEX_02_010: [If any of the operations in SRS_HTTAPIEX_02_009 fails, then HTTPAPIEX_ExecuteRequest shall return HTTPAPIEX_ERROR.] */
+            if (*isOriginalRequestContent == false)
+            {
+                BUFFER_delete(*toBeUsedRequestContent);
+            }
+            LogError("unable to build the request http headers handle");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            /*Codes_SRS_HTTPAPIEX_02_008: [If parameter relativePath is NULL then HTTPAPIEX_INVALID_ARG shall not assume a relative path - that is, it will assume an empty path ("").] */
+            if (relativePath == NULL)
+            {
+                *toBeUsedRelativePath = "";
+            }
+            else
+            {
+                *toBeUsedRelativePath = relativePath;
+            }
+
+            /*Codes_SRS_HTTPAPIEX_02_015: [If statusCode is NULL then HTTPAPIEX_ExecuteRequest shall not write in statusCode the HTTP status code, and it will use a temporary internal int for parameter statusCode to the calls of HTTPAPI_ExecuteRequest.] */
+            if (statusCode == NULL)
+            {
+                /*Codes_SRS_HTTPAPIEX_02_016: [If statusCode is not NULL then If statusCode is NULL then HTTPAPIEX_ExecuteRequest shall use it for parameter statusCode to the calls of HTTPAPI_ExecuteRequest.] */
+                *toBeUsedStatusCode = &dummyStatusCode;
+            }
+            else
+            {
+                *toBeUsedStatusCode = statusCode;
+            }
+
+            /*Codes_SRS_HTTPAPIEX_02_017: [If responseHeaders handle is NULL then HTTPAPIEX_ExecuteRequest shall create a temporary internal instance of HTTPHEADERS object and use that for responseHeaders parameter of HTTPAPI_ExecuteRequest call.] */
+            /*Codes_SRS_HTTPAPIEX_02_019: [If responseHeaders is not NULL, then then HTTPAPIEX_ExecuteRequest shall use that object as parameter responseHeaders of HTTPAPI_ExecuteRequest call.] */
+            if (buildResponseHttpHeadersHandle(responseHttpHeadersHandle, isOriginalResponseHttpHeadersHandle, toBeUsedResponseHttpHeadersHandle) != 0)
+            {
+                /*Codes_SRS_HTTPAPIEX_02_018: [If creating the temporary http headers in SRS_HTTPAPIEX_02_017 fails then HTTPAPIEX_ExecuteRequest shall return HTTPAPIEX_ERROR.] */
+                if (*isOriginalRequestContent == false)
+                {
+                    BUFFER_delete(*toBeUsedRequestContent);
+                }
+                if (*isOriginalRequestHttpHeadersHandle == false)
+                {
+                    HTTPHeaders_Free(*toBeUsedRequestHttpHeadersHandle);
+                }
+                LogError("unable to build response content");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                /*Codes_SRS_HTTPAPIEX_02_020: [If responseContent is NULL then HTTPAPIEX_ExecuteRequest shall create a temporary internal BUFFER object and use that as parameter responseContent of HTTPAPI_ExecuteRequest call.] */
+                /*Codes_SRS_HTTPAPIEX_02_022: [If responseContent is not NULL then HTTPAPIEX_ExecuteRequest use that as parameter responseContent of HTTPAPI_ExecuteRequest call.] */
+                if (buildBufferIfNotExist(responseContent, isOriginalResponseContent, toBeUsedResponseContent) != 0)
+                {
+                    /*Codes_SRS_HTTPAPIEX_02_021: [If creating the BUFFER_HANDLE in SRS_HTTPAPIEX_02_020 fails, then HTTPAPIEX_ExecuteRequest shall return HTTPAPIEX_ERROR.] */
+                    if (*isOriginalRequestContent == false)
+                    {
+                        BUFFER_delete(*toBeUsedRequestContent);
+                    }
+                    if (*isOriginalRequestHttpHeadersHandle == false)
+                    {
+                        HTTPHeaders_Free(*toBeUsedRequestHttpHeadersHandle);
+                    }
+                    if (*isOriginalResponseHttpHeadersHandle == false)
+                    {
+                        HTTPHeaders_Free(*toBeUsedResponseHttpHeadersHandle);
+                    }
+                    LogError("unable to build response content");
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    result = 0;
+                }
+            }
+        }
+    }
+    return result;
+}
+
+HTTPAPIEX_RESULT HTTPAPIEX_ExecuteRequest(HTTPAPIEX_HANDLE handle, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath,
+    HTTP_HEADERS_HANDLE requestHttpHeadersHandle, BUFFER_HANDLE requestContent, unsigned int* statusCode,
+    HTTP_HEADERS_HANDLE responseHttpHeadersHandle, BUFFER_HANDLE responseContent)
+{
+    HTTPAPIEX_RESULT result;
+    /*Codes_SRS_HTTPAPIEX_02_006: [If parameter handle is NULL then HTTPAPIEX_ExecuteRequest shall fail and return HTTPAPIEX_INVALID_ARG.]*/
+    if (handle == NULL)
+    {
+        result = HTTPAPIEX_INVALID_ARG;
+        LOG_HTTAPIEX_ERROR();
+    }
+    else
+    {
+        /*Codes_SRS_HTTPAPIEX_02_007: [If parameter requestType does not indicate a valid request, HTTPAPIEX_ExecuteRequest shall fail and return HTTPAPIEX_INVALID_ARG.] */
+        if (requestType >= MU_COUNT_ARG(HTTPAPI_REQUEST_TYPE_VALUES))
+        {
+            result = HTTPAPIEX_INVALID_ARG;
+            LOG_HTTAPIEX_ERROR();
+        }
+        else
+        {
+            HTTPAPIEX_HANDLE_DATA *handleData = (HTTPAPIEX_HANDLE_DATA *)handle;
+
+            /*call to buildAll*/
+            const char* toBeUsedRelativePath;
+            HTTP_HEADERS_HANDLE toBeUsedRequestHttpHeadersHandle; bool isOriginalRequestHttpHeadersHandle;
+            BUFFER_HANDLE toBeUsedRequestContent; bool isOriginalRequestContent;
+            unsigned int* toBeUsedStatusCode;
+            HTTP_HEADERS_HANDLE toBeUsedResponseHttpHeadersHandle; bool isOriginalResponseHttpHeadersHandle;
+            BUFFER_HANDLE toBeUsedResponseContent;  bool isOriginalResponseContent;
+
+            if (buildAllRequests(handleData, requestType, relativePath, requestHttpHeadersHandle, requestContent, statusCode, responseHttpHeadersHandle, responseContent,
+                &toBeUsedRelativePath,
+                &toBeUsedRequestHttpHeadersHandle, &isOriginalRequestHttpHeadersHandle,
+                &toBeUsedRequestContent, &isOriginalRequestContent,
+                &toBeUsedStatusCode,
+                &toBeUsedResponseHttpHeadersHandle, &isOriginalResponseHttpHeadersHandle,
+                &toBeUsedResponseContent, &isOriginalResponseContent) != 0)
+            {
+                result = HTTPAPIEX_ERROR;
+                LOG_HTTAPIEX_ERROR();
+            }
+            else
+            {
+
+                /*Codes_SRS_HTTPAPIEX_02_023: [HTTPAPIEX_ExecuteRequest shall try to execute the HTTP call by ensuring the following API call sequence is respected:]*/
+                /*Codes_SRS_HTTPAPIEX_02_024: [If any point in the sequence fails, HTTPAPIEX_ExecuteRequest shall attempt to recover by going back to the previous step and retrying that step.]*/
+                /*Codes_SRS_HTTPAPIEX_02_025: [If the first step fails, then the sequence fails.]*/
+                /*Codes_SRS_HTTPAPIEX_02_026: [A step shall be retried at most once.]*/
+                /*Codes_SRS_HTTPAPIEX_02_027: [If a step has been retried then all subsequent steps shall be retried too.]*/
+                bool st[3] = { false, false, false }; /*the three levels of possible failure in resilient send: HTTAPI_Init, HTTPAPI_CreateConnection, HTTPAPI_ExecuteRequest*/
+                if (handleData->k == -1)
+                {
+                    handleData->k = 0;
+                }
+
+                do
+                {
+                    bool goOn;
+
+                    if (handleData->k > 2)
+                    {
+                        /* error */
+                        break;
+                    }
+
+                    if (st[handleData->k] == true) /*already been tried*/
+                    {
+                        goOn = false;
+                    }
+                    else
+                    {
+                        switch (handleData->k)
+                        {
+                        case 0:
+                        {
+                            if (useGlobalInitialization > 0)
+                            {
+                                /*Codes_SRS_HTTPAPIEX_21_048: [If HTTPAPIEX_Init was called, HTTPAPI_ExecuteRequest shall not call HTTPAPI_Init.] */
+                                goOn = true;
+                            }
+                            else if (HTTPAPI_Init() != HTTPAPI_OK)
+                            {
+                                goOn = false;
+                            }
+                            else
+                            {
+                                goOn = true;
+                            }
+                            break;
+                        }
+                        case 1:
+                        {
+                            if ((handleData->httpHandle = HTTPAPI_CreateConnection(STRING_c_str(handleData->hostName))) == NULL)
+                            {
+                                goOn = false;
+                            }
+                            else
+                            {
+                                size_t i;
+                                size_t vectorSize = VECTOR_size(handleData->savedOptions);
+                                for (i = 0; i < vectorSize; i++)
+                                {
+                                    /*Codes_SRS_HTTPAPIEX_02_035: [HTTPAPIEX_ExecuteRequest shall pass all the saved options (see HTTPAPIEX_SetOption) to the newly create HTTPAPI_HANDLE in step 2 by calling HTTPAPI_SetOption.]*/
+                                    /*Codes_SRS_HTTPAPIEX_02_036: [If setting the option fails, then the failure shall be ignored.] */
+                                    HTTPAPIEX_SAVED_OPTION* option = (HTTPAPIEX_SAVED_OPTION*)VECTOR_element(handleData->savedOptions, i);
+                                    if (HTTPAPI_SetOption(handleData->httpHandle, option->optionName, option->value) != HTTPAPI_OK)
+                                    {
+                                        LogError("HTTPAPI_SetOption failed when called for option %s", option->optionName);
+                                    }
+                                }
+                                goOn = true;
+                            }
+                            break;
+                        }
+                        case 2:
+                        {
+                            size_t length = BUFFER_length(toBeUsedRequestContent);
+                            unsigned char* buffer = BUFFER_u_char(toBeUsedRequestContent);
+                            if (HTTPAPI_ExecuteRequest(handleData->httpHandle, requestType, toBeUsedRelativePath, toBeUsedRequestHttpHeadersHandle, buffer, length, toBeUsedStatusCode, toBeUsedResponseHttpHeadersHandle, toBeUsedResponseContent) != HTTPAPI_OK)
+                            {
+                                goOn = false;
+                            }
+                            else
+                            {
+                                goOn = true;
+                            }
+                            break;
+                        }
+                        default:
+                        {
+                            /*serious error*/
+                            goOn = false;
+                            break;
+                        }
+                        }
+                    }
+
+                    if (goOn)
+                    {
+                        if (handleData->k == 2)
+                        {
+                            /*Codes_SRS_HTTPAPIEX_02_028: [HTTPAPIEX_ExecuteRequest shall return HTTPAPIEX_OK when a call to HTTPAPI_ExecuteRequest has been completed successfully.]*/
+                            result = HTTPAPIEX_OK;
+                            goto out;
+                        }
+                        else
+                        {
+                            st[handleData->k] = true;
+                            handleData->k++;
+                            st[handleData->k] = false;
+                        }
+                    }
+                    else
+                    {
+                        st[handleData->k] = false;
+                        handleData->k--;
+                        switch (handleData->k)
+                        {
+                        case 0:
+                        {
+                            /*Codes_SRS_HTTPAPIEX_21_049: [If HTTPAPIEX_Init was called, HTTPAPI_ExecuteRequest shall not call HTTPAPI_Deinit.] */
+                            if (useGlobalInitialization == 0)
+                            {
+                                HTTPAPI_Deinit();
+                            }
+                            break;
+                        }
+                        case 1:
+                        {
+                            HTTPAPI_CloseConnection(handleData->httpHandle);
+                            handleData->httpHandle = NULL;
+                            break;
+                        }
+                        case 2:
+                        {
+                            break;
+                        }
+                        default:
+                        {
+                            break;
+                        }
+                        }
+                    }
+                } while (handleData->k >= 0);
+                /*Codes_SRS_HTTPAPIEX_02_029: [Otherwise, HTTAPIEX_ExecuteRequest shall return HTTPAPIEX_RECOVERYFAILED.] */
+                result = HTTPAPIEX_RECOVERYFAILED;
+                LogError("unable to recover sending to a working state");
+            out:;
+                /*in all cases, unbuild the temporaries*/
+                if (isOriginalRequestContent == false)
+                {
+                    BUFFER_delete(toBeUsedRequestContent);
+                }
+                if (isOriginalRequestHttpHeadersHandle == false)
+                {
+                    HTTPHeaders_Free(toBeUsedRequestHttpHeadersHandle);
+                }
+                if (isOriginalResponseContent == false)
+                {
+                    BUFFER_delete(toBeUsedResponseContent);
+                }
+                if (isOriginalResponseHttpHeadersHandle == false)
+                {
+                    HTTPHeaders_Free(toBeUsedResponseHttpHeadersHandle);
+                }
+            }
+        }
+    }
+    return result;
+}
+
+
+void HTTPAPIEX_Destroy(HTTPAPIEX_HANDLE handle)
+{
+    if (handle != NULL)
+    {
+        /*Codes_SRS_HTTPAPIEX_02_042: [HTTPAPIEX_Destroy shall free all the resources used by HTTAPIEX_HANDLE.]*/
+        size_t i;
+        size_t vectorSize;
+        HTTPAPIEX_HANDLE_DATA* handleData = (HTTPAPIEX_HANDLE_DATA*)handle;
+
+        if (handleData->k == 2)
+        {
+            HTTPAPI_CloseConnection(handleData->httpHandle);
+            /*Codes_SRS_HTTPAPIEX_21_050: [If HTTPAPIEX_Init was called, HTTPAPI_Destroy shall not call HTTPAPI_Deinit.] */
+            if (useGlobalInitialization == 0)
+            {
+                HTTPAPI_Deinit();
+            }
+        }
+        STRING_delete(handleData->hostName);
+
+        vectorSize = VECTOR_size(handleData->savedOptions);
+        for (i = 0; i < vectorSize; i++)
+        {
+            HTTPAPIEX_SAVED_OPTION* savedOption = (HTTPAPIEX_SAVED_OPTION*)VECTOR_element(handleData->savedOptions, i);
+            free((void*)savedOption->optionName);
+            free((void*)savedOption->value);
+        }
+        VECTOR_destroy(handleData->savedOptions);
+
+        free(handle);
+    }
+    else
+    {
+        /*Codes_SRS_HTTPAPIEX_02_043: [If parameter handle is NULL then HTTPAPIEX_Destroy shall take no action.] */
+    }
+}
+
+static bool sameName(const void* element, const void* value)
+{
+    return (strcmp(((HTTPAPIEX_SAVED_OPTION*)element)->optionName, (const char*)value) == 0) ? true : false;
+}
+
+/*return 0 on success, any other value is error*/
+/*obs: value is already cloned at the time of calling this function */
+static int createOrUpdateOption(HTTPAPIEX_HANDLE_DATA* handleData, const char* optionName, const void* value)
+{
+    /*this function is called after the option value has been saved (cloned)*/
+    int result;
+
+    /*decide bwtween update or create*/
+    HTTPAPIEX_SAVED_OPTION* whereIsIt = (HTTPAPIEX_SAVED_OPTION*)VECTOR_find_if(handleData->savedOptions, sameName, optionName);
+    if (whereIsIt != NULL)
+    {
+        free((void*)(whereIsIt->value));
+        whereIsIt->value = value;
+        result = 0;
+    }
+    else
+    {
+        HTTPAPIEX_SAVED_OPTION newOption;
+        if (mallocAndStrcpy_s((char**)&(newOption.optionName), optionName) != 0)
+        {
+            free((void*)value);
+            result = MU_FAILURE;
+        }
+        else
+        {
+            newOption.value = value;
+            if (VECTOR_push_back(handleData->savedOptions, &newOption, 1) != 0)
+            {
+                LogError("unable to VECTOR_push_back");
+                free((void*)newOption.optionName);
+                free((void*)value);
+                result = MU_FAILURE;
+            }
+            else
+            {
+                result = 0;
+            }
+        }
+    }
+
+    return result;
+}
+
+HTTPAPIEX_RESULT HTTPAPIEX_SetOption(HTTPAPIEX_HANDLE handle, const char* optionName, const void* value)
+{
+    HTTPAPIEX_RESULT result;
+    /*Codes_SRS_HTTPAPIEX_02_032: [If parameter handle is NULL then HTTPAPIEX_SetOption shall return HTTPAPIEX_INVALID_ARG.] */
+    /*Codes_SRS_HTTPAPIEX_02_033: [If parameter optionName is NULL then HTTPAPIEX_SetOption shall return HTTPAPIEX_INVALID_ARG.] */
+    /*Codes_SRS_HTTPAPIEX_02_034: [If parameter value is NULL then HTTPAPIEX_SetOption shall return HTTPAPIEX_INVALID_ARG.] */
+    if (
+        (handle == NULL) ||
+        (optionName == NULL) ||
+        (value == NULL)
+        )
+    {
+        result = HTTPAPIEX_INVALID_ARG;
+        LOG_HTTAPIEX_ERROR();
+    }
+    else
+    {
+        const void* savedOption;
+        HTTPAPI_RESULT saveOptionResult;
+
+        /*Codes_SRS_HTTPAPIEX_02_037: [HTTPAPIEX_SetOption shall attempt to save the value of the option by calling HTTPAPI_CloneOption passing optionName and value, irrespective of the existence of a HTTPAPI_HANDLE] */
+        saveOptionResult = HTTPAPI_CloneOption(optionName, value, &savedOption);
+
+        if(saveOptionResult == HTTPAPI_INVALID_ARG)
+        {
+            /*Codes_SRS_HTTPAPIEX_02_038: [If HTTPAPI_CloneOption returns HTTPAPI_INVALID_ARG then HTTPAPIEX shall return HTTPAPIEX_INVALID_ARG.] */
+            result = HTTPAPIEX_INVALID_ARG;
+            LOG_HTTAPIEX_ERROR();
+        }
+        else if (saveOptionResult != HTTPAPI_OK)
+        {
+            /*Codes_SRS_HTTPAPIEX_02_040: [For all other return values of HTTPAPI_SetOption, HTTPIAPIEX_SetOption shall return HTTPAPIEX_ERROR.] */
+            result = HTTPAPIEX_ERROR;
+            LOG_HTTAPIEX_ERROR();
+        }
+        else
+        {
+            HTTPAPIEX_HANDLE_DATA* handleData = (HTTPAPIEX_HANDLE_DATA*)handle;
+            /*Codes_SRS_HTTPAPIEX_02_039: [If HTTPAPI_CloneOption returns HTTPAPI_OK then HTTPAPIEX_SetOption shall create or update the pair optionName/value.]*/
+            if (createOrUpdateOption(handleData, optionName, savedOption) != 0)
+            {
+                /*Codes_SRS_HTTPAPIEX_02_041: [If creating or updating the pair optionName/value fails then shall return HTTPAPIEX_ERROR.] */
+                result = HTTPAPIEX_ERROR;
+                LOG_HTTAPIEX_ERROR();
+
+            }
+            else
+            {
+                /*Codes_SRS_HTTPAPIEX_02_031: [If HTTPAPI_HANDLE exists then HTTPAPIEX_SetOption shall call HTTPAPI_SetOption passing the same optionName and value and shall return a value conforming to the below table:] */
+                if (handleData->httpHandle != NULL)
+                {
+                    HTTPAPI_RESULT HTTPAPI_result = HTTPAPI_SetOption(handleData->httpHandle, optionName, value);
+                    if (HTTPAPI_result == HTTPAPI_OK)
+                    {
+                        result = HTTPAPIEX_OK;
+                    }
+                    else if (HTTPAPI_result == HTTPAPI_INVALID_ARG)
+                    {
+                        result = HTTPAPIEX_INVALID_ARG;
+                        LOG_HTTAPIEX_ERROR();
+                    }
+                    else
+                    {
+                        result = HTTPAPIEX_ERROR;
+                        LOG_HTTAPIEX_ERROR();
+                    }
+                }
+                else
+                {
+                    result = HTTPAPIEX_OK;
+                }
+            }
+        }
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/httpapiexsas.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/httpapiexsas.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/httpapiexsas.c	(revision 453)
@@ -0,0 +1,186 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <time.h>
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/agenttime.h"
+#include "azure_c_shared_utility/strings.h"
+#include "azure_c_shared_utility/buffer_.h"
+#include "azure_c_shared_utility/sastoken.h"
+#include "azure_c_shared_utility/httpheaders.h"
+#include "azure_c_shared_utility/httpapiex.h"
+#include "azure_c_shared_utility/httpapiexsas.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+
+#define SHARED_ACCESS_SIGNATURE_PREFIX "sas="
+
+typedef struct HTTPAPIEX_SAS_STATE_TAG
+{
+    char* key;
+    char* uriResource;
+    char* keyName;
+} HTTPAPIEX_SAS_STATE;
+
+static HTTPAPIEX_SAS_STATE* construct_httpex_sas(const char* key, const char* uriResource, const char* keyName)
+{
+    HTTPAPIEX_SAS_STATE* result;
+
+    result = (HTTPAPIEX_SAS_STATE*)malloc(sizeof(HTTPAPIEX_SAS_STATE));
+    if (result == NULL)
+    {
+        LogError("Failure allocating HTTPAPIEX_SAS_Create.");
+    }
+    else
+    {
+        (void)memset(result, 0, sizeof(HTTPAPIEX_SAS_STATE));
+        if (mallocAndStrcpy_s(&result->key, key) != 0)
+        {
+            /*Codes_SRS_HTTPAPIEXSAS_06_004: [If there are any other errors in the instantiation of this handle then HTTPAPIEX_SAS_Create shall return NULL.]*/
+            LogError("Failure allocating sas key.");
+            HTTPAPIEX_SAS_Destroy(result);
+            result = NULL;
+        }
+        else if (mallocAndStrcpy_s(&result->uriResource, uriResource) != 0)
+        {
+            /*Codes_SRS_HTTPAPIEXSAS_06_004: [If there are any other errors in the instantiation of this handle then HTTPAPIEX_SAS_Create shall return NULL.]*/
+            LogError("Failure allocating sas uriResource.");
+            HTTPAPIEX_SAS_Destroy(result);
+            result = NULL;
+        }
+        else if (keyName != NULL && mallocAndStrcpy_s(&result->keyName, keyName) != 0)
+        {
+            /*Codes_SRS_HTTPAPIEXSAS_06_004: [If there are any other errors in the instantiation of this handle then HTTPAPIEX_SAS_Create shall return NULL.]*/
+            LogError("Failure allocating sas keyName.");
+            HTTPAPIEX_SAS_Destroy(result);
+            result = NULL;
+        }
+    }
+    return result;
+}
+
+HTTPAPIEX_SAS_HANDLE HTTPAPIEX_SAS_Create_From_String(const char* key, const char* uriResource, const char* keyName)
+{
+    HTTPAPIEX_SAS_HANDLE result = NULL;
+    if (key == NULL || uriResource == NULL)
+    {
+        /* Codes_SRS_HTTPAPIEXSAS_07_001: [ If the parameter key or uriResource is NULL then HTTPAPIEX_SAS_Create_From_String shall return NULL. ] */
+        LogError("Invalid parameter key: %p, uriResource: %p", key, uriResource);
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_HTTPAPIEXSAS_07_002: [ If there are any other errors in the instantiation of this handle then HTTPAPIEX_SAS_Create_From_String shall return NULL. ] */
+        result = construct_httpex_sas(key, uriResource, keyName);
+    }
+    /* Codes_SRS_HTTPAPIEXSAS_07_003: [ HTTPAPIEX_SAS_Create_From_String shall create a new instance of HTTPAPIEX_SAS and return a non-NULL handle to it ] */
+    return result;
+}
+
+HTTPAPIEX_SAS_HANDLE HTTPAPIEX_SAS_Create(STRING_HANDLE key, STRING_HANDLE uriResource, STRING_HANDLE keyName)
+{
+    HTTPAPIEX_SAS_HANDLE result = NULL;
+    if (key == NULL)
+    {
+        /*Codes_SRS_HTTPAPIEXSAS_06_001: [If the parameter key is NULL then HTTPAPIEX_SAS_Create shall return NULL.]*/
+        LogError("No key passed to HTTPAPIEX_SAS_Create.");
+    }
+    else if (uriResource == NULL)
+    {
+        /*Codes_SRS_HTTPAPIEXSAS_06_002: [If the parameter uriResource is NULL then HTTPAPIEX_SAS_Create shall return NULL.]*/
+        LogError("No uri resource passed to HTTPAPIEX_SAS_Create.");
+    }
+    else
+    {
+        /*Codes_SRS_HTTPAPIEXSAS_06_003: [The parameter keyName for HTTPAPIEX_SAS_Create is optional and can be NULL.]*/
+        /*Codes_SRS_HTTPAPIEXSAS_01_001: [ HTTPAPIEX_SAS_Create shall create a new instance of HTTPAPIEX_SAS and return a non-NULL handle to it. ]*/
+        const char* keyStr = STRING_c_str(key);
+        const char* uriStr = STRING_c_str(uriResource);
+        const char* keyNameStr = STRING_c_str(keyName);
+        result = construct_httpex_sas(keyStr, uriStr, keyNameStr);
+    }
+    return result;
+}
+
+void HTTPAPIEX_SAS_Destroy(HTTPAPIEX_SAS_HANDLE handle)
+{
+    /*Codes_SRS_HTTPAPIEXSAS_06_005: [If the parameter handle is NULL then HTTAPIEX_SAS_Destroy shall do nothing and return.]*/
+    if (handle)
+    {
+        HTTPAPIEX_SAS_STATE* state = (HTTPAPIEX_SAS_STATE*)handle;
+        /*Codes_SRS_HTTPAPIEXSAS_06_006: [HTTAPIEX_SAS_Destroy shall deallocate any structures denoted by the parameter handle.]*/
+        if (state->key)
+        {
+            free(state->key);
+        }
+        if (state->uriResource)
+        {
+            free(state->uriResource);
+        }
+        if (state->keyName)
+        {
+            free(state->keyName);
+        }
+        free(state);
+    }
+}
+
+HTTPAPIEX_RESULT HTTPAPIEX_SAS_ExecuteRequest(HTTPAPIEX_SAS_HANDLE sasHandle, HTTPAPIEX_HANDLE handle, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath, HTTP_HEADERS_HANDLE requestHttpHeadersHandle, BUFFER_HANDLE requestContent, unsigned int* statusCode, HTTP_HEADERS_HANDLE responseHeadersHandle, BUFFER_HANDLE responseContent)
+{
+    /*Codes_SRS_HTTPAPIEXSAS_06_007: [If the parameter sasHandle is NULL then HTTPAPIEX_SAS_ExecuteRequest shall simply invoke HTTPAPIEX_ExecuteRequest with the remaining parameters (following sasHandle) as its arguments and shall return immediately with the result of that call as the result of HTTPAPIEX_SAS_ExecuteRequest.]*/
+    if (sasHandle != NULL)
+    {
+        /*Codes_SRS_HTTPAPIEXSAS_06_008: [if the parameter requestHttpHeadersHandle is NULL then fallthrough.]*/
+        if (requestHttpHeadersHandle != NULL)
+        {
+            /*Codes_SRS_HTTPAPIEXSAS_06_009: [HTTPHeaders_FindHeaderValue shall be invoked with the requestHttpHeadersHandle as its first argument and the string "Authorization" as its second argument.]*/
+            /*Codes_SRS_HTTPAPIEXSAS_06_010: [If the return result of the invocation of HTTPHeaders_FindHeaderValue is NULL then fallthrough.]*/
+            if (HTTPHeaders_FindHeaderValue(requestHttpHeadersHandle, "Authorization") != NULL)
+            {
+                HTTPAPIEX_SAS_STATE* state = (HTTPAPIEX_SAS_STATE*)sasHandle;
+                /*Codes_SRS_HTTPAPIEXSAS_06_018: [A value of type time_t that shall be known as currentTime is obtained from calling get_time.]*/
+                time_t currentTime = get_time(NULL);
+                /*Codes_SRS_HTTPAPIEXSAS_06_019: [If the value of currentTime is (time_t)-1 is then fallthrough.]*/
+                if (currentTime == (time_t)-1)
+                {
+                    LogError("Time does not appear to be working.");
+                }
+                else
+                {
+                    STRING_HANDLE newSASToken = NULL;
+                    if (strncmp(state->key, SHARED_ACCESS_SIGNATURE_PREFIX, 4) == 0)
+                    {
+                        /*Codes_SRS_HTTPAPIEXSAS_06_017: [If state->key is prefixed with "sas=", SharedAccessSignature will be used rather than created.  STRING_construct will be invoked.]*/
+                        newSASToken = STRING_construct(&state->key[4]);
+                    }
+                    else
+                    {
+                        /*Codes_SRS_HTTPAPIEXSAS_06_011: [SASToken_Create shall be invoked.]*/
+                        /*Codes_SRS_HTTPAPIEXSAS_06_012: [If the return result of SASToken_Create is NULL then fallthrough.]*/
+                        size_t expiry = (size_t)(difftime(currentTime, 0) + 3600);
+                        newSASToken = SASToken_CreateString(state->key, state->uriResource, state->keyName, expiry);
+                    }
+
+                    if (newSASToken != NULL)
+                    {
+                        /*Codes_SRS_HTTPAPIEXSAS_06_013: [HTTPHeaders_ReplaceHeaderNameValuePair shall be invoked with "Authorization" as its second argument and STRING_c_str (newSASToken) as its third argument.]*/
+                        if (HTTPHeaders_ReplaceHeaderNameValuePair(requestHttpHeadersHandle, "Authorization", STRING_c_str(newSASToken)) != HTTP_HEADERS_OK)
+                        {
+                            /*Codes_SRS_HTTPAPIEXSAS_06_014: [If the result of the invocation of HTTPHeaders_ReplaceHeaderNameValuePair is NOT HTTP_HEADERS_OK then fallthrough.]*/
+                            LogError("Unable to replace the old SAS Token.");
+                        }
+                        /*Codes_SRS_HTTPAPIEXSAS_06_015: [STRING_delete(newSASToken) will be invoked.]*/
+                        STRING_delete(newSASToken);
+                    }
+                    else
+                    {
+                        LogError("Unable to create a new SAS token.");
+                    }
+                }
+            }
+        }
+    }
+    /*Codes_SRS_HTTPAPIEXSAS_06_016: [HTTPAPIEX_ExecuteRequest with the remaining parameters (following sasHandle) as its arguments will be invoked and the result of that call is the result of HTTPAPIEX_SAS_ExecuteRequest.]*/
+    return HTTPAPIEX_ExecuteRequest(handle,requestType,relativePath,requestHttpHeadersHandle,requestContent,statusCode,responseHeadersHandle,responseContent);
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/httpheaders.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/httpheaders.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/httpheaders.c	(revision 453)
@@ -0,0 +1,336 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <string.h>
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/map.h"
+#include "azure_c_shared_utility/httpheaders.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/xlogging.h"
+
+MU_DEFINE_ENUM_STRINGS(HTTP_HEADERS_RESULT, HTTP_HEADERS_RESULT_VALUES);
+
+typedef struct HTTP_HEADERS_HANDLE_DATA_TAG
+{
+    MAP_HANDLE headers;
+} HTTP_HEADERS_HANDLE_DATA;
+
+HTTP_HEADERS_HANDLE HTTPHeaders_Alloc(void)
+{
+    /*Codes_SRS_HTTP_HEADERS_99_002:[ This API shall produce a HTTP_HANDLE that can later be used in subsequent calls to the module.]*/
+    HTTP_HEADERS_HANDLE_DATA* result;
+    result = (HTTP_HEADERS_HANDLE_DATA*)malloc(sizeof(HTTP_HEADERS_HANDLE_DATA));
+
+    if (result == NULL)
+    {
+        LogError("malloc failed");
+    }
+    else
+    {
+        /*Codes_SRS_HTTP_HEADERS_99_004:[ After a successful init, HTTPHeaders_GetHeaderCount shall report 0 existing headers.]*/
+        result->headers = Map_Create(NULL);
+        if (result->headers == NULL)
+        {
+            LogError("Map_Create failed");
+            free(result);
+            result = NULL;
+        }
+        else
+        {
+            /*all is fine*/
+        }
+    }
+
+    /*Codes_SRS_HTTP_HEADERS_99_003:[ The function shall return NULL when the function cannot execute properly]*/
+    return (HTTP_HEADERS_HANDLE)result;
+}
+
+/*Codes_SRS_HTTP_HEADERS_99_005:[ Calling this API shall de-allocate the data structures allocated by previous API calls to the same handle.]*/
+void HTTPHeaders_Free(HTTP_HEADERS_HANDLE handle)
+{
+    /*Codes_SRS_HTTP_HEADERS_02_001: [If httpHeadersHandle is NULL then HTTPHeaders_Free shall perform no action.] */
+    if (handle == NULL)
+    {
+        /*do nothing*/
+    }
+    else
+    {
+        /*Codes_SRS_HTTP_HEADERS_99_005:[ Calling this API shall de-allocate the data structures allocated by previous API calls to the same handle.]*/
+        HTTP_HEADERS_HANDLE_DATA* handleData = (HTTP_HEADERS_HANDLE_DATA*)handle;
+
+        Map_Destroy(handleData->headers);
+        free(handleData);
+    }
+}
+
+/*Codes_SRS_HTTP_HEADERS_99_012:[ Calling this API shall record a header from name and value parameters.]*/
+static HTTP_HEADERS_RESULT headers_ReplaceHeaderNameValuePair(HTTP_HEADERS_HANDLE handle, const char* name, const char* value, bool replace)
+{
+    HTTP_HEADERS_RESULT result;
+    /*Codes_SRS_HTTP_HEADERS_99_014:[ The function shall return when the handle is not valid or when name parameter is NULL or when value parameter is NULL.]*/
+    if (
+        (handle == NULL) ||
+        (name == NULL) ||
+        (value == NULL)
+        )
+    {
+        result = HTTP_HEADERS_INVALID_ARG;
+        LogError("invalid arg (NULL) , result= %" PRI_MU_ENUM "", MU_ENUM_VALUE(HTTP_HEADERS_RESULT, result));
+    }
+    else
+    {
+        /*Codes_SRS_HTTP_HEADERS_99_036:[ If name contains the characters outside character codes 33 to 126 then the return value shall be HTTP_HEADERS_INVALID_ARG]*/
+        /*Codes_SRS_HTTP_HEADERS_99_031:[ If name contains the character ":" then the return value shall be HTTP_HEADERS_INVALID_ARG.]*/
+        size_t i;
+        size_t nameLen = strlen(name);
+        for (i = 0; i < nameLen; i++)
+        {
+            if ((name[i] < 33) || (126 < name[i]) || (name[i] == ':'))
+            {
+                break;
+            }
+        }
+
+        if (i < nameLen)
+        {
+            result = HTTP_HEADERS_INVALID_ARG;
+            LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTP_HEADERS_RESULT, result));
+        }
+        else
+        {
+            HTTP_HEADERS_HANDLE_DATA* handleData = (HTTP_HEADERS_HANDLE_DATA*)handle;
+            const char* existingValue = Map_GetValueFromKey(handleData->headers, name);
+            /*eat up the whitespaces from value, as per RFC 2616, chapter 4.2 "The field value MAY be preceded by any amount of LWS, though a single SP is preferred."*/
+            /*Codes_SRS_HTTP_HEADERS_02_002: [The LWS from the beginning of the value shall not be stored.] */
+            while ((value[0] == ' ') || (value[0] == '\t') || (value[0] == '\r') || (value[0] == '\n'))
+            {
+                value++;
+            }
+
+            if (!replace && (existingValue != NULL))
+            {
+                size_t existingValueLen = strlen(existingValue);
+                size_t valueLen = strlen(value);
+                char* newValue = (char*)malloc(sizeof(char) * (existingValueLen + /*COMMA_AND_SPACE_LENGTH*/ 2 + valueLen + /*EOL*/ 1));
+                if (newValue == NULL)
+                {
+                    /*Codes_SRS_HTTP_HEADERS_99_015:[ The function shall return HTTP_HEADERS_ALLOC_FAILED when an internal request to allocate memory fails.]*/
+                    result = HTTP_HEADERS_ALLOC_FAILED;
+                    LogError("failed to malloc , result= %" PRI_MU_ENUM "", MU_ENUM_VALUE(HTTP_HEADERS_RESULT, result));
+                }
+                else
+                {
+                    char* runNewValue;
+                    /*Codes_SRS_HTTP_HEADERS_99_017:[ If the name already exists in the collection of headers, the function shall concatenate the new value after the existing value, separated by a comma and a space as in: old-value+", "+new-value.]*/
+                    (void)memcpy(newValue, existingValue, existingValueLen);
+                    runNewValue = newValue + existingValueLen;
+                    (*runNewValue++) = ',';
+                    (*runNewValue++) = ' ';
+                    (void)memcpy(runNewValue, value, valueLen + /*EOL*/ 1);
+
+                    /*Codes_SRS_HTTP_HEADERS_99_016:[ The function shall store the name:value pair in such a way that when later retrieved by a call to GetHeader it will return a string that shall strcmp equal to the name+": "+value.]*/
+                    if (Map_AddOrUpdate(handleData->headers, name, newValue) != MAP_OK)
+                    {
+                        /*Codes_SRS_HTTP_HEADERS_99_015:[ The function shall return HTTP_HEADERS_ALLOC_FAILED when an internal request to allocate memory fails.]*/
+                        result = HTTP_HEADERS_ERROR;
+                        LogError("failed to Map_AddOrUpdate, result= %" PRI_MU_ENUM "", MU_ENUM_VALUE(HTTP_HEADERS_RESULT, result));
+                    }
+                    else
+                    {
+                        /*Codes_SRS_HTTP_HEADERS_99_013:[ The function shall return HTTP_HEADERS_OK when execution is successful.]*/
+                        result = HTTP_HEADERS_OK;
+                    }
+                    free(newValue);
+                }
+            }
+            else
+            {
+                /*Codes_SRS_HTTP_HEADERS_99_016:[ The function shall store the name:value pair in such a way that when later retrieved by a call to GetHeader it will return a string that shall strcmp equal to the name+": "+value.]*/
+                if (Map_AddOrUpdate(handleData->headers, name, value) != MAP_OK)
+                {
+                    /*Codes_SRS_HTTP_HEADERS_99_015:[ The function shall return HTTP_HEADERS_ALLOC_FAILED when an internal request to allocate memory fails.]*/
+                    result = HTTP_HEADERS_ALLOC_FAILED;
+                    LogError("failed to Map_AddOrUpdate, result= %" PRI_MU_ENUM "", MU_ENUM_VALUE(HTTP_HEADERS_RESULT, result));
+                }
+                else
+                {
+                    result = HTTP_HEADERS_OK;
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+HTTP_HEADERS_RESULT HTTPHeaders_AddHeaderNameValuePair(HTTP_HEADERS_HANDLE httpHeadersHandle, const char* name, const char* value)
+{
+    return headers_ReplaceHeaderNameValuePair(httpHeadersHandle, name, value, false);
+}
+
+/* Codes_SRS_HTTP_HEADERS_06_001: [This API will perform exactly as HTTPHeaders_AddHeaderNameValuePair except that if the header name already exists the already existing value will be replaced as opposed to concatenated to.] */
+HTTP_HEADERS_RESULT HTTPHeaders_ReplaceHeaderNameValuePair(HTTP_HEADERS_HANDLE httpHeadersHandle, const char* name, const char* value)
+{
+    return headers_ReplaceHeaderNameValuePair(httpHeadersHandle, name, value, true);
+}
+
+
+const char* HTTPHeaders_FindHeaderValue(HTTP_HEADERS_HANDLE httpHeadersHandle, const char* name)
+{
+    const char* result;
+    /*Codes_SRS_HTTP_HEADERS_99_022:[ The return value shall be NULL if name parameter is NULL or if httpHeadersHandle is NULL]*/
+    if (
+        (httpHeadersHandle == NULL) ||
+        (name == NULL)
+        )
+    {
+        result = NULL;
+    }
+    else
+    {
+        /*Codes_SRS_HTTP_HEADERS_99_018:[ Calling this API shall retrieve the value for a previously stored name.]*/
+        /*Codes_SRS_HTTP_HEADERS_99_020:[ The return value shall be different than NULL when the name matches the name of a previously stored name:value pair.] */
+        /*Codes_SRS_HTTP_HEADERS_99_021:[ In this case the return value shall point to a string that shall strcmp equal to the original stored string.]*/
+        HTTP_HEADERS_HANDLE_DATA* handleData = (HTTP_HEADERS_HANDLE_DATA*)httpHeadersHandle;
+        result = Map_GetValueFromKey(handleData->headers, name);
+    }
+    return result;
+
+}
+
+HTTP_HEADERS_RESULT HTTPHeaders_GetHeaderCount(HTTP_HEADERS_HANDLE handle, size_t* headerCount)
+{
+    HTTP_HEADERS_RESULT result;
+    /*Codes_SRS_HTTP_HEADERS_99_024:[ The function shall return HTTP_HEADERS_INVALID_ARG when an invalid handle is passed.]*/
+    /*Codes_SRS_HTTP_HEADERS_99_025:[ The function shall return HTTP_HEADERS_INVALID_ARG when headersCount is NULL.]*/
+    if ((handle == NULL) ||
+        (headerCount == NULL))
+    {
+        result = HTTP_HEADERS_INVALID_ARG;
+        LogError("(result = %" PRI_MU_ENUM ")", MU_ENUM_VALUE(HTTP_HEADERS_RESULT, result));
+    }
+    else
+    {
+        HTTP_HEADERS_HANDLE_DATA *handleData = (HTTP_HEADERS_HANDLE_DATA *)handle;
+        const char*const* keys;
+        const char*const* values;
+        /*Codes_SRS_HTTP_HEADERS_99_023:[ Calling this API shall provide the number of stored headers.]*/
+        if (Map_GetInternals(handleData->headers, &keys, &values, headerCount) != MAP_OK)
+        {
+            /*Codes_SRS_HTTP_HEADERS_99_037:[ The function shall return HTTP_HEADERS_ERROR when an internal error occurs.]*/
+            result = HTTP_HEADERS_ERROR;
+            LogError("Map_GetInternals failed, result= %" PRI_MU_ENUM "", MU_ENUM_VALUE(HTTP_HEADERS_RESULT, result));
+        }
+        else
+        {
+            /*Codes_SRS_HTTP_HEADERS_99_026:[ The function shall write in *headersCount the number of currently stored headers and shall return HTTP_HEADERS_OK]*/
+            result = HTTP_HEADERS_OK;
+        }
+    }
+
+    return result;
+}
+
+/*produces a string in *destination that is equal to name: value*/
+HTTP_HEADERS_RESULT HTTPHeaders_GetHeader(HTTP_HEADERS_HANDLE handle, size_t index, char** destination)
+{
+    HTTP_HEADERS_RESULT result = HTTP_HEADERS_OK;
+
+    /*Codes_SRS_HTTP_HEADERS_99_028:[ The function shall return NULL if the handle is invalid.]*/
+    /*Codes_SRS_HTTP_HEADERS_99_032:[ The function shall return HTTP_HEADERS_INVALID_ARG if the destination  is NULL]*/
+    if (
+        (handle == NULL) ||
+        (destination == NULL)
+        )
+    {
+        result = HTTP_HEADERS_INVALID_ARG;
+        LogError("invalid arg (NULL), result= %" PRI_MU_ENUM "", MU_ENUM_VALUE(HTTP_HEADERS_RESULT, result));
+    }
+    /*Codes_SRS_HTTP_HEADERS_99_029:[ The function shall return HTTP_HEADERS_INVALID_ARG if index is not valid (for example, out of range) for the currently stored headers.]*/
+    else
+    {
+        HTTP_HEADERS_HANDLE_DATA* handleData = (HTTP_HEADERS_HANDLE_DATA*)handle;
+        const char*const* keys;
+        const char*const* values;
+        size_t headerCount;
+        if (Map_GetInternals(handleData->headers, &keys, &values, &headerCount) != MAP_OK)
+        {
+            /*Codes_SRS_HTTP_HEADERS_99_034:[ The function shall return HTTP_HEADERS_ERROR when an internal error occurs]*/
+            result = HTTP_HEADERS_ERROR;
+            LogError("Map_GetInternals failed, result= %" PRI_MU_ENUM "", MU_ENUM_VALUE(HTTP_HEADERS_RESULT, result));
+        }
+        else
+        {
+            /*Codes_SRS_HTTP_HEADERS_99_029:[ The function shall return HTTP_HEADERS_INVALID_ARG if index is not valid (for example, out of range) for the currently stored headers.]*/
+            if (index >= headerCount)
+            {
+                result = HTTP_HEADERS_INVALID_ARG;
+                LogError("index out of bounds, result= %" PRI_MU_ENUM "", MU_ENUM_VALUE(HTTP_HEADERS_RESULT, result));
+            }
+            else
+            {
+                size_t keyLen = strlen(keys[index]);
+                size_t valueLen = strlen(values[index]);
+                *destination = (char*)malloc(sizeof(char) * (keyLen + /*COLON_AND_SPACE_LENGTH*/ 2 + valueLen + /*EOL*/ 1));
+                if (*destination == NULL)
+                {
+                    /*Codes_SRS_HTTP_HEADERS_99_034:[ The function shall return HTTP_HEADERS_ERROR when an internal error occurs]*/
+                    result = HTTP_HEADERS_ERROR;
+                    LogError("unable to malloc, result= %" PRI_MU_ENUM "", MU_ENUM_VALUE(HTTP_HEADERS_RESULT, result));
+                }
+                else
+                {
+                    /*Codes_SRS_HTTP_HEADERS_99_016:[ The function shall store the name:value pair in such a way that when later retrieved by a call to GetHeader it will return a string that shall strcmp equal to the name+": "+value.]*/
+                    /*Codes_SRS_HTTP_HEADERS_99_027:[ Calling this API shall produce the string value+": "+pair) for the index header in the *destination parameter.]*/
+                    char* runDestination = (*destination);
+                    (void)memcpy(runDestination, keys[index], keyLen);
+                    runDestination += keyLen;
+                    (*runDestination++) = ':';
+                    (*runDestination++) = ' ';
+                    (void)memcpy(runDestination, values[index], valueLen + /*EOL*/ 1);
+                    /*Codes_SRS_HTTP_HEADERS_99_035:[ The function shall return HTTP_HEADERS_OK when the function executed without error.]*/
+                    result = HTTP_HEADERS_OK;
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+HTTP_HEADERS_HANDLE HTTPHeaders_Clone(HTTP_HEADERS_HANDLE handle)
+{
+    HTTP_HEADERS_HANDLE_DATA* result;
+    /*Codes_SRS_HTTP_HEADERS_02_003: [If handle is NULL then HTTPHeaders_Clone shall return NULL.] */
+    if (handle == NULL)
+    {
+        result = NULL;
+    }
+    else
+    {
+        /*Codes_SRS_HTTP_HEADERS_02_004: [Otherwise HTTPHeaders_Clone shall clone the content of handle to a new handle.] */
+        result = (HTTP_HEADERS_HANDLE_DATA*)malloc(sizeof(HTTP_HEADERS_HANDLE_DATA));
+        if (result == NULL)
+        {
+            /*Codes_SRS_HTTP_HEADERS_02_005: [If cloning fails for any reason, then HTTPHeaders_Clone shall return NULL.] */
+        }
+        else
+        {
+            HTTP_HEADERS_HANDLE_DATA* handleData = handle;
+            result->headers = Map_Clone(handleData->headers);
+            if (result->headers == NULL)
+            {
+                /*Codes_SRS_HTTP_HEADERS_02_005: [If cloning fails for any reason, then HTTPHeaders_Clone shall return NULL.] */
+                free(result);
+                result = NULL;
+            }
+            else
+            {
+                /*all is fine*/
+            }
+        }
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/map.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/map.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/map.c	(revision 453)
@@ -0,0 +1,678 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/map.h"
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/strings.h"
+
+MU_DEFINE_ENUM_STRINGS(MAP_RESULT, MAP_RESULT_VALUES);
+
+typedef struct MAP_HANDLE_DATA_TAG
+{
+    char** keys;
+    char** values;
+    size_t count;
+    MAP_FILTER_CALLBACK mapFilterCallback;
+}MAP_HANDLE_DATA;
+
+#define LOG_MAP_ERROR LogError("result = %" PRI_MU_ENUM "", MU_ENUM_VALUE(MAP_RESULT, result));
+
+MAP_HANDLE Map_Create(MAP_FILTER_CALLBACK mapFilterFunc)
+{
+    /*Codes_SRS_MAP_02_001: [Map_Create shall create a new, empty map.]*/
+    MAP_HANDLE_DATA* result = (MAP_HANDLE_DATA*)calloc(1, sizeof(MAP_HANDLE_DATA));
+    /*Codes_SRS_MAP_02_002: [If during creation there are any error, then Map_Create shall return NULL.]*/
+    if (result != NULL)
+    {
+        /*Codes_SRS_MAP_02_003: [Otherwise, it shall return a non-NULL handle that can be used in subsequent calls.] */
+        result->keys = NULL;
+        result->values = NULL;
+        result->count = 0;
+        result->mapFilterCallback = mapFilterFunc;
+    }
+    return (MAP_HANDLE)result;
+}
+
+void Map_Destroy(MAP_HANDLE handle)
+{
+    /*Codes_SRS_MAP_02_005: [If parameter handle is NULL then Map_Destroy shall take no action.] */
+    if (handle != NULL)
+    {
+        /*Codes_SRS_MAP_02_004: [Map_Destroy shall release all resources associated with the map.] */
+        MAP_HANDLE_DATA* handleData = (MAP_HANDLE_DATA*)handle;
+        size_t i;
+
+        for (i = 0; i < handleData->count; i++)
+        {
+            free(handleData->keys[i]);
+            free(handleData->values[i]);
+        }
+        free(handleData->keys);
+        free(handleData->values);
+        free(handleData);
+    }
+}
+
+/*makes a copy of a vector of const char*, having size "size". source cannot be NULL*/
+/*returns NULL if it fails*/
+static char** Map_CloneVector(const char*const * source, size_t count)
+{
+    char** result;
+    result = (char**)malloc(count *sizeof(char*));
+    if (result == NULL)
+    {
+        /*do nothing, just return it (NULL)*/
+    }
+    else
+    {
+        size_t i;
+        for (i = 0; i < count; i++)
+        {
+            if (mallocAndStrcpy_s(result + i, source[i]) != 0)
+            {
+                break;
+            }
+        }
+
+        if (i == count)
+        {
+            /*it is all good, proceed to return result*/
+        }
+        else
+        {
+            size_t j;
+            for (j = 0; j < i; j++)
+            {
+                free(result[j]);
+            }
+            free(result);
+            result = NULL;
+        }
+    }
+    return result;
+}
+
+/*Codes_SRS_MAP_02_039: [Map_Clone shall make a copy of the map indicated by parameter handle and return a non-NULL handle to it.]*/
+MAP_HANDLE Map_Clone(MAP_HANDLE handle)
+{
+    MAP_HANDLE_DATA* result;
+    if (handle == NULL)
+    {
+        /*Codes_SRS_MAP_02_038: [Map_Clone returns NULL if parameter handle is NULL.]*/
+        result = NULL;
+        LogError("invalid arg to Map_Clone (NULL)");
+    }
+    else
+    {
+        MAP_HANDLE_DATA * handleData = (MAP_HANDLE_DATA *)handle;
+        result = (MAP_HANDLE_DATA*)calloc(1, sizeof(MAP_HANDLE_DATA));
+        if (result == NULL)
+        {
+            /*Codes_SRS_MAP_02_047: [If during cloning, any operation fails, then Map_Clone shall return NULL.] */
+            /*do nothing, proceed to return it, this is an error case*/
+            LogError("unable to malloc");
+        }
+        else
+        {
+            if (handleData->count == 0)
+            {
+                result->count = 0;
+                result->keys = NULL;
+                result->values = NULL;
+                result->mapFilterCallback = NULL;
+            }
+            else
+            {
+                result->mapFilterCallback = handleData->mapFilterCallback;
+                result->count = handleData->count;
+                if( (result->keys = Map_CloneVector((const char* const*)handleData->keys, handleData->count))==NULL)
+                {
+                    /*Codes_SRS_MAP_02_047: [If during cloning, any operation fails, then Map_Clone shall return NULL.] */
+                    LogError("unable to clone keys");
+                    free(result);
+                    result = NULL;
+                }
+                else if ((result->values = Map_CloneVector((const char* const*)handleData->values, handleData->count)) == NULL)
+                {
+                    size_t i;
+                    /*Codes_SRS_MAP_02_047: [If during cloning, any operation fails, then Map_Clone shall return NULL.] */
+                    LogError("unable to clone values");
+                    for (i = 0; i < result->count; i++)
+                    {
+                        free(result->keys[i]);
+                    }
+                    free(result->keys);
+                    free(result);
+                    result = NULL;
+                }
+                else
+                {
+                    /*all fine, return it*/
+                }
+            }
+        }
+    }
+    return (MAP_HANDLE)result;
+}
+
+static int Map_IncreaseStorageKeysValues(MAP_HANDLE_DATA* handleData)
+{
+    int result;
+    char** newKeys = (char**)realloc(handleData->keys, (handleData->count + 1) * sizeof(char*));
+    if (newKeys == NULL)
+    {
+        LogError("realloc error");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        char** newValues;
+        handleData->keys = newKeys;
+        handleData->keys[handleData->count] = NULL;
+        newValues = (char**)realloc(handleData->values, (handleData->count + 1) * sizeof(char*));
+        if (newValues == NULL)
+        {
+            LogError("realloc error");
+            if (handleData->count == 0) /*avoiding an implementation defined behavior */
+            {
+                free(handleData->keys);
+                handleData->keys = NULL;
+            }
+            else
+            {
+                char** undoneKeys = (char**)realloc(handleData->keys, (handleData->count) * sizeof(char*));
+                if (undoneKeys == NULL)
+                {
+                    LogError("CATASTROPHIC error, unable to undo through realloc to a smaller size");
+                }
+                else
+                {
+                    handleData->keys = undoneKeys;
+                }
+            }
+            result = MU_FAILURE;
+        }
+        else
+        {
+            handleData->values = newValues;
+            handleData->values[handleData->count] = NULL;
+            handleData->count++;
+            result = 0;
+        }
+    }
+    return result;
+}
+
+static void Map_DecreaseStorageKeysValues(MAP_HANDLE_DATA* handleData)
+{
+    if (handleData->count == 1)
+    {
+        free(handleData->keys);
+        handleData->keys = NULL;
+        free(handleData->values);
+        handleData->values = NULL;
+        handleData->count = 0;
+        handleData->mapFilterCallback = NULL;
+    }
+    else
+    {
+        /*certainly > 1...*/
+        char** undoneValues;
+        char** undoneKeys = (char**)realloc(handleData->keys, sizeof(char*)* (handleData->count - 1));
+        if (undoneKeys == NULL)
+        {
+            LogError("CATASTROPHIC error, unable to undo through realloc to a smaller size");
+        }
+        else
+        {
+            handleData->keys = undoneKeys;
+        }
+
+        undoneValues = (char**)realloc(handleData->values, sizeof(char*)* (handleData->count - 1));
+        if (undoneValues == NULL)
+        {
+            LogError("CATASTROPHIC error, unable to undo through realloc to a smaller size");
+        }
+        else
+        {
+            handleData->values = undoneValues;
+        }
+
+        handleData->count--;
+    }
+}
+
+static char** findKey(MAP_HANDLE_DATA* handleData, const char* key)
+{
+    char** result;
+    if (handleData->keys == NULL)
+    {
+        result = NULL;
+    }
+    else
+    {
+        size_t i;
+        result = NULL;
+        for (i = 0; i < handleData->count; i++)
+        {
+            if (strcmp(handleData->keys[i], key) == 0)
+            {
+                result = handleData->keys + i;
+                break;
+            }
+        }
+    }
+    return result;
+}
+
+static char** findValue(MAP_HANDLE_DATA* handleData, const char* value)
+{
+    char** result;
+    if (handleData->values == NULL)
+    {
+        result = NULL;
+    }
+    else
+    {
+        size_t i;
+        result = NULL;
+        for (i = 0; i < handleData->count; i++)
+        {
+            if (strcmp(handleData->values[i], value) == 0)
+            {
+                result = handleData->values + i;
+                break;
+            }
+        }
+    }
+    return result;
+}
+
+static int insertNewKeyValue(MAP_HANDLE_DATA* handleData, const char* key, const char* value)
+{
+    int result;
+    if (Map_IncreaseStorageKeysValues(handleData) != 0) /*this increases handleData->count*/
+    {
+        result = MU_FAILURE;
+    }
+    else
+    {
+        if (mallocAndStrcpy_s(&(handleData->keys[handleData->count - 1]), key) != 0)
+        {
+            Map_DecreaseStorageKeysValues(handleData);
+            LogError("unable to mallocAndStrcpy_s");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if (mallocAndStrcpy_s(&(handleData->values[handleData->count - 1]), value) != 0)
+            {
+                free(handleData->keys[handleData->count - 1]);
+                Map_DecreaseStorageKeysValues(handleData);
+                LogError("unable to mallocAndStrcpy_s");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                result = 0;
+            }
+        }
+    }
+    return result;
+}
+
+MAP_RESULT Map_Add(MAP_HANDLE handle, const char* key, const char* value)
+{
+    MAP_RESULT result;
+    /*Codes_SRS_MAP_02_006: [If parameter handle is NULL then Map_Add shall return MAP_INVALID_ARG.] */
+    /*Codes_SRS_MAP_02_007: [If parameter key is NULL then Map_Add shall return MAP_INVALID_ARG.]*/
+    /*Codes_SRS_MAP_02_008: [If parameter value is NULL then Map_Add shall return MAP_INVALID_ARG.] */
+    if (
+        (handle == NULL) ||
+        (key == NULL) ||
+        (value == NULL)
+        )
+    {
+        result = MAP_INVALIDARG;
+        LOG_MAP_ERROR;
+    }
+    else
+    {
+        MAP_HANDLE_DATA* handleData = (MAP_HANDLE_DATA*)handle;
+        /*Codes_SRS_MAP_02_009: [If the key already exists, then Map_Add shall return MAP_KEYEXISTS.] */
+        if (findKey(handleData, key) != NULL)
+        {
+            result = MAP_KEYEXISTS;
+        }
+        else
+        {
+            /* Codes_SRS_MAP_07_009: [If the mapFilterCallback function is not NULL, then the return value will be check and if it is not zero then Map_Add shall return MAP_FILTER_REJECT.] */
+            if ( (handleData->mapFilterCallback != NULL) && (handleData->mapFilterCallback(key, value) != 0) )
+            {
+                result = MAP_FILTER_REJECT;
+            }
+            else
+            {
+                /*Codes_SRS_MAP_02_010: [Otherwise, Map_Add shall add the pair <key,value> to the map.] */
+                if (insertNewKeyValue(handleData, key, value) != 0)
+                {
+                    /*Codes_SRS_MAP_02_011: [If adding the pair <key,value> fails then Map_Add shall return MAP_ERROR.] */
+                    result = MAP_ERROR;
+                    LOG_MAP_ERROR;
+                }
+                else
+                {
+                    /*Codes_SRS_MAP_02_012: [Otherwise, Map_Add shall return MAP_OK.] */
+                    result = MAP_OK;
+                }
+            }
+        }
+    }
+    return result;
+}
+
+MAP_RESULT Map_AddOrUpdate(MAP_HANDLE handle, const char* key, const char* value)
+{
+    MAP_RESULT result;
+    /*Codes_SRS_MAP_02_013: [If parameter handle is NULL then Map_AddOrUpdate shall return MAP_INVALID_ARG.]*/
+    /*Codes_SRS_MAP_02_014: [If parameter key is NULL then Map_AddOrUpdate shall return MAP_INVALID_ARG.]*/
+    /*Codes_SRS_MAP_02_015: [If parameter value is NULL then Map_AddOrUpdate shall return MAP_INVALID_ARG.] */
+    if (
+        (handle == NULL) ||
+        (key == NULL) ||
+        (value == NULL)
+        )
+    {
+        result = MAP_INVALIDARG;
+        LOG_MAP_ERROR;
+    }
+    else
+    {
+        MAP_HANDLE_DATA* handleData = (MAP_HANDLE_DATA*)handle;
+
+        /* Codes_SRS_MAP_07_008: [If the mapFilterCallback function is not NULL, then the return value will be check and if it is not zero then Map_AddOrUpdate shall return MAP_FILTER_REJECT.] */
+        if (handleData->mapFilterCallback != NULL && handleData->mapFilterCallback(key, value) != 0)
+        {
+            result = MAP_FILTER_REJECT;
+        }
+        else
+        {
+            char** whereIsIt = findKey(handleData, key);
+            if (whereIsIt == NULL)
+            {
+                /*Codes_SRS_MAP_02_017: [Otherwise, Map_AddOrUpdate shall add the pair <key,value> to the map.]*/
+                if (insertNewKeyValue(handleData, key, value) != 0)
+                {
+                    result = MAP_ERROR;
+                    LOG_MAP_ERROR;
+                }
+                else
+                {
+                    result = MAP_OK;
+                }
+            }
+            else
+            {
+                /*Codes_SRS_MAP_02_016: [If the key already exists, then Map_AddOrUpdate shall overwrite the value of the existing key with parameter value.]*/
+                size_t index = whereIsIt - handleData->keys;
+                size_t valueLength = strlen(value);
+                /*try to realloc value of this key*/
+                char* newValue = (char*)realloc(handleData->values[index],valueLength  + 1);
+                if (newValue == NULL)
+                {
+                    result = MAP_ERROR;
+                    LOG_MAP_ERROR;
+                }
+                else
+                {
+                    (void)memcpy(newValue, value, valueLength + 1);
+                    handleData->values[index] = newValue;
+                    /*Codes_SRS_MAP_02_019: [Otherwise, Map_AddOrUpdate shall return MAP_OK.] */
+                    result = MAP_OK;
+                }
+            }
+        }
+    }
+    return result;
+}
+
+MAP_RESULT Map_Delete(MAP_HANDLE handle, const char* key)
+{
+    MAP_RESULT result;
+    /*Codes_SRS_MAP_02_020: [If parameter handle is NULL then Map_Delete shall return MAP_INVALIDARG.]*/
+    /*Codes_SRS_MAP_02_021: [If parameter key is NULL then Map_Delete shall return MAP_INVALIDARG.]*/
+    if (
+        (handle == NULL) ||
+        (key == NULL)
+        )
+    {
+        result = MAP_INVALIDARG;
+        LOG_MAP_ERROR;
+    }
+    else
+    {
+        MAP_HANDLE_DATA* handleData = (MAP_HANDLE_DATA*)handle;
+        char** whereIsIt = findKey(handleData,key);
+        if (whereIsIt == NULL)
+        {
+            /*Codes_SRS_MAP_02_022: [If key does not exist then Map_Delete shall return MAP_KEYNOTFOUND.]*/
+            result = MAP_KEYNOTFOUND;
+        }
+        else
+        {
+            /*Codes_SRS_MAP_02_023: [Otherwise, Map_Delete shall remove the key and its associated value from the map and return MAP_OK.]*/
+            size_t index = whereIsIt - handleData->keys;
+            free(handleData->keys[index]);
+            free(handleData->values[index]);
+            memmove(handleData->keys + index, handleData->keys + index + 1, (handleData->count - index - 1)*sizeof(char*)); /*if order doesn't matter... then this can be optimized*/
+            memmove(handleData->values + index, handleData->values + index + 1, (handleData->count - index - 1)*sizeof(char*));
+            Map_DecreaseStorageKeysValues(handleData);
+            result = MAP_OK;
+        }
+
+    }
+    return result;
+}
+
+MAP_RESULT Map_ContainsKey(MAP_HANDLE handle, const char* key, bool* keyExists)
+{
+    MAP_RESULT result;
+    /*Codes_SRS_MAP_02_024: [If parameter handle, key or keyExists are NULL then Map_ContainsKey shall return MAP_INVALIDARG.]*/
+    if (
+        (handle ==NULL) ||
+        (key == NULL) ||
+        (keyExists == NULL)
+        )
+    {
+        result = MAP_INVALIDARG;
+        LOG_MAP_ERROR;
+    }
+    else
+    {
+        MAP_HANDLE_DATA* handleData = (MAP_HANDLE_DATA*)handle;
+        /*Codes_SRS_MAP_02_025: [Otherwise if a key exists then Map_ContainsKey shall return MAP_OK and shall write in keyExists "true".]*/
+        /*Codes_SRS_MAP_02_026: [If a key doesn't exist, then Map_ContainsKey shall return MAP_OK and write in keyExists "false".] */
+        *keyExists = (findKey(handleData, key) != NULL) ? true: false;
+        result = MAP_OK;
+    }
+    return result;
+}
+
+MAP_RESULT Map_ContainsValue(MAP_HANDLE handle, const char* value, bool* valueExists)
+{
+    MAP_RESULT result;
+    /*Codes_SRS_MAP_02_027: [If parameter handle, value or valueExists is NULL then Map_ContainsValue shall return MAP_INVALIDARG.] */
+    if (
+        (handle == NULL) ||
+        (value == NULL) ||
+        (valueExists == NULL)
+        )
+    {
+        result = MAP_INVALIDARG;
+        LOG_MAP_ERROR;
+    }
+    else
+    {
+        MAP_HANDLE_DATA* handleData = (MAP_HANDLE_DATA*)handle;
+        /*Codes_SRS_MAP_02_028: [Otherwise, if a pair <key, value> has its value equal to the parameter value, the Map_ContainsValue shall return MAP_OK and shall write in valueExists "true".]*/
+        /*Codes_SRS_MAP_02_029: [Otherwise, if such a <key, value> does not exist, then Map_ContainsValue shall return MAP_OK and shall write in valueExists "false".] */
+        *valueExists = (findValue(handleData, value) != NULL) ? true : false;
+        result = MAP_OK;
+    }
+    return result;
+}
+
+const char* Map_GetValueFromKey(MAP_HANDLE handle, const char* key)
+{
+    const char* result;
+    /*Codes_SRS_MAP_02_040: [If parameter handle or key is NULL then Map_GetValueFromKey returns NULL.]*/
+    if (
+        (handle == NULL) ||
+        (key == NULL)
+        )
+    {
+        result = NULL;
+        LogError("invalid parameter to Map_GetValueFromKey");
+    }
+    else
+    {
+        MAP_HANDLE_DATA * handleData = (MAP_HANDLE_DATA *)handle;
+        char** whereIsIt = findKey(handleData, key);
+        if(whereIsIt == NULL)
+        {
+            /*Codes_SRS_MAP_02_041: [If the key is not found, then Map_GetValueFromKey returns NULL.]*/
+            result = NULL;
+        }
+        else
+        {
+            /*Codes_SRS_MAP_02_042: [Otherwise, Map_GetValueFromKey returns the key's value.] */
+            size_t index = whereIsIt - handleData->keys;
+            result = handleData->values[index];
+        }
+    }
+    return result;
+}
+
+MAP_RESULT Map_GetInternals(MAP_HANDLE handle, const char*const** keys, const char*const** values, size_t* count)
+{
+    MAP_RESULT result;
+    /*Codes_SRS_MAP_02_046: [If parameter handle, keys, values or count is NULL then Map_GetInternals shall return MAP_INVALIDARG.] */
+    if (
+        (handle == NULL) ||
+        (keys == NULL) ||
+        (values == NULL) ||
+        (count == NULL)
+        )
+    {
+        result = MAP_INVALIDARG;
+        LOG_MAP_ERROR;
+    }
+    else
+    {
+        /*Codes_SRS_MAP_02_043: [Map_GetInternals shall produce in *keys an pointer to an array of const char* having all the keys stored so far by the map.]*/
+        /*Codes_SRS_MAP_02_044: [Map_GetInternals shall produce in *values a pointer to an array of const char* having all the values stored so far by the map.]*/
+        /*Codes_SRS_MAP_02_045: [  Map_GetInternals shall produce in *count the number of stored keys and values.]*/
+        MAP_HANDLE_DATA * handleData = (MAP_HANDLE_DATA *)handle;
+        *keys =(const char* const*)(handleData->keys);
+        *values = (const char* const*)(handleData->values);
+        *count = handleData->count;
+        result = MAP_OK;
+    }
+    return result;
+}
+
+STRING_HANDLE Map_ToJSON(MAP_HANDLE handle)
+{
+    STRING_HANDLE result;
+    /*Codes_SRS_MAP_02_052: [If parameter handle is NULL then Map_ToJSON shall return NULL.] */
+    if (handle == NULL)
+    {
+        result = NULL;
+        LogError("invalid arg (NULL)");
+    }
+    else
+    {
+        /*Codes_SRS_MAP_02_048: [Map_ToJSON shall produce a STRING_HANDLE representing the content of the MAP.] */
+        result = STRING_construct("{");
+        if (result == NULL)
+        {
+            LogError("STRING_construct failed");
+        }
+        else
+        {
+            size_t i;
+            MAP_HANDLE_DATA* handleData = (MAP_HANDLE_DATA *)handle;
+            /*Codes_SRS_MAP_02_049: [If the MAP is empty, then Map_ToJSON shall produce the string "{}".*/
+            bool breakFor = false; /*used to break out of for*/
+            for (i = 0; (i < handleData->count) && (!breakFor); i++)
+            {
+                /*add one entry to the JSON*/
+                /*Codes_SRS_MAP_02_050: [If the map has properties then Map_ToJSON shall produce the following string:{"name1":"value1", "name2":"value2" ...}]*/
+                STRING_HANDLE key = STRING_new_JSON(handleData->keys[i]);
+                if (key == NULL)
+                {
+                    LogError("STRING_new_JSON failed");
+                    STRING_delete(result);
+                    result = NULL;
+                    breakFor = true;
+                }
+                else
+                {
+                    STRING_HANDLE value = STRING_new_JSON(handleData->values[i]);
+                    if (value == NULL)
+                    {
+                        LogError("STRING_new_JSON failed");
+                        STRING_delete(result);
+                        result = NULL;
+                        breakFor = true;
+                    }
+                    else
+                    {
+                        if (!(
+                            ((i>0) ? (STRING_concat(result, ",") == 0) : 1) &&
+                            (STRING_concat_with_STRING(result, key) == 0) &&
+                            (STRING_concat(result, ":") == 0) &&
+                            (STRING_concat_with_STRING(result, value) == 0)
+                            ))
+                        {
+                            LogError("failed to build the JSON");
+                            STRING_delete(result);
+                            result = NULL;
+                            breakFor = true;
+                        }
+                        else
+                        {
+                            /*all nice, go to the next element in the map*/
+                        }
+                        STRING_delete(value);
+                    }
+                    STRING_delete(key);
+                }
+            }
+
+            if (breakFor)
+            {
+                LogError("error happened during JSON string builder");
+            }
+            else
+            {
+                if (STRING_concat(result, "}") != 0)
+                {
+                    LogError("failed to build the JSON");
+                    STRING_delete(result);
+                    result = NULL;
+                }
+                else
+                {
+                    /*return as is, JSON has been build*/
+                }
+            }
+        }
+    }
+    return result;
+
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/optionhandler.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/optionhandler.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/optionhandler.c	(revision 453)
@@ -0,0 +1,268 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "azure_c_shared_utility/optionhandler.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/vector.h"
+
+typedef struct OPTION_TAG
+{
+    const char* name;
+    void* storage;
+}OPTION;
+
+typedef struct OPTIONHANDLER_HANDLE_DATA_TAG
+{
+    pfCloneOption cloneOption;
+    pfDestroyOption destroyOption;
+    pfSetOption setOption;
+    VECTOR_HANDLE storage;
+}OPTIONHANDLER_HANDLE_DATA;
+
+static OPTIONHANDLER_HANDLE CreateInternal(pfCloneOption cloneOption, pfDestroyOption destroyOption, pfSetOption setOption)
+{
+    OPTIONHANDLER_HANDLE result;
+
+    result = (OPTIONHANDLER_HANDLE_DATA*)malloc(sizeof(OPTIONHANDLER_HANDLE_DATA));
+    if (result == NULL)
+    {
+        /*Codes_SRS_OPTIONHANDLER_02_004: [ Otherwise, OptionHandler_Create shall fail and return NULL. ]*/
+        LogError("unable to malloc");
+        /*return as is*/
+    }
+    else
+    {
+        /*Codes_SRS_OPTIONHANDLER_02_002: [ OptionHandler_Create shall create an empty VECTOR that will hold pairs of const char* and void*. ]*/
+        result->storage = VECTOR_create(sizeof(OPTION));
+        if (result->storage == NULL)
+        {
+            /*Codes_SRS_OPTIONHANDLER_02_004: [ Otherwise, OptionHandler_Create shall fail and return NULL. ]*/
+            LogError("unable to VECTOR_create");
+            free(result);
+            result = NULL;
+        }
+        else
+        {
+            /*Codes_SRS_OPTIONHANDLER_02_003: [ If all the operations succeed then OptionHandler_Create shall succeed and return a non-NULL handle. ]*/
+            result->cloneOption = cloneOption;
+            result->destroyOption = destroyOption;
+            result->setOption = setOption;
+            /*return as is*/
+        }
+    }
+
+    return result;
+}
+
+static OPTIONHANDLER_RESULT AddOptionInternal(OPTIONHANDLER_HANDLE handle, const char* name, const void* value)
+{
+    OPTIONHANDLER_RESULT result;
+    const char* cloneOfName;
+    if (mallocAndStrcpy_s((char**)&cloneOfName, name) != 0)
+    {
+        /*Codes_SRS_OPTIONHANDLER_02_009: [ Otherwise, OptionHandler_AddProperty shall succeed and return OPTIONHANDLER_ERROR. ]*/
+        LogError("unable to clone name");
+        result = OPTIONHANDLER_ERROR;
+    }
+    else
+    {
+        /*Codes_SRS_OPTIONHANDLER_02_006: [ OptionHandler_AddProperty shall call pfCloneOption passing name and value. ]*/
+        void* cloneOfValue = handle->cloneOption(name, value);
+        if (cloneOfValue == NULL)
+        {
+            /*Codes_SRS_OPTIONHANDLER_02_009: [ Otherwise, OptionHandler_AddProperty shall succeed and return OPTIONHANDLER_ERROR. ]*/
+            LogError("unable to clone value");
+            free((void*)cloneOfName);
+            result = OPTIONHANDLER_ERROR;
+        }
+        else
+        {
+            OPTION temp;
+            temp.name = cloneOfName;
+            temp.storage = cloneOfValue;
+            /*Codes_SRS_OPTIONHANDLER_02_007: [ OptionHandler_AddProperty shall use VECTOR APIs to save the name and the newly created clone of value. ]*/
+            if (VECTOR_push_back(handle->storage, &temp, 1) != 0)
+            {
+                /*Codes_SRS_OPTIONHANDLER_02_009: [ Otherwise, OptionHandler_AddProperty shall succeed and return OPTIONHANDLER_ERROR. ]*/
+                LogError("unable to VECTOR_push_back");
+                handle->destroyOption(name, cloneOfValue);
+                free((void*)cloneOfName);
+                result = OPTIONHANDLER_ERROR;
+            }
+            else
+            {
+                /*Codes_SRS_OPTIONHANDLER_02_008: [ If all the operations succed then OptionHandler_AddProperty shall succeed and return OPTIONHANDLER_OK. ]*/
+                result = OPTIONHANDLER_OK;
+            }
+        }
+    }
+
+    return result;
+}
+
+static void DestroyInternal(OPTIONHANDLER_HANDLE handle)
+{
+    /*Codes_SRS_OPTIONHANDLER_02_016: [ Otherwise, OptionHandler_Destroy shall free all used resources. ]*/
+    size_t nOptions = VECTOR_size(handle->storage), i;
+    for (i = 0; i < nOptions; i++)
+    {
+        OPTION* option = (OPTION*)VECTOR_element(handle->storage, i);
+        handle->destroyOption(option->name, option->storage);
+        free((void*)option->name);
+    }
+
+    VECTOR_destroy(handle->storage);
+    free(handle);
+}
+
+OPTIONHANDLER_HANDLE OptionHandler_Create(pfCloneOption cloneOption, pfDestroyOption destroyOption, pfSetOption setOption)
+{
+    /*Codes_SRS_OPTIONHANDLER_02_001: [ OptionHandler_Create shall fail and retun NULL if any parameters are NULL. ]*/
+    OPTIONHANDLER_HANDLE_DATA* result;
+    if (
+        (cloneOption == NULL) ||
+        (destroyOption == NULL) ||
+        (setOption == NULL)
+        )
+    {
+        LogError("invalid parameter = pfCloneOption cloneOption=%p, pfDestroyOption destroyOption=%p, pfSetOption setOption=%p", cloneOption, destroyOption, setOption);
+        result = NULL;
+    }
+    else
+    {
+        result = CreateInternal(cloneOption, destroyOption, setOption);
+    }
+
+    return result;
+
+}
+
+OPTIONHANDLER_HANDLE OptionHandler_Clone(OPTIONHANDLER_HANDLE handler)
+{
+    OPTIONHANDLER_HANDLE_DATA* result;
+
+    if (handler == NULL)
+    {
+        /* Codes_SRS_OPTIONHANDLER_01_010: [ If handler is NULL, OptionHandler_Clone shall fail and return NULL. ]*/
+        LogError("NULL argument: handler");
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_OPTIONHANDLER_01_001: [ OptionHandler_Clone shall clone an existing option handler instance. ]*/
+        /* Codes_SRS_OPTIONHANDLER_01_002: [ On success it shall return a non-NULL handle. ]*/
+        /* Codes_SRS_OPTIONHANDLER_01_003: [ OptionHandler_Clone shall allocate memory for the new option handler instance. ]*/
+        result = CreateInternal(handler->cloneOption, handler->destroyOption, handler->setOption);
+        if (result == NULL)
+        {
+            /* Codes_SRS_OPTIONHANDLER_01_004: [ If allocating memory fails, OptionHandler_Clone shall return NULL. ]*/
+            LogError("unable to create option handler");
+        }
+        else
+        {
+            /* Codes_SRS_OPTIONHANDLER_01_005: [ OptionHandler_Clone shall iterate through all the options stored by the option handler to be cloned by using VECTOR's iteration mechanism. ]*/
+            size_t option_count = VECTOR_size(handler->storage);
+            size_t i;
+
+            for (i = 0; i < option_count; i++)
+            {
+                OPTION* option = (OPTION*)VECTOR_element(handler->storage, i);
+
+                /* Codes_SRS_OPTIONHANDLER_01_006: [ For each option the option name shall be cloned by calling mallocAndStrcpy_s. ]*/
+                /* Codes_SRS_OPTIONHANDLER_01_007: [ For each option the value shall be cloned by using the cloning function associated with the source option handler handler. ]*/
+                if (AddOptionInternal(result, option->name, option->storage) != OPTIONHANDLER_OK)
+                {
+                    /* Codes_SRS_OPTIONHANDLER_01_008: [ If cloning one of the option names fails, OptionHandler_Clone shall return NULL. ]*/
+                    /* Codes_SRS_OPTIONHANDLER_01_009: [ If cloning one of the option values fails, OptionHandler_Clone shall return NULL. ]*/
+                    LogError("Error cloning option %s", option->name);
+                    break;
+                }
+            }
+
+            if (i < option_count)
+            {
+                DestroyInternal(result);
+                result = NULL;
+            }
+        }
+    }
+
+    return result;
+}
+
+OPTIONHANDLER_RESULT OptionHandler_AddOption(OPTIONHANDLER_HANDLE handle, const char* name, const void* value)
+{
+    OPTIONHANDLER_RESULT result;
+    /*Codes_SRS_OPTIONHANDLER_02_001: [ OptionHandler_Create shall fail and retun NULL if any parameters are NULL. ]*/
+    if (
+        (handle == NULL) ||
+        (name == NULL) ||
+        (value == NULL)
+        )
+    {
+        LogError("invalid arguments: OPTIONHANDLER_HANDLE handle=%p, const char* name=%p, void* value=%p", handle, name, value);
+        result= OPTIONHANDLER_INVALIDARG;
+    }
+    else
+    {
+        result = AddOptionInternal(handle, name, value);
+    }
+
+    return result;
+}
+
+OPTIONHANDLER_RESULT OptionHandler_FeedOptions(OPTIONHANDLER_HANDLE handle, void* destinationHandle)
+{
+    OPTIONHANDLER_RESULT result;
+    /*Codes_SRS_OPTIONHANDLER_02_010: [ OptionHandler_FeedOptions shall fail and return OPTIONHANDLER_INVALIDARG if any argument is NULL. ]*/
+    if (
+        (handle == NULL) ||
+        (destinationHandle == NULL)
+        )
+    {
+        LogError("invalid arguments OPTIONHANDLER_HANDLE handle=%p, void* destinationHandle=%p", handle, destinationHandle);
+        result = OPTIONHANDLER_INVALIDARG;
+    }
+    else
+    {
+        /*Codes_SRS_OPTIONHANDLER_02_011: [ Otherwise, OptionHandler_FeedOptions shall use VECTOR's iteration mechanisms to retrieve pairs of name, value (const char* and void*). ]*/
+        size_t nOptions = VECTOR_size(handle->storage), i;
+        for (i = 0;i < nOptions;i++)
+        {
+            OPTION* option = (OPTION*)VECTOR_element(handle->storage, i);
+            /*Codes_SRS_OPTIONHANDLER_02_012: [ OptionHandler_FeedOptions shall call for every pair of name,value setOption passing destinationHandle, name and value. ]*/
+            if (handle->setOption(destinationHandle, option->name, option->storage) != 0)
+            {
+                LogError("failure while trying to SetOption with option %s", option->name);
+                break;
+            }
+        }
+
+        if (i == nOptions)
+        {
+            /*Codes_SRS_OPTIONHANDLER_02_014: [ Otherwise, OptionHandler_FeedOptions shall fail and return OPTIONHANDLER_ERROR. ]*/
+            result = OPTIONHANDLER_OK;
+        }
+        else
+        {
+            /*Codes_SRS_OPTIONHANDLER_02_013: [ If all the operations succeed then OptionHandler_FeedOptions shall succeed and return OPTIONHANDLER_OK. ]*/
+            result = OPTIONHANDLER_ERROR;
+        }
+    }
+    return result;
+}
+
+void OptionHandler_Destroy(OPTIONHANDLER_HANDLE handle)
+{
+    /*Codes_SRS_OPTIONHANDLER_02_015: [ OptionHandler_Destroy shall do nothing if parameter handle is NULL. ]*/
+    if (handle == NULL)
+    {
+        LogError("invalid argument OPTIONHANDLER_HANDLE handle=%p", handle);
+    }
+    else
+    {
+        DestroyInternal(handle);
+    }
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/sastoken.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/sastoken.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/sastoken.c	(revision 453)
@@ -0,0 +1,346 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/sastoken.h"
+#include "azure_c_shared_utility/urlencode.h"
+#include "azure_c_shared_utility/hmacsha256.h"
+#include "azure_c_shared_utility/azure_base64.h"
+#include "azure_c_shared_utility/agenttime.h"
+#include "azure_c_shared_utility/strings.h"
+#include "azure_c_shared_utility/buffer_.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+
+static double getExpiryValue(const char* expiryASCII)
+{
+    double value = 0;
+    size_t i = 0;
+    for (i = 0; expiryASCII[i] != '\0'; i++)
+    {
+        if (expiryASCII[i] >= '0' && expiryASCII[i] <= '9')
+        {
+            value = value * 10 + (double)(expiryASCII[i] - '0');
+        }
+        else
+        {
+            value = 0;
+            break;
+        }
+    }
+    return value;
+}
+
+bool SASToken_Validate(STRING_HANDLE sasToken)
+{
+    bool result;
+    /*Codes_SRS_SASTOKEN_25_025: [**SASToken_Validate shall get the SASToken value by invoking STRING_c_str on the handle.**]***/
+    const char* sasTokenArray = STRING_c_str(sasToken);
+
+    /* Codes_SRS_SASTOKEN_25_024: [**If handle is NULL then SASToken_Validate shall return false.**] */
+    /* Codes_SRS_SASTOKEN_25_026: [**If STRING_c_str on handle return NULL then SASToken_Validate shall return false.**] */
+    if (sasToken == NULL || sasTokenArray == NULL)
+    {
+        result = false;
+    }
+    else
+    {
+        int seStart = -1, seStop = -1;
+        int srStart = -1, srStop = -1;
+        int sigStart = -1, sigStop = -1;
+        int tokenLength = (int)STRING_length(sasToken);
+        int i;
+        for (i = 0; i < tokenLength; i++)
+        {
+            if (sasTokenArray[i] == 's' && sasTokenArray[i + 1] == 'e' && sasTokenArray[i + 2] == '=') // Look for se=
+            {
+                seStart = i + 3;
+                if (srStart > 0 && srStop < 0)
+                {
+                    if (sasTokenArray[i - 1] != '&' && sasTokenArray[i - 1] == ' ') // look for either & or space
+                        srStop = i - 1;
+                    else if (sasTokenArray[i - 1] == '&')
+                        srStop = i - 2;
+                    else
+                        seStart = -1; // as the format is not either "&se=" or " se="
+                }
+                else if (sigStart > 0 && sigStop < 0)
+                {
+                    if (sasTokenArray[i - 1] != '&' && sasTokenArray[i - 1] == ' ')
+                        sigStop = i - 1;
+                    else if (sasTokenArray[i - 1] == '&')
+                        sigStop = i - 2;
+                    else
+                        seStart = -1;
+                }
+            }
+            else if (sasTokenArray[i] == 's' && sasTokenArray[i + 1] == 'r' && sasTokenArray[i + 2] == '=') // Look for sr=
+            {
+                srStart = i + 3;
+                if (seStart > 0 && seStop < 0)
+                {
+                    if (sasTokenArray[i - 1] != '&' && sasTokenArray[i - 1] == ' ')
+                        seStop = i - 1;
+                    else if (sasTokenArray[i - 1] == '&')
+                        seStop = i - 2;
+                    else
+                        srStart = -1;
+                }
+                else if (sigStart > 0 && sigStop < 0)
+                {
+                    if (sasTokenArray[i - 1] != '&' && sasTokenArray[i - 1] == ' ')
+                        sigStop = i - 1;
+                    else if (sasTokenArray[i - 1] == '&')
+                        sigStop = i - 2;
+                    else
+                        srStart = -1;
+                }
+            }
+            else if (sasTokenArray[i] == 's' && sasTokenArray[i + 1] == 'i' && sasTokenArray[i + 2] == 'g' && sasTokenArray[i + 3] == '=') // Look for sig=
+            {
+                sigStart = i + 4;
+                if (srStart > 0 && srStop < 0)
+                {
+                    if (sasTokenArray[i - 1] != '&' && sasTokenArray[i - 1] == ' ')
+                        srStop = i - 1;
+                    else if (sasTokenArray[i - 1] == '&')
+                        srStop = i - 2;
+                    else
+                        sigStart = -1;
+                }
+                else if (seStart > 0 && seStop < 0)
+                {
+                    if (sasTokenArray[i - 1] != '&' && sasTokenArray[i - 1] == ' ')
+                        seStop = i - 1;
+                    else if (sasTokenArray[i - 1] == '&')
+                        seStop = i - 2;
+                    else
+                        sigStart = -1;
+                }
+            }
+        }
+
+        /*Codes_SRS_SASTOKEN_25_027: [**If SASTOKEN does not obey the SASToken format then SASToken_Validate shall return false.**]***/
+        /*Codes_SRS_SASTOKEN_25_028: [**SASToken_validate shall check for the presence of sr, se and sig from the token and return false if not found**]***/
+        if (seStart < 0 || srStart < 0 || sigStart < 0)
+        {
+            result = false;
+        }
+        else
+        {
+            if (seStop < 0)
+            {
+                seStop = tokenLength;
+            }
+            else if (srStop < 0)
+            {
+                srStop = tokenLength;
+            }
+            else if (sigStop < 0)
+            {
+                sigStop = tokenLength;
+            }
+
+            if ((seStop <= seStart) ||
+                (srStop <= srStart) ||
+                (sigStop <= sigStart))
+            {
+                result = false;
+            }
+            else
+            {
+                char* expiryASCII = (char*)malloc(seStop - seStart + 1);
+                /*Codes_SRS_SASTOKEN_25_031: [**If malloc fails during validation then SASToken_Validate shall return false.**]***/
+                if (expiryASCII == NULL)
+                {
+                    result = false;
+                }
+                else
+                {
+                    double expiry;
+                    // Add the Null terminator here
+                    memset(expiryASCII, 0, seStop - seStart + 1);
+                    for (i = seStart; i < seStop; i++)
+                    {
+                        // The se contains the expiration values, if a & token is encountered then
+                        // the se field is complete.
+                        if (sasTokenArray[i] == '&')
+                        {
+                            break;
+                        }
+                        expiryASCII[i - seStart] = sasTokenArray[i];
+                    }
+                    expiry = getExpiryValue(expiryASCII);
+                    /*Codes_SRS_SASTOKEN_25_029: [**SASToken_validate shall check for expiry time from token and if token has expired then would return false **]***/
+                    if (expiry <= 0)
+                    {
+                        result = false;
+                    }
+                    else
+                    {
+                        double secSinceEpoch = get_difftime(get_time(NULL), (time_t)0);
+                        if (expiry < secSinceEpoch)
+                        {
+                            /*Codes_SRS_SASTOKEN_25_029: [**SASToken_validate shall check for expiry time from token and if token has expired then would return false **]***/
+                            result = false;
+                        }
+                        else
+                        {
+                            /*Codes_SRS_SASTOKEN_25_030: [**SASToken_validate shall return true only if the format is obeyed and the token has not yet expired **]***/
+                            result = true;
+                        }
+                    }
+                    free(expiryASCII);
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+static STRING_HANDLE construct_sas_token(const char* key, const char* scope, const char* keyname, size_t expiry)
+{
+    STRING_HANDLE result;
+
+    char tokenExpirationTime[32] = { 0 };
+
+    BUFFER_HANDLE decodedKey;
+
+    /*Codes_SRS_SASTOKEN_06_029: [The key parameter is decoded from base64.]*/
+    if ((decodedKey = Azure_Base64_Decode(key)) == NULL)
+    {
+        /*Codes_SRS_SASTOKEN_06_030: [If there is an error in the decoding then SASToken_Create shall return NULL.]*/
+        LogError("Unable to decode the key for generating the SAS.");
+        result = NULL;
+    }
+    else
+    {
+        /*Codes_SRS_SASTOKEN_06_026: [If the conversion to string form fails for any reason then SASToken_Create shall return NULL.]*/
+        if (size_tToString(tokenExpirationTime, sizeof(tokenExpirationTime), expiry) != 0)
+        {
+            LogError("For some reason converting seconds to a string failed.  No SAS can be generated.");
+            result = NULL;
+        }
+        else
+        {
+            STRING_HANDLE toBeHashed = NULL;
+            BUFFER_HANDLE hash = NULL;
+            if (((hash = BUFFER_new()) == NULL) ||
+                ((toBeHashed = STRING_new()) == NULL) ||
+                ((result = STRING_new()) == NULL))
+            {
+                LogError("Unable to allocate memory to prepare SAS token.");
+                result = NULL;
+            }
+            else
+            {
+                /*Codes_SRS_SASTOKEN_06_009: [The scope is the basis for creating a STRING_HANDLE.]*/
+                /*Codes_SRS_SASTOKEN_06_010: [A "\n" is appended to that string.]*/
+                /*Codes_SRS_SASTOKEN_06_011: [tokenExpirationTime is appended to that string.]*/
+                if ((STRING_concat(toBeHashed, scope) != 0) ||
+                    (STRING_concat(toBeHashed, "\n") != 0) ||
+                    (STRING_concat(toBeHashed, tokenExpirationTime) != 0))
+                {
+                    LogError("Unable to build the input to the HMAC to prepare SAS token.");
+                    STRING_delete(result);
+                    result = NULL;
+                }
+                else
+                {
+                    STRING_HANDLE base64Signature = NULL;
+                    STRING_HANDLE urlEncodedSignature = NULL;
+                    size_t inLen = STRING_length(toBeHashed);
+                    const unsigned char* inBuf = (const unsigned char*)STRING_c_str(toBeHashed);
+                    size_t outLen = BUFFER_length(decodedKey);
+                    unsigned char* outBuf = BUFFER_u_char(decodedKey);
+                    /*Codes_SRS_SASTOKEN_06_013: [If an error is returned from the HMAC256 function then NULL is returned from SASToken_Create.]*/
+                    /*Codes_SRS_SASTOKEN_06_012: [An HMAC256 hash is calculated using the decodedKey, over toBeHashed.]*/
+                    /*Codes_SRS_SASTOKEN_06_014: [If there are any errors from the following operations then NULL shall be returned.]*/
+                    /*Codes_SRS_SASTOKEN_06_015: [The hash is base 64 encoded.]*/
+                    /*Codes_SRS_SASTOKEN_06_028: [base64Signature shall be url encoded.]*/
+                    /*Codes_SRS_SASTOKEN_06_016: [The string "SharedAccessSignature sr=" is the first part of the result of SASToken_Create.]*/
+                    /*Codes_SRS_SASTOKEN_06_017: [The scope parameter is appended to result.]*/
+                    /*Codes_SRS_SASTOKEN_06_018: [The string "&sig=" is appended to result.]*/
+                    /*Codes_SRS_SASTOKEN_06_019: [The string urlEncodedSignature shall be appended to result.]*/
+                    /*Codes_SRS_SASTOKEN_06_020: [The string "&se=" shall be appended to result.]*/
+                    /*Codes_SRS_SASTOKEN_06_021: [tokenExpirationTime is appended to result.]*/
+                    /*Codes_SRS_SASTOKEN_06_022: [If keyName is non-NULL, the string "&skn=" is appended to result.]*/
+                    /*Codes_SRS_SASTOKEN_06_023: [If keyName is non-NULL, the argument keyName is appended to result.]*/
+                    if ((HMACSHA256_ComputeHash(outBuf, outLen, inBuf, inLen, hash) != HMACSHA256_OK) ||
+                        ((base64Signature = Azure_Base64_Encode(hash)) == NULL) ||
+                        ((urlEncodedSignature = URL_Encode(base64Signature)) == NULL) ||
+                        (STRING_copy(result, "SharedAccessSignature sr=") != 0) ||
+                        (STRING_concat(result, scope) != 0) ||
+                        (STRING_concat(result, "&sig=") != 0) ||
+                        (STRING_concat_with_STRING(result, urlEncodedSignature) != 0) ||
+                        (STRING_concat(result, "&se=") != 0) ||
+                        (STRING_concat(result, tokenExpirationTime) != 0) ||
+                        ((keyname != NULL) && (STRING_concat(result, "&skn=") != 0)) ||
+                        ((keyname != NULL) && (STRING_concat(result, keyname) != 0)))
+                    {
+                        LogError("Unable to build the SAS token.");
+                        STRING_delete(result);
+                        result = NULL;
+                    }
+                    else
+                    {
+                        /* everything OK */
+                    }
+                    STRING_delete(base64Signature);
+                    STRING_delete(urlEncodedSignature);
+                }
+            }
+            STRING_delete(toBeHashed);
+            BUFFER_delete(hash);
+        }
+        BUFFER_delete(decodedKey);
+    }
+    return result;
+}
+
+STRING_HANDLE SASToken_Create(STRING_HANDLE key, STRING_HANDLE scope, STRING_HANDLE keyName, size_t expiry)
+{
+    STRING_HANDLE result;
+
+    /*Codes_SRS_SASTOKEN_06_001: [If key is NULL then SASToken_Create shall return NULL.]*/
+    /*Codes_SRS_SASTOKEN_06_003: [If scope is NULL then SASToken_Create shall return NULL.]*/
+    /*Codes_SRS_SASTOKEN_06_007: [keyName is optional and can be set to NULL.]*/
+    if ((key == NULL) ||
+        (scope == NULL))
+    {
+        LogError("Invalid Parameter to SASToken_Create. handle key: %p, handle scope: %p, handle keyName: %p", key, scope, keyName);
+        result = NULL;
+    }
+    else
+    {
+        const char* string_key = STRING_c_str(key);
+        const char* string_scope = STRING_c_str(scope);
+        const char* string_name = STRING_c_str(keyName);
+        result = construct_sas_token(string_key, string_scope, string_name, expiry);
+    }
+    return result;
+}
+
+STRING_HANDLE SASToken_CreateString(const char* key, const char* scope, const char* keyName, size_t expiry)
+{
+    STRING_HANDLE result;
+
+    /*Codes_SRS_SASTOKEN_06_001: [If key is NULL then SASToken_Create shall return NULL.]*/
+    /*Codes_SRS_SASTOKEN_06_003: [If scope is NULL then SASToken_Create shall return NULL.]*/
+    /*Codes_SRS_SASTOKEN_06_007: [keyName is optional and can be set to NULL.]*/
+    if ((key == NULL) ||
+        (scope == NULL))
+    {
+        LogError("Invalid Parameter to SASToken_Create. handle key: %p, handle scope: %p, handle keyName: %p", key, scope, keyName);
+        result = NULL;
+    }
+    else
+    {
+        result = construct_sas_token(key, scope, keyName, expiry);
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/sha1.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/sha1.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/sha1.c	(revision 453)
@@ -0,0 +1,445 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/**************************** sha1.c ****************************/
+/******************** See RFC 4634 for details ******************/
+/*
+*  Description:
+*      This file implements the Secure Hash Signature Standard
+*      algorithms as defined in the National Institute of Standards
+*      and Technology Federal Information Processing Standards
+*      Publication (FIPS PUB) 180-1 published on April 17, 1995, 180-2
+*      published on August 1, 2002, and the FIPS PUB 180-2 Change
+*      Notice published on February 28, 2004.
+*
+*      A combined document showing all algorithms is available at
+*              http://csrc.nist.gov/publications/fips/
+*              fips180-2/fips180-2withchangenotice.pdf
+*
+*      The SHA-1 algorithm produces a 160-bit message digest for a
+*      given data stream.  It should take about 2**n steps to find a
+*      message with the same digest as a given message and
+*      2**(n/2) to find any two messages with the same digest,
+*      when n is the digest size in bits.  Therefore, this
+*      algorithm can serve as a means of providing a
+*      "fingerprint" for a message.
+*
+*  Portability Issues:
+*      SHA-1 is defined in terms of 32-bit "words".  This code
+*      uses <stdint.h> (included via "sha.h") to define 32 and 8
+*      bit unsigned integer types.  If your C compiler does not
+*      support 32 bit unsigned integers, this code is not
+*      appropriate.
+*
+*  Caveats:
+*      SHA-1 is designed to work with messages less than 2^64 bits
+*      long. This implementation uses SHA1Input() to hash the bits
+*      that are a multiple of the size of an 8-bit character, and then
+*      uses SHA1FinalBits() to hash the final few bits of the input.
+*/
+
+#include <stdlib.h>
+#include "azure_c_shared_utility/gballoc.h"
+
+#include "azure_c_shared_utility/sha.h"
+#include "azure_c_shared_utility/sha-private.h"
+
+/*
+*  Define the SHA1 circular left shift macro
+*/
+#define SHA1_ROTL(bits,word) \
+                (((word) << (bits)) | ((word) >> (32-(bits))))
+
+/*
+* add "length" to the length
+*/
+#define SHA1AddLength(context, length)                     \
+    (addTemp = (context)->Length_Low,                      \
+     (context)->Corrupted =                                \
+        (((context)->Length_Low += (length)) < addTemp) && \
+        (++(context)->Length_High == 0) ? 1 : 0)
+
+/* Local Function Prototypes */
+static void SHA1Finalize(SHA1Context *context, uint8_t Pad_Byte);
+static void SHA1PadMessage(SHA1Context *, uint8_t Pad_Byte);
+static void SHA1ProcessMessageBlock(SHA1Context *);
+
+/*
+*  SHA1Reset
+*
+*  Description:
+*      This function will initialize the SHA1Context in preparation
+*      for computing a new SHA1 message digest.
+*
+*  Parameters:
+*      context: [in/out]
+*          The context to reset.
+*
+*  Returns:
+*      sha Error Code.
+*
+*/
+int SHA1Reset(SHA1Context *context)
+{
+    if (!context)
+        return shaNull;
+
+    context->Length_Low = 0;
+    context->Length_High = 0;
+    context->Message_Block_Index = 0;
+
+
+    /* Initial Hash Values: FIPS-180-2 section 5.3.1 */
+    context->Intermediate_Hash[0] = 0x67452301;
+    context->Intermediate_Hash[1] = 0xEFCDAB89;
+    context->Intermediate_Hash[2] = 0x98BADCFE;
+    context->Intermediate_Hash[3] = 0x10325476;
+    context->Intermediate_Hash[4] = 0xC3D2E1F0;
+
+    context->Computed = 0;
+    context->Corrupted = 0;
+
+    return shaSuccess;
+}
+
+/*
+*  SHA1Input
+*
+*  Description:
+*      This function accepts an array of octets as the next portion
+*      of the message.
+*
+*  Parameters:
+*      context: [in/out]
+*          The SHA context to update
+*      message_array: [in]
+*          An array of characters representing the next portion of
+*          the message.
+*      length: [in]
+*          The length of the message in message_array
+*
+*  Returns:
+*      sha Error Code.
+*
+*/
+int SHA1Input(SHA1Context *context, const uint8_t *message_array, unsigned int length)
+{
+    int result;
+    uint32_t addTemp;
+    if (!length)
+    {
+        result = shaSuccess;
+    }
+    else if (!context || !message_array)
+    {
+        result = shaNull;
+    }
+    else if (context->Computed) 
+    {
+        result = context->Corrupted = shaStateError;
+    }
+    else if (context->Corrupted)
+    {
+        result = context->Corrupted;
+    }
+    else
+    {
+        while (length-- && !context->Corrupted)
+        {
+            context->Message_Block[context->Message_Block_Index++] = (*message_array & 0xFF);
+
+            if (!SHA1AddLength(context, 8) && (context->Message_Block_Index == SHA1_Message_Block_Size))
+            {
+                SHA1ProcessMessageBlock(context);
+            }
+            message_array++;
+        }
+        result = shaSuccess;
+    }
+    return result;
+}
+
+/*
+* SHA1FinalBits
+*
+* Description:
+*   This function will add in any final bits of the message.
+*
+* Parameters:
+*   context: [in/out]
+*     The SHA context to update
+*   message_bits: [in]
+*     The final bits of the message, in the upper portion of the
+*     byte. (Use 0b###00000 instead of 0b00000### to input the
+*     three bits ###.)
+*   length: [in]
+*     The number of bits in message_bits, between 1 and 7.
+*
+* Returns:
+*   sha Error Code.
+*/
+int SHA1FinalBits(SHA1Context *context, const uint8_t message_bits,
+    unsigned int length)
+{
+    uint32_t addTemp;
+
+    uint8_t masks[8] = {
+        /* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80,
+        /* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0,
+        /* 4 0b11110000 */ 0xF0, /* 5 0b11111000 */ 0xF8,
+        /* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE
+    };
+    uint8_t markbit[8] = {
+        /* 0 0b10000000 */ 0x80, /* 1 0b01000000 */ 0x40,
+        /* 2 0b00100000 */ 0x20, /* 3 0b00010000 */ 0x10,
+        /* 4 0b00001000 */ 0x08, /* 5 0b00000100 */ 0x04,
+        /* 6 0b00000010 */ 0x02, /* 7 0b00000001 */ 0x01
+    };
+
+    if (!length)
+        return shaSuccess;
+
+    if (!context)
+        return shaNull;
+
+    if (context->Computed || (length >= 8) || (length == 0)) {
+        context->Corrupted = shaStateError;
+        return shaStateError;
+    }
+
+    if (context->Corrupted)
+        return context->Corrupted;
+
+    SHA1AddLength(context, length);
+    SHA1Finalize(context,
+        (uint8_t)((message_bits & masks[length]) | markbit[length]));
+
+    return shaSuccess;
+}
+
+/*
+* SHA1Result
+*
+* Description:
+*   This function will return the 160-bit message digest into the
+*   Message_Digest array provided by the caller.
+*   NOTE: The first octet of hash is stored in the 0th element,
+*      the last octet of hash in the 19th element.
+*
+* Parameters:
+*   context: [in/out]
+*     The context to use to calculate the SHA-1 hash.
+*   Message_Digest: [out]
+*     Where the digest is returned.
+*
+* Returns:
+*   sha Error Code.
+*
+*/
+int SHA1Result(SHA1Context *context,
+    uint8_t Message_Digest[SHA1HashSize])
+{
+    int i;
+
+    if (!context || !Message_Digest)
+        return shaNull;
+
+    if (context->Corrupted)
+        return context->Corrupted;
+
+    if (!context->Computed)
+        SHA1Finalize(context, 0x80);
+
+    for (i = 0; i < SHA1HashSize; ++i)
+        Message_Digest[i] = (uint8_t)(context->Intermediate_Hash[i >> 2]
+        >> 8 * (3 - (i & 0x03)));
+
+    return shaSuccess;
+}
+
+/*
+* SHA1Finalize
+*
+* Description:
+*   This helper function finishes off the digest calculations.
+*
+* Parameters:
+*   context: [in/out]
+*     The SHA context to update
+*   Pad_Byte: [in]
+*     The last byte to add to the digest before the 0-padding
+*     and length. This will contain the last bits of the message
+*     followed by another single bit. If the message was an
+*     exact multiple of 8-bits long, Pad_Byte will be 0x80.
+*
+* Returns:
+*   sha Error Code.
+*
+*/
+static void SHA1Finalize(SHA1Context *context, uint8_t Pad_Byte)
+{
+    int i;
+    SHA1PadMessage(context, Pad_Byte);
+    /* message may be sensitive, clear it out */
+    for (i = 0; i < SHA1_Message_Block_Size; ++i)
+        context->Message_Block[i] = 0;
+    context->Length_Low = 0;  /* and clear length */
+    context->Length_High = 0;
+    context->Computed = 1;
+}
+
+/*
+* SHA1PadMessage
+*
+* Description:
+*   According to the standard, the message must be padded to an
+*   even 512 bits. The first padding bit must be a '1'. The last
+*   64 bits represent the length of the original message. All bits
+*   in between should be 0. This helper function will pad the
+*   message according to those rules by filling the Message_Block
+*   array accordingly. When it returns, it can be assumed that the
+*   message digest has been computed.
+*
+* Parameters:
+*   context: [in/out]
+*     The context to pad
+*   Pad_Byte: [in]
+*     The last byte to add to the digest before the 0-padding
+*     and length. This will contain the last bits of the message
+*     followed by another single bit. If the message was an
+*     exact multiple of 8-bits long, Pad_Byte will be 0x80.
+*
+* Returns:
+*   Nothing.
+*/
+static void SHA1PadMessage(SHA1Context *context, uint8_t Pad_Byte)
+{
+    /*
+    * Check to see if the current message block is too small to hold
+    * the initial padding bits and length. If so, we will pad the
+    * block, process it, and then continue padding into a second
+    * block.
+    */
+    if (context->Message_Block_Index >= (SHA1_Message_Block_Size - 8)) {
+        context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
+        while (context->Message_Block_Index < SHA1_Message_Block_Size)
+            context->Message_Block[context->Message_Block_Index++] = 0;
+
+        SHA1ProcessMessageBlock(context);
+    }
+    else
+        context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
+
+    while (context->Message_Block_Index < (SHA1_Message_Block_Size - 8))
+        context->Message_Block[context->Message_Block_Index++] = 0;
+
+    /*
+    * Store the message length as the last 8 octets
+    */
+    context->Message_Block[56] = (uint8_t)(context->Length_High >> 24);
+    context->Message_Block[57] = (uint8_t)(context->Length_High >> 16);
+
+    context->Message_Block[58] = (uint8_t)(context->Length_High >> 8);
+    context->Message_Block[59] = (uint8_t)(context->Length_High);
+    context->Message_Block[60] = (uint8_t)(context->Length_Low >> 24);
+    context->Message_Block[61] = (uint8_t)(context->Length_Low >> 16);
+    context->Message_Block[62] = (uint8_t)(context->Length_Low >> 8);
+    context->Message_Block[63] = (uint8_t)(context->Length_Low);
+
+    SHA1ProcessMessageBlock(context);
+}
+
+/*
+* SHA1ProcessMessageBlock
+*
+* Description:
+*   This helper function will process the next 512 bits of the
+*   message stored in the Message_Block array.
+*
+* Parameters:
+*   None.
+*
+* Returns:
+*   Nothing.
+*
+* Comments:
+*   Many of the variable names in this code, especially the
+*   single character names, were used because those were the
+*   names used in the publication.
+*/
+static void SHA1ProcessMessageBlock(SHA1Context *context)
+{
+    /* Constants defined in FIPS-180-2, section 4.2.1 */
+    const uint32_t K[4] = {
+        0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6
+    };
+    int        t;               /* Loop counter */
+    uint32_t   temp;            /* Temporary word value */
+    uint32_t   W[80];           /* Word sequence */
+    uint32_t   A, B, C, D, E;   /* Word buffers */
+
+    /*
+    * Initialize the first 16 words in the array W
+    */
+    for (t = 0; t < 16; t++) {
+        W[t] = ((uint32_t)context->Message_Block[t * 4]) << 24;
+        W[t] |= ((uint32_t)context->Message_Block[t * 4 + 1]) << 16;
+        W[t] |= ((uint32_t)context->Message_Block[t * 4 + 2]) << 8;
+        W[t] |= ((uint32_t)context->Message_Block[t * 4 + 3]);
+    }
+
+    for (t = 16; t < 80; t++)
+        W[t] = SHA1_ROTL(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]);
+
+    A = context->Intermediate_Hash[0];
+    B = context->Intermediate_Hash[1];
+    C = context->Intermediate_Hash[2];
+    D = context->Intermediate_Hash[3];
+    E = context->Intermediate_Hash[4];
+
+    for (t = 0; t < 20; t++) {
+        temp = SHA1_ROTL(5, A) + SHA_Ch(B, C, D) + E + W[t] + K[0];
+        E = D;
+        D = C;
+        C = SHA1_ROTL(30, B);
+        B = A;
+        A = temp;
+    }
+
+    for (t = 20; t < 40; t++) {
+        temp = SHA1_ROTL(5, A) + SHA_Parity(B, C, D) + E + W[t] + K[1];
+        E = D;
+        D = C;
+        C = SHA1_ROTL(30, B);
+        B = A;
+        A = temp;
+    }
+
+    for (t = 40; t < 60; t++) {
+        temp = SHA1_ROTL(5, A) + SHA_Maj(B, C, D) + E + W[t] + K[2];
+        E = D;
+        D = C;
+        C = SHA1_ROTL(30, B);
+        B = A;
+        A = temp;
+    }
+
+    for (t = 60; t < 80; t++) {
+        temp = SHA1_ROTL(5, A) + SHA_Parity(B, C, D) + E + W[t] + K[3];
+        E = D;
+        D = C;
+        C = SHA1_ROTL(30, B);
+        B = A;
+        A = temp;
+    }
+
+    context->Intermediate_Hash[0] += A;
+    context->Intermediate_Hash[1] += B;
+    context->Intermediate_Hash[2] += C;
+
+    context->Intermediate_Hash[3] += D;
+    context->Intermediate_Hash[4] += E;
+
+    context->Message_Block_Index = 0;
+}
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/sha224.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/sha224.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/sha224.c	(revision 453)
@@ -0,0 +1,624 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/*************************** sha224-256.c ***************************/
+/********************* See RFC 4634 for details *********************/
+/*
+* Description:
+*   This file implements the Secure Hash Signature Standard
+*   algorithms as defined in the National Institute of Standards
+*   and Technology Federal Information Processing Standards
+*   Publication (FIPS PUB) 180-1 published on April 17, 1995, 180-2
+*   published on August 1, 2002, and the FIPS PUB 180-2 Change
+*   Notice published on February 28, 2004.
+*
+*   A combined document showing all algorithms is available at
+*       http://csrc.nist.gov/publications/fips/
+*       fips180-2/fips180-2withchangenotice.pdf
+*
+*   The SHA-224 and SHA-256 algorithms produce 224-bit and 256-bit
+*   message digests for a given data stream. It should take about
+*   2**n steps to find a message with the same digest as a given
+*   message and 2**(n/2) to find any two messages with the same
+*   digest, when n is the digest size in bits. Therefore, this
+*   algorithm can serve as a means of providing a
+*   "fingerprint" for a message.
+*
+* Portability Issues:
+*   SHA-224 and SHA-256 are defined in terms of 32-bit "words".
+*   This code uses <stdint.h> (included via "sha.h") to define 32
+*   and 8 bit unsigned integer types. If your C compiler does not
+*   support 32 bit unsigned integers, this code is not
+*   appropriate.
+*
+* Caveats:
+*   SHA-224 and SHA-256 are designed to work with messages less
+*   than 2^64 bits long. This implementation uses SHA224/256Input()
+*   to hash the bits that are a multiple of the size of an 8-bit
+*   character, and then uses SHA224/256FinalBits() to hash the
+*   final few bits of the input.
+*/
+
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "azure_c_shared_utility/sha.h"
+#include "azure_c_shared_utility/sha-private.h"
+/* Define the SHA shift, rotate left and rotate right macro */
+#define SHA256_SHR(bits,word)      ((word) >> (bits))
+#define SHA256_ROTL(bits,word)                         \
+  (((word) << (bits)) | ((word) >> (32-(bits))))
+#define SHA256_ROTR(bits,word)                         \
+  (((word) >> (bits)) | ((word) << (32-(bits))))
+
+/* Define the SHA SIGMA and sigma macros */
+#define SHA256_SIGMA0(word)   \
+  (SHA256_ROTR( 2,word) ^ SHA256_ROTR(13,word) ^ SHA256_ROTR(22,word))
+#define SHA256_SIGMA1(word)   \
+  (SHA256_ROTR( 6,word) ^ SHA256_ROTR(11,word) ^ SHA256_ROTR(25,word))
+#define SHA256_sigma0(word)   \
+  (SHA256_ROTR( 7,word) ^ SHA256_ROTR(18,word) ^ SHA256_SHR( 3,word))
+#define SHA256_sigma1(word)   \
+  (SHA256_ROTR(17,word) ^ SHA256_ROTR(19,word) ^ SHA256_SHR(10,word))
+
+/*
+* add "length" to the length
+*/
+#define SHA224_256AddLength(context, length)               \
+  (addTemp = (context)->Length_Low, (context)->Corrupted = \
+    (((context)->Length_Low += (length)) < addTemp) &&     \
+    (++(context)->Length_High == 0) ? 1 : 0)
+
+/* Local Function Prototypes */
+static void SHA224_256Finalize(SHA256Context *context, uint8_t Pad_Byte);
+static void SHA224_256PadMessage(SHA256Context *context, uint8_t Pad_Byte);
+static void SHA224_256ProcessMessageBlock(SHA256Context *context);
+static int SHA224_256Reset(SHA256Context *context, uint32_t *H0);
+static int SHA224_256ResultN(SHA256Context *context, uint8_t Message_Digest[], int HashSize);
+
+/* Initial Hash Values: FIPS-180-2 Change Notice 1 */
+static uint32_t SHA224_H0[SHA256HashSize / 4] = {
+    0xC1059ED8, 0x367CD507, 0x3070DD17, 0xF70E5939,
+    0xFFC00B31, 0x68581511, 0x64F98FA7, 0xBEFA4FA4
+};
+
+/* Initial Hash Values: FIPS-180-2 section 5.3.2 */
+static uint32_t SHA256_H0[SHA256HashSize / 4] = {
+    0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
+    0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
+};
+
+/*
+* SHA224Reset
+*
+* Description:
+*   This function will initialize the SHA384Context in preparation
+*   for computing a new SHA224 message digest.
+*
+* Parameters:
+*   context: [in/out]
+*     The context to reset.
+*
+* Returns:
+*   sha Error Code.
+*/
+int SHA224Reset(SHA224Context *context)
+{
+    return SHA224_256Reset(context, SHA224_H0);
+}
+
+/*
+* SHA224Input
+*
+* Description:
+*   This function accepts an array of octets as the next portion
+*   of the message.
+*
+* Parameters:
+*   context: [in/out]
+*     The SHA context to update
+*   message_array: [in]
+*     An array of characters representing the next portion of
+*     the message.
+*   length: [in]
+*     The length of the message in message_array
+*
+* Returns:
+*   sha Error Code.
+*
+*/
+int SHA224Input(SHA224Context *context, const uint8_t *message_array, unsigned int length)
+{
+    return SHA256Input(context, message_array, length);
+}
+
+/*
+* SHA224FinalBits
+*
+* Description:
+*   This function will add in any final bits of the message.
+*
+* Parameters:
+*   context: [in/out]
+*     The SHA context to update
+*   message_bits: [in]
+*     The final bits of the message, in the upper portion of the
+*     byte. (Use 0b###00000 instead of 0b00000### to input the
+*     three bits ###.)
+*   length: [in]
+*     The number of bits in message_bits, between 1 and 7.
+*
+* Returns:
+*   sha Error Code.
+*/
+int SHA224FinalBits(SHA224Context *context, const uint8_t message_bits, unsigned int length)
+{
+    return SHA256FinalBits(context, message_bits, length);
+}
+
+/*
+* SHA224Result
+*
+* Description:
+*   This function will return the 224-bit message
+*   digest into the Message_Digest array provided by the caller.
+*   NOTE: The first octet of hash is stored in the 0th element,
+*      the last octet of hash in the 28th element.
+*
+* Parameters:
+*   context: [in/out]
+*     The context to use to calculate the SHA hash.
+*   Message_Digest: [out]
+*     Where the digest is returned.
+*
+* Returns:
+*   sha Error Code.
+*/
+int SHA224Result(SHA224Context *context, uint8_t Message_Digest[SHA224HashSize])
+{
+    return SHA224_256ResultN(context, Message_Digest, SHA224HashSize);
+}
+
+/*
+* SHA256Reset
+*
+* Description:
+*   This function will initialize the SHA256Context in preparation
+*   for computing a new SHA256 message digest.
+*
+* Parameters:
+*   context: [in/out]
+*     The context to reset.
+*
+* Returns:
+*   sha Error Code.
+*/
+int SHA256Reset(SHA256Context *context)
+{
+    return SHA224_256Reset(context, SHA256_H0);
+}
+
+/*
+* SHA256Input
+*
+* Description:
+*   This function accepts an array of octets as the next portion
+*   of the message.
+*
+* Parameters:
+*   context: [in/out]
+*     The SHA context to update
+*   message_array: [in]
+*     An array of characters representing the next portion of
+*     the message.
+*   length: [in]
+*     The length of the message in message_array
+*
+* Returns:
+*   sha Error Code.
+*/
+int SHA256Input(SHA256Context *context, const uint8_t *message_array, unsigned int length)
+{
+    int result;
+    uint32_t addTemp;
+    if (!length)
+    {
+        result = shaSuccess;
+    }
+    else if (!context || !message_array)
+    {
+        result = shaNull;
+    }
+    else if (context->Computed)
+    {
+        result = context->Corrupted = shaStateError;
+    }
+    else if (context->Corrupted)
+    {
+        result = context->Corrupted;
+    }
+    else
+    {
+        while (length-- && !context->Corrupted)
+        {
+            context->Message_Block[context->Message_Block_Index++] = (*message_array & 0xFF);
+
+            if (!SHA224_256AddLength(context, 8) && (context->Message_Block_Index == SHA256_Message_Block_Size))
+            {
+                SHA224_256ProcessMessageBlock(context);
+            }
+            message_array++;
+        }
+        result = shaSuccess;
+    }
+    return result;
+}
+
+/*
+* SHA256FinalBits
+*
+* Description:
+*   This function will add in any final bits of the message.
+*
+* Parameters:
+*   context: [in/out]
+*     The SHA context to update
+*   message_bits: [in]
+*     The final bits of the message, in the upper portion of the
+*     byte. (Use 0b###00000 instead of 0b00000### to input the
+*     three bits ###.)
+*   length: [in]
+*     The number of bits in message_bits, between 1 and 7.
+*
+* Returns:
+*   sha Error Code.
+*/
+int SHA256FinalBits(SHA256Context *context, const uint8_t message_bits, unsigned int length)
+{
+    int result;
+    uint32_t addTemp;
+    uint8_t masks[8] = {
+        /* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80,
+        /* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0,
+        /* 4 0b11110000 */ 0xF0, /* 5 0b11111000 */ 0xF8,
+        /* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE
+    };
+
+    uint8_t markbit[8] = {
+        /* 0 0b10000000 */ 0x80, /* 1 0b01000000 */ 0x40,
+        /* 2 0b00100000 */ 0x20, /* 3 0b00010000 */ 0x10,
+        /* 4 0b00001000 */ 0x08, /* 5 0b00000100 */ 0x04,
+        /* 6 0b00000010 */ 0x02, /* 7 0b00000001 */ 0x01
+    };
+
+    if (!length)
+    {
+        result = shaSuccess;
+    }
+    else if (!context)
+    {
+        result = shaNull;
+    }
+    else if ((context->Computed) || (length >= 8) || (length == 0))
+    {
+        result = context->Corrupted = shaStateError;
+    }
+    else if (context->Corrupted)
+    {
+        result = context->Corrupted;
+    }
+    else
+    {
+        SHA224_256AddLength(context, length);
+        SHA224_256Finalize(context, (uint8_t)((message_bits & masks[length]) | markbit[length]));
+        result = shaSuccess;
+    }
+    return result;
+}
+
+/*
+* SHA256Result
+*
+* Description:
+*   This function will return the 256-bit message
+*   digest into the Message_Digest array provided by the caller.
+*   NOTE: The first octet of hash is stored in the 0th element,
+*      the last octet of hash in the 32nd element.
+*
+* Parameters:
+*   context: [in/out]
+*     The context to use to calculate the SHA hash.
+*   Message_Digest: [out]
+*     Where the digest is returned.
+*
+* Returns:
+*   sha Error Code.
+*/
+int SHA256Result(SHA256Context *context, uint8_t Message_Digest[SHA256HashSize])
+{
+    return SHA224_256ResultN(context, Message_Digest, SHA256HashSize);
+}
+
+/*
+* SHA224_256Finalize
+*
+* Description:
+*   This helper function finishes off the digest calculations.
+*
+* Parameters:
+*   context: [in/out]
+*     The SHA context to update
+*   Pad_Byte: [in]
+*     The last byte to add to the digest before the 0-padding
+*     and length. This will contain the last bits of the message
+*     followed by another single bit. If the message was an
+*     exact multiple of 8-bits long, Pad_Byte will be 0x80.
+*
+* Returns:
+*   sha Error Code.
+*/
+static void SHA224_256Finalize(SHA256Context *context, uint8_t Pad_Byte)
+{
+    int i;
+    SHA224_256PadMessage(context, Pad_Byte);
+    /* message may be sensitive, so clear it out */
+    for (i = 0; i < SHA256_Message_Block_Size; ++i)
+    {
+        context->Message_Block[i] = 0;
+    }
+    context->Length_Low = 0;  /* and clear length */
+    context->Length_High = 0;
+    context->Computed = 1;
+}
+
+/*
+* SHA224_256PadMessage
+*
+* Description:
+*   According to the standard, the message must be padded to an
+*   even 512 bits. The first padding bit must be a '1'. The
+*   last 64 bits represent the length of the original message.
+*   All bits in between should be 0. This helper function will pad
+*   the message according to those rules by filling the
+*   Message_Block array accordingly. When it returns, it can be
+*   assumed that the message digest has been computed.
+*
+* Parameters:
+*   context: [in/out]
+*     The context to pad
+*   Pad_Byte: [in]
+*     The last byte to add to the digest before the 0-padding
+*     and length. This will contain the last bits of the message
+*     followed by another single bit. If the message was an
+*     exact multiple of 8-bits long, Pad_Byte will be 0x80.
+*
+* Returns:
+*   Nothing.
+*/
+static void SHA224_256PadMessage(SHA256Context *context, uint8_t Pad_Byte)
+{
+    /*
+    * Check to see if the current message block is too small to hold
+    * the initial padding bits and length. If so, we will pad the
+    * block, process it, and then continue padding into a second
+    * block.
+    */
+    if (context->Message_Block_Index >= (SHA256_Message_Block_Size - 8))
+    {
+        context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
+        while (context->Message_Block_Index < SHA256_Message_Block_Size)
+        {
+            context->Message_Block[context->Message_Block_Index++] = 0;
+        }
+        SHA224_256ProcessMessageBlock(context);
+    }
+    else
+    {
+        context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
+    }
+
+    while (context->Message_Block_Index < (SHA256_Message_Block_Size - 8))
+    {
+        context->Message_Block[context->Message_Block_Index++] = 0;
+    }
+
+    /*
+    * Store the message length as the last 8 octets
+    */
+    context->Message_Block[56] = (uint8_t)(context->Length_High >> 24);
+    context->Message_Block[57] = (uint8_t)(context->Length_High >> 16);
+    context->Message_Block[58] = (uint8_t)(context->Length_High >> 8);
+    context->Message_Block[59] = (uint8_t)(context->Length_High);
+    context->Message_Block[60] = (uint8_t)(context->Length_Low >> 24);
+    context->Message_Block[61] = (uint8_t)(context->Length_Low >> 16);
+    context->Message_Block[62] = (uint8_t)(context->Length_Low >> 8);
+    context->Message_Block[63] = (uint8_t)(context->Length_Low);
+
+    SHA224_256ProcessMessageBlock(context);
+}
+
+/*
+* SHA224_256ProcessMessageBlock
+*
+* Description:
+*   This function will process the next 512 bits of the message
+*   stored in the Message_Block array.
+*
+* Parameters:
+*   context: [in/out]
+*     The SHA context to update
+*
+* Returns:
+*   Nothing.
+*
+* Comments:
+*   Many of the variable names in this code, especially the
+*   single character names, were used because those were the
+*   names used in the publication.
+*/
+static void SHA224_256ProcessMessageBlock(SHA256Context *context)
+{
+    /* Constants defined in FIPS-180-2, section 4.2.2 */
+    static const uint32_t K[64] = {
+        0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b,
+        0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01,
+        0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7,
+        0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+        0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152,
+        0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
+        0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
+        0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+        0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819,
+        0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08,
+        0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f,
+        0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+        0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+    };
+    int        t, t4;                   /* Loop counter */
+    uint32_t   temp1, temp2;            /* Temporary word value */
+    uint32_t   W[64];                   /* Word sequence */
+    uint32_t   A, B, C, D, E, F, G, H;  /* Word buffers */
+
+    /*
+    * Initialize the first 16 words in the array W
+    */
+    for (t = t4 = 0; t < 16; t++, t4 += 4)
+    {
+        W[t] = (((uint32_t)context->Message_Block[t4]) << 24) |
+            (((uint32_t)context->Message_Block[t4 + 1]) << 16) |
+            (((uint32_t)context->Message_Block[t4 + 2]) << 8) |
+            (((uint32_t)context->Message_Block[t4 + 3]));
+    }
+    for (t = 16; t < 64; t++)
+    {
+        W[t] = SHA256_sigma1(W[t - 2]) + W[t - 7] +
+            SHA256_sigma0(W[t - 15]) + W[t - 16];
+    }
+    A = context->Intermediate_Hash[0];
+    B = context->Intermediate_Hash[1];
+    C = context->Intermediate_Hash[2];
+    D = context->Intermediate_Hash[3];
+    E = context->Intermediate_Hash[4];
+    F = context->Intermediate_Hash[5];
+    G = context->Intermediate_Hash[6];
+    H = context->Intermediate_Hash[7];
+
+    for (t = 0; t < 64; t++)
+    {
+        temp1 = H + SHA256_SIGMA1(E) + SHA_Ch(E, F, G) + K[t] + W[t];
+        temp2 = SHA256_SIGMA0(A) + SHA_Maj(A, B, C);
+        H = G;
+        G = F;
+        F = E;
+        E = D + temp1;
+        D = C;
+        C = B;
+        B = A;
+        A = temp1 + temp2;
+    }
+
+    context->Intermediate_Hash[0] += A;
+    context->Intermediate_Hash[1] += B;
+    context->Intermediate_Hash[2] += C;
+    context->Intermediate_Hash[3] += D;
+    context->Intermediate_Hash[4] += E;
+    context->Intermediate_Hash[5] += F;
+    context->Intermediate_Hash[6] += G;
+    context->Intermediate_Hash[7] += H;
+
+    context->Message_Block_Index = 0;
+}
+
+/*
+* SHA224_256Reset
+*
+* Description:
+*   This helper function will initialize the SHA256Context in
+*   preparation for computing a new SHA256 message digest.
+*
+* Parameters:
+*   context: [in/out]
+*     The context to reset.
+*   H0
+*     The initial hash value to use.
+*
+* Returns:
+*   sha Error Code.
+*/
+static int SHA224_256Reset(SHA256Context *context, uint32_t *H0)
+{
+    int result;
+    if (!context)
+    {
+        result = shaNull;
+    }
+    else
+    {
+        context->Length_Low = 0;
+        context->Length_High = 0;
+        context->Message_Block_Index = 0;
+
+        context->Intermediate_Hash[0] = H0[0];
+        context->Intermediate_Hash[1] = H0[1];
+        context->Intermediate_Hash[2] = H0[2];
+        context->Intermediate_Hash[3] = H0[3];
+        context->Intermediate_Hash[4] = H0[4];
+        context->Intermediate_Hash[5] = H0[5];
+        context->Intermediate_Hash[6] = H0[6];
+        context->Intermediate_Hash[7] = H0[7];
+
+        context->Computed = 0;
+        context->Corrupted = 0;
+        result = shaSuccess;
+    }
+    return result;
+}
+
+/*
+* SHA224_256ResultN
+*
+* Description:
+*   This helper function will return the 224-bit or 256-bit message
+*   digest into the Message_Digest array provided by the caller.
+*   NOTE: The first octet of hash is stored in the 0th element,
+*      the last octet of hash in the 28th/32nd element.
+*
+* Parameters:
+*   context: [in/out]
+*     The context to use to calculate the SHA hash.
+*   Message_Digest: [out]
+*     Where the digest is returned.
+*   HashSize: [in]
+*     The size of the hash, either 28 or 32.
+*
+* Returns:
+*   sha Error Code.
+*/
+static int SHA224_256ResultN(SHA256Context *context, uint8_t Message_Digest[], int HashSize)
+{
+    int result;
+    int i;
+
+    if (!context || !Message_Digest)
+    {
+        result = shaNull;
+    }
+    else if (context->Corrupted)
+    {
+        result = context->Corrupted;
+    }
+    else
+    {
+        if (!context->Computed)
+        {
+            SHA224_256Finalize(context, 0x80);
+        }
+        for (i = 0; i < HashSize; ++i)
+        {
+            Message_Digest[i] = (uint8_t)(context->Intermediate_Hash[i >> 2] >> 8 * (3 - (i & 0x03)));
+        }
+        result = shaSuccess;
+    }
+    return result;
+}
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/sha384-512.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/sha384-512.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/sha384-512.c	(revision 453)
@@ -0,0 +1,1046 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/*************************** sha384-512.c ***************************/
+/********************* See RFC 4634 for details *********************/
+/*
+* Description:
+*   This file implements the Secure Hash Signature Standard
+*   algorithms as defined in the National Institute of Standards
+*   and Technology Federal Information Processing Standards
+*   Publication (FIPS PUB) 180-1 published on April 17, 1995, 180-2
+*   published on August 1, 2002, and the FIPS PUB 180-2 Change
+*   Notice published on February 28, 2004.
+*
+*   A combined document showing all algorithms is available at
+*       http://csrc.nist.gov/publications/fips/
+*       fips180-2/fips180-2withchangenotice.pdf
+*
+*   The SHA-384 and SHA-512 algorithms produce 384-bit and 512-bit
+*   message digests for a given data stream. It should take about
+*   2**n steps to find a message with the same digest as a given
+*   message and 2**(n/2) to find any two messages with the same
+*   digest, when n is the digest size in bits. Therefore, this
+*   algorithm can serve as a means of providing a
+*   "fingerprint" for a message.
+*
+* Portability Issues:
+*   SHA-384 and SHA-512 are defined in terms of 64-bit "words",
+*   but if USE_32BIT_ONLY is #defined, this code is implemented in
+*   terms of 32-bit "words". This code uses <stdint.h> (included
+*   via "sha.h") to define the 64, 32 and 8 bit unsigned integer
+*   types. If your C compiler does not support 64 bit unsigned
+*   integers, and you do not #define USE_32BIT_ONLY, this code is
+*   not appropriate.
+*
+* Caveats:
+*   SHA-384 and SHA-512 are designed to work with messages less
+*   than 2^128 bits long. This implementation uses
+*   SHA384/512Input() to hash the bits that are a multiple of the
+*   size of an 8-bit character, and then uses SHA384/256FinalBits()
+*   to hash the final few bits of the input.
+*
+*/
+
+#include <stdlib.h>
+#include "azure_c_shared_utility/gballoc.h"
+
+#include "azure_c_shared_utility/sha.h"
+#include "azure_c_shared_utility/sha-private.h"
+
+#ifdef USE_32BIT_ONLY
+#error IoTHubClient does not support USE_32BIT_ONLY flag
+/*
+* Define 64-bit arithmetic in terms of 32-bit arithmetic.
+* Each 64-bit number is represented in a 2-word array.
+* All macros are defined such that the result is the last parameter.
+*/
+
+/*
+* Define shift, rotate left and rotate right functions
+*/
+#define SHA512_SHR(bits, word, ret) (                          \
+    /* (((uint64_t)((word))) >> (bits)) */                     \
+    (ret)[0] = (((bits) < 32) && ((bits) >= 0)) ?              \
+      ((word)[0] >> (bits)) : 0,                               \
+    (ret)[1] = ((bits) > 32) ? ((word)[0] >> ((bits) - 32)) :  \
+      ((bits) == 32) ? (word)[0] :                             \
+      ((bits) >= 0) ?                                          \
+        (((word)[0] << (32 - (bits))) |                        \
+        ((word)[1] >> (bits))) : 0 )
+
+#define SHA512_SHL(bits, word, ret) (                          \
+    /* (((uint64_t)(word)) << (bits)) */                       \
+    (ret)[0] = ((bits) > 32) ? ((word)[1] << ((bits) - 32)) :  \
+         ((bits) == 32) ? (word)[1] :                          \
+         ((bits) >= 0) ?                                       \
+           (((word)[0] << (bits)) |                            \
+           ((word)[1] >> (32 - (bits)))) :                     \
+0, \
+(ret)[1] = (((bits) < 32) && ((bits) >= 0)) ? \
+((word)[1] << (bits)) : 0)
+
+/*
+* Define 64-bit OR
+*/
+#define SHA512_OR(word1, word2, ret) (                         \
+    (ret)[0] = (word1)[0] | (word2)[0],                        \
+    (ret)[1] = (word1)[1] | (word2)[1] )
+
+/*
+* Define 64-bit XOR
+*/
+#define SHA512_XOR(word1, word2, ret) (                        \
+    (ret)[0] = (word1)[0] ^ (word2)[0],                        \
+    (ret)[1] = (word1)[1] ^ (word2)[1] )
+
+/*
+* Define 64-bit AND
+*/
+#define SHA512_AND(word1, word2, ret) (                        \
+    (ret)[0] = (word1)[0] & (word2)[0],                        \
+    (ret)[1] = (word1)[1] & (word2)[1] )
+
+/*
+* Define 64-bit TILDA
+*/
+#define SHA512_TILDA(word, ret)                                \
+  ( (ret)[0] = ~(word)[0], (ret)[1] = ~(word)[1] )
+
+/*
+* Define 64-bit ADD
+*/
+#define SHA512_ADD(word1, word2, ret) (                        \
+    (ret)[1] = (word1)[1], (ret)[1] += (word2)[1],             \
+    (ret)[0] = (word1)[0] + (word2)[0] + ((ret)[1] < (word1)[1]) )
+
+/*
+* Add the 4word value in word2 to word1.
+*/
+static uint32_t ADDTO4_temp, ADDTO4_temp2;
+#define SHA512_ADDTO4(word1, word2) (                          \
+    ADDTO4_temp = (word1)[3],                                  \
+    (word1)[3] += (word2)[3],                                  \
+    ADDTO4_temp2 = (word1)[2],                                 \
+    (word1)[2] += (word2)[2] + ((word1)[3] < ADDTO4_temp),     \
+    ADDTO4_temp = (word1)[1],                                  \
+(word1)[1] += (word2)[1] + ((word1)[2] < ADDTO4_temp2), \
+(word1)[0] += (word2)[0] + ((word1)[1] < ADDTO4_temp))
+
+/*
+* Add the 2word value in word2 to word1.
+*/
+static uint32_t ADDTO2_temp;
+#define SHA512_ADDTO2(word1, word2) (                          \
+    ADDTO2_temp = (word1)[1],                                  \
+    (word1)[1] += (word2)[1],                                  \
+    (word1)[0] += (word2)[0] + ((word1)[1] < ADDTO2_temp) )
+
+/*
+* SHA rotate   ((word >> bits) | (word << (64-bits)))
+*/
+static uint32_t ROTR_temp1[2], ROTR_temp2[2];
+#define SHA512_ROTR(bits, word, ret) (                         \
+    SHA512_SHR((bits), (word), ROTR_temp1),                    \
+    SHA512_SHL(64-(bits), (word), ROTR_temp2),                 \
+    SHA512_OR(ROTR_temp1, ROTR_temp2, (ret)) )
+
+/*
+* Define the SHA SIGMA and sigma macros
+*  SHA512_ROTR(28,word) ^ SHA512_ROTR(34,word) ^ SHA512_ROTR(39,word)
+*/
+static uint32_t SIGMA0_temp1[2], SIGMA0_temp2[2],
+SIGMA0_temp3[2], SIGMA0_temp4[2];
+#define SHA512_SIGMA0(word, ret) (                             \
+    SHA512_ROTR(28, (word), SIGMA0_temp1),                     \
+    SHA512_ROTR(34, (word), SIGMA0_temp2),                     \
+    SHA512_ROTR(39, (word), SIGMA0_temp3),                     \
+    SHA512_XOR(SIGMA0_temp2, SIGMA0_temp3, SIGMA0_temp4),      \
+    SHA512_XOR(SIGMA0_temp1, SIGMA0_temp4, (ret)) )
+
+/*
+* SHA512_ROTR(14,word) ^ SHA512_ROTR(18,word) ^ SHA512_ROTR(41,word)
+*/
+static uint32_t SIGMA1_temp1[2], SIGMA1_temp2[2],
+SIGMA1_temp3[2], SIGMA1_temp4[2];
+#define SHA512_SIGMA1(word, ret) (                             \
+    SHA512_ROTR(14, (word), SIGMA1_temp1),                     \
+    SHA512_ROTR(18, (word), SIGMA1_temp2),                     \
+    SHA512_ROTR(41, (word), SIGMA1_temp3),                     \
+    SHA512_XOR(SIGMA1_temp2, SIGMA1_temp3, SIGMA1_temp4),      \
+    SHA512_XOR(SIGMA1_temp1, SIGMA1_temp4, (ret)) )
+
+/*
+* (SHA512_ROTR( 1,word) ^ SHA512_ROTR( 8,word) ^ SHA512_SHR( 7,word))
+*/
+static uint32_t sigma0_temp1[2], sigma0_temp2[2],
+sigma0_temp3[2], sigma0_temp4[2];
+#define SHA512_sigma0(word, ret) (                             \
+    SHA512_ROTR( 1, (word), sigma0_temp1),                     \
+    SHA512_ROTR( 8, (word), sigma0_temp2),                     \
+    SHA512_SHR( 7, (word), sigma0_temp3),                      \
+    SHA512_XOR(sigma0_temp2, sigma0_temp3, sigma0_temp4),      \
+    SHA512_XOR(sigma0_temp1, sigma0_temp4, (ret)) )
+
+/*
+* (SHA512_ROTR(19,word) ^ SHA512_ROTR(61,word) ^ SHA512_SHR( 6,word))
+*/
+static uint32_t sigma1_temp1[2], sigma1_temp2[2],
+sigma1_temp3[2], sigma1_temp4[2];
+#define SHA512_sigma1(word, ret) (                             \
+    SHA512_ROTR(19, (word), sigma1_temp1),                     \
+    SHA512_ROTR(61, (word), sigma1_temp2),                     \
+    SHA512_SHR( 6, (word), sigma1_temp3),                      \
+    SHA512_XOR(sigma1_temp2, sigma1_temp3, sigma1_temp4),      \
+    SHA512_XOR(sigma1_temp1, sigma1_temp4, (ret)) )
+
+#undef SHA_Ch
+#undef SHA_Maj
+
+#ifndef USE_MODIFIED_MACROS
+/*
+* These definitions are the ones used in FIPS-180-2, section 4.1.3
+*  Ch(x,y,z)   ((x & y) ^ (~x & z))
+*/
+static uint32_t Ch_temp1[2], Ch_temp2[2], Ch_temp3[2];
+#define SHA_Ch(x, y, z, ret) (                                 \
+    SHA512_AND(x, y, Ch_temp1),                                \
+    SHA512_TILDA(x, Ch_temp2),                                 \
+    SHA512_AND(Ch_temp2, z, Ch_temp3),                         \
+    SHA512_XOR(Ch_temp1, Ch_temp3, (ret)) )
+/*
+*  Maj(x,y,z)  (((x)&(y)) ^ ((x)&(z)) ^ ((y)&(z)))
+*/
+static uint32_t Maj_temp1[2], Maj_temp2[2],
+Maj_temp3[2], Maj_temp4[2];
+#define SHA_Maj(x, y, z, ret) (                                \
+    SHA512_AND(x, y, Maj_temp1),                               \
+    SHA512_AND(x, z, Maj_temp2),                               \
+    SHA512_AND(y, z, Maj_temp3),                               \
+    SHA512_XOR(Maj_temp2, Maj_temp3, Maj_temp4),               \
+    SHA512_XOR(Maj_temp1, Maj_temp4, (ret)) )
+
+#else /* !USE_32BIT_ONLY */
+/*
+* These definitions are potentially faster equivalents for the ones
+* used in FIPS-180-2, section 4.1.3.
+*   ((x & y) ^ (~x & z)) becomes
+*   ((x & (y ^ z)) ^ z)
+*/
+#define SHA_Ch(x, y, z, ret) (                                 \
+   (ret)[0] = (((x)[0] & ((y)[0] ^ (z)[0])) ^ (z)[0]),         \
+   (ret)[1] = (((x)[1] & ((y)[1] ^ (z)[1])) ^ (z)[1]) )
+
+/*
+*   ((x & y) ^ (x & z) ^ (y & z)) becomes
+*   ((x & (y | z)) | (y & z))
+*/
+#define SHA_Maj(x, y, z, ret) (                                 \
+   ret[0] = (((x)[0] & ((y)[0] | (z)[0])) | ((y)[0] & (z)[0])), \
+   ret[1] = (((x)[1] & ((y)[1] | (z)[1])) | ((y)[1] & (z)[1])) )
+#endif /* USE_MODIFIED_MACROS */
+
+/*
+* add "length" to the length
+*/
+static uint32_t addTemp[4] = { 0, 0, 0, 0 };
+#define SHA384_512AddLength(context, length) (                        \
+    addTemp[3] = (length), SHA512_ADDTO4((context)->Length, addTemp), \
+    (context)->Corrupted = (((context)->Length[3] == 0) &&            \
+       ((context)->Length[2] == 0) && ((context)->Length[1] == 0) &&  \
+       ((context)->Length[0] < 8)) ? 1 : 0 )
+
+/* Local Function Prototypes */
+static void SHA384_512Finalize(SHA512Context *context,
+    uint8_t Pad_Byte);
+static void SHA384_512PadMessage(SHA512Context *context,
+    uint8_t Pad_Byte);
+static void SHA384_512ProcessMessageBlock(SHA512Context *context);
+static int SHA384_512Reset(SHA512Context *context, uint32_t H0[]);
+static int SHA384_512ResultN(SHA512Context *context,
+    uint8_t Message_Digest[], int HashSize);
+
+/* Initial Hash Values: FIPS-180-2 sections 5.3.3 and 5.3.4 */
+static uint32_t SHA384_H0[SHA512HashSize / 4] = {
+    0xCBBB9D5D, 0xC1059ED8, 0x629A292A, 0x367CD507, 0x9159015A,
+    0x3070DD17, 0x152FECD8, 0xF70E5939, 0x67332667, 0xFFC00B31,
+    0x8EB44A87, 0x68581511, 0xDB0C2E0D, 0x64F98FA7, 0x47B5481D,
+    0xBEFA4FA4
+};
+
+static uint32_t SHA512_H0[SHA512HashSize / 4] = {
+    0x6A09E667, 0xF3BCC908, 0xBB67AE85, 0x84CAA73B, 0x3C6EF372,
+    0xFE94F82B, 0xA54FF53A, 0x5F1D36F1, 0x510E527F, 0xADE682D1,
+    0x9B05688C, 0x2B3E6C1F, 0x1F83D9AB, 0xFB41BD6B, 0x5BE0CD19,
+    0x137E2179
+};
+
+#else /* !USE_32BIT_ONLY */
+
+/* Define the SHA shift, rotate left and rotate right macro */
+#define SHA512_SHR(bits,word)  (((uint64_t)(word)) >> (bits))
+#define SHA512_ROTR(bits,word) ((((uint64_t)(word)) >> (bits)) | \
+                                (((uint64_t)(word)) << (64-(bits))))
+
+/* Define the SHA SIGMA and sigma macros */
+#define SHA512_SIGMA0(word)   \
+ (SHA512_ROTR(28,word) ^ SHA512_ROTR(34,word) ^ SHA512_ROTR(39,word))
+#define SHA512_SIGMA1(word)   \
+ (SHA512_ROTR(14,word) ^ SHA512_ROTR(18,word) ^ SHA512_ROTR(41,word))
+#define SHA512_sigma0(word)   \
+ (SHA512_ROTR( 1,word) ^ SHA512_ROTR( 8,word) ^ SHA512_SHR( 7,word))
+#define SHA512_sigma1(word)   \
+ (SHA512_ROTR(19,word) ^ SHA512_ROTR(61,word) ^ SHA512_SHR( 6,word))
+
+/*
+* add "length" to the length
+*/
+#define SHA384_512AddLength(context, length)                   \
+   (addTemp = context->Length_Low, context->Corrupted =        \
+    ((context->Length_Low += length) < addTemp) &&             \
+    (++context->Length_High == 0) ? 1 : 0)
+
+/* Local Function Prototypes */
+static void SHA384_512Finalize(SHA512Context *context,
+    uint8_t Pad_Byte);
+static void SHA384_512PadMessage(SHA512Context *context,
+    uint8_t Pad_Byte);
+static void SHA384_512ProcessMessageBlock(SHA512Context *context);
+static int SHA384_512Reset(SHA512Context *context, uint64_t H0[]);
+static int SHA384_512ResultN(SHA512Context *context,
+    uint8_t Message_Digest[], int HashSize);
+
+/* Initial Hash Values: FIPS-180-2 sections 5.3.3 and 5.3.4 */
+static uint64_t SHA384_H0[] = {
+    0xCBBB9D5DC1059ED8ull, 0x629A292A367CD507ull, 0x9159015A3070DD17ull,
+    0x152FECD8F70E5939ull, 0x67332667FFC00B31ull, 0x8EB44A8768581511ull,
+    0xDB0C2E0D64F98FA7ull, 0x47B5481DBEFA4FA4ull
+};
+static uint64_t SHA512_H0[] = {
+    0x6A09E667F3BCC908ull, 0xBB67AE8584CAA73Bull, 0x3C6EF372FE94F82Bull,
+    0xA54FF53A5F1D36F1ull, 0x510E527FADE682D1ull, 0x9B05688C2B3E6C1Full,
+    0x1F83D9ABFB41BD6Bull, 0x5BE0CD19137E2179ull
+};
+
+#endif /* USE_32BIT_ONLY */
+
+/*
+* SHA384Reset
+*
+* Description:
+*   This function will initialize the SHA384Context in preparation
+*   for computing a new SHA384 message digest.
+*
+* Parameters:
+*   context: [in/out]
+*     The context to reset.
+*
+* Returns:
+*   sha Error Code.
+*
+*/
+int SHA384Reset(SHA384Context *context)
+{
+    return SHA384_512Reset(context, SHA384_H0);
+}
+
+/*
+* SHA384Input
+*
+* Description:
+*   This function accepts an array of octets as the next portion
+*   of the message.
+*
+* Parameters:
+*   context: [in/out]
+*     The SHA context to update
+*   message_array: [in]
+*     An array of characters representing the next portion of
+*     the message.
+*   length: [in]
+*     The length of the message in message_array
+*
+* Returns:
+*   sha Error Code.
+*
+*/
+int SHA384Input(SHA384Context *context,
+    const uint8_t *message_array, unsigned int length)
+{
+    return SHA512Input(context, message_array, length);
+}
+
+/*
+* SHA384FinalBits
+*
+* Description:
+*   This function will add in any final bits of the message.
+*
+* Parameters:
+*   context: [in/out]
+*     The SHA context to update
+*   message_bits: [in]
+*     The final bits of the message, in the upper portion of the
+*     byte. (Use 0b###00000 instead of 0b00000### to input the
+*     three bits ###.)
+*   length: [in]
+*     The number of bits in message_bits, between 1 and 7.
+*
+* Returns:
+*   sha Error Code.
+*
+*/
+int SHA384FinalBits(SHA384Context *context,
+    const uint8_t message_bits, unsigned int length)
+{
+    return SHA512FinalBits(context, message_bits, length);
+}
+
+/*
+* SHA384Result
+*
+* Description:
+*   This function will return the 384-bit message
+*   digest into the Message_Digest array provided by the caller.
+*   NOTE: The first octet of hash is stored in the 0th element,
+*      the last octet of hash in the 48th element.
+*
+* Parameters:
+*   context: [in/out]
+*     The context to use to calculate the SHA hash.
+*   Message_Digest: [out]
+*     Where the digest is returned.
+*
+* Returns:
+*   sha Error Code.
+*
+*/
+int SHA384Result(SHA384Context *context,
+    uint8_t Message_Digest[SHA384HashSize])
+{
+    return SHA384_512ResultN(context, Message_Digest, SHA384HashSize);
+}
+
+/*
+* SHA512Reset
+*
+* Description:
+*   This function will initialize the SHA512Context in preparation
+*   for computing a new SHA512 message digest.
+*
+* Parameters:
+*   context: [in/out]
+*     The context to reset.
+*
+* Returns:
+*   sha Error Code.
+*
+*/
+int SHA512Reset(SHA512Context *context)
+{
+    return SHA384_512Reset(context, SHA512_H0);
+}
+
+/*
+* SHA512Input
+*
+* Description:
+*   This function accepts an array of octets as the next portion
+*   of the message.
+*
+* Parameters:
+*   context: [in/out]
+*     The SHA context to update
+*   message_array: [in]
+*     An array of characters representing the next portion of
+*     the message.
+*   length: [in]
+*     The length of the message in message_array
+*
+* Returns:
+*   sha Error Code.
+*
+*/
+int SHA512Input(SHA512Context *context,
+    const uint8_t *message_array,
+    unsigned int length)
+{
+    uint64_t addTemp;
+    if (!length)
+        return shaSuccess;
+
+    if (!context || !message_array)
+        return shaNull;
+
+    if (context->Computed) {
+        context->Corrupted = shaStateError;
+        return shaStateError;
+    }
+
+    if (context->Corrupted)
+        return context->Corrupted;
+
+    while (length-- && !context->Corrupted) {
+        context->Message_Block[context->Message_Block_Index++] =
+            (*message_array & 0xFF);
+
+        if (!SHA384_512AddLength(context, 8) &&
+            (context->Message_Block_Index == SHA512_Message_Block_Size))
+            SHA384_512ProcessMessageBlock(context);
+
+        message_array++;
+    }
+
+    return shaSuccess;
+}
+
+/*
+* SHA512FinalBits
+*
+* Description:
+*   This function will add in any final bits of the message.
+*
+* Parameters:
+*   context: [in/out]
+*     The SHA context to update
+*   message_bits: [in]
+*     The final bits of the message, in the upper portion of the
+*     byte. (Use 0b###00000 instead of 0b00000### to input the
+*     three bits ###.)
+*   length: [in]
+*     The number of bits in message_bits, between 1 and 7.
+*
+* Returns:
+*   sha Error Code.
+*
+*/
+int SHA512FinalBits(SHA512Context *context,
+    const uint8_t message_bits, unsigned int length)
+{
+    uint64_t addTemp;
+    uint8_t masks[8] = {
+        /* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80,
+        /* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0,
+        /* 4 0b11110000 */ 0xF0, /* 5 0b11111000 */ 0xF8,
+        /* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE
+    };
+    uint8_t markbit[8] = {
+        /* 0 0b10000000 */ 0x80, /* 1 0b01000000 */ 0x40,
+        /* 2 0b00100000 */ 0x20, /* 3 0b00010000 */ 0x10,
+        /* 4 0b00001000 */ 0x08, /* 5 0b00000100 */ 0x04,
+        /* 6 0b00000010 */ 0x02, /* 7 0b00000001 */ 0x01
+    };
+
+    if (!length)
+        return shaSuccess;
+
+    if (!context)
+        return shaNull;
+
+    if ((context->Computed) || (length >= 8) || (length == 0)) {
+        context->Corrupted = shaStateError;
+        return shaStateError;
+    }
+
+    if (context->Corrupted)
+        return context->Corrupted;
+
+    SHA384_512AddLength(context, length);
+    SHA384_512Finalize(context, (uint8_t)
+        ((message_bits & masks[length]) | markbit[length]));
+
+    return shaSuccess;
+}
+
+/*
+* SHA384_512Finalize
+*
+* Description:
+*   This helper function finishes off the digest calculations.
+*
+* Parameters:
+*   context: [in/out]
+*     The SHA context to update
+*   Pad_Byte: [in]
+*     The last byte to add to the digest before the 0-padding
+*     and length. This will contain the last bits of the message
+*     followed by another single bit. If the message was an
+*     exact multiple of 8-bits long, Pad_Byte will be 0x80.
+*
+* Returns:
+*   sha Error Code.
+*
+*/
+static void SHA384_512Finalize(SHA512Context *context,
+    uint8_t Pad_Byte)
+{
+    int_least16_t i;
+    SHA384_512PadMessage(context, Pad_Byte);
+    /* message may be sensitive, clear it out */
+    for (i = 0; i < SHA512_Message_Block_Size; ++i)
+        context->Message_Block[i] = 0;
+#ifdef USE_32BIT_ONLY    /* and clear length */
+    context->Length[0] = context->Length[1] = 0;
+    context->Length[2] = context->Length[3] = 0;
+#else /* !USE_32BIT_ONLY */
+    context->Length_Low = 0;
+    context->Length_High = 0;
+#endif /* USE_32BIT_ONLY */
+    context->Computed = 1;
+}
+
+/*
+* SHA512Result
+*
+* Description:
+*   This function will return the 512-bit message
+*   digest into the Message_Digest array provided by the caller.
+*   NOTE: The first octet of hash is stored in the 0th element,
+*      the last octet of hash in the 64th element.
+*
+* Parameters:
+*   context: [in/out]
+*     The context to use to calculate the SHA hash.
+*   Message_Digest: [out]
+*     Where the digest is returned.
+*
+* Returns:
+*   sha Error Code.
+*
+*/
+int SHA512Result(SHA512Context *context,
+    uint8_t Message_Digest[SHA512HashSize])
+{
+    return SHA384_512ResultN(context, Message_Digest, SHA512HashSize);
+}
+
+/*
+* SHA384_512PadMessage
+*
+* Description:
+*   According to the standard, the message must be padded to an
+*   even 1024 bits. The first padding bit must be a '1'. The
+*   last 128 bits represent the length of the original message.
+*   All bits in between should be 0. This helper function will
+*   pad the message according to those rules by filling the
+*   Message_Block array accordingly. When it returns, it can be
+*   assumed that the message digest has been computed.
+*
+* Parameters:
+*   context: [in/out]
+*     The context to pad
+*   Pad_Byte: [in]
+*     The last byte to add to the digest before the 0-padding
+*     and length. This will contain the last bits of the message
+*     followed by another single bit. If the message was an
+*     exact multiple of 8-bits long, Pad_Byte will be 0x80.
+*
+* Returns:
+*   Nothing.
+*
+*/
+static void SHA384_512PadMessage(SHA512Context *context,
+    uint8_t Pad_Byte)
+{
+    /*
+    * Check to see if the current message block is too small to hold
+    * the initial padding bits and length. If so, we will pad the
+    * block, process it, and then continue padding into a second
+    * block.
+    */
+    if (context->Message_Block_Index >= (SHA512_Message_Block_Size - 16)) {
+        context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
+        while (context->Message_Block_Index < SHA512_Message_Block_Size)
+            context->Message_Block[context->Message_Block_Index++] = 0;
+
+        SHA384_512ProcessMessageBlock(context);
+    }
+    else
+        context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
+
+    while (context->Message_Block_Index < (SHA512_Message_Block_Size - 16))
+        context->Message_Block[context->Message_Block_Index++] = 0;
+
+    /*
+    * Store the message length as the last 16 octets
+    */
+#ifdef USE_32BIT_ONLY
+    context->Message_Block[112] = (uint8_t)(context->Length[0] >> 24);
+    context->Message_Block[113] = (uint8_t)(context->Length[0] >> 16);
+    context->Message_Block[114] = (uint8_t)(context->Length[0] >> 8);
+    context->Message_Block[115] = (uint8_t)(context->Length[0]);
+    context->Message_Block[116] = (uint8_t)(context->Length[1] >> 24);
+    context->Message_Block[117] = (uint8_t)(context->Length[1] >> 16);
+    context->Message_Block[118] = (uint8_t)(context->Length[1] >> 8);
+    context->Message_Block[119] = (uint8_t)(context->Length[1]);
+
+    context->Message_Block[120] = (uint8_t)(context->Length[2] >> 24);
+    context->Message_Block[121] = (uint8_t)(context->Length[2] >> 16);
+    context->Message_Block[122] = (uint8_t)(context->Length[2] >> 8);
+    context->Message_Block[123] = (uint8_t)(context->Length[2]);
+    context->Message_Block[124] = (uint8_t)(context->Length[3] >> 24);
+    context->Message_Block[125] = (uint8_t)(context->Length[3] >> 16);
+    context->Message_Block[126] = (uint8_t)(context->Length[3] >> 8);
+    context->Message_Block[127] = (uint8_t)(context->Length[3]);
+#else /* !USE_32BIT_ONLY */
+    context->Message_Block[112] = (uint8_t)(context->Length_High >> 56);
+    context->Message_Block[113] = (uint8_t)(context->Length_High >> 48);
+    context->Message_Block[114] = (uint8_t)(context->Length_High >> 40);
+    context->Message_Block[115] = (uint8_t)(context->Length_High >> 32);
+    context->Message_Block[116] = (uint8_t)(context->Length_High >> 24);
+    context->Message_Block[117] = (uint8_t)(context->Length_High >> 16);
+    context->Message_Block[118] = (uint8_t)(context->Length_High >> 8);
+    context->Message_Block[119] = (uint8_t)(context->Length_High);
+
+    context->Message_Block[120] = (uint8_t)(context->Length_Low >> 56);
+    context->Message_Block[121] = (uint8_t)(context->Length_Low >> 48);
+    context->Message_Block[122] = (uint8_t)(context->Length_Low >> 40);
+    context->Message_Block[123] = (uint8_t)(context->Length_Low >> 32);
+    context->Message_Block[124] = (uint8_t)(context->Length_Low >> 24);
+    context->Message_Block[125] = (uint8_t)(context->Length_Low >> 16);
+    context->Message_Block[126] = (uint8_t)(context->Length_Low >> 8);
+    context->Message_Block[127] = (uint8_t)(context->Length_Low);
+#endif /* USE_32BIT_ONLY */
+
+    SHA384_512ProcessMessageBlock(context);
+}
+
+/*
+* SHA384_512ProcessMessageBlock
+*
+* Description:
+*   This helper function will process the next 1024 bits of the
+*   message stored in the Message_Block array.
+*
+* Parameters:
+*   context: [in/out]
+*     The SHA context to update
+*
+* Returns:
+*   Nothing.
+*
+* Comments:
+*   Many of the variable names in this code, especially the
+*   single character names, were used because those were the
+*   names used in the publication.
+*
+*
+*/
+static void SHA384_512ProcessMessageBlock(SHA512Context *context)
+{
+    /* Constants defined in FIPS-180-2, section 4.2.3 */
+#ifdef USE_32BIT_ONLY
+    static const uint32_t K[80 * 2] = {
+        0x428A2F98, 0xD728AE22, 0x71374491, 0x23EF65CD, 0xB5C0FBCF,
+        0xEC4D3B2F, 0xE9B5DBA5, 0x8189DBBC, 0x3956C25B, 0xF348B538,
+        0x59F111F1, 0xB605D019, 0x923F82A4, 0xAF194F9B, 0xAB1C5ED5,
+        0xDA6D8118, 0xD807AA98, 0xA3030242, 0x12835B01, 0x45706FBE,
+        0x243185BE, 0x4EE4B28C, 0x550C7DC3, 0xD5FFB4E2, 0x72BE5D74,
+        0xF27B896F, 0x80DEB1FE, 0x3B1696B1, 0x9BDC06A7, 0x25C71235,
+        0xC19BF174, 0xCF692694, 0xE49B69C1, 0x9EF14AD2, 0xEFBE4786,
+        0x384F25E3, 0x0FC19DC6, 0x8B8CD5B5, 0x240CA1CC, 0x77AC9C65,
+        0x2DE92C6F, 0x592B0275, 0x4A7484AA, 0x6EA6E483, 0x5CB0A9DC,
+        0xBD41FBD4, 0x76F988DA, 0x831153B5, 0x983E5152, 0xEE66DFAB,
+        0xA831C66D, 0x2DB43210, 0xB00327C8, 0x98FB213F, 0xBF597FC7,
+        0xBEEF0EE4, 0xC6E00BF3, 0x3DA88FC2, 0xD5A79147, 0x930AA725,
+        0x06CA6351, 0xE003826F, 0x14292967, 0x0A0E6E70, 0x27B70A85,
+        0x46D22FFC, 0x2E1B2138, 0x5C26C926, 0x4D2C6DFC, 0x5AC42AED,
+        0x53380D13, 0x9D95B3DF, 0x650A7354, 0x8BAF63DE, 0x766A0ABB,
+        0x3C77B2A8, 0x81C2C92E, 0x47EDAEE6, 0x92722C85, 0x1482353B,
+        0xA2BFE8A1, 0x4CF10364, 0xA81A664B, 0xBC423001, 0xC24B8B70,
+        0xD0F89791, 0xC76C51A3, 0x0654BE30, 0xD192E819, 0xD6EF5218,
+        0xD6990624, 0x5565A910, 0xF40E3585, 0x5771202A, 0x106AA070,
+        0x32BBD1B8, 0x19A4C116, 0xB8D2D0C8, 0x1E376C08, 0x5141AB53,
+        0x2748774C, 0xDF8EEB99, 0x34B0BCB5, 0xE19B48A8, 0x391C0CB3,
+        0xC5C95A63, 0x4ED8AA4A, 0xE3418ACB, 0x5B9CCA4F, 0x7763E373,
+        0x682E6FF3, 0xD6B2B8A3, 0x748F82EE, 0x5DEFB2FC, 0x78A5636F,
+        0x43172F60, 0x84C87814, 0xA1F0AB72, 0x8CC70208, 0x1A6439EC,
+        0x90BEFFFA, 0x23631E28, 0xA4506CEB, 0xDE82BDE9, 0xBEF9A3F7,
+        0xB2C67915, 0xC67178F2, 0xE372532B, 0xCA273ECE, 0xEA26619C,
+        0xD186B8C7, 0x21C0C207, 0xEADA7DD6, 0xCDE0EB1E, 0xF57D4F7F,
+        0xEE6ED178, 0x06F067AA, 0x72176FBA, 0x0A637DC5, 0xA2C898A6,
+        0x113F9804, 0xBEF90DAE, 0x1B710B35, 0x131C471B, 0x28DB77F5,
+        0x23047D84, 0x32CAAB7B, 0x40C72493, 0x3C9EBE0A, 0x15C9BEBC,
+        0x431D67C4, 0x9C100D4C, 0x4CC5D4BE, 0xCB3E42B6, 0x597F299C,
+        0xFC657E2A, 0x5FCB6FAB, 0x3AD6FAEC, 0x6C44198C, 0x4A475817
+    };
+    int     t, t2, t8;                  /* Loop counter */
+    uint32_t  temp1[2], temp2[2],       /* Temporary word values */
+        temp3[2], temp4[2], temp5[2];
+    uint32_t  W[2 * 80];                  /* Word sequence */
+    uint32_t  A[2], B[2], C[2], D[2],   /* Word buffers */
+        E[2], F[2], G[2], H[2];
+
+    /* Initialize the first 16 words in the array W */
+    for (t = t2 = t8 = 0; t < 16; t++, t8 += 8) {
+        W[t2++] = ((((uint32_t)context->Message_Block[t8])) << 24) |
+            ((((uint32_t)context->Message_Block[t8 + 1])) << 16) |
+            ((((uint32_t)context->Message_Block[t8 + 2])) << 8) |
+            ((((uint32_t)context->Message_Block[t8 + 3])));
+        W[t2++] = ((((uint32_t)context->Message_Block[t8 + 4])) << 24) |
+            ((((uint32_t)context->Message_Block[t8 + 5])) << 16) |
+            ((((uint32_t)context->Message_Block[t8 + 6])) << 8) |
+            ((((uint32_t)context->Message_Block[t8 + 7])));
+    }
+
+    for (t = 16; t < 80; t++, t2 += 2) {
+        /* W[t] = SHA512_sigma1(W[t-2]) + W[t-7] +
+        SHA512_sigma0(W[t-15]) + W[t-16]; */
+        uint32_t *Wt2 = &W[t2 - 2 * 2];
+        uint32_t *Wt7 = &W[t2 - 7 * 2];
+        uint32_t *Wt15 = &W[t2 - 15 * 2];
+        uint32_t *Wt16 = &W[t2 - 16 * 2];
+        SHA512_sigma1(Wt2, temp1);
+        SHA512_ADD(temp1, Wt7, temp2);
+        SHA512_sigma0(Wt15, temp1);
+        SHA512_ADD(temp1, Wt16, temp3);
+        SHA512_ADD(temp2, temp3, &W[t2]);
+    }
+
+    A[0] = context->Intermediate_Hash[0];
+    A[1] = context->Intermediate_Hash[1];
+    B[0] = context->Intermediate_Hash[2];
+    B[1] = context->Intermediate_Hash[3];
+    C[0] = context->Intermediate_Hash[4];
+    C[1] = context->Intermediate_Hash[5];
+    D[0] = context->Intermediate_Hash[6];
+    D[1] = context->Intermediate_Hash[7];
+    E[0] = context->Intermediate_Hash[8];
+    E[1] = context->Intermediate_Hash[9];
+    F[0] = context->Intermediate_Hash[10];
+    F[1] = context->Intermediate_Hash[11];
+    G[0] = context->Intermediate_Hash[12];
+    G[1] = context->Intermediate_Hash[13];
+    H[0] = context->Intermediate_Hash[14];
+    H[1] = context->Intermediate_Hash[15];
+
+    for (t = t2 = 0; t < 80; t++, t2 += 2) {
+        /*
+        * temp1 = H + SHA512_SIGMA1(E) + SHA_Ch(E,F,G) + K[t] + W[t];
+        */
+        SHA512_SIGMA1(E, temp1);
+        SHA512_ADD(H, temp1, temp2);
+        SHA_Ch(E, F, G, temp3);
+        SHA512_ADD(temp2, temp3, temp4);
+        SHA512_ADD(&K[t2], &W[t2], temp5);
+        SHA512_ADD(temp4, temp5, temp1);
+        /*
+        * temp2 = SHA512_SIGMA0(A) + SHA_Maj(A,B,C);
+        */
+        SHA512_SIGMA0(A, temp3);
+        SHA_Maj(A, B, C, temp4);
+        SHA512_ADD(temp3, temp4, temp2);
+        H[0] = G[0]; H[1] = G[1];
+        G[0] = F[0]; G[1] = F[1];
+        F[0] = E[0]; F[1] = E[1];
+        SHA512_ADD(D, temp1, E);
+        D[0] = C[0]; D[1] = C[1];
+        C[0] = B[0]; C[1] = B[1];
+        B[0] = A[0]; B[1] = A[1];
+        SHA512_ADD(temp1, temp2, A);
+    }
+
+    SHA512_ADDTO2(&context->Intermediate_Hash[0], A);
+    SHA512_ADDTO2(&context->Intermediate_Hash[2], B);
+    SHA512_ADDTO2(&context->Intermediate_Hash[4], C);
+    SHA512_ADDTO2(&context->Intermediate_Hash[6], D);
+    SHA512_ADDTO2(&context->Intermediate_Hash[8], E);
+    SHA512_ADDTO2(&context->Intermediate_Hash[10], F);
+    SHA512_ADDTO2(&context->Intermediate_Hash[12], G);
+    SHA512_ADDTO2(&context->Intermediate_Hash[14], H);
+
+#else /* !USE_32BIT_ONLY */
+    static const uint64_t K[80] = {
+        0x428A2F98D728AE22ull, 0x7137449123EF65CDull, 0xB5C0FBCFEC4D3B2Full,
+        0xE9B5DBA58189DBBCull, 0x3956C25BF348B538ull, 0x59F111F1B605D019ull,
+        0x923F82A4AF194F9Bull, 0xAB1C5ED5DA6D8118ull, 0xD807AA98A3030242ull,
+        0x12835B0145706FBEull, 0x243185BE4EE4B28Cull, 0x550C7DC3D5FFB4E2ull,
+        0x72BE5D74F27B896Full, 0x80DEB1FE3B1696B1ull, 0x9BDC06A725C71235ull,
+        0xC19BF174CF692694ull, 0xE49B69C19EF14AD2ull, 0xEFBE4786384F25E3ull,
+        0x0FC19DC68B8CD5B5ull, 0x240CA1CC77AC9C65ull, 0x2DE92C6F592B0275ull,
+        0x4A7484AA6EA6E483ull, 0x5CB0A9DCBD41FBD4ull, 0x76F988DA831153B5ull,
+        0x983E5152EE66DFABull, 0xA831C66D2DB43210ull, 0xB00327C898FB213Full,
+        0xBF597FC7BEEF0EE4ull, 0xC6E00BF33DA88FC2ull, 0xD5A79147930AA725ull,
+        0x06CA6351E003826Full, 0x142929670A0E6E70ull, 0x27B70A8546D22FFCull,
+        0x2E1B21385C26C926ull, 0x4D2C6DFC5AC42AEDull, 0x53380D139D95B3DFull,
+        0x650A73548BAF63DEull, 0x766A0ABB3C77B2A8ull, 0x81C2C92E47EDAEE6ull,
+        0x92722C851482353Bull, 0xA2BFE8A14CF10364ull, 0xA81A664BBC423001ull,
+        0xC24B8B70D0F89791ull, 0xC76C51A30654BE30ull, 0xD192E819D6EF5218ull,
+        0xD69906245565A910ull, 0xF40E35855771202Aull, 0x106AA07032BBD1B8ull,
+        0x19A4C116B8D2D0C8ull, 0x1E376C085141AB53ull, 0x2748774CDF8EEB99ull,
+        0x34B0BCB5E19B48A8ull, 0x391C0CB3C5C95A63ull, 0x4ED8AA4AE3418ACBull,
+        0x5B9CCA4F7763E373ull, 0x682E6FF3D6B2B8A3ull, 0x748F82EE5DEFB2FCull,
+        0x78A5636F43172F60ull, 0x84C87814A1F0AB72ull, 0x8CC702081A6439ECull,
+        0x90BEFFFA23631E28ull, 0xA4506CEBDE82BDE9ull, 0xBEF9A3F7B2C67915ull,
+        0xC67178F2E372532Bull, 0xCA273ECEEA26619Cull, 0xD186B8C721C0C207ull,
+        0xEADA7DD6CDE0EB1Eull, 0xF57D4F7FEE6ED178ull, 0x06F067AA72176FBAull,
+        0x0A637DC5A2C898A6ull, 0x113F9804BEF90DAEull, 0x1B710B35131C471Bull,
+        0x28DB77F523047D84ull, 0x32CAAB7B40C72493ull, 0x3C9EBE0A15C9BEBCull,
+        0x431D67C49C100D4Cull, 0x4CC5D4BECB3E42B6ull, 0x597F299CFC657E2Aull,
+        0x5FCB6FAB3AD6FAECull, 0x6C44198C4A475817ull
+    };
+    int        t, t8;                   /* Loop counter */
+    uint64_t   temp1, temp2;            /* Temporary word value */
+    uint64_t   W[80];                   /* Word sequence */
+    uint64_t   A, B, C, D, E, F, G, H;  /* Word buffers */
+
+    /*
+    * Initialize the first 16 words in the array W
+    */
+    for (t = t8 = 0; t < 16; t++, t8 += 8)
+        W[t] = ((uint64_t)(context->Message_Block[t8]) << 56) |
+        ((uint64_t)(context->Message_Block[t8 + 1]) << 48) |
+        ((uint64_t)(context->Message_Block[t8 + 2]) << 40) |
+        ((uint64_t)(context->Message_Block[t8 + 3]) << 32) |
+        ((uint64_t)(context->Message_Block[t8 + 4]) << 24) |
+        ((uint64_t)(context->Message_Block[t8 + 5]) << 16) |
+        ((uint64_t)(context->Message_Block[t8 + 6]) << 8) |
+        ((uint64_t)(context->Message_Block[t8 + 7]));
+
+    for (t = 16; t < 80; t++)
+        W[t] = SHA512_sigma1(W[t - 2]) + W[t - 7] +
+        SHA512_sigma0(W[t - 15]) + W[t - 16];
+
+    A = context->Intermediate_Hash[0];
+    B = context->Intermediate_Hash[1];
+    C = context->Intermediate_Hash[2];
+    D = context->Intermediate_Hash[3];
+    E = context->Intermediate_Hash[4];
+    F = context->Intermediate_Hash[5];
+    G = context->Intermediate_Hash[6];
+    H = context->Intermediate_Hash[7];
+
+    for (t = 0; t < 80; t++) {
+        temp1 = H + SHA512_SIGMA1(E) + SHA_Ch(E, F, G) + K[t] + W[t];
+        temp2 = SHA512_SIGMA0(A) + SHA_Maj(A, B, C);
+        H = G;
+        G = F;
+        F = E;
+        E = D + temp1;
+        D = C;
+        C = B;
+        B = A;
+        A = temp1 + temp2;
+    }
+
+    context->Intermediate_Hash[0] += A;
+    context->Intermediate_Hash[1] += B;
+    context->Intermediate_Hash[2] += C;
+    context->Intermediate_Hash[3] += D;
+    context->Intermediate_Hash[4] += E;
+    context->Intermediate_Hash[5] += F;
+    context->Intermediate_Hash[6] += G;
+    context->Intermediate_Hash[7] += H;
+#endif /* USE_32BIT_ONLY */
+
+    context->Message_Block_Index = 0;
+}
+
+/*
+* SHA384_512Reset
+*
+* Description:
+*   This helper function will initialize the SHA512Context in
+*   preparation for computing a new SHA384 or SHA512 message
+*   digest.
+*
+* Parameters:
+*   context: [in/out]
+*     The context to reset.
+*   H0
+*     The initial hash value to use.
+*
+* Returns:
+*   sha Error Code.
+*
+*/
+#ifdef USE_32BIT_ONLY
+static int SHA384_512Reset(SHA512Context *context, uint32_t H0[])
+#else /* !USE_32BIT_ONLY */
+static int SHA384_512Reset(SHA512Context *context, uint64_t H0[])
+#endif /* USE_32BIT_ONLY */
+{
+    int i;
+    if (!context)
+        return shaNull;
+
+    context->Message_Block_Index = 0;
+
+#ifdef USE_32BIT_ONLY
+    context->Length[0] = context->Length[1] = 0;
+    context->Length[2] = context->Length[3] = 0;
+
+    for (i = 0; i < SHA512HashSize / 4; i++)
+        context->Intermediate_Hash[i] = H0[i];
+#else /* !USE_32BIT_ONLY */
+    context->Length_High = context->Length_Low = 0;
+
+    for (i = 0; i < SHA512HashSize / 8; i++)
+        context->Intermediate_Hash[i] = H0[i];
+#endif /* USE_32BIT_ONLY */
+
+    context->Computed = 0;
+    context->Corrupted = 0;
+
+    return shaSuccess;
+}
+
+/*
+* SHA384_512ResultN
+*
+* Description:
+*   This helper function will return the 384-bit or 512-bit message
+*   digest into the Message_Digest array provided by the caller.
+*   NOTE: The first octet of hash is stored in the 0th element,
+*      the last octet of hash in the 48th/64th element.
+*
+* Parameters:
+*   context: [in/out]
+*     The context to use to calculate the SHA hash.
+*   Message_Digest: [out]
+*     Where the digest is returned.
+*   HashSize: [in]
+*     The size of the hash, either 48 or 64.
+*
+* Returns:
+*   sha Error Code.
+*
+*/
+static int SHA384_512ResultN(SHA512Context *context,
+    uint8_t Message_Digest[], int HashSize)
+{
+    int i;
+
+#ifdef USE_32BIT_ONLY
+    int i2;
+#endif /* USE_32BIT_ONLY */
+
+    if (!context || !Message_Digest)
+        return shaNull;
+
+    if (context->Corrupted)
+        return context->Corrupted;
+
+    if (!context->Computed)
+        SHA384_512Finalize(context, 0x80);
+
+#ifdef USE_32BIT_ONLY
+    for (i = i2 = 0; i < HashSize;) {
+        Message_Digest[i++] = (uint8_t)(context->Intermediate_Hash[i2] >> 24);
+        Message_Digest[i++] = (uint8_t)(context->Intermediate_Hash[i2] >> 16);
+        Message_Digest[i++] = (uint8_t)(context->Intermediate_Hash[i2] >> 8);
+        Message_Digest[i++] = (uint8_t)(context->Intermediate_Hash[i2++]);
+        Message_Digest[i++] = (uint8_t)(context->Intermediate_Hash[i2] >> 24);
+        Message_Digest[i++] = (uint8_t)(context->Intermediate_Hash[i2] >> 16);
+        Message_Digest[i++] = (uint8_t)(context->Intermediate_Hash[i2] >> 8);
+        Message_Digest[i++] = (uint8_t)(context->Intermediate_Hash[i2++]);
+    }
+#else /* !USE_32BIT_ONLY */
+    for (i = 0; i < HashSize; ++i)
+        Message_Digest[i] = (uint8_t)
+        (context->Intermediate_Hash[i >> 3] >> 8 * (7 - (i % 8)));
+#endif /* USE_32BIT_ONLY */
+
+    return shaSuccess;
+}
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/singlylinkedlist.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/singlylinkedlist.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/singlylinkedlist.c	(revision 453)
@@ -0,0 +1,409 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/singlylinkedlist.h"
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/xlogging.h"
+
+typedef struct LIST_ITEM_INSTANCE_TAG
+{
+    const void* item;
+    void* next;
+} LIST_ITEM_INSTANCE;
+
+typedef struct SINGLYLINKEDLIST_INSTANCE_TAG
+{
+    LIST_ITEM_INSTANCE* head;
+    LIST_ITEM_INSTANCE* tail;
+} LIST_INSTANCE;
+
+SINGLYLINKEDLIST_HANDLE singlylinkedlist_create(void)
+{
+    LIST_INSTANCE* result;
+
+    /* Codes_SRS_LIST_01_001: [singlylinkedlist_create shall create a new list and return a non-NULL handle on success.] */
+    result = (LIST_INSTANCE*)malloc(sizeof(LIST_INSTANCE));
+    if (result != NULL)
+    {
+        /* Codes_SRS_LIST_01_002: [If any error occurs during the list creation, singlylinkedlist_create shall return NULL.] */
+        result->head = NULL;
+        result->tail = NULL;
+    }
+
+    return result;
+}
+
+void singlylinkedlist_destroy(SINGLYLINKEDLIST_HANDLE list)
+{
+    /* Codes_SRS_LIST_01_004: [If the list argument is NULL, no freeing of resources shall occur.] */
+    if (list != NULL)
+    {
+        LIST_INSTANCE* list_instance = (LIST_INSTANCE*)list;
+
+        while (list_instance->head != NULL)
+        {
+            LIST_ITEM_INSTANCE* current_item = list_instance->head;
+            list_instance->head = (LIST_ITEM_INSTANCE*)current_item->next;
+            free(current_item);
+        }
+
+        /* Codes_SRS_LIST_01_003: [singlylinkedlist_destroy shall free all resources associated with the list identified by the handle argument.] */
+        free(list_instance);
+    }
+}
+
+LIST_ITEM_HANDLE singlylinkedlist_add(SINGLYLINKEDLIST_HANDLE list, const void* item)
+{
+    LIST_ITEM_INSTANCE* result;
+
+    /* Codes_SRS_LIST_01_006: [If any of the arguments is NULL, singlylinkedlist_add shall not add the item to the list and return NULL.] */
+    if ((list == NULL) ||
+        (item == NULL))
+    {
+        LogError("Invalid argument (list=%p, item=%p)", list, item);
+        result = NULL;
+    }
+    else
+    {
+        LIST_INSTANCE* list_instance = (LIST_INSTANCE*)list;
+        result = (LIST_ITEM_INSTANCE*)malloc(sizeof(LIST_ITEM_INSTANCE));
+
+        if (result == NULL)
+        {
+            /* Codes_SRS_LIST_01_007: [If allocating the new list node fails, singlylinkedlist_add shall return NULL.] */
+            /*return as is*/
+        }
+        else
+        {
+            /* Codes_SRS_LIST_01_005: [singlylinkedlist_add shall add one item to the tail of the list and on success it shall return a handle to the added item.] */
+            result->next = NULL;
+            result->item = item;
+
+            if (list_instance->head == NULL)
+            {
+                list_instance->head = result;
+                list_instance->tail = result;
+            }
+            else
+            {
+                list_instance->tail->next = result;
+                list_instance->tail = result;
+            }
+        }
+    }
+
+    return result;
+}
+
+int singlylinkedlist_remove(SINGLYLINKEDLIST_HANDLE list, LIST_ITEM_HANDLE item)
+{
+    int result;
+
+    /* Codes_SRS_LIST_01_024: [If any of the arguments list or item_handle is NULL, singlylinkedlist_remove shall fail and return a non-zero value.] */
+    if ((list == NULL) ||
+        (item == NULL))
+    {
+        LogError("Invalid argument (list=%p, item=%p)", list, item);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        LIST_INSTANCE* list_instance = (LIST_INSTANCE*)list;
+        LIST_ITEM_INSTANCE* current_item = list_instance->head;
+        LIST_ITEM_INSTANCE* previous_item = NULL;
+
+        while (current_item != NULL)
+        {
+            if (current_item == item)
+            {
+                if (previous_item != NULL)
+                {
+                    previous_item->next = current_item->next;
+                }
+                else
+                {
+                    list_instance->head = (LIST_ITEM_INSTANCE*)current_item->next;
+                }
+
+                if (current_item == list_instance->tail)
+                {
+                    list_instance->tail = previous_item;
+                }
+
+                free(current_item);
+
+                break;
+            }
+
+            previous_item = current_item;
+            current_item = (LIST_ITEM_INSTANCE*)current_item->next;
+        }
+
+        if (current_item == NULL)
+        {
+            /* Codes_SRS_LIST_01_025: [If the item item_handle is not found in the list, then singlylinkedlist_remove shall fail and return a non-zero value.] */
+            result = MU_FAILURE;
+        }
+        else
+        {
+            /* Codes_SRS_LIST_01_023: [singlylinkedlist_remove shall remove a list item from the list and on success it shall return 0.] */
+            result = 0;
+        }
+    }
+
+    return result;
+}
+
+LIST_ITEM_HANDLE singlylinkedlist_get_head_item(SINGLYLINKEDLIST_HANDLE list)
+{
+    LIST_ITEM_HANDLE result;
+
+    if (list == NULL)
+    {
+        /* Codes_SRS_LIST_01_009: [If the list argument is NULL, singlylinkedlist_get_head_item shall return NULL.] */
+        LogError("Invalid argument (list=NULL)");
+        result = NULL;
+    }
+    else
+    {
+        LIST_INSTANCE* list_instance = (LIST_INSTANCE*)list;
+
+        /* Codes_SRS_LIST_01_008: [singlylinkedlist_get_head_item shall return the head of the list.] */
+        /* Codes_SRS_LIST_01_010: [If the list is empty, singlylinkedlist_get_head_item_shall_return NULL.] */
+        result = list_instance->head;
+    }
+
+    return result;
+}
+
+LIST_ITEM_HANDLE singlylinkedlist_get_next_item(LIST_ITEM_HANDLE item_handle)
+{
+    LIST_ITEM_HANDLE result;
+
+    if (item_handle == NULL)
+    {
+        LogError("Invalid argument (list is NULL)");
+        /* Codes_SRS_LIST_01_019: [If item_handle is NULL then singlylinkedlist_get_next_item shall return NULL.] */
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_LIST_01_018: [singlylinkedlist_get_next_item shall return the next item in the list following the item item_handle.] */
+        result = (LIST_ITEM_HANDLE)((LIST_ITEM_INSTANCE*)item_handle)->next;
+    }
+
+    return result;
+}
+
+const void* singlylinkedlist_item_get_value(LIST_ITEM_HANDLE item_handle)
+{
+    const void* result;
+
+    if (item_handle == NULL)
+    {
+        LogError("Invalid argument (item_handle is NULL)");
+        /* Codes_SRS_LIST_01_021: [If item_handle is NULL, singlylinkedlist_item_get_value shall return NULL.] */
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_LIST_01_020: [singlylinkedlist_item_get_value shall return the value associated with the list item identified by the item_handle argument.] */
+        result = ((LIST_ITEM_INSTANCE*)item_handle)->item;
+    }
+
+    return result;
+}
+
+LIST_ITEM_HANDLE singlylinkedlist_find(SINGLYLINKEDLIST_HANDLE list, LIST_MATCH_FUNCTION match_function, const void* match_context)
+{
+    LIST_ITEM_HANDLE result;
+
+    if ((list == NULL) ||
+        (match_function == NULL))
+    {
+        LogError("Invalid argument (list=%p, match_function=%p)", list, match_function);
+        /* Codes_SRS_LIST_01_012: [If the list or the match_function argument is NULL, singlylinkedlist_find shall return NULL.] */
+        result = NULL;
+    }
+    else
+    {
+        LIST_INSTANCE* list_instance = (LIST_INSTANCE*)list;
+        LIST_ITEM_INSTANCE* current = list_instance->head;
+
+        /* Codes_SRS_LIST_01_011: [singlylinkedlist_find shall iterate through all items in a list and return the first one that satisfies a certain match function.] */
+        while (current != NULL)
+        {
+            /* Codes_SRS_LIST_01_014: [list find shall determine whether an item satisfies the match criteria by invoking the match function for each item in the list until a matching item is found.] */
+            /* Codes_SRS_LIST_01_013: [The match_function shall get as arguments the list item being attempted to be matched and the match_context as is.] */
+            if (match_function((LIST_ITEM_HANDLE)current, match_context) == true)
+            {
+                /* Codes_SRS_LIST_01_017: [If the match function returns true, singlylinkedlist_find shall consider that item as matching.] */
+                break;
+            }
+
+            /* Codes_SRS_LIST_01_016: [If the match function returns false, singlylinkedlist_find shall consider that item as not matching.] */
+            current = (LIST_ITEM_INSTANCE*)current->next;
+        }
+
+        if (current == NULL)
+        {
+            /* Codes_SRS_LIST_01_015: [If the list is empty, singlylinkedlist_find shall return NULL.] */
+            result = NULL;
+        }
+        else
+        {
+            result = current;
+        }
+    }
+
+    return result;
+}
+
+int singlylinkedlist_remove_if(SINGLYLINKEDLIST_HANDLE list, LIST_CONDITION_FUNCTION condition_function, const void* match_context)
+{
+    int result;
+    /* Codes_SRS_LIST_09_001: [ If the list or the condition_function argument is NULL, singlylinkedlist_remove_if shall return non-zero value. ] */
+    if ((list == NULL) ||
+        (condition_function == NULL))
+    {
+        LogError("Invalid argument (list=%p, condition_function=%p)", list, condition_function);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        LIST_INSTANCE* list_instance = (LIST_INSTANCE*)list;
+        LIST_ITEM_INSTANCE* current_item = list_instance->head;
+        LIST_ITEM_INSTANCE* next_item = NULL;
+        LIST_ITEM_INSTANCE* previous_item = NULL;
+
+        /* Codes_SRS_LIST_09_002: [ singlylinkedlist_remove_if shall iterate through all items in a list and remove all that satisfies a certain condition function. ] */
+        while (current_item != NULL)
+        {
+            bool continue_processing = false;
+
+            next_item = (LIST_ITEM_INSTANCE*)current_item->next;
+
+            /* Codes_SRS_LIST_09_003: [ singlylinkedlist_remove_if shall determine whether an item satisfies the condition criteria by invoking the condition function for that item. ] */
+            /* Codes_SRS_LIST_09_004: [ If the condition function returns true, singlylinkedlist_find shall consider that item as to be removed. ] */
+            if (condition_function(current_item->item, match_context, &continue_processing) == true)
+            {
+                if (previous_item != NULL)
+                {
+                    previous_item->next = next_item;
+                }
+                else
+                {
+                    list_instance->head = next_item;
+                }
+
+                if (current_item == list_instance->tail)
+                {
+                    list_instance->tail = previous_item;
+                }
+
+                free(current_item);
+            }
+            /* Codes_SRS_LIST_09_005: [ If the condition function returns false, singlylinkedlist_find shall consider that item as not to be removed. ] */
+            else
+            {
+                previous_item = current_item;
+            }
+
+            /* Codes_SRS_LIST_09_006: [ If the condition function returns continue_processing as false, singlylinkedlist_remove_if shall stop iterating through the list and return. ] */
+            if (continue_processing == false)
+            {
+                break;
+            }
+
+            current_item = next_item;
+        }
+
+        /* Codes_SRS_LIST_09_007: [ If no errors occur, singlylinkedlist_remove_if shall return zero. ] */
+        result = 0;
+    }
+
+    return result;
+}
+
+int singlylinkedlist_foreach(SINGLYLINKEDLIST_HANDLE list, LIST_ACTION_FUNCTION action_function, const void* action_context)
+{
+    int result;
+
+    /* Codes_SRS_LIST_09_008: [ If the list or the action_function argument is NULL, singlylinkedlist_foreach shall return non-zero value. ] */
+    if ((list == NULL) ||
+        (action_function == NULL))
+    {
+        LogError("Invalid argument (list=%p, action_function=%p)", list, action_function);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        LIST_INSTANCE* list_instance = (LIST_INSTANCE*)list;
+        LIST_ITEM_INSTANCE* list_item = list_instance->head;
+
+        while (list_item != NULL)
+        {
+            bool continue_processing = false;
+
+            /* Codes_SRS_LIST_09_009: [ singlylinkedlist_foreach shall iterate through all items in a list and invoke action_function for each one of them. ] */
+            action_function(list_item->item, action_context, &continue_processing);
+
+            /* Codes_SRS_LIST_09_010: [ If the condition function returns continue_processing as false, singlylinkedlist_foreach shall stop iterating through the list and return. ] */
+            if (continue_processing == false)
+            {
+                break;
+            }
+
+            list_item = (LIST_ITEM_INSTANCE*)list_item->next;
+        }
+
+        /* Codes_SRS_LIST_09_011: [ If no errors occur, singlylinkedlist_foreach shall return zero. ] */
+        result = 0;
+    }
+
+    return result;
+}
+
+LIST_ITEM_HANDLE singlylinkedlist_add_head(SINGLYLINKEDLIST_HANDLE list, const void* item)
+{
+    LIST_ITEM_HANDLE result;
+
+    /* Codes_SRS_LIST_02_001: [ If list is NULL then singlylinkedlist_add_head shall fail and return NULL. ]*/
+    if (list == NULL)
+    {
+        LogError("Invalid argument SINGLYLINKEDLIST_HANDLE list=%p", list);
+        result = NULL;
+    }
+    else
+    {
+        result = malloc(sizeof(LIST_ITEM_INSTANCE));
+
+        if (result == NULL)
+        {
+            /*Codes_SRS_LIST_02_003: [ If there are any failures then singlylinkedlist_add_head shall fail and return NULL. ]*/
+            LogError("failure in malloc");
+            /*return as is*/
+        }
+        else
+        {
+            /*Codes_SRS_LIST_02_002: [ singlylinkedlist_add_head shall insert item at head, succeed and return a non-NULL value. ]*/
+            result->item = item;
+            if (list->head == NULL)
+            {
+                result->next = NULL;
+                list->head = result;
+                list->tail = result;
+                
+            }
+            else
+            {
+                result->next = list->head;
+                list->head = result;
+            }
+        }
+    }
+
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/string_token.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/string_token.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/string_token.c	(revision 453)
@@ -0,0 +1,390 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/string_token.h"
+
+typedef struct STRING_TOKEN_TAG
+{
+    const char* source;
+    size_t length;
+
+    const char* token_start;
+    const char* delimiter_start;
+    const char* delimiter;
+} STRING_TOKEN;
+
+static size_t* get_delimiters_lengths(const char** delimiters, size_t n_delims)
+{
+    size_t* result;
+
+    if ((result = malloc(sizeof(size_t) * n_delims)) == NULL)
+    {
+        LogError("Failed to allocate array for delimiters lengths");
+    }
+    else
+    {
+        size_t i;
+        for (i = 0; i < n_delims; i++)
+        {
+            if (delimiters[i] == NULL)
+            {
+                // Codes_SRS_STRING_TOKENIZER_09_002: [ If any of the strings in delimiters are NULL, the function shall return NULL ]
+                LogError("Invalid argument (delimiter %lu is NULL)", (unsigned long)i);
+                free(result);
+                result = NULL;
+                break;
+            }
+            else
+            {
+                result[i] = strlen(delimiters[i]);
+            }
+        }
+    }
+
+    return result;
+}
+
+static int get_next_token(STRING_TOKEN* token, const char** delimiters, size_t n_delims)
+{
+    int result;
+
+    if (token->token_start != NULL && token->delimiter_start == NULL)
+    {
+        // The parser reached the end of the input string.
+        result = MU_FAILURE;
+    }
+    else
+    {
+        size_t* delimiters_lengths;
+
+        if ((delimiters_lengths = get_delimiters_lengths(delimiters, n_delims)) == NULL)
+        {
+            LogError("Failed to get delimiters lengths");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            const char* new_token_start;
+            const char* current_pos;
+            const char* stop_pos = (char*)token->source + token->length;
+            size_t j; // iterator for the delimiters.
+
+            if (token->delimiter_start == NULL)
+            {
+                // Codes_SRS_STRING_TOKENIZER_09_005: [ The source string shall be split in a token starting from the beginning of source up to occurrence of any one of the demiliters, whichever occurs first in the order provided ]
+                new_token_start = (char*)token->source;
+            }
+            else
+            {
+                // Codes_SRS_STRING_TOKENIZER_09_010: [ The next token shall be selected starting from the position in source right after the previous delimiter up to occurrence of any one of demiliters, whichever occurs first in the order provided ]
+                new_token_start = token->delimiter_start + strlen(token->delimiter);
+            }
+
+            current_pos = new_token_start;
+            result = 0;
+
+            while (current_pos < stop_pos)
+            {
+                for (j = 0; j < n_delims; j++)
+                {
+                    if (*current_pos == *delimiters[j])
+                    {
+                        size_t k;
+                        for (k = 1; k < delimiters_lengths[j] && (current_pos + k) < stop_pos; k++)
+                        {
+                            if (*(current_pos + k) != *(delimiters[j] + k))
+                            {
+                                break;
+                            }
+                        }
+
+                        if (k == delimiters_lengths[j])
+                        {
+                            token->delimiter_start = current_pos;
+                            token->delimiter = delimiters[j];
+
+                            if (token->delimiter_start == token->source)
+                            {
+                                // Delimiter occurs in the beginning of the source string.
+                                token->token_start = NULL;
+                            }
+                            else
+                            {
+                                token->token_start = new_token_start;
+                            }
+                            goto SCAN_COMPLETED;
+                        }
+                    }
+                }
+
+                current_pos++;
+            }
+
+            // Codes_SRS_STRING_TOKENIZER_09_006: [ If the source string does not have any of the demiliters, the resulting token shall be the entire source string ]
+            // Codes_SRS_STRING_TOKENIZER_09_011: [ If the source string, starting right after the position of the last delimiter found, does not have any of the demiliters, the resulting token shall be the entire remaining of the source string ]
+            if (current_pos == stop_pos)
+            {
+                token->token_start = new_token_start;
+                token->delimiter_start = NULL;
+                // Codes_SRS_STRING_TOKENIZER_09_019: [ If the current token extends to the end of source, the function shall return NULL ]
+                token->delimiter = NULL;
+            }
+
+SCAN_COMPLETED:
+            free(delimiters_lengths);
+        }
+    }
+
+    return result;
+}
+
+STRING_TOKEN_HANDLE StringToken_GetFirst(const char* source, size_t length, const char** delimiters, size_t n_delims)
+{
+    STRING_TOKEN* result;
+
+    // Codes_SRS_STRING_TOKENIZER_09_001: [ If source or delimiters are NULL, or n_delims is zero, the function shall return NULL ]
+    if (source == NULL || delimiters == NULL || n_delims == 0)
+    {
+        LogError("Invalid argument (source=%p, delimiters=%p, n_delims=%lu)", source, delimiters, (unsigned long)n_delims);
+        result = NULL;
+    }
+    else
+    {
+        // Codes_SRS_STRING_TOKENIZER_09_003: [ A STRING_TOKEN structure shall be allocated to hold the token parameters ]
+        if ((result = (STRING_TOKEN*)malloc(sizeof(STRING_TOKEN))) == NULL)
+        {
+            // Codes_SRS_STRING_TOKENIZER_09_004: [ If the STRING_TOKEN structure fails to be allocated, the function shall return NULL ]
+            LogError("Failed allocating STRING_TOKEN");
+        }
+        else
+        {
+            (void)memset(result, 0, sizeof(STRING_TOKEN));
+            result->source = source;
+            result->length = length;
+
+            if (get_next_token(result, delimiters, n_delims) != 0)
+            {
+                LogError("Failed to get first token");
+                // Codes_SRS_STRING_TOKENIZER_09_007: [ If any failure occurs, all memory allocated by this function shall be released ]
+                free(result);
+                result = NULL;
+            }
+        }
+    }
+
+    return result;
+}
+
+bool StringToken_GetNext(STRING_TOKEN_HANDLE token, const char** delimiters, size_t n_delims)
+{
+    bool result;
+
+    // Codes_SRS_STRING_TOKENIZER_09_008: [ If token or delimiters are NULL, or n_delims is zero, the function shall return false ]
+    if (token == NULL || delimiters == NULL || n_delims == 0)
+    {
+        LogError("Invalid argument (token=%p, delimiters=%p, n_delims=%lu)", token, delimiters, (unsigned long)n_delims);
+        result = false;
+    }
+    else if (get_next_token(token, delimiters, n_delims) != 0)
+    {
+        // Codes_SRS_STRING_TOKENIZER_09_009: [ If the previous token already extended to the end of source, the function shall return false ]
+        result = false;
+    }
+    else
+    {
+        // Codes_SRS_STRING_TOKENIZER_09_012: [ If a token was identified, the function shall return true ]
+        result = true;
+    }
+
+    return result;
+}
+
+const char* StringToken_GetValue(STRING_TOKEN_HANDLE token)
+{
+    const char* result;
+
+    // Codes_SRS_STRING_TOKENIZER_09_013: [ If token is NULL the function shall return NULL ]
+    if (token == NULL)
+    {
+        LogError("Invalig argument (token is NULL)");
+        result = NULL;
+    }
+    // Beyond the length of the source string.
+    else if (token->token_start == (token->source + token->length))
+    {
+        result = NULL;
+    }
+    // Two delimiters side by side (empty token).
+    else if (token->token_start == token->delimiter_start)
+    {
+        result = NULL;
+    }
+    else
+    {
+        // Codes_SRS_STRING_TOKENIZER_09_014: [ The function shall return the pointer to the position in source where the current token starts. ]
+        result = token->token_start;
+    }
+
+    return result;
+}
+
+size_t StringToken_GetLength(STRING_TOKEN_HANDLE token)
+{
+    size_t result;
+
+    // Codes_SRS_STRING_TOKENIZER_09_015: [ If token is NULL the function shall return zero ]
+    if (token == NULL)
+    {
+        LogError("Invalig argument (token is NULL)");
+        result = 0;
+    }
+    // Codes_SRS_STRING_TOKENIZER_09_016: [ The function shall return the length of the current token ]
+    else if (token->token_start == NULL)
+    {
+        result = 0;
+    }
+    else if (token->delimiter_start == NULL)
+    {
+        result = token->source + token->length - token->token_start;
+    }
+    else
+    {
+        result = token->delimiter_start - token->token_start;
+    }
+
+    return result;
+}
+
+const char* StringToken_GetDelimiter(STRING_TOKEN_HANDLE token)
+{
+    const char* result;
+
+    if (token == NULL)
+    {
+        // Codes_SRS_STRING_TOKENIZER_09_017: [ If token is NULL the function shall return NULL ]
+        LogError("Invalig argument (token is NULL)");
+        result = NULL;
+    }
+    else
+    {
+        // Codes_SRS_STRING_TOKENIZER_09_018: [ The function shall return a pointer to the delimiter that defined the current token, as passed to the previous call to StringToken_GetNext() or StringToken_GetFirst() ]
+        result = token->delimiter;
+    }
+
+    return result;
+}
+
+int StringToken_Split(const char* source, size_t length, const char** delimiters, size_t n_delims, bool include_empty, char*** tokens, size_t* token_count)
+{
+    int result;
+
+    // Codes_SRS_STRING_TOKENIZER_09_022: [ If source, delimiters, token or token_count are NULL, or n_delims is zero the function shall return a non-zero value ]
+    if (source == NULL || delimiters == NULL || n_delims == 0 || tokens == NULL || token_count == NULL)
+    {
+        LogError("Invalid argument (source=%p, delimiters=%p, n_delims=%lu, tokens=%p, token_count=%p)", source, delimiters, (unsigned long)n_delims, tokens, token_count);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        STRING_TOKEN_HANDLE tokenizer;
+
+        // Codes_SRS_STRING_TOKENIZER_09_023: [ source (up to length) shall be split into individual tokens separated by any of delimiters ]
+        tokenizer = StringToken_GetFirst(source, length, delimiters, n_delims);
+
+        *token_count = 0;
+        *tokens = NULL;
+        // Codes_SRS_STRING_TOKENIZER_09_027: [ If no failures occur the function shall return zero ]
+        result = 0;
+
+        if (tokenizer != NULL)
+        {
+            do
+            {
+                const char* tokenValue;
+                size_t tokenLength;
+
+                tokenValue = StringToken_GetValue(tokenizer);
+                tokenLength = StringToken_GetLength(tokenizer);
+
+                if ((tokenValue != NULL && tokenLength == 0) || (tokenValue == NULL && tokenLength > 0))
+                {
+                    LogError("Unexpected token value (%p) or length (%lu)", tokenValue, (unsigned long)tokenLength);
+                    result = MU_FAILURE;
+                    break;
+                }
+                // Codes_SRS_STRING_TOKENIZER_09_024: [ All NULL tokens shall be ommited if include_empty is not TRUE ]
+                else if (tokenValue != NULL || include_empty)
+                {
+                    char** temp_token;
+                    // Codes_SRS_STRING_TOKENIZER_09_025: [ The tokens shall be stored in tokens, and their count stored in token_count ]
+                    *token_count = (*token_count) + 1;
+
+                    if ((temp_token = (char**)realloc(*tokens, sizeof(char*) * (*token_count))) == NULL)
+                    {
+                        // Codes_SRS_STRING_TOKENIZER_09_026: [ If any failures splitting or storing the tokens occur the function shall return a non-zero value ]
+                        LogError("Failed re-allocating the token array");
+                        (*token_count)--;
+                        result = MU_FAILURE;
+                        break;
+                    }
+                    else
+                    {
+                        *tokens = temp_token;
+                        if (tokenLength == 0)
+                        {
+                            (*tokens)[(*token_count) - 1] = NULL;
+                        }
+                        else if (((*tokens)[(*token_count) - 1] = (char*)malloc(sizeof(char) * (tokenLength + 1))) == NULL)
+                        {
+                            // Codes_SRS_STRING_TOKENIZER_09_026: [ If any failures splitting or storing the tokens occur the function shall return a non-zero value ]
+                            LogError("Failed copying token into array");
+                            *token_count = (*token_count) - 1;
+                            result = MU_FAILURE;
+                            break;
+                        }
+                        else
+                        {
+                            (void)memcpy((*tokens)[(*token_count) - 1], tokenValue, tokenLength);
+                            (*tokens)[(*token_count) - 1][tokenLength] = '\0';
+                        }
+                    }
+                }
+            } while (StringToken_GetNext(tokenizer, delimiters, n_delims));
+
+            StringToken_Destroy(tokenizer);
+
+            if (result != 0)
+            {
+                while ((*token_count) > 0 && *tokens != NULL)
+                {
+                    *token_count = (*token_count) - 1;
+                    free((*tokens)[*token_count]);
+                }
+                free(*tokens);
+            }
+        }
+    }
+
+    return result;
+}
+
+void StringToken_Destroy(STRING_TOKEN_HANDLE token)
+{
+    if (token == NULL)
+    {
+        // Codes_SRS_STRING_TOKENIZER_09_020: [ If token is NULL the function shall return ]
+        LogError("Invalig argument (token is NULL)");
+    }
+    else
+    {
+        // Codes_SRS_STRING_TOKENIZER_09_021: [ Otherwise the memory allocated for STRING_TOKEN shall be released ]
+        free(token);
+    }
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/string_tokenizer.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/string_tokenizer.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/string_tokenizer.c	(revision 453)
@@ -0,0 +1,202 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/string_tokenizer.h"
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+
+typedef struct STRING_TOKEN_TAG
+{
+    const char* inputString;
+    const char* currentPos;
+    size_t sizeOfinputString;
+} STRING_TOKEN;
+
+STRING_TOKENIZER_HANDLE STRING_TOKENIZER_create(STRING_HANDLE handle)
+{
+    STRING_TOKENIZER_HANDLE result;
+
+    /* Codes_SRS_STRING_04_001: [STRING_TOKENIZER_create shall return an NULL STRING_TOKENIZER_HANDLE if parameter handle is NULL] */
+    if (handle == NULL)
+    {
+        LogError("Invalid Argument. Handle cannot be NULL.");
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_STRING_04_002: [STRING_TOKENIZER_create shall allocate a new STRING_TOKENIZER_HANDLE having the content of the STRING_HANDLE copied and current position pointing at the beginning of the string] */
+        result = STRING_TOKENIZER_create_from_char(STRING_c_str(handle));
+    }
+
+    return result;
+}
+
+extern STRING_TOKENIZER_HANDLE STRING_TOKENIZER_create_from_char(const char* input)
+{
+    STRING_TOKEN *result;
+    char* inputStringToMalloc;
+
+    /* Codes_SRS_STRING_07_001: [STRING_TOKENIZER_create shall return an NULL STRING_TOKENIZER_HANDLE if parameter input is NULL] */
+    if (input == NULL)
+    {
+        LogError("Invalid Argument. Handle cannot be NULL.");
+        result = NULL;
+    }
+    /* Codes_SRS_STRING_07_002: [STRING_TOKENIZER_create shall allocate a new STRING_TOKENIZER_HANDLE having the content of the STRING_HANDLE copied and current position pointing at the beginning of the string] */
+    else if ((result = (STRING_TOKEN*)calloc(1, sizeof(STRING_TOKEN))) == NULL)
+    {
+        LogError("Memory Allocation failed. Cannot allocate STRING_TOKENIZER.");
+    }
+    else if ((mallocAndStrcpy_s(&inputStringToMalloc, input)) != 0)
+    {
+        LogError("Memory Allocation Failed. Cannot allocate and copy string Content.");
+        free(result);
+        result = NULL;
+    }
+    else
+    {
+        result->inputString = inputStringToMalloc;
+        result->currentPos = result->inputString; //Current Pos will point to the initial position of Token.
+        result->sizeOfinputString = strlen(result->inputString); //Calculate Size of Current String
+    }
+    return (STRING_TOKENIZER_HANDLE)result;
+}
+
+int STRING_TOKENIZER_get_next_token(STRING_TOKENIZER_HANDLE tokenizer, STRING_HANDLE output, const char* delimiters)
+{
+    int result;
+    /* Codes_SRS_STRING_04_004: [STRING_TOKENIZER_get_next_token shall return a nonzero value if any of the 3 parameters is NULL] */
+    if (tokenizer == NULL || output == NULL || delimiters == NULL)
+    {
+        result = MU_FAILURE;
+    }
+    else
+    {
+        STRING_TOKEN* token = (STRING_TOKEN*)tokenizer;
+        /* Codes_SRS_STRING_04_011: [Each subsequent call to STRING_TOKENIZER_get_next_token starts searching from the saved position on t and behaves as described above.] */
+        size_t remainingInputStringSize = token->sizeOfinputString - (token->currentPos - token->inputString);
+        size_t delimitterSize = strlen(delimiters);
+
+        /* First Check if we reached the end of the string*/
+        /* Codes_SRS_STRING_TOKENIZER_04_014: [STRING_TOKENIZER_get_next_token shall return nonzero value if t contains an empty string.] */
+        if (remainingInputStringSize == 0)
+        {
+            result = MU_FAILURE;
+        }
+        else if (delimitterSize == 0)
+        {
+            LogError("Empty delimiters parameter.");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            size_t i;
+            /* Codes_SRS_STRING_04_005: [STRING_TOKENIZER_get_next_token searches the string inside STRING_TOKENIZER_HANDLE for the first character that is NOT contained in the current delimiter] */
+            for (i = 0; i < remainingInputStringSize; i++)
+            {
+                size_t j;
+
+                bool foundDelimitter = false;
+                for (j = 0; j < delimitterSize; j++)
+                {
+                    if (token->currentPos[i] == delimiters[j])
+                    {
+                        foundDelimitter = true;
+                        break;
+                    }
+                }
+
+                /* Codes_SRS_STRING_04_007: [If such a character is found, STRING_TOKENIZER_get_next_token consider it as the start of a token.] */
+                if (!foundDelimitter)
+                {
+                    break;
+                }
+            }
+
+            /* Codes_SRS_STRING_04_006: [If no such character is found, then STRING_TOKENIZER_get_next_token shall return a nonzero Value (You've reach the end of the string or the string consists with only delimiters).] */
+            //At this point update Current Pos to the character of the last token found or end of String.
+            token->currentPos += i;
+
+            //Update the remainingInputStringSize
+            remainingInputStringSize -= i;
+
+            /* Codes_SRS_STRING_04_006: [If no such character is found, then STRING_TOKENIZER_get_next_token shall return a nonzero Value (You've reach the end of the string or the string consists with only delimiters).] */
+            if (remainingInputStringSize == 0)
+            {
+                result = MU_FAILURE;
+            }
+            else
+            {
+                bool foundDelimitter = false;
+                const char* endOfTokenPosition=NULL;
+                size_t amountOfCharactersToCopy;
+                size_t j;
+                //At this point the Current Pos is pointing to a character that is point to a nonDelimiter. So, now search for a Delimiter, till the end of the String.
+                /*Codes_SRS_STRING_04_008: [STRING_TOKENIZER_get_next_token than searches from the start of a token for a character that is contained in the delimiters string.] */
+                /* Codes_SRS_STRING_04_009: [If no such character is found, STRING_TOKENIZER_get_next_token extends the current token to the end of the string inside t, copies the token to output and returns 0.] */
+                /* Codes_SRS_STRING_04_010: [If such a character is found, STRING_TOKENIZER_get_next_token consider it the end of the token and copy it's content to output, updates the current position inside t to the next character and returns 0.] */
+                for (j = 0; j < delimitterSize; j++)
+                {
+                    if ((endOfTokenPosition = strchr(token->currentPos, delimiters[j])) != NULL)
+                    {
+                        foundDelimitter = true;
+                        break;
+                    }
+                }
+
+                //If token not found, than update the EndOfToken to the end of the inputString;
+                if (endOfTokenPosition == NULL)
+                {
+                    amountOfCharactersToCopy = remainingInputStringSize;
+                }
+                else
+                {
+                    amountOfCharactersToCopy = endOfTokenPosition - token->currentPos;
+                }
+
+                //copy here the string to output.
+                if (STRING_copy_n(output, token->currentPos, amountOfCharactersToCopy) != 0)
+                {
+                    LogError("Problem copying token to output String.");
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    //Update the Current position.
+                    //Check if end of String reached so, currentPos points to the end of String.
+                    if (foundDelimitter)
+                    {
+                        token->currentPos += amountOfCharactersToCopy + 1;
+                    }
+                    else
+                    {
+                        token->currentPos += amountOfCharactersToCopy;
+                    }
+
+                    result = 0; //Result will be on the output.
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+
+/* Codes_SRS_STRING_TOKENIZER_04_012: [STRING_TOKENIZER_destroy shall free the memory allocated by the STRING_TOKENIZER_create ] */
+void STRING_TOKENIZER_destroy(STRING_TOKENIZER_HANDLE t)
+{
+    /* Codes_SRS_STRING_TOKENIZER_04_013: [When the t argument is NULL, then STRING_TOKENIZER_destroy shall not attempt to free] */
+    if (t != NULL)
+    {
+        STRING_TOKEN* value = (STRING_TOKEN*)t;
+        free((char*)value->inputString);
+        value->inputString = NULL;
+        free(value);
+    }
+}
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/strings.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/strings.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/strings.c	(revision 453)
@@ -0,0 +1,851 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/strings.h"
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/xlogging.h"
+
+static const char hexToASCII[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+typedef struct STRING_TAG
+{
+    char* s;
+} STRING;
+
+/*this function will allocate a new string with just '\0' in it*/
+/*return NULL if it fails*/
+/* Codes_SRS_STRING_07_001: [STRING_new shall allocate a new STRING_HANDLE pointing to an empty string.] */
+STRING_HANDLE STRING_new(void)
+{
+    STRING* result;
+    if ((result = (STRING*)malloc(sizeof(STRING))) != NULL)
+    {
+        if ((result->s = (char*)malloc(1)) != NULL)
+        {
+            result->s[0] = '\0';
+        }
+        else
+        {
+            /* Codes_SRS_STRING_07_002: [STRING_new shall return an NULL STRING_HANDLE on any error that is encountered.] */
+            LogError("Failure allocating in STRING_new.");
+            free(result);
+            result = NULL;
+        }
+    }
+    return (STRING_HANDLE)result;
+}
+
+/*Codes_SRS_STRING_02_001: [STRING_clone shall produce a new string having the same content as the handle string.*/
+STRING_HANDLE STRING_clone(STRING_HANDLE handle)
+{
+    STRING* result;
+    /*Codes_SRS_STRING_02_002: [If parameter handle is NULL then STRING_clone shall return NULL.]*/
+    if (handle == NULL)
+    {
+        result = NULL;
+    }
+    else
+    {
+        /*Codes_SRS_STRING_02_003: [If STRING_clone fails for any reason, it shall return NULL.] */
+        if ((result = (STRING*)malloc(sizeof(STRING))) != NULL)
+        {
+            STRING* source = (STRING*)handle;
+            /*Codes_SRS_STRING_02_003: [If STRING_clone fails for any reason, it shall return NULL.] */
+            size_t sourceLen = strlen(source->s);
+            if ((result->s = (char*)malloc(sourceLen + 1)) == NULL)
+            {
+                LogError("Failure allocating clone value.");
+                free(result);
+                result = NULL;
+            }
+            else
+            {
+                (void)memcpy(result->s, source->s, sourceLen + 1);
+            }
+        }
+        else
+        {
+            /*not much to do, result is NULL from malloc*/
+        }
+    }
+    return (STRING_HANDLE)result;
+}
+
+/* Codes_SRS_STRING_07_003: [STRING_construct shall allocate a new string with the value of the specified const char*.] */
+STRING_HANDLE STRING_construct(const char* psz)
+{
+    STRING_HANDLE result;
+    if (psz == NULL)
+    {
+        /* Codes_SRS_STRING_07_005: [If the supplied const char* is NULL STRING_construct shall return a NULL value.] */
+        result = NULL;
+    }
+    else
+    {
+        STRING* str;
+        if ((str = (STRING*)malloc(sizeof(STRING))) != NULL)
+        {
+            size_t nLen = strlen(psz) + 1;
+            if ((str->s = (char*)malloc(nLen)) != NULL)
+            {
+                (void)memcpy(str->s, psz, nLen);
+                result = (STRING_HANDLE)str;
+            }
+            /* Codes_SRS_STRING_07_032: [STRING_construct encounters any error it shall return a NULL value.] */
+            else
+            {
+                LogError("Failure allocating constructed value.");
+                free(str);
+                result = NULL;
+            }
+        }
+        else
+        {
+            /* Codes_SRS_STRING_07_032: [STRING_construct encounters any error it shall return a NULL value.] */
+            LogError("Failure allocating value.");
+            result = NULL;
+        }
+    }
+    return result;
+}
+
+#if defined(__GNUC__)
+__attribute__ ((format (printf, 1, 2)))
+#endif
+STRING_HANDLE STRING_construct_sprintf(const char* format, ...)
+{
+    STRING* result;
+
+#ifdef STRINGS_C_SPRINTF_BUFFER_SIZE
+    size_t maxBufSize = STRINGS_C_SPRINTF_BUFFER_SIZE;
+    char buf[STRINGS_C_SPRINTF_BUFFER_SIZE];
+#else
+    size_t maxBufSize = 0;
+    char* buf = NULL;
+#endif
+
+    if (format != NULL)
+    {
+        va_list arg_list;
+        int length;
+        va_start(arg_list, format);
+
+        /* Codes_SRS_STRING_07_041: [STRING_construct_sprintf shall determine the size of the resulting string and allocate the necessary memory.] */
+        length = vsnprintf(buf, maxBufSize, format, arg_list);
+        va_end(arg_list);
+        if (length > 0)
+        {
+            result = (STRING*)malloc(sizeof(STRING));
+            if (result != NULL)
+            {
+                result->s = (char*)malloc(length+1);
+                if (result->s != NULL)
+                {
+                    va_start(arg_list, format);
+                    if (vsnprintf(result->s, length+1, format, arg_list) < 0)
+                    {
+                        /* Codes_SRS_STRING_07_040: [If any error is encountered STRING_construct_sprintf shall return NULL.] */
+                        free(result->s);
+                        free(result);
+                        result = NULL;
+                        LogError("Failure: vsnprintf formatting failed.");
+                    }
+                    va_end(arg_list);
+                }
+                else
+                {
+                    /* Codes_SRS_STRING_07_040: [If any error is encountered STRING_construct_sprintf shall return NULL.] */
+                    free(result);
+                    result = NULL;
+                    LogError("Failure: allocation sprintf value failed.");
+                }
+            }
+            else
+            {
+                LogError("Failure: allocation failed.");
+            }
+        }
+        else if (length == 0)
+        {
+            result = (STRING*)STRING_new();
+        }
+        else
+        {
+            /* Codes_SRS_STRING_07_039: [If the parameter format is NULL then STRING_construct_sprintf shall return NULL.] */
+            result = NULL;
+            LogError("Failure: vsnprintf return 0 length");
+        }
+    }
+    else
+    {
+        LogError("Failure: invalid argument.");
+        result = NULL;
+    }
+    /* Codes_SRS_STRING_07_045: [STRING_construct_sprintf shall allocate a new string with the value of the specified printf formated const char. ] */
+    return (STRING_HANDLE)result;
+}
+
+/*this function will return a new STRING with the memory for the actual string passed in as a parameter.*/
+/*return NULL if it fails.*/
+/* The supplied memory must have been allocated with malloc! */
+/* Codes_SRS_STRING_07_006: [STRING_new_with_memory shall return a STRING_HANDLE by using the supplied char* memory.] */
+STRING_HANDLE STRING_new_with_memory(const char* memory)
+{
+    STRING* result;
+    if (memory == NULL)
+    {
+        /* Codes_SRS_STRING_07_007: [STRING_new_with_memory shall return a NULL STRING_HANDLE if the supplied char* is NULL.] */
+        result = NULL;
+    }
+    else
+    {
+        if ((result = (STRING*)malloc(sizeof(STRING))) != NULL)
+        {
+            result->s = (char*)memory;
+        }
+        else
+        {
+            LogError("Failure: allocating memory string");
+        }
+    }
+    return (STRING_HANDLE)result;
+}
+
+/* Codes_SRS_STRING_07_008: [STRING_new_quoted shall return a valid STRING_HANDLE Copying the supplied const char* value surrounded by quotes.] */
+STRING_HANDLE STRING_new_quoted(const char* source)
+{
+    STRING* result;
+    if (source == NULL)
+    {
+        /* Codes_SRS_STRING_07_009: [STRING_new_quoted shall return a NULL STRING_HANDLE if the supplied const char* is NULL.] */
+        result = NULL;
+    }
+    else if ((result = (STRING*)malloc(sizeof(STRING))) != NULL)
+    {
+        size_t sourceLength = strlen(source);
+        if ((result->s = (char*)malloc(sourceLength + 3)) != NULL)
+        {
+            result->s[0] = '"';
+            (void)memcpy(result->s + 1, source, sourceLength);
+            result->s[sourceLength + 1] = '"';
+            result->s[sourceLength + 2] = '\0';
+        }
+        else
+        {
+            /* Codes_SRS_STRING_07_031: [STRING_new_quoted shall return a NULL STRING_HANDLE if any error is encountered.] */
+            LogError("Failure allocating quoted string value.");
+            free(result);
+            result = NULL;
+        }
+    }
+    return (STRING_HANDLE)result;
+}
+
+/*this function takes a regular const char* and turns in into "this is a\"JSON\" strings\u0008" (starting and ending quote included)*/
+/*the newly created handle needs to be disposed of with STRING_delete*/
+/*returns NULL if there are errors*/
+STRING_HANDLE STRING_new_JSON(const char* source)
+{
+    STRING* result;
+    if (source == NULL)
+    {
+        /*Codes_SRS_STRING_02_011: [If source is NULL then STRING_new_JSON shall return NULL.] */
+        result = NULL;
+        LogError("invalid arg (NULL)");
+    }
+    else
+    {
+        size_t i;
+        size_t nControlCharacters = 0; /*counts how many characters are to be expanded from 1 character to \uxxxx (6 characters)*/
+        size_t nEscapeCharacters = 0;
+        size_t vlen = strlen(source);
+
+        for (i = 0; i < vlen; i++)
+        {
+            /*Codes_SRS_STRING_02_014: [If any character has the value outside [1...127] then STRING_new_JSON shall fail and return NULL.] */
+            if ((unsigned char)source[i] >= 128) /*this be a UNICODE character begin*/
+            {
+                break;
+            }
+            else
+            {
+                if (source[i] <= 0x1F)
+                {
+                    nControlCharacters++;
+                }
+                else if (
+                    (source[i] == '"') ||
+                    (source[i] == '\\') ||
+                    (source[i] == '/')
+                    )
+                {
+                    nEscapeCharacters++;
+                }
+            }
+        }
+
+        if (i < vlen)
+        {
+            result = NULL;
+            LogError("invalid character in input string");
+        }
+        else
+        {
+            if ((result = (STRING*)malloc(sizeof(STRING))) == NULL)
+            {
+                /*Codes_SRS_STRING_02_021: [If the complete JSON representation cannot be produced, then STRING_new_JSON shall fail and return NULL.] */
+                LogError("malloc json failure");
+            }
+            else if ((result->s = (char*)malloc(vlen + 5 * nControlCharacters + nEscapeCharacters + 3)) == NULL)
+            {
+                /*Codes_SRS_STRING_02_021: [If the complete JSON representation cannot be produced, then STRING_new_JSON shall fail and return NULL.] */
+                free(result);
+                result = NULL;
+                LogError("malloc failed");
+            }
+            else
+            {
+                size_t pos = 0;
+                /*Codes_SRS_STRING_02_012: [The string shall begin with the quote character.] */
+                result->s[pos++] = '"';
+                for (i = 0; i < vlen; i++)
+                {
+                    if (source[i] <= 0x1F)
+                    {
+                        /*Codes_SRS_STRING_02_019: [If the character code is less than 0x20 then it shall be represented as \u00xx, where xx is the hex representation of the character code.]*/
+                        result->s[pos++] = '\\';
+                        result->s[pos++] = 'u';
+                        result->s[pos++] = '0';
+                        result->s[pos++] = '0';
+                        result->s[pos++] = hexToASCII[(source[i] & 0xF0) >> 4]; /*high nibble*/
+                        result->s[pos++] = hexToASCII[source[i] & 0x0F]; /*low nibble*/
+                    }
+                    else if (source[i] == '"')
+                    {
+                        /*Codes_SRS_STRING_02_016: [If the character is " (quote) then it shall be repsented as \".] */
+                        result->s[pos++] = '\\';
+                        result->s[pos++] = '"';
+                    }
+                    else if (source[i] == '\\')
+                    {
+                        /*Codes_SRS_STRING_02_017: [If the character is \ (backslash) then it shall represented as \\.] */
+                        result->s[pos++] = '\\';
+                        result->s[pos++] = '\\';
+                    }
+                    else if (source[i] == '/')
+                    {
+                        /*Codes_SRS_STRING_02_018: [If the character is / (slash) then it shall be represented as \/.] */
+                        result->s[pos++] = '\\';
+                        result->s[pos++] = '/';
+                    }
+                    else
+                    {
+                        /*Codes_SRS_STRING_02_013: [The string shall copy the characters of source "as they are" (until the '\0' character) with the following exceptions:] */
+                        result->s[pos++] = source[i];
+                    }
+                }
+                /*Codes_SRS_STRING_02_020: [The string shall end with " (quote).] */
+                result->s[pos++] = '"';
+                /*zero terminating it*/
+                result->s[pos] = '\0';
+            }
+        }
+
+    }
+    return (STRING_HANDLE)result;
+}
+
+/*this function will concatenate to the string s1 the string s2, resulting in s1+s2*/
+/*returns 0 if success*/
+/*any other error code is failure*/
+/* Codes_SRS_STRING_07_012: [STRING_concat shall concatenate the given STRING_HANDLE and the const char* value and place the value in the handle.] */
+int STRING_concat(STRING_HANDLE handle, const char* s2)
+{
+    int result;
+    if ((handle == NULL) || (s2 == NULL))
+    {
+        /* Codes_SRS_STRING_07_013: [STRING_concat shall return a nonzero number if an error is encountered.] */
+        result = MU_FAILURE;
+    }
+    else
+    {
+        STRING* s1 = (STRING*)handle;
+        size_t s1Length = strlen(s1->s);
+        size_t s2Length = strlen(s2);
+        char* temp = (char*)realloc(s1->s, s1Length + s2Length + 1);
+        if (temp == NULL)
+        {
+            /* Codes_SRS_STRING_07_013: [STRING_concat shall return a nonzero number if an error is encountered.] */
+            LogError("Failure reallocating value.");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            s1->s = temp;
+            (void)memcpy(s1->s + s1Length, s2, s2Length + 1);
+            result = 0;
+        }
+    }
+    return result;
+}
+
+/*this function will concatenate to the string s1 the string s2, resulting in s1+s2*/
+/*returns 0 if success*/
+/*any other error code is failure*/
+/* Codes_SRS_STRING_07_034: [String_Concat_with_STRING shall concatenate a given STRING_HANDLE variable with a source STRING_HANDLE.] */
+int STRING_concat_with_STRING(STRING_HANDLE s1, STRING_HANDLE s2)
+{
+    int result;
+    if ((s1 == NULL) || (s2 == NULL))
+    {
+        /* Codes_SRS_STRING_07_035: [String_Concat_with_STRING shall return a nonzero number if an error is encountered.] */
+        LogError("Invalid argument specified");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        STRING* dest = (STRING*)s1;
+        STRING* src = (STRING*)s2;
+
+        size_t s1Length = strlen(dest->s);
+        size_t s2Length = strlen(src->s);
+        char* temp = (char*)realloc(dest->s, s1Length + s2Length + 1);
+        if (temp == NULL)
+        {
+            /* Codes_SRS_STRING_07_035: [String_Concat_with_STRING shall return a nonzero number if an error is encountered.] */
+            LogError("Failure reallocating value");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            dest->s = temp;
+            /* Codes_SRS_STRING_07_034: [String_Concat_with_STRING shall concatenate a given STRING_HANDLE variable with a source STRING_HANDLE.] */
+            (void)memcpy(dest->s + s1Length, src->s, s2Length + 1);
+            result = 0;
+        }
+    }
+    return result;
+}
+
+/*this function will copy the string from s2 to s1*/
+/*returns 0 if success*/
+/*any other error code is failure*/
+/* Codes_SRS_STRING_07_016: [STRING_copy shall copy the const char* into the supplied STRING_HANDLE.] */
+int STRING_copy(STRING_HANDLE handle, const char* s2)
+{
+    int result;
+    if ((handle == NULL) || (s2 == NULL))
+    {
+        /* Codes_SRS_STRING_07_017: [STRING_copy shall return a nonzero value if any of the supplied parameters are NULL.] */
+        result = MU_FAILURE;
+    }
+    else
+    {
+        STRING* s1 = (STRING*)handle;
+        /* Codes_SRS_STRING_07_026: [If the underlying char* refered to by s1 handle is equal to char* s2 than STRING_copy shall be a noop and return 0.] */
+        if (s1->s != s2)
+        {
+            size_t s2Length = strlen(s2);
+            char* temp = (char*)realloc(s1->s, s2Length + 1);
+            if (temp == NULL)
+            {
+                LogError("Failure reallocating value.");
+                /* Codes_SRS_STRING_07_027: [STRING_copy shall return a nonzero value if any error is encountered.] */
+                result = MU_FAILURE;
+            }
+            else
+            {
+                s1->s = temp;
+                memmove(s1->s, s2, s2Length + 1);
+                result = 0;
+            }
+        }
+        else
+        {
+            /* Codes_SRS_STRING_07_033: [If overlapping pointer address is given to STRING_copy the behavior is undefined.] */
+            result = 0;
+        }
+    }
+    return result;
+}
+
+/*this function will copy n chars from s2 to the string s1, resulting in n chars only from s2 being stored in s1.*/
+/*returns 0 if success*/
+/*any other error code is failure*/
+/* Codes_SRS_STRING_07_018: [STRING_copy_n shall copy the number of characters in const char* or the size_t whichever is lesser.] */
+int STRING_copy_n(STRING_HANDLE handle, const char* s2, size_t n)
+{
+    int result;
+    if ((handle == NULL) || (s2 == NULL))
+    {
+        /* Codes_SRS_STRING_07_019: [STRING_copy_n shall return a nonzero value if STRING_HANDLE or const char* is NULL.] */
+        result = MU_FAILURE;
+    }
+    else
+    {
+        STRING* s1 = (STRING*)handle;
+        size_t s2Length = strlen(s2);
+        char* temp;
+        if (s2Length > n)
+        {
+            s2Length = n;
+        }
+
+        temp = (char*)realloc(s1->s, s2Length + 1);
+        if (temp == NULL)
+        {
+            LogError("Failure reallocating value.");
+            /* Codes_SRS_STRING_07_028: [STRING_copy_n shall return a nonzero value if any error is encountered.] */
+            result = MU_FAILURE;
+        }
+        else
+        {
+            s1->s = temp;
+            (void)memcpy(s1->s, s2, s2Length);
+            s1->s[s2Length] = 0;
+            result = 0;
+        }
+
+    }
+    return result;
+}
+
+#if defined(__GNUC__)
+__attribute__ ((format (printf, 2, 3)))
+#endif
+int STRING_sprintf(STRING_HANDLE handle, const char* format, ...)
+{
+    int result;
+
+#ifdef STRINGS_C_SPRINTF_BUFFER_SIZE
+    size_t maxBufSize = STRINGS_C_SPRINTF_BUFFER_SIZE;
+    char buf[STRINGS_C_SPRINTF_BUFFER_SIZE];
+#else
+    size_t maxBufSize = 0;
+    char* buf = NULL;
+#endif
+
+    if (handle == NULL || format == NULL)
+    {
+        /* Codes_SRS_STRING_07_042: [if the parameters s1 or format are NULL then STRING_sprintf shall return non zero value.] */
+        LogError("Invalid arg (NULL)");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        va_list arg_list;
+        int s2Length;
+        va_start(arg_list, format);
+
+        s2Length = vsnprintf(buf, maxBufSize, format, arg_list);
+        va_end(arg_list);
+        if (s2Length < 0)
+        {
+            /* Codes_SRS_STRING_07_043: [If any error is encountered STRING_sprintf shall return a non zero value.] */
+            LogError("Failure vsnprintf return < 0");
+            result = MU_FAILURE;
+        }
+        else if (s2Length == 0)
+        {
+            // Don't need to reallocate and nothing should be added
+            result = 0;
+        }
+        else
+        {
+            STRING* s1 = (STRING*)handle;
+            char* temp;
+            size_t s1Length = strlen(s1->s);
+            temp = (char*)realloc(s1->s, s1Length + s2Length + 1);
+            if (temp != NULL)
+            {
+                s1->s = temp;
+                va_start(arg_list, format);
+                if (vsnprintf(s1->s + s1Length, s1Length + s2Length + 1, format, arg_list) < 0)
+                {
+                    /* Codes_SRS_STRING_07_043: [If any error is encountered STRING_sprintf shall return a non zero value.] */
+                    LogError("Failure vsnprintf formatting error");
+                    s1->s[s1Length] = '\0';
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    /* Codes_SRS_STRING_07_044: [On success STRING_sprintf shall return 0.]*/
+                    result = 0;
+                }
+                va_end(arg_list);
+            }
+            else
+            {
+                /* Codes_SRS_STRING_07_043: [If any error is encountered STRING_sprintf shall return a non zero value.] */
+                LogError("Failure unable to reallocate memory");
+                result = MU_FAILURE;
+            }
+        }
+    }
+    return result;
+}
+
+/*this function will quote the string passed as argument string =>"string"*/
+/*returns 0 if success*/ /*doesn't change the string otherwise*/
+/*any other error code is failure*/
+/* Codes_SRS_STRING_07_014: [STRING_quote shall "quote" the supplied STRING_HANDLE and return 0 on success.] */
+int STRING_quote(STRING_HANDLE handle)
+{
+    int result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_STRING_07_015: [STRING_quote shall return a nonzero value if any of the supplied parameters are NULL.] */
+        result = MU_FAILURE;
+    }
+    else
+    {
+        STRING* s1 = (STRING*)handle;
+        size_t s1Length = strlen(s1->s);
+        char* temp = (char*)realloc(s1->s, s1Length + 2 + 1);/*2 because 2 quotes, 1 because '\0'*/
+        if (temp == NULL)
+        {
+            LogError("Failure reallocating value.");
+            /* Codes_SRS_STRING_07_029: [STRING_quote shall return a nonzero value if any error is encountered.] */
+            result = MU_FAILURE;
+        }
+        else
+        {
+            s1->s = temp;
+            memmove(s1->s + 1, s1->s, s1Length);
+            s1->s[0] = '"';
+            s1->s[s1Length + 1] = '"';
+            s1->s[s1Length + 2] = '\0';
+            result = 0;
+        }
+    }
+    return result;
+}
+/*this function will revert a string to an empty state*/
+/*Returns 0 if the revert was succesful*/
+/* Codes_SRS_STRING_07_022: [STRING_empty shall revert the STRING_HANDLE to an empty state.] */
+int STRING_empty(STRING_HANDLE handle)
+{
+    int result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_STRING_07_023: [STRING_empty shall return a nonzero value if the STRING_HANDLE is NULL.] */
+        result = MU_FAILURE;
+    }
+    else
+    {
+        STRING* s1 = (STRING*)handle;
+        char* temp = (char*)realloc(s1->s, 1);
+        if (temp == NULL)
+        {
+            LogError("Failure reallocating value.");
+            /* Codes_SRS_STRING_07_030: [STRING_empty shall return a nonzero value if the STRING_HANDLE is NULL.] */
+            result = MU_FAILURE;
+        }
+        else
+        {
+            s1->s = temp;
+            s1->s[0] = '\0';
+            result = 0;
+        }
+    }
+    return result;
+}
+
+/*this function will deallocate a string constructed by str_new*/
+/* Codes_SRS_STRING_07_010: [STRING_delete will free the memory allocated by the STRING_HANDLE.] */
+void STRING_delete(STRING_HANDLE handle)
+{
+    /* Codes_SRS_STRING_07_011: [STRING_delete will not attempt to free anything with a NULL STRING_HANDLE.] */
+    if (handle != NULL)
+    {
+        STRING* value = (STRING*)handle;
+        free(value->s);
+        value->s = NULL;
+        free(value);
+    }
+}
+
+/* Codes_SRS_STRING_07_020: [STRING_c_str shall return the const char* associated with the given STRING_HANDLE.] */
+const char* STRING_c_str(STRING_HANDLE handle)
+{
+    const char* result;
+    if (handle != NULL)
+    {
+        result = ((STRING*)handle)->s;
+    }
+    else
+    {
+        /* Codes_SRS_STRING_07_021: [STRING_c_str shall return NULL if the STRING_HANDLE is NULL.] */
+        result = NULL;
+    }
+    return result;
+}
+
+/* Codes_SRS_STRING_07_024: [STRING_length shall return the length of the underlying char* for the given handle] */
+size_t STRING_length(STRING_HANDLE handle)
+{
+    size_t result = 0;
+    /* Codes_SRS_STRING_07_025: [STRING_length shall return zero if the given handle is NULL.] */
+    if (handle != NULL)
+    {
+        STRING* value = (STRING*)handle;
+        result = strlen(value->s);
+    }
+    return result;
+}
+
+/*Codes_SRS_STRING_02_007: [STRING_construct_n shall construct a STRING_HANDLE from first "n" characters of the string pointed to by psz parameter.]*/
+STRING_HANDLE STRING_construct_n(const char* psz, size_t n)
+{
+    STRING_HANDLE result;
+    /*Codes_SRS_STRING_02_008: [If psz is NULL then STRING_construct_n shall return NULL.] */
+    if (psz == NULL)
+    {
+        result = NULL;
+        LogError("invalid arg (NULL)");
+    }
+    else
+    {
+        size_t len = strlen(psz);
+        /*Codes_SRS_STRING_02_009: [If n is bigger than the size of the string psz, then STRING_construct_n shall return NULL.] */
+        if (n > len)
+        {
+            result = NULL;
+            LogError("invalig arg (n is bigger than the size of the string)");
+        }
+        else
+        {
+            STRING* str;
+            if ((str = (STRING*)malloc(sizeof(STRING))) != NULL)
+            {
+                if ((str->s = (char*)malloc(len + 1)) != NULL)
+                {
+                    (void)memcpy(str->s, psz, n);
+                    str->s[n] = '\0';
+                    result = (STRING_HANDLE)str;
+                }
+                /* Codes_SRS_STRING_02_010: [In all other error cases, STRING_construct_n shall return NULL.]  */
+                else
+                {
+                    LogError("Failure allocating value.");
+                    free(str);
+                    result = NULL;
+                }
+            }
+            else
+            {
+                /* Codes_SRS_STRING_02_010: [In all other error cases, STRING_construct_n shall return NULL.]  */
+                result = NULL;
+            }
+        }
+    }
+    return result;
+}
+
+/* Codes_SRS_STRING_07_034: [STRING_compare returns an integer greater than, equal to, or less than zero, accordingly as the string pointed to by s1 is greater than, equal to, or less than the string s2.] */
+int STRING_compare(STRING_HANDLE s1, STRING_HANDLE s2)
+{
+    int result;
+    if (s1 == NULL && s2 == NULL)
+    {
+        /* Codes_SRS_STRING_07_035: [If h1 and h2 are both NULL then STRING_compare shall return 0.]*/
+        result = 0;
+    }
+    else if (s1 == NULL)
+    {
+        /* Codes_SRS_STRING_07_036: [If h1 is NULL and h2 is nonNULL then STRING_compare shall return 1.]*/
+        result = 1;
+    }
+    else if (s2 == NULL)
+    {
+        /* Codes_SRS_STRING_07_037: [If h2 is NULL and h1 is nonNULL then STRING_compare shall return -1.] */
+        result = -1;
+    }
+    else
+    {
+        /* Codes_SRS_STRING_07_038: [STRING_compare shall compare the char s variable using the strcmp function.] */
+        STRING* value1 = (STRING*)s1;
+        STRING* value2 = (STRING*)s2;
+        result = strcmp(value1->s, value2->s);
+    }
+    return result;
+}
+
+STRING_HANDLE STRING_from_byte_array(const unsigned char* source, size_t size)
+{
+    STRING* result;
+    /*Codes_SRS_STRING_02_022: [ If source is NULL and size > 0 then STRING_from_BUFFER shall fail and return NULL. ]*/
+    if ((source == NULL) && (size > 0))
+    {
+        LogError("invalid parameter (NULL)");
+        result = NULL;
+    }
+    else
+    {
+        /*Codes_SRS_STRING_02_023: [ Otherwise, STRING_from_BUFFER shall build a string that has the same content (byte-by-byte) as source and return a non-NULL handle. ]*/
+        result = (STRING*)malloc(sizeof(STRING));
+        if (result == NULL)
+        {
+            /*Codes_SRS_STRING_02_024: [ If building the string fails, then STRING_from_BUFFER shall fail and return NULL. ]*/
+            LogError("oom - unable to malloc");
+            /*return as is*/
+        }
+        else
+        {
+            /*Codes_SRS_STRING_02_023: [ Otherwise, STRING_from_BUFFER shall build a string that has the same content (byte-by-byte) as source and return a non-NULL handle. ]*/
+            result->s = (char*)malloc(size + 1);
+            if (result->s == NULL)
+            {
+                /*Codes_SRS_STRING_02_024: [ If building the string fails, then STRING_from_BUFFER shall fail and return NULL. ]*/
+                LogError("oom - unable to malloc");
+                free(result);
+                result = NULL;
+            }
+            else
+            {
+                (void)memcpy(result->s, source, size);
+                result->s[size] = '\0'; /*all is fine*/
+            }
+        }
+    }
+    return (STRING_HANDLE)result;
+}
+
+int STRING_replace(STRING_HANDLE handle, char target, char replace)
+{
+    int result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_STRING_07_046: [ If handle is NULL STRING_replace shall return a non-zero value. ] */
+        result = MU_FAILURE;
+    }
+    else if (target == replace)
+    {
+        /* Codes_SRS_STRING_07_048: [ If target and replace are equal STRING_replace, shall do nothing shall return zero. ] */
+        result = 0;
+    }
+    else
+    {
+        size_t length;
+        size_t index;
+        /* Codes_SRS_STRING_07_047: [ STRING_replace shall replace all instances of target with replace. ] */
+        STRING* str_value = (STRING*)handle;
+        length = strlen(str_value->s);
+        for (index = 0; index < length; index++)
+        {
+            if (str_value->s[index] == target)
+            {
+                str_value->s[index] = replace;
+            }
+        }
+        /* Codes_SRS_STRING_07_049: [ On success STRING_replace shall return zero. ] */
+        result = 0;
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/urlencode.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/urlencode.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/urlencode.c	(revision 453)
@@ -0,0 +1,350 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <string.h>
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/urlencode.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/strings.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+
+#define NIBBLE_TO_STRING(c) (char)((c) < 10 ? (c) + '0' : (c) - 10 + 'a')
+#define NIBBLE_FROM_STRING(c) (char)(ISDIGIT(c) ? (c) - '0' : TOUPPER(c) + 10 - 'A')
+#define IS_HEXDIGIT(c) (            \
+    ((c >= '0') && (c <= '9')) ||   \
+    ((c >= 'A') && (c <= 'F')) ||   \
+    ((c >= 'a') && (c <= 'f'))      \
+)
+#define IS_PRINTABLE(c) (                           \
+    (c == 0) ||                                     \
+    (c == '!') ||                                   \
+    (c == '(') || (c == ')') || (c == '*') ||       \
+    (c == '-') || (c == '.') ||                     \
+    ((c >= '0') && (c <= '9')) ||                   \
+    ((c >= 'A') && (c <= 'Z')) ||                   \
+    (c == '_') ||                                   \
+    ((c >= 'a') && (c <= 'z'))                      \
+)
+
+/*The below macros are to be called on the big nibble of a hex value*/
+#define IS_IN_ASCII_RANGE(c) (  \
+    (c >= '0') && (c <= '7')    \
+)
+#define IS_IN_EXTENDED_ASCII_RANGE(c) ( \
+    ((c >= '8') && (c <= '9')) ||       \
+    ((c >= 'A') && (c <= 'F')) ||       \
+    ((c >= 'a') && (c <= 'f'))          \
+)
+#define IS_IN_CONTINUATION_BYTE_RANGE(c) (  \
+    (c == '8') || (c == '9') ||             \
+    (c == 'A') || (c == 'B') ||             \
+    (c == 'a') || (c == 'b')                \
+)
+#define IS_IN_LEADING_BYTE_RANGE(c) (   \
+    ((c >= 'C') && (c <= 'F')) ||       \
+    ((c >= 'c') && (c <= 'f'))          \
+)
+#define IS_IN_UNSUPPORTED_LEADING_BYTE_RANGE(c) (   \
+    ((c >= 'D') && (c <= 'F')) ||                   \
+    ((c >= 'd') && (c <= 'f'))                      \
+)
+
+static size_t URL_PrintableChar(unsigned char charVal, char* buffer)
+{
+    size_t size;
+    if (IS_PRINTABLE(charVal))
+    {
+        buffer[0] = (char)charVal;
+        size = 1;
+    }
+    else
+    {
+        char bigNibbleStr;
+        char littleNibbleStr;
+        unsigned char bigNibbleVal = charVal >> 4;
+        unsigned char littleNibbleVal = charVal & 0x0F;
+
+        if (bigNibbleVal >= 0x0C)
+        {
+            bigNibbleVal -= 0x04;
+        }
+
+        bigNibbleStr = NIBBLE_TO_STRING(bigNibbleVal);
+        littleNibbleStr = NIBBLE_TO_STRING(littleNibbleVal);
+
+        buffer[0] = '%';
+
+        if (charVal < 0x80)
+        {
+            buffer[1] = bigNibbleStr;
+            buffer[2] = littleNibbleStr;
+            size = 3;
+        }
+        else
+        {
+            buffer[1] = 'c';
+            buffer[3] = '%';
+            buffer[4] = bigNibbleStr;
+            buffer[5] = littleNibbleStr;
+            if (charVal < 0xC0)
+            {
+                buffer[2] = '2';
+            }
+            else
+            {
+                buffer[2] = '3';
+            }
+            size = 6;
+        }
+    }
+
+    return size;
+}
+
+static size_t calculateDecodedStringSize(const char* encodedString, size_t len)
+{
+    size_t decodedSize = 0;
+
+    if (encodedString == NULL)
+    {
+        LogError("Null encoded string");
+    }
+    else if (len == 0)
+    {
+        decodedSize = 1; //for null terminator
+    }
+    else
+    {
+        size_t remaining_len = len;
+        size_t next_step = 0;
+        size_t i = 0;
+        while (i < len)
+        {
+            //percent encoded character
+            if (encodedString[i] == '%')
+            {
+                if (remaining_len < 3 || !IS_HEXDIGIT(encodedString[i+1]) || !IS_HEXDIGIT(encodedString[i+2]))
+                {
+                    LogError("Incomplete or invalid percent encoding");
+                    break;
+                }
+                else if (!IS_IN_ASCII_RANGE(encodedString[i+1]))
+                {
+                    LogError("Out of range of characters accepted by this decoder");
+                    break;
+                }
+                else
+                {
+                    decodedSize++;
+                    next_step = 3;
+                }
+            }
+            else if (!IS_PRINTABLE(encodedString[i]))
+            {
+                LogError("Unprintable value in encoded string");
+                break;
+            }
+            //safe character
+            else
+            {
+                decodedSize++;
+                next_step = 1;
+            }
+
+            i += next_step;
+            remaining_len -= next_step;
+        }
+
+        if (encodedString[i] != '\0') //i.e. broke out of above loop due to error
+        {
+            decodedSize = 0;
+        }
+        else
+        {
+            decodedSize++; //add space for the null terminator
+        }
+    }
+    return decodedSize;
+}
+
+static unsigned char charFromNibbles(char bigNibbleStr, char littleNibbleStr)
+{
+    unsigned char bigNibbleVal = NIBBLE_FROM_STRING(bigNibbleStr);
+    unsigned char littleNibbleVal = NIBBLE_FROM_STRING(littleNibbleStr);
+
+    return bigNibbleVal << 4 | littleNibbleVal;
+}
+
+static void createDecodedString(const char* input, size_t input_size, char* output)
+{
+    /* Note that there is no danger of reckless indexing here, as calculateDecodedStringSize()
+    has already checked lengths of strings to ensure the formatting is always correct*/
+    size_t i = 0;
+    while (i <= input_size) //the <= instead of < ensures the '\0' will be copied
+    {
+        if (input[i] != '%')
+        {
+            *output++ = input[i];
+            i++;
+        }
+        else
+        {
+            *output++ = charFromNibbles(input[i+1], input[i+2]);
+            i += 3;
+        }
+    }
+}
+
+static size_t URL_PrintableCharSize(unsigned char charVal)
+{
+    size_t size;
+    if (IS_PRINTABLE(charVal))
+    {
+        size = 1;
+    }
+    else
+    {
+        if (charVal < 0x80)
+        {
+            size = 3;
+        }
+        else
+        {
+            size = 6;
+        }
+    }
+    return size;
+}
+
+static STRING_HANDLE encode_url_data(const char* text)
+{
+    STRING_HANDLE result;
+    size_t lengthOfResult = 0;
+    char* encodedURL;
+    unsigned char currentUnsignedChar;
+    const char* iterator = text;
+
+    /*Codes_SRS_URL_ENCODE_06_003: [If input is a zero length string then URL_Encode will return a zero length string.]*/
+    do
+    {
+        currentUnsignedChar = (unsigned char)(*iterator++);
+        lengthOfResult += URL_PrintableCharSize(currentUnsignedChar);
+    } while (currentUnsignedChar != 0);
+
+    if ((encodedURL = (char*)malloc(lengthOfResult)) == NULL)
+    {
+        /*Codes_SRS_URL_ENCODE_06_002: [If an error occurs during the encoding of input then URL_Encode will return NULL.]*/
+        result = NULL;
+        LogError("URL_Encode:: MALLOC failure on encode.");
+    }
+    else
+    {
+        size_t currentEncodePosition = 0;
+        iterator = text;;
+        do
+        {
+            currentUnsignedChar = (unsigned char)(*iterator++);
+            currentEncodePosition += URL_PrintableChar(currentUnsignedChar, &encodedURL[currentEncodePosition]);
+        } while (currentUnsignedChar != 0);
+
+        result = STRING_new_with_memory(encodedURL);
+        if (result == NULL)
+        {
+            LogError("URL_Encode:: MALLOC failure on encode.");
+            free(encodedURL);
+        }
+    }
+    return result;
+}
+
+STRING_HANDLE URL_EncodeString(const char* textEncode)
+{
+    STRING_HANDLE result;
+    if (textEncode == NULL)
+    {
+        result = NULL;
+    }
+    else
+    {
+        result = encode_url_data(textEncode);
+    }
+    return result;
+}
+
+STRING_HANDLE URL_Encode(STRING_HANDLE input)
+{
+    STRING_HANDLE result;
+    if (input == NULL)
+    {
+        /*Codes_SRS_URL_ENCODE_06_001: [If input is NULL then URL_Encode will return NULL.]*/
+        result = NULL;
+        LogError("URL_Encode:: NULL input");
+    }
+    else
+    {
+        result = encode_url_data(STRING_c_str(input));
+    }
+    return result;
+}
+
+STRING_HANDLE URL_DecodeString(const char* textDecode)
+{
+    STRING_HANDLE result;
+    if (textDecode == NULL)
+    {
+        result = NULL;
+    }
+    else
+    {
+        STRING_HANDLE tempString = STRING_construct(textDecode);
+        if (tempString == NULL)
+        {
+            result = NULL;
+        }
+        else
+        {
+            result = URL_Decode(tempString);
+            STRING_delete(tempString);
+        }
+    }
+    return result;
+}
+
+STRING_HANDLE URL_Decode(STRING_HANDLE input)
+{
+    STRING_HANDLE result;
+    if (input == NULL)
+    {
+        LogError("URL_Decode:: NULL input");
+        result = NULL;
+    }
+    else
+    {
+        size_t decodedStringSize;
+        char* decodedString;
+        const char* inputString = STRING_c_str(input);
+        size_t inputLen = strlen(inputString);
+        if ((decodedStringSize = calculateDecodedStringSize(inputString, inputLen)) == 0)
+        {
+            LogError("URL_Decode:: Invalid input string");
+            result = NULL;
+        }
+        else if ((decodedString = (char*)malloc(decodedStringSize)) == NULL)
+        {
+            LogError("URL_Decode:: MALLOC failure on decode.");
+            result = NULL;
+        }
+        else
+        {
+            createDecodedString(inputString, inputLen, decodedString);
+            result = STRING_new_with_memory(decodedString);
+            if (result == NULL)
+            {
+                LogError("URL_Decode:: MALLOC failure on decode");
+                free(decodedString);
+            }
+        }
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/usha.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/usha.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/usha.c	(revision 453)
@@ -0,0 +1,263 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/**************************** usha.c ****************************/
+/******************** See RFC 4634 for details ******************/
+/*
+*  Description:
+*     This file implements a unified interface to the SHA algorithms.
+*/
+
+#include "azure_c_shared_utility/sha.h"
+
+/*
+*  USHAReset
+*
+*  Description:
+*      This function will initialize the SHA Context in preparation
+*      for computing a new SHA message digest.
+*
+*  Parameters:
+*      context: [in/out]
+*          The context to reset.
+*      whichSha: [in]
+*          Selects which SHA reset to call
+*
+*  Returns:
+*      sha Error Code.
+*
+*/
+int USHAReset(USHAContext *ctx, enum SHAversion whichSha)
+{
+    if (ctx) {
+        ctx->whichSha = whichSha;
+        switch (whichSha) {
+        case SHA1:   return SHA1Reset((SHA1Context*)&ctx->ctx);
+        case SHA224: return SHA224Reset((SHA224Context*)&ctx->ctx);
+        case SHA256: return SHA256Reset((SHA256Context*)&ctx->ctx);
+        case SHA384: return SHA384Reset((SHA384Context*)&ctx->ctx);
+        case SHA512: return SHA512Reset((SHA512Context*)&ctx->ctx);
+        default: return shaBadParam;
+        }
+    }
+    else {
+        return shaNull;
+    }
+}
+
+/*
+*  USHAInput
+*
+*  Description:
+*      This function accepts an array of octets as the next portion
+*      of the message.
+*
+*  Parameters:
+*      context: [in/out]
+*          The SHA context to update
+*      message_array: [in]
+*          An array of characters representing the next portion of
+*          the message.
+*      length: [in]
+*          The length of the message in message_array
+*
+*  Returns:
+*      sha Error Code.
+*
+*/
+int USHAInput(USHAContext *ctx,
+    const uint8_t *bytes, unsigned int bytecount)
+{
+    if (ctx) {
+        switch (ctx->whichSha) {
+        case SHA1:
+            return SHA1Input((SHA1Context*)&ctx->ctx, bytes, bytecount);
+        case SHA224:
+            return SHA224Input((SHA224Context*)&ctx->ctx, bytes,
+                bytecount);
+        case SHA256:
+            return SHA256Input((SHA256Context*)&ctx->ctx, bytes,
+                bytecount);
+        case SHA384:
+            return SHA384Input((SHA384Context*)&ctx->ctx, bytes,
+                bytecount);
+        case SHA512:
+            return SHA512Input((SHA512Context*)&ctx->ctx, bytes,
+                bytecount);
+        default: return shaBadParam;
+        }
+    }
+    else {
+        return shaNull;
+    }
+}
+
+/*
+* USHAFinalBits
+*
+* Description:
+*   This function will add in any final bits of the message.
+*
+* Parameters:
+*   context: [in/out]
+*     The SHA context to update
+*   message_bits: [in]
+*     The final bits of the message, in the upper portion of the
+*     byte. (Use 0b###00000 instead of 0b00000### to input the
+*     three bits ###.)
+*   length: [in]
+*     The number of bits in message_bits, between 1 and 7.
+*
+* Returns:
+*   sha Error Code.
+*/
+int USHAFinalBits(USHAContext *ctx,
+const uint8_t bits, unsigned int bitcount)
+{
+    if (ctx) {
+        switch (ctx->whichSha) {
+        case SHA1:
+            return SHA1FinalBits((SHA1Context*)&ctx->ctx, bits, bitcount);
+        case SHA224:
+            return SHA224FinalBits((SHA224Context*)&ctx->ctx, bits,
+                bitcount);
+        case SHA256:
+            return SHA256FinalBits((SHA256Context*)&ctx->ctx, bits,
+                bitcount);
+        case SHA384:
+            return SHA384FinalBits((SHA384Context*)&ctx->ctx, bits,
+                bitcount);
+        case SHA512:
+            return SHA512FinalBits((SHA512Context*)&ctx->ctx, bits,
+                bitcount);
+        default: return shaBadParam;
+        }
+    }
+    else {
+        return shaNull;
+    }
+}
+
+/*
+* USHAResult
+*
+* Description:
+*   This function will return the 160-bit message digest into the
+*   Message_Digest array provided by the caller.
+*   NOTE: The first octet of hash is stored in the 0th element,
+*      the last octet of hash in the 19th element.
+*
+* Parameters:
+*   context: [in/out]
+*     The context to use to calculate the SHA-1 hash.
+*   Message_Digest: [out]
+*     Where the digest is returned.
+*
+* Returns:
+*   sha Error Code.
+*
+*/
+int USHAResult(USHAContext *ctx,
+    uint8_t Message_Digest[USHAMaxHashSize])
+{
+    if (ctx) {
+        switch (ctx->whichSha) {
+        case SHA1:
+            return SHA1Result((SHA1Context*)&ctx->ctx, Message_Digest);
+        case SHA224:
+            return SHA224Result((SHA224Context*)&ctx->ctx, Message_Digest);
+        case SHA256:
+            return SHA256Result((SHA256Context*)&ctx->ctx, Message_Digest);
+        case SHA384:
+            return SHA384Result((SHA384Context*)&ctx->ctx, Message_Digest);
+        case SHA512:
+            return SHA512Result((SHA512Context*)&ctx->ctx, Message_Digest);
+        default: return shaBadParam;
+        }
+    }
+    else {
+        return shaNull;
+    }
+}
+
+/*
+* USHABlockSize
+*
+* Description:
+*   This function will return the blocksize for the given SHA
+*   algorithm.
+*
+* Parameters:
+*   whichSha:
+*     which SHA algorithm to query
+*
+* Returns:
+*   block size
+*
+*/
+int USHABlockSize(enum SHAversion whichSha)
+{
+    switch (whichSha) {
+    case SHA1:   return SHA1_Message_Block_Size;
+    case SHA224: return SHA224_Message_Block_Size;
+    case SHA256: return SHA256_Message_Block_Size;
+    case SHA384: return SHA384_Message_Block_Size;
+    default:
+    case SHA512: return SHA512_Message_Block_Size;
+    }
+}
+
+/*
+* USHAHashSize
+*
+* Description:
+*   This function will return the hashsize for the given SHA
+*   algorithm.
+*
+* Parameters:
+*   whichSha:
+*     which SHA algorithm to query
+*
+* Returns:
+*   hash size
+*
+*/
+int USHAHashSize(enum SHAversion whichSha)
+{
+    switch (whichSha) {
+    case SHA1:   return SHA1HashSize;
+    case SHA224: return SHA224HashSize;
+    case SHA256: return SHA256HashSize;
+    case SHA384: return SHA384HashSize;
+    default:
+    case SHA512: return SHA512HashSize;
+    }
+}
+
+/*
+* USHAHashSizeBits
+*
+* Description:
+*   This function will return the hashsize for the given SHA
+*   algorithm, expressed in bits.
+*
+* Parameters:
+*   whichSha:
+*     which SHA algorithm to query
+*
+* Returns:
+*   hash size in bits
+*
+*/
+int USHAHashSizeBits(enum SHAversion whichSha)
+{
+    switch (whichSha) {
+    case SHA1:   return SHA1HashSizeBits;
+    case SHA224: return SHA224HashSizeBits;
+    case SHA256: return SHA256HashSizeBits;
+    case SHA384: return SHA384HashSizeBits;
+    default:
+    case SHA512: return SHA512HashSizeBits;
+    }
+}
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/utf8_checker.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/utf8_checker.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/utf8_checker.c	(revision 453)
@@ -0,0 +1,175 @@
+ // Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifdef __cplusplus
+#include <cstdlib>
+#include <cstdint>
+#else
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdint.h>
+#endif
+
+#include "azure_c_shared_utility/utf8_checker.h"
+
+bool utf8_checker_is_valid_utf8(const unsigned char* utf8_str, size_t length)
+{
+    bool result;
+
+    if (utf8_str == NULL)
+    {
+        /* Codes_SRS_UTF8_CHECKER_01_002: [ If utf8_checker_is_valid_utf8 is called with NULL utf8_str it shall return false. ]*/
+        result = false;
+    }
+    else
+    {
+        size_t pos = 0;
+
+        /* Codes_SRS_UTF8_CHECKER_01_003: [ If length is 0, utf8_checker_is_valid_utf8 shall consider utf8_str to be valid UTF-8 and return true. ]*/
+        result = true;
+
+        while ((result == true) &&
+               (pos < length))
+        {
+            /* Codes_SRS_UTF8_CHECKER_01_001: [ utf8_checker_is_valid_utf8 shall verify that the sequence of chars pointed to by utf8_str represent UTF-8 encoded codepoints. ]*/
+            if ((utf8_str[pos] >> 3) == 0x1E)
+            {
+                /* 4 bytes */
+                /* Codes_SRS_UTF8_CHECKER_01_009: [ 000uuuuu zzzzyyyy yyxxxxxx 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx ]*/
+                uint32_t code_point = (utf8_str[pos] & 0x07);
+
+                pos++;
+                if ((pos < length) &&
+                    ((utf8_str[pos] >> 6) == 0x02))
+                {
+                    code_point <<= 6;
+                    code_point += utf8_str[pos] & 0x3F;
+
+                    pos++;
+                    if ((pos < length) &&
+                        ((utf8_str[pos] >> 6) == 0x02))
+                    {
+                        code_point <<= 6;
+                        code_point += utf8_str[pos] & 0x3F;
+
+                        pos++;
+                        if ((pos < length) &&
+                            ((utf8_str[pos] >> 6) == 0x02))
+                        {
+                            code_point <<= 6;
+                            code_point += utf8_str[pos] & 0x3F;
+
+                            if (code_point <= 0xFFFF)
+                            {
+                                result = false;
+                            }
+                            else
+                            {
+                                /* Codes_SRS_UTF8_CHECKER_01_005: [ On success it shall return true. ]*/
+                                result = true;
+                                pos++;
+                            }
+                        }
+                        else
+                        {
+                            result = false;
+                        }
+                    }
+                    else
+                    {
+                        result = false;
+                    }
+                }
+                else
+                {
+                    result = false;
+                }
+            }
+            else if ((utf8_str[pos] >> 4) == 0x0E)
+            {
+                /* 3 bytes */
+                /* Codes_SRS_UTF8_CHECKER_01_008: [ zzzzyyyy yyxxxxxx 1110zzzz 10yyyyyy 10xxxxxx ]*/
+                uint32_t code_point = (utf8_str[pos] & 0x0F);
+
+                pos++;
+                if ((pos < length) &&
+                    ((utf8_str[pos] >> 6) == 0x02))
+                {
+                    code_point <<= 6;
+                    code_point += utf8_str[pos] & 0x3F;
+
+                    pos++;
+                    if ((pos < length) &&
+                        ((utf8_str[pos] >> 6) == 0x02))
+                    {
+                        code_point <<= 6;
+                        code_point += utf8_str[pos] & 0x3F;
+
+                        if (code_point <= 0x7FF)
+                        {
+                            result = false;
+                        }
+                        else
+                        {
+                            /* Codes_SRS_UTF8_CHECKER_01_005: [ On success it shall return true. ]*/
+                            result = true;
+                            pos++;
+                        }
+                    }
+                    else
+                    {
+                        result = false;
+                    }
+                }
+                else
+                {
+                    result = false;
+                }
+            }
+            else if ((utf8_str[pos] >> 5) == 0x06)
+            {
+                /* 2 bytes */
+                /* Codes_SRS_UTF8_CHECKER_01_007: [ 00000yyy yyxxxxxx 110yyyyy 10xxxxxx ]*/
+                uint32_t code_point = (utf8_str[pos] & 0x1F);
+
+                pos++;
+                if ((pos < length) &&
+                    ((utf8_str[pos] >> 6) == 0x02))
+                {
+                    code_point <<= 6;
+                    code_point += utf8_str[pos] & 0x3F;
+
+                    if (code_point <= 0x7F)
+                    {
+                        result = false;
+                    }
+                    else
+                    {
+                        /* Codes_SRS_UTF8_CHECKER_01_005: [ On success it shall return true. ]*/
+                        result = true;
+                        pos++;
+                    }
+                }
+                else
+                {
+                    result = false;
+                }
+            }
+            else if ((utf8_str[pos] >> 7) == 0x00)
+            {
+                /* 1 byte */
+                /* Codes_SRS_UTF8_CHECKER_01_006: [ 00000000 0xxxxxxx 0xxxxxxx ]*/
+                /* Codes_SRS_UTF8_CHECKER_01_005: [ On success it shall return true. ]*/
+                result = true;
+                pos++;
+            }
+            else
+            {
+                /* error */
+                result = false;
+            }
+        }
+    }
+
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/uuid.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/uuid.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/uuid.c	(revision 453)
@@ -0,0 +1,167 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/uuid.h"
+#include "azure_c_shared_utility/uniqueid.h"
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/xlogging.h"
+
+#define UUID_STRING_LENGTH          36
+#define UUID_STRING_SIZE            (UUID_STRING_LENGTH + 1)
+#define __SUCCESS__                 0
+#define UUID_FORMAT_STRING          "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
+
+int UUID_from_string(const char* uuid_string, UUID_T* uuid)
+{
+    int result;
+
+    // Codes_SRS_UUID_09_007: [ If uuid_string or uuid are NULL, UUID_from_string shall return a non-zero value ]
+    if (uuid_string == NULL || uuid == NULL)
+    {
+        LogError("Invalid argument (uuid_string=%p, uuid=%p)", uuid_string, uuid);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        size_t uuid_string_length = strlen(uuid_string);
+
+        if (uuid_string_length != UUID_STRING_LENGTH)
+        {
+            LogError("Unexpected size for an UUID string (%lu)", (unsigned long)uuid_string_length);
+            result = MU_FAILURE;
+        }
+        else
+        {
+            // Codes_SRS_UUID_09_008: [ Each pair of digits in uuid_string, excluding dashes, shall be read as a single HEX value and saved on the respective position in uuid ]
+            size_t i, j;
+            char* uuid_bytes;
+
+            uuid_bytes = (char *)uuid;
+            // Codes_SRS_UUID_09_010: [ If no failures occur, UUID_from_string shall return zero ]
+            result = __SUCCESS__;
+
+            for (i = 0, j = 0; i < uuid_string_length; )
+            {
+                if (uuid_string[i] == '-')
+                {
+                    i++;
+                }
+                else
+                {
+                    char double_hex_digit[3] = { 0, 0, 0 };
+
+                    (void)memcpy(double_hex_digit, uuid_string + i, 2);
+
+                    if (sscanf(double_hex_digit, "%02hhx", uuid_bytes + j) != 1)
+                    {
+                        // Codes_SRS_UUID_09_009: [ If uuid fails to be generated, UUID_from_string shall return a non-zero value ]
+                        LogError("Failed decoding UUID string (%lu)", (unsigned long)i);
+                        result = MU_FAILURE;
+                        break;
+                    }
+                    else
+                    {
+                        i += 2;
+                        j++;
+                    }
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+char* UUID_to_string(const UUID_T* uuid)
+{
+    char* result;
+
+    // Codes_SRS_UUID_09_011: [ If uuid is NULL, UUID_to_string shall return a non-zero value ]
+    if (uuid == NULL)
+    {
+        LogError("Invalid argument (uuid is NULL)");
+        result = NULL;
+    }
+    // Codes_SRS_UUID_09_012: [ UUID_to_string shall allocate a valid UUID string (uuid_string) as per RFC 4122 ]
+    else if ((result = (char*)malloc(sizeof(char) * UUID_STRING_SIZE)) == NULL)
+    {
+        // Codes_SRS_UUID_09_013: [ If uuid_string fails to be allocated, UUID_to_string shall return NULL ]
+        LogError("Failed allocating UUID string");
+    }
+    else
+    {
+        unsigned char* uuid_bytes;
+        int number_of_chars_written;
+
+        uuid_bytes = (unsigned char*)uuid;
+
+        // Codes_SRS_UUID_09_014: [ Each character in uuid shall be written in the respective positions of uuid_string as a 2-digit HEX value ]  
+        number_of_chars_written = sprintf(result, "%" PRI_UUID,
+            UUID_FORMAT_VALUES(uuid_bytes));
+
+        if (number_of_chars_written != UUID_STRING_LENGTH)
+        {
+            // Tests_SRS_UUID_09_015: [ If uuid_string fails to be set, UUID_to_string shall return NULL ]
+            LogError("Failed encoding UUID string");
+            free(result);
+            result = NULL;
+        }
+    }
+
+    // Codes_SRS_UUID_09_016: [ If no failures occur, UUID_to_string shall return uuid_string ]
+    return result;
+}
+
+int UUID_generate(UUID_T* uuid)
+{
+    int result;
+
+    // Codes_SRS_UUID_09_001: [ If uuid is NULL, UUID_generate shall return a non-zero value ]
+    if (uuid == NULL)
+    {
+        LogError("Invalid argument (uuid is NULL)");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        char* uuid_string;
+
+        if ((uuid_string = (char*)malloc(sizeof(char) * UUID_STRING_SIZE)) == NULL)
+        {
+            // Codes_SRS_UUID_09_003: [ If the UUID string fails to be obtained, UUID_generate shall fail and return a non-zero value ]
+            LogError("Failed allocating UUID string");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            (void)memset(uuid_string, 0, sizeof(char) * UUID_STRING_SIZE);
+
+            // Codes_SRS_UUID_09_002: [ UUID_generate shall obtain an UUID string from UniqueId_Generate ]
+            if (UniqueId_Generate(uuid_string, UUID_STRING_SIZE) != UNIQUEID_OK)
+            {
+                // Codes_SRS_UUID_09_003: [ If the UUID string fails to be obtained, UUID_generate shall fail and return a non-zero value ]
+                LogError("Failed generating UUID");
+                result = MU_FAILURE;
+            }
+            // Codes_SRS_UUID_09_004: [ The UUID string shall be parsed into an UUID_T type (16 unsigned char array) and filled in uuid ]
+            else if (UUID_from_string(uuid_string, uuid) != 0)
+            {
+                // Codes_SRS_UUID_09_005: [ If uuid fails to be set, UUID_generate shall fail and return a non-zero value ]
+                LogError("Failed parsing UUID string");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                // Codes_SRS_UUID_09_006: [ If no failures occur, UUID_generate shall return zero ]
+                result = __SUCCESS__;
+            }
+
+            free(uuid_string);
+        }
+    }
+
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/uws_client.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/uws_client.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/uws_client.c	(revision 453)
@@ -0,0 +1,2237 @@
+ // Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <limits.h>
+#include <ctype.h>
+#include <limits.h>
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/uws_client.h"
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/xio.h"
+#include "azure_c_shared_utility/singlylinkedlist.h"
+#include "azure_c_shared_utility/socketio.h"
+#include "azure_c_shared_utility/platform.h"
+#include "azure_c_shared_utility/tlsio.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/buffer_.h"
+#include "azure_c_shared_utility/uws_frame_encoder.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/utf8_checker.h"
+#include "azure_c_shared_utility/gb_rand.h"
+#include "azure_c_shared_utility/azure_base64.h"
+#include "azure_c_shared_utility/optionhandler.h"
+#include "azure_c_shared_utility/map.h"
+#include "azure_c_shared_utility/shared_util_options.h"
+
+static const char* UWS_CLIENT_OPTIONS = "uWSClientOptions";
+
+static const char* HTTP_HEADER_KEY_VALUE_SEPARATOR = ": ";
+static const size_t HTTP_HEADER_KEY_VALUE_SEPARATOR_LENGTH = 2;
+static const char* HTTP_HEADER_TERMINATOR = "\r\n";
+static const size_t HTTP_HEADER_TERMINATOR_LENGTH = 2;
+
+/* Requirements not needed as they are optional:
+Codes_SRS_UWS_CLIENT_01_254: [ If an endpoint receives a Ping frame and has not yet sent Pong frame(s) in response to previous Ping frame(s), the endpoint MAY elect to send a Pong frame for only the most recently processed Ping frame. ]
+Codes_SRS_UWS_CLIENT_01_255: [ A Pong frame MAY be sent unsolicited. ]
+Codes_SRS_UWS_CLIENT_01_256: [ A response to an unsolicited Pong frame is not expected. ]
+*/
+
+/* Requirements satisfied by the underlying TLS/socket stack
+Codes_SRS_UWS_CLIENT_01_362: [ To achieve reasonable levels of protection, clients should use only Strong TLS algorithms. ]
+Codes_SRS_UWS_CLIENT_01_289: [ An endpoint SHOULD use a method that cleanly closes the TCP connection, as well as the TLS session, if applicable, discarding any trailing bytes that may have been received. ]
+Codes_SRS_UWS_CLIENT_01_078: [ Otherwise, all further communication on this channel MUST run through the encrypted tunnel [RFC5246]. ]
+Codes_SRS_UWS_CLIENT_01_141: [ masking is done whether or not the WebSocket Protocol is running over TLS. ]
+*/
+
+/* Requirements satisfied by the way the APIs are designed:
+Codes_SRS_UWS_CLIENT_01_211: [One implication of this is that in absence of extensions, senders and receivers must not depend on the presence of specific frame boundaries.]
+*/
+
+typedef enum UWS_STATE_TAG
+{
+    UWS_STATE_CLOSED,
+    UWS_STATE_OPENING_UNDERLYING_IO,
+    UWS_STATE_WAITING_FOR_UPGRADE_RESPONSE,
+    UWS_STATE_OPEN,
+    UWS_STATE_CLOSING_WAITING_FOR_CLOSE,
+    UWS_STATE_CLOSING_SENDING_CLOSE,
+    UWS_STATE_CLOSING_UNDERLYING_IO,
+    UWS_STATE_ERROR
+} UWS_STATE;
+
+typedef struct WS_INSTANCE_PROTOCOL_TAG
+{
+    char* protocol;
+} WS_INSTANCE_PROTOCOL;
+
+typedef struct WS_PENDING_SEND_TAG
+{
+    ON_WS_SEND_FRAME_COMPLETE on_ws_send_frame_complete;
+    void* context;
+    UWS_CLIENT_HANDLE uws_client;
+} WS_PENDING_SEND;
+
+typedef struct UWS_CLIENT_INSTANCE_TAG
+{
+    SINGLYLINKEDLIST_HANDLE pending_sends;
+    XIO_HANDLE underlying_io;
+    char* hostname;
+    char* resource_name;
+    WS_INSTANCE_PROTOCOL* protocols;
+    size_t protocol_count;
+    int port;
+    MAP_HANDLE request_headers;
+    UWS_STATE uws_state;
+    ON_WS_OPEN_COMPLETE on_ws_open_complete;
+    void* on_ws_open_complete_context;
+    ON_WS_FRAME_RECEIVED on_ws_frame_received;
+    void* on_ws_frame_received_context;
+    ON_WS_PEER_CLOSED on_ws_peer_closed;
+    void* on_ws_peer_closed_context;
+    ON_WS_ERROR on_ws_error;
+    void* on_ws_error_context;
+    ON_WS_CLOSE_COMPLETE on_ws_close_complete;
+    void* on_ws_close_complete_context;
+    unsigned char* stream_buffer;
+    size_t stream_buffer_count;
+    unsigned char* fragment_buffer;
+    size_t fragment_buffer_count;
+    unsigned char fragmented_frame_type;
+} UWS_CLIENT_INSTANCE;
+
+/* Codes_SRS_UWS_CLIENT_01_360: [ Connection confidentiality and integrity is provided by running the WebSocket Protocol over TLS (wss URIs). ]*/
+/* Codes_SRS_UWS_CLIENT_01_361: [ WebSocket implementations MUST support TLS and SHOULD employ it when communicating with their peers. ]*/
+/* Codes_SRS_UWS_CLIENT_01_063: [ A client will need to supply a /host/, /port/, /resource name/, and a /secure/ flag, which are the components of a WebSocket URI as discussed in Section 3, along with a list of /protocols/ and /extensions/ to be used. ]*/
+UWS_CLIENT_HANDLE uws_client_create(const char* hostname, unsigned int port, const char* resource_name, bool use_ssl, const WS_PROTOCOL* protocols, size_t protocol_count)
+{
+    UWS_CLIENT_HANDLE result;
+
+    /* Codes_SRS_UWS_CLIENT_01_002: [ If any of the arguments hostname and resource_name is NULL then uws_client_create shall return NULL. ]*/
+    if ((hostname == NULL) ||
+        (resource_name == NULL) ||
+        /* Codes_SRS_UWS_CLIENT_01_411: [ If protocol_count is non zero and protocols is NULL then uws_client_create shall fail and return NULL. ]*/
+        ((protocols == NULL) && (protocol_count > 0)))
+    {
+        LogError("Invalid arguments: hostname = %p, resource_name = %p, protocols = %p, protocol_count = %lu", hostname, resource_name, protocols, (unsigned long)protocol_count);
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_UWS_CLIENT_01_412: [ If the protocol member of any of the items in the protocols argument is NULL, then uws_client_create shall fail and return NULL. ]*/
+        size_t i;
+        for (i = 0; i < protocol_count; i++)
+        {
+            if (protocols[i].protocol == NULL)
+            {
+                break;
+            }
+        }
+
+        if (i < protocol_count)
+        {
+            LogError("Protocol index %lu has NULL name", (unsigned long)i);
+            result = NULL;
+        }
+        else
+        {
+            /* Codes_SRS_UWS_CLIENT_01_001: [uws_client_create shall create an instance of uws and return a non-NULL handle to it.]*/
+            result = (UWS_CLIENT_HANDLE)malloc(sizeof(UWS_CLIENT_INSTANCE));
+            if (result == NULL)
+            {
+                /* Codes_SRS_UWS_CLIENT_01_003: [ If allocating memory for the new uws instance fails then uws_client_create shall return NULL. ]*/
+                LogError("Could not allocate uWS instance");
+            }
+            else
+            {
+                (void)memset(result, 0, sizeof(UWS_CLIENT_INSTANCE));
+
+                /* Codes_SRS_UWS_CLIENT_01_004: [ The argument hostname shall be copied for later use. ]*/
+                if (mallocAndStrcpy_s(&result->hostname, hostname) != 0)
+                {
+                    /* Codes_SRS_UWS_CLIENT_01_392: [ If allocating memory for the copy of the hostname argument fails, then uws_client_create shall return NULL. ]*/
+                    LogError("Could not copy hostname.");
+                    free(result);
+                    result = NULL;
+                }
+                else
+                {
+                    /* Codes_SRS_UWS_CLIENT_01_404: [ The argument resource_name shall be copied for later use. ]*/
+                    if (mallocAndStrcpy_s(&result->resource_name, resource_name) != 0)
+                    {
+                        /* Codes_SRS_UWS_CLIENT_01_405: [ If allocating memory for the copy of the resource argument fails, then uws_client_create shall return NULL. ]*/
+                        LogError("Could not copy resource.");
+                        free(result->hostname);
+                        free(result);
+                        result = NULL;
+                    }
+                    else if ((result->request_headers = Map_Create(NULL)) == NULL)
+                    {
+                        LogError("Failed allocating MAP for request headers");
+                        free(result->resource_name);
+                        free(result->hostname);
+                        free(result);
+                        result = NULL;
+                    }
+                    else
+                    {
+                        /* Codes_SRS_UWS_CLIENT_01_017: [ uws_client_create shall create a pending send IO list that is to be used to queue send packets by calling singlylinkedlist_create. ]*/
+                        result->pending_sends = singlylinkedlist_create();
+                        if (result->pending_sends == NULL)
+                        {
+                            /* Codes_SRS_UWS_CLIENT_01_018: [ If singlylinkedlist_create fails then uws_client_create shall fail and return NULL. ]*/
+                            LogError("Could not allocate pending send frames list");
+                            Map_Destroy(result->request_headers);
+                            free(result->resource_name);
+                            free(result->hostname);
+                            free(result);
+                            result = NULL;
+                        }
+                        else
+                        {
+                            if (use_ssl == true)
+                            {
+                                TLSIO_CONFIG tlsio_config;
+
+                                /* Codes_SRS_UWS_CLIENT_01_006: [ If use_ssl is true then uws_client_create shall obtain the interface used to create a tlsio instance by calling platform_get_default_tlsio. ]*/
+                                /* Codes_SRS_UWS_CLIENT_01_076: [ If /secure/ is true, the client MUST perform a TLS handshake over the connection after opening the connection and before sending the handshake data [RFC2818]. ]*/
+                                const IO_INTERFACE_DESCRIPTION* tlsio_interface = platform_get_default_tlsio();
+                                if (tlsio_interface == NULL)
+                                {
+                                    /* Codes_SRS_UWS_CLIENT_01_007: [ If obtaining the underlying IO interface fails, then uws_client_create shall fail and return NULL. ]*/
+                                    LogError("NULL TLSIO interface description");
+                                    result->underlying_io = NULL;
+                                }
+                                else
+                                {
+                                    SOCKETIO_CONFIG socketio_config;
+
+                                    /* Codes_SRS_UWS_CLIENT_01_013: [ The create arguments for the tls IO (when use_ssl is 1) shall have: ]*/
+                                    /* Codes_SRS_UWS_CLIENT_01_014: [ - hostname set to the hostname argument passed to uws_client_create. ]*/
+                                    /* Codes_SRS_UWS_CLIENT_01_015: [ - port set to the port argument passed to uws_client_create. ]*/
+                                    socketio_config.hostname = hostname;
+                                    socketio_config.port = port;
+                                    socketio_config.accepted_socket = NULL;
+
+                                    tlsio_config.hostname = hostname;
+                                    tlsio_config.port = port;
+                                    tlsio_config.underlying_io_interface = socketio_get_interface_description();
+                                    tlsio_config.underlying_io_parameters = &socketio_config;
+
+                                    result->underlying_io = xio_create(tlsio_interface, &tlsio_config);
+                                    if (result->underlying_io == NULL)
+                                    {
+                                        LogError("Cannot create underlying TLS IO.");
+                                    }
+                                    else
+                                    {
+                                        // Set the underlying socket to turn on renegotiation
+                                        bool set_renegotiation = true;
+                                        xio_setoption(result->underlying_io, OPTION_SET_TLS_RENEGOTIATION, &set_renegotiation);
+                                    }
+                                }
+                            }
+                            else
+                            {
+                                SOCKETIO_CONFIG socketio_config;
+                                /* Codes_SRS_UWS_CLIENT_01_005: [ If use_ssl is false then uws_client_create shall obtain the interface used to create a socketio instance by calling socketio_get_interface_description. ]*/
+                                const IO_INTERFACE_DESCRIPTION* socketio_interface = socketio_get_interface_description();
+                                if (socketio_interface == NULL)
+                                {
+                                    /* Codes_SRS_UWS_CLIENT_01_007: [ If obtaining the underlying IO interface fails, then uws_client_create shall fail and return NULL. ]*/
+                                    LogError("NULL socketio interface description");
+                                    result->underlying_io = NULL;
+                                }
+                                else
+                                {
+                                    /* Codes_SRS_UWS_CLIENT_01_010: [ The create arguments for the socket IO (when use_ssl is 0) shall have: ]*/
+                                    /* Codes_SRS_UWS_CLIENT_01_011: [ - hostname set to the hostname argument passed to uws_client_create. ]*/
+                                    /* Codes_SRS_UWS_CLIENT_01_012: [ - port set to the port argument passed to uws_client_create. ]*/
+                                    socketio_config.hostname = hostname;
+                                    socketio_config.port = port;
+                                    socketio_config.accepted_socket = NULL;
+
+                                    /* Codes_SRS_UWS_CLIENT_01_008: [ The obtained interface shall be used to create the IO used as underlying IO by the newly created uws instance. ]*/
+                                    /* Codes_SRS_UWS_CLIENT_01_009: [ The underlying IO shall be created by calling xio_create. ]*/
+                                    result->underlying_io = xio_create(socketio_interface, &socketio_config);
+                                    if (result->underlying_io == NULL)
+                                    {
+                                        LogError("Cannot create underlying socket IO.");
+                                    }
+                                }
+                            }
+
+                            if (result->underlying_io == NULL)
+                            {
+                                /* Codes_SRS_UWS_CLIENT_01_016: [ If xio_create fails, then uws_client_create shall fail and return NULL. ]*/
+                                singlylinkedlist_destroy(result->pending_sends);
+                                Map_Destroy(result->request_headers);
+                                free(result->resource_name);
+                                free(result->hostname);
+                                free(result);
+                                result = NULL;
+                            }
+                            else
+                            {
+                                result->uws_state = UWS_STATE_CLOSED;
+                                /* Codes_SRS_UWS_CLIENT_01_403: [ The argument port shall be copied for later use. ]*/
+                                result->port = port;
+
+                                result->fragmented_frame_type = WS_FRAME_TYPE_UNKNOWN;
+
+                                result->protocol_count = protocol_count;
+
+                                /* Codes_SRS_UWS_CLIENT_01_410: [ The protocols argument shall be allowed to be NULL, in which case no protocol is to be specified by the client in the upgrade request. ]*/
+                                if (protocols == NULL)
+                                {
+                                    result->protocols = NULL;
+                                }
+                                else
+                                {
+                                    result->protocols = (WS_INSTANCE_PROTOCOL*)malloc(sizeof(WS_INSTANCE_PROTOCOL) * protocol_count);
+                                    if (result->protocols == NULL)
+                                    {
+                                        /* Codes_SRS_UWS_CLIENT_01_414: [ If allocating memory for the copied protocol information fails then uws_client_create shall fail and return NULL. ]*/
+                                        LogError("Cannot allocate memory for the protocols array.");
+                                        xio_destroy(result->underlying_io);
+                                        singlylinkedlist_destroy(result->pending_sends);
+                                        Map_Destroy(result->request_headers);
+                                        free(result->resource_name);
+                                        free(result->hostname);
+                                        free(result);
+                                        result = NULL;
+                                    }
+                                    else
+                                    {
+                                        /* Codes_SRS_UWS_CLIENT_01_413: [ The protocol information indicated by protocols and protocol_count shall be copied for later use (for constructing the upgrade request). ]*/
+                                        for (i = 0; i < protocol_count; i++)
+                                        {
+                                            if (mallocAndStrcpy_s(&result->protocols[i].protocol, protocols[i].protocol) != 0)
+                                            {
+                                                /* Codes_SRS_UWS_CLIENT_01_414: [ If allocating memory for the copied protocol information fails then uws_client_create shall fail and return NULL. ]*/
+                                                LogError("Cannot allocate memory for the protocol index %u.", (unsigned int)i);
+                                                break;
+                                            }
+                                        }
+
+                                        if (i < protocol_count)
+                                        {
+                                            size_t j;
+
+                                            for (j = 0; j < i; j++)
+                                            {
+                                                free(result->protocols[j].protocol);
+                                            }
+
+                                            free(result->protocols);
+                                            xio_destroy(result->underlying_io);
+                                            singlylinkedlist_destroy(result->pending_sends);
+                                            Map_Destroy(result->request_headers);
+                                            free(result->resource_name);
+                                            free(result->hostname);
+                                            free(result);
+                                            result = NULL;
+                                        }
+                                        else
+                                        {
+                                            result->protocol_count = protocol_count;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+UWS_CLIENT_HANDLE uws_client_create_with_io(const IO_INTERFACE_DESCRIPTION* io_interface, void* io_create_parameters, const char* hostname, unsigned int port, const char* resource_name, const WS_PROTOCOL* protocols, size_t protocol_count)
+{
+    UWS_CLIENT_HANDLE result;
+
+    /* Codes_SRS_UWS_CLIENT_01_516: [ If any of the arguments io_interface, hostname and resource_name is NULL then uws_client_create_with_io shall return NULL. ]*/
+    if ((hostname == NULL) ||
+        (io_interface == NULL) ||
+        (resource_name == NULL) ||
+        /* Codes_SRS_UWS_CLIENT_01_525: [ If protocol_count is non zero and protocols is NULL then uws_client_create_with_io shall fail and return NULL. ]*/
+        ((protocols == NULL) && (protocol_count > 0)))
+    {
+        LogError("Invalid arguments: io_interface = %p, resource_name = %p, protocols = %p, protocol_count = %lu", io_interface, resource_name, protocols, (unsigned long)protocol_count);
+        result = NULL;
+    }
+    else
+    {
+        size_t i;
+        for (i = 0; i < protocol_count; i++)
+        {
+            if (protocols[i].protocol == NULL)
+            {
+                break;
+            }
+        }
+
+        if (i < protocol_count)
+        {
+            /* Codes_SRS_UWS_CLIENT_01_526: [ If the protocol member of any of the items in the protocols argument is NULL, then uws_client_create_with_io shall fail and return NULL. ]*/
+            LogError("Protocol index %lu has NULL name", (unsigned long)i);
+            result = NULL;
+        }
+        else
+        {
+            /* Codes_SRS_UWS_CLIENT_01_515: [ uws_client_create_with_io shall create an instance of uws and return a non-NULL handle to it. ]*/
+            result = (UWS_CLIENT_HANDLE)malloc(sizeof(UWS_CLIENT_INSTANCE));
+            if (result == NULL)
+            {
+                /* Codes_SRS_UWS_CLIENT_01_517: [ If allocating memory for the new uws instance fails then uws_client_create_with_io shall return NULL. ]*/
+                LogError("Could not allocate uWS instance");
+            }
+            else
+            {
+                memset(result, 0, sizeof(UWS_CLIENT_INSTANCE));
+
+                /* Codes_SRS_UWS_CLIENT_01_518: [ The argument hostname shall be copied for later use. ]*/
+                if (mallocAndStrcpy_s(&result->hostname, hostname) != 0)
+                {
+                    /* Codes_SRS_UWS_CLIENT_01_519: [ If allocating memory for the copy of the hostname argument fails, then uws_client_create shall return NULL. ]*/
+                    LogError("Could not copy hostname.");
+                    free(result);
+                    result = NULL;
+                }
+                else
+                {
+                    /* Codes_SRS_UWS_CLIENT_01_523: [ The argument resource_name shall be copied for later use. ]*/
+                    if (mallocAndStrcpy_s(&result->resource_name, resource_name) != 0)
+                    {
+                        /* Codes_SRS_UWS_CLIENT_01_529: [ If allocating memory for the copy of the resource_name argument fails, then uws_client_create_with_io shall return NULL. ]*/
+                        LogError("Could not copy resource.");
+                        free(result->hostname);
+                        free(result);
+                        result = NULL;
+                    }
+                    else if ((result->request_headers = Map_Create(NULL)) == NULL)
+                    {
+                        LogError("Failed allocating MAP for request headers");
+                        free(result->resource_name);
+                        free(result->hostname);
+                        free(result);
+                        result = NULL;
+                    }
+                    else
+                    {
+                        /* Codes_SRS_UWS_CLIENT_01_530: [ uws_client_create_with_io shall create a pending send IO list that is to be used to queue send packets by calling singlylinkedlist_create. ]*/
+                        result->pending_sends = singlylinkedlist_create();
+                        if (result->pending_sends == NULL)
+                        {
+                            /* Codes_SRS_UWS_CLIENT_01_531: [ If singlylinkedlist_create fails then uws_client_create_with_io shall fail and return NULL. ]*/
+                            LogError("Could not allocate pending send frames list");
+                            Map_Destroy(result->request_headers);
+                            free(result->resource_name);
+                            free(result->hostname);
+                            free(result);
+                            result = NULL;
+                        }
+                        else
+                        {
+                            /* Codes_SRS_UWS_CLIENT_01_521: [ The underlying IO shall be created by calling xio_create, while passing as arguments the io_interface and io_create_parameters argument values. ]*/
+                            result->underlying_io = xio_create(io_interface, io_create_parameters);
+                            if (result->underlying_io == NULL)
+                            {
+                                /* Codes_SRS_UWS_CLIENT_01_522: [ If xio_create fails, then uws_client_create_with_io shall fail and return NULL. ]*/
+                                LogError("Cannot create underlying IO.");
+                                singlylinkedlist_destroy(result->pending_sends);
+                                Map_Destroy(result->request_headers);
+                                free(result->resource_name);
+                                free(result->hostname);
+                                free(result);
+                                result = NULL;
+                            }
+                            else
+                            {
+                                // Set the underlying socket to turn on renegotiation
+                                bool set_renegotiation = true;
+                                (void)xio_setoption(result->underlying_io, OPTION_SET_TLS_RENEGOTIATION, &set_renegotiation);
+
+                                result->uws_state = UWS_STATE_CLOSED;
+
+                                /* Codes_SRS_UWS_CLIENT_01_520: [ The argument port shall be copied for later use. ]*/
+                                result->port = port;
+
+                                result->fragmented_frame_type = WS_FRAME_TYPE_UNKNOWN;
+
+                                result->protocol_count = protocol_count;
+
+                                /* Codes_SRS_UWS_CLIENT_01_524: [ The protocols argument shall be allowed to be NULL, in which case no protocol is to be specified by the client in the upgrade request. ]*/
+                                if (protocols == NULL)
+                                {
+                                    result->protocols = NULL;
+                                }
+                                else
+                                {
+                                    result->protocols = (WS_INSTANCE_PROTOCOL*)malloc(sizeof(WS_INSTANCE_PROTOCOL) * protocol_count);
+                                    if (result->protocols == NULL)
+                                    {
+                                        /* Codes_SRS_UWS_CLIENT_01_414: [ If allocating memory for the copied protocol information fails then uws_client_create shall fail and return NULL. ]*/
+                                        LogError("Cannot allocate memory for the protocols array.");
+                                        xio_destroy(result->underlying_io);
+                                        singlylinkedlist_destroy(result->pending_sends);
+                                        Map_Destroy(result->request_headers);
+                                        free(result->resource_name);
+                                        free(result->hostname);
+                                        free(result);
+                                        result = NULL;
+                                    }
+                                    else
+                                    {
+                                        /* Codes_SRS_UWS_CLIENT_01_527: [ The protocol information indicated by protocols and protocol_count shall be copied for later use (for constructing the upgrade request). ]*/
+                                        for (i = 0; i < protocol_count; i++)
+                                        {
+                                            if (mallocAndStrcpy_s(&result->protocols[i].protocol, protocols[i].protocol) != 0)
+                                            {
+                                                /* Codes_SRS_UWS_CLIENT_01_528: [ If allocating memory for the copied protocol information fails then uws_client_create_with_io shall fail and return NULL. ]*/
+                                                LogError("Cannot allocate memory for the protocol index %u.", (unsigned int)i);
+                                                break;
+                                            }
+                                        }
+
+                                        if (i < protocol_count)
+                                        {
+                                            size_t j;
+
+                                            for (j = 0; j < i; j++)
+                                            {
+                                                free(result->protocols[j].protocol);
+                                            }
+
+                                            free(result->protocols);
+                                            xio_destroy(result->underlying_io);
+                                            singlylinkedlist_destroy(result->pending_sends);
+                                            Map_Destroy(result->request_headers);
+                                            free(result->resource_name);
+                                            free(result->hostname);
+                                            free(result);
+                                            result = NULL;
+                                        }
+                                        else
+                                        {
+                                            result->protocol_count = protocol_count;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+void uws_client_destroy(UWS_CLIENT_HANDLE uws_client)
+{
+    /* Codes_SRS_UWS_CLIENT_01_020: [ If uws_client is NULL, uws_client_destroy shall do nothing. ]*/
+    if (uws_client == NULL)
+    {
+        LogError("NULL uws handle");
+    }
+    else
+    {
+        free(uws_client->stream_buffer);
+        free(uws_client->fragment_buffer);
+
+        /* Codes_SRS_UWS_CLIENT_01_021: [ uws_client_destroy shall perform a close action if the uws instance has already been open. ]*/
+        switch (uws_client->uws_state)
+        {
+        default:
+            break;
+
+        case UWS_STATE_OPEN:
+        case UWS_STATE_ERROR:
+            uws_client_close_async(uws_client, NULL, NULL);
+            break;
+        }
+
+        if (uws_client->protocol_count > 0)
+        {
+            size_t i;
+
+            /* Codes_SRS_UWS_CLIENT_01_437: [ uws_client_destroy shall free the protocols array allocated in uws_client_create. ]*/
+            for (i = 0; i < uws_client->protocol_count; i++)
+            {
+                free(uws_client->protocols[i].protocol);
+            }
+
+            free(uws_client->protocols);
+        }
+
+        /* Codes_SRS_UWS_CLIENT_01_019: [ uws_client_destroy shall free all resources associated with the uws instance. ]*/
+        /* Codes_SRS_UWS_CLIENT_01_023: [ uws_client_destroy shall ensure the underlying IO created in uws_client_open_async is destroyed by calling xio_destroy. ]*/
+        if (uws_client->underlying_io != NULL)
+        {
+            xio_destroy(uws_client->underlying_io);
+            uws_client->underlying_io = NULL;
+        }
+
+        /* Codes_SRS_UWS_CLIENT_01_024: [ uws_client_destroy shall free the list used to track the pending sends by calling singlylinkedlist_destroy. ]*/
+        singlylinkedlist_destroy(uws_client->pending_sends);
+        free(uws_client->resource_name);
+        free(uws_client->hostname);
+        Map_Destroy(uws_client->request_headers);
+        free(uws_client);
+    }
+}
+
+static void indicate_ws_open_complete_error(UWS_CLIENT_INSTANCE* uws_client, WS_OPEN_RESULT ws_open_result)
+{
+    /* Codes_SRS_UWS_CLIENT_01_409: [ After any error is indicated by on_ws_open_complete, a subsequent uws_client_open_async shall be possible. ]*/
+    uws_client->uws_state = UWS_STATE_CLOSED;
+    uws_client->on_ws_open_complete(uws_client->on_ws_open_complete_context, ws_open_result);
+}
+
+static void indicate_ws_open_complete_error_and_close(UWS_CLIENT_INSTANCE* uws_client, WS_OPEN_RESULT ws_open_result)
+{
+    (void)xio_close(uws_client->underlying_io, NULL, NULL);
+    indicate_ws_open_complete_error(uws_client, ws_open_result);
+}
+
+static void indicate_ws_error(UWS_CLIENT_INSTANCE* uws_client, WS_ERROR error_code)
+{
+    uws_client->uws_state = UWS_STATE_ERROR;
+    uws_client->on_ws_error(uws_client->on_ws_error_context, error_code);
+}
+
+static void indicate_ws_close_complete(UWS_CLIENT_INSTANCE* uws_client)
+{
+    uws_client->uws_state = UWS_STATE_CLOSED;
+
+    /* Codes_SRS_UWS_CLIENT_01_496: [ If the close was initiated by the peer no on_ws_close_complete shall be called. ]*/
+    if (uws_client->on_ws_close_complete != NULL)
+    {
+        /* Codes_SRS_UWS_CLIENT_01_491: [ When calling on_ws_close_complete callback, the on_ws_close_complete_context argument shall be passed to it. ]*/
+        uws_client->on_ws_close_complete(uws_client->on_ws_close_complete_context);
+    }
+}
+
+// This callback usage needs to be either verified and commented or integrated into
+// the state machine.
+static void unchecked_on_send_complete(void* context, IO_SEND_RESULT send_result)
+{
+    (void)context;
+    (void)send_result;
+}
+
+static int send_close_frame(UWS_CLIENT_INSTANCE* uws_client, unsigned int close_error_code)
+{
+    unsigned char* close_frame;
+    unsigned char close_frame_payload[2];
+    size_t close_frame_length;
+    int result;
+    BUFFER_HANDLE close_frame_buffer;
+
+    close_frame_payload[0] = (unsigned char)(close_error_code >> 8);
+    close_frame_payload[1] = (unsigned char)(close_error_code & 0xFF);
+
+    /* Codes_SRS_UWS_CLIENT_01_140: [ To avoid confusing network intermediaries (such as intercepting proxies) and for security reasons that are further discussed in Section 10.3, a client MUST mask all frames that it sends to the server (see Section 5.3 for further details). ]*/
+    close_frame_buffer = uws_frame_encoder_encode(WS_CLOSE_FRAME, close_frame_payload, sizeof(close_frame_payload), true, true, 0);
+    if (close_frame_buffer == NULL)
+    {
+        LogError("Encoding of CLOSE failed.");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        close_frame = BUFFER_u_char(close_frame_buffer);
+        close_frame_length = BUFFER_length(close_frame_buffer);
+
+        /* Codes_SRS_UWS_CLIENT_01_471: [ The callback on_underlying_io_close_sent shall be passed as argument to xio_send. ]*/
+        if (xio_send(uws_client->underlying_io, close_frame, close_frame_length, unchecked_on_send_complete, NULL) != 0)
+        {
+            LogError("Sending CLOSE frame failed.");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            result = 0;
+        }
+
+        BUFFER_delete(close_frame_buffer);
+    }
+
+    return result;
+}
+
+static void indicate_ws_error_and_close(UWS_CLIENT_INSTANCE* uws_client, WS_ERROR error_code, unsigned int close_error_code)
+{
+    uws_client->uws_state = UWS_STATE_ERROR;
+
+    (void)send_close_frame(uws_client, close_error_code);
+
+    uws_client->on_ws_error(uws_client->on_ws_error_context, error_code);
+}
+
+static char* get_request_headers(MAP_HANDLE headers)
+{
+    char* result;
+    const char* const* keys;
+    const char* const* values;
+    size_t count;
+
+    if (Map_GetInternals(headers, &keys, &values, &count) != MAP_OK)
+    {
+        LogError("Failed getting the request headers");
+        result = NULL;
+    }
+    else
+    {
+        size_t length = 0;
+        size_t i;
+
+        for (i = 0; i < count; i++)
+        {
+            // 4 = 2 (": ") + 2 ("\r\n")
+            length += strlen(keys[i]) + strlen(values[i]) + 4;
+        }
+
+        if ((result = (char*)malloc(sizeof(char) * (length + 1))) == NULL)
+        {
+            LogError("Failed allocating string for request headers");
+            result = NULL;
+        }
+        else
+        {
+            size_t position = 0;
+
+            for (i = 0; i < count; i++)
+            {
+                size_t key_length = strlen(keys[i]);
+                size_t value_length = strlen(values[i]);
+
+                (void)memcpy(result + position, keys[i], key_length);
+                position += key_length;
+                (void)memcpy(result + position, HTTP_HEADER_KEY_VALUE_SEPARATOR, HTTP_HEADER_KEY_VALUE_SEPARATOR_LENGTH);
+                position += HTTP_HEADER_KEY_VALUE_SEPARATOR_LENGTH;
+                (void)memcpy(result + position, values[i], value_length);
+                position += value_length;
+                (void)memcpy(result + position, HTTP_HEADER_TERMINATOR, HTTP_HEADER_TERMINATOR_LENGTH);
+                position += HTTP_HEADER_TERMINATOR_LENGTH;
+            }
+
+            result[position] = '\0';
+        }
+    }
+
+    return result;
+}
+
+static void on_underlying_io_open_complete(void* context, IO_OPEN_RESULT open_result)
+{
+    UWS_CLIENT_HANDLE uws_client = (UWS_CLIENT_HANDLE)context;
+    /* Codes_SRS_UWS_CLIENT_01_401: [ If on_underlying_io_open_complete is called with a NULL context, on_underlying_io_open_complete shall do nothing. ]*/
+    if (uws_client == NULL)
+    {
+        LogError("NULL context");
+    }
+    else
+    {
+        switch (uws_client->uws_state)
+        {
+        default:
+        case UWS_STATE_WAITING_FOR_UPGRADE_RESPONSE:
+            /* Codes_SRS_UWS_CLIENT_01_407: [ When on_underlying_io_open_complete is called when the uws instance has send the upgrade request but it is waiting for the response, an error shall be reported to the user by calling the on_ws_open_complete with WS_OPEN_ERROR_MULTIPLE_UNDERLYING_IO_OPEN_EVENTS. ]*/
+            LogError("underlying on_io_open_complete was called again after upgrade request was sent.");
+            indicate_ws_open_complete_error_and_close(uws_client, WS_OPEN_ERROR_MULTIPLE_UNDERLYING_IO_OPEN_EVENTS);
+            break;
+        case UWS_STATE_OPENING_UNDERLYING_IO:
+            switch (open_result)
+            {
+            default:
+            case IO_OPEN_ERROR:
+                /* Codes_SRS_UWS_CLIENT_01_369: [ When on_underlying_io_open_complete is called with IO_OPEN_ERROR while uws is OPENING (uws_client_open_async was called), uws shall report that the open failed by calling the on_ws_open_complete callback passed to uws_client_open_async with WS_OPEN_ERROR_UNDERLYING_IO_OPEN_FAILED. ]*/
+                indicate_ws_open_complete_error(uws_client, WS_OPEN_ERROR_UNDERLYING_IO_OPEN_FAILED);
+                break;
+
+            case IO_OPEN_CANCELLED:
+                /* Codes_SRS_UWS_CLIENT_01_402: [ When on_underlying_io_open_complete is called with IO_OPEN_CANCELLED while uws is OPENING (uws_client_open_async was called), uws shall report that the open failed by calling the on_ws_open_complete callback passed to uws_client_open_async with WS_OPEN_ERROR_UNDERLYING_IO_OPEN_CANCELLED. ]*/
+                indicate_ws_open_complete_error(uws_client, WS_OPEN_ERROR_UNDERLYING_IO_OPEN_CANCELLED);
+                break;
+
+            case IO_OPEN_OK:
+            {
+                int upgrade_request_length;
+                char* upgrade_request;
+                size_t i;
+                unsigned char nonce[16];
+                STRING_HANDLE base64_nonce;
+                char* request_headers = NULL;
+
+                /* Codes_SRS_UWS_CLIENT_01_089: [ The value of this header field MUST be a nonce consisting of a randomly selected 16-byte value that has been base64-encoded (see Section 4 of [RFC4648]). ]*/
+                /* Codes_SRS_UWS_CLIENT_01_090: [ The nonce MUST be selected randomly for each connection. ]*/
+                for (i = 0; i < sizeof(nonce); i++)
+                {
+                    nonce[i] = (unsigned char)gb_rand();
+                }
+
+                /* Codes_SRS_UWS_CLIENT_01_497: [ The nonce needed for the upgrade request shall be Base64 encoded with Azure_Base64_Encode_Bytes. ]*/
+                base64_nonce = Azure_Base64_Encode_Bytes(nonce, sizeof(nonce));
+                if (base64_nonce == NULL)
+                {
+                    /* Codes_SRS_UWS_CLIENT_01_498: [ If Base64 encoding the nonce for the upgrade request fails, then the uws client shall report that the open failed by calling the on_ws_open_complete callback passed to uws_client_open_async with WS_OPEN_ERROR_BASE64_ENCODE_FAILED. ]*/
+                    LogError("Cannot construct the WebSocket upgrade request");
+                    indicate_ws_open_complete_error(uws_client, WS_OPEN_ERROR_BASE64_ENCODE_FAILED);
+                }
+                else if ((request_headers = get_request_headers(uws_client->request_headers)) == NULL)
+                {
+                    LogError("Cannot construct the WebSocket request headers");
+                    indicate_ws_open_complete_error(uws_client, WS_OPEN_ERROR_CONSTRUCTING_UPGRADE_REQUEST);
+                }
+                else
+                {
+                    /* Codes_SRS_UWS_CLIENT_01_371: [ When on_underlying_io_open_complete is called with IO_OPEN_OK while uws is OPENING (uws_client_open_async was called), uws shall prepare the WebSockets upgrade request. ]*/
+                    /* Codes_SRS_UWS_CLIENT_01_081: [ The handshake consists of an HTTP Upgrade request, along with a list of required and optional header fields. ]*/
+                    /* Codes_SRS_UWS_CLIENT_01_082: [ The handshake MUST be a valid HTTP request as specified by [RFC2616]. ]*/
+                    /* Codes_SRS_UWS_CLIENT_01_083: [ The method of the request MUST be GET, and the HTTP version MUST be at least 1.1. ]*/
+                    /* Codes_SRS_UWS_CLIENT_01_084: [ The "Request-URI" part of the request MUST match the /resource name/ defined in Section 3 (a relative URI) or be an absolute http/https URI that, when parsed, has a /resource name/, /host/, and /port/ that match the corresponding ws/wss URI. ]*/
+                    /* Codes_SRS_UWS_CLIENT_01_085: [ The request MUST contain a |Host| header field whose value contains /host/ plus optionally ":" followed by /port/ (when not using the default port). ]*/
+                    /* Codes_SRS_UWS_CLIENT_01_086: [ The request MUST contain an |Upgrade| header field whose value MUST include the "websocket" keyword. ]*/
+                    /* Codes_SRS_UWS_CLIENT_01_087: [ The request MUST contain a |Connection| header field whose value MUST include the "Upgrade" token. ]*/
+                    /* Codes_SRS_UWS_CLIENT_01_088: [ The request MUST include a header field with the name |Sec-WebSocket-Key|. ]*/
+                    /* Codes_SRS_UWS_CLIENT_01_094: [ The request MUST include a header field with the name |Sec-WebSocket-Version|. ]*/
+                    /* Codes_SRS_UWS_CLIENT_01_095: [ The value of this header field MUST be 13. ]*/
+                    /* Codes_SRS_UWS_CLIENT_01_096: [ The request MAY include a header field with the name |Sec-WebSocket-Protocol|. ]*/
+                    /* Codes_SRS_UWS_CLIENT_01_100: [ The request MAY include a header field with the name |Sec-WebSocket-Extensions|. ]*/
+                    /* Codes_SRS_UWS_CLIENT_01_101: [ The request MAY include any other header fields, for example, cookies [RFC6265] and/or authentication-related header fields such as the |Authorization| header field [RFC2616], which are processed according to documents that define them. ] */
+                    const char upgrade_request_format[] = "GET %s HTTP/1.1\r\n"
+                        "Host: %s:%d\r\n"
+                        "Upgrade: websocket\r\n"
+                        "Connection: Upgrade\r\n"
+                        "Sec-WebSocket-Key: %s\r\n"
+                        "Sec-WebSocket-Protocol: %s\r\n"
+                        "Sec-WebSocket-Version: 13\r\n"
+                        "%s"
+                        "\r\n";
+
+                    const char* base64_nonce_chars = STRING_c_str(base64_nonce);
+
+                    upgrade_request_length = (int)(strlen(upgrade_request_format) + strlen(uws_client->resource_name)+strlen(uws_client->hostname) + strlen(base64_nonce_chars) + strlen(uws_client->protocols[0].protocol) + strlen(request_headers) + 5);
+                    if (upgrade_request_length < 0)
+                    {
+                        /* Codes_SRS_UWS_CLIENT_01_408: [ If constructing of the WebSocket upgrade request fails, uws shall report that the open failed by calling the on_ws_open_complete callback passed to uws_client_open_async with WS_OPEN_ERROR_CONSTRUCTING_UPGRADE_REQUEST. ]*/
+                        LogError("Cannot construct the WebSocket upgrade request");
+                        indicate_ws_open_complete_error_and_close(uws_client, WS_OPEN_ERROR_CONSTRUCTING_UPGRADE_REQUEST);
+                    }
+                    else
+                    {
+                        upgrade_request = (char*)malloc(upgrade_request_length + 1);
+                        if (upgrade_request == NULL)
+                        {
+                            /* Codes_SRS_UWS_CLIENT_01_406: [ If not enough memory can be allocated to construct the WebSocket upgrade request, uws shall report that the open failed by calling the on_ws_open_complete callback passed to uws_client_open_async with WS_OPEN_ERROR_NOT_ENOUGH_MEMORY. ]*/
+                            LogError("Cannot allocate memory for the WebSocket upgrade request");
+                            indicate_ws_open_complete_error_and_close(uws_client, WS_OPEN_ERROR_NOT_ENOUGH_MEMORY);
+                        }
+                        else
+                        {
+
+                            upgrade_request_length = sprintf(upgrade_request, upgrade_request_format,
+                                uws_client->resource_name,
+                                uws_client->hostname,
+                                uws_client->port,
+                                base64_nonce_chars,
+                                uws_client->protocols[0].protocol,
+                                request_headers);
+
+                            /* No need to have any send complete here, as we are monitoring the received bytes */
+                            /* Codes_SRS_UWS_CLIENT_01_372: [ Once prepared the WebSocket upgrade request shall be sent by calling xio_send. ]*/
+                            /* Codes_SRS_UWS_CLIENT_01_080: [ Once a connection to the server has been established (including a connection via a proxy or over a TLS-encrypted tunnel), the client MUST send an opening handshake to the server. ]*/
+                            if (xio_send(uws_client->underlying_io, upgrade_request, upgrade_request_length, unchecked_on_send_complete, NULL) != 0)
+                            {
+                                /* Codes_SRS_UWS_CLIENT_01_373: [ If xio_send fails then uws shall report that the open failed by calling the on_ws_open_complete callback passed to uws_client_open_async with WS_OPEN_ERROR_CANNOT_SEND_UPGRADE_REQUEST. ]*/
+                                LogError("Cannot send upgrade request");
+                                indicate_ws_open_complete_error_and_close(uws_client, WS_OPEN_ERROR_CANNOT_SEND_UPGRADE_REQUEST);
+                            }
+                            else
+                            {
+                                /* Codes_SRS_UWS_CLIENT_01_102: [ Once the client's opening handshake has been sent, the client MUST wait for a response from the server before sending any further data. ]*/
+                                uws_client->uws_state = UWS_STATE_WAITING_FOR_UPGRADE_RESPONSE;
+                            }
+
+                            free(upgrade_request);
+                        }
+                    }
+
+                    STRING_delete(base64_nonce);
+                    free(request_headers);
+                }
+
+                break;
+            }
+            }
+        }
+    }
+}
+
+static void consume_stream_buffer_bytes(UWS_CLIENT_INSTANCE* uws_client, size_t consumed_bytes)
+{
+    if (consumed_bytes < uws_client->stream_buffer_count)
+    {
+        (void)memmove(uws_client->stream_buffer, uws_client->stream_buffer + consumed_bytes, uws_client->stream_buffer_count - consumed_bytes);
+    }
+
+    uws_client->stream_buffer_count -= consumed_bytes;
+}
+
+static void on_underlying_io_close_complete(void* context)
+{
+    if (context == NULL)
+    {
+        /* Codes_SRS_UWS_CLIENT_01_477: [ When on_underlying_io_close_complete is called with a NULL context, it shall do nothing. ]*/
+        LogError("NULL context for on_underlying_io_close_complete");
+    }
+    else
+    {
+        UWS_CLIENT_HANDLE uws_client = (UWS_CLIENT_HANDLE)context;
+        if (uws_client->uws_state == UWS_STATE_CLOSING_UNDERLYING_IO)
+        {
+            /* Codes_SRS_UWS_CLIENT_01_475: [ When on_underlying_io_close_complete is called while closing the underlying IO a subsequent uws_client_open_async shall succeed. ]*/
+            indicate_ws_close_complete(uws_client);
+            uws_client->uws_state = UWS_STATE_CLOSED;
+        }
+    }
+}
+
+static void on_underlying_io_close_sent(void* context, IO_SEND_RESULT io_send_result)
+{
+    if (context == NULL)
+    {
+        /* Codes_SRS_UWS_CLIENT_01_489: [ When on_underlying_io_close_sent is called with NULL context, it shall do nothing. ] */
+        LogError("NULL context in ");
+    }
+    else
+    {
+        UWS_CLIENT_INSTANCE* uws_client = (UWS_CLIENT_HANDLE)context;
+
+        switch (io_send_result)
+        {
+        default:
+            LogError("Unknown enum value: %d", io_send_result);
+            break;
+
+        case IO_SEND_OK:
+        case IO_SEND_CANCELLED:
+            if (uws_client->uws_state == UWS_STATE_CLOSING_SENDING_CLOSE)
+            {
+                uws_client->uws_state = UWS_STATE_CLOSING_UNDERLYING_IO;
+
+                /* Codes_SRS_UWS_CLIENT_01_490: [ When on_underlying_io_close_sent is called while the uws client is CLOSING, on_underlying_io_close_sent shall close the underlying IO by calling xio_close. ]*/
+                if (xio_close(uws_client->underlying_io, on_underlying_io_close_complete, uws_client) != 0)
+                {
+                    /* Codes_SRS_UWS_CLIENT_01_496: [ If the close was initiated by the peer no on_ws_close_complete shall be called. ]*/
+                    indicate_ws_close_complete(uws_client);
+                }
+            }
+
+        case IO_SEND_ERROR:
+            break;
+        }
+    }
+}
+
+/*the following function does the same as sscanf(pos2, "%d", &sec)*/
+/*this function only exists because some of platforms do not have sscanf. */
+static int ParseStringToDecimal(const char *src, int* dst)
+{
+    int result;
+    char* next;
+
+    (*dst) = (int)strtol(src, &next, 0);
+    if ((src == next) || ((((*dst) == INT_MAX) || ((*dst) == INT_MIN)) && (errno != 0)))
+    {
+        result = MU_FAILURE;
+    }
+    else
+    {
+        result = 0;
+    }
+
+    return result;
+}
+
+/*the following function does the same as sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &ret) */
+/*this function only exists because some of platforms do not have sscanf. This is not a full implementation; it only works with well-defined HTTP response. */
+static int ParseHttpResponse(const char* src, int* dst)
+{
+    int result;
+    static const char HTTPPrefix[] = "HTTP/";
+    bool fail;
+    const char* runPrefix;
+
+    if ((src == NULL) || (dst == NULL))
+    {
+        result = MU_FAILURE;
+    }
+    else
+    {
+        fail = false;
+        runPrefix = HTTPPrefix;
+
+        while ((*runPrefix) != '\0')
+        {
+            if ((*runPrefix) != (*src))
+            {
+                fail = true;
+                break;
+            }
+            src++;
+            runPrefix++;
+        }
+
+        if (!fail)
+        {
+            while ((*src) != '.')
+            {
+                if ((*src) == '\0')
+                {
+                    fail = true;
+                    break;
+                }
+                src++;
+            }
+        }
+
+        if (!fail)
+        {
+            while ((*src) != ' ')
+            {
+                if ((*src) == '\0')
+                {
+                    fail = true;
+                    break;
+                }
+                src++;
+            }
+        }
+
+        if (fail)
+        {
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if (ParseStringToDecimal(src, dst) != 0)
+            {
+                result = MU_FAILURE;
+            }
+            else
+            {
+                result = 0;
+            }
+        }
+    }
+
+    return result;
+}
+
+static int process_frame_fragment(UWS_CLIENT_INSTANCE *uws_client, size_t length, size_t needed_bytes)
+{
+    int result;
+    unsigned char *new_fragment_bytes = (unsigned char *)realloc(uws_client->fragment_buffer, uws_client->fragment_buffer_count + length);
+    if (new_fragment_bytes == NULL)
+    {
+        /* Codes_SRS_UWS_CLIENT_01_379: [ If allocating memory for accumulating the bytes fails, uws shall report that the open failed by calling the on_ws_open_complete callback passed to uws_client_open_async with WS_OPEN_ERROR_NOT_ENOUGH_MEMORY. ]*/
+        LogError("Cannot allocate memory for received data");
+        indicate_ws_error(uws_client, WS_ERROR_NOT_ENOUGH_MEMORY);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        uws_client->fragment_buffer = new_fragment_bytes;
+        (void)memcpy(uws_client->fragment_buffer + uws_client->fragment_buffer_count, uws_client->stream_buffer + needed_bytes - length, length);
+        uws_client->fragment_buffer_count += length;
+        result = 0;
+    }
+
+    return result;
+}
+
+static void on_underlying_io_bytes_received(void* context, const unsigned char* buffer, size_t size)
+{
+    /* Codes_SRS_UWS_CLIENT_01_415: [ If called with a NULL context argument, on_underlying_io_bytes_received shall do nothing. ]*/
+    if (context != NULL)
+    {
+        UWS_CLIENT_HANDLE uws_client = (UWS_CLIENT_HANDLE)context;
+
+        if ((buffer == NULL) ||
+            (size == 0))
+        {
+            /* Codes_SRS_UWS_CLIENT_01_416: [ If called with NULL buffer or zero size and the state of the iws is OPENING, uws shall report that the open failed by calling the on_ws_open_complete callback passed to uws_client_open_async with WS_OPEN_ERROR_INVALID_BYTES_RECEIVED_ARGUMENTS. ]*/
+            indicate_ws_open_complete_error_and_close(uws_client, WS_OPEN_ERROR_INVALID_BYTES_RECEIVED_ARGUMENTS);
+        }
+        else
+        {
+            unsigned char decode_stream = 1;
+
+            switch (uws_client->uws_state)
+            {
+            default:
+            case UWS_STATE_CLOSED:
+                decode_stream = 0;
+                break;
+
+            case UWS_STATE_OPENING_UNDERLYING_IO:
+                /* Codes_SRS_UWS_CLIENT_01_417: [ When on_underlying_io_bytes_received is called while OPENING but before the on_underlying_io_open_complete has been called, uws shall report that the open failed by calling the on_ws_open_complete callback passed to uws_client_open_async with WS_OPEN_ERROR_BYTES_RECEIVED_BEFORE_UNDERLYING_OPEN. ]*/
+                indicate_ws_open_complete_error_and_close(uws_client, WS_OPEN_ERROR_BYTES_RECEIVED_BEFORE_UNDERLYING_OPEN);
+                decode_stream = 0;
+                break;
+
+            case UWS_STATE_WAITING_FOR_UPGRADE_RESPONSE:
+            {
+                /* Codes_SRS_UWS_CLIENT_01_378: [ When on_underlying_io_bytes_received is called while the uws is OPENING, the received bytes shall be accumulated in order to attempt parsing the WebSocket Upgrade response. ]*/
+                unsigned char* new_received_bytes = (unsigned char*)realloc(uws_client->stream_buffer, uws_client->stream_buffer_count + size + 1);
+                if (new_received_bytes == NULL)
+                {
+                    /* Codes_SRS_UWS_CLIENT_01_379: [ If allocating memory for accumulating the bytes fails, uws shall report that the open failed by calling the on_ws_open_complete callback passed to uws_client_open_async with WS_OPEN_ERROR_NOT_ENOUGH_MEMORY. ]*/
+                    indicate_ws_open_complete_error_and_close(uws_client, WS_OPEN_ERROR_NOT_ENOUGH_MEMORY);
+                    decode_stream = 0;
+                }
+                else
+                {
+                    uws_client->stream_buffer = new_received_bytes;
+                    (void)memcpy(uws_client->stream_buffer + uws_client->stream_buffer_count, buffer, size);
+                    uws_client->stream_buffer_count += size;
+
+                    decode_stream = 1;
+                }
+
+                break;
+            }
+
+            case UWS_STATE_OPEN:
+            case UWS_STATE_CLOSING_WAITING_FOR_CLOSE:
+            {
+                /* Codes_SRS_UWS_CLIENT_01_385: [ If the state of the uws instance is OPEN, the received bytes shall be used for decoding WebSocket frames. ]*/
+                unsigned char* new_received_bytes = (unsigned char*)realloc(uws_client->stream_buffer, uws_client->stream_buffer_count + size + 1);
+                if (new_received_bytes == NULL)
+                {
+                    /* Codes_SRS_UWS_CLIENT_01_418: [ If allocating memory for the bytes accumulated for decoding WebSocket frames fails, an error shall be indicated by calling the on_ws_error callback with WS_ERROR_NOT_ENOUGH_MEMORY. ]*/
+                    LogError("Cannot allocate memory for received data");
+                    indicate_ws_error(uws_client, WS_ERROR_NOT_ENOUGH_MEMORY);
+
+                    decode_stream = 0;
+                }
+                else
+                {
+                    uws_client->stream_buffer = new_received_bytes;
+                    (void)memcpy(uws_client->stream_buffer + uws_client->stream_buffer_count, buffer, size);
+                    uws_client->stream_buffer_count += size;
+
+                    decode_stream = 1;
+                }
+
+                break;
+            }
+            }
+
+            while (decode_stream)
+            {
+                decode_stream = 0;
+
+                switch (uws_client->uws_state)
+                {
+                default:
+                case UWS_STATE_CLOSED:
+                    break;
+
+                case UWS_STATE_OPENING_UNDERLYING_IO:
+                    /* Codes_SRS_UWS_CLIENT_01_417: [ When on_underlying_io_bytes_received is called while OPENING but before the on_underlying_io_open_complete has been called, uws shall report that the open failed by calling the on_ws_open_complete callback passed to uws_client_open_async with WS_OPEN_ERROR_BYTES_RECEIVED_BEFORE_UNDERLYING_OPEN. ]*/
+                    indicate_ws_open_complete_error_and_close(uws_client, WS_OPEN_ERROR_BYTES_RECEIVED_BEFORE_UNDERLYING_OPEN);
+                    break;
+
+                case UWS_STATE_WAITING_FOR_UPGRADE_RESPONSE:
+                {
+                    const char* request_end_ptr;
+
+                    /* Make sure it is zero terminated */
+                    uws_client->stream_buffer[uws_client->stream_buffer_count] = '\0';
+
+                    /* Codes_SRS_UWS_CLIENT_01_380: [ If an WebSocket Upgrade request can be parsed from the accumulated bytes, the status shall be read from the WebSocket upgrade response. ]*/
+                    /* Codes_SRS_UWS_CLIENT_01_381: [ If the status is 101, uws shall be considered OPEN and this shall be indicated by calling the on_ws_open_complete callback passed to uws_client_open_async with IO_OPEN_OK. ]*/
+                    if ((uws_client->stream_buffer_count >= 4) &&
+                        ((request_end_ptr = strstr((const char*)uws_client->stream_buffer, "\r\n\r\n")) != NULL))
+                    {
+                        int status_code;
+
+                        /* This part should really be done with the HTTPAPI, but that has to be done as a separate step
+                        as the HTTPAPI has to expose somehow the underlying IO and currently this would be a too big of a change. */
+
+                        /* Codes_SRS_UWS_CLIENT_01_382: [ If a negative status is decoded from the WebSocket upgrade request, an error shall be indicated by calling the on_ws_open_complete callback passed to uws_client_open_async with WS_OPEN_ERROR_BAD_RESPONSE_STATUS. ]*/
+                        /* Codes_SRS_UWS_CLIENT_01_478: [ A Status-Line with a 101 response code as per RFC 2616 [RFC2616]. ]*/
+                        if (ParseHttpResponse((const char*)uws_client->stream_buffer, &status_code) != 0)
+                        {
+                            /* Codes_SRS_UWS_CLIENT_01_383: [ If the WebSocket upgrade request cannot be decoded an error shall be indicated by calling the on_ws_open_complete callback passed to uws_client_open_async with WS_OPEN_ERROR_BAD_UPGRADE_RESPONSE. ]*/
+                            LogError("Cannot decode HTTP response");
+                            indicate_ws_open_complete_error_and_close(uws_client, WS_OPEN_ERROR_BAD_UPGRADE_RESPONSE);
+                        }
+                        else if (status_code != 101)
+                        {
+                            /* Codes_SRS_UWS_CLIENT_01_382: [ If a negative status is decoded from the WebSocket upgrade request, an error shall be indicated by calling the on_ws_open_complete callback passed to uws_client_open_async with WS_OPEN_ERROR_BAD_RESPONSE_STATUS. ]*/
+                            LogError("Bad status (%d) received in WebSocket Upgrade response", status_code);
+                            indicate_ws_open_complete_error_and_close(uws_client, WS_OPEN_ERROR_BAD_RESPONSE_STATUS);
+                        }
+                        else
+                        {
+                            /* Codes_SRS_UWS_CLIENT_01_384: [ Any extra bytes that are left unconsumed after decoding a succesfull WebSocket upgrade response shall be used for decoding WebSocket frames ]*/
+                            consume_stream_buffer_bytes(uws_client, request_end_ptr - (char*)uws_client->stream_buffer + 4);
+
+                            /* Codes_SRS_UWS_CLIENT_01_381: [ If the status is 101, uws shall be considered OPEN and this shall be indicated by calling the on_ws_open_complete callback passed to uws_client_open_async with IO_OPEN_OK. ]*/
+                            uws_client->uws_state = UWS_STATE_OPEN;
+
+                            /* Codes_SRS_UWS_CLIENT_01_065: [ When the client is to _Establish a WebSocket Connection_ given a set of (/host/, /port/, /resource name/, and /secure/ flag), along with a list of /protocols/ and /extensions/ to be used, and an /origin/ in the case of web browsers, it MUST open a connection, send an opening handshake, and read the server's handshake in response. ]*/
+                            /* Codes_SRS_UWS_CLIENT_01_115: [ If the server's response is validated as provided for above, it is said that _The WebSocket Connection is Established_ and that the WebSocket Connection is in the OPEN state. ]*/
+                            uws_client->on_ws_open_complete(uws_client->on_ws_open_complete_context, WS_OPEN_OK);
+
+                            decode_stream = 1;
+                        }
+                    }
+
+                    break;
+                }
+
+                case UWS_STATE_OPEN:
+                case UWS_STATE_CLOSING_WAITING_FOR_CLOSE:
+                {
+                    size_t needed_bytes = 2;
+                    size_t length;
+
+                    /* Codes_SRS_UWS_CLIENT_01_277: [ To receive WebSocket data, an endpoint listens on the underlying network connection. ]*/
+                    /* Codes_SRS_UWS_CLIENT_01_278: [ Incoming data MUST be parsed as WebSocket frames as defined in Section 5.2. ]*/
+                    if (uws_client->stream_buffer_count >= needed_bytes)
+                    {
+                        unsigned char has_error = 0;
+
+                        /* Codes_SRS_UWS_CLIENT_01_160: [ Defines whether the "Payload data" is masked. ]*/
+                        if ((uws_client->stream_buffer[1] & 0x80) != 0)
+                        {
+                            /* Codes_SRS_UWS_CLIENT_01_144: [ A client MUST close a connection if it detects a masked frame. ]*/
+                            /* Codes_SRS_UWS_CLIENT_01_145: [ In this case, it MAY use the status code 1002 (protocol error) as defined in Section 7.4.1. (These rules might be relaxed in a future specification.) ]*/
+                            LogError("Masked frame detected by WebSocket client");
+                            indicate_ws_error_and_close(uws_client, WS_ERROR_BAD_FRAME_RECEIVED, 1002);
+                        }
+
+                        /* Codes_SRS_UWS_CLIENT_01_163: [ The length of the "Payload data", in bytes: ]*/
+                        /* Codes_SRS_UWS_CLIENT_01_164: [ if 0-125, that is the payload length. ]*/
+                        length = uws_client->stream_buffer[1];
+
+                        if (length == 126)
+                        {
+                            /* Codes_SRS_UWS_CLIENT_01_165: [ If 126, the following 2 bytes interpreted as a 16-bit unsigned integer are the payload length. ]*/
+                            needed_bytes += 2;
+                            if (uws_client->stream_buffer_count >= needed_bytes)
+                            {
+                                /* Codes_SRS_UWS_CLIENT_01_167: [ Multibyte length quantities are expressed in network byte order. ]*/
+                                length = ((size_t)(uws_client->stream_buffer[2]) << 8) + (size_t)uws_client->stream_buffer[3];
+
+                                if (length < 126)
+                                {
+                                    /* Codes_SRS_UWS_CLIENT_01_168: [ Note that in all cases, the minimal number of bytes MUST be used to encode the length, for example, the length of a 124-byte-long string can't be encoded as the sequence 126, 0, 124. ]*/
+                                    LogError("Bad frame: received a %u length on the 16 bit length", (unsigned int)length);
+
+                                    /* Codes_SRS_UWS_CLIENT_01_419: [ If there is an error decoding the WebSocket frame, an error shall be indicated by calling the on_ws_error callback with WS_ERROR_BAD_FRAME_RECEIVED. ]*/
+                                    indicate_ws_error(uws_client, WS_ERROR_BAD_FRAME_RECEIVED);
+                                    has_error = 1;
+                                }
+                                else
+                                {
+                                    needed_bytes += (size_t)length;
+                                }
+                            }
+                        }
+                        else if (length == 127)
+                        {
+                            /* Codes_SRS_UWS_CLIENT_01_166: [ If 127, the following 8 bytes interpreted as a 64-bit unsigned integer (the most significant bit MUST be 0) are the payload length. ]*/
+                            needed_bytes += 8;
+                            if (uws_client->stream_buffer_count >= needed_bytes)
+                            {
+                                if ((uws_client->stream_buffer[2] & 0x80) != 0)
+                                {
+                                    LogError("Bad frame: received a 64 bit length frame with the highest bit set");
+
+                                    /* Codes_SRS_UWS_CLIENT_01_419: [ If there is an error decoding the WebSocket frame, an error shall be indicated by calling the on_ws_error callback with WS_ERROR_BAD_FRAME_RECEIVED. ]*/
+                                    indicate_ws_error(uws_client, WS_ERROR_BAD_FRAME_RECEIVED);
+                                    has_error = 1;
+                                }
+                                else
+                                {
+                                    /* Codes_SRS_UWS_CLIENT_01_167: [ Multibyte length quantities are expressed in network byte order. ]*/
+                                    length = (size_t)(((uint64_t)(uws_client->stream_buffer[2]) << 56) +
+                                        (((uint64_t)uws_client->stream_buffer[3]) << 48) +
+                                        (((uint64_t)uws_client->stream_buffer[4]) << 40) +
+                                        (((uint64_t)uws_client->stream_buffer[5]) << 32) +
+                                        (((uint64_t)uws_client->stream_buffer[6]) << 24) +
+                                        (((uint64_t)uws_client->stream_buffer[7]) << 16) +
+                                        (((uint64_t)uws_client->stream_buffer[8]) << 8) +
+                                        (uint64_t)(uws_client->stream_buffer[9]));
+
+                                    if (length < 65536)
+                                    {
+                                        /* Codes_SRS_UWS_CLIENT_01_168: [ Note that in all cases, the minimal number of bytes MUST be used to encode the length, for example, the length of a 124-byte-long string can't be encoded as the sequence 126, 0, 124. ]*/
+                                        LogError("Bad frame: received a %u length on the 64 bit length", (unsigned int)length);
+
+                                        /* Codes_SRS_UWS_CLIENT_01_419: [ If there is an error decoding the WebSocket frame, an error shall be indicated by calling the on_ws_error callback with WS_ERROR_BAD_FRAME_RECEIVED. ]*/
+                                        indicate_ws_error(uws_client, WS_ERROR_BAD_FRAME_RECEIVED);
+                                        has_error = 1;
+                                    }
+                                    else
+                                    {
+                                        needed_bytes += length;
+                                    }
+                                }
+                            }
+                        }
+                        else
+                        {
+                            needed_bytes += length;
+                        }
+
+                        if ((has_error == 0) &&
+                            (uws_client->stream_buffer_count >= needed_bytes))
+                        {
+                            unsigned char opcode = uws_client->stream_buffer[0] & 0xF;
+
+                            /* Codes_SRS_UWS_CLIENT_01_147: [ Indicates that this is the final fragment in a message. ]*/
+                            bool is_final = (uws_client->stream_buffer[0] & 0x80) != 0;
+
+                            switch (opcode)
+                            {
+                            default:
+                                break;
+                                /* Codes_SRS_UWS_CLIENT_01_152: [* *  %x0 denotes a continuation frame *]*/
+                            case (unsigned char)WS_CONTINUATION_FRAME:
+                            {
+                                /* Codes_SRS_UWS_CLIENT_01_213: [ A fragmented message consists of a single frame with the FIN bit clear and an opcode other than 0, followed by zero or more frames with the FIN bit clear and the opcode set to 0, and terminated by a single frame with the FIN bit set and an opcode of 0. ]*/
+                                /* Codes_SRS_UWS_CLIENT_01_216: [ Message fragments MUST be delivered to the recipient in the order sent by the sender. ]*/
+                                /* Codes_SRS_UWS_CLIENT_01_219: [ A sender MAY create fragments of any size for non-control messages. ]*/
+                                if (process_frame_fragment(uws_client, length, needed_bytes) != 0)
+                                {
+                                    break;
+                                }
+
+                                if (is_final)
+                                {
+                                    /* Codes_SRS_UWS_CLIENT_01_225: [ As a consequence of these rules, all fragments of a message are of the same type, as set by the first fragment's opcode. ]*/
+                                    if (uws_client->fragmented_frame_type == WS_FRAME_TYPE_UNKNOWN)
+                                    {
+                                        LogError("Continuation fragment received without initial fragment specifying frame data type");
+                                        indicate_ws_error(uws_client, WS_ERROR_BAD_FRAME_RECEIVED);
+                                        decode_stream = 1;
+                                        break;
+                                    }
+                                    uws_client->on_ws_frame_received(uws_client->on_ws_frame_received_context, uws_client->fragmented_frame_type, uws_client->fragment_buffer, uws_client->fragment_buffer_count);
+                                    uws_client->fragment_buffer_count = 0;
+                                    uws_client->fragmented_frame_type = WS_FRAME_TYPE_UNKNOWN;
+                                }
+                                decode_stream = 1;
+                                break;
+                            }
+                                /* Codes_SRS_UWS_CLIENT_01_153: [ *  %x1 denotes a text frame ]*/
+                                /* Codes_SRS_UWS_CLIENT_01_258: [** Currently defined opcodes for data frames include 0x1 (Text), 0x2 (Binary). ]*/
+                            case (unsigned char)WS_TEXT_FRAME:
+                            {
+                                /* Codes_SRS_UWS_CLIENT_01_386: [ When a WebSocket data frame is decoded succesfully it shall be indicated via the callback on_ws_frame_received. ]*/
+                                /* Codes_SRS_UWS_CLIENT_01_169: [ The payload length is the length of the "Extension data" + the length of the "Application data". ]*/
+                                /* Codes_SRS_UWS_CLIENT_01_173: [ The "Payload data" is defined as "Extension data" concatenated with "Application data". ]*/
+                                /* Codes_SRS_UWS_CLIENT_01_280: [ Upon receiving a data frame (Section 5.6), the endpoint MUST note the /type/ of the data as defined by the opcode (frame-opcode) from Section 5.2. ]*/
+                                /* Codes_SRS_UWS_CLIENT_01_281: [ The "Application data" from this frame is defined as the /data/ of the message. ]*/
+                                /* Codes_SRS_UWS_CLIENT_01_282: [ If the frame comprises an unfragmented message (Section 5.4), it is said that _A WebSocket Message Has Been Received_ with type /type/ and data /data/. ]*/
+                                if (is_final)
+                                {
+                                    uws_client->on_ws_frame_received(uws_client->on_ws_frame_received_context, WS_FRAME_TYPE_TEXT, uws_client->stream_buffer + needed_bytes - length, length);
+                                }
+                                else
+                                {
+                                    /* Codes_SRS_UWS_CLIENT_01_217: [ The fragments of one message MUST NOT be interleaved between the fragments of another message unless an extension has been negotiated that can interpret the interleaving. ]*/
+                                    if (uws_client->fragmented_frame_type != WS_FRAME_TYPE_UNKNOWN)
+                                    {
+                                        LogError("Fragmented frame received interleaved between the fragments of another message");
+                                        indicate_ws_error(uws_client, WS_ERROR_BAD_FRAME_RECEIVED);
+                                        decode_stream = 1;
+                                        break;
+                                    }
+                                    /* Codes_SRS_UWS_CLIENT_01_213: [ A fragmented message consists of a single frame with the FIN bit clear and an opcode other than 0, followed by zero or more frames with the FIN bit clear and the opcode set to 0, and terminated by a single frame with the FIN bit set and an opcode of 0. ]*/
+                                    /* Codes_SRS_UWS_CLIENT_01_216: [ Message fragments MUST be delivered to the recipient in the order sent by the sender. ]*/
+                                    /* Codes_SRS_UWS_CLIENT_01_219: [ A sender MAY create fragments of any size for non-control messages. ]*/
+                                    if (process_frame_fragment(uws_client, length, needed_bytes) != 0)
+                                    {
+                                        break;
+                                    }
+
+                                    /* Codes_SRS_UWS_CLIENT_01_225: [ As a consequence of these rules, all fragments of a message are of the same type, as set by the first fragment's opcode. ]*/
+                                    /* Codes_SRS_UWS_CLIENT_01_226: [ Since control frames cannot be fragmented, the type for all fragments in a message MUST be either text, binary, or one of the reserved opcodes. ]*/
+                                    uws_client->fragmented_frame_type = WS_FRAME_TYPE_TEXT;
+                                }
+                                decode_stream = 1;
+                                break;
+                            }
+
+                                /* Codes_SRS_UWS_CLIENT_01_154: [ *  %x2 denotes a binary frame ]*/
+                            case (unsigned char)WS_BINARY_FRAME:
+                            {
+                                /* Codes_SRS_UWS_CLIENT_01_386: [ When a WebSocket data frame is decoded succesfully it shall be indicated via the callback on_ws_frame_received. ]*/
+                                /* Codes_SRS_UWS_CLIENT_01_169: [ The payload length is the length of the "Extension data" + the length of the "Application data". ]*/
+                                /* Codes_SRS_UWS_CLIENT_01_173: [ The "Payload data" is defined as "Extension data" concatenated with "Application data". ]*/
+                                /* Codes_SRS_UWS_CLIENT_01_264: [ The "Payload data" is arbitrary binary data whose interpretation is solely up to the application layer. ]*/
+                                /* Codes_SRS_UWS_CLIENT_01_280: [ Upon receiving a data frame (Section 5.6), the endpoint MUST note the /type/ of the data as defined by the opcode (frame-opcode) from Section 5.2. ]*/
+                                /* Codes_SRS_UWS_CLIENT_01_281: [ The "Application data" from this frame is defined as the /data/ of the message. ]*/
+                                /* Codes_SRS_UWS_CLIENT_01_282: [ If the frame comprises an unfragmented message (Section 5.4), it is said that _A WebSocket Message Has Been Received_ with type /type/ and data /data/. ]*/
+                                if (is_final)
+                                {
+                                    uws_client->on_ws_frame_received(uws_client->on_ws_frame_received_context, WS_FRAME_TYPE_BINARY, uws_client->stream_buffer + needed_bytes - length, length);
+                                }
+                                else
+                                {
+                                    /* Codes_SRS_UWS_CLIENT_01_217: [ The fragments of one message MUST NOT be interleaved between the fragments of another message unless an extension has been negotiated that can interpret the interleaving. ]*/
+                                    if (uws_client->fragmented_frame_type != WS_FRAME_TYPE_UNKNOWN)
+                                    {
+                                        LogError("Fragmented frame received interleaved between the fragments of another message");
+                                        indicate_ws_error(uws_client, WS_ERROR_BAD_FRAME_RECEIVED);
+                                        decode_stream = 1;
+                                        break;
+                                    }
+                                    /* Codes_SRS_UWS_CLIENT_01_213: [ A fragmented message consists of a single frame with the FIN bit clear and an opcode other than 0, followed by zero or more frames with the FIN bit clear and the opcode set to 0, and terminated by a single frame with the FIN bit set and an opcode of 0. ]*/
+                                    /* Codes_SRS_UWS_CLIENT_01_216: [ Message fragments MUST be delivered to the recipient in the order sent by the sender. ]*/
+                                    /* Codes_SRS_UWS_CLIENT_01_219: [ A sender MAY create fragments of any size for non-control messages. ]*/
+                                    if (process_frame_fragment(uws_client, length, needed_bytes) != 0)
+                                    {
+                                        break;
+                                    }
+
+                                    /* Codes_SRS_UWS_CLIENT_01_225: [ As a consequence of these rules, all fragments of a message are of the same type, as set by the first fragment's opcode. ]*/
+                                    /* Codes_SRS_UWS_CLIENT_01_226: [ Since control frames cannot be fragmented, the type for all fragments in a message MUST be either text, binary, or one of the reserved opcodes. ]*/
+                                    uws_client->fragmented_frame_type = WS_FRAME_TYPE_BINARY;
+                                }
+                                decode_stream = 1;
+                                break;
+                            }
+
+                                /* Codes_SRS_UWS_CLIENT_01_156: [ *  %x8 denotes a connection close ]*/
+                                /* Codes_SRS_UWS_CLIENT_01_234: [ The Close frame contains an opcode of 0x8. ]*/
+                                /* Codes_SRS_UWS_CLIENT_01_214: [ Control frames (see Section 5.5) MAY be injected in the middle of a fragmented message. ]*/
+                            case (unsigned char)WS_CLOSE_FRAME:
+                            {
+                                uint16_t close_code;
+                                uint16_t* close_code_ptr;
+                                const unsigned char* data_ptr = uws_client->stream_buffer + needed_bytes - length;
+                                const unsigned char* extra_data_ptr;
+                                size_t extra_data_length;
+                                unsigned char* close_frame_bytes;
+                                size_t close_frame_length;
+                                bool utf8_error = false;
+
+                                /* Codes_SRS_UWS_CLIENT_01_215: [ Control frames themselves MUST NOT be fragmented. ]*/
+                                if (!is_final)
+                                {
+                                    LogError("Fragmented control frame received.");
+                                    indicate_ws_error(uws_client, WS_ERROR_BAD_FRAME_RECEIVED);
+                                    break;
+                                }
+
+                                /* Codes_SRS_UWS_CLIENT_01_235: [ The Close frame MAY contain a body (the "Application data" portion of the frame) that indicates a reason for closing, such as an endpoint shutting down, an endpoint having received a frame too large, or an endpoint having received a frame that does not conform to the format expected by the endpoint. ]*/
+                                if (length >= 2)
+                                {
+                                    /* Codes_SRS_UWS_CLIENT_01_236: [ If there is a body, the first two bytes of the body MUST be a 2-byte unsigned integer (in network byte order) representing a status code with value /code/ defined in Section 7.4. ]*/
+                                    close_code = (data_ptr[0] << 8) + data_ptr[1];
+
+                                    /* Codes_SRS_UWS_CLIENT_01_461: [ The argument close_code shall be set to point to the code extracted from the CLOSE frame. ]*/
+                                    close_code_ptr = &close_code;
+                                }
+                                else
+                                {
+                                    /* Codes_SRS_UWS_CLIENT_01_462: [ If no code can be extracted then close_code shall be NULL. ]*/
+                                    close_code_ptr = NULL;
+                                }
+
+                                if (length > 2)
+                                {
+                                    /* Codes_SRS_UWS_CLIENT_01_463: [ The extra bytes (besides the close code) shall be passed to the on_ws_peer_closed callback by using extra_data and extra_data_length. ]*/
+                                    extra_data_ptr = data_ptr + 2;
+                                    extra_data_length = length - 2;
+
+                                    /* Codes_SRS_UWS_CLIENT_01_238: [ As the data is not guaranteed to be human readable, clients MUST NOT show it to end users. ]*/
+                                    /* Codes_SRS_UWS_CLIENT_01_237: [ Following the 2-byte integer, the body MAY contain UTF-8-encoded data with value /reason/, the interpretation of which is not defined by this specification. ]*/
+                                    if (utf8_checker_is_valid_utf8(extra_data_ptr, extra_data_length) != true)
+                                    {
+                                        LogError("Reason in CLOSE frame is not UTF-8.");
+                                        extra_data_ptr = NULL;
+                                        extra_data_length = 0;
+                                        utf8_error = true;
+                                    }
+                                }
+                                else
+                                {
+                                    extra_data_ptr = NULL;
+                                    extra_data_length = 0;
+                                }
+
+                                if (utf8_error)
+                                {
+                                    uws_client->uws_state = UWS_STATE_CLOSING_UNDERLYING_IO;
+                                    if (xio_close(uws_client->underlying_io, on_underlying_io_close_complete, uws_client) != 0)
+                                    {
+                                        LogError("Could not close underlying IO");
+                                        indicate_ws_error(uws_client, WS_ERROR_CANNOT_CLOSE_UNDERLYING_IO);
+                                        uws_client->uws_state = UWS_STATE_CLOSED;
+                                    }
+                                }
+                                else
+                                {
+                                    BUFFER_HANDLE close_frame_buffer;
+
+                                    if (uws_client->uws_state == UWS_STATE_CLOSING_WAITING_FOR_CLOSE)
+                                    {
+                                        uws_client->uws_state = UWS_STATE_CLOSING_UNDERLYING_IO;
+                                        if (xio_close(uws_client->underlying_io, on_underlying_io_close_complete, uws_client) != 0)
+                                        {
+                                            indicate_ws_close_complete(uws_client);
+                                            uws_client->uws_state = UWS_STATE_CLOSED;
+                                        }
+                                    }
+                                    else
+                                    {
+                                        /* Codes_SRS_UWS_CLIENT_01_296: [ Upon either sending or receiving a Close control frame, it is said that _The WebSocket Closing Handshake is Started_ and that the WebSocket connection is in the CLOSING state. ]*/
+                                        /* Codes_SRS_UWS_CLIENT_01_240: [ The application MUST NOT send any more data frames after sending a Close frame. ]*/
+                                        uws_client->uws_state = UWS_STATE_CLOSING_SENDING_CLOSE;
+                                    }
+
+                                    /* Codes_SRS_UWS_CLIENT_01_241: [ If an endpoint receives a Close frame and did not previously send a Close frame, the endpoint MUST send a Close frame in response. ]*/
+                                    /* Codes_SRS_UWS_CLIENT_01_242: [ It SHOULD do so as soon as practical. ]*/
+                                    /* Codes_SRS_UWS_CLIENT_01_239: [ Close frames sent from client to server must be masked as per Section 5.3. ]*/
+                                    /* Codes_SRS_UWS_CLIENT_01_140: [ To avoid confusing network intermediaries (such as intercepting proxies) and for security reasons that are further discussed in Section 10.3, a client MUST mask all frames that it sends to the server (see Section 5.3 for further details). ]*/
+                                    close_frame_buffer = uws_frame_encoder_encode(WS_CLOSE_FRAME, NULL, 0, true, true, 0);
+                                    if (close_frame_buffer == NULL)
+                                    {
+                                        LogError("Cannot encode the response CLOSE frame");
+
+                                        /* Codes_SRS_UWS_CLIENT_01_288: [ To _Close the WebSocket Connection_, an endpoint closes the underlying TCP connection. ]*/
+                                        /* Codes_SRS_UWS_CLIENT_01_290: [ An endpoint MAY close the connection via any means available when necessary, such as when under attack. ]*/
+                                        uws_client->uws_state = UWS_STATE_CLOSING_UNDERLYING_IO;
+                                        if (xio_close(uws_client->underlying_io, on_underlying_io_close_complete, uws_client) != 0)
+                                        {
+                                            indicate_ws_error(uws_client, WS_ERROR_CANNOT_CLOSE_UNDERLYING_IO);
+                                            uws_client->uws_state = UWS_STATE_CLOSED;
+                                        }
+                                    }
+                                    else
+                                    {
+                                        close_frame_bytes = BUFFER_u_char(close_frame_buffer);
+                                        close_frame_length = BUFFER_length(close_frame_buffer);
+                                        if (xio_send(uws_client->underlying_io, close_frame_bytes, close_frame_length, on_underlying_io_close_sent, uws_client) != 0)
+                                        {
+                                            LogError("Cannot send the response CLOSE frame");
+
+                                            /* Codes_SRS_UWS_CLIENT_01_288: [ To _Close the WebSocket Connection_, an endpoint closes the underlying TCP connection. ]*/
+                                            /* Codes_SRS_UWS_CLIENT_01_290: [ An endpoint MAY close the connection via any means available when necessary, such as when under attack. ]*/
+                                            uws_client->uws_state = UWS_STATE_CLOSING_UNDERLYING_IO;
+                                            if (xio_close(uws_client->underlying_io, on_underlying_io_close_complete, uws_client) != 0)
+                                            {
+                                                indicate_ws_error(uws_client, WS_ERROR_CANNOT_CLOSE_UNDERLYING_IO);
+                                                uws_client->uws_state = UWS_STATE_CLOSED;
+                                            }
+                                        }
+
+                                        BUFFER_delete(close_frame_buffer);
+                                    }
+                                }
+
+                                /* Codes_SRS_UWS_CLIENT_01_460: [ When a CLOSE frame is received the callback on_ws_peer_closed passed to uws_client_open_async shall be called, while passing to it the argument on_ws_peer_closed_context. ]*/
+                                uws_client->on_ws_peer_closed(uws_client->on_ws_peer_closed_context, close_code_ptr, extra_data_ptr, extra_data_length);
+
+                                break;
+                            }
+
+                                /* Codes_SRS_UWS_CLIENT_01_157: [ *  %x9 denotes a ping ]*/
+                                /* Codes_SRS_UWS_CLIENT_01_247: [ The Ping frame contains an opcode of 0x9. ]*/
+                                /* Codes_SRS_UWS_CLIENT_01_251: [ An endpoint MAY send a Ping frame any time after the connection is established and before the connection is closed. ]*/
+                                /* Codes_SRS_UWS_CLIENT_01_214: [ Control frames (see Section 5.5) MAY be injected in the middle of a fragmented message. ]*/
+                            case (unsigned char)WS_PING_FRAME:
+                            {
+                                /* Codes_SRS_UWS_CLIENT_01_249: [ Upon receipt of a Ping frame, an endpoint MUST send a Pong frame in response ]*/
+                                /* Codes_SRS_UWS_CLIENT_01_250: [ It SHOULD respond with Pong frame as soon as is practical. ]*/
+                                unsigned char* pong_frame;
+                                size_t pong_frame_length;
+                                BUFFER_HANDLE pong_frame_buffer;
+
+                                /* Codes_SRS_UWS_CLIENT_01_215: [ Control frames themselves MUST NOT be fragmented. ]*/
+                                if (!is_final)
+                                {
+                                    LogError("Fragmented control frame received.");
+                                    indicate_ws_error(uws_client, WS_ERROR_BAD_FRAME_RECEIVED);
+                                    break;
+                                }
+
+                                /* Codes_SRS_UWS_CLIENT_01_140: [ To avoid confusing network intermediaries (such as intercepting proxies) and for security reasons that are further discussed in Section 10.3, a client MUST mask all frames that it sends to the server (see Section 5.3 for further details). ]*/
+                                pong_frame_buffer = uws_frame_encoder_encode(WS_PONG_FRAME, uws_client->stream_buffer + needed_bytes - length, length, true, true, 0);
+                                if (pong_frame_buffer == NULL)
+                                {
+                                    LogError("Encoding of PONG failed.");
+                                }
+                                else
+                                {
+                                    /* Codes_SRS_UWS_CLIENT_01_248: [ A Ping frame MAY include "Application data". ]*/
+                                    pong_frame = BUFFER_u_char(pong_frame_buffer);
+                                    pong_frame_length = BUFFER_length(pong_frame_buffer);
+                                    if (xio_send(uws_client->underlying_io, pong_frame, pong_frame_length, unchecked_on_send_complete, NULL) != 0)
+                                    {
+                                        LogError("Sending PONG frame failed.");
+                                    }
+
+                                    BUFFER_delete(pong_frame_buffer);
+                                }
+
+                                break;
+                            }
+                            /* Codes_SRS_UWS_CLIENT_01_252: [ The Pong frame contains an opcode of 0xA. ]*/
+                            case (unsigned char)WS_PONG_FRAME:
+                                break;
+                            }
+
+                            consume_stream_buffer_bytes(uws_client, needed_bytes);
+                        }
+                    }
+
+                    break;
+                }
+                }
+            }
+        }
+    }
+}
+
+static void on_underlying_io_error(void* context)
+{
+    UWS_CLIENT_HANDLE uws_client = (UWS_CLIENT_HANDLE)context;
+
+    switch (uws_client->uws_state)
+    {
+    default:
+        break;
+
+    case UWS_STATE_CLOSING_WAITING_FOR_CLOSE:
+    case UWS_STATE_CLOSING_SENDING_CLOSE:
+    case UWS_STATE_CLOSING_UNDERLYING_IO:
+        /* Codes_SRS_UWS_CLIENT_01_500: [ The callback on_ws_close_complete shall be called, while passing the on_ws_close_complete_context argument to it. ]*/
+        /* Codes_SRS_UWS_CLIENT_01_377: [ When on_underlying_io_error is called while the uws instance is CLOSING the underlying IO shall be closed by calling xio_close. ]*/
+        (void)xio_close(uws_client->underlying_io, NULL, NULL);
+
+        /* Codes_SRS_UWS_CLIENT_01_499: [ If the CLOSE was due to the peer closing, the callback on_ws_close_complete shall not be called. ]*/
+        indicate_ws_close_complete(uws_client);
+        break;
+
+    case UWS_STATE_OPENING_UNDERLYING_IO:
+    case UWS_STATE_WAITING_FOR_UPGRADE_RESPONSE:
+        /* Codes_SRS_UWS_CLIENT_01_375: [ When on_underlying_io_error is called while uws is OPENING, uws shall report that the open failed by calling the on_ws_open_complete callback passed to uws_client_open_async with WS_OPEN_ERROR_UNDERLYING_IO_ERROR. ]*/
+        /* Codes_SRS_UWS_CLIENT_01_077: [ If this fails (e.g., the server's certificate could not be verified), then the client MUST _Fail the WebSocket Connection_ and abort the connection. ]*/
+        indicate_ws_open_complete_error_and_close(uws_client, WS_OPEN_ERROR_UNDERLYING_IO_ERROR);
+        break;
+
+    case UWS_STATE_OPEN:
+        /* Codes_SRS_UWS_CLIENT_01_376: [ When on_underlying_io_error is called while the uws instance is OPEN, an error shall be reported to the user by calling the on_ws_error callback that was passed to uws_client_open_async with the argument WS_ERROR_UNDERLYING_IO_ERROR. ]*/
+        /* Codes_SRS_UWS_CLIENT_01_318: [ Servers MAY close the WebSocket connection whenever desired. ]*/
+        /* Codes_SRS_UWS_CLIENT_01_269: [ If at any point the state of the WebSocket connection changes, the endpoint MUST abort the following steps. ]*/
+        indicate_ws_error(uws_client, WS_ERROR_UNDERLYING_IO_ERROR);
+        break;
+    }
+}
+
+int uws_client_open_async(UWS_CLIENT_HANDLE uws_client, ON_WS_OPEN_COMPLETE on_ws_open_complete, void* on_ws_open_complete_context, ON_WS_FRAME_RECEIVED on_ws_frame_received, void* on_ws_frame_received_context, ON_WS_PEER_CLOSED on_ws_peer_closed, void* on_ws_peer_closed_context, ON_WS_ERROR on_ws_error, void* on_ws_error_context)
+{
+    int result;
+
+    /* Codes_SRS_UWS_CLIENT_01_393: [ The context arguments for the callbacks shall be allowed to be NULL. ]*/
+    if ((uws_client == NULL) ||
+        (on_ws_open_complete == NULL) ||
+        (on_ws_frame_received == NULL) ||
+        (on_ws_peer_closed == NULL) ||
+        (on_ws_error == NULL))
+    {
+        /* Codes_SRS_UWS_CLIENT_01_027: [ If uws_client, on_ws_open_complete, on_ws_frame_received, on_ws_peer_closed or on_ws_error is NULL, uws_client_open_async shall fail and return a non-zero value. ]*/
+        LogError("Invalid arguments: uws=%p, on_ws_open_complete=%p, on_ws_frame_received=%p, on_ws_error=%p",
+            uws_client, on_ws_open_complete, on_ws_frame_received, on_ws_error);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        if (uws_client->uws_state != UWS_STATE_CLOSED)
+        {
+            /* Codes_SRS_UWS_CLIENT_01_400: [ uws_client_open_async while CLOSING shall fail and return a non-zero value. ]*/
+            /* Codes_SRS_UWS_CLIENT_01_394: [ uws_client_open_async while the uws instance is already OPEN or OPENING shall fail and return a non-zero value. ]*/
+            LogError("Invalid uWS state while trying to open: %d", (int)uws_client->uws_state);
+            result = MU_FAILURE;
+        }
+        else
+        {
+            uws_client->uws_state = UWS_STATE_OPENING_UNDERLYING_IO;
+
+            uws_client->stream_buffer_count = 0;
+            uws_client->fragment_buffer_count = 0;
+            uws_client->fragmented_frame_type = WS_FRAME_TYPE_UNKNOWN;
+
+            uws_client->on_ws_open_complete = on_ws_open_complete;
+            uws_client->on_ws_open_complete_context = on_ws_open_complete_context;
+            uws_client->on_ws_frame_received = on_ws_frame_received;
+            uws_client->on_ws_frame_received_context = on_ws_frame_received_context;
+            uws_client->on_ws_peer_closed = on_ws_peer_closed;
+            uws_client->on_ws_peer_closed_context = on_ws_peer_closed_context;
+            uws_client->on_ws_error = on_ws_error;
+            uws_client->on_ws_error_context = on_ws_error_context;
+
+            /* Codes_SRS_UWS_CLIENT_01_025: [ uws_client_open_async shall open the underlying IO by calling xio_open and providing the IO handle created in uws_client_create as argument. ]*/
+            /* Codes_SRS_UWS_CLIENT_01_367: [ The callbacks on_underlying_io_open_complete, on_underlying_io_bytes_received and on_underlying_io_error shall be passed as arguments to xio_open. ]*/
+            /* Codes_SRS_UWS_CLIENT_01_061: [ To _Establish a WebSocket Connection_, a client opens a connection and sends a handshake as defined in this section. ]*/
+            if (xio_open(uws_client->underlying_io, on_underlying_io_open_complete, uws_client, on_underlying_io_bytes_received, uws_client, on_underlying_io_error, uws_client) != 0)
+            {
+                /* Codes_SRS_UWS_CLIENT_01_028: [ If opening the underlying IO fails then uws_client_open_async shall fail and return a non-zero value. ]*/
+                /* Codes_SRS_UWS_CLIENT_01_075: [ If the connection could not be opened, either because a direct connection failed or because any proxy used returned an error, then the client MUST _Fail the WebSocket Connection_ and abort the connection attempt. ]*/
+                LogError("Opening the underlying IO failed");
+                uws_client->uws_state = UWS_STATE_CLOSED;
+                result = MU_FAILURE;
+            }
+            else
+            {
+                /* Codes_SRS_UWS_CLIENT_01_026: [ On success, uws_client_open_async shall return 0. ]*/
+                result = 0;
+            }
+        }
+    }
+
+    return result;
+}
+
+static int complete_send_frame(WS_PENDING_SEND* ws_pending_send, LIST_ITEM_HANDLE pending_send_frame_item, WS_SEND_FRAME_RESULT ws_send_frame_result)
+{
+    int result;
+    UWS_CLIENT_INSTANCE* uws_client = ws_pending_send->uws_client;
+
+    /* Codes_SRS_UWS_CLIENT_01_432: [ The indicated sent frame shall be removed from the list by calling singlylinkedlist_remove. ]*/
+    if (singlylinkedlist_remove(uws_client->pending_sends, pending_send_frame_item) != 0)
+    {
+        LogError("Failed removing item from list");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        if (ws_pending_send->on_ws_send_frame_complete != NULL)
+        {
+            /* Codes_SRS_UWS_CLIENT_01_037: [ When indicating pending send frames as cancelled the callback context passed to the on_ws_send_frame_complete callback shall be the context given to uws_client_send_frame_async. ]*/
+            ws_pending_send->on_ws_send_frame_complete(ws_pending_send->context, ws_send_frame_result);
+        }
+
+        /* Codes_SRS_UWS_CLIENT_01_434: [ The memory associated with the sent frame shall be freed. ]*/
+        free(ws_pending_send);
+
+        result = 0;
+    }
+
+    return result;
+}
+
+/* Codes_SRS_UWS_CLIENT_01_029: [ uws_client_close_async shall close the uws instance connection if an open action is either pending or has completed successfully (if the IO is open). ]*/
+/* Codes_SRS_UWS_CLIENT_01_317: [ Clients SHOULD NOT close the WebSocket connection arbitrarily. ]*/
+int uws_client_close_async(UWS_CLIENT_HANDLE uws_client, ON_WS_CLOSE_COMPLETE on_ws_close_complete, void* on_ws_close_complete_context)
+{
+    int result;
+
+    /* Codes_SRS_UWS_CLIENT_01_397: [ The on_ws_close_complete argument shall be allowed to be NULL, in which case no callback shall be called when the close is complete. ]*/
+    /* Codes_SRS_UWS_CLIENT_01_398: [ on_ws_close_complete_context shall also be allows to be NULL. ]*/
+    if (uws_client == NULL)
+    {
+        /* Codes_SRS_UWS_CLIENT_01_030: [ if uws_client is NULL, uws_client_close_async shall return a non-zero value. ]*/
+        LogError("NULL uWS handle.");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        if ((uws_client->uws_state == UWS_STATE_CLOSED) ||
+            (uws_client->uws_state == UWS_STATE_CLOSING_SENDING_CLOSE) ||
+            (uws_client->uws_state == UWS_STATE_CLOSING_WAITING_FOR_CLOSE) ||
+            (uws_client->uws_state == UWS_STATE_CLOSING_UNDERLYING_IO))
+        {
+            /* Codes_SRS_UWS_CLIENT_01_032: [ uws_client_close_async when no open action has been issued shall fail and return a non-zero value. ]*/
+            LogError("close has been called when already CLOSED");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            /* Codes_SRS_UWS_CLIENT_01_399: [ on_ws_close_complete and on_ws_close_complete_context shall be saved and the callback on_ws_close_complete shall be triggered when the close is complete. ]*/
+            uws_client->on_ws_close_complete = on_ws_close_complete;
+            uws_client->on_ws_close_complete_context = on_ws_close_complete_context;
+
+            uws_client->uws_state = UWS_STATE_CLOSING_UNDERLYING_IO;
+
+            /* Codes_SRS_UWS_CLIENT_01_031: [ uws_client_close_async shall close the connection by calling xio_close while passing as argument the IO handle created in uws_client_create. ]*/
+            /* Codes_SRS_UWS_CLIENT_01_368: [ The callback on_underlying_io_close shall be passed as argument to xio_close. ]*/
+            if (xio_close(uws_client->underlying_io, (on_ws_close_complete == NULL) ? NULL :  on_underlying_io_close_complete, (on_ws_close_complete == NULL) ? NULL : uws_client) != 0)
+            {
+                /* Codes_SRS_UWS_CLIENT_01_395: [ If xio_close fails, uws_client_close_async shall fail and return a non-zero value. ]*/
+                LogError("Closing the underlying IO failed.");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                /* Codes_SRS_UWS_CLIENT_01_034: [ uws_client_close_async shall obtain all the pending send frames by repetitively querying for the head of the pending IO list and freeing that head item. ]*/
+                LIST_ITEM_HANDLE first_pending_send;
+
+                /* Codes_SRS_UWS_CLIENT_01_035: [ Obtaining the head of the pending send frames list shall be done by calling singlylinkedlist_get_head_item. ]*/
+                while ((first_pending_send = singlylinkedlist_get_head_item(uws_client->pending_sends)) != NULL)
+                {
+                    WS_PENDING_SEND* ws_pending_send = (WS_PENDING_SEND*)singlylinkedlist_item_get_value(first_pending_send);
+
+                    /* Codes_SRS_UWS_CLIENT_01_036: [ For each pending send frame the send complete callback shall be called with UWS_SEND_FRAME_CANCELLED. ]*/
+                    complete_send_frame(ws_pending_send, first_pending_send, WS_SEND_FRAME_CANCELLED);
+                }
+
+                /* Codes_SRS_UWS_CLIENT_01_396: [ On success uws_client_close_async shall return 0. ]*/
+                result = 0;
+            }
+        }
+    }
+
+    return result;
+}
+
+/* Codes_SRS_UWS_CLIENT_01_317: [ Clients SHOULD NOT close the WebSocket connection arbitrarily. ]*/
+int uws_client_close_handshake_async(UWS_CLIENT_HANDLE uws_client, uint16_t close_code, const char* close_reason, ON_WS_CLOSE_COMPLETE on_ws_close_complete, void* on_ws_close_complete_context)
+{
+    int result;
+
+    if (uws_client == NULL)
+    {
+        /* Codes_SRS_UWS_CLIENT_01_467: [ if uws_client is NULL, uws_client_close_handshake_async shall return a non-zero value. ]*/
+        LogError("NULL uws_client");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        if ((uws_client->uws_state == UWS_STATE_CLOSED) ||
+            /* Codes_SRS_UWS_CLIENT_01_474: [ uws_client_close_handshake_async when already CLOSING shall fail and return a non-zero value. ]*/
+            (uws_client->uws_state == UWS_STATE_CLOSING_WAITING_FOR_CLOSE) ||
+            (uws_client->uws_state == UWS_STATE_CLOSING_SENDING_CLOSE) ||
+            (uws_client->uws_state == UWS_STATE_CLOSING_UNDERLYING_IO))
+        {
+            /* Codes_SRS_UWS_CLIENT_01_473: [ uws_client_close_handshake_async when no open action has been issued shall fail and return a non-zero value. ]*/
+            LogError("uws_client_close_handshake_async has been called when already CLOSED");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            (void)close_reason;
+
+            /* Codes_SRS_UWS_CLIENT_01_468: [ on_ws_close_complete and on_ws_close_complete_context shall be saved and the callback on_ws_close_complete shall be triggered when the close is complete. ]*/
+            /* Codes_SRS_UWS_CLIENT_01_469: [ The on_ws_close_complete argument shall be allowed to be NULL, in which case no callback shall be called when the close is complete. ]*/
+            /* Codes_SRS_UWS_CLIENT_01_470: [ on_ws_close_complete_context shall also be allowed to be NULL. ]*/
+            uws_client->on_ws_close_complete = on_ws_close_complete;
+            uws_client->on_ws_close_complete_context = on_ws_close_complete_context;
+
+            uws_client->uws_state = UWS_STATE_CLOSING_WAITING_FOR_CLOSE;
+
+            /* Codes_SRS_UWS_CLIENT_01_465: [ uws_client_close_handshake_async shall initiate the close handshake by sending a close frame to the peer. ]*/
+            if (send_close_frame(uws_client, close_code) != 0)
+            {
+                /* Codes_SRS_UWS_CLIENT_01_472: [ If xio_send fails, uws_client_close_handshake_async shall fail and return a non-zero value. ]*/
+                LogError("Sending CLOSE frame failed");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                LIST_ITEM_HANDLE first_pending_send;
+
+                while ((first_pending_send = singlylinkedlist_get_head_item(uws_client->pending_sends)) != NULL)
+                {
+                    WS_PENDING_SEND* ws_pending_send = (WS_PENDING_SEND*)singlylinkedlist_item_get_value(first_pending_send);
+
+                    complete_send_frame(ws_pending_send, first_pending_send, WS_SEND_FRAME_CANCELLED);
+                }
+
+                /* Codes_SRS_UWS_CLIENT_01_466: [ On success uws_client_close_handshake_async shall return 0. ]*/
+                result = 0;
+            }
+        }
+    }
+
+    return result;
+}
+
+static void on_underlying_io_send_complete(void* context, IO_SEND_RESULT send_result)
+{
+    if (context == NULL)
+    {
+        /* Codes_SRS_UWS_CLIENT_01_435: [ When on_underlying_io_send_complete is called with a NULL context, it shall do nothing. ]*/
+        LogError("on_underlying_io_send_complete called with NULL context");
+    }
+    else
+    {
+        LIST_ITEM_HANDLE ws_pending_send_list_item = (LIST_ITEM_HANDLE)context;
+        WS_PENDING_SEND* ws_pending_send = (WS_PENDING_SEND*)singlylinkedlist_item_get_value(ws_pending_send_list_item);
+        if (ws_pending_send != NULL)
+        {
+            UWS_CLIENT_HANDLE uws_client = ws_pending_send->uws_client;
+            WS_SEND_FRAME_RESULT ws_send_frame_result;
+
+            switch (send_result)
+            {
+                /* Codes_SRS_UWS_CLIENT_01_436: [ When on_underlying_io_send_complete is called with any other error code, the send shall be indicated to the uws user by calling on_ws_send_frame_complete with WS_SEND_FRAME_ERROR. ]*/
+            default:
+            case IO_SEND_ERROR:
+                /* Codes_SRS_UWS_CLIENT_01_390: [ When on_underlying_io_send_complete is called with IO_SEND_ERROR as a result of sending a WebSocket frame to the underlying IO, the send shall be indicated to the uws user by calling on_ws_send_frame_complete with WS_SEND_FRAME_ERROR. ]*/
+                ws_send_frame_result = WS_SEND_FRAME_ERROR;
+                break;
+
+            case IO_SEND_OK:
+                /* Codes_SRS_UWS_CLIENT_01_389: [ When on_underlying_io_send_complete is called with IO_SEND_OK as a result of sending a WebSocket frame to the underlying IO, the send shall be indicated to the uws user by calling on_ws_send_frame_complete with WS_SEND_FRAME_OK. ]*/
+                ws_send_frame_result = WS_SEND_FRAME_OK;
+                break;
+
+            case IO_SEND_CANCELLED:
+                /* Codes_SRS_UWS_CLIENT_01_391: [ When on_underlying_io_send_complete is called with IO_SEND_CANCELLED as a result of sending a WebSocket frame to the underlying IO, the send shall be indicated to the uws user by calling on_ws_send_frame_complete with WS_SEND_FRAME_CANCELLED. ]*/
+                ws_send_frame_result = WS_SEND_FRAME_CANCELLED;
+                break;
+            }
+
+            if (complete_send_frame(ws_pending_send, ws_pending_send_list_item, ws_send_frame_result) != 0)
+            {
+                /* Codes_SRS_UWS_CLIENT_01_433: [ If singlylinkedlist_remove fails an error shall be indicated by calling the on_ws_error callback with WS_ERROR_CANNOT_REMOVE_SENT_ITEM_FROM_LIST. ]*/
+                indicate_ws_error(uws_client, WS_ERROR_CANNOT_REMOVE_SENT_ITEM_FROM_LIST);
+            }
+        }
+        else
+        {
+            LogError("Failing getting singlylinkedlist_item_get_value on_underlying_io_send_complete");
+        }
+    }
+}
+
+static bool find_list_node(LIST_ITEM_HANDLE list_item, const void* match_context)
+{
+    return list_item == (LIST_ITEM_HANDLE)match_context;
+}
+
+int uws_client_send_frame_async(UWS_CLIENT_HANDLE uws_client, unsigned char frame_type, const unsigned char* buffer, size_t size, bool is_final, ON_WS_SEND_FRAME_COMPLETE on_ws_send_frame_complete, void* on_ws_send_frame_complete_context)
+{
+    int result;
+
+    if (uws_client == NULL)
+    {
+        /* Codes_SRS_UWS_CLIENT_01_044: [ If any the arguments uws_client is NULL, uws_client_send_frame_async shall fail and return a non-zero value. ]*/
+        LogError("NULL uws handle.");
+        result = MU_FAILURE;
+    }
+    else if ((buffer == NULL) &&
+        (size > 0))
+    {
+        /* Codes_SRS_UWS_CLIENT_01_045: [ If size is non-zero and buffer is NULL then uws_client_send_frame_async shall fail and return a non-zero value. ]*/
+        LogError("NULL buffer with %u size.", (unsigned int)size);
+        result = MU_FAILURE;
+    }
+    /* Codes_SRS_UWS_CLIENT_01_146: [ A data frame MAY be transmitted by either the client or the server at any time after opening handshake completion and before that endpoint has sent a Close frame (Section 5.5.1). ]*/
+    /* Codes_SRS_UWS_CLIENT_01_268: [ The endpoint MUST ensure the WebSocket connection is in the OPEN state ]*/
+    else if (uws_client->uws_state != UWS_STATE_OPEN)
+    {
+        /* Codes_SRS_UWS_CLIENT_01_043: [ If the uws instance is not OPEN (open has not been called or is still in progress) then uws_client_send_frame_async shall fail and return a non-zero value. ]*/
+        LogError("uws not in OPEN state.");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        WS_PENDING_SEND* ws_pending_send = (WS_PENDING_SEND*)malloc(sizeof(WS_PENDING_SEND));
+        if (ws_pending_send == NULL)
+        {
+            /* Codes_SRS_UWS_CLIENT_01_047: [ If allocating memory for the newly queued item fails, uws_client_send_frame_async shall fail and return a non-zero value. ]*/
+            LogError("Cannot allocate memory for frame to be sent.");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            BUFFER_HANDLE non_control_frame_buffer;
+
+            /* Codes_SRS_UWS_CLIENT_01_425: [ Encoding shall be done by calling uws_frame_encoder_encode and passing to it the buffer and size argument for payload, the is_final flag and setting is_masked to true. ]*/
+            /* Codes_SRS_UWS_CLIENT_01_270: [ An endpoint MUST encapsulate the /data/ in a WebSocket frame as defined in Section 5.2. ]*/
+            /* Codes_SRS_UWS_CLIENT_01_272: [ The opcode (frame-opcode) of the first frame containing the data MUST be set to the appropriate value from Section 5.2 for data that is to be interpreted by the recipient as text or binary data. ]*/
+            /* Codes_SRS_UWS_CLIENT_01_274: [ If the data is being sent by the client, the frame(s) MUST be masked as defined in Section 5.3. ]*/
+            non_control_frame_buffer = uws_frame_encoder_encode((WS_FRAME_TYPE)frame_type, buffer, size, true, is_final, 0);
+            if (non_control_frame_buffer == NULL)
+            {
+                /* Codes_SRS_UWS_CLIENT_01_426: [ If uws_frame_encoder_encode fails, uws_client_send_frame_async shall fail and return a non-zero value. ]*/
+                LogError("Failed encoding WebSocket frame");
+                free(ws_pending_send);
+                result = MU_FAILURE;
+            }
+            else
+            {
+                const unsigned char* encoded_frame;
+                size_t encoded_frame_length;
+                LIST_ITEM_HANDLE new_pending_send_list_item;
+
+                /* Codes_SRS_UWS_CLIENT_01_428: [ The encoded frame buffer memory shall be obtained by calling BUFFER_u_char on the encode buffer. ]*/
+                encoded_frame = BUFFER_u_char(non_control_frame_buffer);
+                /* Codes_SRS_UWS_CLIENT_01_429: [ The encoded frame size shall be obtained by calling BUFFER_length on the encode buffer. ]*/
+                encoded_frame_length = BUFFER_length(non_control_frame_buffer);
+
+                /* Codes_SRS_UWS_CLIENT_01_038: [ uws_client_send_frame_async shall create and queue a structure that contains: ]*/
+                /* Codes_SRS_UWS_CLIENT_01_050: [ The argument on_ws_send_frame_complete shall be optional, if NULL is passed by the caller then no send complete callback shall be triggered. ]*/
+                /* Codes_SRS_UWS_CLIENT_01_040: [ - the send complete callback on_ws_send_frame_complete ]*/
+                /* Codes_SRS_UWS_CLIENT_01_041: [ - the send complete callback context on_ws_send_frame_complete_context ]*/
+                ws_pending_send->on_ws_send_frame_complete = on_ws_send_frame_complete;
+                ws_pending_send->context = on_ws_send_frame_complete_context;
+                ws_pending_send->uws_client = uws_client;
+
+                /* Codes_SRS_UWS_CLIENT_01_048: [ Queueing shall be done by calling singlylinkedlist_add. ]*/
+                new_pending_send_list_item = singlylinkedlist_add(uws_client->pending_sends, ws_pending_send);
+                if (new_pending_send_list_item == NULL)
+                {
+                    /* Codes_SRS_UWS_CLIENT_01_049: [ If singlylinkedlist_add fails, uws_client_send_frame_async shall fail and return a non-zero value. ]*/
+                    LogError("Could not allocate memory for pending frames");
+                    free(ws_pending_send);
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    /* Codes_SRS_UWS_CLIENT_01_431: [ Once encoded the frame shall be sent by using xio_send with the following arguments: ]*/
+                    /* Codes_SRS_UWS_CLIENT_01_053: [ - the io handle shall be the underlyiong IO handle created in uws_client_create. ]*/
+                    /* Codes_SRS_UWS_CLIENT_01_054: [ - the buffer argument shall point to the complete websocket frame to be sent. ]*/
+                    /* Codes_SRS_UWS_CLIENT_01_055: [ - the size argument shall indicate the websocket frame length. ]*/
+                    /* Codes_SRS_UWS_CLIENT_01_056: [ - the send_complete callback shall be the on_underlying_io_send_complete function. ]*/
+                    /* Codes_SRS_UWS_CLIENT_01_057: [ - the send_complete_context argument shall identify the pending send. ]*/
+                    /* Codes_SRS_UWS_CLIENT_01_276: [ The frame(s) that have been formed MUST be transmitted over the underlying network connection. ]*/
+                    if (xio_send(uws_client->underlying_io, encoded_frame, encoded_frame_length, on_underlying_io_send_complete, new_pending_send_list_item) != 0)
+                    {
+                        /* Codes_SRS_UWS_CLIENT_01_058: [ If xio_send fails, uws_client_send_frame_async shall fail and return a non-zero value. ]*/
+                        LogError("Could not send bytes through the underlying IO");
+
+                        /* Codes_SRS_UWS_CLIENT_09_001: [ If xio_send fails and the message is still queued, it shall be de-queued and destroyed. ] */
+                        if (singlylinkedlist_find(uws_client->pending_sends, find_list_node, new_pending_send_list_item) != NULL)
+                        {
+                            // Guards against double free in case the underlying I/O invoked 'on_underlying_io_send_complete' within xio_send.
+                            (void)singlylinkedlist_remove(uws_client->pending_sends, new_pending_send_list_item);
+                            free(ws_pending_send);
+                        }
+
+                        result = MU_FAILURE;
+                    }
+                    else
+                    {
+                        /* Codes_SRS_UWS_CLIENT_01_042: [ On success, uws_client_send_frame_async shall return 0. ]*/
+                        result = 0;
+                    }
+                }
+
+                BUFFER_delete(non_control_frame_buffer);
+            }
+        }
+    }
+
+    return result;
+}
+
+void uws_client_dowork(UWS_CLIENT_HANDLE uws_client)
+{
+    if (uws_client == NULL)
+    {
+        /* Codes_SRS_UWS_CLIENT_01_059: [ If the uws_client argument is NULL, uws_client_dowork shall do nothing. ]*/
+        LogError("NULL uws handle.");
+    }
+    else
+    {
+        /* Codes_SRS_UWS_CLIENT_01_060: [ If the IO is not yet open, uws_client_dowork shall do nothing. ]*/
+        if (uws_client->uws_state != UWS_STATE_CLOSED)
+        {
+            /* Codes_SRS_UWS_CLIENT_01_430: [ uws_client_dowork shall call xio_dowork with the IO handle argument set to the underlying IO created in uws_client_create. ]*/
+            xio_dowork(uws_client->underlying_io);
+        }
+    }
+}
+
+int uws_client_set_option(UWS_CLIENT_HANDLE uws_client, const char* option_name, const void* value)
+{
+    int result;
+
+    if (
+        (uws_client == NULL) ||
+        (option_name == NULL)
+        )
+    {
+        /* Codes_SRS_UWS_CLIENT_01_440: [ If any of the arguments uws_client or option_name is NULL uws_client_set_option shall return a non-zero value. ]*/
+        LogError("invalid parameter (NULL) passed to uws_client_set_option");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        if (strcmp(UWS_CLIENT_OPTIONS, option_name) == 0)
+        {
+            /* Codes_SRS_UWS_CLIENT_01_510: [ If the option name is uWSClientOptions then uws_client_set_option shall call OptionHandler_FeedOptions and pass to it the underlying IO handle and the value argument. ]*/
+            if (OptionHandler_FeedOptions((OPTIONHANDLER_HANDLE)value, uws_client->underlying_io) != OPTIONHANDLER_OK)
+            {
+                /* Codes_SRS_UWS_CLIENT_01_511: [ If OptionHandler_FeedOptions fails, uws_client_set_option shall fail and return a non-zero value. ]*/
+                LogError("OptionHandler_FeedOptions failed");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                /* Codes_SRS_UWS_CLIENT_01_442: [ On success, uws_client_set_option shall return 0. ]*/
+                result = 0;
+            }
+        }
+        else
+        {
+            /* Codes_SRS_UWS_CLIENT_01_441: [ Otherwise all options shall be passed as they are to the underlying IO by calling xio_setoption. ]*/
+            if (xio_setoption(uws_client->underlying_io, option_name, value) != 0)
+            {
+                /* Codes_SRS_UWS_CLIENT_01_443: [ If xio_setoption fails, uws_client_set_option shall fail and return a non-zero value. ]*/
+                LogError("xio_setoption failed.");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                /* Codes_SRS_UWS_CLIENT_01_442: [ On success, uws_client_set_option shall return 0. ]*/
+                result = 0;
+            }
+        }
+    }
+
+    return result;
+}
+
+static void* uws_client_clone_option(const char* name, const void* value)
+{
+    void* result;
+
+    if (
+        (name == NULL) ||
+        (value == NULL)
+        )
+    {
+        /* Codes_SRS_UWS_CLIENT_01_506: [ If uws_client_clone_option is called with NULL name or value it shall return NULL. ]*/
+        LogError("invalid argument detected: const char* name=%p, const void* value=%p", name, value);
+        result = NULL;
+    }
+    else
+    {
+        if (strcmp(name, UWS_CLIENT_OPTIONS) == 0)
+        {
+            /* Codes_SRS_UWS_CLIENT_01_507: [ uws_client_clone_option called with name being uWSClientOptions shall return the same value. ]*/
+            result = (void*)value;
+        }
+        else
+        {
+            /* Codes_SRS_UWS_CLIENT_01_512: [ uws_client_clone_option called with any other option name than uWSClientOptions shall return NULL. ]*/
+            LogError("unknown option: %s", name);
+            result = NULL;
+        }
+    }
+
+    return result;
+}
+
+static void uws_client_destroy_option(const char* name, const void* value)
+{
+    if (
+        (name == NULL) ||
+        (value == NULL)
+        )
+    {
+        /* Codes_SRS_UWS_CLIENT_01_509: [ If uws_client_destroy_option is called with NULL name or value it shall do nothing. ]*/
+        LogError("invalid argument detected: const char* name=%p, const void* value=%p", name, value);
+    }
+    else
+    {
+        if (strcmp(name, UWS_CLIENT_OPTIONS) == 0)
+        {
+            /* Codes_SRS_UWS_CLIENT_01_508: [ uws_client_destroy_option called with the option name being uWSClientOptions shall destroy the value by calling OptionHandler_Destroy. ]*/
+            OptionHandler_Destroy((OPTIONHANDLER_HANDLE)value);
+        }
+        else
+        {
+            /* Codes_SRS_UWS_CLIENT_01_513: [ If uws_client_destroy_option is called with any other name it shall do nothing. ]*/
+            LogError("unknown option: %s", name);
+        }
+    }
+}
+
+OPTIONHANDLER_HANDLE uws_client_retrieve_options(UWS_CLIENT_HANDLE uws_client)
+{
+    OPTIONHANDLER_HANDLE result;
+
+    if (uws_client == NULL)
+    {
+        /* Codes_SRS_UWS_CLIENT_01_444: [ If parameter uws_client is NULL then uws_client_retrieve_options shall fail and return NULL. ]*/
+        LogError("NULL uws handle.");
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_UWS_CLIENT_01_445: [ uws_client_retrieve_options shall call OptionHandler_Create to produce an OPTIONHANDLER_HANDLE and on success return the new OPTIONHANDLER_HANDLE handle. ]*/
+        result = OptionHandler_Create(uws_client_clone_option, uws_client_destroy_option, (pfSetOption)uws_client_set_option);
+        if (result == NULL)
+        {
+            /* Codes_SRS_UWS_CLIENT_01_446: [ If OptionHandler_Create fails then uws_client_retrieve_options shall fail and return NULL. ]*/
+            LogError("OptionHandler_Create failed");
+        }
+        else
+        {
+            /* Codes_SRS_UWS_CLIENT_01_502: [ When calling xio_retrieveoptions the underlying IO handle shall be passed to it. ]*/
+            OPTIONHANDLER_HANDLE underlying_io_options = xio_retrieveoptions(uws_client->underlying_io);
+            if (underlying_io_options == NULL)
+            {
+                /* Codes_SRS_UWS_CLIENT_01_503: [ If xio_retrieveoptions fails, uws_client_retrieve_options shall fail and return NULL. ]*/
+                LogError("unable to concrete_io_retrieveoptions");
+                OptionHandler_Destroy(result);
+                result = NULL;
+            }
+            else
+            {
+                /* Codes_SRS_UWS_CLIENT_01_501: [ uws_client_retrieve_options shall add to the option handler one option, whose name shall be uWSClientOptions and the value shall be queried by calling xio_retrieveoptions. ]*/
+                /* Codes_SRS_UWS_CLIENT_01_504: [ Adding the option shall be done by calling OptionHandler_AddOption. ]*/
+                if (OptionHandler_AddOption(result, UWS_CLIENT_OPTIONS, underlying_io_options) != OPTIONHANDLER_OK)
+                {
+                    /* Codes_SRS_UWS_CLIENT_01_505: [ If OptionHandler_AddOption fails, uws_client_retrieve_options shall fail and return NULL. ]*/
+                    LogError("OptionHandler_AddOption failed");
+                    OptionHandler_Destroy(underlying_io_options);
+                    OptionHandler_Destroy(result);
+                    result = NULL;
+                }
+            }
+        }
+
+    }
+
+    return result;
+}
+
+int uws_client_set_request_header(UWS_CLIENT_HANDLE uws_client, const char* name, const char* value)
+{
+    int result;
+
+    if (uws_client == NULL || name == NULL || value == NULL)
+    {
+        // Codes_SRS_UWS_CLIENT_09_002: [ If any of the arguments uws_client or name or value is NULL uws_client_set_request_header shall fail and return a non-zero value. ]
+        LogError("invalid parameter (uws_client=%p, name=%p, value=%p)", uws_client, name, value);
+        result = MU_FAILURE;
+    }
+    // Codes_SRS_UWS_CLIENT_09_003: [ A copy of name and value shall be stored for later sending in the request message. ]
+    else if (Map_AddOrUpdate(uws_client->request_headers, name, value) != MAP_OK)
+    {
+        // Codes_SRS_UWS_CLIENT_09_004: [ If name or value fail to be stored the function shall fail and return a non-zero value. ]
+        LogError("Failed adding request header %s", name);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        // Codes_SRS_UWS_CLIENT_09_005: [ If no failures occur the function shall return zero. ]
+        result = 0;
+    }
+
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/uws_frame_encoder.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/uws_frame_encoder.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/uws_frame_encoder.c	(revision 453)
@@ -0,0 +1,190 @@
+ // Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/gb_rand.h"
+#include "azure_c_shared_utility/uws_frame_encoder.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/buffer_.h"
+#include "azure_c_shared_utility/uniqueid.h"
+
+BUFFER_HANDLE uws_frame_encoder_encode(WS_FRAME_TYPE opcode, const unsigned char* payload, size_t length, bool is_masked, bool is_final, unsigned char reserved)
+{
+    BUFFER_HANDLE result;
+
+    if (reserved > 7)
+    {
+        /* Codes_SRS_UWS_FRAME_ENCODER_01_052: [ If reserved has any bits set except the lowest 3 then uws_frame_encoder_encode shall fail and return NULL. ]*/
+        LogError("Bad reserved value: 0x%02x", reserved);
+        result = NULL;
+    }
+    else if (opcode > 0x0F)
+    {
+        /* Codes_SRS_UWS_FRAME_ENCODER_01_006: [ If an unknown opcode is received, the receiving endpoint MUST _Fail the WebSocket Connection_. ]*/
+        LogError("Invalid opcode: 0x%02x", opcode);
+        result = NULL;
+    }
+    else if ((length > 0) &&
+        (payload == NULL))
+    {
+        /* Codes_SRS_UWS_FRAME_ENCODER_01_054: [ If length is greater than 0 and payload is NULL, then uws_frame_encoder_encode shall fail and return NULL. ]*/
+        LogError("Invalid arguments: NULL payload and length=%u", (unsigned int)length);
+        result = NULL;
+    }
+    else
+    {
+        size_t needed_bytes = 2;
+        size_t header_bytes;
+
+        /* Codes_SRS_UWS_FRAME_ENCODER_01_044: [ On success uws_frame_encoder_encode shall return a non-NULL handle to the result buffer. ]*/
+        /* Codes_SRS_UWS_FRAME_ENCODER_01_048: [ The newly created buffer shall be created by calling BUFFER_new. ]*/
+        result = BUFFER_new();
+        if (result == NULL)
+        {
+            /* Codes_SRS_UWS_FRAME_ENCODER_01_049: [ If BUFFER_new fails then uws_frame_encoder_encode shall fail and return NULL. ]*/
+            LogError("Cannot create new buffer");
+        }
+        else
+        {
+            /* Codes_SRS_UWS_FRAME_ENCODER_01_001: [ uws_frame_encoder_encode shall encode the information given in opcode, payload, length, is_masked, is_final and reserved according to the RFC6455 into a new buffer.]*/
+            if (length > 65535)
+            {
+                needed_bytes += 8;
+            }
+            else if (length > 125)
+            {
+                needed_bytes += 2;
+            }
+
+            if (is_masked)
+            {
+                needed_bytes += 4;
+            }
+
+            header_bytes = needed_bytes;
+            needed_bytes += length;
+
+            /* Codes_SRS_UWS_FRAME_ENCODER_01_046: [ The result buffer shall be resized accordingly using BUFFER_enlarge. ]*/
+            if (BUFFER_enlarge(result, needed_bytes) != 0)
+            {
+                /* Codes_SRS_UWS_FRAME_ENCODER_01_047: [ If BUFFER_enlarge fails then uws_frame_encoder_encode shall fail and return NULL. ]*/
+                LogError("Cannot allocate memory for encoded frame");
+                BUFFER_delete(result);
+                result = NULL;
+            }
+            else
+            {
+                /* Codes_SRS_UWS_FRAME_ENCODER_01_050: [ The allocated memory shall be accessed by calling BUFFER_u_char. ]*/
+                unsigned char* buffer = BUFFER_u_char(result);
+                if (buffer == NULL)
+                {
+                    /* Codes_SRS_UWS_FRAME_ENCODER_01_051: [ If BUFFER_u_char fails then uws_frame_encoder_encode shall fail and return a NULL. ]*/
+                    LogError("Cannot get encoded buffer pointer");
+                    BUFFER_delete(result);
+                    result = NULL;
+                }
+                else
+                {
+                    /* Codes_SRS_UWS_FRAME_ENCODER_01_007: [ *  %x0 denotes a continuation frame ]*/
+                    /* Codes_SRS_UWS_FRAME_ENCODER_01_008: [ *  %x1 denotes a text frame ]*/
+                    /* Codes_SRS_UWS_FRAME_ENCODER_01_009: [ *  %x2 denotes a binary frame ]*/
+                    /* Codes_SRS_UWS_FRAME_ENCODER_01_010: [ *  %x3-7 are reserved for further non-control frames ]*/
+                    /* Codes_SRS_UWS_FRAME_ENCODER_01_011: [ *  %x8 denotes a connection close ]*/
+                    /* Codes_SRS_UWS_FRAME_ENCODER_01_012: [ *  %x9 denotes a ping ]*/
+                    /* Codes_SRS_UWS_FRAME_ENCODER_01_013: [ *  %xA denotes a pong ]*/
+                    /* Codes_SRS_UWS_FRAME_ENCODER_01_014: [ *  %xB-F are reserved for further control frames ]*/
+                    buffer[0] = (unsigned char)opcode;
+
+                    /* Codes_SRS_UWS_FRAME_ENCODER_01_002: [ Indicates that this is the final fragment in a message. ]*/
+                    /* Codes_SRS_UWS_FRAME_ENCODER_01_003: [ The first fragment MAY also be the final fragment. ]*/
+                    if (is_final)
+                    {
+                        buffer[0] |= 0x80;
+                    }
+
+                    /* Codes_SRS_UWS_FRAME_ENCODER_01_004: [ MUST be 0 unless an extension is negotiated that defines meanings for non-zero values. ]*/
+                    buffer[0] |= reserved << 4;
+
+                    /* Codes_SRS_UWS_FRAME_ENCODER_01_022: [ Note that in all cases, the minimal number of bytes MUST be used to encode the length, for example, the length of a 124-byte-long string can't be encoded as the sequence 126, 0, 124. ]*/
+                    /* Codes_SRS_UWS_FRAME_ENCODER_01_018: [ The length of the "Payload data", in bytes: ]*/
+                    /* Codes_SRS_UWS_FRAME_ENCODER_01_023: [ The payload length is the length of the "Extension data" + the length of the "Application data". ]*/
+                    /* Codes_SRS_UWS_FRAME_ENCODER_01_042: [ The payload length, indicated in the framing as frame-payload-length, does NOT include the length of the masking key. ]*/
+                    if (length > 65535)
+                    {
+                        /* Codes_SRS_UWS_FRAME_ENCODER_01_020: [ If 127, the following 8 bytes interpreted as a 64-bit unsigned integer (the most significant bit MUST be 0) are the payload length. ]*/
+                        buffer[1] = 127;
+
+                        /* Codes_SRS_UWS_FRAME_ENCODER_01_021: [ Multibyte length quantities are expressed in network byte order. ]*/
+                        buffer[2] = (unsigned char)((uint64_t)length >> 56) & 0xFF;
+                        buffer[3] = (unsigned char)((uint64_t)length >> 48) & 0xFF;
+                        buffer[4] = (unsigned char)((uint64_t)length >> 40) & 0xFF;
+                        buffer[5] = (unsigned char)((uint64_t)length >> 32) & 0xFF;
+                        buffer[6] = (unsigned char)((uint64_t)length >> 24) & 0xFF;
+                        buffer[7] = (unsigned char)((uint64_t)length >> 16) & 0xFF;
+                        buffer[8] = (unsigned char)((uint64_t)length >> 8) & 0xFF;
+                        buffer[9] = (unsigned char)(length & 0xFF);
+                    }
+                    else if (length > 125)
+                    {
+                        /* Codes_SRS_UWS_FRAME_ENCODER_01_019: [ If 126, the following 2 bytes interpreted as a 16-bit unsigned integer are the payload length. ]*/
+                        buffer[1] = 126;
+
+                        /* Codes_SRS_UWS_FRAME_ENCODER_01_021: [ Multibyte length quantities are expressed in network byte order. ]*/
+                        buffer[2] = (unsigned char)(length >> 8);
+                        buffer[3] = (unsigned char)(length & 0xFF);
+                    }
+                    else
+                    {
+                        /* Codes_SRS_UWS_FRAME_ENCODER_01_043: [ if 0-125, that is the payload length. ]*/
+                        buffer[1] = (unsigned char)length;
+                    }
+
+                    if (is_masked)
+                    {
+                        /* Codes_SRS_UWS_FRAME_ENCODER_01_015: [ Defines whether the "Payload data" is masked. ]*/
+                        /* Codes_SRS_UWS_FRAME_ENCODER_01_033: [ A masked frame MUST have the field frame-masked set to 1, as defined in Section 5.2. ]*/
+                        buffer[1] |= 0x80;
+
+                        /* Codes_SRS_UWS_FRAME_ENCODER_01_053: [ In order to obtain a 32 bit value for masking, gb_rand shall be used 4 times (for each byte). ]*/
+                        /* Codes_SRS_UWS_FRAME_ENCODER_01_016: [ If set to 1, a masking key is present in masking-key, and this is used to unmask the "Payload data" as per Section 5.3. ]*/
+                        /* Codes_SRS_UWS_FRAME_ENCODER_01_026: [ This field is present if the mask bit is set to 1 and is absent if the mask bit is set to 0. ]*/
+                        /* Codes_SRS_UWS_FRAME_ENCODER_01_034: [ The masking key is contained completely within the frame, as defined in Section 5.2 as frame-masking-key. ]*/
+                        /* Codes_SRS_UWS_FRAME_ENCODER_01_036: [ The masking key is a 32-bit value chosen at random by the client. ]*/
+                        /* Codes_SRS_UWS_FRAME_ENCODER_01_037: [ When preparing a masked frame, the client MUST pick a fresh masking key from the set of allowed 32-bit values. ]*/
+                        /* Codes_SRS_UWS_FRAME_ENCODER_01_038: [ The masking key needs to be unpredictable; thus, the masking key MUST be derived from a strong source of entropy, and the masking key for a given frame MUST NOT make it simple for a server/proxy to predict the masking key for a subsequent frame. ]*/
+                        buffer[header_bytes - 4] = (unsigned char)gb_rand();
+                        buffer[header_bytes - 3] = (unsigned char)gb_rand();
+                        buffer[header_bytes - 2] = (unsigned char)gb_rand();
+                        buffer[header_bytes - 1] = (unsigned char)gb_rand();
+                    }
+
+                    if (length > 0)
+                    {
+                        if (is_masked)
+                        {
+                            size_t i;
+
+                            /* Codes_SRS_UWS_FRAME_ENCODER_01_035: [ It is used to mask the "Payload data" defined in the same section as frame-payload-data, which includes "Extension data" and "Application data". ]*/
+                            /* Codes_SRS_UWS_FRAME_ENCODER_01_039: [ To convert masked data into unmasked data, or vice versa, the following algorithm is applied. ]*/
+                            /* Codes_SRS_UWS_FRAME_ENCODER_01_040: [ The same algorithm applies regardless of the direction of the translation, e.g., the same steps are applied to mask the data as to unmask the data. ]*/
+                            for (i = 0; i < length; i++)
+                            {
+                                /* Codes_SRS_UWS_FRAME_ENCODER_01_041: [ Octet i of the transformed data ("transformed-octet-i") is the XOR of octet i of the original data ("original-octet-i") with octet at index i modulo 4 of the masking key ("masking-key-octet-j"): ]*/
+                                buffer[header_bytes + i] = ((unsigned char*)payload)[i] ^ buffer[header_bytes - 4 + (i % 4)];
+                            }
+                        }
+                        else
+                        {
+                            (void)memcpy(buffer + header_bytes, payload, length);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/vector.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/vector.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/vector.c	(revision 453)
@@ -0,0 +1,338 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/vector.h"
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/xlogging.h"
+
+#include "azure_c_shared_utility/vector_types_internal.h"
+
+IMPLEMENT_MOCKABLE_FUNCTION(, VECTOR_HANDLE, VECTOR_create, size_t, elementSize)
+{
+    VECTOR_HANDLE result;
+
+    /* Codes_SRS_VECTOR_10_002: [VECTOR_create shall fail and return NULL if elementsize is 0.] */
+    if (elementSize == 0)
+    {
+        LogError("invalid elementSize(%zd).", elementSize);
+        result = NULL;
+    }
+    else
+    {
+        result = (VECTOR*)malloc(sizeof(VECTOR));
+        /* Codes_SRS_VECTOR_10_002 : [VECTOR_create shall fail and return NULL if malloc fails.] */
+        if (result == NULL)
+        {
+            LogError("malloc failed.");
+        }
+        else
+        {
+            /* Codes_SRS_VECTOR_10_001: [VECTOR_create shall allocate a VECTOR_HANDLE that will contain an empty vector.The size of each element is given with the parameter elementSize.] */
+            result->storage = NULL;
+            result->count = 0;
+            result->elementSize = elementSize;
+        }
+    }
+    return result;
+}
+
+IMPLEMENT_MOCKABLE_FUNCTION(, void, VECTOR_destroy, VECTOR_HANDLE, handle)
+{
+    /* Codes_SRS_VECTOR_10_009: [VECTOR_destroy shall return if the given handle is NULL.] */
+    if (handle == NULL)
+    {
+        LogError("invalid argument handle(NULL).");
+    }
+    else
+    {
+        /* Codes_SRS_VECTOR_10_008: [VECTOR_destroy shall free the given handle and its internal storage.] */
+        free(handle->storage);
+        free(handle);
+    }
+}
+
+IMPLEMENT_MOCKABLE_FUNCTION(, VECTOR_HANDLE, VECTOR_move, VECTOR_HANDLE, handle)
+{
+    VECTOR_HANDLE result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_VECTOR_10_005: [VECTOR_move shall fail and return NULL if the given handle is NULL.] */
+        LogError("invalid argument - handle(NULL).");
+        result = NULL;
+    }
+    else
+    {
+        result = (VECTOR*)malloc(sizeof(VECTOR));
+        if (result == NULL)
+        {
+            /* Codes_SRS_VECTOR_10_006: [VECTOR_move shall fail and return NULL if malloc fails.] */
+            LogError("malloc failed.");
+        }
+        else
+        {
+            /* Codes_SRS_VECTOR_10_004: [VECTOR_move shall allocate a VECTOR_HANDLE and move the data to it from the given handle.] */
+            result->count = handle->count;
+            result->elementSize = handle->elementSize;
+            result->storage = handle->storage;
+
+            handle->storage = NULL;
+            handle->count = 0;
+        }
+    }
+    return result;
+}
+
+/* insertion */
+
+IMPLEMENT_MOCKABLE_FUNCTION(, int, VECTOR_push_back, VECTOR_HANDLE, handle, const void*, elements, size_t, numElements)
+{
+    int result;
+    if (handle == NULL || elements == NULL || numElements == 0)
+    {
+       /* Codes_SRS_VECTOR_10_011: [VECTOR_push_back shall fail and return non-zero if handle is NULL.] */
+       /* Codes_SRS_VECTOR_10_034: [VECTOR_push_back shall fail and return non-zero if elements is NULL.] */
+       /* Codes_SRS_VECTOR_10_035: [VECTOR_push_back shall fail and return non-zero if numElements is 0.] */
+        LogError("invalid argument - handle(%p), elements(%p), numElements(%zd).", handle, elements, numElements);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        size_t curSize = handle->elementSize * handle->count;
+        size_t appendSize = handle->elementSize * numElements;
+
+        void* temp = realloc(handle->storage, curSize + appendSize);
+        if (temp == NULL)
+        {
+           /* Codes_SRS_VECTOR_10_012: [VECTOR_push_back shall fail and return non-zero if memory allocation fails.] */
+            LogError("realloc failed.");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            /* Codes_SRS_VECTOR_10_013: [VECTOR_push_back shall append the given elements and return 0 indicating success.] */
+            (void)memcpy((unsigned char*)temp + curSize, elements, appendSize);
+            handle->storage = temp;
+            handle->count += numElements;
+            result = 0;
+        }
+    }
+    return result;
+}
+
+/* removal */
+
+IMPLEMENT_MOCKABLE_FUNCTION(, void, VECTOR_erase, VECTOR_HANDLE, handle, void*, elements, size_t, numElements)
+{
+    if (handle == NULL || elements == NULL || numElements == 0)
+    {
+        /* Codes_SRS_VECTOR_10_015: [VECTOR_erase shall return if handle is NULL.] */
+        /* Codes_SRS_VECTOR_10_038: [VECTOR_erase shall return if elements is NULL.] */
+        /* Codes_SRS_VECTOR_10_039: [VECTOR_erase shall return if numElements is 0.] */
+        LogError("invalid argument - handle(%p), elements(%p), numElements(%zd).", handle, elements, numElements);
+    }
+    else
+    {
+        if (elements < handle->storage)
+        {
+            /* Codes_SRS_VECTOR_10_040: [VECTOR_erase shall return if elements is out of bound.] */
+            LogError("invalid argument elements(%p) is not a member of this object.", elements);
+        }
+        else
+        {
+            ptrdiff_t diff = ((unsigned char*)elements) - ((unsigned char*)handle->storage);
+            if ((diff % handle->elementSize) != 0)
+            {
+                /* Codes_SRS_VECTOR_10_041: [VECTOR_erase shall return if elements is misaligned.] */
+                LogError("invalid argument - elements(%p) is misaligned", elements);
+            }
+            else
+            {
+                /* Compute the arguments needed for memmove. */
+                unsigned char* src = (unsigned char*)elements + (handle->elementSize * numElements);
+                unsigned char* srcEnd = (unsigned char*)handle->storage + (handle->elementSize * handle->count);
+                if (src > srcEnd)
+                {
+                    /* Codes_SRS_VECTOR_10_040: [VECTOR_erase shall return if elements is out of bound.] */
+                    LogError("invalid argument - numElements(%zd) is out of bound.", numElements);
+                }
+                else
+                {
+                    /* Codes_SRS_VECTOR_10_014: [VECTOR_erase shall remove the 'numElements' starting at 'elements' and reduce its internal storage.] */
+                    handle->count -= numElements;
+                    if (handle->count == 0)
+                    {
+                        free(handle->storage);
+                        handle->storage = NULL;
+                    }
+                    else
+                    {
+                        void* tmp;
+                        (void)memmove(elements, src, srcEnd - src);
+                        tmp = realloc(handle->storage, (handle->elementSize * handle->count));
+                        if (tmp == NULL)
+                        {
+                            LogInfo("realloc failed. Keeping original internal storage pointer.");
+                        }
+                        else
+                        {
+                            handle->storage = tmp;
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+IMPLEMENT_MOCKABLE_FUNCTION(, void, VECTOR_clear, VECTOR_HANDLE, handle)
+{
+    /* Codes_SRS_VECTOR_10_017: [VECTOR_clear shall if the object is NULL or empty.] */
+    if (handle == NULL)
+    {
+        LogError("invalid argument handle(NULL).");
+    }
+    else
+    {
+        /* Codes_SRS_VECTOR_10_016: [VECTOR_clear shall remove all elements from the object and release internal storage.] */
+        free(handle->storage);
+        handle->storage = NULL;
+        handle->count = 0;
+    }
+}
+
+/* access */
+
+IMPLEMENT_MOCKABLE_FUNCTION(, void*, VECTOR_element, VECTOR_HANDLE, handle, size_t, index)
+{
+    void* result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_VECTOR_10_019: [VECTOR_element shall fail and return NULL if handle is NULL.] */
+        LogError("invalid argument handle(NULL).");
+        result = NULL;
+    }
+    else
+    {
+        if (index >= handle->count)
+        {
+            /* Codes_SRS_VECTOR_10_020: [VECTOR_element shall fail and return NULL if the given index is out of range.] */
+            LogError("invalid argument - index(%zd); should be >= 0 and < %zd.", index, handle->count);
+            result = NULL;
+        }
+        else
+        {
+            /* Codes_SRS_VECTOR_10_018: [VECTOR_element shall return the element at the given index.] */
+            result = (unsigned char*)handle->storage + (handle->elementSize * index);
+        }
+    }
+    return result;
+}
+
+IMPLEMENT_MOCKABLE_FUNCTION(, void*, VECTOR_front, VECTOR_HANDLE, handle)
+{
+    void* result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_VECTOR_10_022: [VECTOR_front shall fail and return NULL if handle is NULL.] */
+        LogError("invalid argument handle (NULL).");
+        result = NULL;
+    }
+    else
+    {
+        if (handle->count == 0)
+        {
+            /* Codes_SRS_VECTOR_10_028: [VECTOR_front shall return NULL if the vector is empty.] */
+            LogError("vector is empty.");
+            result = NULL;
+        }
+        else
+        {
+            /* Codes_SRS_VECTOR_10_021: [VECTOR_front shall return a pointer to the element at index 0.] */
+            result = handle->storage;
+        }
+    }
+    return result;
+}
+
+IMPLEMENT_MOCKABLE_FUNCTION(, void*, VECTOR_back, VECTOR_HANDLE, handle)
+{
+    void* result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_VECTOR_10_024: [VECTOR_back shall fail and return NULL if handle is NULL.] */
+        LogError("invalid argument handle (NULL).");
+        result = NULL;
+    }
+    else
+    {
+        if (handle->count == 0)
+        {
+            /* Codes_SRS_VECTOR_10_029: [VECTOR_back shall return NULL if the vector is empty.] */
+            LogError("vector is empty.");
+            result = NULL;
+        }
+        else
+        {
+            /* Codes_SRS_VECTOR_10_023: [VECTOR_front shall return the last element of the vector.] */
+            result = (unsigned char*)handle->storage + (handle->elementSize * (handle->count - 1));
+        }
+    }
+    return result;
+}
+
+IMPLEMENT_MOCKABLE_FUNCTION(, void*, VECTOR_find_if, VECTOR_HANDLE, handle, PREDICATE_FUNCTION, pred, const void*, value)
+{
+    void* result;
+    if (handle == NULL || pred == NULL)
+    {
+        /* Codes_SRS_VECTOR_10_030: [VECTOR_find_if shall fail and return NULL if handle is NULL.] */
+        /* Codes_SRS_VECTOR_10_036: [VECTOR_find_if shall fail and return NULL if pred is NULL.] */
+        LogError("invalid argument - handle(%p), pred(%p)", handle, pred);
+        result = NULL;
+    }
+    else
+    {
+        size_t i;
+        for (i = 0; i < handle->count; ++i)
+        {
+            if (true == pred((unsigned char*)handle->storage + (handle->elementSize * i), value))
+            {
+                /* Codes_SRS_VECTOR_10_031: [VECTOR_find_if shall return the first element in the vector that matches pred.] */
+                break;
+            }
+        }
+
+        if (i == handle->count)
+        {
+            /* Codes_SRS_VECTOR_10_032: [VECTOR_find_if shall return NULL if no matching element is found.] */
+            result = NULL;
+        }
+        else
+        {
+            /* Codes_SRS_VECTOR_10_031: [VECTOR_find_if shall return the first element in the vector that matches pred.]*/
+            result = (unsigned char*)handle->storage + (handle->elementSize * i);
+        }
+    }
+    return result;
+}
+
+/* capacity */
+
+IMPLEMENT_MOCKABLE_FUNCTION(, size_t, VECTOR_size, VECTOR_HANDLE, handle)
+{
+    size_t result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_VECTOR_10_026: [**VECTOR_size shall return 0 if the given handle is NULL.] */
+        LogError("invalid argument handle(NULL).");
+        result = 0;
+    }
+    else
+    {
+        /* Codes_SRS_VECTOR_10_025: [VECTOR_size shall return the number of elements stored with the given handle.] */
+        result = handle->count;
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/wsio.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/wsio.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/wsio.c	(revision 453)
@@ -0,0 +1,825 @@
+ // Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/wsio.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/singlylinkedlist.h"
+#include "azure_c_shared_utility/optionhandler.h"
+#include "azure_c_shared_utility/xio.h"
+#include "azure_c_shared_utility/shared_util_options.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/uws_client.h"
+#include "azure_c_shared_utility/optimize_size.h"
+
+static const char* WSIO_OPTIONS = "WSIOOptions";
+
+typedef enum IO_STATE_TAG
+{
+    IO_STATE_NOT_OPEN,
+    IO_STATE_OPENING,
+    IO_STATE_OPEN,
+    IO_STATE_CLOSING,
+    IO_STATE_ERROR
+} IO_STATE;
+
+typedef struct PENDING_IO_TAG
+{
+    ON_SEND_COMPLETE on_send_complete;
+    void* callback_context;
+    void* wsio;
+} PENDING_IO;
+
+typedef struct WSIO_INSTANCE_TAG
+{
+    ON_BYTES_RECEIVED on_bytes_received;
+    void* on_bytes_received_context;
+    ON_IO_OPEN_COMPLETE on_io_open_complete;
+    void* on_io_open_complete_context;
+    ON_IO_ERROR on_io_error;
+    void* on_io_error_context;
+    ON_IO_CLOSE_COMPLETE on_io_close_complete;
+    void* on_io_close_complete_context;
+    IO_STATE io_state;
+    SINGLYLINKEDLIST_HANDLE pending_io_list;
+    UWS_CLIENT_HANDLE uws;
+} WSIO_INSTANCE;
+
+static void indicate_error(WSIO_INSTANCE* wsio_instance)
+{
+    wsio_instance->io_state = IO_STATE_ERROR;
+    wsio_instance->on_io_error(wsio_instance->on_io_error_context);
+}
+
+static void indicate_open_complete(WSIO_INSTANCE* ws_io_instance, IO_OPEN_RESULT open_result)
+{
+    ws_io_instance->on_io_open_complete(ws_io_instance->on_io_open_complete_context, open_result);
+}
+
+static void complete_send_item(LIST_ITEM_HANDLE pending_io_list_item, IO_SEND_RESULT io_send_result)
+{
+    PENDING_IO* pending_io = (PENDING_IO*)singlylinkedlist_item_get_value(pending_io_list_item);
+    WSIO_INSTANCE* wsio_instance = (WSIO_INSTANCE*)pending_io->wsio;
+
+    /* Codes_SRS_WSIO_01_145: [ Removing it from the list shall be done by calling singlylinkedlist_remove. ]*/
+    if (singlylinkedlist_remove(wsio_instance->pending_io_list, pending_io_list_item) != 0)
+    {
+        LogError("Failed removing pending IO from linked list.");
+    }
+
+    /* Codes_SRS_WSIO_01_105: [ The argument on_send_complete shall be optional, if NULL is passed by the caller then no send complete callback shall be triggered. ]*/
+    if (pending_io->on_send_complete != NULL)
+    {
+        pending_io->on_send_complete(pending_io->callback_context, io_send_result);
+    }
+
+    /* Codes_SRS_WSIO_01_144: [ Also the pending IO data shall be freed. ]*/
+    free(pending_io);
+}
+
+static void on_underlying_ws_send_frame_complete(void* context, WS_SEND_FRAME_RESULT ws_send_frame_result)
+{
+    if (context == NULL)
+    {
+        LogError("NULL context for on_underlying_ws_send_frame_complete");
+    }
+    else
+    {
+        IO_SEND_RESULT io_send_result;
+        LIST_ITEM_HANDLE list_item_handle = (LIST_ITEM_HANDLE)context;
+
+        /* Codes_SRS_WSIO_01_143: [ When on_underlying_ws_send_frame_complete is called after sending a WebSocket frame, the pending IO shall be removed from the list. ]*/
+        switch (ws_send_frame_result)
+        {
+        default:
+            /* Codes_SRS_WSIO_01_148: [ When on_underlying_ws_send_frame_complete is called with any other error code, the callback on_send_complete shall be called with IO_SEND_ERROR. ]*/
+            LogError("Frame send error with result %d", (int)ws_send_frame_result);
+            io_send_result = IO_SEND_ERROR;
+            break;
+
+        case WS_SEND_FRAME_OK:
+            /* Codes_SRS_WSIO_01_146: [ When on_underlying_ws_send_frame_complete is called with WS_SEND_OK, the callback on_send_complete shall be called with IO_SEND_OK. ]*/
+            io_send_result = IO_SEND_OK;
+            break;
+
+        case WS_SEND_FRAME_CANCELLED:
+            /* Codes_SRS_WSIO_01_147: [ When on_underlying_ws_send_frame_complete is called with WS_SEND_CANCELLED, the callback on_send_complete shall be called with IO_SEND_CANCELLED. ]*/
+            io_send_result = IO_SEND_CANCELLED;
+            break;
+        }
+
+        complete_send_item(list_item_handle, io_send_result);
+    }
+}
+
+static void on_underlying_ws_close_complete(void* context)
+{
+    WSIO_INSTANCE* wsio_instance = (WSIO_INSTANCE*)context;
+    if (wsio_instance == NULL)
+    {
+        /* Codes_SRS_WSIO_01_161: [ If the context passed to on_underlying_ws_close_complete is NULL, on_underlying_ws_close_complete shall do nothing. ]*/
+        LogError("NULL context passed to on_underlying_ws_close_complete");
+    }
+    else
+    {
+        wsio_instance->io_state = IO_STATE_NOT_OPEN;
+
+        /* Codes_SRS_WSIO_01_160: [ If NULL was passed to wsio_close no callback shall be called. ]*/
+        if (wsio_instance->on_io_close_complete != NULL)
+        {
+            /* Codes_SRS_WSIO_01_159: [ When on_underlying_ws_close_complete while the IO is closing (after wsio_close), the close shall be indicated up by calling the on_io_close_complete callback passed to wsio_close. ]*/
+            /* Codes_SRS_WSIO_01_163: [ When on_io_close_complete is called, the context passed to wsio_close shall be passed as argument to on_io_close_complete. ]*/
+            wsio_instance->on_io_close_complete(wsio_instance->on_io_close_complete_context);
+        }
+    }
+}
+
+static int internal_close(WSIO_INSTANCE* wsio_instance, ON_IO_CLOSE_COMPLETE on_io_close_complete, void* on_io_close_complete_context)
+{
+    int result;
+
+    /* Codes_SRS_WSIO_01_089: [ wsio_close after a wsio_close shall fail and return a non-zero value.  ]*/
+    /* Codes_SRS_WSIO_01_088: [ wsio_close when no open action has been issued shall fail and return a non-zero value. ]*/
+    if (wsio_instance->io_state == IO_STATE_NOT_OPEN)
+    {
+        LogError("wsio_close when not open.");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        if (wsio_instance->io_state == IO_STATE_OPENING)
+        {
+            wsio_instance->io_state = IO_STATE_NOT_OPEN;
+            indicate_open_complete(wsio_instance, IO_OPEN_CANCELLED);
+            result = 0;
+        }
+        else if (wsio_instance->io_state == IO_STATE_CLOSING)
+        {
+            LogError("Already closing");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            LIST_ITEM_HANDLE first_pending_io;
+
+            wsio_instance->io_state = IO_STATE_CLOSING;
+
+            wsio_instance->on_io_close_complete = on_io_close_complete;
+            wsio_instance->on_io_close_complete_context = on_io_close_complete_context;
+
+            /* Codes_SRS_WSIO_01_087: [ wsio_close shall call uws_client_close_async while passing as argument the IO handle created in wsio_create.  ]*/
+            if (uws_client_close_async(wsio_instance->uws, on_underlying_ws_close_complete, wsio_instance) != 0)
+            {
+                /* Codes_SRS_WSIO_01_164: [ When uws_client_close_async fails, wsio_close shall call the on_io_close_complete callback and continue. ] */
+                if (wsio_instance->on_io_close_complete != NULL)
+                {
+                    wsio_instance->on_io_close_complete(wsio_instance->on_io_close_complete_context);
+                }
+            }
+
+            /* Codes_SRS_WSIO_01_085: [ wsio_close shall close the websockets IO if an open action is either pending or has completed successfully (if the IO is open).  ]*/
+            /* Codes_SRS_WSIO_01_091: [ wsio_close shall obtain all the pending IO items by repetitively querying for the head of the pending IO list and freeing that head item. ]*/
+            /* Codes_SRS_WSIO_01_092: [ Obtaining the head of the pending IO list shall be done by calling singlylinkedlist_get_head_item. ]*/
+            while ((first_pending_io = singlylinkedlist_get_head_item(wsio_instance->pending_io_list)) != NULL)
+            {
+                complete_send_item(first_pending_io, IO_SEND_CANCELLED);
+            }
+
+            /* Codes_SRS_WSIO_01_133: [ On success wsio_close shall return 0. ]*/
+            result = 0;
+            wsio_instance->io_state = IO_STATE_NOT_OPEN;
+        }
+    }
+    return result;
+}
+
+CONCRETE_IO_HANDLE wsio_create(void* io_create_parameters)
+{
+    /* Codes_SRS_WSIO_01_066: [ io_create_parameters shall be used as a WSIO_CONFIG* . ]*/
+    WSIO_CONFIG* ws_io_config = (WSIO_CONFIG*)io_create_parameters;
+    WSIO_INSTANCE* result;
+
+    /* Codes_SRS_WSIO_01_065: [ If the argument io_create_parameters is NULL then wsio_create shall return NULL. ]*/
+    if ((ws_io_config == NULL) ||
+        /* Codes_SRS_WSIO_01_067: [ If any of the members hostname, resource_name or protocol is NULL in WSIO_CONFIG then wsio_create shall return NULL. ]*/
+        (ws_io_config->hostname == NULL) ||
+        (ws_io_config->resource_name == NULL) ||
+        (ws_io_config->protocol == NULL))
+    {
+        LogError("NULL io_create_parameters.");
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_WSIO_01_001: [wsio_create shall create an instance of wsio and return a non-NULL handle to it.] */
+        result = (WSIO_INSTANCE*)calloc(1, sizeof(WSIO_INSTANCE));
+        if (result == NULL)
+        {
+            /* Codes_SRS_WSIO_01_068: [ If allocating memory for the new wsio instance fails then wsio_create shall return NULL. ]*/
+            LogError("Cannot allocate memory for the new WSIO instance.");
+        }
+        else
+        {
+            WS_PROTOCOL protocols;
+
+            protocols.protocol = ws_io_config->protocol;
+
+            result->on_bytes_received = NULL;
+            result->on_bytes_received_context = NULL;
+            result->on_io_open_complete = NULL;
+            result->on_io_open_complete_context = NULL;
+            result->on_io_error = NULL;
+            result->on_io_error_context = NULL;
+            result->on_io_close_complete = NULL;
+            result->on_io_close_complete_context = NULL;
+
+            /* Codes_SRS_WSIO_01_070: [ The underlying uws instance shall be created by calling uws_client_create_with_io. ]*/
+            /* Codes_SRS_WSIO_01_071: [ The arguments for uws_client_create_with_io shall be: ]*/
+            /* Codes_SRS_WSIO_01_185: [ - underlying_io_interface shall be set to the underlying_io_interface field in the io_create_parameters passed to wsio_create. ]*/
+            /* Codes_SRS_WSIO_01_186: [ - underlying_io_parameters shall be set to the underlying_io_parameters field in the io_create_parameters passed to wsio_create. ]*/
+            /* Codes_SRS_WSIO_01_072: [ - hostname set to the hostname field in the io_create_parameters passed to wsio_create. ]*/
+            /* Codes_SRS_WSIO_01_130: [ - port set to the port field in the io_create_parameters passed to wsio_create. ]*/
+            /* Codes_SRS_WSIO_01_128: [ - resource_name set to the resource_name field in the io_create_parameters passed to wsio_create. ]*/
+            /* Codes_SRS_WSIO_01_129: [ - protocols shall be filled with only one structure, that shall have the protocol set to the value of the protocol field in the io_create_parameters passed to wsio_create. ]*/
+            result->uws = uws_client_create_with_io(ws_io_config->underlying_io_interface, ws_io_config->underlying_io_parameters, ws_io_config->hostname, ws_io_config->port, ws_io_config->resource_name, &protocols, 1);
+            if (result->uws == NULL)
+            {
+                /* Codes_SRS_WSIO_01_075: [ If uws_client_create_with_io fails, then wsio_create shall fail and return NULL. ]*/
+                LogError("Cannot create uws instance.");
+                free(result);
+                result = NULL;
+            }
+            else
+            {
+                /* Codes_SRS_WSIO_01_076: [ wsio_create shall create a pending send IO list that is to be used to queue send packets by calling singlylinkedlist_create. ]*/
+                result->pending_io_list = singlylinkedlist_create();
+                if (result->pending_io_list == NULL)
+                {
+                    /* Codes_SRS_WSIO_01_077: [ If singlylinkedlist_create fails then wsio_create shall fail and return NULL. ]*/
+                    LogError("Cannot create singly linked list.");
+                    uws_client_destroy(result->uws);
+                    free(result);
+                    result = NULL;
+                }
+                else
+                {
+                    result->io_state = IO_STATE_NOT_OPEN;
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+void wsio_destroy(CONCRETE_IO_HANDLE ws_io)
+{
+    /* Codes_SRS_WSIO_01_079: [ If ws_io is NULL, wsio_destroy shall do nothing.  ]*/
+    if (ws_io == NULL)
+    {
+        LogError("NULL handle");
+    }
+    else
+    {
+        WSIO_INSTANCE* wsio_instance = (WSIO_INSTANCE*)ws_io;
+
+        if (wsio_instance->io_state != IO_STATE_NOT_OPEN)
+        {
+            internal_close(wsio_instance, NULL, NULL);
+        }
+
+        /* Codes_SRS_WSIO_01_078: [ wsio_destroy shall free all resources associated with the wsio instance. ]*/
+        /* Codes_SRS_WSIO_01_080: [ wsio_destroy shall destroy the uws instance created in wsio_create by calling uws_client_destroy. ]*/
+        uws_client_destroy(wsio_instance->uws);
+        /* Codes_SRS_WSIO_01_081: [ wsio_destroy shall free the list used to track the pending send IOs by calling singlylinkedlist_destroy. ]*/
+        singlylinkedlist_destroy(wsio_instance->pending_io_list);
+        free(ws_io);
+    }
+}
+
+static void on_underlying_ws_open_complete(void* context, WS_OPEN_RESULT open_result)
+{
+    if (context == NULL)
+    {
+        /* Codes_SRS_WSIO_01_138: [ When on_underlying_ws_open_complete is called with a NULL context, it shall do nothing. ]*/
+        LogError("NULL context in on_underlying_ws_open_complete");
+    }
+    else
+    {
+        WSIO_INSTANCE* wsio_instance = (WSIO_INSTANCE*)context;
+
+        switch (wsio_instance->io_state)
+        {
+        default:
+        /* Codes_SRS_WSIO_01_142: [ When on_underlying_ws_open_complete is called while in the CLOSING state an error shall be indicated by calling the on_io_error callback passed to wsio_open. ]*/
+        case IO_STATE_CLOSING:
+        /* Codes_SRS_WSIO_01_141: [ When on_underlying_ws_open_complete is called while in the ERROR state it shall indicate an error by calling the on_io_error callback passed to wsio_open. ]*/
+        case IO_STATE_ERROR:
+        /* Codes_SRS_WSIO_01_139: [ When on_underlying_ws_open_complete is called while in OPEN state it shall indicate an error by calling the on_io_error callback passed to wsio_open and switch to the ERROR state. ]*/
+        case IO_STATE_OPEN:
+            /* Codes_SRS_WSIO_01_140: [ When calling on_io_error, the on_io_error_context argument given in wsio_open shall be passed to the callback on_io_error. ]*/
+            indicate_error(wsio_instance);
+            break;
+
+        case IO_STATE_OPENING:
+            wsio_instance->io_state = IO_STATE_OPEN;
+
+            switch (open_result)
+            {
+            default:
+                /* Codes_SRS_WSIO_01_137: [ When on_underlying_ws_open_complete is called with any other error code while the IO is opening, the callback on_io_open_complete shall be called with IO_OPEN_ERROR. ]*/
+                wsio_instance->io_state = IO_STATE_NOT_OPEN;
+                indicate_open_complete(wsio_instance, IO_OPEN_ERROR);
+                break;
+
+            case WS_OPEN_CANCELLED:
+                /* Codes_SRS_WSIO_01_149: [ When on_underlying_ws_open_complete is called with WS_OPEN_CANCELLED while the IO is opening, the callback on_io_open_complete shall be called with IO_OPEN_CANCELLED. ]*/
+                wsio_instance->io_state = IO_STATE_NOT_OPEN;
+                indicate_open_complete(wsio_instance, IO_OPEN_CANCELLED);
+                break;
+
+            case WS_OPEN_OK:
+                /* Codes_SRS_WSIO_01_136: [ When on_underlying_ws_open_complete is called with WS_OPEN_OK while the IO is opening, the callback on_io_open_complete shall be called with IO_OPEN_OK. ]*/
+                wsio_instance->io_state = IO_STATE_OPEN;
+                indicate_open_complete(wsio_instance, IO_OPEN_OK);
+                break;
+            }
+
+            break;
+        }
+    }
+}
+
+static void on_underlying_ws_frame_received(void* context, unsigned char frame_type, const unsigned char* buffer, size_t size)
+{
+    if (context == NULL)
+    {
+        /* Codes_SRS_WSIO_01_150: [ If on_underlying_ws_frame_received is called with NULL context it shall do nothing. ]*/
+        LogError("NULL context for on_underlying_ws_frame_received");
+    }
+    else
+    {
+        WSIO_INSTANCE* wsio_instance = (WSIO_INSTANCE*)context;
+
+        if (wsio_instance->io_state != IO_STATE_OPEN)
+        {
+            /* Codes_SRS_WSIO_01_126: [ If on_underlying_ws_frame_received is called while the IO is in any state other than OPEN, it shall do nothing. ]*/
+            LogError("on_underlying_ws_frame_received called in a bad state.");
+        }
+        else
+        {
+            if (frame_type != WS_FRAME_TYPE_BINARY)
+            {
+                /* Codes_SRS_WSIO_01_151: [ If the WebSocket frame type is not binary then an error shall be indicated by calling the on_io_error callback passed to wsio_open. ]*/
+                LogError("Invalid non binary WebSocket frame received.");
+                /* Codes_SRS_WSIO_01_152: [ When calling on_io_error, the on_io_error_context argument given in wsio_open shall be passed to the callback on_io_error. ]*/
+                indicate_error(wsio_instance);
+            }
+            else
+            {
+                /* Codes_SRS_WSIO_01_153: [ When on_underlying_ws_frame_received is called with zero size, no bytes shall be indicated up as received. ]*/
+                if (size > 0)
+                {
+                    if (buffer == NULL)
+                    {
+                        /* Codes_SRS_WSIO_01_154: [ When on_underlying_ws_frame_received is called with a positive size and a NULL buffer, an error shall be indicated by calling the on_io_error callback passed to wsio_open. ]*/
+                        LogError("NULL buffer received for Websocket frame with positive payload length.");
+                        indicate_error(wsio_instance);
+                    }
+                    else
+                    {
+                        /* Codes_SRS_WSIO_01_124: [ When on_underlying_ws_frame_received is called the bytes in the frame shall be indicated by calling the on_bytes_received callback passed to wsio_open. ]*/
+                        /* Codes_SRS_WSIO_01_125: [ When calling on_bytes_received, the on_bytes_received_context argument given in wsio_open shall be passed to the callback on_bytes_received. ]*/
+                        wsio_instance->on_bytes_received(wsio_instance->on_bytes_received_context, buffer, size);
+                    }
+                }
+            }
+        }
+    }
+}
+
+static void on_underlying_ws_peer_closed(void* context, uint16_t* close_code, const unsigned char* extra_data, size_t extra_data_length)
+{
+    /* Codes_SRS_WSIO_01_168: [ The close_code, extra_data and extra_data_length arguments shall be ignored. ]*/
+    (void)close_code;
+    (void)extra_data;
+    (void)extra_data_length;
+
+    if (context == NULL)
+    {
+        /* Codes_SRS_WSIO_01_167: [ If on_underlying_ws_peer_closed is called with a NULL context it shall do nothing. ]*/
+        LogError("NULL context for on_underlying_ws_peer_closed");
+    }
+    else
+    {
+        WSIO_INSTANCE* wsio_instance = (WSIO_INSTANCE*)context;
+
+        switch (wsio_instance->io_state)
+        {
+        default:
+            /* Codes_SRS_WSIO_01_166: [ When on_underlying_ws_peer_closed and the state of the IO is OPEN an error shall be indicated by calling the on_io_error callback passed to wsio_open. ]*/
+        case IO_STATE_OPEN:
+            /* Codes_SRS_WSIO_01_169: [ When on_underlying_ws_peer_closed and the state of the IO is CLOSING an error shall be indicated by calling the on_io_error callback passed to wsio_open. ]*/
+        case IO_STATE_CLOSING:
+            indicate_error(wsio_instance);
+            break;
+
+        case IO_STATE_NOT_OPEN:
+            // Codes_SRS_WSIO_07_001: [When on_underlying_ws_peer_closed and the state of the IO is NOT_OPEN an error will be raised and the io_state will remain as NOT_OPEN]
+            indicate_error(wsio_instance);
+            wsio_instance->io_state = IO_STATE_NOT_OPEN;
+            break;
+
+        case IO_STATE_OPENING:
+            /* Codes_SRS_WSIO_01_170: [ When on_underlying_ws_peer_closed and the state of the IO is OPENING an error shall be indicated by calling the on_io_open_complete callback passed to wsio_open with the error code IO_OPEN_ERROR. ]*/
+            wsio_instance->io_state = IO_STATE_NOT_OPEN;
+            indicate_open_complete(wsio_instance, IO_OPEN_ERROR);
+            break;
+        }
+    }
+}
+
+static void on_underlying_ws_error(void* context, WS_ERROR ws_error)
+{
+    (void)ws_error;
+    /* Don't have much to do with the error here */
+    LogError("on_underlying_ws_error called with error code %d", (int)ws_error);
+
+    if (context == NULL)
+    {
+        /* Codes_SRS_WSIO_01_135: [ When on_underlying_ws_error is called with a NULL context, it shall do nothing. ]*/
+        LogError("NULL context in on_underlying_ws_error");
+    }
+    else
+    {
+        WSIO_INSTANCE* wsio_instance = (WSIO_INSTANCE*)context;
+
+        if (wsio_instance->io_state == IO_STATE_OPENING)
+        {
+            /* Codes_SRS_WSIO_01_123: [ When calling on_io_error, the on_io_error_context argument given in wsio_open shall be passed to the callback on_io_error. ]*/
+            wsio_instance->on_io_open_complete(wsio_instance->on_io_open_complete_context, IO_OPEN_ERROR);
+            wsio_instance->io_state = IO_STATE_NOT_OPEN;
+        }
+        else
+        {
+            /* Codes_SRS_WSIO_01_123: [ When calling on_io_error, the on_io_error_context argument given in wsio_open shall be passed to the callback on_io_error. ]*/
+            wsio_instance->on_io_error(wsio_instance->on_io_error_context);
+        }
+    }
+}
+
+int wsio_open(CONCRETE_IO_HANDLE ws_io, ON_IO_OPEN_COMPLETE on_io_open_complete, void* on_io_open_complete_context, ON_BYTES_RECEIVED on_bytes_received, void* on_bytes_received_context, ON_IO_ERROR on_io_error, void* on_io_error_context)
+{
+    int result = 0;
+
+    if ((ws_io == NULL) ||
+        (on_io_open_complete == NULL) ||
+        (on_bytes_received == NULL) ||
+        (on_io_error == NULL))
+    {
+        /* Codes_SRS_WSIO_01_132: [ If any of the arguments ws_io, on_io_open_complete, on_bytes_received, on_io_error is NULL, wsio_open shall fail and return a non-zero value. ]*/
+        LogError("Bad arguments: ws_io=%p, on_io_open_complete=%p, on_bytes_received=%p, on_io_error=%p",
+            ws_io, on_io_open_complete, on_bytes_received, on_io_error);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        WSIO_INSTANCE* wsio_instance = (WSIO_INSTANCE*)ws_io;
+
+        if (wsio_instance->io_state != IO_STATE_NOT_OPEN)
+        {
+            /* Codes_SRS_WSIO_01_165: [ wsio_open when CLOSING shall fail and return a non-zero value. ]*/
+            /* Codes_SRS_WSIO_01_131: [ wsio_open when already OPEN or OPENING shall fail and return a non-zero value. ]*/
+            LogError("wsio has already been opened current state: %d", wsio_instance->io_state);
+            result = MU_FAILURE;
+        }
+        else
+        {
+            wsio_instance->on_bytes_received = on_bytes_received;
+            wsio_instance->on_bytes_received_context = on_bytes_received_context;
+            wsio_instance->on_io_open_complete = on_io_open_complete;
+            wsio_instance->on_io_open_complete_context = on_io_open_complete_context;
+            wsio_instance->on_io_error = on_io_error;
+            wsio_instance->on_io_error_context = on_io_error_context;
+
+            wsio_instance->io_state = IO_STATE_OPENING;
+
+            /* Codes_SRS_WSIO_01_082: [ wsio_open shall open the underlying uws instance by calling uws_client_open_async and providing the uws handle created in wsio_create as argument. ] */
+            if (uws_client_open_async(wsio_instance->uws, on_underlying_ws_open_complete, wsio_instance, on_underlying_ws_frame_received, wsio_instance, on_underlying_ws_peer_closed, wsio_instance, on_underlying_ws_error, wsio_instance) != 0)
+            {
+                /* Codes_SRS_WSIO_01_084: [ If opening the underlying uws instance fails then wsio_open shall fail and return a non-zero value. ]*/
+                LogError("Opening the uws instance failed.");
+                wsio_instance->io_state = IO_STATE_NOT_OPEN;
+                result = MU_FAILURE;
+            }
+            else
+            {
+                /* Codes_SRS_WSIO_01_083: [ On success, wsio_open shall return 0. ]*/
+                result = 0;
+            }
+        }
+    }
+
+    return result;
+}
+
+int wsio_close(CONCRETE_IO_HANDLE ws_io, ON_IO_CLOSE_COMPLETE on_io_close_complete, void* on_io_close_complete_context)
+{
+    int result = 0;
+
+    if (ws_io == NULL)
+    {
+        /* Codes_SRS_WSIO_01_086: [ if ws_io is NULL, wsio_close shall return a non-zero value.  ]*/
+        LogError("NULL handle");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        WSIO_INSTANCE* wsio_instance = (WSIO_INSTANCE*)ws_io;
+
+        if (internal_close(wsio_instance, on_io_close_complete, on_io_close_complete_context) != 0)
+        {
+            result = MU_FAILURE;
+        }
+        else
+        {
+            result = 0;
+        }
+    }
+
+    return result;
+}
+
+int wsio_send(CONCRETE_IO_HANDLE ws_io, const void* buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void* callback_context)
+{
+    int result;
+
+    /* Codes_SRS_WSIO_01_100: [ If any of the arguments ws_io or buffer are NULL, wsio_send shall fail and return a non-zero value. ]*/
+    if ((ws_io == NULL) ||
+        (buffer == NULL) ||
+        /* Codes_SRS_WSIO_01_101: [ If size is zero then wsio_send shall fail and return a non-zero value. ]*/
+        (size == 0))
+    {
+        LogError("Bad arguments: ws_io=%p, buffer=%p, size=%u",
+            ws_io, buffer, (unsigned int)size);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        WSIO_INSTANCE* wsio_instance = (WSIO_INSTANCE*)ws_io;
+
+        if (wsio_instance->io_state != IO_STATE_OPEN)
+        {
+            /* Codes_SRS_WSIO_01_099: [ If the wsio is not OPEN (open has not been called or is still in progress) then wsio_send shall fail and return a non-zero value. ]*/
+            LogError("Attempting to send when not open");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            LIST_ITEM_HANDLE new_item;
+            PENDING_IO* pending_socket_io = (PENDING_IO*)malloc(sizeof(PENDING_IO));
+            if (pending_socket_io == NULL)
+            {
+                /* Codes_SRS_WSIO_01_134: [ If allocating memory for the pending IO data fails, wsio_send shall fail and return a non-zero value. ]*/
+                result = MU_FAILURE;
+            }
+            else
+            {
+                /* Codes_SRS_WSIO_01_103: [ The entry shall contain the on_send_complete callback and its context. ]*/
+                pending_socket_io->on_send_complete = on_send_complete;
+                pending_socket_io->callback_context = callback_context;
+                pending_socket_io->wsio = wsio_instance;
+
+                /* Codes_SRS_WSIO_01_102: [ An entry shall be queued in the singly linked list by calling singlylinkedlist_add. ]*/
+                if ((new_item = singlylinkedlist_add(wsio_instance->pending_io_list, pending_socket_io)) == NULL)
+                {
+                    /* Codes_SRS_WSIO_01_104: [ If singlylinkedlist_add fails, wsio_send shall fail and return a non-zero value. ]*/
+                    free(pending_socket_io);
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    /* Codes_SRS_WSIO_01_095: [ wsio_send shall call uws_client_send_frame_async, passing the buffer and size arguments as they are: ]*/
+                    /* Codes_SRS_WSIO_01_097: [ The is_final argument shall be set to true. ]*/
+                    /* Codes_SRS_WSIO_01_096: [ The frame type used shall be WS_FRAME_TYPE_BINARY. ]*/
+                    if (uws_client_send_frame_async(wsio_instance->uws, WS_FRAME_TYPE_BINARY, (const unsigned char*)buffer, size, true, on_underlying_ws_send_frame_complete, new_item) != 0)
+                    {
+                        if (singlylinkedlist_remove(wsio_instance->pending_io_list, new_item) != 0)
+                        {
+                            LogError("Failed removing pending IO from linked list.");
+                        }
+
+                        free(pending_socket_io);
+                        result = MU_FAILURE;
+                    }
+                    else
+                    {
+                        /* Codes_SRS_WSIO_01_098: [ On success, wsio_send shall return 0. ]*/
+                        result = 0;
+                    }
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+void wsio_dowork(CONCRETE_IO_HANDLE ws_io)
+{
+    if (ws_io == NULL)
+    {
+        /* Codes_SRS_WSIO_01_107: [ If the ws_io argument is NULL, wsio_dowork shall do nothing. ]*/
+        LogError("NULL handle");
+    }
+    else
+    {
+        WSIO_INSTANCE* wsio_instance = (WSIO_INSTANCE*)ws_io;
+
+        /* Codes_SRS_WSIO_01_108: [ If the IO is not yet open, wsio_dowork shall do nothing. ]*/
+        if (wsio_instance->io_state != IO_STATE_NOT_OPEN)
+        {
+            /* Codes_SRS_WSIO_01_106: [ wsio_dowork shall call uws_client_dowork with the uws handle created in wsio_create. ]*/
+            uws_client_dowork(wsio_instance->uws);
+        }
+    }
+}
+
+int wsio_setoption(CONCRETE_IO_HANDLE ws_io, const char* optionName, const void* value)
+{
+    int result;
+    if (
+        /* Codes_SRS_WSIO_01_109: [ If any of the arguments ws_io or option_name is NULL wsio_setoption shall return a non-zero value. ]*/
+        (ws_io == NULL) ||
+        (optionName == NULL)
+        )
+    {
+        LogError("Bad parameters: ws_io=%p, optionName=%p",
+            ws_io, optionName);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        WSIO_INSTANCE* wsio_instance = (WSIO_INSTANCE*)ws_io;
+
+        if (strcmp(WSIO_OPTIONS, optionName) == 0)
+        {
+            /* Codes_SRS_WSIO_01_183: [ If the option name is WSIOOptions then wsio_setoption shall call OptionHandler_FeedOptions and pass to it the underlying IO handle and the value argument. ]*/
+            if (OptionHandler_FeedOptions((OPTIONHANDLER_HANDLE)value, wsio_instance->uws) != OPTIONHANDLER_OK)
+            {
+                /* Codes_SRS_WSIO_01_184: [ If OptionHandler_FeedOptions fails, wsio_setoption shall fail and return a non-zero value. ]*/
+                LogError("unable to OptionHandler_FeedOptions");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                /* Codes_SRS_WSIO_01_158: [ On success, wsio_setoption shall return 0. ]*/
+                result = 0;
+            }
+        }
+        else
+        {
+            /* Codes_SRS_WSIO_01_156: [ Otherwise all options shall be passed as they are to uws by calling uws_client_set_option. ]*/
+            if (uws_client_set_option(wsio_instance->uws, optionName, value) != 0)
+            {
+                /* Codes_SRS_WSIO_01_157: [ If uws_client_set_option fails, wsio_setoption shall fail and return a non-zero value. ]*/
+                LogError("Setting the option %s failed", optionName);
+                result = MU_FAILURE;
+            }
+            else
+            {
+                /* Codes_SRS_WSIO_01_158: [ On success, wsio_setoption shall return 0. ]*/
+                result = 0;
+            }
+        }
+    }
+
+    return result;
+}
+
+static void* wsio_clone_option(const char* name, const void* value)
+{
+    void *result;
+
+    if (
+        (name == NULL) ||
+        (value == NULL)
+        )
+    {
+        /* Codes_SRS_WSIO_01_174: [ If wsio_clone_option is called with NULL name or value it shall return NULL. ]*/
+        LogError("invalid argument detected: const char* name=%p, const void* value=%p", name, value);
+        result = NULL;
+    }
+    else
+    {
+        if (strcmp(name, WSIO_OPTIONS) == 0)
+        {
+            /* Codes_SRS_WSIO_01_171: [** wsio_clone_option called with name being WSIOOptions shall return the same value. ]*/
+            result = (void*)value;
+        }
+        else
+        {
+            /* Codes_SRS_WSIO_01_173: [ wsio_clone_option called with any other option name than WSIOOptions shall return NULL. ]*/
+            LogError("unknown option: %s", name);
+            result = NULL;
+        }
+    }
+
+    return result;
+}
+
+static void wsio_destroy_option(const char* name, const void* value)
+{
+    if (
+        (name == NULL) ||
+        (value == NULL)
+        )
+    {
+        /* Codes_SRS_WSIO_01_177: [ If wsio_destroy_option is called with NULL name or value it shall do nothing. ]*/
+        LogError("Bad arguments: const char* name=%p, const void* value=%p", name, value);
+    }
+    else
+    {
+        if (strcmp(name, WSIO_OPTIONS) == 0)
+        {
+            /* Codes_SRS_WSIO_01_175: [ wsio_destroy_option called with the option name being WSIOOptions shall destroy the value by calling OptionHandler_Destroy. ]*/
+            OptionHandler_Destroy((OPTIONHANDLER_HANDLE)value);
+        }
+        else
+        {
+            /* Codes_SRS_WSIO_01_176: [ If wsio_destroy_option is called with any other name it shall do nothing. ]*/
+            LogError("unknown option: %s", name);
+        }
+    }
+}
+
+OPTIONHANDLER_HANDLE wsio_retrieveoptions(CONCRETE_IO_HANDLE handle)
+{
+    OPTIONHANDLER_HANDLE result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_WSIO_01_118: [ If parameter handle is NULL then wsio_retrieveoptions shall fail and return NULL. ]*/
+        LogError("parameter handle is NULL");
+        result = NULL;
+    }
+    else
+    {
+        WSIO_INSTANCE* wsio = (WSIO_INSTANCE*)handle;
+
+        /* Codes_SRS_WSIO_01_119: [ wsio_retrieveoptions shall call OptionHandler_Create to produce an OPTIONHANDLER_HANDLE and on success return the new OPTIONHANDLER_HANDLE handle. ]*/
+        result = OptionHandler_Create(wsio_clone_option, wsio_destroy_option, wsio_setoption);
+        if (result == NULL)
+        {
+            /* Codes_SRS_WSIO_01_120: [ If OptionHandler_Create fails then wsio_retrieveoptions shall fail and return NULL.  ]*/
+            LogError("OptionHandler_Create failed");
+        }
+        else
+        {
+            /* Codes_SRS_WSIO_01_179: [ When calling uws_client_retrieve_options the uws client handle shall be passed to it. ]*/
+            /* Codes_SRS_WSIO_01_178: [ uws_client_retrieve_options shall add to the option handler one option, whose name shall be uWSCLientOptions and the value shall be queried by calling uws_client_retrieve_options. ]*/
+            OPTIONHANDLER_HANDLE concreteOptions = uws_client_retrieve_options(wsio->uws);
+            if (concreteOptions == NULL)
+            {
+                /* Codes_SRS_WSIO_01_180: [ If uws_client_retrieve_options fails, uws_client_retrieve_options shall fail and return NULL. ]*/
+                LogError("unable to concrete_io_retrieveoptions");
+                OptionHandler_Destroy(result);
+                result = NULL;
+            }
+            else
+            {
+                /* Codes_SRS_WSIO_01_181: [ Adding the option shall be done by calling OptionHandler_AddOption. ]*/
+                if (OptionHandler_AddOption(result, WSIO_OPTIONS, concreteOptions) != OPTIONHANDLER_OK)
+                {
+                    /* Codes_SRS_WSIO_01_182: [ If OptionHandler_AddOption fails, uws_client_retrieve_options shall fail and return NULL. ]*/
+                    LogError("unable to OptionHandler_AddOption");
+                    OptionHandler_Destroy(concreteOptions);
+                    OptionHandler_Destroy(result);
+                    result = NULL;
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+static const IO_INTERFACE_DESCRIPTION ws_io_interface_description =
+{
+    wsio_retrieveoptions,
+    wsio_create,
+    wsio_destroy,
+    wsio_open,
+    wsio_close,
+    wsio_send,
+    wsio_dowork,
+    wsio_setoption
+};
+
+const IO_INTERFACE_DESCRIPTION* wsio_get_interface_description(void)
+{
+    return &ws_io_interface_description;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/xio.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/xio.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/xio.c	(revision 453)
@@ -0,0 +1,302 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/xio.h"
+#include "azure_c_shared_utility/xlogging.h"
+
+static const char* CONCRETE_OPTIONS = "concreteOptions";
+
+typedef struct XIO_INSTANCE_TAG
+{
+    const IO_INTERFACE_DESCRIPTION* io_interface_description;
+    CONCRETE_IO_HANDLE concrete_xio_handle;
+} XIO_INSTANCE;
+
+XIO_HANDLE xio_create(const IO_INTERFACE_DESCRIPTION* io_interface_description, const void* xio_create_parameters)
+{
+    XIO_INSTANCE* xio_instance;
+    /* Codes_SRS_XIO_01_003: [If the argument io_interface_description is NULL, xio_create shall return NULL.] */
+    if ((io_interface_description == NULL) ||
+        /* Codes_SRS_XIO_01_004: [If any io_interface_description member is NULL, xio_create shall return NULL.] */
+        (io_interface_description->concrete_io_retrieveoptions == NULL) ||
+        (io_interface_description->concrete_io_create == NULL) ||
+        (io_interface_description->concrete_io_destroy == NULL) ||
+        (io_interface_description->concrete_io_open == NULL) ||
+        (io_interface_description->concrete_io_close == NULL) ||
+        (io_interface_description->concrete_io_send == NULL) ||
+        (io_interface_description->concrete_io_dowork == NULL) ||
+        (io_interface_description->concrete_io_setoption == NULL))
+    {
+        xio_instance = NULL;
+    }
+    else
+    {
+        xio_instance = (XIO_INSTANCE*)malloc(sizeof(XIO_INSTANCE));
+
+        /* Codes_SRS_XIO_01_017: [If allocating the memory needed for the IO interface fails then xio_create shall return NULL.] */
+        if (xio_instance != NULL)
+        {
+            /* Codes_SRS_XIO_01_001: [xio_create shall return on success a non-NULL handle to a new IO interface.] */
+            xio_instance->io_interface_description = io_interface_description;
+
+            /* Codes_SRS_XIO_01_002: [In order to instantiate the concrete IO implementation the function concrete_io_create from the io_interface_description shall be called, passing the xio_create_parameters argument.] */
+            xio_instance->concrete_xio_handle = xio_instance->io_interface_description->concrete_io_create((void*)xio_create_parameters);
+
+            /* Codes_SRS_XIO_01_016: [If the underlying concrete_io_create call fails, xio_create shall return NULL.] */
+            if (xio_instance->concrete_xio_handle == NULL)
+            {
+                free(xio_instance);
+                xio_instance = NULL;
+            }
+        }
+    }
+    return (XIO_HANDLE)xio_instance;
+}
+
+void xio_destroy(XIO_HANDLE xio)
+{
+    /* Codes_SRS_XIO_01_007: [If the argument io is NULL, xio_destroy shall do nothing.] */
+    if (xio != NULL)
+    {
+        XIO_INSTANCE* xio_instance = (XIO_INSTANCE*)xio;
+
+        /* Codes_SRS_XIO_01_006: [xio_destroy shall also call the concrete_io_destroy function that is member of the io_interface_description argument passed to xio_create, while passing as argument to concrete_io_destroy the result of the underlying concrete_io_create handle that was called as part of the xio_create call.] */
+        xio_instance->io_interface_description->concrete_io_destroy(xio_instance->concrete_xio_handle);
+
+        /* Codes_SRS_XIO_01_005: [xio_destroy shall free all resources associated with the IO handle.] */
+        free(xio_instance);
+    }
+}
+
+int xio_open(XIO_HANDLE xio, ON_IO_OPEN_COMPLETE on_io_open_complete, void* on_io_open_complete_context, ON_BYTES_RECEIVED on_bytes_received, void* on_bytes_received_context, ON_IO_ERROR on_io_error, void* on_io_error_context)
+{
+    int result;
+
+    if (xio == NULL)
+    {
+        /* Codes_SRS_XIO_01_021: [If handle is NULL, xio_open shall return a non-zero value.] */
+        result = MU_FAILURE;
+    }
+    else
+    {
+        XIO_INSTANCE* xio_instance = (XIO_INSTANCE*)xio;
+
+        /* Codes_SRS_XIO_01_019: [xio_open shall call the specific concrete_xio_open function specified in xio_create, passing callback function and context arguments for three events: open completed, bytes received, and IO error.] */
+        if (xio_instance->io_interface_description->concrete_io_open(xio_instance->concrete_xio_handle, on_io_open_complete, on_io_open_complete_context, on_bytes_received, on_bytes_received_context, on_io_error, on_io_error_context) != 0)
+        {
+            /* Codes_SRS_XIO_01_022: [If the underlying concrete_io_open fails, xio_open shall return a non-zero value.] */
+            result = MU_FAILURE;
+        }
+        else
+        {
+            /* Codes_SRS_XIO_01_020: [On success, xio_open shall return 0.] */
+            result = 0;
+        }
+    }
+
+    return result;
+}
+
+int xio_close(XIO_HANDLE xio, ON_IO_CLOSE_COMPLETE on_io_close_complete, void* callback_context)
+{
+    int result;
+
+    if (xio == NULL)
+    {
+        /* Codes_SRS_XIO_01_025: [If handle is NULL, xio_close shall return a non-zero value.] */
+        result = MU_FAILURE;
+    }
+    else
+    {
+        XIO_INSTANCE* xio_instance = (XIO_INSTANCE*)xio;
+
+        /* Codes_SRS_XIO_01_023: [xio_close shall call the specific concrete_io_close function specified in xio_create.] */
+        if (xio_instance->io_interface_description->concrete_io_close(xio_instance->concrete_xio_handle, on_io_close_complete, callback_context) != 0)
+        {
+            /* Codes_SRS_XIO_01_026: [If the underlying concrete_io_close fails, xio_close shall return a non-zero value.] */
+            result = MU_FAILURE;
+        }
+        else
+        {
+            /* Codes_SRS_XIO_01_024: [On success, xio_close shall return 0.] */
+            result = 0;
+        }
+    }
+
+    return result;
+}
+
+int xio_send(XIO_HANDLE xio, const void* buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void* callback_context)
+{
+    int result;
+
+    /* Codes_SRS_XIO_01_011: [No error check shall be performed on buffer and size.] */
+    /* Codes_SRS_XIO_01_010: [If handle is NULL, xio_send shall return a non-zero value.] */
+    if (xio == NULL)
+    {
+        result = MU_FAILURE;
+    }
+    else
+    {
+        XIO_INSTANCE* xio_instance = (XIO_INSTANCE*)xio;
+
+        /* Codes_SRS_XIO_01_008: [xio_send shall pass the sequence of bytes pointed to by buffer to the concrete IO implementation specified in xio_create, by calling the concrete_io_send function while passing down the buffer and size arguments to it.] */
+        /* Codes_SRS_XIO_01_009: [On success, xio_send shall return 0.] */
+        /* Codes_SRS_XIO_01_015: [If the underlying concrete_io_send fails, xio_send shall return a non-zero value.] */
+        /* Codes_SRS_XIO_01_027: [xio_send shall pass to the concrete_io_send function the on_send_complete and callback_context arguments.] */
+        result = xio_instance->io_interface_description->concrete_io_send(xio_instance->concrete_xio_handle, buffer, size, on_send_complete, callback_context);
+    }
+
+    return result;
+}
+
+void xio_dowork(XIO_HANDLE xio)
+{
+    /* Codes_SRS_XIO_01_018: [When the handle argument is NULL, xio_dowork shall do nothing.] */
+    if (xio != NULL)
+    {
+        XIO_INSTANCE* xio_instance = (XIO_INSTANCE*)xio;
+
+        /* Codes_SRS_XIO_01_012: [xio_dowork shall call the concrete XIO implementation specified in xio_create, by calling the concrete_io_dowork function.] */
+        xio_instance->io_interface_description->concrete_io_dowork(xio_instance->concrete_xio_handle);
+    }
+}
+
+int xio_setoption(XIO_HANDLE xio, const char* optionName, const void* value)
+{
+    int result;
+
+    /* Codes_SRS_XIO_03_030: [If the xio argument or the optionName argument is NULL, xio_setoption shall return a non-zero value.] */
+    if (xio == NULL || optionName == NULL)
+    {
+        result = MU_FAILURE;
+    }
+    else
+    {
+        XIO_INSTANCE* xio_instance = (XIO_INSTANCE*)xio;
+
+        if (strcmp(CONCRETE_OPTIONS, optionName) == 0)
+        {
+            /*then value is a pointer to OPTIONHANDLER_HANDLE*/
+            if (OptionHandler_FeedOptions((OPTIONHANDLER_HANDLE)value, xio_instance->concrete_xio_handle) != OPTIONHANDLER_OK)
+            {
+                LogError("unable to OptionHandler_FeedOptions");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                result = 0;
+            }
+        }
+        else /*passthrough*/
+        {
+            /* Codes_SRS_XIO_003_028: [xio_setoption shall pass the optionName and value to the concrete IO implementation specified in xio_create by invoking the concrete_xio_setoption function.] */
+            /* Codes_SRS_XIO_03_029: [xio_setoption shall return 0 upon success.] */
+            /* Codes_SRS_XIO_03_031: [If the underlying concrete_xio_setoption fails, xio_setOption shall return a non-zero value.] */
+            result = xio_instance->io_interface_description->concrete_io_setoption(xio_instance->concrete_xio_handle, optionName, value);
+        }
+    }
+
+    return result;
+}
+
+static void* xio_CloneOption(const char* name, const void* value)
+{
+    void *result;
+    if (
+        (name == NULL) ||
+        (value == NULL)
+        )
+    {
+        LogError("invalid argument detected: const char* name=%p, const void* value=%p", name, value);
+        result = NULL;
+    }
+    else
+    {
+        if (strcmp(name, CONCRETE_OPTIONS) == 0)
+        {
+            result = (void*)value;
+        }
+        else
+        {
+            LogError("unknown option: %s", name);
+            result = NULL;
+        }
+    }
+    return result;
+}
+
+
+static void xio_DestroyOption(const char* name, const void* value)
+{
+    if (
+        (name == NULL) ||
+        (value == NULL)
+        )
+    {
+        LogError("invalid argument detected: const char* name=%p, const void* value=%p", name, value);
+    }
+    else
+    {
+        if (strcmp(name, CONCRETE_OPTIONS) == 0)
+        {
+            OptionHandler_Destroy((OPTIONHANDLER_HANDLE)value);
+        }
+        else
+        {
+            LogError("unknown option: %s", name);
+        }
+    }
+}
+
+OPTIONHANDLER_HANDLE xio_retrieveoptions(XIO_HANDLE xio)
+{
+    OPTIONHANDLER_HANDLE result;
+
+    if (xio == NULL)
+    {
+        LogError("invalid argument detected: XIO_HANDLE xio=%p", xio);
+        result = NULL;
+    }
+    else
+    {
+        XIO_INSTANCE* xio_instance = (XIO_INSTANCE*)xio;
+        /*xio_retrieveoptions shall return a OPTIONHANDLER_HANDLE that has 1 option called "underlyingOptions" which is of type OPTIONHANDLER_HANDLE*/
+        result = OptionHandler_Create(xio_CloneOption, xio_DestroyOption, (pfSetOption)xio_setoption);
+        if (result == NULL)
+        {
+            LogError("unable to OptionHandler_Create");
+            /*return as is*/
+        }
+        else
+        {
+            OPTIONHANDLER_HANDLE concreteOptions = xio_instance->io_interface_description->concrete_io_retrieveoptions(xio_instance->concrete_xio_handle);
+            if (concreteOptions == NULL)
+            {
+                LogError("unable to concrete_io_retrieveoptions");
+                OptionHandler_Destroy(result);
+                result = NULL;
+            }
+            else
+            {
+                if (OptionHandler_AddOption(result, CONCRETE_OPTIONS, concreteOptions) != OPTIONHANDLER_OK)
+                {
+                    LogError("unable to OptionHandler_AddOption");
+                    OptionHandler_Destroy(concreteOptions);
+                    OptionHandler_Destroy(result);
+                    result = NULL;
+                }
+                else
+                {
+                    /*all is fine*/
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/xlogging.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/xlogging.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/src/xlogging.c	(revision 453)
@@ -0,0 +1,145 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/consolelogger.h"
+
+#ifndef NO_LOGGING
+
+#ifdef WIN32
+#include "windows.h"
+#endif // WIN32
+
+
+LOGGER_LOG global_log_function = consolelogger_log;
+
+void xlogging_set_log_function(LOGGER_LOG log_function)
+{
+    global_log_function = log_function;
+}
+
+LOGGER_LOG xlogging_get_log_function(void)
+{
+    return global_log_function;
+}
+
+#if (defined(_MSC_VER))
+
+LOGGER_LOG_GETLASTERROR global_log_function_GetLastError = consolelogger_log_with_GetLastError;
+
+void xlogging_set_log_function_GetLastError(LOGGER_LOG_GETLASTERROR log_function_GetLastError)
+{
+    global_log_function_GetLastError = log_function_GetLastError;
+}
+
+LOGGER_LOG_GETLASTERROR xlogging_get_log_function_GetLastError(void)
+{
+    return global_log_function_GetLastError;
+}
+#endif
+
+/* Print up to 16 bytes per line. */
+#define LINE_SIZE 16
+
+/* Return the printable char for the provided value. */
+#define PRINTABLE(c)         ((c >= ' ') && (c <= '~')) ? (char)c : '.'
+
+/* Convert the lower nibble of the provided byte to a hexadecimal printable char. */
+#define HEX_STR(c)           (((c) & 0xF) < 0xA) ? (char)(((c) & 0xF) + '0') : (char)(((c) & 0xF) - 0xA + 'A')
+
+void LogBinary(const char* comment, const void* data, size_t size)
+{
+    char charBuf[LINE_SIZE + 1];
+    char hexBuf[LINE_SIZE * 3 + 1];
+    size_t countbuf = 0;
+    size_t i = 0;
+    const unsigned char* bufAsChar = (const unsigned char*)data;
+    const unsigned char* startPos = bufAsChar;
+
+    LOG(AZ_LOG_TRACE, LOG_LINE, "%s     %lu bytes", comment, (unsigned long)size);
+
+    /* Print the whole buffer. */
+    for (i = 0; i < size; i++)
+    {
+        /* Store the printable value of the char in the charBuf to print. */
+        charBuf[countbuf] = PRINTABLE(*bufAsChar);
+
+        /* Convert the high nibble to a printable hexadecimal value. */
+        hexBuf[countbuf * 3] = HEX_STR(*bufAsChar >> 4);
+
+        /* Convert the low nibble to a printable hexadecimal value. */
+        hexBuf[countbuf * 3 + 1] = HEX_STR(*bufAsChar);
+
+        hexBuf[countbuf * 3 + 2] = ' ';
+
+        countbuf++;
+        bufAsChar++;
+        /* If the line is full, print it to start another one. */
+        if (countbuf == LINE_SIZE)
+        {
+            charBuf[countbuf] = '\0';
+            hexBuf[countbuf * 3] = '\0';
+            LOG(AZ_LOG_TRACE, LOG_LINE, "%p: %s    %s", startPos, hexBuf, charBuf);
+            countbuf = 0;
+            startPos = bufAsChar;
+        }
+    }
+
+    /* If the last line does not fit the line size. */
+    if (countbuf > 0)
+    {
+        /* Close the charBuf string. */
+        charBuf[countbuf] = '\0';
+
+        /* Fill the hexBuf with spaces to keep the charBuf alignment. */
+        while ((countbuf++) < LINE_SIZE - 1)
+        {
+            hexBuf[countbuf * 3] = ' ';
+            hexBuf[countbuf * 3 + 1] = ' ';
+            hexBuf[countbuf * 3 + 2] = ' ';
+        }
+        hexBuf[countbuf * 3] = '\0';
+
+        /* Print the last line. */
+        LOG(AZ_LOG_TRACE, LOG_LINE, "%p: %s    %s", startPos, hexBuf, charBuf);
+    }
+}
+
+#ifdef WIN32
+
+void xlogging_LogErrorWinHTTPWithGetLastErrorAsStringFormatter(int errorMessageID)
+{
+    char messageBuffer[MESSAGE_BUFFER_SIZE];
+    if (errorMessageID == 0)
+    {
+        LogError("GetLastError() returned 0. Make sure you are calling this right after the code that failed. ");
+    }
+    else
+    {
+        int size = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS,
+            GetModuleHandle("WinHttp"), errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), messageBuffer, MESSAGE_BUFFER_SIZE, NULL);
+        if (size == 0)
+        {
+            size = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), messageBuffer, MESSAGE_BUFFER_SIZE, NULL);
+            if (size == 0)
+            {
+                LogError("GetLastError Code: %d. ", errorMessageID);
+            }
+            else
+            {
+                LogError("GetLastError: %s.", messageBuffer);
+            }
+        }
+        else
+        {
+            LogError("GetLastError: %s.", messageBuffer);
+        }
+    }
+}
+#endif // WIN32
+
+
+#endif // NO_LOGGING
+
+
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/certs/certs.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/certs/certs.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/certs/certs.c	(revision 453)
@@ -0,0 +1,103 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/* This file contains certs needed to communicate with Azure (IoT) */
+
+#include "certs.h"
+/* Note: for devices with limited resources, only one cert should be loaded. 
+   #defines are used to reduce memory footprint of certificates.
+   For DE and CN regions, please build with -DUSE_MICROSOFTAZURE_DE_CERT or -DUSE_PORTAL_AZURE_CN_CERT, respectively, 
+   if you wish to load ONLY those certs.
+*/
+#if !defined(USE_BALTIMORE_CERT) && !defined(USE_MICROSOFTAZURE_DE_CERT) && !defined(USE_PORTAL_AZURE_CN_CERT)
+// For legacy, if no certificates were explicitly selected then include all of them
+#define USE_BALTIMORE_CERT
+#define USE_MICROSOFTAZURE_DE_CERT 
+#define USE_PORTAL_AZURE_CN_CERT
+#endif
+
+const char certificates[] =
+#if defined(USE_BALTIMORE_CERT)
+/* DigiCert Baltimore Root --Used Globally--*/
+// This cert should be used when connecting to Azure IoT on the Azure Cloud available globally. When in doubt, use this cert.
+"-----BEGIN CERTIFICATE-----\r\n"
+"MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ\r\n"
+"RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD\r\n"
+"VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX\r\n"
+"DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y\r\n"
+"ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy\r\n"
+"VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr\r\n"
+"mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr\r\n"
+"IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK\r\n"
+"mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu\r\n"
+"XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy\r\n"
+"dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye\r\n"
+"jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1\r\n"
+"BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3\r\n"
+"DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92\r\n"
+"9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx\r\n"
+"jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0\r\n"
+"Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz\r\n"
+"ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS\r\n"
+"R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp\r\n"
+"-----END CERTIFICATE-----\r\n"
+#endif /* BALTIMORE_CERT */
+
+#if defined(USE_PORTAL_AZURE_CN_CERT)
+/* DigiCert Global Root CA */
+// This cert should be used when connecting to Azure IoT on the https://portal.azure.cn Cloud address.
+"-----BEGIN CERTIFICATE-----\r\n"
+"MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh\r\n"
+"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\r\n"
+"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\r\n"
+"QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT\r\n"
+"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\r\n"
+"b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG\r\n"
+"9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB\r\n"
+"CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97\r\n"
+"nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\r\n"
+"43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P\r\n"
+"T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4\r\n"
+"gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO\r\n"
+"BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR\r\n"
+"TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw\r\n"
+"DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr\r\n"
+"hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg\r\n"
+"06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF\r\n"
+"PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\r\n"
+"YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk\r\n"
+"CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\r\n"
+"-----END CERTIFICATE-----\r\n"
+#endif /* PORTAL_AZURE_CN_CERT */
+
+#if defined(USE_MICROSOFTAZURE_DE_CERT)
+/* D-TRUST Root Class 3 CA 2 2009 */
+// This cert should be used when connecting to Azure IoT on the https://portal.microsoftazure.de Cloud address.
+"-----BEGIN CERTIFICATE-----\r\n"
+"MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF\r\n"
+"MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD\r\n"
+"bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha\r\n"
+"ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM\r\n"
+"HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB\r\n"
+"BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03\r\n"
+"UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42\r\n"
+"tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R\r\n"
+"ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM\r\n"
+"lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp\r\n"
+"/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G\r\n"
+"A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G\r\n"
+"A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj\r\n"
+"dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy\r\n"
+"MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl\r\n"
+"cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js\r\n"
+"L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL\r\n"
+"BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni\r\n"
+"acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0\r\n"
+"o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K\r\n"
+"zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8\r\n"
+"PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y\r\n"
+"Johw1+qRzT65ysCQblrGXnRl11z+o+I=\r\n"
+"-----END CERTIFICATE-----\r\n"
+#endif /* MICROSOFTAZURE_DE_CERT */
+
+;
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/certs/certs.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/certs/certs.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/certs/certs.h	(revision 453)
@@ -0,0 +1,18 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef CERTS_H
+#define CERTS_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    extern const char certificates[];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CERTS_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/deps/azure-macro-utils-c/inc/azure_macro_utils/macro_utils.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/deps/azure-macro-utils-c/inc/azure_macro_utils/macro_utils.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/deps/azure-macro-utils-c/inc/azure_macro_utils/macro_utils.h	(revision 453)
@@ -0,0 +1,217 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef MACRO_UTILS_H
+#define MACRO_UTILS_H
+
+#include "azure_macro_utils/macro_utils_generated.h"
+
+#ifdef __cplusplus
+#include <cstring>
+#include <cstddef>
+extern "C" {
+#else
+#include <string.h>
+#include <stddef.h>
+#endif
+
+#if (defined OPTIMIZE_RETURN_CODES)
+    #define MU_FAILURE 1
+#else
+    #define MU_FAILURE __LINE__
+#endif
+
+/*"pointer or NULL" macro - because when printf-ing arguments NULL is not valid for %s (section 7.1.4 of C11 standard) */
+#define MU_P_OR_NULL(p) (((p)!=NULL)?(p):"NULL")
+#define MU_WP_OR_NULL(p) (((p)!=NULL)?(p):L"NULL")
+
+#define MU_TOSTRING_(x) #x
+#define MU_TOSTRING(x) MU_TOSTRING_(x)
+
+#define MU_TRIGGER_PARENTHESIS(...) ,
+
+#define MU_LPAREN (
+
+#define MU_C2_(x,y) x##y
+
+#define MU_C2(x,y) MU_C2_(x,y)
+
+#define MU_C3(x,y,z) MU_C2(x, MU_C2(y,z))
+
+#define MU_C4(x,y,z, u) MU_C2(MU_C2(x,y), MU_C2(z,u))
+
+#define MU_C5(x,y,z,u, v) MU_C2(MU_C4(x,y, z, u), v)
+
+#define MU_C1_(x) x
+
+#define MU_C1(x) MU_C1_(x)
+
+#define MU_C2STRING(x,y) x y
+
+#define MU_C3STRING(x,y,z) x y z
+
+#define MU_C4STRING(x,y,z,u) x y z u
+
+#define MU_C5STRING(x,y,z,u,v) x y z u v
+
+/* we need some sort of macro that does:
+MU_IF(0, "true", "false") => "false"
+MU_IF(1, "true", "false") => "true"
+MU_IF(X, "true", "false") => "true"
+*/
+
+#define MU_INTERNALIF(x) MU_INTERNALIF##x
+#define MU_INTERNALIF0
+
+#define MU_ISZERO(x) MU_COUNT_ARG(MU_INTERNALIF(x))
+
+#define MU_IF(condition, trueBranch, falseBranch) MU_C2(MU_IF,MU_ISZERO(condition))(trueBranch, falseBranch)
+#define MU_IF0(trueBranch, falseBranch) falseBranch
+#define MU_IF1(trueBranch, falseBranch) trueBranch
+
+
+/*the following macro want to eat empty arguments from a list */
+/*examples:                                                   */
+/*MU_EAT_EMPTY_ARGS(, , X) expands to X                       */
+
+#define MU_EXPAND_TO_NOTHING(arg)
+#define MU_EAT_EMPTY_ARG(arg_count, arg) MU_IF(MU_ISEMPTY(arg),,arg) MU_IF(MU_ISEMPTY(arg),MU_EXPAND_TO_NOTHING,MU_IFCOMMALOGIC)(MU_DEC(arg_count))
+#define MU_EAT_EMPTY_ARGS(...) MU_FOR_EACH_1_COUNTED(MU_EAT_EMPTY_ARG, __VA_ARGS__)
+
+#define MU_DEFINE_ENUMERATION_CONSTANT(x) x,
+/*MU_DEFINE_ENUM_WITHOUT_INVALID goes to header*/
+#define MU_DEFINE_ENUM_WITHOUT_INVALID(enumName, ...) typedef enum MU_C2(enumName, _TAG) { MU_FOR_EACH_1(MU_DEFINE_ENUMERATION_CONSTANT, __VA_ARGS__)} enumName; \
+    extern const char* MU_C2(enumName,Strings)(enumName value); \
+    extern int MU_C2(enumName, _FromString)(const char* enumAsString, enumName* destination);
+
+// this macro is a wrapper on top of MU_DEFINE_ENUM_WITHOUT_INVALID, adding an _INVALID value as the first enum value in the enum
+#define MU_DEFINE_ENUM(enumName, ...) \
+    MU_DEFINE_ENUM_WITHOUT_INVALID(enumName, MU_C2(enumName, _INVALID), __VA_ARGS__)
+
+#define MU_DEFINE_ENUMERATION_CONSTANT_AS_WIDESTRING(x) MU_C2(L, MU_TOSTRING(x)) , 
+#define MU_DEFINE_ENUMERATION_CONSTANT_AS_STRING(x) MU_TOSTRING(x) , 
+/*MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID goes to .c*/
+#define MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(enumName, ...) const char* MU_C2(enumName, StringStorage)[MU_COUNT_ARG(__VA_ARGS__)] = {MU_FOR_EACH_1(MU_DEFINE_ENUMERATION_CONSTANT_AS_STRING, __VA_ARGS__)}; \
+const char* MU_C2(enumName,Strings)(enumName value)                \
+{                                                                  \
+    if((int)value<0 || (int)value>=MU_COUNT_ARG(__VA_ARGS__))      \
+    {                                                              \
+        /*this is an error case*/                                  \
+        return "NULL";                                             \
+    }                                                              \
+    else                                                           \
+    {                                                              \
+        return MU_C2(enumName, StringStorage)[value];              \
+    }                                                              \
+}                                                                  \
+int MU_C2(enumName, _FromString)(const char* enumAsString, enumName* destination)  \
+{                                                                               \
+    if(                                                                         \
+        (enumAsString==NULL) || (destination==NULL)                             \
+    )                                                                           \
+    {                                                                           \
+        return MU_FAILURE;                                                      \
+    }                                                                           \
+    else                                                                        \
+    {                                                                           \
+        size_t i;                                                               \
+        for(i=0;i<MU_COUNT_ARG(__VA_ARGS__);i++)                                \
+        {                                                                       \
+            if(strcmp(enumAsString, MU_C2(enumName, StringStorage)[i])==0)      \
+            {                                                                   \
+                *destination = (enumName)i;                                     \
+                return 0;                                                       \
+            }                                                                   \
+        }                                                                       \
+        return MU_FAILURE;                                                      \
+    }                                                                           \
+}                                                                               \
+
+// this macro is a wrapper on top of MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID, adding an _INVALID value as the first enum value in the enum
+#define MU_DEFINE_ENUM_STRINGS(enumName, ...) \
+    MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(enumName, MU_C2(enumName, _INVALID), __VA_ARGS__)
+
+#define MU_DEFINE_LOCAL_ENUM_WITHOUT_INVALID(enumName, ...) typedef enum MU_C2(enumName, _TAG) { MU_FOR_EACH_1(MU_DEFINE_ENUMERATION_CONSTANT, __VA_ARGS__)} enumName; \
+static const char* MU_C2(enumName, StringStorage)[MU_COUNT_ARG(__VA_ARGS__)] = {MU_FOR_EACH_1(MU_DEFINE_ENUMERATION_CONSTANT_AS_STRING, __VA_ARGS__)}; \
+static const char* MU_C2(enumName,Strings)(enumName value)         \
+{                                                                  \
+    if((int)value<0 || (int)value>=MU_COUNT_ARG(__VA_ARGS__))      \
+    {                                                              \
+        /*this is an error case*/                                  \
+        return "NULL";                                             \
+    }                                                              \
+    else                                                           \
+    {                                                              \
+        return MU_C2(enumName, StringStorage)[value];              \
+    }                                                              \
+}
+
+// this macro is a wrapper on top of MU_DEFINE_LOCAL_ENUM_WITHOUT_INVALID, adding an _INVALID value as the first enum value in the enum
+#define MU_DEFINE_LOCAL_ENUM(enumName, ...) \
+    MU_DEFINE_LOCAL_ENUM_WITHOUT_INVALID(enumName, MU_C2(enumName, _INVALID), __VA_ARGS__)
+
+// this macro returns the number of enum values (taking into account that an invalid value is generated)
+#define MU_ENUM_VALUE_COUNT(...) (MU_COUNT_ARG(__VA_ARGS__) + 1)
+
+// this macro returns the number of enum 2 values (taking into account that an invalid value is generated)
+#define MU_ENUM_2_VALUE_COUNT(...) ((MU_COUNT_ARG(__VA_ARGS__) / 2) + 1)
+
+#define MU_ENUM_TO_STRING(enumName, enumValue) MU_C2(enumName, Strings)(enumValue)
+#define MU_STRING_TO_ENUM(stringValue, enumName, addressOfEnumVariable) MU_C2(enumName, _FromString)(stringValue, addressOfEnumVariable)
+
+#define MU_EMPTY()
+#define MACRO_UTILS_DELAY(id) id MU_EMPTY MU_LPAREN )
+
+#define MU_DEFINE_ENUMERATION_CONSTANT_2(enumerationConstant, constantExpression) enumerationConstant = constantExpression,
+
+#define MU_DECLARE_ENUM_STRINGS_2(enumIdentifier, ...) extern const char* MU_C3(MU_, enumIdentifier,_ToString)(enumIdentifier enumerationConstant);
+
+#define MU_DEFINE_ENUM_2_WITHOUT_INVALID(enumIdentifier, ... ) typedef enum MU_C2(enumIdentifier, _TAG) {MU_FOR_EACH_2(MU_DEFINE_ENUMERATION_CONSTANT_2, __VA_ARGS__)} enumIdentifier; \
+    MU_DECLARE_ENUM_STRINGS_2(enumIdentifier, __VA_ARGS__)
+
+// this macro is a wrapper on top of MU_DEFINE_ENUM, adding an _INVALID value as the first enum value in the enum
+#define MU_DEFINE_ENUM_2(enumName, ...) \
+    MU_DEFINE_ENUM_2_WITHOUT_INVALID(enumName, MU_C2(enumName, _INVALID), (int)0xDDDDDDDD, __VA_ARGS__)
+
+typedef struct ENUM_VALUE_AND_STRING_TAG
+{
+    int value;
+    const char* valueAsString;
+}ENUM_VALUE_AND_STRING;
+
+#define MU_DEFINE_ENUM_VALUE_AND_STRING(enumerationConstant, constantExpression) {enumerationConstant, MU_TOSTRING(enumerationConstant)},
+#define MU_DEFINE_ENUM_STRINGS_2(enumIdentifier, ... ) static const ENUM_VALUE_AND_STRING MU_C2(enumIdentifier, _ValuesAndStrings)[MU_DIV2(MU_COUNT_ARG(__VA_ARGS__))] ={MU_FOR_EACH_2(MU_DEFINE_ENUM_VALUE_AND_STRING, __VA_ARGS__)}; \
+const char* MU_C3(MU_, enumIdentifier,_ToString)(enumIdentifier value)                                                                                                                                                       \
+{                                                                                                                                                                                                                    \
+    for(size_t i=0;i<sizeof(MU_C2(enumIdentifier, _ValuesAndStrings))/sizeof(MU_C2(enumIdentifier, _ValuesAndStrings)[0]);i++)                                                                                             \
+    {                                                                                                                                                                                                                \
+        if(MU_C2(enumIdentifier, _ValuesAndStrings)[i].value == (int)value)                                                                                                                                             \
+        {                                                                                                                                                                                                            \
+            return MU_C2(enumIdentifier, _ValuesAndStrings)[i].valueAsString;                                                                                                                                           \
+        }                                                                                                                                                                                                            \
+    }                                                                                                                                                                                                                \
+    return "NULL";                                                                                                                                                                                                   \
+}                                                                                                                                                                                                                    \
+
+#define MU_ENUM_TO_STRING_2(enumIdentifier, value) MU_C3(MU_, enumIdentifier,_ToString)(value)
+
+/*PRI_MU_ENUM and MU_ENUM_VALUE/MU_ENUM_VALUE_2 work together as printf format specifier/argument. e.g: printf("enumValue was=%" PRI_MU_ENUM "\n", MU_ENUM_TO_STRING(enumIdentifier, enumValue));*/
+#define PRI_MU_ENUM "s%s (%d)"
+
+#define MU_ENUM_VALUE(enumIdentifier, value) "", MU_ENUM_TO_STRING(enumIdentifier, (value)), (int)(value)
+
+#define MU_ENUM_VALUE_2(enumIdentifier, value) "", MU_ENUM_TO_STRING_2(enumIdentifier, (value)), (int)(value)
+
+#define MU_DEFINE_STRUCT_FIELD(fieldType, fieldName) fieldType fieldName;
+
+/*MU_DEFINE_STRUCT allows creating a struct typedef based on a list of fields*/
+#define MU_DEFINE_STRUCT(structName, ...) typedef struct MU_C2(structName, _TAG) { MU_FOR_EACH_2(MU_DEFINE_STRUCT_FIELD, __VA_ARGS__)} structName;
+
+// this macro allows counting of elements in an array
+#define MU_COUNT_ARRAY_ITEMS(A) (sizeof(A)/sizeof((A)[0]))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*MACRO_UTILS_H*/
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/deps/azure-macro-utils-c/inc/azure_macro_utils/macro_utils_generated.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/deps/azure-macro-utils-c/inc/azure_macro_utils/macro_utils_generated.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/deps/azure-macro-utils-c/inc/azure_macro_utils/macro_utils_generated.h	(revision 453)
@@ -0,0 +1,22477 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/*THIS FILE IS GENERATED*/
+/*DO NOT EDIT BY HAND!!!*/
+/*instead edit macro_utils_generated.tt here: http://www.github.com/azure/azure-macro-utils-c.git */
+
+
+#ifndef MACRO_UTILS_GENERATED_H
+#define MACRO_UTILS_GENERATED_H
+
+#define MU_IFCOMMA(N) MU_C2(MU_IFCOMMA_, N)
+#define MU_IFCOMMA_0
+#define MU_IFCOMMA_2
+#define MU_IFCOMMA_4 ,
+#define MU_IFCOMMA_6 ,
+#define MU_IFCOMMA_8 ,
+#define MU_IFCOMMA_10 ,
+#define MU_IFCOMMA_12 ,
+#define MU_IFCOMMA_14 ,
+#define MU_IFCOMMA_16 ,
+#define MU_IFCOMMA_18 ,
+#define MU_IFCOMMA_20 ,
+#define MU_IFCOMMA_22 ,
+#define MU_IFCOMMA_24 ,
+#define MU_IFCOMMA_26 ,
+#define MU_IFCOMMA_28 ,
+#define MU_IFCOMMA_30 ,
+#define MU_IFCOMMA_32 ,
+#define MU_IFCOMMA_34 ,
+#define MU_IFCOMMA_36 ,
+#define MU_IFCOMMA_38 ,
+#define MU_IFCOMMA_40 ,
+#define MU_IFCOMMA_42 ,
+#define MU_IFCOMMA_44 ,
+#define MU_IFCOMMA_46 ,
+#define MU_IFCOMMA_48 ,
+#define MU_IFCOMMA_50 ,
+#define MU_IFCOMMA_52 ,
+#define MU_IFCOMMA_54 ,
+#define MU_IFCOMMA_56 ,
+#define MU_IFCOMMA_58 ,
+#define MU_IFCOMMA_60 ,
+#define MU_IFCOMMA_62 ,
+#define MU_IFCOMMA_64 ,
+#define MU_IFCOMMA_66 ,
+#define MU_IFCOMMA_68 ,
+#define MU_IFCOMMA_70 ,
+#define MU_IFCOMMA_72 ,
+#define MU_IFCOMMA_74 ,
+#define MU_IFCOMMA_76 ,
+#define MU_IFCOMMA_78 ,
+#define MU_IFCOMMA_80 ,
+#define MU_IFCOMMA_82 ,
+#define MU_IFCOMMA_84 ,
+#define MU_IFCOMMA_86 ,
+#define MU_IFCOMMA_88 ,
+#define MU_IFCOMMA_90 ,
+#define MU_IFCOMMA_92 ,
+#define MU_IFCOMMA_94 ,
+#define MU_IFCOMMA_96 ,
+#define MU_IFCOMMA_98 ,
+#define MU_IFCOMMA_100 ,
+#define MU_IFCOMMA_102 ,
+#define MU_IFCOMMA_104 ,
+#define MU_IFCOMMA_106 ,
+#define MU_IFCOMMA_108 ,
+#define MU_IFCOMMA_110 ,
+#define MU_IFCOMMA_112 ,
+#define MU_IFCOMMA_114 ,
+#define MU_IFCOMMA_116 ,
+#define MU_IFCOMMA_118 ,
+#define MU_IFCOMMA_120 ,
+#define MU_IFCOMMA_122 ,
+#define MU_IFCOMMA_124 ,
+
+#define MU_IFCOMMALOGIC(N) MU_C2(MU_IFCOMMALOGIC_, N)
+#define MU_IFCOMMALOGIC_0 
+#define MU_IFCOMMALOGIC_1 ,
+#define MU_IFCOMMALOGIC_2 ,
+#define MU_IFCOMMALOGIC_3 ,
+#define MU_IFCOMMALOGIC_4 ,
+#define MU_IFCOMMALOGIC_5 ,
+#define MU_IFCOMMALOGIC_6 ,
+#define MU_IFCOMMALOGIC_7 ,
+#define MU_IFCOMMALOGIC_8 ,
+#define MU_IFCOMMALOGIC_9 ,
+#define MU_IFCOMMALOGIC_10 ,
+#define MU_IFCOMMALOGIC_11 ,
+#define MU_IFCOMMALOGIC_12 ,
+#define MU_IFCOMMALOGIC_13 ,
+#define MU_IFCOMMALOGIC_14 ,
+#define MU_IFCOMMALOGIC_15 ,
+#define MU_IFCOMMALOGIC_16 ,
+#define MU_IFCOMMALOGIC_17 ,
+#define MU_IFCOMMALOGIC_18 ,
+#define MU_IFCOMMALOGIC_19 ,
+#define MU_IFCOMMALOGIC_20 ,
+#define MU_IFCOMMALOGIC_21 ,
+#define MU_IFCOMMALOGIC_22 ,
+#define MU_IFCOMMALOGIC_23 ,
+#define MU_IFCOMMALOGIC_24 ,
+#define MU_IFCOMMALOGIC_25 ,
+#define MU_IFCOMMALOGIC_26 ,
+#define MU_IFCOMMALOGIC_27 ,
+#define MU_IFCOMMALOGIC_28 ,
+#define MU_IFCOMMALOGIC_29 ,
+#define MU_IFCOMMALOGIC_30 ,
+#define MU_IFCOMMALOGIC_31 ,
+#define MU_IFCOMMALOGIC_32 ,
+#define MU_IFCOMMALOGIC_33 ,
+#define MU_IFCOMMALOGIC_34 ,
+#define MU_IFCOMMALOGIC_35 ,
+#define MU_IFCOMMALOGIC_36 ,
+#define MU_IFCOMMALOGIC_37 ,
+#define MU_IFCOMMALOGIC_38 ,
+#define MU_IFCOMMALOGIC_39 ,
+#define MU_IFCOMMALOGIC_40 ,
+#define MU_IFCOMMALOGIC_41 ,
+#define MU_IFCOMMALOGIC_42 ,
+#define MU_IFCOMMALOGIC_43 ,
+#define MU_IFCOMMALOGIC_44 ,
+#define MU_IFCOMMALOGIC_45 ,
+#define MU_IFCOMMALOGIC_46 ,
+#define MU_IFCOMMALOGIC_47 ,
+#define MU_IFCOMMALOGIC_48 ,
+#define MU_IFCOMMALOGIC_49 ,
+#define MU_IFCOMMALOGIC_50 ,
+#define MU_IFCOMMALOGIC_51 ,
+#define MU_IFCOMMALOGIC_52 ,
+#define MU_IFCOMMALOGIC_53 ,
+#define MU_IFCOMMALOGIC_54 ,
+#define MU_IFCOMMALOGIC_55 ,
+#define MU_IFCOMMALOGIC_56 ,
+#define MU_IFCOMMALOGIC_57 ,
+#define MU_IFCOMMALOGIC_58 ,
+#define MU_IFCOMMALOGIC_59 ,
+#define MU_IFCOMMALOGIC_60 ,
+#define MU_IFCOMMALOGIC_61 ,
+#define MU_IFCOMMALOGIC_62 ,
+#define MU_IFCOMMALOGIC_63 ,
+#define MU_IFCOMMALOGIC_64 ,
+#define MU_IFCOMMALOGIC_65 ,
+#define MU_IFCOMMALOGIC_66 ,
+#define MU_IFCOMMALOGIC_67 ,
+#define MU_IFCOMMALOGIC_68 ,
+#define MU_IFCOMMALOGIC_69 ,
+#define MU_IFCOMMALOGIC_70 ,
+#define MU_IFCOMMALOGIC_71 ,
+#define MU_IFCOMMALOGIC_72 ,
+#define MU_IFCOMMALOGIC_73 ,
+#define MU_IFCOMMALOGIC_74 ,
+#define MU_IFCOMMALOGIC_75 ,
+#define MU_IFCOMMALOGIC_76 ,
+#define MU_IFCOMMALOGIC_77 ,
+#define MU_IFCOMMALOGIC_78 ,
+#define MU_IFCOMMALOGIC_79 ,
+#define MU_IFCOMMALOGIC_80 ,
+#define MU_IFCOMMALOGIC_81 ,
+#define MU_IFCOMMALOGIC_82 ,
+#define MU_IFCOMMALOGIC_83 ,
+#define MU_IFCOMMALOGIC_84 ,
+#define MU_IFCOMMALOGIC_85 ,
+#define MU_IFCOMMALOGIC_86 ,
+#define MU_IFCOMMALOGIC_87 ,
+#define MU_IFCOMMALOGIC_88 ,
+#define MU_IFCOMMALOGIC_89 ,
+#define MU_IFCOMMALOGIC_90 ,
+#define MU_IFCOMMALOGIC_91 ,
+#define MU_IFCOMMALOGIC_92 ,
+#define MU_IFCOMMALOGIC_93 ,
+#define MU_IFCOMMALOGIC_94 ,
+#define MU_IFCOMMALOGIC_95 ,
+#define MU_IFCOMMALOGIC_96 ,
+#define MU_IFCOMMALOGIC_97 ,
+#define MU_IFCOMMALOGIC_98 ,
+#define MU_IFCOMMALOGIC_99 ,
+#define MU_IFCOMMALOGIC_100 ,
+#define MU_IFCOMMALOGIC_101 ,
+#define MU_IFCOMMALOGIC_102 ,
+#define MU_IFCOMMALOGIC_103 ,
+#define MU_IFCOMMALOGIC_104 ,
+#define MU_IFCOMMALOGIC_105 ,
+#define MU_IFCOMMALOGIC_106 ,
+#define MU_IFCOMMALOGIC_107 ,
+#define MU_IFCOMMALOGIC_108 ,
+#define MU_IFCOMMALOGIC_109 ,
+#define MU_IFCOMMALOGIC_110 ,
+#define MU_IFCOMMALOGIC_111 ,
+#define MU_IFCOMMALOGIC_112 ,
+#define MU_IFCOMMALOGIC_113 ,
+#define MU_IFCOMMALOGIC_114 ,
+#define MU_IFCOMMALOGIC_115 ,
+#define MU_IFCOMMALOGIC_116 ,
+#define MU_IFCOMMALOGIC_117 ,
+#define MU_IFCOMMALOGIC_118 ,
+#define MU_IFCOMMALOGIC_119 ,
+#define MU_IFCOMMALOGIC_120 ,
+#define MU_IFCOMMALOGIC_121 ,
+#define MU_IFCOMMALOGIC_122 ,
+#define MU_IFCOMMALOGIC_123 ,
+#define MU_IFCOMMALOGIC_124 ,
+
+#define MU_IFCOMMA_NOFIRST(N) MU_C2(MU_IFCOMMA_NOFIRST, N)
+#define MU_IFCOMMA_NOFIRST1 
+#define MU_IFCOMMA_NOFIRST2 ,
+#define MU_IFCOMMA_NOFIRST3 ,
+#define MU_IFCOMMA_NOFIRST4 ,
+#define MU_IFCOMMA_NOFIRST5 ,
+#define MU_IFCOMMA_NOFIRST6 ,
+#define MU_IFCOMMA_NOFIRST7 ,
+#define MU_IFCOMMA_NOFIRST8 ,
+#define MU_IFCOMMA_NOFIRST9 ,
+#define MU_IFCOMMA_NOFIRST10 ,
+#define MU_IFCOMMA_NOFIRST11 ,
+#define MU_IFCOMMA_NOFIRST12 ,
+#define MU_IFCOMMA_NOFIRST13 ,
+#define MU_IFCOMMA_NOFIRST14 ,
+#define MU_IFCOMMA_NOFIRST15 ,
+#define MU_IFCOMMA_NOFIRST16 ,
+#define MU_IFCOMMA_NOFIRST17 ,
+#define MU_IFCOMMA_NOFIRST18 ,
+#define MU_IFCOMMA_NOFIRST19 ,
+#define MU_IFCOMMA_NOFIRST20 ,
+#define MU_IFCOMMA_NOFIRST21 ,
+#define MU_IFCOMMA_NOFIRST22 ,
+#define MU_IFCOMMA_NOFIRST23 ,
+#define MU_IFCOMMA_NOFIRST24 ,
+#define MU_IFCOMMA_NOFIRST25 ,
+#define MU_IFCOMMA_NOFIRST26 ,
+#define MU_IFCOMMA_NOFIRST27 ,
+#define MU_IFCOMMA_NOFIRST28 ,
+#define MU_IFCOMMA_NOFIRST29 ,
+#define MU_IFCOMMA_NOFIRST30 ,
+#define MU_IFCOMMA_NOFIRST31 ,
+#define MU_IFCOMMA_NOFIRST32 ,
+#define MU_IFCOMMA_NOFIRST33 ,
+#define MU_IFCOMMA_NOFIRST34 ,
+#define MU_IFCOMMA_NOFIRST35 ,
+#define MU_IFCOMMA_NOFIRST36 ,
+#define MU_IFCOMMA_NOFIRST37 ,
+#define MU_IFCOMMA_NOFIRST38 ,
+#define MU_IFCOMMA_NOFIRST39 ,
+#define MU_IFCOMMA_NOFIRST40 ,
+#define MU_IFCOMMA_NOFIRST41 ,
+#define MU_IFCOMMA_NOFIRST42 ,
+#define MU_IFCOMMA_NOFIRST43 ,
+#define MU_IFCOMMA_NOFIRST44 ,
+#define MU_IFCOMMA_NOFIRST45 ,
+#define MU_IFCOMMA_NOFIRST46 ,
+#define MU_IFCOMMA_NOFIRST47 ,
+#define MU_IFCOMMA_NOFIRST48 ,
+#define MU_IFCOMMA_NOFIRST49 ,
+#define MU_IFCOMMA_NOFIRST50 ,
+#define MU_IFCOMMA_NOFIRST51 ,
+#define MU_IFCOMMA_NOFIRST52 ,
+#define MU_IFCOMMA_NOFIRST53 ,
+#define MU_IFCOMMA_NOFIRST54 ,
+#define MU_IFCOMMA_NOFIRST55 ,
+#define MU_IFCOMMA_NOFIRST56 ,
+#define MU_IFCOMMA_NOFIRST57 ,
+#define MU_IFCOMMA_NOFIRST58 ,
+#define MU_IFCOMMA_NOFIRST59 ,
+#define MU_IFCOMMA_NOFIRST60 ,
+#define MU_IFCOMMA_NOFIRST61 ,
+#define MU_IFCOMMA_NOFIRST62 ,
+#define MU_IFCOMMA_NOFIRST63 ,
+#define MU_IFCOMMA_NOFIRST64 ,
+#define MU_IFCOMMA_NOFIRST65 ,
+#define MU_IFCOMMA_NOFIRST66 ,
+#define MU_IFCOMMA_NOFIRST67 ,
+#define MU_IFCOMMA_NOFIRST68 ,
+#define MU_IFCOMMA_NOFIRST69 ,
+#define MU_IFCOMMA_NOFIRST70 ,
+#define MU_IFCOMMA_NOFIRST71 ,
+#define MU_IFCOMMA_NOFIRST72 ,
+#define MU_IFCOMMA_NOFIRST73 ,
+#define MU_IFCOMMA_NOFIRST74 ,
+#define MU_IFCOMMA_NOFIRST75 ,
+#define MU_IFCOMMA_NOFIRST76 ,
+#define MU_IFCOMMA_NOFIRST77 ,
+#define MU_IFCOMMA_NOFIRST78 ,
+#define MU_IFCOMMA_NOFIRST79 ,
+#define MU_IFCOMMA_NOFIRST80 ,
+#define MU_IFCOMMA_NOFIRST81 ,
+#define MU_IFCOMMA_NOFIRST82 ,
+#define MU_IFCOMMA_NOFIRST83 ,
+#define MU_IFCOMMA_NOFIRST84 ,
+#define MU_IFCOMMA_NOFIRST85 ,
+#define MU_IFCOMMA_NOFIRST86 ,
+#define MU_IFCOMMA_NOFIRST87 ,
+#define MU_IFCOMMA_NOFIRST88 ,
+#define MU_IFCOMMA_NOFIRST89 ,
+#define MU_IFCOMMA_NOFIRST90 ,
+#define MU_IFCOMMA_NOFIRST91 ,
+#define MU_IFCOMMA_NOFIRST92 ,
+#define MU_IFCOMMA_NOFIRST93 ,
+#define MU_IFCOMMA_NOFIRST94 ,
+#define MU_IFCOMMA_NOFIRST95 ,
+#define MU_IFCOMMA_NOFIRST96 ,
+#define MU_IFCOMMA_NOFIRST97 ,
+#define MU_IFCOMMA_NOFIRST98 ,
+#define MU_IFCOMMA_NOFIRST99 ,
+#define MU_IFCOMMA_NOFIRST100 ,
+#define MU_IFCOMMA_NOFIRST101 ,
+#define MU_IFCOMMA_NOFIRST102 ,
+#define MU_IFCOMMA_NOFIRST103 ,
+#define MU_IFCOMMA_NOFIRST104 ,
+#define MU_IFCOMMA_NOFIRST105 ,
+#define MU_IFCOMMA_NOFIRST106 ,
+#define MU_IFCOMMA_NOFIRST107 ,
+#define MU_IFCOMMA_NOFIRST108 ,
+#define MU_IFCOMMA_NOFIRST109 ,
+#define MU_IFCOMMA_NOFIRST110 ,
+#define MU_IFCOMMA_NOFIRST111 ,
+#define MU_IFCOMMA_NOFIRST112 ,
+#define MU_IFCOMMA_NOFIRST113 ,
+#define MU_IFCOMMA_NOFIRST114 ,
+#define MU_IFCOMMA_NOFIRST115 ,
+#define MU_IFCOMMA_NOFIRST116 ,
+#define MU_IFCOMMA_NOFIRST117 ,
+#define MU_IFCOMMA_NOFIRST118 ,
+#define MU_IFCOMMA_NOFIRST119 ,
+#define MU_IFCOMMA_NOFIRST120 ,
+#define MU_IFCOMMA_NOFIRST121 ,
+#define MU_IFCOMMA_NOFIRST122 ,
+#define MU_IFCOMMA_NOFIRST123 ,
+#define MU_IFCOMMA_NOFIRST124 ,
+
+#define MU_DEC(x) MU_C2(MU_DEC,x)
+#define MU_DEC2048 2047
+#define MU_DEC2047 2046
+#define MU_DEC2046 2045
+#define MU_DEC2045 2044
+#define MU_DEC2044 2043
+#define MU_DEC2043 2042
+#define MU_DEC2042 2041
+#define MU_DEC2041 2040
+#define MU_DEC2040 2039
+#define MU_DEC2039 2038
+#define MU_DEC2038 2037
+#define MU_DEC2037 2036
+#define MU_DEC2036 2035
+#define MU_DEC2035 2034
+#define MU_DEC2034 2033
+#define MU_DEC2033 2032
+#define MU_DEC2032 2031
+#define MU_DEC2031 2030
+#define MU_DEC2030 2029
+#define MU_DEC2029 2028
+#define MU_DEC2028 2027
+#define MU_DEC2027 2026
+#define MU_DEC2026 2025
+#define MU_DEC2025 2024
+#define MU_DEC2024 2023
+#define MU_DEC2023 2022
+#define MU_DEC2022 2021
+#define MU_DEC2021 2020
+#define MU_DEC2020 2019
+#define MU_DEC2019 2018
+#define MU_DEC2018 2017
+#define MU_DEC2017 2016
+#define MU_DEC2016 2015
+#define MU_DEC2015 2014
+#define MU_DEC2014 2013
+#define MU_DEC2013 2012
+#define MU_DEC2012 2011
+#define MU_DEC2011 2010
+#define MU_DEC2010 2009
+#define MU_DEC2009 2008
+#define MU_DEC2008 2007
+#define MU_DEC2007 2006
+#define MU_DEC2006 2005
+#define MU_DEC2005 2004
+#define MU_DEC2004 2003
+#define MU_DEC2003 2002
+#define MU_DEC2002 2001
+#define MU_DEC2001 2000
+#define MU_DEC2000 1999
+#define MU_DEC1999 1998
+#define MU_DEC1998 1997
+#define MU_DEC1997 1996
+#define MU_DEC1996 1995
+#define MU_DEC1995 1994
+#define MU_DEC1994 1993
+#define MU_DEC1993 1992
+#define MU_DEC1992 1991
+#define MU_DEC1991 1990
+#define MU_DEC1990 1989
+#define MU_DEC1989 1988
+#define MU_DEC1988 1987
+#define MU_DEC1987 1986
+#define MU_DEC1986 1985
+#define MU_DEC1985 1984
+#define MU_DEC1984 1983
+#define MU_DEC1983 1982
+#define MU_DEC1982 1981
+#define MU_DEC1981 1980
+#define MU_DEC1980 1979
+#define MU_DEC1979 1978
+#define MU_DEC1978 1977
+#define MU_DEC1977 1976
+#define MU_DEC1976 1975
+#define MU_DEC1975 1974
+#define MU_DEC1974 1973
+#define MU_DEC1973 1972
+#define MU_DEC1972 1971
+#define MU_DEC1971 1970
+#define MU_DEC1970 1969
+#define MU_DEC1969 1968
+#define MU_DEC1968 1967
+#define MU_DEC1967 1966
+#define MU_DEC1966 1965
+#define MU_DEC1965 1964
+#define MU_DEC1964 1963
+#define MU_DEC1963 1962
+#define MU_DEC1962 1961
+#define MU_DEC1961 1960
+#define MU_DEC1960 1959
+#define MU_DEC1959 1958
+#define MU_DEC1958 1957
+#define MU_DEC1957 1956
+#define MU_DEC1956 1955
+#define MU_DEC1955 1954
+#define MU_DEC1954 1953
+#define MU_DEC1953 1952
+#define MU_DEC1952 1951
+#define MU_DEC1951 1950
+#define MU_DEC1950 1949
+#define MU_DEC1949 1948
+#define MU_DEC1948 1947
+#define MU_DEC1947 1946
+#define MU_DEC1946 1945
+#define MU_DEC1945 1944
+#define MU_DEC1944 1943
+#define MU_DEC1943 1942
+#define MU_DEC1942 1941
+#define MU_DEC1941 1940
+#define MU_DEC1940 1939
+#define MU_DEC1939 1938
+#define MU_DEC1938 1937
+#define MU_DEC1937 1936
+#define MU_DEC1936 1935
+#define MU_DEC1935 1934
+#define MU_DEC1934 1933
+#define MU_DEC1933 1932
+#define MU_DEC1932 1931
+#define MU_DEC1931 1930
+#define MU_DEC1930 1929
+#define MU_DEC1929 1928
+#define MU_DEC1928 1927
+#define MU_DEC1927 1926
+#define MU_DEC1926 1925
+#define MU_DEC1925 1924
+#define MU_DEC1924 1923
+#define MU_DEC1923 1922
+#define MU_DEC1922 1921
+#define MU_DEC1921 1920
+#define MU_DEC1920 1919
+#define MU_DEC1919 1918
+#define MU_DEC1918 1917
+#define MU_DEC1917 1916
+#define MU_DEC1916 1915
+#define MU_DEC1915 1914
+#define MU_DEC1914 1913
+#define MU_DEC1913 1912
+#define MU_DEC1912 1911
+#define MU_DEC1911 1910
+#define MU_DEC1910 1909
+#define MU_DEC1909 1908
+#define MU_DEC1908 1907
+#define MU_DEC1907 1906
+#define MU_DEC1906 1905
+#define MU_DEC1905 1904
+#define MU_DEC1904 1903
+#define MU_DEC1903 1902
+#define MU_DEC1902 1901
+#define MU_DEC1901 1900
+#define MU_DEC1900 1899
+#define MU_DEC1899 1898
+#define MU_DEC1898 1897
+#define MU_DEC1897 1896
+#define MU_DEC1896 1895
+#define MU_DEC1895 1894
+#define MU_DEC1894 1893
+#define MU_DEC1893 1892
+#define MU_DEC1892 1891
+#define MU_DEC1891 1890
+#define MU_DEC1890 1889
+#define MU_DEC1889 1888
+#define MU_DEC1888 1887
+#define MU_DEC1887 1886
+#define MU_DEC1886 1885
+#define MU_DEC1885 1884
+#define MU_DEC1884 1883
+#define MU_DEC1883 1882
+#define MU_DEC1882 1881
+#define MU_DEC1881 1880
+#define MU_DEC1880 1879
+#define MU_DEC1879 1878
+#define MU_DEC1878 1877
+#define MU_DEC1877 1876
+#define MU_DEC1876 1875
+#define MU_DEC1875 1874
+#define MU_DEC1874 1873
+#define MU_DEC1873 1872
+#define MU_DEC1872 1871
+#define MU_DEC1871 1870
+#define MU_DEC1870 1869
+#define MU_DEC1869 1868
+#define MU_DEC1868 1867
+#define MU_DEC1867 1866
+#define MU_DEC1866 1865
+#define MU_DEC1865 1864
+#define MU_DEC1864 1863
+#define MU_DEC1863 1862
+#define MU_DEC1862 1861
+#define MU_DEC1861 1860
+#define MU_DEC1860 1859
+#define MU_DEC1859 1858
+#define MU_DEC1858 1857
+#define MU_DEC1857 1856
+#define MU_DEC1856 1855
+#define MU_DEC1855 1854
+#define MU_DEC1854 1853
+#define MU_DEC1853 1852
+#define MU_DEC1852 1851
+#define MU_DEC1851 1850
+#define MU_DEC1850 1849
+#define MU_DEC1849 1848
+#define MU_DEC1848 1847
+#define MU_DEC1847 1846
+#define MU_DEC1846 1845
+#define MU_DEC1845 1844
+#define MU_DEC1844 1843
+#define MU_DEC1843 1842
+#define MU_DEC1842 1841
+#define MU_DEC1841 1840
+#define MU_DEC1840 1839
+#define MU_DEC1839 1838
+#define MU_DEC1838 1837
+#define MU_DEC1837 1836
+#define MU_DEC1836 1835
+#define MU_DEC1835 1834
+#define MU_DEC1834 1833
+#define MU_DEC1833 1832
+#define MU_DEC1832 1831
+#define MU_DEC1831 1830
+#define MU_DEC1830 1829
+#define MU_DEC1829 1828
+#define MU_DEC1828 1827
+#define MU_DEC1827 1826
+#define MU_DEC1826 1825
+#define MU_DEC1825 1824
+#define MU_DEC1824 1823
+#define MU_DEC1823 1822
+#define MU_DEC1822 1821
+#define MU_DEC1821 1820
+#define MU_DEC1820 1819
+#define MU_DEC1819 1818
+#define MU_DEC1818 1817
+#define MU_DEC1817 1816
+#define MU_DEC1816 1815
+#define MU_DEC1815 1814
+#define MU_DEC1814 1813
+#define MU_DEC1813 1812
+#define MU_DEC1812 1811
+#define MU_DEC1811 1810
+#define MU_DEC1810 1809
+#define MU_DEC1809 1808
+#define MU_DEC1808 1807
+#define MU_DEC1807 1806
+#define MU_DEC1806 1805
+#define MU_DEC1805 1804
+#define MU_DEC1804 1803
+#define MU_DEC1803 1802
+#define MU_DEC1802 1801
+#define MU_DEC1801 1800
+#define MU_DEC1800 1799
+#define MU_DEC1799 1798
+#define MU_DEC1798 1797
+#define MU_DEC1797 1796
+#define MU_DEC1796 1795
+#define MU_DEC1795 1794
+#define MU_DEC1794 1793
+#define MU_DEC1793 1792
+#define MU_DEC1792 1791
+#define MU_DEC1791 1790
+#define MU_DEC1790 1789
+#define MU_DEC1789 1788
+#define MU_DEC1788 1787
+#define MU_DEC1787 1786
+#define MU_DEC1786 1785
+#define MU_DEC1785 1784
+#define MU_DEC1784 1783
+#define MU_DEC1783 1782
+#define MU_DEC1782 1781
+#define MU_DEC1781 1780
+#define MU_DEC1780 1779
+#define MU_DEC1779 1778
+#define MU_DEC1778 1777
+#define MU_DEC1777 1776
+#define MU_DEC1776 1775
+#define MU_DEC1775 1774
+#define MU_DEC1774 1773
+#define MU_DEC1773 1772
+#define MU_DEC1772 1771
+#define MU_DEC1771 1770
+#define MU_DEC1770 1769
+#define MU_DEC1769 1768
+#define MU_DEC1768 1767
+#define MU_DEC1767 1766
+#define MU_DEC1766 1765
+#define MU_DEC1765 1764
+#define MU_DEC1764 1763
+#define MU_DEC1763 1762
+#define MU_DEC1762 1761
+#define MU_DEC1761 1760
+#define MU_DEC1760 1759
+#define MU_DEC1759 1758
+#define MU_DEC1758 1757
+#define MU_DEC1757 1756
+#define MU_DEC1756 1755
+#define MU_DEC1755 1754
+#define MU_DEC1754 1753
+#define MU_DEC1753 1752
+#define MU_DEC1752 1751
+#define MU_DEC1751 1750
+#define MU_DEC1750 1749
+#define MU_DEC1749 1748
+#define MU_DEC1748 1747
+#define MU_DEC1747 1746
+#define MU_DEC1746 1745
+#define MU_DEC1745 1744
+#define MU_DEC1744 1743
+#define MU_DEC1743 1742
+#define MU_DEC1742 1741
+#define MU_DEC1741 1740
+#define MU_DEC1740 1739
+#define MU_DEC1739 1738
+#define MU_DEC1738 1737
+#define MU_DEC1737 1736
+#define MU_DEC1736 1735
+#define MU_DEC1735 1734
+#define MU_DEC1734 1733
+#define MU_DEC1733 1732
+#define MU_DEC1732 1731
+#define MU_DEC1731 1730
+#define MU_DEC1730 1729
+#define MU_DEC1729 1728
+#define MU_DEC1728 1727
+#define MU_DEC1727 1726
+#define MU_DEC1726 1725
+#define MU_DEC1725 1724
+#define MU_DEC1724 1723
+#define MU_DEC1723 1722
+#define MU_DEC1722 1721
+#define MU_DEC1721 1720
+#define MU_DEC1720 1719
+#define MU_DEC1719 1718
+#define MU_DEC1718 1717
+#define MU_DEC1717 1716
+#define MU_DEC1716 1715
+#define MU_DEC1715 1714
+#define MU_DEC1714 1713
+#define MU_DEC1713 1712
+#define MU_DEC1712 1711
+#define MU_DEC1711 1710
+#define MU_DEC1710 1709
+#define MU_DEC1709 1708
+#define MU_DEC1708 1707
+#define MU_DEC1707 1706
+#define MU_DEC1706 1705
+#define MU_DEC1705 1704
+#define MU_DEC1704 1703
+#define MU_DEC1703 1702
+#define MU_DEC1702 1701
+#define MU_DEC1701 1700
+#define MU_DEC1700 1699
+#define MU_DEC1699 1698
+#define MU_DEC1698 1697
+#define MU_DEC1697 1696
+#define MU_DEC1696 1695
+#define MU_DEC1695 1694
+#define MU_DEC1694 1693
+#define MU_DEC1693 1692
+#define MU_DEC1692 1691
+#define MU_DEC1691 1690
+#define MU_DEC1690 1689
+#define MU_DEC1689 1688
+#define MU_DEC1688 1687
+#define MU_DEC1687 1686
+#define MU_DEC1686 1685
+#define MU_DEC1685 1684
+#define MU_DEC1684 1683
+#define MU_DEC1683 1682
+#define MU_DEC1682 1681
+#define MU_DEC1681 1680
+#define MU_DEC1680 1679
+#define MU_DEC1679 1678
+#define MU_DEC1678 1677
+#define MU_DEC1677 1676
+#define MU_DEC1676 1675
+#define MU_DEC1675 1674
+#define MU_DEC1674 1673
+#define MU_DEC1673 1672
+#define MU_DEC1672 1671
+#define MU_DEC1671 1670
+#define MU_DEC1670 1669
+#define MU_DEC1669 1668
+#define MU_DEC1668 1667
+#define MU_DEC1667 1666
+#define MU_DEC1666 1665
+#define MU_DEC1665 1664
+#define MU_DEC1664 1663
+#define MU_DEC1663 1662
+#define MU_DEC1662 1661
+#define MU_DEC1661 1660
+#define MU_DEC1660 1659
+#define MU_DEC1659 1658
+#define MU_DEC1658 1657
+#define MU_DEC1657 1656
+#define MU_DEC1656 1655
+#define MU_DEC1655 1654
+#define MU_DEC1654 1653
+#define MU_DEC1653 1652
+#define MU_DEC1652 1651
+#define MU_DEC1651 1650
+#define MU_DEC1650 1649
+#define MU_DEC1649 1648
+#define MU_DEC1648 1647
+#define MU_DEC1647 1646
+#define MU_DEC1646 1645
+#define MU_DEC1645 1644
+#define MU_DEC1644 1643
+#define MU_DEC1643 1642
+#define MU_DEC1642 1641
+#define MU_DEC1641 1640
+#define MU_DEC1640 1639
+#define MU_DEC1639 1638
+#define MU_DEC1638 1637
+#define MU_DEC1637 1636
+#define MU_DEC1636 1635
+#define MU_DEC1635 1634
+#define MU_DEC1634 1633
+#define MU_DEC1633 1632
+#define MU_DEC1632 1631
+#define MU_DEC1631 1630
+#define MU_DEC1630 1629
+#define MU_DEC1629 1628
+#define MU_DEC1628 1627
+#define MU_DEC1627 1626
+#define MU_DEC1626 1625
+#define MU_DEC1625 1624
+#define MU_DEC1624 1623
+#define MU_DEC1623 1622
+#define MU_DEC1622 1621
+#define MU_DEC1621 1620
+#define MU_DEC1620 1619
+#define MU_DEC1619 1618
+#define MU_DEC1618 1617
+#define MU_DEC1617 1616
+#define MU_DEC1616 1615
+#define MU_DEC1615 1614
+#define MU_DEC1614 1613
+#define MU_DEC1613 1612
+#define MU_DEC1612 1611
+#define MU_DEC1611 1610
+#define MU_DEC1610 1609
+#define MU_DEC1609 1608
+#define MU_DEC1608 1607
+#define MU_DEC1607 1606
+#define MU_DEC1606 1605
+#define MU_DEC1605 1604
+#define MU_DEC1604 1603
+#define MU_DEC1603 1602
+#define MU_DEC1602 1601
+#define MU_DEC1601 1600
+#define MU_DEC1600 1599
+#define MU_DEC1599 1598
+#define MU_DEC1598 1597
+#define MU_DEC1597 1596
+#define MU_DEC1596 1595
+#define MU_DEC1595 1594
+#define MU_DEC1594 1593
+#define MU_DEC1593 1592
+#define MU_DEC1592 1591
+#define MU_DEC1591 1590
+#define MU_DEC1590 1589
+#define MU_DEC1589 1588
+#define MU_DEC1588 1587
+#define MU_DEC1587 1586
+#define MU_DEC1586 1585
+#define MU_DEC1585 1584
+#define MU_DEC1584 1583
+#define MU_DEC1583 1582
+#define MU_DEC1582 1581
+#define MU_DEC1581 1580
+#define MU_DEC1580 1579
+#define MU_DEC1579 1578
+#define MU_DEC1578 1577
+#define MU_DEC1577 1576
+#define MU_DEC1576 1575
+#define MU_DEC1575 1574
+#define MU_DEC1574 1573
+#define MU_DEC1573 1572
+#define MU_DEC1572 1571
+#define MU_DEC1571 1570
+#define MU_DEC1570 1569
+#define MU_DEC1569 1568
+#define MU_DEC1568 1567
+#define MU_DEC1567 1566
+#define MU_DEC1566 1565
+#define MU_DEC1565 1564
+#define MU_DEC1564 1563
+#define MU_DEC1563 1562
+#define MU_DEC1562 1561
+#define MU_DEC1561 1560
+#define MU_DEC1560 1559
+#define MU_DEC1559 1558
+#define MU_DEC1558 1557
+#define MU_DEC1557 1556
+#define MU_DEC1556 1555
+#define MU_DEC1555 1554
+#define MU_DEC1554 1553
+#define MU_DEC1553 1552
+#define MU_DEC1552 1551
+#define MU_DEC1551 1550
+#define MU_DEC1550 1549
+#define MU_DEC1549 1548
+#define MU_DEC1548 1547
+#define MU_DEC1547 1546
+#define MU_DEC1546 1545
+#define MU_DEC1545 1544
+#define MU_DEC1544 1543
+#define MU_DEC1543 1542
+#define MU_DEC1542 1541
+#define MU_DEC1541 1540
+#define MU_DEC1540 1539
+#define MU_DEC1539 1538
+#define MU_DEC1538 1537
+#define MU_DEC1537 1536
+#define MU_DEC1536 1535
+#define MU_DEC1535 1534
+#define MU_DEC1534 1533
+#define MU_DEC1533 1532
+#define MU_DEC1532 1531
+#define MU_DEC1531 1530
+#define MU_DEC1530 1529
+#define MU_DEC1529 1528
+#define MU_DEC1528 1527
+#define MU_DEC1527 1526
+#define MU_DEC1526 1525
+#define MU_DEC1525 1524
+#define MU_DEC1524 1523
+#define MU_DEC1523 1522
+#define MU_DEC1522 1521
+#define MU_DEC1521 1520
+#define MU_DEC1520 1519
+#define MU_DEC1519 1518
+#define MU_DEC1518 1517
+#define MU_DEC1517 1516
+#define MU_DEC1516 1515
+#define MU_DEC1515 1514
+#define MU_DEC1514 1513
+#define MU_DEC1513 1512
+#define MU_DEC1512 1511
+#define MU_DEC1511 1510
+#define MU_DEC1510 1509
+#define MU_DEC1509 1508
+#define MU_DEC1508 1507
+#define MU_DEC1507 1506
+#define MU_DEC1506 1505
+#define MU_DEC1505 1504
+#define MU_DEC1504 1503
+#define MU_DEC1503 1502
+#define MU_DEC1502 1501
+#define MU_DEC1501 1500
+#define MU_DEC1500 1499
+#define MU_DEC1499 1498
+#define MU_DEC1498 1497
+#define MU_DEC1497 1496
+#define MU_DEC1496 1495
+#define MU_DEC1495 1494
+#define MU_DEC1494 1493
+#define MU_DEC1493 1492
+#define MU_DEC1492 1491
+#define MU_DEC1491 1490
+#define MU_DEC1490 1489
+#define MU_DEC1489 1488
+#define MU_DEC1488 1487
+#define MU_DEC1487 1486
+#define MU_DEC1486 1485
+#define MU_DEC1485 1484
+#define MU_DEC1484 1483
+#define MU_DEC1483 1482
+#define MU_DEC1482 1481
+#define MU_DEC1481 1480
+#define MU_DEC1480 1479
+#define MU_DEC1479 1478
+#define MU_DEC1478 1477
+#define MU_DEC1477 1476
+#define MU_DEC1476 1475
+#define MU_DEC1475 1474
+#define MU_DEC1474 1473
+#define MU_DEC1473 1472
+#define MU_DEC1472 1471
+#define MU_DEC1471 1470
+#define MU_DEC1470 1469
+#define MU_DEC1469 1468
+#define MU_DEC1468 1467
+#define MU_DEC1467 1466
+#define MU_DEC1466 1465
+#define MU_DEC1465 1464
+#define MU_DEC1464 1463
+#define MU_DEC1463 1462
+#define MU_DEC1462 1461
+#define MU_DEC1461 1460
+#define MU_DEC1460 1459
+#define MU_DEC1459 1458
+#define MU_DEC1458 1457
+#define MU_DEC1457 1456
+#define MU_DEC1456 1455
+#define MU_DEC1455 1454
+#define MU_DEC1454 1453
+#define MU_DEC1453 1452
+#define MU_DEC1452 1451
+#define MU_DEC1451 1450
+#define MU_DEC1450 1449
+#define MU_DEC1449 1448
+#define MU_DEC1448 1447
+#define MU_DEC1447 1446
+#define MU_DEC1446 1445
+#define MU_DEC1445 1444
+#define MU_DEC1444 1443
+#define MU_DEC1443 1442
+#define MU_DEC1442 1441
+#define MU_DEC1441 1440
+#define MU_DEC1440 1439
+#define MU_DEC1439 1438
+#define MU_DEC1438 1437
+#define MU_DEC1437 1436
+#define MU_DEC1436 1435
+#define MU_DEC1435 1434
+#define MU_DEC1434 1433
+#define MU_DEC1433 1432
+#define MU_DEC1432 1431
+#define MU_DEC1431 1430
+#define MU_DEC1430 1429
+#define MU_DEC1429 1428
+#define MU_DEC1428 1427
+#define MU_DEC1427 1426
+#define MU_DEC1426 1425
+#define MU_DEC1425 1424
+#define MU_DEC1424 1423
+#define MU_DEC1423 1422
+#define MU_DEC1422 1421
+#define MU_DEC1421 1420
+#define MU_DEC1420 1419
+#define MU_DEC1419 1418
+#define MU_DEC1418 1417
+#define MU_DEC1417 1416
+#define MU_DEC1416 1415
+#define MU_DEC1415 1414
+#define MU_DEC1414 1413
+#define MU_DEC1413 1412
+#define MU_DEC1412 1411
+#define MU_DEC1411 1410
+#define MU_DEC1410 1409
+#define MU_DEC1409 1408
+#define MU_DEC1408 1407
+#define MU_DEC1407 1406
+#define MU_DEC1406 1405
+#define MU_DEC1405 1404
+#define MU_DEC1404 1403
+#define MU_DEC1403 1402
+#define MU_DEC1402 1401
+#define MU_DEC1401 1400
+#define MU_DEC1400 1399
+#define MU_DEC1399 1398
+#define MU_DEC1398 1397
+#define MU_DEC1397 1396
+#define MU_DEC1396 1395
+#define MU_DEC1395 1394
+#define MU_DEC1394 1393
+#define MU_DEC1393 1392
+#define MU_DEC1392 1391
+#define MU_DEC1391 1390
+#define MU_DEC1390 1389
+#define MU_DEC1389 1388
+#define MU_DEC1388 1387
+#define MU_DEC1387 1386
+#define MU_DEC1386 1385
+#define MU_DEC1385 1384
+#define MU_DEC1384 1383
+#define MU_DEC1383 1382
+#define MU_DEC1382 1381
+#define MU_DEC1381 1380
+#define MU_DEC1380 1379
+#define MU_DEC1379 1378
+#define MU_DEC1378 1377
+#define MU_DEC1377 1376
+#define MU_DEC1376 1375
+#define MU_DEC1375 1374
+#define MU_DEC1374 1373
+#define MU_DEC1373 1372
+#define MU_DEC1372 1371
+#define MU_DEC1371 1370
+#define MU_DEC1370 1369
+#define MU_DEC1369 1368
+#define MU_DEC1368 1367
+#define MU_DEC1367 1366
+#define MU_DEC1366 1365
+#define MU_DEC1365 1364
+#define MU_DEC1364 1363
+#define MU_DEC1363 1362
+#define MU_DEC1362 1361
+#define MU_DEC1361 1360
+#define MU_DEC1360 1359
+#define MU_DEC1359 1358
+#define MU_DEC1358 1357
+#define MU_DEC1357 1356
+#define MU_DEC1356 1355
+#define MU_DEC1355 1354
+#define MU_DEC1354 1353
+#define MU_DEC1353 1352
+#define MU_DEC1352 1351
+#define MU_DEC1351 1350
+#define MU_DEC1350 1349
+#define MU_DEC1349 1348
+#define MU_DEC1348 1347
+#define MU_DEC1347 1346
+#define MU_DEC1346 1345
+#define MU_DEC1345 1344
+#define MU_DEC1344 1343
+#define MU_DEC1343 1342
+#define MU_DEC1342 1341
+#define MU_DEC1341 1340
+#define MU_DEC1340 1339
+#define MU_DEC1339 1338
+#define MU_DEC1338 1337
+#define MU_DEC1337 1336
+#define MU_DEC1336 1335
+#define MU_DEC1335 1334
+#define MU_DEC1334 1333
+#define MU_DEC1333 1332
+#define MU_DEC1332 1331
+#define MU_DEC1331 1330
+#define MU_DEC1330 1329
+#define MU_DEC1329 1328
+#define MU_DEC1328 1327
+#define MU_DEC1327 1326
+#define MU_DEC1326 1325
+#define MU_DEC1325 1324
+#define MU_DEC1324 1323
+#define MU_DEC1323 1322
+#define MU_DEC1322 1321
+#define MU_DEC1321 1320
+#define MU_DEC1320 1319
+#define MU_DEC1319 1318
+#define MU_DEC1318 1317
+#define MU_DEC1317 1316
+#define MU_DEC1316 1315
+#define MU_DEC1315 1314
+#define MU_DEC1314 1313
+#define MU_DEC1313 1312
+#define MU_DEC1312 1311
+#define MU_DEC1311 1310
+#define MU_DEC1310 1309
+#define MU_DEC1309 1308
+#define MU_DEC1308 1307
+#define MU_DEC1307 1306
+#define MU_DEC1306 1305
+#define MU_DEC1305 1304
+#define MU_DEC1304 1303
+#define MU_DEC1303 1302
+#define MU_DEC1302 1301
+#define MU_DEC1301 1300
+#define MU_DEC1300 1299
+#define MU_DEC1299 1298
+#define MU_DEC1298 1297
+#define MU_DEC1297 1296
+#define MU_DEC1296 1295
+#define MU_DEC1295 1294
+#define MU_DEC1294 1293
+#define MU_DEC1293 1292
+#define MU_DEC1292 1291
+#define MU_DEC1291 1290
+#define MU_DEC1290 1289
+#define MU_DEC1289 1288
+#define MU_DEC1288 1287
+#define MU_DEC1287 1286
+#define MU_DEC1286 1285
+#define MU_DEC1285 1284
+#define MU_DEC1284 1283
+#define MU_DEC1283 1282
+#define MU_DEC1282 1281
+#define MU_DEC1281 1280
+#define MU_DEC1280 1279
+#define MU_DEC1279 1278
+#define MU_DEC1278 1277
+#define MU_DEC1277 1276
+#define MU_DEC1276 1275
+#define MU_DEC1275 1274
+#define MU_DEC1274 1273
+#define MU_DEC1273 1272
+#define MU_DEC1272 1271
+#define MU_DEC1271 1270
+#define MU_DEC1270 1269
+#define MU_DEC1269 1268
+#define MU_DEC1268 1267
+#define MU_DEC1267 1266
+#define MU_DEC1266 1265
+#define MU_DEC1265 1264
+#define MU_DEC1264 1263
+#define MU_DEC1263 1262
+#define MU_DEC1262 1261
+#define MU_DEC1261 1260
+#define MU_DEC1260 1259
+#define MU_DEC1259 1258
+#define MU_DEC1258 1257
+#define MU_DEC1257 1256
+#define MU_DEC1256 1255
+#define MU_DEC1255 1254
+#define MU_DEC1254 1253
+#define MU_DEC1253 1252
+#define MU_DEC1252 1251
+#define MU_DEC1251 1250
+#define MU_DEC1250 1249
+#define MU_DEC1249 1248
+#define MU_DEC1248 1247
+#define MU_DEC1247 1246
+#define MU_DEC1246 1245
+#define MU_DEC1245 1244
+#define MU_DEC1244 1243
+#define MU_DEC1243 1242
+#define MU_DEC1242 1241
+#define MU_DEC1241 1240
+#define MU_DEC1240 1239
+#define MU_DEC1239 1238
+#define MU_DEC1238 1237
+#define MU_DEC1237 1236
+#define MU_DEC1236 1235
+#define MU_DEC1235 1234
+#define MU_DEC1234 1233
+#define MU_DEC1233 1232
+#define MU_DEC1232 1231
+#define MU_DEC1231 1230
+#define MU_DEC1230 1229
+#define MU_DEC1229 1228
+#define MU_DEC1228 1227
+#define MU_DEC1227 1226
+#define MU_DEC1226 1225
+#define MU_DEC1225 1224
+#define MU_DEC1224 1223
+#define MU_DEC1223 1222
+#define MU_DEC1222 1221
+#define MU_DEC1221 1220
+#define MU_DEC1220 1219
+#define MU_DEC1219 1218
+#define MU_DEC1218 1217
+#define MU_DEC1217 1216
+#define MU_DEC1216 1215
+#define MU_DEC1215 1214
+#define MU_DEC1214 1213
+#define MU_DEC1213 1212
+#define MU_DEC1212 1211
+#define MU_DEC1211 1210
+#define MU_DEC1210 1209
+#define MU_DEC1209 1208
+#define MU_DEC1208 1207
+#define MU_DEC1207 1206
+#define MU_DEC1206 1205
+#define MU_DEC1205 1204
+#define MU_DEC1204 1203
+#define MU_DEC1203 1202
+#define MU_DEC1202 1201
+#define MU_DEC1201 1200
+#define MU_DEC1200 1199
+#define MU_DEC1199 1198
+#define MU_DEC1198 1197
+#define MU_DEC1197 1196
+#define MU_DEC1196 1195
+#define MU_DEC1195 1194
+#define MU_DEC1194 1193
+#define MU_DEC1193 1192
+#define MU_DEC1192 1191
+#define MU_DEC1191 1190
+#define MU_DEC1190 1189
+#define MU_DEC1189 1188
+#define MU_DEC1188 1187
+#define MU_DEC1187 1186
+#define MU_DEC1186 1185
+#define MU_DEC1185 1184
+#define MU_DEC1184 1183
+#define MU_DEC1183 1182
+#define MU_DEC1182 1181
+#define MU_DEC1181 1180
+#define MU_DEC1180 1179
+#define MU_DEC1179 1178
+#define MU_DEC1178 1177
+#define MU_DEC1177 1176
+#define MU_DEC1176 1175
+#define MU_DEC1175 1174
+#define MU_DEC1174 1173
+#define MU_DEC1173 1172
+#define MU_DEC1172 1171
+#define MU_DEC1171 1170
+#define MU_DEC1170 1169
+#define MU_DEC1169 1168
+#define MU_DEC1168 1167
+#define MU_DEC1167 1166
+#define MU_DEC1166 1165
+#define MU_DEC1165 1164
+#define MU_DEC1164 1163
+#define MU_DEC1163 1162
+#define MU_DEC1162 1161
+#define MU_DEC1161 1160
+#define MU_DEC1160 1159
+#define MU_DEC1159 1158
+#define MU_DEC1158 1157
+#define MU_DEC1157 1156
+#define MU_DEC1156 1155
+#define MU_DEC1155 1154
+#define MU_DEC1154 1153
+#define MU_DEC1153 1152
+#define MU_DEC1152 1151
+#define MU_DEC1151 1150
+#define MU_DEC1150 1149
+#define MU_DEC1149 1148
+#define MU_DEC1148 1147
+#define MU_DEC1147 1146
+#define MU_DEC1146 1145
+#define MU_DEC1145 1144
+#define MU_DEC1144 1143
+#define MU_DEC1143 1142
+#define MU_DEC1142 1141
+#define MU_DEC1141 1140
+#define MU_DEC1140 1139
+#define MU_DEC1139 1138
+#define MU_DEC1138 1137
+#define MU_DEC1137 1136
+#define MU_DEC1136 1135
+#define MU_DEC1135 1134
+#define MU_DEC1134 1133
+#define MU_DEC1133 1132
+#define MU_DEC1132 1131
+#define MU_DEC1131 1130
+#define MU_DEC1130 1129
+#define MU_DEC1129 1128
+#define MU_DEC1128 1127
+#define MU_DEC1127 1126
+#define MU_DEC1126 1125
+#define MU_DEC1125 1124
+#define MU_DEC1124 1123
+#define MU_DEC1123 1122
+#define MU_DEC1122 1121
+#define MU_DEC1121 1120
+#define MU_DEC1120 1119
+#define MU_DEC1119 1118
+#define MU_DEC1118 1117
+#define MU_DEC1117 1116
+#define MU_DEC1116 1115
+#define MU_DEC1115 1114
+#define MU_DEC1114 1113
+#define MU_DEC1113 1112
+#define MU_DEC1112 1111
+#define MU_DEC1111 1110
+#define MU_DEC1110 1109
+#define MU_DEC1109 1108
+#define MU_DEC1108 1107
+#define MU_DEC1107 1106
+#define MU_DEC1106 1105
+#define MU_DEC1105 1104
+#define MU_DEC1104 1103
+#define MU_DEC1103 1102
+#define MU_DEC1102 1101
+#define MU_DEC1101 1100
+#define MU_DEC1100 1099
+#define MU_DEC1099 1098
+#define MU_DEC1098 1097
+#define MU_DEC1097 1096
+#define MU_DEC1096 1095
+#define MU_DEC1095 1094
+#define MU_DEC1094 1093
+#define MU_DEC1093 1092
+#define MU_DEC1092 1091
+#define MU_DEC1091 1090
+#define MU_DEC1090 1089
+#define MU_DEC1089 1088
+#define MU_DEC1088 1087
+#define MU_DEC1087 1086
+#define MU_DEC1086 1085
+#define MU_DEC1085 1084
+#define MU_DEC1084 1083
+#define MU_DEC1083 1082
+#define MU_DEC1082 1081
+#define MU_DEC1081 1080
+#define MU_DEC1080 1079
+#define MU_DEC1079 1078
+#define MU_DEC1078 1077
+#define MU_DEC1077 1076
+#define MU_DEC1076 1075
+#define MU_DEC1075 1074
+#define MU_DEC1074 1073
+#define MU_DEC1073 1072
+#define MU_DEC1072 1071
+#define MU_DEC1071 1070
+#define MU_DEC1070 1069
+#define MU_DEC1069 1068
+#define MU_DEC1068 1067
+#define MU_DEC1067 1066
+#define MU_DEC1066 1065
+#define MU_DEC1065 1064
+#define MU_DEC1064 1063
+#define MU_DEC1063 1062
+#define MU_DEC1062 1061
+#define MU_DEC1061 1060
+#define MU_DEC1060 1059
+#define MU_DEC1059 1058
+#define MU_DEC1058 1057
+#define MU_DEC1057 1056
+#define MU_DEC1056 1055
+#define MU_DEC1055 1054
+#define MU_DEC1054 1053
+#define MU_DEC1053 1052
+#define MU_DEC1052 1051
+#define MU_DEC1051 1050
+#define MU_DEC1050 1049
+#define MU_DEC1049 1048
+#define MU_DEC1048 1047
+#define MU_DEC1047 1046
+#define MU_DEC1046 1045
+#define MU_DEC1045 1044
+#define MU_DEC1044 1043
+#define MU_DEC1043 1042
+#define MU_DEC1042 1041
+#define MU_DEC1041 1040
+#define MU_DEC1040 1039
+#define MU_DEC1039 1038
+#define MU_DEC1038 1037
+#define MU_DEC1037 1036
+#define MU_DEC1036 1035
+#define MU_DEC1035 1034
+#define MU_DEC1034 1033
+#define MU_DEC1033 1032
+#define MU_DEC1032 1031
+#define MU_DEC1031 1030
+#define MU_DEC1030 1029
+#define MU_DEC1029 1028
+#define MU_DEC1028 1027
+#define MU_DEC1027 1026
+#define MU_DEC1026 1025
+#define MU_DEC1025 1024
+#define MU_DEC1024 1023
+#define MU_DEC1023 1022
+#define MU_DEC1022 1021
+#define MU_DEC1021 1020
+#define MU_DEC1020 1019
+#define MU_DEC1019 1018
+#define MU_DEC1018 1017
+#define MU_DEC1017 1016
+#define MU_DEC1016 1015
+#define MU_DEC1015 1014
+#define MU_DEC1014 1013
+#define MU_DEC1013 1012
+#define MU_DEC1012 1011
+#define MU_DEC1011 1010
+#define MU_DEC1010 1009
+#define MU_DEC1009 1008
+#define MU_DEC1008 1007
+#define MU_DEC1007 1006
+#define MU_DEC1006 1005
+#define MU_DEC1005 1004
+#define MU_DEC1004 1003
+#define MU_DEC1003 1002
+#define MU_DEC1002 1001
+#define MU_DEC1001 1000
+#define MU_DEC1000 999
+#define MU_DEC999 998
+#define MU_DEC998 997
+#define MU_DEC997 996
+#define MU_DEC996 995
+#define MU_DEC995 994
+#define MU_DEC994 993
+#define MU_DEC993 992
+#define MU_DEC992 991
+#define MU_DEC991 990
+#define MU_DEC990 989
+#define MU_DEC989 988
+#define MU_DEC988 987
+#define MU_DEC987 986
+#define MU_DEC986 985
+#define MU_DEC985 984
+#define MU_DEC984 983
+#define MU_DEC983 982
+#define MU_DEC982 981
+#define MU_DEC981 980
+#define MU_DEC980 979
+#define MU_DEC979 978
+#define MU_DEC978 977
+#define MU_DEC977 976
+#define MU_DEC976 975
+#define MU_DEC975 974
+#define MU_DEC974 973
+#define MU_DEC973 972
+#define MU_DEC972 971
+#define MU_DEC971 970
+#define MU_DEC970 969
+#define MU_DEC969 968
+#define MU_DEC968 967
+#define MU_DEC967 966
+#define MU_DEC966 965
+#define MU_DEC965 964
+#define MU_DEC964 963
+#define MU_DEC963 962
+#define MU_DEC962 961
+#define MU_DEC961 960
+#define MU_DEC960 959
+#define MU_DEC959 958
+#define MU_DEC958 957
+#define MU_DEC957 956
+#define MU_DEC956 955
+#define MU_DEC955 954
+#define MU_DEC954 953
+#define MU_DEC953 952
+#define MU_DEC952 951
+#define MU_DEC951 950
+#define MU_DEC950 949
+#define MU_DEC949 948
+#define MU_DEC948 947
+#define MU_DEC947 946
+#define MU_DEC946 945
+#define MU_DEC945 944
+#define MU_DEC944 943
+#define MU_DEC943 942
+#define MU_DEC942 941
+#define MU_DEC941 940
+#define MU_DEC940 939
+#define MU_DEC939 938
+#define MU_DEC938 937
+#define MU_DEC937 936
+#define MU_DEC936 935
+#define MU_DEC935 934
+#define MU_DEC934 933
+#define MU_DEC933 932
+#define MU_DEC932 931
+#define MU_DEC931 930
+#define MU_DEC930 929
+#define MU_DEC929 928
+#define MU_DEC928 927
+#define MU_DEC927 926
+#define MU_DEC926 925
+#define MU_DEC925 924
+#define MU_DEC924 923
+#define MU_DEC923 922
+#define MU_DEC922 921
+#define MU_DEC921 920
+#define MU_DEC920 919
+#define MU_DEC919 918
+#define MU_DEC918 917
+#define MU_DEC917 916
+#define MU_DEC916 915
+#define MU_DEC915 914
+#define MU_DEC914 913
+#define MU_DEC913 912
+#define MU_DEC912 911
+#define MU_DEC911 910
+#define MU_DEC910 909
+#define MU_DEC909 908
+#define MU_DEC908 907
+#define MU_DEC907 906
+#define MU_DEC906 905
+#define MU_DEC905 904
+#define MU_DEC904 903
+#define MU_DEC903 902
+#define MU_DEC902 901
+#define MU_DEC901 900
+#define MU_DEC900 899
+#define MU_DEC899 898
+#define MU_DEC898 897
+#define MU_DEC897 896
+#define MU_DEC896 895
+#define MU_DEC895 894
+#define MU_DEC894 893
+#define MU_DEC893 892
+#define MU_DEC892 891
+#define MU_DEC891 890
+#define MU_DEC890 889
+#define MU_DEC889 888
+#define MU_DEC888 887
+#define MU_DEC887 886
+#define MU_DEC886 885
+#define MU_DEC885 884
+#define MU_DEC884 883
+#define MU_DEC883 882
+#define MU_DEC882 881
+#define MU_DEC881 880
+#define MU_DEC880 879
+#define MU_DEC879 878
+#define MU_DEC878 877
+#define MU_DEC877 876
+#define MU_DEC876 875
+#define MU_DEC875 874
+#define MU_DEC874 873
+#define MU_DEC873 872
+#define MU_DEC872 871
+#define MU_DEC871 870
+#define MU_DEC870 869
+#define MU_DEC869 868
+#define MU_DEC868 867
+#define MU_DEC867 866
+#define MU_DEC866 865
+#define MU_DEC865 864
+#define MU_DEC864 863
+#define MU_DEC863 862
+#define MU_DEC862 861
+#define MU_DEC861 860
+#define MU_DEC860 859
+#define MU_DEC859 858
+#define MU_DEC858 857
+#define MU_DEC857 856
+#define MU_DEC856 855
+#define MU_DEC855 854
+#define MU_DEC854 853
+#define MU_DEC853 852
+#define MU_DEC852 851
+#define MU_DEC851 850
+#define MU_DEC850 849
+#define MU_DEC849 848
+#define MU_DEC848 847
+#define MU_DEC847 846
+#define MU_DEC846 845
+#define MU_DEC845 844
+#define MU_DEC844 843
+#define MU_DEC843 842
+#define MU_DEC842 841
+#define MU_DEC841 840
+#define MU_DEC840 839
+#define MU_DEC839 838
+#define MU_DEC838 837
+#define MU_DEC837 836
+#define MU_DEC836 835
+#define MU_DEC835 834
+#define MU_DEC834 833
+#define MU_DEC833 832
+#define MU_DEC832 831
+#define MU_DEC831 830
+#define MU_DEC830 829
+#define MU_DEC829 828
+#define MU_DEC828 827
+#define MU_DEC827 826
+#define MU_DEC826 825
+#define MU_DEC825 824
+#define MU_DEC824 823
+#define MU_DEC823 822
+#define MU_DEC822 821
+#define MU_DEC821 820
+#define MU_DEC820 819
+#define MU_DEC819 818
+#define MU_DEC818 817
+#define MU_DEC817 816
+#define MU_DEC816 815
+#define MU_DEC815 814
+#define MU_DEC814 813
+#define MU_DEC813 812
+#define MU_DEC812 811
+#define MU_DEC811 810
+#define MU_DEC810 809
+#define MU_DEC809 808
+#define MU_DEC808 807
+#define MU_DEC807 806
+#define MU_DEC806 805
+#define MU_DEC805 804
+#define MU_DEC804 803
+#define MU_DEC803 802
+#define MU_DEC802 801
+#define MU_DEC801 800
+#define MU_DEC800 799
+#define MU_DEC799 798
+#define MU_DEC798 797
+#define MU_DEC797 796
+#define MU_DEC796 795
+#define MU_DEC795 794
+#define MU_DEC794 793
+#define MU_DEC793 792
+#define MU_DEC792 791
+#define MU_DEC791 790
+#define MU_DEC790 789
+#define MU_DEC789 788
+#define MU_DEC788 787
+#define MU_DEC787 786
+#define MU_DEC786 785
+#define MU_DEC785 784
+#define MU_DEC784 783
+#define MU_DEC783 782
+#define MU_DEC782 781
+#define MU_DEC781 780
+#define MU_DEC780 779
+#define MU_DEC779 778
+#define MU_DEC778 777
+#define MU_DEC777 776
+#define MU_DEC776 775
+#define MU_DEC775 774
+#define MU_DEC774 773
+#define MU_DEC773 772
+#define MU_DEC772 771
+#define MU_DEC771 770
+#define MU_DEC770 769
+#define MU_DEC769 768
+#define MU_DEC768 767
+#define MU_DEC767 766
+#define MU_DEC766 765
+#define MU_DEC765 764
+#define MU_DEC764 763
+#define MU_DEC763 762
+#define MU_DEC762 761
+#define MU_DEC761 760
+#define MU_DEC760 759
+#define MU_DEC759 758
+#define MU_DEC758 757
+#define MU_DEC757 756
+#define MU_DEC756 755
+#define MU_DEC755 754
+#define MU_DEC754 753
+#define MU_DEC753 752
+#define MU_DEC752 751
+#define MU_DEC751 750
+#define MU_DEC750 749
+#define MU_DEC749 748
+#define MU_DEC748 747
+#define MU_DEC747 746
+#define MU_DEC746 745
+#define MU_DEC745 744
+#define MU_DEC744 743
+#define MU_DEC743 742
+#define MU_DEC742 741
+#define MU_DEC741 740
+#define MU_DEC740 739
+#define MU_DEC739 738
+#define MU_DEC738 737
+#define MU_DEC737 736
+#define MU_DEC736 735
+#define MU_DEC735 734
+#define MU_DEC734 733
+#define MU_DEC733 732
+#define MU_DEC732 731
+#define MU_DEC731 730
+#define MU_DEC730 729
+#define MU_DEC729 728
+#define MU_DEC728 727
+#define MU_DEC727 726
+#define MU_DEC726 725
+#define MU_DEC725 724
+#define MU_DEC724 723
+#define MU_DEC723 722
+#define MU_DEC722 721
+#define MU_DEC721 720
+#define MU_DEC720 719
+#define MU_DEC719 718
+#define MU_DEC718 717
+#define MU_DEC717 716
+#define MU_DEC716 715
+#define MU_DEC715 714
+#define MU_DEC714 713
+#define MU_DEC713 712
+#define MU_DEC712 711
+#define MU_DEC711 710
+#define MU_DEC710 709
+#define MU_DEC709 708
+#define MU_DEC708 707
+#define MU_DEC707 706
+#define MU_DEC706 705
+#define MU_DEC705 704
+#define MU_DEC704 703
+#define MU_DEC703 702
+#define MU_DEC702 701
+#define MU_DEC701 700
+#define MU_DEC700 699
+#define MU_DEC699 698
+#define MU_DEC698 697
+#define MU_DEC697 696
+#define MU_DEC696 695
+#define MU_DEC695 694
+#define MU_DEC694 693
+#define MU_DEC693 692
+#define MU_DEC692 691
+#define MU_DEC691 690
+#define MU_DEC690 689
+#define MU_DEC689 688
+#define MU_DEC688 687
+#define MU_DEC687 686
+#define MU_DEC686 685
+#define MU_DEC685 684
+#define MU_DEC684 683
+#define MU_DEC683 682
+#define MU_DEC682 681
+#define MU_DEC681 680
+#define MU_DEC680 679
+#define MU_DEC679 678
+#define MU_DEC678 677
+#define MU_DEC677 676
+#define MU_DEC676 675
+#define MU_DEC675 674
+#define MU_DEC674 673
+#define MU_DEC673 672
+#define MU_DEC672 671
+#define MU_DEC671 670
+#define MU_DEC670 669
+#define MU_DEC669 668
+#define MU_DEC668 667
+#define MU_DEC667 666
+#define MU_DEC666 665
+#define MU_DEC665 664
+#define MU_DEC664 663
+#define MU_DEC663 662
+#define MU_DEC662 661
+#define MU_DEC661 660
+#define MU_DEC660 659
+#define MU_DEC659 658
+#define MU_DEC658 657
+#define MU_DEC657 656
+#define MU_DEC656 655
+#define MU_DEC655 654
+#define MU_DEC654 653
+#define MU_DEC653 652
+#define MU_DEC652 651
+#define MU_DEC651 650
+#define MU_DEC650 649
+#define MU_DEC649 648
+#define MU_DEC648 647
+#define MU_DEC647 646
+#define MU_DEC646 645
+#define MU_DEC645 644
+#define MU_DEC644 643
+#define MU_DEC643 642
+#define MU_DEC642 641
+#define MU_DEC641 640
+#define MU_DEC640 639
+#define MU_DEC639 638
+#define MU_DEC638 637
+#define MU_DEC637 636
+#define MU_DEC636 635
+#define MU_DEC635 634
+#define MU_DEC634 633
+#define MU_DEC633 632
+#define MU_DEC632 631
+#define MU_DEC631 630
+#define MU_DEC630 629
+#define MU_DEC629 628
+#define MU_DEC628 627
+#define MU_DEC627 626
+#define MU_DEC626 625
+#define MU_DEC625 624
+#define MU_DEC624 623
+#define MU_DEC623 622
+#define MU_DEC622 621
+#define MU_DEC621 620
+#define MU_DEC620 619
+#define MU_DEC619 618
+#define MU_DEC618 617
+#define MU_DEC617 616
+#define MU_DEC616 615
+#define MU_DEC615 614
+#define MU_DEC614 613
+#define MU_DEC613 612
+#define MU_DEC612 611
+#define MU_DEC611 610
+#define MU_DEC610 609
+#define MU_DEC609 608
+#define MU_DEC608 607
+#define MU_DEC607 606
+#define MU_DEC606 605
+#define MU_DEC605 604
+#define MU_DEC604 603
+#define MU_DEC603 602
+#define MU_DEC602 601
+#define MU_DEC601 600
+#define MU_DEC600 599
+#define MU_DEC599 598
+#define MU_DEC598 597
+#define MU_DEC597 596
+#define MU_DEC596 595
+#define MU_DEC595 594
+#define MU_DEC594 593
+#define MU_DEC593 592
+#define MU_DEC592 591
+#define MU_DEC591 590
+#define MU_DEC590 589
+#define MU_DEC589 588
+#define MU_DEC588 587
+#define MU_DEC587 586
+#define MU_DEC586 585
+#define MU_DEC585 584
+#define MU_DEC584 583
+#define MU_DEC583 582
+#define MU_DEC582 581
+#define MU_DEC581 580
+#define MU_DEC580 579
+#define MU_DEC579 578
+#define MU_DEC578 577
+#define MU_DEC577 576
+#define MU_DEC576 575
+#define MU_DEC575 574
+#define MU_DEC574 573
+#define MU_DEC573 572
+#define MU_DEC572 571
+#define MU_DEC571 570
+#define MU_DEC570 569
+#define MU_DEC569 568
+#define MU_DEC568 567
+#define MU_DEC567 566
+#define MU_DEC566 565
+#define MU_DEC565 564
+#define MU_DEC564 563
+#define MU_DEC563 562
+#define MU_DEC562 561
+#define MU_DEC561 560
+#define MU_DEC560 559
+#define MU_DEC559 558
+#define MU_DEC558 557
+#define MU_DEC557 556
+#define MU_DEC556 555
+#define MU_DEC555 554
+#define MU_DEC554 553
+#define MU_DEC553 552
+#define MU_DEC552 551
+#define MU_DEC551 550
+#define MU_DEC550 549
+#define MU_DEC549 548
+#define MU_DEC548 547
+#define MU_DEC547 546
+#define MU_DEC546 545
+#define MU_DEC545 544
+#define MU_DEC544 543
+#define MU_DEC543 542
+#define MU_DEC542 541
+#define MU_DEC541 540
+#define MU_DEC540 539
+#define MU_DEC539 538
+#define MU_DEC538 537
+#define MU_DEC537 536
+#define MU_DEC536 535
+#define MU_DEC535 534
+#define MU_DEC534 533
+#define MU_DEC533 532
+#define MU_DEC532 531
+#define MU_DEC531 530
+#define MU_DEC530 529
+#define MU_DEC529 528
+#define MU_DEC528 527
+#define MU_DEC527 526
+#define MU_DEC526 525
+#define MU_DEC525 524
+#define MU_DEC524 523
+#define MU_DEC523 522
+#define MU_DEC522 521
+#define MU_DEC521 520
+#define MU_DEC520 519
+#define MU_DEC519 518
+#define MU_DEC518 517
+#define MU_DEC517 516
+#define MU_DEC516 515
+#define MU_DEC515 514
+#define MU_DEC514 513
+#define MU_DEC513 512
+#define MU_DEC512 511
+#define MU_DEC511 510
+#define MU_DEC510 509
+#define MU_DEC509 508
+#define MU_DEC508 507
+#define MU_DEC507 506
+#define MU_DEC506 505
+#define MU_DEC505 504
+#define MU_DEC504 503
+#define MU_DEC503 502
+#define MU_DEC502 501
+#define MU_DEC501 500
+#define MU_DEC500 499
+#define MU_DEC499 498
+#define MU_DEC498 497
+#define MU_DEC497 496
+#define MU_DEC496 495
+#define MU_DEC495 494
+#define MU_DEC494 493
+#define MU_DEC493 492
+#define MU_DEC492 491
+#define MU_DEC491 490
+#define MU_DEC490 489
+#define MU_DEC489 488
+#define MU_DEC488 487
+#define MU_DEC487 486
+#define MU_DEC486 485
+#define MU_DEC485 484
+#define MU_DEC484 483
+#define MU_DEC483 482
+#define MU_DEC482 481
+#define MU_DEC481 480
+#define MU_DEC480 479
+#define MU_DEC479 478
+#define MU_DEC478 477
+#define MU_DEC477 476
+#define MU_DEC476 475
+#define MU_DEC475 474
+#define MU_DEC474 473
+#define MU_DEC473 472
+#define MU_DEC472 471
+#define MU_DEC471 470
+#define MU_DEC470 469
+#define MU_DEC469 468
+#define MU_DEC468 467
+#define MU_DEC467 466
+#define MU_DEC466 465
+#define MU_DEC465 464
+#define MU_DEC464 463
+#define MU_DEC463 462
+#define MU_DEC462 461
+#define MU_DEC461 460
+#define MU_DEC460 459
+#define MU_DEC459 458
+#define MU_DEC458 457
+#define MU_DEC457 456
+#define MU_DEC456 455
+#define MU_DEC455 454
+#define MU_DEC454 453
+#define MU_DEC453 452
+#define MU_DEC452 451
+#define MU_DEC451 450
+#define MU_DEC450 449
+#define MU_DEC449 448
+#define MU_DEC448 447
+#define MU_DEC447 446
+#define MU_DEC446 445
+#define MU_DEC445 444
+#define MU_DEC444 443
+#define MU_DEC443 442
+#define MU_DEC442 441
+#define MU_DEC441 440
+#define MU_DEC440 439
+#define MU_DEC439 438
+#define MU_DEC438 437
+#define MU_DEC437 436
+#define MU_DEC436 435
+#define MU_DEC435 434
+#define MU_DEC434 433
+#define MU_DEC433 432
+#define MU_DEC432 431
+#define MU_DEC431 430
+#define MU_DEC430 429
+#define MU_DEC429 428
+#define MU_DEC428 427
+#define MU_DEC427 426
+#define MU_DEC426 425
+#define MU_DEC425 424
+#define MU_DEC424 423
+#define MU_DEC423 422
+#define MU_DEC422 421
+#define MU_DEC421 420
+#define MU_DEC420 419
+#define MU_DEC419 418
+#define MU_DEC418 417
+#define MU_DEC417 416
+#define MU_DEC416 415
+#define MU_DEC415 414
+#define MU_DEC414 413
+#define MU_DEC413 412
+#define MU_DEC412 411
+#define MU_DEC411 410
+#define MU_DEC410 409
+#define MU_DEC409 408
+#define MU_DEC408 407
+#define MU_DEC407 406
+#define MU_DEC406 405
+#define MU_DEC405 404
+#define MU_DEC404 403
+#define MU_DEC403 402
+#define MU_DEC402 401
+#define MU_DEC401 400
+#define MU_DEC400 399
+#define MU_DEC399 398
+#define MU_DEC398 397
+#define MU_DEC397 396
+#define MU_DEC396 395
+#define MU_DEC395 394
+#define MU_DEC394 393
+#define MU_DEC393 392
+#define MU_DEC392 391
+#define MU_DEC391 390
+#define MU_DEC390 389
+#define MU_DEC389 388
+#define MU_DEC388 387
+#define MU_DEC387 386
+#define MU_DEC386 385
+#define MU_DEC385 384
+#define MU_DEC384 383
+#define MU_DEC383 382
+#define MU_DEC382 381
+#define MU_DEC381 380
+#define MU_DEC380 379
+#define MU_DEC379 378
+#define MU_DEC378 377
+#define MU_DEC377 376
+#define MU_DEC376 375
+#define MU_DEC375 374
+#define MU_DEC374 373
+#define MU_DEC373 372
+#define MU_DEC372 371
+#define MU_DEC371 370
+#define MU_DEC370 369
+#define MU_DEC369 368
+#define MU_DEC368 367
+#define MU_DEC367 366
+#define MU_DEC366 365
+#define MU_DEC365 364
+#define MU_DEC364 363
+#define MU_DEC363 362
+#define MU_DEC362 361
+#define MU_DEC361 360
+#define MU_DEC360 359
+#define MU_DEC359 358
+#define MU_DEC358 357
+#define MU_DEC357 356
+#define MU_DEC356 355
+#define MU_DEC355 354
+#define MU_DEC354 353
+#define MU_DEC353 352
+#define MU_DEC352 351
+#define MU_DEC351 350
+#define MU_DEC350 349
+#define MU_DEC349 348
+#define MU_DEC348 347
+#define MU_DEC347 346
+#define MU_DEC346 345
+#define MU_DEC345 344
+#define MU_DEC344 343
+#define MU_DEC343 342
+#define MU_DEC342 341
+#define MU_DEC341 340
+#define MU_DEC340 339
+#define MU_DEC339 338
+#define MU_DEC338 337
+#define MU_DEC337 336
+#define MU_DEC336 335
+#define MU_DEC335 334
+#define MU_DEC334 333
+#define MU_DEC333 332
+#define MU_DEC332 331
+#define MU_DEC331 330
+#define MU_DEC330 329
+#define MU_DEC329 328
+#define MU_DEC328 327
+#define MU_DEC327 326
+#define MU_DEC326 325
+#define MU_DEC325 324
+#define MU_DEC324 323
+#define MU_DEC323 322
+#define MU_DEC322 321
+#define MU_DEC321 320
+#define MU_DEC320 319
+#define MU_DEC319 318
+#define MU_DEC318 317
+#define MU_DEC317 316
+#define MU_DEC316 315
+#define MU_DEC315 314
+#define MU_DEC314 313
+#define MU_DEC313 312
+#define MU_DEC312 311
+#define MU_DEC311 310
+#define MU_DEC310 309
+#define MU_DEC309 308
+#define MU_DEC308 307
+#define MU_DEC307 306
+#define MU_DEC306 305
+#define MU_DEC305 304
+#define MU_DEC304 303
+#define MU_DEC303 302
+#define MU_DEC302 301
+#define MU_DEC301 300
+#define MU_DEC300 299
+#define MU_DEC299 298
+#define MU_DEC298 297
+#define MU_DEC297 296
+#define MU_DEC296 295
+#define MU_DEC295 294
+#define MU_DEC294 293
+#define MU_DEC293 292
+#define MU_DEC292 291
+#define MU_DEC291 290
+#define MU_DEC290 289
+#define MU_DEC289 288
+#define MU_DEC288 287
+#define MU_DEC287 286
+#define MU_DEC286 285
+#define MU_DEC285 284
+#define MU_DEC284 283
+#define MU_DEC283 282
+#define MU_DEC282 281
+#define MU_DEC281 280
+#define MU_DEC280 279
+#define MU_DEC279 278
+#define MU_DEC278 277
+#define MU_DEC277 276
+#define MU_DEC276 275
+#define MU_DEC275 274
+#define MU_DEC274 273
+#define MU_DEC273 272
+#define MU_DEC272 271
+#define MU_DEC271 270
+#define MU_DEC270 269
+#define MU_DEC269 268
+#define MU_DEC268 267
+#define MU_DEC267 266
+#define MU_DEC266 265
+#define MU_DEC265 264
+#define MU_DEC264 263
+#define MU_DEC263 262
+#define MU_DEC262 261
+#define MU_DEC261 260
+#define MU_DEC260 259
+#define MU_DEC259 258
+#define MU_DEC258 257
+#define MU_DEC257 256
+#define MU_DEC256 255
+#define MU_DEC255 254
+#define MU_DEC254 253
+#define MU_DEC253 252
+#define MU_DEC252 251
+#define MU_DEC251 250
+#define MU_DEC250 249
+#define MU_DEC249 248
+#define MU_DEC248 247
+#define MU_DEC247 246
+#define MU_DEC246 245
+#define MU_DEC245 244
+#define MU_DEC244 243
+#define MU_DEC243 242
+#define MU_DEC242 241
+#define MU_DEC241 240
+#define MU_DEC240 239
+#define MU_DEC239 238
+#define MU_DEC238 237
+#define MU_DEC237 236
+#define MU_DEC236 235
+#define MU_DEC235 234
+#define MU_DEC234 233
+#define MU_DEC233 232
+#define MU_DEC232 231
+#define MU_DEC231 230
+#define MU_DEC230 229
+#define MU_DEC229 228
+#define MU_DEC228 227
+#define MU_DEC227 226
+#define MU_DEC226 225
+#define MU_DEC225 224
+#define MU_DEC224 223
+#define MU_DEC223 222
+#define MU_DEC222 221
+#define MU_DEC221 220
+#define MU_DEC220 219
+#define MU_DEC219 218
+#define MU_DEC218 217
+#define MU_DEC217 216
+#define MU_DEC216 215
+#define MU_DEC215 214
+#define MU_DEC214 213
+#define MU_DEC213 212
+#define MU_DEC212 211
+#define MU_DEC211 210
+#define MU_DEC210 209
+#define MU_DEC209 208
+#define MU_DEC208 207
+#define MU_DEC207 206
+#define MU_DEC206 205
+#define MU_DEC205 204
+#define MU_DEC204 203
+#define MU_DEC203 202
+#define MU_DEC202 201
+#define MU_DEC201 200
+#define MU_DEC200 199
+#define MU_DEC199 198
+#define MU_DEC198 197
+#define MU_DEC197 196
+#define MU_DEC196 195
+#define MU_DEC195 194
+#define MU_DEC194 193
+#define MU_DEC193 192
+#define MU_DEC192 191
+#define MU_DEC191 190
+#define MU_DEC190 189
+#define MU_DEC189 188
+#define MU_DEC188 187
+#define MU_DEC187 186
+#define MU_DEC186 185
+#define MU_DEC185 184
+#define MU_DEC184 183
+#define MU_DEC183 182
+#define MU_DEC182 181
+#define MU_DEC181 180
+#define MU_DEC180 179
+#define MU_DEC179 178
+#define MU_DEC178 177
+#define MU_DEC177 176
+#define MU_DEC176 175
+#define MU_DEC175 174
+#define MU_DEC174 173
+#define MU_DEC173 172
+#define MU_DEC172 171
+#define MU_DEC171 170
+#define MU_DEC170 169
+#define MU_DEC169 168
+#define MU_DEC168 167
+#define MU_DEC167 166
+#define MU_DEC166 165
+#define MU_DEC165 164
+#define MU_DEC164 163
+#define MU_DEC163 162
+#define MU_DEC162 161
+#define MU_DEC161 160
+#define MU_DEC160 159
+#define MU_DEC159 158
+#define MU_DEC158 157
+#define MU_DEC157 156
+#define MU_DEC156 155
+#define MU_DEC155 154
+#define MU_DEC154 153
+#define MU_DEC153 152
+#define MU_DEC152 151
+#define MU_DEC151 150
+#define MU_DEC150 149
+#define MU_DEC149 148
+#define MU_DEC148 147
+#define MU_DEC147 146
+#define MU_DEC146 145
+#define MU_DEC145 144
+#define MU_DEC144 143
+#define MU_DEC143 142
+#define MU_DEC142 141
+#define MU_DEC141 140
+#define MU_DEC140 139
+#define MU_DEC139 138
+#define MU_DEC138 137
+#define MU_DEC137 136
+#define MU_DEC136 135
+#define MU_DEC135 134
+#define MU_DEC134 133
+#define MU_DEC133 132
+#define MU_DEC132 131
+#define MU_DEC131 130
+#define MU_DEC130 129
+#define MU_DEC129 128
+#define MU_DEC128 127
+#define MU_DEC127 126
+#define MU_DEC126 125
+#define MU_DEC125 124
+#define MU_DEC124 123
+#define MU_DEC123 122
+#define MU_DEC122 121
+#define MU_DEC121 120
+#define MU_DEC120 119
+#define MU_DEC119 118
+#define MU_DEC118 117
+#define MU_DEC117 116
+#define MU_DEC116 115
+#define MU_DEC115 114
+#define MU_DEC114 113
+#define MU_DEC113 112
+#define MU_DEC112 111
+#define MU_DEC111 110
+#define MU_DEC110 109
+#define MU_DEC109 108
+#define MU_DEC108 107
+#define MU_DEC107 106
+#define MU_DEC106 105
+#define MU_DEC105 104
+#define MU_DEC104 103
+#define MU_DEC103 102
+#define MU_DEC102 101
+#define MU_DEC101 100
+#define MU_DEC100 99
+#define MU_DEC99 98
+#define MU_DEC98 97
+#define MU_DEC97 96
+#define MU_DEC96 95
+#define MU_DEC95 94
+#define MU_DEC94 93
+#define MU_DEC93 92
+#define MU_DEC92 91
+#define MU_DEC91 90
+#define MU_DEC90 89
+#define MU_DEC89 88
+#define MU_DEC88 87
+#define MU_DEC87 86
+#define MU_DEC86 85
+#define MU_DEC85 84
+#define MU_DEC84 83
+#define MU_DEC83 82
+#define MU_DEC82 81
+#define MU_DEC81 80
+#define MU_DEC80 79
+#define MU_DEC79 78
+#define MU_DEC78 77
+#define MU_DEC77 76
+#define MU_DEC76 75
+#define MU_DEC75 74
+#define MU_DEC74 73
+#define MU_DEC73 72
+#define MU_DEC72 71
+#define MU_DEC71 70
+#define MU_DEC70 69
+#define MU_DEC69 68
+#define MU_DEC68 67
+#define MU_DEC67 66
+#define MU_DEC66 65
+#define MU_DEC65 64
+#define MU_DEC64 63
+#define MU_DEC63 62
+#define MU_DEC62 61
+#define MU_DEC61 60
+#define MU_DEC60 59
+#define MU_DEC59 58
+#define MU_DEC58 57
+#define MU_DEC57 56
+#define MU_DEC56 55
+#define MU_DEC55 54
+#define MU_DEC54 53
+#define MU_DEC53 52
+#define MU_DEC52 51
+#define MU_DEC51 50
+#define MU_DEC50 49
+#define MU_DEC49 48
+#define MU_DEC48 47
+#define MU_DEC47 46
+#define MU_DEC46 45
+#define MU_DEC45 44
+#define MU_DEC44 43
+#define MU_DEC43 42
+#define MU_DEC42 41
+#define MU_DEC41 40
+#define MU_DEC40 39
+#define MU_DEC39 38
+#define MU_DEC38 37
+#define MU_DEC37 36
+#define MU_DEC36 35
+#define MU_DEC35 34
+#define MU_DEC34 33
+#define MU_DEC33 32
+#define MU_DEC32 31
+#define MU_DEC31 30
+#define MU_DEC30 29
+#define MU_DEC29 28
+#define MU_DEC28 27
+#define MU_DEC27 26
+#define MU_DEC26 25
+#define MU_DEC25 24
+#define MU_DEC24 23
+#define MU_DEC23 22
+#define MU_DEC22 21
+#define MU_DEC21 20
+#define MU_DEC20 19
+#define MU_DEC19 18
+#define MU_DEC18 17
+#define MU_DEC17 16
+#define MU_DEC16 15
+#define MU_DEC15 14
+#define MU_DEC14 13
+#define MU_DEC13 12
+#define MU_DEC12 11
+#define MU_DEC11 10
+#define MU_DEC10 9
+#define MU_DEC9 8
+#define MU_DEC8 7
+#define MU_DEC7 6
+#define MU_DEC6 5
+#define MU_DEC5 4
+#define MU_DEC4 3
+#define MU_DEC3 2
+#define MU_DEC2 1
+#define MU_DEC1 0
+
+#define MU_INC(x) MU_C2(MU_INC,x)
+#define MU_INC2048 2049
+#define MU_INC2047 2048
+#define MU_INC2046 2047
+#define MU_INC2045 2046
+#define MU_INC2044 2045
+#define MU_INC2043 2044
+#define MU_INC2042 2043
+#define MU_INC2041 2042
+#define MU_INC2040 2041
+#define MU_INC2039 2040
+#define MU_INC2038 2039
+#define MU_INC2037 2038
+#define MU_INC2036 2037
+#define MU_INC2035 2036
+#define MU_INC2034 2035
+#define MU_INC2033 2034
+#define MU_INC2032 2033
+#define MU_INC2031 2032
+#define MU_INC2030 2031
+#define MU_INC2029 2030
+#define MU_INC2028 2029
+#define MU_INC2027 2028
+#define MU_INC2026 2027
+#define MU_INC2025 2026
+#define MU_INC2024 2025
+#define MU_INC2023 2024
+#define MU_INC2022 2023
+#define MU_INC2021 2022
+#define MU_INC2020 2021
+#define MU_INC2019 2020
+#define MU_INC2018 2019
+#define MU_INC2017 2018
+#define MU_INC2016 2017
+#define MU_INC2015 2016
+#define MU_INC2014 2015
+#define MU_INC2013 2014
+#define MU_INC2012 2013
+#define MU_INC2011 2012
+#define MU_INC2010 2011
+#define MU_INC2009 2010
+#define MU_INC2008 2009
+#define MU_INC2007 2008
+#define MU_INC2006 2007
+#define MU_INC2005 2006
+#define MU_INC2004 2005
+#define MU_INC2003 2004
+#define MU_INC2002 2003
+#define MU_INC2001 2002
+#define MU_INC2000 2001
+#define MU_INC1999 2000
+#define MU_INC1998 1999
+#define MU_INC1997 1998
+#define MU_INC1996 1997
+#define MU_INC1995 1996
+#define MU_INC1994 1995
+#define MU_INC1993 1994
+#define MU_INC1992 1993
+#define MU_INC1991 1992
+#define MU_INC1990 1991
+#define MU_INC1989 1990
+#define MU_INC1988 1989
+#define MU_INC1987 1988
+#define MU_INC1986 1987
+#define MU_INC1985 1986
+#define MU_INC1984 1985
+#define MU_INC1983 1984
+#define MU_INC1982 1983
+#define MU_INC1981 1982
+#define MU_INC1980 1981
+#define MU_INC1979 1980
+#define MU_INC1978 1979
+#define MU_INC1977 1978
+#define MU_INC1976 1977
+#define MU_INC1975 1976
+#define MU_INC1974 1975
+#define MU_INC1973 1974
+#define MU_INC1972 1973
+#define MU_INC1971 1972
+#define MU_INC1970 1971
+#define MU_INC1969 1970
+#define MU_INC1968 1969
+#define MU_INC1967 1968
+#define MU_INC1966 1967
+#define MU_INC1965 1966
+#define MU_INC1964 1965
+#define MU_INC1963 1964
+#define MU_INC1962 1963
+#define MU_INC1961 1962
+#define MU_INC1960 1961
+#define MU_INC1959 1960
+#define MU_INC1958 1959
+#define MU_INC1957 1958
+#define MU_INC1956 1957
+#define MU_INC1955 1956
+#define MU_INC1954 1955
+#define MU_INC1953 1954
+#define MU_INC1952 1953
+#define MU_INC1951 1952
+#define MU_INC1950 1951
+#define MU_INC1949 1950
+#define MU_INC1948 1949
+#define MU_INC1947 1948
+#define MU_INC1946 1947
+#define MU_INC1945 1946
+#define MU_INC1944 1945
+#define MU_INC1943 1944
+#define MU_INC1942 1943
+#define MU_INC1941 1942
+#define MU_INC1940 1941
+#define MU_INC1939 1940
+#define MU_INC1938 1939
+#define MU_INC1937 1938
+#define MU_INC1936 1937
+#define MU_INC1935 1936
+#define MU_INC1934 1935
+#define MU_INC1933 1934
+#define MU_INC1932 1933
+#define MU_INC1931 1932
+#define MU_INC1930 1931
+#define MU_INC1929 1930
+#define MU_INC1928 1929
+#define MU_INC1927 1928
+#define MU_INC1926 1927
+#define MU_INC1925 1926
+#define MU_INC1924 1925
+#define MU_INC1923 1924
+#define MU_INC1922 1923
+#define MU_INC1921 1922
+#define MU_INC1920 1921
+#define MU_INC1919 1920
+#define MU_INC1918 1919
+#define MU_INC1917 1918
+#define MU_INC1916 1917
+#define MU_INC1915 1916
+#define MU_INC1914 1915
+#define MU_INC1913 1914
+#define MU_INC1912 1913
+#define MU_INC1911 1912
+#define MU_INC1910 1911
+#define MU_INC1909 1910
+#define MU_INC1908 1909
+#define MU_INC1907 1908
+#define MU_INC1906 1907
+#define MU_INC1905 1906
+#define MU_INC1904 1905
+#define MU_INC1903 1904
+#define MU_INC1902 1903
+#define MU_INC1901 1902
+#define MU_INC1900 1901
+#define MU_INC1899 1900
+#define MU_INC1898 1899
+#define MU_INC1897 1898
+#define MU_INC1896 1897
+#define MU_INC1895 1896
+#define MU_INC1894 1895
+#define MU_INC1893 1894
+#define MU_INC1892 1893
+#define MU_INC1891 1892
+#define MU_INC1890 1891
+#define MU_INC1889 1890
+#define MU_INC1888 1889
+#define MU_INC1887 1888
+#define MU_INC1886 1887
+#define MU_INC1885 1886
+#define MU_INC1884 1885
+#define MU_INC1883 1884
+#define MU_INC1882 1883
+#define MU_INC1881 1882
+#define MU_INC1880 1881
+#define MU_INC1879 1880
+#define MU_INC1878 1879
+#define MU_INC1877 1878
+#define MU_INC1876 1877
+#define MU_INC1875 1876
+#define MU_INC1874 1875
+#define MU_INC1873 1874
+#define MU_INC1872 1873
+#define MU_INC1871 1872
+#define MU_INC1870 1871
+#define MU_INC1869 1870
+#define MU_INC1868 1869
+#define MU_INC1867 1868
+#define MU_INC1866 1867
+#define MU_INC1865 1866
+#define MU_INC1864 1865
+#define MU_INC1863 1864
+#define MU_INC1862 1863
+#define MU_INC1861 1862
+#define MU_INC1860 1861
+#define MU_INC1859 1860
+#define MU_INC1858 1859
+#define MU_INC1857 1858
+#define MU_INC1856 1857
+#define MU_INC1855 1856
+#define MU_INC1854 1855
+#define MU_INC1853 1854
+#define MU_INC1852 1853
+#define MU_INC1851 1852
+#define MU_INC1850 1851
+#define MU_INC1849 1850
+#define MU_INC1848 1849
+#define MU_INC1847 1848
+#define MU_INC1846 1847
+#define MU_INC1845 1846
+#define MU_INC1844 1845
+#define MU_INC1843 1844
+#define MU_INC1842 1843
+#define MU_INC1841 1842
+#define MU_INC1840 1841
+#define MU_INC1839 1840
+#define MU_INC1838 1839
+#define MU_INC1837 1838
+#define MU_INC1836 1837
+#define MU_INC1835 1836
+#define MU_INC1834 1835
+#define MU_INC1833 1834
+#define MU_INC1832 1833
+#define MU_INC1831 1832
+#define MU_INC1830 1831
+#define MU_INC1829 1830
+#define MU_INC1828 1829
+#define MU_INC1827 1828
+#define MU_INC1826 1827
+#define MU_INC1825 1826
+#define MU_INC1824 1825
+#define MU_INC1823 1824
+#define MU_INC1822 1823
+#define MU_INC1821 1822
+#define MU_INC1820 1821
+#define MU_INC1819 1820
+#define MU_INC1818 1819
+#define MU_INC1817 1818
+#define MU_INC1816 1817
+#define MU_INC1815 1816
+#define MU_INC1814 1815
+#define MU_INC1813 1814
+#define MU_INC1812 1813
+#define MU_INC1811 1812
+#define MU_INC1810 1811
+#define MU_INC1809 1810
+#define MU_INC1808 1809
+#define MU_INC1807 1808
+#define MU_INC1806 1807
+#define MU_INC1805 1806
+#define MU_INC1804 1805
+#define MU_INC1803 1804
+#define MU_INC1802 1803
+#define MU_INC1801 1802
+#define MU_INC1800 1801
+#define MU_INC1799 1800
+#define MU_INC1798 1799
+#define MU_INC1797 1798
+#define MU_INC1796 1797
+#define MU_INC1795 1796
+#define MU_INC1794 1795
+#define MU_INC1793 1794
+#define MU_INC1792 1793
+#define MU_INC1791 1792
+#define MU_INC1790 1791
+#define MU_INC1789 1790
+#define MU_INC1788 1789
+#define MU_INC1787 1788
+#define MU_INC1786 1787
+#define MU_INC1785 1786
+#define MU_INC1784 1785
+#define MU_INC1783 1784
+#define MU_INC1782 1783
+#define MU_INC1781 1782
+#define MU_INC1780 1781
+#define MU_INC1779 1780
+#define MU_INC1778 1779
+#define MU_INC1777 1778
+#define MU_INC1776 1777
+#define MU_INC1775 1776
+#define MU_INC1774 1775
+#define MU_INC1773 1774
+#define MU_INC1772 1773
+#define MU_INC1771 1772
+#define MU_INC1770 1771
+#define MU_INC1769 1770
+#define MU_INC1768 1769
+#define MU_INC1767 1768
+#define MU_INC1766 1767
+#define MU_INC1765 1766
+#define MU_INC1764 1765
+#define MU_INC1763 1764
+#define MU_INC1762 1763
+#define MU_INC1761 1762
+#define MU_INC1760 1761
+#define MU_INC1759 1760
+#define MU_INC1758 1759
+#define MU_INC1757 1758
+#define MU_INC1756 1757
+#define MU_INC1755 1756
+#define MU_INC1754 1755
+#define MU_INC1753 1754
+#define MU_INC1752 1753
+#define MU_INC1751 1752
+#define MU_INC1750 1751
+#define MU_INC1749 1750
+#define MU_INC1748 1749
+#define MU_INC1747 1748
+#define MU_INC1746 1747
+#define MU_INC1745 1746
+#define MU_INC1744 1745
+#define MU_INC1743 1744
+#define MU_INC1742 1743
+#define MU_INC1741 1742
+#define MU_INC1740 1741
+#define MU_INC1739 1740
+#define MU_INC1738 1739
+#define MU_INC1737 1738
+#define MU_INC1736 1737
+#define MU_INC1735 1736
+#define MU_INC1734 1735
+#define MU_INC1733 1734
+#define MU_INC1732 1733
+#define MU_INC1731 1732
+#define MU_INC1730 1731
+#define MU_INC1729 1730
+#define MU_INC1728 1729
+#define MU_INC1727 1728
+#define MU_INC1726 1727
+#define MU_INC1725 1726
+#define MU_INC1724 1725
+#define MU_INC1723 1724
+#define MU_INC1722 1723
+#define MU_INC1721 1722
+#define MU_INC1720 1721
+#define MU_INC1719 1720
+#define MU_INC1718 1719
+#define MU_INC1717 1718
+#define MU_INC1716 1717
+#define MU_INC1715 1716
+#define MU_INC1714 1715
+#define MU_INC1713 1714
+#define MU_INC1712 1713
+#define MU_INC1711 1712
+#define MU_INC1710 1711
+#define MU_INC1709 1710
+#define MU_INC1708 1709
+#define MU_INC1707 1708
+#define MU_INC1706 1707
+#define MU_INC1705 1706
+#define MU_INC1704 1705
+#define MU_INC1703 1704
+#define MU_INC1702 1703
+#define MU_INC1701 1702
+#define MU_INC1700 1701
+#define MU_INC1699 1700
+#define MU_INC1698 1699
+#define MU_INC1697 1698
+#define MU_INC1696 1697
+#define MU_INC1695 1696
+#define MU_INC1694 1695
+#define MU_INC1693 1694
+#define MU_INC1692 1693
+#define MU_INC1691 1692
+#define MU_INC1690 1691
+#define MU_INC1689 1690
+#define MU_INC1688 1689
+#define MU_INC1687 1688
+#define MU_INC1686 1687
+#define MU_INC1685 1686
+#define MU_INC1684 1685
+#define MU_INC1683 1684
+#define MU_INC1682 1683
+#define MU_INC1681 1682
+#define MU_INC1680 1681
+#define MU_INC1679 1680
+#define MU_INC1678 1679
+#define MU_INC1677 1678
+#define MU_INC1676 1677
+#define MU_INC1675 1676
+#define MU_INC1674 1675
+#define MU_INC1673 1674
+#define MU_INC1672 1673
+#define MU_INC1671 1672
+#define MU_INC1670 1671
+#define MU_INC1669 1670
+#define MU_INC1668 1669
+#define MU_INC1667 1668
+#define MU_INC1666 1667
+#define MU_INC1665 1666
+#define MU_INC1664 1665
+#define MU_INC1663 1664
+#define MU_INC1662 1663
+#define MU_INC1661 1662
+#define MU_INC1660 1661
+#define MU_INC1659 1660
+#define MU_INC1658 1659
+#define MU_INC1657 1658
+#define MU_INC1656 1657
+#define MU_INC1655 1656
+#define MU_INC1654 1655
+#define MU_INC1653 1654
+#define MU_INC1652 1653
+#define MU_INC1651 1652
+#define MU_INC1650 1651
+#define MU_INC1649 1650
+#define MU_INC1648 1649
+#define MU_INC1647 1648
+#define MU_INC1646 1647
+#define MU_INC1645 1646
+#define MU_INC1644 1645
+#define MU_INC1643 1644
+#define MU_INC1642 1643
+#define MU_INC1641 1642
+#define MU_INC1640 1641
+#define MU_INC1639 1640
+#define MU_INC1638 1639
+#define MU_INC1637 1638
+#define MU_INC1636 1637
+#define MU_INC1635 1636
+#define MU_INC1634 1635
+#define MU_INC1633 1634
+#define MU_INC1632 1633
+#define MU_INC1631 1632
+#define MU_INC1630 1631
+#define MU_INC1629 1630
+#define MU_INC1628 1629
+#define MU_INC1627 1628
+#define MU_INC1626 1627
+#define MU_INC1625 1626
+#define MU_INC1624 1625
+#define MU_INC1623 1624
+#define MU_INC1622 1623
+#define MU_INC1621 1622
+#define MU_INC1620 1621
+#define MU_INC1619 1620
+#define MU_INC1618 1619
+#define MU_INC1617 1618
+#define MU_INC1616 1617
+#define MU_INC1615 1616
+#define MU_INC1614 1615
+#define MU_INC1613 1614
+#define MU_INC1612 1613
+#define MU_INC1611 1612
+#define MU_INC1610 1611
+#define MU_INC1609 1610
+#define MU_INC1608 1609
+#define MU_INC1607 1608
+#define MU_INC1606 1607
+#define MU_INC1605 1606
+#define MU_INC1604 1605
+#define MU_INC1603 1604
+#define MU_INC1602 1603
+#define MU_INC1601 1602
+#define MU_INC1600 1601
+#define MU_INC1599 1600
+#define MU_INC1598 1599
+#define MU_INC1597 1598
+#define MU_INC1596 1597
+#define MU_INC1595 1596
+#define MU_INC1594 1595
+#define MU_INC1593 1594
+#define MU_INC1592 1593
+#define MU_INC1591 1592
+#define MU_INC1590 1591
+#define MU_INC1589 1590
+#define MU_INC1588 1589
+#define MU_INC1587 1588
+#define MU_INC1586 1587
+#define MU_INC1585 1586
+#define MU_INC1584 1585
+#define MU_INC1583 1584
+#define MU_INC1582 1583
+#define MU_INC1581 1582
+#define MU_INC1580 1581
+#define MU_INC1579 1580
+#define MU_INC1578 1579
+#define MU_INC1577 1578
+#define MU_INC1576 1577
+#define MU_INC1575 1576
+#define MU_INC1574 1575
+#define MU_INC1573 1574
+#define MU_INC1572 1573
+#define MU_INC1571 1572
+#define MU_INC1570 1571
+#define MU_INC1569 1570
+#define MU_INC1568 1569
+#define MU_INC1567 1568
+#define MU_INC1566 1567
+#define MU_INC1565 1566
+#define MU_INC1564 1565
+#define MU_INC1563 1564
+#define MU_INC1562 1563
+#define MU_INC1561 1562
+#define MU_INC1560 1561
+#define MU_INC1559 1560
+#define MU_INC1558 1559
+#define MU_INC1557 1558
+#define MU_INC1556 1557
+#define MU_INC1555 1556
+#define MU_INC1554 1555
+#define MU_INC1553 1554
+#define MU_INC1552 1553
+#define MU_INC1551 1552
+#define MU_INC1550 1551
+#define MU_INC1549 1550
+#define MU_INC1548 1549
+#define MU_INC1547 1548
+#define MU_INC1546 1547
+#define MU_INC1545 1546
+#define MU_INC1544 1545
+#define MU_INC1543 1544
+#define MU_INC1542 1543
+#define MU_INC1541 1542
+#define MU_INC1540 1541
+#define MU_INC1539 1540
+#define MU_INC1538 1539
+#define MU_INC1537 1538
+#define MU_INC1536 1537
+#define MU_INC1535 1536
+#define MU_INC1534 1535
+#define MU_INC1533 1534
+#define MU_INC1532 1533
+#define MU_INC1531 1532
+#define MU_INC1530 1531
+#define MU_INC1529 1530
+#define MU_INC1528 1529
+#define MU_INC1527 1528
+#define MU_INC1526 1527
+#define MU_INC1525 1526
+#define MU_INC1524 1525
+#define MU_INC1523 1524
+#define MU_INC1522 1523
+#define MU_INC1521 1522
+#define MU_INC1520 1521
+#define MU_INC1519 1520
+#define MU_INC1518 1519
+#define MU_INC1517 1518
+#define MU_INC1516 1517
+#define MU_INC1515 1516
+#define MU_INC1514 1515
+#define MU_INC1513 1514
+#define MU_INC1512 1513
+#define MU_INC1511 1512
+#define MU_INC1510 1511
+#define MU_INC1509 1510
+#define MU_INC1508 1509
+#define MU_INC1507 1508
+#define MU_INC1506 1507
+#define MU_INC1505 1506
+#define MU_INC1504 1505
+#define MU_INC1503 1504
+#define MU_INC1502 1503
+#define MU_INC1501 1502
+#define MU_INC1500 1501
+#define MU_INC1499 1500
+#define MU_INC1498 1499
+#define MU_INC1497 1498
+#define MU_INC1496 1497
+#define MU_INC1495 1496
+#define MU_INC1494 1495
+#define MU_INC1493 1494
+#define MU_INC1492 1493
+#define MU_INC1491 1492
+#define MU_INC1490 1491
+#define MU_INC1489 1490
+#define MU_INC1488 1489
+#define MU_INC1487 1488
+#define MU_INC1486 1487
+#define MU_INC1485 1486
+#define MU_INC1484 1485
+#define MU_INC1483 1484
+#define MU_INC1482 1483
+#define MU_INC1481 1482
+#define MU_INC1480 1481
+#define MU_INC1479 1480
+#define MU_INC1478 1479
+#define MU_INC1477 1478
+#define MU_INC1476 1477
+#define MU_INC1475 1476
+#define MU_INC1474 1475
+#define MU_INC1473 1474
+#define MU_INC1472 1473
+#define MU_INC1471 1472
+#define MU_INC1470 1471
+#define MU_INC1469 1470
+#define MU_INC1468 1469
+#define MU_INC1467 1468
+#define MU_INC1466 1467
+#define MU_INC1465 1466
+#define MU_INC1464 1465
+#define MU_INC1463 1464
+#define MU_INC1462 1463
+#define MU_INC1461 1462
+#define MU_INC1460 1461
+#define MU_INC1459 1460
+#define MU_INC1458 1459
+#define MU_INC1457 1458
+#define MU_INC1456 1457
+#define MU_INC1455 1456
+#define MU_INC1454 1455
+#define MU_INC1453 1454
+#define MU_INC1452 1453
+#define MU_INC1451 1452
+#define MU_INC1450 1451
+#define MU_INC1449 1450
+#define MU_INC1448 1449
+#define MU_INC1447 1448
+#define MU_INC1446 1447
+#define MU_INC1445 1446
+#define MU_INC1444 1445
+#define MU_INC1443 1444
+#define MU_INC1442 1443
+#define MU_INC1441 1442
+#define MU_INC1440 1441
+#define MU_INC1439 1440
+#define MU_INC1438 1439
+#define MU_INC1437 1438
+#define MU_INC1436 1437
+#define MU_INC1435 1436
+#define MU_INC1434 1435
+#define MU_INC1433 1434
+#define MU_INC1432 1433
+#define MU_INC1431 1432
+#define MU_INC1430 1431
+#define MU_INC1429 1430
+#define MU_INC1428 1429
+#define MU_INC1427 1428
+#define MU_INC1426 1427
+#define MU_INC1425 1426
+#define MU_INC1424 1425
+#define MU_INC1423 1424
+#define MU_INC1422 1423
+#define MU_INC1421 1422
+#define MU_INC1420 1421
+#define MU_INC1419 1420
+#define MU_INC1418 1419
+#define MU_INC1417 1418
+#define MU_INC1416 1417
+#define MU_INC1415 1416
+#define MU_INC1414 1415
+#define MU_INC1413 1414
+#define MU_INC1412 1413
+#define MU_INC1411 1412
+#define MU_INC1410 1411
+#define MU_INC1409 1410
+#define MU_INC1408 1409
+#define MU_INC1407 1408
+#define MU_INC1406 1407
+#define MU_INC1405 1406
+#define MU_INC1404 1405
+#define MU_INC1403 1404
+#define MU_INC1402 1403
+#define MU_INC1401 1402
+#define MU_INC1400 1401
+#define MU_INC1399 1400
+#define MU_INC1398 1399
+#define MU_INC1397 1398
+#define MU_INC1396 1397
+#define MU_INC1395 1396
+#define MU_INC1394 1395
+#define MU_INC1393 1394
+#define MU_INC1392 1393
+#define MU_INC1391 1392
+#define MU_INC1390 1391
+#define MU_INC1389 1390
+#define MU_INC1388 1389
+#define MU_INC1387 1388
+#define MU_INC1386 1387
+#define MU_INC1385 1386
+#define MU_INC1384 1385
+#define MU_INC1383 1384
+#define MU_INC1382 1383
+#define MU_INC1381 1382
+#define MU_INC1380 1381
+#define MU_INC1379 1380
+#define MU_INC1378 1379
+#define MU_INC1377 1378
+#define MU_INC1376 1377
+#define MU_INC1375 1376
+#define MU_INC1374 1375
+#define MU_INC1373 1374
+#define MU_INC1372 1373
+#define MU_INC1371 1372
+#define MU_INC1370 1371
+#define MU_INC1369 1370
+#define MU_INC1368 1369
+#define MU_INC1367 1368
+#define MU_INC1366 1367
+#define MU_INC1365 1366
+#define MU_INC1364 1365
+#define MU_INC1363 1364
+#define MU_INC1362 1363
+#define MU_INC1361 1362
+#define MU_INC1360 1361
+#define MU_INC1359 1360
+#define MU_INC1358 1359
+#define MU_INC1357 1358
+#define MU_INC1356 1357
+#define MU_INC1355 1356
+#define MU_INC1354 1355
+#define MU_INC1353 1354
+#define MU_INC1352 1353
+#define MU_INC1351 1352
+#define MU_INC1350 1351
+#define MU_INC1349 1350
+#define MU_INC1348 1349
+#define MU_INC1347 1348
+#define MU_INC1346 1347
+#define MU_INC1345 1346
+#define MU_INC1344 1345
+#define MU_INC1343 1344
+#define MU_INC1342 1343
+#define MU_INC1341 1342
+#define MU_INC1340 1341
+#define MU_INC1339 1340
+#define MU_INC1338 1339
+#define MU_INC1337 1338
+#define MU_INC1336 1337
+#define MU_INC1335 1336
+#define MU_INC1334 1335
+#define MU_INC1333 1334
+#define MU_INC1332 1333
+#define MU_INC1331 1332
+#define MU_INC1330 1331
+#define MU_INC1329 1330
+#define MU_INC1328 1329
+#define MU_INC1327 1328
+#define MU_INC1326 1327
+#define MU_INC1325 1326
+#define MU_INC1324 1325
+#define MU_INC1323 1324
+#define MU_INC1322 1323
+#define MU_INC1321 1322
+#define MU_INC1320 1321
+#define MU_INC1319 1320
+#define MU_INC1318 1319
+#define MU_INC1317 1318
+#define MU_INC1316 1317
+#define MU_INC1315 1316
+#define MU_INC1314 1315
+#define MU_INC1313 1314
+#define MU_INC1312 1313
+#define MU_INC1311 1312
+#define MU_INC1310 1311
+#define MU_INC1309 1310
+#define MU_INC1308 1309
+#define MU_INC1307 1308
+#define MU_INC1306 1307
+#define MU_INC1305 1306
+#define MU_INC1304 1305
+#define MU_INC1303 1304
+#define MU_INC1302 1303
+#define MU_INC1301 1302
+#define MU_INC1300 1301
+#define MU_INC1299 1300
+#define MU_INC1298 1299
+#define MU_INC1297 1298
+#define MU_INC1296 1297
+#define MU_INC1295 1296
+#define MU_INC1294 1295
+#define MU_INC1293 1294
+#define MU_INC1292 1293
+#define MU_INC1291 1292
+#define MU_INC1290 1291
+#define MU_INC1289 1290
+#define MU_INC1288 1289
+#define MU_INC1287 1288
+#define MU_INC1286 1287
+#define MU_INC1285 1286
+#define MU_INC1284 1285
+#define MU_INC1283 1284
+#define MU_INC1282 1283
+#define MU_INC1281 1282
+#define MU_INC1280 1281
+#define MU_INC1279 1280
+#define MU_INC1278 1279
+#define MU_INC1277 1278
+#define MU_INC1276 1277
+#define MU_INC1275 1276
+#define MU_INC1274 1275
+#define MU_INC1273 1274
+#define MU_INC1272 1273
+#define MU_INC1271 1272
+#define MU_INC1270 1271
+#define MU_INC1269 1270
+#define MU_INC1268 1269
+#define MU_INC1267 1268
+#define MU_INC1266 1267
+#define MU_INC1265 1266
+#define MU_INC1264 1265
+#define MU_INC1263 1264
+#define MU_INC1262 1263
+#define MU_INC1261 1262
+#define MU_INC1260 1261
+#define MU_INC1259 1260
+#define MU_INC1258 1259
+#define MU_INC1257 1258
+#define MU_INC1256 1257
+#define MU_INC1255 1256
+#define MU_INC1254 1255
+#define MU_INC1253 1254
+#define MU_INC1252 1253
+#define MU_INC1251 1252
+#define MU_INC1250 1251
+#define MU_INC1249 1250
+#define MU_INC1248 1249
+#define MU_INC1247 1248
+#define MU_INC1246 1247
+#define MU_INC1245 1246
+#define MU_INC1244 1245
+#define MU_INC1243 1244
+#define MU_INC1242 1243
+#define MU_INC1241 1242
+#define MU_INC1240 1241
+#define MU_INC1239 1240
+#define MU_INC1238 1239
+#define MU_INC1237 1238
+#define MU_INC1236 1237
+#define MU_INC1235 1236
+#define MU_INC1234 1235
+#define MU_INC1233 1234
+#define MU_INC1232 1233
+#define MU_INC1231 1232
+#define MU_INC1230 1231
+#define MU_INC1229 1230
+#define MU_INC1228 1229
+#define MU_INC1227 1228
+#define MU_INC1226 1227
+#define MU_INC1225 1226
+#define MU_INC1224 1225
+#define MU_INC1223 1224
+#define MU_INC1222 1223
+#define MU_INC1221 1222
+#define MU_INC1220 1221
+#define MU_INC1219 1220
+#define MU_INC1218 1219
+#define MU_INC1217 1218
+#define MU_INC1216 1217
+#define MU_INC1215 1216
+#define MU_INC1214 1215
+#define MU_INC1213 1214
+#define MU_INC1212 1213
+#define MU_INC1211 1212
+#define MU_INC1210 1211
+#define MU_INC1209 1210
+#define MU_INC1208 1209
+#define MU_INC1207 1208
+#define MU_INC1206 1207
+#define MU_INC1205 1206
+#define MU_INC1204 1205
+#define MU_INC1203 1204
+#define MU_INC1202 1203
+#define MU_INC1201 1202
+#define MU_INC1200 1201
+#define MU_INC1199 1200
+#define MU_INC1198 1199
+#define MU_INC1197 1198
+#define MU_INC1196 1197
+#define MU_INC1195 1196
+#define MU_INC1194 1195
+#define MU_INC1193 1194
+#define MU_INC1192 1193
+#define MU_INC1191 1192
+#define MU_INC1190 1191
+#define MU_INC1189 1190
+#define MU_INC1188 1189
+#define MU_INC1187 1188
+#define MU_INC1186 1187
+#define MU_INC1185 1186
+#define MU_INC1184 1185
+#define MU_INC1183 1184
+#define MU_INC1182 1183
+#define MU_INC1181 1182
+#define MU_INC1180 1181
+#define MU_INC1179 1180
+#define MU_INC1178 1179
+#define MU_INC1177 1178
+#define MU_INC1176 1177
+#define MU_INC1175 1176
+#define MU_INC1174 1175
+#define MU_INC1173 1174
+#define MU_INC1172 1173
+#define MU_INC1171 1172
+#define MU_INC1170 1171
+#define MU_INC1169 1170
+#define MU_INC1168 1169
+#define MU_INC1167 1168
+#define MU_INC1166 1167
+#define MU_INC1165 1166
+#define MU_INC1164 1165
+#define MU_INC1163 1164
+#define MU_INC1162 1163
+#define MU_INC1161 1162
+#define MU_INC1160 1161
+#define MU_INC1159 1160
+#define MU_INC1158 1159
+#define MU_INC1157 1158
+#define MU_INC1156 1157
+#define MU_INC1155 1156
+#define MU_INC1154 1155
+#define MU_INC1153 1154
+#define MU_INC1152 1153
+#define MU_INC1151 1152
+#define MU_INC1150 1151
+#define MU_INC1149 1150
+#define MU_INC1148 1149
+#define MU_INC1147 1148
+#define MU_INC1146 1147
+#define MU_INC1145 1146
+#define MU_INC1144 1145
+#define MU_INC1143 1144
+#define MU_INC1142 1143
+#define MU_INC1141 1142
+#define MU_INC1140 1141
+#define MU_INC1139 1140
+#define MU_INC1138 1139
+#define MU_INC1137 1138
+#define MU_INC1136 1137
+#define MU_INC1135 1136
+#define MU_INC1134 1135
+#define MU_INC1133 1134
+#define MU_INC1132 1133
+#define MU_INC1131 1132
+#define MU_INC1130 1131
+#define MU_INC1129 1130
+#define MU_INC1128 1129
+#define MU_INC1127 1128
+#define MU_INC1126 1127
+#define MU_INC1125 1126
+#define MU_INC1124 1125
+#define MU_INC1123 1124
+#define MU_INC1122 1123
+#define MU_INC1121 1122
+#define MU_INC1120 1121
+#define MU_INC1119 1120
+#define MU_INC1118 1119
+#define MU_INC1117 1118
+#define MU_INC1116 1117
+#define MU_INC1115 1116
+#define MU_INC1114 1115
+#define MU_INC1113 1114
+#define MU_INC1112 1113
+#define MU_INC1111 1112
+#define MU_INC1110 1111
+#define MU_INC1109 1110
+#define MU_INC1108 1109
+#define MU_INC1107 1108
+#define MU_INC1106 1107
+#define MU_INC1105 1106
+#define MU_INC1104 1105
+#define MU_INC1103 1104
+#define MU_INC1102 1103
+#define MU_INC1101 1102
+#define MU_INC1100 1101
+#define MU_INC1099 1100
+#define MU_INC1098 1099
+#define MU_INC1097 1098
+#define MU_INC1096 1097
+#define MU_INC1095 1096
+#define MU_INC1094 1095
+#define MU_INC1093 1094
+#define MU_INC1092 1093
+#define MU_INC1091 1092
+#define MU_INC1090 1091
+#define MU_INC1089 1090
+#define MU_INC1088 1089
+#define MU_INC1087 1088
+#define MU_INC1086 1087
+#define MU_INC1085 1086
+#define MU_INC1084 1085
+#define MU_INC1083 1084
+#define MU_INC1082 1083
+#define MU_INC1081 1082
+#define MU_INC1080 1081
+#define MU_INC1079 1080
+#define MU_INC1078 1079
+#define MU_INC1077 1078
+#define MU_INC1076 1077
+#define MU_INC1075 1076
+#define MU_INC1074 1075
+#define MU_INC1073 1074
+#define MU_INC1072 1073
+#define MU_INC1071 1072
+#define MU_INC1070 1071
+#define MU_INC1069 1070
+#define MU_INC1068 1069
+#define MU_INC1067 1068
+#define MU_INC1066 1067
+#define MU_INC1065 1066
+#define MU_INC1064 1065
+#define MU_INC1063 1064
+#define MU_INC1062 1063
+#define MU_INC1061 1062
+#define MU_INC1060 1061
+#define MU_INC1059 1060
+#define MU_INC1058 1059
+#define MU_INC1057 1058
+#define MU_INC1056 1057
+#define MU_INC1055 1056
+#define MU_INC1054 1055
+#define MU_INC1053 1054
+#define MU_INC1052 1053
+#define MU_INC1051 1052
+#define MU_INC1050 1051
+#define MU_INC1049 1050
+#define MU_INC1048 1049
+#define MU_INC1047 1048
+#define MU_INC1046 1047
+#define MU_INC1045 1046
+#define MU_INC1044 1045
+#define MU_INC1043 1044
+#define MU_INC1042 1043
+#define MU_INC1041 1042
+#define MU_INC1040 1041
+#define MU_INC1039 1040
+#define MU_INC1038 1039
+#define MU_INC1037 1038
+#define MU_INC1036 1037
+#define MU_INC1035 1036
+#define MU_INC1034 1035
+#define MU_INC1033 1034
+#define MU_INC1032 1033
+#define MU_INC1031 1032
+#define MU_INC1030 1031
+#define MU_INC1029 1030
+#define MU_INC1028 1029
+#define MU_INC1027 1028
+#define MU_INC1026 1027
+#define MU_INC1025 1026
+#define MU_INC1024 1025
+#define MU_INC1023 1024
+#define MU_INC1022 1023
+#define MU_INC1021 1022
+#define MU_INC1020 1021
+#define MU_INC1019 1020
+#define MU_INC1018 1019
+#define MU_INC1017 1018
+#define MU_INC1016 1017
+#define MU_INC1015 1016
+#define MU_INC1014 1015
+#define MU_INC1013 1014
+#define MU_INC1012 1013
+#define MU_INC1011 1012
+#define MU_INC1010 1011
+#define MU_INC1009 1010
+#define MU_INC1008 1009
+#define MU_INC1007 1008
+#define MU_INC1006 1007
+#define MU_INC1005 1006
+#define MU_INC1004 1005
+#define MU_INC1003 1004
+#define MU_INC1002 1003
+#define MU_INC1001 1002
+#define MU_INC1000 1001
+#define MU_INC999 1000
+#define MU_INC998 999
+#define MU_INC997 998
+#define MU_INC996 997
+#define MU_INC995 996
+#define MU_INC994 995
+#define MU_INC993 994
+#define MU_INC992 993
+#define MU_INC991 992
+#define MU_INC990 991
+#define MU_INC989 990
+#define MU_INC988 989
+#define MU_INC987 988
+#define MU_INC986 987
+#define MU_INC985 986
+#define MU_INC984 985
+#define MU_INC983 984
+#define MU_INC982 983
+#define MU_INC981 982
+#define MU_INC980 981
+#define MU_INC979 980
+#define MU_INC978 979
+#define MU_INC977 978
+#define MU_INC976 977
+#define MU_INC975 976
+#define MU_INC974 975
+#define MU_INC973 974
+#define MU_INC972 973
+#define MU_INC971 972
+#define MU_INC970 971
+#define MU_INC969 970
+#define MU_INC968 969
+#define MU_INC967 968
+#define MU_INC966 967
+#define MU_INC965 966
+#define MU_INC964 965
+#define MU_INC963 964
+#define MU_INC962 963
+#define MU_INC961 962
+#define MU_INC960 961
+#define MU_INC959 960
+#define MU_INC958 959
+#define MU_INC957 958
+#define MU_INC956 957
+#define MU_INC955 956
+#define MU_INC954 955
+#define MU_INC953 954
+#define MU_INC952 953
+#define MU_INC951 952
+#define MU_INC950 951
+#define MU_INC949 950
+#define MU_INC948 949
+#define MU_INC947 948
+#define MU_INC946 947
+#define MU_INC945 946
+#define MU_INC944 945
+#define MU_INC943 944
+#define MU_INC942 943
+#define MU_INC941 942
+#define MU_INC940 941
+#define MU_INC939 940
+#define MU_INC938 939
+#define MU_INC937 938
+#define MU_INC936 937
+#define MU_INC935 936
+#define MU_INC934 935
+#define MU_INC933 934
+#define MU_INC932 933
+#define MU_INC931 932
+#define MU_INC930 931
+#define MU_INC929 930
+#define MU_INC928 929
+#define MU_INC927 928
+#define MU_INC926 927
+#define MU_INC925 926
+#define MU_INC924 925
+#define MU_INC923 924
+#define MU_INC922 923
+#define MU_INC921 922
+#define MU_INC920 921
+#define MU_INC919 920
+#define MU_INC918 919
+#define MU_INC917 918
+#define MU_INC916 917
+#define MU_INC915 916
+#define MU_INC914 915
+#define MU_INC913 914
+#define MU_INC912 913
+#define MU_INC911 912
+#define MU_INC910 911
+#define MU_INC909 910
+#define MU_INC908 909
+#define MU_INC907 908
+#define MU_INC906 907
+#define MU_INC905 906
+#define MU_INC904 905
+#define MU_INC903 904
+#define MU_INC902 903
+#define MU_INC901 902
+#define MU_INC900 901
+#define MU_INC899 900
+#define MU_INC898 899
+#define MU_INC897 898
+#define MU_INC896 897
+#define MU_INC895 896
+#define MU_INC894 895
+#define MU_INC893 894
+#define MU_INC892 893
+#define MU_INC891 892
+#define MU_INC890 891
+#define MU_INC889 890
+#define MU_INC888 889
+#define MU_INC887 888
+#define MU_INC886 887
+#define MU_INC885 886
+#define MU_INC884 885
+#define MU_INC883 884
+#define MU_INC882 883
+#define MU_INC881 882
+#define MU_INC880 881
+#define MU_INC879 880
+#define MU_INC878 879
+#define MU_INC877 878
+#define MU_INC876 877
+#define MU_INC875 876
+#define MU_INC874 875
+#define MU_INC873 874
+#define MU_INC872 873
+#define MU_INC871 872
+#define MU_INC870 871
+#define MU_INC869 870
+#define MU_INC868 869
+#define MU_INC867 868
+#define MU_INC866 867
+#define MU_INC865 866
+#define MU_INC864 865
+#define MU_INC863 864
+#define MU_INC862 863
+#define MU_INC861 862
+#define MU_INC860 861
+#define MU_INC859 860
+#define MU_INC858 859
+#define MU_INC857 858
+#define MU_INC856 857
+#define MU_INC855 856
+#define MU_INC854 855
+#define MU_INC853 854
+#define MU_INC852 853
+#define MU_INC851 852
+#define MU_INC850 851
+#define MU_INC849 850
+#define MU_INC848 849
+#define MU_INC847 848
+#define MU_INC846 847
+#define MU_INC845 846
+#define MU_INC844 845
+#define MU_INC843 844
+#define MU_INC842 843
+#define MU_INC841 842
+#define MU_INC840 841
+#define MU_INC839 840
+#define MU_INC838 839
+#define MU_INC837 838
+#define MU_INC836 837
+#define MU_INC835 836
+#define MU_INC834 835
+#define MU_INC833 834
+#define MU_INC832 833
+#define MU_INC831 832
+#define MU_INC830 831
+#define MU_INC829 830
+#define MU_INC828 829
+#define MU_INC827 828
+#define MU_INC826 827
+#define MU_INC825 826
+#define MU_INC824 825
+#define MU_INC823 824
+#define MU_INC822 823
+#define MU_INC821 822
+#define MU_INC820 821
+#define MU_INC819 820
+#define MU_INC818 819
+#define MU_INC817 818
+#define MU_INC816 817
+#define MU_INC815 816
+#define MU_INC814 815
+#define MU_INC813 814
+#define MU_INC812 813
+#define MU_INC811 812
+#define MU_INC810 811
+#define MU_INC809 810
+#define MU_INC808 809
+#define MU_INC807 808
+#define MU_INC806 807
+#define MU_INC805 806
+#define MU_INC804 805
+#define MU_INC803 804
+#define MU_INC802 803
+#define MU_INC801 802
+#define MU_INC800 801
+#define MU_INC799 800
+#define MU_INC798 799
+#define MU_INC797 798
+#define MU_INC796 797
+#define MU_INC795 796
+#define MU_INC794 795
+#define MU_INC793 794
+#define MU_INC792 793
+#define MU_INC791 792
+#define MU_INC790 791
+#define MU_INC789 790
+#define MU_INC788 789
+#define MU_INC787 788
+#define MU_INC786 787
+#define MU_INC785 786
+#define MU_INC784 785
+#define MU_INC783 784
+#define MU_INC782 783
+#define MU_INC781 782
+#define MU_INC780 781
+#define MU_INC779 780
+#define MU_INC778 779
+#define MU_INC777 778
+#define MU_INC776 777
+#define MU_INC775 776
+#define MU_INC774 775
+#define MU_INC773 774
+#define MU_INC772 773
+#define MU_INC771 772
+#define MU_INC770 771
+#define MU_INC769 770
+#define MU_INC768 769
+#define MU_INC767 768
+#define MU_INC766 767
+#define MU_INC765 766
+#define MU_INC764 765
+#define MU_INC763 764
+#define MU_INC762 763
+#define MU_INC761 762
+#define MU_INC760 761
+#define MU_INC759 760
+#define MU_INC758 759
+#define MU_INC757 758
+#define MU_INC756 757
+#define MU_INC755 756
+#define MU_INC754 755
+#define MU_INC753 754
+#define MU_INC752 753
+#define MU_INC751 752
+#define MU_INC750 751
+#define MU_INC749 750
+#define MU_INC748 749
+#define MU_INC747 748
+#define MU_INC746 747
+#define MU_INC745 746
+#define MU_INC744 745
+#define MU_INC743 744
+#define MU_INC742 743
+#define MU_INC741 742
+#define MU_INC740 741
+#define MU_INC739 740
+#define MU_INC738 739
+#define MU_INC737 738
+#define MU_INC736 737
+#define MU_INC735 736
+#define MU_INC734 735
+#define MU_INC733 734
+#define MU_INC732 733
+#define MU_INC731 732
+#define MU_INC730 731
+#define MU_INC729 730
+#define MU_INC728 729
+#define MU_INC727 728
+#define MU_INC726 727
+#define MU_INC725 726
+#define MU_INC724 725
+#define MU_INC723 724
+#define MU_INC722 723
+#define MU_INC721 722
+#define MU_INC720 721
+#define MU_INC719 720
+#define MU_INC718 719
+#define MU_INC717 718
+#define MU_INC716 717
+#define MU_INC715 716
+#define MU_INC714 715
+#define MU_INC713 714
+#define MU_INC712 713
+#define MU_INC711 712
+#define MU_INC710 711
+#define MU_INC709 710
+#define MU_INC708 709
+#define MU_INC707 708
+#define MU_INC706 707
+#define MU_INC705 706
+#define MU_INC704 705
+#define MU_INC703 704
+#define MU_INC702 703
+#define MU_INC701 702
+#define MU_INC700 701
+#define MU_INC699 700
+#define MU_INC698 699
+#define MU_INC697 698
+#define MU_INC696 697
+#define MU_INC695 696
+#define MU_INC694 695
+#define MU_INC693 694
+#define MU_INC692 693
+#define MU_INC691 692
+#define MU_INC690 691
+#define MU_INC689 690
+#define MU_INC688 689
+#define MU_INC687 688
+#define MU_INC686 687
+#define MU_INC685 686
+#define MU_INC684 685
+#define MU_INC683 684
+#define MU_INC682 683
+#define MU_INC681 682
+#define MU_INC680 681
+#define MU_INC679 680
+#define MU_INC678 679
+#define MU_INC677 678
+#define MU_INC676 677
+#define MU_INC675 676
+#define MU_INC674 675
+#define MU_INC673 674
+#define MU_INC672 673
+#define MU_INC671 672
+#define MU_INC670 671
+#define MU_INC669 670
+#define MU_INC668 669
+#define MU_INC667 668
+#define MU_INC666 667
+#define MU_INC665 666
+#define MU_INC664 665
+#define MU_INC663 664
+#define MU_INC662 663
+#define MU_INC661 662
+#define MU_INC660 661
+#define MU_INC659 660
+#define MU_INC658 659
+#define MU_INC657 658
+#define MU_INC656 657
+#define MU_INC655 656
+#define MU_INC654 655
+#define MU_INC653 654
+#define MU_INC652 653
+#define MU_INC651 652
+#define MU_INC650 651
+#define MU_INC649 650
+#define MU_INC648 649
+#define MU_INC647 648
+#define MU_INC646 647
+#define MU_INC645 646
+#define MU_INC644 645
+#define MU_INC643 644
+#define MU_INC642 643
+#define MU_INC641 642
+#define MU_INC640 641
+#define MU_INC639 640
+#define MU_INC638 639
+#define MU_INC637 638
+#define MU_INC636 637
+#define MU_INC635 636
+#define MU_INC634 635
+#define MU_INC633 634
+#define MU_INC632 633
+#define MU_INC631 632
+#define MU_INC630 631
+#define MU_INC629 630
+#define MU_INC628 629
+#define MU_INC627 628
+#define MU_INC626 627
+#define MU_INC625 626
+#define MU_INC624 625
+#define MU_INC623 624
+#define MU_INC622 623
+#define MU_INC621 622
+#define MU_INC620 621
+#define MU_INC619 620
+#define MU_INC618 619
+#define MU_INC617 618
+#define MU_INC616 617
+#define MU_INC615 616
+#define MU_INC614 615
+#define MU_INC613 614
+#define MU_INC612 613
+#define MU_INC611 612
+#define MU_INC610 611
+#define MU_INC609 610
+#define MU_INC608 609
+#define MU_INC607 608
+#define MU_INC606 607
+#define MU_INC605 606
+#define MU_INC604 605
+#define MU_INC603 604
+#define MU_INC602 603
+#define MU_INC601 602
+#define MU_INC600 601
+#define MU_INC599 600
+#define MU_INC598 599
+#define MU_INC597 598
+#define MU_INC596 597
+#define MU_INC595 596
+#define MU_INC594 595
+#define MU_INC593 594
+#define MU_INC592 593
+#define MU_INC591 592
+#define MU_INC590 591
+#define MU_INC589 590
+#define MU_INC588 589
+#define MU_INC587 588
+#define MU_INC586 587
+#define MU_INC585 586
+#define MU_INC584 585
+#define MU_INC583 584
+#define MU_INC582 583
+#define MU_INC581 582
+#define MU_INC580 581
+#define MU_INC579 580
+#define MU_INC578 579
+#define MU_INC577 578
+#define MU_INC576 577
+#define MU_INC575 576
+#define MU_INC574 575
+#define MU_INC573 574
+#define MU_INC572 573
+#define MU_INC571 572
+#define MU_INC570 571
+#define MU_INC569 570
+#define MU_INC568 569
+#define MU_INC567 568
+#define MU_INC566 567
+#define MU_INC565 566
+#define MU_INC564 565
+#define MU_INC563 564
+#define MU_INC562 563
+#define MU_INC561 562
+#define MU_INC560 561
+#define MU_INC559 560
+#define MU_INC558 559
+#define MU_INC557 558
+#define MU_INC556 557
+#define MU_INC555 556
+#define MU_INC554 555
+#define MU_INC553 554
+#define MU_INC552 553
+#define MU_INC551 552
+#define MU_INC550 551
+#define MU_INC549 550
+#define MU_INC548 549
+#define MU_INC547 548
+#define MU_INC546 547
+#define MU_INC545 546
+#define MU_INC544 545
+#define MU_INC543 544
+#define MU_INC542 543
+#define MU_INC541 542
+#define MU_INC540 541
+#define MU_INC539 540
+#define MU_INC538 539
+#define MU_INC537 538
+#define MU_INC536 537
+#define MU_INC535 536
+#define MU_INC534 535
+#define MU_INC533 534
+#define MU_INC532 533
+#define MU_INC531 532
+#define MU_INC530 531
+#define MU_INC529 530
+#define MU_INC528 529
+#define MU_INC527 528
+#define MU_INC526 527
+#define MU_INC525 526
+#define MU_INC524 525
+#define MU_INC523 524
+#define MU_INC522 523
+#define MU_INC521 522
+#define MU_INC520 521
+#define MU_INC519 520
+#define MU_INC518 519
+#define MU_INC517 518
+#define MU_INC516 517
+#define MU_INC515 516
+#define MU_INC514 515
+#define MU_INC513 514
+#define MU_INC512 513
+#define MU_INC511 512
+#define MU_INC510 511
+#define MU_INC509 510
+#define MU_INC508 509
+#define MU_INC507 508
+#define MU_INC506 507
+#define MU_INC505 506
+#define MU_INC504 505
+#define MU_INC503 504
+#define MU_INC502 503
+#define MU_INC501 502
+#define MU_INC500 501
+#define MU_INC499 500
+#define MU_INC498 499
+#define MU_INC497 498
+#define MU_INC496 497
+#define MU_INC495 496
+#define MU_INC494 495
+#define MU_INC493 494
+#define MU_INC492 493
+#define MU_INC491 492
+#define MU_INC490 491
+#define MU_INC489 490
+#define MU_INC488 489
+#define MU_INC487 488
+#define MU_INC486 487
+#define MU_INC485 486
+#define MU_INC484 485
+#define MU_INC483 484
+#define MU_INC482 483
+#define MU_INC481 482
+#define MU_INC480 481
+#define MU_INC479 480
+#define MU_INC478 479
+#define MU_INC477 478
+#define MU_INC476 477
+#define MU_INC475 476
+#define MU_INC474 475
+#define MU_INC473 474
+#define MU_INC472 473
+#define MU_INC471 472
+#define MU_INC470 471
+#define MU_INC469 470
+#define MU_INC468 469
+#define MU_INC467 468
+#define MU_INC466 467
+#define MU_INC465 466
+#define MU_INC464 465
+#define MU_INC463 464
+#define MU_INC462 463
+#define MU_INC461 462
+#define MU_INC460 461
+#define MU_INC459 460
+#define MU_INC458 459
+#define MU_INC457 458
+#define MU_INC456 457
+#define MU_INC455 456
+#define MU_INC454 455
+#define MU_INC453 454
+#define MU_INC452 453
+#define MU_INC451 452
+#define MU_INC450 451
+#define MU_INC449 450
+#define MU_INC448 449
+#define MU_INC447 448
+#define MU_INC446 447
+#define MU_INC445 446
+#define MU_INC444 445
+#define MU_INC443 444
+#define MU_INC442 443
+#define MU_INC441 442
+#define MU_INC440 441
+#define MU_INC439 440
+#define MU_INC438 439
+#define MU_INC437 438
+#define MU_INC436 437
+#define MU_INC435 436
+#define MU_INC434 435
+#define MU_INC433 434
+#define MU_INC432 433
+#define MU_INC431 432
+#define MU_INC430 431
+#define MU_INC429 430
+#define MU_INC428 429
+#define MU_INC427 428
+#define MU_INC426 427
+#define MU_INC425 426
+#define MU_INC424 425
+#define MU_INC423 424
+#define MU_INC422 423
+#define MU_INC421 422
+#define MU_INC420 421
+#define MU_INC419 420
+#define MU_INC418 419
+#define MU_INC417 418
+#define MU_INC416 417
+#define MU_INC415 416
+#define MU_INC414 415
+#define MU_INC413 414
+#define MU_INC412 413
+#define MU_INC411 412
+#define MU_INC410 411
+#define MU_INC409 410
+#define MU_INC408 409
+#define MU_INC407 408
+#define MU_INC406 407
+#define MU_INC405 406
+#define MU_INC404 405
+#define MU_INC403 404
+#define MU_INC402 403
+#define MU_INC401 402
+#define MU_INC400 401
+#define MU_INC399 400
+#define MU_INC398 399
+#define MU_INC397 398
+#define MU_INC396 397
+#define MU_INC395 396
+#define MU_INC394 395
+#define MU_INC393 394
+#define MU_INC392 393
+#define MU_INC391 392
+#define MU_INC390 391
+#define MU_INC389 390
+#define MU_INC388 389
+#define MU_INC387 388
+#define MU_INC386 387
+#define MU_INC385 386
+#define MU_INC384 385
+#define MU_INC383 384
+#define MU_INC382 383
+#define MU_INC381 382
+#define MU_INC380 381
+#define MU_INC379 380
+#define MU_INC378 379
+#define MU_INC377 378
+#define MU_INC376 377
+#define MU_INC375 376
+#define MU_INC374 375
+#define MU_INC373 374
+#define MU_INC372 373
+#define MU_INC371 372
+#define MU_INC370 371
+#define MU_INC369 370
+#define MU_INC368 369
+#define MU_INC367 368
+#define MU_INC366 367
+#define MU_INC365 366
+#define MU_INC364 365
+#define MU_INC363 364
+#define MU_INC362 363
+#define MU_INC361 362
+#define MU_INC360 361
+#define MU_INC359 360
+#define MU_INC358 359
+#define MU_INC357 358
+#define MU_INC356 357
+#define MU_INC355 356
+#define MU_INC354 355
+#define MU_INC353 354
+#define MU_INC352 353
+#define MU_INC351 352
+#define MU_INC350 351
+#define MU_INC349 350
+#define MU_INC348 349
+#define MU_INC347 348
+#define MU_INC346 347
+#define MU_INC345 346
+#define MU_INC344 345
+#define MU_INC343 344
+#define MU_INC342 343
+#define MU_INC341 342
+#define MU_INC340 341
+#define MU_INC339 340
+#define MU_INC338 339
+#define MU_INC337 338
+#define MU_INC336 337
+#define MU_INC335 336
+#define MU_INC334 335
+#define MU_INC333 334
+#define MU_INC332 333
+#define MU_INC331 332
+#define MU_INC330 331
+#define MU_INC329 330
+#define MU_INC328 329
+#define MU_INC327 328
+#define MU_INC326 327
+#define MU_INC325 326
+#define MU_INC324 325
+#define MU_INC323 324
+#define MU_INC322 323
+#define MU_INC321 322
+#define MU_INC320 321
+#define MU_INC319 320
+#define MU_INC318 319
+#define MU_INC317 318
+#define MU_INC316 317
+#define MU_INC315 316
+#define MU_INC314 315
+#define MU_INC313 314
+#define MU_INC312 313
+#define MU_INC311 312
+#define MU_INC310 311
+#define MU_INC309 310
+#define MU_INC308 309
+#define MU_INC307 308
+#define MU_INC306 307
+#define MU_INC305 306
+#define MU_INC304 305
+#define MU_INC303 304
+#define MU_INC302 303
+#define MU_INC301 302
+#define MU_INC300 301
+#define MU_INC299 300
+#define MU_INC298 299
+#define MU_INC297 298
+#define MU_INC296 297
+#define MU_INC295 296
+#define MU_INC294 295
+#define MU_INC293 294
+#define MU_INC292 293
+#define MU_INC291 292
+#define MU_INC290 291
+#define MU_INC289 290
+#define MU_INC288 289
+#define MU_INC287 288
+#define MU_INC286 287
+#define MU_INC285 286
+#define MU_INC284 285
+#define MU_INC283 284
+#define MU_INC282 283
+#define MU_INC281 282
+#define MU_INC280 281
+#define MU_INC279 280
+#define MU_INC278 279
+#define MU_INC277 278
+#define MU_INC276 277
+#define MU_INC275 276
+#define MU_INC274 275
+#define MU_INC273 274
+#define MU_INC272 273
+#define MU_INC271 272
+#define MU_INC270 271
+#define MU_INC269 270
+#define MU_INC268 269
+#define MU_INC267 268
+#define MU_INC266 267
+#define MU_INC265 266
+#define MU_INC264 265
+#define MU_INC263 264
+#define MU_INC262 263
+#define MU_INC261 262
+#define MU_INC260 261
+#define MU_INC259 260
+#define MU_INC258 259
+#define MU_INC257 258
+#define MU_INC256 257
+#define MU_INC255 256
+#define MU_INC254 255
+#define MU_INC253 254
+#define MU_INC252 253
+#define MU_INC251 252
+#define MU_INC250 251
+#define MU_INC249 250
+#define MU_INC248 249
+#define MU_INC247 248
+#define MU_INC246 247
+#define MU_INC245 246
+#define MU_INC244 245
+#define MU_INC243 244
+#define MU_INC242 243
+#define MU_INC241 242
+#define MU_INC240 241
+#define MU_INC239 240
+#define MU_INC238 239
+#define MU_INC237 238
+#define MU_INC236 237
+#define MU_INC235 236
+#define MU_INC234 235
+#define MU_INC233 234
+#define MU_INC232 233
+#define MU_INC231 232
+#define MU_INC230 231
+#define MU_INC229 230
+#define MU_INC228 229
+#define MU_INC227 228
+#define MU_INC226 227
+#define MU_INC225 226
+#define MU_INC224 225
+#define MU_INC223 224
+#define MU_INC222 223
+#define MU_INC221 222
+#define MU_INC220 221
+#define MU_INC219 220
+#define MU_INC218 219
+#define MU_INC217 218
+#define MU_INC216 217
+#define MU_INC215 216
+#define MU_INC214 215
+#define MU_INC213 214
+#define MU_INC212 213
+#define MU_INC211 212
+#define MU_INC210 211
+#define MU_INC209 210
+#define MU_INC208 209
+#define MU_INC207 208
+#define MU_INC206 207
+#define MU_INC205 206
+#define MU_INC204 205
+#define MU_INC203 204
+#define MU_INC202 203
+#define MU_INC201 202
+#define MU_INC200 201
+#define MU_INC199 200
+#define MU_INC198 199
+#define MU_INC197 198
+#define MU_INC196 197
+#define MU_INC195 196
+#define MU_INC194 195
+#define MU_INC193 194
+#define MU_INC192 193
+#define MU_INC191 192
+#define MU_INC190 191
+#define MU_INC189 190
+#define MU_INC188 189
+#define MU_INC187 188
+#define MU_INC186 187
+#define MU_INC185 186
+#define MU_INC184 185
+#define MU_INC183 184
+#define MU_INC182 183
+#define MU_INC181 182
+#define MU_INC180 181
+#define MU_INC179 180
+#define MU_INC178 179
+#define MU_INC177 178
+#define MU_INC176 177
+#define MU_INC175 176
+#define MU_INC174 175
+#define MU_INC173 174
+#define MU_INC172 173
+#define MU_INC171 172
+#define MU_INC170 171
+#define MU_INC169 170
+#define MU_INC168 169
+#define MU_INC167 168
+#define MU_INC166 167
+#define MU_INC165 166
+#define MU_INC164 165
+#define MU_INC163 164
+#define MU_INC162 163
+#define MU_INC161 162
+#define MU_INC160 161
+#define MU_INC159 160
+#define MU_INC158 159
+#define MU_INC157 158
+#define MU_INC156 157
+#define MU_INC155 156
+#define MU_INC154 155
+#define MU_INC153 154
+#define MU_INC152 153
+#define MU_INC151 152
+#define MU_INC150 151
+#define MU_INC149 150
+#define MU_INC148 149
+#define MU_INC147 148
+#define MU_INC146 147
+#define MU_INC145 146
+#define MU_INC144 145
+#define MU_INC143 144
+#define MU_INC142 143
+#define MU_INC141 142
+#define MU_INC140 141
+#define MU_INC139 140
+#define MU_INC138 139
+#define MU_INC137 138
+#define MU_INC136 137
+#define MU_INC135 136
+#define MU_INC134 135
+#define MU_INC133 134
+#define MU_INC132 133
+#define MU_INC131 132
+#define MU_INC130 131
+#define MU_INC129 130
+#define MU_INC128 129
+#define MU_INC127 128
+#define MU_INC126 127
+#define MU_INC125 126
+#define MU_INC124 125
+#define MU_INC123 124
+#define MU_INC122 123
+#define MU_INC121 122
+#define MU_INC120 121
+#define MU_INC119 120
+#define MU_INC118 119
+#define MU_INC117 118
+#define MU_INC116 117
+#define MU_INC115 116
+#define MU_INC114 115
+#define MU_INC113 114
+#define MU_INC112 113
+#define MU_INC111 112
+#define MU_INC110 111
+#define MU_INC109 110
+#define MU_INC108 109
+#define MU_INC107 108
+#define MU_INC106 107
+#define MU_INC105 106
+#define MU_INC104 105
+#define MU_INC103 104
+#define MU_INC102 103
+#define MU_INC101 102
+#define MU_INC100 101
+#define MU_INC99 100
+#define MU_INC98 99
+#define MU_INC97 98
+#define MU_INC96 97
+#define MU_INC95 96
+#define MU_INC94 95
+#define MU_INC93 94
+#define MU_INC92 93
+#define MU_INC91 92
+#define MU_INC90 91
+#define MU_INC89 90
+#define MU_INC88 89
+#define MU_INC87 88
+#define MU_INC86 87
+#define MU_INC85 86
+#define MU_INC84 85
+#define MU_INC83 84
+#define MU_INC82 83
+#define MU_INC81 82
+#define MU_INC80 81
+#define MU_INC79 80
+#define MU_INC78 79
+#define MU_INC77 78
+#define MU_INC76 77
+#define MU_INC75 76
+#define MU_INC74 75
+#define MU_INC73 74
+#define MU_INC72 73
+#define MU_INC71 72
+#define MU_INC70 71
+#define MU_INC69 70
+#define MU_INC68 69
+#define MU_INC67 68
+#define MU_INC66 67
+#define MU_INC65 66
+#define MU_INC64 65
+#define MU_INC63 64
+#define MU_INC62 63
+#define MU_INC61 62
+#define MU_INC60 61
+#define MU_INC59 60
+#define MU_INC58 59
+#define MU_INC57 58
+#define MU_INC56 57
+#define MU_INC55 56
+#define MU_INC54 55
+#define MU_INC53 54
+#define MU_INC52 53
+#define MU_INC51 52
+#define MU_INC50 51
+#define MU_INC49 50
+#define MU_INC48 49
+#define MU_INC47 48
+#define MU_INC46 47
+#define MU_INC45 46
+#define MU_INC44 45
+#define MU_INC43 44
+#define MU_INC42 43
+#define MU_INC41 42
+#define MU_INC40 41
+#define MU_INC39 40
+#define MU_INC38 39
+#define MU_INC37 38
+#define MU_INC36 37
+#define MU_INC35 36
+#define MU_INC34 35
+#define MU_INC33 34
+#define MU_INC32 33
+#define MU_INC31 32
+#define MU_INC30 31
+#define MU_INC29 30
+#define MU_INC28 29
+#define MU_INC27 28
+#define MU_INC26 27
+#define MU_INC25 26
+#define MU_INC24 25
+#define MU_INC23 24
+#define MU_INC22 23
+#define MU_INC21 22
+#define MU_INC20 21
+#define MU_INC19 20
+#define MU_INC18 19
+#define MU_INC17 18
+#define MU_INC16 17
+#define MU_INC15 16
+#define MU_INC14 15
+#define MU_INC13 14
+#define MU_INC12 13
+#define MU_INC11 12
+#define MU_INC10 11
+#define MU_INC9 10
+#define MU_INC8 9
+#define MU_INC7 8
+#define MU_INC6 7
+#define MU_INC5 6
+#define MU_INC4 5
+#define MU_INC3 4
+#define MU_INC2 3
+#define MU_INC1 2
+#define MU_INC0 1
+
+#define MU_DIV2(x) MU_C2(MU_DIV2_,x)
+
+#define MU_DIV2_2048 1024
+#define MU_DIV2_2047 1023
+#define MU_DIV2_2046 1023
+#define MU_DIV2_2045 1022
+#define MU_DIV2_2044 1022
+#define MU_DIV2_2043 1021
+#define MU_DIV2_2042 1021
+#define MU_DIV2_2041 1020
+#define MU_DIV2_2040 1020
+#define MU_DIV2_2039 1019
+#define MU_DIV2_2038 1019
+#define MU_DIV2_2037 1018
+#define MU_DIV2_2036 1018
+#define MU_DIV2_2035 1017
+#define MU_DIV2_2034 1017
+#define MU_DIV2_2033 1016
+#define MU_DIV2_2032 1016
+#define MU_DIV2_2031 1015
+#define MU_DIV2_2030 1015
+#define MU_DIV2_2029 1014
+#define MU_DIV2_2028 1014
+#define MU_DIV2_2027 1013
+#define MU_DIV2_2026 1013
+#define MU_DIV2_2025 1012
+#define MU_DIV2_2024 1012
+#define MU_DIV2_2023 1011
+#define MU_DIV2_2022 1011
+#define MU_DIV2_2021 1010
+#define MU_DIV2_2020 1010
+#define MU_DIV2_2019 1009
+#define MU_DIV2_2018 1009
+#define MU_DIV2_2017 1008
+#define MU_DIV2_2016 1008
+#define MU_DIV2_2015 1007
+#define MU_DIV2_2014 1007
+#define MU_DIV2_2013 1006
+#define MU_DIV2_2012 1006
+#define MU_DIV2_2011 1005
+#define MU_DIV2_2010 1005
+#define MU_DIV2_2009 1004
+#define MU_DIV2_2008 1004
+#define MU_DIV2_2007 1003
+#define MU_DIV2_2006 1003
+#define MU_DIV2_2005 1002
+#define MU_DIV2_2004 1002
+#define MU_DIV2_2003 1001
+#define MU_DIV2_2002 1001
+#define MU_DIV2_2001 1000
+#define MU_DIV2_2000 1000
+#define MU_DIV2_1999 999
+#define MU_DIV2_1998 999
+#define MU_DIV2_1997 998
+#define MU_DIV2_1996 998
+#define MU_DIV2_1995 997
+#define MU_DIV2_1994 997
+#define MU_DIV2_1993 996
+#define MU_DIV2_1992 996
+#define MU_DIV2_1991 995
+#define MU_DIV2_1990 995
+#define MU_DIV2_1989 994
+#define MU_DIV2_1988 994
+#define MU_DIV2_1987 993
+#define MU_DIV2_1986 993
+#define MU_DIV2_1985 992
+#define MU_DIV2_1984 992
+#define MU_DIV2_1983 991
+#define MU_DIV2_1982 991
+#define MU_DIV2_1981 990
+#define MU_DIV2_1980 990
+#define MU_DIV2_1979 989
+#define MU_DIV2_1978 989
+#define MU_DIV2_1977 988
+#define MU_DIV2_1976 988
+#define MU_DIV2_1975 987
+#define MU_DIV2_1974 987
+#define MU_DIV2_1973 986
+#define MU_DIV2_1972 986
+#define MU_DIV2_1971 985
+#define MU_DIV2_1970 985
+#define MU_DIV2_1969 984
+#define MU_DIV2_1968 984
+#define MU_DIV2_1967 983
+#define MU_DIV2_1966 983
+#define MU_DIV2_1965 982
+#define MU_DIV2_1964 982
+#define MU_DIV2_1963 981
+#define MU_DIV2_1962 981
+#define MU_DIV2_1961 980
+#define MU_DIV2_1960 980
+#define MU_DIV2_1959 979
+#define MU_DIV2_1958 979
+#define MU_DIV2_1957 978
+#define MU_DIV2_1956 978
+#define MU_DIV2_1955 977
+#define MU_DIV2_1954 977
+#define MU_DIV2_1953 976
+#define MU_DIV2_1952 976
+#define MU_DIV2_1951 975
+#define MU_DIV2_1950 975
+#define MU_DIV2_1949 974
+#define MU_DIV2_1948 974
+#define MU_DIV2_1947 973
+#define MU_DIV2_1946 973
+#define MU_DIV2_1945 972
+#define MU_DIV2_1944 972
+#define MU_DIV2_1943 971
+#define MU_DIV2_1942 971
+#define MU_DIV2_1941 970
+#define MU_DIV2_1940 970
+#define MU_DIV2_1939 969
+#define MU_DIV2_1938 969
+#define MU_DIV2_1937 968
+#define MU_DIV2_1936 968
+#define MU_DIV2_1935 967
+#define MU_DIV2_1934 967
+#define MU_DIV2_1933 966
+#define MU_DIV2_1932 966
+#define MU_DIV2_1931 965
+#define MU_DIV2_1930 965
+#define MU_DIV2_1929 964
+#define MU_DIV2_1928 964
+#define MU_DIV2_1927 963
+#define MU_DIV2_1926 963
+#define MU_DIV2_1925 962
+#define MU_DIV2_1924 962
+#define MU_DIV2_1923 961
+#define MU_DIV2_1922 961
+#define MU_DIV2_1921 960
+#define MU_DIV2_1920 960
+#define MU_DIV2_1919 959
+#define MU_DIV2_1918 959
+#define MU_DIV2_1917 958
+#define MU_DIV2_1916 958
+#define MU_DIV2_1915 957
+#define MU_DIV2_1914 957
+#define MU_DIV2_1913 956
+#define MU_DIV2_1912 956
+#define MU_DIV2_1911 955
+#define MU_DIV2_1910 955
+#define MU_DIV2_1909 954
+#define MU_DIV2_1908 954
+#define MU_DIV2_1907 953
+#define MU_DIV2_1906 953
+#define MU_DIV2_1905 952
+#define MU_DIV2_1904 952
+#define MU_DIV2_1903 951
+#define MU_DIV2_1902 951
+#define MU_DIV2_1901 950
+#define MU_DIV2_1900 950
+#define MU_DIV2_1899 949
+#define MU_DIV2_1898 949
+#define MU_DIV2_1897 948
+#define MU_DIV2_1896 948
+#define MU_DIV2_1895 947
+#define MU_DIV2_1894 947
+#define MU_DIV2_1893 946
+#define MU_DIV2_1892 946
+#define MU_DIV2_1891 945
+#define MU_DIV2_1890 945
+#define MU_DIV2_1889 944
+#define MU_DIV2_1888 944
+#define MU_DIV2_1887 943
+#define MU_DIV2_1886 943
+#define MU_DIV2_1885 942
+#define MU_DIV2_1884 942
+#define MU_DIV2_1883 941
+#define MU_DIV2_1882 941
+#define MU_DIV2_1881 940
+#define MU_DIV2_1880 940
+#define MU_DIV2_1879 939
+#define MU_DIV2_1878 939
+#define MU_DIV2_1877 938
+#define MU_DIV2_1876 938
+#define MU_DIV2_1875 937
+#define MU_DIV2_1874 937
+#define MU_DIV2_1873 936
+#define MU_DIV2_1872 936
+#define MU_DIV2_1871 935
+#define MU_DIV2_1870 935
+#define MU_DIV2_1869 934
+#define MU_DIV2_1868 934
+#define MU_DIV2_1867 933
+#define MU_DIV2_1866 933
+#define MU_DIV2_1865 932
+#define MU_DIV2_1864 932
+#define MU_DIV2_1863 931
+#define MU_DIV2_1862 931
+#define MU_DIV2_1861 930
+#define MU_DIV2_1860 930
+#define MU_DIV2_1859 929
+#define MU_DIV2_1858 929
+#define MU_DIV2_1857 928
+#define MU_DIV2_1856 928
+#define MU_DIV2_1855 927
+#define MU_DIV2_1854 927
+#define MU_DIV2_1853 926
+#define MU_DIV2_1852 926
+#define MU_DIV2_1851 925
+#define MU_DIV2_1850 925
+#define MU_DIV2_1849 924
+#define MU_DIV2_1848 924
+#define MU_DIV2_1847 923
+#define MU_DIV2_1846 923
+#define MU_DIV2_1845 922
+#define MU_DIV2_1844 922
+#define MU_DIV2_1843 921
+#define MU_DIV2_1842 921
+#define MU_DIV2_1841 920
+#define MU_DIV2_1840 920
+#define MU_DIV2_1839 919
+#define MU_DIV2_1838 919
+#define MU_DIV2_1837 918
+#define MU_DIV2_1836 918
+#define MU_DIV2_1835 917
+#define MU_DIV2_1834 917
+#define MU_DIV2_1833 916
+#define MU_DIV2_1832 916
+#define MU_DIV2_1831 915
+#define MU_DIV2_1830 915
+#define MU_DIV2_1829 914
+#define MU_DIV2_1828 914
+#define MU_DIV2_1827 913
+#define MU_DIV2_1826 913
+#define MU_DIV2_1825 912
+#define MU_DIV2_1824 912
+#define MU_DIV2_1823 911
+#define MU_DIV2_1822 911
+#define MU_DIV2_1821 910
+#define MU_DIV2_1820 910
+#define MU_DIV2_1819 909
+#define MU_DIV2_1818 909
+#define MU_DIV2_1817 908
+#define MU_DIV2_1816 908
+#define MU_DIV2_1815 907
+#define MU_DIV2_1814 907
+#define MU_DIV2_1813 906
+#define MU_DIV2_1812 906
+#define MU_DIV2_1811 905
+#define MU_DIV2_1810 905
+#define MU_DIV2_1809 904
+#define MU_DIV2_1808 904
+#define MU_DIV2_1807 903
+#define MU_DIV2_1806 903
+#define MU_DIV2_1805 902
+#define MU_DIV2_1804 902
+#define MU_DIV2_1803 901
+#define MU_DIV2_1802 901
+#define MU_DIV2_1801 900
+#define MU_DIV2_1800 900
+#define MU_DIV2_1799 899
+#define MU_DIV2_1798 899
+#define MU_DIV2_1797 898
+#define MU_DIV2_1796 898
+#define MU_DIV2_1795 897
+#define MU_DIV2_1794 897
+#define MU_DIV2_1793 896
+#define MU_DIV2_1792 896
+#define MU_DIV2_1791 895
+#define MU_DIV2_1790 895
+#define MU_DIV2_1789 894
+#define MU_DIV2_1788 894
+#define MU_DIV2_1787 893
+#define MU_DIV2_1786 893
+#define MU_DIV2_1785 892
+#define MU_DIV2_1784 892
+#define MU_DIV2_1783 891
+#define MU_DIV2_1782 891
+#define MU_DIV2_1781 890
+#define MU_DIV2_1780 890
+#define MU_DIV2_1779 889
+#define MU_DIV2_1778 889
+#define MU_DIV2_1777 888
+#define MU_DIV2_1776 888
+#define MU_DIV2_1775 887
+#define MU_DIV2_1774 887
+#define MU_DIV2_1773 886
+#define MU_DIV2_1772 886
+#define MU_DIV2_1771 885
+#define MU_DIV2_1770 885
+#define MU_DIV2_1769 884
+#define MU_DIV2_1768 884
+#define MU_DIV2_1767 883
+#define MU_DIV2_1766 883
+#define MU_DIV2_1765 882
+#define MU_DIV2_1764 882
+#define MU_DIV2_1763 881
+#define MU_DIV2_1762 881
+#define MU_DIV2_1761 880
+#define MU_DIV2_1760 880
+#define MU_DIV2_1759 879
+#define MU_DIV2_1758 879
+#define MU_DIV2_1757 878
+#define MU_DIV2_1756 878
+#define MU_DIV2_1755 877
+#define MU_DIV2_1754 877
+#define MU_DIV2_1753 876
+#define MU_DIV2_1752 876
+#define MU_DIV2_1751 875
+#define MU_DIV2_1750 875
+#define MU_DIV2_1749 874
+#define MU_DIV2_1748 874
+#define MU_DIV2_1747 873
+#define MU_DIV2_1746 873
+#define MU_DIV2_1745 872
+#define MU_DIV2_1744 872
+#define MU_DIV2_1743 871
+#define MU_DIV2_1742 871
+#define MU_DIV2_1741 870
+#define MU_DIV2_1740 870
+#define MU_DIV2_1739 869
+#define MU_DIV2_1738 869
+#define MU_DIV2_1737 868
+#define MU_DIV2_1736 868
+#define MU_DIV2_1735 867
+#define MU_DIV2_1734 867
+#define MU_DIV2_1733 866
+#define MU_DIV2_1732 866
+#define MU_DIV2_1731 865
+#define MU_DIV2_1730 865
+#define MU_DIV2_1729 864
+#define MU_DIV2_1728 864
+#define MU_DIV2_1727 863
+#define MU_DIV2_1726 863
+#define MU_DIV2_1725 862
+#define MU_DIV2_1724 862
+#define MU_DIV2_1723 861
+#define MU_DIV2_1722 861
+#define MU_DIV2_1721 860
+#define MU_DIV2_1720 860
+#define MU_DIV2_1719 859
+#define MU_DIV2_1718 859
+#define MU_DIV2_1717 858
+#define MU_DIV2_1716 858
+#define MU_DIV2_1715 857
+#define MU_DIV2_1714 857
+#define MU_DIV2_1713 856
+#define MU_DIV2_1712 856
+#define MU_DIV2_1711 855
+#define MU_DIV2_1710 855
+#define MU_DIV2_1709 854
+#define MU_DIV2_1708 854
+#define MU_DIV2_1707 853
+#define MU_DIV2_1706 853
+#define MU_DIV2_1705 852
+#define MU_DIV2_1704 852
+#define MU_DIV2_1703 851
+#define MU_DIV2_1702 851
+#define MU_DIV2_1701 850
+#define MU_DIV2_1700 850
+#define MU_DIV2_1699 849
+#define MU_DIV2_1698 849
+#define MU_DIV2_1697 848
+#define MU_DIV2_1696 848
+#define MU_DIV2_1695 847
+#define MU_DIV2_1694 847
+#define MU_DIV2_1693 846
+#define MU_DIV2_1692 846
+#define MU_DIV2_1691 845
+#define MU_DIV2_1690 845
+#define MU_DIV2_1689 844
+#define MU_DIV2_1688 844
+#define MU_DIV2_1687 843
+#define MU_DIV2_1686 843
+#define MU_DIV2_1685 842
+#define MU_DIV2_1684 842
+#define MU_DIV2_1683 841
+#define MU_DIV2_1682 841
+#define MU_DIV2_1681 840
+#define MU_DIV2_1680 840
+#define MU_DIV2_1679 839
+#define MU_DIV2_1678 839
+#define MU_DIV2_1677 838
+#define MU_DIV2_1676 838
+#define MU_DIV2_1675 837
+#define MU_DIV2_1674 837
+#define MU_DIV2_1673 836
+#define MU_DIV2_1672 836
+#define MU_DIV2_1671 835
+#define MU_DIV2_1670 835
+#define MU_DIV2_1669 834
+#define MU_DIV2_1668 834
+#define MU_DIV2_1667 833
+#define MU_DIV2_1666 833
+#define MU_DIV2_1665 832
+#define MU_DIV2_1664 832
+#define MU_DIV2_1663 831
+#define MU_DIV2_1662 831
+#define MU_DIV2_1661 830
+#define MU_DIV2_1660 830
+#define MU_DIV2_1659 829
+#define MU_DIV2_1658 829
+#define MU_DIV2_1657 828
+#define MU_DIV2_1656 828
+#define MU_DIV2_1655 827
+#define MU_DIV2_1654 827
+#define MU_DIV2_1653 826
+#define MU_DIV2_1652 826
+#define MU_DIV2_1651 825
+#define MU_DIV2_1650 825
+#define MU_DIV2_1649 824
+#define MU_DIV2_1648 824
+#define MU_DIV2_1647 823
+#define MU_DIV2_1646 823
+#define MU_DIV2_1645 822
+#define MU_DIV2_1644 822
+#define MU_DIV2_1643 821
+#define MU_DIV2_1642 821
+#define MU_DIV2_1641 820
+#define MU_DIV2_1640 820
+#define MU_DIV2_1639 819
+#define MU_DIV2_1638 819
+#define MU_DIV2_1637 818
+#define MU_DIV2_1636 818
+#define MU_DIV2_1635 817
+#define MU_DIV2_1634 817
+#define MU_DIV2_1633 816
+#define MU_DIV2_1632 816
+#define MU_DIV2_1631 815
+#define MU_DIV2_1630 815
+#define MU_DIV2_1629 814
+#define MU_DIV2_1628 814
+#define MU_DIV2_1627 813
+#define MU_DIV2_1626 813
+#define MU_DIV2_1625 812
+#define MU_DIV2_1624 812
+#define MU_DIV2_1623 811
+#define MU_DIV2_1622 811
+#define MU_DIV2_1621 810
+#define MU_DIV2_1620 810
+#define MU_DIV2_1619 809
+#define MU_DIV2_1618 809
+#define MU_DIV2_1617 808
+#define MU_DIV2_1616 808
+#define MU_DIV2_1615 807
+#define MU_DIV2_1614 807
+#define MU_DIV2_1613 806
+#define MU_DIV2_1612 806
+#define MU_DIV2_1611 805
+#define MU_DIV2_1610 805
+#define MU_DIV2_1609 804
+#define MU_DIV2_1608 804
+#define MU_DIV2_1607 803
+#define MU_DIV2_1606 803
+#define MU_DIV2_1605 802
+#define MU_DIV2_1604 802
+#define MU_DIV2_1603 801
+#define MU_DIV2_1602 801
+#define MU_DIV2_1601 800
+#define MU_DIV2_1600 800
+#define MU_DIV2_1599 799
+#define MU_DIV2_1598 799
+#define MU_DIV2_1597 798
+#define MU_DIV2_1596 798
+#define MU_DIV2_1595 797
+#define MU_DIV2_1594 797
+#define MU_DIV2_1593 796
+#define MU_DIV2_1592 796
+#define MU_DIV2_1591 795
+#define MU_DIV2_1590 795
+#define MU_DIV2_1589 794
+#define MU_DIV2_1588 794
+#define MU_DIV2_1587 793
+#define MU_DIV2_1586 793
+#define MU_DIV2_1585 792
+#define MU_DIV2_1584 792
+#define MU_DIV2_1583 791
+#define MU_DIV2_1582 791
+#define MU_DIV2_1581 790
+#define MU_DIV2_1580 790
+#define MU_DIV2_1579 789
+#define MU_DIV2_1578 789
+#define MU_DIV2_1577 788
+#define MU_DIV2_1576 788
+#define MU_DIV2_1575 787
+#define MU_DIV2_1574 787
+#define MU_DIV2_1573 786
+#define MU_DIV2_1572 786
+#define MU_DIV2_1571 785
+#define MU_DIV2_1570 785
+#define MU_DIV2_1569 784
+#define MU_DIV2_1568 784
+#define MU_DIV2_1567 783
+#define MU_DIV2_1566 783
+#define MU_DIV2_1565 782
+#define MU_DIV2_1564 782
+#define MU_DIV2_1563 781
+#define MU_DIV2_1562 781
+#define MU_DIV2_1561 780
+#define MU_DIV2_1560 780
+#define MU_DIV2_1559 779
+#define MU_DIV2_1558 779
+#define MU_DIV2_1557 778
+#define MU_DIV2_1556 778
+#define MU_DIV2_1555 777
+#define MU_DIV2_1554 777
+#define MU_DIV2_1553 776
+#define MU_DIV2_1552 776
+#define MU_DIV2_1551 775
+#define MU_DIV2_1550 775
+#define MU_DIV2_1549 774
+#define MU_DIV2_1548 774
+#define MU_DIV2_1547 773
+#define MU_DIV2_1546 773
+#define MU_DIV2_1545 772
+#define MU_DIV2_1544 772
+#define MU_DIV2_1543 771
+#define MU_DIV2_1542 771
+#define MU_DIV2_1541 770
+#define MU_DIV2_1540 770
+#define MU_DIV2_1539 769
+#define MU_DIV2_1538 769
+#define MU_DIV2_1537 768
+#define MU_DIV2_1536 768
+#define MU_DIV2_1535 767
+#define MU_DIV2_1534 767
+#define MU_DIV2_1533 766
+#define MU_DIV2_1532 766
+#define MU_DIV2_1531 765
+#define MU_DIV2_1530 765
+#define MU_DIV2_1529 764
+#define MU_DIV2_1528 764
+#define MU_DIV2_1527 763
+#define MU_DIV2_1526 763
+#define MU_DIV2_1525 762
+#define MU_DIV2_1524 762
+#define MU_DIV2_1523 761
+#define MU_DIV2_1522 761
+#define MU_DIV2_1521 760
+#define MU_DIV2_1520 760
+#define MU_DIV2_1519 759
+#define MU_DIV2_1518 759
+#define MU_DIV2_1517 758
+#define MU_DIV2_1516 758
+#define MU_DIV2_1515 757
+#define MU_DIV2_1514 757
+#define MU_DIV2_1513 756
+#define MU_DIV2_1512 756
+#define MU_DIV2_1511 755
+#define MU_DIV2_1510 755
+#define MU_DIV2_1509 754
+#define MU_DIV2_1508 754
+#define MU_DIV2_1507 753
+#define MU_DIV2_1506 753
+#define MU_DIV2_1505 752
+#define MU_DIV2_1504 752
+#define MU_DIV2_1503 751
+#define MU_DIV2_1502 751
+#define MU_DIV2_1501 750
+#define MU_DIV2_1500 750
+#define MU_DIV2_1499 749
+#define MU_DIV2_1498 749
+#define MU_DIV2_1497 748
+#define MU_DIV2_1496 748
+#define MU_DIV2_1495 747
+#define MU_DIV2_1494 747
+#define MU_DIV2_1493 746
+#define MU_DIV2_1492 746
+#define MU_DIV2_1491 745
+#define MU_DIV2_1490 745
+#define MU_DIV2_1489 744
+#define MU_DIV2_1488 744
+#define MU_DIV2_1487 743
+#define MU_DIV2_1486 743
+#define MU_DIV2_1485 742
+#define MU_DIV2_1484 742
+#define MU_DIV2_1483 741
+#define MU_DIV2_1482 741
+#define MU_DIV2_1481 740
+#define MU_DIV2_1480 740
+#define MU_DIV2_1479 739
+#define MU_DIV2_1478 739
+#define MU_DIV2_1477 738
+#define MU_DIV2_1476 738
+#define MU_DIV2_1475 737
+#define MU_DIV2_1474 737
+#define MU_DIV2_1473 736
+#define MU_DIV2_1472 736
+#define MU_DIV2_1471 735
+#define MU_DIV2_1470 735
+#define MU_DIV2_1469 734
+#define MU_DIV2_1468 734
+#define MU_DIV2_1467 733
+#define MU_DIV2_1466 733
+#define MU_DIV2_1465 732
+#define MU_DIV2_1464 732
+#define MU_DIV2_1463 731
+#define MU_DIV2_1462 731
+#define MU_DIV2_1461 730
+#define MU_DIV2_1460 730
+#define MU_DIV2_1459 729
+#define MU_DIV2_1458 729
+#define MU_DIV2_1457 728
+#define MU_DIV2_1456 728
+#define MU_DIV2_1455 727
+#define MU_DIV2_1454 727
+#define MU_DIV2_1453 726
+#define MU_DIV2_1452 726
+#define MU_DIV2_1451 725
+#define MU_DIV2_1450 725
+#define MU_DIV2_1449 724
+#define MU_DIV2_1448 724
+#define MU_DIV2_1447 723
+#define MU_DIV2_1446 723
+#define MU_DIV2_1445 722
+#define MU_DIV2_1444 722
+#define MU_DIV2_1443 721
+#define MU_DIV2_1442 721
+#define MU_DIV2_1441 720
+#define MU_DIV2_1440 720
+#define MU_DIV2_1439 719
+#define MU_DIV2_1438 719
+#define MU_DIV2_1437 718
+#define MU_DIV2_1436 718
+#define MU_DIV2_1435 717
+#define MU_DIV2_1434 717
+#define MU_DIV2_1433 716
+#define MU_DIV2_1432 716
+#define MU_DIV2_1431 715
+#define MU_DIV2_1430 715
+#define MU_DIV2_1429 714
+#define MU_DIV2_1428 714
+#define MU_DIV2_1427 713
+#define MU_DIV2_1426 713
+#define MU_DIV2_1425 712
+#define MU_DIV2_1424 712
+#define MU_DIV2_1423 711
+#define MU_DIV2_1422 711
+#define MU_DIV2_1421 710
+#define MU_DIV2_1420 710
+#define MU_DIV2_1419 709
+#define MU_DIV2_1418 709
+#define MU_DIV2_1417 708
+#define MU_DIV2_1416 708
+#define MU_DIV2_1415 707
+#define MU_DIV2_1414 707
+#define MU_DIV2_1413 706
+#define MU_DIV2_1412 706
+#define MU_DIV2_1411 705
+#define MU_DIV2_1410 705
+#define MU_DIV2_1409 704
+#define MU_DIV2_1408 704
+#define MU_DIV2_1407 703
+#define MU_DIV2_1406 703
+#define MU_DIV2_1405 702
+#define MU_DIV2_1404 702
+#define MU_DIV2_1403 701
+#define MU_DIV2_1402 701
+#define MU_DIV2_1401 700
+#define MU_DIV2_1400 700
+#define MU_DIV2_1399 699
+#define MU_DIV2_1398 699
+#define MU_DIV2_1397 698
+#define MU_DIV2_1396 698
+#define MU_DIV2_1395 697
+#define MU_DIV2_1394 697
+#define MU_DIV2_1393 696
+#define MU_DIV2_1392 696
+#define MU_DIV2_1391 695
+#define MU_DIV2_1390 695
+#define MU_DIV2_1389 694
+#define MU_DIV2_1388 694
+#define MU_DIV2_1387 693
+#define MU_DIV2_1386 693
+#define MU_DIV2_1385 692
+#define MU_DIV2_1384 692
+#define MU_DIV2_1383 691
+#define MU_DIV2_1382 691
+#define MU_DIV2_1381 690
+#define MU_DIV2_1380 690
+#define MU_DIV2_1379 689
+#define MU_DIV2_1378 689
+#define MU_DIV2_1377 688
+#define MU_DIV2_1376 688
+#define MU_DIV2_1375 687
+#define MU_DIV2_1374 687
+#define MU_DIV2_1373 686
+#define MU_DIV2_1372 686
+#define MU_DIV2_1371 685
+#define MU_DIV2_1370 685
+#define MU_DIV2_1369 684
+#define MU_DIV2_1368 684
+#define MU_DIV2_1367 683
+#define MU_DIV2_1366 683
+#define MU_DIV2_1365 682
+#define MU_DIV2_1364 682
+#define MU_DIV2_1363 681
+#define MU_DIV2_1362 681
+#define MU_DIV2_1361 680
+#define MU_DIV2_1360 680
+#define MU_DIV2_1359 679
+#define MU_DIV2_1358 679
+#define MU_DIV2_1357 678
+#define MU_DIV2_1356 678
+#define MU_DIV2_1355 677
+#define MU_DIV2_1354 677
+#define MU_DIV2_1353 676
+#define MU_DIV2_1352 676
+#define MU_DIV2_1351 675
+#define MU_DIV2_1350 675
+#define MU_DIV2_1349 674
+#define MU_DIV2_1348 674
+#define MU_DIV2_1347 673
+#define MU_DIV2_1346 673
+#define MU_DIV2_1345 672
+#define MU_DIV2_1344 672
+#define MU_DIV2_1343 671
+#define MU_DIV2_1342 671
+#define MU_DIV2_1341 670
+#define MU_DIV2_1340 670
+#define MU_DIV2_1339 669
+#define MU_DIV2_1338 669
+#define MU_DIV2_1337 668
+#define MU_DIV2_1336 668
+#define MU_DIV2_1335 667
+#define MU_DIV2_1334 667
+#define MU_DIV2_1333 666
+#define MU_DIV2_1332 666
+#define MU_DIV2_1331 665
+#define MU_DIV2_1330 665
+#define MU_DIV2_1329 664
+#define MU_DIV2_1328 664
+#define MU_DIV2_1327 663
+#define MU_DIV2_1326 663
+#define MU_DIV2_1325 662
+#define MU_DIV2_1324 662
+#define MU_DIV2_1323 661
+#define MU_DIV2_1322 661
+#define MU_DIV2_1321 660
+#define MU_DIV2_1320 660
+#define MU_DIV2_1319 659
+#define MU_DIV2_1318 659
+#define MU_DIV2_1317 658
+#define MU_DIV2_1316 658
+#define MU_DIV2_1315 657
+#define MU_DIV2_1314 657
+#define MU_DIV2_1313 656
+#define MU_DIV2_1312 656
+#define MU_DIV2_1311 655
+#define MU_DIV2_1310 655
+#define MU_DIV2_1309 654
+#define MU_DIV2_1308 654
+#define MU_DIV2_1307 653
+#define MU_DIV2_1306 653
+#define MU_DIV2_1305 652
+#define MU_DIV2_1304 652
+#define MU_DIV2_1303 651
+#define MU_DIV2_1302 651
+#define MU_DIV2_1301 650
+#define MU_DIV2_1300 650
+#define MU_DIV2_1299 649
+#define MU_DIV2_1298 649
+#define MU_DIV2_1297 648
+#define MU_DIV2_1296 648
+#define MU_DIV2_1295 647
+#define MU_DIV2_1294 647
+#define MU_DIV2_1293 646
+#define MU_DIV2_1292 646
+#define MU_DIV2_1291 645
+#define MU_DIV2_1290 645
+#define MU_DIV2_1289 644
+#define MU_DIV2_1288 644
+#define MU_DIV2_1287 643
+#define MU_DIV2_1286 643
+#define MU_DIV2_1285 642
+#define MU_DIV2_1284 642
+#define MU_DIV2_1283 641
+#define MU_DIV2_1282 641
+#define MU_DIV2_1281 640
+#define MU_DIV2_1280 640
+#define MU_DIV2_1279 639
+#define MU_DIV2_1278 639
+#define MU_DIV2_1277 638
+#define MU_DIV2_1276 638
+#define MU_DIV2_1275 637
+#define MU_DIV2_1274 637
+#define MU_DIV2_1273 636
+#define MU_DIV2_1272 636
+#define MU_DIV2_1271 635
+#define MU_DIV2_1270 635
+#define MU_DIV2_1269 634
+#define MU_DIV2_1268 634
+#define MU_DIV2_1267 633
+#define MU_DIV2_1266 633
+#define MU_DIV2_1265 632
+#define MU_DIV2_1264 632
+#define MU_DIV2_1263 631
+#define MU_DIV2_1262 631
+#define MU_DIV2_1261 630
+#define MU_DIV2_1260 630
+#define MU_DIV2_1259 629
+#define MU_DIV2_1258 629
+#define MU_DIV2_1257 628
+#define MU_DIV2_1256 628
+#define MU_DIV2_1255 627
+#define MU_DIV2_1254 627
+#define MU_DIV2_1253 626
+#define MU_DIV2_1252 626
+#define MU_DIV2_1251 625
+#define MU_DIV2_1250 625
+#define MU_DIV2_1249 624
+#define MU_DIV2_1248 624
+#define MU_DIV2_1247 623
+#define MU_DIV2_1246 623
+#define MU_DIV2_1245 622
+#define MU_DIV2_1244 622
+#define MU_DIV2_1243 621
+#define MU_DIV2_1242 621
+#define MU_DIV2_1241 620
+#define MU_DIV2_1240 620
+#define MU_DIV2_1239 619
+#define MU_DIV2_1238 619
+#define MU_DIV2_1237 618
+#define MU_DIV2_1236 618
+#define MU_DIV2_1235 617
+#define MU_DIV2_1234 617
+#define MU_DIV2_1233 616
+#define MU_DIV2_1232 616
+#define MU_DIV2_1231 615
+#define MU_DIV2_1230 615
+#define MU_DIV2_1229 614
+#define MU_DIV2_1228 614
+#define MU_DIV2_1227 613
+#define MU_DIV2_1226 613
+#define MU_DIV2_1225 612
+#define MU_DIV2_1224 612
+#define MU_DIV2_1223 611
+#define MU_DIV2_1222 611
+#define MU_DIV2_1221 610
+#define MU_DIV2_1220 610
+#define MU_DIV2_1219 609
+#define MU_DIV2_1218 609
+#define MU_DIV2_1217 608
+#define MU_DIV2_1216 608
+#define MU_DIV2_1215 607
+#define MU_DIV2_1214 607
+#define MU_DIV2_1213 606
+#define MU_DIV2_1212 606
+#define MU_DIV2_1211 605
+#define MU_DIV2_1210 605
+#define MU_DIV2_1209 604
+#define MU_DIV2_1208 604
+#define MU_DIV2_1207 603
+#define MU_DIV2_1206 603
+#define MU_DIV2_1205 602
+#define MU_DIV2_1204 602
+#define MU_DIV2_1203 601
+#define MU_DIV2_1202 601
+#define MU_DIV2_1201 600
+#define MU_DIV2_1200 600
+#define MU_DIV2_1199 599
+#define MU_DIV2_1198 599
+#define MU_DIV2_1197 598
+#define MU_DIV2_1196 598
+#define MU_DIV2_1195 597
+#define MU_DIV2_1194 597
+#define MU_DIV2_1193 596
+#define MU_DIV2_1192 596
+#define MU_DIV2_1191 595
+#define MU_DIV2_1190 595
+#define MU_DIV2_1189 594
+#define MU_DIV2_1188 594
+#define MU_DIV2_1187 593
+#define MU_DIV2_1186 593
+#define MU_DIV2_1185 592
+#define MU_DIV2_1184 592
+#define MU_DIV2_1183 591
+#define MU_DIV2_1182 591
+#define MU_DIV2_1181 590
+#define MU_DIV2_1180 590
+#define MU_DIV2_1179 589
+#define MU_DIV2_1178 589
+#define MU_DIV2_1177 588
+#define MU_DIV2_1176 588
+#define MU_DIV2_1175 587
+#define MU_DIV2_1174 587
+#define MU_DIV2_1173 586
+#define MU_DIV2_1172 586
+#define MU_DIV2_1171 585
+#define MU_DIV2_1170 585
+#define MU_DIV2_1169 584
+#define MU_DIV2_1168 584
+#define MU_DIV2_1167 583
+#define MU_DIV2_1166 583
+#define MU_DIV2_1165 582
+#define MU_DIV2_1164 582
+#define MU_DIV2_1163 581
+#define MU_DIV2_1162 581
+#define MU_DIV2_1161 580
+#define MU_DIV2_1160 580
+#define MU_DIV2_1159 579
+#define MU_DIV2_1158 579
+#define MU_DIV2_1157 578
+#define MU_DIV2_1156 578
+#define MU_DIV2_1155 577
+#define MU_DIV2_1154 577
+#define MU_DIV2_1153 576
+#define MU_DIV2_1152 576
+#define MU_DIV2_1151 575
+#define MU_DIV2_1150 575
+#define MU_DIV2_1149 574
+#define MU_DIV2_1148 574
+#define MU_DIV2_1147 573
+#define MU_DIV2_1146 573
+#define MU_DIV2_1145 572
+#define MU_DIV2_1144 572
+#define MU_DIV2_1143 571
+#define MU_DIV2_1142 571
+#define MU_DIV2_1141 570
+#define MU_DIV2_1140 570
+#define MU_DIV2_1139 569
+#define MU_DIV2_1138 569
+#define MU_DIV2_1137 568
+#define MU_DIV2_1136 568
+#define MU_DIV2_1135 567
+#define MU_DIV2_1134 567
+#define MU_DIV2_1133 566
+#define MU_DIV2_1132 566
+#define MU_DIV2_1131 565
+#define MU_DIV2_1130 565
+#define MU_DIV2_1129 564
+#define MU_DIV2_1128 564
+#define MU_DIV2_1127 563
+#define MU_DIV2_1126 563
+#define MU_DIV2_1125 562
+#define MU_DIV2_1124 562
+#define MU_DIV2_1123 561
+#define MU_DIV2_1122 561
+#define MU_DIV2_1121 560
+#define MU_DIV2_1120 560
+#define MU_DIV2_1119 559
+#define MU_DIV2_1118 559
+#define MU_DIV2_1117 558
+#define MU_DIV2_1116 558
+#define MU_DIV2_1115 557
+#define MU_DIV2_1114 557
+#define MU_DIV2_1113 556
+#define MU_DIV2_1112 556
+#define MU_DIV2_1111 555
+#define MU_DIV2_1110 555
+#define MU_DIV2_1109 554
+#define MU_DIV2_1108 554
+#define MU_DIV2_1107 553
+#define MU_DIV2_1106 553
+#define MU_DIV2_1105 552
+#define MU_DIV2_1104 552
+#define MU_DIV2_1103 551
+#define MU_DIV2_1102 551
+#define MU_DIV2_1101 550
+#define MU_DIV2_1100 550
+#define MU_DIV2_1099 549
+#define MU_DIV2_1098 549
+#define MU_DIV2_1097 548
+#define MU_DIV2_1096 548
+#define MU_DIV2_1095 547
+#define MU_DIV2_1094 547
+#define MU_DIV2_1093 546
+#define MU_DIV2_1092 546
+#define MU_DIV2_1091 545
+#define MU_DIV2_1090 545
+#define MU_DIV2_1089 544
+#define MU_DIV2_1088 544
+#define MU_DIV2_1087 543
+#define MU_DIV2_1086 543
+#define MU_DIV2_1085 542
+#define MU_DIV2_1084 542
+#define MU_DIV2_1083 541
+#define MU_DIV2_1082 541
+#define MU_DIV2_1081 540
+#define MU_DIV2_1080 540
+#define MU_DIV2_1079 539
+#define MU_DIV2_1078 539
+#define MU_DIV2_1077 538
+#define MU_DIV2_1076 538
+#define MU_DIV2_1075 537
+#define MU_DIV2_1074 537
+#define MU_DIV2_1073 536
+#define MU_DIV2_1072 536
+#define MU_DIV2_1071 535
+#define MU_DIV2_1070 535
+#define MU_DIV2_1069 534
+#define MU_DIV2_1068 534
+#define MU_DIV2_1067 533
+#define MU_DIV2_1066 533
+#define MU_DIV2_1065 532
+#define MU_DIV2_1064 532
+#define MU_DIV2_1063 531
+#define MU_DIV2_1062 531
+#define MU_DIV2_1061 530
+#define MU_DIV2_1060 530
+#define MU_DIV2_1059 529
+#define MU_DIV2_1058 529
+#define MU_DIV2_1057 528
+#define MU_DIV2_1056 528
+#define MU_DIV2_1055 527
+#define MU_DIV2_1054 527
+#define MU_DIV2_1053 526
+#define MU_DIV2_1052 526
+#define MU_DIV2_1051 525
+#define MU_DIV2_1050 525
+#define MU_DIV2_1049 524
+#define MU_DIV2_1048 524
+#define MU_DIV2_1047 523
+#define MU_DIV2_1046 523
+#define MU_DIV2_1045 522
+#define MU_DIV2_1044 522
+#define MU_DIV2_1043 521
+#define MU_DIV2_1042 521
+#define MU_DIV2_1041 520
+#define MU_DIV2_1040 520
+#define MU_DIV2_1039 519
+#define MU_DIV2_1038 519
+#define MU_DIV2_1037 518
+#define MU_DIV2_1036 518
+#define MU_DIV2_1035 517
+#define MU_DIV2_1034 517
+#define MU_DIV2_1033 516
+#define MU_DIV2_1032 516
+#define MU_DIV2_1031 515
+#define MU_DIV2_1030 515
+#define MU_DIV2_1029 514
+#define MU_DIV2_1028 514
+#define MU_DIV2_1027 513
+#define MU_DIV2_1026 513
+#define MU_DIV2_1025 512
+#define MU_DIV2_1024 512
+#define MU_DIV2_1023 511
+#define MU_DIV2_1022 511
+#define MU_DIV2_1021 510
+#define MU_DIV2_1020 510
+#define MU_DIV2_1019 509
+#define MU_DIV2_1018 509
+#define MU_DIV2_1017 508
+#define MU_DIV2_1016 508
+#define MU_DIV2_1015 507
+#define MU_DIV2_1014 507
+#define MU_DIV2_1013 506
+#define MU_DIV2_1012 506
+#define MU_DIV2_1011 505
+#define MU_DIV2_1010 505
+#define MU_DIV2_1009 504
+#define MU_DIV2_1008 504
+#define MU_DIV2_1007 503
+#define MU_DIV2_1006 503
+#define MU_DIV2_1005 502
+#define MU_DIV2_1004 502
+#define MU_DIV2_1003 501
+#define MU_DIV2_1002 501
+#define MU_DIV2_1001 500
+#define MU_DIV2_1000 500
+#define MU_DIV2_999 499
+#define MU_DIV2_998 499
+#define MU_DIV2_997 498
+#define MU_DIV2_996 498
+#define MU_DIV2_995 497
+#define MU_DIV2_994 497
+#define MU_DIV2_993 496
+#define MU_DIV2_992 496
+#define MU_DIV2_991 495
+#define MU_DIV2_990 495
+#define MU_DIV2_989 494
+#define MU_DIV2_988 494
+#define MU_DIV2_987 493
+#define MU_DIV2_986 493
+#define MU_DIV2_985 492
+#define MU_DIV2_984 492
+#define MU_DIV2_983 491
+#define MU_DIV2_982 491
+#define MU_DIV2_981 490
+#define MU_DIV2_980 490
+#define MU_DIV2_979 489
+#define MU_DIV2_978 489
+#define MU_DIV2_977 488
+#define MU_DIV2_976 488
+#define MU_DIV2_975 487
+#define MU_DIV2_974 487
+#define MU_DIV2_973 486
+#define MU_DIV2_972 486
+#define MU_DIV2_971 485
+#define MU_DIV2_970 485
+#define MU_DIV2_969 484
+#define MU_DIV2_968 484
+#define MU_DIV2_967 483
+#define MU_DIV2_966 483
+#define MU_DIV2_965 482
+#define MU_DIV2_964 482
+#define MU_DIV2_963 481
+#define MU_DIV2_962 481
+#define MU_DIV2_961 480
+#define MU_DIV2_960 480
+#define MU_DIV2_959 479
+#define MU_DIV2_958 479
+#define MU_DIV2_957 478
+#define MU_DIV2_956 478
+#define MU_DIV2_955 477
+#define MU_DIV2_954 477
+#define MU_DIV2_953 476
+#define MU_DIV2_952 476
+#define MU_DIV2_951 475
+#define MU_DIV2_950 475
+#define MU_DIV2_949 474
+#define MU_DIV2_948 474
+#define MU_DIV2_947 473
+#define MU_DIV2_946 473
+#define MU_DIV2_945 472
+#define MU_DIV2_944 472
+#define MU_DIV2_943 471
+#define MU_DIV2_942 471
+#define MU_DIV2_941 470
+#define MU_DIV2_940 470
+#define MU_DIV2_939 469
+#define MU_DIV2_938 469
+#define MU_DIV2_937 468
+#define MU_DIV2_936 468
+#define MU_DIV2_935 467
+#define MU_DIV2_934 467
+#define MU_DIV2_933 466
+#define MU_DIV2_932 466
+#define MU_DIV2_931 465
+#define MU_DIV2_930 465
+#define MU_DIV2_929 464
+#define MU_DIV2_928 464
+#define MU_DIV2_927 463
+#define MU_DIV2_926 463
+#define MU_DIV2_925 462
+#define MU_DIV2_924 462
+#define MU_DIV2_923 461
+#define MU_DIV2_922 461
+#define MU_DIV2_921 460
+#define MU_DIV2_920 460
+#define MU_DIV2_919 459
+#define MU_DIV2_918 459
+#define MU_DIV2_917 458
+#define MU_DIV2_916 458
+#define MU_DIV2_915 457
+#define MU_DIV2_914 457
+#define MU_DIV2_913 456
+#define MU_DIV2_912 456
+#define MU_DIV2_911 455
+#define MU_DIV2_910 455
+#define MU_DIV2_909 454
+#define MU_DIV2_908 454
+#define MU_DIV2_907 453
+#define MU_DIV2_906 453
+#define MU_DIV2_905 452
+#define MU_DIV2_904 452
+#define MU_DIV2_903 451
+#define MU_DIV2_902 451
+#define MU_DIV2_901 450
+#define MU_DIV2_900 450
+#define MU_DIV2_899 449
+#define MU_DIV2_898 449
+#define MU_DIV2_897 448
+#define MU_DIV2_896 448
+#define MU_DIV2_895 447
+#define MU_DIV2_894 447
+#define MU_DIV2_893 446
+#define MU_DIV2_892 446
+#define MU_DIV2_891 445
+#define MU_DIV2_890 445
+#define MU_DIV2_889 444
+#define MU_DIV2_888 444
+#define MU_DIV2_887 443
+#define MU_DIV2_886 443
+#define MU_DIV2_885 442
+#define MU_DIV2_884 442
+#define MU_DIV2_883 441
+#define MU_DIV2_882 441
+#define MU_DIV2_881 440
+#define MU_DIV2_880 440
+#define MU_DIV2_879 439
+#define MU_DIV2_878 439
+#define MU_DIV2_877 438
+#define MU_DIV2_876 438
+#define MU_DIV2_875 437
+#define MU_DIV2_874 437
+#define MU_DIV2_873 436
+#define MU_DIV2_872 436
+#define MU_DIV2_871 435
+#define MU_DIV2_870 435
+#define MU_DIV2_869 434
+#define MU_DIV2_868 434
+#define MU_DIV2_867 433
+#define MU_DIV2_866 433
+#define MU_DIV2_865 432
+#define MU_DIV2_864 432
+#define MU_DIV2_863 431
+#define MU_DIV2_862 431
+#define MU_DIV2_861 430
+#define MU_DIV2_860 430
+#define MU_DIV2_859 429
+#define MU_DIV2_858 429
+#define MU_DIV2_857 428
+#define MU_DIV2_856 428
+#define MU_DIV2_855 427
+#define MU_DIV2_854 427
+#define MU_DIV2_853 426
+#define MU_DIV2_852 426
+#define MU_DIV2_851 425
+#define MU_DIV2_850 425
+#define MU_DIV2_849 424
+#define MU_DIV2_848 424
+#define MU_DIV2_847 423
+#define MU_DIV2_846 423
+#define MU_DIV2_845 422
+#define MU_DIV2_844 422
+#define MU_DIV2_843 421
+#define MU_DIV2_842 421
+#define MU_DIV2_841 420
+#define MU_DIV2_840 420
+#define MU_DIV2_839 419
+#define MU_DIV2_838 419
+#define MU_DIV2_837 418
+#define MU_DIV2_836 418
+#define MU_DIV2_835 417
+#define MU_DIV2_834 417
+#define MU_DIV2_833 416
+#define MU_DIV2_832 416
+#define MU_DIV2_831 415
+#define MU_DIV2_830 415
+#define MU_DIV2_829 414
+#define MU_DIV2_828 414
+#define MU_DIV2_827 413
+#define MU_DIV2_826 413
+#define MU_DIV2_825 412
+#define MU_DIV2_824 412
+#define MU_DIV2_823 411
+#define MU_DIV2_822 411
+#define MU_DIV2_821 410
+#define MU_DIV2_820 410
+#define MU_DIV2_819 409
+#define MU_DIV2_818 409
+#define MU_DIV2_817 408
+#define MU_DIV2_816 408
+#define MU_DIV2_815 407
+#define MU_DIV2_814 407
+#define MU_DIV2_813 406
+#define MU_DIV2_812 406
+#define MU_DIV2_811 405
+#define MU_DIV2_810 405
+#define MU_DIV2_809 404
+#define MU_DIV2_808 404
+#define MU_DIV2_807 403
+#define MU_DIV2_806 403
+#define MU_DIV2_805 402
+#define MU_DIV2_804 402
+#define MU_DIV2_803 401
+#define MU_DIV2_802 401
+#define MU_DIV2_801 400
+#define MU_DIV2_800 400
+#define MU_DIV2_799 399
+#define MU_DIV2_798 399
+#define MU_DIV2_797 398
+#define MU_DIV2_796 398
+#define MU_DIV2_795 397
+#define MU_DIV2_794 397
+#define MU_DIV2_793 396
+#define MU_DIV2_792 396
+#define MU_DIV2_791 395
+#define MU_DIV2_790 395
+#define MU_DIV2_789 394
+#define MU_DIV2_788 394
+#define MU_DIV2_787 393
+#define MU_DIV2_786 393
+#define MU_DIV2_785 392
+#define MU_DIV2_784 392
+#define MU_DIV2_783 391
+#define MU_DIV2_782 391
+#define MU_DIV2_781 390
+#define MU_DIV2_780 390
+#define MU_DIV2_779 389
+#define MU_DIV2_778 389
+#define MU_DIV2_777 388
+#define MU_DIV2_776 388
+#define MU_DIV2_775 387
+#define MU_DIV2_774 387
+#define MU_DIV2_773 386
+#define MU_DIV2_772 386
+#define MU_DIV2_771 385
+#define MU_DIV2_770 385
+#define MU_DIV2_769 384
+#define MU_DIV2_768 384
+#define MU_DIV2_767 383
+#define MU_DIV2_766 383
+#define MU_DIV2_765 382
+#define MU_DIV2_764 382
+#define MU_DIV2_763 381
+#define MU_DIV2_762 381
+#define MU_DIV2_761 380
+#define MU_DIV2_760 380
+#define MU_DIV2_759 379
+#define MU_DIV2_758 379
+#define MU_DIV2_757 378
+#define MU_DIV2_756 378
+#define MU_DIV2_755 377
+#define MU_DIV2_754 377
+#define MU_DIV2_753 376
+#define MU_DIV2_752 376
+#define MU_DIV2_751 375
+#define MU_DIV2_750 375
+#define MU_DIV2_749 374
+#define MU_DIV2_748 374
+#define MU_DIV2_747 373
+#define MU_DIV2_746 373
+#define MU_DIV2_745 372
+#define MU_DIV2_744 372
+#define MU_DIV2_743 371
+#define MU_DIV2_742 371
+#define MU_DIV2_741 370
+#define MU_DIV2_740 370
+#define MU_DIV2_739 369
+#define MU_DIV2_738 369
+#define MU_DIV2_737 368
+#define MU_DIV2_736 368
+#define MU_DIV2_735 367
+#define MU_DIV2_734 367
+#define MU_DIV2_733 366
+#define MU_DIV2_732 366
+#define MU_DIV2_731 365
+#define MU_DIV2_730 365
+#define MU_DIV2_729 364
+#define MU_DIV2_728 364
+#define MU_DIV2_727 363
+#define MU_DIV2_726 363
+#define MU_DIV2_725 362
+#define MU_DIV2_724 362
+#define MU_DIV2_723 361
+#define MU_DIV2_722 361
+#define MU_DIV2_721 360
+#define MU_DIV2_720 360
+#define MU_DIV2_719 359
+#define MU_DIV2_718 359
+#define MU_DIV2_717 358
+#define MU_DIV2_716 358
+#define MU_DIV2_715 357
+#define MU_DIV2_714 357
+#define MU_DIV2_713 356
+#define MU_DIV2_712 356
+#define MU_DIV2_711 355
+#define MU_DIV2_710 355
+#define MU_DIV2_709 354
+#define MU_DIV2_708 354
+#define MU_DIV2_707 353
+#define MU_DIV2_706 353
+#define MU_DIV2_705 352
+#define MU_DIV2_704 352
+#define MU_DIV2_703 351
+#define MU_DIV2_702 351
+#define MU_DIV2_701 350
+#define MU_DIV2_700 350
+#define MU_DIV2_699 349
+#define MU_DIV2_698 349
+#define MU_DIV2_697 348
+#define MU_DIV2_696 348
+#define MU_DIV2_695 347
+#define MU_DIV2_694 347
+#define MU_DIV2_693 346
+#define MU_DIV2_692 346
+#define MU_DIV2_691 345
+#define MU_DIV2_690 345
+#define MU_DIV2_689 344
+#define MU_DIV2_688 344
+#define MU_DIV2_687 343
+#define MU_DIV2_686 343
+#define MU_DIV2_685 342
+#define MU_DIV2_684 342
+#define MU_DIV2_683 341
+#define MU_DIV2_682 341
+#define MU_DIV2_681 340
+#define MU_DIV2_680 340
+#define MU_DIV2_679 339
+#define MU_DIV2_678 339
+#define MU_DIV2_677 338
+#define MU_DIV2_676 338
+#define MU_DIV2_675 337
+#define MU_DIV2_674 337
+#define MU_DIV2_673 336
+#define MU_DIV2_672 336
+#define MU_DIV2_671 335
+#define MU_DIV2_670 335
+#define MU_DIV2_669 334
+#define MU_DIV2_668 334
+#define MU_DIV2_667 333
+#define MU_DIV2_666 333
+#define MU_DIV2_665 332
+#define MU_DIV2_664 332
+#define MU_DIV2_663 331
+#define MU_DIV2_662 331
+#define MU_DIV2_661 330
+#define MU_DIV2_660 330
+#define MU_DIV2_659 329
+#define MU_DIV2_658 329
+#define MU_DIV2_657 328
+#define MU_DIV2_656 328
+#define MU_DIV2_655 327
+#define MU_DIV2_654 327
+#define MU_DIV2_653 326
+#define MU_DIV2_652 326
+#define MU_DIV2_651 325
+#define MU_DIV2_650 325
+#define MU_DIV2_649 324
+#define MU_DIV2_648 324
+#define MU_DIV2_647 323
+#define MU_DIV2_646 323
+#define MU_DIV2_645 322
+#define MU_DIV2_644 322
+#define MU_DIV2_643 321
+#define MU_DIV2_642 321
+#define MU_DIV2_641 320
+#define MU_DIV2_640 320
+#define MU_DIV2_639 319
+#define MU_DIV2_638 319
+#define MU_DIV2_637 318
+#define MU_DIV2_636 318
+#define MU_DIV2_635 317
+#define MU_DIV2_634 317
+#define MU_DIV2_633 316
+#define MU_DIV2_632 316
+#define MU_DIV2_631 315
+#define MU_DIV2_630 315
+#define MU_DIV2_629 314
+#define MU_DIV2_628 314
+#define MU_DIV2_627 313
+#define MU_DIV2_626 313
+#define MU_DIV2_625 312
+#define MU_DIV2_624 312
+#define MU_DIV2_623 311
+#define MU_DIV2_622 311
+#define MU_DIV2_621 310
+#define MU_DIV2_620 310
+#define MU_DIV2_619 309
+#define MU_DIV2_618 309
+#define MU_DIV2_617 308
+#define MU_DIV2_616 308
+#define MU_DIV2_615 307
+#define MU_DIV2_614 307
+#define MU_DIV2_613 306
+#define MU_DIV2_612 306
+#define MU_DIV2_611 305
+#define MU_DIV2_610 305
+#define MU_DIV2_609 304
+#define MU_DIV2_608 304
+#define MU_DIV2_607 303
+#define MU_DIV2_606 303
+#define MU_DIV2_605 302
+#define MU_DIV2_604 302
+#define MU_DIV2_603 301
+#define MU_DIV2_602 301
+#define MU_DIV2_601 300
+#define MU_DIV2_600 300
+#define MU_DIV2_599 299
+#define MU_DIV2_598 299
+#define MU_DIV2_597 298
+#define MU_DIV2_596 298
+#define MU_DIV2_595 297
+#define MU_DIV2_594 297
+#define MU_DIV2_593 296
+#define MU_DIV2_592 296
+#define MU_DIV2_591 295
+#define MU_DIV2_590 295
+#define MU_DIV2_589 294
+#define MU_DIV2_588 294
+#define MU_DIV2_587 293
+#define MU_DIV2_586 293
+#define MU_DIV2_585 292
+#define MU_DIV2_584 292
+#define MU_DIV2_583 291
+#define MU_DIV2_582 291
+#define MU_DIV2_581 290
+#define MU_DIV2_580 290
+#define MU_DIV2_579 289
+#define MU_DIV2_578 289
+#define MU_DIV2_577 288
+#define MU_DIV2_576 288
+#define MU_DIV2_575 287
+#define MU_DIV2_574 287
+#define MU_DIV2_573 286
+#define MU_DIV2_572 286
+#define MU_DIV2_571 285
+#define MU_DIV2_570 285
+#define MU_DIV2_569 284
+#define MU_DIV2_568 284
+#define MU_DIV2_567 283
+#define MU_DIV2_566 283
+#define MU_DIV2_565 282
+#define MU_DIV2_564 282
+#define MU_DIV2_563 281
+#define MU_DIV2_562 281
+#define MU_DIV2_561 280
+#define MU_DIV2_560 280
+#define MU_DIV2_559 279
+#define MU_DIV2_558 279
+#define MU_DIV2_557 278
+#define MU_DIV2_556 278
+#define MU_DIV2_555 277
+#define MU_DIV2_554 277
+#define MU_DIV2_553 276
+#define MU_DIV2_552 276
+#define MU_DIV2_551 275
+#define MU_DIV2_550 275
+#define MU_DIV2_549 274
+#define MU_DIV2_548 274
+#define MU_DIV2_547 273
+#define MU_DIV2_546 273
+#define MU_DIV2_545 272
+#define MU_DIV2_544 272
+#define MU_DIV2_543 271
+#define MU_DIV2_542 271
+#define MU_DIV2_541 270
+#define MU_DIV2_540 270
+#define MU_DIV2_539 269
+#define MU_DIV2_538 269
+#define MU_DIV2_537 268
+#define MU_DIV2_536 268
+#define MU_DIV2_535 267
+#define MU_DIV2_534 267
+#define MU_DIV2_533 266
+#define MU_DIV2_532 266
+#define MU_DIV2_531 265
+#define MU_DIV2_530 265
+#define MU_DIV2_529 264
+#define MU_DIV2_528 264
+#define MU_DIV2_527 263
+#define MU_DIV2_526 263
+#define MU_DIV2_525 262
+#define MU_DIV2_524 262
+#define MU_DIV2_523 261
+#define MU_DIV2_522 261
+#define MU_DIV2_521 260
+#define MU_DIV2_520 260
+#define MU_DIV2_519 259
+#define MU_DIV2_518 259
+#define MU_DIV2_517 258
+#define MU_DIV2_516 258
+#define MU_DIV2_515 257
+#define MU_DIV2_514 257
+#define MU_DIV2_513 256
+#define MU_DIV2_512 256
+#define MU_DIV2_511 255
+#define MU_DIV2_510 255
+#define MU_DIV2_509 254
+#define MU_DIV2_508 254
+#define MU_DIV2_507 253
+#define MU_DIV2_506 253
+#define MU_DIV2_505 252
+#define MU_DIV2_504 252
+#define MU_DIV2_503 251
+#define MU_DIV2_502 251
+#define MU_DIV2_501 250
+#define MU_DIV2_500 250
+#define MU_DIV2_499 249
+#define MU_DIV2_498 249
+#define MU_DIV2_497 248
+#define MU_DIV2_496 248
+#define MU_DIV2_495 247
+#define MU_DIV2_494 247
+#define MU_DIV2_493 246
+#define MU_DIV2_492 246
+#define MU_DIV2_491 245
+#define MU_DIV2_490 245
+#define MU_DIV2_489 244
+#define MU_DIV2_488 244
+#define MU_DIV2_487 243
+#define MU_DIV2_486 243
+#define MU_DIV2_485 242
+#define MU_DIV2_484 242
+#define MU_DIV2_483 241
+#define MU_DIV2_482 241
+#define MU_DIV2_481 240
+#define MU_DIV2_480 240
+#define MU_DIV2_479 239
+#define MU_DIV2_478 239
+#define MU_DIV2_477 238
+#define MU_DIV2_476 238
+#define MU_DIV2_475 237
+#define MU_DIV2_474 237
+#define MU_DIV2_473 236
+#define MU_DIV2_472 236
+#define MU_DIV2_471 235
+#define MU_DIV2_470 235
+#define MU_DIV2_469 234
+#define MU_DIV2_468 234
+#define MU_DIV2_467 233
+#define MU_DIV2_466 233
+#define MU_DIV2_465 232
+#define MU_DIV2_464 232
+#define MU_DIV2_463 231
+#define MU_DIV2_462 231
+#define MU_DIV2_461 230
+#define MU_DIV2_460 230
+#define MU_DIV2_459 229
+#define MU_DIV2_458 229
+#define MU_DIV2_457 228
+#define MU_DIV2_456 228
+#define MU_DIV2_455 227
+#define MU_DIV2_454 227
+#define MU_DIV2_453 226
+#define MU_DIV2_452 226
+#define MU_DIV2_451 225
+#define MU_DIV2_450 225
+#define MU_DIV2_449 224
+#define MU_DIV2_448 224
+#define MU_DIV2_447 223
+#define MU_DIV2_446 223
+#define MU_DIV2_445 222
+#define MU_DIV2_444 222
+#define MU_DIV2_443 221
+#define MU_DIV2_442 221
+#define MU_DIV2_441 220
+#define MU_DIV2_440 220
+#define MU_DIV2_439 219
+#define MU_DIV2_438 219
+#define MU_DIV2_437 218
+#define MU_DIV2_436 218
+#define MU_DIV2_435 217
+#define MU_DIV2_434 217
+#define MU_DIV2_433 216
+#define MU_DIV2_432 216
+#define MU_DIV2_431 215
+#define MU_DIV2_430 215
+#define MU_DIV2_429 214
+#define MU_DIV2_428 214
+#define MU_DIV2_427 213
+#define MU_DIV2_426 213
+#define MU_DIV2_425 212
+#define MU_DIV2_424 212
+#define MU_DIV2_423 211
+#define MU_DIV2_422 211
+#define MU_DIV2_421 210
+#define MU_DIV2_420 210
+#define MU_DIV2_419 209
+#define MU_DIV2_418 209
+#define MU_DIV2_417 208
+#define MU_DIV2_416 208
+#define MU_DIV2_415 207
+#define MU_DIV2_414 207
+#define MU_DIV2_413 206
+#define MU_DIV2_412 206
+#define MU_DIV2_411 205
+#define MU_DIV2_410 205
+#define MU_DIV2_409 204
+#define MU_DIV2_408 204
+#define MU_DIV2_407 203
+#define MU_DIV2_406 203
+#define MU_DIV2_405 202
+#define MU_DIV2_404 202
+#define MU_DIV2_403 201
+#define MU_DIV2_402 201
+#define MU_DIV2_401 200
+#define MU_DIV2_400 200
+#define MU_DIV2_399 199
+#define MU_DIV2_398 199
+#define MU_DIV2_397 198
+#define MU_DIV2_396 198
+#define MU_DIV2_395 197
+#define MU_DIV2_394 197
+#define MU_DIV2_393 196
+#define MU_DIV2_392 196
+#define MU_DIV2_391 195
+#define MU_DIV2_390 195
+#define MU_DIV2_389 194
+#define MU_DIV2_388 194
+#define MU_DIV2_387 193
+#define MU_DIV2_386 193
+#define MU_DIV2_385 192
+#define MU_DIV2_384 192
+#define MU_DIV2_383 191
+#define MU_DIV2_382 191
+#define MU_DIV2_381 190
+#define MU_DIV2_380 190
+#define MU_DIV2_379 189
+#define MU_DIV2_378 189
+#define MU_DIV2_377 188
+#define MU_DIV2_376 188
+#define MU_DIV2_375 187
+#define MU_DIV2_374 187
+#define MU_DIV2_373 186
+#define MU_DIV2_372 186
+#define MU_DIV2_371 185
+#define MU_DIV2_370 185
+#define MU_DIV2_369 184
+#define MU_DIV2_368 184
+#define MU_DIV2_367 183
+#define MU_DIV2_366 183
+#define MU_DIV2_365 182
+#define MU_DIV2_364 182
+#define MU_DIV2_363 181
+#define MU_DIV2_362 181
+#define MU_DIV2_361 180
+#define MU_DIV2_360 180
+#define MU_DIV2_359 179
+#define MU_DIV2_358 179
+#define MU_DIV2_357 178
+#define MU_DIV2_356 178
+#define MU_DIV2_355 177
+#define MU_DIV2_354 177
+#define MU_DIV2_353 176
+#define MU_DIV2_352 176
+#define MU_DIV2_351 175
+#define MU_DIV2_350 175
+#define MU_DIV2_349 174
+#define MU_DIV2_348 174
+#define MU_DIV2_347 173
+#define MU_DIV2_346 173
+#define MU_DIV2_345 172
+#define MU_DIV2_344 172
+#define MU_DIV2_343 171
+#define MU_DIV2_342 171
+#define MU_DIV2_341 170
+#define MU_DIV2_340 170
+#define MU_DIV2_339 169
+#define MU_DIV2_338 169
+#define MU_DIV2_337 168
+#define MU_DIV2_336 168
+#define MU_DIV2_335 167
+#define MU_DIV2_334 167
+#define MU_DIV2_333 166
+#define MU_DIV2_332 166
+#define MU_DIV2_331 165
+#define MU_DIV2_330 165
+#define MU_DIV2_329 164
+#define MU_DIV2_328 164
+#define MU_DIV2_327 163
+#define MU_DIV2_326 163
+#define MU_DIV2_325 162
+#define MU_DIV2_324 162
+#define MU_DIV2_323 161
+#define MU_DIV2_322 161
+#define MU_DIV2_321 160
+#define MU_DIV2_320 160
+#define MU_DIV2_319 159
+#define MU_DIV2_318 159
+#define MU_DIV2_317 158
+#define MU_DIV2_316 158
+#define MU_DIV2_315 157
+#define MU_DIV2_314 157
+#define MU_DIV2_313 156
+#define MU_DIV2_312 156
+#define MU_DIV2_311 155
+#define MU_DIV2_310 155
+#define MU_DIV2_309 154
+#define MU_DIV2_308 154
+#define MU_DIV2_307 153
+#define MU_DIV2_306 153
+#define MU_DIV2_305 152
+#define MU_DIV2_304 152
+#define MU_DIV2_303 151
+#define MU_DIV2_302 151
+#define MU_DIV2_301 150
+#define MU_DIV2_300 150
+#define MU_DIV2_299 149
+#define MU_DIV2_298 149
+#define MU_DIV2_297 148
+#define MU_DIV2_296 148
+#define MU_DIV2_295 147
+#define MU_DIV2_294 147
+#define MU_DIV2_293 146
+#define MU_DIV2_292 146
+#define MU_DIV2_291 145
+#define MU_DIV2_290 145
+#define MU_DIV2_289 144
+#define MU_DIV2_288 144
+#define MU_DIV2_287 143
+#define MU_DIV2_286 143
+#define MU_DIV2_285 142
+#define MU_DIV2_284 142
+#define MU_DIV2_283 141
+#define MU_DIV2_282 141
+#define MU_DIV2_281 140
+#define MU_DIV2_280 140
+#define MU_DIV2_279 139
+#define MU_DIV2_278 139
+#define MU_DIV2_277 138
+#define MU_DIV2_276 138
+#define MU_DIV2_275 137
+#define MU_DIV2_274 137
+#define MU_DIV2_273 136
+#define MU_DIV2_272 136
+#define MU_DIV2_271 135
+#define MU_DIV2_270 135
+#define MU_DIV2_269 134
+#define MU_DIV2_268 134
+#define MU_DIV2_267 133
+#define MU_DIV2_266 133
+#define MU_DIV2_265 132
+#define MU_DIV2_264 132
+#define MU_DIV2_263 131
+#define MU_DIV2_262 131
+#define MU_DIV2_261 130
+#define MU_DIV2_260 130
+#define MU_DIV2_259 129
+#define MU_DIV2_258 129
+#define MU_DIV2_257 128
+#define MU_DIV2_256 128
+#define MU_DIV2_255 127
+#define MU_DIV2_254 127
+#define MU_DIV2_253 126
+#define MU_DIV2_252 126
+#define MU_DIV2_251 125
+#define MU_DIV2_250 125
+#define MU_DIV2_249 124
+#define MU_DIV2_248 124
+#define MU_DIV2_247 123
+#define MU_DIV2_246 123
+#define MU_DIV2_245 122
+#define MU_DIV2_244 122
+#define MU_DIV2_243 121
+#define MU_DIV2_242 121
+#define MU_DIV2_241 120
+#define MU_DIV2_240 120
+#define MU_DIV2_239 119
+#define MU_DIV2_238 119
+#define MU_DIV2_237 118
+#define MU_DIV2_236 118
+#define MU_DIV2_235 117
+#define MU_DIV2_234 117
+#define MU_DIV2_233 116
+#define MU_DIV2_232 116
+#define MU_DIV2_231 115
+#define MU_DIV2_230 115
+#define MU_DIV2_229 114
+#define MU_DIV2_228 114
+#define MU_DIV2_227 113
+#define MU_DIV2_226 113
+#define MU_DIV2_225 112
+#define MU_DIV2_224 112
+#define MU_DIV2_223 111
+#define MU_DIV2_222 111
+#define MU_DIV2_221 110
+#define MU_DIV2_220 110
+#define MU_DIV2_219 109
+#define MU_DIV2_218 109
+#define MU_DIV2_217 108
+#define MU_DIV2_216 108
+#define MU_DIV2_215 107
+#define MU_DIV2_214 107
+#define MU_DIV2_213 106
+#define MU_DIV2_212 106
+#define MU_DIV2_211 105
+#define MU_DIV2_210 105
+#define MU_DIV2_209 104
+#define MU_DIV2_208 104
+#define MU_DIV2_207 103
+#define MU_DIV2_206 103
+#define MU_DIV2_205 102
+#define MU_DIV2_204 102
+#define MU_DIV2_203 101
+#define MU_DIV2_202 101
+#define MU_DIV2_201 100
+#define MU_DIV2_200 100
+#define MU_DIV2_199 99
+#define MU_DIV2_198 99
+#define MU_DIV2_197 98
+#define MU_DIV2_196 98
+#define MU_DIV2_195 97
+#define MU_DIV2_194 97
+#define MU_DIV2_193 96
+#define MU_DIV2_192 96
+#define MU_DIV2_191 95
+#define MU_DIV2_190 95
+#define MU_DIV2_189 94
+#define MU_DIV2_188 94
+#define MU_DIV2_187 93
+#define MU_DIV2_186 93
+#define MU_DIV2_185 92
+#define MU_DIV2_184 92
+#define MU_DIV2_183 91
+#define MU_DIV2_182 91
+#define MU_DIV2_181 90
+#define MU_DIV2_180 90
+#define MU_DIV2_179 89
+#define MU_DIV2_178 89
+#define MU_DIV2_177 88
+#define MU_DIV2_176 88
+#define MU_DIV2_175 87
+#define MU_DIV2_174 87
+#define MU_DIV2_173 86
+#define MU_DIV2_172 86
+#define MU_DIV2_171 85
+#define MU_DIV2_170 85
+#define MU_DIV2_169 84
+#define MU_DIV2_168 84
+#define MU_DIV2_167 83
+#define MU_DIV2_166 83
+#define MU_DIV2_165 82
+#define MU_DIV2_164 82
+#define MU_DIV2_163 81
+#define MU_DIV2_162 81
+#define MU_DIV2_161 80
+#define MU_DIV2_160 80
+#define MU_DIV2_159 79
+#define MU_DIV2_158 79
+#define MU_DIV2_157 78
+#define MU_DIV2_156 78
+#define MU_DIV2_155 77
+#define MU_DIV2_154 77
+#define MU_DIV2_153 76
+#define MU_DIV2_152 76
+#define MU_DIV2_151 75
+#define MU_DIV2_150 75
+#define MU_DIV2_149 74
+#define MU_DIV2_148 74
+#define MU_DIV2_147 73
+#define MU_DIV2_146 73
+#define MU_DIV2_145 72
+#define MU_DIV2_144 72
+#define MU_DIV2_143 71
+#define MU_DIV2_142 71
+#define MU_DIV2_141 70
+#define MU_DIV2_140 70
+#define MU_DIV2_139 69
+#define MU_DIV2_138 69
+#define MU_DIV2_137 68
+#define MU_DIV2_136 68
+#define MU_DIV2_135 67
+#define MU_DIV2_134 67
+#define MU_DIV2_133 66
+#define MU_DIV2_132 66
+#define MU_DIV2_131 65
+#define MU_DIV2_130 65
+#define MU_DIV2_129 64
+#define MU_DIV2_128 64
+#define MU_DIV2_127 63
+#define MU_DIV2_126 63
+#define MU_DIV2_125 62
+#define MU_DIV2_124 62
+#define MU_DIV2_123 61
+#define MU_DIV2_122 61
+#define MU_DIV2_121 60
+#define MU_DIV2_120 60
+#define MU_DIV2_119 59
+#define MU_DIV2_118 59
+#define MU_DIV2_117 58
+#define MU_DIV2_116 58
+#define MU_DIV2_115 57
+#define MU_DIV2_114 57
+#define MU_DIV2_113 56
+#define MU_DIV2_112 56
+#define MU_DIV2_111 55
+#define MU_DIV2_110 55
+#define MU_DIV2_109 54
+#define MU_DIV2_108 54
+#define MU_DIV2_107 53
+#define MU_DIV2_106 53
+#define MU_DIV2_105 52
+#define MU_DIV2_104 52
+#define MU_DIV2_103 51
+#define MU_DIV2_102 51
+#define MU_DIV2_101 50
+#define MU_DIV2_100 50
+#define MU_DIV2_99 49
+#define MU_DIV2_98 49
+#define MU_DIV2_97 48
+#define MU_DIV2_96 48
+#define MU_DIV2_95 47
+#define MU_DIV2_94 47
+#define MU_DIV2_93 46
+#define MU_DIV2_92 46
+#define MU_DIV2_91 45
+#define MU_DIV2_90 45
+#define MU_DIV2_89 44
+#define MU_DIV2_88 44
+#define MU_DIV2_87 43
+#define MU_DIV2_86 43
+#define MU_DIV2_85 42
+#define MU_DIV2_84 42
+#define MU_DIV2_83 41
+#define MU_DIV2_82 41
+#define MU_DIV2_81 40
+#define MU_DIV2_80 40
+#define MU_DIV2_79 39
+#define MU_DIV2_78 39
+#define MU_DIV2_77 38
+#define MU_DIV2_76 38
+#define MU_DIV2_75 37
+#define MU_DIV2_74 37
+#define MU_DIV2_73 36
+#define MU_DIV2_72 36
+#define MU_DIV2_71 35
+#define MU_DIV2_70 35
+#define MU_DIV2_69 34
+#define MU_DIV2_68 34
+#define MU_DIV2_67 33
+#define MU_DIV2_66 33
+#define MU_DIV2_65 32
+#define MU_DIV2_64 32
+#define MU_DIV2_63 31
+#define MU_DIV2_62 31
+#define MU_DIV2_61 30
+#define MU_DIV2_60 30
+#define MU_DIV2_59 29
+#define MU_DIV2_58 29
+#define MU_DIV2_57 28
+#define MU_DIV2_56 28
+#define MU_DIV2_55 27
+#define MU_DIV2_54 27
+#define MU_DIV2_53 26
+#define MU_DIV2_52 26
+#define MU_DIV2_51 25
+#define MU_DIV2_50 25
+#define MU_DIV2_49 24
+#define MU_DIV2_48 24
+#define MU_DIV2_47 23
+#define MU_DIV2_46 23
+#define MU_DIV2_45 22
+#define MU_DIV2_44 22
+#define MU_DIV2_43 21
+#define MU_DIV2_42 21
+#define MU_DIV2_41 20
+#define MU_DIV2_40 20
+#define MU_DIV2_39 19
+#define MU_DIV2_38 19
+#define MU_DIV2_37 18
+#define MU_DIV2_36 18
+#define MU_DIV2_35 17
+#define MU_DIV2_34 17
+#define MU_DIV2_33 16
+#define MU_DIV2_32 16
+#define MU_DIV2_31 15
+#define MU_DIV2_30 15
+#define MU_DIV2_29 14
+#define MU_DIV2_28 14
+#define MU_DIV2_27 13
+#define MU_DIV2_26 13
+#define MU_DIV2_25 12
+#define MU_DIV2_24 12
+#define MU_DIV2_23 11
+#define MU_DIV2_22 11
+#define MU_DIV2_21 10
+#define MU_DIV2_20 10
+#define MU_DIV2_19 9
+#define MU_DIV2_18 9
+#define MU_DIV2_17 8
+#define MU_DIV2_16 8
+#define MU_DIV2_15 7
+#define MU_DIV2_14 7
+#define MU_DIV2_13 6
+#define MU_DIV2_12 6
+#define MU_DIV2_11 5
+#define MU_DIV2_10 5
+#define MU_DIV2_9 4
+#define MU_DIV2_8 4
+#define MU_DIV2_7 3
+#define MU_DIV2_6 3
+#define MU_DIV2_5 2
+#define MU_DIV2_4 2
+#define MU_DIV2_3 1
+#define MU_DIV2_2 1
+#define MU_DIV2_1 0
+#define MU_DIV2_0 0
+
+#define MU_MOD2(x) MU_C2(MU_MOD2_,x)
+#define MU_MOD2_2048 0
+#define MU_MOD2_2047 1
+#define MU_MOD2_2046 0
+#define MU_MOD2_2045 1
+#define MU_MOD2_2044 0
+#define MU_MOD2_2043 1
+#define MU_MOD2_2042 0
+#define MU_MOD2_2041 1
+#define MU_MOD2_2040 0
+#define MU_MOD2_2039 1
+#define MU_MOD2_2038 0
+#define MU_MOD2_2037 1
+#define MU_MOD2_2036 0
+#define MU_MOD2_2035 1
+#define MU_MOD2_2034 0
+#define MU_MOD2_2033 1
+#define MU_MOD2_2032 0
+#define MU_MOD2_2031 1
+#define MU_MOD2_2030 0
+#define MU_MOD2_2029 1
+#define MU_MOD2_2028 0
+#define MU_MOD2_2027 1
+#define MU_MOD2_2026 0
+#define MU_MOD2_2025 1
+#define MU_MOD2_2024 0
+#define MU_MOD2_2023 1
+#define MU_MOD2_2022 0
+#define MU_MOD2_2021 1
+#define MU_MOD2_2020 0
+#define MU_MOD2_2019 1
+#define MU_MOD2_2018 0
+#define MU_MOD2_2017 1
+#define MU_MOD2_2016 0
+#define MU_MOD2_2015 1
+#define MU_MOD2_2014 0
+#define MU_MOD2_2013 1
+#define MU_MOD2_2012 0
+#define MU_MOD2_2011 1
+#define MU_MOD2_2010 0
+#define MU_MOD2_2009 1
+#define MU_MOD2_2008 0
+#define MU_MOD2_2007 1
+#define MU_MOD2_2006 0
+#define MU_MOD2_2005 1
+#define MU_MOD2_2004 0
+#define MU_MOD2_2003 1
+#define MU_MOD2_2002 0
+#define MU_MOD2_2001 1
+#define MU_MOD2_2000 0
+#define MU_MOD2_1999 1
+#define MU_MOD2_1998 0
+#define MU_MOD2_1997 1
+#define MU_MOD2_1996 0
+#define MU_MOD2_1995 1
+#define MU_MOD2_1994 0
+#define MU_MOD2_1993 1
+#define MU_MOD2_1992 0
+#define MU_MOD2_1991 1
+#define MU_MOD2_1990 0
+#define MU_MOD2_1989 1
+#define MU_MOD2_1988 0
+#define MU_MOD2_1987 1
+#define MU_MOD2_1986 0
+#define MU_MOD2_1985 1
+#define MU_MOD2_1984 0
+#define MU_MOD2_1983 1
+#define MU_MOD2_1982 0
+#define MU_MOD2_1981 1
+#define MU_MOD2_1980 0
+#define MU_MOD2_1979 1
+#define MU_MOD2_1978 0
+#define MU_MOD2_1977 1
+#define MU_MOD2_1976 0
+#define MU_MOD2_1975 1
+#define MU_MOD2_1974 0
+#define MU_MOD2_1973 1
+#define MU_MOD2_1972 0
+#define MU_MOD2_1971 1
+#define MU_MOD2_1970 0
+#define MU_MOD2_1969 1
+#define MU_MOD2_1968 0
+#define MU_MOD2_1967 1
+#define MU_MOD2_1966 0
+#define MU_MOD2_1965 1
+#define MU_MOD2_1964 0
+#define MU_MOD2_1963 1
+#define MU_MOD2_1962 0
+#define MU_MOD2_1961 1
+#define MU_MOD2_1960 0
+#define MU_MOD2_1959 1
+#define MU_MOD2_1958 0
+#define MU_MOD2_1957 1
+#define MU_MOD2_1956 0
+#define MU_MOD2_1955 1
+#define MU_MOD2_1954 0
+#define MU_MOD2_1953 1
+#define MU_MOD2_1952 0
+#define MU_MOD2_1951 1
+#define MU_MOD2_1950 0
+#define MU_MOD2_1949 1
+#define MU_MOD2_1948 0
+#define MU_MOD2_1947 1
+#define MU_MOD2_1946 0
+#define MU_MOD2_1945 1
+#define MU_MOD2_1944 0
+#define MU_MOD2_1943 1
+#define MU_MOD2_1942 0
+#define MU_MOD2_1941 1
+#define MU_MOD2_1940 0
+#define MU_MOD2_1939 1
+#define MU_MOD2_1938 0
+#define MU_MOD2_1937 1
+#define MU_MOD2_1936 0
+#define MU_MOD2_1935 1
+#define MU_MOD2_1934 0
+#define MU_MOD2_1933 1
+#define MU_MOD2_1932 0
+#define MU_MOD2_1931 1
+#define MU_MOD2_1930 0
+#define MU_MOD2_1929 1
+#define MU_MOD2_1928 0
+#define MU_MOD2_1927 1
+#define MU_MOD2_1926 0
+#define MU_MOD2_1925 1
+#define MU_MOD2_1924 0
+#define MU_MOD2_1923 1
+#define MU_MOD2_1922 0
+#define MU_MOD2_1921 1
+#define MU_MOD2_1920 0
+#define MU_MOD2_1919 1
+#define MU_MOD2_1918 0
+#define MU_MOD2_1917 1
+#define MU_MOD2_1916 0
+#define MU_MOD2_1915 1
+#define MU_MOD2_1914 0
+#define MU_MOD2_1913 1
+#define MU_MOD2_1912 0
+#define MU_MOD2_1911 1
+#define MU_MOD2_1910 0
+#define MU_MOD2_1909 1
+#define MU_MOD2_1908 0
+#define MU_MOD2_1907 1
+#define MU_MOD2_1906 0
+#define MU_MOD2_1905 1
+#define MU_MOD2_1904 0
+#define MU_MOD2_1903 1
+#define MU_MOD2_1902 0
+#define MU_MOD2_1901 1
+#define MU_MOD2_1900 0
+#define MU_MOD2_1899 1
+#define MU_MOD2_1898 0
+#define MU_MOD2_1897 1
+#define MU_MOD2_1896 0
+#define MU_MOD2_1895 1
+#define MU_MOD2_1894 0
+#define MU_MOD2_1893 1
+#define MU_MOD2_1892 0
+#define MU_MOD2_1891 1
+#define MU_MOD2_1890 0
+#define MU_MOD2_1889 1
+#define MU_MOD2_1888 0
+#define MU_MOD2_1887 1
+#define MU_MOD2_1886 0
+#define MU_MOD2_1885 1
+#define MU_MOD2_1884 0
+#define MU_MOD2_1883 1
+#define MU_MOD2_1882 0
+#define MU_MOD2_1881 1
+#define MU_MOD2_1880 0
+#define MU_MOD2_1879 1
+#define MU_MOD2_1878 0
+#define MU_MOD2_1877 1
+#define MU_MOD2_1876 0
+#define MU_MOD2_1875 1
+#define MU_MOD2_1874 0
+#define MU_MOD2_1873 1
+#define MU_MOD2_1872 0
+#define MU_MOD2_1871 1
+#define MU_MOD2_1870 0
+#define MU_MOD2_1869 1
+#define MU_MOD2_1868 0
+#define MU_MOD2_1867 1
+#define MU_MOD2_1866 0
+#define MU_MOD2_1865 1
+#define MU_MOD2_1864 0
+#define MU_MOD2_1863 1
+#define MU_MOD2_1862 0
+#define MU_MOD2_1861 1
+#define MU_MOD2_1860 0
+#define MU_MOD2_1859 1
+#define MU_MOD2_1858 0
+#define MU_MOD2_1857 1
+#define MU_MOD2_1856 0
+#define MU_MOD2_1855 1
+#define MU_MOD2_1854 0
+#define MU_MOD2_1853 1
+#define MU_MOD2_1852 0
+#define MU_MOD2_1851 1
+#define MU_MOD2_1850 0
+#define MU_MOD2_1849 1
+#define MU_MOD2_1848 0
+#define MU_MOD2_1847 1
+#define MU_MOD2_1846 0
+#define MU_MOD2_1845 1
+#define MU_MOD2_1844 0
+#define MU_MOD2_1843 1
+#define MU_MOD2_1842 0
+#define MU_MOD2_1841 1
+#define MU_MOD2_1840 0
+#define MU_MOD2_1839 1
+#define MU_MOD2_1838 0
+#define MU_MOD2_1837 1
+#define MU_MOD2_1836 0
+#define MU_MOD2_1835 1
+#define MU_MOD2_1834 0
+#define MU_MOD2_1833 1
+#define MU_MOD2_1832 0
+#define MU_MOD2_1831 1
+#define MU_MOD2_1830 0
+#define MU_MOD2_1829 1
+#define MU_MOD2_1828 0
+#define MU_MOD2_1827 1
+#define MU_MOD2_1826 0
+#define MU_MOD2_1825 1
+#define MU_MOD2_1824 0
+#define MU_MOD2_1823 1
+#define MU_MOD2_1822 0
+#define MU_MOD2_1821 1
+#define MU_MOD2_1820 0
+#define MU_MOD2_1819 1
+#define MU_MOD2_1818 0
+#define MU_MOD2_1817 1
+#define MU_MOD2_1816 0
+#define MU_MOD2_1815 1
+#define MU_MOD2_1814 0
+#define MU_MOD2_1813 1
+#define MU_MOD2_1812 0
+#define MU_MOD2_1811 1
+#define MU_MOD2_1810 0
+#define MU_MOD2_1809 1
+#define MU_MOD2_1808 0
+#define MU_MOD2_1807 1
+#define MU_MOD2_1806 0
+#define MU_MOD2_1805 1
+#define MU_MOD2_1804 0
+#define MU_MOD2_1803 1
+#define MU_MOD2_1802 0
+#define MU_MOD2_1801 1
+#define MU_MOD2_1800 0
+#define MU_MOD2_1799 1
+#define MU_MOD2_1798 0
+#define MU_MOD2_1797 1
+#define MU_MOD2_1796 0
+#define MU_MOD2_1795 1
+#define MU_MOD2_1794 0
+#define MU_MOD2_1793 1
+#define MU_MOD2_1792 0
+#define MU_MOD2_1791 1
+#define MU_MOD2_1790 0
+#define MU_MOD2_1789 1
+#define MU_MOD2_1788 0
+#define MU_MOD2_1787 1
+#define MU_MOD2_1786 0
+#define MU_MOD2_1785 1
+#define MU_MOD2_1784 0
+#define MU_MOD2_1783 1
+#define MU_MOD2_1782 0
+#define MU_MOD2_1781 1
+#define MU_MOD2_1780 0
+#define MU_MOD2_1779 1
+#define MU_MOD2_1778 0
+#define MU_MOD2_1777 1
+#define MU_MOD2_1776 0
+#define MU_MOD2_1775 1
+#define MU_MOD2_1774 0
+#define MU_MOD2_1773 1
+#define MU_MOD2_1772 0
+#define MU_MOD2_1771 1
+#define MU_MOD2_1770 0
+#define MU_MOD2_1769 1
+#define MU_MOD2_1768 0
+#define MU_MOD2_1767 1
+#define MU_MOD2_1766 0
+#define MU_MOD2_1765 1
+#define MU_MOD2_1764 0
+#define MU_MOD2_1763 1
+#define MU_MOD2_1762 0
+#define MU_MOD2_1761 1
+#define MU_MOD2_1760 0
+#define MU_MOD2_1759 1
+#define MU_MOD2_1758 0
+#define MU_MOD2_1757 1
+#define MU_MOD2_1756 0
+#define MU_MOD2_1755 1
+#define MU_MOD2_1754 0
+#define MU_MOD2_1753 1
+#define MU_MOD2_1752 0
+#define MU_MOD2_1751 1
+#define MU_MOD2_1750 0
+#define MU_MOD2_1749 1
+#define MU_MOD2_1748 0
+#define MU_MOD2_1747 1
+#define MU_MOD2_1746 0
+#define MU_MOD2_1745 1
+#define MU_MOD2_1744 0
+#define MU_MOD2_1743 1
+#define MU_MOD2_1742 0
+#define MU_MOD2_1741 1
+#define MU_MOD2_1740 0
+#define MU_MOD2_1739 1
+#define MU_MOD2_1738 0
+#define MU_MOD2_1737 1
+#define MU_MOD2_1736 0
+#define MU_MOD2_1735 1
+#define MU_MOD2_1734 0
+#define MU_MOD2_1733 1
+#define MU_MOD2_1732 0
+#define MU_MOD2_1731 1
+#define MU_MOD2_1730 0
+#define MU_MOD2_1729 1
+#define MU_MOD2_1728 0
+#define MU_MOD2_1727 1
+#define MU_MOD2_1726 0
+#define MU_MOD2_1725 1
+#define MU_MOD2_1724 0
+#define MU_MOD2_1723 1
+#define MU_MOD2_1722 0
+#define MU_MOD2_1721 1
+#define MU_MOD2_1720 0
+#define MU_MOD2_1719 1
+#define MU_MOD2_1718 0
+#define MU_MOD2_1717 1
+#define MU_MOD2_1716 0
+#define MU_MOD2_1715 1
+#define MU_MOD2_1714 0
+#define MU_MOD2_1713 1
+#define MU_MOD2_1712 0
+#define MU_MOD2_1711 1
+#define MU_MOD2_1710 0
+#define MU_MOD2_1709 1
+#define MU_MOD2_1708 0
+#define MU_MOD2_1707 1
+#define MU_MOD2_1706 0
+#define MU_MOD2_1705 1
+#define MU_MOD2_1704 0
+#define MU_MOD2_1703 1
+#define MU_MOD2_1702 0
+#define MU_MOD2_1701 1
+#define MU_MOD2_1700 0
+#define MU_MOD2_1699 1
+#define MU_MOD2_1698 0
+#define MU_MOD2_1697 1
+#define MU_MOD2_1696 0
+#define MU_MOD2_1695 1
+#define MU_MOD2_1694 0
+#define MU_MOD2_1693 1
+#define MU_MOD2_1692 0
+#define MU_MOD2_1691 1
+#define MU_MOD2_1690 0
+#define MU_MOD2_1689 1
+#define MU_MOD2_1688 0
+#define MU_MOD2_1687 1
+#define MU_MOD2_1686 0
+#define MU_MOD2_1685 1
+#define MU_MOD2_1684 0
+#define MU_MOD2_1683 1
+#define MU_MOD2_1682 0
+#define MU_MOD2_1681 1
+#define MU_MOD2_1680 0
+#define MU_MOD2_1679 1
+#define MU_MOD2_1678 0
+#define MU_MOD2_1677 1
+#define MU_MOD2_1676 0
+#define MU_MOD2_1675 1
+#define MU_MOD2_1674 0
+#define MU_MOD2_1673 1
+#define MU_MOD2_1672 0
+#define MU_MOD2_1671 1
+#define MU_MOD2_1670 0
+#define MU_MOD2_1669 1
+#define MU_MOD2_1668 0
+#define MU_MOD2_1667 1
+#define MU_MOD2_1666 0
+#define MU_MOD2_1665 1
+#define MU_MOD2_1664 0
+#define MU_MOD2_1663 1
+#define MU_MOD2_1662 0
+#define MU_MOD2_1661 1
+#define MU_MOD2_1660 0
+#define MU_MOD2_1659 1
+#define MU_MOD2_1658 0
+#define MU_MOD2_1657 1
+#define MU_MOD2_1656 0
+#define MU_MOD2_1655 1
+#define MU_MOD2_1654 0
+#define MU_MOD2_1653 1
+#define MU_MOD2_1652 0
+#define MU_MOD2_1651 1
+#define MU_MOD2_1650 0
+#define MU_MOD2_1649 1
+#define MU_MOD2_1648 0
+#define MU_MOD2_1647 1
+#define MU_MOD2_1646 0
+#define MU_MOD2_1645 1
+#define MU_MOD2_1644 0
+#define MU_MOD2_1643 1
+#define MU_MOD2_1642 0
+#define MU_MOD2_1641 1
+#define MU_MOD2_1640 0
+#define MU_MOD2_1639 1
+#define MU_MOD2_1638 0
+#define MU_MOD2_1637 1
+#define MU_MOD2_1636 0
+#define MU_MOD2_1635 1
+#define MU_MOD2_1634 0
+#define MU_MOD2_1633 1
+#define MU_MOD2_1632 0
+#define MU_MOD2_1631 1
+#define MU_MOD2_1630 0
+#define MU_MOD2_1629 1
+#define MU_MOD2_1628 0
+#define MU_MOD2_1627 1
+#define MU_MOD2_1626 0
+#define MU_MOD2_1625 1
+#define MU_MOD2_1624 0
+#define MU_MOD2_1623 1
+#define MU_MOD2_1622 0
+#define MU_MOD2_1621 1
+#define MU_MOD2_1620 0
+#define MU_MOD2_1619 1
+#define MU_MOD2_1618 0
+#define MU_MOD2_1617 1
+#define MU_MOD2_1616 0
+#define MU_MOD2_1615 1
+#define MU_MOD2_1614 0
+#define MU_MOD2_1613 1
+#define MU_MOD2_1612 0
+#define MU_MOD2_1611 1
+#define MU_MOD2_1610 0
+#define MU_MOD2_1609 1
+#define MU_MOD2_1608 0
+#define MU_MOD2_1607 1
+#define MU_MOD2_1606 0
+#define MU_MOD2_1605 1
+#define MU_MOD2_1604 0
+#define MU_MOD2_1603 1
+#define MU_MOD2_1602 0
+#define MU_MOD2_1601 1
+#define MU_MOD2_1600 0
+#define MU_MOD2_1599 1
+#define MU_MOD2_1598 0
+#define MU_MOD2_1597 1
+#define MU_MOD2_1596 0
+#define MU_MOD2_1595 1
+#define MU_MOD2_1594 0
+#define MU_MOD2_1593 1
+#define MU_MOD2_1592 0
+#define MU_MOD2_1591 1
+#define MU_MOD2_1590 0
+#define MU_MOD2_1589 1
+#define MU_MOD2_1588 0
+#define MU_MOD2_1587 1
+#define MU_MOD2_1586 0
+#define MU_MOD2_1585 1
+#define MU_MOD2_1584 0
+#define MU_MOD2_1583 1
+#define MU_MOD2_1582 0
+#define MU_MOD2_1581 1
+#define MU_MOD2_1580 0
+#define MU_MOD2_1579 1
+#define MU_MOD2_1578 0
+#define MU_MOD2_1577 1
+#define MU_MOD2_1576 0
+#define MU_MOD2_1575 1
+#define MU_MOD2_1574 0
+#define MU_MOD2_1573 1
+#define MU_MOD2_1572 0
+#define MU_MOD2_1571 1
+#define MU_MOD2_1570 0
+#define MU_MOD2_1569 1
+#define MU_MOD2_1568 0
+#define MU_MOD2_1567 1
+#define MU_MOD2_1566 0
+#define MU_MOD2_1565 1
+#define MU_MOD2_1564 0
+#define MU_MOD2_1563 1
+#define MU_MOD2_1562 0
+#define MU_MOD2_1561 1
+#define MU_MOD2_1560 0
+#define MU_MOD2_1559 1
+#define MU_MOD2_1558 0
+#define MU_MOD2_1557 1
+#define MU_MOD2_1556 0
+#define MU_MOD2_1555 1
+#define MU_MOD2_1554 0
+#define MU_MOD2_1553 1
+#define MU_MOD2_1552 0
+#define MU_MOD2_1551 1
+#define MU_MOD2_1550 0
+#define MU_MOD2_1549 1
+#define MU_MOD2_1548 0
+#define MU_MOD2_1547 1
+#define MU_MOD2_1546 0
+#define MU_MOD2_1545 1
+#define MU_MOD2_1544 0
+#define MU_MOD2_1543 1
+#define MU_MOD2_1542 0
+#define MU_MOD2_1541 1
+#define MU_MOD2_1540 0
+#define MU_MOD2_1539 1
+#define MU_MOD2_1538 0
+#define MU_MOD2_1537 1
+#define MU_MOD2_1536 0
+#define MU_MOD2_1535 1
+#define MU_MOD2_1534 0
+#define MU_MOD2_1533 1
+#define MU_MOD2_1532 0
+#define MU_MOD2_1531 1
+#define MU_MOD2_1530 0
+#define MU_MOD2_1529 1
+#define MU_MOD2_1528 0
+#define MU_MOD2_1527 1
+#define MU_MOD2_1526 0
+#define MU_MOD2_1525 1
+#define MU_MOD2_1524 0
+#define MU_MOD2_1523 1
+#define MU_MOD2_1522 0
+#define MU_MOD2_1521 1
+#define MU_MOD2_1520 0
+#define MU_MOD2_1519 1
+#define MU_MOD2_1518 0
+#define MU_MOD2_1517 1
+#define MU_MOD2_1516 0
+#define MU_MOD2_1515 1
+#define MU_MOD2_1514 0
+#define MU_MOD2_1513 1
+#define MU_MOD2_1512 0
+#define MU_MOD2_1511 1
+#define MU_MOD2_1510 0
+#define MU_MOD2_1509 1
+#define MU_MOD2_1508 0
+#define MU_MOD2_1507 1
+#define MU_MOD2_1506 0
+#define MU_MOD2_1505 1
+#define MU_MOD2_1504 0
+#define MU_MOD2_1503 1
+#define MU_MOD2_1502 0
+#define MU_MOD2_1501 1
+#define MU_MOD2_1500 0
+#define MU_MOD2_1499 1
+#define MU_MOD2_1498 0
+#define MU_MOD2_1497 1
+#define MU_MOD2_1496 0
+#define MU_MOD2_1495 1
+#define MU_MOD2_1494 0
+#define MU_MOD2_1493 1
+#define MU_MOD2_1492 0
+#define MU_MOD2_1491 1
+#define MU_MOD2_1490 0
+#define MU_MOD2_1489 1
+#define MU_MOD2_1488 0
+#define MU_MOD2_1487 1
+#define MU_MOD2_1486 0
+#define MU_MOD2_1485 1
+#define MU_MOD2_1484 0
+#define MU_MOD2_1483 1
+#define MU_MOD2_1482 0
+#define MU_MOD2_1481 1
+#define MU_MOD2_1480 0
+#define MU_MOD2_1479 1
+#define MU_MOD2_1478 0
+#define MU_MOD2_1477 1
+#define MU_MOD2_1476 0
+#define MU_MOD2_1475 1
+#define MU_MOD2_1474 0
+#define MU_MOD2_1473 1
+#define MU_MOD2_1472 0
+#define MU_MOD2_1471 1
+#define MU_MOD2_1470 0
+#define MU_MOD2_1469 1
+#define MU_MOD2_1468 0
+#define MU_MOD2_1467 1
+#define MU_MOD2_1466 0
+#define MU_MOD2_1465 1
+#define MU_MOD2_1464 0
+#define MU_MOD2_1463 1
+#define MU_MOD2_1462 0
+#define MU_MOD2_1461 1
+#define MU_MOD2_1460 0
+#define MU_MOD2_1459 1
+#define MU_MOD2_1458 0
+#define MU_MOD2_1457 1
+#define MU_MOD2_1456 0
+#define MU_MOD2_1455 1
+#define MU_MOD2_1454 0
+#define MU_MOD2_1453 1
+#define MU_MOD2_1452 0
+#define MU_MOD2_1451 1
+#define MU_MOD2_1450 0
+#define MU_MOD2_1449 1
+#define MU_MOD2_1448 0
+#define MU_MOD2_1447 1
+#define MU_MOD2_1446 0
+#define MU_MOD2_1445 1
+#define MU_MOD2_1444 0
+#define MU_MOD2_1443 1
+#define MU_MOD2_1442 0
+#define MU_MOD2_1441 1
+#define MU_MOD2_1440 0
+#define MU_MOD2_1439 1
+#define MU_MOD2_1438 0
+#define MU_MOD2_1437 1
+#define MU_MOD2_1436 0
+#define MU_MOD2_1435 1
+#define MU_MOD2_1434 0
+#define MU_MOD2_1433 1
+#define MU_MOD2_1432 0
+#define MU_MOD2_1431 1
+#define MU_MOD2_1430 0
+#define MU_MOD2_1429 1
+#define MU_MOD2_1428 0
+#define MU_MOD2_1427 1
+#define MU_MOD2_1426 0
+#define MU_MOD2_1425 1
+#define MU_MOD2_1424 0
+#define MU_MOD2_1423 1
+#define MU_MOD2_1422 0
+#define MU_MOD2_1421 1
+#define MU_MOD2_1420 0
+#define MU_MOD2_1419 1
+#define MU_MOD2_1418 0
+#define MU_MOD2_1417 1
+#define MU_MOD2_1416 0
+#define MU_MOD2_1415 1
+#define MU_MOD2_1414 0
+#define MU_MOD2_1413 1
+#define MU_MOD2_1412 0
+#define MU_MOD2_1411 1
+#define MU_MOD2_1410 0
+#define MU_MOD2_1409 1
+#define MU_MOD2_1408 0
+#define MU_MOD2_1407 1
+#define MU_MOD2_1406 0
+#define MU_MOD2_1405 1
+#define MU_MOD2_1404 0
+#define MU_MOD2_1403 1
+#define MU_MOD2_1402 0
+#define MU_MOD2_1401 1
+#define MU_MOD2_1400 0
+#define MU_MOD2_1399 1
+#define MU_MOD2_1398 0
+#define MU_MOD2_1397 1
+#define MU_MOD2_1396 0
+#define MU_MOD2_1395 1
+#define MU_MOD2_1394 0
+#define MU_MOD2_1393 1
+#define MU_MOD2_1392 0
+#define MU_MOD2_1391 1
+#define MU_MOD2_1390 0
+#define MU_MOD2_1389 1
+#define MU_MOD2_1388 0
+#define MU_MOD2_1387 1
+#define MU_MOD2_1386 0
+#define MU_MOD2_1385 1
+#define MU_MOD2_1384 0
+#define MU_MOD2_1383 1
+#define MU_MOD2_1382 0
+#define MU_MOD2_1381 1
+#define MU_MOD2_1380 0
+#define MU_MOD2_1379 1
+#define MU_MOD2_1378 0
+#define MU_MOD2_1377 1
+#define MU_MOD2_1376 0
+#define MU_MOD2_1375 1
+#define MU_MOD2_1374 0
+#define MU_MOD2_1373 1
+#define MU_MOD2_1372 0
+#define MU_MOD2_1371 1
+#define MU_MOD2_1370 0
+#define MU_MOD2_1369 1
+#define MU_MOD2_1368 0
+#define MU_MOD2_1367 1
+#define MU_MOD2_1366 0
+#define MU_MOD2_1365 1
+#define MU_MOD2_1364 0
+#define MU_MOD2_1363 1
+#define MU_MOD2_1362 0
+#define MU_MOD2_1361 1
+#define MU_MOD2_1360 0
+#define MU_MOD2_1359 1
+#define MU_MOD2_1358 0
+#define MU_MOD2_1357 1
+#define MU_MOD2_1356 0
+#define MU_MOD2_1355 1
+#define MU_MOD2_1354 0
+#define MU_MOD2_1353 1
+#define MU_MOD2_1352 0
+#define MU_MOD2_1351 1
+#define MU_MOD2_1350 0
+#define MU_MOD2_1349 1
+#define MU_MOD2_1348 0
+#define MU_MOD2_1347 1
+#define MU_MOD2_1346 0
+#define MU_MOD2_1345 1
+#define MU_MOD2_1344 0
+#define MU_MOD2_1343 1
+#define MU_MOD2_1342 0
+#define MU_MOD2_1341 1
+#define MU_MOD2_1340 0
+#define MU_MOD2_1339 1
+#define MU_MOD2_1338 0
+#define MU_MOD2_1337 1
+#define MU_MOD2_1336 0
+#define MU_MOD2_1335 1
+#define MU_MOD2_1334 0
+#define MU_MOD2_1333 1
+#define MU_MOD2_1332 0
+#define MU_MOD2_1331 1
+#define MU_MOD2_1330 0
+#define MU_MOD2_1329 1
+#define MU_MOD2_1328 0
+#define MU_MOD2_1327 1
+#define MU_MOD2_1326 0
+#define MU_MOD2_1325 1
+#define MU_MOD2_1324 0
+#define MU_MOD2_1323 1
+#define MU_MOD2_1322 0
+#define MU_MOD2_1321 1
+#define MU_MOD2_1320 0
+#define MU_MOD2_1319 1
+#define MU_MOD2_1318 0
+#define MU_MOD2_1317 1
+#define MU_MOD2_1316 0
+#define MU_MOD2_1315 1
+#define MU_MOD2_1314 0
+#define MU_MOD2_1313 1
+#define MU_MOD2_1312 0
+#define MU_MOD2_1311 1
+#define MU_MOD2_1310 0
+#define MU_MOD2_1309 1
+#define MU_MOD2_1308 0
+#define MU_MOD2_1307 1
+#define MU_MOD2_1306 0
+#define MU_MOD2_1305 1
+#define MU_MOD2_1304 0
+#define MU_MOD2_1303 1
+#define MU_MOD2_1302 0
+#define MU_MOD2_1301 1
+#define MU_MOD2_1300 0
+#define MU_MOD2_1299 1
+#define MU_MOD2_1298 0
+#define MU_MOD2_1297 1
+#define MU_MOD2_1296 0
+#define MU_MOD2_1295 1
+#define MU_MOD2_1294 0
+#define MU_MOD2_1293 1
+#define MU_MOD2_1292 0
+#define MU_MOD2_1291 1
+#define MU_MOD2_1290 0
+#define MU_MOD2_1289 1
+#define MU_MOD2_1288 0
+#define MU_MOD2_1287 1
+#define MU_MOD2_1286 0
+#define MU_MOD2_1285 1
+#define MU_MOD2_1284 0
+#define MU_MOD2_1283 1
+#define MU_MOD2_1282 0
+#define MU_MOD2_1281 1
+#define MU_MOD2_1280 0
+#define MU_MOD2_1279 1
+#define MU_MOD2_1278 0
+#define MU_MOD2_1277 1
+#define MU_MOD2_1276 0
+#define MU_MOD2_1275 1
+#define MU_MOD2_1274 0
+#define MU_MOD2_1273 1
+#define MU_MOD2_1272 0
+#define MU_MOD2_1271 1
+#define MU_MOD2_1270 0
+#define MU_MOD2_1269 1
+#define MU_MOD2_1268 0
+#define MU_MOD2_1267 1
+#define MU_MOD2_1266 0
+#define MU_MOD2_1265 1
+#define MU_MOD2_1264 0
+#define MU_MOD2_1263 1
+#define MU_MOD2_1262 0
+#define MU_MOD2_1261 1
+#define MU_MOD2_1260 0
+#define MU_MOD2_1259 1
+#define MU_MOD2_1258 0
+#define MU_MOD2_1257 1
+#define MU_MOD2_1256 0
+#define MU_MOD2_1255 1
+#define MU_MOD2_1254 0
+#define MU_MOD2_1253 1
+#define MU_MOD2_1252 0
+#define MU_MOD2_1251 1
+#define MU_MOD2_1250 0
+#define MU_MOD2_1249 1
+#define MU_MOD2_1248 0
+#define MU_MOD2_1247 1
+#define MU_MOD2_1246 0
+#define MU_MOD2_1245 1
+#define MU_MOD2_1244 0
+#define MU_MOD2_1243 1
+#define MU_MOD2_1242 0
+#define MU_MOD2_1241 1
+#define MU_MOD2_1240 0
+#define MU_MOD2_1239 1
+#define MU_MOD2_1238 0
+#define MU_MOD2_1237 1
+#define MU_MOD2_1236 0
+#define MU_MOD2_1235 1
+#define MU_MOD2_1234 0
+#define MU_MOD2_1233 1
+#define MU_MOD2_1232 0
+#define MU_MOD2_1231 1
+#define MU_MOD2_1230 0
+#define MU_MOD2_1229 1
+#define MU_MOD2_1228 0
+#define MU_MOD2_1227 1
+#define MU_MOD2_1226 0
+#define MU_MOD2_1225 1
+#define MU_MOD2_1224 0
+#define MU_MOD2_1223 1
+#define MU_MOD2_1222 0
+#define MU_MOD2_1221 1
+#define MU_MOD2_1220 0
+#define MU_MOD2_1219 1
+#define MU_MOD2_1218 0
+#define MU_MOD2_1217 1
+#define MU_MOD2_1216 0
+#define MU_MOD2_1215 1
+#define MU_MOD2_1214 0
+#define MU_MOD2_1213 1
+#define MU_MOD2_1212 0
+#define MU_MOD2_1211 1
+#define MU_MOD2_1210 0
+#define MU_MOD2_1209 1
+#define MU_MOD2_1208 0
+#define MU_MOD2_1207 1
+#define MU_MOD2_1206 0
+#define MU_MOD2_1205 1
+#define MU_MOD2_1204 0
+#define MU_MOD2_1203 1
+#define MU_MOD2_1202 0
+#define MU_MOD2_1201 1
+#define MU_MOD2_1200 0
+#define MU_MOD2_1199 1
+#define MU_MOD2_1198 0
+#define MU_MOD2_1197 1
+#define MU_MOD2_1196 0
+#define MU_MOD2_1195 1
+#define MU_MOD2_1194 0
+#define MU_MOD2_1193 1
+#define MU_MOD2_1192 0
+#define MU_MOD2_1191 1
+#define MU_MOD2_1190 0
+#define MU_MOD2_1189 1
+#define MU_MOD2_1188 0
+#define MU_MOD2_1187 1
+#define MU_MOD2_1186 0
+#define MU_MOD2_1185 1
+#define MU_MOD2_1184 0
+#define MU_MOD2_1183 1
+#define MU_MOD2_1182 0
+#define MU_MOD2_1181 1
+#define MU_MOD2_1180 0
+#define MU_MOD2_1179 1
+#define MU_MOD2_1178 0
+#define MU_MOD2_1177 1
+#define MU_MOD2_1176 0
+#define MU_MOD2_1175 1
+#define MU_MOD2_1174 0
+#define MU_MOD2_1173 1
+#define MU_MOD2_1172 0
+#define MU_MOD2_1171 1
+#define MU_MOD2_1170 0
+#define MU_MOD2_1169 1
+#define MU_MOD2_1168 0
+#define MU_MOD2_1167 1
+#define MU_MOD2_1166 0
+#define MU_MOD2_1165 1
+#define MU_MOD2_1164 0
+#define MU_MOD2_1163 1
+#define MU_MOD2_1162 0
+#define MU_MOD2_1161 1
+#define MU_MOD2_1160 0
+#define MU_MOD2_1159 1
+#define MU_MOD2_1158 0
+#define MU_MOD2_1157 1
+#define MU_MOD2_1156 0
+#define MU_MOD2_1155 1
+#define MU_MOD2_1154 0
+#define MU_MOD2_1153 1
+#define MU_MOD2_1152 0
+#define MU_MOD2_1151 1
+#define MU_MOD2_1150 0
+#define MU_MOD2_1149 1
+#define MU_MOD2_1148 0
+#define MU_MOD2_1147 1
+#define MU_MOD2_1146 0
+#define MU_MOD2_1145 1
+#define MU_MOD2_1144 0
+#define MU_MOD2_1143 1
+#define MU_MOD2_1142 0
+#define MU_MOD2_1141 1
+#define MU_MOD2_1140 0
+#define MU_MOD2_1139 1
+#define MU_MOD2_1138 0
+#define MU_MOD2_1137 1
+#define MU_MOD2_1136 0
+#define MU_MOD2_1135 1
+#define MU_MOD2_1134 0
+#define MU_MOD2_1133 1
+#define MU_MOD2_1132 0
+#define MU_MOD2_1131 1
+#define MU_MOD2_1130 0
+#define MU_MOD2_1129 1
+#define MU_MOD2_1128 0
+#define MU_MOD2_1127 1
+#define MU_MOD2_1126 0
+#define MU_MOD2_1125 1
+#define MU_MOD2_1124 0
+#define MU_MOD2_1123 1
+#define MU_MOD2_1122 0
+#define MU_MOD2_1121 1
+#define MU_MOD2_1120 0
+#define MU_MOD2_1119 1
+#define MU_MOD2_1118 0
+#define MU_MOD2_1117 1
+#define MU_MOD2_1116 0
+#define MU_MOD2_1115 1
+#define MU_MOD2_1114 0
+#define MU_MOD2_1113 1
+#define MU_MOD2_1112 0
+#define MU_MOD2_1111 1
+#define MU_MOD2_1110 0
+#define MU_MOD2_1109 1
+#define MU_MOD2_1108 0
+#define MU_MOD2_1107 1
+#define MU_MOD2_1106 0
+#define MU_MOD2_1105 1
+#define MU_MOD2_1104 0
+#define MU_MOD2_1103 1
+#define MU_MOD2_1102 0
+#define MU_MOD2_1101 1
+#define MU_MOD2_1100 0
+#define MU_MOD2_1099 1
+#define MU_MOD2_1098 0
+#define MU_MOD2_1097 1
+#define MU_MOD2_1096 0
+#define MU_MOD2_1095 1
+#define MU_MOD2_1094 0
+#define MU_MOD2_1093 1
+#define MU_MOD2_1092 0
+#define MU_MOD2_1091 1
+#define MU_MOD2_1090 0
+#define MU_MOD2_1089 1
+#define MU_MOD2_1088 0
+#define MU_MOD2_1087 1
+#define MU_MOD2_1086 0
+#define MU_MOD2_1085 1
+#define MU_MOD2_1084 0
+#define MU_MOD2_1083 1
+#define MU_MOD2_1082 0
+#define MU_MOD2_1081 1
+#define MU_MOD2_1080 0
+#define MU_MOD2_1079 1
+#define MU_MOD2_1078 0
+#define MU_MOD2_1077 1
+#define MU_MOD2_1076 0
+#define MU_MOD2_1075 1
+#define MU_MOD2_1074 0
+#define MU_MOD2_1073 1
+#define MU_MOD2_1072 0
+#define MU_MOD2_1071 1
+#define MU_MOD2_1070 0
+#define MU_MOD2_1069 1
+#define MU_MOD2_1068 0
+#define MU_MOD2_1067 1
+#define MU_MOD2_1066 0
+#define MU_MOD2_1065 1
+#define MU_MOD2_1064 0
+#define MU_MOD2_1063 1
+#define MU_MOD2_1062 0
+#define MU_MOD2_1061 1
+#define MU_MOD2_1060 0
+#define MU_MOD2_1059 1
+#define MU_MOD2_1058 0
+#define MU_MOD2_1057 1
+#define MU_MOD2_1056 0
+#define MU_MOD2_1055 1
+#define MU_MOD2_1054 0
+#define MU_MOD2_1053 1
+#define MU_MOD2_1052 0
+#define MU_MOD2_1051 1
+#define MU_MOD2_1050 0
+#define MU_MOD2_1049 1
+#define MU_MOD2_1048 0
+#define MU_MOD2_1047 1
+#define MU_MOD2_1046 0
+#define MU_MOD2_1045 1
+#define MU_MOD2_1044 0
+#define MU_MOD2_1043 1
+#define MU_MOD2_1042 0
+#define MU_MOD2_1041 1
+#define MU_MOD2_1040 0
+#define MU_MOD2_1039 1
+#define MU_MOD2_1038 0
+#define MU_MOD2_1037 1
+#define MU_MOD2_1036 0
+#define MU_MOD2_1035 1
+#define MU_MOD2_1034 0
+#define MU_MOD2_1033 1
+#define MU_MOD2_1032 0
+#define MU_MOD2_1031 1
+#define MU_MOD2_1030 0
+#define MU_MOD2_1029 1
+#define MU_MOD2_1028 0
+#define MU_MOD2_1027 1
+#define MU_MOD2_1026 0
+#define MU_MOD2_1025 1
+#define MU_MOD2_1024 0
+#define MU_MOD2_1023 1
+#define MU_MOD2_1022 0
+#define MU_MOD2_1021 1
+#define MU_MOD2_1020 0
+#define MU_MOD2_1019 1
+#define MU_MOD2_1018 0
+#define MU_MOD2_1017 1
+#define MU_MOD2_1016 0
+#define MU_MOD2_1015 1
+#define MU_MOD2_1014 0
+#define MU_MOD2_1013 1
+#define MU_MOD2_1012 0
+#define MU_MOD2_1011 1
+#define MU_MOD2_1010 0
+#define MU_MOD2_1009 1
+#define MU_MOD2_1008 0
+#define MU_MOD2_1007 1
+#define MU_MOD2_1006 0
+#define MU_MOD2_1005 1
+#define MU_MOD2_1004 0
+#define MU_MOD2_1003 1
+#define MU_MOD2_1002 0
+#define MU_MOD2_1001 1
+#define MU_MOD2_1000 0
+#define MU_MOD2_999 1
+#define MU_MOD2_998 0
+#define MU_MOD2_997 1
+#define MU_MOD2_996 0
+#define MU_MOD2_995 1
+#define MU_MOD2_994 0
+#define MU_MOD2_993 1
+#define MU_MOD2_992 0
+#define MU_MOD2_991 1
+#define MU_MOD2_990 0
+#define MU_MOD2_989 1
+#define MU_MOD2_988 0
+#define MU_MOD2_987 1
+#define MU_MOD2_986 0
+#define MU_MOD2_985 1
+#define MU_MOD2_984 0
+#define MU_MOD2_983 1
+#define MU_MOD2_982 0
+#define MU_MOD2_981 1
+#define MU_MOD2_980 0
+#define MU_MOD2_979 1
+#define MU_MOD2_978 0
+#define MU_MOD2_977 1
+#define MU_MOD2_976 0
+#define MU_MOD2_975 1
+#define MU_MOD2_974 0
+#define MU_MOD2_973 1
+#define MU_MOD2_972 0
+#define MU_MOD2_971 1
+#define MU_MOD2_970 0
+#define MU_MOD2_969 1
+#define MU_MOD2_968 0
+#define MU_MOD2_967 1
+#define MU_MOD2_966 0
+#define MU_MOD2_965 1
+#define MU_MOD2_964 0
+#define MU_MOD2_963 1
+#define MU_MOD2_962 0
+#define MU_MOD2_961 1
+#define MU_MOD2_960 0
+#define MU_MOD2_959 1
+#define MU_MOD2_958 0
+#define MU_MOD2_957 1
+#define MU_MOD2_956 0
+#define MU_MOD2_955 1
+#define MU_MOD2_954 0
+#define MU_MOD2_953 1
+#define MU_MOD2_952 0
+#define MU_MOD2_951 1
+#define MU_MOD2_950 0
+#define MU_MOD2_949 1
+#define MU_MOD2_948 0
+#define MU_MOD2_947 1
+#define MU_MOD2_946 0
+#define MU_MOD2_945 1
+#define MU_MOD2_944 0
+#define MU_MOD2_943 1
+#define MU_MOD2_942 0
+#define MU_MOD2_941 1
+#define MU_MOD2_940 0
+#define MU_MOD2_939 1
+#define MU_MOD2_938 0
+#define MU_MOD2_937 1
+#define MU_MOD2_936 0
+#define MU_MOD2_935 1
+#define MU_MOD2_934 0
+#define MU_MOD2_933 1
+#define MU_MOD2_932 0
+#define MU_MOD2_931 1
+#define MU_MOD2_930 0
+#define MU_MOD2_929 1
+#define MU_MOD2_928 0
+#define MU_MOD2_927 1
+#define MU_MOD2_926 0
+#define MU_MOD2_925 1
+#define MU_MOD2_924 0
+#define MU_MOD2_923 1
+#define MU_MOD2_922 0
+#define MU_MOD2_921 1
+#define MU_MOD2_920 0
+#define MU_MOD2_919 1
+#define MU_MOD2_918 0
+#define MU_MOD2_917 1
+#define MU_MOD2_916 0
+#define MU_MOD2_915 1
+#define MU_MOD2_914 0
+#define MU_MOD2_913 1
+#define MU_MOD2_912 0
+#define MU_MOD2_911 1
+#define MU_MOD2_910 0
+#define MU_MOD2_909 1
+#define MU_MOD2_908 0
+#define MU_MOD2_907 1
+#define MU_MOD2_906 0
+#define MU_MOD2_905 1
+#define MU_MOD2_904 0
+#define MU_MOD2_903 1
+#define MU_MOD2_902 0
+#define MU_MOD2_901 1
+#define MU_MOD2_900 0
+#define MU_MOD2_899 1
+#define MU_MOD2_898 0
+#define MU_MOD2_897 1
+#define MU_MOD2_896 0
+#define MU_MOD2_895 1
+#define MU_MOD2_894 0
+#define MU_MOD2_893 1
+#define MU_MOD2_892 0
+#define MU_MOD2_891 1
+#define MU_MOD2_890 0
+#define MU_MOD2_889 1
+#define MU_MOD2_888 0
+#define MU_MOD2_887 1
+#define MU_MOD2_886 0
+#define MU_MOD2_885 1
+#define MU_MOD2_884 0
+#define MU_MOD2_883 1
+#define MU_MOD2_882 0
+#define MU_MOD2_881 1
+#define MU_MOD2_880 0
+#define MU_MOD2_879 1
+#define MU_MOD2_878 0
+#define MU_MOD2_877 1
+#define MU_MOD2_876 0
+#define MU_MOD2_875 1
+#define MU_MOD2_874 0
+#define MU_MOD2_873 1
+#define MU_MOD2_872 0
+#define MU_MOD2_871 1
+#define MU_MOD2_870 0
+#define MU_MOD2_869 1
+#define MU_MOD2_868 0
+#define MU_MOD2_867 1
+#define MU_MOD2_866 0
+#define MU_MOD2_865 1
+#define MU_MOD2_864 0
+#define MU_MOD2_863 1
+#define MU_MOD2_862 0
+#define MU_MOD2_861 1
+#define MU_MOD2_860 0
+#define MU_MOD2_859 1
+#define MU_MOD2_858 0
+#define MU_MOD2_857 1
+#define MU_MOD2_856 0
+#define MU_MOD2_855 1
+#define MU_MOD2_854 0
+#define MU_MOD2_853 1
+#define MU_MOD2_852 0
+#define MU_MOD2_851 1
+#define MU_MOD2_850 0
+#define MU_MOD2_849 1
+#define MU_MOD2_848 0
+#define MU_MOD2_847 1
+#define MU_MOD2_846 0
+#define MU_MOD2_845 1
+#define MU_MOD2_844 0
+#define MU_MOD2_843 1
+#define MU_MOD2_842 0
+#define MU_MOD2_841 1
+#define MU_MOD2_840 0
+#define MU_MOD2_839 1
+#define MU_MOD2_838 0
+#define MU_MOD2_837 1
+#define MU_MOD2_836 0
+#define MU_MOD2_835 1
+#define MU_MOD2_834 0
+#define MU_MOD2_833 1
+#define MU_MOD2_832 0
+#define MU_MOD2_831 1
+#define MU_MOD2_830 0
+#define MU_MOD2_829 1
+#define MU_MOD2_828 0
+#define MU_MOD2_827 1
+#define MU_MOD2_826 0
+#define MU_MOD2_825 1
+#define MU_MOD2_824 0
+#define MU_MOD2_823 1
+#define MU_MOD2_822 0
+#define MU_MOD2_821 1
+#define MU_MOD2_820 0
+#define MU_MOD2_819 1
+#define MU_MOD2_818 0
+#define MU_MOD2_817 1
+#define MU_MOD2_816 0
+#define MU_MOD2_815 1
+#define MU_MOD2_814 0
+#define MU_MOD2_813 1
+#define MU_MOD2_812 0
+#define MU_MOD2_811 1
+#define MU_MOD2_810 0
+#define MU_MOD2_809 1
+#define MU_MOD2_808 0
+#define MU_MOD2_807 1
+#define MU_MOD2_806 0
+#define MU_MOD2_805 1
+#define MU_MOD2_804 0
+#define MU_MOD2_803 1
+#define MU_MOD2_802 0
+#define MU_MOD2_801 1
+#define MU_MOD2_800 0
+#define MU_MOD2_799 1
+#define MU_MOD2_798 0
+#define MU_MOD2_797 1
+#define MU_MOD2_796 0
+#define MU_MOD2_795 1
+#define MU_MOD2_794 0
+#define MU_MOD2_793 1
+#define MU_MOD2_792 0
+#define MU_MOD2_791 1
+#define MU_MOD2_790 0
+#define MU_MOD2_789 1
+#define MU_MOD2_788 0
+#define MU_MOD2_787 1
+#define MU_MOD2_786 0
+#define MU_MOD2_785 1
+#define MU_MOD2_784 0
+#define MU_MOD2_783 1
+#define MU_MOD2_782 0
+#define MU_MOD2_781 1
+#define MU_MOD2_780 0
+#define MU_MOD2_779 1
+#define MU_MOD2_778 0
+#define MU_MOD2_777 1
+#define MU_MOD2_776 0
+#define MU_MOD2_775 1
+#define MU_MOD2_774 0
+#define MU_MOD2_773 1
+#define MU_MOD2_772 0
+#define MU_MOD2_771 1
+#define MU_MOD2_770 0
+#define MU_MOD2_769 1
+#define MU_MOD2_768 0
+#define MU_MOD2_767 1
+#define MU_MOD2_766 0
+#define MU_MOD2_765 1
+#define MU_MOD2_764 0
+#define MU_MOD2_763 1
+#define MU_MOD2_762 0
+#define MU_MOD2_761 1
+#define MU_MOD2_760 0
+#define MU_MOD2_759 1
+#define MU_MOD2_758 0
+#define MU_MOD2_757 1
+#define MU_MOD2_756 0
+#define MU_MOD2_755 1
+#define MU_MOD2_754 0
+#define MU_MOD2_753 1
+#define MU_MOD2_752 0
+#define MU_MOD2_751 1
+#define MU_MOD2_750 0
+#define MU_MOD2_749 1
+#define MU_MOD2_748 0
+#define MU_MOD2_747 1
+#define MU_MOD2_746 0
+#define MU_MOD2_745 1
+#define MU_MOD2_744 0
+#define MU_MOD2_743 1
+#define MU_MOD2_742 0
+#define MU_MOD2_741 1
+#define MU_MOD2_740 0
+#define MU_MOD2_739 1
+#define MU_MOD2_738 0
+#define MU_MOD2_737 1
+#define MU_MOD2_736 0
+#define MU_MOD2_735 1
+#define MU_MOD2_734 0
+#define MU_MOD2_733 1
+#define MU_MOD2_732 0
+#define MU_MOD2_731 1
+#define MU_MOD2_730 0
+#define MU_MOD2_729 1
+#define MU_MOD2_728 0
+#define MU_MOD2_727 1
+#define MU_MOD2_726 0
+#define MU_MOD2_725 1
+#define MU_MOD2_724 0
+#define MU_MOD2_723 1
+#define MU_MOD2_722 0
+#define MU_MOD2_721 1
+#define MU_MOD2_720 0
+#define MU_MOD2_719 1
+#define MU_MOD2_718 0
+#define MU_MOD2_717 1
+#define MU_MOD2_716 0
+#define MU_MOD2_715 1
+#define MU_MOD2_714 0
+#define MU_MOD2_713 1
+#define MU_MOD2_712 0
+#define MU_MOD2_711 1
+#define MU_MOD2_710 0
+#define MU_MOD2_709 1
+#define MU_MOD2_708 0
+#define MU_MOD2_707 1
+#define MU_MOD2_706 0
+#define MU_MOD2_705 1
+#define MU_MOD2_704 0
+#define MU_MOD2_703 1
+#define MU_MOD2_702 0
+#define MU_MOD2_701 1
+#define MU_MOD2_700 0
+#define MU_MOD2_699 1
+#define MU_MOD2_698 0
+#define MU_MOD2_697 1
+#define MU_MOD2_696 0
+#define MU_MOD2_695 1
+#define MU_MOD2_694 0
+#define MU_MOD2_693 1
+#define MU_MOD2_692 0
+#define MU_MOD2_691 1
+#define MU_MOD2_690 0
+#define MU_MOD2_689 1
+#define MU_MOD2_688 0
+#define MU_MOD2_687 1
+#define MU_MOD2_686 0
+#define MU_MOD2_685 1
+#define MU_MOD2_684 0
+#define MU_MOD2_683 1
+#define MU_MOD2_682 0
+#define MU_MOD2_681 1
+#define MU_MOD2_680 0
+#define MU_MOD2_679 1
+#define MU_MOD2_678 0
+#define MU_MOD2_677 1
+#define MU_MOD2_676 0
+#define MU_MOD2_675 1
+#define MU_MOD2_674 0
+#define MU_MOD2_673 1
+#define MU_MOD2_672 0
+#define MU_MOD2_671 1
+#define MU_MOD2_670 0
+#define MU_MOD2_669 1
+#define MU_MOD2_668 0
+#define MU_MOD2_667 1
+#define MU_MOD2_666 0
+#define MU_MOD2_665 1
+#define MU_MOD2_664 0
+#define MU_MOD2_663 1
+#define MU_MOD2_662 0
+#define MU_MOD2_661 1
+#define MU_MOD2_660 0
+#define MU_MOD2_659 1
+#define MU_MOD2_658 0
+#define MU_MOD2_657 1
+#define MU_MOD2_656 0
+#define MU_MOD2_655 1
+#define MU_MOD2_654 0
+#define MU_MOD2_653 1
+#define MU_MOD2_652 0
+#define MU_MOD2_651 1
+#define MU_MOD2_650 0
+#define MU_MOD2_649 1
+#define MU_MOD2_648 0
+#define MU_MOD2_647 1
+#define MU_MOD2_646 0
+#define MU_MOD2_645 1
+#define MU_MOD2_644 0
+#define MU_MOD2_643 1
+#define MU_MOD2_642 0
+#define MU_MOD2_641 1
+#define MU_MOD2_640 0
+#define MU_MOD2_639 1
+#define MU_MOD2_638 0
+#define MU_MOD2_637 1
+#define MU_MOD2_636 0
+#define MU_MOD2_635 1
+#define MU_MOD2_634 0
+#define MU_MOD2_633 1
+#define MU_MOD2_632 0
+#define MU_MOD2_631 1
+#define MU_MOD2_630 0
+#define MU_MOD2_629 1
+#define MU_MOD2_628 0
+#define MU_MOD2_627 1
+#define MU_MOD2_626 0
+#define MU_MOD2_625 1
+#define MU_MOD2_624 0
+#define MU_MOD2_623 1
+#define MU_MOD2_622 0
+#define MU_MOD2_621 1
+#define MU_MOD2_620 0
+#define MU_MOD2_619 1
+#define MU_MOD2_618 0
+#define MU_MOD2_617 1
+#define MU_MOD2_616 0
+#define MU_MOD2_615 1
+#define MU_MOD2_614 0
+#define MU_MOD2_613 1
+#define MU_MOD2_612 0
+#define MU_MOD2_611 1
+#define MU_MOD2_610 0
+#define MU_MOD2_609 1
+#define MU_MOD2_608 0
+#define MU_MOD2_607 1
+#define MU_MOD2_606 0
+#define MU_MOD2_605 1
+#define MU_MOD2_604 0
+#define MU_MOD2_603 1
+#define MU_MOD2_602 0
+#define MU_MOD2_601 1
+#define MU_MOD2_600 0
+#define MU_MOD2_599 1
+#define MU_MOD2_598 0
+#define MU_MOD2_597 1
+#define MU_MOD2_596 0
+#define MU_MOD2_595 1
+#define MU_MOD2_594 0
+#define MU_MOD2_593 1
+#define MU_MOD2_592 0
+#define MU_MOD2_591 1
+#define MU_MOD2_590 0
+#define MU_MOD2_589 1
+#define MU_MOD2_588 0
+#define MU_MOD2_587 1
+#define MU_MOD2_586 0
+#define MU_MOD2_585 1
+#define MU_MOD2_584 0
+#define MU_MOD2_583 1
+#define MU_MOD2_582 0
+#define MU_MOD2_581 1
+#define MU_MOD2_580 0
+#define MU_MOD2_579 1
+#define MU_MOD2_578 0
+#define MU_MOD2_577 1
+#define MU_MOD2_576 0
+#define MU_MOD2_575 1
+#define MU_MOD2_574 0
+#define MU_MOD2_573 1
+#define MU_MOD2_572 0
+#define MU_MOD2_571 1
+#define MU_MOD2_570 0
+#define MU_MOD2_569 1
+#define MU_MOD2_568 0
+#define MU_MOD2_567 1
+#define MU_MOD2_566 0
+#define MU_MOD2_565 1
+#define MU_MOD2_564 0
+#define MU_MOD2_563 1
+#define MU_MOD2_562 0
+#define MU_MOD2_561 1
+#define MU_MOD2_560 0
+#define MU_MOD2_559 1
+#define MU_MOD2_558 0
+#define MU_MOD2_557 1
+#define MU_MOD2_556 0
+#define MU_MOD2_555 1
+#define MU_MOD2_554 0
+#define MU_MOD2_553 1
+#define MU_MOD2_552 0
+#define MU_MOD2_551 1
+#define MU_MOD2_550 0
+#define MU_MOD2_549 1
+#define MU_MOD2_548 0
+#define MU_MOD2_547 1
+#define MU_MOD2_546 0
+#define MU_MOD2_545 1
+#define MU_MOD2_544 0
+#define MU_MOD2_543 1
+#define MU_MOD2_542 0
+#define MU_MOD2_541 1
+#define MU_MOD2_540 0
+#define MU_MOD2_539 1
+#define MU_MOD2_538 0
+#define MU_MOD2_537 1
+#define MU_MOD2_536 0
+#define MU_MOD2_535 1
+#define MU_MOD2_534 0
+#define MU_MOD2_533 1
+#define MU_MOD2_532 0
+#define MU_MOD2_531 1
+#define MU_MOD2_530 0
+#define MU_MOD2_529 1
+#define MU_MOD2_528 0
+#define MU_MOD2_527 1
+#define MU_MOD2_526 0
+#define MU_MOD2_525 1
+#define MU_MOD2_524 0
+#define MU_MOD2_523 1
+#define MU_MOD2_522 0
+#define MU_MOD2_521 1
+#define MU_MOD2_520 0
+#define MU_MOD2_519 1
+#define MU_MOD2_518 0
+#define MU_MOD2_517 1
+#define MU_MOD2_516 0
+#define MU_MOD2_515 1
+#define MU_MOD2_514 0
+#define MU_MOD2_513 1
+#define MU_MOD2_512 0
+#define MU_MOD2_511 1
+#define MU_MOD2_510 0
+#define MU_MOD2_509 1
+#define MU_MOD2_508 0
+#define MU_MOD2_507 1
+#define MU_MOD2_506 0
+#define MU_MOD2_505 1
+#define MU_MOD2_504 0
+#define MU_MOD2_503 1
+#define MU_MOD2_502 0
+#define MU_MOD2_501 1
+#define MU_MOD2_500 0
+#define MU_MOD2_499 1
+#define MU_MOD2_498 0
+#define MU_MOD2_497 1
+#define MU_MOD2_496 0
+#define MU_MOD2_495 1
+#define MU_MOD2_494 0
+#define MU_MOD2_493 1
+#define MU_MOD2_492 0
+#define MU_MOD2_491 1
+#define MU_MOD2_490 0
+#define MU_MOD2_489 1
+#define MU_MOD2_488 0
+#define MU_MOD2_487 1
+#define MU_MOD2_486 0
+#define MU_MOD2_485 1
+#define MU_MOD2_484 0
+#define MU_MOD2_483 1
+#define MU_MOD2_482 0
+#define MU_MOD2_481 1
+#define MU_MOD2_480 0
+#define MU_MOD2_479 1
+#define MU_MOD2_478 0
+#define MU_MOD2_477 1
+#define MU_MOD2_476 0
+#define MU_MOD2_475 1
+#define MU_MOD2_474 0
+#define MU_MOD2_473 1
+#define MU_MOD2_472 0
+#define MU_MOD2_471 1
+#define MU_MOD2_470 0
+#define MU_MOD2_469 1
+#define MU_MOD2_468 0
+#define MU_MOD2_467 1
+#define MU_MOD2_466 0
+#define MU_MOD2_465 1
+#define MU_MOD2_464 0
+#define MU_MOD2_463 1
+#define MU_MOD2_462 0
+#define MU_MOD2_461 1
+#define MU_MOD2_460 0
+#define MU_MOD2_459 1
+#define MU_MOD2_458 0
+#define MU_MOD2_457 1
+#define MU_MOD2_456 0
+#define MU_MOD2_455 1
+#define MU_MOD2_454 0
+#define MU_MOD2_453 1
+#define MU_MOD2_452 0
+#define MU_MOD2_451 1
+#define MU_MOD2_450 0
+#define MU_MOD2_449 1
+#define MU_MOD2_448 0
+#define MU_MOD2_447 1
+#define MU_MOD2_446 0
+#define MU_MOD2_445 1
+#define MU_MOD2_444 0
+#define MU_MOD2_443 1
+#define MU_MOD2_442 0
+#define MU_MOD2_441 1
+#define MU_MOD2_440 0
+#define MU_MOD2_439 1
+#define MU_MOD2_438 0
+#define MU_MOD2_437 1
+#define MU_MOD2_436 0
+#define MU_MOD2_435 1
+#define MU_MOD2_434 0
+#define MU_MOD2_433 1
+#define MU_MOD2_432 0
+#define MU_MOD2_431 1
+#define MU_MOD2_430 0
+#define MU_MOD2_429 1
+#define MU_MOD2_428 0
+#define MU_MOD2_427 1
+#define MU_MOD2_426 0
+#define MU_MOD2_425 1
+#define MU_MOD2_424 0
+#define MU_MOD2_423 1
+#define MU_MOD2_422 0
+#define MU_MOD2_421 1
+#define MU_MOD2_420 0
+#define MU_MOD2_419 1
+#define MU_MOD2_418 0
+#define MU_MOD2_417 1
+#define MU_MOD2_416 0
+#define MU_MOD2_415 1
+#define MU_MOD2_414 0
+#define MU_MOD2_413 1
+#define MU_MOD2_412 0
+#define MU_MOD2_411 1
+#define MU_MOD2_410 0
+#define MU_MOD2_409 1
+#define MU_MOD2_408 0
+#define MU_MOD2_407 1
+#define MU_MOD2_406 0
+#define MU_MOD2_405 1
+#define MU_MOD2_404 0
+#define MU_MOD2_403 1
+#define MU_MOD2_402 0
+#define MU_MOD2_401 1
+#define MU_MOD2_400 0
+#define MU_MOD2_399 1
+#define MU_MOD2_398 0
+#define MU_MOD2_397 1
+#define MU_MOD2_396 0
+#define MU_MOD2_395 1
+#define MU_MOD2_394 0
+#define MU_MOD2_393 1
+#define MU_MOD2_392 0
+#define MU_MOD2_391 1
+#define MU_MOD2_390 0
+#define MU_MOD2_389 1
+#define MU_MOD2_388 0
+#define MU_MOD2_387 1
+#define MU_MOD2_386 0
+#define MU_MOD2_385 1
+#define MU_MOD2_384 0
+#define MU_MOD2_383 1
+#define MU_MOD2_382 0
+#define MU_MOD2_381 1
+#define MU_MOD2_380 0
+#define MU_MOD2_379 1
+#define MU_MOD2_378 0
+#define MU_MOD2_377 1
+#define MU_MOD2_376 0
+#define MU_MOD2_375 1
+#define MU_MOD2_374 0
+#define MU_MOD2_373 1
+#define MU_MOD2_372 0
+#define MU_MOD2_371 1
+#define MU_MOD2_370 0
+#define MU_MOD2_369 1
+#define MU_MOD2_368 0
+#define MU_MOD2_367 1
+#define MU_MOD2_366 0
+#define MU_MOD2_365 1
+#define MU_MOD2_364 0
+#define MU_MOD2_363 1
+#define MU_MOD2_362 0
+#define MU_MOD2_361 1
+#define MU_MOD2_360 0
+#define MU_MOD2_359 1
+#define MU_MOD2_358 0
+#define MU_MOD2_357 1
+#define MU_MOD2_356 0
+#define MU_MOD2_355 1
+#define MU_MOD2_354 0
+#define MU_MOD2_353 1
+#define MU_MOD2_352 0
+#define MU_MOD2_351 1
+#define MU_MOD2_350 0
+#define MU_MOD2_349 1
+#define MU_MOD2_348 0
+#define MU_MOD2_347 1
+#define MU_MOD2_346 0
+#define MU_MOD2_345 1
+#define MU_MOD2_344 0
+#define MU_MOD2_343 1
+#define MU_MOD2_342 0
+#define MU_MOD2_341 1
+#define MU_MOD2_340 0
+#define MU_MOD2_339 1
+#define MU_MOD2_338 0
+#define MU_MOD2_337 1
+#define MU_MOD2_336 0
+#define MU_MOD2_335 1
+#define MU_MOD2_334 0
+#define MU_MOD2_333 1
+#define MU_MOD2_332 0
+#define MU_MOD2_331 1
+#define MU_MOD2_330 0
+#define MU_MOD2_329 1
+#define MU_MOD2_328 0
+#define MU_MOD2_327 1
+#define MU_MOD2_326 0
+#define MU_MOD2_325 1
+#define MU_MOD2_324 0
+#define MU_MOD2_323 1
+#define MU_MOD2_322 0
+#define MU_MOD2_321 1
+#define MU_MOD2_320 0
+#define MU_MOD2_319 1
+#define MU_MOD2_318 0
+#define MU_MOD2_317 1
+#define MU_MOD2_316 0
+#define MU_MOD2_315 1
+#define MU_MOD2_314 0
+#define MU_MOD2_313 1
+#define MU_MOD2_312 0
+#define MU_MOD2_311 1
+#define MU_MOD2_310 0
+#define MU_MOD2_309 1
+#define MU_MOD2_308 0
+#define MU_MOD2_307 1
+#define MU_MOD2_306 0
+#define MU_MOD2_305 1
+#define MU_MOD2_304 0
+#define MU_MOD2_303 1
+#define MU_MOD2_302 0
+#define MU_MOD2_301 1
+#define MU_MOD2_300 0
+#define MU_MOD2_299 1
+#define MU_MOD2_298 0
+#define MU_MOD2_297 1
+#define MU_MOD2_296 0
+#define MU_MOD2_295 1
+#define MU_MOD2_294 0
+#define MU_MOD2_293 1
+#define MU_MOD2_292 0
+#define MU_MOD2_291 1
+#define MU_MOD2_290 0
+#define MU_MOD2_289 1
+#define MU_MOD2_288 0
+#define MU_MOD2_287 1
+#define MU_MOD2_286 0
+#define MU_MOD2_285 1
+#define MU_MOD2_284 0
+#define MU_MOD2_283 1
+#define MU_MOD2_282 0
+#define MU_MOD2_281 1
+#define MU_MOD2_280 0
+#define MU_MOD2_279 1
+#define MU_MOD2_278 0
+#define MU_MOD2_277 1
+#define MU_MOD2_276 0
+#define MU_MOD2_275 1
+#define MU_MOD2_274 0
+#define MU_MOD2_273 1
+#define MU_MOD2_272 0
+#define MU_MOD2_271 1
+#define MU_MOD2_270 0
+#define MU_MOD2_269 1
+#define MU_MOD2_268 0
+#define MU_MOD2_267 1
+#define MU_MOD2_266 0
+#define MU_MOD2_265 1
+#define MU_MOD2_264 0
+#define MU_MOD2_263 1
+#define MU_MOD2_262 0
+#define MU_MOD2_261 1
+#define MU_MOD2_260 0
+#define MU_MOD2_259 1
+#define MU_MOD2_258 0
+#define MU_MOD2_257 1
+#define MU_MOD2_256 0
+#define MU_MOD2_255 1
+#define MU_MOD2_254 0
+#define MU_MOD2_253 1
+#define MU_MOD2_252 0
+#define MU_MOD2_251 1
+#define MU_MOD2_250 0
+#define MU_MOD2_249 1
+#define MU_MOD2_248 0
+#define MU_MOD2_247 1
+#define MU_MOD2_246 0
+#define MU_MOD2_245 1
+#define MU_MOD2_244 0
+#define MU_MOD2_243 1
+#define MU_MOD2_242 0
+#define MU_MOD2_241 1
+#define MU_MOD2_240 0
+#define MU_MOD2_239 1
+#define MU_MOD2_238 0
+#define MU_MOD2_237 1
+#define MU_MOD2_236 0
+#define MU_MOD2_235 1
+#define MU_MOD2_234 0
+#define MU_MOD2_233 1
+#define MU_MOD2_232 0
+#define MU_MOD2_231 1
+#define MU_MOD2_230 0
+#define MU_MOD2_229 1
+#define MU_MOD2_228 0
+#define MU_MOD2_227 1
+#define MU_MOD2_226 0
+#define MU_MOD2_225 1
+#define MU_MOD2_224 0
+#define MU_MOD2_223 1
+#define MU_MOD2_222 0
+#define MU_MOD2_221 1
+#define MU_MOD2_220 0
+#define MU_MOD2_219 1
+#define MU_MOD2_218 0
+#define MU_MOD2_217 1
+#define MU_MOD2_216 0
+#define MU_MOD2_215 1
+#define MU_MOD2_214 0
+#define MU_MOD2_213 1
+#define MU_MOD2_212 0
+#define MU_MOD2_211 1
+#define MU_MOD2_210 0
+#define MU_MOD2_209 1
+#define MU_MOD2_208 0
+#define MU_MOD2_207 1
+#define MU_MOD2_206 0
+#define MU_MOD2_205 1
+#define MU_MOD2_204 0
+#define MU_MOD2_203 1
+#define MU_MOD2_202 0
+#define MU_MOD2_201 1
+#define MU_MOD2_200 0
+#define MU_MOD2_199 1
+#define MU_MOD2_198 0
+#define MU_MOD2_197 1
+#define MU_MOD2_196 0
+#define MU_MOD2_195 1
+#define MU_MOD2_194 0
+#define MU_MOD2_193 1
+#define MU_MOD2_192 0
+#define MU_MOD2_191 1
+#define MU_MOD2_190 0
+#define MU_MOD2_189 1
+#define MU_MOD2_188 0
+#define MU_MOD2_187 1
+#define MU_MOD2_186 0
+#define MU_MOD2_185 1
+#define MU_MOD2_184 0
+#define MU_MOD2_183 1
+#define MU_MOD2_182 0
+#define MU_MOD2_181 1
+#define MU_MOD2_180 0
+#define MU_MOD2_179 1
+#define MU_MOD2_178 0
+#define MU_MOD2_177 1
+#define MU_MOD2_176 0
+#define MU_MOD2_175 1
+#define MU_MOD2_174 0
+#define MU_MOD2_173 1
+#define MU_MOD2_172 0
+#define MU_MOD2_171 1
+#define MU_MOD2_170 0
+#define MU_MOD2_169 1
+#define MU_MOD2_168 0
+#define MU_MOD2_167 1
+#define MU_MOD2_166 0
+#define MU_MOD2_165 1
+#define MU_MOD2_164 0
+#define MU_MOD2_163 1
+#define MU_MOD2_162 0
+#define MU_MOD2_161 1
+#define MU_MOD2_160 0
+#define MU_MOD2_159 1
+#define MU_MOD2_158 0
+#define MU_MOD2_157 1
+#define MU_MOD2_156 0
+#define MU_MOD2_155 1
+#define MU_MOD2_154 0
+#define MU_MOD2_153 1
+#define MU_MOD2_152 0
+#define MU_MOD2_151 1
+#define MU_MOD2_150 0
+#define MU_MOD2_149 1
+#define MU_MOD2_148 0
+#define MU_MOD2_147 1
+#define MU_MOD2_146 0
+#define MU_MOD2_145 1
+#define MU_MOD2_144 0
+#define MU_MOD2_143 1
+#define MU_MOD2_142 0
+#define MU_MOD2_141 1
+#define MU_MOD2_140 0
+#define MU_MOD2_139 1
+#define MU_MOD2_138 0
+#define MU_MOD2_137 1
+#define MU_MOD2_136 0
+#define MU_MOD2_135 1
+#define MU_MOD2_134 0
+#define MU_MOD2_133 1
+#define MU_MOD2_132 0
+#define MU_MOD2_131 1
+#define MU_MOD2_130 0
+#define MU_MOD2_129 1
+#define MU_MOD2_128 0
+#define MU_MOD2_127 1
+#define MU_MOD2_126 0
+#define MU_MOD2_125 1
+#define MU_MOD2_124 0
+#define MU_MOD2_123 1
+#define MU_MOD2_122 0
+#define MU_MOD2_121 1
+#define MU_MOD2_120 0
+#define MU_MOD2_119 1
+#define MU_MOD2_118 0
+#define MU_MOD2_117 1
+#define MU_MOD2_116 0
+#define MU_MOD2_115 1
+#define MU_MOD2_114 0
+#define MU_MOD2_113 1
+#define MU_MOD2_112 0
+#define MU_MOD2_111 1
+#define MU_MOD2_110 0
+#define MU_MOD2_109 1
+#define MU_MOD2_108 0
+#define MU_MOD2_107 1
+#define MU_MOD2_106 0
+#define MU_MOD2_105 1
+#define MU_MOD2_104 0
+#define MU_MOD2_103 1
+#define MU_MOD2_102 0
+#define MU_MOD2_101 1
+#define MU_MOD2_100 0
+#define MU_MOD2_99 1
+#define MU_MOD2_98 0
+#define MU_MOD2_97 1
+#define MU_MOD2_96 0
+#define MU_MOD2_95 1
+#define MU_MOD2_94 0
+#define MU_MOD2_93 1
+#define MU_MOD2_92 0
+#define MU_MOD2_91 1
+#define MU_MOD2_90 0
+#define MU_MOD2_89 1
+#define MU_MOD2_88 0
+#define MU_MOD2_87 1
+#define MU_MOD2_86 0
+#define MU_MOD2_85 1
+#define MU_MOD2_84 0
+#define MU_MOD2_83 1
+#define MU_MOD2_82 0
+#define MU_MOD2_81 1
+#define MU_MOD2_80 0
+#define MU_MOD2_79 1
+#define MU_MOD2_78 0
+#define MU_MOD2_77 1
+#define MU_MOD2_76 0
+#define MU_MOD2_75 1
+#define MU_MOD2_74 0
+#define MU_MOD2_73 1
+#define MU_MOD2_72 0
+#define MU_MOD2_71 1
+#define MU_MOD2_70 0
+#define MU_MOD2_69 1
+#define MU_MOD2_68 0
+#define MU_MOD2_67 1
+#define MU_MOD2_66 0
+#define MU_MOD2_65 1
+#define MU_MOD2_64 0
+#define MU_MOD2_63 1
+#define MU_MOD2_62 0
+#define MU_MOD2_61 1
+#define MU_MOD2_60 0
+#define MU_MOD2_59 1
+#define MU_MOD2_58 0
+#define MU_MOD2_57 1
+#define MU_MOD2_56 0
+#define MU_MOD2_55 1
+#define MU_MOD2_54 0
+#define MU_MOD2_53 1
+#define MU_MOD2_52 0
+#define MU_MOD2_51 1
+#define MU_MOD2_50 0
+#define MU_MOD2_49 1
+#define MU_MOD2_48 0
+#define MU_MOD2_47 1
+#define MU_MOD2_46 0
+#define MU_MOD2_45 1
+#define MU_MOD2_44 0
+#define MU_MOD2_43 1
+#define MU_MOD2_42 0
+#define MU_MOD2_41 1
+#define MU_MOD2_40 0
+#define MU_MOD2_39 1
+#define MU_MOD2_38 0
+#define MU_MOD2_37 1
+#define MU_MOD2_36 0
+#define MU_MOD2_35 1
+#define MU_MOD2_34 0
+#define MU_MOD2_33 1
+#define MU_MOD2_32 0
+#define MU_MOD2_31 1
+#define MU_MOD2_30 0
+#define MU_MOD2_29 1
+#define MU_MOD2_28 0
+#define MU_MOD2_27 1
+#define MU_MOD2_26 0
+#define MU_MOD2_25 1
+#define MU_MOD2_24 0
+#define MU_MOD2_23 1
+#define MU_MOD2_22 0
+#define MU_MOD2_21 1
+#define MU_MOD2_20 0
+#define MU_MOD2_19 1
+#define MU_MOD2_18 0
+#define MU_MOD2_17 1
+#define MU_MOD2_16 0
+#define MU_MOD2_15 1
+#define MU_MOD2_14 0
+#define MU_MOD2_13 1
+#define MU_MOD2_12 0
+#define MU_MOD2_11 1
+#define MU_MOD2_10 0
+#define MU_MOD2_9 1
+#define MU_MOD2_8 0
+#define MU_MOD2_7 1
+#define MU_MOD2_6 0
+#define MU_MOD2_5 1
+#define MU_MOD2_4 0
+#define MU_MOD2_3 1
+#define MU_MOD2_2 0
+#define MU_MOD2_1 1
+#define MU_MOD2_0 0
+
+#define MU_THE_NTH_ARG(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123, P124,  ... ) P124
+
+#ifdef _MSC_VER
+#define MU_COUNT_1_OR_MORE_ARG(...) MU_THE_NTH_ARG MU_LPAREN __VA_ARGS__, \
+123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
+#define MU_MORE_THAN_1_ARG(...) MU_THE_NTH_ARG MU_LPAREN __VA_ARGS__, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0)
+#else
+#define MU_COUNT_1_OR_MORE_ARG(...) MU_THE_NTH_ARG (__VA_ARGS__, \
+123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
+#define MU_MORE_THAN_1_ARG(...) MU_THE_NTH_ARG(__VA_ARGS__, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 0)
+#endif
+
+#define MU_COUNT_ARG(...) MU_C2(MU_COUNT_ARG_, MU_ISEMPTY(__VA_ARGS__))(__VA_ARGS__)
+#define MU_COUNT_ARG_1(...) 0
+#define MU_COUNT_ARG_0(...) MU_C1(MU_COUNT_1_OR_MORE_ARG(__VA_ARGS__))
+
+#define MU_ISEMPTY(...) MU_C5(MU_DISPATCH_EMPTY_, MU_MORE_THAN_1_ARG(MU_TRIGGER_PARENTHESIS __VA_ARGS__ ()), MU_MORE_THAN_1_ARG(__VA_ARGS__), MU_MORE_THAN_1_ARG(__VA_ARGS__ ()), MU_MORE_THAN_1_ARG(MU_TRIGGER_PARENTHESIS __VA_ARGS__))
+#define MU_DISPATCH_EMPTY_1000 1
+#define MU_DISPATCH_EMPTY_0000 0
+#define MU_DISPATCH_EMPTY_1100 0
+#define MU_DISPATCH_EMPTY_1111 0
+#define MU_DISPATCH_EMPTY_1001 0
+#define MU_DISPATCH_EMPTY_1010 0
+
+
+#define MU_FOR_EACH_1_124(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123, P124) \
+X(P1) \
+MU_FOR_EACH_1_123(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123, P124)
+
+#define MU_FOR_EACH_1_123(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123) \
+X(P1) \
+MU_FOR_EACH_1_122(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123)
+
+#define MU_FOR_EACH_1_122(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122) \
+X(P1) \
+MU_FOR_EACH_1_121(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122)
+
+#define MU_FOR_EACH_1_121(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121) \
+X(P1) \
+MU_FOR_EACH_1_120(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121)
+
+#define MU_FOR_EACH_1_120(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120) \
+X(P1) \
+MU_FOR_EACH_1_119(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120)
+
+#define MU_FOR_EACH_1_119(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119) \
+X(P1) \
+MU_FOR_EACH_1_118(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119)
+
+#define MU_FOR_EACH_1_118(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118) \
+X(P1) \
+MU_FOR_EACH_1_117(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118)
+
+#define MU_FOR_EACH_1_117(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117) \
+X(P1) \
+MU_FOR_EACH_1_116(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117)
+
+#define MU_FOR_EACH_1_116(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116) \
+X(P1) \
+MU_FOR_EACH_1_115(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116)
+
+#define MU_FOR_EACH_1_115(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115) \
+X(P1) \
+MU_FOR_EACH_1_114(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115)
+
+#define MU_FOR_EACH_1_114(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114) \
+X(P1) \
+MU_FOR_EACH_1_113(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114)
+
+#define MU_FOR_EACH_1_113(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113) \
+X(P1) \
+MU_FOR_EACH_1_112(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113)
+
+#define MU_FOR_EACH_1_112(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112) \
+X(P1) \
+MU_FOR_EACH_1_111(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112)
+
+#define MU_FOR_EACH_1_111(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111) \
+X(P1) \
+MU_FOR_EACH_1_110(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111)
+
+#define MU_FOR_EACH_1_110(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110) \
+X(P1) \
+MU_FOR_EACH_1_109(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110)
+
+#define MU_FOR_EACH_1_109(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109) \
+X(P1) \
+MU_FOR_EACH_1_108(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109)
+
+#define MU_FOR_EACH_1_108(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108) \
+X(P1) \
+MU_FOR_EACH_1_107(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108)
+
+#define MU_FOR_EACH_1_107(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107) \
+X(P1) \
+MU_FOR_EACH_1_106(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107)
+
+#define MU_FOR_EACH_1_106(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106) \
+X(P1) \
+MU_FOR_EACH_1_105(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106)
+
+#define MU_FOR_EACH_1_105(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105) \
+X(P1) \
+MU_FOR_EACH_1_104(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105)
+
+#define MU_FOR_EACH_1_104(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104) \
+X(P1) \
+MU_FOR_EACH_1_103(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104)
+
+#define MU_FOR_EACH_1_103(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103) \
+X(P1) \
+MU_FOR_EACH_1_102(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103)
+
+#define MU_FOR_EACH_1_102(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102) \
+X(P1) \
+MU_FOR_EACH_1_101(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102)
+
+#define MU_FOR_EACH_1_101(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101) \
+X(P1) \
+MU_FOR_EACH_1_100(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101)
+
+#define MU_FOR_EACH_1_100(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100) \
+X(P1) \
+MU_FOR_EACH_1_99(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100)
+
+#define MU_FOR_EACH_1_99(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99) \
+X(P1) \
+MU_FOR_EACH_1_98(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99)
+
+#define MU_FOR_EACH_1_98(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98) \
+X(P1) \
+MU_FOR_EACH_1_97(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98)
+
+#define MU_FOR_EACH_1_97(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97) \
+X(P1) \
+MU_FOR_EACH_1_96(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97)
+
+#define MU_FOR_EACH_1_96(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96) \
+X(P1) \
+MU_FOR_EACH_1_95(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96)
+
+#define MU_FOR_EACH_1_95(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95) \
+X(P1) \
+MU_FOR_EACH_1_94(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95)
+
+#define MU_FOR_EACH_1_94(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94) \
+X(P1) \
+MU_FOR_EACH_1_93(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94)
+
+#define MU_FOR_EACH_1_93(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93) \
+X(P1) \
+MU_FOR_EACH_1_92(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93)
+
+#define MU_FOR_EACH_1_92(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92) \
+X(P1) \
+MU_FOR_EACH_1_91(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92)
+
+#define MU_FOR_EACH_1_91(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91) \
+X(P1) \
+MU_FOR_EACH_1_90(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91)
+
+#define MU_FOR_EACH_1_90(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90) \
+X(P1) \
+MU_FOR_EACH_1_89(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90)
+
+#define MU_FOR_EACH_1_89(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89) \
+X(P1) \
+MU_FOR_EACH_1_88(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89)
+
+#define MU_FOR_EACH_1_88(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88) \
+X(P1) \
+MU_FOR_EACH_1_87(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88)
+
+#define MU_FOR_EACH_1_87(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87) \
+X(P1) \
+MU_FOR_EACH_1_86(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87)
+
+#define MU_FOR_EACH_1_86(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86) \
+X(P1) \
+MU_FOR_EACH_1_85(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86)
+
+#define MU_FOR_EACH_1_85(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85) \
+X(P1) \
+MU_FOR_EACH_1_84(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85)
+
+#define MU_FOR_EACH_1_84(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84) \
+X(P1) \
+MU_FOR_EACH_1_83(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84)
+
+#define MU_FOR_EACH_1_83(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83) \
+X(P1) \
+MU_FOR_EACH_1_82(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83)
+
+#define MU_FOR_EACH_1_82(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82) \
+X(P1) \
+MU_FOR_EACH_1_81(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82)
+
+#define MU_FOR_EACH_1_81(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81) \
+X(P1) \
+MU_FOR_EACH_1_80(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81)
+
+#define MU_FOR_EACH_1_80(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80) \
+X(P1) \
+MU_FOR_EACH_1_79(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80)
+
+#define MU_FOR_EACH_1_79(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79) \
+X(P1) \
+MU_FOR_EACH_1_78(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79)
+
+#define MU_FOR_EACH_1_78(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78) \
+X(P1) \
+MU_FOR_EACH_1_77(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78)
+
+#define MU_FOR_EACH_1_77(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77) \
+X(P1) \
+MU_FOR_EACH_1_76(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77)
+
+#define MU_FOR_EACH_1_76(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76) \
+X(P1) \
+MU_FOR_EACH_1_75(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76)
+
+#define MU_FOR_EACH_1_75(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75) \
+X(P1) \
+MU_FOR_EACH_1_74(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75)
+
+#define MU_FOR_EACH_1_74(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74) \
+X(P1) \
+MU_FOR_EACH_1_73(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74)
+
+#define MU_FOR_EACH_1_73(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73) \
+X(P1) \
+MU_FOR_EACH_1_72(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73)
+
+#define MU_FOR_EACH_1_72(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72) \
+X(P1) \
+MU_FOR_EACH_1_71(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72)
+
+#define MU_FOR_EACH_1_71(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71) \
+X(P1) \
+MU_FOR_EACH_1_70(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71)
+
+#define MU_FOR_EACH_1_70(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70) \
+X(P1) \
+MU_FOR_EACH_1_69(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70)
+
+#define MU_FOR_EACH_1_69(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69) \
+X(P1) \
+MU_FOR_EACH_1_68(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69)
+
+#define MU_FOR_EACH_1_68(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68) \
+X(P1) \
+MU_FOR_EACH_1_67(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68)
+
+#define MU_FOR_EACH_1_67(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67) \
+X(P1) \
+MU_FOR_EACH_1_66(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67)
+
+#define MU_FOR_EACH_1_66(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66) \
+X(P1) \
+MU_FOR_EACH_1_65(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66)
+
+#define MU_FOR_EACH_1_65(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65) \
+X(P1) \
+MU_FOR_EACH_1_64(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65)
+
+#define MU_FOR_EACH_1_64(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64) \
+X(P1) \
+MU_FOR_EACH_1_63(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64)
+
+#define MU_FOR_EACH_1_63(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63) \
+X(P1) \
+MU_FOR_EACH_1_62(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63)
+
+#define MU_FOR_EACH_1_62(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62) \
+X(P1) \
+MU_FOR_EACH_1_61(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62)
+
+#define MU_FOR_EACH_1_61(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61) \
+X(P1) \
+MU_FOR_EACH_1_60(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61)
+
+#define MU_FOR_EACH_1_60(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60) \
+X(P1) \
+MU_FOR_EACH_1_59(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60)
+
+#define MU_FOR_EACH_1_59(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59) \
+X(P1) \
+MU_FOR_EACH_1_58(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59)
+
+#define MU_FOR_EACH_1_58(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58) \
+X(P1) \
+MU_FOR_EACH_1_57(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58)
+
+#define MU_FOR_EACH_1_57(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57) \
+X(P1) \
+MU_FOR_EACH_1_56(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57)
+
+#define MU_FOR_EACH_1_56(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56) \
+X(P1) \
+MU_FOR_EACH_1_55(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56)
+
+#define MU_FOR_EACH_1_55(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55) \
+X(P1) \
+MU_FOR_EACH_1_54(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55)
+
+#define MU_FOR_EACH_1_54(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54) \
+X(P1) \
+MU_FOR_EACH_1_53(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54)
+
+#define MU_FOR_EACH_1_53(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53) \
+X(P1) \
+MU_FOR_EACH_1_52(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53)
+
+#define MU_FOR_EACH_1_52(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52) \
+X(P1) \
+MU_FOR_EACH_1_51(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52)
+
+#define MU_FOR_EACH_1_51(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51) \
+X(P1) \
+MU_FOR_EACH_1_50(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51)
+
+#define MU_FOR_EACH_1_50(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50) \
+X(P1) \
+MU_FOR_EACH_1_49(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50)
+
+#define MU_FOR_EACH_1_49(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49) \
+X(P1) \
+MU_FOR_EACH_1_48(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49)
+
+#define MU_FOR_EACH_1_48(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48) \
+X(P1) \
+MU_FOR_EACH_1_47(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48)
+
+#define MU_FOR_EACH_1_47(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47) \
+X(P1) \
+MU_FOR_EACH_1_46(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47)
+
+#define MU_FOR_EACH_1_46(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46) \
+X(P1) \
+MU_FOR_EACH_1_45(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46)
+
+#define MU_FOR_EACH_1_45(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45) \
+X(P1) \
+MU_FOR_EACH_1_44(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45)
+
+#define MU_FOR_EACH_1_44(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44) \
+X(P1) \
+MU_FOR_EACH_1_43(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44)
+
+#define MU_FOR_EACH_1_43(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43) \
+X(P1) \
+MU_FOR_EACH_1_42(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43)
+
+#define MU_FOR_EACH_1_42(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42) \
+X(P1) \
+MU_FOR_EACH_1_41(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42)
+
+#define MU_FOR_EACH_1_41(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41) \
+X(P1) \
+MU_FOR_EACH_1_40(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41)
+
+#define MU_FOR_EACH_1_40(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40) \
+X(P1) \
+MU_FOR_EACH_1_39(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40)
+
+#define MU_FOR_EACH_1_39(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39) \
+X(P1) \
+MU_FOR_EACH_1_38(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39)
+
+#define MU_FOR_EACH_1_38(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38) \
+X(P1) \
+MU_FOR_EACH_1_37(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38)
+
+#define MU_FOR_EACH_1_37(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37) \
+X(P1) \
+MU_FOR_EACH_1_36(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37)
+
+#define MU_FOR_EACH_1_36(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36) \
+X(P1) \
+MU_FOR_EACH_1_35(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36)
+
+#define MU_FOR_EACH_1_35(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35) \
+X(P1) \
+MU_FOR_EACH_1_34(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35)
+
+#define MU_FOR_EACH_1_34(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34) \
+X(P1) \
+MU_FOR_EACH_1_33(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34)
+
+#define MU_FOR_EACH_1_33(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33) \
+X(P1) \
+MU_FOR_EACH_1_32(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33)
+
+#define MU_FOR_EACH_1_32(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32) \
+X(P1) \
+MU_FOR_EACH_1_31(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32)
+
+#define MU_FOR_EACH_1_31(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31) \
+X(P1) \
+MU_FOR_EACH_1_30(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31)
+
+#define MU_FOR_EACH_1_30(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30) \
+X(P1) \
+MU_FOR_EACH_1_29(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30)
+
+#define MU_FOR_EACH_1_29(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29) \
+X(P1) \
+MU_FOR_EACH_1_28(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29)
+
+#define MU_FOR_EACH_1_28(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28) \
+X(P1) \
+MU_FOR_EACH_1_27(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28)
+
+#define MU_FOR_EACH_1_27(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27) \
+X(P1) \
+MU_FOR_EACH_1_26(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27)
+
+#define MU_FOR_EACH_1_26(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26) \
+X(P1) \
+MU_FOR_EACH_1_25(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26)
+
+#define MU_FOR_EACH_1_25(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25) \
+X(P1) \
+MU_FOR_EACH_1_24(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25)
+
+#define MU_FOR_EACH_1_24(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24) \
+X(P1) \
+MU_FOR_EACH_1_23(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24)
+
+#define MU_FOR_EACH_1_23(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23) \
+X(P1) \
+MU_FOR_EACH_1_22(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23)
+
+#define MU_FOR_EACH_1_22(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22) \
+X(P1) \
+MU_FOR_EACH_1_21(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22)
+
+#define MU_FOR_EACH_1_21(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21) \
+X(P1) \
+MU_FOR_EACH_1_20(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21)
+
+#define MU_FOR_EACH_1_20(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20) \
+X(P1) \
+MU_FOR_EACH_1_19(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20)
+
+#define MU_FOR_EACH_1_19(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19) \
+X(P1) \
+MU_FOR_EACH_1_18(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19)
+
+#define MU_FOR_EACH_1_18(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18) \
+X(P1) \
+MU_FOR_EACH_1_17(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18)
+
+#define MU_FOR_EACH_1_17(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17) \
+X(P1) \
+MU_FOR_EACH_1_16(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17)
+
+#define MU_FOR_EACH_1_16(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16) \
+X(P1) \
+MU_FOR_EACH_1_15(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16)
+
+#define MU_FOR_EACH_1_15(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15) \
+X(P1) \
+MU_FOR_EACH_1_14(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15)
+
+#define MU_FOR_EACH_1_14(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14) \
+X(P1) \
+MU_FOR_EACH_1_13(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14)
+
+#define MU_FOR_EACH_1_13(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13) \
+X(P1) \
+MU_FOR_EACH_1_12(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13)
+
+#define MU_FOR_EACH_1_12(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) \
+X(P1) \
+MU_FOR_EACH_1_11(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12)
+
+#define MU_FOR_EACH_1_11(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11) \
+X(P1) \
+MU_FOR_EACH_1_10(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11)
+
+#define MU_FOR_EACH_1_10(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) \
+X(P1) \
+MU_FOR_EACH_1_9(X, P2, P3, P4, P5, P6, P7, P8, P9, P10)
+
+#define MU_FOR_EACH_1_9(X, P1, P2, P3, P4, P5, P6, P7, P8, P9) \
+X(P1) \
+MU_FOR_EACH_1_8(X, P2, P3, P4, P5, P6, P7, P8, P9)
+
+#define MU_FOR_EACH_1_8(X, P1, P2, P3, P4, P5, P6, P7, P8) \
+X(P1) \
+MU_FOR_EACH_1_7(X, P2, P3, P4, P5, P6, P7, P8)
+
+#define MU_FOR_EACH_1_7(X, P1, P2, P3, P4, P5, P6, P7) \
+X(P1) \
+MU_FOR_EACH_1_6(X, P2, P3, P4, P5, P6, P7)
+
+#define MU_FOR_EACH_1_6(X, P1, P2, P3, P4, P5, P6) \
+X(P1) \
+MU_FOR_EACH_1_5(X, P2, P3, P4, P5, P6)
+
+#define MU_FOR_EACH_1_5(X, P1, P2, P3, P4, P5) \
+X(P1) \
+MU_FOR_EACH_1_4(X, P2, P3, P4, P5)
+
+#define MU_FOR_EACH_1_4(X, P1, P2, P3, P4) \
+X(P1) \
+MU_FOR_EACH_1_3(X, P2, P3, P4)
+
+#define MU_FOR_EACH_1_3(X, P1, P2, P3) \
+X(P1) \
+MU_FOR_EACH_1_2(X, P2, P3)
+
+#define MU_FOR_EACH_1_2(X, P1, P2) \
+X(P1) \
+MU_FOR_EACH_1_1(X, P2)
+
+#define MU_FOR_EACH_1_1(X, P1) \
+X(P1)
+
+#ifdef _MSC_VER
+#define MU_FOR_EACH_1(MACRO_TO_INVOKE, ...) MU_C2(MU_FOR_EACH_1_,MU_C1(MU_COUNT_ARG(__VA_ARGS__))) MU_LPAREN MACRO_TO_INVOKE, __VA_ARGS__)
+#else
+#define MU_FOR_EACH_1(MACRO_TO_INVOKE, ...) MU_C2(MU_FOR_EACH_1_,MU_C1(MU_COUNT_ARG(__VA_ARGS__))) ( MACRO_TO_INVOKE, __VA_ARGS__)
+#endif
+
+#define MU_FOR_EACH_1_KEEP_1_124(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123, P124) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_123(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123, P124)
+
+
+#define MU_FOR_EACH_1_KEEP_1_123(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_122(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123)
+
+
+#define MU_FOR_EACH_1_KEEP_1_122(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_121(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122)
+
+
+#define MU_FOR_EACH_1_KEEP_1_121(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_120(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121)
+
+
+#define MU_FOR_EACH_1_KEEP_1_120(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_119(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120)
+
+
+#define MU_FOR_EACH_1_KEEP_1_119(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_118(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119)
+
+
+#define MU_FOR_EACH_1_KEEP_1_118(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_117(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118)
+
+
+#define MU_FOR_EACH_1_KEEP_1_117(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_116(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117)
+
+
+#define MU_FOR_EACH_1_KEEP_1_116(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_115(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116)
+
+
+#define MU_FOR_EACH_1_KEEP_1_115(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_114(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115)
+
+
+#define MU_FOR_EACH_1_KEEP_1_114(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_113(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114)
+
+
+#define MU_FOR_EACH_1_KEEP_1_113(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_112(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113)
+
+
+#define MU_FOR_EACH_1_KEEP_1_112(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_111(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112)
+
+
+#define MU_FOR_EACH_1_KEEP_1_111(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_110(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111)
+
+
+#define MU_FOR_EACH_1_KEEP_1_110(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_109(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110)
+
+
+#define MU_FOR_EACH_1_KEEP_1_109(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_108(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109)
+
+
+#define MU_FOR_EACH_1_KEEP_1_108(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_107(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108)
+
+
+#define MU_FOR_EACH_1_KEEP_1_107(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_106(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107)
+
+
+#define MU_FOR_EACH_1_KEEP_1_106(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_105(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106)
+
+
+#define MU_FOR_EACH_1_KEEP_1_105(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_104(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105)
+
+
+#define MU_FOR_EACH_1_KEEP_1_104(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_103(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104)
+
+
+#define MU_FOR_EACH_1_KEEP_1_103(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_102(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103)
+
+
+#define MU_FOR_EACH_1_KEEP_1_102(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_101(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102)
+
+
+#define MU_FOR_EACH_1_KEEP_1_101(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_100(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101)
+
+
+#define MU_FOR_EACH_1_KEEP_1_100(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_99(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100)
+
+
+#define MU_FOR_EACH_1_KEEP_1_99(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_98(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99)
+
+
+#define MU_FOR_EACH_1_KEEP_1_98(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_97(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98)
+
+
+#define MU_FOR_EACH_1_KEEP_1_97(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_96(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97)
+
+
+#define MU_FOR_EACH_1_KEEP_1_96(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_95(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96)
+
+
+#define MU_FOR_EACH_1_KEEP_1_95(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_94(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95)
+
+
+#define MU_FOR_EACH_1_KEEP_1_94(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_93(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94)
+
+
+#define MU_FOR_EACH_1_KEEP_1_93(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_92(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93)
+
+
+#define MU_FOR_EACH_1_KEEP_1_92(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_91(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92)
+
+
+#define MU_FOR_EACH_1_KEEP_1_91(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_90(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91)
+
+
+#define MU_FOR_EACH_1_KEEP_1_90(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_89(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90)
+
+
+#define MU_FOR_EACH_1_KEEP_1_89(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_88(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89)
+
+
+#define MU_FOR_EACH_1_KEEP_1_88(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_87(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88)
+
+
+#define MU_FOR_EACH_1_KEEP_1_87(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_86(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87)
+
+
+#define MU_FOR_EACH_1_KEEP_1_86(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_85(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86)
+
+
+#define MU_FOR_EACH_1_KEEP_1_85(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_84(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85)
+
+
+#define MU_FOR_EACH_1_KEEP_1_84(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_83(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84)
+
+
+#define MU_FOR_EACH_1_KEEP_1_83(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_82(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83)
+
+
+#define MU_FOR_EACH_1_KEEP_1_82(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_81(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82)
+
+
+#define MU_FOR_EACH_1_KEEP_1_81(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_80(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81)
+
+
+#define MU_FOR_EACH_1_KEEP_1_80(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_79(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80)
+
+
+#define MU_FOR_EACH_1_KEEP_1_79(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_78(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79)
+
+
+#define MU_FOR_EACH_1_KEEP_1_78(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_77(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78)
+
+
+#define MU_FOR_EACH_1_KEEP_1_77(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_76(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77)
+
+
+#define MU_FOR_EACH_1_KEEP_1_76(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_75(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76)
+
+
+#define MU_FOR_EACH_1_KEEP_1_75(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_74(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75)
+
+
+#define MU_FOR_EACH_1_KEEP_1_74(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_73(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74)
+
+
+#define MU_FOR_EACH_1_KEEP_1_73(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_72(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73)
+
+
+#define MU_FOR_EACH_1_KEEP_1_72(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_71(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72)
+
+
+#define MU_FOR_EACH_1_KEEP_1_71(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_70(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71)
+
+
+#define MU_FOR_EACH_1_KEEP_1_70(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_69(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70)
+
+
+#define MU_FOR_EACH_1_KEEP_1_69(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_68(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69)
+
+
+#define MU_FOR_EACH_1_KEEP_1_68(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_67(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68)
+
+
+#define MU_FOR_EACH_1_KEEP_1_67(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_66(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67)
+
+
+#define MU_FOR_EACH_1_KEEP_1_66(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_65(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66)
+
+
+#define MU_FOR_EACH_1_KEEP_1_65(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_64(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65)
+
+
+#define MU_FOR_EACH_1_KEEP_1_64(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_63(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64)
+
+
+#define MU_FOR_EACH_1_KEEP_1_63(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_62(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63)
+
+
+#define MU_FOR_EACH_1_KEEP_1_62(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_61(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62)
+
+
+#define MU_FOR_EACH_1_KEEP_1_61(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_60(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61)
+
+
+#define MU_FOR_EACH_1_KEEP_1_60(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_59(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60)
+
+
+#define MU_FOR_EACH_1_KEEP_1_59(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_58(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59)
+
+
+#define MU_FOR_EACH_1_KEEP_1_58(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_57(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58)
+
+
+#define MU_FOR_EACH_1_KEEP_1_57(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_56(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57)
+
+
+#define MU_FOR_EACH_1_KEEP_1_56(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_55(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56)
+
+
+#define MU_FOR_EACH_1_KEEP_1_55(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_54(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55)
+
+
+#define MU_FOR_EACH_1_KEEP_1_54(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_53(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54)
+
+
+#define MU_FOR_EACH_1_KEEP_1_53(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_52(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53)
+
+
+#define MU_FOR_EACH_1_KEEP_1_52(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_51(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52)
+
+
+#define MU_FOR_EACH_1_KEEP_1_51(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_50(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51)
+
+
+#define MU_FOR_EACH_1_KEEP_1_50(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_49(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50)
+
+
+#define MU_FOR_EACH_1_KEEP_1_49(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_48(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49)
+
+
+#define MU_FOR_EACH_1_KEEP_1_48(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_47(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48)
+
+
+#define MU_FOR_EACH_1_KEEP_1_47(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_46(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47)
+
+
+#define MU_FOR_EACH_1_KEEP_1_46(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_45(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46)
+
+
+#define MU_FOR_EACH_1_KEEP_1_45(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_44(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45)
+
+
+#define MU_FOR_EACH_1_KEEP_1_44(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_43(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44)
+
+
+#define MU_FOR_EACH_1_KEEP_1_43(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_42(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43)
+
+
+#define MU_FOR_EACH_1_KEEP_1_42(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_41(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42)
+
+
+#define MU_FOR_EACH_1_KEEP_1_41(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_40(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41)
+
+
+#define MU_FOR_EACH_1_KEEP_1_40(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_39(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40)
+
+
+#define MU_FOR_EACH_1_KEEP_1_39(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_38(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39)
+
+
+#define MU_FOR_EACH_1_KEEP_1_38(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_37(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38)
+
+
+#define MU_FOR_EACH_1_KEEP_1_37(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_36(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37)
+
+
+#define MU_FOR_EACH_1_KEEP_1_36(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_35(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36)
+
+
+#define MU_FOR_EACH_1_KEEP_1_35(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_34(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35)
+
+
+#define MU_FOR_EACH_1_KEEP_1_34(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_33(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34)
+
+
+#define MU_FOR_EACH_1_KEEP_1_33(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_32(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33)
+
+
+#define MU_FOR_EACH_1_KEEP_1_32(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_31(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32)
+
+
+#define MU_FOR_EACH_1_KEEP_1_31(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_30(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31)
+
+
+#define MU_FOR_EACH_1_KEEP_1_30(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_29(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30)
+
+
+#define MU_FOR_EACH_1_KEEP_1_29(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_28(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29)
+
+
+#define MU_FOR_EACH_1_KEEP_1_28(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_27(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28)
+
+
+#define MU_FOR_EACH_1_KEEP_1_27(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_26(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27)
+
+
+#define MU_FOR_EACH_1_KEEP_1_26(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_25(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26)
+
+
+#define MU_FOR_EACH_1_KEEP_1_25(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_24(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25)
+
+
+#define MU_FOR_EACH_1_KEEP_1_24(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_23(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24)
+
+
+#define MU_FOR_EACH_1_KEEP_1_23(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_22(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23)
+
+
+#define MU_FOR_EACH_1_KEEP_1_22(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_21(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22)
+
+
+#define MU_FOR_EACH_1_KEEP_1_21(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_20(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21)
+
+
+#define MU_FOR_EACH_1_KEEP_1_20(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_19(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20)
+
+
+#define MU_FOR_EACH_1_KEEP_1_19(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_18(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19)
+
+
+#define MU_FOR_EACH_1_KEEP_1_18(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_17(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18)
+
+
+#define MU_FOR_EACH_1_KEEP_1_17(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_16(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17)
+
+
+#define MU_FOR_EACH_1_KEEP_1_16(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_15(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16)
+
+
+#define MU_FOR_EACH_1_KEEP_1_15(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_14(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15)
+
+
+#define MU_FOR_EACH_1_KEEP_1_14(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_13(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14)
+
+
+#define MU_FOR_EACH_1_KEEP_1_13(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_12(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13)
+
+
+#define MU_FOR_EACH_1_KEEP_1_12(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_11(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12)
+
+
+#define MU_FOR_EACH_1_KEEP_1_11(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_10(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11)
+
+
+#define MU_FOR_EACH_1_KEEP_1_10(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_9(X, keep, P2, P3, P4, P5, P6, P7, P8, P9, P10)
+
+
+#define MU_FOR_EACH_1_KEEP_1_9(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_8(X, keep, P2, P3, P4, P5, P6, P7, P8, P9)
+
+
+#define MU_FOR_EACH_1_KEEP_1_8(X, keep, P1, P2, P3, P4, P5, P6, P7, P8) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_7(X, keep, P2, P3, P4, P5, P6, P7, P8)
+
+
+#define MU_FOR_EACH_1_KEEP_1_7(X, keep, P1, P2, P3, P4, P5, P6, P7) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_6(X, keep, P2, P3, P4, P5, P6, P7)
+
+
+#define MU_FOR_EACH_1_KEEP_1_6(X, keep, P1, P2, P3, P4, P5, P6) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_5(X, keep, P2, P3, P4, P5, P6)
+
+
+#define MU_FOR_EACH_1_KEEP_1_5(X, keep, P1, P2, P3, P4, P5) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_4(X, keep, P2, P3, P4, P5)
+
+
+#define MU_FOR_EACH_1_KEEP_1_4(X, keep, P1, P2, P3, P4) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_3(X, keep, P2, P3, P4)
+
+
+#define MU_FOR_EACH_1_KEEP_1_3(X, keep, P1, P2, P3) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_2(X, keep, P2, P3)
+
+
+#define MU_FOR_EACH_1_KEEP_1_2(X, keep, P1, P2) \
+X(keep, P1) \
+MU_FOR_EACH_1_KEEP_1_1(X, keep, P2)
+
+
+
+#define MU_FOR_EACH_1_KEEP_1_1(X, keep, P1) \
+X(keep, P1)
+
+#ifdef _MSC_VER
+#define MU_FOR_EACH_1_KEEP_1(MACRO_TO_INVOKE, ...) MU_C2(MU_FOR_EACH_1_KEEP_1_, MU_C2(MU_DEC,MU_C1(MU_COUNT_ARG(__VA_ARGS__)))) MU_LPAREN MACRO_TO_INVOKE, __VA_ARGS__)
+#else
+#define MU_FOR_EACH_1_KEEP_1(MACRO_TO_INVOKE, ...) MU_C2(MU_FOR_EACH_1_KEEP_1_, MU_C2(MU_DEC,MU_C1(MU_COUNT_ARG(__VA_ARGS__)))) ( MACRO_TO_INVOKE, __VA_ARGS__)
+#endif
+
+#define MU_FOR_EACH_1_KEEP_2_124(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123, P124) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_123(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123, P124)
+
+
+#define MU_FOR_EACH_1_KEEP_2_123(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_122(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123)
+
+
+#define MU_FOR_EACH_1_KEEP_2_122(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_121(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122)
+
+
+#define MU_FOR_EACH_1_KEEP_2_121(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_120(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121)
+
+
+#define MU_FOR_EACH_1_KEEP_2_120(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_119(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120)
+
+
+#define MU_FOR_EACH_1_KEEP_2_119(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_118(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119)
+
+
+#define MU_FOR_EACH_1_KEEP_2_118(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_117(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118)
+
+
+#define MU_FOR_EACH_1_KEEP_2_117(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_116(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117)
+
+
+#define MU_FOR_EACH_1_KEEP_2_116(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_115(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116)
+
+
+#define MU_FOR_EACH_1_KEEP_2_115(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_114(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115)
+
+
+#define MU_FOR_EACH_1_KEEP_2_114(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_113(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114)
+
+
+#define MU_FOR_EACH_1_KEEP_2_113(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_112(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113)
+
+
+#define MU_FOR_EACH_1_KEEP_2_112(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_111(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112)
+
+
+#define MU_FOR_EACH_1_KEEP_2_111(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_110(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111)
+
+
+#define MU_FOR_EACH_1_KEEP_2_110(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_109(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110)
+
+
+#define MU_FOR_EACH_1_KEEP_2_109(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_108(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109)
+
+
+#define MU_FOR_EACH_1_KEEP_2_108(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_107(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108)
+
+
+#define MU_FOR_EACH_1_KEEP_2_107(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_106(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107)
+
+
+#define MU_FOR_EACH_1_KEEP_2_106(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_105(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106)
+
+
+#define MU_FOR_EACH_1_KEEP_2_105(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_104(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105)
+
+
+#define MU_FOR_EACH_1_KEEP_2_104(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_103(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104)
+
+
+#define MU_FOR_EACH_1_KEEP_2_103(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_102(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103)
+
+
+#define MU_FOR_EACH_1_KEEP_2_102(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_101(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102)
+
+
+#define MU_FOR_EACH_1_KEEP_2_101(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_100(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101)
+
+
+#define MU_FOR_EACH_1_KEEP_2_100(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_99(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100)
+
+
+#define MU_FOR_EACH_1_KEEP_2_99(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_98(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99)
+
+
+#define MU_FOR_EACH_1_KEEP_2_98(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_97(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98)
+
+
+#define MU_FOR_EACH_1_KEEP_2_97(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_96(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97)
+
+
+#define MU_FOR_EACH_1_KEEP_2_96(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_95(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96)
+
+
+#define MU_FOR_EACH_1_KEEP_2_95(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_94(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95)
+
+
+#define MU_FOR_EACH_1_KEEP_2_94(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_93(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94)
+
+
+#define MU_FOR_EACH_1_KEEP_2_93(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_92(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93)
+
+
+#define MU_FOR_EACH_1_KEEP_2_92(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_91(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92)
+
+
+#define MU_FOR_EACH_1_KEEP_2_91(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_90(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91)
+
+
+#define MU_FOR_EACH_1_KEEP_2_90(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_89(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90)
+
+
+#define MU_FOR_EACH_1_KEEP_2_89(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_88(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89)
+
+
+#define MU_FOR_EACH_1_KEEP_2_88(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_87(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88)
+
+
+#define MU_FOR_EACH_1_KEEP_2_87(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_86(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87)
+
+
+#define MU_FOR_EACH_1_KEEP_2_86(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_85(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86)
+
+
+#define MU_FOR_EACH_1_KEEP_2_85(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_84(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85)
+
+
+#define MU_FOR_EACH_1_KEEP_2_84(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_83(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84)
+
+
+#define MU_FOR_EACH_1_KEEP_2_83(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_82(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83)
+
+
+#define MU_FOR_EACH_1_KEEP_2_82(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_81(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82)
+
+
+#define MU_FOR_EACH_1_KEEP_2_81(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_80(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81)
+
+
+#define MU_FOR_EACH_1_KEEP_2_80(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_79(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80)
+
+
+#define MU_FOR_EACH_1_KEEP_2_79(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_78(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79)
+
+
+#define MU_FOR_EACH_1_KEEP_2_78(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_77(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78)
+
+
+#define MU_FOR_EACH_1_KEEP_2_77(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_76(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77)
+
+
+#define MU_FOR_EACH_1_KEEP_2_76(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_75(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76)
+
+
+#define MU_FOR_EACH_1_KEEP_2_75(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_74(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75)
+
+
+#define MU_FOR_EACH_1_KEEP_2_74(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_73(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74)
+
+
+#define MU_FOR_EACH_1_KEEP_2_73(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_72(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73)
+
+
+#define MU_FOR_EACH_1_KEEP_2_72(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_71(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72)
+
+
+#define MU_FOR_EACH_1_KEEP_2_71(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_70(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71)
+
+
+#define MU_FOR_EACH_1_KEEP_2_70(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_69(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70)
+
+
+#define MU_FOR_EACH_1_KEEP_2_69(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_68(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69)
+
+
+#define MU_FOR_EACH_1_KEEP_2_68(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_67(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68)
+
+
+#define MU_FOR_EACH_1_KEEP_2_67(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_66(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67)
+
+
+#define MU_FOR_EACH_1_KEEP_2_66(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_65(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66)
+
+
+#define MU_FOR_EACH_1_KEEP_2_65(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_64(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65)
+
+
+#define MU_FOR_EACH_1_KEEP_2_64(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_63(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64)
+
+
+#define MU_FOR_EACH_1_KEEP_2_63(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_62(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63)
+
+
+#define MU_FOR_EACH_1_KEEP_2_62(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_61(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62)
+
+
+#define MU_FOR_EACH_1_KEEP_2_61(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_60(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61)
+
+
+#define MU_FOR_EACH_1_KEEP_2_60(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_59(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60)
+
+
+#define MU_FOR_EACH_1_KEEP_2_59(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_58(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59)
+
+
+#define MU_FOR_EACH_1_KEEP_2_58(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_57(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58)
+
+
+#define MU_FOR_EACH_1_KEEP_2_57(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_56(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57)
+
+
+#define MU_FOR_EACH_1_KEEP_2_56(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_55(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56)
+
+
+#define MU_FOR_EACH_1_KEEP_2_55(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_54(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55)
+
+
+#define MU_FOR_EACH_1_KEEP_2_54(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_53(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54)
+
+
+#define MU_FOR_EACH_1_KEEP_2_53(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_52(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53)
+
+
+#define MU_FOR_EACH_1_KEEP_2_52(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_51(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52)
+
+
+#define MU_FOR_EACH_1_KEEP_2_51(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_50(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51)
+
+
+#define MU_FOR_EACH_1_KEEP_2_50(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_49(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50)
+
+
+#define MU_FOR_EACH_1_KEEP_2_49(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_48(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49)
+
+
+#define MU_FOR_EACH_1_KEEP_2_48(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_47(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48)
+
+
+#define MU_FOR_EACH_1_KEEP_2_47(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_46(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47)
+
+
+#define MU_FOR_EACH_1_KEEP_2_46(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_45(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46)
+
+
+#define MU_FOR_EACH_1_KEEP_2_45(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_44(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45)
+
+
+#define MU_FOR_EACH_1_KEEP_2_44(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_43(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44)
+
+
+#define MU_FOR_EACH_1_KEEP_2_43(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_42(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43)
+
+
+#define MU_FOR_EACH_1_KEEP_2_42(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_41(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42)
+
+
+#define MU_FOR_EACH_1_KEEP_2_41(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_40(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41)
+
+
+#define MU_FOR_EACH_1_KEEP_2_40(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_39(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40)
+
+
+#define MU_FOR_EACH_1_KEEP_2_39(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_38(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39)
+
+
+#define MU_FOR_EACH_1_KEEP_2_38(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_37(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38)
+
+
+#define MU_FOR_EACH_1_KEEP_2_37(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_36(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37)
+
+
+#define MU_FOR_EACH_1_KEEP_2_36(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_35(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36)
+
+
+#define MU_FOR_EACH_1_KEEP_2_35(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_34(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35)
+
+
+#define MU_FOR_EACH_1_KEEP_2_34(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_33(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34)
+
+
+#define MU_FOR_EACH_1_KEEP_2_33(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_32(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33)
+
+
+#define MU_FOR_EACH_1_KEEP_2_32(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_31(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32)
+
+
+#define MU_FOR_EACH_1_KEEP_2_31(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_30(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31)
+
+
+#define MU_FOR_EACH_1_KEEP_2_30(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_29(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30)
+
+
+#define MU_FOR_EACH_1_KEEP_2_29(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_28(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29)
+
+
+#define MU_FOR_EACH_1_KEEP_2_28(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_27(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28)
+
+
+#define MU_FOR_EACH_1_KEEP_2_27(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_26(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27)
+
+
+#define MU_FOR_EACH_1_KEEP_2_26(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_25(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26)
+
+
+#define MU_FOR_EACH_1_KEEP_2_25(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_24(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25)
+
+
+#define MU_FOR_EACH_1_KEEP_2_24(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_23(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24)
+
+
+#define MU_FOR_EACH_1_KEEP_2_23(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_22(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23)
+
+
+#define MU_FOR_EACH_1_KEEP_2_22(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_21(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22)
+
+
+#define MU_FOR_EACH_1_KEEP_2_21(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_20(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21)
+
+
+#define MU_FOR_EACH_1_KEEP_2_20(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_19(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20)
+
+
+#define MU_FOR_EACH_1_KEEP_2_19(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_18(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19)
+
+
+#define MU_FOR_EACH_1_KEEP_2_18(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_17(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18)
+
+
+#define MU_FOR_EACH_1_KEEP_2_17(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_16(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17)
+
+
+#define MU_FOR_EACH_1_KEEP_2_16(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_15(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16)
+
+
+#define MU_FOR_EACH_1_KEEP_2_15(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_14(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15)
+
+
+#define MU_FOR_EACH_1_KEEP_2_14(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_13(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14)
+
+
+#define MU_FOR_EACH_1_KEEP_2_13(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_12(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13)
+
+
+#define MU_FOR_EACH_1_KEEP_2_12(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_11(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12)
+
+
+#define MU_FOR_EACH_1_KEEP_2_11(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_10(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11)
+
+
+#define MU_FOR_EACH_1_KEEP_2_10(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_9(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9, P10)
+
+
+#define MU_FOR_EACH_1_KEEP_2_9(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_8(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8, P9)
+
+
+#define MU_FOR_EACH_1_KEEP_2_8(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_7(X, keep1, keep2, P2, P3, P4, P5, P6, P7, P8)
+
+
+#define MU_FOR_EACH_1_KEEP_2_7(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_6(X, keep1, keep2, P2, P3, P4, P5, P6, P7)
+
+
+#define MU_FOR_EACH_1_KEEP_2_6(X, keep1, keep2, P1, P2, P3, P4, P5, P6) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_5(X, keep1, keep2, P2, P3, P4, P5, P6)
+
+
+#define MU_FOR_EACH_1_KEEP_2_5(X, keep1, keep2, P1, P2, P3, P4, P5) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_4(X, keep1, keep2, P2, P3, P4, P5)
+
+
+#define MU_FOR_EACH_1_KEEP_2_4(X, keep1, keep2, P1, P2, P3, P4) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_3(X, keep1, keep2, P2, P3, P4)
+
+
+#define MU_FOR_EACH_1_KEEP_2_3(X, keep1, keep2, P1, P2, P3) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_2(X, keep1, keep2, P2, P3)
+
+
+#define MU_FOR_EACH_1_KEEP_2_2(X, keep1, keep2, P1, P2) \
+X(keep1, keep2, P1) \
+MU_FOR_EACH_1_KEEP_2_1(X, keep1, keep2, P2)
+
+
+
+#define MU_FOR_EACH_1_KEEP_2_1(X, keep1, keep2, P1) \
+X(keep1, keep2, P1)
+
+#define MU_FOR_EACH_1_KEEP_2_0(...)
+
+#ifdef _MSC_VER
+#define MU_FOR_EACH_1_KEEP_2(MACRO_TO_INVOKE, ...) MU_C2(MU_FOR_EACH_1_KEEP_2_, MU_C2(MU_DEC,MU_C2(MU_DEC,MU_C1(MU_COUNT_ARG(__VA_ARGS__))))) MU_LPAREN MACRO_TO_INVOKE, __VA_ARGS__)
+#else
+#define MU_FOR_EACH_1_KEEP_2(MACRO_TO_INVOKE, ...) MU_C2(MU_FOR_EACH_1_KEEP_2_, MU_C2(MU_DEC,MU_C2(MU_DEC,MU_C1(MU_COUNT_ARG(__VA_ARGS__))))) ( MACRO_TO_INVOKE, __VA_ARGS__)
+#endif
+
+#define MU_FOR_EACH_2_KEEP_1_124(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123, P124) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_122(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123, P124)
+
+
+#define MU_FOR_EACH_2_KEEP_1_122(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_120(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122)
+
+
+#define MU_FOR_EACH_2_KEEP_1_120(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_118(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120)
+
+
+#define MU_FOR_EACH_2_KEEP_1_118(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_116(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118)
+
+
+#define MU_FOR_EACH_2_KEEP_1_116(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_114(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116)
+
+
+#define MU_FOR_EACH_2_KEEP_1_114(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_112(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114)
+
+
+#define MU_FOR_EACH_2_KEEP_1_112(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_110(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112)
+
+
+#define MU_FOR_EACH_2_KEEP_1_110(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_108(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110)
+
+
+#define MU_FOR_EACH_2_KEEP_1_108(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_106(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108)
+
+
+#define MU_FOR_EACH_2_KEEP_1_106(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_104(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106)
+
+
+#define MU_FOR_EACH_2_KEEP_1_104(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_102(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104)
+
+
+#define MU_FOR_EACH_2_KEEP_1_102(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_100(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102)
+
+
+#define MU_FOR_EACH_2_KEEP_1_100(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_98(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100)
+
+
+#define MU_FOR_EACH_2_KEEP_1_98(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_96(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98)
+
+
+#define MU_FOR_EACH_2_KEEP_1_96(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_94(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96)
+
+
+#define MU_FOR_EACH_2_KEEP_1_94(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_92(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94)
+
+
+#define MU_FOR_EACH_2_KEEP_1_92(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_90(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92)
+
+
+#define MU_FOR_EACH_2_KEEP_1_90(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_88(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90)
+
+
+#define MU_FOR_EACH_2_KEEP_1_88(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_86(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88)
+
+
+#define MU_FOR_EACH_2_KEEP_1_86(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_84(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86)
+
+
+#define MU_FOR_EACH_2_KEEP_1_84(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_82(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84)
+
+
+#define MU_FOR_EACH_2_KEEP_1_82(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_80(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82)
+
+
+#define MU_FOR_EACH_2_KEEP_1_80(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_78(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80)
+
+
+#define MU_FOR_EACH_2_KEEP_1_78(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_76(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78)
+
+
+#define MU_FOR_EACH_2_KEEP_1_76(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_74(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76)
+
+
+#define MU_FOR_EACH_2_KEEP_1_74(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_72(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74)
+
+
+#define MU_FOR_EACH_2_KEEP_1_72(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_70(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72)
+
+
+#define MU_FOR_EACH_2_KEEP_1_70(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_68(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70)
+
+
+#define MU_FOR_EACH_2_KEEP_1_68(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_66(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68)
+
+
+#define MU_FOR_EACH_2_KEEP_1_66(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_64(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66)
+
+
+#define MU_FOR_EACH_2_KEEP_1_64(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_62(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64)
+
+
+#define MU_FOR_EACH_2_KEEP_1_62(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_60(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62)
+
+
+#define MU_FOR_EACH_2_KEEP_1_60(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_58(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60)
+
+
+#define MU_FOR_EACH_2_KEEP_1_58(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_56(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58)
+
+
+#define MU_FOR_EACH_2_KEEP_1_56(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_54(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56)
+
+
+#define MU_FOR_EACH_2_KEEP_1_54(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_52(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54)
+
+
+#define MU_FOR_EACH_2_KEEP_1_52(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_50(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52)
+
+
+#define MU_FOR_EACH_2_KEEP_1_50(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_48(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50)
+
+
+#define MU_FOR_EACH_2_KEEP_1_48(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_46(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48)
+
+
+#define MU_FOR_EACH_2_KEEP_1_46(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_44(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46)
+
+
+#define MU_FOR_EACH_2_KEEP_1_44(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_42(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44)
+
+
+#define MU_FOR_EACH_2_KEEP_1_42(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_40(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42)
+
+
+#define MU_FOR_EACH_2_KEEP_1_40(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_38(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40)
+
+
+#define MU_FOR_EACH_2_KEEP_1_38(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_36(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38)
+
+
+#define MU_FOR_EACH_2_KEEP_1_36(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_34(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36)
+
+
+#define MU_FOR_EACH_2_KEEP_1_34(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_32(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34)
+
+
+#define MU_FOR_EACH_2_KEEP_1_32(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_30(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32)
+
+
+#define MU_FOR_EACH_2_KEEP_1_30(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_28(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30)
+
+
+#define MU_FOR_EACH_2_KEEP_1_28(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_26(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28)
+
+
+#define MU_FOR_EACH_2_KEEP_1_26(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_24(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26)
+
+
+#define MU_FOR_EACH_2_KEEP_1_24(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_22(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24)
+
+
+#define MU_FOR_EACH_2_KEEP_1_22(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_20(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22)
+
+
+#define MU_FOR_EACH_2_KEEP_1_20(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_18(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20)
+
+
+#define MU_FOR_EACH_2_KEEP_1_18(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_16(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18)
+
+
+#define MU_FOR_EACH_2_KEEP_1_16(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_14(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16)
+
+
+#define MU_FOR_EACH_2_KEEP_1_14(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_12(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14)
+
+
+#define MU_FOR_EACH_2_KEEP_1_12(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_10(X, keep, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12)
+
+
+#define MU_FOR_EACH_2_KEEP_1_10(X, keep, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_8(X, keep, P3, P4, P5, P6, P7, P8, P9, P10)
+
+
+#define MU_FOR_EACH_2_KEEP_1_8(X, keep, P1, P2, P3, P4, P5, P6, P7, P8) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_6(X, keep, P3, P4, P5, P6, P7, P8)
+
+
+#define MU_FOR_EACH_2_KEEP_1_6(X, keep, P1, P2, P3, P4, P5, P6) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_4(X, keep, P3, P4, P5, P6)
+
+
+#define MU_FOR_EACH_2_KEEP_1_4(X, keep, P1, P2, P3, P4) \
+X(keep, P1, P2) \
+MU_FOR_EACH_2_KEEP_1_2(X, keep, P3, P4)
+
+
+
+#define MU_FOR_EACH_2_KEEP_1_1(...)
+
+#define MU_FOR_EACH_2_KEEP_1_0(...)
+
+#define MU_FOR_EACH_2_KEEP_1_2(X, keep, P1, P2) \
+    X(keep, P1, P2) \
+
+#ifdef _MSC_VER
+#define MU_FOR_EACH_2_KEEP_1(MACRO_TO_INVOKE, ...) MU_C2(MU_FOR_EACH_2_KEEP_1_, MU_C2(MU_DEC,MU_C1(MU_COUNT_ARG(__VA_ARGS__)))) MU_LPAREN MACRO_TO_INVOKE, __VA_ARGS__)
+#else
+#define MU_FOR_EACH_2_KEEP_1(MACRO_TO_INVOKE, ...) MU_C2(MU_FOR_EACH_2_KEEP_1_, MU_C2(MU_DEC,MU_C1(MU_COUNT_ARG(__VA_ARGS__)))) ( MACRO_TO_INVOKE, __VA_ARGS__)
+#endif
+
+
+#define MU_FOR_EACH_2_KEEP_2_124(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123, P124) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_122(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123, P124)
+
+
+#define MU_FOR_EACH_2_KEEP_2_122(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_120(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122)
+
+
+#define MU_FOR_EACH_2_KEEP_2_120(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_118(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120)
+
+
+#define MU_FOR_EACH_2_KEEP_2_118(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_116(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118)
+
+
+#define MU_FOR_EACH_2_KEEP_2_116(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_114(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116)
+
+
+#define MU_FOR_EACH_2_KEEP_2_114(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_112(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114)
+
+
+#define MU_FOR_EACH_2_KEEP_2_112(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_110(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112)
+
+
+#define MU_FOR_EACH_2_KEEP_2_110(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_108(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110)
+
+
+#define MU_FOR_EACH_2_KEEP_2_108(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_106(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108)
+
+
+#define MU_FOR_EACH_2_KEEP_2_106(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_104(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106)
+
+
+#define MU_FOR_EACH_2_KEEP_2_104(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_102(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104)
+
+
+#define MU_FOR_EACH_2_KEEP_2_102(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_100(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102)
+
+
+#define MU_FOR_EACH_2_KEEP_2_100(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_98(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100)
+
+
+#define MU_FOR_EACH_2_KEEP_2_98(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_96(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98)
+
+
+#define MU_FOR_EACH_2_KEEP_2_96(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_94(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96)
+
+
+#define MU_FOR_EACH_2_KEEP_2_94(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_92(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94)
+
+
+#define MU_FOR_EACH_2_KEEP_2_92(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_90(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92)
+
+
+#define MU_FOR_EACH_2_KEEP_2_90(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_88(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90)
+
+
+#define MU_FOR_EACH_2_KEEP_2_88(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_86(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88)
+
+
+#define MU_FOR_EACH_2_KEEP_2_86(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_84(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86)
+
+
+#define MU_FOR_EACH_2_KEEP_2_84(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_82(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84)
+
+
+#define MU_FOR_EACH_2_KEEP_2_82(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_80(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82)
+
+
+#define MU_FOR_EACH_2_KEEP_2_80(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_78(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80)
+
+
+#define MU_FOR_EACH_2_KEEP_2_78(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_76(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78)
+
+
+#define MU_FOR_EACH_2_KEEP_2_76(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_74(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76)
+
+
+#define MU_FOR_EACH_2_KEEP_2_74(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_72(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74)
+
+
+#define MU_FOR_EACH_2_KEEP_2_72(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_70(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72)
+
+
+#define MU_FOR_EACH_2_KEEP_2_70(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_68(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70)
+
+
+#define MU_FOR_EACH_2_KEEP_2_68(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_66(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68)
+
+
+#define MU_FOR_EACH_2_KEEP_2_66(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_64(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66)
+
+
+#define MU_FOR_EACH_2_KEEP_2_64(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_62(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64)
+
+
+#define MU_FOR_EACH_2_KEEP_2_62(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_60(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62)
+
+
+#define MU_FOR_EACH_2_KEEP_2_60(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_58(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60)
+
+
+#define MU_FOR_EACH_2_KEEP_2_58(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_56(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58)
+
+
+#define MU_FOR_EACH_2_KEEP_2_56(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_54(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56)
+
+
+#define MU_FOR_EACH_2_KEEP_2_54(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_52(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54)
+
+
+#define MU_FOR_EACH_2_KEEP_2_52(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_50(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52)
+
+
+#define MU_FOR_EACH_2_KEEP_2_50(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_48(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50)
+
+
+#define MU_FOR_EACH_2_KEEP_2_48(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_46(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48)
+
+
+#define MU_FOR_EACH_2_KEEP_2_46(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_44(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46)
+
+
+#define MU_FOR_EACH_2_KEEP_2_44(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_42(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44)
+
+
+#define MU_FOR_EACH_2_KEEP_2_42(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_40(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42)
+
+
+#define MU_FOR_EACH_2_KEEP_2_40(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_38(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40)
+
+
+#define MU_FOR_EACH_2_KEEP_2_38(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_36(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38)
+
+
+#define MU_FOR_EACH_2_KEEP_2_36(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_34(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36)
+
+
+#define MU_FOR_EACH_2_KEEP_2_34(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_32(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34)
+
+
+#define MU_FOR_EACH_2_KEEP_2_32(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_30(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32)
+
+
+#define MU_FOR_EACH_2_KEEP_2_30(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_28(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30)
+
+
+#define MU_FOR_EACH_2_KEEP_2_28(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_26(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28)
+
+
+#define MU_FOR_EACH_2_KEEP_2_26(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_24(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26)
+
+
+#define MU_FOR_EACH_2_KEEP_2_24(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_22(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24)
+
+
+#define MU_FOR_EACH_2_KEEP_2_22(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_20(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22)
+
+
+#define MU_FOR_EACH_2_KEEP_2_20(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_18(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20)
+
+
+#define MU_FOR_EACH_2_KEEP_2_18(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_16(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18)
+
+
+#define MU_FOR_EACH_2_KEEP_2_16(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_14(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16)
+
+
+#define MU_FOR_EACH_2_KEEP_2_14(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_12(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14)
+
+
+#define MU_FOR_EACH_2_KEEP_2_12(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_10(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12)
+
+
+#define MU_FOR_EACH_2_KEEP_2_10(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_8(X, keep1, keep2, P3, P4, P5, P6, P7, P8, P9, P10)
+
+
+#define MU_FOR_EACH_2_KEEP_2_8(X, keep1, keep2, P1, P2, P3, P4, P5, P6, P7, P8) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_6(X, keep1, keep2, P3, P4, P5, P6, P7, P8)
+
+
+#define MU_FOR_EACH_2_KEEP_2_6(X, keep1, keep2, P1, P2, P3, P4, P5, P6) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_4(X, keep1, keep2, P3, P4, P5, P6)
+
+
+#define MU_FOR_EACH_2_KEEP_2_4(X, keep1, keep2, P1, P2, P3, P4) \
+X(keep1, keep2, P1, P2) \
+MU_FOR_EACH_2_KEEP_2_2(X, keep1, keep2, P3, P4)
+
+
+
+#define MU_FOR_EACH_2_KEEP_2_1(...)
+
+#define MU_FOR_EACH_2_KEEP_2_0(...)
+
+#define MU_FOR_EACH_2_KEEP_2_2(X, keep1, keep2, P1, P2) \
+    X(keep1, keep2, P1, P2) \
+
+#ifdef _MSC_VER
+#define MU_FOR_EACH_2_KEEP_2(MACRO_TO_INVOKE, ...) MU_C2(MU_FOR_EACH_2_KEEP_2_, MU_C2(MU_DEC,MU_C2(MU_DEC,MU_C1(MU_COUNT_ARG(__VA_ARGS__))))) MU_LPAREN MACRO_TO_INVOKE, __VA_ARGS__)
+#else
+#define MU_FOR_EACH_2_KEEP_2(MACRO_TO_INVOKE, ...) MU_C2(MU_FOR_EACH_2_KEEP_2_, MU_C2(MU_DEC, MU_C2(MU_DEC,MU_C1(MU_COUNT_ARG(__VA_ARGS__))))) ( MACRO_TO_INVOKE, __VA_ARGS__)
+#endif
+
+
+#define MU_FOR_EACH_2_0(...)
+
+#define MU_FOR_EACH_2_2(X, P1, P2) \
+X(P1, P2)
+
+#define MU_FOR_EACH_2_4(X, P1, P2, P3, P4) \
+X(P1, P2) \
+MU_FOR_EACH_2_2(X, P3, P4)
+
+#define MU_FOR_EACH_2_6(X, P1, P2, P3, P4, P5, P6) \
+X(P1, P2) \
+MU_FOR_EACH_2_4(X, P3, P4, P5, P6)
+
+#define MU_FOR_EACH_2_8(X, P1, P2, P3, P4, P5, P6, P7, P8) \
+X(P1, P2) \
+MU_FOR_EACH_2_6(X, P3, P4, P5, P6, P7, P8)
+
+#define MU_FOR_EACH_2_10(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) \
+X(P1, P2) \
+MU_FOR_EACH_2_8(X, P3, P4, P5, P6, P7, P8, P9, P10)
+
+#define MU_FOR_EACH_2_12(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) \
+X(P1, P2) \
+MU_FOR_EACH_2_10(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12)
+
+#define MU_FOR_EACH_2_14(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14) \
+X(P1, P2) \
+MU_FOR_EACH_2_12(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14)
+
+#define MU_FOR_EACH_2_16(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16) \
+X(P1, P2) \
+MU_FOR_EACH_2_14(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16)
+
+#define MU_FOR_EACH_2_18(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18) \
+X(P1, P2) \
+MU_FOR_EACH_2_16(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18)
+
+#define MU_FOR_EACH_2_20(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20) \
+X(P1, P2) \
+MU_FOR_EACH_2_18(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20)
+
+#define MU_FOR_EACH_2_22(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22) \
+X(P1, P2) \
+MU_FOR_EACH_2_20(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22)
+
+#define MU_FOR_EACH_2_24(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24) \
+X(P1, P2) \
+MU_FOR_EACH_2_22(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24)
+
+#define MU_FOR_EACH_2_26(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26) \
+X(P1, P2) \
+MU_FOR_EACH_2_24(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26)
+
+#define MU_FOR_EACH_2_28(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28) \
+X(P1, P2) \
+MU_FOR_EACH_2_26(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28)
+
+#define MU_FOR_EACH_2_30(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30) \
+X(P1, P2) \
+MU_FOR_EACH_2_28(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30)
+
+#define MU_FOR_EACH_2_32(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32) \
+X(P1, P2) \
+MU_FOR_EACH_2_30(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32)
+
+#define MU_FOR_EACH_2_34(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34) \
+X(P1, P2) \
+MU_FOR_EACH_2_32(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34)
+
+#define MU_FOR_EACH_2_36(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36) \
+X(P1, P2) \
+MU_FOR_EACH_2_34(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36)
+
+#define MU_FOR_EACH_2_38(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38) \
+X(P1, P2) \
+MU_FOR_EACH_2_36(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38)
+
+#define MU_FOR_EACH_2_40(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40) \
+X(P1, P2) \
+MU_FOR_EACH_2_38(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40)
+
+#define MU_FOR_EACH_2_42(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42) \
+X(P1, P2) \
+MU_FOR_EACH_2_40(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42)
+
+#define MU_FOR_EACH_2_44(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44) \
+X(P1, P2) \
+MU_FOR_EACH_2_42(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44)
+
+#define MU_FOR_EACH_2_46(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46) \
+X(P1, P2) \
+MU_FOR_EACH_2_44(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46)
+
+#define MU_FOR_EACH_2_48(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48) \
+X(P1, P2) \
+MU_FOR_EACH_2_46(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48)
+
+#define MU_FOR_EACH_2_50(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50) \
+X(P1, P2) \
+MU_FOR_EACH_2_48(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50)
+
+#define MU_FOR_EACH_2_52(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52) \
+X(P1, P2) \
+MU_FOR_EACH_2_50(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52)
+
+#define MU_FOR_EACH_2_54(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54) \
+X(P1, P2) \
+MU_FOR_EACH_2_52(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54)
+
+#define MU_FOR_EACH_2_56(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56) \
+X(P1, P2) \
+MU_FOR_EACH_2_54(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56)
+
+#define MU_FOR_EACH_2_58(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58) \
+X(P1, P2) \
+MU_FOR_EACH_2_56(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58)
+
+#define MU_FOR_EACH_2_60(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60) \
+X(P1, P2) \
+MU_FOR_EACH_2_58(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60)
+
+#define MU_FOR_EACH_2_62(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62) \
+X(P1, P2) \
+MU_FOR_EACH_2_60(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62)
+
+#define MU_FOR_EACH_2_64(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64) \
+X(P1, P2) \
+MU_FOR_EACH_2_62(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64)
+
+#define MU_FOR_EACH_2_66(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66) \
+X(P1, P2) \
+MU_FOR_EACH_2_64(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66)
+
+#define MU_FOR_EACH_2_68(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68) \
+X(P1, P2) \
+MU_FOR_EACH_2_66(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68)
+
+#define MU_FOR_EACH_2_70(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70) \
+X(P1, P2) \
+MU_FOR_EACH_2_68(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70)
+
+#define MU_FOR_EACH_2_72(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72) \
+X(P1, P2) \
+MU_FOR_EACH_2_70(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72)
+
+#define MU_FOR_EACH_2_74(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74) \
+X(P1, P2) \
+MU_FOR_EACH_2_72(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74)
+
+#define MU_FOR_EACH_2_76(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76) \
+X(P1, P2) \
+MU_FOR_EACH_2_74(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76)
+
+#define MU_FOR_EACH_2_78(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78) \
+X(P1, P2) \
+MU_FOR_EACH_2_76(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78)
+
+#define MU_FOR_EACH_2_80(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80) \
+X(P1, P2) \
+MU_FOR_EACH_2_78(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80)
+
+#define MU_FOR_EACH_2_82(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82) \
+X(P1, P2) \
+MU_FOR_EACH_2_80(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82)
+
+#define MU_FOR_EACH_2_84(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84) \
+X(P1, P2) \
+MU_FOR_EACH_2_82(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84)
+
+#define MU_FOR_EACH_2_86(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86) \
+X(P1, P2) \
+MU_FOR_EACH_2_84(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86)
+
+#define MU_FOR_EACH_2_88(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88) \
+X(P1, P2) \
+MU_FOR_EACH_2_86(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88)
+
+#define MU_FOR_EACH_2_90(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90) \
+X(P1, P2) \
+MU_FOR_EACH_2_88(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90)
+
+#define MU_FOR_EACH_2_92(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92) \
+X(P1, P2) \
+MU_FOR_EACH_2_90(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92)
+
+#define MU_FOR_EACH_2_94(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94) \
+X(P1, P2) \
+MU_FOR_EACH_2_92(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94)
+
+#define MU_FOR_EACH_2_96(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96) \
+X(P1, P2) \
+MU_FOR_EACH_2_94(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96)
+
+#define MU_FOR_EACH_2_98(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98) \
+X(P1, P2) \
+MU_FOR_EACH_2_96(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98)
+
+#define MU_FOR_EACH_2_100(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100) \
+X(P1, P2) \
+MU_FOR_EACH_2_98(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100)
+
+#define MU_FOR_EACH_2_102(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102) \
+X(P1, P2) \
+MU_FOR_EACH_2_100(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102)
+
+#define MU_FOR_EACH_2_104(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104) \
+X(P1, P2) \
+MU_FOR_EACH_2_102(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104)
+
+#define MU_FOR_EACH_2_106(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106) \
+X(P1, P2) \
+MU_FOR_EACH_2_104(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106)
+
+#define MU_FOR_EACH_2_108(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108) \
+X(P1, P2) \
+MU_FOR_EACH_2_106(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108)
+
+#define MU_FOR_EACH_2_110(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110) \
+X(P1, P2) \
+MU_FOR_EACH_2_108(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110)
+
+#define MU_FOR_EACH_2_112(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112) \
+X(P1, P2) \
+MU_FOR_EACH_2_110(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112)
+
+#define MU_FOR_EACH_2_114(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114) \
+X(P1, P2) \
+MU_FOR_EACH_2_112(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114)
+
+#define MU_FOR_EACH_2_116(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116) \
+X(P1, P2) \
+MU_FOR_EACH_2_114(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116)
+
+#define MU_FOR_EACH_2_118(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118) \
+X(P1, P2) \
+MU_FOR_EACH_2_116(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118)
+
+#define MU_FOR_EACH_2_120(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120) \
+X(P1, P2) \
+MU_FOR_EACH_2_118(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120)
+
+#define MU_FOR_EACH_2_122(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122) \
+X(P1, P2) \
+MU_FOR_EACH_2_120(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122)
+
+#define MU_FOR_EACH_2_124(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123, P124) \
+X(P1, P2) \
+MU_FOR_EACH_2_122(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123, P124)
+
+
+#define MU_FOR_EACH_2_REVERSE_0(...)
+
+#define MU_FOR_EACH_2_REVERSE_2(X, P1, P2) \
+X(P1, P2)
+
+#define MU_FOR_EACH_2_REVERSE_4(X, P1, P2, P3, P4) \
+X(P3, P4) \
+MU_FOR_EACH_2_REVERSE_2(X, P1, P2)
+
+#define MU_FOR_EACH_2_REVERSE_6(X, P1, P2, P3, P4, P5, P6) \
+X(P5, P6) \
+MU_FOR_EACH_2_REVERSE_4(X, P1, P2, P3, P4)
+
+#define MU_FOR_EACH_2_REVERSE_8(X, P1, P2, P3, P4, P5, P6, P7, P8) \
+X(P7, P8) \
+MU_FOR_EACH_2_REVERSE_6(X, P1, P2, P3, P4, P5, P6)
+
+#define MU_FOR_EACH_2_REVERSE_10(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) \
+X(P9, P10) \
+MU_FOR_EACH_2_REVERSE_8(X, P1, P2, P3, P4, P5, P6, P7, P8)
+
+#define MU_FOR_EACH_2_REVERSE_12(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) \
+X(P11, P12) \
+MU_FOR_EACH_2_REVERSE_10(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10)
+
+#define MU_FOR_EACH_2_REVERSE_14(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14) \
+X(P13, P14) \
+MU_FOR_EACH_2_REVERSE_12(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12)
+
+#define MU_FOR_EACH_2_REVERSE_16(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16) \
+X(P15, P16) \
+MU_FOR_EACH_2_REVERSE_14(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14)
+
+#define MU_FOR_EACH_2_REVERSE_18(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18) \
+X(P17, P18) \
+MU_FOR_EACH_2_REVERSE_16(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16)
+
+#define MU_FOR_EACH_2_REVERSE_20(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20) \
+X(P19, P20) \
+MU_FOR_EACH_2_REVERSE_18(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18)
+
+#define MU_FOR_EACH_2_REVERSE_22(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22) \
+X(P21, P22) \
+MU_FOR_EACH_2_REVERSE_20(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20)
+
+#define MU_FOR_EACH_2_REVERSE_24(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24) \
+X(P23, P24) \
+MU_FOR_EACH_2_REVERSE_22(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22)
+
+#define MU_FOR_EACH_2_REVERSE_26(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26) \
+X(P25, P26) \
+MU_FOR_EACH_2_REVERSE_24(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24)
+
+#define MU_FOR_EACH_2_REVERSE_28(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28) \
+X(P27, P28) \
+MU_FOR_EACH_2_REVERSE_26(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26)
+
+#define MU_FOR_EACH_2_REVERSE_30(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30) \
+X(P29, P30) \
+MU_FOR_EACH_2_REVERSE_28(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28)
+
+#define MU_FOR_EACH_2_REVERSE_32(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32) \
+X(P31, P32) \
+MU_FOR_EACH_2_REVERSE_30(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30)
+
+#define MU_FOR_EACH_2_REVERSE_34(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34) \
+X(P33, P34) \
+MU_FOR_EACH_2_REVERSE_32(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32)
+
+#define MU_FOR_EACH_2_REVERSE_36(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36) \
+X(P35, P36) \
+MU_FOR_EACH_2_REVERSE_34(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34)
+
+#define MU_FOR_EACH_2_REVERSE_38(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38) \
+X(P37, P38) \
+MU_FOR_EACH_2_REVERSE_36(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36)
+
+#define MU_FOR_EACH_2_REVERSE_40(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40) \
+X(P39, P40) \
+MU_FOR_EACH_2_REVERSE_38(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38)
+
+#define MU_FOR_EACH_2_REVERSE_42(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42) \
+X(P41, P42) \
+MU_FOR_EACH_2_REVERSE_40(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40)
+
+#define MU_FOR_EACH_2_REVERSE_44(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44) \
+X(P43, P44) \
+MU_FOR_EACH_2_REVERSE_42(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42)
+
+#define MU_FOR_EACH_2_REVERSE_46(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46) \
+X(P45, P46) \
+MU_FOR_EACH_2_REVERSE_44(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44)
+
+#define MU_FOR_EACH_2_REVERSE_48(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48) \
+X(P47, P48) \
+MU_FOR_EACH_2_REVERSE_46(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46)
+
+#define MU_FOR_EACH_2_REVERSE_50(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50) \
+X(P49, P50) \
+MU_FOR_EACH_2_REVERSE_48(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48)
+
+#define MU_FOR_EACH_2_REVERSE_52(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52) \
+X(P51, P52) \
+MU_FOR_EACH_2_REVERSE_50(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50)
+
+#define MU_FOR_EACH_2_REVERSE_54(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54) \
+X(P53, P54) \
+MU_FOR_EACH_2_REVERSE_52(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52)
+
+#define MU_FOR_EACH_2_REVERSE_56(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56) \
+X(P55, P56) \
+MU_FOR_EACH_2_REVERSE_54(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54)
+
+#define MU_FOR_EACH_2_REVERSE_58(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58) \
+X(P57, P58) \
+MU_FOR_EACH_2_REVERSE_56(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56)
+
+#define MU_FOR_EACH_2_REVERSE_60(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60) \
+X(P59, P60) \
+MU_FOR_EACH_2_REVERSE_58(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58)
+
+#define MU_FOR_EACH_2_REVERSE_62(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62) \
+X(P61, P62) \
+MU_FOR_EACH_2_REVERSE_60(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60)
+
+#define MU_FOR_EACH_2_REVERSE_64(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64) \
+X(P63, P64) \
+MU_FOR_EACH_2_REVERSE_62(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62)
+
+#define MU_FOR_EACH_2_REVERSE_66(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66) \
+X(P65, P66) \
+MU_FOR_EACH_2_REVERSE_64(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64)
+
+#define MU_FOR_EACH_2_REVERSE_68(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68) \
+X(P67, P68) \
+MU_FOR_EACH_2_REVERSE_66(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66)
+
+#define MU_FOR_EACH_2_REVERSE_70(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70) \
+X(P69, P70) \
+MU_FOR_EACH_2_REVERSE_68(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68)
+
+#define MU_FOR_EACH_2_REVERSE_72(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72) \
+X(P71, P72) \
+MU_FOR_EACH_2_REVERSE_70(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70)
+
+#define MU_FOR_EACH_2_REVERSE_74(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74) \
+X(P73, P74) \
+MU_FOR_EACH_2_REVERSE_72(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72)
+
+#define MU_FOR_EACH_2_REVERSE_76(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76) \
+X(P75, P76) \
+MU_FOR_EACH_2_REVERSE_74(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74)
+
+#define MU_FOR_EACH_2_REVERSE_78(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78) \
+X(P77, P78) \
+MU_FOR_EACH_2_REVERSE_76(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76)
+
+#define MU_FOR_EACH_2_REVERSE_80(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80) \
+X(P79, P80) \
+MU_FOR_EACH_2_REVERSE_78(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78)
+
+#define MU_FOR_EACH_2_REVERSE_82(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82) \
+X(P81, P82) \
+MU_FOR_EACH_2_REVERSE_80(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80)
+
+#define MU_FOR_EACH_2_REVERSE_84(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84) \
+X(P83, P84) \
+MU_FOR_EACH_2_REVERSE_82(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82)
+
+#define MU_FOR_EACH_2_REVERSE_86(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86) \
+X(P85, P86) \
+MU_FOR_EACH_2_REVERSE_84(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84)
+
+#define MU_FOR_EACH_2_REVERSE_88(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88) \
+X(P87, P88) \
+MU_FOR_EACH_2_REVERSE_86(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86)
+
+#define MU_FOR_EACH_2_REVERSE_90(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90) \
+X(P89, P90) \
+MU_FOR_EACH_2_REVERSE_88(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88)
+
+#define MU_FOR_EACH_2_REVERSE_92(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92) \
+X(P91, P92) \
+MU_FOR_EACH_2_REVERSE_90(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90)
+
+#define MU_FOR_EACH_2_REVERSE_94(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94) \
+X(P93, P94) \
+MU_FOR_EACH_2_REVERSE_92(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92)
+
+#define MU_FOR_EACH_2_REVERSE_96(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96) \
+X(P95, P96) \
+MU_FOR_EACH_2_REVERSE_94(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94)
+
+#define MU_FOR_EACH_2_REVERSE_98(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98) \
+X(P97, P98) \
+MU_FOR_EACH_2_REVERSE_96(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96)
+
+#define MU_FOR_EACH_2_REVERSE_100(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100) \
+X(P99, P100) \
+MU_FOR_EACH_2_REVERSE_98(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98)
+
+#define MU_FOR_EACH_2_REVERSE_102(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102) \
+X(P101, P102) \
+MU_FOR_EACH_2_REVERSE_100(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100)
+
+#define MU_FOR_EACH_2_REVERSE_104(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104) \
+X(P103, P104) \
+MU_FOR_EACH_2_REVERSE_102(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102)
+
+#define MU_FOR_EACH_2_REVERSE_106(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106) \
+X(P105, P106) \
+MU_FOR_EACH_2_REVERSE_104(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104)
+
+#define MU_FOR_EACH_2_REVERSE_108(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108) \
+X(P107, P108) \
+MU_FOR_EACH_2_REVERSE_106(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106)
+
+#define MU_FOR_EACH_2_REVERSE_110(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110) \
+X(P109, P110) \
+MU_FOR_EACH_2_REVERSE_108(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108)
+
+#define MU_FOR_EACH_2_REVERSE_112(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112) \
+X(P111, P112) \
+MU_FOR_EACH_2_REVERSE_110(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110)
+
+#define MU_FOR_EACH_2_REVERSE_114(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114) \
+X(P113, P114) \
+MU_FOR_EACH_2_REVERSE_112(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112)
+
+#define MU_FOR_EACH_2_REVERSE_116(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116) \
+X(P115, P116) \
+MU_FOR_EACH_2_REVERSE_114(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114)
+
+#define MU_FOR_EACH_2_REVERSE_118(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118) \
+X(P117, P118) \
+MU_FOR_EACH_2_REVERSE_116(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116)
+
+#define MU_FOR_EACH_2_REVERSE_120(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120) \
+X(P119, P120) \
+MU_FOR_EACH_2_REVERSE_118(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118)
+
+#define MU_FOR_EACH_2_REVERSE_122(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122) \
+X(P121, P122) \
+MU_FOR_EACH_2_REVERSE_120(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120)
+
+#define MU_FOR_EACH_2_REVERSE_124(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123, P124) \
+X(P123, P124) \
+MU_FOR_EACH_2_REVERSE_122(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122)
+
+
+#define MU_FOR_EACH_1_COUNTED_0(...)
+
+#define MU_FOR_EACH_1_COUNTED_1(X, P1) \
+    X(1, P1)
+
+#define MU_FOR_EACH_1_COUNTED_2(X, P1, P2) \
+X(2, P1) \
+MU_FOR_EACH_1_COUNTED_1(X, P2)
+
+#define MU_FOR_EACH_1_COUNTED_3(X, P1, P2, P3) \
+X(3, P1) \
+MU_FOR_EACH_1_COUNTED_2(X, P2, P3)
+
+#define MU_FOR_EACH_1_COUNTED_4(X, P1, P2, P3, P4) \
+X(4, P1) \
+MU_FOR_EACH_1_COUNTED_3(X, P2, P3, P4)
+
+#define MU_FOR_EACH_1_COUNTED_5(X, P1, P2, P3, P4, P5) \
+X(5, P1) \
+MU_FOR_EACH_1_COUNTED_4(X, P2, P3, P4, P5)
+
+#define MU_FOR_EACH_1_COUNTED_6(X, P1, P2, P3, P4, P5, P6) \
+X(6, P1) \
+MU_FOR_EACH_1_COUNTED_5(X, P2, P3, P4, P5, P6)
+
+#define MU_FOR_EACH_1_COUNTED_7(X, P1, P2, P3, P4, P5, P6, P7) \
+X(7, P1) \
+MU_FOR_EACH_1_COUNTED_6(X, P2, P3, P4, P5, P6, P7)
+
+#define MU_FOR_EACH_1_COUNTED_8(X, P1, P2, P3, P4, P5, P6, P7, P8) \
+X(8, P1) \
+MU_FOR_EACH_1_COUNTED_7(X, P2, P3, P4, P5, P6, P7, P8)
+
+#define MU_FOR_EACH_1_COUNTED_9(X, P1, P2, P3, P4, P5, P6, P7, P8, P9) \
+X(9, P1) \
+MU_FOR_EACH_1_COUNTED_8(X, P2, P3, P4, P5, P6, P7, P8, P9)
+
+#define MU_FOR_EACH_1_COUNTED_10(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) \
+X(10, P1) \
+MU_FOR_EACH_1_COUNTED_9(X, P2, P3, P4, P5, P6, P7, P8, P9, P10)
+
+#define MU_FOR_EACH_1_COUNTED_11(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11) \
+X(11, P1) \
+MU_FOR_EACH_1_COUNTED_10(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11)
+
+#define MU_FOR_EACH_1_COUNTED_12(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) \
+X(12, P1) \
+MU_FOR_EACH_1_COUNTED_11(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12)
+
+#define MU_FOR_EACH_1_COUNTED_13(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13) \
+X(13, P1) \
+MU_FOR_EACH_1_COUNTED_12(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13)
+
+#define MU_FOR_EACH_1_COUNTED_14(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14) \
+X(14, P1) \
+MU_FOR_EACH_1_COUNTED_13(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14)
+
+#define MU_FOR_EACH_1_COUNTED_15(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15) \
+X(15, P1) \
+MU_FOR_EACH_1_COUNTED_14(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15)
+
+#define MU_FOR_EACH_1_COUNTED_16(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16) \
+X(16, P1) \
+MU_FOR_EACH_1_COUNTED_15(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16)
+
+#define MU_FOR_EACH_1_COUNTED_17(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17) \
+X(17, P1) \
+MU_FOR_EACH_1_COUNTED_16(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17)
+
+#define MU_FOR_EACH_1_COUNTED_18(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18) \
+X(18, P1) \
+MU_FOR_EACH_1_COUNTED_17(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18)
+
+#define MU_FOR_EACH_1_COUNTED_19(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19) \
+X(19, P1) \
+MU_FOR_EACH_1_COUNTED_18(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19)
+
+#define MU_FOR_EACH_1_COUNTED_20(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20) \
+X(20, P1) \
+MU_FOR_EACH_1_COUNTED_19(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20)
+
+#define MU_FOR_EACH_1_COUNTED_21(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21) \
+X(21, P1) \
+MU_FOR_EACH_1_COUNTED_20(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21)
+
+#define MU_FOR_EACH_1_COUNTED_22(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22) \
+X(22, P1) \
+MU_FOR_EACH_1_COUNTED_21(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22)
+
+#define MU_FOR_EACH_1_COUNTED_23(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23) \
+X(23, P1) \
+MU_FOR_EACH_1_COUNTED_22(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23)
+
+#define MU_FOR_EACH_1_COUNTED_24(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24) \
+X(24, P1) \
+MU_FOR_EACH_1_COUNTED_23(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24)
+
+#define MU_FOR_EACH_1_COUNTED_25(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25) \
+X(25, P1) \
+MU_FOR_EACH_1_COUNTED_24(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25)
+
+#define MU_FOR_EACH_1_COUNTED_26(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26) \
+X(26, P1) \
+MU_FOR_EACH_1_COUNTED_25(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26)
+
+#define MU_FOR_EACH_1_COUNTED_27(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27) \
+X(27, P1) \
+MU_FOR_EACH_1_COUNTED_26(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27)
+
+#define MU_FOR_EACH_1_COUNTED_28(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28) \
+X(28, P1) \
+MU_FOR_EACH_1_COUNTED_27(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28)
+
+#define MU_FOR_EACH_1_COUNTED_29(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29) \
+X(29, P1) \
+MU_FOR_EACH_1_COUNTED_28(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29)
+
+#define MU_FOR_EACH_1_COUNTED_30(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30) \
+X(30, P1) \
+MU_FOR_EACH_1_COUNTED_29(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30)
+
+#define MU_FOR_EACH_1_COUNTED_31(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31) \
+X(31, P1) \
+MU_FOR_EACH_1_COUNTED_30(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31)
+
+#define MU_FOR_EACH_1_COUNTED_32(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32) \
+X(32, P1) \
+MU_FOR_EACH_1_COUNTED_31(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32)
+
+#define MU_FOR_EACH_1_COUNTED_33(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33) \
+X(33, P1) \
+MU_FOR_EACH_1_COUNTED_32(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33)
+
+#define MU_FOR_EACH_1_COUNTED_34(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34) \
+X(34, P1) \
+MU_FOR_EACH_1_COUNTED_33(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34)
+
+#define MU_FOR_EACH_1_COUNTED_35(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35) \
+X(35, P1) \
+MU_FOR_EACH_1_COUNTED_34(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35)
+
+#define MU_FOR_EACH_1_COUNTED_36(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36) \
+X(36, P1) \
+MU_FOR_EACH_1_COUNTED_35(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36)
+
+#define MU_FOR_EACH_1_COUNTED_37(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37) \
+X(37, P1) \
+MU_FOR_EACH_1_COUNTED_36(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37)
+
+#define MU_FOR_EACH_1_COUNTED_38(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38) \
+X(38, P1) \
+MU_FOR_EACH_1_COUNTED_37(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38)
+
+#define MU_FOR_EACH_1_COUNTED_39(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39) \
+X(39, P1) \
+MU_FOR_EACH_1_COUNTED_38(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39)
+
+#define MU_FOR_EACH_1_COUNTED_40(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40) \
+X(40, P1) \
+MU_FOR_EACH_1_COUNTED_39(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40)
+
+#define MU_FOR_EACH_1_COUNTED_41(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41) \
+X(41, P1) \
+MU_FOR_EACH_1_COUNTED_40(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41)
+
+#define MU_FOR_EACH_1_COUNTED_42(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42) \
+X(42, P1) \
+MU_FOR_EACH_1_COUNTED_41(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42)
+
+#define MU_FOR_EACH_1_COUNTED_43(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43) \
+X(43, P1) \
+MU_FOR_EACH_1_COUNTED_42(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43)
+
+#define MU_FOR_EACH_1_COUNTED_44(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44) \
+X(44, P1) \
+MU_FOR_EACH_1_COUNTED_43(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44)
+
+#define MU_FOR_EACH_1_COUNTED_45(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45) \
+X(45, P1) \
+MU_FOR_EACH_1_COUNTED_44(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45)
+
+#define MU_FOR_EACH_1_COUNTED_46(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46) \
+X(46, P1) \
+MU_FOR_EACH_1_COUNTED_45(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46)
+
+#define MU_FOR_EACH_1_COUNTED_47(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47) \
+X(47, P1) \
+MU_FOR_EACH_1_COUNTED_46(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47)
+
+#define MU_FOR_EACH_1_COUNTED_48(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48) \
+X(48, P1) \
+MU_FOR_EACH_1_COUNTED_47(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48)
+
+#define MU_FOR_EACH_1_COUNTED_49(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49) \
+X(49, P1) \
+MU_FOR_EACH_1_COUNTED_48(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49)
+
+#define MU_FOR_EACH_1_COUNTED_50(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50) \
+X(50, P1) \
+MU_FOR_EACH_1_COUNTED_49(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50)
+
+#define MU_FOR_EACH_1_COUNTED_51(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51) \
+X(51, P1) \
+MU_FOR_EACH_1_COUNTED_50(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51)
+
+#define MU_FOR_EACH_1_COUNTED_52(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52) \
+X(52, P1) \
+MU_FOR_EACH_1_COUNTED_51(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52)
+
+#define MU_FOR_EACH_1_COUNTED_53(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53) \
+X(53, P1) \
+MU_FOR_EACH_1_COUNTED_52(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53)
+
+#define MU_FOR_EACH_1_COUNTED_54(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54) \
+X(54, P1) \
+MU_FOR_EACH_1_COUNTED_53(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54)
+
+#define MU_FOR_EACH_1_COUNTED_55(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55) \
+X(55, P1) \
+MU_FOR_EACH_1_COUNTED_54(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55)
+
+#define MU_FOR_EACH_1_COUNTED_56(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56) \
+X(56, P1) \
+MU_FOR_EACH_1_COUNTED_55(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56)
+
+#define MU_FOR_EACH_1_COUNTED_57(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57) \
+X(57, P1) \
+MU_FOR_EACH_1_COUNTED_56(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57)
+
+#define MU_FOR_EACH_1_COUNTED_58(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58) \
+X(58, P1) \
+MU_FOR_EACH_1_COUNTED_57(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58)
+
+#define MU_FOR_EACH_1_COUNTED_59(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59) \
+X(59, P1) \
+MU_FOR_EACH_1_COUNTED_58(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59)
+
+#define MU_FOR_EACH_1_COUNTED_60(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60) \
+X(60, P1) \
+MU_FOR_EACH_1_COUNTED_59(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60)
+
+#define MU_FOR_EACH_1_COUNTED_61(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61) \
+X(61, P1) \
+MU_FOR_EACH_1_COUNTED_60(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61)
+
+#define MU_FOR_EACH_1_COUNTED_62(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62) \
+X(62, P1) \
+MU_FOR_EACH_1_COUNTED_61(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62)
+
+#define MU_FOR_EACH_1_COUNTED_63(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63) \
+X(63, P1) \
+MU_FOR_EACH_1_COUNTED_62(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63)
+
+#define MU_FOR_EACH_1_COUNTED_64(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64) \
+X(64, P1) \
+MU_FOR_EACH_1_COUNTED_63(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64)
+
+#define MU_FOR_EACH_1_COUNTED_65(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65) \
+X(65, P1) \
+MU_FOR_EACH_1_COUNTED_64(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65)
+
+#define MU_FOR_EACH_1_COUNTED_66(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66) \
+X(66, P1) \
+MU_FOR_EACH_1_COUNTED_65(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66)
+
+#define MU_FOR_EACH_1_COUNTED_67(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67) \
+X(67, P1) \
+MU_FOR_EACH_1_COUNTED_66(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67)
+
+#define MU_FOR_EACH_1_COUNTED_68(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68) \
+X(68, P1) \
+MU_FOR_EACH_1_COUNTED_67(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68)
+
+#define MU_FOR_EACH_1_COUNTED_69(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69) \
+X(69, P1) \
+MU_FOR_EACH_1_COUNTED_68(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69)
+
+#define MU_FOR_EACH_1_COUNTED_70(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70) \
+X(70, P1) \
+MU_FOR_EACH_1_COUNTED_69(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70)
+
+#define MU_FOR_EACH_1_COUNTED_71(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71) \
+X(71, P1) \
+MU_FOR_EACH_1_COUNTED_70(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71)
+
+#define MU_FOR_EACH_1_COUNTED_72(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72) \
+X(72, P1) \
+MU_FOR_EACH_1_COUNTED_71(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72)
+
+#define MU_FOR_EACH_1_COUNTED_73(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73) \
+X(73, P1) \
+MU_FOR_EACH_1_COUNTED_72(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73)
+
+#define MU_FOR_EACH_1_COUNTED_74(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74) \
+X(74, P1) \
+MU_FOR_EACH_1_COUNTED_73(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74)
+
+#define MU_FOR_EACH_1_COUNTED_75(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75) \
+X(75, P1) \
+MU_FOR_EACH_1_COUNTED_74(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75)
+
+#define MU_FOR_EACH_1_COUNTED_76(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76) \
+X(76, P1) \
+MU_FOR_EACH_1_COUNTED_75(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76)
+
+#define MU_FOR_EACH_1_COUNTED_77(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77) \
+X(77, P1) \
+MU_FOR_EACH_1_COUNTED_76(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77)
+
+#define MU_FOR_EACH_1_COUNTED_78(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78) \
+X(78, P1) \
+MU_FOR_EACH_1_COUNTED_77(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78)
+
+#define MU_FOR_EACH_1_COUNTED_79(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79) \
+X(79, P1) \
+MU_FOR_EACH_1_COUNTED_78(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79)
+
+#define MU_FOR_EACH_1_COUNTED_80(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80) \
+X(80, P1) \
+MU_FOR_EACH_1_COUNTED_79(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80)
+
+#define MU_FOR_EACH_1_COUNTED_81(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81) \
+X(81, P1) \
+MU_FOR_EACH_1_COUNTED_80(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81)
+
+#define MU_FOR_EACH_1_COUNTED_82(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82) \
+X(82, P1) \
+MU_FOR_EACH_1_COUNTED_81(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82)
+
+#define MU_FOR_EACH_1_COUNTED_83(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83) \
+X(83, P1) \
+MU_FOR_EACH_1_COUNTED_82(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83)
+
+#define MU_FOR_EACH_1_COUNTED_84(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84) \
+X(84, P1) \
+MU_FOR_EACH_1_COUNTED_83(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84)
+
+#define MU_FOR_EACH_1_COUNTED_85(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85) \
+X(85, P1) \
+MU_FOR_EACH_1_COUNTED_84(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85)
+
+#define MU_FOR_EACH_1_COUNTED_86(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86) \
+X(86, P1) \
+MU_FOR_EACH_1_COUNTED_85(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86)
+
+#define MU_FOR_EACH_1_COUNTED_87(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87) \
+X(87, P1) \
+MU_FOR_EACH_1_COUNTED_86(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87)
+
+#define MU_FOR_EACH_1_COUNTED_88(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88) \
+X(88, P1) \
+MU_FOR_EACH_1_COUNTED_87(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88)
+
+#define MU_FOR_EACH_1_COUNTED_89(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89) \
+X(89, P1) \
+MU_FOR_EACH_1_COUNTED_88(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89)
+
+#define MU_FOR_EACH_1_COUNTED_90(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90) \
+X(90, P1) \
+MU_FOR_EACH_1_COUNTED_89(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90)
+
+#define MU_FOR_EACH_1_COUNTED_91(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91) \
+X(91, P1) \
+MU_FOR_EACH_1_COUNTED_90(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91)
+
+#define MU_FOR_EACH_1_COUNTED_92(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92) \
+X(92, P1) \
+MU_FOR_EACH_1_COUNTED_91(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92)
+
+#define MU_FOR_EACH_1_COUNTED_93(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93) \
+X(93, P1) \
+MU_FOR_EACH_1_COUNTED_92(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93)
+
+#define MU_FOR_EACH_1_COUNTED_94(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94) \
+X(94, P1) \
+MU_FOR_EACH_1_COUNTED_93(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94)
+
+#define MU_FOR_EACH_1_COUNTED_95(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95) \
+X(95, P1) \
+MU_FOR_EACH_1_COUNTED_94(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95)
+
+#define MU_FOR_EACH_1_COUNTED_96(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96) \
+X(96, P1) \
+MU_FOR_EACH_1_COUNTED_95(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96)
+
+#define MU_FOR_EACH_1_COUNTED_97(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97) \
+X(97, P1) \
+MU_FOR_EACH_1_COUNTED_96(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97)
+
+#define MU_FOR_EACH_1_COUNTED_98(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98) \
+X(98, P1) \
+MU_FOR_EACH_1_COUNTED_97(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98)
+
+#define MU_FOR_EACH_1_COUNTED_99(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99) \
+X(99, P1) \
+MU_FOR_EACH_1_COUNTED_98(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99)
+
+#define MU_FOR_EACH_1_COUNTED_100(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100) \
+X(100, P1) \
+MU_FOR_EACH_1_COUNTED_99(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100)
+
+#define MU_FOR_EACH_1_COUNTED_101(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101) \
+X(101, P1) \
+MU_FOR_EACH_1_COUNTED_100(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101)
+
+#define MU_FOR_EACH_1_COUNTED_102(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102) \
+X(102, P1) \
+MU_FOR_EACH_1_COUNTED_101(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102)
+
+#define MU_FOR_EACH_1_COUNTED_103(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103) \
+X(103, P1) \
+MU_FOR_EACH_1_COUNTED_102(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103)
+
+#define MU_FOR_EACH_1_COUNTED_104(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104) \
+X(104, P1) \
+MU_FOR_EACH_1_COUNTED_103(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104)
+
+#define MU_FOR_EACH_1_COUNTED_105(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105) \
+X(105, P1) \
+MU_FOR_EACH_1_COUNTED_104(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105)
+
+#define MU_FOR_EACH_1_COUNTED_106(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106) \
+X(106, P1) \
+MU_FOR_EACH_1_COUNTED_105(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106)
+
+#define MU_FOR_EACH_1_COUNTED_107(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107) \
+X(107, P1) \
+MU_FOR_EACH_1_COUNTED_106(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107)
+
+#define MU_FOR_EACH_1_COUNTED_108(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108) \
+X(108, P1) \
+MU_FOR_EACH_1_COUNTED_107(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108)
+
+#define MU_FOR_EACH_1_COUNTED_109(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109) \
+X(109, P1) \
+MU_FOR_EACH_1_COUNTED_108(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109)
+
+#define MU_FOR_EACH_1_COUNTED_110(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110) \
+X(110, P1) \
+MU_FOR_EACH_1_COUNTED_109(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110)
+
+#define MU_FOR_EACH_1_COUNTED_111(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111) \
+X(111, P1) \
+MU_FOR_EACH_1_COUNTED_110(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111)
+
+#define MU_FOR_EACH_1_COUNTED_112(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112) \
+X(112, P1) \
+MU_FOR_EACH_1_COUNTED_111(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112)
+
+#define MU_FOR_EACH_1_COUNTED_113(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113) \
+X(113, P1) \
+MU_FOR_EACH_1_COUNTED_112(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113)
+
+#define MU_FOR_EACH_1_COUNTED_114(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114) \
+X(114, P1) \
+MU_FOR_EACH_1_COUNTED_113(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114)
+
+#define MU_FOR_EACH_1_COUNTED_115(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115) \
+X(115, P1) \
+MU_FOR_EACH_1_COUNTED_114(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115)
+
+#define MU_FOR_EACH_1_COUNTED_116(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116) \
+X(116, P1) \
+MU_FOR_EACH_1_COUNTED_115(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116)
+
+#define MU_FOR_EACH_1_COUNTED_117(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117) \
+X(117, P1) \
+MU_FOR_EACH_1_COUNTED_116(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117)
+
+#define MU_FOR_EACH_1_COUNTED_118(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118) \
+X(118, P1) \
+MU_FOR_EACH_1_COUNTED_117(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118)
+
+#define MU_FOR_EACH_1_COUNTED_119(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119) \
+X(119, P1) \
+MU_FOR_EACH_1_COUNTED_118(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119)
+
+#define MU_FOR_EACH_1_COUNTED_120(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120) \
+X(120, P1) \
+MU_FOR_EACH_1_COUNTED_119(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120)
+
+#define MU_FOR_EACH_1_COUNTED_121(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121) \
+X(121, P1) \
+MU_FOR_EACH_1_COUNTED_120(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121)
+
+#define MU_FOR_EACH_1_COUNTED_122(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122) \
+X(122, P1) \
+MU_FOR_EACH_1_COUNTED_121(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122)
+
+#define MU_FOR_EACH_1_COUNTED_123(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123) \
+X(123, P1) \
+MU_FOR_EACH_1_COUNTED_122(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123)
+
+#define MU_FOR_EACH_1_COUNTED_124(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123, P124) \
+X(124, P1) \
+MU_FOR_EACH_1_COUNTED_123(X, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123, P124)
+
+
+#define MU_FOR_EACH_2_COUNTED_0(...)
+
+#define MU_FOR_EACH_2_COUNTED_2(X, P1, P2) \
+    X(2, P1, P2)
+
+#define MU_FOR_EACH_2_COUNTED_4(X, P1, P2, P3, P4) \
+X(4, P1, P2) \
+MU_FOR_EACH_2_COUNTED_2(X, P3, P4)
+
+#define MU_FOR_EACH_2_COUNTED_6(X, P1, P2, P3, P4, P5, P6) \
+X(6, P1, P2) \
+MU_FOR_EACH_2_COUNTED_4(X, P3, P4, P5, P6)
+
+#define MU_FOR_EACH_2_COUNTED_8(X, P1, P2, P3, P4, P5, P6, P7, P8) \
+X(8, P1, P2) \
+MU_FOR_EACH_2_COUNTED_6(X, P3, P4, P5, P6, P7, P8)
+
+#define MU_FOR_EACH_2_COUNTED_10(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) \
+X(10, P1, P2) \
+MU_FOR_EACH_2_COUNTED_8(X, P3, P4, P5, P6, P7, P8, P9, P10)
+
+#define MU_FOR_EACH_2_COUNTED_12(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) \
+X(12, P1, P2) \
+MU_FOR_EACH_2_COUNTED_10(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12)
+
+#define MU_FOR_EACH_2_COUNTED_14(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14) \
+X(14, P1, P2) \
+MU_FOR_EACH_2_COUNTED_12(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14)
+
+#define MU_FOR_EACH_2_COUNTED_16(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16) \
+X(16, P1, P2) \
+MU_FOR_EACH_2_COUNTED_14(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16)
+
+#define MU_FOR_EACH_2_COUNTED_18(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18) \
+X(18, P1, P2) \
+MU_FOR_EACH_2_COUNTED_16(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18)
+
+#define MU_FOR_EACH_2_COUNTED_20(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20) \
+X(20, P1, P2) \
+MU_FOR_EACH_2_COUNTED_18(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20)
+
+#define MU_FOR_EACH_2_COUNTED_22(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22) \
+X(22, P1, P2) \
+MU_FOR_EACH_2_COUNTED_20(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22)
+
+#define MU_FOR_EACH_2_COUNTED_24(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24) \
+X(24, P1, P2) \
+MU_FOR_EACH_2_COUNTED_22(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24)
+
+#define MU_FOR_EACH_2_COUNTED_26(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26) \
+X(26, P1, P2) \
+MU_FOR_EACH_2_COUNTED_24(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26)
+
+#define MU_FOR_EACH_2_COUNTED_28(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28) \
+X(28, P1, P2) \
+MU_FOR_EACH_2_COUNTED_26(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28)
+
+#define MU_FOR_EACH_2_COUNTED_30(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30) \
+X(30, P1, P2) \
+MU_FOR_EACH_2_COUNTED_28(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30)
+
+#define MU_FOR_EACH_2_COUNTED_32(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32) \
+X(32, P1, P2) \
+MU_FOR_EACH_2_COUNTED_30(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32)
+
+#define MU_FOR_EACH_2_COUNTED_34(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34) \
+X(34, P1, P2) \
+MU_FOR_EACH_2_COUNTED_32(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34)
+
+#define MU_FOR_EACH_2_COUNTED_36(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36) \
+X(36, P1, P2) \
+MU_FOR_EACH_2_COUNTED_34(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36)
+
+#define MU_FOR_EACH_2_COUNTED_38(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38) \
+X(38, P1, P2) \
+MU_FOR_EACH_2_COUNTED_36(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38)
+
+#define MU_FOR_EACH_2_COUNTED_40(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40) \
+X(40, P1, P2) \
+MU_FOR_EACH_2_COUNTED_38(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40)
+
+#define MU_FOR_EACH_2_COUNTED_42(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42) \
+X(42, P1, P2) \
+MU_FOR_EACH_2_COUNTED_40(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42)
+
+#define MU_FOR_EACH_2_COUNTED_44(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44) \
+X(44, P1, P2) \
+MU_FOR_EACH_2_COUNTED_42(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44)
+
+#define MU_FOR_EACH_2_COUNTED_46(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46) \
+X(46, P1, P2) \
+MU_FOR_EACH_2_COUNTED_44(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46)
+
+#define MU_FOR_EACH_2_COUNTED_48(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48) \
+X(48, P1, P2) \
+MU_FOR_EACH_2_COUNTED_46(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48)
+
+#define MU_FOR_EACH_2_COUNTED_50(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50) \
+X(50, P1, P2) \
+MU_FOR_EACH_2_COUNTED_48(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50)
+
+#define MU_FOR_EACH_2_COUNTED_52(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52) \
+X(52, P1, P2) \
+MU_FOR_EACH_2_COUNTED_50(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52)
+
+#define MU_FOR_EACH_2_COUNTED_54(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54) \
+X(54, P1, P2) \
+MU_FOR_EACH_2_COUNTED_52(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54)
+
+#define MU_FOR_EACH_2_COUNTED_56(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56) \
+X(56, P1, P2) \
+MU_FOR_EACH_2_COUNTED_54(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56)
+
+#define MU_FOR_EACH_2_COUNTED_58(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58) \
+X(58, P1, P2) \
+MU_FOR_EACH_2_COUNTED_56(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58)
+
+#define MU_FOR_EACH_2_COUNTED_60(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60) \
+X(60, P1, P2) \
+MU_FOR_EACH_2_COUNTED_58(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60)
+
+#define MU_FOR_EACH_2_COUNTED_62(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62) \
+X(62, P1, P2) \
+MU_FOR_EACH_2_COUNTED_60(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62)
+
+#define MU_FOR_EACH_2_COUNTED_64(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64) \
+X(64, P1, P2) \
+MU_FOR_EACH_2_COUNTED_62(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64)
+
+#define MU_FOR_EACH_2_COUNTED_66(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66) \
+X(66, P1, P2) \
+MU_FOR_EACH_2_COUNTED_64(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66)
+
+#define MU_FOR_EACH_2_COUNTED_68(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68) \
+X(68, P1, P2) \
+MU_FOR_EACH_2_COUNTED_66(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68)
+
+#define MU_FOR_EACH_2_COUNTED_70(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70) \
+X(70, P1, P2) \
+MU_FOR_EACH_2_COUNTED_68(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70)
+
+#define MU_FOR_EACH_2_COUNTED_72(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72) \
+X(72, P1, P2) \
+MU_FOR_EACH_2_COUNTED_70(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72)
+
+#define MU_FOR_EACH_2_COUNTED_74(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74) \
+X(74, P1, P2) \
+MU_FOR_EACH_2_COUNTED_72(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74)
+
+#define MU_FOR_EACH_2_COUNTED_76(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76) \
+X(76, P1, P2) \
+MU_FOR_EACH_2_COUNTED_74(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76)
+
+#define MU_FOR_EACH_2_COUNTED_78(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78) \
+X(78, P1, P2) \
+MU_FOR_EACH_2_COUNTED_76(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78)
+
+#define MU_FOR_EACH_2_COUNTED_80(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80) \
+X(80, P1, P2) \
+MU_FOR_EACH_2_COUNTED_78(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80)
+
+#define MU_FOR_EACH_2_COUNTED_82(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82) \
+X(82, P1, P2) \
+MU_FOR_EACH_2_COUNTED_80(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82)
+
+#define MU_FOR_EACH_2_COUNTED_84(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84) \
+X(84, P1, P2) \
+MU_FOR_EACH_2_COUNTED_82(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84)
+
+#define MU_FOR_EACH_2_COUNTED_86(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86) \
+X(86, P1, P2) \
+MU_FOR_EACH_2_COUNTED_84(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86)
+
+#define MU_FOR_EACH_2_COUNTED_88(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88) \
+X(88, P1, P2) \
+MU_FOR_EACH_2_COUNTED_86(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88)
+
+#define MU_FOR_EACH_2_COUNTED_90(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90) \
+X(90, P1, P2) \
+MU_FOR_EACH_2_COUNTED_88(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90)
+
+#define MU_FOR_EACH_2_COUNTED_92(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92) \
+X(92, P1, P2) \
+MU_FOR_EACH_2_COUNTED_90(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92)
+
+#define MU_FOR_EACH_2_COUNTED_94(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94) \
+X(94, P1, P2) \
+MU_FOR_EACH_2_COUNTED_92(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94)
+
+#define MU_FOR_EACH_2_COUNTED_96(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96) \
+X(96, P1, P2) \
+MU_FOR_EACH_2_COUNTED_94(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96)
+
+#define MU_FOR_EACH_2_COUNTED_98(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98) \
+X(98, P1, P2) \
+MU_FOR_EACH_2_COUNTED_96(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98)
+
+#define MU_FOR_EACH_2_COUNTED_100(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100) \
+X(100, P1, P2) \
+MU_FOR_EACH_2_COUNTED_98(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100)
+
+#define MU_FOR_EACH_2_COUNTED_102(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102) \
+X(102, P1, P2) \
+MU_FOR_EACH_2_COUNTED_100(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102)
+
+#define MU_FOR_EACH_2_COUNTED_104(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104) \
+X(104, P1, P2) \
+MU_FOR_EACH_2_COUNTED_102(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104)
+
+#define MU_FOR_EACH_2_COUNTED_106(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106) \
+X(106, P1, P2) \
+MU_FOR_EACH_2_COUNTED_104(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106)
+
+#define MU_FOR_EACH_2_COUNTED_108(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108) \
+X(108, P1, P2) \
+MU_FOR_EACH_2_COUNTED_106(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108)
+
+#define MU_FOR_EACH_2_COUNTED_110(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110) \
+X(110, P1, P2) \
+MU_FOR_EACH_2_COUNTED_108(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110)
+
+#define MU_FOR_EACH_2_COUNTED_112(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112) \
+X(112, P1, P2) \
+MU_FOR_EACH_2_COUNTED_110(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112)
+
+#define MU_FOR_EACH_2_COUNTED_114(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114) \
+X(114, P1, P2) \
+MU_FOR_EACH_2_COUNTED_112(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114)
+
+#define MU_FOR_EACH_2_COUNTED_116(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116) \
+X(116, P1, P2) \
+MU_FOR_EACH_2_COUNTED_114(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116)
+
+#define MU_FOR_EACH_2_COUNTED_118(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118) \
+X(118, P1, P2) \
+MU_FOR_EACH_2_COUNTED_116(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118)
+
+#define MU_FOR_EACH_2_COUNTED_120(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120) \
+X(120, P1, P2) \
+MU_FOR_EACH_2_COUNTED_118(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120)
+
+#define MU_FOR_EACH_2_COUNTED_122(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122) \
+X(122, P1, P2) \
+MU_FOR_EACH_2_COUNTED_120(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122)
+
+#define MU_FOR_EACH_2_COUNTED_124(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123, P124) \
+X(124, P1, P2) \
+MU_FOR_EACH_2_COUNTED_122(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123, P124)
+
+
+#ifdef _MSC_VER
+#define MU_FOR_EACH_2(MACRO_TO_INVOKE, ...) MU_C2(MU_FOR_EACH_2_, MU_C1(MU_COUNT_ARG(__VA_ARGS__))) MU_LPAREN MACRO_TO_INVOKE, __VA_ARGS__)
+/*the COUNTED breed of MU_FOR_EACH macro invokes a macro with 3 parameters: 1st being the count of invocation. For example.
+MU_FOR_EACH_2_COUNTER(MACRO, a,b,c,d,e,f) will result in 
+MACRO(6, a,b)
+MACRO(4, c,d)
+MACRO(2, e,f)
+This macro exists because we need a "stop condition" in outputting COMMA... when calling a function f(a,b,c,d) cannot be f(a,b,c,d,) <=doesn't compile (as opposed to enum definition)
+*/
+#define MU_FOR_EACH_2_COUNTED(MACRO_TO_INVOKE, ...) MU_C2(MU_FOR_EACH_2_COUNTED_, MU_C1(MU_COUNT_ARG(__VA_ARGS__))) MU_LPAREN MACRO_TO_INVOKE, __VA_ARGS__)
+#define MU_FOR_EACH_1_COUNTED(MACRO_TO_INVOKE, ...) MU_C2(MU_FOR_EACH_1_COUNTED_, MU_C1(MU_COUNT_ARG(__VA_ARGS__))) MU_LPAREN MACRO_TO_INVOKE, __VA_ARGS__)
+
+/*MU_FOR_EACH_2_REVERSE acts just like MU_FOR_EACH_2, but in reverse order. Example:
+MU_FOR_EACH_2_REVERSE(X,a,b,c,d,e,f) => X(e,f) X(c,d) X (a, b) in this order */
+#define MU_FOR_EACH_2_REVERSE(MACRO_TO_INVOKE, ...) MU_C2(MU_FOR_EACH_2_REVERSE_, MU_C1(MU_COUNT_ARG(__VA_ARGS__))) MU_LPAREN MACRO_TO_INVOKE, __VA_ARGS__)
+#else
+#define MU_FOR_EACH_2(MACRO_TO_INVOKE, ...) MU_C2(MU_FOR_EACH_2_, MU_C1(MU_COUNT_ARG(__VA_ARGS__))) ( MACRO_TO_INVOKE, __VA_ARGS__)
+#define MU_FOR_EACH_2_COUNTED(MACRO_TO_INVOKE, ...) MU_C2(MU_FOR_EACH_2_COUNTED_, MU_C1(MU_COUNT_ARG(__VA_ARGS__))) ( MACRO_TO_INVOKE,  __VA_ARGS__)
+#define MU_FOR_EACH_1_COUNTED(MACRO_TO_INVOKE, ...) MU_C2(MU_FOR_EACH_1_COUNTED_, MU_C1(MU_COUNT_ARG(__VA_ARGS__))) ( MACRO_TO_INVOKE,  __VA_ARGS__)
+#define MU_FOR_EACH_2_REVERSE(MACRO_TO_INVOKE, ...) MU_C2(MU_FOR_EACH_2_REVERSE_, MU_C1(MU_COUNT_ARG(__VA_ARGS__))) ( MACRO_TO_INVOKE, __VA_ARGS__)
+#endif
+
+#ifdef _MSC_VER
+#define MU_EXPAND_OR_MU_C1(x) x
+#else
+#define MU_EXPAND_OR_MU_C1(...) __VA_ARGS__
+#endif
+
+#define MU_EXPAND_ARGS(...) __VA_ARGS__
+#define MU_EXPAND_TWICE(...) MU_EXPAND_ARGS(__VA_ARGS__)
+
+#define MU_DO_0(MACRO, ...) \
+MACRO(0, __VA_ARGS__)
+
+#define MU_DO_1(MACRO, ...) \
+MACRO(1, __VA_ARGS__) \
+MU_DO_0(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2(MACRO, ...) \
+MACRO(2, __VA_ARGS__) \
+MU_DO_1(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_3(MACRO, ...) \
+MACRO(3, __VA_ARGS__) \
+MU_DO_2(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_4(MACRO, ...) \
+MACRO(4, __VA_ARGS__) \
+MU_DO_3(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_5(MACRO, ...) \
+MACRO(5, __VA_ARGS__) \
+MU_DO_4(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_6(MACRO, ...) \
+MACRO(6, __VA_ARGS__) \
+MU_DO_5(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_7(MACRO, ...) \
+MACRO(7, __VA_ARGS__) \
+MU_DO_6(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_8(MACRO, ...) \
+MACRO(8, __VA_ARGS__) \
+MU_DO_7(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_9(MACRO, ...) \
+MACRO(9, __VA_ARGS__) \
+MU_DO_8(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_10(MACRO, ...) \
+MACRO(10, __VA_ARGS__) \
+MU_DO_9(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_11(MACRO, ...) \
+MACRO(11, __VA_ARGS__) \
+MU_DO_10(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_12(MACRO, ...) \
+MACRO(12, __VA_ARGS__) \
+MU_DO_11(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_13(MACRO, ...) \
+MACRO(13, __VA_ARGS__) \
+MU_DO_12(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_14(MACRO, ...) \
+MACRO(14, __VA_ARGS__) \
+MU_DO_13(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_15(MACRO, ...) \
+MACRO(15, __VA_ARGS__) \
+MU_DO_14(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_16(MACRO, ...) \
+MACRO(16, __VA_ARGS__) \
+MU_DO_15(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_17(MACRO, ...) \
+MACRO(17, __VA_ARGS__) \
+MU_DO_16(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_18(MACRO, ...) \
+MACRO(18, __VA_ARGS__) \
+MU_DO_17(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_19(MACRO, ...) \
+MACRO(19, __VA_ARGS__) \
+MU_DO_18(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_20(MACRO, ...) \
+MACRO(20, __VA_ARGS__) \
+MU_DO_19(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_21(MACRO, ...) \
+MACRO(21, __VA_ARGS__) \
+MU_DO_20(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_22(MACRO, ...) \
+MACRO(22, __VA_ARGS__) \
+MU_DO_21(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_23(MACRO, ...) \
+MACRO(23, __VA_ARGS__) \
+MU_DO_22(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_24(MACRO, ...) \
+MACRO(24, __VA_ARGS__) \
+MU_DO_23(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_25(MACRO, ...) \
+MACRO(25, __VA_ARGS__) \
+MU_DO_24(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_26(MACRO, ...) \
+MACRO(26, __VA_ARGS__) \
+MU_DO_25(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_27(MACRO, ...) \
+MACRO(27, __VA_ARGS__) \
+MU_DO_26(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_28(MACRO, ...) \
+MACRO(28, __VA_ARGS__) \
+MU_DO_27(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_29(MACRO, ...) \
+MACRO(29, __VA_ARGS__) \
+MU_DO_28(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_30(MACRO, ...) \
+MACRO(30, __VA_ARGS__) \
+MU_DO_29(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_31(MACRO, ...) \
+MACRO(31, __VA_ARGS__) \
+MU_DO_30(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_32(MACRO, ...) \
+MACRO(32, __VA_ARGS__) \
+MU_DO_31(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_33(MACRO, ...) \
+MACRO(33, __VA_ARGS__) \
+MU_DO_32(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_34(MACRO, ...) \
+MACRO(34, __VA_ARGS__) \
+MU_DO_33(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_35(MACRO, ...) \
+MACRO(35, __VA_ARGS__) \
+MU_DO_34(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_36(MACRO, ...) \
+MACRO(36, __VA_ARGS__) \
+MU_DO_35(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_37(MACRO, ...) \
+MACRO(37, __VA_ARGS__) \
+MU_DO_36(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_38(MACRO, ...) \
+MACRO(38, __VA_ARGS__) \
+MU_DO_37(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_39(MACRO, ...) \
+MACRO(39, __VA_ARGS__) \
+MU_DO_38(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_40(MACRO, ...) \
+MACRO(40, __VA_ARGS__) \
+MU_DO_39(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_41(MACRO, ...) \
+MACRO(41, __VA_ARGS__) \
+MU_DO_40(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_42(MACRO, ...) \
+MACRO(42, __VA_ARGS__) \
+MU_DO_41(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_43(MACRO, ...) \
+MACRO(43, __VA_ARGS__) \
+MU_DO_42(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_44(MACRO, ...) \
+MACRO(44, __VA_ARGS__) \
+MU_DO_43(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_45(MACRO, ...) \
+MACRO(45, __VA_ARGS__) \
+MU_DO_44(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_46(MACRO, ...) \
+MACRO(46, __VA_ARGS__) \
+MU_DO_45(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_47(MACRO, ...) \
+MACRO(47, __VA_ARGS__) \
+MU_DO_46(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_48(MACRO, ...) \
+MACRO(48, __VA_ARGS__) \
+MU_DO_47(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_49(MACRO, ...) \
+MACRO(49, __VA_ARGS__) \
+MU_DO_48(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_50(MACRO, ...) \
+MACRO(50, __VA_ARGS__) \
+MU_DO_49(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_51(MACRO, ...) \
+MACRO(51, __VA_ARGS__) \
+MU_DO_50(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_52(MACRO, ...) \
+MACRO(52, __VA_ARGS__) \
+MU_DO_51(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_53(MACRO, ...) \
+MACRO(53, __VA_ARGS__) \
+MU_DO_52(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_54(MACRO, ...) \
+MACRO(54, __VA_ARGS__) \
+MU_DO_53(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_55(MACRO, ...) \
+MACRO(55, __VA_ARGS__) \
+MU_DO_54(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_56(MACRO, ...) \
+MACRO(56, __VA_ARGS__) \
+MU_DO_55(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_57(MACRO, ...) \
+MACRO(57, __VA_ARGS__) \
+MU_DO_56(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_58(MACRO, ...) \
+MACRO(58, __VA_ARGS__) \
+MU_DO_57(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_59(MACRO, ...) \
+MACRO(59, __VA_ARGS__) \
+MU_DO_58(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_60(MACRO, ...) \
+MACRO(60, __VA_ARGS__) \
+MU_DO_59(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_61(MACRO, ...) \
+MACRO(61, __VA_ARGS__) \
+MU_DO_60(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_62(MACRO, ...) \
+MACRO(62, __VA_ARGS__) \
+MU_DO_61(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_63(MACRO, ...) \
+MACRO(63, __VA_ARGS__) \
+MU_DO_62(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_64(MACRO, ...) \
+MACRO(64, __VA_ARGS__) \
+MU_DO_63(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_65(MACRO, ...) \
+MACRO(65, __VA_ARGS__) \
+MU_DO_64(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_66(MACRO, ...) \
+MACRO(66, __VA_ARGS__) \
+MU_DO_65(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_67(MACRO, ...) \
+MACRO(67, __VA_ARGS__) \
+MU_DO_66(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_68(MACRO, ...) \
+MACRO(68, __VA_ARGS__) \
+MU_DO_67(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_69(MACRO, ...) \
+MACRO(69, __VA_ARGS__) \
+MU_DO_68(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_70(MACRO, ...) \
+MACRO(70, __VA_ARGS__) \
+MU_DO_69(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_71(MACRO, ...) \
+MACRO(71, __VA_ARGS__) \
+MU_DO_70(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_72(MACRO, ...) \
+MACRO(72, __VA_ARGS__) \
+MU_DO_71(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_73(MACRO, ...) \
+MACRO(73, __VA_ARGS__) \
+MU_DO_72(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_74(MACRO, ...) \
+MACRO(74, __VA_ARGS__) \
+MU_DO_73(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_75(MACRO, ...) \
+MACRO(75, __VA_ARGS__) \
+MU_DO_74(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_76(MACRO, ...) \
+MACRO(76, __VA_ARGS__) \
+MU_DO_75(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_77(MACRO, ...) \
+MACRO(77, __VA_ARGS__) \
+MU_DO_76(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_78(MACRO, ...) \
+MACRO(78, __VA_ARGS__) \
+MU_DO_77(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_79(MACRO, ...) \
+MACRO(79, __VA_ARGS__) \
+MU_DO_78(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_80(MACRO, ...) \
+MACRO(80, __VA_ARGS__) \
+MU_DO_79(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_81(MACRO, ...) \
+MACRO(81, __VA_ARGS__) \
+MU_DO_80(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_82(MACRO, ...) \
+MACRO(82, __VA_ARGS__) \
+MU_DO_81(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_83(MACRO, ...) \
+MACRO(83, __VA_ARGS__) \
+MU_DO_82(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_84(MACRO, ...) \
+MACRO(84, __VA_ARGS__) \
+MU_DO_83(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_85(MACRO, ...) \
+MACRO(85, __VA_ARGS__) \
+MU_DO_84(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_86(MACRO, ...) \
+MACRO(86, __VA_ARGS__) \
+MU_DO_85(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_87(MACRO, ...) \
+MACRO(87, __VA_ARGS__) \
+MU_DO_86(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_88(MACRO, ...) \
+MACRO(88, __VA_ARGS__) \
+MU_DO_87(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_89(MACRO, ...) \
+MACRO(89, __VA_ARGS__) \
+MU_DO_88(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_90(MACRO, ...) \
+MACRO(90, __VA_ARGS__) \
+MU_DO_89(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_91(MACRO, ...) \
+MACRO(91, __VA_ARGS__) \
+MU_DO_90(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_92(MACRO, ...) \
+MACRO(92, __VA_ARGS__) \
+MU_DO_91(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_93(MACRO, ...) \
+MACRO(93, __VA_ARGS__) \
+MU_DO_92(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_94(MACRO, ...) \
+MACRO(94, __VA_ARGS__) \
+MU_DO_93(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_95(MACRO, ...) \
+MACRO(95, __VA_ARGS__) \
+MU_DO_94(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_96(MACRO, ...) \
+MACRO(96, __VA_ARGS__) \
+MU_DO_95(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_97(MACRO, ...) \
+MACRO(97, __VA_ARGS__) \
+MU_DO_96(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_98(MACRO, ...) \
+MACRO(98, __VA_ARGS__) \
+MU_DO_97(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_99(MACRO, ...) \
+MACRO(99, __VA_ARGS__) \
+MU_DO_98(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_100(MACRO, ...) \
+MACRO(100, __VA_ARGS__) \
+MU_DO_99(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_101(MACRO, ...) \
+MACRO(101, __VA_ARGS__) \
+MU_DO_100(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_102(MACRO, ...) \
+MACRO(102, __VA_ARGS__) \
+MU_DO_101(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_103(MACRO, ...) \
+MACRO(103, __VA_ARGS__) \
+MU_DO_102(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_104(MACRO, ...) \
+MACRO(104, __VA_ARGS__) \
+MU_DO_103(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_105(MACRO, ...) \
+MACRO(105, __VA_ARGS__) \
+MU_DO_104(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_106(MACRO, ...) \
+MACRO(106, __VA_ARGS__) \
+MU_DO_105(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_107(MACRO, ...) \
+MACRO(107, __VA_ARGS__) \
+MU_DO_106(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_108(MACRO, ...) \
+MACRO(108, __VA_ARGS__) \
+MU_DO_107(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_109(MACRO, ...) \
+MACRO(109, __VA_ARGS__) \
+MU_DO_108(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_110(MACRO, ...) \
+MACRO(110, __VA_ARGS__) \
+MU_DO_109(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_111(MACRO, ...) \
+MACRO(111, __VA_ARGS__) \
+MU_DO_110(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_112(MACRO, ...) \
+MACRO(112, __VA_ARGS__) \
+MU_DO_111(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_113(MACRO, ...) \
+MACRO(113, __VA_ARGS__) \
+MU_DO_112(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_114(MACRO, ...) \
+MACRO(114, __VA_ARGS__) \
+MU_DO_113(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_115(MACRO, ...) \
+MACRO(115, __VA_ARGS__) \
+MU_DO_114(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_116(MACRO, ...) \
+MACRO(116, __VA_ARGS__) \
+MU_DO_115(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_117(MACRO, ...) \
+MACRO(117, __VA_ARGS__) \
+MU_DO_116(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_118(MACRO, ...) \
+MACRO(118, __VA_ARGS__) \
+MU_DO_117(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_119(MACRO, ...) \
+MACRO(119, __VA_ARGS__) \
+MU_DO_118(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_120(MACRO, ...) \
+MACRO(120, __VA_ARGS__) \
+MU_DO_119(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_121(MACRO, ...) \
+MACRO(121, __VA_ARGS__) \
+MU_DO_120(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_122(MACRO, ...) \
+MACRO(122, __VA_ARGS__) \
+MU_DO_121(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_123(MACRO, ...) \
+MACRO(123, __VA_ARGS__) \
+MU_DO_122(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_124(MACRO, ...) \
+MACRO(124, __VA_ARGS__) \
+MU_DO_123(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_125(MACRO, ...) \
+MACRO(125, __VA_ARGS__) \
+MU_DO_124(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_126(MACRO, ...) \
+MACRO(126, __VA_ARGS__) \
+MU_DO_125(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_127(MACRO, ...) \
+MACRO(127, __VA_ARGS__) \
+MU_DO_126(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_128(MACRO, ...) \
+MACRO(128, __VA_ARGS__) \
+MU_DO_127(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_129(MACRO, ...) \
+MACRO(129, __VA_ARGS__) \
+MU_DO_128(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_130(MACRO, ...) \
+MACRO(130, __VA_ARGS__) \
+MU_DO_129(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_131(MACRO, ...) \
+MACRO(131, __VA_ARGS__) \
+MU_DO_130(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_132(MACRO, ...) \
+MACRO(132, __VA_ARGS__) \
+MU_DO_131(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_133(MACRO, ...) \
+MACRO(133, __VA_ARGS__) \
+MU_DO_132(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_134(MACRO, ...) \
+MACRO(134, __VA_ARGS__) \
+MU_DO_133(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_135(MACRO, ...) \
+MACRO(135, __VA_ARGS__) \
+MU_DO_134(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_136(MACRO, ...) \
+MACRO(136, __VA_ARGS__) \
+MU_DO_135(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_137(MACRO, ...) \
+MACRO(137, __VA_ARGS__) \
+MU_DO_136(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_138(MACRO, ...) \
+MACRO(138, __VA_ARGS__) \
+MU_DO_137(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_139(MACRO, ...) \
+MACRO(139, __VA_ARGS__) \
+MU_DO_138(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_140(MACRO, ...) \
+MACRO(140, __VA_ARGS__) \
+MU_DO_139(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_141(MACRO, ...) \
+MACRO(141, __VA_ARGS__) \
+MU_DO_140(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_142(MACRO, ...) \
+MACRO(142, __VA_ARGS__) \
+MU_DO_141(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_143(MACRO, ...) \
+MACRO(143, __VA_ARGS__) \
+MU_DO_142(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_144(MACRO, ...) \
+MACRO(144, __VA_ARGS__) \
+MU_DO_143(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_145(MACRO, ...) \
+MACRO(145, __VA_ARGS__) \
+MU_DO_144(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_146(MACRO, ...) \
+MACRO(146, __VA_ARGS__) \
+MU_DO_145(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_147(MACRO, ...) \
+MACRO(147, __VA_ARGS__) \
+MU_DO_146(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_148(MACRO, ...) \
+MACRO(148, __VA_ARGS__) \
+MU_DO_147(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_149(MACRO, ...) \
+MACRO(149, __VA_ARGS__) \
+MU_DO_148(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_150(MACRO, ...) \
+MACRO(150, __VA_ARGS__) \
+MU_DO_149(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_151(MACRO, ...) \
+MACRO(151, __VA_ARGS__) \
+MU_DO_150(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_152(MACRO, ...) \
+MACRO(152, __VA_ARGS__) \
+MU_DO_151(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_153(MACRO, ...) \
+MACRO(153, __VA_ARGS__) \
+MU_DO_152(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_154(MACRO, ...) \
+MACRO(154, __VA_ARGS__) \
+MU_DO_153(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_155(MACRO, ...) \
+MACRO(155, __VA_ARGS__) \
+MU_DO_154(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_156(MACRO, ...) \
+MACRO(156, __VA_ARGS__) \
+MU_DO_155(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_157(MACRO, ...) \
+MACRO(157, __VA_ARGS__) \
+MU_DO_156(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_158(MACRO, ...) \
+MACRO(158, __VA_ARGS__) \
+MU_DO_157(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_159(MACRO, ...) \
+MACRO(159, __VA_ARGS__) \
+MU_DO_158(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_160(MACRO, ...) \
+MACRO(160, __VA_ARGS__) \
+MU_DO_159(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_161(MACRO, ...) \
+MACRO(161, __VA_ARGS__) \
+MU_DO_160(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_162(MACRO, ...) \
+MACRO(162, __VA_ARGS__) \
+MU_DO_161(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_163(MACRO, ...) \
+MACRO(163, __VA_ARGS__) \
+MU_DO_162(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_164(MACRO, ...) \
+MACRO(164, __VA_ARGS__) \
+MU_DO_163(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_165(MACRO, ...) \
+MACRO(165, __VA_ARGS__) \
+MU_DO_164(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_166(MACRO, ...) \
+MACRO(166, __VA_ARGS__) \
+MU_DO_165(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_167(MACRO, ...) \
+MACRO(167, __VA_ARGS__) \
+MU_DO_166(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_168(MACRO, ...) \
+MACRO(168, __VA_ARGS__) \
+MU_DO_167(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_169(MACRO, ...) \
+MACRO(169, __VA_ARGS__) \
+MU_DO_168(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_170(MACRO, ...) \
+MACRO(170, __VA_ARGS__) \
+MU_DO_169(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_171(MACRO, ...) \
+MACRO(171, __VA_ARGS__) \
+MU_DO_170(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_172(MACRO, ...) \
+MACRO(172, __VA_ARGS__) \
+MU_DO_171(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_173(MACRO, ...) \
+MACRO(173, __VA_ARGS__) \
+MU_DO_172(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_174(MACRO, ...) \
+MACRO(174, __VA_ARGS__) \
+MU_DO_173(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_175(MACRO, ...) \
+MACRO(175, __VA_ARGS__) \
+MU_DO_174(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_176(MACRO, ...) \
+MACRO(176, __VA_ARGS__) \
+MU_DO_175(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_177(MACRO, ...) \
+MACRO(177, __VA_ARGS__) \
+MU_DO_176(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_178(MACRO, ...) \
+MACRO(178, __VA_ARGS__) \
+MU_DO_177(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_179(MACRO, ...) \
+MACRO(179, __VA_ARGS__) \
+MU_DO_178(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_180(MACRO, ...) \
+MACRO(180, __VA_ARGS__) \
+MU_DO_179(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_181(MACRO, ...) \
+MACRO(181, __VA_ARGS__) \
+MU_DO_180(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_182(MACRO, ...) \
+MACRO(182, __VA_ARGS__) \
+MU_DO_181(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_183(MACRO, ...) \
+MACRO(183, __VA_ARGS__) \
+MU_DO_182(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_184(MACRO, ...) \
+MACRO(184, __VA_ARGS__) \
+MU_DO_183(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_185(MACRO, ...) \
+MACRO(185, __VA_ARGS__) \
+MU_DO_184(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_186(MACRO, ...) \
+MACRO(186, __VA_ARGS__) \
+MU_DO_185(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_187(MACRO, ...) \
+MACRO(187, __VA_ARGS__) \
+MU_DO_186(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_188(MACRO, ...) \
+MACRO(188, __VA_ARGS__) \
+MU_DO_187(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_189(MACRO, ...) \
+MACRO(189, __VA_ARGS__) \
+MU_DO_188(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_190(MACRO, ...) \
+MACRO(190, __VA_ARGS__) \
+MU_DO_189(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_191(MACRO, ...) \
+MACRO(191, __VA_ARGS__) \
+MU_DO_190(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_192(MACRO, ...) \
+MACRO(192, __VA_ARGS__) \
+MU_DO_191(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_193(MACRO, ...) \
+MACRO(193, __VA_ARGS__) \
+MU_DO_192(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_194(MACRO, ...) \
+MACRO(194, __VA_ARGS__) \
+MU_DO_193(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_195(MACRO, ...) \
+MACRO(195, __VA_ARGS__) \
+MU_DO_194(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_196(MACRO, ...) \
+MACRO(196, __VA_ARGS__) \
+MU_DO_195(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_197(MACRO, ...) \
+MACRO(197, __VA_ARGS__) \
+MU_DO_196(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_198(MACRO, ...) \
+MACRO(198, __VA_ARGS__) \
+MU_DO_197(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_199(MACRO, ...) \
+MACRO(199, __VA_ARGS__) \
+MU_DO_198(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_200(MACRO, ...) \
+MACRO(200, __VA_ARGS__) \
+MU_DO_199(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_201(MACRO, ...) \
+MACRO(201, __VA_ARGS__) \
+MU_DO_200(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_202(MACRO, ...) \
+MACRO(202, __VA_ARGS__) \
+MU_DO_201(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_203(MACRO, ...) \
+MACRO(203, __VA_ARGS__) \
+MU_DO_202(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_204(MACRO, ...) \
+MACRO(204, __VA_ARGS__) \
+MU_DO_203(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_205(MACRO, ...) \
+MACRO(205, __VA_ARGS__) \
+MU_DO_204(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_206(MACRO, ...) \
+MACRO(206, __VA_ARGS__) \
+MU_DO_205(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_207(MACRO, ...) \
+MACRO(207, __VA_ARGS__) \
+MU_DO_206(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_208(MACRO, ...) \
+MACRO(208, __VA_ARGS__) \
+MU_DO_207(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_209(MACRO, ...) \
+MACRO(209, __VA_ARGS__) \
+MU_DO_208(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_210(MACRO, ...) \
+MACRO(210, __VA_ARGS__) \
+MU_DO_209(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_211(MACRO, ...) \
+MACRO(211, __VA_ARGS__) \
+MU_DO_210(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_212(MACRO, ...) \
+MACRO(212, __VA_ARGS__) \
+MU_DO_211(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_213(MACRO, ...) \
+MACRO(213, __VA_ARGS__) \
+MU_DO_212(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_214(MACRO, ...) \
+MACRO(214, __VA_ARGS__) \
+MU_DO_213(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_215(MACRO, ...) \
+MACRO(215, __VA_ARGS__) \
+MU_DO_214(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_216(MACRO, ...) \
+MACRO(216, __VA_ARGS__) \
+MU_DO_215(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_217(MACRO, ...) \
+MACRO(217, __VA_ARGS__) \
+MU_DO_216(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_218(MACRO, ...) \
+MACRO(218, __VA_ARGS__) \
+MU_DO_217(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_219(MACRO, ...) \
+MACRO(219, __VA_ARGS__) \
+MU_DO_218(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_220(MACRO, ...) \
+MACRO(220, __VA_ARGS__) \
+MU_DO_219(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_221(MACRO, ...) \
+MACRO(221, __VA_ARGS__) \
+MU_DO_220(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_222(MACRO, ...) \
+MACRO(222, __VA_ARGS__) \
+MU_DO_221(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_223(MACRO, ...) \
+MACRO(223, __VA_ARGS__) \
+MU_DO_222(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_224(MACRO, ...) \
+MACRO(224, __VA_ARGS__) \
+MU_DO_223(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_225(MACRO, ...) \
+MACRO(225, __VA_ARGS__) \
+MU_DO_224(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_226(MACRO, ...) \
+MACRO(226, __VA_ARGS__) \
+MU_DO_225(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_227(MACRO, ...) \
+MACRO(227, __VA_ARGS__) \
+MU_DO_226(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_228(MACRO, ...) \
+MACRO(228, __VA_ARGS__) \
+MU_DO_227(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_229(MACRO, ...) \
+MACRO(229, __VA_ARGS__) \
+MU_DO_228(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_230(MACRO, ...) \
+MACRO(230, __VA_ARGS__) \
+MU_DO_229(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_231(MACRO, ...) \
+MACRO(231, __VA_ARGS__) \
+MU_DO_230(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_232(MACRO, ...) \
+MACRO(232, __VA_ARGS__) \
+MU_DO_231(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_233(MACRO, ...) \
+MACRO(233, __VA_ARGS__) \
+MU_DO_232(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_234(MACRO, ...) \
+MACRO(234, __VA_ARGS__) \
+MU_DO_233(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_235(MACRO, ...) \
+MACRO(235, __VA_ARGS__) \
+MU_DO_234(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_236(MACRO, ...) \
+MACRO(236, __VA_ARGS__) \
+MU_DO_235(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_237(MACRO, ...) \
+MACRO(237, __VA_ARGS__) \
+MU_DO_236(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_238(MACRO, ...) \
+MACRO(238, __VA_ARGS__) \
+MU_DO_237(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_239(MACRO, ...) \
+MACRO(239, __VA_ARGS__) \
+MU_DO_238(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_240(MACRO, ...) \
+MACRO(240, __VA_ARGS__) \
+MU_DO_239(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_241(MACRO, ...) \
+MACRO(241, __VA_ARGS__) \
+MU_DO_240(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_242(MACRO, ...) \
+MACRO(242, __VA_ARGS__) \
+MU_DO_241(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_243(MACRO, ...) \
+MACRO(243, __VA_ARGS__) \
+MU_DO_242(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_244(MACRO, ...) \
+MACRO(244, __VA_ARGS__) \
+MU_DO_243(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_245(MACRO, ...) \
+MACRO(245, __VA_ARGS__) \
+MU_DO_244(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_246(MACRO, ...) \
+MACRO(246, __VA_ARGS__) \
+MU_DO_245(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_247(MACRO, ...) \
+MACRO(247, __VA_ARGS__) \
+MU_DO_246(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_248(MACRO, ...) \
+MACRO(248, __VA_ARGS__) \
+MU_DO_247(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_249(MACRO, ...) \
+MACRO(249, __VA_ARGS__) \
+MU_DO_248(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_250(MACRO, ...) \
+MACRO(250, __VA_ARGS__) \
+MU_DO_249(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_251(MACRO, ...) \
+MACRO(251, __VA_ARGS__) \
+MU_DO_250(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_252(MACRO, ...) \
+MACRO(252, __VA_ARGS__) \
+MU_DO_251(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_253(MACRO, ...) \
+MACRO(253, __VA_ARGS__) \
+MU_DO_252(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_254(MACRO, ...) \
+MACRO(254, __VA_ARGS__) \
+MU_DO_253(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_255(MACRO, ...) \
+MACRO(255, __VA_ARGS__) \
+MU_DO_254(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_256(MACRO, ...) \
+MACRO(256, __VA_ARGS__) \
+MU_DO_255(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_257(MACRO, ...) \
+MACRO(257, __VA_ARGS__) \
+MU_DO_256(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_258(MACRO, ...) \
+MACRO(258, __VA_ARGS__) \
+MU_DO_257(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_259(MACRO, ...) \
+MACRO(259, __VA_ARGS__) \
+MU_DO_258(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_260(MACRO, ...) \
+MACRO(260, __VA_ARGS__) \
+MU_DO_259(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_261(MACRO, ...) \
+MACRO(261, __VA_ARGS__) \
+MU_DO_260(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_262(MACRO, ...) \
+MACRO(262, __VA_ARGS__) \
+MU_DO_261(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_263(MACRO, ...) \
+MACRO(263, __VA_ARGS__) \
+MU_DO_262(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_264(MACRO, ...) \
+MACRO(264, __VA_ARGS__) \
+MU_DO_263(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_265(MACRO, ...) \
+MACRO(265, __VA_ARGS__) \
+MU_DO_264(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_266(MACRO, ...) \
+MACRO(266, __VA_ARGS__) \
+MU_DO_265(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_267(MACRO, ...) \
+MACRO(267, __VA_ARGS__) \
+MU_DO_266(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_268(MACRO, ...) \
+MACRO(268, __VA_ARGS__) \
+MU_DO_267(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_269(MACRO, ...) \
+MACRO(269, __VA_ARGS__) \
+MU_DO_268(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_270(MACRO, ...) \
+MACRO(270, __VA_ARGS__) \
+MU_DO_269(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_271(MACRO, ...) \
+MACRO(271, __VA_ARGS__) \
+MU_DO_270(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_272(MACRO, ...) \
+MACRO(272, __VA_ARGS__) \
+MU_DO_271(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_273(MACRO, ...) \
+MACRO(273, __VA_ARGS__) \
+MU_DO_272(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_274(MACRO, ...) \
+MACRO(274, __VA_ARGS__) \
+MU_DO_273(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_275(MACRO, ...) \
+MACRO(275, __VA_ARGS__) \
+MU_DO_274(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_276(MACRO, ...) \
+MACRO(276, __VA_ARGS__) \
+MU_DO_275(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_277(MACRO, ...) \
+MACRO(277, __VA_ARGS__) \
+MU_DO_276(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_278(MACRO, ...) \
+MACRO(278, __VA_ARGS__) \
+MU_DO_277(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_279(MACRO, ...) \
+MACRO(279, __VA_ARGS__) \
+MU_DO_278(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_280(MACRO, ...) \
+MACRO(280, __VA_ARGS__) \
+MU_DO_279(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_281(MACRO, ...) \
+MACRO(281, __VA_ARGS__) \
+MU_DO_280(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_282(MACRO, ...) \
+MACRO(282, __VA_ARGS__) \
+MU_DO_281(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_283(MACRO, ...) \
+MACRO(283, __VA_ARGS__) \
+MU_DO_282(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_284(MACRO, ...) \
+MACRO(284, __VA_ARGS__) \
+MU_DO_283(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_285(MACRO, ...) \
+MACRO(285, __VA_ARGS__) \
+MU_DO_284(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_286(MACRO, ...) \
+MACRO(286, __VA_ARGS__) \
+MU_DO_285(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_287(MACRO, ...) \
+MACRO(287, __VA_ARGS__) \
+MU_DO_286(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_288(MACRO, ...) \
+MACRO(288, __VA_ARGS__) \
+MU_DO_287(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_289(MACRO, ...) \
+MACRO(289, __VA_ARGS__) \
+MU_DO_288(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_290(MACRO, ...) \
+MACRO(290, __VA_ARGS__) \
+MU_DO_289(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_291(MACRO, ...) \
+MACRO(291, __VA_ARGS__) \
+MU_DO_290(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_292(MACRO, ...) \
+MACRO(292, __VA_ARGS__) \
+MU_DO_291(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_293(MACRO, ...) \
+MACRO(293, __VA_ARGS__) \
+MU_DO_292(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_294(MACRO, ...) \
+MACRO(294, __VA_ARGS__) \
+MU_DO_293(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_295(MACRO, ...) \
+MACRO(295, __VA_ARGS__) \
+MU_DO_294(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_296(MACRO, ...) \
+MACRO(296, __VA_ARGS__) \
+MU_DO_295(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_297(MACRO, ...) \
+MACRO(297, __VA_ARGS__) \
+MU_DO_296(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_298(MACRO, ...) \
+MACRO(298, __VA_ARGS__) \
+MU_DO_297(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_299(MACRO, ...) \
+MACRO(299, __VA_ARGS__) \
+MU_DO_298(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_300(MACRO, ...) \
+MACRO(300, __VA_ARGS__) \
+MU_DO_299(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_301(MACRO, ...) \
+MACRO(301, __VA_ARGS__) \
+MU_DO_300(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_302(MACRO, ...) \
+MACRO(302, __VA_ARGS__) \
+MU_DO_301(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_303(MACRO, ...) \
+MACRO(303, __VA_ARGS__) \
+MU_DO_302(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_304(MACRO, ...) \
+MACRO(304, __VA_ARGS__) \
+MU_DO_303(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_305(MACRO, ...) \
+MACRO(305, __VA_ARGS__) \
+MU_DO_304(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_306(MACRO, ...) \
+MACRO(306, __VA_ARGS__) \
+MU_DO_305(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_307(MACRO, ...) \
+MACRO(307, __VA_ARGS__) \
+MU_DO_306(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_308(MACRO, ...) \
+MACRO(308, __VA_ARGS__) \
+MU_DO_307(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_309(MACRO, ...) \
+MACRO(309, __VA_ARGS__) \
+MU_DO_308(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_310(MACRO, ...) \
+MACRO(310, __VA_ARGS__) \
+MU_DO_309(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_311(MACRO, ...) \
+MACRO(311, __VA_ARGS__) \
+MU_DO_310(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_312(MACRO, ...) \
+MACRO(312, __VA_ARGS__) \
+MU_DO_311(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_313(MACRO, ...) \
+MACRO(313, __VA_ARGS__) \
+MU_DO_312(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_314(MACRO, ...) \
+MACRO(314, __VA_ARGS__) \
+MU_DO_313(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_315(MACRO, ...) \
+MACRO(315, __VA_ARGS__) \
+MU_DO_314(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_316(MACRO, ...) \
+MACRO(316, __VA_ARGS__) \
+MU_DO_315(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_317(MACRO, ...) \
+MACRO(317, __VA_ARGS__) \
+MU_DO_316(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_318(MACRO, ...) \
+MACRO(318, __VA_ARGS__) \
+MU_DO_317(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_319(MACRO, ...) \
+MACRO(319, __VA_ARGS__) \
+MU_DO_318(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_320(MACRO, ...) \
+MACRO(320, __VA_ARGS__) \
+MU_DO_319(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_321(MACRO, ...) \
+MACRO(321, __VA_ARGS__) \
+MU_DO_320(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_322(MACRO, ...) \
+MACRO(322, __VA_ARGS__) \
+MU_DO_321(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_323(MACRO, ...) \
+MACRO(323, __VA_ARGS__) \
+MU_DO_322(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_324(MACRO, ...) \
+MACRO(324, __VA_ARGS__) \
+MU_DO_323(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_325(MACRO, ...) \
+MACRO(325, __VA_ARGS__) \
+MU_DO_324(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_326(MACRO, ...) \
+MACRO(326, __VA_ARGS__) \
+MU_DO_325(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_327(MACRO, ...) \
+MACRO(327, __VA_ARGS__) \
+MU_DO_326(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_328(MACRO, ...) \
+MACRO(328, __VA_ARGS__) \
+MU_DO_327(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_329(MACRO, ...) \
+MACRO(329, __VA_ARGS__) \
+MU_DO_328(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_330(MACRO, ...) \
+MACRO(330, __VA_ARGS__) \
+MU_DO_329(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_331(MACRO, ...) \
+MACRO(331, __VA_ARGS__) \
+MU_DO_330(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_332(MACRO, ...) \
+MACRO(332, __VA_ARGS__) \
+MU_DO_331(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_333(MACRO, ...) \
+MACRO(333, __VA_ARGS__) \
+MU_DO_332(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_334(MACRO, ...) \
+MACRO(334, __VA_ARGS__) \
+MU_DO_333(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_335(MACRO, ...) \
+MACRO(335, __VA_ARGS__) \
+MU_DO_334(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_336(MACRO, ...) \
+MACRO(336, __VA_ARGS__) \
+MU_DO_335(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_337(MACRO, ...) \
+MACRO(337, __VA_ARGS__) \
+MU_DO_336(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_338(MACRO, ...) \
+MACRO(338, __VA_ARGS__) \
+MU_DO_337(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_339(MACRO, ...) \
+MACRO(339, __VA_ARGS__) \
+MU_DO_338(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_340(MACRO, ...) \
+MACRO(340, __VA_ARGS__) \
+MU_DO_339(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_341(MACRO, ...) \
+MACRO(341, __VA_ARGS__) \
+MU_DO_340(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_342(MACRO, ...) \
+MACRO(342, __VA_ARGS__) \
+MU_DO_341(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_343(MACRO, ...) \
+MACRO(343, __VA_ARGS__) \
+MU_DO_342(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_344(MACRO, ...) \
+MACRO(344, __VA_ARGS__) \
+MU_DO_343(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_345(MACRO, ...) \
+MACRO(345, __VA_ARGS__) \
+MU_DO_344(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_346(MACRO, ...) \
+MACRO(346, __VA_ARGS__) \
+MU_DO_345(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_347(MACRO, ...) \
+MACRO(347, __VA_ARGS__) \
+MU_DO_346(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_348(MACRO, ...) \
+MACRO(348, __VA_ARGS__) \
+MU_DO_347(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_349(MACRO, ...) \
+MACRO(349, __VA_ARGS__) \
+MU_DO_348(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_350(MACRO, ...) \
+MACRO(350, __VA_ARGS__) \
+MU_DO_349(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_351(MACRO, ...) \
+MACRO(351, __VA_ARGS__) \
+MU_DO_350(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_352(MACRO, ...) \
+MACRO(352, __VA_ARGS__) \
+MU_DO_351(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_353(MACRO, ...) \
+MACRO(353, __VA_ARGS__) \
+MU_DO_352(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_354(MACRO, ...) \
+MACRO(354, __VA_ARGS__) \
+MU_DO_353(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_355(MACRO, ...) \
+MACRO(355, __VA_ARGS__) \
+MU_DO_354(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_356(MACRO, ...) \
+MACRO(356, __VA_ARGS__) \
+MU_DO_355(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_357(MACRO, ...) \
+MACRO(357, __VA_ARGS__) \
+MU_DO_356(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_358(MACRO, ...) \
+MACRO(358, __VA_ARGS__) \
+MU_DO_357(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_359(MACRO, ...) \
+MACRO(359, __VA_ARGS__) \
+MU_DO_358(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_360(MACRO, ...) \
+MACRO(360, __VA_ARGS__) \
+MU_DO_359(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_361(MACRO, ...) \
+MACRO(361, __VA_ARGS__) \
+MU_DO_360(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_362(MACRO, ...) \
+MACRO(362, __VA_ARGS__) \
+MU_DO_361(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_363(MACRO, ...) \
+MACRO(363, __VA_ARGS__) \
+MU_DO_362(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_364(MACRO, ...) \
+MACRO(364, __VA_ARGS__) \
+MU_DO_363(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_365(MACRO, ...) \
+MACRO(365, __VA_ARGS__) \
+MU_DO_364(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_366(MACRO, ...) \
+MACRO(366, __VA_ARGS__) \
+MU_DO_365(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_367(MACRO, ...) \
+MACRO(367, __VA_ARGS__) \
+MU_DO_366(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_368(MACRO, ...) \
+MACRO(368, __VA_ARGS__) \
+MU_DO_367(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_369(MACRO, ...) \
+MACRO(369, __VA_ARGS__) \
+MU_DO_368(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_370(MACRO, ...) \
+MACRO(370, __VA_ARGS__) \
+MU_DO_369(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_371(MACRO, ...) \
+MACRO(371, __VA_ARGS__) \
+MU_DO_370(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_372(MACRO, ...) \
+MACRO(372, __VA_ARGS__) \
+MU_DO_371(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_373(MACRO, ...) \
+MACRO(373, __VA_ARGS__) \
+MU_DO_372(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_374(MACRO, ...) \
+MACRO(374, __VA_ARGS__) \
+MU_DO_373(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_375(MACRO, ...) \
+MACRO(375, __VA_ARGS__) \
+MU_DO_374(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_376(MACRO, ...) \
+MACRO(376, __VA_ARGS__) \
+MU_DO_375(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_377(MACRO, ...) \
+MACRO(377, __VA_ARGS__) \
+MU_DO_376(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_378(MACRO, ...) \
+MACRO(378, __VA_ARGS__) \
+MU_DO_377(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_379(MACRO, ...) \
+MACRO(379, __VA_ARGS__) \
+MU_DO_378(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_380(MACRO, ...) \
+MACRO(380, __VA_ARGS__) \
+MU_DO_379(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_381(MACRO, ...) \
+MACRO(381, __VA_ARGS__) \
+MU_DO_380(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_382(MACRO, ...) \
+MACRO(382, __VA_ARGS__) \
+MU_DO_381(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_383(MACRO, ...) \
+MACRO(383, __VA_ARGS__) \
+MU_DO_382(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_384(MACRO, ...) \
+MACRO(384, __VA_ARGS__) \
+MU_DO_383(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_385(MACRO, ...) \
+MACRO(385, __VA_ARGS__) \
+MU_DO_384(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_386(MACRO, ...) \
+MACRO(386, __VA_ARGS__) \
+MU_DO_385(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_387(MACRO, ...) \
+MACRO(387, __VA_ARGS__) \
+MU_DO_386(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_388(MACRO, ...) \
+MACRO(388, __VA_ARGS__) \
+MU_DO_387(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_389(MACRO, ...) \
+MACRO(389, __VA_ARGS__) \
+MU_DO_388(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_390(MACRO, ...) \
+MACRO(390, __VA_ARGS__) \
+MU_DO_389(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_391(MACRO, ...) \
+MACRO(391, __VA_ARGS__) \
+MU_DO_390(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_392(MACRO, ...) \
+MACRO(392, __VA_ARGS__) \
+MU_DO_391(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_393(MACRO, ...) \
+MACRO(393, __VA_ARGS__) \
+MU_DO_392(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_394(MACRO, ...) \
+MACRO(394, __VA_ARGS__) \
+MU_DO_393(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_395(MACRO, ...) \
+MACRO(395, __VA_ARGS__) \
+MU_DO_394(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_396(MACRO, ...) \
+MACRO(396, __VA_ARGS__) \
+MU_DO_395(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_397(MACRO, ...) \
+MACRO(397, __VA_ARGS__) \
+MU_DO_396(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_398(MACRO, ...) \
+MACRO(398, __VA_ARGS__) \
+MU_DO_397(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_399(MACRO, ...) \
+MACRO(399, __VA_ARGS__) \
+MU_DO_398(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_400(MACRO, ...) \
+MACRO(400, __VA_ARGS__) \
+MU_DO_399(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_401(MACRO, ...) \
+MACRO(401, __VA_ARGS__) \
+MU_DO_400(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_402(MACRO, ...) \
+MACRO(402, __VA_ARGS__) \
+MU_DO_401(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_403(MACRO, ...) \
+MACRO(403, __VA_ARGS__) \
+MU_DO_402(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_404(MACRO, ...) \
+MACRO(404, __VA_ARGS__) \
+MU_DO_403(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_405(MACRO, ...) \
+MACRO(405, __VA_ARGS__) \
+MU_DO_404(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_406(MACRO, ...) \
+MACRO(406, __VA_ARGS__) \
+MU_DO_405(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_407(MACRO, ...) \
+MACRO(407, __VA_ARGS__) \
+MU_DO_406(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_408(MACRO, ...) \
+MACRO(408, __VA_ARGS__) \
+MU_DO_407(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_409(MACRO, ...) \
+MACRO(409, __VA_ARGS__) \
+MU_DO_408(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_410(MACRO, ...) \
+MACRO(410, __VA_ARGS__) \
+MU_DO_409(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_411(MACRO, ...) \
+MACRO(411, __VA_ARGS__) \
+MU_DO_410(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_412(MACRO, ...) \
+MACRO(412, __VA_ARGS__) \
+MU_DO_411(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_413(MACRO, ...) \
+MACRO(413, __VA_ARGS__) \
+MU_DO_412(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_414(MACRO, ...) \
+MACRO(414, __VA_ARGS__) \
+MU_DO_413(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_415(MACRO, ...) \
+MACRO(415, __VA_ARGS__) \
+MU_DO_414(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_416(MACRO, ...) \
+MACRO(416, __VA_ARGS__) \
+MU_DO_415(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_417(MACRO, ...) \
+MACRO(417, __VA_ARGS__) \
+MU_DO_416(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_418(MACRO, ...) \
+MACRO(418, __VA_ARGS__) \
+MU_DO_417(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_419(MACRO, ...) \
+MACRO(419, __VA_ARGS__) \
+MU_DO_418(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_420(MACRO, ...) \
+MACRO(420, __VA_ARGS__) \
+MU_DO_419(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_421(MACRO, ...) \
+MACRO(421, __VA_ARGS__) \
+MU_DO_420(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_422(MACRO, ...) \
+MACRO(422, __VA_ARGS__) \
+MU_DO_421(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_423(MACRO, ...) \
+MACRO(423, __VA_ARGS__) \
+MU_DO_422(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_424(MACRO, ...) \
+MACRO(424, __VA_ARGS__) \
+MU_DO_423(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_425(MACRO, ...) \
+MACRO(425, __VA_ARGS__) \
+MU_DO_424(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_426(MACRO, ...) \
+MACRO(426, __VA_ARGS__) \
+MU_DO_425(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_427(MACRO, ...) \
+MACRO(427, __VA_ARGS__) \
+MU_DO_426(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_428(MACRO, ...) \
+MACRO(428, __VA_ARGS__) \
+MU_DO_427(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_429(MACRO, ...) \
+MACRO(429, __VA_ARGS__) \
+MU_DO_428(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_430(MACRO, ...) \
+MACRO(430, __VA_ARGS__) \
+MU_DO_429(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_431(MACRO, ...) \
+MACRO(431, __VA_ARGS__) \
+MU_DO_430(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_432(MACRO, ...) \
+MACRO(432, __VA_ARGS__) \
+MU_DO_431(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_433(MACRO, ...) \
+MACRO(433, __VA_ARGS__) \
+MU_DO_432(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_434(MACRO, ...) \
+MACRO(434, __VA_ARGS__) \
+MU_DO_433(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_435(MACRO, ...) \
+MACRO(435, __VA_ARGS__) \
+MU_DO_434(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_436(MACRO, ...) \
+MACRO(436, __VA_ARGS__) \
+MU_DO_435(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_437(MACRO, ...) \
+MACRO(437, __VA_ARGS__) \
+MU_DO_436(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_438(MACRO, ...) \
+MACRO(438, __VA_ARGS__) \
+MU_DO_437(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_439(MACRO, ...) \
+MACRO(439, __VA_ARGS__) \
+MU_DO_438(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_440(MACRO, ...) \
+MACRO(440, __VA_ARGS__) \
+MU_DO_439(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_441(MACRO, ...) \
+MACRO(441, __VA_ARGS__) \
+MU_DO_440(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_442(MACRO, ...) \
+MACRO(442, __VA_ARGS__) \
+MU_DO_441(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_443(MACRO, ...) \
+MACRO(443, __VA_ARGS__) \
+MU_DO_442(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_444(MACRO, ...) \
+MACRO(444, __VA_ARGS__) \
+MU_DO_443(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_445(MACRO, ...) \
+MACRO(445, __VA_ARGS__) \
+MU_DO_444(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_446(MACRO, ...) \
+MACRO(446, __VA_ARGS__) \
+MU_DO_445(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_447(MACRO, ...) \
+MACRO(447, __VA_ARGS__) \
+MU_DO_446(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_448(MACRO, ...) \
+MACRO(448, __VA_ARGS__) \
+MU_DO_447(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_449(MACRO, ...) \
+MACRO(449, __VA_ARGS__) \
+MU_DO_448(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_450(MACRO, ...) \
+MACRO(450, __VA_ARGS__) \
+MU_DO_449(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_451(MACRO, ...) \
+MACRO(451, __VA_ARGS__) \
+MU_DO_450(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_452(MACRO, ...) \
+MACRO(452, __VA_ARGS__) \
+MU_DO_451(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_453(MACRO, ...) \
+MACRO(453, __VA_ARGS__) \
+MU_DO_452(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_454(MACRO, ...) \
+MACRO(454, __VA_ARGS__) \
+MU_DO_453(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_455(MACRO, ...) \
+MACRO(455, __VA_ARGS__) \
+MU_DO_454(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_456(MACRO, ...) \
+MACRO(456, __VA_ARGS__) \
+MU_DO_455(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_457(MACRO, ...) \
+MACRO(457, __VA_ARGS__) \
+MU_DO_456(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_458(MACRO, ...) \
+MACRO(458, __VA_ARGS__) \
+MU_DO_457(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_459(MACRO, ...) \
+MACRO(459, __VA_ARGS__) \
+MU_DO_458(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_460(MACRO, ...) \
+MACRO(460, __VA_ARGS__) \
+MU_DO_459(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_461(MACRO, ...) \
+MACRO(461, __VA_ARGS__) \
+MU_DO_460(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_462(MACRO, ...) \
+MACRO(462, __VA_ARGS__) \
+MU_DO_461(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_463(MACRO, ...) \
+MACRO(463, __VA_ARGS__) \
+MU_DO_462(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_464(MACRO, ...) \
+MACRO(464, __VA_ARGS__) \
+MU_DO_463(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_465(MACRO, ...) \
+MACRO(465, __VA_ARGS__) \
+MU_DO_464(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_466(MACRO, ...) \
+MACRO(466, __VA_ARGS__) \
+MU_DO_465(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_467(MACRO, ...) \
+MACRO(467, __VA_ARGS__) \
+MU_DO_466(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_468(MACRO, ...) \
+MACRO(468, __VA_ARGS__) \
+MU_DO_467(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_469(MACRO, ...) \
+MACRO(469, __VA_ARGS__) \
+MU_DO_468(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_470(MACRO, ...) \
+MACRO(470, __VA_ARGS__) \
+MU_DO_469(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_471(MACRO, ...) \
+MACRO(471, __VA_ARGS__) \
+MU_DO_470(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_472(MACRO, ...) \
+MACRO(472, __VA_ARGS__) \
+MU_DO_471(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_473(MACRO, ...) \
+MACRO(473, __VA_ARGS__) \
+MU_DO_472(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_474(MACRO, ...) \
+MACRO(474, __VA_ARGS__) \
+MU_DO_473(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_475(MACRO, ...) \
+MACRO(475, __VA_ARGS__) \
+MU_DO_474(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_476(MACRO, ...) \
+MACRO(476, __VA_ARGS__) \
+MU_DO_475(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_477(MACRO, ...) \
+MACRO(477, __VA_ARGS__) \
+MU_DO_476(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_478(MACRO, ...) \
+MACRO(478, __VA_ARGS__) \
+MU_DO_477(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_479(MACRO, ...) \
+MACRO(479, __VA_ARGS__) \
+MU_DO_478(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_480(MACRO, ...) \
+MACRO(480, __VA_ARGS__) \
+MU_DO_479(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_481(MACRO, ...) \
+MACRO(481, __VA_ARGS__) \
+MU_DO_480(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_482(MACRO, ...) \
+MACRO(482, __VA_ARGS__) \
+MU_DO_481(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_483(MACRO, ...) \
+MACRO(483, __VA_ARGS__) \
+MU_DO_482(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_484(MACRO, ...) \
+MACRO(484, __VA_ARGS__) \
+MU_DO_483(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_485(MACRO, ...) \
+MACRO(485, __VA_ARGS__) \
+MU_DO_484(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_486(MACRO, ...) \
+MACRO(486, __VA_ARGS__) \
+MU_DO_485(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_487(MACRO, ...) \
+MACRO(487, __VA_ARGS__) \
+MU_DO_486(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_488(MACRO, ...) \
+MACRO(488, __VA_ARGS__) \
+MU_DO_487(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_489(MACRO, ...) \
+MACRO(489, __VA_ARGS__) \
+MU_DO_488(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_490(MACRO, ...) \
+MACRO(490, __VA_ARGS__) \
+MU_DO_489(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_491(MACRO, ...) \
+MACRO(491, __VA_ARGS__) \
+MU_DO_490(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_492(MACRO, ...) \
+MACRO(492, __VA_ARGS__) \
+MU_DO_491(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_493(MACRO, ...) \
+MACRO(493, __VA_ARGS__) \
+MU_DO_492(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_494(MACRO, ...) \
+MACRO(494, __VA_ARGS__) \
+MU_DO_493(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_495(MACRO, ...) \
+MACRO(495, __VA_ARGS__) \
+MU_DO_494(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_496(MACRO, ...) \
+MACRO(496, __VA_ARGS__) \
+MU_DO_495(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_497(MACRO, ...) \
+MACRO(497, __VA_ARGS__) \
+MU_DO_496(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_498(MACRO, ...) \
+MACRO(498, __VA_ARGS__) \
+MU_DO_497(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_499(MACRO, ...) \
+MACRO(499, __VA_ARGS__) \
+MU_DO_498(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_500(MACRO, ...) \
+MACRO(500, __VA_ARGS__) \
+MU_DO_499(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_501(MACRO, ...) \
+MACRO(501, __VA_ARGS__) \
+MU_DO_500(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_502(MACRO, ...) \
+MACRO(502, __VA_ARGS__) \
+MU_DO_501(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_503(MACRO, ...) \
+MACRO(503, __VA_ARGS__) \
+MU_DO_502(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_504(MACRO, ...) \
+MACRO(504, __VA_ARGS__) \
+MU_DO_503(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_505(MACRO, ...) \
+MACRO(505, __VA_ARGS__) \
+MU_DO_504(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_506(MACRO, ...) \
+MACRO(506, __VA_ARGS__) \
+MU_DO_505(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_507(MACRO, ...) \
+MACRO(507, __VA_ARGS__) \
+MU_DO_506(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_508(MACRO, ...) \
+MACRO(508, __VA_ARGS__) \
+MU_DO_507(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_509(MACRO, ...) \
+MACRO(509, __VA_ARGS__) \
+MU_DO_508(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_510(MACRO, ...) \
+MACRO(510, __VA_ARGS__) \
+MU_DO_509(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_511(MACRO, ...) \
+MACRO(511, __VA_ARGS__) \
+MU_DO_510(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_512(MACRO, ...) \
+MACRO(512, __VA_ARGS__) \
+MU_DO_511(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_513(MACRO, ...) \
+MACRO(513, __VA_ARGS__) \
+MU_DO_512(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_514(MACRO, ...) \
+MACRO(514, __VA_ARGS__) \
+MU_DO_513(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_515(MACRO, ...) \
+MACRO(515, __VA_ARGS__) \
+MU_DO_514(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_516(MACRO, ...) \
+MACRO(516, __VA_ARGS__) \
+MU_DO_515(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_517(MACRO, ...) \
+MACRO(517, __VA_ARGS__) \
+MU_DO_516(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_518(MACRO, ...) \
+MACRO(518, __VA_ARGS__) \
+MU_DO_517(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_519(MACRO, ...) \
+MACRO(519, __VA_ARGS__) \
+MU_DO_518(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_520(MACRO, ...) \
+MACRO(520, __VA_ARGS__) \
+MU_DO_519(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_521(MACRO, ...) \
+MACRO(521, __VA_ARGS__) \
+MU_DO_520(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_522(MACRO, ...) \
+MACRO(522, __VA_ARGS__) \
+MU_DO_521(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_523(MACRO, ...) \
+MACRO(523, __VA_ARGS__) \
+MU_DO_522(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_524(MACRO, ...) \
+MACRO(524, __VA_ARGS__) \
+MU_DO_523(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_525(MACRO, ...) \
+MACRO(525, __VA_ARGS__) \
+MU_DO_524(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_526(MACRO, ...) \
+MACRO(526, __VA_ARGS__) \
+MU_DO_525(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_527(MACRO, ...) \
+MACRO(527, __VA_ARGS__) \
+MU_DO_526(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_528(MACRO, ...) \
+MACRO(528, __VA_ARGS__) \
+MU_DO_527(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_529(MACRO, ...) \
+MACRO(529, __VA_ARGS__) \
+MU_DO_528(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_530(MACRO, ...) \
+MACRO(530, __VA_ARGS__) \
+MU_DO_529(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_531(MACRO, ...) \
+MACRO(531, __VA_ARGS__) \
+MU_DO_530(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_532(MACRO, ...) \
+MACRO(532, __VA_ARGS__) \
+MU_DO_531(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_533(MACRO, ...) \
+MACRO(533, __VA_ARGS__) \
+MU_DO_532(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_534(MACRO, ...) \
+MACRO(534, __VA_ARGS__) \
+MU_DO_533(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_535(MACRO, ...) \
+MACRO(535, __VA_ARGS__) \
+MU_DO_534(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_536(MACRO, ...) \
+MACRO(536, __VA_ARGS__) \
+MU_DO_535(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_537(MACRO, ...) \
+MACRO(537, __VA_ARGS__) \
+MU_DO_536(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_538(MACRO, ...) \
+MACRO(538, __VA_ARGS__) \
+MU_DO_537(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_539(MACRO, ...) \
+MACRO(539, __VA_ARGS__) \
+MU_DO_538(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_540(MACRO, ...) \
+MACRO(540, __VA_ARGS__) \
+MU_DO_539(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_541(MACRO, ...) \
+MACRO(541, __VA_ARGS__) \
+MU_DO_540(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_542(MACRO, ...) \
+MACRO(542, __VA_ARGS__) \
+MU_DO_541(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_543(MACRO, ...) \
+MACRO(543, __VA_ARGS__) \
+MU_DO_542(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_544(MACRO, ...) \
+MACRO(544, __VA_ARGS__) \
+MU_DO_543(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_545(MACRO, ...) \
+MACRO(545, __VA_ARGS__) \
+MU_DO_544(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_546(MACRO, ...) \
+MACRO(546, __VA_ARGS__) \
+MU_DO_545(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_547(MACRO, ...) \
+MACRO(547, __VA_ARGS__) \
+MU_DO_546(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_548(MACRO, ...) \
+MACRO(548, __VA_ARGS__) \
+MU_DO_547(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_549(MACRO, ...) \
+MACRO(549, __VA_ARGS__) \
+MU_DO_548(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_550(MACRO, ...) \
+MACRO(550, __VA_ARGS__) \
+MU_DO_549(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_551(MACRO, ...) \
+MACRO(551, __VA_ARGS__) \
+MU_DO_550(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_552(MACRO, ...) \
+MACRO(552, __VA_ARGS__) \
+MU_DO_551(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_553(MACRO, ...) \
+MACRO(553, __VA_ARGS__) \
+MU_DO_552(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_554(MACRO, ...) \
+MACRO(554, __VA_ARGS__) \
+MU_DO_553(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_555(MACRO, ...) \
+MACRO(555, __VA_ARGS__) \
+MU_DO_554(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_556(MACRO, ...) \
+MACRO(556, __VA_ARGS__) \
+MU_DO_555(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_557(MACRO, ...) \
+MACRO(557, __VA_ARGS__) \
+MU_DO_556(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_558(MACRO, ...) \
+MACRO(558, __VA_ARGS__) \
+MU_DO_557(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_559(MACRO, ...) \
+MACRO(559, __VA_ARGS__) \
+MU_DO_558(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_560(MACRO, ...) \
+MACRO(560, __VA_ARGS__) \
+MU_DO_559(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_561(MACRO, ...) \
+MACRO(561, __VA_ARGS__) \
+MU_DO_560(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_562(MACRO, ...) \
+MACRO(562, __VA_ARGS__) \
+MU_DO_561(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_563(MACRO, ...) \
+MACRO(563, __VA_ARGS__) \
+MU_DO_562(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_564(MACRO, ...) \
+MACRO(564, __VA_ARGS__) \
+MU_DO_563(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_565(MACRO, ...) \
+MACRO(565, __VA_ARGS__) \
+MU_DO_564(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_566(MACRO, ...) \
+MACRO(566, __VA_ARGS__) \
+MU_DO_565(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_567(MACRO, ...) \
+MACRO(567, __VA_ARGS__) \
+MU_DO_566(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_568(MACRO, ...) \
+MACRO(568, __VA_ARGS__) \
+MU_DO_567(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_569(MACRO, ...) \
+MACRO(569, __VA_ARGS__) \
+MU_DO_568(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_570(MACRO, ...) \
+MACRO(570, __VA_ARGS__) \
+MU_DO_569(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_571(MACRO, ...) \
+MACRO(571, __VA_ARGS__) \
+MU_DO_570(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_572(MACRO, ...) \
+MACRO(572, __VA_ARGS__) \
+MU_DO_571(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_573(MACRO, ...) \
+MACRO(573, __VA_ARGS__) \
+MU_DO_572(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_574(MACRO, ...) \
+MACRO(574, __VA_ARGS__) \
+MU_DO_573(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_575(MACRO, ...) \
+MACRO(575, __VA_ARGS__) \
+MU_DO_574(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_576(MACRO, ...) \
+MACRO(576, __VA_ARGS__) \
+MU_DO_575(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_577(MACRO, ...) \
+MACRO(577, __VA_ARGS__) \
+MU_DO_576(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_578(MACRO, ...) \
+MACRO(578, __VA_ARGS__) \
+MU_DO_577(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_579(MACRO, ...) \
+MACRO(579, __VA_ARGS__) \
+MU_DO_578(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_580(MACRO, ...) \
+MACRO(580, __VA_ARGS__) \
+MU_DO_579(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_581(MACRO, ...) \
+MACRO(581, __VA_ARGS__) \
+MU_DO_580(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_582(MACRO, ...) \
+MACRO(582, __VA_ARGS__) \
+MU_DO_581(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_583(MACRO, ...) \
+MACRO(583, __VA_ARGS__) \
+MU_DO_582(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_584(MACRO, ...) \
+MACRO(584, __VA_ARGS__) \
+MU_DO_583(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_585(MACRO, ...) \
+MACRO(585, __VA_ARGS__) \
+MU_DO_584(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_586(MACRO, ...) \
+MACRO(586, __VA_ARGS__) \
+MU_DO_585(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_587(MACRO, ...) \
+MACRO(587, __VA_ARGS__) \
+MU_DO_586(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_588(MACRO, ...) \
+MACRO(588, __VA_ARGS__) \
+MU_DO_587(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_589(MACRO, ...) \
+MACRO(589, __VA_ARGS__) \
+MU_DO_588(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_590(MACRO, ...) \
+MACRO(590, __VA_ARGS__) \
+MU_DO_589(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_591(MACRO, ...) \
+MACRO(591, __VA_ARGS__) \
+MU_DO_590(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_592(MACRO, ...) \
+MACRO(592, __VA_ARGS__) \
+MU_DO_591(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_593(MACRO, ...) \
+MACRO(593, __VA_ARGS__) \
+MU_DO_592(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_594(MACRO, ...) \
+MACRO(594, __VA_ARGS__) \
+MU_DO_593(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_595(MACRO, ...) \
+MACRO(595, __VA_ARGS__) \
+MU_DO_594(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_596(MACRO, ...) \
+MACRO(596, __VA_ARGS__) \
+MU_DO_595(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_597(MACRO, ...) \
+MACRO(597, __VA_ARGS__) \
+MU_DO_596(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_598(MACRO, ...) \
+MACRO(598, __VA_ARGS__) \
+MU_DO_597(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_599(MACRO, ...) \
+MACRO(599, __VA_ARGS__) \
+MU_DO_598(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_600(MACRO, ...) \
+MACRO(600, __VA_ARGS__) \
+MU_DO_599(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_601(MACRO, ...) \
+MACRO(601, __VA_ARGS__) \
+MU_DO_600(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_602(MACRO, ...) \
+MACRO(602, __VA_ARGS__) \
+MU_DO_601(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_603(MACRO, ...) \
+MACRO(603, __VA_ARGS__) \
+MU_DO_602(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_604(MACRO, ...) \
+MACRO(604, __VA_ARGS__) \
+MU_DO_603(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_605(MACRO, ...) \
+MACRO(605, __VA_ARGS__) \
+MU_DO_604(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_606(MACRO, ...) \
+MACRO(606, __VA_ARGS__) \
+MU_DO_605(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_607(MACRO, ...) \
+MACRO(607, __VA_ARGS__) \
+MU_DO_606(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_608(MACRO, ...) \
+MACRO(608, __VA_ARGS__) \
+MU_DO_607(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_609(MACRO, ...) \
+MACRO(609, __VA_ARGS__) \
+MU_DO_608(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_610(MACRO, ...) \
+MACRO(610, __VA_ARGS__) \
+MU_DO_609(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_611(MACRO, ...) \
+MACRO(611, __VA_ARGS__) \
+MU_DO_610(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_612(MACRO, ...) \
+MACRO(612, __VA_ARGS__) \
+MU_DO_611(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_613(MACRO, ...) \
+MACRO(613, __VA_ARGS__) \
+MU_DO_612(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_614(MACRO, ...) \
+MACRO(614, __VA_ARGS__) \
+MU_DO_613(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_615(MACRO, ...) \
+MACRO(615, __VA_ARGS__) \
+MU_DO_614(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_616(MACRO, ...) \
+MACRO(616, __VA_ARGS__) \
+MU_DO_615(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_617(MACRO, ...) \
+MACRO(617, __VA_ARGS__) \
+MU_DO_616(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_618(MACRO, ...) \
+MACRO(618, __VA_ARGS__) \
+MU_DO_617(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_619(MACRO, ...) \
+MACRO(619, __VA_ARGS__) \
+MU_DO_618(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_620(MACRO, ...) \
+MACRO(620, __VA_ARGS__) \
+MU_DO_619(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_621(MACRO, ...) \
+MACRO(621, __VA_ARGS__) \
+MU_DO_620(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_622(MACRO, ...) \
+MACRO(622, __VA_ARGS__) \
+MU_DO_621(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_623(MACRO, ...) \
+MACRO(623, __VA_ARGS__) \
+MU_DO_622(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_624(MACRO, ...) \
+MACRO(624, __VA_ARGS__) \
+MU_DO_623(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_625(MACRO, ...) \
+MACRO(625, __VA_ARGS__) \
+MU_DO_624(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_626(MACRO, ...) \
+MACRO(626, __VA_ARGS__) \
+MU_DO_625(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_627(MACRO, ...) \
+MACRO(627, __VA_ARGS__) \
+MU_DO_626(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_628(MACRO, ...) \
+MACRO(628, __VA_ARGS__) \
+MU_DO_627(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_629(MACRO, ...) \
+MACRO(629, __VA_ARGS__) \
+MU_DO_628(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_630(MACRO, ...) \
+MACRO(630, __VA_ARGS__) \
+MU_DO_629(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_631(MACRO, ...) \
+MACRO(631, __VA_ARGS__) \
+MU_DO_630(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_632(MACRO, ...) \
+MACRO(632, __VA_ARGS__) \
+MU_DO_631(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_633(MACRO, ...) \
+MACRO(633, __VA_ARGS__) \
+MU_DO_632(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_634(MACRO, ...) \
+MACRO(634, __VA_ARGS__) \
+MU_DO_633(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_635(MACRO, ...) \
+MACRO(635, __VA_ARGS__) \
+MU_DO_634(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_636(MACRO, ...) \
+MACRO(636, __VA_ARGS__) \
+MU_DO_635(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_637(MACRO, ...) \
+MACRO(637, __VA_ARGS__) \
+MU_DO_636(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_638(MACRO, ...) \
+MACRO(638, __VA_ARGS__) \
+MU_DO_637(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_639(MACRO, ...) \
+MACRO(639, __VA_ARGS__) \
+MU_DO_638(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_640(MACRO, ...) \
+MACRO(640, __VA_ARGS__) \
+MU_DO_639(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_641(MACRO, ...) \
+MACRO(641, __VA_ARGS__) \
+MU_DO_640(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_642(MACRO, ...) \
+MACRO(642, __VA_ARGS__) \
+MU_DO_641(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_643(MACRO, ...) \
+MACRO(643, __VA_ARGS__) \
+MU_DO_642(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_644(MACRO, ...) \
+MACRO(644, __VA_ARGS__) \
+MU_DO_643(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_645(MACRO, ...) \
+MACRO(645, __VA_ARGS__) \
+MU_DO_644(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_646(MACRO, ...) \
+MACRO(646, __VA_ARGS__) \
+MU_DO_645(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_647(MACRO, ...) \
+MACRO(647, __VA_ARGS__) \
+MU_DO_646(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_648(MACRO, ...) \
+MACRO(648, __VA_ARGS__) \
+MU_DO_647(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_649(MACRO, ...) \
+MACRO(649, __VA_ARGS__) \
+MU_DO_648(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_650(MACRO, ...) \
+MACRO(650, __VA_ARGS__) \
+MU_DO_649(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_651(MACRO, ...) \
+MACRO(651, __VA_ARGS__) \
+MU_DO_650(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_652(MACRO, ...) \
+MACRO(652, __VA_ARGS__) \
+MU_DO_651(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_653(MACRO, ...) \
+MACRO(653, __VA_ARGS__) \
+MU_DO_652(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_654(MACRO, ...) \
+MACRO(654, __VA_ARGS__) \
+MU_DO_653(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_655(MACRO, ...) \
+MACRO(655, __VA_ARGS__) \
+MU_DO_654(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_656(MACRO, ...) \
+MACRO(656, __VA_ARGS__) \
+MU_DO_655(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_657(MACRO, ...) \
+MACRO(657, __VA_ARGS__) \
+MU_DO_656(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_658(MACRO, ...) \
+MACRO(658, __VA_ARGS__) \
+MU_DO_657(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_659(MACRO, ...) \
+MACRO(659, __VA_ARGS__) \
+MU_DO_658(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_660(MACRO, ...) \
+MACRO(660, __VA_ARGS__) \
+MU_DO_659(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_661(MACRO, ...) \
+MACRO(661, __VA_ARGS__) \
+MU_DO_660(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_662(MACRO, ...) \
+MACRO(662, __VA_ARGS__) \
+MU_DO_661(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_663(MACRO, ...) \
+MACRO(663, __VA_ARGS__) \
+MU_DO_662(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_664(MACRO, ...) \
+MACRO(664, __VA_ARGS__) \
+MU_DO_663(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_665(MACRO, ...) \
+MACRO(665, __VA_ARGS__) \
+MU_DO_664(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_666(MACRO, ...) \
+MACRO(666, __VA_ARGS__) \
+MU_DO_665(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_667(MACRO, ...) \
+MACRO(667, __VA_ARGS__) \
+MU_DO_666(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_668(MACRO, ...) \
+MACRO(668, __VA_ARGS__) \
+MU_DO_667(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_669(MACRO, ...) \
+MACRO(669, __VA_ARGS__) \
+MU_DO_668(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_670(MACRO, ...) \
+MACRO(670, __VA_ARGS__) \
+MU_DO_669(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_671(MACRO, ...) \
+MACRO(671, __VA_ARGS__) \
+MU_DO_670(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_672(MACRO, ...) \
+MACRO(672, __VA_ARGS__) \
+MU_DO_671(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_673(MACRO, ...) \
+MACRO(673, __VA_ARGS__) \
+MU_DO_672(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_674(MACRO, ...) \
+MACRO(674, __VA_ARGS__) \
+MU_DO_673(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_675(MACRO, ...) \
+MACRO(675, __VA_ARGS__) \
+MU_DO_674(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_676(MACRO, ...) \
+MACRO(676, __VA_ARGS__) \
+MU_DO_675(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_677(MACRO, ...) \
+MACRO(677, __VA_ARGS__) \
+MU_DO_676(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_678(MACRO, ...) \
+MACRO(678, __VA_ARGS__) \
+MU_DO_677(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_679(MACRO, ...) \
+MACRO(679, __VA_ARGS__) \
+MU_DO_678(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_680(MACRO, ...) \
+MACRO(680, __VA_ARGS__) \
+MU_DO_679(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_681(MACRO, ...) \
+MACRO(681, __VA_ARGS__) \
+MU_DO_680(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_682(MACRO, ...) \
+MACRO(682, __VA_ARGS__) \
+MU_DO_681(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_683(MACRO, ...) \
+MACRO(683, __VA_ARGS__) \
+MU_DO_682(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_684(MACRO, ...) \
+MACRO(684, __VA_ARGS__) \
+MU_DO_683(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_685(MACRO, ...) \
+MACRO(685, __VA_ARGS__) \
+MU_DO_684(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_686(MACRO, ...) \
+MACRO(686, __VA_ARGS__) \
+MU_DO_685(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_687(MACRO, ...) \
+MACRO(687, __VA_ARGS__) \
+MU_DO_686(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_688(MACRO, ...) \
+MACRO(688, __VA_ARGS__) \
+MU_DO_687(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_689(MACRO, ...) \
+MACRO(689, __VA_ARGS__) \
+MU_DO_688(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_690(MACRO, ...) \
+MACRO(690, __VA_ARGS__) \
+MU_DO_689(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_691(MACRO, ...) \
+MACRO(691, __VA_ARGS__) \
+MU_DO_690(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_692(MACRO, ...) \
+MACRO(692, __VA_ARGS__) \
+MU_DO_691(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_693(MACRO, ...) \
+MACRO(693, __VA_ARGS__) \
+MU_DO_692(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_694(MACRO, ...) \
+MACRO(694, __VA_ARGS__) \
+MU_DO_693(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_695(MACRO, ...) \
+MACRO(695, __VA_ARGS__) \
+MU_DO_694(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_696(MACRO, ...) \
+MACRO(696, __VA_ARGS__) \
+MU_DO_695(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_697(MACRO, ...) \
+MACRO(697, __VA_ARGS__) \
+MU_DO_696(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_698(MACRO, ...) \
+MACRO(698, __VA_ARGS__) \
+MU_DO_697(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_699(MACRO, ...) \
+MACRO(699, __VA_ARGS__) \
+MU_DO_698(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_700(MACRO, ...) \
+MACRO(700, __VA_ARGS__) \
+MU_DO_699(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_701(MACRO, ...) \
+MACRO(701, __VA_ARGS__) \
+MU_DO_700(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_702(MACRO, ...) \
+MACRO(702, __VA_ARGS__) \
+MU_DO_701(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_703(MACRO, ...) \
+MACRO(703, __VA_ARGS__) \
+MU_DO_702(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_704(MACRO, ...) \
+MACRO(704, __VA_ARGS__) \
+MU_DO_703(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_705(MACRO, ...) \
+MACRO(705, __VA_ARGS__) \
+MU_DO_704(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_706(MACRO, ...) \
+MACRO(706, __VA_ARGS__) \
+MU_DO_705(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_707(MACRO, ...) \
+MACRO(707, __VA_ARGS__) \
+MU_DO_706(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_708(MACRO, ...) \
+MACRO(708, __VA_ARGS__) \
+MU_DO_707(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_709(MACRO, ...) \
+MACRO(709, __VA_ARGS__) \
+MU_DO_708(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_710(MACRO, ...) \
+MACRO(710, __VA_ARGS__) \
+MU_DO_709(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_711(MACRO, ...) \
+MACRO(711, __VA_ARGS__) \
+MU_DO_710(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_712(MACRO, ...) \
+MACRO(712, __VA_ARGS__) \
+MU_DO_711(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_713(MACRO, ...) \
+MACRO(713, __VA_ARGS__) \
+MU_DO_712(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_714(MACRO, ...) \
+MACRO(714, __VA_ARGS__) \
+MU_DO_713(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_715(MACRO, ...) \
+MACRO(715, __VA_ARGS__) \
+MU_DO_714(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_716(MACRO, ...) \
+MACRO(716, __VA_ARGS__) \
+MU_DO_715(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_717(MACRO, ...) \
+MACRO(717, __VA_ARGS__) \
+MU_DO_716(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_718(MACRO, ...) \
+MACRO(718, __VA_ARGS__) \
+MU_DO_717(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_719(MACRO, ...) \
+MACRO(719, __VA_ARGS__) \
+MU_DO_718(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_720(MACRO, ...) \
+MACRO(720, __VA_ARGS__) \
+MU_DO_719(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_721(MACRO, ...) \
+MACRO(721, __VA_ARGS__) \
+MU_DO_720(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_722(MACRO, ...) \
+MACRO(722, __VA_ARGS__) \
+MU_DO_721(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_723(MACRO, ...) \
+MACRO(723, __VA_ARGS__) \
+MU_DO_722(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_724(MACRO, ...) \
+MACRO(724, __VA_ARGS__) \
+MU_DO_723(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_725(MACRO, ...) \
+MACRO(725, __VA_ARGS__) \
+MU_DO_724(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_726(MACRO, ...) \
+MACRO(726, __VA_ARGS__) \
+MU_DO_725(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_727(MACRO, ...) \
+MACRO(727, __VA_ARGS__) \
+MU_DO_726(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_728(MACRO, ...) \
+MACRO(728, __VA_ARGS__) \
+MU_DO_727(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_729(MACRO, ...) \
+MACRO(729, __VA_ARGS__) \
+MU_DO_728(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_730(MACRO, ...) \
+MACRO(730, __VA_ARGS__) \
+MU_DO_729(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_731(MACRO, ...) \
+MACRO(731, __VA_ARGS__) \
+MU_DO_730(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_732(MACRO, ...) \
+MACRO(732, __VA_ARGS__) \
+MU_DO_731(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_733(MACRO, ...) \
+MACRO(733, __VA_ARGS__) \
+MU_DO_732(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_734(MACRO, ...) \
+MACRO(734, __VA_ARGS__) \
+MU_DO_733(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_735(MACRO, ...) \
+MACRO(735, __VA_ARGS__) \
+MU_DO_734(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_736(MACRO, ...) \
+MACRO(736, __VA_ARGS__) \
+MU_DO_735(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_737(MACRO, ...) \
+MACRO(737, __VA_ARGS__) \
+MU_DO_736(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_738(MACRO, ...) \
+MACRO(738, __VA_ARGS__) \
+MU_DO_737(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_739(MACRO, ...) \
+MACRO(739, __VA_ARGS__) \
+MU_DO_738(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_740(MACRO, ...) \
+MACRO(740, __VA_ARGS__) \
+MU_DO_739(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_741(MACRO, ...) \
+MACRO(741, __VA_ARGS__) \
+MU_DO_740(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_742(MACRO, ...) \
+MACRO(742, __VA_ARGS__) \
+MU_DO_741(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_743(MACRO, ...) \
+MACRO(743, __VA_ARGS__) \
+MU_DO_742(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_744(MACRO, ...) \
+MACRO(744, __VA_ARGS__) \
+MU_DO_743(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_745(MACRO, ...) \
+MACRO(745, __VA_ARGS__) \
+MU_DO_744(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_746(MACRO, ...) \
+MACRO(746, __VA_ARGS__) \
+MU_DO_745(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_747(MACRO, ...) \
+MACRO(747, __VA_ARGS__) \
+MU_DO_746(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_748(MACRO, ...) \
+MACRO(748, __VA_ARGS__) \
+MU_DO_747(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_749(MACRO, ...) \
+MACRO(749, __VA_ARGS__) \
+MU_DO_748(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_750(MACRO, ...) \
+MACRO(750, __VA_ARGS__) \
+MU_DO_749(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_751(MACRO, ...) \
+MACRO(751, __VA_ARGS__) \
+MU_DO_750(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_752(MACRO, ...) \
+MACRO(752, __VA_ARGS__) \
+MU_DO_751(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_753(MACRO, ...) \
+MACRO(753, __VA_ARGS__) \
+MU_DO_752(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_754(MACRO, ...) \
+MACRO(754, __VA_ARGS__) \
+MU_DO_753(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_755(MACRO, ...) \
+MACRO(755, __VA_ARGS__) \
+MU_DO_754(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_756(MACRO, ...) \
+MACRO(756, __VA_ARGS__) \
+MU_DO_755(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_757(MACRO, ...) \
+MACRO(757, __VA_ARGS__) \
+MU_DO_756(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_758(MACRO, ...) \
+MACRO(758, __VA_ARGS__) \
+MU_DO_757(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_759(MACRO, ...) \
+MACRO(759, __VA_ARGS__) \
+MU_DO_758(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_760(MACRO, ...) \
+MACRO(760, __VA_ARGS__) \
+MU_DO_759(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_761(MACRO, ...) \
+MACRO(761, __VA_ARGS__) \
+MU_DO_760(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_762(MACRO, ...) \
+MACRO(762, __VA_ARGS__) \
+MU_DO_761(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_763(MACRO, ...) \
+MACRO(763, __VA_ARGS__) \
+MU_DO_762(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_764(MACRO, ...) \
+MACRO(764, __VA_ARGS__) \
+MU_DO_763(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_765(MACRO, ...) \
+MACRO(765, __VA_ARGS__) \
+MU_DO_764(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_766(MACRO, ...) \
+MACRO(766, __VA_ARGS__) \
+MU_DO_765(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_767(MACRO, ...) \
+MACRO(767, __VA_ARGS__) \
+MU_DO_766(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_768(MACRO, ...) \
+MACRO(768, __VA_ARGS__) \
+MU_DO_767(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_769(MACRO, ...) \
+MACRO(769, __VA_ARGS__) \
+MU_DO_768(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_770(MACRO, ...) \
+MACRO(770, __VA_ARGS__) \
+MU_DO_769(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_771(MACRO, ...) \
+MACRO(771, __VA_ARGS__) \
+MU_DO_770(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_772(MACRO, ...) \
+MACRO(772, __VA_ARGS__) \
+MU_DO_771(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_773(MACRO, ...) \
+MACRO(773, __VA_ARGS__) \
+MU_DO_772(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_774(MACRO, ...) \
+MACRO(774, __VA_ARGS__) \
+MU_DO_773(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_775(MACRO, ...) \
+MACRO(775, __VA_ARGS__) \
+MU_DO_774(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_776(MACRO, ...) \
+MACRO(776, __VA_ARGS__) \
+MU_DO_775(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_777(MACRO, ...) \
+MACRO(777, __VA_ARGS__) \
+MU_DO_776(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_778(MACRO, ...) \
+MACRO(778, __VA_ARGS__) \
+MU_DO_777(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_779(MACRO, ...) \
+MACRO(779, __VA_ARGS__) \
+MU_DO_778(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_780(MACRO, ...) \
+MACRO(780, __VA_ARGS__) \
+MU_DO_779(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_781(MACRO, ...) \
+MACRO(781, __VA_ARGS__) \
+MU_DO_780(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_782(MACRO, ...) \
+MACRO(782, __VA_ARGS__) \
+MU_DO_781(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_783(MACRO, ...) \
+MACRO(783, __VA_ARGS__) \
+MU_DO_782(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_784(MACRO, ...) \
+MACRO(784, __VA_ARGS__) \
+MU_DO_783(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_785(MACRO, ...) \
+MACRO(785, __VA_ARGS__) \
+MU_DO_784(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_786(MACRO, ...) \
+MACRO(786, __VA_ARGS__) \
+MU_DO_785(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_787(MACRO, ...) \
+MACRO(787, __VA_ARGS__) \
+MU_DO_786(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_788(MACRO, ...) \
+MACRO(788, __VA_ARGS__) \
+MU_DO_787(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_789(MACRO, ...) \
+MACRO(789, __VA_ARGS__) \
+MU_DO_788(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_790(MACRO, ...) \
+MACRO(790, __VA_ARGS__) \
+MU_DO_789(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_791(MACRO, ...) \
+MACRO(791, __VA_ARGS__) \
+MU_DO_790(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_792(MACRO, ...) \
+MACRO(792, __VA_ARGS__) \
+MU_DO_791(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_793(MACRO, ...) \
+MACRO(793, __VA_ARGS__) \
+MU_DO_792(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_794(MACRO, ...) \
+MACRO(794, __VA_ARGS__) \
+MU_DO_793(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_795(MACRO, ...) \
+MACRO(795, __VA_ARGS__) \
+MU_DO_794(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_796(MACRO, ...) \
+MACRO(796, __VA_ARGS__) \
+MU_DO_795(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_797(MACRO, ...) \
+MACRO(797, __VA_ARGS__) \
+MU_DO_796(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_798(MACRO, ...) \
+MACRO(798, __VA_ARGS__) \
+MU_DO_797(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_799(MACRO, ...) \
+MACRO(799, __VA_ARGS__) \
+MU_DO_798(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_800(MACRO, ...) \
+MACRO(800, __VA_ARGS__) \
+MU_DO_799(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_801(MACRO, ...) \
+MACRO(801, __VA_ARGS__) \
+MU_DO_800(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_802(MACRO, ...) \
+MACRO(802, __VA_ARGS__) \
+MU_DO_801(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_803(MACRO, ...) \
+MACRO(803, __VA_ARGS__) \
+MU_DO_802(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_804(MACRO, ...) \
+MACRO(804, __VA_ARGS__) \
+MU_DO_803(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_805(MACRO, ...) \
+MACRO(805, __VA_ARGS__) \
+MU_DO_804(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_806(MACRO, ...) \
+MACRO(806, __VA_ARGS__) \
+MU_DO_805(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_807(MACRO, ...) \
+MACRO(807, __VA_ARGS__) \
+MU_DO_806(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_808(MACRO, ...) \
+MACRO(808, __VA_ARGS__) \
+MU_DO_807(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_809(MACRO, ...) \
+MACRO(809, __VA_ARGS__) \
+MU_DO_808(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_810(MACRO, ...) \
+MACRO(810, __VA_ARGS__) \
+MU_DO_809(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_811(MACRO, ...) \
+MACRO(811, __VA_ARGS__) \
+MU_DO_810(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_812(MACRO, ...) \
+MACRO(812, __VA_ARGS__) \
+MU_DO_811(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_813(MACRO, ...) \
+MACRO(813, __VA_ARGS__) \
+MU_DO_812(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_814(MACRO, ...) \
+MACRO(814, __VA_ARGS__) \
+MU_DO_813(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_815(MACRO, ...) \
+MACRO(815, __VA_ARGS__) \
+MU_DO_814(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_816(MACRO, ...) \
+MACRO(816, __VA_ARGS__) \
+MU_DO_815(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_817(MACRO, ...) \
+MACRO(817, __VA_ARGS__) \
+MU_DO_816(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_818(MACRO, ...) \
+MACRO(818, __VA_ARGS__) \
+MU_DO_817(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_819(MACRO, ...) \
+MACRO(819, __VA_ARGS__) \
+MU_DO_818(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_820(MACRO, ...) \
+MACRO(820, __VA_ARGS__) \
+MU_DO_819(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_821(MACRO, ...) \
+MACRO(821, __VA_ARGS__) \
+MU_DO_820(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_822(MACRO, ...) \
+MACRO(822, __VA_ARGS__) \
+MU_DO_821(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_823(MACRO, ...) \
+MACRO(823, __VA_ARGS__) \
+MU_DO_822(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_824(MACRO, ...) \
+MACRO(824, __VA_ARGS__) \
+MU_DO_823(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_825(MACRO, ...) \
+MACRO(825, __VA_ARGS__) \
+MU_DO_824(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_826(MACRO, ...) \
+MACRO(826, __VA_ARGS__) \
+MU_DO_825(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_827(MACRO, ...) \
+MACRO(827, __VA_ARGS__) \
+MU_DO_826(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_828(MACRO, ...) \
+MACRO(828, __VA_ARGS__) \
+MU_DO_827(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_829(MACRO, ...) \
+MACRO(829, __VA_ARGS__) \
+MU_DO_828(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_830(MACRO, ...) \
+MACRO(830, __VA_ARGS__) \
+MU_DO_829(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_831(MACRO, ...) \
+MACRO(831, __VA_ARGS__) \
+MU_DO_830(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_832(MACRO, ...) \
+MACRO(832, __VA_ARGS__) \
+MU_DO_831(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_833(MACRO, ...) \
+MACRO(833, __VA_ARGS__) \
+MU_DO_832(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_834(MACRO, ...) \
+MACRO(834, __VA_ARGS__) \
+MU_DO_833(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_835(MACRO, ...) \
+MACRO(835, __VA_ARGS__) \
+MU_DO_834(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_836(MACRO, ...) \
+MACRO(836, __VA_ARGS__) \
+MU_DO_835(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_837(MACRO, ...) \
+MACRO(837, __VA_ARGS__) \
+MU_DO_836(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_838(MACRO, ...) \
+MACRO(838, __VA_ARGS__) \
+MU_DO_837(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_839(MACRO, ...) \
+MACRO(839, __VA_ARGS__) \
+MU_DO_838(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_840(MACRO, ...) \
+MACRO(840, __VA_ARGS__) \
+MU_DO_839(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_841(MACRO, ...) \
+MACRO(841, __VA_ARGS__) \
+MU_DO_840(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_842(MACRO, ...) \
+MACRO(842, __VA_ARGS__) \
+MU_DO_841(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_843(MACRO, ...) \
+MACRO(843, __VA_ARGS__) \
+MU_DO_842(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_844(MACRO, ...) \
+MACRO(844, __VA_ARGS__) \
+MU_DO_843(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_845(MACRO, ...) \
+MACRO(845, __VA_ARGS__) \
+MU_DO_844(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_846(MACRO, ...) \
+MACRO(846, __VA_ARGS__) \
+MU_DO_845(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_847(MACRO, ...) \
+MACRO(847, __VA_ARGS__) \
+MU_DO_846(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_848(MACRO, ...) \
+MACRO(848, __VA_ARGS__) \
+MU_DO_847(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_849(MACRO, ...) \
+MACRO(849, __VA_ARGS__) \
+MU_DO_848(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_850(MACRO, ...) \
+MACRO(850, __VA_ARGS__) \
+MU_DO_849(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_851(MACRO, ...) \
+MACRO(851, __VA_ARGS__) \
+MU_DO_850(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_852(MACRO, ...) \
+MACRO(852, __VA_ARGS__) \
+MU_DO_851(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_853(MACRO, ...) \
+MACRO(853, __VA_ARGS__) \
+MU_DO_852(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_854(MACRO, ...) \
+MACRO(854, __VA_ARGS__) \
+MU_DO_853(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_855(MACRO, ...) \
+MACRO(855, __VA_ARGS__) \
+MU_DO_854(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_856(MACRO, ...) \
+MACRO(856, __VA_ARGS__) \
+MU_DO_855(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_857(MACRO, ...) \
+MACRO(857, __VA_ARGS__) \
+MU_DO_856(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_858(MACRO, ...) \
+MACRO(858, __VA_ARGS__) \
+MU_DO_857(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_859(MACRO, ...) \
+MACRO(859, __VA_ARGS__) \
+MU_DO_858(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_860(MACRO, ...) \
+MACRO(860, __VA_ARGS__) \
+MU_DO_859(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_861(MACRO, ...) \
+MACRO(861, __VA_ARGS__) \
+MU_DO_860(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_862(MACRO, ...) \
+MACRO(862, __VA_ARGS__) \
+MU_DO_861(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_863(MACRO, ...) \
+MACRO(863, __VA_ARGS__) \
+MU_DO_862(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_864(MACRO, ...) \
+MACRO(864, __VA_ARGS__) \
+MU_DO_863(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_865(MACRO, ...) \
+MACRO(865, __VA_ARGS__) \
+MU_DO_864(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_866(MACRO, ...) \
+MACRO(866, __VA_ARGS__) \
+MU_DO_865(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_867(MACRO, ...) \
+MACRO(867, __VA_ARGS__) \
+MU_DO_866(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_868(MACRO, ...) \
+MACRO(868, __VA_ARGS__) \
+MU_DO_867(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_869(MACRO, ...) \
+MACRO(869, __VA_ARGS__) \
+MU_DO_868(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_870(MACRO, ...) \
+MACRO(870, __VA_ARGS__) \
+MU_DO_869(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_871(MACRO, ...) \
+MACRO(871, __VA_ARGS__) \
+MU_DO_870(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_872(MACRO, ...) \
+MACRO(872, __VA_ARGS__) \
+MU_DO_871(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_873(MACRO, ...) \
+MACRO(873, __VA_ARGS__) \
+MU_DO_872(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_874(MACRO, ...) \
+MACRO(874, __VA_ARGS__) \
+MU_DO_873(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_875(MACRO, ...) \
+MACRO(875, __VA_ARGS__) \
+MU_DO_874(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_876(MACRO, ...) \
+MACRO(876, __VA_ARGS__) \
+MU_DO_875(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_877(MACRO, ...) \
+MACRO(877, __VA_ARGS__) \
+MU_DO_876(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_878(MACRO, ...) \
+MACRO(878, __VA_ARGS__) \
+MU_DO_877(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_879(MACRO, ...) \
+MACRO(879, __VA_ARGS__) \
+MU_DO_878(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_880(MACRO, ...) \
+MACRO(880, __VA_ARGS__) \
+MU_DO_879(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_881(MACRO, ...) \
+MACRO(881, __VA_ARGS__) \
+MU_DO_880(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_882(MACRO, ...) \
+MACRO(882, __VA_ARGS__) \
+MU_DO_881(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_883(MACRO, ...) \
+MACRO(883, __VA_ARGS__) \
+MU_DO_882(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_884(MACRO, ...) \
+MACRO(884, __VA_ARGS__) \
+MU_DO_883(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_885(MACRO, ...) \
+MACRO(885, __VA_ARGS__) \
+MU_DO_884(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_886(MACRO, ...) \
+MACRO(886, __VA_ARGS__) \
+MU_DO_885(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_887(MACRO, ...) \
+MACRO(887, __VA_ARGS__) \
+MU_DO_886(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_888(MACRO, ...) \
+MACRO(888, __VA_ARGS__) \
+MU_DO_887(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_889(MACRO, ...) \
+MACRO(889, __VA_ARGS__) \
+MU_DO_888(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_890(MACRO, ...) \
+MACRO(890, __VA_ARGS__) \
+MU_DO_889(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_891(MACRO, ...) \
+MACRO(891, __VA_ARGS__) \
+MU_DO_890(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_892(MACRO, ...) \
+MACRO(892, __VA_ARGS__) \
+MU_DO_891(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_893(MACRO, ...) \
+MACRO(893, __VA_ARGS__) \
+MU_DO_892(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_894(MACRO, ...) \
+MACRO(894, __VA_ARGS__) \
+MU_DO_893(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_895(MACRO, ...) \
+MACRO(895, __VA_ARGS__) \
+MU_DO_894(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_896(MACRO, ...) \
+MACRO(896, __VA_ARGS__) \
+MU_DO_895(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_897(MACRO, ...) \
+MACRO(897, __VA_ARGS__) \
+MU_DO_896(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_898(MACRO, ...) \
+MACRO(898, __VA_ARGS__) \
+MU_DO_897(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_899(MACRO, ...) \
+MACRO(899, __VA_ARGS__) \
+MU_DO_898(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_900(MACRO, ...) \
+MACRO(900, __VA_ARGS__) \
+MU_DO_899(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_901(MACRO, ...) \
+MACRO(901, __VA_ARGS__) \
+MU_DO_900(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_902(MACRO, ...) \
+MACRO(902, __VA_ARGS__) \
+MU_DO_901(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_903(MACRO, ...) \
+MACRO(903, __VA_ARGS__) \
+MU_DO_902(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_904(MACRO, ...) \
+MACRO(904, __VA_ARGS__) \
+MU_DO_903(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_905(MACRO, ...) \
+MACRO(905, __VA_ARGS__) \
+MU_DO_904(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_906(MACRO, ...) \
+MACRO(906, __VA_ARGS__) \
+MU_DO_905(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_907(MACRO, ...) \
+MACRO(907, __VA_ARGS__) \
+MU_DO_906(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_908(MACRO, ...) \
+MACRO(908, __VA_ARGS__) \
+MU_DO_907(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_909(MACRO, ...) \
+MACRO(909, __VA_ARGS__) \
+MU_DO_908(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_910(MACRO, ...) \
+MACRO(910, __VA_ARGS__) \
+MU_DO_909(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_911(MACRO, ...) \
+MACRO(911, __VA_ARGS__) \
+MU_DO_910(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_912(MACRO, ...) \
+MACRO(912, __VA_ARGS__) \
+MU_DO_911(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_913(MACRO, ...) \
+MACRO(913, __VA_ARGS__) \
+MU_DO_912(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_914(MACRO, ...) \
+MACRO(914, __VA_ARGS__) \
+MU_DO_913(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_915(MACRO, ...) \
+MACRO(915, __VA_ARGS__) \
+MU_DO_914(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_916(MACRO, ...) \
+MACRO(916, __VA_ARGS__) \
+MU_DO_915(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_917(MACRO, ...) \
+MACRO(917, __VA_ARGS__) \
+MU_DO_916(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_918(MACRO, ...) \
+MACRO(918, __VA_ARGS__) \
+MU_DO_917(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_919(MACRO, ...) \
+MACRO(919, __VA_ARGS__) \
+MU_DO_918(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_920(MACRO, ...) \
+MACRO(920, __VA_ARGS__) \
+MU_DO_919(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_921(MACRO, ...) \
+MACRO(921, __VA_ARGS__) \
+MU_DO_920(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_922(MACRO, ...) \
+MACRO(922, __VA_ARGS__) \
+MU_DO_921(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_923(MACRO, ...) \
+MACRO(923, __VA_ARGS__) \
+MU_DO_922(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_924(MACRO, ...) \
+MACRO(924, __VA_ARGS__) \
+MU_DO_923(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_925(MACRO, ...) \
+MACRO(925, __VA_ARGS__) \
+MU_DO_924(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_926(MACRO, ...) \
+MACRO(926, __VA_ARGS__) \
+MU_DO_925(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_927(MACRO, ...) \
+MACRO(927, __VA_ARGS__) \
+MU_DO_926(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_928(MACRO, ...) \
+MACRO(928, __VA_ARGS__) \
+MU_DO_927(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_929(MACRO, ...) \
+MACRO(929, __VA_ARGS__) \
+MU_DO_928(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_930(MACRO, ...) \
+MACRO(930, __VA_ARGS__) \
+MU_DO_929(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_931(MACRO, ...) \
+MACRO(931, __VA_ARGS__) \
+MU_DO_930(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_932(MACRO, ...) \
+MACRO(932, __VA_ARGS__) \
+MU_DO_931(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_933(MACRO, ...) \
+MACRO(933, __VA_ARGS__) \
+MU_DO_932(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_934(MACRO, ...) \
+MACRO(934, __VA_ARGS__) \
+MU_DO_933(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_935(MACRO, ...) \
+MACRO(935, __VA_ARGS__) \
+MU_DO_934(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_936(MACRO, ...) \
+MACRO(936, __VA_ARGS__) \
+MU_DO_935(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_937(MACRO, ...) \
+MACRO(937, __VA_ARGS__) \
+MU_DO_936(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_938(MACRO, ...) \
+MACRO(938, __VA_ARGS__) \
+MU_DO_937(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_939(MACRO, ...) \
+MACRO(939, __VA_ARGS__) \
+MU_DO_938(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_940(MACRO, ...) \
+MACRO(940, __VA_ARGS__) \
+MU_DO_939(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_941(MACRO, ...) \
+MACRO(941, __VA_ARGS__) \
+MU_DO_940(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_942(MACRO, ...) \
+MACRO(942, __VA_ARGS__) \
+MU_DO_941(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_943(MACRO, ...) \
+MACRO(943, __VA_ARGS__) \
+MU_DO_942(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_944(MACRO, ...) \
+MACRO(944, __VA_ARGS__) \
+MU_DO_943(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_945(MACRO, ...) \
+MACRO(945, __VA_ARGS__) \
+MU_DO_944(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_946(MACRO, ...) \
+MACRO(946, __VA_ARGS__) \
+MU_DO_945(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_947(MACRO, ...) \
+MACRO(947, __VA_ARGS__) \
+MU_DO_946(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_948(MACRO, ...) \
+MACRO(948, __VA_ARGS__) \
+MU_DO_947(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_949(MACRO, ...) \
+MACRO(949, __VA_ARGS__) \
+MU_DO_948(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_950(MACRO, ...) \
+MACRO(950, __VA_ARGS__) \
+MU_DO_949(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_951(MACRO, ...) \
+MACRO(951, __VA_ARGS__) \
+MU_DO_950(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_952(MACRO, ...) \
+MACRO(952, __VA_ARGS__) \
+MU_DO_951(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_953(MACRO, ...) \
+MACRO(953, __VA_ARGS__) \
+MU_DO_952(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_954(MACRO, ...) \
+MACRO(954, __VA_ARGS__) \
+MU_DO_953(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_955(MACRO, ...) \
+MACRO(955, __VA_ARGS__) \
+MU_DO_954(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_956(MACRO, ...) \
+MACRO(956, __VA_ARGS__) \
+MU_DO_955(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_957(MACRO, ...) \
+MACRO(957, __VA_ARGS__) \
+MU_DO_956(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_958(MACRO, ...) \
+MACRO(958, __VA_ARGS__) \
+MU_DO_957(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_959(MACRO, ...) \
+MACRO(959, __VA_ARGS__) \
+MU_DO_958(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_960(MACRO, ...) \
+MACRO(960, __VA_ARGS__) \
+MU_DO_959(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_961(MACRO, ...) \
+MACRO(961, __VA_ARGS__) \
+MU_DO_960(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_962(MACRO, ...) \
+MACRO(962, __VA_ARGS__) \
+MU_DO_961(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_963(MACRO, ...) \
+MACRO(963, __VA_ARGS__) \
+MU_DO_962(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_964(MACRO, ...) \
+MACRO(964, __VA_ARGS__) \
+MU_DO_963(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_965(MACRO, ...) \
+MACRO(965, __VA_ARGS__) \
+MU_DO_964(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_966(MACRO, ...) \
+MACRO(966, __VA_ARGS__) \
+MU_DO_965(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_967(MACRO, ...) \
+MACRO(967, __VA_ARGS__) \
+MU_DO_966(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_968(MACRO, ...) \
+MACRO(968, __VA_ARGS__) \
+MU_DO_967(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_969(MACRO, ...) \
+MACRO(969, __VA_ARGS__) \
+MU_DO_968(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_970(MACRO, ...) \
+MACRO(970, __VA_ARGS__) \
+MU_DO_969(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_971(MACRO, ...) \
+MACRO(971, __VA_ARGS__) \
+MU_DO_970(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_972(MACRO, ...) \
+MACRO(972, __VA_ARGS__) \
+MU_DO_971(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_973(MACRO, ...) \
+MACRO(973, __VA_ARGS__) \
+MU_DO_972(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_974(MACRO, ...) \
+MACRO(974, __VA_ARGS__) \
+MU_DO_973(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_975(MACRO, ...) \
+MACRO(975, __VA_ARGS__) \
+MU_DO_974(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_976(MACRO, ...) \
+MACRO(976, __VA_ARGS__) \
+MU_DO_975(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_977(MACRO, ...) \
+MACRO(977, __VA_ARGS__) \
+MU_DO_976(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_978(MACRO, ...) \
+MACRO(978, __VA_ARGS__) \
+MU_DO_977(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_979(MACRO, ...) \
+MACRO(979, __VA_ARGS__) \
+MU_DO_978(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_980(MACRO, ...) \
+MACRO(980, __VA_ARGS__) \
+MU_DO_979(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_981(MACRO, ...) \
+MACRO(981, __VA_ARGS__) \
+MU_DO_980(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_982(MACRO, ...) \
+MACRO(982, __VA_ARGS__) \
+MU_DO_981(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_983(MACRO, ...) \
+MACRO(983, __VA_ARGS__) \
+MU_DO_982(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_984(MACRO, ...) \
+MACRO(984, __VA_ARGS__) \
+MU_DO_983(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_985(MACRO, ...) \
+MACRO(985, __VA_ARGS__) \
+MU_DO_984(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_986(MACRO, ...) \
+MACRO(986, __VA_ARGS__) \
+MU_DO_985(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_987(MACRO, ...) \
+MACRO(987, __VA_ARGS__) \
+MU_DO_986(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_988(MACRO, ...) \
+MACRO(988, __VA_ARGS__) \
+MU_DO_987(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_989(MACRO, ...) \
+MACRO(989, __VA_ARGS__) \
+MU_DO_988(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_990(MACRO, ...) \
+MACRO(990, __VA_ARGS__) \
+MU_DO_989(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_991(MACRO, ...) \
+MACRO(991, __VA_ARGS__) \
+MU_DO_990(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_992(MACRO, ...) \
+MACRO(992, __VA_ARGS__) \
+MU_DO_991(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_993(MACRO, ...) \
+MACRO(993, __VA_ARGS__) \
+MU_DO_992(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_994(MACRO, ...) \
+MACRO(994, __VA_ARGS__) \
+MU_DO_993(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_995(MACRO, ...) \
+MACRO(995, __VA_ARGS__) \
+MU_DO_994(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_996(MACRO, ...) \
+MACRO(996, __VA_ARGS__) \
+MU_DO_995(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_997(MACRO, ...) \
+MACRO(997, __VA_ARGS__) \
+MU_DO_996(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_998(MACRO, ...) \
+MACRO(998, __VA_ARGS__) \
+MU_DO_997(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_999(MACRO, ...) \
+MACRO(999, __VA_ARGS__) \
+MU_DO_998(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1000(MACRO, ...) \
+MACRO(1000, __VA_ARGS__) \
+MU_DO_999(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1001(MACRO, ...) \
+MACRO(1001, __VA_ARGS__) \
+MU_DO_1000(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1002(MACRO, ...) \
+MACRO(1002, __VA_ARGS__) \
+MU_DO_1001(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1003(MACRO, ...) \
+MACRO(1003, __VA_ARGS__) \
+MU_DO_1002(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1004(MACRO, ...) \
+MACRO(1004, __VA_ARGS__) \
+MU_DO_1003(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1005(MACRO, ...) \
+MACRO(1005, __VA_ARGS__) \
+MU_DO_1004(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1006(MACRO, ...) \
+MACRO(1006, __VA_ARGS__) \
+MU_DO_1005(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1007(MACRO, ...) \
+MACRO(1007, __VA_ARGS__) \
+MU_DO_1006(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1008(MACRO, ...) \
+MACRO(1008, __VA_ARGS__) \
+MU_DO_1007(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1009(MACRO, ...) \
+MACRO(1009, __VA_ARGS__) \
+MU_DO_1008(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1010(MACRO, ...) \
+MACRO(1010, __VA_ARGS__) \
+MU_DO_1009(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1011(MACRO, ...) \
+MACRO(1011, __VA_ARGS__) \
+MU_DO_1010(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1012(MACRO, ...) \
+MACRO(1012, __VA_ARGS__) \
+MU_DO_1011(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1013(MACRO, ...) \
+MACRO(1013, __VA_ARGS__) \
+MU_DO_1012(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1014(MACRO, ...) \
+MACRO(1014, __VA_ARGS__) \
+MU_DO_1013(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1015(MACRO, ...) \
+MACRO(1015, __VA_ARGS__) \
+MU_DO_1014(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1016(MACRO, ...) \
+MACRO(1016, __VA_ARGS__) \
+MU_DO_1015(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1017(MACRO, ...) \
+MACRO(1017, __VA_ARGS__) \
+MU_DO_1016(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1018(MACRO, ...) \
+MACRO(1018, __VA_ARGS__) \
+MU_DO_1017(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1019(MACRO, ...) \
+MACRO(1019, __VA_ARGS__) \
+MU_DO_1018(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1020(MACRO, ...) \
+MACRO(1020, __VA_ARGS__) \
+MU_DO_1019(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1021(MACRO, ...) \
+MACRO(1021, __VA_ARGS__) \
+MU_DO_1020(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1022(MACRO, ...) \
+MACRO(1022, __VA_ARGS__) \
+MU_DO_1021(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1023(MACRO, ...) \
+MACRO(1023, __VA_ARGS__) \
+MU_DO_1022(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1024(MACRO, ...) \
+MACRO(1024, __VA_ARGS__) \
+MU_DO_1023(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1025(MACRO, ...) \
+MACRO(1025, __VA_ARGS__) \
+MU_DO_1024(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1026(MACRO, ...) \
+MACRO(1026, __VA_ARGS__) \
+MU_DO_1025(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1027(MACRO, ...) \
+MACRO(1027, __VA_ARGS__) \
+MU_DO_1026(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1028(MACRO, ...) \
+MACRO(1028, __VA_ARGS__) \
+MU_DO_1027(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1029(MACRO, ...) \
+MACRO(1029, __VA_ARGS__) \
+MU_DO_1028(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1030(MACRO, ...) \
+MACRO(1030, __VA_ARGS__) \
+MU_DO_1029(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1031(MACRO, ...) \
+MACRO(1031, __VA_ARGS__) \
+MU_DO_1030(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1032(MACRO, ...) \
+MACRO(1032, __VA_ARGS__) \
+MU_DO_1031(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1033(MACRO, ...) \
+MACRO(1033, __VA_ARGS__) \
+MU_DO_1032(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1034(MACRO, ...) \
+MACRO(1034, __VA_ARGS__) \
+MU_DO_1033(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1035(MACRO, ...) \
+MACRO(1035, __VA_ARGS__) \
+MU_DO_1034(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1036(MACRO, ...) \
+MACRO(1036, __VA_ARGS__) \
+MU_DO_1035(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1037(MACRO, ...) \
+MACRO(1037, __VA_ARGS__) \
+MU_DO_1036(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1038(MACRO, ...) \
+MACRO(1038, __VA_ARGS__) \
+MU_DO_1037(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1039(MACRO, ...) \
+MACRO(1039, __VA_ARGS__) \
+MU_DO_1038(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1040(MACRO, ...) \
+MACRO(1040, __VA_ARGS__) \
+MU_DO_1039(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1041(MACRO, ...) \
+MACRO(1041, __VA_ARGS__) \
+MU_DO_1040(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1042(MACRO, ...) \
+MACRO(1042, __VA_ARGS__) \
+MU_DO_1041(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1043(MACRO, ...) \
+MACRO(1043, __VA_ARGS__) \
+MU_DO_1042(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1044(MACRO, ...) \
+MACRO(1044, __VA_ARGS__) \
+MU_DO_1043(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1045(MACRO, ...) \
+MACRO(1045, __VA_ARGS__) \
+MU_DO_1044(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1046(MACRO, ...) \
+MACRO(1046, __VA_ARGS__) \
+MU_DO_1045(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1047(MACRO, ...) \
+MACRO(1047, __VA_ARGS__) \
+MU_DO_1046(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1048(MACRO, ...) \
+MACRO(1048, __VA_ARGS__) \
+MU_DO_1047(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1049(MACRO, ...) \
+MACRO(1049, __VA_ARGS__) \
+MU_DO_1048(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1050(MACRO, ...) \
+MACRO(1050, __VA_ARGS__) \
+MU_DO_1049(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1051(MACRO, ...) \
+MACRO(1051, __VA_ARGS__) \
+MU_DO_1050(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1052(MACRO, ...) \
+MACRO(1052, __VA_ARGS__) \
+MU_DO_1051(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1053(MACRO, ...) \
+MACRO(1053, __VA_ARGS__) \
+MU_DO_1052(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1054(MACRO, ...) \
+MACRO(1054, __VA_ARGS__) \
+MU_DO_1053(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1055(MACRO, ...) \
+MACRO(1055, __VA_ARGS__) \
+MU_DO_1054(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1056(MACRO, ...) \
+MACRO(1056, __VA_ARGS__) \
+MU_DO_1055(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1057(MACRO, ...) \
+MACRO(1057, __VA_ARGS__) \
+MU_DO_1056(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1058(MACRO, ...) \
+MACRO(1058, __VA_ARGS__) \
+MU_DO_1057(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1059(MACRO, ...) \
+MACRO(1059, __VA_ARGS__) \
+MU_DO_1058(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1060(MACRO, ...) \
+MACRO(1060, __VA_ARGS__) \
+MU_DO_1059(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1061(MACRO, ...) \
+MACRO(1061, __VA_ARGS__) \
+MU_DO_1060(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1062(MACRO, ...) \
+MACRO(1062, __VA_ARGS__) \
+MU_DO_1061(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1063(MACRO, ...) \
+MACRO(1063, __VA_ARGS__) \
+MU_DO_1062(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1064(MACRO, ...) \
+MACRO(1064, __VA_ARGS__) \
+MU_DO_1063(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1065(MACRO, ...) \
+MACRO(1065, __VA_ARGS__) \
+MU_DO_1064(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1066(MACRO, ...) \
+MACRO(1066, __VA_ARGS__) \
+MU_DO_1065(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1067(MACRO, ...) \
+MACRO(1067, __VA_ARGS__) \
+MU_DO_1066(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1068(MACRO, ...) \
+MACRO(1068, __VA_ARGS__) \
+MU_DO_1067(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1069(MACRO, ...) \
+MACRO(1069, __VA_ARGS__) \
+MU_DO_1068(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1070(MACRO, ...) \
+MACRO(1070, __VA_ARGS__) \
+MU_DO_1069(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1071(MACRO, ...) \
+MACRO(1071, __VA_ARGS__) \
+MU_DO_1070(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1072(MACRO, ...) \
+MACRO(1072, __VA_ARGS__) \
+MU_DO_1071(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1073(MACRO, ...) \
+MACRO(1073, __VA_ARGS__) \
+MU_DO_1072(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1074(MACRO, ...) \
+MACRO(1074, __VA_ARGS__) \
+MU_DO_1073(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1075(MACRO, ...) \
+MACRO(1075, __VA_ARGS__) \
+MU_DO_1074(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1076(MACRO, ...) \
+MACRO(1076, __VA_ARGS__) \
+MU_DO_1075(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1077(MACRO, ...) \
+MACRO(1077, __VA_ARGS__) \
+MU_DO_1076(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1078(MACRO, ...) \
+MACRO(1078, __VA_ARGS__) \
+MU_DO_1077(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1079(MACRO, ...) \
+MACRO(1079, __VA_ARGS__) \
+MU_DO_1078(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1080(MACRO, ...) \
+MACRO(1080, __VA_ARGS__) \
+MU_DO_1079(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1081(MACRO, ...) \
+MACRO(1081, __VA_ARGS__) \
+MU_DO_1080(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1082(MACRO, ...) \
+MACRO(1082, __VA_ARGS__) \
+MU_DO_1081(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1083(MACRO, ...) \
+MACRO(1083, __VA_ARGS__) \
+MU_DO_1082(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1084(MACRO, ...) \
+MACRO(1084, __VA_ARGS__) \
+MU_DO_1083(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1085(MACRO, ...) \
+MACRO(1085, __VA_ARGS__) \
+MU_DO_1084(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1086(MACRO, ...) \
+MACRO(1086, __VA_ARGS__) \
+MU_DO_1085(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1087(MACRO, ...) \
+MACRO(1087, __VA_ARGS__) \
+MU_DO_1086(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1088(MACRO, ...) \
+MACRO(1088, __VA_ARGS__) \
+MU_DO_1087(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1089(MACRO, ...) \
+MACRO(1089, __VA_ARGS__) \
+MU_DO_1088(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1090(MACRO, ...) \
+MACRO(1090, __VA_ARGS__) \
+MU_DO_1089(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1091(MACRO, ...) \
+MACRO(1091, __VA_ARGS__) \
+MU_DO_1090(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1092(MACRO, ...) \
+MACRO(1092, __VA_ARGS__) \
+MU_DO_1091(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1093(MACRO, ...) \
+MACRO(1093, __VA_ARGS__) \
+MU_DO_1092(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1094(MACRO, ...) \
+MACRO(1094, __VA_ARGS__) \
+MU_DO_1093(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1095(MACRO, ...) \
+MACRO(1095, __VA_ARGS__) \
+MU_DO_1094(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1096(MACRO, ...) \
+MACRO(1096, __VA_ARGS__) \
+MU_DO_1095(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1097(MACRO, ...) \
+MACRO(1097, __VA_ARGS__) \
+MU_DO_1096(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1098(MACRO, ...) \
+MACRO(1098, __VA_ARGS__) \
+MU_DO_1097(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1099(MACRO, ...) \
+MACRO(1099, __VA_ARGS__) \
+MU_DO_1098(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1100(MACRO, ...) \
+MACRO(1100, __VA_ARGS__) \
+MU_DO_1099(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1101(MACRO, ...) \
+MACRO(1101, __VA_ARGS__) \
+MU_DO_1100(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1102(MACRO, ...) \
+MACRO(1102, __VA_ARGS__) \
+MU_DO_1101(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1103(MACRO, ...) \
+MACRO(1103, __VA_ARGS__) \
+MU_DO_1102(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1104(MACRO, ...) \
+MACRO(1104, __VA_ARGS__) \
+MU_DO_1103(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1105(MACRO, ...) \
+MACRO(1105, __VA_ARGS__) \
+MU_DO_1104(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1106(MACRO, ...) \
+MACRO(1106, __VA_ARGS__) \
+MU_DO_1105(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1107(MACRO, ...) \
+MACRO(1107, __VA_ARGS__) \
+MU_DO_1106(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1108(MACRO, ...) \
+MACRO(1108, __VA_ARGS__) \
+MU_DO_1107(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1109(MACRO, ...) \
+MACRO(1109, __VA_ARGS__) \
+MU_DO_1108(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1110(MACRO, ...) \
+MACRO(1110, __VA_ARGS__) \
+MU_DO_1109(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1111(MACRO, ...) \
+MACRO(1111, __VA_ARGS__) \
+MU_DO_1110(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1112(MACRO, ...) \
+MACRO(1112, __VA_ARGS__) \
+MU_DO_1111(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1113(MACRO, ...) \
+MACRO(1113, __VA_ARGS__) \
+MU_DO_1112(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1114(MACRO, ...) \
+MACRO(1114, __VA_ARGS__) \
+MU_DO_1113(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1115(MACRO, ...) \
+MACRO(1115, __VA_ARGS__) \
+MU_DO_1114(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1116(MACRO, ...) \
+MACRO(1116, __VA_ARGS__) \
+MU_DO_1115(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1117(MACRO, ...) \
+MACRO(1117, __VA_ARGS__) \
+MU_DO_1116(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1118(MACRO, ...) \
+MACRO(1118, __VA_ARGS__) \
+MU_DO_1117(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1119(MACRO, ...) \
+MACRO(1119, __VA_ARGS__) \
+MU_DO_1118(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1120(MACRO, ...) \
+MACRO(1120, __VA_ARGS__) \
+MU_DO_1119(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1121(MACRO, ...) \
+MACRO(1121, __VA_ARGS__) \
+MU_DO_1120(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1122(MACRO, ...) \
+MACRO(1122, __VA_ARGS__) \
+MU_DO_1121(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1123(MACRO, ...) \
+MACRO(1123, __VA_ARGS__) \
+MU_DO_1122(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1124(MACRO, ...) \
+MACRO(1124, __VA_ARGS__) \
+MU_DO_1123(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1125(MACRO, ...) \
+MACRO(1125, __VA_ARGS__) \
+MU_DO_1124(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1126(MACRO, ...) \
+MACRO(1126, __VA_ARGS__) \
+MU_DO_1125(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1127(MACRO, ...) \
+MACRO(1127, __VA_ARGS__) \
+MU_DO_1126(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1128(MACRO, ...) \
+MACRO(1128, __VA_ARGS__) \
+MU_DO_1127(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1129(MACRO, ...) \
+MACRO(1129, __VA_ARGS__) \
+MU_DO_1128(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1130(MACRO, ...) \
+MACRO(1130, __VA_ARGS__) \
+MU_DO_1129(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1131(MACRO, ...) \
+MACRO(1131, __VA_ARGS__) \
+MU_DO_1130(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1132(MACRO, ...) \
+MACRO(1132, __VA_ARGS__) \
+MU_DO_1131(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1133(MACRO, ...) \
+MACRO(1133, __VA_ARGS__) \
+MU_DO_1132(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1134(MACRO, ...) \
+MACRO(1134, __VA_ARGS__) \
+MU_DO_1133(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1135(MACRO, ...) \
+MACRO(1135, __VA_ARGS__) \
+MU_DO_1134(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1136(MACRO, ...) \
+MACRO(1136, __VA_ARGS__) \
+MU_DO_1135(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1137(MACRO, ...) \
+MACRO(1137, __VA_ARGS__) \
+MU_DO_1136(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1138(MACRO, ...) \
+MACRO(1138, __VA_ARGS__) \
+MU_DO_1137(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1139(MACRO, ...) \
+MACRO(1139, __VA_ARGS__) \
+MU_DO_1138(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1140(MACRO, ...) \
+MACRO(1140, __VA_ARGS__) \
+MU_DO_1139(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1141(MACRO, ...) \
+MACRO(1141, __VA_ARGS__) \
+MU_DO_1140(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1142(MACRO, ...) \
+MACRO(1142, __VA_ARGS__) \
+MU_DO_1141(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1143(MACRO, ...) \
+MACRO(1143, __VA_ARGS__) \
+MU_DO_1142(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1144(MACRO, ...) \
+MACRO(1144, __VA_ARGS__) \
+MU_DO_1143(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1145(MACRO, ...) \
+MACRO(1145, __VA_ARGS__) \
+MU_DO_1144(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1146(MACRO, ...) \
+MACRO(1146, __VA_ARGS__) \
+MU_DO_1145(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1147(MACRO, ...) \
+MACRO(1147, __VA_ARGS__) \
+MU_DO_1146(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1148(MACRO, ...) \
+MACRO(1148, __VA_ARGS__) \
+MU_DO_1147(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1149(MACRO, ...) \
+MACRO(1149, __VA_ARGS__) \
+MU_DO_1148(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1150(MACRO, ...) \
+MACRO(1150, __VA_ARGS__) \
+MU_DO_1149(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1151(MACRO, ...) \
+MACRO(1151, __VA_ARGS__) \
+MU_DO_1150(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1152(MACRO, ...) \
+MACRO(1152, __VA_ARGS__) \
+MU_DO_1151(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1153(MACRO, ...) \
+MACRO(1153, __VA_ARGS__) \
+MU_DO_1152(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1154(MACRO, ...) \
+MACRO(1154, __VA_ARGS__) \
+MU_DO_1153(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1155(MACRO, ...) \
+MACRO(1155, __VA_ARGS__) \
+MU_DO_1154(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1156(MACRO, ...) \
+MACRO(1156, __VA_ARGS__) \
+MU_DO_1155(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1157(MACRO, ...) \
+MACRO(1157, __VA_ARGS__) \
+MU_DO_1156(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1158(MACRO, ...) \
+MACRO(1158, __VA_ARGS__) \
+MU_DO_1157(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1159(MACRO, ...) \
+MACRO(1159, __VA_ARGS__) \
+MU_DO_1158(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1160(MACRO, ...) \
+MACRO(1160, __VA_ARGS__) \
+MU_DO_1159(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1161(MACRO, ...) \
+MACRO(1161, __VA_ARGS__) \
+MU_DO_1160(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1162(MACRO, ...) \
+MACRO(1162, __VA_ARGS__) \
+MU_DO_1161(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1163(MACRO, ...) \
+MACRO(1163, __VA_ARGS__) \
+MU_DO_1162(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1164(MACRO, ...) \
+MACRO(1164, __VA_ARGS__) \
+MU_DO_1163(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1165(MACRO, ...) \
+MACRO(1165, __VA_ARGS__) \
+MU_DO_1164(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1166(MACRO, ...) \
+MACRO(1166, __VA_ARGS__) \
+MU_DO_1165(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1167(MACRO, ...) \
+MACRO(1167, __VA_ARGS__) \
+MU_DO_1166(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1168(MACRO, ...) \
+MACRO(1168, __VA_ARGS__) \
+MU_DO_1167(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1169(MACRO, ...) \
+MACRO(1169, __VA_ARGS__) \
+MU_DO_1168(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1170(MACRO, ...) \
+MACRO(1170, __VA_ARGS__) \
+MU_DO_1169(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1171(MACRO, ...) \
+MACRO(1171, __VA_ARGS__) \
+MU_DO_1170(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1172(MACRO, ...) \
+MACRO(1172, __VA_ARGS__) \
+MU_DO_1171(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1173(MACRO, ...) \
+MACRO(1173, __VA_ARGS__) \
+MU_DO_1172(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1174(MACRO, ...) \
+MACRO(1174, __VA_ARGS__) \
+MU_DO_1173(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1175(MACRO, ...) \
+MACRO(1175, __VA_ARGS__) \
+MU_DO_1174(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1176(MACRO, ...) \
+MACRO(1176, __VA_ARGS__) \
+MU_DO_1175(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1177(MACRO, ...) \
+MACRO(1177, __VA_ARGS__) \
+MU_DO_1176(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1178(MACRO, ...) \
+MACRO(1178, __VA_ARGS__) \
+MU_DO_1177(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1179(MACRO, ...) \
+MACRO(1179, __VA_ARGS__) \
+MU_DO_1178(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1180(MACRO, ...) \
+MACRO(1180, __VA_ARGS__) \
+MU_DO_1179(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1181(MACRO, ...) \
+MACRO(1181, __VA_ARGS__) \
+MU_DO_1180(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1182(MACRO, ...) \
+MACRO(1182, __VA_ARGS__) \
+MU_DO_1181(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1183(MACRO, ...) \
+MACRO(1183, __VA_ARGS__) \
+MU_DO_1182(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1184(MACRO, ...) \
+MACRO(1184, __VA_ARGS__) \
+MU_DO_1183(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1185(MACRO, ...) \
+MACRO(1185, __VA_ARGS__) \
+MU_DO_1184(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1186(MACRO, ...) \
+MACRO(1186, __VA_ARGS__) \
+MU_DO_1185(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1187(MACRO, ...) \
+MACRO(1187, __VA_ARGS__) \
+MU_DO_1186(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1188(MACRO, ...) \
+MACRO(1188, __VA_ARGS__) \
+MU_DO_1187(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1189(MACRO, ...) \
+MACRO(1189, __VA_ARGS__) \
+MU_DO_1188(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1190(MACRO, ...) \
+MACRO(1190, __VA_ARGS__) \
+MU_DO_1189(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1191(MACRO, ...) \
+MACRO(1191, __VA_ARGS__) \
+MU_DO_1190(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1192(MACRO, ...) \
+MACRO(1192, __VA_ARGS__) \
+MU_DO_1191(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1193(MACRO, ...) \
+MACRO(1193, __VA_ARGS__) \
+MU_DO_1192(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1194(MACRO, ...) \
+MACRO(1194, __VA_ARGS__) \
+MU_DO_1193(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1195(MACRO, ...) \
+MACRO(1195, __VA_ARGS__) \
+MU_DO_1194(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1196(MACRO, ...) \
+MACRO(1196, __VA_ARGS__) \
+MU_DO_1195(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1197(MACRO, ...) \
+MACRO(1197, __VA_ARGS__) \
+MU_DO_1196(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1198(MACRO, ...) \
+MACRO(1198, __VA_ARGS__) \
+MU_DO_1197(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1199(MACRO, ...) \
+MACRO(1199, __VA_ARGS__) \
+MU_DO_1198(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1200(MACRO, ...) \
+MACRO(1200, __VA_ARGS__) \
+MU_DO_1199(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1201(MACRO, ...) \
+MACRO(1201, __VA_ARGS__) \
+MU_DO_1200(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1202(MACRO, ...) \
+MACRO(1202, __VA_ARGS__) \
+MU_DO_1201(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1203(MACRO, ...) \
+MACRO(1203, __VA_ARGS__) \
+MU_DO_1202(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1204(MACRO, ...) \
+MACRO(1204, __VA_ARGS__) \
+MU_DO_1203(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1205(MACRO, ...) \
+MACRO(1205, __VA_ARGS__) \
+MU_DO_1204(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1206(MACRO, ...) \
+MACRO(1206, __VA_ARGS__) \
+MU_DO_1205(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1207(MACRO, ...) \
+MACRO(1207, __VA_ARGS__) \
+MU_DO_1206(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1208(MACRO, ...) \
+MACRO(1208, __VA_ARGS__) \
+MU_DO_1207(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1209(MACRO, ...) \
+MACRO(1209, __VA_ARGS__) \
+MU_DO_1208(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1210(MACRO, ...) \
+MACRO(1210, __VA_ARGS__) \
+MU_DO_1209(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1211(MACRO, ...) \
+MACRO(1211, __VA_ARGS__) \
+MU_DO_1210(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1212(MACRO, ...) \
+MACRO(1212, __VA_ARGS__) \
+MU_DO_1211(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1213(MACRO, ...) \
+MACRO(1213, __VA_ARGS__) \
+MU_DO_1212(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1214(MACRO, ...) \
+MACRO(1214, __VA_ARGS__) \
+MU_DO_1213(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1215(MACRO, ...) \
+MACRO(1215, __VA_ARGS__) \
+MU_DO_1214(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1216(MACRO, ...) \
+MACRO(1216, __VA_ARGS__) \
+MU_DO_1215(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1217(MACRO, ...) \
+MACRO(1217, __VA_ARGS__) \
+MU_DO_1216(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1218(MACRO, ...) \
+MACRO(1218, __VA_ARGS__) \
+MU_DO_1217(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1219(MACRO, ...) \
+MACRO(1219, __VA_ARGS__) \
+MU_DO_1218(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1220(MACRO, ...) \
+MACRO(1220, __VA_ARGS__) \
+MU_DO_1219(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1221(MACRO, ...) \
+MACRO(1221, __VA_ARGS__) \
+MU_DO_1220(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1222(MACRO, ...) \
+MACRO(1222, __VA_ARGS__) \
+MU_DO_1221(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1223(MACRO, ...) \
+MACRO(1223, __VA_ARGS__) \
+MU_DO_1222(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1224(MACRO, ...) \
+MACRO(1224, __VA_ARGS__) \
+MU_DO_1223(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1225(MACRO, ...) \
+MACRO(1225, __VA_ARGS__) \
+MU_DO_1224(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1226(MACRO, ...) \
+MACRO(1226, __VA_ARGS__) \
+MU_DO_1225(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1227(MACRO, ...) \
+MACRO(1227, __VA_ARGS__) \
+MU_DO_1226(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1228(MACRO, ...) \
+MACRO(1228, __VA_ARGS__) \
+MU_DO_1227(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1229(MACRO, ...) \
+MACRO(1229, __VA_ARGS__) \
+MU_DO_1228(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1230(MACRO, ...) \
+MACRO(1230, __VA_ARGS__) \
+MU_DO_1229(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1231(MACRO, ...) \
+MACRO(1231, __VA_ARGS__) \
+MU_DO_1230(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1232(MACRO, ...) \
+MACRO(1232, __VA_ARGS__) \
+MU_DO_1231(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1233(MACRO, ...) \
+MACRO(1233, __VA_ARGS__) \
+MU_DO_1232(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1234(MACRO, ...) \
+MACRO(1234, __VA_ARGS__) \
+MU_DO_1233(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1235(MACRO, ...) \
+MACRO(1235, __VA_ARGS__) \
+MU_DO_1234(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1236(MACRO, ...) \
+MACRO(1236, __VA_ARGS__) \
+MU_DO_1235(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1237(MACRO, ...) \
+MACRO(1237, __VA_ARGS__) \
+MU_DO_1236(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1238(MACRO, ...) \
+MACRO(1238, __VA_ARGS__) \
+MU_DO_1237(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1239(MACRO, ...) \
+MACRO(1239, __VA_ARGS__) \
+MU_DO_1238(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1240(MACRO, ...) \
+MACRO(1240, __VA_ARGS__) \
+MU_DO_1239(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1241(MACRO, ...) \
+MACRO(1241, __VA_ARGS__) \
+MU_DO_1240(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1242(MACRO, ...) \
+MACRO(1242, __VA_ARGS__) \
+MU_DO_1241(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1243(MACRO, ...) \
+MACRO(1243, __VA_ARGS__) \
+MU_DO_1242(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1244(MACRO, ...) \
+MACRO(1244, __VA_ARGS__) \
+MU_DO_1243(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1245(MACRO, ...) \
+MACRO(1245, __VA_ARGS__) \
+MU_DO_1244(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1246(MACRO, ...) \
+MACRO(1246, __VA_ARGS__) \
+MU_DO_1245(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1247(MACRO, ...) \
+MACRO(1247, __VA_ARGS__) \
+MU_DO_1246(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1248(MACRO, ...) \
+MACRO(1248, __VA_ARGS__) \
+MU_DO_1247(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1249(MACRO, ...) \
+MACRO(1249, __VA_ARGS__) \
+MU_DO_1248(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1250(MACRO, ...) \
+MACRO(1250, __VA_ARGS__) \
+MU_DO_1249(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1251(MACRO, ...) \
+MACRO(1251, __VA_ARGS__) \
+MU_DO_1250(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1252(MACRO, ...) \
+MACRO(1252, __VA_ARGS__) \
+MU_DO_1251(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1253(MACRO, ...) \
+MACRO(1253, __VA_ARGS__) \
+MU_DO_1252(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1254(MACRO, ...) \
+MACRO(1254, __VA_ARGS__) \
+MU_DO_1253(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1255(MACRO, ...) \
+MACRO(1255, __VA_ARGS__) \
+MU_DO_1254(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1256(MACRO, ...) \
+MACRO(1256, __VA_ARGS__) \
+MU_DO_1255(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1257(MACRO, ...) \
+MACRO(1257, __VA_ARGS__) \
+MU_DO_1256(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1258(MACRO, ...) \
+MACRO(1258, __VA_ARGS__) \
+MU_DO_1257(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1259(MACRO, ...) \
+MACRO(1259, __VA_ARGS__) \
+MU_DO_1258(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1260(MACRO, ...) \
+MACRO(1260, __VA_ARGS__) \
+MU_DO_1259(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1261(MACRO, ...) \
+MACRO(1261, __VA_ARGS__) \
+MU_DO_1260(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1262(MACRO, ...) \
+MACRO(1262, __VA_ARGS__) \
+MU_DO_1261(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1263(MACRO, ...) \
+MACRO(1263, __VA_ARGS__) \
+MU_DO_1262(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1264(MACRO, ...) \
+MACRO(1264, __VA_ARGS__) \
+MU_DO_1263(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1265(MACRO, ...) \
+MACRO(1265, __VA_ARGS__) \
+MU_DO_1264(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1266(MACRO, ...) \
+MACRO(1266, __VA_ARGS__) \
+MU_DO_1265(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1267(MACRO, ...) \
+MACRO(1267, __VA_ARGS__) \
+MU_DO_1266(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1268(MACRO, ...) \
+MACRO(1268, __VA_ARGS__) \
+MU_DO_1267(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1269(MACRO, ...) \
+MACRO(1269, __VA_ARGS__) \
+MU_DO_1268(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1270(MACRO, ...) \
+MACRO(1270, __VA_ARGS__) \
+MU_DO_1269(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1271(MACRO, ...) \
+MACRO(1271, __VA_ARGS__) \
+MU_DO_1270(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1272(MACRO, ...) \
+MACRO(1272, __VA_ARGS__) \
+MU_DO_1271(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1273(MACRO, ...) \
+MACRO(1273, __VA_ARGS__) \
+MU_DO_1272(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1274(MACRO, ...) \
+MACRO(1274, __VA_ARGS__) \
+MU_DO_1273(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1275(MACRO, ...) \
+MACRO(1275, __VA_ARGS__) \
+MU_DO_1274(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1276(MACRO, ...) \
+MACRO(1276, __VA_ARGS__) \
+MU_DO_1275(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1277(MACRO, ...) \
+MACRO(1277, __VA_ARGS__) \
+MU_DO_1276(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1278(MACRO, ...) \
+MACRO(1278, __VA_ARGS__) \
+MU_DO_1277(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1279(MACRO, ...) \
+MACRO(1279, __VA_ARGS__) \
+MU_DO_1278(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1280(MACRO, ...) \
+MACRO(1280, __VA_ARGS__) \
+MU_DO_1279(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1281(MACRO, ...) \
+MACRO(1281, __VA_ARGS__) \
+MU_DO_1280(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1282(MACRO, ...) \
+MACRO(1282, __VA_ARGS__) \
+MU_DO_1281(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1283(MACRO, ...) \
+MACRO(1283, __VA_ARGS__) \
+MU_DO_1282(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1284(MACRO, ...) \
+MACRO(1284, __VA_ARGS__) \
+MU_DO_1283(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1285(MACRO, ...) \
+MACRO(1285, __VA_ARGS__) \
+MU_DO_1284(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1286(MACRO, ...) \
+MACRO(1286, __VA_ARGS__) \
+MU_DO_1285(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1287(MACRO, ...) \
+MACRO(1287, __VA_ARGS__) \
+MU_DO_1286(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1288(MACRO, ...) \
+MACRO(1288, __VA_ARGS__) \
+MU_DO_1287(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1289(MACRO, ...) \
+MACRO(1289, __VA_ARGS__) \
+MU_DO_1288(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1290(MACRO, ...) \
+MACRO(1290, __VA_ARGS__) \
+MU_DO_1289(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1291(MACRO, ...) \
+MACRO(1291, __VA_ARGS__) \
+MU_DO_1290(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1292(MACRO, ...) \
+MACRO(1292, __VA_ARGS__) \
+MU_DO_1291(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1293(MACRO, ...) \
+MACRO(1293, __VA_ARGS__) \
+MU_DO_1292(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1294(MACRO, ...) \
+MACRO(1294, __VA_ARGS__) \
+MU_DO_1293(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1295(MACRO, ...) \
+MACRO(1295, __VA_ARGS__) \
+MU_DO_1294(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1296(MACRO, ...) \
+MACRO(1296, __VA_ARGS__) \
+MU_DO_1295(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1297(MACRO, ...) \
+MACRO(1297, __VA_ARGS__) \
+MU_DO_1296(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1298(MACRO, ...) \
+MACRO(1298, __VA_ARGS__) \
+MU_DO_1297(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1299(MACRO, ...) \
+MACRO(1299, __VA_ARGS__) \
+MU_DO_1298(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1300(MACRO, ...) \
+MACRO(1300, __VA_ARGS__) \
+MU_DO_1299(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1301(MACRO, ...) \
+MACRO(1301, __VA_ARGS__) \
+MU_DO_1300(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1302(MACRO, ...) \
+MACRO(1302, __VA_ARGS__) \
+MU_DO_1301(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1303(MACRO, ...) \
+MACRO(1303, __VA_ARGS__) \
+MU_DO_1302(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1304(MACRO, ...) \
+MACRO(1304, __VA_ARGS__) \
+MU_DO_1303(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1305(MACRO, ...) \
+MACRO(1305, __VA_ARGS__) \
+MU_DO_1304(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1306(MACRO, ...) \
+MACRO(1306, __VA_ARGS__) \
+MU_DO_1305(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1307(MACRO, ...) \
+MACRO(1307, __VA_ARGS__) \
+MU_DO_1306(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1308(MACRO, ...) \
+MACRO(1308, __VA_ARGS__) \
+MU_DO_1307(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1309(MACRO, ...) \
+MACRO(1309, __VA_ARGS__) \
+MU_DO_1308(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1310(MACRO, ...) \
+MACRO(1310, __VA_ARGS__) \
+MU_DO_1309(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1311(MACRO, ...) \
+MACRO(1311, __VA_ARGS__) \
+MU_DO_1310(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1312(MACRO, ...) \
+MACRO(1312, __VA_ARGS__) \
+MU_DO_1311(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1313(MACRO, ...) \
+MACRO(1313, __VA_ARGS__) \
+MU_DO_1312(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1314(MACRO, ...) \
+MACRO(1314, __VA_ARGS__) \
+MU_DO_1313(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1315(MACRO, ...) \
+MACRO(1315, __VA_ARGS__) \
+MU_DO_1314(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1316(MACRO, ...) \
+MACRO(1316, __VA_ARGS__) \
+MU_DO_1315(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1317(MACRO, ...) \
+MACRO(1317, __VA_ARGS__) \
+MU_DO_1316(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1318(MACRO, ...) \
+MACRO(1318, __VA_ARGS__) \
+MU_DO_1317(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1319(MACRO, ...) \
+MACRO(1319, __VA_ARGS__) \
+MU_DO_1318(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1320(MACRO, ...) \
+MACRO(1320, __VA_ARGS__) \
+MU_DO_1319(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1321(MACRO, ...) \
+MACRO(1321, __VA_ARGS__) \
+MU_DO_1320(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1322(MACRO, ...) \
+MACRO(1322, __VA_ARGS__) \
+MU_DO_1321(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1323(MACRO, ...) \
+MACRO(1323, __VA_ARGS__) \
+MU_DO_1322(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1324(MACRO, ...) \
+MACRO(1324, __VA_ARGS__) \
+MU_DO_1323(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1325(MACRO, ...) \
+MACRO(1325, __VA_ARGS__) \
+MU_DO_1324(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1326(MACRO, ...) \
+MACRO(1326, __VA_ARGS__) \
+MU_DO_1325(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1327(MACRO, ...) \
+MACRO(1327, __VA_ARGS__) \
+MU_DO_1326(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1328(MACRO, ...) \
+MACRO(1328, __VA_ARGS__) \
+MU_DO_1327(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1329(MACRO, ...) \
+MACRO(1329, __VA_ARGS__) \
+MU_DO_1328(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1330(MACRO, ...) \
+MACRO(1330, __VA_ARGS__) \
+MU_DO_1329(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1331(MACRO, ...) \
+MACRO(1331, __VA_ARGS__) \
+MU_DO_1330(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1332(MACRO, ...) \
+MACRO(1332, __VA_ARGS__) \
+MU_DO_1331(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1333(MACRO, ...) \
+MACRO(1333, __VA_ARGS__) \
+MU_DO_1332(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1334(MACRO, ...) \
+MACRO(1334, __VA_ARGS__) \
+MU_DO_1333(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1335(MACRO, ...) \
+MACRO(1335, __VA_ARGS__) \
+MU_DO_1334(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1336(MACRO, ...) \
+MACRO(1336, __VA_ARGS__) \
+MU_DO_1335(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1337(MACRO, ...) \
+MACRO(1337, __VA_ARGS__) \
+MU_DO_1336(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1338(MACRO, ...) \
+MACRO(1338, __VA_ARGS__) \
+MU_DO_1337(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1339(MACRO, ...) \
+MACRO(1339, __VA_ARGS__) \
+MU_DO_1338(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1340(MACRO, ...) \
+MACRO(1340, __VA_ARGS__) \
+MU_DO_1339(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1341(MACRO, ...) \
+MACRO(1341, __VA_ARGS__) \
+MU_DO_1340(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1342(MACRO, ...) \
+MACRO(1342, __VA_ARGS__) \
+MU_DO_1341(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1343(MACRO, ...) \
+MACRO(1343, __VA_ARGS__) \
+MU_DO_1342(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1344(MACRO, ...) \
+MACRO(1344, __VA_ARGS__) \
+MU_DO_1343(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1345(MACRO, ...) \
+MACRO(1345, __VA_ARGS__) \
+MU_DO_1344(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1346(MACRO, ...) \
+MACRO(1346, __VA_ARGS__) \
+MU_DO_1345(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1347(MACRO, ...) \
+MACRO(1347, __VA_ARGS__) \
+MU_DO_1346(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1348(MACRO, ...) \
+MACRO(1348, __VA_ARGS__) \
+MU_DO_1347(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1349(MACRO, ...) \
+MACRO(1349, __VA_ARGS__) \
+MU_DO_1348(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1350(MACRO, ...) \
+MACRO(1350, __VA_ARGS__) \
+MU_DO_1349(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1351(MACRO, ...) \
+MACRO(1351, __VA_ARGS__) \
+MU_DO_1350(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1352(MACRO, ...) \
+MACRO(1352, __VA_ARGS__) \
+MU_DO_1351(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1353(MACRO, ...) \
+MACRO(1353, __VA_ARGS__) \
+MU_DO_1352(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1354(MACRO, ...) \
+MACRO(1354, __VA_ARGS__) \
+MU_DO_1353(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1355(MACRO, ...) \
+MACRO(1355, __VA_ARGS__) \
+MU_DO_1354(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1356(MACRO, ...) \
+MACRO(1356, __VA_ARGS__) \
+MU_DO_1355(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1357(MACRO, ...) \
+MACRO(1357, __VA_ARGS__) \
+MU_DO_1356(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1358(MACRO, ...) \
+MACRO(1358, __VA_ARGS__) \
+MU_DO_1357(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1359(MACRO, ...) \
+MACRO(1359, __VA_ARGS__) \
+MU_DO_1358(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1360(MACRO, ...) \
+MACRO(1360, __VA_ARGS__) \
+MU_DO_1359(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1361(MACRO, ...) \
+MACRO(1361, __VA_ARGS__) \
+MU_DO_1360(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1362(MACRO, ...) \
+MACRO(1362, __VA_ARGS__) \
+MU_DO_1361(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1363(MACRO, ...) \
+MACRO(1363, __VA_ARGS__) \
+MU_DO_1362(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1364(MACRO, ...) \
+MACRO(1364, __VA_ARGS__) \
+MU_DO_1363(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1365(MACRO, ...) \
+MACRO(1365, __VA_ARGS__) \
+MU_DO_1364(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1366(MACRO, ...) \
+MACRO(1366, __VA_ARGS__) \
+MU_DO_1365(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1367(MACRO, ...) \
+MACRO(1367, __VA_ARGS__) \
+MU_DO_1366(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1368(MACRO, ...) \
+MACRO(1368, __VA_ARGS__) \
+MU_DO_1367(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1369(MACRO, ...) \
+MACRO(1369, __VA_ARGS__) \
+MU_DO_1368(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1370(MACRO, ...) \
+MACRO(1370, __VA_ARGS__) \
+MU_DO_1369(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1371(MACRO, ...) \
+MACRO(1371, __VA_ARGS__) \
+MU_DO_1370(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1372(MACRO, ...) \
+MACRO(1372, __VA_ARGS__) \
+MU_DO_1371(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1373(MACRO, ...) \
+MACRO(1373, __VA_ARGS__) \
+MU_DO_1372(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1374(MACRO, ...) \
+MACRO(1374, __VA_ARGS__) \
+MU_DO_1373(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1375(MACRO, ...) \
+MACRO(1375, __VA_ARGS__) \
+MU_DO_1374(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1376(MACRO, ...) \
+MACRO(1376, __VA_ARGS__) \
+MU_DO_1375(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1377(MACRO, ...) \
+MACRO(1377, __VA_ARGS__) \
+MU_DO_1376(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1378(MACRO, ...) \
+MACRO(1378, __VA_ARGS__) \
+MU_DO_1377(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1379(MACRO, ...) \
+MACRO(1379, __VA_ARGS__) \
+MU_DO_1378(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1380(MACRO, ...) \
+MACRO(1380, __VA_ARGS__) \
+MU_DO_1379(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1381(MACRO, ...) \
+MACRO(1381, __VA_ARGS__) \
+MU_DO_1380(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1382(MACRO, ...) \
+MACRO(1382, __VA_ARGS__) \
+MU_DO_1381(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1383(MACRO, ...) \
+MACRO(1383, __VA_ARGS__) \
+MU_DO_1382(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1384(MACRO, ...) \
+MACRO(1384, __VA_ARGS__) \
+MU_DO_1383(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1385(MACRO, ...) \
+MACRO(1385, __VA_ARGS__) \
+MU_DO_1384(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1386(MACRO, ...) \
+MACRO(1386, __VA_ARGS__) \
+MU_DO_1385(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1387(MACRO, ...) \
+MACRO(1387, __VA_ARGS__) \
+MU_DO_1386(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1388(MACRO, ...) \
+MACRO(1388, __VA_ARGS__) \
+MU_DO_1387(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1389(MACRO, ...) \
+MACRO(1389, __VA_ARGS__) \
+MU_DO_1388(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1390(MACRO, ...) \
+MACRO(1390, __VA_ARGS__) \
+MU_DO_1389(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1391(MACRO, ...) \
+MACRO(1391, __VA_ARGS__) \
+MU_DO_1390(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1392(MACRO, ...) \
+MACRO(1392, __VA_ARGS__) \
+MU_DO_1391(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1393(MACRO, ...) \
+MACRO(1393, __VA_ARGS__) \
+MU_DO_1392(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1394(MACRO, ...) \
+MACRO(1394, __VA_ARGS__) \
+MU_DO_1393(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1395(MACRO, ...) \
+MACRO(1395, __VA_ARGS__) \
+MU_DO_1394(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1396(MACRO, ...) \
+MACRO(1396, __VA_ARGS__) \
+MU_DO_1395(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1397(MACRO, ...) \
+MACRO(1397, __VA_ARGS__) \
+MU_DO_1396(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1398(MACRO, ...) \
+MACRO(1398, __VA_ARGS__) \
+MU_DO_1397(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1399(MACRO, ...) \
+MACRO(1399, __VA_ARGS__) \
+MU_DO_1398(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1400(MACRO, ...) \
+MACRO(1400, __VA_ARGS__) \
+MU_DO_1399(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1401(MACRO, ...) \
+MACRO(1401, __VA_ARGS__) \
+MU_DO_1400(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1402(MACRO, ...) \
+MACRO(1402, __VA_ARGS__) \
+MU_DO_1401(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1403(MACRO, ...) \
+MACRO(1403, __VA_ARGS__) \
+MU_DO_1402(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1404(MACRO, ...) \
+MACRO(1404, __VA_ARGS__) \
+MU_DO_1403(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1405(MACRO, ...) \
+MACRO(1405, __VA_ARGS__) \
+MU_DO_1404(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1406(MACRO, ...) \
+MACRO(1406, __VA_ARGS__) \
+MU_DO_1405(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1407(MACRO, ...) \
+MACRO(1407, __VA_ARGS__) \
+MU_DO_1406(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1408(MACRO, ...) \
+MACRO(1408, __VA_ARGS__) \
+MU_DO_1407(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1409(MACRO, ...) \
+MACRO(1409, __VA_ARGS__) \
+MU_DO_1408(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1410(MACRO, ...) \
+MACRO(1410, __VA_ARGS__) \
+MU_DO_1409(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1411(MACRO, ...) \
+MACRO(1411, __VA_ARGS__) \
+MU_DO_1410(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1412(MACRO, ...) \
+MACRO(1412, __VA_ARGS__) \
+MU_DO_1411(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1413(MACRO, ...) \
+MACRO(1413, __VA_ARGS__) \
+MU_DO_1412(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1414(MACRO, ...) \
+MACRO(1414, __VA_ARGS__) \
+MU_DO_1413(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1415(MACRO, ...) \
+MACRO(1415, __VA_ARGS__) \
+MU_DO_1414(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1416(MACRO, ...) \
+MACRO(1416, __VA_ARGS__) \
+MU_DO_1415(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1417(MACRO, ...) \
+MACRO(1417, __VA_ARGS__) \
+MU_DO_1416(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1418(MACRO, ...) \
+MACRO(1418, __VA_ARGS__) \
+MU_DO_1417(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1419(MACRO, ...) \
+MACRO(1419, __VA_ARGS__) \
+MU_DO_1418(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1420(MACRO, ...) \
+MACRO(1420, __VA_ARGS__) \
+MU_DO_1419(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1421(MACRO, ...) \
+MACRO(1421, __VA_ARGS__) \
+MU_DO_1420(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1422(MACRO, ...) \
+MACRO(1422, __VA_ARGS__) \
+MU_DO_1421(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1423(MACRO, ...) \
+MACRO(1423, __VA_ARGS__) \
+MU_DO_1422(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1424(MACRO, ...) \
+MACRO(1424, __VA_ARGS__) \
+MU_DO_1423(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1425(MACRO, ...) \
+MACRO(1425, __VA_ARGS__) \
+MU_DO_1424(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1426(MACRO, ...) \
+MACRO(1426, __VA_ARGS__) \
+MU_DO_1425(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1427(MACRO, ...) \
+MACRO(1427, __VA_ARGS__) \
+MU_DO_1426(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1428(MACRO, ...) \
+MACRO(1428, __VA_ARGS__) \
+MU_DO_1427(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1429(MACRO, ...) \
+MACRO(1429, __VA_ARGS__) \
+MU_DO_1428(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1430(MACRO, ...) \
+MACRO(1430, __VA_ARGS__) \
+MU_DO_1429(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1431(MACRO, ...) \
+MACRO(1431, __VA_ARGS__) \
+MU_DO_1430(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1432(MACRO, ...) \
+MACRO(1432, __VA_ARGS__) \
+MU_DO_1431(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1433(MACRO, ...) \
+MACRO(1433, __VA_ARGS__) \
+MU_DO_1432(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1434(MACRO, ...) \
+MACRO(1434, __VA_ARGS__) \
+MU_DO_1433(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1435(MACRO, ...) \
+MACRO(1435, __VA_ARGS__) \
+MU_DO_1434(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1436(MACRO, ...) \
+MACRO(1436, __VA_ARGS__) \
+MU_DO_1435(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1437(MACRO, ...) \
+MACRO(1437, __VA_ARGS__) \
+MU_DO_1436(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1438(MACRO, ...) \
+MACRO(1438, __VA_ARGS__) \
+MU_DO_1437(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1439(MACRO, ...) \
+MACRO(1439, __VA_ARGS__) \
+MU_DO_1438(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1440(MACRO, ...) \
+MACRO(1440, __VA_ARGS__) \
+MU_DO_1439(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1441(MACRO, ...) \
+MACRO(1441, __VA_ARGS__) \
+MU_DO_1440(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1442(MACRO, ...) \
+MACRO(1442, __VA_ARGS__) \
+MU_DO_1441(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1443(MACRO, ...) \
+MACRO(1443, __VA_ARGS__) \
+MU_DO_1442(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1444(MACRO, ...) \
+MACRO(1444, __VA_ARGS__) \
+MU_DO_1443(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1445(MACRO, ...) \
+MACRO(1445, __VA_ARGS__) \
+MU_DO_1444(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1446(MACRO, ...) \
+MACRO(1446, __VA_ARGS__) \
+MU_DO_1445(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1447(MACRO, ...) \
+MACRO(1447, __VA_ARGS__) \
+MU_DO_1446(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1448(MACRO, ...) \
+MACRO(1448, __VA_ARGS__) \
+MU_DO_1447(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1449(MACRO, ...) \
+MACRO(1449, __VA_ARGS__) \
+MU_DO_1448(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1450(MACRO, ...) \
+MACRO(1450, __VA_ARGS__) \
+MU_DO_1449(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1451(MACRO, ...) \
+MACRO(1451, __VA_ARGS__) \
+MU_DO_1450(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1452(MACRO, ...) \
+MACRO(1452, __VA_ARGS__) \
+MU_DO_1451(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1453(MACRO, ...) \
+MACRO(1453, __VA_ARGS__) \
+MU_DO_1452(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1454(MACRO, ...) \
+MACRO(1454, __VA_ARGS__) \
+MU_DO_1453(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1455(MACRO, ...) \
+MACRO(1455, __VA_ARGS__) \
+MU_DO_1454(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1456(MACRO, ...) \
+MACRO(1456, __VA_ARGS__) \
+MU_DO_1455(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1457(MACRO, ...) \
+MACRO(1457, __VA_ARGS__) \
+MU_DO_1456(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1458(MACRO, ...) \
+MACRO(1458, __VA_ARGS__) \
+MU_DO_1457(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1459(MACRO, ...) \
+MACRO(1459, __VA_ARGS__) \
+MU_DO_1458(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1460(MACRO, ...) \
+MACRO(1460, __VA_ARGS__) \
+MU_DO_1459(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1461(MACRO, ...) \
+MACRO(1461, __VA_ARGS__) \
+MU_DO_1460(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1462(MACRO, ...) \
+MACRO(1462, __VA_ARGS__) \
+MU_DO_1461(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1463(MACRO, ...) \
+MACRO(1463, __VA_ARGS__) \
+MU_DO_1462(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1464(MACRO, ...) \
+MACRO(1464, __VA_ARGS__) \
+MU_DO_1463(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1465(MACRO, ...) \
+MACRO(1465, __VA_ARGS__) \
+MU_DO_1464(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1466(MACRO, ...) \
+MACRO(1466, __VA_ARGS__) \
+MU_DO_1465(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1467(MACRO, ...) \
+MACRO(1467, __VA_ARGS__) \
+MU_DO_1466(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1468(MACRO, ...) \
+MACRO(1468, __VA_ARGS__) \
+MU_DO_1467(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1469(MACRO, ...) \
+MACRO(1469, __VA_ARGS__) \
+MU_DO_1468(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1470(MACRO, ...) \
+MACRO(1470, __VA_ARGS__) \
+MU_DO_1469(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1471(MACRO, ...) \
+MACRO(1471, __VA_ARGS__) \
+MU_DO_1470(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1472(MACRO, ...) \
+MACRO(1472, __VA_ARGS__) \
+MU_DO_1471(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1473(MACRO, ...) \
+MACRO(1473, __VA_ARGS__) \
+MU_DO_1472(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1474(MACRO, ...) \
+MACRO(1474, __VA_ARGS__) \
+MU_DO_1473(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1475(MACRO, ...) \
+MACRO(1475, __VA_ARGS__) \
+MU_DO_1474(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1476(MACRO, ...) \
+MACRO(1476, __VA_ARGS__) \
+MU_DO_1475(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1477(MACRO, ...) \
+MACRO(1477, __VA_ARGS__) \
+MU_DO_1476(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1478(MACRO, ...) \
+MACRO(1478, __VA_ARGS__) \
+MU_DO_1477(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1479(MACRO, ...) \
+MACRO(1479, __VA_ARGS__) \
+MU_DO_1478(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1480(MACRO, ...) \
+MACRO(1480, __VA_ARGS__) \
+MU_DO_1479(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1481(MACRO, ...) \
+MACRO(1481, __VA_ARGS__) \
+MU_DO_1480(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1482(MACRO, ...) \
+MACRO(1482, __VA_ARGS__) \
+MU_DO_1481(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1483(MACRO, ...) \
+MACRO(1483, __VA_ARGS__) \
+MU_DO_1482(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1484(MACRO, ...) \
+MACRO(1484, __VA_ARGS__) \
+MU_DO_1483(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1485(MACRO, ...) \
+MACRO(1485, __VA_ARGS__) \
+MU_DO_1484(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1486(MACRO, ...) \
+MACRO(1486, __VA_ARGS__) \
+MU_DO_1485(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1487(MACRO, ...) \
+MACRO(1487, __VA_ARGS__) \
+MU_DO_1486(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1488(MACRO, ...) \
+MACRO(1488, __VA_ARGS__) \
+MU_DO_1487(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1489(MACRO, ...) \
+MACRO(1489, __VA_ARGS__) \
+MU_DO_1488(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1490(MACRO, ...) \
+MACRO(1490, __VA_ARGS__) \
+MU_DO_1489(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1491(MACRO, ...) \
+MACRO(1491, __VA_ARGS__) \
+MU_DO_1490(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1492(MACRO, ...) \
+MACRO(1492, __VA_ARGS__) \
+MU_DO_1491(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1493(MACRO, ...) \
+MACRO(1493, __VA_ARGS__) \
+MU_DO_1492(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1494(MACRO, ...) \
+MACRO(1494, __VA_ARGS__) \
+MU_DO_1493(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1495(MACRO, ...) \
+MACRO(1495, __VA_ARGS__) \
+MU_DO_1494(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1496(MACRO, ...) \
+MACRO(1496, __VA_ARGS__) \
+MU_DO_1495(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1497(MACRO, ...) \
+MACRO(1497, __VA_ARGS__) \
+MU_DO_1496(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1498(MACRO, ...) \
+MACRO(1498, __VA_ARGS__) \
+MU_DO_1497(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1499(MACRO, ...) \
+MACRO(1499, __VA_ARGS__) \
+MU_DO_1498(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1500(MACRO, ...) \
+MACRO(1500, __VA_ARGS__) \
+MU_DO_1499(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1501(MACRO, ...) \
+MACRO(1501, __VA_ARGS__) \
+MU_DO_1500(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1502(MACRO, ...) \
+MACRO(1502, __VA_ARGS__) \
+MU_DO_1501(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1503(MACRO, ...) \
+MACRO(1503, __VA_ARGS__) \
+MU_DO_1502(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1504(MACRO, ...) \
+MACRO(1504, __VA_ARGS__) \
+MU_DO_1503(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1505(MACRO, ...) \
+MACRO(1505, __VA_ARGS__) \
+MU_DO_1504(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1506(MACRO, ...) \
+MACRO(1506, __VA_ARGS__) \
+MU_DO_1505(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1507(MACRO, ...) \
+MACRO(1507, __VA_ARGS__) \
+MU_DO_1506(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1508(MACRO, ...) \
+MACRO(1508, __VA_ARGS__) \
+MU_DO_1507(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1509(MACRO, ...) \
+MACRO(1509, __VA_ARGS__) \
+MU_DO_1508(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1510(MACRO, ...) \
+MACRO(1510, __VA_ARGS__) \
+MU_DO_1509(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1511(MACRO, ...) \
+MACRO(1511, __VA_ARGS__) \
+MU_DO_1510(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1512(MACRO, ...) \
+MACRO(1512, __VA_ARGS__) \
+MU_DO_1511(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1513(MACRO, ...) \
+MACRO(1513, __VA_ARGS__) \
+MU_DO_1512(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1514(MACRO, ...) \
+MACRO(1514, __VA_ARGS__) \
+MU_DO_1513(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1515(MACRO, ...) \
+MACRO(1515, __VA_ARGS__) \
+MU_DO_1514(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1516(MACRO, ...) \
+MACRO(1516, __VA_ARGS__) \
+MU_DO_1515(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1517(MACRO, ...) \
+MACRO(1517, __VA_ARGS__) \
+MU_DO_1516(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1518(MACRO, ...) \
+MACRO(1518, __VA_ARGS__) \
+MU_DO_1517(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1519(MACRO, ...) \
+MACRO(1519, __VA_ARGS__) \
+MU_DO_1518(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1520(MACRO, ...) \
+MACRO(1520, __VA_ARGS__) \
+MU_DO_1519(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1521(MACRO, ...) \
+MACRO(1521, __VA_ARGS__) \
+MU_DO_1520(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1522(MACRO, ...) \
+MACRO(1522, __VA_ARGS__) \
+MU_DO_1521(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1523(MACRO, ...) \
+MACRO(1523, __VA_ARGS__) \
+MU_DO_1522(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1524(MACRO, ...) \
+MACRO(1524, __VA_ARGS__) \
+MU_DO_1523(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1525(MACRO, ...) \
+MACRO(1525, __VA_ARGS__) \
+MU_DO_1524(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1526(MACRO, ...) \
+MACRO(1526, __VA_ARGS__) \
+MU_DO_1525(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1527(MACRO, ...) \
+MACRO(1527, __VA_ARGS__) \
+MU_DO_1526(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1528(MACRO, ...) \
+MACRO(1528, __VA_ARGS__) \
+MU_DO_1527(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1529(MACRO, ...) \
+MACRO(1529, __VA_ARGS__) \
+MU_DO_1528(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1530(MACRO, ...) \
+MACRO(1530, __VA_ARGS__) \
+MU_DO_1529(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1531(MACRO, ...) \
+MACRO(1531, __VA_ARGS__) \
+MU_DO_1530(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1532(MACRO, ...) \
+MACRO(1532, __VA_ARGS__) \
+MU_DO_1531(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1533(MACRO, ...) \
+MACRO(1533, __VA_ARGS__) \
+MU_DO_1532(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1534(MACRO, ...) \
+MACRO(1534, __VA_ARGS__) \
+MU_DO_1533(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1535(MACRO, ...) \
+MACRO(1535, __VA_ARGS__) \
+MU_DO_1534(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1536(MACRO, ...) \
+MACRO(1536, __VA_ARGS__) \
+MU_DO_1535(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1537(MACRO, ...) \
+MACRO(1537, __VA_ARGS__) \
+MU_DO_1536(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1538(MACRO, ...) \
+MACRO(1538, __VA_ARGS__) \
+MU_DO_1537(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1539(MACRO, ...) \
+MACRO(1539, __VA_ARGS__) \
+MU_DO_1538(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1540(MACRO, ...) \
+MACRO(1540, __VA_ARGS__) \
+MU_DO_1539(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1541(MACRO, ...) \
+MACRO(1541, __VA_ARGS__) \
+MU_DO_1540(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1542(MACRO, ...) \
+MACRO(1542, __VA_ARGS__) \
+MU_DO_1541(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1543(MACRO, ...) \
+MACRO(1543, __VA_ARGS__) \
+MU_DO_1542(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1544(MACRO, ...) \
+MACRO(1544, __VA_ARGS__) \
+MU_DO_1543(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1545(MACRO, ...) \
+MACRO(1545, __VA_ARGS__) \
+MU_DO_1544(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1546(MACRO, ...) \
+MACRO(1546, __VA_ARGS__) \
+MU_DO_1545(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1547(MACRO, ...) \
+MACRO(1547, __VA_ARGS__) \
+MU_DO_1546(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1548(MACRO, ...) \
+MACRO(1548, __VA_ARGS__) \
+MU_DO_1547(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1549(MACRO, ...) \
+MACRO(1549, __VA_ARGS__) \
+MU_DO_1548(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1550(MACRO, ...) \
+MACRO(1550, __VA_ARGS__) \
+MU_DO_1549(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1551(MACRO, ...) \
+MACRO(1551, __VA_ARGS__) \
+MU_DO_1550(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1552(MACRO, ...) \
+MACRO(1552, __VA_ARGS__) \
+MU_DO_1551(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1553(MACRO, ...) \
+MACRO(1553, __VA_ARGS__) \
+MU_DO_1552(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1554(MACRO, ...) \
+MACRO(1554, __VA_ARGS__) \
+MU_DO_1553(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1555(MACRO, ...) \
+MACRO(1555, __VA_ARGS__) \
+MU_DO_1554(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1556(MACRO, ...) \
+MACRO(1556, __VA_ARGS__) \
+MU_DO_1555(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1557(MACRO, ...) \
+MACRO(1557, __VA_ARGS__) \
+MU_DO_1556(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1558(MACRO, ...) \
+MACRO(1558, __VA_ARGS__) \
+MU_DO_1557(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1559(MACRO, ...) \
+MACRO(1559, __VA_ARGS__) \
+MU_DO_1558(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1560(MACRO, ...) \
+MACRO(1560, __VA_ARGS__) \
+MU_DO_1559(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1561(MACRO, ...) \
+MACRO(1561, __VA_ARGS__) \
+MU_DO_1560(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1562(MACRO, ...) \
+MACRO(1562, __VA_ARGS__) \
+MU_DO_1561(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1563(MACRO, ...) \
+MACRO(1563, __VA_ARGS__) \
+MU_DO_1562(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1564(MACRO, ...) \
+MACRO(1564, __VA_ARGS__) \
+MU_DO_1563(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1565(MACRO, ...) \
+MACRO(1565, __VA_ARGS__) \
+MU_DO_1564(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1566(MACRO, ...) \
+MACRO(1566, __VA_ARGS__) \
+MU_DO_1565(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1567(MACRO, ...) \
+MACRO(1567, __VA_ARGS__) \
+MU_DO_1566(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1568(MACRO, ...) \
+MACRO(1568, __VA_ARGS__) \
+MU_DO_1567(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1569(MACRO, ...) \
+MACRO(1569, __VA_ARGS__) \
+MU_DO_1568(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1570(MACRO, ...) \
+MACRO(1570, __VA_ARGS__) \
+MU_DO_1569(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1571(MACRO, ...) \
+MACRO(1571, __VA_ARGS__) \
+MU_DO_1570(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1572(MACRO, ...) \
+MACRO(1572, __VA_ARGS__) \
+MU_DO_1571(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1573(MACRO, ...) \
+MACRO(1573, __VA_ARGS__) \
+MU_DO_1572(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1574(MACRO, ...) \
+MACRO(1574, __VA_ARGS__) \
+MU_DO_1573(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1575(MACRO, ...) \
+MACRO(1575, __VA_ARGS__) \
+MU_DO_1574(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1576(MACRO, ...) \
+MACRO(1576, __VA_ARGS__) \
+MU_DO_1575(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1577(MACRO, ...) \
+MACRO(1577, __VA_ARGS__) \
+MU_DO_1576(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1578(MACRO, ...) \
+MACRO(1578, __VA_ARGS__) \
+MU_DO_1577(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1579(MACRO, ...) \
+MACRO(1579, __VA_ARGS__) \
+MU_DO_1578(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1580(MACRO, ...) \
+MACRO(1580, __VA_ARGS__) \
+MU_DO_1579(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1581(MACRO, ...) \
+MACRO(1581, __VA_ARGS__) \
+MU_DO_1580(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1582(MACRO, ...) \
+MACRO(1582, __VA_ARGS__) \
+MU_DO_1581(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1583(MACRO, ...) \
+MACRO(1583, __VA_ARGS__) \
+MU_DO_1582(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1584(MACRO, ...) \
+MACRO(1584, __VA_ARGS__) \
+MU_DO_1583(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1585(MACRO, ...) \
+MACRO(1585, __VA_ARGS__) \
+MU_DO_1584(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1586(MACRO, ...) \
+MACRO(1586, __VA_ARGS__) \
+MU_DO_1585(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1587(MACRO, ...) \
+MACRO(1587, __VA_ARGS__) \
+MU_DO_1586(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1588(MACRO, ...) \
+MACRO(1588, __VA_ARGS__) \
+MU_DO_1587(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1589(MACRO, ...) \
+MACRO(1589, __VA_ARGS__) \
+MU_DO_1588(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1590(MACRO, ...) \
+MACRO(1590, __VA_ARGS__) \
+MU_DO_1589(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1591(MACRO, ...) \
+MACRO(1591, __VA_ARGS__) \
+MU_DO_1590(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1592(MACRO, ...) \
+MACRO(1592, __VA_ARGS__) \
+MU_DO_1591(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1593(MACRO, ...) \
+MACRO(1593, __VA_ARGS__) \
+MU_DO_1592(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1594(MACRO, ...) \
+MACRO(1594, __VA_ARGS__) \
+MU_DO_1593(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1595(MACRO, ...) \
+MACRO(1595, __VA_ARGS__) \
+MU_DO_1594(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1596(MACRO, ...) \
+MACRO(1596, __VA_ARGS__) \
+MU_DO_1595(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1597(MACRO, ...) \
+MACRO(1597, __VA_ARGS__) \
+MU_DO_1596(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1598(MACRO, ...) \
+MACRO(1598, __VA_ARGS__) \
+MU_DO_1597(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1599(MACRO, ...) \
+MACRO(1599, __VA_ARGS__) \
+MU_DO_1598(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1600(MACRO, ...) \
+MACRO(1600, __VA_ARGS__) \
+MU_DO_1599(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1601(MACRO, ...) \
+MACRO(1601, __VA_ARGS__) \
+MU_DO_1600(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1602(MACRO, ...) \
+MACRO(1602, __VA_ARGS__) \
+MU_DO_1601(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1603(MACRO, ...) \
+MACRO(1603, __VA_ARGS__) \
+MU_DO_1602(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1604(MACRO, ...) \
+MACRO(1604, __VA_ARGS__) \
+MU_DO_1603(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1605(MACRO, ...) \
+MACRO(1605, __VA_ARGS__) \
+MU_DO_1604(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1606(MACRO, ...) \
+MACRO(1606, __VA_ARGS__) \
+MU_DO_1605(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1607(MACRO, ...) \
+MACRO(1607, __VA_ARGS__) \
+MU_DO_1606(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1608(MACRO, ...) \
+MACRO(1608, __VA_ARGS__) \
+MU_DO_1607(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1609(MACRO, ...) \
+MACRO(1609, __VA_ARGS__) \
+MU_DO_1608(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1610(MACRO, ...) \
+MACRO(1610, __VA_ARGS__) \
+MU_DO_1609(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1611(MACRO, ...) \
+MACRO(1611, __VA_ARGS__) \
+MU_DO_1610(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1612(MACRO, ...) \
+MACRO(1612, __VA_ARGS__) \
+MU_DO_1611(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1613(MACRO, ...) \
+MACRO(1613, __VA_ARGS__) \
+MU_DO_1612(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1614(MACRO, ...) \
+MACRO(1614, __VA_ARGS__) \
+MU_DO_1613(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1615(MACRO, ...) \
+MACRO(1615, __VA_ARGS__) \
+MU_DO_1614(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1616(MACRO, ...) \
+MACRO(1616, __VA_ARGS__) \
+MU_DO_1615(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1617(MACRO, ...) \
+MACRO(1617, __VA_ARGS__) \
+MU_DO_1616(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1618(MACRO, ...) \
+MACRO(1618, __VA_ARGS__) \
+MU_DO_1617(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1619(MACRO, ...) \
+MACRO(1619, __VA_ARGS__) \
+MU_DO_1618(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1620(MACRO, ...) \
+MACRO(1620, __VA_ARGS__) \
+MU_DO_1619(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1621(MACRO, ...) \
+MACRO(1621, __VA_ARGS__) \
+MU_DO_1620(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1622(MACRO, ...) \
+MACRO(1622, __VA_ARGS__) \
+MU_DO_1621(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1623(MACRO, ...) \
+MACRO(1623, __VA_ARGS__) \
+MU_DO_1622(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1624(MACRO, ...) \
+MACRO(1624, __VA_ARGS__) \
+MU_DO_1623(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1625(MACRO, ...) \
+MACRO(1625, __VA_ARGS__) \
+MU_DO_1624(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1626(MACRO, ...) \
+MACRO(1626, __VA_ARGS__) \
+MU_DO_1625(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1627(MACRO, ...) \
+MACRO(1627, __VA_ARGS__) \
+MU_DO_1626(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1628(MACRO, ...) \
+MACRO(1628, __VA_ARGS__) \
+MU_DO_1627(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1629(MACRO, ...) \
+MACRO(1629, __VA_ARGS__) \
+MU_DO_1628(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1630(MACRO, ...) \
+MACRO(1630, __VA_ARGS__) \
+MU_DO_1629(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1631(MACRO, ...) \
+MACRO(1631, __VA_ARGS__) \
+MU_DO_1630(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1632(MACRO, ...) \
+MACRO(1632, __VA_ARGS__) \
+MU_DO_1631(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1633(MACRO, ...) \
+MACRO(1633, __VA_ARGS__) \
+MU_DO_1632(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1634(MACRO, ...) \
+MACRO(1634, __VA_ARGS__) \
+MU_DO_1633(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1635(MACRO, ...) \
+MACRO(1635, __VA_ARGS__) \
+MU_DO_1634(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1636(MACRO, ...) \
+MACRO(1636, __VA_ARGS__) \
+MU_DO_1635(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1637(MACRO, ...) \
+MACRO(1637, __VA_ARGS__) \
+MU_DO_1636(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1638(MACRO, ...) \
+MACRO(1638, __VA_ARGS__) \
+MU_DO_1637(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1639(MACRO, ...) \
+MACRO(1639, __VA_ARGS__) \
+MU_DO_1638(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1640(MACRO, ...) \
+MACRO(1640, __VA_ARGS__) \
+MU_DO_1639(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1641(MACRO, ...) \
+MACRO(1641, __VA_ARGS__) \
+MU_DO_1640(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1642(MACRO, ...) \
+MACRO(1642, __VA_ARGS__) \
+MU_DO_1641(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1643(MACRO, ...) \
+MACRO(1643, __VA_ARGS__) \
+MU_DO_1642(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1644(MACRO, ...) \
+MACRO(1644, __VA_ARGS__) \
+MU_DO_1643(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1645(MACRO, ...) \
+MACRO(1645, __VA_ARGS__) \
+MU_DO_1644(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1646(MACRO, ...) \
+MACRO(1646, __VA_ARGS__) \
+MU_DO_1645(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1647(MACRO, ...) \
+MACRO(1647, __VA_ARGS__) \
+MU_DO_1646(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1648(MACRO, ...) \
+MACRO(1648, __VA_ARGS__) \
+MU_DO_1647(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1649(MACRO, ...) \
+MACRO(1649, __VA_ARGS__) \
+MU_DO_1648(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1650(MACRO, ...) \
+MACRO(1650, __VA_ARGS__) \
+MU_DO_1649(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1651(MACRO, ...) \
+MACRO(1651, __VA_ARGS__) \
+MU_DO_1650(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1652(MACRO, ...) \
+MACRO(1652, __VA_ARGS__) \
+MU_DO_1651(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1653(MACRO, ...) \
+MACRO(1653, __VA_ARGS__) \
+MU_DO_1652(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1654(MACRO, ...) \
+MACRO(1654, __VA_ARGS__) \
+MU_DO_1653(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1655(MACRO, ...) \
+MACRO(1655, __VA_ARGS__) \
+MU_DO_1654(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1656(MACRO, ...) \
+MACRO(1656, __VA_ARGS__) \
+MU_DO_1655(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1657(MACRO, ...) \
+MACRO(1657, __VA_ARGS__) \
+MU_DO_1656(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1658(MACRO, ...) \
+MACRO(1658, __VA_ARGS__) \
+MU_DO_1657(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1659(MACRO, ...) \
+MACRO(1659, __VA_ARGS__) \
+MU_DO_1658(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1660(MACRO, ...) \
+MACRO(1660, __VA_ARGS__) \
+MU_DO_1659(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1661(MACRO, ...) \
+MACRO(1661, __VA_ARGS__) \
+MU_DO_1660(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1662(MACRO, ...) \
+MACRO(1662, __VA_ARGS__) \
+MU_DO_1661(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1663(MACRO, ...) \
+MACRO(1663, __VA_ARGS__) \
+MU_DO_1662(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1664(MACRO, ...) \
+MACRO(1664, __VA_ARGS__) \
+MU_DO_1663(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1665(MACRO, ...) \
+MACRO(1665, __VA_ARGS__) \
+MU_DO_1664(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1666(MACRO, ...) \
+MACRO(1666, __VA_ARGS__) \
+MU_DO_1665(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1667(MACRO, ...) \
+MACRO(1667, __VA_ARGS__) \
+MU_DO_1666(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1668(MACRO, ...) \
+MACRO(1668, __VA_ARGS__) \
+MU_DO_1667(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1669(MACRO, ...) \
+MACRO(1669, __VA_ARGS__) \
+MU_DO_1668(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1670(MACRO, ...) \
+MACRO(1670, __VA_ARGS__) \
+MU_DO_1669(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1671(MACRO, ...) \
+MACRO(1671, __VA_ARGS__) \
+MU_DO_1670(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1672(MACRO, ...) \
+MACRO(1672, __VA_ARGS__) \
+MU_DO_1671(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1673(MACRO, ...) \
+MACRO(1673, __VA_ARGS__) \
+MU_DO_1672(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1674(MACRO, ...) \
+MACRO(1674, __VA_ARGS__) \
+MU_DO_1673(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1675(MACRO, ...) \
+MACRO(1675, __VA_ARGS__) \
+MU_DO_1674(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1676(MACRO, ...) \
+MACRO(1676, __VA_ARGS__) \
+MU_DO_1675(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1677(MACRO, ...) \
+MACRO(1677, __VA_ARGS__) \
+MU_DO_1676(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1678(MACRO, ...) \
+MACRO(1678, __VA_ARGS__) \
+MU_DO_1677(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1679(MACRO, ...) \
+MACRO(1679, __VA_ARGS__) \
+MU_DO_1678(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1680(MACRO, ...) \
+MACRO(1680, __VA_ARGS__) \
+MU_DO_1679(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1681(MACRO, ...) \
+MACRO(1681, __VA_ARGS__) \
+MU_DO_1680(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1682(MACRO, ...) \
+MACRO(1682, __VA_ARGS__) \
+MU_DO_1681(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1683(MACRO, ...) \
+MACRO(1683, __VA_ARGS__) \
+MU_DO_1682(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1684(MACRO, ...) \
+MACRO(1684, __VA_ARGS__) \
+MU_DO_1683(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1685(MACRO, ...) \
+MACRO(1685, __VA_ARGS__) \
+MU_DO_1684(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1686(MACRO, ...) \
+MACRO(1686, __VA_ARGS__) \
+MU_DO_1685(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1687(MACRO, ...) \
+MACRO(1687, __VA_ARGS__) \
+MU_DO_1686(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1688(MACRO, ...) \
+MACRO(1688, __VA_ARGS__) \
+MU_DO_1687(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1689(MACRO, ...) \
+MACRO(1689, __VA_ARGS__) \
+MU_DO_1688(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1690(MACRO, ...) \
+MACRO(1690, __VA_ARGS__) \
+MU_DO_1689(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1691(MACRO, ...) \
+MACRO(1691, __VA_ARGS__) \
+MU_DO_1690(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1692(MACRO, ...) \
+MACRO(1692, __VA_ARGS__) \
+MU_DO_1691(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1693(MACRO, ...) \
+MACRO(1693, __VA_ARGS__) \
+MU_DO_1692(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1694(MACRO, ...) \
+MACRO(1694, __VA_ARGS__) \
+MU_DO_1693(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1695(MACRO, ...) \
+MACRO(1695, __VA_ARGS__) \
+MU_DO_1694(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1696(MACRO, ...) \
+MACRO(1696, __VA_ARGS__) \
+MU_DO_1695(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1697(MACRO, ...) \
+MACRO(1697, __VA_ARGS__) \
+MU_DO_1696(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1698(MACRO, ...) \
+MACRO(1698, __VA_ARGS__) \
+MU_DO_1697(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1699(MACRO, ...) \
+MACRO(1699, __VA_ARGS__) \
+MU_DO_1698(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1700(MACRO, ...) \
+MACRO(1700, __VA_ARGS__) \
+MU_DO_1699(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1701(MACRO, ...) \
+MACRO(1701, __VA_ARGS__) \
+MU_DO_1700(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1702(MACRO, ...) \
+MACRO(1702, __VA_ARGS__) \
+MU_DO_1701(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1703(MACRO, ...) \
+MACRO(1703, __VA_ARGS__) \
+MU_DO_1702(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1704(MACRO, ...) \
+MACRO(1704, __VA_ARGS__) \
+MU_DO_1703(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1705(MACRO, ...) \
+MACRO(1705, __VA_ARGS__) \
+MU_DO_1704(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1706(MACRO, ...) \
+MACRO(1706, __VA_ARGS__) \
+MU_DO_1705(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1707(MACRO, ...) \
+MACRO(1707, __VA_ARGS__) \
+MU_DO_1706(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1708(MACRO, ...) \
+MACRO(1708, __VA_ARGS__) \
+MU_DO_1707(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1709(MACRO, ...) \
+MACRO(1709, __VA_ARGS__) \
+MU_DO_1708(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1710(MACRO, ...) \
+MACRO(1710, __VA_ARGS__) \
+MU_DO_1709(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1711(MACRO, ...) \
+MACRO(1711, __VA_ARGS__) \
+MU_DO_1710(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1712(MACRO, ...) \
+MACRO(1712, __VA_ARGS__) \
+MU_DO_1711(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1713(MACRO, ...) \
+MACRO(1713, __VA_ARGS__) \
+MU_DO_1712(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1714(MACRO, ...) \
+MACRO(1714, __VA_ARGS__) \
+MU_DO_1713(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1715(MACRO, ...) \
+MACRO(1715, __VA_ARGS__) \
+MU_DO_1714(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1716(MACRO, ...) \
+MACRO(1716, __VA_ARGS__) \
+MU_DO_1715(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1717(MACRO, ...) \
+MACRO(1717, __VA_ARGS__) \
+MU_DO_1716(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1718(MACRO, ...) \
+MACRO(1718, __VA_ARGS__) \
+MU_DO_1717(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1719(MACRO, ...) \
+MACRO(1719, __VA_ARGS__) \
+MU_DO_1718(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1720(MACRO, ...) \
+MACRO(1720, __VA_ARGS__) \
+MU_DO_1719(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1721(MACRO, ...) \
+MACRO(1721, __VA_ARGS__) \
+MU_DO_1720(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1722(MACRO, ...) \
+MACRO(1722, __VA_ARGS__) \
+MU_DO_1721(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1723(MACRO, ...) \
+MACRO(1723, __VA_ARGS__) \
+MU_DO_1722(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1724(MACRO, ...) \
+MACRO(1724, __VA_ARGS__) \
+MU_DO_1723(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1725(MACRO, ...) \
+MACRO(1725, __VA_ARGS__) \
+MU_DO_1724(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1726(MACRO, ...) \
+MACRO(1726, __VA_ARGS__) \
+MU_DO_1725(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1727(MACRO, ...) \
+MACRO(1727, __VA_ARGS__) \
+MU_DO_1726(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1728(MACRO, ...) \
+MACRO(1728, __VA_ARGS__) \
+MU_DO_1727(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1729(MACRO, ...) \
+MACRO(1729, __VA_ARGS__) \
+MU_DO_1728(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1730(MACRO, ...) \
+MACRO(1730, __VA_ARGS__) \
+MU_DO_1729(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1731(MACRO, ...) \
+MACRO(1731, __VA_ARGS__) \
+MU_DO_1730(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1732(MACRO, ...) \
+MACRO(1732, __VA_ARGS__) \
+MU_DO_1731(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1733(MACRO, ...) \
+MACRO(1733, __VA_ARGS__) \
+MU_DO_1732(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1734(MACRO, ...) \
+MACRO(1734, __VA_ARGS__) \
+MU_DO_1733(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1735(MACRO, ...) \
+MACRO(1735, __VA_ARGS__) \
+MU_DO_1734(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1736(MACRO, ...) \
+MACRO(1736, __VA_ARGS__) \
+MU_DO_1735(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1737(MACRO, ...) \
+MACRO(1737, __VA_ARGS__) \
+MU_DO_1736(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1738(MACRO, ...) \
+MACRO(1738, __VA_ARGS__) \
+MU_DO_1737(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1739(MACRO, ...) \
+MACRO(1739, __VA_ARGS__) \
+MU_DO_1738(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1740(MACRO, ...) \
+MACRO(1740, __VA_ARGS__) \
+MU_DO_1739(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1741(MACRO, ...) \
+MACRO(1741, __VA_ARGS__) \
+MU_DO_1740(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1742(MACRO, ...) \
+MACRO(1742, __VA_ARGS__) \
+MU_DO_1741(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1743(MACRO, ...) \
+MACRO(1743, __VA_ARGS__) \
+MU_DO_1742(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1744(MACRO, ...) \
+MACRO(1744, __VA_ARGS__) \
+MU_DO_1743(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1745(MACRO, ...) \
+MACRO(1745, __VA_ARGS__) \
+MU_DO_1744(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1746(MACRO, ...) \
+MACRO(1746, __VA_ARGS__) \
+MU_DO_1745(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1747(MACRO, ...) \
+MACRO(1747, __VA_ARGS__) \
+MU_DO_1746(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1748(MACRO, ...) \
+MACRO(1748, __VA_ARGS__) \
+MU_DO_1747(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1749(MACRO, ...) \
+MACRO(1749, __VA_ARGS__) \
+MU_DO_1748(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1750(MACRO, ...) \
+MACRO(1750, __VA_ARGS__) \
+MU_DO_1749(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1751(MACRO, ...) \
+MACRO(1751, __VA_ARGS__) \
+MU_DO_1750(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1752(MACRO, ...) \
+MACRO(1752, __VA_ARGS__) \
+MU_DO_1751(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1753(MACRO, ...) \
+MACRO(1753, __VA_ARGS__) \
+MU_DO_1752(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1754(MACRO, ...) \
+MACRO(1754, __VA_ARGS__) \
+MU_DO_1753(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1755(MACRO, ...) \
+MACRO(1755, __VA_ARGS__) \
+MU_DO_1754(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1756(MACRO, ...) \
+MACRO(1756, __VA_ARGS__) \
+MU_DO_1755(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1757(MACRO, ...) \
+MACRO(1757, __VA_ARGS__) \
+MU_DO_1756(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1758(MACRO, ...) \
+MACRO(1758, __VA_ARGS__) \
+MU_DO_1757(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1759(MACRO, ...) \
+MACRO(1759, __VA_ARGS__) \
+MU_DO_1758(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1760(MACRO, ...) \
+MACRO(1760, __VA_ARGS__) \
+MU_DO_1759(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1761(MACRO, ...) \
+MACRO(1761, __VA_ARGS__) \
+MU_DO_1760(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1762(MACRO, ...) \
+MACRO(1762, __VA_ARGS__) \
+MU_DO_1761(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1763(MACRO, ...) \
+MACRO(1763, __VA_ARGS__) \
+MU_DO_1762(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1764(MACRO, ...) \
+MACRO(1764, __VA_ARGS__) \
+MU_DO_1763(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1765(MACRO, ...) \
+MACRO(1765, __VA_ARGS__) \
+MU_DO_1764(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1766(MACRO, ...) \
+MACRO(1766, __VA_ARGS__) \
+MU_DO_1765(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1767(MACRO, ...) \
+MACRO(1767, __VA_ARGS__) \
+MU_DO_1766(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1768(MACRO, ...) \
+MACRO(1768, __VA_ARGS__) \
+MU_DO_1767(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1769(MACRO, ...) \
+MACRO(1769, __VA_ARGS__) \
+MU_DO_1768(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1770(MACRO, ...) \
+MACRO(1770, __VA_ARGS__) \
+MU_DO_1769(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1771(MACRO, ...) \
+MACRO(1771, __VA_ARGS__) \
+MU_DO_1770(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1772(MACRO, ...) \
+MACRO(1772, __VA_ARGS__) \
+MU_DO_1771(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1773(MACRO, ...) \
+MACRO(1773, __VA_ARGS__) \
+MU_DO_1772(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1774(MACRO, ...) \
+MACRO(1774, __VA_ARGS__) \
+MU_DO_1773(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1775(MACRO, ...) \
+MACRO(1775, __VA_ARGS__) \
+MU_DO_1774(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1776(MACRO, ...) \
+MACRO(1776, __VA_ARGS__) \
+MU_DO_1775(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1777(MACRO, ...) \
+MACRO(1777, __VA_ARGS__) \
+MU_DO_1776(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1778(MACRO, ...) \
+MACRO(1778, __VA_ARGS__) \
+MU_DO_1777(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1779(MACRO, ...) \
+MACRO(1779, __VA_ARGS__) \
+MU_DO_1778(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1780(MACRO, ...) \
+MACRO(1780, __VA_ARGS__) \
+MU_DO_1779(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1781(MACRO, ...) \
+MACRO(1781, __VA_ARGS__) \
+MU_DO_1780(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1782(MACRO, ...) \
+MACRO(1782, __VA_ARGS__) \
+MU_DO_1781(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1783(MACRO, ...) \
+MACRO(1783, __VA_ARGS__) \
+MU_DO_1782(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1784(MACRO, ...) \
+MACRO(1784, __VA_ARGS__) \
+MU_DO_1783(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1785(MACRO, ...) \
+MACRO(1785, __VA_ARGS__) \
+MU_DO_1784(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1786(MACRO, ...) \
+MACRO(1786, __VA_ARGS__) \
+MU_DO_1785(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1787(MACRO, ...) \
+MACRO(1787, __VA_ARGS__) \
+MU_DO_1786(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1788(MACRO, ...) \
+MACRO(1788, __VA_ARGS__) \
+MU_DO_1787(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1789(MACRO, ...) \
+MACRO(1789, __VA_ARGS__) \
+MU_DO_1788(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1790(MACRO, ...) \
+MACRO(1790, __VA_ARGS__) \
+MU_DO_1789(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1791(MACRO, ...) \
+MACRO(1791, __VA_ARGS__) \
+MU_DO_1790(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1792(MACRO, ...) \
+MACRO(1792, __VA_ARGS__) \
+MU_DO_1791(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1793(MACRO, ...) \
+MACRO(1793, __VA_ARGS__) \
+MU_DO_1792(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1794(MACRO, ...) \
+MACRO(1794, __VA_ARGS__) \
+MU_DO_1793(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1795(MACRO, ...) \
+MACRO(1795, __VA_ARGS__) \
+MU_DO_1794(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1796(MACRO, ...) \
+MACRO(1796, __VA_ARGS__) \
+MU_DO_1795(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1797(MACRO, ...) \
+MACRO(1797, __VA_ARGS__) \
+MU_DO_1796(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1798(MACRO, ...) \
+MACRO(1798, __VA_ARGS__) \
+MU_DO_1797(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1799(MACRO, ...) \
+MACRO(1799, __VA_ARGS__) \
+MU_DO_1798(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1800(MACRO, ...) \
+MACRO(1800, __VA_ARGS__) \
+MU_DO_1799(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1801(MACRO, ...) \
+MACRO(1801, __VA_ARGS__) \
+MU_DO_1800(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1802(MACRO, ...) \
+MACRO(1802, __VA_ARGS__) \
+MU_DO_1801(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1803(MACRO, ...) \
+MACRO(1803, __VA_ARGS__) \
+MU_DO_1802(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1804(MACRO, ...) \
+MACRO(1804, __VA_ARGS__) \
+MU_DO_1803(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1805(MACRO, ...) \
+MACRO(1805, __VA_ARGS__) \
+MU_DO_1804(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1806(MACRO, ...) \
+MACRO(1806, __VA_ARGS__) \
+MU_DO_1805(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1807(MACRO, ...) \
+MACRO(1807, __VA_ARGS__) \
+MU_DO_1806(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1808(MACRO, ...) \
+MACRO(1808, __VA_ARGS__) \
+MU_DO_1807(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1809(MACRO, ...) \
+MACRO(1809, __VA_ARGS__) \
+MU_DO_1808(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1810(MACRO, ...) \
+MACRO(1810, __VA_ARGS__) \
+MU_DO_1809(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1811(MACRO, ...) \
+MACRO(1811, __VA_ARGS__) \
+MU_DO_1810(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1812(MACRO, ...) \
+MACRO(1812, __VA_ARGS__) \
+MU_DO_1811(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1813(MACRO, ...) \
+MACRO(1813, __VA_ARGS__) \
+MU_DO_1812(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1814(MACRO, ...) \
+MACRO(1814, __VA_ARGS__) \
+MU_DO_1813(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1815(MACRO, ...) \
+MACRO(1815, __VA_ARGS__) \
+MU_DO_1814(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1816(MACRO, ...) \
+MACRO(1816, __VA_ARGS__) \
+MU_DO_1815(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1817(MACRO, ...) \
+MACRO(1817, __VA_ARGS__) \
+MU_DO_1816(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1818(MACRO, ...) \
+MACRO(1818, __VA_ARGS__) \
+MU_DO_1817(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1819(MACRO, ...) \
+MACRO(1819, __VA_ARGS__) \
+MU_DO_1818(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1820(MACRO, ...) \
+MACRO(1820, __VA_ARGS__) \
+MU_DO_1819(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1821(MACRO, ...) \
+MACRO(1821, __VA_ARGS__) \
+MU_DO_1820(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1822(MACRO, ...) \
+MACRO(1822, __VA_ARGS__) \
+MU_DO_1821(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1823(MACRO, ...) \
+MACRO(1823, __VA_ARGS__) \
+MU_DO_1822(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1824(MACRO, ...) \
+MACRO(1824, __VA_ARGS__) \
+MU_DO_1823(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1825(MACRO, ...) \
+MACRO(1825, __VA_ARGS__) \
+MU_DO_1824(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1826(MACRO, ...) \
+MACRO(1826, __VA_ARGS__) \
+MU_DO_1825(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1827(MACRO, ...) \
+MACRO(1827, __VA_ARGS__) \
+MU_DO_1826(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1828(MACRO, ...) \
+MACRO(1828, __VA_ARGS__) \
+MU_DO_1827(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1829(MACRO, ...) \
+MACRO(1829, __VA_ARGS__) \
+MU_DO_1828(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1830(MACRO, ...) \
+MACRO(1830, __VA_ARGS__) \
+MU_DO_1829(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1831(MACRO, ...) \
+MACRO(1831, __VA_ARGS__) \
+MU_DO_1830(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1832(MACRO, ...) \
+MACRO(1832, __VA_ARGS__) \
+MU_DO_1831(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1833(MACRO, ...) \
+MACRO(1833, __VA_ARGS__) \
+MU_DO_1832(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1834(MACRO, ...) \
+MACRO(1834, __VA_ARGS__) \
+MU_DO_1833(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1835(MACRO, ...) \
+MACRO(1835, __VA_ARGS__) \
+MU_DO_1834(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1836(MACRO, ...) \
+MACRO(1836, __VA_ARGS__) \
+MU_DO_1835(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1837(MACRO, ...) \
+MACRO(1837, __VA_ARGS__) \
+MU_DO_1836(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1838(MACRO, ...) \
+MACRO(1838, __VA_ARGS__) \
+MU_DO_1837(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1839(MACRO, ...) \
+MACRO(1839, __VA_ARGS__) \
+MU_DO_1838(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1840(MACRO, ...) \
+MACRO(1840, __VA_ARGS__) \
+MU_DO_1839(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1841(MACRO, ...) \
+MACRO(1841, __VA_ARGS__) \
+MU_DO_1840(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1842(MACRO, ...) \
+MACRO(1842, __VA_ARGS__) \
+MU_DO_1841(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1843(MACRO, ...) \
+MACRO(1843, __VA_ARGS__) \
+MU_DO_1842(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1844(MACRO, ...) \
+MACRO(1844, __VA_ARGS__) \
+MU_DO_1843(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1845(MACRO, ...) \
+MACRO(1845, __VA_ARGS__) \
+MU_DO_1844(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1846(MACRO, ...) \
+MACRO(1846, __VA_ARGS__) \
+MU_DO_1845(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1847(MACRO, ...) \
+MACRO(1847, __VA_ARGS__) \
+MU_DO_1846(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1848(MACRO, ...) \
+MACRO(1848, __VA_ARGS__) \
+MU_DO_1847(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1849(MACRO, ...) \
+MACRO(1849, __VA_ARGS__) \
+MU_DO_1848(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1850(MACRO, ...) \
+MACRO(1850, __VA_ARGS__) \
+MU_DO_1849(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1851(MACRO, ...) \
+MACRO(1851, __VA_ARGS__) \
+MU_DO_1850(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1852(MACRO, ...) \
+MACRO(1852, __VA_ARGS__) \
+MU_DO_1851(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1853(MACRO, ...) \
+MACRO(1853, __VA_ARGS__) \
+MU_DO_1852(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1854(MACRO, ...) \
+MACRO(1854, __VA_ARGS__) \
+MU_DO_1853(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1855(MACRO, ...) \
+MACRO(1855, __VA_ARGS__) \
+MU_DO_1854(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1856(MACRO, ...) \
+MACRO(1856, __VA_ARGS__) \
+MU_DO_1855(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1857(MACRO, ...) \
+MACRO(1857, __VA_ARGS__) \
+MU_DO_1856(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1858(MACRO, ...) \
+MACRO(1858, __VA_ARGS__) \
+MU_DO_1857(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1859(MACRO, ...) \
+MACRO(1859, __VA_ARGS__) \
+MU_DO_1858(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1860(MACRO, ...) \
+MACRO(1860, __VA_ARGS__) \
+MU_DO_1859(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1861(MACRO, ...) \
+MACRO(1861, __VA_ARGS__) \
+MU_DO_1860(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1862(MACRO, ...) \
+MACRO(1862, __VA_ARGS__) \
+MU_DO_1861(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1863(MACRO, ...) \
+MACRO(1863, __VA_ARGS__) \
+MU_DO_1862(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1864(MACRO, ...) \
+MACRO(1864, __VA_ARGS__) \
+MU_DO_1863(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1865(MACRO, ...) \
+MACRO(1865, __VA_ARGS__) \
+MU_DO_1864(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1866(MACRO, ...) \
+MACRO(1866, __VA_ARGS__) \
+MU_DO_1865(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1867(MACRO, ...) \
+MACRO(1867, __VA_ARGS__) \
+MU_DO_1866(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1868(MACRO, ...) \
+MACRO(1868, __VA_ARGS__) \
+MU_DO_1867(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1869(MACRO, ...) \
+MACRO(1869, __VA_ARGS__) \
+MU_DO_1868(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1870(MACRO, ...) \
+MACRO(1870, __VA_ARGS__) \
+MU_DO_1869(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1871(MACRO, ...) \
+MACRO(1871, __VA_ARGS__) \
+MU_DO_1870(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1872(MACRO, ...) \
+MACRO(1872, __VA_ARGS__) \
+MU_DO_1871(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1873(MACRO, ...) \
+MACRO(1873, __VA_ARGS__) \
+MU_DO_1872(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1874(MACRO, ...) \
+MACRO(1874, __VA_ARGS__) \
+MU_DO_1873(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1875(MACRO, ...) \
+MACRO(1875, __VA_ARGS__) \
+MU_DO_1874(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1876(MACRO, ...) \
+MACRO(1876, __VA_ARGS__) \
+MU_DO_1875(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1877(MACRO, ...) \
+MACRO(1877, __VA_ARGS__) \
+MU_DO_1876(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1878(MACRO, ...) \
+MACRO(1878, __VA_ARGS__) \
+MU_DO_1877(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1879(MACRO, ...) \
+MACRO(1879, __VA_ARGS__) \
+MU_DO_1878(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1880(MACRO, ...) \
+MACRO(1880, __VA_ARGS__) \
+MU_DO_1879(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1881(MACRO, ...) \
+MACRO(1881, __VA_ARGS__) \
+MU_DO_1880(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1882(MACRO, ...) \
+MACRO(1882, __VA_ARGS__) \
+MU_DO_1881(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1883(MACRO, ...) \
+MACRO(1883, __VA_ARGS__) \
+MU_DO_1882(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1884(MACRO, ...) \
+MACRO(1884, __VA_ARGS__) \
+MU_DO_1883(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1885(MACRO, ...) \
+MACRO(1885, __VA_ARGS__) \
+MU_DO_1884(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1886(MACRO, ...) \
+MACRO(1886, __VA_ARGS__) \
+MU_DO_1885(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1887(MACRO, ...) \
+MACRO(1887, __VA_ARGS__) \
+MU_DO_1886(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1888(MACRO, ...) \
+MACRO(1888, __VA_ARGS__) \
+MU_DO_1887(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1889(MACRO, ...) \
+MACRO(1889, __VA_ARGS__) \
+MU_DO_1888(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1890(MACRO, ...) \
+MACRO(1890, __VA_ARGS__) \
+MU_DO_1889(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1891(MACRO, ...) \
+MACRO(1891, __VA_ARGS__) \
+MU_DO_1890(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1892(MACRO, ...) \
+MACRO(1892, __VA_ARGS__) \
+MU_DO_1891(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1893(MACRO, ...) \
+MACRO(1893, __VA_ARGS__) \
+MU_DO_1892(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1894(MACRO, ...) \
+MACRO(1894, __VA_ARGS__) \
+MU_DO_1893(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1895(MACRO, ...) \
+MACRO(1895, __VA_ARGS__) \
+MU_DO_1894(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1896(MACRO, ...) \
+MACRO(1896, __VA_ARGS__) \
+MU_DO_1895(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1897(MACRO, ...) \
+MACRO(1897, __VA_ARGS__) \
+MU_DO_1896(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1898(MACRO, ...) \
+MACRO(1898, __VA_ARGS__) \
+MU_DO_1897(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1899(MACRO, ...) \
+MACRO(1899, __VA_ARGS__) \
+MU_DO_1898(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1900(MACRO, ...) \
+MACRO(1900, __VA_ARGS__) \
+MU_DO_1899(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1901(MACRO, ...) \
+MACRO(1901, __VA_ARGS__) \
+MU_DO_1900(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1902(MACRO, ...) \
+MACRO(1902, __VA_ARGS__) \
+MU_DO_1901(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1903(MACRO, ...) \
+MACRO(1903, __VA_ARGS__) \
+MU_DO_1902(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1904(MACRO, ...) \
+MACRO(1904, __VA_ARGS__) \
+MU_DO_1903(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1905(MACRO, ...) \
+MACRO(1905, __VA_ARGS__) \
+MU_DO_1904(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1906(MACRO, ...) \
+MACRO(1906, __VA_ARGS__) \
+MU_DO_1905(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1907(MACRO, ...) \
+MACRO(1907, __VA_ARGS__) \
+MU_DO_1906(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1908(MACRO, ...) \
+MACRO(1908, __VA_ARGS__) \
+MU_DO_1907(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1909(MACRO, ...) \
+MACRO(1909, __VA_ARGS__) \
+MU_DO_1908(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1910(MACRO, ...) \
+MACRO(1910, __VA_ARGS__) \
+MU_DO_1909(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1911(MACRO, ...) \
+MACRO(1911, __VA_ARGS__) \
+MU_DO_1910(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1912(MACRO, ...) \
+MACRO(1912, __VA_ARGS__) \
+MU_DO_1911(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1913(MACRO, ...) \
+MACRO(1913, __VA_ARGS__) \
+MU_DO_1912(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1914(MACRO, ...) \
+MACRO(1914, __VA_ARGS__) \
+MU_DO_1913(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1915(MACRO, ...) \
+MACRO(1915, __VA_ARGS__) \
+MU_DO_1914(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1916(MACRO, ...) \
+MACRO(1916, __VA_ARGS__) \
+MU_DO_1915(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1917(MACRO, ...) \
+MACRO(1917, __VA_ARGS__) \
+MU_DO_1916(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1918(MACRO, ...) \
+MACRO(1918, __VA_ARGS__) \
+MU_DO_1917(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1919(MACRO, ...) \
+MACRO(1919, __VA_ARGS__) \
+MU_DO_1918(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1920(MACRO, ...) \
+MACRO(1920, __VA_ARGS__) \
+MU_DO_1919(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1921(MACRO, ...) \
+MACRO(1921, __VA_ARGS__) \
+MU_DO_1920(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1922(MACRO, ...) \
+MACRO(1922, __VA_ARGS__) \
+MU_DO_1921(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1923(MACRO, ...) \
+MACRO(1923, __VA_ARGS__) \
+MU_DO_1922(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1924(MACRO, ...) \
+MACRO(1924, __VA_ARGS__) \
+MU_DO_1923(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1925(MACRO, ...) \
+MACRO(1925, __VA_ARGS__) \
+MU_DO_1924(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1926(MACRO, ...) \
+MACRO(1926, __VA_ARGS__) \
+MU_DO_1925(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1927(MACRO, ...) \
+MACRO(1927, __VA_ARGS__) \
+MU_DO_1926(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1928(MACRO, ...) \
+MACRO(1928, __VA_ARGS__) \
+MU_DO_1927(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1929(MACRO, ...) \
+MACRO(1929, __VA_ARGS__) \
+MU_DO_1928(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1930(MACRO, ...) \
+MACRO(1930, __VA_ARGS__) \
+MU_DO_1929(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1931(MACRO, ...) \
+MACRO(1931, __VA_ARGS__) \
+MU_DO_1930(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1932(MACRO, ...) \
+MACRO(1932, __VA_ARGS__) \
+MU_DO_1931(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1933(MACRO, ...) \
+MACRO(1933, __VA_ARGS__) \
+MU_DO_1932(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1934(MACRO, ...) \
+MACRO(1934, __VA_ARGS__) \
+MU_DO_1933(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1935(MACRO, ...) \
+MACRO(1935, __VA_ARGS__) \
+MU_DO_1934(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1936(MACRO, ...) \
+MACRO(1936, __VA_ARGS__) \
+MU_DO_1935(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1937(MACRO, ...) \
+MACRO(1937, __VA_ARGS__) \
+MU_DO_1936(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1938(MACRO, ...) \
+MACRO(1938, __VA_ARGS__) \
+MU_DO_1937(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1939(MACRO, ...) \
+MACRO(1939, __VA_ARGS__) \
+MU_DO_1938(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1940(MACRO, ...) \
+MACRO(1940, __VA_ARGS__) \
+MU_DO_1939(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1941(MACRO, ...) \
+MACRO(1941, __VA_ARGS__) \
+MU_DO_1940(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1942(MACRO, ...) \
+MACRO(1942, __VA_ARGS__) \
+MU_DO_1941(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1943(MACRO, ...) \
+MACRO(1943, __VA_ARGS__) \
+MU_DO_1942(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1944(MACRO, ...) \
+MACRO(1944, __VA_ARGS__) \
+MU_DO_1943(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1945(MACRO, ...) \
+MACRO(1945, __VA_ARGS__) \
+MU_DO_1944(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1946(MACRO, ...) \
+MACRO(1946, __VA_ARGS__) \
+MU_DO_1945(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1947(MACRO, ...) \
+MACRO(1947, __VA_ARGS__) \
+MU_DO_1946(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1948(MACRO, ...) \
+MACRO(1948, __VA_ARGS__) \
+MU_DO_1947(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1949(MACRO, ...) \
+MACRO(1949, __VA_ARGS__) \
+MU_DO_1948(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1950(MACRO, ...) \
+MACRO(1950, __VA_ARGS__) \
+MU_DO_1949(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1951(MACRO, ...) \
+MACRO(1951, __VA_ARGS__) \
+MU_DO_1950(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1952(MACRO, ...) \
+MACRO(1952, __VA_ARGS__) \
+MU_DO_1951(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1953(MACRO, ...) \
+MACRO(1953, __VA_ARGS__) \
+MU_DO_1952(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1954(MACRO, ...) \
+MACRO(1954, __VA_ARGS__) \
+MU_DO_1953(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1955(MACRO, ...) \
+MACRO(1955, __VA_ARGS__) \
+MU_DO_1954(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1956(MACRO, ...) \
+MACRO(1956, __VA_ARGS__) \
+MU_DO_1955(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1957(MACRO, ...) \
+MACRO(1957, __VA_ARGS__) \
+MU_DO_1956(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1958(MACRO, ...) \
+MACRO(1958, __VA_ARGS__) \
+MU_DO_1957(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1959(MACRO, ...) \
+MACRO(1959, __VA_ARGS__) \
+MU_DO_1958(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1960(MACRO, ...) \
+MACRO(1960, __VA_ARGS__) \
+MU_DO_1959(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1961(MACRO, ...) \
+MACRO(1961, __VA_ARGS__) \
+MU_DO_1960(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1962(MACRO, ...) \
+MACRO(1962, __VA_ARGS__) \
+MU_DO_1961(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1963(MACRO, ...) \
+MACRO(1963, __VA_ARGS__) \
+MU_DO_1962(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1964(MACRO, ...) \
+MACRO(1964, __VA_ARGS__) \
+MU_DO_1963(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1965(MACRO, ...) \
+MACRO(1965, __VA_ARGS__) \
+MU_DO_1964(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1966(MACRO, ...) \
+MACRO(1966, __VA_ARGS__) \
+MU_DO_1965(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1967(MACRO, ...) \
+MACRO(1967, __VA_ARGS__) \
+MU_DO_1966(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1968(MACRO, ...) \
+MACRO(1968, __VA_ARGS__) \
+MU_DO_1967(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1969(MACRO, ...) \
+MACRO(1969, __VA_ARGS__) \
+MU_DO_1968(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1970(MACRO, ...) \
+MACRO(1970, __VA_ARGS__) \
+MU_DO_1969(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1971(MACRO, ...) \
+MACRO(1971, __VA_ARGS__) \
+MU_DO_1970(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1972(MACRO, ...) \
+MACRO(1972, __VA_ARGS__) \
+MU_DO_1971(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1973(MACRO, ...) \
+MACRO(1973, __VA_ARGS__) \
+MU_DO_1972(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1974(MACRO, ...) \
+MACRO(1974, __VA_ARGS__) \
+MU_DO_1973(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1975(MACRO, ...) \
+MACRO(1975, __VA_ARGS__) \
+MU_DO_1974(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1976(MACRO, ...) \
+MACRO(1976, __VA_ARGS__) \
+MU_DO_1975(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1977(MACRO, ...) \
+MACRO(1977, __VA_ARGS__) \
+MU_DO_1976(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1978(MACRO, ...) \
+MACRO(1978, __VA_ARGS__) \
+MU_DO_1977(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1979(MACRO, ...) \
+MACRO(1979, __VA_ARGS__) \
+MU_DO_1978(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1980(MACRO, ...) \
+MACRO(1980, __VA_ARGS__) \
+MU_DO_1979(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1981(MACRO, ...) \
+MACRO(1981, __VA_ARGS__) \
+MU_DO_1980(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1982(MACRO, ...) \
+MACRO(1982, __VA_ARGS__) \
+MU_DO_1981(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1983(MACRO, ...) \
+MACRO(1983, __VA_ARGS__) \
+MU_DO_1982(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1984(MACRO, ...) \
+MACRO(1984, __VA_ARGS__) \
+MU_DO_1983(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1985(MACRO, ...) \
+MACRO(1985, __VA_ARGS__) \
+MU_DO_1984(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1986(MACRO, ...) \
+MACRO(1986, __VA_ARGS__) \
+MU_DO_1985(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1987(MACRO, ...) \
+MACRO(1987, __VA_ARGS__) \
+MU_DO_1986(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1988(MACRO, ...) \
+MACRO(1988, __VA_ARGS__) \
+MU_DO_1987(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1989(MACRO, ...) \
+MACRO(1989, __VA_ARGS__) \
+MU_DO_1988(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1990(MACRO, ...) \
+MACRO(1990, __VA_ARGS__) \
+MU_DO_1989(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1991(MACRO, ...) \
+MACRO(1991, __VA_ARGS__) \
+MU_DO_1990(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1992(MACRO, ...) \
+MACRO(1992, __VA_ARGS__) \
+MU_DO_1991(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1993(MACRO, ...) \
+MACRO(1993, __VA_ARGS__) \
+MU_DO_1992(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1994(MACRO, ...) \
+MACRO(1994, __VA_ARGS__) \
+MU_DO_1993(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1995(MACRO, ...) \
+MACRO(1995, __VA_ARGS__) \
+MU_DO_1994(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1996(MACRO, ...) \
+MACRO(1996, __VA_ARGS__) \
+MU_DO_1995(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1997(MACRO, ...) \
+MACRO(1997, __VA_ARGS__) \
+MU_DO_1996(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1998(MACRO, ...) \
+MACRO(1998, __VA_ARGS__) \
+MU_DO_1997(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_1999(MACRO, ...) \
+MACRO(1999, __VA_ARGS__) \
+MU_DO_1998(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2000(MACRO, ...) \
+MACRO(2000, __VA_ARGS__) \
+MU_DO_1999(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2001(MACRO, ...) \
+MACRO(2001, __VA_ARGS__) \
+MU_DO_2000(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2002(MACRO, ...) \
+MACRO(2002, __VA_ARGS__) \
+MU_DO_2001(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2003(MACRO, ...) \
+MACRO(2003, __VA_ARGS__) \
+MU_DO_2002(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2004(MACRO, ...) \
+MACRO(2004, __VA_ARGS__) \
+MU_DO_2003(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2005(MACRO, ...) \
+MACRO(2005, __VA_ARGS__) \
+MU_DO_2004(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2006(MACRO, ...) \
+MACRO(2006, __VA_ARGS__) \
+MU_DO_2005(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2007(MACRO, ...) \
+MACRO(2007, __VA_ARGS__) \
+MU_DO_2006(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2008(MACRO, ...) \
+MACRO(2008, __VA_ARGS__) \
+MU_DO_2007(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2009(MACRO, ...) \
+MACRO(2009, __VA_ARGS__) \
+MU_DO_2008(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2010(MACRO, ...) \
+MACRO(2010, __VA_ARGS__) \
+MU_DO_2009(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2011(MACRO, ...) \
+MACRO(2011, __VA_ARGS__) \
+MU_DO_2010(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2012(MACRO, ...) \
+MACRO(2012, __VA_ARGS__) \
+MU_DO_2011(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2013(MACRO, ...) \
+MACRO(2013, __VA_ARGS__) \
+MU_DO_2012(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2014(MACRO, ...) \
+MACRO(2014, __VA_ARGS__) \
+MU_DO_2013(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2015(MACRO, ...) \
+MACRO(2015, __VA_ARGS__) \
+MU_DO_2014(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2016(MACRO, ...) \
+MACRO(2016, __VA_ARGS__) \
+MU_DO_2015(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2017(MACRO, ...) \
+MACRO(2017, __VA_ARGS__) \
+MU_DO_2016(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2018(MACRO, ...) \
+MACRO(2018, __VA_ARGS__) \
+MU_DO_2017(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2019(MACRO, ...) \
+MACRO(2019, __VA_ARGS__) \
+MU_DO_2018(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2020(MACRO, ...) \
+MACRO(2020, __VA_ARGS__) \
+MU_DO_2019(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2021(MACRO, ...) \
+MACRO(2021, __VA_ARGS__) \
+MU_DO_2020(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2022(MACRO, ...) \
+MACRO(2022, __VA_ARGS__) \
+MU_DO_2021(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2023(MACRO, ...) \
+MACRO(2023, __VA_ARGS__) \
+MU_DO_2022(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2024(MACRO, ...) \
+MACRO(2024, __VA_ARGS__) \
+MU_DO_2023(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2025(MACRO, ...) \
+MACRO(2025, __VA_ARGS__) \
+MU_DO_2024(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2026(MACRO, ...) \
+MACRO(2026, __VA_ARGS__) \
+MU_DO_2025(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2027(MACRO, ...) \
+MACRO(2027, __VA_ARGS__) \
+MU_DO_2026(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2028(MACRO, ...) \
+MACRO(2028, __VA_ARGS__) \
+MU_DO_2027(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2029(MACRO, ...) \
+MACRO(2029, __VA_ARGS__) \
+MU_DO_2028(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2030(MACRO, ...) \
+MACRO(2030, __VA_ARGS__) \
+MU_DO_2029(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2031(MACRO, ...) \
+MACRO(2031, __VA_ARGS__) \
+MU_DO_2030(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2032(MACRO, ...) \
+MACRO(2032, __VA_ARGS__) \
+MU_DO_2031(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2033(MACRO, ...) \
+MACRO(2033, __VA_ARGS__) \
+MU_DO_2032(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2034(MACRO, ...) \
+MACRO(2034, __VA_ARGS__) \
+MU_DO_2033(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2035(MACRO, ...) \
+MACRO(2035, __VA_ARGS__) \
+MU_DO_2034(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2036(MACRO, ...) \
+MACRO(2036, __VA_ARGS__) \
+MU_DO_2035(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2037(MACRO, ...) \
+MACRO(2037, __VA_ARGS__) \
+MU_DO_2036(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2038(MACRO, ...) \
+MACRO(2038, __VA_ARGS__) \
+MU_DO_2037(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2039(MACRO, ...) \
+MACRO(2039, __VA_ARGS__) \
+MU_DO_2038(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2040(MACRO, ...) \
+MACRO(2040, __VA_ARGS__) \
+MU_DO_2039(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2041(MACRO, ...) \
+MACRO(2041, __VA_ARGS__) \
+MU_DO_2040(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2042(MACRO, ...) \
+MACRO(2042, __VA_ARGS__) \
+MU_DO_2041(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2043(MACRO, ...) \
+MACRO(2043, __VA_ARGS__) \
+MU_DO_2042(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2044(MACRO, ...) \
+MACRO(2044, __VA_ARGS__) \
+MU_DO_2043(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2045(MACRO, ...) \
+MACRO(2045, __VA_ARGS__) \
+MU_DO_2044(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2046(MACRO, ...) \
+MACRO(2046, __VA_ARGS__) \
+MU_DO_2045(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2047(MACRO, ...) \
+MACRO(2047, __VA_ARGS__) \
+MU_DO_2046(MACRO, __VA_ARGS__)
+
+
+#define MU_DO_2048(MACRO, ...) \
+MACRO(2048, __VA_ARGS__) \
+MU_DO_2047(MACRO, __VA_ARGS__)
+
+
+
+#define MU_DO(TIMES, MACRO, ...) MU_C2(MU_DO_, TIMES)(MACRO, __VA_ARGS__)
+
+#endif /*MACRO_UTILS_GENERATED_H*/
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/deps/parson/parson.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/deps/parson/parson.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/deps/parson/parson.c	(revision 453)
@@ -0,0 +1,2061 @@
+/*
+ SPDX-License-Identifier: MIT
+
+ Parson ( http://kgabis.github.com/parson/ )
+ Copyright (c) 2012 - 2019 Krzysztof Gabis
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+#ifdef _MSC_VER
+#ifndef _CRT_SECURE_NO_WARNINGS
+#define _CRT_SECURE_NO_WARNINGS
+#endif /* _CRT_SECURE_NO_WARNINGS */
+#endif /* _MSC_VER */
+
+#include "parson.h"
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+#include <errno.h>
+
+/* Apparently sscanf is not implemented in some "standard" libraries, so don't use it, if you
+ * don't have to. */
+#define sscanf THINK_TWICE_ABOUT_USING_SSCANF
+
+#define STARTING_CAPACITY 16
+#define MAX_NESTING       2048
+
+#define FLOAT_FORMAT "%1.17g" /* do not increase precision without incresing NUM_BUF_SIZE */
+#define NUM_BUF_SIZE 64 /* double printed with "%1.17g" shouldn't be longer than 25 bytes so let's be paranoid and use 64 */
+
+#define SIZEOF_TOKEN(a)       (sizeof(a) - 1)
+#define SKIP_CHAR(str)        ((*str)++)
+#define SKIP_WHITESPACES(str) while (isspace((unsigned char)(**str))) { SKIP_CHAR(str); }
+#define MAX(a, b)             ((a) > (b) ? (a) : (b))
+
+#undef malloc
+#undef free
+
+#if defined(isnan) && defined(isinf)
+#define IS_NUMBER_INVALID(x) (isnan((x)) || isinf((x)))
+#else
+#define IS_NUMBER_INVALID(x) (((x) * 0.0) != 0.0)
+#endif
+
+static JSON_Malloc_Function parson_malloc = malloc;
+static JSON_Free_Function parson_free = free;
+
+static int parson_escape_slashes = 1;
+
+#define IS_CONT(b) (((unsigned char)(b) & 0xC0) == 0x80) /* is utf-8 continuation byte */
+
+/* Type definitions */
+typedef union json_value_value {
+    char        *string;
+    double       number;
+    JSON_Object *object;
+    JSON_Array  *array;
+    int          boolean;
+    int          null;
+} JSON_Value_Value;
+
+struct json_value_t {
+    JSON_Value      *parent;
+    JSON_Value_Type  type;
+    JSON_Value_Value value;
+};
+
+struct json_object_t {
+    JSON_Value  *wrapping_value;
+    char       **names;
+    JSON_Value **values;
+    size_t       count;
+    size_t       capacity;
+};
+
+struct json_array_t {
+    JSON_Value  *wrapping_value;
+    JSON_Value **items;
+    size_t       count;
+    size_t       capacity;
+};
+
+/* Various */
+static char * read_file(const char *filename);
+static void   remove_comments(char *string, const char *start_token, const char *end_token);
+static char * parson_strndup(const char *string, size_t n);
+static char * parson_strdup(const char *string);
+static int    hex_char_to_int(char c);
+static int    parse_utf16_hex(const char *string, unsigned int *result);
+static int    num_bytes_in_utf8_sequence(unsigned char c);
+static int    verify_utf8_sequence(const unsigned char *string, int *len);
+static int    is_valid_utf8(const char *string, size_t string_len);
+static int    is_decimal(const char *string, size_t length);
+
+/* JSON Object */
+static JSON_Object * json_object_init(JSON_Value *wrapping_value);
+static JSON_Status   json_object_add(JSON_Object *object, const char *name, JSON_Value *value);
+static JSON_Status   json_object_addn(JSON_Object *object, const char *name, size_t name_len, JSON_Value *value);
+static JSON_Status   json_object_resize(JSON_Object *object, size_t new_capacity);
+static JSON_Value  * json_object_getn_value(const JSON_Object *object, const char *name, size_t name_len);
+static JSON_Status   json_object_remove_internal(JSON_Object *object, const char *name, int free_value);
+static JSON_Status   json_object_dotremove_internal(JSON_Object *object, const char *name, int free_value);
+static void          json_object_free(JSON_Object *object);
+
+/* JSON Array */
+static JSON_Array * json_array_init(JSON_Value *wrapping_value);
+static JSON_Status  json_array_add(JSON_Array *array, JSON_Value *value);
+static JSON_Status  json_array_resize(JSON_Array *array, size_t new_capacity);
+static void         json_array_free(JSON_Array *array);
+
+/* JSON Value */
+static JSON_Value * json_value_init_string_no_copy(char *string);
+
+/* Parser */
+static JSON_Status  skip_quotes(const char **string);
+static int          parse_utf16(const char **unprocessed, char **processed);
+static char *       process_string(const char *input, size_t len);
+static char *       get_quoted_string(const char **string);
+static JSON_Value * parse_object_value(const char **string, size_t nesting);
+static JSON_Value * parse_array_value(const char **string, size_t nesting);
+static JSON_Value * parse_string_value(const char **string);
+static JSON_Value * parse_boolean_value(const char **string);
+static JSON_Value * parse_number_value(const char **string);
+static JSON_Value * parse_null_value(const char **string);
+static JSON_Value * parse_value(const char **string, size_t nesting);
+
+/* Serialization */
+static int    json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int level, int is_pretty, char *num_buf);
+static int    json_serialize_string(const char *string, char *buf);
+static int    append_indent(char *buf, int level);
+static int    append_string(char *buf, const char *string);
+
+/* Various */
+static char * parson_strndup(const char *string, size_t n) {
+    char *output_string = (char*)parson_malloc(n + 1);
+    if (!output_string) {
+        return NULL;
+    }
+    output_string[n] = '\0';
+    strncpy(output_string, string, n);
+    return output_string;
+}
+
+static char * parson_strdup(const char *string) {
+    return parson_strndup(string, strlen(string));
+}
+
+static int hex_char_to_int(char c) {
+    if (c >= '0' && c <= '9') {
+        return c - '0';
+    } else if (c >= 'a' && c <= 'f') {
+        return c - 'a' + 10;
+    } else if (c >= 'A' && c <= 'F') {
+        return c - 'A' + 10;
+    }
+    return -1;
+}
+
+static int parse_utf16_hex(const char *s, unsigned int *result) {
+    int x1, x2, x3, x4;
+    if (s[0] == '\0' || s[1] == '\0' || s[2] == '\0' || s[3] == '\0') {
+        return 0;
+    }
+    x1 = hex_char_to_int(s[0]);
+    x2 = hex_char_to_int(s[1]);
+    x3 = hex_char_to_int(s[2]);
+    x4 = hex_char_to_int(s[3]);
+    if (x1 == -1 || x2 == -1 || x3 == -1 || x4 == -1) {
+        return 0;
+    }
+    *result = (unsigned int)((x1 << 12) | (x2 << 8) | (x3 << 4) | x4);
+    return 1;
+}
+
+static int num_bytes_in_utf8_sequence(unsigned char c) {
+    if (c == 0xC0 || c == 0xC1 || c > 0xF4 || IS_CONT(c)) {
+        return 0;
+    } else if ((c & 0x80) == 0) {    /* 0xxxxxxx */
+        return 1;
+    } else if ((c & 0xE0) == 0xC0) { /* 110xxxxx */
+        return 2;
+    } else if ((c & 0xF0) == 0xE0) { /* 1110xxxx */
+        return 3;
+    } else if ((c & 0xF8) == 0xF0) { /* 11110xxx */
+        return 4;
+    }
+    return 0; /* won't happen */
+}
+
+static int verify_utf8_sequence(const unsigned char *string, int *len) {
+    unsigned int cp = 0;
+    *len = num_bytes_in_utf8_sequence(string[0]);
+
+    if (*len == 1) {
+        cp = string[0];
+    } else if (*len == 2 && IS_CONT(string[1])) {
+        cp = string[0] & 0x1F;
+        cp = (cp << 6) | (string[1] & 0x3F);
+    } else if (*len == 3 && IS_CONT(string[1]) && IS_CONT(string[2])) {
+        cp = ((unsigned char)string[0]) & 0xF;
+        cp = (cp << 6) | (string[1] & 0x3F);
+        cp = (cp << 6) | (string[2] & 0x3F);
+    } else if (*len == 4 && IS_CONT(string[1]) && IS_CONT(string[2]) && IS_CONT(string[3])) {
+        cp = string[0] & 0x7;
+        cp = (cp << 6) | (string[1] & 0x3F);
+        cp = (cp << 6) | (string[2] & 0x3F);
+        cp = (cp << 6) | (string[3] & 0x3F);
+    } else {
+        return 0;
+    }
+
+    /* overlong encodings */
+    if ((cp < 0x80    && *len > 1) ||
+        (cp < 0x800   && *len > 2) ||
+        (cp < 0x10000 && *len > 3)) {
+        return 0;
+    }
+
+    /* invalid unicode */
+    if (cp > 0x10FFFF) {
+        return 0;
+    }
+
+    /* surrogate halves */
+    if (cp >= 0xD800 && cp <= 0xDFFF) {
+        return 0;
+    }
+
+    return 1;
+}
+
+static int is_valid_utf8(const char *string, size_t string_len) {
+    int len = 0;
+    const char *string_end =  string + string_len;
+    while (string < string_end) {
+        if (!verify_utf8_sequence((const unsigned char*)string, &len)) {
+            return 0;
+        }
+        string += len;
+    }
+    return 1;
+}
+
+static int is_decimal(const char *string, size_t length) {
+    if (length > 1 && string[0] == '0' && string[1] != '.') {
+        return 0;
+    }
+    if (length > 2 && !strncmp(string, "-0", 2) && string[2] != '.') {
+        return 0;
+    }
+    while (length--) {
+        if (strchr("xX", string[length])) {
+            return 0;
+        }
+    }
+    return 1;
+}
+
+static char * read_file(const char * filename) {
+    FILE *fp = fopen(filename, "r");
+    size_t size_to_read = 0;
+    size_t size_read = 0;
+    long pos;
+    char *file_contents;
+    if (!fp) {
+        return NULL;
+    }
+    fseek(fp, 0L, SEEK_END);
+    pos = ftell(fp);
+    if (pos < 0) {
+        fclose(fp);
+        return NULL;
+    }
+    size_to_read = pos;
+    rewind(fp);
+    file_contents = (char*)parson_malloc(sizeof(char) * (size_to_read + 1));
+    if (!file_contents) {
+        fclose(fp);
+        return NULL;
+    }
+    size_read = fread(file_contents, 1, size_to_read, fp);
+    if (size_read == 0 || ferror(fp)) {
+        fclose(fp);
+        parson_free(file_contents);
+        return NULL;
+    }
+    fclose(fp);
+    file_contents[size_read] = '\0';
+    return file_contents;
+}
+
+static void remove_comments(char *string, const char *start_token, const char *end_token) {
+    int in_string = 0, escaped = 0;
+    size_t i;
+    char *ptr = NULL, current_char;
+    size_t start_token_len = strlen(start_token);
+    size_t end_token_len = strlen(end_token);
+    if (start_token_len == 0 || end_token_len == 0) {
+        return;
+    }
+    while ((current_char = *string) != '\0') {
+        if (current_char == '\\' && !escaped) {
+            escaped = 1;
+            string++;
+            continue;
+        } else if (current_char == '\"' && !escaped) {
+            in_string = !in_string;
+        } else if (!in_string && strncmp(string, start_token, start_token_len) == 0) {
+            for(i = 0; i < start_token_len; i++) {
+                string[i] = ' ';
+            }
+            string = string + start_token_len;
+            ptr = strstr(string, end_token);
+            if (!ptr) {
+                return;
+            }
+            for (i = 0; i < (ptr - string) + end_token_len; i++) {
+                string[i] = ' ';
+            }
+            string = ptr + end_token_len - 1;
+        }
+        escaped = 0;
+        string++;
+    }
+}
+
+/* JSON Object */
+static JSON_Object * json_object_init(JSON_Value *wrapping_value) {
+    JSON_Object *new_obj = (JSON_Object*)parson_malloc(sizeof(JSON_Object));
+    if (new_obj == NULL) {
+        return NULL;
+    }
+    new_obj->wrapping_value = wrapping_value;
+    new_obj->names = (char**)NULL;
+    new_obj->values = (JSON_Value**)NULL;
+    new_obj->capacity = 0;
+    new_obj->count = 0;
+    return new_obj;
+}
+
+static JSON_Status json_object_add(JSON_Object *object, const char *name, JSON_Value *value) {
+    if (name == NULL) {
+        return JSONFailure;
+    }
+    return json_object_addn(object, name, strlen(name), value);
+}
+
+static JSON_Status json_object_addn(JSON_Object *object, const char *name, size_t name_len, JSON_Value *value) {
+    size_t index = 0;
+    if (object == NULL || name == NULL || value == NULL) {
+        return JSONFailure;
+    }
+    if (json_object_getn_value(object, name, name_len) != NULL) {
+        return JSONFailure;
+    }
+    if (object->count >= object->capacity) {
+        size_t new_capacity = MAX(object->capacity * 2, STARTING_CAPACITY);
+        if (json_object_resize(object, new_capacity) == JSONFailure) {
+            return JSONFailure;
+        }
+    }
+    index = object->count;
+    object->names[index] = parson_strndup(name, name_len);
+    if (object->names[index] == NULL) {
+        return JSONFailure;
+    }
+    value->parent = json_object_get_wrapping_value(object);
+    object->values[index] = value;
+    object->count++;
+    return JSONSuccess;
+}
+
+static JSON_Status json_object_resize(JSON_Object *object, size_t new_capacity) {
+    char **temp_names = NULL;
+    JSON_Value **temp_values = NULL;
+
+    if ((object->names == NULL && object->values != NULL) ||
+        (object->names != NULL && object->values == NULL) ||
+        new_capacity == 0) {
+            return JSONFailure; /* Shouldn't happen */
+    }
+    temp_names = (char**)parson_malloc(new_capacity * sizeof(char*));
+    if (temp_names == NULL) {
+        return JSONFailure;
+    }
+    temp_values = (JSON_Value**)parson_malloc(new_capacity * sizeof(JSON_Value*));
+    if (temp_values == NULL) {
+        parson_free(temp_names);
+        return JSONFailure;
+    }
+    if (object->names != NULL && object->values != NULL && object->count > 0) {
+        memcpy(temp_names, object->names, object->count * sizeof(char*));
+        memcpy(temp_values, object->values, object->count * sizeof(JSON_Value*));
+    }
+    parson_free(object->names);
+    parson_free(object->values);
+    object->names = temp_names;
+    object->values = temp_values;
+    object->capacity = new_capacity;
+    return JSONSuccess;
+}
+
+static JSON_Value * json_object_getn_value(const JSON_Object *object, const char *name, size_t name_len) {
+    size_t i, name_length;
+    for (i = 0; i < json_object_get_count(object); i++) {
+        name_length = strlen(object->names[i]);
+        if (name_length != name_len) {
+            continue;
+        }
+        if (strncmp(object->names[i], name, name_len) == 0) {
+            return object->values[i];
+        }
+    }
+    return NULL;
+}
+
+static JSON_Status json_object_remove_internal(JSON_Object *object, const char *name, int free_value) {
+    size_t i = 0, last_item_index = 0;
+    if (object == NULL || json_object_get_value(object, name) == NULL) {
+        return JSONFailure;
+    }
+    last_item_index = json_object_get_count(object) - 1;
+    for (i = 0; i < json_object_get_count(object); i++) {
+        if (strcmp(object->names[i], name) == 0) {
+            parson_free(object->names[i]);
+            if (free_value) {
+                json_value_free(object->values[i]);
+            }
+            if (i != last_item_index) { /* Replace key value pair with one from the end */
+                object->names[i] = object->names[last_item_index];
+                object->values[i] = object->values[last_item_index];
+            }
+            object->count -= 1;
+            return JSONSuccess;
+        }
+    }
+    return JSONFailure; /* No execution path should end here */
+}
+
+static JSON_Status json_object_dotremove_internal(JSON_Object *object, const char *name, int free_value) {
+    JSON_Value *temp_value = NULL;
+    JSON_Object *temp_object = NULL;
+    const char *dot_pos = strchr(name, '.');
+    if (dot_pos == NULL) {
+        return json_object_remove_internal(object, name, free_value);
+    }
+    temp_value = json_object_getn_value(object, name, dot_pos - name);
+    if (json_value_get_type(temp_value) != JSONObject) {
+        return JSONFailure;
+    }
+    temp_object = json_value_get_object(temp_value);
+    return json_object_dotremove_internal(temp_object, dot_pos + 1, free_value);
+}
+
+static void json_object_free(JSON_Object *object) {
+    size_t i;
+    for (i = 0; i < object->count; i++) {
+        parson_free(object->names[i]);
+        json_value_free(object->values[i]);
+    }
+    parson_free(object->names);
+    parson_free(object->values);
+    parson_free(object);
+}
+
+/* JSON Array */
+static JSON_Array * json_array_init(JSON_Value *wrapping_value) {
+    JSON_Array *new_array = (JSON_Array*)parson_malloc(sizeof(JSON_Array));
+    if (new_array == NULL) {
+        return NULL;
+    }
+    new_array->wrapping_value = wrapping_value;
+    new_array->items = (JSON_Value**)NULL;
+    new_array->capacity = 0;
+    new_array->count = 0;
+    return new_array;
+}
+
+static JSON_Status json_array_add(JSON_Array *array, JSON_Value *value) {
+    if (array->count >= array->capacity) {
+        size_t new_capacity = MAX(array->capacity * 2, STARTING_CAPACITY);
+        if (json_array_resize(array, new_capacity) == JSONFailure) {
+            return JSONFailure;
+        }
+    }
+    value->parent = json_array_get_wrapping_value(array);
+    array->items[array->count] = value;
+    array->count++;
+    return JSONSuccess;
+}
+
+static JSON_Status json_array_resize(JSON_Array *array, size_t new_capacity) {
+    JSON_Value **new_items = NULL;
+    if (new_capacity == 0) {
+        return JSONFailure;
+    }
+    new_items = (JSON_Value**)parson_malloc(new_capacity * sizeof(JSON_Value*));
+    if (new_items == NULL) {
+        return JSONFailure;
+    }
+    if (array->items != NULL && array->count > 0) {
+        memcpy(new_items, array->items, array->count * sizeof(JSON_Value*));
+    }
+    parson_free(array->items);
+    array->items = new_items;
+    array->capacity = new_capacity;
+    return JSONSuccess;
+}
+
+static void json_array_free(JSON_Array *array) {
+    size_t i;
+    for (i = 0; i < array->count; i++) {
+        json_value_free(array->items[i]);
+    }
+    parson_free(array->items);
+    parson_free(array);
+}
+
+/* JSON Value */
+static JSON_Value * json_value_init_string_no_copy(char *string) {
+    JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
+    if (!new_value) {
+        return NULL;
+    }
+    new_value->parent = NULL;
+    new_value->type = JSONString;
+    new_value->value.string = string;
+    return new_value;
+}
+
+/* Parser */
+static JSON_Status skip_quotes(const char **string) {
+    if (**string != '\"') {
+        return JSONFailure;
+    }
+    SKIP_CHAR(string);
+    while (**string != '\"') {
+        if (**string == '\0') {
+            return JSONFailure;
+        } else if (**string == '\\') {
+            SKIP_CHAR(string);
+            if (**string == '\0') {
+                return JSONFailure;
+            }
+        }
+        SKIP_CHAR(string);
+    }
+    SKIP_CHAR(string);
+    return JSONSuccess;
+}
+
+static int parse_utf16(const char **unprocessed, char **processed) {
+    unsigned int cp, lead, trail;
+    int parse_succeeded = 0;
+    char *processed_ptr = *processed;
+    const char *unprocessed_ptr = *unprocessed;
+    unprocessed_ptr++; /* skips u */
+    parse_succeeded = parse_utf16_hex(unprocessed_ptr, &cp);
+    if (!parse_succeeded) {
+        return JSONFailure;
+    }
+    if (cp < 0x80) {
+        processed_ptr[0] = (char)cp; /* 0xxxxxxx */
+    } else if (cp < 0x800) {
+        processed_ptr[0] = ((cp >> 6) & 0x1F) | 0xC0; /* 110xxxxx */
+        processed_ptr[1] = ((cp)      & 0x3F) | 0x80; /* 10xxxxxx */
+        processed_ptr += 1;
+    } else if (cp < 0xD800 || cp > 0xDFFF) {
+        processed_ptr[0] = ((cp >> 12) & 0x0F) | 0xE0; /* 1110xxxx */
+        processed_ptr[1] = ((cp >> 6)  & 0x3F) | 0x80; /* 10xxxxxx */
+        processed_ptr[2] = ((cp)       & 0x3F) | 0x80; /* 10xxxxxx */
+        processed_ptr += 2;
+    } else if (cp >= 0xD800 && cp <= 0xDBFF) { /* lead surrogate (0xD800..0xDBFF) */
+        lead = cp;
+        unprocessed_ptr += 4; /* should always be within the buffer, otherwise previous sscanf would fail */
+        if (*unprocessed_ptr++ != '\\' || *unprocessed_ptr++ != 'u') {
+            return JSONFailure;
+        }
+        parse_succeeded = parse_utf16_hex(unprocessed_ptr, &trail);
+        if (!parse_succeeded || trail < 0xDC00 || trail > 0xDFFF) { /* valid trail surrogate? (0xDC00..0xDFFF) */
+            return JSONFailure;
+        }
+        cp = ((((lead - 0xD800) & 0x3FF) << 10) | ((trail - 0xDC00) & 0x3FF)) + 0x010000;
+        processed_ptr[0] = (((cp >> 18) & 0x07) | 0xF0); /* 11110xxx */
+        processed_ptr[1] = (((cp >> 12) & 0x3F) | 0x80); /* 10xxxxxx */
+        processed_ptr[2] = (((cp >> 6)  & 0x3F) | 0x80); /* 10xxxxxx */
+        processed_ptr[3] = (((cp)       & 0x3F) | 0x80); /* 10xxxxxx */
+        processed_ptr += 3;
+    } else { /* trail surrogate before lead surrogate */
+        return JSONFailure;
+    }
+    unprocessed_ptr += 3;
+    *processed = processed_ptr;
+    *unprocessed = unprocessed_ptr;
+    return JSONSuccess;
+}
+
+
+/* Copies and processes passed string up to supplied length.
+Example: "\u006Corem ipsum" -> lorem ipsum */
+static char* process_string(const char *input, size_t len) {
+    const char *input_ptr = input;
+    size_t initial_size = (len + 1) * sizeof(char);
+    size_t final_size = 0;
+    char *output = NULL, *output_ptr = NULL, *resized_output = NULL;
+    output = (char*)parson_malloc(initial_size);
+    if (output == NULL) {
+        goto error;
+    }
+    output_ptr = output;
+    while ((*input_ptr != '\0') && (size_t)(input_ptr - input) < len) {
+        if (*input_ptr == '\\') {
+            input_ptr++;
+            switch (*input_ptr) {
+                case '\"': *output_ptr = '\"'; break;
+                case '\\': *output_ptr = '\\'; break;
+                case '/':  *output_ptr = '/';  break;
+                case 'b':  *output_ptr = '\b'; break;
+                case 'f':  *output_ptr = '\f'; break;
+                case 'n':  *output_ptr = '\n'; break;
+                case 'r':  *output_ptr = '\r'; break;
+                case 't':  *output_ptr = '\t'; break;
+                case 'u':
+                    if (parse_utf16(&input_ptr, &output_ptr) == JSONFailure) {
+                        goto error;
+                    }
+                    break;
+                default:
+                    goto error;
+            }
+        } else if ((unsigned char)*input_ptr < 0x20) {
+            goto error; /* 0x00-0x19 are invalid characters for json string (http://www.ietf.org/rfc/rfc4627.txt) */
+        } else {
+            *output_ptr = *input_ptr;
+        }
+        output_ptr++;
+        input_ptr++;
+    }
+    *output_ptr = '\0';
+    /* resize to new length */
+    final_size = (size_t)(output_ptr-output) + 1;
+    /* todo: don't resize if final_size == initial_size */
+    resized_output = (char*)parson_malloc(final_size);
+    if (resized_output == NULL) {
+        goto error;
+    }
+    memcpy(resized_output, output, final_size);
+    parson_free(output);
+    return resized_output;
+error:
+    parson_free(output);
+    return NULL;
+}
+
+/* Return processed contents of a string between quotes and
+   skips passed argument to a matching quote. */
+static char * get_quoted_string(const char **string) {
+    const char *string_start = *string;
+    size_t string_len = 0;
+    JSON_Status status = skip_quotes(string);
+    if (status != JSONSuccess) {
+        return NULL;
+    }
+    string_len = *string - string_start - 2; /* length without quotes */
+    return process_string(string_start + 1, string_len);
+}
+
+static JSON_Value * parse_value(const char **string, size_t nesting) {
+    if (nesting > MAX_NESTING) {
+        return NULL;
+    }
+    SKIP_WHITESPACES(string);
+    switch (**string) {
+        case '{':
+            return parse_object_value(string, nesting + 1);
+        case '[':
+            return parse_array_value(string, nesting + 1);
+        case '\"':
+            return parse_string_value(string);
+        case 'f': case 't':
+            return parse_boolean_value(string);
+        case '-':
+        case '0': case '1': case '2': case '3': case '4':
+        case '5': case '6': case '7': case '8': case '9':
+            return parse_number_value(string);
+        case 'n':
+            return parse_null_value(string);
+        default:
+            return NULL;
+    }
+}
+
+static JSON_Value * parse_object_value(const char **string, size_t nesting) {
+    JSON_Value *output_value = NULL, *new_value = NULL;
+    JSON_Object *output_object = NULL;
+    char *new_key = NULL;
+    output_value = json_value_init_object();
+    if (output_value == NULL) {
+        return NULL;
+    }
+    if (**string != '{') {
+        json_value_free(output_value);
+        return NULL;
+    }
+    output_object = json_value_get_object(output_value);
+    SKIP_CHAR(string);
+    SKIP_WHITESPACES(string);
+    if (**string == '}') { /* empty object */
+        SKIP_CHAR(string);
+        return output_value;
+    }
+    while (**string != '\0') {
+        new_key = get_quoted_string(string);
+        if (new_key == NULL) {
+            json_value_free(output_value);
+            return NULL;
+        }
+        SKIP_WHITESPACES(string);
+        if (**string != ':') {
+            parson_free(new_key);
+            json_value_free(output_value);
+            return NULL;
+        }
+        SKIP_CHAR(string);
+        new_value = parse_value(string, nesting);
+        if (new_value == NULL) {
+            parson_free(new_key);
+            json_value_free(output_value);
+            return NULL;
+        }
+        if (json_object_add(output_object, new_key, new_value) == JSONFailure) {
+            parson_free(new_key);
+            json_value_free(new_value);
+            json_value_free(output_value);
+            return NULL;
+        }
+        parson_free(new_key);
+        SKIP_WHITESPACES(string);
+        if (**string != ',') {
+            break;
+        }
+        SKIP_CHAR(string);
+        SKIP_WHITESPACES(string);
+    }
+    SKIP_WHITESPACES(string);
+    if (**string != '}' || /* Trim object after parsing is over */
+        json_object_resize(output_object, json_object_get_count(output_object)) == JSONFailure) {
+            json_value_free(output_value);
+            return NULL;
+    }
+    SKIP_CHAR(string);
+    return output_value;
+}
+
+static JSON_Value * parse_array_value(const char **string, size_t nesting) {
+    JSON_Value *output_value = NULL, *new_array_value = NULL;
+    JSON_Array *output_array = NULL;
+    output_value = json_value_init_array();
+    if (output_value == NULL) {
+        return NULL;
+    }
+    if (**string != '[') {
+        json_value_free(output_value);
+        return NULL;
+    }
+    output_array = json_value_get_array(output_value);
+    SKIP_CHAR(string);
+    SKIP_WHITESPACES(string);
+    if (**string == ']') { /* empty array */
+        SKIP_CHAR(string);
+        return output_value;
+    }
+    while (**string != '\0') {
+        new_array_value = parse_value(string, nesting);
+        if (new_array_value == NULL) {
+            json_value_free(output_value);
+            return NULL;
+        }
+        if (json_array_add(output_array, new_array_value) == JSONFailure) {
+            json_value_free(new_array_value);
+            json_value_free(output_value);
+            return NULL;
+        }
+        SKIP_WHITESPACES(string);
+        if (**string != ',') {
+            break;
+        }
+        SKIP_CHAR(string);
+        SKIP_WHITESPACES(string);
+    }
+    SKIP_WHITESPACES(string);
+    if (**string != ']' || /* Trim array after parsing is over */
+        json_array_resize(output_array, json_array_get_count(output_array)) == JSONFailure) {
+            json_value_free(output_value);
+            return NULL;
+    }
+    SKIP_CHAR(string);
+    return output_value;
+}
+
+static JSON_Value * parse_string_value(const char **string) {
+    JSON_Value *value = NULL;
+    char *new_string = get_quoted_string(string);
+    if (new_string == NULL) {
+        return NULL;
+    }
+    value = json_value_init_string_no_copy(new_string);
+    if (value == NULL) {
+        parson_free(new_string);
+        return NULL;
+    }
+    return value;
+}
+
+static JSON_Value * parse_boolean_value(const char **string) {
+    size_t true_token_size = SIZEOF_TOKEN("true");
+    size_t false_token_size = SIZEOF_TOKEN("false");
+    if (strncmp("true", *string, true_token_size) == 0) {
+        *string += true_token_size;
+        return json_value_init_boolean(1);
+    } else if (strncmp("false", *string, false_token_size) == 0) {
+        *string += false_token_size;
+        return json_value_init_boolean(0);
+    }
+    return NULL;
+}
+
+static JSON_Value * parse_number_value(const char **string) {
+    char *end;
+    double number = 0;
+    errno = 0;
+    number = strtod(*string, &end);
+    if (errno || !is_decimal(*string, end - *string)) {
+        return NULL;
+    }
+    *string = end;
+    return json_value_init_number(number);
+}
+
+static JSON_Value * parse_null_value(const char **string) {
+    size_t token_size = SIZEOF_TOKEN("null");
+    if (strncmp("null", *string, token_size) == 0) {
+        *string += token_size;
+        return json_value_init_null();
+    }
+    return NULL;
+}
+
+/* Serialization */
+#define APPEND_STRING(str) do { written = append_string(buf, (str));\
+                                if (written < 0) { return -1; }\
+                                if (buf != NULL) { buf += written; }\
+                                written_total += written; } while(0)
+
+#define APPEND_INDENT(level) do { written = append_indent(buf, (level));\
+                                  if (written < 0) { return -1; }\
+                                  if (buf != NULL) { buf += written; }\
+                                  written_total += written; } while(0)
+
+static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int level, int is_pretty, char *num_buf)
+{
+    const char *key = NULL, *string = NULL;
+    JSON_Value *temp_value = NULL;
+    JSON_Array *array = NULL;
+    JSON_Object *object = NULL;
+    size_t i = 0, count = 0;
+    double num = 0.0;
+    int written = -1, written_total = 0;
+
+    switch (json_value_get_type(value)) {
+        case JSONArray:
+            array = json_value_get_array(value);
+            count = json_array_get_count(array);
+            APPEND_STRING("[");
+            if (count > 0 && is_pretty) {
+                APPEND_STRING("\n");
+            }
+            for (i = 0; i < count; i++) {
+                if (is_pretty) {
+                    APPEND_INDENT(level+1);
+                }
+                temp_value = json_array_get_value(array, i);
+                written = json_serialize_to_buffer_r(temp_value, buf, level+1, is_pretty, num_buf);
+                if (written < 0) {
+                    return -1;
+                }
+                if (buf != NULL) {
+                    buf += written;
+                }
+                written_total += written;
+                if (i < (count - 1)) {
+                    APPEND_STRING(",");
+                }
+                if (is_pretty) {
+                    APPEND_STRING("\n");
+                }
+            }
+            if (count > 0 && is_pretty) {
+                APPEND_INDENT(level);
+            }
+            APPEND_STRING("]");
+            return written_total;
+        case JSONObject:
+            object = json_value_get_object(value);
+            count  = json_object_get_count(object);
+            APPEND_STRING("{");
+            if (count > 0 && is_pretty) {
+                APPEND_STRING("\n");
+            }
+            for (i = 0; i < count; i++) {
+                key = json_object_get_name(object, i);
+                if (key == NULL) {
+                    return -1;
+                }
+                if (is_pretty) {
+                    APPEND_INDENT(level+1);
+                }
+                written = json_serialize_string(key, buf);
+                if (written < 0) {
+                    return -1;
+                }
+                if (buf != NULL) {
+                    buf += written;
+                }
+                written_total += written;
+                APPEND_STRING(":");
+                if (is_pretty) {
+                    APPEND_STRING(" ");
+                }
+                temp_value = json_object_get_value(object, key);
+                written = json_serialize_to_buffer_r(temp_value, buf, level+1, is_pretty, num_buf);
+                if (written < 0) {
+                    return -1;
+                }
+                if (buf != NULL) {
+                    buf += written;
+                }
+                written_total += written;
+                if (i < (count - 1)) {
+                    APPEND_STRING(",");
+                }
+                if (is_pretty) {
+                    APPEND_STRING("\n");
+                }
+            }
+            if (count > 0 && is_pretty) {
+                APPEND_INDENT(level);
+            }
+            APPEND_STRING("}");
+            return written_total;
+        case JSONString:
+            string = json_value_get_string(value);
+            if (string == NULL) {
+                return -1;
+            }
+            written = json_serialize_string(string, buf);
+            if (written < 0) {
+                return -1;
+            }
+            if (buf != NULL) {
+                buf += written;
+            }
+            written_total += written;
+            return written_total;
+        case JSONBoolean:
+            if (json_value_get_boolean(value)) {
+                APPEND_STRING("true");
+            } else {
+                APPEND_STRING("false");
+            }
+            return written_total;
+        case JSONNumber:
+            num = json_value_get_number(value);
+            if (buf != NULL) {
+                num_buf = buf;
+            }
+            written = sprintf(num_buf, FLOAT_FORMAT, num);
+            if (written < 0) {
+                return -1;
+            }
+            if (buf != NULL) {
+                buf += written;
+            }
+            written_total += written;
+            return written_total;
+        case JSONNull:
+            APPEND_STRING("null");
+            return written_total;
+        case JSONError:
+            return -1;
+        default:
+            return -1;
+    }
+}
+
+static int json_serialize_string(const char *string, char *buf) {
+    size_t i = 0, len = strlen(string);
+    char c = '\0';
+    int written = -1, written_total = 0;
+    APPEND_STRING("\"");
+    for (i = 0; i < len; i++) {
+        c = string[i];
+        switch (c) {
+            case '\"': APPEND_STRING("\\\""); break;
+            case '\\': APPEND_STRING("\\\\"); break;
+            case '\b': APPEND_STRING("\\b"); break;
+            case '\f': APPEND_STRING("\\f"); break;
+            case '\n': APPEND_STRING("\\n"); break;
+            case '\r': APPEND_STRING("\\r"); break;
+            case '\t': APPEND_STRING("\\t"); break;
+            case '\x00': APPEND_STRING("\\u0000"); break;
+            case '\x01': APPEND_STRING("\\u0001"); break;
+            case '\x02': APPEND_STRING("\\u0002"); break;
+            case '\x03': APPEND_STRING("\\u0003"); break;
+            case '\x04': APPEND_STRING("\\u0004"); break;
+            case '\x05': APPEND_STRING("\\u0005"); break;
+            case '\x06': APPEND_STRING("\\u0006"); break;
+            case '\x07': APPEND_STRING("\\u0007"); break;
+            /* '\x08' duplicate: '\b' */
+            /* '\x09' duplicate: '\t' */
+            /* '\x0a' duplicate: '\n' */
+            case '\x0b': APPEND_STRING("\\u000b"); break;
+            /* '\x0c' duplicate: '\f' */
+            /* '\x0d' duplicate: '\r' */
+            case '\x0e': APPEND_STRING("\\u000e"); break;
+            case '\x0f': APPEND_STRING("\\u000f"); break;
+            case '\x10': APPEND_STRING("\\u0010"); break;
+            case '\x11': APPEND_STRING("\\u0011"); break;
+            case '\x12': APPEND_STRING("\\u0012"); break;
+            case '\x13': APPEND_STRING("\\u0013"); break;
+            case '\x14': APPEND_STRING("\\u0014"); break;
+            case '\x15': APPEND_STRING("\\u0015"); break;
+            case '\x16': APPEND_STRING("\\u0016"); break;
+            case '\x17': APPEND_STRING("\\u0017"); break;
+            case '\x18': APPEND_STRING("\\u0018"); break;
+            case '\x19': APPEND_STRING("\\u0019"); break;
+            case '\x1a': APPEND_STRING("\\u001a"); break;
+            case '\x1b': APPEND_STRING("\\u001b"); break;
+            case '\x1c': APPEND_STRING("\\u001c"); break;
+            case '\x1d': APPEND_STRING("\\u001d"); break;
+            case '\x1e': APPEND_STRING("\\u001e"); break;
+            case '\x1f': APPEND_STRING("\\u001f"); break;
+            case '/':
+                if (parson_escape_slashes) {
+                    APPEND_STRING("\\/");  /* to make json embeddable in xml\/html */
+                } else {
+                    APPEND_STRING("/");
+                }
+                break;
+            default:
+                if (buf != NULL) {
+                    buf[0] = c;
+                    buf += 1;
+                }
+                written_total += 1;
+                break;
+        }
+    }
+    APPEND_STRING("\"");
+    return written_total;
+}
+
+static int append_indent(char *buf, int level) {
+    int i;
+    int written = -1, written_total = 0;
+    for (i = 0; i < level; i++) {
+        APPEND_STRING("    ");
+    }
+    return written_total;
+}
+
+static int append_string(char *buf, const char *string) {
+    if (buf == NULL) {
+        return (int)strlen(string);
+    }
+    return sprintf(buf, "%s", string);
+}
+
+#undef APPEND_STRING
+#undef APPEND_INDENT
+
+/* Parser API */
+JSON_Value * json_parse_file(const char *filename) {
+    char *file_contents = read_file(filename);
+    JSON_Value *output_value = NULL;
+    if (file_contents == NULL) {
+        return NULL;
+    }
+    output_value = json_parse_string(file_contents);
+    parson_free(file_contents);
+    return output_value;
+}
+
+JSON_Value * json_parse_file_with_comments(const char *filename) {
+    char *file_contents = read_file(filename);
+    JSON_Value *output_value = NULL;
+    if (file_contents == NULL) {
+        return NULL;
+    }
+    output_value = json_parse_string_with_comments(file_contents);
+    parson_free(file_contents);
+    return output_value;
+}
+
+JSON_Value * json_parse_string(const char *string) {
+    if (string == NULL) {
+        return NULL;
+    }
+    if (string[0] == '\xEF' && string[1] == '\xBB' && string[2] == '\xBF') {
+        string = string + 3; /* Support for UTF-8 BOM */
+    }
+    return parse_value((const char**)&string, 0);
+}
+
+JSON_Value * json_parse_string_with_comments(const char *string) {
+    JSON_Value *result = NULL;
+    char *string_mutable_copy = NULL, *string_mutable_copy_ptr = NULL;
+    string_mutable_copy = parson_strdup(string);
+    if (string_mutable_copy == NULL) {
+        return NULL;
+    }
+    remove_comments(string_mutable_copy, "/*", "*/");
+    remove_comments(string_mutable_copy, "//", "\n");
+    string_mutable_copy_ptr = string_mutable_copy;
+    result = parse_value((const char**)&string_mutable_copy_ptr, 0);
+    parson_free(string_mutable_copy);
+    return result;
+}
+
+/* JSON Object API */
+
+JSON_Value * json_object_get_value(const JSON_Object *object, const char *name) {
+    if (object == NULL || name == NULL) {
+        return NULL;
+    }
+    return json_object_getn_value(object, name, strlen(name));
+}
+
+const char * json_object_get_string(const JSON_Object *object, const char *name) {
+    return json_value_get_string(json_object_get_value(object, name));
+}
+
+double json_object_get_number(const JSON_Object *object, const char *name) {
+    return json_value_get_number(json_object_get_value(object, name));
+}
+
+JSON_Object * json_object_get_object(const JSON_Object *object, const char *name) {
+    return json_value_get_object(json_object_get_value(object, name));
+}
+
+JSON_Array * json_object_get_array(const JSON_Object *object, const char *name) {
+    return json_value_get_array(json_object_get_value(object, name));
+}
+
+int json_object_get_boolean(const JSON_Object *object, const char *name) {
+    return json_value_get_boolean(json_object_get_value(object, name));
+}
+
+JSON_Value * json_object_dotget_value(const JSON_Object *object, const char *name) {
+    const char *dot_position = strchr(name, '.');
+    if (!dot_position) {
+        return json_object_get_value(object, name);
+    }
+    object = json_value_get_object(json_object_getn_value(object, name, dot_position - name));
+    return json_object_dotget_value(object, dot_position + 1);
+}
+
+const char * json_object_dotget_string(const JSON_Object *object, const char *name) {
+    return json_value_get_string(json_object_dotget_value(object, name));
+}
+
+double json_object_dotget_number(const JSON_Object *object, const char *name) {
+    return json_value_get_number(json_object_dotget_value(object, name));
+}
+
+JSON_Object * json_object_dotget_object(const JSON_Object *object, const char *name) {
+    return json_value_get_object(json_object_dotget_value(object, name));
+}
+
+JSON_Array * json_object_dotget_array(const JSON_Object *object, const char *name) {
+    return json_value_get_array(json_object_dotget_value(object, name));
+}
+
+int json_object_dotget_boolean(const JSON_Object *object, const char *name) {
+    return json_value_get_boolean(json_object_dotget_value(object, name));
+}
+
+size_t json_object_get_count(const JSON_Object *object) {
+    return object ? object->count : 0;
+}
+
+const char * json_object_get_name(const JSON_Object *object, size_t index) {
+    if (object == NULL || index >= json_object_get_count(object)) {
+        return NULL;
+    }
+    return object->names[index];
+}
+
+JSON_Value * json_object_get_value_at(const JSON_Object *object, size_t index) {
+    if (object == NULL || index >= json_object_get_count(object)) {
+        return NULL;
+    }
+    return object->values[index];
+}
+
+JSON_Value *json_object_get_wrapping_value(const JSON_Object *object) {
+    return object->wrapping_value;
+}
+
+int json_object_has_value (const JSON_Object *object, const char *name) {
+    return json_object_get_value(object, name) != NULL;
+}
+
+int json_object_has_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type) {
+    JSON_Value *val = json_object_get_value(object, name);
+    return val != NULL && json_value_get_type(val) == type;
+}
+
+int json_object_dothas_value (const JSON_Object *object, const char *name) {
+    return json_object_dotget_value(object, name) != NULL;
+}
+
+int json_object_dothas_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type) {
+    JSON_Value *val = json_object_dotget_value(object, name);
+    return val != NULL && json_value_get_type(val) == type;
+}
+
+/* JSON Array API */
+JSON_Value * json_array_get_value(const JSON_Array *array, size_t index) {
+    if (array == NULL || index >= json_array_get_count(array)) {
+        return NULL;
+    }
+    return array->items[index];
+}
+
+const char * json_array_get_string(const JSON_Array *array, size_t index) {
+    return json_value_get_string(json_array_get_value(array, index));
+}
+
+double json_array_get_number(const JSON_Array *array, size_t index) {
+    return json_value_get_number(json_array_get_value(array, index));
+}
+
+JSON_Object * json_array_get_object(const JSON_Array *array, size_t index) {
+    return json_value_get_object(json_array_get_value(array, index));
+}
+
+JSON_Array * json_array_get_array(const JSON_Array *array, size_t index) {
+    return json_value_get_array(json_array_get_value(array, index));
+}
+
+int json_array_get_boolean(const JSON_Array *array, size_t index) {
+    return json_value_get_boolean(json_array_get_value(array, index));
+}
+
+size_t json_array_get_count(const JSON_Array *array) {
+    return array ? array->count : 0;
+}
+
+JSON_Value * json_array_get_wrapping_value(const JSON_Array *array) {
+    return array->wrapping_value;
+}
+
+/* JSON Value API */
+JSON_Value_Type json_value_get_type(const JSON_Value *value) {
+    return value ? value->type : JSONError;
+}
+
+JSON_Object * json_value_get_object(const JSON_Value *value) {
+    return json_value_get_type(value) == JSONObject ? value->value.object : NULL;
+}
+
+JSON_Array * json_value_get_array(const JSON_Value *value) {
+    return json_value_get_type(value) == JSONArray ? value->value.array : NULL;
+}
+
+const char * json_value_get_string(const JSON_Value *value) {
+    return json_value_get_type(value) == JSONString ? value->value.string : NULL;
+}
+
+double json_value_get_number(const JSON_Value *value) {
+    return json_value_get_type(value) == JSONNumber ? value->value.number : 0;
+}
+
+int json_value_get_boolean(const JSON_Value *value) {
+    return json_value_get_type(value) == JSONBoolean ? value->value.boolean : -1;
+}
+
+JSON_Value * json_value_get_parent (const JSON_Value *value) {
+    return value ? value->parent : NULL;
+}
+
+void json_value_free(JSON_Value *value) {
+    switch (json_value_get_type(value)) {
+        case JSONObject:
+            json_object_free(value->value.object);
+            break;
+        case JSONString:
+            parson_free(value->value.string);
+            break;
+        case JSONArray:
+            json_array_free(value->value.array);
+            break;
+        default:
+            break;
+    }
+    parson_free(value);
+}
+
+JSON_Value * json_value_init_object(void) {
+    JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
+    if (!new_value) {
+        return NULL;
+    }
+    new_value->parent = NULL;
+    new_value->type = JSONObject;
+    new_value->value.object = json_object_init(new_value);
+    if (!new_value->value.object) {
+        parson_free(new_value);
+        return NULL;
+    }
+    return new_value;
+}
+
+JSON_Value * json_value_init_array(void) {
+    JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
+    if (!new_value) {
+        return NULL;
+    }
+    new_value->parent = NULL;
+    new_value->type = JSONArray;
+    new_value->value.array = json_array_init(new_value);
+    if (!new_value->value.array) {
+        parson_free(new_value);
+        return NULL;
+    }
+    return new_value;
+}
+
+JSON_Value * json_value_init_string(const char *string) {
+    char *copy = NULL;
+    JSON_Value *value;
+    size_t string_len = 0;
+    if (string == NULL) {
+        return NULL;
+    }
+    string_len = strlen(string);
+    if (!is_valid_utf8(string, string_len)) {
+        return NULL;
+    }
+    copy = parson_strndup(string, string_len);
+    if (copy == NULL) {
+        return NULL;
+    }
+    value = json_value_init_string_no_copy(copy);
+    if (value == NULL) {
+        parson_free(copy);
+    }
+    return value;
+}
+
+JSON_Value * json_value_init_number(double number) {
+    JSON_Value *new_value = NULL;
+    if (IS_NUMBER_INVALID(number)) {
+        return NULL;
+    }
+    new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
+    if (new_value == NULL) {
+        return NULL;
+    }
+    new_value->parent = NULL;
+    new_value->type = JSONNumber;
+    new_value->value.number = number;
+    return new_value;
+}
+
+JSON_Value * json_value_init_boolean(int boolean) {
+    JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
+    if (!new_value) {
+        return NULL;
+    }
+    new_value->parent = NULL;
+    new_value->type = JSONBoolean;
+    new_value->value.boolean = boolean ? 1 : 0;
+    return new_value;
+}
+
+JSON_Value * json_value_init_null(void) {
+    JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
+    if (!new_value) {
+        return NULL;
+    }
+    new_value->parent = NULL;
+    new_value->type = JSONNull;
+    return new_value;
+}
+
+JSON_Value * json_value_deep_copy(const JSON_Value *value) {
+    size_t i = 0;
+    JSON_Value *return_value = NULL, *temp_value_copy = NULL, *temp_value = NULL;
+    const char *temp_string = NULL, *temp_key = NULL;
+    char *temp_string_copy = NULL;
+    JSON_Array *temp_array = NULL, *temp_array_copy = NULL;
+    JSON_Object *temp_object = NULL, *temp_object_copy = NULL;
+
+    switch (json_value_get_type(value)) {
+        case JSONArray:
+            temp_array = json_value_get_array(value);
+            return_value = json_value_init_array();
+            if (return_value == NULL) {
+                return NULL;
+            }
+            temp_array_copy = json_value_get_array(return_value);
+            for (i = 0; i < json_array_get_count(temp_array); i++) {
+                temp_value = json_array_get_value(temp_array, i);
+                temp_value_copy = json_value_deep_copy(temp_value);
+                if (temp_value_copy == NULL) {
+                    json_value_free(return_value);
+                    return NULL;
+                }
+                if (json_array_add(temp_array_copy, temp_value_copy) == JSONFailure) {
+                    json_value_free(return_value);
+                    json_value_free(temp_value_copy);
+                    return NULL;
+                }
+            }
+            return return_value;
+        case JSONObject:
+            temp_object = json_value_get_object(value);
+            return_value = json_value_init_object();
+            if (return_value == NULL) {
+                return NULL;
+            }
+            temp_object_copy = json_value_get_object(return_value);
+            for (i = 0; i < json_object_get_count(temp_object); i++) {
+                temp_key = json_object_get_name(temp_object, i);
+                temp_value = json_object_get_value(temp_object, temp_key);
+                temp_value_copy = json_value_deep_copy(temp_value);
+                if (temp_value_copy == NULL) {
+                    json_value_free(return_value);
+                    return NULL;
+                }
+                if (json_object_add(temp_object_copy, temp_key, temp_value_copy) == JSONFailure) {
+                    json_value_free(return_value);
+                    json_value_free(temp_value_copy);
+                    return NULL;
+                }
+            }
+            return return_value;
+        case JSONBoolean:
+            return json_value_init_boolean(json_value_get_boolean(value));
+        case JSONNumber:
+            return json_value_init_number(json_value_get_number(value));
+        case JSONString:
+            temp_string = json_value_get_string(value);
+            if (temp_string == NULL) {
+                return NULL;
+            }
+            temp_string_copy = parson_strdup(temp_string);
+            if (temp_string_copy == NULL) {
+                return NULL;
+            }
+            return_value = json_value_init_string_no_copy(temp_string_copy);
+            if (return_value == NULL) {
+                parson_free(temp_string_copy);
+            }
+            return return_value;
+        case JSONNull:
+            return json_value_init_null();
+        case JSONError:
+            return NULL;
+        default:
+            return NULL;
+    }
+}
+
+size_t json_serialization_size(const JSON_Value *value) {
+    char num_buf[NUM_BUF_SIZE]; /* recursively allocating buffer on stack is a bad idea, so let's do it only once */
+    int res = json_serialize_to_buffer_r(value, NULL, 0, 0, num_buf);
+    return res < 0 ? 0 : (size_t)(res + 1);
+}
+
+JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes) {
+    int written = -1;
+    size_t needed_size_in_bytes = json_serialization_size(value);
+    if (needed_size_in_bytes == 0 || buf_size_in_bytes < needed_size_in_bytes) {
+        return JSONFailure;
+    }
+    written = json_serialize_to_buffer_r(value, buf, 0, 0, NULL);
+    if (written < 0) {
+        return JSONFailure;
+    }
+    return JSONSuccess;
+}
+
+JSON_Status json_serialize_to_file(const JSON_Value *value, const char *filename) {
+    JSON_Status return_code = JSONSuccess;
+    FILE *fp = NULL;
+    char *serialized_string = json_serialize_to_string(value);
+    if (serialized_string == NULL) {
+        return JSONFailure;
+    }
+    fp = fopen(filename, "w");
+    if (fp == NULL) {
+        json_free_serialized_string(serialized_string);
+        return JSONFailure;
+    }
+    if (fputs(serialized_string, fp) == EOF) {
+        return_code = JSONFailure;
+    }
+    if (fclose(fp) == EOF) {
+        return_code = JSONFailure;
+    }
+    json_free_serialized_string(serialized_string);
+    return return_code;
+}
+
+char * json_serialize_to_string(const JSON_Value *value) {
+    JSON_Status serialization_result = JSONFailure;
+    size_t buf_size_bytes = json_serialization_size(value);
+    char *buf = NULL;
+    if (buf_size_bytes == 0) {
+        return NULL;
+    }
+    buf = (char*)parson_malloc(buf_size_bytes);
+    if (buf == NULL) {
+        return NULL;
+    }
+    serialization_result = json_serialize_to_buffer(value, buf, buf_size_bytes);
+    if (serialization_result == JSONFailure) {
+        json_free_serialized_string(buf);
+        return NULL;
+    }
+    return buf;
+}
+
+size_t json_serialization_size_pretty(const JSON_Value *value) {
+    char num_buf[NUM_BUF_SIZE]; /* recursively allocating buffer on stack is a bad idea, so let's do it only once */
+    int res = json_serialize_to_buffer_r(value, NULL, 0, 1, num_buf);
+    return res < 0 ? 0 : (size_t)(res + 1);
+}
+
+JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes) {
+    int written = -1;
+    size_t needed_size_in_bytes = json_serialization_size_pretty(value);
+    if (needed_size_in_bytes == 0 || buf_size_in_bytes < needed_size_in_bytes) {
+        return JSONFailure;
+    }
+    written = json_serialize_to_buffer_r(value, buf, 0, 1, NULL);
+    if (written < 0) {
+        return JSONFailure;
+    }
+    return JSONSuccess;
+}
+
+JSON_Status json_serialize_to_file_pretty(const JSON_Value *value, const char *filename) {
+    JSON_Status return_code = JSONSuccess;
+    FILE *fp = NULL;
+    char *serialized_string = json_serialize_to_string_pretty(value);
+    if (serialized_string == NULL) {
+        return JSONFailure;
+    }
+    fp = fopen(filename, "w");
+    if (fp == NULL) {
+        json_free_serialized_string(serialized_string);
+        return JSONFailure;
+    }
+    if (fputs(serialized_string, fp) == EOF) {
+        return_code = JSONFailure;
+    }
+    if (fclose(fp) == EOF) {
+        return_code = JSONFailure;
+    }
+    json_free_serialized_string(serialized_string);
+    return return_code;
+}
+
+char * json_serialize_to_string_pretty(const JSON_Value *value) {
+    JSON_Status serialization_result = JSONFailure;
+    size_t buf_size_bytes = json_serialization_size_pretty(value);
+    char *buf = NULL;
+    if (buf_size_bytes == 0) {
+        return NULL;
+    }
+    buf = (char*)parson_malloc(buf_size_bytes);
+    if (buf == NULL) {
+        return NULL;
+    }
+    serialization_result = json_serialize_to_buffer_pretty(value, buf, buf_size_bytes);
+    if (serialization_result == JSONFailure) {
+        json_free_serialized_string(buf);
+        return NULL;
+    }
+    return buf;
+}
+
+void json_free_serialized_string(char *string) {
+    parson_free(string);
+}
+
+JSON_Status json_array_remove(JSON_Array *array, size_t ix) {
+    size_t to_move_bytes = 0;
+    if (array == NULL || ix >= json_array_get_count(array)) {
+        return JSONFailure;
+    }
+    json_value_free(json_array_get_value(array, ix));
+    to_move_bytes = (json_array_get_count(array) - 1 - ix) * sizeof(JSON_Value*);
+    memmove(array->items + ix, array->items + ix + 1, to_move_bytes);
+    array->count -= 1;
+    return JSONSuccess;
+}
+
+JSON_Status json_array_replace_value(JSON_Array *array, size_t ix, JSON_Value *value) {
+    if (array == NULL || value == NULL || value->parent != NULL || ix >= json_array_get_count(array)) {
+        return JSONFailure;
+    }
+    json_value_free(json_array_get_value(array, ix));
+    value->parent = json_array_get_wrapping_value(array);
+    array->items[ix] = value;
+    return JSONSuccess;
+}
+
+JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char* string) {
+    JSON_Value *value = json_value_init_string(string);
+    if (value == NULL) {
+        return JSONFailure;
+    }
+    if (json_array_replace_value(array, i, value) == JSONFailure) {
+        json_value_free(value);
+        return JSONFailure;
+    }
+    return JSONSuccess;
+}
+
+JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number) {
+    JSON_Value *value = json_value_init_number(number);
+    if (value == NULL) {
+        return JSONFailure;
+    }
+    if (json_array_replace_value(array, i, value) == JSONFailure) {
+        json_value_free(value);
+        return JSONFailure;
+    }
+    return JSONSuccess;
+}
+
+JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int boolean) {
+    JSON_Value *value = json_value_init_boolean(boolean);
+    if (value == NULL) {
+        return JSONFailure;
+    }
+    if (json_array_replace_value(array, i, value) == JSONFailure) {
+        json_value_free(value);
+        return JSONFailure;
+    }
+    return JSONSuccess;
+}
+
+JSON_Status json_array_replace_null(JSON_Array *array, size_t i) {
+    JSON_Value *value = json_value_init_null();
+    if (value == NULL) {
+        return JSONFailure;
+    }
+    if (json_array_replace_value(array, i, value) == JSONFailure) {
+        json_value_free(value);
+        return JSONFailure;
+    }
+    return JSONSuccess;
+}
+
+JSON_Status json_array_clear(JSON_Array *array) {
+    size_t i = 0;
+    if (array == NULL) {
+        return JSONFailure;
+    }
+    for (i = 0; i < json_array_get_count(array); i++) {
+        json_value_free(json_array_get_value(array, i));
+    }
+    array->count = 0;
+    return JSONSuccess;
+}
+
+JSON_Status json_array_append_value(JSON_Array *array, JSON_Value *value) {
+    if (array == NULL || value == NULL || value->parent != NULL) {
+        return JSONFailure;
+    }
+    return json_array_add(array, value);
+}
+
+JSON_Status json_array_append_string(JSON_Array *array, const char *string) {
+    JSON_Value *value = json_value_init_string(string);
+    if (value == NULL) {
+        return JSONFailure;
+    }
+    if (json_array_append_value(array, value) == JSONFailure) {
+        json_value_free(value);
+        return JSONFailure;
+    }
+    return JSONSuccess;
+}
+
+JSON_Status json_array_append_number(JSON_Array *array, double number) {
+    JSON_Value *value = json_value_init_number(number);
+    if (value == NULL) {
+        return JSONFailure;
+    }
+    if (json_array_append_value(array, value) == JSONFailure) {
+        json_value_free(value);
+        return JSONFailure;
+    }
+    return JSONSuccess;
+}
+
+JSON_Status json_array_append_boolean(JSON_Array *array, int boolean) {
+    JSON_Value *value = json_value_init_boolean(boolean);
+    if (value == NULL) {
+        return JSONFailure;
+    }
+    if (json_array_append_value(array, value) == JSONFailure) {
+        json_value_free(value);
+        return JSONFailure;
+    }
+    return JSONSuccess;
+}
+
+JSON_Status json_array_append_null(JSON_Array *array) {
+    JSON_Value *value = json_value_init_null();
+    if (value == NULL) {
+        return JSONFailure;
+    }
+    if (json_array_append_value(array, value) == JSONFailure) {
+        json_value_free(value);
+        return JSONFailure;
+    }
+    return JSONSuccess;
+}
+
+JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value) {
+    size_t i = 0;
+    JSON_Value *old_value;
+    if (object == NULL || name == NULL || value == NULL || value->parent != NULL) {
+        return JSONFailure;
+    }
+    old_value = json_object_get_value(object, name);
+    if (old_value != NULL) { /* free and overwrite old value */
+        json_value_free(old_value);
+        for (i = 0; i < json_object_get_count(object); i++) {
+            if (strcmp(object->names[i], name) == 0) {
+                value->parent = json_object_get_wrapping_value(object);
+                object->values[i] = value;
+                return JSONSuccess;
+            }
+        }
+    }
+    /* add new key value pair */
+    return json_object_add(object, name, value);
+}
+
+JSON_Status json_object_set_string(JSON_Object *object, const char *name, const char *string) {
+    return json_object_set_value(object, name, json_value_init_string(string));
+}
+
+JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number) {
+    return json_object_set_value(object, name, json_value_init_number(number));
+}
+
+JSON_Status json_object_set_boolean(JSON_Object *object, const char *name, int boolean) {
+    return json_object_set_value(object, name, json_value_init_boolean(boolean));
+}
+
+JSON_Status json_object_set_null(JSON_Object *object, const char *name) {
+    return json_object_set_value(object, name, json_value_init_null());
+}
+
+JSON_Status json_object_dotset_value(JSON_Object *object, const char *name, JSON_Value *value) {
+    const char *dot_pos = NULL;
+    JSON_Value *temp_value = NULL, *new_value = NULL;
+    JSON_Object *temp_object = NULL, *new_object = NULL;
+    JSON_Status status = JSONFailure;
+    size_t name_len = 0;
+    if (object == NULL || name == NULL || value == NULL) {
+        return JSONFailure;
+    }
+    dot_pos = strchr(name, '.');
+    if (dot_pos == NULL) {
+        return json_object_set_value(object, name, value);
+    }
+    name_len = dot_pos - name;
+    temp_value = json_object_getn_value(object, name, name_len);
+    if (temp_value) {
+        /* Don't overwrite existing non-object (unlike json_object_set_value, but it shouldn't be changed at this point) */
+        if (json_value_get_type(temp_value) != JSONObject) {
+            return JSONFailure;
+        }
+        temp_object = json_value_get_object(temp_value);
+        return json_object_dotset_value(temp_object, dot_pos + 1, value);
+    }
+    new_value = json_value_init_object();
+    if (new_value == NULL) {
+        return JSONFailure;
+    }
+    new_object = json_value_get_object(new_value);
+    status = json_object_dotset_value(new_object, dot_pos + 1, value);
+    if (status != JSONSuccess) {
+        json_value_free(new_value);
+        return JSONFailure;
+    }
+    status = json_object_addn(object, name, name_len, new_value);
+    if (status != JSONSuccess) {
+        json_object_dotremove_internal(new_object, dot_pos + 1, 0);
+        json_value_free(new_value);
+        return JSONFailure;
+    }
+    return JSONSuccess;
+}
+
+JSON_Status json_object_dotset_string(JSON_Object *object, const char *name, const char *string) {
+    JSON_Value *value = json_value_init_string(string);
+    if (value == NULL) {
+        return JSONFailure;
+    }
+    if (json_object_dotset_value(object, name, value) == JSONFailure) {
+        json_value_free(value);
+        return JSONFailure;
+    }
+    return JSONSuccess;
+}
+
+JSON_Status json_object_dotset_number(JSON_Object *object, const char *name, double number) {
+    JSON_Value *value = json_value_init_number(number);
+    if (value == NULL) {
+        return JSONFailure;
+    }
+    if (json_object_dotset_value(object, name, value) == JSONFailure) {
+        json_value_free(value);
+        return JSONFailure;
+    }
+    return JSONSuccess;
+}
+
+JSON_Status json_object_dotset_boolean(JSON_Object *object, const char *name, int boolean) {
+    JSON_Value *value = json_value_init_boolean(boolean);
+    if (value == NULL) {
+        return JSONFailure;
+    }
+    if (json_object_dotset_value(object, name, value) == JSONFailure) {
+        json_value_free(value);
+        return JSONFailure;
+    }
+    return JSONSuccess;
+}
+
+JSON_Status json_object_dotset_null(JSON_Object *object, const char *name) {
+    JSON_Value *value = json_value_init_null();
+    if (value == NULL) {
+        return JSONFailure;
+    }
+    if (json_object_dotset_value(object, name, value) == JSONFailure) {
+        json_value_free(value);
+        return JSONFailure;
+    }
+    return JSONSuccess;
+}
+
+JSON_Status json_object_remove(JSON_Object *object, const char *name) {
+    return json_object_remove_internal(object, name, 1);
+}
+
+JSON_Status json_object_dotremove(JSON_Object *object, const char *name) {
+    return json_object_dotremove_internal(object, name, 1);
+}
+
+JSON_Status json_object_clear(JSON_Object *object) {
+    size_t i = 0;
+    if (object == NULL) {
+        return JSONFailure;
+    }
+    for (i = 0; i < json_object_get_count(object); i++) {
+        parson_free(object->names[i]);
+        json_value_free(object->values[i]);
+    }
+    object->count = 0;
+    return JSONSuccess;
+}
+
+JSON_Status json_validate(const JSON_Value *schema, const JSON_Value *value) {
+    JSON_Value *temp_schema_value = NULL, *temp_value = NULL;
+    JSON_Array *schema_array = NULL, *value_array = NULL;
+    JSON_Object *schema_object = NULL, *value_object = NULL;
+    JSON_Value_Type schema_type = JSONError, value_type = JSONError;
+    const char *key = NULL;
+    size_t i = 0, count = 0;
+    if (schema == NULL || value == NULL) {
+        return JSONFailure;
+    }
+    schema_type = json_value_get_type(schema);
+    value_type = json_value_get_type(value);
+    if (schema_type != value_type && schema_type != JSONNull) { /* null represents all values */
+        return JSONFailure;
+    }
+    switch (schema_type) {
+        case JSONArray:
+            schema_array = json_value_get_array(schema);
+            value_array = json_value_get_array(value);
+            count = json_array_get_count(schema_array);
+            if (count == 0) {
+                return JSONSuccess; /* Empty array allows all types */
+            }
+            /* Get first value from array, rest is ignored */
+            temp_schema_value = json_array_get_value(schema_array, 0);
+            for (i = 0; i < json_array_get_count(value_array); i++) {
+                temp_value = json_array_get_value(value_array, i);
+                if (json_validate(temp_schema_value, temp_value) == JSONFailure) {
+                    return JSONFailure;
+                }
+            }
+            return JSONSuccess;
+        case JSONObject:
+            schema_object = json_value_get_object(schema);
+            value_object = json_value_get_object(value);
+            count = json_object_get_count(schema_object);
+            if (count == 0) {
+                return JSONSuccess; /* Empty object allows all objects */
+            } else if (json_object_get_count(value_object) < count) {
+                return JSONFailure; /* Tested object mustn't have less name-value pairs than schema */
+            }
+            for (i = 0; i < count; i++) {
+                key = json_object_get_name(schema_object, i);
+                temp_schema_value = json_object_get_value(schema_object, key);
+                temp_value = json_object_get_value(value_object, key);
+                if (temp_value == NULL) {
+                    return JSONFailure;
+                }
+                if (json_validate(temp_schema_value, temp_value) == JSONFailure) {
+                    return JSONFailure;
+                }
+            }
+            return JSONSuccess;
+        case JSONString: case JSONNumber: case JSONBoolean: case JSONNull:
+            return JSONSuccess; /* equality already tested before switch */
+        case JSONError: default:
+            return JSONFailure;
+    }
+}
+
+int json_value_equals(const JSON_Value *a, const JSON_Value *b) {
+    JSON_Object *a_object = NULL, *b_object = NULL;
+    JSON_Array *a_array = NULL, *b_array = NULL;
+    const char *a_string = NULL, *b_string = NULL;
+    const char *key = NULL;
+    size_t a_count = 0, b_count = 0, i = 0;
+    JSON_Value_Type a_type, b_type;
+    a_type = json_value_get_type(a);
+    b_type = json_value_get_type(b);
+    if (a_type != b_type) {
+        return 0;
+    }
+    switch (a_type) {
+        case JSONArray:
+            a_array = json_value_get_array(a);
+            b_array = json_value_get_array(b);
+            a_count = json_array_get_count(a_array);
+            b_count = json_array_get_count(b_array);
+            if (a_count != b_count) {
+                return 0;
+            }
+            for (i = 0; i < a_count; i++) {
+                if (!json_value_equals(json_array_get_value(a_array, i),
+                                       json_array_get_value(b_array, i))) {
+                    return 0;
+                }
+            }
+            return 1;
+        case JSONObject:
+            a_object = json_value_get_object(a);
+            b_object = json_value_get_object(b);
+            a_count = json_object_get_count(a_object);
+            b_count = json_object_get_count(b_object);
+            if (a_count != b_count) {
+                return 0;
+            }
+            for (i = 0; i < a_count; i++) {
+                key = json_object_get_name(a_object, i);
+                if (!json_value_equals(json_object_get_value(a_object, key),
+                                       json_object_get_value(b_object, key))) {
+                    return 0;
+                }
+            }
+            return 1;
+        case JSONString:
+            a_string = json_value_get_string(a);
+            b_string = json_value_get_string(b);
+            if (a_string == NULL || b_string == NULL) {
+                return 0; /* shouldn't happen */
+            }
+            return strcmp(a_string, b_string) == 0;
+        case JSONBoolean:
+            return json_value_get_boolean(a) == json_value_get_boolean(b);
+        case JSONNumber:
+            return fabs(json_value_get_number(a) - json_value_get_number(b)) < 0.000001; /* EPSILON */
+        case JSONError:
+            return 1;
+        case JSONNull:
+            return 1;
+        default:
+            return 1;
+    }
+}
+
+JSON_Value_Type json_type(const JSON_Value *value) {
+    return json_value_get_type(value);
+}
+
+JSON_Object * json_object (const JSON_Value *value) {
+    return json_value_get_object(value);
+}
+
+JSON_Array * json_array  (const JSON_Value *value) {
+    return json_value_get_array(value);
+}
+
+const char * json_string (const JSON_Value *value) {
+    return json_value_get_string(value);
+}
+
+double json_number (const JSON_Value *value) {
+    return json_value_get_number(value);
+}
+
+int json_boolean(const JSON_Value *value) {
+    return json_value_get_boolean(value);
+}
+
+void json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON_Free_Function free_fun) {
+    parson_malloc = malloc_fun;
+    parson_free = free_fun;
+}
+
+void json_set_escape_slashes(int escape_slashes) {
+    parson_escape_slashes = escape_slashes;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/deps/parson/parson.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/deps/parson/parson.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/deps/parson/parson.h	(revision 453)
@@ -0,0 +1,240 @@
+/*
+ SPDX-License-Identifier: MIT
+
+ Parson ( http://kgabis.github.com/parson/ )
+ Copyright (c) 2012 - 2019 Krzysztof Gabis
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+#ifndef parson_parson_h
+#define parson_parson_h
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stddef.h>   /* size_t */
+
+/* Types and enums */
+typedef struct json_object_t JSON_Object;
+typedef struct json_array_t  JSON_Array;
+typedef struct json_value_t  JSON_Value;
+
+enum json_value_type {
+    JSONError   = -1,
+    JSONNull    = 1,
+    JSONString  = 2,
+    JSONNumber  = 3,
+    JSONObject  = 4,
+    JSONArray   = 5,
+    JSONBoolean = 6
+};
+typedef int JSON_Value_Type;
+
+enum json_result_t {
+    JSONSuccess = 0,
+    JSONFailure = -1
+};
+typedef int JSON_Status;
+
+typedef void * (*JSON_Malloc_Function)(size_t);
+typedef void   (*JSON_Free_Function)(void *);
+
+/* Call only once, before calling any other function from parson API. If not called, malloc and free
+   from stdlib will be used for all allocations */
+void json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON_Free_Function free_fun);
+
+/* Sets if slashes should be escaped or not when serializing JSON. By default slashes are escaped.
+ This function sets a global setting and is not thread safe. */
+void json_set_escape_slashes(int escape_slashes);
+
+/* Parses first JSON value in a file, returns NULL in case of error */
+JSON_Value * json_parse_file(const char *filename);
+
+/* Parses first JSON value in a file and ignores comments (/ * * / and //),
+   returns NULL in case of error */
+JSON_Value * json_parse_file_with_comments(const char *filename);
+
+/*  Parses first JSON value in a string, returns NULL in case of error */
+JSON_Value * json_parse_string(const char *string);
+
+/*  Parses first JSON value in a string and ignores comments (/ * * / and //),
+    returns NULL in case of error */
+JSON_Value * json_parse_string_with_comments(const char *string);
+
+/* Serialization */
+size_t      json_serialization_size(const JSON_Value *value); /* returns 0 on fail */
+JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes);
+JSON_Status json_serialize_to_file(const JSON_Value *value, const char *filename);
+char *      json_serialize_to_string(const JSON_Value *value);
+
+/* Pretty serialization */
+size_t      json_serialization_size_pretty(const JSON_Value *value); /* returns 0 on fail */
+JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes);
+JSON_Status json_serialize_to_file_pretty(const JSON_Value *value, const char *filename);
+char *      json_serialize_to_string_pretty(const JSON_Value *value);
+
+void        json_free_serialized_string(char *string); /* frees string from json_serialize_to_string and json_serialize_to_string_pretty */
+
+/* Comparing */
+int  json_value_equals(const JSON_Value *a, const JSON_Value *b);
+
+/* Validation
+   This is *NOT* JSON Schema. It validates json by checking if object have identically
+   named fields with matching types.
+   For example schema {"name":"", "age":0} will validate
+   {"name":"Joe", "age":25} and {"name":"Joe", "age":25, "gender":"m"},
+   but not {"name":"Joe"} or {"name":"Joe", "age":"Cucumber"}.
+   In case of arrays, only first value in schema is checked against all values in tested array.
+   Empty objects ({}) validate all objects, empty arrays ([]) validate all arrays,
+   null validates values of every type.
+ */
+JSON_Status json_validate(const JSON_Value *schema, const JSON_Value *value);
+
+/*
+ * JSON Object
+ */
+JSON_Value  * json_object_get_value  (const JSON_Object *object, const char *name);
+const char  * json_object_get_string (const JSON_Object *object, const char *name);
+JSON_Object * json_object_get_object (const JSON_Object *object, const char *name);
+JSON_Array  * json_object_get_array  (const JSON_Object *object, const char *name);
+double        json_object_get_number (const JSON_Object *object, const char *name); /* returns 0 on fail */
+int           json_object_get_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */
+
+/* dotget functions enable addressing values with dot notation in nested objects,
+ just like in structs or c++/java/c# objects (e.g. objectA.objectB.value).
+ Because valid names in JSON can contain dots, some values may be inaccessible
+ this way. */
+JSON_Value  * json_object_dotget_value  (const JSON_Object *object, const char *name);
+const char  * json_object_dotget_string (const JSON_Object *object, const char *name);
+JSON_Object * json_object_dotget_object (const JSON_Object *object, const char *name);
+JSON_Array  * json_object_dotget_array  (const JSON_Object *object, const char *name);
+double        json_object_dotget_number (const JSON_Object *object, const char *name); /* returns 0 on fail */
+int           json_object_dotget_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */
+
+/* Functions to get available names */
+size_t        json_object_get_count   (const JSON_Object *object);
+const char  * json_object_get_name    (const JSON_Object *object, size_t index);
+JSON_Value  * json_object_get_value_at(const JSON_Object *object, size_t index);
+JSON_Value  * json_object_get_wrapping_value(const JSON_Object *object);
+
+/* Functions to check if object has a value with a specific name. Returned value is 1 if object has
+ * a value and 0 if it doesn't. dothas functions behave exactly like dotget functions. */
+int json_object_has_value        (const JSON_Object *object, const char *name);
+int json_object_has_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type);
+
+int json_object_dothas_value        (const JSON_Object *object, const char *name);
+int json_object_dothas_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type);
+
+/* Creates new name-value pair or frees and replaces old value with a new one.
+ * json_object_set_value does not copy passed value so it shouldn't be freed afterwards. */
+JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value);
+JSON_Status json_object_set_string(JSON_Object *object, const char *name, const char *string);
+JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number);
+JSON_Status json_object_set_boolean(JSON_Object *object, const char *name, int boolean);
+JSON_Status json_object_set_null(JSON_Object *object, const char *name);
+
+/* Works like dotget functions, but creates whole hierarchy if necessary.
+ * json_object_dotset_value does not copy passed value so it shouldn't be freed afterwards. */
+JSON_Status json_object_dotset_value(JSON_Object *object, const char *name, JSON_Value *value);
+JSON_Status json_object_dotset_string(JSON_Object *object, const char *name, const char *string);
+JSON_Status json_object_dotset_number(JSON_Object *object, const char *name, double number);
+JSON_Status json_object_dotset_boolean(JSON_Object *object, const char *name, int boolean);
+JSON_Status json_object_dotset_null(JSON_Object *object, const char *name);
+
+/* Frees and removes name-value pair */
+JSON_Status json_object_remove(JSON_Object *object, const char *name);
+
+/* Works like dotget function, but removes name-value pair only on exact match. */
+JSON_Status json_object_dotremove(JSON_Object *object, const char *key);
+
+/* Removes all name-value pairs in object */
+JSON_Status json_object_clear(JSON_Object *object);
+
+/*
+ *JSON Array
+ */
+JSON_Value  * json_array_get_value  (const JSON_Array *array, size_t index);
+const char  * json_array_get_string (const JSON_Array *array, size_t index);
+JSON_Object * json_array_get_object (const JSON_Array *array, size_t index);
+JSON_Array  * json_array_get_array  (const JSON_Array *array, size_t index);
+double        json_array_get_number (const JSON_Array *array, size_t index); /* returns 0 on fail */
+int           json_array_get_boolean(const JSON_Array *array, size_t index); /* returns -1 on fail */
+size_t        json_array_get_count  (const JSON_Array *array);
+JSON_Value  * json_array_get_wrapping_value(const JSON_Array *array);
+    
+/* Frees and removes value at given index, does nothing and returns JSONFailure if index doesn't exist.
+ * Order of values in array may change during execution.  */
+JSON_Status json_array_remove(JSON_Array *array, size_t i);
+
+/* Frees and removes from array value at given index and replaces it with given one.
+ * Does nothing and returns JSONFailure if index doesn't exist.
+ * json_array_replace_value does not copy passed value so it shouldn't be freed afterwards. */
+JSON_Status json_array_replace_value(JSON_Array *array, size_t i, JSON_Value *value);
+JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char* string);
+JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number);
+JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int boolean);
+JSON_Status json_array_replace_null(JSON_Array *array, size_t i);
+
+/* Frees and removes all values from array */
+JSON_Status json_array_clear(JSON_Array *array);
+
+/* Appends new value at the end of array.
+ * json_array_append_value does not copy passed value so it shouldn't be freed afterwards. */
+JSON_Status json_array_append_value(JSON_Array *array, JSON_Value *value);
+JSON_Status json_array_append_string(JSON_Array *array, const char *string);
+JSON_Status json_array_append_number(JSON_Array *array, double number);
+JSON_Status json_array_append_boolean(JSON_Array *array, int boolean);
+JSON_Status json_array_append_null(JSON_Array *array);
+
+/*
+ *JSON Value
+ */
+JSON_Value * json_value_init_object (void);
+JSON_Value * json_value_init_array  (void);
+JSON_Value * json_value_init_string (const char *string); /* copies passed string */
+JSON_Value * json_value_init_number (double number);
+JSON_Value * json_value_init_boolean(int boolean);
+JSON_Value * json_value_init_null   (void);
+JSON_Value * json_value_deep_copy   (const JSON_Value *value);
+void         json_value_free        (JSON_Value *value);
+
+JSON_Value_Type json_value_get_type   (const JSON_Value *value);
+JSON_Object *   json_value_get_object (const JSON_Value *value);
+JSON_Array  *   json_value_get_array  (const JSON_Value *value);
+const char  *   json_value_get_string (const JSON_Value *value);
+double          json_value_get_number (const JSON_Value *value);
+int             json_value_get_boolean(const JSON_Value *value);
+JSON_Value  *   json_value_get_parent (const JSON_Value *value);
+
+/* Same as above, but shorter */
+JSON_Value_Type json_type   (const JSON_Value *value);
+JSON_Object *   json_object (const JSON_Value *value);
+JSON_Array  *   json_array  (const JSON_Value *value);
+const char  *   json_string (const JSON_Value *value);
+double          json_number (const JSON_Value *value);
+int             json_boolean(const JSON_Value *value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/deps/umock-c/inc/umock_c/umock_c_prod.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/deps/umock-c/inc/umock_c/umock_c_prod.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/deps/umock-c/inc/umock_c/umock_c_prod.h	(revision 453)
@@ -0,0 +1,123 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include "azure_macro_utils/macro_utils.h"
+
+#undef MOCKABLE_FUNCTION
+#undef MOCKABLE_FUNCTION_WITH_RETURNS
+#undef MOCKABLE_FUNCTION_WITH_CODE
+#undef MOCKABLE_FUNCTION_WITH_CODE_END
+#undef IMPLEMENT_MOCKABLE_FUNCTION
+#undef MOCKABLE_INTERFACE
+
+/* This header is meant to be included by production code headers, so that the MOCKABLE_FUNCTION gets enabled. */
+/* 
+    If you are porting to a new platform and do not want to build the tests, but only the production code,
+    simply make sure that this file is in the include path (either by copying it to your inc folder or 
+    by adjusting the include paths).
+*/
+
+#define DO_NOTHING_WITH_RETURN_VALUES(success_return_value, failure_return_value) \
+
+/* These 2 macros are used to check if a type is "void" or not */
+#define UMOCK_C_PROD_TEST_void 0
+#define UMOCK_C_PROD_IS_NOT_VOID(x) \
+    MU_IF(MU_C2(UMOCK_C_PROD_TEST_,x), 1, 0)
+
+#ifdef ENABLE_MOCKS
+
+#ifdef ENABLE_MOCK_FILTERING
+#define ENABLE_MOCK_FILTERING_SWITCH 1
+#else
+#define ENABLE_MOCK_FILTERING_SWITCH 0
+#endif
+
+#define UMOCK_C_PROD_ARG_IN_SIGNATURE(count, arg_type, arg_name) arg_type arg_name MU_IFCOMMA(count)
+
+#define MOCKABLE_FUNCTION_SIGNATURE(modifiers, result, function, ...) \
+    result modifiers function(MU_IF(MU_COUNT_ARG(__VA_ARGS__),,void) MU_FOR_EACH_2_COUNTED(UMOCK_C_PROD_ARG_IN_SIGNATURE, __VA_ARGS__))
+
+#define MOCKABLE_FUNCTION_DISABLED(do_returns, modifiers, result, function, ...) \
+    result modifiers function(MU_IF(MU_COUNT_ARG(__VA_ARGS__), , void) MU_FOR_EACH_2_COUNTED(UMOCK_C_PROD_ARG_IN_SIGNATURE, __VA_ARGS__)); \
+    MU_IF(do_returns, MU_IF(UMOCK_C_PROD_IS_NOT_VOID(result), DO_NOTHING_WITH_RETURN_VALUES,), )
+
+/* Codes_SRS_UMOCK_C_LIB_01_001: [MOCKABLE_FUNCTION shall be used to wrap function definition allowing the user to declare a function that can be mocked.]*/
+#define MOCKABLE_FUNCTION(modifiers, result, function, ...) \
+    MU_IF(ENABLE_MOCK_FILTERING_SWITCH,MU_IF(MU_C2(please_mock_, function),MOCKABLE_FUNCTION_DISABLED,MOCKABLE_FUNCTION_UMOCK_INTERNAL_WITH_MOCK), MOCKABLE_FUNCTION_UMOCK_INTERNAL_WITH_MOCK) (0, modifiers, result, function, __VA_ARGS__)
+
+/* Codes_SRS_UMOCK_C_LIB_01_212: [ MOCKABLE_FUNCTION_WITH_RETURNS shall be used to wrap function definitions, allowing the user to declare a function that can be mocked and aditionally declares the values that are to be returned in case of success and failure. ]*/
+#define MOCKABLE_FUNCTION_WITH_RETURNS(modifiers, result, function, ...) \
+    MU_IF(ENABLE_MOCK_FILTERING_SWITCH,MU_IF(MU_C2(please_mock_, function),MOCKABLE_FUNCTION_DISABLED,MOCKABLE_FUNCTION_UMOCK_INTERNAL_WITH_MOCK), MOCKABLE_FUNCTION_UMOCK_INTERNAL_WITH_MOCK) (1, modifiers, result, function, __VA_ARGS__)
+
+// The below MOCKABLE_FUNCTION_WITH_CODE macros are a temporary solution and should not be used for long term
+// They will be removed once the real support is in umock_c
+#define MOCKABLE_FUNCTION_WITH_CODE(modifiers, result, function, ...) \
+    MOCKABLE_FUNCTION_INTERNAL_WITH_CODE(modifiers, result, function, __VA_ARGS__)
+
+#define MOCKABLE_FUNCTION_WITH_CODE_END(...) \
+    MOCKABLE_FUNCTION_END(__VA_ARGS__)
+
+/* Codes_SRS_UMOCK_C_LIB_01_217: [ In the presence of the ENABLE_MOCKS define, IMPLEMENT_MOCKABLE_FUNCTION shall expand to the signature of the function, but the name shall be changed to be prefix with real_. ]*/
+#define IMPLEMENT_MOCKABLE_FUNCTION(modifiers, result, function, ...) \
+    MOCKABLE_FUNCTION_SIGNATURE(modifiers, result, MU_C2(real_, function), __VA_ARGS__)
+
+#define EXPAND_ENTRY(A) \
+    MOCKABLE_##A
+
+#define REGISTER_GLOBAL_MOCK_REAL_FUNCTION(modifiers, result, function, ...) \
+    REGISTER_GLOBAL_MOCK_HOOK(function, MU_C2(real_, function));
+
+#define REGISTER_GLOBAL_MOCK_REAL(A) \
+    REGISTER_GLOBAL_MOCK_REAL_##A
+
+/* Codes_SRS_UMOCK_C_LIB_01_215: [ Each item in ... shall be an entry for one mockable function. ]*/
+/* Codes_SRS_UMOCK_C_LIB_01_216: [ Each item in ... shall be defined using a macro called FUNCTION, which shall be an alias for MOCKABLE_FUNCTION. ]*/
+#define MOCKABLE_INTERFACE(interface_name, ...) \
+    MU_FOR_EACH_1(EXPAND_ENTRY, __VA_ARGS__) \
+    static void MU_C2(register_reals_, interface_name)(void) \
+    { \
+        MU_FOR_EACH_1(REGISTER_GLOBAL_MOCK_REAL, __VA_ARGS__); \
+    } \
+
+#include "umock_c/umock_c.h"
+
+#else
+
+#define UMOCK_C_PROD_ARG_IN_SIGNATURE(count, arg_type, arg_name) arg_type arg_name MU_IFCOMMA(count)
+
+#define MOCKABLE_FUNCTION_SIGNATURE(modifiers, result, function, ...) \
+    result modifiers function(MU_IF(MU_COUNT_ARG(__VA_ARGS__),,void) MU_FOR_EACH_2_COUNTED(UMOCK_C_PROD_ARG_IN_SIGNATURE, __VA_ARGS__))
+
+/* Codes_SRS_UMOCK_C_LIB_01_002: [The macro shall generate a function signature in case ENABLE_MOCKS is not defined.] */
+/* Codes_SRS_UMOCK_C_LIB_01_005: [If ENABLE_MOCKS is not defined, MOCKABLE_FUNCTION shall only generate a declaration for the function.] */
+/* Codes_SRS_UMOCK_C_LIB_01_001: [MOCKABLE_FUNCTION shall be used to wrap function definition allowing the user to declare a function that can be mocked.]*/
+#define MOCKABLE_FUNCTION(modifiers, result, function, ...) \
+    MOCKABLE_FUNCTION_SIGNATURE(modifiers, result, function, __VA_ARGS__);
+
+/* Codes_SRS_UMOCK_C_LIB_01_213: [ The macro shall generate a function signature in case ENABLE_MOCKS is not defined. ]*/
+/* Codes_SRS_UMOCK_C_LIB_01_212: [ MOCKABLE_FUNCTION_WITH_RETURNS shall be used to wrap function definitions, allowing the user to declare a function that can be mocked and aditionally declares the values that are to be returned in case of success and failure. ]*/
+#define MOCKABLE_FUNCTION_WITH_RETURNS(modifiers, result, function, ...) \
+    result modifiers function(MU_IF(MU_COUNT_ARG(__VA_ARGS__),,void) MU_FOR_EACH_2_COUNTED(UMOCK_C_PROD_ARG_IN_SIGNATURE, __VA_ARGS__)); \
+    MU_IF(UMOCK_C_PROD_IS_NOT_VOID(result), DO_NOTHING_WITH_RETURN_VALUES,)
+
+#define UMOCK_C_PROD_ARG_IN_SIGNATURE_2(count, arg_type, arg_name) 
+
+// The below MOCKABLE_FUNCTION_WITH_CODE macros are a temporary solution and should not be used for long term
+// They will be removed once the real support is in umock_c
+#define MOCKABLE_FUNCTION_WITH_CODE(modifiers, result, function, ...) \
+    MOCKABLE_FUNCTION_SIGNATURE(modifiers, result, function, __VA_ARGS__)
+
+/* Codes_SRS_UMOCK_C_LIB_01_218: [ If ENABLE_MOCKS is not defined, IMPLEMENT_MOCKABLE_FUNCTION shall expand to the signature of the function. ]*/
+#define IMPLEMENT_MOCKABLE_FUNCTION(modifiers, result, function, ...) \
+    MOCKABLE_FUNCTION_SIGNATURE(modifiers, result, function, __VA_ARGS__)
+
+#define EXPAND_PROD_ENTRY(A) MOCKABLE_##A
+
+/* Codes_SRS_UMOCK_C_LIB_01_215: [ Each item in ... shall be an entry for one mockable function. ]*/
+/* Codes_SRS_UMOCK_C_LIB_01_216: [ Each item in ... shall be defined using a macro called FUNCTION, which shall be an alias for MOCKABLE_FUNCTION. ]*/
+#define MOCKABLE_INTERFACE(interface_name, ...) \
+    MU_FOR_EACH_1(EXPAND_PROD_ENTRY, __VA_ARGS__)
+
+#define MOCKABLE_FUNCTION_WITH_CODE_END(...) \
+
+#endif
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/blob.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/blob.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/blob.h	(revision 453)
@@ -0,0 +1,81 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/** @file blob.h
+*    @brief Contains blob APIs needed for File Upload feature of IoTHub client.
+*
+*    @details IoTHub client needs to upload a byte array by using blob storage API
+*             IoTHub service provides the complete SAS URI to execute a PUT request
+*             that will upload the data.
+*
+*/
+
+#ifndef BLOB_H
+#define BLOB_H
+
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/buffer_.h"
+#include "azure_c_shared_utility/strings_types.h"
+#include "azure_c_shared_utility/httpapiex.h"
+#include "iothub_client_core_ll.h"
+#include "azure_c_shared_utility/shared_util_options.h"
+
+#ifdef __cplusplus
+#include <cstddef>
+extern "C"
+{
+#else
+#include <stddef.h>
+#endif
+
+#include "umock_c/umock_c_prod.h"
+
+/* Allow unit tests to override MAX_BLOCK_COUNT to something much smaller */
+#ifndef MAX_BLOCK_COUNT
+/* Maximum count of blocks uploaded is 50000, per server*/
+#define MAX_BLOCK_COUNT 50000
+#endif
+
+#define BLOB_RESULT_VALUES \
+    BLOB_OK,               \
+    BLOB_ERROR,            \
+    BLOB_NOT_IMPLEMENTED,  \
+    BLOB_HTTP_ERROR,       \
+    BLOB_INVALID_ARG,      \
+    BLOB_ABORTED
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(BLOB_RESULT, BLOB_RESULT_VALUES)
+
+/**
+* @brief  Synchronously uploads a byte array to blob storage
+*
+* @param  SASURI            The URI to use to upload data
+* @param  getDataCallbackEx A callback to be invoked to acquire the file chunks to be uploaded, as well as to indicate the status of the upload of the previous block.
+* @param  context           Any data provided by the user to serve as context on getDataCallback.
+* @param  httpStatus        A pointer to an out argument receiving the HTTP status (available only when the return value is BLOB_OK)
+* @param  httpResponse      A BUFFER_HANDLE that receives the HTTP response from the server (available only when the return value is BLOB_OK)
+* @param  certificates      A null terminated string containing CA certificates to be used
+* @param    proxyOptions    A structure that contains optional web proxy information
+*
+* @return    A @c BLOB_RESULT. BLOB_OK means the blob has been uploaded successfully. Any other value indicates an error
+*/
+MOCKABLE_FUNCTION(, BLOB_RESULT, Blob_UploadMultipleBlocksFromSasUri, const char*, SASURI, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context, unsigned int*, httpStatus, BUFFER_HANDLE, httpResponse, const char*, certificates, HTTP_PROXY_OPTIONS*, proxyOptions)
+
+/**
+* @brief  Synchronously uploads a byte array as a new block to blob storage
+*
+* @param  requestContent      The data to upload
+* @param  blockId             The block id (from 00000 to 49999)
+* @param  xml                 The XML file containing the blockId list
+* @param  relativePath        The destination path within the storage
+* @param  httpApiExHandle     The connection handle
+* @param  httpStatus          A pointer to an out argument receiving the HTTP status (available only when the return value is BLOB_OK)
+* @param  httpResponse        A BUFFER_HANDLE that receives the HTTP response from the server (available only when the return value is BLOB_OK)
+*/
+//MOCKABLE_FUNCTION(, BLOB_RESULT, Blob_UploadNextBlock, BUFFER_HANDLE, requestContent, unsigned int, blockID, STRING_HANDLE, xml, const char*, relativePath, HTTPAPIEX_HANDLE, httpApiExHandle, unsigned int*, httpStatus, BUFFER_HANDLE, httpResponse)
+MOCKABLE_FUNCTION(, BLOB_RESULT, Blob_UploadBlock, HTTPAPIEX_HANDLE, httpApiExHandle, const char*, relativePath, BUFFER_HANDLE, requestContent, unsigned int, blockID, STRING_HANDLE, blockIDList, unsigned int*, httpStatus, BUFFER_HANDLE, httpResponse)
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BLOB_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothub_client_authorization.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothub_client_authorization.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothub_client_authorization.h	(revision 453)
@@ -0,0 +1,64 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef IOTHUB_CLIENT_AUTHORIZATION_H
+#define IOTHUB_CLIENT_AUTHORIZATION_H
+
+#include "azure_macro_utils/macro_utils.h"
+#include "umock_c/umock_c_prod.h"
+#include "azure_c_shared_utility/xio.h"
+
+#ifdef __cplusplus
+extern "C" {
+#include <cstdint>
+#else
+#include <stdint.h>
+#include <stdbool.h>
+#endif /* __cplusplus */
+
+typedef struct IOTHUB_AUTHORIZATION_DATA_TAG* IOTHUB_AUTHORIZATION_HANDLE;
+
+#define IOTHUB_CREDENTIAL_TYPE_VALUES       \
+    IOTHUB_CREDENTIAL_TYPE_UNKNOWN,         \
+    IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY,      \
+    IOTHUB_CREDENTIAL_TYPE_X509,            \
+    IOTHUB_CREDENTIAL_TYPE_X509_ECC,        \
+    IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN,       \
+    IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH
+
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(IOTHUB_CREDENTIAL_TYPE, IOTHUB_CREDENTIAL_TYPE_VALUES);
+
+#define SAS_TOKEN_STATUS_VALUES  \
+    SAS_TOKEN_STATUS_FAILED,     \
+    SAS_TOKEN_STATUS_VALID,      \
+    SAS_TOKEN_STATUS_INVALID
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(SAS_TOKEN_STATUS, SAS_TOKEN_STATUS_VALUES);
+
+MOCKABLE_FUNCTION(, IOTHUB_AUTHORIZATION_HANDLE, IoTHubClient_Auth_Create, const char*, device_key, const char*, device_id, const char*, device_sas_token, const char *, module_id);
+MOCKABLE_FUNCTION(, IOTHUB_AUTHORIZATION_HANDLE, IoTHubClient_Auth_CreateFromDeviceAuth, const char*, device_id, const char*, module_id);
+MOCKABLE_FUNCTION(, void, IoTHubClient_Auth_Destroy, IOTHUB_AUTHORIZATION_HANDLE, handle);
+MOCKABLE_FUNCTION(, IOTHUB_CREDENTIAL_TYPE, IoTHubClient_Auth_Set_x509_Type, IOTHUB_AUTHORIZATION_HANDLE, handle, bool, enable_x509);
+MOCKABLE_FUNCTION(, IOTHUB_CREDENTIAL_TYPE, IoTHubClient_Auth_Get_Credential_Type, IOTHUB_AUTHORIZATION_HANDLE, handle);
+MOCKABLE_FUNCTION(, char*, IoTHubClient_Auth_Get_SasToken, IOTHUB_AUTHORIZATION_HANDLE, handle, const char*, scope, size_t, expiry_time_relative_seconds, const char*, key_name);
+MOCKABLE_FUNCTION(, int, IoTHubClient_Auth_Set_xio_Certificate, IOTHUB_AUTHORIZATION_HANDLE, handle, XIO_HANDLE, xio);
+MOCKABLE_FUNCTION(, const char*, IoTHubClient_Auth_Get_DeviceId, IOTHUB_AUTHORIZATION_HANDLE, handle);
+MOCKABLE_FUNCTION(, const char*, IoTHubClient_Auth_Get_ModuleId, IOTHUB_AUTHORIZATION_HANDLE, handle);
+MOCKABLE_FUNCTION(, const char*, IoTHubClient_Auth_Get_DeviceKey, IOTHUB_AUTHORIZATION_HANDLE, handle);
+MOCKABLE_FUNCTION(, SAS_TOKEN_STATUS, IoTHubClient_Auth_Is_SasToken_Valid, IOTHUB_AUTHORIZATION_HANDLE, handle);
+MOCKABLE_FUNCTION(, int, IoTHubClient_Auth_Get_x509_info, IOTHUB_AUTHORIZATION_HANDLE, handle, char**, x509_cert, char**, x509_key);
+MOCKABLE_FUNCTION(, int, IoTHubClient_Auth_Set_SasToken_Expiry, IOTHUB_AUTHORIZATION_HANDLE, handle, size_t, expiry_time_seconds);
+MOCKABLE_FUNCTION(, size_t, IoTHubClient_Auth_Get_SasToken_Expiry, IOTHUB_AUTHORIZATION_HANDLE, handle);
+
+
+#ifdef USE_EDGE_MODULES
+MOCKABLE_FUNCTION(, char*, IoTHubClient_Auth_Get_TrustBundle, IOTHUB_AUTHORIZATION_HANDLE, handle, const char*, certificate_file_name);
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IOTHUB_CLIENT_AUTHORIZATION_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothub_client_diagnostic.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothub_client_diagnostic.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothub_client_diagnostic.h	(revision 453)
@@ -0,0 +1,48 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/** @file   iothub_client_diagnostic.h
+*    @brief  The @c diagnostic is a component that helps to add predefined diagnostic
+            properties to message for end to end diagnostic purpose
+*/
+
+#ifndef IOTHUB_CLIENT_DIAGNOSTIC_H
+#define IOTHUB_CLIENT_DIAGNOSTIC_H
+
+#include "umock_c/umock_c_prod.h"
+
+#include "iothub_message.h"
+#include <stdint.h>
+
+#ifdef __cplusplus
+#include <cstddef>
+extern "C" {
+#else
+#include <stddef.h>
+#endif
+
+/** @brief diagnostic related setting */
+typedef struct IOTHUB_DIAGNOSTIC_SETTING_DATA_TAG
+{
+    uint32_t diagSamplingPercentage;
+    uint32_t currentMessageNumber;
+} IOTHUB_DIAGNOSTIC_SETTING_DATA;
+
+/**
+    * @brief    Adds diagnostic information to message if:
+    *           a. diagSetting->diagSamplingPercentage > 0 and
+    *           b. the number of current message matches sample rule specified by diagSetting->diagSamplingPercentage
+    *
+    * @param    diagSetting        Pointer to an @c IOTHUB_DIAGNOSTIC_SETTING_DATA structure
+    *
+    * @param    messageHandle    message handle
+    *
+    * @return    0 upon success
+    */
+MOCKABLE_FUNCTION(, int, IoTHubClient_Diagnostic_AddIfNecessary, IOTHUB_DIAGNOSTIC_SETTING_DATA *, diagSetting, IOTHUB_MESSAGE_HANDLE, messageHandle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IOTHUB_CLIENT_DIAGNOSTIC_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothub_client_hsm_ll.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothub_client_hsm_ll.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothub_client_hsm_ll.h	(revision 453)
@@ -0,0 +1,22 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/** @file iothub_client_version.h
+*    @brief Functions for managing the client SDK version.
+*/
+
+#ifndef IOTHUB_CLIENT_PROVISIONING_H
+#define IOTHUB_CLIENT_PROVISIONING_H
+
+#include "azure_macro_utils/macro_utils.h"
+#include "umock_c/umock_c_prod.h"
+
+#ifdef USE_PROV_MODULE
+#include "azure_prov_client/internal/iothub_auth_client.h"
+#endif
+
+#include "iothub_client_ll.h"
+
+/*This header is DEPREPCATED and mainatined only for backward compatibility*/
+
+#endif // IOTHUB_CLIENT_PROVISIONING_H
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothub_client_ll_uploadtoblob.h	(revision 453)
@@ -0,0 +1,58 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/** @file iothub_client_ll.h
+*    @brief     APIs that allow a user (usually a device) to communicate
+*             with an Azure IoTHub.
+*
+*    @details IoTHubClient_LL is a module that allows a user (usually a
+*             device) to communicate with an Azure IoTHub. It can send events
+*             and receive messages. At any given moment in time there can only
+*             be at most 1 message callback function.
+*
+*             This API surface contains a set of APIs that allows the user to
+*             interact with the lower layer portion of the IoTHubClient. These APIs
+*             contain @c _LL_ in their name, but retain the same functionality like the
+*             @c IoTHubClient_... APIs, with one difference. If the @c _LL_ APIs are
+*             used then the user is responsible for scheduling when the actual work done
+*             by the IoTHubClient happens (when the data is sent/received on/from the wire).
+*             This is useful for constrained devices where spinning a separate thread is
+*             often not desired.
+*/
+
+#ifndef DONT_USE_UPLOADTOBLOB
+
+#ifndef IOTHUB_CLIENT_LL_UPLOADTOBLOB_H
+#define IOTHUB_CLIENT_LL_UPLOADTOBLOB_H
+
+#include "iothub_client_core_ll.h"
+#include "internal/iothub_client_authorization.h"
+
+#include "umock_c/umock_c_prod.h"
+#ifdef __cplusplus
+#include <cstddef>
+extern "C"
+{
+#else
+#include <stddef.h>
+#endif
+
+    #define BLOCK_SIZE (4*1024*1024)
+
+    typedef struct IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE;
+
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, IoTHubClient_LL_UploadToBlob_Create, const IOTHUB_CLIENT_CONFIG*, config, IOTHUB_AUTHORIZATION_HANDLE, auth_handle);
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_Impl, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle, const char*, destinationFileName, const unsigned char*, source, size_t, size);
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context);
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_SetOption, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle, const char*, optionName, const void*, value);
+    MOCKABLE_FUNCTION(, void, IoTHubClient_LL_UploadToBlob_Destroy, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IOTHUB_CLIENT_LL_UPLOADTOBLOB_H */
+
+#else
+#error "trying to #include iothub_client_ll_uploadtoblob.h in the presence of #define DONT_USE_UPLOADTOBLOB"
+#endif /*DONT_USE_UPLOADTOBLOB*/
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothub_client_private.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothub_client_private.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothub_client_private.h	(revision 453)
@@ -0,0 +1,76 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef IOTHUB_CLIENT_PRIVATE_H
+#define IOTHUB_CLIENT_PRIVATE_H
+
+#include <stdbool.h>
+
+#include "azure_c_shared_utility/constbuffer.h"
+#include "azure_c_shared_utility/doublylinkedlist.h"
+#include "azure_c_shared_utility/tickcounter.h"
+#include "umock_c/umock_c_prod.h"
+
+#include "iothub_message.h"
+#include "internal/iothub_transport_ll_private.h"
+#include "iothub_client_core_common.h"
+#include "iothub_client_core_ll.h"
+
+#ifdef USE_EDGE_MODULES
+#include "internal/iothub_client_edge.h"
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define CLIENT_DEVICE_TYPE_PREFIX "iothubclient"
+#define CLIENT_DEVICE_BACKSLASH "/"
+
+typedef bool(*IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC_EX)(MESSAGE_CALLBACK_INFO* messageData, void* userContextCallback);
+
+MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_SetMessageCallback_Ex, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC_EX, messageCallback, void*, userContextCallback);
+MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_SendMessageDisposition, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, MESSAGE_CALLBACK_INFO*, messageData, IOTHUBMESSAGE_DISPOSITION_RESULT, disposition);
+MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_SetInputMessageCallbackEx, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, inputName, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC_EX, eventHandlerCallbackEx, void *, userContextCallback, size_t, userContextCallbackLength);
+MOCKABLE_FUNCTION(, int, IoTHubClientCore_LL_GetTransportCallbacks, TRANSPORT_CALLBACKS_INFO*, transport_cb);
+
+#ifdef USE_EDGE_MODULES
+/* (Should be replaced after iothub_client refactor)*/
+MOCKABLE_FUNCTION(, IOTHUB_CLIENT_EDGE_HANDLE, IoTHubClientCore_LL_GetEdgeHandle, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle);
+MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_GenericMethodInvoke, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, deviceId, const char*, moduleId, const char*, methodName, const char*, methodPayload, unsigned int, timeout, int*, responseStatus, unsigned char**, responsePayload, size_t*, responsePayloadSize);
+#endif
+
+typedef struct IOTHUB_MESSAGE_LIST_TAG
+{
+    IOTHUB_MESSAGE_HANDLE messageHandle;
+    IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK callback;
+    void* context;
+    DLIST_ENTRY entry;
+    tickcounter_ms_t ms_timesOutAfter; /* a value of "0" means "no timeout", if the IOTHUBCLIENT_LL's handle tickcounter > msTimesOutAfer then the message shall timeout*/
+    tickcounter_ms_t message_timeout_value;
+}IOTHUB_MESSAGE_LIST;
+
+typedef struct IOTHUB_DEVICE_TWIN_TAG
+{
+    uint32_t item_id;
+    tickcounter_ms_t ms_timesOutAfter; /* a value of "0" means "no timeout", if the IOTHUBCLIENT_LL's handle tickcounter > msTimesOutAfer then the message shall timeout*/
+    IOTHUB_CLIENT_REPORTED_STATE_CALLBACK reported_state_callback;
+    CONSTBUFFER_HANDLE report_data_handle;
+    void* context;
+    DLIST_ENTRY entry;
+    IOTHUB_CLIENT_CORE_LL_HANDLE client_handle;
+    IOTHUB_DEVICE_HANDLE device_handle;
+} IOTHUB_DEVICE_TWIN;
+
+union IOTHUB_IDENTITY_INFO_TAG
+{
+    IOTHUB_DEVICE_TWIN* device_twin;
+    IOTHUB_MESSAGE_LIST* iothub_message;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IOTHUB_CLIENT_PRIVATE_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothub_client_retry_control.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothub_client_retry_control.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothub_client_retry_control.h	(revision 453)
@@ -0,0 +1,48 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef IOTHUB_CLIENT_RETRY_CONTROL
+#define IOTHUB_CLIENT_RETRY_CONTROL
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include "azure_c_shared_utility/optionhandler.h"
+#include "umock_c/umock_c_prod.h"
+#include "iothub_client_core_ll.h"
+#include "internal/iothubtransport.h"
+#include "azure_c_shared_utility/const_defines.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+static STATIC_VAR_UNUSED const char* RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS = "initial_wait_time_in_secs";
+static STATIC_VAR_UNUSED const char* RETRY_CONTROL_OPTION_MAX_JITTER_PERCENT = "max_jitter_percent";
+static STATIC_VAR_UNUSED const char* RETRY_CONTROL_OPTION_MAX_DELAY_IN_SECS = "max_delay_in_secs";
+static STATIC_VAR_UNUSED const char* RETRY_CONTROL_OPTION_SAVED_OPTIONS = "retry_control_saved_options";
+
+typedef enum RETRY_ACTION_TAG
+{
+    RETRY_ACTION_RETRY_NOW,
+    RETRY_ACTION_RETRY_LATER,
+    RETRY_ACTION_STOP_RETRYING
+} RETRY_ACTION;
+
+struct RETRY_CONTROL_INSTANCE_TAG;
+typedef struct RETRY_CONTROL_INSTANCE_TAG* RETRY_CONTROL_HANDLE;
+
+MOCKABLE_FUNCTION(, RETRY_CONTROL_HANDLE, retry_control_create, IOTHUB_CLIENT_RETRY_POLICY, policy, unsigned int, max_retry_time_in_secs);
+MOCKABLE_FUNCTION(, int, retry_control_should_retry, RETRY_CONTROL_HANDLE, retry_control_handle, RETRY_ACTION*, retry_action);
+MOCKABLE_FUNCTION(, void, retry_control_reset, RETRY_CONTROL_HANDLE, retry_control_handle);
+MOCKABLE_FUNCTION(, int, retry_control_set_option, RETRY_CONTROL_HANDLE, retry_control_handle, const char*, name, const void*, value);
+MOCKABLE_FUNCTION(, OPTIONHANDLER_HANDLE, retry_control_retrieve_options, RETRY_CONTROL_HANDLE, retry_control_handle);
+MOCKABLE_FUNCTION(, void, retry_control_destroy, RETRY_CONTROL_HANDLE, retry_control_handle);
+
+MOCKABLE_FUNCTION(, int, is_timeout_reached, time_t, start_time, unsigned int, timeout_in_secs, bool*, is_timed_out);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // IOTHUB_CLIENT_RETRY_CONTROL
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothub_internal_consts.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothub_internal_consts.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothub_internal_consts.h	(revision 453)
@@ -0,0 +1,29 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef IOTHUB_INTERNAL_CONSTS_H
+#define IOTHUB_INTERNAL_CONSTS_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    static const char* IOTHUB_API_VERSION = "2019-10-01";
+    // TODO: https://github.com/Azure/azure-iot-sdk-c/issues/1547 tracks removing this preview 
+    // variable once the underlying logic is enabled on all IoTHubs.
+    static const char* IOTHUB_API_PREVIEW_VERSION = "2020-05-31-preview";
+
+    static const char* SECURITY_INTERFACE_INTERNAL_ID = "iothub-interface-internal-id";
+    static const char* SECURITY_INTERFACE_INTERNAL_ID_VALUE = "security*azureiot*com^SecurityAgent^1*0*0";
+    static const char* SECURITY_INTERFACE_ID = "iothub-interface-id";
+    static const char* SECURITY_INTERFACE_ID_MQTT = "ifid";
+    static const char* SECURITY_INTERFACE_ID_VALUE = "urn:azureiot:Security:SecurityAgent:1";
+    static const char* SECURITY_MESSAGE_SCHEMA = "iothub-message-schema";
+    static const char* SECURITY_MESSAGE_SCHEMA_VALUE = "sevent";
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IOTHUB_INTERNAL_CONSTS_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothub_transport_ll_private.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothub_transport_ll_private.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothub_transport_ll_private.h	(revision 453)
@@ -0,0 +1,134 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef IOTHUB_TRANSPORT_LL_PRIVATE_H
+#define IOTHUB_TRANSPORT_LL_PRIVATE_H
+
+#include "iothub_transport_ll.h"
+
+union IOTHUB_IDENTITY_INFO_TAG;
+typedef union IOTHUB_IDENTITY_INFO_TAG IOTHUB_IDENTITY_INFO;
+
+#include "azure_c_shared_utility/doublylinkedlist.h"
+#include "azure_c_shared_utility/strings.h"
+#include "azure_c_shared_utility/platform.h"
+#include "internal/iothub_client_authorization.h"
+#include "iothub_message.h"
+
+struct MESSAGE_DISPOSITION_CONTEXT_TAG;
+typedef struct MESSAGE_DISPOSITION_CONTEXT_TAG* MESSAGE_DISPOSITION_CONTEXT_HANDLE;
+typedef struct MESSAGE_CALLBACK_INFO_TAG
+{
+    IOTHUB_MESSAGE_HANDLE messageHandle;
+    MESSAGE_DISPOSITION_CONTEXT_HANDLE transportContext;
+}MESSAGE_CALLBACK_INFO;
+
+#include "iothub_client_ll.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    typedef bool (*pfTransport_MessageCallbackFromInput)(MESSAGE_CALLBACK_INFO* messageData, void* ctx);
+    typedef bool (*pfTransport_MessageCallback)(MESSAGE_CALLBACK_INFO* messageData, void* ctx);
+    typedef void (*pfTransport_ConnectionStatusCallBack)(IOTHUB_CLIENT_CONNECTION_STATUS status, IOTHUB_CLIENT_CONNECTION_STATUS_REASON reason, void* ctx);
+    typedef void (*pfTransport_SendComplete_Callback)(PDLIST_ENTRY completed, IOTHUB_CLIENT_CONFIRMATION_RESULT result, void* ctx);
+    typedef const char* (*pfTransport_GetOption_Product_Info_Callback)(void* ctx);
+    typedef void (*pfTransport_Twin_ReportedStateComplete_Callback)(uint32_t item_id, int status_code, void* ctx);
+    typedef void (*pfTransport_Twin_RetrievePropertyComplete_Callback)(DEVICE_TWIN_UPDATE_STATE update_state, const unsigned char* payLoad, size_t size, void* ctx);
+    typedef int (*pfTransport_DeviceMethod_Complete_Callback)(const char* method_name, const unsigned char* payLoad, size_t size, METHOD_HANDLE response_id, void* ctx);
+    typedef const char* (*pfTransport_GetOption_Model_Id_Callback)(void* ctx);
+
+    /** @brief    This struct captures device configuration. */
+    typedef struct IOTHUB_DEVICE_CONFIG_TAG
+    {
+        /** @brief    A string that identifies the device. */
+        const char* deviceId;
+
+        /** @brief    The device key used to authenticate the device. */
+        const char* deviceKey;
+
+        /** @brief    The device SAS used to authenticate the device in place of using the device key. */
+        const char* deviceSasToken;
+
+        IOTHUB_AUTHORIZATION_HANDLE authorization_module; // with either SAS Token, x509 Certs, and Device SAS Token
+
+        /** @brief  A string that identifies the module.  Optional. */
+        const char* moduleId;
+    } IOTHUB_DEVICE_CONFIG;
+
+    typedef struct TRANSPORT_CALLBACKS_INFO_TAG
+    {
+        pfTransport_MessageCallbackFromInput msg_input_cb;
+        pfTransport_MessageCallback msg_cb;
+        pfTransport_ConnectionStatusCallBack connection_status_cb;
+        pfTransport_SendComplete_Callback send_complete_cb;
+        pfTransport_GetOption_Product_Info_Callback prod_info_cb;
+        pfTransport_Twin_ReportedStateComplete_Callback twin_rpt_state_complete_cb;
+        pfTransport_Twin_RetrievePropertyComplete_Callback twin_retrieve_prop_complete_cb;
+        pfTransport_DeviceMethod_Complete_Callback method_complete_cb;
+        pfTransport_GetOption_Model_Id_Callback get_model_id_cb;
+    } TRANSPORT_CALLBACKS_INFO;
+
+    typedef STRING_HANDLE (*pfIoTHubTransport_GetHostname)(TRANSPORT_LL_HANDLE handle);
+    typedef IOTHUB_CLIENT_RESULT(*pfIoTHubTransport_SetOption)(TRANSPORT_LL_HANDLE handle, const char *optionName, const void* value);
+    typedef TRANSPORT_LL_HANDLE(*pfIoTHubTransport_Create)(const IOTHUBTRANSPORT_CONFIG* config, TRANSPORT_CALLBACKS_INFO* cb_info, void* ctx);
+    typedef void (*pfIoTHubTransport_Destroy)(TRANSPORT_LL_HANDLE handle);
+    typedef IOTHUB_DEVICE_HANDLE(*pfIotHubTransport_Register)(TRANSPORT_LL_HANDLE handle, const IOTHUB_DEVICE_CONFIG* device, PDLIST_ENTRY waitingToSend);
+    typedef void(*pfIotHubTransport_Unregister)(IOTHUB_DEVICE_HANDLE deviceHandle);
+    typedef int (*pfIoTHubTransport_Subscribe)(IOTHUB_DEVICE_HANDLE handle);
+    typedef void (*pfIoTHubTransport_Unsubscribe)(IOTHUB_DEVICE_HANDLE handle);
+    typedef void (*pfIoTHubTransport_DoWork)(TRANSPORT_LL_HANDLE handle);
+    typedef int(*pfIoTHubTransport_SetRetryPolicy)(TRANSPORT_LL_HANDLE handle, IOTHUB_CLIENT_RETRY_POLICY retryPolicy, size_t retryTimeoutLimitInSeconds);
+    typedef IOTHUB_CLIENT_RESULT(*pfIoTHubTransport_GetSendStatus)(IOTHUB_DEVICE_HANDLE handle, IOTHUB_CLIENT_STATUS *iotHubClientStatus);
+    typedef int (*pfIoTHubTransport_Subscribe_DeviceTwin)(IOTHUB_DEVICE_HANDLE handle);
+    typedef void (*pfIoTHubTransport_Unsubscribe_DeviceTwin)(IOTHUB_DEVICE_HANDLE handle);
+    typedef IOTHUB_CLIENT_RESULT(*pfIoTHubTransport_GetTwinAsync)(IOTHUB_DEVICE_HANDLE handle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK completionCallback, void* callbackContext);
+    typedef IOTHUB_CLIENT_RESULT(*pfIotHubTransport_SendMessageDisposition)(MESSAGE_CALLBACK_INFO* messageData, IOTHUBMESSAGE_DISPOSITION_RESULT disposition);
+    typedef IOTHUB_PROCESS_ITEM_RESULT(*pfIoTHubTransport_ProcessItem)(TRANSPORT_LL_HANDLE handle, IOTHUB_IDENTITY_TYPE item_type, IOTHUB_IDENTITY_INFO* iothub_item);
+    typedef int(*pfIoTHubTransport_Subscribe_DeviceMethod)(IOTHUB_DEVICE_HANDLE handle);
+    typedef void(*pfIoTHubTransport_Unsubscribe_DeviceMethod)(IOTHUB_DEVICE_HANDLE handle);
+    typedef int(*pfIoTHubTransport_DeviceMethod_Response)(IOTHUB_DEVICE_HANDLE handle, METHOD_HANDLE methodId, const unsigned char* response, size_t response_size, int status_response);
+    typedef int(*pfIoTHubTransport_Subscribe_InputQueue)(IOTHUB_DEVICE_HANDLE handle);
+    typedef void(*pfIoTHubTransport_Unsubscribe_InputQueue)(IOTHUB_DEVICE_HANDLE handle);
+    typedef int(*pfIoTHubTransport_SetCallbackContext)(TRANSPORT_LL_HANDLE handle, void* ctx);
+    typedef int(*pfIoTHubTransport_GetSupportedPlatformInfo)(TRANSPORT_LL_HANDLE handle, PLATFORM_INFO_OPTION* info);
+
+#define TRANSPORT_PROVIDER_FIELDS                                                   \
+pfIotHubTransport_SendMessageDisposition IoTHubTransport_SendMessageDisposition;    \
+pfIoTHubTransport_Subscribe_DeviceMethod IoTHubTransport_Subscribe_DeviceMethod;    \
+pfIoTHubTransport_Unsubscribe_DeviceMethod IoTHubTransport_Unsubscribe_DeviceMethod;\
+pfIoTHubTransport_DeviceMethod_Response IoTHubTransport_DeviceMethod_Response;      \
+pfIoTHubTransport_Subscribe_DeviceTwin IoTHubTransport_Subscribe_DeviceTwin;        \
+pfIoTHubTransport_Unsubscribe_DeviceTwin IoTHubTransport_Unsubscribe_DeviceTwin;    \
+pfIoTHubTransport_ProcessItem IoTHubTransport_ProcessItem;                          \
+pfIoTHubTransport_GetHostname IoTHubTransport_GetHostname;                          \
+pfIoTHubTransport_SetOption IoTHubTransport_SetOption;                              \
+pfIoTHubTransport_Create IoTHubTransport_Create;                                    \
+pfIoTHubTransport_Destroy IoTHubTransport_Destroy;                                  \
+pfIotHubTransport_Register IoTHubTransport_Register;                                \
+pfIotHubTransport_Unregister IoTHubTransport_Unregister;                            \
+pfIoTHubTransport_Subscribe IoTHubTransport_Subscribe;                              \
+pfIoTHubTransport_Unsubscribe IoTHubTransport_Unsubscribe;                          \
+pfIoTHubTransport_DoWork IoTHubTransport_DoWork;                                    \
+pfIoTHubTransport_SetRetryPolicy IoTHubTransport_SetRetryPolicy;                    \
+pfIoTHubTransport_GetSendStatus IoTHubTransport_GetSendStatus;                      \
+pfIoTHubTransport_Subscribe_InputQueue IoTHubTransport_Subscribe_InputQueue;        \
+pfIoTHubTransport_Unsubscribe_InputQueue IoTHubTransport_Unsubscribe_InputQueue;    \
+pfIoTHubTransport_SetCallbackContext IoTHubTransport_SetCallbackContext;            \
+pfIoTHubTransport_GetTwinAsync IoTHubTransport_GetTwinAsync;                        \
+pfIoTHubTransport_GetSupportedPlatformInfo IoTHubTransport_GetSupportedPlatformInfo     /*there's an intentional missing ; on this line*/
+
+    struct TRANSPORT_PROVIDER_TAG
+    {
+        TRANSPORT_PROVIDER_FIELDS;
+    };
+
+    MOCKABLE_FUNCTION(, int, IoTHub_Transport_ValidateCallbacks, const TRANSPORT_CALLBACKS_INFO*, transport_cb);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IOTHUB_TRANSPORT_LL_PRIVATE_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothubtransport.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothubtransport.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothubtransport.h	(revision 453)
@@ -0,0 +1,49 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef IOTHUB_TRANSPORT_H
+#define IOTHUB_TRANSPORT_H
+
+#include "azure_c_shared_utility/lock.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "iothub_transport_ll.h"
+#include "iothub_client_core.h"
+#include "internal/iothub_client_private.h"
+#include "internal/iothub_transport_ll_private.h"
+#include "internal/iothub_client_authorization.h"
+
+#ifndef IOTHUB_CLIENT_CORE_INSTANCE_TYPE
+typedef struct IOTHUB_CLIENT_CORE_INSTANCE_TAG* IOTHUB_CLIENT_CORE_HANDLE;
+#define IOTHUB_CLIENT_CORE_INSTANCE_TYPE
+#endif // IOTHUB_CLIENT_CORE_INSTANCE
+
+#ifdef __cplusplus
+extern "C"
+{
+#else
+#include <stdbool.h>
+#endif
+
+#include "umock_c/umock_c_prod.h"
+
+    /** @brief  This struct captures IoTHub transport configuration. */
+    struct IOTHUBTRANSPORT_CONFIG_TAG
+    {
+        const IOTHUB_CLIENT_CONFIG* upperConfig;
+        PDLIST_ENTRY waitingToSend;
+        IOTHUB_AUTHORIZATION_HANDLE auth_module_handle;
+        const char* moduleId;
+    };
+
+    typedef void(*IOTHUB_CLIENT_MULTIPLEXED_DO_WORK)(void* iotHubClientInstance);
+
+    MOCKABLE_FUNCTION(, LOCK_HANDLE, IoTHubTransport_GetLock, TRANSPORT_HANDLE, transportHandle);
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubTransport_StartWorkerThread, TRANSPORT_HANDLE, transportHandle, IOTHUB_CLIENT_CORE_HANDLE, clientHandle, IOTHUB_CLIENT_MULTIPLEXED_DO_WORK, muxDoWork);
+    MOCKABLE_FUNCTION(, bool, IoTHubTransport_SignalEndWorkerThread, TRANSPORT_HANDLE, transportHandle, IOTHUB_CLIENT_CORE_HANDLE, clientHandle);
+    MOCKABLE_FUNCTION(, void, IoTHubTransport_JoinWorkerThread, TRANSPORT_HANDLE, transportHandle, IOTHUB_CLIENT_CORE_HANDLE, clientHandle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IOTHUB_TRANSPORT_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothubtransport_mqtt_common.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothubtransport_mqtt_common.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/internal/iothubtransport_mqtt_common.h	(revision 453)
@@ -0,0 +1,56 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef IOTHUBTRANSPORT_MQTT_COMMON_H
+#define IOTHUBTRANSPORT_MQTT_COMMON_H
+
+#include "internal/iothub_transport_ll_private.h"
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#include <cstdlib>
+#else
+#include <stdlib.h>
+#endif
+
+typedef struct MQTT_TRANSPORT_PROXY_OPTIONS_TAG
+{
+    const char* host_address;
+    int port;
+    const char* username;
+    const char* password;
+} MQTT_TRANSPORT_PROXY_OPTIONS;
+
+typedef XIO_HANDLE(*MQTT_GET_IO_TRANSPORT)(const char* fully_qualified_name, const MQTT_TRANSPORT_PROXY_OPTIONS* mqtt_transport_proxy_options);
+
+MOCKABLE_FUNCTION(, TRANSPORT_LL_HANDLE, IoTHubTransport_MQTT_Common_Create, const IOTHUBTRANSPORT_CONFIG*,  config, MQTT_GET_IO_TRANSPORT, get_io_transport, TRANSPORT_CALLBACKS_INFO*, cb_info, void*, ctx);
+MOCKABLE_FUNCTION(, void, IoTHubTransport_MQTT_Common_Destroy, TRANSPORT_LL_HANDLE, handle);
+MOCKABLE_FUNCTION(, int, IoTHubTransport_MQTT_Common_Subscribe, TRANSPORT_LL_HANDLE, handle);
+MOCKABLE_FUNCTION(, void, IoTHubTransport_MQTT_Common_Unsubscribe, TRANSPORT_LL_HANDLE, handle);
+MOCKABLE_FUNCTION(, int, IoTHubTransport_MQTT_Common_Subscribe_DeviceTwin, TRANSPORT_LL_HANDLE, handle);
+MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubTransport_MQTT_Common_GetTwinAsync, IOTHUB_DEVICE_HANDLE, handle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK, completionCallback, void*, callbackContext);
+MOCKABLE_FUNCTION(, void, IoTHubTransport_MQTT_Common_Unsubscribe_DeviceTwin, TRANSPORT_LL_HANDLE, handle);
+MOCKABLE_FUNCTION(, int, IoTHubTransport_MQTT_Common_Subscribe_DeviceMethod, TRANSPORT_LL_HANDLE, handle);
+MOCKABLE_FUNCTION(, void, IoTHubTransport_MQTT_Common_Unsubscribe_DeviceMethod, TRANSPORT_LL_HANDLE, handle);
+MOCKABLE_FUNCTION(, int, IoTHubTransport_MQTT_Common_DeviceMethod_Response, TRANSPORT_LL_HANDLE, handle, METHOD_HANDLE, methodId, const unsigned char*, response, size_t, response_size, int, status_response);
+MOCKABLE_FUNCTION(, IOTHUB_PROCESS_ITEM_RESULT, IoTHubTransport_MQTT_Common_ProcessItem, TRANSPORT_LL_HANDLE, handle, IOTHUB_IDENTITY_TYPE, item_type, IOTHUB_IDENTITY_INFO*, iothub_item);
+MOCKABLE_FUNCTION(, void, IoTHubTransport_MQTT_Common_DoWork, TRANSPORT_LL_HANDLE, handle);
+MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubTransport_MQTT_Common_GetSendStatus, TRANSPORT_LL_HANDLE, handle, IOTHUB_CLIENT_STATUS*, iotHubClientStatus);
+MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubTransport_MQTT_Common_SetOption, TRANSPORT_LL_HANDLE, handle, const char*, option, const void*, value);
+MOCKABLE_FUNCTION(, TRANSPORT_LL_HANDLE, IoTHubTransport_MQTT_Common_Register, TRANSPORT_LL_HANDLE, handle, const IOTHUB_DEVICE_CONFIG*, device, PDLIST_ENTRY, waitingToSend);
+MOCKABLE_FUNCTION(, void, IoTHubTransport_MQTT_Common_Unregister, TRANSPORT_LL_HANDLE, deviceHandle);
+MOCKABLE_FUNCTION(, int, IoTHubTransport_MQTT_Common_SetRetryPolicy, TRANSPORT_LL_HANDLE, handle, IOTHUB_CLIENT_RETRY_POLICY, retryPolicy, size_t, retryTimeoutLimitInSeconds);
+MOCKABLE_FUNCTION(, STRING_HANDLE, IoTHubTransport_MQTT_Common_GetHostname, TRANSPORT_LL_HANDLE, handle);
+MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubTransport_MQTT_Common_SendMessageDisposition, MESSAGE_CALLBACK_INFO*, message_data, IOTHUBMESSAGE_DISPOSITION_RESULT, disposition);
+MOCKABLE_FUNCTION(, int, IoTHubTransport_MQTT_Common_Subscribe_InputQueue, TRANSPORT_LL_HANDLE, handle);
+MOCKABLE_FUNCTION(, void, IoTHubTransport_MQTT_Common_Unsubscribe_InputQueue, TRANSPORT_LL_HANDLE, handle);
+MOCKABLE_FUNCTION(, int, IoTHubTransport_MQTT_SetCallbackContext, TRANSPORT_LL_HANDLE, handle, void*, ctx);
+MOCKABLE_FUNCTION(, int, IoTHubTransport_MQTT_GetSupportedPlatformInfo, TRANSPORT_LL_HANDLE, handle, PLATFORM_INFO_OPTION*, info);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IOTHUBTRANSPORT_MQTT_COMMON_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub.h	(revision 453)
@@ -0,0 +1,31 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef IOTHUB_H
+#define IOTHUB_H
+
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#else
+#endif
+    /**
+    * @brief    IoTHubClient_Init Initializes the IoTHub Client System.
+    *
+    * @return   int zero upon success, any other value upon failure.
+    */
+    MOCKABLE_FUNCTION(, int, IoTHub_Init);
+
+    /**
+    * @brief    IoTHubClient_Deinit Frees resources initialized in the IoTHubClient_Init function call.
+    *
+    */
+    MOCKABLE_FUNCTION(, void, IoTHub_Deinit);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IOTHUB_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_client.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_client.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_client.h	(revision 453)
@@ -0,0 +1,396 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/** @file iothub_client.h
+*    @brief Extends the IoTHubCLient_LL module with additional features.
+*
+*    @note  DEPRECATED. New users use iothub_device_client.h for IoTHubClient APIs.
+*    @details IoTHubClient is a module that extends the IoTHubCLient_LL
+*             module with 2 features:
+*                - scheduling the work for the IoTHubCLient from a
+*                  thread, so that the user does not need to create their
+*                  own thread
+*                - thread-safe APIs
+*/
+
+#ifndef IOTHUB_CLIENT_H
+#define IOTHUB_CLIENT_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "umock_c/umock_c_prod.h"
+#include "iothub_transport_ll.h"
+#include "iothub_client_core_ll.h"
+#include "iothub_client_core.h"
+#include "iothub_client_ll.h"
+
+#ifndef IOTHUB_CLIENT_INSTANCE_TYPE
+typedef IOTHUB_CLIENT_CORE_HANDLE IOTHUB_CLIENT_HANDLE;
+#define IOTHUB_CLIENT_INSTANCE_TYPE
+#endif // IOTHUB_CLIENT_INSTANCE
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    /**
+    * @brief    Creates a IoT Hub client for communication with an existing
+    *             IoT Hub using the specified connection string parameter.
+    *
+    * @param    connectionString    Pointer to a character string
+    * @param    protocol            Function pointer for protocol implementation
+    *
+    *            Sample connection string:
+    *                <blockquote>
+    *                    <pre>HostName=[IoT Hub name goes here].[IoT Hub suffix goes here, e.g., private.azure-devices-int.net];DeviceId=[Device ID goes here];SharedAccessKey=[Device key goes here];</pre>
+    *                   <pre>HostName=[IoT Hub name goes here].[IoT Hub suffix goes here, e.g., private.azure-devices-int.net];DeviceId=[Device ID goes here];SharedAccessSignature=SharedAccessSignature sr=[IoT Hub name goes here].[IoT Hub suffix goes here, e.g., private.azure-devices-int.net]/devices/[Device ID goes here]&sig=[SAS Token goes here]&se=[Expiry Time goes here];</pre>
+    *                </blockquote>
+    *
+    * @return    A non-NULL @c IOTHUB_CLIENT_HANDLE value that is used when
+    *             invoking other functions for IoT Hub client and @c NULL on failure.
+    */
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_HANDLE, IoTHubClient_CreateFromConnectionString, const char*, connectionString, IOTHUB_CLIENT_TRANSPORT_PROVIDER, protocol);
+
+    /**
+    * @brief    Creates a IoT Hub client for communication with an existing IoT
+    *             Hub using the specified parameters.
+    *
+    * @param    config    Pointer to an @c IOTHUB_CLIENT_CONFIG structure
+    *
+    *            The API does not allow sharing of a connection across multiple
+    *            devices. This is a blocking call.
+    *
+    * @return    A non-NULL @c IOTHUB_CLIENT_HANDLE value that is used when
+    *             invoking other functions for IoT Hub client and @c NULL on failure.
+    */
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_HANDLE, IoTHubClient_Create, const IOTHUB_CLIENT_CONFIG*, config);
+
+    /**
+    * @brief    Creates a IoT Hub client for communication with an existing IoT
+    *             Hub using the specified parameters.
+    *
+    * @param    transportHandle    TRANSPORT_HANDLE which represents a connection.
+    * @param    config    Pointer to an @c IOTHUB_CLIENT_CONFIG structure
+    *
+    *            The API allows sharing of a connection across multiple
+    *            devices. This is a blocking call.
+    *
+    * @return    A non-NULL @c IOTHUB_CLIENT_HANDLE value that is used when
+    *             invoking other functions for IoT Hub client and @c NULL on failure.
+    */
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_HANDLE, IoTHubClient_CreateWithTransport, TRANSPORT_HANDLE, transportHandle, const IOTHUB_CLIENT_CONFIG*, config);
+
+    /**
+    * @brief    Creates a IoT Hub client for communication with an existing IoT
+    *             Hub using the device auth module.
+    *
+    * @param    iothub_uri    Pointer to an ioThub hostname received in the registration process
+    * @param    device_id    Pointer to the device Id of the device
+    * @param    protocol    Function pointer for protocol implementation
+    *
+    * @return    A non-NULL @c IOTHUB_CLIENT_LL_HANDLE value that is used when
+    *             invoking other functions for IoT Hub client and @c NULL on failure.
+    */
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_HANDLE, IoTHubClient_CreateFromDeviceAuth, const char*, iothub_uri, const char*, device_id, IOTHUB_CLIENT_TRANSPORT_PROVIDER, protocol);
+
+    /**
+    * @brief    Disposes of resources allocated by the IoT Hub client. This is a
+    *             blocking call.
+    *
+    * @param    iotHubClientHandle    The handle created by a call to the create function.
+    */
+    MOCKABLE_FUNCTION(, void, IoTHubClient_Destroy, IOTHUB_CLIENT_HANDLE, iotHubClientHandle);
+
+    /**
+    * @brief    Asynchronous call to send the message specified by @p eventMessageHandle.
+    *
+    * @param    iotHubClientHandle               The handle created by a call to the create function.
+    * @param    eventMessageHandle               The handle to an IoT Hub message.
+    * @param    eventConfirmationCallback      The callback specified by the device for receiving
+    *                                         confirmation of the delivery of the IoT Hub message.
+    *                                         This callback can be expected to invoke the
+    *                                         ::IoTHubClient_SendEventAsync function for the
+    *                                         same message in an attempt to retry sending a failing
+    *                                         message. The user can specify a @c NULL value here to
+    *                                         indicate that no callback is required.
+    * @param    userContextCallback            User specified context that will be provided to the
+    *                                         callback. This can be @c NULL.
+    *
+    *            @b NOTE: The application behavior is undefined if the user calls
+    *            the ::IoTHubClient_Destroy function from within any callback.
+    * @remarks
+    *            The IOTHUB_MESSAGE_HANDLE instance provided as argument is copied by the function,
+    *            so this argument can be destroyed by the calling application right after IoTHubClient_SendEventAsync returns.
+    *            The copy of @c eventMessageHandle is later destroyed by the iothub client when the message is effectively sent, if a failure sending it occurs, or if the client is destroyed.
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_SendEventAsync, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, IOTHUB_MESSAGE_HANDLE, eventMessageHandle, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK, eventConfirmationCallback, void*, userContextCallback);
+
+    /**
+    * @brief    This function returns the current sending status for IoTHubClient.
+    *
+    * @param    iotHubClientHandle        The handle created by a call to the create function.
+    * @param    iotHubClientStatus        The sending state is populated at the address pointed
+    *                                     at by this parameter. The value will be set to
+    *                                     @c IOTHUBCLIENT_SENDSTATUS_IDLE if there is currently
+    *                                     no item to be sent and @c IOTHUBCLIENT_SENDSTATUS_BUSY
+    *                                     if there are.
+    *
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_GetSendStatus, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_STATUS*, iotHubClientStatus);
+
+    /**
+    * @brief    Sets up the message callback to be invoked when IoT Hub issues a
+    *             message to the device. This is a blocking call.
+    *
+    * @param    iotHubClientHandle               The handle created by a call to the create function.
+    * @param    messageCallback                The callback specified by the device for receiving
+    *                                         messages from IoT Hub.
+    * @param    userContextCallback            User specified context that will be provided to the
+    *                                         callback. This can be @c NULL.
+    *
+    *            @b NOTE: The application behavior is undefined if the user calls
+    *            the ::IoTHubClient_Destroy function from within any callback.
+    *
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_SetMessageCallback, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC, messageCallback, void*, userContextCallback);
+
+    /**
+    * @brief    Sets up the connection status callback to be invoked representing the status of
+    * the connection to IOT Hub. This is a blocking call.
+    *
+    * @param    iotHubClientHandle                       The handle created by a call to the create function.
+    * @param    connectionStatusCallback                The callback specified by the device for receiving
+    *                                                 updates about the status of the connection to IoT Hub.
+    * @param    userContextCallback                    User specified context that will be provided to the
+    *                                                 callback. This can be @c NULL.
+    *
+    *            @b NOTE: The application behavior is undefined if the user calls
+    *            the ::IoTHubClient_LL_Destroy function from within any callback.
+    *
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_SetConnectionStatusCallback, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_CONNECTION_STATUS_CALLBACK, connectionStatusCallback, void*, userContextCallback);
+
+    /**
+    * @brief    Sets up the connection status callback to be invoked representing the status of
+    * the connection to IOT Hub. This is a blocking call.
+    *
+    * @param    iotHubClientHandle                       The handle created by a call to the create function.
+    * @param    retryPolicy                             The policy to use to reconnect to IoT Hub when a
+    *                                               connection drops.
+    * @param    retryTimeoutLimitInSeconds            Maximum amount of time(seconds) to attempt reconnection when a
+    *                                               connection drops to IOT Hub.
+    *
+    *            @b NOTE: The application behavior is undefined if the user calls
+    *            the ::IoTHubClient_LL_Destroy function from within any callback.
+    *
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_SetRetryPolicy, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY, retryPolicy, size_t, retryTimeoutLimitInSeconds);
+
+    /**
+    * @brief    Sets up the connection status callback to be invoked representing the status of
+    * the connection to IOT Hub. This is a blocking call.
+    *
+    * @param    iotHubClientHandle                       The handle created by a call to the create function.
+    * @param    retryPolicy                             Out parameter containing the policy to use to reconnect to IoT Hub.
+    * @param    retryTimeoutLimitInSeconds            Out parameter containing maximum amount of time in seconds to attempt reconnection
+    to IOT Hub.
+    *
+    *            @b NOTE: The application behavior is undefined if the user calls
+    *            the ::IoTHubClient_LL_Destroy function from within any callback.
+    *
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_GetRetryPolicy, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY*, retryPolicy, size_t*, retryTimeoutLimitInSeconds);
+
+    /**
+    * @brief    This function returns in the out parameter @p lastMessageReceiveTime
+    *             what was the value of the @c time function when the last message was
+    *             received at the client.
+    *
+    * @param    iotHubClientHandle                The handle created by a call to the create function.
+    * @param    lastMessageReceiveTime          Out parameter containing the value of @c time function
+    *                                             when the last message was received.
+    *
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_GetLastMessageReceiveTime, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, time_t*, lastMessageReceiveTime);
+
+    /**
+    * @brief    This API sets a runtime option identified by parameter @p optionName
+    *             to a value pointed to by @p value. @p optionName and the data type
+    *             @p value is pointing to are specific for every option.
+    *
+    * @param    iotHubClientHandle    The handle created by a call to the create function.
+    * @param    optionName              Name of the option.
+    * @param    value                  The value.
+    *
+    *            The options that can be set via this API are:
+    *                - @b timeout - the maximum time in milliseconds a communication is
+    *                  allowed to use. @p value is a pointer to an @c unsigned @c int with
+    *                  the timeout value in milliseconds. This is only supported for the HTTP
+    *                  protocol as of now. When the HTTP protocol uses CURL, the meaning of
+    *                  the parameter is <em>total request time</em>. When the HTTP protocol uses
+    *                  winhttp, the meaning is the same as the @c dwSendTimeout and
+    *                  @c dwReceiveTimeout parameters of the
+    *                  <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa384116(v=vs.85).aspx">
+    *                  WinHttpSetTimeouts</a> API.
+    *                - @b CURLOPT_LOW_SPEED_LIMIT - only available for HTTP protocol and only
+    *                  when CURL is used. It has the same meaning as CURL's option with the same
+    *                  name. @p value is pointer to a long.
+    *                - @b CURLOPT_LOW_SPEED_TIME - only available for HTTP protocol and only
+    *                  when CURL is used. It has the same meaning as CURL's option with the same
+    *                  name. @p value is pointer to a long.
+    *                - @b CURLOPT_FORBID_REUSE - only available for HTTP protocol and only
+    *                  when CURL is used. It has the same meaning as CURL's option with the same
+    *                  name. @p value is pointer to a long.
+    *                - @b CURLOPT_FRESH_CONNECT - only available for HTTP protocol and only
+    *                  when CURL is used. It has the same meaning as CURL's option with the same
+    *                  name. @p value is pointer to a long.
+    *                - @b CURLOPT_VERBOSE - only available for HTTP protocol and only
+    *                  when CURL is used. It has the same meaning as CURL's option with the same
+    *                  name. @p value is pointer to a long.
+    *                - @b messageTimeout - the maximum time in milliseconds until a message
+    *                 is timeouted. The time starts at IoTHubClient_SendEventAsync. By default,
+    *                 messages do not expire. @p is a pointer to a uint64_t
+    *                - @b svc2cl_keep_alive_timeout_secs - the AMQP service side keep alive interval in seconds.
+    *                 After the connection established the client requests the server to set the
+    *                 keep alive interval for given time.
+    *                 If it is not set then the default 240 sec applies.
+    *                 If it is set to zero the server will not send keep alive messages to the client.
+    *                - @b cl2svc_keep_alive_send_ratio - the AMQP client side keep alive interval in seconds.
+    *                 After the connection established the server requests the client to set the
+    *                 keep alive interval for given time.
+    *                 If it is not set then the default ratio of 1/2 is applied.
+    *                 The ratio has to be greater than 0.0 and equal to or less than 0.9
+
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_SetOption, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, const char*, optionName, const void*, value);
+
+    /**
+    * @brief    This API specifies a call back to be used when the device receives a state update.
+    *
+    * @param    iotHubClientHandle        The handle created by a call to the create function.
+    * @param    deviceTwinCallback        The callback specified by the device client to be used for updating
+    *                                    the desired state. The callback will be called in response to a
+    *                                    request send by the IoTHub services. The payload will be passed to the
+    *                                    callback, along with two version numbers:
+    *                                        - Desired:
+    *                                        - LastSeenReported:
+    * @param    userContextCallback        User specified context that will be provided to the
+    *                                     callback. This can be @c NULL.
+    *
+    *            @b NOTE: The application behavior is undefined if the user calls
+    *            the ::IoTHubClient_Destroy function from within any callback.
+    *
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_SetDeviceTwinCallback, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK, deviceTwinCallback, void*, userContextCallback);
+
+    /**
+    * @brief    This API sends a report of the device's properties and their current values.
+    *
+    * @param    iotHubClientHandle        The handle created by a call to the create function.
+    * @param    reportedState            The current device property values to be 'reported' to the IoTHub.
+    * @param    reportedStateCallback    The callback specified by the device client to be called with the
+    *                                    result of the transaction.
+    * @param    userContextCallback        User specified context that will be provided to the
+    *                                     callback. This can be @c NULL.
+    *
+    *            @b NOTE: The application behavior is undefined if the user calls
+    *            the ::IoTHubClient_Destroy function from within any callback.
+    *
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_SendReportedState, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, const unsigned char*, reportedState, size_t, size, IOTHUB_CLIENT_REPORTED_STATE_CALLBACK, reportedStateCallback, void*, userContextCallback);
+
+    /**
+    * @brief    This API sets callback for cloud to device method call.
+    *
+    * @param    iotHubClientHandle        The handle created by a call to the create function.
+    * @param    deviceMethodCallback    The callback which will be called by IoTHub.
+    * @param    userContextCallback        User specified context that will be provided to the
+    *                                     callback. This can be @c NULL.
+    *
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_SetDeviceMethodCallback, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_DEVICE_METHOD_CALLBACK_ASYNC, deviceMethodCallback, void*, userContextCallback);
+
+    /**
+    * @brief    This API sets callback for async cloud to device method call.
+    *
+    * @param    iotHubClientHandle                The handle created by a call to the create function.
+    * @param    inboundDeviceMethodCallback     The callback which will be called by IoTHub.
+    * @param    userContextCallback                User specified context that will be provided to the
+    *                                             callback. This can be @c NULL.
+    *
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_SetDeviceMethodCallback_Ex, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK, inboundDeviceMethodCallback, void*, userContextCallback);
+
+    /**
+    * @brief    This API responses to a asnyc method callback identified the methodId.
+    *
+    * @param    iotHubClientHandle      The handle created by a call to the create function.
+    * @param    methodId                The methodId of the Device Method callback.
+    * @param    response                The response data for the method callback.
+    * @param    response_size           The size of the response data buffer.
+    * @param    status_response         The status response of the method callback.
+    *
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_DeviceMethodResponse, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, METHOD_HANDLE, methodId, const unsigned char*, response, size_t, response_size, int, statusCode);
+
+#ifndef DONT_USE_UPLOADTOBLOB
+    /**
+    * @brief    IoTHubClient_UploadToBlobAsync uploads data from memory to a file in Azure Blob Storage.
+    *
+    * @param    iotHubClientHandle                    The handle created by a call to the IoTHubClient_Create function.
+    * @param    destinationFileName                    The name of the file to be created in Azure Blob Storage.
+    * @param    source                              The source of data.
+    * @param    size                                The size of data.
+    * @param    iotHubClientFileUploadCallback      A callback to be invoked when the file upload operation has finished.
+    * @param    context                             A user-provided context to be passed to the file upload callback.
+    *
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_UploadToBlobAsync, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, const char*, destinationFileName, const unsigned char*, source, size_t, size, IOTHUB_CLIENT_FILE_UPLOAD_CALLBACK, iotHubClientFileUploadCallback, void*, context);
+
+    /**
+    ** DEPRECATED: Use IoTHubClient_UploadMultipleBlocksToBlobAsyncEx instead **
+    * @brief                          Uploads a file to a Blob storage in chunks, fed through the callback function provided by the user.
+    * @remarks                        This function allows users to upload large files in chunks, not requiring the whole file content to be passed in memory.
+    * @param iotHubClientHandle       The handle created by a call to the IoTHubClient_Create function.
+    * @param destinationFileName      The name of the file to be created in Azure Blob Storage.
+    * @param getDataCallback          A callback to be invoked to acquire the file chunks to be uploaded, as well as to indicate the status of the upload of the previous block.
+    * @param context                  Any data provided by the user to serve as context on getDataCallback.
+    * @returns                        An IOTHUB_CLIENT_RESULT value indicating the success or failure of the API call.
+    ** DEPRECATED: Use IoTHubClient_UploadMultipleBlocksToBlobAsyncEx instead **
+    */
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_UploadMultipleBlocksToBlobAsync, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK, getDataCallback, void*, context);
+
+    /**
+    * @brief                          Uploads a file to a Blob storage in chunks, fed through the callback function provided by the user.
+    * @remarks                        This function allows users to upload large files in chunks, not requiring the whole file content to be passed in memory.
+    * @param iotHubClientHandle       The handle created by a call to the IoTHubClient_Create function.
+    * @param destinationFileName      The name of the file to be created in Azure Blob Storage.
+    * @param getDataCallbackEx        A callback to be invoked to acquire the file chunks to be uploaded, as well as to indicate the status of the upload of the previous block.
+    * @param context                  Any data provided by the user to serve as context on getDataCallback.
+    * @returns                        An IOTHUB_CLIENT_RESULT value indicating the success or failure of the API call.*/
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_UploadMultipleBlocksToBlobAsyncEx, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context);
+
+#endif /* DONT_USE_UPLOADTOBLOB */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IOTHUB_CLIENT_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_client_core.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_client_core.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_client_core.h	(revision 453)
@@ -0,0 +1,71 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/** @file iothub_client_core.h
+*    @brief Extends the IoTHubClientCore_LL module with additional features.
+*
+*    @details IoTHubClientCore is a module that extends the IoTHubClientCore_LL
+*             module with 2 features:
+*                - scheduling the work for the IoTHubCLient from a
+*                  thread, so that the user does not need to create their
+*                  own thread
+*                - thread-safe APIs
+*/
+
+#ifndef IOTHUB_CLIENT_CORE_H
+#define IOTHUB_CLIENT_CORE_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include "umock_c/umock_c_prod.h"
+
+#include "iothub_client_core_ll.h"
+
+#ifndef IOTHUB_CLIENT_CORE_INSTANCE_TYPE
+typedef struct IOTHUB_CLIENT_CORE_INSTANCE_TAG* IOTHUB_CLIENT_CORE_HANDLE;
+#define IOTHUB_CLIENT_CORE_INSTANCE_TYPE
+#endif // IOTHUB_CLIENT_CORE_INSTANCE
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_CORE_HANDLE, IoTHubClientCore_CreateFromConnectionString, const char*, connectionString, IOTHUB_CLIENT_TRANSPORT_PROVIDER, protocol);
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_CORE_HANDLE, IoTHubClientCore_Create, const IOTHUB_CLIENT_CONFIG*, config);
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_CORE_HANDLE, IoTHubClientCore_CreateWithTransport, TRANSPORT_HANDLE, transportHandle, const IOTHUB_CLIENT_CONFIG*, config);
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_CORE_HANDLE, IoTHubClientCore_CreateFromDeviceAuth, const char*, iothub_uri, const char*, device_id, IOTHUB_CLIENT_TRANSPORT_PROVIDER, protocol);
+    MOCKABLE_FUNCTION(, void, IoTHubClientCore_Destroy, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle);
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_SendEventAsync, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, IOTHUB_MESSAGE_HANDLE, eventMessageHandle, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK, eventConfirmationCallback, void*, userContextCallback);
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_GetSendStatus, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_STATUS*, iotHubClientStatus);
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_SetMessageCallback, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC, messageCallback, void*, userContextCallback);
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_SetConnectionStatusCallback, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_CONNECTION_STATUS_CALLBACK, connectionStatusCallback, void*, userContextCallback);
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_SetRetryPolicy, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY, retryPolicy, size_t, retryTimeoutLimitInSeconds);
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_GetRetryPolicy, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY*, retryPolicy, size_t*, retryTimeoutLimitInSeconds);
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_GetLastMessageReceiveTime, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, time_t*, lastMessageReceiveTime);
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_SetOption, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, const char*, optionName, const void*, value);
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_SetDeviceTwinCallback, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK, deviceTwinCallback, void*, userContextCallback);
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_SendReportedState, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, const unsigned char*, reportedState, size_t, size, IOTHUB_CLIENT_REPORTED_STATE_CALLBACK, reportedStateCallback, void*, userContextCallback);
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_GetTwinAsync, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK, deviceTwinCallback, void*, userContextCallback);
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_SetDeviceMethodCallback, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_DEVICE_METHOD_CALLBACK_ASYNC, deviceMethodCallback, void*, userContextCallback);
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_SetDeviceMethodCallback_Ex, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK, inboundDeviceMethodCallback, void*, userContextCallback);
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_DeviceMethodResponse, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, METHOD_HANDLE, methodId, const unsigned char*, response, size_t, response_size, int, statusCode);
+
+#ifndef DONT_USE_UPLOADTOBLOB
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_UploadToBlobAsync, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, const char*, destinationFileName, const unsigned char*, source, size_t, size, IOTHUB_CLIENT_FILE_UPLOAD_CALLBACK, iotHubClientFileUploadCallback, void*, context);
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_UploadMultipleBlocksToBlobAsync, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK, getDataCallback, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context);
+#endif /* DONT_USE_UPLOADTOBLOB */
+
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_SendEventToOutputAsync, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, IOTHUB_MESSAGE_HANDLE, eventMessageHandle, const char*, outputName, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK, eventConfirmationCallback, void*, userContextCallback);
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_SetInputMessageCallback, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, const char*, inputName, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC, eventHandlerCallback, void*, userContextCallback);
+
+#ifdef USE_EDGE_MODULES
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_CORE_HANDLE, IoTHubClientCore_CreateFromEnvironment, IOTHUB_CLIENT_TRANSPORT_PROVIDER, protocol);
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_GenericMethodInvoke, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, const char*, deviceId, const char*, moduleId, const char*, methodName, const char*, methodPayload, unsigned int, timeout, IOTHUB_METHOD_INVOKE_CALLBACK, methodInvokeCallback, void*, context);
+#endif /* USE_EDGE_MODULES */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IOTHUB_CLIENT_CORE_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_client_core_common.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_client_core_common.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_client_core_common.h	(revision 453)
@@ -0,0 +1,241 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/* Shared structures and enums for iothub convenience layer and LL layer */
+
+#ifndef IOTHUB_CLIENT_CORE_COMMON_H
+#define IOTHUB_CLIENT_CORE_COMMON_H
+
+#include "azure_macro_utils/macro_utils.h"
+#include "umock_c/umock_c_prod.h"
+
+#include "iothub_transport_ll.h"
+#include "iothub_message.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define IOTHUB_CLIENT_FILE_UPLOAD_RESULT_VALUES \
+    FILE_UPLOAD_OK, \
+    FILE_UPLOAD_ERROR
+
+    MU_DEFINE_ENUM_WITHOUT_INVALID(IOTHUB_CLIENT_FILE_UPLOAD_RESULT, IOTHUB_CLIENT_FILE_UPLOAD_RESULT_VALUES)
+        typedef void(*IOTHUB_CLIENT_FILE_UPLOAD_CALLBACK)(IOTHUB_CLIENT_FILE_UPLOAD_RESULT result, void* userContextCallback);
+
+#define IOTHUB_CLIENT_RESULT_VALUES       \
+    IOTHUB_CLIENT_OK,                     \
+    IOTHUB_CLIENT_INVALID_ARG,            \
+    IOTHUB_CLIENT_ERROR,                  \
+    IOTHUB_CLIENT_INVALID_SIZE,           \
+    IOTHUB_CLIENT_INDEFINITE_TIME
+
+    /** @brief Enumeration specifying the status of calls to various APIs in this module.
+    */
+
+    MU_DEFINE_ENUM_WITHOUT_INVALID(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_RESULT_VALUES);
+
+    typedef void(*IOTHUB_METHOD_INVOKE_CALLBACK)(IOTHUB_CLIENT_RESULT result, int responseStatus, unsigned char* responsePayload, size_t responsePayloadSize, void* context);
+
+#define IOTHUB_CLIENT_RETRY_POLICY_VALUES     \
+    IOTHUB_CLIENT_RETRY_NONE,                   \
+    IOTHUB_CLIENT_RETRY_IMMEDIATE,                  \
+    IOTHUB_CLIENT_RETRY_INTERVAL,      \
+    IOTHUB_CLIENT_RETRY_LINEAR_BACKOFF,      \
+    IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF,                 \
+    IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF_WITH_JITTER,                 \
+    IOTHUB_CLIENT_RETRY_RANDOM
+
+    /** @brief Enumeration passed in by the IoT Hub when the event confirmation
+    *           callback is invoked to indicate status of the event processing in
+    *           the hub.
+    */
+    MU_DEFINE_ENUM_WITHOUT_INVALID(IOTHUB_CLIENT_RETRY_POLICY, IOTHUB_CLIENT_RETRY_POLICY_VALUES);
+
+    struct IOTHUBTRANSPORT_CONFIG_TAG;
+    typedef struct IOTHUBTRANSPORT_CONFIG_TAG IOTHUBTRANSPORT_CONFIG;
+
+#define IOTHUB_CLIENT_STATUS_VALUES       \
+    IOTHUB_CLIENT_SEND_STATUS_IDLE,       \
+    IOTHUB_CLIENT_SEND_STATUS_BUSY
+
+    /** @brief Enumeration returned by the ::IoTHubClient_LL_GetSendStatus
+    *           API to indicate the current sending status of the IoT Hub client.
+    */
+    MU_DEFINE_ENUM_WITHOUT_INVALID(IOTHUB_CLIENT_STATUS, IOTHUB_CLIENT_STATUS_VALUES);
+
+#define IOTHUB_IDENTITY_TYPE_VALUE  \
+    IOTHUB_TYPE_TELEMETRY,          \
+    IOTHUB_TYPE_DEVICE_TWIN,        \
+    IOTHUB_TYPE_DEVICE_METHODS,     \
+    IOTHUB_TYPE_EVENT_QUEUE
+    MU_DEFINE_ENUM_WITHOUT_INVALID(IOTHUB_IDENTITY_TYPE, IOTHUB_IDENTITY_TYPE_VALUE);
+
+#define IOTHUB_PROCESS_ITEM_RESULT_VALUE    \
+    IOTHUB_PROCESS_OK,                      \
+    IOTHUB_PROCESS_ERROR,                   \
+    IOTHUB_PROCESS_NOT_CONNECTED,           \
+    IOTHUB_PROCESS_CONTINUE
+    MU_DEFINE_ENUM_WITHOUT_INVALID(IOTHUB_PROCESS_ITEM_RESULT, IOTHUB_PROCESS_ITEM_RESULT_VALUE);
+
+#define IOTHUBMESSAGE_DISPOSITION_RESULT_VALUES \
+    IOTHUBMESSAGE_ACCEPTED, \
+    IOTHUBMESSAGE_REJECTED, \
+    IOTHUBMESSAGE_ABANDONED
+
+    /** @brief Enumeration returned by the callback which is invoked whenever the
+    *           IoT Hub sends a message to the device.
+    */
+    MU_DEFINE_ENUM_WITHOUT_INVALID(IOTHUBMESSAGE_DISPOSITION_RESULT, IOTHUBMESSAGE_DISPOSITION_RESULT_VALUES);
+
+#define IOTHUB_CLIENT_IOTHUB_METHOD_STATUS_VALUES \
+    IOTHUB_CLIENT_IOTHUB_METHOD_STATUS_SUCCESS,   \
+    IOTHUB_CLIENT_IOTHUB_METHOD_STATUS_ERROR      \
+
+    /** @brief Enumeration returned by remotely executed functions
+    */
+    MU_DEFINE_ENUM_WITHOUT_INVALID(IOTHUB_CLIENT_IOTHUB_METHOD_STATUS, IOTHUB_CLIENT_IOTHUB_METHOD_STATUS_VALUES);
+
+
+#define IOTHUB_CLIENT_CONFIRMATION_RESULT_VALUES     \
+    IOTHUB_CLIENT_CONFIRMATION_OK,                   \
+    IOTHUB_CLIENT_CONFIRMATION_BECAUSE_DESTROY,      \
+    IOTHUB_CLIENT_CONFIRMATION_MESSAGE_TIMEOUT,      \
+    IOTHUB_CLIENT_CONFIRMATION_ERROR                 \
+
+    /** @brief Enumeration passed in by the IoT Hub when the event confirmation
+    *           callback is invoked to indicate status of the event processing in
+    *           the hub.
+    */
+    MU_DEFINE_ENUM_WITHOUT_INVALID(IOTHUB_CLIENT_CONFIRMATION_RESULT, IOTHUB_CLIENT_CONFIRMATION_RESULT_VALUES);
+
+#define IOTHUB_CLIENT_CONNECTION_STATUS_VALUES             \
+    IOTHUB_CLIENT_CONNECTION_AUTHENTICATED,                \
+    IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED               \
+
+
+    /** @brief Enumeration passed in by the IoT Hub when the connection status
+    *           callback is invoked to indicate status of the connection in
+    *           the hub.
+    */
+    MU_DEFINE_ENUM_WITHOUT_INVALID(IOTHUB_CLIENT_CONNECTION_STATUS, IOTHUB_CLIENT_CONNECTION_STATUS_VALUES);
+
+#define IOTHUB_CLIENT_CONNECTION_STATUS_REASON_VALUES      \
+    IOTHUB_CLIENT_CONNECTION_EXPIRED_SAS_TOKEN,            \
+    IOTHUB_CLIENT_CONNECTION_DEVICE_DISABLED,              \
+    IOTHUB_CLIENT_CONNECTION_BAD_CREDENTIAL,               \
+    IOTHUB_CLIENT_CONNECTION_RETRY_EXPIRED,                \
+    IOTHUB_CLIENT_CONNECTION_NO_NETWORK,                   \
+    IOTHUB_CLIENT_CONNECTION_COMMUNICATION_ERROR,          \
+    IOTHUB_CLIENT_CONNECTION_OK,                           \
+    IOTHUB_CLIENT_CONNECTION_NO_PING_RESPONSE              \
+
+    /** @brief Enumeration passed in by the IoT Hub when the connection status
+    *           callback is invoked to indicate status of the connection in
+    *           the hub.
+    */
+    MU_DEFINE_ENUM_WITHOUT_INVALID(IOTHUB_CLIENT_CONNECTION_STATUS_REASON, IOTHUB_CLIENT_CONNECTION_STATUS_REASON_VALUES);
+
+#define TRANSPORT_TYPE_VALUES \
+    TRANSPORT_LL, /*LL comes from "LowLevel" */ \
+    TRANSPORT_THREADED
+
+    MU_DEFINE_ENUM_WITHOUT_INVALID(TRANSPORT_TYPE, TRANSPORT_TYPE_VALUES);
+
+#define DEVICE_TWIN_UPDATE_STATE_VALUES \
+    DEVICE_TWIN_UPDATE_COMPLETE, \
+    DEVICE_TWIN_UPDATE_PARTIAL
+
+    MU_DEFINE_ENUM_WITHOUT_INVALID(DEVICE_TWIN_UPDATE_STATE, DEVICE_TWIN_UPDATE_STATE_VALUES);
+
+    typedef void(*IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK)(IOTHUB_CLIENT_CONFIRMATION_RESULT result, void* userContextCallback);
+    typedef void(*IOTHUB_CLIENT_CONNECTION_STATUS_CALLBACK)(IOTHUB_CLIENT_CONNECTION_STATUS result, IOTHUB_CLIENT_CONNECTION_STATUS_REASON reason, void* userContextCallback);
+    typedef IOTHUBMESSAGE_DISPOSITION_RESULT (*IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC)(IOTHUB_MESSAGE_HANDLE message, void* userContextCallback);
+
+    typedef void(*IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK)(DEVICE_TWIN_UPDATE_STATE update_state, const unsigned char* payLoad, size_t size, void* userContextCallback);
+    typedef void(*IOTHUB_CLIENT_REPORTED_STATE_CALLBACK)(int status_code, void* userContextCallback);
+    typedef int(*IOTHUB_CLIENT_DEVICE_METHOD_CALLBACK_ASYNC)(const char* method_name, const unsigned char* payload, size_t size, unsigned char** response, size_t* response_size, void* userContextCallback);
+    typedef int(*IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK)(const char* method_name, const unsigned char* payload, size_t size, METHOD_HANDLE method_id, void* userContextCallback);
+
+
+#define IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT_VALUES \
+    IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_OK, \
+    IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_ABORT
+
+    MU_DEFINE_ENUM_WITHOUT_INVALID(IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT_VALUES);
+
+    /**
+    *  @brief           Callback invoked by IoTHubClient_UploadMultipleBlocksToBlobAsync requesting the chunks of data to be uploaded.
+    *  @param result    The result of the upload of the previous block of data provided by the user (IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX only)
+    *  @param data      Next block of data to be uploaded, to be provided by the user when this callback is invoked.
+    *  @param size      Size of the data parameter.
+    *  @param context   User context provided on the call to IoTHubClient_UploadMultipleBlocksToBlobAsync.
+    *  @remarks         If the user wants to abort the upload, the callback should return IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_ABORT
+    *                   It should return IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_OK otherwise.
+    *                   If a NULL is provided for parameter "data" and/or zero is provided for "size", the user indicates to the client that the complete file has been uploaded.
+    *                   In such case this callback will be invoked only once more to indicate the status of the final block upload.
+    *                   If result is not FILE_UPLOAD_OK, the upload is cancelled and this callback stops being invoked.
+    *                   When this callback is called for the last time, no data or size is expected, so data and size are NULL
+    */
+    typedef void(*IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK)(IOTHUB_CLIENT_FILE_UPLOAD_RESULT result, unsigned char const ** data, size_t* size, void* context);
+    typedef IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT(*IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX)(IOTHUB_CLIENT_FILE_UPLOAD_RESULT result, unsigned char const ** data, size_t* size, void* context);
+
+    /** @brief    This struct captures IoTHub client configuration. */
+    typedef struct IOTHUB_CLIENT_CONFIG_TAG
+    {
+        /** @brief A function pointer that is passed into the @c IoTHubClientCreate.
+        *    A function definition for AMQP is defined in the include @c iothubtransportamqp.h.
+        *   A function definition for HTTP is defined in the include @c iothubtransporthttp.h
+        *   A function definition for MQTT is defined in the include @c iothubtransportmqtt.h */
+        IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol;
+
+        /** @brief    A string that identifies the device. */
+        const char* deviceId;
+
+        /** @brief    The device key used to authenticate the device.
+        If neither deviceSasToken nor deviceKey is present then the authentication is assumed x509.*/
+        const char* deviceKey;
+
+        /** @brief    The device SAS Token used to authenticate the device in place of device key.
+        If neither deviceSasToken nor deviceKey is present then the authentication is assumed x509.*/
+        const char* deviceSasToken;
+
+        /** @brief    The IoT Hub name to which the device is connecting. */
+        const char* iotHubName;
+
+        /** @brief    IoT Hub suffix goes here, e.g., private.azure-devices-int.net. */
+        const char* iotHubSuffix;
+
+        const char* protocolGatewayHostName;
+    } IOTHUB_CLIENT_CONFIG;
+
+    /** @brief    This struct captures IoTHub client device configuration. */
+    typedef struct IOTHUB_CLIENT_DEVICE_CONFIG_TAG
+    {
+        /** @brief A function pointer that is passed into the @c IoTHubClientCreate.
+        *    A function definition for AMQP is defined in the include @c iothubtransportamqp.h.
+        *   A function definition for HTTP is defined in the include @c iothubtransporthttp.h
+        *   A function definition for MQTT is defined in the include @c iothubtransportmqtt.h */
+        IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol;
+
+        /** @brief a transport handle implementing the protocol */
+        void * transportHandle;
+
+        /** @brief    A string that identifies the device. */
+        const char* deviceId;
+
+        /** @brief    The device key used to authenticate the device.
+        x509 authentication is is not supported for multiplexed connections*/
+        const char* deviceKey;
+
+        /** @brief    The device SAS Token used to authenticate the device in place of device key.
+        x509 authentication is is not supported for multiplexed connections.*/
+        const char* deviceSasToken;
+    } IOTHUB_CLIENT_DEVICE_CONFIG;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IOTHUB_CLIENT_CORE_COMMON_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_client_core_ll.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_client_core_ll.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_client_core_ll.h	(revision 453)
@@ -0,0 +1,74 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/** @file iothub_client_core_ll.h
+*    @brief     APIs that allow a user (usually a device) to communicate
+*             with an Azure IoTHub.
+*
+*    @details IoTHubClientCore_LL is a module that allows a user (usually a
+*             device) to communicate with an Azure IoTHub. It can send events
+*             and receive messages. At any given moment in time there can only
+*             be at most 1 message callback function.
+*
+*             This API surface contains a set of APIs that allows the user to
+*             interact with the lower layer portion of the IoTHubClient. These APIs
+*             contain @c _LL_ in their name, but retain the same functionality like the
+*             @c IoTHubClient_... APIs, with one difference. If the @c _LL_ APIs are
+*             used then the user is responsible for scheduling when the actual work done
+*             by the IoTHubClient happens (when the data is sent/received on/from the wire).
+*             This is useful for constrained devices where spinning a separate thread is
+*             often not desired.
+*/
+
+#ifndef IOTHUB_CLIENT_CORE_LL_H
+#define IOTHUB_CLIENT_CORE_LL_H
+
+typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG* IOTHUB_CLIENT_CORE_LL_HANDLE;
+
+#include <time.h>
+#include "umock_c/umock_c_prod.h"
+#include "iothub_transport_ll.h"
+#include "iothub_client_core_common.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_CORE_LL_HANDLE, IoTHubClientCore_LL_CreateFromConnectionString, const char*, connectionString, IOTHUB_CLIENT_TRANSPORT_PROVIDER, protocol);
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_CORE_LL_HANDLE, IoTHubClientCore_LL_Create, const IOTHUB_CLIENT_CONFIG*, config);
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_CORE_LL_HANDLE, IoTHubClientCore_LL_CreateWithTransport, const IOTHUB_CLIENT_DEVICE_CONFIG*, config);
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_CORE_LL_HANDLE, IoTHubClientCore_LL_CreateFromDeviceAuth, const char*, iothub_uri, const char*, device_id, IOTHUB_CLIENT_TRANSPORT_PROVIDER, protocol);
+     MOCKABLE_FUNCTION(, void, IoTHubClientCore_LL_Destroy, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle);
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_SendEventAsync, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, IOTHUB_MESSAGE_HANDLE, eventMessageHandle, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK, eventConfirmationCallback, void*, userContextCallback);
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_GetSendStatus, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_STATUS*, iotHubClientStatus);
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_SetMessageCallback, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC, messageCallback, void*, userContextCallback);
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_SetConnectionStatusCallback, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_CONNECTION_STATUS_CALLBACK, connectionStatusCallback, void*, userContextCallback);
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_SetRetryPolicy, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY, retryPolicy, size_t, retryTimeoutLimitInSeconds);
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_GetRetryPolicy, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY*, retryPolicy, size_t*, retryTimeoutLimitInSeconds);
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_GetLastMessageReceiveTime, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, time_t*, lastMessageReceiveTime);
+     MOCKABLE_FUNCTION(, void, IoTHubClientCore_LL_DoWork, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle);
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_SetOption, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, optionName, const void*, value);
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_SetDeviceTwinCallback, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK, deviceTwinCallback, void*, userContextCallback);
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_SendReportedState, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const unsigned char*, reportedState, size_t, size, IOTHUB_CLIENT_REPORTED_STATE_CALLBACK, reportedStateCallback, void*, userContextCallback);
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_GetTwinAsync, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK, deviceTwinCallback, void*, userContextCallback);
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_SetDeviceMethodCallback, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_DEVICE_METHOD_CALLBACK_ASYNC, deviceMethodCallback, void*, userContextCallback);
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_SetDeviceMethodCallback_Ex, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK, inboundDeviceMethodCallback, void*, userContextCallback);
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_DeviceMethodResponse, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, METHOD_HANDLE, methodId, const unsigned char*, response, size_t, respSize, int, statusCode);
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_SendEventToOutputAsync, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, IOTHUB_MESSAGE_HANDLE, eventMessageHandle, const char*, outputName, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK, eventConfirmationCallback, void*, userContextCallback);
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_SetInputMessageCallback, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, inputName, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC, eventHandlerCallback, void*, userContextCallback);
+
+#ifndef DONT_USE_UPLOADTOBLOB
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_UploadToBlob, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, const unsigned char*, source, size_t, size);
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_UploadMultipleBlocksToBlob, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK, getDataCallback, void*, context);
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context);
+#endif /*DONT_USE_UPLOADTOBLOB*/
+
+#ifdef USE_EDGE_MODULES
+    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_CORE_LL_HANDLE, IoTHubClientCore_LL_CreateFromEnvironment, IOTHUB_CLIENT_TRANSPORT_PROVIDER, protocol);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IOTHUB_CLIENT_CORE_LL_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_client_ll.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_client_ll.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_client_ll.h	(revision 453)
@@ -0,0 +1,407 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/** @file iothub_client_ll.h
+*    @brief     APIs that allow a user (usually a device) to communicate
+*             with an Azure IoTHub.
+*
+*    @details IoTHubClient_LL is a module that allows a user (usually a
+*             device) to communicate with an Azure IoTHub. It can send events
+*             and receive messages. At any given moment in time there can only
+*             be at most 1 message callback function.
+*
+*             This API surface contains a set of APIs that allows the user to
+*             interact with the lower layer portion of the IoTHubClient. These APIs
+*             contain @c _LL_ in their name, but retain the same functionality like the
+*             @c IoTHubClient_... APIs, with one difference. If the @c _LL_ APIs are
+*             used then the user is responsible for scheduling when the actual work done
+*             by the IoTHubClient happens (when the data is sent/received on/from the wire).
+*             This is useful for constrained devices where spinning a separate thread is
+*             often not desired.
+*/
+
+#ifndef IOTHUB_CLIENT_LL_H
+#define IOTHUB_CLIENT_LL_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <time.h>
+#include "umock_c/umock_c_prod.h"
+
+#include "iothub_client_core_common.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG* IOTHUB_CLIENT_LL_HANDLE;
+
+
+    /**
+    * @brief    Creates a IoT Hub client for communication with an existing
+    *             IoT Hub using the specified connection string parameter.
+    *
+    * @param    connectionString    Pointer to a character string
+    * @param    protocol            Function pointer for protocol implementation
+    *
+    *            Sample connection string:
+    *                <blockquote>
+    *                    <pre>HostName=[IoT Hub name goes here].[IoT Hub suffix goes here, e.g., private.azure-devices-int.net];DeviceId=[Device ID goes here];SharedAccessKey=[Device key goes here];</pre>
+    *                </blockquote>
+    *
+    * @return    A non-NULL @c IOTHUB_CLIENT_LL_HANDLE value that is used when
+    *             invoking other functions for IoT Hub client and @c NULL on failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_HANDLE, IoTHubClient_LL_CreateFromConnectionString, const char*, connectionString, IOTHUB_CLIENT_TRANSPORT_PROVIDER, protocol);
+
+    /**
+    * @brief    Creates a IoT Hub client for communication with an existing IoT
+    *             Hub using the specified parameters.
+    *
+    * @param    config    Pointer to an @c IOTHUB_CLIENT_CONFIG structure
+    *
+    *            The API does not allow sharing of a connection across multiple
+    *            devices. This is a blocking call.
+    *
+    * @return    A non-NULL @c IOTHUB_CLIENT_LL_HANDLE value that is used when
+    *             invoking other functions for IoT Hub client and @c NULL on failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_HANDLE, IoTHubClient_LL_Create, const IOTHUB_CLIENT_CONFIG*, config);
+
+    /**
+    * @brief    Creates a IoT Hub client for communication with an existing IoT
+    *             Hub using an existing transport.
+    *
+    * @param    config    Pointer to an @c IOTHUB_CLIENT_DEVICE_CONFIG structure
+    *
+    *            The API *allows* sharing of a connection across multiple
+    *            devices. This is a blocking call.
+    *
+    * @return    A non-NULL @c IOTHUB_CLIENT_LL_HANDLE value that is used when
+    *             invoking other functions for IoT Hub client and @c NULL on failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_HANDLE, IoTHubClient_LL_CreateWithTransport, const IOTHUB_CLIENT_DEVICE_CONFIG*, config);
+
+     /**
+     * @brief    Creates a IoT Hub client for communication with an existing IoT
+     *             Hub using the device auth module.
+     *
+     * @param    iothub_uri    Pointer to an ioThub hostname received in the registration process
+     * @param    device_id    Pointer to the device Id of the device
+     * @param    device_auth_handle    a device auth handle used to generate the connection string
+     * @param    protocol            Function pointer for protocol implementation
+     *
+     * @return    A non-NULL @c IOTHUB_CLIENT_LL_HANDLE value that is used when
+     *             invoking other functions for IoT Hub client and @c NULL on failure.
+     */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_HANDLE, IoTHubClient_LL_CreateFromDeviceAuth, const char*, iothub_uri, const char*, device_id, IOTHUB_CLIENT_TRANSPORT_PROVIDER, protocol);
+
+    /**
+    * @brief    Disposes of resources allocated by the IoT Hub client. This is a
+    *             blocking call.
+    *
+    * @param    iotHubClientHandle    The handle created by a call to the create function.
+    */
+     MOCKABLE_FUNCTION(, void, IoTHubClient_LL_Destroy, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle);
+
+    /**
+    * @brief    Asynchronous call to send the message specified by @p eventMessageHandle.
+    *
+    * @param    iotHubClientHandle               The handle created by a call to the create function.
+    * @param    eventMessageHandle               The handle to an IoT Hub message.
+    * @param    eventConfirmationCallback      The callback specified by the device for receiving
+    *                                         confirmation of the delivery of the IoT Hub message.
+    *                                         This callback can be expected to invoke the
+    *                                         ::IoTHubClient_LL_SendEventAsync function for the
+    *                                         same message in an attempt to retry sending a failing
+    *                                         message. The user can specify a @c NULL value here to
+    *                                         indicate that no callback is required.
+    * @param    userContextCallback            User specified context that will be provided to the
+    *                                         callback. This can be @c NULL.
+    *
+    *            @b NOTE: The application behavior is undefined if the user calls
+    *            the ::IoTHubClient_LL_Destroy function from within any callback.
+    * @remarks
+    *            The IOTHUB_MESSAGE_HANDLE instance provided as argument is copied by the function,
+    *            so this argument can be destroyed by the calling application right after IoTHubClient_LL_SendEventAsync returns.
+    *            The copy of @c eventMessageHandle is later destroyed by the iothub client when the message is effectively sent, if a failure sending it occurs, or if the client is destroyed.
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SendEventAsync, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_MESSAGE_HANDLE, eventMessageHandle, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK, eventConfirmationCallback, void*, userContextCallback);
+
+    /**
+    * @brief    This function returns the current sending status for IoTHubClient.
+    *
+    * @param    iotHubClientHandle        The handle created by a call to the create function.
+    * @param    iotHubClientStatus        The sending state is populated at the address pointed
+    *                                     at by this parameter. The value will be set to
+    *                                     @c IOTHUBCLIENT_SENDSTATUS_IDLE if there is currently
+    *                                     no item to be sent and @c IOTHUBCLIENT_SENDSTATUS_BUSY
+    *                                     if there are.
+    *
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_GetSendStatus, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_STATUS*, iotHubClientStatus);
+
+    /**
+    * @brief    Sets up the message callback to be invoked when IoT Hub issues a
+    *             message to the device. This is a blocking call.
+    *
+    * @param    iotHubClientHandle               The handle created by a call to the create function.
+    * @param    messageCallback                The callback specified by the device for receiving
+    *                                         messages from IoT Hub.
+    * @param    userContextCallback            User specified context that will be provided to the
+    *                                         callback. This can be @c NULL.
+    *
+    *            @b NOTE: The application behavior is undefined if the user calls
+    *            the ::IoTHubClient_LL_Destroy function from within any callback.
+    *
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SetMessageCallback, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC, messageCallback, void*, userContextCallback);
+
+    /**
+    * @brief    Sets up the connection status callback to be invoked representing the status of
+    * the connection to IOT Hub. This is a blocking call.
+    *
+    * @param    iotHubClientHandle                       The handle created by a call to the create function.
+    * @param    connectionStatusCallback                The callback specified by the device for receiving
+    *                                                 updates about the status of the connection to IoT Hub.
+    * @param    userContextCallback                    User specified context that will be provided to the
+    *                                                 callback. This can be @c NULL.
+    *
+    *            @b NOTE: The application behavior is undefined if the user calls
+    *            the ::IoTHubClient_LL_Destroy function from within any callback.
+    *
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SetConnectionStatusCallback, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_CONNECTION_STATUS_CALLBACK, connectionStatusCallback, void*, userContextCallback);
+
+    /**
+    * @brief    Sets up the connection status callback to be invoked representing the status of
+    * the connection to IOT Hub. This is a blocking call.
+    *
+    * @param    iotHubClientHandle                       The handle created by a call to the create function.
+    * @param    retryPolicy                             The policy to use to reconnect to IoT Hub when a
+    *                                               connection drops.
+    * @param    retryTimeoutLimitInSeconds            Maximum amount of time(seconds) to attempt reconnection when a
+    *                                               connection drops to IOT Hub.
+    *
+    *            @b NOTE: The application behavior is undefined if the user calls
+    *            the ::IoTHubClient_LL_Destroy function from within any callback.
+    *
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SetRetryPolicy, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY, retryPolicy, size_t, retryTimeoutLimitInSeconds);
+
+
+    /**
+    * @brief    Sets up the connection status callback to be invoked representing the status of
+    * the connection to IOT Hub. This is a blocking call.
+    *
+    * @param    iotHubClientHandle                       The handle created by a call to the create function.
+    * @param    retryPolicy                             Out parameter containing the policy to use to reconnect to IoT Hub.
+    * @param    retryTimeoutLimitInSeconds            Out parameter containing maximum amount of time in seconds to attempt reconnection
+                                                    to IOT Hub.
+    *
+    *            @b NOTE: The application behavior is undefined if the user calls
+    *            the ::IoTHubClient_LL_Destroy function from within any callback.
+    *
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_GetRetryPolicy, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY*, retryPolicy, size_t*, retryTimeoutLimitInSeconds);
+
+    /**
+    * @brief    This function returns in the out parameter @p lastMessageReceiveTime
+    *             what was the value of the @c time function when the last message was
+    *             received at the client.
+    *
+    * @param    iotHubClientHandle                The handle created by a call to the create function.
+    * @param    lastMessageReceiveTime          Out parameter containing the value of @c time function
+    *                                             when the last message was received.
+    *
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_GetLastMessageReceiveTime, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, time_t*, lastMessageReceiveTime);
+
+    /**
+    * @brief    This function is meant to be called by the user when work
+    *             (sending/receiving) can be done by the IoTHubClient.
+    *
+    * @param    iotHubClientHandle    The handle created by a call to the create function.
+    *
+    *            All IoTHubClient interactions (in regards to network traffic
+    *            and/or user level callbacks) are the effect of calling this
+    *            function and they take place synchronously inside _DoWork.
+    */
+     MOCKABLE_FUNCTION(, void, IoTHubClient_LL_DoWork, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle);
+
+    /**
+    * @brief    This API sets a runtime option identified by parameter @p optionName
+    *             to a value pointed to by @p value. @p optionName and the data type
+    *             @p value is pointing to are specific for every option.
+    *
+    * @param    iotHubClientHandle    The handle created by a call to the create function.
+    * @param    optionName              Name of the option.
+    * @param    value                  The value.
+    *
+    *            The options that can be set via this API are:
+    *                - @b timeout - the maximum time in milliseconds a communication is
+    *                  allowed to use. @p value is a pointer to an @c unsigned @c int with
+    *                  the timeout value in milliseconds. This is only supported for the HTTP
+    *                  protocol as of now. When the HTTP protocol uses CURL, the meaning of
+    *                  the parameter is <em>total request time</em>. When the HTTP protocol uses
+    *                  winhttp, the meaning is the same as the @c dwSendTimeout and
+    *                  @c dwReceiveTimeout parameters of the
+    *                  <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa384116(v=vs.85).aspx">
+    *                  WinHttpSetTimeouts</a> API.
+    *                - @b CURLOPT_LOW_SPEED_LIMIT - only available for HTTP protocol and only
+    *                  when CURL is used. It has the same meaning as CURL's option with the same
+    *                  name. @p value is pointer to a long.
+    *                - @b CURLOPT_LOW_SPEED_TIME - only available for HTTP protocol and only
+    *                  when CURL is used. It has the same meaning as CURL's option with the same
+    *                  name. @p value is pointer to a long.
+    *                - @b CURLOPT_FORBID_REUSE - only available for HTTP protocol and only
+    *                  when CURL is used. It has the same meaning as CURL's option with the same
+    *                  name. @p value is pointer to a long.
+    *                - @b CURLOPT_FRESH_CONNECT - only available for HTTP protocol and only
+    *                  when CURL is used. It has the same meaning as CURL's option with the same
+    *                  name. @p value is pointer to a long.
+    *                - @b CURLOPT_VERBOSE - only available for HTTP protocol and only
+    *                  when CURL is used. It has the same meaning as CURL's option with the same
+    *                  name. @p value is pointer to a long.
+    *              - @b keepalive - available for MQTT protocol.  Integer value that sets the
+    *                interval in seconds when pings are sent to the server.
+    *              - @b logtrace - available for MQTT protocol.  Boolean value that turns on and
+    *                off the diagnostic logging.
+    *              - @b sas_token_lifetime - available for MQTT & AMQP protocol.  size_t value that that determines the
+    *                sas token timeout length.
+    *
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SetOption, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, optionName, const void*, value);
+
+    /**
+    * @brief    This API specifies a call back to be used when the device receives a desired state update.
+    *
+    * @param    iotHubClientHandle        The handle created by a call to the create function.
+    * @param    deviceTwinCallback        The callback specified by the device client to be used for updating
+    *                                    the desired state. The callback will be called in response to patch
+    *                                    request send by the IoTHub services. The payload will be passed to the
+    *                                    callback, along with two version numbers:
+    *                                        - Desired:
+    *                                        - LastSeenReported:
+    * @param    userContextCallback        User specified context that will be provided to the
+    *                                     callback. This can be @c NULL.
+    *
+    *            @b NOTE: The application behavior is undefined if the user calls
+    *            the ::IoTHubClient_LL_Destroy function from within any callback.
+    *
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SetDeviceTwinCallback, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK, deviceTwinCallback, void*, userContextCallback);
+
+    /**
+    * @brief    This API sneds a report of the device's properties and their current values.
+    *
+    * @param    iotHubClientHandle        The handle created by a call to the create function.
+    * @param    reportedState            The current device property values to be 'reported' to the IoTHub.
+    * @param    reportedStateCallback    The callback specified by the device client to be called with the
+    *                                    result of the transaction.
+    * @param    userContextCallback        User specified context that will be provided to the
+    *                                     callback. This can be @c NULL.
+    *
+    *            @b NOTE: The application behavior is undefined if the user calls
+    *            the ::IoTHubClient_LL_Destroy function from within any callback.
+    *
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SendReportedState, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, const unsigned char*, reportedState, size_t, size, IOTHUB_CLIENT_REPORTED_STATE_CALLBACK, reportedStateCallback, void*, userContextCallback);
+
+     /**
+     * @brief    This API sets callback for cloud to device method call.
+     *
+     * @param    iotHubClientHandle        The handle created by a call to the create function.
+     * @param    deviceMethodCallback    The callback which will be called by IoTHub.
+     * @param    userContextCallback        User specified context that will be provided to the
+     *                                     callback. This can be @c NULL.
+     *
+     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+     */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SetDeviceMethodCallback, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_DEVICE_METHOD_CALLBACK_ASYNC, deviceMethodCallback, void*, userContextCallback);
+
+     /**
+     * @brief    This API sets callback for async cloud to device method call.
+     *
+     * @param    iotHubClientHandle                The handle created by a call to the create function.
+     * @param    inboundDeviceMethodCallback     The callback which will be called by IoTHub.
+     * @param    userContextCallback                User specified context that will be provided to the
+     *                                             callback. This can be @c NULL.
+     *
+     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+     */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SetDeviceMethodCallback_Ex, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK, inboundDeviceMethodCallback, void*, userContextCallback);
+
+     /**
+     * @brief    This API responses to a asnyc method callback identified the methodId.
+     *
+     * @param    iotHubClientHandle      The handle created by a call to the create function.
+     * @param    methodId                The methodId of the Device Method callback.
+     * @param    response                The response data for the method callback.
+     * @param    response_size           The size of the response data buffer.
+     * @param    status_response         The status response of the method callback.
+     *
+     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+     */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_DeviceMethodResponse, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, METHOD_HANDLE, methodId, const unsigned char*, response, size_t, respSize, int, statusCode);
+
+#ifndef DONT_USE_UPLOADTOBLOB
+    /**
+    * @brief    This API uploads to Azure Storage the content pointed to by @p source having the size @p size
+    *           under the blob name devicename/@pdestinationFileName
+    *
+    * @param    iotHubClientHandle        The handle created by a call to the create function.
+    * @param    destinationFileName     name of the file.
+    * @param    source                  pointer to the source for file content (can be NULL)
+    * @param    size                    the size of the source in memory (if @p source is NULL then size needs to be 0).
+    *
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, const unsigned char*, source, size_t, size);
+
+     /**
+     ** DEPRECATED: Use IoTHubClient_LL_UploadMultipleBlocksToBlobAsyncEx instead **
+     * @brief    This API uploads to Azure Storage the content provided block by block by @p getDataCallback
+     *           under the blob name devicename/@pdestinationFileName
+     *
+     * @param    iotHubClientHandle      The handle created by a call to the create function.
+     * @param    destinationFileName     name of the file.
+     * @param    getDataCallback         A callback to be invoked to acquire the file chunks to be uploaded, as well as to indicate the status of the upload of the previous block.
+     * @param    context                 Any data provided by the user to serve as context on getDataCallback.
+     *
+     * @return   IOTHUB_CLIENT_OK upon success or an error code upon failure.
+     ** DEPRECATED: Use IoTHubClient_LL_UploadMultipleBlocksToBlobAsyncEx instead **
+     */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadMultipleBlocksToBlob, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK, getDataCallback, void*, context);
+
+     /**
+     * @brief    This API uploads to Azure Storage the content provided block by block by @p getDataCallback
+     *           under the blob name devicename/@pdestinationFileName
+     *
+     * @param    iotHubClientHandle      The handle created by a call to the create function.
+     * @param    destinationFileName     name of the file.
+     * @param    getDataCallbackEx       A callback to be invoked to acquire the file chunks to be uploaded, as well as to indicate the status of the upload of the previous block.
+     * @param    context                 Any data provided by the user to serve as context on getDataCallback.
+     *
+     * @return   IOTHUB_CLIENT_OK upon success or an error code upon failure.
+     */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadMultipleBlocksToBlobEx, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context);
+
+#endif /*DONT_USE_UPLOADTOBLOB*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IOTHUB_CLIENT_LL_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_client_options.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_client_options.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_client_options.h	(revision 453)
@@ -0,0 +1,93 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef IOTHUB_CLIENT_OPTIONS_H
+#define IOTHUB_CLIENT_OPTIONS_H
+
+#include "azure_c_shared_utility/const_defines.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    typedef struct IOTHUB_PROXY_OPTIONS_TAG
+    {
+        const char* host_address;
+        const char* username;
+        const char* password;
+    } IOTHUB_PROXY_OPTIONS;
+
+    static STATIC_VAR_UNUSED const char* OPTION_RETRY_INTERVAL_SEC = "retry_interval_sec";
+    static STATIC_VAR_UNUSED const char* OPTION_RETRY_MAX_DELAY_SECS = "retry_max_delay_secs";
+
+    static STATIC_VAR_UNUSED const char* OPTION_LOG_TRACE = "logtrace";
+    static STATIC_VAR_UNUSED const char* OPTION_X509_CERT = "x509certificate";
+    static STATIC_VAR_UNUSED const char* OPTION_X509_PRIVATE_KEY = "x509privatekey";
+    static STATIC_VAR_UNUSED const char* OPTION_KEEP_ALIVE = "keepalive";
+    static STATIC_VAR_UNUSED const char* OPTION_CONNECTION_TIMEOUT = "connect_timeout";
+
+    static STATIC_VAR_UNUSED const char* OPTION_PROXY_HOST = "proxy_address";
+    static STATIC_VAR_UNUSED const char* OPTION_PROXY_USERNAME = "proxy_username";
+    static STATIC_VAR_UNUSED const char* OPTION_PROXY_PASSWORD = "proxy_password";
+
+    static STATIC_VAR_UNUSED const char* OPTION_SAS_TOKEN_LIFETIME = "sas_token_lifetime";
+    static STATIC_VAR_UNUSED const char* OPTION_SAS_TOKEN_REFRESH_TIME = "sas_token_refresh_time";
+    static STATIC_VAR_UNUSED const char* OPTION_CBS_REQUEST_TIMEOUT = "cbs_request_timeout";
+
+    static STATIC_VAR_UNUSED const char* OPTION_MIN_POLLING_TIME = "MinimumPollingTime";
+    static STATIC_VAR_UNUSED const char* OPTION_BATCHING = "Batching";
+
+    /* DEPRECATED:: OPTION_MESSAGE_TIMEOUT is DEPRECATED! Use OPTION_SERVICE_SIDE_KEEP_ALIVE_FREQ_SECS for AMQP; MQTT has no option available. OPTION_MESSAGE_TIMEOUT legacy variable will be kept for back-compat.  */
+    static STATIC_VAR_UNUSED const char* OPTION_MESSAGE_TIMEOUT = "messageTimeout";
+    static STATIC_VAR_UNUSED const char* OPTION_BLOB_UPLOAD_TIMEOUT_SECS = "blob_upload_timeout_secs";
+    static STATIC_VAR_UNUSED const char* OPTION_PRODUCT_INFO = "product_info";
+
+    /*
+    * @brief    Specifies the Digital Twin Model Id of the connection. Only valid for use with MQTT Transport
+    */
+    static STATIC_VAR_UNUSED const char* OPTION_MODEL_ID = "model_id";
+
+    /*
+    * @brief    Turns on automatic URL encoding of message properties + system properties. Only valid for use with MQTT Transport
+    */
+    static STATIC_VAR_UNUSED const char* OPTION_AUTO_URL_ENCODE_DECODE = "auto_url_encode_decode";
+
+    /*
+    * @brief Informs the service of what is the maximum period the client will wait for a keep-alive message from the service.
+    *        The service must send keep-alives before this timeout is reached, otherwise the client will trigger its re-connection logic.
+    *        Setting this option to a low value results in more aggressive/responsive re-connection by the client.
+    *        The default value for this option is 240 seconds, and the minimum allowed is usually 5 seconds.
+    *        To virtually disable the keep-alives from the service (and consequently the keep-alive timeout control on the client-side), set this option to a high value (e.g., UINT_MAX).
+    */
+    static STATIC_VAR_UNUSED const char* OPTION_SERVICE_SIDE_KEEP_ALIVE_FREQ_SECS = "svc2cl_keep_alive_timeout_secs";
+
+    /* DEPRECATED:: OPTION_C2D_KEEP_ALIVE_FREQ_SECS is DEPRECATED!  Use OPTION_SERVICE_SIDE_KEEP_ALIVE_FREQ_SECS, but OPTION_C2D_KEEP_ALIVE_FREQ_SECS legacy variable kept for back-compat.  */
+    static STATIC_VAR_UNUSED const char* OPTION_C2D_KEEP_ALIVE_FREQ_SECS = "c2d_keep_alive_freq_secs";
+
+    /*
+    * @brief Ratio to be used for client side pings in AMQP protocol.
+    *        The client must use this ratio to send keep-alives before service side remote idle timeout is reached, otherwise the service will disconnect the client.
+    *        The default value for this option is 1/2 of the remote idle value sent by the service.
+    *        For AMQP remote idle set to 4 minutes, default client ping will be 2 minutes. For AMQP remote idle set to 25 minutes configured via per Hub basis, the default ping will be 12.5 minutes.
+    */
+    static STATIC_VAR_UNUSED const char* OPTION_REMOTE_IDLE_TIMEOUT_RATIO = "cl2svc_keep_alive_send_ratio";
+
+    /*
+    * @brief This option should be used instead of OPTION_MESSAGE_TIMEOUT if using AMQP protocol.
+    *        It defines the maximum ammount of time, in seconds, the client will wait for a telemetry message to complete sending before returning it with a IOTHUB_CLIENT_CONFIRMATION_MESSAGE_TIMEOUT error.
+    *        The default value 5 (five) minutes.
+    *        This option is applicable only to AMQP protocol.
+    */
+    static STATIC_VAR_UNUSED const char* OPTION_EVENT_SEND_TIMEOUT_SECS = "event_send_timeout_secs";
+
+    //diagnostic sampling percentage value, [0-100]
+    static STATIC_VAR_UNUSED const char* OPTION_DIAGNOSTIC_SAMPLING_PERCENTAGE = "diag_sampling_percentage";
+
+    static STATIC_VAR_UNUSED const char* OPTION_DO_WORK_FREQUENCY_IN_MS = "do_work_freq_ms";
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IOTHUB_CLIENT_OPTIONS_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_client_version.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_client_version.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_client_version.h	(revision 453)
@@ -0,0 +1,33 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/** @file iothub_client_version.h
+*    @brief Functions for managing the client SDK version.
+*/
+
+#ifndef IOTHUB_CLIENT_VERSION_H
+#define IOTHUB_CLIENT_VERSION_H
+
+#define IOTHUB_SDK_VERSION "1.3.8"
+
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    /**
+     * @brief   Returns a pointer to a null terminated string containing the
+     *          current IoT Hub Client SDK version.
+     *
+     * @return  Pointer to a null terminated string containing the
+     *          current IoT Hub Client SDK version.
+     */
+    MOCKABLE_FUNCTION(, const char*, IoTHubClient_GetVersionString);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // IOTHUB_CLIENT_VERSION_H
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_device_client_ll.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_device_client_ll.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_device_client_ll.h	(revision 453)
@@ -0,0 +1,400 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/** @file iothub_device_client_ll.h
+*    @brief     APIs that allow a user (usually a device) to communicate
+*             with an Azure IoTHub.
+*
+*    @details IoTHubDeviceClient_LL is a module that allows a user (usually a
+*             device) to communicate with an Azure IoTHub. It can send events
+*             and receive messages. At any given moment in time there can only
+*             be at most 1 message callback function.
+*
+*             This API surface contains a set of APIs that allows the user to
+*             interact with the lower layer portion of the IoTHubClient. These APIs
+*             contain @c _LL_ in their name, but retain the same functionality like the
+*             @c IoTHubDeviceClient_... APIs, with one difference. If the @c _LL_ APIs are
+*             used then the user is responsible for scheduling when the actual work done
+*             by the IoTHubClient happens (when the data is sent/received on/from the wire).
+*             This is useful for constrained devices where spinning a separate thread is
+*             often not desired.
+*/
+
+#ifndef IOTHUB_DEVICE_CLIENT_LL_H
+#define IOTHUB_DEVICE_CLIENT_LL_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "azure_macro_utils/macro_utils.h"
+#include "umock_c/umock_c_prod.h"
+
+#include "iothub_transport_ll.h"
+#include "iothub_client_core_ll.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG* IOTHUB_DEVICE_CLIENT_LL_HANDLE;
+
+
+    /**
+    * @brief    Creates a IoT Hub client for communication with an existing
+    *           IoT Hub using the specified connection string parameter.
+    *
+    * @param    connectionString    Pointer to a character string
+    * @param    protocol            Function pointer for protocol implementation
+    *
+    *            Sample connection string:
+    *                <blockquote>
+    *                    <pre>HostName=[IoT Hub name goes here].[IoT Hub suffix goes here, e.g., private.azure-devices-int.net];DeviceId=[Device ID goes here];SharedAccessKey=[Device key goes here];</pre>
+    *                </blockquote>
+    *
+    * @return    A non-NULL @c IOTHUB_DEVICE_CLIENT_LL_HANDLE value that is used when
+    *             invoking other functions for IoT Hub client and @c NULL on failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_DEVICE_CLIENT_LL_HANDLE, IoTHubDeviceClient_LL_CreateFromConnectionString, const char*, connectionString, IOTHUB_CLIENT_TRANSPORT_PROVIDER, protocol);
+
+    /**
+    * @brief    Creates a IoT Hub client for communication with an existing IoT
+    *           Hub using the specified parameters.
+    *
+    * @param    config    Pointer to an @c IOTHUB_CLIENT_CONFIG structure
+    *
+    *           The API does not allow sharing of a connection across multiple
+    *           devices. This is a blocking call.
+    *
+    * @return    A non-NULL @c IOTHUB_DEVICE_CLIENT_LL_HANDLE value that is used when
+    *            invoking other functions for IoT Hub client and @c NULL on failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_DEVICE_CLIENT_LL_HANDLE, IoTHubDeviceClient_LL_Create, const IOTHUB_CLIENT_CONFIG*, config);
+
+    /**
+    * @brief    Creates a IoT Hub client for communication with an existing IoT
+    *           Hub using an existing transport.
+    *
+    * @param    config    Pointer to an @c IOTHUB_CLIENT_DEVICE_CONFIG structure
+    *
+    *           The API *allows* sharing of a connection across multiple
+    *           devices. This is a blocking call.
+    *
+    * @return   A non-NULL @c IOTHUB_DEVICE_CLIENT_LL_HANDLE value that is used when
+    *           invoking other functions for IoT Hub client and @c NULL on failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_DEVICE_CLIENT_LL_HANDLE, IoTHubDeviceClient_LL_CreateWithTransport, const IOTHUB_CLIENT_DEVICE_CONFIG*, config);
+
+     /**
+     * @brief    Creates a IoT Hub client for communication with an existing IoT
+     *           Hub using the device auth module.
+     *
+     * @param    iothub_uri             Pointer to an ioThub hostname received in the registration process
+     * @param    device_id              Pointer to the device Id of the device
+     * @param    device_auth_handle     A device auth handle used to generate the connection string
+     * @param    protocol               Function pointer for protocol implementation
+     *
+     * @return   A non-NULL @c IOTHUB_DEVICE_CLIENT_LL_HANDLE value that is used when
+     *           invoking other functions for IoT Hub client and @c NULL on failure.
+     */
+     MOCKABLE_FUNCTION(, IOTHUB_DEVICE_CLIENT_LL_HANDLE, IoTHubDeviceClient_LL_CreateFromDeviceAuth, const char*, iothub_uri, const char*, device_id, IOTHUB_CLIENT_TRANSPORT_PROVIDER, protocol);
+
+    /**
+    * @brief    Disposes of resources allocated by the IoT Hub client. This is a
+    *           blocking call.
+    *
+    * @param    iotHubClientHandle    The handle created by a call to the create function.
+    */
+     MOCKABLE_FUNCTION(, void, IoTHubDeviceClient_LL_Destroy, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle);
+
+    /**
+    * @brief    Asynchronous call to send the message specified by @p eventMessageHandle.
+    *
+    * @param    iotHubClientHandle              The handle created by a call to the create function.
+    * @param    eventMessageHandle              The handle to an IoT Hub message.
+    * @param    eventConfirmationCallback       The callback specified by the device for receiving
+    *                                           confirmation of the delivery of the IoT Hub message.
+    *                                           This callback can be expected to invoke the
+    *                                           ::IoTHubDeviceClient_LL_SendEventAsync function for the
+    *                                           same message in an attempt to retry sending a failing
+    *                                           message. The user can specify a @c NULL value here to
+    *                                           indicate that no callback is required.
+    * @param    userContextCallback             User specified context that will be provided to the
+    *                                           callback. This can be @c NULL.
+    *
+    *           @b NOTE: The application behavior is undefined if the user calls
+    *           the ::IoTHubDeviceClient_LL_Destroy function from within any callback.
+    * @remarks
+    *           The IOTHUB_MESSAGE_HANDLE instance provided as argument is copied by the function,
+    *           so this argument can be destroyed by the calling application right after IoTHubDeviceClient_LL_SendEventAsync returns.
+    *           The copy of @c eventMessageHandle is later destroyed by the iothub client when the message is effectively sent, if a failure sending it occurs, or if the client is destroyed.
+    * @return   IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_SendEventAsync, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_MESSAGE_HANDLE, eventMessageHandle, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK, eventConfirmationCallback, void*, userContextCallback);
+
+    /**
+    * @brief    This function returns the current sending status for IoTHubClient.
+    *
+    * @param    iotHubClientHandle        The handle created by a call to the create function.
+    * @param    iotHubClientStatus        The sending state is populated at the address pointed
+    *                                     at by this parameter. The value will be set to
+    *                                     @c IOTHUBCLIENT_SENDSTATUS_IDLE if there is currently
+    *                                     no item to be sent and @c IOTHUBCLIENT_SENDSTATUS_BUSY
+    *                                     if there are.
+    *
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_GetSendStatus, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_STATUS*, iotHubClientStatus);
+
+    /**
+    * @brief    Sets up the message callback to be invoked when IoT Hub issues a
+    *           message to the device. This is a blocking call.
+    *
+    * @param    iotHubClientHandle              The handle created by a call to the create function.
+    * @param    messageCallback                 The callback specified by the device for receiving
+    *                                           messages from IoT Hub.
+    * @param    userContextCallback             User specified context that will be provided to the
+    *                                           callback. This can be @c NULL.
+    *
+    *           @b NOTE: The application behavior is undefined if the user calls
+    *           the ::IoTHubDeviceClient_LL_Destroy function from within any callback.
+    *
+    * @return   IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_SetMessageCallback, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC, messageCallback, void*, userContextCallback);
+
+    /**
+    * @brief    Sets up the connection status callback to be invoked representing the status of
+    * the connection to IOT Hub. This is a blocking call.
+    *
+    * @param    iotHubClientHandle              The handle created by a call to the create function.
+    * @param    connectionStatusCallback        The callback specified by the device for receiving
+    *                                           updates about the status of the connection to IoT Hub.
+    * @param    userContextCallback             User specified context that will be provided to the
+    *                                           callback. This can be @c NULL.
+    *
+    *           @b NOTE: The application behavior is undefined if the user calls
+    *           the ::IoTHubDeviceClient_LL_Destroy function from within any callback.
+    *
+    * @return   IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_SetConnectionStatusCallback, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_CONNECTION_STATUS_CALLBACK, connectionStatusCallback, void*, userContextCallback);
+
+    /**
+    * @brief    Sets up the connection status callback to be invoked representing the status of
+    * the connection to IOT Hub. This is a blocking call.
+    *
+    * @param    iotHubClientHandle              The handle created by a call to the create function.
+    * @param    retryPolicy                     The policy to use to reconnect to IoT Hub when a
+    *                                           connection drops.
+    * @param    retryTimeoutLimitInSeconds      Maximum amount of time(seconds) to attempt reconnection when a
+    *                                           connection drops to IOT Hub.
+    *
+    *           @b NOTE: The application behavior is undefined if the user calls
+    *           the ::IoTHubDeviceClient_LL_Destroy function from within any callback.
+    *
+    * @return   IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_SetRetryPolicy, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY, retryPolicy, size_t, retryTimeoutLimitInSeconds);
+
+
+    /**
+    * @brief    Sets up the connection status callback to be invoked representing the status of
+    * the connection to IOT Hub. This is a blocking call.
+    *
+    * @param    iotHubClientHandle                  The handle created by a call to the create function.
+    * @param    retryPolicy                         Out parameter containing the policy to use to reconnect to IoT Hub.
+    * @param    retryTimeoutLimitInSeconds          Out parameter containing maximum amount of time in seconds to attempt reconnection
+                                                    to IOT Hub.
+    *
+    *           @b NOTE: The application behavior is undefined if the user calls
+    *           the ::IoTHubDeviceClient_LL_Destroy function from within any callback.
+    *
+    * @return   IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_GetRetryPolicy, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY*, retryPolicy, size_t*, retryTimeoutLimitInSeconds);
+
+    /**
+    * @brief    This function returns in the out parameter @p lastMessageReceiveTime
+    *           what was the value of the @c time function when the last message was
+    *           received at the client.
+    *
+    * @param    iotHubClientHandle          The handle created by a call to the create function.
+    * @param    lastMessageReceiveTime      Out parameter containing the value of @c time function
+    *                                       when the last message was received.
+    *
+    * @return   IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_GetLastMessageReceiveTime, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, time_t*, lastMessageReceiveTime);
+
+    /**
+    * @brief    This function MUST be called by the user so work (sending/receiving data on the wire,
+    *           computing and enforcing timeout controls, managing the connection to the IoT Hub) can
+    *           be done by the IoTHubClient.
+    *           The recommended call frequency is at least once every 100 milliseconds.
+    *
+    * @param    iotHubClientHandle    The handle created by a call to the create function.
+    *
+    *           All IoTHubClient interactions (in regards to network traffic
+    *           and/or user level callbacks) are the effect of calling this
+    *           function and they take place synchronously inside _DoWork.
+    */
+     MOCKABLE_FUNCTION(, void, IoTHubDeviceClient_LL_DoWork, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle);
+
+    /**
+    * @brief    This API sets a runtime option identified by parameter @p optionName
+    *           to a value pointed to by @p value. @p optionName and the data type
+    *           @p value is pointing to are specific for every option.
+    *
+    * @param    iotHubClientHandle      The handle created by a call to the create function.
+    * @param    optionName              Name of the option.
+    * @param    value                   The value.
+    *
+    *           The options that can be set via this API are:
+    *                - @b timeout - the maximum time in milliseconds a communication is
+    *                  allowed to use. @p value is a pointer to an @c unsigned @c int with
+    *                  the timeout value in milliseconds. This is only supported for the HTTP
+    *                  protocol as of now. When the HTTP protocol uses CURL, the meaning of
+    *                  the parameter is <em>total request time</em>. When the HTTP protocol uses
+    *                  winhttp, the meaning is the same as the @c dwSendTimeout and
+    *                  @c dwReceiveTimeout parameters of the
+    *                  <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa384116(v=vs.85).aspx">
+    *                  WinHttpSetTimeouts</a> API.
+    *                - @b CURLOPT_LOW_SPEED_LIMIT - only available for HTTP protocol and only
+    *                  when CURL is used. It has the same meaning as CURL's option with the same
+    *                  name. @p value is pointer to a long.
+    *                - @b CURLOPT_LOW_SPEED_TIME - only available for HTTP protocol and only
+    *                  when CURL is used. It has the same meaning as CURL's option with the same
+    *                  name. @p value is pointer to a long.
+    *                - @b CURLOPT_FORBID_REUSE - only available for HTTP protocol and only
+    *                  when CURL is used. It has the same meaning as CURL's option with the same
+    *                  name. @p value is pointer to a long.
+    *                - @b CURLOPT_FRESH_CONNECT - only available for HTTP protocol and only
+    *                  when CURL is used. It has the same meaning as CURL's option with the same
+    *                  name. @p value is pointer to a long.
+    *                - @b CURLOPT_VERBOSE - only available for HTTP protocol and only
+    *                  when CURL is used. It has the same meaning as CURL's option with the same
+    *                  name. @p value is pointer to a long.
+    *                - @b keepalive - available for MQTT protocol.  Integer value that sets the
+    *                  interval in seconds when pings are sent to the server.
+    *                - @b logtrace - available for MQTT protocol.  Boolean value that turns on and
+    *                  off the diagnostic logging.
+    *                - @b sas_token_lifetime - available for MQTT & AMQP protocol.  size_t value that that determines the
+    *                  sas token timeout length.
+    *                - @b OPTION_TRUSTED_CERT - Azure Server certificate used to validate TLS connection to iothub.
+    *
+    * @return   IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_SetOption, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, optionName, const void*, value);
+
+    /**
+    * @brief   This API specifies a callback to be used when the device receives a desired state update.
+    *
+    * @param   iotHubClientHandle        The handle created by a call to the create function.
+    * @param   deviceTwinCallback        The callback specified by the device client to be used for updating
+    *                                    the desired state. The callback will be called in response to patch
+    *                                    request send by the IoTHub services. The payload will be passed to the
+    *                                    callback, along with two version numbers:
+    *                                        - Desired:
+    *                                        - LastSeenReported:
+    * @param   userContextCallback       User specified context that will be provided to the
+    *                                    callback. This can be @c NULL.
+    *
+    *           @b NOTE: The application behavior is undefined if the user calls
+    *           the ::IoTHubDeviceClient_LL_Destroy function from within any callback.
+    *
+    * @return   IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_SetDeviceTwinCallback, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK, deviceTwinCallback, void*, userContextCallback);
+
+    /**
+    * @brief    This API sends a report of the device's properties and their current values.
+    *
+    * @param    iotHubClientHandle        The handle created by a call to the create function.
+    * @param    reportedState             The current device property values to be 'reported' to the IoTHub.
+    * @param    reportedStateCallback     The callback specified by the device client to be called with the
+    *                                     result of the transaction.
+    * @param    userContextCallback       User specified context that will be provided to the
+    *                                     callback. This can be @c NULL.
+    *
+    *            @b NOTE: The application behavior is undefined if the user calls
+    *            the ::IoTHubDeviceClient_LL_Destroy function from within any callback.
+    *
+    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_SendReportedState, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, const unsigned char*, reportedState, size_t, size, IOTHUB_CLIENT_REPORTED_STATE_CALLBACK, reportedStateCallback, void*, userContextCallback);
+
+     /**
+     * @brief	This API enabled the device to request the full device twin (with all the desired and reported properties) on demand.
+     *
+     * @param	iotHubClientHandle		The handle created by a call to the create function.
+     * @param	deviceTwinCallback	    The callback specified by the device client to receive the Twin document.
+     * @param	userContextCallback		User specified context that will be provided to the
+     * 									callback. This can be @c NULL.
+     *
+     *			@b NOTE: The application behavior is undefined if the user calls
+     *			the ::IoTHubClient_LL_Destroy function from within any callback.
+     *
+     * @return	IOTHUB_CLIENT_OK upon success or an error code upon failure.
+     */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_GetTwinAsync, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK, deviceTwinCallback, void*, userContextCallback);
+
+     /**
+     * @brief    This API sets the callback for async cloud to device method calls.
+     *
+     * @param    iotHubClientHandle                 The handle created by a call to the create function.
+     * @param    inboundDeviceMethodCallback        The callback which will be called by IoTHub.
+     * @param    userContextCallback                User specified context that will be provided to the
+     *                                              callback. This can be @c NULL.
+     *
+     * @return   IOTHUB_CLIENT_OK upon success or an error code upon failure.
+     */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_SetDeviceMethodCallback, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_DEVICE_METHOD_CALLBACK_ASYNC, deviceMethodCallback, void*, userContextCallback);
+
+     /**
+     * @brief    This API responds to an asnyc method callback identified the methodId.
+     *
+     * @param    iotHubClientHandle      The handle created by a call to the create function.
+     * @param    methodId                The methodId of the Device Method callback.
+     * @param    response                The response data for the method callback.
+     * @param    response_size           The size of the response data buffer.
+     * @param    status_response         The status response of the method callback.
+     *
+     * @return   IOTHUB_CLIENT_OK upon success or an error code upon failure.
+     */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_DeviceMethodResponse, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, METHOD_HANDLE, methodId, const unsigned char*, response, size_t, respSize, int, statusCode);
+
+#ifndef DONT_USE_UPLOADTOBLOB
+    /**
+    * @brief    This API uploads to Azure Storage the content pointed to by @p source having the size @p size
+    *           under the blob name devicename/@pdestinationFileName
+    *
+    * @param    iotHubClientHandle      The handle created by a call to the create function.
+    * @param    destinationFileName     name of the file.
+    * @param    source                  pointer to the source for file content (can be NULL)
+    * @param    size                    the size of the source in memory (if @p source is NULL then size needs to be 0).
+    *
+    * @return   IOTHUB_CLIENT_OK upon success or an error code upon failure.
+    */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_UploadToBlob, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, const unsigned char*, source, size_t, size);
+
+     /**
+     * @brief    This API uploads to Azure Storage the content provided block by block by @p getDataCallback
+     *           under the blob name devicename/@pdestinationFileName
+     *
+     * @param    iotHubClientHandle      The handle created by a call to the create function.
+     * @param    destinationFileName     name of the file.
+     * @param    getDataCallbackEx       A callback to be invoked to acquire the file chunks to be uploaded, as well as to indicate the status of the upload of the previous block.
+     * @param    context                 Any data provided by the user to serve as context on getDataCallback.
+     *
+     * @return   IOTHUB_CLIENT_OK upon success or an error code upon failure.
+     */
+     MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context);
+
+#endif /*DONT_USE_UPLOADTOBLOB*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IOTHUB_DEVICE_CLIENT_LL_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_message.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_message.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_message.h	(revision 453)
@@ -0,0 +1,401 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/** @file   iothub_message.h
+*    @brief  The @c IoTHub_Message component encapsulates one message that
+*           can be transferred by an IoT hub client.
+*/
+
+#ifndef IOTHUB_MESSAGE_H
+#define IOTHUB_MESSAGE_H
+
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/map.h"
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+#include <cstddef>
+extern "C"
+{
+#else
+#include <stddef.h>
+#endif
+
+#define IOTHUB_MESSAGE_RESULT_VALUES         \
+    IOTHUB_MESSAGE_OK,                       \
+    IOTHUB_MESSAGE_INVALID_ARG,              \
+    IOTHUB_MESSAGE_INVALID_TYPE,             \
+    IOTHUB_MESSAGE_ERROR                     \
+
+/** @brief Enumeration specifying the status of calls to various
+*  APIs in this module.
+*/
+MU_DEFINE_ENUM_WITHOUT_INVALID(IOTHUB_MESSAGE_RESULT, IOTHUB_MESSAGE_RESULT_VALUES);
+
+#define IOTHUBMESSAGE_CONTENT_TYPE_VALUES \
+IOTHUBMESSAGE_BYTEARRAY, \
+IOTHUBMESSAGE_STRING, \
+IOTHUBMESSAGE_UNKNOWN \
+
+/** @brief Enumeration specifying the content type of the a given
+* message.
+*/
+MU_DEFINE_ENUM_WITHOUT_INVALID(IOTHUBMESSAGE_CONTENT_TYPE, IOTHUBMESSAGE_CONTENT_TYPE_VALUES);
+
+typedef struct IOTHUB_MESSAGE_HANDLE_DATA_TAG* IOTHUB_MESSAGE_HANDLE;
+
+/** @brief diagnostic related data*/
+typedef struct IOTHUB_MESSAGE_DIAGNOSTIC_PROPERTY_DATA_TAG
+{
+    char* diagnosticId;
+    char* diagnosticCreationTimeUtc;
+}IOTHUB_MESSAGE_DIAGNOSTIC_PROPERTY_DATA, *IOTHUB_MESSAGE_DIAGNOSTIC_PROPERTY_DATA_HANDLE;
+
+static const char DIAG_CREATION_TIME_UTC_PROPERTY_NAME[] = "diag_creation_time_utc";
+
+/**
+* @brief   Creates a new IoT hub message from a byte array. The type of the
+*          message will be set to @c IOTHUBMESSAGE_BYTEARRAY.
+*
+* @param   byteArray   The byte array from which the message is to be created.
+* @param   size        The size of the byte array.
+*
+* @return  A valid @c IOTHUB_MESSAGE_HANDLE if the message was successfully
+*          created or @c NULL in case an error occurs.
+*/
+MOCKABLE_FUNCTION(, IOTHUB_MESSAGE_HANDLE, IoTHubMessage_CreateFromByteArray, const unsigned char*, byteArray, size_t, size);
+
+/**
+* @brief   Creates a new IoT hub message from a null terminated string.  The
+*          type of the message will be set to @c IOTHUBMESSAGE_STRING.
+*
+* @param   source  The null terminated string from which the message is to be
+*                  created.
+*
+* @return  A valid @c IOTHUB_MESSAGE_HANDLE if the message was successfully
+*          created or @c NULL in case an error occurs.
+*/
+MOCKABLE_FUNCTION(, IOTHUB_MESSAGE_HANDLE, IoTHubMessage_CreateFromString, const char*, source);
+
+/**
+* @brief   Creates a new IoT hub message with the content identical to that
+*          of the @p iotHubMessageHandle parameter.
+*
+* @param   iotHubMessageHandle Handle to the message that is to be cloned.
+*
+* @return  A valid @c IOTHUB_MESSAGE_HANDLE if the message was successfully
+*          cloned or @c NULL in case an error occurs.
+*/
+MOCKABLE_FUNCTION(, IOTHUB_MESSAGE_HANDLE, IoTHubMessage_Clone, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle);
+
+/**
+* @brief   Fetches a pointer and size for the data associated with the IoT
+*          hub message handle. If the content type of the message is not
+*          @c IOTHUBMESSAGE_BYTEARRAY then the function returns
+*          @c IOTHUB_MESSAGE_INVALID_ARG.
+*
+* @param   iotHubMessageHandle Handle to the message.
+* @param   buffer              Pointer to the memory location where the
+*                              pointer to the buffer will be written.
+* @param   size                The size of the buffer will be written to
+*                              this address.
+*
+* @return  Returns IOTHUB_MESSAGE_OK if the byte array was fetched successfully
+*          or an error code otherwise.
+*/
+MOCKABLE_FUNCTION(, IOTHUB_MESSAGE_RESULT, IoTHubMessage_GetByteArray, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle, const unsigned char**, buffer, size_t*, size);
+
+/**
+* @brief   Returns the null terminated string stored in the message.
+*          If the content type of the message is not @c IOTHUBMESSAGE_STRING
+*          then the function returns @c NULL. No new memory is allocated,
+*          the caller is not responsible for freeing the memory. The memory
+*          is valid until IoTHubMessage_Destroy is called on the message.
+*
+* @param   iotHubMessageHandle Handle to the message.
+*
+* @return  @c NULL if an error occurs or a pointer to the stored null
+*          terminated string otherwise.
+*/
+MOCKABLE_FUNCTION(, const char*, IoTHubMessage_GetString, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle);
+
+/**
+* @brief   Returns the content type of the message given by parameter
+*          @c iotHubMessageHandle.
+*
+* @param   iotHubMessageHandle Handle to the message.
+*
+* @remarks This function retrieves the standardized type of the payload, which indicates if @c iotHubMessageHandle was created using a String or a Byte Array.
+*
+* @return  An @c IOTHUBMESSAGE_CONTENT_TYPE value.
+*/
+MOCKABLE_FUNCTION(, IOTHUBMESSAGE_CONTENT_TYPE, IoTHubMessage_GetContentType, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle);
+
+/**
+* @brief   Sets the content-type of the message payload, as per supported values on RFC 2046.
+*
+* @param   iotHubMessageHandle Handle to the message.
+*
+* @param   contentType String defining the type of the payload (e.g., text/plain).
+*
+* @return  An @c IOTHUB_MESSAGE_RESULT value.
+*/
+MOCKABLE_FUNCTION(, IOTHUB_MESSAGE_RESULT, IoTHubMessage_SetContentTypeSystemProperty, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle, const char*, contentType);
+
+/**
+* @brief   Returns the content-type of the message payload, if defined. No new memory is allocated,
+*          the caller is not responsible for freeing the memory.  The memory
+*          is valid until IoTHubMessage_Destroy is called on the message.
+*
+* @param   iotHubMessageHandle Handle to the message.
+*
+* @return  A string with the content-type value if defined (or NULL otherwise).
+*/
+MOCKABLE_FUNCTION(, const char*, IoTHubMessage_GetContentTypeSystemProperty, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle);
+
+/**
+* @brief   Sets the content-encoding of the message payload, as per supported values on RFC 2616.
+*
+* @param   iotHubMessageHandle Handle to the message.
+*
+* @param   contentEncoding String defining the encoding of the payload (e.g., utf-8).
+*
+* @return  An @c IOTHUB_MESSAGE_RESULT value.
+*/
+MOCKABLE_FUNCTION(, IOTHUB_MESSAGE_RESULT, IoTHubMessage_SetContentEncodingSystemProperty, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle, const char*, contentEncoding);
+
+/**
+* @brief   Returns the content-encoding of the message payload, if defined. No new memory is allocated,
+*          the caller is not responsible for freeing the memory. The memory
+*          is valid until IoTHubMessage_Destroy is called on the message.
+*
+* @param   iotHubMessageHandle Handle to the message.
+*
+* @return  A string with the content-encoding value if defined (or NULL otherwise).
+*/
+MOCKABLE_FUNCTION(, const char*, IoTHubMessage_GetContentEncodingSystemProperty, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle);
+
+/**
+** DEPRECATED: Use IoTHubMessage_SetProperty and IoTHubMessage_GetProperty instead. **
+* @brief   Gets a handle to the message's properties map.
+*          Note that when sending messages via the HTTP transport, the key names in the map must not contain spaces.
+*
+* @param   iotHubMessageHandle Handle to the message.
+*
+* @return  A @c MAP_HANDLE pointing to the properties map for this message.
+*/
+MOCKABLE_FUNCTION(, MAP_HANDLE, IoTHubMessage_Properties, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle);
+
+/**
+* @brief   Sets a property on a Iothub Message.
+*
+* @param   iotHubMessageHandle Handle to the message.
+*
+* @param   key name of the property to set.  Note that when sending messages via the HTTP transport, this value must not contain spaces.
+*
+* @param   value of the property to set.
+*
+* @return  An @c IOTHUB_MESSAGE_RESULT value indicating the result of setting the property.
+*/
+MOCKABLE_FUNCTION(, IOTHUB_MESSAGE_RESULT, IoTHubMessage_SetProperty, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle, const char*, key, const char*, value);
+
+/**
+* @brief   Gets a IotHub Message's properties item. No new memory is allocated,
+*          the caller is not responsible for freeing the memory. The memory
+*          is valid until IoTHubMessage_Destroy is called on the message.
+*
+* @param   iotHubMessageHandle Handle to the message.
+*
+* @param   key name of the property to retrieve.
+*
+* @return  A string with the property's value, or NULL if it does not exist in the properties list.
+*/
+MOCKABLE_FUNCTION(, const char*, IoTHubMessage_GetProperty, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle, const char*, key);
+
+/**
+* @brief   Gets the MessageId from the IOTHUB_MESSAGE_HANDLE. No new memory is allocated,
+*          the caller is not responsible for freeing the memory. The memory
+*          is valid until IoTHubMessage_Destroy is called on the message.
+*
+* @param   iotHubMessageHandle Handle to the message.
+*
+* @return  A const char* pointing to the Message Id.
+*/
+MOCKABLE_FUNCTION(, const char*, IoTHubMessage_GetMessageId, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle);
+
+/**
+* @brief   Sets the MessageId for the IOTHUB_MESSAGE_HANDLE.
+*
+* @param   iotHubMessageHandle Handle to the message.
+* @param   messageId Pointer to the memory location of the messageId
+*
+* @return  Returns IOTHUB_MESSAGE_OK if the messageId was set successfully
+*          or an error code otherwise.
+*/
+MOCKABLE_FUNCTION(, IOTHUB_MESSAGE_RESULT, IoTHubMessage_SetMessageId, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle, const char*, messageId);
+
+/**
+* @brief   Gets the CorrelationId from the IOTHUB_MESSAGE_HANDLE. No new memory is allocated,
+*          the caller is not responsible for freeing the memory. The memory
+*          is valid until IoTHubMessage_Destroy is called on the message.
+*
+* @param   iotHubMessageHandle Handle to the message.
+*
+* @return  A const char* pointing to the Correlation Id.
+*/
+MOCKABLE_FUNCTION(, const char*, IoTHubMessage_GetCorrelationId, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle);
+
+/**
+* @brief   Sets the CorrelationId for the IOTHUB_MESSAGE_HANDLE.
+*
+* @param   iotHubMessageHandle Handle to the message.
+* @param   correlationId Pointer to the memory location of the messageId
+*
+* @return  Returns IOTHUB_MESSAGE_OK if the messageId was set successfully
+*          or an error code otherwise.
+*/
+MOCKABLE_FUNCTION(, IOTHUB_MESSAGE_RESULT, IoTHubMessage_SetCorrelationId, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle, const char*, correlationId);
+
+/**
+* @brief   Gets the DiagnosticData from the IOTHUB_MESSAGE_HANDLE. CAUTION: SDK user should not call it directly, it is for internal use only.
+*
+* @param   iotHubMessageHandle Handle to the message.
+*
+* @return  A const IOTHUB_MESSAGE_DIAGNOSTIC_PROPERTY_DATA* pointing to the diagnostic property data.
+*/
+MOCKABLE_FUNCTION(, const IOTHUB_MESSAGE_DIAGNOSTIC_PROPERTY_DATA*, IoTHubMessage_GetDiagnosticPropertyData, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle);
+
+/**
+* @brief   Sets the DiagnosticData for the IOTHUB_MESSAGE_HANDLE. CAUTION: SDK user should not call it directly, it is for internal use only.
+*
+* @param   iotHubMessageHandle Handle to the message.
+* @param   diagnosticData Pointer to the memory location of the diagnosticData
+*
+* @return  Returns IOTHUB_MESSAGE_OK if the DiagnosticData was set successfully
+*          or an error code otherwise.
+*/
+MOCKABLE_FUNCTION(, IOTHUB_MESSAGE_RESULT, IoTHubMessage_SetDiagnosticPropertyData, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle, const IOTHUB_MESSAGE_DIAGNOSTIC_PROPERTY_DATA*, diagnosticData);
+
+/**
+* @brief   Gets the output name from the IOTHUB_MESSAGE_HANDLE. No new memory is allocated,
+*          the caller is not responsible for freeing the memory. The memory
+*          is valid until IoTHubMessage_Destroy is called on the message.
+*
+* @param   iotHubMessageHandle Handle to the message.
+*
+* @return  A const char* pointing to the Output Id.
+*/
+MOCKABLE_FUNCTION(, const char*, IoTHubMessage_GetOutputName, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle);
+
+
+/**
+* @brief   Sets output for named queues. CAUTION: SDK user should not call it directly, it is for internal use only.
+*
+* @param   iotHubMessageHandle Handle to the message.
+* @param   outputName Pointer to the queue to output message to
+*
+* @return  Returns IOTHUB_MESSAGE_OK if the DiagnosticData was set successfully
+*          or an error code otherwise.
+*/
+MOCKABLE_FUNCTION(, IOTHUB_MESSAGE_RESULT, IoTHubMessage_SetOutputName, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle, const char*, outputName);
+
+
+/**
+* @brief   Gets the input name from the IOTHUB_MESSAGE_HANDLE. No new memory is allocated,
+*          the caller is not responsible for freeing the memory. The memory
+*          is valid until IoTHubMessage_Destroy is called on the message.
+*
+* @param   iotHubMessageHandle Handle to the message.
+*
+* @return  A const char* pointing to the Input Id.
+*/
+MOCKABLE_FUNCTION(, const char*, IoTHubMessage_GetInputName, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle);
+
+/**
+* @brief   Sets input for named queues. CAUTION: SDK user should not call it directly, it is for internal use only.
+*
+* @param   iotHubMessageHandle Handle to the message.
+* @param   inputName Pointer to the queue to input message to
+*
+* @return  Returns IOTHUB_MESSAGE_OK if the DiagnosticData was set successfully
+*          or an error code otherwise.
+*/
+MOCKABLE_FUNCTION(, IOTHUB_MESSAGE_RESULT, IoTHubMessage_SetInputName, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle, const char*, inputName);
+
+/**
+* @brief   Gets the module name from the IOTHUB_MESSAGE_HANDLE. No new memory is allocated,
+*          the caller is not responsible for freeing the memory. The memory
+*          is valid until IoTHubMessage_Destroy is called on the message.
+*
+* @param   iotHubMessageHandle Handle to the message.
+*
+* @return  A const char* pointing to the connection module Id.
+*/
+MOCKABLE_FUNCTION(, const char*, IoTHubMessage_GetConnectionModuleId, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle);
+
+/**
+* @brief   Sets connection module ID. CAUTION: SDK user should not call it directly, it is for internal use only.
+*
+* @param   iotHubMessageHandle Handle to the message.
+* @param   connectionModuleId Pointer to the module ID of connector
+*
+* @return  Returns IOTHUB_MESSAGE_OK if the DiagnosticData was set successfully
+*          or an error code otherwise.
+*/
+MOCKABLE_FUNCTION(, IOTHUB_MESSAGE_RESULT, IoTHubMessage_SetConnectionModuleId, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle, const char*, connectionModuleId);
+
+
+/**
+* @brief   Gets the connection device ID from the IOTHUB_MESSAGE_HANDLE. No new memory is allocated,
+*          the caller is not responsible for freeing the memory. The memory
+*          is valid until IoTHubMessage_Destroy is called on the message.
+*
+* @param   iotHubMessageHandle Handle to the message.
+*
+* @return  A const char* pointing to the connection device Id.
+*/
+MOCKABLE_FUNCTION(, const char*, IoTHubMessage_GetConnectionDeviceId, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle);
+
+/**
+* @brief   Sets connection device Id. CAUTION: SDK user should not call it directly, it is for internal use only.
+*
+* @param   iotHubMessageHandle Handle to the message.
+* @param   connectionDeviceId Pointer to the device ID of connector
+*
+* @return  Returns IOTHUB_MESSAGE_OK if the DiagnosticData was set successfully
+*          or an error code otherwise.
+*/
+MOCKABLE_FUNCTION(, IOTHUB_MESSAGE_RESULT, IoTHubMessage_SetConnectionDeviceId, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle, const char*, connectionDeviceId);
+
+
+/**
+* @brief   Marks a IoTHub message as a security message. CAUTION: Security messages are special messages not easily accessable by the user.
+*
+* @param   iotHubMessageHandle Handle to the message.
+*
+* @return  Returns IOTHUB_MESSAGE_OK if the Security Message was set successfully
+*          or an error code otherwise.
+*/
+MOCKABLE_FUNCTION(, IOTHUB_MESSAGE_RESULT, IoTHubMessage_SetAsSecurityMessage, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle);
+
+/**
+* @brief   returns if this message is a IoTHub security message or not
+*
+* @param   iotHubMessageHandle Handle to the message.
+*
+* @return  Returns true if the Message is a security message false otherwise.
+*/
+MOCKABLE_FUNCTION(, bool, IoTHubMessage_IsSecurityMessage, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle);
+
+/**
+* @brief   Frees all resources associated with the given message handle.
+*
+* @param   iotHubMessageHandle Handle to the message.
+*/
+MOCKABLE_FUNCTION(, void, IoTHubMessage_Destroy, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IOTHUB_MESSAGE_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_transport_ll.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_transport_ll.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothub_transport_ll.h	(revision 453)
@@ -0,0 +1,41 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef IOTHUB_TRANSPORT_LL_H
+#define IOTHUB_TRANSPORT_LL_H
+
+#ifdef __cplusplus
+#include <cstddef>
+#include <cstdint>
+extern "C"
+{
+#else
+#include <stddef.h>
+#include <stdint.h>
+#endif
+
+#include "umock_c/umock_c_prod.h"
+
+typedef void* TRANSPORT_LL_HANDLE;
+typedef void* IOTHUB_DEVICE_HANDLE;
+
+struct TRANSPORT_HANDLE_DATA_TAG;
+typedef struct TRANSPORT_HANDLE_DATA_TAG* TRANSPORT_HANDLE;
+
+typedef void* METHOD_HANDLE;
+
+struct TRANSPORT_PROVIDER_TAG;
+typedef struct TRANSPORT_PROVIDER_TAG TRANSPORT_PROVIDER;
+
+typedef const TRANSPORT_PROVIDER*(*IOTHUB_CLIENT_TRANSPORT_PROVIDER)(void);
+
+MOCKABLE_FUNCTION(, TRANSPORT_HANDLE, IoTHubTransport_Create, IOTHUB_CLIENT_TRANSPORT_PROVIDER, protocol, const char*, iotHubName, const char*, iotHubSuffix);
+MOCKABLE_FUNCTION(, void, IoTHubTransport_Destroy, TRANSPORT_HANDLE, transportHandle);
+MOCKABLE_FUNCTION(, TRANSPORT_LL_HANDLE, IoTHubTransport_GetLLTransport, TRANSPORT_HANDLE, transportHandle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IOTHUB_TRANSPORT_LL_H */
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothubtransporthttp.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothubtransporthttp.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothubtransporthttp.h	(revision 453)
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef IOTHUBTRANSPORTHTTP_H
+#define IOTHUBTRANSPORTHTTP_H
+
+#include "iothub_transport_ll.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+	extern const TRANSPORT_PROVIDER* HTTP_Protocol(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*IOTHUBTRANSPORTHTTP_H*/
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothubtransportmqtt.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothubtransportmqtt.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothubtransportmqtt.h	(revision 453)
@@ -0,0 +1,19 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef IOTHUBTRANSPORTMQTT_H
+#define IOTHUBTRANSPORTMQTT_H
+
+#include "iothub_transport_ll.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+    extern const TRANSPORT_PROVIDER* MQTT_Protocol(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*IOTHUBTRANSPORTMQTT_H*/
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothubtransportmqtt_websockets.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothubtransportmqtt_websockets.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/inc/iothubtransportmqtt_websockets.h	(revision 453)
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef IOTHUBTRANSPORTMQTT_WEBSOCKETS_H
+#define IOTHUBTRANSPORTMQTT_WEBSOCKETS_H
+
+#include "iothub_transport_ll.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    extern const TRANSPORT_PROVIDER* MQTT_WebSocket_Protocol(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*IOTHUBTRANSPORTMQTT_WEBSOCKETS_H*/
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/blob.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/blob.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/blob.c	(revision 453)
@@ -0,0 +1,387 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "azure_c_shared_utility/gballoc.h"
+#include "internal/blob.h"
+#include "internal/iothub_client_ll_uploadtoblob.h"
+
+#include "azure_c_shared_utility/httpapiex.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/azure_base64.h"
+#include "azure_c_shared_utility/shared_util_options.h"
+
+BLOB_RESULT Blob_UploadBlock(
+        HTTPAPIEX_HANDLE httpApiExHandle,
+        const char* relativePath,
+        BUFFER_HANDLE requestContent,
+        unsigned int blockID,
+        STRING_HANDLE blockIDList,
+        unsigned int* httpStatus,
+        BUFFER_HANDLE httpResponse)
+{
+    BLOB_RESULT result;
+
+    if (requestContent == NULL ||
+        blockIDList == NULL ||
+        relativePath == NULL ||
+        httpApiExHandle == NULL ||
+        httpStatus == NULL ||
+        httpResponse == NULL)
+    {
+        LogError("invalid argument detected requestContent=%p blockIDList=%p relativePath=%p httpApiExHandle=%p httpStatus=%p httpResponse=%p", requestContent, blockIDList, relativePath, httpApiExHandle, httpStatus, httpResponse);
+        result = BLOB_ERROR;
+    }
+    else if (blockID > 49999) /*outside the expected range of 000000... 049999*/
+    {
+        LogError("block ID too large");
+        result = BLOB_ERROR;
+    }
+    else
+    {
+        char temp[7]; /*this will contain 000000... 049999*/
+        if (sprintf(temp, "%6u", (unsigned int)blockID) != 6) /*produces 000000... 049999*/
+        {
+            /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
+            LogError("failed to sprintf");
+            result = BLOB_ERROR;
+        }
+        else
+        {
+            STRING_HANDLE blockIdString = Azure_Base64_Encode_Bytes((const unsigned char*)temp, 6);
+            if (blockIdString == NULL)
+            {
+                /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
+                LogError("unable to Azure_Base64_Encode_Bytes");
+                result = BLOB_ERROR;
+            }
+            else
+            {
+                /*add the blockId base64 encoded to the XML*/
+                if (!(
+                    (STRING_concat(blockIDList, "<Latest>") == 0) &&
+                    (STRING_concat_with_STRING(blockIDList, blockIdString) == 0) &&
+                    (STRING_concat(blockIDList, "</Latest>") == 0)
+                    ))
+                {
+                    /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
+                    LogError("unable to STRING_concat");
+                    result = BLOB_ERROR;
+                }
+                else
+                {
+                    /*Codes_SRS_BLOB_02_022: [ Blob_UploadMultipleBlocksFromSasUri shall construct a new relativePath from following string: base relativePath + "&comp=block&blockid=BASE64 encoded string of blockId" ]*/
+                    STRING_HANDLE newRelativePath = STRING_construct(relativePath);
+                    if (newRelativePath == NULL)
+                    {
+                        /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
+                        LogError("unable to STRING_construct");
+                        result = BLOB_ERROR;
+                    }
+                    else
+                    {
+                        if (!(
+                            (STRING_concat(newRelativePath, "&comp=block&blockid=") == 0) &&
+                            (STRING_concat_with_STRING(newRelativePath, blockIdString) == 0)
+                            ))
+                        {
+                            /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
+                            LogError("unable to STRING concatenate");
+                            result = BLOB_ERROR;
+                        }
+                        else
+                        {
+                            /*Codes_SRS_BLOB_02_024: [ Blob_UploadMultipleBlocksFromSasUri shall call HTTPAPIEX_ExecuteRequest with a PUT operation, passing httpStatus and httpResponse. ]*/
+                            if (HTTPAPIEX_ExecuteRequest(
+                                httpApiExHandle,
+                                HTTPAPI_REQUEST_PUT,
+                                STRING_c_str(newRelativePath),
+                                NULL,
+                                requestContent,
+                                httpStatus,
+                                NULL,
+                                httpResponse) != HTTPAPIEX_OK
+                                )
+                            {
+                                /*Codes_SRS_BLOB_02_025: [ If HTTPAPIEX_ExecuteRequest fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_HTTP_ERROR. ]*/
+                                LogError("unable to HTTPAPIEX_ExecuteRequest");
+                                result = BLOB_HTTP_ERROR;
+                            }
+                            else if (*httpStatus >= 300)
+                            {
+                                /*Codes_SRS_BLOB_02_026: [ Otherwise, if HTTP response code is >=300 then Blob_UploadMultipleBlocksFromSasUri shall succeed and return BLOB_OK. ]*/
+                                LogError("HTTP status from storage does not indicate success (%d)", (int)*httpStatus);
+                                result = BLOB_OK;
+                            }
+                            else
+                            {
+                                /*Codes_SRS_BLOB_02_027: [ Otherwise Blob_UploadMultipleBlocksFromSasUri shall continue execution. ]*/
+                                result = BLOB_OK;
+                            }
+                        }
+                        STRING_delete(newRelativePath);
+                    }
+                }
+                STRING_delete(blockIdString);
+            }
+        }
+    }
+    return result;
+}
+
+BLOB_RESULT Blob_UploadMultipleBlocksFromSasUri(const char* SASURI, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx, void* context, unsigned int* httpStatus, BUFFER_HANDLE httpResponse, const char* certificates, HTTP_PROXY_OPTIONS *proxyOptions)
+{
+    BLOB_RESULT result;
+    /*Codes_SRS_BLOB_02_001: [ If SASURI is NULL then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/
+    if (SASURI == NULL)
+    {
+        LogError("parameter SASURI is NULL");
+        result = BLOB_INVALID_ARG;
+    }
+    else
+    {
+        /*Codes_SRS_BLOB_02_002: [ If getDataCallbackEx is NULL then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/
+        if (getDataCallbackEx == NULL)
+        {
+            LogError("IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx is NULL");
+            result = BLOB_INVALID_ARG;
+        }
+        /*the below define avoid a "condition always false" on some compilers*/
+        else
+        {
+            /*Codes_SRS_BLOB_02_017: [ Blob_UploadMultipleBlocksFromSasUri shall copy from SASURI the hostname to a new const char* ]*/
+            /*to find the hostname, the following logic is applied:*/
+            /*the hostname starts at the first character after "://"*/
+            /*the hostname ends at the first character before the next "/" after "://"*/
+            const char* hostnameBegin = strstr(SASURI, "://");
+            if (hostnameBegin == NULL)
+            {
+                /*Codes_SRS_BLOB_02_005: [ If the hostname cannot be determined, then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/
+                LogError("hostname cannot be determined");
+                result = BLOB_INVALID_ARG;
+            }
+            else
+            {
+                hostnameBegin += 3; /*have to skip 3 characters which are "://"*/
+                const char* hostnameEnd = strchr(hostnameBegin, '/');
+                if (hostnameEnd == NULL)
+                {
+                    /*Codes_SRS_BLOB_02_005: [ If the hostname cannot be determined, then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/
+                    LogError("hostname cannot be determined");
+                    result = BLOB_INVALID_ARG;
+                }
+                else
+                {
+                    size_t hostnameSize = hostnameEnd - hostnameBegin;
+                    char* hostname = (char*)malloc(hostnameSize + 1); /*+1 because of '\0' at the end*/
+                    if (hostname == NULL)
+                    {
+                        /*Codes_SRS_BLOB_02_016: [ If the hostname copy cannot be made then then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
+                        LogError("oom - out of memory");
+                        result = BLOB_ERROR;
+                    }
+                    else
+                    {
+                        HTTPAPIEX_HANDLE httpApiExHandle;
+                        (void)memcpy(hostname, hostnameBegin, hostnameSize);
+                        hostname[hostnameSize] = '\0';
+
+                        /*Codes_SRS_BLOB_02_018: [ Blob_UploadMultipleBlocksFromSasUri shall create a new HTTPAPI_EX_HANDLE by calling HTTPAPIEX_Create passing the hostname. ]*/
+                        httpApiExHandle = HTTPAPIEX_Create(hostname);
+                        if (httpApiExHandle == NULL)
+                        {
+                            /*Codes_SRS_BLOB_02_007: [ If HTTPAPIEX_Create fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR. ]*/
+                            LogError("unable to create a HTTPAPIEX_HANDLE");
+                            result = BLOB_ERROR;
+                        }
+                        else
+                        {
+                            if ((certificates != NULL)&& (HTTPAPIEX_SetOption(httpApiExHandle, "TrustedCerts", certificates) == HTTPAPIEX_ERROR))
+                            {
+                                LogError("failure in setting trusted certificates");
+                                result = BLOB_ERROR;
+                            }
+                            else if ((proxyOptions != NULL && proxyOptions->host_address != NULL) && HTTPAPIEX_SetOption(httpApiExHandle, OPTION_HTTP_PROXY, proxyOptions) == HTTPAPIEX_ERROR)
+                            {
+                                LogError("failure in setting proxy options");
+                                result = BLOB_ERROR;
+                            }
+                            else
+                            {
+                                /*Codes_SRS_BLOB_02_019: [ Blob_UploadMultipleBlocksFromSasUri shall compute the base relative path of the request from the SASURI parameter. ]*/
+                                const char* relativePath = hostnameEnd; /*this is where the relative path begins in the SasUri*/
+
+                                /*Codes_SRS_BLOB_02_028: [ Blob_UploadMultipleBlocksFromSasUri shall construct an XML string with the following content: ]*/
+                                STRING_HANDLE blockIDList = STRING_construct("<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<BlockList>"); /*the XML "build as we go"*/
+                                if (blockIDList == NULL)
+                                {
+                                    /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
+                                    LogError("failed to STRING_construct");
+                                    result = BLOB_HTTP_ERROR;
+                                }
+                                else
+                                {
+                                    /*Codes_SRS_BLOB_02_021: [ For every block returned by `getDataCallbackEx` the following operations shall happen: ]*/
+                                    unsigned int blockID = 0; /* incremented for each new block */
+                                    unsigned int isError = 0; /* set to 1 if a block upload fails or if getDataCallbackEx returns incorrect blocks to upload */
+                                    unsigned int uploadOneMoreBlock = 1; /* set to 1 while getDataCallbackEx returns correct blocks to upload */
+                                    unsigned char const * source; /* data set by getDataCallbackEx */
+                                    size_t size; /* source size set by getDataCallbackEx */
+                                    IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT getDataReturnValue;
+
+                                    do
+                                    {
+                                        getDataReturnValue = getDataCallbackEx(FILE_UPLOAD_OK, &source, &size, context);
+                                        if (getDataReturnValue == IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_ABORT)
+                                        {
+                                            /*Codes_SRS_BLOB_99_004: [ If `getDataCallbackEx` returns `IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT_ABORT`, then `Blob_UploadMultipleBlocksFromSasUri` shall exit the loop and return `BLOB_ABORTED`. ]*/
+                                            LogInfo("Upload to blob has been aborted by the user");
+                                            uploadOneMoreBlock = 0;
+                                            result = BLOB_ABORTED;
+                                        }
+                                        else if (source == NULL || size == 0)
+                                        {
+                                            /*Codes_SRS_BLOB_99_002: [ If the size of the block returned by `getDataCallbackEx` is 0 or if the data is NULL, then `Blob_UploadMultipleBlocksFromSasUri` shall exit the loop. ]*/
+                                            uploadOneMoreBlock = 0;
+                                            result = BLOB_OK;
+                                        }
+                                        else
+                                        {
+                                            if (size > BLOCK_SIZE)
+                                            {
+                                                /*Codes_SRS_BLOB_99_001: [ If the size of the block returned by `getDataCallbackEx` is bigger than 4MB, then `Blob_UploadMultipleBlocksFromSasUri` shall fail and return `BLOB_INVALID_ARG`. ]*/
+                                                LogError("tried to upload block of size %lu, max allowed size is %d", (unsigned long)size, BLOCK_SIZE);
+                                                result = BLOB_INVALID_ARG;
+                                                isError = 1;
+                                            }
+                                            else if (blockID >= MAX_BLOCK_COUNT)
+                                            {
+                                                /*Codes_SRS_BLOB_99_003: [ If `getDataCallbackEx` returns more than 50000 blocks, then `Blob_UploadMultipleBlocksFromSasUri` shall fail and return `BLOB_INVALID_ARG`. ]*/
+                                                LogError("unable to upload more than %lu blocks in one blob", (unsigned long)MAX_BLOCK_COUNT);
+                                                result = BLOB_INVALID_ARG;
+                                                isError = 1;
+                                            }
+                                            else
+                                            {
+                                                /*Codes_SRS_BLOB_02_023: [ Blob_UploadMultipleBlocksFromSasUri shall create a BUFFER_HANDLE from source and size parameters. ]*/
+                                                BUFFER_HANDLE requestContent = BUFFER_create(source, size);
+                                                if (requestContent == NULL)
+                                                {
+                                                    /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
+                                                    LogError("unable to BUFFER_create");
+                                                    result = BLOB_ERROR;
+                                                    isError = 1;
+                                                }
+                                                else
+                                                {
+                                                    result = Blob_UploadBlock(
+                                                            httpApiExHandle,
+                                                            relativePath,
+                                                            requestContent,
+                                                            blockID,
+                                                            blockIDList,
+                                                            httpStatus,
+                                                            httpResponse);
+
+                                                    BUFFER_delete(requestContent);
+                                                }
+
+                                                /*Codes_SRS_BLOB_02_026: [ Otherwise, if HTTP response code is >=300 then Blob_UploadMultipleBlocksFromSasUri shall succeed and return BLOB_OK. ]*/
+                                                if (result != BLOB_OK || *httpStatus >= 300)
+                                                {
+                                                    LogError("unable to Blob_UploadBlock. Returned value=%d, httpStatus=%u", result, (unsigned int)*httpStatus);
+                                                    isError = 1;
+                                                }
+                                            }
+                                            blockID++;
+                                        }
+                                    }
+                                    while(uploadOneMoreBlock && !isError);
+
+                                    if (isError || result != BLOB_OK)
+                                    {
+                                        /*do nothing, it will be reported "as is"*/
+                                    }
+                                    else
+                                    {
+                                        /*complete the XML*/
+                                        if (STRING_concat(blockIDList, "</BlockList>") != 0)
+                                        {
+                                            /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
+                                            LogError("failed to STRING_concat");
+                                            result = BLOB_ERROR;
+                                        }
+                                        else
+                                        {
+                                            /*Codes_SRS_BLOB_02_029: [Blob_UploadMultipleBlocksFromSasUri shall construct a new relativePath from following string : base relativePath + "&comp=blocklist"]*/
+                                            STRING_HANDLE newRelativePath = STRING_construct(relativePath);
+                                            if (newRelativePath == NULL)
+                                            {
+                                                /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
+                                                LogError("failed to STRING_construct");
+                                                result = BLOB_ERROR;
+                                            }
+                                            else
+                                            {
+                                                if (STRING_concat(newRelativePath, "&comp=blocklist") != 0)
+                                                {
+                                                    /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
+                                                    LogError("failed to STRING_concat");
+                                                    result = BLOB_ERROR;
+                                                }
+                                                else
+                                                {
+                                                    /*Codes_SRS_BLOB_02_030: [ Blob_UploadMultipleBlocksFromSasUri shall call HTTPAPIEX_ExecuteRequest with a PUT operation, passing the new relativePath, httpStatus and httpResponse and the XML string as content. ]*/
+                                                    const char* s = STRING_c_str(blockIDList);
+                                                    BUFFER_HANDLE blockIDListAsBuffer = BUFFER_create((const unsigned char*)s, strlen(s));
+                                                    if (blockIDListAsBuffer == NULL)
+                                                    {
+                                                        /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
+                                                        LogError("failed to BUFFER_create");
+                                                        result = BLOB_ERROR;
+                                                    }
+                                                    else
+                                                    {
+                                                        if (HTTPAPIEX_ExecuteRequest(
+                                                            httpApiExHandle,
+                                                            HTTPAPI_REQUEST_PUT,
+                                                            STRING_c_str(newRelativePath),
+                                                            NULL,
+                                                            blockIDListAsBuffer,
+                                                            httpStatus,
+                                                            NULL,
+                                                            httpResponse
+                                                        ) != HTTPAPIEX_OK)
+                                                        {
+                                                            /*Codes_SRS_BLOB_02_031: [ If HTTPAPIEX_ExecuteRequest fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_HTTP_ERROR. ]*/
+                                                            LogError("unable to HTTPAPIEX_ExecuteRequest");
+                                                            result = BLOB_HTTP_ERROR;
+                                                        }
+                                                        else
+                                                        {
+                                                            /*Codes_SRS_BLOB_02_032: [ Otherwise, Blob_UploadMultipleBlocksFromSasUri shall succeed and return BLOB_OK. ]*/
+                                                            result = BLOB_OK;
+                                                        }
+                                                        BUFFER_delete(blockIDListAsBuffer);
+                                                    }
+                                                }
+                                                STRING_delete(newRelativePath);
+                                            }
+                                        }
+                                    }
+                                    STRING_delete(blockIDList);
+                                }
+
+                            }
+                            HTTPAPIEX_Destroy(httpApiExHandle);
+                        }
+                        free(hostname);
+                    }
+                }
+            }
+        }
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub.c	(revision 453)
@@ -0,0 +1,29 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+
+#include "azure_c_shared_utility/platform.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_macro_utils/macro_utils.h"
+#include "iothub.h"
+
+int IoTHub_Init(void)
+{
+    int result;
+    if (platform_init() != 0)
+    {
+        LogError("Platform initialization failed");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        result = 0;
+    }
+    return result;
+}
+
+void IoTHub_Deinit(void)
+{
+    platform_deinit();
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_client.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_client.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_client.c	(revision 453)
@@ -0,0 +1,119 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "umock_c/umock_c_prod.h"
+#include "azure_c_shared_utility/gballoc.h"
+
+#include "iothub_client_core.h"
+#include "iothub_client.h"
+
+IOTHUB_CLIENT_HANDLE IoTHubClient_CreateFromConnectionString(const char* connectionString, IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol)
+{
+    return (IOTHUB_CLIENT_HANDLE)IoTHubClientCore_CreateFromConnectionString(connectionString, protocol);
+}
+
+IOTHUB_CLIENT_HANDLE IoTHubClient_Create(const IOTHUB_CLIENT_CONFIG* config)
+{
+    return (IOTHUB_CLIENT_HANDLE)IoTHubClientCore_Create(config);
+}
+
+IOTHUB_CLIENT_HANDLE IoTHubClient_CreateWithTransport(TRANSPORT_HANDLE transportHandle, const IOTHUB_CLIENT_CONFIG* config)
+{
+    return (IOTHUB_CLIENT_HANDLE)IoTHubClientCore_CreateWithTransport(transportHandle, config);
+}
+
+IOTHUB_CLIENT_HANDLE IoTHubClient_CreateFromDeviceAuth(const char* iothub_uri, const char* device_id, IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol)
+{
+    return (IOTHUB_CLIENT_HANDLE)IoTHubClientCore_CreateFromDeviceAuth(iothub_uri, device_id, protocol);
+}
+
+void IoTHubClient_Destroy(IOTHUB_CLIENT_HANDLE iotHubClientHandle)
+{
+    IoTHubClientCore_Destroy((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_SendEventAsync(IOTHUB_CLIENT_HANDLE iotHubClientHandle, IOTHUB_MESSAGE_HANDLE eventMessageHandle, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK eventConfirmationCallback, void* userContextCallback)
+{
+    return IoTHubClientCore_SendEventAsync((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, eventMessageHandle, eventConfirmationCallback, userContextCallback);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_GetSendStatus(IOTHUB_CLIENT_HANDLE iotHubClientHandle, IOTHUB_CLIENT_STATUS *iotHubClientStatus)
+{
+    return IoTHubClientCore_GetSendStatus((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, iotHubClientStatus);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_SetMessageCallback(IOTHUB_CLIENT_HANDLE iotHubClientHandle, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC messageCallback, void* userContextCallback)
+{
+    return IoTHubClientCore_SetMessageCallback((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, messageCallback, userContextCallback);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_SetConnectionStatusCallback(IOTHUB_CLIENT_HANDLE iotHubClientHandle, IOTHUB_CLIENT_CONNECTION_STATUS_CALLBACK connectionStatusCallback, void * userContextCallback)
+{
+    return IoTHubClientCore_SetConnectionStatusCallback((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, connectionStatusCallback, userContextCallback);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_SetRetryPolicy(IOTHUB_CLIENT_HANDLE iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY retryPolicy, size_t retryTimeoutLimitInSeconds)
+{
+    return IoTHubClientCore_SetRetryPolicy((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, retryPolicy, retryTimeoutLimitInSeconds);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_GetRetryPolicy(IOTHUB_CLIENT_HANDLE iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY* retryPolicy, size_t* retryTimeoutLimitInSeconds)
+{
+    return IoTHubClientCore_GetRetryPolicy((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, retryPolicy, retryTimeoutLimitInSeconds);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_GetLastMessageReceiveTime(IOTHUB_CLIENT_HANDLE iotHubClientHandle, time_t* lastMessageReceiveTime)
+{
+    return IoTHubClientCore_GetLastMessageReceiveTime((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, lastMessageReceiveTime);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_SetOption(IOTHUB_CLIENT_HANDLE iotHubClientHandle, const char* optionName, const void* value)
+{
+    return IoTHubClientCore_SetOption((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, optionName, value);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_SetDeviceTwinCallback(IOTHUB_CLIENT_HANDLE iotHubClientHandle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK deviceTwinCallback, void* userContextCallback)
+{
+    return IoTHubClientCore_SetDeviceTwinCallback((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, deviceTwinCallback, userContextCallback);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_SendReportedState(IOTHUB_CLIENT_HANDLE iotHubClientHandle, const unsigned char* reportedState, size_t size, IOTHUB_CLIENT_REPORTED_STATE_CALLBACK reportedStateCallback, void* userContextCallback)
+{
+    return IoTHubClientCore_SendReportedState((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, reportedState, size, reportedStateCallback, userContextCallback);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_SetDeviceMethodCallback(IOTHUB_CLIENT_HANDLE iotHubClientHandle, IOTHUB_CLIENT_DEVICE_METHOD_CALLBACK_ASYNC deviceMethodCallback, void* userContextCallback)
+{
+    return IoTHubClientCore_SetDeviceMethodCallback((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, deviceMethodCallback, userContextCallback);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_SetDeviceMethodCallback_Ex(IOTHUB_CLIENT_HANDLE iotHubClientHandle, IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK inboundDeviceMethodCallback, void* userContextCallback)
+{
+    return IoTHubClientCore_SetDeviceMethodCallback_Ex((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, inboundDeviceMethodCallback, userContextCallback);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_DeviceMethodResponse(IOTHUB_CLIENT_HANDLE iotHubClientHandle, METHOD_HANDLE methodId, const unsigned char* response, size_t respSize, int statusCode)
+{
+    return IoTHubClientCore_DeviceMethodResponse((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, methodId, response, respSize, statusCode);
+}
+
+#ifndef DONT_USE_UPLOADTOBLOB
+
+IOTHUB_CLIENT_RESULT IoTHubClient_UploadToBlobAsync(IOTHUB_CLIENT_HANDLE iotHubClientHandle, const char* destinationFileName, const unsigned char* source, size_t size, IOTHUB_CLIENT_FILE_UPLOAD_CALLBACK iotHubClientFileUploadCallback, void* context)
+{
+    return IoTHubClientCore_UploadToBlobAsync((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, destinationFileName, source, size, iotHubClientFileUploadCallback, context);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_UploadMultipleBlocksToBlobAsync(IOTHUB_CLIENT_HANDLE iotHubClientHandle, const char* destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK getDataCallback, void* context)
+{
+    return IoTHubClientCore_UploadMultipleBlocksToBlobAsync((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, destinationFileName, getDataCallback, NULL, context);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_UploadMultipleBlocksToBlobAsyncEx(IOTHUB_CLIENT_HANDLE iotHubClientHandle, const char* destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx, void* context)
+{
+    return IoTHubClientCore_UploadMultipleBlocksToBlobAsync((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, destinationFileName, NULL, getDataCallbackEx, context);
+}
+
+#endif /*DONT_USE_UPLOADTOBLOB*/
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_client_authorization.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_client_authorization.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_client_authorization.c	(revision 453)
@@ -0,0 +1,728 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_macro_utils/macro_utils.h"
+#include "umock_c/umock_c_prod.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/agenttime.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/strings.h"
+#include "azure_c_shared_utility/sastoken.h"
+#include "azure_c_shared_utility/shared_util_options.h"
+#include "azure_c_shared_utility/azure_base64.h"
+#include "azure_c_shared_utility/buffer_.h"
+
+#ifdef USE_PROV_MODULE
+#include "azure_prov_client/internal/iothub_auth_client.h"
+#endif
+
+#include "internal/iothub_client_authorization.h"
+
+#define DEFAULT_SAS_TOKEN_EXPIRY_TIME_SECS          3600
+#define INDEFINITE_TIME                             ((time_t)(-1))
+#define MIN_SAS_EXPIRY_TIME                         5  // 5 seconds
+
+typedef struct IOTHUB_AUTHORIZATION_DATA_TAG
+{
+    char* device_sas_token;
+    char* device_key;
+    char* device_id;
+    char* module_id;
+    size_t token_expiry_time_sec;
+    IOTHUB_CREDENTIAL_TYPE cred_type;
+#ifdef USE_PROV_MODULE
+    IOTHUB_SECURITY_HANDLE device_auth_handle;
+#endif
+} IOTHUB_AUTHORIZATION_DATA;
+
+static int get_seconds_since_epoch(size_t* seconds)
+{
+    int result;
+    time_t current_time;
+    if ((current_time = get_time(NULL)) == INDEFINITE_TIME)
+    {
+        LogError("Failed getting the current local time (get_time() failed)");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        *seconds = (size_t)get_difftime(current_time, (time_t)0);
+        result = 0;
+    }
+    return result;
+}
+
+static IOTHUB_AUTHORIZATION_DATA* initialize_auth_client(const char* device_id, const char* module_id)
+{
+    IOTHUB_AUTHORIZATION_DATA* result;
+
+    /* Codes_SRS_IoTHub_Authorization_07_002: [IoTHubClient_Auth_Create shall allocate a IOTHUB_AUTHORIZATION_HANDLE that is needed for subsequent calls. ] */
+    result = (IOTHUB_AUTHORIZATION_DATA*)malloc(sizeof(IOTHUB_AUTHORIZATION_DATA) );
+    if (result == NULL)
+    {
+        /* Codes_SRS_IoTHub_Authorization_07_019: [ On error IoTHubClient_Auth_Create shall return NULL. ] */
+        LogError("Failed allocating IOTHUB_AUTHORIZATION_DATA");
+        result = NULL;
+    }
+    else
+    {
+        memset(result, 0, sizeof(IOTHUB_AUTHORIZATION_DATA) );
+        if (mallocAndStrcpy_s(&result->device_id, device_id) != 0)
+        {
+            /* Codes_SRS_IoTHub_Authorization_07_019: [ On error IoTHubClient_Auth_Create shall return NULL. ] */
+            LogError("Failed allocating device_key");
+            free(result);
+            result = NULL;
+        }
+        else if (module_id != NULL && mallocAndStrcpy_s(&result->module_id, module_id) != 0)
+        {
+            /* Codes_SRS_IoTHub_Authorization_07_019: [ On error IoTHubClient_Auth_Create shall return NULL. ] */
+            LogError("Failed allocating module_id");
+            free(result->device_id);
+            free(result);
+            result = NULL;
+        }
+        else
+        {
+            result->token_expiry_time_sec = DEFAULT_SAS_TOKEN_EXPIRY_TIME_SECS;
+        }
+    }
+    return result;
+}
+
+IOTHUB_AUTHORIZATION_HANDLE IoTHubClient_Auth_Create(const char* device_key, const char* device_id, const char* device_sas_token, const char *module_id)
+{
+    IOTHUB_AUTHORIZATION_DATA* result;
+    bool is_key_valid;
+
+    if (device_key == NULL)
+    {
+        is_key_valid = true;
+    }
+    else
+    {
+        /* Codes_SRS_IoTHub_Authorization_21_021: [ If the provided key is not base64 encoded, IoTHubClient_Auth_Create shall return NULL. ] */
+        BUFFER_HANDLE key = Azure_Base64_Decode(device_key);
+        if (key != NULL)
+        {
+            is_key_valid = true;
+        }
+        else
+        {
+            is_key_valid = false;
+        }
+        BUFFER_delete(key);
+    }
+    
+    /* Codes_SRS_IoTHub_Authorization_07_001: [if device_id is NULL IoTHubClient_Auth_Create, shall return NULL. ] */
+    if ((device_id == NULL) || (!is_key_valid))
+    {
+        LogError("Invalid Parameter %s", ((device_id == NULL) ? "device_id: NULL" : "key"));
+        result = NULL;
+    }
+    else
+    {
+        result = initialize_auth_client(device_id, module_id);
+        if (result == NULL)
+        {
+            LogError("Failure initializing auth client");
+        }
+        else if (device_key != NULL && mallocAndStrcpy_s(&result->device_key, device_key) != 0)
+        {
+            /* Codes_SRS_IoTHub_Authorization_07_019: [ On error IoTHubClient_Auth_Create shall return NULL. ] */
+            LogError("Failed allocating device_key");
+            free(result->device_id);
+            free(result->module_id);
+            free(result);
+            result = NULL;
+        }
+        else
+        {
+            if (device_key != NULL)
+            {
+                /* Codes_SRS_IoTHub_Authorization_07_003: [ IoTHubClient_Auth_Create shall set the credential type to IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY if the device_sas_token is NULL. ]*/
+                result->cred_type = IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY;
+            }
+            else if (device_sas_token != NULL)
+            {
+                /* Codes_SRS_IoTHub_Authorization_07_020: [ else IoTHubClient_Auth_Create shall set the credential type to IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN. ] */
+                result->cred_type = IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN;
+                if (mallocAndStrcpy_s(&result->device_sas_token, device_sas_token) != 0)
+                {
+                    /* Codes_SRS_IoTHub_Authorization_07_019: [ On error IoTHubClient_Auth_Create shall return NULL. ] */
+                    LogError("Failed allocating device_key");
+                    free(result->device_key);
+                    free(result->device_id);
+                    free(result->module_id);
+                    free(result);
+                    result = NULL;
+                }
+            }
+            else
+            {
+                /* Codes_SRS_IoTHub_Authorization_07_024: [ if device_sas_token and device_key are NULL IoTHubClient_Auth_Create shall set the credential type to IOTHUB_CREDENTIAL_TYPE_UNKNOWN. ] */
+                result->cred_type = IOTHUB_CREDENTIAL_TYPE_UNKNOWN;
+            }
+        }
+    }
+    /* Codes_SRS_IoTHub_Authorization_07_004: [ If successful IoTHubClient_Auth_Create shall return a IOTHUB_AUTHORIZATION_HANDLE value. ] */
+    return result;
+}
+
+IOTHUB_AUTHORIZATION_HANDLE IoTHubClient_Auth_CreateFromDeviceAuth(const char* device_id, const char* module_id)
+{
+    IOTHUB_AUTHORIZATION_DATA* result;
+    if (device_id == NULL)
+    {
+        LogError("Invalid Parameter device_id: %p", device_id);
+        result = NULL;
+    }
+    else
+    {
+#ifdef USE_PROV_MODULE
+        result = initialize_auth_client(device_id, module_id);
+        if (result == NULL)
+        {
+            LogError("Failure initializing auth client");
+        }
+        else
+        {
+            result->device_auth_handle = iothub_device_auth_create();
+            if (result->device_auth_handle == NULL)
+            {
+                LogError("Failed allocating IOTHUB_AUTHORIZATION_DATA");
+                free(result->device_id);
+                free(result->module_id);
+                free(result);
+                result = NULL;
+            }
+            else
+            {
+                DEVICE_AUTH_TYPE auth_type = iothub_device_auth_get_type(result->device_auth_handle);
+                if (auth_type == AUTH_TYPE_SAS || auth_type == AUTH_TYPE_SYMM_KEY)
+                {
+                    result->cred_type = IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH;
+                }
+                else
+                {
+                    result->cred_type = IOTHUB_CREDENTIAL_TYPE_X509_ECC;
+                }
+            }
+        }
+#else
+        (void)module_id;
+        LogError("Failed HSM module is not supported");
+        result = NULL;
+#endif
+    }
+    return result;
+}
+
+void IoTHubClient_Auth_Destroy(IOTHUB_AUTHORIZATION_HANDLE handle)
+{
+    /* Codes_SRS_IoTHub_Authorization_07_005: [ if handle is NULL IoTHubClient_Auth_Destroy shall do nothing. ] */
+    if (handle != NULL)
+    {
+        /* Codes_SRS_IoTHub_Authorization_07_006: [ IoTHubClient_Auth_Destroy shall free all resources associated with the IOTHUB_AUTHORIZATION_HANDLE handle. ] */
+#ifdef USE_PROV_MODULE
+        iothub_device_auth_destroy(handle->device_auth_handle);
+#endif
+        free(handle->device_key);
+        free(handle->device_id);
+        free(handle->module_id);
+        free(handle->device_sas_token);
+        free(handle);
+    }
+}
+
+IOTHUB_CREDENTIAL_TYPE IoTHubClient_Auth_Set_x509_Type(IOTHUB_AUTHORIZATION_HANDLE handle, bool enable_x509)
+{
+    IOTHUB_CREDENTIAL_TYPE result;
+    if (handle != NULL)
+    {
+        if (enable_x509)
+        {
+            result = handle->cred_type = IOTHUB_CREDENTIAL_TYPE_X509;
+        }
+        else
+        {
+            if (handle->device_sas_token == NULL)
+            {
+                result = handle->cred_type = IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY;
+            }
+            else if (handle->device_key == NULL)
+            {
+                result = handle->cred_type = IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN;
+            }
+            else
+            {
+                result = handle->cred_type = IOTHUB_CREDENTIAL_TYPE_UNKNOWN;
+            }
+        }
+    }
+    else
+    {
+        result = IOTHUB_CREDENTIAL_TYPE_UNKNOWN;
+    }
+    return result;
+}
+
+int IoTHubClient_Auth_Set_xio_Certificate(IOTHUB_AUTHORIZATION_HANDLE handle, XIO_HANDLE xio)
+{
+    int result;
+    if (handle == NULL || xio == NULL)
+    {
+        LogError("Invalid Parameter handle: %p xio: %p", handle, xio);
+        result = MU_FAILURE;
+    }
+    else if (handle->cred_type != IOTHUB_CREDENTIAL_TYPE_X509_ECC)
+    {
+        LogError("Invalid credential types for this operation");
+        result = MU_FAILURE;
+    }
+    else
+    {
+#ifdef USE_PROV_MODULE
+        CREDENTIAL_RESULT* cred_result = iothub_device_auth_generate_credentials(handle->device_auth_handle, NULL);
+        if (cred_result == NULL)
+        {
+            LogError("Failure generating credentials");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if (xio_setoption(xio, OPTION_X509_ECC_CERT, cred_result->auth_cred_result.x509_result.x509_cert) != 0)
+            {
+                LogError("Failure setting x509 cert on xio");
+                result = MU_FAILURE;
+            }
+            else if (xio_setoption(xio, OPTION_X509_ECC_KEY, cred_result->auth_cred_result.x509_result.x509_alias_key) != 0)
+            {
+                LogError("Failure setting x509 key on xio");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                result = 0;
+            }
+            free(cred_result);
+        }
+#else
+        LogError("Failed HSM module is not supported");
+        result = MU_FAILURE;
+#endif
+    }
+    return result;
+}
+
+int IoTHubClient_Auth_Get_x509_info(IOTHUB_AUTHORIZATION_HANDLE handle, char** x509_cert, char** x509_key)
+{
+    int result;
+    if (handle == NULL || x509_cert == NULL || x509_key == NULL)
+    {
+        LogError("Invalid Parameter handle: %p, x509_cert: %p, x509_key: %p", handle, x509_cert, x509_key);
+        result = MU_FAILURE;
+    }
+    else if (handle->cred_type != IOTHUB_CREDENTIAL_TYPE_X509_ECC)
+    {
+        LogError("Invalid credential types for this operation");
+        result = MU_FAILURE;
+    }
+    else
+    {
+#ifdef USE_PROV_MODULE
+        CREDENTIAL_RESULT* cred_result = iothub_device_auth_generate_credentials(handle->device_auth_handle, NULL);
+        if (cred_result == NULL)
+        {
+            LogError("Failure generating credentials");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if (mallocAndStrcpy_s(x509_cert, cred_result->auth_cred_result.x509_result.x509_cert) != 0)
+            {
+                LogError("Failure copying certificate");
+                result = MU_FAILURE;
+            }
+            else if (mallocAndStrcpy_s(x509_key, cred_result->auth_cred_result.x509_result.x509_alias_key) != 0)
+            {
+                LogError("Failure copying private key");
+                result = MU_FAILURE;
+                free(*x509_cert);
+            }
+            else
+            {
+                result = 0;
+            }
+            free(cred_result);
+        }
+#else
+        LogError("Failed HSM module is not supported");
+        result = MU_FAILURE;
+#endif
+    }
+    return result;
+}
+
+IOTHUB_CREDENTIAL_TYPE IoTHubClient_Auth_Get_Credential_Type(IOTHUB_AUTHORIZATION_HANDLE handle)
+{
+    IOTHUB_CREDENTIAL_TYPE result;
+    /* Codes_SRS_IoTHub_Authorization_07_007: [ if handle is NULL IoTHub_Auth_Get_Credential_Type shall return IOTHUB_CREDENTIAL_TYPE_UNKNOWN. ] */
+    if (handle == NULL)
+    {
+        LogError("Invalid Parameter handle: %p", handle);
+        result = IOTHUB_CREDENTIAL_TYPE_UNKNOWN;
+    }
+    else
+    {
+        /* Codes_SRS_IoTHub_Authorization_07_008: [ IoTHub_Auth_Get_Credential_Type shall return the credential type that is set upon creation. ] */
+        result = handle->cred_type;
+    }
+    return result;
+}
+
+char* IoTHubClient_Auth_Get_SasToken(IOTHUB_AUTHORIZATION_HANDLE handle, const char* scope, size_t expiry_time_relative_seconds, const char* key_name)
+{
+    char* result;
+    (void)expiry_time_relative_seconds;
+    /* Codes_SRS_IoTHub_Authorization_07_009: [ if handle or scope are NULL, IoTHubClient_Auth_Get_SasToken shall return NULL. ] */
+    if (handle == NULL)
+    {
+        LogError("Invalid Parameter handle: %p", handle);
+        result = NULL;
+    }
+    else
+    {
+        if (handle->cred_type == IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH)
+        {
+#ifdef USE_PROV_MODULE
+            DEVICE_AUTH_CREDENTIAL_INFO dev_auth_cred;
+            size_t sec_since_epoch;
+
+            if (get_seconds_since_epoch(&sec_since_epoch) != 0)
+            {
+                LogError("failure getting seconds from epoch");
+                result = NULL;
+            }
+            else
+            {
+                memset(&dev_auth_cred, 0, sizeof(DEVICE_AUTH_CREDENTIAL_INFO));
+                size_t expiry_time = sec_since_epoch + handle->token_expiry_time_sec;
+                dev_auth_cred.sas_info.expiry_seconds = expiry_time;
+                dev_auth_cred.sas_info.token_scope = scope;
+                dev_auth_cred.sas_info.key_name = key_name;
+                dev_auth_cred.dev_auth_type = AUTH_TYPE_SAS;
+
+                CREDENTIAL_RESULT* cred_result = iothub_device_auth_generate_credentials(handle->device_auth_handle, &dev_auth_cred);
+                if (cred_result == NULL)
+                {
+                    LogError("failure getting credentials from device auth module");
+                    result = NULL;
+                }
+                else
+                {
+                    if (mallocAndStrcpy_s(&result, cred_result->auth_cred_result.sas_result.sas_token) != 0)
+                    {
+                        LogError("failure allocating Sas Token");
+                        result = NULL;
+                    }
+                    free(cred_result);
+                }
+            }
+#else
+            LogError("Failed HSM module is not supported");
+            result = NULL;
+#endif
+        }
+        else if (handle->cred_type == IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN)
+        {
+            /* Codes_SRS_IoTHub_Authorization_07_021: [If the device_sas_token is NOT NULL IoTHubClient_Auth_Get_SasToken shall return a copy of the device_sas_token. ] */
+            if (handle->device_sas_token != NULL)
+            {
+                if (mallocAndStrcpy_s(&result, handle->device_sas_token) != 0)
+                {
+                    LogError("failure allocating sas token");
+                    result = NULL;
+                }
+            }
+            else
+            {
+                LogError("failure device sas token is NULL");
+                result = NULL;
+            }
+        }
+        else if (handle->cred_type == IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY)
+        {
+            /* Codes_SRS_IoTHub_Authorization_07_009: [ if handle or scope are NULL, IoTHubClient_Auth_Get_SasToken shall return NULL. ] */
+            if (scope == NULL)
+            {
+                LogError("Invalid Parameter scope: %p", scope);
+                result = NULL;
+            }
+            else
+            {
+                STRING_HANDLE sas_token;
+                size_t sec_since_epoch;
+
+                /* Codes_SRS_IoTHub_Authorization_07_010: [ IoTHubClient_Auth_Get_SasToken` shall construct the expiration time using the handle->token_expiry_time_sec added to epoch time. ] */
+                if (get_seconds_since_epoch(&sec_since_epoch) != 0)
+                {
+                    /* Codes_SRS_IoTHub_Authorization_07_020: [ If any error is encountered IoTHubClient_Auth_Get_ConnString shall return NULL. ] */
+                    LogError("failure getting seconds from epoch");
+                    result = NULL;
+                }
+                else
+                {
+                    /* Codes_SRS_IoTHub_Authorization_07_011: [ IoTHubClient_Auth_Get_ConnString shall call SASToken_CreateString to construct the sas token. ] */
+                    size_t expiry_time = sec_since_epoch + handle->token_expiry_time_sec;
+                    if ( (sas_token = SASToken_CreateString(handle->device_key, scope, key_name, expiry_time)) == NULL)
+                    {
+                        /* Codes_SRS_IoTHub_Authorization_07_020: [ If any error is encountered IoTHubClient_Auth_Get_ConnString shall return NULL. ] */
+                        LogError("Failed creating sas_token");
+                        result = NULL;
+                    }
+                    else
+                    {
+                        /* Codes_SRS_IoTHub_Authorization_07_012: [ On success IoTHubClient_Auth_Get_ConnString shall allocate and return the sas token in a char*. ] */
+                        if (mallocAndStrcpy_s(&result, STRING_c_str(sas_token) ) != 0)
+                        {
+                            /* Codes_SRS_IoTHub_Authorization_07_020: [ If any error is encountered IoTHubClient_Auth_Get_ConnString shall return NULL. ] */
+                            LogError("Failed copying result");
+                            result = NULL;
+                        }
+                        STRING_delete(sas_token);
+                    }
+                }
+            }
+        }
+        else
+        {
+            LogError("Failed getting sas token invalid credential type");
+            result = NULL;
+        }
+    }
+    return result;
+}
+
+const char* IoTHubClient_Auth_Get_DeviceId(IOTHUB_AUTHORIZATION_HANDLE handle)
+{
+    const char* result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_IoTHub_Authorization_07_013: [ if handle is NULL, IoTHubClient_Auth_Get_DeviceId shall return NULL. ] */
+        LogError("Invalid Parameter handle: %p", handle);
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_IoTHub_Authorization_07_014: [ IoTHubClient_Auth_Get_DeviceId shall return the device_id specified upon creation. ] */
+        result = handle->device_id;
+    }
+    return result;
+}
+
+const char* IoTHubClient_Auth_Get_ModuleId(IOTHUB_AUTHORIZATION_HANDLE handle)
+{
+    const char* result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_IoTHub_Authorization_31_025: [ if handle is NULL, IoTHubClient_Auth_Get_ModuleId shall return NULL. ] */
+        LogError("Invalid Parameter handle: %p", handle);
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_IoTHub_Authorization_31_026: [ IoTHubClient_Auth_Get_ModuleId shall return the module_id specified upon creation. ] */
+        result = handle->module_id;
+    }
+    return result;
+}
+
+const char* IoTHubClient_Auth_Get_DeviceKey(IOTHUB_AUTHORIZATION_HANDLE handle)
+{
+    const char* result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_IoTHub_Authorization_07_022: [ if handle is NULL, IoTHubClient_Auth_Get_DeviceKey shall return NULL. ] */
+        LogError("Invalid Parameter handle: %p", handle);
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_IoTHub_Authorization_07_023: [ IoTHubClient_Auth_Get_DeviceKey shall return the device_key specified upon creation. ] */
+        result = handle->device_key;
+    }
+    return result;
+}
+
+SAS_TOKEN_STATUS IoTHubClient_Auth_Is_SasToken_Valid(IOTHUB_AUTHORIZATION_HANDLE handle)
+{
+    SAS_TOKEN_STATUS result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_IoTHub_Authorization_07_015: [ if handle is NULL, IoTHubClient_Auth_Is_SasToken_Valid shall return false. ] */
+        LogError("Invalid Parameter handle: %p", handle);
+        result = SAS_TOKEN_STATUS_FAILED;
+    }
+    else
+    {
+        if (handle->cred_type == IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN)
+        {
+            if (handle->device_sas_token == NULL)
+            {
+                /* Codes_SRS_IoTHub_Authorization_07_017: [ If the sas_token is NULL IoTHubClient_Auth_Is_SasToken_Valid shall return false. ] */
+                LogError("Failure: device_sas_toke is NULL");
+                result = SAS_TOKEN_STATUS_FAILED;
+            }
+            else
+            {
+                /* Codes_SRS_IoTHub_Authorization_07_018: [ otherwise IoTHubClient_Auth_Is_SasToken_Valid shall return the value returned by SASToken_Validate. ] */
+                STRING_HANDLE strSasToken = STRING_construct(handle->device_sas_token);
+                if (strSasToken != NULL)
+                {
+                    if (!SASToken_Validate(strSasToken))
+                    {
+                        result = SAS_TOKEN_STATUS_INVALID;
+                    }
+                    else
+                    {
+                        result = SAS_TOKEN_STATUS_VALID;
+                    }
+                    STRING_delete(strSasToken);
+                }
+                else
+                {
+                    LogError("Failure constructing SAS Token");
+                    result = SAS_TOKEN_STATUS_FAILED;
+                }
+            }
+        }
+        else
+        {
+            /* Codes_SRS_IoTHub_Authorization_07_016: [ if credential type is not IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN IoTHubClient_Auth_Is_SasToken_Valid shall return SAS_TOKEN_STATUS_VALID. ] */
+            result = SAS_TOKEN_STATUS_VALID;
+        }
+    }
+    return result;
+}
+
+#ifdef USE_EDGE_MODULES
+
+// For debugging C modules, the environment can set the environment variable 'EdgeModuleCACertificateFile' to provide
+// trusted certificates.  We'd otherwise usually get these from trusted Edge service, but this complicates debugging experience.
+// EdgeModuleCACertificateFile and the related EdgeHubConnectionString can be set either manually or by tooling (e.g. VS Code).
+static char* read_ca_certificate_from_file(const char* certificate_file_name)
+{
+    char* result;
+    FILE *file_stream = NULL;
+
+    if ((file_stream = fopen(certificate_file_name, "r")) == NULL)
+    {
+        LogError("Cannot read file %s, errno=%d", certificate_file_name, errno);
+        result = NULL;
+    }
+    else if (fseek(file_stream, 0, SEEK_END) != 0)
+    {
+        LogError("fseek on file %s fails, errno=%d", certificate_file_name, errno);
+        result = NULL;
+    }
+    else
+    {
+        long int file_size = ftell(file_stream);
+        if (file_size < 0)
+        {
+            LogError("ftell fails reading %s, errno=%d",  certificate_file_name, errno);
+            result = NULL;
+        }
+        else if (file_size == 0)
+        {
+            LogError("file %s is 0 bytes, which is not valid certificate",  certificate_file_name);
+            result = NULL;
+        }
+        else
+        {
+            rewind(file_stream);
+
+            if ((result = calloc(1, file_size + 1)) == NULL)
+            {
+                LogError("Cannot allocate %lu bytes", (unsigned long)file_size);
+            }
+            else if ((fread(result, 1, file_size, file_stream) == 0) || (ferror(file_stream) != 0))
+            {
+                LogError("fread failed on file %s, errno=%d", certificate_file_name, errno);
+                free(result);
+                result = NULL;
+            }
+        }
+    }
+
+    if (file_stream != NULL)
+    {
+        fclose(file_stream);
+    }
+
+    return result;
+}
+
+// IoTHubClient_Auth_Get_TrustBundle retrieves a trust bundle - namely a PEM indicating the certificates the client should
+// trust as root authorities - to caller.  If certificate_file_name, we read this from a local file.  This should in general
+// be limited only to debugging modules on Edge.  If certificate_file_name is NULL, we invoke into the underlying
+// HSM to retrieve this.
+char* IoTHubClient_Auth_Get_TrustBundle(IOTHUB_AUTHORIZATION_HANDLE handle, const char* certificate_file_name)
+{
+    char* result;
+    if (handle == NULL)
+    {
+        LogError("Security Handle is NULL");
+        result = NULL;
+    }
+    else if (certificate_file_name != NULL)
+    {
+        result = read_ca_certificate_from_file(certificate_file_name);
+    }
+    else
+    {
+        result = iothub_device_auth_get_trust_bundle(handle->device_auth_handle);
+    }
+    return result;
+}
+#endif
+
+int IoTHubClient_Auth_Set_SasToken_Expiry(IOTHUB_AUTHORIZATION_HANDLE handle, size_t expiry_time_seconds)
+{
+    int result;
+    if (handle == NULL)
+    {
+        LogError("Invalid handle value handle: NULL");
+        result = MU_FAILURE;
+    }
+    // Validate the expiry_time in seconds
+    else if (expiry_time_seconds < MIN_SAS_EXPIRY_TIME)
+    {
+        LogError("Failure setting expiry time to value %lu min value is %d", (unsigned long)expiry_time_seconds, MIN_SAS_EXPIRY_TIME);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        handle->token_expiry_time_sec = expiry_time_seconds;
+        result = 0;
+    }
+    return result;
+}
+
+size_t IoTHubClient_Auth_Get_SasToken_Expiry(IOTHUB_AUTHORIZATION_HANDLE handle)
+{
+    size_t result;
+    if (handle == NULL)
+    {
+        LogError("Invalid handle value handle: NULL");
+        result = 0;
+    }
+    else
+    {
+        result = handle->token_expiry_time_sec;
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_client_core.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_client_core.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_client_core.c	(revision 453)
@@ -0,0 +1,2660 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "umock_c/umock_c_prod.h"
+#include "azure_c_shared_utility/gballoc.h"
+
+#include <signal.h>
+#include <stddef.h>
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "iothub_client_core.h"
+#include "iothub_client_core_ll.h"
+#include "internal/iothubtransport.h"
+#include "internal/iothub_client_private.h"
+#include "internal/iothubtransport.h"
+#include "azure_c_shared_utility/threadapi.h"
+#include "azure_c_shared_utility/lock.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/singlylinkedlist.h"
+#include "azure_c_shared_utility/vector.h"
+#include "iothub_client_options.h"
+#include "azure_c_shared_utility/tickcounter.h"
+#include "azure_c_shared_utility/agenttime.h"
+
+
+#define DO_WORK_FREQ_DEFAULT 1
+
+struct IOTHUB_QUEUE_CONTEXT_TAG;
+
+typedef struct IOTHUB_CLIENT_CORE_INSTANCE_TAG
+{
+    IOTHUB_CLIENT_CORE_LL_HANDLE IoTHubClientLLHandle;
+    TRANSPORT_HANDLE TransportHandle;
+    THREAD_HANDLE ThreadHandle;
+    LOCK_HANDLE LockHandle;
+    sig_atomic_t StopThread;
+    SINGLYLINKEDLIST_HANDLE httpWorkerThreadInfoList; /*list containing HTTPWORKER_THREAD_INFO*/
+    int created_with_transport_handle;
+    VECTOR_HANDLE saved_user_callback_list;
+    IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK desired_state_callback;
+    IOTHUB_CLIENT_CONNECTION_STATUS_CALLBACK connection_status_callback;
+    IOTHUB_CLIENT_DEVICE_METHOD_CALLBACK_ASYNC device_method_callback;
+    IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK inbound_device_method_callback;
+    IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC message_callback;
+    struct IOTHUB_QUEUE_CONTEXT_TAG* devicetwin_user_context;
+    struct IOTHUB_QUEUE_CONTEXT_TAG* connection_status_user_context;
+    struct IOTHUB_QUEUE_CONTEXT_TAG* message_user_context;
+    struct IOTHUB_QUEUE_CONTEXT_TAG* method_user_context;
+    tickcounter_ms_t do_work_freq_ms;
+    tickcounter_ms_t currentMessageTimeout;
+} IOTHUB_CLIENT_CORE_INSTANCE;
+
+typedef enum HTTPWORKER_THREAD_TYPE_TAG
+{
+    HTTPWORKER_THREAD_UPLOAD_TO_BLOB,
+    HTTPWORKER_THREAD_INVOKE_METHOD
+} HTTPWORKER_THREAD_TYPE;
+
+typedef struct UPLOADTOBLOB_SAVED_DATA_TAG
+{
+    unsigned char* source;
+    size_t size;
+    IOTHUB_CLIENT_FILE_UPLOAD_CALLBACK iotHubClientFileUploadCallback;
+}UPLOADTOBLOB_SAVED_DATA;
+
+typedef struct UPLOADTOBLOB_MULTIBLOCK_SAVED_DATA_TAG
+{
+    IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK getDataCallback;
+    IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx;
+}UPLOADTOBLOB_MULTIBLOCK_SAVED_DATA;
+
+typedef struct INVOKE_METHOD_SAVED_DATA_TAG
+{
+    const char* deviceId;
+    const char* moduleId;
+    const char* methodName;
+    const char* methodPayload;
+    unsigned int timeout;
+    IOTHUB_METHOD_INVOKE_CALLBACK methodInvokeCallback;
+} INVOKE_METHOD_SAVED_DATA;
+
+typedef struct HTTPWORKER_THREAD_INFO_TAG
+{
+    HTTPWORKER_THREAD_TYPE workerThreadType;
+    char* destinationFileName;
+    THREAD_HANDLE threadHandle;
+    LOCK_HANDLE lockGarbage;
+    int canBeGarbageCollected; /*flag indicating that the structure can be freed because the thread deadling with it finished*/
+    IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle;
+    void* context;
+    UPLOADTOBLOB_SAVED_DATA uploadBlobSavedData;
+    INVOKE_METHOD_SAVED_DATA invokeMethodSavedData;
+    UPLOADTOBLOB_MULTIBLOCK_SAVED_DATA uploadBlobMultiblockSavedData;
+}HTTPWORKER_THREAD_INFO;
+
+#define USER_CALLBACK_TYPE_VALUES       \
+    CALLBACK_TYPE_DEVICE_TWIN,          \
+    CALLBACK_TYPE_EVENT_CONFIRM,        \
+    CALLBACK_TYPE_REPORTED_STATE,       \
+    CALLBACK_TYPE_CONNECTION_STATUS,    \
+    CALLBACK_TYPE_DEVICE_METHOD,        \
+    CALLBACK_TYPE_INBOUD_DEVICE_METHOD, \
+    CALLBACK_TYPE_MESSAGE,              \
+    CALLBACK_TYPE_INPUTMESSAGE
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(USER_CALLBACK_TYPE, USER_CALLBACK_TYPE_VALUES)
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(USER_CALLBACK_TYPE, USER_CALLBACK_TYPE_VALUES)
+
+typedef struct DEVICE_TWIN_CALLBACK_INFO_TAG
+{
+    DEVICE_TWIN_UPDATE_STATE update_state;
+    unsigned char* payLoad;
+    size_t size;
+    IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK userCallback;
+    void* userContext;
+} DEVICE_TWIN_CALLBACK_INFO;
+
+typedef struct EVENT_CONFIRM_CALLBACK_INFO_TAG
+{
+    IOTHUB_CLIENT_CONFIRMATION_RESULT confirm_result;
+    IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK eventConfirmationCallback;
+} EVENT_CONFIRM_CALLBACK_INFO;
+
+typedef struct REPORTED_STATE_CALLBACK_INFO_TAG
+{
+    int status_code;
+    IOTHUB_CLIENT_REPORTED_STATE_CALLBACK reportedStateCallback;
+} REPORTED_STATE_CALLBACK_INFO;
+
+typedef struct CONNECTION_STATUS_CALLBACK_INFO_TAG
+{
+    IOTHUB_CLIENT_CONNECTION_STATUS connection_status;
+    IOTHUB_CLIENT_CONNECTION_STATUS_REASON status_reason;
+} CONNECTION_STATUS_CALLBACK_INFO;
+
+typedef struct METHOD_CALLBACK_INFO_TAG
+{
+    STRING_HANDLE method_name;
+    BUFFER_HANDLE payload;
+    METHOD_HANDLE method_id;
+} METHOD_CALLBACK_INFO;
+
+typedef struct INPUTMESSAGE_CALLBACK_INFO_TAG
+{
+    IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC eventHandlerCallback;
+    MESSAGE_CALLBACK_INFO* message_cb_info;
+} INPUTMESSAGE_CALLBACK_INFO;
+
+typedef struct USER_CALLBACK_INFO_TAG
+{
+    USER_CALLBACK_TYPE type;
+    void* userContextCallback;
+    union IOTHUB_CALLBACK
+    {
+        DEVICE_TWIN_CALLBACK_INFO dev_twin_cb_info;
+        EVENT_CONFIRM_CALLBACK_INFO event_confirm_cb_info;
+        REPORTED_STATE_CALLBACK_INFO reported_state_cb_info;
+        CONNECTION_STATUS_CALLBACK_INFO connection_status_cb_info;
+        METHOD_CALLBACK_INFO method_cb_info;
+        MESSAGE_CALLBACK_INFO* message_cb_info;
+        INPUTMESSAGE_CALLBACK_INFO inputmessage_cb_info;
+    } iothub_callback;
+} USER_CALLBACK_INFO;
+
+typedef struct IOTHUB_QUEUE_CONTEXT_TAG
+{
+    IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientHandle;
+    void* userContextCallback;
+    union IOTHUB_CALLBACK_FUNCTION
+    {
+        IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK eventConfirmationCallback;
+        IOTHUB_CLIENT_REPORTED_STATE_CALLBACK reportedStateCallback;
+    } callbackFunction;
+} IOTHUB_QUEUE_CONTEXT;
+
+typedef struct IOTHUB_QUEUE_CONSOLIDATED_CONTEXT_TAG
+{
+    IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientHandle;
+
+    union USER_CALLBACK_TAG
+    {
+        IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK getTwin;
+    } userCallback;
+
+    void* userContext;
+} IOTHUB_QUEUE_CONSOLIDATED_CONTEXT;
+
+typedef struct IOTHUB_INPUTMESSAGE_CALLBACK_CONTEXT_TAG
+{
+    IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle;
+    IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC eventHandlerCallback;
+    void* userContextCallback;
+} IOTHUB_INPUTMESSAGE_CALLBACK_CONTEXT;
+
+/*used by unittests only*/
+const size_t IoTHubClientCore_ThreadTerminationOffset = offsetof(IOTHUB_CLIENT_CORE_INSTANCE, StopThread);
+
+typedef enum CREATE_HUB_INSTANCE_TYPE_TAG
+{
+    CREATE_HUB_INSTANCE_FROM_CONNECTION_STRING,
+    CREATE_HUB_INSTANCE_FROM_EDGE_ENVIRONMENT,
+    CREATE_HUB_INSTANCE_FROM_TRANSPORT,
+    CREATE_HUB_INSTANCE_FROM_CLIENT_CONFIG,
+    CREATE_HUB_INSTANCE_FROM_DEVICE_AUTH
+} CREATE_HUB_INSTANCE_TYPE;
+
+static void freeHttpWorkerThreadInfo(HTTPWORKER_THREAD_INFO* threadInfo)
+{
+    Lock_Deinit(threadInfo->lockGarbage);
+    if (threadInfo->workerThreadType == HTTPWORKER_THREAD_UPLOAD_TO_BLOB)
+    {
+        free(threadInfo->uploadBlobSavedData.source);
+        free(threadInfo->destinationFileName);
+    }
+    else if (threadInfo->workerThreadType == HTTPWORKER_THREAD_INVOKE_METHOD)
+    {
+        free((char*)threadInfo->invokeMethodSavedData.deviceId);
+        free((char*)threadInfo->invokeMethodSavedData.moduleId);
+        free((char*)threadInfo->invokeMethodSavedData.methodName);
+        free((char*)threadInfo->invokeMethodSavedData.methodPayload);
+    }
+
+    free(threadInfo);
+}
+
+/*this function is called from _Destroy and from ScheduleWork_Thread to join finished blobUpload threads and free that memory*/
+static void garbageCollectorImpl(IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance)
+{
+    /*see if any savedData structures can be disposed of*/
+    /*Codes_SRS_IOTHUBCLIENT_02_072: [ All threads marked as disposable (upon completion of a file upload) shall be joined and the data structures build for them shall be freed. ]*/
+    LIST_ITEM_HANDLE item = singlylinkedlist_get_head_item(iotHubClientInstance->httpWorkerThreadInfoList);
+    while (item != NULL)
+    {
+        HTTPWORKER_THREAD_INFO* threadInfo = (HTTPWORKER_THREAD_INFO*)singlylinkedlist_item_get_value(item);
+        LIST_ITEM_HANDLE old_item = item;
+        item = singlylinkedlist_get_next_item(item);
+
+        if (Lock(threadInfo->lockGarbage) != LOCK_OK)
+        {
+            LogError("unable to Lock");
+        }
+        else
+        {
+            if (threadInfo->canBeGarbageCollected == 1)
+            {
+                int notUsed;
+                if (ThreadAPI_Join(threadInfo->threadHandle, &notUsed) != THREADAPI_OK)
+                {
+                    LogError("unable to ThreadAPI_Join");
+                }
+                (void)singlylinkedlist_remove(iotHubClientInstance->httpWorkerThreadInfoList, old_item);
+
+                if (Unlock(threadInfo->lockGarbage) != LOCK_OK)
+                {
+                    LogError("unable to unlock after locking");
+                }
+                freeHttpWorkerThreadInfo(threadInfo);
+            }
+            else
+            {
+                if (Unlock(threadInfo->lockGarbage) != LOCK_OK)
+                {
+                    LogError("unable to unlock after locking");
+                }
+            }
+        }
+    }
+}
+
+
+static bool iothub_ll_message_callback(MESSAGE_CALLBACK_INFO* messageData, void* userContextCallback)
+{
+    bool result;
+    IOTHUB_QUEUE_CONTEXT* queue_context = (IOTHUB_QUEUE_CONTEXT*)userContextCallback;
+    if (queue_context == NULL)
+    {
+        LogError("invalid parameter userContextCallback(NULL)");
+        result = false;
+    }
+    else
+    {
+        USER_CALLBACK_INFO queue_cb_info;
+        queue_cb_info.type = CALLBACK_TYPE_MESSAGE;
+        queue_cb_info.userContextCallback = queue_context->userContextCallback;
+        queue_cb_info.iothub_callback.message_cb_info = messageData;
+        if (VECTOR_push_back(queue_context->iotHubClientHandle->saved_user_callback_list, &queue_cb_info, 1) == 0)
+        {
+            result = true;
+        }
+        else
+        {
+            LogError("message callback vector push failed.");
+            result = false;
+        }
+    }
+    return result;
+}
+
+static bool iothub_ll_inputmessage_callback(MESSAGE_CALLBACK_INFO* message_cb_info, void* userContextCallback)
+{
+    bool result;
+    IOTHUB_INPUTMESSAGE_CALLBACK_CONTEXT *inputMessageCallbackContext = (IOTHUB_INPUTMESSAGE_CALLBACK_CONTEXT *)userContextCallback;
+    if (inputMessageCallbackContext == NULL)
+    {
+        LogError("invalid parameter userContextCallback(NULL)");
+        result = false;
+    }
+    else
+    {
+        USER_CALLBACK_INFO queue_cb_info;
+        queue_cb_info.type = CALLBACK_TYPE_INPUTMESSAGE;
+        queue_cb_info.userContextCallback = inputMessageCallbackContext->userContextCallback;
+        queue_cb_info.iothub_callback.inputmessage_cb_info.eventHandlerCallback = inputMessageCallbackContext->eventHandlerCallback;
+        queue_cb_info.iothub_callback.inputmessage_cb_info.message_cb_info = message_cb_info;
+
+        if (VECTOR_push_back(inputMessageCallbackContext->iotHubClientHandle->saved_user_callback_list, &queue_cb_info, 1) == 0)
+        {
+            result = true;
+        }
+        else
+        {
+            LogError("message callback vector push failed.");
+            result = false;
+        }
+    }
+
+    return result;
+}
+
+static int make_method_calback_queue_context(USER_CALLBACK_INFO* queue_cb_info, const char* method_name, const unsigned char* payload, size_t size, METHOD_HANDLE method_id, IOTHUB_QUEUE_CONTEXT* queue_context)
+{
+    int result;
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_002: [ IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK shall copy the method_name and payload. ] */
+    queue_cb_info->userContextCallback = queue_context->userContextCallback;
+    queue_cb_info->iothub_callback.method_cb_info.method_id = method_id;
+    if ((queue_cb_info->iothub_callback.method_cb_info.method_name = STRING_construct(method_name)) == NULL)
+    {
+        /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_003: [ If a failure is encountered IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK shall return a non-NULL value. ]*/
+        LogError("STRING_construct failed");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        if ((queue_cb_info->iothub_callback.method_cb_info.payload = BUFFER_create(payload, size)) == NULL)
+        {
+            STRING_delete(queue_cb_info->iothub_callback.method_cb_info.method_name);
+            /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_003: [ If a failure is encountered IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK shall return a non-NULL value. ]*/
+            LogError("BUFFER_create failed");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if (VECTOR_push_back(queue_context->iotHubClientHandle->saved_user_callback_list, queue_cb_info, 1) == 0)
+            {
+                result = 0;
+            }
+            else
+            {
+                STRING_delete(queue_cb_info->iothub_callback.method_cb_info.method_name);
+                BUFFER_delete(queue_cb_info->iothub_callback.method_cb_info.payload);
+                /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_003: [ If a failure is encountered IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK shall return a non-NULL value. ]*/
+                LogError("VECTOR_push_back failed");
+                result = MU_FAILURE;
+            }
+        }
+    }
+    return result;
+}
+
+static int iothub_ll_device_method_callback(const char* method_name, const unsigned char* payload, size_t size, METHOD_HANDLE method_id, void* userContextCallback)
+{
+    int result;
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_001: [ if userContextCallback is NULL, IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK shall return a nonNULL value. ] */
+    if (userContextCallback == NULL)
+    {
+        LogError("invalid parameter userContextCallback(NULL)");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        IOTHUB_QUEUE_CONTEXT* queue_context = (IOTHUB_QUEUE_CONTEXT*)userContextCallback;
+
+        USER_CALLBACK_INFO queue_cb_info;
+        queue_cb_info.type = CALLBACK_TYPE_DEVICE_METHOD;
+
+        result = make_method_calback_queue_context(&queue_cb_info, method_name, payload, size, method_id, queue_context);
+        if (result != 0)
+        {
+            LogError("construction of method calback queue context failed");
+            result = MU_FAILURE;
+        }
+    }
+    return result;
+}
+
+static int iothub_ll_inbound_device_method_callback(const char* method_name, const unsigned char* payload, size_t size, METHOD_HANDLE method_id, void* userContextCallback)
+{
+    int result;
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_001: [ if userContextCallback is NULL, IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK shall return a nonNULL value. ] */
+    if (userContextCallback == NULL)
+    {
+        LogError("invalid parameter userContextCallback(NULL)");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        IOTHUB_QUEUE_CONTEXT* queue_context = (IOTHUB_QUEUE_CONTEXT*)userContextCallback;
+
+        USER_CALLBACK_INFO queue_cb_info;
+        queue_cb_info.type = CALLBACK_TYPE_INBOUD_DEVICE_METHOD;
+
+        result = make_method_calback_queue_context(&queue_cb_info, method_name, payload, size, method_id, queue_context);
+        if (result != 0)
+        {
+            LogError("construction of method calback queue context failed");
+            result = MU_FAILURE;
+        }
+    }
+    return result;
+}
+
+static void iothub_ll_connection_status_callback(IOTHUB_CLIENT_CONNECTION_STATUS result, IOTHUB_CLIENT_CONNECTION_STATUS_REASON reason, void* userContextCallback)
+{
+    IOTHUB_QUEUE_CONTEXT* queue_context = (IOTHUB_QUEUE_CONTEXT*)userContextCallback;
+    if (queue_context != NULL)
+    {
+        USER_CALLBACK_INFO queue_cb_info;
+        queue_cb_info.type = CALLBACK_TYPE_CONNECTION_STATUS;
+        queue_cb_info.userContextCallback = queue_context->userContextCallback;
+        queue_cb_info.iothub_callback.connection_status_cb_info.status_reason = reason;
+        queue_cb_info.iothub_callback.connection_status_cb_info.connection_status = result;
+        if (VECTOR_push_back(queue_context->iotHubClientHandle->saved_user_callback_list, &queue_cb_info, 1) != 0)
+        {
+            LogError("connection status callback vector push failed.");
+        }
+    }
+}
+
+static void iothub_ll_event_confirm_callback(IOTHUB_CLIENT_CONFIRMATION_RESULT result, void* userContextCallback)
+{
+    IOTHUB_QUEUE_CONTEXT* queue_context = (IOTHUB_QUEUE_CONTEXT*)userContextCallback;
+    if (queue_context != NULL)
+    {
+        USER_CALLBACK_INFO queue_cb_info;
+        queue_cb_info.type = CALLBACK_TYPE_EVENT_CONFIRM;
+        queue_cb_info.userContextCallback = queue_context->userContextCallback;
+        queue_cb_info.iothub_callback.event_confirm_cb_info.confirm_result = result;
+        queue_cb_info.iothub_callback.event_confirm_cb_info.eventConfirmationCallback = queue_context->callbackFunction.eventConfirmationCallback;
+        if (VECTOR_push_back(queue_context->iotHubClientHandle->saved_user_callback_list, &queue_cb_info, 1) != 0)
+        {
+            LogError("event confirm callback vector push failed.");
+        }
+        free(queue_context);
+    }
+}
+
+static void iothub_ll_reported_state_callback(int status_code, void* userContextCallback)
+{
+    IOTHUB_QUEUE_CONTEXT* queue_context = (IOTHUB_QUEUE_CONTEXT*)userContextCallback;
+    if (queue_context != NULL)
+    {
+        USER_CALLBACK_INFO queue_cb_info;
+        queue_cb_info.type = CALLBACK_TYPE_REPORTED_STATE;
+        queue_cb_info.userContextCallback = queue_context->userContextCallback;
+        queue_cb_info.iothub_callback.reported_state_cb_info.status_code = status_code;
+        queue_cb_info.iothub_callback.reported_state_cb_info.reportedStateCallback = queue_context->callbackFunction.reportedStateCallback;
+        if (VECTOR_push_back(queue_context->iotHubClientHandle->saved_user_callback_list, &queue_cb_info, 1) != 0)
+        {
+            LogError("reported state callback vector push failed.");
+        }
+        free(queue_context);
+    }
+}
+
+static void iothub_ll_device_twin_callback(DEVICE_TWIN_UPDATE_STATE update_state, const unsigned char* payLoad, size_t size, void* userContextCallback)
+{
+    IOTHUB_QUEUE_CONTEXT* queue_context = (IOTHUB_QUEUE_CONTEXT*)userContextCallback;
+    if (queue_context != NULL)
+    {
+        int push_to_vector;
+
+        USER_CALLBACK_INFO queue_cb_info;
+        queue_cb_info.type = CALLBACK_TYPE_DEVICE_TWIN;
+        queue_cb_info.userContextCallback = queue_context->userContextCallback;
+        queue_cb_info.iothub_callback.dev_twin_cb_info.update_state = update_state;
+        queue_cb_info.iothub_callback.dev_twin_cb_info.userCallback = NULL;
+        queue_cb_info.iothub_callback.dev_twin_cb_info.userContext = NULL;
+
+        if (payLoad == NULL)
+        {
+            queue_cb_info.iothub_callback.dev_twin_cb_info.payLoad = NULL;
+            queue_cb_info.iothub_callback.dev_twin_cb_info.size = 0;
+            push_to_vector = 0;
+        }
+        else
+        {
+            queue_cb_info.iothub_callback.dev_twin_cb_info.payLoad = (unsigned char*)malloc(size);
+            if (queue_cb_info.iothub_callback.dev_twin_cb_info.payLoad == NULL)
+            {
+                LogError("failure allocating payload in device twin callback.");
+                queue_cb_info.iothub_callback.dev_twin_cb_info.size = 0;
+                push_to_vector = MU_FAILURE;
+            }
+            else
+            {
+                (void)memcpy(queue_cb_info.iothub_callback.dev_twin_cb_info.payLoad, payLoad, size);
+                queue_cb_info.iothub_callback.dev_twin_cb_info.size = size;
+                push_to_vector = 0;
+            }
+        }
+        if (push_to_vector == 0)
+        {
+            if (VECTOR_push_back(queue_context->iotHubClientHandle->saved_user_callback_list, &queue_cb_info, 1) != 0)
+            {
+                if (queue_cb_info.iothub_callback.dev_twin_cb_info.payLoad != NULL)
+                {
+                    free(queue_cb_info.iothub_callback.dev_twin_cb_info.payLoad);
+                }
+                LogError("device twin callback userContextCallback vector push failed.");
+            }
+        }
+    }
+    else
+    {
+        LogError("device twin callback userContextCallback NULL");
+    }
+}
+
+static void iothub_ll_get_device_twin_async_callback(DEVICE_TWIN_UPDATE_STATE update_state, const unsigned char* payLoad, size_t size, void* userContextCallback)
+{
+    IOTHUB_QUEUE_CONSOLIDATED_CONTEXT* queue_context = (IOTHUB_QUEUE_CONSOLIDATED_CONTEXT*)userContextCallback;
+
+    if (queue_context != NULL)
+    {
+        USER_CALLBACK_INFO queue_cb_info;
+        queue_cb_info.type = CALLBACK_TYPE_DEVICE_TWIN;
+        queue_cb_info.userContextCallback = queue_context->userContext;
+        queue_cb_info.iothub_callback.dev_twin_cb_info.update_state = update_state;
+        queue_cb_info.iothub_callback.dev_twin_cb_info.userCallback = queue_context->userCallback.getTwin;
+        queue_cb_info.iothub_callback.dev_twin_cb_info.userContext = queue_context->userContext;
+
+        if (payLoad == NULL)
+        {
+            queue_cb_info.iothub_callback.dev_twin_cb_info.payLoad = NULL;
+            queue_cb_info.iothub_callback.dev_twin_cb_info.size = 0;
+        }
+        else
+        {
+            queue_cb_info.iothub_callback.dev_twin_cb_info.payLoad = (unsigned char*)malloc(size);
+
+            if (queue_cb_info.iothub_callback.dev_twin_cb_info.payLoad == NULL)
+            {
+                LogError("Failure allocating payload in get device twin callback.");
+                queue_cb_info.iothub_callback.dev_twin_cb_info.size = 0;
+            }
+            else
+            {
+                (void)memcpy(queue_cb_info.iothub_callback.dev_twin_cb_info.payLoad, payLoad, size);
+                queue_cb_info.iothub_callback.dev_twin_cb_info.size = size;
+            }
+        }
+
+        if (VECTOR_push_back(queue_context->iotHubClientHandle->saved_user_callback_list, &queue_cb_info, 1) != 0)
+        {
+            LogError("device twin callback userContextCallback vector push failed.");
+
+            if (queue_cb_info.iothub_callback.dev_twin_cb_info.payLoad != NULL)
+            {
+                free(queue_cb_info.iothub_callback.dev_twin_cb_info.payLoad);
+            }
+        }
+
+        free(queue_context);
+    }
+    else
+    {
+        LogError("Get device twin callback userContextCallback NULL");
+    }
+}
+
+static void dispatch_user_callbacks(IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance, VECTOR_HANDLE call_backs)
+{
+    size_t callbacks_length = VECTOR_size(call_backs);
+    size_t index;
+
+    IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK desired_state_callback = NULL;
+    IOTHUB_CLIENT_CONNECTION_STATUS_CALLBACK connection_status_callback = NULL;
+    IOTHUB_CLIENT_DEVICE_METHOD_CALLBACK_ASYNC device_method_callback = NULL;
+    IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK inbound_device_method_callback = NULL;
+    IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC message_callback = NULL;
+    IOTHUB_CLIENT_CORE_HANDLE message_user_context_handle = NULL;
+    IOTHUB_CLIENT_CORE_HANDLE method_user_context_handle = NULL;
+
+    // Make a local copy of these callbacks, as we don't run with a lock held and iotHubClientInstance may change mid-run.
+    if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK)
+    {
+        LogError("failed locking for dispatch_user_callbacks");
+    }
+    else
+    {
+        desired_state_callback = iotHubClientInstance->desired_state_callback;
+        connection_status_callback = iotHubClientInstance->connection_status_callback;
+        device_method_callback = iotHubClientInstance->device_method_callback;
+        inbound_device_method_callback = iotHubClientInstance->inbound_device_method_callback;
+        message_callback = iotHubClientInstance->message_callback;
+        if (iotHubClientInstance->method_user_context)
+        {
+            method_user_context_handle = iotHubClientInstance->method_user_context->iotHubClientHandle;
+        }
+        if (iotHubClientInstance->message_user_context)
+        {
+            message_user_context_handle = iotHubClientInstance->message_user_context->iotHubClientHandle;
+        }
+
+        (void)Unlock(iotHubClientInstance->LockHandle);
+    }
+
+
+    for (index = 0; index < callbacks_length; index++)
+    {
+        USER_CALLBACK_INFO* queued_cb = (USER_CALLBACK_INFO*)VECTOR_element(call_backs, index);
+        if (queued_cb == NULL)
+        {
+            LogError("VECTOR_element at index %zd is NULL.", index);
+        }
+        else
+        {
+            switch (queued_cb->type)
+            {
+            case CALLBACK_TYPE_DEVICE_TWIN:
+            {
+                // Callback if for GetTwinAsync
+                if (queued_cb->iothub_callback.dev_twin_cb_info.userCallback)
+                {
+                    queued_cb->iothub_callback.dev_twin_cb_info.userCallback(
+                        queued_cb->iothub_callback.dev_twin_cb_info.update_state,
+                        queued_cb->iothub_callback.dev_twin_cb_info.payLoad,
+                        queued_cb->iothub_callback.dev_twin_cb_info.size,
+                        queued_cb->iothub_callback.dev_twin_cb_info.userContext
+                    );
+                }
+                // Callback if for Desired properties.
+                else if (desired_state_callback)
+                {
+                    desired_state_callback(queued_cb->iothub_callback.dev_twin_cb_info.update_state, queued_cb->iothub_callback.dev_twin_cb_info.payLoad, queued_cb->iothub_callback.dev_twin_cb_info.size, queued_cb->userContextCallback);
+                }
+
+                if (queued_cb->iothub_callback.dev_twin_cb_info.payLoad)
+                {
+                    free(queued_cb->iothub_callback.dev_twin_cb_info.payLoad);
+                }
+                break;
+            }
+            case CALLBACK_TYPE_EVENT_CONFIRM:
+                if (queued_cb->iothub_callback.event_confirm_cb_info.eventConfirmationCallback)
+                {
+                    queued_cb->iothub_callback.event_confirm_cb_info.eventConfirmationCallback(queued_cb->iothub_callback.event_confirm_cb_info.confirm_result, queued_cb->userContextCallback);
+                }
+                break;
+            case CALLBACK_TYPE_REPORTED_STATE:
+                if (queued_cb->iothub_callback.reported_state_cb_info.reportedStateCallback)
+                {
+                    queued_cb->iothub_callback.reported_state_cb_info.reportedStateCallback(queued_cb->iothub_callback.reported_state_cb_info.status_code, queued_cb->userContextCallback);
+                }
+                break;
+            case CALLBACK_TYPE_CONNECTION_STATUS:
+                if (connection_status_callback)
+                {
+                    connection_status_callback(queued_cb->iothub_callback.connection_status_cb_info.connection_status, queued_cb->iothub_callback.connection_status_cb_info.status_reason, queued_cb->userContextCallback);
+                }
+                break;
+            case CALLBACK_TYPE_DEVICE_METHOD:
+                if (device_method_callback)
+                {
+                    const char* method_name = STRING_c_str(queued_cb->iothub_callback.method_cb_info.method_name);
+                    const unsigned char* payload = BUFFER_u_char(queued_cb->iothub_callback.method_cb_info.payload);
+                    size_t payload_len = BUFFER_length(queued_cb->iothub_callback.method_cb_info.payload);
+
+                    unsigned char* payload_resp = NULL;
+                    size_t response_size = 0;
+                    int status = device_method_callback(method_name, payload, payload_len, &payload_resp, &response_size, queued_cb->userContextCallback);
+
+                    if (payload_resp && (response_size > 0))
+                    {
+                        IOTHUB_CLIENT_RESULT result = IoTHubClientCore_DeviceMethodResponse(method_user_context_handle, queued_cb->iothub_callback.method_cb_info.method_id, (const unsigned char*)payload_resp, response_size, status);
+                        if (result != IOTHUB_CLIENT_OK)
+                        {
+                            LogError("IoTHubClientCore_LL_DeviceMethodResponse failed");
+                        }
+                    }
+
+                    BUFFER_delete(queued_cb->iothub_callback.method_cb_info.payload);
+                    STRING_delete(queued_cb->iothub_callback.method_cb_info.method_name);
+
+                    if (payload_resp)
+                    {
+                        free(payload_resp);
+                    }
+                }
+                break;
+            case CALLBACK_TYPE_INBOUD_DEVICE_METHOD:
+                if (inbound_device_method_callback)
+                {
+                    const char* method_name = STRING_c_str(queued_cb->iothub_callback.method_cb_info.method_name);
+                    const unsigned char* payload = BUFFER_u_char(queued_cb->iothub_callback.method_cb_info.payload);
+                    size_t payload_len = BUFFER_length(queued_cb->iothub_callback.method_cb_info.payload);
+
+                    inbound_device_method_callback(method_name, payload, payload_len, queued_cb->iothub_callback.method_cb_info.method_id, queued_cb->userContextCallback);
+
+                    BUFFER_delete(queued_cb->iothub_callback.method_cb_info.payload);
+                    STRING_delete(queued_cb->iothub_callback.method_cb_info.method_name);
+                }
+                break;
+            case CALLBACK_TYPE_MESSAGE:
+                if (message_callback && message_user_context_handle)
+                {
+                    IOTHUBMESSAGE_DISPOSITION_RESULT disposition = message_callback(queued_cb->iothub_callback.message_cb_info->messageHandle, queued_cb->userContextCallback);
+
+                    if (Lock(message_user_context_handle->LockHandle) == LOCK_OK)
+                    {
+                        IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_SendMessageDisposition(message_user_context_handle->IoTHubClientLLHandle, queued_cb->iothub_callback.message_cb_info, disposition);
+                        (void)Unlock(message_user_context_handle->LockHandle);
+                        if (result != IOTHUB_CLIENT_OK)
+                        {
+                            LogError("IoTHubClientCore_LL_SendMessageDisposition failed");
+                        }
+                    }
+                    else
+                    {
+                        LogError("Lock failed");
+                    }
+                }
+                break;
+
+                case CALLBACK_TYPE_INPUTMESSAGE:
+                {
+                    const INPUTMESSAGE_CALLBACK_INFO *inputmessage_cb_info = &queued_cb->iothub_callback.inputmessage_cb_info;
+                    IOTHUBMESSAGE_DISPOSITION_RESULT disposition = inputmessage_cb_info->eventHandlerCallback(inputmessage_cb_info->message_cb_info->messageHandle, queued_cb->userContextCallback);
+
+                    if (Lock(iotHubClientInstance->LockHandle) == LOCK_OK)
+                    {
+                        IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_SendMessageDisposition(iotHubClientInstance->IoTHubClientLLHandle, inputmessage_cb_info->message_cb_info, disposition);
+                        (void)Unlock(iotHubClientInstance->LockHandle);
+                        if (result != IOTHUB_CLIENT_OK)
+                        {
+                            LogError("IoTHubClient_LL_SendMessageDisposition failed");
+                        }
+                    }
+                    else
+                    {
+                        LogError("Lock failed");
+                    }
+                }
+                break;
+
+            default:
+                LogError("Invalid callback type '%s'", MU_ENUM_TO_STRING(USER_CALLBACK_TYPE, queued_cb->type));
+                break;
+            }
+        }
+    }
+    VECTOR_destroy(call_backs);
+}
+
+static void ScheduleWork_Thread_ForMultiplexing(void* iotHubClientHandle)
+{
+    IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_CORE_INSTANCE*)iotHubClientHandle;
+
+    garbageCollectorImpl(iotHubClientInstance);
+    if (Lock(iotHubClientInstance->LockHandle) == LOCK_OK)
+    {
+        VECTOR_HANDLE call_backs = VECTOR_move(iotHubClientInstance->saved_user_callback_list);
+        (void)Unlock(iotHubClientInstance->LockHandle);
+
+        if (call_backs == NULL)
+        {
+            LogError("Failed moving user callbacks");
+        }
+        else
+        {
+            dispatch_user_callbacks(iotHubClientInstance, call_backs);
+        }
+    }
+    else
+    {
+        LogError("failed locking for ScheduleWork_Thread_ForMultiplexing");
+    }
+}
+
+static int ScheduleWork_Thread(void* threadArgument)
+{
+    IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_CORE_INSTANCE*)threadArgument;
+    unsigned int sleeptime_in_ms = DO_WORK_FREQ_DEFAULT;
+
+    srand((unsigned int)get_time(NULL));
+
+    while (1)
+    {
+        if (Lock(iotHubClientInstance->LockHandle) == LOCK_OK)
+        {
+            /*Codes_SRS_IOTHUBCLIENT_01_038: [ The thread shall exit when IoTHubClient_Destroy is called. ]*/
+            if (iotHubClientInstance->StopThread)
+            {
+                (void)Unlock(iotHubClientInstance->LockHandle);
+                break; /*gets out of the thread*/
+            }
+            else
+            {
+                /* Codes_SRS_IOTHUBCLIENT_01_037: [The thread created by IoTHubClient_SendEvent or IoTHubClient_SetMessageCallback shall call IoTHubClientCore_LL_DoWork every 1 ms by default.] */
+                /* Codes_SRS_IOTHUBCLIENT_01_039: [All calls to IoTHubClientCore_LL_DoWork shall be protected by the lock created in IotHubClient_Create.] */
+                IoTHubClientCore_LL_DoWork(iotHubClientInstance->IoTHubClientLLHandle);
+
+                garbageCollectorImpl(iotHubClientInstance);
+                VECTOR_HANDLE call_backs = VECTOR_move(iotHubClientInstance->saved_user_callback_list);
+                sleeptime_in_ms = (unsigned int)iotHubClientInstance->do_work_freq_ms; // Update the sleepval within the locked thread.
+                (void)Unlock(iotHubClientInstance->LockHandle);
+                if (call_backs == NULL)
+                {
+                    LogError("VECTOR_move failed");
+                }
+                else
+                {
+                    dispatch_user_callbacks(iotHubClientInstance, call_backs);
+                }
+
+
+            }
+        }
+        else
+        {
+            /*Codes_SRS_IOTHUBCLIENT_01_040: [If acquiring the lock fails, IoTHubClientCore_LL_DoWork shall not be called.]*/
+            /*no code, shall retry*/
+        }
+        /* Codes_SRS_IOTHUBCLIENT_041_02: [The thread shall sleep for a specified time in ms as provided through IoTHubClientCore_SetOption, with a default of 1 ms ] */
+        (void)ThreadAPI_Sleep(sleeptime_in_ms);
+    }
+
+    ThreadAPI_Exit(0);
+    return 0;
+}
+
+static IOTHUB_CLIENT_RESULT StartWorkerThreadIfNeeded(IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance)
+{
+    IOTHUB_CLIENT_RESULT result;
+    if (iotHubClientInstance->TransportHandle == NULL)
+    {
+        if (iotHubClientInstance->ThreadHandle == NULL)
+        {
+            iotHubClientInstance->StopThread = 0;
+            if (ThreadAPI_Create(&iotHubClientInstance->ThreadHandle, ScheduleWork_Thread, iotHubClientInstance) != THREADAPI_OK)
+            {
+                LogError("ThreadAPI_Create failed");
+                iotHubClientInstance->ThreadHandle = NULL;
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else
+            {
+                result = IOTHUB_CLIENT_OK;
+            }
+        }
+        else
+        {
+            result = IOTHUB_CLIENT_OK;
+        }
+    }
+    else
+    {
+        /*Codes_SRS_IOTHUBCLIENT_17_012: [ If the transport connection is shared, the thread shall be started by calling IoTHubTransport_StartWorkerThread. ]*/
+        /*Codes_SRS_IOTHUBCLIENT_17_011: [ If the transport connection is shared, the thread shall be started by calling IoTHubTransport_StartWorkerThread*/
+        result = IoTHubTransport_StartWorkerThread(iotHubClientInstance->TransportHandle, iotHubClientInstance, ScheduleWork_Thread_ForMultiplexing);
+    }
+    return result;
+}
+
+static IOTHUB_CLIENT_CORE_INSTANCE* create_iothub_instance(CREATE_HUB_INSTANCE_TYPE create_hub_instance_type, const IOTHUB_CLIENT_CONFIG* config, TRANSPORT_HANDLE transportHandle, const char* connectionString, IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol, const char* iothub_uri, const char* device_id)
+{
+    /* Codes_SRS_IOTHUBCLIENT_12_020: [** `IoTHubClient_CreateFromDeviceAuth` shall allocate a new `IoTHubClient` instance. **] */
+    IOTHUB_CLIENT_CORE_INSTANCE* result = (IOTHUB_CLIENT_CORE_INSTANCE*)malloc(sizeof(IOTHUB_CLIENT_CORE_INSTANCE));
+    (void)create_hub_instance_type;
+
+    /* Codes_SRS_IOTHUBCLIENT_12_021: [** If allocating memory for the new `IoTHubClient` instance fails, then `IoTHubClient_CreateFromDeviceAuth` shall return `NULL`. **] */
+    /* Codes_SRS_IOTHUBCLIENT_01_004: [If allocating memory for the new IoTHubClient instance fails, then IoTHubClient_Create shall return NULL.] */
+    if (result != NULL)
+    {
+        memset((void *)result, 0, sizeof(IOTHUB_CLIENT_CORE_INSTANCE));
+
+        /* Codes_SRS_IOTHUBCLIENT_41_02 [] */
+        result->do_work_freq_ms = DO_WORK_FREQ_DEFAULT;
+        /* Default currentMessageTimeout to NULL until it is set by SetOption */
+        result->currentMessageTimeout = 0;
+
+        /* Codes_SRS_IOTHUBCLIENT_01_029: [IoTHubClient_Create shall create a lock object to be used later for serializing IoTHubClient calls.] */
+        if ((result->saved_user_callback_list = VECTOR_create(sizeof(USER_CALLBACK_INFO))) == NULL)
+        {
+            LogError("Failed creating VECTOR");
+            free(result);
+            result = NULL;
+        }
+        else
+        {
+            /*Codes_SRS_IOTHUBCLIENT_02_060: [ IoTHubClient_Create shall create a SINGLYLINKEDLIST_HANDLE containing THREAD_HANDLE (created by future calls to IoTHubClient_UploadToBlobAsync). ]*/
+            if ((result->httpWorkerThreadInfoList = singlylinkedlist_create()) == NULL)
+            {
+                /*Codes_SRS_IOTHUBCLIENT_02_061: [ If creating the SINGLYLINKEDLIST_HANDLE fails then IoTHubClient_Create shall fail and return NULL. ]*/
+                LogError("unable to singlylinkedlist_create");
+                VECTOR_destroy(result->saved_user_callback_list);
+                free(result);
+                result = NULL;
+            }
+            else
+            {
+                result->TransportHandle = transportHandle;
+                result->created_with_transport_handle = 0;
+                if (config != NULL)
+                {
+                    if (transportHandle != NULL)
+                    {
+                        /*Codes_SRS_IOTHUBCLIENT_17_005: [ IoTHubClient_CreateWithTransport shall call IoTHubTransport_GetLock to get the transport lock to be used later for serializing IoTHubClient calls. ]*/
+                        result->LockHandle = IoTHubTransport_GetLock(transportHandle);
+                        if (result->LockHandle == NULL)
+                        {
+                            LogError("unable to IoTHubTransport_GetLock");
+                            result->IoTHubClientLLHandle = NULL;
+                        }
+                        else
+                        {
+                            IOTHUB_CLIENT_DEVICE_CONFIG deviceConfig;
+                            deviceConfig.deviceId = config->deviceId;
+                            deviceConfig.deviceKey = config->deviceKey;
+                            deviceConfig.protocol = config->protocol;
+                            deviceConfig.deviceSasToken = config->deviceSasToken;
+
+                            /*Codes_SRS_IOTHUBCLIENT_17_003: [ IoTHubClient_CreateWithTransport shall call IoTHubTransport_GetLLTransport on transportHandle to get lower layer transport. ]*/
+                            deviceConfig.transportHandle = IoTHubTransport_GetLLTransport(transportHandle);
+                            if (deviceConfig.transportHandle == NULL)
+                            {
+                                LogError("unable to IoTHubTransport_GetLLTransport");
+                                result->IoTHubClientLLHandle = NULL;
+                            }
+                            else
+                            {
+                                if (Lock(result->LockHandle) != LOCK_OK)
+                                {
+                                    LogError("unable to Lock");
+                                    result->IoTHubClientLLHandle = NULL;
+                                }
+                                else
+                                {
+                                    /*Codes_SRS_IOTHUBCLIENT_17_007: [ IoTHubClient_CreateWithTransport shall instantiate a new IoTHubClientCore_LL instance by calling IoTHubClientCore_LL_CreateWithTransport and passing the lower layer transport and config argument. ]*/
+                                    result->IoTHubClientLLHandle = IoTHubClientCore_LL_CreateWithTransport(&deviceConfig);
+                                    result->created_with_transport_handle = 1;
+                                    if (Unlock(result->LockHandle) != LOCK_OK)
+                                    {
+                                        LogError("unable to Unlock");
+                                        result->IoTHubClientLLHandle = NULL;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    else
+                    {
+                        result->LockHandle = Lock_Init();
+                        if (result->LockHandle == NULL)
+                        {
+                            /* Codes_SRS_IOTHUBCLIENT_01_030: [If creating the lock fails, then IoTHubClient_Create shall return NULL.] */
+                            /* Codes_SRS_IOTHUBCLIENT_01_031: [If IoTHubClient_Create fails, all resources allocated by it shall be freed.] */
+                            LogError("Failure creating Lock object");
+                            result->IoTHubClientLLHandle = NULL;
+                        }
+                        else
+                        {
+                            /* Codes_SRS_IOTHUBCLIENT_01_002: [IoTHubClient_Create shall instantiate a new IoTHubClientCore_LL instance by calling IoTHubClientCore_LL_Create and passing the config argument.] */
+                            result->IoTHubClientLLHandle = IoTHubClientCore_LL_Create(config);
+                        }
+                    }
+                }
+                else if (iothub_uri != NULL)
+                {
+#ifdef USE_PROV_MODULE
+                    /* Codes_SRS_IOTHUBCLIENT_12_022: [** `IoTHubClient_CreateFromDeviceAuth` shall create a lock object to be used later for serializing IoTHubClient calls. **] */
+                    result->LockHandle = Lock_Init();
+                    if (result->LockHandle == NULL)
+                    {
+                        /* Codes_SRS_IOTHUBCLIENT_12_023: [** If creating the lock fails, then IoTHubClient_CreateFromDeviceAuth shall return NULL. **] */
+                        LogError("Failure creating Lock object");
+                        result->IoTHubClientLLHandle = NULL;
+                    }
+                    else
+                    {
+                        /* Codes_SRS_IOTHUBCLIENT_12_025: [** `IoTHubClient_CreateFromDeviceAuth` shall instantiate a new `IoTHubClientCore_LL` instance by calling `IoTHubClientCore_LL_CreateFromDeviceAuth` and passing iothub_uri, device_id and protocol argument.  **] */
+                        result->IoTHubClientLLHandle = IoTHubClientCore_LL_CreateFromDeviceAuth(iothub_uri, device_id, protocol);
+                    }
+#else
+                    (void)device_id;
+                    LogError("Provisioning is not enabled for the build");
+                    result->IoTHubClientLLHandle = NULL;
+#endif
+                }
+#ifdef USE_EDGE_MODULES
+                else if (create_hub_instance_type == CREATE_HUB_INSTANCE_FROM_EDGE_ENVIRONMENT)
+                {
+                    result->LockHandle = Lock_Init();
+                    if (result->LockHandle == NULL)
+                    {
+                        /* Codes_SRS_IOTHUBCLIENT_01_030: [If creating the lock fails, then IoTHubClient_Create shall return NULL.] */
+                        /* Codes_SRS_IOTHUBCLIENT_01_031: [If IoTHubClient_Create fails, all resources allocated by it shall be freed.] */
+                        LogError("Failure creating Lock object");
+                        result->IoTHubClientLLHandle = NULL;
+                    }
+                    else
+                    {
+                        result->IoTHubClientLLHandle = IoTHubClientCore_LL_CreateFromEnvironment(protocol);
+                    }
+                }
+#endif
+                else
+                {
+                    result->LockHandle = Lock_Init();
+                    if (result->LockHandle == NULL)
+                    {
+                        /* Codes_SRS_IOTHUBCLIENT_01_030: [If creating the lock fails, then IoTHubClient_Create shall return NULL.] */
+                        /* Codes_SRS_IOTHUBCLIENT_01_031: [If IoTHubClient_Create fails, all resources allocated by it shall be freed.] */
+                        LogError("Failure creating Lock object");
+                        result->IoTHubClientLLHandle = NULL;
+                    }
+                    else
+                    {
+                        result->IoTHubClientLLHandle = IoTHubClientCore_LL_CreateFromConnectionString(connectionString, protocol);
+                    }
+                }
+
+                if (result->IoTHubClientLLHandle == NULL)
+                {
+                    /* Codes_SRS_IOTHUBCLIENT_01_003: [If IoTHubClientCore_LL_Create fails, then IoTHubClient_Create shall return NULL.] */
+                    /* Codes_SRS_IOTHUBCLIENT_01_031: [If IoTHubClient_Create fails, all resources allocated by it shall be freed.] */
+                    /* Codes_SRS_IOTHUBCLIENT_17_006: [ If IoTHubTransport_GetLock fails, then IoTHubClient_CreateWithTransport shall return NULL. ]*/
+                    if ((transportHandle == NULL) && (result->LockHandle != NULL))
+                    {
+                        Lock_Deinit(result->LockHandle);
+                    }
+                    singlylinkedlist_destroy(result->httpWorkerThreadInfoList);
+                    LogError("Failure creating iothub handle");
+                    VECTOR_destroy(result->saved_user_callback_list);
+                    free(result);
+                    result = NULL;
+                }
+                else
+                {
+                    result->ThreadHandle = NULL;
+                    result->desired_state_callback = NULL;
+                    result->devicetwin_user_context = NULL;
+                    result->connection_status_callback = NULL;
+                    result->connection_status_user_context = NULL;
+                    result->message_callback = NULL;
+                    result->message_user_context = NULL;
+                    result->method_user_context = NULL;
+                }
+            }
+        }
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_CORE_HANDLE IoTHubClientCore_CreateFromConnectionString(const char* connectionString, IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol)
+{
+    IOTHUB_CLIENT_CORE_INSTANCE* result;
+
+    if (connectionString == NULL)
+    {
+        LogError("Input parameter is NULL: connectionString");
+        result = NULL;
+    }
+    else if (protocol == NULL)
+    {
+        LogError("Input parameter is NULL: protocol");
+        result = NULL;
+    }
+    else
+    {
+        result = create_iothub_instance(CREATE_HUB_INSTANCE_FROM_CONNECTION_STRING, NULL, NULL, connectionString, protocol, NULL, NULL);
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_CORE_HANDLE IoTHubClientCore_Create(const IOTHUB_CLIENT_CONFIG* config)
+{
+    IOTHUB_CLIENT_CORE_INSTANCE* result;
+    if (config == NULL)
+    {
+        LogError("Input parameter is NULL: IOTHUB_CLIENT_CONFIG");
+        result = NULL;
+    }
+    else
+    {
+        result = create_iothub_instance(CREATE_HUB_INSTANCE_FROM_CLIENT_CONFIG, config, NULL, NULL, NULL, NULL, NULL);
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_CORE_HANDLE IoTHubClientCore_CreateWithTransport(TRANSPORT_HANDLE transportHandle, const IOTHUB_CLIENT_CONFIG* config)
+{
+    IOTHUB_CLIENT_CORE_INSTANCE* result;
+    /*Codes_SRS_IOTHUBCLIENT_17_013: [ IoTHubClient_CreateWithTransport shall return NULL if transportHandle is NULL. ]*/
+    /*Codes_SRS_IOTHUBCLIENT_17_014: [ IoTHubClient_CreateWithTransport shall return NULL if config is NULL. ]*/
+    if (transportHandle == NULL || config == NULL)
+    {
+        LogError("invalid parameter TRANSPORT_HANDLE transportHandle=%p, const IOTHUB_CLIENT_CONFIG* config=%p", transportHandle, config);
+        result = NULL;
+    }
+    else
+    {
+        result = create_iothub_instance(CREATE_HUB_INSTANCE_FROM_TRANSPORT, config, transportHandle, NULL, NULL, NULL, NULL);
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_CORE_HANDLE IoTHubClientCore_CreateFromDeviceAuth(const char* iothub_uri, const char* device_id, IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol)
+{
+    IOTHUB_CLIENT_CORE_INSTANCE* result;
+
+    /* Codes_SRS_IOTHUBCLIENT_12_019: [** `IoTHubClient_CreateFromDeviceAuth` shall verify the input parameters and if any of them `NULL` then return `NULL`. **] */
+    if (iothub_uri == NULL)
+    {
+        LogError("Input parameter is NULL: iothub_uri");
+        result = NULL;
+    }
+    else if (device_id == NULL)
+    {
+        LogError("Input parameter is NULL: device_id");
+        result = NULL;
+    }
+    else if (protocol == NULL)
+    {
+        LogError("Input parameter is NULL: protocol");
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_IOTHUBCLIENT_12_020: [** `IoTHubClient_CreateFromDeviceAuth` shall allocate a new `IoTHubClient` instance. **] */
+        /* Codes_SRS_IOTHUBCLIENT_12_021: [** If allocating memory for the new `IoTHubClient` instance fails, then `IoTHubClient_CreateFromDeviceAuth` shall return `NULL`. **] */
+        /* Codes_SRS_IOTHUBCLIENT_12_022: [** `IoTHubClient_CreateFromDeviceAuth` shall create a lock object to be used later for serializing IoTHubClient calls. **] */
+        /* Codes_SRS_IOTHUBCLIENT_12_023: [** If creating the lock fails, then IoTHubClient_CreateFromDeviceAuth shall return NULL. **] */
+        /* Codes_SRS_IOTHUBCLIENT_12_024: [** If IoTHubClient_CreateFromDeviceAuth fails, all resources allocated by it shall be freed. **] */
+        /* Codes_SRS_IOTHUBCLIENT_12_025: [** `IoTHubClient_CreateFromDeviceAuth` shall instantiate a new `IoTHubClientCore_LL` instance by calling `IoTHubClientCore_LL_CreateFromDeviceAuth` and passing iothub_uri, device_id and protocol argument.  **] */
+        result = create_iothub_instance(CREATE_HUB_INSTANCE_FROM_DEVICE_AUTH, NULL, NULL, NULL, protocol, iothub_uri, device_id);
+    }
+    return result;
+}
+
+#ifdef USE_EDGE_MODULES
+IOTHUB_CLIENT_CORE_HANDLE IoTHubClientCore_CreateFromEnvironment(IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol)
+{
+    return create_iothub_instance(CREATE_HUB_INSTANCE_FROM_EDGE_ENVIRONMENT, NULL, NULL, NULL, protocol, NULL, NULL);
+}
+#endif
+
+
+/* Codes_SRS_IOTHUBCLIENT_01_005: [IoTHubClient_Destroy shall free all resources associated with the iotHubClientHandle instance.] */
+void IoTHubClientCore_Destroy(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle)
+{
+    /* Codes_SRS_IOTHUBCLIENT_01_008: [IoTHubClient_Destroy shall do nothing if parameter iotHubClientHandle is NULL.] */
+    if (iotHubClientHandle != NULL)
+    {
+        bool joinClientThread;
+        bool joinTransportThread;
+        size_t vector_size;
+
+        IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_CORE_INSTANCE*)iotHubClientHandle;
+
+        if (iotHubClientInstance->TransportHandle != NULL)
+        {
+            /*Codes_SRS_IOTHUBCLIENT_01_007: [ The thread created as part of executing IoTHubClient_SendEventAsync or IoTHubClient_SetNotificationMessageCallback shall be joined. ]*/
+            joinTransportThread = IoTHubTransport_SignalEndWorkerThread(iotHubClientInstance->TransportHandle, iotHubClientHandle);
+        }
+        else
+        {
+            joinTransportThread = false;
+        }
+
+        /*Codes_SRS_IOTHUBCLIENT_02_043: [ IoTHubClient_Destroy shall lock the serializing lock and signal the worker thread (if any) to end ]*/
+        if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK)
+        {
+            LogError("unable to Lock - - will still proceed to try to end the thread without locking");
+        }
+
+        if (iotHubClientInstance->ThreadHandle != NULL)
+        {
+            iotHubClientInstance->StopThread = 1;
+            joinClientThread = true;
+        }
+        else
+        {
+            joinClientThread = false;
+        }
+
+        /*Codes_SRS_IOTHUBCLIENT_02_045: [ IoTHubClient_Destroy shall unlock the serializing lock. ]*/
+        if (Unlock(iotHubClientInstance->LockHandle) != LOCK_OK)
+        {
+            LogError("unable to Unlock");
+        }
+
+        if (joinClientThread == true)
+        {
+            int res;
+            /*Codes_SRS_IOTHUBCLIENT_01_007: [ The thread created as part of executing IoTHubClient_SendEventAsync or IoTHubClient_SetNotificationMessageCallback shall be joined. ]*/
+            if (ThreadAPI_Join(iotHubClientInstance->ThreadHandle, &res) != THREADAPI_OK)
+            {
+                LogError("ThreadAPI_Join failed");
+            }
+        }
+
+        if (joinTransportThread == true)
+        {
+            /*Codes_SRS_IOTHUBCLIENT_01_007: [ The thread created as part of executing IoTHubClient_SendEventAsync or IoTHubClient_SetNotificationMessageCallback shall be joined. ]*/
+            IoTHubTransport_JoinWorkerThread(iotHubClientInstance->TransportHandle, iotHubClientHandle);
+        }
+
+        if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK)
+        {
+            LogError("unable to Lock - - will still proceed to try to end the thread without locking");
+        }
+
+        /*Codes_SRS_IOTHUBCLIENT_02_069: [ IoTHubClient_Destroy shall free all data created by IoTHubClient_UploadToBlobAsync ]*/
+        /*wait for all uploading threads to finish*/
+        while (singlylinkedlist_get_head_item(iotHubClientInstance->httpWorkerThreadInfoList) != NULL)
+        {
+            garbageCollectorImpl(iotHubClientInstance);
+        }
+
+        if (iotHubClientInstance->httpWorkerThreadInfoList != NULL)
+        {
+            singlylinkedlist_destroy(iotHubClientInstance->httpWorkerThreadInfoList);
+        }
+
+        /* Codes_SRS_IOTHUBCLIENT_01_006: [That includes destroying the IoTHubClientCore_LL instance by calling IoTHubClientCore_LL_Destroy.] */
+        IoTHubClientCore_LL_Destroy(iotHubClientInstance->IoTHubClientLLHandle);
+
+        if (Unlock(iotHubClientInstance->LockHandle) != LOCK_OK)
+        {
+            LogError("unable to Unlock");
+        }
+
+
+        vector_size = VECTOR_size(iotHubClientInstance->saved_user_callback_list);
+        size_t index = 0;
+        for (index = 0; index < vector_size; index++)
+        {
+            USER_CALLBACK_INFO* queue_cb_info = (USER_CALLBACK_INFO*)VECTOR_element(iotHubClientInstance->saved_user_callback_list, index);
+            if (queue_cb_info != NULL)
+            {
+                if ((queue_cb_info->type == CALLBACK_TYPE_DEVICE_METHOD) || (queue_cb_info->type == CALLBACK_TYPE_INBOUD_DEVICE_METHOD))
+                {
+                    STRING_delete(queue_cb_info->iothub_callback.method_cb_info.method_name);
+                    BUFFER_delete(queue_cb_info->iothub_callback.method_cb_info.payload);
+                }
+                else if (queue_cb_info->type == CALLBACK_TYPE_DEVICE_TWIN)
+                {
+                    if (queue_cb_info->iothub_callback.dev_twin_cb_info.payLoad != NULL)
+                    {
+                        free(queue_cb_info->iothub_callback.dev_twin_cb_info.payLoad);
+                    }
+                }
+                else if (queue_cb_info->type == CALLBACK_TYPE_EVENT_CONFIRM)
+                {
+                    if (queue_cb_info->iothub_callback.event_confirm_cb_info.eventConfirmationCallback)
+                    {
+                        queue_cb_info->iothub_callback.event_confirm_cb_info.eventConfirmationCallback(queue_cb_info->iothub_callback.event_confirm_cb_info.confirm_result, queue_cb_info->userContextCallback);
+                    }
+                }
+                else if (queue_cb_info->type == CALLBACK_TYPE_REPORTED_STATE)
+                {
+                    if (queue_cb_info->iothub_callback.reported_state_cb_info.reportedStateCallback)
+                    {
+                        queue_cb_info->iothub_callback.reported_state_cb_info.reportedStateCallback(queue_cb_info->iothub_callback.reported_state_cb_info.status_code, queue_cb_info->userContextCallback);
+                    }
+                }
+            }
+        }
+        VECTOR_destroy(iotHubClientInstance->saved_user_callback_list);
+
+        if (iotHubClientInstance->TransportHandle == NULL)
+        {
+            /* Codes_SRS_IOTHUBCLIENT_01_032: [If the lock was allocated in IoTHubClient_Create, it shall be also freed..] */
+            Lock_Deinit(iotHubClientInstance->LockHandle);
+        }
+        if (iotHubClientInstance->devicetwin_user_context != NULL)
+        {
+            free(iotHubClientInstance->devicetwin_user_context);
+        }
+        if (iotHubClientInstance->connection_status_user_context != NULL)
+        {
+            free(iotHubClientInstance->connection_status_user_context);
+        }
+        if (iotHubClientInstance->message_user_context != NULL)
+        {
+            free(iotHubClientInstance->message_user_context);
+        }
+        if (iotHubClientInstance->method_user_context != NULL)
+        {
+            free(iotHubClientInstance->method_user_context);
+        }
+        free(iotHubClientInstance);
+    }
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_SendEventAsync(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, IOTHUB_MESSAGE_HANDLE eventMessageHandle, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK eventConfirmationCallback, void* userContextCallback)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    if (iotHubClientHandle == NULL)
+    {
+        /* Codes_SRS_IOTHUBCLIENT_01_011: [If iotHubClientHandle is NULL, IoTHubClient_SendEventAsync shall return IOTHUB_CLIENT_INVALID_ARG.] */
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LogError("NULL iothubClientHandle");
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_CORE_INSTANCE*)iotHubClientHandle;
+
+        /* Codes_SRS_IOTHUBCLIENT_01_009: [IoTHubClient_SendEventAsync shall start the worker thread if it was not previously started.] */
+        if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK)
+        {
+            /* Codes_SRS_IOTHUBCLIENT_01_010: [If starting the thread fails, IoTHubClient_SendEventAsync shall return IOTHUB_CLIENT_ERROR.] */
+            result = IOTHUB_CLIENT_ERROR;
+            LogError("Could not start worker thread");
+        }
+        else
+        {
+            /* Codes_SRS_IOTHUBCLIENT_01_025: [IoTHubClient_SendEventAsync shall be made thread-safe by using the lock created in IoTHubClient_Create.] */
+            if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK)
+            {
+                /* Codes_SRS_IOTHUBCLIENT_01_026: [If acquiring the lock fails, IoTHubClient_SendEventAsync shall return IOTHUB_CLIENT_ERROR.] */
+                result = IOTHUB_CLIENT_ERROR;
+                LogError("Could not acquire lock");
+            }
+            else
+            {
+                if (iotHubClientInstance->created_with_transport_handle != 0 || eventConfirmationCallback == NULL)
+                {
+                    result = IoTHubClientCore_LL_SendEventAsync(iotHubClientInstance->IoTHubClientLLHandle, eventMessageHandle, eventConfirmationCallback, userContextCallback);
+                }
+                else
+                {
+                    /* Codes_SRS_IOTHUBCLIENT_07_001: [ IoTHubClient_SendEventAsync shall allocate a IOTHUB_QUEUE_CONTEXT object to be sent to the IoTHubClientCore_LL_SendEventAsync function as a user context. ] */
+                    IOTHUB_QUEUE_CONTEXT* queue_context = (IOTHUB_QUEUE_CONTEXT*)malloc(sizeof(IOTHUB_QUEUE_CONTEXT));
+                    if (queue_context == NULL)
+                    {
+                        result = IOTHUB_CLIENT_ERROR;
+                        LogError("Failed allocating QUEUE_CONTEXT");
+                    }
+                    else
+                    {
+                        queue_context->iotHubClientHandle = iotHubClientInstance;
+                        queue_context->userContextCallback = userContextCallback;
+                        queue_context->callbackFunction.eventConfirmationCallback = eventConfirmationCallback;
+                        /* Codes_SRS_IOTHUBCLIENT_01_012: [IoTHubClient_SendEventAsync shall call IoTHubClientCore_LL_SendEventAsync, while passing the IoTHubClientCore_LL handle created by IoTHubClient_Create and the parameters eventMessageHandle, eventConfirmationCallback and userContextCallback.] */
+                        /* Codes_SRS_IOTHUBCLIENT_01_013: [When IoTHubClientCore_LL_SendEventAsync is called, IoTHubClient_SendEventAsync shall return the result of IoTHubClientCore_LL_SendEventAsync.] */
+                        result = IoTHubClientCore_LL_SendEventAsync(iotHubClientInstance->IoTHubClientLLHandle, eventMessageHandle, iothub_ll_event_confirm_callback, queue_context);
+                        if (result != IOTHUB_CLIENT_OK)
+                        {
+                            LogError("IoTHubClientCore_LL_SendEventAsync failed");
+                            free(queue_context);
+                        }
+                    }
+                }
+
+                /* Codes_SRS_IOTHUBCLIENT_01_025: [IoTHubClient_SendEventAsync shall be made thread-safe by using the lock created in IoTHubClient_Create.] */
+                (void)Unlock(iotHubClientInstance->LockHandle);
+            }
+        }
+    }
+
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_GetSendStatus(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, IOTHUB_CLIENT_STATUS *iotHubClientStatus)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    if (iotHubClientHandle == NULL)
+    {
+        /* Codes_SRS_IOTHUBCLIENT_01_023: [If iotHubClientHandle is NULL, IoTHubClient_ GetSendStatus shall return IOTHUB_CLIENT_INVALID_ARG.] */
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LogError("NULL iothubClientHandle");
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_CORE_INSTANCE*)iotHubClientHandle;
+
+        /* Codes_SRS_IOTHUBCLIENT_01_033: [IoTHubClient_GetSendStatus shall be made thread-safe by using the lock created in IoTHubClient_Create.] */
+        if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK)
+        {
+            /* Codes_SRS_IOTHUBCLIENT_01_034: [If acquiring the lock fails, IoTHubClient_GetSendStatus shall return IOTHUB_CLIENT_ERROR.] */
+            result = IOTHUB_CLIENT_ERROR;
+            LogError("Could not acquire lock");
+        }
+        else
+        {
+            /* Codes_SRS_IOTHUBCLIENT_01_022: [IoTHubClient_GetSendStatus shall call IoTHubClientCore_LL_GetSendStatus, while passing the IoTHubClientCore_LL handle created by IoTHubClient_Create and the parameter iotHubClientStatus.] */
+            /* Codes_SRS_IOTHUBCLIENT_01_024: [Otherwise, IoTHubClient_GetSendStatus shall return the result of IoTHubClientCore_LL_GetSendStatus.] */
+            result = IoTHubClientCore_LL_GetSendStatus(iotHubClientInstance->IoTHubClientLLHandle, iotHubClientStatus);
+
+            /* Codes_SRS_IOTHUBCLIENT_01_033: [IoTHubClient_GetSendStatus shall be made thread-safe by using the lock created in IoTHubClient_Create.] */
+            (void)Unlock(iotHubClientInstance->LockHandle);
+        }
+    }
+
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_SetMessageCallback(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC messageCallback, void* userContextCallback)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    if (iotHubClientHandle == NULL)
+    {
+        /* Codes_SRS_IOTHUBCLIENT_01_016: [If iotHubClientHandle is NULL, IoTHubClient_SetMessageCallback shall return IOTHUB_CLIENT_INVALID_ARG.] */
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LogError("NULL iothubClientHandle");
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_CORE_INSTANCE*)iotHubClientHandle;
+
+        /* Codes_SRS_IOTHUBCLIENT_01_014: [IoTHubClient_SetMessageCallback shall start the worker thread if it was not previously started.] */
+        if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK)
+        {
+            /* Codes_SRS_IOTHUBCLIENT_01_015: [If starting the thread fails, IoTHubClient_SetMessageCallback shall return IOTHUB_CLIENT_ERROR.] */
+            result = IOTHUB_CLIENT_ERROR;
+            LogError("Could not start worker thread");
+        }
+        else
+        {
+            /* Codes_SRS_IOTHUBCLIENT_01_027: [IoTHubClient_SetMessageCallback shall be made thread-safe by using the lock created in IoTHubClient_Create.] */
+            if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK)
+            {
+                /* Codes_SRS_IOTHUBCLIENT_01_028: [If acquiring the lock fails, IoTHubClient_SetMessageCallback shall return IOTHUB_CLIENT_ERROR.] */
+                result = IOTHUB_CLIENT_ERROR;
+                LogError("Could not acquire lock");
+            }
+            else
+            {
+                if (iotHubClientInstance->created_with_transport_handle == 0)
+                {
+                    iotHubClientInstance->message_callback = messageCallback;
+                }
+                if (iotHubClientInstance->message_user_context != NULL)
+                {
+                    free(iotHubClientInstance->message_user_context);
+                    iotHubClientInstance->message_user_context = NULL;
+                }
+                if (messageCallback == NULL)
+                {
+                    result = IoTHubClientCore_LL_SetMessageCallback_Ex(iotHubClientInstance->IoTHubClientLLHandle, NULL, iotHubClientInstance->message_user_context);
+                }
+                else if (iotHubClientInstance->created_with_transport_handle != 0)
+                {
+                    result = IoTHubClientCore_LL_SetMessageCallback(iotHubClientInstance->IoTHubClientLLHandle, messageCallback, userContextCallback);
+                }
+                else
+                {
+                    iotHubClientInstance->message_user_context = (IOTHUB_QUEUE_CONTEXT*)malloc(sizeof(IOTHUB_QUEUE_CONTEXT));
+                    if (iotHubClientInstance->message_user_context == NULL)
+                    {
+                        result = IOTHUB_CLIENT_ERROR;
+                        LogError("Failed allocating QUEUE_CONTEXT");
+                    }
+                    else
+                    {
+                        iotHubClientInstance->message_user_context->iotHubClientHandle = iotHubClientHandle;
+                        iotHubClientInstance->message_user_context->userContextCallback = userContextCallback;
+
+                        /* Codes_SRS_IOTHUBCLIENT_01_017: [IoTHubClient_SetMessageCallback shall call IoTHubClientCore_LL_SetMessageCallback_Ex, while passing the IoTHubClientCore_LL handle created by IoTHubClient_Create and the local iothub_ll_message_callback wrapper of messageCallback and userContextCallback.] */
+                        /* Codes_SRS_IOTHUBCLIENT_01_018: [When IoTHubClientCore_LL_SetMessageCallback_Ex is called, IoTHubClient_SetMessageCallback shall return the result of IoTHubClientCore_LL_SetMessageCallback_Ex.] */
+                        result = IoTHubClientCore_LL_SetMessageCallback_Ex(iotHubClientInstance->IoTHubClientLLHandle, iothub_ll_message_callback, iotHubClientInstance->message_user_context);
+                        if (result != IOTHUB_CLIENT_OK)
+                        {
+                            LogError("IoTHubClientCore_LL_SetMessageCallback failed");
+                            free(iotHubClientInstance->message_user_context);
+                            iotHubClientInstance->message_user_context = NULL;
+                        }
+                    }
+                }
+
+                /* Codes_SRS_IOTHUBCLIENT_01_027: [IoTHubClient_SetMessageCallback shall be made thread-safe by using the lock created in IoTHubClient_Create.] */
+                (void)Unlock(iotHubClientInstance->LockHandle);
+            }
+        }
+    }
+
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_SetConnectionStatusCallback(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, IOTHUB_CLIENT_CONNECTION_STATUS_CALLBACK connectionStatusCallback, void * userContextCallback)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    if (iotHubClientHandle == NULL)
+    {
+        /* Codes_SRS_IOTHUBCLIENT_25_076: [** If `iotHubClientHandle` is `NULL`, `IoTHubClient_SetRetryPolicy` shall return `IOTHUB_CLIENT_INVALID_ARG`. ] */
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LogError("NULL iothubClientHandle");
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_CORE_INSTANCE*)iotHubClientHandle;
+
+        /* Codes_SRS_IOTHUBCLIENT_25_081: [ `IoTHubClient_SetConnectionStatusCallback` shall start the worker thread if it was not previously started. ]*/
+        if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK)
+        {
+            /* Codes_SRS_IOTHUBCLIENT_25_083: [ If starting the thread fails, `IoTHubClient_SetConnectionStatusCallback` shall return `IOTHUB_CLIENT_ERROR`. ]*/
+            result = IOTHUB_CLIENT_ERROR;
+            LogError("Could not start worker thread");
+        }
+        else
+        {
+            /* Codes_SRS_IOTHUBCLIENT_25_087: [ `IoTHubClient_SetConnectionStatusCallback` shall be made thread-safe by using the lock created in `IoTHubClient_Create`. ] */
+            if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK)
+            {
+                /* Codes_SRS_IOTHUBCLIENT_25_088: [ If acquiring the lock fails, `IoTHubClient_SetConnectionStatusCallback` shall return `IOTHUB_CLIENT_ERROR`. ]*/
+                result = IOTHUB_CLIENT_ERROR;
+                LogError("Could not acquire lock");
+            }
+            else
+            {
+                if (iotHubClientInstance->created_with_transport_handle == 0)
+                {
+                    iotHubClientInstance->connection_status_callback = connectionStatusCallback;
+                }
+
+                if (iotHubClientInstance->created_with_transport_handle != 0 || connectionStatusCallback == NULL)
+                {
+                    /* Codes_SRS_IOTHUBCLIENT_25_085: [ `IoTHubClient_SetConnectionStatusCallback` shall call `IoTHubClientCore_LL_SetConnectionStatusCallback`, while passing the `IoTHubClientCore_LL` handle created by `IoTHubClient_Create` and the parameters `connectionStatusCallback` and `userContextCallback`. ]*/
+                    result = IoTHubClientCore_LL_SetConnectionStatusCallback(iotHubClientInstance->IoTHubClientLLHandle, connectionStatusCallback, userContextCallback);
+                }
+                else
+                {
+                    if (iotHubClientInstance->connection_status_user_context != NULL)
+                    {
+                        free(iotHubClientInstance->connection_status_user_context);
+                    }
+                    iotHubClientInstance->connection_status_user_context = (IOTHUB_QUEUE_CONTEXT*)malloc(sizeof(IOTHUB_QUEUE_CONTEXT));
+                    if (iotHubClientInstance->connection_status_user_context == NULL)
+                    {
+                        result = IOTHUB_CLIENT_ERROR;
+                        LogError("Failed allocating QUEUE_CONTEXT");
+                    }
+                    else
+                    {
+                        iotHubClientInstance->connection_status_user_context->iotHubClientHandle = iotHubClientInstance;
+                        iotHubClientInstance->connection_status_user_context->userContextCallback = userContextCallback;
+
+                        /* Codes_SRS_IOTHUBCLIENT_25_085: [ `IoTHubClient_SetConnectionStatusCallback` shall call `IoTHubClientCore_LL_SetConnectionStatusCallback`, while passing the `IoTHubClientCore_LL` handle created by `IoTHubClient_Create` and the parameters `connectionStatusCallback` and `userContextCallback`. ]*/
+                        result = IoTHubClientCore_LL_SetConnectionStatusCallback(iotHubClientInstance->IoTHubClientLLHandle, iothub_ll_connection_status_callback, iotHubClientInstance->connection_status_user_context);
+                        if (result != IOTHUB_CLIENT_OK)
+                        {
+                            LogError("IoTHubClientCore_LL_SetConnectionStatusCallback failed");
+                            free(iotHubClientInstance->connection_status_user_context);
+                            iotHubClientInstance->connection_status_user_context = NULL;
+                        }
+                    }
+                }
+                (void)Unlock(iotHubClientInstance->LockHandle);
+            }
+        }
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_SetRetryPolicy(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY retryPolicy, size_t retryTimeoutLimitInSeconds)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    if (iotHubClientHandle == NULL)
+    {
+        /* Codes_SRS_IOTHUBCLIENT_25_076: [** If `iotHubClientHandle` is `NULL`, `IoTHubClient_SetRetryPolicy` shall return `IOTHUB_CLIENT_INVALID_ARG`. ] */
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LogError("NULL iothubClientHandle");
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_CORE_INSTANCE*)iotHubClientHandle;
+
+        /* Codes_SRS_IOTHUBCLIENT_25_073: [ `IoTHubClient_SetRetryPolicy` shall start the worker thread if it was not previously started. ] */
+        if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK)
+        {
+            /* Codes_SRS_IOTHUBCLIENT_25_075: [ If starting the thread fails, `IoTHubClient_SetRetryPolicy` shall return `IOTHUB_CLIENT_ERROR`. ]*/
+            result = IOTHUB_CLIENT_ERROR;
+            LogError("Could not start worker thread");
+        }
+        else
+        {
+            /* Codes_SRS_IOTHUBCLIENT_25_079: [ `IoTHubClient_SetRetryPolicy` shall be made thread-safe by using the lock created in `IoTHubClient_Create`.] */
+            if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK)
+            {
+                /* Codes_SRS_IOTHUBCLIENT_25_080: [ If acquiring the lock fails, `IoTHubClient_SetRetryPolicy` shall return `IOTHUB_CLIENT_ERROR`. ]*/
+                result = IOTHUB_CLIENT_ERROR;
+                LogError("Could not acquire lock");
+            }
+            else
+            {
+                /* Codes_SRS_IOTHUBCLIENT_25_077: [ `IoTHubClient_SetRetryPolicy` shall call `IoTHubClientCore_LL_SetRetryPolicy`, while passing the `IoTHubClientCore_LL` handle created by `IoTHubClient_Create` and the parameters `retryPolicy` and `retryTimeoutLimitinSeconds`.]*/
+                result = IoTHubClientCore_LL_SetRetryPolicy(iotHubClientInstance->IoTHubClientLLHandle, retryPolicy, retryTimeoutLimitInSeconds);
+                (void)Unlock(iotHubClientInstance->LockHandle);
+            }
+
+        }
+    }
+
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_GetRetryPolicy(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY* retryPolicy, size_t* retryTimeoutLimitInSeconds)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    if (iotHubClientHandle == NULL)
+    {
+        /* Codes_SRS_IOTHUBCLIENT_25_092: [ If `iotHubClientHandle` is `NULL`, `IoTHubClient_GetRetryPolicy` shall return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LogError("NULL iothubClientHandle");
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_CORE_INSTANCE*)iotHubClientHandle;
+
+        /* Codes_SRS_IOTHUBCLIENT_25_089: [ `IoTHubClient_GetRetryPolicy` shall start the worker thread if it was not previously started.]*/
+        if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK)
+        {
+            /* Codes_SRS_IOTHUBCLIENT_25_091: [ If starting the thread fails, `IoTHubClient_GetRetryPolicy` shall return `IOTHUB_CLIENT_ERROR`.]*/
+            result = IOTHUB_CLIENT_ERROR;
+            LogError("Could not start worker thread");
+        }
+        else
+        {
+            /* Codes_SRS_IOTHUBCLIENT_25_095: [ `IoTHubClient_GetRetryPolicy` shall be made thread-safe by using the lock created in `IoTHubClient_Create`. ]*/
+            if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK)
+            {
+                /* Codes_SRS_IOTHUBCLIENT_25_096: [ If acquiring the lock fails, `IoTHubClient_GetRetryPolicy` shall return `IOTHUB_CLIENT_ERROR`. ]*/
+                result = IOTHUB_CLIENT_ERROR;
+                LogError("Could not acquire lock");
+            }
+            else
+            {
+                /* Codes_SRS_IOTHUBCLIENT_25_093: [ `IoTHubClient_GetRetryPolicy` shall call `IoTHubClientCore_LL_GetRetryPolicy`, while passing the `IoTHubClientCore_LL` handle created by `IoTHubClient_Create` and the parameters `connectionStatusCallback` and `userContextCallback`.]*/
+                result = IoTHubClientCore_LL_GetRetryPolicy(iotHubClientInstance->IoTHubClientLLHandle, retryPolicy, retryTimeoutLimitInSeconds);
+                (void)Unlock(iotHubClientInstance->LockHandle);
+            }
+        }
+    }
+
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_GetLastMessageReceiveTime(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, time_t* lastMessageReceiveTime)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    if (iotHubClientHandle == NULL)
+    {
+        /* Codes_SRS_IOTHUBCLIENT_01_020: [If iotHubClientHandle is NULL, IoTHubClient_GetLastMessageReceiveTime shall return IOTHUB_CLIENT_INVALID_ARG.] */
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LogError("NULL iothubClientHandle");
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_CORE_INSTANCE*)iotHubClientHandle;
+
+        /* Codes_SRS_IOTHUBCLIENT_01_035: [IoTHubClient_GetLastMessageReceiveTime shall be made thread-safe by using the lock created in IoTHubClient_Create.] */
+        if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK)
+        {
+            /* Codes_SRS_IOTHUBCLIENT_01_036: [If acquiring the lock fails, IoTHubClient_GetLastMessageReceiveTime shall return IOTHUB_CLIENT_ERROR.] */
+            result = IOTHUB_CLIENT_ERROR;
+            LogError("Could not acquire lock");
+        }
+        else
+        {
+            /* Codes_SRS_IOTHUBCLIENT_01_019: [IoTHubClient_GetLastMessageReceiveTime shall call IoTHubClientCore_LL_GetLastMessageReceiveTime, while passing the IoTHubClientCore_LL handle created by IoTHubClient_Create and the parameter lastMessageReceiveTime.] */
+            /* Codes_SRS_IOTHUBCLIENT_01_021: [Otherwise, IoTHubClient_GetLastMessageReceiveTime shall return the result of IoTHubClientCore_LL_GetLastMessageReceiveTime.] */
+            result = IoTHubClientCore_LL_GetLastMessageReceiveTime(iotHubClientInstance->IoTHubClientLLHandle, lastMessageReceiveTime);
+
+            /* Codes_SRS_IOTHUBCLIENT_01_035: [IoTHubClient_GetLastMessageReceiveTime shall be made thread-safe by using the lock created in IoTHubClient_Create.] */
+            (void)Unlock(iotHubClientInstance->LockHandle);
+        }
+    }
+
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_SetOption(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, const char* optionName, const void* value)
+{
+    IOTHUB_CLIENT_RESULT result;
+    /*Codes_SRS_IOTHUBCLIENT_02_034: [If parameter iotHubClientHandle is NULL then IoTHubClient_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.] */
+    /*Codes_SRS_IOTHUBCLIENT_02_035: [ If parameter optionName is NULL then IoTHubClient_SetOption shall return IOTHUB_CLIENT_INVALID_ARG. ]*/
+    /*Codes_SRS_IOTHUBCLIENT_02_036: [ If parameter value is NULL then IoTHubClient_SetOption shall return IOTHUB_CLIENT_INVALID_ARG. ]*/
+    if (
+        (iotHubClientHandle == NULL) ||
+        (optionName == NULL) ||
+        (value == NULL)
+        )
+    {
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LogError("invalid arg (NULL)");
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_CORE_INSTANCE*)iotHubClientHandle;
+
+        /* Codes_SRS_IOTHUBCLIENT_01_041: [ IoTHubClient_SetOption shall be made thread-safe by using the lock created in IoTHubClient_Create. ]*/
+        if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK)
+        {
+            /* Codes_SRS_IOTHUBCLIENT_01_042: [ If acquiring the lock fails, IoTHubClient_SetOption shall return IOTHUB_CLIENT_ERROR. ]*/
+            result = IOTHUB_CLIENT_ERROR;
+            LogError("Could not acquire lock");
+        }
+        else
+        {
+            /* Codes_SRS_IOTHUBCLIENT_41_001 [ If parameter `optionName` is `OPTION_DO_WORK_FREQUENCY_IN_MS` then `IoTHubClient_SetOption` shall set `do_work_freq_ms` parameter of `IoTHubClientInstance` ]*/
+            if (strcmp(OPTION_DO_WORK_FREQUENCY_IN_MS, optionName) == 0)
+            {
+                /* Codes_SRS_IOTHUBCLIENT_41_003: [ The value for `OPTION_DO_WORK_FREQUENCY_IN_MS` shall be limited to 100 to follow SDK best practices by not reducing the DoWork frequency below 10 Hz ]*/
+                if (0 < * (unsigned int *)value && * (unsigned int *)value <= 100)
+                {
+                    /* Codes_SRS_IOTHUBCLIENT_41_004: [ If `currentMessageTimeout` is not greater than `do_work_freq_ms`, `IotHubClientCore_SetOption` shall return `IOTHUB_CLIENT_INVALID_ARG` ]*/
+                    /* Codes_SRS_IOTHUBCLIENT_41_007: [** If parameter `optionName` is `OPTION_DO_WORK_FREQUENCY_IN_MS` then `value` should be of type `tickcounter_ms_t *`. **]*/
+                    if ((!iotHubClientInstance->currentMessageTimeout) || ( * (tickcounter_ms_t *)value < iotHubClientInstance->currentMessageTimeout))
+                    {
+                        iotHubClientInstance->do_work_freq_ms = * (tickcounter_ms_t *)value;
+                        result = IOTHUB_CLIENT_OK;
+                    }
+                    else
+                    {
+                        result = IOTHUB_CLIENT_INVALID_ARG;
+                        LogError("Invalid value: OPTION_DO_WORK_FREQUENCY_IN_MS cannot exceed that of OPTION_MESSAGE_TIMEOUT.");
+                    }
+                }
+                else
+                {
+                    result = IOTHUB_CLIENT_INVALID_ARG;
+                    LogError("Invalid value: OPTION_DO_WORK_FREQUENCY_IN_MS cannot exceed 100 ms. If you wish to reduce the frequency further, consider using the LL layer.");
+                }
+            }
+            /* Codes_SRS_IOTHUBCLIENT_41_005: [ If parameter `optionName` is `OPTION_MESSAGE_TIMEOUT` then `IoTHubClientCore_SetOption` shall set `currentMessageTimeout` parameter of `IoTHubClientInstance` ]*/
+            else if (strcmp(OPTION_MESSAGE_TIMEOUT, optionName) == 0)
+            {
+                iotHubClientInstance->currentMessageTimeout = * (tickcounter_ms_t *)value;
+
+                /* Codes_SRS_IOTHUBCLIENT_41_004: [ If `currentMessageTimeout` is not greater than `do_work_freq_ms`, `IotHubClientCore_SetOption` shall return `IOTHUB_CLIENT_INVALID_ARG` ]*/
+				if (iotHubClientInstance->do_work_freq_ms < iotHubClientInstance->currentMessageTimeout)
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_41_006: [ If parameter `optionName` is `OPTION_MESSAGE_TIMEOUT` then `IoTHubClientCore_SetOption` shall call `IoTHubClientCore_LL_SetOption` passing the same parameters and return what IoTHubClientCore_LL_SetOption returns. ] */
+                    result = IoTHubClientCore_LL_SetOption(iotHubClientInstance->IoTHubClientLLHandle, optionName, value);
+                    if (result != IOTHUB_CLIENT_OK)
+                    {
+                        LogError("IoTHubClientCore_LL_SetOption failed");
+                    }
+                }
+                else
+                {
+                    result = IOTHUB_CLIENT_INVALID_ARG;
+                    LogError("invalid value: OPTION_MESSAGE_TIMEOUT cannot exceed the value of OPTION_DO_WORK_FREQUENCY_IN_MS ");
+                }
+            }
+            else
+            {
+                /*Codes_SRS_IOTHUBCLIENT_02_038: [If optionName doesn't match one of the options handled by this module then IoTHubClient_SetOption shall call IoTHubClientCore_LL_SetOption passing the same parameters and return what IoTHubClientCore_LL_SetOption returns.] */
+                result = IoTHubClientCore_LL_SetOption(iotHubClientInstance->IoTHubClientLLHandle, optionName, value);
+                if (result != IOTHUB_CLIENT_OK)
+                {
+                    LogError("IoTHubClientCore_LL_SetOption failed");
+                }
+            }
+            (void)Unlock(iotHubClientInstance->LockHandle);
+        }
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_SetDeviceTwinCallback(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK deviceTwinCallback, void* userContextCallback)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    /*Codes_SRS_IOTHUBCLIENT_10_001: [** `IoTHubClient_SetDeviceTwinCallback` shall fail and return `IOTHUB_CLIENT_INVALID_ARG` if parameter `iotHubClientHandle` is `NULL`. ]*/
+    if (iotHubClientHandle == NULL)
+    {
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LogError("invalid arg (NULL)");
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_CORE_INSTANCE*)iotHubClientHandle;
+
+        /*Codes_SRS_IOTHUBCLIENT_10_003: [** If the transport connection is shared, the thread shall be started by calling `IoTHubTransport_StartWorkerThread`. ]*/
+        if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK)
+        {
+            /*Codes_SRS_IOTHUBCLIENT_10_004: [** If starting the thread fails, `IoTHubClient_SetDeviceTwinCallback` shall return `IOTHUB_CLIENT_ERROR`. ]*/
+            result = IOTHUB_CLIENT_ERROR;
+            LogError("Could not start worker thread");
+        }
+        else
+        {
+            /*Codes_SRS_IOTHUBCLIENT_10_020: [** `IoTHubClient_SetDeviceTwinCallback` shall be made thread - safe by using the lock created in IoTHubClient_Create. ]*/
+            if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK)
+            {
+                /*Codes_SRS_IOTHUBCLIENT_10_002: [** If acquiring the lock fails, `IoTHubClient_SetDeviceTwinCallback` shall return `IOTHUB_CLIENT_ERROR`. ]*/
+                result = IOTHUB_CLIENT_ERROR;
+                LogError("Could not acquire lock");
+            }
+            else
+            {
+                if (iotHubClientInstance->created_with_transport_handle == 0)
+                {
+                    iotHubClientInstance->desired_state_callback = deviceTwinCallback;
+                }
+
+                if (iotHubClientInstance->created_with_transport_handle != 0 || deviceTwinCallback == NULL)
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_10_005: [** `IoTHubClientCore_LL_SetDeviceTwinCallback` shall call `IoTHubClientCore_LL_SetDeviceTwinCallback`, while passing the `IoTHubClientCore_LL handle` created by `IoTHubClientCore_LL_Create` along with the parameters `reportedStateCallback` and `userContextCallback`. ]*/
+                    result = IoTHubClientCore_LL_SetDeviceTwinCallback(iotHubClientInstance->IoTHubClientLLHandle, deviceTwinCallback, userContextCallback);
+                }
+                else
+                {
+                    if (iotHubClientInstance->devicetwin_user_context != NULL)
+                    {
+                        free(iotHubClientInstance->devicetwin_user_context);
+                    }
+
+                    /*Codes_SRS_IOTHUBCLIENT_07_002: [ IoTHubClient_SetDeviceTwinCallback shall allocate a IOTHUB_QUEUE_CONTEXT object to be sent to the IoTHubClientCore_LL_SetDeviceTwinCallback function as a user context. ]*/
+                    iotHubClientInstance->devicetwin_user_context = (IOTHUB_QUEUE_CONTEXT*)malloc(sizeof(IOTHUB_QUEUE_CONTEXT));
+                    if (iotHubClientInstance->devicetwin_user_context == NULL)
+                    {
+                        result = IOTHUB_CLIENT_ERROR;
+                        LogError("Failed allocating QUEUE_CONTEXT");
+                    }
+                    else
+                    {
+                        /*Codes_SRS_IOTHUBCLIENT_10_005: [** `IoTHubClientCore_LL_SetDeviceTwinCallback` shall call `IoTHubClientCore_LL_SetDeviceTwinCallback`, while passing the `IoTHubClientCore_LL handle` created by `IoTHubClientCore_LL_Create` along with the parameters `iothub_ll_device_twin_callback` and IOTHUB_QUEUE_CONTEXT variable. ]*/
+                        iotHubClientInstance->devicetwin_user_context->iotHubClientHandle = iotHubClientInstance;
+                        iotHubClientInstance->devicetwin_user_context->userContextCallback = userContextCallback;
+                        result = IoTHubClientCore_LL_SetDeviceTwinCallback(iotHubClientInstance->IoTHubClientLLHandle, iothub_ll_device_twin_callback, iotHubClientInstance->devicetwin_user_context);
+                        if (result != IOTHUB_CLIENT_OK)
+                        {
+                            LogError("IoTHubClientCore_LL_SetDeviceTwinCallback failed");
+                            free(iotHubClientInstance->devicetwin_user_context);
+                            iotHubClientInstance->devicetwin_user_context = NULL;
+                        }
+                    }
+                }
+
+                (void)Unlock(iotHubClientInstance->LockHandle);
+            }
+        }
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_SendReportedState(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, const unsigned char* reportedState, size_t size, IOTHUB_CLIENT_REPORTED_STATE_CALLBACK reportedStateCallback, void* userContextCallback)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    /*Codes_SRS_IOTHUBCLIENT_10_013: [** If `iotHubClientHandle` is `NULL`, `IoTHubClient_SendReportedState` shall return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
+    if (iotHubClientHandle == NULL)
+    {
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LogError("invalid arg (NULL)");
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_CORE_INSTANCE*)iotHubClientHandle;
+
+        /*Codes_SRS_IOTHUBCLIENT_10_015: [** If the transport connection is shared, the thread shall be started by calling `IoTHubTransport_StartWorkerThread`. ]*/
+        if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK)
+        {
+            /*Codes_SRS_IOTHUBCLIENT_10_016: [** If starting the thread fails, `IoTHubClient_SendReportedState` shall return `IOTHUB_CLIENT_ERROR`. ]*/
+            result = IOTHUB_CLIENT_ERROR;
+            LogError("Could not start worker thread");
+        }
+        else
+        {
+            /*Codes_SRS_IOTHUBCLIENT_10_021: [** `IoTHubClient_SendReportedState` shall be made thread-safe by using the lock created in IoTHubClient_Create. ]*/
+            if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK)
+            {
+                /*Codes_SRS_IOTHUBCLIENT_10_014: [** If acquiring the lock fails, `IoTHubClient_SendReportedState` shall return `IOTHUB_CLIENT_ERROR`. ]*/
+                result = IOTHUB_CLIENT_ERROR;
+                LogError("Could not acquire lock");
+            }
+            else
+            {
+                if (iotHubClientInstance->created_with_transport_handle != 0 || reportedStateCallback == NULL)
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_10_017: [** `IoTHubClient_SendReportedState` shall call `IoTHubClientCore_LL_SendReportedState`, while passing the `IoTHubClientCore_LL handle` created by `IoTHubClientCore_LL_Create` along with the parameters `reportedState`, `size`, `reportedStateCallback`, and `userContextCallback`. ]*/
+                    /*Codes_SRS_IOTHUBCLIENT_10_018: [** When `IoTHubClientCore_LL_SendReportedState` is called, `IoTHubClient_SendReportedState` shall return the result of `IoTHubClientCore_LL_SendReportedState`. **]*/
+                    result = IoTHubClientCore_LL_SendReportedState(iotHubClientInstance->IoTHubClientLLHandle, reportedState, size, reportedStateCallback, userContextCallback);
+                }
+                else
+                {
+                    /* Codes_SRS_IOTHUBCLIENT_07_003: [ IoTHubClient_SendReportedState shall allocate a IOTHUB_QUEUE_CONTEXT object to be sent to the IoTHubClientCore_LL_SendReportedState function as a user context. ] */
+                    IOTHUB_QUEUE_CONTEXT* queue_context = (IOTHUB_QUEUE_CONTEXT*)malloc(sizeof(IOTHUB_QUEUE_CONTEXT));
+                    if (queue_context == NULL)
+                    {
+                        result = IOTHUB_CLIENT_ERROR;
+                        LogError("Failed allocating QUEUE_CONTEXT");
+                    }
+                    else
+                    {
+                        queue_context->iotHubClientHandle = iotHubClientInstance;
+                        queue_context->userContextCallback = userContextCallback;
+                        queue_context->callbackFunction.reportedStateCallback = reportedStateCallback;
+                        /*Codes_SRS_IOTHUBCLIENT_10_017: [** `IoTHubClient_SendReportedState` shall call `IoTHubClientCore_LL_SendReportedState`, while passing the `IoTHubClientCore_LL handle` created by `IoTHubClientCore_LL_Create` along with the parameters `reportedState`, `size`, `iothub_ll_reported_state_callback` and IOTHUB_QUEUE_CONTEXT variable. ]*/
+                        /*Codes_SRS_IOTHUBCLIENT_10_018: [** When `IoTHubClientCore_LL_SendReportedState` is called, `IoTHubClient_SendReportedState` shall return the result of `IoTHubClientCore_LL_SendReportedState`. **]*/
+                        result = IoTHubClientCore_LL_SendReportedState(iotHubClientInstance->IoTHubClientLLHandle, reportedState, size, iothub_ll_reported_state_callback, queue_context);
+                        if (result != IOTHUB_CLIENT_OK)
+                        {
+                            LogError("IoTHubClientCore_LL_SendReportedState failed");
+                            free(queue_context);
+                        }
+                    }
+                }
+
+                (void)Unlock(iotHubClientInstance->LockHandle);
+            }
+        }
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_GetTwinAsync(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK deviceTwinCallback, void* userContextCallback)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    // Codes_SRS_IOTHUBCLIENT_09_009: [ If `iotHubClientHandle` or `deviceTwinCallback` are `NULL`, `IoTHubClientCore_GetTwinAsync` shall return `IOTHUB_CLIENT_INVALID_ARG`. ]
+    if (iotHubClientHandle == NULL || deviceTwinCallback == NULL)
+    {
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LogError("Invalid argument (iotHubClientHandle=%p, deviceTwinCallback=%p)", iotHubClientHandle, deviceTwinCallback);
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_CORE_INSTANCE*)iotHubClientHandle;
+
+        // Codes_SRS_IOTHUBCLIENT_09_010: [ The thread that executes the client  I/O shall be started if not running already. ]
+        if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK)
+        {
+            // Codes_SRS_IOTHUBCLIENT_09_011: [ If starting the thread fails, `IoTHubClientCore_GetTwinAsync` shall return `IOTHUB_CLIENT_ERROR`. ]
+            result = IOTHUB_CLIENT_ERROR;
+            LogError("Could not start worker thread");
+        }
+        else
+        {
+            IOTHUB_QUEUE_CONSOLIDATED_CONTEXT* queueContext;
+
+            if ((queueContext = (IOTHUB_QUEUE_CONSOLIDATED_CONTEXT*)malloc(sizeof(IOTHUB_QUEUE_CONSOLIDATED_CONTEXT))) == NULL)
+            {
+                LogError("Failed creating queue context");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else
+            {
+                queueContext->iotHubClientHandle = iotHubClientHandle;
+                queueContext->userCallback.getTwin = deviceTwinCallback;
+                queueContext->userContext = userContextCallback;
+
+                // Codes_SRS_IOTHUBCLIENT_09_012: [ `IoTHubClientCore_GetTwinAsync` shall be made thread-safe by using the lock created in IoTHubClient_Create. ]
+                if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK)
+                {
+                    // Codes_SRS_IOTHUBCLIENT_09_013: [ If acquiring the lock fails, `IoTHubClientCore_GetTwinAsync` shall return `IOTHUB_CLIENT_ERROR`. ]
+                    result = IOTHUB_CLIENT_ERROR;
+                    LogError("Could not acquire lock");
+                    free(queueContext);
+                }
+                else
+                {
+                    // Codes_SRS_IOTHUBCLIENT_09_014: [ `IoTHubClientCore_GetTwinAsync` shall call `IoTHubClientCore_LL_GetTwinAsync`, passing the `IoTHubClient_LL handle`, `deviceTwinCallback` and `userContextCallback` as arguments ]
+                    // Codes_SRS_IOTHUBCLIENT_09_015: [ When `IoTHubClientCore_LL_GetTwinAsync` is called, `IoTHubClientCore_GetTwinAsync` shall return the result of `IoTHubClientCore_LL_GetTwinAsync`. ]
+                    result = IoTHubClientCore_LL_GetTwinAsync(iotHubClientInstance->IoTHubClientLLHandle, iothub_ll_get_device_twin_async_callback, queueContext);
+
+                    if (result != IOTHUB_CLIENT_OK)
+                    {
+                        LogError("IoTHubClientCore_LL_GetTwinAsync failed");
+                        free(queueContext);
+                    }
+
+                    (void)Unlock(iotHubClientInstance->LockHandle);
+                }
+            }
+        }
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_SetDeviceMethodCallback(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, IOTHUB_CLIENT_DEVICE_METHOD_CALLBACK_ASYNC deviceMethodCallback, void* userContextCallback)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    /*Codes_SRS_IOTHUBCLIENT_12_012: [ If iotHubClientHandle is NULL, IoTHubClient_SetDeviceMethodCallback shall return IOTHUB_CLIENT_INVALID_ARG. ]*/
+    if (iotHubClientHandle == NULL)
+    {
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LogError("invalid arg (NULL)");
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_CORE_INSTANCE*)iotHubClientHandle;
+
+        /*Codes_SRS_IOTHUBCLIENT_12_014: [ If the transport handle is null and the worker thread is not initialized, the thread shall be started by calling IoTHubTransport_StartWorkerThread. ]*/
+        if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK)
+        {
+            /*Codes_SRS_IOTHUBCLIENT_12_015: [ If starting the thread fails, IoTHubClient_SetDeviceMethodCallback shall return IOTHUB_CLIENT_ERROR. ]*/
+            result = IOTHUB_CLIENT_ERROR;
+            LogError("Could not start worker thread");
+        }
+        else
+        {
+            /*Codes_SRS_IOTHUBCLIENT_12_018: [ IoTHubClient_SetDeviceMethodCallback shall be made thread-safe by using the lock created in IoTHubClient_Create. ]*/
+            if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK)
+            {
+                /*Codes_SRS_IOTHUBCLIENT_12_013: [ If acquiring the lock fails, IoTHubClient_SetDeviceMethodCallback shall return IOTHUB_CLIENT_ERROR. ]*/
+                result = IOTHUB_CLIENT_ERROR;
+                LogError("Could not acquire lock");
+            }
+            else
+            {
+                if (iotHubClientInstance->created_with_transport_handle == 0)
+                {
+                    iotHubClientInstance->device_method_callback = deviceMethodCallback;
+                }
+
+                if (iotHubClientInstance->method_user_context)
+                {
+                    free(iotHubClientInstance->method_user_context);
+                    iotHubClientInstance->method_user_context = NULL;
+                }
+                if (deviceMethodCallback == NULL)
+                {
+                    result = IoTHubClientCore_LL_SetDeviceMethodCallback_Ex(iotHubClientInstance->IoTHubClientLLHandle, NULL, NULL);
+                }
+                else
+                {
+                    iotHubClientInstance->method_user_context = (IOTHUB_QUEUE_CONTEXT*)malloc(sizeof(IOTHUB_QUEUE_CONTEXT));
+                    if (iotHubClientInstance->method_user_context == NULL)
+                    {
+                        result = IOTHUB_CLIENT_ERROR;
+                        LogError("Failed allocating QUEUE_CONTEXT");
+                    }
+                    else
+                    {
+                        iotHubClientInstance->method_user_context->iotHubClientHandle = iotHubClientHandle;
+                        iotHubClientInstance->method_user_context->userContextCallback = userContextCallback;
+
+                        /*Codes_SRS_IOTHUBCLIENT_12_016: [ IoTHubClient_SetDeviceMethodCallback shall call IoTHubClientCore_LL_SetDeviceMethodCallback, while passing the IoTHubClientCore_LL_handle created by IoTHubClientCore_LL_Create along with the parameters deviceMethodCallback and userContextCallback. ]*/
+                        /*Codes_SRS_IOTHUBCLIENT_12_017: [ When IoTHubClientCore_LL_SetDeviceMethodCallback is called, IoTHubClient_SetDeviceMethodCallback shall return the result of IoTHubClientCore_LL_SetDeviceMethodCallback. ]*/
+                        result = IoTHubClientCore_LL_SetDeviceMethodCallback_Ex(iotHubClientInstance->IoTHubClientLLHandle, iothub_ll_device_method_callback, iotHubClientInstance->method_user_context);
+                        if (result != IOTHUB_CLIENT_OK)
+                        {
+                            LogError("IoTHubClientCore_LL_SetDeviceMethodCallback_Ex failed");
+                            free(iotHubClientInstance->method_user_context);
+                            iotHubClientInstance->method_user_context = NULL;
+                        }
+                        else
+                        {
+                            iotHubClientInstance->device_method_callback = deviceMethodCallback;
+                        }
+                    }
+                }
+
+                (void)Unlock(iotHubClientInstance->LockHandle);
+            }
+
+        }
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_SetDeviceMethodCallback_Ex(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK inboundDeviceMethodCallback, void* userContextCallback)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    /*Codes_SRS_IOTHUBCLIENT_07_001: [ If iotHubClientHandle is NULL, IoTHubClient_SetDeviceMethodCallback_Ex shall return IOTHUB_CLIENT_INVALID_ARG. ]*/
+    if (iotHubClientHandle == NULL)
+    {
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LogError("invalid arg (NULL)");
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_CORE_INSTANCE*)iotHubClientHandle;
+
+        /*Codes_SRS_IOTHUBCLIENT_07_003: [ If the transport handle is NULL and the worker thread is not initialized, the thread shall be started by calling IoTHubTransport_StartWorkerThread. ]*/
+        if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK)
+        {
+            /*Codes_SRS_IOTHUBCLIENT_07_004: [ If starting the thread fails, IoTHubClient_SetDeviceMethodCallback_Ex shall return IOTHUB_CLIENT_ERROR. ]*/
+            result = IOTHUB_CLIENT_ERROR;
+            LogError("Could not start worker thread");
+        }
+        else
+        {
+            /*Codes_SRS_IOTHUBCLIENT_07_007: [ IoTHubClient_SetDeviceMethodCallback_Ex shall be made thread-safe by using the lock created in IoTHubClient_Create. ]*/
+            if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK)
+            {
+                /*Codes_SRS_IOTHUBCLIENT_07_002: [ If acquiring the lock fails, IoTHubClient_SetDeviceMethodCallback_Ex shall return IOTHUB_CLIENT_ERROR. ]*/
+                result = IOTHUB_CLIENT_ERROR;
+                LogError("Could not acquire lock");
+            }
+            else
+            {
+                if (iotHubClientInstance->created_with_transport_handle == 0)
+                {
+                    iotHubClientInstance->inbound_device_method_callback = inboundDeviceMethodCallback;
+                }
+
+                if (iotHubClientInstance->method_user_context)
+                {
+                    free(iotHubClientInstance->method_user_context);
+                    iotHubClientInstance->method_user_context = NULL;
+                }
+                if (inboundDeviceMethodCallback == NULL)
+                {
+                    /* Codes_SRS_IOTHUBCLIENT_07_008: [ If inboundDeviceMethodCallback is NULL, IoTHubClient_SetDeviceMethodCallback_Ex shall call IoTHubClientCore_LL_SetDeviceMethodCallback_Ex, passing NULL for the iothub_ll_inbound_device_method_callback. ] */
+                    result = IoTHubClientCore_LL_SetDeviceMethodCallback_Ex(iotHubClientInstance->IoTHubClientLLHandle, NULL, NULL);
+                }
+                else
+                {
+                    iotHubClientInstance->method_user_context = (IOTHUB_QUEUE_CONTEXT*)malloc(sizeof(IOTHUB_QUEUE_CONTEXT));
+                    if (iotHubClientInstance->method_user_context == NULL)
+                    {
+                        result = IOTHUB_CLIENT_ERROR;
+                        LogError("Failed allocating QUEUE_CONTEXT");
+                    }
+                    else
+                    {
+                        /*Codes_SRS_IOTHUBCLIENT_07_005: [ IoTHubClient_SetDeviceMethodCallback_Ex shall call IoTHubClientCore_LL_SetDeviceMethodCallback_Ex, while passing the IoTHubClientCore_LL_handle created by IoTHubClientCore_LL_Create along with the parameters iothub_ll_inbound_device_method_callback and IOTHUB_QUEUE_CONTEXT. ]*/
+                        iotHubClientInstance->method_user_context->iotHubClientHandle = iotHubClientHandle;
+                        iotHubClientInstance->method_user_context->userContextCallback = userContextCallback;
+
+                        /* Codes_SRS_IOTHUBCLIENT_07_006: [ When IoTHubClientCore_LL_SetDeviceMethodCallback_Ex is called, IoTHubClient_SetDeviceMethodCallback_Ex shall return the result of IoTHubClientCore_LL_SetDeviceMethodCallback_Ex. ] */
+                        result = IoTHubClientCore_LL_SetDeviceMethodCallback_Ex(iotHubClientInstance->IoTHubClientLLHandle, iothub_ll_inbound_device_method_callback, iotHubClientInstance->method_user_context);
+                        if (result != IOTHUB_CLIENT_OK)
+                        {
+                            LogError("IoTHubClientCore_LL_SetDeviceMethodCallback_Ex failed");
+                            free(iotHubClientInstance->method_user_context);
+                            iotHubClientInstance->method_user_context = NULL;
+                        }
+                        else
+                        {
+                            iotHubClientInstance->inbound_device_method_callback = inboundDeviceMethodCallback;
+                        }
+                    }
+                }
+
+                (void)Unlock(iotHubClientInstance->LockHandle);
+            }
+        }
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_DeviceMethodResponse(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, METHOD_HANDLE methodId, const unsigned char* response, size_t respSize, int statusCode)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    /*Codes_SRS_IOTHUBCLIENT_12_012: [ If iotHubClientHandle is NULL, IoTHubClient_SetDeviceMethodCallback shall return IOTHUB_CLIENT_INVALID_ARG. ]*/
+    if (iotHubClientHandle == NULL)
+    {
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LogError("invalid arg (NULL)");
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_CORE_INSTANCE*)iotHubClientHandle;
+
+        /*Codes_SRS_IOTHUBCLIENT_12_018: [ IoTHubClient_SetDeviceMethodCallback shall be made thread-safe by using the lock created in IoTHubClient_Create. ]*/
+        if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK)
+        {
+            /*Codes_SRS_IOTHUBCLIENT_12_013: [ If acquiring the lock fails, IoTHubClient_SetDeviceMethodCallback shall return IOTHUB_CLIENT_ERROR. ]*/
+            result = IOTHUB_CLIENT_ERROR;
+            LogError("Could not acquire lock");
+        }
+        else
+        {
+            result = IoTHubClientCore_LL_DeviceMethodResponse(iotHubClientInstance->IoTHubClientLLHandle, methodId, response, respSize, statusCode);
+            if (result != IOTHUB_CLIENT_OK)
+            {
+                LogError("IoTHubClientCore_LL_DeviceMethodResponse failed");
+            }
+            (void)Unlock(iotHubClientInstance->LockHandle);
+        }
+    }
+    return result;
+}
+
+#if !defined(DONT_USE_UPLOADTOBLOB) || defined(USE_EDGE_MODULES)
+static IOTHUB_CLIENT_RESULT startHttpWorkerThread(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, HTTPWORKER_THREAD_INFO* threadInfo, THREAD_START_FUNC httpWorkerThreadFunc)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    LIST_ITEM_HANDLE item;
+
+    // StartWorkerThreadIfNeeded creates the "main" worker thread used for transports.  Though its not used
+    // for these HTTP based worker threads (see ThreadAPI_Create call below) the main one is needed for garbage collection.
+    if ((result = StartWorkerThreadIfNeeded(iotHubClientHandle)) != IOTHUB_CLIENT_OK)
+    {
+        /*Codes_SRS_IOTHUBCLIENT_02_053: [ If copying to the structure or spawning the thread fails, then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+        LogError("Could not start worker thread");
+    }
+    else if (Lock(threadInfo->iotHubClientHandle->LockHandle) != LOCK_OK)
+    {
+        LogError("Lock failed");
+        result = IOTHUB_CLIENT_ERROR;
+    }
+    else
+    {
+        if ((item = singlylinkedlist_add(threadInfo->iotHubClientHandle->httpWorkerThreadInfoList, threadInfo)) == NULL)
+        {
+            LogError("Adding item to list failed");
+            result = IOTHUB_CLIENT_ERROR;
+        }
+        else if (ThreadAPI_Create(&threadInfo->threadHandle, httpWorkerThreadFunc, threadInfo) != THREADAPI_OK)
+        {
+            /*Codes_SRS_IOTHUBCLIENT_02_053: [ If copying to the structure or spawning the thread fails, then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+            LogError("unable to ThreadAPI_Create");
+            // Remove the item from linked list here, while we're still under lock.  Final garbage collector also does it under lock.
+            (void)singlylinkedlist_remove(threadInfo->iotHubClientHandle->httpWorkerThreadInfoList, item);
+            result = IOTHUB_CLIENT_ERROR;
+        }
+        else
+        {
+            result = IOTHUB_CLIENT_OK;
+        }
+        (void)Unlock(threadInfo->iotHubClientHandle->LockHandle);
+    }
+
+    return result;
+}
+
+static int markThreadReadyToBeGarbageCollected(HTTPWORKER_THREAD_INFO* threadInfo)
+{
+    /*Codes_SRS_IOTHUBCLIENT_02_071: [ The thread shall mark itself as disposable. ]*/
+    if (Lock(threadInfo->lockGarbage) != LOCK_OK)
+    {
+        LogError("unable to Lock - trying anyway");
+        threadInfo->canBeGarbageCollected = 1;
+    }
+    else
+    {
+        threadInfo->canBeGarbageCollected = 1;
+
+        if (Unlock(threadInfo->lockGarbage) != LOCK_OK)
+        {
+            LogError("unable to Unlock after locking");
+        }
+    }
+
+    ThreadAPI_Exit(0);
+    return 0;
+}
+
+#endif // !defined(DONT_USE_UPLOADTOBLOB) || defined(USE_EDGE_MODULES)
+
+#if !defined(DONT_USE_UPLOADTOBLOB)
+static HTTPWORKER_THREAD_INFO* allocateUploadToBlob(const char* destinationFileName, IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, void* context)
+{
+    HTTPWORKER_THREAD_INFO* threadInfo = (HTTPWORKER_THREAD_INFO*)malloc(sizeof(HTTPWORKER_THREAD_INFO));
+    if (threadInfo == NULL)
+    {
+        LogError("unable to allocate thread object");
+    }
+    else
+    {
+        memset(threadInfo, 0, sizeof(HTTPWORKER_THREAD_INFO));
+        threadInfo->workerThreadType = HTTPWORKER_THREAD_UPLOAD_TO_BLOB;
+        threadInfo->iotHubClientHandle = iotHubClientHandle;
+        threadInfo->context = context;
+
+        if (mallocAndStrcpy_s(&threadInfo->destinationFileName, destinationFileName) != 0)
+        {
+            /*Codes_SRS_IOTHUBCLIENT_02_053: [ If copying to the structure or spawning the thread fails, then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+            LogError("unable to mallocAndStrcpy_s");
+            freeHttpWorkerThreadInfo(threadInfo);
+            threadInfo = NULL;
+        }
+        else if ((threadInfo->lockGarbage = Lock_Init()) == NULL)
+        {
+            LogError("unable to allocate a lock");
+            freeHttpWorkerThreadInfo(threadInfo);
+            threadInfo = NULL;
+        }
+    }
+
+    return threadInfo;
+}
+
+
+static IOTHUB_CLIENT_RESULT initializeUploadToBlobData(HTTPWORKER_THREAD_INFO* threadInfo, const unsigned char* source, size_t size, IOTHUB_CLIENT_FILE_UPLOAD_CALLBACK iotHubClientFileUploadCallback)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    threadInfo->uploadBlobSavedData.size = size;
+    threadInfo->uploadBlobSavedData.iotHubClientFileUploadCallback = iotHubClientFileUploadCallback;
+
+    if (size != 0)
+    {
+        if ((threadInfo->uploadBlobSavedData.source = (unsigned char*)malloc(size)) == NULL)
+        {
+            LogError("Cannot allocate source field");
+            result = IOTHUB_CLIENT_ERROR;
+        }
+        else
+        {
+            memcpy(threadInfo->uploadBlobSavedData.source, source, size);
+            result = IOTHUB_CLIENT_OK;
+        }
+    }
+    else
+    {
+        result = IOTHUB_CLIENT_OK;
+    }
+
+    return result;
+}
+
+
+static int uploadingThread(void *data)
+{
+    IOTHUB_CLIENT_FILE_UPLOAD_RESULT upload_result;
+    HTTPWORKER_THREAD_INFO* threadInfo = (HTTPWORKER_THREAD_INFO*)data;
+
+    srand((unsigned int)get_time(NULL));
+
+    /*it so happens that IoTHubClientCore_LL_UploadToBlob is thread-safe because there's no saved state in the handle and there are no globals, so no need to protect it*/
+    /*not having it protected means multiple simultaneous uploads can happen*/
+    /*Codes_SRS_IOTHUBCLIENT_02_054: [ The thread shall call IoTHubClientCore_LL_UploadToBlob passing the information packed in the structure. ]*/
+    if (IoTHubClientCore_LL_UploadToBlob(threadInfo->iotHubClientHandle->IoTHubClientLLHandle, threadInfo->destinationFileName, threadInfo->uploadBlobSavedData.source, threadInfo->uploadBlobSavedData.size) == IOTHUB_CLIENT_OK)
+    {
+        upload_result = FILE_UPLOAD_OK;
+    }
+    else
+    {
+        LogError("unable to IoTHubClientCore_LL_UploadToBlob");
+        upload_result = FILE_UPLOAD_ERROR;
+    }
+
+    if (threadInfo->uploadBlobSavedData.iotHubClientFileUploadCallback != NULL)
+    {
+        /*Codes_SRS_IOTHUBCLIENT_02_055: [ If IoTHubClientCore_LL_UploadToBlob fails then the thread shall call iotHubClientFileUploadCallbackInternal passing as result FILE_UPLOAD_ERROR and as context the structure from SRS IOTHUBCLIENT 02 051. ]*/
+        threadInfo->uploadBlobSavedData.iotHubClientFileUploadCallback(upload_result, threadInfo->context);
+    }
+
+    return markThreadReadyToBeGarbageCollected(threadInfo);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_UploadToBlobAsync(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, const char* destinationFileName, const unsigned char* source, size_t size, IOTHUB_CLIENT_FILE_UPLOAD_CALLBACK iotHubClientFileUploadCallback, void* context)
+{
+    IOTHUB_CLIENT_RESULT result;
+    /*Codes_SRS_IOTHUBCLIENT_02_047: [ If iotHubClientHandle is NULL then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/
+    /*Codes_SRS_IOTHUBCLIENT_02_048: [ If destinationFileName is NULL then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/
+    /*Codes_SRS_IOTHUBCLIENT_02_049: [ If source is NULL and size is greated than 0 then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/
+    if (
+        (iotHubClientHandle == NULL) ||
+        (destinationFileName == NULL) ||
+        ((source == NULL) && (size > 0))
+        )
+    {
+        LogError("invalid parameters IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle = %p , const char* destinationFileName = %s, const unsigned char* source= %p, size_t size = %lu, IOTHUB_CLIENT_FILE_UPLOAD_CALLBACK iotHubClientFileUploadCallback = %p, void* context = %p",
+            iotHubClientHandle,
+            destinationFileName,
+            source,
+            (unsigned long)size,
+            iotHubClientFileUploadCallback,
+            context
+        );
+        result = IOTHUB_CLIENT_INVALID_ARG;
+    }
+    else
+    {
+        /*Codes_SRS_IOTHUBCLIENT_02_051: [IoTHubClient_UploadToBlobAsync shall copy the souce, size, iotHubClientFileUploadCallback, context into a structure.]*/
+        HTTPWORKER_THREAD_INFO *threadInfo = allocateUploadToBlob(destinationFileName, iotHubClientHandle, context);
+        if (threadInfo == NULL)
+        {
+            /*Codes_SRS_IOTHUBCLIENT_02_053: [ If copying to the structure or spawning the thread fails, then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+            LogError("unable to create upload thread info");
+            result = IOTHUB_CLIENT_ERROR;
+        }
+        else if ((result = initializeUploadToBlobData(threadInfo, source, size, iotHubClientFileUploadCallback)) != IOTHUB_CLIENT_OK)
+        {
+            /*Codes_SRS_IOTHUBCLIENT_02_053: [ If copying to the structure or spawning the thread fails, then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+            LogError("unable to initialize upload blob info");
+            result = IOTHUB_CLIENT_ERROR;
+        }
+        /*Codes_SRS_IOTHUBCLIENT_02_052: [ IoTHubClient_UploadToBlobAsync shall spawn a thread passing the structure build in SRS IOTHUBCLIENT 02 051 as thread data.]*/
+        else if ((result = startHttpWorkerThread(iotHubClientHandle, threadInfo, uploadingThread)) != IOTHUB_CLIENT_OK)
+        {
+            /*Codes_SRS_IOTHUBCLIENT_02_053: [ If copying to the structure or spawning the thread fails, then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+            LogError("unable to start upload thread");
+            freeHttpWorkerThreadInfo(threadInfo);
+        }
+        else
+        {
+            result = IOTHUB_CLIENT_OK;
+        }
+    }
+
+    return result;
+}
+
+static int uploadMultipleBlock_thread(void* data)
+{
+    HTTPWORKER_THREAD_INFO* threadInfo = (HTTPWORKER_THREAD_INFO*)data;
+    IOTHUB_CLIENT_CORE_LL_HANDLE llHandle = threadInfo->iotHubClientHandle->IoTHubClientLLHandle;
+
+    /*Codes_SRS_IOTHUBCLIENT_99_078: [ The thread shall call `IoTHubClientCore_LL_UploadMultipleBlocksToBlob` or `IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx` passing the information packed in the structure. ]*/
+    IOTHUB_CLIENT_RESULT result;
+
+    srand((unsigned int)get_time(NULL));
+
+    if (threadInfo->uploadBlobMultiblockSavedData.getDataCallback != NULL)
+    {
+        result = IoTHubClientCore_LL_UploadMultipleBlocksToBlob(llHandle, threadInfo->destinationFileName, threadInfo->uploadBlobMultiblockSavedData.getDataCallback, threadInfo->context);
+    }
+    else
+    {
+        result = IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx(llHandle, threadInfo->destinationFileName, threadInfo->uploadBlobMultiblockSavedData.getDataCallbackEx, threadInfo->context);
+    }
+    (void)markThreadReadyToBeGarbageCollected(threadInfo);
+
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_UploadMultipleBlocksToBlobAsync(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, const char* destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK getDataCallback, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx, void* context)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    /*Codes_SRS_IOTHUBCLIENT_99_072: [ If `iotHubClientHandle` is `NULL` then `IoTHubClient_UploadMultipleBlocksToBlobAsync(Ex)` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
+    /*Codes_SRS_IOTHUBCLIENT_99_073: [ If `destinationFileName` is `NULL` then `IoTHubClient_UploadMultipleBlocksToBlobAsync(Ex)` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
+    /*Codes_SRS_IOTHUBCLIENT_99_074: [ If `getDataCallback` is `NULL` then `IoTHubClient_UploadMultipleBlocksToBlobAsync(Ex)` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
+    if (
+        (iotHubClientHandle == NULL) ||
+        (destinationFileName == NULL) ||
+        ((getDataCallback == NULL) && (getDataCallbackEx == NULL))
+        )
+    {
+        LogError("invalid parameters iotHubClientHandle = %p , destinationFileName = %p, getDataCallback = %p, getDataCallbackEx = %p",
+            iotHubClientHandle,
+            destinationFileName,
+            getDataCallback,
+            getDataCallbackEx
+        );
+        result = IOTHUB_CLIENT_INVALID_ARG;
+    }
+    else
+    {
+        /*Codes_SRS_IOTHUBCLIENT_99_075: [ `IoTHubClient_UploadMultipleBlocksToBlobAsync(Ex)` shall copy the `destinationFileName`, `getDataCallback`, `context`  and `iotHubClientHandle` into a structure. ]*/
+        HTTPWORKER_THREAD_INFO *threadInfo = allocateUploadToBlob(destinationFileName, iotHubClientHandle, context);
+        if (threadInfo == NULL)
+        {
+            /*Codes_SRS_IOTHUBCLIENT_02_053: [ If copying to the structure or spawning the thread fails, then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+            LogError("unable to create upload thread info");
+            result = IOTHUB_CLIENT_ERROR;
+        }
+        else
+        {
+            /*Codes_SRS_IOTHUBCLIENT_99_075: [ `IoTHubClient_UploadMultipleBlocksToBlobAsync(Ex)` shall copy the `destinationFileName`, `getDataCallback`, `context`  and `iotHubClientHandle` into a structure. ]*/
+            threadInfo->uploadBlobMultiblockSavedData.getDataCallback = getDataCallback;
+            threadInfo->uploadBlobMultiblockSavedData.getDataCallbackEx = getDataCallbackEx;
+
+            if ((result = startHttpWorkerThread(iotHubClientHandle, threadInfo, uploadMultipleBlock_thread)) != IOTHUB_CLIENT_OK)
+            {
+                /*Codes_SRS_IOTHUBCLIENT_02_053: [ If copying to the structure or spawning the thread fails, then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                LogError("unable to start upload thread");
+                freeHttpWorkerThreadInfo(threadInfo);
+            }
+            else
+            {
+                /*Codes_SRS_IOTHUBCLIENT_99_077: [ If copying to the structure and spawning the thread succeeds, then `IoTHubClient_UploadMultipleBlocksToBlobAsync(Ex)` shall return `IOTHUB_CLIENT_OK`. ]*/
+                result = IOTHUB_CLIENT_OK;
+            }
+        }
+    }
+    return result;
+}
+
+#endif /*DONT_USE_UPLOADTOBLOB*/
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_SendEventToOutputAsync(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, IOTHUB_MESSAGE_HANDLE eventMessageHandle, const char* outputName, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK eventConfirmationCallback, void* userContextCallback)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    if ((iotHubClientHandle == NULL) || (outputName == NULL) || (eventMessageHandle == NULL))
+    {
+        // Codes_SRS_IOTHUBCLIENT_31_100: [ If `iotHubClientHandle`, `outputName`, or `eventConfirmationCallback` is `NULL`, `IoTHubClient_SendEventToOutputAsync` shall return `IOTHUB_CLIENT_INVALID_ARG`. ]
+        LogError("Invalid argument (iotHubClientHandle=%p, outputName=%p, eventMessageHandle=%p)", iotHubClientHandle, outputName, eventMessageHandle);
+        result = IOTHUB_CLIENT_INVALID_ARG;
+    }
+    else
+    {
+        // Codes_SRS_IOTHUBCLIENT_31_101: [ `IoTHubClient_SendEventToOutputAsync` shall set the outputName of the message to send. ]
+        if (IoTHubMessage_SetOutputName(eventMessageHandle, outputName) != IOTHUB_MESSAGE_OK)
+        {
+            LogError("IoTHubMessage_SetOutputName failed");
+            result = IOTHUB_CLIENT_ERROR;
+        }
+        // Codes_SRS_IOTHUBCLIENT_31_102: [ `IoTHubClient_SendEventToOutputAsync` shall invoke `IoTHubClient_SendEventAsync` to send the message. ]
+        else if ((result = IoTHubClientCore_SendEventAsync(iotHubClientHandle, eventMessageHandle, eventConfirmationCallback, userContextCallback)) != IOTHUB_CLIENT_OK)
+        {
+            LogError("Call into IoTHubClient_SendEventAsync failed, result=%d", result);
+        }
+    }
+
+    return result;
+}
+
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_SetInputMessageCallback(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, const char* inputName, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC eventHandlerCallback, void* userContextCallback)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    if (iotHubClientHandle == NULL)
+    {
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LogError("NULL iothubClientHandle");
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_CORE_INSTANCE*)iotHubClientHandle;
+
+        // Codes_SRS_IOTHUBCLIENT_31_098: [ `IoTHubClient_SetMessageCallback` shall start the worker thread if it was not previously started. ]
+        if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK)
+        {
+            result = IOTHUB_CLIENT_ERROR;
+            LogError("Could not start worker thread");
+        }
+        else
+        {
+            if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK)
+            {
+                result = IOTHUB_CLIENT_ERROR;
+                LogError("Could not acquire lock");
+            }
+            else
+            {
+                // Codes_SRS_IOTHUBCLIENT_31_099: [ `IoTHubClient_SetMessageCallback` shall call `IoTHubClient_LL_SetInputMessageCallback`, passing its input arguments ]
+                IOTHUB_INPUTMESSAGE_CALLBACK_CONTEXT inputMessageCallbackContext;
+                inputMessageCallbackContext.iotHubClientHandle = iotHubClientHandle;
+                inputMessageCallbackContext.eventHandlerCallback = eventHandlerCallback;
+                inputMessageCallbackContext.userContextCallback = userContextCallback;
+
+                result = IoTHubClientCore_LL_SetInputMessageCallbackEx(iotHubClientInstance->IoTHubClientLLHandle, inputName, iothub_ll_inputmessage_callback, (void*)&inputMessageCallbackContext, sizeof(inputMessageCallbackContext));
+                (void)Unlock(iotHubClientInstance->LockHandle);
+            }
+        }
+    }
+
+    return result;
+}
+
+#ifdef USE_EDGE_MODULES
+
+HTTPWORKER_THREAD_INFO * allocateMethodInvoke(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, const char* deviceId, const char* moduleId, const char* methodName, const char* methodPayload, unsigned int timeout, IOTHUB_METHOD_INVOKE_CALLBACK methodInvokeCallback, void* context)
+{
+    HTTPWORKER_THREAD_INFO* threadInfo = (HTTPWORKER_THREAD_INFO*)malloc(sizeof(HTTPWORKER_THREAD_INFO));
+    if (threadInfo == NULL)
+    {
+        LogError("unable to allocate thread object");
+    }
+    else
+    {
+        memset(threadInfo, 0, sizeof(HTTPWORKER_THREAD_INFO));
+        threadInfo->workerThreadType = HTTPWORKER_THREAD_INVOKE_METHOD;
+        threadInfo->iotHubClientHandle = iotHubClientHandle;
+        threadInfo->context = context;
+
+        threadInfo->invokeMethodSavedData.timeout = timeout;
+        threadInfo->invokeMethodSavedData.methodInvokeCallback = methodInvokeCallback;
+
+        if ((mallocAndStrcpy_s((char**)&threadInfo->invokeMethodSavedData.deviceId, deviceId) != 0) ||
+            ((moduleId != NULL) && mallocAndStrcpy_s((char**)&threadInfo->invokeMethodSavedData.moduleId, moduleId) != 0) ||
+            (mallocAndStrcpy_s((char**)&threadInfo->invokeMethodSavedData.methodName, methodName) != 0) ||
+            (mallocAndStrcpy_s((char**)&threadInfo->invokeMethodSavedData.methodPayload, methodPayload) != 0))
+        {
+            LogError("Allocating resources failed");
+            freeHttpWorkerThreadInfo(threadInfo);
+            threadInfo = NULL;
+        }
+        else if ((threadInfo->lockGarbage = Lock_Init()) == NULL)
+        {
+            LogError("unable to allocate a lock");
+            freeHttpWorkerThreadInfo(threadInfo);
+            threadInfo = NULL;
+        }
+    }
+
+    return threadInfo;
+}
+
+static int uploadMethodInvoke_thread(void* data)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    HTTPWORKER_THREAD_INFO* threadInfo = (HTTPWORKER_THREAD_INFO*)data;
+
+    srand((unsigned int)get_time(NULL));
+
+    int responseStatus;
+    unsigned char* responsePayload = NULL;
+    size_t responsePayloadSize;
+
+    result = IoTHubClientCore_LL_GenericMethodInvoke(threadInfo->iotHubClientHandle->IoTHubClientLLHandle,
+                                                     threadInfo->invokeMethodSavedData.deviceId,
+                                                     threadInfo->invokeMethodSavedData.moduleId,
+                                                     threadInfo->invokeMethodSavedData.methodName,
+                                                     threadInfo->invokeMethodSavedData.methodPayload,
+                                                     threadInfo->invokeMethodSavedData.timeout,
+                                                     &responseStatus,
+                                                     &responsePayload,
+                                                     &responsePayloadSize);
+
+    if (threadInfo->invokeMethodSavedData.methodInvokeCallback != NULL)
+    {
+        threadInfo->invokeMethodSavedData.methodInvokeCallback(result, responseStatus, responsePayload, responsePayloadSize, threadInfo->context);
+    }
+
+    if (responsePayload != NULL)
+    {
+        free(responsePayload);
+    }
+
+    (void)markThreadReadyToBeGarbageCollected(threadInfo);
+    return result;
+}
+
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_GenericMethodInvoke(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, const char* deviceId, const char* moduleId, const char* methodName, const char* methodPayload, unsigned int timeout, IOTHUB_METHOD_INVOKE_CALLBACK methodInvokeCallback, void* context)
+{
+    IOTHUB_CLIENT_RESULT result;
+    HTTPWORKER_THREAD_INFO *threadInfo;
+
+    if ((iotHubClientHandle == NULL) || (deviceId == NULL) || (methodName == NULL) || (methodPayload == NULL))
+    {
+        LogError("Invalid argument (iotHubClientHandle=%p, deviceId=%p, methodName=%p, methodPayload=%p)", iotHubClientHandle, deviceId, methodName, methodPayload);
+        result = IOTHUB_CLIENT_INVALID_ARG;
+    }
+    else if ((threadInfo = allocateMethodInvoke(iotHubClientHandle, deviceId, moduleId, methodName, methodPayload, timeout, methodInvokeCallback, context)) == NULL)
+    {
+        LogError("failed allocating method invoke thread info");
+        result = IOTHUB_CLIENT_ERROR;
+    }
+    else if ((result = startHttpWorkerThread(iotHubClientHandle, threadInfo, uploadMethodInvoke_thread)) != IOTHUB_CLIENT_OK)
+    {
+        LogError("unable to start method invoke thread");
+        freeHttpWorkerThreadInfo(threadInfo);
+    }
+    else
+    {
+        result = IOTHUB_CLIENT_OK;
+    }
+    return result;
+}
+#endif /* USE_EDGE_MODULES */
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_client_core_ll.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_client_core_ll.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_client_core_ll.c	(revision 453)
@@ -0,0 +1,3064 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/string_tokenizer.h"
+#include "azure_c_shared_utility/doublylinkedlist.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/tickcounter.h"
+#include "azure_c_shared_utility/constbuffer.h"
+#include "azure_c_shared_utility/platform.h"
+#include "azure_c_shared_utility/singlylinkedlist.h"
+#include "azure_c_shared_utility/shared_util_options.h"
+#include "azure_c_shared_utility/agenttime.h"
+
+#include "iothub_client_core_ll.h"
+#include "iothub_client_options.h"
+#include "iothub_client_version.h"
+#include "iothub_transport_ll.h"
+#include "internal/iothub_client_authorization.h"
+#include "internal/iothub_client_private.h"
+#include "internal/iothub_client_diagnostic.h"
+#include "internal/iothubtransport.h"
+
+#ifndef DONT_USE_UPLOADTOBLOB
+#include "internal/iothub_client_ll_uploadtoblob.h"
+#endif
+
+#ifdef USE_EDGE_MODULES
+#include "azure_c_shared_utility/envvariable.h"
+#include "azure_prov_client/iothub_security_factory.h"
+#include "internal/iothub_client_edge.h"
+#endif
+
+#define LOG_ERROR_RESULT LogError("result = %s", MU_ENUM_TO_STRING(IOTHUB_CLIENT_RESULT, result));
+#define INDEFINITE_TIME ((time_t)(-1))
+#define ERROR_CODE_BECAUSE_DESTROY 0
+
+
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(IOTHUB_CLIENT_FILE_UPLOAD_RESULT, IOTHUB_CLIENT_FILE_UPLOAD_RESULT_VALUES);
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_RESULT_VALUES);
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(IOTHUB_CLIENT_RETRY_POLICY, IOTHUB_CLIENT_RETRY_POLICY_VALUES);
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(IOTHUB_CLIENT_STATUS, IOTHUB_CLIENT_STATUS_VALUES);
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(IOTHUB_IDENTITY_TYPE, IOTHUB_IDENTITY_TYPE_VALUE);
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(IOTHUB_PROCESS_ITEM_RESULT, IOTHUB_PROCESS_ITEM_RESULT_VALUE);
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(IOTHUB_CLIENT_IOTHUB_METHOD_STATUS, IOTHUB_CLIENT_IOTHUB_METHOD_STATUS_VALUES);
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(IOTHUB_CLIENT_CONFIRMATION_RESULT, IOTHUB_CLIENT_CONFIRMATION_RESULT_VALUES);
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(IOTHUB_CLIENT_CONNECTION_STATUS, IOTHUB_CLIENT_CONNECTION_STATUS_VALUES);
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(IOTHUB_CLIENT_CONNECTION_STATUS_REASON, IOTHUB_CLIENT_CONNECTION_STATUS_REASON_VALUES);
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(TRANSPORT_TYPE, TRANSPORT_TYPE_VALUES);
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(DEVICE_TWIN_UPDATE_STATE, DEVICE_TWIN_UPDATE_STATE_VALUES);
+#ifndef DONT_USE_UPLOADTOBLOB
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT_VALUES);
+#endif // DONT_USE_UPLOADTOBLOB
+
+#define CALLBACK_TYPE_VALUES \
+    CALLBACK_TYPE_NONE,      \
+    CALLBACK_TYPE_SYNC,    \
+    CALLBACK_TYPE_ASYNC
+
+MU_DEFINE_ENUM(CALLBACK_TYPE, CALLBACK_TYPE_VALUES)
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(CALLBACK_TYPE, CALLBACK_TYPE_VALUES)
+
+typedef struct IOTHUB_METHOD_CALLBACK_DATA_TAG
+{
+    CALLBACK_TYPE type;
+    IOTHUB_CLIENT_DEVICE_METHOD_CALLBACK_ASYNC callbackSync;
+    IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK callbackAsync;
+    void* userContextCallback;
+}IOTHUB_METHOD_CALLBACK_DATA;
+
+typedef struct IOTHUB_EVENT_CALLBACK_TAG
+{
+    STRING_HANDLE inputName;
+    IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC callbackAsync;
+    IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC_EX callbackAsyncEx;
+    void* userContextCallback;
+    void* userContextCallbackEx;
+}IOTHUB_EVENT_CALLBACK;
+
+typedef struct IOTHUB_MESSAGE_CALLBACK_DATA_TAG
+{
+    CALLBACK_TYPE type;
+    IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC callbackSync;
+    IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC_EX callbackAsync;
+    void* userContextCallback;
+}IOTHUB_MESSAGE_CALLBACK_DATA;
+
+typedef struct GET_TWIN_CONTEXT_TAG
+{
+    IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK callback;
+    void* context;
+} GET_TWIN_CONTEXT;
+
+typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG
+{
+    DLIST_ENTRY waitingToSend;
+    DLIST_ENTRY iot_msg_queue;
+    DLIST_ENTRY iot_ack_queue;
+    TRANSPORT_LL_HANDLE transportHandle;
+    bool isSharedTransport;
+    IOTHUB_DEVICE_HANDLE deviceHandle;
+    TRANSPORT_PROVIDER_FIELDS;
+    IOTHUB_MESSAGE_CALLBACK_DATA messageCallback;
+    IOTHUB_METHOD_CALLBACK_DATA methodCallback;
+    IOTHUB_CLIENT_CONNECTION_STATUS_CALLBACK conStatusCallback;
+    void* conStatusUserContextCallback;
+    time_t lastMessageReceiveTime;
+    TICK_COUNTER_HANDLE tickCounter; /*shared tickcounter used to track message timeouts in waitingToSend list*/
+    tickcounter_ms_t currentMessageTimeout;
+    uint64_t current_device_twin_timeout;
+    IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK deviceTwinCallback;
+    void* deviceTwinContextCallback;
+    IOTHUB_CLIENT_RETRY_POLICY retryPolicy;
+    size_t retryTimeoutLimitInSeconds;
+#ifndef DONT_USE_UPLOADTOBLOB
+    IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE uploadToBlobHandle;
+#endif
+#ifdef USE_EDGE_MODULES
+    IOTHUB_CLIENT_EDGE_HANDLE methodHandle;
+#endif
+    uint32_t data_msg_id;
+    bool complete_twin_update_encountered;
+    IOTHUB_AUTHORIZATION_HANDLE authorization_module;
+    STRING_HANDLE product_info;
+    IOTHUB_DIAGNOSTIC_SETTING_DATA diagnostic_setting;
+    SINGLYLINKEDLIST_HANDLE event_callbacks;  // List of IOTHUB_EVENT_CALLBACK's
+    STRING_HANDLE model_id;
+}IOTHUB_CLIENT_CORE_LL_HANDLE_DATA;
+
+static const char HOSTNAME_TOKEN[] = "HostName";
+static const char DEVICEID_TOKEN[] = "DeviceId";
+static const char X509_TOKEN[] = "x509";
+static const char X509_TOKEN_ONLY_ACCEPTABLE_VALUE[] = "true";
+static const char DEVICEKEY_TOKEN[] = "SharedAccessKey";
+static const char DEVICESAS_TOKEN[] = "SharedAccessSignature";
+static const char PROTOCOL_GATEWAY_HOST_TOKEN[] = "GatewayHostName";
+static const char MODULE_ID_TOKEN[] = "ModuleId";
+static const char PROVISIONING_TOKEN[] = "UseProvisioning";
+static const char PROVISIONING_ACCEPTABLE_VALUE[] = "true";
+
+#ifdef USE_EDGE_MODULES
+/*The following section should be moved to iothub_module_client_ll.c during impending refactor*/
+
+static const char* ENVIRONMENT_VAR_EDGEHUB_CONNECTIONSTRING = "EdgeHubConnectionString";
+static const char* ENVIRONMENT_VAR_EDGEHUB_CACERTIFICATEFILE = "EdgeModuleCACertificateFile";
+static const char* ENVIRONMENT_VAR_EDGEAUTHSCHEME = "IOTEDGE_AUTHSCHEME";
+static const char* ENVIRONMENT_VAR_EDGEDEVICEID = "IOTEDGE_DEVICEID";
+static const char* ENVIRONMENT_VAR_EDGEMODULEID = "IOTEDGE_MODULEID";
+static const char* ENVIRONMENT_VAR_EDGEHUBHOSTNAME = "IOTEDGE_IOTHUBHOSTNAME";
+static const char* ENVIRONMENT_VAR_EDGEGATEWAYHOST = "IOTEDGE_GATEWAYHOSTNAME";
+static const char* SAS_TOKEN_AUTH = "sasToken";
+
+
+typedef struct EDGE_ENVIRONMENT_VARIABLES_TAG
+{
+    const char* connection_string;
+    const char* ca_trusted_certificate_file;
+    const char* auth_scheme;
+    const char* device_id;
+    const char* iothub_name;
+    const char* iothub_suffix;
+    const char* gatewayhostname;
+    const char* module_id;
+    char* iothub_buffer;
+} EDGE_ENVIRONMENT_VARIABLES;
+
+
+static int retrieve_edge_environment_variabes(EDGE_ENVIRONMENT_VARIABLES *edge_environment_variables)
+{
+    int result;
+    const char* edgehubhostname;
+    char* edgehubhostname_separator;
+
+    if ((edge_environment_variables->connection_string = environment_get_variable(ENVIRONMENT_VAR_EDGEHUB_CONNECTIONSTRING)) != NULL)
+    {
+        if ((edge_environment_variables->ca_trusted_certificate_file = environment_get_variable(ENVIRONMENT_VAR_EDGEHUB_CACERTIFICATEFILE)) == NULL)
+        {
+            LogError("Environment variable %s is missing.  When %s is set, it is required", ENVIRONMENT_VAR_EDGEHUB_CACERTIFICATEFILE, ENVIRONMENT_VAR_EDGEHUB_CONNECTIONSTRING);
+            result = MU_FAILURE;
+        }
+        else
+        {
+            // If we can read in the connection string and trusted certs, we're done.
+            result = 0;
+        }
+    }
+    else
+    {
+        // We're NOT using pre-configured EdgeConnection string / certificates.  In this case, we use these environment variables when
+        // communicating to Edge service.
+        if ((edge_environment_variables->auth_scheme = environment_get_variable(ENVIRONMENT_VAR_EDGEAUTHSCHEME)) == NULL)
+        {
+            LogError("Environment %s not set", ENVIRONMENT_VAR_EDGEAUTHSCHEME);
+            result = MU_FAILURE;
+        }
+        else if (strcmp(edge_environment_variables->auth_scheme, SAS_TOKEN_AUTH) != 0)
+        {
+            LogError("Environment %s was set to %s, but only support for %s", ENVIRONMENT_VAR_EDGEAUTHSCHEME, edge_environment_variables->auth_scheme, SAS_TOKEN_AUTH);
+            result = MU_FAILURE;
+        }
+        else if ((edge_environment_variables->device_id = environment_get_variable(ENVIRONMENT_VAR_EDGEDEVICEID)) == NULL)
+        {
+            LogError("Environment %s not set", ENVIRONMENT_VAR_EDGEDEVICEID);
+            result = MU_FAILURE;
+        }
+        else if ((edgehubhostname = environment_get_variable(ENVIRONMENT_VAR_EDGEHUBHOSTNAME)) == NULL)
+        {
+            LogError("Environment %s not set", ENVIRONMENT_VAR_EDGEHUBHOSTNAME);
+            result = MU_FAILURE;
+        }
+        else if ((edge_environment_variables->gatewayhostname = environment_get_variable(ENVIRONMENT_VAR_EDGEGATEWAYHOST)) == NULL)
+        {
+            LogError("Environment %s not set", ENVIRONMENT_VAR_EDGEGATEWAYHOST);
+            result = MU_FAILURE;
+        }
+        else if ((edge_environment_variables->module_id = environment_get_variable(ENVIRONMENT_VAR_EDGEMODULEID)) == NULL)
+        {
+            LogError("Environment %s not set", ENVIRONMENT_VAR_EDGEMODULEID);
+            result = MU_FAILURE;
+        }
+        // Make a copy of just ENVIRONMENT_VAR_EDGEHUBHOSTNAME.  We need to make changes in place (namely inserting a '\0')
+        // and can't do this with system environment variable safely.
+        else if (mallocAndStrcpy_s(&edge_environment_variables->iothub_buffer, edgehubhostname) != 0)
+        {
+            LogError("Unable to copy buffer");
+            result = MU_FAILURE;
+        }
+        else if ((edgehubhostname_separator = strchr(edge_environment_variables->iothub_buffer, '.')) == NULL)
+        {
+            LogError("Environment edgehub %s invalid, requires '.' separator", edge_environment_variables->iothub_buffer);
+            result = MU_FAILURE;
+        }
+        else if (*(edgehubhostname_separator + 1) == 0)
+        {
+            LogError("Environment edgehub %s invalid, no content after '.' separator", edge_environment_variables->iothub_buffer);
+            result = MU_FAILURE;
+        }
+        else
+        {
+            edge_environment_variables->iothub_name = edge_environment_variables->iothub_buffer;
+            *edgehubhostname_separator = 0;
+            edge_environment_variables->iothub_suffix = edgehubhostname_separator + 1;
+            result = 0;
+        }
+    }
+
+    return result;
+}
+
+IOTHUB_CLIENT_EDGE_HANDLE IoTHubClientCore_LL_GetEdgeHandle(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle)
+{
+    IOTHUB_CLIENT_EDGE_HANDLE result;
+    if (iotHubClientHandle != NULL)
+    {
+        result = iotHubClientHandle->methodHandle;
+    }
+    else
+    {
+        result = NULL;
+    }
+
+    return result;
+}
+#endif /* USE_EDGE_MODULES */
+
+static void setTransportProtocol(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData, TRANSPORT_PROVIDER* protocol)
+{
+    handleData->IoTHubTransport_SendMessageDisposition = protocol->IoTHubTransport_SendMessageDisposition;
+    handleData->IoTHubTransport_GetHostname = protocol->IoTHubTransport_GetHostname;
+    handleData->IoTHubTransport_SetOption = protocol->IoTHubTransport_SetOption;
+    handleData->IoTHubTransport_Create = protocol->IoTHubTransport_Create;
+    handleData->IoTHubTransport_Destroy = protocol->IoTHubTransport_Destroy;
+    handleData->IoTHubTransport_Register = protocol->IoTHubTransport_Register;
+    handleData->IoTHubTransport_Unregister = protocol->IoTHubTransport_Unregister;
+    handleData->IoTHubTransport_Subscribe = protocol->IoTHubTransport_Subscribe;
+    handleData->IoTHubTransport_Unsubscribe = protocol->IoTHubTransport_Unsubscribe;
+    handleData->IoTHubTransport_DoWork = protocol->IoTHubTransport_DoWork;
+    handleData->IoTHubTransport_SetRetryPolicy = protocol->IoTHubTransport_SetRetryPolicy;
+    handleData->IoTHubTransport_GetSendStatus = protocol->IoTHubTransport_GetSendStatus;
+    handleData->IoTHubTransport_ProcessItem = protocol->IoTHubTransport_ProcessItem;
+    handleData->IoTHubTransport_Subscribe_DeviceTwin = protocol->IoTHubTransport_Subscribe_DeviceTwin;
+    handleData->IoTHubTransport_Unsubscribe_DeviceTwin = protocol->IoTHubTransport_Unsubscribe_DeviceTwin;
+    handleData->IoTHubTransport_GetTwinAsync = protocol->IoTHubTransport_GetTwinAsync;
+    handleData->IoTHubTransport_Subscribe_DeviceMethod = protocol->IoTHubTransport_Subscribe_DeviceMethod;
+    handleData->IoTHubTransport_Unsubscribe_DeviceMethod = protocol->IoTHubTransport_Unsubscribe_DeviceMethod;
+    handleData->IoTHubTransport_DeviceMethod_Response = protocol->IoTHubTransport_DeviceMethod_Response;
+    handleData->IoTHubTransport_Subscribe_InputQueue = protocol->IoTHubTransport_Subscribe_InputQueue;
+    handleData->IoTHubTransport_Unsubscribe_InputQueue = protocol->IoTHubTransport_Unsubscribe_InputQueue;
+    handleData->IoTHubTransport_SetCallbackContext = protocol->IoTHubTransport_SetCallbackContext;
+    handleData->IoTHubTransport_GetSupportedPlatformInfo = protocol->IoTHubTransport_GetSupportedPlatformInfo;
+}
+
+static bool is_event_equal(IOTHUB_EVENT_CALLBACK *event_callback, const char *input_name)
+{
+    bool result;
+
+    if (event_callback != NULL)
+    {
+        const char* event_input_name = STRING_c_str(event_callback->inputName);
+        if ((event_input_name != NULL) && (input_name != NULL))
+        {
+            // Matched the input queue name of a named handler
+            result = (strcmp(event_input_name, input_name) == 0);
+        }
+        else if ((input_name == NULL) && (event_input_name == NULL))
+        {
+            // Matched the default handler
+            result = true;
+        }
+        else
+        {
+            result = false;
+        }
+    }
+    else
+    {
+        result = false;
+    }
+    return result;
+}
+
+static bool is_event_equal_for_match(LIST_ITEM_HANDLE list_item, const void* match_context)
+{
+    return is_event_equal((IOTHUB_EVENT_CALLBACK*)singlylinkedlist_item_get_value(list_item), (const char*)match_context);
+}
+
+static void device_twin_data_destroy(IOTHUB_DEVICE_TWIN* client_item)
+{
+    CONSTBUFFER_DecRef(client_item->report_data_handle);
+    free(client_item);
+}
+
+static int create_edge_handle(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handle_data, const IOTHUB_CLIENT_CONFIG* config, const char* module_id)
+{
+    int result;
+    (void)config;
+    (void)module_id;
+#ifdef USE_EDGE_MODULES
+    /* There is no way to currently distinguish a regular module from a edge module, so this handle is created regardless of if appropriate.
+    However, as a gateway hostname is required in order to create an Edge Handle, we need to at least make sure that exists
+    in order to prevent errors.
+
+    The end result is that all edge modules will have an EdgeHandle, but only some non-edge modules will have it.
+    Regardless, non-edge modules will never be able to use the handle.
+    */
+    if (config->protocolGatewayHostName != NULL)
+    {
+        handle_data->methodHandle = IoTHubClient_EdgeHandle_Create(config, handle_data->authorization_module, module_id);
+
+        if (handle_data->methodHandle == NULL)
+        {
+            LogError("Unable to IoTHubModuleClient_LL_MethodHandle_Create");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            result = 0;
+        }
+    }
+    else
+    {
+        result = 0;
+    }
+
+#else
+    (void)handle_data;
+    result = 0;
+#endif
+    return result;
+}
+
+static int create_blob_upload_module(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handle_data, const IOTHUB_CLIENT_CONFIG* config)
+{
+    int result;
+    (void)handle_data;
+    (void)config;
+#ifndef DONT_USE_UPLOADTOBLOB
+    handle_data->uploadToBlobHandle = IoTHubClient_LL_UploadToBlob_Create(config, handle_data->authorization_module);
+    if (handle_data->uploadToBlobHandle == NULL)
+    {
+        LogError("unable to IoTHubClientCore_LL_UploadToBlob_Create");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        result = 0;
+    }
+#else
+    result = 0;
+#endif
+    return result;
+}
+
+static void destroy_blob_upload_module(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handle_data)
+{
+    (void)handle_data;
+#ifndef DONT_USE_UPLOADTOBLOB
+    /*Codes_SRS_IOTHUBCLIENT_LL_02_046: [ If creating the TICK_COUNTER_HANDLE fails then IoTHubClientCore_LL_Create shall fail and return NULL. ]*/
+    IoTHubClient_LL_UploadToBlob_Destroy(handle_data->uploadToBlobHandle);
+#endif
+}
+
+static void destroy_module_method_module(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handle_data)
+{
+    (void)handle_data;
+#ifdef USE_EDGE_MODULES
+    IoTHubClient_EdgeHandle_Destroy(handle_data->methodHandle);
+#endif
+}
+
+static bool invoke_message_callback(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData, MESSAGE_CALLBACK_INFO* messageData)
+{
+    bool result;
+    /* Codes_SRS_IOTHUBCLIENT_LL_09_004: [IoTHubClient_LL_GetLastMessageReceiveTime shall return lastMessageReceiveTime in localtime] */
+    handleData->lastMessageReceiveTime = get_time(NULL);
+
+    switch (handleData->messageCallback.type)
+    {
+        case CALLBACK_TYPE_NONE:
+        {
+            /*Codes_SRS_IOTHUBCLIENT_LL_02_032: [If the client is not subscribed to receive messages then IoTHubClient_LL_MessageCallback shall return false.] */
+            LogError("Invalid workflow - not currently set up to accept messages");
+            result = false;
+            break;
+        }
+        case CALLBACK_TYPE_SYNC:
+        {
+            /*Codes_SRS_IOTHUBCLIENT_LL_02_030: [If messageCallbackType is LEGACY then IoTHubClient_LL_MessageCallback shall invoke the last callback function (the parameter messageCallback to IoTHubClient_LL_SetMessageCallback) passing the message and the passed userContextCallback.]*/
+            IOTHUBMESSAGE_DISPOSITION_RESULT cb_result = handleData->messageCallback.callbackSync(messageData->messageHandle, handleData->messageCallback.userContextCallback);
+
+            /*Codes_SRS_IOTHUBCLIENT_LL_10_007: [If messageCallbackType is LEGACY then IoTHubClient_LL_MessageCallback shall send the message disposition as returned by the client to the underlying layer.] */
+            if (handleData->IoTHubTransport_SendMessageDisposition(messageData, cb_result) != IOTHUB_CLIENT_OK)
+            {
+                LogError("IoTHubTransport_SendMessageDisposition failed");
+            }
+            result = true;
+            break;
+        }
+        case CALLBACK_TYPE_ASYNC:
+        {
+            /* Codes_SRS_IOTHUBCLIENT_LL_10_009: [If messageCallbackType is ASYNC then IoTHubClient_LL_MessageCallback shall return what messageCallbacEx returns.] */
+            result = handleData->messageCallback.callbackAsync(messageData, handleData->messageCallback.userContextCallback);
+            if (!result)
+            {
+                LogError("messageCallbackEx failed");
+            }
+            break;
+        }
+        default:
+        {
+            LogError("Invalid state");
+            result = false;
+            break;
+        }
+    }
+
+    return result;
+}
+
+/*Codes_SRS_IOTHUBCLIENT_LL_10_032: ["product_info" - takes a char string as an argument to specify the product information(e.g. `"ProductName/ProductVersion"`). ]*/
+/*Codes_SRS_IOTHUBCLIENT_LL_10_034: ["product_info" - shall store the given string concatenated with the sdk information and the platform information in the form(ProductInfo DeviceSDKName / DeviceSDKVersion(OSName OSVersion; Architecture). ]*/
+static STRING_HANDLE make_product_info(const char* product, PLATFORM_INFO_OPTION option)
+{
+    STRING_HANDLE result;
+    STRING_HANDLE pfi = platform_get_platform_info(option);
+    if (pfi == NULL)
+    {
+        LogError("Platform get info failed");
+        result = NULL;
+    }
+    else
+    {
+        if (product == NULL)
+        {
+            result = STRING_construct_sprintf("%s %s", CLIENT_DEVICE_TYPE_PREFIX CLIENT_DEVICE_BACKSLASH IOTHUB_SDK_VERSION, STRING_c_str(pfi));
+        }
+        else
+        {
+            result = STRING_construct_sprintf("%s %s %s", product, CLIENT_DEVICE_TYPE_PREFIX CLIENT_DEVICE_BACKSLASH IOTHUB_SDK_VERSION, STRING_c_str(pfi));
+        }
+        STRING_delete(pfi);
+    }
+    return result;
+}
+
+static void IoTHubClientCore_LL_SendComplete(PDLIST_ENTRY completed, IOTHUB_CLIENT_CONFIRMATION_RESULT result, void* ctx)
+{
+    /*Codes_SRS_IOTHUBCLIENT_LL_02_022: [If parameter completed is NULL, or parameter handle is NULL then IoTHubClientCore_LL_SendBatch shall return.]*/
+    if (
+        (ctx == NULL) ||
+        (completed == NULL)
+        )
+    {
+        /*"shall return"*/
+        LogError("invalid arg");
+    }
+    else
+    {
+        /*Codes_SRS_IOTHUBCLIENT_LL_02_027: [If parameter result is IOTHUB_CLIENT_CONFIRMATION_ERROR then IoTHubClientCore_LL_SendComplete shall call all the non-NULL callbacks with the result parameter set to IOTHUB_CLIENT_CONFIRMATION_ERROR and the context set to the context passed originally in the SendEventAsync call.] */
+        /*Codes_SRS_IOTHUBCLIENT_LL_02_025: [If parameter result is IOTHUB_CLIENT_CONFIRMATION_OK then IoTHubClientCore_LL_SendComplete shall call all the non-NULL callbacks with the result parameter set to IOTHUB_CLIENT_CONFIRMATION_OK and the context set to the context passed originally in the SendEventAsync call.]*/
+        PDLIST_ENTRY oldest;
+        while ((oldest = DList_RemoveHeadList(completed)) != completed)
+        {
+            IOTHUB_MESSAGE_LIST* messageList = (IOTHUB_MESSAGE_LIST*)containingRecord(oldest, IOTHUB_MESSAGE_LIST, entry);
+            /*Codes_SRS_IOTHUBCLIENT_LL_02_026: [If any callback is NULL then there shall not be a callback call.]*/
+            if (messageList->callback != NULL)
+            {
+                messageList->callback(result, messageList->context);
+            }
+            IoTHubMessage_Destroy(messageList->messageHandle);
+            free(messageList);
+        }
+    }
+}
+
+static void IoTHubClientCore_LL_RetrievePropertyComplete(DEVICE_TWIN_UPDATE_STATE update_state, const unsigned char* payLoad, size_t size, void* ctx)
+{
+    if (ctx == NULL)
+    {
+        /* Codes_SRS_IOTHUBCLIENT_LL_07_013: [ If handle is NULL then IoTHubClientCore_LL_RetrievePropertyComplete shall do nothing.] */
+        LogError("Invalid argument ctx NULL");
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)ctx;
+        /* Codes_SRS_IOTHUBCLIENT_LL_07_014: [ If deviceTwinCallback is NULL then IoTHubClientCore_LL_RetrievePropertyComplete shall do nothing.] */
+        if (handleData->deviceTwinCallback)
+        {
+            /* Codes_SRS_IOTHUBCLIENT_LL_07_015: [ If the the update_state parameter is DEVICE_TWIN_UPDATE_PARTIAL and a DEVICE_TWIN_UPDATE_COMPLETE has not been previously recieved then IoTHubClientCore_LL_RetrievePropertyComplete shall do nothing.] */
+            if (update_state == DEVICE_TWIN_UPDATE_COMPLETE)
+            {
+                handleData->complete_twin_update_encountered = true;
+            }
+            if (handleData->complete_twin_update_encountered)
+            {
+                /* Codes_SRS_IOTHUBCLIENT_LL_07_016: [ If deviceTwinCallback is set and DEVICE_TWIN_UPDATE_COMPLETE has been encountered then IoTHubClientCore_LL_RetrievePropertyComplete shall call deviceTwinCallback.] */
+                handleData->deviceTwinCallback(update_state, payLoad, size, handleData->deviceTwinContextCallback);
+            }
+        }
+    }
+}
+
+static void IoTHubClientCore_LL_ReportedStateComplete(uint32_t item_id, int status_code, void* ctx)
+{
+    /* Codes_SRS_IOTHUBCLIENT_LL_07_002: [ if handle or queue_handle are NULL then IoTHubClientCore_LL_ReportedStateComplete shall do nothing. ] */
+    if (ctx == NULL)
+    {
+        /*"shall return"*/
+        LogError("Invalid argument handle=%p", ctx);
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)ctx;
+
+        /* Codes_SRS_IOTHUBCLIENT_LL_07_003: [ IoTHubClientCore_LL_ReportedStateComplete shall enumerate through the IOTHUB_DEVICE_TWIN structures in queue_handle. ]*/
+        DLIST_ENTRY* client_item = handleData->iot_ack_queue.Flink;
+        while (client_item != &(handleData->iot_ack_queue)) /*while we are not at the end of the list*/
+        {
+            PDLIST_ENTRY next_item = client_item->Flink;
+            IOTHUB_DEVICE_TWIN* queue_data = containingRecord(client_item, IOTHUB_DEVICE_TWIN, entry);
+            if (queue_data->item_id == item_id)
+            {
+                if (queue_data->reported_state_callback != NULL)
+                {
+                    queue_data->reported_state_callback(status_code, queue_data->context);
+                }
+                /*Codes_SRS_IOTHUBCLIENT_LL_07_009: [ IoTHubClientCore_LL_ReportedStateComplete shall remove the IOTHUB_DEVICE_TWIN item from the ack queue.]*/
+                DList_RemoveEntryList(client_item);
+                device_twin_data_destroy(queue_data);
+                break;
+            }
+            client_item = next_item;
+        }
+    }
+}
+
+static void IoTHubClientCore_LL_ConnectionStatusCallBack(IOTHUB_CLIENT_CONNECTION_STATUS status, IOTHUB_CLIENT_CONNECTION_STATUS_REASON reason, void* ctx)
+{
+    /*Codes_SRS_IOTHUBCLIENT_LL_25_113: [If parameter connectionStatus is NULL or parameter handle is NULL then IoTHubClientCore_LL_ConnectionStatusCallBack shall return.]*/
+    if (ctx == NULL)
+    {
+        /*"shall return"*/
+        LogError("invalid arg");
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)ctx;
+
+        /*Codes_SRS_IOTHUBCLIENT_LL_25_114: [IoTHubClientCore_LL_ConnectionStatusCallBack shall call non-callback set by the user from IoTHubClientCore_LL_SetConnectionStatusCallback passing the status, reason and the passed userContextCallback.]*/
+        if (handleData->conStatusCallback != NULL)
+        {
+            handleData->conStatusCallback(status, reason, handleData->conStatusUserContextCallback);
+        }
+    }
+
+}
+
+static const char* IoTHubClientCore_LL_GetProductInfo(void* ctx)
+{
+    const char* result;
+    if (ctx == NULL)
+    {
+        result = NULL;
+        LogError("invalid argument ctx %p", ctx);
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* iothub_data = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)ctx;
+        result = STRING_c_str(iothub_data->product_info);
+    }
+    return result;
+}
+
+static const char* IoTHubClientCore_LL_GetModelId(void* ctx)
+{
+    const char* result;
+    if (ctx == NULL)
+    {
+        result = NULL;
+        LogError("invalid argument ctx %p", ctx);
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* iothub_data = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)ctx;
+        result = STRING_c_str(iothub_data->model_id);
+    }
+    return result;
+}
+
+static bool IoTHubClientCore_LL_MessageCallbackFromInput(MESSAGE_CALLBACK_INFO* messageData, void* ctx)
+{
+    bool result;
+    IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)ctx;
+
+    if ((handleData == NULL) || messageData == NULL)
+    {
+        // Codes_SRS_IOTHUBCLIENT_LL_31_137: [ If either parameter `handle` or `messageData` is `NULL` then `IoTHubClient_LL_MessageCallbackFromInput` shall return `false`.** ]
+        LogError("invalid argument: handle(%p), messageData(%p)", handleData, messageData);
+        result = false;
+    }
+    else if (messageData->messageHandle == NULL)
+    {
+        // Codes_SRS_IOTHUBCLIENT_LL_31_137: [ If either parameter `handle` or `messageData` is `NULL` then `IoTHubClient_LL_MessageCallbackFromInput` shall return `false`.** ]
+        LogError("invalid argument messageData->messageHandle(NULL)");
+        result = false;
+    }
+    else if (handleData->event_callbacks == NULL)
+    {
+        LogError("Callback from input called but no input specific callbacks registered");
+        result = false;
+    }
+    else
+    {
+        const char* inputName = IoTHubMessage_GetInputName(messageData->messageHandle);
+
+        LIST_ITEM_HANDLE item_handle = NULL;
+
+        item_handle = singlylinkedlist_find(handleData->event_callbacks, is_event_equal_for_match, (const void*)inputName);
+
+        if (item_handle == NULL)
+        {
+            // Codes_SRS_IOTHUBCLIENT_LL_31_138: [ If there is no registered handler for the inputName from `IoTHubMessage_GetInputName`, then `IoTHubClient_LL_MessageCallbackFromInput` shall attempt invoke the default handler handler.** ]
+            item_handle = singlylinkedlist_find(handleData->event_callbacks, is_event_equal_for_match, NULL);
+        }
+
+        if (item_handle == NULL)
+        {
+            LogError("Could not find callback (explicit or default) for input queue %s", inputName);
+            result = false;
+        }
+        else
+        {
+            IOTHUB_EVENT_CALLBACK* event_callback = (IOTHUB_EVENT_CALLBACK*)singlylinkedlist_item_get_value(item_handle);
+            if (NULL == event_callback)
+            {
+                LogError("singlylinkedlist_item_get_value for event_callback failed");
+                result = false;
+            }
+            else
+            {
+                // Codes_SRS_IOTHUBCLIENT_LL_09_004: [IoTHubClient_LL_GetLastMessageReceiveTime shall return lastMessageReceiveTime in localtime]
+                handleData->lastMessageReceiveTime = get_time(NULL);
+
+                if (event_callback->callbackAsyncEx != NULL)
+                {
+                    // Codes_SRS_IOTHUBCLIENT_LL_31_139: [ `IoTHubClient_LL_MessageCallbackFromInput` shall the callback from the given inputName queue if it has been registered.** ]
+                    result = event_callback->callbackAsyncEx(messageData, event_callback->userContextCallbackEx);
+                }
+                else
+                {
+                    // Codes_SRS_IOTHUBCLIENT_LL_31_139: [ `IoTHubClient_LL_MessageCallbackFromInput` shall the callback from the given inputName queue if it has been registered.** ]
+                    IOTHUBMESSAGE_DISPOSITION_RESULT cb_result = event_callback->callbackAsync(messageData->messageHandle, event_callback->userContextCallback);
+
+                    // Codes_SRS_IOTHUBCLIENT_LL_31_140: [ `IoTHubClient_LL_MessageCallbackFromInput` shall send the message disposition as returned by the client to the underlying layer and return `true` if an input queue match is found.** ]
+                    if (handleData->IoTHubTransport_SendMessageDisposition(messageData, cb_result) != IOTHUB_CLIENT_OK)
+                    {
+                        LogError("IoTHubTransport_SendMessageDisposition failed");
+                    }
+                    result = true;
+                }
+            }
+        }
+    }
+    return result;
+}
+
+static bool IoTHubClientCore_LL_MessageCallback(MESSAGE_CALLBACK_INFO* messageData, void* ctx)
+{
+    bool result;
+    if ((ctx == NULL) || messageData == NULL)
+    {
+        /*Codes_SRS_IOTHUBCLIENT_LL_02_029: [If parameter handle is NULL then IoTHubClient_LL_MessageCallback shall return IOTHUBMESSAGE_ABANDONED.] */
+        LogError("invalid argument: ctx(%p), messageData(%p)", ctx, messageData);
+        result = false;
+    }
+    else if (messageData->messageHandle == NULL)
+    {
+        /*Codes_SRS_IOTHUBCLIENT_LL_10_004: [If messageHandle field of paramger messageData is NULL then IoTHubClient_LL_MessageCallback shall return IOTHUBMESSAGE_ABANDONED.] */
+        LogError("invalid argument messageData->messageHandle(NULL)");
+        result = false;
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)ctx;
+        return invoke_message_callback(handleData, messageData);
+    }
+    return result;
+}
+
+static int IoTHubClientCore_LL_DeviceMethodComplete(const char* method_name, const unsigned char* payLoad, size_t size, METHOD_HANDLE response_id, void* ctx)
+{
+    int result;
+    if (ctx == NULL)
+    {
+        /* Codes_SRS_IOTHUBCLIENT_LL_07_017: [ If handle or response is NULL then IoTHubClientCore_LL_DeviceMethodComplete shall return 500. ] */
+        LogError("Invalid argument ctx=%p", ctx);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        /* Codes_SRS_IOTHUBCLIENT_LL_07_018: [ If deviceMethodCallback is not NULL IoTHubClientCore_LL_DeviceMethodComplete shall execute deviceMethodCallback and return the status. ] */
+        IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)ctx;
+        switch (handleData->methodCallback.type)
+        {
+            case CALLBACK_TYPE_SYNC:
+            {
+                unsigned char* payload_resp = NULL;
+                size_t response_size = 0;
+                result = handleData->methodCallback.callbackSync(method_name, payLoad, size, &payload_resp, &response_size, handleData->methodCallback.userContextCallback);
+                /* Codes_SRS_IOTHUBCLIENT_LL_07_020: [ deviceMethodCallback shall build the BUFFER_HANDLE with the response payload from the IOTHUB_CLIENT_DEVICE_METHOD_CALLBACK_ASYNC callback. ] */
+                if (payload_resp != NULL && response_size > 0)
+                {
+                    result = handleData->IoTHubTransport_DeviceMethod_Response(handleData->deviceHandle, response_id, payload_resp, response_size, result);
+                }
+                else
+                {
+                    result = MU_FAILURE;
+                }
+                if (payload_resp != NULL)
+                {
+                    free(payload_resp);
+                }
+                break;
+            }
+            case CALLBACK_TYPE_ASYNC:
+                result = handleData->methodCallback.callbackAsync(method_name, payLoad, size, response_id, handleData->methodCallback.userContextCallback);
+                break;
+            default:
+                /* Codes_SRS_IOTHUBCLIENT_LL_07_019: [ If deviceMethodCallback is NULL IoTHubClientCore_LL_DeviceMethodComplete shall return 404. ] */
+                result = 0;
+                break;
+        }
+    }
+    return result;
+}
+
+static IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* initialize_iothub_client(const IOTHUB_CLIENT_CONFIG* client_config, const IOTHUB_CLIENT_DEVICE_CONFIG* device_config, bool use_dev_auth, const char* module_id)
+{
+    IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* result;
+    srand((unsigned int)get_time(NULL));
+
+    result = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)malloc(sizeof(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA));
+    if (result == NULL)
+    {
+        LogError("failure allocating IOTHUB_CLIENT_CORE_LL_HANDLE_DATA");
+    }
+    else
+    {
+        IOTHUB_CLIENT_CONFIG actual_config;
+        const IOTHUB_CLIENT_CONFIG* config = NULL;
+        char* IoTHubName = NULL;
+        char* IoTHubSuffix = NULL;
+
+        memset(result, 0, sizeof(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA));
+        if (use_dev_auth)
+        {
+            if ((result->authorization_module = IoTHubClient_Auth_CreateFromDeviceAuth(client_config->deviceId, module_id)) == NULL)
+            {
+                LogError("Failed create authorization module");
+                free(result);
+                result = NULL;
+            }
+        }
+        else
+        {
+            const char* device_key;
+            const char* device_id;
+            const char* sas_token;
+            if (device_config == NULL)
+            {
+                device_key = client_config->deviceKey;
+                device_id = client_config->deviceId;
+                sas_token = client_config->deviceSasToken;
+            }
+            else
+            {
+                device_key = device_config->deviceKey;
+                device_id = device_config->deviceId;
+                sas_token = device_config->deviceSasToken;
+            }
+
+            /* Codes_SRS_IOTHUBCLIENT_LL_07_029: [ IoTHubClientCore_LL_Create shall create the Auth module with the device_key, device_id, and/or deviceSasToken values ] */
+            if ((result->authorization_module = IoTHubClient_Auth_Create(device_key, device_id, sas_token, module_id)) == NULL)
+            {
+                LogError("Failed create authorization module");
+                free(result);
+                result = NULL;
+            }
+        }
+
+        if (result != NULL)
+        {
+            TRANSPORT_CALLBACKS_INFO transport_cb;
+            memset(&transport_cb, 0, sizeof(TRANSPORT_CALLBACKS_INFO));
+            transport_cb.send_complete_cb = IoTHubClientCore_LL_SendComplete;
+            transport_cb.twin_retrieve_prop_complete_cb = IoTHubClientCore_LL_RetrievePropertyComplete;
+            transport_cb.twin_rpt_state_complete_cb = IoTHubClientCore_LL_ReportedStateComplete;
+            transport_cb.connection_status_cb = IoTHubClientCore_LL_ConnectionStatusCallBack;
+            transport_cb.prod_info_cb = IoTHubClientCore_LL_GetProductInfo;
+            transport_cb.msg_input_cb = IoTHubClientCore_LL_MessageCallbackFromInput;
+            transport_cb.msg_cb = IoTHubClientCore_LL_MessageCallback;
+            transport_cb.method_complete_cb = IoTHubClientCore_LL_DeviceMethodComplete;
+            transport_cb.get_model_id_cb = IoTHubClientCore_LL_GetModelId;
+
+            if (client_config != NULL)
+            {
+                IOTHUBTRANSPORT_CONFIG lowerLayerConfig;
+                memset(&lowerLayerConfig, 0, sizeof(IOTHUBTRANSPORT_CONFIG));
+                /*Codes_SRS_IOTHUBCLIENT_LL_02_006: [IoTHubClientCore_LL_Create shall populate a structure of type IOTHUBTRANSPORT_CONFIG with the information from config parameter and the previous DLIST and shall pass that to the underlying layer _Create function.]*/
+                lowerLayerConfig.upperConfig = client_config;
+                lowerLayerConfig.waitingToSend = &(result->waitingToSend);
+                lowerLayerConfig.auth_module_handle = result->authorization_module;
+                lowerLayerConfig.moduleId = module_id;
+
+                setTransportProtocol(result, (TRANSPORT_PROVIDER*)client_config->protocol());
+                if ((result->transportHandle = result->IoTHubTransport_Create(&lowerLayerConfig, &transport_cb, result)) == NULL)
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_02_007: [If the underlaying layer _Create function fails them IoTHubClientCore_LL_Create shall fail and return NULL.] */
+                    LogError("underlying transport failed");
+                    destroy_blob_upload_module(result);
+                    destroy_module_method_module(result);
+                    tickcounter_destroy(result->tickCounter);
+                    IoTHubClient_Auth_Destroy(result->authorization_module);
+                    free(result);
+                    result = NULL;
+                }
+                else
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_02_008: [Otherwise, IoTHubClientCore_LL_Create shall succeed and return a non-NULL handle.] */
+                    result->isSharedTransport = false;
+                    config = client_config;
+                }
+            }
+            else
+            {
+                STRING_HANDLE transport_hostname = NULL;
+
+                result->transportHandle = device_config->transportHandle;
+                setTransportProtocol(result, (TRANSPORT_PROVIDER*)device_config->protocol());
+
+                if (result->IoTHubTransport_SetCallbackContext(result->transportHandle, result) != 0)
+                {
+                    LogError("unable to set transport callbacks");
+                    IoTHubClient_Auth_Destroy(result->authorization_module);
+                    free(result);
+                    result = NULL;
+                }
+                else if ((transport_hostname = result->IoTHubTransport_GetHostname(result->transportHandle)) == NULL)
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_02_097: [ If creating the data structures fails or instantiating the IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE fails then IoTHubClientCore_LL_CreateWithTransport shall fail and return NULL. ]*/
+                    LogError("unable to determine the transport IoTHub name");
+                    IoTHubClient_Auth_Destroy(result->authorization_module);
+                    free(result);
+                    result = NULL;
+                }
+                else
+                {
+                    const char* hostname = STRING_c_str(transport_hostname);
+                    /*Codes_SRS_IOTHUBCLIENT_LL_02_096: [ IoTHubClientCore_LL_CreateWithTransport shall create the data structures needed to instantiate a IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE. ]*/
+                    /*the first '.' says where the iothubname finishes*/
+                    const char* whereIsDot = strchr(hostname, '.');
+                    if (whereIsDot == NULL)
+                    {
+                        /*Codes_SRS_IOTHUBCLIENT_LL_02_097: [ If creating the data structures fails or instantiating the IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE fails then IoTHubClientCore_LL_CreateWithTransport shall fail and return NULL. ]*/
+                        LogError("unable to determine the IoTHub name");
+                        IoTHubClient_Auth_Destroy(result->authorization_module);
+                        free(result);
+                        result = NULL;
+                    }
+                    else
+                    {
+                        size_t suffix_len = strlen(whereIsDot);
+                        /*Codes_SRS_IOTHUBCLIENT_LL_02_096: [ IoTHubClientCore_LL_CreateWithTransport shall create the data structures needed to instantiate a IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE. ]*/
+                        IoTHubName = (char*)malloc(whereIsDot - hostname + 1);
+                        if (IoTHubName == NULL)
+                        {
+                            /*Codes_SRS_IOTHUBCLIENT_LL_02_097: [ If creating the data structures fails or instantiating the IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE fails then IoTHubClientCore_LL_CreateWithTransport shall fail and return NULL. ]*/
+                            LogError("unable to malloc");
+                            IoTHubClient_Auth_Destroy(result->authorization_module);
+                            free(result);
+                            result = NULL;
+                        }
+                        else if ((IoTHubSuffix = (char*)malloc(suffix_len + 1)) == NULL)
+                        {
+                            /*Codes_SRS_IOTHUBCLIENT_LL_02_097: [ If creating the data structures fails or instantiating the IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE fails then IoTHubClientCore_LL_CreateWithTransport shall fail and return NULL. ]*/
+                            LogError("unable to malloc");
+                            IoTHubClient_Auth_Destroy(result->authorization_module);
+                            free(result);
+                            result = NULL;
+                        }
+                        else
+                        {
+                            memset(IoTHubName, 0, whereIsDot - hostname + 1);
+                            (void)memcpy(IoTHubName, hostname, whereIsDot - hostname);
+                            (void)strcpy(IoTHubSuffix, whereIsDot+1);
+
+                            actual_config.deviceId = device_config->deviceId;
+                            actual_config.deviceKey = device_config->deviceKey;
+                            actual_config.deviceSasToken = device_config->deviceSasToken;
+                            actual_config.iotHubName = IoTHubName;
+                            actual_config.iotHubSuffix = IoTHubSuffix;
+                            actual_config.protocol = NULL; /*irrelevant to IoTHubClientCore_LL_UploadToBlob*/
+                            actual_config.protocolGatewayHostName = NULL; /*irrelevant to IoTHubClientCore_LL_UploadToBlob*/
+
+                            config = &actual_config;
+
+                            /*Codes_SRS_IOTHUBCLIENT_LL_02_008: [Otherwise, IoTHubClientCore_LL_Create shall succeed and return a non-NULL handle.] */
+                            result->isSharedTransport = true;
+                        }
+                    }
+                }
+                STRING_delete(transport_hostname);
+            }
+        }
+        if (result != NULL)
+        {
+            if (create_blob_upload_module(result, config) != 0)
+            {
+                LogError("unable to create blob upload");
+                // Codes_SRS_IOTHUBCLIENT_LL_09_010: [ If any failure occurs `IoTHubClientCore_LL_Create` shall destroy the `transportHandle` only if it has created it ]
+                if (!result->isSharedTransport)
+                {
+                    result->IoTHubTransport_Destroy(result->transportHandle);
+                }
+                destroy_blob_upload_module(result);
+                IoTHubClient_Auth_Destroy(result->authorization_module);
+                free(result);
+                result = NULL;
+            }
+            else if ((module_id != NULL) && create_edge_handle(result, config, module_id) != 0)
+            {
+                LogError("unable to create module method handle");
+                if (!result->isSharedTransport)
+                {
+                    result->IoTHubTransport_Destroy(result->transportHandle);
+                }
+                destroy_blob_upload_module(result);
+                IoTHubClient_Auth_Destroy(result->authorization_module);
+                free(result);
+                result = NULL;
+            }
+            else
+            {
+                PLATFORM_INFO_OPTION supportedPlatformInfo;
+                if ((result->tickCounter = tickcounter_create()) == NULL)
+                {
+                    LogError("unable to get a tickcounter");
+                    // Codes_SRS_IOTHUBCLIENT_LL_09_010: [ If any failure occurs `IoTHubClientCore_LL_Create` shall destroy the `transportHandle` only if it has created it ]
+                    if (!result->isSharedTransport)
+                    {
+                        result->IoTHubTransport_Destroy(result->transportHandle);
+                    }
+                    destroy_blob_upload_module(result);
+                    destroy_module_method_module(result);
+                    IoTHubClient_Auth_Destroy(result->authorization_module);
+                    free(result);
+                    result = NULL;
+                }
+                // Add extended info to product info if required
+                else if (result->IoTHubTransport_GetSupportedPlatformInfo(result->transportHandle, &supportedPlatformInfo) != 0)
+                {
+                    LogError("failed to get supported platform info");
+                    // Codes_SRS_IOTHUBCLIENT_LL_09_010: [ If any failure occurs `IoTHubClientCore_LL_Create` shall destroy the `transportHandle` only if it has created it ]
+                    if (!result->isSharedTransport)
+                    {
+                        result->IoTHubTransport_Destroy(result->transportHandle);
+                    }
+                    tickcounter_destroy(result->tickCounter);
+                    destroy_blob_upload_module(result);
+                    destroy_module_method_module(result);
+                    IoTHubClient_Auth_Destroy(result->authorization_module);
+                    free(result);
+                    result = NULL;
+                }
+                else if ((result->product_info = make_product_info(NULL, supportedPlatformInfo)) == NULL)
+                {
+                    LogError("failed to initialize product info");
+                    // Codes_SRS_IOTHUBCLIENT_LL_09_010: [ If any failure occurs `IoTHubClientCore_LL_Create` shall destroy the `transportHandle` only if it has created it ]
+                    if (!result->isSharedTransport)
+                    {
+                        result->IoTHubTransport_Destroy(result->transportHandle);
+                    }
+                    tickcounter_destroy(result->tickCounter);
+                    destroy_blob_upload_module(result);
+                    destroy_module_method_module(result);
+                    IoTHubClient_Auth_Destroy(result->authorization_module);
+                    free(result);
+                    result = NULL;
+                }
+                else
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_02_004: [Otherwise IoTHubClientCore_LL_Create shall initialize a new DLIST (further called "waitingToSend") containing records with fields of the following types: IOTHUB_MESSAGE_HANDLE, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK, void*.]*/
+                    DList_InitializeListHead(&(result->waitingToSend));
+                    DList_InitializeListHead(&(result->iot_msg_queue));
+                    DList_InitializeListHead(&(result->iot_ack_queue));
+                    result->messageCallback.type = CALLBACK_TYPE_NONE;
+                    result->methodCallback.type = CALLBACK_TYPE_NONE;
+                    result->lastMessageReceiveTime = INDEFINITE_TIME;
+                    result->data_msg_id = 1;
+
+                    IOTHUB_DEVICE_CONFIG deviceConfig;
+                    deviceConfig.deviceId = config->deviceId;
+                    deviceConfig.deviceKey = config->deviceKey;
+                    deviceConfig.deviceSasToken = config->deviceSasToken;
+                    deviceConfig.authorization_module = result->authorization_module;
+                    deviceConfig.moduleId = module_id;
+
+                    /*Codes_SRS_IOTHUBCLIENT_LL_17_008: [IoTHubClientCore_LL_Create shall call the transport _Register function with a populated structure of type IOTHUB_DEVICE_CONFIG and waitingToSend list.] */
+                    if ((result->deviceHandle = result->IoTHubTransport_Register(result->transportHandle, &deviceConfig, &(result->waitingToSend))) == NULL)
+                    {
+                        LogError("Registering device in transport failed");
+                        IoTHubClient_Auth_Destroy(result->authorization_module);
+                        // Codes_SRS_IOTHUBCLIENT_LL_09_010: [ If any failure occurs `IoTHubClientCore_LL_Create` shall destroy the `transportHandle` only if it has created it ]
+                        if (!result->isSharedTransport)
+                        {
+                            result->IoTHubTransport_Destroy(result->transportHandle);
+                        }
+                        destroy_blob_upload_module(result);
+                        destroy_module_method_module(result);
+                        tickcounter_destroy(result->tickCounter);
+                        STRING_delete(result->product_info);
+                        free(result);
+                        result = NULL;
+                    }
+                    else
+                    {
+                        /*Codes_SRS_IOTHUBCLIENT_LL_02_042: [ By default, messages shall not timeout. ]*/
+                        result->currentMessageTimeout = 0;
+                        result->current_device_twin_timeout = 0;
+
+                        result->diagnostic_setting.currentMessageNumber = 0;
+                        result->diagnostic_setting.diagSamplingPercentage = 0;
+                        /*Codes_SRS_IOTHUBCLIENT_LL_25_124: [ `IoTHubClientCore_LL_Create` shall set the default retry policy as Exponential backoff with jitter and if succeed and return a `non-NULL` handle. ]*/
+                        if (IoTHubClientCore_LL_SetRetryPolicy(result, IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF_WITH_JITTER, 0) != IOTHUB_CLIENT_OK)
+                        {
+                            LogError("Setting default retry policy in transport failed");
+                            result->IoTHubTransport_Unregister(result->deviceHandle);
+                            IoTHubClient_Auth_Destroy(result->authorization_module);
+                            // Codes_SRS_IOTHUBCLIENT_LL_09_010: [ If any failure occurs `IoTHubClientCore_LL_Create` shall destroy the `transportHandle` only if it has created it ]
+                            if (!result->isSharedTransport)
+                            {
+                                result->IoTHubTransport_Destroy(result->transportHandle);
+                            }
+                            destroy_blob_upload_module(result);
+                            destroy_module_method_module(result);
+                            tickcounter_destroy(result->tickCounter);
+                            STRING_delete(result->product_info);
+                            free(result);
+                            result = NULL;
+                        }
+                    }
+                }
+            }
+        }
+        if (IoTHubName)
+        {
+            free(IoTHubName);
+        }
+        if (IoTHubSuffix)
+        {
+            free(IoTHubSuffix);
+        }
+    }
+    return result;
+}
+
+static uint32_t get_next_item_id(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData)
+{
+    if (handleData->data_msg_id+1 >= UINT32_MAX)
+    {
+        handleData->data_msg_id = 1;
+    }
+    else
+    {
+        handleData->data_msg_id++;
+    }
+    return handleData->data_msg_id;
+}
+
+static IOTHUB_DEVICE_TWIN* dev_twin_data_create(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData, uint32_t id, const unsigned char* reportedState, size_t size, IOTHUB_CLIENT_REPORTED_STATE_CALLBACK reportedStateCallback, void* userContextCallback)
+{
+    IOTHUB_DEVICE_TWIN* result = (IOTHUB_DEVICE_TWIN*)malloc(sizeof(IOTHUB_DEVICE_TWIN) );
+    if (result != NULL)
+    {
+        result->report_data_handle = CONSTBUFFER_Create(reportedState, size);
+        if (result->report_data_handle == NULL)
+        {
+            LogError("Failure allocating reported state data");
+            free(result);
+            result = NULL;
+        }
+        else
+        {
+            result->item_id = id;
+            result->ms_timesOutAfter = 0;
+            result->context = userContextCallback;
+            result->reported_state_callback = reportedStateCallback;
+            result->client_handle = handleData;
+            result->device_handle = handleData->deviceHandle;
+        }
+    }
+    else
+    {
+        LogError("Failure allocating device twin information");
+    }
+    return result;
+}
+
+static void on_get_device_twin_completed(DEVICE_TWIN_UPDATE_STATE update_state, const unsigned char* payLoad, size_t size, void* userContextCallback)
+{
+    if (userContextCallback == NULL)
+    {
+        LogError("Invalid argument (userContextCallback=NULL)");
+    }
+    else
+    {
+        GET_TWIN_CONTEXT* getTwinCtx = (GET_TWIN_CONTEXT*)userContextCallback;
+
+        getTwinCtx->callback(update_state, payLoad, size, getTwinCtx->context);
+
+        free(getTwinCtx);
+    }
+}
+
+static void delete_event(IOTHUB_EVENT_CALLBACK* event_callback)
+{
+    STRING_delete(event_callback->inputName);
+    free(event_callback->userContextCallbackEx);
+    free(event_callback);
+}
+
+static void delete_event_callback(const void* item, const void* action_context, bool* continue_processing)
+{
+    (void)action_context;
+    delete_event((IOTHUB_EVENT_CALLBACK*)item);
+    *continue_processing = true;
+}
+
+static void delete_event_callback_list(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData)
+{
+    if (handleData->event_callbacks != NULL)
+    {
+        singlylinkedlist_foreach(handleData->event_callbacks, delete_event_callback, NULL);
+        singlylinkedlist_destroy(handleData->event_callbacks);
+        handleData->event_callbacks = NULL;
+    }
+}
+
+
+IOTHUB_CLIENT_CORE_LL_HANDLE IoTHubClientCore_LL_CreateFromDeviceAuth(const char* iothub_uri, const char* device_id, IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol)
+{
+    IOTHUB_CLIENT_CORE_LL_HANDLE result;
+    if (iothub_uri == NULL || protocol == NULL || device_id == NULL)
+    {
+        LogError("Input parameter is NULL: iothub_uri: %p  protocol: %p device_id: %p", iothub_uri, protocol, device_id);
+        result = NULL;
+    }
+    else
+    {
+#ifdef USE_PROV_MODULE
+        IOTHUB_CLIENT_CONFIG* config = (IOTHUB_CLIENT_CONFIG*)malloc(sizeof(IOTHUB_CLIENT_CONFIG));
+        if (config == NULL)
+        {
+            /* Codes_SRS_IOTHUBCLIENT_LL_12_012: [If the allocation failed IoTHubClientCore_LL_CreateFromConnectionString  returns NULL]  */
+            LogError("Malloc failed");
+            result = NULL;
+        }
+        else
+        {
+            const char* iterator;
+            const char* initial;
+            char* iothub_name = NULL;
+            char* iothub_suffix = NULL;
+
+            memset(config, 0, sizeof(IOTHUB_CLIENT_CONFIG));
+            config->protocol = protocol;
+            config->deviceId = device_id;
+
+            // Find the iothub suffix
+            initial = iterator = iothub_uri;
+            while (iterator != NULL && *iterator != '\0')
+            {
+                if (*iterator == '.')
+                {
+                    size_t length = iterator - initial;
+                    iothub_name = (char*)malloc(length + 1);
+                    if (iothub_name != NULL)
+                    {
+                        memset(iothub_name, 0, length + 1);
+                        memcpy(iothub_name, initial, length);
+                        config->iotHubName = iothub_name;
+
+                        length = strlen(initial) - length - 1;
+                        iothub_suffix = (char*)malloc(length + 1);
+                        if (iothub_suffix != NULL)
+                        {
+                            memset(iothub_suffix, 0, length + 1);
+                            memcpy(iothub_suffix, iterator + 1, length);
+                            config->iotHubSuffix = iothub_suffix;
+                            break;
+                        }
+                        else
+                        {
+                            LogError("Failed to allocate iothub suffix");
+                            free(iothub_name);
+                            iothub_name = NULL;
+                            result = NULL;
+                        }
+                    }
+                    else
+                    {
+                        LogError("Failed to allocate iothub name");
+                        result = NULL;
+                    }
+                }
+                iterator++;
+            }
+
+            if (config->iotHubName == NULL || config->iotHubSuffix == NULL)
+            {
+                LogError("initialize iothub client");
+                result = NULL;
+            }
+            else
+            {
+                IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = initialize_iothub_client(config, NULL, true, NULL);
+                if (handleData == NULL)
+                {
+                    LogError("initialize iothub client");
+                    result = NULL;
+                }
+                else
+                {
+                    result = handleData;
+                }
+            }
+
+            free(iothub_name);
+            free(iothub_suffix);
+            free(config);
+        }
+#else
+        LogError("HSM module is not included");
+        result = NULL;
+#endif
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_CORE_LL_HANDLE IoTHubClientCore_LL_CreateFromConnectionString(const char* connectionString, IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol)
+{
+    IOTHUB_CLIENT_CORE_LL_HANDLE result;
+
+    /* Codes_SRS_IOTHUBCLIENT_LL_12_003: [IoTHubClientCore_LL_CreateFromConnectionString shall verify the input parameter and if it is NULL then return NULL] */
+    if (connectionString == NULL)
+    {
+        LogError("Input parameter is NULL: connectionString");
+        result = NULL;
+    }
+    else if (protocol == NULL)
+    {
+        LogError("Input parameter is NULL: protocol");
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_IOTHUBCLIENT_LL_12_004: [IoTHubClientCore_LL_CreateFromConnectionString shall allocate IOTHUB_CLIENT_CONFIG structure] */
+        IOTHUB_CLIENT_CONFIG* config = (IOTHUB_CLIENT_CONFIG*) malloc(sizeof(IOTHUB_CLIENT_CONFIG));
+        if (config == NULL)
+        {
+            /* Codes_SRS_IOTHUBCLIENT_LL_12_012: [If the allocation failed IoTHubClientCore_LL_CreateFromConnectionString  returns NULL]  */
+            LogError("Malloc failed");
+            result = NULL;
+        }
+        else
+        {
+            STRING_TOKENIZER_HANDLE tokenizer1 = NULL;
+            STRING_HANDLE connString = NULL;
+            STRING_HANDLE tokenString = NULL;
+            STRING_HANDLE valueString = NULL;
+            STRING_HANDLE hostNameString = NULL;
+            STRING_HANDLE hostSuffixString = NULL;
+            STRING_HANDLE deviceIdString = NULL;
+            STRING_HANDLE deviceKeyString = NULL;
+            STRING_HANDLE deviceSasTokenString = NULL;
+            STRING_HANDLE protocolGateway = NULL;
+            STRING_HANDLE moduleId = NULL;
+
+            memset(config, 0, sizeof(*config));
+            config->protocol = protocol;
+
+            /* Codes_SRS_IOTHUBCLIENT_LL_04_002: [If it does not, it shall pass the protocolGatewayHostName NULL.] */
+            config->protocolGatewayHostName = NULL;
+
+            if ((connString = STRING_construct(connectionString)) == NULL)
+            {
+                LogError("Error constructing connectiong String");
+                result = NULL;
+            }
+            else if ((tokenizer1 = STRING_TOKENIZER_create(connString)) == NULL)
+            {
+                LogError("Error creating Tokenizer");
+                result = NULL;
+            }
+            else if ((tokenString = STRING_new()) == NULL)
+            {
+                LogError("Error creating Token String");
+                result = NULL;
+            }
+            else if ((valueString = STRING_new()) == NULL)
+            {
+                LogError("Error creating Value String");
+                result = NULL;
+            }
+            else if ((hostNameString = STRING_new()) == NULL)
+            {
+                LogError("Error creating HostName String");
+                result = NULL;
+            }
+            else if ((hostSuffixString = STRING_new()) == NULL)
+            {
+                LogError("Error creating HostSuffix String");
+                result = NULL;
+            }
+            /* Codes_SRS_IOTHUBCLIENT_LL_12_005: [IoTHubClientCore_LL_CreateFromConnectionString shall try to parse the connectionString input parameter for the following structure: "Key1=value1;key2=value2;key3=value3..."] */
+            /* Codes_SRS_IOTHUBCLIENT_LL_12_006: [IoTHubClientCore_LL_CreateFromConnectionString shall verify the existence of the following Key/Value pairs in the connection string: HostName, DeviceId, SharedAccessKey, SharedAccessSignature or x509]  */
+            else
+            {
+                int isx509found = 0;
+                bool use_provisioning = false;
+                while ((STRING_TOKENIZER_get_next_token(tokenizer1, tokenString, "=") == 0))
+                {
+                    if (STRING_TOKENIZER_get_next_token(tokenizer1, valueString, ";") != 0)
+                    {
+                        LogError("Tokenizer error");
+                        break;
+                    }
+                    else
+                    {
+                        if (tokenString != NULL)
+                        {
+                            /* Codes_SRS_IOTHUBCLIENT_LL_12_010: [IoTHubClientCore_LL_CreateFromConnectionString shall fill up the IOTHUB_CLIENT_CONFIG structure using the following mapping: iotHubName = Name, iotHubSuffix = Suffix, deviceId = DeviceId, deviceKey = SharedAccessKey or deviceSasToken = SharedAccessSignature] */
+                            const char* s_token = STRING_c_str(tokenString);
+                            if (strcmp(s_token, HOSTNAME_TOKEN) == 0)
+                            {
+                                /* Codes_SRS_IOTHUBCLIENT_LL_12_009: [IoTHubClientCore_LL_CreateFromConnectionString shall split the value of HostName to Name and Suffix using the first "." as a separator] */
+                                STRING_TOKENIZER_HANDLE tokenizer2 = NULL;
+                                if ((tokenizer2 = STRING_TOKENIZER_create(valueString)) == NULL)
+                                {
+                                    LogError("Error creating Tokenizer");
+                                    break;
+                                }
+                                else
+                                {
+                                    /* Codes_SRS_IOTHUBCLIENT_LL_12_015: [If the string split failed, IoTHubClientCore_LL_CreateFromConnectionString returns NULL ] */
+                                    if (STRING_TOKENIZER_get_next_token(tokenizer2, hostNameString, ".") != 0)
+                                    {
+                                        LogError("Tokenizer error");
+                                        STRING_TOKENIZER_destroy(tokenizer2);
+                                        break;
+                                    }
+                                    else
+                                    {
+                                        config->iotHubName = STRING_c_str(hostNameString);
+                                        if (STRING_TOKENIZER_get_next_token(tokenizer2, hostSuffixString, ";") != 0)
+                                        {
+                                            LogError("Tokenizer error");
+                                            STRING_TOKENIZER_destroy(tokenizer2);
+                                            break;
+                                        }
+                                        else
+                                        {
+                                            config->iotHubSuffix = STRING_c_str(hostSuffixString);
+                                        }
+                                    }
+                                    STRING_TOKENIZER_destroy(tokenizer2);
+                                }
+                            }
+                            else if (strcmp(s_token, DEVICEID_TOKEN) == 0)
+                            {
+                                deviceIdString = STRING_clone(valueString);
+                                if (deviceIdString != NULL)
+                                {
+                                    config->deviceId = STRING_c_str(deviceIdString);
+                                }
+                                else
+                                {
+                                    LogError("Failure cloning device id string");
+                                    break;
+                                }
+                            }
+                            else if (strcmp(s_token, DEVICEKEY_TOKEN) == 0)
+                            {
+                                deviceKeyString = STRING_clone(valueString);
+                                if (deviceKeyString != NULL)
+                                {
+                                    config->deviceKey = STRING_c_str(deviceKeyString);
+                                }
+                                else
+                                {
+                                    LogError("Failure cloning device key string");
+                                    break;
+                                }
+                            }
+                            else if (strcmp(s_token, DEVICESAS_TOKEN) == 0)
+                            {
+                                deviceSasTokenString = STRING_clone(valueString);
+                                if (deviceSasTokenString != NULL)
+                                {
+                                    config->deviceSasToken = STRING_c_str(deviceSasTokenString);
+                                }
+                                else
+                                {
+                                    LogError("Failure cloning device sasToken string");
+                                    break;
+                                }
+                            }
+                            else if (strcmp(s_token, X509_TOKEN) == 0)
+                            {
+                                if (strcmp(STRING_c_str(valueString), X509_TOKEN_ONLY_ACCEPTABLE_VALUE) != 0)
+                                {
+                                    LogError("x509 option has wrong value, the only acceptable one is \"true\"");
+                                    break;
+                                }
+                                else
+                                {
+                                    isx509found = 1;
+                                }
+                            }
+                            else if (strcmp(s_token, PROVISIONING_TOKEN) == 0)
+                            {
+                                if (strcmp(STRING_c_str(valueString), PROVISIONING_ACCEPTABLE_VALUE) != 0)
+                                {
+                                    LogError("provisioning option has wrong value, the only acceptable one is \"true\"");
+                                    break;
+                                }
+                                else
+                                {
+                                    use_provisioning = 1;
+                                }
+                            }
+
+                            /* Codes_SRS_IOTHUBCLIENT_LL_04_001: [IoTHubClientCore_LL_CreateFromConnectionString shall verify the existence of key/value pair GatewayHostName. If it does exist it shall pass the value to IoTHubClientCore_LL_Create API.] */
+                            else if (strcmp(s_token, PROTOCOL_GATEWAY_HOST_TOKEN) == 0)
+                            {
+                                protocolGateway = STRING_clone(valueString);
+                                if (protocolGateway != NULL)
+                                {
+                                    config->protocolGatewayHostName = STRING_c_str(protocolGateway);
+                                }
+                                else
+                                {
+                                    LogError("Failure cloning protocol Gateway Name");
+                                    break;
+                                }
+                            }
+                            /*Codes_SRS_IOTHUBCLIENT_LL_31_126: [IoTHubClient_LL_CreateFromConnectionString shall optionally parse ModuleId, if present.] */
+                            else if (strcmp(s_token, MODULE_ID_TOKEN) == 0)
+                            {
+                                moduleId = STRING_clone(valueString);
+                                if (moduleId == NULL)
+                                {
+                                    LogError("Failure cloning moduleId string");
+                                    break;
+                                }
+                            }
+                            else
+                            {
+                                // If we get an unknown token, log it to error stream but do not cause a fatal error.
+                                LogError("Unknown token <%s> in connection string.  Ignoring error and continuing to parse", s_token);
+                            }
+                        }
+                    }
+                }
+                /* parsing is done - check the result */
+                if (config->iotHubName == NULL)
+                {
+                    LogError("iotHubName is not found");
+                    result = NULL;
+                }
+                else if (config->iotHubSuffix == NULL)
+                {
+                    LogError("iotHubSuffix is not found");
+                    result = NULL;
+                }
+                else if (config->deviceId == NULL)
+                {
+                    LogError("deviceId is not found");
+                    result = NULL;
+                }
+                else if (!(
+                    ((!use_provisioning && !isx509found) && (config->deviceSasToken == NULL) ^ (config->deviceKey == NULL)) ||
+                    ((use_provisioning || isx509found) && (config->deviceSasToken == NULL) && (config->deviceKey == NULL))
+                    ))
+                {
+                    LogError("invalid combination of x509, provisioning, deviceSasToken and deviceKey");
+                    result = NULL;
+                }
+                else
+                {
+                    /* Codes_SRS_IOTHUBCLIENT_LL_12_011: [IoTHubClientCore_LL_CreateFromConnectionString shall call into the IoTHubClientCore_LL_Create API with the current structure and returns with the return value of it] */
+                    result = initialize_iothub_client(config, NULL, use_provisioning, STRING_c_str(moduleId));
+                    if (result == NULL)
+                    {
+                        LogError("IoTHubClientCore_LL_Create failed");
+                    }
+                    else
+                    {
+                        /*return as is*/
+                    }
+                }
+            }
+            if (deviceSasTokenString != NULL)
+                STRING_delete(deviceSasTokenString);
+            if (deviceKeyString != NULL)
+                STRING_delete(deviceKeyString);
+            if (deviceIdString != NULL)
+                STRING_delete(deviceIdString);
+            if (hostSuffixString != NULL)
+                STRING_delete(hostSuffixString);
+            if (hostNameString != NULL)
+                STRING_delete(hostNameString);
+            if (valueString != NULL)
+                STRING_delete(valueString);
+            if (tokenString != NULL)
+                STRING_delete(tokenString);
+            if (connString != NULL)
+                STRING_delete(connString);
+            if (protocolGateway != NULL)
+                STRING_delete(protocolGateway);
+            if (moduleId != NULL)
+                STRING_delete(moduleId);
+
+            if (tokenizer1 != NULL)
+                STRING_TOKENIZER_destroy(tokenizer1);
+
+            free(config);
+        }
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_CORE_LL_HANDLE IoTHubClientCore_LL_CreateImpl(const IOTHUB_CLIENT_CONFIG* config, const char* module_id, bool use_dev_auth)
+{
+    IOTHUB_CLIENT_CORE_LL_HANDLE result;
+    /*Codes_SRS_IOTHUBCLIENT_LL_02_001: [IoTHubClientCore_LL_Create shall return NULL if config parameter is NULL or protocol field is NULL.]*/
+    if(
+        (config == NULL) ||
+        (config->protocol == NULL)
+        )
+    {
+        result = NULL;
+        LogError("invalid configuration (NULL detected)");
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = initialize_iothub_client(config, NULL, use_dev_auth, module_id);
+        if (handleData == NULL)
+        {
+            LogError("initialize iothub client");
+            result = NULL;
+        }
+        else
+        {
+            result = handleData;
+        }
+    }
+
+    return result;
+}
+
+IOTHUB_CLIENT_CORE_LL_HANDLE IoTHubClientCore_LL_Create(const IOTHUB_CLIENT_CONFIG* config)
+{
+    return IoTHubClientCore_LL_CreateImpl(config, NULL, false);
+}
+
+#ifdef USE_EDGE_MODULES
+IOTHUB_CLIENT_CORE_LL_HANDLE IoTHubClientCore_LL_CreateFromEnvironment(IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol)
+{
+    IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* result;
+    EDGE_ENVIRONMENT_VARIABLES edge_environment_variables;
+
+    memset(&edge_environment_variables, 0, sizeof(edge_environment_variables));
+
+    if (retrieve_edge_environment_variabes(&edge_environment_variables) != 0)
+    {
+        LogError("retrieve_edge_environment_variabes failed");
+        result = NULL;
+    }
+    // The presence of a connection string environment variable means we use it, ignoring other settings
+    else if (edge_environment_variables.connection_string != NULL)
+    {
+        if ((result = IoTHubClientCore_LL_CreateFromConnectionString(edge_environment_variables.connection_string, protocol)) == NULL)
+        {
+            LogError("IoTHubClientCore_LL_CreateFromConnectionString fails");
+        }
+    }
+    else if (iothub_security_init(IOTHUB_SECURITY_TYPE_HTTP_EDGE) != 0)
+    {
+        LogError("iothub_security_init failed");
+        result = NULL;
+    }
+    else
+    {
+        IOTHUB_CLIENT_CONFIG client_config;
+
+        memset(&client_config, 0, sizeof(client_config));
+        client_config.protocol = protocol;
+        client_config.deviceId = edge_environment_variables.device_id;
+        client_config.iotHubName = edge_environment_variables.iothub_name;
+        client_config.iotHubSuffix = edge_environment_variables.iothub_suffix;
+        client_config.protocolGatewayHostName = edge_environment_variables.gatewayhostname;
+
+        if ((result = IoTHubClientCore_LL_CreateImpl(&client_config, edge_environment_variables.module_id, true)) == NULL)
+        {
+            LogError("IoTHubClientCore_LL_CreateImpl fails");
+        }
+    }
+
+    if (result != NULL)
+    {
+        // Because the Edge Hub almost always use self-signed certificates, we need to specify which certificates to trust.  We need to do
+        // this regardless of how we created the underlying IOTHUB_CLIENT_CORE_LL_HANDLE_DATA.
+        IOTHUB_CLIENT_RESULT setTrustResult;
+        char* trustedCertificate = IoTHubClient_Auth_Get_TrustBundle(result->authorization_module, edge_environment_variables.ca_trusted_certificate_file);
+
+        if (trustedCertificate == NULL)
+        {
+            LogError("IoTHubClient_Auth_Get_TrustBundle failed");
+            IoTHubClientCore_LL_Destroy(result);
+            result = NULL;
+        }
+        else if ((setTrustResult = IoTHubClientCore_LL_SetOption(result, OPTION_TRUSTED_CERT, trustedCertificate)) != IOTHUB_CLIENT_OK)
+        {
+            LogError("IoTHubClientCore_LL_SetOption failed, err = %d", setTrustResult);
+            IoTHubClientCore_LL_Destroy(result);
+            result = NULL;
+        }
+
+        free(trustedCertificate);
+    }
+
+    free(edge_environment_variables.iothub_buffer);
+    return result;
+}
+#endif
+
+
+IOTHUB_CLIENT_CORE_LL_HANDLE IoTHubClientCore_LL_CreateWithTransport(const IOTHUB_CLIENT_DEVICE_CONFIG * config)
+{
+    IOTHUB_CLIENT_CORE_LL_HANDLE result;
+    /*Codes_SRS_IOTHUBCLIENT_LL_17_001: [IoTHubClientCore_LL_CreateWithTransport shall return NULL if config parameter is NULL, or protocol field is NULL or transportHandle is NULL.]*/
+    if (
+        (config == NULL) ||
+        (config->protocol == NULL) ||
+        (config->transportHandle == NULL) ||
+        /*Codes_SRS_IOTHUBCLIENT_LL_02_098: [ IoTHubClientCore_LL_CreateWithTransport shall fail and return NULL if both config->deviceKey AND config->deviceSasToken are NULL. ]*/
+        ((config->deviceKey == NULL) && (config->deviceSasToken == NULL))
+        )
+    {
+        result = NULL;
+        LogError("invalid configuration (NULL detected)");
+    }
+    else
+    {
+        result = initialize_iothub_client(NULL, config, false, NULL);
+    }
+    return result;
+}
+
+void IoTHubClientCore_LL_Destroy(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle)
+{
+    /*Codes_SRS_IOTHUBCLIENT_LL_02_009: [IoTHubClientCore_LL_Destroy shall do nothing if parameter iotHubClientHandle is NULL.]*/
+    if (iotHubClientHandle != NULL)
+    {
+        PDLIST_ENTRY unsend;
+        /*Codes_SRS_IOTHUBCLIENT_LL_17_010: [IoTHubClientCore_LL_Destroy  shall call the underlaying layer's _Unregister function] */
+        IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
+        handleData->IoTHubTransport_Unregister(handleData->deviceHandle);
+        if (handleData->isSharedTransport == false)
+        {
+            /*Codes_SRS_IOTHUBCLIENT_LL_02_010: [If iotHubClientHandle was not created by IoTHubClientCore_LL_CreateWithTransport, IoTHubClientCore_LL_Destroy  shall call the underlaying layer's _Destroy function.] */
+            handleData->IoTHubTransport_Destroy(handleData->transportHandle);
+        }
+        /*if any, remove the items currently not send*/
+        while ((unsend = DList_RemoveHeadList(&(handleData->waitingToSend))) != &(handleData->waitingToSend))
+        {
+            IOTHUB_MESSAGE_LIST* temp = containingRecord(unsend, IOTHUB_MESSAGE_LIST, entry);
+            /*Codes_SRS_IOTHUBCLIENT_LL_02_033: [Otherwise, IoTHubClientCore_LL_Destroy shall complete all the event message callbacks that are in the waitingToSend list with the result IOTHUB_CLIENT_CONFIRMATION_BECAUSE_DESTROY.] */
+            if (temp->callback != NULL)
+            {
+                temp->callback(IOTHUB_CLIENT_CONFIRMATION_BECAUSE_DESTROY, temp->context);
+            }
+            IoTHubMessage_Destroy(temp->messageHandle);
+            free(temp);
+        }
+
+        /* Codes_SRS_IOTHUBCLIENT_LL_07_007: [ IoTHubClientCore_LL_Destroy shall iterate the device twin queues and destroy any remaining items. ] */
+        while ((unsend = DList_RemoveHeadList(&(handleData->iot_msg_queue))) != &(handleData->iot_msg_queue))
+        {
+            IOTHUB_DEVICE_TWIN* temp = containingRecord(unsend, IOTHUB_DEVICE_TWIN, entry);
+
+            // The Twin reported properties status codes are based on HTTP codes and provided by the service.
+            // Following design already implemented in the transport layer, the status code shall be artificially 
+            // returned as zero to indicate the report was not sent due to the client being destroyed.
+            if (temp->reported_state_callback != NULL)
+            {
+                temp->reported_state_callback(ERROR_CODE_BECAUSE_DESTROY, temp->context);
+            }  
+
+            device_twin_data_destroy(temp);
+        }
+        while ((unsend = DList_RemoveHeadList(&(handleData->iot_ack_queue))) != &(handleData->iot_ack_queue))
+        {
+            IOTHUB_DEVICE_TWIN* temp = containingRecord(unsend, IOTHUB_DEVICE_TWIN, entry);
+
+            // The Twin reported properties status codes are based on HTTP codes and provided by the service.
+            // Following design already implemented in the transport layer, the status code shall be artificially 
+            // returned as zero to indicate the report was not sent due to the client being destroyed.
+            if (temp->reported_state_callback != NULL)
+            {
+                temp->reported_state_callback(ERROR_CODE_BECAUSE_DESTROY, temp->context);
+            }
+
+            device_twin_data_destroy(temp);
+        }
+
+        /* Codes_SRS_IOTHUBCLIENT_LL_31_141: [ IoTHubClient_LL_Destroy shall iterate registered callbacks for input queues and destroy any remaining items. ] */
+        delete_event_callback_list(handleData);
+
+        /*Codes_SRS_IOTHUBCLIENT_LL_17_011: [IoTHubClientCore_LL_Destroy  shall free the resources allocated by IoTHubClient (if any).] */
+        IoTHubClient_Auth_Destroy(handleData->authorization_module);
+        tickcounter_destroy(handleData->tickCounter);
+#ifndef DONT_USE_UPLOADTOBLOB
+        IoTHubClient_LL_UploadToBlob_Destroy(handleData->uploadToBlobHandle);
+#endif
+#ifdef USE_EDGE_MODULES
+        IoTHubClient_EdgeHandle_Destroy(handleData->methodHandle);
+#endif
+        STRING_delete(handleData->product_info);
+        STRING_delete(handleData->model_id);
+        free(handleData);
+    }
+}
+
+/*Codes_SRS_IOTHUBCLIENT_LL_02_044: [ Messages already delivered to IoTHubClientCore_LL shall not have their timeouts modified by a new call to IoTHubClientCore_LL_SetOption. ]*/
+/*returns 0 on success, any other value is error*/
+static int attach_ms_timesOutAfter(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData, IOTHUB_MESSAGE_LIST *newEntry)
+{
+    int result;
+    /*Codes_SRS_IOTHUBCLIENT_LL_02_043: [ Calling IoTHubClientCore_LL_SetOption with value set to "0" shall disable the timeout mechanism for all new messages. ]*/
+    if (handleData->currentMessageTimeout == 0)
+    {
+        newEntry->ms_timesOutAfter = 0; /*do not timeout*/
+        newEntry->message_timeout_value = 0;
+        result = 0;
+    }
+    else
+    {
+        /*Codes_SRS_IOTHUBCLIENT_LL_02_039: [ "messageTimeout" - once IoTHubClientCore_LL_SendEventAsync is called the message shall timeout after value miliseconds. Value is a pointer to a tickcounter_ms_t. ]*/
+        if (tickcounter_get_current_ms(handleData->tickCounter, &newEntry->ms_timesOutAfter) != 0)
+        {
+            result = MU_FAILURE;
+            LogError("unable to get the current relative tickcount");
+        }
+        else
+        {
+            newEntry->message_timeout_value = handleData->currentMessageTimeout;
+            result = 0;
+        }
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SendEventAsync(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_MESSAGE_HANDLE eventMessageHandle, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK eventConfirmationCallback, void* userContextCallback)
+{
+    IOTHUB_CLIENT_RESULT result;
+    /*Codes_SRS_IOTHUBCLIENT_LL_02_011: [IoTHubClientCore_LL_SendEventAsync shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter iotHubClientHandle or eventMessageHandle is NULL.]*/
+    if (
+        (iotHubClientHandle == NULL) ||
+        (eventMessageHandle == NULL) ||
+        /*Codes_SRS_IOTHUBCLIENT_LL_02_012: [IoTHubClientCore_LL_SendEventAsync shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter eventConfirmationCallback is NULL and userContextCallback is not NULL.] */
+        ((eventConfirmationCallback == NULL) && (userContextCallback != NULL))
+        )
+    {
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LOG_ERROR_RESULT;
+    }
+    else
+    {
+        IOTHUB_MESSAGE_LIST *newEntry = (IOTHUB_MESSAGE_LIST*)malloc(sizeof(IOTHUB_MESSAGE_LIST));
+        if (newEntry == NULL)
+        {
+            result = IOTHUB_CLIENT_ERROR;
+            LOG_ERROR_RESULT;
+        }
+        else
+        {
+            IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
+
+            if (attach_ms_timesOutAfter(handleData, newEntry) != 0)
+            {
+                result = IOTHUB_CLIENT_ERROR;
+                LOG_ERROR_RESULT;
+                free(newEntry);
+            }
+            else
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_02_013: [IoTHubClientCore_LL_SendEventAsync shall add the DLIST waitingToSend a new record cloning the information from eventMessageHandle, eventConfirmationCallback, userContextCallback.]*/
+                if ((newEntry->messageHandle = IoTHubMessage_Clone(eventMessageHandle)) == NULL)
+                {
+                    result = IOTHUB_CLIENT_ERROR;
+                    free(newEntry);
+                    LOG_ERROR_RESULT;
+                }
+                else if (IoTHubClient_Diagnostic_AddIfNecessary(&handleData->diagnostic_setting, newEntry->messageHandle) != 0)
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_02_014: [If cloning and/or adding the information/diagnostic fails for any reason, IoTHubClientCore_LL_SendEventAsync shall fail and return IOTHUB_CLIENT_ERROR.] */
+                    result = IOTHUB_CLIENT_ERROR;
+                    IoTHubMessage_Destroy(newEntry->messageHandle);
+                    free(newEntry);
+                    LOG_ERROR_RESULT;
+                }
+                else
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_02_013: [IoTHubClientCore_LL_SendEventAsync shall add the DLIST waitingToSend a new record cloning the information from eventMessageHandle, eventConfirmationCallback, userContextCallback.]*/
+                    newEntry->callback = eventConfirmationCallback;
+                    newEntry->context = userContextCallback;
+                    DList_InsertTailList(&(iotHubClientHandle->waitingToSend), &(newEntry->entry));
+                    /*Codes_SRS_IOTHUBCLIENT_LL_02_015: [Otherwise IoTHubClientCore_LL_SendEventAsync shall succeed and return IOTHUB_CLIENT_OK.] */
+                    result = IOTHUB_CLIENT_OK;
+                }
+            }
+        }
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SetMessageCallback(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC messageCallback, void* userContextCallback)
+{
+    IOTHUB_CLIENT_RESULT result;
+    if (iotHubClientHandle == NULL)
+    {
+        /*Codes_SRS_IOTHUBCLIENT_LL_02_016: [IoTHubClientCore_LL_SetMessageCallback shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter iotHubClientHandle is NULL.] */
+        LogError("Invalid argument - iotHubClientHandle is NULL");
+        result = IOTHUB_CLIENT_INVALID_ARG;
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
+        if (messageCallback == NULL)
+        {
+            if (handleData->messageCallback.type == CALLBACK_TYPE_NONE)
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_10_010: [If parameter messageCallback is NULL and the _SetMessageCallback had not been called to subscribe for messages, then IoTHubClientCore_LL_SetMessageCallback shall fail and return IOTHUB_CLIENT_ERROR.] */
+                LogError("not currently set to accept or process incoming messages.");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else if (handleData->messageCallback.type == CALLBACK_TYPE_ASYNC)
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_10_010: [If parameter messageCallback is NULL and the _SetMessageCallback had not been called to subscribe for messages, then IoTHubClientCore_LL_SetMessageCallback shall fail and return IOTHUB_CLIENT_ERROR.] */
+                LogError("Invalid workflow sequence. Please unsubscribe using the IoTHubClientCore_LL_SetMessageCallback_Ex function.");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_02_019: [If parameter messageCallback is NULL then IoTHubClientCore_LL_SetMessageCallback shall call the underlying layer's _Unsubscribe function and return IOTHUB_CLIENT_OK.] */
+                handleData->IoTHubTransport_Unsubscribe(handleData->deviceHandle);
+                handleData->messageCallback.type = CALLBACK_TYPE_NONE;
+                handleData->messageCallback.callbackSync = NULL;
+                handleData->messageCallback.callbackAsync = NULL;
+                handleData->messageCallback.userContextCallback = NULL;
+                result = IOTHUB_CLIENT_OK;
+            }
+        }
+        else
+        {
+            if (handleData->messageCallback.type == CALLBACK_TYPE_ASYNC)
+            {
+                /* Codes_SRS_IOTHUBCLIENT_LL_10_011: [If parameter messageCallback is non-NULL and the _SetMessageCallback_Ex had been used to susbscribe for messages, then IoTHubClientCore_LL_SetMessageCallback shall fail and return IOTHUB_CLIENT_ERROR.] */
+                LogError("Invalid workflow sequence. Please unsubscribe using the IoTHubClientCore_LL_SetMessageCallback_Ex function before subscribing with MessageCallback.");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else
+            {
+                if (handleData->IoTHubTransport_Subscribe(handleData->deviceHandle) == 0)
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_02_017: [If parameter messageCallback is non-NULL then IoTHubClientCore_LL_SetMessageCallback shall call the underlying layer's _Subscribe function.]*/
+                    handleData->messageCallback.type = CALLBACK_TYPE_SYNC;
+                    handleData->messageCallback.callbackSync = messageCallback;
+                    handleData->messageCallback.userContextCallback = userContextCallback;
+                    result = IOTHUB_CLIENT_OK;
+                }
+                else
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_02_018: [If the underlying layer's _Subscribe function fails, then IoTHubClientCore_LL_SetMessageCallback shall fail and return IOTHUB_CLIENT_ERROR. Otherwise IoTHubClientCore_LL_SetMessageCallback shall succeed and return IOTHUB_CLIENT_OK.]*/
+                    LogError("IoTHubTransport_Subscribe failed");
+                    handleData->messageCallback.type = CALLBACK_TYPE_NONE;
+                    handleData->messageCallback.callbackSync = NULL;
+                    handleData->messageCallback.callbackAsync = NULL;
+                    handleData->messageCallback.userContextCallback = NULL;
+                    result = IOTHUB_CLIENT_ERROR;
+                }
+            }
+        }
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SetMessageCallback_Ex(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC_EX messageCallback, void* userContextCallback)
+{
+    IOTHUB_CLIENT_RESULT result;
+    if (iotHubClientHandle == NULL)
+    {
+        /*Codes_SRS_IOTHUBCLIENT_LL_10_021: [IoTHubClientCore_LL_SetMessageCallback_Ex shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter iotHubClientHandle is NULL.]*/
+        LogError("Invalid argument - iotHubClientHandle is NULL");
+        result = IOTHUB_CLIENT_INVALID_ARG;
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
+        if (messageCallback == NULL)
+        {
+            if (handleData->messageCallback.type == CALLBACK_TYPE_NONE)
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_10_018: [If parameter messageCallback is NULL and IoTHubClientCore_LL_SetMessageCallback_Ex had not been used to subscribe for messages, then IoTHubClientCore_LL_SetMessageCallback_Ex shall fail and return IOTHUB_CLIENT_ERROR.] */
+                LogError("not currently set to accept or process incoming messages.");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else if (handleData->messageCallback.type == CALLBACK_TYPE_SYNC)
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_10_019: [If parameter messageCallback is NULL and IoTHubClientCore_LL_SetMessageCallback had been used to subscribe for messages, then IoTHubClientCore_LL_SetMessageCallback_Ex shall fail and return IOTHUB_CLIENT_ERROR.] */
+                LogError("Invalid workflow sequence. Please unsubscribe using the IoTHubClientCore_LL_SetMessageCallback function.");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_10_023: [If parameter messageCallback is NULL then IoTHubClientCore_LL_SetMessageCallback_Ex shall call the underlying layer's _Unsubscribe function and return IOTHUB_CLIENT_OK.] */
+                handleData->IoTHubTransport_Unsubscribe(handleData->deviceHandle);
+                handleData->messageCallback.type = CALLBACK_TYPE_NONE;
+                handleData->messageCallback.callbackSync = NULL;
+                handleData->messageCallback.callbackAsync = NULL;
+                handleData->messageCallback.userContextCallback = NULL;
+                result = IOTHUB_CLIENT_OK;
+            }
+        }
+        else
+        {
+            if (handleData->messageCallback.type == CALLBACK_TYPE_SYNC)
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_10_020: [If parameter messageCallback is non-NULL, and IoTHubClientCore_LL_SetMessageCallback had been used to subscribe for messages, then IoTHubClientCore_LL_SetMessageCallback_Ex shall fail and return IOTHUB_CLIENT_ERROR.] */
+                LogError("Invalid workflow sequence. Please unsubscribe using the IoTHubClientCore_LL_MessageCallbackEx function before subscribing with MessageCallback.");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else
+            {
+                if (handleData->IoTHubTransport_Subscribe(handleData->deviceHandle) == 0)
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_10_024: [If parameter messageCallback is non-NULL then IoTHubClientCore_LL_SetMessageCallback_Ex shall call the underlying layer's _Subscribe function.]*/
+                    handleData->messageCallback.type = CALLBACK_TYPE_ASYNC;
+                    handleData->messageCallback.callbackAsync = messageCallback;
+                    handleData->messageCallback.userContextCallback = userContextCallback;
+                    result = IOTHUB_CLIENT_OK;
+                }
+                else
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_10_025: [If the underlying layer's _Subscribe function fails, then IoTHubClientCore_LL_SetMessageCallback_Ex shall fail and return IOTHUB_CLIENT_ERROR. Otherwise IoTHubClientCore_LL_SetMessageCallback_Ex shall succeed and return IOTHUB_CLIENT_OK.] */
+                    LogError("IoTHubTransport_Subscribe failed");
+                    handleData->messageCallback.type = CALLBACK_TYPE_NONE;
+                    handleData->messageCallback.callbackSync = NULL;
+                    handleData->messageCallback.callbackAsync = NULL;
+                    handleData->messageCallback.userContextCallback = NULL;
+                    result = IOTHUB_CLIENT_ERROR;
+                }
+            }
+        }
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SendMessageDisposition(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, MESSAGE_CALLBACK_INFO* message_data, IOTHUBMESSAGE_DISPOSITION_RESULT disposition)
+{
+    IOTHUB_CLIENT_RESULT result;
+    if ((iotHubClientHandle == NULL) || (message_data == NULL))
+    {
+        /*Codes_SRS_IOTHUBCLIENT_LL_10_026: [IoTHubClientCore_LL_SendMessageDisposition shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter iotHubClientHandle is NULL.]*/
+        LogError("Invalid argument handle=%p, message=%p", iotHubClientHandle, message_data);
+        result = IOTHUB_CLIENT_INVALID_ARG;
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
+        /*Codes_SRS_IOTHUBCLIENT_LL_10_027: [IoTHubClientCore_LL_SendMessageDisposition shall return the result from calling the underlying layer's _Send_Message_Disposition.]*/
+        result = handleData->IoTHubTransport_SendMessageDisposition(message_data, disposition);
+    }
+    return result;
+}
+
+static void DoTimeouts(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData)
+{
+    tickcounter_ms_t nowTick;
+    if (tickcounter_get_current_ms(handleData->tickCounter, &nowTick) != 0)
+    {
+        LogError("unable to get the current ms, timeouts will not be processed");
+    }
+    else
+    {
+        DLIST_ENTRY* currentItemInWaitingToSend = handleData->waitingToSend.Flink;
+        while (currentItemInWaitingToSend != &(handleData->waitingToSend)) /*while we are not at the end of the list*/
+        {
+            IOTHUB_MESSAGE_LIST* fullEntry = containingRecord(currentItemInWaitingToSend, IOTHUB_MESSAGE_LIST, entry);
+            /*Codes_SRS_IOTHUBCLIENT_LL_02_041: [ If more than value miliseconds have passed since the call to IoTHubClientCore_LL_SendEventAsync then the message callback shall be called with a status code of IOTHUB_CLIENT_CONFIRMATION_TIMEOUT. ]*/
+            if ((fullEntry->ms_timesOutAfter != 0) && ((nowTick - fullEntry->ms_timesOutAfter) > fullEntry->message_timeout_value))
+            {
+                PDLIST_ENTRY theNext = currentItemInWaitingToSend->Flink; /*need to save the next item, because the below operations are destructive*/
+                DList_RemoveEntryList(currentItemInWaitingToSend);
+                if (fullEntry->callback != NULL)
+                {
+                    fullEntry->callback(IOTHUB_CLIENT_CONFIRMATION_MESSAGE_TIMEOUT, fullEntry->context);
+                }
+                IoTHubMessage_Destroy(fullEntry->messageHandle); /*because it has been cloned*/
+                free(fullEntry);
+                currentItemInWaitingToSend = theNext;
+            }
+            else
+            {
+                currentItemInWaitingToSend = currentItemInWaitingToSend->Flink;
+            }
+        }
+    }
+}
+
+void IoTHubClientCore_LL_DoWork(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle)
+{
+    /*Codes_SRS_IOTHUBCLIENT_LL_02_020: [If parameter iotHubClientHandle is NULL then IoTHubClientCore_LL_DoWork shall not perform any action.] */
+    if (iotHubClientHandle != NULL)
+    {
+        IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
+        DoTimeouts(handleData);
+
+        /*Codes_SRS_IOTHUBCLIENT_LL_07_008: [ IoTHubClientCore_LL_DoWork shall iterate the message queue and execute the underlying transports IoTHubTransport_ProcessItem function for each item. ] */
+        DLIST_ENTRY* client_item = handleData->iot_msg_queue.Flink;
+        while (client_item != &(handleData->iot_msg_queue)) /*while we are not at the end of the list*/
+        {
+            PDLIST_ENTRY next_item = client_item->Flink;
+
+            IOTHUB_DEVICE_TWIN* queue_data = containingRecord(client_item, IOTHUB_DEVICE_TWIN, entry);
+            IOTHUB_IDENTITY_INFO identity_info;
+            identity_info.device_twin = queue_data;
+            IOTHUB_PROCESS_ITEM_RESULT process_results =  handleData->IoTHubTransport_ProcessItem(handleData->transportHandle, IOTHUB_TYPE_DEVICE_TWIN, &identity_info);
+            if (process_results == IOTHUB_PROCESS_CONTINUE || process_results == IOTHUB_PROCESS_NOT_CONNECTED)
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_07_010: [ If 'IoTHubTransport_ProcessItem' returns IOTHUB_PROCESS_CONTINUE or IOTHUB_PROCESS_NOT_CONNECTED IoTHubClientCore_LL_DoWork shall continue on to call the underlaying layer's _DoWork function. ]*/
+                break;
+            }
+            else
+            {
+                DList_RemoveEntryList(client_item);
+                if (process_results == IOTHUB_PROCESS_OK)
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_07_011: [ If 'IoTHubTransport_ProcessItem' returns IOTHUB_PROCESS_OK IoTHubClientCore_LL_DoWork shall add the IOTHUB_DEVICE_TWIN to the ack queue. ]*/
+                    DList_InsertTailList(&(iotHubClientHandle->iot_ack_queue), &(queue_data->entry));
+                }
+                else
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_07_012: [ If 'IoTHubTransport_ProcessItem' returns any other value IoTHubClientCore_LL_DoWork shall destroy the IOTHUB_DEVICE_TWIN item. ]*/
+                    LogError("Failure queue processing item");
+                    device_twin_data_destroy(queue_data);
+                }
+            }
+            // Move along to the next item
+            client_item = next_item;
+        }
+
+        /*Codes_SRS_IOTHUBCLIENT_LL_02_021: [Otherwise, IoTHubClientCore_LL_DoWork shall invoke the underlaying layer's _DoWork function.]*/
+        handleData->IoTHubTransport_DoWork(handleData->transportHandle);
+    }
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_GetSendStatus(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_STATUS *iotHubClientStatus)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    /* Codes_SRS_IOTHUBCLIENT_09_007: [IoTHubClient_GetSendStatus shall return IOTHUB_CLIENT_INVALID_ARG if called with NULL parameter] */
+    if (iotHubClientHandle == NULL || iotHubClientStatus == NULL)
+    {
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LOG_ERROR_RESULT;
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
+
+        /* Codes_SRS_IOTHUBCLIENT_09_008: [IoTHubClient_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_IDLE if there is currently no items to be sent] */
+        /* Codes_SRS_IOTHUBCLIENT_09_009: [IoTHubClient_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_BUSY if there are currently items to be sent] */
+        result = handleData->IoTHubTransport_GetSendStatus(handleData->deviceHandle, iotHubClientStatus);
+    }
+
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SetConnectionStatusCallback(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_CONNECTION_STATUS_CALLBACK connectionStatusCallback, void * userContextCallback)
+{
+    IOTHUB_CLIENT_RESULT result;
+    /*Codes_SRS_IOTHUBCLIENT_LL_25_111: [IoTHubClientCore_LL_SetConnectionStatusCallback shall return IOTHUB_CLIENT_INVALID_ARG if called with NULL parameter iotHubClientHandle**]** */
+    if (iotHubClientHandle == NULL)
+    {
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LOG_ERROR_RESULT;
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
+        /*Codes_SRS_IOTHUBCLIENT_LL_25_112: [IoTHubClientCore_LL_SetConnectionStatusCallback shall return IOTHUB_CLIENT_OK and save the callback and userContext as a member of the handle.] */
+        handleData->conStatusCallback = connectionStatusCallback;
+        handleData->conStatusUserContextCallback = userContextCallback;
+        result = IOTHUB_CLIENT_OK;
+    }
+
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SetRetryPolicy(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY retryPolicy, size_t retryTimeoutLimitInSeconds)
+{
+    IOTHUB_CLIENT_RESULT result;
+    IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
+
+    /* Codes_SRS_IOTHUBCLIENT_LL_25_116: [If iotHubClientHandle, retryPolicy or retryTimeoutLimitinSeconds is NULL, IoTHubClientCore_LL_GetRetryPolicy shall return IOTHUB_CLIENT_INVALID_ARG]*/
+    if (handleData == NULL)
+    {
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LOG_ERROR_RESULT;
+    }
+    else
+    {
+        if (handleData->transportHandle == NULL)
+        {
+            result = IOTHUB_CLIENT_ERROR;
+            LOG_ERROR_RESULT;
+        }
+        else
+        {
+            if (handleData->IoTHubTransport_SetRetryPolicy(handleData->transportHandle, retryPolicy, retryTimeoutLimitInSeconds) != 0)
+            {
+                result = IOTHUB_CLIENT_ERROR;
+                LOG_ERROR_RESULT;
+            }
+            else
+            {
+                /* Codes_SRS_IOTHUBCLIENT_LL_25_118: [IoTHubClientCore_LL_SetRetryPolicy shall save connection retry policies specified by the user to retryPolicy in struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA] */
+                /* Codes_SRS_IOTHUBCLIENT_LL_25_119: [IoTHubClientCore_LL_SetRetryPolicy shall save retryTimeoutLimitInSeconds in seconds to retryTimeout in struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA] */
+                handleData->retryPolicy = retryPolicy;
+                handleData->retryTimeoutLimitInSeconds = retryTimeoutLimitInSeconds;
+                result = IOTHUB_CLIENT_OK;
+            }
+        }
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_GetRetryPolicy(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY* retryPolicy, size_t* retryTimeoutLimitInSeconds)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    /* Codes_SRS_IOTHUBCLIENT_LL_09_001: [IoTHubClientCore_LL_GetLastMessageReceiveTime shall return IOTHUB_CLIENT_INVALID_ARG if any of the arguments is NULL] */
+    if (iotHubClientHandle == NULL || retryPolicy == NULL || retryTimeoutLimitInSeconds == NULL)
+    {
+        LogError("Invalid parameter IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle = %p, IOTHUB_CLIENT_RETRY_POLICY* retryPolicy = %p, size_t* retryTimeoutLimitInSeconds = %p", iotHubClientHandle, retryPolicy, retryTimeoutLimitInSeconds);
+        result = IOTHUB_CLIENT_INVALID_ARG;
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
+
+        *retryPolicy = handleData->retryPolicy;
+        *retryTimeoutLimitInSeconds = handleData->retryTimeoutLimitInSeconds;
+        result = IOTHUB_CLIENT_OK;
+    }
+
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_GetLastMessageReceiveTime(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, time_t* lastMessageReceiveTime)
+{
+    IOTHUB_CLIENT_RESULT result;
+    IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
+
+    /* Codes_SRS_IOTHUBCLIENT_LL_09_001: [IoTHubClientCore_LL_GetLastMessageReceiveTime shall return IOTHUB_CLIENT_INVALID_ARG if any of the arguments is NULL] */
+    if (handleData == NULL || lastMessageReceiveTime == NULL)
+    {
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LOG_ERROR_RESULT;
+    }
+    else
+    {
+        /* Codes_SRS_IOTHUBCLIENT_LL_09_002: [IoTHubClientCore_LL_GetLastMessageReceiveTime shall return IOTHUB_CLIENT_INDEFINITE_TIME - and not set 'lastMessageReceiveTime' - if it is unable to provide the time for the last commands] */
+        if (handleData->lastMessageReceiveTime == INDEFINITE_TIME)
+        {
+            result = IOTHUB_CLIENT_INDEFINITE_TIME;
+            LOG_ERROR_RESULT;
+        }
+        else
+        {
+            /* Codes_SRS_IOTHUBCLIENT_LL_09_003: [IoTHubClientCore_LL_GetLastMessageReceiveTime shall return IOTHUB_CLIENT_OK if it wrote in the lastMessageReceiveTime the time when the last command was received] */
+            /* Codes_SRS_IOTHUBCLIENT_LL_09_004: [IoTHubClientCore_LL_GetLastMessageReceiveTime shall return lastMessageReceiveTime in localtime] */
+            *lastMessageReceiveTime = handleData->lastMessageReceiveTime;
+            result = IOTHUB_CLIENT_OK;
+        }
+    }
+
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SetOption(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* optionName, const void* value)
+{
+
+    IOTHUB_CLIENT_RESULT result;
+    /*Codes_SRS_IOTHUBCLIENT_LL_02_034: [If iotHubClientHandle is NULL then IoTHubClientCore_LL_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.]*/
+    /*Codes_SRS_IOTHUBCLIENT_LL_02_035: [If optionName is NULL then IoTHubClientCore_LL_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.] */
+    /*Codes_SRS_IOTHUBCLIENT_LL_02_036: [If value is NULL then IoTHubClientCore_LL_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.] */
+    if (
+        (iotHubClientHandle == NULL) ||
+        (optionName == NULL) ||
+        (value == NULL)
+        )
+    {
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LogError("invalid argument (NULL)");
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
+
+        /*Codes_SRS_IOTHUBCLIENT_LL_02_039: [ "messageTimeout" - once IoTHubClientCore_LL_SendEventAsync is called the message shall timeout after value miliseconds. Value is a pointer to a tickcounter_ms_t. ]*/
+        if (strcmp(optionName, OPTION_MESSAGE_TIMEOUT) == 0)
+        {
+            /*this is an option handled by IoTHubClientCore_LL*/
+            /*Codes_SRS_IOTHUBCLIENT_LL_02_043: [ Calling IoTHubClientCore_LL_SetOption with value set to "0" shall disable the timeout mechanism for all new messages. ]*/
+            handleData->currentMessageTimeout = *(const tickcounter_ms_t*)value;
+            result = IOTHUB_CLIENT_OK;
+        }
+        else if (strcmp(optionName, OPTION_PRODUCT_INFO) == 0)
+        {
+            /*Codes_SRS_IOTHUBCLIENT_LL_10_033: [repeat calls with "product_info" will erase the previously set product information if applicatble. ]*/
+            if (handleData->product_info != NULL)
+            {
+                STRING_delete(handleData->product_info);
+                handleData->product_info = NULL;
+            }
+
+            PLATFORM_INFO_OPTION supportedPlatformInfo;
+            if (handleData->IoTHubTransport_GetSupportedPlatformInfo(handleData->transportHandle, &supportedPlatformInfo) != 0)
+            {
+                LogError("IoTHubTransport_GetSupportedPlatformInfo failed");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            /*Codes_SRS_IOTHUBCLIENT_LL_10_035: [If string concatenation fails, `IoTHubClientCore_LL_SetOption` shall return `IOTHUB_CLIENT_ERROR`. Otherwise, `IOTHUB_CLIENT_OK` shall be returned. ]*/
+            else if ((handleData->product_info = make_product_info((const char*)value, supportedPlatformInfo)) == NULL)
+            {
+                LogError("STRING_construct_sprintf failed");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else
+            {
+                result = IOTHUB_CLIENT_OK;
+            }
+        }
+        else if (strcmp(optionName, OPTION_DIAGNOSTIC_SAMPLING_PERCENTAGE) == 0)
+        {
+            uint32_t percentage = *(uint32_t*)value;
+            if (percentage > 100)
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_10_036: [Calling IoTHubClientCore_LL_SetOption with value > 100 shall return `IOTHUB_CLIENT_ERRROR`. ]*/
+                LogError("The value of diag_sampling_percentage is out of range [0, 100]: %u", percentage);
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_10_037: [Calling IoTHubClientCore_LL_SetOption with value between [0, 100] shall return `IOTHUB_CLIENT_OK`. ]*/
+                handleData->diagnostic_setting.diagSamplingPercentage = percentage;
+                handleData->diagnostic_setting.currentMessageNumber = 0;
+                result = IOTHUB_CLIENT_OK;
+            }
+        }
+        else if ((strcmp(optionName, OPTION_BLOB_UPLOAD_TIMEOUT_SECS) == 0) || (strcmp(optionName, OPTION_CURL_VERBOSE) == 0))
+        {
+#ifndef DONT_USE_UPLOADTOBLOB
+            // This option just gets passed down into IoTHubClientCore_LL_UploadToBlob
+            /*Codes_SRS_IOTHUBCLIENT_LL_30_010: [ blob_xfr_timeout - IoTHubClientCore_LL_SetOption shall pass this option to IoTHubClient_UploadToBlob_SetOption and return its result. ]*/
+            result = IoTHubClient_LL_UploadToBlob_SetOption(handleData->uploadToBlobHandle, optionName, value);
+            if(result != IOTHUB_CLIENT_OK)
+            {
+                LogError("unable to IoTHubClientCore_LL_UploadToBlob_SetOption, result=%d", result);
+            }
+#else
+            LogError("%s option being set with DONT_USE_UPLOADTOBLOB compiler switch", optionName);
+            result = IOTHUB_CLIENT_ERROR;
+#endif /*DONT_USE_UPLOADTOBLOB*/
+        }
+        // OPTION_SAS_TOKEN_REFRESH_TIME is, but may be updated in the future
+        // if this becomes necessary
+        else if (strcmp(optionName, OPTION_SAS_TOKEN_REFRESH_TIME) == 0 || strcmp(optionName, OPTION_SAS_TOKEN_LIFETIME) == 0)
+        {
+            if (IoTHubClient_Auth_Set_SasToken_Expiry(handleData->authorization_module, *(size_t*)value) != 0)
+            {
+                LogError("Failed setting the Token Expiry time");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else
+            {
+                result = IOTHUB_CLIENT_OK;
+            }
+        }
+        else if (strcmp(optionName, OPTION_MODEL_ID) == 0)
+        {
+            if (handleData->model_id != NULL)
+            {
+                LogError("DT ModelId already specified.");
+                result = IOTHUB_CLIENT_ERROR;
+            } 
+            else if ((handleData->model_id = STRING_construct((const char*)value)) == NULL)
+            {
+                LogError("STRING_construct failed");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else
+            {
+                result = IOTHUB_CLIENT_OK;
+            }
+        }
+        else
+        {
+            // This section is unusual for SetOption calls because it attempts to pass unhandled options
+            // to two downstream targets (IoTHubTransport_SetOption and IoTHubClientCore_LL_UploadToBlob_SetOption) instead of one.
+
+            /*Codes_SRS_IOTHUBCLIENT_LL_30_011: [ IoTHubClientCore_LL_SetOption shall always pass unhandled options to Transport_SetOption. ]*/
+            /*Codes_SRS_IOTHUBCLIENT_LL_30_012: [ If Transport_SetOption fails, IoTHubClientCore_LL_SetOption shall return that failure code. ]*/
+            result = handleData->IoTHubTransport_SetOption(handleData->transportHandle, optionName, value);
+            if(result != IOTHUB_CLIENT_OK)
+            {
+                LogError("unable to IoTHubTransport_SetOption");
+            }
+#ifndef DONT_USE_UPLOADTOBLOB
+            else
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_30_013: [ If the DONT_USE_UPLOADTOBLOB compiler switch is undefined, IoTHubClientCore_LL_SetOption shall pass unhandled options to IoTHubClient_UploadToBlob_SetOption and ignore the result. ]*/
+                (void)IoTHubClient_LL_UploadToBlob_SetOption(handleData->uploadToBlobHandle, optionName, value);
+            }
+#endif /*DONT_USE_UPLOADTOBLOB*/
+        }
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SetDeviceTwinCallback(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK deviceTwinCallback, void* userContextCallback)
+{
+    IOTHUB_CLIENT_RESULT result;
+    /* Codes_SRS_IOTHUBCLIENT_LL_10_001: [ IoTHubClientCore_LL_SetDeviceTwinCallback shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter iotHubClientHandle is NULL.] */
+    if (iotHubClientHandle == NULL)
+    {
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LogError("Invalid argument specified iothubClientHandle=%p", iotHubClientHandle);
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
+        if (deviceTwinCallback == NULL)
+        {
+            /* Codes_SRS_IOTHUBCLIENT_LL_10_006: [ If deviceTwinCallback is NULL, then IoTHubClientCore_LL_SetDeviceTwinCallback shall call the underlying layer's _Unsubscribe function and return IOTHUB_CLIENT_OK.] */
+            handleData->IoTHubTransport_Unsubscribe_DeviceTwin(handleData->transportHandle);
+            handleData->deviceTwinCallback = NULL;
+            result = IOTHUB_CLIENT_OK;
+        }
+        else
+        {
+            /* Codes_SRS_IOTHUBCLIENT_LL_10_002: [ If deviceTwinCallback is not NULL, then IoTHubClientCore_LL_SetDeviceTwinCallback shall call the underlying layer's _Subscribe function.] */
+            if (handleData->IoTHubTransport_Subscribe_DeviceTwin(handleData->transportHandle) == 0)
+            {
+                handleData->deviceTwinCallback = deviceTwinCallback;
+                handleData->deviceTwinContextCallback = userContextCallback;
+                /* Codes_SRS_IOTHUBCLIENT_LL_10_005: [ Otherwise IoTHubClientCore_LL_SetDeviceTwinCallback shall succeed and return IOTHUB_CLIENT_OK.] */
+                result = IOTHUB_CLIENT_OK;
+            }
+            else
+            {
+                /* Codes_SRS_IOTHUBCLIENT_LL_10_003: [ If the underlying layer's _Subscribe function fails, then IoTHubClientCore_LL_SetDeviceTwinCallback shall fail and return IOTHUB_CLIENT_ERROR.] */
+                result = IOTHUB_CLIENT_ERROR;
+            }
+        }
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SendReportedState(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const unsigned char* reportedState, size_t size, IOTHUB_CLIENT_REPORTED_STATE_CALLBACK reportedStateCallback, void* userContextCallback)
+{
+    IOTHUB_CLIENT_RESULT result;
+    /* Codes_SRS_IOTHUBCLIENT_LL_10_012: [ IoTHubClientCore_LL_SendReportedState shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter iotHubClientHandle is NULL. ] */
+    /* Codes_SRS_IOTHUBCLIENT_LL_10_013: [ IoTHubClientCore_LL_SendReportedState shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter reportedState is NULL] */
+    /* Codes_SRS_IOTHUBCLIENT_LL_07_005: [ IoTHubClientCore_LL_SendReportedState shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter size is equal to 0. ] */
+    if (iotHubClientHandle == NULL || (reportedState == NULL || size == 0) )
+    {
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LogError("Invalid argument specified iothubClientHandle=%p, reportedState=%p, size=%lu", iotHubClientHandle, reportedState, (unsigned long)size);
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
+        /* Codes_SRS_IOTHUBCLIENT_LL_10_014: [IoTHubClientCore_LL_SendReportedState shall construct and queue the reported a Device_Twin structure for transmition by the underlying transport.] */
+        IOTHUB_DEVICE_TWIN* client_data = dev_twin_data_create(handleData, get_next_item_id(handleData), reportedState, size, reportedStateCallback, userContextCallback);
+        if (client_data == NULL)
+        {
+            /* Codes_SRS_IOTHUBCLIENT_LL_10_015: [If any error is encountered IoTHubClientCore_LL_SendReportedState shall return IOTHUB_CLIENT_ERROR.] */
+            LogError("Failure constructing device twin data");
+            result = IOTHUB_CLIENT_ERROR;
+        }
+        else
+        {
+            if (handleData->IoTHubTransport_Subscribe_DeviceTwin(handleData->transportHandle) != 0)
+            {
+                LogError("Failure adding device twin data to queue");
+                device_twin_data_destroy(client_data);
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else
+            {
+                /* Codes_SRS_IOTHUBCLIENT_LL_07_001: [ IoTHubClientCore_LL_SendReportedState shall queue the constructed reportedState data to be consumed by the targeted transport. ] */
+                DList_InsertTailList(&(iotHubClientHandle->iot_msg_queue), &(client_data->entry));
+
+                /* Codes_SRS_IOTHUBCLIENT_LL_10_016: [ Otherwise IoTHubClientCore_LL_SendReportedState shall succeed and return IOTHUB_CLIENT_OK.] */
+                result = IOTHUB_CLIENT_OK;
+            }
+        }
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_GetTwinAsync(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK deviceTwinCallback, void* userContextCallback)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    // Codes_SRS_IOTHUBCLIENT_LL_09_011: [ If `iotHubClientHandle` or `deviceTwinCallback` are `NULL`, `IoTHubClientCore_LL_GetTwinAsync` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]
+    if (iotHubClientHandle == NULL || deviceTwinCallback == NULL)
+    {
+        LogError("Invalid argument iothubClientHandle=%p, deviceTwinCallback=%p", iotHubClientHandle, deviceTwinCallback);
+        result = IOTHUB_CLIENT_INVALID_ARG;
+    }
+    else
+    {
+        if (iotHubClientHandle->IoTHubTransport_Subscribe_DeviceTwin(iotHubClientHandle->transportHandle) != 0)
+        {
+            LogError("Failure adding device twin data to queue");
+            result = IOTHUB_CLIENT_ERROR;
+        }
+        else
+        {
+            GET_TWIN_CONTEXT* getTwinCtx;
+
+            if ((getTwinCtx = (GET_TWIN_CONTEXT*)malloc(sizeof(GET_TWIN_CONTEXT))) == NULL)
+            {
+                LogError("Failed creating get-twin context");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else
+            {
+                IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
+
+                getTwinCtx->callback = deviceTwinCallback;
+                getTwinCtx->context = userContextCallback;
+
+                // Codes_SRS_IOTHUBCLIENT_LL_09_012: [ IoTHubClientCore_LL_GetTwinAsync shall invoke IoTHubTransport_GetTwinAsync, passing `on_device_twin_report_received` and the user data as context  ]
+                if (handleData->IoTHubTransport_GetTwinAsync(handleData->deviceHandle, on_get_device_twin_completed, getTwinCtx) != IOTHUB_CLIENT_OK)
+                {
+                    // Codes_SRS_IOTHUBCLIENT_LL_09_013: [ If IoTHubTransport_GetTwinAsync fails, `IoTHubClientCore_LL_GetTwinAsync` shall fail and return `IOTHUB_CLIENT_ERROR`. ]
+                    LogError("Failed getting device twin document");
+                    free(getTwinCtx);
+                    result = IOTHUB_CLIENT_ERROR;
+                }
+                else
+                {
+                    // Codes_SRS_IOTHUBCLIENT_LL_09_014: [ If no errors occur IoTHubClientCore_LL_GetTwinAsync shall return `IOTHUB_CLIENT_OK`. ]
+                    handleData->complete_twin_update_encountered = true;
+                    result = IOTHUB_CLIENT_OK;
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SetDeviceMethodCallback(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_DEVICE_METHOD_CALLBACK_ASYNC deviceMethodCallback, void* userContextCallback)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    /*Codes_SRS_IOTHUBCLIENT_LL_12_017: [ IoTHubClientCore_LL_SetDeviceMethodCallback shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter iotHubClientHandle is NULL. ] */
+    if (iotHubClientHandle == NULL)
+    {
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LOG_ERROR_RESULT;
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
+        if (deviceMethodCallback == NULL)
+        {
+            if (handleData->methodCallback.type == CALLBACK_TYPE_NONE)
+            {
+                /* Codes_SRS_IOTHUBCLIENT_LL_10_029: [ If deviceMethodCallback is NULL and the client is not subscribed to receive method calls, IoTHubClientCore_LL_SetDeviceMethodCallback shall fail and return IOTHUB_CLIENT_ERROR. ] */
+                LogError("not currently set to accept or process incoming messages.");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else if (handleData->methodCallback.type == CALLBACK_TYPE_ASYNC)
+            {
+                /* Codes_SRS_IOTHUBCLIENT_LL_10_028: [If the user has subscribed using IoTHubClientCore_LL_SetDeviceMethodCallback_Ex, IoTHubClientCore_LL_SetDeviceMethodCallback shall fail and return IOTHUB_CLIENT_ERROR. ] */
+                LogError("Invalid workflow sequence. Please unsubscribe using the IoTHubClientCore_LL_SetDeviceMethodCallback_Ex function.");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_02_019: [If parameter messageCallback is NULL then IoTHubClientCore_LL_SetMessageCallback shall call the underlying layer's _Unsubscribe function and return IOTHUB_CLIENT_OK.] */
+                /*Codes_SRS_IOTHUBCLIENT_LL_12_018: [If deviceMethodCallback is NULL, then IoTHubClientCore_LL_SetDeviceMethodCallback shall call the underlying layer's IoTHubTransport_Unsubscribe_DeviceMethod function and return IOTHUB_CLIENT_OK. ] */
+                /*Codes_SRS_IOTHUBCLIENT_LL_12_022: [ Otherwise IoTHubClientCore_LL_SetDeviceMethodCallback shall succeed and return IOTHUB_CLIENT_OK. ]*/
+                handleData->IoTHubTransport_Unsubscribe_DeviceMethod(handleData->deviceHandle);
+                handleData->methodCallback.type = CALLBACK_TYPE_NONE;
+                handleData->methodCallback.callbackSync = NULL;
+                handleData->methodCallback.userContextCallback = NULL;
+                result = IOTHUB_CLIENT_OK;
+            }
+        }
+        else
+        {
+            if (handleData->methodCallback.type == CALLBACK_TYPE_ASYNC)
+            {
+                /* Codes_SRS_IOTHUBCLIENT_LL_10_028: [If the user has subscribed using IoTHubClientCore_LL_SetDeviceMethodCallback_Ex, IoTHubClientCore_LL_SetDeviceMethodCallback shall fail and return IOTHUB_CLIENT_ERROR. ] */
+                LogError("Invalid workflow sequence. Please unsubscribe using the IoTHubClientCore_LL_SetDeviceMethodCallback_Ex function before subscribing with IoTHubClientCore_LL_SetDeviceMethodCallback.");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_12_019: [ If deviceMethodCallback is not NULL, then IoTHubClientCore_LL_SetDeviceMethodCallback shall call the underlying layer's IoTHubTransport_Subscribe_DeviceMethod function. ]*/
+                if (handleData->IoTHubTransport_Subscribe_DeviceMethod(handleData->deviceHandle) == 0)
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_12_022: [ Otherwise IoTHubClientCore_LL_SetDeviceMethodCallback shall succeed and return IOTHUB_CLIENT_OK. ]*/
+                    handleData->methodCallback.type = CALLBACK_TYPE_SYNC;
+                    handleData->methodCallback.callbackSync = deviceMethodCallback;
+                    handleData->methodCallback.callbackAsync = NULL;
+                    handleData->methodCallback.userContextCallback = userContextCallback;
+                    result = IOTHUB_CLIENT_OK;
+                }
+                else
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_12_020: [ If the underlying layer's IoTHubTransport_Subscribe_DeviceMethod function fails, then IoTHubClientCore_LL_SetDeviceMethodCallback shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                    /*Codes_SRS_IOTHUBCLIENT_LL_12_021: [ If adding the information fails for any reason, IoTHubClientCore_LL_SetDeviceMethodCallback shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                    LogError("IoTHubTransport_Subscribe_DeviceMethod failed");
+                    handleData->methodCallback.type = CALLBACK_TYPE_NONE;
+                    handleData->methodCallback.callbackAsync = NULL;
+                    handleData->methodCallback.callbackSync = NULL;
+                    handleData->methodCallback.userContextCallback = NULL;
+                    result = IOTHUB_CLIENT_ERROR;
+                }
+            }
+        }
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SetDeviceMethodCallback_Ex(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK inboundDeviceMethodCallback, void* userContextCallback)
+{
+    IOTHUB_CLIENT_RESULT result;
+    /* Codes_SRS_IOTHUBCLIENT_LL_07_021: [ If handle is NULL then IoTHubClientCore_LL_SetDeviceMethodCallback_Ex shall return IOTHUB_CLIENT_INVALID_ARG.] */
+    if (iotHubClientHandle == NULL)
+    {
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LOG_ERROR_RESULT;
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
+        if (inboundDeviceMethodCallback == NULL)
+        {
+            if (handleData->methodCallback.type == CALLBACK_TYPE_NONE)
+            {
+                /* Codes_SRS_IOTHUBCLIENT_LL_10_030: [ If deviceMethodCallback is NULL and the client is not subscribed to receive method calls, IoTHubClientCore_LL_SetDeviceMethodCallback shall fail and return IOTHUB_CLIENT_ERROR. ] */
+                LogError("not currently set to accept or process incoming messages.");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else if (handleData->methodCallback.type == CALLBACK_TYPE_SYNC)
+            {
+                /* Codes_SRS_IOTHUBCLIENT_LL_10_031: [If the user has subscribed using IoTHubClientCore_LL_SetDeviceMethodCallback, IoTHubClientCore_LL_SetDeviceMethodCallback_Ex shall fail and return IOTHUB_CLIENT_ERROR. ] */
+                LogError("Invalid workflow sequence. Please unsubscribe using the IoTHubClientCore_LL_SetDeviceMethodCallback function.");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else
+            {
+                /* Codes_SRS_IOTHUBCLIENT_LL_07_022: [ If inboundDeviceMethodCallback is NULL then IoTHubClientCore_LL_SetDeviceMethodCallback_Ex shall call the underlying layer's IoTHubTransport_Unsubscribe_DeviceMethod function and return IOTHUB_CLIENT_OK.] */
+                handleData->IoTHubTransport_Unsubscribe_DeviceMethod(handleData->deviceHandle);
+                handleData->methodCallback.type = CALLBACK_TYPE_NONE;
+                handleData->methodCallback.callbackAsync = NULL;
+                handleData->methodCallback.userContextCallback = NULL;
+                result = IOTHUB_CLIENT_OK;
+            }
+        }
+        else
+        {
+            if (handleData->methodCallback.type == CALLBACK_TYPE_SYNC)
+            {
+                /* Codes_SRS_IOTHUBCLIENT_LL_10_031: [If the user has subscribed using IoTHubClientCore_LL_SetDeviceMethodCallback, IoTHubClientCore_LL_SetDeviceMethodCallback_Ex shall fail and return IOTHUB_CLIENT_ERROR. ] */
+                LogError("Invalid workflow sequence. Please unsubscribe using the IoTHubClientCore_LL_SetDeviceMethodCallback function before subscribing with IoTHubClientCore_LL_SetDeviceMethodCallback_Ex.");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else
+            {
+                /* Codes_SRS_IOTHUBCLIENT_LL_07_023: [ If inboundDeviceMethodCallback is non-NULL then IoTHubClientCore_LL_SetDeviceMethodCallback_Ex shall call the underlying layer's IoTHubTransport_Subscribe_DeviceMethod function.]*/
+                if (handleData->IoTHubTransport_Subscribe_DeviceMethod(handleData->deviceHandle) == 0)
+                {
+                    handleData->methodCallback.type = CALLBACK_TYPE_ASYNC;
+                    handleData->methodCallback.callbackAsync = inboundDeviceMethodCallback;
+                    handleData->methodCallback.callbackSync = NULL;
+                    handleData->methodCallback.userContextCallback = userContextCallback;
+                    result = IOTHUB_CLIENT_OK;
+                }
+                else
+                {
+                    /* Codes_SRS_IOTHUBCLIENT_LL_07_025: [ If any error is encountered then IoTHubClientCore_LL_SetDeviceMethodCallback_Ex shall return IOTHUB_CLIENT_ERROR.] */
+                    LogError("IoTHubTransport_Subscribe_DeviceMethod failed");
+                    handleData->methodCallback.type = CALLBACK_TYPE_NONE;
+                    handleData->methodCallback.callbackAsync = NULL;
+                    handleData->methodCallback.callbackSync = NULL;
+                    handleData->methodCallback.userContextCallback = NULL;
+                    result = IOTHUB_CLIENT_ERROR;
+                }
+            }
+        }
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_DeviceMethodResponse(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, METHOD_HANDLE methodId, const unsigned char* response, size_t response_size, int status_response)
+{
+    IOTHUB_CLIENT_RESULT result;
+    /* Codes_SRS_IOTHUBCLIENT_LL_07_026: [ If handle or methodId is NULL then IoTHubClientCore_LL_DeviceMethodResponse shall return IOTHUB_CLIENT_INVALID_ARG.] */
+    if (iotHubClientHandle == NULL || methodId == NULL)
+    {
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LOG_ERROR_RESULT;
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
+        /* Codes_SRS_IOTHUBCLIENT_LL_07_027: [ IoTHubClientCore_LL_DeviceMethodResponse shall call the IoTHubTransport_DeviceMethod_Response transport function.] */
+        if (handleData->IoTHubTransport_DeviceMethod_Response(handleData->deviceHandle, methodId, response, response_size, status_response) != 0)
+        {
+            LogError("IoTHubTransport_DeviceMethod_Response failed");
+            result = IOTHUB_CLIENT_ERROR;
+        }
+        else
+        {
+            result = IOTHUB_CLIENT_OK;
+        }
+    }
+    return result;
+}
+
+#ifndef DONT_USE_UPLOADTOBLOB
+IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_UploadToBlob(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* destinationFileName, const unsigned char* source, size_t size)
+{
+    IOTHUB_CLIENT_RESULT result;
+    /*Codes_SRS_IOTHUBCLIENT_LL_02_061: [ If iotHubClientHandle is NULL then IoTHubClientCore_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/
+    /*Codes_SRS_IOTHUBCLIENT_LL_02_062: [ If destinationFileName is NULL then IoTHubClientCore_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/
+    /*Codes_SRS_IOTHUBCLIENT_LL_02_063: [ If `source` is `NULL` and size is greater than 0 then `IoTHubClientCore_LL_UploadToBlob` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
+    if (
+        (iotHubClientHandle == NULL) ||
+        (destinationFileName == NULL) ||
+        ((source == NULL) && (size >0))
+        )
+    {
+        LogError("invalid parameters IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle=%p, const char* destinationFileName=%s, const unsigned char* source=%p, size_t size=%lu", iotHubClientHandle, destinationFileName, source, (unsigned long)size);
+        result = IOTHUB_CLIENT_INVALID_ARG;
+    }
+    else
+    {
+        result = IoTHubClient_LL_UploadToBlob_Impl(iotHubClientHandle->uploadToBlobHandle, destinationFileName, source, size);
+    }
+    return result;
+}
+
+typedef struct UPLOAD_MULTIPLE_BLOCKS_WRAPPER_CONTEXT_TAG
+{
+    IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK getDataCallback;
+    void* context;
+} UPLOAD_MULTIPLE_BLOCKS_WRAPPER_CONTEXT;
+
+
+static IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT uploadMultipleBlocksCallbackWrapper(IOTHUB_CLIENT_FILE_UPLOAD_RESULT result, unsigned char const ** data, size_t* size, void* context)
+{
+    UPLOAD_MULTIPLE_BLOCKS_WRAPPER_CONTEXT* wrapperContext = (UPLOAD_MULTIPLE_BLOCKS_WRAPPER_CONTEXT*)context;
+    wrapperContext->getDataCallback(result, data, size, wrapperContext->context);
+    return IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_OK;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_UploadMultipleBlocksToBlob(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK getDataCallback, void* context)
+{
+    IOTHUB_CLIENT_RESULT result;
+    /*Codes_SRS_IOTHUBCLIENT_LL_99_005: [ If `iotHubClientHandle` is `NULL` then `IoTHubClientCore_LL_UploadMultipleBlocksToBlob(Ex)` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
+    /*Codes_SRS_IOTHUBCLIENT_LL_99_006: [ If `destinationFileName` is `NULL` then `IoTHubClientCore_LL_UploadMultipleBlocksToBlob(Ex)` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
+    /*Codes_SRS_IOTHUBCLIENT_LL_99_007: [ If `getDataCallback` is `NULL` then `IoTHubClientCore_LL_UploadMultipleBlocksToBlob(Ex)` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
+    if (
+        (iotHubClientHandle == NULL) ||
+        (destinationFileName == NULL) ||
+        (getDataCallback == NULL)
+        )
+    {
+        LogError("invalid parameters IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle=%p, const char* destinationFileName=%p, getDataCallback=%p", iotHubClientHandle, destinationFileName, getDataCallback);
+        result = IOTHUB_CLIENT_INVALID_ARG;
+    }
+    else
+    {
+        UPLOAD_MULTIPLE_BLOCKS_WRAPPER_CONTEXT uploadMultipleBlocksWrapperContext;
+        uploadMultipleBlocksWrapperContext.getDataCallback = getDataCallback;
+        uploadMultipleBlocksWrapperContext.context = context;
+
+        result = IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl(iotHubClientHandle->uploadToBlobHandle, destinationFileName, uploadMultipleBlocksCallbackWrapper, &uploadMultipleBlocksWrapperContext);
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx, void* context)
+{
+    IOTHUB_CLIENT_RESULT result;
+    /*Codes_SRS_IOTHUBCLIENT_LL_99_005: [ If `iotHubClientHandle` is `NULL` then `IoTHubClientCore_LL_UploadMultipleBlocksToBlob(Ex)` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
+    /*Codes_SRS_IOTHUBCLIENT_LL_99_006: [ If `destinationFileName` is `NULL` then `IoTHubClientCore_LL_UploadMultipleBlocksToBlob(Ex)` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
+    /*Codes_SRS_IOTHUBCLIENT_LL_99_007: [ If `getDataCallback` is `NULL` then `IoTHubClientCore_LL_UploadMultipleBlocksToBlob(Ex)` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
+    if (
+        (iotHubClientHandle == NULL) ||
+        (destinationFileName == NULL) ||
+        (getDataCallbackEx == NULL)
+        )
+    {
+        LogError("invalid parameters IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle=%p, destinationFileName=%p, getDataCallbackEx=%p", iotHubClientHandle, destinationFileName, getDataCallbackEx);
+        result = IOTHUB_CLIENT_INVALID_ARG;
+    }
+    else
+    {
+        result = IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl(iotHubClientHandle->uploadToBlobHandle, destinationFileName, getDataCallbackEx, context);
+    }
+    return result;
+}
+#endif // DONT_USE_UPLOADTOBLOB
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SendEventToOutputAsync(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_MESSAGE_HANDLE eventMessageHandle, const char* outputName, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK eventConfirmationCallback, void* userContextCallback)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    if ((iotHubClientHandle == NULL) || (outputName == NULL) || (eventMessageHandle == NULL) || ((eventConfirmationCallback == NULL) && (userContextCallback != NULL)))
+    {
+        // Codes_SRS_IOTHUBCLIENT_LL_31_127: [ If `iotHubClientHandle`, `outputName`, or `eventConfirmationCallback` is `NULL`, `IoTHubClient_LL_SendEventToOutputAsync` shall return `IOTHUB_CLIENT_INVALID_ARG`. ]
+        LogError("Invalid argument (iotHubClientHandle=%p, outputName=%p, eventMessageHandle=%p)", iotHubClientHandle, outputName, eventMessageHandle);
+        result = IOTHUB_CLIENT_INVALID_ARG;
+    }
+    else
+    {
+        // Codes_SRS_IOTHUBCLIENT_LL_31_128: [ `IoTHubClient_LL_SendEventToOutputAsync` shall set the outputName of the message to send. ]
+        if (IoTHubMessage_SetOutputName(eventMessageHandle, outputName) != IOTHUB_MESSAGE_OK)
+        {
+            LogError("IoTHubMessage_SetOutputName failed");
+            result = IOTHUB_CLIENT_ERROR;
+        }
+        // Codes_SRS_IOTHUBCLIENT_LL_31_129: [ `IoTHubClient_LL_SendEventToOutputAsync` shall invoke `IoTHubClient_LL_SendEventAsync` to send the message. ]
+        else if ((result = IoTHubClientCore_LL_SendEventAsync(iotHubClientHandle, eventMessageHandle, eventConfirmationCallback, userContextCallback)) != IOTHUB_CLIENT_OK)
+        {
+            LogError("Call into IoTHubClient_LL_SendEventAsync failed, result=%d", result);
+        }
+    }
+
+    return result;
+}
+
+
+static IOTHUB_CLIENT_RESULT create_event_handler_callback(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData, const char* inputName, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC callbackSync, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC_EX callbackSyncEx, void* userContextCallback, void* userContextCallbackEx, size_t userContextCallbackExLength)
+{
+    IOTHUB_CLIENT_RESULT result = IOTHUB_CLIENT_ERROR;
+    bool add_to_list = false;
+
+    if ((handleData->event_callbacks == NULL) && ((handleData->event_callbacks = singlylinkedlist_create()) == NULL))
+    {
+        LogError("Could not allocate linked list for callbacks");
+        result = IOTHUB_CLIENT_ERROR;
+    }
+    else
+    {
+        IOTHUB_EVENT_CALLBACK* event_callback = NULL;
+        LIST_ITEM_HANDLE item_handle = singlylinkedlist_find(handleData->event_callbacks, is_event_equal_for_match, (const void*)inputName);
+        if (item_handle == NULL)
+        {
+            // Codes_SRS_IOTHUBCLIENT_LL_31_134: [ `IoTHubClient_LL_SetInputMessageCallback` shall allocate a callback handle to associate callbacks from the transport => client if `inputName` isn't already present in the callback list. ]
+            event_callback = (IOTHUB_EVENT_CALLBACK*)malloc(sizeof(IOTHUB_EVENT_CALLBACK));
+            if (event_callback == NULL)
+            {
+                LogError("Could not allocate IOTHUB_EVENT_CALLBACK");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else
+            {
+                memset(event_callback, 0, sizeof(*event_callback));
+                add_to_list = true;
+            }
+        }
+        else
+        {
+            // Codes_SRS_IOTHUBCLIENT_LL_31_135: [ `IoTHubClient_LL_SetInputMessageCallback` shall reuse the existing callback handle if `inputName` is already present in the callback list. ]
+            event_callback = (IOTHUB_EVENT_CALLBACK*)singlylinkedlist_item_get_value(item_handle);
+            if (event_callback == NULL)
+            {
+                LogError("singlylinkedlist_item_get_value failed looking up event callback");
+            }
+        }
+
+        if (event_callback != NULL)
+        {
+            if ((inputName != NULL) && (event_callback->inputName == NULL))
+            {
+                event_callback->inputName = STRING_construct(inputName);
+            }
+
+            if ((inputName == NULL) || (event_callback->inputName != NULL))
+            {
+                event_callback->callbackAsync = callbackSync;
+                event_callback->callbackAsyncEx = callbackSyncEx;
+
+                free(event_callback->userContextCallbackEx);
+                event_callback->userContextCallbackEx = NULL;
+
+                if (userContextCallbackEx == NULL)
+                {
+                    event_callback->userContextCallback = userContextCallback;
+                }
+
+                if ((userContextCallbackEx != NULL) &&
+                    (NULL == (event_callback->userContextCallbackEx = malloc(userContextCallbackExLength))))
+                {
+                    LogError("Unable to allocate userContextCallback");
+                    delete_event(event_callback);
+                    result = IOTHUB_CLIENT_ERROR;
+                }
+                else if ((add_to_list == true) && (NULL == singlylinkedlist_add(handleData->event_callbacks, event_callback)))
+                {
+                    LogError("Unable to add eventCallback to list");
+                    delete_event(event_callback);
+                    result = IOTHUB_CLIENT_ERROR;
+                }
+                else
+                {
+                    if (userContextCallbackEx != NULL)
+                    {
+                        // Codes_SRS_IOTHUBCLIENT_LL_31_141: [`IoTHubClient_LL_SetInputMessageCallbackEx` shall copy the data passed in extended context. ]
+                        memcpy(event_callback->userContextCallbackEx, userContextCallbackEx, userContextCallbackExLength);
+                    }
+                    result = IOTHUB_CLIENT_OK;
+                }
+            }
+            else
+            {
+                delete_event(event_callback);
+                result = IOTHUB_CLIENT_ERROR;
+            }
+        }
+    }
+
+    return result;
+}
+
+static IOTHUB_CLIENT_RESULT remove_event_unsubscribe_if_needed(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData, const char* inputName)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    LIST_ITEM_HANDLE item_handle = singlylinkedlist_find(handleData->event_callbacks, is_event_equal_for_match, (const void*)inputName);
+    if (item_handle == NULL)
+    {
+        // Codes_SRS_IOTHUBCLIENT_LL_31_132: [ If `eventHandlerCallback` is NULL, `IoTHubClient_LL_SetInputMessageCallback` shall return `IOTHUB_CLIENT_ERROR` if the `inputName` is not present. ]
+        LogError("Input name %s was not present", inputName);
+        result = IOTHUB_CLIENT_ERROR;
+    }
+    else
+    {
+        IOTHUB_EVENT_CALLBACK* event_callback = (IOTHUB_EVENT_CALLBACK*)singlylinkedlist_item_get_value(item_handle);
+        if (event_callback == NULL)
+        {
+            LogError("singlylinkedlist_item_get_value failed");
+            result = IOTHUB_CLIENT_ERROR;
+        }
+        else
+        {
+            delete_event(event_callback);
+            // Codes_SRS_IOTHUBCLIENT_LL_31_131: [ If `eventHandlerCallback` is NULL, `IoTHubClient_LL_SetInputMessageCallback` shall remove the `inputName` from its callback list if present. ]
+            if (singlylinkedlist_remove(handleData->event_callbacks, item_handle) != 0)
+            {
+                LogError("singlylinkedlist_remove failed");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else
+            {
+                if (singlylinkedlist_get_head_item(handleData->event_callbacks) == NULL)
+                {
+                    // Codes_SRS_IOTHUBCLIENT_LL_31_133: [ If `eventHandlerCallback` is NULL, `IoTHubClient_LL_SetInputMessageCallback` shall invoke `IoTHubTransport_Unsubscribe_InputQueue` if this was the last input callback. ]
+                    handleData->IoTHubTransport_Unsubscribe_InputQueue(handleData);
+                }
+                result = IOTHUB_CLIENT_OK;
+            }
+        }
+    }
+
+    return result;
+}
+
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SetInputMessageCallbackImpl(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* inputName, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC eventHandlerCallback, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC_EX eventHandlerCallbackEx, void *userContextCallback, void *userContextCallbackEx, size_t userContextCallbackExLength)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    if (iotHubClientHandle == NULL)
+    {
+        // Codes_SRS_IOTHUBCLIENT_LL_31_130: [ If `iotHubClientHandle` or `inputName` is NULL, `IoTHubClient_LL_SetInputMessageCallback` shall return IOTHUB_CLIENT_INVALID_ARG. ]
+        LogError("Invalid argument - iotHubClientHandle=%p, inputName=%p", iotHubClientHandle, inputName);
+        result = IOTHUB_CLIENT_INVALID_ARG;
+    }
+    else
+    {
+        IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
+        if ((eventHandlerCallback == NULL) && (eventHandlerCallbackEx == NULL))
+        {
+            result = (IOTHUB_CLIENT_RESULT)remove_event_unsubscribe_if_needed(handleData, inputName);
+        }
+        else
+        {
+            bool registered_with_transport_handler = (handleData->event_callbacks != NULL) && (singlylinkedlist_get_head_item(handleData->event_callbacks) != NULL);
+            if ((result = (IOTHUB_CLIENT_RESULT)create_event_handler_callback(handleData, inputName, eventHandlerCallback, eventHandlerCallbackEx, userContextCallback, userContextCallbackEx, userContextCallbackExLength)) != IOTHUB_CLIENT_OK)
+            {
+                LogError("create_event_handler_callback call failed, error = %d", result);
+            }
+            // Codes_SRS_IOTHUBCLIENT_LL_31_136: [ `IoTHubClient_LL_SetInputMessageCallback` shall invoke `IoTHubTransport_Subscribe_InputQueue` if this is the first callback being registered. ]
+            else if (!registered_with_transport_handler && (handleData->IoTHubTransport_Subscribe_InputQueue(handleData->deviceHandle) != 0))
+            {
+                LogError("IoTHubTransport_Subscribe_InputQueue failed");
+                delete_event_callback_list(handleData);
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else
+            {
+                result = IOTHUB_CLIENT_OK;
+            }
+        }
+    }
+    return result;
+
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SetInputMessageCallbackEx(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* inputName, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC_EX eventHandlerCallbackEx, void *userContextCallbackEx, size_t userContextCallbackExLength)
+{
+    return IoTHubClientCore_LL_SetInputMessageCallbackImpl(iotHubClientHandle, inputName, NULL, eventHandlerCallbackEx, NULL, userContextCallbackEx, userContextCallbackExLength);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SetInputMessageCallback(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* inputName, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC eventHandlerCallback, void* userContextCallback)
+{
+    return IoTHubClientCore_LL_SetInputMessageCallbackImpl(iotHubClientHandle, inputName, eventHandlerCallback, NULL, userContextCallback, NULL, 0);
+}
+
+int IoTHubClientCore_LL_GetTransportCallbacks(TRANSPORT_CALLBACKS_INFO* transport_cb)
+{
+    int result;
+    if (transport_cb == NULL)
+    {
+        LogError("Invalid parameter transport callback can not be NULL");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        transport_cb->send_complete_cb = IoTHubClientCore_LL_SendComplete;
+        transport_cb->twin_retrieve_prop_complete_cb = IoTHubClientCore_LL_RetrievePropertyComplete;
+        transport_cb->twin_rpt_state_complete_cb = IoTHubClientCore_LL_ReportedStateComplete;
+        transport_cb->connection_status_cb = IoTHubClientCore_LL_ConnectionStatusCallBack;
+        transport_cb->prod_info_cb = IoTHubClientCore_LL_GetProductInfo;
+        transport_cb->msg_input_cb = IoTHubClientCore_LL_MessageCallbackFromInput;
+        transport_cb->msg_cb = IoTHubClientCore_LL_MessageCallback;
+        transport_cb->method_complete_cb = IoTHubClientCore_LL_DeviceMethodComplete;
+        transport_cb->get_model_id_cb = IoTHubClientCore_LL_GetModelId;
+        result = 0;
+    }
+    return result;
+}
+
+#ifdef USE_EDGE_MODULES
+/* These should be replaced during iothub_client refactor */
+IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_GenericMethodInvoke(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* deviceId, const char* moduleId, const char* methodName, const char* methodPayload, unsigned int timeout, int* responseStatus, unsigned char** responsePayload, size_t* responsePayloadSize)
+{
+    IOTHUB_CLIENT_RESULT result;
+    if (iotHubClientHandle != NULL)
+    {
+        if (moduleId != NULL)
+        {
+            result = IoTHubClient_Edge_ModuleMethodInvoke(iotHubClientHandle->methodHandle, deviceId, moduleId, methodName, methodPayload, timeout, responseStatus, responsePayload, responsePayloadSize);
+        }
+        else
+        {
+            result = IoTHubClient_Edge_DeviceMethodInvoke(iotHubClientHandle->methodHandle, deviceId, methodName, methodPayload, timeout, responseStatus, responsePayload, responsePayloadSize);
+
+        }
+    }
+    else
+    {
+        result = IOTHUB_CLIENT_INVALID_ARG;
+    }
+    return result;
+}
+#endif
+
+/*end*/
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_client_diagnostic.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_client_diagnostic.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_client_diagnostic.c	(revision 453)
@@ -0,0 +1,199 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include <math.h>
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/agenttime.h"
+#include "azure_c_shared_utility/buffer_.h"
+
+#include "internal/iothub_client_diagnostic.h"
+
+#define TIME_STRING_BUFFER_LEN 30
+
+static const int BASE_36 = 36;
+
+#define INDEFINITE_TIME ((time_t)-1)
+
+static char* get_epoch_time(char* timeBuffer)
+{
+    char* result;
+    time_t epochTime;
+    int timeLen = sizeof(time_t);
+
+    if ((epochTime = get_time(NULL)) == INDEFINITE_TIME)
+    {
+        LogError("Failed getting current time");
+        result = NULL;
+    }
+    else if (timeLen == sizeof(int64_t))
+    {
+        if (sprintf(timeBuffer, "%"PRIu64, (int64_t)epochTime) < 0)
+        {
+            LogError("Failed sprintf to timeBuffer with 8 bytes of time_t");
+            result = NULL;
+        }
+        else
+        {
+            result = timeBuffer;
+        }
+    }
+    else if (timeLen == sizeof(int32_t))
+    {
+        if (sprintf(timeBuffer, "%"PRIu32, (int32_t)epochTime) < 0)
+        {
+            LogError("Failed sprintf to timeBuffer with 4 bytes of time_t");
+            result = NULL;
+        }
+        else
+        {
+            result = timeBuffer;
+        }
+    }
+    else
+    {
+        LogError("Unknown size of time_t");
+        result = NULL;
+    }
+
+    return result;
+}
+
+static char get_base36_char(unsigned char value)
+{
+    return value <= 9 ? '0' + value : 'a' + value - 10;
+}
+
+static char* generate_eight_random_characters(char *randomString)
+{
+    int i;
+    char* randomStringPos = randomString;
+    for (i = 0; i < 4; ++i)
+    {
+        int rawRandom = rand();
+        int first = rawRandom % BASE_36;
+        int second = rawRandom / BASE_36 % BASE_36;
+        *randomStringPos++ = get_base36_char((unsigned char)first);
+        *randomStringPos++ = get_base36_char((unsigned char)second);
+    }
+    *randomStringPos = 0;
+
+    return randomString;
+}
+
+static bool should_add_diagnostic_info(IOTHUB_DIAGNOSTIC_SETTING_DATA* diagSetting)
+{
+    bool result = false;
+    if (diagSetting->diagSamplingPercentage > 0)
+    {
+        double number;
+        double percentage;
+
+        if (diagSetting->currentMessageNumber == UINT32_MAX)
+        {
+            diagSetting->currentMessageNumber %= diagSetting->diagSamplingPercentage * 100;
+        }
+        ++diagSetting->currentMessageNumber;
+
+        number = diagSetting->currentMessageNumber;
+        percentage = diagSetting->diagSamplingPercentage;
+        result = (floor((number - 2) * percentage / 100.0) < floor((number - 1) * percentage / 100.0));
+    }
+    return result;
+}
+
+static IOTHUB_MESSAGE_DIAGNOSTIC_PROPERTY_DATA* prepare_message_diagnostic_data()
+{
+    IOTHUB_MESSAGE_DIAGNOSTIC_PROPERTY_DATA* result = (IOTHUB_MESSAGE_DIAGNOSTIC_PROPERTY_DATA*)malloc(sizeof(IOTHUB_MESSAGE_DIAGNOSTIC_PROPERTY_DATA));
+    if (result == NULL)
+    {
+        LogError("malloc for DiagnosticData failed");
+    }
+    else
+    {
+        char* diagId = (char*)malloc(9);
+        if (diagId == NULL)
+        {
+            LogError("malloc for diagId failed");
+            free(result);
+            result = NULL;
+        }
+        else
+        {
+            char* timeBuffer;
+
+            (void)generate_eight_random_characters(diagId);
+            result->diagnosticId = diagId;
+
+            timeBuffer = (char*)malloc(TIME_STRING_BUFFER_LEN);
+            if (timeBuffer == NULL)
+            {
+                LogError("malloc for timeBuffer failed");
+                free(result->diagnosticId);
+                free(result);
+                result = NULL;
+            }
+            else if (get_epoch_time(timeBuffer) == NULL)
+            {
+                LogError("Failed getting current time");
+                free(result->diagnosticId);
+                free(result);
+                free(timeBuffer);
+                result = NULL;
+            }
+            else
+            {
+                result->diagnosticCreationTimeUtc = timeBuffer;
+            }
+        }
+    }
+    return result;
+}
+
+int IoTHubClient_Diagnostic_AddIfNecessary(IOTHUB_DIAGNOSTIC_SETTING_DATA* diagSetting, IOTHUB_MESSAGE_HANDLE messageHandle)
+{
+    int result;
+    /* Codes_SRS_IOTHUB_DIAGNOSTIC_13_001: [ IoTHubClient_Diagnostic_AddIfNecessary should return nonezero if diagSetting or messageHandle is NULL. ]*/
+    if (diagSetting == NULL || messageHandle == NULL)
+    {
+        result = MU_FAILURE;
+    }
+    /* Codes_SRS_IOTHUB_DIAGNOSTIC_13_003: [ If diagSamplingPercentage is equal to 0, message number should not be increased and no diagnostic properties added ]*/
+    else if (should_add_diagnostic_info(diagSetting))
+    {
+        /* Codes_SRS_IOTHUB_DIAGNOSTIC_13_004: [ If diagSamplingPercentage is equal to 100, diagnostic properties should be added to all messages]*/
+        /* Codes_SRS_IOTHUB_DIAGNOSTIC_13_005: [ If diagSamplingPercentage is between(0, 100), diagnostic properties should be added based on percentage]*/
+
+        IOTHUB_MESSAGE_DIAGNOSTIC_PROPERTY_DATA* diagnosticData;
+        if ((diagnosticData = prepare_message_diagnostic_data()) == NULL)
+        {
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if (IoTHubMessage_SetDiagnosticPropertyData(messageHandle, diagnosticData) != IOTHUB_MESSAGE_OK)
+            {
+                /* Codes_SRS_IOTHUB_DIAGNOSTIC_13_002: [ IoTHubClient_Diagnostic_AddIfNecessary should return nonezero if failing to add diagnostic property. ]*/
+                result = MU_FAILURE;
+            }
+            else
+            {
+                result = 0;
+            }
+
+            free(diagnosticData->diagnosticCreationTimeUtc);
+            free(diagnosticData->diagnosticId);
+            free(diagnosticData);
+            diagnosticData = NULL;
+        }
+    }
+    else
+    {
+        result = 0;
+    }
+
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_client_ll.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_client_ll.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_client_ll.c	(revision 453)
@@ -0,0 +1,141 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <string.h>
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/string_tokenizer.h"
+#include "azure_c_shared_utility/doublylinkedlist.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/tickcounter.h"
+#include "azure_c_shared_utility/constbuffer.h"
+#include "azure_c_shared_utility/platform.h"
+
+#include "iothub_client_core_ll.h"
+#include "internal/iothub_client_authorization.h"
+#include "iothub_client_ll.h"
+#include "iothub_transport_ll.h"
+#include "iothub_device_client_ll.h"
+#include "internal/iothub_client_private.h"
+#include "iothub_client_options.h"
+#include "iothub_client_version.h"
+#include <stdint.h>
+
+#ifndef DONT_USE_UPLOADTOBLOB
+#include "internal/iothub_client_ll_uploadtoblob.h"
+#endif
+
+IOTHUB_CLIENT_LL_HANDLE IoTHubClient_LL_CreateFromConnectionString(const char* connectionString, IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol)
+{
+    return (IOTHUB_CLIENT_LL_HANDLE)IoTHubClientCore_LL_CreateFromConnectionString(connectionString, protocol);
+}
+
+IOTHUB_CLIENT_LL_HANDLE IoTHubClient_LL_Create(const IOTHUB_CLIENT_CONFIG* config)
+{
+    return (IOTHUB_CLIENT_LL_HANDLE)IoTHubClientCore_LL_Create(config);
+}
+
+IOTHUB_CLIENT_LL_HANDLE IoTHubClient_LL_CreateWithTransport(const IOTHUB_CLIENT_DEVICE_CONFIG * config)
+{
+    return (IOTHUB_CLIENT_LL_HANDLE)IoTHubClientCore_LL_CreateWithTransport(config);
+}
+
+IOTHUB_CLIENT_LL_HANDLE IoTHubClient_LL_CreateFromDeviceAuth(const char* iothub_uri, const char* device_id, IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol)
+{
+    return (IOTHUB_CLIENT_LL_HANDLE)IoTHubClientCore_LL_CreateFromDeviceAuth(iothub_uri, device_id, protocol);
+}
+
+void IoTHubClient_LL_Destroy(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle)
+{
+    IoTHubClientCore_LL_Destroy((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_LL_SendEventAsync(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, IOTHUB_MESSAGE_HANDLE eventMessageHandle, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK eventConfirmationCallback, void* userContextCallback)
+{
+    return IoTHubClientCore_LL_SendEventAsync((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, eventMessageHandle, eventConfirmationCallback, userContextCallback);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_LL_GetSendStatus(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_STATUS *iotHubClientStatus)
+{
+    return IoTHubClientCore_LL_GetSendStatus((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, iotHubClientStatus);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_LL_SetMessageCallback(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC messageCallback, void* userContextCallback)
+{
+    return IoTHubClientCore_LL_SetMessageCallback((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, messageCallback, userContextCallback);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_LL_SetConnectionStatusCallback(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_CONNECTION_STATUS_CALLBACK connectionStatusCallback, void * userContextCallback)
+{
+    return IoTHubClientCore_LL_SetConnectionStatusCallback((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, connectionStatusCallback, userContextCallback);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_LL_SetRetryPolicy(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY retryPolicy, size_t retryTimeoutLimitInSeconds)
+{
+    return IoTHubClientCore_LL_SetRetryPolicy((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, retryPolicy, retryTimeoutLimitInSeconds);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_LL_GetRetryPolicy(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY* retryPolicy, size_t* retryTimeoutLimitInSeconds)
+{
+    return IoTHubClientCore_LL_GetRetryPolicy((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, retryPolicy, retryTimeoutLimitInSeconds);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_LL_GetLastMessageReceiveTime(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, time_t* lastMessageReceiveTime)
+{
+    return IoTHubClientCore_LL_GetLastMessageReceiveTime((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, lastMessageReceiveTime);
+}
+
+void IoTHubClient_LL_DoWork(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle)
+{
+    IoTHubClientCore_LL_DoWork((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_LL_SetDeviceTwinCallback(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK deviceTwinCallback, void* userContextCallback)
+{
+    return IoTHubClientCore_LL_SetDeviceTwinCallback((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, deviceTwinCallback, userContextCallback);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_LL_SetOption(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, const char* optionName, const void* value)
+{
+    return IoTHubClientCore_LL_SetOption((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, optionName, value);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_LL_SendReportedState(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, const unsigned char* reportedState, size_t size, IOTHUB_CLIENT_REPORTED_STATE_CALLBACK reportedStateCallback, void* userContextCallback)
+{
+    return IoTHubClientCore_LL_SendReportedState((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, reportedState, size, reportedStateCallback, userContextCallback);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_LL_SetDeviceMethodCallback(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_DEVICE_METHOD_CALLBACK_ASYNC deviceMethodCallback, void* userContextCallback)
+{
+    return IoTHubClientCore_LL_SetDeviceMethodCallback((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, deviceMethodCallback, userContextCallback);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_LL_SetDeviceMethodCallback_Ex(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK inboundDeviceMethodCallback, void* userContextCallback)
+{
+    return IoTHubClientCore_LL_SetDeviceMethodCallback_Ex((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, inboundDeviceMethodCallback, userContextCallback);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_LL_DeviceMethodResponse(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, METHOD_HANDLE methodId, const unsigned char* response, size_t response_size, int status_response)
+{
+    return IoTHubClientCore_LL_DeviceMethodResponse((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, methodId, response, response_size, status_response);
+}
+
+#ifndef DONT_USE_UPLOADTOBLOB
+IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, const char* destinationFileName, const unsigned char* source, size_t size)
+{
+    return IoTHubClientCore_LL_UploadToBlob((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, destinationFileName, source, size);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadMultipleBlocksToBlob(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, const char* destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK getDataCallback, void* context)
+{
+    return IoTHubClientCore_LL_UploadMultipleBlocksToBlob((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, destinationFileName, getDataCallback, context);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadMultipleBlocksToBlobEx(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, const char* destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx, void* context)
+{
+    return IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, destinationFileName, getDataCallbackEx, context);
+}
+#endif
+
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_client_ll_uploadtoblob.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_client_ll_uploadtoblob.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_client_ll_uploadtoblob.c	(revision 453)
@@ -0,0 +1,1176 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef DONT_USE_UPLOADTOBLOB
+
+#include <stdlib.h>
+#include <string.h>
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/string_tokenizer.h"
+#include "azure_c_shared_utility/doublylinkedlist.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/tickcounter.h"
+#include "azure_c_shared_utility/httpapiexsas.h"
+#include "azure_c_shared_utility/shared_util_options.h"
+#include "azure_c_shared_utility/urlencode.h"
+
+#include "iothub_client_core_ll.h"
+#include "iothub_client_options.h"
+#include "internal/iothub_client_private.h"
+#include "iothub_client_version.h"
+#include "iothub_transport_ll.h"
+#include "parson.h"
+#include "internal/iothub_client_ll_uploadtoblob.h"
+#include "internal/iothub_client_authorization.h"
+#include "internal/blob.h"
+
+#define API_VERSION "?api-version=2016-11-14"
+
+#ifdef WINCE
+#include <stdarg.h>
+// Returns number of characters copied.
+int snprintf(char * s, size_t n, const char * format, ...)
+{
+    int result;
+    va_list args;
+    va_start(args, format);
+    result = vsnprintf(s, n, format, args);
+    va_end(args);
+    return result;
+}
+#endif
+
+/*Codes_SRS_IOTHUBCLIENT_LL_02_085: [ IoTHubClient_LL_UploadToBlob shall use the same authorization as step 1. to prepare and perform a HTTP request with the following parameters: ]*/
+static const char* const RESPONSE_BODY_FORMAT = "{\"correlationId\":\"%s\", \"isSuccess\":%s, \"statusCode\":%d, \"statusDescription\":\"%s\"}";
+static const char* const RESPONSE_BODY_ABORTED_MESSAGE = "file upload aborted";
+static const char* const RESPONSE_BODY_FAILED_MESSAGE = "client not able to connect with the server";
+static const char* const RESPONSE_BODY_ERROR_RETURN_CODE = "-1";
+static const char* const RESPONSE_BODY_ERROR_BOOLEAN_STRING = "false";
+
+#define INDEFINITE_TIME                            ((time_t)-1)
+
+static const char* const EMPTY_STRING = "";
+static const char* const HEADER_AUTHORIZATION = "Authorization";
+static const char* const HEADER_APP_JSON = "application/json";
+
+typedef struct UPLOADTOBLOB_X509_CREDENTIALS_TAG
+{
+    char* x509certificate;
+    char* x509privatekey;
+} UPLOADTOBLOB_X509_CREDENTIALS;
+
+typedef enum UPOADTOBLOB_CURL_VERBOSITY_TAG
+{
+    UPOADTOBLOB_CURL_VERBOSITY_UNSET,
+    UPOADTOBLOB_CURL_VERBOSITY_ON,
+    UPOADTOBLOB_CURL_VERBOSITY_OFF
+} UPOADTOBLOB_CURL_VERBOSITY;
+
+typedef struct IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA_TAG
+{
+    const char* deviceId;
+    char* hostname;
+    IOTHUB_AUTHORIZATION_HANDLE authorization_module;
+    IOTHUB_CREDENTIAL_TYPE cred_type;
+    union 
+    {
+        UPLOADTOBLOB_X509_CREDENTIALS x509_credentials;
+        char* supplied_sas_token;
+    } credentials;
+    
+    char* certificates;
+    HTTP_PROXY_OPTIONS http_proxy_options;
+    UPOADTOBLOB_CURL_VERBOSITY curl_verbosity_level;
+    size_t blob_upload_timeout_secs;
+}IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA;
+
+typedef struct BLOB_UPLOAD_CONTEXT_TAG
+{
+    const unsigned char* blobSource; /* source to upload */
+    size_t blobSourceSize; /* size of the source */
+    size_t remainingSizeToUpload; /* size not yet uploaded */
+} BLOB_UPLOAD_CONTEXT;
+
+static int send_http_sas_request(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_client, const char* uri_resource, HTTPAPIEX_HANDLE http_api_handle, const char* relative_path, HTTP_HEADERS_HANDLE request_header, BUFFER_HANDLE blobBuffer, BUFFER_HANDLE response_buff)
+{
+    int result;
+    unsigned int statusCode;
+
+    /*Codes_SRS_IOTHUBCLIENT_LL_02_089: [ If creating the HTTPAPIEX_SAS_HANDLE fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+    HTTPAPIEX_SAS_HANDLE http_sas_handle = HTTPAPIEX_SAS_Create_From_String(IoTHubClient_Auth_Get_DeviceKey(upload_client->authorization_module), uri_resource, EMPTY_STRING);
+    if (http_sas_handle == NULL)
+    {
+        LogError("unable to HTTPAPIEX_SAS_Create");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        /*Codes_SRS_IOTHUBCLIENT_LL_32_003: [ IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall execute HTTPAPIEX_ExecuteRequest passing the following information for arguments: ]*/
+        if (HTTPAPIEX_SAS_ExecuteRequest(http_sas_handle, http_api_handle, HTTPAPI_REQUEST_POST, relative_path, request_header,
+            blobBuffer, &statusCode, NULL, response_buff) != HTTPAPIEX_OK)
+        {
+            /*Codes_SRS_IOTHUBCLIENT_LL_02_076: [ If HTTPAPIEX_ExecuteRequest call fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+            result = MU_FAILURE;
+            LogError("unable to HTTPAPIEX_ExecuteRequest");
+        }
+        else if (statusCode >= 300)
+        {
+            result = MU_FAILURE;
+            LogError("HTTP code was %u", statusCode);
+        }
+        else
+        {
+            result = 0;
+        }
+        HTTPAPIEX_SAS_Destroy(http_sas_handle);
+    }
+    return result;
+}
+
+static int send_http_request(HTTPAPIEX_HANDLE http_api_handle, const char* relative_path, HTTP_HEADERS_HANDLE request_header, BUFFER_HANDLE blobBuffer, BUFFER_HANDLE response_buff)
+{
+    int result;
+    unsigned int statusCode;
+    /*Codes_SRS_IOTHUBCLIENT_LL_32_003: [ IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall execute HTTPAPIEX_ExecuteRequest passing the following information for arguments: ]*/
+    if (HTTPAPIEX_ExecuteRequest(http_api_handle, HTTPAPI_REQUEST_POST, relative_path, request_header,
+        blobBuffer, &statusCode, NULL, response_buff) != HTTPAPIEX_OK)
+    {
+        /*Codes_SRS_IOTHUBCLIENT_LL_02_076: [ If HTTPAPIEX_ExecuteRequest call fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+        result = MU_FAILURE;
+        LogError("unable to HTTPAPIEX_ExecuteRequest");
+    }
+    else if (statusCode >= 300)
+    {
+        result = MU_FAILURE;
+        LogError("HTTP code was %u", statusCode);
+    }
+    else
+    {
+        result = 0;
+    }
+    return result;
+}
+
+static int parse_result_json(const char* json_response, STRING_HANDLE correlation_id, STRING_HANDLE sas_uri)
+{
+    int result;
+
+    JSON_Object* json_obj;
+    /*Codes_SRS_IOTHUBCLIENT_LL_02_081: [ Otherwise, IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall use parson to extract and save the following information from the response buffer: correlationID and SasUri. ]*/
+    JSON_Value* json = json_parse_string(json_response);
+    if (json == NULL)
+    {
+        /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+        LogError("unable to json_parse_string");
+        result = MU_FAILURE;
+
+    }
+    else
+    {
+        if ((json_obj = json_value_get_object(json)) == NULL)
+        {
+            LogError("unable to get json_value_get_object");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            const char* json_corr_id;
+            const char* json_hostname;
+            const char* json_container_name;
+            const char* json_blob_name;
+            const char* json_sas_token;
+            STRING_HANDLE filename;
+            if ((json_corr_id = json_object_get_string(json_obj, "correlationId")) == NULL)
+            {
+                LogError("unable to retrieve correlation Id from json");
+                result = MU_FAILURE;
+            }
+            else if ((json_hostname = json_object_get_string(json_obj, "hostName")) == NULL)
+            {
+                LogError("unable to retrieve hostname Id from json");
+                result = MU_FAILURE;
+            }
+            else if ((json_container_name = json_object_get_string(json_obj, "containerName")) == NULL)
+            {
+                LogError("unable to retrieve container name Id from json");
+                result = MU_FAILURE;
+            }
+            else if ((json_blob_name = json_object_get_string(json_obj, "blobName")) == NULL)
+            {
+                LogError("unable to retrieve blob name Id from json");
+                result = MU_FAILURE;
+            }
+            else if ((json_sas_token = json_object_get_string(json_obj, "sasToken")) == NULL)
+            {
+                LogError("unable to retrieve sas token from json");
+                result = MU_FAILURE;
+            }
+            /*Codes_SRS_IOTHUBCLIENT_LL_32_008: [ The returned file name shall be URL encoded before passing back to the cloud. ]*/
+            else if ((filename = URL_EncodeString(json_blob_name)) == NULL)
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_32_009: [ If URL_EncodeString fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                LogError("unable to URL encode of filename");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                if (STRING_sprintf(sas_uri, "https://%s/%s/%s%s", json_hostname, json_container_name, STRING_c_str(filename), json_sas_token) != 0)
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                    LogError("unable to construct uri string");
+                    result = MU_FAILURE;
+                }
+                else if (STRING_copy(correlation_id, json_corr_id) != 0)
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                    LogError("unable to copy correlation Id");
+                    result = MU_FAILURE;
+                    STRING_empty(sas_uri);
+                }
+                else
+                {
+                    result = 0;
+                }
+                STRING_delete(filename);
+            }
+        }
+        json_value_free(json);
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE IoTHubClient_LL_UploadToBlob_Create(const IOTHUB_CLIENT_CONFIG* config, IOTHUB_AUTHORIZATION_HANDLE auth_handle)
+{
+    IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data;
+    if (auth_handle == NULL || config == NULL)
+    {
+        LogError("Invalid arguments auth_handle: %p, config: %p", auth_handle, config);
+        upload_data = NULL;
+    }
+    else
+    {
+        upload_data = malloc(sizeof(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA));
+        if (upload_data == NULL)
+        {
+            LogError("Failed malloc allocation");
+            /*return as is*/
+        }
+        else
+        {
+            memset(upload_data, 0, sizeof(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA));
+
+            upload_data->authorization_module = auth_handle;
+
+            size_t iotHubNameLength = strlen(config->iotHubName);
+            size_t iotHubSuffixLength = strlen(config->iotHubSuffix);
+            upload_data->hostname = malloc(iotHubNameLength + 1 + iotHubSuffixLength + 1); /*first +1 is because "." the second +1 is because \0*/
+            if (upload_data->hostname == NULL)
+            {
+                LogError("Failed malloc allocation");
+                free(upload_data);
+                upload_data = NULL;
+            }
+            else if ((upload_data->deviceId = IoTHubClient_Auth_Get_DeviceId(upload_data->authorization_module)) == NULL)
+            {
+                LogError("Failed retrieving device ID");
+                free(upload_data->hostname);
+                free(upload_data);
+                upload_data = NULL;
+            }
+            else
+            {
+                char* insert_pos = (char*)upload_data->hostname;
+                (void)memcpy((char*)insert_pos, config->iotHubName, iotHubNameLength);
+                insert_pos += iotHubNameLength;
+                *insert_pos = '.';
+                insert_pos += 1;
+                (void)memcpy(insert_pos, config->iotHubSuffix, iotHubSuffixLength); /*+1 will copy the \0 too*/
+                insert_pos += iotHubSuffixLength;
+                *insert_pos = '\0';
+
+                upload_data->cred_type = IoTHubClient_Auth_Get_Credential_Type(upload_data->authorization_module);
+                // If the credential type is unknown then it means that we are using x509 because the certs need to get
+                // passed down later in the process.
+                if (upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_UNKNOWN || upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_X509)
+                {
+                    upload_data->cred_type = IOTHUB_CREDENTIAL_TYPE_X509;
+                    upload_data->credentials.x509_credentials.x509certificate = NULL;
+                    upload_data->credentials.x509_credentials.x509privatekey = NULL;
+                }
+                else if (upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_X509_ECC)
+                {
+                    if (IoTHubClient_Auth_Get_x509_info(upload_data->authorization_module, &upload_data->credentials.x509_credentials.x509certificate, &upload_data->credentials.x509_credentials.x509privatekey) != 0)
+                    {
+                        LogError("Failed getting x509 certificate information");
+                        free(upload_data->hostname);
+                        free(upload_data);
+                        upload_data = NULL;
+                    }
+                }
+                else if (upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN)
+                {
+                    upload_data->credentials.supplied_sas_token = IoTHubClient_Auth_Get_SasToken(upload_data->authorization_module, NULL, 0, EMPTY_STRING);
+                    if (upload_data->credentials.supplied_sas_token == NULL)
+                    {
+                        LogError("Failed retrieving supplied sas token");
+                        free(upload_data->hostname);
+                        free(upload_data);
+                        upload_data = NULL;
+                    }
+                }
+            }
+        }
+    }
+    return (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE)upload_data;
+
+}
+
+/*returns 0 when correlationId, sasUri contain data*/
+static int IoTHubClient_LL_UploadToBlob_step1and2(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data, HTTPAPIEX_HANDLE iotHubHttpApiExHandle, HTTP_HEADERS_HANDLE requestHttpHeaders, const char* destinationFileName, STRING_HANDLE correlationId, STRING_HANDLE sasUri)
+{
+    int result;
+
+    /*Codes_SRS_IOTHUBCLIENT_LL_02_066: [ IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall create an HTTP relative path formed from "/devices/" + deviceId + "/files/" + "?api-version=API_VERSION". ]*/
+    STRING_HANDLE relativePath = STRING_construct_sprintf("/devices/%s/files/%s", upload_data->deviceId, API_VERSION);
+    if (relativePath == NULL)
+    {
+        /*Codes_SRS_IOTHUBCLIENT_LL_02_067: [ If creating the relativePath fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+        LogError("Failure constructing string");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        /*Codes_SRS_IOTHUBCLIENT_LL_32_001: [ IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall create a JSON string formed from "{ \"blobName\": \" + destinationFileName + "\" }" */
+        STRING_HANDLE blobName = STRING_construct_sprintf("{ \"blobName\": \"%s\" }", destinationFileName);
+        if (blobName == NULL)
+        {
+            /*Codes_SRS_IOTHUBCLIENT_LL_32_002: [ If creating the JSON string fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+            LogError("Failure constructing string");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            BUFFER_HANDLE responseContent;
+            size_t len = STRING_length(blobName);
+            BUFFER_HANDLE blobBuffer = BUFFER_create((const unsigned char *)STRING_c_str(blobName), len);
+            if (blobBuffer == NULL)
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_32_002: [ If creating the JSON string fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                LogError("unable to create BUFFER");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_02_068: [ IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall create an HTTP responseContent BUFFER_HANDLE. ]*/
+                if ((responseContent = BUFFER_new()) == NULL)
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_02_069: [ If creating the HTTP response buffer handle fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                    result = MU_FAILURE;
+                    LogError("unable to BUFFER_new");
+                }
+                else
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_02_072: [ IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall add the following name:value to request HTTP headers: ] "Content-Type": "application/json" "Accept": "application/json" "User-Agent": "iothubclient/" IOTHUB_SDK_VERSION*/
+                    /*Codes_SRS_IOTHUBCLIENT_LL_02_107: [ - "Authorization" header shall not be build. ]*/
+                    if (!(
+                        (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "Content-Type", HEADER_APP_JSON) == HTTP_HEADERS_OK) &&
+                        (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "Accept", HEADER_APP_JSON) == HTTP_HEADERS_OK) &&
+                        (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "User-Agent", "iothubclient/" IOTHUB_SDK_VERSION) == HTTP_HEADERS_OK) &&
+                        ((upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_X509 || upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_X509_ECC) ||
+                        (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, HEADER_AUTHORIZATION, EMPTY_STRING) == HTTP_HEADERS_OK))
+                        ))
+                    {
+                        /*Codes_SRS_IOTHUBCLIENT_LL_02_071: [ If creating the HTTP headers fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                        LogError("unable to HTTPHeaders_AddHeaderNameValuePair");
+                        result = MU_FAILURE;
+                    }
+                    else
+                    {
+                        int wasIoTHubRequestSuccess = 0; /*!=0 means responseContent has a buffer that should be parsed by parson after executing the below switch*/
+                        /* set the result to error by default */
+                        result = MU_FAILURE;
+                        switch (upload_data->cred_type)
+                        {
+                            default:
+                            {
+                                /*wasIoTHubRequestSuccess takes care of the return value*/
+                                LogError("Internal Error: unexpected value in auth schema = %d", upload_data->cred_type);
+                                result = MU_FAILURE;
+                                break;
+                            }
+                            case IOTHUB_CREDENTIAL_TYPE_X509_ECC:
+                            case IOTHUB_CREDENTIAL_TYPE_X509:
+                            {
+                                if (send_http_request(iotHubHttpApiExHandle, STRING_c_str(relativePath), requestHttpHeaders, blobBuffer, responseContent) != 0)
+                                {
+                                    /*Codes_SRS_IOTHUBCLIENT_LL_02_076: [ If HTTPAPIEX_ExecuteRequest call fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                    result = MU_FAILURE;
+                                    LogError("unable to HTTPAPIEX_ExecuteRequest");
+                                }
+                                else
+                                {
+                                    wasIoTHubRequestSuccess = 1;
+                                }
+                                break;
+                            }
+                            case IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY:
+                            case IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH:
+                            {
+                                STRING_HANDLE uri_resource = STRING_construct_sprintf("%s/devices/%s", upload_data->hostname, upload_data->deviceId);
+                                if (uri_resource == NULL)
+                                {
+                                    /*Codes_SRS_IOTHUBCLIENT_LL_02_089: [ If creating the HTTPAPIEX_SAS_HANDLE fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                    result = MU_FAILURE;
+                                    LogError("Failure constructing string");
+                                }
+                                else
+                                {
+                                    if (upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH)
+                                    {
+                                        time_t curr_time;
+                                        if ((curr_time = get_time(NULL)) == INDEFINITE_TIME)
+                                        {
+                                            result = MU_FAILURE;
+                                            LogError("failure retrieving time");
+                                        }
+                                        else
+                                        {
+                                            size_t expiry = (size_t)(difftime(curr_time, 0) + 3600);
+                                            char* sas_token = IoTHubClient_Auth_Get_SasToken(upload_data->authorization_module, STRING_c_str(uri_resource), expiry, EMPTY_STRING);
+                                            if (sas_token == NULL)
+                                            {
+                                                result = MU_FAILURE;
+                                                LogError("unable to retrieve sas token");
+                                            }
+                                            else
+                                            {
+                                                if (HTTPHeaders_ReplaceHeaderNameValuePair(requestHttpHeaders, HEADER_AUTHORIZATION, sas_token) != HTTP_HEADERS_OK)
+                                                {
+                                                    /*Codes_SRS_IOTHUBCLIENT_LL_02_074: [ If adding "Authorization" fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR ]*/
+                                                    result = MU_FAILURE;
+                                                    LogError("unable to HTTPHeaders_AddHeaderNameValuePair");
+                                                }
+                                                else if (send_http_request(iotHubHttpApiExHandle, STRING_c_str(relativePath), requestHttpHeaders, blobBuffer, responseContent) != 0)
+                                                {
+                                                    /*Codes_SRS_IOTHUBCLIENT_LL_02_076: [ If HTTPAPIEX_ExecuteRequest call fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                                    result = MU_FAILURE;
+                                                    LogError("unable to HTTPAPIEX_ExecuteRequest");
+                                                }
+                                                else
+                                                {
+                                                    wasIoTHubRequestSuccess = 1;
+                                                }
+                                            }
+                                            free(sas_token);
+                                        }
+                                    }
+                                    else
+                                    {
+                                        if (send_http_sas_request(upload_data, STRING_c_str(uri_resource), iotHubHttpApiExHandle, STRING_c_str(relativePath), requestHttpHeaders, blobBuffer, responseContent) != 0)
+                                        {
+                                            /*Codes_SRS_IOTHUBCLIENT_LL_02_076: [ If HTTPAPIEX_ExecuteRequest call fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                            result = MU_FAILURE;
+                                            LogError("unable to HTTPAPIEX_ExecuteRequest");
+                                        }
+                                        else
+                                        {
+                                            wasIoTHubRequestSuccess = 1;
+                                        }
+                                    }
+                                    STRING_delete(uri_resource);
+                                }
+                                break;
+                            }
+                            case IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN:
+                            {
+                                /*Codes_SRS_IOTHUBCLIENT_LL_02_073: [ If the credentials used to create handle have "sasToken" then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall add the following HTTP request headers: ]*/
+                                if (HTTPHeaders_ReplaceHeaderNameValuePair(requestHttpHeaders, HEADER_AUTHORIZATION, upload_data->credentials.supplied_sas_token) != HTTP_HEADERS_OK)
+                                {
+                                    /*Codes_SRS_IOTHUBCLIENT_LL_02_074: [ If adding "Authorization" fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR ]*/
+                                    result = MU_FAILURE;
+                                    LogError("unable to HTTPHeaders_AddHeaderNameValuePair");
+                                }
+                                else if (send_http_request(iotHubHttpApiExHandle, STRING_c_str(relativePath), requestHttpHeaders, blobBuffer, responseContent) != 0)
+                                {
+                                    /*Codes_SRS_IOTHUBCLIENT_LL_02_076: [ If HTTPAPIEX_ExecuteRequest call fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                    result = MU_FAILURE;
+                                    LogError("unable to HTTPAPIEX_ExecuteRequest");
+                                }
+                                else
+                                {
+                                    wasIoTHubRequestSuccess = 1;
+                                }
+                                break;
+                            }
+                        }
+                        if (wasIoTHubRequestSuccess == 1)
+                        {
+                            const unsigned char*responseContent_u_char = BUFFER_u_char(responseContent);
+                            size_t responseContent_length = BUFFER_length(responseContent);
+                            STRING_HANDLE responseAsString = STRING_from_byte_array(responseContent_u_char, responseContent_length);
+                            if (responseAsString == NULL)
+                            {
+                                result = MU_FAILURE;
+                                LogError("unable to get the response as string");
+                            }
+                            else
+                            {
+                                if (parse_result_json(STRING_c_str(responseAsString), correlationId, sasUri) != 0)
+                                {
+                                    /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                    LogError("unable to parse json result");
+                                    result = MU_FAILURE;
+                                }
+                                else
+                                {
+                                    result = 0;
+                                }
+                                STRING_delete(responseAsString);
+                            }
+                        }
+                    }
+                    BUFFER_delete(responseContent);
+                }
+                BUFFER_delete(blobBuffer);
+            }
+            STRING_delete(blobName);
+        }
+        STRING_delete(relativePath);
+    }
+    return result;
+}
+
+/*returns 0 when the IoTHub has been informed about the file upload status*/
+static int IoTHubClient_LL_UploadToBlob_step3(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data, HTTPAPIEX_HANDLE iotHubHttpApiExHandle, HTTP_HEADERS_HANDLE requestHttpHeaders, BUFFER_HANDLE messageBody)
+{
+    int result;
+    /*here is step 3. depending on the outcome of step 2 it needs to inform IoTHub about the file upload status*/
+    /*if step 1 failed, there's nothing that step 3 needs to report.*/
+    /*this POST "tries" to happen*/
+
+    /*Codes_SRS_IOTHUBCLIENT_LL_02_085: [ IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall use the same authorization as step 1. to prepare and perform a HTTP request with the following parameters: ]*/
+    STRING_HANDLE relativePathNotification = STRING_construct_sprintf("/devices/%s/files/notifications/%s", upload_data->deviceId, API_VERSION);
+    if (relativePathNotification == NULL)
+    {
+        result = MU_FAILURE;
+        LogError("Failure constructing string");
+    }
+    else
+    {
+        /*Codes_SRS_IOTHUBCLIENT_LL_02_086: [ If performing the HTTP request fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+        switch (upload_data->cred_type)
+        {
+            default:
+            {
+                LogError("internal error: unknown authorization Scheme");
+                result = MU_FAILURE;
+                break;
+            }
+            case IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN:
+            case IOTHUB_CREDENTIAL_TYPE_X509:
+            case IOTHUB_CREDENTIAL_TYPE_X509_ECC:
+            case IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH:
+            {
+                if (send_http_request(iotHubHttpApiExHandle, STRING_c_str(relativePathNotification), requestHttpHeaders, messageBody, NULL) != 0)
+                {
+                    LogError("unable to execute HTTPAPIEX_ExecuteRequest");
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    result = 0;
+                }
+                break;
+            }
+            case IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY:
+            {
+                STRING_HANDLE uriResource = STRING_construct_sprintf("%s/devices/%s/files/notifications", upload_data->hostname, upload_data->deviceId);
+                if (uriResource == NULL)
+                {
+                    LogError("Failure constructing string");
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    if (send_http_sas_request(upload_data, STRING_c_str(uriResource), iotHubHttpApiExHandle, STRING_c_str(relativePathNotification), requestHttpHeaders, messageBody, NULL) != 0)
+                    {
+                        LogError("unable to execute HTTPAPIEX_ExecuteRequest");
+                        result = MU_FAILURE;
+                    }
+                    else
+                    {
+                        result = 0;
+                    }
+                    STRING_delete(uriResource);
+                }
+                break;
+            }
+        }
+        STRING_delete(relativePathNotification);
+    }
+    return result;
+}
+
+// this callback splits the source data into blocks to be fed to IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex)_Impl
+static IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT FileUpload_GetData_Callback(IOTHUB_CLIENT_FILE_UPLOAD_RESULT result, unsigned char const ** data, size_t* size, void* context)
+{
+    BLOB_UPLOAD_CONTEXT* uploadContext = (BLOB_UPLOAD_CONTEXT*) context;
+
+    if (data == NULL || size == NULL)
+    {
+        // This is the last call, nothing to do
+    }
+    else if (result != FILE_UPLOAD_OK)
+    {
+        // Last call failed
+        *data = NULL;
+        *size = 0;
+    }
+    else if (uploadContext->remainingSizeToUpload == 0)
+    {
+        // Everything has been uploaded
+        *data = NULL;
+        *size = 0;
+    }
+    else
+    {
+        // Upload next block
+        size_t thisBlockSize = (uploadContext->remainingSizeToUpload > BLOCK_SIZE) ? BLOCK_SIZE : uploadContext->remainingSizeToUpload;
+        *data = (unsigned char*)uploadContext->blobSource + (uploadContext->blobSourceSize - uploadContext->remainingSizeToUpload);
+        *size = thisBlockSize;
+        uploadContext->remainingSizeToUpload -= thisBlockSize;
+    }
+
+    return IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_OK;
+}
+
+static HTTPAPIEX_RESULT set_transfer_timeout(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data, HTTPAPIEX_HANDLE iotHubHttpApiExHandle)
+{
+    HTTPAPIEX_RESULT result;
+    if (upload_data->blob_upload_timeout_secs != 0)
+    {
+        // Convert the timeout to milliseconds for curl
+        long http_timeout = (long)upload_data->blob_upload_timeout_secs * 1000;
+        result = HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_HTTP_TIMEOUT, &http_timeout);
+    }
+    else
+    {
+        result = HTTPAPIEX_OK;
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE handle, const char* destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx, void* context)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    /*Codes_SRS_IOTHUBCLIENT_LL_02_061: [ If handle is NULL then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/
+    /*Codes_SRS_IOTHUBCLIENT_LL_02_062: [ If destinationFileName is NULL then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/
+
+    if (handle == NULL || destinationFileName == NULL || getDataCallbackEx == NULL)
+    {
+        LogError("invalid argument detected handle=%p destinationFileName=%p getDataCallbackEx=%p", handle, destinationFileName, getDataCallbackEx);
+        result = IOTHUB_CLIENT_INVALID_ARG;
+    }
+    else
+    {
+        IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data = (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA*)handle;
+
+        /*Codes_SRS_IOTHUBCLIENT_LL_02_064: [ IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall create an HTTPAPIEX_HANDLE to the IoTHub hostname. ]*/
+        HTTPAPIEX_HANDLE iotHubHttpApiExHandle = HTTPAPIEX_Create(upload_data->hostname);
+        /*Codes_SRS_IOTHUBCLIENT_LL_02_065: [ If creating the HTTPAPIEX_HANDLE fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+        if (iotHubHttpApiExHandle == NULL)
+        {
+            LogError("unable to HTTPAPIEX_Create");
+            result = IOTHUB_CLIENT_ERROR;
+        }
+        /*Codes_SRS_IOTHUBCLIENT_LL_30_020: [ If the blob_upload_timeout_secs option has been set to non-zero, IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall set the timeout on the underlying transport accordingly. ]*/
+        else if (set_transfer_timeout(upload_data, iotHubHttpApiExHandle) != HTTPAPIEX_OK)
+        {
+            LogError("unable to set blob transfer timeout");
+            result = IOTHUB_CLIENT_ERROR;
+        }
+        else
+        {
+            if (upload_data->curl_verbosity_level != UPOADTOBLOB_CURL_VERBOSITY_UNSET)
+            {
+                size_t curl_verbose = (upload_data->curl_verbosity_level == UPOADTOBLOB_CURL_VERBOSITY_ON);
+                (void)HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_CURL_VERBOSE, &curl_verbose);
+            }
+
+            /*transmit the x509certificate and x509privatekey*/
+            /*Codes_SRS_IOTHUBCLIENT_LL_02_106: [ - x509certificate and x509privatekey saved options shall be passed on the HTTPAPIEX_SetOption ]*/
+            if ((upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_X509 || upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_X509_ECC) &&
+                ((HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_X509_CERT, upload_data->credentials.x509_credentials.x509certificate) != HTTPAPIEX_OK) ||
+                (HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_X509_PRIVATE_KEY, upload_data->credentials.x509_credentials.x509privatekey) != HTTPAPIEX_OK))
+                )
+            {
+                LogError("unable to HTTPAPIEX_SetOption for x509 certificate");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_02_111: [ If certificates is non-NULL then certificates shall be passed to HTTPAPIEX_SetOption with optionName TrustedCerts. ]*/
+                if ((upload_data->certificates != NULL) && (HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_TRUSTED_CERT, upload_data->certificates) != HTTPAPIEX_OK))
+                {
+                    LogError("unable to set TrustedCerts!");
+                    result = IOTHUB_CLIENT_ERROR;
+                }
+                else
+                {
+
+                    if (upload_data->http_proxy_options.host_address != NULL)
+                    {
+                        HTTP_PROXY_OPTIONS proxy_options;
+                        proxy_options = upload_data->http_proxy_options;
+
+                        if (HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_HTTP_PROXY, &proxy_options) != HTTPAPIEX_OK)
+                        {
+                            LogError("unable to set http proxy!");
+                            result = IOTHUB_CLIENT_ERROR;
+                        }
+                        else
+                        {
+                            result = IOTHUB_CLIENT_OK;
+                        }
+                    }
+                    else
+                    {
+                        result = IOTHUB_CLIENT_OK;
+                    }
+
+                    if (result != IOTHUB_CLIENT_ERROR)
+                    {
+                        STRING_HANDLE sasUri;
+                        STRING_HANDLE correlationId;
+                        if ((correlationId = STRING_new()) == NULL)
+                        {
+                            LogError("unable to STRING_new");
+                            result = IOTHUB_CLIENT_ERROR;
+                        }
+                        else if ((sasUri = STRING_new()) == NULL)
+                        {
+                            LogError("unable to create sas uri");
+                            result = IOTHUB_CLIENT_ERROR;
+                            STRING_delete(correlationId);
+                        }
+                        else
+                        {
+                            /*Codes_SRS_IOTHUBCLIENT_LL_02_070: [ IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall create request HTTP headers. ]*/
+                            HTTP_HEADERS_HANDLE requestHttpHeaders = HTTPHeaders_Alloc(); /*these are build by step 1 and used by step 3 too*/
+                            if (requestHttpHeaders == NULL)
+                            {
+                                LogError("unable to HTTPHeaders_Alloc");
+                                result = IOTHUB_CLIENT_ERROR;
+                            }
+                            else
+                            {
+                                /*do step 1*/
+                                if (IoTHubClient_LL_UploadToBlob_step1and2(upload_data, iotHubHttpApiExHandle, requestHttpHeaders, destinationFileName, correlationId, sasUri) != 0)
+                                {
+                                    LogError("error in IoTHubClient_LL_UploadToBlob_step1");
+                                    result = IOTHUB_CLIENT_ERROR;
+                                }
+                                else
+                                {
+                                    /*do step 2.*/
+
+                                    unsigned int httpResponse;
+                                    BUFFER_HANDLE responseToIoTHub = BUFFER_new();
+                                    if (responseToIoTHub == NULL)
+                                    {
+                                        result = IOTHUB_CLIENT_ERROR;
+                                        LogError("unable to BUFFER_new");
+                                    }
+                                    else
+                                    {
+                                        /*Codes_SRS_IOTHUBCLIENT_LL_02_083: [ IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall call Blob_UploadFromSasUri and capture the HTTP return code and HTTP body. ]*/
+                                        BLOB_RESULT uploadMultipleBlocksResult = Blob_UploadMultipleBlocksFromSasUri(STRING_c_str(sasUri), getDataCallbackEx, context, &httpResponse, responseToIoTHub, upload_data->certificates, &(upload_data->http_proxy_options));
+                                        if (uploadMultipleBlocksResult == BLOB_ABORTED)
+                                        {
+                                            /*Codes_SRS_IOTHUBCLIENT_LL_99_008: [ If step 2 is aborted by the client, then the HTTP message body shall look like:  ]*/
+                                            LogInfo("Blob_UploadFromSasUri aborted file upload");
+
+                                            STRING_HANDLE aborted_response = STRING_construct_sprintf(RESPONSE_BODY_FORMAT,
+                                                                                        STRING_c_str(correlationId),
+                                                                                        RESPONSE_BODY_ERROR_BOOLEAN_STRING,
+                                                                                        RESPONSE_BODY_ERROR_RETURN_CODE,
+                                                                                        RESPONSE_BODY_ABORTED_MESSAGE);
+                                            if(aborted_response == NULL)
+                                            {
+                                                LogError("STRING_construct_sprintf failed");
+                                                result = IOTHUB_CLIENT_ERROR;
+                                            }
+                                            else
+                                            {
+                                                size_t response_length = STRING_length(aborted_response);
+                                                if (BUFFER_build(responseToIoTHub, (const unsigned char*)STRING_c_str(aborted_response), response_length) == 0)
+                                                {
+                                                    if (IoTHubClient_LL_UploadToBlob_step3(upload_data, iotHubHttpApiExHandle, requestHttpHeaders, responseToIoTHub) != 0)
+                                                    {
+                                                        LogError("IoTHubClient_LL_UploadToBlob_step3 failed");
+                                                        result = IOTHUB_CLIENT_ERROR;
+                                                    }
+                                                    else
+                                                    {
+                                                        /*Codes_SRS_IOTHUBCLIENT_LL_99_009: [ If step 2 is aborted by the client and if step 3 succeeds, then `IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex)` shall return `IOTHUB_CLIENT_OK`. ] */
+                                                        result = IOTHUB_CLIENT_OK;
+                                                    }
+                                                }
+                                                else
+                                                {
+                                                    LogError("Unable to BUFFER_build, can't perform IoTHubClient_LL_UploadToBlob_step3");
+                                                    result = IOTHUB_CLIENT_ERROR;
+                                                }
+                                                STRING_delete(aborted_response);
+                                            }
+                                        }
+                                        else if (uploadMultipleBlocksResult != BLOB_OK)
+                                        {
+                                            /*Codes_SRS_IOTHUBCLIENT_LL_02_084: [ If Blob_UploadFromSasUri fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                            LogError("unable to Blob_UploadFromSasUri");
+
+                                            /*do step 3*/ /*try*/
+                                            /*Codes_SRS_IOTHUBCLIENT_LL_02_091: [ If step 2 fails without establishing an HTTP dialogue, then the HTTP message body shall look like: ]*/
+                                            STRING_HANDLE failed_response = STRING_construct_sprintf(RESPONSE_BODY_FORMAT, 
+                                                                                        STRING_c_str(correlationId), 
+                                                                                        RESPONSE_BODY_ERROR_BOOLEAN_STRING,
+                                                                                        RESPONSE_BODY_ERROR_RETURN_CODE,
+                                                                                        RESPONSE_BODY_FAILED_MESSAGE);
+                                            if(failed_response == NULL)
+                                            {
+                                                LogError("STRING_construct_sprintf failed");
+                                                result = IOTHUB_CLIENT_ERROR;
+                                            }
+                                            else
+                                            {
+                                                size_t response_length = STRING_length(failed_response);
+                                                if (BUFFER_build(responseToIoTHub, (const unsigned char*)STRING_c_str(failed_response), response_length) == 0)
+                                                {
+                                                    if (IoTHubClient_LL_UploadToBlob_step3(upload_data, iotHubHttpApiExHandle, requestHttpHeaders, responseToIoTHub) != 0)
+                                                    {
+                                                        LogError("IoTHubClient_LL_UploadToBlob_step3 failed");
+                                                    }
+                                                }
+                                                STRING_delete(failed_response);
+                                                result = IOTHUB_CLIENT_ERROR;
+                                            }
+                                        }
+                                        else
+                                        {
+                                            /*must make a json*/
+                                            unsigned char * response = BUFFER_u_char(responseToIoTHub);
+                                            STRING_HANDLE req_string;
+                                            req_string = STRING_construct_sprintf(RESPONSE_BODY_FORMAT,
+                                                                                        STRING_c_str(correlationId),
+                                                                                        ((httpResponse < 300) ? "true" : "false"),
+                                                                                        httpResponse, 
+                                                                                        (response == NULL ? (const unsigned char*)"" : response));
+                                            if (req_string == NULL)
+                                            {
+                                                LogError("Failure constructing string");
+                                                result = IOTHUB_CLIENT_ERROR;
+                                            }
+                                            else
+                                            {
+                                                /*do again snprintf*/
+                                                BUFFER_HANDLE toBeTransmitted = NULL;
+                                                size_t req_string_len = STRING_length(req_string);
+                                                const char* required_string = STRING_c_str(req_string);
+                                                if ((toBeTransmitted = BUFFER_create((const unsigned char*)required_string, req_string_len)) == NULL)
+                                                {
+                                                    LogError("unable to BUFFER_create");
+                                                    result = IOTHUB_CLIENT_ERROR;
+                                                }
+                                                else
+                                                {
+                                                    if (IoTHubClient_LL_UploadToBlob_step3(upload_data, iotHubHttpApiExHandle, requestHttpHeaders, toBeTransmitted) != 0)
+                                                    {
+                                                        LogError("IoTHubClient_LL_UploadToBlob_step3 failed");
+                                                        result = IOTHUB_CLIENT_ERROR;
+                                                    }
+                                                    else
+                                                    {
+                                                        result = (httpResponse < 300) ? IOTHUB_CLIENT_OK : IOTHUB_CLIENT_ERROR;
+                                                    }
+                                                    BUFFER_delete(toBeTransmitted);
+                                                }
+                                                STRING_delete(req_string);
+                                            }
+                                        }
+                                        BUFFER_delete(responseToIoTHub);
+                                    }
+                                }
+                                HTTPHeaders_Free(requestHttpHeaders);
+                            }
+                            STRING_delete(sasUri);
+                            STRING_delete(correlationId);
+                        }
+                    }
+                }
+            }
+            HTTPAPIEX_Destroy(iotHubHttpApiExHandle);
+        }
+
+        /*Codes_SRS_IOTHUBCLIENT_LL_99_003: [ If `IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex)` return `IOTHUB_CLIENT_OK`, it shall call `getDataCallbackEx` with `result` set to `FILE_UPLOAD_OK`, and `data` and `size` set to NULL. ]*/
+        /*Codes_SRS_IOTHUBCLIENT_LL_99_004: [ If `IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex)` does not return `IOTHUB_CLIENT_OK`, it shall call `getDataCallbackEx` with `result` set to `FILE_UPLOAD_ERROR`, and `data` and `size` set to NULL. ]*/
+        (void)getDataCallbackEx(result == IOTHUB_CLIENT_OK ? FILE_UPLOAD_OK : FILE_UPLOAD_ERROR, NULL, NULL, context);
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_Impl(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE handle, const char* destinationFileName, const unsigned char* source, size_t size)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    if (handle == NULL || destinationFileName == NULL)
+    {
+        LogError("Invalid parameter handle:%p destinationFileName:%p", handle, destinationFileName);
+        result = IOTHUB_CLIENT_INVALID_ARG;
+    }
+    /*Codes_SRS_IOTHUBCLIENT_LL_02_063: [ If source is NULL and size is greater than 0 then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/
+    else if (source == NULL && size > 0)
+    {
+        LogError("Invalid source and size combination: source=%p size=%lu", source, (unsigned long)size);
+        result = IOTHUB_CLIENT_INVALID_ARG;
+    }
+    else
+    {
+        /*Codes_SRS_IOTHUBCLIENT_LL_99_001: [ `IoTHubClient_LL_UploadToBlob` shall create a struct containing the `source`, the `size`, and the remaining size to upload.]*/
+        BLOB_UPLOAD_CONTEXT context;
+        context.blobSource = source;
+        context.blobSourceSize = size;
+        context.remainingSizeToUpload = size;
+
+        /*Codes_SRS_IOTHUBCLIENT_LL_99_002: [ `IoTHubClient_LL_UploadToBlob` shall call `IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl` with `FileUpload_GetData_Callback` as `getDataCallbackEx` and pass the struct created at step SRS_IOTHUBCLIENT_LL_99_001 as `context` ]*/
+        result = IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl(handle, destinationFileName, FileUpload_GetData_Callback, &context);
+    }
+    return result;
+}
+
+void IoTHubClient_LL_UploadToBlob_Destroy(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE handle)
+{
+    if (handle == NULL)
+    {
+        LogError("unexpected NULL argument");
+    }
+    else
+    {
+        IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data = (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA*)handle;
+
+        if (upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_X509 || upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_X509_ECC)
+        {
+            free(upload_data->credentials.x509_credentials.x509certificate);
+            free(upload_data->credentials.x509_credentials.x509privatekey);
+        }
+        else if (upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN)
+        {
+            free(upload_data->credentials.supplied_sas_token);
+        }
+
+        free((void*)upload_data->hostname);
+        if (upload_data->certificates != NULL)
+        {
+            free(upload_data->certificates);
+        }
+        if (upload_data->http_proxy_options.host_address != NULL)
+        {
+            free((char *)upload_data->http_proxy_options.host_address);
+        }
+        if (upload_data->http_proxy_options.username != NULL)
+        {
+            free((char *)upload_data->http_proxy_options.username);
+        }
+        if (upload_data->http_proxy_options.password != NULL)
+        {
+            free((char *)upload_data->http_proxy_options.password);
+        }
+        free(upload_data);
+    }
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_SetOption(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE handle, const char* optionName, const void* value)
+{
+    IOTHUB_CLIENT_RESULT result;
+    /*Codes_SRS_IOTHUBCLIENT_LL_02_110: [ If parameter handle is NULL then IoTHubClient_LL_UploadToBlob_SetOption shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+    if (handle == NULL)
+    {
+        LogError("invalid argument detected: IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE handle=%p, const char* optionName=%s, const void* value=%p", handle, optionName, value);
+        result = IOTHUB_CLIENT_ERROR;
+    }
+    else
+    {
+        IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data = (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA*)handle;
+
+        /*Codes_SRS_IOTHUBCLIENT_LL_02_100: [ x509certificate - then value then is a null terminated string that contains the x509 certificate. ]*/
+        if (strcmp(optionName, OPTION_X509_CERT) == 0)
+        {
+            /*Codes_SRS_IOTHUBCLIENT_LL_02_109: [ If the authentication scheme is NOT x509 then IoTHubClient_LL_UploadToBlob_SetOption shall return IOTHUB_CLIENT_INVALID_ARG. ]*/
+            if (upload_data->cred_type != IOTHUB_CREDENTIAL_TYPE_X509)
+            {
+                LogError("trying to set a x509 certificate while the authentication scheme is not x509");
+                result = IOTHUB_CLIENT_INVALID_ARG;
+            }
+            else
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_02_103: [ The options shall be saved. ]*/
+                /*try to make a copy of the certificate*/
+                char* temp;
+                if (mallocAndStrcpy_s(&temp, value) != 0)
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_02_104: [ If saving fails, then IoTHubClient_LL_UploadToBlob_SetOption shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                    LogError("unable to mallocAndStrcpy_s");
+                    result = IOTHUB_CLIENT_ERROR;
+                }
+                else
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_02_105: [ Otherwise IoTHubClient_LL_UploadToBlob_SetOption shall succeed and return IOTHUB_CLIENT_OK. ]*/
+                    if (upload_data->credentials.x509_credentials.x509certificate != NULL) /*free any previous values, if any*/
+                    {
+                        free(upload_data->credentials.x509_credentials.x509certificate);
+                    }
+                    upload_data->credentials.x509_credentials.x509certificate = temp;
+                    result = IOTHUB_CLIENT_OK;
+                }
+            }
+        }
+        /*Codes_SRS_IOTHUBCLIENT_LL_02_101: [ x509privatekey - then value is a null terminated string that contains the x509 privatekey. ]*/
+        else if (strcmp(optionName, OPTION_X509_PRIVATE_KEY) == 0)
+        {
+            /*Codes_SRS_IOTHUBCLIENT_LL_02_109: [ If the authentication scheme is NOT x509 then IoTHubClient_LL_UploadToBlob_SetOption shall return IOTHUB_CLIENT_INVALID_ARG. ]*/
+            if (upload_data->cred_type != IOTHUB_CREDENTIAL_TYPE_X509)
+            {
+                LogError("trying to set a x509 privatekey while the authentication scheme is not x509");
+                result = IOTHUB_CLIENT_INVALID_ARG;
+            }
+            else
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_02_103: [ The options shall be saved. ]*/
+                /*try to make a copy of the privatekey*/
+                char* temp;
+                if (mallocAndStrcpy_s(&temp, value) != 0)
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_02_104: [ If saving fails, then IoTHubClient_LL_UploadToBlob_SetOption shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                    LogError("unable to mallocAndStrcpy_s");
+                    result = IOTHUB_CLIENT_ERROR;
+                }
+                else
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_02_105: [ Otherwise IoTHubClient_LL_UploadToBlob_SetOption shall succeed and return IOTHUB_CLIENT_OK. ]*/
+                    if (upload_data->credentials.x509_credentials.x509privatekey != NULL) /*free any previous values, if any*/
+                    {
+                        free(upload_data->credentials.x509_credentials.x509privatekey);
+                    }
+                    upload_data->credentials.x509_credentials.x509privatekey = temp;
+                    result = IOTHUB_CLIENT_OK;
+                }
+            }
+        }
+        else if (strcmp(OPTION_TRUSTED_CERT, optionName) == 0)
+        {
+            if (value == NULL)
+            {
+                LogError("NULL is a not a valid value for TrustedCerts");
+                result = IOTHUB_CLIENT_INVALID_ARG;
+            }
+            else
+            {
+                char* tempCopy;
+                if (mallocAndStrcpy_s(&tempCopy, value) != 0)
+                {
+                    LogError("failure in mallocAndStrcpy_s");
+                    result = IOTHUB_CLIENT_ERROR;
+                }
+                else
+                {
+                    if (upload_data->certificates != NULL)
+                    {
+                        free(upload_data->certificates);
+                    }
+                    upload_data->certificates = tempCopy;
+                    result = IOTHUB_CLIENT_OK;
+                }
+            }
+        }
+        /*Codes_SRS_IOTHUBCLIENT_LL_32_008: [ OPTION_HTTP_PROXY - then the value will be a pointer to HTTP_PROXY_OPTIONS structure. ]*/
+        else if (strcmp(optionName, OPTION_HTTP_PROXY) == 0)
+        {
+            HTTP_PROXY_OPTIONS* proxy_options = (HTTP_PROXY_OPTIONS *)value;
+
+            if (proxy_options->host_address == NULL)
+            {
+                /* Codes_SRS_IOTHUBCLIENT_LL_32_006: [ If `host_address` is NULL, `IoTHubClient_LL_UploadToBlob_SetOption` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
+                LogError("NULL host_address in proxy options");
+                result = IOTHUB_CLIENT_INVALID_ARG;
+            }
+            /* Codes_SRS_IOTHUBCLIENT_LL_32_007: [ If only one of `username` and `password` is NULL, `IoTHubClient_LL_UploadToBlob_SetOption` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
+            else if (((proxy_options->username == NULL) || (proxy_options->password == NULL)) &&
+                (proxy_options->username != proxy_options->password))
+            {
+                LogError("Only one of username and password for proxy settings was NULL");
+                result = IOTHUB_CLIENT_INVALID_ARG;
+            }
+            else
+            {
+                if (upload_data->http_proxy_options.host_address != NULL)
+                {
+                    free((char *)upload_data->http_proxy_options.host_address);
+                    upload_data->http_proxy_options.host_address = NULL;
+                }
+                if (upload_data->http_proxy_options.username != NULL)
+                {
+                    free((char *)upload_data->http_proxy_options.username);
+                    upload_data->http_proxy_options.username = NULL;
+                }
+                if (upload_data->http_proxy_options.password != NULL)
+                {
+                    free((char *)upload_data->http_proxy_options.password);
+                    upload_data->http_proxy_options.password = NULL;
+                }
+
+                upload_data->http_proxy_options.port = proxy_options->port;
+
+                if (mallocAndStrcpy_s((char **)(&upload_data->http_proxy_options.host_address), proxy_options->host_address) != 0)
+                {
+                    LogError("failure in mallocAndStrcpy_s - upload_data->http_proxy_options.host_address");
+                    result = IOTHUB_CLIENT_ERROR;
+                }
+                else if (proxy_options->username != NULL && mallocAndStrcpy_s((char **)(&upload_data->http_proxy_options.username), proxy_options->username) != 0)
+                {
+                    LogError("failure in mallocAndStrcpy_s - upload_data->http_proxy_options.username");
+                    result = IOTHUB_CLIENT_ERROR;
+                }
+                else if (proxy_options->password != NULL && mallocAndStrcpy_s((char **)(&upload_data->http_proxy_options.password), proxy_options->password) != 0)
+                {
+                    LogError("failure in mallocAndStrcpy_s - upload_data->http_proxy_options.password");
+                    result = IOTHUB_CLIENT_ERROR;
+                }
+                else
+                {
+                    result = IOTHUB_CLIENT_OK;
+                }
+            }
+        }
+        else if (strcmp(optionName, OPTION_CURL_VERBOSE) == 0)
+        {
+            upload_data->curl_verbosity_level = ((*(bool*)value) == 0) ? UPOADTOBLOB_CURL_VERBOSITY_OFF : UPOADTOBLOB_CURL_VERBOSITY_ON;
+            result = IOTHUB_CLIENT_OK;
+        }
+        else if (strcmp(optionName, OPTION_BLOB_UPLOAD_TIMEOUT_SECS) == 0)
+        {
+            upload_data->blob_upload_timeout_secs = *(size_t*)value;
+            result = IOTHUB_CLIENT_OK;
+        }
+        else
+        {
+            /*Codes_SRS_IOTHUBCLIENT_LL_02_102: [ If an unknown option is presented then IoTHubClient_LL_UploadToBlob_SetOption shall return IOTHUB_CLIENT_INVALID_ARG. ]*/
+            result = IOTHUB_CLIENT_INVALID_ARG;
+        }
+    }
+    return result;
+}
+
+#endif /*DONT_USE_UPLOADTOBLOB*/
+
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_client_retry_control.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_client_retry_control.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_client_retry_control.c	(revision 453)
@@ -0,0 +1,544 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include "internal/iothub_client_retry_control.h"
+
+#include <math.h>
+
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/agenttime.h"
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/xlogging.h"
+
+#define RESULT_OK                 0
+#define INDEFINITE_TIME           ((time_t)-1)
+#define DEFAULT_MAX_DELAY_IN_SECS 30
+
+typedef struct RETRY_CONTROL_INSTANCE_TAG
+{
+    IOTHUB_CLIENT_RETRY_POLICY policy;
+    unsigned int max_retry_time_in_secs;
+
+    unsigned int initial_wait_time_in_secs;
+    unsigned int max_jitter_percent;
+    unsigned int max_delay_in_secs;
+
+    unsigned int retry_count;
+    time_t first_retry_time;
+    time_t last_retry_time;
+    unsigned int current_wait_time_in_secs;
+} RETRY_CONTROL_INSTANCE;
+
+typedef int (*RETRY_ACTION_EVALUATION_FUNCTION)(RETRY_CONTROL_INSTANCE* retry_state, RETRY_ACTION* retry_action);
+
+
+// ========== Helper Functions ========== //
+
+// ---------- Set/Retrieve Options Helpers ----------//
+
+static void* retry_control_clone_option(const char* name, const void* value)
+{
+    void* result;
+
+    if ((name == NULL) || (value == NULL))
+    {
+        LogError("Failed to clone option (either name (%p) or value (%p) are NULL)", name, value);
+        result = NULL;
+    }
+    else if (strcmp(RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS, name) == 0 ||
+            strcmp(RETRY_CONTROL_OPTION_MAX_JITTER_PERCENT, name) == 0)
+    {
+        unsigned int* cloned_value;
+
+        if ((cloned_value = (unsigned int*)malloc(sizeof(unsigned int))) == NULL)
+        {
+            LogError("Failed to clone option '%p' (malloc failed)", name);
+            result = NULL;
+        }
+        else
+        {
+            *cloned_value = *(unsigned int*)value;
+
+            result = (void*)cloned_value;
+        }
+    }
+    else
+    {
+        LogError("Failed to clone option (option with name '%s' is not suppported)", name);
+        result = NULL;
+    }
+
+    return result;
+}
+
+static void retry_control_destroy_option(const char* name, const void* value)
+{
+    if ((name == NULL) || (value == NULL))
+    {
+        LogError("Failed to destroy option (either name (%p) or value (%p) are NULL)", name, value);
+    }
+    else if (strcmp(RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS, name) == 0 ||
+        strcmp(RETRY_CONTROL_OPTION_MAX_JITTER_PERCENT, name) == 0)
+    {
+        free((void*)value);
+    }
+    else
+    {
+        LogError("Failed to destroy option (option with name '%s' is not suppported)", name);
+    }
+}
+
+// ========== _should_retry() Auxiliary Functions ========== //
+
+static int evaluate_retry_action(RETRY_CONTROL_INSTANCE* retry_control, RETRY_ACTION* retry_action)
+{
+    int result;
+
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_019: [If `retry_control->retry_count` is 0, `retry_action` shall be set to RETRY_ACTION_RETRY_NOW]
+    if (retry_control->retry_count == 0)
+    {
+        *retry_action = RETRY_ACTION_RETRY_NOW;
+        result = RESULT_OK;
+    }
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_020: [If `retry_control->last_retry_time` is INDEFINITE_TIME and policy is not IOTHUB_CLIENT_RETRY_IMMEDIATE, the evaluation function shall return non-zero]
+    else if (retry_control->last_retry_time == INDEFINITE_TIME &&
+             retry_control->policy != IOTHUB_CLIENT_RETRY_IMMEDIATE)
+    {
+        LogError("Failed to evaluate retry action (last_retry_time is INDEFINITE_TIME)");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        time_t current_time;
+
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_021: [`current_time` shall be set using get_time()]
+        if ((current_time = get_time(NULL)) == INDEFINITE_TIME)
+        {
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_022: [If get_time() fails, the evaluation function shall return non-zero]
+            LogError("Failed to evaluate retry action (get_time() failed)");
+            result = MU_FAILURE;
+        }
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_023: [If `retry_control->max_retry_time_in_secs` is not 0 and (`current_time` - `retry_control->first_retry_time`) is greater than or equal to `retry_control->max_retry_time_in_secs`, `retry_action` shall be set to RETRY_ACTION_STOP_RETRYING]
+        else if (retry_control->max_retry_time_in_secs > 0 &&
+            get_difftime(current_time, retry_control->first_retry_time) >= retry_control->max_retry_time_in_secs)
+        {
+            *retry_action = RETRY_ACTION_STOP_RETRYING;
+
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_026: [If no errors occur, the evaluation function shall return 0]
+            result = RESULT_OK;
+        }
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_028: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_IMMEDIATE, retry_action shall be set to RETRY_ACTION_RETRY_NOW]
+        else if (retry_control->policy == IOTHUB_CLIENT_RETRY_IMMEDIATE)
+        {
+            *retry_action = RETRY_ACTION_RETRY_NOW;
+
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_026: [If no errors occur, the evaluation function shall return 0]
+            result = RESULT_OK;
+        }
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_024: [Otherwise, if (`current_time` - `retry_control->last_retry_time`) is less than `retry_control->current_wait_time_in_secs`, `retry_action` shall be set to RETRY_ACTION_RETRY_LATER]
+        else if (get_difftime(current_time, retry_control->last_retry_time) < retry_control->current_wait_time_in_secs)
+        {
+            *retry_action = RETRY_ACTION_RETRY_LATER;
+
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_026: [If no errors occur, the evaluation function shall return 0]
+            result = RESULT_OK;
+        }
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_025: [Otherwise, if (`current_time` - `retry_control->last_retry_time`) is greater or equal to `retry_control->current_wait_time_in_secs`, `retry_action` shall be set to RETRY_ACTION_RETRY_NOW]
+        else
+        {
+            *retry_action = RETRY_ACTION_RETRY_NOW;
+
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_026: [If no errors occur, the evaluation function shall return 0]
+            result = RESULT_OK;
+        }
+    }
+
+    return result;
+}
+
+static unsigned int calculate_next_wait_time(RETRY_CONTROL_INSTANCE* retry_control)
+{
+    unsigned int result;
+
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_029: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_INTERVAL, `calculate_next_wait_time` shall return `retry_control->initial_wait_time_in_secs`]
+    if (retry_control->policy == IOTHUB_CLIENT_RETRY_INTERVAL)
+    {
+        result = retry_control->initial_wait_time_in_secs;
+    }
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_030: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_LINEAR_BACKOFF, `calculate_next_wait_time` shall return (`retry_control->initial_wait_time_in_secs` * (`retry_control->retry_count`))]
+    else if (retry_control->policy == IOTHUB_CLIENT_RETRY_LINEAR_BACKOFF)
+    {
+        unsigned int base_delay = retry_control->initial_wait_time_in_secs * (retry_control->retry_count);
+
+        if (base_delay > retry_control->max_delay_in_secs) 
+        {
+            base_delay = retry_control->max_delay_in_secs;
+        }        
+        
+        result = base_delay;
+    }
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_031: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF, `calculate_next_wait_time` shall return (pow(2, `retry_control->retry_count` - 1) * `retry_control->initial_wait_time_in_secs`)]
+    else if (retry_control->policy == IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF)
+    {
+        double base_delay = pow(2, retry_control->retry_count - 1) * retry_control->initial_wait_time_in_secs;
+
+        if (base_delay > retry_control->max_delay_in_secs) 
+        {
+            base_delay = retry_control->max_delay_in_secs;
+        }
+
+        result = (unsigned int)base_delay;
+    }
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_032: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF_WITH_JITTER, `calculate_next_wait_time` shall return ((pow(2, `retry_control->retry_count` - 1) * `retry_control->initial_wait_time_in_secs`) * (1 + (`retry_control->max_jitter_percent` / 100) * (rand() / RAND_MAX)))]
+    else if (retry_control->policy == IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF_WITH_JITTER)
+    {
+        double jitter_percent = (retry_control->max_jitter_percent / 100.0) * (rand() / ((double)RAND_MAX));
+
+        double base_delay = pow(2, retry_control->retry_count - 1) * retry_control->initial_wait_time_in_secs;
+
+        if (base_delay > retry_control->max_delay_in_secs) 
+        {
+            base_delay = retry_control->max_delay_in_secs;
+        }
+
+        result =  (unsigned int)(base_delay * (1 + jitter_percent));
+    }
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_033: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_RANDOM, `calculate_next_wait_time` shall return (`retry_control->initial_wait_time_in_secs` * (rand() / RAND_MAX))]
+    else if (retry_control->policy == IOTHUB_CLIENT_RETRY_RANDOM)
+    {
+        double random_percent = ((double)rand() / (double)RAND_MAX);
+        result = (unsigned int)(retry_control->initial_wait_time_in_secs * random_percent);
+    }
+    else
+    {
+        LogError("Failed to calculate the next wait time (policy %d is not expected)", retry_control->policy);
+
+        result = 0;
+    }
+
+    return result;
+}
+
+
+// ========== Public API ========== //
+
+int is_timeout_reached(time_t start_time, unsigned int timeout_in_secs, bool* is_timed_out)
+{
+    int result;
+
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_057: [If `start_time` is INDEFINITE_TIME, `is_timeout_reached` shall fail and return non-zero]
+    if (start_time == INDEFINITE_TIME)
+    {
+        LogError("Failed to verify timeout (start_time is INDEFINITE)");
+        result = MU_FAILURE;
+    }
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_058: [If `is_timed_out` is NULL, `is_timeout_reached` shall fail and return non-zero]
+    else if (is_timed_out == NULL)
+    {
+        LogError("Failed to verify timeout (is_timed_out is NULL)");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        time_t current_time;
+
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_059: [`is_timeout_reached` shall obtain the `current_time` using get_time()]
+        if ((current_time = get_time(NULL)) == INDEFINITE_TIME)
+        {
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_060: [If get_time() fails, `is_timeout_reached` shall fail and return non-zero]
+            LogError("Failed to verify timeout (get_time failed)");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_061: [If (`current_time` - `start_time`) is greater or equal to `timeout_in_secs`, `is_timed_out` shall be set to true]
+            if (get_difftime(current_time, start_time) >= timeout_in_secs)
+            {
+                *is_timed_out = true;
+            }
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_062: [If (`current_time` - `start_time`) is less than `timeout_in_secs`, `is_timed_out` shall be set to false]
+            else
+            {
+                *is_timed_out = false;
+            }
+
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_063: [If no errors occur, `is_timeout_reached` shall return 0]
+            result = RESULT_OK;
+        }
+    }
+
+    return result;
+}
+
+void retry_control_reset(RETRY_CONTROL_HANDLE retry_control_handle)
+{
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_034: [If `retry_control_handle` is NULL, `retry_control_reset` shall return]
+    if (retry_control_handle == NULL)
+    {
+        LogError("Failed to reset the retry control (retry_state_handle is NULL)");
+    }
+    else
+    {
+        RETRY_CONTROL_INSTANCE* retry_control = (RETRY_CONTROL_INSTANCE*)retry_control_handle;
+
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_035: [`retry_control` shall have fields `retry_count` and `current_wait_time_in_secs` set to 0 (zero), `first_retry_time` and `last_retry_time` set to INDEFINITE_TIME]
+        retry_control->retry_count = 0;
+        retry_control->current_wait_time_in_secs = 0;
+        retry_control->first_retry_time = INDEFINITE_TIME;
+        retry_control->last_retry_time = INDEFINITE_TIME;
+    }
+}
+
+RETRY_CONTROL_HANDLE retry_control_create(IOTHUB_CLIENT_RETRY_POLICY policy, unsigned int max_retry_time_in_secs)
+{
+    RETRY_CONTROL_INSTANCE* retry_control;
+
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_002: [`retry_control_create` shall allocate memory for the retry control instance structure (a.k.a. `retry_control`)]
+    if ((retry_control = (RETRY_CONTROL_INSTANCE*)malloc(sizeof(RETRY_CONTROL_INSTANCE))) == NULL)
+    {
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_003: [If malloc fails, `retry_control_create` shall fail and return NULL]
+        LogError("Failed creating the retry control (malloc failed)");
+    }
+    else
+    {
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_004: [The parameters passed to `retry_control_create` shall be saved into `retry_control`]
+        memset(retry_control, 0, sizeof(RETRY_CONTROL_INSTANCE));
+        retry_control->policy = policy;
+        retry_control->max_retry_time_in_secs = max_retry_time_in_secs;
+
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_005: [If `policy` is IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF or IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF_WITH_JITTER, `retry_control->initial_wait_time_in_secs` shall be set to 1]
+        if (retry_control->policy == IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF ||
+            retry_control->policy == IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF_WITH_JITTER)
+        {
+            retry_control->initial_wait_time_in_secs = 1;
+        }
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_006: [Otherwise `retry_control->initial_wait_time_in_secs` shall be set to 5]
+        else
+        {
+            retry_control->initial_wait_time_in_secs = 5;
+        }
+
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_007: [`retry_control->max_jitter_percent` shall be set to 5]
+        retry_control->max_jitter_percent = 5;
+        retry_control->max_delay_in_secs = DEFAULT_MAX_DELAY_IN_SECS;
+
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_008: [The remaining fields in `retry_control` shall be initialized according to retry_control_reset()]
+        retry_control_reset(retry_control);
+    }
+
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_009: [If no errors occur, `retry_control_create` shall return a handle to `retry_control`]
+    return (RETRY_CONTROL_HANDLE)retry_control;
+}
+
+void retry_control_destroy(RETRY_CONTROL_HANDLE retry_control_handle)
+{
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_055: [If `retry_control_handle` is NULL, `retry_control_destroy` shall return]
+    if (retry_control_handle == NULL)
+    {
+        LogError("Failed to destroy the retry control (retry_control_handle is NULL)");
+    }
+    else
+    {
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_056: [`retry_control_destroy` shall destroy `retry_control_handle` using free()]
+        free(retry_control_handle);
+    }
+}
+
+int retry_control_should_retry(RETRY_CONTROL_HANDLE retry_control_handle, RETRY_ACTION* retry_action)
+{
+    int result;
+
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_010: [If `retry_control_handle` or `retry_action` are NULL, `retry_control_should_retry` shall fail and return non-zero]
+    if ((retry_control_handle == NULL) || (retry_action == NULL))
+    {
+        LogError("Failed to evaluate if retry should be attempted (either retry_control_handle (%p) or retry_action (%p) are NULL)", retry_control_handle, retry_action);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        RETRY_CONTROL_INSTANCE* retry_control = (RETRY_CONTROL_INSTANCE*)retry_control_handle;
+
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_027: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_NONE, retry_action shall be set to RETRY_ACTION_STOP_RETRYING and return immediatelly with result 0]
+        if (retry_control->policy == IOTHUB_CLIENT_RETRY_NONE)
+        {
+            *retry_action = RETRY_ACTION_STOP_RETRYING;
+            result = RESULT_OK;
+        }
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_011: [If `retry_control->first_retry_time` is INDEFINITE_TIME, it shall be set using get_time()]
+        else if (retry_control->first_retry_time == INDEFINITE_TIME && (retry_control->first_retry_time = get_time(NULL)) == INDEFINITE_TIME)
+        {
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_012: [If get_time() fails, `retry_control_should_retry` shall fail and return non-zero]
+            LogError("Failed to evaluate if retry should be attempted (get_time() failed)");
+            result = MU_FAILURE;
+        }
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_013: [evaluate_retry_action() shall be invoked]
+        else if (evaluate_retry_action(retry_control, retry_action) != RESULT_OK)
+        {
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_014: [If evaluate_retry_action() fails, `retry_control_should_retry` shall fail and return non-zero]
+            LogError("Failed to evaluate if retry should be attempted (evaluate_retry_action() failed)");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if (*retry_action == RETRY_ACTION_RETRY_NOW)
+            {
+                // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_015: [If `retry_action` is set to RETRY_ACTION_RETRY_NOW, `retry_control->retry_count` shall be incremented by 1]
+                retry_control->retry_count++;
+
+                if (retry_control->policy != IOTHUB_CLIENT_RETRY_IMMEDIATE)
+                {
+                    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_016: [If `retry_action` is set to RETRY_ACTION_RETRY_NOW and policy is not IOTHUB_CLIENT_RETRY_IMMEDIATE, `retry_control->last_retry_time` shall be set using get_time()]
+                    retry_control->last_retry_time = get_time(NULL);
+
+                    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_017: [If `retry_action` is set to RETRY_ACTION_RETRY_NOW and policy is not IOTHUB_CLIENT_RETRY_IMMEDIATE, `retry_control->current_wait_time_in_secs` shall be set using calculate_next_wait_time()]
+                    retry_control->current_wait_time_in_secs = calculate_next_wait_time(retry_control);
+                }
+            }
+
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_018: [If no errors occur, `retry_control_should_retry` shall return 0]
+            result = RESULT_OK;
+        }
+    }
+
+    return result;
+}
+
+int retry_control_set_option(RETRY_CONTROL_HANDLE retry_control_handle, const char* name, const void* value)
+{
+    int result;
+
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_036: [If `retry_control_handle`, `name` or `value` are NULL, `retry_control_set_option` shall fail and return non-zero]
+    if (retry_control_handle == NULL || name == NULL || value == NULL)
+    {
+        LogError("Failed to set option (either retry_state_handle (%p), name (%p) or value (%p) are NULL)", retry_control_handle, name, value);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        RETRY_CONTROL_INSTANCE* retry_control = (RETRY_CONTROL_INSTANCE*)retry_control_handle;
+
+        if (strcmp(RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS, name) == 0)
+        {
+            unsigned int cast_value = *((unsigned int*)value);
+
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_037: [If `name` is "initial_wait_time_in_secs" and `value` is less than 1, `retry_control_set_option` shall fail and return non-zero]
+            if (cast_value < 1)
+            {
+                LogError("Failed to set option '%s' (value must be equal or greater to 1)", name);
+                result = MU_FAILURE;
+            }
+            else
+            {
+                // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_038: [If `name` is "initial_wait_time_in_secs", `value` shall be saved on `retry_control->initial_wait_time_in_secs`]
+                retry_control->initial_wait_time_in_secs = cast_value;
+
+                // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_044: [If no errors occur, retry_control_set_option shall return 0]
+                result = RESULT_OK;
+            }
+        }
+        else if (strcmp(RETRY_CONTROL_OPTION_MAX_JITTER_PERCENT, name) == 0)
+        {
+            unsigned int cast_value = *((unsigned int*)value);
+
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_039: [If `name` is "max_jitter_percent" and `value` is less than 0 or greater than 100, `retry_control_set_option` shall fail and return non-zero]
+            if (cast_value > 100) // it's unsigned int, it doesn't need to be checked for less than zero.
+            {
+                LogError("Failed to set option '%s' (value must be in the range 0 to 100)", name);
+                result = MU_FAILURE;
+            }
+            else
+            {
+                // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_040: [If `name` is "max_jitter_percent", value shall be saved on `retry_control->max_jitter_percent`]
+                retry_control->max_jitter_percent = cast_value;
+
+                // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_044: [If no errors occur, retry_control_set_option shall return 0]
+                result = RESULT_OK;
+            }
+        }
+        else if (strcmp(RETRY_CONTROL_OPTION_MAX_DELAY_IN_SECS, name) == 0)
+        {
+            retry_control->max_delay_in_secs = *((unsigned int*)value);
+
+            result = RESULT_OK;
+        }
+        else if (strcmp(RETRY_CONTROL_OPTION_SAVED_OPTIONS, name) == 0)
+        {
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_041: [If `name` is "retry_control_options", value shall be fed to `retry_control` using OptionHandler_FeedOptions]
+            if (OptionHandler_FeedOptions((OPTIONHANDLER_HANDLE)value, retry_control_handle) != OPTIONHANDLER_OK)
+            {
+                // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_042: [If OptionHandler_FeedOptions fails, `retry_control_set_option` shall fail and return non-zero]
+                LogError("messenger_set_option failed (OptionHandler_FeedOptions failed)");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_044: [If no errors occur, `retry_control_set_option` shall return 0]
+                result = RESULT_OK;
+            }
+        }
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_043: [If `name` is not a supported option, `retry_control_set_option` shall fail and return non-zero]
+        else
+        {
+            LogError("messenger_set_option failed (option with name '%s' is not suppported)", name);
+            result = MU_FAILURE;
+        }
+    }
+
+    return result;
+}
+
+OPTIONHANDLER_HANDLE retry_control_retrieve_options(RETRY_CONTROL_HANDLE retry_control_handle)
+{
+    OPTIONHANDLER_HANDLE result;
+
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_045: [If `retry_control_handle`, `retry_control_retrieve_options` shall fail and return NULL]
+    if (retry_control_handle == NULL)
+    {
+        LogError("Failed to retrieve options (retry_state_handle is NULL)");
+        result = NULL;
+    }
+    else
+    {
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_046: [An instance of OPTIONHANDLER_HANDLE (a.k.a. `options`) shall be created using OptionHandler_Create]
+        OPTIONHANDLER_HANDLE options = OptionHandler_Create(retry_control_clone_option, retry_control_destroy_option, (pfSetOption)retry_control_set_option);
+
+        if (options == NULL)
+        {
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_047: [If OptionHandler_Create fails, `retry_control_retrieve_options` shall fail and return NULL]
+            LogError("Failed to retrieve options (OptionHandler_Create failed)");
+            result = NULL;
+        }
+        else
+        {
+            RETRY_CONTROL_INSTANCE* retry_control = (RETRY_CONTROL_INSTANCE*)retry_control_handle;
+
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_050: [`retry_control->initial_wait_time_in_secs` shall be added to `options` using OptionHandler_Add]
+            if (OptionHandler_AddOption(options, RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS, (void*)&retry_control->initial_wait_time_in_secs) != OPTIONHANDLER_OK)
+            {
+                // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_052: [If any call to OptionHandler_Add fails, `retry_control_retrieve_options` shall fail and return NULL]
+                LogError("Failed to retrieve options (OptionHandler_Create failed for option '%s')", RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS);
+                result = NULL;
+            }
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_051: [`retry_control->max_jitter_percent` shall be added to `options` using OptionHandler_Add]
+            else if (OptionHandler_AddOption(options, RETRY_CONTROL_OPTION_MAX_JITTER_PERCENT, (void*)&retry_control->max_jitter_percent) != OPTIONHANDLER_OK)
+            {
+                // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_052: [If any call to OptionHandler_Add fails, `retry_control_retrieve_options` shall fail and return NULL]
+                LogError("Failed to retrieve options (OptionHandler_Create failed for option '%s')", RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS);
+                result = NULL;
+            }
+            else
+            {
+                // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_054: [If no errors occur, `retry_control_retrieve_options` shall return the OPTIONHANDLER_HANDLE instance]
+                result = options;
+            }
+
+            if (result == NULL)
+            {
+                // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_053: [If any failures occur, `retry_control_retrieve_options` shall release any memory it has allocated]
+                OptionHandler_Destroy(options);
+            }
+        }
+    }
+
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_device_client_ll.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_device_client_ll.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_device_client_ll.c	(revision 453)
@@ -0,0 +1,135 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <string.h>
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/string_tokenizer.h"
+#include "azure_c_shared_utility/doublylinkedlist.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/tickcounter.h"
+#include "azure_c_shared_utility/constbuffer.h"
+#include "azure_c_shared_utility/platform.h"
+
+#include "iothub_client_core_ll.h"
+#include "internal/iothub_client_authorization.h"
+#include "iothub_device_client_ll.h"
+#include "iothub_transport_ll.h"
+#include "internal/iothub_client_private.h"
+#include "iothub_client_options.h"
+#include "iothub_client_version.h"
+#include "internal/iothub_client_diagnostic.h"
+#include <stdint.h>
+
+#ifndef DONT_USE_UPLOADTOBLOB
+#include "internal/iothub_client_ll_uploadtoblob.h"
+#endif
+
+IOTHUB_DEVICE_CLIENT_LL_HANDLE IoTHubDeviceClient_LL_CreateFromConnectionString(const char* connectionString, IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol)
+{
+    return (IOTHUB_DEVICE_CLIENT_LL_HANDLE)IoTHubClientCore_LL_CreateFromConnectionString(connectionString, protocol);
+}
+
+IOTHUB_DEVICE_CLIENT_LL_HANDLE IoTHubDeviceClient_LL_Create(const IOTHUB_CLIENT_CONFIG* config)
+{
+    return (IOTHUB_DEVICE_CLIENT_LL_HANDLE)IoTHubClientCore_LL_Create(config);
+}
+
+IOTHUB_DEVICE_CLIENT_LL_HANDLE IoTHubDeviceClient_LL_CreateWithTransport(const IOTHUB_CLIENT_DEVICE_CONFIG * config)
+{
+    return (IOTHUB_DEVICE_CLIENT_LL_HANDLE)IoTHubClientCore_LL_CreateWithTransport(config);
+}
+
+IOTHUB_DEVICE_CLIENT_LL_HANDLE IoTHubDeviceClient_LL_CreateFromDeviceAuth(const char* iothub_uri, const char* device_id, IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol)
+{
+    return (IOTHUB_DEVICE_CLIENT_LL_HANDLE)IoTHubClientCore_LL_CreateFromDeviceAuth(iothub_uri, device_id, protocol);
+}
+
+void IoTHubDeviceClient_LL_Destroy(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle)
+{
+    IoTHubClientCore_LL_Destroy((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_SendEventAsync(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, IOTHUB_MESSAGE_HANDLE eventMessageHandle, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK eventConfirmationCallback, void* userContextCallback)
+{
+    return IoTHubClientCore_LL_SendEventAsync((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, eventMessageHandle, eventConfirmationCallback, userContextCallback);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_GetSendStatus(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_STATUS *iotHubClientStatus)
+{
+    return IoTHubClientCore_LL_GetSendStatus((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, iotHubClientStatus);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_SetMessageCallback(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC messageCallback, void* userContextCallback)
+{
+    return IoTHubClientCore_LL_SetMessageCallback((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, messageCallback, userContextCallback);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_SetConnectionStatusCallback(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_CONNECTION_STATUS_CALLBACK connectionStatusCallback, void * userContextCallback)
+{
+    return IoTHubClientCore_LL_SetConnectionStatusCallback((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, connectionStatusCallback, userContextCallback);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_SetRetryPolicy(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY retryPolicy, size_t retryTimeoutLimitInSeconds)
+{
+    return IoTHubClientCore_LL_SetRetryPolicy((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, retryPolicy, retryTimeoutLimitInSeconds);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_GetRetryPolicy(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY* retryPolicy, size_t* retryTimeoutLimitInSeconds)
+{
+    return IoTHubClientCore_LL_GetRetryPolicy((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, retryPolicy, retryTimeoutLimitInSeconds);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_GetLastMessageReceiveTime(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, time_t* lastMessageReceiveTime)
+{
+    return IoTHubClientCore_LL_GetLastMessageReceiveTime((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, lastMessageReceiveTime);
+}
+
+void IoTHubDeviceClient_LL_DoWork(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle)
+{
+    IoTHubClientCore_LL_DoWork((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_SetOption(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, const char* optionName, const void* value)
+{
+    return IoTHubClientCore_LL_SetOption((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, optionName, value);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_SetDeviceTwinCallback(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK deviceTwinCallback, void* userContextCallback)
+{
+    return IoTHubClientCore_LL_SetDeviceTwinCallback((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, deviceTwinCallback, userContextCallback);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_GetTwinAsync(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK deviceTwinCallback, void* userContextCallback)
+{
+    return IoTHubClientCore_LL_GetTwinAsync((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, deviceTwinCallback, userContextCallback);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_SendReportedState(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, const unsigned char* reportedState, size_t size, IOTHUB_CLIENT_REPORTED_STATE_CALLBACK reportedStateCallback, void* userContextCallback)
+{
+    return IoTHubClientCore_LL_SendReportedState((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, reportedState, size, reportedStateCallback, userContextCallback);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_SetDeviceMethodCallback(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_DEVICE_METHOD_CALLBACK_ASYNC deviceMethodCallback, void* userContextCallback)
+{
+    return IoTHubClientCore_LL_SetDeviceMethodCallback((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, deviceMethodCallback, userContextCallback);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_DeviceMethodResponse(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, METHOD_HANDLE methodId, const unsigned char* response, size_t response_size, int status_response)
+{
+    return IoTHubClientCore_LL_DeviceMethodResponse((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, methodId, response, response_size, status_response);
+}
+
+#ifndef DONT_USE_UPLOADTOBLOB
+IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_UploadToBlob(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, const char* destinationFileName, const unsigned char* source, size_t size)
+{
+    return IoTHubClientCore_LL_UploadToBlob((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, destinationFileName, source, size);
+}
+
+IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, const char* destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx, void* context)
+{
+    return IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, destinationFileName, getDataCallbackEx, context);
+}
+
+#endif
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_message.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_message.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_message.c	(revision 453)
@@ -0,0 +1,1081 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/buffer_.h"
+
+#include "iothub_message.h"
+
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(IOTHUB_MESSAGE_RESULT, IOTHUB_MESSAGE_RESULT_VALUES);
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(IOTHUBMESSAGE_CONTENT_TYPE, IOTHUBMESSAGE_CONTENT_TYPE_VALUES);
+
+static const char* SECURITY_CLIENT_JSON_ENCODING = "application/json";
+
+typedef struct IOTHUB_MESSAGE_HANDLE_DATA_TAG
+{
+    IOTHUBMESSAGE_CONTENT_TYPE contentType;
+    union
+    {
+        BUFFER_HANDLE byteArray;
+        STRING_HANDLE string;
+    } value;
+    MAP_HANDLE properties;
+    char* messageId;
+    char* correlationId;
+    char* userDefinedContentType;
+    char* contentEncoding;
+    char* outputName;
+    char* inputName;
+    char* connectionModuleId;
+    char* connectionDeviceId;
+    IOTHUB_MESSAGE_DIAGNOSTIC_PROPERTY_DATA_HANDLE diagnosticData;
+    bool is_security_message;
+}IOTHUB_MESSAGE_HANDLE_DATA;
+
+static bool ContainsOnlyUsAscii(const char* asciiValue)
+{
+    bool result = true;
+    const char* iterator = asciiValue;
+    while (iterator != NULL && *iterator != '\0')
+    {
+        // Allow only printable ascii char
+        if (*iterator < ' ' || *iterator > '~')
+        {
+            result = false;
+            break;
+        }
+        iterator++;
+    }
+    return result;
+}
+
+/* Codes_SRS_IOTHUBMESSAGE_07_008: [ValidateAsciiCharactersFilter shall loop through the mapKey and mapValue strings to ensure that they only contain valid US-Ascii characters Ascii value 32 - 126.] */
+static int ValidateAsciiCharactersFilter(const char* mapKey, const char* mapValue)
+{
+    int result;
+    if (!ContainsOnlyUsAscii(mapKey) || !ContainsOnlyUsAscii(mapValue))
+    {
+        result = MU_FAILURE;
+    }
+    else
+    {
+        result = 0;
+    }
+    return result;
+}
+
+static void DestroyDiagnosticPropertyData(IOTHUB_MESSAGE_DIAGNOSTIC_PROPERTY_DATA_HANDLE diagnosticHandle)
+{
+    if (diagnosticHandle != NULL)
+    {
+        free(diagnosticHandle->diagnosticId);
+        free(diagnosticHandle->diagnosticCreationTimeUtc);
+    }
+    free(diagnosticHandle);
+}
+
+static void DestroyMessageData(IOTHUB_MESSAGE_HANDLE_DATA* handleData)
+{
+    if (handleData->contentType == IOTHUBMESSAGE_BYTEARRAY)
+    {
+        BUFFER_delete(handleData->value.byteArray);
+    }
+    else if (handleData->contentType == IOTHUBMESSAGE_STRING)
+    {
+        STRING_delete(handleData->value.string);
+    }
+
+    Map_Destroy(handleData->properties);
+    free(handleData->messageId);
+    handleData->messageId = NULL;
+    free(handleData->correlationId);
+    handleData->correlationId = NULL;
+    free(handleData->userDefinedContentType);
+    free(handleData->contentEncoding);
+    DestroyDiagnosticPropertyData(handleData->diagnosticData);
+    free(handleData->outputName);
+    free(handleData->inputName);
+    free(handleData->connectionModuleId);
+    free(handleData->connectionDeviceId);
+    free(handleData);
+}
+
+static int set_content_encoding(IOTHUB_MESSAGE_HANDLE_DATA* handleData, const char* encoding)
+{
+    int result;
+    char* tmp_encoding;
+
+    if (mallocAndStrcpy_s(&tmp_encoding, encoding) != 0)
+    {
+        LogError("Failed saving a copy of contentEncoding");
+        // Codes_SRS_IOTHUBMESSAGE_09_008: [If the allocation or the copying of `contentEncoding` fails, then IoTHubMessage_SetContentEncodingSystemProperty shall return IOTHUB_MESSAGE_ERROR.]
+        result = MU_FAILURE;
+    }
+    else
+    {
+        // Codes_SRS_IOTHUBMESSAGE_09_007: [If the IOTHUB_MESSAGE_HANDLE `contentEncoding` is not NULL it shall be deallocated.]
+        if (handleData->contentEncoding != NULL)
+        {
+            free(handleData->contentEncoding);
+        }
+        handleData->contentEncoding = tmp_encoding;
+        result = 0;
+    }
+    return result;
+}
+
+static IOTHUB_MESSAGE_DIAGNOSTIC_PROPERTY_DATA_HANDLE CloneDiagnosticPropertyData(const IOTHUB_MESSAGE_DIAGNOSTIC_PROPERTY_DATA* source)
+{
+    IOTHUB_MESSAGE_DIAGNOSTIC_PROPERTY_DATA_HANDLE result = NULL;
+    if (source == NULL)
+    {
+        LogError("Invalid argument - source is NULL");
+    }
+    else
+    {
+        result = (IOTHUB_MESSAGE_DIAGNOSTIC_PROPERTY_DATA_HANDLE)malloc(sizeof(IOTHUB_MESSAGE_DIAGNOSTIC_PROPERTY_DATA));
+        if (result == NULL)
+        {
+            LogError("malloc failed");
+        }
+        else
+        {
+            result->diagnosticCreationTimeUtc = NULL;
+            result->diagnosticId = NULL;
+            if (source->diagnosticCreationTimeUtc != NULL && mallocAndStrcpy_s(&result->diagnosticCreationTimeUtc, source->diagnosticCreationTimeUtc) != 0)
+            {
+                LogError("mallocAndStrcpy_s for diagnosticCreationTimeUtc failed");
+                free(result);
+                result = NULL;
+            }
+            else if (source->diagnosticId != NULL && mallocAndStrcpy_s(&result->diagnosticId, source->diagnosticId) != 0)
+            {
+                LogError("mallocAndStrcpy_s for diagnosticId failed");
+                free(result->diagnosticCreationTimeUtc);
+                free(result);
+                result = NULL;
+            }
+        }
+    }
+    return result;
+}
+
+IOTHUB_MESSAGE_HANDLE IoTHubMessage_CreateFromByteArray(const unsigned char* byteArray, size_t size)
+{
+    IOTHUB_MESSAGE_HANDLE_DATA* result;
+    if ((byteArray == NULL) && (size != 0))
+    {
+        LogError("Invalid argument - byteArray is NULL");
+        result = NULL;
+    }
+    else
+    {
+        result = (IOTHUB_MESSAGE_HANDLE_DATA*)malloc(sizeof(IOTHUB_MESSAGE_HANDLE_DATA));
+        if (result == NULL)
+        {
+            LogError("unable to malloc");
+            /*Codes_SRS_IOTHUBMESSAGE_02_024: [If there are any errors then IoTHubMessage_CreateFromByteArray shall return NULL.] */
+            /*let it go through*/
+        }
+        else
+        {
+            const unsigned char* source;
+            unsigned char temp = 0x00;
+
+            memset(result, 0, sizeof(*result));
+            /*Codes_SRS_IOTHUBMESSAGE_02_026: [The type of the new message shall be IOTHUBMESSAGE_BYTEARRAY.] */
+            result->contentType = IOTHUBMESSAGE_BYTEARRAY;
+
+            if (size != 0)
+            {
+                /*Codes_SRS_IOTHUBMESSAGE_06_002: [If size is NOT zero then byteArray MUST NOT be NULL*/
+                if (byteArray == NULL)
+                {
+                    LogError("Attempted to create a Hub Message from a NULL pointer!");
+                    DestroyMessageData(result);
+                    result = NULL;
+                    source = NULL;
+                }
+                else
+                {
+                    source = byteArray;
+                }
+            }
+            else
+            {
+                /*Codes_SRS_IOTHUBMESSAGE_06_001: [If size is zero then byteArray may be NULL.]*/
+                source = &temp;
+            }
+            if (result != NULL)
+            {
+                /*Codes_SRS_IOTHUBMESSAGE_02_022: [IoTHubMessage_CreateFromByteArray shall call BUFFER_create passing byteArray and size as parameters.] */
+                if ((result->value.byteArray = BUFFER_create(source, size)) == NULL)
+                {
+                    LogError("BUFFER_create failed");
+                    /*Codes_SRS_IOTHUBMESSAGE_02_024: [If there are any errors then IoTHubMessage_CreateFromByteArray shall return NULL.] */
+                    DestroyMessageData(result);
+                    result = NULL;
+                }
+                /*Codes_SRS_IOTHUBMESSAGE_02_023: [IoTHubMessage_CreateFromByteArray shall call Map_Create to create the message properties.] */
+                else if ((result->properties = Map_Create(ValidateAsciiCharactersFilter)) == NULL)
+                {
+                    LogError("Map_Create for properties failed");
+                    /*Codes_SRS_IOTHUBMESSAGE_02_024: [If there are any errors then IoTHubMessage_CreateFromByteArray shall return NULL.] */
+                    DestroyMessageData(result);
+                    result = NULL;
+                }
+                /*Codes_SRS_IOTHUBMESSAGE_02_025: [Otherwise, IoTHubMessage_CreateFromByteArray shall return a non-NULL handle.] */
+            }
+        }
+    }
+    return result;
+}
+
+IOTHUB_MESSAGE_HANDLE IoTHubMessage_CreateFromString(const char* source)
+{
+    IOTHUB_MESSAGE_HANDLE_DATA* result;
+    if (source == NULL)
+    {
+        LogError("Invalid argument - source is NULL");
+        result = NULL;
+    }
+    else
+    {
+        result = (IOTHUB_MESSAGE_HANDLE_DATA*)malloc(sizeof(IOTHUB_MESSAGE_HANDLE_DATA));
+        if (result == NULL)
+        {
+            LogError("malloc failed");
+            /*Codes_SRS_IOTHUBMESSAGE_02_029: [If there are any encountered in the execution of IoTHubMessage_CreateFromString then IoTHubMessage_CreateFromString shall return NULL.] */
+            /*let it go through*/
+        }
+        else
+        {
+            memset(result, 0, sizeof(*result));
+            /*Codes_SRS_IOTHUBMESSAGE_02_032: [The type of the new message shall be IOTHUBMESSAGE_STRING.] */
+            result->contentType = IOTHUBMESSAGE_STRING;
+
+            /*Codes_SRS_IOTHUBMESSAGE_02_027: [IoTHubMessage_CreateFromString shall call STRING_construct passing source as parameter.] */
+            if ((result->value.string = STRING_construct(source)) == NULL)
+            {
+                LogError("STRING_construct failed");
+                /*Codes_SRS_IOTHUBMESSAGE_02_029: [If there are any encountered in the execution of IoTHubMessage_CreateFromString then IoTHubMessage_CreateFromString shall return NULL.] */
+                DestroyMessageData(result);
+                result = NULL;
+            }
+            /*Codes_SRS_IOTHUBMESSAGE_02_028: [IoTHubMessage_CreateFromString shall call Map_Create to create the message properties.] */
+            else if ((result->properties = Map_Create(ValidateAsciiCharactersFilter)) == NULL)
+            {
+                LogError("Map_Create for properties failed");
+                /*Codes_SRS_IOTHUBMESSAGE_02_029: [If there are any encountered in the execution of IoTHubMessage_CreateFromString then IoTHubMessage_CreateFromString shall return NULL.] */
+                DestroyMessageData(result);
+                result = NULL;
+            }
+            /*Codes_SRS_IOTHUBMESSAGE_02_031: [Otherwise, IoTHubMessage_CreateFromString shall return a non-NULL handle.] */
+        }
+    }
+    return result;
+}
+
+/*Codes_SRS_IOTHUBMESSAGE_03_001: [IoTHubMessage_Clone shall create a new IoT hub message with data content identical to that of the iotHubMessageHandle parameter.]*/
+IOTHUB_MESSAGE_HANDLE IoTHubMessage_Clone(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
+{
+    IOTHUB_MESSAGE_HANDLE_DATA* result;
+    const IOTHUB_MESSAGE_HANDLE_DATA* source = (const IOTHUB_MESSAGE_HANDLE_DATA*)iotHubMessageHandle;
+    /* Codes_SRS_IOTHUBMESSAGE_03_005: [IoTHubMessage_Clone shall return NULL if iotHubMessageHandle is NULL.] */
+    if (source == NULL)
+    {
+        result = NULL;
+        LogError("iotHubMessageHandle parameter cannot be NULL for IoTHubMessage_Clone");
+    }
+    else
+    {
+        result = (IOTHUB_MESSAGE_HANDLE_DATA*)malloc(sizeof(IOTHUB_MESSAGE_HANDLE_DATA));
+        /*Codes_SRS_IOTHUBMESSAGE_03_004: [IoTHubMessage_Clone shall return NULL if it fails for any reason.]*/
+        if (result == NULL)
+        {
+            /*Codes_SRS_IOTHUBMESSAGE_03_004: [IoTHubMessage_Clone shall return NULL if it fails for any reason.]*/
+            /*do nothing and return as is*/
+            LogError("unable to malloc");
+        }
+        else
+        {
+            memset(result, 0, sizeof(*result));
+            result->contentType = source->contentType;
+            result->is_security_message = source->is_security_message;
+
+            if (source->messageId != NULL && mallocAndStrcpy_s(&result->messageId, source->messageId) != 0)
+            {
+                LogError("unable to Copy messageId");
+                DestroyMessageData(result);
+                result = NULL;
+            }
+            else if (source->correlationId != NULL && mallocAndStrcpy_s(&result->correlationId, source->correlationId) != 0)
+            {
+                LogError("unable to Copy correlationId");
+                DestroyMessageData(result);
+                result = NULL;
+            }
+            else if (source->userDefinedContentType != NULL && mallocAndStrcpy_s(&result->userDefinedContentType, source->userDefinedContentType) != 0)
+            {
+                LogError("unable to copy contentType");
+                DestroyMessageData(result);
+                result = NULL;
+            }
+            else if (source->contentEncoding != NULL && mallocAndStrcpy_s(&result->contentEncoding, source->contentEncoding) != 0)
+            {
+                LogError("unable to copy contentEncoding");
+                DestroyMessageData(result);
+                result = NULL;
+            }
+            else if (source->diagnosticData != NULL && (result->diagnosticData = CloneDiagnosticPropertyData(source->diagnosticData)) == NULL)
+            {
+                LogError("unable to copy CloneDiagnosticPropertyData");
+                DestroyMessageData(result);
+                result = NULL;
+            }
+            else if (source->outputName != NULL && mallocAndStrcpy_s(&result->outputName, source->outputName) != 0)
+            {
+                LogError("unable to copy outputName");
+                DestroyMessageData(result);
+                result = NULL;
+            }
+            else if (source->inputName != NULL && mallocAndStrcpy_s(&result->inputName, source->inputName) != 0)
+            {
+                LogError("unable to copy inputName");
+                DestroyMessageData(result);
+                result = NULL;
+            }
+            else if (source->connectionModuleId != NULL && mallocAndStrcpy_s(&result->connectionModuleId, source->connectionModuleId) != 0)
+            {
+                LogError("unable to copy inputName");
+                DestroyMessageData(result);
+                result = NULL;
+            }
+            else if (source->connectionDeviceId != NULL && mallocAndStrcpy_s(&result->connectionDeviceId, source->connectionDeviceId) != 0)
+            {
+                LogError("unable to copy inputName");
+                DestroyMessageData(result);
+                result = NULL;
+            }
+            else if (source->contentType == IOTHUBMESSAGE_BYTEARRAY)
+            {
+                /*Codes_SRS_IOTHUBMESSAGE_02_006: [IoTHubMessage_Clone shall clone to content by a call to BUFFER_clone] */
+                if ((result->value.byteArray = BUFFER_clone(source->value.byteArray)) == NULL)
+                {
+                    /*Codes_SRS_IOTHUBMESSAGE_03_004: [IoTHubMessage_Clone shall return NULL if it fails for any reason.]*/
+                    LogError("unable to BUFFER_clone");
+                    DestroyMessageData(result);
+                    result = NULL;
+                }
+                /*Codes_SRS_IOTHUBMESSAGE_02_005: [IoTHubMessage_Clone shall clone the properties map by using Map_Clone.] */
+                else if ((result->properties = Map_Clone(source->properties)) == NULL)
+                {
+                    /*Codes_SRS_IOTHUBMESSAGE_03_004: [IoTHubMessage_Clone shall return NULL if it fails for any reason.]*/
+                    LogError("unable to Map_Clone");
+                    DestroyMessageData(result);
+                    result = NULL;
+                }
+                /*Codes_SRS_IOTHUBMESSAGE_03_002: [IoTHubMessage_Clone shall return upon success a non-NULL handle to the newly created IoT hub message.]*/
+            }
+            else /*can only be STRING*/
+            {
+                /*Codes_SRS_IOTHUBMESSAGE_02_006: [IoTHubMessage_Clone shall clone the content by a call to BUFFER_clone or STRING_clone] */
+                if ((result->value.string = STRING_clone(source->value.string)) == NULL)
+                {
+                    /*Codes_SRS_IOTHUBMESSAGE_03_004: [IoTHubMessage_Clone shall return NULL if it fails for any reason.]*/
+                    LogError("failed to STRING_clone");
+                    DestroyMessageData(result);
+                    result = NULL;
+                }
+                /*Codes_SRS_IOTHUBMESSAGE_02_005: [IoTHubMessage_Clone shall clone the properties map by using Map_Clone.] */
+                else if ((result->properties = Map_Clone(source->properties)) == NULL)
+                {
+                    /*Codes_SRS_IOTHUBMESSAGE_03_004: [IoTHubMessage_Clone shall return NULL if it fails for any reason.]*/
+                    LogError("unable to Map_Clone");
+                    DestroyMessageData(result);
+                    result = NULL;
+                }
+            }
+        }
+    }
+    return result;
+}
+
+IOTHUB_MESSAGE_RESULT IoTHubMessage_GetByteArray(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle, const unsigned char** buffer, size_t* size)
+{
+    IOTHUB_MESSAGE_RESULT result;
+    if (
+        (iotHubMessageHandle == NULL) ||
+        (buffer == NULL) ||
+        (size == NULL)
+        )
+    {
+        /*Codes_SRS_IOTHUBMESSAGE_01_014: [If any of the arguments passed to IoTHubMessage_GetByteArray  is NULL IoTHubMessage_GetByteArray shall return IOTHUBMESSAGE_INVALID_ARG.] */
+        LogError("invalid parameter (NULL) to IoTHubMessage_GetByteArray IOTHUB_MESSAGE_HANDLE iotHubMessageHandle=%p, const unsigned char** buffer=%p, size_t* size=%p", iotHubMessageHandle, buffer, size);
+        result = IOTHUB_MESSAGE_INVALID_ARG;
+    }
+    else
+    {
+        IOTHUB_MESSAGE_HANDLE_DATA* handleData = iotHubMessageHandle;
+        if (handleData->contentType != IOTHUBMESSAGE_BYTEARRAY)
+        {
+            /*Codes_SRS_IOTHUBMESSAGE_02_021: [If iotHubMessageHandle is not a iothubmessage containing BYTEARRAY data, then IoTHubMessage_GetData shall write in *buffer NULL and shall set *size to 0.] */
+            result = IOTHUB_MESSAGE_INVALID_ARG;
+            LogError("invalid type of message %s", MU_ENUM_TO_STRING(IOTHUBMESSAGE_CONTENT_TYPE, handleData->contentType));
+        }
+        else
+        {
+            /*Codes_SRS_IOTHUBMESSAGE_01_011: [The pointer shall be obtained by using BUFFER_u_char and it shall be copied in the buffer argument.]*/
+            *buffer = BUFFER_u_char(handleData->value.byteArray);
+            /*Codes_SRS_IOTHUBMESSAGE_01_012: [The size of the associated data shall be obtained by using BUFFER_length and it shall be copied to the size argument.]*/
+            *size = BUFFER_length(handleData->value.byteArray);
+            result = IOTHUB_MESSAGE_OK;
+        }
+    }
+    return result;
+}
+
+const char* IoTHubMessage_GetString(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
+{
+    const char* result;
+    if (iotHubMessageHandle == NULL)
+    {
+        /*Codes_SRS_IOTHUBMESSAGE_02_016: [If any parameter is NULL then IoTHubMessage_GetString  shall return NULL.] */
+        result = NULL;
+    }
+    else
+    {
+        IOTHUB_MESSAGE_HANDLE_DATA* handleData = iotHubMessageHandle;
+        if (handleData->contentType != IOTHUBMESSAGE_STRING)
+        {
+            /*Codes_SRS_IOTHUBMESSAGE_02_017: [IoTHubMessage_GetString shall return NULL if the iotHubMessageHandle does not refer to a IOTHUBMESSAGE of type STRING.] */
+            result = NULL;
+        }
+        else
+        {
+            /*Codes_SRS_IOTHUBMESSAGE_02_018: [IoTHubMessage_GetStringData shall return the currently stored null terminated string.] */
+            result = STRING_c_str(handleData->value.string);
+        }
+    }
+    return result;
+}
+
+IOTHUBMESSAGE_CONTENT_TYPE IoTHubMessage_GetContentType(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
+{
+    IOTHUBMESSAGE_CONTENT_TYPE result;
+    /*Codes_SRS_IOTHUBMESSAGE_02_008: [If any parameter is NULL then IoTHubMessage_GetContentType shall return IOTHUBMESSAGE_UNKNOWN.] */
+    if (iotHubMessageHandle == NULL)
+    {
+        result = IOTHUBMESSAGE_UNKNOWN;
+    }
+    else
+    {
+        /*Codes_SRS_IOTHUBMESSAGE_02_009: [Otherwise IoTHubMessage_GetContentType shall return the type of the message.] */
+        IOTHUB_MESSAGE_HANDLE_DATA* handleData = iotHubMessageHandle;
+        result = handleData->contentType;
+    }
+    return result;
+}
+
+MAP_HANDLE IoTHubMessage_Properties(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
+{
+    MAP_HANDLE result;
+    /*Codes_SRS_IOTHUBMESSAGE_02_001: [If iotHubMessageHandle is NULL then IoTHubMessage_Properties shall return NULL.]*/
+    if (iotHubMessageHandle == NULL)
+    {
+        LogError("invalid arg (NULL) passed to IoTHubMessage_Properties");
+        result = NULL;
+    }
+    else
+    {
+        /*Codes_SRS_IOTHUBMESSAGE_02_002: [Otherwise, for any non-NULL iotHubMessageHandle it shall return a non-NULL MAP_HANDLE.]*/
+        IOTHUB_MESSAGE_HANDLE_DATA* handleData = (IOTHUB_MESSAGE_HANDLE_DATA*)iotHubMessageHandle;
+        result = handleData->properties;
+    }
+    return result;
+}
+
+IOTHUB_MESSAGE_RESULT IoTHubMessage_SetProperty(IOTHUB_MESSAGE_HANDLE msg_handle, const char* key, const char* value)
+{
+    IOTHUB_MESSAGE_RESULT result;
+    if (msg_handle == NULL || key == NULL || value == NULL)
+    {
+        LogError("invalid parameter (NULL) to IoTHubMessage_SetProperty iotHubMessageHandle=%p, key=%p, value=%p", msg_handle, key, value);
+        result = IOTHUB_MESSAGE_INVALID_ARG;
+    }
+    else
+    {
+        if (Map_AddOrUpdate(msg_handle->properties, key, value) != MAP_OK)
+        {
+            LogError("Failure adding property to internal map");
+            result = IOTHUB_MESSAGE_ERROR;
+        }
+        else
+        {
+            result = IOTHUB_MESSAGE_OK;
+        }
+    }
+    return result;
+}
+
+const char* IoTHubMessage_GetProperty(IOTHUB_MESSAGE_HANDLE msg_handle, const char* key)
+{
+    const char* result;
+    if (msg_handle == NULL || key == NULL)
+    {
+        LogError("invalid parameter (NULL) to IoTHubMessage_GetProperty iotHubMessageHandle=%p, key=%p", msg_handle, key);
+        result = NULL;
+    }
+    else
+    {
+        bool key_exists = false;
+        // The return value is not neccessary, just check the key_exist variable
+        if ((Map_ContainsKey(msg_handle->properties, key, &key_exists) == MAP_OK) && key_exists)
+        {
+            result = Map_GetValueFromKey(msg_handle->properties, key);
+        }
+        else
+        {
+            result = NULL;
+        }
+    }
+    return result;
+}
+
+const char* IoTHubMessage_GetCorrelationId(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
+{
+    const char* result;
+    /* Codes_SRS_IOTHUBMESSAGE_07_016: [if the iotHubMessageHandle parameter is NULL then IoTHubMessage_GetCorrelationId shall return a NULL value.] */
+    if (iotHubMessageHandle == NULL)
+    {
+        LogError("invalid arg (NULL) passed to IoTHubMessage_GetCorrelationId");
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_IOTHUBMESSAGE_07_017: [IoTHubMessage_GetCorrelationId shall return the correlationId as a const char*.] */
+        IOTHUB_MESSAGE_HANDLE_DATA* handleData = iotHubMessageHandle;
+        result = handleData->correlationId;
+    }
+    return result;
+}
+
+IOTHUB_MESSAGE_RESULT IoTHubMessage_SetCorrelationId(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle, const char* correlationId)
+{
+    IOTHUB_MESSAGE_RESULT result;
+    /* Codes_SRS_IOTHUBMESSAGE_07_018: [if any of the parameters are NULL then IoTHubMessage_SetCorrelationId shall return a IOTHUB_MESSAGE_INVALID_ARG value.]*/
+    if (iotHubMessageHandle == NULL || correlationId == NULL)
+    {
+        LogError("invalid arg (NULL) passed to IoTHubMessage_SetCorrelationId");
+        result = IOTHUB_MESSAGE_INVALID_ARG;
+    }
+    else
+    {
+        IOTHUB_MESSAGE_HANDLE_DATA* handleData = iotHubMessageHandle;
+        /* Codes_SRS_IOTHUBMESSAGE_07_019: [If the IOTHUB_MESSAGE_HANDLE correlationId is not NULL, then the IOTHUB_MESSAGE_HANDLE correlationId will be deallocated.] */
+        if (handleData->correlationId != NULL)
+        {
+            free(handleData->correlationId);
+            handleData->correlationId = NULL;
+        }
+
+        if (mallocAndStrcpy_s(&handleData->correlationId, correlationId) != 0)
+        {
+            /* Codes_SRS_IOTHUBMESSAGE_07_020: [If the allocation or the copying of the correlationId fails, then IoTHubMessage_SetCorrelationId shall return IOTHUB_MESSAGE_ERROR.] */
+            result = IOTHUB_MESSAGE_ERROR;
+        }
+        else
+        {
+            /* Codes_SRS_IOTHUBMESSAGE_07_021: [IoTHubMessage_SetCorrelationId finishes successfully it shall return IOTHUB_MESSAGE_OK.] */
+            result = IOTHUB_MESSAGE_OK;
+        }
+    }
+    return result;
+}
+
+IOTHUB_MESSAGE_RESULT IoTHubMessage_SetMessageId(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle, const char* messageId)
+{
+    IOTHUB_MESSAGE_RESULT result;
+    /* Codes_SRS_IOTHUBMESSAGE_07_012: [if any of the parameters are NULL then IoTHubMessage_SetMessageId shall return a IOTHUB_MESSAGE_INVALID_ARG value.] */
+    if (iotHubMessageHandle == NULL || messageId == NULL)
+    {
+        LogError("invalid arg (NULL) passed to IoTHubMessage_SetMessageId");
+        result = IOTHUB_MESSAGE_INVALID_ARG;
+    }
+    else
+    {
+        IOTHUB_MESSAGE_HANDLE_DATA* handleData = iotHubMessageHandle;
+        /* Codes_SRS_IOTHUBMESSAGE_07_013: [If the IOTHUB_MESSAGE_HANDLE messageId is not NULL, then the IOTHUB_MESSAGE_HANDLE messageId will be freed] */
+        if (handleData->messageId != NULL)
+        {
+            free(handleData->messageId);
+            handleData->messageId = NULL;
+        }
+
+        /* Codes_SRS_IOTHUBMESSAGE_07_014: [If the allocation or the copying of the messageId fails, then IoTHubMessage_SetMessageId shall return IOTHUB_MESSAGE_ERROR.] */
+        if (mallocAndStrcpy_s(&handleData->messageId, messageId) != 0)
+        {
+            result = IOTHUB_MESSAGE_ERROR;
+        }
+        else
+        {
+            result = IOTHUB_MESSAGE_OK;
+        }
+    }
+    return result;
+}
+
+const char* IoTHubMessage_GetMessageId(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
+{
+    const char* result;
+    /* Codes_SRS_IOTHUBMESSAGE_07_010: [if the iotHubMessageHandle parameter is NULL then IoTHubMessage_MessageId shall return a NULL value.] */
+    if (iotHubMessageHandle == NULL)
+    {
+        LogError("invalid arg (NULL) passed to IoTHubMessage_GetMessageId");
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_IOTHUBMESSAGE_07_011: [IoTHubMessage_MessageId shall return the messageId as a const char*.] */
+        IOTHUB_MESSAGE_HANDLE_DATA* handleData = iotHubMessageHandle;
+        result = handleData->messageId;
+    }
+    return result;
+}
+
+IOTHUB_MESSAGE_RESULT IoTHubMessage_SetContentTypeSystemProperty(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle, const char* contentType)
+{
+    IOTHUB_MESSAGE_RESULT result;
+
+    // Codes_SRS_IOTHUBMESSAGE_09_001: [If any of the parameters are NULL then IoTHubMessage_SetContentTypeSystemProperty shall return a IOTHUB_MESSAGE_INVALID_ARG value.]
+    if (iotHubMessageHandle == NULL || contentType == NULL)
+    {
+        LogError("Invalid argument (iotHubMessageHandle=%p, contentType=%p)", iotHubMessageHandle, contentType);
+        result = IOTHUB_MESSAGE_INVALID_ARG;
+    }
+    else
+    {
+        IOTHUB_MESSAGE_HANDLE_DATA* handleData = (IOTHUB_MESSAGE_HANDLE_DATA*)iotHubMessageHandle;
+
+        // Codes_SRS_IOTHUBMESSAGE_09_002: [If the IOTHUB_MESSAGE_HANDLE `contentType` is not NULL it shall be deallocated.]
+        if (handleData->userDefinedContentType != NULL)
+        {
+            free(handleData->userDefinedContentType);
+            handleData->userDefinedContentType = NULL;
+        }
+
+        if (mallocAndStrcpy_s(&handleData->userDefinedContentType, contentType) != 0)
+        {
+            LogError("Failed saving a copy of contentType");
+            // Codes_SRS_IOTHUBMESSAGE_09_003: [If the allocation or the copying of `contentType` fails, then IoTHubMessage_SetContentTypeSystemProperty shall return IOTHUB_MESSAGE_ERROR.]
+            result = IOTHUB_MESSAGE_ERROR;
+        }
+        else
+        {
+            // Codes_SRS_IOTHUBMESSAGE_09_004: [If IoTHubMessage_SetContentTypeSystemProperty finishes successfully it shall return IOTHUB_MESSAGE_OK.]
+            result = IOTHUB_MESSAGE_OK;
+        }
+    }
+
+    return result;
+}
+
+const char* IoTHubMessage_GetContentTypeSystemProperty(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
+{
+    const char* result;
+
+    // Codes_SRS_IOTHUBMESSAGE_09_005: [If any of the parameters are NULL then IoTHubMessage_GetContentTypeSystemProperty shall return a IOTHUB_MESSAGE_INVALID_ARG value.]
+    if (iotHubMessageHandle == NULL)
+    {
+        LogError("Invalid argument (iotHubMessageHandle is NULL)");
+        result = NULL;
+    }
+    else
+    {
+        IOTHUB_MESSAGE_HANDLE_DATA* handleData = iotHubMessageHandle;
+
+        // Codes_SRS_IOTHUBMESSAGE_09_006: [IoTHubMessage_GetContentTypeSystemProperty shall return the `contentType` as a const char* ]
+        result = (const char*)handleData->userDefinedContentType;
+    }
+
+    return result;
+}
+
+IOTHUB_MESSAGE_RESULT IoTHubMessage_SetContentEncodingSystemProperty(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle, const char* contentEncoding)
+{
+    IOTHUB_MESSAGE_RESULT result;
+
+    // Codes_SRS_IOTHUBMESSAGE_09_006: [If any of the parameters are NULL then IoTHubMessage_SetContentEncodingSystemProperty shall return a IOTHUB_MESSAGE_INVALID_ARG value.]
+    if (iotHubMessageHandle == NULL || contentEncoding == NULL)
+    {
+        LogError("Invalid argument (iotHubMessageHandle=%p, contentEncoding=%p)", iotHubMessageHandle, contentEncoding);
+        result = IOTHUB_MESSAGE_INVALID_ARG;
+    }
+    else
+    {
+        if (set_content_encoding(iotHubMessageHandle, contentEncoding) != 0)
+        {
+            LogError("Failed saving a copy of contentEncoding");
+            // Codes_SRS_IOTHUBMESSAGE_09_008: [If the allocation or the copying of `contentEncoding` fails, then IoTHubMessage_SetContentEncodingSystemProperty shall return IOTHUB_MESSAGE_ERROR.]
+            result = IOTHUB_MESSAGE_ERROR;
+        }
+        else
+        {
+            // Codes_SRS_IOTHUBMESSAGE_09_009: [If IoTHubMessage_SetContentEncodingSystemProperty finishes successfully it shall return IOTHUB_MESSAGE_OK.]
+            result = IOTHUB_MESSAGE_OK;
+        }
+    }
+    return result;
+}
+
+const char* IoTHubMessage_GetContentEncodingSystemProperty(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
+{
+    const char* result;
+
+    // Codes_SRS_IOTHUBMESSAGE_09_010: [If any of the parameters are NULL then IoTHubMessage_GetContentEncodingSystemProperty shall return a IOTHUB_MESSAGE_INVALID_ARG value.]
+    if (iotHubMessageHandle == NULL)
+    {
+        LogError("Invalid argument (iotHubMessageHandle is NULL)");
+        result = NULL;
+    }
+    else
+    {
+        IOTHUB_MESSAGE_HANDLE_DATA* handleData = iotHubMessageHandle;
+
+        // Codes_SRS_IOTHUBMESSAGE_09_011: [IoTHubMessage_GetContentEncodingSystemProperty shall return the `contentEncoding` as a const char* ]
+        result = (const char*)handleData->contentEncoding;
+    }
+
+    return result;
+}
+
+const IOTHUB_MESSAGE_DIAGNOSTIC_PROPERTY_DATA* IoTHubMessage_GetDiagnosticPropertyData(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
+{
+    const IOTHUB_MESSAGE_DIAGNOSTIC_PROPERTY_DATA* result;
+    // Codes_SRS_IOTHUBMESSAGE_10_001: [If any of the parameters are NULL then IoTHubMessage_GetDiagnosticPropertyData shall return a NULL value.]
+    if (iotHubMessageHandle == NULL)
+    {
+        LogError("Invalid argument (iotHubMessageHandle is NULL)");
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_IOTHUBMESSAGE_10_002: [IoTHubMessage_GetDiagnosticPropertyData shall return the diagnosticData as a const IOTHUB_MESSAGE_DIAGNOSTIC_PROPERTY_DATA*.] */
+        result = iotHubMessageHandle->diagnosticData;
+    }
+    return result;
+}
+
+IOTHUB_MESSAGE_RESULT IoTHubMessage_SetDiagnosticPropertyData(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle, const IOTHUB_MESSAGE_DIAGNOSTIC_PROPERTY_DATA* diagnosticData)
+{
+    IOTHUB_MESSAGE_RESULT result;
+    // Codes_SRS_IOTHUBMESSAGE_10_003: [If any of the parameters are NULL then IoTHubMessage_SetDiagnosticId shall return a IOTHUB_MESSAGE_INVALID_ARG value.]
+    if (iotHubMessageHandle == NULL ||
+        diagnosticData == NULL ||
+        diagnosticData->diagnosticCreationTimeUtc == NULL ||
+        diagnosticData->diagnosticId == NULL)
+    {
+        LogError("Invalid argument (iotHubMessageHandle=%p, diagnosticData=%p, diagnosticData->diagnosticId=%p, diagnosticData->diagnosticCreationTimeUtc=%p)",
+            iotHubMessageHandle, diagnosticData,
+            diagnosticData == NULL ? NULL : diagnosticData->diagnosticId,
+            diagnosticData == NULL ? NULL : diagnosticData->diagnosticCreationTimeUtc);
+        result = IOTHUB_MESSAGE_INVALID_ARG;
+    }
+    else
+    {
+        // Codes_SRS_IOTHUBMESSAGE_10_004: [If the IOTHUB_MESSAGE_HANDLE `diagnosticData` is not NULL it shall be deallocated.]
+        if (iotHubMessageHandle->diagnosticData != NULL)
+        {
+            DestroyDiagnosticPropertyData(iotHubMessageHandle->diagnosticData);
+            iotHubMessageHandle->diagnosticData = NULL;
+        }
+
+        // Codes_SRS_IOTHUBMESSAGE_10_005: [If the allocation or the copying of `diagnosticData` fails, then IoTHubMessage_SetDiagnosticPropertyData shall return IOTHUB_MESSAGE_ERROR.]
+        if ((iotHubMessageHandle->diagnosticData = CloneDiagnosticPropertyData(diagnosticData)) == NULL)
+        {
+            LogError("Failed saving a copy of diagnosticData");
+            result = IOTHUB_MESSAGE_ERROR;
+        }
+        else
+        {
+            // Codes_SRS_IOTHUBMESSAGE_10_006: [If IoTHubMessage_SetDiagnosticPropertyData finishes successfully it shall return IOTHUB_MESSAGE_OK.]
+            result = IOTHUB_MESSAGE_OK;
+        }
+    }
+    return result;
+}
+
+
+const char* IoTHubMessage_GetOutputName(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
+{
+    const char* result;
+    // Codes_SRS_IOTHUBMESSAGE_31_034: [If the iotHubMessageHandle parameter is NULL then IoTHubMessage_GetOutputName shall return a NULL value.]
+    if (iotHubMessageHandle == NULL)
+    {
+        LogError("Invalid argument (iotHubMessageHandle is NULL)");
+        result = NULL;
+    }
+    else
+    {
+        // Codes_SRS_IOTHUBMESSAGE_31_035: [IoTHubMessage_GetOutputName shall return the OutputName as a const char*.]
+        result = iotHubMessageHandle->outputName;
+    }
+    return result;
+}
+
+IOTHUB_MESSAGE_RESULT IoTHubMessage_SetOutputName(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle, const char* outputName)
+{
+    IOTHUB_MESSAGE_RESULT result;
+
+    // Codes_SRS_IOTHUBMESSAGE_31_036: [If any of the parameters are NULL then IoTHubMessage_SetOutputName shall return a IOTHUB_MESSAGE_INVALID_ARG value.]
+    if ((iotHubMessageHandle == NULL) || (outputName == NULL))
+    {
+        LogError("Invalid argument (iotHubMessageHandle=%p, outputName=%p)", iotHubMessageHandle, outputName);
+        result = IOTHUB_MESSAGE_INVALID_ARG;
+    }
+    else
+    {
+        IOTHUB_MESSAGE_HANDLE_DATA* handleData = (IOTHUB_MESSAGE_HANDLE_DATA*)iotHubMessageHandle;
+
+        // Codes_SRS_IOTHUBMESSAGE_31_037: [If the IOTHUB_MESSAGE_HANDLE OutputName is not NULL, then the IOTHUB_MESSAGE_HANDLE OutputName will be deallocated.]
+        if (handleData->outputName != NULL)
+        {
+            free(handleData->outputName);
+            handleData->outputName = NULL;
+        }
+
+        if (mallocAndStrcpy_s(&handleData->outputName, outputName) != 0)
+        {
+            // Codes_SRS_IOTHUBMESSAGE_31_038: [If the allocation or the copying of the OutputName fails, then IoTHubMessage_SetOutputName shall return IOTHUB_MESSAGE_ERROR.]
+            LogError("Failed saving a copy of outputName");
+            result = IOTHUB_MESSAGE_ERROR;
+        }
+        else
+        {
+            // Codes_SRS_IOTHUBMESSAGE_31_039: [IoTHubMessage_SetOutputName finishes successfully it shall return IOTHUB_MESSAGE_OK.]
+            result = IOTHUB_MESSAGE_OK;
+        }
+
+    }
+
+    return result;
+}
+
+const char* IoTHubMessage_GetInputName(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
+{
+    const char* result;
+    // Codes_SRS_IOTHUBMESSAGE_31_040: [if the iotHubMessageHandle parameter is NULL then IoTHubMessage_GetInputName shall return a NULL value.]
+    if (iotHubMessageHandle == NULL)
+    {
+        LogError("Invalid argument (iotHubMessageHandle is NULL)");
+        result = NULL;
+    }
+    else
+    {
+        // Codes_SRS_IOTHUBMESSAGE_31_041: [IoTHubMessage_GetInputName shall return the InputName as a const char*.]
+        result = iotHubMessageHandle->inputName;
+    }
+    return result;
+}
+
+IOTHUB_MESSAGE_RESULT IoTHubMessage_SetInputName(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle, const char* inputName)
+{
+    IOTHUB_MESSAGE_RESULT result;
+
+    // Codes_SRS_IOTHUBMESSAGE_31_042: [if any of the parameters are NULL then IoTHubMessage_SetInputName shall return a IOTHUB_MESSAGE_INVALID_ARG value.]
+    if ((iotHubMessageHandle == NULL) || (inputName == NULL))
+    {
+        LogError("Invalid argument (iotHubMessageHandle=%p, inputName=%p)", iotHubMessageHandle, inputName);
+        result = IOTHUB_MESSAGE_INVALID_ARG;
+    }
+    else
+    {
+        IOTHUB_MESSAGE_HANDLE_DATA* handleData = (IOTHUB_MESSAGE_HANDLE_DATA*)iotHubMessageHandle;
+
+        // Codes_SRS_IOTHUBMESSAGE_31_043: [If the IOTHUB_MESSAGE_HANDLE InputName is not NULL, then the IOTHUB_MESSAGE_HANDLE InputName will be deallocated.]
+        if (handleData->inputName != NULL)
+        {
+            free(handleData->inputName);
+            handleData->inputName = NULL;
+        }
+
+        if (mallocAndStrcpy_s(&handleData->inputName, inputName) != 0)
+        {
+            // Codes_SRS_IOTHUBMESSAGE_31_044: [If the allocation or the copying of the InputName fails, then IoTHubMessage_SetInputName shall return IOTHUB_MESSAGE_ERROR.]
+            LogError("Failed saving a copy of inputName");
+            result = IOTHUB_MESSAGE_ERROR;
+        }
+        else
+        {
+            // Codes_SRS_IOTHUBMESSAGE_31_045: [IoTHubMessage_SetInputName finishes successfully it shall return IOTHUB_MESSAGE_OK.]
+            result = IOTHUB_MESSAGE_OK;
+        }
+
+    }
+
+    return result;
+}
+
+
+const char* IoTHubMessage_GetConnectionModuleId(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
+{
+    const char* result;
+    // Codes_SRS_IOTHUBMESSAGE_31_046: [if the iotHubMessageHandle parameter is NULL then IoTHubMessage_GetConnectionModuleId shall return a NULL value.]
+    if (iotHubMessageHandle == NULL)
+    {
+        LogError("Invalid argument (iotHubMessageHandle is NULL)");
+        result = NULL;
+    }
+    else
+    {
+        // Codes_SRS_IOTHUBMESSAGE_31_047: [IoTHubMessage_GetConnectionModuleId shall return the ConnectionModuleId as a const char*.]
+        result = iotHubMessageHandle->connectionModuleId;
+    }
+    return result;
+}
+
+IOTHUB_MESSAGE_RESULT IoTHubMessage_SetConnectionModuleId(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle, const char* connectionModuleId)
+{
+    IOTHUB_MESSAGE_RESULT result;
+
+    // Codes_SRS_IOTHUBMESSAGE_31_048: [if any of the parameters are NULL then IoTHubMessage_SetConnectionModuleId shall return a IOTHUB_MESSAGE_INVALID_ARG value.]
+    if ((iotHubMessageHandle == NULL) || (connectionModuleId == NULL))
+    {
+        LogError("Invalid argument (iotHubMessageHandle=%p, connectionModuleId=%p)", iotHubMessageHandle, connectionModuleId);
+        result = IOTHUB_MESSAGE_INVALID_ARG;
+    }
+    else
+    {
+        IOTHUB_MESSAGE_HANDLE_DATA* handleData = (IOTHUB_MESSAGE_HANDLE_DATA*)iotHubMessageHandle;
+
+        // Codes_SRS_IOTHUBMESSAGE_31_049: [If the IOTHUB_MESSAGE_HANDLE ConnectionModuleId is not NULL, then the IOTHUB_MESSAGE_HANDLE ConnectionModuleId will be deallocated.]
+        if (handleData->connectionModuleId != NULL)
+        {
+            free(handleData->connectionModuleId);
+            handleData->connectionModuleId = NULL;
+        }
+
+        if (mallocAndStrcpy_s(&handleData->connectionModuleId, connectionModuleId) != 0)
+        {
+            // Codes_SRS_IOTHUBMESSAGE_31_050: [If the allocation or the copying of the ConnectionModuleId fails, then IoTHubMessage_SetConnectionModuleId shall return IOTHUB_MESSAGE_ERROR.]
+            LogError("Failed saving a copy of connectionModuleId");
+            result = IOTHUB_MESSAGE_ERROR;
+        }
+        else
+        {
+            // Codes_SRS_IOTHUBMESSAGE_31_051: [IoTHubMessage_SetConnectionModuleId finishes successfully it shall return IOTHUB_MESSAGE_OK.]
+            result = IOTHUB_MESSAGE_OK;
+        }
+
+    }
+
+    return result;
+}
+
+
+const char* IoTHubMessage_GetConnectionDeviceId(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
+{
+    const char* result;
+    // Codes_SRS_IOTHUBMESSAGE_31_052: [if the iotHubMessageHandle parameter is NULL then IoTHubMessage_GetConnectionDeviceId shall return a NULL value.]
+    if (iotHubMessageHandle == NULL)
+    {
+        LogError("Invalid argument (iotHubMessageHandle is NULL)");
+        result = NULL;
+    }
+    else
+    {
+        // Codes_SRS_IOTHUBMESSAGE_31_053: [IoTHubMessage_GetConnectionDeviceId shall return the ConnectionDeviceId as a const char*.]
+        result = iotHubMessageHandle->connectionDeviceId;
+    }
+    return result;
+}
+
+IOTHUB_MESSAGE_RESULT IoTHubMessage_SetConnectionDeviceId(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle, const char* connectionDeviceId)
+{
+    IOTHUB_MESSAGE_RESULT result;
+
+    // Codes_SRS_IOTHUBMESSAGE_31_054: [if any of the parameters are NULL then IoTHubMessage_SetConnectionDeviceId shall return a IOTHUB_MESSAGE_INVALID_ARG value.]
+    if ((iotHubMessageHandle == NULL) || (connectionDeviceId == NULL))
+    {
+        LogError("Invalid argument (iotHubMessageHandle=%p, connectionDeviceId=%p)", iotHubMessageHandle, connectionDeviceId);
+        result = IOTHUB_MESSAGE_INVALID_ARG;
+    }
+    else
+    {
+        IOTHUB_MESSAGE_HANDLE_DATA* handleData = (IOTHUB_MESSAGE_HANDLE_DATA*)iotHubMessageHandle;
+
+        // Codes_SRS_IOTHUBMESSAGE_31_055: [If the IOTHUB_MESSAGE_HANDLE ConnectionDeviceId is not NULL, then the IOTHUB_MESSAGE_HANDLE ConnectionDeviceId will be deallocated.]
+        if (handleData->connectionDeviceId != NULL)
+        {
+            free(handleData->connectionDeviceId);
+            handleData->connectionDeviceId = NULL;
+        }
+
+        if (mallocAndStrcpy_s(&handleData->connectionDeviceId, connectionDeviceId) != 0)
+        {
+            // Codes_SRS_IOTHUBMESSAGE_31_056: [If the allocation or the copying of the ConnectionDeviceId fails, then IoTHubMessage_SetConnectionDeviceId shall return IOTHUB_MESSAGE_ERROR.]
+            LogError("Failed saving a copy of connectionDeviceId");
+            result = IOTHUB_MESSAGE_ERROR;
+        }
+        else
+        {
+            // Codes_SRS_IOTHUBMESSAGE_31_057: [IoTHubMessage_SetConnectionDeviceId finishes successfully it shall return IOTHUB_MESSAGE_OK.]
+            result = IOTHUB_MESSAGE_OK;
+        }
+
+    }
+
+    return result;
+}
+
+IOTHUB_MESSAGE_RESULT IoTHubMessage_SetAsSecurityMessage(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
+{
+    IOTHUB_MESSAGE_RESULT result;
+    if (iotHubMessageHandle == NULL)
+    {
+        LogError("Invalid argument (iotHubMessageHandle is NULL)");
+        result = IOTHUB_MESSAGE_INVALID_ARG;
+    }
+    else
+    {
+        if (set_content_encoding(iotHubMessageHandle, SECURITY_CLIENT_JSON_ENCODING) != 0)
+        {
+            LogError("Failure setting security message content encoding");
+            result = IOTHUB_MESSAGE_ERROR;
+        }
+        else
+        {
+            iotHubMessageHandle->is_security_message = true;
+            result = IOTHUB_MESSAGE_OK;
+        }
+    }
+    return result;
+}
+
+bool IoTHubMessage_IsSecurityMessage(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
+{
+    bool result;
+    if (iotHubMessageHandle == NULL)
+    {
+        LogError("Invalid argument (iotHubMessageHandle is NULL)");
+        result = false;
+    }
+    else
+    {
+        result = iotHubMessageHandle->is_security_message;
+    }
+    return result;
+}
+
+void IoTHubMessage_Destroy(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
+{
+    /*Codes_SRS_IOTHUBMESSAGE_01_004: [If iotHubMessageHandle is NULL, IoTHubMessage_Destroy shall do nothing.] */
+    if (iotHubMessageHandle != NULL)
+    {
+        /*Codes_SRS_IOTHUBMESSAGE_01_003: [IoTHubMessage_Destroy shall free all resources associated with iotHubMessageHandle.]  */
+        DestroyMessageData((IOTHUB_MESSAGE_HANDLE_DATA*)iotHubMessageHandle);
+    }
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_transport_ll_private.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_transport_ll_private.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothub_transport_ll_private.c	(revision 453)
@@ -0,0 +1,32 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+
+#include "azure_c_shared_utility/xlogging.h"
+#include "internal/iothub_transport_ll_private.h"
+
+int IoTHub_Transport_ValidateCallbacks(const TRANSPORT_CALLBACKS_INFO* transport_cb)
+{
+    int result;
+    if (
+        transport_cb == NULL ||
+        transport_cb->connection_status_cb == NULL ||
+        transport_cb->msg_input_cb == NULL ||
+        transport_cb->msg_cb == NULL ||
+        transport_cb->send_complete_cb == NULL ||
+        transport_cb->prod_info_cb == NULL ||
+        transport_cb->twin_rpt_state_complete_cb == NULL ||
+        transport_cb->twin_retrieve_prop_complete_cb == NULL ||
+        transport_cb->method_complete_cb == NULL
+        )
+    {
+        LogError("Failure callback function NULL");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        result = 0;
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothubtransport.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothubtransport.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothubtransport.c	(revision 453)
@@ -0,0 +1,465 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <signal.h>
+#include <stddef.h>
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "internal/iothubtransport.h"
+#include "iothub_client_core.h"
+#include "internal/iothub_client_private.h"
+#include "azure_c_shared_utility/threadapi.h"
+#include "azure_c_shared_utility/lock.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/vector.h"
+
+#include "internal/iothubtransport.h"
+#include "internal/iothub_client_private.h"
+#include "iothub_transport_ll.h"
+#include "iothub_client_core.h"
+
+typedef struct TRANSPORT_HANDLE_DATA_TAG
+{
+    TRANSPORT_LL_HANDLE transportLLHandle;
+    THREAD_HANDLE workerThreadHandle;
+    LOCK_HANDLE lockHandle;
+    sig_atomic_t stopThread;
+    TRANSPORT_PROVIDER_FIELDS;
+    VECTOR_HANDLE clients;
+    LOCK_HANDLE clientsLockHandle;
+    IOTHUB_CLIENT_MULTIPLEXED_DO_WORK clientDoWork;
+} TRANSPORT_HANDLE_DATA;
+
+/* Used for Unit test */
+const size_t IoTHubTransport_ThreadTerminationOffset = offsetof(TRANSPORT_HANDLE_DATA, stopThread);
+
+TRANSPORT_HANDLE IoTHubTransport_Create(IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol, const char* iotHubName, const char* iotHubSuffix)
+{
+    TRANSPORT_HANDLE_DATA *result;
+    TRANSPORT_CALLBACKS_INFO transport_cb;
+
+    if (protocol == NULL || iotHubName == NULL || iotHubSuffix == NULL)
+    {
+        /*Codes_SRS_IOTHUBTRANSPORT_17_002: [ If protocol is NULL, this function shall return NULL. ]*/
+        /*Codes_SRS_IOTHUBTRANSPORT_17_003: [ If iotHubName is NULL, this function shall return NULL. ]*/
+        /*Codes_SRS_IOTHUBTRANSPORT_17_004: [ If iotHubSuffix is NULL, this function shall return NULL. ]*/
+        LogError("Invalid NULL argument, protocol [%p], name [%p], suffix [%p].", protocol, iotHubName, iotHubSuffix);
+        result = NULL;
+    }
+    else if (IoTHubClientCore_LL_GetTransportCallbacks(&transport_cb) != 0)
+    {
+        LogError("Failure getting transport callbacks");
+        result = NULL;
+    }
+    else
+    {
+        /*Codes_SRS_IOTHUBTRANSPORT_17_032: [ IoTHubTransport_Create shall allocate memory for the transport data. ]*/
+        result = (TRANSPORT_HANDLE_DATA*)malloc(sizeof(TRANSPORT_HANDLE_DATA));
+        if (result == NULL)
+        {
+            /*Codes_SRS_IOTHUBTRANSPORT_17_040: [ If memory allocation fails, IoTHubTransport_Create shall return NULL. ]*/
+            LogError("Transport handle was not allocated.");
+        }
+        else
+        {
+            TRANSPORT_PROVIDER * transportProtocol = (TRANSPORT_PROVIDER*)(protocol());
+            IOTHUB_CLIENT_CONFIG upperConfig;
+            upperConfig.deviceId = NULL;
+            upperConfig.deviceKey = NULL;
+            upperConfig.iotHubName = iotHubName;
+            upperConfig.iotHubSuffix = iotHubSuffix;
+            upperConfig.protocol = protocol;
+            upperConfig.protocolGatewayHostName = NULL;
+
+            IOTHUBTRANSPORT_CONFIG transportLLConfig;
+            memset(&transportLLConfig, 0, sizeof(IOTHUBTRANSPORT_CONFIG));
+            transportLLConfig.upperConfig = &upperConfig;
+            transportLLConfig.waitingToSend = NULL;
+
+            /*Codes_SRS_IOTHUBTRANSPORT_17_005: [ IoTHubTransport_Create shall create the lower layer transport by calling the protocol's IoTHubTransport_Create function. ]*/
+            result->transportLLHandle = transportProtocol->IoTHubTransport_Create(&transportLLConfig, &transport_cb, NULL);
+            if (result->transportLLHandle == NULL)
+            {
+                /*Codes_SRS_IOTHUBTRANSPORT_17_006: [ If the creation of the transport fails, IoTHubTransport_Create shall return NULL. ]*/
+                LogError("Lower Layer transport not created.");
+                free(result);
+                result = NULL;
+            }
+            else
+            {
+                /*Codes_SRS_IOTHUBTRANSPORT_17_007: [ IoTHubTransport_Create shall create the transport lock by Calling Lock_Init. ]*/
+                result->lockHandle = Lock_Init();
+                if (result->lockHandle == NULL)
+                {
+                    /*Codes_SRS_IOTHUBTRANSPORT_17_008: [ If the lock creation fails, IoTHubTransport_Create shall return NULL. ]*/
+                    LogError("transport Lock not created.");
+                    transportProtocol->IoTHubTransport_Destroy(result->transportLLHandle);
+                    free(result);
+                    result = NULL;
+                }
+                else if ((result->clientsLockHandle = Lock_Init()) == NULL)
+                {
+                    LogError("clients Lock not created.");
+                    Lock_Deinit(result->lockHandle);
+                    transportProtocol->IoTHubTransport_Destroy(result->transportLLHandle);
+                    free(result);
+                    result = NULL;
+                }
+                else
+                {
+                    /*Codes_SRS_IOTHUBTRANSPORT_17_038: [ IoTHubTransport_Create shall call VECTOR_Create to make a list of IOTHUB_CLIENT_CORE_HANDLE using this transport. ]*/
+                    result->clients = VECTOR_create(sizeof(IOTHUB_CLIENT_CORE_HANDLE));
+                    if (result->clients == NULL)
+                    {
+                        /*Codes_SRS_IOTHUBTRANSPORT_17_039: [ If the Vector creation fails, IoTHubTransport_Create shall return NULL. ]*/
+                        /*Codes_SRS_IOTHUBTRANSPORT_17_009: [ IoTHubTransport_Create shall clean up any resources it creates if the function does not succeed. ]*/
+                        LogError("clients list not created.");
+                        Lock_Deinit(result->clientsLockHandle);
+                        Lock_Deinit(result->lockHandle);
+                        transportProtocol->IoTHubTransport_Destroy(result->transportLLHandle);
+                        free(result);
+                        result = NULL;
+                    }
+                    else
+                    {
+                        /*Codes_SRS_IOTHUBTRANSPORT_17_001: [ IoTHubTransport_Create shall return a non-NULL handle on success.]*/
+                        result->stopThread = 1;
+                        result->clientDoWork = NULL;
+                        result->workerThreadHandle = NULL; /* create thread when work needs to be done */
+                        result->IoTHubTransport_GetHostname = transportProtocol->IoTHubTransport_GetHostname;
+                        result->IoTHubTransport_SetOption = transportProtocol->IoTHubTransport_SetOption;
+                        result->IoTHubTransport_Create = transportProtocol->IoTHubTransport_Create;
+                        result->IoTHubTransport_Destroy = transportProtocol->IoTHubTransport_Destroy;
+                        result->IoTHubTransport_Register = transportProtocol->IoTHubTransport_Register;
+                        result->IoTHubTransport_Unregister = transportProtocol->IoTHubTransport_Unregister;
+                        result->IoTHubTransport_Subscribe = transportProtocol->IoTHubTransport_Subscribe;
+                        result->IoTHubTransport_Unsubscribe = transportProtocol->IoTHubTransport_Unsubscribe;
+                        result->IoTHubTransport_DoWork = transportProtocol->IoTHubTransport_DoWork;
+                        result->IoTHubTransport_SetRetryPolicy = transportProtocol->IoTHubTransport_SetRetryPolicy;
+                        result->IoTHubTransport_GetSendStatus = transportProtocol->IoTHubTransport_GetSendStatus;
+                    }
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+static void multiplexed_client_do_work(TRANSPORT_HANDLE_DATA* transportData)
+{
+    if (Lock(transportData->clientsLockHandle) != LOCK_OK)
+    {
+        LogError("failed to lock for multiplexed_client_do_work");
+    }
+    else
+    {
+        size_t numberOfClients;
+        size_t iterator;
+
+        numberOfClients = VECTOR_size(transportData->clients);
+        for (iterator = 0; iterator < numberOfClients; iterator++)
+        {
+            IOTHUB_CLIENT_CORE_HANDLE* clientHandle = (IOTHUB_CLIENT_CORE_HANDLE*)VECTOR_element(transportData->clients, iterator);
+
+            if (clientHandle != NULL)
+            {
+                transportData->clientDoWork(*clientHandle);
+            }
+        }
+
+        if (Unlock(transportData->clientsLockHandle) != LOCK_OK)
+        {
+            LogError("failed to unlock on multiplexed_client_do_work");
+        }
+    }
+}
+
+static int transport_worker_thread(void* threadArgument)
+{
+    TRANSPORT_HANDLE_DATA* transportData = (TRANSPORT_HANDLE_DATA*)threadArgument;
+
+    while (1)
+    {
+        /*Codes_SRS_IOTHUBTRANSPORT_17_030: [ All calls to lower layer transport DoWork shall be protected by the lock created in IoTHubTransport_Create. ]*/
+        if (Lock(transportData->lockHandle) == LOCK_OK)
+        {
+            /*Codes_SRS_IOTHUBTRANSPORT_17_031: [ If acquiring the lock fails, lower layer transport DoWork shall not be called. ]*/
+            if (transportData->stopThread)
+            {
+                /*Codes_SRS_IOTHUBTRANSPORT_17_028: [ The thread shall exit when IoTHubTransport_EndWorkerThread has been called for each clientHandle which invoked IoTHubTransport_StartWorkerThread. ]*/
+                (void)Unlock(transportData->lockHandle);
+                break;
+            }
+            else
+            {
+                (transportData->IoTHubTransport_DoWork)(transportData->transportLLHandle);
+
+                (void)Unlock(transportData->lockHandle);
+            }
+        }
+
+        multiplexed_client_do_work(transportData);
+
+        /*Codes_SRS_IOTHUBTRANSPORT_17_029: [ The thread shall call lower layer transport DoWork every 1 ms. ]*/
+        ThreadAPI_Sleep(1);
+    }
+
+    ThreadAPI_Exit(0);
+    return 0;
+}
+
+static bool find_by_handle(const void* element, const void* value)
+{
+    /* data stored at element is device handle */
+    const IOTHUB_CLIENT_CORE_HANDLE * guess = (const IOTHUB_CLIENT_CORE_HANDLE *)element;
+    const IOTHUB_CLIENT_CORE_HANDLE match = (const IOTHUB_CLIENT_CORE_HANDLE)value;
+    return (*guess == match);
+}
+
+static IOTHUB_CLIENT_RESULT start_worker_if_needed(TRANSPORT_HANDLE_DATA * transportData, IOTHUB_CLIENT_CORE_HANDLE clientHandle)
+{
+    IOTHUB_CLIENT_RESULT result;
+    if (transportData->workerThreadHandle == NULL)
+    {
+        /*Codes_SRS_IOTHUBTRANSPORT_17_018: [ If the worker thread does not exist, IoTHubTransport_StartWorkerThread shall start the thread using ThreadAPI_Create. ]*/
+        transportData->stopThread = 0;
+        if (ThreadAPI_Create(&transportData->workerThreadHandle, transport_worker_thread, transportData) != THREADAPI_OK)
+        {
+            transportData->workerThreadHandle = NULL;
+        }
+    }
+    if (transportData->workerThreadHandle != NULL)
+    {
+        if (Lock(transportData->clientsLockHandle) != LOCK_OK)
+        {
+            LogError("failed to lock for start_worker_if_needed");
+            result = IOTHUB_CLIENT_ERROR;
+        }
+        else
+        {
+            /*Codes_SRS_IOTHUBTRANSPORT_17_020: [ IoTHubTransport_StartWorkerThread shall search for IoTHubClient clientHandle in the list of IoTHubClient handles. ]*/
+            bool addToList = ((VECTOR_size(transportData->clients) == 0) || (VECTOR_find_if(transportData->clients, find_by_handle, clientHandle) == NULL));
+            if (addToList)
+            {
+                /*Codes_SRS_IOTHUBTRANSPORT_17_021: [ If handle is not found, then clientHandle shall be added to the list. ]*/
+                if (VECTOR_push_back(transportData->clients, &clientHandle, 1) != 0)
+                {
+                    LogError("Failed adding device to list (VECTOR_push_back failed)");
+                    /*Codes_SRS_IOTHUBTRANSPORT_17_042: [ If Adding to the client list fails, IoTHubTransport_StartWorkerThread shall return IOTHUB_CLIENT_ERROR. ]*/
+                    result = IOTHUB_CLIENT_ERROR;
+                }
+                else
+                {
+                    result = IOTHUB_CLIENT_OK;
+                }
+            }
+            else
+            {
+                result = IOTHUB_CLIENT_OK;
+            }
+
+            if (Unlock(transportData->clientsLockHandle) != LOCK_OK)
+            {
+                LogError("failed to unlock on start_worker_if_needed");
+            }
+        }
+    }
+    else
+    {
+        result = IOTHUB_CLIENT_ERROR;
+    }
+    return result;
+}
+
+static void stop_worker_thread(TRANSPORT_HANDLE_DATA* transportData)
+{
+    /*Codes_SRS_IOTHUBTRANSPORT_17_043: [** IoTHubTransport_SignalEndWorkerThread shall signal the worker thread to end.*/
+    if (Lock(transportData->lockHandle) != LOCK_OK)
+    {
+        // Need to setup a critical error function here to inform the user that an critical error
+        // has occured.
+        LogError("Unable to lock - will still attempt to end thread without thread safety");
+        transportData->stopThread = 1;
+    }
+    else
+    {
+        transportData->stopThread = 1;
+        (void)Unlock(transportData->lockHandle);
+    }
+
+}
+
+static void wait_worker_thread(TRANSPORT_HANDLE_DATA * transportData)
+{
+    if (transportData->workerThreadHandle != NULL)
+    {
+        int res;
+        /*Codes_SRS_IOTHUBTRANSPORT_17_027: [ If handle list is empty, IoTHubTransport_EndWorkerThread shall be joined. ]*/
+        if (ThreadAPI_Join(transportData->workerThreadHandle, &res) != THREADAPI_OK)
+        {
+            LogError("ThreadAPI_Join failed");
+        }
+        else
+        {
+            transportData->workerThreadHandle = NULL;
+        }
+    }
+}
+
+static bool signal_end_worker_thread(TRANSPORT_HANDLE_DATA * transportData, IOTHUB_CLIENT_CORE_HANDLE clientHandle)
+{
+    bool okToJoin;
+
+    if (Lock(transportData->clientsLockHandle) != LOCK_OK)
+    {
+        LogError("failed to lock for signal_end_worker_thread");
+        okToJoin = false;
+    }
+    else
+    {
+        void* element = VECTOR_find_if(transportData->clients, find_by_handle, clientHandle);
+        if (element != NULL)
+        {
+            /*Codes_SRS_IOTHUBTRANSPORT_17_026: [ IoTHubTransport_EndWorkerThread shall remove clientHandlehandle from handle list. ]*/
+            VECTOR_erase(transportData->clients, element, 1);
+        }
+        /*Codes_SRS_IOTHUBTRANSPORT_17_025: [ If the worker thread does not exist, then IoTHubTransport_EndWorkerThread shall return. ]*/
+        if (transportData->workerThreadHandle != NULL)
+        {
+            if (VECTOR_size(transportData->clients) == 0)
+            {
+                stop_worker_thread(transportData);
+                okToJoin = true;
+            }
+            else
+            {
+                okToJoin = false;
+            }
+        }
+        else
+        {
+            okToJoin = false;
+        }
+
+        if (Unlock(transportData->clientsLockHandle) != LOCK_OK)
+        {
+            LogError("failed to unlock on signal_end_worker_thread");
+        }
+    }
+    return okToJoin;
+}
+
+void IoTHubTransport_Destroy(TRANSPORT_HANDLE transportHandle)
+{
+    /*Codes_SRS_IOTHUBTRANSPORT_17_011: [ IoTHubTransport_Destroy shall do nothing if transportHandle is NULL. ]*/
+    if (transportHandle != NULL)
+    {
+        TRANSPORT_HANDLE_DATA * transportData = (TRANSPORT_HANDLE_DATA*)transportHandle;
+        /*Codes_SRS_IOTHUBTRANSPORT_17_033: [ IoTHubTransport_Destroy shall lock the transport lock. ]*/
+        stop_worker_thread(transportData);
+        wait_worker_thread(transportData);
+        /*Codes_SRS_IOTHUBTRANSPORT_17_010: [ IoTHubTransport_Destroy shall free all resources. ]*/
+        Lock_Deinit(transportData->lockHandle);
+        (transportData->IoTHubTransport_Destroy)(transportData->transportLLHandle);
+        VECTOR_destroy(transportData->clients);
+        Lock_Deinit(transportData->clientsLockHandle);
+        free(transportHandle);
+    }
+}
+
+LOCK_HANDLE IoTHubTransport_GetLock(TRANSPORT_HANDLE transportHandle)
+{
+    LOCK_HANDLE lock;
+    if (transportHandle == NULL)
+    {
+        /*Codes_SRS_IOTHUBTRANSPORT_17_013: [ If transportHandle is NULL, IoTHubTransport_GetLock shall return NULL. ]*/
+        lock = NULL;
+    }
+    else
+    {
+        /*Codes_SRS_IOTHUBTRANSPORT_17_012: [ IoTHubTransport_GetLock shall return a handle to the transport lock. ]*/
+        TRANSPORT_HANDLE_DATA * transportData = (TRANSPORT_HANDLE_DATA*)transportHandle;
+        lock = transportData->lockHandle;
+    }
+    return lock;
+}
+
+TRANSPORT_LL_HANDLE IoTHubTransport_GetLLTransport(TRANSPORT_HANDLE transportHandle)
+{
+    TRANSPORT_LL_HANDLE llTransport;
+    if (transportHandle == NULL)
+    {
+        /*Codes_SRS_IOTHUBTRANSPORT_17_015: [ If transportHandle is NULL, IoTHubTransport_GetLLTransport shall return NULL. ]*/
+        llTransport = NULL;
+    }
+    else
+    {
+        /*Codes_SRS_IOTHUBTRANSPORT_17_014: [ IoTHubTransport_GetLLTransport shall return a handle to the lower layer transport. ]*/
+        TRANSPORT_HANDLE_DATA * transportData = (TRANSPORT_HANDLE_DATA*)transportHandle;
+        llTransport = transportData->transportLLHandle;
+    }
+    return llTransport;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubTransport_StartWorkerThread(TRANSPORT_HANDLE transportHandle, IOTHUB_CLIENT_CORE_HANDLE clientHandle, IOTHUB_CLIENT_MULTIPLEXED_DO_WORK muxDoWork)
+{
+    IOTHUB_CLIENT_RESULT result;
+    if (transportHandle == NULL || clientHandle == NULL)
+    {
+        /*Codes_SRS_IOTHUBTRANSPORT_17_016: [ If transportHandle is NULL, IoTHubTransport_StartWorkerThread shall return IOTHUB_CLIENT_INVALID_ARG. ]*/
+        /*Codes_SRS_IOTHUBTRANSPORT_17_017: [ If clientHandle is NULL, IoTHubTransport_StartWorkerThread shall return IOTHUB_CLIENT_INVALID_ARG. ]*/
+        result = IOTHUB_CLIENT_INVALID_ARG;
+    }
+    else
+    {
+        TRANSPORT_HANDLE_DATA * transportData = (TRANSPORT_HANDLE_DATA*)transportHandle;
+
+        if (transportData->clientDoWork == NULL)
+        {
+            transportData->clientDoWork = muxDoWork;
+        }
+
+        if ((result = start_worker_if_needed(transportData, clientHandle)) != IOTHUB_CLIENT_OK)
+        {
+            /*Codes_SRS_IOTHUBTRANSPORT_17_019: [ If thread creation fails, IoTHubTransport_StartWorkerThread shall return IOTHUB_CLIENT_ERROR. */
+            LogError("Unable to start thread safely");
+        }
+        else
+        {
+            /*Codes_SRS_IOTHUBTRANSPORT_17_022: [ Upon success, IoTHubTransport_StartWorkerThread shall return IOTHUB_CLIENT_OK. ]*/
+            result = IOTHUB_CLIENT_OK;
+        }
+    }
+    return result;
+}
+
+bool IoTHubTransport_SignalEndWorkerThread(TRANSPORT_HANDLE transportHandle, IOTHUB_CLIENT_CORE_HANDLE clientHandle)
+{
+    bool okToJoin;
+    /*Codes_SRS_IOTHUBTRANSPORT_17_023: [ If transportHandle is NULL, IoTHubTransport_EndWorkerThread shall return. ]*/
+    /*Codes_SRS_IOTHUBTRANSPORT_17_024: [ If clientHandle is NULL, IoTHubTransport_EndWorkerThread shall return. ]*/
+    if (!(transportHandle == NULL || clientHandle == NULL))
+    {
+        TRANSPORT_HANDLE_DATA * transportData = (TRANSPORT_HANDLE_DATA*)transportHandle;
+        okToJoin = signal_end_worker_thread(transportData, clientHandle);
+    }
+    else
+    {
+        okToJoin = false;
+    }
+    return okToJoin;
+}
+
+void IoTHubTransport_JoinWorkerThread(TRANSPORT_HANDLE transportHandle, IOTHUB_CLIENT_CORE_HANDLE clientHandle)
+{
+    /*Codes_SRS_IOTHUBTRANSPORT_17_044: [ If transportHandle is NULL, IoTHubTransport_JoinWorkerThread shall do nothing. ]*/
+    /*Codes_SRS_IOTHUBTRANSPORT_17_045: [ If clientHandle is NULL, IoTHubTransport_JoinWorkerThread shall do nothing. ]*/
+    if (!(transportHandle == NULL || clientHandle == NULL))
+    {
+        TRANSPORT_HANDLE_DATA * transportData = (TRANSPORT_HANDLE_DATA*)transportHandle;
+        /*Codes_SRS_IOTHUBTRANSPORT_17_027: [ The worker thread shall be joined. ]*/
+        wait_worker_thread(transportData);
+    }
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothubtransport_mqtt_common.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothubtransport_mqtt_common.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothubtransport_mqtt_common.c	(revision 453)
@@ -0,0 +1,3700 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/strings.h"
+#include "azure_c_shared_utility/doublylinkedlist.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/agenttime.h"
+#include "azure_c_shared_utility/threadapi.h"
+#include "azure_c_shared_utility/sastoken.h"
+#include "azure_c_shared_utility/tickcounter.h"
+#include "azure_c_shared_utility/tlsio.h"
+#include "azure_c_shared_utility/platform.h"
+#include "azure_c_shared_utility/string_tokenizer.h"
+#include "azure_c_shared_utility/shared_util_options.h"
+#include "azure_c_shared_utility/urlencode.h"
+
+#include "internal/iothub_client_private.h"
+#include "internal/iothub_client_retry_control.h"
+#include "internal/iothub_transport_ll_private.h"
+#include "internal/iothubtransport_mqtt_common.h"
+#include "internal/iothubtransport.h"
+#include "internal/iothub_internal_consts.h"
+
+#include "azure_umqtt_c/mqtt_client.h"
+
+#include "iothub_client_options.h"
+#include "iothub_client_version.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include <limits.h>
+#include <inttypes.h>
+
+#define SAS_REFRESH_MULTIPLIER              .8
+#define EPOCH_TIME_T_VALUE                  0
+#define DEFAULT_MQTT_KEEPALIVE              4*60 // 4 min
+#define DEFAULT_CONNACK_TIMEOUT             30 // 30 seconds
+#define BUILD_CONFIG_USERNAME               24
+#define SAS_TOKEN_DEFAULT_LEN               10
+#define RESEND_TIMEOUT_VALUE_MIN            1*60
+#define MAX_SEND_RECOUNT_LIMIT              2
+#define DEFAULT_CONNECTION_INTERVAL         30
+#define FAILED_CONN_BACKOFF_VALUE           5
+#define STATUS_CODE_FAILURE_VALUE           500
+#define STATUS_CODE_TIMEOUT_VALUE           408
+
+#define DEFAULT_RETRY_POLICY                IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF_WITH_JITTER
+#define DEFAULT_RETRY_TIMEOUT_IN_SECONDS    0
+#define MAX_DISCONNECT_VALUE                50
+
+#define ON_DEMAND_GET_TWIN_REQUEST_TIMEOUT_SECS    60
+#define TWIN_REPORT_UPDATE_TIMEOUT_SECS           (60*5)
+
+static const char TOPIC_DEVICE_TWIN_PREFIX[] = "$iothub/twin";
+static const char TOPIC_DEVICE_METHOD_PREFIX[] = "$iothub/methods";
+
+static const char* TOPIC_GET_DESIRED_STATE = "$iothub/twin/res/#";
+static const char* TOPIC_NOTIFICATION_STATE = "$iothub/twin/PATCH/properties/desired/#";
+
+static const char* TOPIC_DEVICE_MSG = "devices/%s/messages/devicebound/#";
+static const char* TOPIC_DEVICE_MODULE_MSG = "devices/%s/modules/%s/messages/devicebound/#";
+static const char* TOPIC_DEVICE_DEVICE = "devices/%s/messages/events/";
+static const char* TOPIC_DEVICE_DEVICE_MODULE = "devices/%s/modules/%s/messages/events/";
+
+static const char* TOPIC_INPUT_QUEUE_NAME = "devices/%s/modules/%s/#";
+
+static const char* TOPIC_DEVICE_METHOD_SUBSCRIBE = "$iothub/methods/POST/#";
+
+static const char* PROPERTY_SEPARATOR = "&";
+static const char* REPORTED_PROPERTIES_TOPIC = "$iothub/twin/PATCH/properties/reported/?$rid=%"PRIu16;
+static const char* GET_PROPERTIES_TOPIC = "$iothub/twin/GET/?$rid=%"PRIu16;
+static const char* DEVICE_METHOD_RESPONSE_TOPIC = "$iothub/methods/res/%d/?$rid=%s";
+
+static const char* REQUEST_ID_PROPERTY = "?$rid=";
+
+static const char* MESSAGE_ID_PROPERTY = "mid";
+static const char* CORRELATION_ID_PROPERTY = "cid";
+static const char* CONTENT_TYPE_PROPERTY = "ct";
+static const char* CONTENT_ENCODING_PROPERTY = "ce";
+static const char* DIAGNOSTIC_ID_PROPERTY = "diagid";
+static const char* DIAGNOSTIC_CONTEXT_PROPERTY = "diagctx";
+static const char* CONNECTION_DEVICE_ID = "cdid";
+static const char* CONNECTION_MODULE_ID_PROPERTY = "cmid";
+
+static const char* DIAGNOSTIC_CONTEXT_CREATION_TIME_UTC_PROPERTY = "creationtimeutc";
+
+static const char DT_MODEL_ID_TOKEN[] = "model-id";
+
+static const char DEFAULT_IOTHUB_PRODUCT_IDENTIFIER[] = CLIENT_DEVICE_TYPE_PREFIX "/" IOTHUB_SDK_VERSION;
+
+#define TOLOWER(c) (((c>='A') && (c<='Z'))?c-'A'+'a':c)
+
+#define UNSUBSCRIBE_FROM_TOPIC                  0x0000
+#define SUBSCRIBE_GET_REPORTED_STATE_TOPIC      0x0001
+#define SUBSCRIBE_NOTIFICATION_STATE_TOPIC      0x0002
+#define SUBSCRIBE_TELEMETRY_TOPIC               0x0004
+#define SUBSCRIBE_DEVICE_METHOD_TOPIC           0x0008
+#define SUBSCRIBE_INPUT_QUEUE_TOPIC             0x0010
+#define SUBSCRIBE_TOPIC_COUNT                   5
+
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(MQTT_CLIENT_EVENT_ERROR, MQTT_CLIENT_EVENT_ERROR_VALUES)
+
+typedef struct SYSTEM_PROPERTY_INFO_TAG
+{
+    const char* propName;
+    size_t propLength;
+} SYSTEM_PROPERTY_INFO;
+
+static SYSTEM_PROPERTY_INFO sysPropList[] = {
+    { "%24.exp", 7 },
+    { "%24.mid", 7 },
+    { "%24.uid", 7 },
+    { "%24.to", 6 },
+    { "%24.cid", 7 },
+    { "%24.ct", 6 },
+    { "%24.ce", 6 },
+    { "devices/", 8 },
+    { "iothub-operation", 16 },
+    { "iothub-ack", 10 },
+    { "%24.on", 6 },
+    { "%24.cdid", 8 },
+    { "%24.cmid", 8 }
+};
+
+static const int slashes_to_reach_input_name = 5;
+
+typedef enum DEVICE_TWIN_MSG_TYPE_TAG
+{
+    REPORTED_STATE,
+    RETRIEVE_PROPERTIES
+} DEVICE_TWIN_MSG_TYPE;
+
+typedef enum MQTT_TRANSPORT_CREDENTIAL_TYPE_TAG
+{
+    CREDENTIAL_NOT_BUILD,
+    X509,
+    SAS_TOKEN_FROM_USER,
+    DEVICE_KEY,
+} MQTT_TRANSPORT_CREDENTIAL_TYPE;
+
+typedef enum MQTT_CLIENT_STATUS_TAG
+{
+    MQTT_CLIENT_STATUS_NOT_CONNECTED,
+    MQTT_CLIENT_STATUS_CONNECTING,
+    MQTT_CLIENT_STATUS_CONNECTED,
+    MQTT_CLIENT_STATUS_PENDING_CLOSE,
+    MQTT_CLIENT_STATUS_EXECUTE_DISCONNECT
+} MQTT_CLIENT_STATUS;
+
+typedef struct MQTTTRANSPORT_HANDLE_DATA_TAG
+{
+    // Topic control
+    STRING_HANDLE topic_MqttEvent;
+    STRING_HANDLE topic_MqttMessage;
+    STRING_HANDLE topic_GetState;
+    STRING_HANDLE topic_NotifyState;
+    STRING_HANDLE topic_InputQueue;
+
+    STRING_HANDLE topic_DeviceMethods;
+
+    uint32_t topics_ToSubscribe;
+
+    // Connection related constants
+    STRING_HANDLE hostAddress;
+    STRING_HANDLE device_id;
+    STRING_HANDLE module_id;
+    STRING_HANDLE devicesAndModulesPath;
+    int portNum;
+    // conn_attempted indicates whether a connection has *ever* been attempted on the lifetime
+    // of this handle.  Even if a given xio transport is added/removed, this always stays true.
+    bool conn_attempted;
+
+    MQTT_GET_IO_TRANSPORT get_io_transport;
+
+    // The current mqtt iothub implementation requires that the hub name and the domain suffix be passed as the first of a series of segments
+    // passed through the username portion of the connection frame.
+    // The second segment will contain the device id.  The two segments are delemited by a "/".
+    // The first segment can be a maximum 256 characters.
+    // The second segment can be a maximum 128 characters.
+    // With the / delimeter you have 384 chars (Plus a terminator of 0).
+    STRING_HANDLE configPassedThroughUsername;
+
+    // Protocol
+    MQTT_CLIENT_HANDLE mqttClient;
+    XIO_HANDLE xioTransport;
+
+    // Session - connection
+    uint16_t packetId;
+    uint16_t twin_resp_packet_id;
+
+    // Connection state control
+    bool isRegistered;
+    MQTT_CLIENT_STATUS mqttClientStatus;
+    bool isDestroyCalled;
+    bool isRetryExpiredCallbackSet;
+    bool device_twin_get_sent;
+    bool twin_resp_sub_recv;
+    bool isRecoverableError;
+    uint16_t keepAliveValue;
+    uint16_t connect_timeout_in_sec;
+    tickcounter_ms_t mqtt_connect_time;
+    size_t connectFailCount;
+    tickcounter_ms_t connectTick;
+    bool log_trace;
+    bool raw_trace;
+    TICK_COUNTER_HANDLE msgTickCounter;
+    OPTIONHANDLER_HANDLE saved_tls_options; // Here are the options from the xio layer if any is saved.
+
+    // Internal lists for message tracking
+    PDLIST_ENTRY waitingToSend;
+    DLIST_ENTRY ack_waiting_queue;
+
+    DLIST_ENTRY pending_get_twin_queue;
+
+    // Message tracking
+    CONTROL_PACKET_TYPE currPacketState;
+
+    // Telemetry specific
+    DLIST_ENTRY telemetry_waitingForAck;
+    bool auto_url_encode_decode;
+
+    // Controls frequency of reconnection logic.
+    RETRY_CONTROL_HANDLE retry_control_handle;
+
+    // Auth module used to generating handle authorization
+    // with either SAS Token, x509 Certs, and Device SAS Token
+    IOTHUB_AUTHORIZATION_HANDLE authorization_module;
+
+    TRANSPORT_CALLBACKS_INFO transport_callbacks;
+    void* transport_ctx;
+
+    char* http_proxy_hostname;
+    int http_proxy_port;
+    char* http_proxy_username;
+    char* http_proxy_password;
+    bool isConnectUsernameSet;
+    int disconnect_recv_flag;
+} MQTTTRANSPORT_HANDLE_DATA, *PMQTTTRANSPORT_HANDLE_DATA;
+
+typedef struct MQTT_DEVICE_TWIN_ITEM_TAG
+{
+    tickcounter_ms_t msgCreationTime;
+    tickcounter_ms_t msgPublishTime;
+    size_t retryCount;
+    uint16_t packet_id;
+    uint32_t iothub_msg_id;
+    IOTHUB_DEVICE_TWIN* device_twin_data;
+    DEVICE_TWIN_MSG_TYPE device_twin_msg_type;
+    DLIST_ENTRY entry;
+    IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK userCallback;
+    void* userContext;
+} MQTT_DEVICE_TWIN_ITEM;
+
+typedef struct MQTT_MESSAGE_DETAILS_LIST_TAG
+{
+    tickcounter_ms_t msgPublishTime;
+    size_t retryCount;
+    IOTHUB_MESSAGE_LIST* iotHubMessageEntry;
+    void* context;
+    uint16_t packet_id;
+    DLIST_ENTRY entry;
+} MQTT_MESSAGE_DETAILS_LIST, *PMQTT_MESSAGE_DETAILS_LIST;
+
+typedef struct DEVICE_METHOD_INFO_TAG
+{
+    STRING_HANDLE request_id;
+} DEVICE_METHOD_INFO;
+
+static void free_proxy_data(MQTTTRANSPORT_HANDLE_DATA* mqtt_transport_instance)
+{
+    if (mqtt_transport_instance->http_proxy_hostname != NULL)
+    {
+        free(mqtt_transport_instance->http_proxy_hostname);
+        mqtt_transport_instance->http_proxy_hostname = NULL;
+    }
+
+    if (mqtt_transport_instance->http_proxy_username != NULL)
+    {
+        free(mqtt_transport_instance->http_proxy_username);
+        mqtt_transport_instance->http_proxy_username = NULL;
+    }
+
+    if (mqtt_transport_instance->http_proxy_password != NULL)
+    {
+        free(mqtt_transport_instance->http_proxy_password);
+        mqtt_transport_instance->http_proxy_password = NULL;
+    }
+}
+
+// Destroys xio transport associated with MQTT handle and resets appropriate state
+static void DestroyXioTransport(PMQTTTRANSPORT_HANDLE_DATA transport_data)
+{
+    xio_destroy(transport_data->xioTransport);
+    transport_data->xioTransport = NULL;
+}
+
+static void set_saved_tls_options(PMQTTTRANSPORT_HANDLE_DATA transport, OPTIONHANDLER_HANDLE new_options)
+{
+    if (transport->saved_tls_options != NULL)
+    {
+        OptionHandler_Destroy(transport->saved_tls_options);
+    }
+    transport->saved_tls_options = new_options;
+}
+
+static void free_transport_handle_data(MQTTTRANSPORT_HANDLE_DATA* transport_data)
+{
+    if (transport_data->mqttClient != NULL)
+    {
+        mqtt_client_deinit(transport_data->mqttClient);
+    }
+
+    if (transport_data->retry_control_handle != NULL)
+    {
+        retry_control_destroy(transport_data->retry_control_handle);
+    }
+
+    set_saved_tls_options(transport_data, NULL);
+
+    tickcounter_destroy(transport_data->msgTickCounter);
+
+    free_proxy_data(transport_data);
+
+    STRING_delete(transport_data->devicesAndModulesPath);
+    STRING_delete(transport_data->topic_MqttEvent);
+    STRING_delete(transport_data->topic_MqttMessage);
+    STRING_delete(transport_data->device_id);
+    STRING_delete(transport_data->module_id);
+    STRING_delete(transport_data->hostAddress);
+    STRING_delete(transport_data->configPassedThroughUsername);
+    STRING_delete(transport_data->topic_GetState);
+    STRING_delete(transport_data->topic_NotifyState);
+    STRING_delete(transport_data->topic_DeviceMethods);
+    STRING_delete(transport_data->topic_InputQueue);
+
+    DestroyXioTransport(transport_data);
+
+    free(transport_data);
+}
+
+int IoTHubTransport_MQTT_Common_SetRetryPolicy(TRANSPORT_LL_HANDLE handle, IOTHUB_CLIENT_RETRY_POLICY retryPolicy, size_t retryTimeoutLimitInSeconds)
+{
+    int result;
+
+    if (handle == NULL)
+    {
+        /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_25_041: [**If any handle is NULL then IoTHubTransport_MQTT_Common_SetRetryPolicy shall return resultant line.] */
+        LogError("Invalid handle parameter. NULL.");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        RETRY_CONTROL_HANDLE new_retry_control_handle;
+
+        // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_006: [ IoTHubTransport_MQTT_Common_SetRetryPolicy shall set the retry logic by calling retry_control_create() with retry policy and retryTimeout as parameters]
+        // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_009: [ If retry_control_create() fails then IoTHubTransport_MQTT_Common_SetRetryPolicy shall revert to previous retry policy and return non-zero value ]
+        if ((new_retry_control_handle = retry_control_create(retryPolicy, (unsigned int)retryTimeoutLimitInSeconds)) == NULL)
+        {
+            LogError("Failed creating new retry control handle");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
+            RETRY_CONTROL_HANDLE previous_retry_control_handle = transport_data->retry_control_handle;
+
+            transport_data->retry_control_handle = new_retry_control_handle;
+            retry_control_destroy(previous_retry_control_handle);
+
+            /*Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_25_045: [**If retry logic for specified parameters of retry policy and retryTimeoutLimitInSeconds is created successfully then IoTHubTransport_MQTT_Common_SetRetryPolicy shall return 0]*/
+            result = 0;
+        }
+    }
+
+    return result;
+}
+
+static uint16_t get_next_packet_id(PMQTTTRANSPORT_HANDLE_DATA transport_data)
+{
+    if (transport_data->packetId + 1 >= USHRT_MAX)
+    {
+        transport_data->packetId = 1;
+    }
+    else
+    {
+        transport_data->packetId++;
+    }
+    return transport_data->packetId;
+}
+
+#ifndef NO_LOGGING
+static const char* retrieve_mqtt_return_codes(CONNECT_RETURN_CODE rtn_code)
+{
+    switch (rtn_code)
+    {
+        case CONNECTION_ACCEPTED:
+            return "Accepted";
+        case CONN_REFUSED_UNACCEPTABLE_VERSION:
+            return "Unacceptable Version";
+        case CONN_REFUSED_ID_REJECTED:
+            return "Id Rejected";
+        case CONN_REFUSED_SERVER_UNAVAIL:
+            return "Server Unavailable";
+        case CONN_REFUSED_BAD_USERNAME_PASSWORD:
+            return "Bad Username/Password";
+        case CONN_REFUSED_NOT_AUTHORIZED:
+            return "Not Authorized";
+        case CONN_REFUSED_UNKNOWN:
+        default:
+            return "Unknown";
+    }
+}
+#endif // NO_LOGGING
+
+static int retrieve_device_method_rid_info(const char* resp_topic, STRING_HANDLE method_name, STRING_HANDLE request_id)
+{
+    int result;
+
+    STRING_TOKENIZER_HANDLE token_handle = STRING_TOKENIZER_create_from_char(resp_topic);
+    if (token_handle == NULL)
+    {
+        LogError("Failed creating token from device twin topic.");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        STRING_HANDLE token_value;
+        if ((token_value = STRING_new()) == NULL)
+        {
+            LogError("Failed allocating new string .");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            size_t token_index = 0;
+            size_t request_id_length = strlen(REQUEST_ID_PROPERTY);
+            result = MU_FAILURE;
+            while (STRING_TOKENIZER_get_next_token(token_handle, token_value, "/") == 0)
+            {
+                if (token_index == 3)
+                {
+                    if (STRING_concat_with_STRING(method_name, token_value) != 0)
+                    {
+                        LogError("Failed STRING_concat_with_STRING.");
+                        result = MU_FAILURE;
+                        break;
+                    }
+                }
+                else if (token_index == 4)
+                {
+                    if (STRING_length(token_value) >= request_id_length)
+                    {
+                        const char* request_id_value = STRING_c_str(token_value);
+                        if (memcmp(request_id_value, REQUEST_ID_PROPERTY, request_id_length) == 0)
+                        {
+                            if (STRING_concat(request_id, request_id_value + request_id_length) != 0)
+                            {
+                                LogError("Failed STRING_concat failed.");
+                                result = MU_FAILURE;
+                            }
+                            else
+                            {
+                                result = 0;
+                            }
+                            break;
+                        }
+                    }
+                }
+                token_index++;
+            }
+            STRING_delete(token_value);
+        }
+        STRING_TOKENIZER_destroy(token_handle);
+    }
+
+    return result;
+}
+
+static int parse_device_twin_topic_info(const char* resp_topic, bool* patch_msg, size_t* request_id, int* status_code)
+{
+    int result;
+    STRING_TOKENIZER_HANDLE token_handle = STRING_TOKENIZER_create_from_char(resp_topic);
+    if (token_handle == NULL)
+    {
+        LogError("Failed creating token from device twin topic.");
+        result = MU_FAILURE;
+        *status_code = 0;
+        *request_id = 0;
+        *patch_msg = false;
+    }
+    else
+    {
+        STRING_HANDLE token_value;
+        if ((token_value = STRING_new()) == NULL)
+        {
+            LogError("Failed allocating new string .");
+            result = MU_FAILURE;
+            *status_code = 0;
+            *request_id = 0;
+            *patch_msg = false;
+        }
+        else
+        {
+            result = MU_FAILURE;
+            size_t token_count = 0;
+            while (STRING_TOKENIZER_get_next_token(token_handle, token_value, "/") == 0)
+            {
+                if (token_count == 2)
+                {
+                    if (strcmp(STRING_c_str(token_value), "PATCH") == 0)
+                    {
+                        *patch_msg = true;
+                        *status_code = 0;
+                        *request_id = 0;
+                        result = 0;
+                        break;
+                    }
+                    else
+                    {
+                        *patch_msg = false;
+                    }
+                }
+                else if (token_count == 3)
+                {
+                    *status_code = (int)atol(STRING_c_str(token_value));
+                    if (STRING_TOKENIZER_get_next_token(token_handle, token_value, "/?$rid=") == 0)
+                    {
+                        *request_id = (size_t)atol(STRING_c_str(token_value));
+                    }
+                    *patch_msg = false;
+                    result = 0;
+                    break;
+                }
+                token_count++;
+            }
+            STRING_delete(token_value);
+        }
+        STRING_TOKENIZER_destroy(token_handle);
+    }
+    return result;
+}
+
+static int InternStrnicmp(const char* s1, const char* s2, size_t n)
+{
+    int result;
+
+    if (s1 == NULL) result = -1;
+    else if (s2 == NULL) result = 1;
+    else
+    {
+        result = 0;
+
+        while (n-- && result == 0)
+        {
+            if (*s1 == 0) result = -1;
+            else if (*s2 == 0) result = 1;
+            else
+            {
+
+                result = TOLOWER(*s1) - TOLOWER(*s2);
+                ++s1;
+                ++s2;
+            }
+        }
+    }
+    return result;
+}
+
+static IOTHUB_IDENTITY_TYPE retrieve_topic_type(const char* topic_resp, const char* input_queue)
+{
+    IOTHUB_IDENTITY_TYPE type;
+    if (InternStrnicmp(topic_resp, TOPIC_DEVICE_TWIN_PREFIX, sizeof(TOPIC_DEVICE_TWIN_PREFIX) - 1) == 0)
+    {
+        type = IOTHUB_TYPE_DEVICE_TWIN;
+    }
+    else if (InternStrnicmp(topic_resp, TOPIC_DEVICE_METHOD_PREFIX, sizeof(TOPIC_DEVICE_METHOD_PREFIX) - 1) == 0)
+    {
+        type = IOTHUB_TYPE_DEVICE_METHODS;
+    }
+    // input_queue contains additional "#" from subscribe, which we strip off on comparing incoming.
+    else if ((input_queue != NULL) && InternStrnicmp(topic_resp, input_queue, strlen(input_queue) - 1) == 0)
+    {
+        type = IOTHUB_TYPE_EVENT_QUEUE;
+    }
+    else
+    {
+        type = IOTHUB_TYPE_TELEMETRY;
+    }
+    return type;
+
+}
+
+static void sendMsgComplete(IOTHUB_MESSAGE_LIST* iothubMsgList, PMQTTTRANSPORT_HANDLE_DATA transport_data, IOTHUB_CLIENT_CONFIRMATION_RESULT confirmResult)
+{
+    DLIST_ENTRY messageCompleted;
+    DList_InitializeListHead(&messageCompleted);
+    DList_InsertTailList(&messageCompleted, &(iothubMsgList->entry));
+    transport_data->transport_callbacks.send_complete_cb(&messageCompleted, confirmResult, transport_data->transport_ctx);
+}
+
+static int addUserPropertiesTouMqttMessage(IOTHUB_MESSAGE_HANDLE iothub_message_handle, STRING_HANDLE topic_string, size_t* index_ptr, bool urlencode)
+{
+    int result = 0;
+    const char* const* propertyKeys;
+    const char* const* propertyValues;
+    size_t propertyCount;
+    size_t index = *index_ptr;
+    MAP_HANDLE properties_map = IoTHubMessage_Properties(iothub_message_handle);
+    if (properties_map != NULL)
+    {
+        if (Map_GetInternals(properties_map, &propertyKeys, &propertyValues, &propertyCount) != MAP_OK)
+        {
+            LogError("Failed to get the internals of the property map.");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if (propertyCount != 0)
+            {
+                for (index = 0; index < propertyCount && result == 0; index++)
+                {
+                    if (urlencode)
+                    {
+                        STRING_HANDLE property_key = URL_EncodeString(propertyKeys[index]);
+                        STRING_HANDLE property_value = URL_EncodeString(propertyValues[index]);
+                        if ((property_key == NULL) || (property_value == NULL))
+                        {
+                            LogError("Failed URL Encoding properties");
+                            result = MU_FAILURE;
+                        }
+                        else if (STRING_sprintf(topic_string, "%s=%s%s", STRING_c_str(property_key), STRING_c_str(property_value), propertyCount - 1 == index ? "" : PROPERTY_SEPARATOR) != 0)
+                        {
+                            LogError("Failed constructing property string.");
+                            result = MU_FAILURE;
+                        }
+                        STRING_delete(property_key);
+                        STRING_delete(property_value);
+                    }
+                    else
+                    {
+                        if (STRING_sprintf(topic_string, "%s=%s%s", propertyKeys[index], propertyValues[index], propertyCount - 1 == index ? "" : PROPERTY_SEPARATOR) != 0)
+                        {
+                            LogError("Failed constructing property string.");
+                            result = MU_FAILURE;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    *index_ptr = index;
+    return result;
+}
+
+static int addSystemPropertyToTopicString(STRING_HANDLE topic_string, size_t index, const char* property_key, const char* property_value, bool urlencode)
+{
+    int result = 0;
+
+    if (urlencode)
+    {
+        STRING_HANDLE encoded_property_value = URL_EncodeString(property_value);
+        if (encoded_property_value == NULL)
+        {
+            LogError("Failed URL encoding %s.", property_key);
+            result = MU_FAILURE;
+        }
+        else if (STRING_sprintf(topic_string, "%s%%24.%s=%s", index == 0 ? "" : PROPERTY_SEPARATOR, property_key, STRING_c_str(encoded_property_value)) != 0)
+        {
+            LogError("Failed setting %s.", property_key);
+            result = MU_FAILURE;
+        }
+        STRING_delete(encoded_property_value);
+    }
+    else
+    {
+        if (STRING_sprintf(topic_string, "%s%%24.%s=%s", index == 0 ? "" : PROPERTY_SEPARATOR, property_key, property_value) != 0)
+        {
+            LogError("Failed setting %s.", property_key);
+            result = MU_FAILURE;
+        }
+    }
+    return result;
+}
+
+static int addSystemPropertiesTouMqttMessage(IOTHUB_MESSAGE_HANDLE iothub_message_handle, STRING_HANDLE topic_string, size_t* index_ptr, bool urlencode)
+{
+    int result = 0;
+    size_t index = *index_ptr;
+
+    bool is_security_msg = IoTHubMessage_IsSecurityMessage(iothub_message_handle);
+    /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_07_052: [ IoTHubTransport_MQTT_Common_DoWork shall check for the CorrelationId property and if found add the value as a system property in the format of $.cid=<id> ] */
+    const char* correlation_id = IoTHubMessage_GetCorrelationId(iothub_message_handle);
+    if (correlation_id != NULL)
+    {
+        result = addSystemPropertyToTopicString(topic_string, index, CORRELATION_ID_PROPERTY, correlation_id, urlencode);
+        index++;
+    }
+    /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_07_053: [ IoTHubTransport_MQTT_Common_DoWork shall check for the MessageId property and if found add the value as a system property in the format of $.mid=<id> ] */
+    if (result == 0)
+    {
+        const char* msg_id = IoTHubMessage_GetMessageId(iothub_message_handle);
+        if (msg_id != NULL)
+        {
+            result = addSystemPropertyToTopicString(topic_string, index, MESSAGE_ID_PROPERTY, msg_id, urlencode);
+            index++;
+        }
+    }
+    // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_010: [ `IoTHubTransport_MQTT_Common_DoWork` shall check for the ContentType property and if found add the `value` as a system property in the format of `$.ct=<value>` ]
+    if (result == 0)
+    {
+        const char* content_type = IoTHubMessage_GetContentTypeSystemProperty(iothub_message_handle);
+        if (content_type != NULL)
+        {
+            result = addSystemPropertyToTopicString(topic_string, index, CONTENT_TYPE_PROPERTY, content_type, urlencode);
+            index++;
+        }
+    }
+    // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_011: [ `IoTHubTransport_MQTT_Common_DoWork` shall check for the ContentEncoding property and if found add the `value` as a system property in the format of `$.ce=<value>` ]
+    if (result == 0)
+    {
+        const char* content_encoding = IoTHubMessage_GetContentEncodingSystemProperty(iothub_message_handle);
+        if (content_encoding != NULL)
+        {
+            // Security message require content encoding
+            result = addSystemPropertyToTopicString(topic_string, index, CONTENT_ENCODING_PROPERTY, content_encoding, is_security_msg ? true : urlencode);
+            index++;
+        }
+    }
+    if (result == 0)
+    {
+        if (is_security_msg)
+        {
+            // The Security interface Id value must be encoded
+            if (addSystemPropertyToTopicString(topic_string, index++, SECURITY_INTERFACE_ID_MQTT, SECURITY_INTERFACE_ID_VALUE, true) != 0)
+            {
+                LogError("Failed setting Security interface id");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                result = 0;
+            }
+        }
+    }
+    *index_ptr = index;
+    return result;
+}
+
+static int addDiagnosticPropertiesTouMqttMessage(IOTHUB_MESSAGE_HANDLE iothub_message_handle, STRING_HANDLE topic_string, size_t* index_ptr)
+{
+    int result = 0;
+    size_t index = *index_ptr;
+
+    // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_014: [ `IoTHubTransport_MQTT_Common_DoWork` shall check for the diagnostic properties including diagid and diagCreationTimeUtc and if found both add them as system property in the format of `$.diagid` and `$.diagctx` respectively]
+    const IOTHUB_MESSAGE_DIAGNOSTIC_PROPERTY_DATA* diagnosticData = IoTHubMessage_GetDiagnosticPropertyData(iothub_message_handle);
+    if (diagnosticData != NULL)
+    {
+        const char* diag_id = diagnosticData->diagnosticId;
+        const char* creation_time_utc = diagnosticData->diagnosticCreationTimeUtc;
+        //diagid and creationtimeutc must be present/unpresent simultaneously
+        if (diag_id != NULL && creation_time_utc != NULL)
+        {
+            if (STRING_sprintf(topic_string, "%s%%24.%s=%s", index == 0 ? "" : PROPERTY_SEPARATOR, DIAGNOSTIC_ID_PROPERTY, diag_id) != 0)
+            {
+                LogError("Failed setting diagnostic id");
+                result = MU_FAILURE;
+            }
+            index++;
+
+            if (result == 0)
+            {
+                //construct diagnostic context, it should be urlencode(key1=value1,key2=value2)
+                STRING_HANDLE diagContextHandle = STRING_construct_sprintf("%s=%s", DIAGNOSTIC_CONTEXT_CREATION_TIME_UTC_PROPERTY, creation_time_utc);
+                if (diagContextHandle == NULL)
+                {
+                    LogError("Failed constructing diagnostic context");
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    //Add other diagnostic context properties here if have more
+                    STRING_HANDLE encodedContextValueHandle = URL_Encode(diagContextHandle);
+                    const char* encodedContextValueString = NULL;
+                    if (encodedContextValueHandle != NULL &&
+                        (encodedContextValueString = STRING_c_str(encodedContextValueHandle)) != NULL)
+                    {
+                        if (STRING_sprintf(topic_string, "%s%%24.%s=%s", index == 0 ? "" : PROPERTY_SEPARATOR, DIAGNOSTIC_CONTEXT_PROPERTY, encodedContextValueString) != 0)
+                        {
+                            LogError("Failed setting diagnostic context");
+                            result = MU_FAILURE;
+                        }
+                        STRING_delete(encodedContextValueHandle);
+                        encodedContextValueHandle = NULL;
+                    }
+                    else
+                    {
+                        LogError("Failed encoding diagnostic context value");
+                        result = MU_FAILURE;
+                    }
+                    STRING_delete(diagContextHandle);
+                    diagContextHandle = NULL;
+                    index++;
+                }
+            }
+        }
+        else if (diag_id != NULL || creation_time_utc != NULL)
+        {
+            // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_015: [ `IoTHubTransport_MQTT_Common_DoWork` shall check whether diagid and diagCreationTimeUtc be present simultaneously, treat as error if not]
+            LogError("diagid and diagcreationtimeutc must be present simultaneously.");
+            result = MU_FAILURE;
+        }
+    }
+    return result;
+}
+
+
+static STRING_HANDLE addPropertiesTouMqttMessage(IOTHUB_MESSAGE_HANDLE iothub_message_handle, const char* eventTopic, bool urlencode)
+{
+    size_t index = 0;
+    STRING_HANDLE result = STRING_construct(eventTopic);
+    if (result == NULL)
+    {
+        LogError("Failed to create event topic string handle");
+    }
+    else if (addUserPropertiesTouMqttMessage(iothub_message_handle, result, &index, urlencode) != 0)
+    {
+        LogError("Failed adding Properties to uMQTT Message");
+        STRING_delete(result);
+        result = NULL;
+    }
+    else if (addSystemPropertiesTouMqttMessage(iothub_message_handle, result, &index, urlencode) != 0)
+    {
+        LogError("Failed adding System Properties to uMQTT Message");
+        STRING_delete(result);
+        result = NULL;
+    }
+    else if (addDiagnosticPropertiesTouMqttMessage(iothub_message_handle, result, &index) != 0)
+    {
+        LogError("Failed adding Diagnostic Properties to uMQTT Message");
+        STRING_delete(result);
+        result = NULL;
+    }
+
+    // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_060: [ `IoTHubTransport_MQTT_Common_DoWork` shall check for the OutputName property and if found add the value as a system property in the format of $.on=<value> ]
+    if (result != NULL)
+    {
+        const char* output_name = IoTHubMessage_GetOutputName(iothub_message_handle);
+        if (output_name != NULL)
+        {
+            if (STRING_sprintf(result, "%s%%24.on=%s/", index == 0 ? "" : PROPERTY_SEPARATOR, output_name) != 0)
+            {
+                LogError("Failed setting output name.");
+                STRING_delete(result);
+                result = NULL;
+            }
+            index++;
+        }
+    }
+
+    return result;
+}
+
+static int publish_mqtt_telemetry_msg(PMQTTTRANSPORT_HANDLE_DATA transport_data, MQTT_MESSAGE_DETAILS_LIST* mqttMsgEntry, const unsigned char* payload, size_t len)
+{
+    int result;
+    STRING_HANDLE msgTopic = addPropertiesTouMqttMessage(mqttMsgEntry->iotHubMessageEntry->messageHandle, STRING_c_str(transport_data->topic_MqttEvent), transport_data->auto_url_encode_decode);
+    if (msgTopic == NULL)
+    {
+        LogError("Failed adding properties to mqtt message");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        MQTT_MESSAGE_HANDLE mqttMsg = mqttmessage_create_in_place(mqttMsgEntry->packet_id, STRING_c_str(msgTopic), DELIVER_AT_LEAST_ONCE, payload, len);
+        if (mqttMsg == NULL)
+        {
+            LogError("Failed creating mqtt message");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if (tickcounter_get_current_ms(transport_data->msgTickCounter, &mqttMsgEntry->msgPublishTime) != 0)
+            {
+                LogError("Failed retrieving tickcounter info");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                if (mqtt_client_publish(transport_data->mqttClient, mqttMsg) != 0)
+                {
+                    LogError("Failed attempting to publish mqtt message");
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    mqttMsgEntry->retryCount++;
+                    result = 0;
+                }
+            }
+            mqttmessage_destroy(mqttMsg);
+        }
+        STRING_delete(msgTopic);
+    }
+    return result;
+}
+
+static int publish_device_method_message(MQTTTRANSPORT_HANDLE_DATA* transport_data, int status_code, STRING_HANDLE request_id, const unsigned char* response, size_t response_size)
+{
+    int result;
+    uint16_t packet_id = get_next_packet_id(transport_data);
+
+    STRING_HANDLE msg_topic = STRING_construct_sprintf(DEVICE_METHOD_RESPONSE_TOPIC, status_code, STRING_c_str(request_id));
+    if (msg_topic == NULL)
+    {
+        LogError("Failed constructing message topic.");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        MQTT_MESSAGE_HANDLE mqtt_get_msg = mqttmessage_create_in_place(packet_id, STRING_c_str(msg_topic), DELIVER_AT_MOST_ONCE, response, response_size);
+        if (mqtt_get_msg == NULL)
+        {
+            LogError("Failed constructing mqtt message.");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if (mqtt_client_publish(transport_data->mqttClient, mqtt_get_msg) != 0)
+            {
+                LogError("Failed publishing to mqtt client.");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                result = 0;
+            }
+            mqttmessage_destroy(mqtt_get_msg);
+        }
+        STRING_delete(msg_topic);
+    }
+    return result;
+}
+
+
+static void destroy_device_twin_get_message(MQTT_DEVICE_TWIN_ITEM* msg_entry)
+{
+    free(msg_entry);
+}
+
+static MQTT_DEVICE_TWIN_ITEM* create_device_twin_message(MQTTTRANSPORT_HANDLE_DATA* transport_data, DEVICE_TWIN_MSG_TYPE device_twin_msg_type, uint32_t iothub_msg_id)
+{
+    MQTT_DEVICE_TWIN_ITEM* result;
+    tickcounter_ms_t current_time;
+
+    if (tickcounter_get_current_ms(transport_data->msgTickCounter, &current_time) != 0)
+    {
+        LogError("Failed retrieving tickcounter info");
+        result = NULL;
+    }
+    else if ((result = (MQTT_DEVICE_TWIN_ITEM*)malloc(sizeof(MQTT_DEVICE_TWIN_ITEM))) == NULL)
+    {
+        LogError("Failed allocating device twin data.");
+        result = NULL;
+    }
+    else
+    {
+        memset(result, 0, sizeof(*result));
+        result->msgCreationTime = current_time;
+        result->packet_id = get_next_packet_id(transport_data);
+        result->iothub_msg_id = iothub_msg_id;
+        result->device_twin_msg_type = device_twin_msg_type;
+    }
+
+    return result;
+}
+
+static int publish_device_twin_get_message(MQTTTRANSPORT_HANDLE_DATA* transport_data, MQTT_DEVICE_TWIN_ITEM* mqtt_info)
+{
+    int result;
+
+    STRING_HANDLE msg_topic = STRING_construct_sprintf(GET_PROPERTIES_TOPIC, mqtt_info->packet_id);
+    if (msg_topic == NULL)
+    {
+        LogError("Failed constructing get Prop topic.");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        MQTT_MESSAGE_HANDLE mqtt_get_msg = mqttmessage_create(mqtt_info->packet_id, STRING_c_str(msg_topic), DELIVER_AT_MOST_ONCE, NULL, 0);
+        if (mqtt_get_msg == NULL)
+        {
+            LogError("Failed constructing mqtt message.");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if (mqtt_client_publish(transport_data->mqttClient, mqtt_get_msg) != 0)
+            {
+                LogError("Failed publishing to mqtt client.");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                DList_InsertTailList(&transport_data->ack_waiting_queue, &mqtt_info->entry);
+                result = 0;
+            }
+            mqttmessage_destroy(mqtt_get_msg);
+        }
+        STRING_delete(msg_topic);
+    }
+
+    return result;
+}
+
+static void sendPendingGetTwinRequests(PMQTTTRANSPORT_HANDLE_DATA transportData)
+{
+    PDLIST_ENTRY dev_twin_item = transportData->pending_get_twin_queue.Flink;
+
+    while (dev_twin_item != &transportData->pending_get_twin_queue)
+    {
+        DLIST_ENTRY saveListEntry;
+        saveListEntry.Flink = dev_twin_item->Flink;
+        MQTT_DEVICE_TWIN_ITEM* msg_entry = containingRecord(dev_twin_item, MQTT_DEVICE_TWIN_ITEM, entry);
+        (void)DList_RemoveEntryList(dev_twin_item);
+
+        if (publish_device_twin_get_message(transportData, msg_entry) != 0)
+        {
+            LogError("Failed sending pending get twin request");
+            destroy_device_twin_get_message(msg_entry);
+        }
+        else
+        {
+            transportData->device_twin_get_sent = true;
+        }
+
+        dev_twin_item = saveListEntry.Flink;
+    }
+}
+
+
+static void removeExpiredTwinRequestsFromList(PMQTTTRANSPORT_HANDLE_DATA transport_data, tickcounter_ms_t current_ms, DLIST_ENTRY* twin_list)
+{
+    PDLIST_ENTRY list_item = twin_list->Flink;
+    
+    while (list_item != twin_list)
+    {
+        DLIST_ENTRY next_list_item;
+        next_list_item.Flink = list_item->Flink;
+        MQTT_DEVICE_TWIN_ITEM* msg_entry = containingRecord(list_item, MQTT_DEVICE_TWIN_ITEM, entry);
+        bool item_timed_out = false;
+
+        if ((msg_entry->device_twin_msg_type == RETRIEVE_PROPERTIES) &&
+            (((current_ms - msg_entry->msgCreationTime) / 1000) >= ON_DEMAND_GET_TWIN_REQUEST_TIMEOUT_SECS))
+        {
+            item_timed_out = true;
+            if (msg_entry->userCallback != NULL)
+            {
+                msg_entry->userCallback(DEVICE_TWIN_UPDATE_COMPLETE, NULL, 0, msg_entry->userContext);
+            }
+        }
+        else if ((msg_entry->device_twin_msg_type == REPORTED_STATE) &&
+                 (((current_ms - msg_entry->msgCreationTime) / 1000) >= TWIN_REPORT_UPDATE_TIMEOUT_SECS))
+        {
+            item_timed_out = true;
+            transport_data->transport_callbacks.twin_rpt_state_complete_cb(msg_entry->iothub_msg_id, STATUS_CODE_TIMEOUT_VALUE, transport_data->transport_ctx);
+        }
+
+        if (item_timed_out)
+        {
+            (void)DList_RemoveEntryList(list_item);
+            destroy_device_twin_get_message(msg_entry);
+        }
+
+        list_item = next_list_item.Flink;
+    }
+
+}
+
+static void removeExpiredTwinRequests(PMQTTTRANSPORT_HANDLE_DATA transport_data)
+{
+    tickcounter_ms_t current_ms;
+
+    if (tickcounter_get_current_ms(transport_data->msgTickCounter, &current_ms) == 0)
+    {
+        removeExpiredTwinRequestsFromList(transport_data, current_ms, &transport_data->pending_get_twin_queue);
+        removeExpiredTwinRequestsFromList(transport_data, current_ms, &transport_data->ack_waiting_queue);
+    }
+}
+
+static int publish_device_twin_message(MQTTTRANSPORT_HANDLE_DATA* transport_data, IOTHUB_DEVICE_TWIN* device_twin_info, MQTT_DEVICE_TWIN_ITEM* mqtt_info)
+{
+    int result;
+
+    STRING_HANDLE msgTopic = STRING_construct_sprintf(REPORTED_PROPERTIES_TOPIC, mqtt_info->packet_id);
+    if (msgTopic == NULL)
+    {
+        LogError("Failed constructing reported prop topic.");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        const CONSTBUFFER* data_buff;
+        if ((data_buff = CONSTBUFFER_GetContent(device_twin_info->report_data_handle)) == NULL)
+        {
+            LogError("Failed retrieving buffer content");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            MQTT_MESSAGE_HANDLE mqtt_rpt_msg = mqttmessage_create_in_place(mqtt_info->packet_id, STRING_c_str(msgTopic), DELIVER_AT_MOST_ONCE, data_buff->buffer, data_buff->size);
+            if (mqtt_rpt_msg == NULL)
+            {
+                LogError("Failed creating mqtt message");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                if (tickcounter_get_current_ms(transport_data->msgTickCounter, &mqtt_info->msgPublishTime) != 0)
+                {
+                    LogError("Failed retrieving tickcounter info");
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    if (mqtt_client_publish(transport_data->mqttClient, mqtt_rpt_msg) != 0)
+                    {
+                        LogError("Failed publishing mqtt message");
+                        result = MU_FAILURE;
+                    }
+                    else
+                    {
+                        mqtt_info->retryCount++;
+                        result = 0;
+                    }
+                }
+                mqttmessage_destroy(mqtt_rpt_msg);
+            }
+        }
+        STRING_delete(msgTopic);
+    }
+    return result;
+}
+
+static void changeStateToSubscribeIfAllowed(PMQTTTRANSPORT_HANDLE_DATA transport_data)
+{
+    if (transport_data->currPacketState != CONNACK_TYPE &&
+        transport_data->currPacketState != CONNECT_TYPE &&
+        transport_data->currPacketState != DISCONNECT_TYPE &&
+        transport_data->currPacketState != PACKET_TYPE_ERROR)
+    {
+        transport_data->currPacketState = SUBSCRIBE_TYPE;
+    }
+}
+
+static int subscribeToNotifyStateIfNeeded(PMQTTTRANSPORT_HANDLE_DATA transport_data)
+{
+    int result;
+
+    if (transport_data->topic_NotifyState == NULL)
+    {
+        transport_data->topic_NotifyState = STRING_construct(TOPIC_NOTIFICATION_STATE);
+        if (transport_data->topic_NotifyState == NULL)
+        {
+            LogError("Failure: unable constructing notify state topic");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            transport_data->topics_ToSubscribe |= SUBSCRIBE_NOTIFICATION_STATE_TOPIC;
+            result = 0;
+        }
+    }
+    else
+    {
+        result = 0;
+    }
+
+    if (result == 0)
+    {
+        changeStateToSubscribeIfAllowed(transport_data);
+    }
+
+    return result;
+}
+
+
+static bool isSystemProperty(const char* tokenData)
+{
+    bool result = false;
+    size_t propCount = sizeof(sysPropList) / sizeof(sysPropList[0]);
+    size_t index = 0;
+    for (index = 0; index < propCount; index++)
+    {
+        if (memcmp(tokenData, sysPropList[index].propName, sysPropList[index].propLength) == 0)
+        {
+            result = true;
+            break;
+        }
+    }
+    return result;
+}
+
+// Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_061: [ If the message is sent to an input queue, `IoTHubTransport_MQTT_Common_DoWork` shall parse out to the input queue name and store it in the message with IoTHubMessage_SetInputName ]
+// Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_062: [ If IoTHubTransport_MQTT_Common_DoWork receives a malformatted inputQueue, it shall fail ]
+static int addInputNamePropertyToMessage(IOTHUB_MESSAGE_HANDLE IoTHubMessage, const char* topic_name)
+{
+    int result = MU_FAILURE;
+    int number_tokens_read = 0;
+
+    STRING_TOKENIZER_HANDLE token_handle = STRING_TOKENIZER_create_from_char(topic_name);
+    if (token_handle == NULL)
+    {
+        LogError("STRING_TOKENIZER_create_from_char failed\n");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        STRING_HANDLE token_value;
+        if ((token_value = STRING_new()) == NULL)
+        {
+            LogError("Failed allocating token_value");
+        }
+        else
+        {
+            while (STRING_TOKENIZER_get_next_token(token_handle, token_value, "/") == 0)
+            {
+                number_tokens_read++;
+                if (number_tokens_read == (slashes_to_reach_input_name + 1))
+                {
+                    if ((IOTHUB_MESSAGE_OK != IoTHubMessage_SetInputName(IoTHubMessage, STRING_c_str(token_value))))
+                    {
+                        LogError("Failed adding input name to msg");
+                        result = MU_FAILURE;
+                    }
+                    else
+                    {
+                        result = 0;
+                    }
+                    break;
+                }
+            }
+        }
+        STRING_delete(token_value);
+
+        if (number_tokens_read != (slashes_to_reach_input_name + 1))
+        {
+            LogError("Not enough '/' to contain input name.  Got %d, need at least %d", number_tokens_read, (slashes_to_reach_input_name + 1));
+            result = MU_FAILURE;
+        }
+        STRING_TOKENIZER_destroy(token_handle);
+    }
+
+    return result;
+}
+
+static int setMqttMessagePropertyIfPossible(IOTHUB_MESSAGE_HANDLE IoTHubMessage, const char* propName, const char* propValue, size_t nameLen)
+{
+    // Not finding a system property to map to isn't an error.
+    int result = 0;
+
+    if (nameLen > 4)
+    {
+        if (strcmp((const char*)&propName[nameLen - 4], CONNECTION_DEVICE_ID) == 0)
+        {
+            // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_063: [ If type is IOTHUB_TYPE_TELEMETRY and the system property `$.cdid` is defined, its value shall be set on the IOTHUB_MESSAGE_HANDLE's ConnectionDeviceId property ]
+            if (IoTHubMessage_SetConnectionDeviceId(IoTHubMessage, propValue) != IOTHUB_MESSAGE_OK)
+            {
+                LogError("Failed to set IOTHUB_MESSAGE_HANDLE 'messageId' property.");
+                result = MU_FAILURE;
+            }
+            return result;
+        }
+        if (strcmp((const char*)&propName[nameLen - 4], CONNECTION_MODULE_ID_PROPERTY) == 0)
+        {
+            // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_064: [ If type is IOTHUB_TYPE_TELEMETRY and the system property `$.cmid` is defined, its value shall be set on the IOTHUB_MESSAGE_HANDLE's ConnectionModuleId property ]
+            if (IoTHubMessage_SetConnectionModuleId(IoTHubMessage, propValue) != IOTHUB_MESSAGE_OK)
+            {
+                LogError("Failed to set IOTHUB_MESSAGE_HANDLE 'correlationId' property.");
+                result = MU_FAILURE;
+            }
+            return result;
+        }
+    }
+    if (nameLen > 3)
+    {
+        if (strcmp((const char*)&propName[nameLen - 3], MESSAGE_ID_PROPERTY) == 0)
+        {
+            if (IoTHubMessage_SetMessageId(IoTHubMessage, propValue) != IOTHUB_MESSAGE_OK)
+            {
+                LogError("Failed to set IOTHUB_MESSAGE_HANDLE 'messageId' property.");
+                result = MU_FAILURE;
+            }
+            return result;
+        }
+        else if (strcmp((const char*)&propName[nameLen - 3], CORRELATION_ID_PROPERTY) == 0)
+        {
+            if (IoTHubMessage_SetCorrelationId(IoTHubMessage, propValue) != IOTHUB_MESSAGE_OK)
+            {
+                LogError("Failed to set IOTHUB_MESSAGE_HANDLE 'correlationId' property.");
+                result = MU_FAILURE;
+            }
+            return result;
+        }
+    }
+
+    if (nameLen > 2)
+    {
+        // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_012: [ If type is IOTHUB_TYPE_TELEMETRY and the system property `$.ct` is defined, its value shall be set on the IOTHUB_MESSAGE_HANDLE's ContentType property ]
+        if (strcmp((const char*)&propName[nameLen - 2], CONTENT_TYPE_PROPERTY) == 0)
+        {
+            if (IoTHubMessage_SetContentTypeSystemProperty(IoTHubMessage, propValue) != IOTHUB_MESSAGE_OK)
+            {
+                LogError("Failed to set IOTHUB_MESSAGE_HANDLE 'customContentType' property.");
+                result = MU_FAILURE;
+            }
+            return result;
+        }
+        // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_013: [ If type is IOTHUB_TYPE_TELEMETRY and the system property `$.ce` is defined, its value shall be set on the IOTHUB_MESSAGE_HANDLE's ContentEncoding property ]
+        else if (strcmp((const char*)&propName[nameLen - 2], CONTENT_ENCODING_PROPERTY) == 0)
+        {
+            if (IoTHubMessage_SetContentEncodingSystemProperty(IoTHubMessage, propValue) != IOTHUB_MESSAGE_OK)
+            {
+                LogError("Failed to set IOTHUB_MESSAGE_HANDLE 'contentEncoding' property.");
+                result = MU_FAILURE;
+            }
+            return result;
+        }
+    }
+
+    return result;
+}
+
+static int extractMqttProperties(IOTHUB_MESSAGE_HANDLE IoTHubMessage, const char* topic_name, bool urldecode)
+{
+    int result;
+    STRING_TOKENIZER_HANDLE token = STRING_TOKENIZER_create_from_char(topic_name);
+    if (token != NULL)
+    {
+        MAP_HANDLE propertyMap = IoTHubMessage_Properties(IoTHubMessage);
+        if (propertyMap == NULL)
+        {
+            LogError("Failure to retrieve IoTHubMessage_properties.");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            STRING_HANDLE output = STRING_new();
+            if (output == NULL)
+            {
+                LogError("Failure to allocate STRING_new.");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                result = 0;
+
+                while (STRING_TOKENIZER_get_next_token(token, output, PROPERTY_SEPARATOR) == 0 && result == 0)
+                {
+                    const char* tokenData = STRING_c_str(output);
+                    size_t tokenLen = strlen(tokenData);
+                    if (tokenData == NULL || tokenLen == 0)
+                    {
+                        break;
+                    }
+                    else
+                    {
+                        if (isSystemProperty(tokenData))
+                        {
+                            const char* iterator = tokenData;
+                            while (iterator != NULL && *iterator != '\0' && result == 0)
+                            {
+                                if (*iterator == '=')
+                                {
+                                    char* propName = NULL;
+                                    char* propValue = NULL;
+                                    size_t nameLen = iterator - tokenData;
+                                    size_t valLen = tokenLen - (nameLen + 1) + 1;
+
+                                    if ((propName = malloc(nameLen + 1)) == NULL || (propValue = malloc(valLen + 1)) == NULL)
+                                    {
+                                        LogError("Failed allocating property name (%p) and/or value (%p)", propName, propValue);
+                                        free(propName);
+                                        result = MU_FAILURE;
+                                    }
+                                    else
+                                    {
+                                        memcpy(propName, tokenData, nameLen);
+                                        propName[nameLen] = '\0';
+
+                                        memcpy(propValue, iterator + 1, valLen);
+                                        propValue[valLen] = '\0';
+
+                                        if (urldecode)
+                                        {
+                                            STRING_HANDLE propValue_decoded;
+                                            if ((propValue_decoded = URL_DecodeString(propValue)) == NULL)
+                                            {
+                                                LogError("Failed to URL decode property value");
+                                                result = MU_FAILURE;
+                                            }
+                                            else if (setMqttMessagePropertyIfPossible(IoTHubMessage, propName, STRING_c_str(propValue_decoded), nameLen) != 0)
+                                            {
+                                                LogError("Unable to set message property");
+                                                result = MU_FAILURE;
+                                            }
+                                            STRING_delete(propValue_decoded);
+                                        }
+                                        else
+                                        {
+                                            if (setMqttMessagePropertyIfPossible(IoTHubMessage, propName, propValue, nameLen) != 0)
+                                            {
+                                                LogError("Unable to set message property");
+                                                result = MU_FAILURE;
+                                            }
+                                        }
+                                        free(propName);
+                                        free(propValue);
+                                    }
+                                    break;
+                                }
+                                iterator++;
+                            }
+                        }
+                        else //User Properties
+                        {
+                            const char* iterator = tokenData;
+                            while (iterator != NULL && *iterator != '\0' && result == 0)
+                            {
+                                if (*iterator == '=')
+                                {
+                                    char* propName = NULL;
+                                    char* propValue = NULL;
+                                    size_t nameLen = iterator - tokenData;
+                                    size_t valLen = tokenLen - (nameLen + 1) + 1;
+
+                                    if ((propName = (char*)malloc(nameLen + 1)) == NULL || (propValue = (char*)malloc(valLen + 1)) == NULL)
+                                    {
+                                        free(propName);
+                                        LogError("Failed allocating property information");
+                                        result = MU_FAILURE;
+                                    }
+                                    else
+                                    {
+                                        memcpy(propName, tokenData, nameLen);
+                                        propName[nameLen] = '\0';
+
+                                        memcpy(propValue, iterator + 1, valLen);
+                                        propValue[valLen] = '\0';
+
+                                        if (urldecode)
+                                        {
+                                            STRING_HANDLE propName_decoded = URL_DecodeString(propName);
+                                            STRING_HANDLE propValue_decoded = URL_DecodeString(propValue);
+                                            if (propName_decoded == NULL || propValue_decoded == NULL)
+                                            {
+                                                LogError("Failed to URL decode property");
+                                                result = MU_FAILURE;
+                                            }
+                                            else if (Map_AddOrUpdate(propertyMap, STRING_c_str(propName_decoded), STRING_c_str(propValue_decoded)) != MAP_OK)
+                                            {
+                                                LogError("Map_AddOrUpdate failed.");
+                                                result = MU_FAILURE;
+                                            }
+                                            STRING_delete(propName_decoded);
+                                            STRING_delete(propValue_decoded);
+                                        }
+                                        else
+                                        {
+                                            if (Map_AddOrUpdate(propertyMap, propName, propValue) != MAP_OK)
+                                            {
+                                                LogError("Map_AddOrUpdate failed.");
+                                                result = MU_FAILURE;
+                                            }
+                                        }
+                                        free(propName);
+                                        free(propValue);
+                                    }
+                                    break;
+                                }
+                                iterator++;
+                            }
+                        }
+                    }
+                }
+                STRING_delete(output);
+            }
+        }
+        STRING_TOKENIZER_destroy(token);
+    }
+    else
+    {
+        LogError("Unable to create Tokenizer object.");
+        result = MU_FAILURE;
+    }
+    return result;
+}
+
+static void mqtt_notification_callback(MQTT_MESSAGE_HANDLE msgHandle, void* callbackCtx)
+{
+    /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_051: [ If msgHandle or callbackCtx is NULL, mqtt_notification_callback shall do nothing. ] */
+    if (msgHandle != NULL && callbackCtx != NULL)
+    {
+        /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_052: [ mqtt_notification_callback shall extract the topic Name from the MQTT_MESSAGE_HANDLE. ] */
+        const char* topic_resp = mqttmessage_getTopicName(msgHandle);
+        if (topic_resp == NULL)
+        {
+            LogError("Failure: NULL topic name encountered");
+        }
+        else
+        {
+            PMQTTTRANSPORT_HANDLE_DATA transportData = (PMQTTTRANSPORT_HANDLE_DATA)callbackCtx;
+
+            IOTHUB_IDENTITY_TYPE type = retrieve_topic_type(topic_resp, STRING_c_str(transportData->topic_InputQueue));
+            if (type == IOTHUB_TYPE_DEVICE_TWIN)
+            {
+                size_t request_id;
+                int status_code;
+                bool notification_msg;
+                if (parse_device_twin_topic_info(topic_resp, &notification_msg, &request_id, &status_code) != 0)
+                {
+                    LogError("Failure: parsing device topic info");
+                }
+                else
+                {
+                    const APP_PAYLOAD* payload = mqttmessage_getApplicationMsg(msgHandle);
+                    if (notification_msg)
+                    {
+                        transportData->transport_callbacks.twin_retrieve_prop_complete_cb(DEVICE_TWIN_UPDATE_PARTIAL, payload->message, payload->length, transportData->transport_ctx);
+                    }
+                    else
+                    {
+                        PDLIST_ENTRY dev_twin_item = transportData->ack_waiting_queue.Flink;
+                        while (dev_twin_item != &transportData->ack_waiting_queue)
+                        {
+                            DLIST_ENTRY saveListEntry;
+                            saveListEntry.Flink = dev_twin_item->Flink;
+                            MQTT_DEVICE_TWIN_ITEM* msg_entry = containingRecord(dev_twin_item, MQTT_DEVICE_TWIN_ITEM, entry);
+                            if (request_id == msg_entry->packet_id)
+                            {
+                                (void)DList_RemoveEntryList(dev_twin_item);
+                                if (msg_entry->device_twin_msg_type == RETRIEVE_PROPERTIES)
+                                {
+                                    if (msg_entry->userCallback == NULL)
+                                    {
+                                        /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_054: [ If type is IOTHUB_TYPE_DEVICE_TWIN, then on success if msg_type is RETRIEVE_PROPERTIES then mqtt_notification_callback shall call IoTHubClientCore_LL_RetrievePropertyComplete... ] */
+                                        transportData->transport_callbacks.twin_retrieve_prop_complete_cb(DEVICE_TWIN_UPDATE_COMPLETE, payload->message, payload->length, transportData->transport_ctx);
+                                        // Only after receiving device twin request should we start listening for patches.
+                                        (void)subscribeToNotifyStateIfNeeded(transportData);
+                                    }
+                                    else
+                                    {
+                                        // This is a on-demand get twin request.
+                                        msg_entry->userCallback(DEVICE_TWIN_UPDATE_COMPLETE, payload->message, payload->length, msg_entry->userContext);
+                                    }
+                                }
+                                else
+                                {
+                                    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_055: [ if device_twin_msg_type is not RETRIEVE_PROPERTIES then mqtt_notification_callback shall call IoTHubClientCore_LL_ReportedStateComplete ] */
+                                    transportData->transport_callbacks.twin_rpt_state_complete_cb(msg_entry->iothub_msg_id, status_code, transportData->transport_ctx);
+                                    // Only after receiving device twin request should we start listening for patches.
+                                    (void)subscribeToNotifyStateIfNeeded(transportData);
+                                }
+
+                                destroy_device_twin_get_message(msg_entry);
+                                break;
+                            }
+                            dev_twin_item = saveListEntry.Flink;
+                        }
+                    }
+                }
+            }
+            else if (type == IOTHUB_TYPE_DEVICE_METHODS)
+            {
+                STRING_HANDLE method_name = STRING_new();
+                if (method_name == NULL)
+                {
+                    LogError("Failure: allocating method_name string value");
+                }
+                else
+                {
+                    DEVICE_METHOD_INFO* dev_method_info = malloc(sizeof(DEVICE_METHOD_INFO));
+                    if (dev_method_info == NULL)
+                    {
+                        LogError("Failure: allocating DEVICE_METHOD_INFO object");
+                    }
+                    else
+                    {
+                        dev_method_info->request_id = STRING_new();
+                        if (dev_method_info->request_id == NULL)
+                        {
+                            LogError("Failure constructing request_id string");
+                            free(dev_method_info);
+                        }
+                        else if (retrieve_device_method_rid_info(topic_resp, method_name, dev_method_info->request_id) != 0)
+                        {
+                            LogError("Failure: retrieve device topic info");
+                            STRING_delete(dev_method_info->request_id);
+                            free(dev_method_info);
+                        }
+                        else
+                        {
+                            /* CodesSRS_IOTHUB_MQTT_TRANSPORT_07_053: [ If type is IOTHUB_TYPE_DEVICE_METHODS, then on success mqtt_notification_callback shall call IoTHubClientCore_LL_DeviceMethodComplete. ] */
+                            const APP_PAYLOAD* payload = mqttmessage_getApplicationMsg(msgHandle);
+                            if (transportData->transport_callbacks.method_complete_cb(STRING_c_str(method_name), payload->message, payload->length, (void*)dev_method_info, transportData->transport_ctx) != 0)
+                            {
+                                LogError("Failure: IoTHubClientCore_LL_DeviceMethodComplete");
+                                STRING_delete(dev_method_info->request_id);
+                                free(dev_method_info);
+                            }
+                        }
+                    }
+                    STRING_delete(method_name);
+                }
+            }
+            else
+            {
+                const APP_PAYLOAD* appPayload = mqttmessage_getApplicationMsg(msgHandle);
+                IOTHUB_MESSAGE_HANDLE IoTHubMessage = IoTHubMessage_CreateFromByteArray(appPayload->message, appPayload->length);
+                if (IoTHubMessage == NULL)
+                {
+                    LogError("Failure: IotHub Message creation has failed.");
+                }
+                else
+                {
+                    if ((type == IOTHUB_TYPE_EVENT_QUEUE) && (addInputNamePropertyToMessage(IoTHubMessage, topic_resp) != 0))
+                    {
+                        LogError("failure adding input name to property.");
+                    }
+                    // Will need to update this when the service has messages that can be rejected
+                    else if (extractMqttProperties(IoTHubMessage, topic_resp, transportData->auto_url_encode_decode) != 0)
+                    {
+                        LogError("failure extracting mqtt properties.");
+                    }
+                    else
+                    {
+                        MESSAGE_CALLBACK_INFO* messageData = (MESSAGE_CALLBACK_INFO*)malloc(sizeof(MESSAGE_CALLBACK_INFO));
+                        if (messageData == NULL)
+                        {
+                            LogError("malloc failed");
+                        }
+                        else
+                        {
+                            messageData->messageHandle = IoTHubMessage;
+                            messageData->transportContext = NULL;
+
+                            if (type == IOTHUB_TYPE_EVENT_QUEUE)
+                            {
+                                // Codes_SRS_IOTHUB_MQTT_TRANSPORT_31_065: [ If type is IOTHUB_TYPE_TELEMETRY and sent to an input queue, then on success `mqtt_notification_callback` shall call `IoTHubClient_LL_MessageCallback`. ]
+                                if (!transportData->transport_callbacks.msg_input_cb(messageData, transportData->transport_ctx))
+                                {
+                                    LogError("IoTHubClientCore_LL_MessageCallbackreturned false");
+
+                                    IoTHubMessage_Destroy(IoTHubMessage);
+                                    free(messageData);
+                                }
+                            }
+                            else
+                            {
+                                /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_056: [ If type is IOTHUB_TYPE_TELEMETRY, then on success mqtt_notification_callback shall call IoTHubClientCore_LL_MessageCallback. ] */
+                                if (!transportData->transport_callbacks.msg_cb(messageData, transportData->transport_ctx))
+                                {
+                                    LogError("IoTHubClientCore_LL_MessageCallback returned false");
+                                    IoTHubMessage_Destroy(IoTHubMessage);
+                                    free(messageData);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+static void mqtt_operation_complete_callback(MQTT_CLIENT_HANDLE handle, MQTT_CLIENT_EVENT_RESULT actionResult, const void* msgInfo, void* callbackCtx)
+{
+    (void)handle;
+    if (callbackCtx != NULL)
+    {
+        PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)callbackCtx;
+
+        switch (actionResult)
+        {
+            case MQTT_CLIENT_ON_PUBLISH_ACK:
+            case MQTT_CLIENT_ON_PUBLISH_COMP:
+            {
+                const PUBLISH_ACK* puback = (const PUBLISH_ACK*)msgInfo;
+                if (puback != NULL)
+                {
+                    PDLIST_ENTRY currentListEntry = transport_data->telemetry_waitingForAck.Flink;
+                    while (currentListEntry != &transport_data->telemetry_waitingForAck)
+                    {
+                        MQTT_MESSAGE_DETAILS_LIST* mqttMsgEntry = containingRecord(currentListEntry, MQTT_MESSAGE_DETAILS_LIST, entry);
+                        DLIST_ENTRY saveListEntry;
+                        saveListEntry.Flink = currentListEntry->Flink;
+
+                        if (puback->packetId == mqttMsgEntry->packet_id)
+                        {
+                            (void)DList_RemoveEntryList(currentListEntry); //First remove the item from Waiting for Ack List.
+                            sendMsgComplete(mqttMsgEntry->iotHubMessageEntry, transport_data, IOTHUB_CLIENT_CONFIRMATION_OK);
+                            free(mqttMsgEntry);
+                        }
+                        currentListEntry = saveListEntry.Flink;
+                    }
+                }
+                else
+                {
+                    LogError("Failure: MQTT_CLIENT_ON_PUBLISH_ACK publish_ack structure NULL.");
+                }
+                break;
+            }
+            case MQTT_CLIENT_ON_CONNACK:
+            {
+                const CONNECT_ACK* connack = (const CONNECT_ACK*)msgInfo;
+                if (connack != NULL)
+                {
+                    if (connack->returnCode == CONNECTION_ACCEPTED)
+                    {
+                        // The connect packet has been acked
+                        transport_data->currPacketState = CONNACK_TYPE;
+                        transport_data->isRecoverableError = true;
+                        transport_data->mqttClientStatus = MQTT_CLIENT_STATUS_CONNECTED;
+
+                        // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_008: [ Upon successful connection the retry control shall be reset using retry_control_reset() ]
+                        retry_control_reset(transport_data->retry_control_handle);
+
+                        transport_data->transport_callbacks.connection_status_cb(IOTHUB_CLIENT_CONNECTION_AUTHENTICATED, IOTHUB_CLIENT_CONNECTION_OK, transport_data->transport_ctx);
+                    }
+                    else
+                    {
+                        if (connack->returnCode == CONN_REFUSED_SERVER_UNAVAIL)
+                        {
+                            transport_data->transport_callbacks.connection_status_cb(IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_DEVICE_DISABLED, transport_data->transport_ctx);
+                        }
+                        else if (connack->returnCode == CONN_REFUSED_BAD_USERNAME_PASSWORD || connack->returnCode == CONN_REFUSED_ID_REJECTED)
+                        {
+                            transport_data->isRecoverableError = false;
+                            transport_data->transport_callbacks.connection_status_cb(IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_BAD_CREDENTIAL, transport_data->transport_ctx);
+                        }
+                        else if (connack->returnCode == CONN_REFUSED_NOT_AUTHORIZED)
+                        {
+                            transport_data->transport_callbacks.connection_status_cb(IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_BAD_CREDENTIAL, transport_data->transport_ctx);
+                        }
+                        else if (connack->returnCode == CONN_REFUSED_UNACCEPTABLE_VERSION)
+                        {
+                            transport_data->isRecoverableError = false;
+                        }
+                        LogError("Connection Not Accepted: 0x%x: %s", connack->returnCode, retrieve_mqtt_return_codes(connack->returnCode));
+                        transport_data->mqttClientStatus = MQTT_CLIENT_STATUS_PENDING_CLOSE;
+                        transport_data->currPacketState = PACKET_TYPE_ERROR;
+                    }
+                }
+                else
+                {
+                    LogError("MQTT_CLIENT_ON_CONNACK CONNACK parameter is NULL.");
+                }
+                break;
+            }
+            case MQTT_CLIENT_ON_SUBSCRIBE_ACK:
+            {
+                const SUBSCRIBE_ACK* suback = (const SUBSCRIBE_ACK*)msgInfo;
+                if (suback != NULL)
+                {
+                    size_t index = 0;
+                    for (index = 0; index < suback->qosCount; index++)
+                    {
+                        if (suback->qosReturn[index] == DELIVER_FAILURE)
+                        {
+                            LogError("Subscribe delivery failure of subscribe %lu", (unsigned long)index);
+                        }
+                    }
+                    // The subscribed packet has been acked
+                    transport_data->currPacketState = SUBACK_TYPE;
+
+                    // Is this a twin message
+                    if (suback->packetId == transport_data->twin_resp_packet_id)
+                    {
+                        transport_data->twin_resp_sub_recv = true;
+                    }
+                }
+                else
+                {
+                    LogError("Failure: MQTT_CLIENT_ON_SUBSCRIBE_ACK SUBSCRIBE_ACK parameter is NULL.");
+                }
+                break;
+            }
+            case MQTT_CLIENT_ON_PUBLISH_RECV:
+            case MQTT_CLIENT_ON_PUBLISH_REL:
+            {
+                // Currently not used
+                break;
+            }
+            case MQTT_CLIENT_ON_DISCONNECT:
+            {
+                // Close the client so we can reconnect again
+                transport_data->mqttClientStatus = MQTT_CLIENT_STATUS_NOT_CONNECTED;
+                break;
+            }
+            case MQTT_CLIENT_ON_UNSUBSCRIBE_ACK:
+            case MQTT_CLIENT_ON_PING_RESPONSE:
+            default:
+            {
+                break;
+            }
+        }
+    }
+}
+
+// Prior to creating a new connection, if we have an existing xioTransport that has been connected before
+// we need to clear it now or else cached settings (especially TLS when communicating with HTTP proxies)
+// will break reconnection attempt.
+static void ResetConnectionIfNecessary(PMQTTTRANSPORT_HANDLE_DATA transport_data)
+{
+    if (transport_data->xioTransport != NULL && transport_data->conn_attempted)
+    {
+        OPTIONHANDLER_HANDLE options = xio_retrieveoptions(transport_data->xioTransport);
+        set_saved_tls_options(transport_data, options);
+        DestroyXioTransport(transport_data);
+    }
+}
+
+static void mqtt_disconnect_cb(void* ctx)
+{
+    if (ctx != NULL)
+    {
+        int* disconn_recv = (int*)ctx;
+        *disconn_recv = 1;
+    }
+}
+
+static void DisconnectFromClient(PMQTTTRANSPORT_HANDLE_DATA transport_data)
+{
+    if (transport_data->currPacketState != DISCONNECT_TYPE)
+    {
+        if (!transport_data->isDestroyCalled)
+        {
+            OPTIONHANDLER_HANDLE options = xio_retrieveoptions(transport_data->xioTransport);
+            set_saved_tls_options(transport_data, options);
+        }
+        // Ensure the disconnect message is sent
+        if (transport_data->mqttClientStatus == MQTT_CLIENT_STATUS_CONNECTED)
+        {
+            transport_data->disconnect_recv_flag = 0;
+            (void)mqtt_client_disconnect(transport_data->mqttClient, mqtt_disconnect_cb, &transport_data->disconnect_recv_flag);
+            size_t disconnect_ctr = 0;
+            do
+            {
+                mqtt_client_dowork(transport_data->mqttClient);
+                disconnect_ctr++;
+                ThreadAPI_Sleep(50);
+            } while ((disconnect_ctr < MAX_DISCONNECT_VALUE) && (transport_data->disconnect_recv_flag == 0));
+        }
+        DestroyXioTransport(transport_data);
+
+        transport_data->device_twin_get_sent = false;
+        transport_data->mqttClientStatus = MQTT_CLIENT_STATUS_NOT_CONNECTED;
+        transport_data->currPacketState = DISCONNECT_TYPE;
+    }
+}
+
+static void mqtt_error_callback(MQTT_CLIENT_HANDLE handle, MQTT_CLIENT_EVENT_ERROR error, void* callbackCtx)
+{
+    (void)handle;
+    if (callbackCtx != NULL)
+    {
+        PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)callbackCtx;
+        switch (error)
+        {
+            case MQTT_CLIENT_CONNECTION_ERROR:
+            {
+                transport_data->transport_callbacks.connection_status_cb(IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_NO_NETWORK, transport_data->transport_ctx);
+                break;
+            }
+            case MQTT_CLIENT_COMMUNICATION_ERROR:
+            {
+                transport_data->transport_callbacks.connection_status_cb(IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_COMMUNICATION_ERROR, transport_data->transport_ctx);
+                break;
+            }
+            case MQTT_CLIENT_NO_PING_RESPONSE:
+            {
+                LogError("Mqtt Ping Response was not encountered.  Reconnecting device...");
+                transport_data->transport_callbacks.connection_status_cb(IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_NO_PING_RESPONSE, transport_data->transport_ctx);
+                break;
+            }
+            case MQTT_CLIENT_PARSE_ERROR:
+            case MQTT_CLIENT_MEMORY_ERROR:
+            case MQTT_CLIENT_UNKNOWN_ERROR:
+            default:
+            {
+                LogError("INTERNAL ERROR: unexpected error value received %s", MU_ENUM_TO_STRING(MQTT_CLIENT_EVENT_ERROR, error));
+                break;
+            }
+        }
+        if (transport_data->mqttClientStatus != MQTT_CLIENT_STATUS_PENDING_CLOSE)
+        {
+            // We have encountered an mqtt protocol error in an non-closing state
+            // The best course of action is to execute a shutdown of the mqtt/tls/socket
+            // layer and then attempt to reconnect
+            transport_data->mqttClientStatus = MQTT_CLIENT_STATUS_EXECUTE_DISCONNECT;
+        }
+        transport_data->currPacketState = PACKET_TYPE_ERROR;
+        transport_data->device_twin_get_sent = false;
+        if (transport_data->topic_MqttMessage != NULL)
+        {
+            transport_data->topics_ToSubscribe |= SUBSCRIBE_TELEMETRY_TOPIC;
+        }
+        if (transport_data->topic_GetState != NULL)
+        {
+            transport_data->topics_ToSubscribe |= SUBSCRIBE_GET_REPORTED_STATE_TOPIC;
+        }
+        if (transport_data->topic_NotifyState != NULL)
+        {
+            transport_data->topics_ToSubscribe |= SUBSCRIBE_NOTIFICATION_STATE_TOPIC;
+        }
+        if (transport_data->topic_DeviceMethods != NULL)
+        {
+            transport_data->topics_ToSubscribe |= SUBSCRIBE_DEVICE_METHOD_TOPIC;
+        }
+        if (transport_data->topic_InputQueue != NULL)
+        {
+            transport_data->topics_ToSubscribe |= SUBSCRIBE_INPUT_QUEUE_TOPIC;
+        }
+    }
+    else
+    {
+        LogError("Failure: mqtt called back with null context.");
+    }
+}
+
+static void SubscribeToMqttProtocol(PMQTTTRANSPORT_HANDLE_DATA transport_data)
+{
+    if (transport_data->topics_ToSubscribe != UNSUBSCRIBE_FROM_TOPIC)
+    {
+        uint32_t topic_subscription = 0;
+        size_t subscribe_count = 0;
+        uint16_t packet_id = get_next_packet_id(transport_data);
+        SUBSCRIBE_PAYLOAD subscribe[SUBSCRIBE_TOPIC_COUNT];
+        if ((transport_data->topic_MqttMessage != NULL) && (SUBSCRIBE_TELEMETRY_TOPIC & transport_data->topics_ToSubscribe))
+        {
+            subscribe[subscribe_count].subscribeTopic = STRING_c_str(transport_data->topic_MqttMessage);
+            subscribe[subscribe_count].qosReturn = DELIVER_AT_LEAST_ONCE;
+            topic_subscription |= SUBSCRIBE_TELEMETRY_TOPIC;
+            subscribe_count++;
+        }
+        if ((transport_data->topic_GetState != NULL) && (SUBSCRIBE_GET_REPORTED_STATE_TOPIC & transport_data->topics_ToSubscribe))
+        {
+            subscribe[subscribe_count].subscribeTopic = STRING_c_str(transport_data->topic_GetState);
+            subscribe[subscribe_count].qosReturn = DELIVER_AT_MOST_ONCE;
+            topic_subscription |= SUBSCRIBE_GET_REPORTED_STATE_TOPIC;
+            subscribe_count++;
+            transport_data->twin_resp_packet_id = packet_id;
+        }
+        if ((transport_data->topic_NotifyState != NULL) && (SUBSCRIBE_NOTIFICATION_STATE_TOPIC & transport_data->topics_ToSubscribe))
+        {
+            subscribe[subscribe_count].subscribeTopic = STRING_c_str(transport_data->topic_NotifyState);
+            subscribe[subscribe_count].qosReturn = DELIVER_AT_MOST_ONCE;
+            topic_subscription |= SUBSCRIBE_NOTIFICATION_STATE_TOPIC;
+            subscribe_count++;
+        }
+        if ((transport_data->topic_DeviceMethods != NULL) && (SUBSCRIBE_DEVICE_METHOD_TOPIC & transport_data->topics_ToSubscribe))
+        {
+            subscribe[subscribe_count].subscribeTopic = STRING_c_str(transport_data->topic_DeviceMethods);
+            subscribe[subscribe_count].qosReturn = DELIVER_AT_MOST_ONCE;
+            topic_subscription |= SUBSCRIBE_DEVICE_METHOD_TOPIC;
+            subscribe_count++;
+        }
+        if ((transport_data->topic_InputQueue != NULL) && (SUBSCRIBE_INPUT_QUEUE_TOPIC & transport_data->topics_ToSubscribe))
+        {
+            subscribe[subscribe_count].subscribeTopic = STRING_c_str(transport_data->topic_InputQueue);
+            subscribe[subscribe_count].qosReturn = DELIVER_AT_MOST_ONCE;
+            topic_subscription |= SUBSCRIBE_INPUT_QUEUE_TOPIC;
+            subscribe_count++;
+        }
+
+        if (subscribe_count != 0)
+        {
+            /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_016: [IoTHubTransport_MQTT_Common_Subscribe shall call mqtt_client_subscribe to subscribe to the Message Topic.] */
+            if (mqtt_client_subscribe(transport_data->mqttClient, packet_id, subscribe, subscribe_count) != 0)
+            {
+                /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_017: [Upon failure IoTHubTransport_MQTT_Common_Subscribe shall return a non-zero value.] */
+                LogError("Failure: mqtt_client_subscribe returned error.");
+            }
+            else
+            {
+                /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_018: [On success IoTHubTransport_MQTT_Common_Subscribe shall return 0.] */
+                transport_data->topics_ToSubscribe &= ~topic_subscription;
+                transport_data->currPacketState = SUBSCRIBE_TYPE;
+            }
+        }
+        else
+        {
+            /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_017: [Upon failure IoTHubTransport_MQTT_Common_Subscribe shall return a non-zero value.] */
+            LogError("Failure: subscribe_topic is empty.");
+        }
+        transport_data->currPacketState = SUBSCRIBE_TYPE;
+    }
+    else
+    {
+        transport_data->currPacketState = PUBLISH_TYPE;
+    }
+}
+
+static bool RetrieveMessagePayload(IOTHUB_MESSAGE_HANDLE messageHandle, const unsigned char** payload, size_t* length)
+{
+    bool result;
+    IOTHUBMESSAGE_CONTENT_TYPE contentType = IoTHubMessage_GetContentType(messageHandle);
+    if (contentType == IOTHUBMESSAGE_BYTEARRAY)
+    {
+        if (IoTHubMessage_GetByteArray(messageHandle, &(*payload), length) != IOTHUB_MESSAGE_OK)
+        {
+            LogError("Failure result from IoTHubMessage_GetByteArray");
+            result = false;
+            *length = 0;
+        }
+        else
+        {
+            result = true;
+        }
+    }
+    else if (contentType == IOTHUBMESSAGE_STRING)
+    {
+        *payload = (const unsigned char*)IoTHubMessage_GetString(messageHandle);
+        if (*payload == NULL)
+        {
+            LogError("Failure result from IoTHubMessage_GetString");
+            result = false;
+            *length = 0;
+        }
+        else
+        {
+            *length = strlen((const char*)*payload);
+            result = true;
+        }
+    }
+    else
+    {
+        result = false;
+        *length = 0;
+    }
+    return result;
+}
+
+static void process_queued_ack_messages(PMQTTTRANSPORT_HANDLE_DATA transport_data)
+{
+    PDLIST_ENTRY current_entry = transport_data->telemetry_waitingForAck.Flink;
+    tickcounter_ms_t current_ms;
+    (void)tickcounter_get_current_ms(transport_data->msgTickCounter, &current_ms);
+    while (current_entry != &transport_data->telemetry_waitingForAck)
+    {
+        MQTT_MESSAGE_DETAILS_LIST* msg_detail_entry = containingRecord(current_entry, MQTT_MESSAGE_DETAILS_LIST, entry);
+        DLIST_ENTRY nextListEntry;
+        nextListEntry.Flink = current_entry->Flink;
+
+        if (((current_ms - msg_detail_entry->msgPublishTime) / 1000) > RESEND_TIMEOUT_VALUE_MIN)
+        {
+            if (msg_detail_entry->retryCount >= MAX_SEND_RECOUNT_LIMIT)
+            {
+                sendMsgComplete(msg_detail_entry->iotHubMessageEntry, transport_data, IOTHUB_CLIENT_CONFIRMATION_MESSAGE_TIMEOUT);
+                (void)DList_RemoveEntryList(current_entry);
+                free(msg_detail_entry);
+
+                DisconnectFromClient(transport_data);
+            }
+            else
+            {
+                // Ensure that the packet state is PUBLISH_TYPE and then attempt to send the message
+                // again
+                if (transport_data->currPacketState == PUBLISH_TYPE)
+                {
+                    size_t messageLength;
+                    const unsigned char* messagePayload = NULL;
+                    if (!RetrieveMessagePayload(msg_detail_entry->iotHubMessageEntry->messageHandle, &messagePayload, &messageLength))
+                    {
+                        (void)DList_RemoveEntryList(current_entry);
+                        sendMsgComplete(msg_detail_entry->iotHubMessageEntry, transport_data, IOTHUB_CLIENT_CONFIRMATION_ERROR);
+                    }
+                    else
+                    {
+                        if (publish_mqtt_telemetry_msg(transport_data, msg_detail_entry, messagePayload, messageLength) != 0)
+                        {
+                            (void)DList_RemoveEntryList(current_entry);
+                            sendMsgComplete(msg_detail_entry->iotHubMessageEntry, transport_data, IOTHUB_CLIENT_CONFIRMATION_ERROR);
+                            free(msg_detail_entry);
+                        }
+                    }
+                }
+                else
+                {
+                    msg_detail_entry->retryCount++;
+                    msg_detail_entry->msgPublishTime = current_ms;
+                }
+            }
+        }
+        current_entry = nextListEntry.Flink;
+    }
+}
+
+static int GetTransportProviderIfNecessary(PMQTTTRANSPORT_HANDLE_DATA transport_data)
+{
+    int result;
+
+    if (transport_data->xioTransport == NULL)
+    {
+        // construct address
+        const char* hostAddress = STRING_c_str(transport_data->hostAddress);
+        MQTT_TRANSPORT_PROXY_OPTIONS mqtt_proxy_options;
+
+        /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_011: [ If no `proxy_data` option has been set, NULL shall be passed as the argument `mqtt_transport_proxy_options` when calling the function `get_io_transport` passed in `IoTHubTransport_MQTT_Common__Create`. ]*/
+        mqtt_proxy_options.host_address = transport_data->http_proxy_hostname;
+        mqtt_proxy_options.port = transport_data->http_proxy_port;
+        mqtt_proxy_options.username = transport_data->http_proxy_username;
+        mqtt_proxy_options.password = transport_data->http_proxy_password;
+
+        /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_010: [ If the `proxy_data` option has been set, the proxy options shall be filled in the argument `mqtt_transport_proxy_options` when calling the function `get_io_transport` passed in `IoTHubTransport_MQTT_Common__Create` to obtain the underlying IO handle. ]*/
+        transport_data->xioTransport = transport_data->get_io_transport(hostAddress, (transport_data->http_proxy_hostname == NULL) ? NULL : &mqtt_proxy_options);
+        if (transport_data->xioTransport == NULL)
+        {
+            LogError("Unable to create the lower level TLS layer.");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if (transport_data->saved_tls_options != NULL)
+            {
+                if (OptionHandler_FeedOptions(transport_data->saved_tls_options, transport_data->xioTransport) != OPTIONHANDLER_OK)
+                {
+                    LogError("Failed feeding existing options to new TLS instance.");
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    // The tlsio has the options, so our copy can be deleted
+                    set_saved_tls_options(transport_data, NULL);
+                    result = 0;
+                }
+            }
+            else if (IoTHubClient_Auth_Get_Credential_Type(transport_data->authorization_module) == IOTHUB_CREDENTIAL_TYPE_X509_ECC)
+            {
+                if (IoTHubClient_Auth_Set_xio_Certificate(transport_data->authorization_module, transport_data->xioTransport) != 0)
+                {
+                    LogError("Unable to create the lower level TLS layer.");
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    result = 0;
+                }
+            }
+            else
+            {
+                result = 0;
+            }
+        }
+    }
+    else
+    {
+        result = 0;
+    }
+    return result;
+}
+
+static STRING_HANDLE buildClientId(const char* device_id, const char* module_id)
+{
+    if (module_id == NULL)
+    {
+        return STRING_construct_sprintf("%s", device_id);
+    }
+    else
+    {
+        return STRING_construct_sprintf("%s/%s", device_id, module_id);
+    }
+}
+
+static int buildConfigForUsernameStep2IfNeeded(PMQTTTRANSPORT_HANDLE_DATA transport_data)
+{
+    int result;
+
+    if (!transport_data->isConnectUsernameSet)
+    {
+        STRING_HANDLE userName = NULL;
+        STRING_HANDLE modelIdParameter = NULL;
+        STRING_HANDLE urlEncodedModelId = NULL;
+        const char* modelId = transport_data->transport_callbacks.get_model_id_cb(transport_data->transport_ctx);
+        // TODO: The preview API version in SDK is only scoped to scenarios that require the modelId to be set.
+        // https://github.com/Azure/azure-iot-sdk-c/issues/1547 tracks removing this once non-preview API versions support modelId.
+        const char* apiVersion = (modelId != NULL) ? IOTHUB_API_PREVIEW_VERSION : IOTHUB_API_VERSION;
+        const char* appSpecifiedProductInfo = transport_data->transport_callbacks.prod_info_cb(transport_data->transport_ctx);
+        STRING_HANDLE productInfoEncoded = NULL; 
+
+        if ((productInfoEncoded = URL_EncodeString((appSpecifiedProductInfo != NULL) ? appSpecifiedProductInfo : DEFAULT_IOTHUB_PRODUCT_IDENTIFIER)) == NULL)
+        {
+            LogError("Unable to UrlEncode productInfo");
+            result = MU_FAILURE;
+        }
+        else if ((userName = STRING_construct_sprintf("%s?api-version=%s&DeviceClientType=%s", STRING_c_str(transport_data->configPassedThroughUsername), apiVersion, STRING_c_str(productInfoEncoded))) == NULL)
+        {
+            LogError("Failed constructing string");
+            result = 0;
+        }
+        else if (modelId != NULL)
+        {
+            if ((urlEncodedModelId = URL_EncodeString(modelId)) == NULL)
+            {
+                LogError("Failed to URL encode the modelID string");
+                result = MU_FAILURE;
+            }
+            else if ((modelIdParameter = STRING_construct_sprintf("&%s=%s", DT_MODEL_ID_TOKEN, STRING_c_str(urlEncodedModelId))) == NULL)
+            {
+                LogError("Cannot build modelID string");
+                result = MU_FAILURE;
+            }
+            else if (STRING_concat_with_STRING(userName, modelIdParameter) != 0)
+            {
+                LogError("Failed to set modelID parameter in connect");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                result = 0;
+            }
+        }
+        else
+        {
+            result = 0;
+        }
+
+        if (result == 0)
+        {
+            STRING_delete(transport_data->configPassedThroughUsername);
+            transport_data->configPassedThroughUsername = userName;
+            userName = NULL;
+            // setting connect string is only allowed once in the lifetime of the device client.
+            transport_data->isConnectUsernameSet = true;
+        }
+
+        STRING_delete(userName);
+        STRING_delete(modelIdParameter);
+        STRING_delete(urlEncodedModelId);
+        STRING_delete(productInfoEncoded);
+    }
+    else
+    {
+        result = 0;
+    }
+
+    return result;
+}
+
+static int SendMqttConnectMsg(PMQTTTRANSPORT_HANDLE_DATA transport_data)
+{
+    int result;
+
+    char* sasToken = NULL;
+    result = 0;
+
+    IOTHUB_CREDENTIAL_TYPE cred_type = IoTHubClient_Auth_Get_Credential_Type(transport_data->authorization_module);
+    if (cred_type == IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY || cred_type == IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH)
+    {
+        sasToken = IoTHubClient_Auth_Get_SasToken(transport_data->authorization_module, STRING_c_str(transport_data->devicesAndModulesPath), 0, NULL);
+        if (sasToken == NULL)
+        {
+            LogError("failure getting sas token from IoTHubClient_Auth_Get_SasToken.");
+            result = MU_FAILURE;
+        }
+    }
+    else if (cred_type == IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN)
+    {
+        SAS_TOKEN_STATUS token_status = IoTHubClient_Auth_Is_SasToken_Valid(transport_data->authorization_module);
+        if (token_status == SAS_TOKEN_STATUS_INVALID)
+        {
+            transport_data->transport_callbacks.connection_status_cb(IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_EXPIRED_SAS_TOKEN, transport_data->transport_ctx);
+            result = MU_FAILURE;
+        }
+        else if (token_status == SAS_TOKEN_STATUS_FAILED)
+        {
+            transport_data->transport_callbacks.connection_status_cb(IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_BAD_CREDENTIAL, transport_data->transport_ctx);
+            result = MU_FAILURE;
+        }
+        else
+        {
+            sasToken = IoTHubClient_Auth_Get_SasToken(transport_data->authorization_module, NULL, 0, NULL);
+            if (sasToken == NULL)
+            {
+                LogError("failure getting sas Token.");
+                result = MU_FAILURE;
+            }
+        }
+    }
+
+    if (result == 0)
+    {
+        STRING_HANDLE clientId;
+        if (buildConfigForUsernameStep2IfNeeded(transport_data) != 0)
+        {
+            LogError("Failed to add optional connect parameters.");
+            result = MU_FAILURE;
+        }
+        else if ((clientId = buildClientId(STRING_c_str(transport_data->device_id), STRING_c_str(transport_data->module_id))) == NULL)
+        {
+            LogError("Unable to allocate clientId");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            MQTT_CLIENT_OPTIONS options = { 0 };
+            options.clientId = (char*)STRING_c_str(clientId);
+            options.willMessage = NULL;
+            options.username = (char*)STRING_c_str(transport_data->configPassedThroughUsername);
+            if (sasToken != NULL)
+            {
+                options.password = sasToken;
+            }
+            options.keepAliveInterval = transport_data->keepAliveValue;
+            options.useCleanSession = false;
+            options.qualityOfServiceValue = DELIVER_AT_LEAST_ONCE;
+
+            if (GetTransportProviderIfNecessary(transport_data) == 0)
+            {
+                transport_data->conn_attempted = true;
+                if (mqtt_client_connect(transport_data->mqttClient, transport_data->xioTransport, &options) != 0)
+                {
+                    LogError("failure connecting to address %s.", STRING_c_str(transport_data->hostAddress));
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    transport_data->currPacketState = CONNECT_TYPE;
+                    transport_data->isRetryExpiredCallbackSet = false;
+                    (void)tickcounter_get_current_ms(transport_data->msgTickCounter, &transport_data->mqtt_connect_time);
+                    result = 0;
+                }
+            }
+            else
+            {
+                result = MU_FAILURE;
+            }
+
+            if (sasToken != NULL)
+            {
+                free(sasToken);
+            }
+            STRING_delete(clientId);
+        }
+    }
+    return result;
+}
+
+static int InitializeConnection(PMQTTTRANSPORT_HANDLE_DATA transport_data)
+{
+    int result = 0;
+
+    // Make sure we're not destroying the object
+    if (!transport_data->isDestroyCalled)
+    {
+        RETRY_ACTION retry_action = RETRY_ACTION_RETRY_LATER;
+
+        // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_007: [ IoTHubTransport_MQTT_Common_DoWork shall try to reconnect according to the current retry policy set ]
+        if (transport_data->mqttClientStatus == MQTT_CLIENT_STATUS_NOT_CONNECTED && transport_data->isRecoverableError)
+        {
+            // Note: in case retry_control_should_retry fails, the reconnection shall be attempted anyway (defaulting to policy IOTHUB_CLIENT_RETRY_IMMEDIATE).
+            if (!transport_data->conn_attempted || retry_control_should_retry(transport_data->retry_control_handle, &retry_action) != 0 || retry_action == RETRY_ACTION_RETRY_NOW)
+            {
+                if (tickcounter_get_current_ms(transport_data->msgTickCounter, &transport_data->connectTick) != 0)
+                {
+                    transport_data->connectFailCount++;
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    ResetConnectionIfNecessary(transport_data);
+
+                    if (SendMqttConnectMsg(transport_data) != 0)
+                    {
+                        transport_data->connectFailCount++;
+                        result = MU_FAILURE;
+                    }
+                    else
+                    {
+                        transport_data->mqttClientStatus = MQTT_CLIENT_STATUS_CONNECTING;
+                        transport_data->connectFailCount = 0;
+                        result = 0;
+                    }
+                }
+            }
+            else if (retry_action == RETRY_ACTION_STOP_RETRYING)
+            {
+                // Set callback if retry expired
+                if (!transport_data->isRetryExpiredCallbackSet)
+                {
+                    transport_data->transport_callbacks.connection_status_cb(IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_RETRY_EXPIRED, transport_data->transport_ctx);
+                    transport_data->isRetryExpiredCallbackSet = true;
+                }
+                result = MU_FAILURE;
+            }
+            else if (retry_action == RETRY_ACTION_RETRY_LATER)
+            {
+                result = MU_FAILURE;
+            }
+        }
+        else if (transport_data->mqttClientStatus == MQTT_CLIENT_STATUS_EXECUTE_DISCONNECT)
+        {
+            // Need to disconnect from client
+            DisconnectFromClient(transport_data);
+            result = 0;
+        }
+        // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_001: [ IoTHubTransport_MQTT_Common_DoWork shall trigger reconnection if the mqtt_client_connect does not complete within `keepalive` seconds]
+        else if (transport_data->mqttClientStatus == MQTT_CLIENT_STATUS_CONNECTING)
+        {
+            tickcounter_ms_t current_time;
+            if (tickcounter_get_current_ms(transport_data->msgTickCounter, &current_time) != 0)
+            {
+                LogError("failed verifying MQTT_CLIENT_STATUS_CONNECTING timeout");
+                result = MU_FAILURE;
+            }
+            else if ((current_time - transport_data->mqtt_connect_time) / 1000 > transport_data->connect_timeout_in_sec)
+            {
+                LogError("mqtt_client timed out waiting for CONNACK");
+                transport_data->currPacketState = PACKET_TYPE_ERROR;
+                DisconnectFromClient(transport_data);
+                result = MU_FAILURE;
+            }
+        }
+        else if (transport_data->mqttClientStatus == MQTT_CLIENT_STATUS_CONNECTED)
+        {
+            // We are connected and not being closed, so does SAS need to reconnect?
+            tickcounter_ms_t current_time;
+            if (tickcounter_get_current_ms(transport_data->msgTickCounter, &current_time) != 0)
+            {
+                transport_data->connectFailCount++;
+                result = MU_FAILURE;
+            }
+            else
+            {
+                IOTHUB_CREDENTIAL_TYPE cred_type = IoTHubClient_Auth_Get_Credential_Type(transport_data->authorization_module);
+                // If the credential type is not an x509 certificate then we shall renew the Sas_Token
+                if (cred_type != IOTHUB_CREDENTIAL_TYPE_X509 && cred_type != IOTHUB_CREDENTIAL_TYPE_X509_ECC)
+                {
+                    size_t sas_token_expiry = IoTHubClient_Auth_Get_SasToken_Expiry(transport_data->authorization_module);
+                    if ((current_time - transport_data->mqtt_connect_time) / 1000 > (sas_token_expiry*SAS_REFRESH_MULTIPLIER))
+                    {
+                        /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_07_058: [ If the sas token has timed out IoTHubTransport_MQTT_Common_DoWork shall disconnect from the mqtt client and destroy the transport information and wait for reconnect. ] */
+                        DisconnectFromClient(transport_data);
+
+                        transport_data->transport_callbacks.connection_status_cb(IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_EXPIRED_SAS_TOKEN, transport_data->transport_ctx);
+                        transport_data->currPacketState = UNKNOWN_TYPE;
+                        if (transport_data->topic_MqttMessage != NULL)
+                        {
+                            transport_data->topics_ToSubscribe |= SUBSCRIBE_TELEMETRY_TOPIC;
+                        }
+                        if (transport_data->topic_GetState != NULL)
+                        {
+                            transport_data->topics_ToSubscribe |= SUBSCRIBE_GET_REPORTED_STATE_TOPIC;
+                        }
+                        if (transport_data->topic_NotifyState != NULL)
+                        {
+                            transport_data->topics_ToSubscribe |= SUBSCRIBE_NOTIFICATION_STATE_TOPIC;
+                        }
+                        if (transport_data->topic_DeviceMethods != NULL)
+                        {
+                            transport_data->topics_ToSubscribe |= SUBSCRIBE_DEVICE_METHOD_TOPIC;
+                        }
+                        if (transport_data->topic_InputQueue != NULL)
+                        {
+                            transport_data->topics_ToSubscribe |= SUBSCRIBE_INPUT_QUEUE_TOPIC;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return result;
+}
+
+// At handle creation time, we don't have all the fields required for building up the user name (e.g. productID)
+// We build up as much of the string as we can at this point because we do not store upperConfig after initialization.
+// In buildConfigForUsernameStep2IfNeeded, only immediately before we do CONNECT itself, do we complete building up this string.
+static STRING_HANDLE buildConfigForUsernameStep1(const IOTHUB_CLIENT_CONFIG* upperConfig, const char* moduleId)
+{
+    if (moduleId == NULL)
+    {
+        return STRING_construct_sprintf("%s.%s/%s/", upperConfig->iotHubName, upperConfig->iotHubSuffix, upperConfig->deviceId);
+    }
+    else
+    {
+        return STRING_construct_sprintf("%s.%s/%s/%s/", upperConfig->iotHubName, upperConfig->iotHubSuffix, upperConfig->deviceId, moduleId);
+    }
+}
+
+static STRING_HANDLE buildMqttEventString(const char* device_id, const char* module_id)
+{
+    if (module_id == NULL)
+    {
+        return STRING_construct_sprintf(TOPIC_DEVICE_DEVICE, device_id);
+    }
+    else
+    {
+        return STRING_construct_sprintf(TOPIC_DEVICE_DEVICE_MODULE, device_id, module_id);
+    }
+}
+
+static STRING_HANDLE buildDevicesAndModulesPath(const IOTHUB_CLIENT_CONFIG* upperConfig, const char* moduleId)
+{
+    if (moduleId == NULL)
+    {
+        return STRING_construct_sprintf("%s.%s/devices/%s", upperConfig->iotHubName, upperConfig->iotHubSuffix, upperConfig->deviceId);
+    }
+    else
+    {
+        return STRING_construct_sprintf("%s.%s/devices/%s/modules/%s", upperConfig->iotHubName, upperConfig->iotHubSuffix, upperConfig->deviceId, moduleId);
+    }
+}
+
+static PMQTTTRANSPORT_HANDLE_DATA InitializeTransportHandleData(const IOTHUB_CLIENT_CONFIG* upperConfig, PDLIST_ENTRY waitingToSend, IOTHUB_AUTHORIZATION_HANDLE auth_module, const char* moduleId)
+{
+    PMQTTTRANSPORT_HANDLE_DATA state = (PMQTTTRANSPORT_HANDLE_DATA)malloc(sizeof(MQTTTRANSPORT_HANDLE_DATA));
+    if (state == NULL)
+    {
+        LogError("Could not create MQTT transport state. Memory allocation failed.");
+    }
+    else
+    {
+        memset(state, 0, sizeof(MQTTTRANSPORT_HANDLE_DATA));
+        if ((state->msgTickCounter = tickcounter_create()) == NULL)
+        {
+            LogError("Invalid Argument: iotHubName is empty");
+            free_transport_handle_data(state);
+            state = NULL;
+        }
+        // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_005: [ MQTT transport shall use EXPONENTIAL_WITH_BACK_OFF as default retry policy ]
+        else if ((state->retry_control_handle = retry_control_create(DEFAULT_RETRY_POLICY, DEFAULT_RETRY_TIMEOUT_IN_SECONDS)) == NULL)
+        {
+            LogError("Failed creating default retry control");
+            free_transport_handle_data(state);
+            state = NULL;
+        }
+        else if ((state->device_id = STRING_construct(upperConfig->deviceId)) == NULL)
+        {
+            LogError("failure constructing device_id.");
+            free_transport_handle_data(state);
+            state = NULL;
+        }
+        else if ((moduleId != NULL) && ((state->module_id = STRING_construct(moduleId)) == NULL))
+        {
+            LogError("failure constructing module_id.");
+            free_transport_handle_data(state);
+            state = NULL;
+        }
+        else if ((state->devicesAndModulesPath = buildDevicesAndModulesPath(upperConfig, moduleId)) == NULL)
+        {
+            LogError("failure constructing devicesPath.");
+            free_transport_handle_data(state);
+            state = NULL;
+        }
+        else
+        {
+            if ((state->topic_MqttEvent = buildMqttEventString(upperConfig->deviceId, moduleId)) == NULL)
+            {
+                LogError("Could not create topic_MqttEvent for MQTT");
+                free_transport_handle_data(state);
+                state = NULL;
+            }
+            else
+            {
+                state->mqttClient = mqtt_client_init(mqtt_notification_callback, mqtt_operation_complete_callback, state, mqtt_error_callback, state);
+                if (state->mqttClient == NULL)
+                {
+                    LogError("failure initializing mqtt client.");
+                    free_transport_handle_data(state);
+                    state = NULL;
+                }
+                else
+                {
+                    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_008: [If the upperConfig contains a valid protocolGatewayHostName value this shall be used for the hostname, otherwise the hostname shall be constructed using the iothubName and iothubSuffix.] */
+                    if (upperConfig->protocolGatewayHostName == NULL)
+                    {
+                        state->hostAddress = STRING_construct_sprintf("%s.%s", upperConfig->iotHubName, upperConfig->iotHubSuffix);
+                    }
+                    else
+                    {
+                        state->hostAddress = STRING_construct(upperConfig->protocolGatewayHostName);
+                    }
+
+                    if (state->hostAddress == NULL)
+                    {
+                        LogError("failure constructing host address.");
+                        free_transport_handle_data(state);
+                        state = NULL;
+                    }
+                    else if ((state->configPassedThroughUsername = buildConfigForUsernameStep1(upperConfig, moduleId)) == NULL)
+                    {
+                        free_transport_handle_data(state);
+                        state = NULL;
+                    }
+                    else
+                    {
+                        /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_010: [IoTHubTransport_MQTT_Common_Create shall allocate memory to save its internal state where all topics, hostname, device_id, device_key, sasTokenSr and client handle shall be saved.] */
+                        DList_InitializeListHead(&(state->telemetry_waitingForAck));
+                        DList_InitializeListHead(&(state->ack_waiting_queue));
+                        DList_InitializeListHead(&(state->pending_get_twin_queue));
+                        state->mqttClientStatus = MQTT_CLIENT_STATUS_NOT_CONNECTED;
+                        state->isRecoverableError = true;
+                        state->packetId = 1;
+                        state->waitingToSend = waitingToSend;
+                        state->currPacketState = CONNECT_TYPE;
+                        state->keepAliveValue = DEFAULT_MQTT_KEEPALIVE;
+                        state->connect_timeout_in_sec = DEFAULT_CONNACK_TIMEOUT;
+                        state->topics_ToSubscribe = UNSUBSCRIBE_FROM_TOPIC;
+                        srand((unsigned int)get_time(NULL));
+                        state->authorization_module = auth_module;
+
+                        state->isDestroyCalled = false;
+                        state->isRetryExpiredCallbackSet = false;
+                        state->isRegistered = false;
+                        state->device_twin_get_sent = false;
+                        state->xioTransport = NULL;
+                        state->portNum = 0;
+                        state->connectFailCount = 0;
+                        state->connectTick = 0;
+                        state->topic_MqttMessage = NULL;
+                        state->topic_GetState = NULL;
+                        state->topic_NotifyState = NULL;
+                        state->topic_DeviceMethods = NULL;
+                        state->topic_InputQueue = NULL;
+                        state->log_trace = state->raw_trace = false;
+                        state->isConnectUsernameSet = false;
+                        state->auto_url_encode_decode = false;
+                        state->conn_attempted = false;
+                    }
+                }
+            }
+        }
+    }
+    return state;
+}
+
+TRANSPORT_LL_HANDLE IoTHubTransport_MQTT_Common_Create(const IOTHUBTRANSPORT_CONFIG* config, MQTT_GET_IO_TRANSPORT get_io_transport, TRANSPORT_CALLBACKS_INFO* cb_info, void* ctx)
+{
+    PMQTTTRANSPORT_HANDLE_DATA result;
+    size_t deviceIdSize;
+
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_001: [If parameter config is NULL then IoTHubTransport_MQTT_Common_Create shall return NULL.] */
+    /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_07_041: [ if get_io_transport is NULL then IoTHubTransport_MQTT_Common_Create shall return NULL. ] */
+    if (config == NULL || get_io_transport == NULL || cb_info == NULL)
+    {
+        LogError("Invalid Argument config: %p, get_io_transport: %p, cb_info: %p", config, get_io_transport, cb_info);
+        result = NULL;
+    }
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_002: [If the parameter config's variables upperConfig, auth_module_handle or waitingToSend are NULL then IoTHubTransport_MQTT_Common_Create shall return NULL.] */
+    else if (config->auth_module_handle == NULL)
+    {
+        LogError("Invalid Argument: auth_module_handle is NULL)");
+        result = NULL;
+    }
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_002: [If the parameter config's variables upperConfig or waitingToSend are NULL then IoTHubTransport_MQTT_Common_Create shall return NULL.] */
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_003: [If the upperConfig's variables deviceId, both deviceKey and deviceSasToken, iotHubName, protocol, or iotHubSuffix are NULL then IoTHubTransport_MQTT_Common_Create shall return NULL.] */
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_03_003: [If both deviceKey & deviceSasToken fields are NOT NULL then IoTHubTransport_MQTT_Common_Create shall return NULL.] */
+    else if (config->upperConfig == NULL ||
+        config->upperConfig->protocol == NULL ||
+        config->upperConfig->deviceId == NULL ||
+        ((config->upperConfig->deviceKey != NULL) && (config->upperConfig->deviceSasToken != NULL)) ||
+        config->upperConfig->iotHubName == NULL ||
+        config->upperConfig->iotHubSuffix == NULL)
+    {
+        LogError("Invalid Argument: upperConfig structure contains an invalid parameter");
+        result = NULL;
+    }
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_002: [If the parameter config's variables upperConfig, auth_module_handle or waitingToSend are NULL then IoTHubTransport_MQTT_Common_Create shall return NULL.] */
+    else if (config->waitingToSend == NULL)
+    {
+        LogError("Invalid Argument: waitingToSend is NULL)");
+        result = NULL;
+    }
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_006: [If the upperConfig's variables deviceId is an empty strings or length is greater then 128 then IoTHubTransport_MQTT_Common_Create shall return NULL.] */
+    else if (((deviceIdSize = strlen(config->upperConfig->deviceId)) > 128U) || (deviceIdSize == 0))
+    {
+        LogError("Invalid Argument: DeviceId is of an invalid size");
+        result = NULL;
+    }
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_003: [If the upperConfig's variables deviceId, both deviceKey and deviceSasToken, iotHubName, protocol, or iotHubSuffix are NULL then IoTHubTransport_MQTT_Common_Create shall return NULL.] */
+    else if ((config->upperConfig->deviceKey != NULL) && (strlen(config->upperConfig->deviceKey) == 0))
+    {
+        LogError("Invalid Argument: deviceKey is empty");
+        result = NULL;
+    }
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_003: [If the upperConfig's variables deviceId, both deviceKey and deviceSasToken, iotHubName, protocol, or iotHubSuffix are NULL then IoTHubTransport_MQTT_Common_Create shall return NULL.] */
+    else if ((config->upperConfig->deviceSasToken != NULL) && (strlen(config->upperConfig->deviceSasToken) == 0))
+    {
+        LogError("Invalid Argument: deviceSasToken is empty");
+        result = NULL;
+    }
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_003: [If the upperConfig's variables deviceId, deviceKey, iotHubName, protocol, or iotHubSuffix are NULL then IoTHubTransport_MQTT_Common_Create shall return NULL.] */
+    else if (strlen(config->upperConfig->iotHubName) == 0)
+    {
+        LogError("Invalid Argument: iotHubName is empty");
+        result = NULL;
+    }
+    else if (IoTHub_Transport_ValidateCallbacks(cb_info) != 0)
+    {
+        LogError("failure checking transport callbacks");
+        result = NULL;
+    }
+    else
+    {
+        result = InitializeTransportHandleData(config->upperConfig, config->waitingToSend, config->auth_module_handle, config->moduleId);
+        if (result != NULL)
+        {
+            result->get_io_transport = get_io_transport;
+            result->http_proxy_hostname = NULL;
+            result->http_proxy_username = NULL;
+            result->http_proxy_password = NULL;
+
+            result->transport_ctx = ctx;
+            memcpy(&result->transport_callbacks, cb_info, sizeof(TRANSPORT_CALLBACKS_INFO));
+        }
+    }
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_009: [If any error is encountered then IoTHubTransport_MQTT_Common_Create shall return NULL.] */
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_011: [On Success IoTHubTransport_MQTT_Common_Create shall return a non-NULL value.] */
+    return result;
+}
+
+void IoTHubTransport_MQTT_Common_Destroy(TRANSPORT_LL_HANDLE handle)
+{
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_012: [IoTHubTransport_MQTT_Common_Destroy shall do nothing if parameter handle is NULL.] */
+    PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
+    if (transport_data != NULL)
+    {
+        transport_data->isDestroyCalled = true;
+
+        DisconnectFromClient(transport_data);
+
+        //Empty the Waiting for Ack Messages.
+        while (!DList_IsListEmpty(&transport_data->telemetry_waitingForAck))
+        {
+            PDLIST_ENTRY currentEntry = DList_RemoveHeadList(&transport_data->telemetry_waitingForAck);
+            MQTT_MESSAGE_DETAILS_LIST* mqttMsgEntry = containingRecord(currentEntry, MQTT_MESSAGE_DETAILS_LIST, entry);
+            sendMsgComplete(mqttMsgEntry->iotHubMessageEntry, transport_data, IOTHUB_CLIENT_CONFIRMATION_BECAUSE_DESTROY);
+            free(mqttMsgEntry);
+        }
+        while (!DList_IsListEmpty(&transport_data->ack_waiting_queue))
+        {
+            PDLIST_ENTRY currentEntry = DList_RemoveHeadList(&transport_data->ack_waiting_queue);
+            MQTT_DEVICE_TWIN_ITEM* mqtt_device_twin = containingRecord(currentEntry, MQTT_DEVICE_TWIN_ITEM, entry);
+
+            if (mqtt_device_twin->userCallback == NULL)
+            {
+                transport_data->transport_callbacks.twin_rpt_state_complete_cb(mqtt_device_twin->iothub_msg_id, STATUS_CODE_TIMEOUT_VALUE, transport_data->transport_ctx);
+            }
+            else
+            {
+                mqtt_device_twin->userCallback(DEVICE_TWIN_UPDATE_COMPLETE, NULL, 0, mqtt_device_twin->userContext);
+            }
+
+            destroy_device_twin_get_message(mqtt_device_twin);
+        }
+        while (!DList_IsListEmpty(&transport_data->pending_get_twin_queue))
+        {
+            PDLIST_ENTRY currentEntry = DList_RemoveHeadList(&transport_data->pending_get_twin_queue);
+
+            MQTT_DEVICE_TWIN_ITEM* mqtt_device_twin = containingRecord(currentEntry, MQTT_DEVICE_TWIN_ITEM, entry);
+
+            mqtt_device_twin->userCallback(DEVICE_TWIN_UPDATE_COMPLETE, NULL, 0, mqtt_device_twin->userContext);
+
+            destroy_device_twin_get_message(mqtt_device_twin);
+        }
+
+        /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_014: [IoTHubTransport_MQTT_Common_Destroy shall free all the resources currently in use.] */
+        /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_012: [ `IoTHubTransport_MQTT_Common_Destroy` shall free the stored proxy options. ]*/
+        free_transport_handle_data(transport_data);
+    }
+}
+
+int IoTHubTransport_MQTT_Common_Subscribe_DeviceTwin(TRANSPORT_LL_HANDLE handle)
+{
+    int result;
+    PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
+    if (transport_data == NULL)
+    {
+        /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_042: [If the parameter handle is NULL than IoTHubTransport_MQTT_Common_Subscribe shall return a non-zero value.] */
+        LogError("Invalid handle parameter. NULL.");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        if (transport_data->topic_GetState == NULL)
+        {
+            /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_044: [IoTHubTransport_MQTT_Common_Subscribe_DeviceTwin shall construct the get state topic string and the notify state topic string.] */
+            transport_data->topic_GetState = STRING_construct(TOPIC_GET_DESIRED_STATE);
+            if (transport_data->topic_GetState == NULL)
+            {
+                /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_046: [Upon failure IoTHubTransport_MQTT_Common_Subscribe_DeviceTwin shall return a non-zero value.] */
+                LogError("Failure: unable constructing reported state topic");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_047: [On success IoTHubTransport_MQTT_Common_Subscribe_DeviceTwin shall return 0.] */
+                transport_data->topics_ToSubscribe |= SUBSCRIBE_GET_REPORTED_STATE_TOPIC;
+                result = 0;
+            }
+        }
+        else
+        {
+            result = 0;
+        }
+        if (result == 0)
+        {
+            changeStateToSubscribeIfAllowed(transport_data);
+        }
+    }
+    return result;
+}
+
+void IoTHubTransport_MQTT_Common_Unsubscribe_DeviceTwin(TRANSPORT_LL_HANDLE handle)
+{
+    PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_048: [If the parameter handle is NULL than IoTHubTransport_MQTT_Common_Unsubscribe_DeviceTwin shall do nothing.] */
+    if (transport_data != NULL)
+    {
+        if (transport_data->topic_GetState != NULL)
+        {
+            /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_049: [If subscribe_state is set to IOTHUB_DEVICE_TWIN_DESIRED_STATE then IoTHubTransport_MQTT_Common_Unsubscribe_DeviceTwin shall unsubscribe from the topic_GetState to the mqtt client.] */
+            transport_data->topics_ToSubscribe &= ~SUBSCRIBE_GET_REPORTED_STATE_TOPIC;
+            STRING_delete(transport_data->topic_GetState);
+            transport_data->topic_GetState = NULL;
+        }
+        if (transport_data->topic_NotifyState != NULL)
+        {
+            /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_050: [If subscribe_state is set to IOTHUB_DEVICE_TWIN_NOTIFICATION_STATE then IoTHubTransport_MQTT_Common_Unsubscribe_DeviceTwin shall unsubscribe from the topic_NotifyState to the mqtt client.] */
+            transport_data->topics_ToSubscribe &= ~SUBSCRIBE_NOTIFICATION_STATE_TOPIC;
+            STRING_delete(transport_data->topic_NotifyState);
+            transport_data->topic_NotifyState = NULL;
+        }
+    }
+    else
+    {
+        LogError("Invalid argument to unsubscribe (handle is NULL).");
+    }
+}
+
+IOTHUB_CLIENT_RESULT IoTHubTransport_MQTT_Common_GetTwinAsync(IOTHUB_DEVICE_HANDLE handle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK completionCallback, void* callbackContext)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    // Codes_SRS_IOTHUB_MQTT_TRANSPORT_09_001: [ If `handle` or `completionCallback` are `NULL` than `IoTHubTransport_MQTT_Common_GetTwinAsync` shall return IOTHUB_CLIENT_INVALID_ARG. ]
+    if (handle == NULL || completionCallback == NULL)
+    {
+        LogError("Invalid argument (handle=%p, completionCallback=%p)", handle, completionCallback);
+        result = IOTHUB_CLIENT_INVALID_ARG;
+    }
+    else
+    {
+        PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
+        MQTT_DEVICE_TWIN_ITEM* mqtt_info;
+
+        if ((mqtt_info = create_device_twin_message(transport_data, RETRIEVE_PROPERTIES, 0)) == NULL)
+        {
+            LogError("Failed creating the device twin get request message");
+            // Codes_SRS_IOTHUB_MQTT_TRANSPORT_09_003: [ If any failure occurs, IoTHubTransport_MQTT_Common_GetTwinAsync shall return IOTHUB_CLIENT_ERROR ]
+            result = IOTHUB_CLIENT_ERROR;
+        }
+        else if (tickcounter_get_current_ms(transport_data->msgTickCounter, &mqtt_info->msgCreationTime) != 0)
+        {
+            LogError("Failed setting the get twin request enqueue time");
+            destroy_device_twin_get_message(mqtt_info);
+            // Codes_SRS_IOTHUB_MQTT_TRANSPORT_09_003: [ If any failure occurs, IoTHubTransport_MQTT_Common_GetTwinAsync shall return IOTHUB_CLIENT_ERROR ]
+            result = IOTHUB_CLIENT_ERROR;
+        }
+        else
+        {
+            mqtt_info->userCallback = completionCallback;
+            mqtt_info->userContext = callbackContext;
+
+            // Codes_SRS_IOTHUB_MQTT_TRANSPORT_09_002: [ The request shall be queued to be sent when the transport is connected, through DoWork ]
+            DList_InsertTailList(&transport_data->pending_get_twin_queue, &mqtt_info->entry);
+
+            // Codes_SRS_IOTHUB_MQTT_TRANSPORT_09_004: [ If no failure occurs, IoTHubTransport_MQTT_Common_GetTwinAsync shall return IOTHUB_CLIENT_OK ]
+            result = IOTHUB_CLIENT_OK;
+        }
+    }
+
+    return result;
+}
+
+int IoTHubTransport_MQTT_Common_Subscribe_DeviceMethod(IOTHUB_DEVICE_HANDLE handle)
+{
+    int result;
+    PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
+
+    if (transport_data == NULL)
+    {
+        /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_001 : [If the parameter handle is NULL than IoTHubTransport_MQTT_Common_Subscribe_DeviceMethod shall return a non - zero value.]*/
+        LogError("Invalid handle parameter. NULL.");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        if (transport_data->topic_DeviceMethods == NULL)
+        {
+            /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_004 : [IoTHubTransport_MQTT_Common_Subscribe_DeviceMethod shall construct the DEVICE_METHOD topic string for subscribe.]*/
+            transport_data->topic_DeviceMethods = STRING_construct(TOPIC_DEVICE_METHOD_SUBSCRIBE);
+            if (transport_data->topic_DeviceMethods == NULL)
+            {
+                /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_006 : [Upon failure IoTHubTransport_MQTT_Common_Subscribe_DeviceMethod shall return a non - zero value.]*/
+                LogError("Failure: unable constructing device method subscribe topic");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_003 : [IoTHubTransport_MQTT_Common_Subscribe_DeviceMethod shall set the signaling flag for DEVICE_METHOD topic for the receiver's topic list. ]*/
+                transport_data->topics_ToSubscribe |= SUBSCRIBE_DEVICE_METHOD_TOPIC;
+                result = 0;
+            }
+        }
+        else
+        {
+            /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_002 : [If the MQTT transport has been previously subscribed to DEVICE_METHOD topic IoTHubTransport_MQTT_Common_Subscribe_DeviceMethod shall do nothing and return 0.]*/
+            result = 0;
+        }
+
+        if (result == 0)
+        {
+            /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_005 : [IoTHubTransport_MQTT_Common_Subscribe_DeviceMethod shall schedule the send of the subscription.]*/
+            /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_007 : [On success IoTHubTransport_MQTT_Common_Subscribe_DeviceMethod shall return 0.]*/
+            changeStateToSubscribeIfAllowed(transport_data);
+        }
+    }
+    return result;
+}
+
+void IoTHubTransport_MQTT_Common_Unsubscribe_DeviceMethod(TRANSPORT_LL_HANDLE handle)
+{
+    PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
+    /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_008 : [If the parameter handle is NULL than IoTHubTransport_MQTT_Common_Unsubscribe_DeviceMethod shall do nothing and return.]*/
+    if (transport_data != NULL)
+    {
+        /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_009 : [If the MQTT transport has not been subscribed to DEVICE_METHOD topic IoTHubTransport_MQTT_Common_Unsubscribe_DeviceMethod shall do nothing and return.]*/
+        if (transport_data->topic_DeviceMethods != NULL)
+        {
+            /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_010 : [IoTHubTransport_MQTT_Common_Unsubscribe_DeviceMethod shall construct the DEVICE_METHOD topic string for unsubscribe.]*/
+            const char* unsubscribe[1];
+            unsubscribe[0] = STRING_c_str(transport_data->topic_DeviceMethods);
+
+            /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_011 : [IoTHubTransport_MQTT_Common_Unsubscribe_DeviceMethod shall send the unsubscribe.]*/
+            if (mqtt_client_unsubscribe(transport_data->mqttClient, get_next_packet_id(transport_data), unsubscribe, 1) != 0)
+            {
+                LogError("Failure calling mqtt_client_unsubscribe");
+            }
+
+            /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_012 : [IoTHubTransport_MQTT_Common_Unsubscribe_DeviceMethod shall removes the signaling flag for DEVICE_METHOD topic from the receiver's topic list. ]*/
+            STRING_delete(transport_data->topic_DeviceMethods);
+            transport_data->topic_DeviceMethods = NULL;
+            transport_data->topics_ToSubscribe &= ~SUBSCRIBE_DEVICE_METHOD_TOPIC;
+        }
+    }
+    else
+    {
+        LogError("Invalid argument to unsubscribe (NULL).");
+    }
+}
+
+int IoTHubTransport_MQTT_Common_DeviceMethod_Response(TRANSPORT_LL_HANDLE handle, METHOD_HANDLE methodId, const unsigned char* response, size_t respSize, int status)
+{
+    int result;
+    MQTTTRANSPORT_HANDLE_DATA* transport_data = (MQTTTRANSPORT_HANDLE_DATA*)handle;
+    if (transport_data != NULL)
+    {
+        /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_07_042: [ IoTHubTransport_MQTT_Common_DeviceMethod_Response shall publish an mqtt message for the device method response. ] */
+        DEVICE_METHOD_INFO* dev_method_info = (DEVICE_METHOD_INFO*)methodId;
+        if (dev_method_info == NULL)
+        {
+            LogError("Failure: DEVICE_METHOD_INFO was NULL");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if (publish_device_method_message(transport_data, status, dev_method_info->request_id, response, respSize) != 0)
+            {
+                /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_07_051: [ If any error is encountered, IoTHubTransport_MQTT_Common_DeviceMethod_Response shall return a non-zero value. ] */
+                LogError("Failure: publishing device method response");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                result = 0;
+            }
+            STRING_delete(dev_method_info->request_id);
+            free(dev_method_info);
+        }
+    }
+    else
+    {
+        /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_07_041: [ If the parameter handle is NULL than IoTHubTransport_MQTT_Common_DeviceMethod_Response shall return a non-zero value. ] */
+        result = MU_FAILURE;
+        LogError("Failure: invalid TRANSPORT_LL_HANDLE parameter specified");
+    }
+    return result;
+}
+
+static STRING_HANDLE buildTopicMqttMessage(const char* device_id, const char* module_id)
+{
+    if (module_id == NULL)
+    {
+        return STRING_construct_sprintf(TOPIC_DEVICE_MSG, device_id);
+    }
+    else
+    {
+        return STRING_construct_sprintf(TOPIC_DEVICE_MODULE_MSG, device_id, module_id);
+    }
+}
+
+int IoTHubTransport_MQTT_Common_Subscribe(TRANSPORT_LL_HANDLE handle)
+{
+    int result;
+    PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
+    if (transport_data == NULL)
+    {
+        /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_015: [If parameter handle is NULL than IoTHubTransport_MQTT_Common_Subscribe shall return a non-zero value.] */
+        LogError("Invalid handle parameter. NULL.");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        /* Code_SRS_IOTHUB_MQTT_TRANSPORT_07_016: [IoTHubTransport_MQTT_Common_Subscribe shall set a flag to enable mqtt_client_subscribe to be called to subscribe to the Message Topic.] */
+        transport_data->topic_MqttMessage = buildTopicMqttMessage(STRING_c_str(transport_data->device_id), STRING_c_str(transport_data->module_id));
+        if (transport_data->topic_MqttMessage == NULL)
+        {
+            LogError("Failure constructing Message Topic");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            transport_data->topics_ToSubscribe |= SUBSCRIBE_TELEMETRY_TOPIC;
+            /* Code_SRS_IOTHUB_MQTT_TRANSPORT_07_035: [If current packet state is not CONNACT, DISCONNECT_TYPE, or PACKET_TYPE_ERROR then IoTHubTransport_MQTT_Common_Subscribe shall set the packet state to SUBSCRIBE_TYPE.]*/
+            changeStateToSubscribeIfAllowed(transport_data);
+            result = 0;
+        }
+    }
+    return result;
+}
+
+void IoTHubTransport_MQTT_Common_Unsubscribe(TRANSPORT_LL_HANDLE handle)
+{
+    PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_019: [If parameter handle is NULL then IoTHubTransport_MQTT_Common_Unsubscribe shall do nothing.] */
+    if (transport_data != NULL)
+    {
+        /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_020: [IoTHubTransport_MQTT_Common_Unsubscribe shall call mqtt_client_unsubscribe to unsubscribe the mqtt message topic.] */
+        const char* unsubscribe[1];
+        unsubscribe[0] = STRING_c_str(transport_data->topic_MqttMessage);
+        if (mqtt_client_unsubscribe(transport_data->mqttClient, get_next_packet_id(transport_data), unsubscribe, 1) != 0)
+        {
+            LogError("Failure calling mqtt_client_unsubscribe");
+        }
+        STRING_delete(transport_data->topic_MqttMessage);
+        transport_data->topic_MqttMessage = NULL;
+        transport_data->topics_ToSubscribe &= ~SUBSCRIBE_TELEMETRY_TOPIC;
+    }
+    else
+    {
+        LogError("Invalid argument to unsubscribe (NULL).");
+    }
+}
+
+IOTHUB_PROCESS_ITEM_RESULT IoTHubTransport_MQTT_Common_ProcessItem(TRANSPORT_LL_HANDLE handle, IOTHUB_IDENTITY_TYPE item_type, IOTHUB_IDENTITY_INFO* iothub_item)
+{
+    IOTHUB_PROCESS_ITEM_RESULT result;
+    /* Codes_SRS_IOTHUBCLIENT_LL_07_001: [ If handle or iothub_item are NULL then IoTHubTransport_MQTT_Common_ProcessItem shall return IOTHUB_PROCESS_ERROR. ]*/
+    if (handle == NULL || iothub_item == NULL)
+    {
+        LogError("Invalid handle parameter iothub_item=%p", iothub_item);
+        result = IOTHUB_PROCESS_ERROR;
+    }
+    else
+    {
+        PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
+
+        if (transport_data->currPacketState == PUBLISH_TYPE)
+        {
+            // Ensure the reported property suback has been received
+            if (item_type == IOTHUB_TYPE_DEVICE_TWIN && transport_data->twin_resp_sub_recv)
+            {
+                MQTT_DEVICE_TWIN_ITEM* mqtt_info = create_device_twin_message(transport_data, REPORTED_STATE, iothub_item->device_twin->item_id);
+                if (mqtt_info == NULL)
+                {
+                    /* Codes_SRS_IOTHUBCLIENT_LL_07_004: [ If any errors are encountered IoTHubTransport_MQTT_Common_ProcessItem shall return IOTHUB_PROCESS_ERROR. ]*/
+                    result = IOTHUB_PROCESS_ERROR;
+                }
+                else
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_07_003: [ IoTHubTransport_MQTT_Common_ProcessItem shall publish a message to the mqtt protocol with the message topic for the message type.]*/
+                    /* Codes_SRS_IOTHUBCLIENT_LL_07_005: [ If successful IoTHubTransport_MQTT_Common_ProcessItem shall add mqtt info structure acknowledgement queue. ] */
+                    DList_InsertTailList(&transport_data->ack_waiting_queue, &mqtt_info->entry);
+
+                    if (publish_device_twin_message(transport_data, iothub_item->device_twin, mqtt_info) != 0)
+                    {
+                        DList_RemoveEntryList(&mqtt_info->entry);
+
+                        free(mqtt_info);
+                        /* Codes_SRS_IOTHUBCLIENT_LL_07_004: [ If any errors are encountered IoTHubTransport_MQTT_Common_ProcessItem shall return IOTHUB_PROCESS_ERROR. ]*/
+                        result = IOTHUB_PROCESS_ERROR;
+                    }
+                    else
+                    {
+                        result = IOTHUB_PROCESS_OK;
+                    }
+                }
+            }
+            else
+            {
+                /* Codes_SRS_IOTHUBCLIENT_LL_07_006: [ If the item_type is not a supported type IoTHubTransport_MQTT_Common_ProcessItem shall return IOTHUB_PROCESS_CONTINUE. ]*/
+                result = IOTHUB_PROCESS_CONTINUE;
+            }
+        }
+        else
+        {
+            /* Codes_SRS_IOTHUBCLIENT_LL_07_002: [ If the mqtt is not ready to publish messages IoTHubTransport_MQTT_Common_ProcessItem shall return IOTHUB_PROCESS_NOT_CONNECTED. ] */
+            result = IOTHUB_PROCESS_NOT_CONNECTED;
+        }
+    }
+    return result;
+}
+
+/* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_054: [ IoTHubTransport_MQTT_Common_DoWork shall subscribe to the Notification and get_state Topics if they are defined. ] */
+void IoTHubTransport_MQTT_Common_DoWork(TRANSPORT_LL_HANDLE handle)
+{
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_026: [IoTHubTransport_MQTT_Common_DoWork shall do nothing if parameter handle and/or iotHubClientHandle is NULL.] */
+    PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
+    if (transport_data != NULL)
+    {
+        if (InitializeConnection(transport_data) == 0)
+        {
+            if (transport_data->mqttClientStatus == MQTT_CLIENT_STATUS_PENDING_CLOSE)
+            {
+                mqtt_client_disconnect(transport_data->mqttClient, NULL, NULL);
+                transport_data->mqttClientStatus = MQTT_CLIENT_STATUS_NOT_CONNECTED;
+            }
+            else if (transport_data->currPacketState == CONNACK_TYPE || transport_data->currPacketState == SUBSCRIBE_TYPE)
+            {
+                SubscribeToMqttProtocol(transport_data);
+            }
+            else if (transport_data->currPacketState == SUBACK_TYPE)
+            {
+                if ((transport_data->topic_NotifyState != NULL || transport_data->topic_GetState != NULL) &&
+                    !transport_data->device_twin_get_sent)
+                {
+                    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_055: [ IoTHubTransport_MQTT_Common_DoWork shall send a device twin get property message upon successfully retrieving a SUBACK on device twin topics. ] */
+                    MQTT_DEVICE_TWIN_ITEM* mqtt_info;
+
+                    if ((mqtt_info = create_device_twin_message(transport_data, RETRIEVE_PROPERTIES, 0)) == NULL)
+                    {
+                        LogError("Failure: could not create message for twin get command");
+                    }
+                    else if (publish_device_twin_get_message(transport_data, mqtt_info) == 0)
+                    {
+                        transport_data->device_twin_get_sent = true;
+                    }
+                    else
+                    {
+                        LogError("Failure: sending device twin get property command.");
+                        destroy_device_twin_get_message(mqtt_info);
+                    }
+                }
+                // Publish can be called now
+                transport_data->currPacketState = PUBLISH_TYPE;
+            }
+            else if (transport_data->currPacketState == PUBLISH_TYPE)
+            {
+                PDLIST_ENTRY currentListEntry = transport_data->waitingToSend->Flink;
+                /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_027: [IoTHubTransport_MQTT_Common_DoWork shall inspect the "waitingToSend" DLIST passed in config structure.] */
+                while (currentListEntry != transport_data->waitingToSend)
+                {
+                    IOTHUB_MESSAGE_LIST* iothubMsgList = containingRecord(currentListEntry, IOTHUB_MESSAGE_LIST, entry);
+                    DLIST_ENTRY savedFromCurrentListEntry;
+                    savedFromCurrentListEntry.Flink = currentListEntry->Flink;
+
+                    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_027: [IoTHubTransport_MQTT_Common_DoWork shall inspect the "waitingToSend" DLIST passed in config structure.] */
+                    size_t messageLength;
+                    const unsigned char* messagePayload = NULL;
+                    if (!RetrieveMessagePayload(iothubMsgList->messageHandle, &messagePayload, &messageLength))
+                    {
+                        (void)(DList_RemoveEntryList(currentListEntry));
+                        sendMsgComplete(iothubMsgList, transport_data, IOTHUB_CLIENT_CONFIRMATION_ERROR);
+                        LogError("Failure result from IoTHubMessage_GetData");
+                    }
+                    else
+                    {
+                        /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_029: [IoTHubTransport_MQTT_Common_DoWork shall create a MQTT_MESSAGE_HANDLE and pass this to a call to mqtt_client_publish.] */
+                        MQTT_MESSAGE_DETAILS_LIST* mqttMsgEntry = (MQTT_MESSAGE_DETAILS_LIST*)malloc(sizeof(MQTT_MESSAGE_DETAILS_LIST));
+                        if (mqttMsgEntry == NULL)
+                        {
+                            LogError("Allocation Error: Failure allocating MQTT Message Detail List.");
+                        }
+                        else
+                        {
+                            mqttMsgEntry->retryCount = 0;
+                            mqttMsgEntry->iotHubMessageEntry = iothubMsgList;
+                            mqttMsgEntry->packet_id = get_next_packet_id(transport_data);
+                            if (publish_mqtt_telemetry_msg(transport_data, mqttMsgEntry, messagePayload, messageLength) != 0)
+                            {
+                                (void)(DList_RemoveEntryList(currentListEntry));
+                                sendMsgComplete(iothubMsgList, transport_data, IOTHUB_CLIENT_CONFIRMATION_ERROR);
+                                free(mqttMsgEntry);
+                            }
+                            else
+                            {
+                                // Remove the message from the waiting queue ...
+                                (void)(DList_RemoveEntryList(currentListEntry));
+                                // and add it to the ack queue
+                                DList_InsertTailList(&(transport_data->telemetry_waitingForAck), &(mqttMsgEntry->entry));
+                            }
+                        }
+                    }
+                    currentListEntry = savedFromCurrentListEntry.Flink;
+                }
+
+                if (transport_data->twin_resp_sub_recv)
+                {
+                    sendPendingGetTwinRequests(transport_data);
+                }
+            }
+            /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_030: [IoTHubTransport_MQTT_Common_DoWork shall call mqtt_client_dowork everytime it is called if it is connected.] */
+            mqtt_client_dowork(transport_data->mqttClient);
+        }
+
+        // Check the ack messages timeouts
+        process_queued_ack_messages(transport_data);
+        removeExpiredTwinRequests(transport_data);
+    }
+}
+
+IOTHUB_CLIENT_RESULT IoTHubTransport_MQTT_Common_GetSendStatus(TRANSPORT_LL_HANDLE handle, IOTHUB_CLIENT_STATUS *iotHubClientStatus)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    if (handle == NULL || iotHubClientStatus == NULL)
+    {
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_023: [IoTHubTransport_MQTT_Common_GetSendStatus shall return IOTHUB_CLIENT_INVALID_ARG if called with NULL parameter.] */
+    LogError("invalid arument.");
+    result = IOTHUB_CLIENT_INVALID_ARG;
+    }
+    else
+    {
+    MQTTTRANSPORT_HANDLE_DATA* handleData = (MQTTTRANSPORT_HANDLE_DATA*)handle;
+    if (!DList_IsListEmpty(handleData->waitingToSend) || !DList_IsListEmpty(&(handleData->telemetry_waitingForAck)))
+    {
+        /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_025: [IoTHubTransport_MQTT_Common_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_BUSY if there are currently event items to be sent or being sent.] */
+        *iotHubClientStatus = IOTHUB_CLIENT_SEND_STATUS_BUSY;
+    }
+    else
+    {
+        /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_024: [IoTHubTransport_MQTT_Common_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_IDLE if there are currently no event items to be sent or being sent.] */
+        *iotHubClientStatus = IOTHUB_CLIENT_SEND_STATUS_IDLE;
+    }
+    result = IOTHUB_CLIENT_OK;
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubTransport_MQTT_Common_SetOption(TRANSPORT_LL_HANDLE handle, const char* option, const void* value)
+{
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_021: [If any parameter is NULL then IoTHubTransport_MQTT_Common_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.] */
+    IOTHUB_CLIENT_RESULT result;
+    if (
+        (handle == NULL) ||
+        (option == NULL) ||
+        (value == NULL)
+        )
+    {
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LogError("invalid parameter (NULL) passed to IoTHubTransport_MQTT_Common_SetOption.");
+    }
+    else
+    {
+        MQTTTRANSPORT_HANDLE_DATA* transport_data = (MQTTTRANSPORT_HANDLE_DATA*)handle;
+
+        IOTHUB_CREDENTIAL_TYPE cred_type = IoTHubClient_Auth_Get_Credential_Type(transport_data->authorization_module);
+
+        /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_031: [If the option parameter is set to "logtrace" then the value shall be a bool_ptr and the value will determine if the mqtt client log is on or off.] */
+        if (strcmp(OPTION_LOG_TRACE, option) == 0)
+        {
+            transport_data->log_trace = *((bool*)value);
+            mqtt_client_set_trace(transport_data->mqttClient, transport_data->log_trace, transport_data->raw_trace);
+            result = IOTHUB_CLIENT_OK;
+        }
+        else if (strcmp("rawlogtrace", option) == 0)
+        {
+            transport_data->raw_trace = *((bool*)value);
+            mqtt_client_set_trace(transport_data->mqttClient, transport_data->log_trace, transport_data->raw_trace);
+            result = IOTHUB_CLIENT_OK;
+        }
+        else if (strcmp(OPTION_AUTO_URL_ENCODE_DECODE, option) == 0)
+        {
+            transport_data->auto_url_encode_decode = *((bool*)value);
+            result = IOTHUB_CLIENT_OK;
+        }
+        else if (strcmp(OPTION_CONNECTION_TIMEOUT, option) == 0)
+        {
+            int* connection_time = (int*)value;
+            if (*connection_time != transport_data->connect_timeout_in_sec)
+            {
+                transport_data->connect_timeout_in_sec = (uint16_t)(*connection_time);
+            }
+            result = IOTHUB_CLIENT_OK;
+        }
+        else if (strcmp(OPTION_KEEP_ALIVE, option) == 0)
+        {
+            /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_036: [If the option parameter is set to "keepalive" then the value shall be a int_ptr and the value will determine the mqtt keepalive time that is set for pings.] */
+            int* keepAliveOption = (int*)value;
+            /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_037 : [If the option parameter is set to supplied int_ptr keepalive is the same value as the existing keepalive then IoTHubTransport_MQTT_Common_SetOption shall do nothing.] */
+            if (*keepAliveOption != transport_data->keepAliveValue)
+            {
+                transport_data->keepAliveValue = (uint16_t)(*keepAliveOption);
+                if (transport_data->mqttClientStatus != MQTT_CLIENT_STATUS_NOT_CONNECTED)
+                {
+                    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_038: [If the client is connected when the keepalive is set then IoTHubTransport_MQTT_Common_SetOption shall disconnect and reconnect with the specified keepalive value.] */
+                    DisconnectFromClient(transport_data);
+                }
+            }
+            result = IOTHUB_CLIENT_OK;
+        }
+        /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_039: [If the option parameter is set to "x509certificate" then the value shall be a const char of the certificate to be used for x509.] */
+        else if ((strcmp(OPTION_X509_CERT, option) == 0) && (cred_type != IOTHUB_CREDENTIAL_TYPE_X509 && cred_type != IOTHUB_CREDENTIAL_TYPE_UNKNOWN))
+        {
+            LogError("x509certificate specified, but authentication method is not x509");
+            result = IOTHUB_CLIENT_INVALID_ARG;
+        }
+        /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_040: [If the option parameter is set to "x509privatekey" then the value shall be a const char of the RSA Private Key to be used for x509.] */
+        else if ((strcmp(OPTION_X509_PRIVATE_KEY, option) == 0) && (cred_type != IOTHUB_CREDENTIAL_TYPE_X509 && cred_type != IOTHUB_CREDENTIAL_TYPE_UNKNOWN))
+        {
+            LogError("x509privatekey specified, but authentication method is not x509");
+            result = IOTHUB_CLIENT_INVALID_ARG;
+        }
+        else if (strcmp(OPTION_RETRY_INTERVAL_SEC, option) == 0)
+        {
+            if (retry_control_set_option(transport_data->retry_control_handle, RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS, value) != 0)
+            {
+                LogError("Failure setting retry interval option");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else
+            {
+                result = IOTHUB_CLIENT_OK;
+            }
+        }
+        else if (strcmp(OPTION_RETRY_MAX_DELAY_SECS, option) == 0)
+        {
+            if (retry_control_set_option(transport_data->retry_control_handle, RETRY_CONTROL_OPTION_MAX_DELAY_IN_SECS, value) != 0)
+            {
+                LogError("Failure setting retry max delay option");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else
+            {
+                result = IOTHUB_CLIENT_OK;
+            }
+        }
+        else if (strcmp(OPTION_HTTP_PROXY, option) == 0)
+        {
+            /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_001: [ If `option` is `proxy_data`, `value` shall be used as an `HTTP_PROXY_OPTIONS*`. ]*/
+            HTTP_PROXY_OPTIONS* proxy_options = (HTTP_PROXY_OPTIONS*)value;
+
+            if (transport_data->xioTransport != NULL)
+            {
+                /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_007: [ If the underlying IO has already been created, then `IoTHubTransport_MQTT_Common_SetOption` shall fail and return `IOTHUB_CLIENT_ERROR`. ]*/
+                LogError("Cannot set proxy option once the underlying IO is created");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else if (proxy_options->host_address == NULL)
+            {
+                /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_003: [ If `host_address` is NULL, `IoTHubTransport_MQTT_Common_SetOption` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
+                LogError("NULL host_address in proxy options");
+                result = IOTHUB_CLIENT_INVALID_ARG;
+            }
+            /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_006: [ If only one of `username` and `password` is NULL, `IoTHubTransport_MQTT_Common_SetOption` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
+            else if (((proxy_options->username == NULL) || (proxy_options->password == NULL)) &&
+                (proxy_options->username != proxy_options->password))
+            {
+                LogError("Only one of username and password for proxy settings was NULL");
+                result = IOTHUB_CLIENT_INVALID_ARG;
+            }
+            else
+            {
+                char* copied_proxy_hostname = NULL;
+                char* copied_proxy_username = NULL;
+                char* copied_proxy_password = NULL;
+
+                /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_002: [ The fields `host_address`, `port`, `username` and `password` shall be saved for later used (needed when creating the underlying IO to be used by the transport). ]*/
+                transport_data->http_proxy_port = proxy_options->port;
+                if (mallocAndStrcpy_s(&copied_proxy_hostname, proxy_options->host_address) != 0)
+                {
+                    /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_004: [ If copying `host_address`, `username` or `password` fails, `IoTHubTransport_MQTT_Common_SetOption` shall fail and return `IOTHUB_CLIENT_ERROR`. ]*/
+                    LogError("Cannot copy HTTP proxy hostname");
+                    result = IOTHUB_CLIENT_ERROR;
+                }
+                /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_005: [ `username` and `password` shall be allowed to be NULL. ]*/
+                else if ((proxy_options->username != NULL) && (mallocAndStrcpy_s(&copied_proxy_username, proxy_options->username) != 0))
+                {
+                    /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_004: [ If copying `host_address`, `username` or `password` fails, `IoTHubTransport_MQTT_Common_SetOption` shall fail and return `IOTHUB_CLIENT_ERROR`. ]*/
+                    free(copied_proxy_hostname);
+                    LogError("Cannot copy HTTP proxy username");
+                    result = IOTHUB_CLIENT_ERROR;
+                }
+                /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_005: [ `username` and `password` shall be allowed to be NULL. ]*/
+                else if ((proxy_options->password != NULL) && (mallocAndStrcpy_s(&copied_proxy_password, proxy_options->password) != 0))
+                {
+                    /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_004: [ If copying `host_address`, `username` or `password` fails, `IoTHubTransport_MQTT_Common_SetOption` shall fail and return `IOTHUB_CLIENT_ERROR`. ]*/
+                    if (copied_proxy_username != NULL)
+                    {
+                        free(copied_proxy_username);
+                    }
+                    free(copied_proxy_hostname);
+                    LogError("Cannot copy HTTP proxy password");
+                    result = IOTHUB_CLIENT_ERROR;
+                }
+                else
+                {
+                    /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_009: [ When setting the proxy options succeeds any previously saved proxy options shall be freed. ]*/
+                    free_proxy_data(transport_data);
+
+                    transport_data->http_proxy_hostname = copied_proxy_hostname;
+                    transport_data->http_proxy_username = copied_proxy_username;
+                    transport_data->http_proxy_password = copied_proxy_password;
+
+                    /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_008: [ If setting the `proxy_data` option suceeds, `IoTHubTransport_MQTT_Common_SetOption` shall return `IOTHUB_CLIENT_OK` ]*/
+                    result = IOTHUB_CLIENT_OK;
+                }
+            }
+        }
+        else
+        {
+            /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_039: [If the option parameter is set to "x509certificate" then the value shall be a const char of the certificate to be used for x509.] */
+            if (((strcmp(OPTION_X509_CERT, option) == 0) || (strcmp(OPTION_X509_PRIVATE_KEY, option) == 0)) && (cred_type != IOTHUB_CREDENTIAL_TYPE_X509))
+            {
+                IoTHubClient_Auth_Set_x509_Type(transport_data->authorization_module, true);
+            }
+
+            /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_032: [IoTHubTransport_MQTT_Common_SetOption shall pass down the option to xio_setoption if the option parameter is not a known option string for the MQTT transport.] */
+            if (GetTransportProviderIfNecessary(transport_data) == 0)
+            {
+                if (xio_setoption(transport_data->xioTransport, option, value) == 0)
+                {
+                    result = IOTHUB_CLIENT_OK;
+                }
+                else
+                {
+                    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_132: [IoTHubTransport_MQTT_Common_SetOption shall return IOTHUB_CLIENT_INVALID_ARG xio_setoption fails] */
+                    result = IOTHUB_CLIENT_INVALID_ARG;
+                }
+            }
+            else
+            {
+                result = IOTHUB_CLIENT_ERROR;
+            }
+        }
+    }
+    return result;
+}
+
+static bool check_module_ids_equal(const char* transportModuleId, const char* deviceModuleId)
+{
+    if ((transportModuleId != NULL) && (deviceModuleId == NULL))
+    {
+        return false;
+    }
+    else if ((transportModuleId == NULL) && (deviceModuleId != NULL))
+    {
+        return false;
+    }
+    else if ((transportModuleId == NULL) && (deviceModuleId == NULL))
+    {
+        return true;
+    }
+    else
+    {
+        return (0 == strcmp(transportModuleId, deviceModuleId));
+    }
+}
+
+TRANSPORT_LL_HANDLE IoTHubTransport_MQTT_Common_Register(TRANSPORT_LL_HANDLE handle, const IOTHUB_DEVICE_CONFIG* device, PDLIST_ENTRY waitingToSend)
+{
+    TRANSPORT_LL_HANDLE result = NULL;
+
+    // Codes_SRS_IOTHUB_MQTT_TRANSPORT_17_001: [ IoTHubTransport_MQTT_Common_Register shall return NULL if the TRANSPORT_LL_HANDLE is NULL.]
+    // Codes_SRS_IOTHUB_MQTT_TRANSPORT_17_002: [ IoTHubTransport_MQTT_Common_Register shall return NULL if device or waitingToSend are NULL.]
+    if ((handle == NULL) || (device == NULL) || (waitingToSend == NULL))
+    {
+        LogError("IoTHubTransport_MQTT_Common_Register: handle, device or waitingToSend is NULL.");
+        result = NULL;
+    }
+    else
+    {
+        MQTTTRANSPORT_HANDLE_DATA* transport_data = (MQTTTRANSPORT_HANDLE_DATA*)handle;
+
+        // Codes_SRS_IOTHUB_MQTT_TRANSPORT_03_001: [ IoTHubTransport_MQTT_Common_Register shall return NULL if deviceId, or both deviceKey and deviceSasToken are NULL.]
+        if (device->deviceId == NULL)
+        {
+            LogError("IoTHubTransport_MQTT_Common_Register: deviceId is NULL.");
+            result = NULL;
+        }
+        // Codes_SRS_IOTHUB_MQTT_TRANSPORT_03_002: [ IoTHubTransport_MQTT_Common_Register shall return NULL if both deviceKey and deviceSasToken are provided.]
+        else if ((device->deviceKey != NULL) && (device->deviceSasToken != NULL))
+        {
+            LogError("IoTHubTransport_MQTT_Common_Register: Both deviceKey and deviceSasToken are defined. Only one can be used.");
+            result = NULL;
+        }
+        else
+        {
+            // Codes_SRS_IOTHUB_MQTT_TRANSPORT_17_003: [ IoTHubTransport_MQTT_Common_Register shall return NULL if deviceId or deviceKey do not match the deviceId and deviceKey passed in during IoTHubTransport_MQTT_Common_Create.]
+            if (strcmp(STRING_c_str(transport_data->device_id), device->deviceId) != 0)
+            {
+                LogError("IoTHubTransport_MQTT_Common_Register: deviceId does not match.");
+                result = NULL;
+            }
+            else if (!check_module_ids_equal(STRING_c_str(transport_data->module_id), device->moduleId))
+            {
+                LogError("IoTHubTransport_MQTT_Common_Register: moduleId does not match.");
+                result = NULL;
+            }
+            // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_43_001: [ IoTHubTransport_MQTT_Common_Register shall return NULL if deviceKey is NULL when credential type is IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY ]
+            else if (IoTHubClient_Auth_Get_Credential_Type(transport_data->authorization_module) == IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY &&
+                ((device->deviceKey == NULL) || (strcmp(IoTHubClient_Auth_Get_DeviceKey(transport_data->authorization_module), device->deviceKey) != 0)))
+            {
+                LogError("IoTHubTransport_MQTT_Common_Register: deviceKey does not match.");
+                result = NULL;
+            }
+            else
+            {
+                if (transport_data->isRegistered == true)
+                {
+                    LogError("Transport already has device registered by id: [%s]", device->deviceId);
+                    result = NULL;
+                }
+                else
+                {
+                    transport_data->isRegistered = true;
+                    // Codes_SRS_IOTHUB_MQTT_TRANSPORT_17_004: [ IoTHubTransport_MQTT_Common_Register shall return the TRANSPORT_LL_HANDLE as the TRANSPORT_LL_HANDLE. ]
+                    result = (TRANSPORT_LL_HANDLE)handle;
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+void IoTHubTransport_MQTT_Common_Unregister(TRANSPORT_LL_HANDLE deviceHandle)
+{
+    // Codes_SRS_IOTHUB_MQTT_TRANSPORT_17_005: [ If deviceHandle is NULL `IoTHubTransport_MQTT_Common_Unregister` shall do nothing. ]
+    if (deviceHandle != NULL)
+    {
+        MQTTTRANSPORT_HANDLE_DATA* transport_data = (MQTTTRANSPORT_HANDLE_DATA*)deviceHandle;
+
+        transport_data->isRegistered = false;
+    }
+}
+
+STRING_HANDLE IoTHubTransport_MQTT_Common_GetHostname(TRANSPORT_LL_HANDLE handle)
+{
+    STRING_HANDLE result;
+    /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_02_001: [ If handle is NULL then IoTHubTransport_MQTT_Common_GetHostname shall fail and return NULL. ]*/
+    if (handle == NULL)
+    {
+        result = NULL;
+    }
+    /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_02_002: [ Otherwise IoTHubTransport_MQTT_Common_GetHostname shall return a non-NULL STRING_HANDLE containg the hostname. ]*/
+    else if ((result = STRING_clone(((MQTTTRANSPORT_HANDLE_DATA*)(handle))->hostAddress)) == NULL)
+    {
+        LogError("Cannot provide the target host name (STRING_clone failed).");
+    }
+
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubTransport_MQTT_Common_SendMessageDisposition(MESSAGE_CALLBACK_INFO* message_data, IOTHUBMESSAGE_DISPOSITION_RESULT disposition)
+{
+    (void)disposition;
+
+    IOTHUB_CLIENT_RESULT result;
+    if (message_data)
+    {
+        if (message_data->messageHandle)
+        {
+            IoTHubMessage_Destroy(message_data->messageHandle);
+            result = IOTHUB_CLIENT_OK;
+        }
+        else
+        {
+            /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_10_002: [If any of the messageData fields are NULL, IoTHubTransport_MQTT_Common_SendMessageDisposition shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+            LogError("message handle is NULL");
+            result = IOTHUB_CLIENT_ERROR;
+        }
+        free(message_data);
+    }
+    else
+    {
+        /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_10_001: [If messageData is NULL, IoTHubTransport_MQTT_Common_SendMessageDisposition shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+        LogError("message_data is NULL");
+        result = IOTHUB_CLIENT_ERROR;
+    }
+    return result;
+}
+
+
+int IoTHubTransport_MQTT_Common_Subscribe_InputQueue(TRANSPORT_LL_HANDLE handle)
+{
+    int result;
+    PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
+    if (transport_data == NULL)
+    {
+        // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_066: [ If parameter handle is NULL than IoTHubTransport_MQTT_Common_Subscribe_InputQueue shall return a non-zero value.]
+        LogError("Invalid handle parameter. NULL.");
+        result = MU_FAILURE;
+    }
+    else if (transport_data->module_id == NULL)
+    {
+        // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_073: [ If module ID is not set on the transpont, IoTHubTransport_MQTT_Common_Unsubscribe_InputQueue shall fail.]
+        LogError("ModuleID must be specified for input queues. NULL.");
+        result = MU_FAILURE;
+    }
+    else if ((transport_data->topic_InputQueue == NULL) &&
+        (transport_data->topic_InputQueue = STRING_construct_sprintf(TOPIC_INPUT_QUEUE_NAME, STRING_c_str(transport_data->device_id), STRING_c_str(transport_data->module_id))) == NULL)
+    {
+        LogError("Failure constructing Message Topic");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_067: [ IoTHubTransport_MQTT_Common_Subscribe_InputQueue shall set a flag to enable mqtt_client_subscribe to be called to subscribe to the input queue Message Topic.]
+        transport_data->topics_ToSubscribe |= SUBSCRIBE_INPUT_QUEUE_TOPIC;
+        changeStateToSubscribeIfAllowed(transport_data);
+        // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_070: [ On success IoTHubTransport_MQTT_Common_Subscribe_InputQueue shall return 0.]
+        result = 0;
+    }
+    return result;
+}
+
+void IoTHubTransport_MQTT_Common_Unsubscribe_InputQueue(TRANSPORT_LL_HANDLE handle)
+{
+    PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
+    if ((transport_data != NULL) && (transport_data->topic_InputQueue != NULL))
+    {
+        // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_072: [ IoTHubTransport_MQTT_Common_Unsubscribe_InputQueue shall call mqtt_client_unsubscribe to unsubscribe the mqtt input queue message topic.]
+        const char* unsubscribe[1];
+        unsubscribe[0] = STRING_c_str(transport_data->topic_InputQueue);
+        if (mqtt_client_unsubscribe(transport_data->mqttClient, get_next_packet_id(transport_data), unsubscribe, 1) != 0)
+        {
+            LogError("Failure calling mqtt_client_unsubscribe");
+        }
+        STRING_delete(transport_data->topic_InputQueue);
+        transport_data->topic_InputQueue = NULL;
+        transport_data->topics_ToSubscribe &= ~SUBSCRIBE_INPUT_QUEUE_TOPIC;
+    }
+    else
+    {
+        // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_071: [ If parameter handle is NULL then IoTHubTransport_MQTT_Common_Unsubscribe_InputQueue shall do nothing.]
+        LogError("Invalid argument to unsubscribe input queue (NULL).");
+    }
+}
+
+int IoTHubTransport_MQTT_SetCallbackContext(TRANSPORT_LL_HANDLE handle, void* ctx)
+{
+    int result;
+    if (handle == NULL)
+    {
+        LogError("Invalid parameter specified handle: %p", handle);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        MQTTTRANSPORT_HANDLE_DATA* transport_data = (MQTTTRANSPORT_HANDLE_DATA*)handle;
+        transport_data->transport_ctx = ctx;
+        result = 0;
+    }
+    return result;
+}
+
+int IoTHubTransport_MQTT_GetSupportedPlatformInfo(TRANSPORT_LL_HANDLE handle, PLATFORM_INFO_OPTION* info)
+{
+    int result;
+
+    if (handle == NULL || info == NULL)
+    {
+        LogError("Invalid parameter specified (handle: %p, info: %p)", handle, info);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        *info = PLATFORM_INFO_OPTION_RETRIEVE_SQM;
+        result = 0;
+    }
+
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothubtransporthttp.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothubtransporthttp.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothubtransporthttp.c	(revision 453)
@@ -0,0 +1,2572 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "azure_c_shared_utility/gballoc.h"
+
+#include <time.h>
+#include "iothub_client_options.h"
+#include "iothub_client_version.h"
+#include "iothub_transport_ll.h"
+#include "iothubtransporthttp.h"
+#include "internal/iothub_client_private.h"
+#include "internal/iothubtransport.h"
+#include "internal/iothub_transport_ll_private.h"
+#include "internal/iothub_internal_consts.h"
+
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/httpapiexsas.h"
+#include "azure_c_shared_utility/urlencode.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/httpapiex.h"
+#include "azure_c_shared_utility/httpapiexsas.h"
+#include "azure_c_shared_utility/strings.h"
+#include "azure_c_shared_utility/azure_base64.h"
+#include "azure_c_shared_utility/doublylinkedlist.h"
+#include "azure_c_shared_utility/vector.h"
+#include "azure_c_shared_utility/httpheaders.h"
+#include "azure_c_shared_utility/agenttime.h"
+
+#define IOTHUB_APP_PREFIX "iothub-app-"
+static const char* IOTHUB_MESSAGE_ID = "iothub-messageid";
+static const char* IOTHUB_CORRELATION_ID = "iothub-correlationid";
+static const char* IOTHUB_CONTENT_TYPE_D2C = "iothub-contenttype";
+static const char* IOTHUB_CONTENT_ENCODING_D2C = "iothub-contentencoding";
+static const char* IOTHUB_CONTENT_TYPE_C2D = "ContentType";
+static const char* IOTHUB_CONTENT_ENCODING_C2D = "ContentEncoding";
+
+static const char* IOTHUB_AUTH_HEADER_VALUE = "Authorization";
+
+#define CONTENT_TYPE "Content-Type"
+#define APPLICATION_OCTET_STREAM "application/octet-stream"
+#define APPLICATION_VND_MICROSOFT_IOTHUB_JSON "application/vnd.microsoft.iothub.json"
+#define API_VERSION "?api-version=2016-11-14"
+#define EVENT_ENDPOINT "/messages/events"
+#define MESSAGE_ENDPOINT_HTTP "/messages/devicebound"
+#define MESSAGE_ENDPOINT_HTTP_ETAG "/messages/devicebound/"
+
+/*DEFAULT_GETMINIMUMPOLLINGTIME is the minimum time in seconds allowed between 2 consecutive GET issues to the service (GET=fetch messages)*/
+/*the default is 25 minutes*/
+#define DEFAULT_GETMINIMUMPOLLINGTIME ((unsigned int)25*60)
+
+#define MAXIMUM_MESSAGE_SIZE (255*1024-1)
+#define MAXIMUM_PAYLOAD_OVERHEAD 384
+#define MAXIMUM_PROPERTY_OVERHEAD 16
+
+/*forward declaration*/
+static int appendMapToJSON(STRING_HANDLE existing, const char* const* keys, const char* const* values, size_t count);
+
+typedef struct HTTPTRANSPORT_HANDLE_DATA_TAG
+{
+    STRING_HANDLE hostName;
+    HTTPAPIEX_HANDLE httpApiExHandle;
+    bool doBatchedTransfers;
+    unsigned int getMinimumPollingTime;
+    VECTOR_HANDLE perDeviceList;
+
+    TRANSPORT_CALLBACKS_INFO transport_callbacks;
+    void* transport_ctx;
+
+}HTTPTRANSPORT_HANDLE_DATA;
+
+typedef struct HTTPTRANSPORT_PERDEVICE_DATA_TAG
+{
+    HTTPTRANSPORT_HANDLE_DATA* transportHandle;
+
+    STRING_HANDLE deviceId;
+    STRING_HANDLE deviceKey;
+    STRING_HANDLE deviceSasToken;
+    STRING_HANDLE eventHTTPrelativePath;
+    STRING_HANDLE messageHTTPrelativePath;
+    HTTP_HEADERS_HANDLE eventHTTPrequestHeaders;
+    HTTP_HEADERS_HANDLE messageHTTPrequestHeaders;
+    STRING_HANDLE abandonHTTPrelativePathBegin;
+    HTTPAPIEX_SAS_HANDLE sasObject;
+    bool DoWork_PullMessage;
+    time_t lastPollTime;
+    bool isFirstPoll;
+
+    void* device_transport_ctx;
+    PDLIST_ENTRY waitingToSend;
+    DLIST_ENTRY eventConfirmations; /*holds items for event confirmations*/
+} HTTPTRANSPORT_PERDEVICE_DATA;
+
+typedef struct MESSAGE_DISPOSITION_CONTEXT_TAG
+{
+    HTTPTRANSPORT_HANDLE_DATA* handleData;
+    HTTPTRANSPORT_PERDEVICE_DATA* deviceData;
+    char* etagValue;
+} MESSAGE_DISPOSITION_CONTEXT;
+
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(IOTHUBMESSAGE_DISPOSITION_RESULT, IOTHUBMESSAGE_DISPOSITION_RESULT_VALUES);
+
+static void destroy_eventHTTPrelativePath(HTTPTRANSPORT_PERDEVICE_DATA* handleData)
+{
+    STRING_delete(handleData->eventHTTPrelativePath);
+    handleData->eventHTTPrelativePath = NULL;
+}
+
+static bool create_eventHTTPrelativePath(HTTPTRANSPORT_PERDEVICE_DATA* handleData, const char * deviceId)
+{
+    /*Codes_SRS_TRANSPORTMULTITHTTP_17_017: [ IoTHubTransportHttp_Register shall create an immutable string (further called "event HTTP relative path") from the following pieces: "/devices/" + URL_ENCODED(deviceId) + "/messages/events" + APIVERSION. ]*/
+    bool result;
+    STRING_HANDLE urlEncodedDeviceId;
+    handleData->eventHTTPrelativePath = STRING_construct("/devices/");
+    if (handleData->eventHTTPrelativePath == NULL)
+    {
+        LogError("STRING_construct failed.");
+        result = false;
+    }
+    else
+    {
+        if (!(
+            ((urlEncodedDeviceId = URL_EncodeString(deviceId)) != NULL) &&
+            (STRING_concat_with_STRING(handleData->eventHTTPrelativePath, urlEncodedDeviceId) == 0) &&
+            (STRING_concat(handleData->eventHTTPrelativePath, EVENT_ENDPOINT API_VERSION) == 0)
+            ))
+        {
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_018: [ If creating the string fail for any reason then IoTHubTransportHttp_Register shall fail and return NULL. ]*/
+            destroy_eventHTTPrelativePath(handleData);
+            LogError("Creating HTTP event relative path failed.");
+            result = false;
+        }
+        else
+        {
+            result = true;
+        }
+        STRING_delete(urlEncodedDeviceId);
+    }
+    return result;
+}
+
+static int retrieve_message_properties(HTTP_HEADERS_HANDLE resp_header, IOTHUB_MESSAGE_HANDLE recv_msg)
+{
+    int result = 0;
+    /*Codes_SRS_TRANSPORTMULTITHTTP_17_090: [All the HTTP headers of the form iothub-app-name:somecontent shall be transformed in message properties {name, somecontent}.]*/
+    /*Codes_SRS_TRANSPORTMULTITHTTP_17_091: [The HTTP header of iothub-messageid shall be set in the MessageId.]*/
+    size_t nHeaders;
+    if (HTTPHeaders_GetHeaderCount(resp_header, &nHeaders) != HTTP_HEADERS_OK)
+    {
+        LogError("unable to get the count of HTTP headers");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        MAP_HANDLE properties = (nHeaders > 0) ? IoTHubMessage_Properties(recv_msg) : NULL;
+        for (size_t index = 0; index < nHeaders; index++)
+        {
+            char* completeHeader;
+            if (HTTPHeaders_GetHeader(resp_header, index, &completeHeader) != HTTP_HEADERS_OK)
+            {
+                LogError("Failed getting header %lu", (unsigned long)index);
+                result = MU_FAILURE;
+                break;
+            }
+            else
+            {
+                char* colon_pos;
+                if (strncmp(IOTHUB_APP_PREFIX, completeHeader, strlen(IOTHUB_APP_PREFIX)) == 0)
+                {
+                    /*looks like a property headers*/
+                    /*there's a guaranteed ':' in the completeHeader, by HTTP_HEADERS module*/
+                    colon_pos = strchr(completeHeader, ':');
+                    if (colon_pos != NULL)
+                    {
+                        *colon_pos = '\0'; /*cut it down*/
+                        if (Map_AddOrUpdate(properties, completeHeader + strlen(IOTHUB_APP_PREFIX), colon_pos + 2) != MAP_OK) /*whereIsColon+1 is a space because HTTPEHADERS outputs a ": " between name and value*/
+                        {
+                            free(completeHeader);
+                            result = MU_FAILURE;
+                            break;
+                        }
+                    }
+                }
+                else if (strncmp(IOTHUB_MESSAGE_ID, completeHeader, strlen(IOTHUB_MESSAGE_ID)) == 0)
+                {
+                    char* whereIsColon = strchr(completeHeader, ':');
+                    if (whereIsColon != NULL)
+                    {
+                        *whereIsColon = '\0'; /*cut it down*/
+                        if (IoTHubMessage_SetMessageId(recv_msg, whereIsColon + 2) != IOTHUB_MESSAGE_OK)
+                        {
+                            free(completeHeader);
+                            result = MU_FAILURE;
+                            break;
+                        }
+                    }
+                }
+                else if (strncmp(IOTHUB_CORRELATION_ID, completeHeader, strlen(IOTHUB_CORRELATION_ID)) == 0)
+                {
+                    char* whereIsColon = strchr(completeHeader, ':');
+                    if (whereIsColon != NULL)
+                    {
+                        *whereIsColon = '\0'; /*cut it down*/
+                        if (IoTHubMessage_SetCorrelationId(recv_msg, whereIsColon + 2) != IOTHUB_MESSAGE_OK)
+                        {
+                            free(completeHeader);
+                            result = MU_FAILURE;
+                            break;
+                        }
+                    }
+                }
+                // Codes_SRS_TRANSPORTMULTITHTTP_09_003: [ The HTTP header value of `ContentType` shall be set in the `IoTHubMessage_SetContentTypeSystemProperty`. ]
+                else if (strncmp(IOTHUB_CONTENT_TYPE_C2D, completeHeader, strlen(IOTHUB_CONTENT_TYPE_C2D)) == 0)
+                {
+                    char* whereIsColon = strchr(completeHeader, ':');
+                    if (whereIsColon != NULL)
+                    {
+                        *whereIsColon = '\0'; /*cut it down*/
+                        if (IoTHubMessage_SetContentTypeSystemProperty(recv_msg, whereIsColon + 2) != IOTHUB_MESSAGE_OK)
+                        {
+                            LogError("Failed setting IoTHubMessage content-type");
+                            result = MU_FAILURE;
+                            break;
+                        }
+                    }
+                }
+                // Codes_SRS_TRANSPORTMULTITHTTP_09_004: [ The HTTP header value of `ContentEncoding` shall be set in the `IoTHub_SetContentEncoding`. ]
+                else if (strncmp(IOTHUB_CONTENT_ENCODING_C2D, completeHeader, strlen(IOTHUB_CONTENT_ENCODING_C2D)) == 0)
+                {
+                    char* whereIsColon = strchr(completeHeader, ':');
+                    if (whereIsColon != NULL)
+                    {
+                        *whereIsColon = '\0'; /*cut it down*/
+                        if (IoTHubMessage_SetContentEncodingSystemProperty(recv_msg, whereIsColon + 2) != IOTHUB_MESSAGE_OK)
+                        {
+                            LogError("Failed setting IoTHubMessage content-encoding");
+                            break;
+                        }
+                    }
+                }
+                free(completeHeader);
+            }
+        }
+    }
+    return result;
+}
+
+static int set_system_properties(IOTHUB_MESSAGE_LIST* message, HTTP_HEADERS_HANDLE headers)
+{
+    int result;
+    const char* msgId;
+    const char* corrId;
+    const char* content_type;
+    const char* contentEncoding;
+
+    // Add the Message Id and the Correlation Id
+    msgId = IoTHubMessage_GetMessageId(message->messageHandle);
+    if (msgId != NULL && HTTPHeaders_ReplaceHeaderNameValuePair(headers, IOTHUB_MESSAGE_ID, msgId) != HTTP_HEADERS_OK)
+    {
+        LogError("unable to HTTPHeaders_ReplaceHeaderNameValuePair");
+        result = MU_FAILURE;
+    }
+    else if ((corrId = IoTHubMessage_GetCorrelationId(message->messageHandle)) != NULL && HTTPHeaders_ReplaceHeaderNameValuePair(headers, IOTHUB_CORRELATION_ID, corrId) != HTTP_HEADERS_OK)
+    {
+        LogError("unable to HTTPHeaders_ReplaceHeaderNameValuePair");
+        result = MU_FAILURE;
+    }
+    // Codes_SRS_TRANSPORTMULTITHTTP_09_001: [ If the IoTHubMessage being sent contains property `content-type` it shall be added to the HTTP headers as "iothub-contenttype":"value". ]
+    else if ((content_type = IoTHubMessage_GetContentTypeSystemProperty(message->messageHandle)) != NULL && HTTPHeaders_ReplaceHeaderNameValuePair(headers, IOTHUB_CONTENT_TYPE_D2C, content_type) != HTTP_HEADERS_OK)
+    {
+        LogError("unable to HTTPHeaders_ReplaceHeaderNameValuePair (content-type)");
+        result = MU_FAILURE;
+    }
+    // Codes_SRS_TRANSPORTMULTITHTTP_09_002: [ If the IoTHubMessage being sent contains property `content-encoding` it shall be added to the HTTP headers as "iothub-contentencoding":"value". ]
+    else if ((contentEncoding = IoTHubMessage_GetContentEncodingSystemProperty(message->messageHandle)) != NULL && HTTPHeaders_ReplaceHeaderNameValuePair(headers, IOTHUB_CONTENT_ENCODING_D2C, contentEncoding) != HTTP_HEADERS_OK)
+    {
+        LogError("unable to HTTPHeaders_ReplaceHeaderNameValuePair (content-encoding)");
+        result = MU_FAILURE;
+    }
+    else if (IoTHubMessage_IsSecurityMessage(message->messageHandle) && HTTPHeaders_ReplaceHeaderNameValuePair(headers, SECURITY_INTERFACE_ID, SECURITY_INTERFACE_ID_VALUE) != HTTP_HEADERS_OK)
+    {
+        LogError("unable to set security message header info");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        result = 0;
+    }
+    return result;
+}
+
+static bool set_message_properties(IOTHUB_MESSAGE_LIST* message, size_t* msg_size, HTTP_HEADERS_HANDLE headers, HTTPTRANSPORT_HANDLE_DATA* handleData, HTTPTRANSPORT_PERDEVICE_DATA* deviceData)
+{
+    bool result = true;
+
+    /*Codes_SRS_TRANSPORTMULTITHTTP_17_078: [Every message property "property":"value" shall be added to the HTTP headers as an individual header "iothub-app-property":"value".] */
+    MAP_HANDLE map = IoTHubMessage_Properties(message->messageHandle);
+    const char*const* keys;
+    const char*const* values;
+    size_t count;
+    if (Map_GetInternals(map, &keys, &values, &count) != MAP_OK)
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_079: [If any HTTP header operation fails, _DoWork shall advance to the next action.] */
+        LogError("unable to Map_GetInternals");
+        result = false;
+    }
+    else
+    {
+        for (size_t index = 0; index < count; index++)
+        {
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_074: [Every property name shall add  to the message size the length of the property name + the length of the property value + 16 bytes.] */
+            *msg_size += (strlen(values[index]) + strlen(keys[index]) + MAXIMUM_PROPERTY_OVERHEAD);
+            if (*msg_size > MAXIMUM_MESSAGE_SIZE)
+            {
+                /*Codes_SRS_TRANSPORTMULTITHTTP_17_072: [The message size shall be limited to 255KB -1 bytes.] */
+                PDLIST_ENTRY head = DList_RemoveHeadList(deviceData->waitingToSend); /*actually this is the same as "actual", but now it is removed*/
+                DList_InsertTailList(&(deviceData->eventConfirmations), head);
+                handleData->transport_callbacks.send_complete_cb(&(deviceData->eventConfirmations), IOTHUB_CLIENT_CONFIRMATION_ERROR, deviceData->device_transport_ctx); // takes care of emptying the list too
+                result = false;
+                break;
+            }
+            else
+            {
+                STRING_HANDLE app_construct = STRING_construct_sprintf("%s%s", IOTHUB_APP_PREFIX, keys[index]);
+                if (app_construct == NULL)
+                {
+                    /*Codes_SRS_TRANSPORTMULTITHTTP_17_079: [If any HTTP header operation fails, _DoWork shall advance to the next action.] */
+                    LogError("Unable to construct app header");
+                    result = false;
+                    break;
+                }
+                else
+                {
+                    if (HTTPHeaders_ReplaceHeaderNameValuePair(headers, STRING_c_str(app_construct), values[index]) != HTTP_HEADERS_OK)
+                    {
+                        /*Codes_SRS_TRANSPORTMULTITHTTP_17_079: [If any HTTP header operation fails, _DoWork shall advance to the next action.] */
+                        LogError("Unable to add app properties to http header");
+                        result = false;
+                        break;
+                    }
+                    STRING_delete(app_construct);
+                }
+            }
+        }
+    }
+    return result;
+}
+
+static void destroy_messageHTTPrelativePath(HTTPTRANSPORT_PERDEVICE_DATA* handleData)
+{
+    STRING_delete(handleData->messageHTTPrelativePath);
+    handleData->messageHTTPrelativePath = NULL;
+}
+
+static bool create_messageHTTPrelativePath(HTTPTRANSPORT_PERDEVICE_DATA* handleData, const char * deviceId)
+{
+    bool result;
+    handleData->messageHTTPrelativePath = STRING_construct("/devices/");
+    if (handleData->messageHTTPrelativePath == NULL)
+    {
+        LogError("STRING_construct failed.");
+        result = false;
+    }
+    else
+    {
+        STRING_HANDLE urlEncodedDeviceId;
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_019: [ IoTHubTransportHttp_Register shall create an immutable string (further called "message HTTP relative path") from the following pieces: "/devices/" + URL_ENCODED(deviceId) + "/messages/devicebound" + APIVERSION. ]*/
+        if (!(
+            ((urlEncodedDeviceId = URL_EncodeString(deviceId)) != NULL) &&
+            (STRING_concat_with_STRING(handleData->messageHTTPrelativePath, urlEncodedDeviceId) == 0) &&
+            (STRING_concat(handleData->messageHTTPrelativePath, MESSAGE_ENDPOINT_HTTP API_VERSION) == 0)
+            ))
+        {
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_020: [ If creating the message HTTP relative path fails, then IoTHubTransportHttp_Register shall fail and return NULL. ]*/
+            LogError("Creating HTTP message relative path failed.");
+            result = false;
+            destroy_messageHTTPrelativePath(handleData);
+        }
+        else
+        {
+            result = true;
+        }
+        STRING_delete(urlEncodedDeviceId);
+    }
+
+    return result;
+}
+
+static void destroy_eventHTTPrequestHeaders(HTTPTRANSPORT_PERDEVICE_DATA* handleData)
+{
+    HTTPHeaders_Free(handleData->eventHTTPrequestHeaders);
+    handleData->eventHTTPrequestHeaders = NULL;
+}
+
+static HTTP_HEADERS_RESULT addUserAgentHeaderInfo(HTTPTRANSPORT_HANDLE_DATA* transport_data, HTTP_HEADERS_HANDLE eventHTTPrequestHeaders)
+{
+    HTTP_HEADERS_RESULT result;
+    const char* product_info = transport_data->transport_callbacks.prod_info_cb(transport_data->transport_ctx);
+    if (product_info == NULL)
+    {
+        result = HTTPHeaders_AddHeaderNameValuePair(eventHTTPrequestHeaders, "User-Agent", CLIENT_DEVICE_TYPE_PREFIX CLIENT_DEVICE_BACKSLASH IOTHUB_SDK_VERSION);
+    }
+    else
+    {
+        result = HTTPHeaders_AddHeaderNameValuePair(eventHTTPrequestHeaders, "User-Agent", product_info);
+    }
+    return result;
+}
+
+static bool create_eventHTTPrequestHeaders(HTTPTRANSPORT_PERDEVICE_DATA* handleData, HTTPTRANSPORT_HANDLE_DATA* transport_data, const char * deviceId, bool is_x509_used)
+{
+    /*Codes_SRS_TRANSPORTMULTITHTTP_17_021: [ IoTHubTransportHttp_Register shall create a set of HTTP headers (further called "event HTTP request headers") consisting of the following fixed field names and values: "iothub-to":"/devices/" + URL_ENCODED(deviceId) + "/messages/events"; "Authorization":""
+    "Accept":"application/json"
+    "Connection":"Keep-Alive" ]*/
+    bool result;
+    handleData->eventHTTPrequestHeaders = HTTPHeaders_Alloc();
+    if (handleData->eventHTTPrequestHeaders == NULL)
+    {
+        LogError("HTTPHeaders_Alloc failed.");
+        result = false;
+    }
+    else
+    {
+        STRING_HANDLE temp = STRING_construct("/devices/");
+        if (temp == NULL)
+        {
+            LogError("STRING_construct failed.");
+            result = false;
+            destroy_eventHTTPrequestHeaders(handleData);
+        }
+        else
+        {
+            STRING_HANDLE urlEncodedDeviceId;
+            if (!(
+                ((urlEncodedDeviceId = URL_EncodeString(deviceId)) != NULL) &&
+                (STRING_concat_with_STRING(temp, urlEncodedDeviceId) == 0) &&
+                (STRING_concat(temp, EVENT_ENDPOINT) == 0)
+                ))
+            {
+                LogError("deviceId construction failed.");
+                result = false;
+                destroy_eventHTTPrequestHeaders(handleData);
+            }
+            else
+            {
+                if (!(
+                    (HTTPHeaders_AddHeaderNameValuePair(handleData->eventHTTPrequestHeaders, "iothub-to", STRING_c_str(temp)) == HTTP_HEADERS_OK) &&
+                    (is_x509_used || (HTTPHeaders_AddHeaderNameValuePair(handleData->eventHTTPrequestHeaders, IOTHUB_AUTH_HEADER_VALUE, " ") == HTTP_HEADERS_OK)) &&
+                    (HTTPHeaders_AddHeaderNameValuePair(handleData->eventHTTPrequestHeaders, "Accept", "application/json") == HTTP_HEADERS_OK) &&
+                    (HTTPHeaders_AddHeaderNameValuePair(handleData->eventHTTPrequestHeaders, "Connection", "Keep-Alive") == HTTP_HEADERS_OK) &&
+                    (addUserAgentHeaderInfo(transport_data, handleData->eventHTTPrequestHeaders) == HTTP_HEADERS_OK)
+                    ))
+                {
+                    /*Codes_SRS_TRANSPORTMULTITHTTP_17_022: [ If creating the event HTTP request headers fails, then IoTHubTransportHttp_Register shall fail and return NULL.] */
+                    LogError("adding header properties failed.");
+                    result = false;
+                    destroy_eventHTTPrequestHeaders(handleData);
+                }
+                else
+                {
+                    result = true;
+                }
+            }
+            STRING_delete(urlEncodedDeviceId);
+            STRING_delete(temp);
+        }
+    }
+    return result;
+}
+
+static void destroy_messageHTTPrequestHeaders(HTTPTRANSPORT_PERDEVICE_DATA* handleData)
+{
+    HTTPHeaders_Free(handleData->messageHTTPrequestHeaders);
+    handleData->messageHTTPrequestHeaders = NULL;
+}
+
+static bool create_messageHTTPrequestHeaders(HTTPTRANSPORT_PERDEVICE_DATA* handleData, HTTPTRANSPORT_HANDLE_DATA* transport_data, bool is_x509_used)
+{
+    /*Codes_SRS_TRANSPORTMULTITHTTP_17_132: [ IoTHubTransportHttp_Register shall create a set of HTTP headers (further called "message HTTP request headers") consisting of the following fixed field names and values:
+    "Authorization": "" ]*/
+    bool result;
+    handleData->messageHTTPrequestHeaders = HTTPHeaders_Alloc();
+    if (handleData->messageHTTPrequestHeaders == NULL)
+    {
+        LogError("HTTPHeaders_Alloc failed.");
+        result = false;
+    }
+    else
+    {
+        if (!(
+            (addUserAgentHeaderInfo(transport_data, handleData->messageHTTPrequestHeaders) == HTTP_HEADERS_OK) &&
+            (is_x509_used || (HTTPHeaders_AddHeaderNameValuePair(handleData->messageHTTPrequestHeaders, IOTHUB_AUTH_HEADER_VALUE, " ") == HTTP_HEADERS_OK))
+            ))
+        {
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_023: [ If creating message HTTP request headers then IoTHubTransportHttp_Register shall fail and return NULL. ]*/
+            destroy_messageHTTPrequestHeaders(handleData);
+            LogError("adding header properties failed.");
+            result = false;
+        }
+        else
+        {
+            result = true;
+        }
+    }
+    return result;
+}
+
+static void destroy_abandonHTTPrelativePathBegin(HTTPTRANSPORT_PERDEVICE_DATA* handleData)
+{
+    STRING_delete(handleData->abandonHTTPrelativePathBegin);
+    handleData->abandonHTTPrelativePathBegin = NULL;
+}
+
+static bool create_abandonHTTPrelativePathBegin(HTTPTRANSPORT_PERDEVICE_DATA* handleData, const char * deviceId)
+{
+    /*Codes_SRS_TRANSPORTMULTITHTTP_17_024: [ IoTHubTransportHttp_Register shall create a STRING containing: "/devices/" + URL_ENCODED(device id) +"/messages/deviceBound/" called abandonHTTPrelativePathBegin. ]*/
+    bool result;
+    handleData->abandonHTTPrelativePathBegin = STRING_construct("/devices/");
+    if (handleData->abandonHTTPrelativePathBegin == NULL)
+    {
+        result = false;
+    }
+    else
+    {
+        STRING_HANDLE urlEncodedDeviceId;
+        if (!(
+            ((urlEncodedDeviceId = URL_EncodeString(deviceId)) != NULL) &&
+            (STRING_concat_with_STRING(handleData->abandonHTTPrelativePathBegin, urlEncodedDeviceId) == 0) &&
+            (STRING_concat(handleData->abandonHTTPrelativePathBegin, MESSAGE_ENDPOINT_HTTP_ETAG) == 0)
+            ))
+        {
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_025: [ If creating the abandonHTTPrelativePathBegin fails then IoTHubTransportHttp_Register shall fail and return NULL. ]*/
+            LogError("unable to create abandon path string.");
+            STRING_delete(handleData->abandonHTTPrelativePathBegin);
+            result = false;
+        }
+        else
+        {
+            result = true;
+        }
+        STRING_delete(urlEncodedDeviceId);
+    }
+    return result;
+}
+
+static void destroy_SASObject(HTTPTRANSPORT_PERDEVICE_DATA* handleData)
+{
+    HTTPAPIEX_SAS_Destroy(handleData->sasObject);
+    handleData->sasObject = NULL;
+}
+
+static bool create_deviceSASObject(HTTPTRANSPORT_PERDEVICE_DATA* handleData, STRING_HANDLE hostName, const char * deviceId, const char * deviceKey)
+{
+    STRING_HANDLE keyName;
+    bool result;
+    /*Codes_SRS_TRANSPORTMULTITHTTP_17_026: [IoTHubTransportHttp_Create shall invoke URL_EncodeString with an argument of device id.]*/
+    keyName = URL_EncodeString(deviceId);
+    if (keyName == NULL)
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_027: [If the encode fails then IoTHubTransportHttp_Create shall fail and return NULL.]*/
+        LogError("URL_EncodeString keyname failed");
+        result = false;
+    }
+    else
+    {
+        STRING_HANDLE uriResource;
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_028: [IoTHubTransportHttp_Create shall invoke STRING_clone using the previously created hostname.]*/
+        uriResource = STRING_clone(hostName);
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_029: [If the clone fails then IoTHubTransportHttp_Create shall fail and return NULL.]*/
+        if (uriResource != NULL)
+        {
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_030: [IoTHubTransportHttp_Create shall invoke STRING_concat with arguments uriResource and the string "/devices/".]*/
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_141: [If the concat fails then IoTHubTransportHttp_Create shall fail and return NULL.]*/
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_031: [IoTHubTransportHttp_Create shall invoke STRING_concat_with_STRING with arguments uriResource and keyName.]*/
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_032: [If the STRING_concat_with_STRING fails then IoTHubTransportHttp_Create shall fail and return NULL.]*/
+            if ((STRING_concat(uriResource, "/devices/") == 0) &&
+                (STRING_concat_with_STRING(uriResource, keyName) == 0))
+            {
+                /*Codes_SRS_TRANSPORTMULTITHTTP_17_033: [IoTHubTransportHttp_Create shall invoke STRING_construct with an argument of config->upperConfig->deviceKey.]*/
+                /*Codes_SRS_TRANSPORTMULTITHTTP_17_034: [If the STRING_construct fails then IoTHubTransportHttp_Create shall fail and return NULL.]*/
+                STRING_HANDLE key = STRING_construct(deviceKey);
+                if (key != NULL)
+                {
+                    /*Codes_SRS_TRANSPORTMULTITHTTP_17_035: [The keyName is shortened to zero length, if that fails then IoTHubTransportHttp_Create shall fail and return NULL.]*/
+                    if (STRING_empty(keyName) != 0)
+                    {
+                        LogError("Unable to form the device key name for the SAS");
+                        result = false;
+                    }
+                    else
+                    {
+                        /*Codes_SRS_TRANSPORTMULTITHTTP_17_036: [IoTHubTransportHttp_Create shall invoke HTTPAPIEX_SAS_Create with arguments key, uriResource, and zero length keyName.]*/
+                        /*Codes_SRS_TRANSPORTMULTITHTTP_17_037: [If the HTTPAPIEX_SAS_Create fails then IoTHubTransportHttp_Create shall fail and return NULL.]*/
+                        handleData->sasObject = HTTPAPIEX_SAS_Create(key, uriResource, keyName);
+                        result = (handleData->sasObject != NULL) ? (true) : (false);
+                    }
+                    STRING_delete(key);
+                }
+                else
+                {
+                    LogError("STRING_construct Key failed");
+                    result = false;
+                }
+            }
+            else
+            {
+                LogError("STRING_concat uri resource failed");
+                result = false;
+            }
+            STRING_delete(uriResource);
+        }
+        else
+        {
+            LogError("STRING_staticclone uri resource failed");
+            result = false;
+        }
+        STRING_delete(keyName);
+    }
+    return result;
+}
+
+static void destroy_deviceId(HTTPTRANSPORT_PERDEVICE_DATA* handleData)
+{
+    STRING_delete(handleData->deviceId);
+    handleData->deviceId = NULL;
+}
+
+static bool create_deviceId(HTTPTRANSPORT_PERDEVICE_DATA* handleData, const char * deviceId)
+{
+    /*Codes_SRS_TRANSPORTMULTITHTTP_17_133: [ IoTHubTransportHttp_Register shall create an immutable string (further called "deviceId") from config->deviceConfig->deviceId. ]*/
+    bool result;
+    handleData->deviceId = STRING_construct(deviceId);
+    if (handleData->deviceId == NULL)
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_134: [ If deviceId is not created, then IoTHubTransportHttp_Register shall fail and return NULL. */
+        LogError("STRING_construct deviceId failed");
+        result = false;
+    }
+    else
+    {
+        result = true;
+    }
+    return result;
+}
+
+static void destroy_deviceKey(HTTPTRANSPORT_PERDEVICE_DATA* handleData)
+{
+    STRING_delete(handleData->deviceKey);
+    handleData->deviceKey = NULL;
+}
+
+static void destroy_deviceSas(HTTPTRANSPORT_PERDEVICE_DATA* handleData)
+{
+    STRING_delete(handleData->deviceSasToken);
+    handleData->deviceSasToken = NULL;
+}
+
+static bool create_deviceKey(HTTPTRANSPORT_PERDEVICE_DATA* handleData, const char * deviceKey)
+{
+    /*Codes_SRS_TRANSPORTMULTITHTTP_17_135: [ IoTHubTransportHttp_Register shall create an immutable string (further called "deviceKey") from deviceKey. ]*/
+    bool result;
+    handleData->deviceKey = STRING_construct(deviceKey);
+    if (handleData->deviceKey == NULL)
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_136: [ If deviceKey is not created, then IoTHubTransportHttp_Register shall fail and return NULL. ]*/
+        LogError("STRING_construct deviceKey failed");
+        result = false;
+    }
+    else
+    {
+        result = true;
+    }
+    return result;
+}
+
+static void destroy_deviceSasToken(HTTPTRANSPORT_PERDEVICE_DATA* handleData)
+{
+    STRING_delete(handleData->deviceSasToken);
+    handleData->deviceSasToken = NULL;
+}
+
+static bool create_deviceSasToken(HTTPTRANSPORT_PERDEVICE_DATA* handleData, const char * deviceSasToken)
+{
+    /*Codes_SRS_TRANSPORTMULTITHTTP_03_135: [ IoTHubTransportHttp_Register shall create an immutable string (further called "deviceSasToken") from deviceSasToken. ]*/
+    bool result;
+    handleData->deviceSasToken = STRING_construct(deviceSasToken);
+    if (handleData->deviceSasToken == NULL)
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_03_136: [ If deviceSasToken is not created, then IoTHubTransportHttp_Register shall fail and return NULL. ]*/
+        LogError("STRING_construct deviceSasToken failed");
+        result = false;
+    }
+    else
+    {
+        result = true;
+    }
+    return result;
+}
+
+/*
+* List queries  Find by handle and find by device name
+*/
+
+/*Codes_SRS_TRANSPORTMULTITHTTP_17_137: [ IoTHubTransportHttp_Register shall search the devices list for any device matching name deviceId. If deviceId is found it shall return NULL. ]*/
+static bool findDeviceHandle(const void* element, const void* value)
+{
+    bool result;
+    /* data stored at element is device handle */
+    const IOTHUB_DEVICE_HANDLE * guess = (const IOTHUB_DEVICE_HANDLE *)element;
+    IOTHUB_DEVICE_HANDLE match = (IOTHUB_DEVICE_HANDLE)value;
+    result = (*guess == match) ? true : false;
+    return result;
+}
+
+static bool findDeviceById(const void* element, const void* value)
+{
+    bool result;
+    const char* deviceId = (const char *)value;
+    const HTTPTRANSPORT_PERDEVICE_DATA * perDeviceElement = *(const HTTPTRANSPORT_PERDEVICE_DATA **)element;
+
+    result = (strcmp(STRING_c_str(perDeviceElement->deviceId), deviceId) == 0);
+
+    return result;
+}
+
+static IOTHUB_DEVICE_HANDLE IoTHubTransportHttp_Register(TRANSPORT_LL_HANDLE handle, const IOTHUB_DEVICE_CONFIG* device, PDLIST_ENTRY waitingToSend)
+{
+    HTTPTRANSPORT_PERDEVICE_DATA* result;
+    if (handle == NULL || device == NULL)
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_142: [ If handle is NULL or device is NULL, then IoTHubTransportHttp_Register shall return NULL. ]*/
+        LogError("Transport handle is NULL");
+        result = NULL;
+    }
+    else if (device->deviceId == NULL || ((device->deviceKey != NULL) && (device->deviceSasToken != NULL)) || waitingToSend == NULL)
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_015: [ If IOTHUB_DEVICE_CONFIG fields deviceKey and deviceSasToken are NULL, then IoTHubTransportHttp_Register shall assume a x509 authentication. ]*/
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_014: [ If IOTHUB_DEVICE_CONFIG field deviceId is NULL, then IoTHubTransportHttp_Register shall return NULL. ]*/
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_016: [ If parameter waitingToSend is NULL, then IoTHubTransportHttp_Register shall return NULL. ]*/
+        LogError("invalid parameters detected TRANSPORT_LL_HANDLE handle=%p, const IOTHUB_DEVICE_CONFIG* device=%p, PDLIST_ENTRY waitingToSend=%p",
+            handle, device, waitingToSend);
+        result = NULL;
+    }
+    else
+    {
+        HTTPTRANSPORT_HANDLE_DATA* handleData = (HTTPTRANSPORT_HANDLE_DATA*)handle;
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_137: [ IoTHubTransportHttp_Register shall search the devices list for any device matching name deviceId. If deviceId is found it shall return NULL. ]*/
+        void* listItem = VECTOR_find_if(handleData->perDeviceList, findDeviceById, device->deviceId);
+        if (listItem != NULL)
+        {
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_137: [ IoTHubTransportHttp_Register shall search the devices list for any device matching name deviceId. If deviceId is found it shall return NULL. ]*/
+            LogError("Transport already has device registered by id: [%s]", device->deviceId);
+            result = NULL;
+        }
+        else
+        {
+            bool was_create_deviceKey_ok = false;
+            bool was_create_deviceSasToken_ok = false;
+            bool was_sasObject_ok = false;
+            bool was_x509_ok = false; /*there's nothing "created" in the case of x509, it is a flag indicating that x509 is used*/
+
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_038: [ Otherwise, IoTHubTransportHttp_Register shall allocate the IOTHUB_DEVICE_HANDLE structure. ]*/
+            bool was_resultCreated_ok = ((result = (HTTPTRANSPORT_PERDEVICE_DATA *)malloc(sizeof(HTTPTRANSPORT_PERDEVICE_DATA))) != NULL);
+            bool was_create_deviceId_ok = was_resultCreated_ok && create_deviceId(result, device->deviceId);
+
+            if (was_create_deviceId_ok)
+            {
+                if (device->deviceSasToken != NULL)
+                {
+                    /*device->deviceKey is certainly NULL (because of the validation condition (else if (device->deviceId == NULL || ((device->deviceKey != NULL) && (device->deviceSasToken != NULL)) || waitingToSend == NULL))that does not accept that both satoken AND devicekey are non-NULL*/
+                    was_create_deviceSasToken_ok = create_deviceSasToken(result, device->deviceSasToken);
+                    result->deviceKey = NULL;
+                    result->sasObject = NULL;
+                }
+                else /*when deviceSasToken == NULL*/
+                {
+                    if (device->deviceKey != NULL)
+                    {
+                        was_create_deviceKey_ok = create_deviceKey(result, device->deviceKey);
+                        result->deviceSasToken = NULL;
+                    }
+                    else
+                    {
+                        /*when both of them are NULL*/
+                        was_x509_ok = true;
+                        result->deviceKey = NULL;
+                        result->deviceSasToken = NULL;
+                    }
+                }
+            }
+
+            bool was_eventHTTPrelativePath_ok = (was_create_deviceKey_ok || was_create_deviceSasToken_ok || was_x509_ok) && create_eventHTTPrelativePath(result, device->deviceId);
+            bool was_messageHTTPrelativePath_ok = was_eventHTTPrelativePath_ok && create_messageHTTPrelativePath(result, device->deviceId);
+            bool was_eventHTTPrequestHeaders_ok;
+            if (was_messageHTTPrelativePath_ok)
+            {
+                result->device_transport_ctx = handleData->transport_ctx;
+                was_eventHTTPrequestHeaders_ok = create_eventHTTPrequestHeaders(result, handleData, device->deviceId, was_x509_ok);
+            }
+            else
+            {
+                was_eventHTTPrequestHeaders_ok = false;
+            }
+            bool was_messageHTTPrequestHeaders_ok = was_eventHTTPrequestHeaders_ok && create_messageHTTPrequestHeaders(result, handleData, was_x509_ok);
+            bool was_abandonHTTPrelativePathBegin_ok = was_messageHTTPrequestHeaders_ok && create_abandonHTTPrelativePathBegin(result, device->deviceId);
+
+            if (was_x509_ok)
+            {
+                result->sasObject = NULL; /**/
+                was_sasObject_ok = true;
+            }
+            else
+            {
+                if (!was_create_deviceSasToken_ok)
+                {
+                    was_sasObject_ok = was_abandonHTTPrelativePathBegin_ok && create_deviceSASObject(result, handleData->hostName, device->deviceId, device->deviceKey);
+                }
+            }
+
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_041: [ IoTHubTransportHttp_Register shall call VECTOR_push_back to store the new device information. ]*/
+            bool was_list_add_ok = (was_sasObject_ok || was_create_deviceSasToken_ok || was_x509_ok) && (VECTOR_push_back(handleData->perDeviceList, &result, 1) == 0);
+
+            if (was_list_add_ok)
+            {
+                /*Codes_SRS_TRANSPORTMULTITHTTP_17_043: [ Upon success, IoTHubTransportHttp_Register shall store the transport handle, and the waitingToSend queue in the device handle return a non-NULL value. ]*/
+                /*Codes_SRS_TRANSPORTMULTITHTTP_17_040: [ IoTHubTransportHttp_Register shall put event HTTP relative path, message HTTP relative path, event HTTP request headers, message HTTP request headers, abandonHTTPrelativePathBegin, HTTPAPIEX_SAS_HANDLE, and the device handle into a device structure. ]*/
+                /*Codes_SRS_TRANSPORTMULTITHTTP_17_128: [ IoTHubTransportHttp_Register shall mark this device as unsubscribed. ]*/
+                result->DoWork_PullMessage = false;
+                result->isFirstPoll = true;
+                result->waitingToSend = waitingToSend;
+                DList_InitializeListHead(&(result->eventConfirmations));
+                result->transportHandle = (HTTPTRANSPORT_HANDLE_DATA *)handle;
+            }
+            else
+            {
+                /*Codes_SRS_TRANSPORTMULTITHTTP_17_042: [ If the singlylinkedlist_add fails then IoTHubTransportHttp_Register shall fail and return NULL. ]*/
+                if (was_sasObject_ok) destroy_SASObject(result);
+                if (was_abandonHTTPrelativePathBegin_ok) destroy_abandonHTTPrelativePathBegin(result);
+                if (was_messageHTTPrelativePath_ok) destroy_messageHTTPrelativePath(result);
+                if (was_eventHTTPrequestHeaders_ok) destroy_eventHTTPrequestHeaders(result);
+                if (was_messageHTTPrequestHeaders_ok) destroy_messageHTTPrequestHeaders(result);
+                if (was_eventHTTPrelativePath_ok) destroy_eventHTTPrelativePath(result);
+                if (was_create_deviceId_ok) destroy_deviceId(result);
+                if (was_create_deviceKey_ok) destroy_deviceKey(result);
+                if (was_create_deviceSasToken_ok) destroy_deviceSasToken(result);
+                /*Codes_SRS_TRANSPORTMULTITHTTP_17_039: [ If the allocating the device handle fails then IoTHubTransportHttp_Register shall fail and return NULL. ] */
+                if (was_resultCreated_ok) free(result);
+                result = NULL;
+            }
+        }
+
+    }
+    return (IOTHUB_DEVICE_HANDLE)result;
+}
+
+
+static void destroy_perDeviceData(HTTPTRANSPORT_PERDEVICE_DATA * perDeviceItem)
+{
+    destroy_deviceId(perDeviceItem);
+    destroy_deviceKey(perDeviceItem);
+    destroy_deviceSas(perDeviceItem);
+    destroy_eventHTTPrelativePath(perDeviceItem);
+    destroy_messageHTTPrelativePath(perDeviceItem);
+    destroy_eventHTTPrequestHeaders(perDeviceItem);
+    destroy_messageHTTPrequestHeaders(perDeviceItem);
+    destroy_abandonHTTPrelativePathBegin(perDeviceItem);
+    destroy_SASObject(perDeviceItem);
+}
+
+static IOTHUB_DEVICE_HANDLE* get_perDeviceDataItem(IOTHUB_DEVICE_HANDLE deviceHandle)
+{
+    HTTPTRANSPORT_PERDEVICE_DATA* deviceHandleData = (HTTPTRANSPORT_PERDEVICE_DATA*)deviceHandle;
+    IOTHUB_DEVICE_HANDLE* listItem;
+
+    HTTPTRANSPORT_HANDLE_DATA* handleData = deviceHandleData->transportHandle;
+
+    listItem = (IOTHUB_DEVICE_HANDLE *)VECTOR_find_if(handleData->perDeviceList, findDeviceHandle, deviceHandle);
+    if (listItem == NULL)
+    {
+        LogError("device handle not found in transport device list");
+        listItem = NULL;
+    }
+    else
+    {
+        /* sucessfully found device in list. */
+    }
+
+    return listItem;
+}
+
+static void IoTHubTransportHttp_Unregister(IOTHUB_DEVICE_HANDLE deviceHandle)
+{
+    if (deviceHandle == NULL)
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_044: [ If deviceHandle is NULL, then IoTHubTransportHttp_Unregister shall do nothing. ]*/
+        LogError("Unregister a NULL device handle");
+    }
+    else
+    {
+        HTTPTRANSPORT_PERDEVICE_DATA* deviceHandleData = (HTTPTRANSPORT_PERDEVICE_DATA*)deviceHandle;
+        HTTPTRANSPORT_HANDLE_DATA* handleData = deviceHandleData->transportHandle;
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_045: [ IoTHubTransportHttp_Unregister shall locate deviceHandle in the transport device list by calling list_find_if. ]*/
+        IOTHUB_DEVICE_HANDLE* listItem = get_perDeviceDataItem(deviceHandle);
+        if (listItem == NULL)
+        {
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_046: [ If the device structure is not found, then this function shall fail and do nothing. ]*/
+            LogError("Device Handle [%p] not found in transport", deviceHandle);
+        }
+        else
+        {
+            HTTPTRANSPORT_PERDEVICE_DATA * perDeviceItem = (HTTPTRANSPORT_PERDEVICE_DATA *)(*listItem);
+
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_047: [ IoTHubTransportHttp_Unregister shall free all the resources used in the device structure. ]*/
+            destroy_perDeviceData(perDeviceItem);
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_048: [ IoTHubTransportHttp_Unregister shall call singlylinkedlist_remove to remove device from devices list. ]*/
+            VECTOR_erase(handleData->perDeviceList, listItem, 1);
+            free(deviceHandleData);
+        }
+    }
+
+    return;
+}
+
+/*Codes_SRS_TRANSPORTMULTITHTTP_17_005: [If config->upperConfig->protocolGatewayHostName is NULL, `IoTHubTransportHttp_Create` shall create an immutable string (further called hostname) containing `config->transportConfig->iotHubName + config->transportConfig->iotHubSuffix`.]  */
+/*Codes_SRS_TRANSPORTMULTITHTTP_20_001: [If config->upperConfig->protocolGatewayHostName is not NULL, IoTHubTransportHttp_Create shall use it as hostname] */
+static void destroy_hostName(HTTPTRANSPORT_HANDLE_DATA* handleData)
+{
+    STRING_delete(handleData->hostName);
+    handleData->hostName = NULL;
+}
+
+static bool create_hostName(HTTPTRANSPORT_HANDLE_DATA* handleData, const IOTHUBTRANSPORT_CONFIG* config)
+{
+    bool result;
+    if (config->upperConfig->protocolGatewayHostName != NULL)
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_20_001: [If config->upperConfig->protocolGatewayHostName is not NULL, IoTHubTransportHttp_Create shall use it as hostname] */
+        handleData->hostName = STRING_construct(config->upperConfig->protocolGatewayHostName);
+        result = (handleData->hostName != NULL);
+    }
+    else
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_005: [If config->upperConfig->protocolGatewayHostName is NULL, `IoTHubTransportHttp_Create` shall create an immutable string (further called hostname) containing `config->transportConfig->iotHubName + config->transportConfig->iotHubSuffix`.]  */
+        handleData->hostName = STRING_construct(config->upperConfig->iotHubName);
+
+        if (handleData->hostName == NULL)
+        {
+            result = false;
+        }
+        else
+        {
+            if ((STRING_concat(handleData->hostName, ".") != 0) ||
+                (STRING_concat(handleData->hostName, config->upperConfig->iotHubSuffix) != 0))
+            {
+                /*Codes_SRS_TRANSPORTMULTITHTTP_17_006: [ If creating the hostname fails then IoTHubTransportHttp_Create shall fail and return NULL. ] */
+                destroy_hostName(handleData);
+                result = false;
+            }
+            else
+            {
+                result = true;
+            }
+        }
+    }
+    return result;
+}
+
+/*Codes_SRS_TRANSPORTMULTITHTTP_17_007: [Otherwise, IoTHubTransportHttp_Create shall create a HTTPAPIEX_HANDLE by a call to HTTPAPIEX_Create passing for hostName the hostname so far constructed by IoTHubTransportHttp_Create.]*/
+static void destroy_httpApiExHandle(HTTPTRANSPORT_HANDLE_DATA* handleData)
+{
+    HTTPAPIEX_Destroy(handleData->httpApiExHandle);
+    handleData->httpApiExHandle = NULL;
+}
+
+/*Codes_SRS_TRANSPORTMULTITHTTP_17_007: [ IoTHubTransportHttp_Create shall create a HTTPAPIEX_HANDLE by a call to HTTPAPIEX_Create passing for hostName the hostname so far constructed by IoTHubTransportHttp_Create. ]*/
+static bool create_httpApiExHandle(HTTPTRANSPORT_HANDLE_DATA* handleData, const IOTHUBTRANSPORT_CONFIG* config)
+{
+    bool result;
+    (void)config;
+    handleData->httpApiExHandle = HTTPAPIEX_Create(STRING_c_str(handleData->hostName));
+    if (handleData->httpApiExHandle == NULL)
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_008: [ If creating the HTTPAPIEX_HANDLE fails then IoTHubTransportHttp_Create shall fail and return NULL. ] */
+        result = false;
+    }
+    else
+    {
+        result = true;
+    }
+    return result;
+}
+
+static void destroy_perDeviceList(HTTPTRANSPORT_HANDLE_DATA* handleData)
+{
+    VECTOR_destroy(handleData->perDeviceList);
+    handleData->perDeviceList = NULL;
+}
+
+/*Codes_SRS_TRANSPORTMULTITHTTP_17_009: [ IoTHubTransportHttp_Create shall call singlylinkedlist_create to create a list of registered devices. ]*/
+static bool create_perDeviceList(HTTPTRANSPORT_HANDLE_DATA* handleData)
+{
+    bool result;
+    handleData->perDeviceList = VECTOR_create(sizeof(IOTHUB_DEVICE_HANDLE));
+    if (handleData == NULL || handleData->perDeviceList == NULL)
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_010: [ If creating the list fails, then IoTHubTransportHttp_Create shall fail and return NULL. ]*/
+        result = false;
+    }
+    else
+    {
+        result = true;
+    }
+    return result;
+}
+
+static TRANSPORT_LL_HANDLE IoTHubTransportHttp_Create(const IOTHUBTRANSPORT_CONFIG* config, TRANSPORT_CALLBACKS_INFO* cb_info, void* ctx)
+{
+    HTTPTRANSPORT_HANDLE_DATA* result;
+    if (config == NULL)
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_001: [If parameter config is NULL, then IoTHubTransportHttp_Create shall return NULL.]*/
+        LogError("invalid arg (configuration is missing)");
+        result = NULL;
+    }
+    else if (config->upperConfig == NULL)
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_002: [ If field transportConfig is NULL, then IoTHubTransportHttp_Create shall return NULL. ]*/
+        LogError("invalid arg (upperConfig is NULL)");
+        result = NULL;
+    }
+    else if (config->upperConfig->protocol == NULL)
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_003: [ If fields protocol, iotHubName or iotHubSuffix in transportConfig are NULL, then IoTHubTransportHttp_Create shall return NULL. ]*/
+        LogError("invalid arg (protocol is NULL)");
+        result = NULL;
+    }
+    else if (config->upperConfig->iotHubName == NULL)
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_003: [ If fields protocol, iotHubName or iotHubSuffix in transportConfig are NULL, then IoTHubTransportHttp_Create shall return NULL. ]*/
+        LogError("invalid arg (iotHubName is NULL)");
+        result = NULL;
+    }
+    else if (config->upperConfig->iotHubSuffix == NULL)
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_003: [ If fields protocol, iotHubName or iotHubSuffix in transportConfig are NULL, then IoTHubTransportHttp_Create shall return NULL. ]*/
+        LogError("invalid arg (iotHubSuffix is NULL)");
+        result = NULL;
+    }
+    else if (IoTHub_Transport_ValidateCallbacks(cb_info) != 0)
+    {
+        LogError("Invalid transport callback information");
+        result = NULL;
+    }
+    else
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_130: [ IoTHubTransportHttp_Create shall allocate memory for the handle. ]*/
+        result = (HTTPTRANSPORT_HANDLE_DATA*)malloc(sizeof(HTTPTRANSPORT_HANDLE_DATA));
+        if (result == NULL)
+        {
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_131: [ If allocation fails, IoTHubTransportHttp_Create shall fail and return NULL. ]*/
+            LogError("unable to malloc");
+        }
+        else if (HTTPAPIEX_Init() == HTTPAPIEX_ERROR)
+        {
+            /*Codes_SRS_TRANSPORTMULTITHTTP_21_143: [ If HTTPAPIEX_Init fails, IoTHubTransportHttp_Create shall fail and return NULL. ]*/
+            LogError("Error initializing HTTP");
+            free(result);
+            result = NULL;
+        }
+        else
+        {
+            bool was_hostName_ok = create_hostName(result, config);
+            bool was_httpApiExHandle_ok = was_hostName_ok && create_httpApiExHandle(result, config);
+            bool was_perDeviceList_ok = was_httpApiExHandle_ok && create_perDeviceList(result);
+
+            if (was_perDeviceList_ok)
+            {
+                /*Codes_SRS_TRANSPORTMULTITHTTP_17_011: [ Otherwise, IoTHubTransportHttp_Create shall succeed and return a non-NULL value. ]*/
+                result->doBatchedTransfers = false;
+                result->getMinimumPollingTime = DEFAULT_GETMINIMUMPOLLINGTIME;
+
+                result->transport_ctx = ctx;
+                memcpy(&result->transport_callbacks, cb_info, sizeof(TRANSPORT_CALLBACKS_INFO));
+            }
+            else
+            {
+                if (was_httpApiExHandle_ok) destroy_httpApiExHandle(result);
+                if (was_hostName_ok) destroy_hostName(result);
+                HTTPAPIEX_Deinit();
+
+                free(result);
+                result = NULL;
+            }
+        }
+    }
+    return result;
+}
+
+static void IoTHubTransportHttp_Destroy(TRANSPORT_LL_HANDLE handle)
+{
+    /*Codes_SRS_TRANSPORTMULTITHTTP_17_012: [ IoTHubTransportHttp_Destroy shall do nothing is handle is NULL. ]*/
+    if (handle != NULL)
+    {
+        HTTPTRANSPORT_HANDLE_DATA* handleData = (HTTPTRANSPORT_HANDLE_DATA*)handle;
+        IOTHUB_DEVICE_HANDLE* listItem;
+
+        size_t deviceListSize = VECTOR_size(handleData->perDeviceList);
+
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_013: [ Otherwise, IoTHubTransportHttp_Destroy shall free all the resources currently in use. ]*/
+        for (size_t i = 0; i < deviceListSize; i++)
+        {
+            listItem = (IOTHUB_DEVICE_HANDLE *)VECTOR_element(handleData->perDeviceList, i);
+            HTTPTRANSPORT_PERDEVICE_DATA* perDeviceItem = (HTTPTRANSPORT_PERDEVICE_DATA*)(*listItem);
+            destroy_perDeviceData(perDeviceItem);
+            free(perDeviceItem);
+        }
+
+        destroy_hostName((HTTPTRANSPORT_HANDLE_DATA *)handle);
+        destroy_httpApiExHandle((HTTPTRANSPORT_HANDLE_DATA *)handle);
+        destroy_perDeviceList((HTTPTRANSPORT_HANDLE_DATA *)handle);
+        HTTPAPIEX_Deinit();
+        free(handle);
+    }
+}
+
+static int IoTHubTransportHttp_Subscribe(IOTHUB_DEVICE_HANDLE handle)
+{
+    int result;
+    if (handle == NULL)
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_103: [ If parameter deviceHandle is NULL then IoTHubTransportHttp_Subscribe shall fail and return a non-zero value. ]*/
+        LogError("invalid arg passed to IoTHubTransportHttp_Subscribe");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_104: [ IoTHubTransportHttp_Subscribe shall locate deviceHandle in the transport device list by calling list_find_if. ]*/
+        IOTHUB_DEVICE_HANDLE* listItem = get_perDeviceDataItem(handle);
+
+        if (listItem == NULL)
+        {
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_105: [ If the device structure is not found, then this function shall fail and return a non-zero value. ]*/
+            LogError("did not find device in transport handle");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            HTTPTRANSPORT_PERDEVICE_DATA * perDeviceItem;
+
+            perDeviceItem = (HTTPTRANSPORT_PERDEVICE_DATA *)(*listItem);
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_106: [ Otherwise, IoTHubTransportHttp_Subscribe shall set the device so that subsequent calls to DoWork should execute HTTP requests. ]*/
+            perDeviceItem->DoWork_PullMessage = true;
+        }
+        result = 0;
+    }
+    return result;
+}
+
+static void IoTHubTransportHttp_Unsubscribe(IOTHUB_DEVICE_HANDLE handle)
+{
+    /*Codes_SRS_TRANSPORTMULTITHTTP_17_107: [ If parameter deviceHandle is NULL then IoTHubTransportHttp_Unsubscribe shall fail do nothing. ]*/
+    if (handle != NULL)
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_108: [ IoTHubTransportHttp_Unsubscribe shall locate deviceHandle in the transport device list by calling list_find_if. ]*/
+        IOTHUB_DEVICE_HANDLE* listItem = get_perDeviceDataItem(handle);
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_109: [ If the device structure is not found, then this function shall fail and do nothing. ]*/
+        if (listItem != NULL)
+        {
+            HTTPTRANSPORT_PERDEVICE_DATA * perDeviceItem = (HTTPTRANSPORT_PERDEVICE_DATA *)(*listItem);
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_110: [ Otherwise, IoTHubTransportHttp_Subscribe shall set the device so that subsequent calls to DoWork shall not execute HTTP requests. ]*/
+            perDeviceItem->DoWork_PullMessage = false;
+        }
+        else
+        {
+            LogError("Device not found to unsuscribe.");
+        }
+    }
+    else
+    {
+        LogError("Null handle passed to Unsuscribe.");
+    }
+}
+
+static int IoTHubTransportHttp_Subscribe_DeviceTwin(IOTHUB_DEVICE_HANDLE handle)
+{
+    /*Codes_SRS_TRANSPORTMULTITHTTP_02_003: [ IoTHubTransportHttp_Subscribe_DeviceTwin shall return a non-zero value. ]*/
+    (void)handle;
+    int result = MU_FAILURE;
+    LogError("IoTHubTransportHttp_Subscribe_DeviceTwin Not supported");
+    return result;
+}
+
+static void IoTHubTransportHttp_Unsubscribe_DeviceTwin(IOTHUB_DEVICE_HANDLE handle)
+{
+    (void)handle;
+    /*Codes_SRS_TRANSPORTMULTITHTTP_02_004: [ IoTHubTransportHttp_Unsubscribe_DeviceTwin shall return ]*/
+    LogError("IoTHubTransportHttp_Unsubscribe_DeviceTwin Not supported");
+}
+
+static IOTHUB_CLIENT_RESULT IoTHubTransportHttp_GetTwinAsync(IOTHUB_DEVICE_HANDLE handle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK completionCallback, void* callbackContext)
+{
+    (void)handle;
+    (void)completionCallback;
+    (void)callbackContext;
+    LogError("Currently Not Supported.");
+    // Codes_SRS_TRANSPORTMULTITHTTP_09_005: [ `IoTHubTransportHttp_GetTwinAsync` shall return IOTHUB_CLIENT_ERROR]
+    return IOTHUB_CLIENT_ERROR;
+}
+
+static int IoTHubTransportHttp_Subscribe_DeviceMethod(IOTHUB_DEVICE_HANDLE handle)
+{
+    (void)handle;
+    int result = MU_FAILURE;
+    LogError("not implemented (yet)");
+    return result;
+}
+
+static void IoTHubTransportHttp_Unsubscribe_DeviceMethod(IOTHUB_DEVICE_HANDLE handle)
+{
+    (void)handle;
+    LogError("not implemented (yet)");
+}
+
+static int IoTHubTransportHttp_DeviceMethod_Response(IOTHUB_DEVICE_HANDLE handle, METHOD_HANDLE methodId, const unsigned char* response, size_t response_size, int status_response)
+{
+    (void)handle;
+    (void)methodId;
+    (void)response;
+    (void)response_size;
+    (void)status_response;
+    LogError("not implemented (yet)");
+    return MU_FAILURE;
+}
+
+/*produces a representation of the properties, if they exist*/
+/*if they do not exist, produces ""*/
+static int concat_Properties(STRING_HANDLE existing, MAP_HANDLE map, size_t* propertiesMessageSizeContribution)
+{
+    int result;
+    const char*const* keys;
+    const char*const* values;
+    size_t count;
+    if (Map_GetInternals(map, &keys, &values, &count) != MAP_OK)
+    {
+        result = MU_FAILURE;
+        LogError("error while Map_GetInternals");
+    }
+    else
+    {
+
+        if (count == 0)
+        {
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_064: [If IoTHubMessage does not have properties, then "properties":{...} shall be missing from the payload*/
+            /*no properties - do nothing with existing*/
+            result = 0;
+            *propertiesMessageSizeContribution = 0;
+        }
+        else
+        {
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_058: [If IoTHubMessage has properties, then they shall be serialized at the same level as "body" using the following pattern: "properties":{"iothub-app-name1":"value1","iothub-app-name2":"value2*/
+            if (STRING_concat(existing, ",\"properties\":") != 0)
+            {
+                /*go ahead and return it*/
+                result = MU_FAILURE;
+                LogError("failed STRING_concat");
+            }
+            else if (appendMapToJSON(existing, keys, values, count) != 0)
+            {
+                result = MU_FAILURE;
+                LogError("unable to append the properties");
+            }
+            else
+            {
+                /*all is fine*/
+                size_t i;
+                *propertiesMessageSizeContribution = 0;
+                for (i = 0; i < count; i++)
+                {
+                    /*Codes_SRS_TRANSPORTMULTITHTTP_17_063: [Every property name shall add to the message size the length of the property name + the length of the property value + 16 bytes.] */
+                    *propertiesMessageSizeContribution += (strlen(keys[i]) + strlen(values[i]) + MAXIMUM_PROPERTY_OVERHEAD);
+                }
+                result = 0;
+            }
+        }
+    }
+    return result;
+}
+
+/*produces a JSON representation of the map : {"a": "value_of_a","b":"value_of_b"}*/
+static int appendMapToJSON(STRING_HANDLE existing, const char* const* keys, const char* const* values, size_t count) /*under consideration: move to MAP module when it has more than 1 user*/
+{
+    int result;
+    if (STRING_concat(existing, "{") != 0)
+    {
+        /*go on and return it*/
+        LogError("STRING_construct failed");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        size_t i;
+        for (i = 0; i < count; i++)
+        {
+            if (!(
+                (STRING_concat(existing, (i == 0) ? "\"" IOTHUB_APP_PREFIX : ",\"" IOTHUB_APP_PREFIX) == 0) &&
+                (STRING_concat(existing, keys[i]) == 0) &&
+                (STRING_concat(existing, "\":\"") == 0) &&
+                (STRING_concat(existing, values[i]) == 0) &&
+                (STRING_concat(existing, "\"") == 0)
+                ))
+            {
+                LogError("unable to STRING_concat");
+                break;
+            }
+        }
+
+        if (i < count)
+        {
+            result = MU_FAILURE;
+            /*error, let it go through*/
+        }
+        else if (STRING_concat(existing, "}") != 0)
+        {
+            LogError("unable to STRING_concat");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            /*all is fine*/
+            result = 0;
+        }
+    }
+    return result;
+}
+
+/*makes the following string:{"body":"base64 encoding of the message content"[,"properties":{"a":"valueOfA"}]}*/
+/*return NULL if there was a failure, or a non-NULL STRING_HANDLE that contains the intended data*/
+static STRING_HANDLE make1EventJSONitem(PDLIST_ENTRY item, size_t *messageSizeContribution)
+{
+    STRING_HANDLE result; /*temp wants to contain :{"body":"base64 encoding of the message content"[,"properties":{"a":"valueOfA"}]}*/
+    IOTHUB_MESSAGE_LIST* message = containingRecord(item, IOTHUB_MESSAGE_LIST, entry);
+    IOTHUBMESSAGE_CONTENT_TYPE contentType = IoTHubMessage_GetContentType(message->messageHandle);
+
+    switch (contentType)
+    {
+    case IOTHUBMESSAGE_BYTEARRAY:
+    {
+        result = STRING_construct("{\"body\":\"");
+        if (result == NULL)
+        {
+            LogError("unable to STRING_construct");
+        }
+        else
+        {
+            const unsigned char* source;
+            size_t size;
+
+            if (IoTHubMessage_GetByteArray(message->messageHandle, &source, &size) != IOTHUB_MESSAGE_OK)
+            {
+                LogError("unable to get the data for the message.");
+                STRING_delete(result);
+                result = NULL;
+            }
+            else
+            {
+                STRING_HANDLE encoded = Azure_Base64_Encode_Bytes(source, size);
+                if (encoded == NULL)
+                {
+                    LogError("unable to Azure_Base64_Encode_Bytes.");
+                    STRING_delete(result);
+                    result = NULL;
+                }
+                else
+                {
+                    size_t propertiesSize = 0;
+                    if (!(
+                        (STRING_concat_with_STRING(result, encoded) == 0) &&
+                        (STRING_concat(result, "\"") == 0) && /*\" because closing value*/
+                        (concat_Properties(result, IoTHubMessage_Properties(message->messageHandle), &propertiesSize) == 0) &&
+                        (STRING_concat(result, "},") == 0) /*the last comma shall be replaced by a ']' by DaCr's suggestion (which is awesome enough to receive credits in the source code)*/
+                        ))
+                    {
+                        STRING_delete(result);
+                        result = NULL;
+                        LogError("unable to STRING_concat_with_STRING.");
+                    }
+                    else
+                    {
+                        /*all is fine... */
+                        /*Codes_SRS_TRANSPORTMULTITHTTP_17_062: [The message size is computed from the length of the payload + 384.] */
+                        *messageSizeContribution = size + MAXIMUM_PAYLOAD_OVERHEAD + propertiesSize;
+                    }
+                    STRING_delete(encoded);
+                }
+            }
+        }
+        break;
+    }
+    /*Codes_SRS_TRANSPORTMULTITHTTP_17_057: [If a messages to be send has type IOTHUBMESSAGE_STRING, then its serialization shall be {"body":"JSON encoding of the string", "base64Encoded":false}] */
+    case IOTHUBMESSAGE_STRING:
+    {
+        result = STRING_construct("{\"body\":");
+        if (result == NULL)
+        {
+            LogError("unable to STRING_construct");
+        }
+        else
+        {
+            const char* source = IoTHubMessage_GetString(message->messageHandle);
+            if (source == NULL)
+            {
+                LogError("unable to IoTHubMessage_GetString");
+                STRING_delete(result);
+                result = NULL;
+            }
+            else
+            {
+                STRING_HANDLE asJson = STRING_new_JSON(source);
+                if (asJson == NULL)
+                {
+                    LogError("unable to STRING_new_JSON");
+                    STRING_delete(result);
+                    result = NULL;
+                }
+                else
+                {
+                    size_t propertiesSize = 0;
+                    if (!(
+                        (STRING_concat_with_STRING(result, asJson) == 0) &&
+                        (STRING_concat(result, ",\"base64Encoded\":false") == 0) &&
+                        (concat_Properties(result, IoTHubMessage_Properties(message->messageHandle), &propertiesSize) == 0) &&
+                        (STRING_concat(result, "},") == 0) /*the last comma shall be replaced by a ']' by DaCr's suggestion (which is awesome enough to receive credits in the source code)*/
+                        ))
+                    {
+                        LogError("unable to STRING_concat_with_STRING");
+                        STRING_delete(result);
+                        result = NULL;
+                    }
+                    else
+                    {
+                        /*result has the intended content*/
+                        /*Codes_SRS_TRANSPORTMULTITHTTP_17_062: [The message size is computed from the length of the payload + 384.] */
+                        *messageSizeContribution = strlen(source) + MAXIMUM_PAYLOAD_OVERHEAD + propertiesSize;
+                    }
+                    STRING_delete(asJson);
+                }
+            }
+        }
+        break;
+    }
+    default:
+    {
+        LogError("an unknown message type was encountered (%d)", contentType);
+        result = NULL; /*unknown message type*/
+        break;
+    }
+    }
+    return result;
+}
+
+#define MAKE_PAYLOAD_RESULT_VALUES \
+    MAKE_PAYLOAD_OK, /*returned when there is a payload to be later send by HTTP*/ \
+    MAKE_PAYLOAD_NO_ITEMS, /*returned when there are no items to be send*/ \
+    MAKE_PAYLOAD_ERROR, /*returned when there were errors*/ \
+    MAKE_PAYLOAD_FIRST_ITEM_DOES_NOT_FIT /*returned when the first item doesn't fit*/
+
+MU_DEFINE_ENUM(MAKE_PAYLOAD_RESULT, MAKE_PAYLOAD_RESULT_VALUES);
+
+/*this function assembles several {"body":"base64 encoding of the message content"," base64Encoded": true} into 1 payload*/
+/*Codes_SRS_TRANSPORTMULTITHTTP_17_056: [IoTHubTransportHttp_DoWork shall build the following string:[{"body":"base64 encoding of the message1 content"},{"body":"base64 encoding of the message2 content"}...]]*/
+static MAKE_PAYLOAD_RESULT makePayload(HTTPTRANSPORT_PERDEVICE_DATA* deviceData, STRING_HANDLE* payload)
+{
+    MAKE_PAYLOAD_RESULT result;
+    size_t allMessagesSize = 0;
+    *payload = STRING_construct("[");
+    if (*payload == NULL)
+    {
+        LogError("unable to STRING_construct");
+        result = MAKE_PAYLOAD_ERROR;
+    }
+    else
+    {
+        bool isFirst = true;
+        PDLIST_ENTRY actual;
+        bool keepGoing = true; /*keepGoing gets sometimes to false from within the loop*/
+                               /*either all the items enter the list or only some*/
+        result = MAKE_PAYLOAD_OK; /*optimistically initializing it*/
+        while (keepGoing && ((actual = deviceData->waitingToSend->Flink) != deviceData->waitingToSend))
+        {
+            size_t messageSize;
+            STRING_HANDLE temp = make1EventJSONitem(actual, &messageSize);
+            if (isFirst)
+            {
+                isFirst = false;
+                /*Codes_SRS_TRANSPORTMULTITHTTP_17_067: [If there is no valid payload, IoTHubTransportHttp_DoWork shall advance to the next activity.]*/
+                if (temp == NULL) /*first item failed to create, nothing to send*/
+                {
+                    result = MAKE_PAYLOAD_ERROR;
+                    STRING_delete(*payload);
+                    *payload = NULL;
+                    keepGoing = false;
+                }
+                else
+                {
+                    /*Codes_SRS_TRANSPORTMULTITHTTP_17_065: [If the oldest message in waitingToSend causes the message size to exceed the message size limit then it shall be removed from waitingToSend, and IoTHubClientCore_LL_SendComplete shall be called. Parameter PDLIST_ENTRY completed shall point to a list containing only the oldest item, and parameter IOTHUB_CLIENT_CONFIRMATION_RESULT result shall be set to IOTHUB_CLIENT_CONFIRMATION_BATCHSTATE_FAILED.]*/
+                    /*Codes_SRS_TRANSPORTMULTITHTTP_17_061: [The message size shall be limited to 255KB - 1 byte.]*/
+                    if (messageSize > MAXIMUM_MESSAGE_SIZE)
+                    {
+                        PDLIST_ENTRY head = DList_RemoveHeadList(deviceData->waitingToSend); /*actually this is the same as "actual", but now it is removed*/
+                        DList_InsertTailList(&(deviceData->eventConfirmations), head);
+                        result = MAKE_PAYLOAD_FIRST_ITEM_DOES_NOT_FIT;
+                        STRING_delete(*payload);
+                        *payload = NULL;
+                        keepGoing = false;
+                    }
+                    else
+                    {
+                        if (STRING_concat_with_STRING(*payload, temp) != 0)
+                        {
+                            /*Codes_SRS_TRANSPORTMULTITHTTP_17_067: [If there is no valid payload, IoTHubTransportHttp_DoWork shall advance to the next activity.]*/
+                            result = MAKE_PAYLOAD_ERROR;
+                            STRING_delete(*payload);
+                            *payload = NULL;
+                            keepGoing = false;
+                        }
+                        else
+                        {
+                            /*first item was put nicely in the payload*/
+                            PDLIST_ENTRY head = DList_RemoveHeadList(deviceData->waitingToSend); /*actually this is the same as "actual", but now it is removed*/
+                            DList_InsertTailList(&(deviceData->eventConfirmations), head);
+                            allMessagesSize += messageSize;
+                        }
+                    }
+                    STRING_delete(temp);
+                }
+            }
+            else
+            {
+                /*there is at least 1 item already in the payload*/
+                if (temp == NULL)
+                {
+                    /*there are multiple payloads encoded, the last one had an internal error, just go with those - closing the payload happens "after the loop"*/
+                    /*Codes_SRS_TRANSPORTMULTITHTTP_17_066: [If at any point during construction of the string there are errors, IoTHubTransportHttp_DoWork shall use the so far constructed string as payload.]*/
+                    result = MAKE_PAYLOAD_OK;
+                    keepGoing = false;
+                }
+                else
+                {
+                    if (allMessagesSize + messageSize > MAXIMUM_MESSAGE_SIZE)
+                    {
+                        /*this item doesn't make it to the payload, but the payload is valid so far*/
+                        /*Codes_SRS_TRANSPORTMULTITHTTP_17_066: [If at any point during construction of the string there are errors, IoTHubTransportHttp_DoWork shall use the so far constructed string as payload.]*/
+                        result = MAKE_PAYLOAD_OK;
+                        keepGoing = false;
+                    }
+                    else if (STRING_concat_with_STRING(*payload, temp) != 0)
+                    {
+                        /*should still send what there is so far...*/
+                        /*Codes_SRS_TRANSPORTMULTITHTTP_17_066: [If at any point during construction of the string there are errors, IoTHubTransportHttp_DoWork shall use the so far constructed string as payload.]*/
+                        result = MAKE_PAYLOAD_OK;
+                        keepGoing = false;
+                    }
+                    else
+                    {
+                        /*cool, the payload made it there, let's continue... */
+                        PDLIST_ENTRY head = DList_RemoveHeadList(deviceData->waitingToSend); /*actually this is the same as "actual", but now it is removed*/
+                        DList_InsertTailList(&(deviceData->eventConfirmations), head);
+                        allMessagesSize += messageSize;
+                    }
+                    STRING_delete(temp);
+                }
+            }
+        }
+
+        /*closing the payload*/
+        if (result == MAKE_PAYLOAD_OK)
+        {
+            ((char*)STRING_c_str(*payload))[STRING_length(*payload) - 1] = ']'; /*TODO - do this in STRING_HANDLE*/
+        }
+        else
+        {
+            /*no need to close anything*/
+        }
+    }
+    return result;
+}
+
+static void reversePutListBackIn(PDLIST_ENTRY source, PDLIST_ENTRY destination)
+{
+    /*this function takes a list, and inserts it in another list. When done in the context of this file, it reverses the effects of a not-able-to-send situation*/
+    DList_AppendTailList(destination->Flink, source);
+    DList_RemoveEntryList(source);
+    DList_InitializeListHead(source);
+}
+
+static void DoEvent(HTTPTRANSPORT_HANDLE_DATA* handleData, HTTPTRANSPORT_PERDEVICE_DATA* deviceData)
+{
+
+    if (DList_IsListEmpty(deviceData->waitingToSend))
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_060: [If the list is empty then IoTHubTransportHttp_DoWork shall proceed to the following action.] */
+    }
+    else
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_053: [If option SetBatching is true then _Dowork shall send batched event message as specced below.] */
+        if (handleData->doBatchedTransfers)
+        {
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_054: [Request HTTP headers shall have the value of "Content-Type" created or updated to "application/vnd.microsoft.iothub.json" by a call to HTTPHeaders_ReplaceHeaderNameValuePair.] */
+            if (HTTPHeaders_ReplaceHeaderNameValuePair(deviceData->eventHTTPrequestHeaders, CONTENT_TYPE, APPLICATION_VND_MICROSOFT_IOTHUB_JSON) != HTTP_HEADERS_OK)
+            {
+                /*Codes_SRS_TRANSPORTMULTITHTTP_17_055: [If updating Content-Type fails for any reason, then _DoWork shall advance to the next action.] */
+                LogError("unable to HTTPHeaders_ReplaceHeaderNameValuePair");
+            }
+            else
+            {
+                /*Codes_SRS_TRANSPORTMULTITHTTP_17_059: [It shall inspect the "waitingToSend" DLIST passed in config structure.] */
+                STRING_HANDLE payload;
+                switch (makePayload(deviceData, &payload))
+                {
+                case MAKE_PAYLOAD_OK:
+                {
+                    /*Codes_SRS_TRANSPORTMULTITHTTP_17_068: [Once a final payload has been obtained, IoTHubTransportHttp_DoWork shall call HTTPAPIEX_SAS_ExecuteRequest passing the following parameters:] */
+                    BUFFER_HANDLE temp = BUFFER_new();
+                    if (temp == NULL)
+                    {
+                        LogError("unable to BUFFER_new");
+                        /*Codes_SRS_TRANSPORTMULTITHTTP_17_067: [If there is no valid payload, IoTHubTransportHttp_DoWork shall advance to the next activity.]*/
+                        reversePutListBackIn(&(deviceData->eventConfirmations), deviceData->waitingToSend);
+                    }
+                    else
+                    {
+                        if (BUFFER_build(temp, (const unsigned char*)STRING_c_str(payload), STRING_length(payload)) != 0)
+                        {
+                            LogError("unable to BUFFER_build");
+                            //items go back to waitingToSend
+                            /*Codes_SRS_TRANSPORTMULTITHTTP_17_067: [If there is no valid payload, IoTHubTransportHttp_DoWork shall advance to the next activity.]*/
+                            reversePutListBackIn(&(deviceData->eventConfirmations), deviceData->waitingToSend);
+                        }
+                        else
+                        {
+                            unsigned int statusCode;
+                            if (HTTPAPIEX_SAS_ExecuteRequest(
+                                deviceData->sasObject,
+                                handleData->httpApiExHandle,
+                                HTTPAPI_REQUEST_POST,
+                                STRING_c_str(deviceData->eventHTTPrelativePath),
+                                deviceData->eventHTTPrequestHeaders,
+                                temp,
+                                &statusCode,
+                                NULL,
+                                NULL
+                            ) != HTTPAPIEX_OK)
+                            {
+                                LogError("unable to HTTPAPIEX_ExecuteRequest");
+                                //items go back to waitingToSend
+                                /*Codes_SRS_TRANSPORTMULTITHTTP_17_069: [if HTTPAPIEX_SAS_ExecuteRequest fails or the http status code >=300 then IoTHubTransportHttp_DoWork shall not do any other action (it is assumed at the next _DoWork it shall be retried).] */
+                                reversePutListBackIn(&(deviceData->eventConfirmations), deviceData->waitingToSend);
+                            }
+                            else
+                            {
+                                if (statusCode < 300)
+                                {
+                                    /*Codes_SRS_TRANSPORTMULTITHTTP_17_070: [If HTTPAPIEX_SAS_ExecuteRequest does not fail and http status code <300 then IoTHubTransportHttp_DoWork shall call IoTHubClientCore_LL_SendComplete. Parameter PDLIST_ENTRY completed shall point to a list containing all the items batched, and parameter IOTHUB_CLIENT_CONFIRMATION_RESULT result shall be set to IOTHUB_CLIENT_CONFIRMATION_OK. The batched items shall be removed from waitingToSend.] */
+                                    handleData->transport_callbacks.send_complete_cb(&(deviceData->eventConfirmations), IOTHUB_CLIENT_CONFIRMATION_OK, deviceData->device_transport_ctx);
+                                }
+                                else
+                                {
+                                    //items go back to waitingToSend
+                                    /*Codes_SRS_TRANSPORTMULTITHTTP_17_069: [if HTTPAPIEX_SAS_ExecuteRequest fails or the http status code >=300 then IoTHubTransportHttp_DoWork shall not do any other action (it is assumed at the next _DoWork it shall be retried).] */
+                                    LogError("unexpected HTTP status code (%u)", statusCode);
+                                    reversePutListBackIn(&(deviceData->eventConfirmations), deviceData->waitingToSend);
+                                }
+                            }
+                        }
+                        BUFFER_delete(temp);
+                    }
+                    STRING_delete(payload);
+                    break;
+                }
+                case MAKE_PAYLOAD_FIRST_ITEM_DOES_NOT_FIT:
+                {
+                    handleData->transport_callbacks.send_complete_cb(&(deviceData->eventConfirmations), IOTHUB_CLIENT_CONFIRMATION_ERROR, deviceData->device_transport_ctx); // takes care of emptying the list too
+                    break;
+                }
+                case MAKE_PAYLOAD_ERROR:
+                {
+                    LogError("unrecoverable errors while building a batch message");
+                    break;
+                }
+                case MAKE_PAYLOAD_NO_ITEMS:
+                {
+                    /*do nothing*/
+                    break;
+                }
+                default:
+                {
+                    LogError("internal error: switch's default branch reached when never intended");
+                    break;
+                }
+                }
+            }
+        }
+        else
+        {
+            const unsigned char* messageContent = NULL;
+            size_t messageSize = 0;
+            size_t originalMessageSize = 0;
+            IOTHUB_MESSAGE_LIST* message = containingRecord(deviceData->waitingToSend->Flink, IOTHUB_MESSAGE_LIST, entry);
+            IOTHUBMESSAGE_CONTENT_TYPE contentType = IoTHubMessage_GetContentType(message->messageHandle);
+
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_073: [The message size is computed from the length of the payload + 384.]*/
+            if (!(
+                (((contentType == IOTHUBMESSAGE_BYTEARRAY) &&
+                (IoTHubMessage_GetByteArray(message->messageHandle, &messageContent, &originalMessageSize) == IOTHUB_MESSAGE_OK))
+                    ? ((void)(messageSize = originalMessageSize + MAXIMUM_PAYLOAD_OVERHEAD), 1)
+                    : 0)
+
+                ||
+
+                ((contentType == IOTHUBMESSAGE_STRING) &&
+                ((void)(messageContent = (const unsigned char*)IoTHubMessage_GetString(message->messageHandle)),
+                    ((void)(messageSize = MAXIMUM_PAYLOAD_OVERHEAD + (originalMessageSize = ((messageContent == NULL)
+                        ? 0
+                        : strlen((const char*)messageContent))))),
+                    messageContent != NULL)
+                    )
+                ))
+            {
+                LogError("unable to get the message content");
+                /*go on...*/
+            }
+            else
+            {
+                /*Codes_SRS_TRANSPORTMULTITHTTP_17_075: [If the oldest message in waitingToSend causes the message to exceed the message size limit then it shall be removed from waitingToSend, and IoTHubClientCore_LL_SendComplete shall be called. Parameter PDLIST_ENTRY completed shall point to a list containing only the oldest item, and parameter IOTHUB_CLIENT_CONFIRMATION_RESULT result shall be set to IOTHUB_CLIENT_CONFIRMATION_BATCHSTATE_FAILED.]*/
+                /*Codes_SRS_TRANSPORTMULTITHTTP_17_072: [The message size shall be limited to 255KB -1 bytes.] */
+                if (messageSize > MAXIMUM_MESSAGE_SIZE)
+                {
+                    PDLIST_ENTRY head = DList_RemoveHeadList(deviceData->waitingToSend); /*actually this is the same as "actual", but now it is removed*/
+                    DList_InsertTailList(&(deviceData->eventConfirmations), head);
+                    handleData->transport_callbacks.send_complete_cb(&(deviceData->eventConfirmations), IOTHUB_CLIENT_CONFIRMATION_ERROR, deviceData->device_transport_ctx); // takes care of emptying the list too
+                }
+                else
+                {
+                    /*Codes_SRS_TRANSPORTMULTITHTTP_17_071: [If option SetBatching is false then _Dowork shall send individual event message as specced below.] */
+                    /*Codes_SRS_TRANSPORTMULTITHTTP_17_076: [A clone of the event HTTP request headers shall be created.]*/
+                    HTTP_HEADERS_HANDLE clonedEventHTTPrequestHeaders = HTTPHeaders_Clone(deviceData->eventHTTPrequestHeaders);
+                    if (clonedEventHTTPrequestHeaders == NULL)
+                    {
+                        /*Codes_SRS_TRANSPORTMULTITHTTP_17_079: [If any HTTP header operation fails, _DoWork shall advance to the next action.] */
+                        LogError("HTTPHeaders_Clone failed");
+                    }
+                    else
+                    {
+                        /*Codes_SRS_TRANSPORTMULTITHTTP_17_077: [The cloned HTTP headers shall have the HTTP header "Content-Type" set to "application/octet-stream".] */
+                        if (HTTPHeaders_ReplaceHeaderNameValuePair(clonedEventHTTPrequestHeaders, CONTENT_TYPE, APPLICATION_OCTET_STREAM) != HTTP_HEADERS_OK)
+                        {
+                            /*Codes_SRS_TRANSPORTMULTITHTTP_17_079: [If any HTTP header operation fails, _DoWork shall advance to the next action.] */
+                            LogError("HTTPHeaders_ReplaceHeaderNameValuePair failed");
+                        }
+                        else
+                        {
+                            // set_message_properties returning false does not necessarily mean the the function failed, it just means
+                            // the the adding of messages should not continue and should try the next time.  So you should not log if this
+                            // returns false
+                            if (set_message_properties(message, &messageSize, clonedEventHTTPrequestHeaders, handleData, deviceData))
+                            {
+
+                                if (set_system_properties(message, clonedEventHTTPrequestHeaders) != 0)
+                                {
+                                    /*Codes_SRS_TRANSPORTMULTITHTTP_17_079: [If any HTTP header operation fails, _DoWork shall advance to the next action.] */
+                                }
+                                else
+                                {
+                                    BUFFER_HANDLE toBeSend = BUFFER_create(messageContent, originalMessageSize);
+                                    if (toBeSend == NULL)
+                                    {
+                                        LogError("unable to BUFFER_new");
+                                    }
+                                    else
+                                    {
+                                        unsigned int statusCode = 0;
+                                        HTTPAPIEX_RESULT r;
+                                        if (deviceData->deviceSasToken != NULL)
+                                        {
+                                            /*Codes_SRS_TRANSPORTMULTITHTTP_03_001: [if a deviceSasToken exists, HTTPHeaders_ReplaceHeaderNameValuePair shall be invoked with "Authorization" as its second argument and STRING_c_str (deviceSasToken) as its third argument.]*/
+                                            if (HTTPHeaders_ReplaceHeaderNameValuePair(clonedEventHTTPrequestHeaders, IOTHUB_AUTH_HEADER_VALUE, STRING_c_str(deviceData->deviceSasToken)) != HTTP_HEADERS_OK)
+                                            {
+                                                r = HTTPAPIEX_ERROR;
+                                                /*Codes_SRS_TRANSPORTMULTITHTTP_03_002: [If the result of the invocation of HTTPHeaders_ReplaceHeaderNameValuePair is NOT HTTP_HEADERS_OK then fallthrough.]*/
+                                                LogError("Unable to replace the old SAS Token.");
+                                            }
+                                            /*Codes_SRS_TRANSPORTMULTITHTTP_03_003: [If a deviceSasToken exists, IoTHubTransportHttp_DoWork shall call HTTPAPIEX_ExecuteRequest passing the following parameters] */
+                                            else if ((r = HTTPAPIEX_ExecuteRequest(
+                                                handleData->httpApiExHandle, HTTPAPI_REQUEST_POST, STRING_c_str(deviceData->eventHTTPrelativePath),
+                                                clonedEventHTTPrequestHeaders, toBeSend, &statusCode, NULL, NULL)) != HTTPAPIEX_OK)
+                                            {
+                                                LogError("Unable to HTTPAPIEX_ExecuteRequest.");
+                                            }
+                                        }
+                                        else
+                                        {
+                                            /*Codes_SRS_TRANSPORTMULTITHTTP_17_080: [If a deviceSasToken does not exist, IoTHubTransportHttp_DoWork shall call HTTPAPIEX_SAS_ExecuteRequest passing the following parameters] */
+                                            if ((r = HTTPAPIEX_SAS_ExecuteRequest(deviceData->sasObject, handleData->httpApiExHandle, HTTPAPI_REQUEST_POST, STRING_c_str(deviceData->eventHTTPrelativePath),
+                                                clonedEventHTTPrequestHeaders, toBeSend, &statusCode, NULL, NULL )) != HTTPAPIEX_OK)
+                                            {
+                                                LogError("unable to HTTPAPIEX_SAS_ExecuteRequest");
+                                            }
+                                        }
+                                        if (r == HTTPAPIEX_OK)
+                                        {
+                                            if (statusCode < 300)
+                                            {
+                                                /*Codes_SRS_TRANSPORTMULTITHTTP_17_082: [If HTTPAPIEX_SAS_ExecuteRequest does not fail and http status code <300 then IoTHubTransportHttp_DoWork shall call IoTHubClientCore_LL_SendComplete. Parameter PDLIST_ENTRY completed shall point to a list the item send, and parameter IOTHUB_CLIENT_CONFIRMATION_RESULT result shall be set to IOTHUB_CLIENT_CONFIRMATION_OK. The item shall be removed from waitingToSend.] */
+                                                PDLIST_ENTRY justSent = DList_RemoveHeadList(deviceData->waitingToSend); /*actually this is the same as "actual", but now it is removed*/
+                                                DList_InsertTailList(&(deviceData->eventConfirmations), justSent);
+                                                handleData->transport_callbacks.send_complete_cb(&(deviceData->eventConfirmations), IOTHUB_CLIENT_CONFIRMATION_OK, deviceData->device_transport_ctx); // takes care of emptying the list too
+                                            }
+                                            else
+                                            {
+                                                /*Codes_SRS_TRANSPORTMULTITHTTP_17_081: [If HTTPAPIEX_SAS_ExecuteRequest fails or the http status code >=300 then IoTHubTransportHttp_DoWork shall not do any other action (it is assumed at the next _DoWork it shall be retried).] */
+                                                LogError("unexpected HTTP status code (%u)", statusCode);
+                                            }
+                                        }
+                                        else if (r == HTTPAPIEX_RECOVERYFAILED)
+                                        {
+                                            PDLIST_ENTRY justSent = DList_RemoveHeadList(deviceData->waitingToSend); /*actually this is the same as "actual", but now it is removed*/
+                                            DList_InsertTailList(&(deviceData->eventConfirmations), justSent);
+                                            handleData->transport_callbacks.send_complete_cb(&(deviceData->eventConfirmations), IOTHUB_CLIENT_CONFIRMATION_ERROR, deviceData->device_transport_ctx); // takes care of emptying the list too
+                                        }
+                                    }
+                                    BUFFER_delete(toBeSend);
+                                }
+                            }
+                        }
+                        HTTPHeaders_Free(clonedEventHTTPrequestHeaders);
+                    }
+                }
+            }
+        }
+    }
+}
+
+static bool abandonOrAcceptMessage(HTTPTRANSPORT_HANDLE_DATA* handleData, HTTPTRANSPORT_PERDEVICE_DATA* deviceData, const char* ETag, IOTHUBMESSAGE_DISPOSITION_RESULT action)
+{
+    /*Codes_SRS_TRANSPORTMULTITHTTP_17_097: [_DoWork shall call HTTPAPIEX_SAS_ExecuteRequest with the following parameters:
+    -requestType: POST
+    -relativePath: abandon relative path begin (as created by _Create) + value of ETag + "/abandon?api-version=2016-11-14"
+    - requestHttpHeadersHandle: an HTTP headers instance containing the following
+    Authorization: " "
+    If-Match: value of ETag
+    - requestContent: NULL
+    - statusCode: a pointer to unsigned int which might be examined for logging
+    - responseHeadearsHandle: NULL
+    - responseContent: NULL]*/
+    /*Codes_SRS_TRANSPORTMULTITHTTP_17_099: [_DoWork shall call HTTPAPIEX_SAS_ExecuteRequest with the following parameters:
+    -requestType: DELETE
+    -relativePath: abandon relative path begin + value of ETag + "?api-version=2016-11-14"
+    - requestHttpHeadersHandle: an HTTP headers instance containing the following
+    Authorization: " "
+    If-Match: value of ETag
+    - requestContent: NULL
+    - statusCode: a pointer to unsigned int which might be used by logging
+    - responseHeadearsHandle: NULL
+    - responseContent: NULL]*/
+    /*Codes_SRS_TRANSPORTMULTITHTTP_17_101: [_DoWork shall call HTTPAPIEX_SAS_ExecuteRequest with the following parameters:
+    -requestType: DELETE
+    -relativePath: abandon relative path begin + value of ETag +"?api-version=2016-11-14" + "&reject"
+    - requestHttpHeadersHandle: an HTTP headers instance containing the following
+    Authorization: " "
+    If-Match: value of ETag
+    - requestContent: NULL
+    - statusCode: a pointer to unsigned int which might be used by logging
+    - responseHeadearsHandle: NULL
+    - responseContent: NULL]*/
+
+    bool result;
+    STRING_HANDLE fullAbandonRelativePath = STRING_clone(deviceData->abandonHTTPrelativePathBegin);
+    if (fullAbandonRelativePath == NULL)
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_098: [Abandoning the message is considered successful if the HTTPAPIEX_SAS_ExecuteRequest doesn't fail and the statusCode is 204.]*/
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_100: [Accepting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_102: [Rejecting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
+        LogError("unable to STRING_clone");
+        result = false;
+    }
+    else
+    {
+        STRING_HANDLE ETagUnquoted = STRING_construct_n(ETag + 1, strlen(ETag) - 2); /*skip first character which is '"' and the last one (which is also '"')*/
+        if (ETagUnquoted == NULL)
+        {
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_098: [Abandoning the message is considered successful if the HTTPAPIEX_SAS_ExecuteRequest doesn't fail and the statusCode is 204.]*/
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_100: [Accepting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_102: [Rejecting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
+            LogError("unable to STRING_construct_n");
+            result = false;
+        }
+        else
+        {
+            if (!(
+                (STRING_concat_with_STRING(fullAbandonRelativePath, ETagUnquoted) == 0) &&
+                (STRING_concat(fullAbandonRelativePath, (action == IOTHUBMESSAGE_ABANDONED) ? "/abandon" API_VERSION : ((action == IOTHUBMESSAGE_REJECTED) ? API_VERSION "&reject" : API_VERSION)) == 0)
+                ))
+            {
+                /*Codes_SRS_TRANSPORTMULTITHTTP_17_098: [Abandoning the message is considered successful if the HTTPAPIEX_SAS_ExecuteRequest doesn't fail and the statusCode is 204.]*/
+                /*Codes_SRS_TRANSPORTMULTITHTTP_17_100: [Accepting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
+                /*Codes_SRS_TRANSPORTMULTITHTTP_17_102: [Rejecting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
+                LogError("unable to STRING_concat");
+                result = false;
+            }
+            else
+            {
+                HTTP_HEADERS_HANDLE abandonRequestHttpHeaders = HTTPHeaders_Alloc();
+                if (abandonRequestHttpHeaders == NULL)
+                {
+                    /*Codes_SRS_TRANSPORTMULTITHTTP_17_098: [Abandoning the message is considered successful if the HTTPAPIEX_SAS_ExecuteRequest doesn't fail and the statusCode is 204.]*/
+                    /*Codes_SRS_TRANSPORTMULTITHTTP_17_100: [Accepting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
+                    /*Codes_SRS_TRANSPORTMULTITHTTP_17_102: [Rejecting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
+                    LogError("unable to HTTPHeaders_Alloc");
+                    result = false;
+                }
+                else
+                {
+                    if (!(
+                        (addUserAgentHeaderInfo(handleData, abandonRequestHttpHeaders) == HTTP_HEADERS_OK) &&
+                        (HTTPHeaders_AddHeaderNameValuePair(abandonRequestHttpHeaders, IOTHUB_AUTH_HEADER_VALUE, " ") == HTTP_HEADERS_OK) &&
+                        (HTTPHeaders_AddHeaderNameValuePair(abandonRequestHttpHeaders, "If-Match", ETag) == HTTP_HEADERS_OK)
+                        ))
+                    {
+                        /*Codes_SRS_TRANSPORTMULTITHTTP_17_098: [Abandoning the message is considered successful if the HTTPAPIEX_SAS_ExecuteRequest doesn't fail and the statusCode is 204.]*/
+                        /*Codes_SRS_TRANSPORTMULTITHTTP_17_100: [Accepting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
+                        /*Codes_SRS_TRANSPORTMULTITHTTP_17_102: [Rejecting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
+                        LogError("unable to HTTPHeaders_AddHeaderNameValuePair");
+                        result = false;
+                    }
+                    else
+                    {
+                        unsigned int statusCode = 0;
+                        HTTPAPIEX_RESULT r;
+                        if (deviceData->deviceSasToken != NULL)
+                        {
+                            /*Codes_SRS_TRANSPORTMULTITHTTP_03_001: [if a deviceSasToken exists, HTTPHeaders_ReplaceHeaderNameValuePair shall be invoked with "Authorization" as its second argument and STRING_c_str (deviceSasToken) as its third argument.]*/
+                            if (HTTPHeaders_ReplaceHeaderNameValuePair(abandonRequestHttpHeaders, IOTHUB_AUTH_HEADER_VALUE, STRING_c_str(deviceData->deviceSasToken)) != HTTP_HEADERS_OK)
+                            {
+                                r = HTTPAPIEX_ERROR;
+                                /*Codes_SRS_TRANSPORTMULTITHTTP_03_002: [If the result of the invocation of HTTPHeaders_ReplaceHeaderNameValuePair is NOT HTTP_HEADERS_OK then fallthrough.]*/
+                                LogError("Unable to replace the old SAS Token.");
+                                result = false;
+                            }
+                            else if ((r = HTTPAPIEX_ExecuteRequest(
+                                handleData->httpApiExHandle,
+                                (action == IOTHUBMESSAGE_ABANDONED) ? HTTPAPI_REQUEST_POST : HTTPAPI_REQUEST_DELETE,                               /*-requestType: POST                                                                                                       */
+                                STRING_c_str(fullAbandonRelativePath),              /*-relativePath: abandon relative path begin (as created by _Create) + value of ETag + "/abandon?api-version=2016-11-14"   */
+                                abandonRequestHttpHeaders,                          /*- requestHttpHeadersHandle: an HTTP headers instance containing the following                                            */
+                                NULL,                                               /*- requestContent: NULL                                                                                                   */
+                                &statusCode,                                         /*- statusCode: a pointer to unsigned int which might be examined for logging                                              */
+                                NULL,                                               /*- responseHeadearsHandle: NULL                                                                                           */
+                                NULL                                                /*- responseContent: NULL]                                                                                                 */
+                            )) != HTTPAPIEX_OK)
+                            {
+                                /*Codes_SRS_TRANSPORTMULTITHTTP_17_098: [Abandoning the message is considered successful if the HTTPAPIEX_SAS_ExecuteRequest doesn't fail and the statusCode is 204.]*/
+                                /*Codes_SRS_TRANSPORTMULTITHTTP_17_100: [Accepting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
+                                /*Codes_SRS_TRANSPORTMULTITHTTP_17_102: [Rejecting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
+                                LogError("Unable to HTTPAPIEX_ExecuteRequest.");
+                                result = false;
+                            }
+                        }
+                        else if ((r = HTTPAPIEX_SAS_ExecuteRequest(
+                            deviceData->sasObject,
+                            handleData->httpApiExHandle,
+                            (action == IOTHUBMESSAGE_ABANDONED) ? HTTPAPI_REQUEST_POST : HTTPAPI_REQUEST_DELETE,                               /*-requestType: POST                                                                                                       */
+                            STRING_c_str(fullAbandonRelativePath),              /*-relativePath: abandon relative path begin (as created by _Create) + value of ETag + "/abandon?api-version=2016-11-14"   */
+                            abandonRequestHttpHeaders,                          /*- requestHttpHeadersHandle: an HTTP headers instance containing the following                                            */
+                            NULL,                                               /*- requestContent: NULL                                                                                                   */
+                            &statusCode,                                         /*- statusCode: a pointer to unsigned int which might be examined for logging                                              */
+                            NULL,                                               /*- responseHeadearsHandle: NULL                                                                                           */
+                            NULL                                                /*- responseContent: NULL]                                                                                                 */
+                        )) != HTTPAPIEX_OK)
+                        {
+                            /*Codes_SRS_TRANSPORTMULTITHTTP_17_098: [Abandoning the message is considered successful if the HTTPAPIEX_SAS_ExecuteRequest doesn't fail and the statusCode is 204.]*/
+                            /*Codes_SRS_TRANSPORTMULTITHTTP_17_100: [Accepting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
+                            /*Codes_SRS_TRANSPORTMULTITHTTP_17_102: [Rejecting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
+                            LogError("unable to HTTPAPIEX_SAS_ExecuteRequest");
+                            result = false;
+                        }
+                        if (r == HTTPAPIEX_OK)
+                        {
+                            if (statusCode != 204)
+                            {
+                                /*Codes_SRS_TRANSPORTMULTITHTTP_17_098: [Abandoning the message is considered successful if the HTTPAPIEX_SAS_ExecuteRequest doesn't fail and the statusCode is 204.]*/
+                                /*Codes_SRS_TRANSPORTMULTITHTTP_17_100: [Accepting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
+                                /*Codes_SRS_TRANSPORTMULTITHTTP_17_102: [Rejecting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
+                                LogError("unexpected status code returned %u (was expecting 204)", statusCode);
+                                result = false;
+                            }
+                            else
+                            {
+                                /*Codes_SRS_TRANSPORTMULTITHTTP_17_098: [Abandoning the message is considered successful if the HTTPAPIEX_SAS_ExecuteRequest doesn't fail and the statusCode is 204.]*/
+                                /*Codes_SRS_TRANSPORTMULTITHTTP_17_100: [Accepting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
+                                /*Codes_SRS_TRANSPORTMULTITHTTP_17_102: [Rejecting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
+                                /*all is fine*/
+                                result = true;
+                            }
+                        }
+                        else
+                        {
+                            result = false;
+                        }
+                    }
+                    HTTPHeaders_Free(abandonRequestHttpHeaders);
+                }
+            }
+            STRING_delete(ETagUnquoted);
+        }
+        STRING_delete(fullAbandonRelativePath);
+    }
+    return result;
+}
+
+static IOTHUB_CLIENT_RESULT IoTHubTransportHttp_SendMessageDisposition(MESSAGE_CALLBACK_INFO* message_data, IOTHUBMESSAGE_DISPOSITION_RESULT disposition)
+{
+    IOTHUB_CLIENT_RESULT result;
+    if (message_data == NULL)
+    {
+        /* Codes_SRS_TRANSPORTMULTITHTTP_10_001: [If messageData is NULL, IoTHubTransportHttp_SendMessageDisposition shall fail and return IOTHUB_CLIENT_ERROR.] */
+        LogError("invalid argument messageData is NULL");
+        result = IOTHUB_CLIENT_ERROR;
+    }
+    else
+    {
+        if (message_data->messageHandle == NULL)
+        {
+            /* Codes_SRS_TRANSPORTMULTITHTTP_10_002: [If any of the messageData fields are NULL, IoTHubTransportHttp_SendMessageDisposition shall fail and return IOTHUB_CLIENT_ERROR.] */
+            LogError("invalid message handle");
+            result = IOTHUB_CLIENT_ERROR;
+        }
+        else
+        {
+            MESSAGE_DISPOSITION_CONTEXT* tc = (MESSAGE_DISPOSITION_CONTEXT*)(message_data->transportContext);
+            if (tc == NULL)
+            {
+                /* Codes_SRS_TRANSPORTMULTITHTTP_10_002: [If any of the messageData fields are NULL, IoTHubTransportHttp_SendMessageDisposition shall fail and return IOTHUB_CLIENT_ERROR.] */
+                LogError("invalid transport context data");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else
+            {
+                if ((tc->handleData == NULL) || (tc->deviceData == NULL) || (tc->etagValue == NULL))
+                {
+                    /* Codes_SRS_TRANSPORTMULTITHTTP_10_002: [If any of the messageData fields are NULL, IoTHubTransportHttp_SendMessageDisposition shall fail and return IOTHUB_CLIENT_ERROR.] */
+                    LogError("invalid transport context data");
+                    result = IOTHUB_CLIENT_ERROR;
+                }
+                else
+                {
+                    if (abandonOrAcceptMessage(tc->handleData, tc->deviceData, tc->etagValue, disposition))
+                    {
+                        result = IOTHUB_CLIENT_OK;
+                    }
+                    else
+                    {
+                        /* Codes_SRS_TRANSPORTMULTITHTTP_10_003: [IoTHubTransportHttp_SendMessageDisposition shall fail and return IOTHUB_CLIENT_ERROR if the POST message fails, otherwise return IOTHUB_CLIENT_OK.] */
+                        LogError("HTTP Transport layer failed to report %s disposition", MU_ENUM_TO_STRING(IOTHUBMESSAGE_DISPOSITION_RESULT, disposition));
+                        result = IOTHUB_CLIENT_ERROR;
+                    }
+                }
+                free(tc->etagValue);
+                free(tc);
+            }
+            IoTHubMessage_Destroy(message_data->messageHandle);
+        }
+        free(message_data);
+    }
+    return result;
+}
+
+static MESSAGE_CALLBACK_INFO* MESSAGE_CALLBACK_INFO_Create(IOTHUB_MESSAGE_HANDLE received_message, HTTPTRANSPORT_HANDLE_DATA* handleData, HTTPTRANSPORT_PERDEVICE_DATA* deviceData, const char* etagValue)
+{
+    MESSAGE_CALLBACK_INFO* result = (MESSAGE_CALLBACK_INFO*)malloc(sizeof(MESSAGE_CALLBACK_INFO));
+    if (result == NULL)
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_10_006: [If assembling the transport context fails, _DoWork shall "abandon" the message.] */
+        LogError("malloc failed");
+    }
+    else
+    {
+        MESSAGE_DISPOSITION_CONTEXT* tc = (MESSAGE_DISPOSITION_CONTEXT*)malloc(sizeof(MESSAGE_DISPOSITION_CONTEXT));
+        if (tc == NULL)
+        {
+            /*Codes_SRS_TRANSPORTMULTITHTTP_10_006: [If assembling the transport context fails, _DoWork shall "abandon" the message.] */
+            LogError("malloc failed");
+            free(result);
+            result = NULL;
+        }
+        else
+        {
+            result->messageHandle = IoTHubMessage_Clone(received_message);
+            if (result->messageHandle == NULL)
+            {
+                /*Codes_SRS_TRANSPORTMULTITHTTP_10_007: [If assembling a message clone, _DoWork shall "abandon" the message.]*/
+                LogError("IoTHubMessage_Clone failed");
+                free(tc);
+                free(result);
+                result = NULL;
+            }
+            else
+            {
+                if (mallocAndStrcpy_s(&tc->etagValue, etagValue) != 0)
+                {
+                    LogError("mallocAndStrcpy_s failed");
+                    free(tc);
+                    free(result);
+                    result = NULL;
+                }
+                else
+                {
+                    tc->handleData = handleData;
+                    tc->deviceData = deviceData;
+
+                    result->transportContext = tc;
+                }
+            }
+        }
+    }
+    return result;
+}
+
+static void DoMessages(HTTPTRANSPORT_HANDLE_DATA* handleData, HTTPTRANSPORT_PERDEVICE_DATA* deviceData)
+{
+    /*Codes_SRS_TRANSPORTMULTITHTTP_17_083: [ If device is not subscribed then _DoWork shall advance to the next action. ] */
+    if (deviceData->DoWork_PullMessage)
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_123: [After client creation, the first GET shall be allowed no matter what the value of GetMinimumPollingTime.] */
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_124: [If time is not available then all calls shall be treated as if they are the first one.] */
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_122: [A GET request that happens earlier than GetMinimumPollingTime shall be ignored.] */
+        time_t timeNow = get_time(NULL);
+        bool isPollingAllowed = deviceData->isFirstPoll || (timeNow == (time_t)(-1)) || (get_difftime(timeNow, deviceData->lastPollTime) > handleData->getMinimumPollingTime);
+        if (isPollingAllowed)
+        {
+            HTTP_HEADERS_HANDLE responseHTTPHeaders = HTTPHeaders_Alloc();
+            if (responseHTTPHeaders == NULL)
+            {
+                /*Codes_SRS_TRANSPORTMULTITHTTP_17_085: [If the call to HTTPAPIEX_SAS_ExecuteRequest did not executed successfully or building any part of the prerequisites of the call fails, then _DoWork shall advance to the next action in this description.] */
+                LogError("unable to HTTPHeaders_Alloc");
+            }
+            else
+            {
+                BUFFER_HANDLE responseContent = BUFFER_new();
+                if (responseContent == NULL)
+                {
+                    /*Codes_SRS_TRANSPORTMULTITHTTP_17_085: [If the call to HTTPAPIEX_SAS_ExecuteRequest did not executed successfully or building any part of the prerequisites of the call fails, then _DoWork shall advance to the next action in this description.] */
+                    LogError("unable to BUFFER_new");
+                }
+                else
+                {
+                    unsigned int statusCode = 0;
+                    HTTPAPIEX_RESULT r;
+                    if (deviceData->deviceSasToken != NULL)
+                    {
+                        /*Codes_SRS_TRANSPORTMULTITHTTP_03_001: [if a deviceSasToken exists, HTTPHeaders_ReplaceHeaderNameValuePair shall be invoked with "Authorization" as its second argument and STRING_c_str (deviceSasToken) as its third argument.]*/
+                        if (HTTPHeaders_ReplaceHeaderNameValuePair(deviceData->messageHTTPrequestHeaders, IOTHUB_AUTH_HEADER_VALUE, STRING_c_str(deviceData->deviceSasToken)) != HTTP_HEADERS_OK)
+                        {
+                            r = HTTPAPIEX_ERROR;
+                            /*Codes_SRS_TRANSPORTMULTITHTTP_03_002: [If the result of the invocation of HTTPHeaders_ReplaceHeaderNameValuePair is NOT HTTP_HEADERS_OK then fallthrough.]*/
+                            LogError("Unable to replace the old SAS Token.");
+                        }
+                        else if ((r = HTTPAPIEX_ExecuteRequest(
+                            handleData->httpApiExHandle,
+                            HTTPAPI_REQUEST_GET,                                            /*requestType: GET*/
+                            STRING_c_str(deviceData->messageHTTPrelativePath),         /*relativePath: the message HTTP relative path*/
+                            deviceData->messageHTTPrequestHeaders,                     /*requestHttpHeadersHandle: message HTTP request headers created by _Create*/
+                            NULL,                                                           /*requestContent: NULL*/
+                            &statusCode,                                                    /*statusCode: a pointer to unsigned int which shall be later examined*/
+                            responseHTTPHeaders,                                            /*responseHeadearsHandle: a new instance of HTTP headers*/
+                            responseContent                                                 /*responseContent: a new instance of buffer*/
+                        )) != HTTPAPIEX_OK)
+                        {
+                            /*Codes_SRS_TRANSPORTMULTITHTTP_17_085: [If the call to HTTPAPIEX_SAS_ExecuteRequest did not executed successfully or building any part of the prerequisites of the call fails, then _DoWork shall advance to the next action in this description.] */
+                            LogError("Unable to HTTPAPIEX_ExecuteRequest.");
+                        }
+                    }
+
+                    /*Codes_SRS_TRANSPORTMULTITHTTP_17_084: [Otherwise, IoTHubTransportHttp_DoWork shall call HTTPAPIEX_SAS_ExecuteRequest passing the following parameters
+                    requestType: GET
+                    relativePath: the message HTTP relative path
+                    requestHttpHeadersHandle: message HTTP request headers created by _Create
+                    requestContent: NULL
+                    statusCode: a pointer to unsigned int which shall be later examined
+                    responseHeadearsHandle: a new instance of HTTP headers
+                    responseContent: a new instance of buffer]
+                    */
+                    else if ((r = HTTPAPIEX_SAS_ExecuteRequest(
+                        deviceData->sasObject,
+                        handleData->httpApiExHandle,
+                        HTTPAPI_REQUEST_GET,                                            /*requestType: GET*/
+                        STRING_c_str(deviceData->messageHTTPrelativePath),         /*relativePath: the message HTTP relative path*/
+                        deviceData->messageHTTPrequestHeaders,                     /*requestHttpHeadersHandle: message HTTP request headers created by _Create*/
+                        NULL,                                                           /*requestContent: NULL*/
+                        &statusCode,                                                    /*statusCode: a pointer to unsigned int which shall be later examined*/
+                        responseHTTPHeaders,                                            /*responseHeadearsHandle: a new instance of HTTP headers*/
+                        responseContent                                                 /*responseContent: a new instance of buffer*/
+                    )) != HTTPAPIEX_OK)
+                    {
+                        /*Codes_SRS_TRANSPORTMULTITHTTP_17_085: [If the call to HTTPAPIEX_SAS_ExecuteRequest did not executed successfully or building any part of the prerequisites of the call fails, then _DoWork shall advance to the next action in this description.] */
+                        LogError("unable to HTTPAPIEX_SAS_ExecuteRequest");
+                    }
+                    if (r == HTTPAPIEX_OK)
+                    {
+                        /*HTTP dialogue was succesfull*/
+                        if (timeNow == (time_t)(-1))
+                        {
+                            deviceData->isFirstPoll = true;
+                        }
+                        else
+                        {
+                            deviceData->isFirstPoll = false;
+                            deviceData->lastPollTime = timeNow;
+                        }
+                        if (statusCode == 204)
+                        {
+                            /*Codes_SRS_TRANSPORTMULTITHTTP_17_086: [If the HTTPAPIEX_SAS_ExecuteRequest executed successfully then status code shall be examined. Any status code different than 200 causes _DoWork to advance to the next action.] */
+                            /*this is an expected status code, means "no commands", but logging that creates panic*/
+
+                            /*do nothing, advance to next action*/
+                        }
+                        else if (statusCode != 200)
+                        {
+                            /*Codes_SRS_TRANSPORTMULTITHTTP_17_086: [If the HTTPAPIEX_SAS_ExecuteRequest executed successfully then status code shall be examined. Any status code different than 200 causes _DoWork to advance to the next action.] */
+                            LogError("expected status code was 200, but actually was received %u... moving on", statusCode);
+                        }
+                        else
+                        {
+                            /*Codes_SRS_TRANSPORTMULTITHTTP_17_087: [If status code is 200, then _DoWork shall make a copy of the value of the "ETag" http header.]*/
+                            const char* etagValue = HTTPHeaders_FindHeaderValue(responseHTTPHeaders, "ETag");
+                            if (etagValue == NULL)
+                            {
+                                LogError("unable to find a received header called \"E-Tag\"");
+                            }
+                            else
+                            {
+                                /*Codes_SRS_TRANSPORTMULTITHTTP_17_088: [If no such header is found or is invalid, then _DoWork shall advance to the next action.]*/
+                                size_t etagsize = strlen(etagValue);
+                                if (
+                                    (etagsize < 2) ||
+                                    (etagValue[0] != '"') ||
+                                    (etagValue[etagsize - 1] != '"')
+                                    )
+                                {
+                                    LogError("ETag is not a valid quoted string");
+                                }
+                                else
+                                {
+                                    const unsigned char* resp_content;
+                                    size_t resp_len;
+                                    /*Codes_SRS_TRANSPORTMULTITHTTP_17_089: [_DoWork shall assemble an IOTHUBMESSAGE_HANDLE from the received HTTP content (using the responseContent buffer).] */
+                                    resp_content = BUFFER_u_char(responseContent);
+                                    resp_len = BUFFER_length(responseContent);
+                                    IOTHUB_MESSAGE_HANDLE receivedMessage = IoTHubMessage_CreateFromByteArray(resp_content, resp_len);
+                                    if (receivedMessage == NULL)
+                                    {
+                                        /*Codes_SRS_TRANSPORTMULTITHTTP_17_092: [If assembling the message fails in any way, then _DoWork shall "abandon" the message.]*/
+                                        LogError("unable to IoTHubMessage_CreateFromByteArray, trying to abandon the message... ");
+                                        if (!abandonOrAcceptMessage(handleData, deviceData, etagValue, IOTHUBMESSAGE_ABANDONED))
+                                        {
+                                            LogError("HTTP Transport layer failed to report ABANDON disposition");
+                                        }
+                                    }
+                                    else
+                                    {
+                                        if (retrieve_message_properties(responseHTTPHeaders, receivedMessage) != 0)
+                                        {
+                                            if (!abandonOrAcceptMessage(handleData, deviceData, etagValue, IOTHUBMESSAGE_ABANDONED))
+                                            {
+                                                LogError("HTTP Transport layer failed to report ABANDON disposition");
+                                            }
+                                        }
+                                        else
+                                        {
+                                            MESSAGE_CALLBACK_INFO* messageData = MESSAGE_CALLBACK_INFO_Create(receivedMessage, handleData, deviceData, etagValue);
+                                            if (messageData == NULL)
+                                            {
+                                                /*Codes_SRS_TRANSPORTMULTITHTTP_10_006: [If assembling the transport context fails, _DoWork shall "abandon" the message.] */
+                                                LogError("failed to assemble callback info");
+                                                if (!abandonOrAcceptMessage(handleData, deviceData, etagValue, IOTHUBMESSAGE_ABANDONED))
+                                                {
+                                                    LogError("HTTP Transport layer failed to report ABANDON disposition");
+                                                }
+                                            }
+                                            else
+                                            {
+                                                bool abandon;
+                                                if (handleData->transport_callbacks.msg_cb(messageData, deviceData->device_transport_ctx))
+                                                {
+                                                    abandon = false;
+                                                }
+                                                else
+                                                {
+                                                    LogError("IoTHubClientCore_LL_MessageCallback failed");
+                                                    abandon = true;
+                                                }
+
+                                                /*Codes_SRS_TRANSPORTMULTITHTTP_17_096: [If IoTHubClientCore_LL_MessageCallback returns false then _DoWork shall "abandon" the message.] */
+                                                if (abandon)
+                                                {
+                                                    (void)IoTHubTransportHttp_SendMessageDisposition(messageData, IOTHUBMESSAGE_ABANDONED);
+                                                }
+                                            }
+                                        }
+                                        IoTHubMessage_Destroy(receivedMessage);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    BUFFER_delete(responseContent);
+                }
+                HTTPHeaders_Free(responseHTTPHeaders);
+            }
+        }
+        else
+        {
+            /*isPollingAllowed is false... */
+            /*do nothing "shall be ignored*/
+        }
+    }
+}
+
+static IOTHUB_PROCESS_ITEM_RESULT IoTHubTransportHttp_ProcessItem(TRANSPORT_LL_HANDLE handle, IOTHUB_IDENTITY_TYPE item_type, IOTHUB_IDENTITY_INFO* iothub_item)
+{
+    (void)handle;
+    (void)item_type;
+    (void)iothub_item;
+    LogError("Currently Not Supported.");
+    return IOTHUB_PROCESS_ERROR;
+}
+
+static void IoTHubTransportHttp_DoWork(TRANSPORT_LL_HANDLE handle)
+{
+    /*Codes_SRS_TRANSPORTMULTITHTTP_17_049: [ If handle is NULL, then IoTHubTransportHttp_DoWork shall do nothing. ]*/
+    if (handle != NULL)
+    {
+        HTTPTRANSPORT_HANDLE_DATA* handleData = (HTTPTRANSPORT_HANDLE_DATA*)handle;
+        IOTHUB_DEVICE_HANDLE* listItem;
+        size_t deviceListSize = VECTOR_size(handleData->perDeviceList);
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_052: [ IoTHubTransportHttp_DoWork shall perform a round-robin loop through every deviceHandle in the transport device list. ]*/
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_050: [ IoTHubTransportHttp_DoWork shall call loop through the device list. ] */
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_051: [ IF the list is empty, then IoTHubTransportHttp_DoWork shall do nothing. ]*/
+        for (size_t i = 0; i < deviceListSize; i++)
+        {
+            listItem = (IOTHUB_DEVICE_HANDLE *)VECTOR_element(handleData->perDeviceList, i);
+            HTTPTRANSPORT_PERDEVICE_DATA* perDeviceItem = *(HTTPTRANSPORT_PERDEVICE_DATA**)(listItem);
+            DoEvent(handleData, perDeviceItem);
+            DoMessages(handleData, perDeviceItem);
+        }
+    }
+    else
+    {
+        LogError("Invalid Argument NULL call on DoWork.");
+    }
+}
+
+static IOTHUB_CLIENT_RESULT IoTHubTransportHttp_GetSendStatus(IOTHUB_DEVICE_HANDLE handle, IOTHUB_CLIENT_STATUS *iotHubClientStatus)
+{
+    IOTHUB_CLIENT_RESULT result;
+
+    if (handle == NULL)
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_111: [ IoTHubTransportHttp_GetSendStatus shall return IOTHUB_CLIENT_INVALID_ARG if called with NULL parameter. ]*/
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LogError("Invalid handle to IoTHubClient HTTP transport instance.");
+    }
+    else if (iotHubClientStatus == NULL)
+    {
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LogError("Invalid pointer to output parameter IOTHUB_CLIENT_STATUS.");
+    }
+    else
+    {
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_138: [ IoTHubTransportHttp_GetSendStatus shall locate deviceHandle in the transport device list by calling list_find_if. ]*/
+        IOTHUB_DEVICE_HANDLE* listItem = get_perDeviceDataItem(handle);
+        if (listItem == NULL)
+        {
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_139: [ If the device structure is not found, then this function shall fail and return with IOTHUB_CLIENT_INVALID_ARG. ]*/
+            result = IOTHUB_CLIENT_INVALID_ARG;
+            LogError("Device not found in transport list.");
+        }
+        else
+        {
+            HTTPTRANSPORT_PERDEVICE_DATA* deviceData = (HTTPTRANSPORT_PERDEVICE_DATA*)(*listItem);
+            /* Codes_SRS_TRANSPORTMULTITHTTP_17_113: [ IoTHubTransportHttp_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_BUSY if there are currently event items to be sent or being sent. ] */
+            if (!DList_IsListEmpty(deviceData->waitingToSend))
+            {
+                *iotHubClientStatus = IOTHUB_CLIENT_SEND_STATUS_BUSY;
+            }
+            /* Codes_SRS_TRANSPORTMULTITHTTP_17_112: [ IoTHubTransportHttp_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_IDLE if there are currently no event items to be sent or being sent. ] */
+            else
+            {
+                *iotHubClientStatus = IOTHUB_CLIENT_SEND_STATUS_IDLE;
+            }
+            result = IOTHUB_CLIENT_OK;
+        }
+    }
+
+    return result;
+}
+
+static IOTHUB_CLIENT_RESULT IoTHubTransportHttp_SetOption(TRANSPORT_LL_HANDLE handle, const char* option, const void* value)
+{
+    IOTHUB_CLIENT_RESULT result;
+    /*Codes_SRS_TRANSPORTMULTITHTTP_17_114: [If handle parameter is NULL then IoTHubTransportHttp_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.] */
+    /*Codes_SRS_TRANSPORTMULTITHTTP_17_115: [If option parameter is NULL then IoTHubTransportHttp_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.] */
+    /*Codes_SRS_TRANSPORTMULTITHTTP_17_116: [If value parameter is NULL then IoTHubTransportHttp_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.] */
+    if (
+        (handle == NULL) ||
+        (option == NULL) ||
+        (value == NULL)
+        )
+    {
+        result = IOTHUB_CLIENT_INVALID_ARG;
+        LogError("invalid parameter (NULL) passed to IoTHubTransportHttp_SetOption");
+    }
+    else
+    {
+        HTTPTRANSPORT_HANDLE_DATA* handleData = (HTTPTRANSPORT_HANDLE_DATA*)handle;
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_120: ["Batching"] */
+        if (strcmp(OPTION_BATCHING, option) == 0)
+        {
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_117: [If optionName is an option handled by IoTHubTransportHttp then it shall be set.] */
+            handleData->doBatchedTransfers = *(bool*)value;
+            result = IOTHUB_CLIENT_OK;
+        }
+        /*Codes_SRS_TRANSPORTMULTITHTTP_17_121: ["MinimumPollingTime"] */
+        else if (strcmp(OPTION_MIN_POLLING_TIME, option) == 0)
+        {
+            handleData->getMinimumPollingTime = *(unsigned int*)value;
+            result = IOTHUB_CLIENT_OK;
+        }
+        else
+        {
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_126: [ "TrustedCerts"] */
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_127: [ NULL shall be allowed. ]*/
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_129: [ This option shall passed down to the lower layer by calling HTTPAPIEX_SetOption. ]*/
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_118: [Otherwise, IoTHubTransport_Http shall call HTTPAPIEX_SetOption with the same parameters and return the translated code.] */
+            HTTPAPIEX_RESULT HTTPAPIEX_result = HTTPAPIEX_SetOption(handleData->httpApiExHandle, option, value);
+            /*Codes_SRS_TRANSPORTMULTITHTTP_17_119: [The following table translates HTTPAPIEX return codes to IOTHUB_CLIENT_RESULT return codes:] */
+            if (HTTPAPIEX_result == HTTPAPIEX_OK)
+            {
+                result = IOTHUB_CLIENT_OK;
+            }
+            else if (HTTPAPIEX_result == HTTPAPIEX_INVALID_ARG)
+            {
+                result = IOTHUB_CLIENT_INVALID_ARG;
+                LogError("HTTPAPIEX_SetOption failed");
+            }
+            else
+            {
+                result = IOTHUB_CLIENT_ERROR;
+                LogError("HTTPAPIEX_SetOption failed");
+            }
+        }
+    }
+    return result;
+}
+
+static STRING_HANDLE IoTHubTransportHttp_GetHostname(TRANSPORT_LL_HANDLE handle)
+{
+    STRING_HANDLE result;
+    /*Codes_SRS_TRANSPORTMULTITHTTP_02_001: [ If handle is NULL then IoTHubTransportHttp_GetHostname shall fail and return NULL. ]*/
+    if (handle == NULL)
+    {
+        LogError("invalid parameter handle=%p", handle);
+        result = NULL;
+    }
+    /*Codes_SRS_TRANSPORTMULTITHTTP_02_002: [ Otherwise IoTHubTransportHttp_GetHostname shall return a non-NULL STRING_HANDLE containing the hostname. ]*/
+    else if ((result = STRING_clone(((HTTPTRANSPORT_HANDLE_DATA*)(handle))->hostName)) == NULL)
+    {
+        LogError("Cannot provide the target host name (STRING_clone failed).");
+    }
+
+    return result;
+}
+
+static int IoTHubTransportHttp_SetRetryPolicy(TRANSPORT_LL_HANDLE handle, IOTHUB_CLIENT_RETRY_POLICY retryPolicy, size_t retryTimeoutLimitInSeconds)
+{
+    int result;
+    (void)handle;
+    (void)retryPolicy;
+    (void)retryTimeoutLimitInSeconds;
+
+    /* Retry Policy is not currently not available for HTTP */
+
+    result = 0;
+    return result;
+}
+
+static int IotHubTransportHttp_Subscribe_InputQueue(IOTHUB_DEVICE_HANDLE handle)
+{
+    (void)handle;
+    LogError("HTTP does not support input queues");
+    return MU_FAILURE;
+}
+
+static void IotHubTransportHttp_Unsubscribe_InputQueue(IOTHUB_DEVICE_HANDLE handle)
+{
+    (void)handle;
+    LogError("HTTP does not support input queues");
+}
+
+int IoTHubTransportHttp_SetCallbackContext(TRANSPORT_LL_HANDLE handle, void* ctx)
+{
+    int result;
+    if (handle == NULL)
+    {
+        LogError("Invalid parameter specified handle: %p", handle);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        HTTPTRANSPORT_HANDLE_DATA* handleData = (HTTPTRANSPORT_HANDLE_DATA*)handle;
+        handleData->transport_ctx = ctx;
+        result = 0;
+    }
+    return result;
+}
+
+static int IoTHubTransportHttp_GetSupportedPlatformInfo(TRANSPORT_LL_HANDLE handle, PLATFORM_INFO_OPTION* info)
+{
+    int result;
+    if (handle == NULL)
+    {
+        result = MU_FAILURE;
+    }
+    else
+    {
+        *info = PLATFORM_INFO_OPTION_DEFAULT;
+        result = 0;
+    }
+
+    return result;
+}
+
+/*Codes_SRS_TRANSPORTMULTITHTTP_17_125: [This function shall return a pointer to a structure of type TRANSPORT_PROVIDER having the following values for its fields:] */
+static TRANSPORT_PROVIDER thisTransportProvider =
+{
+    IoTHubTransportHttp_SendMessageDisposition,     /*pfIotHubTransport_SendMessageDisposition IoTHubTransport_SendMessageDisposition;*/
+    IoTHubTransportHttp_Subscribe_DeviceMethod,     /*pfIoTHubTransport_Subscribe_DeviceMethod IoTHubTransport_Subscribe_DeviceMethod;*/
+    IoTHubTransportHttp_Unsubscribe_DeviceMethod,   /*pfIoTHubTransport_Unsubscribe_DeviceMethod IoTHubTransport_Unsubscribe_DeviceMethod;*/
+    IoTHubTransportHttp_DeviceMethod_Response,      /*pfIoTHubTransport_DeviceMethod_Response IoTHubTransport_DeviceMethod_Response;*/
+    IoTHubTransportHttp_Subscribe_DeviceTwin,       /*pfIoTHubTransport_Subscribe_DeviceTwin IoTHubTransport_Subscribe_DeviceTwin;*/
+    IoTHubTransportHttp_Unsubscribe_DeviceTwin,     /*pfIoTHubTransport_Unsubscribe_DeviceTwin IoTHubTransport_Unsubscribe_DeviceTwin;*/
+    IoTHubTransportHttp_ProcessItem,                /*pfIoTHubTransport_ProcessItem IoTHubTransport_ProcessItem;*/
+    IoTHubTransportHttp_GetHostname,                /*pfIoTHubTransport_GetHostname IoTHubTransport_GetHostname;*/
+    IoTHubTransportHttp_SetOption,                  /*pfIoTHubTransport_SetOption IoTHubTransport_SetOption;*/
+    IoTHubTransportHttp_Create,                     /*pfIoTHubTransport_Create IoTHubTransport_Create;*/
+    IoTHubTransportHttp_Destroy,                    /*pfIoTHubTransport_Destroy IoTHubTransport_Destroy;*/
+    IoTHubTransportHttp_Register,                   /*pfIotHubTransport_Register IoTHubTransport_Register;*/
+    IoTHubTransportHttp_Unregister,                 /*pfIotHubTransport_Unregister IoTHubTransport_Unegister;*/
+    IoTHubTransportHttp_Subscribe,                  /*pfIoTHubTransport_Subscribe IoTHubTransport_Subscribe;*/
+    IoTHubTransportHttp_Unsubscribe,                /*pfIoTHubTransport_Unsubscribe IoTHubTransport_Unsubscribe;*/
+    IoTHubTransportHttp_DoWork,                     /*pfIoTHubTransport_DoWork IoTHubTransport_DoWork;*/
+    IoTHubTransportHttp_SetRetryPolicy,             /*pfIoTHubTransport_DoWork IoTHubTransport_SetRetryPolicy;*/
+    IoTHubTransportHttp_GetSendStatus,              /*pfIoTHubTransport_GetSendStatus IoTHubTransport_GetSendStatus;*/
+    IotHubTransportHttp_Subscribe_InputQueue,       /*pfIoTHubTransport_Subscribe_InputQueue IoTHubTransport_Subscribe_InputQueue; */
+    IotHubTransportHttp_Unsubscribe_InputQueue,     /*pfIoTHubTransport_Unsubscribe_InputQueue IoTHubTransport_Unsubscribe_InputQueue; */
+    IoTHubTransportHttp_SetCallbackContext,         /*pfIoTHubTransport_SetTransportCallbacks IoTHubTransport_SetTransportCallbacks; */
+    IoTHubTransportHttp_GetTwinAsync,               /*pfIoTHubTransport_GetTwinAsync IoTHubTransport_GetTwinAsync;*/
+    IoTHubTransportHttp_GetSupportedPlatformInfo      /*pfIoTHubTransport_GetSupportedPlatformInfo IoTHubTransport_GetSupportedPlatformInfo;*/
+};
+
+const TRANSPORT_PROVIDER* HTTP_Protocol(void)
+{
+    return &thisTransportProvider;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothubtransportmqtt.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothubtransportmqtt.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothubtransportmqtt.c	(revision 453)
@@ -0,0 +1,213 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "iothubtransportmqtt.h"
+#include "azure_c_shared_utility/xio.h"
+#include "azure_c_shared_utility/tlsio.h"
+#include "azure_c_shared_utility/platform.h"
+#include "internal/iothubtransport_mqtt_common.h"
+#include "azure_c_shared_utility/xlogging.h"
+
+static XIO_HANDLE getIoTransportProvider(const char* fully_qualified_name, const MQTT_TRANSPORT_PROXY_OPTIONS* mqtt_transport_proxy_options)
+{
+    XIO_HANDLE result;
+
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_01_001: [ `getIoTransportProvider` shall obtain the TLS IO interface handle by calling `platform_get_default_tlsio`. ]*/
+    const IO_INTERFACE_DESCRIPTION* io_interface_description = platform_get_default_tlsio();
+    (void)mqtt_transport_proxy_options;
+
+    if (io_interface_description == NULL)
+    {
+        /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_013: [ If `platform_get_default_tlsio` returns NULL, `getIoTransportProvider` shall return NULL. ] */
+        LogError("Failure constructing the provider interface");
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_01_002: [ The TLS IO parameters shall be a `TLSIO_CONFIG` structure filled as below: ]*/
+        TLSIO_CONFIG tls_io_config;
+
+        /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_01_003: [ - `hostname` shall be set to `fully_qualified_name`. ]*/
+        tls_io_config.hostname = fully_qualified_name;
+        /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_01_004: [ - `port` shall be set to 8883. ]*/
+        tls_io_config.port = 8883;
+        /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_01_005: [ - `underlying_io_interface` shall be set to NULL. ]*/
+        tls_io_config.underlying_io_interface = NULL;
+        /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_01_006: [ - `underlying_io_parameters` shall be set to NULL. ]*/
+        tls_io_config.underlying_io_parameters = NULL;
+
+        /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_012: [ `getIoTransportProvider` shall return the `XIO_HANDLE` returned by `xio_create`. ] */
+        result = xio_create(io_interface_description, &tls_io_config);
+    }
+    return result;
+}
+
+static TRANSPORT_LL_HANDLE IoTHubTransportMqtt_Create(const IOTHUBTRANSPORT_CONFIG* config, TRANSPORT_CALLBACKS_INFO* cb_info, void* ctx)
+{
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_001: [IoTHubTransportMqtt_Create shall create a TRANSPORT_LL_HANDLE by calling into the IoTHubMqttAbstract_Create function.] */
+    return IoTHubTransport_MQTT_Common_Create(config, getIoTransportProvider, cb_info, ctx);
+}
+
+static void IoTHubTransportMqtt_Destroy(TRANSPORT_LL_HANDLE handle)
+{
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_002: [ IoTHubTransportMqtt_Destroy shall destroy the TRANSPORT_LL_HANDLE by calling into the IoTHubMqttAbstract_Destroy function. ] */
+    IoTHubTransport_MQTT_Common_Destroy(handle);
+}
+
+static int IoTHubTransportMqtt_Subscribe(IOTHUB_DEVICE_HANDLE handle)
+{
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_005: [ IoTHubTransportMqtt_Subscribe shall subscribe the TRANSPORT_LL_HANDLE by calling into the IoTHubMqttAbstract_Subscribe function. ] */
+    return IoTHubTransport_MQTT_Common_Subscribe(handle);
+}
+
+static void IoTHubTransportMqtt_Unsubscribe(IOTHUB_DEVICE_HANDLE handle)
+{
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_006: [ IoTHubTransportMqtt_Unsubscribe shall unsubscribe the TRANSPORT_LL_HANDLE by calling into the IoTHubMqttAbstract_Unsubscribe function. ] */
+    IoTHubTransport_MQTT_Common_Unsubscribe(handle);
+}
+
+/* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_026: [ IoTHubTransportMqtt_Subscribe_DeviceMethod shall subscribe the TRANSPORT_LL_HANDLE by calling into the IoTHubMqttAbstract_Subscribe_DeviceMethod function. ] */
+static int IoTHubTransportMqtt_Subscribe_DeviceMethod(IOTHUB_DEVICE_HANDLE handle)
+{
+    return IoTHubTransport_MQTT_Common_Subscribe_DeviceMethod(handle);
+}
+
+/* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_027: [ IoTHubTransportMqtt_Unsubscribe_DeviceMethod shall call into the IoTHubMqttAbstract_Unsubscribe_DeviceMethod function. ] */
+static void IoTHubTransportMqtt_Unsubscribe_DeviceMethod(IOTHUB_DEVICE_HANDLE handle)
+{
+    IoTHubTransport_MQTT_Common_Unsubscribe_DeviceMethod(handle);
+}
+
+/* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_025: [ IoTHubTransportMqtt_Subscribe_DeviceTwin shall call into the IoTHubMqttAbstract_Subscribe_DeviceTwin function. ] */
+static int IoTHubTransportMqtt_Subscribe_DeviceTwin(IOTHUB_DEVICE_HANDLE handle)
+{
+    return IoTHubTransport_MQTT_Common_Subscribe_DeviceTwin(handle);
+}
+
+/* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_024: [ IoTHubTransportMqtt_Unsubscribe_DeviceTwin shall shall call into the IoTHubMqttAbstract_Unsubscribe_DeviceTwin function. ] */
+static void IoTHubTransportMqtt_Unsubscribe_DeviceTwin(IOTHUB_DEVICE_HANDLE handle)
+{
+    IoTHubTransport_MQTT_Common_Unsubscribe_DeviceTwin(handle);
+}
+
+static IOTHUB_CLIENT_RESULT IoTHubTransportMqtt_GetTwinAsync(IOTHUB_DEVICE_HANDLE handle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK completionCallback, void* callbackContext)
+{
+    // Codes_SRS_IOTHUB_MQTT_TRANSPORT_09_001: [ IoTHubTransportMqtt_GetTwinAsync shall call into the IoTHubTransport_MQTT_Common_GetTwinAsync function. ]
+    return IoTHubTransport_MQTT_Common_GetTwinAsync(handle, completionCallback, callbackContext);
+}
+
+/* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_023: [ IoTHubTransportMqtt_DeviceMethod_Response shall call into the IoTHubMqttAbstract_DeviceMethod_Response function. ] */
+static int IoTHubTransportMqtt_DeviceMethod_Response(IOTHUB_DEVICE_HANDLE handle, METHOD_HANDLE methodId, const unsigned char* response, size_t response_size, int status_response)
+{
+    return IoTHubTransport_MQTT_Common_DeviceMethod_Response(handle, methodId, response, response_size, status_response);
+}
+
+/* Codes_SRS_IOTHUB_MQTT_TRANSPORT_10_001: [IoTHubTransportMqtt_SendMessageDisposition shall send the message disposition by calling into the IoTHubMqttAbstract_SendMessageDisposition function.] */
+static IOTHUB_CLIENT_RESULT IoTHubTransportMqtt_SendMessageDisposition(MESSAGE_CALLBACK_INFO* message_data, IOTHUBMESSAGE_DISPOSITION_RESULT disposition)
+{
+    return IoTHubTransport_MQTT_Common_SendMessageDisposition(message_data, disposition);
+}
+
+static IOTHUB_PROCESS_ITEM_RESULT IoTHubTransportMqtt_ProcessItem(TRANSPORT_LL_HANDLE handle, IOTHUB_IDENTITY_TYPE item_type, IOTHUB_IDENTITY_INFO* iothub_item)
+{
+    return IoTHubTransport_MQTT_Common_ProcessItem(handle, item_type, iothub_item);
+}
+
+/* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_054: [ IoTHubTransportMqtt_DoWork shall subscribe to the Notification and get_state Topics if they are defined. ] */
+static void IoTHubTransportMqtt_DoWork(TRANSPORT_LL_HANDLE handle)
+{
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_007: [ IoTHubTransportMqtt_DoWork shall call into the IoTHubMqttAbstract_DoWork function. ] */
+    IoTHubTransport_MQTT_Common_DoWork(handle);
+}
+
+static int IoTHubTransportMqtt_SetRetryPolicy(TRANSPORT_LL_HANDLE handle, IOTHUB_CLIENT_RETRY_POLICY retryPolicy, size_t retryTimeoutLimitInSeconds)
+{
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_25_012: [** IoTHubTransportMqtt_SetRetryPolicy shall call into the IoTHubMqttAbstract_SetRetryPolicy function. ] */
+    return IoTHubTransport_MQTT_Common_SetRetryPolicy(handle, retryPolicy, retryTimeoutLimitInSeconds);
+}
+
+static IOTHUB_CLIENT_RESULT IoTHubTransportMqtt_GetSendStatus(IOTHUB_DEVICE_HANDLE handle, IOTHUB_CLIENT_STATUS *iotHubClientStatus)
+{
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_008: [ IoTHubTransportMqtt_GetSendStatus shall get the send status by calling into the IoTHubMqttAbstract_GetSendStatus function. ] */
+    return IoTHubTransport_MQTT_Common_GetSendStatus(handle, iotHubClientStatus);
+}
+
+static IOTHUB_CLIENT_RESULT IoTHubTransportMqtt_SetOption(TRANSPORT_LL_HANDLE handle, const char* option, const void* value)
+{
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_009: [ IoTHubTransportMqtt_SetOption shall set the options by calling into the IoTHubMqttAbstract_SetOption function. ] */
+    return IoTHubTransport_MQTT_Common_SetOption(handle, option, value);
+}
+
+static IOTHUB_DEVICE_HANDLE IoTHubTransportMqtt_Register(TRANSPORT_LL_HANDLE handle, const IOTHUB_DEVICE_CONFIG* device, PDLIST_ENTRY waitingToSend)
+{
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_003: [ IoTHubTransportMqtt_Register shall register the TRANSPORT_LL_HANDLE by calling into the IoTHubMqttAbstract_Register function. ] */
+    return IoTHubTransport_MQTT_Common_Register(handle, device, waitingToSend);
+}
+
+static void IoTHubTransportMqtt_Unregister(IOTHUB_DEVICE_HANDLE deviceHandle)
+{
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_004: [ IoTHubTransportMqtt_Unregister shall register the TRANSPORT_LL_HANDLE by calling into the IoTHubMqttAbstract_Unregister function. ] */
+    IoTHubTransport_MQTT_Common_Unregister(deviceHandle);
+}
+
+static STRING_HANDLE IoTHubTransportMqtt_GetHostname(TRANSPORT_LL_HANDLE handle)
+{
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_010: [ IoTHubTransportMqtt_GetHostname shall get the hostname by calling into the IoTHubMqttAbstract_GetHostname function. ] */
+    return IoTHubTransport_MQTT_Common_GetHostname(handle);
+}
+
+static int IotHubTransportMqtt_Subscribe_InputQueue(IOTHUB_DEVICE_HANDLE handle)
+{
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_31_14: [ IoTHubTransportMqtt_Subscribe shall subscribe the TRANSPORT_LL_HANDLE by calling into IoTHubTransport_MQTT_Common_Subscribe_InputQueue. ] */
+    return IoTHubTransport_MQTT_Common_Subscribe_InputQueue(handle);
+}
+
+static void IotHubTransportMqtt_Unsubscribe_InputQueue(IOTHUB_DEVICE_HANDLE handle)
+{
+    /* Codes_SRS_IOTHUBTRANSPORTAMQP_31_015: [IotHubTransportMQTT_Unsubscribe_InputQueue shall unsubscribe by calling into IoTHubTransport_MQTT_Common_Unsubscribe_InputQueue. ] */
+    IoTHubTransport_MQTT_Common_Unsubscribe_InputQueue(handle);
+}
+
+static int IotHubTransportMqtt_SetCallbackContext(TRANSPORT_LL_HANDLE handle, void* ctx)
+{
+    return IoTHubTransport_MQTT_SetCallbackContext(handle, ctx);
+}
+
+static int IotHubTransportMqtt_GetSupportedPlatformInfo(TRANSPORT_LL_HANDLE handle, PLATFORM_INFO_OPTION* info)
+{
+    return IoTHubTransport_MQTT_GetSupportedPlatformInfo(handle, info);
+}
+
+static TRANSPORT_PROVIDER myfunc =
+{
+    IoTHubTransportMqtt_SendMessageDisposition,     /*pfIotHubTransport_SendMessageDisposition IoTHubTransport_SendMessageDisposition;*/
+    IoTHubTransportMqtt_Subscribe_DeviceMethod,     /*pfIoTHubTransport_Subscribe_DeviceMethod IoTHubTransport_Subscribe_DeviceMethod;*/
+    IoTHubTransportMqtt_Unsubscribe_DeviceMethod,   /*pfIoTHubTransport_Unsubscribe_DeviceMethod IoTHubTransport_Unsubscribe_DeviceMethod;*/
+    IoTHubTransportMqtt_DeviceMethod_Response,      /*pfIoTHubTransport_DeviceMethod_Response IoTHubTransport_DeviceMethod_Response;*/
+    IoTHubTransportMqtt_Subscribe_DeviceTwin,       /*pfIoTHubTransport_Subscribe_DeviceTwin IoTHubTransport_Subscribe_DeviceTwin;*/
+    IoTHubTransportMqtt_Unsubscribe_DeviceTwin,     /*pfIoTHubTransport_Unsubscribe_DeviceTwin IoTHubTransport_Unsubscribe_DeviceTwin;*/
+    IoTHubTransportMqtt_ProcessItem,                /*pfIoTHubTransport_ProcessItem IoTHubTransport_ProcessItem;*/
+    IoTHubTransportMqtt_GetHostname,                /*pfIoTHubTransport_GetHostname IoTHubTransport_GetHostname;*/
+    IoTHubTransportMqtt_SetOption,                  /*pfIoTHubTransport_SetOption IoTHubTransport_SetOption;*/
+    IoTHubTransportMqtt_Create,                     /*pfIoTHubTransport_Create IoTHubTransport_Create;*/
+    IoTHubTransportMqtt_Destroy,                    /*pfIoTHubTransport_Destroy IoTHubTransport_Destroy;*/
+    IoTHubTransportMqtt_Register,                   /*pfIotHubTransport_Register IoTHubTransport_Register;*/
+    IoTHubTransportMqtt_Unregister,                 /*pfIotHubTransport_Unregister IoTHubTransport_Unegister;*/
+    IoTHubTransportMqtt_Subscribe,                  /*pfIoTHubTransport_Subscribe IoTHubTransport_Subscribe;*/
+    IoTHubTransportMqtt_Unsubscribe,                /*pfIoTHubTransport_Unsubscribe IoTHubTransport_Unsubscribe;*/
+    IoTHubTransportMqtt_DoWork,                     /*pfIoTHubTransport_DoWork IoTHubTransport_DoWork;*/
+    IoTHubTransportMqtt_SetRetryPolicy,             /*pfIoTHubTransport_DoWork IoTHubTransport_SetRetryPolicy;*/
+    IoTHubTransportMqtt_GetSendStatus,              /*pfIoTHubTransport_GetSendStatus IoTHubTransport_GetSendStatus;*/
+    IotHubTransportMqtt_Subscribe_InputQueue,       /*pfIoTHubTransport_Subscribe_InputQueue IoTHubTransport_Subscribe_InputQueue; */
+    IotHubTransportMqtt_Unsubscribe_InputQueue,     /*pfIoTHubTransport_Unsubscribe_InputQueue IoTHubTransport_Unsubscribe_InputQueue; */
+    IotHubTransportMqtt_SetCallbackContext,         /*pfIoTHubTransport_SetCallbackContext IoTHubTransport_SetCallbackContext; */
+    IoTHubTransportMqtt_GetTwinAsync,               /*pfIoTHubTransport_GetTwinAsync IoTHubTransport_GetTwinAsync;*/
+    IotHubTransportMqtt_GetSupportedPlatformInfo      /*pfIoTHubTransport_GetSupportedPlatformInfo IoTHubTransport_GetSupportedPlatformInfo;*/
+};
+
+/* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_022: [This function shall return a pointer to a structure of type TRANSPORT_PROVIDER */
+extern const TRANSPORT_PROVIDER* MQTT_Protocol(void)
+{
+    return &myfunc;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothubtransportmqtt_websockets.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothubtransportmqtt_websockets.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/iothubtransportmqtt_websockets.c	(revision 453)
@@ -0,0 +1,282 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "azure_c_shared_utility/xio.h"
+#include "azure_c_shared_utility/wsio.h"
+#include "azure_c_shared_utility/tlsio.h"
+#include "azure_c_shared_utility/platform.h"
+#include "azure_c_shared_utility/http_proxy_io.h"
+#include "iothubtransportmqtt_websockets.h"
+#include "internal/iothubtransport_mqtt_common.h"
+
+static XIO_HANDLE getWebSocketsIOTransport(const char* fully_qualified_name, const MQTT_TRANSPORT_PROXY_OPTIONS* mqtt_transport_proxy_options)
+{
+    XIO_HANDLE result;
+    /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_01_001: [ `getIoTransportProvider` shall obtain the WebSocket IO interface handle by calling `wsio_get_interface_description`. ]*/
+    const IO_INTERFACE_DESCRIPTION* io_interface_description = wsio_get_interface_description();
+    TLSIO_CONFIG tls_io_config;
+    HTTP_PROXY_IO_CONFIG http_proxy_io_config;
+
+    if (io_interface_description == NULL)
+    {
+        /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_07_013: [ If `wsio_get_interface_description` returns NULL `getIoTransportProvider` shall return NULL. ] */
+        LogError("Failure constructing the provider interface");
+        result = NULL;
+    }
+    else
+    {
+        WSIO_CONFIG ws_io_config;
+
+        /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_01_003: [ - `hostname` shall be set to `fully_qualified_name`. ]*/
+        ws_io_config.hostname = fully_qualified_name;
+        /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_01_004: [ - `port` shall be set to 443. ]*/
+        ws_io_config.port = 443;
+        /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_01_005: [ - `protocol` shall be set to `MQTT`. ]*/
+        ws_io_config.protocol = "MQTT";
+        /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_01_006: [ - `resource_name` shall be set to `/$iothub/websocket`. ]*/
+        ws_io_config.resource_name = "/$iothub/websocket";
+        /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_01_007: [ - `underlying_io_interface` shall be set to the TLS IO interface description. ]*/
+        /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_01_009: [ `getIoTransportProvider` shall obtain the TLS IO interface handle by calling `platform_get_default_tlsio`. ]*/
+        ws_io_config.underlying_io_interface = platform_get_default_tlsio();
+
+        /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_01_029: [ If `platform_get_default_tlsio` returns NULL, NULL shall be set in the WebSocket IO parameters structure for the interface description and parameters. ]*/
+        if (ws_io_config.underlying_io_interface == NULL)
+        {
+            ws_io_config.underlying_io_parameters = NULL;
+        }
+        else
+        {
+            /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_01_008: [ - `underlying_io_parameters` shall be set to the TLS IO arguments. ]*/
+            /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_01_010: [ The TLS IO parameters shall be a TLSIO_CONFIG structure filled as below: ]*/
+            ws_io_config.underlying_io_parameters = &tls_io_config;
+
+            /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_01_011: [ - `hostname` shall be set to `fully_qualified_name`. ]*/
+            tls_io_config.hostname = fully_qualified_name;
+            /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_01_012: [ - `port` shall be set to 443. ]*/
+            tls_io_config.port = 443;
+
+            if (mqtt_transport_proxy_options != NULL)
+            {
+                /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_01_015: [ - If `mqtt_transport_proxy_options` is not NULL, `underlying_io_interface` shall be set to the HTTP proxy IO interface description. ]*/
+                /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_01_022: [ `getIoTransportProvider` shall obtain the HTTP proxy IO interface handle by calling `http_proxy_io_get_interface_description`. ]*/
+                tls_io_config.underlying_io_interface = http_proxy_io_get_interface_description();
+
+                /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_01_028: [ If `http_proxy_io_get_interface_description` returns NULL, NULL shall be set in the TLS IO parameters structure for the interface description and parameters. ]*/
+                if (tls_io_config.underlying_io_interface == NULL)
+                {
+                    tls_io_config.underlying_io_parameters = NULL;
+                }
+                else
+                {
+                    /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_01_016: [ - If `mqtt_transport_proxy_options` is not NULL `underlying_io_parameters` shall be set to the HTTP proxy IO arguments. ]*/
+                    tls_io_config.underlying_io_parameters = &http_proxy_io_config;
+
+                    /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_01_023: [ The HTTP proxy IO arguments shall be an `HTTP_PROXY_IO_CONFIG` structure, filled as below: ]*/
+                    /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_01_026: [ - `proxy_hostname`, `proxy_port`, `username` and `password` shall be copied from the `mqtt_transport_proxy_options` argument. ]*/
+                    http_proxy_io_config.proxy_hostname = mqtt_transport_proxy_options->host_address;
+                    http_proxy_io_config.proxy_port = mqtt_transport_proxy_options->port;
+                    http_proxy_io_config.username = mqtt_transport_proxy_options->username;
+                    http_proxy_io_config.password = mqtt_transport_proxy_options->password;
+                    /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_01_024: [ - `hostname` shall be set to `fully_qualified_name`. ]*/
+                    http_proxy_io_config.hostname = fully_qualified_name;
+                    /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_01_025: [ - `port` shall be set to 443. ]*/
+                    http_proxy_io_config.port = 443;
+                }
+            }
+            else
+            {
+                /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_01_013: [ - If `mqtt_transport_proxy_options` is NULL, `underlying_io_interface` shall be set to NULL ]*/
+                tls_io_config.underlying_io_interface = NULL;
+                /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_01_014: [ - If `mqtt_transport_proxy_options` is NULL `underlying_io_parameters` shall be set to NULL. ]*/
+                tls_io_config.underlying_io_parameters = NULL;
+            }
+        }
+
+        /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_07_012: [ `getIoTransportProvider` shall return the `XIO_HANDLE` returned by `xio_create`. ] */
+        /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_01_002: [ `getIoTransportProvider` shall call `xio_create` while passing the WebSocket IO interface description to it and the WebSocket configuration as a WSIO_CONFIG structure, filled as below ]*/
+        result = xio_create(io_interface_description, &ws_io_config);
+    }
+    return result;
+}
+
+/* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_07_001: [ IoTHubTransportMqtt_WS_Create shall create a TRANSPORT_LL_HANDLE by calling into the IoTHubMqttAbstract_Create function. ] */
+static TRANSPORT_LL_HANDLE IoTHubTransportMqtt_WS_Create(const IOTHUBTRANSPORT_CONFIG* config, TRANSPORT_CALLBACKS_INFO* cb_info, void* ctx)
+{
+    return IoTHubTransport_MQTT_Common_Create(config, getWebSocketsIOTransport, cb_info, ctx);
+}
+
+/* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_07_002: [ IoTHubTransportMqtt_WS_Destroy shall destroy the TRANSPORT_LL_HANDLE by calling into the IoTHubMqttAbstract_Destroy function. ] */
+static void IoTHubTransportMqtt_WS_Destroy(TRANSPORT_LL_HANDLE handle)
+{
+    IoTHubTransport_MQTT_Common_Destroy(handle);
+}
+
+/* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_07_005: [ IoTHubTransportMqtt_WS_Subscribe shall subscribe the TRANSPORT_LL_HANDLE by calling into the IoTHubMqttAbstract_Subscribe function. ] */
+static int IoTHubTransportMqtt_WS_Subscribe(IOTHUB_DEVICE_HANDLE handle)
+{
+    return IoTHubTransport_MQTT_Common_Subscribe(handle);
+}
+
+/* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_07_006: [ IoTHubTransportMqtt_WS_Unsubscribe shall unsubscribe the TRANSPORT_LL_HANDLE by calling into the IoTHubMqttAbstract_Unsubscribe function. ] */
+static void IoTHubTransportMqtt_WS_Unsubscribe(IOTHUB_DEVICE_HANDLE handle)
+{
+    IoTHubTransport_MQTT_Common_Unsubscribe(handle);
+}
+
+/* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_07_015: [ IoTHubTransportMqtt_WS_Subscribe_DeviceMethod shall call into the IoTHubTransport_MQTT_Common_Subscribe_DeviceMethod function ] */
+static int IoTHubTransportMqtt_WS_Subscribe_DeviceMethod(IOTHUB_DEVICE_HANDLE handle)
+{
+    return IoTHubTransport_MQTT_Common_Subscribe_DeviceMethod(handle);
+}
+
+/* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_07_016: [ IoTHubTransportMqtt_WS_Unsubscribe_DeviceMethod shall call into the IoTHubTransport_MQTT_Common_Unsubscribe_DeviceMethod ] */
+static void IoTHubTransportMqtt_WS_Unsubscribe_DeviceMethod(IOTHUB_DEVICE_HANDLE handle)
+{
+    IoTHubTransport_MQTT_Common_Unsubscribe_DeviceMethod(handle);
+}
+
+static int IoTHubTransportMqtt_WS_DeviceMethod_Response(IOTHUB_DEVICE_HANDLE handle, METHOD_HANDLE methodId, const unsigned char* response, size_t response_size, int status_response)
+{
+    return IoTHubTransport_MQTT_Common_DeviceMethod_Response(handle, methodId, response, response_size, status_response);
+}
+
+/* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_07_017: [ IoTHubTransportMqtt_WS_Subscribe_DeviceTwin shall call into the IoTHubTransport_MQTT_Common_Subscribe_DeviceTwin ] */
+static int IoTHubTransportMqtt_WS_Subscribe_DeviceTwin(IOTHUB_DEVICE_HANDLE handle)
+{
+    return IoTHubTransport_MQTT_Common_Subscribe_DeviceTwin(handle);
+}
+
+/* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_07_018: [ IoTHubTransportMqtt_WS_Unsubscribe_DeviceTwin shall call into the IoTHubTransport_MQTT_Common_Unsubscribe_DeviceTwin ] */
+static void IoTHubTransportMqtt_WS_Unsubscribe_DeviceTwin(IOTHUB_DEVICE_HANDLE handle)
+{
+    IoTHubTransport_MQTT_Common_Unsubscribe_DeviceTwin(handle);
+}
+
+// Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_09_001: [ IoTHubTransportMqtt_WS_GetTwinAsync shall call into the IoTHubTransport_MQTT_Common_GetTwinAsync ]
+static IOTHUB_CLIENT_RESULT IoTHubTransportMqtt_WS_GetTwinAsync(IOTHUB_DEVICE_HANDLE handle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK completionCallback, void* callbackContext)
+{
+    return IoTHubTransport_MQTT_Common_GetTwinAsync(handle, completionCallback, callbackContext);
+}
+
+/* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_07_014: [ IoTHubTransportMqtt_WS_ProcessItem shall call into the IoTHubTransport_MQTT_Common_DoWork function ] */
+static IOTHUB_PROCESS_ITEM_RESULT IoTHubTransportMqtt_WS_ProcessItem(TRANSPORT_LL_HANDLE handle, IOTHUB_IDENTITY_TYPE item_type, IOTHUB_IDENTITY_INFO* iothub_item)
+{
+    return IoTHubTransport_MQTT_Common_ProcessItem(handle, item_type, iothub_item);
+}
+
+/* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_07_007: [ IoTHubTransportMqtt_WS_DoWork shall call into the IoTHubMqttAbstract_DoWork function. ] */
+static void IoTHubTransportMqtt_WS_DoWork(TRANSPORT_LL_HANDLE handle)
+{
+    IoTHubTransport_MQTT_Common_DoWork(handle);
+}
+
+/* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_07_008: [ IoTHubTransportMqtt_WS_GetSendStatus shall get the send status by calling into the IoTHubMqttAbstract_GetSendStatus function. ] */
+static IOTHUB_CLIENT_RESULT IoTHubTransportMqtt_WS_GetSendStatus(IOTHUB_DEVICE_HANDLE handle, IOTHUB_CLIENT_STATUS *iotHubClientStatus)
+{
+    return IoTHubTransport_MQTT_Common_GetSendStatus(handle, iotHubClientStatus);
+}
+
+/* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_07_009: [ IoTHubTransportMqtt_WS_SetOption shall set the options by calling into the IoTHubMqttAbstract_SetOption function. ] */
+static IOTHUB_CLIENT_RESULT IoTHubTransportMqtt_WS_SetOption(TRANSPORT_LL_HANDLE handle, const char* option, const void* value)
+{
+    return IoTHubTransport_MQTT_Common_SetOption(handle, option, value);
+}
+
+/* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_07_003: [ IoTHubTransportMqtt_WS_Register shall register the TRANSPORT_LL_HANDLE by calling into the IoTHubMqttAbstract_Register function. ]*/
+static IOTHUB_DEVICE_HANDLE IoTHubTransportMqtt_WS_Register(TRANSPORT_LL_HANDLE handle, const IOTHUB_DEVICE_CONFIG* device, PDLIST_ENTRY waitingToSend)
+{
+    return IoTHubTransport_MQTT_Common_Register(handle, device, waitingToSend);
+}
+
+/* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_07_004: [ IoTHubTransportMqtt_WS_Unregister shall register the TRANSPORT_LL_HANDLE by calling into the IoTHubMqttAbstract_Unregister function. ] */
+static void IoTHubTransportMqtt_WS_Unregister(IOTHUB_DEVICE_HANDLE deviceHandle)
+{
+    IoTHubTransport_MQTT_Common_Unregister(deviceHandle);
+}
+
+/* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_07_010: [ IoTHubTransportMqtt_WS_GetHostname shall get the hostname by calling into the IoTHubMqttAbstract_GetHostname function. ] */
+static STRING_HANDLE IoTHubTransportMqtt_WS_GetHostname(TRANSPORT_LL_HANDLE handle)
+{
+    return IoTHubTransport_MQTT_Common_GetHostname(handle);
+}
+
+static int IoTHubTransportMqtt_WS_SetRetryPolicy(TRANSPORT_LL_HANDLE handle, IOTHUB_CLIENT_RETRY_POLICY retryPolicy, size_t retryTimeoutLimitinSeconds)
+{
+    /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_25_012: [** IoTHubTransportMqtt_WS_SetRetryPolicy shall call into the IoTHubMqttAbstract_SetRetryPolicy function.]*/
+    return IoTHubTransport_MQTT_Common_SetRetryPolicy(handle, retryPolicy, retryTimeoutLimitinSeconds);
+}
+
+static IOTHUB_CLIENT_RESULT IoTHubTransportMqtt_WS_SendMessageDisposition(MESSAGE_CALLBACK_INFO* message_data, IOTHUBMESSAGE_DISPOSITION_RESULT disposition)
+{
+    /* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_10_001: [IoTHubTransportMqtt_WS_SendMessageDisposition shall send the message disposition by calling into the IoTHubTransport_MQTT_Common_SendMessageDisposition()]*/
+    return IoTHubTransport_MQTT_Common_SendMessageDisposition(message_data, disposition);
+}
+
+static int IoTHubTransportMqtt_WS_Subscribe_InputQueue(IOTHUB_DEVICE_HANDLE handle)
+{
+    (void)handle;
+    LogError("IoTHubTransportMqtt_WS_Subscribe_InputQueue not implemented\n");
+    return MU_FAILURE;
+}
+
+static void IoTHubTransportMqtt_WS_Unsubscribe_InputQueue(IOTHUB_DEVICE_HANDLE handle)
+{
+    LogError("IoTHubTransportMqtt_WS_Unsubscribe_InputQueue not implemented\n");
+    (void)handle;
+}
+
+static int IotHubTransportMqtt_WS_SetCallbackContext(TRANSPORT_LL_HANDLE handle, void* ctx)
+{
+    return IoTHubTransport_MQTT_SetCallbackContext(handle, ctx);
+}
+
+static int IotHubTransportMqtt_WS_GetSupportedPlatformInfo(TRANSPORT_LL_HANDLE handle, PLATFORM_INFO_OPTION* info)
+{
+    return IoTHubTransport_MQTT_GetSupportedPlatformInfo(handle, info);
+}
+
+/* Codes_SRS_IOTHUB_MQTT_WEBSOCKET_TRANSPORT_07_011: [ This function shall return a pointer to a structure of type TRANSPORT_PROVIDER having the following values for its fields:
+IoTHubTransport_SendMessageDisposition = IoTHubTransport_WS_SendMessageDisposition
+IoTHubTransport_Subscribe_DeviceMethod = IoTHubTransport_WS_Subscribe_DeviceMethod
+IoTHubTransport_Unsubscribe_DeviceMethod IoTHubTransport_WS_Unsubscribe_DeviceMethod
+IoTHubTransport_Subscribe_DeviceTwin IoTHubTransport_WS_Subscribe_DeviceTwin
+IoTHubTransport_Unsubscribe_DeviceTwin IoTHubTransport_WS_Unsubscribe_DeviceTwin
+IoTHubTransport_GetHostname = IoTHubTransportMqtt_WS_GetHostname
+IoTHubTransport_Create = IoTHubTransportMqtt_WS_Create
+IoTHubTransport_Destroy = IoTHubTransportMqtt_WS_Destroy
+IoTHubTransport_Subscribe = IoTHubTransportMqtt_WS_Subscribe
+IoTHubTransport_Unsubscribe = IoTHubTransportMqtt_WS_Unsubscribe
+IoTHubTransport_DoWork = IoTHubTransportMqtt_WS_DoWork
+IoTHubTransport_SetOption = IoTHubTransportMqtt_WS_SetOption 
+IoTHubTransport_GetSupportedPlatformInfo = IoTHubTransportMqtt_WS_GetSupportedPlatformInfo ] */
+static TRANSPORT_PROVIDER thisTransportProvider_WebSocketsOverTls = {
+    IoTHubTransportMqtt_WS_SendMessageDisposition,
+    IoTHubTransportMqtt_WS_Subscribe_DeviceMethod,
+    IoTHubTransportMqtt_WS_Unsubscribe_DeviceMethod,
+    IoTHubTransportMqtt_WS_DeviceMethod_Response,
+    IoTHubTransportMqtt_WS_Subscribe_DeviceTwin,
+    IoTHubTransportMqtt_WS_Unsubscribe_DeviceTwin,
+    IoTHubTransportMqtt_WS_ProcessItem,
+    IoTHubTransportMqtt_WS_GetHostname,
+    IoTHubTransportMqtt_WS_SetOption,
+    IoTHubTransportMqtt_WS_Create,
+    IoTHubTransportMqtt_WS_Destroy,
+    IoTHubTransportMqtt_WS_Register,
+    IoTHubTransportMqtt_WS_Unregister,
+    IoTHubTransportMqtt_WS_Subscribe,
+    IoTHubTransportMqtt_WS_Unsubscribe,
+    IoTHubTransportMqtt_WS_DoWork,
+    IoTHubTransportMqtt_WS_SetRetryPolicy,
+    IoTHubTransportMqtt_WS_GetSendStatus,
+    IoTHubTransportMqtt_WS_Subscribe_InputQueue,
+    IoTHubTransportMqtt_WS_Unsubscribe_InputQueue,
+    IotHubTransportMqtt_WS_SetCallbackContext,
+    IoTHubTransportMqtt_WS_GetTwinAsync,
+    IotHubTransportMqtt_WS_GetSupportedPlatformInfo
+};
+
+const TRANSPORT_PROVIDER* MQTT_WebSocket_Protocol(void)
+{
+    return &thisTransportProvider_WebSocketsOverTls;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/version.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/version.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/iothub_client/src/version.c	(revision 453)
@@ -0,0 +1,10 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include "iothub_client_version.h"
+
+const char* IoTHubClient_GetVersionString(void)
+{
+    /*Codes_SRS_IOTHUBCLIENT_05_001: [IoTHubClient_GetVersionString shall return a pointer to a constant string which indicates the version of IoTHubClient API.]*/
+    return IOTHUB_SDK_VERSION;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/adapters/hsm_client_data.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/adapters/hsm_client_data.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/adapters/hsm_client_data.c	(revision 453)
@@ -0,0 +1,61 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+
+#include "azure_c_shared_utility/xlogging.h"
+#include "hsm_client_data.h"
+
+#if defined(HSM_TYPE_SAS_TOKEN)  || defined(HSM_AUTH_TYPE_CUSTOM)
+#include "hsm_client_tpm.h"
+#endif
+
+#if defined(HSM_TYPE_X509) || defined(HSM_AUTH_TYPE_CUSTOM)
+#include "hsm_client_riot.h"
+#endif
+
+#if defined(HSM_TYPE_SYMM_KEY) || defined(HSM_AUTH_TYPE_CUSTOM)
+#include "hsm_client_key.h"
+#endif
+
+int initialize_hsm_system()
+{
+    int result = 0;
+#if defined(HSM_TYPE_X509) || defined(HSM_AUTH_TYPE_CUSTOM)
+    // Initialize x509
+    if ((result == 0) && (hsm_client_x509_init() != 0))
+    {
+        LogError("Failure initializing x509 system");
+        result = __LINE__;
+    }
+#endif
+#if defined(HSM_TYPE_SAS_TOKEN)  || defined(HSM_AUTH_TYPE_CUSTOM)
+    if ((result == 0) && (hsm_client_tpm_init() != 0))
+    {
+        LogError("Failure initializing tpm system");
+        result = __LINE__;
+    }
+#endif
+#ifdef HSM_TYPE_HTTP_EDGE
+    if ((result == 0) && (hsm_client_http_edge_init() != 0))
+    {
+        LogError("Failure initializing http edge system");
+        result = __LINE__;
+    }
+#endif
+
+    return result;
+}
+
+void deinitialize_hsm_system()
+{
+#ifdef HSM_TYPE_HTTP_EDGE
+    hsm_client_http_edge_deinit();
+#endif
+#if defined(HSM_TYPE_X509) || defined(HSM_AUTH_TYPE_CUSTOM)
+    hsm_client_x509_deinit();
+#endif
+#if defined(HSM_TYPE_SAS_TOKEN)  || defined(HSM_AUTH_TYPE_CUSTOM)
+    hsm_client_tpm_deinit();
+#endif
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/adapters/hsm_client_data.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/adapters/hsm_client_data.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/adapters/hsm_client_data.h	(revision 453)
@@ -0,0 +1,101 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef HSM_CLIENT_DATA_H
+#define HSM_CLIENT_DATA_H
+
+#ifdef __cplusplus
+#include <cstddef>
+extern "C" {
+#else
+#include <stddef.h>
+#endif /* __cplusplus */
+
+typedef void* HSM_CLIENT_HANDLE;
+
+typedef HSM_CLIENT_HANDLE (*HSM_CLIENT_CREATE)();
+typedef void (*HSM_CLIENT_DESTROY)(HSM_CLIENT_HANDLE handle);
+
+// TPM
+typedef int (*HSM_CLIENT_ACTIVATE_IDENTITY_KEY)(HSM_CLIENT_HANDLE handle, const unsigned char* key, size_t key_len);
+typedef int (*HSM_CLIENT_GET_ENDORSEMENT_KEY)(HSM_CLIENT_HANDLE handle, unsigned char** key, size_t* key_len);
+typedef int (*HSM_CLIENT_GET_STORAGE_ROOT_KEY)(HSM_CLIENT_HANDLE handle, unsigned char** key, size_t* key_len);
+typedef int (*HSM_CLIENT_SIGN_WITH_IDENTITY)(HSM_CLIENT_HANDLE handle, const unsigned char* data, size_t data_len, unsigned char** key, size_t* key_len);
+
+// x509
+typedef char* (*HSM_CLIENT_GET_CERTIFICATE)(HSM_CLIENT_HANDLE handle);
+typedef char* (*HSM_CLIENT_GET_ALIAS_KEY)(HSM_CLIENT_HANDLE handle);
+typedef char* (*HSM_CLIENT_GET_COMMON_NAME)(HSM_CLIENT_HANDLE handle);
+
+// Edge
+typedef char* (*HSM_CLIENT_GET_TRUST_BUNDLE)(HSM_CLIENT_HANDLE handle);
+
+// Symmetrical Keys
+typedef char* (*HSM_CLIENT_GET_SYMMETRICAL_KEY)(HSM_CLIENT_HANDLE handle);
+typedef char* (*HSM_CLIENT_GET_REGISTRATION_NAME)(HSM_CLIENT_HANDLE handle);
+typedef int (*HSM_CLIENT_SET_SYMMETRICAL_KEY_INFO)(HSM_CLIENT_HANDLE handle, const char* reg_name, const char* symm_key);
+
+typedef struct HSM_CLIENT_TPM_INTERFACE_TAG
+{
+    HSM_CLIENT_CREATE hsm_client_tpm_create;
+    HSM_CLIENT_DESTROY hsm_client_tpm_destroy;
+
+    HSM_CLIENT_ACTIVATE_IDENTITY_KEY hsm_client_activate_identity_key;
+    HSM_CLIENT_GET_ENDORSEMENT_KEY hsm_client_get_ek;
+    HSM_CLIENT_GET_STORAGE_ROOT_KEY hsm_client_get_srk;
+    HSM_CLIENT_SIGN_WITH_IDENTITY hsm_client_sign_with_identity;
+} HSM_CLIENT_TPM_INTERFACE;
+
+typedef struct HSM_CLIENT_X509_INTERFACE_TAG
+{
+    HSM_CLIENT_CREATE hsm_client_x509_create;
+    HSM_CLIENT_DESTROY hsm_client_x509_destroy;
+
+    HSM_CLIENT_GET_CERTIFICATE hsm_client_get_cert;
+    HSM_CLIENT_GET_ALIAS_KEY hsm_client_get_key;
+    HSM_CLIENT_GET_COMMON_NAME hsm_client_get_common_name;
+} HSM_CLIENT_X509_INTERFACE;
+
+#ifdef HSM_TYPE_HTTP_EDGE
+typedef struct HSM_CLIENT_HTTP_EDGE_INTERFACE_TAG
+{
+    HSM_CLIENT_CREATE hsm_client_http_edge_create;
+    HSM_CLIENT_DESTROY hsm_client_http_edge_destroy;
+    HSM_CLIENT_SIGN_WITH_IDENTITY hsm_client_sign_with_identity;
+    HSM_CLIENT_GET_TRUST_BUNDLE hsm_client_get_trust_bundle;
+} HSM_CLIENT_HTTP_EDGE_INTERFACE;
+#endif
+
+typedef struct HSM_CLIENT_KEY_INTERFACE_TAG
+{
+    HSM_CLIENT_CREATE hsm_client_key_create;
+    HSM_CLIENT_DESTROY hsm_client_key_destroy;
+
+    HSM_CLIENT_GET_SYMMETRICAL_KEY hsm_client_get_symm_key;
+    HSM_CLIENT_GET_REGISTRATION_NAME hsm_client_get_registration_name;
+    HSM_CLIENT_SET_SYMMETRICAL_KEY_INFO hsm_client_set_symm_key_info;
+} HSM_CLIENT_KEY_INTERFACE;
+
+extern int initialize_hsm_system();
+extern void deinitialize_hsm_system();
+
+extern const HSM_CLIENT_TPM_INTERFACE* hsm_client_tpm_interface();
+extern const HSM_CLIENT_X509_INTERFACE* hsm_client_x509_interface();
+extern const HSM_CLIENT_KEY_INTERFACE* hsm_client_key_interface();
+
+extern int hsm_client_x509_init();
+extern void hsm_client_x509_deinit();
+extern int hsm_client_tpm_init();
+extern void hsm_client_tpm_deinit();
+
+#ifdef HSM_TYPE_HTTP_EDGE
+extern int hsm_client_http_edge_init();
+extern void hsm_client_http_edge_deinit(void);
+extern const HSM_CLIENT_HTTP_EDGE_INTERFACE* hsm_client_http_edge_interface();
+#endif
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif // HSM_CLIENT_DATA_H
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/adapters/hsm_client_key.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/adapters/hsm_client_key.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/adapters/hsm_client_key.c	(revision 453)
@@ -0,0 +1,151 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "umock_c/umock_c_prod.h"
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/urlencode.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+
+#include "hsm_client_data.h"
+#include "hsm_client_key.h"
+
+typedef struct HSM_CLIENT_KEY_INFO_TAG
+{
+    char* symmetrical_key;
+    char* registration_name;
+} HSM_CLIENT_KEY_INFO;
+
+HSM_CLIENT_HANDLE hsm_client_key_create(void)
+{
+    HSM_CLIENT_KEY_INFO* result;
+    result = malloc(sizeof(HSM_CLIENT_KEY_INFO) );
+    if (result == NULL)
+    {
+        LogError("Failure: malloc HSM_CLIENT_KEY_INFO.");
+    }
+    else
+    {
+        memset(result, 0, sizeof(HSM_CLIENT_KEY_INFO));
+    }
+    return result;
+}
+
+void hsm_client_key_destroy(HSM_CLIENT_HANDLE handle)
+{
+    if (handle != NULL)
+    {
+        HSM_CLIENT_KEY_INFO* key_client = (HSM_CLIENT_KEY_INFO*)handle;
+        if (key_client->symmetrical_key != NULL)
+        {
+            free(key_client->symmetrical_key);
+            key_client->symmetrical_key = NULL;
+        }
+        if (key_client->registration_name != NULL)
+        {
+            free(key_client->registration_name);
+            key_client->registration_name = NULL;
+        }
+        free(key_client);
+    }
+}
+
+char* hsm_client_get_symmetric_key(HSM_CLIENT_HANDLE handle)
+{
+    char* result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_HSM_CLIENT_RIOT_07_010: [ if handle is NULL, hsm_client_riot_get_certificate shall return NULL. ] */
+        LogError("Invalid handle value specified");
+        result = NULL;
+    }
+    else
+    {
+        HSM_CLIENT_KEY_INFO* key_client = (HSM_CLIENT_KEY_INFO*)handle;
+        if (mallocAndStrcpy_s(&result, key_client->symmetrical_key) != 0)
+        {
+            LogError("Failed to allocate symmetrical_key.");
+            result = NULL;
+        }
+    }
+    return result;
+}
+
+char* hsm_client_get_registration_name(HSM_CLIENT_HANDLE handle)
+{
+    char* result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_HSM_CLIENT_RIOT_07_026: [ if handle is NULL, hsm_client_riot_get_common_name shall return NULL. ] */
+        LogError("Invalid handle value specified");
+        result = NULL;
+    }
+    else
+    {
+        HSM_CLIENT_KEY_INFO* key_client = (HSM_CLIENT_KEY_INFO*)handle;
+        if (mallocAndStrcpy_s(&result, key_client->registration_name) != 0)
+        {
+            LogError("Failure allocating registration_name");
+            result = NULL;
+        }
+    }
+    return result;
+}
+
+int hsm_client_set_key_info(HSM_CLIENT_HANDLE handle, const char* reg_name, const char* symm_key)
+{
+    int result;
+    if (handle == NULL || reg_name == NULL || symm_key == NULL)
+    {
+        LogError("Invalid parameter specified handle: %p, reg_name: %p, symm_key: %p", handle, reg_name, symm_key);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        HSM_CLIENT_KEY_INFO* key_client = (HSM_CLIENT_KEY_INFO*)handle;
+
+        char* temp_reg_name;
+        char* temp_key;
+        if (mallocAndStrcpy_s(&temp_reg_name, reg_name) != 0)
+        {
+            LogError("Failure allocating registration name");
+            result = MU_FAILURE;
+        }
+        else if (mallocAndStrcpy_s(&temp_key, symm_key) != 0)
+        {
+            LogError("Failure allocating symmetric key");
+            free(temp_reg_name);
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if (key_client->symmetrical_key != NULL)
+            {
+                free(key_client->symmetrical_key);
+            }
+            if (key_client->registration_name != NULL)
+            {
+                free(key_client->registration_name);
+            }
+            key_client->symmetrical_key = temp_key;
+            key_client->registration_name = temp_reg_name;
+            result = 0;
+        }
+    }
+    return result;
+}
+
+static const HSM_CLIENT_KEY_INTERFACE key_interface =
+{
+    hsm_client_key_create,
+    hsm_client_key_destroy,
+    hsm_client_get_symmetric_key,
+    hsm_client_get_registration_name,
+    hsm_client_set_key_info
+};
+
+const HSM_CLIENT_KEY_INTERFACE* hsm_client_key_interface(void)
+{
+    return &key_interface;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/adapters/hsm_client_key.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/adapters/hsm_client_key.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/adapters/hsm_client_key.h	(revision 453)
@@ -0,0 +1,27 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef HSM_CLIENT_KEY_H
+#define HSM_CLIENT_KEY_H
+
+#ifdef __cplusplus
+extern "C" {
+#include <cstddef>
+#else
+#include <stddef.h>
+#endif /* __cplusplus */
+
+#include "umock_c/umock_c_prod.h"
+#include "hsm_client_data.h"
+
+MOCKABLE_FUNCTION(, HSM_CLIENT_HANDLE, hsm_client_key_create);
+MOCKABLE_FUNCTION(, void, hsm_client_key_destroy, HSM_CLIENT_HANDLE, handle);
+MOCKABLE_FUNCTION(, char*, hsm_client_get_symmetric_key, HSM_CLIENT_HANDLE, handle);
+MOCKABLE_FUNCTION(, char*, hsm_client_get_registration_name, HSM_CLIENT_HANDLE, handle);
+MOCKABLE_FUNCTION(, int, hsm_client_set_key_info, HSM_CLIENT_HANDLE, handle, const char*, reg_name, const char*, symm_key);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif // HSM_CLIENT_RIOT
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/internal/iothub_auth_client.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/internal/iothub_auth_client.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/internal/iothub_auth_client.h	(revision 453)
@@ -0,0 +1,78 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef DEVICE_AUTH_H
+#define DEVICE_AUTH_H
+
+#ifdef __cplusplus
+extern "C" {
+#include <cstdint>
+#include <cstddef>
+#else
+#include <stdint.h>
+#include <stddef.h>
+#endif /* __cplusplus */
+
+#include "umock_c/umock_c_prod.h"
+#include "azure_macro_utils/macro_utils.h"
+
+typedef struct IOTHUB_SECURITY_INFO_TAG* IOTHUB_SECURITY_HANDLE;
+
+#define DEVICE_AUTH_TYPE_VALUES \
+    AUTH_TYPE_UNKNOWN,          \
+    AUTH_TYPE_SAS,              \
+    AUTH_TYPE_X509,             \
+    AUTH_TYPE_SYMM_KEY
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(DEVICE_AUTH_TYPE, DEVICE_AUTH_TYPE_VALUES);
+
+typedef struct DEVICE_AUTH_SAS_INFO_TAG
+{
+    uint64_t expiry_seconds;
+    const char* token_scope;
+    const char* key_name;
+} DEVICE_AUTH_SAS_INFO;
+
+typedef struct DEVICE_AUTH_SAS_RESULT_TAG
+{
+    const char* sas_token;
+} DEVICE_AUTH_SAS_RESULT;
+
+typedef struct DEVICE_AUTH_X509_RESULT_TAG
+{
+    const char* x509_cert;
+    const char* x509_alias_key;
+} DEVICE_AUTH_X509_RESULT;
+
+typedef struct DEVICE_AUTH_CREDENTIAL_INFO_TAG
+{
+    DEVICE_AUTH_TYPE dev_auth_type;
+    DEVICE_AUTH_SAS_INFO sas_info;
+} DEVICE_AUTH_CREDENTIAL_INFO;
+
+typedef struct CREDENTIAL_RESULT_TAG
+{
+    DEVICE_AUTH_TYPE dev_auth_type;
+    union
+    {
+        DEVICE_AUTH_SAS_RESULT sas_result;
+        DEVICE_AUTH_X509_RESULT x509_result;
+    } auth_cred_result;
+} CREDENTIAL_RESULT;
+
+
+MOCKABLE_FUNCTION(, IOTHUB_SECURITY_HANDLE, iothub_device_auth_create);
+MOCKABLE_FUNCTION(, void, iothub_device_auth_destroy, IOTHUB_SECURITY_HANDLE, handle);
+MOCKABLE_FUNCTION(, DEVICE_AUTH_TYPE, iothub_device_auth_get_type, IOTHUB_SECURITY_HANDLE, handle);
+MOCKABLE_FUNCTION(, CREDENTIAL_RESULT*, iothub_device_auth_generate_credentials, IOTHUB_SECURITY_HANDLE, handle, const DEVICE_AUTH_CREDENTIAL_INFO*, dev_auth_cred);
+
+#ifdef USE_EDGE_MODULES
+MOCKABLE_FUNCTION(, char*, iothub_device_auth_get_trust_bundle, IOTHUB_SECURITY_HANDLE, handle);
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif // DEVICE_AUTH
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/internal/prov_auth_client.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/internal/prov_auth_client.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/internal/prov_auth_client.h	(revision 453)
@@ -0,0 +1,59 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef PROV_AUTH_CLIENT_H
+#define PROV_AUTH_CLIENT_H
+
+#ifdef __cplusplus
+extern "C" {
+#include <cstdint>
+#include <cstddef>
+#else
+#include <stdint.h>
+#include <stddef.h>
+#endif /* __cplusplus */
+
+#include "umock_c/umock_c_prod.h"
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/buffer_.h"
+
+typedef struct PROV_AUTH_INFO_TAG* PROV_AUTH_HANDLE;
+
+#define PROV_AUTH_RESULT_VALUES   \
+    PROV_AUTH_SUCCESS,            \
+    PROV_AUTH_INVALID_ARG,        \
+    PROV_AUTH_ERROR,              \
+    PROV_AUTH_STATUS_UNASSIGNED,   \
+    PROV_AUTH_STATUS_ASSIGNING
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(PROV_AUTH_RESULT, PROV_AUTH_RESULT_VALUES);
+
+#define PROV_AUTH_TYPE_VALUES \
+    PROV_AUTH_TYPE_UNKNOWN,   \
+    PROV_AUTH_TYPE_TPM,       \
+    PROV_AUTH_TYPE_X509,      \
+    PROV_AUTH_TYPE_KEY
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(PROV_AUTH_TYPE, PROV_AUTH_TYPE_VALUES);
+
+MOCKABLE_FUNCTION(, PROV_AUTH_HANDLE, prov_auth_create);
+MOCKABLE_FUNCTION(, void, prov_auth_destroy, PROV_AUTH_HANDLE, handle);
+MOCKABLE_FUNCTION(, PROV_AUTH_TYPE, prov_auth_get_type, PROV_AUTH_HANDLE, handle);
+MOCKABLE_FUNCTION(, char*, prov_auth_get_registration_id, PROV_AUTH_HANDLE, handle);
+MOCKABLE_FUNCTION(, int, prov_auth_set_registration_id, PROV_AUTH_HANDLE, handle, const char*, registration_id);
+
+// TPM
+MOCKABLE_FUNCTION(, BUFFER_HANDLE, prov_auth_get_endorsement_key, PROV_AUTH_HANDLE, handle);
+MOCKABLE_FUNCTION(, BUFFER_HANDLE, prov_auth_get_storage_key, PROV_AUTH_HANDLE, handle);
+MOCKABLE_FUNCTION(, int, prov_auth_import_key, PROV_AUTH_HANDLE, handle, const unsigned char*, key, size_t, key_len);
+MOCKABLE_FUNCTION(, char*, prov_auth_construct_sas_token, PROV_AUTH_HANDLE, handle, const char*, token_scope, const char*, key_name, size_t, expiry_time);
+
+// X509
+MOCKABLE_FUNCTION(, char*, prov_auth_get_certificate, PROV_AUTH_HANDLE, handle);
+MOCKABLE_FUNCTION(, char*, prov_auth_get_alias_key, PROV_AUTH_HANDLE, handle);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif // PROV_AUTH_CLIENT_H
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/internal/prov_transport_mqtt_common.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/internal/prov_transport_mqtt_common.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/internal/prov_transport_mqtt_common.h	(revision 453)
@@ -0,0 +1,42 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef PROV_TRANSPORT_AMQP_COMMON_H
+#define PROV_TRANSPORT_AMQP_COMMON_H
+
+#ifdef __cplusplus
+extern "C" {
+#include <cstdint>
+#include <cstddef>
+#else
+#include <stdint.h>
+#include <stddef.h>
+#include <stdbool.h>
+#endif /* __cplusplus */
+
+#include "umock_c/umock_c_prod.h"
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_prov_client/prov_transport.h"
+#include "azure_prov_client/internal/prov_transport_private.h"
+#include "azure_c_shared_utility/http_proxy_io.h"
+
+typedef XIO_HANDLE(*PROV_MQTT_TRANSPORT_IO)(const char* fully_qualified_name, const HTTP_PROXY_OPTIONS* proxy_info);
+
+MOCKABLE_FUNCTION(, PROV_DEVICE_TRANSPORT_HANDLE, prov_transport_common_mqtt_create, const char*, uri, TRANSPORT_HSM_TYPE, type, const char*, scope_id, const char*, api_version, PROV_MQTT_TRANSPORT_IO, transport_io, PROV_TRANSPORT_ERROR_CALLBACK, error_cb, void*, error_ctx);
+MOCKABLE_FUNCTION(, void, prov_transport_common_mqtt_destroy, PROV_DEVICE_TRANSPORT_HANDLE, handle);
+MOCKABLE_FUNCTION(, int, prov_transport_common_mqtt_open, PROV_DEVICE_TRANSPORT_HANDLE, handle, const char*, registration_id, BUFFER_HANDLE, ek, BUFFER_HANDLE, srk, PROV_DEVICE_TRANSPORT_REGISTER_CALLBACK, data_callback, void*, user_ctx, PROV_DEVICE_TRANSPORT_STATUS_CALLBACK, status_cb, void*, status_ctx, PROV_TRANSPORT_CHALLENGE_CALLBACK, reg_challenge_cb, void*, challenge_ctx);
+MOCKABLE_FUNCTION(, int, prov_transport_common_mqtt_close, PROV_DEVICE_TRANSPORT_HANDLE, handle);
+MOCKABLE_FUNCTION(, int, prov_transport_common_mqtt_register_device, PROV_DEVICE_TRANSPORT_HANDLE, handle, PROV_TRANSPORT_JSON_PARSE, json_parse_cb, PROV_TRANSPORT_CREATE_JSON_PAYLOAD, json_create_cb, void*, json_ctx);
+MOCKABLE_FUNCTION(, int, prov_transport_common_mqtt_get_operation_status, PROV_DEVICE_TRANSPORT_HANDLE, handle);
+MOCKABLE_FUNCTION(, void, prov_transport_common_mqtt_dowork, PROV_DEVICE_TRANSPORT_HANDLE, handle);
+MOCKABLE_FUNCTION(, int, prov_transport_common_mqtt_set_trace, PROV_DEVICE_TRANSPORT_HANDLE, handle, bool, trace_on);
+MOCKABLE_FUNCTION(, int, prov_transport_common_mqtt_set_proxy, PROV_DEVICE_TRANSPORT_HANDLE, handle, const HTTP_PROXY_OPTIONS*, proxy_options);
+MOCKABLE_FUNCTION(, int, prov_transport_common_mqtt_set_trusted_cert, PROV_DEVICE_TRANSPORT_HANDLE, handle, const char*, certificate);
+MOCKABLE_FUNCTION(, int, prov_transport_common_mqtt_x509_cert, PROV_DEVICE_TRANSPORT_HANDLE, handle, const char*, certificate, const char*, private_key);
+MOCKABLE_FUNCTION(, int, prov_transport_common_mqtt_set_option, PROV_DEVICE_TRANSPORT_HANDLE, handle, const char*, option, const void*, value);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif // PROV_TRANSPORT_AMQP_COMMON_H
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/internal/prov_transport_private.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/internal/prov_transport_private.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/internal/prov_transport_private.h	(revision 453)
@@ -0,0 +1,93 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef PROV_TRANSPORT_PRIVATE_H
+#define PROV_TRANSPORT_PRIVATE_H
+
+#include "umock_c/umock_c_prod.h"
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/shared_util_options.h"
+#include "azure_c_shared_utility/buffer_.h"
+#include "azure_prov_client/prov_transport.h"
+
+#ifdef __cplusplus
+extern "C" {
+#else
+#include <stdint.h>
+#include <stdbool.h>
+#endif /* __cplusplus */
+
+    #define PROV_STATUS_CODE_TRANSIENT_ERROR    429
+
+    #define PROV_DEVICE_TRANSPORT_STATUS_VALUES     \
+        PROV_DEVICE_TRANSPORT_STATUS_CONNECTED,     \
+        PROV_DEVICE_TRANSPORT_STATUS_AUTHENTICATED, \
+        PROV_DEVICE_TRANSPORT_STATUS_UNASSIGNED,    \
+        PROV_DEVICE_TRANSPORT_STATUS_ASSIGNING,     \
+        PROV_DEVICE_TRANSPORT_STATUS_ASSIGNED,      \
+        PROV_DEVICE_TRANSPORT_STATUS_BLACKLISTED,   \
+        PROV_DEVICE_TRANSPORT_STATUS_TRANSIENT,     \
+        PROV_DEVICE_TRANSPORT_STATUS_ERROR,         \
+        PROV_DEVICE_TRANSPORT_STATUS_DISABLED
+
+    MU_DEFINE_ENUM_WITHOUT_INVALID(PROV_DEVICE_TRANSPORT_STATUS, PROV_DEVICE_TRANSPORT_STATUS_VALUES);
+
+    #define PROV_DEVICE_TRANSPORT_ERROR_VALUE   \
+        PROV_DEVICE_ERROR_KEY_FAIL,             \
+        PROV_DEVICE_ERROR_KEY_UNAUTHORIZED,     \
+        PROV_DEVICE_ERROR_MEMORY
+
+    MU_DEFINE_ENUM_WITHOUT_INVALID(PROV_DEVICE_TRANSPORT_ERROR, PROV_DEVICE_TRANSPORT_ERROR_VALUE);
+
+    typedef struct PROV_JSON_INFO_TAG
+    {
+        PROV_DEVICE_TRANSPORT_STATUS prov_status;
+        char* operation_id;
+        BUFFER_HANDLE authorization_key;
+        char* key_name;
+        char* iothub_uri;
+        char* device_id;
+    } PROV_JSON_INFO;
+
+    typedef void(*PROV_DEVICE_TRANSPORT_REGISTER_CALLBACK)(PROV_DEVICE_TRANSPORT_RESULT transport_result, BUFFER_HANDLE iothub_key, const char* assigned_hub, const char* device_id, void* user_ctx);
+    typedef void(*PROV_DEVICE_TRANSPORT_STATUS_CALLBACK)(PROV_DEVICE_TRANSPORT_STATUS transport_status, uint32_t retry_interval, void* user_ctx);
+    typedef char*(*PROV_TRANSPORT_CHALLENGE_CALLBACK)(const unsigned char* nonce, size_t nonce_len, const char* key_name, void* user_ctx);
+    typedef PROV_JSON_INFO*(*PROV_TRANSPORT_JSON_PARSE)(const char* json_document, void* user_ctx);
+    typedef char*(*PROV_TRANSPORT_CREATE_JSON_PAYLOAD)(const char* ek_value, const char* srk_value, void* user_ctx);
+    typedef void(*PROV_TRANSPORT_ERROR_CALLBACK)(PROV_DEVICE_TRANSPORT_ERROR transport_error, void* user_context);
+
+    typedef PROV_DEVICE_TRANSPORT_HANDLE(*pfprov_transport_create)(const char* uri, TRANSPORT_HSM_TYPE type, const char* scope_id, const char* api_version, PROV_TRANSPORT_ERROR_CALLBACK error_cb, void* error_ctx);
+    typedef void(*pfprov_transport_destroy)(PROV_DEVICE_TRANSPORT_HANDLE handle);
+    typedef int(*pfprov_transport_open)(PROV_DEVICE_TRANSPORT_HANDLE handle, const char* registration_id, BUFFER_HANDLE ek, BUFFER_HANDLE srk, PROV_DEVICE_TRANSPORT_REGISTER_CALLBACK data_callback, void* user_ctx, PROV_DEVICE_TRANSPORT_STATUS_CALLBACK status_cb, void* status_ctx, PROV_TRANSPORT_CHALLENGE_CALLBACK reg_challenge_cb, void* challenge_ctx);
+    typedef int(*pfprov_transport_close)(PROV_DEVICE_TRANSPORT_HANDLE handle);
+
+    typedef int(*pfprov_transport_register_device)(PROV_DEVICE_TRANSPORT_HANDLE handle, PROV_TRANSPORT_JSON_PARSE json_parse_cb, PROV_TRANSPORT_CREATE_JSON_PAYLOAD json_create_cb, void* json_ctx);
+    typedef int(*pfprov_transport_get_operation_status)(PROV_DEVICE_TRANSPORT_HANDLE handle);
+    typedef void(*pfprov_transport_dowork)(PROV_DEVICE_TRANSPORT_HANDLE handle);
+    typedef int(*pfprov_transport_set_trace)(PROV_DEVICE_TRANSPORT_HANDLE handle, bool trace_on);
+    typedef int(*pfprov_transport_set_x509_cert)(PROV_DEVICE_TRANSPORT_HANDLE handle, const char* certificate, const char* private_key);
+    typedef int(*pfprov_transport_set_trusted_cert)(PROV_DEVICE_TRANSPORT_HANDLE handle, const char* certificate);
+    typedef int(*pfprov_transport_set_proxy)(PROV_DEVICE_TRANSPORT_HANDLE handle, const HTTP_PROXY_OPTIONS* proxy_option);
+    typedef int(*pfprov_transport_set_option)(PROV_DEVICE_TRANSPORT_HANDLE handle, const char* option_name, const void* value);
+
+    struct PROV_DEVICE_TRANSPORT_PROVIDER_TAG
+    {
+        pfprov_transport_create prov_transport_create;
+        pfprov_transport_destroy prov_transport_destroy;
+        pfprov_transport_open prov_transport_open;
+        pfprov_transport_close prov_transport_close;
+        pfprov_transport_register_device prov_transport_register;
+        pfprov_transport_get_operation_status prov_transport_get_op_status;
+        pfprov_transport_dowork prov_transport_dowork;
+        pfprov_transport_set_trace prov_transport_set_trace;
+        pfprov_transport_set_x509_cert prov_transport_x509_cert;
+        pfprov_transport_set_trusted_cert prov_transport_trusted_cert;
+        pfprov_transport_set_proxy prov_transport_set_proxy;
+        pfprov_transport_set_option prov_transport_set_option;
+    };
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif // PROV_TRANSPORT_PRIVATE_H
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/iothub_security_factory.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/iothub_security_factory.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/iothub_security_factory.h	(revision 453)
@@ -0,0 +1,43 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef IOTHUB_SECURITY_FACTORY_H
+#define IOTHUB_SECURITY_FACTORY_H
+
+#ifdef __cplusplus
+#include <cstddef>
+extern "C" {
+#else
+#include <stddef.h>
+#endif /* __cplusplus */
+
+#include "umock_c/umock_c_prod.h"
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/buffer_.h"
+
+#define IOTHUB_SECURITY_TYPE_VALUES \
+    IOTHUB_SECURITY_TYPE_UNKNOWN,   \
+    IOTHUB_SECURITY_TYPE_SAS,       \
+    IOTHUB_SECURITY_TYPE_X509,      \
+    IOTHUB_SECURITY_TYPE_HTTP_EDGE, \
+    IOTHUB_SECURITY_TYPE_SYMMETRIC_KEY
+
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(IOTHUB_SECURITY_TYPE, IOTHUB_SECURITY_TYPE_VALUES);
+
+MOCKABLE_FUNCTION(, int, iothub_security_init, IOTHUB_SECURITY_TYPE, sec_type);
+MOCKABLE_FUNCTION(, void, iothub_security_deinit);
+
+MOCKABLE_FUNCTION(, const void*, iothub_security_interface);
+MOCKABLE_FUNCTION(, IOTHUB_SECURITY_TYPE, iothub_security_type);
+
+// Symmetric key information
+MOCKABLE_FUNCTION(, int, iothub_security_set_symmetric_key_info, const char*, registration_name, const char*, symmetric_key);
+MOCKABLE_FUNCTION(, const char*, iothub_security_get_symmetric_key);
+MOCKABLE_FUNCTION(, const char*, iothub_security_get_symm_registration_name);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif // IOTHUB_SECURITY_FACTORY_H
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_client_const.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_client_const.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_client_const.h	(revision 453)
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef PROV_CLIENT_CONST_H
+#define PROV_CLIENT_CONST_H
+
+#define PROV_DEVICE_CLIENT_VERSION "1.3.8"
+#define PROV_GET_THROTTLE_TIME      1
+#define MAX_PROV_GET_THROTTLE_TIME  5*60
+
+static const char* const PROV_ASSIGNED_STATUS = "assigned";
+static const char* const PROV_ASSIGNING_STATUS = "assigning";
+static const char* const PROV_UNASSIGNED_STATUS = "unassigned";
+static const char* const PROV_DISABLE_STATUS = "disabled";
+
+static const char* const RETRY_AFTER_KEY_VALUE = "retry-after";
+
+static const char* const PROV_API_VERSION = "2019-03-31";
+
+#endif // PROV_CLIENT_CONST_H
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_device_client.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_device_client.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_device_client.h	(revision 453)
@@ -0,0 +1,64 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/** @file prov_device_client.h
+*    @brief Extends the Prov_Device_LL module with additional features.
+*
+*    @details Prov_Device is a module that extends the Prov_Device_LL
+*             module with 2 features:
+*                - scheduling the work for the IoTHubCLient from a
+*                  thread, so that the user does not need to create their
+*                  own thread
+*                - thread-safe APIs
+*/
+
+#ifndef PROV_DEVICE_CLIENT_H
+#define PROV_DEVICE_CLIENT_H
+
+#ifndef PROV_DEVICE_CLIENT_INSTANCE_TYPE
+typedef struct PROV_DEVICE_INSTANCE_TAG* PROV_DEVICE_HANDLE;
+#define PROV_DEVICE_CLIENT_INSTANCE_TYPE
+#endif // PROV_DEVICE_CLIENT_INSTANCE_TYPE
+
+#include <stddef.h>
+#include <stdint.h>
+#include "prov_device_ll_client.h"
+#include "umock_c/umock_c_prod.h"
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_prov_client/prov_transport.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+MOCKABLE_FUNCTION(, PROV_DEVICE_HANDLE, Prov_Device_Create, const char*, uri, const char*, scope_id, PROV_DEVICE_TRANSPORT_PROVIDER_FUNCTION, protocol);
+MOCKABLE_FUNCTION(, void, Prov_Device_Destroy, PROV_DEVICE_HANDLE, prov_device_handle);
+MOCKABLE_FUNCTION(, PROV_DEVICE_RESULT, Prov_Device_Register_Device, PROV_DEVICE_HANDLE, prov_device_handle, PROV_DEVICE_CLIENT_REGISTER_DEVICE_CALLBACK, register_callback, void*, user_context, PROV_DEVICE_CLIENT_REGISTER_STATUS_CALLBACK, register_status_callback, void*, status_user_context);
+MOCKABLE_FUNCTION(, PROV_DEVICE_RESULT, Prov_Device_SetOption, PROV_DEVICE_HANDLE, prov_device_handle, const char*, optionName, const void*, value);
+MOCKABLE_FUNCTION(, const char*, Prov_Device_GetVersionString);
+
+/**
+* @brief    Sets the Provisioning Data that is sent to the Provisioning service
+*
+* @param    handle          The handle created by a call to the create function.
+* @param    json            The json payload field that is sent to the service.  Setting json to NULL will unset the value previously set
+*
+* @return PROV_DEVICE_RESULT_OK upon success or an error code upon failure
+*/
+MOCKABLE_FUNCTION(, PROV_DEVICE_RESULT, Prov_Device_Set_Provisioning_Payload, PROV_DEVICE_HANDLE, handle, const char*, json);
+
+/**
+* @brief    Retrieves the Provisioning Data that is sent from the Provisioning service
+*
+* @param    handle          The handle created by a call to the create function.
+*
+* @return The data that was specified by the service
+*/
+MOCKABLE_FUNCTION(, const char*, Prov_Device_Get_Provisioning_Payload, PROV_DEVICE_HANDLE, handle);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif // PROV_DEVICE_CLIENT_H
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_device_ll_client.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_device_ll_client.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_device_ll_client.h	(revision 453)
@@ -0,0 +1,137 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef PROV_DEVICE_LL_CLIENT_H
+#define PROV_DEVICE_LL_CLIENT_H
+
+#include "umock_c/umock_c_prod.h"
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_prov_client/prov_transport.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct PROV_INSTANCE_INFO_TAG* PROV_DEVICE_LL_HANDLE;
+
+#define PROV_DEVICE_RESULT_VALUE            \
+    PROV_DEVICE_RESULT_OK,                  \
+    PROV_DEVICE_RESULT_INVALID_ARG,         \
+    PROV_DEVICE_RESULT_SUCCESS,             \
+    PROV_DEVICE_RESULT_MEMORY,              \
+    PROV_DEVICE_RESULT_PARSING,             \
+    PROV_DEVICE_RESULT_TRANSPORT,           \
+    PROV_DEVICE_RESULT_INVALID_STATE,       \
+    PROV_DEVICE_RESULT_DEV_AUTH_ERROR,      \
+    PROV_DEVICE_RESULT_TIMEOUT,             \
+    PROV_DEVICE_RESULT_KEY_ERROR,           \
+    PROV_DEVICE_RESULT_ERROR,               \
+    PROV_DEVICE_RESULT_HUB_NOT_SPECIFIED,   \
+    PROV_DEVICE_RESULT_UNAUTHORIZED,        \
+    PROV_DEVICE_RESULT_DISABLED
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(PROV_DEVICE_RESULT, PROV_DEVICE_RESULT_VALUE);
+
+#define PROV_DEVICE_REG_STATUS_VALUES      \
+    PROV_DEVICE_REG_STATUS_CONNECTED,      \
+    PROV_DEVICE_REG_STATUS_REGISTERING,    \
+    PROV_DEVICE_REG_STATUS_ASSIGNING,      \
+    PROV_DEVICE_REG_STATUS_ASSIGNED,       \
+    PROV_DEVICE_REG_STATUS_ERROR,          \
+    PROV_DEVICE_REG_HUB_NOT_SPECIFIED
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(PROV_DEVICE_REG_STATUS, PROV_DEVICE_REG_STATUS_VALUES);
+
+static const char* const PROV_REGISTRATION_ID = "registration_id";
+static const char* const PROV_OPTION_LOG_TRACE = "logtrace";
+static const char* const PROV_OPTION_TIMEOUT = "provisioning_timeout";
+
+typedef void(*PROV_DEVICE_CLIENT_REGISTER_DEVICE_CALLBACK)(PROV_DEVICE_RESULT register_result, const char* iothub_uri, const char* device_id, void* user_context);
+typedef void(*PROV_DEVICE_CLIENT_REGISTER_STATUS_CALLBACK)(PROV_DEVICE_REG_STATUS reg_status, void* user_context);
+
+typedef const PROV_DEVICE_TRANSPORT_PROVIDER*(*PROV_DEVICE_TRANSPORT_PROVIDER_FUNCTION)(void);
+
+/**
+* @brief    Creates a Provisioning Client for communications with the Device Provisioning Client Service
+*
+* @param    uri         The URI of the Device Provisioning Service
+* @param    scope_id    The customer specific Id Scope
+* @param    protocol    Function pointer for protocol implementation
+*
+* @return   A non-NULL PROV_DEVICE_LL_HANDLE value that is used when invoking other functions
+*           and NULL on Failure
+*/
+MOCKABLE_FUNCTION(, PROV_DEVICE_LL_HANDLE, Prov_Device_LL_Create, const char*, uri, const char*, scope_id, PROV_DEVICE_TRANSPORT_PROVIDER_FUNCTION, protocol);
+
+/**
+* @brief    Disposes of resources allocated by the provisioning Client.
+*
+* @param    handle  The handle created by a call to the create function
+*
+*/
+MOCKABLE_FUNCTION(, void, Prov_Device_LL_Destroy, PROV_DEVICE_LL_HANDLE, handle);
+
+/**
+* @brief    Asynchronous call initiates the registration of a device.
+*
+* @param    handle              The handle created by a call to the create function.
+* @param    register_callback   The callback that gets called on registration or if an error is encountered
+* @param    user_context        User specified context that will be provided to the callback
+* @param    reg_status_cb       An optional registration status callback used to inform the caller of registration status
+* @param    status_user_ctext   User specified context that will be provided to the registration status callback
+*
+* @return PROV_DEVICE_RESULT_OK upon success or an error code upon failure
+*/
+MOCKABLE_FUNCTION(, PROV_DEVICE_RESULT, Prov_Device_LL_Register_Device, PROV_DEVICE_LL_HANDLE, handle, PROV_DEVICE_CLIENT_REGISTER_DEVICE_CALLBACK, register_callback, void*, user_context, PROV_DEVICE_CLIENT_REGISTER_STATUS_CALLBACK, reg_status_cb, void*, status_user_ctext);
+
+/**
+* @brief    Api to be called by user when work (registering device) can be done
+*
+* @param    handle  The handle created by a call to the create function.
+*
+*/
+MOCKABLE_FUNCTION(, void, Prov_Device_LL_DoWork, PROV_DEVICE_LL_HANDLE, handle);
+
+/**
+* @brief    API sets a runtime option identified by parameter optionName to a value pointed to by value
+*
+* @param    handle          The handle created by a call to the create function.
+* @param    optionName      The name of the option to be set
+* @param    value           A pointer to the value of the option to be set
+*
+* @return PROV_DEVICE_RESULT_OK upon success or an error code upon failure
+*/
+MOCKABLE_FUNCTION(, PROV_DEVICE_RESULT, Prov_Device_LL_SetOption, PROV_DEVICE_LL_HANDLE, handle, const char*, optionName, const void*, value);
+
+/**
+* @brief    API to get the version of the provisioning client
+*
+* @return The version number of the provisioning client
+*/
+MOCKABLE_FUNCTION(, const char*, Prov_Device_LL_GetVersionString);
+
+
+/**
+* @brief    Sets the Provisioning Data that is sent to the Provisioning service
+*
+* @param    handle          The handle created by a call to the create function.
+* @param    json            The data field that is sent to the service.  Setting json to NULL will unset the value previously set
+*
+* @return PROV_DEVICE_RESULT_OK upon success or an error code upon failure
+*/
+MOCKABLE_FUNCTION(, PROV_DEVICE_RESULT, Prov_Device_LL_Set_Provisioning_Payload, PROV_DEVICE_LL_HANDLE, handle, const char*, json);
+
+/**
+* @brief    Retrieves the Provisioning Data that is sent from the Provisioning service
+*
+* @param    handle          The handle created by a call to the create function.
+*
+* @return The data that was specified by the service
+*/
+MOCKABLE_FUNCTION(, const char*, Prov_Device_LL_Get_Provisioning_Payload, PROV_DEVICE_LL_HANDLE, handle);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif // PROV_DEVICE_LL_CLIENT_H
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_edge_trusted_certificates.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_edge_trusted_certificates.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_edge_trusted_certificates.h	(revision 453)
@@ -0,0 +1,21 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef PROV_EDGE_TRUSTED_CERTIFICATES_H
+#define PROV_EDGE_TRUSTED_CERTIFICATES_H
+
+#ifdef __cplusplus
+extern "C" {
+#else
+#endif /* __cplusplus */
+
+
+MOCKABLE_FUNCTION(, const char*, prov_get_edge_trusted_certificates);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif // PROV_EDGE_TRUSTED_CERTIFICATES_H
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_security_factory.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_security_factory.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_security_factory.h	(revision 453)
@@ -0,0 +1,40 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef PROV_SECURITY_FACTORY_H
+#define PROV_SECURITY_FACTORY_H
+
+#ifdef __cplusplus
+#include <cstddef>
+extern "C" {
+#else
+#include <stddef.h>
+#endif /* __cplusplus */
+
+#include "umock_c/umock_c_prod.h"
+#include "azure_macro_utils/macro_utils.h"
+
+#define SECURE_DEVICE_TYPE_VALUES \
+    SECURE_DEVICE_TYPE_UNKNOWN,   \
+    SECURE_DEVICE_TYPE_TPM,       \
+    SECURE_DEVICE_TYPE_X509,      \
+    SECURE_DEVICE_TYPE_HTTP_EDGE, \
+    SECURE_DEVICE_TYPE_SYMMETRIC_KEY
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(SECURE_DEVICE_TYPE, SECURE_DEVICE_TYPE_VALUES);
+
+
+MOCKABLE_FUNCTION(, int, prov_dev_security_init, SECURE_DEVICE_TYPE, hsm_type);
+MOCKABLE_FUNCTION(, void, prov_dev_security_deinit);
+MOCKABLE_FUNCTION(, SECURE_DEVICE_TYPE, prov_dev_security_get_type);
+
+// Symmetric key information
+MOCKABLE_FUNCTION(, int, prov_dev_set_symmetric_key_info, const char*, registration_name, const char*, symmetric_key);
+MOCKABLE_FUNCTION(, const char*, prov_dev_get_symmetric_key);
+MOCKABLE_FUNCTION(, const char*, prov_dev_get_symm_registration_name);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif // PROV_SECURITY_FACTORY_H
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_transport.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_transport.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_transport.h	(revision 453)
@@ -0,0 +1,78 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef PROV_TRANSPORT_H
+#define PROV_TRANSPORT_H
+
+#include "umock_c/umock_c_prod.h"
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/shared_util_options.h"
+#include "azure_c_shared_utility/buffer_.h"
+#include "azure_prov_client/prov_client_const.h"
+
+#ifdef __cplusplus
+extern "C" {
+#include <cstdint>
+#include <cstdlib>
+#else
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#endif /* __cplusplus */
+
+    struct PROV_DEVICE_TRANSPORT_PROVIDER_TAG;
+    typedef struct PROV_DEVICE_TRANSPORT_PROVIDER_TAG PROV_DEVICE_TRANSPORT_PROVIDER;
+
+    typedef void* PROV_DEVICE_TRANSPORT_HANDLE;
+
+#define TRANSPORT_HSM_TYPE_VALUES   \
+    TRANSPORT_HSM_TYPE_TPM,         \
+    TRANSPORT_HSM_TYPE_X509,        \
+    TRANSPORT_HSM_TYPE_SYMM_KEY
+
+    MU_DEFINE_ENUM_WITHOUT_INVALID(TRANSPORT_HSM_TYPE, TRANSPORT_HSM_TYPE_VALUES);
+
+#define PROV_DEVICE_TRANSPORT_RESULT_VALUES     \
+    PROV_DEVICE_TRANSPORT_RESULT_OK,            \
+    PROV_DEVICE_TRANSPORT_RESULT_UNAUTHORIZED,  \
+    PROV_DEVICE_TRANSPORT_RESULT_ERROR
+
+    MU_DEFINE_ENUM_WITHOUT_INVALID(PROV_DEVICE_TRANSPORT_RESULT, PROV_DEVICE_TRANSPORT_RESULT_VALUES);
+
+    // Snippit from RFC 7231 https://tools.ietf.org/html/rfc7231
+    // The value of this field can be either an HTTP - date or a number of
+    // seconds to delay after the response is received.
+
+    // Retry - After = HTTP - date / delay - seconds
+
+    // A delay - seconds value is a non - negative decimal integer, representing
+    // time in seconds.
+
+    // delay - seconds = 1 * DIGIT
+    // Two examples of its use are
+
+    // Retry-After: Fri, 31 Dec 1999 23 : 59 : 59 GMT
+    // Retry-After : 120
+    static inline uint32_t parse_retry_after_value(const char* retry_after)
+    {
+        uint32_t result = PROV_GET_THROTTLE_TIME;
+        if (retry_after != NULL)
+        {
+            // Is the retry after a number
+            if (retry_after[0] >= 0x30 && retry_after[0] <= 0x39)
+            {
+                result = atol(retry_after);
+                if (result < PROV_GET_THROTTLE_TIME || result > MAX_PROV_GET_THROTTLE_TIME)
+                {
+                    result = PROV_GET_THROTTLE_TIME;
+                }
+            }
+            // Will need to parse the retry after for date information
+        }
+        return result;
+    }
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif // PROV_TRANSPORT
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_transport_http_client.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_transport_http_client.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_transport_http_client.h	(revision 453)
@@ -0,0 +1,26 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef PROV_TRANSPORT_HTTP_CLIENT_H
+#define PROV_TRANSPORT_HTTP_CLIENT_H
+
+#ifdef __cplusplus
+extern "C" {
+#include <cstdint>
+#include <cstddef>
+#else
+#include <stdint.h>
+#include <stddef.h>
+#endif /* __cplusplus */
+
+#include "umock_c/umock_c_prod.h"
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_prov_client/prov_transport.h"
+
+MOCKABLE_FUNCTION(, const PROV_DEVICE_TRANSPORT_PROVIDER*, Prov_Device_HTTP_Protocol);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif // PROV_TRANSPORT_HTTP_CLIENT_H
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_transport_mqtt_client.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_transport_mqtt_client.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_transport_mqtt_client.h	(revision 453)
@@ -0,0 +1,26 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef PROV_TRANSPORT_MQTT_CLIENT_H
+#define PROV_TRANSPORT_MQTT_CLIENT_H
+
+#ifdef __cplusplus
+extern "C" {
+#include <cstdint>
+#include <cstddef>
+#else
+#include <stdint.h>
+#include <stddef.h>
+#endif /* __cplusplus */
+
+#include "umock_c/umock_c_prod.h"
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_prov_client/prov_transport.h"
+
+MOCKABLE_FUNCTION(, const PROV_DEVICE_TRANSPORT_PROVIDER*, Prov_Device_MQTT_Protocol);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif // PROV_TRANSPORT_MQTT_CLIENT_H
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_transport_mqtt_ws_client.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_transport_mqtt_ws_client.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_transport_mqtt_ws_client.h	(revision 453)
@@ -0,0 +1,26 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef PROV_TRANSPORT_MQTT_WS_CLIENT_H
+#define PROV_TRANSPORT_MQTT_WS_CLIENT_H
+
+#ifdef __cplusplus
+extern "C" {
+#include <cstdint>
+#include <cstddef>
+#else
+#include <stdint.h>
+#include <stddef.h>
+#endif /* __cplusplus */
+
+#include "umock_c/umock_c_prod.h"
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_prov_client/prov_transport.h"
+
+MOCKABLE_FUNCTION(, const PROV_DEVICE_TRANSPORT_PROVIDER*, Prov_Device_MQTT_WS_Protocol);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif // PROV_TRANSPORT_MQTT_WS_CLIENT_H
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/iothub_auth_client.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/iothub_auth_client.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/iothub_auth_client.c	(revision 453)
@@ -0,0 +1,484 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "umock_c/umock_c_prod.h"
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/sastoken.h"
+#include "azure_c_shared_utility/azure_base64.h"
+#include "azure_c_shared_utility/sha.h"
+#include "azure_c_shared_utility/urlencode.h"
+#include "azure_c_shared_utility/strings.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/hmacsha256.h"
+
+#include "azure_prov_client/internal/iothub_auth_client.h"
+#include "azure_prov_client/iothub_security_factory.h"
+#include "hsm_client_data.h"
+
+typedef struct IOTHUB_SECURITY_INFO_TAG
+{
+    DEVICE_AUTH_TYPE cred_type;
+
+    HSM_CLIENT_HANDLE hsm_client_handle;
+
+    HSM_CLIENT_CREATE hsm_client_create;
+    HSM_CLIENT_DESTROY hsm_client_destroy;
+
+    HSM_CLIENT_SIGN_WITH_IDENTITY hsm_client_sign_data;
+
+    HSM_CLIENT_GET_CERTIFICATE hsm_client_get_cert;
+    HSM_CLIENT_GET_ALIAS_KEY hsm_client_get_alias_key;
+
+    HSM_CLIENT_GET_TRUST_BUNDLE hsm_client_get_trust_bundle;
+    HSM_CLIENT_GET_SYMMETRICAL_KEY hsm_client_get_symm_key;
+    HSM_CLIENT_SET_SYMMETRICAL_KEY_INFO hsm_client_set_symm_key_info;
+
+    char* sas_token;
+    char* x509_certificate;
+    char* x509_alias_key;
+    bool base64_encode_signature;
+    bool urlencode_token_scope;
+} IOTHUB_SECURITY_INFO;
+
+#define HMAC_LENGTH                 32
+static const char* const SAS_TOKEN_FORMAT = "SharedAccessSignature sr=%s&sig=%s&se=%s%s%s";
+static const char* const SKN_SECTION_FORMAT = "&skn=";
+
+static int sign_sas_data(IOTHUB_SECURITY_INFO* security_info, const char* payload, unsigned char** output, size_t* len)
+{
+    int result;
+    size_t payload_len = strlen(payload);
+    if (security_info->cred_type == AUTH_TYPE_SAS)
+    {
+        if (security_info->hsm_client_sign_data(security_info->hsm_client_handle, (const unsigned char*)payload, strlen(payload), output, len) != 0)
+        {
+            LogError("Failed signing data");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            result = 0;
+        }
+    }
+    else
+    {
+        char* symmetrical_key = security_info->hsm_client_get_symm_key(security_info->hsm_client_handle);
+        if (symmetrical_key == NULL)
+        {
+            LogError("Failed getting asymmetrical key");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            BUFFER_HANDLE decoded_key;
+            BUFFER_HANDLE output_hash;
+
+            if ((decoded_key = Azure_Base64_Decode(symmetrical_key)) == NULL)
+            {
+                LogError("Failed decoding symmetrical key");
+                result = MU_FAILURE;
+            }
+            else if ((output_hash = BUFFER_new()) == NULL)
+            {
+                LogError("Failed allocating output hash buffer");
+                BUFFER_delete(decoded_key);
+                result = MU_FAILURE;
+            }
+            else
+            {
+                if (HMACSHA256_ComputeHash(BUFFER_u_char(decoded_key), BUFFER_length(decoded_key), (const unsigned char*)payload, payload_len, output_hash) != HMACSHA256_OK)
+                {
+                    LogError("Failed computing HMAC Hash");
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    *len = BUFFER_length(output_hash);
+                    if ((*output = malloc(*len)) == NULL)
+                    {
+                        LogError("Failed allocating output buffer");
+                        result = MU_FAILURE;
+                    }
+                    else
+                    {
+                        const unsigned char* output_data = BUFFER_u_char(output_hash);
+                        memcpy(*output, output_data, *len);
+                        result = 0;
+                    }
+                }
+                BUFFER_delete(decoded_key);
+                BUFFER_delete(output_hash);
+            }
+            free(symmetrical_key);
+        }
+    }
+    return result;
+}
+
+IOTHUB_SECURITY_HANDLE iothub_device_auth_create()
+{
+    IOTHUB_SECURITY_INFO* result;
+
+    IOTHUB_SECURITY_TYPE iothub_security_t = iothub_security_type();
+
+    if ((result = (IOTHUB_SECURITY_INFO*)malloc(sizeof(IOTHUB_SECURITY_INFO))) == NULL)
+    {
+        /* Codes_IOTHUB_DEV_AUTH_07_001: [ if any failure is encountered iothub_device_auth_create shall return NULL. ] */
+        LogError("Failed allocating IOTHUB_SECURITY_INFO.");
+    }
+    else
+    {
+        memset(result, 0, sizeof(IOTHUB_SECURITY_INFO) );
+#if defined(HSM_TYPE_SAS_TOKEN)  || defined(HSM_AUTH_TYPE_CUSTOM)
+        if (iothub_security_t == IOTHUB_SECURITY_TYPE_SAS)
+        {
+            result->cred_type = AUTH_TYPE_SAS;
+            result->base64_encode_signature = true;
+            result->urlencode_token_scope = false;
+            const HSM_CLIENT_TPM_INTERFACE* tpm_interface = hsm_client_tpm_interface();
+            if ((tpm_interface == NULL) ||
+                ((result->hsm_client_create = tpm_interface->hsm_client_tpm_create) == NULL) ||
+                ((result->hsm_client_destroy = tpm_interface->hsm_client_tpm_destroy) == NULL) ||
+                ((result->hsm_client_sign_data = tpm_interface->hsm_client_sign_with_identity) == NULL)
+                )
+            {
+                /* Codes_IOTHUB_DEV_AUTH_07_034: [ if any of the iothub_security_interface function are NULL iothub_device_auth_create shall return NULL. ] */
+                LogError("Invalid secure device interface");
+                free(result);
+                result = NULL;
+            }
+        }
+#endif
+#if defined(HSM_TYPE_X509) || defined(HSM_AUTH_TYPE_CUSTOM)
+        if (result != NULL && iothub_security_t == IOTHUB_SECURITY_TYPE_X509)
+        {
+            result->cred_type = AUTH_TYPE_X509;
+            result->base64_encode_signature = true;
+            result->urlencode_token_scope = false;
+            const HSM_CLIENT_X509_INTERFACE* x509_interface = hsm_client_x509_interface();
+            if ((x509_interface == NULL) ||
+                ((result->hsm_client_create = x509_interface->hsm_client_x509_create) == NULL) ||
+                ((result->hsm_client_destroy = x509_interface->hsm_client_x509_destroy) == NULL) ||
+                ((result->hsm_client_get_cert = x509_interface->hsm_client_get_cert) == NULL) ||
+                ((result->hsm_client_get_alias_key = x509_interface->hsm_client_get_key) == NULL)
+                )
+            {
+                /* Codes_IOTHUB_DEV_AUTH_07_034: [ if any of the iothub_security_interface function are NULL iothub_device_auth_create shall return NULL. ] */
+                LogError("Invalid handle parameter: DEVICE_AUTH_CREATION_INFO is NULL");
+                free(result);
+                result = NULL;
+            }
+        }
+#endif
+#if defined(HSM_TYPE_SYMM_KEY) || defined(HSM_AUTH_TYPE_CUSTOM)
+        if (result != NULL && iothub_security_t == IOTHUB_SECURITY_TYPE_SYMMETRIC_KEY)
+        {
+            result->cred_type = AUTH_TYPE_SYMM_KEY;
+            result->base64_encode_signature = true;
+            result->urlencode_token_scope = false;
+            const HSM_CLIENT_KEY_INTERFACE* key_interface = hsm_client_key_interface();
+            if ((key_interface == NULL) ||
+                ((result->hsm_client_create = key_interface->hsm_client_key_create) == NULL) ||
+                ((result->hsm_client_destroy = key_interface->hsm_client_key_destroy) == NULL) ||
+                ((result->hsm_client_get_symm_key = key_interface->hsm_client_get_symm_key) == NULL) ||
+                ((result->hsm_client_set_symm_key_info = key_interface->hsm_client_set_symm_key_info) == NULL)
+                )
+            {
+                LogError("Invalid x509 secure device interface was specified");
+                free(result);
+                result = NULL;
+            }
+        }
+#endif
+#ifdef HSM_TYPE_HTTP_EDGE
+        if (result != NULL && iothub_security_t == IOTHUB_SECURITY_TYPE_HTTP_EDGE)
+        {
+            result->cred_type = AUTH_TYPE_SAS;
+            // Because HTTP_edge operates over HTTP, the server has already base64 encoded signature its returning to us.
+            result->base64_encode_signature = false;
+            result->urlencode_token_scope = true;
+            const HSM_CLIENT_HTTP_EDGE_INTERFACE* http_edge_interface = hsm_client_http_edge_interface();
+            if ((http_edge_interface == NULL) ||
+                ((result->hsm_client_create = http_edge_interface->hsm_client_http_edge_create) == NULL) ||
+                ((result->hsm_client_destroy = http_edge_interface->hsm_client_http_edge_destroy) == NULL) ||
+                ((result->hsm_client_sign_data = http_edge_interface->hsm_client_sign_with_identity) == NULL) ||
+                ((result->hsm_client_get_trust_bundle = http_edge_interface->hsm_client_get_trust_bundle) == NULL))
+            {
+                LogError("Invalid secure device interface");
+                free(result);
+                result = NULL;
+            }
+        }
+#endif
+        if (result == NULL)
+        {
+            LogError("Error allocating result or else unsupported security type %d", iothub_security_t);
+        }
+        else if (result->hsm_client_create == NULL)
+        {
+            LogError("hsm_client_create is not a valid address");
+            free(result);
+            result = NULL;
+        }
+        else
+        {
+            /* Codes_IOTHUB_DEV_AUTH_07_025: [ iothub_device_auth_create shall call the concrete_iothub_device_auth_create function associated with the interface_desc. ] */
+            /* Codes_IOTHUB_DEV_AUTH_07_026: [ if concrete_iothub_device_auth_create fails iothub_device_auth_create shall return NULL. ] */
+            if ((result->hsm_client_handle = result->hsm_client_create()) == NULL)
+            {
+                /* Codes_IOTHUB_DEV_AUTH_07_002: [ iothub_device_auth_create shall allocate the IOTHUB_SECURITY_INFO and shall fail if the allocation fails. ]*/
+                LogError("failed create device auth module.");
+                free(result);
+                result = NULL;
+            }
+            else if (result->cred_type == AUTH_TYPE_SYMM_KEY && result->hsm_client_set_symm_key_info(result->hsm_client_handle, iothub_security_get_symm_registration_name(), iothub_security_get_symmetric_key()) != 0)
+            {
+                LogError("Invalid x509 secure device interface was specified");
+                result->hsm_client_destroy(result->hsm_client_handle);
+                free(result);
+                result = NULL;
+            }
+        }
+    }
+    /* Codes_IOTHUB_DEV_AUTH_07_003: [ If the function succeeds iothub_device_auth_create shall return a IOTHUB_SECURITY_HANDLE. ] */
+    return result;
+}
+
+void iothub_device_auth_destroy(IOTHUB_SECURITY_HANDLE handle)
+{
+    /* Codes_IOTHUB_DEV_AUTH_07_006: [ If the argument handle is NULL, iothub_device_auth_destroy shall do nothing ] */
+    if (handle != NULL)
+    {
+        /* Codes_IOTHUB_DEV_AUTH_07_005: [ iothub_device_auth_destroy shall call the concrete_iothub_device_auth_destroy function associated with the XDA_INTERFACE_DESCRIPTION. ] */
+        free(handle->x509_certificate);
+        free(handle->x509_alias_key);
+        free(handle->sas_token);
+        handle->hsm_client_destroy(handle->hsm_client_handle);
+        /* Codes_IOTHUB_DEV_AUTH_07_004: [ iothub_device_auth_destroy shall free all resources associated with the IOTHUB_SECURITY_HANDLE handle ] */
+        free(handle);
+    }
+}
+
+DEVICE_AUTH_TYPE iothub_device_auth_get_type(IOTHUB_SECURITY_HANDLE handle)
+{
+    DEVICE_AUTH_TYPE result;
+    /* Codes_IOTHUB_DEV_AUTH_07_007: [ If the argument handle is NULL, iothub_device_auth_get_auth_type shall return AUTH_TYPE_UNKNOWN. ] */
+    if (handle == NULL)
+    {
+        LogError("Invalid handle specified");
+        result = AUTH_TYPE_UNKNOWN;
+    }
+    else
+    {
+        /* Codes_IOTHUB_DEV_AUTH_07_008: [ iothub_device_auth_get_auth_type shall call concrete_iothub_device_auth_type function associated with the XDA_INTERFACE_DESCRIPTION. ] */
+        /* Codes_IOTHUB_DEV_AUTH_07_009: [ iothub_device_auth_get_auth_type shall return the DEVICE_AUTH_TYPE returned by the concrete_iothub_device_auth_type function. ] */
+        result = handle->cred_type;
+    }
+    return result;
+}
+
+CREDENTIAL_RESULT* iothub_device_auth_generate_credentials(IOTHUB_SECURITY_HANDLE handle, const DEVICE_AUTH_CREDENTIAL_INFO* dev_auth_cred)
+{
+    CREDENTIAL_RESULT* result;
+    /* Codes_IOTHUB_DEV_AUTH_07_010: [ If the argument handle or dev_auth_cred is NULL, iothub_device_auth_generate_credentials shall return a NULL value. ] */
+    if (handle == NULL)
+    {
+        LogError("Invalid handle parameter: handle");
+        result = NULL;
+    }
+    else
+    {
+        if (handle->cred_type == AUTH_TYPE_SAS || handle->cred_type == AUTH_TYPE_SYMM_KEY)
+        {
+            char expire_token[64] = { 0 };
+            if (handle->sas_token != NULL)
+            {
+                free(handle->sas_token);
+                handle->sas_token = NULL;
+            }
+            if (dev_auth_cred == NULL || dev_auth_cred->sas_info.token_scope == NULL)
+            {
+                LogError("Invalid handle parameter: dev_auth_cred");
+                result = NULL;
+            }
+            else if (dev_auth_cred->dev_auth_type != AUTH_TYPE_SAS && dev_auth_cred->dev_auth_type != AUTH_TYPE_SYMM_KEY)
+            {
+                LogError("Invalid handle parameter: dev_auth_cred.dev_auth_type");
+                result = NULL;
+            }
+            else if (size_tToString(expire_token, sizeof(expire_token), (size_t)dev_auth_cred->sas_info.expiry_seconds) != 0)
+            {
+                result = NULL;
+                LogError("Failure creating expire token");
+            }
+            else
+            {
+                size_t len = strlen(dev_auth_cred->sas_info.token_scope)+strlen(expire_token)+3;
+                char* payload = malloc(len+1);
+                if (payload == NULL)
+                {
+                    result = NULL;
+                    LogError("Failure allocating payload.");
+                }
+                else
+                {
+                    unsigned char* data_value;
+                    size_t data_len;
+
+                    size_t total_len = sprintf(payload, "%s\n%s", dev_auth_cred->sas_info.token_scope, expire_token);
+                    if (total_len <= 0)
+                    {
+                        result = NULL;
+                        LogError("Failure constructing hash payload.");
+                    }
+                    /* Codes_IOTHUB_DEV_AUTH_07_035: [ For tpm type iothub_device_auth_generate_credentials shall call the concrete_dev_auth_sign_data function to hash the data. ] */
+                    else if (sign_sas_data(handle, payload, &data_value, &data_len) == 0)
+                    {
+                        STRING_HANDLE urlEncodedSignature = NULL;
+                        STRING_HANDLE signature = NULL;
+                        if (handle->base64_encode_signature == true)
+                        {
+                            signature = Azure_Base64_Encode_Bytes(data_value, data_len);
+                        }
+                        else
+                        {
+                            signature = STRING_construct((const char*)data_value);
+                        }
+
+                        if (signature == NULL)
+                        {
+                            result = NULL;
+                            LogError("Failure constructing encoding.");
+                        }
+                        else if ((urlEncodedSignature = URL_Encode(signature)) == NULL)
+                        {
+                            result = NULL;
+                            LogError("Failure constructing url Signature.");
+                            STRING_delete(signature);
+                        }
+                        else
+                        {
+                            const char* skn_key = "";
+                            const char* skn_value = "";
+
+                            if ((dev_auth_cred->sas_info.key_name != NULL) && (strlen(dev_auth_cred->sas_info.key_name) > 0))
+                            {
+                                // If the key name is valid then add to the sas token
+                                skn_key = SKN_SECTION_FORMAT;
+                                skn_value = dev_auth_cred->sas_info.key_name;
+                            }
+
+                            STRING_HANDLE sas_token_handle = NULL;
+
+                            if (handle->urlencode_token_scope == true)
+                            {
+                                STRING_HANDLE url_encoded = URL_EncodeString(dev_auth_cred->sas_info.token_scope);
+                                if (url_encoded == NULL)
+                                {
+                                    LogError("failed to url string %s", dev_auth_cred->sas_info.token_scope);
+                                }
+                                else
+                                {
+                                    sas_token_handle = STRING_construct_sprintf(SAS_TOKEN_FORMAT, STRING_c_str(url_encoded), STRING_c_str(urlEncodedSignature), expire_token, skn_key, skn_value);
+                                }
+
+                                STRING_delete(url_encoded);
+                            }
+                            else
+                            {
+                                sas_token_handle = STRING_construct_sprintf(SAS_TOKEN_FORMAT, dev_auth_cred->sas_info.token_scope, STRING_c_str(urlEncodedSignature), expire_token, skn_key, skn_value);
+                            }
+
+                            if (sas_token_handle == NULL)
+                            {
+                                result = NULL;
+                                LogError("Failure constructing url Signature.");
+                            }
+                            else if ((result = malloc(sizeof(CREDENTIAL_RESULT))) == NULL)
+                            {
+                                STRING_delete(sas_token_handle);
+                                LogError("Failure allocating credential result.");
+                            }
+                            else
+                            {
+                                const char* temp_sas_token = STRING_c_str(sas_token_handle);
+                                if (mallocAndStrcpy_s(&handle->sas_token, temp_sas_token) != 0)
+                                {
+                                    free(result);
+                                    result = NULL;
+                                    LogError("Failure allocating and copying string.");
+                                }
+                                else
+                                {
+                                    result->auth_cred_result.sas_result.sas_token = handle->sas_token;
+                                }
+                                STRING_delete(sas_token_handle);
+                            }
+                            STRING_delete(signature);
+                            STRING_delete(urlEncodedSignature);
+                        }
+                        free(data_value);
+                    }
+                    else
+                    {
+                        result = NULL;
+                        LogError("Failure generate hash from tpm.");
+                    }
+                    free(payload);
+                }
+            }
+        }
+        else
+        {
+            if (handle->x509_certificate != NULL)
+            {
+                free(handle->x509_certificate);
+                handle->x509_certificate = NULL;
+            }
+            if (handle->x509_alias_key != NULL)
+            {
+                free(handle->x509_alias_key);
+                handle->x509_alias_key = NULL;
+            }
+
+            if ((result = malloc(sizeof(CREDENTIAL_RESULT))) == NULL)
+            {
+                LogError("Failure allocating credential result.");
+            }
+            else if ((handle->x509_certificate = handle->hsm_client_get_cert(handle->hsm_client_handle)) == NULL)
+            {
+                LogError("Failure allocating device credential result.");
+                free(result);
+                result = NULL;
+            }
+            else if ((handle->x509_alias_key = handle->hsm_client_get_alias_key(handle->hsm_client_handle)) == NULL)
+            {
+                LogError("Failure allocating device credential result.");
+                free(handle->x509_certificate);
+                handle->x509_certificate = NULL;
+                free(result);
+                result = NULL;
+            }
+            else
+            {
+                result->auth_cred_result.x509_result.x509_cert = handle->x509_certificate;
+                result->auth_cred_result.x509_result.x509_alias_key = handle->x509_alias_key;
+            }
+        }
+    }
+    return result;
+}
+
+#ifdef USE_EDGE_MODULES
+char* iothub_device_auth_get_trust_bundle(IOTHUB_SECURITY_HANDLE handle)
+{
+    if (handle->hsm_client_get_trust_bundle == NULL)
+    {
+        LogError("This authentication type does not support getting trusted certificates");
+        return NULL;
+    }
+    return handle->hsm_client_get_trust_bundle(handle->hsm_client_handle);
+}
+#endif
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/iothub_security_factory.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/iothub_security_factory.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/iothub_security_factory.c	(revision 453)
@@ -0,0 +1,181 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "azure_prov_client/iothub_security_factory.h"
+#include "azure_prov_client/prov_security_factory.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+
+#include "hsm_client_data.h"
+
+static IOTHUB_SECURITY_TYPE g_security_type = IOTHUB_SECURITY_TYPE_UNKNOWN;
+static char* g_symm_key = NULL;
+static char* g_symm_key_reg_name = NULL;
+
+static SECURE_DEVICE_TYPE get_secure_device_type(IOTHUB_SECURITY_TYPE sec_type)
+{
+    SECURE_DEVICE_TYPE ret;
+
+    switch (sec_type)
+    {
+#if defined(HSM_TYPE_SAS_TOKEN)  || defined(HSM_AUTH_TYPE_CUSTOM)
+        case IOTHUB_SECURITY_TYPE_SAS:
+            ret = SECURE_DEVICE_TYPE_TPM;
+            break;
+#endif
+
+#if defined(HSM_TYPE_X509) || defined(HSM_AUTH_TYPE_CUSTOM)
+        case IOTHUB_SECURITY_TYPE_X509:
+            ret = SECURE_DEVICE_TYPE_X509;
+            break;
+#endif
+
+#if defined(HSM_TYPE_SYMM_KEY) || defined(HSM_AUTH_TYPE_CUSTOM)
+        case IOTHUB_SECURITY_TYPE_SYMMETRIC_KEY:
+            ret = SECURE_DEVICE_TYPE_SYMMETRIC_KEY;
+            break;
+#endif
+
+#ifdef HSM_TYPE_HTTP_EDGE
+        case IOTHUB_SECURITY_TYPE_HTTP_EDGE:
+            ret = SECURE_DEVICE_TYPE_HTTP_EDGE;
+            break;
+#endif
+
+        default:
+            ret = SECURE_DEVICE_TYPE_UNKNOWN;
+            break;
+    }
+
+    return ret;
+}
+
+int iothub_security_init(IOTHUB_SECURITY_TYPE sec_type)
+{
+    int result;
+
+    SECURE_DEVICE_TYPE secure_device_type_from_caller = get_secure_device_type(sec_type);
+
+    if (secure_device_type_from_caller == SECURE_DEVICE_TYPE_UNKNOWN)
+    {
+        LogError("Security type %d is not supported in this SDK build", sec_type);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        g_security_type = sec_type;
+        SECURE_DEVICE_TYPE security_device_type_from_prov = prov_dev_security_get_type();
+        if (security_device_type_from_prov == SECURE_DEVICE_TYPE_UNKNOWN)
+        {
+            result = prov_dev_security_init(secure_device_type_from_caller);
+        }
+        else if (secure_device_type_from_caller != security_device_type_from_prov)
+        {
+            LogError("Security type from caller %d (which maps to security device type %d) does not match already specified security device type %d", sec_type, secure_device_type_from_caller, security_device_type_from_prov);
+            result = MU_FAILURE;
+        }
+        else
+        {
+            result = 0;
+        }
+
+        if (result == 0)
+        {
+            result = initialize_hsm_system();
+        }
+    }
+    return result;
+}
+
+void iothub_security_deinit()
+{
+    if (g_symm_key != NULL)
+    {
+        free(g_symm_key);
+        g_symm_key = NULL;
+    }
+    if (g_symm_key_reg_name != NULL)
+    {
+        free(g_symm_key_reg_name);
+        g_symm_key_reg_name = NULL;
+    }
+    deinitialize_hsm_system();
+    if (prov_dev_get_symmetric_key() != NULL || prov_dev_get_symm_registration_name() != NULL)
+    {
+        prov_dev_security_deinit();
+    }
+}
+
+IOTHUB_SECURITY_TYPE iothub_security_type()
+{
+    return g_security_type;
+}
+
+int iothub_security_set_symmetric_key_info(const char* registration_name, const char* symmetric_key)
+{
+    int result;
+    if (registration_name == NULL || symmetric_key == NULL)
+    {
+        LogError("Invalid parameter specified reg_name: %p, symm_key: %p", registration_name, symmetric_key);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        char* temp_key;
+        char* temp_name;
+        if (mallocAndStrcpy_s(&temp_name, registration_name) != 0)
+        {
+            LogError("Failure allocating registration name");
+            result = MU_FAILURE;
+        }
+        else if (mallocAndStrcpy_s(&temp_key, symmetric_key) != 0)
+        {
+            LogError("Failure allocating symmetric key");
+            free(temp_name);
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if (g_symm_key != NULL)
+            {
+                free(g_symm_key);
+            }
+            if (g_symm_key_reg_name != NULL)
+            {
+                free(g_symm_key_reg_name);
+            }
+            g_symm_key_reg_name = temp_name;
+            g_symm_key = temp_key;
+
+            // Sync iothub with dps
+            if (prov_dev_get_symmetric_key() == NULL || prov_dev_get_symm_registration_name() == NULL)
+            {
+                if (prov_dev_set_symmetric_key_info(g_symm_key_reg_name, g_symm_key) != 0)
+                {
+                    LogError("Failure syncing dps & IoThub key information");
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    result = 0;
+                }
+            }
+            else
+            {
+                result = 0;
+            }
+        }
+    }
+    return result;
+}
+
+const char* iothub_security_get_symmetric_key()
+{
+    return g_symm_key;
+}
+
+const char* iothub_security_get_symm_registration_name()
+{
+    return g_symm_key_reg_name;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/prov_auth_client.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/prov_auth_client.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/prov_auth_client.c	(revision 453)
@@ -0,0 +1,666 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "umock_c/umock_c_prod.h"
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/azure_base64.h"
+#include "azure_c_shared_utility/azure_base32.h"
+#include "azure_c_shared_utility/urlencode.h"
+#include "azure_c_shared_utility/sha.h"
+#include "azure_c_shared_utility/strings.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/sastoken.h"
+#include "azure_c_shared_utility/hmacsha256.h"
+
+#include "azure_prov_client/internal/prov_auth_client.h"
+#include "hsm_client_data.h"
+
+#include "azure_prov_client/prov_security_factory.h"
+
+typedef struct PROV_AUTH_INFO_TAG
+{
+    HSM_CLIENT_HANDLE hsm_client_handle;
+
+    PROV_AUTH_TYPE sec_type;
+
+    char* registration_id;
+
+    HSM_CLIENT_CREATE hsm_client_create;
+    HSM_CLIENT_DESTROY hsm_client_destroy;
+
+    HSM_CLIENT_ACTIVATE_IDENTITY_KEY hsm_client_import_key;
+    HSM_CLIENT_GET_ENDORSEMENT_KEY hsm_client_get_endorsement_key;
+    HSM_CLIENT_GET_STORAGE_ROOT_KEY hsm_client_get_srk;
+    HSM_CLIENT_SIGN_WITH_IDENTITY hsm_client_sign_data;
+
+    HSM_CLIENT_GET_CERTIFICATE hsm_client_get_cert;
+    HSM_CLIENT_GET_ALIAS_KEY hsm_client_get_alias_key;
+    HSM_CLIENT_GET_COMMON_NAME hsm_client_get_common_name;
+
+    HSM_CLIENT_GET_SYMMETRICAL_KEY hsm_client_get_symm_key;
+    HSM_CLIENT_SET_SYMMETRICAL_KEY_INFO hsm_client_set_symm_key_info;
+} PROV_AUTH_INFO;
+
+static char* encode_value(const uint8_t* msg_digest, size_t digest_len)
+{
+    char* result;
+
+    char* encoded_hash = Azure_Base32_Encode_Bytes(msg_digest, digest_len);
+    if (encoded_hash == NULL)
+    {
+        LogError("Failure encoded Base32");
+        result = NULL;
+    }
+    else
+    {
+        size_t encode_len = strlen(encoded_hash);
+        char* iterator = encoded_hash + encode_len - 1;
+
+        while (iterator != encoded_hash)
+        {
+            if (*iterator != '=')
+            {
+                *(iterator+1) = '\0';
+                break;
+            }
+            iterator--;
+        }
+
+        if (mallocAndStrcpy_s(&result, encoded_hash) != 0)
+        {
+            LogError("Failure allocating encoded base32 result");
+            result = NULL;
+        }
+        free(encoded_hash);
+    }
+    return result;
+}
+
+static int load_registration_id(PROV_AUTH_INFO* handle)
+{
+    int result;
+    if (handle->sec_type == PROV_AUTH_TYPE_TPM)
+    {
+        SHA256Context sha_ctx;
+        uint8_t msg_digest[SHA256HashSize];
+        unsigned char* endorsement_key;
+        size_t ek_len;
+
+        if (handle->hsm_client_get_endorsement_key(handle->hsm_client_handle, &endorsement_key, &ek_len) != 0)
+        {
+            LogError("Failed getting device reg id");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if (SHA256Reset(&sha_ctx) != 0)
+            {
+                LogError("Failed sha256 reset");
+                result = MU_FAILURE;
+            }
+            else if (SHA256Input(&sha_ctx, endorsement_key, (unsigned int)ek_len) != 0)
+            {
+                LogError("Failed SHA256Input");
+                result = MU_FAILURE;
+            }
+            else if (SHA256Result(&sha_ctx, msg_digest) != 0)
+            {
+                LogError("Failed SHA256Result");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                handle->registration_id = encode_value(msg_digest, SHA256HashSize);
+                if (handle->registration_id == NULL)
+                {
+                    LogError("Failed allocating registration Id");
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    result = 0;
+                }
+            }
+            free(endorsement_key);
+        }
+    }
+    else
+    {
+        handle->registration_id = handle->hsm_client_get_common_name(handle->hsm_client_handle);
+        if (handle->registration_id == NULL)
+        {
+            LogError("Failed getting common name from certificate");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            result = 0;
+        }
+    }
+    return result;
+}
+
+static int sign_sas_data(PROV_AUTH_INFO* auth_info, const char* payload, unsigned char** output, size_t* len)
+{
+    int result;
+    size_t payload_len = strlen(payload);
+    if (auth_info->sec_type == PROV_AUTH_TYPE_TPM)
+    {
+        if (auth_info->hsm_client_sign_data(auth_info->hsm_client_handle, (const unsigned char*)payload, strlen(payload), output, len) != 0)
+        {
+            LogError("Failed signing data");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            result = 0;
+        }
+    }
+    else
+    {
+        char* symmetrical_key = auth_info->hsm_client_get_symm_key(auth_info->hsm_client_handle);
+        if (symmetrical_key == NULL)
+        {
+            LogError("Failed getting asymmetrical key");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            BUFFER_HANDLE decoded_key;
+            BUFFER_HANDLE output_hash;
+            if ((decoded_key = Azure_Base64_Decode(symmetrical_key)) == NULL)
+            {
+                LogError("Failed decoding symmetrical key");
+                result = MU_FAILURE;
+            }
+            else if ((output_hash = BUFFER_new()) == NULL)
+            {
+                LogError("Failed allocating output hash buffer");
+                BUFFER_delete(decoded_key);
+                result = MU_FAILURE;
+            }
+            else
+            {
+                size_t decoded_key_len = BUFFER_length(decoded_key);
+                const unsigned char* decoded_key_bytes = BUFFER_u_char(decoded_key);
+
+                if (HMACSHA256_ComputeHash(decoded_key_bytes, decoded_key_len, (const unsigned char*)payload, payload_len, output_hash) != HMACSHA256_OK)
+                {
+                    LogError("Failed computing HMAC Hash");
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    *len = BUFFER_length(output_hash);
+                    if ((*output = malloc(*len)) == NULL)
+                    {
+                        LogError("Failed allocating output buffer");
+                        result = MU_FAILURE;
+                    }
+                    else
+                    {
+                        const unsigned char* output_data = BUFFER_u_char(output_hash);
+                        memcpy(*output, output_data, *len);
+                        result = 0;
+                    }
+                }
+                BUFFER_delete(decoded_key);
+                BUFFER_delete(output_hash);
+            }
+        }
+        free(symmetrical_key);
+    }
+    return result;
+}
+
+PROV_AUTH_HANDLE prov_auth_create(void)
+{
+    PROV_AUTH_INFO* result;
+    /* Codes_SRS_PROV_AUTH_CLIENT_07_001: [ prov_auth_create shall allocate the PROV_AUTH_INFO. ] */
+    if ((result = (PROV_AUTH_INFO*)malloc(sizeof(PROV_AUTH_INFO))) == NULL)
+    {
+        LogError("Failed allocating PROV_AUTH_INFO.");
+    }
+    else
+    {
+        memset(result, 0, sizeof(PROV_AUTH_INFO) );
+        SECURE_DEVICE_TYPE sec_type = prov_dev_security_get_type();
+#if defined(HSM_TYPE_SAS_TOKEN)  || defined(HSM_AUTH_TYPE_CUSTOM)
+        if (sec_type == SECURE_DEVICE_TYPE_TPM)
+        {
+            /* Codes_SRS_PROV_AUTH_CLIENT_07_003: [ prov_auth_create shall validate the specified secure enclave interface to ensure. ] */
+            result->sec_type = PROV_AUTH_TYPE_TPM;
+            const HSM_CLIENT_TPM_INTERFACE* tpm_interface = hsm_client_tpm_interface();
+            if ((tpm_interface == NULL) ||
+                ((result->hsm_client_create = tpm_interface->hsm_client_tpm_create) == NULL) ||
+                ((result->hsm_client_destroy = tpm_interface->hsm_client_tpm_destroy) == NULL) ||
+                ((result->hsm_client_import_key = tpm_interface->hsm_client_activate_identity_key) == NULL) ||
+                ((result->hsm_client_get_endorsement_key = tpm_interface->hsm_client_get_ek) == NULL) ||
+                ((result->hsm_client_get_srk = tpm_interface->hsm_client_get_srk) == NULL) ||
+                ((result->hsm_client_sign_data = tpm_interface->hsm_client_sign_with_identity) == NULL)
+                )
+            {
+                /* Codes_SRS_PROV_AUTH_CLIENT_07_002: [ If any failure is encountered prov_auth_create shall return NULL ] */
+                LogError("Invalid TPM secure device interface was specified");
+                free(result);
+                result = NULL;
+            }
+        }
+#endif
+#if defined(HSM_TYPE_X509) || defined(HSM_AUTH_TYPE_CUSTOM)
+        if (sec_type == SECURE_DEVICE_TYPE_X509)
+        {
+            /* Codes_SRS_PROV_AUTH_CLIENT_07_003: [ prov_auth_create shall validate the specified secure enclave interface to ensure. ] */
+            result->sec_type = PROV_AUTH_TYPE_X509;
+            const HSM_CLIENT_X509_INTERFACE* x509_interface = hsm_client_x509_interface();
+            if ((x509_interface == NULL) ||
+                ((result->hsm_client_create = x509_interface->hsm_client_x509_create) == NULL) ||
+                ((result->hsm_client_destroy = x509_interface->hsm_client_x509_destroy) == NULL) ||
+                ((result->hsm_client_get_cert = x509_interface->hsm_client_get_cert) == NULL) ||
+                ((result->hsm_client_get_common_name = x509_interface->hsm_client_get_common_name) == NULL) ||
+                ((result->hsm_client_get_alias_key = x509_interface->hsm_client_get_key) == NULL)
+                )
+            {
+                LogError("Invalid x509 secure device interface was specified");
+                free(result);
+                result = NULL;
+            }
+        }
+#endif
+#if defined(HSM_TYPE_SYMM_KEY) || defined(HSM_AUTH_TYPE_CUSTOM)
+        if (sec_type == SECURE_DEVICE_TYPE_SYMMETRIC_KEY)
+        {
+            result->sec_type = PROV_AUTH_TYPE_KEY;
+            const HSM_CLIENT_KEY_INTERFACE* key_interface = hsm_client_key_interface();
+            if ((key_interface == NULL) ||
+                ((result->hsm_client_create = key_interface->hsm_client_key_create) == NULL) ||
+                ((result->hsm_client_destroy = key_interface->hsm_client_key_destroy) == NULL) ||
+                ((result->hsm_client_get_common_name = key_interface->hsm_client_get_registration_name) == NULL) ||
+                ((result->hsm_client_get_symm_key = key_interface->hsm_client_get_symm_key) == NULL) ||
+                ((result->hsm_client_set_symm_key_info = key_interface->hsm_client_set_symm_key_info) == NULL)
+                )
+            {
+                LogError("Invalid symmetric key secure device interface was specified");
+                free(result);
+                result = NULL;
+            }
+        }
+#endif
+
+        if (result == NULL)
+        {
+            LogError("Error allocating result or else unsupported security type %d", sec_type);
+        }
+        else if (result->hsm_client_create == NULL)
+        {
+            LogError("hsm_client_create is not a valid address");
+            free(result);
+            result = NULL;
+        }
+        else
+        {
+            /* Codes_SRS_PROV_AUTH_CLIENT_07_004: [ prov_auth_create shall call hsm_client_create on the secure enclave interface. ] */
+            if ((result->hsm_client_handle = result->hsm_client_create() ) == NULL)
+            {
+                LogError("failed create device auth module.");
+                free(result);
+                result = NULL;
+            }
+            else if (result->sec_type == PROV_AUTH_TYPE_KEY && result->hsm_client_set_symm_key_info(result->hsm_client_handle, prov_dev_get_symm_registration_name(), prov_dev_get_symmetric_key()) != 0)
+            {
+                LogError("failed create device auth module.");
+                result->hsm_client_destroy(result->hsm_client_handle);
+                free(result);
+                result = NULL;
+            }
+        }
+    }
+    return result;
+}
+
+void prov_auth_destroy(PROV_AUTH_HANDLE handle)
+{
+    /* Codes_SRS_PROV_AUTH_CLIENT_07_005: [ if handle is NULL, prov_auth_destroy shall do nothing. ] */
+    if (handle != NULL)
+    {
+        /* Codes_SRS_PROV_AUTH_CLIENT_07_007: [ prov_auth_destroy shall free all resources allocated in this module. ] */
+        free(handle->registration_id);
+        handle->hsm_client_destroy(handle->hsm_client_handle);
+        /* Codes_SRS_PROV_AUTH_CLIENT_07_006: [ prov_auth_destroy shall free the PROV_AUTH_HANDLE instance. ] */
+        free(handle);
+    }
+}
+
+PROV_AUTH_TYPE prov_auth_get_type(PROV_AUTH_HANDLE handle)
+{
+    PROV_AUTH_TYPE result;
+    /* Codes_SRS_PROV_AUTH_CLIENT_07_008: [ if handle is NULL prov_auth_get_type shall return PROV_AUTH_TYPE_UNKNOWN ] */
+    if (handle == NULL)
+    {
+        LogError("Invalid handle specified");
+        result = PROV_AUTH_TYPE_UNKNOWN;
+    }
+    else
+    {
+        /* Codes_SRS_PROV_AUTH_CLIENT_07_009: [ prov_auth_get_type shall return the PROV_AUTH_TYPE of the underlying secure enclave. ] */
+        result = handle->sec_type;
+    }
+    return result;
+}
+
+char* prov_auth_get_registration_id(PROV_AUTH_HANDLE handle)
+{
+    char* result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_PROV_AUTH_CLIENT_07_010: [ if handle is NULL prov_auth_get_registration_id shall return NULL. ] */
+        LogError("Invalid handle parameter");
+        result = NULL;
+    }
+    else
+    {
+        int load_result = 0;
+        int reg_id_allocated = 0;
+        if (handle->registration_id == NULL)
+        {
+            /* Codes_SRS_PROV_AUTH_CLIENT_07_011: [ prov_auth_get_registration_id shall load the registration id if it has not been previously loaded. ] */
+            load_result = load_registration_id(handle);
+            if (load_result == 0)
+            {
+                reg_id_allocated = 1;
+            }
+        }
+
+        if (load_result != 0)
+        {
+            /* Codes_SRS_PROV_AUTH_CLIENT_07_012: [ If a failure is encountered, prov_auth_get_registration_id shall return NULL. ] */
+            LogError("Failed loading registration key");
+            result = NULL;
+        }
+        /* Codes_SRS_PROV_AUTH_CLIENT_07_013: [ Upon success prov_auth_get_registration_id shall return the registration id of the secure enclave. ] */
+        else if (mallocAndStrcpy_s(&result, handle->registration_id) != 0)
+        {
+            /* Codes_SRS_PROV_AUTH_CLIENT_07_012: [ If a failure is encountered, prov_auth_get_registration_id shall return NULL. ] */
+            LogError("Failed allocating registration key");
+            if (reg_id_allocated == 1)
+            {
+                free(handle->registration_id);
+                handle->registration_id = NULL;
+            }
+            result = NULL;
+        }
+    }
+    return result;
+}
+
+int prov_auth_set_registration_id(PROV_AUTH_HANDLE handle, const char* registration_id)
+{
+    int result;
+    if (handle == NULL || registration_id == NULL)
+    {
+        LogError("Invalid parameter handle: %p, registration_id: %p", handle, registration_id);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        if (handle->registration_id != NULL)
+        {
+            LogError("Registration_id has been previously set, registration can not be changed");
+            result = MU_FAILURE;
+        }
+        else if (mallocAndStrcpy_s(&handle->registration_id, registration_id) != 0)
+        {
+            LogError("Failed allocating registration key");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            result = 0;
+        }
+    }
+    return result;
+}
+
+BUFFER_HANDLE prov_auth_get_endorsement_key(PROV_AUTH_HANDLE handle)
+{
+    BUFFER_HANDLE result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_SECURE_ENCLAVE_CLIENT_07_021: [ If handle is NULL prov_auth_get_endorsement_key shall return NULL. ] */
+        LogError("Invalid handle parameter");
+        result = NULL;
+    }
+    else if (handle->sec_type != PROV_AUTH_TYPE_TPM)
+    {
+        /* Codes_SRS_SECURE_ENCLAVE_CLIENT_07_023: [ If the sec_type is PROV_AUTH_TYPE_X509, prov_auth_get_endorsement_key shall return NULL. ] */
+        LogError("Invalid type for operation");
+        result = NULL;
+    }
+    else
+    {
+        unsigned char* ek_value;
+        size_t ek_len;
+
+        if (handle->hsm_client_get_endorsement_key(handle->hsm_client_handle, &ek_value, &ek_len) != 0)
+        {
+            LogError("Failed getting endorsement key");
+            result = NULL;
+        }
+        else
+        {
+            /* Codes_SRS_SECURE_ENCLAVE_CLIENT_07_022: [ prov_auth_get_endorsement_key shall return the endorsement key returned by the hsm_client_get_ek secure enclave function. ] */
+            result = BUFFER_create(ek_value, ek_len);
+            if (result == NULL)
+            {
+                LogError("Failed creating BUFFER HANDLE");
+            }
+            free(ek_value);
+        }
+    }
+    return result;
+}
+
+BUFFER_HANDLE prov_auth_get_storage_key(PROV_AUTH_HANDLE handle)
+{
+    BUFFER_HANDLE result;
+    /* Codes_SRS_SECURE_ENCLAVE_CLIENT_07_024: [ If handle is NULL prov_auth_get_storage_key shall return NULL. ] */
+    if (handle == NULL)
+    {
+        LogError("Invalid handle parameter");
+        result = NULL;
+    }
+    else if (handle->sec_type != PROV_AUTH_TYPE_TPM)
+    {
+        /* Codes_SRS_SECURE_ENCLAVE_CLIENT_07_026: [ If the sec_type is PROV_AUTH_TYPE_X509, prov_auth_get_storage_key shall return NULL. ] */
+        LogError("Invalid type for operation");
+        result = NULL;
+    }
+    else
+    {
+        unsigned char* srk_value;
+        size_t srk_len;
+
+        if (handle->hsm_client_get_srk(handle->hsm_client_handle, &srk_value, &srk_len) != 0)
+        {
+            LogError("Failed getting storage root key");
+            result = NULL;
+        }
+        else
+        {
+            /* Codes_SRS_SECURE_ENCLAVE_CLIENT_07_025: [ prov_auth_get_storage_key shall return the endorsement key returned by the hsm_client_get_srk secure enclave function. ] */
+            result = BUFFER_create(srk_value, srk_len);
+            if (result == NULL)
+            {
+                LogError("Failed creating BUFFER HANDLE");
+            }
+            free(srk_value);
+        }
+    }
+    return result;
+}
+
+int prov_auth_import_key(PROV_AUTH_HANDLE handle, const unsigned char* key_value, size_t key_len)
+{
+    int result;
+    if (handle == NULL || key_value == NULL || key_len == 0)
+    {
+        /* Codes_SRS_SECURE_ENCLAVE_CLIENT_07_027: [ If handle or key are NULL prov_auth_import_key shall return a non-zero value. ] */
+        LogError("Invalid handle parameter");
+        result = MU_FAILURE;
+    }
+    else if (handle->sec_type != PROV_AUTH_TYPE_TPM)
+    {
+        /* Codes_SRS_SECURE_ENCLAVE_CLIENT_07_029: [ If the sec_type is not SECURE_ENCLAVE_TYPE_TPM, prov_auth_import_key shall return NULL. ] */
+        LogError("Invalid type for operation");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        /* Codes_SRS_SECURE_ENCLAVE_CLIENT_07_028: [ prov_auth_import_key shall import the specified key into the tpm using hsm_client_import_key secure enclave function. ] */
+        if (handle->hsm_client_import_key(handle->hsm_client_handle, key_value, key_len) != 0)
+        {
+            /* SRS_SECURE_ENCLAVE_CLIENT_07_040: [ If hsm_client_import_key returns an error prov_auth_import_key shall return a non-zero value. ]*/
+            LogError("failure importing key into tpm");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            result = 0;
+        }
+    }
+    return result;
+}
+
+char* prov_auth_construct_sas_token(PROV_AUTH_HANDLE handle, const char* token_scope, const char* key_name, size_t expiry_time)
+{
+    char* result;
+    char expire_token[64] = { 0 };
+
+    if (handle == NULL || token_scope == NULL || key_name == NULL)
+    {
+        LogError("Invalid handle parameter handle: %p, token_scope: %p, key_name: %p", handle, token_scope, key_name);
+        result = NULL;
+    }
+    else if (handle->sec_type == PROV_AUTH_TYPE_X509)
+    {
+        LogError("Invalid type for operation");
+        result = NULL;
+    }
+    else if (size_tToString(expire_token, sizeof(expire_token), expiry_time) != 0)
+    {
+        result = NULL;
+        LogError("Failure creating expire token");
+    }
+    else
+    {
+        size_t len = strlen(token_scope) + strlen(expire_token) + 3;
+        char* payload = malloc(len + 1);
+        if (payload == NULL)
+        {
+            result = NULL;
+            LogError("Failure allocating payload for sas token.");
+        }
+        else
+        {
+            unsigned char* data_value;
+            size_t data_len;
+            (void)sprintf(payload, "%s\n%s", token_scope, expire_token);
+
+            /* Codes_SRS_SECURE_ENCLAVE_CLIENT_07_031: [ prov_auth_get_certificate shall import the specified cert into the client using hsm_client_get_cert secure enclave function. ] */
+            if (sign_sas_data(handle, payload, &data_value, &data_len) == 0)
+            {
+                STRING_HANDLE urlEncodedSignature;
+                STRING_HANDLE base64Signature;
+                STRING_HANDLE sas_token_handle;
+                if ((base64Signature = Azure_Base64_Encode_Bytes(data_value, data_len)) == NULL)
+                {
+                    result = NULL;
+                    LogError("Failure constructing base64 encoding.");
+                }
+                else if ((urlEncodedSignature = URL_Encode(base64Signature)) == NULL)
+                {
+                    result = NULL;
+                    LogError("Failure constructing url Signature.");
+                    STRING_delete(base64Signature);
+                }
+                else
+                {
+                    sas_token_handle = STRING_construct_sprintf("SharedAccessSignature sr=%s&sig=%s&se=%s&skn=%s", token_scope, STRING_c_str(urlEncodedSignature), expire_token, key_name);
+                    if (sas_token_handle == NULL)
+                    {
+                        result = NULL;
+                        LogError("Failure constructing url Signature.");
+                    }
+                    else
+                    {
+                        const char* temp_sas_token = STRING_c_str(sas_token_handle);
+                        if (mallocAndStrcpy_s(&result, temp_sas_token) != 0)
+                        {
+                            LogError("Failure allocating and copying string.");
+                            result = NULL;
+                        }
+                        STRING_delete(sas_token_handle);
+                    }
+                    STRING_delete(base64Signature);
+                    STRING_delete(urlEncodedSignature);
+                }
+                free(data_value);
+            }
+            else
+            {
+                result = NULL;
+                LogError("Failure generate sas token.");
+            }
+            free(payload);
+        }
+    }
+    return result;
+}
+
+char* prov_auth_get_certificate(PROV_AUTH_HANDLE handle)
+{
+    char* result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_SECURE_ENCLAVE_CLIENT_07_030: [ If handle or key are NULL prov_auth_get_certificate shall return a non-zero value. ] */
+        LogError("Invalid handle parameter");
+        result = NULL;
+    }
+    else if (handle->sec_type != PROV_AUTH_TYPE_X509)
+    {
+        /* Codes_SRS_SECURE_ENCLAVE_CLIENT_07_032: [ If the sec_type is not PROV_AUTH_TYPE_X509, prov_auth_get_certificate shall return NULL. ] */
+        LogError("Invalid type for operation");
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_SECURE_ENCLAVE_CLIENT_07_031: [ prov_auth_get_certificate shall import the specified cert into the client using hsm_client_get_cert secure enclave function. ] */
+        result = handle->hsm_client_get_cert(handle->hsm_client_handle);
+    }
+    return result;
+}
+
+char* prov_auth_get_alias_key(PROV_AUTH_HANDLE handle)
+{
+    char* result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_SECURE_ENCLAVE_CLIENT_07_033: [ If handle or key are NULL prov_auth_get_alias_key shall return a non-zero value. ] */
+        LogError("Invalid handle parameter");
+        result = NULL;
+    }
+    else if (handle->sec_type != PROV_AUTH_TYPE_X509)
+    {
+        /* Codes_SRS_SECURE_ENCLAVE_CLIENT_07_035: [ If the sec_type is not PROV_AUTH_TYPE_X509, prov_auth_get_alias_key shall return NULL. ] */
+        LogError("Invalid type for operation");
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_SECURE_ENCLAVE_CLIENT_07_034: [ prov_auth_get_alias_key shall import the specified alias key into the client using hsm_client_get_ak secure enclave function. ] */
+        result = handle->hsm_client_get_alias_key(handle->hsm_client_handle);
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/prov_device_client.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/prov_device_client.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/prov_device_client.c	(revision 453)
@@ -0,0 +1,316 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+
+#include <signal.h>
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/threadapi.h"
+#include "azure_c_shared_utility/lock.h"
+#include "azure_c_shared_utility/xlogging.h"
+
+#include "azure_prov_client/prov_device_ll_client.h"
+#include "azure_prov_client/prov_device_client.h"
+#include "azure_c_shared_utility/vector.h"
+
+#define DO_WORK_FREQ_DEFAULT 1
+
+static const char* const OPTION_DO_WORK_FREQUENCY_IN_MS = "do_work_freq_ms";
+
+typedef struct PROV_DEVICE_INSTANCE_TAG
+{
+    PROV_DEVICE_LL_HANDLE ProvDeviceLLHandle;
+    THREAD_HANDLE ThreadHandle;
+    LOCK_HANDLE LockHandle;
+    sig_atomic_t StopThread;
+    uint16_t do_work_freq_ms;
+} PROV_DEVICE_INSTANCE;
+
+static int ScheduleWork_Thread(void* threadArgument)
+{
+    PROV_DEVICE_INSTANCE* prov_device_instance = (PROV_DEVICE_INSTANCE*)threadArgument;
+    uint16_t sleeptime_in_ms = DO_WORK_FREQ_DEFAULT;
+
+    srand((unsigned int)get_time(NULL));
+
+    while (1)
+    {
+        if (Lock(prov_device_instance->LockHandle) == LOCK_OK)
+        {
+            if (prov_device_instance->StopThread)
+            {
+                (void)Unlock(prov_device_instance->LockHandle);
+                break; /*gets out of the thread*/
+            }
+            else
+            {
+                Prov_Device_LL_DoWork(prov_device_instance->ProvDeviceLLHandle);
+                sleeptime_in_ms = prov_device_instance->do_work_freq_ms; // Update the sleepval within the locked thread. 
+                (void)Unlock(prov_device_instance->LockHandle);
+            }
+        }
+        else
+        {
+            LogError("Lock failed, shall retry");
+        }
+        (void)ThreadAPI_Sleep(sleeptime_in_ms);
+    }
+
+    ThreadAPI_Exit(0);
+    return 0;
+}
+
+static PROV_DEVICE_RESULT StartWorkerThreadIfNeeded(PROV_DEVICE_INSTANCE* prov_device_instance)
+{
+    PROV_DEVICE_RESULT result;
+    if (prov_device_instance->ThreadHandle == NULL)
+    {
+        prov_device_instance->StopThread = 0;
+        if (ThreadAPI_Create(&prov_device_instance->ThreadHandle, ScheduleWork_Thread, prov_device_instance) != THREADAPI_OK)
+        {
+            LogError("ThreadAPI_Create failed");
+            result = PROV_DEVICE_RESULT_ERROR;
+        }
+        else
+        {
+            result = PROV_DEVICE_RESULT_OK;
+        }
+    }
+    else
+    {
+        result = PROV_DEVICE_RESULT_OK;
+    }
+    return result;
+}
+
+PROV_DEVICE_HANDLE Prov_Device_Create(const char* uri, const char* id_scope, PROV_DEVICE_TRANSPORT_PROVIDER_FUNCTION protocol)
+{
+    PROV_DEVICE_INSTANCE* result;
+
+    /* Codes_SRS_PROV_DEVICE_CLIENT_12_001: [ If any of the input parameter is NULL `Prov_Device_Create` shall return NULL.] */
+    if (uri == NULL || id_scope == NULL || protocol == NULL)
+    {
+        LogError("Invalid parameter specified uri: %p, id_scope: %p, protocol: %p", uri, id_scope, protocol);
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_PROV_DEVICE_CLIENT_12_002: [ The function shall allocate memory for PROV_DEVICE_INSTANCE data structure. ] */
+        result = (PROV_DEVICE_INSTANCE*)malloc(sizeof(PROV_DEVICE_INSTANCE));
+        if (result == NULL)
+        {
+            /* Codes_SRS_PROV_DEVICE_CLIENT_12_003: [ If the memory allocation failed the function shall return NULL. ] */
+            LogError("Unable to allocate Instance Info");
+        }
+        else
+        {
+            memset(result, 0, sizeof(PROV_DEVICE_INSTANCE) );
+            /* Codes_SRS_PROV_DEVICE_CLIENT_12_004: [ The function shall initialize the Lock. ] */
+            result->LockHandle = Lock_Init();
+            if (result->LockHandle == NULL)
+            {
+                /* Codes_SRS_PROV_DEVICE_CLIENT_12_005: [ If the Lock initialization failed the function shall clean up the all resources and return NULL. ] */
+                LogError("Lock_Init failed");
+                free(result);
+                result = NULL;
+            }
+            else
+            {
+                /* Codes_SRS_PROV_DEVICE_CLIENT_12_006: [ The function shall call the LL layer Prov_Device_LL_Create function and return with it's result. ] */
+                result->ProvDeviceLLHandle = Prov_Device_LL_Create(uri, id_scope, protocol);
+                if (result->ProvDeviceLLHandle == NULL)
+                {
+                    /* Codes_SRS_PROV_DEVICE_CLIENT_12_025: [ If the Client initialization failed the function shall clean up the all resources and return NULL. ] */
+                    LogError("Prov_Device_LL_Create failed");
+                    free(result);
+                    result = NULL;
+                }
+                else
+                {
+                    /* Codes_SRS_PROV_DEVICE_CLIENT_12_007: [ The function shall initialize the result datastructure. ] */
+                    result->ThreadHandle = NULL;
+                    result->StopThread = 0;
+                    result->do_work_freq_ms = DO_WORK_FREQ_DEFAULT;
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+void Prov_Device_Destroy(PROV_DEVICE_HANDLE prov_device_handle)
+{
+    /* Codes_SRS_PROV_DEVICE_CLIENT_12_008: [ If the input parameter is NULL `Prov_Device_Destroy` shall return. ] */
+    if (prov_device_handle == NULL)
+    {
+        LogError("NULL prov_device_handle");
+    }
+    else
+    {
+        PROV_DEVICE_INSTANCE* prov_device_instance = (PROV_DEVICE_INSTANCE*)prov_device_handle;
+
+        if (Lock(prov_device_handle->LockHandle) != LOCK_OK)
+        {
+            /* Codes_SRS_PROV_DEVICE_CLIENT_12_009: [ The function shall check the Lock status and if it is not OK set the thread signal to stop. ] */
+            LogError("Could not acquire lock");
+            prov_device_handle->StopThread = 1; /*setting it even when Lock fails*/
+        }
+        else
+        {
+            /* Codes_SRS_PROV_DEVICE_CLIENT_12_010: [ The function shall check the Lock status and if it is OK set the thread signal to stop and unlock the Lock. ] */
+            prov_device_handle->StopThread = 1;
+
+            (void)Unlock(prov_device_handle->LockHandle);
+        }
+
+        /* Codes_SRS_PROV_DEVICE_CLIENT_12_011: [ If there is a running worker thread the function shall call join to finish. ] */
+        if (prov_device_handle->ThreadHandle != NULL)
+        {
+            int res;
+            if (ThreadAPI_Join(prov_device_handle->ThreadHandle, &res) != THREADAPI_OK)
+            {
+                LogError("ThreadAPI_Join failed");
+            }
+        }
+
+        /* Codes_SRS_PROV_DEVICE_CLIENT_12_012: [ The function shall call the LL layer Prov_Device_LL_Destroy with the given handle. ] */
+        Prov_Device_LL_Destroy(prov_device_instance->ProvDeviceLLHandle);
+
+        /* Codes_SRS_PROV_DEVICE_CLIENT_12_013: [ The function shall free the Lock resource with de-init. ] */
+        Lock_Deinit(prov_device_instance->LockHandle);
+
+        /* Codes_SRS_PROV_DEVICE_CLIENT_12_014: [ The function shall free the device handle resource. ] */
+        free(prov_device_instance);
+    }
+}
+
+PROV_DEVICE_RESULT Prov_Device_Register_Device(PROV_DEVICE_HANDLE prov_device_handle, PROV_DEVICE_CLIENT_REGISTER_DEVICE_CALLBACK register_callback, void* user_context, PROV_DEVICE_CLIENT_REGISTER_STATUS_CALLBACK register_status_callback, void* status_user_context)
+{
+    PROV_DEVICE_RESULT result;
+
+    /* Codes_SRS_PROV_DEVICE_CLIENT_12_015: [ If the prov_device_handle or register_callback input parameter is NULL `Prov_Device_Register_Device` shall return with invalid argument error. ] */
+    if (prov_device_handle == NULL || register_callback == NULL)
+    {
+        LogError("Invalid parameter specified prov_device_handle: %p, register_callback: %p", prov_device_handle, register_callback);
+        result = PROV_DEVICE_RESULT_INVALID_ARG;
+    }
+    else
+    {
+        PROV_DEVICE_INSTANCE* prov_device_instance = (PROV_DEVICE_INSTANCE*)prov_device_handle;
+
+        /* Codes_SRS_PROV_DEVICE_CLIENT_12_018: [ The function shall try to lock the Lock. ] */
+        if (Lock(prov_device_instance->LockHandle) != LOCK_OK)
+        {
+            /* Codes_SRS_PROV_DEVICE_CLIENT_12_019: [ If the locking failed the function shall return with error. ] */
+            LogError("Could not acquire lock");
+            result = PROV_DEVICE_RESULT_ERROR;
+        }
+        else
+        {
+            /* Codes_SRS_PROV_DEVICE_CLIENT_12_020: [ The function shall call the LL layer Prov_Device_LL_Register_Device with the given parameters and return with the result. ] */
+            result = Prov_Device_LL_Register_Device(prov_device_instance->ProvDeviceLLHandle, register_callback, user_context, register_status_callback, status_user_context);
+
+            /* Codes_SRS_PROV_DEVICE_CLIENT_12_021: [ The function shall unlock the Lock. ] */
+            (void)Unlock(prov_device_instance->LockHandle);
+
+            if (result == PROV_DEVICE_RESULT_OK)
+            {
+                /* Codes_SRS_PROV_DEVICE_CLIENT_12_016: [ The function shall start a worker thread with the device instance. ] */
+                if ((result = StartWorkerThreadIfNeeded(prov_device_instance)) != PROV_DEVICE_RESULT_OK)
+                {
+                    /* Codes_SRS_PROV_DEVICE_CLIENT_12_017: [ If the thread initialization failed the function shall return error. ] */
+                    LogError("Could not start worker thread");
+                    result = PROV_DEVICE_RESULT_ERROR;
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+PROV_DEVICE_RESULT Prov_Device_SetOption(PROV_DEVICE_HANDLE prov_device_handle, const char* optionName, const void* value)
+{
+    PROV_DEVICE_RESULT result;
+
+    /* Codes_SRS_PROV_DEVICE_CLIENT_12_022: [ If any of the input parameter is NULL `Prov_Device_SetOption` shall return with invalid argument error. ] */
+    if (
+        (prov_device_handle == NULL) || 
+        (optionName == NULL) || 
+        (value == NULL)
+        )
+    {
+        result = PROV_DEVICE_RESULT_INVALID_ARG;
+        LogError("Invalid parameter specified prov_device_handle: %p, optionName: %p, value: %p", prov_device_handle, optionName, value);
+    }
+    else 
+    {
+        /* Codes_SRS_PROV_DEVICE_CLIENT_12_023: [ The function shall call the LL layer Prov_Device_LL_SetOption with the given parameters and return with the result. ] */
+        PROV_DEVICE_INSTANCE* prov_device_instance = (PROV_DEVICE_INSTANCE*)prov_device_handle;
+
+        /* Codes_SRS_PROV_DEVICE_CLIENT_41_002: [ `Prov_Device_SetOption` shall be made thread-safe by using the lock created in `Prov_Device_Create`. ] */
+        if (Lock(prov_device_instance->LockHandle) != LOCK_OK)
+        {
+            /* Codes_SRS_PROV_DEVICE_CLIENT_41_003: [ If acquiring the lock fails, `Prov_Device_SetOption` shall return `IOTHUB_CLIENT_ERROR`. ] */
+            result = PROV_DEVICE_RESULT_ERROR;
+            LogError("Could not acquire lock");
+        }
+        else 
+        {
+            /* Codes_SRS_PROV_DEVICE_CLIENT_41_001: [ If parameter `optionName` is `OPTION_DO_WORK_FREQUENCY_IN_MS` then `IoTHubClientCore_SetOption` shall set `do_work_freq_ms` parameter of `prov_device_instance` ] */
+            if (strcmp(OPTION_DO_WORK_FREQUENCY_IN_MS, optionName) == 0)
+            {
+                prov_device_instance->do_work_freq_ms = *((uint16_t *)value);
+                result = PROV_DEVICE_RESULT_OK;  
+            }
+            else 
+            {
+                result = Prov_Device_LL_SetOption(prov_device_instance->ProvDeviceLLHandle, optionName, value);
+                if (result != PROV_DEVICE_RESULT_OK)
+                {
+                    LogError("Prov_Device_LL_SetOption failed");
+                }
+            }
+            (void)Unlock(prov_device_instance->LockHandle);
+        }
+    }
+    return result;
+}
+
+const char* Prov_Device_GetVersionString(void)
+{
+    /* Codes_SRS_PROV_DEVICE_CLIENT_12_024: [ The function shall call the LL layer Prov_Device_LL_GetVersionString and return with the result. ] */
+    return Prov_Device_LL_GetVersionString();
+}
+
+PROV_DEVICE_RESULT Prov_Device_Set_Provisioning_Payload(PROV_DEVICE_HANDLE handle, const char* json)
+{
+    PROV_DEVICE_RESULT result;
+    if (handle == NULL)
+    {
+        LogError("Invalid parameter specified handle: %p", handle);
+        result = PROV_DEVICE_RESULT_INVALID_ARG;
+    }
+    else
+    {
+        result = Prov_Device_LL_Set_Provisioning_Payload(handle->ProvDeviceLLHandle, json);
+    }
+    return result;
+}
+
+const char* Prov_Device_Get_Provisioning_Payload(PROV_DEVICE_HANDLE handle)
+{
+    const char* result;
+    if (handle == NULL)
+    {
+        LogError("Invalid parameter specified handle: %p", handle);
+        result = NULL;
+    }
+    else
+    {
+        result = Prov_Device_LL_Get_Provisioning_Payload(handle->ProvDeviceLLHandle);
+    }
+    return result;
+}
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/prov_device_ll_client.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/prov_device_ll_client.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/prov_device_ll_client.c	(revision 453)
@@ -0,0 +1,1391 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "parson.h"
+
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/strings.h"
+#include "azure_c_shared_utility/buffer_.h"
+#include "azure_c_shared_utility/uniqueid.h"
+#include "azure_c_shared_utility/sastoken.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/azure_base64.h"
+#include "azure_c_shared_utility/urlencode.h"
+#include "azure_c_shared_utility/shared_util_options.h"
+#include "azure_c_shared_utility/tickcounter.h"
+
+#include "azure_prov_client/internal/prov_auth_client.h"
+#include "azure_prov_client/internal/prov_transport_private.h"
+#include "azure_prov_client/prov_device_ll_client.h"
+#include "azure_prov_client/prov_client_const.h"
+
+static const char* const OPTION_LOG_TRACE = "logtrace";
+
+static const char* const JSON_NODE_STATUS = "status";
+static const char* const JSON_NODE_REG_STATUS = "registrationState";
+static const char* const JSON_NODE_AUTH_KEY = "authenticationKey";
+static const char* const JSON_NODE_DEVICE_ID = "deviceId";
+static const char* const JSON_NODE_KEY_NAME = "keyName";
+static const char* const JSON_NODE_OPERATION_ID = "operationId";
+static const char* const JSON_NODE_ASSIGNED_HUB = "assignedHub";
+static const char* const JSON_NODE_TPM_NODE = "tpm";
+static const char* const JSON_NODE_DATE_TIME = "lastUpdatedDateTimeUtc";
+static const char* const JSON_NODE_ERROR_MSG = "errorMessage";
+static const char* const JSON_NODE_ERROR_CODE = "errorCode";
+static const char* const PROV_FAILED_STATUS = "failed";
+static const char* const PROV_BLACKLISTED_STATUS = "blacklisted";
+static const char* const JSON_CUSTOM_DATA_TAG = "payload";
+static const char* const JSON_NODE_RETURNED_DATA = "payload";
+
+static const char* const SAS_TOKEN_SCOPE_FMT = "%s/registrations/%s";
+
+static const char* const REGISTRATION_ID = "registrationId";
+static const char* const JSON_ENDORSMENT_KEY_NODE = "endorsementKey";
+static const char* const JSON_STORAGE_ROOT_KEY_NODE = "storageRootKey";
+
+#define DPS_HUB_ERROR_NO_HUB        400208
+#define DPS_HUB_ERROR_UNAUTH        400209
+
+#define SAS_TOKEN_DEFAULT_LIFETIME  2400
+#define EPOCH_TIME_T_VALUE          (time_t)0
+#define MAX_AUTH_ATTEMPTS           3
+#define PROV_DEFAULT_TIMEOUT        60
+
+typedef enum CLIENT_STATE_TAG
+{
+    CLIENT_STATE_READY,
+
+    CLIENT_STATE_REGISTER_SEND,
+    CLIENT_STATE_REGISTER_SENT,
+    CLIENT_STATE_REGISTER_RECV,
+
+    CLIENT_STATE_STATUS_SEND,
+    CLIENT_STATE_STATUS_SENT,
+    CLIENT_STATE_STATUS_RECV,
+
+    CLIENT_STATE_ERROR
+} CLIENT_STATE;
+
+typedef struct IOTHUB_REQ_INFO_TAG
+{
+    char* iothub_url;
+    char* iothub_key;
+    char* device_id;
+} IOTHUB_REQ_INFO;
+
+typedef struct PROV_INSTANCE_INFO_TAG
+{
+    PROV_DEVICE_CLIENT_REGISTER_DEVICE_CALLBACK register_callback;
+    void* user_context;
+    PROV_DEVICE_CLIENT_REGISTER_STATUS_CALLBACK register_status_cb;
+    void* status_user_ctx;
+    PROV_DEVICE_RESULT error_reason;
+
+    const PROV_DEVICE_TRANSPORT_PROVIDER* prov_transport_protocol;
+    PROV_DEVICE_TRANSPORT_HANDLE transport_handle;
+    bool transport_open;
+
+    TICK_COUNTER_HANDLE tick_counter;
+
+    tickcounter_ms_t status_throttle;
+    tickcounter_ms_t timeout_value;
+    uint32_t retry_after_value;
+
+    uint8_t prov_timeout;
+
+    char* registration_id;
+    bool user_supplied_reg_id;
+
+    PROV_AUTH_HANDLE prov_auth_handle;
+
+    bool is_connected;
+
+    PROV_AUTH_TYPE hsm_type;
+
+    IOTHUB_REQ_INFO iothub_info;
+
+    CLIENT_STATE prov_state;
+
+    size_t auth_attempts_made;
+
+    char* scope_id;
+
+    char* custom_request_data;
+    char* custom_response_data;
+} PROV_INSTANCE_INFO;
+
+static char* prov_transport_challenge_callback(const unsigned char* nonce, size_t nonce_len, const char* key_name, void* user_ctx)
+{
+    char* result;
+    if (user_ctx == NULL)
+    {
+        LogError("Bad argument user_ctx is NULL");
+        result = NULL;
+    }
+    else
+    {
+        PROV_INSTANCE_INFO* prov_info = (PROV_INSTANCE_INFO*)user_ctx;
+        if ((prov_info->hsm_type == PROV_AUTH_TYPE_TPM) && nonce == NULL)
+        {
+            LogError("Bad argument nonce is NULL");
+            result = NULL;
+        }
+        else
+        {
+            char* token_scope;
+            size_t token_scope_len;
+
+            size_t sec_since_epoch = (size_t)(difftime(get_time(NULL), EPOCH_TIME_T_VALUE) + 0);
+            size_t expiry_time = sec_since_epoch + SAS_TOKEN_DEFAULT_LIFETIME;
+
+            // Construct Token scope
+            token_scope_len = strlen(SAS_TOKEN_SCOPE_FMT) + strlen(prov_info->scope_id) + strlen(prov_info->registration_id);
+
+            token_scope = malloc(token_scope_len + 1);
+            if (token_scope == NULL)
+            {
+                LogError("Failure to allocate token scope");
+                result = NULL;
+            }
+            else if (sprintf(token_scope, SAS_TOKEN_SCOPE_FMT, prov_info->scope_id, prov_info->registration_id) <= 0)
+            {
+                LogError("Failure to constructing token_scope");
+                free(token_scope);
+                result = NULL;
+            }
+            else
+            {
+                STRING_HANDLE encoded_token = URL_EncodeString(token_scope);
+                if (encoded_token == NULL)
+                {
+                    LogError("Failure to url encoding string");
+                    result = NULL;
+                }
+                else
+                {
+                    if (prov_info->hsm_type == PROV_AUTH_TYPE_TPM && (prov_auth_import_key(prov_info->prov_auth_handle, nonce, nonce_len) != 0))
+                    {
+                        LogError("Failure to import the provisioning key");
+                        result = NULL;
+                    }
+                    else
+                    {
+                        if ((result = prov_auth_construct_sas_token(prov_info->prov_auth_handle, STRING_c_str(encoded_token), key_name, expiry_time)) == NULL)
+                        {
+                            LogError("Failure to import the provisioning key");
+                            result = NULL;
+                        }
+                    }
+                    STRING_delete(encoded_token);
+                }
+                free(token_scope);
+            }
+        }
+    }
+    return result;
+}
+
+static void on_transport_error(PROV_DEVICE_TRANSPORT_ERROR transport_error, void* user_ctx)
+{
+    if (user_ctx != NULL)
+    {
+        PROV_INSTANCE_INFO* prov_info = (PROV_INSTANCE_INFO*)user_ctx;
+        switch (transport_error)
+        {
+            case PROV_DEVICE_ERROR_KEY_FAIL:
+                prov_info->error_reason = PROV_DEVICE_RESULT_KEY_ERROR;
+                break;
+            case PROV_DEVICE_ERROR_KEY_UNAUTHORIZED:
+                prov_info->error_reason = PROV_DEVICE_RESULT_DEV_AUTH_ERROR;
+                break;
+
+            case PROV_DEVICE_ERROR_MEMORY:
+                prov_info->error_reason = PROV_DEVICE_RESULT_MEMORY;
+                break;
+        }
+    }
+}
+
+static PROV_DEVICE_TRANSPORT_STATUS retrieve_status_type(const char* prov_status)
+{
+    PROV_DEVICE_TRANSPORT_STATUS result;
+    if (strcmp(prov_status, PROV_UNASSIGNED_STATUS) == 0)
+    {
+        result = PROV_DEVICE_TRANSPORT_STATUS_UNASSIGNED;
+    }
+    else if (strcmp(prov_status, PROV_ASSIGNING_STATUS) == 0)
+    {
+        result = PROV_DEVICE_TRANSPORT_STATUS_ASSIGNING;
+    }
+    else if (strcmp(prov_status, PROV_ASSIGNED_STATUS) == 0)
+    {
+        result = PROV_DEVICE_TRANSPORT_STATUS_ASSIGNED;
+    }
+    else if (strcmp(prov_status, PROV_FAILED_STATUS) == 0)
+    {
+        result = PROV_DEVICE_TRANSPORT_STATUS_ERROR;
+    }
+    else if (strcmp(prov_status, PROV_BLACKLISTED_STATUS) == 0)
+    {
+        result = PROV_DEVICE_TRANSPORT_STATUS_BLACKLISTED;
+    }
+    else if (strcmp(prov_status, PROV_DISABLE_STATUS) == 0)
+    {
+        result = PROV_DEVICE_TRANSPORT_STATUS_DISABLED;
+    }
+    else
+    {
+        result = PROV_DEVICE_TRANSPORT_STATUS_ERROR;
+    }
+    return result;
+}
+
+static int retrieve_json_number(JSON_Object* json_object, const char* field_name)
+{
+    int result;
+    JSON_Value* json_field;
+    if ((json_field = json_object_get_value(json_object, field_name)) == NULL)
+    {
+        LogError("failure retrieving json operation id");
+        result = 0;
+    }
+    else
+    {
+        result = (int)json_value_get_number(json_field);
+    }
+    return result;
+}
+
+static void retrieve_json_payload(JSON_Object* json_object, PROV_INSTANCE_INFO* prov_info)
+{
+    JSON_Value* json_field;
+
+    // Returned Data is not available
+    if ((json_field = json_object_get_value(json_object, JSON_NODE_RETURNED_DATA)) != NULL)
+    {
+        prov_info->custom_response_data = json_serialize_to_string(json_field);
+    }
+}
+
+static char* retrieve_json_string(JSON_Object* json_object, const char* field_name, bool is_required)
+{
+    char* result;
+    JSON_Value* json_field;
+    if ((json_field = json_object_get_value(json_object, field_name)) == NULL)
+    {
+        if (is_required)
+        {
+            LogError("failure retrieving json object value %s", field_name);
+        }
+        result = NULL;
+    }
+    else
+    {
+        const char* json_item = json_value_get_string(json_field);
+        if (json_item != NULL)
+        {
+            if (mallocAndStrcpy_s(&result, json_item) != 0)
+            {
+                LogError("failure retrieving operation id");
+                result = NULL;
+            }
+        }
+        else
+        {
+            result = NULL;
+        }
+    }
+    return result;
+}
+
+static JSON_Value* construct_security_type_json(PROV_INSTANCE_INFO* prov_info, const char* ek_value, const char* srk_value)
+{
+    JSON_Value* result;
+
+    JSON_Object* json_object;
+    result = json_value_init_object();
+    if (result == NULL)
+    {
+        LogError("Failure constructing json information");
+    }
+    else if ((json_object = json_value_get_object(result)) == NULL)
+    {
+        LogError("failure retrieving node root object");
+        json_value_free(result);
+        result = NULL;
+    }
+    else
+    {
+        if (json_object_set_string(json_object, REGISTRATION_ID, prov_info->registration_id) != JSONSuccess)
+        {
+            LogError("failure setting registration Id json node");
+            json_value_free(result);
+            result = NULL;
+        }
+        else
+        {
+            if (prov_info->hsm_type == PROV_AUTH_TYPE_TPM)
+            {
+                // tpm_node value only gets released on failure
+                JSON_Object* tpm_object;
+                JSON_Value* tpm_node = json_value_init_object();
+                if (tpm_node == NULL)
+                {
+                    LogError("failure constructing json tpm object");
+                    json_value_free(tpm_node);
+                    json_value_free(result);
+                    result = NULL;
+                }
+                else if ((tpm_object = json_value_get_object(tpm_node)) == NULL)
+                {
+                    LogError("failure retrieving node root object");
+                    json_value_free(tpm_node);
+                    json_value_free(result);
+                    result = NULL;
+                }
+                else if (json_object_set_string(tpm_object, JSON_ENDORSMENT_KEY_NODE, ek_value) != JSONSuccess)
+                {
+                    LogError("failure setting endorsement key node");
+                    json_value_free(tpm_node);
+                    json_value_free(result);
+                    result = NULL;
+                }
+                else if (json_object_set_string(tpm_object, JSON_STORAGE_ROOT_KEY_NODE, srk_value) != JSONSuccess)
+                {
+                    LogError("failure setting tpm storage root key node");
+                    json_value_free(tpm_node);
+                    json_value_free(result);
+                    result = NULL;
+                }
+                else if (json_object_set_value(json_object, JSON_NODE_TPM_NODE, tpm_node) != JSONSuccess)
+                {
+                    LogError("failure constructing json tpm object");
+                    json_value_free(tpm_node);
+                    json_value_free(result);
+                    result = NULL;
+                }
+            }
+        }
+    }
+    return result;
+}
+
+static char* prov_transport_create_json_payload(const char* ek_value, const char* srk_value, void* user_ctx)
+{
+    char* result = NULL;
+    if (user_ctx == NULL)
+    {
+        LogError("failure user_ctx is NULL");
+    }
+    else
+    {
+        PROV_INSTANCE_INFO* prov_info = (PROV_INSTANCE_INFO*)user_ctx;
+
+        JSON_Value* json_root = construct_security_type_json(prov_info, ek_value, srk_value);
+        if (json_root == NULL)
+        {
+            LogError("Failure constructing security json");
+        }
+        else
+        {
+            bool error_encountered = false;
+            if (prov_info->custom_request_data != NULL)
+            {
+                JSON_Object* json_object;
+                JSON_Value* json_custom_data = NULL;
+
+                if ((json_object = json_value_get_object(json_root)) == NULL)
+                {
+                    LogError("failure retrieving node root object");
+                    error_encountered = true;
+                }
+                else if ((json_custom_data = json_parse_string(prov_info->custom_request_data)) == NULL)
+                {
+                    LogError("failure parsing custom info.  This custom info MUST be valid json");
+                    error_encountered = true;
+                }
+                // Success on json_object_set_value transfers ownership of json_custom_data to json_object, so do not
+                // explicitly free json_custom_data after this point.
+                else if (json_object_set_value(json_object, JSON_CUSTOM_DATA_TAG, json_custom_data) != JSONSuccess)
+                {
+                    LogError("failure setting %s value", JSON_CUSTOM_DATA_TAG);
+                    json_value_free(json_custom_data);
+                    error_encountered = true;
+                }
+            }
+
+            if (!error_encountered)
+            {
+                char* json_string = json_serialize_to_string(json_root);
+                if (json_string == NULL)
+                {
+                    LogError("failure serializing json to string");
+                }
+                else
+                {
+                    if (mallocAndStrcpy_s(&result, json_string) != 0)
+                    {
+                        LogError("failure constructing json result value");
+                    }
+                    json_free_serialized_string(json_string);
+                }
+            }
+            json_value_free(json_root);
+        }
+    }
+
+    return result;
+}
+
+static PROV_JSON_INFO* prov_transport_process_json_reply(const char* json_document, void* user_ctx)
+{
+    PROV_JSON_INFO* result;
+    JSON_Value* root_value;
+    JSON_Object* json_object;
+    if (user_ctx == NULL)
+    {
+        LogError("failure user_ctx is NULL");
+        result = NULL;
+    }
+    else if ((root_value = json_parse_string(json_document)) == NULL)
+    {
+        LogError("failure calling json_parse_string");
+        result = NULL;
+    }
+    else if ((json_object = json_value_get_object(root_value)) == NULL)
+    {
+        LogError("failure retrieving node root object");
+        json_value_free(root_value);
+        result = NULL;
+    }
+    else if ((result = malloc(sizeof(PROV_JSON_INFO))) == NULL)
+    {
+        LogError("failure allocating PROV_JSON_INFO");
+        json_value_free(root_value);
+    }
+    else
+    {
+        memset(result, 0, sizeof(PROV_JSON_INFO));
+        PROV_INSTANCE_INFO* prov_info = (PROV_INSTANCE_INFO*)user_ctx;
+        JSON_Value* json_status = json_object_get_value(json_object, JSON_NODE_STATUS);
+
+        if (json_status == NULL)
+        {
+            // Under TPM the status will be error if this is an authorization request.  We need to make it unassigned.
+            if (prov_info->hsm_type == PROV_AUTH_TYPE_TPM)
+            {
+                result->prov_status = PROV_DEVICE_TRANSPORT_STATUS_UNASSIGNED;
+            }
+            else
+            {
+                result->prov_status = PROV_DEVICE_TRANSPORT_STATUS_ERROR;
+            }
+        }
+        else
+        {
+            // status can be NULL
+            const char* json_string = json_value_get_string(json_status);
+            if (json_string == NULL)
+            {
+                result->prov_status = PROV_DEVICE_TRANSPORT_STATUS_ERROR;
+            }
+            else
+            {
+                result->prov_status = retrieve_status_type(json_string);
+            }
+        }
+        switch (result->prov_status)
+        {
+            case PROV_DEVICE_TRANSPORT_STATUS_UNASSIGNED:
+            {
+                JSON_Value* auth_key;
+                if ((auth_key = json_object_get_value(json_object, JSON_NODE_AUTH_KEY)) == NULL)
+                {
+                    LogError("failure retrieving json auth key value");
+                    prov_info->error_reason = PROV_DEVICE_RESULT_PARSING;
+                    free(result);
+                    result = NULL;
+                }
+                else
+                {
+                    const char* nonce_field = json_value_get_string(auth_key);
+                    if ((result->authorization_key = Azure_Base64_Decode(nonce_field)) == NULL)
+                    {
+                        LogError("failure creating buffer nonce field");
+                        prov_info->error_reason = PROV_DEVICE_RESULT_MEMORY;
+                        free(result);
+                        result = NULL;
+                    }
+                    else
+                    {
+                        result->key_name = retrieve_json_string(json_object, JSON_NODE_KEY_NAME, true);
+                        if (result->key_name == NULL)
+                        {
+                            LogError("failure retrieving keyname field");
+                            prov_info->error_reason = PROV_DEVICE_RESULT_PARSING;
+                            BUFFER_delete(result->authorization_key);
+                            free(result);
+                            result = NULL;
+                        }
+                    }
+                }
+                break;
+            }
+
+            case PROV_DEVICE_TRANSPORT_STATUS_ASSIGNING:
+                if ((result->operation_id = retrieve_json_string(json_object, JSON_NODE_OPERATION_ID, true)) == NULL)
+                {
+                    LogError("Failure: operation_id node is mising");
+                    prov_info->error_reason = PROV_DEVICE_RESULT_PARSING;
+                    free(result);
+                    result = NULL;
+                }
+                break;
+
+            case PROV_DEVICE_TRANSPORT_STATUS_ASSIGNED:
+            {
+                JSON_Object* json_reg_status_node;
+                if ((json_reg_status_node = json_object_get_object(json_object, JSON_NODE_REG_STATUS)) == NULL)
+                {
+                    LogError("failure retrieving json registration status node");
+                    prov_info->error_reason = PROV_DEVICE_RESULT_PARSING;
+                    free(result);
+                    result = NULL;
+                }
+                else
+                {
+                    if (prov_info->hsm_type == PROV_AUTH_TYPE_TPM)
+                    {
+                        JSON_Object* json_tpm_node;
+                        JSON_Value* auth_key;
+
+                        if ((json_tpm_node = json_object_get_object(json_reg_status_node, JSON_NODE_TPM_NODE)) == NULL)
+                        {
+                            LogError("failure retrieving tpm node json_tpm_node: %p, auth key: %p", json_tpm_node, result->authorization_key);
+                            free(result);
+                            prov_info->error_reason = PROV_DEVICE_RESULT_PARSING;
+                            result = NULL;
+                        }
+                        else if ((auth_key = json_object_get_value(json_tpm_node, JSON_NODE_AUTH_KEY)) == NULL)
+                        {
+                            LogError("failure retrieving json auth key value");
+                            free(result);
+                            prov_info->error_reason = PROV_DEVICE_RESULT_PARSING;
+                            result = NULL;
+                        }
+                        else
+                        {
+                            const char* nonce_field = json_value_get_string(auth_key);
+                            if (nonce_field == NULL)
+                            {
+                                LogError("failure getting nonce field from json");
+                                prov_info->error_reason = PROV_DEVICE_RESULT_MEMORY;
+                                free(result);
+                                result = NULL;
+                            }
+                            else if ((result->authorization_key = Azure_Base64_Decode(nonce_field)) == NULL)
+                            {
+                                LogError("failure creating buffer nonce field");
+                                prov_info->error_reason = PROV_DEVICE_RESULT_MEMORY;
+                                free(result);
+                                result = NULL;
+                            }
+                        }
+                    }
+
+                    if (result != NULL)
+                    {
+                        if (
+                            ((result->iothub_uri = retrieve_json_string(json_reg_status_node, JSON_NODE_ASSIGNED_HUB, true)) == NULL) ||
+                            ((result->device_id = retrieve_json_string(json_reg_status_node, JSON_NODE_DEVICE_ID, true)) == NULL)
+                            )
+                        {
+                            LogError("failure retrieving json value assigned_hub: %p, device_id: %p", result->iothub_uri, result->device_id);
+                            prov_info->error_reason = PROV_DEVICE_RESULT_PARSING;
+                            free(result->iothub_uri);
+                            free(result->authorization_key);
+                            free(result);
+                            result = NULL;
+                        }
+                        else
+                        {
+                            // Get the returned Data from the payload if it's there
+                            retrieve_json_payload(json_reg_status_node, prov_info);
+                        }
+                    }
+                }
+                break;
+            }
+
+            case PROV_DEVICE_TRANSPORT_STATUS_BLACKLISTED:
+                LogError("The device is unauthorized with service");
+                prov_info->error_reason = PROV_DEVICE_RESULT_ERROR;
+                free(result);
+                result = NULL;
+                break;
+
+            case PROV_DEVICE_TRANSPORT_STATUS_ERROR:
+            {
+                char* json_operation_id = NULL;
+                JSON_Object* json_reg_state = NULL;
+                if ((json_reg_state = json_object_get_object(json_object, JSON_NODE_REG_STATUS)) != NULL &&
+                    (json_operation_id = retrieve_json_string(json_object, JSON_NODE_OPERATION_ID, true)) != NULL)
+                {
+                    int error_code = retrieve_json_number(json_reg_state, JSON_NODE_ERROR_CODE);
+                    switch (error_code)
+                    {
+                        case DPS_HUB_ERROR_NO_HUB:
+                            prov_info->error_reason = PROV_DEVICE_RESULT_HUB_NOT_SPECIFIED;
+                            break;
+                        case DPS_HUB_ERROR_UNAUTH:
+                            prov_info->error_reason = PROV_DEVICE_RESULT_UNAUTHORIZED;
+                            break;
+                        default:
+                            prov_info->error_reason = PROV_DEVICE_RESULT_DEV_AUTH_ERROR;
+                            break;
+                    }
+#ifndef NO_LOGGING
+                    JSON_Value* json_error_date_time = NULL;
+                    JSON_Value* json_error_msg = NULL;
+                    if ((json_error_msg = json_object_get_value(json_reg_state, JSON_NODE_ERROR_MSG)) != NULL &&
+                        (json_error_date_time = json_object_get_value(json_reg_state, JSON_NODE_DATE_TIME)) != NULL)
+                    {
+                        LogError("Provisioning Failure: OperationId: %s - Date: %s - Msg: %s", json_operation_id, json_value_get_string(json_error_date_time), json_value_get_string(json_error_msg) );
+                    }
+                    else
+                    {
+                        LogError("Unsuccessful json encountered: %s", json_document);
+                    }
+                    free(json_operation_id);
+#endif
+                }
+                else
+                {
+                    prov_info->error_reason = PROV_DEVICE_RESULT_DEV_AUTH_ERROR;
+                    LogError("Unsuccessful json encountered: %s", json_document);
+                }
+                free(result);
+                result = NULL;
+                break;
+            }
+
+            case PROV_DEVICE_TRANSPORT_STATUS_DISABLED:
+                LogError("The device has been disabled by DPS service");
+                prov_info->error_reason = PROV_DEVICE_RESULT_DISABLED;
+                free(result);
+                result = NULL;
+                break;
+
+            default:
+                LogError("invalid json status specified %d", result->prov_status);
+                free(result);
+                result = NULL;
+                break;
+        }
+        json_value_free(root_value);
+    }
+    return result;
+}
+
+static void cleanup_prov_info(PROV_INSTANCE_INFO* prov_info)
+{
+    if (prov_info->transport_open)
+    {
+        prov_info->prov_transport_protocol->prov_transport_close(prov_info->transport_handle);
+        prov_info->transport_open = false;
+        prov_info->is_connected = false;
+    }
+    free(prov_info->registration_id);
+    prov_info->registration_id = NULL;
+    free(prov_info->iothub_info.device_id);
+    prov_info->iothub_info.device_id = NULL;
+    free(prov_info->iothub_info.iothub_key);
+    prov_info->iothub_info.iothub_key = NULL;
+    free(prov_info->iothub_info.iothub_url);
+    prov_info->iothub_info.iothub_url = NULL;
+    prov_info->auth_attempts_made = 0;
+}
+
+static void on_transport_registration_data(PROV_DEVICE_TRANSPORT_RESULT transport_result, BUFFER_HANDLE iothub_key, const char* assigned_hub, const char* device_id, void* user_ctx)
+{
+    if (user_ctx == NULL)
+    {
+        LogError("user context was unexpectantly NULL");
+    }
+    else
+    {
+        PROV_INSTANCE_INFO* prov_info = (PROV_INSTANCE_INFO*)user_ctx;
+        if (transport_result == PROV_DEVICE_TRANSPORT_RESULT_OK)
+        {
+            if (prov_info->hsm_type == PROV_AUTH_TYPE_TPM)
+            {
+                if (iothub_key == NULL)
+                {
+                    prov_info->prov_state = CLIENT_STATE_ERROR;
+                    if (prov_info->error_reason == PROV_DEVICE_RESULT_OK)
+                    {
+                        prov_info->error_reason = PROV_DEVICE_RESULT_KEY_ERROR;
+                    }
+                    LogError("invalid iothub device key");
+                }
+                else
+                {
+                    const unsigned char* key_value = BUFFER_u_char(iothub_key);
+                    size_t key_len = BUFFER_length(iothub_key);
+
+                    /* Codes_SRS_SECURE_ENCLAVE_CLIENT_07_028: [ prov_auth_import_key shall import the specified key into the tpm using secure_device_import_key secure enclave function. ] */
+                    if (prov_auth_import_key(prov_info->prov_auth_handle, key_value, key_len) != 0)
+                    {
+                        prov_info->prov_state = CLIENT_STATE_ERROR;
+                        prov_info->error_reason = PROV_DEVICE_RESULT_KEY_ERROR;
+                        LogError("Failure to import the provisioning key");
+                    }
+                }
+            }
+
+            if (prov_info->prov_state != CLIENT_STATE_ERROR)
+            {
+                prov_info->register_callback(PROV_DEVICE_RESULT_OK, assigned_hub, device_id, prov_info->user_context);
+                prov_info->prov_state = CLIENT_STATE_READY;
+                cleanup_prov_info(prov_info);
+            }
+        }
+        else if (transport_result == PROV_DEVICE_TRANSPORT_RESULT_UNAUTHORIZED)
+        {
+            prov_info->prov_state = CLIENT_STATE_ERROR;
+            prov_info->error_reason = PROV_DEVICE_RESULT_DEV_AUTH_ERROR;
+            LogError("provisioning result is unauthorized");
+        }
+        else
+        {
+            prov_info->prov_state = CLIENT_STATE_ERROR;
+            if (prov_info->error_reason == PROV_DEVICE_RESULT_OK)
+            {
+                prov_info->error_reason = PROV_DEVICE_RESULT_TRANSPORT;
+            }
+            LogError("Failure retrieving data from the provisioning service");
+        }
+    }
+}
+
+static void on_transport_status(PROV_DEVICE_TRANSPORT_STATUS transport_status, uint32_t retry_interval, void* user_ctx)
+{
+    if (user_ctx == NULL)
+    {
+        LogError("user_ctx was unexpectatly NULL");
+    }
+    else
+    {
+        PROV_INSTANCE_INFO* prov_info = (PROV_INSTANCE_INFO*)user_ctx;
+
+        prov_info->retry_after_value = retry_interval;
+
+        switch (transport_status)
+        {
+            case PROV_DEVICE_TRANSPORT_STATUS_CONNECTED:
+                prov_info->is_connected = true;
+                if (prov_info->register_status_cb != NULL)
+                {
+                    prov_info->register_status_cb(PROV_DEVICE_REG_STATUS_CONNECTED, prov_info->status_user_ctx);
+                }
+                break;
+            case PROV_DEVICE_TRANSPORT_STATUS_AUTHENTICATED:
+            case PROV_DEVICE_TRANSPORT_STATUS_ASSIGNING:
+            case PROV_DEVICE_TRANSPORT_STATUS_UNASSIGNED:
+                prov_info->prov_state = CLIENT_STATE_STATUS_SEND;
+                if (transport_status == PROV_DEVICE_TRANSPORT_STATUS_UNASSIGNED)
+                {
+                    if (prov_info->register_status_cb != NULL)
+                    {
+                        prov_info->register_status_cb(PROV_DEVICE_REG_STATUS_REGISTERING, prov_info->status_user_ctx);
+                    }
+                }
+                else if (transport_status == PROV_DEVICE_TRANSPORT_STATUS_ASSIGNING)
+                {
+                    if (prov_info->register_status_cb != NULL)
+                    {
+                        prov_info->register_status_cb(PROV_DEVICE_REG_STATUS_ASSIGNING, prov_info->status_user_ctx);
+                    }
+                }
+                break;
+            case PROV_DEVICE_TRANSPORT_STATUS_TRANSIENT:
+                if (prov_info->prov_state == CLIENT_STATE_REGISTER_SENT)
+                {
+                    prov_info->prov_state = CLIENT_STATE_REGISTER_SEND;
+                }
+                else if (prov_info->prov_state == CLIENT_STATE_STATUS_SENT)
+                {
+                    prov_info->prov_state = CLIENT_STATE_STATUS_SEND;
+                }
+                else
+                {
+                    // Ideally this should not happen
+                    LogError("State Error: Transient Error occured in the %d state", (int)transport_status);
+                }
+                break;
+            default:
+                LogError("Unknown status encountered");
+                break;
+        }
+    }
+}
+
+static void destroy_instance(PROV_INSTANCE_INFO* prov_info)
+{
+    cleanup_prov_info(prov_info);
+    // Clean custom request data
+    free(prov_info->custom_request_data);
+    prov_info->custom_request_data = NULL;
+    if (prov_info->custom_response_data != NULL)
+    {
+        json_free_serialized_string(prov_info->custom_response_data);
+        prov_info->custom_response_data = NULL;
+    }
+    prov_info->prov_transport_protocol->prov_transport_destroy(prov_info->transport_handle);
+    prov_info->transport_handle = NULL;
+    free(prov_info->scope_id);
+    prov_auth_destroy(prov_info->prov_auth_handle);
+    tickcounter_destroy(prov_info->tick_counter);
+    free(prov_info);
+}
+
+PROV_DEVICE_LL_HANDLE Prov_Device_LL_Create(const char* uri, const char* id_scope, PROV_DEVICE_TRANSPORT_PROVIDER_FUNCTION protocol)
+{
+    PROV_INSTANCE_INFO* result;
+    /* Codes_SRS_PROV_CLIENT_07_001: [If uri is NULL Prov_Device_LL_CreateFromUri shall return NULL.] */
+    if (uri == NULL || id_scope == NULL || protocol == NULL)
+    {
+        LogError("Invalid parameter specified uri: %p, id_scope: %p, protocol: %p", uri, id_scope, protocol);
+        result = NULL;
+    }
+    else
+    {
+        srand((unsigned int)get_time(NULL));
+
+        /* Codes_SRS_PROV_CLIENT_07_002: [ Prov_Device_LL_CreateFromUri shall allocate a PROV_DEVICE_LL_HANDLE and initialize all members. ] */
+        result = (PROV_INSTANCE_INFO*)malloc(sizeof(PROV_INSTANCE_INFO));
+        if (result == NULL)
+        {
+            LogError("unable to allocate Instance Info");
+        }
+        else
+        {
+            memset(result, 0, sizeof(PROV_INSTANCE_INFO));
+
+            /* Codes_SRS_PROV_CLIENT_07_028: [ CLIENT_STATE_READY is the initial state after the object is created which will send a uhttp_client_open call to the http endpoint. ] */
+            result->prov_state = CLIENT_STATE_READY;
+            result->retry_after_value = PROV_GET_THROTTLE_TIME;
+            result->prov_transport_protocol = protocol();
+            result->error_reason = PROV_DEVICE_RESULT_OK;
+
+            /* Codes_SRS_PROV_CLIENT_07_034: [ Prov_Device_LL_Create shall construct a id_scope by base64 encoding the uri. ] */
+            if (mallocAndStrcpy_s(&result->scope_id, id_scope) != 0)
+            {
+                /* Codes_SRS_PROV_CLIENT_07_003: [ If any error is encountered, Prov_Device_LL_CreateFromUri shall return NULL. ] */
+                LogError("failed to construct id_scope");
+                free(result);
+                result = NULL;
+            }
+            else if ((result->prov_auth_handle = prov_auth_create()) == NULL)
+            {
+                /* Codes_SRS_PROV_CLIENT_07_003: [ If any error is encountered, Prov_Device_LL_CreateFromUri shall return NULL. ] */
+                LogError("failed calling prov_auth_create\r\n");
+                destroy_instance(result);
+                result = NULL;
+            }
+            else if ((result->tick_counter = tickcounter_create()) == NULL)
+            {
+                LogError("failure: allocating tickcounter");
+                destroy_instance(result);
+                result = NULL;
+            }
+            else
+            {
+                TRANSPORT_HSM_TYPE hsm_type;
+                if ((result->hsm_type = prov_auth_get_type(result->prov_auth_handle)) == PROV_AUTH_TYPE_TPM)
+                {
+                    hsm_type = TRANSPORT_HSM_TYPE_TPM;
+                }
+                else if (result->hsm_type == PROV_AUTH_TYPE_KEY)
+                {
+                    hsm_type = TRANSPORT_HSM_TYPE_SYMM_KEY;
+                }
+                else
+                {
+                    hsm_type = TRANSPORT_HSM_TYPE_X509;
+                }
+
+                if ((result->transport_handle = result->prov_transport_protocol->prov_transport_create(uri, hsm_type, result->scope_id, PROV_API_VERSION, on_transport_error, result)) == NULL)
+                {
+                    /* Codes_SRS_PROV_CLIENT_07_003: [ If any error is encountered, Prov_Device_LL_CreateFromUri shall return NULL. ] */
+                    LogError("failed calling into transport create");
+                    destroy_instance(result);
+                    result = NULL;
+                }
+                else
+                {
+                    // Ensure that we are passed the throttling time and send on the first send
+                    (void)tickcounter_get_current_ms(result->tick_counter, &result->status_throttle);
+                    result->status_throttle += (result->retry_after_value * 1000);
+                }
+            }
+        }
+    }
+    return (PROV_DEVICE_LL_HANDLE)result;
+}
+
+void Prov_Device_LL_Destroy(PROV_DEVICE_LL_HANDLE handle)
+{
+    /* Codes_SRS_PROV_CLIENT_07_005: [ If handle is NULL Prov_Device_LL_Destroy shall do nothing. ] */
+    if (handle != NULL)
+    {
+        /* Codes_SRS_PROV_CLIENT_07_006: [ Prov_Device_LL_Destroy shall destroy resources associated with the IoTHub_client ] */
+        destroy_instance(handle);
+    }
+}
+
+PROV_DEVICE_RESULT Prov_Device_LL_Register_Device(PROV_DEVICE_LL_HANDLE handle, PROV_DEVICE_CLIENT_REGISTER_DEVICE_CALLBACK register_callback, void* user_context, PROV_DEVICE_CLIENT_REGISTER_STATUS_CALLBACK reg_status_cb, void* status_ctx)
+{
+    PROV_DEVICE_RESULT result;
+    /* Codes_SRS_PROV_CLIENT_07_007: [ If handle or register_callback is NULL, Prov_Device_LL_Register_Device shall return PROV_CLIENT_INVALID_ARG. ] */
+    if (handle == NULL || register_callback == NULL)
+    {
+        LogError("Invalid parameter specified handle: %p register_callback: %p", handle, register_callback);
+        result = PROV_DEVICE_RESULT_INVALID_ARG;
+    }
+    /* Codes_SRS_PROV_CLIENT_07_035: [ Prov_Device_LL_Create shall store the registration_id from the security module. ] */
+    else if (handle->registration_id == NULL && (handle->registration_id = prov_auth_get_registration_id(handle->prov_auth_handle)) == NULL)
+    {
+        /* Codes_SRS_PROV_CLIENT_07_003: [ If any error is encountered, Prov_Device_LL_CreateFromUri shall return NULL. ] */
+        LogError("failure: Unable to retrieve registration Id from device auth.");
+        result = PROV_DEVICE_RESULT_ERROR;
+    }
+    else
+    {
+        BUFFER_HANDLE ek_value = NULL;
+        BUFFER_HANDLE srk_value = NULL;
+
+        if (handle->prov_state != CLIENT_STATE_READY)
+        {
+            LogError("state is invalid");
+            if (!handle->user_supplied_reg_id)
+            {
+                free(handle->registration_id);
+                handle->registration_id = NULL;
+            }
+            result = PROV_DEVICE_RESULT_ERROR;
+        }
+        else
+        {
+            if (handle->hsm_type == PROV_AUTH_TYPE_TPM)
+            {
+                if ((ek_value = prov_auth_get_endorsement_key(handle->prov_auth_handle)) == NULL)
+                {
+                    LogError("Could not get endorsement key from tpm");
+                    if (!handle->user_supplied_reg_id)
+                    {
+                        free(handle->registration_id);
+                        handle->registration_id = NULL;
+                    }
+                    result = PROV_DEVICE_RESULT_ERROR;
+                }
+                else if ((srk_value = prov_auth_get_storage_key(handle->prov_auth_handle)) == NULL)
+                {
+                    LogError("Could not get storage root key from tpm");
+                    if (!handle->user_supplied_reg_id)
+                    {
+                        free(handle->registration_id);
+                        handle->registration_id = NULL;
+                    }
+                    result = PROV_DEVICE_RESULT_ERROR;
+                    BUFFER_delete(ek_value);
+                }
+                else
+                {
+                    result = PROV_DEVICE_RESULT_OK;
+                }
+            }
+            else if (handle->hsm_type == PROV_AUTH_TYPE_X509)
+            {
+                char* x509_cert;
+                char* x509_private_key;
+                if ((x509_cert = prov_auth_get_certificate(handle->prov_auth_handle)) == NULL)
+                {
+                    LogError("Could not get the x509 certificate");
+                    if (!handle->user_supplied_reg_id)
+                    {
+                        free(handle->registration_id);
+                        handle->registration_id = NULL;
+                    }
+                    result = PROV_DEVICE_RESULT_ERROR;
+                }
+                else if ((x509_private_key = prov_auth_get_alias_key(handle->prov_auth_handle)) == NULL)
+                {
+                    LogError("Could not get the x509 alias key");
+                    if (!handle->user_supplied_reg_id)
+                    {
+                        free(handle->registration_id);
+                        handle->registration_id = NULL;
+                    }
+                    free(x509_cert);
+                    result = PROV_DEVICE_RESULT_ERROR;
+                }
+                else
+                {
+                    if (handle->prov_transport_protocol->prov_transport_x509_cert(handle->transport_handle, x509_cert, x509_private_key) != 0)
+                    {
+                        LogError("unable to set the x509 certificate information on transport");
+                        if (!handle->user_supplied_reg_id)
+                        {
+                            free(handle->registration_id);
+                            handle->registration_id = NULL;
+                        }
+                        result = PROV_DEVICE_RESULT_ERROR;
+                    }
+                    else
+                    {
+                        result = PROV_DEVICE_RESULT_OK;
+                    }
+                    free(x509_cert);
+                    free(x509_private_key);
+                }
+            }
+            else
+            {
+                result = PROV_DEVICE_RESULT_OK;
+            }
+        }
+        if (result == PROV_DEVICE_RESULT_OK)
+        {
+            /* Codes_SRS_PROV_CLIENT_07_008: [ Prov_Device_LL_Register_Device shall set the state to send the registration request to on subsequent DoWork calls. ] */
+            handle->register_callback = register_callback;
+            handle->user_context = user_context;
+
+            handle->register_status_cb = reg_status_cb;
+            handle->status_user_ctx = status_ctx;
+            
+            // Free the custom data if its been allocated
+            if (handle->custom_response_data != NULL)
+            {
+                json_free_serialized_string(handle->custom_response_data);
+                handle->custom_response_data = NULL;
+            }
+
+            if (handle->prov_transport_protocol->prov_transport_open(handle->transport_handle, handle->registration_id, ek_value, srk_value, on_transport_registration_data, handle, on_transport_status, handle, prov_transport_challenge_callback, handle) != 0)
+            {
+                LogError("Failure establishing  connection");
+                if (!handle->user_supplied_reg_id)
+                {
+                    free(handle->registration_id);
+                    handle->registration_id = NULL;
+                }
+                handle->register_callback = NULL;
+                handle->user_context = NULL;
+
+                handle->register_status_cb = NULL;
+                handle->status_user_ctx = NULL;
+                result = PROV_DEVICE_RESULT_ERROR;
+            }
+            else
+            {
+                handle->transport_open = true;
+                handle->prov_state = CLIENT_STATE_REGISTER_SEND;
+                /* Codes_SRS_PROV_CLIENT_07_009: [ Upon success Prov_Device_LL_Register_Device shall return PROV_CLIENT_OK. ] */
+                result = PROV_DEVICE_RESULT_OK;
+            }
+            BUFFER_delete(ek_value);
+            BUFFER_delete(srk_value);
+        }
+    }
+    return result;
+}
+
+void Prov_Device_LL_DoWork(PROV_DEVICE_LL_HANDLE handle)
+{
+    /* Codes_SRS_PROV_CLIENT_07_010: [ If handle is NULL, Prov_Device_LL_DoWork shall do nothing. ] */
+    if (handle != NULL)
+    {
+        PROV_INSTANCE_INFO* prov_info = (PROV_INSTANCE_INFO*)handle;
+        /* Codes_SRS_PROV_CLIENT_07_011: [ Prov_Device_LL_DoWork shall call the underlying http_client_dowork function ] */
+        if (prov_info->prov_state != CLIENT_STATE_ERROR)
+        {
+            prov_info->prov_transport_protocol->prov_transport_dowork(prov_info->transport_handle);
+        }
+        if (prov_info->is_connected || prov_info->prov_state == CLIENT_STATE_ERROR)
+        {
+            switch (prov_info->prov_state)
+            {
+                case CLIENT_STATE_REGISTER_SEND:
+                    /* Codes_SRS_PROV_CLIENT_07_013: [ CLIENT_STATE_REGISTER_SEND which shall construct an initial call to the service with endorsement information ] */
+                    if (prov_info->prov_transport_protocol->prov_transport_register(prov_info->transport_handle, prov_transport_process_json_reply, prov_transport_create_json_payload, prov_info) != 0)
+                    {
+                        LogError("Failure registering device");
+                        if (prov_info->error_reason == PROV_DEVICE_RESULT_OK)
+                        {
+                            prov_info->error_reason = PROV_DEVICE_RESULT_TRANSPORT;
+                        }
+                        prov_info->prov_state = CLIENT_STATE_ERROR;
+                    }
+                    else
+                    {
+                        (void)tickcounter_get_current_ms(prov_info->tick_counter, &prov_info->timeout_value);
+                        prov_info->prov_state = CLIENT_STATE_REGISTER_SENT;
+                    }
+                    break;
+
+                case CLIENT_STATE_STATUS_SEND:
+                {
+                    tickcounter_ms_t current_time = 0;
+                    if (tickcounter_get_current_ms(prov_info->tick_counter, &current_time) != 0)
+                    {
+                        LogError("Failure getting the current time");
+                        prov_info->error_reason = PROV_DEVICE_RESULT_ERROR;
+                        prov_info->prov_state = CLIENT_STATE_ERROR;
+                    }
+                    else
+                    {
+                        if ((current_time - prov_info->status_throttle) / 1000 > prov_info->retry_after_value)
+                        {
+                            /* Codes_SRS_PROV_CLIENT_07_026: [ Upon receiving the reply of the CLIENT_STATE_URL_REQ_SEND message from  iothub_client shall process the the reply of the CLIENT_STATE_URL_REQ_SEND state ] */
+                            if (prov_info->prov_transport_protocol->prov_transport_get_op_status(prov_info->transport_handle) != 0)
+                            {
+                                LogError("Failure sending operation status");
+                                if (prov_info->error_reason == PROV_DEVICE_RESULT_OK)
+                                {
+                                    prov_info->error_reason = PROV_DEVICE_RESULT_TRANSPORT;
+                                }
+                                prov_info->prov_state = CLIENT_STATE_ERROR;
+                            }
+                            else
+                            {
+                                prov_info->prov_state = CLIENT_STATE_STATUS_SENT;
+                                if (tickcounter_get_current_ms(prov_info->tick_counter, &prov_info->timeout_value) != 0)
+                                {
+                                    LogError("Failure getting the current time");
+                                    prov_info->error_reason = PROV_DEVICE_RESULT_ERROR;
+                                    prov_info->prov_state = CLIENT_STATE_ERROR;
+                                }
+                            }
+                            prov_info->status_throttle = current_time;
+                        }
+                    }
+                    break;
+                }
+
+                case CLIENT_STATE_REGISTER_SENT:
+                case CLIENT_STATE_STATUS_SENT:
+                {
+                    if (prov_info->prov_timeout > 0)
+                    {
+                        tickcounter_ms_t current_time = 0;
+                        (void)tickcounter_get_current_ms(prov_info->tick_counter, &current_time);
+                        if ((current_time - prov_info->timeout_value) / 1000 > prov_info->prov_timeout)
+                        {
+                            LogError("Timeout waiting for reply");
+                            prov_info->error_reason = PROV_DEVICE_RESULT_TIMEOUT;
+                            prov_info->prov_state = CLIENT_STATE_ERROR;
+                        }
+                    }
+                    break;
+                }
+
+                case CLIENT_STATE_READY:
+                    break;
+
+                case CLIENT_STATE_ERROR:
+                default:
+                    prov_info->register_callback(prov_info->error_reason, NULL, NULL, prov_info->user_context);
+                    prov_info->prov_state = CLIENT_STATE_READY;
+                    cleanup_prov_info(prov_info);
+                    break;
+            }
+        }
+        else
+        {
+            // Check the connection
+            if ((prov_info->prov_state != CLIENT_STATE_READY) && (prov_info->prov_timeout > 0))
+            {
+                tickcounter_ms_t current_time = 0;
+                (void)tickcounter_get_current_ms(prov_info->tick_counter, &current_time);
+                if ((current_time - prov_info->timeout_value) / 1000 > prov_info->prov_timeout)
+                {
+                    LogError("Timed out connecting to provisioning service");
+                    prov_info->error_reason = PROV_DEVICE_RESULT_TIMEOUT;
+                    prov_info->prov_state = CLIENT_STATE_ERROR;
+                }
+            }
+        }
+    }
+}
+
+PROV_DEVICE_RESULT Prov_Device_LL_SetOption(PROV_DEVICE_LL_HANDLE handle, const char* option_name, const void* value)
+{
+    PROV_DEVICE_RESULT result;
+    if (handle == NULL || option_name == NULL)
+    {
+        LogError("Invalid parameter specified handle: %p option_name: %p", handle, option_name);
+        result = PROV_DEVICE_RESULT_INVALID_ARG;
+    }
+    else
+    {
+        if (strcmp(option_name, OPTION_TRUSTED_CERT) == 0)
+        {
+            const char* cert_info = (const char*)value;
+            if (handle->prov_transport_protocol->prov_transport_trusted_cert(handle->transport_handle, cert_info) != 0)
+            {
+                result = PROV_DEVICE_RESULT_ERROR;
+                LogError("failure allocating certificate");
+            }
+            else
+            {
+                result = PROV_DEVICE_RESULT_OK;
+            }
+        }
+        else if (strcmp(OPTION_LOG_TRACE, option_name) == 0)
+        {
+            bool log_trace = *((bool*)value);
+            if (handle->prov_transport_protocol->prov_transport_set_trace(handle->transport_handle, log_trace) != 0)
+            {
+                result = PROV_DEVICE_RESULT_ERROR;
+                LogError("failure setting trace option");
+            }
+            else
+            {
+                result = PROV_DEVICE_RESULT_OK;
+            }
+        }
+        else if (strcmp(OPTION_HTTP_PROXY, option_name) == 0)
+        {
+            /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_001: [ If `option` is `proxy_data`, `value` shall be used as an `HTTP_PROXY_OPTIONS*`. ]*/
+            HTTP_PROXY_OPTIONS* proxy_options = (HTTP_PROXY_OPTIONS*)value;
+
+            if (handle->prov_transport_protocol->prov_transport_set_proxy(handle->transport_handle, proxy_options) != 0)
+            {
+                LogError("setting proxy options");
+                result = PROV_DEVICE_RESULT_ERROR;
+            }
+            else
+            {
+                result = PROV_DEVICE_RESULT_OK;
+            }
+        }
+        else if (strcmp(PROV_OPTION_TIMEOUT, option_name) == 0)
+        {
+            if (value == NULL)
+            {
+                LogError("setting proxy options");
+                result = PROV_DEVICE_RESULT_ERROR;
+            }
+            else
+            {
+                handle->prov_timeout = *((uint8_t*)value);
+                result = PROV_DEVICE_RESULT_OK;
+            }
+        }
+        else if (strcmp(PROV_REGISTRATION_ID, option_name) == 0)
+        {
+            if (handle->prov_state != CLIENT_STATE_READY)
+            {
+                LogError("registration id cannot be set after registration has begun");
+                result = PROV_DEVICE_RESULT_ERROR;
+            }
+            else if (value == NULL)
+            {
+                LogError("value must be set to the correct registration id");
+                result = PROV_DEVICE_RESULT_ERROR;
+            }
+            else
+            {
+                char* temp_reg;
+                if (mallocAndStrcpy_s(&temp_reg, (const char*)value) != 0)
+                {
+                    LogError("Failure allocating setting registration id");
+                    result = PROV_DEVICE_RESULT_ERROR;
+                }
+                else if (prov_auth_set_registration_id(handle->prov_auth_handle, temp_reg) != 0)
+                {
+                    LogError("Failure setting registration id");
+                    free(temp_reg);
+                    result = PROV_DEVICE_RESULT_ERROR;
+                }
+                else
+                {
+                    if (handle->registration_id != NULL)
+                    {
+                        free(handle->registration_id);
+                    }
+                    handle->registration_id = temp_reg;
+                    handle->user_supplied_reg_id = true;
+                    result = PROV_DEVICE_RESULT_OK;
+                }
+            }
+        }
+        else
+        {
+            if (handle->prov_transport_protocol->prov_transport_set_option(handle->transport_handle, option_name, value) != 0)
+            {
+                LogError("Failure in prov transport set option\n");
+                result = PROV_DEVICE_RESULT_ERROR;
+            }
+            else
+            {
+                result = PROV_DEVICE_RESULT_OK;
+            }
+        }
+    }
+    return result;
+}
+
+const char* Prov_Device_LL_GetVersionString(void)
+{
+    return PROV_DEVICE_CLIENT_VERSION;
+}
+
+PROV_DEVICE_RESULT Prov_Device_LL_Set_Provisioning_Payload(PROV_DEVICE_LL_HANDLE handle, const char* jsonDataField)
+{
+    PROV_DEVICE_RESULT result;
+    if (handle == NULL)
+    {
+        LogError("Invalid parameter specified handle: %p", handle);
+        result = PROV_DEVICE_RESULT_INVALID_ARG;
+    }
+    else
+    {
+        char* temp_data;
+        if (mallocAndStrcpy_s(&temp_data, jsonDataField) != 0)
+        {
+            LogError("Failure setting custom provisioning data");
+            result = PROV_DEVICE_RESULT_ERROR;
+        }
+        else
+        {
+            if (handle->custom_request_data != NULL)
+            {
+                free(handle->custom_request_data);
+            }
+            handle->custom_request_data = temp_data;
+            result = PROV_DEVICE_RESULT_OK;
+        }
+    }
+    return result;
+}
+
+const char* Prov_Device_LL_Get_Provisioning_Payload(PROV_DEVICE_LL_HANDLE handle)
+{
+    const char* result;
+    if (handle == NULL)
+    {
+        LogError("Invalid parameter specified handle: %p", handle);
+        result = NULL;
+    }
+    else
+    {
+        result = handle->custom_response_data;
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/prov_security_factory.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/prov_security_factory.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/prov_security_factory.c	(revision 453)
@@ -0,0 +1,184 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_prov_client/prov_security_factory.h"
+#include "azure_prov_client/iothub_security_factory.h"
+
+#include "hsm_client_data.h"
+
+static SECURE_DEVICE_TYPE g_device_hsm_type = SECURE_DEVICE_TYPE_UNKNOWN;
+static char* g_symm_key = NULL;
+static char* g_symm_key_reg_name = NULL;
+
+static IOTHUB_SECURITY_TYPE get_iothub_security_type(SECURE_DEVICE_TYPE sec_type)
+{
+    IOTHUB_SECURITY_TYPE ret;
+
+    switch (sec_type)
+    {
+#if defined(HSM_TYPE_SAS_TOKEN)  || defined(HSM_AUTH_TYPE_CUSTOM)
+        case SECURE_DEVICE_TYPE_TPM:
+            ret = IOTHUB_SECURITY_TYPE_SAS;
+            break;
+#endif
+
+#if defined(HSM_TYPE_X509) || defined(HSM_AUTH_TYPE_CUSTOM)
+        case SECURE_DEVICE_TYPE_X509:
+            ret = IOTHUB_SECURITY_TYPE_X509;
+            break;
+#endif
+
+#if defined(HSM_TYPE_SYMM_KEY) || defined(HSM_AUTH_TYPE_CUSTOM)
+        case SECURE_DEVICE_TYPE_SYMMETRIC_KEY:
+            ret = IOTHUB_SECURITY_TYPE_SYMMETRIC_KEY;
+            break;
+#endif
+
+#ifdef HSM_TYPE_HTTP_EDGE
+        case SECURE_DEVICE_TYPE_HTTP_EDGE:
+            ret = IOTHUB_SECURITY_TYPE_HTTP_EDGE;
+            break;
+#endif
+
+        default:
+            ret = IOTHUB_SECURITY_TYPE_UNKNOWN;
+            break;
+    }
+
+    return ret;
+}
+
+int prov_dev_security_init(SECURE_DEVICE_TYPE hsm_type)
+{
+    int result;
+
+    IOTHUB_SECURITY_TYPE security_type_from_caller = get_iothub_security_type(hsm_type);
+
+    if (security_type_from_caller == IOTHUB_SECURITY_TYPE_UNKNOWN)
+    {
+        LogError("HSM type %d is not supported on this SDK build", hsm_type);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        g_device_hsm_type = hsm_type;
+        IOTHUB_SECURITY_TYPE security_type_from_iot = iothub_security_type();
+        if (security_type_from_iot == IOTHUB_SECURITY_TYPE_UNKNOWN)
+        {
+            // Initialize iothub_security layer if not currently
+            result = iothub_security_init(security_type_from_caller);
+        }
+        else if (security_type_from_iot != security_type_from_caller)
+        {
+            LogError("Security HSM from caller %d (which maps to security type %d) does not match already specified security type %d", hsm_type, security_type_from_caller, security_type_from_iot);
+            result = MU_FAILURE;
+        }
+        else
+        {
+            result = 0;
+        }
+
+        if (result == 0)
+        {
+            result = initialize_hsm_system();
+        }
+    }
+    return result;
+}
+
+void prov_dev_security_deinit(void)
+{
+    if (g_symm_key != NULL)
+    {
+        free(g_symm_key);
+        g_symm_key = NULL;
+    }
+    if (g_symm_key_reg_name != NULL)
+    {
+        free(g_symm_key_reg_name);
+        g_symm_key_reg_name = NULL;
+    }
+    deinitialize_hsm_system();
+    if (iothub_security_get_symmetric_key() != NULL || iothub_security_get_symm_registration_name() != NULL)
+    {
+        // Clear out iothub info
+        iothub_security_deinit();
+    }
+}
+
+SECURE_DEVICE_TYPE prov_dev_security_get_type(void)
+{
+    return g_device_hsm_type;
+}
+
+int prov_dev_set_symmetric_key_info(const char* registration_name, const char* symmetric_key)
+{
+    int result;
+    if (registration_name == NULL || symmetric_key == NULL)
+    {
+        LogError("Invalid parameter specified reg_name: %p, symm_key: %p", registration_name, symmetric_key);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        char* temp_key;
+        char* temp_name;
+        if (mallocAndStrcpy_s(&temp_name, registration_name) != 0)
+        {
+            LogError("Failure allocating registration name");
+            result = MU_FAILURE;
+        }
+        else if (mallocAndStrcpy_s(&temp_key, symmetric_key) != 0)
+        {
+            LogError("Failure allocating symmetric key");
+            free(temp_name);
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if (g_symm_key != NULL)
+            {
+                free(g_symm_key);
+            }
+            if (g_symm_key_reg_name != NULL)
+            {
+                free(g_symm_key_reg_name);
+            }
+            g_symm_key_reg_name = temp_name;
+            g_symm_key = temp_key;
+
+            // Sync dps with iothub only if it is NULL
+            if (iothub_security_get_symmetric_key() == NULL || iothub_security_get_symm_registration_name() == NULL)
+            {
+                if (iothub_security_set_symmetric_key_info(g_symm_key_reg_name, g_symm_key) != 0)
+                {
+                    LogError("Failure syncing dps & IoThub key information");
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    result = 0;
+                }
+            }
+            else
+            {
+                result = 0;
+            }
+        }
+    }
+    return result;
+}
+
+const char* prov_dev_get_symmetric_key(void)
+{
+    return g_symm_key;
+}
+
+const char* prov_dev_get_symm_registration_name(void)
+{
+    return g_symm_key_reg_name;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/prov_transport_http_client.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/prov_transport_http_client.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/prov_transport_http_client.c	(revision 453)
@@ -0,0 +1,1259 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/platform.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/tlsio.h"
+#include "azure_c_shared_utility/shared_util_options.h"
+#include "azure_c_shared_utility/http_proxy_io.h"
+#include "azure_c_shared_utility/urlencode.h"
+#include "azure_c_shared_utility/azure_base64.h"
+
+#include "azure_prov_client/prov_transport_http_client.h"
+#include "azure_prov_client/internal/prov_transport_private.h"
+#include "azure_prov_client/prov_client_const.h"
+
+#include "azure_uhttp_c/uhttp.h"
+#include "parson.h"
+
+#define HTTP_PORT_NUM                       443
+#define HTTP_STATUS_CODE_OK                 200
+#define HTTP_STATUS_CODE_OK_MAX             226
+#define HTTP_STATUS_CODE_UNAUTHORIZED       401
+
+static const char* const PROV_REGISTRATION_URI_FMT = "/%s/registrations/%s/register?api-version=%s";
+static const char* const PROV_OP_STATUS_URI_FMT = "/%s/registrations/%s/operations/%s?api-version=%s";
+static const char* const HEADER_KEY_AUTHORIZATION = "Authorization";
+static const char* const HEADER_USER_AGENT = "UserAgent";
+static const char* const HEADER_ACCEPT = "Accept";
+static const char* const HEADER_CONTENT_TYPE = "Content-Type";
+static const char* const HEADER_CONNECTION = "Connection";
+static const char* const USER_AGENT_VALUE = "prov_device_client/1.0";
+static const char* const ACCEPT_VALUE = "application/json";
+static const char* const CONTENT_TYPE_VALUE = "application/json; charset=utf-8";
+static const char* const KEEP_ALIVE_VALUE = "keep-alive";
+static const char* const KEY_NAME_VALUE = "registration";
+
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(HTTP_CALLBACK_REASON, HTTP_CALLBACK_REASON_VALUES);
+
+typedef enum PROV_TRANSPORT_STATE_TAG
+{
+    TRANSPORT_CLIENT_STATE_IDLE,
+
+    TRANSPORT_CLIENT_STATE_REG_SEND,
+    TRANSPORT_CLIENT_STATE_REG_SENT,
+    TRANSPORT_CLIENT_STATE_REG_RECV,
+
+    TRANSPORT_CLIENT_STATE_STATUS_SENT,
+    TRANSPORT_CLIENT_STATE_STATUS_RECV,
+
+    TRANSPORT_CLIENT_STATE_TRANSIENT,
+
+    TRANSPORT_CLIENT_STATE_ERROR
+} PROV_TRANSPORT_STATE;
+
+typedef struct PROV_TRANSPORT_HTTP_INFO_TAG
+{
+    PROV_DEVICE_TRANSPORT_REGISTER_CALLBACK register_data_cb;
+    void* user_ctx;
+    PROV_DEVICE_TRANSPORT_STATUS_CALLBACK status_cb;
+    void* status_ctx;
+    PROV_TRANSPORT_CHALLENGE_CALLBACK challenge_cb;
+    void* challenge_ctx;
+    PROV_TRANSPORT_CREATE_JSON_PAYLOAD json_create_cb;
+    PROV_TRANSPORT_JSON_PARSE json_parse_cb;
+    void* json_ctx;
+
+    char* hostname;
+    char* proxy_host;
+    int proxy_port;
+    char* username;
+    char* password;
+
+    char* x509_cert;
+    char* private_key;
+
+    char* certificate;
+
+    BUFFER_HANDLE ek;
+    BUFFER_HANDLE srk;
+    char* registration_id;
+    char* scope_id;
+    char* sas_token;
+
+    BUFFER_HANDLE nonce;
+
+    char* operation_id;
+
+    char* api_version;
+
+    char* payload_data;
+    unsigned int http_status_code;
+
+    bool http_connected;
+    bool log_trace;
+    PROV_TRANSPORT_STATE transport_state;
+    TRANSPORT_HSM_TYPE hsm_type;
+
+    HTTP_CLIENT_HANDLE http_client;
+    uint32_t retry_after_value;
+
+    PROV_TRANSPORT_ERROR_CALLBACK error_cb;
+    void* error_ctx;
+} PROV_TRANSPORT_HTTP_INFO;
+
+static void on_http_error(void* callback_ctx, HTTP_CALLBACK_REASON error_result)
+{
+    (void)error_result;
+    if (callback_ctx != NULL)
+    {
+        PROV_TRANSPORT_HTTP_INFO* http_info = (PROV_TRANSPORT_HTTP_INFO*)callback_ctx;
+        http_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+        LogError("http error encountered: %s", MU_ENUM_TO_STRING(HTTP_CALLBACK_REASON, error_result));
+    }
+    else
+    {
+        LogError("callback_ctx NULL.  http error encountered: %s", MU_ENUM_TO_STRING(HTTP_CALLBACK_REASON, error_result));
+    }
+}
+
+static void on_http_reply_recv(void* callback_ctx, HTTP_CALLBACK_REASON request_result, const unsigned char* content, size_t content_len, unsigned int status_code, HTTP_HEADERS_HANDLE responseHeadersHandle)
+{
+    (void)responseHeadersHandle;
+    if (callback_ctx != NULL)
+    {
+        PROV_TRANSPORT_HTTP_INFO* http_info = (PROV_TRANSPORT_HTTP_INFO*)callback_ctx;
+        http_info->http_status_code = status_code;
+        if (request_result != HTTP_CALLBACK_REASON_OK)
+        {
+            LogError("Failure http reply %s", MU_ENUM_TO_STRING(HTTP_CALLBACK_REASON, request_result));
+            http_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+        }
+        else if ((status_code >= HTTP_STATUS_CODE_OK && status_code <= HTTP_STATUS_CODE_OK_MAX) || status_code == HTTP_STATUS_CODE_UNAUTHORIZED)
+        {
+            if (content != NULL && content_len > 0)
+            {
+                /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_038: [ prov_transport_http_dowork shall free the payload_data ] */
+                if (http_info->payload_data != NULL)
+                {
+                    free(http_info->payload_data);
+                }
+                http_info->payload_data = malloc(content_len + 1);
+                if (http_info->payload_data == NULL)
+                {
+                    LogError("Failure sending http request");
+                    http_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+                }
+                else
+                {
+                    memset(http_info->payload_data, 0, content_len + 1);
+                    memcpy(http_info->payload_data, content, content_len);
+                    if (http_info->transport_state == TRANSPORT_CLIENT_STATE_REG_SENT)
+                    {
+                        http_info->transport_state = TRANSPORT_CLIENT_STATE_REG_RECV;
+                    }
+                    else
+                    {
+                        http_info->transport_state = TRANSPORT_CLIENT_STATE_STATUS_RECV;
+                    }
+                }
+            }
+            else
+            {
+                if (http_info->transport_state == TRANSPORT_CLIENT_STATE_REG_SENT)
+                {
+                    http_info->transport_state = TRANSPORT_CLIENT_STATE_REG_RECV;
+                }
+                else
+                {
+                    http_info->transport_state = TRANSPORT_CLIENT_STATE_STATUS_RECV;
+                }
+            }
+        }
+        else if (status_code >= PROV_STATUS_CODE_TRANSIENT_ERROR)
+        {
+            // On transient error reset the transport to send state
+            http_info->transport_state = TRANSPORT_CLIENT_STATE_TRANSIENT;
+        }
+        else
+        {
+            LogError("Failure status code sent from the server: %u", status_code);
+            http_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+        }
+        // The call to parse_retry_after_value can not fail
+        http_info->retry_after_value = parse_retry_after_value(HTTPHeaders_FindHeaderValue(responseHeadersHandle, RETRY_AFTER_KEY_VALUE));
+    }
+    else
+    {
+        LogError("Null callback_ctx specified");
+    }
+}
+
+static void on_http_connected(void* callback_ctx, HTTP_CALLBACK_REASON open_result)
+{
+    if (callback_ctx != NULL)
+    {
+        PROV_TRANSPORT_HTTP_INFO* http_info = (PROV_TRANSPORT_HTTP_INFO*)callback_ctx;
+        if (open_result == HTTP_CALLBACK_REASON_OK)
+        {
+            if (http_info->status_cb != NULL)
+            {
+                http_info->status_cb(PROV_DEVICE_TRANSPORT_STATUS_CONNECTED, http_info->retry_after_value, http_info->status_ctx);
+            }
+            http_info->http_connected = true;
+        }
+        else
+        {
+            LogError("Http connection failed to connect");
+            http_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+            http_info->http_connected = false;
+        }
+    }
+    else
+    {
+        LogError("Null callback_ctx specified");
+    }
+}
+
+static HTTP_HEADERS_HANDLE construct_http_headers(const char* sas_token)
+{
+    HTTP_HEADERS_HANDLE result;
+    if ((result = HTTPHeaders_Alloc()) == NULL)
+    {
+        LogError("failure sending request");
+    }
+    else
+    {
+        if ((HTTPHeaders_AddHeaderNameValuePair(result, HEADER_USER_AGENT, USER_AGENT_VALUE) != HTTP_HEADERS_OK) ||
+            (HTTPHeaders_AddHeaderNameValuePair(result, HEADER_ACCEPT, ACCEPT_VALUE) != HTTP_HEADERS_OK) ||
+            (HTTPHeaders_AddHeaderNameValuePair(result, HEADER_CONNECTION, KEEP_ALIVE_VALUE) != HTTP_HEADERS_OK) ||
+            (HTTPHeaders_AddHeaderNameValuePair(result, HEADER_CONTENT_TYPE, CONTENT_TYPE_VALUE) != HTTP_HEADERS_OK))
+        {
+            LogError("failure adding header value");
+            HTTPHeaders_Free(result);
+            result = NULL;
+        }
+        else
+        {
+            if (sas_token != NULL)
+            {
+                if (HTTPHeaders_AddHeaderNameValuePair(result, HEADER_KEY_AUTHORIZATION, sas_token) != HTTP_HEADERS_OK)
+                {
+                    LogError("failure adding sas_token header value");
+                    HTTPHeaders_Free(result);
+                    result = NULL;
+                }
+            }
+        }
+    }
+    return result;
+}
+
+static char* construct_json_data(PROV_TRANSPORT_HTTP_INFO* http_info)
+{
+    char* result;
+    bool data_success = true;
+    STRING_HANDLE encoded_srk = NULL;
+    STRING_HANDLE encoded_ek = NULL;
+    const char* ek_value = NULL;
+    const char* srk_value = NULL;
+
+    // For TPM we need to add tpm encoded values
+    if (http_info->hsm_type == TRANSPORT_HSM_TYPE_TPM)
+    {
+        if ((encoded_ek = Azure_Base64_Encode(http_info->ek)) == NULL)
+        {
+            LogError("Failure encoding ek");
+            data_success = false;
+        }
+        else if ((encoded_srk = Azure_Base64_Encode(http_info->srk)) == NULL)
+        {
+            LogError("Failure encoding srk");
+            data_success = false;
+        }
+        else
+        {
+            ek_value = STRING_c_str(encoded_ek);
+            srk_value = STRING_c_str(encoded_srk);
+        }
+    }
+
+    if (data_success)
+    {
+        result = http_info->json_create_cb(ek_value, srk_value, http_info->json_ctx);
+    }
+    else
+    {
+        result = NULL;
+    }
+
+    if (encoded_srk != NULL)
+    {
+        STRING_delete(encoded_srk);
+    }
+    if (encoded_ek != NULL)
+    {
+        STRING_delete(encoded_ek);
+    }
+    return result;
+}
+
+static char* construct_url_path(PROV_TRANSPORT_HTTP_INFO* http_info)
+{
+    char* result;
+    size_t path_len;
+    STRING_HANDLE encoded_scope;
+
+    STRING_HANDLE encoded_reg_id = URL_EncodeString(http_info->registration_id);
+    if (encoded_reg_id == NULL)
+    {
+        LogError("Failure encoding reg id");
+        result = NULL;
+    }
+    else if ((encoded_scope = URL_EncodeString(http_info->scope_id)) == NULL)
+    {
+        LogError("Failure encoding string value");
+        STRING_delete(encoded_reg_id);
+        result = NULL;
+    }
+    else
+    {
+        if (http_info->operation_id == NULL)
+        {
+            path_len = strlen(PROV_REGISTRATION_URI_FMT) + STRING_length(encoded_scope) + STRING_length(encoded_reg_id) + strlen(http_info->api_version);
+            if ((result = malloc(path_len + 1)) == NULL)
+            {
+                LogError("Failure allocating url path");
+            }
+            else
+            {
+                if (sprintf(result, PROV_REGISTRATION_URI_FMT, STRING_c_str(encoded_scope), STRING_c_str(encoded_reg_id), http_info->api_version) == 0)
+                {
+                    LogError("Failure constructing url path");
+                    free(result);
+                    result = NULL;
+                }
+            }
+        }
+        else
+        {
+            STRING_HANDLE encoded_op_id = URL_EncodeString(http_info->operation_id);
+            if (encoded_op_id == NULL)
+            {
+                LogError("Failure encoding operation id");
+                result = NULL;
+            }
+            else
+            {
+                path_len = strlen(PROV_OP_STATUS_URI_FMT) + STRING_length(encoded_scope) + STRING_length(encoded_reg_id) + STRING_length(encoded_op_id) + strlen(http_info->api_version);
+                if ((result = malloc(path_len + 1)) == NULL)
+                {
+                    LogError("failure allocating retrieval path");
+                }
+                else
+                {
+                    if (sprintf(result, PROV_OP_STATUS_URI_FMT, STRING_c_str(encoded_scope), STRING_c_str(encoded_reg_id), STRING_c_str(encoded_op_id), http_info->api_version) == 0)
+                    {
+                        LogError("failure allocating retrieval path");
+                        free(result);
+                        result = NULL;
+                    }
+                }
+                STRING_delete(encoded_op_id);
+            }
+        }
+        STRING_delete(encoded_scope);
+        STRING_delete(encoded_reg_id);
+    }
+    return result;
+}
+
+static int send_registration_info(PROV_TRANSPORT_HTTP_INFO* http_info)
+{
+    int result;
+    char* uri_path;
+    char* json_data;
+    HTTP_HEADERS_HANDLE http_headers;
+
+    /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_018: [ prov_transport_http_register_device shall construct the http headers for anonymous communication to the service. ] */
+    if ((http_headers = construct_http_headers(http_info->sas_token)) == NULL)
+    {
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_021: [ If any error is encountered prov_transport_http_register_device shall return a non-zero value. ] */
+        LogError("failure constructing http headers");
+        result = MU_FAILURE;
+    }
+    /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_019: [ prov_transport_http_register_device shall construct the path to the service in the following format: /<scope_id>/registrations/<url_encoded_registration_id>/register-me?api-version=<api_version> ] */
+    else if ((uri_path = construct_url_path(http_info)) == NULL)
+    {
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_021: [ If any error is encountered prov_transport_http_register_device shall return a non-zero value. ] */
+        LogError("Failure constructing uri path");
+        HTTPHeaders_Free(http_headers);
+        result = MU_FAILURE;
+    }
+    else if ((json_data = construct_json_data(http_info)) == NULL)
+    {
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_021: [ If any error is encountered prov_transport_http_register_device shall return a non-zero value. ] */
+        LogError("Failure constructing json payload");
+        HTTPHeaders_Free(http_headers);
+        free(uri_path);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_020: [ prov_transport_http_register_device shall send the request using the http client. ] */
+        if (uhttp_client_execute_request(http_info->http_client, HTTP_CLIENT_REQUEST_PUT, uri_path, http_headers, (const unsigned char*)json_data, strlen(json_data), on_http_reply_recv, http_info) != HTTP_CLIENT_OK)
+        {
+            /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_021: [ If any error is encountered prov_transport_http_register_device shall return a non-zero value. ] */
+            LogError("Failure sending http request");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            result = 0;
+        }
+        free(uri_path);
+        free(json_data);
+        HTTPHeaders_Free(http_headers);
+    }
+    return result;
+}
+
+static int send_challenge_response(PROV_TRANSPORT_HTTP_INFO* http_info)
+{
+    int result;
+    HTTP_HEADERS_HANDLE http_headers;
+    char* uri_path;
+    char* json_data;
+
+    if ((http_headers = construct_http_headers(http_info->sas_token)) == NULL)
+    {
+        LogError("failure constructing http headers");
+        result = MU_FAILURE;
+    }
+    else if ((uri_path = construct_url_path(http_info)) == NULL)
+    {
+        LogError("Failure constructing uri path");
+        HTTPHeaders_Free(http_headers);
+        result = MU_FAILURE;
+    }
+    else if ((json_data = construct_json_data(http_info)) == NULL)
+    {
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_021: [ If any error is encountered prov_transport_http_register_device shall return a non-zero value. ] */
+        LogError("Failure constructing uri path");
+        HTTPHeaders_Free(http_headers);
+        free(uri_path);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        if (uhttp_client_execute_request(http_info->http_client, HTTP_CLIENT_REQUEST_PUT, uri_path, http_headers, (const unsigned char*)json_data, strlen(json_data), on_http_reply_recv, http_info) != HTTP_CLIENT_OK)
+        {
+            LogError("Failure sending http request");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            result = 0;
+        }
+        free(json_data);
+        free(uri_path);
+        HTTPHeaders_Free(http_headers);
+    }
+    return result;
+}
+
+static void free_json_parse_info(PROV_JSON_INFO* parse_info)
+{
+    switch (parse_info->prov_status)
+    {
+        case PROV_DEVICE_TRANSPORT_STATUS_UNASSIGNED:
+            BUFFER_delete(parse_info->authorization_key);
+            free(parse_info->key_name);
+            break;
+        case PROV_DEVICE_TRANSPORT_STATUS_ASSIGNED:
+            BUFFER_delete(parse_info->authorization_key);
+            free(parse_info->iothub_uri);
+            free(parse_info->device_id);
+            break;
+        case PROV_DEVICE_TRANSPORT_STATUS_ASSIGNING:
+            free(parse_info->operation_id);
+            break;
+        default:
+            break;
+    }
+    free(parse_info);
+}
+
+static void free_allocated_data(PROV_TRANSPORT_HTTP_INFO* http_info)
+{
+    free(http_info->hostname);
+    free(http_info->registration_id);
+    free(http_info->api_version);
+    free(http_info->scope_id);
+    free(http_info->certificate);
+    free(http_info->proxy_host);
+    free(http_info->x509_cert);
+    free(http_info->private_key);
+    free(http_info->username);
+    free(http_info->password);
+    free(http_info->payload_data);
+    free(http_info->sas_token);
+    free(http_info->operation_id);
+    BUFFER_delete(http_info->ek);
+    BUFFER_delete(http_info->srk);
+    BUFFER_delete(http_info->nonce);
+    if (http_info->http_client != NULL)
+    {
+        uhttp_client_destroy(http_info->http_client);
+    }
+    free(http_info);
+}
+
+static int create_transport_io_object(PROV_TRANSPORT_HTTP_INFO* http_info)
+{
+    int result;
+    if (http_info->http_client == NULL)
+    {
+        TLSIO_CONFIG tls_io_config;
+        HTTP_PROXY_IO_CONFIG http_proxy;
+        memset(&tls_io_config, 0, sizeof(TLSIO_CONFIG));
+        tls_io_config.hostname = http_info->hostname;
+        tls_io_config.port = HTTP_PORT_NUM;
+
+        // Setup proxy
+        if (http_info->proxy_host != NULL)
+        {
+            memset(&http_proxy, 0, sizeof(HTTP_PROXY_IO_CONFIG));
+            http_proxy.hostname = http_info->hostname;
+            http_proxy.port = HTTP_PORT_NUM;
+            http_proxy.proxy_hostname = http_info->proxy_host;
+            http_proxy.proxy_port = http_info->proxy_port;
+            http_proxy.username = http_info->username;
+            http_proxy.password = http_info->password;
+
+            tls_io_config.underlying_io_interface = http_proxy_io_get_interface_description();
+            tls_io_config.underlying_io_parameters = &http_proxy;
+        }
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_009: [ prov_transport_http_open shall create the http client adding any proxy and certificate information that is presented. ] */
+        const IO_INTERFACE_DESCRIPTION* interface_desc;
+
+        if ((interface_desc = platform_get_default_tlsio()) == NULL)
+        {
+            LogError("failgetting tls interface description");
+            result = MU_FAILURE;
+        }
+        else if ((http_info->http_client = uhttp_client_create(interface_desc, &tls_io_config, on_http_error, http_info)) == NULL)
+        {
+            LogError("failed to create http client");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            result = 0;
+        }
+    }
+    else
+    {
+        result = 0;
+    }
+    return result;
+}
+
+static int create_connection(PROV_TRANSPORT_HTTP_INFO* http_info)
+{
+    int result;
+    /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_009: [ prov_transport_http_open shall create the http client adding any proxy and certificate information that is presented. ] */
+    if (create_transport_io_object(http_info) != 0)
+    {
+        LogError("Failure setting transport object");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        (void)uhttp_client_set_trace(http_info->http_client, http_info->log_trace, true);
+
+        if (http_info->certificate != NULL && uhttp_client_set_trusted_cert(http_info->http_client, http_info->certificate) != HTTP_CLIENT_OK)
+        {
+            LogError("fail to set the trusted certificate in the http client");
+            uhttp_client_destroy(http_info->http_client);
+            http_info->http_client = NULL;
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if (http_info->hsm_type == TRANSPORT_HSM_TYPE_X509)
+            {
+                if (http_info->x509_cert == NULL || http_info->private_key == NULL)
+                {
+                    LogError("x509 certificate information was not properly set");
+                    result = MU_FAILURE;
+                }
+                else if (uhttp_client_set_X509_cert(http_info->http_client, true, http_info->x509_cert, http_info->private_key) != HTTP_CLIENT_OK)
+                {
+                    LogError("failed to set x509 certificate information");
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    result = 0;
+                }
+            }
+            else
+            {
+                result = 0;
+            }
+        }
+    }
+    if (result == 0 && !http_info->http_connected)
+    {
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_010: [ prov_transport_http_open shall opening the http communications with the service. ] */
+        if (uhttp_client_open(http_info->http_client, http_info->hostname, HTTP_PORT_NUM, on_http_connected, http_info) != HTTP_CLIENT_OK)
+        {
+            LogError("failed to open http client");
+            if (http_info->error_cb != NULL)
+            {
+                http_info->error_cb(PROV_DEVICE_ERROR_KEY_FAIL, http_info->error_ctx);
+            }
+            uhttp_client_destroy(http_info->http_client);
+            http_info->http_client = NULL;
+            result = MU_FAILURE;
+        }
+        else
+        {
+            result = 0;
+        }
+    }
+    return result;
+}
+
+PROV_DEVICE_TRANSPORT_HANDLE prov_transport_http_create(const char* uri, TRANSPORT_HSM_TYPE type, const char* scope_id, const char* api_version, PROV_TRANSPORT_ERROR_CALLBACK error_cb, void* error_ctx)
+{
+    PROV_TRANSPORT_HTTP_INFO* result;
+    if (uri == NULL || scope_id == NULL || api_version == NULL)
+    {
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_001: [ If uri, scope_id, registration_id or api_version are NULL prov_transport_http_create shall return NULL. ] */
+        LogError("Invalid parameter specified uri: %p, scope_id: %p, api_version: %p", uri, scope_id, api_version);
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_002: [ prov_transport_http_create shall allocate the memory for the PROV_DEVICE_TRANSPORT_HANDLE variables. ] */
+        result = malloc(sizeof(PROV_TRANSPORT_HTTP_INFO));
+        if (result == NULL)
+        {
+            /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_003: [ If any error is encountered prov_transport_http_create shall return NULL. ] */
+            LogError("Unable to allocate PROV_TRANSPORT_HTTP_INFO");
+        }
+        else
+        {
+            memset(result, 0, sizeof(PROV_TRANSPORT_HTTP_INFO));
+            if (mallocAndStrcpy_s(&result->hostname, uri) != 0)
+            {
+                /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_003: [ If any error is encountered prov_transport_http_create shall return NULL. ] */
+                LogError("Failure allocating hostname");
+                free(result);
+                result = NULL;
+            }
+            else if (mallocAndStrcpy_s(&result->api_version, api_version) != 0)
+            {
+                /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_003: [ If any error is encountered prov_transport_http_create shall return NULL. ] */
+                LogError("Failure allocating api_version");
+                free_allocated_data(result);
+                result = NULL;
+            }
+            else if (mallocAndStrcpy_s(&result->scope_id, scope_id) != 0)
+            {
+                /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_003: [ If any error is encountered prov_transport_http_create shall return NULL. ] */
+                LogError("Failure allocating scope Id");
+                free_allocated_data(result);
+                result = NULL;
+            }
+            else
+            {
+                result->retry_after_value = PROV_GET_THROTTLE_TIME;
+                result->hsm_type = type;
+                result->error_cb = error_cb;
+                result->error_ctx = error_ctx;
+            }
+        }
+    }
+    /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_004: [ On success prov_transport_http_create shall return a PROV_DEVICE_TRANSPORT_HANDLE. ] */
+    return result;
+}
+
+void prov_transport_http_destroy(PROV_DEVICE_TRANSPORT_HANDLE handle)
+{
+    /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_007: [ If the argument handle is NULL, prov_transport_http_destroy shall do nothing ] */
+    if (handle != NULL)
+    {
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_005: [ prov_transport_http_destroy shall free all resources associated with the PROV_DEVICE_TRANSPORT_HANDLE handle ] */
+        PROV_TRANSPORT_HTTP_INFO* http_info = (PROV_TRANSPORT_HTTP_INFO*)handle;
+        free_allocated_data(http_info);
+    }
+}
+
+int prov_transport_http_open(PROV_DEVICE_TRANSPORT_HANDLE handle, const char* registration_id, BUFFER_HANDLE ek, BUFFER_HANDLE srk, PROV_DEVICE_TRANSPORT_REGISTER_CALLBACK data_callback, void* user_ctx, PROV_DEVICE_TRANSPORT_STATUS_CALLBACK status_cb, void* status_ctx, PROV_TRANSPORT_CHALLENGE_CALLBACK reg_challenge_cb, void* challenge_ctx)
+{
+    int result;
+    PROV_TRANSPORT_HTTP_INFO* http_info = (PROV_TRANSPORT_HTTP_INFO*)handle;
+    if (http_info == NULL || data_callback == NULL || status_cb == NULL || registration_id == NULL)
+    {
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_008: [ If the argument handle, data_callback, or status_cb are NULL, prov_transport_http_open shall return a non-zero value. ] */
+        LogError("Invalid parameter specified handle: %p, data_callback: %p, status_cb: %p, registration_id: %p", handle, data_callback, status_cb, registration_id);
+        result = MU_FAILURE;
+    }
+    else if ((http_info->hsm_type == TRANSPORT_HSM_TYPE_TPM || http_info->hsm_type == TRANSPORT_HSM_TYPE_SYMM_KEY) && reg_challenge_cb == NULL)
+    {
+        LogError("registration challenge callback must be set");
+        result = MU_FAILURE;
+    }
+    else if (http_info->hsm_type == TRANSPORT_HSM_TYPE_TPM && (ek == NULL || srk == NULL))
+    {
+        LogError("Invalid parameter specified ek: %p, srk: %p", ek, srk);
+        result = MU_FAILURE;
+    }
+    else if (ek != NULL && (http_info->ek = BUFFER_clone(ek)) == NULL)
+    {
+        LogError("Unable to allocate endorsement key");
+        result = MU_FAILURE;
+    }
+    else if (srk != NULL && (http_info->srk = BUFFER_clone(srk)) == NULL)
+    {
+        LogError("Unable to allocate storage root key");
+        BUFFER_delete(http_info->ek);
+        http_info->ek = NULL;
+        result = MU_FAILURE;
+    }
+    else if (mallocAndStrcpy_s(&http_info->registration_id, registration_id) != 0)
+    {
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_003: [ If any error is encountered prov_transport_http_create shall return NULL. ] */
+        LogError("failure constructing registration Id");
+        BUFFER_delete(http_info->ek);
+        http_info->ek = NULL;
+        BUFFER_delete(http_info->srk);
+        http_info->srk = NULL;
+        result = MU_FAILURE;
+    }
+    else if ((http_info->hsm_type == TRANSPORT_HSM_TYPE_SYMM_KEY) && (http_info->sas_token = reg_challenge_cb(NULL, 0, KEY_NAME_VALUE, challenge_ctx)) == NULL)
+    {
+        LogError("failure constructing challenge value");
+        BUFFER_delete(http_info->ek);
+        http_info->ek = NULL;
+        BUFFER_delete(http_info->srk);
+        http_info->srk = NULL;
+        result = MU_FAILURE;
+    }
+    else
+    {
+        http_info->register_data_cb = data_callback;
+        http_info->user_ctx = user_ctx;
+        http_info->status_cb = status_cb;
+        http_info->status_ctx = status_ctx;
+        http_info->challenge_cb = reg_challenge_cb;
+        http_info->challenge_ctx = challenge_ctx;
+
+        if (create_connection(http_info) != 0)
+        {
+            /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_013: [ If an error is encountered prov_transport_http_open shall return a non-zero value. ] */
+            LogError("Failure creating http connection");
+            if (http_info->ek != NULL)
+            {
+                BUFFER_delete(http_info->ek);
+                http_info->ek = NULL;
+            }
+            if (http_info->srk != NULL)
+            {
+                BUFFER_delete(http_info->srk);
+                http_info->srk = NULL;
+            }
+            http_info->register_data_cb = NULL;
+            http_info->user_ctx = NULL;
+            http_info->status_cb = NULL;
+            http_info->status_ctx = NULL;
+            free(http_info->registration_id);
+            http_info->registration_id = NULL;
+            result = MU_FAILURE;
+        }
+        else
+        {
+            result = 0;
+        }
+    }
+    /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_012: [ If successful prov_transport_http_open shall return 0. ] */
+    return result;
+}
+
+int prov_transport_http_close(PROV_DEVICE_TRANSPORT_HANDLE handle)
+{
+    int result;
+    if (handle == NULL)
+    {
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_014: [ If the argument handle is NULL, prov_transport_http_close shall return a non-zero value. ] */
+        LogError("Invalid parameter specified handle: %p", handle);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_015: [ prov_transport_http_close shall attempt to close the http communication with the service. ] */
+        PROV_TRANSPORT_HTTP_INFO* http_info = (PROV_TRANSPORT_HTTP_INFO*)handle;
+        if (http_info->http_client != NULL)
+        {
+            BUFFER_delete(http_info->ek);
+            http_info->ek = NULL;
+            BUFFER_delete(http_info->srk);
+            http_info->srk = NULL;
+            free(http_info->registration_id);
+            http_info->registration_id = NULL;
+
+            uhttp_client_close(http_info->http_client, NULL, NULL);
+            uhttp_client_dowork(http_info->http_client);
+
+            /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_006: [ prov_transport_http_close shall call the uhttp_client_destroy function function associated with the http_client ] */
+            uhttp_client_destroy(http_info->http_client);
+            http_info->http_client = NULL;
+        }
+        http_info->http_connected = false;
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_016: [ On success prov_transport_http_close shall return 0. ] */
+        result = 0;
+    }
+    return result;
+}
+
+int prov_transport_http_register_device(PROV_DEVICE_TRANSPORT_HANDLE handle, PROV_TRANSPORT_JSON_PARSE json_parse_cb, PROV_TRANSPORT_CREATE_JSON_PAYLOAD json_create_cb, void* json_ctx)
+{
+    int result;
+    PROV_TRANSPORT_HTTP_INFO* http_info = (PROV_TRANSPORT_HTTP_INFO*)handle;
+    if (http_info == NULL || json_parse_cb == NULL || json_create_cb == NULL)
+    {
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_017: [ If the argument handle or json_data is NULL, prov_transport_http_register_device shall return a non-zero value. ] */
+        LogError("Invalid parameter specified handle: %p, json_parse_cb: %p", handle, json_parse_cb);
+        result = MU_FAILURE;
+    }
+    else if (http_info->transport_state == TRANSPORT_CLIENT_STATE_ERROR)
+    {
+        LogError("Provisioning is in an error state, close the connection and try again.");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_022: [ On success prov_transport_http_register_device shall return 0. ] */
+        http_info->transport_state = TRANSPORT_CLIENT_STATE_REG_SEND;
+        http_info->json_parse_cb = json_parse_cb;
+        http_info->json_create_cb = json_create_cb;
+        http_info->json_ctx = json_ctx;
+
+        result = 0;
+    }
+    return result;
+}
+
+int prov_transport_http_get_operation_status(PROV_DEVICE_TRANSPORT_HANDLE handle)
+{
+    int result;
+    if (handle == NULL)
+    {
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_029: [ If the argument handle, or operation_id is NULL, prov_transport_http_get_operation_status shall return a non-zero value. ] */
+        LogError("Invalid parameter specified handle: %p", handle);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        PROV_TRANSPORT_HTTP_INFO* http_info = (PROV_TRANSPORT_HTTP_INFO*)handle;
+        HTTP_HEADERS_HANDLE http_headers;
+        char* uri_path;
+
+        if (http_info->operation_id == NULL)
+        {
+            LogError("operation_id was not previously set in the challenge method");
+            result = MU_FAILURE;
+        }
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_030: [ prov_transport_http_get_operation_status shall construct the http headers with SAS_TOKEN as Authorization header. ] */
+        else if ((http_headers = construct_http_headers(http_info->sas_token)) == NULL)
+        {
+            /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_033: [ If any error is encountered prov_transport_http_get_operation_status shall return a non-zero value. ] */
+            LogError("failure constructing http headers");
+            result = MU_FAILURE;
+        }
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_031: [ prov_transport_http_get_operation_status shall construct the path to the service in the following format: /<scope_id>/registrations/<url_encoded_registration_id>/operations<url_encoded_operation_id>?api-version=<api_version> ] */
+        else if ((uri_path = construct_url_path(http_info)) == NULL)
+        {
+            /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_033: [ If any error is encountered prov_transport_http_get_operation_status shall return a non-zero value. ] */
+            LogError("Failure constructing uri path");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_032: [ prov_transport_http_get_operation_status shall send the request using the http client. ] */
+            if (uhttp_client_execute_request(http_info->http_client, HTTP_CLIENT_REQUEST_GET, uri_path, http_headers, NULL, 0, on_http_reply_recv, http_info) != HTTP_CLIENT_OK)
+            {
+                /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_033: [ If any error is encountered prov_transport_http_get_operation_status shall return a non-zero value. ] */
+                LogError("Failure sending data to server");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                http_info->transport_state = TRANSPORT_CLIENT_STATE_STATUS_SENT;
+                /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_034: [ On success prov_transport_http_get_operation_status shall return 0. ] */
+                result = 0;
+            }
+            HTTPHeaders_Free(http_headers);
+            free(uri_path);
+        }
+    }
+    return result;
+}
+
+void prov_transport_http_dowork(PROV_DEVICE_TRANSPORT_HANDLE handle)
+{
+    if (handle != NULL)
+    {
+        PROV_TRANSPORT_HTTP_INFO* http_info = (PROV_TRANSPORT_HTTP_INFO*)handle;
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_036: [ prov_transport_http_dowork shall call the underlying http client do work method. ] */
+        uhttp_client_dowork(http_info->http_client);
+
+        if (http_info->http_connected || http_info->transport_state == TRANSPORT_CLIENT_STATE_ERROR)
+        {
+            switch (http_info->transport_state)
+            {
+            case TRANSPORT_CLIENT_STATE_REG_SEND:
+                if (send_registration_info(http_info) != 0)
+                {
+                    LogError("NULL sas_token provided in challenge callback.");
+                    http_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+                }
+                else
+                {
+                    http_info->transport_state = TRANSPORT_CLIENT_STATE_REG_SENT;
+                }
+                break;
+            case TRANSPORT_CLIENT_STATE_STATUS_RECV:
+            case TRANSPORT_CLIENT_STATE_REG_RECV:
+            {
+                /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_037: [ If the prov_transport_http_dowork state is Message received prov_transport_http_dowork shall call the calling process registration_data callback ] */
+                PROV_JSON_INFO* parse_info = http_info->json_parse_cb(http_info->payload_data, http_info->json_ctx);
+                if (parse_info == NULL)
+                {
+                    LogError("Unable to process registration reply.");
+                    http_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+                }
+                else
+                {
+                    switch (parse_info->prov_status)
+                    {
+                        case PROV_DEVICE_TRANSPORT_STATUS_ASSIGNED:
+                            http_info->register_data_cb(PROV_DEVICE_TRANSPORT_RESULT_OK, parse_info->authorization_key, parse_info->iothub_uri, parse_info->device_id, http_info->user_ctx);
+                            http_info->transport_state = TRANSPORT_CLIENT_STATE_IDLE;
+                            break;
+
+                        case PROV_DEVICE_TRANSPORT_STATUS_UNASSIGNED:
+                        {
+                            const unsigned char* nonce = BUFFER_u_char(parse_info->authorization_key);
+                            size_t nonce_len = BUFFER_length(parse_info->authorization_key);
+
+                            http_info->sas_token = http_info->challenge_cb(nonce, nonce_len, parse_info->key_name, http_info->user_ctx);
+                            if (http_info->sas_token == NULL)
+                            {
+                                LogError("NULL sas_token provided in challenge callback.");
+                                http_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+                            }
+                            else
+                            {
+                                send_challenge_response(http_info);
+                                http_info->transport_state = TRANSPORT_CLIENT_STATE_REG_SENT;
+                            }
+                            break;
+                        }
+
+                        case PROV_DEVICE_TRANSPORT_STATUS_ASSIGNING:
+                            if (parse_info->operation_id == NULL)
+                            {
+                                LogError("Failure operation Id invalid");
+                                http_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+                            }
+                            else if (http_info->operation_id == NULL && mallocAndStrcpy_s(&http_info->operation_id, parse_info->operation_id) != 0)
+                            {
+                                LogError("Failure copying operation Id");
+                                http_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+                            }
+                            else
+                            {
+                                if (http_info->status_cb != NULL)
+                                {
+                                    http_info->status_cb(parse_info->prov_status, http_info->retry_after_value, http_info->status_ctx);
+                                }
+                                http_info->transport_state = TRANSPORT_CLIENT_STATE_IDLE;
+                            }
+                            break;
+
+                        default:
+                        case PROV_DEVICE_TRANSPORT_STATUS_ERROR:
+                            LogError("Unable to process status reply");
+                            http_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+                            break;
+                    }
+                    free_json_parse_info(parse_info);
+                }
+                break;
+            }
+
+            case TRANSPORT_CLIENT_STATE_TRANSIENT:
+                if (http_info->status_cb != NULL)
+                {
+                    http_info->status_cb(PROV_DEVICE_TRANSPORT_STATUS_TRANSIENT, http_info->retry_after_value, http_info->status_ctx);
+                }
+                http_info->transport_state = TRANSPORT_CLIENT_STATE_IDLE;
+                break;
+
+            case TRANSPORT_CLIENT_STATE_ERROR:
+                /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_039: [ If the state is Error, prov_transport_http_dowork shall call the registration_data callback with PROV_DEVICE_TRANSPORT_RESULT_ERROR and NULL payload_data. ] */
+                http_info->register_data_cb(PROV_DEVICE_TRANSPORT_RESULT_ERROR, NULL, NULL, NULL, http_info->user_ctx);
+                http_info->transport_state = TRANSPORT_CLIENT_STATE_IDLE;
+                break;
+
+            case TRANSPORT_CLIENT_STATE_REG_SENT:
+            case TRANSPORT_CLIENT_STATE_STATUS_SENT:
+            case TRANSPORT_CLIENT_STATE_IDLE:
+            default:
+                break;
+            }
+        }
+    }
+}
+
+int prov_transport_http_set_trace(PROV_DEVICE_TRANSPORT_HANDLE handle, bool trace_on)
+{
+    int result;
+    if (handle == NULL)
+    {
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_040: [ If the argument handle, is NULL, prov_transport_http_set_trace shall return a non-zero value. ] */
+        LogError("Invalid parameter specified handle: %p", handle);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        PROV_TRANSPORT_HTTP_INFO* http_info = (PROV_TRANSPORT_HTTP_INFO*)handle;
+        if (http_info->hsm_type == TRANSPORT_HSM_TYPE_X509)
+        {
+            http_info->log_trace = trace_on;
+            if (http_info->http_client != NULL)
+            {
+                /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_041: [ If the http client is not NULL, prov_transport_http_set_trace shall set the http client log trace function with the specified trace_on flag. ] */
+                (void)uhttp_client_set_trace(http_info->http_client, http_info->log_trace, http_info->log_trace);
+            }
+            /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_042: [ On success prov_transport_http_set_trace shall return zero. ] */
+            result = 0;
+        }
+        else
+        {
+            LogError("Unable to enable logging when not using x509 certificates");
+                result = MU_FAILURE;
+        }
+    }
+    return result;
+}
+
+static int prov_transport_http_x509_cert(PROV_DEVICE_TRANSPORT_HANDLE handle, const char* certificate, const char* private_key)
+{
+    int result;
+    if (handle == NULL || certificate == NULL || private_key == NULL)
+    {
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_043: [ If the argument handle, private_key or certificate is NULL, prov_transport_http_x509_cert shall return a non-zero value. ] */
+        LogError("Invalid parameter specified handle: %p, certificate: %p, private_key: %p", handle, certificate, private_key);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        PROV_TRANSPORT_HTTP_INFO* http_info = (PROV_TRANSPORT_HTTP_INFO*)handle;
+        if (http_info->x509_cert != NULL)
+        {
+            free(http_info->x509_cert);
+        }
+        if (http_info->private_key != NULL)
+        {
+            free(http_info->private_key);
+        }
+
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_045: [ prov_transport_http_x509_cert shall store the certificate and private_key for use when the http client connects. ] */
+        if (mallocAndStrcpy_s(&http_info->x509_cert, certificate) != 0)
+        {
+            /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_044: [ If any error is encountered prov_transport_http_x509_cert shall return a non-zero value. ] */
+            result = MU_FAILURE;
+            LogError("failure allocating certificate");
+        }
+        else if (mallocAndStrcpy_s(&http_info->private_key, private_key) != 0)
+        {
+            /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_044: [ If any error is encountered prov_transport_http_x509_cert shall return a non-zero value. ] */
+            free(http_info->x509_cert);
+            http_info->x509_cert = NULL;
+            result = MU_FAILURE;
+            LogError("failure allocating certificate");
+        }
+        else
+        {
+            /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_046: [ On success prov_transport_http_set_trace shall return zero. ] */
+            result = 0;
+        }
+    }
+    return result;
+}
+
+static int prov_transport_http_set_trusted_cert(PROV_DEVICE_TRANSPORT_HANDLE handle, const char* certificate)
+{
+    int result;
+    if (handle == NULL || certificate == NULL)
+    {
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_047: [ If the argument handle, certificate is NULL, prov_transport_http_set_trusted_cert shall return a non-zero value. ] */
+        LogError("Invalid parameter specified handle: %p, certificate: %p", handle, certificate);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        PROV_TRANSPORT_HTTP_INFO* http_info = (PROV_TRANSPORT_HTTP_INFO*)handle;
+        if (http_info->certificate != NULL)
+        {
+            free(http_info->certificate);
+        }
+
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_049: [ prov_transport_http_set_trusted_cert shall store the certificate for use when the http client connects. ] */
+        if (mallocAndStrcpy_s(&http_info->certificate, certificate) != 0)
+        {
+            /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_048: [ If any error is encountered prov_transport_http_set_trusted_cert shall return a non-zero value. ] */
+            result = MU_FAILURE;
+            LogError("failure allocating certificate");
+        }
+        else
+        {
+            /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_050: [ On success prov_transport_http_set_trusted_cert shall return zero. ] */
+            result = 0;
+        }
+    }
+    return result;
+}
+
+static int prov_transport_http_set_proxy(PROV_DEVICE_TRANSPORT_HANDLE handle, const HTTP_PROXY_OPTIONS* proxy_options)
+{
+    int result;
+    if (handle == NULL || proxy_options == NULL)
+    {
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_051: [ If the argument handle or proxy_options is NULL, prov_transport_http_set_proxy shall return a non-zero value. ] */
+        LogError("Invalid parameter specified handle: %p, proxy_options: %p", handle, proxy_options);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        PROV_TRANSPORT_HTTP_INFO* http_info = (PROV_TRANSPORT_HTTP_INFO*)handle;
+        if (proxy_options->host_address == NULL)
+        {
+            /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_055: [ If proxy_options host_name is NULL prov_transport_http_set_proxy shall return a non-zero value. ] */
+            LogError("NULL host_address in proxy options");
+            result = MU_FAILURE;
+        }
+        else if (((proxy_options->username == NULL) || (proxy_options->password == NULL)) &&
+            (proxy_options->username != proxy_options->password))
+        {
+            /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_053: [ If proxy_options username is NULL and proxy_options::password is not NULL prov_transport_http_set_proxy shall return a non-zero value. ] */
+            LogError("Only one of username and password for proxy settings was NULL");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if (http_info->proxy_host != NULL)
+            {
+                free(http_info->proxy_host);
+            }
+            if (http_info->username != NULL)
+            {
+                free(http_info->username);
+                http_info->username = NULL;
+            }
+            if (http_info->password != NULL)
+            {
+                free(http_info->password);
+                http_info->password = NULL;
+            }
+
+            http_info->proxy_port = proxy_options->port;
+            if (mallocAndStrcpy_s(&http_info->proxy_host, proxy_options->host_address) != 0)
+            {
+                /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_052: [ If any error is encountered prov_transport_http_set_proxy shall return a non-zero value. ] */
+                LogError("Failure setting proxy_host name");
+                result = MU_FAILURE;
+            }
+            else if (proxy_options->username != NULL && mallocAndStrcpy_s(&http_info->username, proxy_options->username) != 0)
+            {
+                /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_052: [ If any error is encountered prov_transport_http_set_proxy shall return a non-zero value. ] */
+                free(http_info->proxy_host);
+                http_info->proxy_host = NULL;
+                LogError("Failure setting proxy username");
+                result = MU_FAILURE;
+            }
+            else if (proxy_options->password != NULL && mallocAndStrcpy_s(&http_info->password, proxy_options->password) != 0)
+            {
+                /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_052: [ If any error is encountered prov_transport_http_set_proxy shall return a non-zero value. ] */
+                LogError("Failure setting proxy password");
+                free(http_info->proxy_host);
+                http_info->proxy_host = NULL;
+                free(http_info->username);
+                http_info->username = NULL;
+                result = MU_FAILURE;
+            }
+            else
+            {
+                /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_054: [ On success prov_transport_http_set_proxy shall return zero. ] */
+                result = 0;
+            }
+        }
+    }
+    return result;
+}
+
+static int prov_transport_http_set_option(PROV_DEVICE_TRANSPORT_HANDLE handle, const char* option, const void* value)
+{
+    int result;
+    // needs to invoke correct behavior
+    if (handle == NULL || option == NULL)
+    {
+        LogError("Invalid parameter specified handle: %p, option: %p", handle, option);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        PROV_TRANSPORT_HTTP_INFO* http_info = (PROV_TRANSPORT_HTTP_INFO*)handle;
+        if (http_info->http_client == NULL && create_transport_io_object(http_info) != 0)
+        {
+            LogError("Failure creating transport io object");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            result = uhttp_client_set_option(http_info->http_client, option, value);
+        }
+    }
+    return result;
+}
+
+static PROV_DEVICE_TRANSPORT_PROVIDER prov_http_func =
+{
+    prov_transport_http_create,
+    prov_transport_http_destroy,
+    prov_transport_http_open,
+    prov_transport_http_close,
+    prov_transport_http_register_device,
+    prov_transport_http_get_operation_status,
+    prov_transport_http_dowork,
+    prov_transport_http_set_trace,
+    prov_transport_http_x509_cert,
+    prov_transport_http_set_trusted_cert,
+    prov_transport_http_set_proxy,
+    prov_transport_http_set_option
+};
+
+const PROV_DEVICE_TRANSPORT_PROVIDER* Prov_Device_HTTP_Protocol(void)
+{
+    return &prov_http_func;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/prov_transport_mqtt_client.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/prov_transport_mqtt_client.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/prov_transport_mqtt_client.c	(revision 453)
@@ -0,0 +1,151 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_prov_client/prov_transport_mqtt_client.h"
+#include "azure_prov_client/internal/prov_transport_mqtt_common.h"
+#include "azure_c_shared_utility/xio.h"
+#include "azure_c_shared_utility/tlsio.h"
+#include "azure_c_shared_utility/http_proxy_io.h"
+#include "azure_c_shared_utility/platform.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/shared_util_options.h"
+
+#define MQTT_PORT_NUM               8883
+
+static XIO_HANDLE mqtt_transport_io(const char* fqdn, const HTTP_PROXY_OPTIONS* proxy_info)
+{
+    XIO_HANDLE result;
+    HTTP_PROXY_IO_CONFIG proxy_config;
+    TLSIO_CONFIG tls_io_config;
+
+    memset(&tls_io_config, 0, sizeof(TLSIO_CONFIG));
+    tls_io_config.hostname = fqdn;
+    tls_io_config.port = MQTT_PORT_NUM;
+    if (proxy_info != NULL)
+    {
+        /* Codes_PROV_TRANSPORT_MQTT_CLIENT_07_012: [ If proxy_info is not NULL, amqp_transport_io shall construct a HTTP_PROXY_IO_CONFIG object and assign it to TLSIO_CONFIG underlying_io_parameters ] */
+        proxy_config.hostname = tls_io_config.hostname;
+        proxy_config.port = MQTT_PORT_NUM;
+        proxy_config.proxy_hostname = proxy_info->host_address;
+        proxy_config.proxy_port = proxy_info->port;
+        proxy_config.username = proxy_info->username;
+        proxy_config.password = proxy_info->password;
+
+        tls_io_config.underlying_io_interface = http_proxy_io_get_interface_description();
+        tls_io_config.underlying_io_parameters = &proxy_config;
+    }
+
+    const IO_INTERFACE_DESCRIPTION* tlsio_interface = platform_get_default_tlsio();
+    if (tlsio_interface == NULL)
+    {
+        /* Codes_PROV_TRANSPORT_MQTT_CLIENT_07_013: [ If any failure is encountered amqp_transport_io shall return NULL ]*/
+        LogError("platform_get_default_tlsio return NULL IO Interface");
+        result = NULL;
+    }
+    else
+    {
+        result = xio_create(tlsio_interface, &tls_io_config);
+        if (result == NULL)
+        {
+            /* Codes_PROV_TRANSPORT_MQTT_CLIENT_07_013: [ If any failure is encountered amqp_transport_io shall return NULL ]*/
+            LogError("failed calling xio_create on underlying io");
+            result = NULL;
+        }
+    }
+    /* Codes_PROV_TRANSPORT_MQTT_CLIENT_07_014: [ On success mqtt_transport_io shall return allocated XIO_HANDLE. ] */
+    return result;
+}
+
+PROV_DEVICE_TRANSPORT_HANDLE prov_transport_mqtt_create(const char* uri, TRANSPORT_HSM_TYPE type, const char* scope_id, const char* api_version, PROV_TRANSPORT_ERROR_CALLBACK error_cb, void* error_ctx)
+{
+    /* Codes_PROV_TRANSPORT_MQTT_CLIENT_07_001: [ prov_transport_mqtt_create shall call the prov_transport_common_mqtt_create function with mqtt_transport_io transport IO estabishment. ] */
+    return prov_transport_common_mqtt_create(uri, type, scope_id, api_version, mqtt_transport_io, error_cb, error_ctx);
+}
+
+void prov_transport_mqtt_destroy(PROV_DEVICE_TRANSPORT_HANDLE handle)
+{
+    /* Codes_PROV_TRANSPORT_MQTT_CLIENT_07_002: [ prov_transport_mqtt_destroy shall invoke the prov_transport_common_mqtt_destroy method ] */
+    prov_transport_common_mqtt_destroy(handle);
+}
+
+int prov_transport_mqtt_open(PROV_DEVICE_TRANSPORT_HANDLE handle, const char* registration_id, BUFFER_HANDLE ek, BUFFER_HANDLE srk, PROV_DEVICE_TRANSPORT_REGISTER_CALLBACK data_callback, void* user_ctx, PROV_DEVICE_TRANSPORT_STATUS_CALLBACK status_cb, void* status_ctx, PROV_TRANSPORT_CHALLENGE_CALLBACK reg_challenge_cb, void* challenge_ctx)
+{
+    /* Codes_PROV_TRANSPORT_MQTT_CLIENT_07_003: [ prov_transport_mqtt_open shall invoke the prov_transport_common_mqtt_open method ] */
+    return prov_transport_common_mqtt_open(handle, registration_id, ek, srk, data_callback, user_ctx, status_cb, status_ctx, reg_challenge_cb, challenge_ctx);
+}
+
+int prov_transport_mqtt_close(PROV_DEVICE_TRANSPORT_HANDLE handle)
+{
+    /* Codes_PROV_TRANSPORT_MQTT_CLIENT_07_004: [ prov_transport_mqtt_close shall invoke the prov_transport_common_mqtt_close method ] */
+    return prov_transport_common_mqtt_close(handle);
+}
+
+int prov_transport_mqtt_register_device(PROV_DEVICE_TRANSPORT_HANDLE handle, PROV_TRANSPORT_JSON_PARSE json_parse_cb, PROV_TRANSPORT_CREATE_JSON_PAYLOAD json_create_cb, void* json_ctx)
+{
+    /* Codes_PROV_TRANSPORT_MQTT_CLIENT_07_005: [ prov_transport_mqtt_register_device shall invoke the prov_transport_common_mqtt_register_device method ] */
+    return prov_transport_common_mqtt_register_device(handle, json_parse_cb, json_create_cb, json_ctx);
+}
+
+int prov_transport_mqtt_get_operation_status(PROV_DEVICE_TRANSPORT_HANDLE handle)
+{
+    /* Codes_PROV_TRANSPORT_MQTT_CLIENT_07_006: [ prov_transport_mqtt_get_operation_status shall invoke the prov_transport_common_mqtt_get_operation_status method ] */
+    return prov_transport_common_mqtt_get_operation_status(handle);
+}
+
+void prov_transport_mqtt_dowork(PROV_DEVICE_TRANSPORT_HANDLE handle)
+{
+    /* Codes_PROV_TRANSPORT_MQTT_CLIENT_07_007: [ prov_transport_mqtt_dowork shall invoke the prov_transport_common_mqtt_dowork method ] */
+    prov_transport_common_mqtt_dowork(handle);
+}
+
+int prov_transport_mqtt_set_trace(PROV_DEVICE_TRANSPORT_HANDLE handle, bool trace_on)
+{
+    /* Codes_PROV_TRANSPORT_MQTT_CLIENT_07_008: [ prov_transport_mqtt_set_trace shall invoke the prov_transport_common_mqtt_set_trace method ] */
+    return prov_transport_common_mqtt_set_trace(handle, trace_on);
+}
+
+static int prov_transport_mqtt_x509_cert(PROV_DEVICE_TRANSPORT_HANDLE handle, const char* certificate, const char* private_key)
+{
+    /* Codes_PROV_TRANSPORT_MQTT_CLIENT_07_009: [ prov_transport_mqtt_x509_cert shall invoke the prov_trans_common_mqtt_x509_cert method ]*/
+    return prov_transport_common_mqtt_x509_cert(handle, certificate, private_key);
+}
+
+static int prov_transport_mqtt_set_trusted_cert(PROV_DEVICE_TRANSPORT_HANDLE handle, const char* certificate)
+{
+    /* Codes_PROV_TRANSPORT_MQTT_CLIENT_07_010: [ prov_transport_mqtt_set_trusted_cert shall invoke the prov_transport_common_mqtt_set_trusted_cert method ] */
+    return prov_transport_common_mqtt_set_trusted_cert(handle, certificate);
+}
+
+static int prov_transport_mqtt_set_proxy(PROV_DEVICE_TRANSPORT_HANDLE handle, const HTTP_PROXY_OPTIONS* proxy_options)
+{
+    /* Codes_PROV_TRANSPORT_MQTT_CLIENT_07_011: [ prov_transport_mqtt_set_proxy shall invoke the prov_transport_common_mqtt_set_proxy method ] */
+    return prov_transport_common_mqtt_set_proxy(handle, proxy_options);
+}
+
+static int prov_transport_mqtt_set_option(PROV_DEVICE_TRANSPORT_HANDLE handle, const char* option, const void* value)
+{
+    return prov_transport_common_mqtt_set_option(handle, option, value);
+}
+
+static PROV_DEVICE_TRANSPORT_PROVIDER prov_mqtt_func =
+{
+    prov_transport_mqtt_create,
+    prov_transport_mqtt_destroy,
+    prov_transport_mqtt_open,
+    prov_transport_mqtt_close,
+    prov_transport_mqtt_register_device,
+    prov_transport_mqtt_get_operation_status,
+    prov_transport_mqtt_dowork,
+    prov_transport_mqtt_set_trace,
+    prov_transport_mqtt_x509_cert,
+    prov_transport_mqtt_set_trusted_cert,
+    prov_transport_mqtt_set_proxy,
+    prov_transport_mqtt_set_option
+};
+
+const PROV_DEVICE_TRANSPORT_PROVIDER* Prov_Device_MQTT_Protocol(void)
+{
+    return &prov_mqtt_func;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/prov_transport_mqtt_common.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/prov_transport_mqtt_common.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/prov_transport_mqtt_common.c	(revision 453)
@@ -0,0 +1,1303 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <ctype.h>
+#include <limits.h>
+#include <inttypes.h>
+
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/platform.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/tlsio.h"
+#include "azure_c_shared_utility/shared_util_options.h"
+#include "azure_c_shared_utility/http_proxy_io.h"
+#include "azure_c_shared_utility/urlencode.h"
+#include "azure_c_shared_utility/http_proxy_io.h"
+
+#include "azure_prov_client/internal/prov_transport_mqtt_common.h"
+#include "azure_umqtt_c/mqtt_client.h"
+
+#include "azure_prov_client/prov_client_const.h"
+
+#define SUBSCRIBE_TOPIC_COUNT       1
+
+static const char* const MQTT_SUBSCRIBE_TOPIC = "$dps/registrations/res/#";
+static const char* const MQTT_USERNAME_FMT = "%s/registrations/%s/api-version=%s&ClientVersion=%s";
+static const char* const MQTT_REGISTER_MESSAGE_FMT = "$dps/registrations/PUT/iotdps-register/?$rid=%d";
+static const char* const MQTT_STATUS_MESSAGE_FMT = "$dps/registrations/GET/iotdps-get-operationstatus/?$rid=%d&operationId=%s";
+static const char* const MQTT_TOPIC_STATUS_PREFIX = "$dps/registrations/res/";
+static const char* const KEY_NAME_VALUE = "registration";
+
+typedef enum MQTT_TRANSPORT_STATE_TAG
+{
+    MQTT_STATE_IDLE,
+    MQTT_STATE_DISCONNECTED,
+    MQTT_STATE_CONNECTING,
+    MQTT_STATE_CONNECTED,
+
+    MQTT_STATE_SUBSCRIBING,
+    MQTT_STATE_SUBSCRIBED,
+
+    MQTT_STATE_ERROR
+} MQTT_TRANSPORT_STATE;
+
+typedef enum PROV_TRANSPORT_STATE_TAG
+{
+    TRANSPORT_CLIENT_STATE_IDLE,
+
+    TRANSPORT_CLIENT_STATE_REG_SEND,
+    TRANSPORT_CLIENT_STATE_REG_SENT,
+    TRANSPORT_CLIENT_STATE_REG_RECV,
+
+    TRANSPORT_CLIENT_STATE_STATUS_SEND,
+    TRANSPORT_CLIENT_STATE_STATUS_SENT,
+    TRANSPORT_CLIENT_STATE_STATUS_RECV,
+
+    TRANSPORT_CLIENT_STATE_TRANSIENT,
+    TRANSPORT_CLIENT_STATE_ERROR
+} PROV_TRANSPORT_STATE;
+
+typedef struct PROV_TRANSPORT_MQTT_INFO_TAG
+{
+    PROV_DEVICE_TRANSPORT_REGISTER_CALLBACK register_data_cb;
+    void* user_ctx;
+    PROV_DEVICE_TRANSPORT_STATUS_CALLBACK status_cb;
+    void* status_ctx;
+    PROV_TRANSPORT_CHALLENGE_CALLBACK challenge_cb;
+    void* challenge_ctx;
+    PROV_TRANSPORT_JSON_PARSE json_parse_cb;
+    PROV_TRANSPORT_CREATE_JSON_PAYLOAD json_create_cb;
+    void* json_ctx;
+
+    MQTT_CLIENT_HANDLE mqtt_client;
+
+    char* hostname;
+
+    HTTP_PROXY_OPTIONS proxy_option;
+
+    char* x509_cert;
+    char* private_key;
+
+    char* certificate;
+
+    BUFFER_HANDLE ek;
+    BUFFER_HANDLE srk;
+    char* registration_id;
+    char* scope_id;
+    char* sas_token;
+
+    char* operation_id;
+
+    char* api_version;
+    char* payload_data;
+
+    bool log_trace;
+
+    uint16_t packet_id;
+
+    TRANSPORT_HSM_TYPE hsm_type;
+
+    PROV_MQTT_TRANSPORT_IO transport_io_cb;
+
+    PROV_TRANSPORT_STATE transport_state;
+    MQTT_TRANSPORT_STATE mqtt_state;
+
+    XIO_HANDLE transport_io;
+    uint32_t retry_after_value;
+
+    PROV_TRANSPORT_ERROR_CALLBACK error_cb;
+    void* error_ctx;
+} PROV_TRANSPORT_MQTT_INFO;
+
+static uint16_t get_next_packet_id(PROV_TRANSPORT_MQTT_INFO* mqtt_info)
+{
+    if (mqtt_info->packet_id + 1 >= USHRT_MAX)
+    {
+        mqtt_info->packet_id = 1;
+    }
+    else
+    {
+        mqtt_info->packet_id++;
+    }
+    return mqtt_info->packet_id;
+}
+
+static void mqtt_error_callback(MQTT_CLIENT_HANDLE handle, MQTT_CLIENT_EVENT_ERROR error, void* user_ctx)
+{
+    (void)handle;
+    if (user_ctx != NULL)
+    {
+        PROV_TRANSPORT_MQTT_INFO* mqtt_info = (PROV_TRANSPORT_MQTT_INFO*)user_ctx;
+        switch (error)
+        {
+            case MQTT_CLIENT_CONNECTION_ERROR:
+            case MQTT_CLIENT_COMMUNICATION_ERROR:
+                LogError("MQTT communication error");
+                break;
+            case MQTT_CLIENT_NO_PING_RESPONSE:
+                LogError("Mqtt Ping Response was not encountered.  Reconnecting device...");
+                break;
+
+            case MQTT_CLIENT_PARSE_ERROR:
+            case MQTT_CLIENT_MEMORY_ERROR:
+            case MQTT_CLIENT_UNKNOWN_ERROR:
+            default:
+            {
+                LogError("INTERNAL ERROR: unexpected error value received %d", error);
+                break;
+            }
+        }
+        mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+        mqtt_info->mqtt_state = MQTT_STATE_ERROR;
+    }
+    else
+    {
+        LogError("mqtt_error_callback was invoked with a NULL context");
+    }
+}
+
+#ifndef NO_LOGGING
+static const char* retrieve_mqtt_return_codes(CONNECT_RETURN_CODE rtn_code)
+{
+    switch (rtn_code)
+    {
+    case CONNECTION_ACCEPTED:
+        return "Accepted";
+    case CONN_REFUSED_UNACCEPTABLE_VERSION:
+        return "Unacceptable Version";
+    case CONN_REFUSED_ID_REJECTED:
+        return "Id Rejected";
+    case CONN_REFUSED_SERVER_UNAVAIL:
+        return "Server Unavailable";
+    case CONN_REFUSED_BAD_USERNAME_PASSWORD:
+        return "Bad Username/Password";
+    case CONN_REFUSED_NOT_AUTHORIZED:
+        return "Not Authorized";
+    case CONN_REFUSED_UNKNOWN:
+    default:
+        return "Unknown";
+    }
+}
+#endif // NO_LOGGING
+
+static void mqtt_operation_complete_callback(MQTT_CLIENT_HANDLE handle, MQTT_CLIENT_EVENT_RESULT event_result, const void* msg_info, void* user_ctx)
+{
+    (void)handle;
+    (void)msg_info;
+    if (user_ctx != NULL)
+    {
+        PROV_TRANSPORT_MQTT_INFO* mqtt_info = (PROV_TRANSPORT_MQTT_INFO*)user_ctx;
+        switch (event_result)
+        {
+            case MQTT_CLIENT_ON_CONNACK:
+            {
+                const CONNECT_ACK* connack = (const CONNECT_ACK*)msg_info;
+                if (connack != NULL)
+                {
+                    if (connack->returnCode == CONNECTION_ACCEPTED)
+                    {
+                        /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_052: [ Once the mqtt CONNACK is recieved prov_transport_common_mqtt_dowork shall set mqtt_state to MQTT_STATE_CONNECTED ] */
+                        mqtt_info->mqtt_state = MQTT_STATE_CONNECTED;
+                    }
+                    else
+                    {
+                        LogError("Connection Not Accepted: 0x%x: %s", connack->returnCode, retrieve_mqtt_return_codes(connack->returnCode));
+                        mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+                        mqtt_info->mqtt_state = MQTT_STATE_ERROR;
+                        if (mqtt_info->error_cb != NULL)
+                        {
+                            mqtt_info->error_cb(PROV_DEVICE_ERROR_KEY_UNAUTHORIZED, mqtt_info->error_ctx);
+                        }
+                    }
+                }
+                else
+                {
+                    mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+                    mqtt_info->mqtt_state = MQTT_STATE_ERROR;
+                    LogError("CONNECT_ACK packet is NULL");
+                }
+                break;
+            }
+            case MQTT_CLIENT_ON_SUBSCRIBE_ACK:
+            {
+                const SUBSCRIBE_ACK* suback = (const SUBSCRIBE_ACK*)msg_info;
+                if (suback != NULL)
+                {
+                    size_t index = 0;
+                    for (index = 0; index < suback->qosCount; index++)
+                    {
+                        if (suback->qosReturn[index] == DELIVER_FAILURE)
+                        {
+                            LogError("Subscribe delivery failure of subscribe %lu", (unsigned long)index);
+                            break;
+                        }
+                    }
+
+                    if (index == suback->qosCount)
+                    {
+                        mqtt_info->mqtt_state = MQTT_STATE_SUBSCRIBED;
+                    }
+                    else
+                    {
+                        mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+                        mqtt_info->mqtt_state = MQTT_STATE_ERROR;
+                    }
+                }
+                else
+                {
+                    mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+                    mqtt_info->mqtt_state = MQTT_STATE_ERROR;
+                    LogError("SUBSCRIBE_ACK packet is NULL");
+                }
+                break;
+            }
+            case MQTT_CLIENT_ON_PUBLISH_ACK:
+            case MQTT_CLIENT_ON_PUBLISH_COMP:
+            case MQTT_CLIENT_ON_PUBLISH_RECV:
+            case MQTT_CLIENT_ON_PUBLISH_REL:
+            case MQTT_CLIENT_ON_DISCONNECT:
+            case MQTT_CLIENT_ON_UNSUBSCRIBE_ACK:
+                break;
+            default:
+                LogError("Unknown MQTT_CLIENT_EVENT_RESULT item %d", (int)event_result);
+                break;
+        }
+    }
+    else
+    {
+        LogError("mqtt_operation_complete_callback was invoked with a NULL context");
+    }
+}
+
+static int get_retry_after_property(const char* topic_name, PROV_TRANSPORT_MQTT_INFO* mqtt_info)
+{
+    int result = MU_FAILURE;
+
+    const char* iterator = topic_name;
+
+    size_t topic_len = strlen(iterator);
+    size_t retry_len = strlen(RETRY_AFTER_KEY_VALUE);
+    while (iterator != NULL && *iterator != '\0')
+    {
+        if (topic_len > retry_len)
+        {
+            if (memcmp(iterator, RETRY_AFTER_KEY_VALUE, retry_len) == 0)
+            {
+                // send the retry-after value to parse
+                mqtt_info->retry_after_value = parse_retry_after_value(iterator + retry_len + 1);
+                result = 0;
+                break;
+            }
+        }
+        else
+        {
+            // Topic string is not there
+            result = MU_FAILURE;
+            break;
+        }
+        iterator++;
+        topic_len--;
+    }
+    return result;
+}
+
+static void mqtt_notification_callback(MQTT_MESSAGE_HANDLE handle, void* user_ctx)
+{
+    if (user_ctx != NULL)
+    {
+        PROV_TRANSPORT_MQTT_INFO* mqtt_info = (PROV_TRANSPORT_MQTT_INFO*)user_ctx;
+
+        bool is_transient_error = false;
+        const char* topic_resp = mqttmessage_getTopicName(handle);
+        if (topic_resp != NULL)
+        {
+            // Extract the registration status
+            size_t status_pos = strlen(MQTT_TOPIC_STATUS_PREFIX);
+            if (memcmp(MQTT_TOPIC_STATUS_PREFIX, topic_resp, status_pos) == 0)
+            {
+                // If the status code is > 429 then this is a transient error
+                long status_code = atol(topic_resp + status_pos);
+                if (status_code >= PROV_STATUS_CODE_TRANSIENT_ERROR)
+                {
+                    // On transient error reset the transport to send state
+                    mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_TRANSIENT;
+                    is_transient_error = true;
+                }
+            }
+
+            // Get the retry after field on failures this value will
+            // be set to the default value
+            (void)get_retry_after_property(topic_resp, mqtt_info);
+        }
+        else
+        {
+            LogError("failure topic name is NULL");
+            mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+            mqtt_info->mqtt_state = MQTT_STATE_ERROR;
+        }
+
+        if (!is_transient_error)
+        {
+            const APP_PAYLOAD* payload = mqttmessage_getApplicationMsg(handle);
+            if (payload != NULL)
+            {
+                if (mqtt_info->payload_data != NULL)
+                {
+                    free(mqtt_info->payload_data);
+                    mqtt_info->payload_data = NULL;
+                }
+
+                if ((mqtt_info->payload_data = malloc(payload->length + 1)) == NULL)
+                {
+                    LogError("failure allocating payload data");
+                    mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+                    mqtt_info->mqtt_state = MQTT_STATE_ERROR;
+                }
+                else
+                {
+                    memset(mqtt_info->payload_data, 0, payload->length + 1);
+                    memcpy(mqtt_info->payload_data, payload->message, payload->length);
+                    if (mqtt_info->transport_state == TRANSPORT_CLIENT_STATE_REG_SENT)
+                    {
+                        mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_REG_RECV;
+                    }
+                    else
+                    {
+                        mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_STATUS_RECV;
+                    }
+                }
+            }
+            else
+            {
+                LogError("failure NULL message encountered from umqtt");
+                mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+                mqtt_info->mqtt_state = MQTT_STATE_ERROR;
+            }
+        }
+    }
+    else
+    {
+        LogError("mqtt_notification_callback was invoked with a NULL context");
+    }
+}
+
+static int send_mqtt_message(PROV_TRANSPORT_MQTT_INFO* mqtt_info, const char* msg_topic)
+{
+    int result;
+    MQTT_MESSAGE_HANDLE msg_handle = NULL;
+    char* prov_payload;
+
+    if ((prov_payload = mqtt_info->json_create_cb(NULL, NULL, mqtt_info->json_ctx)) == NULL)
+    {
+        LogError("Failed creating json mqtt payload");
+        result = MU_FAILURE;
+    }
+    else if ((msg_handle = mqttmessage_create_in_place(get_next_packet_id(mqtt_info), msg_topic, DELIVER_AT_MOST_ONCE, (const uint8_t*)prov_payload, strlen(prov_payload))) == NULL)
+    {
+        LogError("Failed creating mqtt message");
+        result = MU_FAILURE;
+        free(prov_payload);
+    }
+    else
+    {
+        if (mqtt_client_publish(mqtt_info->mqtt_client, msg_handle) != 0)
+        {
+            LogError("Failed publishing client message");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            result = 0;
+        }
+        mqttmessage_destroy(msg_handle);
+        free(prov_payload);
+    }
+    return result;
+}
+
+static int send_register_message(PROV_TRANSPORT_MQTT_INFO* mqtt_info)
+{
+    int result;
+    char* msg_topic;
+
+    size_t length = strlen(MQTT_REGISTER_MESSAGE_FMT) + 8;
+    if ((msg_topic = malloc(length + 1)) == NULL)
+    {
+        LogError("Failed allocating mqtt registration message");
+        result = MU_FAILURE;
+    }
+    else if (sprintf(msg_topic, MQTT_REGISTER_MESSAGE_FMT, mqtt_info->packet_id) <= 0)
+    {
+        LogError("Failed setting registration message");
+        free(msg_topic);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        result = send_mqtt_message(mqtt_info, msg_topic);
+        free(msg_topic);
+    }
+    return result;
+}
+
+static int send_operation_status_message(PROV_TRANSPORT_MQTT_INFO* mqtt_info)
+{
+    int result;
+    char* msg_topic;
+
+    size_t length = strlen(MQTT_STATUS_MESSAGE_FMT) + strlen(mqtt_info->operation_id) + 8;
+    if ((msg_topic = malloc(length + 1)) == NULL)
+    {
+        LogError("Failed allocating mqtt status message");
+        result = MU_FAILURE;
+    }
+    else if (sprintf(msg_topic, MQTT_STATUS_MESSAGE_FMT, mqtt_info->packet_id, mqtt_info->operation_id) <= 0)
+    {
+        LogError("Failed creating mqtt status message");
+        free(msg_topic);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        result = send_mqtt_message(mqtt_info, msg_topic);
+        free(msg_topic);
+    }
+    return result;
+}
+
+static int subscribe_to_topic(PROV_TRANSPORT_MQTT_INFO* mqtt_info)
+{
+    int result;
+    SUBSCRIBE_PAYLOAD subscribe[SUBSCRIBE_TOPIC_COUNT];
+    subscribe[0].subscribeTopic = MQTT_SUBSCRIBE_TOPIC;
+    subscribe[0].qosReturn = DELIVER_AT_LEAST_ONCE;
+
+    if (mqtt_client_subscribe(mqtt_info->mqtt_client, get_next_packet_id(mqtt_info), subscribe, SUBSCRIBE_TOPIC_COUNT) != 0)
+    {
+        LogError("Failed subscribing to topic.");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        result = 0;
+    }
+    return result;
+}
+
+static char* construct_username(PROV_TRANSPORT_MQTT_INFO* mqtt_info)
+{
+    char* result;
+    size_t length;
+
+    length = strlen(MQTT_USERNAME_FMT) + strlen(mqtt_info->registration_id) + strlen(mqtt_info->scope_id) + strlen(mqtt_info->api_version) + strlen(PROV_DEVICE_CLIENT_VERSION);
+    if ((result = malloc(length + 1)) == NULL)
+    {
+        LogError("Failure allocating username");
+        result = NULL;
+    }
+    else if (sprintf(result, MQTT_USERNAME_FMT, mqtt_info->scope_id, mqtt_info->registration_id, mqtt_info->api_version, PROV_DEVICE_CLIENT_VERSION) <= 0)
+    {
+        LogError("Failure creating mqtt username");
+        free(result);
+        result = NULL;
+    }
+    return result;
+}
+
+static int create_transport_io_object(PROV_TRANSPORT_MQTT_INFO* mqtt_info)
+{
+    int result;
+    if (mqtt_info->transport_io == NULL)
+    {
+        HTTP_PROXY_OPTIONS* transport_proxy;
+        if (mqtt_info->proxy_option.host_address != NULL)
+        {
+            transport_proxy = &mqtt_info->proxy_option;
+        }
+        else
+        {
+            transport_proxy = NULL;
+        }
+
+        if ((mqtt_info->transport_io = mqtt_info->transport_io_cb(mqtt_info->hostname, transport_proxy)) == NULL)
+        {
+            LogError("Failure calling transport_io callback");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            result = 0;
+        }
+    }
+    else
+    {
+        result = 0;
+    }
+    return result;
+}
+
+static int construct_transport(PROV_TRANSPORT_MQTT_INFO* mqtt_info)
+{
+    int result;
+
+    if (create_transport_io_object(mqtt_info) != 0)
+    {
+        LogError("Failed constructing transport io");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        if (mqtt_info->certificate != NULL && xio_setoption(mqtt_info->transport_io, OPTION_TRUSTED_CERT, mqtt_info->certificate) != 0)
+        {
+            LogError("Failure setting trusted certs");
+            result = MU_FAILURE;
+            xio_destroy(mqtt_info->transport_io);
+            mqtt_info->transport_io = NULL;
+        }
+        else if (mqtt_info->hsm_type == TRANSPORT_HSM_TYPE_X509)
+        {
+            if (mqtt_info->x509_cert != NULL && mqtt_info->private_key != NULL)
+            {
+                if (xio_setoption(mqtt_info->transport_io, OPTION_X509_ECC_CERT, mqtt_info->x509_cert) != 0)
+                {
+                    LogError("Failure setting x509 cert on xio");
+                    xio_destroy(mqtt_info->transport_io);
+                    mqtt_info->transport_io = NULL;
+                    result = MU_FAILURE;
+                }
+                else if (xio_setoption(mqtt_info->transport_io, OPTION_X509_ECC_KEY, mqtt_info->private_key) != 0)
+                {
+                    LogError("Failure setting x509 key on xio");
+                    if (mqtt_info->error_cb != NULL)
+                    {
+                        mqtt_info->error_cb(PROV_DEVICE_ERROR_KEY_FAIL, mqtt_info->error_ctx);
+                    }
+                    xio_destroy(mqtt_info->transport_io);
+                    mqtt_info->transport_io = NULL;
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    result = 0;
+                }
+            }
+            else
+            {
+                LogError("x509 certificate is NULL");
+                xio_destroy(mqtt_info->transport_io);
+                mqtt_info->transport_io = NULL;
+                result = MU_FAILURE;
+            }
+        }
+        else
+        {
+            result = 0;
+        }
+    }
+    return result;
+}
+
+static int create_connection(PROV_TRANSPORT_MQTT_INFO* mqtt_info)
+{
+    int result;
+    MQTT_CLIENT_OPTIONS options;
+    memset(&options, 0, sizeof(MQTT_CLIENT_OPTIONS));
+
+    char* username_info;
+
+    if ((username_info = construct_username(mqtt_info)) == NULL)
+    {
+        LogError("Failure creating username info");
+        result = MU_FAILURE;
+    }
+    else if (construct_transport(mqtt_info) != 0)
+    {
+        LogError("Failure constructing transport");
+        free(username_info);
+        result = MU_FAILURE;
+    }
+    else if ((mqtt_info->hsm_type == TRANSPORT_HSM_TYPE_SYMM_KEY) && (options.password = mqtt_info->challenge_cb(NULL, 0, KEY_NAME_VALUE, mqtt_info->challenge_ctx)) == NULL)
+    {
+        LogError("Failure retrieving sas token from key");
+        xio_destroy(mqtt_info->transport_io);
+        mqtt_info->transport_io = NULL;
+        free(username_info);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        (void)mqtt_client_set_trace(mqtt_info->mqtt_client, mqtt_info->log_trace, false);
+
+        options.username = username_info;
+        options.clientId = mqtt_info->registration_id;
+        options.useCleanSession = 1;
+        options.log_trace = mqtt_info->log_trace;
+        options.qualityOfServiceValue = DELIVER_AT_LEAST_ONCE;
+        if (mqtt_client_connect(mqtt_info->mqtt_client, mqtt_info->transport_io, &options) != 0)
+        {
+            xio_destroy(mqtt_info->transport_io);
+            mqtt_info->transport_io = NULL;
+            LogError("Failure connecting to mqtt server");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            result = 0;
+        }
+        if (options.password != NULL)
+        {
+            free(options.password);
+        }
+        free(username_info);
+    }
+    return result;
+}
+
+static void free_json_parse_info(PROV_JSON_INFO* parse_info)
+{
+    switch (parse_info->prov_status)
+    {
+        case PROV_DEVICE_TRANSPORT_STATUS_UNASSIGNED:
+            BUFFER_delete(parse_info->authorization_key);
+            free(parse_info->key_name);
+            break;
+        case PROV_DEVICE_TRANSPORT_STATUS_ASSIGNED:
+            BUFFER_delete(parse_info->authorization_key);
+            free(parse_info->iothub_uri);
+            free(parse_info->device_id);
+            break;
+        case PROV_DEVICE_TRANSPORT_STATUS_ASSIGNING:
+            free(parse_info->operation_id);
+            break;
+        default:
+            break;
+    }
+    free(parse_info);
+}
+
+void cleanup_mqtt_data(PROV_TRANSPORT_MQTT_INFO* mqtt_info)
+{
+    free(mqtt_info->hostname);
+    free(mqtt_info->registration_id);
+    free(mqtt_info->operation_id);
+    free(mqtt_info->api_version);
+    free(mqtt_info->scope_id);
+    free(mqtt_info->certificate);
+    free((char*)mqtt_info->proxy_option.host_address);
+    free((char*)mqtt_info->proxy_option.username);
+    free((char*)mqtt_info->proxy_option.password);
+    free(mqtt_info->x509_cert);
+    free(mqtt_info->private_key);
+    free(mqtt_info->sas_token);
+    free(mqtt_info->payload_data);
+    if (mqtt_info->transport_io != NULL)
+    {
+        xio_destroy(mqtt_info->transport_io);
+    }
+    free(mqtt_info);
+}
+
+PROV_DEVICE_TRANSPORT_HANDLE prov_transport_common_mqtt_create(const char* uri, TRANSPORT_HSM_TYPE type, const char* scope_id, const char* api_version, PROV_MQTT_TRANSPORT_IO transport_io, PROV_TRANSPORT_ERROR_CALLBACK error_cb, void* error_ctx)
+{
+    PROV_TRANSPORT_MQTT_INFO* result;
+    if (uri == NULL || scope_id == NULL || api_version == NULL || transport_io == NULL)
+    {
+        /* Codes_PROV_TRANSPORT_MQTT_COMMON_07_001: [ If uri, scope_id, registration_id, api_version, or transport_io is NULL, prov_transport_common_mqtt_create shall return NULL. ] */
+        LogError("Invalid parameter specified uri: %p, scope_id: %p, api_version: %p, transport_io: %p", uri, scope_id, api_version, transport_io);
+        result = NULL;
+    }
+    else if (type == TRANSPORT_HSM_TYPE_TPM)
+    {
+        /* Codes_PROV_TRANSPORT_MQTT_COMMON_07_062: [ If TRANSPORT_HSM_TYPE is TRANSPORT_HSM_TYPE_TPM prov_transport_common_mqtt_create shall return NULL (currently TPM is not supported). ] */
+        LogError("HSM type of TPM is not supported");
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_PROV_TRANSPORT_MQTT_COMMON_07_003: [ prov_transport_common_mqtt_create shall allocate a PROV_TRANSPORT_MQTT_INFO and initialize the containing fields. ] */
+        result = malloc(sizeof(PROV_TRANSPORT_MQTT_INFO));
+        if (result == NULL)
+        {
+            /* Codes_PROV_TRANSPORT_MQTT_COMMON_07_002: [ If any error is encountered, prov_transport_common_mqtt_create shall return NULL. ] */
+            LogError("Unable to allocate PROV_TRANSPORT_MQTT_INFO");
+        }
+        else
+        {
+            memset(result, 0, sizeof(PROV_TRANSPORT_MQTT_INFO));
+            if (mallocAndStrcpy_s(&result->hostname, uri) != 0)
+            {
+                /* Codes_PROV_TRANSPORT_MQTT_COMMON_07_002: [ If any error is encountered, prov_transport_common_mqtt_create shall return NULL. ] */
+                LogError("Failure allocating hostname");
+                free(result);
+                result = NULL;
+            }
+            else if (mallocAndStrcpy_s(&result->api_version, api_version) != 0)
+            {
+                /* Codes_PROV_TRANSPORT_MQTT_COMMON_07_002: [ If any error is encountered, prov_transport_common_mqtt_create shall return NULL. ] */
+                LogError("Failure allocating api_version");
+                cleanup_mqtt_data(result);
+                result = NULL;
+            }
+            else if (mallocAndStrcpy_s(&result->scope_id, scope_id) != 0)
+            {
+                /* Codes_PROV_TRANSPORT_MQTT_COMMON_07_002: [ If any error is encountered, prov_transport_common_mqtt_create shall return NULL. ] */
+                LogError("Failure allocating scope_id");
+                cleanup_mqtt_data(result);
+                result = NULL;
+            }
+            else if ((result->mqtt_client = mqtt_client_init(mqtt_notification_callback, mqtt_operation_complete_callback, result, mqtt_error_callback, result)) == NULL)
+            {
+                /* Codes_PROV_TRANSPORT_MQTT_COMMON_07_002: [ If any error is encountered, prov_transport_common_mqtt_create shall return NULL. ] */
+                LogError("Failed initializing mqtt client.");
+                cleanup_mqtt_data(result);
+                result = NULL;
+            }
+            else
+            {
+                result->transport_io_cb = transport_io;
+                result->hsm_type = type;
+                result->error_cb = error_cb;
+                result->error_ctx = error_ctx;
+                result->retry_after_value = PROV_GET_THROTTLE_TIME;
+            }
+        }
+    }
+    /* Codes_PROV_TRANSPORT_MQTT_COMMON_07_004: [ On success prov_transport_common_mqtt_create shall return a new instance of PROV_DEVICE_TRANSPORT_HANDLE. ] */
+    return result;
+}
+
+void prov_transport_common_mqtt_destroy(PROV_DEVICE_TRANSPORT_HANDLE handle)
+{
+    /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_005: [ If handle is NULL, prov_transport_common_mqtt_destroy shall do nothing. ] */
+    if (handle != NULL)
+    {
+        /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_006: [ prov_transport_common_mqtt_destroy shall free all resources used in this module. ] */
+        PROV_TRANSPORT_MQTT_INFO* mqtt_info = (PROV_TRANSPORT_MQTT_INFO*)handle;
+        mqtt_client_deinit(mqtt_info->mqtt_client);
+        mqtt_info->mqtt_client = NULL;
+        cleanup_mqtt_data(mqtt_info);
+    }
+}
+
+int prov_transport_common_mqtt_open(PROV_DEVICE_TRANSPORT_HANDLE handle, const char* registration_id, BUFFER_HANDLE ek, BUFFER_HANDLE srk, PROV_DEVICE_TRANSPORT_REGISTER_CALLBACK data_callback, void* user_ctx, PROV_DEVICE_TRANSPORT_STATUS_CALLBACK status_cb, void* status_ctx, PROV_TRANSPORT_CHALLENGE_CALLBACK reg_challenge_cb, void* challenge_ctx)
+{
+    int result;
+    PROV_TRANSPORT_MQTT_INFO* mqtt_info = (PROV_TRANSPORT_MQTT_INFO*)handle;
+    if (mqtt_info == NULL || data_callback == NULL || status_cb == NULL || registration_id == NULL)
+    {
+        /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_007: [ If handle, data_callback, or status_cb is NULL, prov_transport_common_mqtt_open shall return a non-zero value. ] */
+        LogError("Invalid parameter specified handle: %p, data_callback: %p, status_cb: %p, registration_id: %p", handle, data_callback, status_cb, registration_id);
+        result = MU_FAILURE;
+    }
+    else if ((mqtt_info->hsm_type == TRANSPORT_HSM_TYPE_TPM || mqtt_info->hsm_type == TRANSPORT_HSM_TYPE_SYMM_KEY) && reg_challenge_cb == NULL)
+    {
+        LogError("registration challenge callback must be set");
+        result = MU_FAILURE;
+    }
+    // Should never be here since TPM is not supported, so I'm going to check to ensure compliance
+    else if (ek != NULL || srk != NULL)
+    {
+        /* Codes_PROV_TRANSPORT_MQTT_COMMON_07_008: [ If hsm_type is TRANSPORT_HSM_TYPE_TPM and ek or srk is NULL, prov_transport_common_mqtt_open shall return a non-zero value. ] */
+        LogError("Invalid parameter specified ek: %p, srk: %p", ek, srk);
+        result = MU_FAILURE;
+    }
+    else if (mallocAndStrcpy_s(&mqtt_info->registration_id, registration_id) != 0)
+    {
+        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_003: [ If any error is encountered prov_transport_http_create shall return NULL. ] */
+        LogError("failure constructing registration Id");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        mqtt_info->register_data_cb = data_callback;
+        mqtt_info->user_ctx = user_ctx;
+        mqtt_info->status_cb = status_cb;
+        mqtt_info->status_ctx = status_ctx;
+        mqtt_info->mqtt_state = MQTT_STATE_DISCONNECTED;
+        // Must add a false connect here due to the protocol quirk
+        //mqtt_info->status_cb(PROV_DEVICE_TRANSPORT_STATUS_CONNECTED, mqtt_info->status_ctx);
+        mqtt_info->challenge_cb = reg_challenge_cb;
+        mqtt_info->challenge_ctx = challenge_ctx;
+
+        result = 0;
+    }
+    return result;
+}
+
+int prov_transport_common_mqtt_close(PROV_DEVICE_TRANSPORT_HANDLE handle)
+{
+    int result;
+    if (handle == NULL)
+    {
+        /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_011: [ If handle is NULL, prov_transport_common_mqtt_close shall return a non-zero value. ] */
+        LogError("Invalid parameter specified handle: %p", handle);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        PROV_TRANSPORT_MQTT_INFO* mqtt_info = (PROV_TRANSPORT_MQTT_INFO*)handle;
+        BUFFER_delete(mqtt_info->ek);
+        mqtt_info->ek = NULL;
+        BUFFER_delete(mqtt_info->srk);
+        mqtt_info->srk = NULL;
+        free(mqtt_info->registration_id);
+        mqtt_info->registration_id = NULL;
+
+        /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_012: [ prov_transport_common_mqtt_close shall close all connection associated with mqtt communication. ] */
+        if (mqtt_client_disconnect(mqtt_info->mqtt_client, NULL, NULL) == 0)
+        {
+            mqtt_client_dowork(mqtt_info->mqtt_client);
+        }
+        xio_destroy(mqtt_info->transport_io);
+        mqtt_info->transport_io = NULL;
+
+        /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_013: [ On success prov_transport_common_mqtt_close shall return a zero value. ] */
+        mqtt_info->mqtt_state = MQTT_STATE_IDLE;
+        result = 0;
+    }
+    return result;
+}
+
+int prov_transport_common_mqtt_register_device(PROV_DEVICE_TRANSPORT_HANDLE handle, PROV_TRANSPORT_JSON_PARSE json_parse_cb, PROV_TRANSPORT_CREATE_JSON_PAYLOAD json_create_cb, void* json_ctx)
+{
+    int result;
+    PROV_TRANSPORT_MQTT_INFO* mqtt_info = (PROV_TRANSPORT_MQTT_INFO*)handle;
+    if (mqtt_info == NULL || json_parse_cb == NULL || json_create_cb == NULL)
+    {
+        /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_014: [ If handle is NULL, prov_transport_common_mqtt_register_device shall return a non-zero value. ] */
+        LogError("Invalid parameter specified handle: %p, json_parse_cb: %p", handle, json_parse_cb);
+        result = MU_FAILURE;
+    }
+    /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_061: [ If the transport_state is TRANSPORT_CLIENT_STATE_REG_SEND or the the operation_id is NULL, prov_transport_common_mqtt_register_device shall return a non-zero value. ] */
+    else if (mqtt_info->transport_state == TRANSPORT_CLIENT_STATE_REG_SEND || mqtt_info->operation_id != NULL)
+    {
+        LogError("Failure: device is currently in the registration process");
+        result = MU_FAILURE;
+    }
+    else if (mqtt_info->transport_state == TRANSPORT_CLIENT_STATE_ERROR)
+    {
+        LogError("Provisioning is in an error state, close the connection and try again.");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_REG_SEND;
+        mqtt_info->json_parse_cb = json_parse_cb;
+        mqtt_info->json_create_cb = json_create_cb;
+        mqtt_info->json_ctx = json_ctx;
+
+        /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_017: [ On success prov_transport_common_mqtt_register_device shall return a zero value. ] */
+        result = 0;
+    }
+    return result;
+}
+
+int prov_transport_common_mqtt_get_operation_status(PROV_DEVICE_TRANSPORT_HANDLE handle)
+{
+    int result;
+    if (handle == NULL)
+    {
+        /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_018: [ If handle is NULL, prov_transport_common_mqtt_get_operation_status shall return a non-zero value. ] */
+        LogError("Invalid parameter specified handle: %p", handle);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        PROV_TRANSPORT_MQTT_INFO* mqtt_info = (PROV_TRANSPORT_MQTT_INFO*)handle;
+        if (mqtt_info->operation_id == NULL)
+        {
+            /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_019: [ If the operation_id is NULL, prov_transport_common_mqtt_get_operation_status shall return a non-zero value. ] */
+            LogError("operation_id was not previously set in the challenge method");
+            result = MU_FAILURE;
+        }
+        else if (mqtt_info->transport_state == TRANSPORT_CLIENT_STATE_ERROR)
+        {
+            LogError("Provisioning is in an error state, close the connection and try again.");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_021: [ prov_transport_common_mqtt_get_operation_status shall set the transport_state to TRANSPORT_CLIENT_STATE_STATUS_SEND. ] */
+            mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_STATUS_SEND;
+            /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_022: [ On success prov_transport_common_mqtt_get_operation_status shall return a zero value. ] */
+            result = 0;
+        }
+    }
+    return result;
+}
+
+void prov_transport_common_mqtt_dowork(PROV_DEVICE_TRANSPORT_HANDLE handle)
+{
+    /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_046: [ If handle is NULL, prov_transport_common_mqtt_dowork shall do nothing. ] */
+    if (handle != NULL)
+    {
+        PROV_TRANSPORT_MQTT_INFO* mqtt_info = (PROV_TRANSPORT_MQTT_INFO*)handle;
+        if (mqtt_info->mqtt_state == MQTT_STATE_DISCONNECTED)
+        {
+            /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_047: [ If the mqtt_state is MQTT_STATE_DISCONNECTED prov_transport_common_mqtt_dowork shall attempt to connect the mqtt connections. ] */
+            if (create_connection(mqtt_info) != 0)
+            {
+                /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_049: [ If any error is encountered prov_transport_common_mqtt_dowork shall set the mqtt_state to MQTT_STATE_ERROR and the transport_state to TRANSPORT_CLIENT_STATE_ERROR. ] */
+                LogError("unable to create mqtt connection");
+                mqtt_info->mqtt_state = MQTT_STATE_ERROR;
+                mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+            }
+            else
+            {
+                mqtt_info->mqtt_state = MQTT_STATE_CONNECTING;
+            }
+        }
+        else if (mqtt_info->mqtt_state == MQTT_STATE_CONNECTED)
+        {
+            mqtt_client_dowork(mqtt_info->mqtt_client);
+            /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_050: [ When the mqtt_state is MQTT_STATE_CONNECTED, prov_transport_common_mqtt_dowork shall subscribe to the topic $dps/registrations/res/# ] */
+            if (subscribe_to_topic(mqtt_info) != 0)
+            {
+                /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_049: [ If any error is encountered prov_transport_common_mqtt_dowork shall set the mqtt_state to MQTT_STATE_ERROR and the transport_state to TRANSPORT_CLIENT_STATE_ERROR. ] */
+                LogError("Failure subscribing to topic");
+                mqtt_info->mqtt_state = MQTT_STATE_ERROR;
+                mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+            }
+            else
+            {
+                mqtt_info->status_cb(PROV_DEVICE_TRANSPORT_STATUS_CONNECTED, mqtt_info->retry_after_value, mqtt_info->status_ctx);
+                mqtt_info->mqtt_state = MQTT_STATE_SUBSCRIBING;
+            }
+        }
+        else if (mqtt_info->mqtt_state != MQTT_STATE_IDLE)
+        {
+            mqtt_client_dowork(mqtt_info->mqtt_client);
+            if (mqtt_info->mqtt_state == MQTT_STATE_SUBSCRIBED || mqtt_info->mqtt_state == MQTT_STATE_ERROR)
+            {
+                switch (mqtt_info->transport_state)
+                {
+                    case TRANSPORT_CLIENT_STATE_REG_SEND:
+                        /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_053: [ When then transport_state is set to TRANSPORT_CLIENT_STATE_REG_SEND, prov_transport_common_mqtt_dowork shall send a REGISTER_ME message ] */
+                        if (send_register_message(mqtt_info) != 0)
+                        {
+                            /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_049: [ If any error is encountered prov_transport_common_mqtt_dowork shall set the mqtt_state to MQTT_STATE_ERROR and the transport_state to TRANSPORT_CLIENT_STATE_ERROR. ] */
+                            mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+                            mqtt_info->mqtt_state = MQTT_STATE_ERROR;
+                        }
+                        else
+                        {
+                            /* Codes_PROV_TRANSPORT_MQTT_COMMON_07_054: [ Upon successful sending of a TRANSPORT_CLIENT_STATE_REG_SEND message, prov_transport_common_mqtt_dowork shall set the transport_state to TRANSPORT_CLIENT_STATE_REG_SENT ] */
+                            mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_REG_SENT;
+                        }
+                        break;
+                    case TRANSPORT_CLIENT_STATE_STATUS_SEND:
+                        /* Codes_PROV_TRANSPORT_MQTT_COMMON_07_055: [ When then transport_state is set to TRANSPORT_CLIENT_STATE_STATUS_SEND, prov_transport_common_mqtt_dowork shall send a AMQP_OPERATION_STATUS message ] */
+                        if (send_operation_status_message(mqtt_info) != 0)
+                        {
+                            /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_049: [ If any error is encountered prov_transport_common_mqtt_dowork shall set the mqtt_state to MQTT_STATE_ERROR and the transport_state to TRANSPORT_CLIENT_STATE_ERROR. ] */
+                            mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+                            mqtt_info->mqtt_state = MQTT_STATE_ERROR;
+                        }
+                        else
+                        {
+                            /* Codes_PROV_TRANSPORT_MQTT_COMMON_07_056: [ Upon successful sending of a AMQP_OPERATION_STATUS message, prov_transport_common_mqtt_dowork shall set the transport_state to TRANSPORT_CLIENT_STATE_STATUS_SENT ] */
+                            mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_STATUS_SENT;
+                        }
+                        break;
+
+                    case TRANSPORT_CLIENT_STATE_REG_RECV:
+                    case TRANSPORT_CLIENT_STATE_STATUS_RECV:
+                    {
+                        PROV_JSON_INFO* parse_info = mqtt_info->json_parse_cb(mqtt_info->payload_data, mqtt_info->json_ctx);
+                        if (parse_info == NULL)
+                        {
+                            /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_049: [ If any error is encountered prov_transport_common_mqtt_dowork shall set the mqtt_state to MQTT_STATE_ERROR and the transport_state to TRANSPORT_CLIENT_STATE_ERROR. ] */
+                            LogError("Unable to process registration reply.");
+                            mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+                            mqtt_info->mqtt_state = MQTT_STATE_ERROR;
+                        }
+                        else
+                        {
+                            switch (parse_info->prov_status)
+                            {
+                                case PROV_DEVICE_TRANSPORT_STATUS_UNASSIGNED:
+                                case PROV_DEVICE_TRANSPORT_STATUS_ASSIGNING:
+                                    if (parse_info->operation_id == NULL)
+                                    {
+                                        /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_049: [ If any error is encountered prov_transport_common_mqtt_dowork shall set the mqtt_state to MQTT_STATE_ERROR and the transport_state to TRANSPORT_CLIENT_STATE_ERROR. ] */
+                                        LogError("Failure operation Id invalid");
+                                        mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+                                        mqtt_info->mqtt_state = MQTT_STATE_ERROR;
+                                    }
+                                    else if (mqtt_info->operation_id == NULL && mallocAndStrcpy_s(&mqtt_info->operation_id, parse_info->operation_id) != 0)
+                                    {
+                                        /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_049: [ If any error is encountered prov_transport_common_mqtt_dowork shall set the mqtt_state to MQTT_STATE_ERROR and the transport_state to TRANSPORT_CLIENT_STATE_ERROR. ] */
+                                        LogError("Failure copying operation Id");
+                                        mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+                                        mqtt_info->mqtt_state = MQTT_STATE_ERROR;
+                                    }
+                                    else
+                                    {
+                                        if (mqtt_info->status_cb != NULL)
+                                        {
+                                            mqtt_info->status_cb(parse_info->prov_status, mqtt_info->retry_after_value, mqtt_info->status_ctx);
+                                        }
+                                        mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_IDLE;
+                                    }
+                                    break;
+                                case PROV_DEVICE_TRANSPORT_STATUS_ASSIGNED:
+                                    mqtt_info->register_data_cb(PROV_DEVICE_TRANSPORT_RESULT_OK, parse_info->authorization_key, parse_info->iothub_uri, parse_info->device_id, mqtt_info->user_ctx);
+                                    mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_IDLE;
+                                    break;
+                                case PROV_DEVICE_TRANSPORT_STATUS_TRANSIENT:
+                                    break;
+                                case PROV_DEVICE_TRANSPORT_STATUS_ERROR:
+                                default:
+                                    /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_049: [ If any error is encountered prov_transport_common_mqtt_dowork shall set the mqtt_state to MQTT_STATE_ERROR and the transport_state to TRANSPORT_CLIENT_STATE_ERROR. ] */
+                                    LogError("Unable to process message reply.");
+                                    mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_ERROR;
+                                    mqtt_info->mqtt_state = MQTT_STATE_ERROR;
+                                    break;
+
+                            }
+                            free_json_parse_info(parse_info);
+                        }
+                        break;
+                    }
+                    case TRANSPORT_CLIENT_STATE_TRANSIENT:
+                        if (mqtt_info->status_cb != NULL)
+                        {
+                            mqtt_info->status_cb(PROV_DEVICE_TRANSPORT_STATUS_TRANSIENT, mqtt_info->retry_after_value, mqtt_info->status_ctx);
+                        }
+                        mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_IDLE;
+                        break;
+
+                    case TRANSPORT_CLIENT_STATE_ERROR:
+                        /* Codes_PROV_TRANSPORT_MQTT_COMMON_07_057: [ If transport_state is set to TRANSPORT_CLIENT_STATE_ERROR, prov_transport_common_mqtt_dowork shall call the register_data_cb function with PROV_DEVICE_TRANSPORT_RESULT_ERROR setting the transport_state to TRANSPORT_CLIENT_STATE_IDLE ] */
+                        mqtt_info->register_data_cb(PROV_DEVICE_TRANSPORT_RESULT_ERROR, NULL, NULL, NULL, mqtt_info->user_ctx);
+                        mqtt_info->transport_state = TRANSPORT_CLIENT_STATE_IDLE;
+                        mqtt_info->mqtt_state = MQTT_STATE_IDLE;
+                        break;
+                    case TRANSPORT_CLIENT_STATE_REG_SENT:
+                    case TRANSPORT_CLIENT_STATE_STATUS_SENT:
+                        break;
+
+                    case TRANSPORT_CLIENT_STATE_IDLE:
+                    default:
+                        break;
+                }
+            }
+        }
+    }
+}
+
+int prov_transport_common_mqtt_set_trace(PROV_DEVICE_TRANSPORT_HANDLE handle, bool trace_on)
+{
+    int result;
+    if (handle == NULL)
+    {
+        /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_023: [ If handle is NULL, prov_transport_common_mqtt_set_trace shall return a non-zero value. ] */
+        LogError("Invalid parameter specified handle: %p", handle);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        PROV_TRANSPORT_MQTT_INFO* mqtt_info = (PROV_TRANSPORT_MQTT_INFO*)handle;
+        /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_024: [ prov_transport_common_mqtt_set_trace shall set the log_trace variable to trace_on. ]*/
+        mqtt_info->log_trace = trace_on;
+        if (mqtt_info->mqtt_client != NULL)
+        {
+            /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_059: [ If the umqtt connection is not NULL, prov_transport_common_mqtt_set_trace shall set the trace option on that connection. ] */
+            mqtt_client_set_trace(mqtt_info->mqtt_client, mqtt_info->log_trace, false);
+        }
+        result = 0;
+    }
+    return result;
+}
+
+int prov_transport_common_mqtt_x509_cert(PROV_DEVICE_TRANSPORT_HANDLE handle, const char* certificate, const char* private_key)
+{
+    int result;
+    if (handle == NULL || certificate == NULL)
+    {
+        /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_026: [ If handle or certificate is NULL, prov_transport_common_mqtt_x509_cert shall return a non-zero value. ] */
+        LogError("Invalid parameter specified handle: %p, certificate: %p", handle, certificate);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        PROV_TRANSPORT_MQTT_INFO* mqtt_info = (PROV_TRANSPORT_MQTT_INFO*)handle;
+
+        if (mqtt_info->x509_cert != NULL)
+        {
+            free(mqtt_info->x509_cert);
+            mqtt_info->x509_cert = NULL;
+        }
+        if (mqtt_info->private_key != NULL)
+        {
+            free(mqtt_info->private_key);
+            mqtt_info->private_key = NULL;
+        }
+
+        /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_027: [ prov_transport_common_mqtt_x509_cert shall copy the certificate and private_key values. ] */
+        if (mallocAndStrcpy_s(&mqtt_info->x509_cert, certificate) != 0)
+        {
+            /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_028: [ On any failure prov_transport_common_mqtt_x509_cert, shall return a non-zero value. ] */
+            result = MU_FAILURE;
+            LogError("failure allocating certificate");
+        }
+        else if (mallocAndStrcpy_s(&mqtt_info->private_key, private_key) != 0)
+        {
+            /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_028: [ On any failure prov_transport_common_mqtt_x509_cert, shall return a non-zero value. ] */
+            LogError("failure allocating certificate");
+            free(mqtt_info->x509_cert);
+            mqtt_info->x509_cert = NULL;
+            result = MU_FAILURE;
+        }
+        else
+        {
+            /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_029: [ On success prov_transport_common_mqtt_x509_cert shall return a zero value. ] */
+            result = 0;
+        }
+    }
+    return result;
+}
+
+int prov_transport_common_mqtt_set_trusted_cert(PROV_DEVICE_TRANSPORT_HANDLE handle, const char* certificate)
+{
+    int result;
+    if (handle == NULL || certificate == NULL)
+    {
+        /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_030: [ If handle or certificate is NULL, prov_transport_common_mqtt_set_trusted_cert shall return a non-zero value. ] */
+        LogError("Invalid parameter specified handle: %p, certificate: %p", handle, certificate);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        PROV_TRANSPORT_MQTT_INFO* mqtt_info = (PROV_TRANSPORT_MQTT_INFO*)handle;
+
+        if (mqtt_info->certificate != NULL)
+        {
+            free(mqtt_info->certificate);
+            mqtt_info->certificate = NULL;
+        }
+
+        /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_031: [ prov_transport_common_mqtt_set_trusted_cert shall copy the certificate value. ] */
+        if (mallocAndStrcpy_s(&mqtt_info->certificate, certificate) != 0)
+        {
+            /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_032: [ On any failure prov_transport_common_mqtt_set_trusted_cert, shall return a non-zero value. ] */
+            result = MU_FAILURE;
+            LogError("failure allocating certificate");
+        }
+        else
+        {
+            /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_033: [ On success prov_transport_common_mqtt_set_trusted_cert shall return a zero value. ] */
+            result = 0;
+        }
+    }
+    return result;
+}
+
+int prov_transport_common_mqtt_set_proxy(PROV_DEVICE_TRANSPORT_HANDLE handle, const HTTP_PROXY_OPTIONS* proxy_options)
+{
+    int result;
+    if (handle == NULL || proxy_options == NULL)
+    {
+        /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_034: [ If handle or proxy_options is NULL, prov_transport_common_mqtt_set_proxy shall return a non-zero value. ]*/
+        LogError("Invalid parameter specified handle: %p, proxy_options: %p", handle, proxy_options);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        PROV_TRANSPORT_MQTT_INFO* mqtt_info = (PROV_TRANSPORT_MQTT_INFO*)handle;
+        if (proxy_options->host_address == NULL)
+        {
+            /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_035: [ If HTTP_PROXY_OPTIONS host_address is NULL, prov_transport_common_mqtt_set_proxy shall return a non-zero value. ] */
+            LogError("NULL host_address in proxy options");
+            result = MU_FAILURE;
+        }
+        /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_036: [ If HTTP_PROXY_OPTIONS password is not NULL and username is NULL, prov_transport_common_mqtt_set_proxy shall return a non-zero value. ] */
+        else if (((proxy_options->username == NULL) || (proxy_options->password == NULL)) &&
+            (proxy_options->username != proxy_options->password))
+        {
+            /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_039: [ On any failure prov_transport_common_mqtt_set_proxy, shall return a non-zero value. ] */
+            LogError("Only one of username and password for proxy settings was NULL");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_037: [ If any of the host_addess, username, or password variables are non-NULL, prov_transport_common_mqtt_set_proxy shall free the memory. ] */
+            if (mqtt_info->proxy_option.host_address != NULL)
+            {
+                free((char*)mqtt_info->proxy_option.host_address);
+                mqtt_info->proxy_option.host_address = NULL;
+            }
+            if (mqtt_info->proxy_option.username != NULL)
+            {
+                free((char*)mqtt_info->proxy_option.username);
+                mqtt_info->proxy_option.username = NULL;
+            }
+            if (mqtt_info->proxy_option.password != NULL)
+            {
+                free((char*)mqtt_info->proxy_option.password);
+                mqtt_info->proxy_option.password = NULL;
+            }
+
+            /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_038: [ prov_transport_common_mqtt_set_proxy shall copy the host_addess, username, or password variables ] */
+            mqtt_info->proxy_option.port = proxy_options->port;
+            if (mallocAndStrcpy_s((char**)&mqtt_info->proxy_option.host_address, proxy_options->host_address) != 0)
+            {
+                /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_039: [ On any failure prov_transport_common_mqtt_set_proxy, shall return a non-zero value. ] */
+                LogError("Failure setting proxy_host name");
+                result = MU_FAILURE;
+            }
+            else if (proxy_options->username != NULL && mallocAndStrcpy_s((char**)&mqtt_info->proxy_option.username, proxy_options->username) != 0)
+            {
+                /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_039: [ On any failure prov_transport_common_mqtt_set_proxy, shall return a non-zero value. ] */
+                LogError("Failure setting proxy username");
+                free((char*)mqtt_info->proxy_option.host_address);
+                mqtt_info->proxy_option.host_address = NULL;
+                result = MU_FAILURE;
+            }
+            else if (proxy_options->password != NULL && mallocAndStrcpy_s((char**)&mqtt_info->proxy_option.password, proxy_options->password) != 0)
+            {
+                /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_039: [ On any failure prov_transport_common_mqtt_set_proxy, shall return a non-zero value. ] */
+                LogError("Failure setting proxy password");
+                free((char*)mqtt_info->proxy_option.host_address);
+                mqtt_info->proxy_option.host_address = NULL;
+                free((char*)mqtt_info->proxy_option.username);
+                mqtt_info->proxy_option.username = NULL;
+                result = MU_FAILURE;
+            }
+            else
+            {
+                /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_040: [ On success prov_transport_common_mqtt_set_proxy shall return a zero value. ] */
+                result = 0;
+            }
+        }
+    }
+    return result;
+}
+
+int prov_transport_common_mqtt_set_option(PROV_DEVICE_TRANSPORT_HANDLE handle, const char* option, const void* value)
+{
+    int result;
+    if (handle == NULL || option == NULL)
+    {
+        LogError("Invalid parameter specified handle: %p, option: %p", handle, option);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        PROV_TRANSPORT_MQTT_INFO* mqtt_info = (PROV_TRANSPORT_MQTT_INFO*)handle;
+        if (mqtt_info->transport_io == NULL && create_transport_io_object(mqtt_info) != 0)
+        {
+            LogError("Failure creating transport io object");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            result = xio_setoption(mqtt_info->transport_io, option, value);
+        }
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/prov_transport_mqtt_ws_client.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/prov_transport_mqtt_ws_client.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/provisioning_client/src/prov_transport_mqtt_ws_client.c	(revision 453)
@@ -0,0 +1,167 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/wsio.h"
+#include "azure_prov_client/prov_transport_mqtt_client.h"
+#include "azure_prov_client/internal/prov_transport_mqtt_common.h"
+#include "azure_c_shared_utility/xio.h"
+#include "azure_c_shared_utility/tlsio.h"
+#include "azure_c_shared_utility/http_proxy_io.h"
+#include "azure_c_shared_utility/platform.h"
+#include "azure_c_shared_utility/shared_util_options.h"
+
+#define MQTT_WS_PORT_NUM               443
+#define MQTT_WS_PROTOCOL_NAME "MQTT"
+#define MQTT_WS_RELATIVE_PATH "/$iothub/websocket"
+
+static XIO_HANDLE mqtt_transport_ws_io(const char* fqdn, const HTTP_PROXY_OPTIONS* proxy_info)
+{
+    XIO_HANDLE result;
+    HTTP_PROXY_IO_CONFIG proxy_config;
+    TLSIO_CONFIG tls_io_config;
+    WSIO_CONFIG ws_io_config;
+    const IO_INTERFACE_DESCRIPTION* ws_io_interface;
+    const IO_INTERFACE_DESCRIPTION* tlsio_interface;
+
+    if ((ws_io_interface = wsio_get_interface_description()) == NULL)
+    {
+        /* Codes_PROV_TRANSPORT_MQTT_WS_CLIENT_07_013: [ If any failure is encountered amqp_transport_ws_io shall return NULL ] */
+        LogError("wsio_get_interface_description return NULL IO Interface");
+        result = NULL;
+    }
+    else if ((tlsio_interface = platform_get_default_tlsio()) == NULL)
+    {
+        /* Codes_PROV_TRANSPORT_MQTT_WS_CLIENT_07_013: [ If any failure is encountered amqp_transport_ws_io shall return NULL ] */
+        LogError("platform_get_default_tlsio return NULL IO Interface");
+        result = NULL;
+    }
+    else
+    {
+        memset(&tls_io_config, 0, sizeof(TLSIO_CONFIG));
+
+        ws_io_config.hostname = fqdn;
+        ws_io_config.port = MQTT_WS_PORT_NUM;
+        ws_io_config.protocol = MQTT_WS_PROTOCOL_NAME;
+        ws_io_config.resource_name = MQTT_WS_RELATIVE_PATH;
+        ws_io_config.underlying_io_interface = tlsio_interface;
+        ws_io_config.underlying_io_parameters = &tls_io_config;
+
+        tls_io_config.hostname = fqdn;
+        tls_io_config.port = MQTT_WS_PORT_NUM;
+        if (proxy_info != NULL)
+        {
+            /* Codes_PROV_TRANSPORT_MQTT_CLIENT_07_012: [ If proxy_info is not NULL, amqp_transport_io shall construct a HTTP_PROXY_IO_CONFIG object and assign it to TLSIO_CONFIG underlying_io_parameters ] */
+            proxy_config.hostname = tls_io_config.hostname;
+            proxy_config.port = MQTT_WS_PORT_NUM;
+            proxy_config.proxy_hostname = proxy_info->host_address;
+            proxy_config.proxy_port = proxy_info->port;
+            proxy_config.username = proxy_info->username;
+            proxy_config.password = proxy_info->password;
+
+            tls_io_config.underlying_io_interface = http_proxy_io_get_interface_description();
+            tls_io_config.underlying_io_parameters = &proxy_config;
+        }
+
+        result = xio_create(ws_io_interface, &ws_io_config);
+        if (result == NULL)
+        {
+            LogError("failed calling xio_create on underlying io");
+        }
+    }
+    /* Codes_PROV_TRANSPORT_MQTT_WS_CLIENT_07_014: [ On success mqtt_transport_ws_io shall return an allocated XIO_HANDLE. ] */
+    return result;
+}
+
+PROV_DEVICE_TRANSPORT_HANDLE prov_transport_mqtt_ws_create(const char* uri, TRANSPORT_HSM_TYPE type, const char* scope_id, const char* api_version, PROV_TRANSPORT_ERROR_CALLBACK error_cb, void* error_ctx)
+{
+    /* Codes_PROV_TRANSPORT_MQTT_WS_CLIENT_07_001: [ prov_transport_mqtt_ws_create shall call the prov_trans_common_mqtt_create function with mqtt_transport_ws_io transport IO estabishment. ] */
+    return prov_transport_common_mqtt_create(uri, type, scope_id, api_version, mqtt_transport_ws_io, error_cb, error_ctx);
+}
+
+void prov_transport_mqtt_ws_destroy(PROV_DEVICE_TRANSPORT_HANDLE handle)
+{
+    /* Codes_PROV_TRANSPORT_MQTT_WS_CLIENT_07_002: [ prov_transport_mqtt_ws_destroy shall invoke the prov_transport_common_mqtt_destroy method ] */
+    prov_transport_common_mqtt_destroy(handle);
+}
+
+int prov_transport_mqtt_ws_open(PROV_DEVICE_TRANSPORT_HANDLE handle, const char* registration_id, BUFFER_HANDLE ek, BUFFER_HANDLE srk, PROV_DEVICE_TRANSPORT_REGISTER_CALLBACK data_callback, void* user_ctx, PROV_DEVICE_TRANSPORT_STATUS_CALLBACK status_cb, void* status_ctx, PROV_TRANSPORT_CHALLENGE_CALLBACK reg_challenge_cb, void* challenge_ctx)
+{
+    /* Codes_PROV_TRANSPORT_MQTT_WS_CLIENT_07_003: [ prov_transport_mqtt_ws_open shall invoke the prov_transport_common_mqtt_open method ] */
+    return prov_transport_common_mqtt_open(handle, registration_id, ek, srk, data_callback, user_ctx, status_cb, status_ctx, reg_challenge_cb, challenge_ctx);
+}
+
+int prov_transport_mqtt_ws_close(PROV_DEVICE_TRANSPORT_HANDLE handle)
+{
+    /* Codes_PROV_TRANSPORT_MQTT_WS_CLIENT_07_004: [ prov_transport_mqtt_ws_close shall invoke the prov_transport_common_mqtt_close method ] */
+    return prov_transport_common_mqtt_close(handle);
+}
+
+int prov_transport_mqtt_ws_register_device(PROV_DEVICE_TRANSPORT_HANDLE handle, PROV_TRANSPORT_JSON_PARSE json_parse_cb, PROV_TRANSPORT_CREATE_JSON_PAYLOAD json_create_cb, void* json_ctx)
+{
+    /* Codes_PROV_TRANSPORT_MQTT_WS_CLIENT_07_005: [ prov_transport_mqtt_ws_register_device shall invoke the prov_transport_common_mqtt_register_device method ] */
+    return prov_transport_common_mqtt_register_device(handle, json_parse_cb, json_create_cb, json_ctx);
+}
+
+int prov_transport_mqtt_ws_get_operation_status(PROV_DEVICE_TRANSPORT_HANDLE handle)
+{
+    /* Codes_PROV_TRANSPORT_MQTT_WS_CLIENT_07_006: [ prov_transport_mqtt_ws_get_operation_status shall invoke the prov_transport_common_mqtt_get_operation_status method ] */
+    return prov_transport_common_mqtt_get_operation_status(handle);
+}
+
+void prov_transport_mqtt_ws_dowork(PROV_DEVICE_TRANSPORT_HANDLE handle)
+{
+    /* Codes_PROV_TRANSPORT_MQTT_WS_CLIENT_07_007: [ prov_transport_mqtt_ws_dowork shall invoke the prov_transport_common_mqtt_dowork method ] */
+    prov_transport_common_mqtt_dowork(handle);
+}
+
+int prov_transport_mqtt_ws_set_trace(PROV_DEVICE_TRANSPORT_HANDLE handle, bool trace_on)
+{
+    /* Codes_PROV_TRANSPORT_MQTT_WS_CLIENT_07_008: [ prov_transport_mqtt_ws_set_trace shall invoke the prov_transport_common_mqtt_set_trace method ] */
+    return prov_transport_common_mqtt_set_trace(handle, trace_on);
+}
+
+static int prov_transport_mqtt_ws_x509_cert(PROV_DEVICE_TRANSPORT_HANDLE handle, const char* certificate, const char* private_key)
+{
+    /* Codes_PROV_TRANSPORT_MQTT_WS_CLIENT_07_009: [ prov_transport_mqtt_ws_x509_cert shall invoke the prov_trans_common_mqtt_x509_cert method ] */
+    return prov_transport_common_mqtt_x509_cert(handle, certificate, private_key);
+}
+
+static int prov_transport_mqtt_ws_set_trusted_cert(PROV_DEVICE_TRANSPORT_HANDLE handle, const char* certificate)
+{
+    /* Codes_PROV_TRANSPORT_MQTT_WS_CLIENT_07_010: [ prov_transport_mqtt_ws_set_trusted_cert shall invoke the prov_transport_common_mqtt_set_trusted_cert method ] */
+    return prov_transport_common_mqtt_set_trusted_cert(handle, certificate);
+}
+
+static int prov_transport_mqtt_ws_set_proxy(PROV_DEVICE_TRANSPORT_HANDLE handle, const HTTP_PROXY_OPTIONS* proxy_options)
+{
+    /* Codes_PROV_TRANSPORT_MQTT_WS_CLIENT_07_011: [ prov_transport_mqtt_ws_set_proxy shall invoke the prov_transport_common_mqtt_set_proxy method ] */
+    return prov_transport_common_mqtt_set_proxy(handle, proxy_options);
+}
+
+static int prov_transport_mqtt_ws_set_option(PROV_DEVICE_TRANSPORT_HANDLE handle, const char* option, const void* value)
+{
+    return prov_transport_common_mqtt_set_option(handle, option, value);
+}
+
+static PROV_DEVICE_TRANSPORT_PROVIDER prov_mqtt_func =
+{
+    prov_transport_mqtt_ws_create,
+    prov_transport_mqtt_ws_destroy,
+    prov_transport_mqtt_ws_open,
+    prov_transport_mqtt_ws_close,
+    prov_transport_mqtt_ws_register_device,
+    prov_transport_mqtt_ws_get_operation_status,
+    prov_transport_mqtt_ws_dowork,
+    prov_transport_mqtt_ws_set_trace,
+    prov_transport_mqtt_ws_x509_cert,
+    prov_transport_mqtt_ws_set_trusted_cert,
+    prov_transport_mqtt_ws_set_proxy,
+    prov_transport_mqtt_ws_set_option
+};
+
+const PROV_DEVICE_TRANSPORT_PROVIDER* Prov_Device_MQTT_WS_Protocol(void)
+{
+    return &prov_mqtt_func;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/agenttypesystem.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/agenttypesystem.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/agenttypesystem.h	(revision 453)
@@ -0,0 +1,718 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef AGENT_DATA_TYPES_H
+#define AGENT_DATA_TYPES_H
+
+#ifdef __cplusplus
+#include <cstdint>
+#include <ctime>
+#include <cstddef>
+#else
+#if ((defined _WIN32_WCE) && _WIN32_WCE==0x0600)
+#include "stdint_ce6.h"
+#else
+#include <stdint.h>
+#endif
+#include <stddef.h>
+#endif
+
+#include "azure_c_shared_utility/agenttime.h"
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/strings.h"
+
+/*Codes_SRS_AGENT_TYPE_SYSTEM_99_001:[ AGENT_TYPE_SYSTEM shall have the following interface]*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*the following forward declarations the closest implementation to "interface" in OOP*/
+struct AGENT_DATA_TYPE_TAG;
+typedef struct AGENT_DATA_TYPE_TAG AGENT_DATA_TYPE;
+
+/*this file contains the definitions of the data types of EDM*/
+/*the types are taken from */
+/*http://docs.oasis-open.org/odata/odata/v4.0/cos01/part3-csdl/odata-v4.0-cos01-part3-csdl.html*/
+/*chapter 4.4 - "Primitive Data Types" */
+
+/*the C implementation of these types follows:*/
+/*even the simpler types are encapsulated in structs to purposely avoid compiler promotions/casts etc*/
+
+/*Binary data.*/
+typedef struct EDM_BINARY_TAG
+{
+    size_t size;
+    unsigned char* data;
+}EDM_BINARY;
+
+#define EDM_BOOLEANS_VALUES \
+    EDM_TRUE, \
+    EDM_FALSE
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(EDM_BOOLEANS, EDM_BOOLEANS_VALUES);
+
+/*ispositiveinfinity*/
+
+#ifdef _MSC_VER
+#define ISPOSITIVEINFINITY(x) ((_finite((x))==0) && ((_fpclass((x)) & _FPCLASS_PINF) == _FPCLASS_PINF))
+#else
+#if defined __STDC_VERSION__
+#if ((__STDC_VERSION__  == 199901L) || (__STDC_VERSION__ == 201112L) || (__STDC_VERSION__ == 201710L))
+/*C99, C11 or C18 compiler*/
+#define ISPOSITIVEINFINITY(x) (isinf((x)) && (signbit((x))==0))
+#else
+#error update this file to contain the latest C standard.
+#endif
+#else
+#ifdef __cplusplus
+#define ISPOSITIVEINFINITY(x) (std::isinf((x)) && (signbit((x))==0))
+#else
+#error unknown (or C89) compiler, must provide a definition for ISPOSITIVEINFINITY
+#endif
+#endif
+#endif
+
+#ifdef _MSC_VER
+/*not exactly signbit*/
+#define ISNEGATIVEINFINITY(x) ((_finite((x))==0) && ((_fpclass((x)) & _FPCLASS_NINF) == _FPCLASS_NINF))
+#else
+#if defined __STDC_VERSION__
+#if ((__STDC_VERSION__  == 199901L) || (__STDC_VERSION__ == 201112L) || (__STDC_VERSION__ == 201710L))
+/*C99, C11 or C18 compiler*/
+#define ISNEGATIVEINFINITY(x) (isinf((x)) && (signbit((x))!=0))
+#else
+#error update this file to contain the latest C standard.
+#endif
+#else
+#ifdef __cplusplus
+#define ISNEGATIVEINFINITY(x) (std::isinf((x)) && (signbit((x)) != 0))
+#else
+#error unknown (or C89) compiler, must provide a definition for ISNEGATIVEINFINITY
+#endif
+#endif
+#endif
+
+/*Binary-valued logic.*/
+typedef struct EDM_BOOLEAN_TAG
+{
+    EDM_BOOLEANS value;
+}EDM_BOOLEAN;
+
+/*Unsigned 8-bit integer*/
+typedef struct EDM_BYTE_TAG
+{
+    uint8_t value;
+} EDM_BYTE;
+
+/*Date without a time-zone offset*/
+/*The edm:Date expression evaluates to a primitive date value. A date expression MUST be assigned a
+value of type xs:date, see [XML-Schema-2], section 3.3.9. The value MUST also conform to rule
+dateValue in [OData-ABNF], i.e. it MUST NOT contain a time-zone offset.*/
+/*section 3.3.9: date uses the date/timeSevenPropertyModel, with hour, minute, and second required to be absent.*/
+/*dateValue in OData-ABNF is : dateValue = year "-" month "-" day */
+/*year  = [ "-" ] ( "0" 3DIGIT / oneToNine 3*DIGIT )
+month = "0" oneToNine
+/ "1" ( "0" / "1" / "2" )
+day   = "0" oneToNine
+/ ( "1" / "2" ) DIGIT
+/ "3" ( "0" / "1" )*/
+typedef struct EDM_DATE_TAG
+{
+    int16_t year; /*can represent all values for a year*/ /*they can be between -9999 and 9999*/
+    uint8_t month;
+    uint8_t day;
+} EDM_DATE;
+
+
+/*The edm:DateTimeOffset expression evaluates to a primitive date/time value with a time-zone offset.
+A date/time expression MUST be assigned a value of type xs:dateTimeStamp, see [XML-Schema-2],
+section 3.4.28. The value MUST also conform to rule dateTimeOffsetValue in [OData-ABNF], i.e. it
+MUST NOT contain an end-of-day fragment (24:00:00).*/
+/*section 3.4.28 says : dateTimeStampLexicalRep ::= yearFrag '-' monthFrag '-' dayFrag 'T' ((hourFrag ':' minuteFrag ':' secondFrag) | endOfDayFrag) timezoneFrag?*/
+/*[OData-ABNF] says: dateTimeOffsetValue = year "-" month "-" day "T" hour ":" minute [ ":" second [ "." fractionalSeconds ] ] ( "Z" / sign hour ":" minute )*/
+/*fractionalSeconds = 1*12DIGIT, FYI*/
+typedef struct EDM_DATE_TIME_OFFSET_TAG
+{
+    struct tm dateTime;
+    uint8_t hasFractionalSecond;
+    uint64_t fractionalSecond; /*because UINT32 only has 10 digits*/
+    uint8_t hasTimeZone;
+    int8_t timeZoneHour;
+    uint8_t timeZoneMinute;
+}EDM_DATE_TIME_OFFSET;
+
+/*Edm.Guid*/
+/*16-byte (128-bit) unique identifier*/
+/*The edm:Guid expression evaluates to a primitive 32-character string value. A guid expression MUST be
+assigned a value conforming to the rule guidValue in [OData-ABNF].*/
+/*guidValue is 8HEXDIG "-" 4HEXDIG "-" 4HEXDIG "-" 4HEXDIG "-" 12HEXDIG*/
+typedef struct EDM_GUID_TAG
+{
+    uint8_t GUID[16];
+}EDM_GUID;
+
+
+/*Edm.Decimal*/
+/*The edm:Decimal expression evaluates to a primitive decimal value. A decimal expression MUST be
+assigned a value conforming to the rule decimalValue in [OData-ABNF].*/
+/*[OData-ABNF] says: decimalValue = [SIGN] 1*DIGIT ["." 1*DIGIT] */
+/* this is binary coded decimal style then*/
+typedef struct EDM_DECIMAL_TAG
+{
+    STRING_HANDLE value;
+} EDM_DECIMAL;
+
+/*Edm.Double*/
+/*IEEE 754 binary64 floating-point number (15-17 decimal digits)*/
+
+typedef struct EDM_DOUBLE_TAG
+{
+    double value;
+} EDM_DOUBLE;
+
+
+/*Edm.Duration*/
+/*Signed duration in days, hours, minutes, and (sub)seconds*/
+/*The edm:Duration expression evaluates to a primitive duration value. A duration expression MUST be
+assigned a value of type xs:dayTimeDuration, see [XML-Schema-2], section 3.4.27.*/
+/*XML-Schema section 3.4.27 says: "[...]leaving only those with day, hour, minutes, and/or seconds fields." */
+/*day is "unsignedNoDecimalPtNumeral" and that can have as many digits... ?*/
+typedef struct EDM_DURATION_TAG
+{
+    size_t nDigits;
+    char* digits;
+}
+EDM_DURATION;
+
+
+/*Edm.Int16*/
+/*Signed 16-bit integer*/
+/*[OData=ABNF] says about Int16:  numbers in the range from -32768 to 32767 */
+/*this is not C compliant, because C89 has for (read:guarantees) short SHRT_MIN -32767... (notice how it misses -32768)*/
+/*C99 has the same*/
+/*C11 has the same*/
+/*platform types has to check for -32768 compliance*/
+typedef struct EDM_INT16_TAG
+{
+    int16_t value;
+} EDM_INT16;
+
+/*Edm.Int32*/
+/*Signed 32-bit integer*/
+/*OData-ABNF has for int32Value = [ sign ] 1*10DIGIT ; numbers in the range from -2147483648 to 2147483647*/
+/*same issue as for EDM_16*/
+/*platform types has to check compliance based on LONG_MIN #define*/
+typedef struct EDM_INT32_TAG
+{
+    int32_t value;
+} EDM_INT32;
+
+/*Edm.Int64*/
+/*Signed 64-bit integer*/
+/*OData=ABNF: int64Value = [ sign ] 1*19DIGIT ; numbers in the range from -9223372036854775808 to 9223372036854775807*/
+/*C89 has no mention of anything on 64bits*/
+/*C99 mention LLONG_MIN as -9223372036854775807 and LLONG_MAX as 9223372036854775807*/
+/*C11 is the same as C99*/
+typedef struct EDM_INT64_TAG
+{
+    int64_t value; /*SINT64 might be a single type or s truct provided by platformTypes, depending on C compiler support*/
+} EDM_INT64;
+
+/*Edm.SByte*/
+/*Signed 8-bit integer*/
+/*OData=ABNF: sbyteValue = [ sign ] 1*3DIGIT  ; numbers in the range from -128 to 127*/
+/*C89, C99, C11 all have SCHAR_MIN, SCHAR_MAX between -127 and 127 (guaranteed)*/
+/*so platformTypes.h has to check that -128 is attainable*/
+typedef struct EDM_SBYTE_TAG
+{
+    int8_t value;
+} EDM_SBYTE;
+
+/*Edm.Single*/
+/*IEEE 754 binary32 floating-point number (6-9 decimal digits)*/
+/*with the same "fears" as for Edm.Double*/
+typedef struct EDM_SINGLE_TAG
+{
+    float value;
+} EDM_SINGLE;
+
+/*not clear what this is
+typedef EDM_STREAM_TAG
+{
+
+}EDM_STREAM;
+*/
+
+/*Edm.String*/
+/*Sequence of UTF-8 characters*/
+typedef struct EDM_STRING_TAG
+{
+    size_t length; /*number of unsigned char* in the string*/
+    char* chars;
+} EDM_STRING;
+
+/*Edm.TimeOfDay*/
+/*Clock time 00:00-23:59:59.999999999999*/
+/*The edm:TimeOfDay expression evaluates to a primitive time value. A time-of-day expression MUST be
+assigned a value conforming to the rule timeOfDayValue in [OData-ABNF].*/
+/*timeOfDayValue = hour ":" minute [ ":" second [ "." fractionalSeconds ] ]*/
+typedef struct EDM_TIME_OF_DAY_TAG
+{
+    uint8_t hour;
+    uint8_t minute;
+    uint8_t second;
+    uint64_t fractionalSecond;
+}EDM_TIME_OF_DAY;
+
+/*positionLiteral  = doubleValue SP doubleValue  ; longitude, then latitude*/
+typedef struct EDM_POSITION_LITERAL_TAG
+{
+    double longitude;
+    double latitude;
+}EDM_POSITION_LITERAL;
+
+
+/*sridLiteral      = "SRID" EQ 1*5DIGIT SEMI*/
+typedef struct EDM_SRID_LITERAL_TAG
+{
+    uint16_t digits;
+} EDM_SRID_LITERAL;
+
+/*lineStringData        = OPEN positionLiteral 1*( COMMA positionLiteral ) CLOSE*/
+typedef struct EDM_LINE_STRING_DATA_TAG
+{
+    size_t nPositionLiterals;
+    EDM_POSITION_LITERAL *positionLiterals;
+}EDM_LINE_STRING_DATA;
+
+/*pointData        = OPEN positionLiteral CLOSE*/
+typedef struct EDM_POINT_DATA_TAG
+{
+    EDM_POSITION_LITERAL positionLiteral;
+}EDM_POINT_DATA;
+
+/*ringLiteral        = OPEN positionLiteral *( COMMA positionLiteral ) CLOSE*/
+typedef struct EDM_RING_LITERAL_TAG
+{
+    size_t nPositionLiterals;
+    EDM_POSITION_LITERAL *positionLiterals;
+}EDM_RING_LITERAL;
+
+/*pointLiteral     ="Point" pointData*/
+typedef struct EDM_POINT_LITERAL_TAG
+{
+    EDM_POINT_DATA pointData;
+} EDM_POINT_LITERAL;
+
+/*polygonData        = OPEN ringLiteral *( COMMA ringLiteral ) CLOSE*/
+typedef struct EDM_POLYGON_DATA_TAG
+{
+    size_t nRingLiterals;
+    EDM_RING_LITERAL *ringLiterals;
+}EDM_POLYGON_DATA;
+
+/*polygonLiteral     = "Polygon" polygonData*/
+typedef struct EDM_POLYGON_LITERAL_TAG
+{
+    EDM_POLYGON_DATA polygonData;
+}EDM_POLYGON_LITERAL;
+
+/*fullPolygonLiteral = sridLiteral polygonLiteral*/
+typedef struct EDM_FULL_POLYGON_LITERAL_TAG
+{
+    EDM_SRID_LITERAL srid;
+    EDM_POLYGON_LITERAL polygonLiteral;
+}EDM_FULL_POLYGON_LITERAL;
+
+/*fullPointLiteral = sridLiteral pointLiteral*/
+typedef struct EDM_FULL_POINT_LITERAL_TAG
+{
+    EDM_SRID_LITERAL srid;
+    EDM_POINT_LITERAL pointLiteral;
+} EDM_FULL_POINT_LITERAL;
+
+/*geographyPoint   = geographyPrefix SQUOTE fullPointLiteral SQUOTE*/
+typedef struct EDM_GEOGRAPHY_POINT_TAG
+{
+    EDM_FULL_POINT_LITERAL fullPointLiteral;
+}EDM_GEOGRAPHY_POINT;
+
+/*multiPolygonLiteral     = "MultiPolygon(" [ polygonData *( COMMA polygonData ) ] CLOSE*/
+typedef struct EDM_MULTI_POLYGON_LITERAL_TAG
+{
+    size_t nPolygonDatas;
+    EDM_POLYGON_DATA * polygonDatas;
+}EDM_MULTI_POLYGON_LITERAL;
+
+/*fullMultiPolygonLiteral = sridLiteral multiPolygonLiteral*/
+typedef struct EDM_FULL_MULTI_POLYGON_LITERAL_TAG
+{
+    EDM_SRID_LITERAL srid;
+    EDM_MULTI_POLYGON_LITERAL multiPolygonLiteral;
+}EDM_FULL_MULTI_POLYGON_LITERAL;
+
+/*multiPointLiteral     = "MultiPoint(" [ pointData *( COMMA pointData ) ] CLOSE*/
+typedef struct EDM_MULTI_POINT_LITERAL_TAG
+{
+    size_t nPointDatas;
+    EDM_POINT_DATA *pointDatas;
+}EDM_MULTI_POINT_LITERAL;
+
+/*fullMultiPointLiteral = sridLiteral multiPointLiteral*/
+typedef struct EDM_FULL_MULTI_POINT_LITERAL_TAG
+{
+    EDM_SRID_LITERAL srid;
+    EDM_MULTI_POINT_LITERAL multiPointLiteral;
+}EDM_FULL_MULTI_POINT_LITERAL;
+
+/*lineStringLiteral     = "LineString" lineStringData*/
+typedef struct EDM_LINE_STRING_LITERAL_TAG
+{
+    EDM_LINE_STRING_DATA lineStringData;
+}EDM_LINE_STRING_LITERAL;
+
+/*fullLineStringLiteral = sridLiteral lineStringLiteral*/
+typedef struct EDM_FULL_LINE_STRING_LITERAL_TAG
+{
+    EDM_SRID_LITERAL srid;
+    EDM_LINE_STRING_LITERAL lineStringLiteral;
+} EDM_FULL_LINE_STRING_LITERAL;
+
+/*multiLineStringLiteral     = "MultiLineString(" [ lineStringData *( COMMA lineStringData ) ] CLOSE*/
+typedef struct EDM_MULTI_LINE_STRING_LITERAL_TAG
+{
+    size_t nLineStringDatas;
+    EDM_LINE_STRING_DATA lineStringData;
+}EDM_MULTI_LINE_STRING_LITERAL;
+
+/*fullMultiLineStringLiteral = sridLiteral multiLineStringLiteral*/
+typedef struct EDM_FULL_MULTI_LINE_STRING_LITERAL_TAG
+{
+    EDM_SRID_LITERAL srid;
+    EDM_MULTI_LINE_STRING_LITERAL multiLineStringLiteral;
+}EDM_FULL_MULTI_LINE_STRING_LITERAL;
+
+
+
+/*forward defines*/
+struct EDM_GEO_LITERAL_TAG;
+typedef struct EDM_GEO_LITERAL_TAG EDM_GEO_LITERAL;
+
+/*collectionLiteral     = "Collection(" geoLiteral *( COMMA geoLiteral ) CLOSE*/
+typedef struct EDM_COLLECTION_LITERAL_TAG
+{
+    size_t nGeoLiterals;
+    EDM_GEO_LITERAL* geoLiterals;
+} EDM_COLLECTION_LITERAL;
+
+/*geoLiteral            = collectionLiteral
+/ lineStringLiteral
+/ multiPointLiteral
+/ multiLineStringLiteral
+/ multiPolygonLiteral
+/ pointLiteral
+/ polygonLiteral
+*/
+typedef enum EDM_GEO_LITERAL_TYPE_TAG
+{
+    EDM_COLLECTION_LITERAL_TYPE,
+    EDM_LINE_STRING_LITERAL_TYPE,
+    EDM_MULTI_POINT_LITERAL_TYPE,
+    EDM_MULTI_LINE_STRING_LITERAL_TYPE,
+    EDM_MULTI_POLIGON_LITERAL_TYPE,
+    EDM_POINT_LITERAL_TYPE,
+    EDM_POLYGON_LITERAL_TYPE
+}EDM_GEO_LITERAL_TYPE;
+
+struct EDM_GEO_LITERAL_TAG
+{
+    EDM_GEO_LITERAL_TYPE literalType;
+    union
+    {
+        EDM_COLLECTION_LITERAL collectionLiteral;
+        EDM_LINE_STRING_LITERAL lineStringLiteral;
+        EDM_MULTI_POINT_LITERAL multiPointLiteral;
+        EDM_MULTI_LINE_STRING_LITERAL multiLineStringLiteral;
+        EDM_MULTI_POLYGON_LITERAL multiPolygonLiteral;
+        EDM_POINT_LITERAL pointLiteral;
+        EDM_POLYGON_LITERAL polygonLiteral;
+    } u;
+};
+
+/*fullCollectionLiteral = sridLiteral collectionLiteral*/
+typedef struct EDM_FULL_COLLECTION_LITERAL_TAG
+{
+    EDM_SRID_LITERAL srid;
+    EDM_COLLECTION_LITERAL collectionLiteral;
+}EDM_FULL_COLLECTION_LITERAL;
+
+/*now geography stuff*/
+
+/*geographyCollection   = geographyPrefix SQUOTE fullCollectionLiteral SQUOTE*/
+typedef struct EDM_GEOGRAPHY_COLLECTION_TAG
+{
+    EDM_FULL_COLLECTION_LITERAL fullCollectionLiteral;
+}EDM_GEOGRAPHY_COLLECTION;
+
+/*geographyLineString   = geographyPrefix SQUOTE fullLineStringLiteral SQUOTE*/
+typedef struct EDM_GEOGRAPHY_LINE_STRING_TAG
+{
+    EDM_FULL_LINE_STRING_LITERAL fullLineStringLiteral;
+}EDM_GEOGRAPHY_LINE_STRING;
+
+/*geographyMultiLineString   = geographyPrefix SQUOTE fullMultiLineStringLiteral SQUOTE*/
+typedef struct EDM_GEOGRAPHY_MULTI_LINE_STRING_TAG
+{
+    EDM_FULL_MULTI_LINE_STRING_LITERAL fullMultiLineStringLiteral;
+}EDM_GEOGRAPHY_MULTI_LINE_STRING;
+
+/*geographyMultiPoint   = geographyPrefix SQUOTE fullMultiPointLiteral SQUOTE*/
+typedef struct EDM_GEOGRAPHY_MULTI_POINT_TAG
+{
+    EDM_FULL_MULTI_POINT_LITERAL fullMultiPointLiteral;
+}EDM_GEOGRAPHY_MULTI_POINT;
+
+/*geographyMultiPolygon   = geographyPrefix SQUOTE fullMultiPolygonLiteral SQUOTE*/
+typedef struct EDM_GEOGRAPHY_MULTI_POLYGON_TAG
+{
+    EDM_FULL_MULTI_POLYGON_LITERAL fullMultiPolygonLiteral;
+}EDM_GEOGRAPHY_MULTI_POLYGON;
+
+/*geographyPolygon   = geographyPrefix SQUOTE fullPolygonLiteral SQUOTE*/
+typedef struct EDM_GEOGRAPHY_POLYGON_TAG
+{
+    EDM_FULL_POLYGON_LITERAL fullPolygonLiteral;
+}EDM_GEOGRAPHY_POLYGON;
+
+/*geometryCollection      = geometryPrefix SQUOTE fullCollectionLiteral      SQUOTE*/
+/*forward defines*/
+
+
+/*geometryPolygon         = geometryPrefix SQUOTE fullPolygonLiteral         SQUOTE*/
+typedef struct EDM_GEOMETRY_POLYGON_TAG
+{
+    EDM_FULL_POLYGON_LITERAL fullPolygonLiteral;
+}EDM_GEOMETRY_POLYGON;
+
+/*geometryPoint           = geometryPrefix SQUOTE fullPointLiteral           SQUOTE*/
+typedef struct EDM_GEOMETRY_POINT_TAG
+{
+    EDM_FULL_POINT_LITERAL fullPointLiteral;
+}EDM_GEOMETRY_POINT;
+
+/*geometryMultiPolygon    = geometryPrefix SQUOTE fullMultiPolygonLiteral    SQUOTE*/
+typedef struct EDM_GEOMETRY_MULTI_POLYGON_TAG
+{
+    EDM_FULL_MULTI_POLYGON_LITERAL fullMultiPolygonLiteral;
+}
+EDM_GEOMETRY_MULTI_POLYGON;
+
+/*geometryMultiPoint      = geometryPrefix SQUOTE fullMultiPointLiteral      SQUOTE*/
+typedef struct EDM_GEOMETRY_MULTI_POINT_TAG
+{
+    EDM_FULL_MULTI_POINT_LITERAL fullMultiPointLiteral;
+}EDM_GEOMETRY_MULTI_POINT;
+
+/*geometryMultiLineString = geometryPrefix SQUOTE fullMultiLineStringLiteral SQUOTE*/
+typedef struct EDM_GEOMETRY_MULTI_LINE_STRING_TAG
+{
+    EDM_FULL_MULTI_LINE_STRING_LITERAL fullMultiLineStringLiteral;
+}EDM_GEOMETRY_MULTI_LINE_STRING;
+
+/*geometryLineString      = geometryPrefix SQUOTE fullLineStringLiteral      SQUOTE*/
+typedef struct EDM_GEOMETRY_LINE_STRING_TAG
+{
+    EDM_FULL_LINE_STRING_LITERAL fullLineStringLiteral;
+}EDM_GEOMETRY_LINE_STRING;
+
+/*geometryCollection      = geometryPrefix SQUOTE fullCollectionLiteral      SQUOTE*/
+typedef struct EDM_GEOMETRY_COLLECTION_TAG
+{
+    EDM_FULL_COLLECTION_LITERAL fullCollectionLiteral;
+}EDM_GEOMETRY_COLLECTION;
+
+/*holds the name and the value of a COMPLEX_TYPE... field*/
+typedef struct COMPLEX_TYPE_FIELD_TAG
+{
+    const char* fieldName;
+    AGENT_DATA_TYPE* value;
+}COMPLEX_TYPE_FIELD_TYPE;
+
+/*EDM_COMPLEX_TYPE - this type doesn't exist in EDMX as a primitive type*/
+typedef struct EDM_COMPLEX_TYPE_TAG
+{
+    size_t nMembers;
+    COMPLEX_TYPE_FIELD_TYPE *fields;
+}EDM_COMPLEX_TYPE;
+
+#define AGENT_DATA_TYPES_RESULT_VALUES \
+    AGENT_DATA_TYPES_OK, \
+    AGENT_DATA_TYPES_ERROR, \
+    AGENT_DATA_TYPES_INVALID_ARG, \
+    AGENT_DATA_TYPES_NOT_IMPLEMENTED, \
+    AGENT_DATA_TYPES_JSON_ENCODER_ERRROR
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(AGENT_DATA_TYPES_RESULT, AGENT_DATA_TYPES_RESULT_VALUES);
+
+#define AGENT_DATA_TYPE_TYPE_VALUES\
+    EDM_NO_TYPE,                                                                   \
+    EDM_BINARY_TYPE,                                                               \
+    EDM_BOOLEAN_TYPE,                                                              \
+    EDM_BYTE_TYPE,                                                                 \
+    EDM_DATE_TYPE,                                                                 \
+    EDM_DATE_TIME_OFFSET_TYPE,                                                     \
+    EDM_DECIMAL_TYPE,                                                              \
+    EDM_DOUBLE_TYPE,                                                               \
+    EDM_DURATION_TYPE,                                                             \
+    EDM_GUID_TYPE,                                                                 \
+    EDM_INT16_TYPE,                                                                \
+    EDM_INT32_TYPE,                                                                \
+    EDM_INT64_TYPE,                                                                \
+    EDM_SBYTE_TYPE,                                                                \
+    EDM_SINGLE_TYPE,                                                               \
+    EDM_STREAM, /*not supported, because what is stream?*/                         \
+    EDM_STRING_TYPE,                                                               \
+    EDM_TIME_OF_DAY_TYPE,                                                          \
+    EDM_GEOGRAPHY_TYPE, /*not supported because what is "abstract base type"*/     \
+    EDM_GEOGRAPHY_POINT_TYPE,                                                      \
+    EDM_GEOGRAPHY_LINE_STRING_TYPE,                                                \
+    EDM_GEOGRAPHY_POLYGON_TYPE,                                                    \
+    EDM_GEOGRAPHY_MULTI_POINT_TYPE,                                                \
+    EDM_GEOGRAPHY_MULTI_LINE_STRING_TYPE,                                          \
+    EDM_GEOGRAPHY_MULTI_POLYGON_TYPE,                                              \
+    EDM_GEOGRAPHY_COLLECTION_TYPE,                                                 \
+    EDM_GEOMETRY_TYPE, /*not supported because what is "abstract base type"*/      \
+    EDM_GEOMETRY_POINT_TYPE,                                                       \
+    EDM_GEOMETRY_LINE_STRING_TYPE,                                                 \
+    EDM_GEOMETRY_POLYGON_TYPE,                                                     \
+    EDM_GEOMETRY_MULTI_POINT_TYPE,                                                 \
+    EDM_GEOMETRY_MULTI_LINE_STRING_TYPE,                                           \
+    EDM_GEOMETRY_MULTI_POLYGON_TYPE,                                               \
+    EDM_GEOMETRY_COLLECTION_TYPE,                                                  \
+    EDM_COMPLEX_TYPE_TYPE,                                                         \
+    EDM_NULL_TYPE,                                                                 \
+    EDM_ENTITY_TYPE_TYPE,                                                          \
+    EDM_STRING_NO_QUOTES_TYPE                                                      \
+
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(AGENT_DATA_TYPE_TYPE, AGENT_DATA_TYPE_TYPE_VALUES);
+
+struct AGENT_DATA_TYPE_TAG
+{
+    AGENT_DATA_TYPE_TYPE type;
+    union
+    {
+        EDM_BINARY edmBinary;
+        EDM_BOOLEAN edmBoolean;
+        EDM_BYTE edmByte;
+        EDM_DATE edmDate;
+        EDM_DATE_TIME_OFFSET edmDateTimeOffset;
+        EDM_DECIMAL edmDecimal;
+        EDM_DOUBLE edmDouble;
+        EDM_DURATION edmDuration;
+        EDM_GUID edmGuid;
+        EDM_INT16 edmInt16;
+        EDM_INT32 edmInt32;
+        EDM_INT64 edmInt64;
+        EDM_SBYTE edmSbyte;
+        EDM_SINGLE edmSingle;
+        /*EDM_STREAM, not supported, because what is stream?*/
+        EDM_STRING edmString;
+        EDM_STRING edmStringNoQuotes;
+        EDM_TIME_OF_DAY edmTimeOfDay;
+        /*EDM_GEOGRAPHY_, not supported because what is "abstract base type"*/
+        EDM_GEOGRAPHY_POINT edmGeographyPoint;
+        EDM_GEOGRAPHY_LINE_STRING edmGeographyLineString;
+        EDM_GEOGRAPHY_POLYGON edmGeographyPolygon;
+        EDM_GEOGRAPHY_MULTI_POINT edmGeographyMultiPoint;
+        EDM_GEOGRAPHY_MULTI_LINE_STRING edmGeographyMultiLineString;
+        EDM_GEOGRAPHY_MULTI_POLYGON edmGeographyMultiPolygon;
+        EDM_GEOGRAPHY_COLLECTION edmGeographyCollection;
+        /* EDM_GEOMETRY_, not supported because what is "abstract base type"*/
+        EDM_GEOMETRY_POINT edmGeometryPoint;
+        EDM_GEOMETRY_LINE_STRING edmGeometryLineString;
+        EDM_GEOMETRY_POLYGON edmGeometryPolygon;
+        EDM_GEOMETRY_MULTI_POINT edmGeometryMultiPoint;
+        EDM_GEOMETRY_MULTI_LINE_STRING edmGeoemtryMultiLineString;
+        EDM_GEOMETRY_MULTI_POLYGON edmGeometryMultiPolygon;
+        EDM_GEOMETRY_COLLECTION edmGeometryCollection;
+        EDM_COMPLEX_TYPE edmComplexType;
+    } value;
+};
+
+#include "umock_c/umock_c_prod.h"
+
+MOCKABLE_FUNCTION(, AGENT_DATA_TYPES_RESULT, AgentDataTypes_ToString, STRING_HANDLE, destination, const AGENT_DATA_TYPE*, value);
+
+/*Create/Destroy work in pairs. For some data type not calling Uncreate might be ok. For some, it will lead to memory leaks*/
+
+/*creates an AGENT_DATA_TYPE containing a EDM_BOOLEAN from a int*/
+MOCKABLE_FUNCTION(, AGENT_DATA_TYPES_RESULT, Create_EDM_BOOLEAN_from_int, AGENT_DATA_TYPE*, agentData, int, v);
+
+/*creates an AGENT_DATA_TYPE containing a UINT8*/
+MOCKABLE_FUNCTION(, AGENT_DATA_TYPES_RESULT, Create_AGENT_DATA_TYPE_from_UINT8, AGENT_DATA_TYPE*, agentData, uint8_t, v);
+
+/*creates an AGENT_DATA_TYPE containing a EDM_DATE */
+MOCKABLE_FUNCTION(, AGENT_DATA_TYPES_RESULT, Create_AGENT_DATA_TYPE_from_date, AGENT_DATA_TYPE*, agentData, int16_t, year, uint8_t, month, uint8_t, day);
+
+/*create an AGENT_DATA_TYPE containing an EDM_DECIMAL from a string representation*/
+MOCKABLE_FUNCTION(, AGENT_DATA_TYPES_RESULT, Create_EDM_DECIMAL_from_charz, AGENT_DATA_TYPE*, agentData, const char*, v);
+
+/*create an AGENT_DATA_TYPE containing an EDM_DOUBLE from a double*/
+MOCKABLE_FUNCTION(, AGENT_DATA_TYPES_RESULT, Create_AGENT_DATA_TYPE_from_DOUBLE, AGENT_DATA_TYPE*, agentData, double, v);
+
+/*create an AGENT_DATA_TYPE from INT16_T*/
+MOCKABLE_FUNCTION(, AGENT_DATA_TYPES_RESULT, Create_AGENT_DATA_TYPE_from_SINT16, AGENT_DATA_TYPE*, agentData, int16_t, v);
+
+/*create an AGENT_DATA_TYPE from INT32_T*/
+MOCKABLE_FUNCTION(, AGENT_DATA_TYPES_RESULT, Create_AGENT_DATA_TYPE_from_SINT32, AGENT_DATA_TYPE*, agentData, int32_t, v);
+
+/*create an AGENT_DATA_TYPE from INT64_T*/
+MOCKABLE_FUNCTION(, AGENT_DATA_TYPES_RESULT, Create_AGENT_DATA_TYPE_from_SINT64, AGENT_DATA_TYPE*, agentData, int64_t, v);
+
+/*create an AGENT_DATA_TYPE from int8_t*/
+MOCKABLE_FUNCTION(, AGENT_DATA_TYPES_RESULT, Create_AGENT_DATA_TYPE_from_SINT8, AGENT_DATA_TYPE*, agentData, int8_t, v);
+
+/*Codes_SRS_AGENT_TYPE_SYSTEM_99_091:[Creates an AGENT_DATA_TYPE containing an Edm.DateTimeOffset from an EDM_DATE_TIME_OFFSET.]*/
+MOCKABLE_FUNCTION(, AGENT_DATA_TYPES_RESULT, Create_AGENT_DATA_TYPE_from_EDM_DATE_TIME_OFFSET, AGENT_DATA_TYPE*, agentData, EDM_DATE_TIME_OFFSET, v);
+
+/*creates an AGENT_DATA_TYPE containing a EDM_GUID*/
+MOCKABLE_FUNCTION(, AGENT_DATA_TYPES_RESULT, Create_AGENT_DATA_TYPE_from_EDM_GUID, AGENT_DATA_TYPE*, agentData, EDM_GUID, v);
+
+/*creates an AGENT_DATA_TYPE containing a EDM_BINARY*/
+MOCKABLE_FUNCTION(, AGENT_DATA_TYPES_RESULT, Create_AGENT_DATA_TYPE_from_EDM_BINARY, AGENT_DATA_TYPE*, agentData, EDM_BINARY, v);
+
+/*create an AGENT_DATA_TYPE from SINGLE*/
+MOCKABLE_FUNCTION(, AGENT_DATA_TYPES_RESULT, Create_AGENT_DATA_TYPE_from_FLOAT, AGENT_DATA_TYPE*, agentData, float, v);
+
+/*create an AGENT_DATA_TYPE from ANSI zero terminated string*/
+MOCKABLE_FUNCTION(, AGENT_DATA_TYPES_RESULT, Create_AGENT_DATA_TYPE_from_charz, AGENT_DATA_TYPE*, agentData, const char*, v);
+
+/*create an AGENT_DATA_TYPE from ANSI zero terminated string (no quotes)*/
+MOCKABLE_FUNCTION(, AGENT_DATA_TYPES_RESULT, Create_AGENT_DATA_TYPE_from_charz_no_quotes, AGENT_DATA_TYPE*, agentData, const char*, v);
+
+/*create an AGENT_DATA_TYPE of type EDM_NULL_TYPE */
+MOCKABLE_FUNCTION(, AGENT_DATA_TYPES_RESULT, Create_NULL_AGENT_DATA_TYPE, AGENT_DATA_TYPE*, agentData);
+
+/*create an AGENT_DATA_TYPE that holds a structs from its fields*/
+MOCKABLE_FUNCTION(, AGENT_DATA_TYPES_RESULT, Create_AGENT_DATA_TYPE_from_Members, AGENT_DATA_TYPE*,agentData, const char*, typeName, size_t, nMembers, const char* const *, memberNames, const AGENT_DATA_TYPE*, memberValues);
+
+/*create a complex AGENT_DATA_TYPE from pointers to AGENT_DATA_TYPE fields*/
+MOCKABLE_FUNCTION(, AGENT_DATA_TYPES_RESULT, Create_AGENT_DATA_TYPE_from_MemberPointers, AGENT_DATA_TYPE*, agentData, const char*, typeName, size_t, nMembers, const char* const *, memberNames, const AGENT_DATA_TYPE** ,memberPointerValues);
+
+/*creates a copy of the AGENT_DATA_TYPE*/
+MOCKABLE_FUNCTION(, AGENT_DATA_TYPES_RESULT, Create_AGENT_DATA_TYPE_from_AGENT_DATA_TYPE, AGENT_DATA_TYPE*, dest, const AGENT_DATA_TYPE*, src);
+
+MOCKABLE_FUNCTION(, void, Destroy_AGENT_DATA_TYPE, AGENT_DATA_TYPE*, agentData);
+
+MOCKABLE_FUNCTION(, AGENT_DATA_TYPES_RESULT, CreateAgentDataType_From_String, const char*, source, AGENT_DATA_TYPE_TYPE, type, AGENT_DATA_TYPE*, agentData);
+
+MOCKABLE_FUNCTION(, COMPLEX_TYPE_FIELD_TYPE*, AgentDataType_GetComplexTypeField, AGENT_DATA_TYPE*, agentData, size_t, index);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/codefirst.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/codefirst.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/codefirst.h	(revision 453)
@@ -0,0 +1,191 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef CODEFIRST_H
+#define CODEFIRST_H
+
+#include "methodreturn.h"
+#include "agenttypesystem.h"
+#include "schema.h"
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/strings.h"
+#include "iotdevice.h"
+
+#ifdef __cplusplus
+#include <cstddef>
+#include <cstdarg>
+extern "C" {
+#else
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#endif
+
+typedef char* ascii_char_ptr;
+typedef char* ascii_char_ptr_no_quotes;
+
+typedef enum REFLECTION_TYPE_TAG
+{
+    REFLECTION_METHOD_TYPE,
+    REFLECTION_DESIRED_PROPERTY_TYPE,
+    REFLECTION_REPORTED_PROPERTY_TYPE,
+    REFLECTION_STRUCT_TYPE,
+    REFLECTION_FIELD_TYPE,
+    REFLECTION_PROPERTY_TYPE,
+    REFLECTION_ACTION_TYPE,
+    REFLECTION_MODEL_TYPE,
+    REFLECTION_NOTHING
+}REFLECTION_TYPE;
+
+typedef EXECUTE_COMMAND_RESULT (*actionWrapper)(void* device, size_t ParameterCount, const AGENT_DATA_TYPE* values);
+
+typedef METHODRETURN_HANDLE (*methodWrapper)(void* device, size_t ParameterCount, const AGENT_DATA_TYPE* values);
+
+typedef struct REFLECTION_STRUCT_TAG
+{
+    const char* name;
+}REFLECTION_STRUCT;
+
+typedef struct WRAPPER_ARGUMENT_TAG
+{
+    const char* type;
+    const char* name;
+}WRAPPER_ARGUMENT;
+
+typedef struct REFLECTION_ACTION_TAG
+{
+    const char* name;
+    size_t nArguments;
+    const WRAPPER_ARGUMENT* arguments;
+    actionWrapper wrapper;
+    const char* modelName;
+}REFLECTION_ACTION;
+
+typedef struct REFLECTION_METHOD_TAG
+{
+    const char* name;
+    size_t nArguments;
+    const WRAPPER_ARGUMENT* arguments;
+    methodWrapper wrapper;
+    const char* modelName;
+}REFLECTION_METHOD;
+
+typedef struct REFLECTION_FIELD_TAG
+{
+    const char* fieldName;
+    const char* fieldType;
+    const char* structName;
+}REFLECTION_FIELD;
+
+typedef struct REFLECTION_PROPERTY_TAG
+{
+    const char* name;
+    const char* type;
+    int(*Create_AGENT_DATA_TYPE_from_Ptr)(void* param, AGENT_DATA_TYPE* dest);
+    size_t offset;
+    size_t size;
+    const char* modelName;
+} REFLECTION_PROPERTY;
+
+
+typedef struct REFLECTION_REPORTED_PROPERTY_TAG
+{
+    const char* name;
+    const char* type;
+    int(*Create_AGENT_DATA_TYPE_from_Ptr)(void* param, AGENT_DATA_TYPE* dest);
+    size_t offset;
+    size_t size;
+    const char* modelName;
+} REFLECTION_REPORTED_PROPERTY;
+
+typedef struct REFLECTION_DESIRED_PROPERTY_TAG
+{
+    pfOnDesiredProperty onDesiredProperty;
+    void(*desiredPropertInitialize)(void* destination);
+    void(*desiredPropertDeinitialize)(void* destination);
+    const char* name;
+    const char* type;
+    int(*FromAGENT_DATA_TYPE)(const AGENT_DATA_TYPE* source, void* dest); /*destination is "something" everytime. When the DESIRED_PROPERTY is a MODEL, the function is empty*/
+    size_t offset;
+    size_t size;
+    const char* modelName;
+} REFLECTION_DESIRED_PROPERTY;
+
+typedef struct REFLECTION_MODEL_TAG
+{
+    const char* name;
+} REFLECTION_MODEL;
+
+typedef struct REFLECTED_SOMETHING_TAG
+{
+    REFLECTION_TYPE type;
+    const struct REFLECTED_SOMETHING_TAG* next;
+    struct what
+    {
+        REFLECTION_METHOD method;
+        REFLECTION_DESIRED_PROPERTY desiredProperty;
+        REFLECTION_REPORTED_PROPERTY reportedProperty;
+        REFLECTION_STRUCT structure;
+        REFLECTION_FIELD field;
+        REFLECTION_PROPERTY property;
+        REFLECTION_ACTION action;
+        REFLECTION_MODEL model;
+    } what;
+} REFLECTED_SOMETHING;
+
+typedef struct REFLECTED_DATA_FROM_DATAPROVIDER_TAG
+{
+    const REFLECTED_SOMETHING* reflectedData;
+}REFLECTED_DATA_FROM_DATAPROVIDER;
+
+#define ALL_SOMETHING_REFLECTED(schemaNamespace) MU_C2(schemaNamespace, _allSomethingReflected)
+#define ALL_REFLECTED(schemaNamespace) MU_C2(schemaNamespace, _allReflected)
+#define ADDRESS_OF_ALL_REFLECTED(schemaNamespace) & MU_C2(schemaNamespace, _allReflected),
+#define DECLARE_EXTERN_CONST_DATAPROVIDER_DATA(x) extern const REFLECTED_DATA_FROM_DATAPROVIDER ALL_REFLECTED(x);
+
+#define CODEFIRST_RESULT_VALUES                \
+CODEFIRST_OK,                                  \
+CODEFIRST_INVALID_ARG,                         \
+CODEFIRST_ALREADY_INIT,                        \
+CODEFIRST_NOT_INIT,                            \
+CODEFIRST_ERROR,                               \
+CODEFIRST_NOT_ENOUGH_MEMORY,                   \
+CODEFIRST_ACTION_NOT_FOUND,                    \
+CODEFIRST_ACTION_EXECUTION_ERROR,              \
+CODEFIRST_SCHEMA_ERROR,                        \
+CODEFIRST_AGENT_DATA_TYPE_ERROR,               \
+CODEFIRST_VALUES_FROM_DIFFERENT_DEVICES_ERROR, \
+CODEFIRST_DEVICE_FAILED,                       \
+CODEFIRST_DEVICE_PUBLISH_FAILED,               \
+CODEFIRST_NOT_A_PROPERTY
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(CODEFIRST_RESULT, CODEFIRST_RESULT_VALUES)
+
+#include "umock_c/umock_c_prod.h"
+MOCKABLE_FUNCTION(, CODEFIRST_RESULT, CodeFirst_Init, const char*, overrideSchemaNamespace);
+MOCKABLE_FUNCTION(, void, CodeFirst_Deinit);
+MOCKABLE_FUNCTION(, SCHEMA_HANDLE, CodeFirst_RegisterSchema, const char*, schemaNamespace, const REFLECTED_DATA_FROM_DATAPROVIDER*, metadata);
+
+MOCKABLE_FUNCTION(, EXECUTE_COMMAND_RESULT, CodeFirst_InvokeAction, DEVICE_HANDLE, deviceHandle, void*, callbackUserContext, const char*, relativeActionPath, const char*, actionName, size_t, parameterCount, const AGENT_DATA_TYPE*, parameterValues);
+
+MOCKABLE_FUNCTION(, METHODRETURN_HANDLE, CodeFirst_InvokeMethod, DEVICE_HANDLE, deviceHandle, void*, callbackUserContext, const char*, relativeMethodPath, const char*, methodName, size_t, parameterCount, const AGENT_DATA_TYPE*, parameterValues);
+
+MOCKABLE_FUNCTION(, EXECUTE_COMMAND_RESULT, CodeFirst_ExecuteCommand, void*, device, const char*, command);
+
+MOCKABLE_FUNCTION(, METHODRETURN_HANDLE, CodeFirst_ExecuteMethod, void*, device, const char*, methodName, const char*, methodPayload);
+
+MOCKABLE_FUNCTION(, void*, CodeFirst_CreateDevice, SCHEMA_MODEL_TYPE_HANDLE, model, const REFLECTED_DATA_FROM_DATAPROVIDER*, metadata, size_t, dataSize, bool, includePropertyPath);
+MOCKABLE_FUNCTION(, void, CodeFirst_DestroyDevice, void*, device);
+
+extern CODEFIRST_RESULT CodeFirst_SendAsync(unsigned char** destination, size_t* destinationSize, size_t numProperties, ...);
+extern CODEFIRST_RESULT CodeFirst_SendAsyncReported(unsigned char** destination, size_t* destinationSize, size_t numReportedProperties, ...);
+
+MOCKABLE_FUNCTION(, CODEFIRST_RESULT, CodeFirst_IngestDesiredProperties, void*, device, const char*, jsonPayload, bool, parseDesiredNode);
+
+MOCKABLE_FUNCTION(, AGENT_DATA_TYPE_TYPE, CodeFirst_GetPrimitiveType, const char*, typeName);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CODEFIRST_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/commanddecoder.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/commanddecoder.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/commanddecoder.h	(revision 453)
@@ -0,0 +1,55 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef COMMAND_DECODER_H
+#define COMMAND_DECODER_H
+
+#include "multitree.h"
+#include "schema.h"
+#include "agenttypesystem.h"
+#include "azure_macro_utils/macro_utils.h"
+#include "methodreturn.h"
+
+#ifdef __cplusplus
+extern "C" {
+#else
+#include <stdbool.h>
+#endif
+
+#define COMMANDDECODER_RESULT_VALUES \
+    COMMANDDECODER_OK, \
+    COMMANDDECODER_ERROR, \
+    COMMANDDECODER_INVALID_ARG
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(COMMANDDECODER_RESULT, COMMANDDECODER_RESULT_VALUES)
+
+#define EXECUTE_COMMAND_RESULT_VALUES \
+EXECUTE_COMMAND_SUCCESS, /*when the final recipient of the command indicates a successful execution*/ \
+EXECUTE_COMMAND_FAILED, /*when the final recipient of the command indicates a failure*/ \
+EXECUTE_COMMAND_ERROR /*when a transient error either in the final recipient or until the final recipient*/
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(EXECUTE_COMMAND_RESULT, EXECUTE_COMMAND_RESULT_VALUES)
+
+
+
+
+/* Codes_SRS_COMMAND_DECODER_99_001:[ The CommandDecoder module shall expose the following API:] */
+
+typedef struct COMMAND_DECODER_HANDLE_DATA_TAG* COMMAND_DECODER_HANDLE;
+typedef EXECUTE_COMMAND_RESULT(*ACTION_CALLBACK_FUNC)(void* actionCallbackContext, const char* relativeActionPath, const char* actionName, size_t argCount, const AGENT_DATA_TYPE* args);
+typedef METHODRETURN_HANDLE(*METHOD_CALLBACK_FUNC)(void* methodCallbackContext, const char* relativeMethodPath, const char* methodName, size_t argCount, const AGENT_DATA_TYPE* args);
+
+#include "umock_c/umock_c_prod.h"
+
+MOCKABLE_FUNCTION(,COMMAND_DECODER_HANDLE, CommandDecoder_Create, SCHEMA_MODEL_TYPE_HANDLE, modelHandle, ACTION_CALLBACK_FUNC, actionCallback, void*, actionCallbackContext, METHOD_CALLBACK_FUNC, methodCallback, void*, methodCallbackContext);
+MOCKABLE_FUNCTION(,EXECUTE_COMMAND_RESULT, CommandDecoder_ExecuteCommand, COMMAND_DECODER_HANDLE, handle, const char*, command);
+MOCKABLE_FUNCTION(,METHODRETURN_HANDLE, CommandDecoder_ExecuteMethod, COMMAND_DECODER_HANDLE, handle, const char*, fullMethodName, const char*, methodPayload);
+MOCKABLE_FUNCTION(,void, CommandDecoder_Destroy, COMMAND_DECODER_HANDLE, commandDecoderHandle);
+
+MOCKABLE_FUNCTION(, EXECUTE_COMMAND_RESULT, CommandDecoder_IngestDesiredProperties, void*, startAddress, COMMAND_DECODER_HANDLE, handle, const char*, jsonPayload, bool, parseDesiredNode);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* COMMAND_DECODER_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/datamarshaller.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/datamarshaller.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/datamarshaller.h	(revision 453)
@@ -0,0 +1,51 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef DATAMARSHALLER_H
+#define DATAMARSHALLER_H
+
+#include <stdbool.h>
+#include "agenttypesystem.h"
+#include "schema.h"
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/vector.h"
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*Codes_SRS_DATA_MARSHALLER_99_002:[ DataMarshaller shall have the following interface]*/
+#define DATA_MARSHALLER_RESULT_VALUES           \
+DATA_MARSHALLER_OK,                             \
+DATA_MARSHALLER_INVALID_ARG,                    \
+DATA_MARSHALLER_NO_DEVICE_IDENTITY,             \
+DATA_MARSHALLER_SCHEMA_FAILED,                  \
+DATA_MARSHALLER_INVALID_MODEL_PROPERTY,         \
+DATA_MARSHALLER_JSON_ENCODER_ERROR,             \
+DATA_MARSHALLER_ERROR,                          \
+DATA_MARSHALLER_AGENT_DATA_TYPES_ERROR,         \
+DATA_MARSHALLER_MULTITREE_ERROR,                \
+DATA_MARSHALLER_ONLY_ONE_VALUE_ALLOWED          \
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(DATA_MARSHALLER_RESULT, DATA_MARSHALLER_RESULT_VALUES);
+
+typedef struct DATA_MARSHALLER_VALUE_TAG
+{
+    const char* PropertyPath;
+    const AGENT_DATA_TYPE* Value;
+} DATA_MARSHALLER_VALUE;
+
+typedef struct DATA_MARSHALLER_HANDLE_DATA_TAG* DATA_MARSHALLER_HANDLE;
+#include "umock_c/umock_c_prod.h"
+
+MOCKABLE_FUNCTION(,DATA_MARSHALLER_HANDLE, DataMarshaller_Create, SCHEMA_MODEL_TYPE_HANDLE, modelHandle, bool, includePropertyPath);
+MOCKABLE_FUNCTION(,void, DataMarshaller_Destroy, DATA_MARSHALLER_HANDLE, dataMarshallerHandle);
+MOCKABLE_FUNCTION(,DATA_MARSHALLER_RESULT, DataMarshaller_SendData, DATA_MARSHALLER_HANDLE, dataMarshallerHandle, size_t, valueCount, const DATA_MARSHALLER_VALUE*, values, unsigned char**, destination, size_t*, destinationSize);
+
+MOCKABLE_FUNCTION(, DATA_MARSHALLER_RESULT, DataMarshaller_SendData_ReportedProperties, DATA_MARSHALLER_HANDLE, dataMarshallerHandle, VECTOR_HANDLE, values, unsigned char**, destination, size_t*, destinationSize);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DATAMARSHALLER_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/datapublisher.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/datapublisher.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/datapublisher.h	(revision 453)
@@ -0,0 +1,54 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef DATA_PUBLISHER_H
+#define DATA_PUBLISHER_H
+
+#include "agenttypesystem.h"
+#include "schema.h"
+/* Normally we could include <stdbool> for cpp, but some toolchains are not well behaved and simply don't have it - ARM CC for example */
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DATA_PUBLISHER_RESULT_VALUES    \
+DATA_PUBLISHER_OK,                      \
+DATA_PUBLISHER_INVALID_ARG,             \
+DATA_PUBLISHER_MARSHALLER_ERROR,        \
+DATA_PUBLISHER_EMPTY_TRANSACTION,       \
+DATA_PUBLISHER_AGENT_DATA_TYPES_ERROR,  \
+DATA_PUBLISHER_SCHEMA_FAILED,           \
+DATA_PUBLISHER_BUFFER_STORAGE_ERROR,    \
+DATA_PUBLISHER_ERROR
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(DATA_PUBLISHER_RESULT, DATA_PUBLISHER_RESULT_VALUES);
+
+#include "umock_c/umock_c_prod.h"
+
+typedef struct TRANSACTION_HANDLE_DATA_TAG* TRANSACTION_HANDLE;
+typedef struct REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA_TAG* REPORTED_PROPERTIES_TRANSACTION_HANDLE;
+typedef struct DATA_PUBLISHER_HANDLE_DATA_TAG* DATA_PUBLISHER_HANDLE;
+
+MOCKABLE_FUNCTION(,DATA_PUBLISHER_HANDLE, DataPublisher_Create, SCHEMA_MODEL_TYPE_HANDLE, modelHandle, bool, includePropertyPath);
+MOCKABLE_FUNCTION(,void, DataPublisher_Destroy, DATA_PUBLISHER_HANDLE, dataPublisherHandle);
+
+MOCKABLE_FUNCTION(,TRANSACTION_HANDLE, DataPublisher_StartTransaction, DATA_PUBLISHER_HANDLE, dataPublisherHandle);
+MOCKABLE_FUNCTION(,DATA_PUBLISHER_RESULT, DataPublisher_PublishTransacted, TRANSACTION_HANDLE, transactionHandle, const char*, propertyPath, const AGENT_DATA_TYPE*, data);
+MOCKABLE_FUNCTION(,DATA_PUBLISHER_RESULT, DataPublisher_EndTransaction, TRANSACTION_HANDLE, transactionHandle, unsigned char**, destination, size_t*, destinationSize);
+MOCKABLE_FUNCTION(,DATA_PUBLISHER_RESULT, DataPublisher_CancelTransaction, TRANSACTION_HANDLE, transactionHandle);
+MOCKABLE_FUNCTION(,void, DataPublisher_SetMaxBufferSize, size_t, value);
+MOCKABLE_FUNCTION(,size_t, DataPublisher_GetMaxBufferSize);
+
+MOCKABLE_FUNCTION(, REPORTED_PROPERTIES_TRANSACTION_HANDLE, DataPublisher_CreateTransaction_ReportedProperties, DATA_PUBLISHER_HANDLE, dataPublisherHandle);
+MOCKABLE_FUNCTION(, DATA_PUBLISHER_RESULT, DataPublisher_PublishTransacted_ReportedProperty, REPORTED_PROPERTIES_TRANSACTION_HANDLE, transactionHandle, const char*, reportedPropertyPath, const AGENT_DATA_TYPE*, data);
+MOCKABLE_FUNCTION(, DATA_PUBLISHER_RESULT, DataPublisher_CommitTransaction_ReportedProperties, REPORTED_PROPERTIES_TRANSACTION_HANDLE, transactionHandle, unsigned char**, destination, size_t*, destinationSize);
+MOCKABLE_FUNCTION(, void, DataPublisher_DestroyTransaction_ReportedProperties, REPORTED_PROPERTIES_TRANSACTION_HANDLE, transactionHandle);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DATA_PUBLISHER_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/dataserializer.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/dataserializer.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/dataserializer.h	(revision 453)
@@ -0,0 +1,42 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef DATASERIALIZER_H
+#define DATASERIALIZER_H
+
+#include "azure_macro_utils/macro_utils.h"
+#include "multitree.h"
+#include "azure_c_shared_utility/buffer_.h"
+
+#ifdef __cplusplus
+#include <cstddef>
+extern "C"
+{
+#else
+#include <stddef.h>
+#endif
+
+/*Codes_SRS_DATA_SERIALIZER_07_001: [DataSerializer will have the following interface]*/
+#define DATA_SERIALIZER_RESULT_VALUES           \
+DATA_SERIALIZER_INVALID_ARG,                    \
+DATA_SERIALIZER_ERROR                            \
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(DATA_SERIALIZER_RESULT, DATA_SERIALIZER_RESULT_VALUES);
+
+#define DATA_SERIALIZER_MULTITREE_TYPE_VALUES   \
+    DATA_SERIALIZER_TYPE_CHAR_PTR,              \
+    DATA_SERIALIZER_TYPE_AGENT_DATA             \
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(DATA_SERIALIZER_MULTITREE_TYPE, DATA_SERIALIZER_MULTITREE_TYPE_VALUES);
+
+typedef BUFFER_HANDLE (*DATA_SERIALIZER_ENCODE_FUNC)(MULTITREE_HANDLE multiTreeHandle, DATA_SERIALIZER_MULTITREE_TYPE dataType);
+typedef MULTITREE_HANDLE (*DATA_SERIALIZER_DECODE_FUNC)(BUFFER_HANDLE decodeData);
+
+extern BUFFER_HANDLE DataSerializer_Encode(MULTITREE_HANDLE multiTreeHandle, DATA_SERIALIZER_MULTITREE_TYPE dataType, DATA_SERIALIZER_ENCODE_FUNC encodeFunc);
+extern MULTITREE_HANDLE DataSerializer_Decode(BUFFER_HANDLE data, DATA_SERIALIZER_DECODE_FUNC decodeFunc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // DATASERIALIZER_H
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/iotdevice.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/iotdevice.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/iotdevice.h	(revision 453)
@@ -0,0 +1,58 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef IOTDEVICE_H
+#define IOTDEVICE_H
+
+#include <stdbool.h>
+#include "azure_macro_utils/macro_utils.h"
+#include "schema.h"
+#include "datapublisher.h"
+#include "commanddecoder.h"
+#include "methodreturn.h"
+
+#ifdef __cplusplus
+#include <cstddef>
+extern "C" {
+#else
+#include <stddef.h>
+#endif
+
+#define DEVICE_RESULT_VALUES            \
+    DEVICE_OK,                            \
+    DEVICE_INVALID_ARG,                    \
+    DEVICE_DATA_PUBLISHER_FAILED,        \
+    DEVICE_COMMAND_DECODER_FAILED,        \
+    DEVICE_ERROR
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(DEVICE_RESULT, DEVICE_RESULT_VALUES)
+
+#include "umock_c/umock_c_prod.h"
+
+typedef struct DEVICE_HANDLE_DATA_TAG* DEVICE_HANDLE;
+typedef EXECUTE_COMMAND_RESULT (*pfDeviceActionCallback)(DEVICE_HANDLE deviceHandle, void* callbackUserContext, const char* relativeActionPath, const char* actionName, size_t argCount, const AGENT_DATA_TYPE* args);
+typedef METHODRETURN_HANDLE    (*pfDeviceMethodCallback)(DEVICE_HANDLE deviceHandle, void* callbackUserContext, const char* relativeMethodPath, const char* methodName, size_t argCount, const AGENT_DATA_TYPE* args);
+
+MOCKABLE_FUNCTION(,DEVICE_RESULT, Device_Create, SCHEMA_MODEL_TYPE_HANDLE, modelHandle, pfDeviceActionCallback, deviceActionCallback, void*, callbackUserContext, pfDeviceMethodCallback, methodCallback, void*, methodCallbackContext, bool, includePropertyPath, DEVICE_HANDLE*, deviceHandle);
+MOCKABLE_FUNCTION(, void, Device_Destroy, DEVICE_HANDLE, deviceHandle);
+
+MOCKABLE_FUNCTION(,TRANSACTION_HANDLE, Device_StartTransaction, DEVICE_HANDLE, deviceHandle);
+MOCKABLE_FUNCTION(,DEVICE_RESULT, Device_PublishTransacted, TRANSACTION_HANDLE, transactionHandle, const char*, propertyPath, const AGENT_DATA_TYPE*, data);
+MOCKABLE_FUNCTION(,DEVICE_RESULT, Device_EndTransaction, TRANSACTION_HANDLE, transactionHandle, unsigned char**, destination, size_t*, destinationSize);
+MOCKABLE_FUNCTION(,DEVICE_RESULT, Device_CancelTransaction, TRANSACTION_HANDLE, transactionHandle);
+
+MOCKABLE_FUNCTION(, REPORTED_PROPERTIES_TRANSACTION_HANDLE, Device_CreateTransaction_ReportedProperties, DEVICE_HANDLE, deviceHandle);
+MOCKABLE_FUNCTION(, DEVICE_RESULT, Device_PublishTransacted_ReportedProperty, REPORTED_PROPERTIES_TRANSACTION_HANDLE, transactionHandle, const char*, reportedPropertyPath, const AGENT_DATA_TYPE*, data);
+MOCKABLE_FUNCTION(, DEVICE_RESULT, Device_CommitTransaction_ReportedProperties, REPORTED_PROPERTIES_TRANSACTION_HANDLE, transactionHandle, unsigned char**, destination, size_t*, destinationSize);
+MOCKABLE_FUNCTION(, void, Device_DestroyTransaction_ReportedProperties, REPORTED_PROPERTIES_TRANSACTION_HANDLE, transactionHandle);
+
+MOCKABLE_FUNCTION(, EXECUTE_COMMAND_RESULT, Device_ExecuteCommand, DEVICE_HANDLE, deviceHandle, const char*, command);
+MOCKABLE_FUNCTION(, METHODRETURN_HANDLE, Device_ExecuteMethod, DEVICE_HANDLE, deviceHandle, const char*, methodName, const char*, methodPayload);
+
+MOCKABLE_FUNCTION(, DEVICE_RESULT, Device_IngestDesiredProperties, void*, startAddress, DEVICE_HANDLE, deviceHandle, const char*, jsonPayload, bool, parseDesiredNode);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IOTDEVICE_H */
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/jsondecoder.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/jsondecoder.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/jsondecoder.h	(revision 453)
@@ -0,0 +1,33 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef JSONDECODER_H
+#define JSONDECODER_H
+
+#include "multitree.h"
+
+#ifdef __cplusplus
+#include <cstddef>
+extern "C" {
+#else
+#include <stddef.h>
+#endif
+
+#include "umock_c/umock_c_prod.h"
+
+#define JSON_DECODER_RESULT_VALUES      \
+    JSON_DECODER_OK,                    \
+    JSON_DECODER_INVALID_ARG,           \
+    JSON_DECODER_PARSE_ERROR,           \
+    JSON_DECODER_MULTITREE_FAILED,      \
+    JSON_DECODER_ERROR                  \
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(JSON_DECODER_RESULT, JSON_DECODER_RESULT_VALUES);
+
+MOCKABLE_FUNCTION(, JSON_DECODER_RESULT, JSONDecoder_JSON_To_MultiTree, char*, json, MULTITREE_HANDLE*, multiTreeHandle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* JSONDECODER_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/jsonencoder.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/jsonencoder.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/jsonencoder.h	(revision 453)
@@ -0,0 +1,48 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef JSONENCODER_H
+#define JSONENCODER_H
+
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/strings.h"
+
+#ifdef __cplusplus
+#include "cstddef"
+extern "C" {
+#else
+#include "stddef.h"
+#endif
+
+#include "multitree.h"
+
+#define JSON_ENCODER_RESULT_VALUES           \
+JSON_ENCODER_OK,                             \
+JSON_ENCODER_INVALID_ARG,                    \
+JSON_ENCODER_ALREADY_EXISTS,                 \
+JSON_ENCODER_MULTITREE_ERROR,                \
+JSON_ENCODER_TOSTRING_FUNCTION_ERROR,        \
+JSON_ENCODER_ERROR
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(JSON_ENCODER_RESULT, JSON_ENCODER_RESULT_VALUES);
+
+#define JSON_ENCODER_TOSTRING_RESULT_VALUES  \
+JSON_ENCODER_TOSTRING_OK,                    \
+JSON_ENCODER_TOSTRING_INVALID_ARG,           \
+JSON_ENCODER_TOSTRING_ERROR
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(JSON_ENCODER_TOSTRING_RESULT, JSON_ENCODER_TOSTRING_RESULT_VALUES);
+
+typedef JSON_ENCODER_TOSTRING_RESULT(*JSON_ENCODER_TOSTRING_FUNC)(STRING_HANDLE, const void* value);
+
+#include "umock_c/umock_c_prod.h"
+
+MOCKABLE_FUNCTION(, JSON_ENCODER_TOSTRING_RESULT, JSONEncoder_CharPtr_ToString, STRING_HANDLE, destination, const void*, value);
+MOCKABLE_FUNCTION(, JSON_ENCODER_RESULT, JSONEncoder_EncodeTree, MULTITREE_HANDLE, treeHandle, STRING_HANDLE, destination, JSON_ENCODER_TOSTRING_FUNC, toStringFunc);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* JSONENCODER_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/methodreturn.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/methodreturn.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/methodreturn.h	(revision 453)
@@ -0,0 +1,34 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef METHODRETURN_H
+#define METHODRETURN_H
+
+typedef struct METHODRETURN_HANDLE_DATA_TAG* METHODRETURN_HANDLE;
+
+#include "azure_macro_utils/macro_utils.h"
+
+typedef struct METHODRETURN_DATA_TAG
+{
+    int statusCode;
+    char* jsonValue;
+}METHODRETURN_DATA;
+
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+MOCKABLE_FUNCTION(, METHODRETURN_HANDLE, MethodReturn_Create, int, statusCode, const char*, jsonValue);
+MOCKABLE_FUNCTION(, void, MethodReturn_Destroy, METHODRETURN_HANDLE, handle);
+MOCKABLE_FUNCTION(, const METHODRETURN_DATA*, MethodReturn_GetReturn, METHODRETURN_HANDLE, handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /*METHODRETURN_H*/
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/multitree.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/multitree.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/multitree.h	(revision 453)
@@ -0,0 +1,54 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef MULTITREE_H
+#define MULTITREE_H
+
+#include "azure_c_shared_utility/strings.h"
+#include "azure_macro_utils/macro_utils.h"
+
+#ifdef __cplusplus
+#include <cstddef>
+extern "C"
+{
+#else
+#include <stddef.h>
+#include <stdbool.h>
+#endif
+
+typedef struct MULTITREE_HANDLE_DATA_TAG* MULTITREE_HANDLE;
+
+#define MULTITREE_RESULT_VALUES           \
+    MULTITREE_OK,                         \
+    MULTITREE_INVALID_ARG,                \
+    MULTITREE_ALREADY_HAS_A_VALUE,        \
+    MULTITREE_EMPTY_CHILD_NAME,           \
+    MULTITREE_EMPTY_VALUE,                \
+    MULTITREE_OUT_OF_RANGE_INDEX,         \
+    MULTITREE_ERROR,                      \
+    MULTITREE_CHILD_NOT_FOUND             \
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(MULTITREE_RESULT, MULTITREE_RESULT_VALUES);
+
+typedef void (*MULTITREE_FREE_FUNCTION)(void* value);
+typedef int (*MULTITREE_CLONE_FUNCTION)(void** destination, const void* source);
+
+#include "umock_c/umock_c_prod.h"
+MOCKABLE_FUNCTION(, MULTITREE_HANDLE, MultiTree_Create, MULTITREE_CLONE_FUNCTION, cloneFunction, MULTITREE_FREE_FUNCTION, freeFunction);
+MOCKABLE_FUNCTION(, MULTITREE_RESULT, MultiTree_AddLeaf, MULTITREE_HANDLE, treeHandle, const char*, destinationPath, const void*, value);
+MOCKABLE_FUNCTION(, MULTITREE_RESULT, MultiTree_AddChild, MULTITREE_HANDLE, treeHandle, const char*, childName, MULTITREE_HANDLE*, childHandle);
+MOCKABLE_FUNCTION(, MULTITREE_RESULT, MultiTree_GetChildCount, MULTITREE_HANDLE, treeHandle, size_t*, count);
+MOCKABLE_FUNCTION(, MULTITREE_RESULT, MultiTree_GetChild, MULTITREE_HANDLE, treeHandle, size_t, index, MULTITREE_HANDLE*, childHandle);
+MOCKABLE_FUNCTION(, MULTITREE_RESULT, MultiTree_GetChildByName, MULTITREE_HANDLE, treeHandle, const char*, childName, MULTITREE_HANDLE*, childHandle);
+MOCKABLE_FUNCTION(, MULTITREE_RESULT, MultiTree_GetName, MULTITREE_HANDLE, treeHandle, STRING_HANDLE, destination);
+MOCKABLE_FUNCTION(, MULTITREE_RESULT, MultiTree_GetValue, MULTITREE_HANDLE, treeHandle, const void**, destination);
+MOCKABLE_FUNCTION(, MULTITREE_RESULT, MultiTree_GetLeafValue, MULTITREE_HANDLE, treeHandle, const char*, leafPath, const void**, destination);
+MOCKABLE_FUNCTION(, MULTITREE_RESULT, MultiTree_SetValue, MULTITREE_HANDLE, treeHandle, void*, value);
+MOCKABLE_FUNCTION(, void, MultiTree_Destroy, MULTITREE_HANDLE, treeHandle);
+MOCKABLE_FUNCTION(, MULTITREE_RESULT, MultiTree_DeleteChild, MULTITREE_HANDLE, treeHandle, const char*, childName);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/schema.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/schema.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/schema.h	(revision 453)
@@ -0,0 +1,178 @@
+// Copyright (c) Microsoft. All rights reserved.MOCKABLE_FUNCTION(,
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef SCHEMA_H
+#define SCHEMA_H
+
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "agenttypesystem.h"
+
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+#include <cstddef>
+extern "C" {
+#else
+#include <stddef.h>
+#endif
+
+/* Codes_SRS_SCHEMA_99_095: [Schema shall expose the following API:] */
+
+typedef struct SCHEMA_HANDLE_DATA_TAG* SCHEMA_HANDLE;
+typedef struct SCHEMA_MODEL_TYPE_HANDLE_DATA_TAG* SCHEMA_MODEL_TYPE_HANDLE;
+typedef struct SCHEMA_STRUCT_TYPE_HANDLE_DATA_TAG* SCHEMA_STRUCT_TYPE_HANDLE;
+typedef struct SCHEMA_PROPERTY_HANDLE_DATA_TAG* SCHEMA_PROPERTY_HANDLE;
+typedef struct SCHEMA_REPORTED_PROPERTY_HANDLE_DATA_TAG* SCHEMA_REPORTED_PROPERTY_HANDLE;
+typedef struct SCHEMA_DESIRED_PROPERTY_HANDLE_DATA_TAG* SCHEMA_DESIRED_PROPERTY_HANDLE;
+typedef struct SCHEMA_ACTION_HANDLE_DATA_TAG* SCHEMA_ACTION_HANDLE;
+typedef struct SCHEMA_ACTION_ARGUMENT_HANDLE_DATA_TAG* SCHEMA_ACTION_ARGUMENT_HANDLE;
+typedef struct SCHEMA_METHOD_ARGUMENT_HANDLE_DATA_TAG* SCHEMA_METHOD_ARGUMENT_HANDLE;
+typedef struct SCHEMA_METHOD_HANDLE_DATA_TAG* SCHEMA_METHOD_HANDLE;
+
+
+typedef void(*pfOnDesiredProperty)(void* model);
+typedef int(*pfDesiredPropertyFromAGENT_DATA_TYPE)(const AGENT_DATA_TYPE* source, void* dest);
+typedef void(*pfDesiredPropertyInitialize)(void* destination);
+typedef void(*pfDesiredPropertyDeinitialize)(void* destination);
+
+
+#define SCHEMA_RESULT_VALUES    \
+SCHEMA_OK,                      \
+SCHEMA_INVALID_ARG,             \
+SCHEMA_DUPLICATE_ELEMENT,       \
+SCHEMA_ELEMENT_NOT_FOUND,       \
+SCHEMA_MODEL_IN_USE,            \
+SCHEMA_DEVICE_COUNT_ZERO,       \
+SCHEMA_ERROR
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(SCHEMA_RESULT, SCHEMA_RESULT_VALUES)
+
+#define SCHEMA_ELEMENT_TYPE_VALUES \
+SCHEMA_NOT_FOUND, \
+SCHEMA_SEARCH_INVALID_ARG, \
+SCHEMA_PROPERTY, \
+SCHEMA_REPORTED_PROPERTY, \
+SCHEMA_DESIRED_PROPERTY, \
+SCHEMA_MODEL_ACTION, \
+SCHEMA_MODEL_IN_MODEL
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(SCHEMA_ELEMENT_TYPE, SCHEMA_ELEMENT_TYPE_VALUES);
+
+typedef struct SCHEMA_MODEL_ELEMENT_TAG
+{
+    SCHEMA_ELEMENT_TYPE elementType;
+    union ELEMENT_HANDLE_UNION_TAG
+    {
+        SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle;
+        SCHEMA_PROPERTY_HANDLE propertyHandle;
+        SCHEMA_REPORTED_PROPERTY_HANDLE reportedPropertyHandle;
+        SCHEMA_ACTION_HANDLE actionHandle;
+        SCHEMA_MODEL_TYPE_HANDLE modelHandle;
+    } elementHandle;
+}SCHEMA_MODEL_ELEMENT;
+
+MOCKABLE_FUNCTION(, SCHEMA_HANDLE, Schema_Create, const char*, schemaNamespace, void*, metadata);
+MOCKABLE_FUNCTION(, void*, Schema_GetMetadata, SCHEMA_HANDLE, schemaHandle);
+MOCKABLE_FUNCTION(, size_t, Schema_GetSchemaCount);
+MOCKABLE_FUNCTION(, SCHEMA_HANDLE, Schema_GetSchemaByNamespace, const char*, schemaNamespace);
+MOCKABLE_FUNCTION(, SCHEMA_HANDLE, Schema_GetSchemaForModel, const char*, modelName);
+MOCKABLE_FUNCTION(, const char*, Schema_GetSchemaNamespace, SCHEMA_HANDLE, schemaHandle);
+MOCKABLE_FUNCTION(, SCHEMA_RESULT, Schema_AddDeviceRef, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle);
+MOCKABLE_FUNCTION(, SCHEMA_RESULT, Schema_ReleaseDeviceRef, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle);
+
+MOCKABLE_FUNCTION(, SCHEMA_MODEL_TYPE_HANDLE, Schema_CreateModelType, SCHEMA_HANDLE, schemaHandle, const char*, modelName);
+MOCKABLE_FUNCTION(, SCHEMA_HANDLE, Schema_GetSchemaForModelType, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle);
+MOCKABLE_FUNCTION(, const char*, Schema_GetModelName, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle);
+
+MOCKABLE_FUNCTION(, SCHEMA_STRUCT_TYPE_HANDLE, Schema_CreateStructType, SCHEMA_HANDLE, schemaHandle, const char*, structTypeName);
+
+MOCKABLE_FUNCTION(, const char*, Schema_GetStructTypeName, SCHEMA_STRUCT_TYPE_HANDLE, structTypeHandle);
+
+MOCKABLE_FUNCTION(, SCHEMA_RESULT, Schema_AddStructTypeProperty, SCHEMA_STRUCT_TYPE_HANDLE, structTypeHandle, const char*, propertyName, const char*, propertyType);
+
+MOCKABLE_FUNCTION(, SCHEMA_RESULT, Schema_AddModelProperty, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, const char*, propertyName, const char*, propertyType);
+MOCKABLE_FUNCTION(, SCHEMA_RESULT, Schema_AddModelReportedProperty, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, const char*, reportedPropertyName, const char*, reportedPropertyType);
+MOCKABLE_FUNCTION(, SCHEMA_RESULT, Schema_AddModelDesiredProperty, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, const char*, desiredPropertyName, const char*, desiredPropertyType, pfDesiredPropertyFromAGENT_DATA_TYPE, desiredPropertyFromAGENT_DATA_TYPE, pfDesiredPropertyInitialize, desiredPropertyInitialize, pfDesiredPropertyDeinitialize, desiredPropertyDeinitialize, size_t, offset, pfOnDesiredProperty, onDesiredProperty);
+MOCKABLE_FUNCTION(, SCHEMA_RESULT, Schema_AddModelModel, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, const char*, propertyName, SCHEMA_MODEL_TYPE_HANDLE, modelType, size_t, offset, pfOnDesiredProperty, onDesiredProperty);
+MOCKABLE_FUNCTION(, SCHEMA_ACTION_HANDLE, Schema_CreateModelAction, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, const char*, actionName);
+MOCKABLE_FUNCTION(, SCHEMA_METHOD_HANDLE, Schema_CreateModelMethod, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, const char*, methodName);
+MOCKABLE_FUNCTION(, SCHEMA_RESULT, Schema_AddModelActionArgument, SCHEMA_ACTION_HANDLE, actionHandle, const char*, argumentName, const char*, argumentType);
+MOCKABLE_FUNCTION(, SCHEMA_RESULT, Schema_AddModelMethodArgument, SCHEMA_METHOD_HANDLE, methodHandle, const char*, argumentName, const char*, argumentType);
+MOCKABLE_FUNCTION(, pfDesiredPropertyFromAGENT_DATA_TYPE, Schema_GetModelDesiredProperty_pfDesiredPropertyFromAGENT_DATA_TYPE, SCHEMA_DESIRED_PROPERTY_HANDLE, desiredPropertyHandle);
+MOCKABLE_FUNCTION(, pfOnDesiredProperty, Schema_GetModelDesiredProperty_pfOnDesiredProperty, SCHEMA_DESIRED_PROPERTY_HANDLE, desiredPropertyHandle);
+
+
+MOCKABLE_FUNCTION(, size_t, Schema_GetModelModelByName_Offset, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, const char*, propertyName);
+MOCKABLE_FUNCTION(, pfOnDesiredProperty, Schema_GetModelModelByName_OnDesiredProperty, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, const char*, propertyName);
+
+MOCKABLE_FUNCTION(, size_t, Schema_GetModelModelByIndex_Offset, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, size_t, index);
+
+MOCKABLE_FUNCTION(, size_t, Schema_GetModelDesiredProperty_offset, SCHEMA_DESIRED_PROPERTY_HANDLE, desiredPropertyHandle);
+MOCKABLE_FUNCTION(, const char*, Schema_GetModelDesiredPropertyType, SCHEMA_DESIRED_PROPERTY_HANDLE, desiredPropertyHandle);
+MOCKABLE_FUNCTION(, pfDesiredPropertyDeinitialize, Schema_GetModelDesiredProperty_pfDesiredPropertyDeinitialize, SCHEMA_DESIRED_PROPERTY_HANDLE, desiredPropertyHandle);
+MOCKABLE_FUNCTION(, pfDesiredPropertyInitialize, Schema_GetModelDesiredProperty_pfDesiredPropertyInitialize, SCHEMA_DESIRED_PROPERTY_HANDLE, desiredPropertyHandle);
+
+MOCKABLE_FUNCTION(, SCHEMA_MODEL_ELEMENT, Schema_GetModelElementByName, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, const char*, elementName);
+
+MOCKABLE_FUNCTION(, SCHEMA_RESULT, Schema_GetModelCount, SCHEMA_HANDLE, schemaHandle, size_t*, modelCount);
+MOCKABLE_FUNCTION(, SCHEMA_MODEL_TYPE_HANDLE, Schema_GetModelByName, SCHEMA_HANDLE, schemaHandle, const char*, modelName);
+MOCKABLE_FUNCTION(, SCHEMA_MODEL_TYPE_HANDLE, Schema_GetModelByIndex, SCHEMA_HANDLE, schemaHandle, size_t, index);
+
+MOCKABLE_FUNCTION(, SCHEMA_RESULT, Schema_GetModelPropertyCount, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, size_t*, propertyCount);
+MOCKABLE_FUNCTION(, SCHEMA_PROPERTY_HANDLE, Schema_GetModelPropertyByName, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, const char*, propertyName);
+MOCKABLE_FUNCTION(, SCHEMA_PROPERTY_HANDLE, Schema_GetModelPropertyByIndex, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, size_t, index);
+
+MOCKABLE_FUNCTION(, SCHEMA_RESULT, Schema_GetModelReportedPropertyCount, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, size_t*, reportedPropertyCount);
+MOCKABLE_FUNCTION(, SCHEMA_REPORTED_PROPERTY_HANDLE, Schema_GetModelReportedPropertyByName, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, const char*, reportedPropertyName);
+MOCKABLE_FUNCTION(, SCHEMA_REPORTED_PROPERTY_HANDLE, Schema_GetModelReportedPropertyByIndex, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, size_t, index);
+
+MOCKABLE_FUNCTION(, SCHEMA_RESULT, Schema_GetModelDesiredPropertyCount, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, size_t*, desiredPropertyCount);
+MOCKABLE_FUNCTION(, SCHEMA_DESIRED_PROPERTY_HANDLE, Schema_GetModelDesiredPropertyByName, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, const char*, desiredPropertyName);
+MOCKABLE_FUNCTION(, SCHEMA_DESIRED_PROPERTY_HANDLE, Schema_GetModelDesiredPropertyByIndex, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, size_t, index);
+
+MOCKABLE_FUNCTION(, SCHEMA_RESULT, Schema_GetModelModelCount, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, size_t*, modelCount);
+MOCKABLE_FUNCTION(, SCHEMA_MODEL_TYPE_HANDLE, Schema_GetModelModelByName, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, const char*, propertyName);
+MOCKABLE_FUNCTION(, SCHEMA_MODEL_TYPE_HANDLE, Schema_GetModelModelyByIndex, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, size_t, index);
+MOCKABLE_FUNCTION(, const char*, Schema_GetModelModelPropertyNameByIndex, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, size_t, index);
+
+MOCKABLE_FUNCTION(, bool, Schema_ModelPropertyByPathExists, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, const char*, propertyPath);
+
+MOCKABLE_FUNCTION(, bool, Schema_ModelReportedPropertyByPathExists, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, const char*, reportedPropertyPath);
+MOCKABLE_FUNCTION(, bool, Schema_ModelDesiredPropertyByPathExists, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, const char*, desiredPropertyPath);
+
+MOCKABLE_FUNCTION(, SCHEMA_RESULT, Schema_GetModelActionCount, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, size_t*, actionCount);
+MOCKABLE_FUNCTION(, SCHEMA_ACTION_HANDLE, Schema_GetModelActionByName, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, const char*, actionName);
+MOCKABLE_FUNCTION(, SCHEMA_METHOD_HANDLE, Schema_GetModelMethodByName, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, const char*, methodName);
+MOCKABLE_FUNCTION(, SCHEMA_ACTION_HANDLE, Schema_GetModelActionByIndex, SCHEMA_MODEL_TYPE_HANDLE, modelTypeHandle, size_t, index);
+
+MOCKABLE_FUNCTION(, SCHEMA_RESULT, Schema_GetModelActionArgumentCount, SCHEMA_ACTION_HANDLE, actionHandle, size_t*, argumentCount);
+MOCKABLE_FUNCTION(, SCHEMA_RESULT, Schema_GetModelMethodArgumentCount, SCHEMA_METHOD_HANDLE, methodHandle, size_t*, argumentCount);
+MOCKABLE_FUNCTION(, const char*, Schema_GetModelActionName, SCHEMA_ACTION_HANDLE, actionHandle);
+
+MOCKABLE_FUNCTION(, SCHEMA_ACTION_ARGUMENT_HANDLE, Schema_GetModelActionArgumentByName, SCHEMA_ACTION_HANDLE, actionHandle, const char*, actionArgumentName);
+MOCKABLE_FUNCTION(, SCHEMA_ACTION_ARGUMENT_HANDLE, Schema_GetModelActionArgumentByIndex, SCHEMA_ACTION_HANDLE, actionHandle, size_t, argumentIndex);
+MOCKABLE_FUNCTION(, SCHEMA_METHOD_ARGUMENT_HANDLE, Schema_GetModelMethodArgumentByIndex, SCHEMA_METHOD_HANDLE, actionHandle, size_t, argumentIndex);
+MOCKABLE_FUNCTION(, const char*, Schema_GetActionArgumentName, SCHEMA_ACTION_ARGUMENT_HANDLE, actionArgumentHandle);
+MOCKABLE_FUNCTION(, const char*, Schema_GetMethodArgumentName, SCHEMA_METHOD_ARGUMENT_HANDLE, methodArgumentHandle);
+MOCKABLE_FUNCTION(, const char*, Schema_GetActionArgumentType, SCHEMA_ACTION_ARGUMENT_HANDLE, actionArgumentHandle);
+MOCKABLE_FUNCTION(, const char*, Schema_GetMethodArgumentType, SCHEMA_METHOD_ARGUMENT_HANDLE, methodArgumentHandle);
+
+MOCKABLE_FUNCTION(, SCHEMA_RESULT, Schema_GetStructTypeCount, SCHEMA_HANDLE, schemaHandle, size_t*, structTypeCount);
+MOCKABLE_FUNCTION(, SCHEMA_STRUCT_TYPE_HANDLE, Schema_GetStructTypeByName, SCHEMA_HANDLE, schemaHandle, const char*, structTypeName);
+MOCKABLE_FUNCTION(, SCHEMA_STRUCT_TYPE_HANDLE, Schema_GetStructTypeByIndex, SCHEMA_HANDLE, schemaHandle, size_t, index);
+
+MOCKABLE_FUNCTION(, SCHEMA_RESULT, Schema_GetStructTypePropertyCount, SCHEMA_STRUCT_TYPE_HANDLE, structTypeHandle, size_t*, propertyCount);
+MOCKABLE_FUNCTION(, SCHEMA_PROPERTY_HANDLE, Schema_GetStructTypePropertyByName, SCHEMA_STRUCT_TYPE_HANDLE, structTypeHandle, const char*, propertyName);
+MOCKABLE_FUNCTION(, SCHEMA_PROPERTY_HANDLE, Schema_GetStructTypePropertyByIndex, SCHEMA_STRUCT_TYPE_HANDLE, structTypeHandle, size_t, index);
+MOCKABLE_FUNCTION(, const char*, Schema_GetPropertyName, SCHEMA_PROPERTY_HANDLE, propertyHandle);
+MOCKABLE_FUNCTION(, const char*, Schema_GetPropertyType, SCHEMA_PROPERTY_HANDLE, propertyHandle);
+
+MOCKABLE_FUNCTION(, void, Schema_Destroy, SCHEMA_HANDLE, schemaHandle);
+MOCKABLE_FUNCTION(, SCHEMA_RESULT, Schema_DestroyIfUnused,SCHEMA_MODEL_TYPE_HANDLE, modelHandle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SCHEMA_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/schemalib.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/schemalib.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/schemalib.h	(revision 453)
@@ -0,0 +1,84 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/** @file   schemalib.h
+ *    @brief    The IoT Hub Serializer APIs allows developers to define models for
+*            their devices
+ */
+
+#ifndef SCHEMALIB_H
+#define SCHEMALIB_H
+
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/strings.h"
+#include "iotdevice.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Codes_SRS_SCHEMALIB__99_001:[ IoTHubSchema_Client shall expose the following API: ... ] */
+#define SERIALIZER_RESULT_VALUES                   \
+    SERIALIZER_OK,                                 \
+    SERIALIZER_INVALID_ARG,                        \
+    SERIALIZER_CODEFIRST_INIT_FAILED,              \
+    SERIALIZER_SCHEMA_FAILED,                      \
+    SERIALIZER_HTTP_API_INIT_FAILED,               \
+    SERIALIZER_ALREADY_INIT,                       \
+    SERIALIZER_ERROR,                              \
+    SERIALIZER_NOT_INITIALIZED,                    \
+    SERIALIZER_ALREADY_STARTED,                    \
+    SERIALIZER_DEVICE_CREATE_FAILED,               \
+    SERIALIZER_GET_MODEL_HANDLE_FAILED,            \
+    SERIALIZER_SERVICEBUS_FAILED
+
+/** @brief Enumeration specifying the status of calls to various APIs in this
+ * module.
+ */
+MU_DEFINE_ENUM_WITHOUT_INVALID(SERIALIZER_RESULT, SERIALIZER_RESULT_VALUES);
+
+#define SERIALIZER_CONFIG_VALUES  \
+    CommandPollingInterval,     \
+    SerializeDelayedBufferMaxSize
+
+/** @brief Enumeration specifying the option to set on the serializer when
+ * calling ::serializer_setconfig.
+ */
+MU_DEFINE_ENUM_WITHOUT_INVALID(SERIALIZER_CONFIG, SERIALIZER_CONFIG_VALUES);
+
+/**
+ * @brief   Initializes the library.
+ *
+ * @param   overrideSchemaNamespace An override schema namespace to use for all
+ *                                  models. Optional, can be @c NULL.
+ *
+ *          If @p schemaNamespace is not @c NULL, its value shall be used
+ *          instead of the namespace defined for each model by using the
+ *          @c DECLARE_XXX macro.
+ *
+ * @return  @c SERIALIZER_OK on success and any other error on failure.
+ */
+extern SERIALIZER_RESULT serializer_init(const char* overrideSchemaNamespace);
+
+/** @brief  Shuts down the IOT library.
+ *
+ *          The library will track all created devices and upon a call to
+ *          ::serializer_deinit it will de-initialize all devices.
+ */
+extern void serializer_deinit(void);
+
+/**
+ * @brief   Set serializer options.
+ *
+ * @param   which   The option to be set.
+ * @param   value   The value to set for the given option.
+ *
+ * @return  @c SERIALIZER_OK on success and any other error on failure.
+ */
+extern SERIALIZER_RESULT serializer_setconfig(SERIALIZER_CONFIG which, void* value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SCHEMALIB_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/schemaserializer.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/schemaserializer.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/schemaserializer.h	(revision 453)
@@ -0,0 +1,27 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef SCHEMASERIALIZER_H
+#define SCHEMASERIALIZER_H
+
+#include "schema.h"
+#include "azure_c_shared_utility/strings.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SCHEMA_SERIALIZER_RESULT_VALUES    \
+    SCHEMA_SERIALIZER_OK,            \
+    SCHEMA_SERIALIZER_INVALID_ARG,  \
+    SCHEMA_SERIALIZER_ERROR
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(SCHEMA_SERIALIZER_RESULT, SCHEMA_SERIALIZER_RESULT_VALUES)
+
+extern SCHEMA_SERIALIZER_RESULT SchemaSerializer_SerializeCommandMetadata(SCHEMA_MODEL_TYPE_HANDLE modelHandle, STRING_HANDLE schemaText);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SCHEMASERIALIZER_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/serializer.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/serializer.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/serializer.h	(revision 453)
@@ -0,0 +1,1520 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/** @file   serializer.h
+*    @brief    The IoT Hub Serializer APIs allows developers to define models for
+*            their devices
+*
+*    @details    The IoT Hub Serializer APIs allows developers to quickly and easily define
+*                models for their devices directly as code, while supporting the required
+*                features for modeling devices (including multiple models and multiple
+*                devices within the same application). For example:
+*
+*        <pre>
+*       BEGIN_NAMESPACE(Contoso);
+*
+*           DECLARE_STRUCT(SystemProperties,
+*               ascii_char_ptr, DeviceID,
+*               _Bool, Enabled
+*           );
+*
+*           DECLARE_MODEL(VendingMachine,
+*
+*               WITH_DATA(int, SensorValue),
+*
+*               WITH_DATA(ascii_char_ptr, ObjectName),
+*               WITH_DATA(ascii_char_ptr, ObjectType),
+*               WITH_DATA(ascii_char_ptr, Version),
+*               WITH_DATA(SystemProperties, SystemProperties),
+*               WITH_DATA(ascii_char_ptr_no_quotes, Commands),
+*
+*               WITH_ACTION(SetItemPrice, ascii_char_ptr, itemId, ascii_char_ptr, price)
+*           );
+*
+*       END_NAMESPACE(Contoso);
+*       </pre>
+*/
+
+#ifndef SERIALIZER_H
+#define SERIALIZER_H
+
+#ifdef __cplusplus
+#include <cstdlib>
+#include <cstdarg>
+
+#else
+#include <stdlib.h>
+#include <stdarg.h>
+#endif
+
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_macro_utils/macro_utils.h"
+#include "iotdevice.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "methodreturn.h"
+#include "schemalib.h"
+#include "codefirst.h"
+#include "agenttypesystem.h"
+#include "schema.h"
+
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    /* IOT Agent Macros */
+
+    /**
+     * @def BEGIN_NAMESPACE(schemaNamespace)
+     * This macro marks the start of a section that declares IOT model
+     * elements (like complex types, etc.). Declarations are typically
+     * placed in header files, so that they can be shared between
+     * translation units.
+     */
+     /* Codes_SRS_SERIALIZER_99_001:[For each completed schema declaration block, a unique storage container for schema metadata shall be available in the translation unit at runtime.] */
+#define BEGIN_NAMESPACE(schemaNamespace) \
+    REFLECTED_END_OF_LIST
+
+/**
+* @def END_NAMESPACE(schemaNamespace)
+* This macro marks the end of a section that declares IOT model
+* elements.
+*/
+#define END_NAMESPACE(schemaNamespace) \
+    REFLECTED_LIST_HEAD(schemaNamespace)
+
+#define GLOBAL_INITIALIZE_STRUCT_FIELD(structType, destination, type, name) GlobalInitialize_##type((char*)destination+offsetof(structType, name));
+#define GLOBAL_DEINITIALIZE_STRUCT_FIELD(structType, destination, type, name) GlobalDeinitialize_##type((char*)destination+offsetof(structType, name));
+/**
+* @def DECLARE_STRUCT(name, ...)
+* This macro allows the definition of a struct type that can then be used as
+* part of a model definition.
+*
+* @param name                      Name of the struct
+* @param element1, element2...     Specifies a list of struct members
+*/
+/* Codes_SRS_SERIALIZER_99_080:[ The DECLARE_STRUCT declaration shall insert metadata describing a complex data type.] */
+#define DECLARE_STRUCT(name, ...) \
+    /* Codes_SRS_SERIALIZER_99_096:[ DECLARE_STRUCT shall declare a matching C struct data type named name, which can be referenced from any code that can access the declaration.] */ \
+    typedef struct name##_TAG { \
+        MU_FOR_EACH_2(INSERT_FIELD_INTO_STRUCT, __VA_ARGS__) \
+    } name; \
+    /* Codes_SRS_SERIALIZER_99_081:[ DECLARE_STRUCT's name argument shall uniquely identify the struct within the schema.] */ \
+    REFLECTED_STRUCT(name) \
+    /* Codes_SRS_SERIALIZER_99_082:[ DECLARE_STRUCT's field<n>Name argument shall uniquely name a field within the struct.] */ \
+    MU_FOR_EACH_2_KEEP_1(REFLECTED_FIELD, name, __VA_ARGS__) \
+    TO_AGENT_DATA_TYPE(name, __VA_ARGS__) \
+    /*Codes_SRS_SERIALIZER_99_042:[ The parameter types are either predefined parameter types (specs SRS_SERIALIZER_99_004-SRS_SERIALIZER_99_014) or a type introduced by DECLARE_STRUCT.]*/ \
+    static AGENT_DATA_TYPES_RESULT FromAGENT_DATA_TYPE_##name(const AGENT_DATA_TYPE* source, name* destination) \
+    { \
+        AGENT_DATA_TYPES_RESULT result; \
+        if(source->type != EDM_COMPLEX_TYPE_TYPE) \
+        { \
+            result = AGENT_DATA_TYPES_INVALID_ARG; \
+        } \
+        else if(MU_DIV2(MU_COUNT_ARG(__VA_ARGS__)) != source->value.edmComplexType.nMembers) \
+        { \
+            /*too many or too few fields*/ \
+            result = AGENT_DATA_TYPES_INVALID_ARG; \
+        } \
+        else \
+        { \
+            result = AGENT_DATA_TYPES_OK; \
+            MU_FOR_EACH_2(BUILD_DESTINATION_FIELD, __VA_ARGS__); \
+        } \
+        return result; \
+    } \
+    static void MU_C2(destroyLocalParameter, name)(name * value) \
+    { \
+        MU_FOR_EACH_2_KEEP_1(UNBUILD_DESTINATION_FIELD, value, __VA_ARGS__); \
+    } \
+    static void MU_C2(GlobalInitialize_, name)(void* destination) \
+    { \
+        MU_FOR_EACH_2_KEEP_2(GLOBAL_INITIALIZE_STRUCT_FIELD, name, destination, __VA_ARGS__); \
+    } \
+    static void MU_C2(GlobalDeinitialize_, name)(void* destination) \
+    { \
+        MU_FOR_EACH_2_KEEP_2(GLOBAL_DEINITIALIZE_STRUCT_FIELD, name, destination, __VA_ARGS__); \
+    } \
+
+
+/**
+ * @def     DECLARE_MODEL(name, ...)
+ * This macro allows declaring a model that can be later used to instantiate
+ * a device.
+ *
+ * @param   name                        Specifies the model name
+ * @param   element1, element2...       Specifies a model element which can be
+ *                                         a property or an action.
+ *                                             - A property is described in a
+ *                                               model by using the WITH_DATA
+ *                                             - An action is described in a
+ *                                               model by using the ::WITH_ACTION
+ *                                               macro.
+ *
+ */
+ /* WITH_DATA's name argument shall be one of the following data types: */
+ /* Codes_SRS_SERIALIZER_99_133:[a model type introduced previously by DECLARE_MODEL] */
+
+#define CREATE_DESIRED_PROPERTY_CALLBACK_MODEL_ACTION(...)
+#define CREATE_DESIRED_PROPERTY_CALLBACK_MODEL_METHOD(...)
+#define CREATE_DESIRED_PROPERTY_CALLBACK_MODEL_DESIRED_PROPERTY(type, name, ...) MU_IF(MU_COUNT_ARG(__VA_ARGS__), void __VA_ARGS__ (void*);, )
+#define CREATE_DESIRED_PROPERTY_CALLBACK_MODEL_PROPERTY(...)
+#define CREATE_DESIRED_PROPERTY_CALLBACK_MODEL_REPORTED_PROPERTY(...)
+
+#define CREATE_DESIRED_PROPERTY_CALLBACK(...) CREATE_DESIRED_PROPERTY_CALLBACK_##__VA_ARGS__
+
+#define SERIALIZER_REGISTER_NAMESPACE(NAMESPACE) CodeFirst_RegisterSchema(#NAMESPACE, & ALL_REFLECTED(NAMESPACE))
+
+#define DECLARE_MODEL(name, ...)                                                             \
+    REFLECTED_MODEL(name)                                                                    \
+    MU_FOR_EACH_1(CREATE_DESIRED_PROPERTY_CALLBACK, __VA_ARGS__)                                \
+    typedef struct name { int :1; MU_FOR_EACH_1(BUILD_MODEL_STRUCT, __VA_ARGS__) } name;        \
+    MU_FOR_EACH_1_KEEP_1(CREATE_MODEL_ELEMENT, name, __VA_ARGS__)                               \
+    TO_AGENT_DATA_TYPE(name, DROP_FIRST_COMMA_FROM_ARGS(EXPAND_MODEL_ARGS(__VA_ARGS__)))     \
+    int FromAGENT_DATA_TYPE_##name(const AGENT_DATA_TYPE* source, void* destination)         \
+    {                                                                                        \
+        (void)source;                                                                        \
+        (void)destination;                                                                   \
+        LogError("SHOULD NOT GET CALLED... EVER");                                           \
+        return 0;                                                                            \
+    }                                                                                        \
+    static void MU_C2(GlobalInitialize_, name)(void* destination)                               \
+    {                                                                                        \
+        (void)destination;                                                                   \
+        MU_FOR_EACH_1_KEEP_1(CREATE_MODEL_ELEMENT_GLOBAL_INITIALIZE, name, __VA_ARGS__)         \
+    }                                                                                        \
+    static void MU_C2(GlobalDeinitialize_, name)(void* destination)                             \
+    {                                                                                        \
+        (void)destination;                                                                   \
+        MU_FOR_EACH_1_KEEP_1(CREATE_MODEL_ELEMENT_GLOBAL_DEINITIALIZE, name, __VA_ARGS__)       \
+    }                                                                                        \
+
+
+
+/**
+ * @def   WITH_DATA(type, name)
+ * The ::WITH_DATA macro allows declaring a model property in a model. A
+ * property can be published by using the ::SERIALIZE macro.
+ *
+ * @param   type    Specifies the property type. Can be any of the following
+ *                  types:
+ *                   - int
+ *                   - double
+ *                   - float
+ *                   - long
+ *                   - int8_t
+ *                   - uint8_t
+ *                   - int16_t
+ *                   - int32_t
+ *                   - int64_t
+ *                   - bool
+ *                   - ascii_char_ptr
+ *                   - EDM_DATE_TIME_OFFSET
+ *                   - EDM_GUID
+ *                   - EDM_BINARY
+ *                   - Any struct type previously introduced by another ::DECLARE_STRUCT.
+ *
+ * @param   name    Specifies the property name
+ */
+#define WITH_DATA(type, name) MODEL_PROPERTY(type, name)
+
+
+#define WITH_REPORTED_PROPERTY(type, name) MODEL_REPORTED_PROPERTY(type, name)
+
+#define WITH_DESIRED_PROPERTY(type, name, ...) MODEL_DESIRED_PROPERTY(type, name, __VA_ARGS__)
+
+/**
+ * @def   WITH_ACTION(name, ...)
+ * The ::WITH_ACTION macro allows declaring a model action.
+ *
+ * @param   name                    Specifies the action name.
+ * @param   argXtype, argXName...   Defines the type and name for the X<sup>th</sup>
+ *                                  argument of the action. The type can be any of
+ *                                  the primitive types or a struct type.
+ */
+/*Codes_SRS_SERIALIZER_99_039:[WITH_ACTION shall declare an action of the current data provider called as the first macro parameter(name) and having the first parameter called parameter1Name of type parameter1Type, the second parameter named parameter2Name having the type parameter2Type and so on.]*/
+#define WITH_ACTION(name, ...)  MODEL_ACTION(name, __VA_ARGS__)
+
+
+/**
+* @def   WITH_METHOD(name, ...)
+* The ::WITH_METHOD macro allows declaring a model method.
+*
+* @param   name                    Specifies the method name.
+* @param   argXtype, argXName...   Defines the type and name for the X<sup>th</sup>
+*                                  argument of the method. The type can be any of
+*                                  the primitive types or a struct type.
+*/
+/*Codes_SRS_SERIALIZER_H_02_029: [ WITH_METHOD shall declare a function with the signature 'METHODRETURN_HANDLE name(param1Type param1Name, ...)', which the developer can define to receive corresponding commands from the IoT service. ]*/
+#define WITH_METHOD(name, ...)  MODEL_METHOD(name, __VA_ARGS__)
+
+
+/**
+ * @def   GET_MODEL_HANDLE(schemaNamespace, modelName)
+ * The ::GET_MODEL_HANDLE macro returns a model handle that can be used in
+ * subsequent operations like generating the CSDL schema for the model,
+ * uploading the schema, creating a device, etc.
+ *
+ * @param   schemaNamespace The namespace to which the model belongs.
+ * @param   modelName       The name of the model.
+ */
+/* Codes_SRS_SERIALIZER_99_110:[ The GET_MODEL_HANDLE function macro shall first register the schema by calling CodeFirst_RegisterSchema, passing schemaNamespace and a pointer to the metadata generated in the schema declaration block.] */
+/* Codes_SRS_SERIALIZER_99_094:[ GET_MODEL_HANDLE shall then call Schema_GetModelByName, passing the schemaHandle obtained from CodeFirst_RegisterSchema and modelName arguments, to retrieve the SCHEMA_MODEL_TYPE_HANDLE corresponding to the modelName argument.] */
+/* Codes_SRS_SERIALIZER_99_112:[ GET_MODEL_HANDLE will return the handle for the named model.] */
+#define GET_MODEL_HANDLE(schemaNamespace, modelName) \
+    Schema_GetModelByName(CodeFirst_RegisterSchema(MU_TOSTRING(schemaNamespace), &ALL_REFLECTED(schemaNamespace)), #modelName)
+
+/* Codes_SRS_SERIALIZER_01_002: [If the argument serializerIncludePropertyPath is specified, its value shall be passed to CodeFirst_Create.] */
+#define CREATE_DEVICE_WITH_INCLUDE_PROPERTY_PATH(schemaNamespace, modelName, serializerIncludePropertyPath) \
+    (modelName*)CodeFirst_CreateDevice(GET_MODEL_HANDLE(schemaNamespace, modelName), &ALL_REFLECTED(schemaNamespace), sizeof(modelName), serializerIncludePropertyPath)
+
+/* Codes_SRS_SERIALIZER_01_003: [If the argument serializerIncludePropertyPath is not specified, CREATE_MODEL_INSTANCE shall pass false to CodeFirst_Create.] */
+#define CREATE_DEVICE_WITHOUT_INCLUDE_PROPERTY_PATH(schemaNamespace, modelName) \
+    (modelName*)CodeFirst_CreateDevice(GET_MODEL_HANDLE(schemaNamespace, modelName), &ALL_REFLECTED(schemaNamespace), sizeof(modelName), false)
+
+/* Codes_SRS_SERIALIZER_99_104:[ CREATE_MODEL_INSTANCE shall call GET_MODEL_HANDLE, passing schemaNamespace and modelName, to get a model handle representing the model defined in the corresponding schema declaration block.] */
+/* Codes_SRS_SERIALIZER_99_106:[ CREATE_MODEL_INSTANCE shall call CodeFirst_CreateDevice, passing the model handle (SCHEMA_MODEL_TYPE_HANDLE]*/
+/* Codes_SRS_SERIALIZER_99_107:[ If CodeFirst_CreateDevice fails, CREATE_MODEL_INSTANCE shall return NULL.] */
+/* Codes_SRS_SERIALIZER_99_108:[ If CodeFirst_CreateDevice succeeds, CREATE_MODEL_INSTANCE shall return a pointer to an instance of the C struct representing the model for the device.] */
+#define CREATE_MODEL_INSTANCE(schemaNamespace, ...) \
+    MU_IF(MU_DIV2(MU_COUNT_ARG(__VA_ARGS__)), CREATE_DEVICE_WITH_INCLUDE_PROPERTY_PATH, CREATE_DEVICE_WITHOUT_INCLUDE_PROPERTY_PATH) (schemaNamespace, __VA_ARGS__)
+
+/* Codes_SRS_SERIALIZER_99_109:[ DESTROY_MODEL_INSTANCE shall call CodeFirst_DestroyDevice, passing the pointer returned from CREATE_MODEL_INSTANCE, to release all resources associated with the device.] */
+#define DESTROY_MODEL_INSTANCE(deviceData) \
+    CodeFirst_DestroyDevice(deviceData)
+
+/**
+ * @def      SERIALIZE(destination, destinationSize,...)
+ * This macro produces JSON serialized representation of the properties.
+ *
+ * @param   destination                  Pointer to an @c unsigned @c char* that
+ *                                       will receive the serialized data.
+ * @param   destinationSize              Pointer to a @c size_t that gets
+ *                                       written with the size in bytes of the
+ *                                       serialized data
+ * @param    property1, property2...     A list of property values to send. The
+ *                                       order in which the properties appear in
+ *                                       the list does not matter, all values
+ *                                       will be sent together.
+ *
+ */
+/*Codes_SRS_SERIALIZER_99_113:[ SERIALIZE shall call CodeFirst_SendAsync, passing a destination, destinationSize, the number of properties to publish, and pointers to the values for each property.] */
+/*Codes_SRS_SERIALIZER_99_117:[ If CodeFirst_SendAsync succeeds, SEND will return IOT_AGENT_OK.] */
+/*Codes_SRS_SERIALIZER_99_114:[ If CodeFirst_SendAsync fails, SEND shall return IOT_AGENT_SERIALIZE_FAILED.] */
+#define SERIALIZE(destination, destinationSize,...) CodeFirst_SendAsync(destination, destinationSize, MU_COUNT_ARG(__VA_ARGS__) MU_FOR_EACH_1(ADDRESS_MACRO, __VA_ARGS__))
+
+#define SERIALIZE_REPORTED_PROPERTIES(destination, destinationSize,...) CodeFirst_SendAsyncReported(destination, destinationSize, MU_COUNT_ARG(__VA_ARGS__) MU_FOR_EACH_1(ADDRESS_MACRO, __VA_ARGS__))
+
+
+#define IDENTITY_MACRO(x) ,x
+#define SERIALIZE_REPORTED_PROPERTIES_FROM_POINTERS(destination, destinationSize, ...) CodeFirst_SendAsyncReported(destination, destinationSize, MU_COUNT_ARG(__VA_ARGS__) MU_FOR_EACH_1(IDENTITY_MACRO, __VA_ARGS__))
+
+/**
+ * @def   EXECUTE_COMMAND(device, command)
+ * Any action that is declared in a model must also have an implementation as
+ * a C function.
+ *
+ * @param   device      Pointer to device data.
+ * @param   command     Values that match the arguments declared in the model
+ *                      action.
+ */
+/*Codes_SRS_SERIALIZER_02_018: [EXECUTE_COMMAND macro shall call CodeFirst_ExecuteCommand passing device, commandBuffer and commandBufferSize.]*/
+#define EXECUTE_COMMAND(device, command) (CodeFirst_ExecuteCommand(device, command))
+
+/**
+* @def   EXECUTE_METHOD(device, methodName, methodPayload)
+* Any method that is declared in a model must also have an implementation as
+* a C function.
+*
+* @param   device      Pointer to device data.
+* @param   methodName       The method name.
+* @param   methodPayload    The method payload.
+*/
+#define EXECUTE_METHOD(device, methodName, methodPayload) CodeFirst_ExecuteMethod(device, methodName, methodPayload)
+
+/**
+* @def   INGEST_DESIRED_PROPERTIES(device, desiredProperties)
+*
+* @param   device                return of CodeFirst_CreateDevice.
+* @param   desiredProperties     a null terminated string containing in JSON format the desired properties
+*/
+#define INGEST_DESIRED_PROPERTIES(device, jsonPayload, parseDesiredNode) (CodeFirst_IngestDesiredProperties(device, jsonPayload, parseDesiredNode))
+
+/* Helper macros */
+
+/* These macros remove a useless comma from the beginning of an argument list that looks like:
+,x1,y1,x2,y2 */
+#ifdef _MSC_VER
+
+#define DROP_FIRST_COMMA(N, x) \
+x MU_IFCOMMA_NOFIRST(N)
+
+#define DROP_IF_EMPTY(N, x) \
+MU_IF(MU_COUNT_ARG(x),DROP_FIRST_COMMA(N,x),x)
+
+#define DROP_FIRST_COMMA_FROM_ARGS(...) \
+MU_FOR_EACH_1_COUNTED(DROP_IF_EMPTY, MU_C1(__VA_ARGS__))
+
+#else
+
+#define DROP_FIRST_COMMA_0(N, x) \
+    x MU_IFCOMMA_NOFIRST(N)
+
+#define DROP_FIRST_COMMA_1(N, x) \
+    x
+
+#define DROP_FIRST_COMMA(empty, N, x) \
+    MU_C2(DROP_FIRST_COMMA_,empty)(N,x)
+
+#define DROP_IF_EMPTY(N, x) \
+    DROP_FIRST_COMMA(MU_ISEMPTY(x),N,x)
+
+#define DROP_FIRST_COMMA_FROM_ARGS(...) \
+    MU_FOR_EACH_1_COUNTED(DROP_IF_EMPTY, __VA_ARGS__)
+
+#endif
+
+/* These macros expand a sequence of arguments for DECLARE_MODEL that looks like
+WITH_DATA(x, y), WITH_DATA(x2, y2) to a list of arguments consumed by the macro that marshalls a struct, like:
+x, y, x2, y2
+Actions are discarded, since no marshalling will be done for those when sending state data */
+#define TO_AGENT_DT_EXPAND_MODEL_PROPERTY(x, y) ,x,y
+
+#define TO_AGENT_DT_EXPAND_MODEL_REPORTED_PROPERTY(x, y) ,x,y
+
+#define TO_AGENT_DT_EXPAND_MODEL_DESIRED_PROPERTY(x, y, ...) ,x,y
+
+#define TO_AGENT_DT_EXPAND_MODEL_ACTION(...)
+
+#define TO_AGENT_DT_EXPAND_MODEL_METHOD(...)
+
+#define TO_AGENT_DT_EXPAND_ELEMENT_ARGS(N, ...) TO_AGENT_DT_EXPAND_##__VA_ARGS__
+
+#define EXPAND_MODEL_ARGS(...) \
+    MU_FOR_EACH_1_COUNTED(TO_AGENT_DT_EXPAND_ELEMENT_ARGS, __VA_ARGS__)
+
+#define TO_AGENT_DATA_TYPE(name, ...) \
+    static AGENT_DATA_TYPES_RESULT ToAGENT_DATA_TYPE_##name(AGENT_DATA_TYPE *destination, const name value) \
+    { \
+        AGENT_DATA_TYPES_RESULT result = AGENT_DATA_TYPES_OK; \
+        size_t iMember = 0; \
+        DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(phantomName, 1); \
+        const char* memberNames[MU_IF(MU_DIV2(MU_C1(MU_COUNT_ARG(__VA_ARGS__))), MU_DIV2(MU_C1(MU_COUNT_ARG(__VA_ARGS__))), 1)] = { 0 }; \
+        size_t memberCount = sizeof(memberNames) / sizeof(memberNames[0]); \
+        (void)value; \
+        if (memberCount == 0) \
+        { \
+            result = AGENT_DATA_TYPES_OK; \
+        } \
+        else \
+        { \
+            AGENT_DATA_TYPE members[sizeof(memberNames) / sizeof(memberNames[0])]; \
+            DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(phantomName, 2); \
+            MU_FOR_EACH_2(FIELD_AS_STRING, MU_EXPAND_TWICE(__VA_ARGS__)) \
+            iMember = 0; \
+            { \
+                DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(phantomName, 3); \
+                MU_FOR_EACH_2(CREATE_AGENT_DATA_TYPE, MU_EXPAND_TWICE(__VA_ARGS__)) \
+                {DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(phantomName, 4); } \
+                result = ((result == AGENT_DATA_TYPES_OK) && (Create_AGENT_DATA_TYPE_from_Members(destination, #name, sizeof(memberNames) / sizeof(memberNames[0]), memberNames, members) == AGENT_DATA_TYPES_OK)) \
+                            ? AGENT_DATA_TYPES_OK \
+                            : AGENT_DATA_TYPES_ERROR; \
+                { \
+                    size_t jMember; \
+                    for (jMember = 0; jMember < iMember; jMember++) \
+                    { \
+                        Destroy_AGENT_DATA_TYPE(&members[jMember]); \
+                    } \
+                } \
+            } \
+        } \
+        return result; \
+    }
+
+#define FIELD_AS_STRING(x,y) memberNames[iMember++] = #y;
+
+#define REFLECTED_LIST_HEAD(name) \
+    static const REFLECTED_DATA_FROM_DATAPROVIDER ALL_REFLECTED(name) = { &MU_C2(REFLECTED_, MU_C1(MU_DEC(__COUNTER__))) };
+#define REFLECTED_STRUCT(name) \
+    static const REFLECTED_SOMETHING MU_C2(REFLECTED_, MU_C1(MU_INC(__COUNTER__))) = { REFLECTION_STRUCT_TYPE,               &MU_C2(REFLECTED_, MU_C1(MU_DEC(MU_DEC(__COUNTER__)))), { {0}, {0}, {0}, {MU_TOSTRING(name)}, {0}, {0}, {0}, {0}} };
+#define REFLECTED_FIELD(XstructName, XfieldType, XfieldName) \
+    static const REFLECTED_SOMETHING MU_C2(REFLECTED_, MU_C1(MU_INC(__COUNTER__))) = { REFLECTION_FIELD_TYPE,                &MU_C2(REFLECTED_, MU_C1(MU_DEC(MU_DEC(__COUNTER__)))), { {0}, {0}, {0}, {0}, {MU_TOSTRING(XfieldName), MU_TOSTRING(XfieldType), MU_TOSTRING(XstructName)}, {0}, {0}, {0} } };
+#define REFLECTED_MODEL(name) \
+    static const REFLECTED_SOMETHING MU_C2(REFLECTED_, MU_C1(MU_INC(__COUNTER__))) = { REFLECTION_MODEL_TYPE,                &MU_C2(REFLECTED_, MU_C1(MU_DEC(MU_DEC(__COUNTER__)))), { {0}, {0}, {0}, {0}, {0}, {0}, {0}, {MU_TOSTRING(name)} } };
+#define REFLECTED_PROPERTY(type, name, modelName) \
+    static const REFLECTED_SOMETHING MU_C2(REFLECTED_, MU_C1(MU_INC(__COUNTER__))) = { REFLECTION_PROPERTY_TYPE,             &MU_C2(REFLECTED_, MU_C1(MU_DEC(MU_DEC(__COUNTER__)))), { {0}, {0}, {0}, {0}, {0}, {MU_TOSTRING(name), MU_TOSTRING(type), Create_AGENT_DATA_TYPE_From_Ptr_##modelName##name, offsetof(modelName, name), sizeof(type), MU_TOSTRING(modelName)}, {0}, {0} } };
+#define REFLECTED_REPORTED_PROPERTY(type, name, modelName) \
+    static const REFLECTED_SOMETHING MU_C2(REFLECTED_, MU_C1(MU_INC(__COUNTER__))) = { REFLECTION_REPORTED_PROPERTY_TYPE,    &MU_C2(REFLECTED_, MU_C1(MU_DEC(MU_DEC(__COUNTER__)))), { {0}, {0}, {MU_TOSTRING(name), MU_TOSTRING(type), Create_AGENT_DATA_TYPE_From_Ptr_##modelName##name, offsetof(modelName, name), sizeof(type), MU_TOSTRING(modelName)}, {0}, {0}, {0}, {0}, {0} } };
+
+
+#define REFLECTED_DESIRED_PROPERTY_WITH_ON_DESIRED_PROPERTY_CHANGE(type, name, modelName, COUNTER, onDesiredPropertyChange) \
+    static const REFLECTED_SOMETHING MU_C2(REFLECTED_, MU_C1(MU_INC(COUNTER))) =      { REFLECTION_DESIRED_PROPERTY_TYPE,     &MU_C2(REFLECTED_, MU_C1(MU_DEC(COUNTER))),         { {0}, {onDesiredPropertyChange, DesiredPropertyInitialize_##modelName##name, DesiredPropertyDeinitialize_##modelName##name, MU_TOSTRING(name), MU_TOSTRING(type), (int(*)(const AGENT_DATA_TYPE*, void*))FromAGENT_DATA_TYPE_##type, offsetof(modelName, name), sizeof(type), MU_TOSTRING(modelName)}, {0}, {0}, {0}, {0}, {0}, {0}} };
+
+#define REFLECTED_DESIRED_PROPERTY(type, name, modelName, ...)                                                              \
+    MU_IF(MU_COUNT_ARG(__VA_ARGS__),                                                                                              \
+        MACRO_UTILS_DELAY(REFLECTED_DESIRED_PROPERTY_WITH_ON_DESIRED_PROPERTY_CHANGE)(type, name, modelName,__COUNTER__, __VA_ARGS__),  \
+        MACRO_UTILS_DELAY(REFLECTED_DESIRED_PROPERTY_WITH_ON_DESIRED_PROPERTY_CHANGE)(type, name, modelName,MU_DEC(__COUNTER__), NULL)     \
+    )                                                                                                                       \
+
+#define REFLECTED_ACTION(name, argc, argv, fn, modelName) \
+    static const REFLECTED_SOMETHING MU_C2(REFLECTED_, MU_C1(MU_INC(__COUNTER__))) = { REFLECTION_ACTION_TYPE,               &MU_C2(REFLECTED_, MU_C1(MU_DEC(MU_DEC(__COUNTER__)))), { {0}, {0}, {0}, {0}, {0}, {0}, {MU_TOSTRING(name), argc, argv, fn, MU_TOSTRING(modelName)}, {0}} };
+
+#define REFLECTED_METHOD(name, argc, argv, fn, modelName) \
+    static const REFLECTED_SOMETHING MU_C2(REFLECTED_, MU_C1(MU_INC(__COUNTER__))) = { REFLECTION_METHOD_TYPE,               &MU_C2(REFLECTED_, MU_C1(MU_DEC(MU_DEC(__COUNTER__)))), { {MU_TOSTRING(name), argc, argv, fn, MU_TOSTRING(modelName)}, {0}, {0}, {0}, {0}, {0}, {0}, {0}} };
+
+
+#define REFLECTED_END_OF_LIST \
+    static const REFLECTED_SOMETHING MU_C2(REFLECTED_, __COUNTER__) = {          REFLECTION_NOTHING,                   NULL,                                       { {0},{0}, {0}, {0}, {0}, {0}, {0}, {0}} };
+
+#define EXPAND_MODEL_PROPERTY(type, name) MU_EXPAND_ARGS(MODEL_PROPERTY, type, name)
+
+#define EXPAND_MODEL_REPORTED_PROPERTY(type, name) MU_EXPAND_ARGS(MODEL_REPORTED_PROPERTY, type, name)
+
+#define EXPAND_MODEL_DESIRED_PROPERTY(type, name, ...) MU_EXPAND_ARGS(MODEL_DESIRED_PROPERTY, type, name, __VA_ARGS__)
+
+#define EXPAND_MODEL_ACTION(...) MU_EXPAND_ARGS(MODEL_ACTION, __VA_ARGS__)
+
+#define EXPAND_MODEL_METHOD(...) MU_EXPAND_ARGS(MODEL_METHOD, __VA_ARGS__)
+
+#define BUILD_MODEL_STRUCT(elem) INSERT_FIELD_FOR_##elem
+
+#define CREATE_MODEL_ENTITY(modelName, callType, ...) MU_EXPAND_ARGS(CREATE_##callType(modelName, __VA_ARGS__))
+#define CREATE_SOMETHING(modelName, ...) MU_EXPAND_ARGS(CREATE_MODEL_ENTITY(modelName, __VA_ARGS__))
+#define CREATE_ELEMENT(modelName, elem) MU_EXPAND_ARGS(CREATE_SOMETHING(modelName, MU_EXPAND_ARGS(EXPAND_##elem)))
+
+#define CREATE_MODEL_ELEMENT(modelName, elem) MU_EXPAND_ARGS(CREATE_ELEMENT(modelName, elem))
+
+
+#define CREATE_MODEL_ENTITY_GLOBAL_INITIALIZATION(modelName, callType, ...) MU_EXPAND_ARGS(CREATE_GLOBAL_INITIALIZE_##callType(modelName, __VA_ARGS__))
+#define CREATE_SOMETHING_GLOBAL_INITIALIZATION(modelName, ...) MU_EXPAND_ARGS(CREATE_MODEL_ENTITY_GLOBAL_INITIALIZATION(modelName, __VA_ARGS__))
+#define CREATE_ELEMENT_GLOBAL_INITIALIZATION(modelName, elem) MU_EXPAND_ARGS(CREATE_SOMETHING_GLOBAL_INITIALIZATION(modelName, MU_EXPAND_ARGS(EXPAND_##elem)))
+#define CREATE_MODEL_ELEMENT_GLOBAL_INITIALIZE(modelName, elem) MU_EXPAND_ARGS(CREATE_ELEMENT_GLOBAL_INITIALIZATION(modelName, elem))
+
+#define CREATE_MODEL_ENTITY_GLOBAL_DEINITIALIZATION(modelName, callType, ...) MU_EXPAND_ARGS(CREATE_GLOBAL_DEINITIALIZE_##callType(modelName, __VA_ARGS__))
+#define CREATE_SOMETHING_GLOBAL_DEINITIALIZATION(modelName, ...) MU_EXPAND_ARGS(CREATE_MODEL_ENTITY_GLOBAL_DEINITIALIZATION(modelName, __VA_ARGS__))
+#define CREATE_ELEMENT_GLOBAL_DEINITIALIZATION(modelName, elem) MU_EXPAND_ARGS(CREATE_SOMETHING_GLOBAL_DEINITIALIZATION(modelName, MU_EXPAND_ARGS(EXPAND_##elem)))
+#define CREATE_MODEL_ELEMENT_GLOBAL_DEINITIALIZE(modelName, elem) MU_EXPAND_ARGS(CREATE_ELEMENT_GLOBAL_DEINITIALIZATION(modelName, elem))
+
+#define INSERT_FIELD_INTO_STRUCT(x, y) x y;
+
+
+#define INSERT_FIELD_FOR_MODEL_PROPERTY(type, name) INSERT_FIELD_INTO_STRUCT(type, name)
+#define CREATE_GLOBAL_INITIALIZE_MODEL_PROPERTY(modelName, type, name) /*do nothing, this is written by user*/
+#define CREATE_GLOBAL_DEINITIALIZE_MODEL_PROPERTY(modelName, type, name) /*do nothing, this is user's stuff*/
+
+/*REPORTED_PROPERTY is not different than regular WITH_DATA*/
+#define INSERT_FIELD_FOR_MODEL_REPORTED_PROPERTY(type, name) INSERT_FIELD_INTO_STRUCT(type, name)
+#define CREATE_GLOBAL_INITIALIZE_MODEL_REPORTED_PROPERTY(modelName, type,name) GlobalInitialize_##type((char*)destination+offsetof(modelName, name));
+#define CREATE_GLOBAL_DEINITIALIZE_MODEL_REPORTED_PROPERTY(modelName, type,name) GlobalDeinitialize_##type((char*)destination+offsetof(modelName, name));
+
+/*DESIRED_PROPERTY is not different than regular WITH_DATA*/
+#define INSERT_FIELD_FOR_MODEL_DESIRED_PROPERTY(type, name, ...) INSERT_FIELD_INTO_STRUCT(type, name)
+#define CREATE_GLOBAL_INITIALIZE_MODEL_DESIRED_PROPERTY(modelName, type, name, ...) /*do nothing*/
+#define CREATE_GLOBAL_DEINITIALIZE_MODEL_DESIRED_PROPERTY(modelName, type, name, ...) /*do nothing*/
+
+#define INSERT_FIELD_FOR_MODEL_ACTION(name, ...) /* action isn't a part of the model struct */
+#define INSERT_FIELD_FOR_MODEL_METHOD(name, ...) /* method isn't a part of the model struct */
+
+#define CREATE_GLOBAL_INITIALIZE_MODEL_ACTION(...) /*do nothing*/
+#define CREATE_GLOBAL_DEINITIALIZE_MODEL_ACTION(...) /*do nothing*/
+
+#define CREATE_GLOBAL_INITIALIZE_MODEL_METHOD(...) /*do nothing*/
+#define CREATE_GLOBAL_DEINITIALIZE_MODEL_METHOD(...) /*do nothing*/
+
+#define CREATE_MODEL_PROPERTY(modelName, type, name) \
+    IMPL_PROPERTY(type, name, modelName)
+
+#define CREATE_MODEL_REPORTED_PROPERTY(modelName, type, name) \
+    IMPL_REPORTED_PROPERTY(type, name, modelName)
+
+#define CREATE_MODEL_DESIRED_PROPERTY(modelName, type, name, ...) \
+    IMPL_DESIRED_PROPERTY(type, name, modelName, __VA_ARGS__)
+
+#define IMPL_PROPERTY(propertyType, propertyName, modelName) \
+    static int Create_AGENT_DATA_TYPE_From_Ptr_##modelName##propertyName(void* param, AGENT_DATA_TYPE* dest) \
+    { \
+        return MU_C1(ToAGENT_DATA_TYPE_##propertyType)(dest, *(propertyType*)param); \
+    } \
+    REFLECTED_PROPERTY(propertyType, propertyName, modelName)
+
+#define IMPL_REPORTED_PROPERTY(propertyType, propertyName, modelName) \
+    static int Create_AGENT_DATA_TYPE_From_Ptr_##modelName##propertyName(void* param, AGENT_DATA_TYPE* dest) \
+    { \
+        return MU_C1(ToAGENT_DATA_TYPE_##propertyType)(dest, *(propertyType*)param); \
+    } \
+    REFLECTED_REPORTED_PROPERTY(propertyType, propertyName, modelName)
+
+#define IMPL_DESIRED_PROPERTY(propertyType, propertyName, modelName, ...)           \
+    static void DesiredPropertyInitialize_##modelName##propertyName(void* destination)                             \
+    {                                                                                                   \
+        GlobalInitialize_##propertyType(destination);                                                   \
+    }                                                                                                   \
+    static void DesiredPropertyDeinitialize_##modelName##propertyName(void* destination)                           \
+    {                                                                                                   \
+       GlobalDeinitialize_##propertyType(destination);                                                  \
+    }                                                                                                   \
+    REFLECTED_DESIRED_PROPERTY(propertyType, propertyName, modelName, __VA_ARGS__)          \
+
+#define CREATE_MODEL_ACTION(modelName, actionName, ...) \
+    DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(modelName##actionName, 1); \
+    EXECUTE_COMMAND_RESULT actionName (modelName* device MU_FOR_EACH_2(DEFINE_FUNCTION_PARAMETER, __VA_ARGS__)); \
+    static EXECUTE_COMMAND_RESULT MU_C2(actionName, WRAPPER)(void* device, size_t ParameterCount, const AGENT_DATA_TYPE* values); \
+    /*for macro purposes, this array always has at least 1 element*/ \
+    /*Codes_SRS_SERIALIZER_99_043:[ It is valid for a method not to have any parameters.]*/ \
+    DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(actionName, 1); \
+    static const WRAPPER_ARGUMENT MU_C2(actionName, WRAPPERARGUMENTS)[MU_DIV2(MU_INC(MU_INC(MU_COUNT_ARG(__VA_ARGS__))))] = { MU_FOR_EACH_2_COUNTED(MAKE_WRAPPER_ARGUMENT, __VA_ARGS__) MU_IFCOMMA(MU_INC(MU_INC(MU_COUNT_ARG(__VA_ARGS__)))) {0} }; \
+    REFLECTED_ACTION(actionName, MU_DIV2(MU_COUNT_ARG(__VA_ARGS__)), MU_C2(actionName, WRAPPERARGUMENTS), MU_C2(actionName, WRAPPER), modelName) \
+    /*Codes_SRS_SERIALIZER_99_040:[ In addition to declaring the function, DECLARE_IOT_METHOD shall provide a definition for a wrapper that takes as parameters a size_t parameterCount and const AGENT_DATA_TYPE*.] */ \
+    /*Codes_SRS_SERIALIZER_99_041:[ This wrapper shall convert all the arguments to predefined types and then call the function written by the data provider developer.]*/ \
+    static EXECUTE_COMMAND_RESULT MU_C2(actionName, WRAPPER)(void* device, size_t ParameterCount, const AGENT_DATA_TYPE* values) \
+    { \
+        EXECUTE_COMMAND_RESULT result; \
+        DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(actionName, 2); \
+        /*Codes_SRS_SERIALIZER_99_045:[ If the number of passed parameters doesn't match the number of declared parameters, wrapper execution shall fail and return DATA_PROVIDER_INVALID_ARG;]*/ \
+        if(ParameterCount != MU_DIV2(MU_COUNT_ARG(__VA_ARGS__))) \
+        { \
+            result = EXECUTE_COMMAND_ERROR; \
+        } \
+        else \
+        { \
+            /*the below line takes care of initialized but not referenced parameter warning*/ \
+            DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(actionName, 3); \
+            MU_IF(MU_DIV2(MU_COUNT_ARG(__VA_ARGS__)), size_t iParameter = 0;, ) \
+            DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(actionName, 4); \
+            /*the below line takes care of an unused parameter when values is really never questioned*/ \
+            DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(actionName, 5); \
+            MU_FOR_EACH_2(DEFINE_LOCAL_PARAMETER, __VA_ARGS__) \
+            DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(actionName, 6); \
+            MU_IF(MU_DIV2(MU_COUNT_ARG(__VA_ARGS__)), , (void)values;) \
+            { \
+               DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(actionName, 7); \
+            } \
+            MU_FOR_EACH_2_KEEP_1(START_BUILD_LOCAL_PARAMETER, EXECUTE_COMMAND_ERROR, __VA_ARGS__) \
+            { \
+               DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(actionName, 8); \
+            } \
+            result = actionName((modelName*)device MU_FOR_EACH_2(PUSH_LOCAL_PARAMETER, __VA_ARGS__)); \
+            MU_FOR_EACH_2_REVERSE(END_BUILD_LOCAL_PARAMETER, __VA_ARGS__) \
+        } \
+        return result; \
+    }
+
+#define CREATE_MODEL_METHOD(modelName, methodName, ...) \
+    DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(modelName##methodName, 1); \
+    METHODRETURN_HANDLE methodName (modelName* device MU_FOR_EACH_2(DEFINE_FUNCTION_PARAMETER, __VA_ARGS__)); \
+    static METHODRETURN_HANDLE MU_C2(methodName, WRAPPER)(void* device, size_t ParameterCount, const AGENT_DATA_TYPE* values); \
+    /*for macro purposes, this array always has at least 1 element*/ \
+    /*Codes_SRS_SERIALIZER_H_02_030: [ It is valid for a method function not to have any parameters. ]*/ \
+    DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(methodName, 1); \
+    static const WRAPPER_ARGUMENT MU_C2(methodName, WRAPPERARGUMENTS)[MU_DIV2(MU_INC(MU_INC(MU_COUNT_ARG(__VA_ARGS__))))] = { MU_FOR_EACH_2_COUNTED(MAKE_WRAPPER_ARGUMENT, __VA_ARGS__) MU_IFCOMMA(MU_INC(MU_INC(MU_COUNT_ARG(__VA_ARGS__)))) {0} }; \
+    REFLECTED_METHOD(methodName, MU_DIV2(MU_COUNT_ARG(__VA_ARGS__)), MU_C2(methodName, WRAPPERARGUMENTS), MU_C2(methodName, WRAPPER), modelName) \
+    /*Codes_SRS_SERIALIZER_H_02_034: [ WITH_METHOD shall result in the declaration of a conversion function with the prototype METHODRETURN_HANDLE nameWRAPPER(size_t ParameterCount, const AGENT_DATA_TYPE* values)' ]*/ \
+    /*Codes_SRS_SERIALIZER_H_02_031: [ The function shall convert the input arguments to the types declared in the method parameter list and then call the user-defined method function. ]*/ \
+    static METHODRETURN_HANDLE MU_C2(methodName, WRAPPER)(void* device, size_t ParameterCount, const AGENT_DATA_TYPE* values) \
+    { \
+        METHODRETURN_HANDLE result; \
+        DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(methodName, 2); \
+        /*Codes_SRS_SERIALIZER_H_02_032: [ If the number of arguments passed to the conversion function does not match the expected count, the function shall return DATAPROVIDER_INVALID_ARG. ]*/ \
+        if(ParameterCount != MU_DIV2(MU_COUNT_ARG(__VA_ARGS__))) \
+        { \
+            LogError("expected parameter count (%lu) does not match the actual parameter count (%lu)", (unsigned long)ParameterCount, (unsigned long)MU_COUNT_ARG(__VA_ARGS__)); \
+            result = NULL; \
+        } \
+        else \
+        { \
+            /*the below line takes care of initialized but not referenced parameter warning*/ \
+            DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(methodName, 3); \
+            MU_IF(MU_DIV2(MU_COUNT_ARG(__VA_ARGS__)), size_t iParameter = 0;, ) \
+            DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(methodName, 4); \
+            /*the below line takes care of an unused parameter when values is really never questioned*/ \
+            DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(methodName, 5); \
+            MU_FOR_EACH_2(DEFINE_LOCAL_PARAMETER, __VA_ARGS__) \
+            DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(methodName, 6); \
+            MU_IF(MU_DIV2(MU_COUNT_ARG(__VA_ARGS__)), , (void)values;) \
+            { \
+               DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(actionName, 7); \
+            } \
+            MU_FOR_EACH_2_KEEP_1(START_BUILD_LOCAL_PARAMETER, NULL,__VA_ARGS__) \
+            { \
+               DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(actionName, 8); \
+            } \
+            result = methodName((modelName*)device MU_FOR_EACH_2(PUSH_LOCAL_PARAMETER, __VA_ARGS__)); \
+            MU_FOR_EACH_2_REVERSE(END_BUILD_LOCAL_PARAMETER, __VA_ARGS__) \
+        } \
+        return result; \
+    }
+
+#define CREATE_AGENT_DATA_TYPE(type, name) \
+    result = (( result==AGENT_DATA_TYPES_OK) && (ToAGENT_DATA_TYPE_##type( &(members[iMember]), value.name) == AGENT_DATA_TYPES_OK))?AGENT_DATA_TYPES_OK:AGENT_DATA_TYPES_ERROR; \
+    iMember+= ((result==AGENT_DATA_TYPES_OK)?1:0);
+
+#define BUILD_DESTINATION_FIELD(type, name) \
+    if(result == AGENT_DATA_TYPES_OK) \
+    { \
+        size_t i; \
+        bool wasFieldConverted = false; \
+        for (i = 0; i < source->value.edmComplexType.nMembers; i++) \
+        { \
+            /*the name of the field of the complex type must match the name of the field of the structure (parameter name here)*/ \
+            if (strcmp(source->value.edmComplexType.fields[i].fieldName, MU_TOSTRING(name)) == 0) \
+            { /*Codes_SRS_SERIALIZER_99_017:[ These types can either be one of the types mentioned in WITH_DATA or it can be a type introduced by a previous DECLARE_STRUCT.]*/ \
+                wasFieldConverted = (MU_C2(FromAGENT_DATA_TYPE_, type)(source->value.edmComplexType.fields[i].value, &(destination->name)) == AGENT_DATA_TYPES_OK); \
+                break; \
+            } \
+        } \
+        result = (wasFieldConverted == true)? AGENT_DATA_TYPES_OK: AGENT_DATA_TYPES_INVALID_ARG; \
+    } \
+    else \
+    { \
+        /*fallthrough*/ \
+    }
+
+#define UNBUILD_DESTINATION_FIELD(value, type, name) \
+    MU_C2(destroyLocalParameter, type)(&(value->name));
+
+
+#define ADDRESS_MACRO(x) ,&x
+
+#define KEEP_FIRST_(X, ...) X
+#ifdef _MSC_VER
+#define KEEP_FIRST(X) KEEP_FIRST_ LPAREN X)
+#else
+#define KEEP_FIRST(X) KEEP_FIRST_(X)
+#endif
+
+#define PROMOTIONMAP_float double, double
+#define PROMOTIONMAP_int8_t int, int
+#define PROMOTIONMAP_uint8_t int, int
+#define PROMOTIONMAP_int16_t int, int
+#define PROMOTIONMAP__Bool int, int
+#define PROMOTIONMAP_bool int, int
+
+#define CASTMAP_float (float), (float)
+#define CASTMAP_int8_t (int8_t), (int8_t)
+#define CASTMAP_uint8_t (uint8_t), (uint8_t)
+#define CASTMAP_int16_t (int16_t), (int16_t)
+#define CASTMAP__Bool 0!=, 0!=
+#define CASTMAP_bool 0!=, 0!=
+
+#define EMPTY_TOKEN
+
+#define ANOTHERIF(x) MU_C2(ANOTHERIF,x)
+#define ANOTHERIF0(a,b) a
+#define ANOTHERIF1(a,b) b
+#define ANOTHERIF2(a,b) b
+#define ANOTHERIF3(a,b) b
+#define ANOTHERIF4(a,b) b
+#define ANOTHERIF5(a,b) b
+#define ANOTHERIF6(a,b) b
+#define ANOTHERIF7(a,b) b
+#define ANOTHERIF8(a,b) b
+#define ANOTHERIF9(a,b) b
+#define ANOTHERIF10(a,b) b
+#define ANOTHERIF11(a,b) b
+#define ANOTHERIF12(a,b) b
+
+#define MAP_PROMOTED_TYPE(X) ANOTHERIF(MU_DEC(MU_COUNT_ARG(PROMOTIONMAP_##X))) (X, KEEP_FIRST(PROMOTIONMAP_##X))
+#define MAP_CAST_TYPE(X) ANOTHERIF(MU_DEC(MU_COUNT_ARG(CASTMAP_##X)))    (EMPTY_TOKEN, KEEP_FIRST(CASTMAP_##X)  )
+
+#define MU_IFCOMMA(N) MU_C2(MU_IFCOMMA_, N)
+#define MU_IFCOMMA_0
+#define MU_IFCOMMA_2
+#define MU_IFCOMMA_4 ,
+#define MU_IFCOMMA_6 ,
+#define MU_IFCOMMA_8 ,
+#define MU_IFCOMMA_10 ,
+#define MU_IFCOMMA_12 ,
+#define MU_IFCOMMA_14 ,
+#define MU_IFCOMMA_16 ,
+#define MU_IFCOMMA_18 ,
+#define MU_IFCOMMA_20 ,
+#define MU_IFCOMMA_22 ,
+#define MU_IFCOMMA_24 ,
+#define MU_IFCOMMA_26 ,
+#define MU_IFCOMMA_28 ,
+#define MU_IFCOMMA_30 ,
+#define MU_IFCOMMA_32 ,
+#define MU_IFCOMMA_34 ,
+#define MU_IFCOMMA_36 ,
+#define MU_IFCOMMA_38 ,
+#define MU_IFCOMMA_40 ,
+#define MU_IFCOMMA_42 ,
+#define MU_IFCOMMA_44 ,
+#define MU_IFCOMMA_46 ,
+#define MU_IFCOMMA_48 ,
+#define MU_IFCOMMA_50 ,
+#define MU_IFCOMMA_52 ,
+#define MU_IFCOMMA_54 ,
+#define MU_IFCOMMA_56 ,
+#define MU_IFCOMMA_58 ,
+#define MU_IFCOMMA_60 ,
+#define MU_IFCOMMA_62 ,
+#define MU_IFCOMMA_64 ,
+#define MU_IFCOMMA_66 ,
+#define MU_IFCOMMA_68 ,
+#define MU_IFCOMMA_70 ,
+#define MU_IFCOMMA_72 ,
+#define MU_IFCOMMA_74 ,
+#define MU_IFCOMMA_76 ,
+#define MU_IFCOMMA_78 ,
+#define MU_IFCOMMA_80 ,
+#define MU_IFCOMMA_82 ,
+#define MU_IFCOMMA_84 ,
+#define MU_IFCOMMA_86 ,
+#define MU_IFCOMMA_88 ,
+#define MU_IFCOMMA_90 ,
+#define MU_IFCOMMA_92 ,
+#define MU_IFCOMMA_94 ,
+#define MU_IFCOMMA_96 ,
+#define MU_IFCOMMA_98 ,
+#define MU_IFCOMMA_100 ,
+#define MU_IFCOMMA_102 ,
+#define MU_IFCOMMA_104 ,
+#define MU_IFCOMMA_106 ,
+#define MU_IFCOMMA_108 ,
+#define MU_IFCOMMA_110 ,
+#define MU_IFCOMMA_112 ,
+#define MU_IFCOMMA_114 ,
+#define MU_IFCOMMA_116 ,
+#define MU_IFCOMMA_118 ,
+#define MU_IFCOMMA_120 ,
+#define MU_IFCOMMA_122 ,
+#define MU_IFCOMMA_124 ,
+#define MU_IFCOMMA_126 ,
+#define MU_IFCOMMA_128 ,
+
+#define DEFINE_LOCAL_PARAMETER(type, name) type MU_C2(name,_local); GlobalInitialize_##type(& MU_C2(name, _local));
+
+#define START_BUILD_LOCAL_PARAMETER(errorWhenItFails, type, name) \
+    if (MU_C2(FromAGENT_DATA_TYPE_, type)(&values[iParameter], &MU_C2(name, _local)) != AGENT_DATA_TYPES_OK) \
+    { \
+        /*Codes_SRS_SERIALIZER_99_046:[ If the types of the parameters do not match the declared types, DATAPROVIDER_INVALID_ARG shall be returned.]*/ \
+        result = errorWhenItFails; \
+    }\
+    else \
+    { \
+        iParameter++;
+
+#define END_BUILD_LOCAL_PARAMETER(type, name) \
+    (void)MU_C2(destroyLocalParameter, type)(&MU_C2(name, _local)); \
+    }
+
+/*The following constructs have been devised to work around the precompiler bug of Visual Studio 2005, version 14.00.50727.42*/
+/* The bug is explained in https://connect.microsoft.com/VisualStudio/feedback/details/278752/comma-missing-when-using-va-args */
+/*A short description is: preprocessor is mysteriously eating commas ','.
+In order to feed the appetite of the preprocessor, several constructs have
+been devised that can sustain a missing ',' while still compiling and while still doing nothing
+and while hopefully being eliminated from the code based on "doesn't do anything" so no code size penalty
+*/
+
+/*the reason why all these constructs work is:
+if two strings separated by a comma will lose the comma (myteriously) then they will become just one string:
+"a", "b" ------Preprocessor------> "a" "b" -----Compiler----> "ab"
+*/
+
+#define LOTS_OF_COMMA_TO_BE_EATEN /*there were witnesses where as many as THREE commas have been eaten!*/ \
+"0" "1", "2", "3", "4", "5", "6", "7", "8", "9"
+#define DEFINITION_THAT_CAN_SUSTAIN_A_COMMA_STEAL(name, instance) static const char* eatThese_COMMA_##name##instance[] = {LOTS_OF_COMMA_TO_BE_EATEN}
+
+#define PUSH_LOCAL_PARAMETER(type, name) , MU_C2(name, _local)
+#define DEFINE_FUNCTION_PARAMETER(type, name) , type name
+#define MAKE_WRAPPER_ARGUMENT(N, type, name) {MU_TOSTRING(type), MU_TOSTRING(name)} MU_IFCOMMA(N)
+
+/*Codes_SRS_SERIALIZER_99_019:[ Create_AGENT_DATA_TYPE_from_DOUBLE]*/
+/*Codes_SRS_SERIALIZER_99_004:[ The propertyType can be any of the following data types: double]*/
+static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, double)(AGENT_DATA_TYPE* dest, double source)
+{
+    return Create_AGENT_DATA_TYPE_from_DOUBLE(dest, source);
+}
+
+static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, double)(const AGENT_DATA_TYPE* agentData, double* dest)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    if (agentData->type != EDM_DOUBLE_TYPE)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+    }
+    else
+    {
+        *dest = agentData->value.edmDouble.value;
+        result = AGENT_DATA_TYPES_OK;
+    }
+    return result;
+}
+
+static void MU_C2(GlobalInitialize_, double)(void* dest)
+{
+    *(double*)dest = 0.0;
+}
+
+static void MU_C2(GlobalDeinitialize_, double)(void* dest)
+{
+    (void)(dest);
+}
+
+/*Codes_SRS_SERIALIZER_99_021:[ Create_AGENT_DATA_TYPE_from_FLOAT]*/
+/*Codes_SRS_SERIALIZER_99_006:[ float]*/
+static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, float)(AGENT_DATA_TYPE* dest, float source)
+{
+    return Create_AGENT_DATA_TYPE_from_FLOAT(dest, source);
+}
+
+static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, float)(const AGENT_DATA_TYPE* agentData, float* dest)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    if (agentData->type != EDM_SINGLE_TYPE)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+    }
+    else
+    {
+        *dest = agentData->value.edmSingle.value;
+        result = AGENT_DATA_TYPES_OK;
+    }
+    return result;
+}
+
+static void MU_C2(GlobalInitialize_, float)(void* dest)
+{
+    *(float*)dest = 0.0f;
+}
+
+static void MU_C2(GlobalDeinitialize_, float)(void* dest)
+{
+    (void)(dest);
+}
+
+
+/*Codes_SRS_SERIALIZER_99_020:[ Create_AGENT_DATA_TYPE_from_SINT32]*/
+/*Codes_SRS_SERIALIZER_99_005:[ int], */
+static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, int)(AGENT_DATA_TYPE* dest, int source)
+{
+    return Create_AGENT_DATA_TYPE_from_SINT32(dest, source);
+}
+
+static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, int)(const AGENT_DATA_TYPE* agentData, int* dest)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    if (agentData->type != EDM_INT32_TYPE)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+    }
+    else
+    {
+        *dest = agentData->value.edmInt32.value;
+        result = AGENT_DATA_TYPES_OK;
+    }
+    return result;
+}
+
+static void MU_C2(GlobalInitialize_, int)(void* dest)
+{
+    *(int*)dest = 0;
+}
+
+static void MU_C2(GlobalDeinitialize_, int)(void* dest)
+{
+    (void)(dest);
+}
+
+/*Codes_SRS_SERIALIZER_99_022:[ Create_AGENT_DATA_TYPE_from_SINT64]*/
+/*Codes_SRS_SERIALIZER_99_007:[ long]*/
+static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, long)(AGENT_DATA_TYPE* dest, long source)
+{
+    return Create_AGENT_DATA_TYPE_from_SINT64(dest, source);
+}
+
+static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, long)(const AGENT_DATA_TYPE* agentData, long* dest)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    if (agentData->type != EDM_INT64_TYPE)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+    }
+    else
+    {
+        *dest = (long)agentData->value.edmInt64.value;
+        result = AGENT_DATA_TYPES_OK;
+    }
+    return result;
+}
+
+static void MU_C2(GlobalInitialize_, long)(void* dest)
+{
+    *(long*)dest = 0;
+}
+
+static void MU_C2(GlobalDeinitialize_, long)(void* dest)
+{
+    (void)(dest);
+}
+
+
+/*Codes_SRS_SERIALIZER_99_023:[ Create_AGENT_DATA_TYPE_from_SINT8]*/
+/*Codes_SRS_SERIALIZER_99_008:[ int8_t]*/
+static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, int8_t)(AGENT_DATA_TYPE* dest, int8_t source)
+{
+    return Create_AGENT_DATA_TYPE_from_SINT8(dest, source);
+}
+
+static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, int8_t)(const AGENT_DATA_TYPE* agentData, int8_t* dest)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    if (agentData->type != EDM_SBYTE_TYPE)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+    }
+    else
+    {
+        *dest = agentData->value.edmSbyte.value;
+        result = AGENT_DATA_TYPES_OK;
+    }
+    return result;
+}
+
+static void MU_C2(GlobalInitialize_, int8_t)(void* dest)
+{
+    *(int8_t*)dest = 0;
+}
+
+static void MU_C2(GlobalDeinitialize_, int8_t)(void* dest)
+{
+    (void)(dest);
+}
+
+/*Codes_SRS_SERIALIZER_99_024:[ Create_AGENT_DATA_TYPE_from_UINT8]*/
+/*Codes_SRS_SERIALIZER_99_009:[ uint8_t]*/
+static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, uint8_t)(AGENT_DATA_TYPE* dest, uint8_t source)
+{
+    return Create_AGENT_DATA_TYPE_from_UINT8(dest, source);
+}
+
+static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, uint8_t)(const AGENT_DATA_TYPE* agentData, uint8_t* dest)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    if (agentData->type != EDM_BYTE_TYPE)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+    }
+    else
+    {
+        *dest = agentData->value.edmByte.value;
+        result = AGENT_DATA_TYPES_OK;
+    }
+    return result;
+}
+
+static void MU_C2(GlobalInitialize_, uint8_t)(void* dest)
+{
+    *(uint8_t*)dest = 0;
+}
+
+static void MU_C2(GlobalDeinitialize_, uint8_t)(void* dest)
+{
+    (void)(dest);
+}
+
+
+/*Codes_SRS_SERIALIZER_99_025:[ Create_AGENT_DATA_TYPE_from_SINT16]*/
+/*Codes_SRS_SERIALIZER_99_010:[ int16_t]*/
+static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, int16_t)(AGENT_DATA_TYPE* dest, int16_t source)
+{
+    return Create_AGENT_DATA_TYPE_from_SINT16(dest, source);
+}
+
+static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, int16_t)(const AGENT_DATA_TYPE* agentData, int16_t* dest)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    if (agentData->type != EDM_INT16_TYPE)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+    }
+    else
+    {
+        *dest = agentData->value.edmInt16.value;
+        result = AGENT_DATA_TYPES_OK;
+    }
+    return result;
+}
+
+static void MU_C2(GlobalInitialize_, int16_t)(void* dest)
+{
+    *(int16_t*)dest = 0;
+}
+
+static void MU_C2(GlobalDeinitialize_, int16_t)(void* dest)
+{
+    (void)(dest);
+}
+
+/*Codes_SRS_SERIALIZER_99_026:[ Create_AGENT_DATA_TYPE_from_SINT32]*/
+/*Codes_SRS_SERIALIZER_99_011:[ int32_t]*/
+static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, int32_t)(AGENT_DATA_TYPE* dest, int32_t source)
+{
+    return Create_AGENT_DATA_TYPE_from_SINT32(dest, source);
+}
+
+static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, int32_t)(const AGENT_DATA_TYPE* agentData, int32_t* dest)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    if (agentData->type != EDM_INT32_TYPE)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+    }
+    else
+    {
+        *dest = agentData->value.edmInt32.value;
+        result = AGENT_DATA_TYPES_OK;
+    }
+    return result;
+}
+
+static void MU_C2(GlobalInitialize_, int32_t)(void* dest)
+{
+    *(int32_t*)dest = 0;
+}
+
+static void MU_C2(GlobalDeinitialize_, int32_t)(void* dest)
+{
+    (void)(dest);
+}
+
+/*Codes_SRS_SERIALIZER_99_027:[ Create_AGENT_DATA_TYPE_from_SINT64]*/
+/*Codes_SRS_SERIALIZER_99_012:[ int64_t]*/
+static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, int64_t)(AGENT_DATA_TYPE* dest, int64_t source)
+{
+    return Create_AGENT_DATA_TYPE_from_SINT64(dest, source);
+}
+
+static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, int64_t)(const AGENT_DATA_TYPE* agentData, int64_t* dest)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    if (agentData->type != EDM_INT64_TYPE)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+    }
+    else
+    {
+        *dest = agentData->value.edmInt64.value;
+        result = AGENT_DATA_TYPES_OK;
+    }
+    return result;
+}
+
+static void MU_C2(GlobalInitialize_, int64_t)(void* dest)
+{
+    *(int64_t*)dest = 0;
+}
+
+static void MU_C2(GlobalDeinitialize_, int64_t)(void* dest)
+{
+    (void)(dest);
+}
+
+/*Codes_SRS_SERIALIZER_99_013:[ bool]*/
+static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, bool)(AGENT_DATA_TYPE* dest, bool source)
+{
+    return Create_EDM_BOOLEAN_from_int(dest, source == true);
+}
+
+static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, bool)(const AGENT_DATA_TYPE* agentData, bool* dest)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    if (agentData->type != EDM_BOOLEAN_TYPE)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+    }
+    else
+    {
+        *dest = (agentData->value.edmBoolean.value == EDM_TRUE) ? true : false;
+        result = AGENT_DATA_TYPES_OK;
+    }
+    return result;
+}
+
+static void MU_C2(GlobalInitialize_, bool)(void* dest)
+{
+    *(bool*)dest = false;
+}
+
+static void MU_C2(GlobalDeinitialize_, bool)(void* dest)
+{
+    (void)(dest);
+}
+
+/*Codes_SRS_SERIALIZER_99_014:[ ascii_char_ptr]*/
+static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, ascii_char_ptr)(AGENT_DATA_TYPE* dest, ascii_char_ptr source)
+{
+    return Create_AGENT_DATA_TYPE_from_charz(dest, source);
+}
+
+static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, ascii_char_ptr)(const AGENT_DATA_TYPE* agentData, ascii_char_ptr* dest)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    if (agentData->type != EDM_STRING_TYPE)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+    }
+    else
+    {
+        if (*dest != NULL)
+        {
+            free(*dest);
+            *dest = NULL;
+        }
+
+        if (mallocAndStrcpy_s(dest, agentData->value.edmString.chars) != 0)
+        {
+            LogError("failure in mallocAndStrcpy_s");
+            result = AGENT_DATA_TYPES_ERROR;
+        }
+        else
+        {
+            result = AGENT_DATA_TYPES_OK;
+        }
+
+    }
+    return result;
+}
+
+static void MU_C2(GlobalInitialize_, ascii_char_ptr)(void* dest)
+{
+    *(ascii_char_ptr*)dest = NULL;
+}
+
+static void MU_C2(GlobalDeinitialize_, ascii_char_ptr)(void* dest)
+{
+    if (*(ascii_char_ptr*)dest != NULL)
+    {
+        free(*(ascii_char_ptr*)dest);
+    }
+}
+
+static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, ascii_char_ptr_no_quotes)(AGENT_DATA_TYPE* dest, ascii_char_ptr_no_quotes source)
+{
+    return Create_AGENT_DATA_TYPE_from_charz_no_quotes(dest, source);
+}
+
+static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, ascii_char_ptr_no_quotes)(const AGENT_DATA_TYPE* agentData, ascii_char_ptr_no_quotes* dest)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    if (agentData->type != EDM_STRING_NO_QUOTES_TYPE)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+    }
+    else
+    {
+        if (*dest != NULL)
+        {
+            free(*dest);
+            *dest = NULL;
+        }
+
+        if (mallocAndStrcpy_s(dest, agentData->value.edmStringNoQuotes.chars) != 0)
+        {
+            LogError("failure in mallocAndStrcpy_s");
+            result = AGENT_DATA_TYPES_ERROR;
+        }
+        else
+        {
+            result = AGENT_DATA_TYPES_OK;
+        }
+    }
+    return result;
+}
+
+static void MU_C2(GlobalInitialize_, ascii_char_ptr_no_quotes)(void* dest)
+{
+    *(ascii_char_ptr_no_quotes*)dest = NULL;
+}
+
+static void MU_C2(GlobalDeinitialize_, ascii_char_ptr_no_quotes)(void* dest)
+{
+    if (*(ascii_char_ptr_no_quotes*)dest != NULL)
+    {
+        free(*(ascii_char_ptr_no_quotes*)dest);
+    }
+}
+
+/*Codes_SRS_SERIALIZER_99_051:[ EDM_DATE_TIME_OFFSET*/
+/*Codes_SRS_SERIALIZER_99_053:[Create_AGENT_DATA_TYPE_from_EDM_DATE_TIME_OFFSET]*/
+static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, EDM_DATE_TIME_OFFSET)(AGENT_DATA_TYPE* dest, EDM_DATE_TIME_OFFSET source)
+{
+    return Create_AGENT_DATA_TYPE_from_EDM_DATE_TIME_OFFSET(dest, source);
+}
+
+static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, EDM_DATE_TIME_OFFSET)(const AGENT_DATA_TYPE* agentData, EDM_DATE_TIME_OFFSET* dest)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    if (agentData->type != EDM_DATE_TIME_OFFSET_TYPE)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+    }
+    else
+    {
+        *dest = agentData->value.edmDateTimeOffset;
+        result = AGENT_DATA_TYPES_OK;
+    }
+    return result;
+}
+
+static void MU_C2(GlobalInitialize_, EDM_DATE_TIME_OFFSET)(void* dest)
+{
+    memset(dest, 0, sizeof(EDM_DATE_TIME_OFFSET));
+}
+
+static void MU_C2(GlobalDeinitialize_, EDM_DATE_TIME_OFFSET)(void* dest)
+{
+    (void)(dest);
+}
+
+/*Codes_SRS_SERIALIZER_99_072:[ EDM_GUID]*/
+/*Codes_SRS_SERIALIZER_99_073:[ Create_AGENT_DATA_TYPE_from_EDM_GUID]*/
+static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, EDM_GUID)(AGENT_DATA_TYPE* dest, EDM_GUID guid)
+{
+    return Create_AGENT_DATA_TYPE_from_EDM_GUID(dest, guid);
+}
+
+static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, EDM_GUID)(const AGENT_DATA_TYPE* agentData, EDM_GUID* dest)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    if (agentData->type != EDM_GUID_TYPE)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+    }
+    else
+    {
+        (void)memcpy(dest->GUID, agentData->value.edmGuid.GUID, 16);
+        result = AGENT_DATA_TYPES_OK;
+    }
+    return result;
+}
+
+static void MU_C2(GlobalInitialize_, EDM_GUID)(void* dest)
+{
+    memset(dest, 0, sizeof(EDM_GUID));
+}
+
+static void MU_C2(GlobalDeinitialize_, EDM_GUID)(void* dest)
+{
+    (void)(dest);
+}
+
+
+/*Codes_SRS_SERIALIZER_99_074:[ EDM_BINARY]*/
+/*Codes_SRS_SERIALIZER_99_075:[ Create_AGENT_DATA_TYPE_from_EDM_BINARY]*/
+static AGENT_DATA_TYPES_RESULT MU_C2(ToAGENT_DATA_TYPE_, EDM_BINARY)(AGENT_DATA_TYPE* dest, EDM_BINARY edmBinary)
+{
+    return Create_AGENT_DATA_TYPE_from_EDM_BINARY(dest, edmBinary);
+}
+
+static AGENT_DATA_TYPES_RESULT MU_C2(FromAGENT_DATA_TYPE_, EDM_BINARY)(const AGENT_DATA_TYPE* agentData, EDM_BINARY* dest)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    if (agentData->type != EDM_BINARY_TYPE)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+    }
+    else
+    {
+        if ((dest->data = (unsigned char *)malloc(agentData->value.edmBinary.size)) == NULL) /*cast because this get included in a C++ file.*/
+        {
+            result = AGENT_DATA_TYPES_ERROR;
+        }
+        else
+        {
+            (void)memcpy(dest->data, agentData->value.edmBinary.data, agentData->value.edmBinary.size);
+            dest->size = agentData->value.edmBinary.size;
+            result = AGENT_DATA_TYPES_OK;
+        }
+    }
+    return result;
+}
+
+static void MU_C2(GlobalInitialize_, EDM_BINARY)(void* dest)
+{
+    ((EDM_BINARY*)dest)->data = NULL;
+    ((EDM_BINARY*)dest)->size = 0;
+}
+
+static void MU_C2(GlobalDeinitialize_, EDM_BINARY)(void* dest)
+{
+    if ((((EDM_BINARY*)dest)->data) != NULL)
+    {
+        free(((EDM_BINARY*)dest)->data);
+    }
+}
+
+static void MU_C2(destroyLocalParameter, EDM_BINARY)(EDM_BINARY* value)
+{
+    if (value != NULL)
+    {
+        free(value->data);
+        value->data = NULL;
+        value->size = 0;
+    }
+}
+
+static void MU_C2(destroyLocalParameter, EDM_BOOLEAN)(EDM_BOOLEAN* value)
+{
+    (void)value;
+}
+
+static void MU_C2(destroyLocalParameter, EDM_BYTE)(EDM_BYTE* value)
+{
+    (void)value;
+}
+
+static void MU_C2(destroyLocalParameter, EDM_DATE)(EDM_DATE* value)
+{
+    (void)value;
+}
+
+static void MU_C2(destroyLocalParameter, EDM_DATE_TIME_OFFSET)(EDM_DATE_TIME_OFFSET* value)
+{
+    (void)value;
+}
+
+static void MU_C2(destroyLocalParameter, EDM_DECIMAL)(EDM_DECIMAL* value)
+{
+    if (value != NULL)
+    {
+        STRING_delete(value->value);
+        value->value = NULL;
+    }
+}
+
+static void MU_C2(destroyLocalParameter, EDM_DOUBLE)(EDM_DOUBLE* value)
+{
+    (void)value;
+}
+
+static void MU_C2(destroyLocalParameter, EDM_DURATION)(EDM_DURATION* value)
+{
+    if (value != NULL)
+    {
+        free(value->digits);
+        value->digits = NULL;
+        value->nDigits = 0;
+    }
+}
+
+static void MU_C2(destroyLocalParameter, EDM_GUID)(EDM_GUID* value)
+{
+    (void)value;
+}
+
+static void MU_C2(destroyLocalParameter, EDM_INT16)(EDM_INT16* value)
+{
+    (void)value;
+}
+
+static void MU_C2(destroyLocalParameter, EDM_INT32)(EDM_INT32* value)
+{
+    (void)value;
+}
+
+static void MU_C2(destroyLocalParameter, EDM_INT64)(EDM_INT64* value)
+{
+    (void)value;
+}
+
+static void MU_C2(destroyLocalParameter, EDM_SBYTE)(EDM_SBYTE* value)
+{
+    (void)value;
+}
+
+static void MU_C2(destroyLocalParameter, EDM_SINGLE)(EDM_SINGLE* value)
+{
+    (void)value;
+}
+
+static void MU_C2(destroyLocalParameter, EDM_STRING)(EDM_STRING* value)
+{
+    (void)value;
+}
+
+
+static void MU_C2(destroyLocalParameter, EDM_TIME_OF_DAY)(EDM_TIME_OF_DAY* value)
+{
+    (void)value;
+}
+
+static void MU_C2(destroyLocalParameter, int)(int* value)
+{
+    (void)value;
+}
+
+static void MU_C2(destroyLocalParameter, float)(float* value)
+{
+    (void)value;
+}
+
+static void MU_C2(destroyLocalParameter, double)(double* value)
+{
+    (void)value;
+}
+
+static void MU_C2(destroyLocalParameter, long)(long* value)
+{
+    (void)value;
+}
+
+static void MU_C2(destroyLocalParameter, int8_t)(int8_t* value)
+{
+    (void)value;
+}
+
+static void MU_C2(destroyLocalParameter, uint8_t)(uint8_t* value)
+{
+    (void)value;
+}
+
+static void MU_C2(destroyLocalParameter, int16_t)(int16_t* value)
+{
+    (void)value;
+}
+
+static void MU_C2(destroyLocalParameter, int32_t)(int32_t* value)
+{
+    (void)value;
+}
+
+static void MU_C2(destroyLocalParameter, int64_t)(int64_t* value)
+{
+    (void)value;
+}
+
+static void MU_C2(destroyLocalParameter, bool)(bool* value)
+{
+    (void)value;
+}
+
+static void MU_C2(destroyLocalParameter, ascii_char_ptr)(ascii_char_ptr* value)
+{
+    if (value != NULL)
+    {
+        free(*value);
+    }
+
+}
+
+static void MU_C2(destroyLocalParameter, ascii_char_ptr_no_quotes)(ascii_char_ptr_no_quotes* value)
+{
+    if (value != NULL)
+    {
+        free(*value);
+    }
+}
+
+#ifdef __cplusplus
+    }
+#endif
+
+#endif /*SERIALIZER_H*/
+
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/serializer_devicetwin.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/serializer_devicetwin.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/inc/serializer_devicetwin.h	(revision 453)
@@ -0,0 +1,472 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+
+#ifndef SERIALIZER_DEVICE_TWIN_H
+#define SERIALIZER_DEVICE_TWIN_H
+
+#include "serializer.h"
+
+#include "iothub_client.h"
+#include "iothub_client_ll.h"
+#include "parson.h"
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/vector.h"
+#include "methodreturn.h"
+
+static void serializer_ingest(DEVICE_TWIN_UPDATE_STATE update_state, const unsigned char* payLoad, size_t size, void* userContextCallback)
+{
+    /*by convention, userContextCallback is a pointer to a model instance created with CodeFirst_CreateDevice*/
+
+    /*Codes_SRS_SERIALIZERDEVICETWIN_02_001: [ serializer_ingest shall clone the payload into a null terminated string. ]*/
+    char* copyOfPayload = (char*)malloc(size + 1);
+    if (copyOfPayload == NULL)
+    {
+        /*Codes_SRS_SERIALIZERDEVICETWIN_02_008: [ If any of the above operations fail, then serializer_ingest shall return. ]*/
+        LogError("unable to malloc\n");
+    }
+    else
+    {
+        (void)memcpy(copyOfPayload, payLoad, size);
+        copyOfPayload[size] = '\0';
+
+        bool parseDesiredNode = (update_state == DEVICE_TWIN_UPDATE_COMPLETE);
+
+        if (CodeFirst_IngestDesiredProperties(userContextCallback, copyOfPayload, parseDesiredNode) != CODEFIRST_OK)
+        {
+            /*Codes_SRS_SERIALIZERDEVICETWIN_02_008: [ If any of the above operations fail, then serializer_ingest shall return. ]*/
+            LogError("failure ingesting desired properties\n");
+        }
+        else
+        {
+            /*all is fine*/
+        }
+
+        free(copyOfPayload);
+    }
+}
+
+/*both LL and convenience layer can be served by the same callback*/
+static int deviceMethodCallback(const char* method_name, const unsigned char* payload, size_t size, unsigned char** response, size_t* resp_size, void* userContextCallback)
+{
+    int result;
+    /*Codes_SRS_SERIALIZERDEVICETWIN_02_021: [ deviceMethodCallback shall transform payload and size into a null terminated string. ]*/
+    char* payloadZeroTerminated = (char*)malloc(size + 1);
+    if (payloadZeroTerminated == NULL)
+    {
+        LogError("failure in malloc");
+        /*Codes_SRS_SERIALIZERDEVICETWIN_02_026: [ If any failure occurs in the above operations, then deviceMethodCallback shall fail, return 500, set *response to NULL and '*resp_size` to 0. ]*/
+        *response = NULL;
+        *resp_size = 0;
+        result = 500;
+    }
+    else
+    {
+        (void)memcpy(payloadZeroTerminated, payload, size);
+        payloadZeroTerminated[size] = '\0';
+
+        /*Codes_SRS_SERIALIZERDEVICETWIN_02_022: [ deviceMethodCallback shall call EXECUTE_METHOD passing the userContextCallback, method_name and the null terminated string build before. ]*/
+        METHODRETURN_HANDLE mr = EXECUTE_METHOD(userContextCallback, method_name, payloadZeroTerminated);
+
+        if (mr == NULL)
+        {
+            LogError("failure in EXECUTE_METHOD");
+            /*Codes_SRS_SERIALIZERDEVICETWIN_02_026: [ If any failure occurs in the above operations, then deviceMethodCallback shall fail, return 500, set *response to NULL and '*resp_size` to 0. ]*/
+            *response = NULL;
+            *resp_size = 0;
+            result = 500;
+        }
+        else
+        {
+            /*Codes_SRS_SERIALIZERDEVICETWIN_02_023: [ deviceMethodCallback shall get the MethodReturn_Data and shall copy the response JSON value into a new byte array. ]*/
+            const METHODRETURN_DATA* data = MethodReturn_GetReturn(mr);
+
+            /*Codes_SRS_SERIALIZERDEVICETWIN_02_025: [ deviceMethodCallback returns the statusCode from the user. ]*/
+            result = data->statusCode;
+
+            if (data->jsonValue == NULL)
+            {
+                *resp_size = 0;
+                *response = NULL;
+            }
+            else
+            {
+                *resp_size = strlen(data->jsonValue);
+                *response = (unsigned char*)malloc(*resp_size);
+                if (*response == NULL)
+                {
+                    LogError("failure in malloc");
+                    /*Codes_SRS_SERIALIZERDEVICETWIN_02_026: [ If any failure occurs in the above operations, then deviceMethodCallback shall fail, return 500, set *response to NULL and '*resp_size` to 0. ]*/
+                    *response = NULL;
+                    *resp_size = 0;
+                    result = 500;
+                }
+                else
+                {
+                    /*Codes_SRS_SERIALIZERDEVICETWIN_02_024: [ deviceMethodCallback shall set *response to this new byte array, *resp_size to the size of the array. ]*/
+                    (void)memcpy(*response, data->jsonValue, *resp_size);
+                }
+            }
+            MethodReturn_Destroy(mr);
+        }
+        free(payloadZeroTerminated);
+    }
+    return result;
+}
+
+/*an enum that sets the type of the handle used to record IoTHubDeviceTwin_Create was called*/
+#define IOTHUB_CLIENT_HANDLE_TYPE_VALUES \
+    IOTHUB_CLIENT_CONVENIENCE_HANDLE_TYPE, \
+    IOTHUB_CLIENT_LL_HANDLE_TYPE
+
+MU_DEFINE_ENUM_WITHOUT_INVALID(IOTHUB_CLIENT_HANDLE_TYPE, IOTHUB_CLIENT_HANDLE_TYPE_VALUES)
+
+typedef union IOTHUB_CLIENT_HANDLE_VALUE_TAG
+{
+    IOTHUB_CLIENT_HANDLE iothubClientHandle;
+    IOTHUB_CLIENT_LL_HANDLE iothubClientLLHandle;
+} IOTHUB_CLIENT_HANDLE_VALUE;
+
+typedef struct IOTHUB_CLIENT_HANDLE_VARIANT_TAG
+{
+    IOTHUB_CLIENT_HANDLE_TYPE iothubClientHandleType;
+    IOTHUB_CLIENT_HANDLE_VALUE iothubClientHandleValue;
+} IOTHUB_CLIENT_HANDLE_VARIANT;
+
+typedef struct SERIALIZER_DEVICETWIN_PROTOHANDLE_TAG /*it is called "PROTOHANDLE" because it is a primitive type of handle*/
+{
+    IOTHUB_CLIENT_HANDLE_VARIANT iothubClientHandleVariant;
+    void* deviceAssigned;
+} SERIALIZER_DEVICETWIN_PROTOHANDLE;
+
+static VECTOR_HANDLE g_allProtoHandles=NULL; /*contains SERIALIZER_DEVICETWIN_PROTOHANDLE*/
+
+static int lazilyAddProtohandle(const SERIALIZER_DEVICETWIN_PROTOHANDLE* protoHandle)
+{
+    int result;
+    if ((g_allProtoHandles == NULL) && ((g_allProtoHandles = VECTOR_create(sizeof(SERIALIZER_DEVICETWIN_PROTOHANDLE))) == NULL))
+    {
+        LogError("failure in VECTOR_create");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        if (VECTOR_push_back(g_allProtoHandles, protoHandle, 1) != 0)
+        {
+            LogError("failure in VECTOR_push_back");
+            result = MU_FAILURE;
+
+            /*leave it as it was*/
+
+            if (VECTOR_size(g_allProtoHandles) == 0)
+            {
+                VECTOR_destroy(g_allProtoHandles);
+                g_allProtoHandles = NULL;
+            }
+        }
+        else
+        {
+            result = 0;
+        }
+    }
+    return result;
+}
+
+static IOTHUB_CLIENT_RESULT Generic_IoTHubClient_SetCallbacks(const SERIALIZER_DEVICETWIN_PROTOHANDLE* protoHandle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK deviceTwinCallback, void* userContextCallback)
+{
+    IOTHUB_CLIENT_RESULT result;
+    /*Codes_SRS_SERIALIZERDEVICETWIN_02_011: [ IoTHubDeviceTwinCreate_Impl shall set the device twin callback. ]*/
+    switch (protoHandle->iothubClientHandleVariant.iothubClientHandleType)
+    {
+    case IOTHUB_CLIENT_CONVENIENCE_HANDLE_TYPE:
+    {
+        if ((result = IoTHubClient_SetDeviceTwinCallback(protoHandle->iothubClientHandleVariant.iothubClientHandleValue.iothubClientHandle, deviceTwinCallback, userContextCallback)) != IOTHUB_CLIENT_OK)
+        {
+            LogError("failure in IoTHubClient_SetDeviceTwinCallback");
+        }
+        else
+        {
+            /*Codes_SRS_SERIALIZERDEVICETWIN_02_027: [ IoTHubDeviceTwinCreate_Impl shall set the device method callback ]*/
+            if ((result = IoTHubClient_SetDeviceMethodCallback(protoHandle->iothubClientHandleVariant.iothubClientHandleValue.iothubClientHandle, deviceMethodCallback, userContextCallback)) != IOTHUB_CLIENT_OK)
+            {
+                (void)IoTHubClient_SetDeviceTwinCallback(protoHandle->iothubClientHandleVariant.iothubClientHandleValue.iothubClientHandle, NULL, NULL);
+                LogError("failure in IoTHubClient_SetDeviceMethodCallback");
+            }
+        }
+        break;
+    }
+    case IOTHUB_CLIENT_LL_HANDLE_TYPE:
+    {
+        if ((result =IoTHubClient_LL_SetDeviceTwinCallback(protoHandle->iothubClientHandleVariant.iothubClientHandleValue.iothubClientLLHandle, deviceTwinCallback, userContextCallback)) != IOTHUB_CLIENT_OK)
+        {
+            LogError("failure in IoTHubClient_LL_SetDeviceTwinCallback");
+        }
+        else
+        {
+            /*Codes_SRS_SERIALIZERDEVICETWIN_02_027: [ IoTHubDeviceTwinCreate_Impl shall set the device method callback ]*/
+            if ((result = IoTHubClient_LL_SetDeviceMethodCallback(protoHandle->iothubClientHandleVariant.iothubClientHandleValue.iothubClientLLHandle, deviceMethodCallback, userContextCallback)) != IOTHUB_CLIENT_OK)
+            {
+                (void)IoTHubClient_LL_SetDeviceTwinCallback(protoHandle->iothubClientHandleVariant.iothubClientHandleValue.iothubClientLLHandle, NULL, NULL);
+                LogError("failure in IoTHubClient_SetDeviceMethodCallback");
+            }
+        }
+        break;
+    }
+    default:
+    {
+        result = IOTHUB_CLIENT_ERROR;
+        LogError("INTERNAL ERROR");
+    }
+    }/*switch*/
+    return result;
+}
+
+static void* IoTHubDeviceTwinCreate_Impl(const char* name, size_t sizeOfName, SERIALIZER_DEVICETWIN_PROTOHANDLE* protoHandle)
+{
+    void* result;
+    /*Codes_SRS_SERIALIZERDEVICETWIN_02_009: [ IoTHubDeviceTwinCreate_Impl shall locate the model and the metadata for name by calling Schema_GetSchemaForModel/Schema_GetMetadata/Schema_GetModelByName. ]*/
+    SCHEMA_HANDLE h = Schema_GetSchemaForModel(name);
+    if (h == NULL)
+    {
+        /*Codes_SRS_SERIALIZERDEVICETWIN_02_014: [ Otherwise, IoTHubDeviceTwinCreate_Impl shall fail and return NULL. ]*/
+        LogError("failure in Schema_GetSchemaForModel.");
+        result = NULL;
+    }
+    else
+    {
+        void* metadata = Schema_GetMetadata(h);
+        SCHEMA_MODEL_TYPE_HANDLE modelType = Schema_GetModelByName(h, name);
+        if (modelType == NULL)
+        {
+            /*Codes_SRS_SERIALIZERDEVICETWIN_02_014: [ Otherwise, IoTHubDeviceTwinCreate_Impl shall fail and return NULL. ]*/
+            LogError("failure in Schema_GetModelByName");
+            result = NULL;
+        }
+        else
+        {
+            /*Codes_SRS_SERIALIZERDEVICETWIN_02_010: [ IoTHubDeviceTwinCreate_Impl shall call CodeFirst_CreateDevice. ]*/
+            result = CodeFirst_CreateDevice(modelType, (REFLECTED_DATA_FROM_DATAPROVIDER *)metadata, sizeOfName, true);
+            if (result == NULL)
+            {
+                /*Codes_SRS_SERIALIZERDEVICETWIN_02_014: [ Otherwise, IoTHubDeviceTwinCreate_Impl shall fail and return NULL. ]*/
+                LogError("failure in CodeFirst_CreateDevice");
+                /*return as is*/
+            }
+            else
+            {
+                protoHandle->deviceAssigned = result;
+                if (Generic_IoTHubClient_SetCallbacks(protoHandle, serializer_ingest, result) != IOTHUB_CLIENT_OK)
+                {
+                    /*Codes_SRS_SERIALIZERDEVICETWIN_02_014: [ Otherwise, IoTHubDeviceTwinCreate_Impl shall fail and return NULL. ]*/
+                    LogError("failure in Generic_IoTHubClient_SetCallbacks");
+                    CodeFirst_DestroyDevice(result);
+                    result = NULL;
+                }
+                else
+                {
+                    /*lazily add the protohandle to the array of tracking handles*/
+
+                    /*Codes_SRS_SERIALIZERDEVICETWIN_02_012: [ IoTHubDeviceTwinCreate_Impl shall record the pair of (device, IoTHubClient(_LL)). ]*/
+                    if (lazilyAddProtohandle(protoHandle) != 0)
+                    {
+                        /*Codes_SRS_SERIALIZERDEVICETWIN_02_014: [ Otherwise, IoTHubDeviceTwinCreate_Impl shall fail and return NULL. ]*/
+                        LogError("unable to add the protohandle to the collection of handles");
+                        /*unsubscribe*/
+                        if (Generic_IoTHubClient_SetCallbacks(protoHandle, NULL, NULL) != IOTHUB_CLIENT_OK)
+                        {
+                            /*just log the error*/
+                            LogError("failure in Generic_IoTHubClient_SetCallbacks");
+                        }
+                        CodeFirst_DestroyDevice(result);
+                        result = NULL;
+                    }
+                    else
+                    {
+                        /*Codes_SRS_SERIALIZERDEVICETWIN_02_013: [ If all operations complete successfully then IoTHubDeviceTwinCreate_Impl shall succeeds and return a non-NULL value. ]*/
+                        /*return as is*/
+                    }
+                }
+            }
+        }
+    }
+    return result;
+}
+
+static bool protoHandleHasDeviceStartAddress(const void* element, const void* value)
+{
+    const SERIALIZER_DEVICETWIN_PROTOHANDLE* protoHandle = (const SERIALIZER_DEVICETWIN_PROTOHANDLE*)element;
+    return protoHandle->deviceAssigned == value;
+}
+
+static void IoTHubDeviceTwin_Destroy_Impl(void* model)
+{
+    /*Codes_SRS_SERIALIZERDEVICETWIN_02_020: [ If model is NULL then IoTHubDeviceTwin_Destroy_Impl shall return. ]*/
+    if (model == NULL)
+    {
+        LogError("invalid argument void* model=%p", model);
+    }
+    else
+    {
+        /*Codes_SRS_SERIALIZERDEVICETWIN_02_015: [ IoTHubDeviceTwin_Destroy_Impl shall locate the saved handle belonging to model. ]*/
+        SERIALIZER_DEVICETWIN_PROTOHANDLE* protoHandle = (SERIALIZER_DEVICETWIN_PROTOHANDLE*)VECTOR_find_if(g_allProtoHandles, protoHandleHasDeviceStartAddress, model);
+        if (protoHandle == NULL)
+        {
+            LogError("failure in VECTOR_find_if [not found]");
+        }
+        else
+        {
+            /*Codes_SRS_SERIALIZERDEVICETWIN_02_016: [ IoTHubDeviceTwin_Destroy_Impl shall set the devicetwin callback to NULL. ]*/
+            switch (protoHandle->iothubClientHandleVariant.iothubClientHandleType)
+            {
+            case IOTHUB_CLIENT_CONVENIENCE_HANDLE_TYPE:
+            {
+                if (IoTHubClient_SetDeviceTwinCallback(protoHandle->iothubClientHandleVariant.iothubClientHandleValue.iothubClientHandle, NULL, NULL) != IOTHUB_CLIENT_OK)
+                {
+                    LogError("failure in IoTHubClient_SetDeviceTwinCallback");
+                }
+                /*Codes_SRS_SERIALIZERDEVICETWIN_02_028: [ IoTHubDeviceTwin_Destroy_Impl shall set the method callback to NULL. ]*/
+                if (IoTHubClient_SetDeviceMethodCallback(protoHandle->iothubClientHandleVariant.iothubClientHandleValue.iothubClientHandle, NULL, NULL) != IOTHUB_CLIENT_OK)
+                {
+                    LogError("failure in IoTHubClient_SetDeviceMethodCallback");
+                }
+                break;
+            }
+            case IOTHUB_CLIENT_LL_HANDLE_TYPE:
+            {
+                if (IoTHubClient_LL_SetDeviceTwinCallback(protoHandle->iothubClientHandleVariant.iothubClientHandleValue.iothubClientLLHandle, NULL, NULL) != IOTHUB_CLIENT_OK)
+                {
+                    LogError("failure in IoTHubClient_LL_SetDeviceTwinCallback");
+                }
+                /*Codes_SRS_SERIALIZERDEVICETWIN_02_028: [ IoTHubDeviceTwin_Destroy_Impl shall set the method callback to NULL. ]*/
+                if (IoTHubClient_LL_SetDeviceMethodCallback(protoHandle->iothubClientHandleVariant.iothubClientHandleValue.iothubClientLLHandle, NULL, NULL) != IOTHUB_CLIENT_OK)
+                {
+                    LogError("failure in IoTHubClient_LL_SetDeviceMethodCallback");
+                }
+                break;
+            }
+            default:
+            {
+                LogError("INTERNAL ERROR");
+            }
+            }/*switch*/
+
+             /*Codes_SRS_SERIALIZERDEVICETWIN_02_017: [ IoTHubDeviceTwin_Destroy_Impl shall call CodeFirst_DestroyDevice. ]*/
+            CodeFirst_DestroyDevice(protoHandle->deviceAssigned);
+
+            /*Codes_SRS_SERIALIZERDEVICETWIN_02_018: [ IoTHubDeviceTwin_Destroy_Impl shall remove the IoTHubClient_Handle and the device handle from the recorded set. ]*/
+            VECTOR_erase(g_allProtoHandles, protoHandle, 1);
+        }
+
+        /*Codes_SRS_SERIALIZERDEVICETWIN_02_019: [ If the recorded set of IoTHubClient handles is zero size, then the set shall be destroyed. ]*/
+        if (VECTOR_size(g_allProtoHandles) == 0) /*lazy init means more work @ destroy time*/
+        {
+            VECTOR_destroy(g_allProtoHandles);
+            g_allProtoHandles = NULL;
+        }
+    }
+}
+
+/*the below function sends the reported state of a model previously created by IoTHubDeviceTwin_Create*/
+/*this function serves both the _LL and the convenience layer because of protohandles*/
+static IOTHUB_CLIENT_RESULT IoTHubDeviceTwin_SendReportedState_Impl(void* model, IOTHUB_CLIENT_REPORTED_STATE_CALLBACK deviceTwinCallback, void* context)
+{
+    unsigned char*buffer;
+    size_t bufferSize;
+
+    IOTHUB_CLIENT_RESULT result;
+
+    if (SERIALIZE_REPORTED_PROPERTIES_FROM_POINTERS(&buffer, &bufferSize, model) != CODEFIRST_OK)
+    {
+        LogError("Failed serializing reported state");
+        result = IOTHUB_CLIENT_ERROR;
+    }
+    else
+    {
+        SERIALIZER_DEVICETWIN_PROTOHANDLE* protoHandle = (SERIALIZER_DEVICETWIN_PROTOHANDLE*)VECTOR_find_if(g_allProtoHandles, protoHandleHasDeviceStartAddress, model);
+        if (protoHandle == NULL)
+        {
+            LogError("failure in VECTOR_find_if [not found]");
+            result = IOTHUB_CLIENT_ERROR;
+        }
+        else
+        {
+            switch (protoHandle->iothubClientHandleVariant.iothubClientHandleType)
+            {
+                case IOTHUB_CLIENT_CONVENIENCE_HANDLE_TYPE:
+                {
+                    if (IoTHubClient_SendReportedState(protoHandle->iothubClientHandleVariant.iothubClientHandleValue.iothubClientHandle, buffer, bufferSize, deviceTwinCallback, context) != IOTHUB_CLIENT_OK)
+                    {
+                        LogError("Failure sending data");
+                        result = IOTHUB_CLIENT_ERROR;
+                    }
+                    else
+                    {
+                        result = IOTHUB_CLIENT_OK;
+                    }
+                    break;
+                }
+                case IOTHUB_CLIENT_LL_HANDLE_TYPE:
+                {
+                    if (IoTHubClient_LL_SendReportedState(protoHandle->iothubClientHandleVariant.iothubClientHandleValue.iothubClientLLHandle, buffer, bufferSize, deviceTwinCallback, context) != IOTHUB_CLIENT_OK)
+                    {
+                        LogError("Failure sending data");
+                        result = IOTHUB_CLIENT_ERROR;
+                    }
+                    else
+                    {
+                        result = IOTHUB_CLIENT_OK;
+                    }
+                    break;
+                }
+                default:
+                {
+                    LogError("INTERNAL ERROR: unexpected value for enum (%d)", (int)protoHandle->iothubClientHandleVariant.iothubClientHandleType);
+                    result = IOTHUB_CLIENT_ERROR;
+                    break;
+                }
+            }
+        }
+        free(buffer);
+    }
+    return result;
+}
+
+#define DECLARE_DEVICETWIN_MODEL(name, ...)    \
+    DECLARE_MODEL(name, __VA_ARGS__)           \
+    static name* MU_C2(IoTHubDeviceTwin_Create, name)(IOTHUB_CLIENT_HANDLE iotHubClientHandle)                                                                                         \
+    {                                                                                                                                                                               \
+        SERIALIZER_DEVICETWIN_PROTOHANDLE protoHandle;                                                                                                                              \
+        protoHandle.iothubClientHandleVariant.iothubClientHandleType = IOTHUB_CLIENT_CONVENIENCE_HANDLE_TYPE;                                                                       \
+        protoHandle.iothubClientHandleVariant.iothubClientHandleValue.iothubClientHandle = iotHubClientHandle;                                                                      \
+        return (name*)IoTHubDeviceTwinCreate_Impl(#name, sizeof(name), &protoHandle);                                                                                               \
+    }                                                                                                                                                                               \
+                                                                                                                                                                                    \
+    static void MU_C2(IoTHubDeviceTwin_Destroy, name) (name* model)                                                                                                                    \
+    {                                                                                                                                                                               \
+        IoTHubDeviceTwin_Destroy_Impl(model);                                                                                                                                       \
+    }                                                                                                                                                                               \
+                                                                                                                                                                                    \
+    static name* MU_C2(IoTHubDeviceTwin_LL_Create, name)(IOTHUB_CLIENT_LL_HANDLE iotHubClientLLHandle)                                                                                 \
+    {                                                                                                                                                                               \
+        SERIALIZER_DEVICETWIN_PROTOHANDLE protoHandle;                                                                                                                              \
+        protoHandle.iothubClientHandleVariant.iothubClientHandleType = IOTHUB_CLIENT_LL_HANDLE_TYPE;                                                                                \
+        protoHandle.iothubClientHandleVariant.iothubClientHandleValue.iothubClientLLHandle = iotHubClientLLHandle;                                                                  \
+        return (name*)IoTHubDeviceTwinCreate_Impl(#name, sizeof(name), &protoHandle);                                                                                               \
+    }                                                                                                                                                                               \
+                                                                                                                                                                                    \
+    static void MU_C2(IoTHubDeviceTwin_LL_Destroy, name) (name* model)                                                                                                                 \
+    {                                                                                                                                                                               \
+        IoTHubDeviceTwin_Destroy_Impl(model);                                                                                                                                       \
+    }                                                                                                                                                                               \
+    static IOTHUB_CLIENT_RESULT MU_C2(IoTHubDeviceTwin_LL_SendReportedState, name) (name* model, IOTHUB_CLIENT_REPORTED_STATE_CALLBACK deviceTwinCallback, void* context)              \
+    {                                                                                                                                                                               \
+        return IoTHubDeviceTwin_SendReportedState_Impl(model, deviceTwinCallback, context);                                                                                         \
+    }                                                                                                                                                                               \
+    static IOTHUB_CLIENT_RESULT MU_C2(IoTHubDeviceTwin_SendReportedState, name) (name* model, IOTHUB_CLIENT_REPORTED_STATE_CALLBACK deviceTwinCallback, void* context)                 \
+    {                                                                                                                                                                               \
+        return IoTHubDeviceTwin_SendReportedState_Impl(model, deviceTwinCallback, context);                                                                                         \
+    }                                                                                                                                                                               \
+
+#endif /*SERIALIZER_DEVICE_TWIN_H*/
+
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/agenttypesystem.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/agenttypesystem.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/agenttypesystem.c	(revision 453)
@@ -0,0 +1,4011 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "azure_c_shared_utility/gballoc.h"
+
+#include "agenttypesystem.h"
+#include <inttypes.h>
+
+#ifdef _MSC_VER
+#pragma warning(disable: 4756) /* Known warning for INFINITY */
+#endif
+
+#include <stddef.h>
+
+#include <float.h>
+#include <math.h>
+#include <limits.h>
+#include <errno.h>
+
+/*if ULLONG_MAX is defined by limits.h for whatever reasons... */
+#ifndef ULLONG_MAX
+#define ULLONG_MAX 18446744073709551615
+#endif
+
+#include "azure_c_shared_utility/crt_abstractions.h"
+
+#include "jsonencoder.h"
+#include "multitree.h"
+
+#include "azure_c_shared_utility/xlogging.h"
+
+#define NaN_STRING "NaN"
+#define MINUSINF_STRING "-INF"
+#define PLUSINF_STRING "INF"
+
+#ifndef _HUGE_ENUF
+#define _HUGE_ENUF  1e+300    /* _HUGE_ENUF*_HUGE_ENUF must overflow */
+#endif /* _HUGE_ENUF */
+
+#ifndef INFINITY
+#define INFINITY   ((float)(_HUGE_ENUF * _HUGE_ENUF))  /* causes warning C4756: overflow in constant arithmetic (by design) */
+#endif /* INFINITY */
+
+#ifndef NAN
+#define NAN        ((float)(INFINITY * 0.0F))
+#endif /* NAN */
+
+#define GUID_STRING_LENGTH 38
+
+// This is an artificial upper limit on floating point string length
+// (e.g. the size of the string when printing %f). It is set to twice the
+// maximum decimal precision plus 2. 1 for the decimal point and 1 for a
+// sign (+/-)
+// Unfortunately it is quite possible to print a float larger than this.
+// An example of this would be printf("%.*f", MAX_FLOATING_POINT_STRING_LENGTH, 1.3);
+// But currently no explicit requests for this exist in the file nor are
+// any expected to reasonably occur when being used (numbers that hit
+// this limit would be experiencing significant precision loss in storage anyway.
+#define MAX_FLOATING_POINT_STRING_LENGTH (DECIMAL_DIG *2 + 2)
+
+// This maximum length is 11 for 32 bit integers (including the sign)
+// optionally increase to 21 if longs are 64 bit
+#define MAX_LONG_STRING_LENGTH ( 11 + (10 * (sizeof(long)/ 8)))
+
+// This is the maximum length for the largest 64 bit number (signed)
+#define MAX_ULONG_LONG_STRING_LENGTH 20
+
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(AGENT_DATA_TYPES_RESULT, AGENT_DATA_TYPES_RESULT_VALUES);
+
+static int ValidateDate(int year, int month, int day);
+
+static int NoCloneFunction(void** destination, const void* source)
+{
+    *destination = (void*)source;
+    return 0;
+}
+
+static void NoFreeFunction(void* value)
+{
+    (void)value;
+}
+
+
+#define IS_DIGIT(a) (('0'<=(a)) &&((a)<='9'))
+#define splitInt(intVal, bytePos)   (char)((intVal >> (bytePos << 3)) & 0xFF)
+#define joinChars(a, b, c, d) (uint32_t)( (uint32_t)a + ((uint32_t)b << 8) + ((uint32_t)c << 16) + ((uint32_t)d << 24))
+
+static char base64char(unsigned char val)
+{
+    char result;
+
+    if (val < 26)
+    {
+        result = 'A' + (char)val;
+    }
+    else if (val < 52)
+    {
+        result = 'a' + ((char)val - 26);
+    }
+    else if (val < 62)
+    {
+        result = '0' + ((char)val - 52);
+    }
+    else if (val == 62)
+    {
+        result = '-';
+    }
+    else
+    {
+        result = '_';
+    }
+
+    return result;
+}
+
+static char base64b16(unsigned char val)
+{
+    const uint32_t base64b16values[4] = {
+        joinChars('A', 'E', 'I', 'M'),
+        joinChars('Q', 'U', 'Y', 'c'),
+        joinChars('g', 'k', 'o', 's'),
+        joinChars('w', '0', '4', '8')
+    };
+    return splitInt(base64b16values[val >> 2], (val & 0x03));
+}
+
+static char base64b8(unsigned char val)
+{
+    const uint32_t base64b8values = joinChars('A', 'Q', 'g', 'w');
+    return splitInt(base64b8values, val);
+};
+
+/*creates an AGENT_DATA_TYPE containing a EDM_BOOLEAN from a int*/
+AGENT_DATA_TYPES_RESULT Create_EDM_BOOLEAN_from_int(AGENT_DATA_TYPE* agentData, int v)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[All the Create_... functions shall check their parameters for validity.When an invalid parameter is detected, a code of AGENT_DATA_TYPES_INVALID_ARG shall be returned]*/
+    if(agentData==NULL)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+    }
+    else
+    {
+        /*Codes_SRS_AGENT_TYPE_SYSTEM_99_031:[ Creates a AGENT_DATA_TYPE representing an EDM_BOOLEAN.]*/
+        agentData->type = EDM_BOOLEAN_TYPE;
+        agentData->value.edmBoolean.value = (v)?(EDM_TRUE):(EDM_FALSE);
+        result = AGENT_DATA_TYPES_OK;
+    }
+    return result;
+}
+
+/*creates an AGENT_DATA_TYPE containing a UINT8*/
+AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_UINT8(AGENT_DATA_TYPE* agentData, uint8_t v)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[ All the Create_... functions shall check their parameters for validity. When an invalid parameter is detected, a code of AGENT_DATA_TYPES_INVALID_ARG shall be returned ].*/
+    if (agentData == NULL)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+    }
+    else
+    {
+        agentData->type = EDM_BYTE_TYPE;
+        agentData->value.edmByte.value = v;
+        result = AGENT_DATA_TYPES_OK;
+    }
+    return result;
+}
+
+/*Codes_SRS_AGENT_TYPE_SYSTEM_99_091:[Creates an AGENT_DATA_TYPE containing an Edm.DateTimeOffset from an EDM_DATE_TIME_OFFSET.]*/
+AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_EDM_DATE_TIME_OFFSET(AGENT_DATA_TYPE* agentData, EDM_DATE_TIME_OFFSET v)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[ All the Create_... functions shall check their parameters for validity. When an invalid parameter is detected, a code of AGENT_DATA_TYPES_INVALID_ARG shall be returned ]*/
+    if (agentData == NULL)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+    }
+    else if (ValidateDate(v.dateTime.tm_year+1900, v.dateTime.tm_mon +1 , v.dateTime.tm_mday) != 0)
+    {
+        /*Codes_SRS_AGENT_TYPE_SYSTEM_99_092:[ The structure shall be validated to be conforming to OData specifications (odata-abnf-construction-rules, 2013), and if found invalid, AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+    }
+    else if (
+        (v.dateTime.tm_hour > 23) ||
+        (v.dateTime.tm_hour < 0) ||
+        (v.dateTime.tm_min > 59) ||
+        (v.dateTime.tm_min < 0) ||
+        (v.dateTime.tm_sec > 59) ||
+        (v.dateTime.tm_sec < 0)
+        )
+    {
+        /*Codes_SRS_AGENT_TYPE_SYSTEM_99_092:[ The structure shall be validated, and if found invalid, AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+    }
+    else if ((v.hasFractionalSecond) && (v.fractionalSecond > 999999999999))
+    {
+        /*Codes_SRS_AGENT_TYPE_SYSTEM_99_092:[ The structure shall be validated to be conforming to OData specifications (odata-abnf-construction-rules, 2013), and if found invalid, AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+    }
+    else if (
+        (v.hasTimeZone) &&
+        (
+            (v.timeZoneHour<-23) ||
+            (v.timeZoneHour>23) ||
+            (v.timeZoneMinute>59)
+        )
+    )
+    {
+        /*Codes_SRS_AGENT_TYPE_SYSTEM_99_092:[ The structure shall be validated to be conforming to OData specifications (odata-abnf-construction-rules, 2013), and if found invalid, AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+    }
+    else
+    {
+        agentData->type = EDM_DATE_TIME_OFFSET_TYPE;
+        agentData->value.edmDateTimeOffset = v;
+        result = AGENT_DATA_TYPES_OK;
+    }
+    return result;
+}
+
+/*Codes_SRS_AGENT_TYPE_SYSTEM_99_094:[ Creates and AGENT_DATA_TYPE containing a EDM_GUID from an EDM_GUID]*/
+AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_EDM_GUID(AGENT_DATA_TYPE* agentData, EDM_GUID v)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[ All the functions shall check their parameters for validity. When an invalid parameter is detected, the value AGENT_DATA_TYPES_INVALID_ARG shall be returned ].*/
+    if (agentData == NULL)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("result = %s ", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+    }
+    else
+    {
+        /*Codes_SRS_AGENT_TYPE_SYSTEM_99_094:[ Creates and AGENT_DATA_TYPE containing a EDM_GUID from an EDM_GUID]*/
+        agentData->type = EDM_GUID_TYPE;
+        memmove(agentData->value.edmGuid.GUID, v.GUID, 16);
+        result = AGENT_DATA_TYPES_OK;
+    }
+    return result;
+}
+
+/*Codes_SRS_AGENT_TYPE_SYSTEM_99_098:[ Creates an AGENT_DATA_TYPE containing a EDM_BINARY from a EDM_BINARY.]*/
+AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_EDM_BINARY(AGENT_DATA_TYPE* agentData, EDM_BINARY v)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[ All the functions shall check their parameters for validity. When an invalid parameter is detected, the value AGENT_DATA_TYPES_INVALID_ARG shall be returned ].*/
+    if (agentData == NULL)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("result = %s", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+    }
+    else
+    {
+        /*Codes_SRS_AGENT_TYPE_SYSTEM_99_098:[ Creates an AGENT_DATA_TYPE containing a EDM_BINARY from a EDM_BINARY.]*/
+        if (v.data == NULL)
+        {
+            if (v.size != 0)
+            {
+                result = AGENT_DATA_TYPES_INVALID_ARG;
+                LogError("result = %s ", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+            }
+            else
+            {
+                agentData->type = EDM_BINARY_TYPE;
+                agentData->value.edmBinary.size = 0;
+                agentData->value.edmBinary.data = NULL;
+                result = AGENT_DATA_TYPES_OK;
+            }
+        }
+        else
+        {
+            if (v.size != 0)
+            {
+                /*make a copy*/
+                if ((agentData->value.edmBinary.data = (unsigned char*)malloc(v.size)) == NULL)
+                {
+                    result = AGENT_DATA_TYPES_ERROR;
+                    LogError("result = %s", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    (void)memcpy(agentData->value.edmBinary.data, v.data, v.size);
+                    agentData->type = EDM_BINARY_TYPE;
+                    agentData->value.edmBinary.size = v.size;
+                    result = AGENT_DATA_TYPES_OK;
+                }
+            }
+            else
+            {
+                result = AGENT_DATA_TYPES_INVALID_ARG;
+                LogError("result = %s", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+            }
+        }
+    }
+    return result;
+}
+
+/*scans sign, if any*/
+/*if no sign, then it will set *sign to = +1*/
+/*if sign, then it will set *sign to = +/-1*/
+static void scanOptionalSign(const char* source, size_t sourceSize, size_t* position, int* sign)
+{
+    if (*position < sourceSize)
+    {
+        if (source[*position] == '-')
+        {
+
+            *sign = -1;
+            (*position)++;
+        }
+        else if (source[*position] == '+')
+        {
+            *sign = +1;
+            (*position)++;
+        }
+        else
+        {
+            *sign = +1;
+        }
+    }
+}
+
+/*scans a minus sign, if any*/
+/*if no sign, then it will set *sign to = +1*/
+/*if sign, then it will set *sign to = +/-1*/
+static void scanOptionalMinusSign(const char* source, size_t sourceSize, size_t* position, int* sign)
+{
+    if (*position < sourceSize)
+    {
+        if (source[*position] == '-')
+        {
+
+            *sign = -1;
+            (*position)++;
+        }
+        else
+        {
+            *sign = +1;
+        }
+    }
+}
+
+/*this function alawys returns 0 if it processed 1 digit*/
+/*return 1 when error (such as wrong parameters)*/
+static int scanMandatoryOneDigit(const char* source, size_t sourceSize, size_t* position)
+{
+    int result;
+    if (*position < sourceSize)
+    {
+        if (IS_DIGIT(source[*position]))
+        {
+            (*position)++;
+            result = 0;
+        }
+        else
+        {
+            result = 1;
+        }
+    }
+    else
+    {
+        result = 1;
+    }
+    return result;
+}
+
+/*scans digits, if any*/
+static void scanOptionalNDigits(const char* source, size_t sourceSize, size_t* position)
+{
+    while (*position < sourceSize)
+    {
+        if (IS_DIGIT(source[*position]))
+        {
+            (*position)++;
+        }
+        else
+        {
+            break;
+        }
+    }
+}
+
+/*from the string pointed to by source, having the size sourceSize, starting at initial position *position*/
+/*this function will attempt to read a decimal number having an optional sign(+/-) followed by precisely N digits */
+/*will return 0 if in the string there was a number and that number has been read in the *value parameter*/
+/*will update position parameter to reflect the first character not belonging to the number*/
+static int scanAndReadNDigitsInt(const char* source, size_t* position, int *value, size_t N)
+{
+    N++;
+    *value = 0;
+    while ((IS_DIGIT(source[*position])) &&
+        (N > 0))
+    {
+        *value *= 10;
+        *value += (source[*position] - '0');
+        (*position)++;
+        N--;
+    }
+
+    return N != 1;
+}
+
+/*this function alawys returns 0 if it found a dot followed by at least digit*/
+/*return 1 when error (such as wrong parameters)*/
+static int scanOptionalDotAndDigits(const char* source, size_t sourceSize, size_t* position)
+{
+    int result = 0;
+    if (*position < sourceSize)
+    {
+        if (source[*position] == '.')
+        {
+            (*position)++;
+            if (scanMandatoryOneDigit(source, sourceSize, position) != 0)
+            {
+                /* not a digit following the dot... */
+                result = 1;
+            }
+            else
+            {
+                scanOptionalNDigits(source, sourceSize, position);
+            }
+        }
+        else
+        {
+            /*not a dot, don't care*/
+        }
+    }
+    return result;
+}
+
+
+static int scanMandatory1CapitalHexDigit(const char* source, uint8_t* value)
+{
+    int result = 0;
+    if (('0' <= source[0]) && (source[0] <= '9'))
+    {
+        *value = (source[0] - '0');
+    }
+    else if (('A' <= source[0]) && (source[0] <= 'F'))
+    {
+        *value = (source[0] - 'A'+10);
+    }
+    else
+    {
+        result = 1;
+    }
+    return result;
+}
+
+/*this function alawys returns 0 if it found 2 hex digits, also updates the *value parameter*/
+/*return 1 when error (such as wrong parameters)*/
+static int scanMandatory2CapitalHexDigits(const char* source, uint8_t* value)
+{
+    int result;
+    uint8_t temp;
+    if (scanMandatory1CapitalHexDigit(source, &temp) == 0)
+    {
+        *value = temp*16;
+        if (scanMandatory1CapitalHexDigit(source + 1, &temp) == 0)
+        {
+            *value += temp;
+            result = 0;
+        }
+        else
+        {
+            result = 1;
+        }
+    }
+    else
+    {
+        result = 2;
+    }
+
+    return result;
+}
+
+static int ValidateDecimal(const char* v, size_t vlen)
+{
+    int result;
+    int sign = 0;
+    size_t validatePosition = 0;
+    scanOptionalSign(v, vlen, &validatePosition, &sign);
+    if (scanMandatoryOneDigit(v, vlen, &validatePosition) != 0)
+    {
+        result = 1;
+    }
+    else
+    {
+        scanOptionalNDigits(v, vlen, &validatePosition);
+        if (scanOptionalDotAndDigits(v, vlen, &validatePosition) != 0)
+        {
+            /*Codes_SRS_AGENT_TYPE_SYSTEM_99_067:[ If the string indicated by the parameter v does not match exactly an ODATA string representation, AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
+            result = 1;
+        }
+        else if (validatePosition != vlen) /*Trailing wrong characters*/
+        {
+            /*Codes_SRS_AGENT_TYPE_SYSTEM_99_067:[ If the string indicated by the parameter v does not match exactly an ODATA string representation, AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
+            result = 1;
+        }
+        else
+        {
+            result = 0;
+        }
+    }
+
+    return result;
+}
+
+/*return 0 if everything went ok*/
+/*takes 1 base64char and returns its value*/
+static int base64toValue(char base64charSource, unsigned char* value)
+{
+    int result;
+    if (('A' <= base64charSource) && (base64charSource <= 'Z'))
+    {
+        *value = base64charSource - 'A';
+        result = 0;
+    }
+    else if (('a' <= base64charSource) && (base64charSource <= 'z'))
+    {
+        *value = ('Z' - 'A') +1+ (base64charSource - 'a');
+        result = 0;
+    }
+    else if (('0' <= base64charSource) && (base64charSource <= '9'))
+    {
+        *value = ('Z' - 'A') +1+('z'-'a')+1 +(base64charSource - '0');
+        result = 0;
+    }
+    else if ('-' == base64charSource)
+    {
+        *value = 62;
+        result = 0;
+    }
+    else if ('_' == base64charSource)
+    {
+        *value = 63;
+        result = 0;
+    }
+    else
+    {
+        result = 1;
+    }
+    return result;
+}
+
+/*returns 0 if everything went ok*/
+/*scans 4 base64 characters and returns 3 usual bytes*/
+static int scan4base64char(const char* source, size_t sourceSize, unsigned char *destination0, unsigned char* destination1, unsigned char* destination2)
+{
+    int result;
+    if (sourceSize < 4)
+    {
+        result = 1;
+    }
+    else
+    {
+        unsigned char b0, b1, b2, b3;
+        if (
+            (base64toValue(source[0], &b0) == 0) &&
+            (base64toValue(source[1], &b1) == 0) &&
+            (base64toValue(source[2], &b2) == 0) &&
+            (base64toValue(source[3], &b3) == 0)
+            )
+        {
+            *destination0 = (b0 << 2) | ((b1 & 0x30) >> 4);
+            *destination1 = ((b1 & 0x0F)<<4) | ((b2 & 0x3C) >>2 );
+            *destination2 = ((b2 & 0x03) << 6) | (b3);
+            result = 0;
+        }
+        else
+        {
+            result = 2;
+        }
+    }
+    return result;
+}
+
+/*return 0 if the character is one of ( 'A' / 'E' / 'I' / 'M' / 'Q' / 'U' / 'Y' / 'c' / 'g' / 'k' / 'o' / 's' / 'w' / '0' / '4' / '8' )*/
+static int base64b16toValue(unsigned char source, unsigned char* destination)
+{
+    unsigned char i;
+    for (i = 0; i <= 15; i++)
+    {
+        if (base64b16(i) == source)
+        {
+            *destination = i;
+            return 0;
+        }
+    }
+    return 1;
+}
+
+/*return 0 if the character is one of ( 'A' / 'Q' / 'g' / 'w' )*/
+static int base64b8toValue(unsigned char source, unsigned char* destination)
+{
+    unsigned char i;
+    for (i = 0; i <= 3; i++)
+    {
+        if (base64b8(i) == source)
+        {
+            *destination = i;
+            return 0;
+        }
+    }
+    return 1;
+}
+
+
+/*returns 0 if everything went ok*/
+/*scans 2 base64 characters + 1 special + 1 optional = and returns 2 usual bytes*/
+int scanbase64b16(const char* source, size_t sourceSize, size_t *consumed, unsigned char* destination0, unsigned char* destination1)
+{
+    int result;
+    if (sourceSize < 3)
+    {
+        result = 1;
+    }
+    else
+    {
+        unsigned char c0, c1, c2;
+        *consumed = 0;
+        if (
+            (base64toValue(source[0], &c0) == 0) &&
+            (base64toValue(source[1], &c1) == 0) &&
+            (base64b16toValue(source[2], &c2) == 0)
+            )
+        {
+            *consumed = 3 + ((sourceSize>=3)&&(source[3] == '=')); /*== produce 1 or 0 ( in C )*/
+            *destination0 = (c0 << 2) | ((c1 & 0x30) >> 4);
+            *destination1 = ((c1 &0x0F) <<4) | c2;
+            result = 0;
+        }
+        else
+        {
+            result = 2;
+        }
+    }
+    return result;
+}
+
+/*return 0 if everything is ok*/
+/*Reads base64b8    = base64char ( 'A' / 'Q' / 'g' / 'w' ) [ "==" ]*/
+int scanbase64b8(const char* source, size_t sourceSize, size_t *consumed, unsigned char* destination0)
+{
+    int result;
+    if (sourceSize < 2)
+    {
+        result = 1;
+    }
+    else
+    {
+        unsigned char c0, c1;
+        if (
+            (base64toValue(source[0], &c0) == 0) &&
+            (base64b8toValue(source[1], &c1) == 0)
+            )
+        {
+            *consumed = 2 + (((sourceSize>=4) && (source[2] == '=') && (source[3] == '='))?2:0); /*== produce 1 or 0 ( in C )*/
+            *destination0 = (c0 << 2) | (c1 & 3);
+            result = 0;
+        }
+        else
+        {
+            result = 2;
+        }
+    }
+    return result;
+}
+
+/*Codes_SRS_AGENT_TYPE_SYSTEM_99_039:[ Creates an AGENT_DATA_TYPE containing an EDM_DECIMAL from a null-terminated string.]*/
+AGENT_DATA_TYPES_RESULT Create_EDM_DECIMAL_from_charz(AGENT_DATA_TYPE* agentData, const char* v)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[ All the Create_... functions shall check their parameters for validity. When an invalid parameter is detected, a code of AGENT_DATA_TYPES_INVALID_ARG shall be returned ].*/
+    if (agentData == NULL)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+    }
+    else if (v == NULL)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+    }
+    else
+    {
+        size_t vlen = strlen(v);
+        /*validate that v has the form [SIGN] 1*DIGIT ["." 1*DIGIT]*/
+        if (vlen == 0)
+        {
+            /*Codes_SRS_AGENT_TYPE_SYSTEM_99_067:[ If the string indicated by the parameter v does not match exactly an ODATA string representation, AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
+            result = AGENT_DATA_TYPES_INVALID_ARG;
+            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+        }
+        else
+        {
+            if (ValidateDecimal(v, vlen) != 0)
+            {
+                /*Codes_SRS_AGENT_TYPE_SYSTEM_99_067:[ If the string indicated by the parameter v does not match exactly an ODATA string representation, AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
+                result = AGENT_DATA_TYPES_INVALID_ARG;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+            }
+            else if ((agentData->value.edmDecimal.value = STRING_construct(v)) == NULL)
+            {
+                result = AGENT_DATA_TYPES_ERROR;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+            }
+            else
+            {
+                agentData->type = EDM_DECIMAL_TYPE;
+                result = AGENT_DATA_TYPES_OK;
+            }
+        }
+    }
+    return result;
+}
+
+/*create an AGENT_DATA_TYPE containing an EDM_DOUBLE from a double*/
+AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_DOUBLE(AGENT_DATA_TYPE* agentData, double v)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[All the Create_... functions shall check their parameters for validity.When an invalid parameter is detected, a code of AGENT_DATA_TYPES_INVALID_ARG shall be returned]*/
+    if(agentData==NULL)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+    }
+    else
+    {
+        /*Codes_SRS_AGENT_TYPE_SYSTEM_99_041:[Creates an AGENT_DATA_TYPE containing an EDM_DOUBLE from double]*/
+        /*Codes_SRS_AGENT_TYPE_SYSTEM_99_042:[Values of NaN, -INF, +INF are accepted]*/
+        agentData->type = EDM_DOUBLE_TYPE;
+        agentData->value.edmDouble.value = v;
+        result = AGENT_DATA_TYPES_OK;
+    }
+    return result;
+}
+
+/*create an AGENT_DATA_TYPE from INT16_T*/
+/*Codes_SRS_AGENT_TYPE_SYSTEM_99_043:[ Creates an AGENT_DATA_TYPE containing an EDM_INT16 from int16_t]*/
+AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_SINT16(AGENT_DATA_TYPE* agentData, int16_t v)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[ All the Create_... functions shall check their parameters for validity. When an invalid parameter is detected, a code of AGENT_DATA_TYPES_INVALID_ARG shall be returned ].*/
+    if (agentData == NULL)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+    }
+    else
+    {
+        agentData->type = EDM_INT16_TYPE;
+        agentData->value.edmInt16.value = v;
+        result = AGENT_DATA_TYPES_OK;
+    }
+    return result;
+}
+
+/*create an AGENT_DATA_TYPE from INT32_T*/
+AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_SINT32(AGENT_DATA_TYPE* agentData, int32_t v)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[ All the Create_... functions shall check their parameters for validity. When an invalid parameter is detected, a code of AGENT_DATA_TYPES_INVALID_ARG shall be returned ].*/
+    if (agentData == NULL)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+    }
+    else
+    {
+        agentData->type = EDM_INT32_TYPE;
+        agentData->value.edmInt32.value = v;
+        result = AGENT_DATA_TYPES_OK;
+    }
+    return result;
+}
+
+/*create an AGENT_DATA_TYPE from INT64_T*/
+/*Codes_SRS_AGENT_TYPE_SYSTEM_99_045:[ Creates an AGENT_DATA_TYPE containing an EDM_INT64 from int64_t]*/
+AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_SINT64(AGENT_DATA_TYPE* agentData, int64_t v)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[ All the Create_... functions shall check their parameters for validity. When an invalid parameter is detected, a code of AGENT_DATA_TYPES_INVALID_ARG shall be returned ].*/
+    if (agentData == NULL)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+
+    }
+    else
+    {
+        agentData->type = EDM_INT64_TYPE;
+        agentData->value.edmInt64.value = v;
+        result = AGENT_DATA_TYPES_OK;
+    }
+    return result;
+}
+
+/*create an AGENT_DATA_TYPE from int8_t*/
+AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_SINT8(AGENT_DATA_TYPE* agentData, int8_t v)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[ All the Create_... functions shall check their parameters for validity. When an invalid parameter is detected, a code of AGENT_DATA_TYPES_INVALID_ARG shall be returned ].*/
+    if (agentData == NULL)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+
+    }
+    else
+    {
+        agentData->type = EDM_SBYTE_TYPE;
+        agentData->value.edmSbyte.value = v;
+        result = AGENT_DATA_TYPES_OK;
+    }
+    return result;
+}
+
+static int ValidateDate(int year, int month, int day)
+{
+    int result;
+
+    if ((year <= -10000) || (year >= 10000))
+    {
+        result = 1;
+    }
+    else
+    {
+        /*Codes_SRS_AGENT_TYPE_SYSTEM_99_070:[ If year-month-date does not indicate a valid day (for example 31 Feb 2013), then AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
+        if (day <= 0)
+        {
+            result = 1;
+        }
+        else
+        {
+            /*the following data will be validated...*/
+            /*leap years are those that can be divided by 4. But if the year can be divided by 100, it is not leap. But if they year can be divided by 400 it is leap*/
+            if (
+                (month == 1) || /*these months have always 31 days*/
+                (month == 3) ||
+                (month == 5) ||
+                (month == 7) ||
+                (month == 8) ||
+                (month == 10) ||
+                (month == 12)
+                )
+            {
+                if (day <= 31)
+                {
+                    result = 0;
+                }
+                else
+                {
+                    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_070:[If year - month - date does not indicate a valid day(for example 31 Feb 2013), then AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
+                    result = 1;
+                }
+            }
+            else if (
+                (month == 4) ||
+                (month == 6) ||
+                (month == 9) ||
+                (month == 11)
+                )
+            {
+                if (day <= 30)
+                {
+                    result = 0;
+                }
+                else
+                {
+                    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_070:[If year - month - date does not indicate a valid day(for example 31 Feb 2013), then AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
+                    result = -1;
+                }
+            }
+            else if (month == 2)/*february*/
+            {
+                if ((year % 400) == 0)
+                {
+                    /*these are leap years, suchs as 2000*/
+                    if (day <= 29)
+                    {
+                        result = 0;
+                    }
+                    else
+                    {
+                        /*Codes_SRS_AGENT_TYPE_SYSTEM_99_070:[If year - month - date does not indicate a valid day(for example 31 Feb 2013), then AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
+                        result = 1;
+                    }
+                }
+                else if ((year % 100) == 0)
+                {
+                    /*non-leap year, such as 1900*/
+                    if (day <= 28)
+                    {
+                        result = 0;
+                    }
+                    else
+                    {
+                        /*Codes_SRS_AGENT_TYPE_SYSTEM_99_070:[If year - month - date does not indicate a valid day(for example 31 Feb 2013), then AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
+                        result = 1;
+                    }
+                }
+                else if ((year % 4) == 0)
+                {
+                    /*these are leap years, such as 2104*/
+                    if (day <= 29)
+                    {
+                        result = 0;
+                    }
+                    else
+                    {
+                        /*Codes_SRS_AGENT_TYPE_SYSTEM_99_070:[If year - month - date does not indicate a valid day(for example 31 Feb 2013), then AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
+                        result = 1;
+                    }
+                }
+                else
+                {
+                    /*certainly not a leap year*/
+                    if (day <= 28)
+                    {
+                        result = 0;
+                    }
+                    else
+                    {
+                        /*Codes_SRS_AGENT_TYPE_SYSTEM_99_070:[If year - month - date does not indicate a valid day(for example 31 Feb 2013), then AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
+                        result = 1;
+                    }
+                }
+            }
+            else
+            {
+                /*Codes_SRS_AGENT_TYPE_SYSTEM_99_070:[If year - month - date does not indicate a valid day(for example 31 Feb 2013), then AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
+                result = 1;
+            }
+        }
+    }
+
+    return result;
+}
+
+/*Codes_SRS_AGENT_TYPE_SYSTEM_99_069:[ Creates an AGENT_DATA_TYPE containing an EDM_DATE from a year, a month and a day of the month.]*/
+AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_date(AGENT_DATA_TYPE* agentData, int16_t year, uint8_t month, uint8_t day)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[ All the Create_... functions shall check their parameters for validity. When an invalid parameter is detected, a code of AGENT_DATA_TYPES_INVALID_ARG shall be returned ].*/
+    if (agentData == NULL)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+    }
+    /*ODATA-ABNF: year  = [ "-" ] ( "0" 3DIGIT / oneToNine 3*DIGIT )*/
+    else if (ValidateDate(year, month, day) != 0)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+    }
+    else
+    {
+        /*Codes_SRS_AGENT_TYPE_SYSTEM_99_069:[ Creates an AGENT_DATA_TYPE containing an EDM_DATE from a year, a month and a day of the month.]*/
+        agentData->type = EDM_DATE_TYPE;
+        agentData->value.edmDate.year = year;
+        agentData->value.edmDate.month = month;
+        agentData->value.edmDate.day = day;
+        result = AGENT_DATA_TYPES_OK;
+    }
+
+    return result;
+}
+
+
+/*create an AGENT_DATA_TYPE from SINGLE*/
+AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_FLOAT(AGENT_DATA_TYPE* agentData, float v)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[All the Create_... functions shall check their parameters for validity.When an invalid parameter is detected, a code of AGENT_DATA_TYPES_INVALID_ARG shall be returned]*/
+    if(agentData==NULL)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+    }
+    else
+    {
+        agentData->type = EDM_SINGLE_TYPE;
+        agentData->value.edmSingle.value = v;
+        result = AGENT_DATA_TYPES_OK;
+    }
+    return result;
+}
+
+const char hexToASCII[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+/*create an AGENT_DATA_TYPE from ANSI zero terminated string*/
+AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_charz(AGENT_DATA_TYPE* agentData, const char* v)
+{
+    AGENT_DATA_TYPES_RESULT result = AGENT_DATA_TYPES_OK;
+    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[ All the Create_... functions shall check their parameters for validity. When an invalid parameter is detected, a code of AGENT_DATA_TYPES_INVALID_ARG shall be returned ].*/
+    if (agentData == NULL)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+    }
+    else if (v == NULL)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+    }
+    else
+    {
+        /*Codes_SRS_AGENT_TYPE_SYSTEM_99_049:[ Creates an AGENT_DATA_TYPE containing an EDM_STRING from an ASCII zero terminated string.]*/
+        agentData->type = EDM_STRING_TYPE;
+        if (mallocAndStrcpy_s(&agentData->value.edmString.chars, v) != 0)
+        {
+            result = AGENT_DATA_TYPES_ERROR;
+            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+        }
+        else
+        {
+            agentData->value.edmString.length = strlen(agentData->value.edmString.chars);
+            result = AGENT_DATA_TYPES_OK;
+        }
+    }
+    return result;
+}
+
+/*create an AGENT_DATA_TYPE from ANSI zero terminated string (without quotes) */
+AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_charz_no_quotes(AGENT_DATA_TYPE* agentData, const char* v)
+{
+    AGENT_DATA_TYPES_RESULT result = AGENT_DATA_TYPES_OK;
+    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[ All the Create_... functions shall check their parameters for validity. When an invalid parameter is detected, a code of AGENT_DATA_TYPES_INVALID_ARG shall be returned ].*/
+    if (agentData == NULL)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+    }
+    else if (v == NULL)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+    }
+    else
+    {
+        /* Codes_SRS_AGENT_TYPE_SYSTEM_01_001: [Creates an AGENT_DATA_TYPE containing an EDM_STRING from an ASCII zero terminated string.] */
+        agentData->type = EDM_STRING_NO_QUOTES_TYPE;
+        if (mallocAndStrcpy_s(&agentData->value.edmStringNoQuotes.chars, v) != 0)
+        {
+            result = AGENT_DATA_TYPES_ERROR;
+            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+        }
+        else
+        {
+            agentData->value.edmStringNoQuotes.length = strlen(agentData->value.edmStringNoQuotes.chars);
+            result = AGENT_DATA_TYPES_OK;
+        }
+    }
+    return result;
+}
+
+void Destroy_AGENT_DATA_TYPE(AGENT_DATA_TYPE* agentData)
+{
+    if(agentData==NULL)
+    {
+        LogError("agentData was NULL.");
+    }
+    else
+    {
+        switch(agentData->type)
+        {
+            default:
+            {
+                LogError("invalid agentData");
+                break;
+            }
+            case(EDM_NO_TYPE):
+            {
+                LogError("invalid agentData");
+                break;
+            }
+            case(EDM_BINARY_TYPE):
+            {
+                /*destroying means maybe deallocating some memory*/
+                free(agentData->value.edmBinary.data); /* If ptr is a null pointer, no action occurs*/
+                agentData->value.edmBinary.data = NULL;
+                break;
+            }
+            case(EDM_BOOLEAN_TYPE):
+            {
+                /*nothing to do*/
+                break;
+            }
+            case(EDM_BYTE_TYPE):
+            {
+                /*nothing to do*/
+                break;
+            }
+            case(EDM_DATE_TYPE):
+            {
+                /*nothing to do*/
+                break;
+            }
+            case(EDM_DATE_TIME_OFFSET_TYPE):
+            {
+                /*nothing to do*/
+                break;
+            }
+            case(EDM_DECIMAL_TYPE):
+            {
+                STRING_delete(agentData->value.edmDecimal.value);
+                agentData->value.edmDecimal.value = NULL;
+                break;
+            }
+            case(EDM_DURATION_TYPE):
+            {
+                LogError("EDM_DURATION_TYPE not implemented");
+                break;
+            }
+            case(EDM_GUID_TYPE):
+            {
+                /*nothing to do*/
+                break;
+            }
+            case(EDM_INT16_TYPE):
+            {
+                /*nothing to do*/
+                break;
+            }
+            case(EDM_INT32_TYPE):
+            {
+                /*nothing to do*/
+                break;
+            }
+            case(EDM_INT64_TYPE):
+            {
+                /*nothing to do*/
+                break;
+            }
+            case(EDM_SBYTE_TYPE):
+            {
+                /*nothing to do*/
+                break;
+            }
+            case(EDM_STREAM):
+            {
+                LogError("EDM_STREAM not implemented");
+                break;
+            }
+            case(EDM_STRING_TYPE):
+            {
+                if (agentData->value.edmString.chars != NULL)
+                {
+                    free(agentData->value.edmString.chars);
+                    agentData->value.edmString.chars = NULL;
+                }
+                break;
+            }
+            case(EDM_STRING_NO_QUOTES_TYPE) :
+            {
+                if (agentData->value.edmStringNoQuotes.chars != NULL)
+                {
+                    free(agentData->value.edmStringNoQuotes.chars);
+                    agentData->value.edmStringNoQuotes.chars = NULL;
+                }
+                break;
+            }
+            case(EDM_TIME_OF_DAY_TYPE) :
+            {
+                LogError("EDM_TIME_OF_DAY_TYPE not implemented");
+                break;
+            }
+            case(EDM_GEOGRAPHY_TYPE):
+            {
+                LogError("EDM_GEOGRAPHY_TYPE not implemented");
+                break;
+            }
+            case(EDM_GEOGRAPHY_POINT_TYPE):
+            {
+                LogError("EDM_GEOGRAPHY_POINT_TYPE not implemented");
+                break;
+            }
+            case(EDM_GEOGRAPHY_LINE_STRING_TYPE):
+            {
+                LogError("EDM_GEOGRAPHY_LINE_STRING_TYPE not implemented");
+                break;
+            }
+            case(EDM_GEOGRAPHY_POLYGON_TYPE):
+            {
+                LogError("EDM_GEOGRAPHY_POLYGON_TYPE not implemented");
+                break;
+            }
+            case(EDM_GEOGRAPHY_MULTI_POINT_TYPE):
+            {
+                LogError("EDM_GEOGRAPHY_MULTI_POINT_TYPE not implemented");
+                break;
+            }
+            case(EDM_GEOGRAPHY_MULTI_LINE_STRING_TYPE):
+            {
+                LogError("EDM_GEOGRAPHY_MULTI_LINE_STRING_TYPE not implemented");
+                break;
+            }
+            case(EDM_GEOGRAPHY_MULTI_POLYGON_TYPE):
+            {
+                LogError("EDM_GEOGRAPHY_MULTI_POLYGON_TYPE");
+                break;
+            }
+            case(EDM_GEOGRAPHY_COLLECTION_TYPE):
+            {
+                LogError("EDM_GEOGRAPHY_COLLECTION_TYPE not implemented");
+                break;
+            }
+            case(EDM_GEOMETRY_TYPE):
+            {
+                LogError("EDM_GEOMETRY_TYPE not implemented");
+                break;
+            }
+            case(EDM_GEOMETRY_POINT_TYPE):
+            {
+                LogError("EDM_GEOMETRY_POINT_TYPE not implemented");
+                break;
+            }
+            case(EDM_GEOMETRY_LINE_STRING_TYPE):
+            {
+                LogError("EDM_GEOMETRY_LINE_STRING_TYPE not implemented");
+                break;
+            }
+            case(EDM_GEOMETRY_POLYGON_TYPE):
+            {
+                LogError("EDM_GEOMETRY_POLYGON_TYPE not implemented");
+                break;
+            }
+            case(EDM_GEOMETRY_MULTI_POINT_TYPE):
+            {
+                LogError("EDM_GEOMETRY_MULTI_POINT_TYPE not implemented");
+                break;
+            }
+            case(EDM_GEOMETRY_MULTI_LINE_STRING_TYPE):
+            {
+                LogError("EDM_GEOMETRY_MULTI_LINE_STRING_TYPE not implemented");
+                break;
+            }
+            case(EDM_GEOMETRY_MULTI_POLYGON_TYPE):
+            {
+                LogError("EDM_GEOMETRY_MULTI_POLYGON_TYPE not implemented");
+                break;
+            }
+            case(EDM_GEOMETRY_COLLECTION_TYPE):
+            {
+                LogError("EDM_GEOMETRY_COLLECTION_TYPE not implemented");
+                break;
+            }
+            case(EDM_SINGLE_TYPE):
+            {
+                break;
+            }
+            case(EDM_DOUBLE_TYPE):
+            {
+                break;
+            }
+            case (EDM_COMPLEX_TYPE_TYPE):
+            {
+                /*Codes_SRS_AGENT_TYPE_SYSTEM_99_050:[Destroy_AGENT_DATA_TYPE shall deallocate all allocated resources used to represent the type.]*/
+                size_t i;
+                for (i = 0; i < agentData->value.edmComplexType.nMembers; i++)
+                {
+                    free((void*)(agentData->value.edmComplexType.fields[i].fieldName));
+                    agentData->value.edmComplexType.fields[i].fieldName = NULL;
+                    Destroy_AGENT_DATA_TYPE(agentData->value.edmComplexType.fields[i].value);
+                    free(agentData->value.edmComplexType.fields[i].value);
+                    agentData->value.edmComplexType.fields[i].value = NULL;
+                }
+                free(agentData->value.edmComplexType.fields);
+                break;
+            }
+        }
+        agentData->type = EDM_NO_TYPE; /*mark as detroyed*/
+    }
+}
+
+static char hexDigitToChar(uint8_t hexDigit)
+{
+    if (hexDigit < 10) return '0' + hexDigit;
+    else return ('A' - 10) + hexDigit;
+}
+
+AGENT_DATA_TYPES_RESULT AgentDataTypes_ToString(STRING_HANDLE destination, const AGENT_DATA_TYPE* value)
+{
+    AGENT_DATA_TYPES_RESULT result;
+
+    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_015:[If destination parameter is NULL, AgentDataTypes_ToString shall return AGENT_DATA_TYPES_INVALID_ARG.]*/
+    if(destination == NULL)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+    }
+    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_053:[ If value is NULL or has been destroyed or otherwise doesn't contain valid data, AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
+    else if (value == NULL)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+    }
+    else
+    {
+        switch(value->type)
+        {
+            default:
+            {
+                result = AGENT_DATA_TYPES_INVALID_ARG;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                break;
+            }
+        case(EDM_NULL_TYPE) :
+            {
+                /*SRS_AGENT_TYPE_SYSTEM_99_101:[ EDM_NULL_TYPE shall return the unquoted string null.]*/
+                if (STRING_concat(destination, "null") != 0)
+                {
+                    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_016:[ When the value cannot be converted to a string AgentDataTypes_ToString shall return AGENT_DATA_TYPES_ERROR.]*/
+                    result = AGENT_DATA_TYPES_ERROR;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_014:[ All functions shall return AGENT_DATA_TYPES_OK when the processing is successful.]*/
+                    result = AGENT_DATA_TYPES_OK;
+                }
+                break;
+            }
+        case(EDM_BOOLEAN_TYPE) :
+            {
+                /*Codes_SRS_AGENT_TYPE_SYSTEM_99_017:[EDM_BOOLEAN:as in(odata - abnf - construction - rules, 2013), booleanValue = "true" / "false"]*/
+                if (value->value.edmBoolean.value == EDM_TRUE)
+                {
+                    /*SRS_AGENT_TYPE_SYSTEM_99_030:[If v is different than 0 then the AGENT_DATA_TYPE shall have the value "true".]*/
+                    if (STRING_concat(destination, "true") != 0)
+                    {
+                        /*Codes_SRS_AGENT_TYPE_SYSTEM_99_016:[ When the value cannot be converted to a string AgentDataTypes_ToString shall return AGENT_DATA_TYPES_ERROR.]*/
+                        result = AGENT_DATA_TYPES_ERROR;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                    }
+                    else
+                    {
+                        /*Codes_SRS_AGENT_TYPE_SYSTEM_99_014:[ All functions shall return AGENT_DATA_TYPES_OK when the processing is successful.]*/
+                        result = AGENT_DATA_TYPES_OK;
+                    }
+                }
+                /*Codes_SRS_AGENT_TYPE_SYSTEM_99_017:[EDM_BOOLEAN:as in(odata - abnf - construction - rules, 2013), booleanValue = "true" / "false"]*/
+                else if (value->value.edmBoolean.value == EDM_FALSE)
+                {
+                    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_029:[ If v 0 then the AGENT_DATA_TYPE shall have the value "false" Boolean.]*/
+                    if (STRING_concat(destination, "false") != 0)
+                    {
+                        /*Codes_SRS_AGENT_TYPE_SYSTEM_99_016:[ When the value cannot be converted to a string AgentDataTypes_ToString shall return AGENT_DATA_TYPES_ERROR.]*/
+                        result = AGENT_DATA_TYPES_ERROR;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                    }
+                    else
+                    {
+                        /*Codes_SRS_AGENT_TYPE_SYSTEM_99_014:[ All functions shall return AGENT_DATA_TYPES_OK when the processing is successful.]*/
+                        result = AGENT_DATA_TYPES_OK;
+                    }
+                }
+                else
+                {
+                    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_053:[ If value contains invalid data, AgentDataTypes_ToString shall return AGENT_DATA_TYPES_INVALID_ARG.]*/
+                    result = AGENT_DATA_TYPES_INVALID_ARG;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+
+                break;
+            }
+            case(EDM_BYTE_TYPE) :
+            {
+                char tempbuffer2[4]; /*because bytes can at most be 255 and that is 3 characters + 1 for '\0'*/
+                size_t pos = 0;
+                if (value->value.edmByte.value >= 100) tempbuffer2[pos++] = '0' + (value->value.edmByte.value / 100);
+                if (value->value.edmByte.value >= 10) tempbuffer2[pos++] = '0' + (value->value.edmByte.value % 100) / 10;
+                tempbuffer2[pos++] = '0' + (value->value.edmByte.value % 10);
+                tempbuffer2[pos++] = '\0';
+
+                if (STRING_concat(destination, tempbuffer2) != 0)
+                {
+                    result = AGENT_DATA_TYPES_ERROR;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    result = AGENT_DATA_TYPES_OK;
+                }
+                break;
+            }
+            case(EDM_DATE_TYPE) :
+            {
+                size_t pos = 0;
+                char tempBuffer2[1 + 5 + 1 + 2 + 1 + 2 + 1+1];
+                int16_t year = value->value.edmDate.year;
+                tempBuffer2[pos++] = '\"';
+                /*Codes_SRS_AGENT_TYPE_SYSTEM_99_068:[ EDM_DATE: dateValue = year "-" month "-" day.]*/
+                if (year < 0)
+                {
+                    tempBuffer2[pos++] = '-';
+                    year = -year;
+                }
+
+                tempBuffer2[pos++] = '0' + (char)(year / 1000);
+                tempBuffer2[pos++] = '0' + (char)((year % 1000) / 100);
+                tempBuffer2[pos++] = '0' + (char)((year % 100) / 10);
+                tempBuffer2[pos++] = '0' + (char)(year % 10);
+                tempBuffer2[pos++] = '-';
+                tempBuffer2[pos++] = '0' + value->value.edmDate.month / 10;
+                tempBuffer2[pos++] = '0' + value->value.edmDate.month % 10;
+                tempBuffer2[pos++] = '-';
+                tempBuffer2[pos++] = '0' + value->value.edmDate.day / 10;
+                tempBuffer2[pos++] = '0' + value->value.edmDate.day % 10;
+                tempBuffer2[pos++] = '\"';
+                tempBuffer2[pos++] = '\0';
+
+                if (STRING_concat(destination, tempBuffer2) != 0)
+                {
+                    result = AGENT_DATA_TYPES_ERROR;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    result = AGENT_DATA_TYPES_OK;
+                }
+                break;
+            }
+            case (EDM_DATE_TIME_OFFSET_TYPE):
+            {
+                /*Codes_SRS_AGENT_TYPE_SYSTEM_99_019:[ EDM_DATETIMEOFFSET: dateTimeOffsetValue = year "-" month "-" day "T" hour ":" minute [ ":" second [ "." fractionalSeconds ] ] ( "Z" / sign hour ":" minute )]*/
+                /*from ABNF seems like these numbers HAVE to be padded with zeroes*/
+                if (value->value.edmDateTimeOffset.hasTimeZone)
+                {
+                    if (value->value.edmDateTimeOffset.hasFractionalSecond)
+                    {
+                        size_t tempBufferSize = 1 + // \"
+                            MAX_LONG_STRING_LENGTH + // %.4d
+                            1 + // -
+                            MAX_LONG_STRING_LENGTH + // %.2d
+                            1 + // -
+                            MAX_LONG_STRING_LENGTH + // %.2d
+                            1 + // T
+                            MAX_LONG_STRING_LENGTH + // %.2d
+                            1 + // :
+                            MAX_LONG_STRING_LENGTH + // %.2d
+                            1 + // :
+                            MAX_LONG_STRING_LENGTH + // %.2d
+                            1 + // .
+                            MAX_ULONG_LONG_STRING_LENGTH + // %.12llu
+                            1 + MAX_LONG_STRING_LENGTH + // %+.2d
+                            1 + // :
+                            MAX_LONG_STRING_LENGTH + // %.2d
+                            1 + //\"
+                            1;  // " (terminating NULL);
+
+                        char* tempBuffer = (char*)malloc(tempBufferSize);
+                        if (tempBuffer == NULL)
+                        {
+                            result = AGENT_DATA_TYPES_ERROR;
+                            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                        }
+                        else
+                        {
+                            if (sprintf_s(tempBuffer, tempBufferSize, "\"%.4d-%.2d-%.2dT%.2d:%.2d:%.2d.%.12llu%+.2d:%.2d\"", /*+ in printf forces the sign to appear*/
+                                value->value.edmDateTimeOffset.dateTime.tm_year+1900,
+                                value->value.edmDateTimeOffset.dateTime.tm_mon+1,
+                                value->value.edmDateTimeOffset.dateTime.tm_mday,
+                                value->value.edmDateTimeOffset.dateTime.tm_hour,
+                                value->value.edmDateTimeOffset.dateTime.tm_min,
+                                value->value.edmDateTimeOffset.dateTime.tm_sec,
+                                value->value.edmDateTimeOffset.fractionalSecond,
+                                value->value.edmDateTimeOffset.timeZoneHour,
+                                value->value.edmDateTimeOffset.timeZoneMinute) < 0)
+                            {
+                                result = AGENT_DATA_TYPES_ERROR;
+                                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                            }
+                            else if (STRING_concat(destination, tempBuffer) != 0)
+                            {
+                                result = AGENT_DATA_TYPES_ERROR;
+                                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                            }
+                            else
+                            {
+                                result = AGENT_DATA_TYPES_OK;
+                            }
+
+                            // Clean up temp buffer if allocated
+                            free(tempBuffer);
+                        }
+                    }
+                    else
+                    {
+                        size_t tempBufferSize = 1 + // \"
+                            MAX_LONG_STRING_LENGTH + // %.4d
+                            1 + // -
+                            MAX_LONG_STRING_LENGTH + // %.2d
+                            1 + // -
+                            MAX_LONG_STRING_LENGTH + // %.2d
+                            1 + // T
+                            MAX_LONG_STRING_LENGTH + // %.2d
+                            1 + // :
+                            MAX_LONG_STRING_LENGTH + // %.2d
+                            1 + // :
+                            MAX_LONG_STRING_LENGTH + // %.2d
+                            1 + MAX_LONG_STRING_LENGTH + // %+.2d
+                            1 + // :
+                            MAX_LONG_STRING_LENGTH + // %.2d
+                            1 + // \"
+                            1; // " terminating NULL
+                        char* tempBuffer = (char*)malloc(tempBufferSize);
+
+                        if (tempBuffer == NULL)
+                        {
+                            result = AGENT_DATA_TYPES_ERROR;
+                            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                        }
+                        else
+                        {
+                            if (sprintf_s(tempBuffer, tempBufferSize, "\"%.4d-%.2d-%.2dT%.2d:%.2d:%.2d%+.2d:%.2d\"", /*+ in printf forces the sign to appear*/
+                                value->value.edmDateTimeOffset.dateTime.tm_year + 1900,
+                                value->value.edmDateTimeOffset.dateTime.tm_mon+1,
+                                value->value.edmDateTimeOffset.dateTime.tm_mday,
+                                value->value.edmDateTimeOffset.dateTime.tm_hour,
+                                value->value.edmDateTimeOffset.dateTime.tm_min,
+                                value->value.edmDateTimeOffset.dateTime.tm_sec,
+                                value->value.edmDateTimeOffset.timeZoneHour,
+                                value->value.edmDateTimeOffset.timeZoneMinute) < 0)
+                            {
+                                result = AGENT_DATA_TYPES_ERROR;
+                                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                            }
+                            else if (STRING_concat(destination, tempBuffer) != 0)
+                            {
+                                result = AGENT_DATA_TYPES_ERROR;
+                                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                            }
+                            else
+                            {
+                                result = AGENT_DATA_TYPES_OK;
+                            }
+
+                            // Clean up temp buffer if allocated
+                            free(tempBuffer);
+                        }
+                    }
+                }
+                else
+                {
+                    if (value->value.edmDateTimeOffset.hasFractionalSecond)
+                    {
+                        size_t tempBufferSize = 1 + //\"
+                            MAX_LONG_STRING_LENGTH + // %.4d
+                            1 + // -
+                            MAX_LONG_STRING_LENGTH + // %.2d
+                            1 + // -
+                            MAX_LONG_STRING_LENGTH + // %.2d
+                            1 + // T
+                            MAX_LONG_STRING_LENGTH + // %.2d
+                            1 + // :
+                            MAX_LONG_STRING_LENGTH + // %.2d
+                            1 + // :
+                            MAX_LONG_STRING_LENGTH + // %.2d
+                            1 + // .
+                            MAX_ULONG_LONG_STRING_LENGTH + // %.12llu
+                            1 + // Z
+                            1 + // \"
+                            1; // " (terminating NULL)
+                        char* tempBuffer = (char*)malloc(tempBufferSize);
+
+                        if (tempBuffer == NULL)
+                        {
+                            result = AGENT_DATA_TYPES_ERROR;
+                            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                        }
+                        else
+                        {
+                            if (sprintf_s(tempBuffer, tempBufferSize, "\"%.4d-%.2d-%.2dT%.2d:%.2d:%.2d.%.12lluZ\"", /*+ in printf forces the sign to appear*/
+                                value->value.edmDateTimeOffset.dateTime.tm_year + 1900,
+                                value->value.edmDateTimeOffset.dateTime.tm_mon+1,
+                                value->value.edmDateTimeOffset.dateTime.tm_mday,
+                                value->value.edmDateTimeOffset.dateTime.tm_hour,
+                                value->value.edmDateTimeOffset.dateTime.tm_min,
+                                value->value.edmDateTimeOffset.dateTime.tm_sec,
+                                value->value.edmDateTimeOffset.fractionalSecond) < 0)
+                            {
+                                result = AGENT_DATA_TYPES_ERROR;
+                                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                            }
+                            else if (STRING_concat(destination, tempBuffer) != 0)
+                            {
+                                result = AGENT_DATA_TYPES_ERROR;
+                                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                            }
+                            else
+                            {
+                                result = AGENT_DATA_TYPES_OK;
+                            }
+
+                            free(tempBuffer);
+                        }
+                    }
+                    else
+                    {
+                        size_t tempBufferSize = 1 + // \"
+                            MAX_LONG_STRING_LENGTH + // %.4d
+                            1 + // -
+                            MAX_LONG_STRING_LENGTH + // %.2d
+                            1 + // -
+                            MAX_LONG_STRING_LENGTH + // %.2d
+                            1 + // T
+                            MAX_LONG_STRING_LENGTH + // %.2d
+                            1 + // :
+                            MAX_LONG_STRING_LENGTH + // %.2d
+                            1 + // :
+                            MAX_LONG_STRING_LENGTH + // %.2d
+                            1 + // Z
+                            1 + // \"
+                            1; // " (terminating null);
+
+                        char* tempBuffer = (char*)malloc(tempBufferSize);
+
+                        if (tempBuffer == NULL)
+                        {
+                            result = AGENT_DATA_TYPES_ERROR;
+                            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                        }
+                        else
+                        {
+                            if (sprintf_s(tempBuffer, tempBufferSize, "\"%.4d-%.2d-%.2dT%.2d:%.2d:%.2dZ\"",
+                                value->value.edmDateTimeOffset.dateTime.tm_year + 1900,
+                                value->value.edmDateTimeOffset.dateTime.tm_mon+1,
+                                value->value.edmDateTimeOffset.dateTime.tm_mday,
+                                value->value.edmDateTimeOffset.dateTime.tm_hour,
+                                value->value.edmDateTimeOffset.dateTime.tm_min,
+                                value->value.edmDateTimeOffset.dateTime.tm_sec) < 0)
+                            {
+                                result = AGENT_DATA_TYPES_ERROR;
+                                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                            }
+                            else if (STRING_concat(destination, tempBuffer) != 0)
+                            {
+                                result = AGENT_DATA_TYPES_ERROR;
+                                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                            }
+                            else
+                            {
+                                result = AGENT_DATA_TYPES_OK;
+                            }
+
+                            free(tempBuffer);
+                        }
+                    }
+                }
+                break;
+            }
+            case(EDM_DECIMAL_TYPE) :
+            {
+                if (STRING_concat_with_STRING(destination, value->value.edmDecimal.value) != 0)
+                {
+                    result = AGENT_DATA_TYPES_ERROR;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    result = AGENT_DATA_TYPES_OK;
+                }
+                break;
+            }
+            case (EDM_INT16_TYPE) :
+            {
+                /*-32768 to +32767*/
+                char buffertemp2[7]; /*because 5 digits and sign and '\0'*/
+                uint16_t positiveValue;
+                size_t pos = 0;
+                uint16_t rank = (uint16_t)10000;
+                bool foundFirstDigit = false;
+
+                if (value->value.edmInt16.value < 0)
+                {
+                    buffertemp2[pos++] = '-';
+                    positiveValue = -value->value.edmInt16.value;
+                }
+                else
+                {
+                    positiveValue = value->value.edmInt16.value;
+                }
+
+                while (rank >= 10)
+                {
+                    if ((foundFirstDigit == true) || (positiveValue / rank) > 0)
+                    {
+                        buffertemp2[pos++] = '0' + (char)(positiveValue / rank);
+                        foundFirstDigit = true;
+                    }
+                    positiveValue %= rank;
+                    rank /= 10;
+                }
+                buffertemp2[pos++] = '0' + (char)(positiveValue);
+                buffertemp2[pos++] = '\0';
+
+                if (STRING_concat(destination, buffertemp2) != 0)
+                {
+                    result = AGENT_DATA_TYPES_ERROR;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    result = AGENT_DATA_TYPES_OK;
+                }
+                break;
+            }
+            case (EDM_INT32_TYPE) :
+            {
+                /*-2147483648 to +2147483647*/
+                char buffertemp2[12]; /*because 10 digits and sign and '\0'*/
+                uint32_t positiveValue;
+                size_t pos = 0;
+                uint32_t rank = 1000000000UL;
+                bool foundFirstDigit = false;
+
+                if (value->value.edmInt32.value < 0)
+                {
+                    buffertemp2[pos++] = '-';
+                    positiveValue = - value->value.edmInt32.value;
+                }
+                else
+                {
+                    positiveValue = value->value.edmInt32.value;
+                }
+
+                while (rank >= 10)
+                {
+                    if ((foundFirstDigit == true) || (positiveValue / rank) > 0)
+                    {
+                        buffertemp2[pos++] = '0' + (char)(positiveValue / rank);
+                        foundFirstDigit = true;
+                    }
+                    positiveValue %= rank;
+                    rank /= 10;
+                }
+                buffertemp2[pos++] = '0' + (char)(positiveValue);
+                buffertemp2[pos++] = '\0';
+
+                if (STRING_concat(destination, buffertemp2) != 0)
+                {
+                    result = AGENT_DATA_TYPES_ERROR;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    result = AGENT_DATA_TYPES_OK;
+                }
+                break;
+            }
+            case (EDM_INT64_TYPE):
+            {
+                char buffertemp2[21]; /*because 19 digits and sign and '\0'*/
+                uint64_t positiveValue;
+                size_t pos = 0;
+                uint64_t rank = 10000000000000000000ULL;
+                bool foundFirstDigit = false;
+
+                if (value->value.edmInt64.value < 0)
+                {
+                    buffertemp2[pos++] = '-';
+                    positiveValue = -value->value.edmInt64.value;
+                }
+                else
+                {
+                    positiveValue = value->value.edmInt64.value;
+                }
+
+                while (rank >= 10)
+                {
+                    if ((foundFirstDigit == true) || (positiveValue / rank) > 0)
+                    {
+                        buffertemp2[pos++] = '0' + (char)(positiveValue / rank);
+                        foundFirstDigit = true;
+                    }
+                    positiveValue %= rank;
+                    rank /= 10;
+                }
+                buffertemp2[pos++] = '0' + (char)(positiveValue);
+                buffertemp2[pos++] = '\0';
+
+                if (STRING_concat(destination, buffertemp2) != 0)
+                {
+                    result = AGENT_DATA_TYPES_ERROR;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    result = AGENT_DATA_TYPES_OK;
+                }
+                break;
+            }
+            case (EDM_SBYTE_TYPE) :
+            {
+                char tempbuffer2[5]; /* because '-' and 3 characters for 127 let's say and '\0'*/
+                int absValue = value->value.edmSbyte.value;
+                size_t pos=0;
+                /*Codes_SRS_AGENT_TYPE_SYSTEM_99_026:[ EDM_SBYTE: sbyteValue = [ sign ] 1*3DIGIT  ; numbers in the range from -128 to 127]*/
+
+                if (value->value.edmSbyte.value < 0)
+                {
+                    tempbuffer2[pos++] = '-';
+                    absValue = -absValue;
+                }
+
+                if (absValue >= 100 ) tempbuffer2[pos++] = '0' + (char)(absValue / 100);
+                if (absValue >=10) tempbuffer2[pos++] = '0' + (absValue % 100) / 10;
+                tempbuffer2[pos++] = '0' + (absValue % 10);
+                tempbuffer2[pos++] = '\0';
+
+
+                if (STRING_concat(destination, tempbuffer2) != 0)
+                {
+                    result = AGENT_DATA_TYPES_ERROR;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    result = AGENT_DATA_TYPES_OK;
+                }
+                break;
+            }
+            case (EDM_STRING_TYPE):
+            {
+                size_t i;
+                size_t nControlCharacters = 0; /*counts how many characters are to be expanded from 1 character to \uxxxx (6 characters)*/
+                size_t nEscapeCharacters = 0;
+                size_t vlen = value->value.edmString.length;
+                char* v = value->value.edmString.chars;
+
+                for (i = 0; i < vlen; i++)
+                {
+                    if ((unsigned char)v[i] >= 128) /*this be a UNICODE character begin*/
+                    {
+                        break;
+                    }
+                    else
+                    {
+                        if (v[i] <= 0x1F)
+                        {
+                            nControlCharacters++;
+                        }
+                        else if (
+                            (v[i] == '"') ||
+                            (v[i] == '\\') ||
+                            (v[i] == '/')
+                            )
+                        {
+                            nEscapeCharacters++;
+                        }
+                    }
+                }
+
+                if (i < vlen)
+                {
+                    result = AGENT_DATA_TYPES_INVALID_ARG; /*don't handle those who do not copy bit by bit to UTF8*/
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    /*forward parse the string to scan for " and for \ that in JSON are \" respectively \\*/
+                    size_t tempBufferSize = vlen + 5 * nControlCharacters + nEscapeCharacters + 3 + 1;
+                    char* tempBuffer = (char*)malloc(tempBufferSize);
+                    if (tempBuffer == NULL)
+                    {
+                        result = AGENT_DATA_TYPES_ERROR;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                    }
+                    else
+                    {
+                        size_t w = 0;
+                        tempBuffer[w++] = '"';
+                        for (i = 0; i < vlen; i++)
+                        {
+                            if (v[i] <= 0x1F)
+                            {
+                                tempBuffer[w++] = '\\';
+                                tempBuffer[w++] = 'u';
+                                tempBuffer[w++] = '0';
+                                tempBuffer[w++] = '0';
+                                tempBuffer[w++] = hexToASCII[(v[i] & 0xF0) >> 4]; /*high nibble*/
+                                tempBuffer[w++] = hexToASCII[v[i] & 0x0F]; /*lowNibble nibble*/
+                            }
+                            else if (v[i] == '"')
+                            {
+                                tempBuffer[w++] = '\\';
+                                tempBuffer[w++] = '"';
+                            }
+                            else if (v[i] == '\\')
+                            {
+                                tempBuffer[w++] = '\\';
+                                tempBuffer[w++] = '\\';
+                            }
+                            else if (v[i] == '/')
+                            {
+                                tempBuffer[w++] = '\\';
+                                tempBuffer[w++] = '/';
+                            }
+                            else
+                            {
+                                tempBuffer[w++] = v[i];
+                            }
+                        }
+
+#ifdef _MSC_VER
+#pragma warning(suppress: 6386) /* The test Create_AGENT_DATA_TYPE_from_charz_With_2_Slashes_Succeeds verifies that Code Analysis is wrong here */
+#endif
+                        tempBuffer[w] = '"';
+                        /*zero terminating it*/
+                        tempBuffer[vlen + 5 * nControlCharacters + nEscapeCharacters + 3 - 1] = '\0';
+
+                        if (STRING_concat(destination, tempBuffer) != 0)
+                        {
+                            result = AGENT_DATA_TYPES_ERROR;
+                            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                        }
+                        else
+                        {
+                            result = AGENT_DATA_TYPES_OK;
+                        }
+
+                        free(tempBuffer);
+                    }
+                }
+
+                break;
+            }
+
+            /* Codes_SRS_AGENT_TYPE_SYSTEM_01_003: [EDM_STRING_no_quotes: the string is copied as given when the AGENT_DATA_TYPE was created.] */
+            case (EDM_STRING_NO_QUOTES_TYPE) :
+            {
+                /* this is a special case where we just want to copy/paste the contents, no encoding, no quotes */
+                /* Codes_SRS_AGENT_TYPE_SYSTEM_01_002: [When serialized, this type is not enclosed with quotes.] */
+                if (STRING_concat(destination, value->value.edmStringNoQuotes.chars) != 0)
+                {
+                    result = AGENT_DATA_TYPES_ERROR;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    result = AGENT_DATA_TYPES_OK;
+                }
+
+                break;
+            }
+
+#ifndef NO_FLOATS
+            case(EDM_SINGLE_TYPE):
+            {
+                /*C89 standard says: When a float is promoted to double or long double, or a double is promoted to long double, its value is unchanged*/
+                /*I read that as : when a float is NaN or Inf, it will stay NaN or INF in double representation*/
+
+                /*The sprintf function returns the number of characters written in the array, not counting the terminating null character.*/
+
+                if(ISNAN(value->value.edmSingle.value))
+                {
+                    if (STRING_concat(destination, NaN_STRING) != 0)
+                    {
+                        result = AGENT_DATA_TYPES_ERROR;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                    }
+                    else
+                    {
+                        result = AGENT_DATA_TYPES_OK;
+                    }
+                }
+                else if (ISNEGATIVEINFINITY(value->value.edmSingle.value))
+                {
+                    if (STRING_concat(destination, MINUSINF_STRING) != 0)
+                    {
+                        result = AGENT_DATA_TYPES_ERROR;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                    }
+                    else
+                    {
+                        result = AGENT_DATA_TYPES_OK;
+                    }
+                }
+                else if (ISPOSITIVEINFINITY(value->value.edmSingle.value))
+                {
+                    if (STRING_concat(destination, PLUSINF_STRING) != 0)
+                    {
+                        result = AGENT_DATA_TYPES_ERROR;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                    }
+                    else
+                    {
+                        result = AGENT_DATA_TYPES_OK;
+                    }
+                }
+                else
+                {
+                    size_t tempBufferSize = MAX_FLOATING_POINT_STRING_LENGTH;
+                    char* tempBuffer = (char*)malloc(tempBufferSize);
+                    if (tempBuffer == NULL)
+                    {
+                        result = AGENT_DATA_TYPES_ERROR;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                    }
+                    else
+                    {
+                        if (sprintf_s(tempBuffer, tempBufferSize, "%.*f", FLT_DIG, (double)(value->value.edmSingle.value)) < 0)
+                        {
+                            result = AGENT_DATA_TYPES_ERROR;
+                            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                        }
+                        else if (STRING_concat(destination, tempBuffer) != 0)
+                        {
+                            result = AGENT_DATA_TYPES_ERROR;
+                            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                        }
+                        else
+                        {
+                            result = AGENT_DATA_TYPES_OK;
+                        }
+
+                        free(tempBuffer);
+                    }
+                }
+                break;
+            }
+            case(EDM_DOUBLE_TYPE):
+            {
+                /*The sprintf function returns the number of characters written in the array, not counting the terminating null character.*/
+                /*OData-ABNF says these can be used: nanInfinity = 'NaN' / '-INF' / 'INF'*/
+                /*C90 doesn't declare a NaN or Inf in the standard, however, values might be NaN or Inf...*/
+                /*C99 ... does*/
+                /*C11 is same as C99*/
+                /*Codes_SRS_AGENT_TYPE_SYSTEM_99_022:[ EDM_DOUBLE: doubleValue = decimalValue [ "e" [SIGN] 1*DIGIT ] / nanInfinity ; IEEE 754 binary64 floating-point number (15-17 decimal digits). The representation shall use DBL_DIG C #define*/
+                if(ISNAN(value->value.edmDouble.value))
+                {
+                    if (STRING_concat(destination, NaN_STRING) != 0)
+                    {
+                        result = AGENT_DATA_TYPES_ERROR;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                    }
+                    else
+                    {
+                        result = AGENT_DATA_TYPES_OK;
+                    }
+                }
+                /*Codes_SRS_AGENT_TYPE_SYSTEM_99_022:[ EDM_DOUBLE: doubleValue = decimalValue [ "e" [SIGN] 1*DIGIT ] / nanInfinity ; IEEE 754 binary64 floating-point number (15-17 decimal digits). The representation shall use DBL_DIG C #define*/
+                else if (ISNEGATIVEINFINITY(value->value.edmDouble.value))
+                {
+                    if (STRING_concat(destination, MINUSINF_STRING) != 0)
+                    {
+                        result = AGENT_DATA_TYPES_ERROR;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                    }
+                    else
+                    {
+                        result = AGENT_DATA_TYPES_OK;
+                    }
+                }
+                /*Codes_SRS_AGENT_TYPE_SYSTEM_99_022:[ EDM_DOUBLE: doubleValue = decimalValue [ "e" [SIGN] 1*DIGIT ] / nanInfinity ; IEEE 754 binary64 floating-point number (15-17 decimal digits). The representation shall use DBL_DIG C #define*/
+                else if (ISPOSITIVEINFINITY(value->value.edmDouble.value))
+                {
+                    if (STRING_concat(destination, PLUSINF_STRING) != 0)
+                    {
+                        result = AGENT_DATA_TYPES_ERROR;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                    }
+                    else
+                    {
+                        result = AGENT_DATA_TYPES_OK;
+                    }
+                }
+                /*Codes_SRS_AGENT_TYPE_SYSTEM_99_022:[ EDM_DOUBLE: doubleValue = decimalValue [ "e" [SIGN] 1*DIGIT ] / nanInfinity ; IEEE 754 binary64 floating-point number (15-17 decimal digits). The representation shall use DBL_DIG C #define*/
+                else
+                {
+                    size_t tempBufferSize = DECIMAL_DIG * 2;
+                    char* tempBuffer = (char*)malloc(tempBufferSize);
+                    if (tempBuffer == NULL)
+                    {
+                        result = AGENT_DATA_TYPES_ERROR;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                    }
+                    else
+                    {
+                        if (sprintf_s(tempBuffer, tempBufferSize, "%.*f", DBL_DIG, value->value.edmDouble.value) < 0)
+                        {
+                            result = AGENT_DATA_TYPES_ERROR;
+                            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                        }
+                        else if (STRING_concat(destination, tempBuffer) != 0)
+                        {
+                            result = AGENT_DATA_TYPES_ERROR;
+                            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                        }
+                        else
+                        {
+                            result = AGENT_DATA_TYPES_OK;
+                        }
+
+                        free(tempBuffer);
+                    }
+                }
+                break;
+            }
+#endif
+
+            case(EDM_COMPLEX_TYPE_TYPE) :
+            {
+                /*to produce an EDM_COMPLEX_TYPE is a recursive process*/
+                /*uses JSON encoder*/
+                /*Codes_SRS_AGENT_TYPE_SYSTEM_99_062:[ If the AGENT_DATA_TYPE represents a "complex type", then the JSON marshaller shall produce the following JSON value:[...]*/
+                MULTITREE_HANDLE treeHandle;
+                result = AGENT_DATA_TYPES_OK;
+                /*SRS_AGENT_TYPE_SYSTEM_99_016:[ When the value cannot be converted to a string AgentDataTypes_ToString shall return AGENT_DATA_TYPES_ERROR.]*/
+                treeHandle = MultiTree_Create(NoCloneFunction, NoFreeFunction);
+                if (treeHandle == NULL)
+                {
+                    result = AGENT_DATA_TYPES_ERROR;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    size_t i;
+                    for (i = 0; i < value->value.edmComplexType.nMembers; i++)
+                    {
+                        if (MultiTree_AddLeaf(treeHandle, value->value.edmComplexType.fields[i].fieldName, value->value.edmComplexType.fields[i].value) != MULTITREE_OK)
+                        {
+                            /*SRS_AGENT_TYPE_SYSTEM_99_016:[ When the value cannot be converted to a string AgentDataTypes_ToString shall return AGENT_DATA_TYPES_ERROR.]*/
+                            result = AGENT_DATA_TYPES_ERROR;
+                            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                            break;
+                        }
+                        else
+                        {
+                            /*all is fine*/
+                        }
+                    }
+
+                    if (result == AGENT_DATA_TYPES_OK)
+                    {
+                            /*SRS_AGENT_TYPE_SYSTEM_99_016:[ When the value cannot be converted to a string AgentDataTypes_ToString shall return AGENT_DATA_TYPES_ERROR.]*/
+                            if (JSONEncoder_EncodeTree(treeHandle, destination, (JSON_ENCODER_TOSTRING_FUNC)AgentDataTypes_ToString) != JSON_ENCODER_OK)
+                            {
+                                result = AGENT_DATA_TYPES_ERROR;
+                                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                            }
+                            else
+                            {
+                                /*all is fine*/
+                            }
+
+                    }
+
+                    MultiTree_Destroy(treeHandle);
+                }
+                break;
+            }
+            case EDM_GUID_TYPE:
+            {
+                char tempBuffer2[1 + 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12 + 1+ 1];
+                /*Codes_SRS_AGENT_TYPE_SYSTEM_99_093:[ EDM_GUID: 8HEXDIG "-" 4HEXDIG "-" 4HEXDIG "-" 4HEXDIG "-" 12HEXDIG]*/
+                tempBuffer2[0] = '\"';
+                tempBuffer2[1] = hexDigitToChar(value->value.edmGuid.GUID[0] / 16);
+                tempBuffer2[2] = hexDigitToChar(value->value.edmGuid.GUID[0] % 16);
+                tempBuffer2[3] = hexDigitToChar(value->value.edmGuid.GUID[1] / 16);
+                tempBuffer2[4] = hexDigitToChar(value->value.edmGuid.GUID[1] % 16);
+                tempBuffer2[5] = hexDigitToChar(value->value.edmGuid.GUID[2] / 16);
+                tempBuffer2[6] = hexDigitToChar(value->value.edmGuid.GUID[2] % 16);
+                tempBuffer2[7] = hexDigitToChar(value->value.edmGuid.GUID[3] / 16);
+                tempBuffer2[8] = hexDigitToChar(value->value.edmGuid.GUID[3] % 16);
+
+                tempBuffer2[9] = '-';
+                tempBuffer2[10] = hexDigitToChar(value->value.edmGuid.GUID[4] / 16);
+                tempBuffer2[11] = hexDigitToChar(value->value.edmGuid.GUID[4] % 16);
+                tempBuffer2[12] = hexDigitToChar(value->value.edmGuid.GUID[5] / 16);
+                tempBuffer2[13] = hexDigitToChar(value->value.edmGuid.GUID[5] % 16);
+
+                tempBuffer2[14] = '-';
+                tempBuffer2[15] = hexDigitToChar(value->value.edmGuid.GUID[6] / 16);
+                tempBuffer2[16] = hexDigitToChar(value->value.edmGuid.GUID[6] % 16);
+                tempBuffer2[17] = hexDigitToChar(value->value.edmGuid.GUID[7] / 16);
+                tempBuffer2[18] = hexDigitToChar(value->value.edmGuid.GUID[7] % 16);
+
+                tempBuffer2[19] = '-';
+                tempBuffer2[20] = hexDigitToChar(value->value.edmGuid.GUID[8] / 16);
+                tempBuffer2[21] = hexDigitToChar(value->value.edmGuid.GUID[8] % 16);
+                tempBuffer2[22] = hexDigitToChar(value->value.edmGuid.GUID[9] / 16);
+                tempBuffer2[23] = hexDigitToChar(value->value.edmGuid.GUID[9] % 16);
+
+                tempBuffer2[24] = '-';
+                tempBuffer2[25] = hexDigitToChar(value->value.edmGuid.GUID[10] / 16);
+                tempBuffer2[26] = hexDigitToChar(value->value.edmGuid.GUID[10] % 16);
+                tempBuffer2[27] = hexDigitToChar(value->value.edmGuid.GUID[11] / 16);
+                tempBuffer2[28] = hexDigitToChar(value->value.edmGuid.GUID[11] % 16);
+                tempBuffer2[29] = hexDigitToChar(value->value.edmGuid.GUID[12] / 16);
+                tempBuffer2[30] = hexDigitToChar(value->value.edmGuid.GUID[12] % 16);
+                tempBuffer2[31] = hexDigitToChar(value->value.edmGuid.GUID[13] / 16);
+                tempBuffer2[32] = hexDigitToChar(value->value.edmGuid.GUID[13] % 16);
+                tempBuffer2[33] = hexDigitToChar(value->value.edmGuid.GUID[14] / 16);
+                tempBuffer2[34] = hexDigitToChar(value->value.edmGuid.GUID[14] % 16);
+                tempBuffer2[35] = hexDigitToChar(value->value.edmGuid.GUID[15] / 16);
+                tempBuffer2[36] = hexDigitToChar(value->value.edmGuid.GUID[15] % 16);
+
+                tempBuffer2[37] = '\"';
+                tempBuffer2[38] = '\0';
+
+                if (STRING_concat(destination, tempBuffer2) != 0)
+                {
+                    result = AGENT_DATA_TYPES_ERROR;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    result = AGENT_DATA_TYPES_OK;
+                }
+                break;
+            }
+            case EDM_BINARY_TYPE:
+            {
+                size_t currentPosition = 0;
+                char* temp;
+                /*binary types */
+                /*Codes_SRS_AGENT_TYPE_SYSTEM_99_099:[EDM_BINARY:= *(4base64char)[base64b16 / base64b8]]*/
+                /*the following will happen*/
+                /*1. the "data" of the binary shall be "eaten" 3 characters at a time and produce 4 base64 encoded characters for as long as there are more than 3 characters still to process*/
+                /*2. the remaining characters (1 or 2) shall be encoded.*/
+                /*there's a level of assumption that 'a' corresponds to 0b000000 and that '_' corresponds to 0b111111*/
+                /*the encoding will use the optional [=] or [==] at the end of the encoded string, so that other less standard aware libraries can do their work*/
+                /*these are the bits of the 3 normal bytes to be encoded*/
+                size_t neededSize = 2; /*2 because starting and ending quotes */
+                neededSize += (value->value.edmBinary.size == 0) ? (0) : ((((value->value.edmBinary.size-1) / 3) + 1) * 4);
+                neededSize += 1; /*+1 because \0 at the end of the string*/
+                if ((temp = (char*)malloc(neededSize))==NULL)
+                {
+                    result = AGENT_DATA_TYPES_ERROR;
+                }
+                else
+                {
+                    /*b0            b1(+1)          b2(+2)
+                      7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
+                      |----c1---| |----c2---| |----c3---| |----c4---|
+                    */
+
+                    size_t destinationPointer = 0;
+                    temp[destinationPointer++] = '"';
+                    while (value->value.edmBinary.size - currentPosition >= 3)
+                    {
+                        char c1 = base64char(value->value.edmBinary.data[currentPosition] >> 2);
+                        char c2 = base64char(
+                            ((value->value.edmBinary.data[currentPosition] & 3) << 4) |
+                                (value->value.edmBinary.data[currentPosition + 1] >> 4)
+                        );
+                        char c3 = base64char(
+                            ((value->value.edmBinary.data[currentPosition + 1] & 0x0F) << 2) |
+                                ((value->value.edmBinary.data[currentPosition + 2] >> 6) & 3)
+                        );
+                        char c4 = base64char(
+                            value->value.edmBinary.data[currentPosition + 2] & 0x3F
+                        );
+                        currentPosition += 3;
+                        temp[destinationPointer++] = c1;
+                        temp[destinationPointer++] = c2;
+                        temp[destinationPointer++] = c3;
+                        temp[destinationPointer++] = c4;
+
+                    }
+                    if (value->value.edmBinary.size - currentPosition == 2)
+                    {
+                        char c1 = base64char(value->value.edmBinary.data[currentPosition] >> 2);
+                        char c2 = base64char(
+                            ((value->value.edmBinary.data[currentPosition] & 0x03) << 4) |
+                                (value->value.edmBinary.data[currentPosition + 1] >> 4)
+                        );
+                        char c3 = base64b16(value->value.edmBinary.data[currentPosition + 1] & 0x0F);
+                        temp[destinationPointer++] = c1;
+                        temp[destinationPointer++] = c2;
+                        temp[destinationPointer++] = c3;
+                        temp[destinationPointer++] = '=';
+                    }
+                    else if (value->value.edmBinary.size - currentPosition == 1)
+                    {
+                        char c1 = base64char(value->value.edmBinary.data[currentPosition] >> 2);
+                        char c2 = base64b8(value->value.edmBinary.data[currentPosition] & 0x03);
+                        temp[destinationPointer++] = c1;
+                        temp[destinationPointer++] = c2;
+                        temp[destinationPointer++] = '=';
+                        temp[destinationPointer++] = '=';
+                    }
+
+                    /*closing quote*/
+                    temp[destinationPointer++] = '"';
+                    /*null terminating the string*/
+                    temp[destinationPointer] = '\0';
+
+                    if (STRING_concat(destination, temp) != 0)
+                    {
+                        result = AGENT_DATA_TYPES_ERROR;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                    }
+                    else
+                    {
+                        result = AGENT_DATA_TYPES_OK;
+                    }
+                    free(temp);
+                }
+                break;
+            }
+        }
+    }
+    return result;
+}
+
+/*return 0 if all names are different than NULL*/
+static int isOneNameNULL(size_t nMemberNames, const char* const * memberNames)
+{
+    size_t i;
+    int result = 0;
+    for (i = 0; i < nMemberNames; i++)
+    {
+        if (memberNames[i] == NULL)
+        {
+            result = 1;
+            break;
+        }
+    }
+    return result;
+}
+
+/*return 0 if all names are different than NULL*/
+static int areThereTwoSameNames(size_t nMemberNames, const char* const * memberNames)
+{
+    size_t i, j;
+    int result = 0;
+    for (i = 0; i < nMemberNames-1; i++)
+    {
+        for (j = i + 1; j < nMemberNames; j++)
+        {
+            if (strcmp(memberNames[i], memberNames[j]) == 0)
+            {
+                result = 1;
+                goto out;
+            }
+        }
+    }
+out:
+    return result;
+}
+
+static void DestroyHalfBakedComplexType(AGENT_DATA_TYPE* agentData)
+{
+    size_t i;
+    if (agentData != NULL)
+    {
+        if (agentData->type == EDM_COMPLEX_TYPE_TYPE)
+        {
+            if (agentData->value.edmComplexType.fields != NULL)
+            {
+                for (i = 0; i < agentData->value.edmComplexType.nMembers; i++)
+                {
+                    if (agentData->value.edmComplexType.fields[i].fieldName != NULL)
+                    {
+                        free((void*)(agentData->value.edmComplexType.fields[i].fieldName));
+                        agentData->value.edmComplexType.fields[i].fieldName = NULL;
+                    }
+                    if (agentData->value.edmComplexType.fields[i].value != NULL)
+                    {
+                        Destroy_AGENT_DATA_TYPE(agentData->value.edmComplexType.fields[i].value);
+                        free(agentData->value.edmComplexType.fields[i].value);
+                        agentData->value.edmComplexType.fields[i].value = NULL;
+                    }
+                }
+                free(agentData->value.edmComplexType.fields);
+                agentData->value.edmComplexType.fields = NULL;
+            }
+            agentData->type = EDM_NO_TYPE;
+        }
+    }
+}
+
+/* Creates an object of AGENT_DATA_TYPE_TYPE EDM_NULL_TYPE*/
+AGENT_DATA_TYPES_RESULT Create_NULL_AGENT_DATA_TYPE(AGENT_DATA_TYPE* agentData)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    if (agentData == NULL)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+    }
+    else
+    {
+        agentData->type = EDM_NULL_TYPE;
+        result = AGENT_DATA_TYPES_OK;
+    }
+    return result;
+}
+/*creates a copy of the AGENT_DATA_TYPE*/
+AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_AGENT_DATA_TYPE(AGENT_DATA_TYPE* dest, const AGENT_DATA_TYPE* src)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    size_t i;
+    if ((dest == NULL) || (src == NULL))
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+    }
+    else
+    {
+        switch (src->type)
+        {
+            default:
+            {
+                result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                break;
+            }
+            case(EDM_NO_TYPE) :
+            case(EDM_NULL_TYPE) :
+            {
+                dest->type = src->type;
+                result = AGENT_DATA_TYPES_OK;
+                break;
+            }
+            case(EDM_BOOLEAN_TYPE) :
+            {
+                dest->type = src->type;
+                dest->value.edmBoolean= src->value.edmBoolean;
+                result = AGENT_DATA_TYPES_OK;
+                break;
+            }
+            case(EDM_BYTE_TYPE) :
+            {
+                dest->type = src->type;
+                dest->value.edmByte= src->value.edmByte;
+                result = AGENT_DATA_TYPES_OK;
+                break;
+            }
+            case(EDM_DATE_TYPE) :
+            {
+                dest->type = src->type;
+                dest->value.edmDate = src->value.edmDate;
+                result = AGENT_DATA_TYPES_OK;
+                break;
+            }
+            case(EDM_DATE_TIME_OFFSET_TYPE) :
+            {
+                dest->type = src->type;
+                dest->value.edmDateTimeOffset = src->value.edmDateTimeOffset;
+                result = AGENT_DATA_TYPES_OK;
+                break;
+            }
+            case(EDM_DECIMAL_TYPE) :
+            {
+                if ((dest->value.edmDecimal.value = STRING_clone(src->value.edmDecimal.value)) == NULL)
+                {
+                    result = AGENT_DATA_TYPES_ERROR;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    dest->type = src->type;
+                    result = AGENT_DATA_TYPES_OK;
+                    /*all is fine*/
+                }
+                break;
+            }
+            case(EDM_DOUBLE_TYPE) :
+            {
+                dest->type = src->type;
+                dest->value.edmDouble = src->value.edmDouble;
+                result = AGENT_DATA_TYPES_OK;
+                break;
+            }
+            case(EDM_DURATION_TYPE) :
+            {
+                result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                break;
+            }
+            case(EDM_GUID_TYPE) :
+            {
+                dest->type = src->type;
+                dest->value.edmGuid = src->value.edmGuid;
+                result = AGENT_DATA_TYPES_OK;
+                break;
+            }
+            case EDM_BINARY_TYPE:
+            {
+                if (src->value.edmBinary.size == 0)
+                {
+                    dest->value.edmBinary.size = 0;
+                    dest->value.edmBinary.data = NULL;
+                    dest->type = EDM_BINARY_TYPE;
+                    result = AGENT_DATA_TYPES_OK;
+                }
+                else
+                {
+                    if ((dest->value.edmBinary.data = (unsigned char*)malloc(src->value.edmBinary.size)) == NULL)
+                    {
+                        result = AGENT_DATA_TYPES_ERROR;
+                    }
+                    else
+                    {
+                        dest->value.edmBinary.size = src->value.edmBinary.size;
+                        (void)memcpy(dest->value.edmBinary.data, src->value.edmBinary.data, src->value.edmBinary.size);
+                        dest->type = EDM_BINARY_TYPE;
+                        result = AGENT_DATA_TYPES_OK;
+                    }
+                }
+                break;
+            }
+            case(EDM_INT16_TYPE) :
+            {
+                dest->type = src->type;
+                dest->value.edmInt16 = src->value.edmInt16;
+                result = AGENT_DATA_TYPES_OK;
+                break;
+            }
+            case(EDM_INT32_TYPE) :
+            {
+                dest->type = src->type;
+                dest->value.edmInt32 = src->value.edmInt32;
+                result = AGENT_DATA_TYPES_OK;
+                break;
+            }
+            case(EDM_INT64_TYPE) :
+            {
+                dest->type = src->type;
+                dest->value.edmInt64 = src->value.edmInt64;
+                result = AGENT_DATA_TYPES_OK;
+                break;
+            }
+            case(EDM_SBYTE_TYPE) :
+            {
+                dest->type = src->type;
+                dest->value.edmSbyte = src->value.edmSbyte;
+                result = AGENT_DATA_TYPES_OK;
+                break;
+            }
+            case(EDM_SINGLE_TYPE) :
+            {
+                dest->type = src->type;
+                dest->value.edmSingle = src->value.edmSingle;
+                result = AGENT_DATA_TYPES_OK;
+                break;
+            }
+            case(EDM_STREAM) :
+            {
+                result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                break;
+            } /*not supported, because what is stream?*/
+            case(EDM_STRING_TYPE) :
+            {
+                dest->type = src->type;
+                dest->value.edmString.length = src->value.edmString.length;
+                if (mallocAndStrcpy_s((char**)&(dest->value.edmString.chars), (char*)src->value.edmString.chars) != 0)
+                {
+                    result = AGENT_DATA_TYPES_ERROR;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    result = AGENT_DATA_TYPES_OK;
+                    /*all is fine*/
+                }
+                break;
+            }
+            case(EDM_STRING_NO_QUOTES_TYPE) :
+            {
+                dest->type = src->type;
+                dest->value.edmStringNoQuotes.length = src->value.edmStringNoQuotes.length;
+                if (mallocAndStrcpy_s((char**)&(dest->value.edmStringNoQuotes.chars), (char*)src->value.edmStringNoQuotes.chars) != 0)
+                {
+                    result = AGENT_DATA_TYPES_ERROR;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    result = AGENT_DATA_TYPES_OK;
+                    /*all is fine*/
+                }
+                break;
+            }
+            case(EDM_TIME_OF_DAY_TYPE) :
+            {
+                result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                break;
+            }
+            case(EDM_GEOGRAPHY_TYPE) :
+            {
+                result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                break;
+            } /*not supported because what is "abstract base type"*/
+            case(EDM_GEOGRAPHY_POINT_TYPE) :
+            {
+                result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                break;
+            }
+            case(EDM_GEOGRAPHY_LINE_STRING_TYPE) :
+            {
+                result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                break;
+            }
+            case(EDM_GEOGRAPHY_POLYGON_TYPE) :
+            {
+                result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                break;
+            }
+            case(EDM_GEOGRAPHY_MULTI_POINT_TYPE) :
+            {
+                result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                break;
+            }
+            case(EDM_GEOGRAPHY_MULTI_LINE_STRING_TYPE) :
+            {
+                result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                break;
+            }
+            case(EDM_GEOGRAPHY_MULTI_POLYGON_TYPE) :
+            {
+                result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                break;
+            }
+            case(EDM_GEOGRAPHY_COLLECTION_TYPE) :
+            {
+                result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                break;
+            }
+            case(EDM_GEOMETRY_TYPE) :
+            {
+                result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                break;
+            } /*not supported because what is "abstract base type"*/
+            case(EDM_GEOMETRY_POINT_TYPE) :
+            {
+                result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                break;
+            }
+            case(EDM_GEOMETRY_LINE_STRING_TYPE) :
+            {
+                result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                break;
+            }
+            case(EDM_GEOMETRY_POLYGON_TYPE) :
+            {
+                result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                break;
+            }
+            case(EDM_GEOMETRY_MULTI_POINT_TYPE) :
+            {
+                result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                break;
+            }
+            case(EDM_GEOMETRY_MULTI_LINE_STRING_TYPE) :
+            {
+                result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                break;
+            }
+            case(EDM_GEOMETRY_MULTI_POLYGON_TYPE) :
+            {
+                result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                break;
+            }
+            case(EDM_GEOMETRY_COLLECTION_TYPE) :
+            {
+                result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                break;
+            }
+            case(EDM_COMPLEX_TYPE_TYPE) :
+            {
+                result = AGENT_DATA_TYPES_OK;
+                /*copying a COMPLEX_TYPE means to copy all its member names and all its fields*/
+                dest->type = src->type;
+                if (src->value.edmComplexType.nMembers == 0)
+                {
+                    /*error*/
+                    result = AGENT_DATA_TYPES_INVALID_ARG;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    dest->value.edmComplexType.nMembers = src->value.edmComplexType.nMembers;
+                    dest->value.edmComplexType.fields = (COMPLEX_TYPE_FIELD_TYPE*)malloc(dest->value.edmComplexType.nMembers * sizeof(COMPLEX_TYPE_FIELD_TYPE));
+                    if (dest->value.edmComplexType.fields == NULL)
+                    {
+                        result = AGENT_DATA_TYPES_ERROR;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                    }
+                    else
+                    {
+                        for (i = 0; i < dest->value.edmComplexType.nMembers; i++)
+                        {
+                            dest->value.edmComplexType.fields[i].fieldName = NULL;
+                            dest->value.edmComplexType.fields[i].value = NULL;
+                        }
+
+                        for (i = 0; i < dest->value.edmComplexType.nMembers; i++)
+                        {
+                            /*copy the name of this field*/
+                            if (mallocAndStrcpy_s((char**)(&(dest->value.edmComplexType.fields[i].fieldName)), src->value.edmComplexType.fields[i].fieldName) != 0)
+                            {
+                                result = AGENT_DATA_TYPES_ERROR;
+                                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                                break;
+                            }
+                            else
+                            {
+                                /*field name copied success*/
+                                /*field value copy follows*/
+                                dest->value.edmComplexType.fields[i].value = (AGENT_DATA_TYPE*)calloc(1, sizeof(AGENT_DATA_TYPE));
+                                if (dest->value.edmComplexType.fields[i].value == NULL)
+                                {
+                                    result = AGENT_DATA_TYPES_ERROR;
+                                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                                    break;
+                                }
+                                else
+                                {
+                                    if (Create_AGENT_DATA_TYPE_from_AGENT_DATA_TYPE(dest->value.edmComplexType.fields[i].value, src->value.edmComplexType.fields[i].value) != AGENT_DATA_TYPES_OK)
+                                    {
+                                        result = AGENT_DATA_TYPES_ERROR;
+                                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                                        break;
+                                    }
+                                    else
+                                    {
+                                        /*all is fine*/
+                                    }
+                                }
+                            }
+                        }
+
+                        if (result != AGENT_DATA_TYPES_OK)
+                        {
+                            /*unbuild*/
+                            DestroyHalfBakedComplexType(dest);
+                        }
+                    }
+                }
+                break;
+            } /*ANY CHANGE (?!) here must be reflected in the tool providing the binary file (XML2BINARY) */
+        }
+
+        if (result != AGENT_DATA_TYPES_OK)
+        {
+            dest->type = EDM_NO_TYPE;
+        }
+    }
+
+    return result;
+}
+
+AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_MemberPointers(AGENT_DATA_TYPE* agentData, const char* typeName, size_t nMembers, const char* const * memberNames, const AGENT_DATA_TYPE** memberPointerValues)
+{
+    AGENT_DATA_TYPES_RESULT result;
+
+    /* Codes_SRS_AGENT_TYPE_SYSTEM_99_109:[ AGENT_DATA_TYPES_INVALID_ARG shall be returned if memberPointerValues parameter is NULL.] */
+    if (memberPointerValues == NULL)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result: AGENT_DATA_TYPES_INVALID_ARG)");
+    }
+    else
+    {
+        AGENT_DATA_TYPE* values = (AGENT_DATA_TYPE*)calloc(1, (nMembers* sizeof(AGENT_DATA_TYPE)));
+        if (values == NULL)
+        {
+            result = AGENT_DATA_TYPES_ERROR;
+            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+        }
+        else
+        {
+            size_t i;
+            for (i = 0; i < nMembers; i++)
+            {
+                if (Create_AGENT_DATA_TYPE_from_AGENT_DATA_TYPE(values + i, memberPointerValues[i]) != AGENT_DATA_TYPES_OK)
+                {
+                    size_t j;
+                    for (j = 0; j < i; j++)
+                    {
+                        Destroy_AGENT_DATA_TYPE(values + j);
+                    }
+                    break;
+                }
+            }
+
+            if (i != nMembers)
+            {
+                result = AGENT_DATA_TYPES_ERROR;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+            }
+            else
+            {
+                /* SRS_AGENT_TYPE_SYSTEM_99_111:[ AGENT_DATA_TYPES_OK shall be returned upon success.] */
+                result = Create_AGENT_DATA_TYPE_from_Members(agentData, typeName, nMembers, memberNames, values);
+                if (result != AGENT_DATA_TYPES_OK)
+                {
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                for (i = 0; i < nMembers; i++)
+                {
+                    Destroy_AGENT_DATA_TYPE(&values[i]);
+                }
+            }
+            free(values);
+        }
+    }
+    return result;
+}
+
+AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_Members(AGENT_DATA_TYPE* agentData, const char* typeName, size_t nMembers, const char* const * memberNames, const AGENT_DATA_TYPE* memberValues)
+{
+    AGENT_DATA_TYPES_RESULT result;
+    size_t i;
+    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[ All the functions shall check their parameters for validity. When an invalid parameter is detected, the value AGENT_DATA_TYPES_INVALID_ARG shall be returned ]*/
+    if (agentData == NULL)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result: AGENT_DATA_TYPES_INVALID_ARG)");
+    }
+    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_055:[ If typeName is NULL, the function shall return AGENT_DATA_TYPES_INVALID_ARG .]*/
+    else if (typeName==NULL)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result: AGENT_DATA_TYPES_INVALID_ARG)");
+    }
+    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_056:[If nMembers is 0, the function shall return AGENT_DATA_TYPES_INVALID_ARG .]*/
+    else if (nMembers == 0)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+    }
+    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_057:[ If memberNames is NULL, the function shall return AGENT_DATA_TYPES_INVALID_ARG .]*/
+    else if (memberNames == NULL)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+    }
+    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_058:[ If any of the memberNames[i] is NULL, the function shall return AGENT_DATA_TYPES_INVALID_ARG .]*/
+    else if (isOneNameNULL(nMembers, memberNames)!=0)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+    }
+    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_059:[ If memberValues is NULL, the function shall return AGENT_DATA_TYPES_INVALID_ARG .]*/
+    else if (memberValues == NULL)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+    }
+    /*Codes_SRS_AGENT_TYPE_SYSTEM_99_063:[ If there are two memberNames with the same name, then the function shall return  AGENT_DATA_TYPES_INVALID_ARG.]*/
+    else if (areThereTwoSameNames(nMembers, memberNames) != 0)
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+    }
+    else
+    {
+        agentData->value.edmComplexType.nMembers = nMembers;
+        agentData->value.edmComplexType.fields = (COMPLEX_TYPE_FIELD_TYPE*)malloc(nMembers *sizeof(COMPLEX_TYPE_FIELD_TYPE));
+        if (agentData->value.edmComplexType.fields == NULL)
+        {
+            result = AGENT_DATA_TYPES_ERROR;
+            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+        }
+        else
+        {
+            result = AGENT_DATA_TYPES_OK; /*not liking this, solution might be to use a temp variable*/
+
+            /*initialize the fields*/
+            for (i = 0; i < nMembers; i++)
+            {
+                agentData->value.edmComplexType.fields[i].fieldName = NULL;
+                agentData->value.edmComplexType.fields[i].value = NULL;
+            }
+
+            for (i = 0; i < nMembers; i++)
+            {
+                /*copy the name*/
+                if (mallocAndStrcpy_s((char**)(&(agentData->value.edmComplexType.fields[i].fieldName)), memberNames[i]) != 0)
+                {
+                    result = AGENT_DATA_TYPES_ERROR;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                    break;
+                }
+                else
+                {
+                    /*field name was transferred successfully*/
+                    /*copy the rest*/
+                    agentData->value.edmComplexType.fields[i].value = (AGENT_DATA_TYPE*)calloc(1, sizeof(AGENT_DATA_TYPE));
+                    if (agentData->value.edmComplexType.fields[i].value == NULL)
+                    {
+                        /*deallocate the name*/
+                        free((void*)(agentData->value.edmComplexType.fields[i].fieldName));
+                        agentData->value.edmComplexType.fields[i].fieldName = NULL;
+                        result = AGENT_DATA_TYPES_ERROR;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                        break;
+                    }
+                    else
+                    {
+                        /*copy the values*/
+                        if (Create_AGENT_DATA_TYPE_from_AGENT_DATA_TYPE(agentData->value.edmComplexType.fields[i].value, &(memberValues[i])) != AGENT_DATA_TYPES_OK)
+                        {
+                            result = AGENT_DATA_TYPES_ERROR;
+                            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                            break;
+                        }
+                        else
+                        {
+                            /*all is fine*/
+                        }
+                    }
+                }
+
+            }
+        }
+
+        if (result != AGENT_DATA_TYPES_OK)
+        {
+            /*dealloc, something went bad*/
+            DestroyHalfBakedComplexType(agentData);
+        }
+        else
+        {
+            agentData->type = EDM_COMPLEX_TYPE_TYPE;
+        }
+    }
+    return result;
+}
+
+#define isLeapYear(y) ((((y) % 400) == 0) || (((y)%4==0)&&(!((y)%100==0))))
+
+static int daysInAllPreviousMonths(int month)
+{
+    int result = 0;
+    for (int i = 0; i < month; i++)
+    {
+        switch (i)
+        {
+        case 0:
+        case 2:
+        case 4:
+        case 6:
+        case 7:
+        case 9:
+            result += 31;
+            break;
+        case 1:
+            result += 28;
+            break;
+        default:
+            result += 30;
+        }
+    }
+    return result;
+}
+
+/*this function assumes a correctly filled in tm_year, tm_mon and tm_mday and will fill in tm_yday and tm_wday*/
+static void fill_tm_yday_and_tm_wday(struct tm* source)
+{
+    /*to fill in tm_yday the function shall add the number of days in every month, not including the current one*/
+    /*and then it will add the number of days in the current month*/
+    /*1st of Jan is day "0" in a year*/
+    int year = source->tm_year + 1900 + 10000;
+    int nLeapYearsSinceYearMinus9999 = ((year - 1) / 4) - ((year - 1) / 100) + ((year - 1) / 400);
+    source->tm_yday = (daysInAllPreviousMonths(source->tm_mon)) + (source->tm_mday - 1) + ((source->tm_mon > 1 /*1 is Feb*/) && isLeapYear(year));
+    source->tm_wday = ((365 * year + nLeapYearsSinceYearMinus9999) + source->tm_yday) % 7;
+    /*day "0" is 1st jan -9999 (this is how much odata can span*/
+    /*the function shall count days */
+}
+
+/*the following function does the same as  sscanf(pos2, ":%02d", &sec)*/
+/*this function only exists because of optimizing valgrind time, otherwise sscanf would be just as good*/
+static int sscanf2d(const char *pos2, int* sec)
+{
+    int result;
+    size_t position = 1;
+    if (
+        (pos2[0] == ':') &&
+        (scanAndReadNDigitsInt(pos2, &position, sec, 2) == 0)
+        )
+    {
+        result = 1;
+    }
+    else
+    {
+        result = EOF;
+    }
+
+    return result;
+
+}
+
+/*the following function does the same as  sscanf(pos2, "%d", &sec)*/
+/*this function only exists because of optimizing valgrind time, otherwise sscanf would be just as good*/
+static int sscanfd(const char *src, int* dst)
+{
+    int result;
+    char* next;
+    long int temp = strtol(src, &next, 10);
+    if ((src == next) || (((temp == LONG_MAX) || (temp == LONG_MIN)) && (errno != 0)))
+    {
+        result = EOF;
+    }
+    else
+    {
+        (*dst) = (int)temp;
+        result = 1;
+    }
+    return result;
+}
+
+/*the following function does the same as  sscanf(src, "%llu", &dst), but, it changes the src pointer.*/
+static int sscanfllu(const char** src, unsigned long long* dst)
+{
+    int result = 1;
+    char* next;
+    (*dst) = strtoull((*src), &next, 10);
+    if (((*src) == (const char*)next) || (((*dst) == ULLONG_MAX) && (errno != 0)))
+    {
+        result = EOF;
+    }
+    (*src) = (const char*)next;
+    return result;
+}
+
+/*the following function does the same as  sscanf(src, ".%llu", &dst)*/
+static int sscanfdotllu(const char*src, unsigned long long* dst)
+{
+    int result;
+
+    if ((*src) != '.')
+    {
+        /*doesn't start with '.' error out*/
+        result = EOF;
+    }
+    else
+    {
+        src++;
+        result = sscanfllu(&src, dst);
+    }
+
+    return result;
+}
+
+/*the following function does the same as  sscanf(src, "%u", &dst)*/
+static int sscanfu(const char* src, uint32_t* dst)
+{
+    int result;
+    char* next;
+    unsigned long int temp = strtoul(src, &next, 10);
+    if ((src == next) || ((temp == ULONG_MAX) && (errno != 0)))
+    {
+        result = EOF;
+    }
+    else
+    {
+        result = 1;
+        (*dst) = (uint32_t)temp;
+    }
+    return result;
+}
+
+/*the following function does the same as  sscanf(src, "%f", &dst)*/
+static int sscanff(const char*src, float* dst)
+{
+    int result = 1;
+    char* next;
+    (*dst) = strtof(src, &next);
+    if ((src == next) || (((*dst) == HUGE_VALF) && (errno != 0)))
+    {
+        result = EOF;
+    }
+    return result;
+}
+
+/*the following function does the same as  sscanf(src, "%lf", &dst)*/
+static int sscanflf(const char*src, double* dst)
+{
+    int result = 1;
+    char* next;
+    (*dst) = strtod(src, &next);
+    if ((src == next) || (((*dst) == HUGE_VALL) && (errno != 0)))
+    {
+        result = EOF;
+    }
+    return result;
+}
+
+
+/*the below function replaces sscanf(src, "%03d:%02d\"", &hourOffset, &minOffset)*/
+/*return 2 if success*/
+
+static int sscanf3d2d(const char* src, int* hourOffset, int* minOffset)
+{
+    size_t position = 0;
+    int result = EOF;
+    bool isNegative = false;
+
+    if (*src == '+')
+    {
+        position++;
+    }
+    else if (*src == '-')
+    {
+        isNegative = true;
+        position++;
+    }
+
+    if (
+        (scanAndReadNDigitsInt(src, &position, hourOffset, (3-position)) == 0) &&
+        (src[position++] == ':') &&
+        (scanAndReadNDigitsInt(src, &position, minOffset, 2) == 0)
+        )
+    {
+        result = 2;
+    }
+    else
+    {
+        result = 0;
+    }
+    if (isNegative)
+        *hourOffset *= -1;
+
+    return result;
+}
+
+AGENT_DATA_TYPES_RESULT CreateAgentDataType_From_String(const char* source, AGENT_DATA_TYPE_TYPE type, AGENT_DATA_TYPE* agentData)
+{
+
+    AGENT_DATA_TYPES_RESULT result;
+
+    /* Codes_SRS_AGENT_TYPE_SYSTEM_99_073:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is NULL.] */
+    if ((source == NULL) ||
+        /* Codes_SRS_AGENT_TYPE_SYSTEM_99_074:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if agentData is NULL.] */
+        (agentData == NULL))
+    {
+        result = AGENT_DATA_TYPES_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+    }
+    else
+    {
+        /* Codes_SRS_AGENT_TYPE_SYSTEM_99_071:[ CreateAgentDataType_From_String shall create an AGENT_DATA_TYPE from a char* representation of the type indicated by type parameter.] */
+        /* Codes_SRS_AGENT_TYPE_SYSTEM_99_072:[ The implementation for the transformation of the char* source into AGENT_DATA_TYPE shall be type specific.] */
+        switch (type)
+        {
+            default:
+                /* Codes_SRS_AGENT_TYPE_SYSTEM_99_075:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_NOT_IMPLEMENTED if type is not a supported type.] */
+                result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                break;
+
+            /* Codes_SRS_AGENT_TYPE_SYSTEM_99_086:[ EDM_STRING] */
+            case EDM_BOOLEAN_TYPE:
+            {
+                if (strcmp(source, "true") == 0)
+                {
+                    agentData->type = EDM_BOOLEAN_TYPE;
+                    agentData->value.edmBoolean.value = EDM_TRUE;
+                    result = AGENT_DATA_TYPES_OK;
+                }
+                else if (strcmp(source, "false") == 0)
+                {
+                    agentData->type = EDM_BOOLEAN_TYPE;
+                    agentData->value.edmBoolean.value = EDM_FALSE;
+                    result = AGENT_DATA_TYPES_OK;
+                }
+                else
+                {
+                    /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
+                    result = AGENT_DATA_TYPES_INVALID_ARG;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+
+                break;
+            }
+            case EDM_NULL_TYPE:
+            {
+                if (strcmp(source, "null") == 0)
+                {
+                    agentData->type = EDM_NULL_TYPE;
+                    result = AGENT_DATA_TYPES_OK;
+                }
+                else
+                {
+                    /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
+                    result = AGENT_DATA_TYPES_INVALID_ARG;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+
+                break;
+            }
+
+            /* Codes_SRS_AGENT_TYPE_SYSTEM_99_084:[ EDM_SBYTE] */
+            case EDM_SBYTE_TYPE:
+            {
+                int sByteValue;
+                if ((sscanfd(source, &sByteValue) != 1) ||
+                    (sByteValue < -128) ||
+                    (sByteValue > 127))
+                {
+                    /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
+                    result = AGENT_DATA_TYPES_INVALID_ARG;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    agentData->type = EDM_SBYTE_TYPE;
+                    agentData->value.edmSbyte.value = (int8_t)sByteValue;
+                    result = AGENT_DATA_TYPES_OK;
+                }
+
+                break;
+            }
+
+            /* Codes_SRS_AGENT_TYPE_SYSTEM_99_077:[ EDM_BYTE] */
+            case EDM_BYTE_TYPE:
+            {
+                int byteValue;
+                if ((sscanfd(source, &byteValue) != 1) ||
+                    (byteValue < 0) ||
+                    (byteValue > 255))
+                {
+                    /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
+                    result = AGENT_DATA_TYPES_INVALID_ARG;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    agentData->type = EDM_BYTE_TYPE;
+                    agentData->value.edmByte.value = (uint8_t)byteValue;
+                    result = AGENT_DATA_TYPES_OK;
+                }
+
+                break;
+            }
+
+            /* Codes_SRS_AGENT_TYPE_SYSTEM_99_081:[ EDM_INT16] */
+            case EDM_INT16_TYPE:
+            {
+                int int16Value;
+                if ((sscanfd(source, &int16Value) != 1) ||
+                    (int16Value < -32768) ||
+                    (int16Value > 32767))
+                {
+                    /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
+                    result = AGENT_DATA_TYPES_INVALID_ARG;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    agentData->type = EDM_INT16_TYPE;
+                    agentData->value.edmInt16.value = (int16_t)int16Value;
+                    result = AGENT_DATA_TYPES_OK;
+                }
+
+                break;
+            }
+
+            /* Codes_SRS_AGENT_TYPE_SYSTEM_99_082:[ EDM_INT32] */
+            case EDM_INT32_TYPE:
+            {
+                int32_t int32Value;
+                unsigned char isNegative;
+                uint32_t uint32Value;
+                const char* pos;
+                size_t strLength;
+
+                if (source[0] == '-')
+                {
+                    isNegative = 1;
+                    pos = &source[1];
+                }
+                else
+                {
+                    isNegative = 0;
+                    pos = &source[0];
+                }
+
+                strLength = strlen(source);
+
+                if ((sscanfu(pos, &uint32Value) != 1) ||
+                    (strLength > 11) ||
+                    ((uint32Value > 2147483648UL) && isNegative) ||
+                    ((uint32Value > 2147483647UL) && (!isNegative)))
+                {
+                    /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
+                    result = AGENT_DATA_TYPES_INVALID_ARG;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    if (isNegative)
+                    {
+                        if (uint32Value == 2147483648UL)
+                        {
+                           int32Value = -2147483647L - 1L;
+                        }
+                        else
+                        {
+                            int32Value = -(int32_t)uint32Value;
+                        }
+                    }
+                    else
+                    {
+                        int32Value = uint32Value;
+                    }
+
+                    agentData->type = EDM_INT32_TYPE;
+                    agentData->value.edmInt32.value = (int32_t)int32Value;
+                    result = AGENT_DATA_TYPES_OK;
+                }
+
+                break;
+            }
+
+            /* Codes_SRS_AGENT_TYPE_SYSTEM_99_083:[ EDM_INT64] */
+            case EDM_INT64_TYPE:
+            {
+                long long int64Value;
+                unsigned char isNegative;
+                unsigned long long ullValue;
+                const char* pos;
+                size_t strLength;
+
+                if (source[0] == '-')
+                {
+                    isNegative = 1;
+                    pos = &source[1];
+                }
+                else
+                {
+                    isNegative = 0;
+                    pos = &source[0];
+                }
+
+                strLength = strlen(source);
+
+                if ((sscanfllu(&pos, &ullValue) != 1) ||
+                    (strLength > 20) ||
+                    ((ullValue > 9223372036854775808ULL) && isNegative) ||
+                    ((ullValue > 9223372036854775807ULL) && (!isNegative)))
+                {
+                    /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
+                    result = AGENT_DATA_TYPES_INVALID_ARG;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    if (isNegative)
+                    {
+                        if (ullValue == 9223372036854775808ULL)
+                        {
+                            int64Value = -9223372036854775807LL - 1LL;
+                        }
+                        else
+                        {
+                            int64Value = -(long long)ullValue;
+                        }
+                    }
+                    else
+                    {
+                        int64Value = ullValue;
+                    }
+                    agentData->type = EDM_INT64_TYPE;
+                    agentData->value.edmInt64.value = (int64_t)int64Value;
+                    result = AGENT_DATA_TYPES_OK;
+                }
+
+                break;
+            }
+
+            /* Codes_SRS_AGENT_TYPE_SYSTEM_99_085:[ EDM_DATE] */
+            case EDM_DATE_TYPE:
+            {
+                int year;
+                int month;
+                int day;
+                size_t strLength = strlen(source);
+
+                if ((strLength < 2) ||
+                    (source[0] != '"') ||
+                    (source[strLength - 1] != '"'))
+                {
+                    /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
+                    result = AGENT_DATA_TYPES_INVALID_ARG;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    size_t pos = 1;
+                    int sign;
+                    scanOptionalMinusSign(source, 2, &pos, &sign);
+
+                    if ((scanAndReadNDigitsInt(source, &pos, &year, 4) != 0) ||
+                        (source[pos++] != '-') ||
+                        (scanAndReadNDigitsInt(source, &pos, &month, 2) != 0) ||
+                        (source[pos++] != '-') ||
+                        (scanAndReadNDigitsInt(source, &pos, &day, 2) != 0) ||
+                        (Create_AGENT_DATA_TYPE_from_date(agentData, (int16_t)(sign*year), (uint8_t)month, (uint8_t)day) != AGENT_DATA_TYPES_OK))
+                    {
+                        /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
+                        result = AGENT_DATA_TYPES_INVALID_ARG;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                    }
+                    else
+                    {
+                        result = AGENT_DATA_TYPES_OK;
+                    }
+                }
+
+                break;
+            }
+
+            /* Codes_SRS_AGENT_TYPE_SYSTEM_99_078:[ EDM_DATETIMEOFFSET] */
+            case EDM_DATE_TIME_OFFSET_TYPE:
+            {
+                int year;
+                int month;
+                int day;
+                int hour;
+                int min;
+                int sec = 0;
+                int hourOffset;
+                int minOffset;
+                unsigned long long fractionalSeconds = 0;
+                size_t strLength = strlen(source);
+
+                agentData->value.edmDateTimeOffset.hasFractionalSecond = 0;
+                agentData->value.edmDateTimeOffset.hasTimeZone = 0;
+                /* The value of tm_isdst is positive if Daylight Saving Time is in effect, zero if Daylight
+                   Saving Time is not in effect, and negative if the information is not available.*/
+                agentData->value.edmDateTimeOffset.dateTime.tm_isdst = -1;
+
+                if ((strLength < 2) ||
+                    (source[0] != '"') ||
+                    (source[strLength - 1] != '"'))
+                {
+                    /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
+                    result = AGENT_DATA_TYPES_INVALID_ARG;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    size_t pos = 1;
+                    int sign;
+                    scanOptionalMinusSign(source, 2, &pos, &sign);
+
+                    if ((scanAndReadNDigitsInt(source, &pos, &year, 4) != 0) ||
+                        (source[pos++] != '-') ||
+                        (scanAndReadNDigitsInt(source, &pos, &month, 2) != 0) ||
+                        (source[pos++] != '-') ||
+                        (scanAndReadNDigitsInt(source, &pos, &day, 2) != 0) ||
+                        (source[pos++] != 'T') ||
+                        (scanAndReadNDigitsInt(source, &pos, &hour, 2) != 0) ||
+                        (source[pos++] != ':') ||
+                        (scanAndReadNDigitsInt(source, &pos, &min, 2) != 0))
+                    {
+                        /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
+                        result = AGENT_DATA_TYPES_INVALID_ARG;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                    }
+                    else
+                    {
+                        const char* pos2;
+                        year = year*sign;
+                        if ((pos2 = strchr(source, ':')) == NULL)
+                        {
+                            /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
+                            result = AGENT_DATA_TYPES_INVALID_ARG;
+                            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                        }
+                        else
+                        {
+                            pos2 += 3;
+                            if (*pos2 == ':')
+                            {
+                                if (sscanf2d(pos2, &sec) != 1)
+                                {
+                                    pos2 = NULL;
+                                }
+                                else
+                                {
+                                    pos2 += 3;
+                                }
+                            }
+
+                            if ((pos2 != NULL) &&
+                                (*pos2 == '.'))
+                            {
+                                if (sscanfdotllu(pos2, &fractionalSeconds) != 1)
+                                {
+                                    pos2 = NULL;
+                                }
+                                else
+                                {
+                                    pos2++;
+
+                                    agentData->value.edmDateTimeOffset.hasFractionalSecond = 1;
+
+                                    while ((*pos2 != '\0') &&
+                                        (IS_DIGIT(*pos2)))
+                                    {
+                                        pos2++;
+                                    }
+
+                                    if (*pos2 == '\0')
+                                    {
+                                        pos2 = NULL;
+                                    }
+                                }
+                            }
+
+                            if (pos2 == NULL)
+                            {
+                                /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
+                                result = AGENT_DATA_TYPES_INVALID_ARG;
+                                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                            }
+                            else
+                            {
+                                hourOffset = 0;
+                                minOffset = 0;
+
+                                if (sscanf3d2d(pos2, &hourOffset, &minOffset) == 2)
+                                {
+                                    agentData->value.edmDateTimeOffset.hasTimeZone = 1;
+                                }
+
+                                if ((strcmp(pos2, "Z\"") == 0) ||
+                                    agentData->value.edmDateTimeOffset.hasTimeZone)
+                                {
+                                    if ((ValidateDate(year, month, day) != 0) ||
+                                        (hour < 0) ||
+                                        (hour > 23) ||
+                                        (min < 0) ||
+                                        (min > 59) ||
+                                        (sec < 0) ||
+                                        (sec > 59) ||
+                                        (fractionalSeconds > 999999999999) ||
+                                        (hourOffset < -23) ||
+                                        (hourOffset > 23) ||
+                                        (minOffset < 0) ||
+                                        (minOffset > 59))
+                                    {
+                                        /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
+                                        result = AGENT_DATA_TYPES_INVALID_ARG;
+                                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                                    }
+                                    else
+                                    {
+                                        agentData->type = EDM_DATE_TIME_OFFSET_TYPE;
+                                        agentData->value.edmDateTimeOffset.dateTime.tm_year= year-1900;
+                                        agentData->value.edmDateTimeOffset.dateTime.tm_mon = month-1;
+                                        agentData->value.edmDateTimeOffset.dateTime.tm_mday = day;
+                                        agentData->value.edmDateTimeOffset.dateTime.tm_hour = hour;
+                                        agentData->value.edmDateTimeOffset.dateTime.tm_min = min;
+                                        agentData->value.edmDateTimeOffset.dateTime.tm_sec = sec;
+                                        /*fill in tm_wday and tm_yday*/
+                                        fill_tm_yday_and_tm_wday(&agentData->value.edmDateTimeOffset.dateTime);
+                                        agentData->value.edmDateTimeOffset.fractionalSecond = (uint64_t)fractionalSeconds;
+                                        agentData->value.edmDateTimeOffset.timeZoneHour = (int8_t)hourOffset;
+                                        agentData->value.edmDateTimeOffset.timeZoneMinute = (uint8_t)minOffset;
+                                        result = AGENT_DATA_TYPES_OK;
+                                    }
+                                }
+                                else
+                                {
+                                    /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
+                                    result = AGENT_DATA_TYPES_INVALID_ARG;
+                                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                                }
+                            }
+                        }
+                    }
+                }
+
+                break;
+            }
+
+            /* Codes_SRS_AGENT_TYPE_SYSTEM_99_080:[ EDM_DOUBLE] */
+            case EDM_DOUBLE_TYPE:
+            {
+                if (strcmp(source, "\"NaN\"") == 0)
+                {
+                    agentData->type = EDM_DOUBLE_TYPE;
+                    agentData->value.edmDouble.value = NAN;
+                    result = AGENT_DATA_TYPES_OK;
+                }
+                else if (strcmp(source, "\"INF\"") == 0)
+                {
+                    agentData->type = EDM_DOUBLE_TYPE;
+                    agentData->value.edmDouble.value = INFINITY;
+                    result = AGENT_DATA_TYPES_OK;
+                }
+                else if (strcmp(source, "\"-INF\"") == 0)
+                {
+                    agentData->type = EDM_DOUBLE_TYPE;
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4056) /* Known warning for INIFNITY */
+#endif
+                    agentData->value.edmDouble.value = -INFINITY;
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+                    result = AGENT_DATA_TYPES_OK;
+                }
+                else if (sscanflf(source, &(agentData->value.edmDouble.value)) != 1)
+                {
+                    /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
+                    result = AGENT_DATA_TYPES_INVALID_ARG;
+                }
+                else
+                {
+                    agentData->type = EDM_DOUBLE_TYPE;
+                    result = AGENT_DATA_TYPES_OK;
+                }
+                break;
+            }
+
+            /* Codes_SRS_AGENT_TYPE_SYSTEM_99_089:[EDM_SINGLE] */
+            case EDM_SINGLE_TYPE:
+            {
+                if (strcmp(source, "\"NaN\"") == 0)
+                {
+                    agentData->type = EDM_SINGLE_TYPE;
+                    agentData->value.edmSingle.value = NAN;
+                    result = AGENT_DATA_TYPES_OK;
+                }
+                else if (strcmp(source, "\"INF\"") == 0)
+                {
+                    agentData->type = EDM_SINGLE_TYPE;
+                    agentData->value.edmSingle.value = INFINITY;
+                    result = AGENT_DATA_TYPES_OK;
+                }
+                else if (strcmp(source, "\"-INF\"") == 0)
+                {
+                    agentData->type = EDM_SINGLE_TYPE;
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4056) /* Known warning for INIFNITY */
+#endif
+                    agentData->value.edmSingle.value = -INFINITY;
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+result = AGENT_DATA_TYPES_OK;
+                }
+                else if (sscanff(source, &agentData->value.edmSingle.value) != 1)
+                {
+                    /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
+                    result = AGENT_DATA_TYPES_INVALID_ARG;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    agentData->type = EDM_SINGLE_TYPE;
+                    result = AGENT_DATA_TYPES_OK;
+                }
+                break;
+            }
+
+            /* Codes_SRS_AGENT_TYPE_SYSTEM_99_079:[ EDM_DECIMAL] */
+            case EDM_DECIMAL_TYPE:
+            {
+                size_t strLength = strlen(source);
+                if ((strLength < 2) ||
+                    (source[0] != '"') ||
+                    (source[strLength - 1] != '"') ||
+                    (ValidateDecimal(source + 1, strLength - 2) != 0))
+                {
+                    /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
+                    result = AGENT_DATA_TYPES_INVALID_ARG;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    agentData->type = EDM_DECIMAL_TYPE;
+                    agentData->value.edmDecimal.value = STRING_construct_n(source + 1, strLength-2);
+                    if (agentData->value.edmDecimal.value == NULL)
+                    {
+                        /* Codes_SRS_AGENT_TYPE_SYSTEM_99_088:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_ERROR if any other error occurs.] */
+                        result = AGENT_DATA_TYPES_ERROR;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                    }
+                    else
+                    {
+                        result = AGENT_DATA_TYPES_OK;
+                    }
+                }
+                break;
+            }
+
+            /* Codes_SRS_AGENT_TYPE_SYSTEM_99_086:[ EDM_STRING] */
+            case EDM_STRING_TYPE:
+            {
+                size_t strLength = strlen(source);
+                if ((strLength < 2) ||
+                    (source[0] != '"') ||
+                    (source[strLength - 1] != '"'))
+                {
+                    /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
+                    result = AGENT_DATA_TYPES_INVALID_ARG;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    char* temp;
+                    if ((temp = (char*)malloc(strLength - 1)) == NULL)
+                    {
+                        result = AGENT_DATA_TYPES_ERROR;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                    }
+                    else if (memcpy(temp, source + 1, strLength - 2) == NULL)
+                    {
+                        free(temp);
+
+                        result = AGENT_DATA_TYPES_ERROR;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                    }
+                    else
+                    {
+                        // Removes the "
+                        temp[strLength - 2] = 0;
+                        agentData->type = EDM_STRING_TYPE;
+                        agentData->value.edmString.chars = temp;
+                        agentData->value.edmString.length = strLength - 2;
+                        result = AGENT_DATA_TYPES_OK;
+                    }
+                }
+                break;
+            }
+            /* Codes_SRS_AGENT_TYPE_SYSTEM_01_004: [EDM_STRING_NO_QUOTES] */
+            case EDM_STRING_NO_QUOTES_TYPE:
+            {
+                char* temp;
+                size_t strLength = strlen(source);
+                if (mallocAndStrcpy_s(&temp, source) != 0)
+                {
+                    result = AGENT_DATA_TYPES_ERROR;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
+                }
+                else
+                {
+                    agentData->type = EDM_STRING_NO_QUOTES_TYPE;
+                    agentData->value.edmStringNoQuotes.chars = temp;
+                    agentData->value.edmStringNoQuotes.length = strLength;
+                    result = AGENT_DATA_TYPES_OK;
+                }
+                break;
+            }
+            /*Codes_SRS_AGENT_TYPE_SYSTEM_99_097:[ EDM_GUID]*/
+            case EDM_GUID_TYPE:
+            {
+                if (strlen(source) != GUID_STRING_LENGTH)
+                {
+                    result = AGENT_DATA_TYPES_INVALID_ARG;
+                }
+                else
+                {
+                    if (source[0] != '"')
+                    {
+                        result = AGENT_DATA_TYPES_INVALID_ARG;
+                    }
+                    else if (scanMandatory2CapitalHexDigits(source + 1, &(agentData->value.edmGuid.GUID[0])) != 0)
+                    {
+                        result = AGENT_DATA_TYPES_INVALID_ARG;
+                    }
+                    else if (scanMandatory2CapitalHexDigits(source + 3, &(agentData->value.edmGuid.GUID[1])) != 0)
+                    {
+                        result = AGENT_DATA_TYPES_INVALID_ARG;
+                    }
+                    else if (scanMandatory2CapitalHexDigits(source + 5, &(agentData->value.edmGuid.GUID[2])) != 0)
+                    {
+                        result = AGENT_DATA_TYPES_INVALID_ARG;
+                    }
+                    else if (scanMandatory2CapitalHexDigits(source + 7, &(agentData->value.edmGuid.GUID[3])) != 0)
+                    {
+                        result = AGENT_DATA_TYPES_INVALID_ARG;
+                    }
+                    else if (source[9] != '-')
+                    {
+                        result = AGENT_DATA_TYPES_INVALID_ARG;
+                    }
+                    else if (scanMandatory2CapitalHexDigits(source + 10, &(agentData->value.edmGuid.GUID[4])) != 0)
+                    {
+                        result = AGENT_DATA_TYPES_INVALID_ARG;
+                    }
+                    else if (scanMandatory2CapitalHexDigits(source + 12, &(agentData->value.edmGuid.GUID[5])) != 0)
+                    {
+                        result = AGENT_DATA_TYPES_INVALID_ARG;
+                    }
+                    else if (source[14] != '-')
+                    {
+                        result = AGENT_DATA_TYPES_INVALID_ARG;
+                    }
+                    else if (scanMandatory2CapitalHexDigits(source + 15, &(agentData->value.edmGuid.GUID[6])) != 0)
+                    {
+                        result = AGENT_DATA_TYPES_INVALID_ARG;
+                    }
+                    else if (scanMandatory2CapitalHexDigits(source + 17, &(agentData->value.edmGuid.GUID[7])) != 0)
+                    {
+                        result = AGENT_DATA_TYPES_INVALID_ARG;
+                    }
+                    else if (source[19] != '-')
+                    {
+                        result = AGENT_DATA_TYPES_INVALID_ARG;
+                    }
+                    else if (scanMandatory2CapitalHexDigits(source + 20, &(agentData->value.edmGuid.GUID[8])) != 0)
+                    {
+                        result = AGENT_DATA_TYPES_INVALID_ARG;
+                    }
+                    else if (scanMandatory2CapitalHexDigits(source + 22, &(agentData->value.edmGuid.GUID[9])) != 0)
+                    {
+                        result = AGENT_DATA_TYPES_INVALID_ARG;
+                    }
+                    else if (source[24] != '-')
+                    {
+                        result = AGENT_DATA_TYPES_INVALID_ARG;
+                    }
+                    else if (scanMandatory2CapitalHexDigits(source + 25, &(agentData->value.edmGuid.GUID[10])) != 0)
+                    {
+                        result = AGENT_DATA_TYPES_INVALID_ARG;
+                    }
+                    else if (scanMandatory2CapitalHexDigits(source + 27, &(agentData->value.edmGuid.GUID[11])) != 0)
+                    {
+                        result = AGENT_DATA_TYPES_INVALID_ARG;
+                    }
+                    else if (scanMandatory2CapitalHexDigits(source + 29, &(agentData->value.edmGuid.GUID[12])) != 0)
+                    {
+                        result = AGENT_DATA_TYPES_INVALID_ARG;
+                    }
+                    else if (scanMandatory2CapitalHexDigits(source + 31, &(agentData->value.edmGuid.GUID[13])) != 0)
+                    {
+                        result = AGENT_DATA_TYPES_INVALID_ARG;
+                    }
+                    else if (scanMandatory2CapitalHexDigits(source + 33, &(agentData->value.edmGuid.GUID[14])) != 0)
+                    {
+                        result = AGENT_DATA_TYPES_INVALID_ARG;
+                    }
+                    else if (scanMandatory2CapitalHexDigits(source + 35, &(agentData->value.edmGuid.GUID[15])) != 0)
+                    {
+                        result = AGENT_DATA_TYPES_INVALID_ARG;
+                    }
+                    else if (source[37] != '"')
+                    {
+                        result = AGENT_DATA_TYPES_INVALID_ARG;
+                    }
+                    else
+                    {
+                        agentData->type = EDM_GUID_TYPE;
+                        result = AGENT_DATA_TYPES_OK;
+                    }
+                }
+                break;
+            }
+            case EDM_BINARY_TYPE:
+            {
+                size_t sourceLength = strlen(source);
+                if (sourceLength < 2)
+                {
+                    result = AGENT_DATA_TYPES_INVALID_ARG;
+                }
+                else if (sourceLength == 2)
+                {
+                    agentData->type = EDM_BINARY_TYPE;
+                    agentData->value.edmBinary.data = NULL;
+                    agentData->value.edmBinary.size = 0;
+                    result = AGENT_DATA_TYPES_OK;
+                }
+                else
+                {
+                    size_t sourcePosition = 0;
+                    if (source[sourcePosition++] != '"') /*if it doesn't start with a quote then... */
+                    {
+                        result = AGENT_DATA_TYPES_INVALID_ARG;
+                    }
+                    else
+                    {
+                        /*1. read groups of 4 base64 character and transfer those into groups of 3 "normal" characters.
+                        2. read the end of the string and produce from that the ending characters*/
+
+                        /*compute the amount of memory to allocate*/
+                        agentData->value.edmBinary.size = (((sourceLength - 2) + 4) / 4) * 3; /*this is overallocation, shall be trimmed later*/
+                        agentData->value.edmBinary.data = (unsigned char*)malloc(agentData->value.edmBinary.size); /*this is overallocation, shall be trimmed later*/
+                        if (agentData->value.edmBinary.data == NULL)
+                        {
+                            result = AGENT_DATA_TYPES_ERROR;
+                        }
+                        else
+                        {
+
+                            size_t destinationPosition = 0;
+                            size_t consumed;
+                            /*read and store "solid" groups of 4 base64 chars*/
+                            while (scan4base64char(source + sourcePosition, sourceLength - sourcePosition, agentData->value.edmBinary.data + destinationPosition, agentData->value.edmBinary.data + destinationPosition + 1, agentData->value.edmBinary.data + destinationPosition + 2) == 0)
+                            {
+                                sourcePosition += 4;
+                                destinationPosition += 3;
+                            }
+
+                            if (scanbase64b16(source + sourcePosition, sourceLength - sourcePosition, &consumed, agentData->value.edmBinary.data + destinationPosition, agentData->value.edmBinary.data + destinationPosition + 1) == 0)
+                            {
+                                sourcePosition += consumed;
+                                destinationPosition += 2;
+
+                            }
+                            else if (scanbase64b8(source + sourcePosition, sourceLength - sourcePosition, &consumed, agentData->value.edmBinary.data + destinationPosition) == 0)
+                            {
+                                sourcePosition += consumed;
+                                destinationPosition += 1;
+                            }
+
+                            if (source[sourcePosition++] != '"') /*if it doesn't end with " then bail out*/
+                            {
+                                free(agentData->value.edmBinary.data);
+                                agentData->value.edmBinary.data = NULL;
+                                result = AGENT_DATA_TYPES_INVALID_ARG;
+                            }
+                            else if (sourcePosition != sourceLength)
+                            {
+                                free(agentData->value.edmBinary.data);
+                                agentData->value.edmBinary.data = NULL;
+                                result = AGENT_DATA_TYPES_INVALID_ARG;
+                            }
+                            else
+                            {
+                                /*trim the result*/
+                                void* temp = realloc(agentData->value.edmBinary.data, destinationPosition);
+                                if (temp == NULL) /*this is extremely unlikely to happen, but whatever*/
+                                {
+                                    free(agentData->value.edmBinary.data);
+                                    agentData->value.edmBinary.data = NULL;
+                                    result = AGENT_DATA_TYPES_ERROR;
+                                }
+                                else
+                                {
+                                    agentData->type = EDM_BINARY_TYPE;
+                                    agentData->value.edmBinary.data = (unsigned char*)temp;
+                                    agentData->value.edmBinary.size = destinationPosition;
+                                    result = AGENT_DATA_TYPES_OK;
+                                }
+                            }
+                        }
+                    }
+                }
+                break;
+            }
+        }
+    }
+
+    return result;
+}
+
+// extern AGENT_DATA_TYPES_RESULT AgentDataType_GetComplexTypeField(AGENT_DATA_TYPE* agentData, size_t index, COMPLEX_TYPE_FIELD_TYPE* complexField);
+COMPLEX_TYPE_FIELD_TYPE* AgentDataType_GetComplexTypeField(AGENT_DATA_TYPE* agentData, size_t index)
+{
+    COMPLEX_TYPE_FIELD_TYPE* complexField = NULL;
+    if (agentData == NULL)
+    {
+        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, AGENT_DATA_TYPES_INVALID_ARG));
+    }
+    else
+    {
+        if (agentData->type != EDM_COMPLEX_TYPE_TYPE)
+        {
+            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, AGENT_DATA_TYPES_INVALID_ARG));
+        }
+
+        else
+        {
+            if (index >= agentData->value.edmComplexType.nMembers)
+            {
+                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, AGENT_DATA_TYPES_INVALID_ARG));
+            }
+            else
+            {
+                complexField = (COMPLEX_TYPE_FIELD_TYPE*)malloc(sizeof(COMPLEX_TYPE_FIELD_TYPE));
+                if (complexField == NULL)
+                {
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, AGENT_DATA_TYPES_ERROR));
+                }
+                else
+                {
+                    *complexField = agentData->value.edmComplexType.fields[index];
+                }
+            }
+        }
+    }
+    return complexField;
+}
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/codefirst.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/codefirst.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/codefirst.c	(revision 453)
@@ -0,0 +1,1637 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include "azure_c_shared_utility/gballoc.h"
+
+#include "codefirst.h"
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include <stddef.h>
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "iotdevice.h"
+
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(CODEFIRST_RESULT, CODEFIRST_RESULT_VALUES)
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(EXECUTE_COMMAND_RESULT, EXECUTE_COMMAND_RESULT_VALUES)
+
+#define LOG_CODEFIRST_ERROR \
+    LogError("(result = %s)", MU_ENUM_TO_STRING(CODEFIRST_RESULT, result))
+
+typedef struct DEVICE_HEADER_DATA_TAG
+{
+    DEVICE_HANDLE DeviceHandle;
+    const REFLECTED_DATA_FROM_DATAPROVIDER* ReflectedData;
+    SCHEMA_MODEL_TYPE_HANDLE ModelHandle;
+    size_t DataSize;
+    unsigned char* data;
+} DEVICE_HEADER_DATA;
+
+#define COUNT_OF(A) (sizeof(A) / sizeof((A)[0]))
+
+/*design considerations for lazy init of CodeFirst:
+    There are 2 main states: either CodeFirst is in an initialized state, or it is not initialized.
+    The initialized state means there's a g_OverrideSchemaNamespace set (even when it is set to NULL).
+    The uninitialized state means g_OverrideSchemaNamespace is not set.
+
+    To switch to Init state, either call CodeFirst_Init (that sets g_OverrideSchemaNamespace to something)
+    or call directly an API (that will set automatically g_OverrideSchemaNamespace to NULL).
+
+    To switch to NOT INIT state, depending on the method used to initialize:
+        - if CodeFirst_Init was called, then only by a call to CodeFirst_Deinit the switch will take place
+            (note how in this case g_OverrideSchemaNamespace survives destruction of all devices).
+        - if the init has been done "lazily" by an API call then the module returns to uninitialized state
+            when the number of devices reaches zero.
+
+                              +-----------------------------+
+     Start  +---------------->|                             |
+                              |  NOT INIT                   |
+            +---------------->|                             |
+            |                 +------------+----------------+
+            |                              |
+            |                              |
+            |                              | _Init | APIs
+            |                              |
+            |                              v
+            |     +---------------------------------------------------+
+            |     | Init State                                        |
+            |     | +-----------------+       +-----------------+     |
+            |     | |                 |       |                 |     |
+            |     | |  init by _Init  |       |   init by API   |     |
+            |     | +------+----------+       +---------+-------+     |
+            |     |        |                            |             |
+            |     |        |_DeInit                     | nDevices==0 |
+            |     |        |                            |             |
+            |     +--------v----------------+-----------v-------------+
+            |                               |
+            +-------------------------------+
+
+*/
+
+
+#define CODEFIRST_STATE_VALUES \
+    CODEFIRST_STATE_NOT_INIT, \
+    CODEFIRST_STATE_INIT_BY_INIT, \
+    CODEFIRST_STATE_INIT_BY_API
+
+MU_DEFINE_ENUM(CODEFIRST_STATE, CODEFIRST_STATE_VALUES)
+
+static CODEFIRST_STATE g_state = CODEFIRST_STATE_NOT_INIT;
+static const char* g_OverrideSchemaNamespace;
+static size_t g_DeviceCount = 0;
+static DEVICE_HEADER_DATA** g_Devices = NULL;
+
+static void deinitializeDesiredProperties(SCHEMA_MODEL_TYPE_HANDLE model, void* destination)
+{
+    size_t nDesiredProperties;
+    if (Schema_GetModelDesiredPropertyCount(model, &nDesiredProperties) != SCHEMA_OK)
+    {
+        LogError("unexpected error in Schema_GetModelDesiredPropertyCount");
+    }
+    else
+    {
+        size_t nProcessedDesiredProperties = 0;
+        for (size_t i = 0;i < nDesiredProperties;i++)
+        {
+            SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle = Schema_GetModelDesiredPropertyByIndex(model, i);
+            if (desiredPropertyHandle == NULL)
+            {
+                LogError("unexpected error in Schema_GetModelDesiredPropertyByIndex");
+                i = nDesiredProperties;
+            }
+            else
+            {
+                pfDesiredPropertyDeinitialize desiredPropertyDeinitialize = Schema_GetModelDesiredProperty_pfDesiredPropertyDeinitialize(desiredPropertyHandle);
+                if (desiredPropertyDeinitialize == NULL)
+                {
+                    LogError("unexpected error in Schema_GetModelDesiredProperty_pfDesiredPropertyDeinitialize");
+                    i = nDesiredProperties;
+                }
+                else
+                {
+                    size_t offset = Schema_GetModelDesiredProperty_offset(desiredPropertyHandle);
+                    desiredPropertyDeinitialize((char*)destination + offset);
+                    nProcessedDesiredProperties++;
+                }
+            }
+        }
+
+        if (nDesiredProperties == nProcessedDesiredProperties)
+        {
+            /*recursively go in the model and initialize the other fields*/
+            size_t nModelInModel;
+            if (Schema_GetModelModelCount(model, &nModelInModel) != SCHEMA_OK)
+            {
+                LogError("unexpected error in Schema_GetModelModelCount");
+            }
+            else
+            {
+                size_t nProcessedModelInModel = 0;
+                for (size_t i = 0; i < nModelInModel;i++)
+                {
+                    SCHEMA_MODEL_TYPE_HANDLE modelInModel = Schema_GetModelModelyByIndex(model, i);
+                    if (modelInModel == NULL)
+                    {
+                        LogError("unexpected failure in Schema_GetModelModelyByIndex");
+                        i = nModelInModel;
+                    }
+                    else
+                    {
+                        size_t offset = Schema_GetModelModelByIndex_Offset(model, i);
+                        deinitializeDesiredProperties(modelInModel, (char*)destination + offset);
+                        nProcessedModelInModel++;
+                    }
+                }
+
+                if (nProcessedModelInModel == nModelInModel)
+                {
+                    /*all is fine... */
+                }
+            }
+        }
+    }
+}
+
+static void DestroyDevice(DEVICE_HEADER_DATA* deviceHeader)
+{
+    /* Codes_SRS_CODEFIRST_99_085:[CodeFirst_DestroyDevice shall free all resources associated with a device.] */
+    /* Codes_SRS_CODEFIRST_99_087:[In order to release the device handle, CodeFirst_DestroyDevice shall call Device_Destroy.] */
+
+    Device_Destroy(deviceHeader->DeviceHandle);
+    free(deviceHeader->data);
+    free(deviceHeader);
+}
+
+static CODEFIRST_RESULT buildStructTypes(SCHEMA_HANDLE schemaHandle, const REFLECTED_DATA_FROM_DATAPROVIDER* reflectedData)
+{
+    CODEFIRST_RESULT result = CODEFIRST_OK;
+
+    const REFLECTED_SOMETHING* something;
+    for (something = reflectedData->reflectedData; something != NULL; something = something->next)
+    {
+        if (something->type == REFLECTION_STRUCT_TYPE)
+        {
+            SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle;
+            structTypeHandle = Schema_CreateStructType(schemaHandle, something->what.structure.name);
+
+            if (structTypeHandle == NULL)
+            {
+                /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
+                result = CODEFIRST_SCHEMA_ERROR;
+                LogError("create struct failed %s", MU_ENUM_TO_STRING(CODEFIRST_RESULT, result));
+                break;
+            }
+            else
+            {
+                const REFLECTED_SOMETHING* maybeField;
+                /*look for the field... */
+                for (maybeField = reflectedData->reflectedData; maybeField != NULL; maybeField = maybeField->next)
+                {
+                    if (maybeField->type == REFLECTION_FIELD_TYPE)
+                    {
+                        if (strcmp(maybeField->what.field.structName, something->what.structure.name) == 0)
+                        {
+                            if (Schema_AddStructTypeProperty(structTypeHandle, maybeField->what.field.fieldName, maybeField->what.field.fieldType) != SCHEMA_OK)
+                            {
+                                /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
+                                result = CODEFIRST_SCHEMA_ERROR;
+                                LogError("add struct property failed %s", MU_ENUM_TO_STRING(CODEFIRST_RESULT, result));
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+static CODEFIRST_RESULT buildModel(SCHEMA_HANDLE schemaHandle, const REFLECTED_DATA_FROM_DATAPROVIDER* reflectedData, const REFLECTED_SOMETHING* modelReflectedData)
+{
+    CODEFIRST_RESULT result = CODEFIRST_OK;
+    const REFLECTED_SOMETHING* something;
+    SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle;
+
+    modelTypeHandle = Schema_GetModelByName(schemaHandle, modelReflectedData->what.model.name);
+    if (modelTypeHandle == NULL)
+    {
+        /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
+        result = CODEFIRST_SCHEMA_ERROR;
+        LogError("cannot get model %s %s", modelReflectedData->what.model.name, MU_ENUM_TO_STRING(CODEFIRST_RESULT, result));
+        goto out;
+    }
+
+    for (something = reflectedData->reflectedData; something != NULL; something = something->next)
+    {
+        /* looking for all elements that belong to a model: properties and actions */
+        if ((something->type == REFLECTION_PROPERTY_TYPE) &&
+            (strcmp(something->what.property.modelName, modelReflectedData->what.model.name) == 0))
+        {
+            SCHEMA_MODEL_TYPE_HANDLE childModelHande = Schema_GetModelByName(schemaHandle, something->what.property.type);
+
+            /* if this is a model type use the appropriate APIs for it */
+            if (childModelHande != NULL)
+            {
+                if (Schema_AddModelModel(modelTypeHandle, something->what.property.name, childModelHande, something->what.property.offset, NULL) != SCHEMA_OK)
+                {
+                    /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
+                    result = CODEFIRST_SCHEMA_ERROR;
+                    LogError("add model failed %s", MU_ENUM_TO_STRING(CODEFIRST_RESULT, result));
+                    goto out;
+                }
+            }
+            else
+            {
+                if (Schema_AddModelProperty(modelTypeHandle, something->what.property.name, something->what.property.type) != SCHEMA_OK)
+                {
+                    /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
+                    result = CODEFIRST_SCHEMA_ERROR;
+                    LogError("add property failed %s", MU_ENUM_TO_STRING(CODEFIRST_RESULT, result));
+                    goto out;
+                }
+            }
+        }
+
+        if ((something->type == REFLECTION_REPORTED_PROPERTY_TYPE) &&
+            (strcmp(something->what.reportedProperty.modelName, modelReflectedData->what.model.name) == 0))
+        {
+            SCHEMA_MODEL_TYPE_HANDLE childModelHande = Schema_GetModelByName(schemaHandle, something->what.reportedProperty.type);
+
+            /* if this is a model type use the appropriate APIs for it */
+            if (childModelHande != NULL)
+            {
+                if (Schema_AddModelModel(modelTypeHandle, something->what.reportedProperty.name, childModelHande, something->what.reportedProperty.offset, NULL) != SCHEMA_OK)
+                {
+                    /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
+                    result = CODEFIRST_SCHEMA_ERROR;
+                    LogError("add model failed %s", MU_ENUM_TO_STRING(CODEFIRST_RESULT, result));
+                    goto out;
+                }
+            }
+            else
+            {
+                if (Schema_AddModelReportedProperty(modelTypeHandle, something->what.reportedProperty.name, something->what.reportedProperty.type) != SCHEMA_OK)
+                {
+                    /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
+                    result = CODEFIRST_SCHEMA_ERROR;
+                    LogError("add reported property failed %s", MU_ENUM_TO_STRING(CODEFIRST_RESULT, result));
+                    goto out;
+                }
+            }
+        }
+
+        if ((something->type == REFLECTION_DESIRED_PROPERTY_TYPE) &&
+            (strcmp(something->what.desiredProperty.modelName, modelReflectedData->what.model.name) == 0))
+        {
+            SCHEMA_MODEL_TYPE_HANDLE childModelHande = Schema_GetModelByName(schemaHandle, something->what.desiredProperty.type);
+
+            /* if this is a model type use the appropriate APIs for it */
+            if (childModelHande != NULL)
+            {
+                if (Schema_AddModelModel(modelTypeHandle, something->what.desiredProperty.name, childModelHande, something->what.desiredProperty.offset, something->what.desiredProperty.onDesiredProperty) != SCHEMA_OK)
+                {
+                    /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
+                    result = CODEFIRST_SCHEMA_ERROR;
+                    LogError("add model failed %s", MU_ENUM_TO_STRING(CODEFIRST_RESULT, result));
+                    goto out;
+                }
+            }
+            else
+            {
+                if (Schema_AddModelDesiredProperty(modelTypeHandle,
+                    something->what.desiredProperty.name,
+                    something->what.desiredProperty.type,
+                    something->what.desiredProperty.FromAGENT_DATA_TYPE,
+                    something->what.desiredProperty.desiredPropertInitialize,
+                    something->what.desiredProperty.desiredPropertDeinitialize,
+                    something->what.desiredProperty.offset,
+                    something->what.desiredProperty.onDesiredProperty) != SCHEMA_OK)
+                {
+                    /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
+                    result = CODEFIRST_SCHEMA_ERROR;
+                    LogError("add desired property failed %s", MU_ENUM_TO_STRING(CODEFIRST_RESULT, result));
+                    goto out;
+                }
+            }
+        }
+
+        if ((something->type == REFLECTION_ACTION_TYPE) &&
+            (strcmp(something->what.action.modelName, modelReflectedData->what.model.name) == 0))
+        {
+            SCHEMA_ACTION_HANDLE actionHandle;
+            size_t i;
+
+            if ((actionHandle = Schema_CreateModelAction(modelTypeHandle, something->what.action.name)) == NULL)
+            {
+                /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
+                result = CODEFIRST_SCHEMA_ERROR;
+                LogError("add model action failed %s", MU_ENUM_TO_STRING(CODEFIRST_RESULT, result));
+                goto out;
+            }
+
+            for (i = 0; i < something->what.action.nArguments; i++)
+            {
+                if (Schema_AddModelActionArgument(actionHandle, something->what.action.arguments[i].name, something->what.action.arguments[i].type) != SCHEMA_OK)
+                {
+                    /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
+                    result = CODEFIRST_SCHEMA_ERROR;
+                    LogError("add model action argument failed %s", MU_ENUM_TO_STRING(CODEFIRST_RESULT, result));
+                    goto out;
+                }
+            }
+        }
+
+        if ((something->type == REFLECTION_METHOD_TYPE) &&
+            (strcmp(something->what.method.modelName, modelReflectedData->what.model.name) == 0))
+        {
+            SCHEMA_METHOD_HANDLE methodHandle;
+            size_t i;
+
+            if ((methodHandle = Schema_CreateModelMethod(modelTypeHandle, something->what.method.name)) == NULL)
+            {
+                /*Codes_SRS_CODEFIRST_99_076: [ If any Schema APIs fail, CodeFirst_RegisterSchema shall return NULL. ]*/
+                result = CODEFIRST_SCHEMA_ERROR;
+                LogError("add model method failed %s", MU_ENUM_TO_STRING(CODEFIRST_RESULT, result));
+                goto out;
+            }
+
+            for (i = 0; i < something->what.method.nArguments; i++)
+            {
+                if (Schema_AddModelMethodArgument(methodHandle, something->what.method.arguments[i].name, something->what.method.arguments[i].type) != SCHEMA_OK)
+                {
+                    /*Codes_SRS_CODEFIRST_99_076: [ If any Schema APIs fail, CodeFirst_RegisterSchema shall return NULL. ]*/
+                    result = CODEFIRST_SCHEMA_ERROR;
+                    LogError("add model method argument failed %s", MU_ENUM_TO_STRING(CODEFIRST_RESULT, result));
+                    goto out;
+                }
+            }
+        }
+    }
+
+out:
+    return result;
+}
+
+static CODEFIRST_RESULT buildModelTypes(SCHEMA_HANDLE schemaHandle, const REFLECTED_DATA_FROM_DATAPROVIDER* reflectedData)
+{
+    CODEFIRST_RESULT result = CODEFIRST_OK;
+    const REFLECTED_SOMETHING* something;
+
+    /* first have a pass and add all the model types */
+    for (something = reflectedData->reflectedData; something != NULL; something = something->next)
+    {
+        if (something->type == REFLECTION_MODEL_TYPE)
+        {
+            if (Schema_CreateModelType(schemaHandle, something->what.model.name) == NULL)
+            {
+                /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
+                result = CODEFIRST_SCHEMA_ERROR;
+                LogError("create model failed %s", MU_ENUM_TO_STRING(CODEFIRST_RESULT, result));
+                goto out;
+            }
+        }
+    }
+
+    for (something = reflectedData->reflectedData; something != NULL; something = something->next)
+    {
+        if (something->type == REFLECTION_MODEL_TYPE)
+        {
+            result = buildModel(schemaHandle, reflectedData, something);
+            if (result != CODEFIRST_OK)
+            {
+                break;
+            }
+        }
+    }
+
+out:
+    return result;
+}
+
+static CODEFIRST_RESULT CodeFirst_Init_impl(const char* overrideSchemaNamespace, bool calledFromCodeFirst_Init)
+{
+    /*shall build the default EntityContainer*/
+    CODEFIRST_RESULT result;
+
+    if (g_state != CODEFIRST_STATE_NOT_INIT)
+    {
+        /*Codes_SRS_CODEFIRST_99_003:[ If the module is already initialized, the initialization shall fail and the return value shall be CODEFIRST_ALREADY_INIT.]*/
+        result = CODEFIRST_ALREADY_INIT;
+        if(calledFromCodeFirst_Init) /*do not log this error when APIs attempt lazy init*/
+        {
+             LogError("CodeFirst was already init %s", MU_ENUM_TO_STRING(CODEFIRST_RESULT, result));
+        }
+    }
+    else
+    {
+        g_DeviceCount = 0;
+        g_OverrideSchemaNamespace = overrideSchemaNamespace;
+        g_Devices = NULL;
+
+        /*Codes_SRS_CODEFIRST_99_002:[ CodeFirst_Init shall initialize the CodeFirst module. If initialization is successful, it shall return CODEFIRST_OK.]*/
+        g_state = calledFromCodeFirst_Init? CODEFIRST_STATE_INIT_BY_INIT: CODEFIRST_STATE_INIT_BY_API;
+        result = CODEFIRST_OK;
+    }
+    return result;
+}
+
+/*Codes_SRS_CODEFIRST_99_002:[ CodeFirst_Init shall initialize the CodeFirst module. If initialization is successful, it shall return CODEFIRST_OK.]*/
+CODEFIRST_RESULT CodeFirst_Init(const char* overrideSchemaNamespace)
+{
+    return CodeFirst_Init_impl(overrideSchemaNamespace, true);
+}
+
+void CodeFirst_Deinit(void)
+{
+    /*Codes_SRS_CODEFIRST_99_006:[If the module is not previously initialed, CodeFirst_Deinit shall do nothing.]*/
+    if (g_state != CODEFIRST_STATE_INIT_BY_INIT)
+    {
+        LogError("CodeFirst_Deinit called when CodeFirst was not initialized by CodeFirst_Init");
+    }
+    else
+    {
+        size_t i;
+
+        /*Codes_SRS_CODEFIRST_99_005:[ CodeFirst_Deinit shall deinitialize the module, freeing all the resources and placing the module in an uninitialized state.]*/
+        for (i = 0; i < g_DeviceCount; i++)
+        {
+            DestroyDevice(g_Devices[i]);
+        }
+
+        free(g_Devices);
+        g_Devices = NULL;
+        g_DeviceCount = 0;
+
+        g_state = CODEFIRST_STATE_NOT_INIT;
+    }
+}
+
+static const REFLECTED_SOMETHING* FindModelInCodeFirstMetadata(const REFLECTED_SOMETHING* reflectedData, const char* modelName)
+{
+    const REFLECTED_SOMETHING* result;
+
+    for (result = reflectedData; result != NULL; result = result->next)
+    {
+        if ((result->type == REFLECTION_MODEL_TYPE) &&
+            (strcmp(result->what.model.name, modelName) == 0))
+        {
+            /* found model type */
+            break;
+        }
+    }
+
+    return result;
+}
+
+static const REFLECTED_SOMETHING* FindChildModelInCodeFirstMetadata(const REFLECTED_SOMETHING* reflectedData, const REFLECTED_SOMETHING* startModel, const char* relativePath, size_t* offset)
+{
+    const REFLECTED_SOMETHING* result = startModel;
+    *offset = 0;
+
+    /* Codes_SRS_CODEFIRST_99_139:[If the relativeActionPath is empty then the action shall be looked up in the device model.] */
+    while ((*relativePath != 0) && (result != NULL))
+    {
+        /* Codes_SRS_CODEFIRST_99_142:[The relativeActionPath argument shall be in the format "childModel1/childModel2/.../childModelN".] */
+        const REFLECTED_SOMETHING* childModelProperty;
+        size_t propertyNameLength;
+        const char* slashPos = strchr(relativePath, '/');
+        if (slashPos == NULL)
+        {
+            slashPos = &relativePath[strlen(relativePath)];
+        }
+
+        propertyNameLength = slashPos - relativePath;
+
+        for (childModelProperty = reflectedData; childModelProperty != NULL; childModelProperty = childModelProperty->next)
+        {
+            if ((childModelProperty->type == REFLECTION_PROPERTY_TYPE) &&
+                (strcmp(childModelProperty->what.property.modelName, result->what.model.name) == 0) &&
+                (strncmp(childModelProperty->what.property.name, relativePath, propertyNameLength) == 0) &&
+                (strlen(childModelProperty->what.property.name) == propertyNameLength))
+            {
+                /* property found, now let's find the model */
+                /* Codes_SRS_CODEFIRST_99_140:[CodeFirst_InvokeAction shall pass to the action wrapper that it calls a pointer to the model where the action is defined.] */
+                *offset += childModelProperty->what.property.offset;
+                break;
+            }
+        }
+
+        if (childModelProperty == NULL)
+        {
+            /* not found */
+            result = NULL;
+        }
+        else
+        {
+            result = FindModelInCodeFirstMetadata(reflectedData, childModelProperty->what.property.type);
+        }
+
+        relativePath = slashPos;
+    }
+
+    return result;
+}
+
+EXECUTE_COMMAND_RESULT CodeFirst_InvokeAction(DEVICE_HANDLE deviceHandle, void* callbackUserContext, const char* relativeActionPath, const char* actionName, size_t parameterCount, const AGENT_DATA_TYPE* parameterValues)
+{
+    EXECUTE_COMMAND_RESULT result;
+    DEVICE_HEADER_DATA* deviceHeader = (DEVICE_HEADER_DATA*)callbackUserContext;
+
+    /*Codes_SRS_CODEFIRST_99_068:[ If the function is called before CodeFirst is initialized then EXECUTE_COMMAND_ERROR shall be returned.] */
+    if (g_state == CODEFIRST_STATE_NOT_INIT)
+    {
+        result = EXECUTE_COMMAND_ERROR;
+        LogError("CodeFirst_InvokeAction called before init has an error %s ", MU_ENUM_TO_STRING(EXECUTE_COMMAND_RESULT, result));
+    }
+    /*Codes_SRS_CODEFIRST_99_066:[ If actionName, relativeActionPath or deviceHandle is NULL then EXECUTE_COMMAND_ERROR shall be returned*/
+    else if ((actionName == NULL) ||
+        (deviceHandle == NULL) ||
+        (relativeActionPath == NULL))
+    {
+        result = EXECUTE_COMMAND_ERROR;
+        LogError("action Name is NULL %s ", MU_ENUM_TO_STRING(EXECUTE_COMMAND_RESULT, result));
+    }
+    /*Codes_SRS_CODEFIRST_99_067:[ If parameterCount is greater than zero and parameterValues is NULL then EXECUTE_COMMAND_ERROR shall be returned.]*/
+    else if ((parameterCount > 0) && (parameterValues == NULL))
+    {
+        result = EXECUTE_COMMAND_ERROR;
+        LogError("parameterValues error %s ", MU_ENUM_TO_STRING(EXECUTE_COMMAND_RESULT, result));
+    }
+    /*Codes_SRS_CODEFIRST_99_200:[ If deviceHeader (callbackUserContext) is NULL then EXECUTE_COMMAND_ERROR shall be returned.]*/
+    else if (deviceHeader == NULL)
+    {
+        result = EXECUTE_COMMAND_ERROR;
+        LogError("callback User Context error %s ", MU_ENUM_TO_STRING(EXECUTE_COMMAND_RESULT, result));
+    }
+    else
+    {
+        const REFLECTED_SOMETHING* something;
+        const REFLECTED_SOMETHING* childModel;
+        const char* modelName;
+        size_t offset;
+
+        modelName = Schema_GetModelName(deviceHeader->ModelHandle);
+
+        if (((childModel = FindModelInCodeFirstMetadata(deviceHeader->ReflectedData->reflectedData, modelName)) == NULL) ||
+            /* Codes_SRS_CODEFIRST_99_138:[The relativeActionPath argument shall be used by CodeFirst_InvokeAction to find the child model where the action is declared.] */
+            ((childModel = FindChildModelInCodeFirstMetadata(deviceHeader->ReflectedData->reflectedData, childModel, relativeActionPath, &offset)) == NULL))
+        {
+            /*Codes_SRS_CODEFIRST_99_141:[If a child model specified in the relativeActionPath argument cannot be found by CodeFirst_InvokeAction, it shall return EXECUTE_COMMAND_ERROR.] */
+            result = EXECUTE_COMMAND_ERROR;
+            LogError("action %s was not found %s ", actionName, MU_ENUM_TO_STRING(EXECUTE_COMMAND_RESULT, result));
+        }
+        else
+        {
+            /* Codes_SRS_CODEFIRST_99_062:[ When CodeFirst_InvokeAction is called it shall look through the codefirst metadata associated with a specific device for a previously declared action (function) named actionName.]*/
+            /* Codes_SRS_CODEFIRST_99_078:[If such a function is not found then the function shall return EXECUTE_COMMAND_ERROR.]*/
+            result = EXECUTE_COMMAND_ERROR;
+            for (something = deviceHeader->ReflectedData->reflectedData; something != NULL; something = something->next)
+            {
+                if ((something->type == REFLECTION_ACTION_TYPE) &&
+                    (strcmp(actionName, something->what.action.name) == 0) &&
+                    (strcmp(childModel->what.model.name, something->what.action.modelName) == 0))
+                {
+                    /*Codes_SRS_CODEFIRST_99_063:[ If the function is found, then CodeFirst shall call the wrapper of the found function inside the data provider. The wrapper is linked in the reflected data to the function name. The wrapper shall be called with the same arguments as CodeFirst_InvokeAction has been called.]*/
+                    /*Codes_SRS_CODEFIRST_99_064:[ If the wrapper call succeeds then CODEFIRST_OK shall be returned. ]*/
+                    /*Codes_SRS_CODEFIRST_99_065:[ For all the other return values CODEFIRST_ACTION_EXECUTION_ERROR shall be returned.]*/
+                    /* Codes_SRS_CODEFIRST_99_140:[CodeFirst_InvokeAction shall pass to the action wrapper that it calls a pointer to the model where the action is defined.] */
+                    /*Codes_SRS_CODEFIRST_02_013: [The wrapper's return value shall be returned.]*/
+                    result = something->what.action.wrapper(deviceHeader->data + offset, parameterCount, parameterValues);
+                    break;
+                }
+            }
+        }
+    }
+
+    if (result == EXECUTE_COMMAND_ERROR)
+    {
+        LogError(" %s ", MU_ENUM_TO_STRING(EXECUTE_COMMAND_RESULT, result));
+    }
+    return result;
+}
+
+METHODRETURN_HANDLE CodeFirst_InvokeMethod(DEVICE_HANDLE deviceHandle, void* callbackUserContext, const char* relativeMethodPath, const char* methodName, size_t parameterCount, const AGENT_DATA_TYPE* parameterValues)
+{
+    METHODRETURN_HANDLE result;
+    DEVICE_HEADER_DATA* deviceHeader = (DEVICE_HEADER_DATA*)callbackUserContext;
+
+    if (g_state == CODEFIRST_STATE_NOT_INIT)
+    {
+        result = NULL;
+        LogError("CodeFirst_InvokeMethod called before CodeFirst_Init");
+    }
+    else if ((methodName == NULL) ||
+        (deviceHandle == NULL) ||
+        (relativeMethodPath == NULL))
+    {
+        result = NULL;
+        LogError("invalid args: DEVICE_HANDLE deviceHandle=%p, void* callbackUserContext=%p, const char* relativeMethodPath=%p, const char* methodName=%p, size_t parameterCount=%lu, const AGENT_DATA_TYPE* parameterValues=%p",
+            deviceHandle, callbackUserContext, relativeMethodPath, methodName, (unsigned long)parameterCount, parameterValues);
+    }
+    else if ((parameterCount > 0) && (parameterValues == NULL))
+    {
+        result = NULL;
+        LogError("parameterValues error ");
+    }
+    else if (deviceHeader == NULL)
+    {
+        result = NULL;
+        LogError("callback User Context error ");
+    }
+    else
+    {
+        const REFLECTED_SOMETHING* something;
+        const REFLECTED_SOMETHING* childModel;
+        const char* modelName;
+        size_t offset;
+
+        modelName = Schema_GetModelName(deviceHeader->ModelHandle);
+
+        if (((childModel = FindModelInCodeFirstMetadata(deviceHeader->ReflectedData->reflectedData, modelName)) == NULL) ||
+            ((childModel = FindChildModelInCodeFirstMetadata(deviceHeader->ReflectedData->reflectedData, childModel, relativeMethodPath, &offset)) == NULL))
+        {
+            result = NULL;
+            LogError("method %s was not found", methodName);
+        }
+        else
+        {
+            result = NULL;
+            for (something = deviceHeader->ReflectedData->reflectedData; something != NULL; something = something->next)
+            {
+                if ((something->type == REFLECTION_METHOD_TYPE) &&
+                    (strcmp(methodName, something->what.method.name) == 0) &&
+                    (strcmp(childModel->what.model.name, something->what.method.modelName) == 0))
+                {
+                    break; /*found...*/
+                }
+            }
+
+            if (something == NULL)
+            {
+                LogError("method \"%s\" not found", methodName);
+                result = NULL;
+            }
+            else
+            {
+                result = something->what.method.wrapper(deviceHeader->data + offset, parameterCount, parameterValues);
+                if (result == NULL)
+                {
+                    LogError("method \"%s\" execution error (returned NULL)", methodName);
+                }
+            }
+        }
+    }
+    return result;
+}
+
+
+/* Codes_SRS_CODEFIRST_99_002:[ CodeFirst_RegisterSchema shall create the schema information and give it to the Schema module for one schema, identified by the metadata argument. On success, it shall return a handle to the schema.] */
+SCHEMA_HANDLE CodeFirst_RegisterSchema(const char* schemaNamespace, const REFLECTED_DATA_FROM_DATAPROVIDER* metadata)
+{
+    SCHEMA_HANDLE result;
+    /*Codes_SRS_CODEFIRST_02_048: [ If schemaNamespace is NULL then CodeFirst_RegisterSchema shall fail and return NULL. ]*/
+    /*Codes_SRS_CODEFIRST_02_049: [ If metadata is NULL then CodeFirst_RegisterSchema shall fail and return NULL. ]*/
+    if (
+        (schemaNamespace == NULL) ||
+        (metadata == NULL)
+        )
+    {
+        LogError("invalid arg const char* schemaNamespace=%p, const REFLECTED_DATA_FROM_DATAPROVIDER* metadata=%p", schemaNamespace, metadata);
+        result = NULL;
+    }
+    else
+    {
+        if (g_OverrideSchemaNamespace != NULL)
+        {
+            schemaNamespace = g_OverrideSchemaNamespace;
+        }
+
+        /* Codes_SRS_CODEFIRST_99_121:[If the schema has already been registered, CodeFirst_RegisterSchema shall return its handle.] */
+        result = Schema_GetSchemaByNamespace(schemaNamespace);
+        if (result == NULL)
+        {
+            if ((result = Schema_Create(schemaNamespace, (void*)metadata)) == NULL)
+            {
+                /* Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CodeFirst_RegisterSchema shall return NULL.] */
+                result = NULL;
+                LogError("schema init failed %s", MU_ENUM_TO_STRING(CODEFIRST_RESULT, CODEFIRST_SCHEMA_ERROR));
+            }
+            else
+            {
+                if ((buildStructTypes(result, metadata) != CODEFIRST_OK) ||
+                    (buildModelTypes(result, metadata) != CODEFIRST_OK))
+                {
+                    Schema_Destroy(result);
+                    result = NULL;
+                }
+                else
+                {
+                    /* do nothing, everything is OK */
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+AGENT_DATA_TYPE_TYPE CodeFirst_GetPrimitiveType(const char* typeName)
+{
+#ifndef NO_FLOATS
+    if (strcmp(typeName, "double") == 0)
+    {
+        return EDM_DOUBLE_TYPE;
+    }
+    else if (strcmp(typeName, "float") == 0)
+    {
+        return EDM_SINGLE_TYPE;
+    }
+    else
+#endif
+    if (strcmp(typeName, "int") == 0)
+    {
+        return EDM_INT32_TYPE;
+    }
+    else if (strcmp(typeName, "long") == 0)
+    {
+        return EDM_INT64_TYPE;
+    }
+    else if (strcmp(typeName, "int8_t") == 0)
+    {
+        return EDM_SBYTE_TYPE;
+    }
+    else if (strcmp(typeName, "uint8_t") == 0)
+    {
+        return EDM_BYTE_TYPE;
+    }
+    else if (strcmp(typeName, "int16_t") == 0)
+    {
+        return EDM_INT16_TYPE;
+    }
+    else if (strcmp(typeName, "int32_t") == 0)
+    {
+        return EDM_INT32_TYPE;
+    }
+    else if (strcmp(typeName, "int64_t") == 0)
+    {
+        return EDM_INT64_TYPE;
+    }
+    else if (
+        (strcmp(typeName, "_Bool") == 0) ||
+        (strcmp(typeName, "bool") == 0)
+        )
+    {
+        return EDM_BOOLEAN_TYPE;
+    }
+    else if (strcmp(typeName, "ascii_char_ptr") == 0)
+    {
+        return EDM_STRING_TYPE;
+    }
+    else if (strcmp(typeName, "ascii_char_ptr_no_quotes") == 0)
+    {
+        return EDM_STRING_NO_QUOTES_TYPE;
+    }
+    else if (strcmp(typeName, "EDM_DATE_TIME_OFFSET") == 0)
+    {
+        return EDM_DATE_TIME_OFFSET_TYPE;
+    }
+    else if (strcmp(typeName, "EDM_GUID") == 0)
+    {
+        return EDM_GUID_TYPE;
+    }
+    else if (strcmp(typeName, "EDM_BINARY") == 0)
+    {
+        return EDM_BINARY_TYPE;
+    }
+    else
+    {
+        return EDM_NO_TYPE;
+    }
+}
+
+static void initializeDesiredProperties(SCHEMA_MODEL_TYPE_HANDLE model, void* destination)
+{
+    /*this function assumes that at the address given by destination there is an instance of a model*/
+    /*some constituents of the model need to be initialized - ascii_char_ptr for example should be set to NULL*/
+
+    size_t nDesiredProperties;
+    if (Schema_GetModelDesiredPropertyCount(model, &nDesiredProperties) != SCHEMA_OK)
+    {
+        LogError("unexpected error in Schema_GetModelDesiredPropertyCount");
+    }
+    else
+    {
+        size_t nProcessedDesiredProperties = 0;
+        for (size_t i = 0;i < nDesiredProperties;i++)
+        {
+            SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle = Schema_GetModelDesiredPropertyByIndex(model, i);
+            if (desiredPropertyHandle == NULL)
+            {
+                LogError("unexpected error in Schema_GetModelDesiredPropertyByIndex");
+                i = nDesiredProperties;
+            }
+            else
+            {
+                pfDesiredPropertyInitialize desiredPropertyInitialize = Schema_GetModelDesiredProperty_pfDesiredPropertyInitialize(desiredPropertyHandle);
+                if (desiredPropertyInitialize == NULL)
+                {
+                    LogError("unexpected error in Schema_GetModelDesiredProperty_pfDesiredPropertyInitialize");
+                    i = nDesiredProperties;
+                }
+                else
+                {
+                    /*Codes_SRS_CODEFIRST_02_036: [ CodeFirst_CreateDevice shall initialize all the desired properties to their default values. ]*/
+                    size_t offset = Schema_GetModelDesiredProperty_offset(desiredPropertyHandle);
+                    desiredPropertyInitialize((char*)destination + offset);
+                    nProcessedDesiredProperties++;
+                }
+            }
+        }
+
+        if (nDesiredProperties == nProcessedDesiredProperties)
+        {
+            /*recursively go in the model and initialize the other fields*/
+            size_t nModelInModel;
+            if (Schema_GetModelModelCount(model, &nModelInModel) != SCHEMA_OK)
+            {
+                LogError("unexpected error in Schema_GetModelModelCount");
+            }
+            else
+            {
+                size_t nProcessedModelInModel = 0;
+                for (size_t i = 0; i < nModelInModel;i++)
+                {
+                    SCHEMA_MODEL_TYPE_HANDLE modelInModel = Schema_GetModelModelyByIndex(model, i);
+                    if (modelInModel == NULL)
+                    {
+                        LogError("unexpected failure in Schema_GetModelModelyByIndex");
+                        i = nModelInModel;
+                    }
+                    else
+                    {
+                        size_t offset = Schema_GetModelModelByIndex_Offset(model, i);
+                        initializeDesiredProperties(modelInModel, (char*)destination + offset);
+                        nProcessedModelInModel++;
+                    }
+                }
+
+                if (nProcessedModelInModel == nModelInModel)
+                {
+                    /*all is fine... */
+                }
+            }
+        }
+    }
+}
+
+/* Codes_SRS_CODEFIRST_99_079:[CodeFirst_CreateDevice shall create a device and allocate a memory block that should hold the device data.] */
+void* CodeFirst_CreateDevice(SCHEMA_MODEL_TYPE_HANDLE model, const REFLECTED_DATA_FROM_DATAPROVIDER* metadata, size_t dataSize, bool includePropertyPath)
+{
+    void* result;
+    DEVICE_HEADER_DATA* deviceHeader;
+
+    /* Codes_SRS_CODEFIRST_99_080:[If CodeFirst_CreateDevice is invoked with a NULL model, it shall return NULL.]*/
+    if (model == NULL)
+    {
+        result = NULL;
+        LogError(" %s ", MU_ENUM_TO_STRING(CODEFIRST_RESULT, CODEFIRST_INVALID_ARG));
+    }
+    else
+    {
+        /*Codes_SRS_CODEFIRST_02_037: [ CodeFirst_CreateDevice shall call CodeFirst_Init, passing NULL for overrideSchemaNamespace. ]*/
+        (void)CodeFirst_Init_impl(NULL, false); /*lazy init*/
+
+        if ((deviceHeader = (DEVICE_HEADER_DATA*)calloc(1, sizeof(DEVICE_HEADER_DATA))) == NULL)
+        {
+            /* Codes_SRS_CODEFIRST_99_102:[On any other errors, Device_Create shall return NULL.] */
+            result = NULL;
+            LogError(" %s ", MU_ENUM_TO_STRING(CODEFIRST_RESULT, CODEFIRST_ERROR));
+        }
+        /* Codes_SRS_CODEFIRST_99_081:[CodeFirst_CreateDevice shall use Device_Create to create a device handle.] */
+        /* Codes_SRS_CODEFIRST_99_082: [ CodeFirst_CreateDevice shall pass to Device_Create the function CodeFirst_InvokeAction, action callback argument and the CodeFirst_InvokeMethod ] */
+        else
+        {
+            if ((deviceHeader->data = malloc(dataSize)) == NULL)
+            {
+                free(deviceHeader);
+                deviceHeader = NULL;
+                result = NULL;
+                LogError(" %s ", MU_ENUM_TO_STRING(CODEFIRST_RESULT, CODEFIRST_ERROR));
+            }
+            else
+            {
+                DEVICE_HEADER_DATA** newDevices;
+
+                initializeDesiredProperties(model, deviceHeader->data);
+
+                if (Device_Create(model, CodeFirst_InvokeAction, deviceHeader, CodeFirst_InvokeMethod, deviceHeader,
+                    includePropertyPath, &deviceHeader->DeviceHandle) != DEVICE_OK)
+                {
+                    free(deviceHeader->data);
+                    free(deviceHeader);
+
+                    /* Codes_SRS_CODEFIRST_99_084:[If Device_Create fails, CodeFirst_CreateDevice shall return NULL.] */
+                    result = NULL;
+                    LogError(" %s ", MU_ENUM_TO_STRING(CODEFIRST_RESULT, CODEFIRST_DEVICE_FAILED));
+                }
+                else if ((newDevices = (DEVICE_HEADER_DATA**)realloc(g_Devices, sizeof(DEVICE_HEADER_DATA*) * (g_DeviceCount + 1))) == NULL)
+                {
+                    Device_Destroy(deviceHeader->DeviceHandle);
+                    free(deviceHeader->data);
+                    free(deviceHeader);
+
+                    /* Codes_SRS_CODEFIRST_99_102:[On any other errors, Device_Create shall return NULL.] */
+                    result = NULL;
+                    LogError(" %s ", MU_ENUM_TO_STRING(CODEFIRST_RESULT, CODEFIRST_ERROR));
+                }
+                else
+                {
+                    SCHEMA_RESULT schemaResult;
+                    deviceHeader->ReflectedData = metadata;
+                    deviceHeader->DataSize = dataSize;
+                    deviceHeader->ModelHandle = model;
+                    schemaResult = Schema_AddDeviceRef(model);
+                    if (schemaResult != SCHEMA_OK)
+                    {
+                        Device_Destroy(deviceHeader->DeviceHandle);
+                        free(newDevices);
+                        free(deviceHeader->data);
+                        free(deviceHeader);
+
+                        /* Codes_SRS_CODEFIRST_99_102:[On any other errors, Device_Create shall return NULL.] */
+                        result = NULL;
+                    }
+                    else
+                    {
+                        g_Devices = newDevices;
+                        g_Devices[g_DeviceCount] = deviceHeader;
+                        g_DeviceCount++;
+
+                        /* Codes_SRS_CODEFIRST_99_101:[On success, CodeFirst_CreateDevice shall return a non NULL pointer to the device data.] */
+                        result = deviceHeader->data;
+                    }
+                }
+            }
+        }
+
+    }
+
+    return result;
+}
+
+void CodeFirst_DestroyDevice(void* device)
+{
+    /* Codes_SRS_CODEFIRST_99_086:[If the argument is NULL, CodeFirst_DestroyDevice shall do nothing.] */
+    if (device != NULL)
+    {
+        size_t i;
+
+        for (i = 0; i < g_DeviceCount; i++)
+        {
+            if (g_Devices[i]->data == device)
+            {
+                deinitializeDesiredProperties(g_Devices[i]->ModelHandle, g_Devices[i]->data);
+                Schema_ReleaseDeviceRef(g_Devices[i]->ModelHandle);
+
+                // Delete the Created Schema if all the devices are unassociated
+                Schema_DestroyIfUnused(g_Devices[i]->ModelHandle);
+
+                DestroyDevice(g_Devices[i]);
+                (void)memcpy(&g_Devices[i], &g_Devices[i + 1], (g_DeviceCount - i - 1) * sizeof(DEVICE_HEADER_DATA*));
+                g_DeviceCount--;
+                break;
+            }
+        }
+
+        /*Codes_SRS_CODEFIRST_02_039: [ If the current device count is zero then CodeFirst_DestroyDevice shall deallocate all other used resources. ]*/
+        if ((g_state == CODEFIRST_STATE_INIT_BY_API) && (g_DeviceCount == 0))
+        {
+            free(g_Devices);
+            g_Devices = NULL;
+            g_state = CODEFIRST_STATE_NOT_INIT;
+        }
+    }
+}
+
+static DEVICE_HEADER_DATA* FindDevice(void* value)
+{
+    size_t i;
+    DEVICE_HEADER_DATA* result = NULL;
+
+    for (i = 0; i < g_DeviceCount; i++)
+    {
+        if ((g_Devices[i]->data <= (unsigned char*)value) &&
+            (g_Devices[i]->data + g_Devices[i]->DataSize > (unsigned char*)value))
+        {
+            result = g_Devices[i];
+            break;
+        }
+    }
+
+    return result;
+}
+
+static const REFLECTED_SOMETHING* FindValue(DEVICE_HEADER_DATA* deviceHeader, void* value, const char* modelName, size_t startOffset, STRING_HANDLE valuePath)
+{
+    const REFLECTED_SOMETHING* result;
+    size_t valueOffset = (size_t)((unsigned char*)value - (unsigned char*)deviceHeader->data) - startOffset;
+
+    for (result = deviceHeader->ReflectedData->reflectedData; result != NULL; result = result->next)
+    {
+        if (result->type == REFLECTION_PROPERTY_TYPE &&
+            (strcmp(result->what.property.modelName, modelName) == 0) &&
+            (result->what.property.offset <= valueOffset) &&
+            (result->what.property.offset + result->what.property.size > valueOffset))
+        {
+            if (startOffset != 0)
+            {
+                STRING_concat(valuePath, "/");
+            }
+
+            STRING_concat(valuePath, result->what.property.name);
+            break;
+        }
+    }
+
+    if (result != NULL)
+    {
+        /* Codes_SRS_CODEFIRST_99_133:[CodeFirst_SendAsync shall allow sending of properties that are part of a child model.] */
+        if (result->what.property.offset < valueOffset)
+        {
+            /* find recursively the property in the inner model, if there is one */
+            result = FindValue(deviceHeader, value, result->what.property.type, startOffset + result->what.property.offset, valuePath);
+        }
+    }
+
+    return result;
+}
+
+static const REFLECTED_SOMETHING* FindReportedProperty(DEVICE_HEADER_DATA* deviceHeader, void* value, const char* modelName, size_t startOffset, STRING_HANDLE valuePath)
+{
+    const REFLECTED_SOMETHING* result;
+    size_t valueOffset = (size_t)((unsigned char*)value - (unsigned char*)deviceHeader->data) - startOffset;
+
+    for (result = deviceHeader->ReflectedData->reflectedData; result != NULL; result = result->next)
+    {
+        if (result->type == REFLECTION_REPORTED_PROPERTY_TYPE &&
+            (strcmp(result->what.reportedProperty.modelName, modelName) == 0) &&
+            (result->what.reportedProperty.offset <= valueOffset) &&
+            (result->what.reportedProperty.offset + result->what.reportedProperty.size > valueOffset))
+        {
+            if (startOffset != 0)
+            {
+                if (STRING_concat(valuePath, "/") != 0)
+                {
+                    LogError("unable to STRING_concat");
+                    result = NULL;
+                    break;
+                }
+            }
+
+            if (STRING_concat(valuePath, result->what.reportedProperty.name) != 0)
+            {
+                LogError("unable to STRING_concat");
+                result = NULL;
+                break;
+            }
+            break;
+        }
+    }
+
+    if (result != NULL)
+    {
+        /* Codes_SRS_CODEFIRST_99_133:[CodeFirst_SendAsync shall allow sending of properties that are part of a child model.] */
+        if (result->what.reportedProperty.offset < valueOffset)
+        {
+            /* find recursively the property in the inner model, if there is one */
+            result = FindReportedProperty(deviceHeader, value, result->what.reportedProperty.type, startOffset + result->what.reportedProperty.offset, valuePath);
+        }
+    }
+
+    return result;
+}
+
+/* Codes_SRS_CODEFIRST_99_130:[If a pointer to the beginning of a device block is passed to CodeFirst_SendAsync instead of a pointer to a property, CodeFirst_SendAsync shall send all the properties that belong to that device.] */
+/* Codes_SRS_CODEFIRST_99_131:[The properties shall be given to Device as one transaction, as if they were all passed as individual arguments to Code_First.] */
+static CODEFIRST_RESULT SendAllDeviceProperties(DEVICE_HEADER_DATA* deviceHeader, TRANSACTION_HANDLE transaction)
+{
+    const char* modelName = Schema_GetModelName(deviceHeader->ModelHandle);
+    const REFLECTED_SOMETHING* something;
+    unsigned char* deviceAddress = (unsigned char*)deviceHeader->data;
+    CODEFIRST_RESULT result = CODEFIRST_OK;
+
+    for (something = deviceHeader->ReflectedData->reflectedData; something != NULL; something = something->next)
+    {
+        if ((something->type == REFLECTION_PROPERTY_TYPE) &&
+            (strcmp(something->what.property.modelName, modelName) == 0))
+        {
+            AGENT_DATA_TYPE agentDataType;
+
+            /* Codes_SRS_CODEFIRST_99_097:[For each value marshalling to AGENT_DATA_TYPE shall be performed.] */
+            /* Codes_SRS_CODEFIRST_99_098:[The marshalling shall be done by calling the Create_AGENT_DATA_TYPE_from_Ptr function associated with the property.] */
+            if (something->what.property.Create_AGENT_DATA_TYPE_from_Ptr(deviceAddress + something->what.property.offset, &agentDataType) != AGENT_DATA_TYPES_OK)
+            {
+                /* Codes_SRS_CODEFIRST_99_099:[If Create_AGENT_DATA_TYPE_from_Ptr fails, CodeFirst_SendAsync shall return CODEFIRST_AGENT_DATA_TYPE_ERROR.] */
+                result = CODEFIRST_AGENT_DATA_TYPE_ERROR;
+                LOG_CODEFIRST_ERROR;
+                break;
+            }
+            else
+            {
+                /* Codes_SRS_CODEFIRST_99_092:[CodeFirst shall publish each value by using Device_PublishTransacted.] */
+                if (Device_PublishTransacted(transaction, something->what.property.name, &agentDataType) != DEVICE_OK)
+                {
+                    Destroy_AGENT_DATA_TYPE(&agentDataType);
+
+                    /* Codes_SRS_CODEFIRST_99_094:[If any Device API fail, CodeFirst_SendAsync shall return CODEFIRST_DEVICE_PUBLISH_FAILED.] */
+                    result = CODEFIRST_DEVICE_PUBLISH_FAILED;
+                    LOG_CODEFIRST_ERROR;
+                    break;
+                }
+
+                Destroy_AGENT_DATA_TYPE(&agentDataType);
+            }
+        }
+    }
+
+    return result;
+}
+
+static CODEFIRST_RESULT SendAllDeviceReportedProperties(DEVICE_HEADER_DATA* deviceHeader, REPORTED_PROPERTIES_TRANSACTION_HANDLE transaction)
+{
+    const char* modelName = Schema_GetModelName(deviceHeader->ModelHandle);
+    const REFLECTED_SOMETHING* something;
+    unsigned char* deviceAddress = (unsigned char*)deviceHeader->data;
+    CODEFIRST_RESULT result = CODEFIRST_OK;
+
+    for (something = deviceHeader->ReflectedData->reflectedData; something != NULL; something = something->next)
+    {
+        if ((something->type == REFLECTION_REPORTED_PROPERTY_TYPE) &&
+            (strcmp(something->what.reportedProperty.modelName, modelName) == 0))
+        {
+            AGENT_DATA_TYPE agentDataType;
+
+            if (something->what.reportedProperty.Create_AGENT_DATA_TYPE_from_Ptr(deviceAddress + something->what.reportedProperty.offset, &agentDataType) != AGENT_DATA_TYPES_OK)
+            {
+                result = CODEFIRST_AGENT_DATA_TYPE_ERROR;
+                LOG_CODEFIRST_ERROR;
+                break;
+            }
+            else
+            {
+                if (Device_PublishTransacted_ReportedProperty(transaction, something->what.reportedProperty.name, &agentDataType) != DEVICE_OK)
+                {
+                    Destroy_AGENT_DATA_TYPE(&agentDataType);
+                    result = CODEFIRST_DEVICE_PUBLISH_FAILED;
+                    LOG_CODEFIRST_ERROR;
+                    break;
+                }
+
+                Destroy_AGENT_DATA_TYPE(&agentDataType);
+            }
+        }
+    }
+
+    return result;
+}
+
+
+/* Codes_SRS_CODEFIRST_99_088:[CodeFirst_SendAsync shall send to the Device module a set of properties, a destination and a destinationSize.]*/
+CODEFIRST_RESULT CodeFirst_SendAsync(unsigned char** destination, size_t* destinationSize, size_t numProperties, ...)
+{
+    CODEFIRST_RESULT result;
+    va_list ap;
+
+    if (
+        (numProperties == 0) ||
+        (destination == NULL) ||
+        (destinationSize == NULL)
+        )
+    {
+        /* Codes_SRS_CODEFIRST_04_002: [If CodeFirst_SendAsync receives destination or destinationSize NULL, CodeFirst_SendAsync shall return Invalid Argument.]*/
+        /* Codes_SRS_CODEFIRST_99_103:[If CodeFirst_SendAsync is called with numProperties being zero, CODEFIRST_INVALID_ARG shall be returned.] */
+        result = CODEFIRST_INVALID_ARG;
+        LOG_CODEFIRST_ERROR;
+    }
+    else
+    {
+        /*Codes_SRS_CODEFIRST_02_040: [ CodeFirst_SendAsync shall call CodeFirst_Init, passing NULL for overrideSchemaNamespace. ]*/
+        (void)CodeFirst_Init_impl(NULL, false); /*lazy init*/
+
+        DEVICE_HEADER_DATA* deviceHeader = NULL;
+        size_t i;
+        TRANSACTION_HANDLE transaction = NULL;
+        result = CODEFIRST_OK;
+
+        /* Codes_SRS_CODEFIRST_99_105:[The properties are passed as pointers to the memory locations where the data exists in the device block allocated by CodeFirst_CreateDevice.] */
+        va_start(ap, numProperties);
+
+        /* Codes_SRS_CODEFIRST_99_089:[The numProperties argument shall indicate how many properties are to be sent.] */
+        for (i = 0; i < numProperties; i++)
+        {
+            void* value = (void*)va_arg(ap, void*);
+
+            /* Codes_SRS_CODEFIRST_99_095:[For each value passed to it, CodeFirst_SendAsync shall look up to which device the value belongs.] */
+            DEVICE_HEADER_DATA* currentValueDeviceHeader = FindDevice(value);
+            if (currentValueDeviceHeader == NULL)
+            {
+                /* Codes_SRS_CODEFIRST_99_104:[If a property cannot be associated with a device, CodeFirst_SendAsync shall return CODEFIRST_INVALID_ARG.] */
+                result = CODEFIRST_INVALID_ARG;
+                LOG_CODEFIRST_ERROR;
+                break;
+            }
+            else if ((deviceHeader != NULL) &&
+                (currentValueDeviceHeader != deviceHeader))
+            {
+                /* Codes_SRS_CODEFIRST_99_096:[All values have to belong to the same device, otherwise CodeFirst_SendAsync shall return CODEFIRST_VALUES_FROM_DIFFERENT_DEVICES_ERROR.] */
+                result = CODEFIRST_VALUES_FROM_DIFFERENT_DEVICES_ERROR;
+                LOG_CODEFIRST_ERROR;
+                break;
+            }
+            /* Codes_SRS_CODEFIRST_99_090:[All the properties shall be sent together by using the transacted APIs of the device.] */
+            /* Codes_SRS_CODEFIRST_99_091:[CodeFirst_SendAsync shall start a transaction by calling Device_StartTransaction.] */
+            else if ((deviceHeader == NULL) &&
+                ((transaction = Device_StartTransaction(currentValueDeviceHeader->DeviceHandle)) == NULL))
+            {
+                /* Codes_SRS_CODEFIRST_99_094:[If any Device API fail, CodeFirst_SendAsync shall return CODEFIRST_DEVICE_PUBLISH_FAILED.] */
+                result = CODEFIRST_DEVICE_PUBLISH_FAILED;
+                LOG_CODEFIRST_ERROR;
+                break;
+            }
+            else
+            {
+                deviceHeader = currentValueDeviceHeader;
+
+                if (value == ((unsigned char*)deviceHeader->data))
+                {
+                    /* we got a full device, send all its state data */
+                    result = SendAllDeviceProperties(deviceHeader, transaction);
+                    if (result != CODEFIRST_OK)
+                    {
+                        LOG_CODEFIRST_ERROR;
+                        break;
+                    }
+                }
+                else
+                {
+                    const REFLECTED_SOMETHING* propertyReflectedData;
+                    const char* modelName;
+                    STRING_HANDLE valuePath;
+
+                    if ((valuePath = STRING_new()) == NULL)
+                    {
+                        /* Codes_SRS_CODEFIRST_99_134:[If CodeFirst_Notify fails for any other reason it shall return CODEFIRST_ERROR.] */
+                        result = CODEFIRST_ERROR;
+                        LOG_CODEFIRST_ERROR;
+                        break;
+                    }
+                    else
+                    {
+                        if ((modelName = Schema_GetModelName(deviceHeader->ModelHandle)) == NULL)
+                        {
+                            /* Codes_SRS_CODEFIRST_99_134:[If CodeFirst_Notify fails for any other reason it shall return CODEFIRST_ERROR.] */
+                            result = CODEFIRST_ERROR;
+                            LOG_CODEFIRST_ERROR;
+                            STRING_delete(valuePath);
+                            break;
+                        }
+                        else if ((propertyReflectedData = FindValue(deviceHeader, value, modelName, 0, valuePath)) == NULL)
+                        {
+                            /* Codes_SRS_CODEFIRST_99_104:[If a property cannot be associated with a device, CodeFirst_SendAsync shall return CODEFIRST_INVALID_ARG.] */
+                            result = CODEFIRST_INVALID_ARG;
+                            LOG_CODEFIRST_ERROR;
+                            STRING_delete(valuePath);
+                            break;
+                        }
+                        else
+                        {
+                            AGENT_DATA_TYPE agentDataType;
+
+                            /* Codes_SRS_CODEFIRST_99_097:[For each value marshalling to AGENT_DATA_TYPE shall be performed.] */
+                            /* Codes_SRS_CODEFIRST_99_098:[The marshalling shall be done by calling the Create_AGENT_DATA_TYPE_from_Ptr function associated with the property.] */
+                            if (propertyReflectedData->what.property.Create_AGENT_DATA_TYPE_from_Ptr(value, &agentDataType) != AGENT_DATA_TYPES_OK)
+                            {
+                                /* Codes_SRS_CODEFIRST_99_099:[If Create_AGENT_DATA_TYPE_from_Ptr fails, CodeFirst_SendAsync shall return CODEFIRST_AGENT_DATA_TYPE_ERROR.] */
+                                result = CODEFIRST_AGENT_DATA_TYPE_ERROR;
+                                LOG_CODEFIRST_ERROR;
+                                STRING_delete(valuePath);
+                                break;
+                            }
+                            else
+                            {
+                                /* Codes_SRS_CODEFIRST_99_092:[CodeFirst shall publish each value by using Device_PublishTransacted.] */
+                                /* Codes_SRS_CODEFIRST_99_136:[CodeFirst_SendAsync shall build the full path for each property and then pass it to Device_PublishTransacted.] */
+                                if (Device_PublishTransacted(transaction, STRING_c_str(valuePath), &agentDataType) != DEVICE_OK)
+                                {
+                                    Destroy_AGENT_DATA_TYPE(&agentDataType);
+
+                                    /* Codes_SRS_CODEFIRST_99_094:[If any Device API fail, CodeFirst_SendAsync shall return CODEFIRST_DEVICE_PUBLISH_FAILED.] */
+                                    result = CODEFIRST_DEVICE_PUBLISH_FAILED;
+                                    LOG_CODEFIRST_ERROR;
+                                    STRING_delete(valuePath);
+                                    break;
+                                }
+                                else
+                                {
+                                    STRING_delete(valuePath); /*anyway*/
+                                }
+
+                                Destroy_AGENT_DATA_TYPE(&agentDataType);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        if (i < numProperties)
+        {
+            if (transaction != NULL)
+            {
+                (void)Device_CancelTransaction(transaction);
+            }
+        }
+        /* Codes_SRS_CODEFIRST_99_093:[After all values have been published, Device_EndTransaction shall be called.] */
+        else if (Device_EndTransaction(transaction, destination, destinationSize) != DEVICE_OK)
+        {
+            /* Codes_SRS_CODEFIRST_99_094:[If any Device API fail, CodeFirst_SendAsync shall return CODEFIRST_DEVICE_PUBLISH_FAILED.] */
+            result = CODEFIRST_DEVICE_PUBLISH_FAILED;
+            LOG_CODEFIRST_ERROR;
+        }
+        else
+        {
+            /* Codes_SRS_CODEFIRST_99_117:[On success, CodeFirst_SendAsync shall return CODEFIRST_OK.] */
+            result = CODEFIRST_OK;
+        }
+
+        va_end(ap);
+
+    }
+
+    return result;
+}
+
+CODEFIRST_RESULT CodeFirst_SendAsyncReported(unsigned char** destination, size_t* destinationSize, size_t numReportedProperties, ...)
+{
+    CODEFIRST_RESULT result;
+    if ((destination == NULL) || (destinationSize == NULL) || numReportedProperties == 0)
+    {
+        /*Codes_SRS_CODEFIRST_02_018: [ If parameter destination, destinationSize or any of the values passed through va_args is NULL then CodeFirst_SendAsyncReported shall fail and return CODEFIRST_INVALID_ARG. ]*/
+        LogError("invalid argument unsigned char** destination=%p, size_t* destinationSize=%p, size_t numReportedProperties=%lu", destination, destinationSize, (unsigned long)numReportedProperties);
+        result = CODEFIRST_INVALID_ARG;
+    }
+    else
+    {
+        /*Codes_SRS_CODEFIRST_02_046: [ CodeFirst_SendAsyncReported shall call CodeFirst_Init, passing NULL for overrideSchemaNamespace. ]*/
+        (void)CodeFirst_Init_impl(NULL, false);/*lazy init*/
+
+        DEVICE_HEADER_DATA* deviceHeader = NULL;
+        size_t i;
+        REPORTED_PROPERTIES_TRANSACTION_HANDLE transaction = NULL;
+        va_list ap;
+        result = CODEFIRST_ACTION_EXECUTION_ERROR; /*this initialization squelches a false warning about result not being initialized*/
+
+        va_start(ap, numReportedProperties);
+
+        for (i = 0; i < numReportedProperties; i++)
+        {
+            void* value = (void*)va_arg(ap, void*);
+            /*Codes_SRS_CODEFIRST_02_018: [ If parameter destination, destinationSize or any of the values passed through va_args is NULL then CodeFirst_SendAsyncReported shall fail and return CODEFIRST_INVALID_ARG. ]*/
+            if (value == NULL)
+            {
+                LogError("argument number %lu passed through variable arguments is NULL", (unsigned long)i);
+                result = CODEFIRST_INVALID_ARG;
+                break;
+            }
+            else
+            {
+                DEVICE_HEADER_DATA* currentValueDeviceHeader = FindDevice(value);
+                if (currentValueDeviceHeader == NULL)
+                {
+                    result = CODEFIRST_INVALID_ARG;
+                    LOG_CODEFIRST_ERROR;
+                    break;
+                }
+                /*Codes_SRS_CODEFIRST_02_019: [ If values passed through va_args do not belong to the same device then CodeFirst_SendAsyncReported shall fail and return CODEFIRST_VALUES_FROM_DIFFERENT_DEVICES_ERROR. ]*/
+                else if ((deviceHeader != NULL) &&
+                    (currentValueDeviceHeader != deviceHeader))
+                {
+                    result = CODEFIRST_VALUES_FROM_DIFFERENT_DEVICES_ERROR;
+                    LOG_CODEFIRST_ERROR;
+                    break;
+                }
+                /*Codes_SRS_CODEFIRST_02_022: [ CodeFirst_SendAsyncReported shall start a transaction by calling Device_CreateTransaction_ReportedProperties. ]*/
+                else if ((deviceHeader == NULL) &&
+                    ((transaction = Device_CreateTransaction_ReportedProperties(currentValueDeviceHeader->DeviceHandle)) == NULL))
+                {
+                    result = CODEFIRST_DEVICE_PUBLISH_FAILED;
+                    LOG_CODEFIRST_ERROR;
+                    break;
+                }
+                else
+                {
+                    deviceHeader = currentValueDeviceHeader;
+                    if (value == ((unsigned char*)deviceHeader->data))
+                    {
+                        /*Codes_SRS_CODEFIRST_02_021: [ If the value passed through va_args is a complete model instance, then CodeFirst_SendAsyncReported shall send all the reported properties of that device. ]*/
+                        result = SendAllDeviceReportedProperties(deviceHeader, transaction);
+                        if (result != CODEFIRST_OK)
+                        {
+                            LOG_CODEFIRST_ERROR;
+                            break;
+                        }
+                    }
+                    else
+                    {
+                        /*Codes_SRS_CODEFIRST_02_020: [ If values passed through va_args are not all of type REFLECTED_REPORTED_PROPERTY then CodeFirst_SendAsyncReported shall fail and return CODEFIRST_INVALID_ARG. ]*/
+                        const REFLECTED_SOMETHING* propertyReflectedData;
+                        const char* modelName;
+
+                        STRING_HANDLE valuePath;
+                        if ((valuePath = STRING_new()) == NULL)
+                        {
+                            result = CODEFIRST_ERROR;
+                            LOG_CODEFIRST_ERROR;
+                            break;
+                        }
+                        else
+                        {
+                            modelName = Schema_GetModelName(deviceHeader->ModelHandle);
+
+                            /*Codes_SRS_CODEFIRST_02_025: [ CodeFirst_SendAsyncReported shall compute for every AGENT_DATA_TYPE the valuePath. ]*/
+                            if ((propertyReflectedData = FindReportedProperty(deviceHeader, value, modelName, 0, valuePath)) == NULL)
+                            {
+                                result = CODEFIRST_INVALID_ARG;
+                                LOG_CODEFIRST_ERROR;
+                                STRING_delete(valuePath);
+                                break;
+                            }
+                            else
+                            {
+                                AGENT_DATA_TYPE agentDataType;
+                                /*Codes_SRS_CODEFIRST_02_023: [ CodeFirst_SendAsyncReported shall convert all REPORTED_PROPERTY model components to AGENT_DATA_TYPE. ]*/
+                                if (propertyReflectedData->what.reportedProperty.Create_AGENT_DATA_TYPE_from_Ptr(value, &agentDataType) != AGENT_DATA_TYPES_OK)
+                                {
+                                    result = CODEFIRST_AGENT_DATA_TYPE_ERROR;
+                                    LOG_CODEFIRST_ERROR;
+                                    STRING_delete(valuePath);
+                                    break;
+                                }
+                                else
+                                {
+                                    /*Codes_SRS_CODEFIRST_02_024: [ CodeFirst_SendAsyncReported shall call Device_PublishTransacted_ReportedProperty for every AGENT_DATA_TYPE converted from REPORTED_PROPERTY. ]*/
+                                    if (Device_PublishTransacted_ReportedProperty(transaction, STRING_c_str(valuePath), &agentDataType) != DEVICE_OK)
+                                    {
+                                        Destroy_AGENT_DATA_TYPE(&agentDataType);
+                                        result = CODEFIRST_DEVICE_PUBLISH_FAILED;
+                                        LOG_CODEFIRST_ERROR;
+                                        STRING_delete(valuePath);
+                                        break;
+                                    }
+                                    else
+                                    {
+                                        STRING_delete(valuePath);
+                                    }
+                                    Destroy_AGENT_DATA_TYPE(&agentDataType);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        /*Codes_SRS_CODEFIRST_02_027: [ If any error occurs, CodeFirst_SendAsyncReported shall fail and return CODEFIRST_ERROR. ]*/
+        if (i < numReportedProperties)
+        {
+            if (transaction != NULL)
+            {
+                Device_DestroyTransaction_ReportedProperties(transaction);
+            }
+        }
+        /*Codes_SRS_CODEFIRST_02_026: [ CodeFirst_SendAsyncReported shall call Device_CommitTransaction_ReportedProperties to commit the transaction. ]*/
+        else
+        {
+            if (Device_CommitTransaction_ReportedProperties(transaction, destination, destinationSize) != DEVICE_OK)
+            {
+                result = CODEFIRST_DEVICE_PUBLISH_FAILED;
+                LOG_CODEFIRST_ERROR;
+            }
+            else
+            {
+                /*Codes_SRS_CODEFIRST_02_028: [ CodeFirst_SendAsyncReported shall return CODEFIRST_OK when it succeeds. ]*/
+                result = CODEFIRST_OK;
+            }
+
+            /*Codes_SRS_CODEFIRST_02_029: [ CodeFirst_SendAsyncReported shall call Device_DestroyTransaction_ReportedProperties to destroy the transaction. ]*/
+            Device_DestroyTransaction_ReportedProperties(transaction);
+        }
+
+        va_end(ap);
+    }
+    return result;
+}
+
+EXECUTE_COMMAND_RESULT CodeFirst_ExecuteCommand(void* device, const char* command)
+{
+    EXECUTE_COMMAND_RESULT result;
+    /*Codes_SRS_CODEFIRST_02_014: [If parameter device or command is NULL then CodeFirst_ExecuteCommand shall return EXECUTE_COMMAND_ERROR.] */
+    if (
+        (device == NULL) ||
+        (command == NULL)
+        )
+    {
+        result = EXECUTE_COMMAND_ERROR;
+        LogError("invalid argument (NULL) passed to CodeFirst_ExecuteCommand void* device = %p, const char* command = %p", device, command);
+    }
+    else
+    {
+        /*Codes_SRS_CODEFIRST_02_015: [CodeFirst_ExecuteCommand shall find the device.]*/
+        DEVICE_HEADER_DATA* deviceHeader = FindDevice(device);
+        if(deviceHeader == NULL)
+        {
+            /*Codes_SRS_CODEFIRST_02_016: [If finding the device fails, then CodeFirst_ExecuteCommand shall return EXECUTE_COMMAND_ERROR.]*/
+            result = EXECUTE_COMMAND_ERROR;
+            LogError("unable to find the device given by address %p", device);
+        }
+        else
+        {
+            /*Codes_SRS_CODEFIRST_02_017: [Otherwise CodeFirst_ExecuteCommand shall call Device_ExecuteCommand and return what Device_ExecuteCommand is returning.] */
+            result = Device_ExecuteCommand(deviceHeader->DeviceHandle, command);
+        }
+    }
+    return result;
+}
+
+METHODRETURN_HANDLE CodeFirst_ExecuteMethod(void* device, const char* methodName, const char* methodPayload)
+{
+    METHODRETURN_HANDLE result;
+    if (
+        (device == NULL) ||
+        (methodName== NULL) /*methodPayload can be NULL*/
+        )
+    {
+        result = NULL;
+        LogError("invalid argument (NULL) passed to CodeFirst_ExecuteMethod void* device = %p, const char* methodName = %p", device, methodName);
+    }
+    else
+    {
+        DEVICE_HEADER_DATA* deviceHeader = FindDevice(device);
+        if (deviceHeader == NULL)
+        {
+            result = NULL;
+            LogError("unable to find the device given by address %p", device);
+        }
+        else
+        {
+            result = Device_ExecuteMethod(deviceHeader->DeviceHandle, methodName, methodPayload);
+        }
+    }
+    return result;
+}
+
+CODEFIRST_RESULT CodeFirst_IngestDesiredProperties(void* device, const char* jsonPayload, bool parseDesiredNode)
+{
+    CODEFIRST_RESULT result;
+    /*Codes_SRS_CODEFIRST_02_030: [ If argument device is NULL then CodeFirst_IngestDesiredProperties shall fail and return CODEFIRST_INVALID_ARG. ]*/
+    /*Codes_SRS_CODEFIRST_02_031: [ If argument jsonPayload is NULL then CodeFirst_IngestDesiredProperties shall fail and return CODEFIRST_INVALID_ARG. ]*/
+    if (
+        (device == NULL) ||
+        (jsonPayload == NULL)
+        )
+    {
+        LogError("invalid argument void* device=%p, const char* jsonPayload=%p", device, jsonPayload);
+        result = CODEFIRST_INVALID_ARG;
+    }
+    else
+    {
+        /*Codes_SRS_CODEFIRST_02_032: [ CodeFirst_IngestDesiredProperties shall locate the device associated with device. ]*/
+        DEVICE_HEADER_DATA* deviceHeader = FindDevice(device);
+        if (deviceHeader == NULL)
+        {
+            /*Codes_SRS_CODEFIRST_02_034: [ If there is any failure, then CodeFirst_IngestDesiredProperties shall fail and return CODEFIRST_ERROR. ]*/
+            LogError("unable to find a device having this memory address %p", device);
+            result = CODEFIRST_ERROR;
+        }
+        else
+        {
+            /*Codes_SRS_CODEFIRST_02_033: [ CodeFirst_IngestDesiredProperties shall call Device_IngestDesiredProperties. ]*/
+            if (Device_IngestDesiredProperties(device, deviceHeader->DeviceHandle, jsonPayload, parseDesiredNode) != DEVICE_OK)
+            {
+                LogError("failure in Device_IngestDesiredProperties");
+                result = CODEFIRST_ERROR;
+            }
+            else
+            {
+                /*Codes_SRS_CODEFIRST_02_035: [ Otherwise, CodeFirst_IngestDesiredProperties shall return CODEFIRST_OK. ]*/
+                result = CODEFIRST_OK;
+            }
+        }
+    }
+    return result;
+}
+
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/commanddecoder.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/commanddecoder.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/commanddecoder.c	(revision 453)
@@ -0,0 +1,1040 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/gballoc.h"
+
+#include <stddef.h>
+
+#include "commanddecoder.h"
+#include "multitree.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "schema.h"
+#include "codefirst.h"
+#include "jsondecoder.h"
+
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(COMMANDDECODER_RESULT, COMMANDDECODER_RESULT_VALUES);
+
+typedef struct COMMAND_DECODER_HANDLE_DATA_TAG
+{
+    METHOD_CALLBACK_FUNC methodCallback;
+    void* methodCallbackContext;
+    SCHEMA_MODEL_TYPE_HANDLE ModelHandle;
+    ACTION_CALLBACK_FUNC ActionCallback;
+    void* ActionCallbackContext;
+} COMMAND_DECODER_HANDLE_DATA;
+
+static int DecodeValueFromNode(SCHEMA_HANDLE schemaHandle, AGENT_DATA_TYPE* agentDataType, MULTITREE_HANDLE node, const char* edmTypeName)
+{
+    /* because "pottentially uninitialized variable on MS compiler" */
+    int result = 0;
+    const char* argStringValue;
+    AGENT_DATA_TYPE_TYPE primitiveType;
+
+    /* Codes_SRS_COMMAND_DECODER_99_029:[ If the argument type is complex then a complex type value shall be built from the child nodes.] */
+    if ((primitiveType = CodeFirst_GetPrimitiveType(edmTypeName)) == EDM_NO_TYPE)
+    {
+        SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle;
+        size_t propertyCount;
+
+        /* Codes_SRS_COMMAND_DECODER_99_033:[ In order to determine which are the members of a complex types, Schema APIs for structure types shall be used.] */
+        if (((structTypeHandle = Schema_GetStructTypeByName(schemaHandle, edmTypeName)) == NULL) ||
+            (Schema_GetStructTypePropertyCount(structTypeHandle, &propertyCount) != SCHEMA_OK))
+        {
+            /* Codes_SRS_COMMAND_DECODER_99_010:[ If any Schema API fails then the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.]*/
+            result = MU_FAILURE;
+            LogError("Getting Struct information failed.");
+        }
+        else
+        {
+            if (propertyCount == 0)
+            {
+                /* Codes_SRS_COMMAND_DECODER_99_034:[ If Schema APIs indicate that a complex type has 0 members then the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.] */
+                result = MU_FAILURE;
+                LogError("Struct type with 0 members is not allowed");
+            }
+            else
+            {
+                AGENT_DATA_TYPE* memberValues = (AGENT_DATA_TYPE*)calloc(1, (sizeof(AGENT_DATA_TYPE)* propertyCount));
+                if (memberValues == NULL)
+                {
+                    /* Codes_SRS_COMMAND_DECODER_99_021:[ If the parsing of the command fails for any other reason the command shall not be dispatched.] */
+                    result = MU_FAILURE;
+                    LogError("Failed allocating member values for command argument");
+                }
+                else
+                {
+                    const char** memberNames = (const char**)malloc(sizeof(const char*)* propertyCount);
+                    if (memberNames == NULL)
+                    {
+                        /* Codes_SRS_COMMAND_DECODER_99_021:[ If the parsing of the command fails for any other reason the command shall not be dispatched.] */
+                        result = MU_FAILURE;
+                        LogError("Failed allocating member names for command argument.");
+                    }
+                    else
+                    {
+                        size_t j;
+                        size_t k;
+
+                        for (j = 0; j < propertyCount; j++)
+                        {
+                            SCHEMA_PROPERTY_HANDLE propertyHandle;
+                            MULTITREE_HANDLE memberNode;
+                            const char* propertyName;
+                            const char* propertyType;
+
+                            if ((propertyHandle = Schema_GetStructTypePropertyByIndex(structTypeHandle, j)) == NULL)
+                            {
+                                /* Codes_SRS_COMMAND_DECODER_99_010:[ If any Schema API fails then the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.]*/
+                                result = MU_FAILURE;
+                                LogError("Getting struct member failed.");
+                                break;
+                            }
+                            else if (((propertyName = Schema_GetPropertyName(propertyHandle)) == NULL) ||
+                                     ((propertyType = Schema_GetPropertyType(propertyHandle)) == NULL))
+                            {
+                                /* Codes_SRS_COMMAND_DECODER_99_010:[ If any Schema API fails then the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.]*/
+                                result = MU_FAILURE;
+                                LogError("Getting the struct member information failed.");
+                                break;
+                            }
+                            else
+                            {
+                                memberNames[j] = propertyName;
+
+                                /* Codes_SRS_COMMAND_DECODER_01_014: [CommandDecoder shall use the MultiTree APIs to extract a specific element from the command JSON.] */
+                                if (MultiTree_GetChildByName(node, memberNames[j], &memberNode) != MULTITREE_OK)
+                                {
+                                    /* Codes_SRS_COMMAND_DECODER_99_028:[ If decoding the argument fails then the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.] */
+                                    result = MU_FAILURE;
+                                    LogError("Getting child %s failed", propertyName);
+                                    break;
+                                }
+                                /* Codes_SRS_COMMAND_DECODER_99_032:[ Nesting shall be supported for complex type.] */
+                                else if ((result = DecodeValueFromNode(schemaHandle, &memberValues[j], memberNode, propertyType)) != 0)
+                                {
+                                    break;
+                                }
+                            }
+                        }
+
+                        if (j == propertyCount)
+                        {
+                            /* Codes_SRS_COMMAND_DECODER_99_031:[ The complex type value that aggregates the children shall be built by using the Create_AGENT_DATA_TYPE_from_Members.] */
+                            if (Create_AGENT_DATA_TYPE_from_Members(agentDataType, edmTypeName, propertyCount, (const char* const*)memberNames, memberValues) != AGENT_DATA_TYPES_OK)
+                            {
+                                /* Codes_SRS_COMMAND_DECODER_99_028:[ If decoding the argument fails then the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.] */
+                                result = MU_FAILURE;
+                                LogError("Creating the agent data type from members failed.");
+                            }
+                            else
+                            {
+                                result = 0;
+                            }
+                        }
+
+                        for (k = 0; k < j; k++)
+                        {
+                            Destroy_AGENT_DATA_TYPE(&memberValues[k]);
+                        }
+
+                        free((void*)memberNames);
+                    }
+
+                    free(memberValues);
+                }
+            }
+        }
+    }
+    else
+    {
+        /* Codes_SRS_COMMAND_DECODER_01_014: [CommandDecoder shall use the MultiTree APIs to extract a specific element from the command JSON.] */
+        if (MultiTree_GetValue(node, (const void **)&argStringValue) != MULTITREE_OK)
+        {
+            /* Codes_SRS_COMMAND_DECODER_99_012:[ If any argument is missing in the command text then the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.] */
+            result = MU_FAILURE;
+            LogError("Getting the string from the multitree failed.");
+        }
+        /* Codes_SRS_COMMAND_DECODER_99_027:[ The value for an argument of primitive type shall be decoded by using the CreateAgentDataType_From_String API.] */
+        else if (CreateAgentDataType_From_String(argStringValue, primitiveType, agentDataType) != AGENT_DATA_TYPES_OK)
+        {
+            /* Codes_SRS_COMMAND_DECODER_99_028:[ If decoding the argument fails then the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.] */
+            result = MU_FAILURE;
+            LogError("Failed parsing node %s.", argStringValue);
+        }
+    }
+
+    return result;
+}
+
+static EXECUTE_COMMAND_RESULT DecodeAndExecuteModelAction(COMMAND_DECODER_HANDLE_DATA* commandDecoderInstance, SCHEMA_HANDLE schemaHandle, SCHEMA_MODEL_TYPE_HANDLE modelHandle, const char* relativeActionPath, const char* actionName, MULTITREE_HANDLE commandNode)
+{
+    EXECUTE_COMMAND_RESULT result;
+    char tempStr[128];
+    size_t strLength = strlen(actionName);
+
+    if (strLength <= 1)
+    {
+        /* Codes_SRS_COMMAND_DECODER_99_021:[ If the parsing of the command fails for any other reason the command shall not be dispatched.] */
+        LogError("Invalid action name");
+        result = EXECUTE_COMMAND_ERROR;
+    }
+    else if (strLength >= 128)
+    {
+        /* Codes_SRS_COMMAND_DECODER_99_021:[ If the parsing of the command fails for any other reason the command shall not be dispatched.] */
+        LogError("Invalid action name length");
+        result = EXECUTE_COMMAND_ERROR;
+    }
+    else
+    {
+        /* Codes_SRS_COMMAND_DECODER_99_006:[ The action name shall be decoded from the element "Name" of the command JSON.] */
+        SCHEMA_ACTION_HANDLE modelActionHandle;
+        size_t argCount;
+        MULTITREE_HANDLE parametersTreeNode;
+
+        if (memcpy(tempStr, actionName, strLength-1) == NULL)
+        {
+            /* Codes_SRS_COMMAND_DECODER_99_021:[ If the parsing of the command fails for any other reason the command shall not be dispatched.] */
+            LogError("Invalid action name.");
+            result = EXECUTE_COMMAND_ERROR;
+        }
+        /* Codes_SRS_COMMAND_DECODER_01_014: [CommandDecoder shall use the MultiTree APIs to extract a specific element from the command JSON.] */
+        else if (MultiTree_GetChildByName(commandNode, "Parameters", &parametersTreeNode) != MULTITREE_OK)
+        {
+            /* Codes_SRS_COMMAND_DECODER_01_015: [If any MultiTree API call fails then the processing shall stop and the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.] */
+            LogError("Error getting Parameters node.");
+            result = EXECUTE_COMMAND_ERROR;
+        }
+        else
+        {
+            tempStr[strLength-1] = 0;
+            /* Codes_SRS_COMMAND_DECODER_99_009:[ CommandDecoder shall call Schema_GetModelActionByName to obtain the information about a specific action.] */
+            if (((modelActionHandle = Schema_GetModelActionByName(modelHandle, tempStr)) == NULL) ||
+                (Schema_GetModelActionArgumentCount(modelActionHandle, &argCount) != SCHEMA_OK))
+            {
+                /* Codes_SRS_COMMAND_DECODER_99_010:[ If any Schema API fails then the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.]*/
+                LogError("Failed reading action %s from the schema", tempStr);
+                result = EXECUTE_COMMAND_ERROR;
+            }
+            else
+            {
+                AGENT_DATA_TYPE* arguments = NULL;
+
+                if (argCount > 0)
+                {
+                    arguments = (AGENT_DATA_TYPE*)calloc(1, (sizeof(AGENT_DATA_TYPE)* argCount));
+                }
+
+                if ((argCount > 0) &&
+                    (arguments == NULL))
+                {
+                    /* Codes_SRS_COMMAND_DECODER_99_021:[ If the parsing of the command fails for any other reason the command shall not be dispatched.] */
+                    LogError("Failed allocating arguments array");
+                    result = EXECUTE_COMMAND_ERROR;
+                }
+                else
+                {
+                    size_t i;
+                    size_t j;
+                    result = EXECUTE_COMMAND_ERROR;
+
+                    /* Codes_SRS_COMMAND_DECODER_99_011:[ CommandDecoder shall attempt to extract from the command text the value for each action argument.] */
+                    for (i = 0; i < argCount; i++)
+                    {
+                        SCHEMA_ACTION_ARGUMENT_HANDLE actionArgumentHandle;
+                        MULTITREE_HANDLE argumentNode;
+                        const char* argName;
+                        const char* argType;
+
+                        if (((actionArgumentHandle = Schema_GetModelActionArgumentByIndex(modelActionHandle, i)) == NULL) ||
+                            ((argName = Schema_GetActionArgumentName(actionArgumentHandle)) == NULL) ||
+                            ((argType = Schema_GetActionArgumentType(actionArgumentHandle)) == NULL))
+                        {
+                            LogError("Failed getting the argument information from the schema");
+                            result = EXECUTE_COMMAND_ERROR;
+                            break;
+                        }
+                        /* Codes_SRS_COMMAND_DECODER_01_014: [CommandDecoder shall use the MultiTree APIs to extract a specific element from the command JSON.] */
+                        /* Codes_SRS_COMMAND_DECODER_01_008: [Each argument shall be looked up as a field, member of the "Parameters" node.]  */
+                        else if (MultiTree_GetChildByName(parametersTreeNode, argName, &argumentNode) != MULTITREE_OK)
+                        {
+                            /* Codes_SRS_COMMAND_DECODER_99_012:[ If any argument is missing in the command text then the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.] */
+                            LogError("Missing argument %s", argName);
+                            result = EXECUTE_COMMAND_ERROR;
+                            break;
+                        }
+                        else if (DecodeValueFromNode(schemaHandle, &arguments[i], argumentNode, argType) != 0)
+                        {
+                            result = EXECUTE_COMMAND_ERROR;
+                            break;
+                        }
+                    }
+
+                    if (i == argCount)
+                    {
+                        /* Codes_SRS_COMMAND_DECODER_99_005:[ If an Invoke Action is decoded successfully then the callback actionCallback shall be called, passing to it the callback action context, decoded name and arguments.] */
+                        result = commandDecoderInstance->ActionCallback(commandDecoderInstance->ActionCallbackContext, relativeActionPath, tempStr, argCount, arguments);
+                    }
+
+                    for (j = 0; j < i; j++)
+                    {
+                        Destroy_AGENT_DATA_TYPE(&arguments[j]);
+                    }
+
+                    if (arguments != NULL)
+                    {
+                        free(arguments);
+                    }
+                }
+            }
+        }
+    }
+    return result;
+}
+
+static METHODRETURN_HANDLE DecodeAndExecuteModelMethod(COMMAND_DECODER_HANDLE_DATA* commandDecoderInstance, SCHEMA_HANDLE schemaHandle, SCHEMA_MODEL_TYPE_HANDLE modelHandle, const char* relativeMethodPath, const char* methodName, MULTITREE_HANDLE methodTree)
+{
+    METHODRETURN_HANDLE result;
+    size_t strLength = strlen(methodName);
+
+    if (strLength == 0)
+    {
+        /*Codes_SRS_COMMAND_DECODER_02_023: [ If any of the previous operations fail, then CommandDecoder_ExecuteMethod shall return NULL. ]*/
+        LogError("Invalid method name");
+        result = NULL;
+    }
+    else
+    {
+        SCHEMA_METHOD_HANDLE modelMethodHandle;
+        size_t argCount;
+
+#ifdef _MSC_VER
+#pragma warning(suppress: 6324) /* We intentionally use here strncpy */
+#endif
+
+        /*Codes_SRS_COMMAND_DECODER_02_020: [ CommandDecoder_ExecuteMethod shall verify that the model has a method called methodName. ]*/
+        if (((modelMethodHandle = Schema_GetModelMethodByName(modelHandle, methodName)) == NULL) ||
+            (Schema_GetModelMethodArgumentCount(modelMethodHandle, &argCount) != SCHEMA_OK))
+        {
+            /*Codes_SRS_COMMAND_DECODER_02_023: [ If any of the previous operations fail, then CommandDecoder_ExecuteMethod shall return NULL. ]*/
+            LogError("Failed reading method %s from the schema", methodName);
+            result = NULL;
+        }
+        else
+        {
+            /*Codes_SRS_COMMAND_DECODER_02_021: [ For every argument of methodName, CommandDecoder_ExecuteMethod shall build an AGENT_DATA_TYPE from the node with the same name from the MULTITREE_HANDLE. ]*/
+
+            if (argCount == 0)
+            {
+                /*no need for any parameters*/
+                result = commandDecoderInstance->methodCallback(commandDecoderInstance->methodCallbackContext, relativeMethodPath, methodName, 0, NULL);
+            }
+            else
+            {
+                AGENT_DATA_TYPE* arguments;
+                arguments = (AGENT_DATA_TYPE*)calloc(1, (sizeof(AGENT_DATA_TYPE)* argCount));
+                if (arguments == NULL)
+                {
+                    LogError("Failed allocating arguments array");
+                    result = NULL;
+                }
+                else
+                {
+                    size_t i;
+                    size_t j;
+                    result = NULL;
+
+                    for (i = 0; i < argCount; i++)
+                    {
+                        SCHEMA_METHOD_ARGUMENT_HANDLE methodArgumentHandle;
+                        MULTITREE_HANDLE argumentNode;
+                        const char* argName;
+                        const char* argType;
+
+                        if (((methodArgumentHandle = Schema_GetModelMethodArgumentByIndex(modelMethodHandle, i)) == NULL) ||
+                            ((argName = Schema_GetMethodArgumentName(methodArgumentHandle)) == NULL) ||
+                            ((argType = Schema_GetMethodArgumentType(methodArgumentHandle)) == NULL))
+                        {
+                            /*Codes_SRS_COMMAND_DECODER_02_023: [ If any of the previous operations fail, then CommandDecoder_ExecuteMethod shall return NULL. ]*/
+                            LogError("Failed getting the argument information from the schema");
+                            result = NULL;
+                            break;
+                        }
+                        else if (MultiTree_GetChildByName(methodTree, argName, &argumentNode) != MULTITREE_OK)
+                        {
+                            /*Codes_SRS_COMMAND_DECODER_02_023: [ If any of the previous operations fail, then CommandDecoder_ExecuteMethod shall return NULL. ]*/
+                            LogError("Missing argument %s", argName);
+                            result = NULL;
+                            break;
+                        }
+                        else if (DecodeValueFromNode(schemaHandle, &arguments[i], argumentNode, argType) != 0)
+                        {
+                            /*Codes_SRS_COMMAND_DECODER_02_023: [ If any of the previous operations fail, then CommandDecoder_ExecuteMethod shall return NULL. ]*/
+                            LogError("failure in DecodeValueFromNode");
+                            result = NULL;
+                            break;
+                        }
+                    }
+
+                    if (i == argCount)
+                    {
+                        /*Codes_SRS_COMMAND_DECODER_02_022: [ CommandDecoder_ExecuteMethod shall call methodCallback passing the context, the methodName, number of arguments and the AGENT_DATA_TYPE. ]*/
+                        /*Codes_SRS_COMMAND_DECODER_02_024: [ Otherwise, CommandDecoder_ExecuteMethod shall return what methodCallback returns. ]*/
+                        result = commandDecoderInstance->methodCallback(commandDecoderInstance->methodCallbackContext, relativeMethodPath, methodName, argCount, arguments);
+                    }
+
+                    for (j = 0; j < i; j++)
+                    {
+                        Destroy_AGENT_DATA_TYPE(&arguments[j]);
+                    }
+
+                    free(arguments);
+                }
+
+            }
+        }
+
+    }
+    return result;
+}
+
+
+static EXECUTE_COMMAND_RESULT ScanActionPathAndExecuteAction(COMMAND_DECODER_HANDLE_DATA* commandDecoderInstance, SCHEMA_HANDLE schemaHandle, const char* actionPath, MULTITREE_HANDLE commandNode)
+{
+    EXECUTE_COMMAND_RESULT result;
+    char* relativeActionPath;
+    const char* actionName = actionPath;
+    SCHEMA_MODEL_TYPE_HANDLE modelHandle = commandDecoderInstance->ModelHandle;
+
+    /* Codes_SRS_COMMAND_DECODER_99_035:[ CommandDecoder_ExecuteCommand shall support paths to actions that are in child models (i.e. ChildModel/SomeAction.] */
+    do
+    {
+        /* find the slash */
+        const char* slashPos = strchr(actionName, '/');
+        if (slashPos == NULL)
+        {
+            size_t relativeActionPathLength;
+
+            /* Codes_SRS_COMMAND_DECODER_99_037:[ The relative path passed to the actionCallback shall be in the format "childModel1/childModel2/.../childModelN".] */
+            if (actionName == actionPath)
+            {
+                relativeActionPathLength = 0;
+            }
+            else
+            {
+                relativeActionPathLength = actionName - actionPath - 1;
+            }
+
+            relativeActionPath = (char*)malloc(relativeActionPathLength + 1);
+            if (relativeActionPath == NULL)
+            {
+                /* Codes_SRS_COMMAND_DECODER_99_021:[ If the parsing of the command fails for any other reason the command shall not be dispatched.] */
+                LogError("Failed allocating relative action path");
+                result = EXECUTE_COMMAND_ERROR;
+            }
+            else
+            {
+                strncpy(relativeActionPath, actionPath, relativeActionPathLength);
+                relativeActionPath[relativeActionPathLength] = 0;
+
+                /* no slash found, this must be an action */
+                result = DecodeAndExecuteModelAction(commandDecoderInstance, schemaHandle, modelHandle, relativeActionPath, actionName, commandNode);
+
+                free(relativeActionPath);
+                actionName = NULL;
+            }
+            break;
+        }
+        else
+        {
+            /* found a slash, get the child model name */
+            size_t modelLength = slashPos - actionName;
+            char* childModelName = (char*)malloc(modelLength + 1);
+            if (childModelName == NULL)
+            {
+                /* Codes_SRS_COMMAND_DECODER_99_021:[ If the parsing of the command fails for any other reason the command shall not be dispatched.] */
+                LogError("Failed allocating child model name");
+                result = EXECUTE_COMMAND_ERROR;
+                break;
+            }
+            else
+            {
+                strncpy(childModelName, actionName, modelLength);
+                childModelName[modelLength] = 0;
+
+                /* find the model */
+                modelHandle = Schema_GetModelModelByName(modelHandle, childModelName);
+                if (modelHandle == NULL)
+                {
+                    /* Codes_SRS_COMMAND_DECODER_99_036:[ If a child model cannot be found by using Schema APIs then the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.] */
+                    LogError("Getting the model %s failed", childModelName);
+                    free(childModelName);
+                    result = EXECUTE_COMMAND_ERROR;
+                    break;
+                }
+                else
+                {
+                    free(childModelName);
+                    actionName = slashPos + 1;
+                    result = EXECUTE_COMMAND_ERROR; /*this only exists to quench a compiler warning about returning an uninitialized variable, which is not possible by design*/
+                }
+            }
+        }
+    } while (actionName != NULL);
+    return result;
+}
+
+static METHODRETURN_HANDLE ScanMethodPathAndExecuteMethod(COMMAND_DECODER_HANDLE_DATA* commandDecoderInstance, SCHEMA_HANDLE schemaHandle, const char* fullMethodName, MULTITREE_HANDLE methodTree)
+{
+    METHODRETURN_HANDLE result;
+    char* relativeMethodPath;
+    const char* methodName = fullMethodName;
+    SCHEMA_MODEL_TYPE_HANDLE modelHandle = commandDecoderInstance->ModelHandle;
+
+    /*Codes_SRS_COMMAND_DECODER_02_018: [ CommandDecoder_ExecuteMethod shall validate that consecutive segments of the fullMethodName exist in the model. ]*/
+    /*Codes_SRS_COMMAND_DECODER_02_019: [ CommandDecoder_ExecuteMethod shall locate the final model to which the methodName applies. ]*/
+    do
+    {
+        /* find the slash */
+        const char* slashPos = strchr(methodName, '/');
+        if (slashPos == NULL)
+        {
+            size_t relativeMethodPathLength;
+
+            if (methodName == fullMethodName)
+            {
+                relativeMethodPathLength = 0;
+            }
+            else
+            {
+                relativeMethodPathLength = methodName - fullMethodName - 1;
+            }
+
+            relativeMethodPath = (char*)malloc(relativeMethodPathLength + 1);
+            if (relativeMethodPath == NULL)
+            {
+                /*Codes_SRS_COMMAND_DECODER_02_023: [ If any of the previous operations fail, then CommandDecoder_ExecuteMethod shall return NULL. ]*/
+                LogError("Failed allocating relative method path");
+                result = NULL;
+            }
+            else
+            {
+                strncpy(relativeMethodPath, fullMethodName, relativeMethodPathLength);
+                relativeMethodPath[relativeMethodPathLength] = 0;
+
+                /* no slash found, this must be an method */
+                result = DecodeAndExecuteModelMethod(commandDecoderInstance, schemaHandle, modelHandle, relativeMethodPath, methodName, methodTree);
+
+                free(relativeMethodPath);
+                methodName = NULL;
+            }
+            break;
+        }
+        else
+        {
+            /* found a slash, get the child model name */
+            size_t modelLength = slashPos - methodName;
+            char* childModelName = (char*)malloc(modelLength + 1);
+            if (childModelName == NULL)
+            {
+                /*Codes_SRS_COMMAND_DECODER_02_023: [ If any of the previous operations fail, then CommandDecoder_ExecuteMethod shall return NULL. ]*/
+                LogError("Failed allocating child model name");
+                result = NULL;
+                break;
+            }
+            else
+            {
+                strncpy(childModelName, methodName, modelLength);
+                childModelName[modelLength] = 0;
+
+                /* find the model */
+                modelHandle = Schema_GetModelModelByName(modelHandle, childModelName);
+                if (modelHandle == NULL)
+                {
+                    /*Codes_SRS_COMMAND_DECODER_02_023: [ If any of the previous operations fail, then CommandDecoder_ExecuteMethod shall return NULL. ]*/
+                    LogError("Getting the model %s failed", childModelName);
+                    free(childModelName);
+                    result = NULL;
+                    break;
+                }
+                else
+                {
+                    free(childModelName);
+                    methodName = slashPos + 1;
+                    result = NULL; /*this only exists to quench a compiler warning about returning an uninitialized variable, which is not possible by design*/
+                }
+            }
+        }
+    } while (methodName != NULL);
+    return result;
+}
+
+static EXECUTE_COMMAND_RESULT DecodeCommand(COMMAND_DECODER_HANDLE_DATA* commandDecoderInstance, MULTITREE_HANDLE commandNode)
+{
+    EXECUTE_COMMAND_RESULT result;
+    SCHEMA_HANDLE schemaHandle;
+
+    /* Codes_SRS_COMMAND_DECODER_99_022:[ CommandDecoder shall use the Schema APIs to obtain the information about the entity set name and namespace] */
+    if ((schemaHandle = Schema_GetSchemaForModelType(commandDecoderInstance->ModelHandle)) == NULL)
+    {
+        /* Codes_SRS_COMMAND_DECODER_99_010:[ If any Schema API fails then the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.]*/
+        LogError("Getting schema information failed");
+        result = EXECUTE_COMMAND_ERROR;
+    }
+    else
+    {
+        const char* actionName;
+        MULTITREE_HANDLE nameTreeNode;
+
+        /* Codes_SRS_COMMAND_DECODER_01_014: [CommandDecoder shall use the MultiTree APIs to extract a specific element from the command JSON.] */
+        /* Codes_SRS_COMMAND_DECODER_99_006:[ The action name shall be decoded from the element "name" of the command JSON.] */
+        if ((MultiTree_GetChildByName(commandNode, "Name", &nameTreeNode) != MULTITREE_OK) ||
+            (MultiTree_GetValue(nameTreeNode, (const void **)&actionName) != MULTITREE_OK))
+        {
+            /* Codes_SRS_COMMAND_DECODER_01_015: [If any MultiTree API call fails then the processing shall stop and the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.] */
+            LogError("Getting action name failed.");
+            result = EXECUTE_COMMAND_ERROR;
+        }
+        else if (strlen(actionName) < 2)
+        {
+            /* Codes_SRS_COMMAND_DECODER_99_021:[ If the parsing of the command fails for any other reason the command shall not be dispatched.] */
+            LogError("Invalid action name.");
+            result = EXECUTE_COMMAND_ERROR;
+        }
+        else
+        {
+            actionName++;
+            result = ScanActionPathAndExecuteAction(commandDecoderInstance, schemaHandle, actionName, commandNode);
+        }
+    }
+    return result;
+}
+
+static METHODRETURN_HANDLE DecodeMethod(COMMAND_DECODER_HANDLE_DATA* commandDecoderInstance, const char* fullMethodName, MULTITREE_HANDLE methodTree)
+{
+    METHODRETURN_HANDLE result;
+    SCHEMA_HANDLE schemaHandle;
+
+    /*Codes_SRS_COMMAND_DECODER_02_017: [ CommandDecoder_ExecuteMethod shall get the SCHEMA_HANDLE associated with the modelHandle passed at CommandDecoder_Create. ]*/
+    if ((schemaHandle = Schema_GetSchemaForModelType(commandDecoderInstance->ModelHandle)) == NULL)
+    {
+        LogError("Getting schema information failed");
+        result = NULL;
+    }
+    else
+    {
+        result = ScanMethodPathAndExecuteMethod(commandDecoderInstance, schemaHandle, fullMethodName, methodTree);
+
+    }
+    return result;
+}
+
+/*Codes_SRS_COMMAND_DECODER_01_009: [Whenever CommandDecoder_ExecuteCommand is the command shall be decoded and further dispatched to the actionCallback passed in CommandDecoder_Create.]*/
+EXECUTE_COMMAND_RESULT CommandDecoder_ExecuteCommand(COMMAND_DECODER_HANDLE handle, const char* command)
+{
+    EXECUTE_COMMAND_RESULT result;
+    COMMAND_DECODER_HANDLE_DATA* commandDecoderInstance = (COMMAND_DECODER_HANDLE_DATA*)handle;
+    /*Codes_SRS_COMMAND_DECODER_01_010: [If either the buffer or the receiveCallbackContext argument is NULL, the processing shall stop and the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.]*/
+    if (
+        (command == NULL) ||
+        (commandDecoderInstance == NULL)
+    )
+    {
+        LogError("Invalid argument, COMMAND_DECODER_HANDLE handle=%p, const char* command=%p", handle, command);
+        result = EXECUTE_COMMAND_ERROR;
+    }
+    else
+    {
+        size_t size = strlen(command);
+        char* commandJSON;
+
+        /* Codes_SRS_COMMAND_DECODER_01_011: [If the size of the command is 0 then the processing shall stop and the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.]*/
+        if (size == 0)
+        {
+            LogError("Failed because command size is zero");
+            result = EXECUTE_COMMAND_ERROR;
+        }
+        /*Codes_SRS_COMMAND_DECODER_01_013: [If parsing the JSON to a multi tree fails, the processing shall stop and the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.]*/
+        else if ((commandJSON = (char*)malloc(size + 1)) == NULL)
+        {
+            LogError("Failed to allocate temporary storage for the commands JSON");
+            result = EXECUTE_COMMAND_ERROR;
+        }
+        else
+        {
+            MULTITREE_HANDLE commandsTree;
+
+            (void)memcpy(commandJSON, command, size);
+            commandJSON[size] = '\0';
+
+            /* Codes_SRS_COMMAND_DECODER_01_012: [CommandDecoder shall decode the command JSON contained in buffer to a multi-tree by using JSONDecoder_JSON_To_MultiTree.] */
+            if (JSONDecoder_JSON_To_MultiTree(commandJSON, &commandsTree) != JSON_DECODER_OK)
+            {
+                /* Codes_SRS_COMMAND_DECODER_01_013: [If parsing the JSON to a multi tree fails, the processing shall stop and the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.] */
+                LogError("Decoding JSON to a multi tree failed");
+                result = EXECUTE_COMMAND_ERROR;
+            }
+            else
+            {
+                result = DecodeCommand(commandDecoderInstance, commandsTree);
+
+                /* Codes_SRS_COMMAND_DECODER_01_016: [CommandDecoder shall ensure that the multi-tree resulting from JSONDecoder_JSON_To_MultiTree is freed after the commands are executed.] */
+                MultiTree_Destroy(commandsTree);
+            }
+
+            free(commandJSON);
+        }
+    }
+    return result;
+}
+
+METHODRETURN_HANDLE CommandDecoder_ExecuteMethod(COMMAND_DECODER_HANDLE handle, const char* fullMethodName, const char* methodPayload)
+{
+    METHODRETURN_HANDLE result;
+    /*Codes_SRS_COMMAND_DECODER_02_014: [ If handle is NULL then CommandDecoder_ExecuteMethod shall fail and return NULL. ]*/
+    /*Codes_SRS_COMMAND_DECODER_02_015: [ If fulMethodName is NULL then CommandDecoder_ExecuteMethod shall fail and return NULL. ]*/
+    if (
+        (handle == NULL) ||
+        (fullMethodName == NULL) /*methodPayload can be NULL*/
+        )
+    {
+        LogError("Invalid argument, COMMAND_DECODER_HANDLE handle=%p, const char* fullMethodName=%p", handle, fullMethodName);
+        result = NULL;
+    }
+    else
+    {
+        COMMAND_DECODER_HANDLE_DATA* commandDecoderInstance = (COMMAND_DECODER_HANDLE_DATA*)handle;
+        /*Codes_SRS_COMMAND_DECODER_02_025: [ If methodCallback is NULL then CommandDecoder_ExecuteMethod shall fail and return NULL. ]*/
+        if (commandDecoderInstance->methodCallback == NULL)
+        {
+            LogError("unable to execute a method when the methodCallback passed in CommandDecoder_Create is NULL");
+            result = NULL;
+        }
+        else
+        {
+            /*Codes_SRS_COMMAND_DECODER_02_016: [ If methodPayload is not NULL then CommandDecoder_ExecuteMethod shall build a MULTITREE_HANDLE out of methodPayload. ]*/
+            if (methodPayload == NULL)
+            {
+                result = DecodeMethod(commandDecoderInstance, fullMethodName, NULL);
+            }
+            else
+            {
+                char* methodJSON;
+
+                if (mallocAndStrcpy_s(&methodJSON, methodPayload) != 0)
+                {
+                    LogError("Failed to allocate temporary storage for the method JSON");
+                    result = NULL;
+                }
+                else
+                {
+                    MULTITREE_HANDLE methodTree;
+                    if (JSONDecoder_JSON_To_MultiTree(methodJSON, &methodTree) != JSON_DECODER_OK)
+                    {
+                        LogError("Decoding JSON to a multi tree failed");
+                        result = NULL;
+                    }
+                    else
+                    {
+                        result = DecodeMethod(commandDecoderInstance, fullMethodName, methodTree);
+                        MultiTree_Destroy(methodTree);
+                    }
+                    free(methodJSON);
+                }
+            }
+        }
+    }
+    return result;
+}
+
+
+COMMAND_DECODER_HANDLE CommandDecoder_Create(SCHEMA_MODEL_TYPE_HANDLE modelHandle, ACTION_CALLBACK_FUNC actionCallback, void* actionCallbackContext, METHOD_CALLBACK_FUNC methodCallback, void* methodCallbackContext)
+{
+    COMMAND_DECODER_HANDLE_DATA* result;
+    /* Codes_SRS_COMMAND_DECODER_99_019:[ For all exposed APIs argument validity checks shall precede other checks.] */
+    /* Codes_SRS_COMMAND_DECODER_01_003: [ If modelHandle is NULL, CommandDecoder_Create shall return NULL. ]*/
+    if (modelHandle == NULL)
+    {
+        LogError("Invalid arguments: SCHEMA_MODEL_TYPE_HANDLE modelHandle=%p, ACTION_CALLBACK_FUNC actionCallback=%p, void* actionCallbackContext=%p, METHOD_CALLBACK_FUNC methodCallback=%p, void* methodCallbackContext=%p",
+            modelHandle, actionCallback, actionCallbackContext, methodCallback, methodCallbackContext);
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_COMMAND_DECODER_01_001: [CommandDecoder_Create shall create a new instance of a CommandDecoder.] */
+        result = malloc(sizeof(COMMAND_DECODER_HANDLE_DATA));
+        if (result == NULL)
+        {
+            /* Codes_SRS_COMMAND_DECODER_01_004: [If any error is encountered during CommandDecoder_Create CommandDecoder_Create shall return NULL.] */
+            /*return as is*/
+        }
+        else
+        {
+            result->ModelHandle = modelHandle;
+            result->ActionCallback = actionCallback;
+            result->ActionCallbackContext = actionCallbackContext;
+            result->methodCallback = methodCallback;
+            result->methodCallbackContext = methodCallbackContext;
+        }
+    }
+
+    return result;
+}
+
+void CommandDecoder_Destroy(COMMAND_DECODER_HANDLE commandDecoderHandle)
+{
+    /* Codes_SRS_COMMAND_DECODER_01_007: [If CommandDecoder_Destroy is called with a NULL handle, CommandDecoder_Destroy shall do nothing.] */
+    if (commandDecoderHandle != NULL)
+    {
+        COMMAND_DECODER_HANDLE_DATA* commandDecoderInstance = (COMMAND_DECODER_HANDLE_DATA*)commandDecoderHandle;
+
+        /* Codes_SRS_COMMAND_DECODER_01_005: [CommandDecoder_Destroy shall free all resources associated with the commandDecoderHandle instance.] */
+        free(commandDecoderInstance);
+    }
+}
+
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(AGENT_DATA_TYPE_TYPE, AGENT_DATA_TYPE_TYPE_VALUES);
+
+/*validates that the multitree (coming from a JSON) is actually a serialization of the model (complete or incomplete)*/
+/*if the serialization contains more than the model, then it fails.*/
+/*if the serialization does not contain mandatory items from the model, it fails*/
+static bool validateModel_vs_Multitree(void* startAddress, SCHEMA_MODEL_TYPE_HANDLE modelHandle, MULTITREE_HANDLE desiredPropertiesTree, size_t offset)
+{
+
+    bool result;
+    size_t nChildren;
+    size_t nProcessedChildren = 0;
+    (void)MultiTree_GetChildCount(desiredPropertiesTree, &nChildren);
+    for (size_t i = 0;i < nChildren;i++)
+    {
+        MULTITREE_HANDLE child;
+        if (MultiTree_GetChild(desiredPropertiesTree, i, &child) != MULTITREE_OK)
+        {
+            LogError("failure in MultiTree_GetChild");
+            i = nChildren;
+        }
+        else
+        {
+            STRING_HANDLE childName = STRING_new();
+            if (childName == NULL)
+            {
+                LogError("failure to STRING_new");
+                i = nChildren;
+            }
+            else
+            {
+                if (MultiTree_GetName(child, childName) != MULTITREE_OK)
+                {
+                    LogError("failure to MultiTree_GetName");
+                    i = nChildren;
+                }
+                else
+                {
+                    const char *childName_str = STRING_c_str(childName);
+                    SCHEMA_MODEL_ELEMENT elementType = Schema_GetModelElementByName(modelHandle, childName_str);
+                    switch (elementType.elementType)
+                    {
+                        default:
+                        {
+                            LogError("INTERNAL ERROR: unexpected function return");
+                            i = nChildren;
+                            break;
+                        }
+                        case (SCHEMA_PROPERTY):
+                        {
+                            LogError("cannot ingest name (WITH_DATA instead of WITH_DESIRED_PROPERTY): %s", childName_str);
+                            i = nChildren;
+                            break;
+                        }
+                        case (SCHEMA_REPORTED_PROPERTY):
+                        {
+                            LogError("cannot ingest name (WITH_REPORTED_PROPERTY instead of WITH_DESIRED_PROPERTY): %s", childName_str);
+                            i = nChildren;
+                            break;
+                        }
+                        case (SCHEMA_DESIRED_PROPERTY):
+                        {
+                            /*Codes_SRS_COMMAND_DECODER_02_007: [ If the child name corresponds to a desired property then an AGENT_DATA_TYPE shall be constructed from the MULTITREE node. ]*/
+                            SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle = elementType.elementHandle.desiredPropertyHandle;
+
+                            const char* desiredPropertyType = Schema_GetModelDesiredPropertyType(desiredPropertyHandle);
+                            AGENT_DATA_TYPE output;
+                            if (DecodeValueFromNode(Schema_GetSchemaForModelType(modelHandle), &output, child, desiredPropertyType) != 0)
+                            {
+                                LogError("failure in DecodeValueFromNode");
+                                i = nChildren;
+                            }
+                            else
+                            {
+                                /*Codes_SRS_COMMAND_DECODER_02_008: [ The desired property shall be constructed in memory by calling pfDesiredPropertyFromAGENT_DATA_TYPE. ]*/
+                                pfDesiredPropertyFromAGENT_DATA_TYPE leFunction = Schema_GetModelDesiredProperty_pfDesiredPropertyFromAGENT_DATA_TYPE(desiredPropertyHandle);
+                                if (leFunction(&output, (char*)startAddress + offset + Schema_GetModelDesiredProperty_offset(desiredPropertyHandle)) != 0)
+                                {
+                                    LogError("failure in a function that converts from AGENT_DATA_TYPE to C data");
+                                }
+                                else
+                                {
+                                    /*Codes_SRS_COMMAND_DECODER_02_013: [ If the desired property has a non-NULL pfOnDesiredProperty then it shall be called. ]*/
+                                    pfOnDesiredProperty onDesiredProperty = Schema_GetModelDesiredProperty_pfOnDesiredProperty(desiredPropertyHandle);
+                                    if (onDesiredProperty != NULL)
+                                    {
+                                        onDesiredProperty((char*)startAddress + offset);
+                                    }
+                                    nProcessedChildren++;
+                                }
+                                Destroy_AGENT_DATA_TYPE(&output);
+                            }
+
+                            break;
+                        }
+                        case(SCHEMA_MODEL_IN_MODEL):
+                        {
+                            SCHEMA_MODEL_TYPE_HANDLE modelModel = elementType.elementHandle.modelHandle;
+
+                            /*Codes_SRS_COMMAND_DECODER_02_009: [ If the child name corresponds to a model in model then the function shall call itself recursively. ]*/
+                            if (!validateModel_vs_Multitree(startAddress, modelModel, child, offset + Schema_GetModelModelByName_Offset(modelHandle, childName_str)))
+                            {
+                                LogError("failure in validateModel_vs_Multitree");
+                                i = nChildren;
+                            }
+                            else
+                            {
+                                /*if the model in model so happened to be a WITH_DESIRED_PROPERTY... (only those has non_NULL pfOnDesiredProperty) */
+                                /*Codes_SRS_COMMAND_DECODER_02_012: [ If the child model in model has a non-NULL pfOnDesiredProperty then pfOnDesiredProperty shall be called. ]*/
+                                pfOnDesiredProperty onDesiredProperty = Schema_GetModelModelByName_OnDesiredProperty(modelHandle, childName_str);
+                                if (onDesiredProperty != NULL)
+                                {
+                                    onDesiredProperty((char*)startAddress + offset);
+                                }
+
+                                nProcessedChildren++;
+                            }
+
+                            break;
+                        }
+
+                    } /*switch*/
+                }
+                STRING_delete(childName);
+            }
+        }
+    }
+
+    if(nProcessedChildren == nChildren)
+    {
+        /*Codes_SRS_COMMAND_DECODER_02_010: [ If the complete MULTITREE has been parsed then CommandDecoder_IngestDesiredProperties shall succeed and return EXECUTE_COMMAND_SUCCESS. ]*/
+        result = true;
+    }
+    else
+    {
+        /*Codes_SRS_COMMAND_DECODER_02_011: [ Otherwise CommandDecoder_IngestDesiredProperties shall fail and return EXECUTE_COMMAND_FAILED. ]*/
+        LogError("not all constituents of the JSON have been ingested");
+        result = false;
+    }
+    return result;
+}
+
+static EXECUTE_COMMAND_RESULT DecodeDesiredProperties(void* startAddress, COMMAND_DECODER_HANDLE_DATA* handle, MULTITREE_HANDLE desiredPropertiesTree)
+{
+    /*Codes_SRS_COMMAND_DECODER_02_006: [ CommandDecoder_IngestDesiredProperties shall parse the MULTITREEE recursively. ]*/
+    return validateModel_vs_Multitree(startAddress, handle->ModelHandle, desiredPropertiesTree, 0 )?EXECUTE_COMMAND_SUCCESS:EXECUTE_COMMAND_FAILED;
+}
+
+/* Raw JSON has properties we don't need; potentially nodes other than "desired" for full TWIN as well as a $version we don't pass to callees */
+static bool RemoveUnneededTwinProperties(MULTITREE_HANDLE initialParsedTree, bool parseDesiredNode, MULTITREE_HANDLE *desiredPropertiesTree)
+{
+    MULTITREE_HANDLE updateTree;
+    bool result;
+
+    if (parseDesiredNode)
+    {
+        /*Codes_SRS_COMMAND_DECODER_02_014: [ If parseDesiredNode is TRUE, parse only the `desired` part of JSON tree ]*/
+        if (MultiTree_GetChildByName(initialParsedTree, "desired", &updateTree) != MULTITREE_OK)
+        {
+            LogError("Unable to find 'desired' in tree");
+            return false;
+        }
+    }
+    else
+    {
+        // Tree already starts on node we want so just use it.
+        updateTree = initialParsedTree;
+    }
+
+    /*Codes_COMMAND_DECODER_02_015: [ Remove '$version' string from node, if it is present.  It not being present is not an error ]*/
+    MULTITREE_RESULT deleteChildResult = MultiTree_DeleteChild(updateTree, "$version");
+    if ((deleteChildResult == MULTITREE_OK) || (deleteChildResult == MULTITREE_CHILD_NOT_FOUND))
+    {
+        *desiredPropertiesTree = updateTree;
+        result = true;
+    }
+    else
+    {
+        *desiredPropertiesTree = NULL;
+        result = false;
+    }
+
+    return result;
+}
+
+EXECUTE_COMMAND_RESULT CommandDecoder_IngestDesiredProperties(void* startAddress, COMMAND_DECODER_HANDLE handle, const char* jsonPayload, bool parseDesiredNode)
+{
+    EXECUTE_COMMAND_RESULT result;
+
+    /*Codes_SRS_COMMAND_DECODER_02_001: [ If startAddress is NULL then CommandDecoder_IngestDesiredProperties shall fail and return EXECUTE_COMMAND_ERROR. ]*/
+    /*Codes_SRS_COMMAND_DECODER_02_002: [ If handle is NULL then CommandDecoder_IngestDesiredProperties shall fail and return EXECUTE_COMMAND_ERROR. ]*/
+    /*Codes_SRS_COMMAND_DECODER_02_003: [ If jsonPayload is NULL then CommandDecoder_IngestDesiredProperties shall fail and return EXECUTE_COMMAND_ERROR. ]*/
+    if(
+        (startAddress == NULL) ||
+        (handle == NULL) ||
+        (jsonPayload == NULL)
+        )
+    {
+        LogError("invalid argument COMMAND_DECODER_HANDLE handle=%p, const char* jsonPayload=%p", handle, jsonPayload);
+        result = EXECUTE_COMMAND_ERROR;
+    }
+    else
+    {
+        /*Codes_SRS_COMMAND_DECODER_02_004: [ CommandDecoder_IngestDesiredProperties shall clone desiredProperties. ]*/
+        char* copy;
+        if (mallocAndStrcpy_s(&copy, jsonPayload) != 0)
+        {
+            LogError("failure in mallocAndStrcpy_s");
+            result = EXECUTE_COMMAND_FAILED;
+        }
+        else
+        {
+            /*Codes_SRS_COMMAND_DECODER_02_005: [ CommandDecoder_IngestDesiredProperties shall create a MULTITREE_HANDLE ouf of the clone of desiredProperties. ]*/
+            MULTITREE_HANDLE initialParsedTree;
+            MULTITREE_HANDLE desiredPropertiesTree;
+
+            if (JSONDecoder_JSON_To_MultiTree(copy, &initialParsedTree) != JSON_DECODER_OK)
+            {
+                LogError("Decoding JSON to a multi tree failed");
+                result = EXECUTE_COMMAND_ERROR;
+            }
+            else
+            {
+                if (RemoveUnneededTwinProperties(initialParsedTree, parseDesiredNode, &desiredPropertiesTree) == false)
+                {
+                    LogError("Removing unneeded twin properties failed");
+                    result = EXECUTE_COMMAND_ERROR;
+                }
+                else
+                {
+                    COMMAND_DECODER_HANDLE_DATA* commandDecoderInstance = (COMMAND_DECODER_HANDLE_DATA*)handle;
+
+                    /*Codes_SRS_COMMAND_DECODER_02_006: [ CommandDecoder_IngestDesiredProperties shall parse the MULTITREEE recursively. ]*/
+                    result = DecodeDesiredProperties(startAddress, commandDecoderInstance, desiredPropertiesTree);
+
+                    // Do NOT free desiredPropertiesTree.  It is only a pointer into initialParsedTree.
+                    MultiTree_Destroy(initialParsedTree);
+                }
+            }
+            free(copy);
+        }
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/datamarshaller.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/datamarshaller.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/datamarshaller.c	(revision 453)
@@ -0,0 +1,365 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h> /*for free*/
+#include "azure_c_shared_utility/gballoc.h"
+
+#include <stdbool.h>
+#include "datamarshaller.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "schema.h"
+#include "jsonencoder.h"
+#include "agenttypesystem.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "parson.h"
+#include "azure_c_shared_utility/vector.h"
+
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(DATA_MARSHALLER_RESULT, DATA_MARSHALLER_RESULT_VALUES);
+
+#define LOG_DATA_MARSHALLER_ERROR \
+    LogError("(result = %s)", MU_ENUM_TO_STRING(DATA_MARSHALLER_RESULT, result));
+
+typedef struct DATA_MARSHALLER_HANDLE_DATA_TAG
+{
+    SCHEMA_MODEL_TYPE_HANDLE ModelHandle;
+    bool IncludePropertyPath;
+} DATA_MARSHALLER_HANDLE_DATA;
+
+static int NoCloneFunction(void** destination, const void* source)
+{
+    *destination = (void*)source;
+    return 0;
+}
+
+static void NoFreeFunction(void* value)
+{
+    (void)value;
+}
+
+DATA_MARSHALLER_HANDLE DataMarshaller_Create(SCHEMA_MODEL_TYPE_HANDLE modelHandle, bool includePropertyPath)
+{
+    DATA_MARSHALLER_HANDLE_DATA* result;
+
+    /*Codes_SRS_DATA_MARSHALLER_99_019:[ DataMarshaller_Create shall return NULL if any argument is NULL.]*/
+    if (modelHandle == NULL)
+    {
+        result = NULL;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(DATA_MARSHALLER_RESULT, DATA_MARSHALLER_INVALID_ARG));
+    }
+    else if ((result = (DATA_MARSHALLER_HANDLE_DATA*)calloc(1, sizeof(DATA_MARSHALLER_HANDLE_DATA))) == NULL)
+    {
+        /* Codes_SRS_DATA_MARSHALLER_99_048:[On any other errors not explicitly specified, DataMarshaller_Create shall return NULL.] */
+        result = NULL;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(DATA_MARSHALLER_RESULT, DATA_MARSHALLER_ERROR));
+    }
+    else
+    {
+        /*everything ok*/
+        /*Codes_SRS_DATA_MARSHALLER_99_018:[ DataMarshaller_Create shall create a new DataMarshaller instance and on success it shall return a non NULL handle.]*/
+        result->ModelHandle = modelHandle;
+        result->IncludePropertyPath = includePropertyPath;
+    }
+    return result;
+}
+
+void DataMarshaller_Destroy(DATA_MARSHALLER_HANDLE dataMarshallerHandle)
+{
+    /* Codes_SRS_DATA_MARSHALLER_99_024:[ When called with a NULL handle, DataMarshaller_Destroy shall do nothing.] */
+    if (dataMarshallerHandle != NULL)
+    {
+        /* Codes_SRS_DATA_MARSHALLER_99_022:[ DataMarshaller_Destroy shall free all resources associated with the dataMarshallerHandle argument.] */
+        DATA_MARSHALLER_HANDLE_DATA* dataMarshallerInstance = (DATA_MARSHALLER_HANDLE_DATA*)dataMarshallerHandle;
+        free(dataMarshallerInstance);
+    }
+}
+
+DATA_MARSHALLER_RESULT DataMarshaller_SendData(DATA_MARSHALLER_HANDLE dataMarshallerHandle, size_t valueCount, const DATA_MARSHALLER_VALUE* values, unsigned char** destination, size_t* destinationSize)
+{
+    DATA_MARSHALLER_HANDLE_DATA* dataMarshallerInstance = (DATA_MARSHALLER_HANDLE_DATA*)dataMarshallerHandle;
+    DATA_MARSHALLER_RESULT result;
+    MULTITREE_HANDLE treeHandle;
+
+    /* Codes_SRS_DATA_MARSHALLER_99_034:[All argument checks shall be performed before calling any other modules.] */
+    /* Codes_SRS_DATA_MARSHALLER_99_004:[ DATA_MARSHALLER_INVALID_ARG shall be returned when the function has detected an invalid parameter (NULL) being passed to the function.] */
+    if ((values == NULL) ||
+        (dataMarshallerHandle == NULL) ||
+        (destination == NULL) ||
+        (destinationSize == NULL) ||
+        /* Codes_SRS_DATA_MARSHALLER_99_033:[ DATA_MARSHALLER_INVALID_ARG shall be returned if the valueCount is zero.] */
+        (valueCount == 0))
+    {
+        result = DATA_MARSHALLER_INVALID_ARG;
+        LOG_DATA_MARSHALLER_ERROR
+    }
+    else
+    {
+        size_t i;
+        bool includePropertyPath = dataMarshallerInstance->IncludePropertyPath;
+        /* VS complains wrongly that result is not initialized */
+        result = DATA_MARSHALLER_ERROR;
+
+        for (i = 0; i < valueCount; i++)
+        {
+            if ((values[i].PropertyPath == NULL) ||
+                (values[i].Value == NULL))
+            {
+                /*Codes_SRS_DATA_MARSHALLER_99_007:[ DATA_MARSHALLER_INVALID_MODEL_PROPERTY shall be returned when any of the items in values contain invalid data]*/
+                result = DATA_MARSHALLER_INVALID_MODEL_PROPERTY;
+                LOG_DATA_MARSHALLER_ERROR
+                break;
+            }
+
+            if ((!dataMarshallerInstance->IncludePropertyPath) &&
+                (values[i].Value->type == EDM_COMPLEX_TYPE_TYPE) &&
+                (valueCount > 1))
+            {
+                /* Codes_SRS_DATAMARSHALLER_01_002: [If the includePropertyPath argument passed to DataMarshaller_Create was false and the number of values passed to SendData is greater than 1 and at least one of them is a struct, DataMarshaller_SendData shall fallback to  including the complete property path in the output JSON.] */
+                includePropertyPath = true;
+            }
+        }
+
+        if (i == valueCount)
+        {
+            /* Codes_SRS_DATA_MARSHALLER_99_037:[DataMarshaller shall store as MultiTree the data to be encoded by the JSONEncoder module.] */
+            if ((treeHandle = MultiTree_Create(NoCloneFunction, NoFreeFunction)) == NULL)
+            {
+                /* Codes_SRS_DATA_MARSHALLER_99_035:[DATA_MARSHALLER_MULTITREE_ERROR shall be returned in case any MultiTree API call fails.] */
+                result = DATA_MARSHALLER_MULTITREE_ERROR;
+                LOG_DATA_MARSHALLER_ERROR
+            }
+            else
+            {
+                size_t j;
+                result = DATA_MARSHALLER_OK; /* addressing warning in VS compiler */
+                /* Codes_SRS_DATA_MARSHALLER_99_038:[For each pair in the values argument, a string : value pair shall exist in the JSON object in the form of propertyName : value.] */
+                for (j = 0; j < valueCount; j++)
+                {
+                    if ((includePropertyPath == false) && (values[j].Value->type == EDM_COMPLEX_TYPE_TYPE))
+                    {
+                        size_t k;
+
+                        /* Codes_SRS_DATAMARSHALLER_01_001: [If the includePropertyPath argument passed to DataMarshaller_Create was false and only one struct is being sent, the relative path of the value passed to DataMarshaller_SendData - including property name - shall be ignored and the value shall be placed at JSON root.] */
+                        for (k = 0; k < values[j].Value->value.edmComplexType.nMembers; k++)
+                        {
+                            /* Codes_SRS_DATAMARSHALLER_01_004: [In this case the members of the struct shall be added as leafs into the MultiTree, each leaf having the name of the struct member.] */
+                            if (MultiTree_AddLeaf(treeHandle, values[j].Value->value.edmComplexType.fields[k].fieldName, (void*)values[j].Value->value.edmComplexType.fields[k].value) != MULTITREE_OK)
+                            {
+                                break;
+                            }
+                        }
+
+                        if (k < values[j].Value->value.edmComplexType.nMembers)
+                        {
+                            /* Codes_SRS_DATA_MARSHALLER_99_035:[DATA_MARSHALLER_MULTITREE_ERROR shall be returned in case any MultiTree API call fails.] */
+                            result = DATA_MARSHALLER_MULTITREE_ERROR;
+                            LOG_DATA_MARSHALLER_ERROR
+                            break;
+                        }
+                    }
+                    else
+                    {
+                        /* Codes_SRS_DATA_MARSHALLER_99_039:[ If the includePropertyPath argument passed to DataMarshaller_Create was true each property shall be placed in the appropriate position in the JSON according to its path in the model.] */
+                        if (MultiTree_AddLeaf(treeHandle, values[j].PropertyPath, (void*)values[j].Value) != MULTITREE_OK)
+                        {
+                            /* Codes_SRS_DATA_MARSHALLER_99_035:[DATA_MARSHALLER_MULTITREE_ERROR shall be returned in case any MultiTree API call fails.] */
+                            result = DATA_MARSHALLER_MULTITREE_ERROR;
+                            LOG_DATA_MARSHALLER_ERROR
+                            break;
+                        }
+                    }
+
+                }
+
+                if (j == valueCount)
+                {
+                    STRING_HANDLE payload = STRING_new();
+                    if (payload == NULL)
+                    {
+                        result = DATA_MARSHALLER_ERROR;
+                        LOG_DATA_MARSHALLER_ERROR
+                    }
+                    else
+                    {
+                        if (JSONEncoder_EncodeTree(treeHandle, payload, (JSON_ENCODER_TOSTRING_FUNC)AgentDataTypes_ToString) != JSON_ENCODER_OK)
+                        {
+                            /* Codes_SRS_DATA_MARSHALLER_99_027:[ DATA_MARSHALLER_JSON_ENCODER_ERROR shall be returned when JSONEncoder returns an error code.] */
+                            result = DATA_MARSHALLER_JSON_ENCODER_ERROR;
+                            LOG_DATA_MARSHALLER_ERROR
+                        }
+                        else
+                        {
+                            /*Codes_SRS_DATAMARSHALLER_02_007: [DataMarshaller_SendData shall copy in the output parameters *destination, *destinationSize the content and the content length of the encoded JSON tree.] */
+                            size_t resultSize = STRING_length(payload);
+                            unsigned char* temp = malloc(resultSize);
+                            if (temp == NULL)
+                            {
+                                /*Codes_SRS_DATA_MARSHALLER_99_015:[ DATA_MARSHALLER_ERROR shall be returned in all the other error cases not explicitly defined here.]*/
+                                result = DATA_MARSHALLER_ERROR;
+                                LOG_DATA_MARSHALLER_ERROR;
+                            }
+                            else
+                            {
+                                (void)memcpy(temp, STRING_c_str(payload), resultSize);
+                                *destination = temp;
+                                *destinationSize = resultSize;
+                                result = DATA_MARSHALLER_OK;
+                            }
+                        }
+                        STRING_delete(payload);
+                    }
+                } /* if (j==valueCount)*/
+                MultiTree_Destroy(treeHandle);
+            } /* MultiTree_Create */
+        }
+    }
+
+    return result;
+}
+
+
+DATA_MARSHALLER_RESULT DataMarshaller_SendData_ReportedProperties(DATA_MARSHALLER_HANDLE dataMarshallerHandle, VECTOR_HANDLE values, unsigned char** destination, size_t* destinationSize)
+{
+    DATA_MARSHALLER_RESULT result;
+    /*Codes_SRS_DATA_MARSHALLER_02_021: [ If argument dataMarshallerHandle is NULL then DataMarshaller_SendData_ReportedProperties shall fail and return DATA_MARSHALLER_INVALID_ARG. ]*/
+    /*Codes_SRS_DATA_MARSHALLER_02_008: [ If argument values is NULL then DataMarshaller_SendData_ReportedProperties shall fail and return DATA_MARSHALLER_INVALID_ARG. ]*/
+    /*Codes_SRS_DATA_MARSHALLER_02_009: [ If argument destination NULL then DataMarshaller_SendData_ReportedProperties shall fail and return DATA_MARSHALLER_INVALID_ARG. ]*/
+    /*Codes_SRS_DATA_MARSHALLER_02_010: [ If argument destinationSize NULL then DataMarshaller_SendData_ReportedProperties shall fail and return DATA_MARSHALLER_INVALID_ARG. ]*/
+    if (
+        (dataMarshallerHandle == NULL) ||
+        (values == NULL) ||
+        (destination == NULL) ||
+        (destinationSize == NULL)
+        )
+    {
+        LogError("invalid argument DATA_MARSHALLER_HANDLE dataMarshallerHandle=%p, VECTOR_HANDLE values=%p, unsigned char** destination=%p, size_t* destinationSize=%p",
+            dataMarshallerHandle,
+            values,
+            destination,
+            destinationSize);
+        result = DATA_MARSHALLER_INVALID_ARG;
+    }
+    else
+    {
+        /*Codes_SRS_DATA_MARSHALLER_02_012: [ DataMarshaller_SendData_ReportedProperties shall create an empty JSON_Value. ]*/
+        JSON_Value* json = json_value_init_object();
+        if (json == NULL)
+        {
+            /*Codes_SRS_DATA_MARSHALLER_02_019: [ If any failure occurs, DataMarshaller_SendData_ReportedProperties shall fail and return DATA_MARSHALLER_ERROR. ]*/
+            LogError("failure calling json_value_init_object");
+            result = DATA_MARSHALLER_ERROR;
+        }
+        else
+        {
+            /*Codes_SRS_DATA_MARSHALLER_02_013: [ DataMarshaller_SendData_ReportedProperties shall get the object behind the JSON_Value by calling json_object. ]*/
+            JSON_Object* jsonObject = json_object(json);
+            if (jsonObject == NULL)
+            {
+                /*Codes_SRS_DATA_MARSHALLER_02_019: [ If any failure occurs, DataMarshaller_SendData_ReportedProperties shall fail and return DATA_MARSHALLER_ERROR. ]*/
+                LogError("failure calling json_object");
+                result = DATA_MARSHALLER_ERROR;
+            }
+            else
+            {
+                size_t nReportedProperties = VECTOR_size(values), nProcessedProperties = 0;
+
+                for (size_t i = 0;i < nReportedProperties; i++)
+                {
+                    DATA_MARSHALLER_VALUE* v = *(DATA_MARSHALLER_VALUE**)VECTOR_element(values, i);
+                    STRING_HANDLE s = STRING_new();
+                    if (s == NULL)
+                    {
+                        /*Codes_SRS_DATA_MARSHALLER_02_019: [ If any failure occurs, DataMarshaller_SendData_ReportedProperties shall fail and return DATA_MARSHALLER_ERROR. ]*/
+                        LogError("failure calling STRING_new");
+                        i = nReportedProperties;/*forces loop to break, result is set in the "if" following this for*/
+                    }
+                    else
+                    {
+                        /*Codes_SRS_DATA_MARSHALLER_02_014: [ For every reported property, DataMarshaller_SendData_ReportedProperties shall get the reported property's JSON value (as string) by calling AgentDataTypes_ToString. ]*/
+                        if (AgentDataTypes_ToString(s, v->Value) != AGENT_DATA_TYPES_OK)
+                        {
+                            /*Codes_SRS_DATA_MARSHALLER_02_019: [ If any failure occurs, DataMarshaller_SendData_ReportedProperties shall fail and return DATA_MARSHALLER_ERROR. ]*/
+                            LogError("failure calling AgentDataTypes_ToString");
+                            i = nReportedProperties;/*forces loop to break, result is set in the "if" following this for*/
+                        }
+                        else
+                        {
+                            /*Codes_SRS_DATA_MARSHALLER_02_015: [ DataMarshaller_SendData_ReportedProperties shall import the JSON value (as string) by calling json_parse_string. ]*/
+                            JSON_Value * rightSide = json_parse_string(STRING_c_str(s));
+                            if (rightSide == NULL)
+                            {
+                                /*Codes_SRS_DATA_MARSHALLER_02_019: [ If any failure occurs, DataMarshaller_SendData_ReportedProperties shall fail and return DATA_MARSHALLER_ERROR. ]*/
+                                LogError("failure calling json_parse_string");
+                                i = nReportedProperties;/*forces loop to break, result is set in the "if" following this for*/
+                            }
+                            else
+                            {
+                                char* leftSide;
+                                if (mallocAndStrcpy_s(&leftSide, v->PropertyPath) != 0)
+                                {
+                                    /*Codes_SRS_DATA_MARSHALLER_02_019: [ If any failure occurs, DataMarshaller_SendData_ReportedProperties shall fail and return DATA_MARSHALLER_ERROR. ]*/
+                                    LogError("failure calling mallocAndStrcpy_s");
+                                    json_value_free(rightSide);
+                                    i = nReportedProperties;/*forces loop to break, result is set in the "if" following this for*/
+                                }
+                                else
+                                {
+                                    /*Codes_SRS_DATA_MARSHALLER_02_016: [ DataMarshaller_SendData_ReportedProperties shall replace all the occurences of / with . in the reported property paths. ]*/
+                                    char *whereIsSlash;
+                                    while ((whereIsSlash = strchr(leftSide, '/')) != NULL)
+                                    {
+                                        *whereIsSlash = '.';
+                                    }
+
+                                    /*Codes_SRS_DATA_MARSHALLER_02_017: [ DataMarshaller_SendData_ReportedProperties shall use json_object_dotset_value passing the reported property path and the imported json value. ]*/
+                                    /*Codes_SRS_DATA_MARSHALLER_02_011: [ DataMarshaller_SendData_ReportedProperties shall ignore the value of includePropertyPath and shall consider it to be true. ]*/
+                                    if (json_object_dotset_value(jsonObject, leftSide, rightSide) != JSONSuccess)
+                                    {
+                                        /*Codes_SRS_DATA_MARSHALLER_02_019: [ If any failure occurs, DataMarshaller_SendData_ReportedProperties shall fail and return DATA_MARSHALLER_ERROR. ]*/
+                                        LogError("failure calling json_object_dotset_value");
+                                        json_value_free(rightSide);
+                                        i = nReportedProperties;/*forces loop to break, result is set in the "if" following this for*/
+                                    }
+                                    else
+                                    {
+                                        /*all is fine with this property... */
+                                        nProcessedProperties++;
+                                    }
+                                    free(leftSide);
+                                }
+                            }
+                        }
+                        STRING_delete(s);
+                    }
+                }
+
+                if (nProcessedProperties != nReportedProperties)
+                {
+                    result = DATA_MARSHALLER_ERROR;
+                    /*all properties have NOT been processed*/
+                    /*return result as is*/
+                }
+                else
+                {
+                    /*Codes_SRS_DATA_MARSHALLER_02_018: [ DataMarshaller_SendData_ReportedProperties shall use json_serialize_to_string_pretty to produce the output JSON string that fills out parameters destination and destionationSize. ]*/
+                    char* temp = json_serialize_to_string_pretty(json);
+                    if (temp == NULL)
+                    {
+                        /*Codes_SRS_DATA_MARSHALLER_02_019: [ If any failure occurs, DataMarshaller_SendData_ReportedProperties shall fail and return DATA_MARSHALLER_ERROR. ]*/
+                        LogError("failure calling json_serialize_to_string_pretty ");
+                        result = DATA_MARSHALLER_ERROR;
+                    }
+                    else
+                    {
+                        /*Codes_SRS_DATA_MARSHALLER_02_020: [ Otherwise DataMarshaller_SendData_ReportedProperties shall succeed and return DATA_MARSHALLER_OK. ]*/
+                        *destination = (unsigned char*)temp;
+                        *destinationSize = strlen(temp);
+                        result = DATA_MARSHALLER_OK;
+                        /*all is fine... */
+                    }
+                }
+            }
+            json_value_free(json);
+        }
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/datapublisher.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/datapublisher.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/datapublisher.c	(revision 453)
@@ -0,0 +1,571 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "azure_c_shared_utility/gballoc.h"
+
+#include <stdbool.h>
+#include "datapublisher.h"
+#include "jsonencoder.h"
+#include "datamarshaller.h"
+#include "agenttypesystem.h"
+#include "schema.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/vector.h"
+
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(DATA_PUBLISHER_RESULT, DATA_PUBLISHER_RESULT_VALUES)
+
+#define LOG_DATA_PUBLISHER_ERROR \
+    LogError("(result = %s)", MU_ENUM_TO_STRING(DATA_PUBLISHER_RESULT, result))
+
+#define DEFAULT_MAX_BUFFER_SIZE 10240
+/* Codes_SRS_DATA_PUBLISHER_99_066:[ A single value shall be used by all instances of DataPublisher.] */
+/* Codes_SRS_DATA_PUBLISHER_99_067:[ Before any call to DataPublisher_SetMaxBufferSize, the default max buffer size shall be equal to 10KB.] */
+static size_t maxBufferSize_ = DEFAULT_MAX_BUFFER_SIZE;
+
+typedef struct DATA_PUBLISHER_HANDLE_DATA_TAG
+{
+    DATA_MARSHALLER_HANDLE DataMarshallerHandle;
+    SCHEMA_MODEL_TYPE_HANDLE ModelHandle;
+} DATA_PUBLISHER_HANDLE_DATA;
+
+typedef struct TRANSACTION_HANDLE_DATA_TAG
+{
+    DATA_PUBLISHER_HANDLE_DATA* DataPublisherInstance;
+    size_t ValueCount;
+    DATA_MARSHALLER_VALUE* Values;
+} TRANSACTION_HANDLE_DATA;
+
+typedef struct REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA_TAG
+{
+    DATA_PUBLISHER_HANDLE_DATA* DataPublisherInstance;
+    VECTOR_HANDLE value; /*holds (DATA_MARSHALLER_VALUE*) */
+}REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA;
+
+DATA_PUBLISHER_HANDLE DataPublisher_Create(SCHEMA_MODEL_TYPE_HANDLE modelHandle, bool includePropertyPath)
+{
+    DATA_PUBLISHER_HANDLE_DATA* result;
+
+    /* Codes_SRS_DATA_PUBLISHER_99_042:[ If a NULL argument is passed to it, DataPublisher_Create shall return NULL.] */
+    if (modelHandle == NULL)
+    {
+        result = NULL;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(DATA_PUBLISHER_RESULT, DATA_PUBLISHER_INVALID_ARG));
+    }
+    else if ((result = (DATA_PUBLISHER_HANDLE_DATA*)malloc(sizeof(DATA_PUBLISHER_HANDLE_DATA))) == NULL)
+    {
+        /* Codes_SRS_DATA_PUBLISHER_99_047:[ For any other error not specified here, DataPublisher_Create shall return NULL.] */
+        result = NULL;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(DATA_PUBLISHER_RESULT, DATA_PUBLISHER_ERROR));
+    }
+    else
+    {
+        /* Codes_SRS_DATA_PUBLISHER_99_043:[ DataPublisher_Create shall initialize and hold a handle to a DataMarshaller instance.] */
+        /* Codes_SRS_DATA_PUBLISHER_01_001: [DataPublisher_Create shall pass the includePropertyPath argument to DataMarshaller_Create.] */
+        if ((result->DataMarshallerHandle = DataMarshaller_Create(modelHandle, includePropertyPath)) == NULL)
+        {
+            free(result);
+
+            /* Codes_SRS_DATA_PUBLISHER_99_044:[ If the creation of the DataMarshaller instance fails, DataPublisher_Create shall return NULL.] */
+            result = NULL;
+            LogError("(result = %s)", MU_ENUM_TO_STRING(DATA_PUBLISHER_RESULT, DATA_PUBLISHER_MARSHALLER_ERROR));
+        }
+        else
+        {
+            /* Codes_SRS_DATA_PUBLISHER_99_041:[ DataPublisher_Create shall create a new DataPublisher instance and return a non-NULL handle in case of success.] */
+            result->ModelHandle = modelHandle;
+        }
+    }
+
+    return result;
+}
+
+void DataPublisher_Destroy(DATA_PUBLISHER_HANDLE dataPublisherHandle)
+{
+    if (dataPublisherHandle != NULL)
+    {
+        DATA_PUBLISHER_HANDLE_DATA* dataPublisherInstance = (DATA_PUBLISHER_HANDLE_DATA*)dataPublisherHandle;
+        DataMarshaller_Destroy(dataPublisherInstance->DataMarshallerHandle);
+
+        free(dataPublisherHandle);
+    }
+}
+
+TRANSACTION_HANDLE DataPublisher_StartTransaction(DATA_PUBLISHER_HANDLE dataPublisherHandle)
+{
+    TRANSACTION_HANDLE_DATA* transaction;
+
+    /* Codes_SRS_DATA_PUBLISHER_99_038:[ If DataPublisher_StartTransaction is called with a NULL argument it shall return NULL.] */
+    if (dataPublisherHandle == NULL)
+    {
+        transaction = NULL;
+        LogError("(Error code: %s)", MU_ENUM_TO_STRING(DATA_PUBLISHER_RESULT, DATA_PUBLISHER_INVALID_ARG));
+    }
+    else
+    {
+        /* Codes_SRS_DATA_PUBLISHER_99_007:[ A call to DataPublisher_StartTransaction shall start a new transaction.] */
+        transaction = (TRANSACTION_HANDLE_DATA*)calloc(1, sizeof(TRANSACTION_HANDLE_DATA));
+        if (transaction == NULL)
+        {
+            LogError("Allocating transaction failed (Error code: %s)", MU_ENUM_TO_STRING(DATA_PUBLISHER_RESULT, DATA_PUBLISHER_ERROR));
+        }
+        else
+        {
+            transaction->ValueCount = 0;
+            transaction->Values = NULL;
+            transaction->DataPublisherInstance = (DATA_PUBLISHER_HANDLE_DATA*)dataPublisherHandle;
+        }
+    }
+
+    /* Codes_SRS_DATA_PUBLISHER_99_008:[ DataPublisher_StartTransaction shall return a non-NULL handle upon success.] */
+    /* Codes_SRS_DATA_PUBLISHER_99_009:[ DataPublisher_StartTransaction shall return NULL upon failure.] */
+    return transaction;
+}
+
+DATA_PUBLISHER_RESULT DataPublisher_PublishTransacted(TRANSACTION_HANDLE transactionHandle, const char* propertyPath, const AGENT_DATA_TYPE* data)
+{
+    DATA_PUBLISHER_RESULT result;
+    char* propertyPathCopy;
+
+    /* Codes_SRS_DATA_PUBLISHER_99_017:[ When one or more NULL parameter(s) are specified, DataPublisher_PublishTransacted is called with a NULL transactionHandle, it shall return DATA_PUBLISHER_INVALID_ARG.] */
+    if ((transactionHandle == NULL) ||
+        (propertyPath == NULL) ||
+        (data == NULL))
+    {
+        result = DATA_PUBLISHER_INVALID_ARG;
+        LOG_DATA_PUBLISHER_ERROR;
+    }
+    else if (mallocAndStrcpy_s(&propertyPathCopy, propertyPath) != 0)
+    {
+        /* Codes_SRS_DATA_PUBLISHER_99_020:[ For any errors not explicitly mentioned here the DataPublisher APIs shall return DATA_PUBLISHER_ERROR.] */
+        result = DATA_PUBLISHER_ERROR;
+        LOG_DATA_PUBLISHER_ERROR;
+    }
+    else
+    {
+        TRANSACTION_HANDLE_DATA* transaction = (TRANSACTION_HANDLE_DATA*)transactionHandle;
+        AGENT_DATA_TYPE* propertyValue;
+
+        if (!Schema_ModelPropertyByPathExists(transaction->DataPublisherInstance->ModelHandle, propertyPath))
+        {
+            free(propertyPathCopy);
+
+            /* Codes_SRS_DATA_PUBLISHER_99_040:[ When propertyPath does not exist in the supplied model, DataPublisher_Publish shall return DATA_PUBLISHER_SCHEMA_FAILED without dispatching data.] */
+            result = DATA_PUBLISHER_SCHEMA_FAILED;
+            LOG_DATA_PUBLISHER_ERROR;
+        }
+        else if ((propertyValue = (AGENT_DATA_TYPE*)calloc(1, sizeof(AGENT_DATA_TYPE))) == NULL)
+        {
+            free(propertyPathCopy);
+
+            /* Codes_SRS_DATA_PUBLISHER_99_020:[ For any errors not explicitly mentioned here the DataPublisher APIs shall return DATA_PUBLISHER_ERROR.] */
+            result = DATA_PUBLISHER_ERROR;
+            LOG_DATA_PUBLISHER_ERROR;
+        }
+        else if (Create_AGENT_DATA_TYPE_from_AGENT_DATA_TYPE(propertyValue, data) != AGENT_DATA_TYPES_OK)
+        {
+            free(propertyPathCopy);
+            free(propertyValue);
+
+            /* Codes_SRS_DATA_PUBLISHER_99_028:[ If creating the copy fails then DATA_PUBLISHER_AGENT_DATA_TYPES_ERROR shall be returned.] */
+            result = DATA_PUBLISHER_AGENT_DATA_TYPES_ERROR;
+            LOG_DATA_PUBLISHER_ERROR;
+        }
+        else
+        {
+            size_t i;
+            DATA_MARSHALLER_VALUE* propertySlot = NULL;
+
+            /* Codes_SRS_DATA_PUBLISHER_99_019:[ If the same property is associated twice with a transaction, then the last value shall be kept associated with the transaction.] */
+            for (i = 0; i < transaction->ValueCount; i++)
+            {
+                if (strcmp(transaction->Values[i].PropertyPath, propertyPath) == 0)
+                {
+                    propertySlot = &transaction->Values[i];
+                    break;
+                }
+            }
+
+            if (propertySlot == NULL)
+            {
+                DATA_MARSHALLER_VALUE* newValues = (DATA_MARSHALLER_VALUE*)realloc(transaction->Values, sizeof(DATA_MARSHALLER_VALUE)* (transaction->ValueCount + 1));
+                if (newValues != NULL)
+                {
+                    transaction->Values = newValues;
+                    propertySlot = &transaction->Values[transaction->ValueCount];
+                    propertySlot->Value = NULL;
+                    propertySlot->PropertyPath = NULL;
+                    transaction->ValueCount++;
+                }
+            }
+
+            if (propertySlot == NULL)
+            {
+                Destroy_AGENT_DATA_TYPE((AGENT_DATA_TYPE*)propertyValue);
+                free(propertyValue);
+                free(propertyPathCopy);
+
+                /* Codes_SRS_DATA_PUBLISHER_99_020:[ For any errors not explicitly mentioned here the DataPublisher APIs shall return DATA_PUBLISHER_ERROR.] */
+                result = DATA_PUBLISHER_ERROR;
+                LOG_DATA_PUBLISHER_ERROR;
+            }
+            else
+            {
+                if (propertySlot->Value != NULL)
+                {
+                    Destroy_AGENT_DATA_TYPE((AGENT_DATA_TYPE*)propertySlot->Value);
+                    free((AGENT_DATA_TYPE*)propertySlot->Value);
+                }
+                if (propertySlot->PropertyPath != NULL)
+                {
+                    char* existingValue = (char*)propertySlot->PropertyPath;
+                    free(existingValue);
+                }
+
+                /* Codes_SRS_DATA_PUBLISHER_99_016:[ When DataPublisher_PublishTransacted is invoked, DataPublisher shall associate the data with the transaction identified by the transactionHandle argument and return DATA_PUBLISHER_OK. No data shall be dispatched at the time of the call.] */
+                propertySlot->PropertyPath = propertyPathCopy;
+                propertySlot->Value = propertyValue;
+
+                result = DATA_PUBLISHER_OK;
+            }
+        }
+    }
+
+    return result;
+}
+
+DATA_PUBLISHER_RESULT DataPublisher_EndTransaction(TRANSACTION_HANDLE transactionHandle, unsigned char** destination, size_t* destinationSize)
+{
+    DATA_PUBLISHER_RESULT result;
+
+    /*Codes_SRS_DATA_PUBLISHER_02_006: [If the destination argument is NULL, DataPublisher_EndTransaction shall return DATA_PUBLISHER_INVALID_ARG.] */
+    /*Codes_SRS_DATA_PUBLISHER_02_007: [If the destinationSize argument is NULL, DataPublisher_EndTransaction shall return DATA_PUBLISHER_INVALID_ARG.] */
+    if (
+        (transactionHandle == NULL) ||
+        (destination == NULL) ||
+        (destinationSize == NULL)
+        )
+    {
+        /* Codes_SRS_DATA_PUBLISHER_99_011:[ If the transactionHandle argument is NULL, DataPublisher_EndTransaction shall return DATA_PUBLISHER_INVALID_ARG.] */
+        result = DATA_PUBLISHER_INVALID_ARG;
+        LOG_DATA_PUBLISHER_ERROR;
+    }
+    else
+    {
+        TRANSACTION_HANDLE_DATA* transaction = (TRANSACTION_HANDLE_DATA*)transactionHandle;
+
+        if (transaction->ValueCount == 0)
+        {
+            /* Codes_SRS_DATA_PUBLISHER_99_024:[ If no values have been associated with the transaction, no data shall be dispatched
+                                            to DataMarshaller, the transaction shall be discarded and DataPublisher_EndTransaction shall return DATA_PUBLISHER_EMPTY_TRANSACTION.] */
+            result = DATA_PUBLISHER_EMPTY_TRANSACTION;
+            LOG_DATA_PUBLISHER_ERROR;
+        }
+        /* Codes_SRS_DATA_PUBLISHER_99_010:[ A call to DataPublisher_EndTransaction shall mark the end of a transaction and, trigger a dispatch of all the data grouped by that transaction.] */
+        else if (DataMarshaller_SendData(transaction->DataPublisherInstance->DataMarshallerHandle, transaction->ValueCount, transaction->Values, destination, destinationSize) != DATA_MARSHALLER_OK)
+        {
+            /* Codes_SRS_DATA_PUBLISHER_99_025:[ When the DataMarshaller_SendData call fails, DataPublisher_EndTransaction shall return DATA_PUBLISHER_MARSHALLER_ERROR.] */
+            result = DATA_PUBLISHER_MARSHALLER_ERROR;
+            LOG_DATA_PUBLISHER_ERROR;
+        }
+        else
+        {
+            /* Codes_SRS_DATA_PUBLISHER_99_026:[ On success, DataPublisher_EndTransaction shall return DATA_PUBLISHER_OK.] */
+            result = DATA_PUBLISHER_OK;
+        }
+
+        /* Codes_SRS_DATA_PUBLISHER_99_012:[ DataPublisher_EndTransaction shall dispose of any resources associated with the transaction.] */
+        (void)DataPublisher_CancelTransaction(transactionHandle);
+    }
+
+    return result;
+}
+
+DATA_PUBLISHER_RESULT DataPublisher_CancelTransaction(TRANSACTION_HANDLE transactionHandle)
+{
+    DATA_PUBLISHER_RESULT result;
+
+    if (transactionHandle == NULL)
+    {
+        /* Codes_SRS_DATA_PUBLISHER_99_014:[ If the transactionHandle argument is NULL DataPublisher_CancelTransaction shall return DATA_PUBLISHER_INVALID_ARG.] */
+        result = DATA_PUBLISHER_INVALID_ARG;
+        LOG_DATA_PUBLISHER_ERROR;
+    }
+    else
+    {
+        TRANSACTION_HANDLE_DATA* transaction = (TRANSACTION_HANDLE_DATA*)transactionHandle;
+        size_t i;
+
+        /* Codes_SRS_DATA_PUBLISHER_99_015:[ DataPublisher_CancelTransaction shall dispose of any resources associated with the transaction.] */
+        for (i = 0; i < transaction->ValueCount; i++)
+        {
+            Destroy_AGENT_DATA_TYPE((AGENT_DATA_TYPE*)transaction->Values[i].Value);
+            free((char*)transaction->Values[i].PropertyPath);
+            free((AGENT_DATA_TYPE*)transaction->Values[i].Value);
+        }
+
+        /* Codes_SRS_DATA_PUBLISHER_99_015:[ DataPublisher_CancelTransaction shall dispose of any resources associated with the transaction.] */
+        free(transaction->Values);
+        free(transaction);
+
+        /* Codes_SRS_DATA_PUBLISHER_99_013:[ A call to DataPublisher_CancelTransaction shall dispose of the transaction without dispatching
+                                        the data to the DataMarshaller module and it shall return DATA_PUBLISHER_OK.] */
+        result = DATA_PUBLISHER_OK;
+    }
+
+    return result;
+}
+
+/* Codes_SRS_DATA_PUBLISHER_99_065:[ DataPublisher_SetMaxBufferSize shall directly update the value used to limit how much data (in bytes) can be buffered in the BufferStorage instance.] */
+void DataPublisher_SetMaxBufferSize(size_t value)
+{
+    maxBufferSize_ = value;
+}
+
+/* Codes_SRS_DATA_PUBLISHER_99_069:[ DataMarshaller_GetMaxBufferSize shall return the current max buffer size value used by any new instance of DataMarshaller.] */
+size_t DataPublisher_GetMaxBufferSize(void)
+{
+    return maxBufferSize_;
+}
+
+REPORTED_PROPERTIES_TRANSACTION_HANDLE DataPublisher_CreateTransaction_ReportedProperties(DATA_PUBLISHER_HANDLE dataPublisherHandle)
+{
+    REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA* result;
+    /*Codes_SRS_DATA_PUBLISHER_02_027: [ If argument dataPublisherHandle is NULL then DataPublisher_CreateTransaction_ReportedProperties shall fail and return NULL. ]*/
+    if (dataPublisherHandle == NULL)
+    {
+        LogError("invalid argument DATA_PUBLISHER_HANDLE dataPublisherHandle=%p", dataPublisherHandle);
+        result = NULL;
+    }
+    else
+    {
+        /*Codes_SRS_DATA_PUBLISHER_02_028: [ DataPublisher_CreateTransaction_ReportedProperties shall create a VECTOR_HANDLE holding the individual elements of the transaction (DATA_MARSHALLER_VALUE). ]*/
+        result = (REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA*)malloc(sizeof(REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA));
+        if (result == NULL)
+        {
+            /*Codes_SRS_DATA_PUBLISHER_02_029: [ If any error occurs then DataPublisher_CreateTransaction_ReportedProperties shall fail and return NULL. ]*/
+            LogError("unable to malloc");
+            /*return as is */
+        }
+        else
+        {
+            result->value = VECTOR_create(sizeof(DATA_MARSHALLER_VALUE*));
+            if (result->value == NULL)
+            {
+                /*Codes_SRS_DATA_PUBLISHER_02_029: [ If any error occurs then DataPublisher_CreateTransaction_ReportedProperties shall fail and return NULL. ]*/
+                LogError("unable to VECTOR_create");
+                free(result);
+                result = NULL;
+            }
+            else
+            {
+                /*Codes_SRS_DATA_PUBLISHER_02_030: [ Otherwise DataPublisher_CreateTransaction_ReportedProperties shall succeed and return a non-NULL handle. ]*/
+                result->DataPublisherInstance = dataPublisherHandle;
+            }
+        }
+    }
+
+    return result;
+}
+
+static bool reportedPropertyExistsByPath(const void* element, const void* value)
+{
+    DATA_MARSHALLER_VALUE* dataMarshallerValue = *(DATA_MARSHALLER_VALUE**)element;
+    return (strcmp(dataMarshallerValue->PropertyPath, (const char*)value) == 0);
+}
+
+DATA_PUBLISHER_RESULT DataPublisher_PublishTransacted_ReportedProperty(REPORTED_PROPERTIES_TRANSACTION_HANDLE transactionHandle, const char* reportedPropertyPath, const AGENT_DATA_TYPE* data)
+{
+    DATA_PUBLISHER_RESULT result;
+    /*Codes_SRS_DATA_PUBLISHER_02_009: [ If argument transactionHandle is NULL then DataPublisher_PublishTransacted_ReportedProperty shall fail and return DATA_PUBLISHER_INVALID_ARG. ]*/
+    /*Codes_SRS_DATA_PUBLISHER_02_010: [ If argument reportedPropertyPath is NULL then DataPublisher_PublishTransacted_ReportedProperty shall fail and return DATA_PUBLISHER_INVALID_ARG. ]*/
+    /*Codes_SRS_DATA_PUBLISHER_02_011: [ If argument data is NULL then DataPublisher_PublishTransacted_ReportedProperty shall fail and return DATA_PUBLISHER_INVALID_ARG. ]*/
+    if (
+        (transactionHandle == NULL) ||
+        (reportedPropertyPath == NULL) ||
+        (data == NULL)
+        )
+    {
+        LogError("invalid argument REPORTED_PROPERTIES_TRANSACTION_HANDLE transactionHandle=%p, const char* reportedPropertyPath=%p, const AGENT_DATA_TYPE* data=%p", transactionHandle, reportedPropertyPath, data);
+        result = DATA_PUBLISHER_INVALID_ARG;
+    }
+    else
+    {
+        REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA* handleData = (REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA*)transactionHandle;
+        /*Codes_SRS_DATA_PUBLISHER_02_012: [ DataPublisher_PublishTransacted_ReportedProperty shall verify that a reported property having the path reportedPropertyPath exists in the model by calling Schema_ModelReportedPropertyByPathExists ]*/
+        if (!Schema_ModelReportedPropertyByPathExists(handleData->DataPublisherInstance->ModelHandle, reportedPropertyPath))
+        {
+            /*Codes_SRS_DATA_PUBLISHER_02_013: [ If a reported property with path reportedPropertyPath does not exist in the model then DataPublisher_PublishTransacted_ReportedProperty shall fail and return DATA_PUBLISHER_INVALID_ARG. ]*/
+            LogError("unable to find a reported property by path \"%s\"", reportedPropertyPath);
+            result = DATA_PUBLISHER_INVALID_ARG;
+        }
+        else
+        {
+            DATA_MARSHALLER_VALUE** existingValue = VECTOR_find_if(handleData->value, reportedPropertyExistsByPath, reportedPropertyPath);
+            if(existingValue != NULL)
+            {
+                /*Codes_SRS_DATA_PUBLISHER_02_014: [ If the same (by reportedPropertypath) reported property has already been added to the transaction, then DataPublisher_PublishTransacted_ReportedProperty shall overwrite the previous reported property. ]*/
+                AGENT_DATA_TYPE *clone = (AGENT_DATA_TYPE *)calloc(1, sizeof(AGENT_DATA_TYPE));
+                if(clone == NULL)
+                {
+                    /*Codes_SRS_DATA_PUBLISHER_02_016: [ If any error occurs then DataPublisher_PublishTransacted_ReportedProperty shall fail and return DATA_PUBLISHER_ERROR. ]*/
+                    LogError("unable to malloc");
+                    result = DATA_PUBLISHER_ERROR;
+                }
+                else
+                {
+                    if (Create_AGENT_DATA_TYPE_from_AGENT_DATA_TYPE(clone, data) != AGENT_DATA_TYPES_OK)
+                    {
+                        /*Codes_SRS_DATA_PUBLISHER_02_016: [ If any error occurs then DataPublisher_PublishTransacted_ReportedProperty shall fail and return DATA_PUBLISHER_ERROR. ]*/
+                        LogError("unable to Create_AGENT_DATA_TYPE_from_AGENT_DATA_TYPE");
+                        free(clone);
+                        result = DATA_PUBLISHER_ERROR;
+                    }
+                    else
+                    {
+                        /*Codes_SRS_DATA_PUBLISHER_02_017: [ Otherwise DataPublisher_PublishTransacted_ReportedProperty shall succeed and return DATA_PUBLISHER_OK. ]*/
+                        Destroy_AGENT_DATA_TYPE((AGENT_DATA_TYPE*)((*existingValue)->Value));
+                        free((void*)((*existingValue)->Value));
+                        (*existingValue)->Value = clone;
+                        result = DATA_PUBLISHER_OK;
+                    }
+                }
+            }
+            else
+            {
+                /*totally new reported property*/
+                DATA_MARSHALLER_VALUE* newValue = (DATA_MARSHALLER_VALUE*)malloc(sizeof(DATA_MARSHALLER_VALUE));
+                if (newValue == NULL)
+                {
+                    /*Codes_SRS_DATA_PUBLISHER_02_016: [ If any error occurs then DataPublisher_PublishTransacted_ReportedProperty shall fail and return DATA_PUBLISHER_ERROR. ]*/
+                    LogError("unable to malloc");
+                    result = DATA_PUBLISHER_ERROR;
+                }
+                else
+                {
+                    if (mallocAndStrcpy_s((char**)&(newValue->PropertyPath), reportedPropertyPath) != 0)
+                    {
+                        /*Codes_SRS_DATA_PUBLISHER_02_016: [ If any error occurs then DataPublisher_PublishTransacted_ReportedProperty shall fail and return DATA_PUBLISHER_ERROR. ]*/
+                        LogError("unable to mallocAndStrcpy_s");
+                        free(newValue);
+                        result = DATA_PUBLISHER_ERROR;
+                    }
+                    else
+                    {
+                        if ((newValue->Value = (AGENT_DATA_TYPE*)calloc(1, sizeof(AGENT_DATA_TYPE))) == NULL)
+                        {
+                            LogError("unable to malloc");
+                            free((void*)newValue->PropertyPath);
+                            free(newValue);
+                            result = DATA_PUBLISHER_ERROR;
+                        }
+                        else
+                        {
+                            if (Create_AGENT_DATA_TYPE_from_AGENT_DATA_TYPE((AGENT_DATA_TYPE*)newValue->Value, data) != AGENT_DATA_TYPES_OK)
+                            {
+                                /*Codes_SRS_DATA_PUBLISHER_02_016: [ If any error occurs then DataPublisher_PublishTransacted_ReportedProperty shall fail and return DATA_PUBLISHER_ERROR. ]*/
+                                LogError("unable to Create_AGENT_DATA_TYPE_from_AGENT_DATA_TYPE");
+                                free((void*)newValue->Value);
+                                free((void*)newValue->PropertyPath);
+                                free(newValue);
+                                result = DATA_PUBLISHER_ERROR;
+                            }
+                            else
+                            {
+                                /*Codes_SRS_DATA_PUBLISHER_02_015: [ DataPublisher_PublishTransacted_ReportedProperty shall add a new DATA_MARSHALLER_VALUE to the VECTOR_HANDLE. ]*/
+                                if (VECTOR_push_back(handleData->value, &newValue, 1) != 0)
+                                {
+                                    /*Codes_SRS_DATA_PUBLISHER_02_016: [ If any error occurs then DataPublisher_PublishTransacted_ReportedProperty shall fail and return DATA_PUBLISHER_ERROR. */
+                                    LogError("unable to VECTOR_push_back");
+                                    Destroy_AGENT_DATA_TYPE((AGENT_DATA_TYPE*)newValue->Value);
+                                    free((void*)newValue->Value);
+                                    free((void*)newValue->PropertyPath);
+                                    free(newValue);
+                                    result = DATA_PUBLISHER_ERROR;
+                                }
+                                else
+                                {
+                                    /*Codes_SRS_DATA_PUBLISHER_02_017: [ Otherwise DataPublisher_PublishTransacted_ReportedProperty shall succeed and return DATA_PUBLISHER_OK. ]*/
+                                    result = DATA_PUBLISHER_OK;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return result;
+}
+
+DATA_PUBLISHER_RESULT DataPublisher_CommitTransaction_ReportedProperties(REPORTED_PROPERTIES_TRANSACTION_HANDLE transactionHandle, unsigned char** destination, size_t* destinationSize)
+{
+    DATA_PUBLISHER_RESULT result;
+    /*Codes_SRS_DATA_PUBLISHER_02_019: [ If argument transactionHandle is NULL then DataPublisher_CommitTransaction_ReportedProperties shall fail and return DATA_PUBLISHER_INVALID_ARG. ]*/
+    /*Codes_SRS_DATA_PUBLISHER_02_020: [ If argument destination is NULL then DataPublisher_CommitTransaction_ReportedProperties shall fail and return DATA_PUBLISHER_INVALID_ARG. ]*/
+    /*Codes_SRS_DATA_PUBLISHER_02_021: [ If argument destinationSize NULL then DataPublisher_CommitTransaction_ReportedProperties shall fail and return DATA_PUBLISHER_INVALID_ARG. ]*/
+    if (
+        (transactionHandle == NULL) ||
+        (destination == NULL) ||
+        (destinationSize == NULL)
+        )
+    {
+        LogError("invalid argument REPORTED_PROPERTIES_TRANSACTION_HANDLE transactionHandle=%p, unsigned char** destination=%p, size_t* destinationSize=%p", transactionHandle, destination, destinationSize);
+        result = DATA_PUBLISHER_INVALID_ARG;
+    }
+    else
+    {
+        /*Codes_SRS_DATA_PUBLISHER_02_031: [ If the transaction contains zero elements then DataPublisher_CommitTransaction_ReportedProperties shall fail and return DATA_PUBLISHER_INVALID_ARG. ]*/
+        REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA* handle = (REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA*)transactionHandle;
+        if (VECTOR_size(handle->value) == 0)
+        {
+            LogError("cannot commit empty transaction");
+            result = DATA_PUBLISHER_INVALID_ARG;
+        }
+        else
+        {
+            /*Codes_SRS_DATA_PUBLISHER_02_022: [ DataPublisher_CommitTransaction_ReportedProperties shall call DataMarshaller_SendData_ReportedProperties providing the VECTOR_HANDLE holding the transacted reported properties, destination and destinationSize. ]*/
+            if (DataMarshaller_SendData_ReportedProperties(handle->DataPublisherInstance->DataMarshallerHandle, handle->value, destination, destinationSize) != DATA_MARSHALLER_OK)
+            {
+                /*Codes_SRS_DATA_PUBLISHER_02_023: [ If any error occurs then DataPublisher_CommitTransaction_ReportedProperties shall fail and return DATA_PUBLISHER_ERROR. ]*/
+                LogError("unable to DataMarshaller_SendData_ReportedProperties");
+                result = DATA_PUBLISHER_ERROR;
+            }
+            else
+            {
+                /*Codes_SRS_DATA_PUBLISHER_02_024: [ Otherwise DataPublisher_CommitTransaction_ReportedProperties shall succeed and return DATA_PUBLISHER_OK. ]*/
+                result = DATA_PUBLISHER_OK;
+            }
+        }
+    }
+
+    return result;
+}
+
+void DataPublisher_DestroyTransaction_ReportedProperties(REPORTED_PROPERTIES_TRANSACTION_HANDLE transactionHandle)
+{
+    /*Codes_SRS_DATA_PUBLISHER_02_025: [ If argument transactionHandle is NULL then DataPublisher_DestroyTransaction_ReportedProperties shall return. ]*/
+    if (transactionHandle == NULL)
+    {
+        LogError("invalig argument REPORTED_PROPERTIES_TRANSACTION_HANDLE transactionHandle=%p", transactionHandle);
+    }
+    else
+    {
+        /*Codes_SRS_DATA_PUBLISHER_02_026: [ Otherwise DataPublisher_DestroyTransaction_ReportedProperties shall free all resources associated with the reported properties transactionHandle. ]*/
+        REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA* handleData = (REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA*)transactionHandle;
+        size_t i, nReportedProperties;
+        nReportedProperties = VECTOR_size(handleData->value);
+        for (i = 0;i < nReportedProperties;i++)
+        {
+            DATA_MARSHALLER_VALUE *value = *(DATA_MARSHALLER_VALUE**)VECTOR_element(handleData->value, i);
+            Destroy_AGENT_DATA_TYPE((AGENT_DATA_TYPE*)value->Value);
+            free((void*)value->Value);
+            free((void*)value->PropertyPath);
+            free((void*)value);
+        }
+        VECTOR_destroy(handleData->value);
+        free(handleData);
+    }
+    return;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/dataserializer.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/dataserializer.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/dataserializer.c	(revision 453)
@@ -0,0 +1,58 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include "azure_c_shared_utility/gballoc.h"
+
+#include "dataserializer.h"
+#include "azure_c_shared_utility/xlogging.h"
+
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(DATA_SERIALIZER_RESULT, DATA_SERIALIZER_RESULT_VALUES);
+
+BUFFER_HANDLE DataSerializer_Encode(MULTITREE_HANDLE multiTreeHandle, DATA_SERIALIZER_MULTITREE_TYPE dataType, DATA_SERIALIZER_ENCODE_FUNC encodeFunc)
+{
+    BUFFER_HANDLE pBuffer;
+
+    /* Codes_SRS_DATA_SERIALIZER_07_003: [NULL shall be returned when an invalid parameter is supplied.] */
+    if (multiTreeHandle == NULL || encodeFunc == NULL)
+    {
+        pBuffer = NULL;
+        LogError("(Error code: %s)", MU_ENUM_TO_STRING(DATA_SERIALIZER_RESULT, DATA_SERIALIZER_INVALID_ARG) );
+    }
+    else
+    {
+        /* Codes_SRS_DATA_SERIALIZER_07_009: [DataSerializer_Encode function shall call into the given DATA_SERIALIZER_ENCODE_FUNC callback with a valid BUFFER object and valid MULTITREE_HANDLE object.] */
+        pBuffer = encodeFunc(multiTreeHandle, dataType);
+        if (pBuffer == NULL)
+        {
+            /* Codes_SRS_DATA_SERIALIZER_07_010: [Upon a DATA_SERIALIZER_ENCODE_FUNC failure the DataSerializer_Encode function shall return NULL.] */
+            LogError("(Error code: %s)", MU_ENUM_TO_STRING(DATA_SERIALIZER_RESULT, DATA_SERIALIZER_ERROR) );
+        }
+    }
+    /* Codes_SRS_DATA_SERIALIZER_07_002: [DataSerializer_Encode shall return a valid BUFFER_HANDLE when the function executes successfully.] */
+    return pBuffer;
+}
+
+MULTITREE_HANDLE DataSerializer_Decode(BUFFER_HANDLE data, DATA_SERIALIZER_DECODE_FUNC decodeFunc)
+{
+    MULTITREE_HANDLE multiTreeHandle;
+
+    /* Codes_SRS_DATA_SERIALIZER_07_007: [NULL shall be returned when an invalid parameter is supplied.] */
+    if (data == NULL || decodeFunc == NULL)
+    {
+        multiTreeHandle = NULL;
+        LogError("(Error code: %s)", MU_ENUM_TO_STRING(DATA_SERIALIZER_RESULT, DATA_SERIALIZER_INVALID_ARG) );
+    }
+    else
+    {
+        /* Codes_SRS_DATA_SERIALIZER_07_012: [DataSerializer_Decode function shall call into the given DATA_SERIALIZER_DECODE_FUNC callback with a valid BUFFER object and valid MULTITREE_HANDLE object.] */
+        multiTreeHandle = decodeFunc(data);
+        if (multiTreeHandle == NULL)
+        {
+            /* Codes_SRS_DATA_SERIALIZER_07_013: [Upon a DATA_SERIALIZER_DECODE_FUNC callback failure the DataSerializer_Encode function Shall return NULL.] */
+            LogError("(Error code: %s)", MU_ENUM_TO_STRING(DATA_SERIALIZER_RESULT, DATA_SERIALIZER_ERROR) );
+        }
+    }
+
+    /* Codes_SRS_DATA_SERIALIZER_07_006: [DataSerializer_Decode shall return a valid MULTITREE_HANDLE when the function executes successfully.] */
+    return multiTreeHandle;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/iotdevice.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/iotdevice.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/iotdevice.c	(revision 453)
@@ -0,0 +1,450 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "azure_c_shared_utility/gballoc.h"
+
+#include <stdbool.h>
+#include "iotdevice.h"
+#include "datapublisher.h"
+#include "commanddecoder.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/xlogging.h"
+
+#define LOG_DEVICE_ERROR \
+    LogError("(result = %s)", MU_ENUM_TO_STRING(DEVICE_RESULT, result))
+
+
+
+typedef struct DEVICE_HANDLE_DATA_TAG
+{
+    SCHEMA_MODEL_TYPE_HANDLE model;
+    DATA_PUBLISHER_HANDLE dataPublisherHandle;
+    pfDeviceActionCallback deviceActionCallback;
+    void* callbackUserContext;
+    pfDeviceMethodCallback deviceMethodCallback;
+    void* methodCallbackUserContext;
+
+    COMMAND_DECODER_HANDLE commandDecoderHandle;
+} DEVICE_HANDLE_DATA;
+
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(DEVICE_RESULT, DEVICE_RESULT_VALUES);
+
+static EXECUTE_COMMAND_RESULT DeviceInvokeAction(void* actionCallbackContext, const char* relativeActionPath, const char* actionName, size_t argCount, const AGENT_DATA_TYPE* args)
+{
+    EXECUTE_COMMAND_RESULT result;
+
+    /*Codes_SRS_DEVICE_02_011: [If the parameter actionCallbackContent passed the callback is NULL then the callback shall return EXECUTE_COMMAND_ERROR.] */
+    if (actionCallbackContext == NULL)
+    {
+        result = EXECUTE_COMMAND_ERROR;
+        LogError("(Error code = %s)", MU_ENUM_TO_STRING(DEVICE_RESULT, DEVICE_INVALID_ARG));
+    }
+    else
+    {
+        DEVICE_HANDLE_DATA* device = (DEVICE_HANDLE_DATA*)actionCallbackContext;
+
+        /* Codes_SRS_DEVICE_01_052: [When the action callback passed to CommandDecoder is called, Device shall call the appropriate user callback associated with the device handle.] */
+        /* Codes_SRS_DEVICE_01_055: [The value passed in callbackUserContext when creating the device shall be passed to the callback as the value for the callbackUserContext argument.] */
+        result = device->deviceActionCallback((DEVICE_HANDLE)device, device->callbackUserContext, relativeActionPath, actionName, argCount, args);
+    }
+
+    return result;
+}
+
+static METHODRETURN_HANDLE DeviceInvokeMethod(void* methodCallbackContext, const char* relativeMethodPath, const char* methodName, size_t argCount, const AGENT_DATA_TYPE* args)
+{
+    METHODRETURN_HANDLE result;
+
+    if (methodCallbackContext == NULL)
+    {
+        result = NULL;
+        LogError("(Error code = %s)", MU_ENUM_TO_STRING(DEVICE_RESULT, DEVICE_INVALID_ARG));
+    }
+    else
+    {
+        DEVICE_HANDLE_DATA* device = (DEVICE_HANDLE_DATA*)methodCallbackContext;
+
+        result = device->deviceMethodCallback((DEVICE_HANDLE)device, device->methodCallbackUserContext, relativeMethodPath, methodName, argCount, args);
+    }
+
+    return result;
+}
+
+DEVICE_RESULT Device_Create(SCHEMA_MODEL_TYPE_HANDLE modelHandle, pfDeviceActionCallback deviceActionCallback, void* callbackUserContext, pfDeviceMethodCallback methodCallback, void* methodCallbackContext, bool includePropertyPath, DEVICE_HANDLE* deviceHandle)
+{
+    DEVICE_RESULT result;
+
+    /* Codes_SRS_DEVICE_05_014: [If any of the modelHandle, deviceHandle or deviceActionCallback arguments are NULL, Device_Create shall return DEVICE_INVALID_ARG.]*/
+    if (modelHandle == NULL || deviceHandle == NULL || deviceActionCallback == NULL || methodCallback == NULL || methodCallbackContext == NULL)
+    {
+        result = DEVICE_INVALID_ARG;
+        LOG_DEVICE_ERROR;
+    }
+    else
+    {
+        DEVICE_HANDLE_DATA* device = (DEVICE_HANDLE_DATA*)malloc(sizeof(DEVICE_HANDLE_DATA));
+        if (device == NULL)
+        {
+            /* Codes_SRS_DEVICE_05_015: [If an error occurs while trying to create the device, Device_Create shall return DEVICE_ERROR.] */
+            result = DEVICE_ERROR;
+            LOG_DEVICE_ERROR;
+        }
+        else
+        {
+            /* Codes_SRS_DEVICE_01_018: [Device_Create shall create a DataPublisher instance by calling DataPublisher_Create.] */
+            /* Codes_SRS_DEVICE_01_020: [Device_Create shall pass to DataPublisher_Create the FrontDoor instance obtained earlier.] */
+            /* Codes_SRS_DEVICE_01_004: [DeviceCreate shall pass to DataPublisher_create the includePropertyPath argument.] */
+            if ((device->dataPublisherHandle = DataPublisher_Create(modelHandle, includePropertyPath)) == NULL)
+            {
+                free(device);
+
+                /* Codes_SRS_DEVICE_01_019: [If creating the DataPublisher instance fails, Device_Create shall return DEVICE_DATA_PUBLISHER_FAILED.] */
+                result = DEVICE_DATA_PUBLISHER_FAILED;
+                LOG_DEVICE_ERROR;
+            }
+            else
+            {
+                device->model = modelHandle;
+                device->deviceActionCallback = deviceActionCallback;
+                device->callbackUserContext = callbackUserContext;
+                device->deviceMethodCallback = methodCallback;
+                device->methodCallbackUserContext = methodCallbackContext;
+
+                /* Codes_SRS_DEVICE_01_001: [Device_Create shall create a CommandDecoder instance by calling CommandDecoder_Create and passing to it the model handle.] */
+                /* Codes_SRS_DEVICE_01_002: [Device_Create shall also pass to CommandDecoder_Create a callback to be invoked when a command is received and a context that shall be the device handle.] */
+                if ((device->commandDecoderHandle = CommandDecoder_Create(modelHandle, DeviceInvokeAction, device, DeviceInvokeMethod, device)) == NULL)
+                {
+                    DataPublisher_Destroy(device->dataPublisherHandle);
+                    free(device);
+
+                    /* Codes_SRS_DEVICE_01_003: [If CommandDecoder_Create fails, Device_Create shall return DEVICE_COMMAND_DECODER_FAILED.] */
+                    result = DEVICE_COMMAND_DECODER_FAILED;
+                    LOG_DEVICE_ERROR;
+                }
+                else
+                {
+                    /* Codes_SRS_DEVICE_03_003: [The DEVICE_HANDLE shall be provided via the deviceHandle out argument.] */
+                    *deviceHandle = (DEVICE_HANDLE)device;
+                    /* Codes_SRS_DEVICE_03_004: [Device_Create shall return DEVICE_OK upon success.] */
+                    result = DEVICE_OK;
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+/* Codes_SRS_DEVICE_03_006: [Device_Destroy shall free all resources associated with a device.] */
+void Device_Destroy(DEVICE_HANDLE deviceHandle)
+{
+    /* Codes_SRS_DEVICE_03_007: [Device_Destroy will not do anything if deviceHandle is NULL.] */
+    if (deviceHandle != NULL)
+    {
+        DEVICE_HANDLE_DATA* device = (DEVICE_HANDLE_DATA*)deviceHandle;
+
+        DataPublisher_Destroy(device->dataPublisherHandle);
+        CommandDecoder_Destroy(device->commandDecoderHandle);
+
+        free(device);
+    }
+}
+
+TRANSACTION_HANDLE Device_StartTransaction(DEVICE_HANDLE deviceHandle)
+{
+    TRANSACTION_HANDLE result;
+
+    /* Codes_SRS_DEVICE_01_035: [If any argument is NULL, Device_StartTransaction shall return NULL.] */
+    if (deviceHandle == NULL)
+    {
+        result = NULL;
+        LogError("(Error code = %s)", MU_ENUM_TO_STRING(DEVICE_RESULT, DEVICE_INVALID_ARG));
+    }
+    else
+    {
+        DEVICE_HANDLE_DATA* deviceInstance = (DEVICE_HANDLE_DATA*)deviceHandle;
+
+        /* Codes_SRS_DEVICE_01_034: [Device_StartTransaction shall invoke DataPublisher_StartTransaction for the DataPublisher handle associated with the deviceHandle argument.] */
+        /* Codes_SRS_DEVICE_01_043: [On success, Device_StartTransaction shall return a non NULL handle.] */
+        /* Codes_SRS_DEVICE_01_048: [When DataPublisher_StartTransaction fails, Device_StartTransaction shall return NULL.] */
+        result = DataPublisher_StartTransaction(deviceInstance->dataPublisherHandle);
+    }
+
+    return result;
+}
+
+DEVICE_RESULT Device_PublishTransacted(TRANSACTION_HANDLE transactionHandle, const char* propertyPath, const AGENT_DATA_TYPE* data)
+{
+    DEVICE_RESULT result;
+
+    /* Codes_SRS_DEVICE_01_037: [If any argument is NULL, Device_PublishTransacted shall return DEVICE_INVALID_ARG.] */
+    if (
+        (transactionHandle == NULL) ||
+        (propertyPath == NULL) ||
+        (data == NULL)
+       )
+    {
+        result = DEVICE_INVALID_ARG;
+        LOG_DEVICE_ERROR;
+    }
+    /* Codes_SRS_DEVICE_01_036: [Device_PublishTransacted shall invoke DataPublisher_PublishTransacted.] */
+    else if (DataPublisher_PublishTransacted(transactionHandle, propertyPath, data) != DATA_PUBLISHER_OK)
+    {
+        /* Codes_SRS_DEVICE_01_049: [When DataPublisher_PublishTransacted fails, Device_PublishTransacted shall return DEVICE_DATA_PUBLISHER_FAILED.] */
+        result = DEVICE_DATA_PUBLISHER_FAILED;
+        LOG_DEVICE_ERROR;
+    }
+    else
+    {
+        /* Codes_SRS_DEVICE_01_044: [On success, Device_PublishTransacted shall return DEVICE_OK.] */
+        result = DEVICE_OK;
+    }
+
+    return result;
+}
+
+DEVICE_RESULT Device_EndTransaction(TRANSACTION_HANDLE transactionHandle, unsigned char** destination, size_t* destinationSize)
+{
+    DEVICE_RESULT result;
+
+    /* Codes_SRS_DEVICE_01_039: [If any parameter is NULL, Device_EndTransaction shall return DEVICE_INVALID_ARG.]*/
+    if (
+        (transactionHandle == NULL) ||
+        (destination == NULL) ||
+        (destinationSize == NULL)
+        )
+    {
+        result = DEVICE_INVALID_ARG;
+        LOG_DEVICE_ERROR;
+    }
+    /* Codes_SRS_DEVICE_01_038: [Device_EndTransaction shall invoke DataPublisher_EndTransaction.] */
+    else if (DataPublisher_EndTransaction(transactionHandle, destination, destinationSize) != DATA_PUBLISHER_OK)
+    {
+        /* Codes_SRS_DEVICE_01_050: [When DataPublisher_EndTransaction fails, Device_EndTransaction shall return DEVICE_DATA_PUBLISHER_FAILED.] */
+        result = DEVICE_DATA_PUBLISHER_FAILED;
+        LOG_DEVICE_ERROR;
+    }
+    else
+    {
+        /* Codes_SRS_DEVICE_01_045: [On success, Device_EndTransaction shall return DEVICE_OK.] */
+        result = DEVICE_OK;
+    }
+
+    return result;
+}
+
+DEVICE_RESULT Device_CancelTransaction(TRANSACTION_HANDLE transactionHandle)
+{
+    DEVICE_RESULT result;
+
+    /* Codes_SRS_DEVICE_01_041: [If any argument is NULL, Device_CancelTransaction shall return DEVICE_INVALID_ARG.] */
+    if (transactionHandle == NULL)
+    {
+        result = DEVICE_INVALID_ARG;
+        LOG_DEVICE_ERROR;
+    }
+    /* Codes_SRS_DEVICE_01_040: [Device_CancelTransaction shall invoke DataPublisher_CancelTransaction.] */
+    else if (DataPublisher_CancelTransaction(transactionHandle) != DATA_PUBLISHER_OK)
+    {
+        /* Codes_SRS_DEVICE_01_051: [When DataPublisher_CancelTransaction fails, Device_CancelTransaction shall return DEVICE_DATA_PUBLISHER_FAILED.] */
+        result = DEVICE_DATA_PUBLISHER_FAILED;
+        LOG_DEVICE_ERROR;
+    }
+    else
+    {
+        /* Codes_SRS_DEVICE_01_046: [On success, Device_PublishTransacted shall return DEVICE_OK.] */
+        result = DEVICE_OK;
+    }
+
+    return result;
+}
+
+EXECUTE_COMMAND_RESULT Device_ExecuteCommand(DEVICE_HANDLE deviceHandle, const char* command)
+{
+    EXECUTE_COMMAND_RESULT result;
+    /*Codes_SRS_DEVICE_02_012: [If any parameters are NULL, then Device_ExecuteCommand shall return EXECUTE_COMMAND_ERROR.] */
+    if (
+        (deviceHandle == NULL) ||
+        (command == NULL)
+        )
+    {
+        result = EXECUTE_COMMAND_ERROR;
+        LogError("invalid parameter (NULL passed to Device_ExecuteCommand DEVICE_HANDLE deviceHandle=%p, const char* command=%p", deviceHandle, command);
+    }
+    else
+    {
+        /*Codes_SRS_DEVICE_02_013: [Otherwise, Device_ExecuteCommand shall call CommandDecoder_ExecuteCommand and return what CommandDecoder_ExecuteCommand is returning.] */
+        DEVICE_HANDLE_DATA* device = (DEVICE_HANDLE_DATA*)deviceHandle;
+        result = CommandDecoder_ExecuteCommand(device->commandDecoderHandle, command);
+    }
+    return result;
+}
+
+METHODRETURN_HANDLE Device_ExecuteMethod(DEVICE_HANDLE deviceHandle, const char* methodName, const char* methodPayload)
+{
+    METHODRETURN_HANDLE result;
+    if (
+        (deviceHandle == NULL) ||
+        (methodName == NULL) /*methodPayload can be NULL*/
+        )
+    {
+        result = NULL;
+        LogError("invalid parameter (NULL passed to Device_ExecuteMethod DEVICE_HANDLE deviceHandle=%p, const char* methodPayload=%p", deviceHandle, methodPayload);
+    }
+    else
+    {
+        DEVICE_HANDLE_DATA* device = (DEVICE_HANDLE_DATA*)deviceHandle;
+        result = CommandDecoder_ExecuteMethod(device->commandDecoderHandle, methodName, methodPayload);
+    }
+    return result;
+}
+
+REPORTED_PROPERTIES_TRANSACTION_HANDLE Device_CreateTransaction_ReportedProperties(DEVICE_HANDLE deviceHandle)
+{
+    REPORTED_PROPERTIES_TRANSACTION_HANDLE result;
+
+    /*Codes_SRS_DEVICE_02_014: [ If argument deviceHandle is NULL then Device_CreateTransaction_ReportedProperties shall fail and return NULL. ]*/
+    if (deviceHandle == NULL)
+    {
+        LogError("invalid argument DEVICE_HANDLE deviceHandle=%p", deviceHandle);
+        result = NULL;
+    }
+    else
+    {
+        DEVICE_HANDLE_DATA* deviceInstance = (DEVICE_HANDLE_DATA*)deviceHandle;
+        /*Codes_SRS_DEVICE_02_015: [ Otherwise, Device_CreateTransaction_ReportedProperties shall call DataPublisher_CreateTransaction_ReportedProperties. ]*/
+        /*Codes_SRS_DEVICE_02_016: [ If DataPublisher_CreateTransaction_ReportedProperties fails then Device_CreateTransaction_ReportedProperties shall fail and return NULL. ]*/
+        /*Codes_SRS_DEVICE_02_017: [ Otherwise Device_CreateTransaction_ReportedProperties shall succeed and return a non-NULL value. ]*/
+        result = DataPublisher_CreateTransaction_ReportedProperties(deviceInstance->dataPublisherHandle);
+        if (result == NULL)
+        {
+            LogError("unable to DataPublisher_CreateTransaction_ReportedProperties");
+            /*return as is*/
+        }
+        else
+        {
+            /*return as is*/
+        }
+    }
+
+    return result;
+}
+
+DEVICE_RESULT Device_PublishTransacted_ReportedProperty(REPORTED_PROPERTIES_TRANSACTION_HANDLE transactionHandle, const char* reportedPropertyPath, const AGENT_DATA_TYPE* data)
+{
+    DEVICE_RESULT result;
+    /*Codes_SRS_DEVICE_02_018: [ If argument transactionHandle is NULL then Device_PublishTransacted_ReportedProperty shall fail and return DEVICE_INVALID_ARG. ]*/
+    /*Codes_SRS_DEVICE_02_019: [ If argument reportedPropertyPath is NULL then Device_PublishTransacted_ReportedProperty shall fail and return DEVICE_INVALID_ARG. ]*/
+    /*Codes_SRS_DEVICE_02_020: [ If argument data is NULL then Device_PublishTransacted_ReportedProperty shall fail and return DEVICE_INVALID_ARG. ]*/
+    if (
+        (transactionHandle == NULL) ||
+        (reportedPropertyPath == NULL) ||
+        (data == NULL)
+        )
+    {
+        LogError("invalid argument REPORTED_PROPERTIES_TRANSACTION_HANDLE transactionHandle=%p, const char* reportedPropertyPath=%s, const AGENT_DATA_TYPE* data=%p", transactionHandle, reportedPropertyPath, data);
+        result = DEVICE_INVALID_ARG;
+    }
+    else
+    {
+        /*Codes_SRS_DEVICE_02_021: [ Device_PublishTransacted_ReportedProperty shall call DataPublisher_PublishTransacted_ReportedProperty. ]*/
+        DATA_PUBLISHER_RESULT r = DataPublisher_PublishTransacted_ReportedProperty(transactionHandle, reportedPropertyPath, data);
+        if (r != DATA_PUBLISHER_OK)
+        {
+            LogError("unable to DataPublisher_PublishTransacted_ReportedProperty");
+            /*Codes_SRS_DEVICE_02_022: [ If DataPublisher_PublishTransacted_ReportedProperty fails then Device_PublishTransacted_ReportedProperty shall fail and return DEVICE_DATA_PUBLISHER_FAILED. ]*/
+            result = DEVICE_DATA_PUBLISHER_FAILED;
+        }
+        else
+        {
+            /*Codes_SRS_DEVICE_02_023: [ Otherwise, Device_PublishTransacted_ReportedProperty shall succeed and return DEVICE_OK. ]*/
+            result = DEVICE_OK;
+        }
+    }
+    return result;
+}
+
+DEVICE_RESULT Device_CommitTransaction_ReportedProperties(REPORTED_PROPERTIES_TRANSACTION_HANDLE transactionHandle, unsigned char** destination, size_t* destinationSize)
+{
+    DEVICE_RESULT result;
+
+    /*Codes_SRS_DEVICE_02_024: [ If argument transactionHandle is NULL then Device_CommitTransaction_ReportedProperties shall fail and return DEVICE_INVALID_ARG. ]*/
+    /*Codes_SRS_DEVICE_02_025: [ If argument destination is NULL then Device_CommitTransaction_ReportedProperties shall fail and return DEVICE_INVALID_ARG. ]*/
+    /*Codes_SRS_DEVICE_02_026: [ If argument destinationSize is NULL then Device_CommitTransaction_ReportedProperties shall fail and return DEVICE_INVALID_ARG. ]*/
+    if (
+        (transactionHandle == NULL) ||
+        (destination == NULL) ||
+        (destinationSize == NULL)
+        )
+    {
+        LogError("invalid argument REPORTED_PROPERTIES_TRANSACTION_HANDLE transactionHandle=%p, unsigned char** destination=%p, size_t* destinationSize=%p", transactionHandle, destination, destinationSize);
+        result = DEVICE_INVALID_ARG;
+    }
+    else
+    {
+        /*Codes_SRS_DEVICE_02_027: [ Device_CommitTransaction_ReportedProperties shall call DataPublisher_CommitTransaction_ReportedProperties. ]*/
+        DATA_PUBLISHER_RESULT r = DataPublisher_CommitTransaction_ReportedProperties(transactionHandle, destination, destinationSize);
+
+        /*Codes_SRS_DEVICE_02_028: [ If DataPublisher_CommitTransaction_ReportedProperties fails then Device_CommitTransaction_ReportedProperties shall fail and return DEVICE_DATA_PUBLISHER_FAILED. ]*/
+        if (r != DATA_PUBLISHER_OK)
+        {
+            LogError("unable to DataPublisher_CommitTransaction_ReportedProperties");
+            result = DEVICE_DATA_PUBLISHER_FAILED;
+        }
+        else
+        {
+            /*Codes_SRS_DEVICE_02_029: [ Otherwise Device_CommitTransaction_ReportedProperties shall succeed and return DEVICE_OK. ]*/
+            result = DEVICE_OK;
+        }
+    }
+    return result;
+}
+
+void Device_DestroyTransaction_ReportedProperties(REPORTED_PROPERTIES_TRANSACTION_HANDLE transactionHandle)
+{
+    /*Codes_SRS_DEVICE_02_030: [ If argument transactionHandle is NULL then Device_DestroyTransaction_ReportedProperties shall return. ]*/
+    if (transactionHandle == NULL)
+    {
+        LogError("invalid argument REPORTED_PROPERTIES_TRANSACTION_HANDLE transactionHandle=%p", transactionHandle);
+    }
+    else
+    {
+        /*Codes_SRS_DEVICE_02_031: [ Otherwise Device_DestroyTransaction_ReportedProperties shall free all used resources. ]*/
+        DataPublisher_DestroyTransaction_ReportedProperties(transactionHandle);
+    }
+}
+
+DEVICE_RESULT Device_IngestDesiredProperties(void* startAddress, DEVICE_HANDLE deviceHandle, const char* jsonPayload, bool parseDesiredNode)
+{
+    DEVICE_RESULT result;
+    /*Codes_SRS_DEVICE_02_032: [ If deviceHandle is NULL then Device_IngestDesiredProperties shall fail and return DEVICE_INVALID_ARG. ]*/
+    /*Codes_SRS_DEVICE_02_033: [ If jsonPayload is NULL then Device_IngestDesiredProperties shall fail and return DEVICE_INVALID_ARG. ]*/
+    /*Codes_SRS_DEVICE_02_037: [ If startAddress is NULL then Device_IngestDesiredProperties shall fail and return DEVICE_INVALID_ARG. ]*/
+    if (
+        (deviceHandle == NULL) ||
+        (jsonPayload == NULL) ||
+        (startAddress == NULL)
+        )
+    {
+        LogError("invalid argument void* startAddress=%p, DEVICE_HANDLE deviceHandle=%p, const char* jsonPayload=%p\n", startAddress, deviceHandle, jsonPayload);
+        result = DEVICE_INVALID_ARG;
+    }
+    else
+    {
+        /*Codes_SRS_DEVICE_02_034: [ Device_IngestDesiredProperties shall call CommandDecoder_IngestDesiredProperties. ]*/
+        DEVICE_HANDLE_DATA* device = (DEVICE_HANDLE_DATA*)deviceHandle;
+        if (CommandDecoder_IngestDesiredProperties(startAddress, device->commandDecoderHandle, jsonPayload, parseDesiredNode) != EXECUTE_COMMAND_SUCCESS)
+        {
+            /*Codes_SRS_DEVICE_02_035: [ If any failure happens then Device_IngestDesiredProperties shall fail and return DEVICE_ERROR. ]*/
+            LogError("failure in CommandDecoder_IngestDesiredProperties");
+            result = DEVICE_ERROR;
+        }
+        else
+        {
+            /*Codes_SRS_DEVICE_02_036: [ Otherwise, Device_IngestDesiredProperties shall succeed and return DEVICE_OK. ]*/
+            result = DEVICE_OK;
+        }
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/jsondecoder.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/jsondecoder.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/jsondecoder.c	(revision 453)
@@ -0,0 +1,611 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+
+#include "jsondecoder.h"
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stddef.h>
+
+#define IsWhiteSpace(A) (((A) == 0x20) || ((A) == 0x09) || ((A) == 0x0A) || ((A) == 0x0D))
+
+typedef struct PARSER_STATE_TAG
+{
+    char* json;
+} PARSER_STATE;
+
+static JSON_DECODER_RESULT ParseArray(PARSER_STATE* parserState, MULTITREE_HANDLE currentNode);
+static JSON_DECODER_RESULT ParseObject(PARSER_STATE* parserState, MULTITREE_HANDLE currentNode);
+
+/* Codes_SRS_JSON_DECODER_99_049:[ JSONDecoder shall not allocate new string values for the leafs, but rather point to strings in the original JSON.] */
+static void NoFreeFunction(void* value)
+{
+    (void)value;
+}
+
+static int NOPCloneFunction(void** destination, const void* source)
+{
+    *destination = (void**)source;
+    return 0;
+}
+
+void SkipWhiteSpaces(PARSER_STATE* parserState)
+{
+    while ((*(parserState->json) != '\0') && IsWhiteSpace(*(parserState->json)))
+    {
+        parserState->json++;
+    }
+}
+
+static JSON_DECODER_RESULT ParseString(PARSER_STATE* parserState, char** stringBegin)
+{
+    JSON_DECODER_RESULT result = JSON_DECODER_OK;
+    *stringBegin = parserState->json;
+
+    /* Codes_SRS_JSON_DECODER_99_028:[ A string begins and ends with quotation marks.] */
+    if (*(parserState->json) != '"')
+    {
+        /* Codes_SRS_JSON_DECODER_99_007:[ If parsing the JSON fails due to the JSON string being malformed, JSONDecoder_JSON_To_MultiTree shall return JSON_DECODER_PARSE_ERROR.] */
+        result = JSON_DECODER_PARSE_ERROR;
+    }
+    else
+    {
+        parserState->json++;
+        while ((*(parserState->json) != '"') && (*(parserState->json) != '\0'))
+        {
+            /* Codes_SRS_JSON_DECODER_99_030:[ Any character may be escaped.]  */
+            /* Codes_SRS_JSON_DECODER_99_033:[ Alternatively, there are two-character sequence escape  representations of some popular characters.  So, for example, a string containing only a single reverse solidus character may be represented more compactly as "\\".] */
+            if (*(parserState->json) == '\\')
+            {
+                parserState->json++;
+                if (
+                    /* Codes_SRS_JSON_DECODER_99_051:[ %x5C /          ; \    reverse solidus U+005C] */
+                    (*parserState->json == '\\') ||
+                    /* Codes_SRS_JSON_DECODER_99_050:[ %x22 /          ; "    quotation mark  U+0022] */
+                    (*parserState->json == '"') ||
+                    /* Codes_SRS_JSON_DECODER_99_052:[ %x2F /          ; /    solidus         U+002F] */
+                    (*parserState->json == '/') ||
+                    /* Codes_SRS_JSON_DECODER_99_053:[ %x62 /          ; b    backspace       U+0008] */
+                    (*parserState->json == 'b') ||
+                    /* Codes_SRS_JSON_DECODER_99_054:[ %x66 /          ; f    form feed       U+000C] */
+                    (*parserState->json == 'f') ||
+                    /* Codes_SRS_JSON_DECODER_99_055:[ %x6E /          ; n    line feed       U+000A] */
+                    (*parserState->json == 'n') ||
+                    /* Codes_SRS_JSON_DECODER_99_056:[ %x72 /          ; r    carriage return U+000D] */
+                    (*parserState->json == 'r') ||
+                    /* Codes_SRS_JSON_DECODER_99_057:[ %x74 /          ; t    tab             U+0009] */
+                    (*parserState->json == 't'))
+                {
+                    parserState->json++;
+                }
+                else
+                {
+                    /* Codes_SRS_JSON_DECODER_99_007:[ If parsing the JSON fails due to the JSON string being malformed, JSONDecoder_JSON_To_MultiTree shall return JSON_DECODER_PARSE_ERROR.] */
+                    result = JSON_DECODER_PARSE_ERROR;
+                    break;
+                }
+            }
+            else
+            {
+                parserState->json++;
+            }
+        }
+
+        if (*(parserState->json) != '"')
+        {
+            /* Codes_SRS_JSON_DECODER_99_007:[ If parsing the JSON fails due to the JSON string being malformed, JSONDecoder_JSON_To_MultiTree shall return JSON_DECODER_PARSE_ERROR.] */
+            result = JSON_DECODER_PARSE_ERROR;
+        }
+        else
+        {
+            parserState->json++;
+            result = JSON_DECODER_OK;
+        }
+    }
+
+    return result;
+}
+
+static JSON_DECODER_RESULT ParseNumber(PARSER_STATE* parserState)
+{
+    JSON_DECODER_RESULT result = JSON_DECODER_OK;
+    size_t digitCount = 0;
+
+    if (*(parserState->json) == '-')
+    {
+        parserState->json++;
+    }
+
+    /* Codes_SRS_JSON_DECODER_99_043:[ A number contains an integer component that may be prefixed with an optional minus sign, which may be followed by a fraction part and/or an exponent part.] */
+    while (*(parserState->json) != '\0')
+    {
+        /* Codes_SRS_JSON_DECODER_99_044:[ Octal and hex forms are not allowed.] */
+        if (ISDIGIT(*(parserState->json)))
+        {
+            digitCount++;
+            /* simply continue */
+        }
+        else
+        {
+            break;
+        }
+
+        parserState->json++;
+    }
+
+    if ((digitCount == 0) ||
+        /* Codes_SRS_JSON_DECODER_99_045:[ Leading zeros are not allowed.] */
+        ((digitCount > 1) && *(parserState->json - digitCount) == '0'))
+    {
+        /* Codes_SRS_JSON_DECODER_99_007:[ If parsing the JSON fails due to the JSON string being malformed, JSONDecoder_JSON_To_MultiTree shall return JSON_DECODER_PARSE_ERROR.] */
+        result = JSON_DECODER_PARSE_ERROR;
+    }
+    else
+    {
+        /* Codes_SRS_JSON_DECODER_99_046:[ A fraction part is a decimal point followed by one or more digits.] */
+        if (*(parserState->json) == '.')
+        {
+            /* optional fractional part */
+            parserState->json++;
+            digitCount = 0;
+
+            while (*(parserState->json) != '\0')
+            {
+                /* Codes_SRS_JSON_DECODER_99_044:[ Octal and hex forms are not allowed.] */
+                if (ISDIGIT(*(parserState->json)))
+                {
+                    digitCount++;
+                    /* simply continue */
+                }
+                else
+                {
+                    break;
+                }
+
+                parserState->json++;
+            }
+
+            if (digitCount == 0)
+            {
+                /* Codes_SRS_JSON_DECODER_99_007:[ If parsing the JSON fails due to the JSON string being malformed, JSONDecoder_JSON_To_MultiTree shall return JSON_DECODER_PARSE_ERROR.] */
+                result = JSON_DECODER_PARSE_ERROR;
+            }
+        }
+
+        /* Codes_SRS_JSON_DECODER_99_047:[ An exponent part begins with the letter E in upper or lowercase, which may be followed by a plus or minus sign.] */
+        if ((*(parserState->json) == 'e') || (*(parserState->json) == 'E'))
+        {
+            parserState->json++;
+
+            /* optional sign */
+            if ((*(parserState->json) == '-') || (*(parserState->json) == '+'))
+            {
+                parserState->json++;
+            }
+
+            digitCount = 0;
+
+            /* Codes_SRS_JSON_DECODER_99_048:[ The E and optional sign are followed by one or more digits.] */
+            while (*(parserState->json) != '\0')
+            {
+                /* Codes_SRS_JSON_DECODER_99_044:[ Octal and hex forms are not allowed.] */
+                if (ISDIGIT(*(parserState->json)))
+                {
+                    digitCount++;
+                    /* simply continue */
+                }
+                else
+                {
+                    break;
+                }
+
+                parserState->json++;
+            }
+
+            if (digitCount == 0)
+            {
+                /* Codes_SRS_JSON_DECODER_99_007:[ If parsing the JSON fails due to the JSON string being malformed, JSONDecoder_JSON_To_MultiTree shall return JSON_DECODER_PARSE_ERROR.] */
+                result = JSON_DECODER_PARSE_ERROR;
+            }
+        }
+    }
+
+    return result;
+}
+
+static JSON_DECODER_RESULT ParseValue(PARSER_STATE* parserState, MULTITREE_HANDLE currentNode, char** stringBegin)
+{
+    JSON_DECODER_RESULT result;
+
+    SkipWhiteSpaces(parserState);
+
+    if (*(parserState->json) == '"')
+    {
+        result = ParseString(parserState, stringBegin);
+    }
+    /* Codes_SRS_JSON_DECODER_99_018:[ A JSON value MUST be an object, array, number, or string, or one of the following three literal names: false null true] */
+    /* Codes_SRS_JSON_DECODER_99_019:[ The literal names MUST be lowercase.] */
+    /* Codes_SRS_JSON_DECODER_99_020:[ No other literal names are allowed.] */
+    else if (strncmp(parserState->json, "false", 5) == 0)
+    {
+        *stringBegin = parserState->json;
+        parserState->json += 5;
+        result = JSON_DECODER_OK;
+    }
+    else if (strncmp(parserState->json, "true", 4) == 0)
+    {
+        *stringBegin = parserState->json;
+        parserState->json += 4;
+        result = JSON_DECODER_OK;
+    }
+    else if (strncmp(parserState->json, "null", 4) == 0)
+    {
+        *stringBegin = parserState->json;
+        parserState->json += 4;
+        result = JSON_DECODER_OK;
+    }
+    /* Tests_SRS_JSON_DECODER_99_018:[ A JSON value MUST be an object, array, number, or string, or one of the following three literal names: false null true] */
+    else if (*(parserState->json) == '[')
+    {
+        result = ParseArray(parserState, currentNode);
+        *stringBegin = NULL;
+    }
+    else if (*(parserState->json) == '{')
+    {
+        result = ParseObject(parserState, currentNode);
+        *stringBegin = NULL;
+    }
+    else if (
+        (
+            ISDIGIT(*(parserState->json))
+        )
+        || (*(parserState->json) == '-'))
+    {
+        *stringBegin = parserState->json;
+        result = ParseNumber(parserState);
+    }
+    else
+    {
+        /* Codes_SRS_JSON_DECODER_99_007:[ If parsing the JSON fails due to the JSON string being malformed, JSONDecoder_JSON_To_MultiTree shall return JSON_DECODER_PARSE_ERROR.] */
+        result = JSON_DECODER_PARSE_ERROR;
+    }
+
+    return result;
+}
+
+static JSON_DECODER_RESULT ParseColon(PARSER_STATE* parserState)
+{
+    JSON_DECODER_RESULT result;
+
+    SkipWhiteSpaces(parserState);
+    /* Codes_SRS_JSON_DECODER_99_023:[  A single colon comes after each name, separating the name from the value.] */
+    if (*(parserState->json) != ':')
+    {
+        /* Codes_SRS_JSON_DECODER_99_007:[ If parsing the JSON fails due to the JSON string being malformed, JSONDecoder_JSON_To_MultiTree shall return JSON_DECODER_PARSE_ERROR.] */
+        result = JSON_DECODER_PARSE_ERROR;
+    }
+    else
+    {
+        parserState->json++;
+        result = JSON_DECODER_OK;
+    }
+
+    return result;
+}
+
+static JSON_DECODER_RESULT ParseOpenCurly(PARSER_STATE* parserState)
+{
+    JSON_DECODER_RESULT result = JSON_DECODER_OK;
+
+    SkipWhiteSpaces(parserState);
+
+    /* Codes_SRS_JSON_DECODER_99_021:[    An object structure is represented as a pair of curly brackets surrounding zero or more name/value pairs (or members).] */
+    if (*(parserState->json) != '{')
+    {
+        /* Codes_SRS_JSON_DECODER_99_007:[ If parsing the JSON fails due to the JSON string being malformed, JSONDecoder_JSON_To_MultiTree shall return JSON_DECODER_PARSE_ERROR.] */
+        result = JSON_DECODER_PARSE_ERROR;
+    }
+    else
+    {
+        parserState->json++;
+        result = JSON_DECODER_OK;
+    }
+
+    return result;
+}
+
+static JSON_DECODER_RESULT ParseNameValuePair(PARSER_STATE* parserState, MULTITREE_HANDLE currentNode)
+{
+    JSON_DECODER_RESULT result;
+    char* memberNameBegin;
+
+    SkipWhiteSpaces(parserState);
+
+    /* Codes_SRS_JSON_DECODER_99_022:[ A name is a string.] */
+    result = ParseString(parserState, &memberNameBegin);
+    if (result == JSON_DECODER_OK)
+    {
+        char* valueBegin;
+        MULTITREE_HANDLE childNode;
+        *(parserState->json - 1) = 0;
+
+        result = ParseColon(parserState);
+        if (result == JSON_DECODER_OK)
+        {
+            /* Codes_SRS_JSON_DECODER_99_025:[ The names within an object SHOULD be unique.] */
+            /* Multi Tree takes care of not having 2 children with the same name */
+            /* Codes_SRS_JSON_DECODER_99_002:[ JSONDecoder_JSON_To_MultiTree shall use the MultiTree APIs to create the multi tree and add leafs to the multi tree.] */
+            /* Codes_SRS_JSON_DECODER_99_003:[ When a JSON element is decoded from the JSON object then a leaf shall be added to the MultiTree.] */
+            /* Codes_SRS_JSON_DECODER_99_004:[ The leaf node name in the multi tree shall be the JSON element name.] */
+            if (MultiTree_AddChild(currentNode, memberNameBegin + 1, &childNode) != MULTITREE_OK)
+            {
+                /* Codes_SRS_JSON_DECODER_99_038:[ If any MultiTree API fails, JSONDecoder_JSON_To_MultiTree shall return JSON_DECODER_MULTITREE_FAILED.] */
+                result = JSON_DECODER_MULTITREE_FAILED;
+            }
+            else
+            {
+                result = ParseValue(parserState, childNode, &valueBegin);
+                if ((result == JSON_DECODER_OK) && (valueBegin != NULL))
+                {
+                    /* Codes_SRS_JSON_DECODER_99_005:[ The leaf node added in the multi tree shall have the value the string value of the JSON element as parsed from the JSON object.] */
+                    if (MultiTree_SetValue(childNode, valueBegin) != MULTITREE_OK)
+                    {
+                        /* Codes_SRS_JSON_DECODER_99_038:[ If any MultiTree API fails, JSONDecoder_JSON_To_MultiTree shall return JSON_DECODER_MULTITREE_FAILED.] */
+                        result = JSON_DECODER_MULTITREE_FAILED;
+                    }
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+static JSON_DECODER_RESULT ParseObject(PARSER_STATE* parserState, MULTITREE_HANDLE currentNode)
+{
+    JSON_DECODER_RESULT result = ParseOpenCurly(parserState);
+    if (result == JSON_DECODER_OK)
+    {
+        char jsonChar;
+
+        SkipWhiteSpaces(parserState);
+
+        jsonChar = *(parserState->json);
+        while ((jsonChar != '}') && (jsonChar != '\0'))
+        {
+            char* valueEnd;
+
+            /* decode each value */
+            result = ParseNameValuePair(parserState, currentNode);
+            if (result != JSON_DECODER_OK)
+            {
+                break;
+            }
+
+            valueEnd = parserState->json;
+
+            SkipWhiteSpaces(parserState);
+            jsonChar = *(parserState->json);
+            *valueEnd = 0;
+
+            /* Codes_SRS_JSON_DECODER_99_024:[ A single comma separates a value from a following name.] */
+            if (jsonChar == ',')
+            {
+                parserState->json++;
+                /* get the next name/value pair */
+            }
+        }
+
+        if (result != JSON_DECODER_OK)
+        {
+            /* already have error */
+        }
+        else
+        {
+            if (jsonChar != '}')
+            {
+                /* Codes_SRS_JSON_DECODER_99_007:[ If parsing the JSON fails due to the JSON string being malformed, JSONDecoder_JSON_To_MultiTree shall return JSON_DECODER_PARSE_ERROR.] */
+                result = JSON_DECODER_PARSE_ERROR;
+            }
+            else
+            {
+                parserState->json++;
+            }
+        }
+    }
+
+    return result;
+}
+
+static JSON_DECODER_RESULT ParseArray(PARSER_STATE* parserState, MULTITREE_HANDLE currentNode)
+{
+    JSON_DECODER_RESULT result = JSON_DECODER_OK;
+
+    SkipWhiteSpaces(parserState);
+
+    /* Codes_SRS_JSON_DECODER_99_026:[ An array structure is represented as square brackets surrounding zero or more values (or elements).] */
+    if (*(parserState->json) != '[')
+    {
+        /* Codes_SRS_JSON_DECODER_99_007:[ If parsing the JSON fails due to the JSON string being malformed, JSONDecoder_JSON_To_MultiTree shall return JSON_DECODER_PARSE_ERROR.] */
+        result = JSON_DECODER_PARSE_ERROR;
+    }
+    else
+    {
+        char* stringBegin;
+        char jsonChar;
+        int arrayIndex = 0;
+        result = JSON_DECODER_OK;
+
+        parserState->json++;
+
+        SkipWhiteSpaces(parserState);
+
+        jsonChar = *parserState->json;
+        while ((jsonChar != ']') && (jsonChar != '\0'))
+        {
+            char arrayIndexStr[22];
+            MULTITREE_HANDLE childNode;
+
+            /* Codes_SRS_JSON_DECODER_99_039:[ For array elements the multi tree node name shall be the string representation of the array index.] */
+            if (sprintf(arrayIndexStr, "%d", arrayIndex++) < 0)
+            {
+                result = JSON_DECODER_ERROR;
+                break;
+            }
+            /* Codes_SRS_JSON_DECODER_99_003:[ When a JSON element is decoded from the JSON object then a leaf shall be added to the MultiTree.] */
+            else if (MultiTree_AddChild(currentNode, arrayIndexStr, &childNode) != MULTITREE_OK)
+            {
+                /* Codes_SRS_JSON_DECODER_99_038:[ If any MultiTree API fails, JSONDecoder_JSON_To_MultiTree shall return JSON_DECODER_MULTITREE_FAILED.] */
+                result = JSON_DECODER_MULTITREE_FAILED;
+            }
+            else
+            {
+                char* valueEnd;
+
+                /* decode each value */
+                result = ParseValue(parserState, childNode, &stringBegin);
+                if (result != JSON_DECODER_OK)
+                {
+                    break;
+                }
+
+                if (stringBegin != NULL)
+                {
+                    /* Codes_SRS_JSON_DECODER_99_005:[ The leaf node added in the multi tree shall have the value the string value of the JSON element as parsed from the JSON object.] */
+                    if (MultiTree_SetValue(childNode, stringBegin) != MULTITREE_OK)
+                    {
+                        /* Codes_SRS_JSON_DECODER_99_038:[ If any MultiTree API fails, JSONDecoder_JSON_To_MultiTree shall return JSON_DECODER_MULTITREE_FAILED.] */
+                        result = JSON_DECODER_MULTITREE_FAILED;
+                        break;
+                    }
+                }
+
+                valueEnd = parserState->json;
+
+                SkipWhiteSpaces(parserState);
+                jsonChar = *(parserState->json);
+                *valueEnd = 0;
+
+                /* Codes_SRS_JSON_DECODER_99_027:[ Elements are separated by commas.] */
+                if (jsonChar == ',')
+                {
+                    parserState->json++;
+                    /* get the next value pair */
+                }
+                else if (jsonChar == ']')
+                {
+                    break;
+                }
+                else
+                {
+                    /* Codes_SRS_JSON_DECODER_99_007:[ If parsing the JSON fails due to the JSON string being malformed, JSONDecoder_JSON_To_MultiTree shall return JSON_DECODER_PARSE_ERROR.] */
+                    result = JSON_DECODER_PARSE_ERROR;
+                    break;
+                }
+            }
+        }
+
+        if (result != JSON_DECODER_OK)
+        {
+            /* already have error */
+        }
+        else
+        {
+            if (jsonChar != ']')
+            {
+                /* Codes_SRS_JSON_DECODER_99_007:[ If parsing the JSON fails due to the JSON string being malformed, JSONDecoder_JSON_To_MultiTree shall return JSON_DECODER_PARSE_ERROR.] */
+                result = JSON_DECODER_PARSE_ERROR;
+            }
+            else
+            {
+                parserState->json++;
+                SkipWhiteSpaces(parserState);
+            }
+        }
+    }
+
+    return result;
+}
+
+/* Codes_SRS_JSON_DECODER_99_012:[ A JSON text is a serialized object or array.] */
+static JSON_DECODER_RESULT ParseObjectOrArray(PARSER_STATE* parserState, MULTITREE_HANDLE currentNode)
+{
+    JSON_DECODER_RESULT result = JSON_DECODER_PARSE_ERROR;
+
+    SkipWhiteSpaces(parserState);
+
+    if (*(parserState->json) == '{')
+    {
+        result = ParseObject(parserState, currentNode);
+        SkipWhiteSpaces(parserState);
+    }
+    else if (*(parserState->json) == '[')
+    {
+        result = ParseArray(parserState, currentNode);
+        SkipWhiteSpaces(parserState);
+    }
+    else
+    {
+        /* Codes_SRS_JSON_DECODER_99_007:[ If parsing the JSON fails due to the JSON string being malformed, JSONDecoder_JSON_To_MultiTree shall return JSON_DECODER_PARSE_ERROR.] */
+        result = JSON_DECODER_PARSE_ERROR;
+    }
+
+    if ((result == JSON_DECODER_OK) &&
+        (*(parserState->json) != '\0'))
+    {
+        /* Codes_SRS_JSON_DECODER_99_007:[ If parsing the JSON fails due to the JSON string being malformed, JSONDecoder_JSON_To_MultiTree shall return JSON_DECODER_PARSE_ERROR.] */
+        result = JSON_DECODER_PARSE_ERROR;
+    }
+
+    return result;
+}
+
+static JSON_DECODER_RESULT ParseJSON(char* json, MULTITREE_HANDLE currentNode)
+{
+    /* Codes_SRS_JSON_DECODER_99_009:[ On success, JSONDecoder_JSON_To_MultiTree shall return a handle to the multi tree it created in the multiTreeHandle argument and it shall return JSON_DECODER_OK.] */
+    PARSER_STATE parseState;
+    parseState.json = json;
+    return ParseObjectOrArray(&parseState, currentNode);
+}
+
+JSON_DECODER_RESULT JSONDecoder_JSON_To_MultiTree(char* json, MULTITREE_HANDLE* multiTreeHandle)
+{
+    JSON_DECODER_RESULT result;
+
+    if ((json == NULL) ||
+        (multiTreeHandle == NULL))
+    {
+        /* Codes_SRS_JSON_DECODER_99_001:[ If any of the parameters passed to the JSONDecoder_JSON_To_MultiTree function is NULL then the function call shall return JSON_DECODER_INVALID_ARG.] */
+        result = JSON_DECODER_INVALID_ARG;
+    }
+    else if (*json == '\0')
+    {
+        /* Codes_SRS_JSON_DECODER_99_007:[ If parsing the JSON fails due to the JSON string being malformed, JSONDecoder_JSON_To_MultiTree shall return JSON_DECODER_PARSE_ERROR.] */
+        result = JSON_DECODER_PARSE_ERROR;
+    }
+    else
+    {
+        /* Codes_SRS_JSON_DECODER_99_008:[ JSONDecoder_JSON_To_MultiTree shall create a multi tree based on the json string argument.] */
+        /* Codes_SRS_JSON_DECODER_99_002:[ JSONDecoder_JSON_To_MultiTree shall use the MultiTree APIs to create the multi tree and add leafs to the multi tree.] */
+        /* Codes_SRS_JSON_DECODER_99_009:[ On success, JSONDecoder_JSON_To_MultiTree shall return a handle to the multi tree it created in the multiTreeHandle argument and it shall return JSON_DECODER_OK.] */
+        *multiTreeHandle = MultiTree_Create(NOPCloneFunction, NoFreeFunction);
+        if (*multiTreeHandle == NULL)
+        {
+            /* Codes_SRS_JSON_DECODER_99_038:[ If any MultiTree API fails, JSONDecoder_JSON_To_MultiTree shall return JSON_DECODER_MULTITREE_FAILED.] */
+            result = JSON_DECODER_MULTITREE_FAILED;
+        }
+        else
+        {
+            result = ParseJSON(json, *multiTreeHandle);
+            if (result != JSON_DECODER_OK)
+            {
+                MultiTree_Destroy(*multiTreeHandle);
+            }
+        }
+    }
+
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/jsonencoder.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/jsonencoder.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/jsonencoder.c	(revision 453)
@@ -0,0 +1,218 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include "azure_c_shared_utility/gballoc.h"
+
+#include "jsonencoder.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/strings.h"
+
+#ifdef _MSC_VER
+#pragma warning(disable: 4701) /* potentially uninitialized local variable 'result' used */ /* the scanner cannot track variable "i" and link it to childCount*/
+#endif
+
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(JSON_ENCODER_TOSTRING_RESULT, JSON_ENCODER_TOSTRING_RESULT_VALUES);
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(JSON_ENCODER_RESULT, JSON_ENCODER_RESULT_VALUES);
+
+JSON_ENCODER_RESULT JSONEncoder_EncodeTree(MULTITREE_HANDLE treeHandle, STRING_HANDLE destination, JSON_ENCODER_TOSTRING_FUNC toStringFunc)
+{
+    JSON_ENCODER_RESULT result;
+
+    size_t childCount;
+
+    /* Codes_SRS_JSON_ENCODER_99_032:[If any of the arguments passed to JSONEncoder_EncodeTree is NULL then JSON_ENCODER_INVALID_ARG shall be returned.] */
+    if ((treeHandle == NULL) ||
+        (destination == NULL) ||
+        (toStringFunc == NULL))
+    {
+        result = JSON_ENCODER_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(JSON_ENCODER_RESULT, result));
+    }
+    /*Codes_SRS_JSON_ENCODER_99_035:[ JSON encoder shall inquire the number of child nodes (further called childCount) of the current node (given by parameter treeHandle.]*/
+    else if (MultiTree_GetChildCount(treeHandle, &childCount) != MULTITREE_OK)
+    {
+        result = JSON_ENCODER_MULTITREE_ERROR;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(JSON_ENCODER_RESULT, result));
+    }
+    else
+    {
+        size_t i;
+        /*Codes_SRS_JSON_ENCODER_99_036:[ The string "{" shall be added to the output;]*/
+        if (STRING_concat(destination,  "{") != 0)
+        {
+            result = JSON_ENCODER_ERROR;
+            LogError("(result = %s)", MU_ENUM_TO_STRING(JSON_ENCODER_RESULT, result));
+        }
+        else
+        {
+            result = JSON_ENCODER_OK;
+            for (i = 0; (i < childCount) && (result == JSON_ENCODER_OK); i++)
+            {
+                MULTITREE_HANDLE childTreeHandle;
+
+                if ((i > 0) &&
+                    (STRING_concat(destination, ", ") != 0))
+                {
+                    result = JSON_ENCODER_ERROR;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(JSON_ENCODER_RESULT, result));
+                }
+                else if (STRING_concat(destination, "\"") != 0)
+                {
+                    result = JSON_ENCODER_ERROR;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(JSON_ENCODER_RESULT, result));
+                }
+                else
+                {
+                    STRING_HANDLE name = STRING_new();
+                    if (name == NULL)
+                    {
+                        result = JSON_ENCODER_ERROR;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(JSON_ENCODER_RESULT, result));
+                    }
+                    else
+                    {
+                        if (MultiTree_GetChild(treeHandle, i, &childTreeHandle) != MULTITREE_OK)
+                        {
+                            result = JSON_ENCODER_MULTITREE_ERROR;
+                            LogError("(result = %s)", MU_ENUM_TO_STRING(JSON_ENCODER_RESULT, result));
+                        }
+                        else if (MultiTree_GetName(childTreeHandle, name) != MULTITREE_OK)
+                        {
+                            result = JSON_ENCODER_MULTITREE_ERROR;
+                            LogError("(result = %s)", MU_ENUM_TO_STRING(JSON_ENCODER_RESULT, result));
+                        }
+                        else if (STRING_concat_with_STRING(destination, name) != 0)
+                        {
+                            result = JSON_ENCODER_ERROR;
+                            LogError("(result = %s)", MU_ENUM_TO_STRING(JSON_ENCODER_RESULT, result));
+                        }
+                        else if (STRING_concat(destination, "\":") != 0)
+                        {
+                            result = JSON_ENCODER_ERROR;
+                            LogError("(result = %s)", MU_ENUM_TO_STRING(JSON_ENCODER_RESULT, result));
+                        }
+                        else
+                        {
+                            size_t innerChildCount;
+                            if (MultiTree_GetChildCount(childTreeHandle, &innerChildCount) != MULTITREE_OK)
+                            {
+                                result = JSON_ENCODER_MULTITREE_ERROR;
+                                LogError("(result = %s)", MU_ENUM_TO_STRING(JSON_ENCODER_RESULT, result));
+                            }
+                            else
+                            {
+                                if (innerChildCount > 0)
+                                {
+                                    STRING_HANDLE child = STRING_new();
+                                    if (child == NULL)
+                                    {
+                                        result = JSON_ENCODER_ERROR;
+                                        LogError("(result = %s)", MU_ENUM_TO_STRING(JSON_ENCODER_RESULT, result));
+                                    }
+                                    else
+                                    {
+                                        if ((result = JSONEncoder_EncodeTree(childTreeHandle, child, toStringFunc)) != JSON_ENCODER_OK)
+                                        {
+                                            LogError("(result = %s)", MU_ENUM_TO_STRING(JSON_ENCODER_RESULT, result));
+                                        }
+                                        else if (STRING_concat_with_STRING(destination, child)!=0)
+                                        {
+                                            result = JSON_ENCODER_ERROR;
+                                            LogError("(result = %s)", MU_ENUM_TO_STRING(JSON_ENCODER_RESULT, result));
+                                        }
+                                        STRING_delete(child);
+                                    }
+                                }
+                                else
+                                {
+                                    const void* value;
+                                    if (MultiTree_GetValue(childTreeHandle, &value) != MULTITREE_OK)
+                                    {
+                                        result = JSON_ENCODER_MULTITREE_ERROR;
+                                        LogError("(result = %s)", MU_ENUM_TO_STRING(JSON_ENCODER_RESULT, result));
+
+                                    }
+                                    else
+                                    {
+                                        STRING_HANDLE childValue = STRING_new();
+                                        if (childValue == NULL)
+                                        {
+                                            result = JSON_ENCODER_ERROR;
+                                            LogError("(result = %s)", MU_ENUM_TO_STRING(JSON_ENCODER_RESULT, result));
+                                        }
+                                        else
+                                        {
+                                            if (toStringFunc(childValue, value) != JSON_ENCODER_TOSTRING_OK)
+                                            {
+                                                result = JSON_ENCODER_TOSTRING_FUNCTION_ERROR;
+                                                LogError("(result = %s)", MU_ENUM_TO_STRING(JSON_ENCODER_RESULT, result));
+                                            }
+                                            else if (STRING_concat_with_STRING(destination, childValue)!=0)
+                                            {
+                                                result = JSON_ENCODER_ERROR;
+                                                LogError("(result = %s)", MU_ENUM_TO_STRING(JSON_ENCODER_RESULT, result));
+                                            }
+                                            else
+                                            {
+                                                /*do nothing, result = JSON_ENCODER_OK is set above at the beginning of the FOR loop*/
+                                            }
+                                            STRING_delete(childValue);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                        STRING_delete(name);
+                    }
+                }
+            }
+
+            if ((i == childCount) && (result == JSON_ENCODER_OK))
+            {
+                if (STRING_concat(destination,  "}") != 0)
+                {
+                    result = JSON_ENCODER_ERROR;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(JSON_ENCODER_RESULT, result));
+                }
+                else
+                {
+                    /* Codes_SRS_JSON_ENCODER_99_031:[On success, JSONEncoder_EncodeTree shall return JSON_ENCODER_OK.] */
+                    result = JSON_ENCODER_OK;
+                }
+            }
+        }
+    }
+
+    return result;
+#ifdef _MSC_VER
+#pragma warning(disable: 4701) /* potentially uninitialized local variable 'result' used */ /* the scanner cannot track variable "i" and link it to childCount*/
+#endif
+}
+
+JSON_ENCODER_TOSTRING_RESULT JSONEncoder_CharPtr_ToString(STRING_HANDLE destination, const void* value)
+{
+    JSON_ENCODER_TOSTRING_RESULT result;
+
+    /*Coes_SRS_JSON_ENCODER_99_047:[ JSONEncoder_CharPtr_ToString shall return JSON_ENCODER_TOSTRING_INVALID_ARG if destination or value parameters passed to it are NULL.]*/
+    if ((destination == NULL) ||
+        (value == NULL))
+    {
+        result = JSON_ENCODER_TOSTRING_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(JSON_ENCODER_TOSTRING_RESULT, result));
+    }
+    /*Codes_SRS_JSON_ENCODER_99_048:[ JSONEncoder_CharPtr_ToString shall use strcpy_s to copy from value to destination.]*/
+    else if (STRING_concat(destination, (const char*)value) != 0)
+    {
+        /*Codes_SRS_JSON_ENCODER_99_049:[ If strcpy_s fails then JSONEncoder_CharPtr_ToString shall return JSON_ENCODER_TOSTRING_ERROR.]*/
+        result = JSON_ENCODER_TOSTRING_ERROR;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(JSON_ENCODER_TOSTRING_RESULT, result));
+    }
+    else
+    {
+        /*Codes_SRS_JSON_ENCODER_99_050:[ If strcpy_s doesn't fail, then JSONEncoder_CharPtr_ToString shall return JSON_ENCODER_TOSTRING_OK]*/
+        result = JSON_ENCODER_TOSTRING_OK;
+    }
+
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/methodreturn.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/methodreturn.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/methodreturn.c	(revision 453)
@@ -0,0 +1,123 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <limits.h>
+
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/strings.h"
+#include "parson.h"
+
+#include "methodreturn.h"
+
+typedef struct METHODRETURN_HANDLE_DATA_TAG
+{
+    METHODRETURN_DATA data;
+}METHODRETURN_HANDLE_DATA;
+
+bool is_json_present_and_unparsable(const char* jsonValue)
+{
+    bool is_present_and_unparsable;
+    if (jsonValue == NULL)
+    {
+        // Null json is not considered invalid here
+        is_present_and_unparsable = false;
+    }
+    else
+    {
+        JSON_Value* temp = json_parse_string(jsonValue);
+        if (temp == NULL)
+        {
+            is_present_and_unparsable = true;
+        }
+        else
+        {
+            json_value_free(temp);
+            is_present_and_unparsable = false;
+        }
+    }
+    return is_present_and_unparsable;
+}
+
+METHODRETURN_HANDLE MethodReturn_Create(int statusCode, const char* jsonValue)
+{
+    METHODRETURN_HANDLE result;
+    /*Codes_SRS_METHODRETURN_02_009: [ If jsonValue is not a JSON value then MethodReturn_Create shall fail and return NULL. ]*/
+    if (is_json_present_and_unparsable(jsonValue))
+    {
+        LogError("%s is not JSON", jsonValue);
+        result = NULL;
+    }
+    else
+    {
+        result = (METHODRETURN_HANDLE_DATA*)calloc(1, sizeof(METHODRETURN_HANDLE_DATA));
+        if (result == NULL)
+        {
+            /*Codes_SRS_METHODRETURN_02_002: [ If any failure is encountered then MethodReturn_Create shall return NULL ]*/
+            LogError("unable to malloc");
+            /*return as is*/
+        }
+        else
+        {
+            if (jsonValue == NULL)
+            {
+                /*Codes_SRS_METHODRETURN_02_001: [ MethodReturn_Create shall create a non-NULL handle containing statusCode and a clone of jsonValue. ]*/
+                result->data.jsonValue = NULL;
+                result->data.statusCode = statusCode;
+            }
+            else
+            {
+                if (mallocAndStrcpy_s(&(result->data.jsonValue), jsonValue) != 0)
+                {
+                    LogError("failure in mallocAndStrcpy_s");
+                    free(result);
+                    result = NULL;
+                }
+                else
+                {
+                    /*Codes_SRS_METHODRETURN_02_001: [ MethodReturn_Create shall create a non-NULL handle containing statusCode and a clone of jsonValue. ]*/
+                    result->data.statusCode = statusCode;
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+void MethodReturn_Destroy(METHODRETURN_HANDLE handle)
+{
+    if (handle == NULL)
+    {
+        /*Codes_SRS_METHODRETURN_02_003: [ If handle is NULL then MethodReturn_Destroy shall return. ]*/
+        LogError("invalid argument METHODRETURN_HANDLE handle=%p", handle);
+    }
+    else
+    {
+        /*Codes_SRS_METHODRETURN_02_004: [ Otherwise, MethodReturn_Destroy shall free all used resources by handle. ]*/
+        if (handle->data.jsonValue != NULL)
+        {
+            free(handle->data.jsonValue);
+        }
+        free(handle);
+    }
+}
+
+
+const METHODRETURN_DATA* MethodReturn_GetReturn(METHODRETURN_HANDLE handle)
+{
+    const METHODRETURN_DATA* result;
+    if (handle == NULL)
+    {
+        /*Codes_SRS_METHODRETURN_02_010: [ If handle is NULL then MethodReturn_GetReturn shall fail and return NULL. ]*/
+        result = NULL;
+    }
+    else
+    {
+        /*Codes_SRS_METHODRETURN_02_011: [ Otherwise, MethodReturn_GetReturn shall return a non-NULL const pointer to a METHODRETURN_DATA. ]*/
+        result = &(handle->data);
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/multitree.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/multitree.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/multitree.c	(revision 453)
@@ -0,0 +1,835 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "azure_c_shared_utility/gballoc.h"
+
+#include "multitree.h"
+#include <string.h>
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/const_defines.h"
+
+/*assume a name cannot be longer than 100 characters*/
+#define INNER_NODE_NAME_SIZE 128
+
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(MULTITREE_RESULT, MULTITREE_RESULT_VALUES);
+
+typedef struct MULTITREE_HANDLE_DATA_TAG
+{
+    char* name;
+    void* value;
+    MULTITREE_CLONE_FUNCTION cloneFunction;
+    MULTITREE_FREE_FUNCTION freeFunction;
+    size_t nChildren;
+    struct MULTITREE_HANDLE_DATA_TAG** children; /*an array of nChildren count of MULTITREE_HANDLE_DATA*   */
+}MULTITREE_HANDLE_DATA;
+
+
+MULTITREE_HANDLE MultiTree_Create(MULTITREE_CLONE_FUNCTION cloneFunction, MULTITREE_FREE_FUNCTION freeFunction)
+{
+    MULTITREE_HANDLE_DATA* result;
+
+    /* Codes_SRS_MULTITREE_99_052:[If any of the arguments passed to MultiTree_Create is NULL, the call shall return NULL.]*/
+    if ((cloneFunction == NULL) ||
+        (freeFunction == NULL))
+    {
+        LogError("CloneFunction or FreeFunction is Null.");
+        result = NULL;
+    }
+    else
+    {
+        /*Codes_SRS_MULTITREE_99_005:[ MultiTree_Create creates a new tree.]*/
+        /*Codes_SRS_MULTITREE_99_006:[MultiTree_Create returns a non - NULL pointer if the tree has been successfully created.]*/
+        /*Codes_SRS_MULTITREE_99_007:[MultiTree_Create returns NULL if the tree has not been successfully created.]*/
+        result = (MULTITREE_HANDLE_DATA*)calloc(1, sizeof(MULTITREE_HANDLE_DATA));
+        if (result != NULL)
+        {
+            result->name = NULL;
+            result->value = NULL;
+            result->cloneFunction = cloneFunction;
+            result->freeFunction = freeFunction;
+            result->nChildren = 0;
+            result->children = NULL;
+        }
+        else
+        {
+            LogError("MultiTree_Create failed because malloc failed");
+        }
+    }
+
+    return (MULTITREE_HANDLE)result;
+}
+
+
+/*return NULL if a child with the name "name" doesn't exists*/
+/*returns a pointer to the existing child (if any)*/
+static MULTITREE_HANDLE_DATA* getChildByName(MULTITREE_HANDLE_DATA* node, const char* name)
+{
+    MULTITREE_HANDLE_DATA* result = NULL;
+    size_t i;
+    for (i = 0; i < node->nChildren; i++)
+    {
+        if (strcmp(node->children[i]->name, name) == 0)
+        {
+            result = node->children[i];
+            break;
+        }
+    }
+    return result;
+}
+
+/*helper function to create a child immediately under this node*/
+/*return 0 if it created it, any other number is error*/
+
+typedef enum CREATELEAF_RESULT_TAG
+{
+    CREATELEAF_OK,
+    CREATELEAF_ALREADY_EXISTS,
+    CREATELEAF_EMPTY_NAME,
+    CREATELEAF_ERROR,
+    CREATELEAF_RESULT_COUNT // Used to track the number of elements in the enum
+                            // Do not remove, or add new enum values below this one
+}CREATELEAF_RESULT;
+
+static STATIC_VAR_UNUSED const char* CreateLeaf_ResultAsString[CREATELEAF_RESULT_COUNT] =
+{
+    MU_TOSTRING(CREATELEAF_OK),
+    MU_TOSTRING(CREATELEAF_ALREADY_EXISTS),
+    MU_TOSTRING(CREATELEAF_EMPTY_NAME),
+    MU_TOSTRING(CREATELEAF_ERROR)
+};
+
+/*name cannot be empty, value can be empty or NULL*/
+#ifdef __APPLE__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wconditional-uninitialized"
+#endif
+#ifdef _MSC_VER
+#pragma warning(disable: 4701) /* potentially uninitialized local variable 'result' used */ /* the scanner cannot track linked "newNode" and "result" therefore the warning*/
+#endif
+static CREATELEAF_RESULT createLeaf(MULTITREE_HANDLE_DATA* node, const char*name, const char*value, MULTITREE_HANDLE_DATA** childNode)
+{
+    CREATELEAF_RESULT result;
+    /*can only create it if it doesn't exist*/
+    if (strlen(name) == 0)
+    {
+        /*Codes_SRS_MULTITREE_99_024:[ if a child name is empty (such as in  "/child1//child12"), MULTITREE_EMPTY_CHILD_NAME shall be returned.]*/
+        result = CREATELEAF_EMPTY_NAME;
+        LogError("(result = %s)", CreateLeaf_ResultAsString[result]);
+    }
+    else if (getChildByName(node, name) != NULL)
+    {
+        result = CREATELEAF_ALREADY_EXISTS;
+        LogError("(result = %s)", CreateLeaf_ResultAsString[result]);
+    }
+    else
+    {
+        MULTITREE_HANDLE_DATA* newNode = (MULTITREE_HANDLE_DATA*)calloc(1, sizeof(MULTITREE_HANDLE_DATA));
+        if (newNode == NULL)
+        {
+            result = CREATELEAF_ERROR;
+            LogError("(result = %s)", CreateLeaf_ResultAsString[result]);
+        }
+        else
+        {
+            newNode->nChildren = 0;
+            newNode->children = NULL;
+            if (mallocAndStrcpy_s(&(newNode->name), name) != 0)
+            {
+                /*not nice*/
+                free(newNode);
+                newNode = NULL;
+                result = CREATELEAF_ERROR;
+                LogError("(result = %s)", CreateLeaf_ResultAsString[result]);
+            }
+            else
+            {
+                newNode->cloneFunction = node->cloneFunction;
+                newNode->freeFunction = node->freeFunction;
+
+                if (value == NULL)
+                {
+                    newNode->value = NULL;
+                }
+                else if (node->cloneFunction(&(newNode->value), value) != 0)
+                {
+                    free(newNode->name);
+                    newNode->name = NULL;
+                    free(newNode);
+                    newNode = NULL;
+                    result = CREATELEAF_ERROR;
+                    LogError("(result = %s)", CreateLeaf_ResultAsString[result]);
+                }
+                else
+                {
+                    /*all is fine until now*/
+                }
+            }
+
+
+            if (newNode!=NULL)
+            {
+                /*allocate space in the father node*/
+                MULTITREE_HANDLE_DATA** newChildren = (MULTITREE_HANDLE_DATA**)realloc(node->children, (node->nChildren + 1)*sizeof(MULTITREE_HANDLE_DATA*));
+                if (newChildren == NULL)
+                {
+                    /*no space for the new node*/
+                    newNode->value = NULL;
+                    free(newNode->name);
+                    newNode->name = NULL;
+                    free(newNode);
+                    newNode = NULL;
+                    result = CREATELEAF_ERROR;
+                    LogError("(result = %s)", CreateLeaf_ResultAsString[result]);
+                }
+                else
+                {
+                    node->children = newChildren;
+                    node->children[node->nChildren] = newNode;
+                    node->nChildren++;
+                    if (childNode != NULL)
+                    {
+                        *childNode = newNode;
+                    }
+                    result = CREATELEAF_OK;
+                }
+            }
+        }
+    }
+
+    return result;
+#ifdef _MSC_VER
+#pragma warning(default: 4701) /* potentially uninitialized local variable 'result' used */ /* the scanner cannot track linked "newNode" and "result" therefore the warning*/
+#endif
+#ifdef __APPLE__
+#pragma clang diagnostic pop
+#endif
+}
+
+MULTITREE_RESULT MultiTree_AddLeaf(MULTITREE_HANDLE treeHandle, const char* destinationPath, const void* value)
+{
+    /*codes_SRS_MULTITREE_99_018:[ If the treeHandle parameter is NULL, MULTITREE_INVALID_ARG shall be returned.]*/
+    MULTITREE_RESULT result;
+    if (treeHandle == NULL)
+    {
+        result = MULTITREE_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+    }
+    /*Codes_SRS_MULTITREE_99_019:[ If parameter destinationPath is NULL, MULTITREE_INVALID_ARG shall be returned.]*/
+    else if (destinationPath == NULL)
+    {
+        result = MULTITREE_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+    }
+    /*Codes_SRS_MULTITREE_99_020:[ If parameter value is NULL, MULTITREE_INVALID_ARG shall be returned.]*/
+    else if (value == NULL)
+    {
+        result = MULTITREE_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+    }
+    /*Codes_SRS_MULTITREE_99_050:[ If destinationPath a string with zero characters, MULTITREE_INVALID_ARG shall be returned.]*/
+    else if (strlen(destinationPath) == 0)
+    {
+        result = MULTITREE_EMPTY_CHILD_NAME;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+    }
+    else
+    {
+        /*break the path into components*/
+        /*find the first child name*/
+        MULTITREE_HANDLE_DATA * node = (MULTITREE_HANDLE_DATA *)treeHandle;
+        char * whereIsDelimiter;
+        /*if first character is / then skip it*/
+        /*Codes_SRS_MULTITREE_99_014:[DestinationPath is a string in the following format: /child1/child12 or child1/child12] */
+        if (destinationPath[0] == '/')
+        {
+            destinationPath++;
+        }
+        /*if there's just a string, it needs to be created here*/
+        whereIsDelimiter = (char*)strchr(destinationPath, '/');
+        if (whereIsDelimiter == NULL)
+        {
+            /*Codes_SRS_MULTITREE_99_017:[ Subsequent names designate hierarchical children in the tree. The last child designates the child that will receive the value.]*/
+            CREATELEAF_RESULT res = createLeaf(node, destinationPath, (const char*)value, NULL);
+            switch (res)
+            {
+                default:
+                {
+                    /*Codes_SRS_MULTITREE_99_025:[The function shall return MULTITREE_ERROR to indicate any other error not specified here.]*/
+                    result = MULTITREE_ERROR;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+                    break;
+                }
+                case CREATELEAF_ALREADY_EXISTS:
+                {
+                    /*Codes_SRS_MULTITREE_99_021:[ If the node already has a value assigned to it, MULTITREE_ALREADY_HAS_A_VALUE shall be returned and the existing value shall not be changed.]*/
+                    result = MULTITREE_ALREADY_HAS_A_VALUE;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+                    break;
+                }
+                case CREATELEAF_OK:
+                {
+                    /*Codes_SRS_MULTITREE_99_034:[ The function returns MULTITREE_OK when data has been stored in the tree.]*/
+                    result = MULTITREE_OK;
+                    break;
+                }
+                case CREATELEAF_EMPTY_NAME:
+                {
+                    /*Codes_SRS_MULTITREE_99_024:[ if a child name is empty (such as in  "/child1//child12"), MULTITREE_EMPTY_CHILD_NAME shall be returned.]*/
+                    result = MULTITREE_EMPTY_CHILD_NAME;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+                    break;
+                }
+            }
+        }
+        else
+        {
+            /*if there's more or 1 delimiter in the path... */
+            /*Codes_SRS_MULTITREE_99_017:[ Subsequent names designate hierarchical children in the tree. The last child designates the child that will receive the value.]*/
+            char firstInnerNodeName[INNER_NODE_NAME_SIZE];
+            if ((whereIsDelimiter - destinationPath) >= INNER_NODE_NAME_SIZE)
+            {
+                /*Codes_SRS_MULTITREE_99_025:[ The function shall return MULTITREE_ERROR to indicate any other error not specified here.]*/
+                result = MULTITREE_ERROR;
+                LogError("Destination path is too large %lu", (unsigned long)(whereIsDelimiter - destinationPath));
+            }
+            else if (memcpy(firstInnerNodeName, destinationPath, whereIsDelimiter - destinationPath) == NULL)
+            {
+                /*Codes_SRS_MULTITREE_99_025:[ The function shall return MULTITREE_ERROR to indicate any other error not specified here.]*/
+                result = MULTITREE_ERROR;
+                LogError("(result = MULTITREE_ERROR)");
+            }
+            else
+            {
+                firstInnerNodeName[whereIsDelimiter - destinationPath] = 0;
+                MULTITREE_HANDLE_DATA *child = getChildByName(node, firstInnerNodeName);
+                if (child == NULL)
+                {
+                    /*Codes_SRS_MULTITREE_99_022:[ If a child along the path does not exist, it shall be created.] */
+                    /*Codes_SRS_MULTITREE_99_023:[ The newly created children along the path shall have a NULL value by default.]*/
+                    CREATELEAF_RESULT res = createLeaf(node, firstInnerNodeName, NULL, NULL);
+                    switch (res)
+                    {
+                        default:
+                        {
+                            result = MULTITREE_ERROR;
+                            LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+                            break;
+                        }
+                        case(CREATELEAF_EMPTY_NAME):
+                        {
+                            /*Codes_SRS_MULTITREE_99_024:[ if a child name is empty (such as in  "/child1//child12"), MULTITREE_EMPTY_CHILD_NAME shall be returned.]*/
+                            result = MULTITREE_EMPTY_CHILD_NAME;
+                            LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+                            break;
+                        }
+                        case(CREATELEAF_OK):
+                        {
+                            MULTITREE_HANDLE_DATA *createdChild = getChildByName(node, firstInnerNodeName);
+                            result = MultiTree_AddLeaf(createdChild, whereIsDelimiter, value);
+                            break;
+                        }
+                    };
+                }
+                else
+                {
+                    result = MultiTree_AddLeaf(child, whereIsDelimiter, value);
+                }
+            }
+        }
+    }
+    return result;
+}
+
+/* Codes_SRS_MULTITREE_99_053:[ MultiTree_AddChild shall add a new node with the name childName to the multi tree node identified by treeHandle] */
+MULTITREE_RESULT MultiTree_AddChild(MULTITREE_HANDLE treeHandle, const char* childName, MULTITREE_HANDLE* childHandle)
+{
+    MULTITREE_RESULT result;
+    /* Codes_SRS_MULTITREE_99_055:[ If any argument is NULL, MultiTree_AddChild shall return MULTITREE_INVALID_ARG.] */
+    if ((treeHandle == NULL) ||
+        (childName == NULL) ||
+        (childHandle == NULL))
+    {
+        result = MULTITREE_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+    }
+    else
+    {
+        MULTITREE_HANDLE_DATA* childNode;
+
+        /* Codes_SRS_MULTITREE_99_060:[ The value associated with the new node shall be NULL.] */
+        CREATELEAF_RESULT res = createLeaf((MULTITREE_HANDLE_DATA*)treeHandle, childName, NULL, &childNode);
+        switch (res)
+        {
+            default:
+            {
+                result = MULTITREE_ERROR;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+                break;
+            }
+            case CREATELEAF_ALREADY_EXISTS:
+            {
+                /* Codes_SRS_MULTITREE_99_061:[ If a child node with the same name already exists, MultiTree_AddChild shall return MULTITREE_ALREADY_HAS_A_VALUE.] */
+                result = MULTITREE_ALREADY_HAS_A_VALUE;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+                break;
+            }
+            case CREATELEAF_OK:
+            {
+                /* Codes_SRS_MULTITREE_99_062:[ The new node handle shall be returned in the childHandle argument.] */
+                *childHandle = childNode;
+
+                /* Codes_SRS_MULTITREE_99_054:[ On success, MultiTree_AddChild shall return MULTITREE_OK.] */
+                result = MULTITREE_OK;
+                break;
+            }
+            case CREATELEAF_EMPTY_NAME:
+            {
+                /* Tests_SRS_MULTITREE_99_066:[ If the childName argument is an empty string, MultiTree_AddChild shall return MULTITREE_EMPTY_CHILD_NAME.] */
+                result = MULTITREE_EMPTY_CHILD_NAME;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+                break;
+            }
+        }
+    }
+
+    return result;
+}
+
+MULTITREE_RESULT MultiTree_GetChildCount(MULTITREE_HANDLE treeHandle, size_t* count)
+{
+    MULTITREE_RESULT result;
+    /*Codes_SRS_MULTITREE_99_027:[If treeHandle is NULL, the function returns MULTITREE_INVALID_ARG.]*/
+    if (treeHandle == NULL)
+    {
+        result = MULTITREE_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+    }
+    /*Codes_SRS_MULTITREE_99_028:[ If parameter count is NULL, the function returns MULTITREE_INVALID_ARG.]*/
+    else if (count == NULL)
+    {
+        result = MULTITREE_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+    }
+    else
+    {
+        /*Codes_SRS_MULTITREE_99_029:[ This function writes in *count the number of direct children for a tree node specified by the parameter treeHandle]*/
+        *count = ((MULTITREE_HANDLE_DATA*)treeHandle)->nChildren;
+        /*Codes_SRS_MULTITREE_99_035:[ The function shall return MULTITREE_OK when *count contains the number of children of the node pointed to be parameter treeHandle.]*/
+        result = MULTITREE_OK;
+    }
+    return result;
+}
+
+MULTITREE_RESULT MultiTree_GetChild(MULTITREE_HANDLE treeHandle, size_t index, MULTITREE_HANDLE *childHandle)
+{
+    MULTITREE_RESULT result;
+    /*Codes_SRS_MULTITREE_99_031:[ If parameter treeHandle is NULL, the function returns MULTITREE_INVALID_ARG.]*/
+    if (treeHandle == NULL)
+    {
+        result = MULTITREE_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+    }
+    /*Codes_SRS_MULTITREE_99_033:[ If parameter childHandle is NULL, the function shall return MULTITREE_INVALID_ARG.]*/
+    else if (childHandle == NULL)
+    {
+        result = MULTITREE_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+    }
+    else
+    {
+        MULTITREE_HANDLE_DATA * node = (MULTITREE_HANDLE_DATA *)treeHandle;
+        /*Codes_SRS_MULTITREE_99_032:[If parameter index is out of range, the function shall return MULTITREE_OUT_OF_RANGE_INDEX]*/
+        if (node->nChildren <= index)
+        {
+            result = MULTITREE_INVALID_ARG;
+            LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+        }
+        else
+        {
+            /*Codes_SRS_MULTITREE_99_030:[ This function writes in *childHandle parameter the "index"th child of the node pointed to by parameter treeHandle]*/
+            /*Codes_SRS_MULTITREE_99_035:[ The function returns MULTITREE_OK when *childHandle contains a handle to the "index"th child of the tree designated by parameter treeHandle.]*/
+            *childHandle = node->children[index];
+            result = MULTITREE_OK;
+        }
+    }
+    return result;
+}
+
+MULTITREE_RESULT MultiTree_GetName(MULTITREE_HANDLE treeHandle, STRING_HANDLE destination)
+{
+    MULTITREE_RESULT result;
+    /*Codes_SRS_MULTITREE_99_037:[ If treeHandle is NULL, the function shall return MULTITREE_INVALID_ARG.]*/
+    if (treeHandle == NULL)
+    {
+        result = MULTITREE_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+    }
+    /*Codes_SRS_MULTITREE_99_038:[If destination is NULL, the function shall return MULTITREE_INVALID_ARG.]*/
+    else if (destination == NULL)
+    {
+        result = MULTITREE_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+    }
+    else
+    {
+        MULTITREE_HANDLE_DATA *node = (MULTITREE_HANDLE_DATA*)treeHandle;
+        /*Codes_SRS_MULTITREE_99_051:[ The function returns MULTITREE_EMPTY_CHILD_NAME when used with the root of the tree.]*/
+        if (node->name == NULL)
+        {
+            result = MULTITREE_EMPTY_CHILD_NAME;
+            LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+        }
+        /*Codes_SRS_MULTITREE_99_036:[ This function fills the buffer pointed to by parameter destination with the name of the root node of the tree designated by parameter treeHandle.]*/
+        else if (STRING_concat(destination, node->name)!=0)
+        {
+            /*Codes_SRS_MULTITREE_99_040:[ The function returns MULTITREE_ERROR to indicate any other error.]*/
+            result = MULTITREE_ERROR;
+            LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+        }
+        else
+        {
+            /*Codes_SRS_MULTITREE_99_039:[ The function returns MULTITREE_OK when destination contains the name of the root node of the tree designated by treeHandle parameter.]*/
+            result = MULTITREE_OK;
+        }
+    }
+
+    return result;
+}
+
+/* Codes_SRS_MULTITREE_99_063:[ MultiTree_GetChildByName shall retrieve the handle of the child node childName from the treeNode node.] */
+MULTITREE_RESULT MultiTree_GetChildByName(MULTITREE_HANDLE treeHandle, const char* childName, MULTITREE_HANDLE *childHandle)
+{
+    MULTITREE_RESULT result;
+
+    /* Codes_SRS_MULTITREE_99_065:[ If any argument is NULL, MultiTree_GetChildByName shall return MULTITREE_INVALID_ARG.] */
+    if ((treeHandle == NULL) ||
+        (childHandle == NULL) ||
+        (childName == NULL))
+    {
+        result = MULTITREE_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+    }
+    else
+    {
+        MULTITREE_HANDLE_DATA * node = (MULTITREE_HANDLE_DATA *)treeHandle;
+        size_t i;
+
+        for (i = 0; i < node->nChildren; i++)
+        {
+            if (strcmp(node->children[i]->name, childName) == 0)
+            {
+                break;
+            }
+        }
+
+        if (i == node->nChildren)
+        {
+            /* Codes_SRS_MULTITREE_99_068:[ If the specified child is not found, MultiTree_GetChildByName shall return MULTITREE_CHILD_NOT_FOUND.] */
+            result = MULTITREE_CHILD_NOT_FOUND;
+            LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+        }
+        else
+        {
+            /* Codes_SRS_MULTITREE_99_067:[ The child node handle shall be returned in the childHandle argument.] */
+            *childHandle = node->children[i];
+
+            /* Codes_SRS_MULTITREE_99_064:[ On success, MultiTree_GetChildByName shall return MULTITREE_OK.] */
+            result = MULTITREE_OK;
+        }
+    }
+    return result;
+}
+
+MULTITREE_RESULT MultiTree_GetValue(MULTITREE_HANDLE treeHandle, const void** destination)
+{
+    MULTITREE_RESULT result;
+    /*Codes_SRS_MULTITREE_99_042:[If treeHandle is NULL, the function shall return MULTITREE_INVALID_ARG.]*/
+    if (treeHandle == NULL)
+    {
+        result = MULTITREE_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+    }
+    /*Codes_SRS_MULTITREE_99_043:[ If destination is NULL, the function shall return MULTITREE_INVALID_ARG.]*/
+    else if (destination == NULL)
+    {
+        result = MULTITREE_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+    }
+    else
+    {
+        MULTITREE_HANDLE_DATA * node = (MULTITREE_HANDLE_DATA*)treeHandle;
+        /*Codes_SRS_MULTITREE_99_044:[ If there is no value in the node then MULTITREE_EMPTY_VALUE shall be returned.]*/
+        if (node->value == NULL)
+        {
+            result = MULTITREE_EMPTY_VALUE;
+            LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+        }
+        else
+        {
+            /*Codes_SRS_MULTITREE_99_041:[This function updates the *destination parameter to the internally stored value.]*/
+            *destination = node->value;
+            result = MULTITREE_OK;
+        }
+    }
+    return result;
+}
+
+MULTITREE_RESULT MultiTree_SetValue(MULTITREE_HANDLE treeHandle, void* value)
+{
+    MULTITREE_RESULT result;
+
+    /* Codes_SRS_MULTITREE_99_074:[ If any argument is NULL, MultiTree_SetValue shall return MULTITREE_INVALID_ARG.] */
+    if ((treeHandle == NULL) ||
+        (value == NULL))
+    {
+        result = MULTITREE_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+    }
+    else
+    {
+        MULTITREE_HANDLE_DATA * node = (MULTITREE_HANDLE_DATA*)treeHandle;
+        if (node->value != NULL)
+        {
+            /* Codes_SRS_MULTITREE_99_076:[ If the node already has a value then MultiTree_SetValue shall return MULTITREE_ALREADY_HAS_A_VALUE.] */
+            result = MULTITREE_ALREADY_HAS_A_VALUE;
+            LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+        }
+        else
+        {
+            /* Codes_SRS_MULTITREE_99_072:[ MultiTree_SetValue shall set the value of the node indicated by the treeHandle argument to the value of the argument value.] */
+            if (node->cloneFunction(&node->value, value) != 0)
+            {
+                /* Codes_SRS_MULTITREE_99_075:[ MultiTree_SetValue shall return MULTITREE_ERROR to indicate any other error.] */
+                result = MULTITREE_ERROR;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+            }
+            else
+            {
+                /* Codes_SRS_MULTITREE_99_073:[ On success, MultiTree_SetValue shall return MULTITREE_OK.] */
+                result = MULTITREE_OK;
+            }
+        }
+    }
+    return result;
+}
+
+void MultiTree_Destroy(MULTITREE_HANDLE treeHandle)
+{
+    if (treeHandle != NULL)
+    {
+        MULTITREE_HANDLE_DATA* node = (MULTITREE_HANDLE_DATA*)treeHandle;
+        size_t i;
+        for (i = 0; i < node->nChildren;i++)
+        {
+            /*Codes_SRS_MULTITREE_99_047:[ This function frees any system resource used by the tree designated by parameter treeHandle]*/
+            MultiTree_Destroy(node->children[i]);
+        }
+        /*Codes_SRS_MULTITREE_99_047:[ This function frees any system resource used by the tree designated by parameter treeHandle]*/
+        if (node->children != NULL)
+        {
+            free(node->children);
+            node->children = NULL;
+        }
+
+        /*Codes_SRS_MULTITREE_99_047:[ This function frees any system resource used by the tree designated by parameter treeHandle]*/
+        if (node->name != NULL)
+        {
+            free(node->name);
+            node->name = NULL;
+        }
+
+        /*Codes_SRS_MULTITREE_99_047:[ This function frees any system resource used by the tree designated by parameter treeHandle]*/
+        if (node->value != NULL)
+        {
+            node->freeFunction(node->value);
+            node->value = NULL;
+        }
+
+        /*Codes_SRS_MULTITREE_99_047:[ This function frees any system resource used by the tree designated by parameter treeHandle]*/
+        free(node);
+    }
+}
+
+MULTITREE_RESULT MultiTree_GetLeafValue(MULTITREE_HANDLE treeHandle, const char* leafPath, const void** destination)
+{
+    MULTITREE_RESULT result;
+
+    /* Codes_SRS_MULTITREE_99_055:[ If any argument is NULL, MultiTree_GetLeafValue shall return MULTITREE_INVALID_ARG.] */
+    if ((treeHandle == NULL) ||
+        (leafPath == NULL) ||
+        (destination == NULL))
+    {
+        result = MULTITREE_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+    }
+    /* Codes_SRS_MULTITREE_99_058:[ The last child designates the child that will receive the value. If a child name is empty (such as in  "/child1//child12"), MULTITREE_EMPTY_CHILD_NAME shall be returned.] */
+    else if (strlen(leafPath) == 0)
+    {
+        result = MULTITREE_EMPTY_CHILD_NAME;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+    }
+    else
+    {
+        /*break the path into components*/
+        /*find the first child name*/
+        MULTITREE_HANDLE_DATA* node = (MULTITREE_HANDLE_DATA *)treeHandle;
+        const char* pos = leafPath;
+        const char * whereIsDelimiter;
+
+        /*if first character is / then skip it*/
+        if (*pos == '/')
+        {
+            pos++;
+        }
+
+        if (*pos == '\0')
+        {
+            /* Codes_SRS_MULTITREE_99_069:[ If a child name is empty (such as in  "/child1//child12"), MULTITREE_EMPTY_CHILD_NAME shall be returned.] */
+            result = MULTITREE_EMPTY_CHILD_NAME;
+            LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+        }
+        else
+        {
+            result = MULTITREE_OK;
+
+            /* Codes_SRS_MULTITREE_99_056:[ The leafPath argument is a string in the following format: /child1/child12 or child1/child12.] */
+            /* Codes_SRS_MULTITREE_99_058:[ The last child designates the child that will receive the value.] */
+            while (*pos != '\0')
+            {
+                size_t i;
+                size_t childCount = node->nChildren;
+
+                whereIsDelimiter = pos;
+
+                while ((*whereIsDelimiter != '/') && (*whereIsDelimiter != '\0'))
+                {
+                    whereIsDelimiter++;
+                }
+
+                if (whereIsDelimiter == pos)
+                {
+                    /* Codes_SRS_MULTITREE_99_069:[ If a child name is empty (such as in  "/child1//child12"), MULTITREE_EMPTY_CHILD_NAME shall be returned.] */
+                    result = MULTITREE_EMPTY_CHILD_NAME;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+                    break;
+                }
+                else if (childCount == 0)
+                {
+                    /* Codes_SRS_MULTITREE_99_071:[ When the child node is not found, MultiTree_GetLeafValue shall return MULTITREE_CHILD_NOT_FOUND.] */
+                    result = MULTITREE_CHILD_NOT_FOUND;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+                    break;
+                }
+                else
+                {
+                    for (i = 0; i < childCount; i++)
+                    {
+                        if (strncmp(node->children[i]->name, pos, whereIsDelimiter - pos) == 0)
+                        {
+                            /* Codes_SRS_MULTITREE_99_057:[ Subsequent names designate hierarchical children in the tree.] */
+                            node = node->children[i];
+                            break;
+                        }
+                    }
+
+                    if (i == childCount)
+                    {
+                        /* Codes_SRS_MULTITREE_99_071:[ When the child node is not found, MultiTree_GetLeafValue shall return MULTITREE_CHILD_NOT_FOUND.] */
+                        result = MULTITREE_CHILD_NOT_FOUND;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+                        break;
+                    }
+                    else
+                    {
+                        if (*whereIsDelimiter == '/')
+                        {
+                            pos = whereIsDelimiter + 1;
+                        }
+                        else
+                        {
+                            /* end of path */
+                            pos = whereIsDelimiter;
+                            break;
+                        }
+                    }
+                }
+            }
+
+            if (*pos == 0)
+            {
+                if (node->value == NULL)
+                {
+                    /* Codes_SRS_MULTITREE_99_070:[ If an attempt is made to get the value for a node that does not have a value set, then MultiTree_GetLeafValue shall return MULTITREE_EMPTY_VALUE.] */
+                    result = MULTITREE_EMPTY_VALUE;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+                }
+                /*Codes_SRS_MULTITREE_99_053:[ MultiTree_GetLeafValue shall copy into the *destination argument the value of the node identified by the leafPath argument.]*/
+                else
+                {
+                    *destination = node->value;
+                    /* Codes_SRS_MULTITREE_99_054:[ On success, MultiTree_GetLeafValue shall return MULTITREE_OK.] */
+                    result = MULTITREE_OK;
+                }
+            }
+        }
+    }
+    return result;
+}
+
+/* Codes_SRS_MULTITREE_99_077:[ MultiTree_DeleteChild shall remove the direct children node (no recursive search) set by childName.] */
+MULTITREE_RESULT MultiTree_DeleteChild(MULTITREE_HANDLE treeHandle, const char* childName)
+{
+    MULTITREE_RESULT result;
+    /* Codes_SRS_MULTITREE_99_077:[ If any argument is NULL, MultiTree_DeleteChild shall return MULTITREE_INVALID_ARG.] */
+    if ((treeHandle == NULL) ||
+        (childName == NULL))
+    {
+        result = MULTITREE_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(MULTITREE_RESULT, result));
+    }
+    else
+    {
+        size_t i;
+        size_t childToRemove = treeHandle->nChildren;
+        MULTITREE_HANDLE treeToRemove = NULL;
+
+        for (i = 0; i < treeHandle->nChildren; i++)
+        {
+            if (0 == strcmp(treeHandle->children[i]->name, childName))
+            {
+                childToRemove = i;
+                treeToRemove = treeHandle->children[childToRemove];
+                break;
+            }
+        }
+
+        if (i == treeHandle->nChildren)
+        {
+            /* Codes_SRS_MULTITREE_99_079:[If childName is not found, MultiTree_DeleteChild shall return MULTITREE_CHILD_NOT_FOUND.] */
+            result = MULTITREE_CHILD_NOT_FOUND;
+            // Don't log error; this function is best effort only.  Caller will determine actual error state.
+        }
+        else
+        {
+            for (i = childToRemove; i < treeHandle->nChildren - 1; i++)
+            {
+                treeHandle->children[i] = treeHandle->children[i+1];
+            }
+
+            /* Codes_SRS_MULTITREE_99_077:[ MultiTree_DeleteChild shall remove the direct children node (no recursive search) set by childName  */
+            MultiTree_Destroy(treeToRemove);
+
+            // Even though this isn't reachable anymore after decrementing count, NULL out for cleanliness
+            treeHandle->children[treeHandle->nChildren - 1] = NULL;
+            treeHandle->nChildren = treeHandle->nChildren - 1;
+
+            result = MULTITREE_OK;
+        }
+    }
+
+    return result;
+}
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/schema.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/schema.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/schema.c	(revision 453)
@@ -0,0 +1,3258 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "azure_c_shared_utility/gballoc.h"
+
+#include "schema.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/vector.h"
+
+
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(SCHEMA_RESULT, SCHEMA_RESULT_VALUES);
+
+typedef struct SCHEMA_PROPERTY_HANDLE_DATA_TAG
+{
+    const char* PropertyName;
+    const char* PropertyType;
+} SCHEMA_PROPERTY_HANDLE_DATA;
+
+typedef struct SCHEMA_REPORTED_PROPERTY_HANDLE_DATA_TAG
+{
+    const char* reportedPropertyName;
+    const char* reportedPropertyType;
+} SCHEMA_REPORTED_PROPERTY_HANDLE_DATA;
+
+typedef struct SCHEMA_DESIRED_PROPERTY_HANDLE_DATA_TAG
+{
+    pfOnDesiredProperty onDesiredProperty;
+    pfDesiredPropertyInitialize desiredPropertInitialize;
+    pfDesiredPropertyDeinitialize desiredPropertDeinitialize;
+    const char* desiredPropertyName;
+    const char* desiredPropertyType;
+    pfDesiredPropertyFromAGENT_DATA_TYPE desiredPropertyFromAGENT_DATA_TYPE;
+    size_t offset;
+} SCHEMA_DESIRED_PROPERTY_HANDLE_DATA;
+
+typedef struct SCHEMA_ACTION_ARGUMENT_HANDLE_DATA_TAG
+{
+    const char* Name;
+    const char* Type;
+} SCHEMA_ACTION_ARGUMENT_HANDLE_DATA;
+
+typedef struct SCHEMA_METHOD_ARGUMENT_HANDLE_DATA_TAG
+{
+    char* Name;
+    char* Type;
+} SCHEMA_METHOD_ARGUMENT_HANDLE_DATA;
+
+typedef struct SCHEMA_ACTION_HANDLE_DATA_TAG
+{
+    const char* ActionName;
+    size_t ArgumentCount;
+    SCHEMA_ACTION_ARGUMENT_HANDLE* ArgumentHandles;
+} SCHEMA_ACTION_HANDLE_DATA;
+
+typedef struct SCHEMA_METHOD_HANDLE_DATA_TAG
+{
+    char* methodName;
+    VECTOR_HANDLE methodArguments; /*holds SCHEMA_METHOD_ARGUMENT_HANDLE*/
+} SCHEMA_METHOD_HANDLE_DATA;
+
+typedef struct MODEL_IN_MODEL_TAG
+{
+    pfOnDesiredProperty onDesiredProperty; /*is NULL if not specified or if the model in model is not WITH_DESIRED_PROPERTY*/
+    size_t offset; /*offset of the model in model (offsetof)*/
+    const char* propertyName;
+    SCHEMA_MODEL_TYPE_HANDLE modelHandle;
+} MODEL_IN_MODEL;
+
+typedef struct SCHEMA_MODEL_TYPE_HANDLE_DATA_TAG
+{
+    VECTOR_HANDLE methods; /*holds SCHEMA_METHOD_HANDLE*/
+    VECTOR_HANDLE desiredProperties; /*holds SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*/
+    const char* Name;
+    SCHEMA_HANDLE SchemaHandle;
+    SCHEMA_PROPERTY_HANDLE* Properties;
+    size_t PropertyCount;
+    VECTOR_HANDLE reportedProperties; /*holds SCHEMA_REPORTED_PROPERTY_HANDLE*/
+    SCHEMA_ACTION_HANDLE* Actions;
+    size_t ActionCount;
+    VECTOR_HANDLE models;
+    size_t DeviceCount;
+} SCHEMA_MODEL_TYPE_HANDLE_DATA;
+
+typedef struct SCHEMA_STRUCT_TYPE_HANDLE_DATA_TAG
+{
+    const char* Name;
+    SCHEMA_PROPERTY_HANDLE* Properties;
+    size_t PropertyCount;
+} SCHEMA_STRUCT_TYPE_HANDLE_DATA;
+
+typedef struct SCHEMA_HANDLE_DATA_TAG
+{
+    void* metadata;
+    const char* Namespace;
+    SCHEMA_MODEL_TYPE_HANDLE* ModelTypes;
+    size_t ModelTypeCount;
+    SCHEMA_STRUCT_TYPE_HANDLE* StructTypes;
+    size_t StructTypeCount;
+} SCHEMA_HANDLE_DATA;
+
+static VECTOR_HANDLE g_schemas = NULL;
+
+static void DestroyProperty(SCHEMA_PROPERTY_HANDLE propertyHandle)
+{
+    SCHEMA_PROPERTY_HANDLE_DATA* propertyType = (SCHEMA_PROPERTY_HANDLE_DATA*)propertyHandle;
+    free((void*)propertyType->PropertyName);
+    free((void*)propertyType->PropertyType);
+    free(propertyType);
+}
+
+static void DestroyActionArgument(SCHEMA_ACTION_ARGUMENT_HANDLE actionArgumentHandle)
+{
+    SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* actionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)actionArgumentHandle;
+    if (actionArgument != NULL)
+    {
+        free((void*)actionArgument->Name);
+        free((void*)actionArgument->Type);
+        free(actionArgument);
+    }
+}
+
+static void DestroyMethodArgument(SCHEMA_METHOD_ARGUMENT_HANDLE methodArgumentHandle)
+{
+    free(methodArgumentHandle->Name);
+    free(methodArgumentHandle->Type);
+    free(methodArgumentHandle);
+}
+
+static void DestroyAction(SCHEMA_ACTION_HANDLE actionHandle)
+{
+    SCHEMA_ACTION_HANDLE_DATA* action = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle;
+    if (action != NULL)
+    {
+        size_t j;
+
+        for (j = 0; j < action->ArgumentCount; j++)
+        {
+            DestroyActionArgument(action->ArgumentHandles[j]);
+        }
+        free(action->ArgumentHandles);
+
+        free((void*)action->ActionName);
+        free(action);
+    }
+}
+
+static void DestroyMethod(SCHEMA_METHOD_HANDLE methodHandle)
+{
+    size_t nArguments = VECTOR_size(methodHandle->methodArguments);
+
+    for (size_t j = 0; j < nArguments; j++)
+    {
+        SCHEMA_METHOD_ARGUMENT_HANDLE* methodArgumentHandle = VECTOR_element(methodHandle->methodArguments, j);
+        DestroyMethodArgument(*methodArgumentHandle);
+    }
+    free(methodHandle->methodName);
+    VECTOR_destroy(methodHandle->methodArguments);
+    free(methodHandle);
+}
+
+static void DestroyMethods(SCHEMA_MODEL_TYPE_HANDLE modelHandle)
+{
+    size_t nMethods = VECTOR_size(modelHandle->methods);
+
+    for (size_t j = 0; j < nMethods; j++)
+    {
+        SCHEMA_METHOD_HANDLE* methodHandle = VECTOR_element(modelHandle->methods, j);
+        DestroyMethod(*methodHandle);
+    }
+    VECTOR_destroy(modelHandle->methods);
+}
+
+
+static void DestroyStruct(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle)
+{
+    size_t i;
+    SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle;
+    if (structType != NULL)
+    {
+        for (i = 0; i < structType->PropertyCount; i++)
+        {
+            DestroyProperty(structType->Properties[i]);
+        }
+        free(structType->Properties);
+
+        free((void*)structType->Name);
+
+        free(structType);
+    }
+}
+
+static void DestroyModel(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle)
+{
+    SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+    size_t i, nReportedProperties;
+
+    free((void*)modelType->Name);
+    modelType->Name = NULL;
+
+    for (i = 0; i < modelType->PropertyCount; i++)
+    {
+        DestroyProperty(modelType->Properties[i]);
+    }
+
+    free(modelType->Properties);
+
+    for (i = 0; i < modelType->ActionCount; i++)
+    {
+        DestroyAction(modelType->Actions[i]);
+    }
+
+    DestroyMethods(modelType);
+
+    /*destroy the vector holding the added models. This does not destroy the said models, however, their names shall be*/
+    for (i = 0; i < VECTOR_size(modelType->models); i++)
+    {
+        MODEL_IN_MODEL* temp = (MODEL_IN_MODEL*)VECTOR_element(modelType->models, i);
+        free((void*)temp->propertyName);
+    }
+
+    nReportedProperties = VECTOR_size(modelType->reportedProperties);
+    for (i = 0;i < nReportedProperties;i++)
+    {
+        SCHEMA_REPORTED_PROPERTY_HANDLE_DATA* reportedProperty = *(SCHEMA_REPORTED_PROPERTY_HANDLE_DATA **)VECTOR_element(modelType->reportedProperties, i);
+        free((void*)reportedProperty->reportedPropertyName);
+        free((void*)reportedProperty->reportedPropertyType);
+        free(reportedProperty);
+    }
+    VECTOR_destroy(modelType->reportedProperties);
+
+    size_t nDesiredProperties = VECTOR_size(modelType->desiredProperties);
+    for (i = 0;i < nDesiredProperties;i++)
+    {
+        SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desiredProperty = *(SCHEMA_DESIRED_PROPERTY_HANDLE_DATA **)VECTOR_element(modelType->desiredProperties, i);
+        free((void*)desiredProperty->desiredPropertyName);
+        free((void*)desiredProperty->desiredPropertyType);
+        free(desiredProperty);
+    }
+    VECTOR_destroy(modelType->desiredProperties);
+
+    VECTOR_clear(modelType->models);
+    VECTOR_destroy(modelType->models);
+
+    free(modelType->Actions);
+    free(modelType);
+}
+
+static SCHEMA_RESULT AddModelProperty(SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType, const char* name, const char* type)
+{
+    SCHEMA_RESULT result;
+
+    /* Codes_SRS_SCHEMA_99_013:[If any of the arguments is NULL, Schema_AddModelProperty shall return SCHEMA_INVALID_ARG.] */
+    if ((modelType == NULL) ||
+        (name == NULL) ||
+        (type == NULL))
+    {
+        result = SCHEMA_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+    }
+    else
+    {
+        size_t i;
+
+        /* Codes_SRS_SCHEMA_99_015:[The property name shall be unique per model, if the same property name is added twice to a model, SCHEMA_DUPLICATE_ELEMENT shall be returned.] */
+        for (i = 0; i < modelType->PropertyCount; i++)
+        {
+            SCHEMA_PROPERTY_HANDLE_DATA* property = (SCHEMA_PROPERTY_HANDLE_DATA*)modelType->Properties[i];
+            if (strcmp(property->PropertyName, name) == 0)
+            {
+                break;
+            }
+        }
+
+        if (i < modelType->PropertyCount)
+        {
+            result = SCHEMA_DUPLICATE_ELEMENT;
+            LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+        }
+        else
+        {
+            SCHEMA_PROPERTY_HANDLE* newProperties = (SCHEMA_PROPERTY_HANDLE*)realloc(modelType->Properties, sizeof(SCHEMA_PROPERTY_HANDLE) * (modelType->PropertyCount + 1));
+            if (newProperties == NULL)
+            {
+                /* Codes_SRS_SCHEMA_99_014:[On any other error, Schema_AddModelProperty shall return SCHEMA_ERROR.] */
+                result = SCHEMA_ERROR;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+            }
+            else
+            {
+                SCHEMA_PROPERTY_HANDLE_DATA* newProperty;
+
+                modelType->Properties = newProperties;
+                if ((newProperty = (SCHEMA_PROPERTY_HANDLE_DATA*)malloc(sizeof(SCHEMA_PROPERTY_HANDLE_DATA))) == NULL)
+                {
+                    /* Codes_SRS_SCHEMA_99_014:[On any other error, Schema_AddModelProperty shall return SCHEMA_ERROR.] */
+                    result = SCHEMA_ERROR;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+                }
+                else
+                {
+                    if (mallocAndStrcpy_s((char**)&newProperty->PropertyName, name) != 0)
+                    {
+                        /* Codes_SRS_SCHEMA_99_014:[On any other error, Schema_AddModelProperty shall return SCHEMA_ERROR.] */
+                        free(newProperty);
+                        result = SCHEMA_ERROR;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+                    }
+                    else if (mallocAndStrcpy_s((char**)&newProperty->PropertyType, type) != 0)
+                    {
+                        /* Codes_SRS_SCHEMA_99_014:[On any other error, Schema_AddModelProperty shall return SCHEMA_ERROR.] */
+                        free((void*)newProperty->PropertyName);
+                        free(newProperty);
+                        result = SCHEMA_ERROR;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+                    }
+                    else
+                    {
+                        modelType->Properties[modelType->PropertyCount] = (SCHEMA_PROPERTY_HANDLE)newProperty;
+                        modelType->PropertyCount++;
+
+                        /* Codes_SRS_SCHEMA_99_012:[On success, Schema_AddModelProperty shall return SCHEMA_OK.] */
+                        result = SCHEMA_OK;
+                    }
+                }
+
+                /* If possible, reduce the memory of over allocation */
+                if (result != SCHEMA_OK)
+                {
+                    if (modelType->PropertyCount > 0)
+                    {
+                        SCHEMA_PROPERTY_HANDLE *oldProperties = (SCHEMA_PROPERTY_HANDLE *)realloc(modelType->Properties, sizeof(SCHEMA_PROPERTY_HANDLE) * modelType->PropertyCount);
+                        if (oldProperties == NULL)
+                        {
+                            result = SCHEMA_ERROR;
+                            LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+                        }
+                        else
+                        {
+                            modelType->Properties = oldProperties;
+                        }
+                    }
+                    else
+                    {
+                        modelType->Properties = NULL;
+                    }
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+static bool SchemaHandlesMatch(const SCHEMA_HANDLE* handle, const SCHEMA_HANDLE* otherHandle)
+{
+    return (*handle == *otherHandle);
+}
+
+static bool SchemaNamespacesMatch(const SCHEMA_HANDLE* handle, const char* schemaNamespace)
+{
+    const SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)*handle;
+    return (strcmp(schema->Namespace, schemaNamespace) == 0);
+}
+
+/* Codes_SRS_SCHEMA_99_001:[Schema_Create shall initialize a schema with a given namespace.] */
+SCHEMA_HANDLE Schema_Create(const char* schemaNamespace, void* metadata)
+{
+    SCHEMA_HANDLE_DATA* result;
+    /*Codes_SRS_SCHEMA_02_090: [ If metadata is NULL then Schema_Create shall fail and return NULL. ]*/
+    /* Codes_SRS_SCHEMA_99_004:[If schemaNamespace is NULL, Schema_Create shall fail.] */
+    if (
+        (schemaNamespace == NULL)||
+        (metadata == NULL)
+        )
+    {
+        /* Codes_SRS_SCHEMA_99_003:[On failure, NULL shall be returned.] */
+        LogError("invalid arg const char* schemaNamespace=%p, void* metadata=%p",schemaNamespace, metadata);
+        result = NULL;
+    }
+    else
+    {
+        if (g_schemas == NULL && (g_schemas = VECTOR_create(sizeof(SCHEMA_HANDLE_DATA*) ) ) == NULL)
+        {
+            /* Codes_SRS_SCHEMA_99_003:[On failure, NULL shall be returned.] */
+            result = NULL;
+            LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
+        }
+        else if ((result = (SCHEMA_HANDLE_DATA*)calloc(1, sizeof(SCHEMA_HANDLE_DATA))) == NULL)
+        {
+            /* Codes_SRS_SCHEMA_99_003:[On failure, NULL shall be returned.] */
+            LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
+        }
+        else if (mallocAndStrcpy_s((char**)&result->Namespace, schemaNamespace) != 0)
+        {
+            /* Codes_SRS_SCHEMA_99_003:[On failure, NULL shall be returned.] */
+            free(result);
+            result = NULL;
+            LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
+        }
+        else if (VECTOR_push_back(g_schemas, &result, 1) != 0)
+        {
+            free((void*)result->Namespace);
+            free(result);
+            result = NULL;
+            LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
+        }
+        else
+        {
+            /* Codes_SRS_SCHEMA_99_002:[On success a non-NULL handle to the newly created schema shall be returned.] */
+            result->ModelTypes = NULL;
+            result->ModelTypeCount = 0;
+            result->StructTypes = NULL;
+            result->StructTypeCount = 0;
+            result->metadata = metadata;
+        }
+    }
+
+    return (SCHEMA_HANDLE)result;
+}
+
+size_t Schema_GetSchemaCount(void)
+{
+    /* Codes_SRS_SCHEMA_99_153: [Schema_GetSchemaCount shall return the number of "active" schemas (all schemas created with Schema_Create
+    in the current process, for which Schema_Destroy has not been called).] */
+    return VECTOR_size(g_schemas);
+}
+
+SCHEMA_HANDLE Schema_GetSchemaByNamespace(const char* schemaNamespace)
+{
+    /* Codes_SRS_SCHEMA_99_151: [If no active schema matches the schemaNamespace argument, Schema_GetSchemaByNamespace shall return NULL.] */
+    SCHEMA_HANDLE result = NULL;
+
+    /* Codes_SRS_SCHEMA_99_150: [If the schemaNamespace argument is NULL, Schema_GetSchemaByNamespace shall return NULL.] */
+    if (schemaNamespace != NULL)
+    {
+        SCHEMA_HANDLE* handle = (g_schemas==NULL)?NULL:(SCHEMA_HANDLE*)VECTOR_find_if(g_schemas, (PREDICATE_FUNCTION)SchemaNamespacesMatch, schemaNamespace);
+        if (handle != NULL)
+        {
+            /* Codes_SRS_SCHEMA_99_148: [Schema_GetSchemaByNamespace shall search all active schemas and return the schema with the
+               namespace given by the schemaNamespace argument.] */
+            result = *handle;
+        }
+    }
+
+    return result;
+}
+
+const char* Schema_GetSchemaNamespace(SCHEMA_HANDLE schemaHandle)
+{
+    const char* result;
+
+    /* Codes_SRS_SCHEMA_99_130: [If the schemaHandle argument is NULL, Schema_GetSchemaNamespace shall return NULL.] */
+    if (schemaHandle == NULL)
+    {
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_SCHEMA_99_129: [Schema_GetSchemaNamespace shall return the namespace for the schema identified by schemaHandle.] */
+        result = ((SCHEMA_HANDLE_DATA*)schemaHandle)->Namespace;
+    }
+
+    return result;
+}
+
+void Schema_Destroy(SCHEMA_HANDLE schemaHandle)
+{
+    /* Codes_SRS_SCHEMA_99_006:[If the schemaHandle is NULL, Schema_Destroy shall do nothing.] */
+    if (schemaHandle != NULL)
+    {
+        SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
+        size_t i;
+
+        /* Codes_SRS_SCHEMA_99_005:[Schema_Destroy shall free all resources associated with a schema.] */
+        for (i = 0; i < schema->ModelTypeCount; i++)
+        {
+            DestroyModel(schema->ModelTypes[i]);
+        }
+
+        free(schema->ModelTypes);
+
+        /* Codes_SRS_SCHEMA_99_005:[Schema_Destroy shall free all resources associated with a schema.] */
+        for (i = 0; i < schema->StructTypeCount; i++)
+        {
+            DestroyStruct(schema->StructTypes[i]);
+        }
+
+        free(schema->StructTypes);
+        free((void*)schema->Namespace);
+        free(schema);
+
+        schema = (SCHEMA_HANDLE_DATA*)VECTOR_find_if(g_schemas, (PREDICATE_FUNCTION)SchemaHandlesMatch, &schemaHandle);
+        if (schema != NULL)
+        {
+            VECTOR_erase(g_schemas, schema, 1);
+        }
+        // If the g_schema is empty then destroy it
+        if (VECTOR_size(g_schemas) == 0)
+        {
+            VECTOR_destroy(g_schemas);
+            g_schemas = NULL;
+        }
+    }
+}
+
+SCHEMA_RESULT Schema_DestroyIfUnused(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle)
+{
+    SCHEMA_RESULT result;
+
+    /* Codes_SRS_SCHEMA_07_189: [If modelHandle variable is NULL Schema_DestroyIfUnused shall do nothing.] */
+    if (modelTypeHandle != NULL)
+    {
+        SCHEMA_HANDLE schemaHandle = Schema_GetSchemaForModelType(modelTypeHandle);
+        if (schemaHandle == NULL)
+        {
+            result = SCHEMA_ERROR;
+        }
+        else
+        {
+            SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
+            size_t nIndex;
+
+            /* Codes_SRS_SCHEMA_07_190: [Schema_DestroyIfUnused shall iterate through the ModuleTypes objects and if all the DeviceCount variables 0 then it will delete the schemaHandle.] */
+            for (nIndex = 0; nIndex < schema->ModelTypeCount; nIndex++)
+            {
+                SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)schema->ModelTypes[nIndex];
+                if (modelType->DeviceCount > 0)
+                    break;
+            }
+            /* Codes_SRS_SCHEMA_07_191: [If 1 or more DeviceCount variables are > 0 then Schema_DestroyIfUnused shall do nothing.] */
+            if (nIndex == schema->ModelTypeCount)
+            {
+                Schema_Destroy(schemaHandle);
+                result = SCHEMA_OK;
+            }
+            else
+            {
+                result = SCHEMA_MODEL_IN_USE;
+            }
+        }
+    }
+    else
+    {
+        result = SCHEMA_INVALID_ARG;
+    }
+    return result;
+}
+
+SCHEMA_RESULT Schema_AddDeviceRef(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle)
+{
+    SCHEMA_RESULT result;
+    if (modelTypeHandle == NULL)
+    {
+        /* Codes_SRS_SCHEMA_07_187: [Schema_AddDeviceRef shall return SCHEMA_INVALID_ARG if modelTypeHandle is NULL.] */
+        result = SCHEMA_INVALID_ARG;
+        LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+    }
+    else
+    {
+        SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+        /* Codes_SRS_SCHEMA_07_188: [If the modelTypeHandle is nonNULL, Schema_AddDeviceRef shall increment the SCHEMA_MODEL_TYPE_HANDLE_DATA DeviceCount variable.] */
+        model->DeviceCount++;
+        result = SCHEMA_OK;
+    }
+    return result;
+}
+
+SCHEMA_RESULT Schema_ReleaseDeviceRef(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle)
+{
+    SCHEMA_RESULT result;
+    /* Codes_SRS_SCHEMA_07_184: [Schema_DeviceRelease shall do nothing if the supplied modelHandle is NULL.] */
+    if (modelTypeHandle == NULL)
+    {
+        result = SCHEMA_INVALID_ARG;
+        LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+    }
+    else
+    {
+        SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+        if (model->DeviceCount > 0)
+        {
+            /* Codes_SRS_SCHEMA_07_186: [On a nonNULL SCHEMA_MODEL_TYPE_HANDLE if the DeviceCount variable is > 0 then the variable will be decremented.] */
+            model->DeviceCount--;
+            result = SCHEMA_OK;
+        }
+        else
+        {
+result = SCHEMA_DEVICE_COUNT_ZERO;
+LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+        }
+    }
+    return result;
+}
+
+/* Codes_SRS_SCHEMA_99_007:[Schema_CreateModelType shall create a new model type and return a handle to it.] */
+SCHEMA_MODEL_TYPE_HANDLE Schema_CreateModelType(SCHEMA_HANDLE schemaHandle, const char* modelName)
+{
+    SCHEMA_MODEL_TYPE_HANDLE result;
+
+    /* Codes_SRS_SCHEMA_99_010:[If any of the arguments is NULL, Schema_CreateModelType shall fail.] */
+    if ((schemaHandle == NULL) ||
+        (modelName == NULL))
+    {
+        /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */
+        result = NULL;
+        LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
+    }
+    else
+    {
+        SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
+
+        /* Codes_SRS_SCHEMA_99_100: [Schema_CreateModelType shall return SCHEMA_DUPLICATE_ELEMENT if modelName already exists.] */
+        size_t i;
+        for (i = 0; i < schema->ModelTypeCount; i++)
+        {
+            SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)(schema->ModelTypes[i]);
+            if (strcmp(model->Name, modelName) == 0)
+            {
+                break;
+            }
+        }
+
+        if (i < schema->ModelTypeCount)
+        {
+            /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */
+            result = NULL;
+            LogError("%s Model Name already exists", modelName);
+        }
+
+        else
+        {
+            SCHEMA_MODEL_TYPE_HANDLE* newModelTypes = (SCHEMA_MODEL_TYPE_HANDLE*)realloc(schema->ModelTypes, sizeof(SCHEMA_MODEL_TYPE_HANDLE) * (schema->ModelTypeCount + 1));
+            if (newModelTypes == NULL)
+            {
+                /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */
+                result = NULL;
+                LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
+            }
+            else
+            {
+                SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType;
+                schema->ModelTypes = newModelTypes;
+
+                if ((modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)calloc(1, sizeof(SCHEMA_MODEL_TYPE_HANDLE_DATA))) == NULL)
+                {
+
+                    /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */
+                    result = NULL;
+                    LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
+                }
+                else if (mallocAndStrcpy_s((char**)&modelType->Name, modelName) != 0)
+                {
+                    /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */
+                    result = NULL;
+                    free(modelType);
+                    LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
+                }
+                else
+                {
+                    modelType->models = VECTOR_create(sizeof(MODEL_IN_MODEL));
+                    if (modelType->models == NULL)
+                    {
+                        /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */
+                        LogError("unable to VECTOR_create");
+                        free((void*)modelType->Name);
+                        free((void*)modelType);
+                        result = NULL;
+                    }
+                    else
+                    {
+                        if ((modelType->reportedProperties = VECTOR_create(sizeof(SCHEMA_REPORTED_PROPERTY_HANDLE))) == NULL)
+                        {
+                            /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */
+                            LogError("failed to VECTOR_create (reported properties)");
+                            VECTOR_destroy(modelType->models);
+                            free((void*)modelType->Name);
+                            free((void*)modelType);
+                            result = NULL;
+
+                        }
+                        else
+                        {
+                            /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */
+                            if ((modelType->desiredProperties = VECTOR_create(sizeof(SCHEMA_DESIRED_PROPERTY_HANDLE))) == NULL)
+                            {
+                                LogError("failure in VECTOR_create (desired properties)");
+                                VECTOR_destroy(modelType->reportedProperties);
+                                VECTOR_destroy(modelType->models);
+                                free((void*)modelType->Name);
+                                free((void*)modelType);
+                                result = NULL;
+                            }
+                            else
+                            {
+                                if ((modelType->methods = VECTOR_create(sizeof(SCHEMA_METHOD_HANDLE))) == NULL)
+                                {
+                                    LogError("failure in VECTOR_create (desired properties)");
+                                    VECTOR_destroy(modelType->desiredProperties);
+                                    VECTOR_destroy(modelType->reportedProperties);
+                                    VECTOR_destroy(modelType->models);
+                                    free((void*)modelType->Name);
+                                    free((void*)modelType);
+                                    result = NULL;
+                                }
+                                else
+                                {
+                                    modelType->PropertyCount = 0;
+                                    modelType->Properties = NULL;
+                                    modelType->ActionCount = 0;
+                                    modelType->Actions = NULL;
+                                    modelType->SchemaHandle = schemaHandle;
+                                    modelType->DeviceCount = 0;
+
+                                    schema->ModelTypes[schema->ModelTypeCount] = modelType;
+                                    schema->ModelTypeCount++;
+                                    /* Codes_SRS_SCHEMA_99_008:[On success, a non-NULL handle shall be returned.] */
+                                    result = (SCHEMA_MODEL_TYPE_HANDLE)modelType;
+                                }
+                            }
+                        }
+                    }
+                }
+
+                /* If possible, reduce the memory of over allocation */
+                if ((result == NULL) &&(schema->ModelTypeCount>0))
+                {
+                    SCHEMA_MODEL_TYPE_HANDLE* oldModelTypes = (SCHEMA_MODEL_TYPE_HANDLE*)realloc(schema->ModelTypes, sizeof(SCHEMA_MODEL_TYPE_HANDLE) * schema->ModelTypeCount);
+                    if (oldModelTypes == NULL)
+                    {
+                        LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
+                    }
+                    else
+                    {
+                        schema->ModelTypes = oldModelTypes;
+                    }
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+SCHEMA_HANDLE Schema_GetSchemaForModelType(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle)
+{
+    SCHEMA_HANDLE result;
+
+    if (modelTypeHandle == NULL)
+    {
+        /* Codes_SRS_SCHEMA_99_132: [If the modelTypeHandle argument is NULL, Schema_GetSchemaForModelType shall return NULL.] */
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_SCHEMA_99_131: [Schema_GetSchemaForModelType returns the schema handle for a given model type.] */
+        result = ((SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle)->SchemaHandle;
+    }
+
+    return result;
+}
+
+/* Codes_SRS_SCHEMA_99_011:[Schema_AddModelProperty shall add one property to the model type identified by modelTypeHandle.] */
+SCHEMA_RESULT Schema_AddModelProperty(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName, const char* propertyType)
+{
+    return AddModelProperty((SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle, propertyName, propertyType);
+}
+
+static bool reportedPropertyExists(const void* element, const void* value)
+{
+    SCHEMA_REPORTED_PROPERTY_HANDLE_DATA* reportedProperty = *(SCHEMA_REPORTED_PROPERTY_HANDLE_DATA**)element;
+    return (strcmp(reportedProperty->reportedPropertyName, value) == 0);
+}
+
+SCHEMA_RESULT Schema_AddModelReportedProperty(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* reportedPropertyName, const char* reportedPropertyType)
+{
+    SCHEMA_RESULT result;
+    /*Codes_SRS_SCHEMA_02_001: [ If modelTypeHandle is NULL then Schema_AddModelReportedProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
+    /*Codes_SRS_SCHEMA_02_002: [ If reportedPropertyName is NULL then Schema_AddModelReportedProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
+    /*Codes_SRS_SCHEMA_02_003: [ If reportedPropertyType is NULL then Schema_AddModelReportedProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
+    if (
+        (modelTypeHandle == NULL) ||
+        (reportedPropertyName == NULL) ||
+        (reportedPropertyType == NULL)
+        )
+    {
+        LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* reportedPropertyName=%p, const char* reportedPropertyType=%p", modelTypeHandle, reportedPropertyName, reportedPropertyType);
+        result = SCHEMA_INVALID_ARG;
+    }
+    else
+    {
+        SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+        /*Codes_SRS_SCHEMA_02_004: [ If reportedPropertyName has already been added then Schema_AddModelReportedProperty shall fail and return SCHEMA_PROPERTY_ELEMENT_EXISTS. ]*/
+        if (VECTOR_find_if(modelType->reportedProperties, reportedPropertyExists, reportedPropertyName) != NULL)
+        {
+            LogError("unable to add reportedProperty %s because it already exists", reportedPropertyName);
+            result = SCHEMA_DUPLICATE_ELEMENT;
+        }
+        else
+        {
+            /*Codes_SRS_SCHEMA_02_005: [ Schema_AddModelReportedProperty shall record reportedPropertyName and reportedPropertyType. ]*/
+            SCHEMA_REPORTED_PROPERTY_HANDLE_DATA* reportedProperty = (SCHEMA_REPORTED_PROPERTY_HANDLE_DATA*)malloc(sizeof(SCHEMA_REPORTED_PROPERTY_HANDLE_DATA));
+            if (reportedProperty == NULL)
+            {
+                /*Codes_SRS_SCHEMA_02_006: [ If any error occurs then Schema_AddModelReportedProperty shall fail and return SCHEMA_ERROR. ]*/
+                LogError("unable to malloc");
+                result = SCHEMA_ERROR;
+            }
+            else
+            {
+                if (mallocAndStrcpy_s((char**)&reportedProperty->reportedPropertyName, reportedPropertyName) != 0)
+                {
+                    /*Codes_SRS_SCHEMA_02_006: [ If any error occurs then Schema_AddModelReportedProperty shall fail and return SCHEMA_ERROR. ]*/
+                    LogError("unable to mallocAndStrcpy_s");
+                    free(reportedProperty);
+                    result = SCHEMA_ERROR;
+                }
+                else
+                {
+                    if (mallocAndStrcpy_s((char**)&reportedProperty->reportedPropertyType, reportedPropertyType) != 0)
+                    {
+                        /*Codes_SRS_SCHEMA_02_006: [ If any error occurs then Schema_AddModelReportedProperty shall fail and return SCHEMA_ERROR. ]*/
+                        LogError("unable to mallocAndStrcpy_s");
+                        free((void*)reportedProperty->reportedPropertyName);
+                        free(reportedProperty);
+                        result = SCHEMA_ERROR;
+                    }
+                    else
+                    {
+                        if (VECTOR_push_back(modelType->reportedProperties, &reportedProperty, 1) != 0)
+                        {
+                            /*Codes_SRS_SCHEMA_02_006: [ If any error occurs then Schema_AddModelReportedProperty shall fail and return SCHEMA_ERROR. ]*/
+                            LogError("unable to VECTOR_push_back");
+                            free((void*)reportedProperty->reportedPropertyType);
+                            free((void*)reportedProperty->reportedPropertyName);
+                            free(reportedProperty);
+                            result = SCHEMA_ERROR;
+                        }
+                        else
+                        {
+                            /*Codes_SRS_SCHEMA_02_007: [ Otherwise Schema_AddModelReportedProperty shall succeed and return SCHEMA_OK. ]*/
+                            result = SCHEMA_OK;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return result;
+}
+
+SCHEMA_ACTION_HANDLE Schema_CreateModelAction(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* actionName)
+{
+    SCHEMA_ACTION_HANDLE result;
+
+    /* Codes_SRS_SCHEMA_99_104: [If any of the modelTypeHandle or actionName arguments is NULL, Schema_CreateModelAction shall return NULL.] */
+    if ((modelTypeHandle == NULL) ||
+        (actionName == NULL))
+    {
+        result = NULL;
+        LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
+    }
+    else
+    {
+        SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+        size_t i;
+
+        /* Codes_SRS_SCHEMA_99_105: [The action name shall be unique per model, if the same action name is added twice to a model, Schema_CreateModelAction shall return NULL.] */
+        for (i = 0; i < modelType->ActionCount; i++)
+        {
+            SCHEMA_ACTION_HANDLE_DATA* action = (SCHEMA_ACTION_HANDLE_DATA*)modelType->Actions[i];
+            if (strcmp(action->ActionName, actionName) == 0)
+            {
+                break;
+            }
+        }
+
+        if (i < modelType->ActionCount)
+        {
+            result = NULL;
+            LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_DUPLICATE_ELEMENT));
+        }
+        else
+        {
+            /* Codes_SRS_SCHEMA_99_102: [Schema_CreateModelAction shall add one action to the model type identified by modelTypeHandle.] */
+            SCHEMA_ACTION_HANDLE* newActions = (SCHEMA_ACTION_HANDLE*)realloc(modelType->Actions, sizeof(SCHEMA_ACTION_HANDLE) * (modelType->ActionCount + 1));
+            if (newActions == NULL)
+            {
+                /* Codes_SRS_SCHEMA_99_106: [On any other error, Schema_CreateModelAction shall return NULL.]*/
+                result = NULL;
+                LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
+            }
+            else
+            {
+                SCHEMA_ACTION_HANDLE_DATA* newAction;
+                modelType->Actions = newActions;
+
+                /* Codes_SRS_SCHEMA_99_103: [On success, Schema_CreateModelAction shall return a none-NULL SCHEMA_ACTION_HANDLE to the newly created action.] */
+                if ((newAction = (SCHEMA_ACTION_HANDLE_DATA*)calloc(1, sizeof(SCHEMA_ACTION_HANDLE_DATA))) == NULL)
+                {
+                    /* Codes_SRS_SCHEMA_99_106: [On any other error, Schema_CreateModelAction shall return NULL.]*/
+                    result = NULL;
+                    LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
+                }
+                else
+                {
+                    if (mallocAndStrcpy_s((char**)&newAction->ActionName, actionName) != 0)
+                    {
+                        /* Codes_SRS_SCHEMA_99_106: [On any other error, Schema_CreateModelAction shall return NULL.]*/
+                        free(newAction);
+                        result = NULL;
+                        LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
+                    }
+                    else
+                    {
+                        newAction->ArgumentCount = 0;
+                        newAction->ArgumentHandles = NULL;
+
+                        modelType->Actions[modelType->ActionCount] = newAction;
+                        modelType->ActionCount++;
+                        result = (SCHEMA_ACTION_HANDLE)(newAction);
+                    }
+
+                    /* If possible, reduce the memory of over allocation */
+                    if (result == NULL)
+                    {
+                        if (modelType->ActionCount > 0)
+                        {
+                            SCHEMA_ACTION_HANDLE *oldActions = (SCHEMA_ACTION_HANDLE *)realloc(modelType->Actions, sizeof(SCHEMA_ACTION_HANDLE) * modelType->ActionCount);
+                            if (oldActions == NULL)
+                            {
+                                LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
+                            }
+                            else
+                            {
+                                modelType->Actions = oldActions;
+                            }
+                        }
+                        else
+                        {
+                            modelType->Actions = NULL;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return result;
+}
+
+
+static bool methodExists(const void* element, const void* value)
+{
+    const SCHEMA_METHOD_HANDLE* method = (const SCHEMA_METHOD_HANDLE*)element;
+    return (strcmp((*method)->methodName, value) == 0);
+}
+
+
+SCHEMA_METHOD_HANDLE Schema_CreateModelMethod(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* methodName)
+{
+    SCHEMA_METHOD_HANDLE result;
+
+    /*Codes_SRS_SCHEMA_02_096: [ If modelTypeHandle is NULL then Schema_CreateModelMethod shall fail and return NULL. ]*/
+    /*Codes_SRS_SCHEMA_02_097: [ If methodName is NULL then Schema_CreateModelMethod shall fail and return NULL. ]*/
+    if ((modelTypeHandle == NULL) ||
+        (methodName == NULL))
+    {
+        result = NULL;
+        LogError("invalid argument: SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* methodName=%p", modelTypeHandle, methodName);
+    }
+    else
+    {
+        /*Codes_SRS_SCHEMA_02_103: [ If methodName already exists, then Schema_CreateModelMethod shall fail and return NULL. ]*/
+        if (VECTOR_find_if(modelTypeHandle->methods, methodExists, methodName) != NULL)
+        {
+            LogError("method %s already exists", methodName);
+            result = NULL;
+        }
+        else
+        {
+            /*Codes_SRS_SCHEMA_02_098: [ Schema_CreateModelMethod shall allocate the space for the method. ]*/
+            result = malloc(sizeof(SCHEMA_METHOD_HANDLE_DATA));
+            if (result == NULL)
+            {
+                LogError("failed to malloc");
+                /*Codes_SRS_SCHEMA_02_102: [ If any of the above fails, then Schema_CreateModelMethod shall fail and return NULL. ]*/
+                /*return as is*/
+            }
+            else
+            {
+                /*Codes_SRS_SCHEMA_02_099: [ Schema_CreateModelMethod shall create a VECTOR that will hold the method's arguments. ]*/
+                result->methodArguments = VECTOR_create(sizeof(SCHEMA_METHOD_ARGUMENT_HANDLE));
+                if (result->methodArguments == NULL)
+                {
+                    /*Codes_SRS_SCHEMA_02_102: [ If any of the above fails, then Schema_CreateModelMethod shall fail and return NULL. ]*/
+                    LogError("failure in VECTOR_create");
+                    free(result);
+                    result = NULL;
+                }
+                else
+                {
+                    /*Codes_SRS_SCHEMA_02_100: [ Schema_CreateModelMethod shall clone methodName ]*/
+                    if (mallocAndStrcpy_s(&result->methodName, methodName) != 0)
+                    {
+                        /*Codes_SRS_SCHEMA_02_102: [ If any of the above fails, then Schema_CreateModelMethod shall fail and return NULL. ]*/
+                        LogError("failure in mallocAndStrcpy_s");
+                        VECTOR_destroy(result->methodArguments);
+                        free(result);
+                        result = NULL;
+                    }
+                    else
+                    {
+                        /*Codes_SRS_SCHEMA_02_101: [ Schema_CreateModelMethod shall add the new created method to the model's list of methods. ]*/
+                        if (VECTOR_push_back(modelTypeHandle->methods, &result, 1) != 0)
+                        {
+                            /*Codes_SRS_SCHEMA_02_102: [ If any of the above fails, then Schema_CreateModelMethod shall fail and return NULL. ]*/
+                            LogError("failure in VECTOR_push_back");
+                            free(result->methodName);
+                            VECTOR_destroy(result->methodArguments);
+                            free(result);
+                            result = NULL;
+                        }
+                        else
+                        {
+                            /*Codes_SRS_SCHEMA_02_104: [ Otherwise, Schema_CreateModelMethod shall succeed and return a non-NULL SCHEMA_METHOD_HANDLE. ]*/
+                            /*return as is*/
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return result;
+}
+
+
+SCHEMA_RESULT Schema_AddModelActionArgument(SCHEMA_ACTION_HANDLE actionHandle, const char* argumentName, const char* argumentType)
+{
+    SCHEMA_RESULT result;
+
+    /* Codes_SRS_SCHEMA_99_109: [If any of the arguments is NULL, Schema_AddModelActionArgument shall return SCHEMA_INVALID_ARG.] */
+    if ((actionHandle == NULL) ||
+        (argumentName == NULL) ||
+        (argumentType == NULL))
+    {
+        result = SCHEMA_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+    }
+    else
+    {
+        SCHEMA_ACTION_HANDLE_DATA* action = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle;
+
+        /* Codes_SRS_SCHEMA_99_110: [The argument name shall be unique per action, if the same name is added twice to an action, SCHEMA_DUPLICATE_ELEMENT shall be returned.] */
+        /* Codes_SRS_SCHEMA_99_111: [Schema_AddModelActionArgument shall accept arguments with different names of the same type.]  */
+        size_t i;
+        for (i = 0; i < action->ArgumentCount; i++)
+        {
+            SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* actionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)action->ArgumentHandles[i];
+            if (strcmp((actionArgument->Name), argumentName) == 0)
+            {
+                break;
+            }
+        }
+
+        if (i < action->ArgumentCount)
+        {
+            result = SCHEMA_DUPLICATE_ELEMENT;
+            LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+        }
+        else
+        {
+            /* Codes_SRS_SCHEMA_99_107: [Schema_AddModelActionArgument shall add one argument name & type to an action identified by actionHandle.]  */
+            SCHEMA_ACTION_ARGUMENT_HANDLE* newArguments = (SCHEMA_ACTION_ARGUMENT_HANDLE*)realloc(action->ArgumentHandles, sizeof(SCHEMA_ACTION_ARGUMENT_HANDLE) * (action->ArgumentCount + 1));
+            if (newArguments == NULL)
+            {
+                /* Codes_SRS_SCHEMA_99_112: [On any other error, Schema_ AddModelActionArgumet shall return SCHEMA_ERROR.] */
+                result = SCHEMA_ERROR;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+            }
+            else
+            {
+                action->ArgumentHandles = newArguments;
+
+                SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* newActionArgument;
+
+                action->ArgumentHandles = newArguments;
+                if ((newActionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)malloc(sizeof(SCHEMA_ACTION_ARGUMENT_HANDLE_DATA))) == NULL)
+                {
+                    /* Codes_SRS_SCHEMA_99_112: [On any other error, Schema_ AddModelActionArgumet shall return SCHEMA_ERROR.] */
+                    result = SCHEMA_ERROR;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+                }
+                else
+                {
+                    if (mallocAndStrcpy_s((char**)&newActionArgument->Name, argumentName) != 0)
+                    {
+                        /* Codes_SRS_SCHEMA_99_112: [On any other error, Schema_ AddModelActionArgumet shall return SCHEMA_ERROR.] */
+                        free(newActionArgument);
+                        result = SCHEMA_ERROR;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+                    }
+                    else if (mallocAndStrcpy_s((char**)&newActionArgument->Type, argumentType) != 0)
+                    {
+                        /* Codes_SRS_SCHEMA_99_112: [On any other error, Schema_ AddModelActionArgumet shall return SCHEMA_ERROR.] */
+                        free((void*)newActionArgument->Name);
+                        free(newActionArgument);
+                        result = SCHEMA_ERROR;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+                    }
+                    else
+                    {
+                        /* Codes_SRS_SCHEMA_99_119: [Schema_AddModelActionArgument shall preserve the order of the action arguments according to the order in which they were added, starting with index 0 for the first added argument.] */
+                        action->ArgumentHandles[action->ArgumentCount] = newActionArgument;
+                        action->ArgumentCount++;
+
+                        /* Codes_SRS_SCHEMA_99_108: [On success, Schema_AddModelActionArgunent shall return SCHEMA_OK.] */
+                        result = SCHEMA_OK;
+                    }
+                }
+
+                /* If possible, reduce the memory of over allocation */
+                if (result == SCHEMA_ERROR)
+                {
+                    if (action->ArgumentCount > 0)
+                    {
+                        SCHEMA_ACTION_ARGUMENT_HANDLE *oldArguments = (SCHEMA_ACTION_ARGUMENT_HANDLE *)realloc(action->ArgumentHandles, sizeof(SCHEMA_ACTION_ARGUMENT_HANDLE) * action->ArgumentCount);
+                        if (oldArguments == NULL)
+                        {
+                            LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
+                        }
+                        else
+                        {
+                            action->ArgumentHandles = oldArguments;
+                        }
+                    }
+                    else
+                    {
+                        action->ArgumentHandles = NULL;
+                    }
+                }
+            }
+        }
+    }
+    return result;
+}
+
+static bool methodFindArgumentByBame(const void* element, const void* value)
+{
+    /*element is a pointer to SCHEMA_METHOD_ARGUMENT_HANDLE*/
+    const SCHEMA_METHOD_ARGUMENT_HANDLE* decodedElement = (const SCHEMA_METHOD_ARGUMENT_HANDLE*)element;
+    const char* name = (const char*)value;
+    return (strcmp((*decodedElement)->Name, name) == 0);
+}
+
+SCHEMA_RESULT Schema_AddModelMethodArgument(SCHEMA_METHOD_HANDLE methodHandle, const char* argumentName, const char* argumentType)
+{
+    SCHEMA_RESULT result;
+    /*Codes_SRS_SCHEMA_02_105: [ If methodHandle is NULL then Schema_AddModelMethodArgument shall fail and return SCHEMA_INVALID_ARG. ]*/
+    /*Codes_SRS_SCHEMA_02_106: [ If argumentName is NULL then Schema_AddModelMethodArgument shall fail and return SCHEMA_INVALID_ARG. ]*/
+    /*Codes_SRS_SCHEMA_02_107: [ If argumentType is NULL then Schema_AddModelMethodArgument shall fail and return SCHEMA_INVALID_ARG. ]*/
+    if ((methodHandle == NULL) ||
+        (argumentName == NULL) ||
+        (argumentType == NULL))
+    {
+        result = SCHEMA_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+    }
+    else
+    {
+        /*Codes_SRS_SCHEMA_02_108: [ If argumentName already exists in the list of arguments then then Schema_AddModelMethodArgument shall fail and return SCHEMA_INVALID_ARG. ]*/
+        if (VECTOR_find_if(methodHandle->methodArguments, methodFindArgumentByBame, argumentName) != NULL)
+        {
+            LogError("an argument with name %s already exists", argumentName);
+            result = SCHEMA_INVALID_ARG;
+        }
+        else
+        {
+            /*Codes_SRS_SCHEMA_02_109: [ Schema_AddModelMethodArgument shall allocate memory for the new argument. ]*/
+            SCHEMA_METHOD_ARGUMENT_HANDLE_DATA* argument = malloc(sizeof(SCHEMA_METHOD_ARGUMENT_HANDLE_DATA));
+            if (argument == NULL)
+            {
+                /*Codes_SRS_SCHEMA_02_113: [ If any of the above operations fails, then Schema_AddModelMethodArgument shall fail and return SCHEMA_ERROR. ]*/
+                LogError("failure to malloc");
+                result = SCHEMA_ERROR;
+            }
+            else
+            {
+                /*Codes_SRS_SCHEMA_02_110: [ Schema_AddModelMethodArgument shall clone methodHandle. ]*/
+                if (mallocAndStrcpy_s(&argument->Name, argumentName) != 0)
+                {
+                    /*Codes_SRS_SCHEMA_02_113: [ If any of the above operations fails, then Schema_AddModelMethodArgument shall fail and return SCHEMA_ERROR. ]*/
+                    LogError("failure in mallocAndStrcpy_s");
+                    free(argument);
+                    result = SCHEMA_ERROR;
+                }
+                else
+                {
+                    /*Codes_SRS_SCHEMA_02_111: [ Schema_AddModelMethodArgument shall clone argumentType. ]*/
+                    if (mallocAndStrcpy_s(&argument->Type, argumentType) != 0)
+                    {
+                        /*Codes_SRS_SCHEMA_02_113: [ If any of the above operations fails, then Schema_AddModelMethodArgument shall fail and return SCHEMA_ERROR. ]*/
+                        LogError("failure in mallocAndStrcpy_s");
+                        free(argument->Name);
+                        free(argument);
+                        result = SCHEMA_ERROR;
+                    }
+                    else
+                    {
+                        /*Codes_SRS_SCHEMA_02_112: [ Schema_AddModelMethodArgument shall add the created argument to the method's list of arguments. ]*/
+                        if (VECTOR_push_back(methodHandle->methodArguments, &argument, 1) != 0)
+                        {
+                            /*Codes_SRS_SCHEMA_02_113: [ If any of the above operations fails, then Schema_AddModelMethodArgument shall fail and return SCHEMA_ERROR. ]*/
+                            LogError("failure in VECTOR_push_back");
+                            free(argument->Name);
+                            free(argument->Type);
+                            free(argument);
+                            result = SCHEMA_ERROR;
+                        }
+                        else
+                        {
+                            /*Codes_SRS_SCHEMA_02_114: [ Otherwise, Schema_AddModelMethodArgument shall succeed and return SCHEMA_OK. ]*/
+                            result = SCHEMA_OK;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return result;
+}
+
+SCHEMA_PROPERTY_HANDLE Schema_GetModelPropertyByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName)
+{
+    SCHEMA_PROPERTY_HANDLE result;
+
+    /* Codes_SRS_SCHEMA_99_038:[Schema_GetModelPropertyByName shall return NULL if unable to find a matching property or if any of the arguments are NULL.] */
+    if ((modelTypeHandle == NULL) ||
+        (propertyName == NULL))
+    {
+        result = NULL;
+        LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
+    }
+    else
+    {
+        size_t i;
+        SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+
+        /* Codes_SRS_SCHEMA_99_036:[Schema_GetModelPropertyByName shall return a non-NULL SCHEMA_PROPERTY_HANDLE corresponding to the model type identified by modelTypeHandle and matching the propertyName argument value.] */
+        for (i = 0; i < modelType->PropertyCount; i++)
+        {
+            SCHEMA_PROPERTY_HANDLE_DATA* modelProperty = (SCHEMA_PROPERTY_HANDLE_DATA*)modelType->Properties[i];
+            if (strcmp(modelProperty->PropertyName, propertyName) == 0)
+            {
+                break;
+            }
+        }
+
+        if (i == modelType->PropertyCount)
+        {
+            /* Codes_SRS_SCHEMA_99_038:[Schema_GetModelPropertyByName shall return NULL if unable to find a matching property or if any of the arguments are NULL.] */
+            result = NULL;
+            LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ELEMENT_NOT_FOUND));
+        }
+        else
+        {
+            result = (SCHEMA_PROPERTY_HANDLE)(modelType->Properties[i]);
+        }
+    }
+
+    return result;
+}
+
+SCHEMA_RESULT Schema_GetModelPropertyCount(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t* propertyCount)
+{
+    SCHEMA_RESULT result;
+
+    /* Codes_SRS_SCHEMA_99_092: [Schema_GetModelPropertyCount shall return SCHEMA_INVALID_ARG if any of the arguments is NULL.] */
+    if ((modelTypeHandle == NULL) ||
+        (propertyCount == NULL))
+    {
+        result = SCHEMA_INVALID_ARG;
+    }
+    else
+    {
+        /* Codes_SRS_SCHEMA_99_089: [Schema_GetModelPropertyCount shall provide the number of properties defined in the model type identified by modelTypeHandle.] */
+        SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+
+        /* Codes_SRS_SCHEMA_99_090: [The count shall be provided via the out argument propertyCount.]*/
+        *propertyCount = modelType->PropertyCount;
+
+        /* Codes_SRS_SCHEMA_99_091: [On success, Schema_GetModelPropertyCount shall return SCHEMA_OK.] */
+        result = SCHEMA_OK;
+    }
+
+    return result;
+}
+
+SCHEMA_RESULT Schema_GetModelReportedPropertyCount(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t* reportedPropertyCount)
+{
+    SCHEMA_RESULT result;
+    /*Codes_SRS_SCHEMA_02_008: [ If parameter modelTypeHandle is NULL then Schema_GetModelReportedPropertyCount shall fail and return SCHEMA_INVALID_ARG. ]*/
+    /*Codes_SRS_SCHEMA_02_009: [ If parameter reportedPropertyCount is NULL then Schema_GetModelReportedPropertyCount shall fail and return SCHEMA_INVALID_ARG. ]*/
+    if (
+        (modelTypeHandle == NULL)||
+        (reportedPropertyCount==NULL)
+        )
+    {
+        LogError("SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, size_t* reportedPropertyCount=%p", modelTypeHandle, reportedPropertyCount);
+        result = SCHEMA_INVALID_ARG;
+    }
+    else
+    {
+        /*Codes_SRS_SCHEMA_02_010: [ Schema_GetModelReportedPropertyCount shall provide in reportedPropertyCount the number of reported properties and return SCHEMA_OK. ]*/
+        SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+        *reportedPropertyCount = VECTOR_size(modelType->reportedProperties);
+        result = SCHEMA_OK;
+    }
+    return result;
+}
+
+SCHEMA_REPORTED_PROPERTY_HANDLE Schema_GetModelReportedPropertyByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* reportedPropertyName)
+{
+    SCHEMA_REPORTED_PROPERTY_HANDLE result;
+    /*Codes_SRS_SCHEMA_02_011: [ If argument modelTypeHandle is NULL then Schema_GetModelReportedPropertyByName shall fail and return NULL. ]*/
+    /*Codes_SRS_SCHEMA_02_012: [ If argument reportedPropertyName is NULL then Schema_GetModelReportedPropertyByName shall fail and return NULL. ]*/
+    if(
+        (modelTypeHandle == NULL) ||
+        (reportedPropertyName == NULL)
+        )
+    {
+        LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* reportedPropertyName=%p", modelTypeHandle, reportedPropertyName);
+        result = NULL;
+    }
+    else
+    {
+        SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+        /*Codes_SRS_SCHEMA_02_013: [ If reported property by the name reportedPropertyName exists then Schema_GetModelReportedPropertyByName shall succeed and return a non-NULL value. ]*/
+        /*Codes_SRS_SCHEMA_02_014: [ Otherwise Schema_GetModelReportedPropertyByName shall fail and return NULL. ]*/
+        if((result = VECTOR_find_if(modelType->reportedProperties, reportedPropertyExists, reportedPropertyName))==NULL)
+        {
+            LogError("a reported property with name \"%s\" does not exist", reportedPropertyName);
+        }
+        else
+        {
+            /*return as is*/
+        }
+    }
+    return result;
+}
+
+SCHEMA_REPORTED_PROPERTY_HANDLE Schema_GetModelReportedPropertyByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index)
+{
+    SCHEMA_REPORTED_PROPERTY_HANDLE result;
+    /*Codes_SRS_SCHEMA_02_015: [ If argument modelTypeHandle is NULL then Schema_GetModelReportedPropertyByIndex shall fail and return NULL. ]*/
+    if (modelTypeHandle == NULL)
+    {
+        LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, size_t index=%lu", modelTypeHandle, (unsigned long)index);
+        result = NULL;
+    }
+    else
+    {
+        SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+
+        /*Codes_SRS_SCHEMA_02_016: [ If a reported property with index equal to index exists then Schema_GetModelReportedPropertyByIndex shall succeed and return the non-NULL handle of that REPORTED_PROPERTY. ]*/
+        /*Codes_SRS_SCHEMA_02_017: [ Otherwise Schema_GetModelReportedPropertyByIndex shall fail and return NULL. ]*/
+        if ((result = VECTOR_element(modelType->reportedProperties, index)) == NULL)
+        {
+            LogError("index %lu is invalid", (unsigned long)index);
+        }
+        else
+        {
+            /*return as is*/
+        }
+    }
+    return result;
+}
+
+SCHEMA_PROPERTY_HANDLE Schema_GetModelPropertyByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index)
+{
+    SCHEMA_PROPERTY_HANDLE result;
+    SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+
+    /* Codes_SRS_SCHEMA_99_094: [Schema_GetModelProperty shall return NULL if the index specified is outside the valid range or if modelTypeHandle argument is NULL.] */
+    if ((modelTypeHandle == NULL) ||
+        (index >= modelType->PropertyCount))
+    {
+        result = NULL;
+        LogError("(Error code: %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
+    }
+    else
+    {
+        /* Tests_SRS_SCHEMA_99_093: [Schema_GetModelProperty shall return a non-NULL SCHEMA_PROPERTY_HANDLE corresponding to the model type identified by modelTypeHandle and matching the index number provided by the index argument.] */
+        /* Codes_SRS_SCHEMA_99_097: [index is zero based, and the order in which actions were added shall be the index in which they will be retrieved.] */
+        result = modelType->Properties[index];
+    }
+
+    return result;
+}
+
+SCHEMA_ACTION_HANDLE Schema_GetModelActionByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* actionName)
+{
+    SCHEMA_ACTION_HANDLE result;
+
+    /* Codes_SRS_SCHEMA_99_041:[Schema_GetModelActionByName shall return NULL if unable to find a matching action, if any of the arguments are NULL.] */
+    if ((modelTypeHandle == NULL) ||
+        (actionName == NULL))
+    {
+        result = NULL;
+        LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
+    }
+    else
+    {
+        size_t i;
+        SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+
+        /* Codes_SRS_SCHEMA_99_040:[Schema_GetModelActionByName shall return a non-NULL SCHEMA_ACTION_HANDLE corresponding to the model type identified by modelTypeHandle and matching the actionName argument value.] */
+        for (i = 0; i < modelType->ActionCount; i++)
+        {
+            SCHEMA_ACTION_HANDLE_DATA* modelAction = (SCHEMA_ACTION_HANDLE_DATA*)modelType->Actions[i];
+            if (strcmp(modelAction->ActionName, actionName) == 0)
+            {
+                break;
+            }
+        }
+
+        if (i == modelType->ActionCount)
+        {
+            /* Codes_SRS_SCHEMA_99_041:[Schema_GetModelActionByName shall return NULL if unable to find a matching action, if any of the arguments are NULL.] */
+            result = NULL;
+            LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ELEMENT_NOT_FOUND));
+        }
+        else
+        {
+            result = modelType->Actions[i];
+        }
+    }
+
+    return result;
+}
+
+static bool matchModelMethod(const void* element, const void* value)
+{
+    /*element is a pointer to SCHEMA_METHOD_HANDLE_DATA*/
+    const SCHEMA_METHOD_HANDLE* decodedElement = (const SCHEMA_METHOD_HANDLE* )element;
+    const char* name = (const char*)value;
+    return (strcmp((*decodedElement)->methodName, name) == 0);
+}
+
+SCHEMA_METHOD_HANDLE Schema_GetModelMethodByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* methodName)
+{
+    SCHEMA_METHOD_HANDLE result;
+
+    /*Codes_SRS_SCHEMA_02_115: [ If modelTypeHandle is NULL then Schema_GetModelMethodByName shall fail and return NULL. ]*/
+    /*Codes_SRS_SCHEMA_02_116: [ If methodName is NULL then Schema_GetModelMethodByName shall fail and return NULL. ]*/
+    if ((modelTypeHandle == NULL) ||
+        (methodName == NULL))
+    {
+        result = NULL;
+        LogError("invalid arguments SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* methodName=%p", modelTypeHandle, methodName);
+    }
+    else
+    {
+        /*Codes_SRS_SCHEMA_02_117: [ If a method with the name methodName exists then Schema_GetModelMethodByName shall succeed and returns its handle. ]*/
+        SCHEMA_METHOD_HANDLE* found = VECTOR_find_if(modelTypeHandle->methods, matchModelMethod, methodName);
+        if (found == NULL)
+        {
+            /*Codes_SRS_SCHEMA_02_118: [ Otherwise, Schema_GetModelMethodByName shall fail and return NULL. ]*/
+            LogError("no such method by name = %s", methodName);
+            result = NULL;
+        }
+        else
+        {
+            result = *found;
+        }
+    }
+
+    return result;
+}
+
+SCHEMA_RESULT Schema_GetModelActionCount(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t* actionCount)
+{
+    SCHEMA_RESULT result;
+
+    /* Codes_SRS_SCHEMA_99_045:[If any of the modelTypeHandle or actionCount arguments is NULL, Schema_GetModelActionCount shall return SCHEMA_INVALID_ARG.] */
+    if ((modelTypeHandle == NULL) ||
+        (actionCount == NULL))
+    {
+        result = SCHEMA_INVALID_ARG;
+        LogError("(result=%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+    }
+    else
+    {
+        /* Codes_SRS_SCHEMA_99_042:[Schema_GetModelActionCount shall provide the total number of actions defined in a model type identified by the modelTypeHandle.] */
+        SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+
+        /* Codes_SRS_SCHEMA_99_043:[The count shall be provided via the out argument actionCount.] */
+        *actionCount = modelType->ActionCount;
+
+        /* Codes_SRS_SCHEMA_99_044:[On success, Schema_GetModelActionCount shall return SCHEMA_OK.] */
+        result = SCHEMA_OK;
+    }
+
+    return result;
+}
+
+SCHEMA_ACTION_HANDLE Schema_GetModelActionByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index)
+{
+    SCHEMA_ACTION_HANDLE result;
+    SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+
+    /* Codes_SRS_SCHEMA_99_048:[Schema_GetModelAction shall return NULL if the index specified is outside the valid range or if modelTypeHandle argument is NULL.] */
+    if ((modelType == NULL) ||
+        (index >= modelType->ActionCount))
+    {
+        result = NULL;
+        LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
+    }
+    else
+    {
+        /* Codes_SRS_SCHEMA_99_047:[Schema_GetModelAction shall return a non-NULL SCHEMA_ACTION_HANDLE corresponding to the model type identified by modelTypeHandle and matching the index number provided by the index argument.] */
+        /* Codes_SRS_SCHEMA_99_096: [index is zero based and the order in which actions were added shall be the index in which they will be retrieved.] */
+        result = modelType->Actions[index];
+    }
+
+    return result;
+}
+
+const char* Schema_GetModelActionName(SCHEMA_ACTION_HANDLE actionHandle)
+{
+    const char* result;
+
+    /* Codes_SRS_SCHEMA_99_050:[If the actionHandle is NULL, Schema_GetModelActionName shall return NULL.] */
+    if (actionHandle == NULL)
+    {
+        result = NULL;
+        LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
+    }
+    else
+    {
+        SCHEMA_ACTION_HANDLE_DATA* action = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle;
+        /* Codes_SRS_SCHEMA_99_049:[Schema_GetModelActionName shall return the action name for a given action handle.] */
+        result = action->ActionName;
+    }
+
+    return result;
+}
+
+SCHEMA_RESULT Schema_GetModelActionArgumentCount(SCHEMA_ACTION_HANDLE actionHandle, size_t* argumentCount)
+{
+    SCHEMA_RESULT result;
+
+    /* Codes_SRS_SCHEMA_99_054:[If any argument is NULL, Schema_GetModelActionArgumentCount shall return SCHEMA_INVALID_ARG.] */
+    if ((actionHandle == NULL) ||
+        (argumentCount == NULL))
+    {
+        result = SCHEMA_INVALID_ARG;
+        LogError("(result=%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+    }
+    else
+    {
+        SCHEMA_ACTION_HANDLE_DATA* modelAction = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle;
+
+        /* Codes_SRS_SCHEMA_99_051:[Schema_GetModelActionArgumentCount shall provide the number of arguments for a specific schema action identified by actionHandle.] */
+        /* Codes_SRS_SCHEMA_99_052:[The argument count shall be provided via the out argument argumentCount.] */
+        *argumentCount = modelAction->ArgumentCount;
+
+        /* Codes_SRS_SCHEMA_99_053:[On success, Schema_GetModelActionArgumentCount shall return SCHEMA_OK.] */
+        result = SCHEMA_OK;
+    }
+
+    return result;
+}
+
+SCHEMA_RESULT Schema_GetModelMethodArgumentCount(SCHEMA_METHOD_HANDLE methodHandle, size_t* argumentCount)
+{
+    SCHEMA_RESULT result;
+
+    /*Codes_SRS_SCHEMA_02_119: [ If methodHandle is NULL then Schema_GetModelMethodArgumentCount shall fail and return SCHEMA_INVALID_ARG. ]*/
+    /*Codes_SRS_SCHEMA_02_120: [ If argumentCount is NULL then Schema_GetModelMethodArgumentCount shall fail and return SCHEMA_INVALID_ARG. ]*/
+    if ((methodHandle == NULL) ||
+        (argumentCount == NULL))
+    {
+        result = SCHEMA_INVALID_ARG;
+        LogError("(result=%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+    }
+    else
+    {
+        /*Codes_SRS_SCHEMA_02_121: [ Otherwise, Schema_GetModelMethodArgumentCount shall succeed, return in argumentCount the number of arguments for the method and return SCHEMA_OK. ]*/
+        *argumentCount = VECTOR_size(methodHandle->methodArguments);
+        result = SCHEMA_OK;
+    }
+
+    return result;
+}
+
+
+SCHEMA_ACTION_ARGUMENT_HANDLE Schema_GetModelActionArgumentByName(SCHEMA_ACTION_HANDLE actionHandle, const char* actionArgumentName)
+{
+    SCHEMA_ACTION_ARGUMENT_HANDLE result;
+
+    /* Codes_SRS_SCHEMA_99_118: [Schema_GetModelActionArgumentByName shall return NULL if unable to find a matching argument or if any of the arguments are NULL.] */
+    if ((actionHandle == NULL) ||
+        (actionArgumentName == NULL))
+    {
+        result = NULL;
+        LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
+    }
+    else
+    {
+        /* Codes_SRS_SCHEMA_99_118: [Schema_GetModelActionArgumentByName shall return NULL if unable to find a matching argument or if any of the arguments are NULL.] */
+        SCHEMA_ACTION_HANDLE_DATA* modelAction = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle;
+        size_t i;
+
+        for (i = 0; i < modelAction->ArgumentCount; i++)
+        {
+            SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* actionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)modelAction->ArgumentHandles[i];
+            if (strcmp(actionArgument->Name, actionArgumentName) == 0)
+            {
+                break;
+            }
+        }
+
+        if (i == modelAction->ArgumentCount)
+        {
+            /* Codes_SRS_SCHEMA_99_118: [Schema_GetModelActionArgumentByName shall return NULL if unable to find a matching argument or if any of the arguments are NULL.] */
+            result = NULL;
+            LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ELEMENT_NOT_FOUND));
+        }
+        else
+        {
+            /* Codes_SRS_SCHEMA_99_117: [Schema_GetModelActionArgumentByName shall return a non-NULL handle corresponding to an action argument identified by the actionHandle and actionArgumentName.] */
+            result = modelAction->ArgumentHandles[i];
+        }
+    }
+
+    return result;
+}
+
+SCHEMA_ACTION_ARGUMENT_HANDLE Schema_GetModelActionArgumentByIndex(SCHEMA_ACTION_HANDLE actionHandle, size_t argumentIndex)
+{
+    SCHEMA_ACTION_ARGUMENT_HANDLE result;
+    SCHEMA_ACTION_HANDLE_DATA* modelAction = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle;
+
+    /* Codes_SRS_SCHEMA_99_056:[Schema_GetModelActionArgument shall return NULL if the index specified is outside the valid range or if the actionHandle argument is NULL.] */
+    if ((actionHandle == NULL) ||
+        (argumentIndex >= modelAction->ArgumentCount))
+    {
+        result = NULL;
+        LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
+    }
+    else
+    {
+        /* Codes_SRS_SCHEMA_99_055:[Schema_GetModelActionArgument shall return a non-NULL SCHEMA_ACTION_ARGUMENT_HANDLE corresponding to the action type identified by actionHandle and matching the index number provided by the argumentIndex argument.] */
+        result = modelAction->ArgumentHandles[argumentIndex];
+    }
+
+    return result;
+}
+
+SCHEMA_METHOD_ARGUMENT_HANDLE Schema_GetModelMethodArgumentByIndex(SCHEMA_METHOD_HANDLE methodHandle, size_t argumentIndex)
+{
+    SCHEMA_METHOD_ARGUMENT_HANDLE result;
+
+    /*Codes_SRS_SCHEMA_02_122: [ If methodHandle is NULL then Schema_GetModelMethodArgumentByIndex shall fail and return NULL. ]*/
+    if (methodHandle == NULL)
+    {
+        result = NULL;
+        LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
+    }
+    else
+    {
+        /*Codes_SRS_SCHEMA_02_123: [ If argumentIndex does not exist then Schema_GetModelMethodArgumentByIndex shall fail and return NULL. ]*/
+        SCHEMA_METHOD_ARGUMENT_HANDLE *temp = VECTOR_element(methodHandle->methodArguments, argumentIndex);
+        if (temp == NULL)
+        {
+            result = NULL;
+        }
+        else
+        {
+            /*Codes_SRS_SCHEMA_02_124: [ Otherwise, Schema_GetModelMethodArgumentByIndex shall succeed and return a non-NULL value. ]*/
+            result = *temp;
+        }
+    }
+
+    return result;
+}
+
+
+const char* Schema_GetActionArgumentName(SCHEMA_ACTION_ARGUMENT_HANDLE actionArgumentHandle)
+{
+    const char* result;
+    /* Codes_SRS_SCHEMA_99_114: [Schema_GetActionArgumentName shall return NULL if actionArgumentHandle is NULL.] */
+    if (actionArgumentHandle == NULL)
+    {
+        result = NULL;
+        LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
+    }
+    else
+    {
+        /* Codes_SRS_SCHEMA_99_113: [Schema_GetActionArgumentName shall return the argument name identified by the actionArgumentHandle.] */
+        SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* actionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)actionArgumentHandle;
+        result = actionArgument->Name;
+    }
+    return result;
+}
+
+const char* Schema_GetMethodArgumentName(SCHEMA_METHOD_ARGUMENT_HANDLE methodArgumentHandle)
+{
+    const char* result;
+    /*Codes_SRS_SCHEMA_02_125: [ If methodArgumentHandle is NULL then Schema_GetMethodArgumentName shall fail and return NULL. ]*/
+    if (methodArgumentHandle == NULL)
+    {
+        result = NULL;
+        LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
+    }
+    else
+    {
+        /*Codes_SRS_SCHEMA_02_126: [ Otherwise, Schema_GetMethodArgumentName shall succeed and return a non-NULL value. ]*/
+        result = methodArgumentHandle->Name;
+    }
+    return result;
+}
+
+
+const char* Schema_GetActionArgumentType(SCHEMA_ACTION_ARGUMENT_HANDLE actionArgumentHandle)
+{
+    const char* result;
+    /* Codes_SRS_SCHEMA_99_116: [Schema_GetActionArgumentType shall return NULL if actionArgumentHandle is NULL.] */
+    if (actionArgumentHandle == NULL)
+    {
+        result = NULL;
+        LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
+    }
+    else
+    {
+        /* Codes_SRS_SCHEMA_99_115: [Schema_GetActionArgumentType shall return the argument type identified by the actionArgumentHandle.] */
+        SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* actionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)actionArgumentHandle;
+        result = actionArgument->Type;
+    }
+    return result;
+}
+
+const char* Schema_GetMethodArgumentType(SCHEMA_METHOD_ARGUMENT_HANDLE methodArgumentHandle)
+{
+    const char* result;
+    /*Codes_SRS_SCHEMA_02_127: [ If methodArgumentHandle is NULL then Schema_GetMethodArgumentType shall fail and return NULL. ]*/
+    if (methodArgumentHandle == NULL)
+    {
+        result = NULL;
+        LogError("invalid argument SCHEMA_METHOD_ARGUMENT_HANDLE methodArgumentHandle=%p", methodArgumentHandle);
+    }
+    else
+    {
+        /*Codes_SRS_SCHEMA_02_128: [ Otherwise, Schema_GetMethodArgumentType shall succeed and return a non-NULL value. ]*/
+        result = methodArgumentHandle->Type;
+    }
+    return result;
+}
+
+
+SCHEMA_STRUCT_TYPE_HANDLE Schema_CreateStructType(SCHEMA_HANDLE schemaHandle, const char* typeName)
+{
+    SCHEMA_STRUCT_TYPE_HANDLE result;
+    SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
+
+    /* Codes_SRS_SCHEMA_99_060:[If any of the arguments is NULL, Schema_CreateStructType shall return NULL.] */
+    if ((schema == NULL) ||
+        (typeName == NULL))
+    {
+        result = NULL;
+        LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
+    }
+    else
+    {
+        SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType;
+        size_t i;
+
+        /* Codes_SRS_SCHEMA_99_061:[If a struct type with the same name already exists, Schema_CreateStructType shall return NULL.] */
+        for (i = 0; i < schema->StructTypeCount; i++)
+        {
+            structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)schema->StructTypes[i];
+            if (strcmp(structType->Name, typeName) == 0)
+            {
+                break;
+            }
+        }
+
+        if (i < schema->StructTypeCount)
+        {
+            result = NULL;
+            LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_DUPLICATE_ELEMENT));
+        }
+        else
+        {
+            SCHEMA_STRUCT_TYPE_HANDLE* newStructTypes = (SCHEMA_STRUCT_TYPE_HANDLE*)realloc(schema->StructTypes, sizeof(SCHEMA_STRUCT_TYPE_HANDLE) * (schema->StructTypeCount + 1));
+            if (newStructTypes == NULL)
+            {
+                /* Codes_SRS_SCHEMA_99_066:[On any other error, Schema_CreateStructType shall return NULL.] */
+                result = NULL;
+                LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
+            }
+            else
+            {
+                schema->StructTypes = newStructTypes;
+                if ((structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)calloc(1, sizeof(SCHEMA_STRUCT_TYPE_HANDLE_DATA))) == NULL)
+                {
+                    /* Codes_SRS_SCHEMA_99_066:[On any other error, Schema_CreateStructType shall return NULL.] */
+                    result = NULL;
+                    LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
+                }
+                else if (mallocAndStrcpy_s((char**)&structType->Name, typeName) != 0)
+                {
+                    /* Codes_SRS_SCHEMA_99_066:[On any other error, Schema_CreateStructType shall return NULL.] */
+                    result = NULL;
+                    free(structType);
+                    LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
+                }
+                else
+                {
+                    /* Codes_SRS_SCHEMA_99_057:[Schema_CreateStructType shall create a new struct type and return a handle to it.] */
+                    schema->StructTypes[schema->StructTypeCount] = structType;
+                    schema->StructTypeCount++;
+                    structType->PropertyCount = 0;
+                    structType->Properties = NULL;
+
+                    /* Codes_SRS_SCHEMA_99_058:[On success, a non-NULL handle shall be returned.] */
+                    result = (SCHEMA_STRUCT_TYPE_HANDLE)structType;
+                }
+
+                /* If possible, reduce the memory of over allocation */
+                if (result == NULL)
+                {
+                    if (schema->StructTypeCount > 0)
+                    {
+                        SCHEMA_STRUCT_TYPE_HANDLE *oldStructTypes = (SCHEMA_STRUCT_TYPE_HANDLE *)realloc(schema->StructTypes, sizeof(SCHEMA_STRUCT_TYPE_HANDLE) * schema->StructTypeCount);
+                        if (oldStructTypes == NULL)
+                        {
+                            result = NULL;
+                            LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
+                        }
+                        else
+                        {
+                            schema->StructTypes = oldStructTypes;
+                        }
+                    }
+                    else
+                    {
+                        schema->StructTypes = NULL;
+                    }
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+const char* Schema_GetStructTypeName(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle)
+{
+    const char* result;
+
+    /* Codes_SRS_SCHEMA_99_136: [If structTypeHandle is NULL, Schema_GetStructTypeName shall return NULL.] */
+    if (structTypeHandle == NULL)
+    {
+        result = NULL;
+        LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
+    }
+    else
+    {
+        /* Codes_SRS_SCHEMA_99_135: [Schema_GetStructTypeName shall return the name of a struct type identified by the structTypeHandle argument.] */
+        result = ((SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle)->Name;
+    }
+
+    return result;
+}
+
+SCHEMA_RESULT Schema_GetStructTypeCount(SCHEMA_HANDLE schemaHandle, size_t* structTypeCount)
+{
+    SCHEMA_RESULT result;
+
+    /* Codes_SRS_SCHEMA_99_140: [Schema_GetStructTypeCount shall return SCHEMA_INVALID_ARG if any of the arguments is NULL.] */
+    if ((schemaHandle == NULL) ||
+        (structTypeCount == NULL))
+    {
+        result = SCHEMA_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+    }
+    else
+    {
+        /* Codes_SRS_SCHEMA_99_137: [Schema_GetStructTypeCount shall provide the number of structs defined in the schema identified by schemaHandle.] */
+        SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
+        /* Codes_SRS_SCHEMA_99_138: [The count shall be provided via the out argument structTypeCount.] */
+        *structTypeCount = schema->StructTypeCount;
+        /* Codes_SRS_SCHEMA_99_139: [On success, Schema_GetStructTypeCount shall return SCHEMA_OK.] */
+        result = SCHEMA_OK;
+    }
+
+    return result;
+}
+
+SCHEMA_STRUCT_TYPE_HANDLE Schema_GetStructTypeByName(SCHEMA_HANDLE schemaHandle, const char* name)
+{
+    SCHEMA_STRUCT_TYPE_HANDLE result;
+    SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
+
+    /* Codes_SRS_SCHEMA_99_069:[Schema_GetStructTypeByName shall return NULL if unable to find a matching struct or if any of the arguments are NULL.] */
+    if ((schemaHandle == NULL) ||
+        (name == NULL))
+    {
+        result = NULL;
+        LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
+    }
+    else
+    {
+        size_t i;
+
+        /* Codes_SRS_SCHEMA_99_068:[Schema_GetStructTypeByName shall return a non-NULL handle corresponding to the struct type identified by the structTypeName in the schemaHandle schema.] */
+        for (i = 0; i < schema->StructTypeCount; i++)
+        {
+            SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)schema->StructTypes[i];
+            if (strcmp(structType->Name, name) == 0)
+            {
+                break;
+            }
+        }
+
+        if (i == schema->StructTypeCount)
+        {
+            /* Codes_SRS_SCHEMA_99_069:[Schema_GetStructTypeByName shall return NULL if unable to find a matching struct or if any of the arguments are NULL.] */
+            result = NULL;
+            LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ELEMENT_NOT_FOUND));
+        }
+        else
+        {
+            result = schema->StructTypes[i];
+        }
+    }
+
+    return result;
+}
+
+SCHEMA_STRUCT_TYPE_HANDLE Schema_GetStructTypeByIndex(SCHEMA_HANDLE schemaHandle, size_t index)
+{
+    SCHEMA_STRUCT_TYPE_HANDLE result;
+    SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
+
+    /* Codes_SRS_SCHEMA_99_143: [Schema_GetStructTypeByIndex shall return NULL if the index specified is outside the valid range or if schemaHandle argument is NULL.] */
+    /* Codes_SRS_SCHEMA_99_142: [The index argument is zero based, and the order in which models were added shall be the index in which they will be retrieved.] */
+    if ((schemaHandle == NULL) ||
+        (index >= schema->StructTypeCount))
+    {
+        result = NULL;
+        LogError("(Error code: %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
+    }
+    else
+    {
+
+        /* Codes_SRS_SCHEMA_99_141: [Schema_GetStructTypeByIndex shall return a non-NULL SCHEMA_STRUCT_TYPE_HANDLE corresponding to the struct type identified by schemaHandle and matching the index number provided by the index argument.] */
+        /* Codes_SRS_SCHEMA_99_142: [The index argument is zero based, and the order in which models were added shall be the index in which they will be retrieved.] */
+        result = schema->StructTypes[index];
+    }
+    return result;
+}
+
+SCHEMA_RESULT Schema_AddStructTypeProperty(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle, const char* propertyName, const char* propertyType)
+{
+    SCHEMA_RESULT result;
+
+    /* Codes_SRS_SCHEMA_99_072:[If any of the arguments is NULL, Schema_AddStructTypeProperty shall return SCHEMA_INVALID_ARG.] */
+    if ((structTypeHandle == NULL) ||
+        (propertyName == NULL) ||
+        (propertyType == NULL))
+    {
+        result = SCHEMA_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+    }
+    else
+    {
+        size_t i;
+        SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle;
+
+        /* Codes_SRS_SCHEMA_99_074:[The property name shall be unique per struct type, if the same property name is added twice to a struct type, SCHEMA_DUPLICATE_ELEMENT shall be returned.] */
+        for (i = 0; i < structType->PropertyCount; i++)
+        {
+            SCHEMA_PROPERTY_HANDLE_DATA* property = (SCHEMA_PROPERTY_HANDLE_DATA*)structType->Properties[i];
+            if (strcmp(property->PropertyName, propertyName) == 0)
+            {
+                break;
+            }
+        }
+
+        if (i < structType->PropertyCount)
+        {
+            result = SCHEMA_DUPLICATE_ELEMENT;
+            LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+        }
+        else
+        {
+            SCHEMA_PROPERTY_HANDLE* newProperties = (SCHEMA_PROPERTY_HANDLE*)realloc(structType->Properties, sizeof(SCHEMA_PROPERTY_HANDLE) * (structType->PropertyCount + 1));
+            if (newProperties == NULL)
+            {
+                result = SCHEMA_ERROR;
+                LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+            }
+            else
+            {
+                SCHEMA_PROPERTY_HANDLE_DATA* newProperty;
+
+                structType->Properties = newProperties;
+                if ((newProperty = (SCHEMA_PROPERTY_HANDLE_DATA*)malloc(sizeof(SCHEMA_PROPERTY_HANDLE_DATA))) == NULL)
+                {
+                    result = SCHEMA_ERROR;
+                    LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+                }
+                else
+                {
+                    if (mallocAndStrcpy_s((char**)&newProperty->PropertyName, propertyName) != 0)
+                    {
+                        free(newProperty);
+                        result = SCHEMA_ERROR;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+                    }
+                    else if (mallocAndStrcpy_s((char**)&newProperty->PropertyType, propertyType) != 0)
+                    {
+                        free((void*)newProperty->PropertyName);
+                        free(newProperty);
+                        result = SCHEMA_ERROR;
+                        LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+                    }
+                    else
+                    {
+                        /* Codes_SRS_SCHEMA_99_070:[Schema_AddStructTypeProperty shall add one property to the struct type identified by structTypeHandle.] */
+                        structType->Properties[structType->PropertyCount] = (SCHEMA_PROPERTY_HANDLE)newProperty;
+                        structType->PropertyCount++;
+
+                        /* Codes_SRS_SCHEMA_99_071:[On success, Schema_AddStructTypeProperty shall return SCHEMA_OK.] */
+                        result = SCHEMA_OK;
+                    }
+                }
+
+                /* If possible, reduce the memory of over allocation */
+                if (result != SCHEMA_OK)
+                {
+                    if (structType->PropertyCount > 0)
+                    {
+                        SCHEMA_PROPERTY_HANDLE *oldProperties = (SCHEMA_PROPERTY_HANDLE *)realloc(structType->Properties, sizeof(SCHEMA_PROPERTY_HANDLE) * structType->PropertyCount);
+                        if (oldProperties == NULL)
+                        {
+                            result = SCHEMA_ERROR;
+                            LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+                        }
+                        else
+                        {
+                            structType->Properties = oldProperties;
+                        }
+                    }
+                    else
+                    {
+                        structType->Properties = NULL;
+                    }
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+SCHEMA_PROPERTY_HANDLE Schema_GetStructTypePropertyByName(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle, const char* propertyName)
+{
+    SCHEMA_PROPERTY_HANDLE result;
+
+    /* Codes_SRS_SCHEMA_99_076:[Schema_GetStructTypePropertyByName shall return NULL if unable to find a matching property or if any of the arguments are NULL.] */
+    if ((structTypeHandle == NULL) ||
+        (propertyName == NULL))
+    {
+        result = NULL;
+        LogError("(Error code: %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
+    }
+    else
+    {
+        size_t i;
+        SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle;
+
+        for (i = 0; i < structType->PropertyCount; i++)
+        {
+            SCHEMA_PROPERTY_HANDLE_DATA* modelProperty = (SCHEMA_PROPERTY_HANDLE_DATA*)structType->Properties[i];
+            if (strcmp(modelProperty->PropertyName, propertyName) == 0)
+            {
+                break;
+            }
+        }
+
+        /* Codes_SRS_SCHEMA_99_076:[Schema_GetStructTypePropertyByName shall return NULL if unable to find a matching property or if any of the arguments are NULL.] */
+        if (i == structType->PropertyCount)
+        {
+            result = NULL;
+            LogError("(Error code: %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ELEMENT_NOT_FOUND));
+        }
+        /* Codes_SRS_SCHEMA_99_075:[Schema_GetStructTypePropertyByName shall return a non-NULL handle corresponding to a property identified by the structTypeHandle and propertyName.] */
+        else
+        {
+            result = structType->Properties[i];
+        }
+    }
+
+    return result;
+}
+
+SCHEMA_RESULT Schema_GetStructTypePropertyCount(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle, size_t* propertyCount)
+{
+    SCHEMA_RESULT result;
+
+    /* Codes_SRS_SCHEMA_99_079: [Schema_GetStructTypePropertyCount shall return SCHEMA_INVALID_ARG if any of the structlTypeHandle or propertyCount arguments is NULL.] */
+    if ((structTypeHandle == NULL) ||
+        (propertyCount == NULL))
+    {
+        result = SCHEMA_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+    }
+    else
+    {
+        SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle;
+
+        /* Codes_SRS_SCHEMA_99_077: [Schema_GetStructTypePropertyCount shall provide the total number of properties defined in a struct type identified by structTypeHandle. The value is provided via the out argument propertyCount.] */
+        /* Codes_SRS_SCHEMA_99_081: [The count shall be provided via the out argument propertyCount.] */
+        *propertyCount = structType->PropertyCount;
+
+        /* Codes_SRS_SCHEMA_99_078: [On success, Schema_ GetStructTypePropertyCount shall return SCHEMA_OK.] */
+        result = SCHEMA_OK;
+    }
+
+    return result;
+}
+
+SCHEMA_PROPERTY_HANDLE Schema_GetStructTypePropertyByIndex(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle, size_t index)
+{
+    SCHEMA_PROPERTY_HANDLE result;
+    SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle;
+
+    /* Codes_SRS_SCHEMA_99_083: [Schema_ GetStructTypeProperty shall return NULL if the index specified is outside the valid range, if structTypeHandle argument is NULL] */
+    if ((structTypeHandle == NULL) ||
+        (index >= structType->PropertyCount))
+    {
+        result = NULL;
+        LogError("(Error code: %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
+    }
+    else
+    {
+        /* Codes_SRS_SCHEMA_99_082: [Schema_GetStructTypeProperty shall return a non-NULL SCHEMA_PROPERTY_HANDLE corresponding to the struct type identified by strutTypeHandle and matching the index number provided by the index argument.] */
+        /* Codes_SRS_SCHEMA_99_098: [index is zero based and the order in which actions were added shall be the index in which they will be retrieved.] */
+        result = structType->Properties[index];
+    }
+
+    return result;
+}
+
+const char* Schema_GetPropertyName(SCHEMA_PROPERTY_HANDLE propertyHandle)
+{
+    const char* result;
+
+    /* Codes_SRS_SCHEMA_99_086: [If propertyHandle is NULL, Schema_GetPropertyName shall return NULL.] */
+    if (propertyHandle == NULL)
+    {
+        result = NULL;
+        LogError("(Error code: %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
+    }
+    else
+    {
+        SCHEMA_PROPERTY_HANDLE_DATA* propertyType = (SCHEMA_PROPERTY_HANDLE_DATA*)propertyHandle;
+
+        /* Codes_SRS_SCHEMA_99_085: [Schema_GetPropertyName shall return the property name identified by the propertyHandle.] */
+        result = propertyType->PropertyName;
+    }
+
+    return result;
+}
+
+const char* Schema_GetPropertyType(SCHEMA_PROPERTY_HANDLE propertyHandle)
+{
+    const char* result;
+
+    /* Codes_SRS_SCHEMA_99_088: [If propertyHandle is NULL, Schema_GetPropertyType shall return NULL.] */
+    if (propertyHandle == NULL)
+    {
+        result = NULL;
+        LogError("(Error code: %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
+    }
+    else
+    {
+        SCHEMA_PROPERTY_HANDLE_DATA* modelProperty = (SCHEMA_PROPERTY_HANDLE_DATA*)propertyHandle;
+
+        /* Codes_SRS_SCHEMA_99_087: [Schema_GetPropertyType shall return the property type identified by the propertyHandle.] */
+        result = modelProperty->PropertyType;
+    }
+
+    return result;
+}
+
+SCHEMA_RESULT Schema_GetModelCount(SCHEMA_HANDLE schemaHandle, size_t* modelCount)
+{
+    SCHEMA_RESULT result;
+    /* Codes_SRS_SCHEMA_99_123: [Schema_GetModelCount shall return SCHEMA_INVALID_ARG if any of the arguments is NULL.] */
+    if ((schemaHandle == NULL) ||
+        (modelCount == NULL) )
+    {
+        result = SCHEMA_INVALID_ARG;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+    }
+    else
+    {
+        /* Codes_SRS_SCHEMA_99_120: [Schema_GetModelCount shall provide the number of models defined in the schema identified by schemaHandle.] */
+        SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
+        /* Codes_SRS_SCHEMA_99_121: [The count shall be provided via the out argument modelCount.] */
+        *modelCount = schema->ModelTypeCount;
+        /* Codes_SRS_SCHEMA_99_122: [On success, Schema_GetModelCount shall return SCHEMA_OK.] */
+        result = SCHEMA_OK;
+    }
+    return result;
+}
+
+SCHEMA_MODEL_TYPE_HANDLE Schema_GetModelByName(SCHEMA_HANDLE schemaHandle, const char* modelName)
+{
+    SCHEMA_MODEL_TYPE_HANDLE result;
+
+    /* Codes_SRS_SCHEMA_99_125: [Schema_GetModelByName shall return NULL if unable to find a matching model, or if any of the arguments are NULL.] */
+    if ((schemaHandle == NULL) ||
+        (modelName == NULL))
+    {
+        result = NULL;
+        LogError("(Error code: %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
+    }
+    else
+    {
+        /* Codes_SRS_SCHEMA_99_124: [Schema_GetModelByName shall return a non-NULL SCHEMA_MODEL_TYPE_HANDLE corresponding to the model identified by schemaHandle and matching the modelName argument value.] */
+        SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
+        size_t i;
+        for (i = 0; i < schema->ModelTypeCount; i++)
+        {
+            SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)schema->ModelTypes[i];
+            if (strcmp(modelName, modelType->Name)==0)
+            {
+                break;
+            }
+        }
+        if (i == schema->ModelTypeCount)
+        {
+            /* Codes_SRS_SCHEMA_99_125: [Schema_GetModelByName shall return NULL if unable to find a matching model, or if any of the arguments are NULL.] */
+            result = NULL;
+        }
+        else
+        {
+            result = schema->ModelTypes[i];
+        }
+    }
+    return result;
+}
+
+SCHEMA_MODEL_TYPE_HANDLE Schema_GetModelByIndex(SCHEMA_HANDLE schemaHandle, size_t index)
+{
+    SCHEMA_MODEL_TYPE_HANDLE result;
+    SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
+
+    /* Codes_SRS_SCHEMA_99_128: [Schema_GetModelByIndex shall return NULL if the index specified is outside the valid range or if schemaHandle argument is NULL.] */
+    /* Codes_SRS_SCHEMA_99_127: [The index argument is zero based, and the order in which models were added shall be the index in which they will be retrieved.] */
+    if ((schemaHandle == NULL) ||
+        (index >= schema->ModelTypeCount))
+    {
+        result = NULL;
+        LogError("(Error code: %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
+    }
+    else
+    {
+
+        /* Codes_SRS_SCHEMA_99_126: [Schema_GetModelByIndex shall return a non-NULL SCHEMA_MODEL_TYPE_HANDLE corresponding to the model identified by schemaHandle and matching the index number provided by the index argument.] */
+        /* Codes_SRS_SCHEMA_99_127: [The index argument is zero based, and the order in which models were added shall be the index in which they will be retrieved.] */
+        result = schema->ModelTypes[index];
+    }
+    return result;
+}
+
+/*Codes_SRS_SCHEMA_99_160: [Schema_GetModelName shall return the name of the model identified by modelTypeHandle. If the name cannot be retrieved, then NULL shall be returned.]*/
+const char* Schema_GetModelName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle)
+{
+    const char* result;
+    if (modelTypeHandle == NULL)
+    {
+        result = NULL;
+    }
+    else
+    {
+        SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+        result = modelType->Name;
+    }
+    return result;
+}
+
+/*Codes_SRS_SCHEMA_99_163: [Schema_AddModelModel shall insert an existing model, identified by the handle modelType, into the existing model identified by modelTypeHandle under a property having the name propertyName.]*/
+SCHEMA_RESULT Schema_AddModelModel(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName, SCHEMA_MODEL_TYPE_HANDLE modelType, size_t offset, pfOnDesiredProperty onDesiredProperty)
+{
+    SCHEMA_RESULT result;
+    /*Codes_SRS_SCHEMA_99_165: [If any of the parameters is NULL then Schema_AddModelModel shall return SCHEMA_INVALID_ARG.]*/
+    if (
+        (modelTypeHandle == NULL) ||
+        (propertyName == NULL) ||
+        (modelType == NULL)
+        )
+    {
+        result = SCHEMA_INVALID_ARG;
+        LogError("(Error code: %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
+    }
+    else
+    {
+        SCHEMA_MODEL_TYPE_HANDLE_DATA* parentModel = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+        MODEL_IN_MODEL temp;
+        temp.modelHandle = modelType;
+        temp.offset = offset;
+        temp.onDesiredProperty = onDesiredProperty;
+        if (mallocAndStrcpy_s((char**)&(temp.propertyName), propertyName) != 0)
+        {
+            result = SCHEMA_ERROR;
+            LogError("(Error code: %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+        }
+        else if (VECTOR_push_back(parentModel->models, &temp, 1) != 0)
+        {
+            /*Codes_SRS_SCHEMA_99_174: [The function shall return SCHEMA_ERROR if any other error occurs.]*/
+            free((void*)temp.propertyName);
+            result = SCHEMA_ERROR;
+            LogError("(Error code: %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+        }
+        else
+        {
+            /*Codes_SRS_SCHEMA_99_164: [If the function succeeds, then the return value shall be SCHEMA_OK.]*/
+
+            result = SCHEMA_OK;
+        }
+    }
+    return result;
+}
+
+
+SCHEMA_RESULT Schema_GetModelModelCount(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t* modelCount)
+{
+    SCHEMA_RESULT result;
+    /*Codes_SRS_SCHEMA_99_169: [If any of the parameters is NULL, then the function shall return SCHEMA_INVALID_ARG.]*/
+    if (
+        (modelTypeHandle == NULL) ||
+        (modelCount == NULL)
+        )
+    {
+        result = SCHEMA_INVALID_ARG;
+        LogError("(Error code: %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
+    }
+    else
+    {
+        SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+        /*Codes_SRS_SCHEMA_99_167: [Schema_GetModelModelCount shall return in parameter modelCount the number of models inserted in the model identified by parameter modelTypeHandle.]*/
+        *modelCount = VECTOR_size(model->models);
+        /*SRS_SCHEMA_99_168: [If the function succeeds, it shall return SCHEMA_OK.]*/
+        result = SCHEMA_OK;
+    }
+    return result;
+}
+
+static bool matchModelName(const void* element, const void* value)
+{
+    MODEL_IN_MODEL* decodedElement = (MODEL_IN_MODEL*)element;
+    const char* name = (const char*)value;
+    return (strcmp(decodedElement->propertyName, name) == 0);
+}
+
+SCHEMA_MODEL_TYPE_HANDLE Schema_GetModelModelByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName)
+{
+    SCHEMA_MODEL_TYPE_HANDLE result;
+    if (
+        (modelTypeHandle == NULL) ||
+        (propertyName == NULL)
+        )
+    {
+        /*Codes_SRS_SCHEMA_99_171: [If Schema_GetModelModelByName is unable to provide the handle it shall return NULL.]*/
+        result = NULL;
+        LogError("error SCHEMA_INVALID_ARG");
+    }
+    else
+    {
+        SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+        /*Codes_SRS_SCHEMA_99_170: [Schema_GetModelModelByName shall return a handle to the model identified by the property with the name propertyName in the model identified by the handle modelTypeHandle.]*/
+        /*Codes_SRS_SCHEMA_99_171: [If Schema_GetModelModelByName is unable to provide the handle it shall return NULL.]*/
+        void* temp = VECTOR_find_if(model->models, matchModelName, propertyName);
+        if (temp == NULL)
+        {
+            LogError("specified propertyName not found (%s)", propertyName);
+            result = NULL;
+        }
+        else
+        {
+            result = ((MODEL_IN_MODEL*)temp)->modelHandle;
+        }
+    }
+    return result;
+}
+
+size_t Schema_GetModelModelByName_Offset(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName)
+{
+    size_t result;
+    /*Codes_SRS_SCHEMA_02_053: [ If modelTypeHandle is NULL then Schema_GetModelModelByName_Offset shall fail and return 0. ]*/
+    /*Codes_SRS_SCHEMA_02_054: [ If propertyName is NULL then Schema_GetModelModelByName_Offset shall fail and return 0. ]*/
+    if (
+        (modelTypeHandle == NULL) ||
+        (propertyName == NULL)
+        )
+    {
+        /*Codes_SRS_SCHEMA_99_171: [If Schema_GetModelModelByName is unable to provide the handle it shall return NULL.]*/
+        result = 0;
+        LogError("error SCHEMA_INVALID_ARG");
+    }
+    else
+    {
+        SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+        /*Codes_SRS_SCHEMA_02_056: [ If propertyName is not a model then Schema_GetModelModelByName_Offset shall fail and return 0. ]*/
+        void* temp = VECTOR_find_if(model->models, matchModelName, propertyName);
+        if (temp == NULL)
+        {
+            LogError("specified propertyName not found (%s)", propertyName);
+            result = 0;
+        }
+        else
+        {
+            /*Codes_SRS_SCHEMA_02_055: [ Otherwise Schema_GetModelModelByName_Offset shall succeed and return the offset. ]*/
+            result = ((MODEL_IN_MODEL*)temp)->offset;
+        }
+    }
+    return result;
+}
+
+pfOnDesiredProperty Schema_GetModelModelByName_OnDesiredProperty(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName)
+{
+    pfOnDesiredProperty result;
+    /*Codes_SRS_SCHEMA_02_086: [ If modelTypeHandle is NULL then Schema_GetModelModelByName_OnDesiredProperty shall return NULL. ]*/
+    /*Codes_SRS_SCHEMA_02_087: [ If propertyName is NULL then Schema_GetModelModelByName_OnDesiredProperty shall return NULL. ]*/
+    if (
+        (modelTypeHandle == NULL) ||
+        (propertyName == NULL)
+        )
+    {
+        result = NULL;
+        LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* propertyName=%p",modelTypeHandle, propertyName);
+    }
+    else
+    {
+        SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+        void* temp = VECTOR_find_if(model->models, matchModelName, propertyName);
+        if (temp == NULL)
+        {
+            LogError("specified propertyName not found (%s)", propertyName);
+            result = NULL;
+        }
+        else
+        {
+            /*Codes_SRS_SCHEMA_02_089: [ Otherwise Schema_GetModelModelByName_OnDesiredProperty shall return the desired property callback. ]*/
+            result = ((MODEL_IN_MODEL*)temp)->onDesiredProperty;
+        }
+    }
+    return result;
+
+}
+
+size_t Schema_GetModelModelByIndex_Offset(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index)
+{
+    size_t result;
+    /*Codes_SRS_SCHEMA_02_057: [ If modelTypeHandle is NULL then Schema_GetModelModelByIndex_Offset shall fail and return 0. ]*/
+    if (modelTypeHandle == NULL)
+    {
+        result = 0;
+        LogError("error SCHEMA_INVALID_ARG");
+    }
+    else
+    {
+        SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+        /*Codes_SRS_SCHEMA_02_058: [ If index is not valid then Schema_GetModelModelByIndex_Offset shall fail and return 0. ]*/
+        void* temp = VECTOR_element(model->models, index);
+        if (temp == 0)
+        {
+            LogError("specified index [out of bounds] (%lu)", (unsigned long)index);
+            result = 0;
+        }
+        else
+        {
+            /*Codes_SRS_SCHEMA_02_059: [ Otherwise Schema_GetModelModelByIndex_Offset shall succeed and return the offset. ]*/
+            result = ((MODEL_IN_MODEL*)temp)->offset;
+        }
+    }
+    return result;
+}
+
+SCHEMA_MODEL_TYPE_HANDLE Schema_GetModelModelyByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index)
+{
+    SCHEMA_MODEL_TYPE_HANDLE result;
+    if (modelTypeHandle == NULL)
+    {
+        /*Codes_SRS_SCHEMA_99_173: [Schema_GetModelModelyByIndex shall return NULL in the cases when it cannot provide the handle.]*/
+        result = NULL;
+        LogError("error SCHEMA_INVALID_ARG");
+    }
+    else
+    {
+        SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+        size_t nModelsInModel;
+        /*Codes_SRS_SCHEMA_99_172: [ Schema_GetModelModelyByIndex shall return a handle to the "index"th model inserted in the model identified by the parameter modelTypeHandle.]*/
+        /*Codes_SRS_SCHEMA_99_173: [Schema_GetModelModelyByIndex shall return NULL in the cases when it cannot provide the handle.]*/
+        nModelsInModel = VECTOR_size(model->models);
+        if (index < nModelsInModel)
+        {
+            result = ((MODEL_IN_MODEL*)VECTOR_element(model->models, index))->modelHandle;
+        }
+        else
+        {
+            LogError("attempted out of bounds access in array.");
+            result = NULL; /*out of bounds array access*/
+        }
+    }
+    return result;
+}
+
+const char* Schema_GetModelModelPropertyNameByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index)
+{
+    const char* result;
+    if (modelTypeHandle == NULL)
+    {
+        /*Codes_SRS_SCHEMA_99_176: [If Schema_GetModelModelPropertyNameByIndex cannot produce the property name, it shall return NULL.]*/
+        result = NULL;
+    }
+    else
+    {
+        SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+        size_t nModelsInModel;
+        /*Codes_SRS_SCHEMA_99_175: [Schema_GetModelModelPropertyNameByIndex shall return the name of the property for the "index"th model in the model identified by modelTypeHandle parameter.]*/
+        /*Codes_SRS_SCHEMA_99_176: [If Schema_GetModelModelPropertyNameByIndex cannot produce the property name, it shall return NULL.]*/
+        nModelsInModel = VECTOR_size(model->models);
+        if (index < nModelsInModel)
+        {
+            result = ((MODEL_IN_MODEL*)VECTOR_element(model->models, index))->propertyName;
+        }
+        else
+        {
+            LogError("attempted out of bounds access in array.");
+            result = NULL; /*out of bounds array access*/
+        }
+    }
+    return result;
+}
+
+bool Schema_ModelPropertyByPathExists(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyPath)
+{
+    bool result;
+
+    /* Codes_SRS_SCHEMA_99_180: [If any of the arguments are NULL, Schema_ModelPropertyByPathExists shall return false.] */
+    if ((modelTypeHandle == NULL) ||
+        (propertyPath == NULL))
+    {
+        LogError("error SCHEMA_INVALID_ARG");
+        result = false;
+    }
+    else
+    {
+        const char* slashPos;
+        result = false;
+
+        /* Codes_SRS_SCHEMA_99_182: [A single slash ('/') at the beginning of the path shall be ignored and the path shall still be valid.] */
+        if (*propertyPath == '/')
+        {
+            propertyPath++;
+        }
+
+        do
+        {
+            const char* endPos;
+            size_t i;
+            size_t modelCount;
+            SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+
+            /* Codes_SRS_SCHEMA_99_179: [The propertyPath shall be assumed to be in the format model1/model2/.../propertyName.] */
+            slashPos = strchr(propertyPath, '/');
+            endPos = slashPos;
+            if (endPos == NULL)
+            {
+                endPos = &propertyPath[strlen(propertyPath)];
+            }
+
+            /* get the child-model */
+            modelCount = VECTOR_size(modelType->models);
+            for (i = 0; i < modelCount; i++)
+            {
+                MODEL_IN_MODEL* childModel = (MODEL_IN_MODEL*)VECTOR_element(modelType->models, i);
+                if ((strncmp(childModel->propertyName, propertyPath, endPos - propertyPath) == 0) &&
+                    (strlen(childModel->propertyName) == (size_t)(endPos - propertyPath)))
+                {
+                    /* found */
+                    modelTypeHandle = childModel->modelHandle;
+                    break;
+                }
+            }
+
+            if (i < modelCount)
+            {
+                /* model found, check if there is more in the path */
+                if (slashPos == NULL)
+                {
+                    /* this is the last one, so this is the thing we were looking for */
+                    result = true;
+                    break;
+                }
+                else
+                {
+                    /* continue looking, there's more  */
+                    propertyPath = slashPos + 1;
+                }
+            }
+            else
+            {
+                /* no model found, let's see if this is a property */
+                /* Codes_SRS_SCHEMA_99_178: [The argument propertyPath shall be used to find the leaf property.] */
+                for (i = 0; i < modelType->PropertyCount; i++)
+                {
+                    SCHEMA_PROPERTY_HANDLE_DATA* property = (SCHEMA_PROPERTY_HANDLE_DATA*)modelType->Properties[i];
+                    if ((strncmp(property->PropertyName, propertyPath, endPos - propertyPath) == 0) &&
+                        (strlen(property->PropertyName) == (size_t)(endPos - propertyPath)))
+                    {
+                        /* found property */
+                        /* Codes_SRS_SCHEMA_99_177: [Schema_ModelPropertyByPathExists shall return true if a leaf property exists in the model modelTypeHandle.] */
+                        result = true;
+                        break;
+                    }
+                }
+
+                break;
+            }
+        } while (slashPos != NULL);
+    }
+
+    return result;
+}
+
+bool Schema_ModelReportedPropertyByPathExists(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* reportedPropertyPath)
+{
+    bool result;
+
+    /*Codes_SRS_SCHEMA_02_018: [ If argument modelTypeHandle is NULL then Schema_ModelReportedPropertyByPathExists shall fail and return false. ]*/
+    /*Codes_SRS_SCHEMA_02_019: [ If argument reportedPropertyPath is NULL then Schema_ModelReportedPropertyByPathExists shall fail and return false. ]*/
+    if ((modelTypeHandle == NULL) ||
+        (reportedPropertyPath == NULL))
+    {
+        LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* reportedPropertyPath=%s", modelTypeHandle, reportedPropertyPath);
+        result = false;
+    }
+    else
+    {
+        const char* slashPos;
+
+        /*Codes_SRS_SCHEMA_02_021: [ If the reported property cannot be found Schema_ModelReportedPropertyByPathExists shall fail and return false. ]*/
+        result = false;
+
+        /*Codes_SRS_SCHEMA_02_020: [ reportedPropertyPath shall be assumed to be in the format model1/model2/.../reportedPropertyName. ]*/
+        if (*reportedPropertyPath == '/')
+        {
+            reportedPropertyPath++;
+        }
+
+        do
+        {
+            const char* endPos;
+            size_t i;
+            size_t modelCount;
+            SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+
+            slashPos = strchr(reportedPropertyPath, '/');
+            endPos = slashPos;
+            if (endPos == NULL)
+            {
+                endPos = &reportedPropertyPath[strlen(reportedPropertyPath)];
+            }
+
+            modelCount = VECTOR_size(modelType->models);
+            for (i = 0; i < modelCount; i++)
+            {
+                MODEL_IN_MODEL* childModel = (MODEL_IN_MODEL*)VECTOR_element(modelType->models, i);
+                if ((strncmp(childModel->propertyName, reportedPropertyPath, endPos - reportedPropertyPath) == 0) &&
+                    (strlen(childModel->propertyName) == (size_t)(endPos - reportedPropertyPath)))
+                {
+                    /* found */
+                    modelTypeHandle = childModel->modelHandle;
+                    break;
+                }
+            }
+
+            if (i < modelCount)
+            {
+                /* model found, check if there is more in the path */
+                if (slashPos == NULL)
+                {
+                    /*Codes_SRS_SCHEMA_02_022: [ If the path reportedPropertyPath points to a sub-model, Schema_ModelReportedPropertyByPathExists shall succeed and true. ]*/
+                    /* this is the last one, so this is the thing we were looking for */
+                    result = true;
+                    break;
+                }
+                else
+                {
+                    /* continue looking, there's more  */
+                    reportedPropertyPath = slashPos + 1;
+                }
+            }
+            else
+            {
+                /* no model found, let's see if this is a property */
+                result = (VECTOR_find_if(modelType->reportedProperties, reportedPropertyExists, reportedPropertyPath) != NULL);
+                if (!result)
+                {
+                    LogError("no such reported property \"%s\"", reportedPropertyPath);
+                }
+                break;
+            }
+        } while (slashPos != NULL);
+    }
+
+    return result;
+}
+
+static bool desiredPropertyExists(const void* element, const void* value)
+{
+    SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desiredProperty = *(SCHEMA_DESIRED_PROPERTY_HANDLE_DATA**)element;
+    return (strcmp(desiredProperty->desiredPropertyName, value) == 0);
+}
+
+SCHEMA_RESULT Schema_AddModelDesiredProperty(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* desiredPropertyName, const char* desiredPropertyType, pfDesiredPropertyFromAGENT_DATA_TYPE desiredPropertyFromAGENT_DATA_TYPE, pfDesiredPropertyInitialize desiredPropertyInitialize, pfDesiredPropertyDeinitialize desiredPropertyDeinitialize, size_t offset, pfOnDesiredProperty onDesiredProperty)
+{
+    SCHEMA_RESULT result;
+    /*Codes_SRS_SCHEMA_02_024: [ If modelTypeHandle is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
+    /*Codes_SRS_SCHEMA_02_025: [ If desiredPropertyName is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
+    /*Codes_SRS_SCHEMA_02_026: [ If desiredPropertyType is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
+    /*Codes_SRS_SCHEMA_02_048: [ If desiredPropertyFromAGENT_DATA_TYPE is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
+    /*Codes_SRS_SCHEMA_02_049: [ If desiredPropertyInitialize is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
+    /*Codes_SRS_SCHEMA_02_050: [ If desiredPropertyDeinitialize is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
+    if (
+        (modelTypeHandle == NULL) ||
+        (desiredPropertyName == NULL) ||
+        (desiredPropertyType == NULL) ||
+        (desiredPropertyFromAGENT_DATA_TYPE == NULL) ||
+        (desiredPropertyInitialize == NULL) ||
+        (desiredPropertyDeinitialize== NULL)
+        )
+    {
+        LogError("invalid arg SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* desiredPropertyName=%p, const char* desiredPropertyType=%p, pfDesiredPropertyFromAGENT_DATA_TYPE desiredPropertyFromAGENT_DATA_TYPE=%p, pfDesiredPropertyInitialize desiredPropertyInitialize=%p, pfDesiredPropertyDeinitialize desiredPropertyDeinitialize=%p, size_t offset=%lu",
+            modelTypeHandle, desiredPropertyName, desiredPropertyType, desiredPropertyFromAGENT_DATA_TYPE, desiredPropertyInitialize, desiredPropertyDeinitialize, (unsigned long)offset);
+        result = SCHEMA_INVALID_ARG;
+    }
+    else
+    {
+        SCHEMA_MODEL_TYPE_HANDLE_DATA* handleData = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+        /*Codes_SRS_SCHEMA_02_027: [ Schema_AddModelDesiredProperty shall add the desired property given by the name desiredPropertyName and the type desiredPropertyType to the collection of existing desired properties. ]*/
+        if (VECTOR_find_if(handleData->desiredProperties, desiredPropertyExists, desiredPropertyName) != NULL)
+        {
+            /*Codes_SRS_SCHEMA_02_047: [ If the desired property already exists, then Schema_AddModelDesiredProperty shall fail and return SCHEMA_DUPLICATE_ELEMENT. ]*/
+            LogError("unable to Schema_AddModelDesiredProperty because a desired property with the same name (%s) already exists", desiredPropertyName);
+            result = SCHEMA_DUPLICATE_ELEMENT;
+        }
+        else
+        {
+            SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desiredProperty = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)calloc(1, sizeof(SCHEMA_DESIRED_PROPERTY_HANDLE_DATA));
+            if (desiredProperty == NULL)
+            {
+                /*Codes_SRS_SCHEMA_02_028: [ If any failure occurs then Schema_AddModelDesiredProperty shall fail and return SCHEMA_ERROR. ]*/
+                LogError("failure in malloc");
+                result = SCHEMA_ERROR;
+            }
+            else
+            {
+                if (mallocAndStrcpy_s((char**)&desiredProperty->desiredPropertyName, desiredPropertyName) != 0)
+                {
+                    /*Codes_SRS_SCHEMA_02_028: [ If any failure occurs then Schema_AddModelDesiredProperty shall fail and return SCHEMA_ERROR. ]*/
+                    LogError("failure in mallocAndStrcpy_s");
+                    free(desiredProperty);
+                    result = SCHEMA_ERROR;
+                }
+                else
+                {
+                    if (mallocAndStrcpy_s((char**)&desiredProperty->desiredPropertyType, desiredPropertyType) != 0)
+                    {
+                        /*Codes_SRS_SCHEMA_02_028: [ If any failure occurs then Schema_AddModelDesiredProperty shall fail and return SCHEMA_ERROR. ]*/
+                        LogError("failure in mallocAndStrcpy_s");
+                        free((void*)desiredProperty->desiredPropertyName);
+                        free(desiredProperty);
+                        result = SCHEMA_ERROR;
+                    }
+                    else
+                    {
+                        if (VECTOR_push_back(handleData->desiredProperties, &desiredProperty, 1) != 0)
+                        {
+                            /*Codes_SRS_SCHEMA_02_028: [ If any failure occurs then Schema_AddModelDesiredProperty shall fail and return SCHEMA_ERROR. ]*/
+                            LogError("failure in VECTOR_push_back");
+                            free((void*)desiredProperty->desiredPropertyType);
+                            free((void*)desiredProperty->desiredPropertyName);
+                            free(desiredProperty);
+                            result = SCHEMA_ERROR;
+                        }
+                        else
+                        {
+                            /*Codes_SRS_SCHEMA_02_029: [ Otherwise, Schema_AddModelDesiredProperty shall succeed and return SCHEMA_OK. ]*/
+                            desiredProperty->desiredPropertyFromAGENT_DATA_TYPE = desiredPropertyFromAGENT_DATA_TYPE;
+                            desiredProperty->desiredPropertInitialize = desiredPropertyInitialize;
+                            desiredProperty->desiredPropertDeinitialize = desiredPropertyDeinitialize;
+                            desiredProperty->onDesiredProperty = onDesiredProperty; /*NULL is a perfectly fine value*/
+                            desiredProperty->offset = offset;
+                            result = SCHEMA_OK;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return result;
+}
+
+
+SCHEMA_RESULT Schema_GetModelDesiredPropertyCount(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t* desiredPropertyCount)
+{
+    SCHEMA_RESULT result;
+    /*Codes_SRS_SCHEMA_02_030: [ If modelTypeHandle is NULL then Schema_GetModelDesiredPropertyCount shall fail and return SCHEMA_INVALID_ARG. ]*/
+    /*Codes_SRS_SCHEMA_02_031: [ If desiredPropertyCount is NULL then Schema_GetModelDesiredPropertyCount shall fail and return SCHEMA_INVALID_ARG. ]*/
+    if (
+        (modelTypeHandle == NULL) ||
+        (desiredPropertyCount == NULL)
+        )
+    {
+        LogError("invalid arg: SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, size_t* desiredPropertyCount=%p", modelTypeHandle, desiredPropertyCount);
+        result = SCHEMA_INVALID_ARG;
+    }
+    else
+    {
+        /*Codes_SRS_SCHEMA_02_032: [ Otherwise, Schema_GetModelDesiredPropertyCount shall succeed and write in desiredPropertyCount the existing number of desired properties. ]*/
+        SCHEMA_MODEL_TYPE_HANDLE_DATA* handleData = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+        *desiredPropertyCount = VECTOR_size(handleData->desiredProperties);
+        result = SCHEMA_OK;
+    }
+    return result;
+}
+
+SCHEMA_DESIRED_PROPERTY_HANDLE Schema_GetModelDesiredPropertyByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* desiredPropertyName)
+{
+    SCHEMA_DESIRED_PROPERTY_HANDLE result;
+    /*Codes_SRS_SCHEMA_02_034: [ If modelTypeHandle is NULL then Schema_GetModelDesiredPropertyByName shall fail and return NULL. ]*/
+    /*Codes_SRS_SCHEMA_02_035: [ If desiredPropertyName is NULL then Schema_GetModelDesiredPropertyByName shall fail and return NULL. ]*/
+    if (
+        (modelTypeHandle == NULL) ||
+        (desiredPropertyName == NULL)
+        )
+    {
+        LogError("invalid arg SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* desiredPropertyName=%p", modelTypeHandle, desiredPropertyName);
+        result = NULL;
+    }
+    else
+    {
+        /*Codes_SRS_SCHEMA_02_036: [ If a desired property having the name desiredPropertyName exists then Schema_GetModelDesiredPropertyByName shall succeed and return a non-NULL value. ]*/
+        /*Codes_SRS_SCHEMA_02_037: [ Otherwise, Schema_GetModelDesiredPropertyByName shall fail and return NULL. ]*/
+        SCHEMA_MODEL_TYPE_HANDLE_DATA* handleData = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+        SCHEMA_DESIRED_PROPERTY_HANDLE* temp = VECTOR_find_if(handleData->desiredProperties, desiredPropertyExists, desiredPropertyName);
+        if (temp == NULL)
+        {
+            LogError("no such desired property by name %s", desiredPropertyName);
+            result = NULL;
+        }
+        else
+        {
+            result = *temp;
+        }
+    }
+    return result;
+}
+
+SCHEMA_DESIRED_PROPERTY_HANDLE Schema_GetModelDesiredPropertyByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index)
+{
+    SCHEMA_DESIRED_PROPERTY_HANDLE result;
+    /*Codes_SRS_SCHEMA_02_038: [ If modelTypeHandle is NULL then Schema_GetModelDesiredPropertyByIndex shall fail and return NULL. ]*/
+    if (modelTypeHandle == NULL)
+    {
+        LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, size_t index=%lu", modelTypeHandle, (unsigned long)index);
+        result = NULL;
+    }
+    else
+    {
+        SCHEMA_MODEL_TYPE_HANDLE_DATA* handleData = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+        /*Codes_SRS_SCHEMA_02_039: [ If index is outside the range for existing indexes of desire properties, then Schema_GetModelDesiredPropertyByIndex shall fail and return NULL. ]*/
+        /*Codes_SRS_SCHEMA_02_040: [ Otherwise, Schema_GetModelDesiredPropertyByIndex shall succeed and return a non-NULL value. ]*/
+        SCHEMA_DESIRED_PROPERTY_HANDLE* temp = VECTOR_element(handleData->desiredProperties, index);
+        if (temp == NULL)
+        {
+            LogError("VECTOR_element produced NULL (likely out of bounds index)");
+            result = NULL;
+        }
+        else
+        {
+            result = *temp;
+        }
+    }
+    return result;
+}
+
+bool Schema_ModelDesiredPropertyByPathExists(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* desiredPropertyPath)
+{
+    bool result;
+    /*Codes_SRS_SCHEMA_02_041: [ If modelTypeHandle is NULL then Schema_ModelDesiredPropertyByPathExists shall fail and return false. ]*/
+    /*Codes_SRS_SCHEMA_02_042: [ If desiredPropertyPath is NULL then Schema_ModelDesiredPropertyByPathExists shall fail and return false. ]*/
+    if (
+        (modelTypeHandle == NULL) ||
+        (desiredPropertyPath == NULL)
+        )
+    {
+        LogError("invalid arg SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* desiredPropertyPath=%p", modelTypeHandle, desiredPropertyPath);
+        result = false;
+    }
+    else
+    {
+        const char* slashPos;
+
+        /*Codes_SRS_SCHEMA_02_044: [ If the desired property cannot be found Schema_ModelDesiredPropertyByPathExists shall fail and return false. ]*/
+        result = false;
+
+        /*Codes_SRS_SCHEMA_02_043: [ desiredPropertyPath shall be assumed to be in the format model1/model2/.../desiredPropertyName. ]*/
+        if (*desiredPropertyPath == '/')
+        {
+            desiredPropertyPath++;
+        }
+
+        do
+        {
+            const char* endPos;
+            size_t i;
+            size_t modelCount;
+            SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+
+            slashPos = strchr(desiredPropertyPath, '/');
+            endPos = slashPos;
+            if (endPos == NULL)
+            {
+                endPos = &desiredPropertyPath[strlen(desiredPropertyPath)];
+            }
+
+            modelCount = VECTOR_size(modelType->models);
+            for (i = 0; i < modelCount; i++)
+            {
+                MODEL_IN_MODEL* childModel = (MODEL_IN_MODEL*)VECTOR_element(modelType->models, i);
+                if ((strncmp(childModel->propertyName, desiredPropertyPath, endPos - desiredPropertyPath) == 0) &&
+                    (strlen(childModel->propertyName) == (size_t)(endPos - desiredPropertyPath)))
+                {
+                    /* found */
+                    modelTypeHandle = childModel->modelHandle;
+                    break;
+                }
+            }
+
+            if (i < modelCount)
+            {
+                /* model found, check if there is more in the path */
+                if (slashPos == NULL)
+                {
+                    /*Codes_SRS_SCHEMA_02_045: [ If the path desiredPropertyPath points to a sub-model, Schema_ModelDesiredPropertyByPathExists shall succeed and true. ]*/
+                    /* this is the last one, so this is the thing we were looking for */
+                    result = true;
+                    break;
+                }
+                else
+                {
+                    /* continue looking, there's more  */
+                    desiredPropertyPath = slashPos + 1;
+                }
+            }
+            else
+            {
+                /* no model found, let's see if this is a property */
+                result = (VECTOR_find_if(modelType->desiredProperties, desiredPropertyExists, desiredPropertyPath) != NULL);
+                if (!result)
+                {
+                    LogError("no such desired property \"%s\"", desiredPropertyPath);
+                }
+                break;
+            }
+        } while (slashPos != NULL);
+    }
+    return result;
+}
+
+const char* Schema_GetModelDesiredPropertyType(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle)
+{
+    const char* result;
+    /*Codes_SRS_SCHEMA_02_062: [ If desiredPropertyHandle is NULL then Schema_GetModelDesiredPropertyType shall fail and return NULL. ]*/
+    if (desiredPropertyHandle == NULL)
+    {
+        LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle);
+        result = NULL;
+    }
+    else
+    {
+        /*Codes_SRS_SCHEMA_02_063: [ Otherwise, Schema_GetModelDesiredPropertyType shall return the type of the desired property. ]*/
+        SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desirePropertyHandleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle;
+        result = desirePropertyHandleData->desiredPropertyType;
+    }
+    return result;
+}
+
+pfDesiredPropertyFromAGENT_DATA_TYPE Schema_GetModelDesiredProperty_pfDesiredPropertyFromAGENT_DATA_TYPE(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle)
+{
+    pfDesiredPropertyFromAGENT_DATA_TYPE result;
+    if (desiredPropertyHandle == NULL)
+    {
+        LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle);
+        result = NULL;
+    }
+    else
+    {
+        SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desirePropertyHandleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle;
+        result = desirePropertyHandleData->desiredPropertyFromAGENT_DATA_TYPE;
+    }
+    return result;
+}
+
+pfOnDesiredProperty Schema_GetModelDesiredProperty_pfOnDesiredProperty(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle)
+{
+    pfOnDesiredProperty result;
+    /*Codes_SRS_SCHEMA_02_084: [ If desiredPropertyHandle is NULL then Schema_GetModelDesiredProperty_pfOnDesiredProperty shall return NULL. ]*/
+    if (desiredPropertyHandle == NULL)
+    {
+        LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle);
+        result = NULL;
+    }
+    else
+    {
+        /*Codes_SRS_SCHEMA_02_085: [ Otherwise Schema_GetModelDesiredProperty_pfOnDesiredProperty shall return the saved desired property callback. ]*/
+        SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desirePropertyHandleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle;
+        result = desirePropertyHandleData->onDesiredProperty;
+    }
+    return result;
+}
+
+size_t Schema_GetModelDesiredProperty_offset(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle)
+{
+    size_t result;
+    /*Codes_SRS_SCHEMA_02_060: [ If desiredPropertyHandle is NULL then Schema_GetModelDesiredProperty_offset shall fail and return 0. ]*/
+    if (desiredPropertyHandle == NULL)
+    {
+        LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle);
+        result = 0;
+    }
+    else
+    {
+        /*Codes_SRS_SCHEMA_02_061: [ Otherwise Schema_GetModelDesiredProperty_offset shall succeed and return the offset. ]*/
+        SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desirePropertyHandleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle;
+        result = desirePropertyHandleData->offset;
+    }
+    return result;
+}
+
+static bool modelInModelExists(const void* element, const void* value)
+{
+    MODEL_IN_MODEL* modelInModel = (MODEL_IN_MODEL*)element;
+    return (strcmp(modelInModel->propertyName, value) == 0);
+}
+
+SCHEMA_MODEL_ELEMENT Schema_GetModelElementByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* elementName)
+{
+    SCHEMA_MODEL_ELEMENT result;
+    /*Codes_SRS_SCHEMA_02_076: [ If modelTypeHandle is NULL then Schema_GetModelElementByName shall fail and set SCHEMA_MODEL_ELEMENT.elementType to SCHEMA_SEARCH_INVALID_ARG. ]*/
+    /*Codes_SRS_SCHEMA_02_077: [ If elementName is NULL then Schema_GetModelElementByName shall fail and set SCHEMA_MODEL_ELEMENT.elementType to SCHEMA_SEARCH_INVALID_ARG. ]*/
+    if (
+        (modelTypeHandle == NULL) ||
+        (elementName == NULL)
+        )
+    {
+        LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* elementName=%p", modelTypeHandle, elementName);
+        result.elementType = SCHEMA_SEARCH_INVALID_ARG;
+    }
+    else
+    {
+        SCHEMA_MODEL_TYPE_HANDLE_DATA* handleData = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
+
+        SCHEMA_DESIRED_PROPERTY_HANDLE* desiredPropertyHandle = VECTOR_find_if(handleData->desiredProperties, desiredPropertyExists, elementName);
+        if (desiredPropertyHandle != NULL)
+        {
+            /*Codes_SRS_SCHEMA_02_080: [ If elementName is a desired property then Schema_GetModelElementByName shall succeed and set SCHEMA_MODEL_ELEMENT.elementType to SCHEMA_DESIRED_PROPERTY and SCHEMA_MODEL_ELEMENT.elementHandle.desiredPropertyHandle to the handle of the desired property. ]*/
+            result.elementType = SCHEMA_DESIRED_PROPERTY;
+            result.elementHandle.desiredPropertyHandle = *desiredPropertyHandle;
+        }
+        else
+        {
+            size_t nProcessedProperties = 0;
+            SCHEMA_PROPERTY_HANDLE_DATA* property = NULL;
+            for (size_t i = 0; i < handleData->PropertyCount;i++)
+            {
+                property = (SCHEMA_PROPERTY_HANDLE_DATA*)(handleData->Properties[i]);
+                if (strcmp(property->PropertyName, elementName) == 0)
+                {
+                    i = handleData->PropertyCount; /*found it*/
+                }
+                else
+                {
+                    nProcessedProperties++;
+                }
+            }
+
+            if (nProcessedProperties < handleData->PropertyCount)
+            {
+                /*Codes_SRS_SCHEMA_02_078: [ If elementName is a property then Schema_GetModelElementByName shall succeed and set SCHEMA_MODEL_ELEMENT.elementType to SCHEMA_PROPERTY and SCHEMA_MODEL_ELEMENT.elementHandle.propertyHandle to the handle of the property. ]*/
+                result.elementType = SCHEMA_PROPERTY;
+                result.elementHandle.propertyHandle = property;
+            }
+            else
+            {
+
+                SCHEMA_REPORTED_PROPERTY_HANDLE* reportedPropertyHandle = VECTOR_find_if(handleData->reportedProperties, reportedPropertyExists, elementName);
+                if (reportedPropertyHandle != NULL)
+                {
+                    /*Codes_SRS_SCHEMA_02_079: [ If elementName is a reported property then Schema_GetModelElementByName shall succeed and set SCHEMA_MODEL_ELEMENT.elementType to SCHEMA_REPORTED_PROPERTY and SCHEMA_MODEL_ELEMENT.elementHandle.reportedPropertyHandle to the handle of the reported property. ]*/
+                    result.elementType = SCHEMA_REPORTED_PROPERTY;
+                    result.elementHandle.reportedPropertyHandle = *reportedPropertyHandle;
+                }
+                else
+                {
+
+                    size_t nProcessedActions = 0;
+                    SCHEMA_ACTION_HANDLE_DATA* actionHandleData = NULL;
+                    for (size_t i = 0;i < handleData->ActionCount; i++)
+                    {
+                        actionHandleData = (SCHEMA_ACTION_HANDLE_DATA*)(handleData->Actions[i]);
+                        if (strcmp(actionHandleData->ActionName, elementName) == 0)
+                        {
+                            i = handleData->ActionCount; /*get out quickly*/
+                        }
+                        else
+                        {
+                            nProcessedActions++;
+                        }
+                    }
+
+                    if (nProcessedActions < handleData->ActionCount)
+                    {
+                        /*Codes_SRS_SCHEMA_02_081: [ If elementName is a model action then Schema_GetModelElementByName shall succeed and set SCHEMA_MODEL_ELEMENT.elementType to SCHEMA_MODEL_ACTION and SCHEMA_MODEL_ELEMENT.elementHandle.actionHandle to the handle of the action. ]*/
+                        result.elementType = SCHEMA_MODEL_ACTION;
+                        result.elementHandle.actionHandle = actionHandleData;
+                    }
+                    else
+                    {
+                        MODEL_IN_MODEL* modelInModel = VECTOR_find_if(handleData->models, modelInModelExists, elementName);
+                        if (modelInModel != NULL)
+                        {
+                            /*Codes_SRS_SCHEMA_02_082: [ If elementName is a model in model then Schema_GetModelElementByName shall succeed and set SCHEMA_MODEL_ELEMENT.elementType to SCHEMA_MODEL_IN_MODEL and SCHEMA_MODEL_ELEMENT.elementHandle.modelHandle to the handle of the model. ]*/
+                            result.elementType = SCHEMA_MODEL_IN_MODEL;
+                            result.elementHandle.modelHandle = modelInModel->modelHandle;
+                        }
+                        else
+                        {
+                            /*Codes_SRS_SCHEMA_02_083: [ Otherwise Schema_GetModelElementByName shall fail and set SCHEMA_MODEL_ELEMENT.elementType to SCHEMA_NOT_FOUND. ]*/
+                            result.elementType = SCHEMA_NOT_FOUND;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return result;
+}
+
+pfDesiredPropertyDeinitialize Schema_GetModelDesiredProperty_pfDesiredPropertyDeinitialize(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle)
+{
+    pfDesiredPropertyDeinitialize result;
+    /*Ccodes_SRS_SCHEMA_02_064: [ If desiredPropertyHandle is NULL then Schema_GetModelDesiredProperty_pfDesiredPropertyDeinitialize shall fail and return NULL. ]*/
+    if (desiredPropertyHandle == NULL)
+    {
+        LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle);
+        result = NULL;
+    }
+    else
+    {
+        /*Codes_SRS_SCHEMA_02_065: [ Otherwise Schema_GetModelDesiredProperty_pfDesiredPropertyDeinitialize shall return a non-NULL function pointer. ]*/
+        SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* handleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle;
+        result = handleData->desiredPropertDeinitialize;
+    }
+    return result;
+}
+
+pfDesiredPropertyInitialize Schema_GetModelDesiredProperty_pfDesiredPropertyInitialize(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle)
+{
+    pfDesiredPropertyInitialize result;
+    /*Codes_SRS_SCHEMA_02_066: [ If desiredPropertyHandle is NULL then Schema_GetModelDesiredProperty_pfDesiredPropertyInitialize shall fail and return NULL. ]*/
+    if (desiredPropertyHandle == NULL)
+    {
+        LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle);
+        result = NULL;
+    }
+    else
+    {
+        /*Codes_SRS_SCHEMA_02_067: [ Otherwise Schema_GetModelDesiredProperty_pfDesiredPropertyInitialize shall return a non-NULL function pointer. ]*/
+        SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* handleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle;
+        result = handleData->desiredPropertInitialize;
+    }
+    return result;
+}
+
+static bool SchemaHasModel(const SCHEMA_HANDLE* schemaHandle, const char* modelName)
+{
+    return (Schema_GetModelByName(*schemaHandle, modelName) != NULL);
+}
+
+
+SCHEMA_HANDLE Schema_GetSchemaForModel(const char* modelName)
+{
+    SCHEMA_HANDLE result;
+    /*Codes_SRS_SCHEMA_02_093: [ If modelName is NULL then Schema_GetSchemaForModel shall fail and return NULL. ]*/
+    if (modelName == NULL)
+    {
+        LogError("invalid arg const char* modelName=%p", modelName);
+        result = NULL;
+    }
+    else
+    {
+        /*Codes_SRS_SCHEMA_02_094: [ Schema_GetSchemaForModel shall find the SCHEMA_HANDLE that contains a model by name modelName and if found, succeed and return that. ]*/
+        SCHEMA_HANDLE* temp = VECTOR_find_if(g_schemas, (PREDICATE_FUNCTION)SchemaHasModel, modelName);
+
+        if (temp == NULL)
+        {
+            /*Codes_SRS_SCHEMA_02_095: [ If the model is not found in any schema, then Schema_GetSchemaForModel shall fail and return NULL. ]*/
+            LogError("unable to find a schema that has a model named %s", modelName);
+            result = NULL;
+        }
+        else
+        {
+            /*Codes_SRS_SCHEMA_02_094: [ Schema_GetSchemaForModel shall find the SCHEMA_HANDLE that contains a model by name modelName and if found, succeed and return that. ]*/
+            result = *temp;
+        }
+    }
+
+    return result;
+}
+
+void* Schema_GetMetadata(SCHEMA_HANDLE schemaHandle)
+{
+    void* result;
+    /*Codes_SRS_SCHEMA_02_091: [ If schemaHandle is NULL then Schema_GetMetadata shall fail and return NULL. ]*/
+    if (schemaHandle == NULL)
+    {
+        LogError("invalid arg SCHEMA_HANDLE schemaHandle=%p", schemaHandle);
+        result = NULL;
+    }
+    else
+    {
+        /*Codes_SRS_SCHEMA_02_092: [ Otherwise, Schema_GetMetadata shall succeed and return the saved metadata pointer. ]*/
+        result = ((SCHEMA_HANDLE_DATA*)schemaHandle)->metadata;
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/schemalib.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/schemalib.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/schemalib.c	(revision 453)
@@ -0,0 +1,94 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include "azure_c_shared_utility/gballoc.h"
+
+#include "schemalib.h"
+#include "codefirst.h"
+#include "schema.h"
+#include "datamarshaller.h"
+#include "datapublisher.h"
+#include <stddef.h>
+#include "azure_c_shared_utility/xlogging.h"
+#include "iotdevice.h"
+
+#define DEFAULT_CONTAINER_NAME  "Container"
+
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(SERIALIZER_RESULT, SERIALIZER_RESULT_VALUES);
+
+typedef enum AGENT_STATE_TAG
+{
+    AGENT_NOT_INITIALIZED,
+    AGENT_INITIALIZED
+} AGENT_STATE;
+
+static AGENT_STATE g_AgentState = AGENT_NOT_INITIALIZED;
+
+SERIALIZER_RESULT serializer_init(const char* overrideSchemaNamespace)
+{
+    SERIALIZER_RESULT result;
+
+    /* Codes_SRS_SCHEMALIB_99_074:[serializer_init when already initialized shall return SERIALIZER_ALREADY_INIT.] */
+    if (g_AgentState != AGENT_NOT_INITIALIZED)
+    {
+        result = SERIALIZER_ALREADY_INIT;
+        LogError("(result = %s)", MU_ENUM_TO_STRING(SERIALIZER_RESULT, result));
+    }
+    else
+    {
+        /* Codes_SRS_SCHEMALIB_99_006:[ Initialize CodeFirst by a call to CodeFirst_Init.] */
+        /* Codes_SRS_SCHEMALIB_99_076:[serializer_init shall pass the value of overrideSchemaNamespace argument to CodeFirst_Init.] */
+        if (CodeFirst_Init(overrideSchemaNamespace) != CODEFIRST_OK)
+        {
+            /* Codes_SRS_SCHEMALIB_99_007:[ On error SERIALIZER_CODEFIRST_INIT_FAILED shall be returned.] */
+            result = SERIALIZER_CODEFIRST_INIT_FAILED;
+            LogError("(result = %s)", MU_ENUM_TO_STRING(SERIALIZER_RESULT, result));
+        }
+        else
+        {
+            /* Codes_SRS_SCHEMALIB_99_075:[When an serializer_init call fails for any reason the previous initialization state shall be preserved. The initialized state shall only be changed on a succesfull Init.] */
+            g_AgentState = AGENT_INITIALIZED;
+
+            /* Codes_SRS_SCHEMALIB_99_073:[On success serializer_init shall return SERIALIZER_OK.] */
+            result = SERIALIZER_OK;
+        }
+    }
+
+    return result;
+}
+
+void serializer_deinit(void)
+{
+    /* Codes_SRS_SCHEMALIB_99_025:[ serializer_deinit shall de-initialize all modules initialized by serializer_init.] */
+    if (g_AgentState == AGENT_INITIALIZED)
+    {
+        CodeFirst_Deinit();
+    }
+
+    /* Codes_SRS_SCHEMALIB_99_026:[ A subsequent call to serializer_start shall succeed.] */
+    g_AgentState = AGENT_NOT_INITIALIZED;
+}
+
+SERIALIZER_RESULT serializer_setconfig(SERIALIZER_CONFIG which, void* value)
+{
+    SERIALIZER_RESULT result;
+
+    /* Codes_SRS_SCHEMALIB_99_137:[ If the value argument is NULL, serializer_setconfig shall return SERIALIZER_INVALID_ARG.] */
+    if (value == NULL)
+    {
+        result = SERIALIZER_INVALID_ARG;
+    }
+    /* Codes_SRS_SCHEMALIB_99_142:[ When the which argument is SerializeDelayedBufferMaxSize, serializer_setconfig shall invoke DataPublisher_SetMaxBufferSize with the dereferenced value argument, and shall return SERIALIZER_OK.] */
+    else if (which == SerializeDelayedBufferMaxSize)
+    {
+        DataPublisher_SetMaxBufferSize(*(size_t*)value);
+        result = SERIALIZER_OK;
+    }
+    /* Codes_SRS_SCHEMALIB_99_138:[ If the which argument is not one of the declared members of the SERIALIZER_CONFIG enum, serializer_setconfig shall return SERIALIZER_INVALID_ARG.] */
+    else
+    {
+        result = SERIALIZER_INVALID_ARG;
+    }
+
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/schemaserializer.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/schemaserializer.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/schemaserializer.c	(revision 453)
@@ -0,0 +1,174 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "azure_c_shared_utility/gballoc.h"
+
+#include <stddef.h>
+#include "schemaserializer.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_macro_utils/macro_utils.h"
+
+MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(SCHEMA_SERIALIZER_RESULT, SCHEMA_SERIALIZER_RESULT_VALUES);
+
+#define LOG_SCHEMA_SERIALIZER_ERROR(result) LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_SERIALIZER_RESULT, (result)))
+
+static const char* ConvertType(const char* sourceType)
+{
+    /* Codes_SRS_SCHEMA_SERIALIZER_01_016: ["ascii_char_ptr" shall be translated to "string".] */
+    if (strcmp(sourceType, "ascii_char_ptr") == 0)
+    {
+        return "string";
+    }
+    else
+    {
+        /* Codes_SRS_SCHEMA_SERIALIZER_01_017: [All other types shall be kept as they are.] */
+        return sourceType;
+    }
+}
+
+/* Codes_SRS_SCHEMA_SERIALIZER_01_001: [SchemaSerializer_SerializeCommandMetadata shall serialize a specific model to a string using JSON as format.] */
+SCHEMA_SERIALIZER_RESULT SchemaSerializer_SerializeCommandMetadata(SCHEMA_MODEL_TYPE_HANDLE modelHandle, STRING_HANDLE schemaText)
+{
+    SCHEMA_SERIALIZER_RESULT result;
+
+    /* Codes_SRS_SCHEMA_SERIALIZER_01_013: [If the modelHandle argument is NULL, SchemaSerializer_SerializeCommandMetadata shall return SCHEMA_SERIALIZER_INVALID_ARG.] */
+    if ((modelHandle == NULL) ||
+        /* Codes_SRS_SCHEMA_SERIALIZER_01_014: [If the schemaText argument is NULL, SchemaSerializer_SerializeCommandMetadata shall return SCHEMA_SERIALIZER_INVALID_ARG.] */
+        (schemaText == NULL))
+    {
+        result = SCHEMA_SERIALIZER_INVALID_ARG;
+        LogError("(result = %s), modelHandle = %p, schemaText = %p", MU_ENUM_TO_STRING(SCHEMA_SERIALIZER_RESULT, result), modelHandle, schemaText);
+    }
+    else
+    {
+        size_t commandCount;
+
+        /* Codes_SRS_SCHEMA_SERIALIZER_01_002: [Only commands shall be serialized, the properties of a model shall be ignored.] */
+
+        /* Codes_SRS_SCHEMA_SERIALIZER_01_003: [The output JSON shall have an array, where each array element shall represent a command.] */
+        /* Codes_SRS_SCHEMA_SERIALIZER_01_011: [The JSON text shall be built into the string indicated by the schemaText argument by using String APIs.] */
+        if ((STRING_concat(schemaText, "[") != 0) ||
+            /* Codes_SRS_SCHEMA_SERIALIZER_01_006: [The object for a command shall have a member named Name, whose value shall be the command name as obtained by using Schema APIs.] */
+            (Schema_GetModelActionCount(modelHandle, &commandCount) != SCHEMA_OK))
+        {
+            /* Codes_SRS_SCHEMA_SERIALIZER_01_015: [If any of the Schema or String APIs fail then SchemaSerializer_SerializeCommandMetadata shall return SCHEMA_SERIALIZER_ERROR.] */
+            result = SCHEMA_SERIALIZER_ERROR;
+            LOG_SCHEMA_SERIALIZER_ERROR(result);
+        }
+        else
+        {
+            size_t i;
+
+            for (i = 0; i < commandCount; i++)
+            {
+                SCHEMA_ACTION_HANDLE actionHandle = Schema_GetModelActionByIndex(modelHandle, i);
+                const char* commandName;
+                size_t argCount;
+                size_t j;
+
+                /* Codes_SRS_SCHEMA_SERIALIZER_01_005: [Each array element shall be a JSON object.] */
+                if ((actionHandle == NULL) ||
+                    (STRING_concat(schemaText, "{ \"Name\":\"") != 0) ||
+                    ((commandName = Schema_GetModelActionName(actionHandle)) == NULL) ||
+                    (STRING_concat(schemaText, commandName) != 0) ||
+                    /* Codes_SRS_SCHEMA_SERIALIZER_01_007: [The object for a command shall also have a "Parameters" member.] */
+                    (STRING_concat(schemaText, "\", \"Parameters\":[") != 0) ||
+                    (Schema_GetModelActionArgumentCount(actionHandle, &argCount) != SCHEMA_OK))
+                {
+                    /* Codes_SRS_SCHEMA_SERIALIZER_01_015: [If any of the Schema or String APIs fail then SchemaSerializer_SerializeCommandMetadata shall return SCHEMA_SERIALIZER_ERROR.] */
+                    LogError("Failed encoding action.");
+                    break;
+                }
+                else
+                {
+                    for (j = 0; j < argCount; j++)
+                    {
+                        /* Codes_SRS_SCHEMA_SERIALIZER_01_008: [The parameters member shall be an array, where each entry is a command parameter.] */
+                        SCHEMA_ACTION_ARGUMENT_HANDLE argHandle = Schema_GetModelActionArgumentByIndex(actionHandle, j);
+                        const char* argName;
+                        const char* argType;
+
+                        /* Codes_SRS_SCHEMA_SERIALIZER_01_009: [Each command parameter shall have a member named "Name", that should have as value the command argument name as obtained by using Schema APIs.] */
+                        if ((argHandle == NULL) ||
+                            (STRING_concat(schemaText, "{\"Name\":\"") != 0) ||
+                            ((argName = Schema_GetActionArgumentName(argHandle)) == NULL) ||
+                            (STRING_concat(schemaText, argName) != 0) ||
+                            /* Codes_SRS_SCHEMA_SERIALIZER_01_010: [Each command parameter shall have a member named "Type", that should have as value the command argument type as obtained by using Schema APIs.] */
+                            (STRING_concat(schemaText, "\",\"Type\":\"") != 0) ||
+                            ((argType = Schema_GetActionArgumentType(argHandle)) == NULL) ||
+                            (STRING_concat(schemaText, ConvertType(argType)) != 0))
+                        {
+                            /* Codes_SRS_SCHEMA_SERIALIZER_01_015: [If any of the Schema or String APIs fail then SchemaSerializer_SerializeCommandMetadata shall return SCHEMA_SERIALIZER_ERROR.] */
+                            LogError("Failed encoding argument.");
+                            break;
+                        }
+                        else
+                        {
+                            if (j + 1 < argCount)
+                            {
+                                if (STRING_concat(schemaText, "\"},") != 0)
+                                {
+                                    /* Codes_SRS_SCHEMA_SERIALIZER_01_015: [If any of the Schema or String APIs fail then SchemaSerializer_SerializeCommandMetadata shall return SCHEMA_SERIALIZER_ERROR.] */
+                                    LogError("Failed to concatenate arg end.");
+                                    break;
+                                }
+                            }
+                            else
+                            {
+                                if (STRING_concat(schemaText, "\"}") != 0)
+                                {
+                                    /* Codes_SRS_SCHEMA_SERIALIZER_01_015: [If any of the Schema or String APIs fail then SchemaSerializer_SerializeCommandMetadata shall return SCHEMA_SERIALIZER_ERROR.] */
+                                    LogError("Failed to concatenate arg end.");
+                                    break;
+                                }
+                            }
+                        }
+                    }
+
+                    if (j < argCount)
+                    {
+                        break;
+                    }
+
+                    if (i + 1 < commandCount)
+                    {
+                        if (STRING_concat(schemaText, "]},") != 0)
+                        {
+                            /* Codes_SRS_SCHEMA_SERIALIZER_01_015: [If any of the Schema or String APIs fail then SchemaSerializer_SerializeCommandMetadata shall return SCHEMA_SERIALIZER_ERROR.] */
+                            LogError("Failed to concatenate.");
+                            break;
+                        }
+                    }
+                    else
+                    {
+                        if (STRING_concat(schemaText, "]}") != 0)
+                        {
+                            /* Codes_SRS_SCHEMA_SERIALIZER_01_015: [If any of the Schema or String APIs fail then SchemaSerializer_SerializeCommandMetadata shall return SCHEMA_SERIALIZER_ERROR.] */
+                            LogError("Failed to concatenate.");
+                            break;
+                        }
+                    }
+                }
+            }
+
+            if (i < commandCount)
+            {
+                result = SCHEMA_SERIALIZER_ERROR;
+            }
+            else if (STRING_concat(schemaText, "]") != 0)
+            {
+                /* Codes_SRS_SCHEMA_SERIALIZER_01_015: [If any of the Schema or String APIs fail then SchemaSerializer_SerializeCommandMetadata shall return SCHEMA_SERIALIZER_ERROR.] */
+                LogError("Failed to concatenate commands object end.");
+                result = SCHEMA_SERIALIZER_ERROR;
+            }
+            else
+            {
+                /* Codes_SRS_SCHEMA_SERIALIZER_01_012: [On success SchemaSerializer_SerializeCommandMetadata shall return SCHEMA_SERIALIZER_OK.] */
+                result = SCHEMA_SERIALIZER_OK;
+            }
+        }
+    }
+
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/serializer.def
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/serializer.def	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/serializer/src/serializer.def	(revision 453)
@@ -0,0 +1,218 @@
+LIBRARY serializer
+EXPORTS
+    MethodReturn_Create
+    MethodReturn_Destroy
+    MethodReturn_GetReturn
+    SCHEMA_SERIALIZER_RESULTStringStorage
+    SCHEMA_SERIALIZER_RESULTStrings
+    SCHEMA_SERIALIZER_RESULT_FromString
+    SchemaSerializer_SerializeCommandMetadata
+    SERIALIZER_RESULTStringStorage
+    SERIALIZER_RESULTStrings
+    SERIALIZER_RESULT_FromString
+    serializer_init
+    serializer_deinit
+    serializer_setconfig
+    SCHEMA_RESULTStringStorage
+    SCHEMA_RESULTStrings
+    SCHEMA_RESULT_FromString
+    Schema_Create
+    Schema_GetMetadata
+    Schema_GetSchemaCount
+    Schema_GetSchemaByNamespace
+    Schema_GetSchemaForModel
+    Schema_GetSchemaNamespace
+    Schema_AddDeviceRef
+    Schema_ReleaseDeviceRef
+    Schema_CreateModelType
+    Schema_GetSchemaForModelType
+    Schema_GetModelName
+    Schema_CreateStructType
+    Schema_GetStructTypeName
+    Schema_AddStructTypeProperty
+    Schema_AddModelProperty
+    Schema_AddModelReportedProperty
+    Schema_AddModelDesiredProperty
+    Schema_AddModelModel
+    Schema_CreateModelAction
+    Schema_CreateModelMethod
+    Schema_AddModelActionArgument
+    Schema_AddModelMethodArgument
+    Schema_GetModelDesiredProperty_pfDesiredPropertyFromAGENT_DATA_TYPE
+    Schema_GetModelDesiredProperty_pfOnDesiredProperty
+    Schema_GetModelModelByName_Offset
+    Schema_GetModelModelByName_OnDesiredProperty
+    Schema_GetModelModelByIndex_Offset
+    Schema_GetModelDesiredProperty_offset
+    Schema_GetModelDesiredPropertyType
+    Schema_GetModelDesiredProperty_pfDesiredPropertyDeinitialize
+    Schema_GetModelDesiredProperty_pfDesiredPropertyInitialize
+    Schema_GetModelElementByName
+    Schema_GetModelCount
+    Schema_GetModelByName
+    Schema_GetModelByIndex
+    Schema_GetModelPropertyCount
+    Schema_GetModelPropertyByName
+    Schema_GetModelPropertyByIndex
+    Schema_GetModelReportedPropertyCount
+    Schema_GetModelReportedPropertyByName
+    Schema_GetModelReportedPropertyByIndex
+    Schema_GetModelDesiredPropertyCount
+    Schema_GetModelDesiredPropertyByName
+    Schema_GetModelDesiredPropertyByIndex
+    Schema_GetModelModelCount
+    Schema_GetModelModelByName
+    Schema_GetModelModelyByIndex
+    Schema_GetModelModelPropertyNameByIndex
+    Schema_ModelPropertyByPathExists
+    Schema_ModelReportedPropertyByPathExists
+    Schema_ModelDesiredPropertyByPathExists
+    Schema_GetModelActionCount
+    Schema_GetModelActionByName
+    Schema_GetModelMethodByName
+    Schema_GetModelActionByIndex
+    Schema_GetModelActionArgumentCount
+    Schema_GetModelMethodArgumentCount
+    Schema_GetModelActionName
+    Schema_GetModelActionArgumentByName
+    Schema_GetModelActionArgumentByIndex
+    Schema_GetModelMethodArgumentByIndex
+    Schema_GetActionArgumentName
+    Schema_GetMethodArgumentName
+    Schema_GetActionArgumentType
+    Schema_GetMethodArgumentType
+    Schema_GetStructTypeCount
+    Schema_GetStructTypeByName
+    Schema_GetStructTypeByIndex
+    Schema_GetStructTypePropertyCount
+    Schema_GetStructTypePropertyByName
+    Schema_GetStructTypePropertyByIndex
+    Schema_GetPropertyName
+    Schema_GetPropertyType
+    Schema_Destroy
+    Schema_DestroyIfUnused
+    MULTITREE_RESULTStringStorage
+    MULTITREE_RESULTStrings
+    MULTITREE_RESULT_FromString
+    MultiTree_Create
+    MultiTree_AddLeaf
+    MultiTree_AddChild
+    MultiTree_GetChildCount
+    MultiTree_GetChild
+    MultiTree_GetChildByName
+    MultiTree_GetName
+    MultiTree_GetValue
+    MultiTree_GetLeafValue
+    MultiTree_SetValue
+    MultiTree_Destroy
+    JSON_ENCODER_TOSTRING_RESULTStringStorage
+    JSON_ENCODER_RESULTStringStorage
+    JSON_ENCODER_RESULTStrings
+    JSON_ENCODER_RESULT_FromString
+    JSON_ENCODER_TOSTRING_RESULTStrings
+    JSON_ENCODER_TOSTRING_RESULT_FromString
+    JSONEncoder_CharPtr_ToString
+    JSONEncoder_EncodeTree
+    JSONDecoder_JSON_To_MultiTree
+    SkipWhiteSpaces
+    DEVICE_RESULTStringStorage
+    DEVICE_RESULTStrings
+    DEVICE_RESULT_FromString
+    Device_Create
+    Device_Destroy
+    Device_StartTransaction
+    Device_PublishTransacted
+    Device_EndTransaction
+    Device_CancelTransaction
+    Device_CreateTransaction_ReportedProperties
+    Device_PublishTransacted_ReportedProperty
+    Device_CommitTransaction_ReportedProperties
+    Device_DestroyTransaction_ReportedProperties
+    Device_ExecuteCommand
+    Device_ExecuteMethod
+    Device_IngestDesiredProperties
+    DATA_SERIALIZER_RESULTStringStorage
+    DATA_SERIALIZER_RESULTStrings
+    DATA_SERIALIZER_RESULT_FromString
+    DataSerializer_Encode
+    DataSerializer_Decode
+    DATA_PUBLISHER_RESULTStringStorage
+    DATA_PUBLISHER_RESULTStrings
+    DATA_PUBLISHER_RESULT_FromString
+    DataPublisher_Create
+    DataPublisher_Destroy
+    DataPublisher_StartTransaction
+    DataPublisher_PublishTransacted
+    DataPublisher_EndTransaction
+    DataPublisher_CancelTransaction
+    DataPublisher_SetMaxBufferSize
+    DataPublisher_GetMaxBufferSize
+    DataPublisher_CreateTransaction_ReportedProperties
+    DataPublisher_PublishTransacted_ReportedProperty
+    DataPublisher_CommitTransaction_ReportedProperties
+    DataPublisher_DestroyTransaction_ReportedProperties
+    DATA_MARSHALLER_RESULTStringStorage
+    DATA_MARSHALLER_RESULTStrings
+    DATA_MARSHALLER_RESULT_FromString
+    DataMarshaller_Create
+    DataMarshaller_Destroy
+    DataMarshaller_SendData
+    DataMarshaller_SendData_ReportedProperties
+    COMMANDDECODER_RESULTStringStorage
+    AGENT_DATA_TYPE_TYPEStringStorage
+    AGENT_DATA_TYPE_TYPEStrings
+    AGENT_DATA_TYPE_TYPE_FromString
+    COMMANDDECODER_RESULTStrings
+    COMMANDDECODER_RESULT_FromString
+    CommandDecoder_Create
+    CommandDecoder_ExecuteCommand
+    CommandDecoder_ExecuteMethod
+    CommandDecoder_Destroy
+    CommandDecoder_IngestDesiredProperties
+    CODEFIRST_RESULTStringStorage
+    EXECUTE_COMMAND_RESULTStringStorage
+    EXECUTE_COMMAND_RESULTStrings
+    EXECUTE_COMMAND_RESULT_FromString
+    CODEFIRST_RESULTStrings
+    CODEFIRST_RESULT_FromString
+    CodeFirst_Init
+    CodeFirst_Deinit
+    CodeFirst_RegisterSchema
+    CodeFirst_InvokeAction
+    CodeFirst_InvokeMethod
+    CodeFirst_ExecuteCommand
+    CodeFirst_ExecuteMethod
+    CodeFirst_CreateDevice
+    CodeFirst_DestroyDevice
+    CodeFirst_SendAsync
+    CodeFirst_SendAsyncReported
+    CodeFirst_IngestDesiredProperties
+    CodeFirst_GetPrimitiveType
+    hexToASCII
+    AGENT_DATA_TYPES_RESULTStringStorage
+    AGENT_DATA_TYPES_RESULTStrings
+    AGENT_DATA_TYPES_RESULT_FromString
+    AgentDataTypes_ToString
+    Create_EDM_BOOLEAN_from_int
+    Create_AGENT_DATA_TYPE_from_UINT8
+    Create_AGENT_DATA_TYPE_from_date
+    Create_EDM_DECIMAL_from_charz
+    Create_AGENT_DATA_TYPE_from_DOUBLE
+    Create_AGENT_DATA_TYPE_from_SINT16
+    Create_AGENT_DATA_TYPE_from_SINT32
+    Create_AGENT_DATA_TYPE_from_SINT64
+    Create_AGENT_DATA_TYPE_from_SINT8
+    Create_AGENT_DATA_TYPE_from_EDM_DATE_TIME_OFFSET
+    Create_AGENT_DATA_TYPE_from_EDM_GUID
+    Create_AGENT_DATA_TYPE_from_EDM_BINARY
+    Create_AGENT_DATA_TYPE_from_FLOAT
+    Create_AGENT_DATA_TYPE_from_charz
+    Create_AGENT_DATA_TYPE_from_charz_no_quotes
+    Create_NULL_AGENT_DATA_TYPE
+    Create_AGENT_DATA_TYPE_from_Members
+    Create_AGENT_DATA_TYPE_from_MemberPointers
+    Create_AGENT_DATA_TYPE_from_AGENT_DATA_TYPE
+    Destroy_AGENT_DATA_TYPE
+    CreateAgentDataType_From_String
+    AgentDataType_GetComplexTypeField
+
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/uhttp/inc/azure_uhttp_c/uhttp.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/uhttp/inc/azure_uhttp_c/uhttp.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/uhttp/inc/azure_uhttp_c/uhttp.h	(revision 453)
@@ -0,0 +1,85 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef UHTTP_H
+#define UHTTP_H
+
+#ifdef __cplusplus
+extern "C" {
+#include <cstddef>
+#else
+#include <stddef.h>
+#include <stdbool.h>
+#endif /* __cplusplus */
+
+#include "azure_c_shared_utility/httpheaders.h"
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/xio.h"
+#include "umock_c/umock_c_prod.h"
+
+typedef struct HTTP_CLIENT_HANDLE_DATA_TAG* HTTP_CLIENT_HANDLE;
+
+#define HTTP_CLIENT_RESULT_VALUES       \
+    HTTP_CLIENT_OK,                     \
+    HTTP_CLIENT_INVALID_ARG,            \
+    HTTP_CLIENT_ERROR,                  \
+    HTTP_CLIENT_OPEN_FAILED,            \
+    HTTP_CLIENT_SEND_FAILED,            \
+    HTTP_CLIENT_ALREADY_INIT,           \
+    HTTP_CLIENT_HTTP_HEADERS_FAILED,    \
+    HTTP_CLIENT_INVALID_STATE           \
+
+
+/** @brief Enumeration specifying the possible return values for the APIs in
+*           this module.
+*/
+MU_DEFINE_ENUM(HTTP_CLIENT_RESULT, HTTP_CLIENT_RESULT_VALUES);
+
+#define HTTP_CLIENT_REQUEST_TYPE_VALUES \
+    HTTP_CLIENT_REQUEST_OPTIONS,        \
+    HTTP_CLIENT_REQUEST_GET,            \
+    HTTP_CLIENT_REQUEST_POST,           \
+    HTTP_CLIENT_REQUEST_PUT,            \
+    HTTP_CLIENT_REQUEST_DELETE,         \
+    HTTP_CLIENT_REQUEST_PATCH
+
+MU_DEFINE_ENUM(HTTP_CLIENT_REQUEST_TYPE, HTTP_CLIENT_REQUEST_TYPE_VALUES);
+
+#define HTTP_CALLBACK_REASON_VALUES     \
+    HTTP_CALLBACK_REASON_OK,            \
+    HTTP_CALLBACK_REASON_OPEN_FAILED,   \
+    HTTP_CALLBACK_REASON_SEND_FAILED,   \
+    HTTP_CALLBACK_REASON_ERROR,         \
+    HTTP_CALLBACK_REASON_PARSING_ERROR, \
+    HTTP_CALLBACK_REASON_DESTROY,       \
+    HTTP_CALLBACK_REASON_DISCONNECTED
+
+MU_DEFINE_ENUM(HTTP_CALLBACK_REASON, HTTP_CALLBACK_REASON_VALUES);
+
+typedef void(*ON_HTTP_OPEN_COMPLETE_CALLBACK)(void* callback_ctx, HTTP_CALLBACK_REASON open_result);
+typedef void(*ON_HTTP_ERROR_CALLBACK)(void* callback_ctx, HTTP_CALLBACK_REASON error_result);
+typedef void(*ON_HTTP_REQUEST_CALLBACK)(void* callback_ctx, HTTP_CALLBACK_REASON request_result, const unsigned char* content, size_t content_length, unsigned int status_code,
+    HTTP_HEADERS_HANDLE response_headers);
+typedef void(*ON_HTTP_CLOSED_CALLBACK)(void* callback_ctx);
+
+MOCKABLE_FUNCTION(, HTTP_CLIENT_HANDLE, uhttp_client_create, const IO_INTERFACE_DESCRIPTION*, io_interface_desc, const void*, xio_param, ON_HTTP_ERROR_CALLBACK, on_http_error, void*, callback_ctx);
+MOCKABLE_FUNCTION(, void, uhttp_client_destroy, HTTP_CLIENT_HANDLE, handle);
+MOCKABLE_FUNCTION(, HTTP_CLIENT_RESULT, uhttp_client_open, HTTP_CLIENT_HANDLE, handle, const char*, host, int, port_num, ON_HTTP_OPEN_COMPLETE_CALLBACK, on_connect, void*, callback_ctx);
+MOCKABLE_FUNCTION(, void, uhttp_client_close, HTTP_CLIENT_HANDLE, handle, ON_HTTP_CLOSED_CALLBACK, on_close_callback, void*, callback_ctx);
+MOCKABLE_FUNCTION(, HTTP_CLIENT_RESULT, uhttp_client_execute_request, HTTP_CLIENT_HANDLE, handle, HTTP_CLIENT_REQUEST_TYPE, request_type, const char*, relative_path,
+    HTTP_HEADERS_HANDLE, http_header_handle, const unsigned char*, content, size_t, content_length, ON_HTTP_REQUEST_CALLBACK, on_request_callback, void*, callback_ctx);
+
+MOCKABLE_FUNCTION(, void, uhttp_client_dowork, HTTP_CLIENT_HANDLE, handle);
+
+MOCKABLE_FUNCTION(, HTTP_CLIENT_RESULT, uhttp_client_set_trace, HTTP_CLIENT_HANDLE, handle, bool, trace_on, bool, trace_data);
+MOCKABLE_FUNCTION(, HTTP_CLIENT_RESULT, uhttp_client_set_X509_cert, HTTP_CLIENT_HANDLE, handle, bool, ecc_type, const char*, certificate, const char*, private_key);
+MOCKABLE_FUNCTION(, HTTP_CLIENT_RESULT, uhttp_client_set_trusted_cert, HTTP_CLIENT_HANDLE, handle, const char*, certificate);
+MOCKABLE_FUNCTION(, const char*, uhttp_client_get_trusted_cert, HTTP_CLIENT_HANDLE, handle);
+MOCKABLE_FUNCTION(, HTTP_CLIENT_RESULT, uhttp_client_set_option, HTTP_CLIENT_HANDLE, handle, const char*, optionName, const void*, value);
+MOCKABLE_FUNCTION(, XIO_HANDLE, uhttp_client_get_underlying_xio, HTTP_CLIENT_HANDLE, handle);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* UHTTP_H */
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/uhttp/src/uhttp.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/uhttp/src/uhttp.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/uhttp/src/uhttp.c	(revision 453)
@@ -0,0 +1,1525 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <ctype.h>
+
+#include "umock_c/umock_c_prod.h"
+#include "azure_c_shared_utility/gballoc.h"
+
+#include <string.h>
+#include "azure_uhttp_c/uhttp.h"
+#include "azure_c_shared_utility/httpheaders.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/strings.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/buffer_.h"
+#include "azure_c_shared_utility/singlylinkedlist.h"
+#include "azure_c_shared_utility/shared_util_options.h"
+#include "azure_c_shared_utility/optimize_size.h"
+
+#define MAX_HOSTNAME        64
+#define TIME_MAX_BUFFER     16
+#define HTTP_CRLF_LEN       2
+#define HTTP_END_TOKEN_LEN  4
+#define MAX_CONTENT_LENGTH  16
+
+static const char* HTTP_REQUEST_LINE_FMT = "%s %s HTTP/1.1\r\n";
+static const char* HTTP_HOST = "Host";
+// The following header names MUST be lowercase as they are used for HTTP response header comparison:
+static const char* HTTP_CONTENT_LEN = "content-length";
+static const char* HTTP_TRANSFER_ENCODING = "transfer-encoding";
+static const char* HTTP_CRLF_VALUE = "\r\n";
+
+typedef enum RESPONSE_MESSAGE_STATE_TAG
+{
+    state_initial,
+    state_opening,
+    state_open,
+    state_process_status_line,
+    state_process_headers,
+    state_process_body,
+    state_process_chunked_body,
+
+    state_send_user_callback,
+    state_parse_complete,
+
+    state_closing,
+    state_closed,
+    state_error
+} RESPONSE_MESSAGE_STATE;
+
+typedef struct HTTP_RECV_DATA_TAG
+{
+    ON_HTTP_REQUEST_CALLBACK on_request_callback;
+    void* user_ctx;
+    int status_code;
+    RESPONSE_MESSAGE_STATE recv_state;
+    HTTP_HEADERS_HANDLE resp_header;
+    BUFFER_HANDLE msg_body;
+    size_t total_body_len;
+    BUFFER_HANDLE accrual_buff;
+    bool chunked_reply;
+} HTTP_RECV_DATA;
+
+typedef struct HTTP_CLIENT_HANDLE_DATA_TAG
+{
+    XIO_HANDLE xio_handle;
+    ON_HTTP_OPEN_COMPLETE_CALLBACK on_connect;
+    void* connect_user_ctx;
+    ON_HTTP_ERROR_CALLBACK on_error;
+    void* error_user_ctx;
+    ON_HTTP_CLOSED_CALLBACK on_close_callback;
+    void* close_user_ctx;
+    HTTP_RECV_DATA recv_msg;
+    bool chunk_request;
+    bool trace_on;
+    bool trace_body;
+    char* host_name;
+    int port_num;
+    SINGLYLINKEDLIST_HANDLE data_list;
+    bool cert_type_ecc;
+    char* x509_cert;
+    char* x509_pk;
+    char* certificate;
+    int connected;
+} HTTP_CLIENT_HANDLE_DATA;
+
+typedef struct HTTP_SEND_DATA_TAG
+{
+    HTTP_CLIENT_REQUEST_TYPE request_type;
+    STRING_HANDLE relative_path;
+    STRING_HANDLE header_line;
+    BUFFER_HANDLE content;
+} HTTP_SEND_DATA;
+
+static void send_complete_callback(void* context, IO_SEND_RESULT send_result)
+{
+    (void)context;(void)send_result;
+}
+
+static int initialize_received_data(HTTP_CLIENT_HANDLE_DATA* http_data)
+{
+    int result = 0;
+
+    // Initialize data if necessary
+    if (http_data->recv_msg.resp_header == NULL)
+    {
+        http_data->recv_msg.resp_header = HTTPHeaders_Alloc();
+        if (http_data->recv_msg.resp_header == NULL)
+        {
+            /* Codes_SRS_UHTTP_07_048: [ If any error is encountered on_bytes_received shall set the state to error. ] */
+            LogError("Failure creating Http header.");
+            result = MU_FAILURE;
+        }
+    }
+    if (result == 0 && http_data->recv_msg.accrual_buff == NULL)
+    {
+        http_data->recv_msg.accrual_buff = BUFFER_new();
+        if (http_data->recv_msg.accrual_buff == NULL)
+        {
+            /* Codes_SRS_UHTTP_07_048: [ If any error is encountered on_bytes_received shall set the state to error. ] */
+            LogError("Failure creating accrual buffer.");
+            result = MU_FAILURE;
+        }
+    }
+    http_data->recv_msg.chunked_reply = false;
+    return result;
+}
+
+static int process_status_code_line(const unsigned char* buffer, size_t len, size_t* position, int* statusLen)
+{
+    int result = MU_FAILURE;
+    size_t index;
+    int spaceFound = 0;
+    const char* initSpace = NULL;
+    char status_code[4];
+
+    for (index = 0; index < len; index++)
+    {
+        if (buffer[index] == ' ')
+        {
+            if (spaceFound == 1)
+            {
+                (void)memcpy(status_code, initSpace, 3);
+                status_code[3] = '\0';
+            }
+            else
+            {
+                initSpace = (const char*)buffer + index + 1;
+            }
+            spaceFound++;
+        }
+        else if (buffer[index] == '\n')
+        {
+            *statusLen = (int)atol(status_code);
+            if (index < len)
+            {
+                *position = index + 1;
+            }
+            else
+            {
+                *position = index;
+            }
+            result = 0;
+            break;
+        }
+    }
+    return result;
+}
+
+static int process_header_line(const unsigned char* buffer, size_t len, size_t* position, HTTP_HEADERS_HANDLE resp_header, size_t* contentLen, bool* isChunked)
+{
+    int result = MU_FAILURE;
+    size_t index;
+    const unsigned char* targetPos = buffer;
+    bool crlfEncounted = false;
+    bool colonEncountered = false;
+    char* headerKey = NULL;
+    bool continueProcessing = true;
+
+    for (index = 0; index < len && continueProcessing; index++)
+    {
+        if (buffer[index] == ':' && !colonEncountered)
+        {
+            colonEncountered = true;
+            size_t keyLen = (&buffer[index])-targetPos;
+
+            if (headerKey != NULL)
+            {
+                free(headerKey);
+                headerKey = NULL;
+            }
+            headerKey = (char*)malloc(keyLen+1);
+            if (headerKey == NULL)
+            {
+                result = MU_FAILURE;
+                continueProcessing = false;
+            }
+            else
+            {
+                memcpy(headerKey, targetPos, keyLen);
+                headerKey[keyLen] = '\0';
+
+                // Convert to lower case
+                for (size_t inner = 0; inner < keyLen; inner++)
+                {
+                    headerKey[inner] = (char)tolower(headerKey[inner]);
+                }
+
+                targetPos = buffer+index+1;
+                crlfEncounted = false;
+            }
+        }
+        else if (buffer[index] == '\r')
+        {
+            if (headerKey != NULL)
+            {
+                // Remove leading spaces
+                while (*targetPos == 32) { targetPos++; }
+
+                size_t valueLen = (&buffer[index])-targetPos;
+                char* headerValue = (char*)malloc(valueLen+1);
+                if (headerValue == NULL)
+                {
+                    result = MU_FAILURE;
+                    continueProcessing = false;
+                }
+                else
+                {
+                    memcpy(headerValue, targetPos, valueLen);
+                    headerValue[valueLen] = '\0';
+
+                    if (HTTPHeaders_AddHeaderNameValuePair(resp_header, headerKey, headerValue) != HTTP_HEADERS_OK)
+                    {
+                        result = MU_FAILURE;
+                        continueProcessing = false;
+                    }
+                    else
+                    {
+                        if (strcmp(headerKey, HTTP_CONTENT_LEN) == 0)
+                        {
+                            *isChunked = false;
+                            *contentLen = atol(headerValue);
+                        }
+                        else if (strcmp(headerKey, HTTP_TRANSFER_ENCODING) == 0)
+                        {
+                            *isChunked = true;
+                            *contentLen = 0;
+                        }
+                        if (index < len)
+                        {
+                            *position = index;
+                        }
+                        else
+                        {
+                            *position = index-1;
+                        }
+                    }
+                }
+                free(headerKey);
+                headerKey = NULL;
+                free(headerValue);
+            }
+        }
+        else if (buffer[index] == '\n')
+        {
+            if (crlfEncounted)
+            {
+                if (index < len)
+                {
+                    *position = index+1;
+                }
+                else
+                {
+                    *position = index;
+                }
+                result = 0;
+                break;
+            }
+            else
+            {
+                colonEncountered = false;
+                crlfEncounted = true;
+                targetPos = buffer+index+1;
+            }
+        }
+        else
+        {
+            crlfEncounted = false;
+        }
+    }
+    if (headerKey != NULL)
+    {
+        free(headerKey);
+    }
+    return result;
+}
+
+static int write_text_line(HTTP_CLIENT_HANDLE_DATA* http_data, const char* text_line)
+{
+    int result;
+    if (xio_send(http_data->xio_handle, text_line, strlen(text_line), send_complete_callback, NULL) != 0)
+    {
+        LogError("Failure calling xio_send.");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        result = 0;
+        if (http_data->trace_on)
+        {
+            LOG(AZ_LOG_TRACE, LOG_LINE, "%s", text_line);
+        }
+    }
+    return result;
+}
+
+static int write_data_line(HTTP_CLIENT_HANDLE_DATA* http_data, const unsigned char* data_line, size_t length)
+{
+    int result;
+    if (xio_send(http_data->xio_handle, data_line, length, send_complete_callback, NULL) != 0)
+    {
+        LogError("Failure calling xio_send.");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        result = 0;
+        if (http_data->trace_on)
+        {
+            if (length > 0)
+            {
+                if (http_data->trace_body)
+                {
+                    LOG(AZ_LOG_TRACE, LOG_LINE, "len: %d\r\n%.*s\r\n", (int)length, (int)length, data_line);
+                }
+                else
+                {
+                    LOG(AZ_LOG_TRACE, LOG_LINE, "<data> len: %d\r\n", (int)length);
+                }
+            }
+            else
+            {
+                LOG(AZ_LOG_TRACE, LOG_LINE, "len: %d\r\n", (int)length);
+            }
+        }
+    }
+    return result;
+}
+
+static int convert_char_to_hex(const unsigned char* hexText, size_t len)
+{
+    int result = 0;
+    for (size_t index = 0; index < len; index++)
+    {
+        if (hexText[index] == ';')
+        {
+            break;
+        }
+        else
+        {
+            int accumulator = 0;
+            if (hexText[index] >= 48 && hexText[index] <= 57)
+            {
+                accumulator = hexText[index] - 48;
+            }
+            else if (hexText[index] >= 65 && hexText[index] <= 70)
+            {
+                accumulator = hexText[index] - 55;
+            }
+            else if (hexText[index] >= 97 && hexText[index] <= 102)
+            {
+                accumulator = hexText[index] - 87;
+            }
+            if (index > 0)
+            {
+                result = result << 4;
+            }
+            result += accumulator;
+        }
+    }
+    return result;
+}
+
+static int setup_init_recv_msg(HTTP_RECV_DATA* recv_msg)
+{
+    int result;
+    recv_msg->status_code = 0;
+    recv_msg->recv_state = state_initial;
+    recv_msg->total_body_len = 0;
+    if (recv_msg->resp_header != NULL)
+    {
+        HTTPHeaders_Free(recv_msg->resp_header);
+    }
+    if (recv_msg->msg_body != NULL)
+    {
+        BUFFER_delete(recv_msg->msg_body);
+    }
+    if ((recv_msg->resp_header = HTTPHeaders_Alloc()) == NULL)
+    {
+        /* Codes_SRS_UHTTP_07_017: [If any failure encountered http_client_execute_request shall return HTTP_CLIENT_ERROR] */
+        LogError("Failure allocating http http_data items");
+        result = HTTP_CLIENT_ERROR;
+    }
+    else if ((recv_msg->msg_body = BUFFER_new()) == NULL)
+    {
+        /* Codes_SRS_UHTTP_07_017: [If any failure encountered http_client_execute_request shall return HTTP_CLIENT_ERROR] */
+        LogError("Failure allocating http data items");
+        HTTPHeaders_Free(recv_msg->resp_header);
+        recv_msg->resp_header = NULL;
+        result = HTTP_CLIENT_ERROR;
+    }
+    else
+    {
+        result = 0;
+    }
+    return result;
+}
+
+static void on_bytes_received(void* context, const unsigned char* buffer, size_t len)
+{
+    HTTP_CLIENT_HANDLE_DATA* http_data = (HTTP_CLIENT_HANDLE_DATA*)context;
+
+    if (http_data != NULL && buffer != NULL && len > 0 && http_data->recv_msg.recv_state != state_error)
+    {
+        if (http_data->recv_msg.recv_state == state_parse_complete)
+        {
+            // The callback is getting called during a new send.
+            setup_init_recv_msg(&http_data->recv_msg);
+
+        }
+
+        if (http_data->recv_msg.recv_state == state_initial || http_data->recv_msg.recv_state == state_open)
+        {
+            if (initialize_received_data(http_data) != 0)
+            {
+                http_data->recv_msg.recv_state = state_error;
+            }
+            else
+            {
+                http_data->recv_msg.recv_state = state_process_status_line;
+            }
+        }
+
+        // Put the data in the buffer
+        if (BUFFER_append_build(http_data->recv_msg.accrual_buff, buffer, len) != 0)
+        {
+            /* Codes_SRS_UHTTP_07_048: [ If any error is encountered on_bytes_received shall set the state to error. ] */
+            LogError("Failure appending bytes to buffer.");
+            http_data->recv_msg.recv_state = state_error;
+        }
+
+        if (http_data->recv_msg.recv_state == state_process_status_line)
+        {
+            size_t index = 0;
+            const unsigned char* stored_bytes = BUFFER_u_char(http_data->recv_msg.accrual_buff);
+            size_t stored_len = BUFFER_length(http_data->recv_msg.accrual_buff);
+
+            int lineComplete = process_status_code_line(stored_bytes, stored_len, &index, &http_data->recv_msg.status_code);
+            if (lineComplete == 0 && http_data->recv_msg.status_code > 0)
+            {
+                if (BUFFER_shrink(http_data->recv_msg.accrual_buff, index, false) != 0)
+                {
+                    LogError("Failure appending bytes to buffer.");
+                    http_data->recv_msg.recv_state = state_error;
+                }
+                else
+                {
+                    http_data->recv_msg.recv_state = state_process_headers;
+                }
+            }
+        }
+
+        if (http_data->recv_msg.recv_state == state_process_headers)
+        {
+            size_t index = 0;
+            const unsigned char* stored_bytes = BUFFER_u_char(http_data->recv_msg.accrual_buff);
+            size_t stored_len = BUFFER_length(http_data->recv_msg.accrual_buff);
+
+            int headerComplete = process_header_line(stored_bytes, stored_len, &index, http_data->recv_msg.resp_header, &http_data->recv_msg.total_body_len, &http_data->recv_msg.chunked_reply);
+            if (headerComplete == 0)
+            {
+                if (http_data->recv_msg.total_body_len == 0)
+                {
+                    if (http_data->recv_msg.chunked_reply)
+                    {
+
+                        /* Codes_SRS_UHTTP_07_054: [ If the http header does not include a content length then it indicates a chunk response. ] */
+                        http_data->recv_msg.recv_state = state_process_chunked_body;
+                    }
+                    else
+                    {
+                        // Content len is 0 so we are finished with the body
+                        http_data->recv_msg.recv_state = state_send_user_callback;
+                    }
+                }
+                else
+                {
+                    http_data->recv_msg.recv_state = state_process_body;
+                }
+            }
+            if (index > 0)
+            {
+                if (BUFFER_shrink(http_data->recv_msg.accrual_buff, index, false) != 0)
+                {
+                    LogError("Failure appending bytes to buffer.");
+                    http_data->recv_msg.recv_state = state_error;
+                }
+            }
+        }
+
+        if (http_data->recv_msg.recv_state == state_process_body)
+        {
+            if (http_data->recv_msg.total_body_len != 0)
+            {
+                size_t stored_len = BUFFER_length(http_data->recv_msg.accrual_buff);
+
+                if ((http_data->recv_msg.total_body_len == stored_len) || (http_data->recv_msg.total_body_len == (stored_len - HTTP_END_TOKEN_LEN)))
+                {
+                    if (http_data->recv_msg.msg_body != NULL)
+                    {
+                        BUFFER_delete(http_data->recv_msg.msg_body);
+                    }
+                    if ((http_data->recv_msg.msg_body = BUFFER_clone(http_data->recv_msg.accrual_buff)) == NULL)
+                    {
+                        LogError("Failure cloning BUFFER.");
+                        http_data->recv_msg.recv_state = state_error;
+                    }
+                    else
+                    {
+                        http_data->recv_msg.recv_state = state_send_user_callback;
+                    }
+                }
+                else if (stored_len > http_data->recv_msg.total_body_len)
+                {
+                    LogError("Failure bytes encountered is greater then body length.");
+                    http_data->recv_msg.recv_state = state_error;
+                }
+            }
+        }
+
+        if (http_data->recv_msg.recv_state == state_process_chunked_body)
+        {
+            const unsigned char* iterator = BUFFER_u_char(http_data->recv_msg.accrual_buff);
+            const unsigned char* initial_pos = iterator;
+            const unsigned char* begin = iterator;
+            const unsigned char* end = iterator;
+            size_t accural_len = BUFFER_length(http_data->recv_msg.accrual_buff);
+
+            /* Codes_SRS_UHTTP_07_059: [ on_bytes_received shall loop throught the stored data to find the /r/n separator. ] */
+            while (iterator < (initial_pos + accural_len))
+            {
+                if (*iterator == '\r')
+                {
+                    // Don't need anything
+                    end = iterator;
+                    iterator++;
+                }
+                else if (*iterator == '\n')
+                {
+                    size_t data_length = 0;
+
+                    /* Codes_SRS_UHTTP_07_055: [ on_bytes_received shall convert the hexs length supplied in the response to the data length of the chunked data. ] */
+                    size_t hex_len = end - begin;
+                    data_length = convert_char_to_hex(begin, hex_len);
+                    if (data_length == 0)
+                    {
+                        if (accural_len - (iterator - initial_pos + 1) <= HTTP_END_TOKEN_LEN)
+                        {
+                            http_data->recv_msg.recv_state = state_send_user_callback;
+                        }
+                        else
+                        {
+                            // Need to continue parsing
+                            http_data->recv_msg.recv_state = state_process_headers;
+                        }
+                        break;
+                    }
+                    else if ((data_length + HTTP_CRLF_LEN) < accural_len - (iterator - initial_pos))
+                    {
+                        /* Codes_SRS_UHTTP_07_056: [ After the response chunk is parsed it shall be placed in a BUFFER_HANDLE. ] */
+                        iterator += 1;
+                        if (BUFFER_append_build(http_data->recv_msg.msg_body, iterator, data_length) != 0)
+                        {
+                            /* Codes_SRS_UHTTP_07_048: [ If any error is encountered on_bytes_received shall set the stop processing the request. ] */
+                            LogError("Failure building buffer for chunked data.");
+                            http_data->recv_msg.recv_state = state_error;
+                        }
+                        else
+                        {
+                            /* Codes_SRS_UHTTP_07_060: [ if the data_length specified in the chunk is beyond the amount of data recieved, the parsing shall end and wait for more data. ] */
+                            if (iterator + (data_length + HTTP_CRLF_LEN) > initial_pos + accural_len)
+                            {
+                                LogError("Invalid length specified.");
+                                http_data->recv_msg.recv_state = state_error;
+                                break;
+                            }
+                            else if (iterator + (data_length + HTTP_CRLF_LEN) == initial_pos + accural_len)
+                            {
+                                if (BUFFER_shrink(http_data->recv_msg.accrual_buff, accural_len, false) != 0)
+                                {
+                                    LogError("Failure shrinking accural buffer.");
+                                    http_data->recv_msg.recv_state = state_error;
+                                }
+                                break;
+                            }
+                            else
+                            {
+                                // Move the iterator beyond the data we read and the /r/n
+                                iterator += (data_length + HTTP_CRLF_LEN);
+                            }
+
+                            /* Codes_SRS_UHTTP_07_058: [ Once a chunk size value of 0 is encountered on_bytes_received shall call the on_request_callback with the http message ] */
+                            if (*iterator == '0' && (accural_len - (iterator - initial_pos + 1) <= HTTP_END_TOKEN_LEN))
+                            {
+                                if (accural_len - (iterator - initial_pos + 1) <= HTTP_END_TOKEN_LEN)
+                                {
+                                    http_data->recv_msg.recv_state = state_send_user_callback;
+                                }
+                                else
+                                {
+                                    // Need to continue parsing
+                                    http_data->recv_msg.recv_state = state_process_headers;
+                                }
+                                break;
+                            }
+                            else
+                            {
+                                size_t shrink_len = iterator - initial_pos;
+                                if (shrink_len > 0)
+                                {
+                                    if (BUFFER_shrink(http_data->recv_msg.accrual_buff, shrink_len, false) != 0)
+                                    {
+                                        LogError("Failure shrinking accrual buffer.");
+                                        http_data->recv_msg.recv_state = state_error;
+                                    }
+                                    else
+                                    {
+                                        accural_len = BUFFER_length(http_data->recv_msg.accrual_buff);
+                                        initial_pos = iterator = BUFFER_u_char(http_data->recv_msg.accrual_buff);
+                                    }
+                                }
+                            }
+                        }
+                        begin = end = iterator;
+                    }
+                    else
+                    {
+                        break;
+                    }
+                }
+                else
+                {
+                    end = iterator;
+                    iterator++;
+                }
+            }
+        }
+
+        if (http_data->recv_msg.recv_state == state_send_user_callback || http_data->recv_msg.recv_state == state_error)
+        {
+            const unsigned char* reply_data = NULL;
+            size_t reply_len = 0;
+            HTTP_CALLBACK_REASON http_reason = HTTP_CALLBACK_REASON_OK;
+            if (http_data->recv_msg.msg_body != NULL)
+            {
+                reply_data = BUFFER_u_char(http_data->recv_msg.msg_body);
+                reply_len = BUFFER_length(http_data->recv_msg.msg_body);
+            }
+            if (http_data->recv_msg.recv_state == state_error)
+            {
+                http_reason = HTTP_CALLBACK_REASON_PARSING_ERROR;
+            }
+            if (http_data->trace_on)
+            {
+                LOG(AZ_LOG_TRACE, LOG_LINE, "\r\nHTTP Status: %d\r\n", http_data->recv_msg.status_code);
+
+                // Loop through headers
+                size_t count;
+                if (HTTPHeaders_GetHeaderCount(http_data->recv_msg.resp_header, &count) == 0)
+                {
+                    for (size_t index = 0; index < count; index++)
+                    {
+                        char* header;
+                        if (HTTPHeaders_GetHeader(http_data->recv_msg.resp_header, index, &header) == HTTP_HEADERS_OK)
+                        {
+                            LOG(AZ_LOG_TRACE, LOG_LINE, "%s", header);
+                            free(header);
+                        }
+                    }
+                }
+                if (http_data->trace_body && reply_len > 0)
+                {
+                    LOG(AZ_LOG_TRACE, LOG_LINE, "\r\n%.*s\r\n", (int)reply_len, reply_data);
+                }
+            }
+            http_data->recv_msg.on_request_callback(http_data->recv_msg.user_ctx, http_reason, reply_data, reply_len, http_data->recv_msg.status_code, http_data->recv_msg.resp_header);
+            http_data->recv_msg.recv_state = state_parse_complete;
+        }
+
+        if (http_data->recv_msg.recv_state == state_parse_complete)
+        {
+            HTTPHeaders_Free(http_data->recv_msg.resp_header);
+            http_data->recv_msg.resp_header = NULL;
+            BUFFER_delete(http_data->recv_msg.msg_body);
+            http_data->recv_msg.msg_body = NULL;
+            BUFFER_delete(http_data->recv_msg.accrual_buff);
+            http_data->recv_msg.accrual_buff = NULL;
+        }
+    }
+}
+
+static void on_xio_close_complete(void* context)
+{
+    if (context != NULL)
+    {
+        /* Codes_SRS_UHTTP_07_045: [ If on_close_callback is not NULL, on_close_callback shall be called once the underlying xio is closed. ] */
+        HTTP_CLIENT_HANDLE_DATA* http_data = (HTTP_CLIENT_HANDLE_DATA*)context;
+        if (http_data->on_close_callback)
+        {
+            http_data->on_close_callback(http_data->close_user_ctx);
+        }
+        http_data->recv_msg.recv_state = state_closed;
+        http_data->connected = 0;
+    }
+}
+
+static void on_xio_open_complete(void* context, IO_OPEN_RESULT open_result)
+{
+    /* Codes_SRS_UHTTP_07_049: [ If not NULL uhttp_client_open shall call the on_connect callback with the callback_ctx, once the underlying xio's open is complete. ] */
+    if (context != NULL)
+    {
+        HTTP_CLIENT_HANDLE_DATA* http_data = (HTTP_CLIENT_HANDLE_DATA*)context;
+        if (open_result == IO_OPEN_OK)
+        {
+            /* Codes_SRS_UHTTP_07_042: [ If the underlying socket opens successfully the on_connect callback shall be call with HTTP_CALLBACK_REASON_OK... ] */
+            if (http_data->on_connect != NULL)
+            {
+                http_data->on_connect(http_data->connect_user_ctx, HTTP_CALLBACK_REASON_OK);
+            }
+            http_data->recv_msg.recv_state = state_open;
+            http_data->connected = 1;
+        }
+        else
+        {
+            /* Codes_SRS_UHTTP_07_043: [ Otherwise on_connect callback shall be call with HTTP_CLIENT_OPEN_REQUEST_FAILED. ] */
+            if (http_data->on_connect != NULL)
+            {
+                http_data->on_connect(http_data->connect_user_ctx, HTTP_CALLBACK_REASON_OPEN_FAILED);
+            }
+        }
+    }
+    else
+    {
+        LogError("Context on_xio_open_complete is NULL");
+    }
+}
+
+static void on_io_error(void* context)
+{
+    /* Codes_SRS_UHTTP_07_050: [ if context is NULL on_io_error shall do nothing. ] */
+    if (context != NULL)
+    {
+        HTTP_CLIENT_HANDLE_DATA* http_data = (HTTP_CLIENT_HANDLE_DATA*)context;
+        /* Codes_SRS_UHTTP_07_051: [ if on_error callback is not NULL, on_io_error shall call on_error callback. ] */
+        if (http_data->on_error)
+        {
+            http_data->on_error(http_data->error_user_ctx, HTTP_CALLBACK_REASON_ERROR);
+        }
+        http_data->connected = 0;
+    }
+    else
+    {
+        LogError("Context on_io_error is NULL");
+    }
+}
+
+static int construct_http_headers(HTTP_HEADERS_HANDLE http_header, size_t content_len, STRING_HANDLE buffData, bool chunk_data, const char* hostname, int port_num)
+{
+    (void)chunk_data;
+    int result = 0;
+    size_t headerCnt = 0;
+    if ( (http_header != NULL) && HTTPHeaders_GetHeaderCount(http_header, &headerCnt) != HTTP_HEADERS_OK)
+    {
+        LogError("Failed in HTTPHeaders_GetHeaderCount");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        bool hostname_found = false;
+        for (size_t index = 0; index < headerCnt && result == 0; index++)
+        {
+            char* header;
+            if (HTTPHeaders_GetHeader(http_header, index, &header) != HTTP_HEADERS_OK)
+            {
+                result = MU_FAILURE;
+                LogError("Failed in HTTPHeaders_GetHeader");
+            }
+            else
+            {
+                size_t dataLen = strlen(header)+2;
+                char* sendData = malloc(dataLen+1);
+                if (sendData == NULL)
+                {
+                    result = MU_FAILURE;
+                    LogError("Failed in allocating header data");
+                }
+                else
+                {
+                    if (strcmp(header, HTTP_HOST) == 0)
+                    {
+                        hostname_found = true;
+                    }
+
+                    if (snprintf(sendData, dataLen+1, "%s\r\n", header) <= 0)
+                    {
+                        result = MU_FAILURE;
+                        LogError("Failed in constructing header data");
+                    }
+                    else
+                    {
+                        if (STRING_concat(buffData, sendData) != 0)
+                        {
+                            result = MU_FAILURE;
+                            LogError("Failed in building header data");
+                        }
+                    }
+                    free(sendData);
+                }
+                free(header);
+            }
+        }
+        if (!hostname_found)
+        {
+            // calculate the size of the host header
+            size_t host_len = strlen(HTTP_HOST) + strlen(hostname) + MAX_CONTENT_LENGTH + 2;
+            char* host_header = malloc(host_len + 1);
+            if (host_header == NULL)
+            {
+                LogError("Failed allocating host header");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                if (snprintf(host_header, host_len + 1, "%s: %s:%d\r\n", HTTP_HOST, hostname, port_num) <= 0)
+                {
+                    LogError("Failed constructing host header");
+                    result = MU_FAILURE;
+                }
+                else if (STRING_concat(buffData, host_header) != 0)
+                {
+                    LogError("Failed adding the host header to the http item");
+                    result = MU_FAILURE;
+                }
+                free(host_header);
+            }
+        }
+
+        if (result == 0)
+        {
+            /* Codes_SRS_UHTTP_07_015: [uhttp_client_execute_request shall add the Content-Length to the request if the contentLength is > 0] */
+            size_t fmtLen = strlen(HTTP_CONTENT_LEN) + HTTP_CRLF_LEN + 8;
+            char* content = malloc(fmtLen+1);
+            if (content == NULL)
+            {
+                LogError("Failed allocating chunk header");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                /* Codes_SRS_UHTTP_07_015: [on_bytes_received shall add the Content-Length http header item to the request.] */
+                if (sprintf(content, "%s: %u%s", HTTP_CONTENT_LEN, (unsigned int)content_len, HTTP_CRLF_VALUE) <= 0)
+                {
+                    result = MU_FAILURE;
+                    LogError("Failed allocating content len header data");
+                }
+                else
+                {
+                    if (STRING_concat(buffData, content) != 0)
+                    {
+                        result = MU_FAILURE;
+                        LogError("Failed building content len header data");
+                    }
+                }
+                free(content);
+            }
+
+            if (STRING_concat(buffData, "\r\n") != 0)
+            {
+                result = MU_FAILURE;
+                LogError("Failed sending header finalization data");
+            }
+        }
+    }
+    return result;
+}
+
+static STRING_HANDLE construct_http_data(HTTP_CLIENT_REQUEST_TYPE request_type, const char* relative_path, STRING_HANDLE http_line)
+{
+    STRING_HANDLE result;
+
+    const char* method = (request_type == HTTP_CLIENT_REQUEST_GET) ? "GET"
+        : (request_type == HTTP_CLIENT_REQUEST_OPTIONS) ? "OPTIONS"
+        : (request_type == HTTP_CLIENT_REQUEST_POST) ? "POST"
+        : (request_type == HTTP_CLIENT_REQUEST_PUT) ? "PUT"
+        : (request_type == HTTP_CLIENT_REQUEST_DELETE) ? "DELETE"
+        : (request_type == HTTP_CLIENT_REQUEST_PATCH) ? "PATCH"
+        : NULL;
+    /* Codes_SRS_UHTTP_07_014: [If the request_type is not a valid request http_client_execute_request shall return HTTP_CLIENT_ERROR] */
+    if (method == NULL)
+    {
+        LogError("Invalid request method %s specified", method);
+        result = NULL;
+    }
+    else
+    {
+        size_t buffLen = strlen(HTTP_REQUEST_LINE_FMT) + strlen(method) + strlen(relative_path);
+        char* request = malloc(buffLen+1);
+        if (request == NULL)
+        {
+            result = NULL;
+            LogError("Failure allocating Request data");
+        }
+        else
+        {
+            if (snprintf(request, buffLen + 1, HTTP_REQUEST_LINE_FMT, method, relative_path) <= 0)
+            {
+                result = NULL;
+                LogError("Failure writing request buffer");
+            }
+            else
+            {
+                result = STRING_construct(request);
+                if (result == NULL)
+                {
+                    LogError("Failure creating buffer object");
+                }
+                else if (STRING_concat_with_STRING(result, http_line) != 0)
+                {
+                    STRING_delete(result);
+                    result = NULL;
+                    LogError("Failure writing request buffers");
+                }
+            }
+            free(request);
+        }
+    }
+    return result;
+}
+
+static int send_http_data(HTTP_CLIENT_HANDLE_DATA* http_data, HTTP_CLIENT_REQUEST_TYPE request_type, const char* relative_path,
+    STRING_HANDLE http_line)
+{
+    int result;
+    STRING_HANDLE transmit_data = construct_http_data(request_type, relative_path, http_line);
+    if (transmit_data == NULL)
+    {
+        LogError("Failure constructing http data");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        /* Tests_SRS_UHTTP_07_016: [http_client_execute_request shall transmit the http headers data through a call to xio_send;]*/
+        if (write_text_line(http_data, STRING_c_str(transmit_data) ) != 0)
+        {
+            result = MU_FAILURE;
+            LogError("Failure writing request buffer");
+        }
+        else
+        {
+            result = 0;
+        }
+        STRING_delete(transmit_data);
+    }
+    return result;
+}
+
+HTTP_CLIENT_HANDLE uhttp_client_create(const IO_INTERFACE_DESCRIPTION* io_interface_desc, const void* xio_param, ON_HTTP_ERROR_CALLBACK on_http_error, void* callback_ctx)
+{
+    HTTP_CLIENT_HANDLE_DATA* result;
+    /* Codes_SRS_UHTTP_07_002: [If io_interface_desc is NULL, uhttp_client_create shall return NULL.] */
+    if (io_interface_desc == NULL)
+    {
+        LogError("Invalid Parameter io_interface_desc is NULL");
+        result = NULL;
+    }
+    else
+    {
+        result = malloc(sizeof(HTTP_CLIENT_HANDLE_DATA));
+        if (result == NULL)
+        {
+            /* Codes_SRS_UHTTP_07_003: [If uhttp_client_create encounters any error then it shall return NULL] */
+            LogError("Failure allocating http_client_handle");
+        }
+        else
+        {
+            memset(result, 0, sizeof(HTTP_CLIENT_HANDLE_DATA) );
+            if ((result->data_list = singlylinkedlist_create() ) == NULL)
+            {
+                /* Codes_SRS_UHTTP_07_003: [If uhttp_client_create encounters any error then it shall return NULL] */
+                LogError("Failure allocating data list");
+                free(result);
+                result = NULL;
+            }
+            else if ((result->xio_handle = xio_create(io_interface_desc, xio_param) ) == NULL)
+            {
+                /* Codes_SRS_UHTTP_07_044: [ if a failure is encountered on xio_open uhttp_client_open shall return HTTP_CLIENT_OPEN_REQUEST_FAILED. ] */
+                LogError("xio create failed");
+                singlylinkedlist_destroy(result->data_list);
+                free(result);
+                result = NULL;
+            }
+            else
+            {
+                /* Codes_SRS_UHTTP_07_001: [uhttp_client_create shall return an initialize the http client handle.] */
+                result->on_error = on_http_error;
+                result->error_user_ctx = callback_ctx;
+                result->recv_msg.recv_state = state_initial;
+                result->chunk_request = false;
+                result->trace_on = false;
+            }
+        }
+    }
+    return (HTTP_CLIENT_HANDLE)result;
+}
+
+void uhttp_client_destroy(HTTP_CLIENT_HANDLE handle)
+{
+    /* Codes_SRS_UHTTP_07_004: [ If handle is NULL then uhttp_client_destroy shall do nothing ] */
+    if (handle != NULL)
+    {
+        /* Codes_SRS_UHTTP_07_005: [uhttp_client_destroy shall free any resource that is allocated in this translation unit] */
+        if(handle->host_name != NULL)
+        {
+            free(handle->host_name);
+            handle->host_name = NULL;
+        }
+        singlylinkedlist_destroy(handle->data_list);
+        xio_destroy(handle->xio_handle);
+        free(handle->certificate);
+        free(handle->x509_pk);
+        free(handle->x509_cert);
+        free(handle);
+    }
+}
+
+HTTP_CLIENT_RESULT uhttp_client_open(HTTP_CLIENT_HANDLE handle, const char* host, int port_num, ON_HTTP_OPEN_COMPLETE_CALLBACK on_connect, void* callback_ctx)
+{
+    HTTP_CLIENT_RESULT result;
+    if (handle == NULL || host == NULL)
+    {
+        /* Codes_SRS_UHTTP_07_006: [If handle, io_interface_desc or host is NULL then `uhttp_client_open` shall return HTTP_CLIENT_INVALID_ARG] */
+        LogError("Invalid handle value");
+        result = HTTP_CLIENT_INVALID_ARG;
+    }
+    else
+    {
+        HTTP_CLIENT_HANDLE_DATA* http_data = (HTTP_CLIENT_HANDLE_DATA*)handle;
+
+        if ((http_data->recv_msg.recv_state != state_initial) &&
+            (http_data->recv_msg.recv_state != state_error) &&
+            (http_data->recv_msg.recv_state != state_closed))
+        {
+            LogError("Unable to open previously open client.");
+            result = HTTP_CLIENT_INVALID_STATE;
+        }
+        else
+        {
+            if (http_data->host_name != NULL)
+            {
+                free(http_data->host_name);
+                handle->host_name = NULL;
+            }
+
+            if (mallocAndStrcpy_s(&http_data->host_name, host) != 0)
+            {
+                LogError("copying hostname has failed");
+                result = HTTP_CLIENT_ERROR;
+            }
+            /* Codes_SRS_UHTTP_07_007: [http_client_connect shall attempt to open the xio_handle. ] */
+            else
+            {
+                result = HTTP_CLIENT_OK;
+                http_data->recv_msg.recv_state = state_opening;
+                http_data->on_connect = on_connect;
+                http_data->connect_user_ctx = callback_ctx;
+                http_data->port_num = port_num;
+
+                if ((http_data->x509_cert != NULL) && (http_data->x509_pk != NULL))
+                {
+                    if ((xio_setoption(http_data->xio_handle, SU_OPTION_X509_CERT, http_data->x509_cert) != 0) ||
+                        (xio_setoption(http_data->xio_handle, SU_OPTION_X509_PRIVATE_KEY, http_data->x509_pk) != 0))
+                    {
+                        LogError("Failed setting x509 certificate");
+                        result = HTTP_CLIENT_ERROR;
+                        free(http_data->host_name);
+                        http_data->host_name = NULL;
+                        http_data->on_connect = NULL;
+                        http_data->connect_user_ctx = NULL;
+                        http_data->port_num = 0;
+                    }
+                }
+
+                if ((result == HTTP_CLIENT_OK) && (http_data->certificate != NULL))
+                {
+                    if (xio_setoption(http_data->xio_handle, OPTION_TRUSTED_CERT, http_data->certificate) != 0)
+                    {
+                        LogError("Failed setting Trusted certificate");
+                        result = HTTP_CLIENT_ERROR;
+                        free(http_data->host_name);
+                        http_data->host_name = NULL;
+                        http_data->on_connect = NULL;
+                        http_data->connect_user_ctx = NULL;
+                        http_data->port_num = 0;
+                    }
+                }
+
+                if (result == HTTP_CLIENT_OK)
+                {
+                    if (xio_open(http_data->xio_handle, on_xio_open_complete, http_data, on_bytes_received, http_data, on_io_error, http_data) != 0)
+                    {
+                        /* Codes_SRS_UHTTP_07_044: [ if a failure is encountered on xio_open uhttp_client_open shall return HTTP_CLIENT_OPEN_REQUEST_FAILED. ] */
+                        LogError("opening xio failed");
+                        free(http_data->host_name);
+                        http_data->host_name = NULL;
+                        http_data->on_connect = NULL;
+                        http_data->connect_user_ctx = NULL;
+                        http_data->port_num = 0;
+                        http_data->recv_msg.recv_state = state_error;
+
+                        result = HTTP_CLIENT_OPEN_FAILED;
+                    }
+                    else
+                    {
+                        /* Codes_SRS_UHTTP_07_008: [If http_client_connect succeeds then it shall return HTTP_CLIENT_OK] */
+                        result = HTTP_CLIENT_OK;
+                    }
+                }
+            }
+        }
+    }
+    return result;
+}
+
+void uhttp_client_close(HTTP_CLIENT_HANDLE handle, ON_HTTP_CLOSED_CALLBACK on_close_callback, void* callback_ctx)
+{
+    HTTP_CLIENT_HANDLE_DATA* http_data = (HTTP_CLIENT_HANDLE_DATA*)handle;
+    /* Codes_SRS_UHTTP_07_009: [If handle is NULL then http_client_close shall do nothing] */
+    /* Codes_SRS_UHTTP_07_049: [ If the state has been previously set to state_closed, uhttp_client_close shall do nothing. ] */
+    if (http_data != NULL && http_data->recv_msg.recv_state != state_closed && http_data->recv_msg.recv_state != state_closing)
+    {
+        http_data->on_close_callback = on_close_callback;
+        http_data->close_user_ctx = callback_ctx;
+        /* Codes_SRS_UHTTP_07_010: [If the xio_handle is NOT NULL http_client_close shall call xio_close to close the handle] */
+        (void)xio_close(http_data->xio_handle, on_xio_close_complete, http_data);
+
+        LIST_ITEM_HANDLE pending_list_item;
+        while ((pending_list_item = singlylinkedlist_get_head_item(http_data->data_list)) != NULL)
+        {
+            HTTP_SEND_DATA* send_data = (HTTP_SEND_DATA*)singlylinkedlist_item_get_value(pending_list_item);
+            if (send_data != NULL)
+            {
+                STRING_delete(send_data->relative_path);
+                BUFFER_delete(send_data->content);
+                STRING_delete(send_data->header_line);
+                free(send_data);
+            }
+            singlylinkedlist_remove(http_data->data_list, pending_list_item);
+        }
+
+        http_data->recv_msg.status_code = 0;
+        http_data->recv_msg.recv_state = state_closed;
+        http_data->recv_msg.total_body_len = 0;
+        free(http_data->host_name);
+        http_data->host_name = NULL;
+
+        /* Codes_SRS_UHTTP_07_011: [http_client_close shall free any HTTPHeader object that has not been freed] */
+        if (http_data->recv_msg.resp_header != NULL)
+        {
+            HTTPHeaders_Free(http_data->recv_msg.resp_header);
+            http_data->recv_msg.resp_header = NULL;
+        }
+        if (http_data->recv_msg.msg_body != NULL)
+        {
+            BUFFER_delete(http_data->recv_msg.msg_body);
+            http_data->recv_msg.msg_body = NULL;
+        }
+    }
+}
+
+HTTP_CLIENT_RESULT uhttp_client_execute_request(HTTP_CLIENT_HANDLE handle, HTTP_CLIENT_REQUEST_TYPE request_type, const char* relative_path,
+    HTTP_HEADERS_HANDLE http_header_handle, const unsigned char* content, size_t content_len, ON_HTTP_REQUEST_CALLBACK on_request_callback, void* callback_ctx)
+{
+    HTTP_CLIENT_RESULT result;
+    LIST_ITEM_HANDLE list_item;
+
+    /* Codes_SRS_UHTTP_07_012: [If handle, relativePath, or httpHeadersHandle is NULL then http_client_execute_request shall return HTTP_CLIENT_INVALID_ARG] */
+    if (handle == NULL || on_request_callback == NULL ||
+        (content != NULL && content_len == 0) || (content == NULL && content_len != 0) )
+    {
+        result = HTTP_CLIENT_INVALID_ARG;
+        LogError("Invalid parameter sent to execute_request");
+    }
+    else
+    {
+        HTTP_CLIENT_HANDLE_DATA* http_data = (HTTP_CLIENT_HANDLE_DATA*)handle;
+
+        http_data->recv_msg.on_request_callback = on_request_callback;
+        http_data->recv_msg.user_ctx = callback_ctx;
+        if (setup_init_recv_msg(&http_data->recv_msg) != 0)
+        {
+            /* Codes_SRS_UHTTP_07_017: [If any failure encountered http_client_execute_request shall return HTTP_CLIENT_ERROR] */
+            LogError("Failure allocating http http_data items");
+            result = HTTP_CLIENT_ERROR;
+        }
+        else
+        {
+            HTTP_SEND_DATA* send_data = (HTTP_SEND_DATA*)malloc(sizeof(HTTP_SEND_DATA));
+            if (send_data == NULL)
+            {
+                LogError("Failure allocating http data items");
+                BUFFER_delete(http_data->recv_msg.msg_body);
+                http_data->recv_msg.msg_body = NULL;
+                HTTPHeaders_Free(http_data->recv_msg.resp_header);
+                http_data->recv_msg.resp_header = NULL;
+                result = HTTP_CLIENT_ERROR;
+            }
+            else
+            {
+                memset(send_data, 0, sizeof(HTTP_SEND_DATA));
+                /* Codes_SRS_UHTTP_07_041: [HTTP_CLIENT_REQUEST_TYPE shall support all request types specified under section 9.1.2 in the spec.] */
+                send_data->request_type = request_type;
+                if ( (content_len > 0) && (send_data->content = BUFFER_create(content, content_len)) == NULL)
+                {
+                    LogError("Failure allocating content buffer");
+                    result = HTTP_CLIENT_ERROR;
+                    BUFFER_delete(http_data->recv_msg.msg_body);
+                    http_data->recv_msg.msg_body = NULL;
+                    HTTPHeaders_Free(http_data->recv_msg.resp_header);
+                    http_data->recv_msg.resp_header = NULL;
+                    free(send_data);
+                }
+                else if ((send_data->header_line = STRING_new()) == NULL)
+                {
+                    LogError("Failure allocating content buffer");
+                    result = HTTP_CLIENT_ERROR;
+                    BUFFER_delete(send_data->content);
+                    BUFFER_delete(http_data->recv_msg.msg_body);
+                    http_data->recv_msg.msg_body = NULL;
+                    HTTPHeaders_Free(http_data->recv_msg.resp_header);
+                    http_data->recv_msg.resp_header = NULL;
+                    free(send_data);
+                }
+                else if (construct_http_headers(http_header_handle, content_len, send_data->header_line, false, http_data->host_name, http_data->port_num))
+                {
+                    LogError("Failure allocating content buffer");
+                    result = HTTP_CLIENT_ERROR;
+                    BUFFER_delete(send_data->content);
+                    STRING_delete(send_data->header_line);
+                    BUFFER_delete(http_data->recv_msg.msg_body);
+                    http_data->recv_msg.msg_body = NULL;
+                    HTTPHeaders_Free(http_data->recv_msg.resp_header);
+                    http_data->recv_msg.resp_header = NULL;
+                    free(send_data);
+                }
+                else if ((list_item = singlylinkedlist_add(http_data->data_list, send_data)) == NULL)
+                {
+                    STRING_delete(send_data->header_line);
+                    BUFFER_delete(send_data->content);
+                    LogError("Failure adding send data to list");
+                    result = HTTP_CLIENT_ERROR;
+                    BUFFER_delete(http_data->recv_msg.msg_body);
+                    http_data->recv_msg.msg_body = NULL;
+                    HTTPHeaders_Free(http_data->recv_msg.resp_header);
+                    http_data->recv_msg.resp_header = NULL;
+                    free(send_data);
+                }
+                else
+                {
+                    if (relative_path != NULL)
+                    {
+                        if ((send_data->relative_path = STRING_construct(relative_path)) == NULL)
+                        {
+                            (void)singlylinkedlist_remove(http_data->data_list, list_item);
+                            STRING_delete(send_data->header_line);
+                            BUFFER_delete(send_data->content);
+                            LogError("Failure allocating relative path buffer");
+                            BUFFER_delete(http_data->recv_msg.msg_body);
+                            http_data->recv_msg.msg_body = NULL;
+                            HTTPHeaders_Free(http_data->recv_msg.resp_header);
+                            http_data->recv_msg.resp_header = NULL;
+                            free(send_data);
+                            result = HTTP_CLIENT_ERROR;
+                        }
+                        else
+                        {
+                            /* Codes_SRS_UHTTP_07_018: [upon success http_client_execute_request shall return HTTP_CLIENT_OK.] */
+                            result = HTTP_CLIENT_OK;
+                        }
+                    }
+                    else
+                    {
+                        if ((send_data->relative_path = STRING_construct("/")) == NULL)
+                        {
+                            (void)singlylinkedlist_remove(http_data->data_list, list_item);
+                            STRING_delete(send_data->header_line);
+                            BUFFER_delete(send_data->content);
+                            LogError("Failure allocating relative path buffer");
+                            BUFFER_delete(http_data->recv_msg.msg_body);
+                            http_data->recv_msg.msg_body = NULL;
+                            HTTPHeaders_Free(http_data->recv_msg.resp_header);
+                            http_data->recv_msg.resp_header = NULL;
+                            free(send_data);
+                            result = HTTP_CLIENT_ERROR;
+                        }
+                        else
+                        {
+                            /* Codes_SRS_UHTTP_07_018: [upon success http_client_execute_request shall return HTTP_CLIENT_OK.] */
+                            result = HTTP_CLIENT_OK;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return result;
+}
+
+void uhttp_client_dowork(HTTP_CLIENT_HANDLE handle)
+{
+    if (handle != NULL)
+    {
+        /* Codes_SRS_UHTTP_07_037: [http_client_dowork shall call the underlying xio_dowork function. ] */
+        HTTP_CLIENT_HANDLE_DATA* http_data = (HTTP_CLIENT_HANDLE_DATA*)handle;
+        xio_dowork(http_data->xio_handle);
+
+        // Wait till I'm connected
+        if (handle->connected == 1)
+        {
+            LIST_ITEM_HANDLE pending_list_item;
+            /* Codes_SRS_UHTTP_07_016: [http_client_dowork shall iterate through the queued Data using the xio interface to send the http request in the following ways...] */
+            while ((pending_list_item = singlylinkedlist_get_head_item(http_data->data_list)) != NULL)
+            {
+                HTTP_SEND_DATA* send_data = (HTTP_SEND_DATA*)singlylinkedlist_item_get_value(pending_list_item);
+                if (send_data != NULL)
+                {
+                    size_t content_len = BUFFER_length(send_data->content);
+                    /* Codes_SRS_UHTTP_07_052: [uhttp_client_dowork shall call xio_send to transmits the header information... ] */
+                    if (send_http_data(http_data, send_data->request_type, STRING_c_str(send_data->relative_path), send_data->header_line) != 0)
+                    {
+                        LogError("Failure writing content buffer");
+                        if (http_data->on_error)
+                        {
+                            http_data->on_error(http_data->error_user_ctx, HTTP_CALLBACK_REASON_SEND_FAILED);
+                        }
+                    }
+                    else if (content_len > 0)
+                    {
+                        /* Codes_SRS_UHTTP_07_053: [ Then uhttp_client_dowork shall use xio_send to transmit the content of the http request. ] */
+                        if (write_data_line(http_data, BUFFER_u_char(send_data->content), content_len) != 0)
+                        {
+                            LogError("Failure writing content buffer");
+                            if (http_data->on_error)
+                            {
+                                http_data->on_error(http_data->error_user_ctx, HTTP_CALLBACK_REASON_SEND_FAILED);
+                            }
+                        }
+                    }
+
+                    /* Codes_SRS_UHTTP_07_046: [ http_client_dowork shall free resouces queued to send to the http endpoint. ] */
+                    STRING_delete(send_data->relative_path);
+                    BUFFER_delete(send_data->content);
+                    STRING_delete(send_data->header_line);
+                    free(send_data);
+                }
+                (void)singlylinkedlist_remove(http_data->data_list, pending_list_item);
+            }
+        }
+    }
+}
+
+HTTP_CLIENT_RESULT uhttp_client_set_trace(HTTP_CLIENT_HANDLE handle, bool trace_on, bool trace_data)
+{
+    HTTP_CLIENT_RESULT result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_UHTTP_07_038: [If handle is NULL then http_client_set_trace shall return HTTP_CLIENT_INVALID_ARG] */
+        result = HTTP_CLIENT_INVALID_ARG;
+        LogError("invalid parameter (NULL) passed to http_client_set_trace");
+    }
+    else
+    {
+        /* Codes_SRS_UHTTP_07_039: [http_client_set_trace shall set the HTTP tracing to the trace_on variable.] */
+        handle->trace_on = trace_on;
+        handle->trace_body = trace_data;
+        /* Codes_SRS_UHTTP_07_040: [if http_client_set_trace finishes successfully then it shall return HTTP_CLIENT_OK.] */
+        result = HTTP_CLIENT_OK;
+    }
+    return result;
+}
+
+HTTP_CLIENT_RESULT uhttp_client_set_X509_cert(HTTP_CLIENT_HANDLE handle, bool ecc_type, const char* certificate, const char* private_key)
+{
+    HTTP_CLIENT_RESULT result;
+    if (handle == NULL || certificate == NULL || private_key == NULL)
+    {
+        /* Codes_SRS_UHTTP_07_038: [If handle is NULL then http_client_set_trace shall return HTTP_CLIENT_INVALID_ARG] */
+        result = HTTP_CLIENT_INVALID_ARG;
+        LogError("invalid parameter handle: %p certificate: %p private_key: %p", handle, certificate, private_key);
+    }
+    else if (handle->recv_msg.recv_state != state_initial)
+    {
+        result = HTTP_CLIENT_INVALID_STATE;
+        LogError("You must set the X509 certificates before opening the connection");
+    }
+    else
+    {
+        handle->cert_type_ecc = ecc_type;
+        if (mallocAndStrcpy_s(&handle->x509_cert, certificate) != 0)
+        {
+            result = HTTP_CLIENT_ERROR;
+            LogError("failure allocating certificate");
+        }
+        else if (mallocAndStrcpy_s(&handle->x509_pk, private_key) != 0)
+        {
+            free(handle->x509_cert);
+            handle->x509_cert = NULL;
+            result = HTTP_CLIENT_ERROR;
+            LogError("failure allocating private key");
+        }
+        else
+        {
+            result = HTTP_CLIENT_OK;
+        }
+    }
+    return result;
+}
+
+HTTP_CLIENT_RESULT uhttp_client_set_trusted_cert(HTTP_CLIENT_HANDLE handle, const char* certificate)
+{
+    HTTP_CLIENT_RESULT result;
+    if (handle == NULL || certificate == NULL)
+    {
+        /* Codes_SRS_UHTTP_07_038: [If handle is NULL then http_client_set_trace shall return HTTP_CLIENT_INVALID_ARG] */
+        result = HTTP_CLIENT_INVALID_ARG;
+        LogError("invalid parameter handle: %p certificate: %p", handle, certificate);
+    }
+    else if (handle->recv_msg.recv_state != state_initial)
+    {
+        result = HTTP_CLIENT_INVALID_STATE;
+        LogError("You must set the certificates before opening the connection");
+    }
+    else
+    {
+        if (mallocAndStrcpy_s(&handle->certificate, certificate) != 0)
+        {
+            result = HTTP_CLIENT_ERROR;
+            LogError("failure allocating certificate");
+        }
+        else
+        {
+            result = HTTP_CLIENT_OK;
+        }
+    }
+    return result;
+}
+
+const char* uhttp_client_get_trusted_cert(HTTP_CLIENT_HANDLE handle)
+{
+    const char* result;
+    if (handle == NULL)
+    {
+        result = NULL;
+        LogError("invalid parameter NULL handle");
+    }
+    else
+    {
+        result = handle->certificate;
+    }
+    return result;
+}
+
+HTTP_CLIENT_RESULT uhttp_client_set_option(HTTP_CLIENT_HANDLE handle, const char* optionName, const void* value)
+{
+    HTTP_CLIENT_RESULT result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_UHTTP_07_038: [If handle is NULL then http_client_set_trace shall return HTTP_CLIENT_INVALID_ARG] */
+        result = HTTP_CLIENT_INVALID_ARG;
+        LogError("invalid parameter handle: %p", handle);
+    }
+    else
+    {
+        int setoption_result = xio_setoption(handle->xio_handle, optionName, value);
+        if (setoption_result != 0)
+        {
+            LogError("xio_setoption fails, returns %d", setoption_result);
+            result = HTTP_CLIENT_ERROR;
+        }
+        else
+        {
+            result = HTTP_CLIENT_OK;
+        }
+
+    }
+
+    return result;
+}
+
+XIO_HANDLE uhttp_client_get_underlying_xio(HTTP_CLIENT_HANDLE handle)
+{
+    XIO_HANDLE result;
+    if (handle == NULL)
+    {
+        LogError("invalid parameter handle: %p", handle);
+        result = NULL;
+    }
+    else
+    {
+        result = handle->xio_handle;
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/umqtt/inc/azure_umqtt_c/mqtt_client.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/umqtt/inc/azure_umqtt_c/mqtt_client.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/umqtt/inc/azure_umqtt_c/mqtt_client.h	(revision 453)
@@ -0,0 +1,70 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef MQTT_CLIENT_H
+#define MQTT_CLIENT_H
+
+#include "azure_c_shared_utility/xio.h"
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_umqtt_c/mqttconst.h"
+#include "azure_umqtt_c/mqtt_message.h"
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+#include <cstdint>
+extern "C" {
+#else
+#include <stdint.h>
+#endif // __cplusplus
+
+
+typedef struct MQTT_CLIENT_TAG* MQTT_CLIENT_HANDLE;
+
+#define MQTT_CLIENT_EVENT_VALUES     \
+    MQTT_CLIENT_ON_CONNACK,          \
+    MQTT_CLIENT_ON_PUBLISH_ACK,      \
+    MQTT_CLIENT_ON_PUBLISH_RECV,     \
+    MQTT_CLIENT_ON_PUBLISH_REL,      \
+    MQTT_CLIENT_ON_PUBLISH_COMP,     \
+    MQTT_CLIENT_ON_SUBSCRIBE_ACK,    \
+    MQTT_CLIENT_ON_UNSUBSCRIBE_ACK,  \
+    MQTT_CLIENT_ON_PING_RESPONSE,    \
+    MQTT_CLIENT_ON_DISCONNECT
+
+MU_DEFINE_ENUM(MQTT_CLIENT_EVENT_RESULT, MQTT_CLIENT_EVENT_VALUES);
+
+#define MQTT_CLIENT_EVENT_ERROR_VALUES     \
+    MQTT_CLIENT_CONNECTION_ERROR,          \
+    MQTT_CLIENT_PARSE_ERROR,               \
+    MQTT_CLIENT_MEMORY_ERROR,              \
+    MQTT_CLIENT_COMMUNICATION_ERROR,       \
+    MQTT_CLIENT_NO_PING_RESPONSE,          \
+    MQTT_CLIENT_UNKNOWN_ERROR
+
+MU_DEFINE_ENUM(MQTT_CLIENT_EVENT_ERROR, MQTT_CLIENT_EVENT_ERROR_VALUES);
+
+typedef void(*ON_MQTT_OPERATION_CALLBACK)(MQTT_CLIENT_HANDLE handle, MQTT_CLIENT_EVENT_RESULT actionResult, const void* msgInfo, void* callbackCtx);
+typedef void(*ON_MQTT_ERROR_CALLBACK)(MQTT_CLIENT_HANDLE handle, MQTT_CLIENT_EVENT_ERROR error, void* callbackCtx);
+typedef void(*ON_MQTT_MESSAGE_RECV_CALLBACK)(MQTT_MESSAGE_HANDLE msgHandle, void* callbackCtx);
+typedef void(*ON_MQTT_DISCONNECTED_CALLBACK)(void* callbackCtx);
+
+MOCKABLE_FUNCTION(, MQTT_CLIENT_HANDLE, mqtt_client_init, ON_MQTT_MESSAGE_RECV_CALLBACK, msgRecv, ON_MQTT_OPERATION_CALLBACK, opCallback, void*, opCallbackCtx, ON_MQTT_ERROR_CALLBACK, onErrorCallBack, void*, errorCBCtx);
+MOCKABLE_FUNCTION(, void, mqtt_client_deinit, MQTT_CLIENT_HANDLE, handle);
+
+MOCKABLE_FUNCTION(, int, mqtt_client_connect, MQTT_CLIENT_HANDLE, handle, XIO_HANDLE, xioHandle, MQTT_CLIENT_OPTIONS*, mqttOptions);
+MOCKABLE_FUNCTION(, int, mqtt_client_disconnect, MQTT_CLIENT_HANDLE, handle, ON_MQTT_DISCONNECTED_CALLBACK, callback, void*, ctx);
+
+MOCKABLE_FUNCTION(, int, mqtt_client_subscribe, MQTT_CLIENT_HANDLE, handle, uint16_t, packetId, SUBSCRIBE_PAYLOAD*, subscribeList, size_t, count);
+MOCKABLE_FUNCTION(, int, mqtt_client_unsubscribe, MQTT_CLIENT_HANDLE, handle, uint16_t, packetId, const char**, unsubscribeList, size_t, count);
+
+MOCKABLE_FUNCTION(, int, mqtt_client_publish, MQTT_CLIENT_HANDLE, handle, MQTT_MESSAGE_HANDLE, msgHandle);
+
+MOCKABLE_FUNCTION(, void, mqtt_client_dowork, MQTT_CLIENT_HANDLE, handle);
+
+MOCKABLE_FUNCTION(, void, mqtt_client_set_trace, MQTT_CLIENT_HANDLE, handle, bool, traceOn, bool, rawBytesOn);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // MQTTCLIENT_H
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/umqtt/inc/azure_umqtt_c/mqtt_codec.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/umqtt/inc/azure_umqtt_c/mqtt_codec.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/umqtt/inc/azure_umqtt_c/mqtt_codec.h	(revision 453)
@@ -0,0 +1,48 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef MQTT_CODEC_H
+#define MQTT_CODEC_H
+
+#include "azure_c_shared_utility/xio.h"
+#include "azure_c_shared_utility/buffer_.h"
+#include "umock_c/umock_c_prod.h"
+#include "azure_umqtt_c/mqttconst.h"
+#include "azure_c_shared_utility/strings.h"
+
+#ifdef __cplusplus
+#include <cstdint>
+#include <cstddef>
+extern "C" {
+#else
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#endif // __cplusplus
+
+typedef struct MQTTCODEC_INSTANCE_TAG* MQTTCODEC_HANDLE;
+
+typedef void(*ON_PACKET_COMPLETE_CALLBACK)(void* context, CONTROL_PACKET_TYPE packet, int flags, BUFFER_HANDLE headerData);
+
+MOCKABLE_FUNCTION(, MQTTCODEC_HANDLE, mqtt_codec_create, ON_PACKET_COMPLETE_CALLBACK, packetComplete, void*, callbackCtx);
+MOCKABLE_FUNCTION(, void, mqtt_codec_destroy, MQTTCODEC_HANDLE, handle);
+
+MOCKABLE_FUNCTION(, void, mqtt_codec_reset, MQTTCODEC_HANDLE, handle);
+MOCKABLE_FUNCTION(, BUFFER_HANDLE, mqtt_codec_connect, const MQTT_CLIENT_OPTIONS*, mqttOptions, STRING_HANDLE, trace_log);
+MOCKABLE_FUNCTION(, BUFFER_HANDLE, mqtt_codec_disconnect);
+MOCKABLE_FUNCTION(, BUFFER_HANDLE, mqtt_codec_publish, QOS_VALUE, qosValue, bool, duplicateMsg, bool, serverRetain, uint16_t, packetId, const char*, topicName, const uint8_t*, msgBuffer, size_t, buffLen, STRING_HANDLE, trace_log);
+MOCKABLE_FUNCTION(, BUFFER_HANDLE, mqtt_codec_publishAck, uint16_t, packetId);
+MOCKABLE_FUNCTION(, BUFFER_HANDLE, mqtt_codec_publishReceived, uint16_t, packetId);
+MOCKABLE_FUNCTION(, BUFFER_HANDLE, mqtt_codec_publishRelease, uint16_t, packetId);
+MOCKABLE_FUNCTION(, BUFFER_HANDLE, mqtt_codec_publishComplete, uint16_t, packetId);
+MOCKABLE_FUNCTION(, BUFFER_HANDLE, mqtt_codec_ping);
+MOCKABLE_FUNCTION(, BUFFER_HANDLE, mqtt_codec_subscribe, uint16_t, packetId, SUBSCRIBE_PAYLOAD*, subscribeList, size_t, count, STRING_HANDLE, trace_log);
+MOCKABLE_FUNCTION(, BUFFER_HANDLE, mqtt_codec_unsubscribe, uint16_t, packetId, const char**, unsubscribeList, size_t, count, STRING_HANDLE, trace_log);
+
+MOCKABLE_FUNCTION(, int, mqtt_codec_bytesReceived, MQTTCODEC_HANDLE, handle, const unsigned char*, buffer, size_t, size);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // MQTT_CODEC_H
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/umqtt/inc/azure_umqtt_c/mqtt_message.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/umqtt/inc/azure_umqtt_c/mqtt_message.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/umqtt/inc/azure_umqtt_c/mqtt_message.h	(revision 453)
@@ -0,0 +1,50 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef MQTT_MESSAGE_H
+#define MQTT_MESSAGE_H
+
+#include "azure_umqtt_c/mqttconst.h"
+#include "umock_c/umock_c_prod.h"
+
+#ifdef __cplusplus
+#include <cstdint>
+#include <cstddef>
+extern "C" {
+#else
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#endif // __cplusplus
+
+typedef struct MQTT_MESSAGE_TAG* MQTT_MESSAGE_HANDLE;
+
+MOCKABLE_FUNCTION(, MQTT_MESSAGE_HANDLE, mqttmessage_create_in_place, uint16_t, packetId, const char*, topicName, QOS_VALUE, qosValue, const uint8_t*, appMsg, size_t, appMsgLength);
+MOCKABLE_FUNCTION(, MQTT_MESSAGE_HANDLE, mqttmessage_create, uint16_t, packetId, const char*, topicName, QOS_VALUE, qosValue, const uint8_t*, appMsg, size_t, appMsgLength);
+MOCKABLE_FUNCTION(,void, mqttmessage_destroy, MQTT_MESSAGE_HANDLE, handle);
+MOCKABLE_FUNCTION(,MQTT_MESSAGE_HANDLE, mqttmessage_clone, MQTT_MESSAGE_HANDLE, handle);
+
+MOCKABLE_FUNCTION(, uint16_t, mqttmessage_getPacketId, MQTT_MESSAGE_HANDLE, handle);
+MOCKABLE_FUNCTION(, const char*, mqttmessage_getTopicName, MQTT_MESSAGE_HANDLE, handle);
+
+/*
+*    @brief    Gets the individual names of the MQTT topic levels, in the original order.
+*    @param    handle    Handle to the MQTT message.
+*    @param    levels    Pointer the variable where to store the level names.
+*    @param    count     Number of levels in the topic name.
+*    @return   return    Zero if no failures occur, or non-zero otherwise.
+*/
+MOCKABLE_FUNCTION(, int, mqttmessage_getTopicLevels, MQTT_MESSAGE_HANDLE, handle, char***, levels, size_t*, count);
+
+MOCKABLE_FUNCTION(, QOS_VALUE, mqttmessage_getQosType, MQTT_MESSAGE_HANDLE, handle);
+MOCKABLE_FUNCTION(, bool, mqttmessage_getIsDuplicateMsg, MQTT_MESSAGE_HANDLE, handle);
+MOCKABLE_FUNCTION(, bool, mqttmessage_getIsRetained, MQTT_MESSAGE_HANDLE, handle);
+MOCKABLE_FUNCTION(, int, mqttmessage_setIsDuplicateMsg, MQTT_MESSAGE_HANDLE, handle, bool, duplicateMsg);
+MOCKABLE_FUNCTION(, int, mqttmessage_setIsRetained, MQTT_MESSAGE_HANDLE, handle, bool, retainMsg);
+MOCKABLE_FUNCTION(, const APP_PAYLOAD*, mqttmessage_getApplicationMsg, MQTT_MESSAGE_HANDLE, handle);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // MQTT_MESSAGE_H
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/umqtt/inc/azure_umqtt_c/mqttconst.h
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/umqtt/inc/azure_umqtt_c/mqttconst.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/umqtt/inc/azure_umqtt_c/mqttconst.h	(revision 453)
@@ -0,0 +1,111 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef MQTTCONST_H
+#define MQTTCONST_H
+
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_macro_utils/macro_utils.h"
+
+#ifdef __cplusplus
+#include <cstddef>
+#include <cstdint>
+extern "C" {
+#else
+#include <stddef.h>
+#include <stdint.h>
+#endif /* __cplusplus */
+
+#define CONTROL_PACKET_TYPE_VALUES \
+    CONNECT_TYPE, 0x10, \
+    CONNACK_TYPE, 0x20, \
+    PUBLISH_TYPE, 0x30, \
+    PUBACK_TYPE, 0x40, \
+    PUBREC_TYPE, 0x50, \
+    PUBREL_TYPE, 0x60, \
+    PUBCOMP_TYPE, 0x70, \
+    SUBSCRIBE_TYPE, 0x80, \
+    SUBACK_TYPE, 0x90, \
+    UNSUBSCRIBE_TYPE, 0xA0, \
+    UNSUBACK_TYPE, 0xB0, \
+    PINGREQ_TYPE, 0xC0, \
+    PINGRESP_TYPE, 0xD0, \
+    DISCONNECT_TYPE, 0xE0, \
+    PACKET_TYPE_ERROR, 0xE1, /* 0xE1 was assigned because ENUM_2 needs it */ \
+    UNKNOWN_TYPE, 0xE2 /* 0xE2 was assigned because ENUM_2 needs it */
+
+MU_DEFINE_ENUM_2(CONTROL_PACKET_TYPE, CONTROL_PACKET_TYPE_VALUES)
+
+#define QOS_VALUE_VALUES \
+    DELIVER_AT_MOST_ONCE, 0x00, \
+    DELIVER_AT_LEAST_ONCE, 0x01, \
+    DELIVER_EXACTLY_ONCE, 0x02, \
+    DELIVER_FAILURE, 0x80
+
+MU_DEFINE_ENUM_2(QOS_VALUE, QOS_VALUE_VALUES)
+
+typedef struct APP_PAYLOAD_TAG
+{
+    uint8_t* message;
+    size_t length;
+} APP_PAYLOAD;
+
+typedef struct MQTT_CLIENT_OPTIONS_TAG
+{
+    char* clientId;
+    char* willTopic;
+    char* willMessage;
+    char* username;
+    char* password;
+    uint16_t keepAliveInterval;
+    bool messageRetain;
+    bool useCleanSession;
+    QOS_VALUE qualityOfServiceValue;
+    bool log_trace;
+} MQTT_CLIENT_OPTIONS;
+
+typedef enum CONNECT_RETURN_CODE_TAG
+{
+    CONNECTION_ACCEPTED = 0x00,
+    CONN_REFUSED_UNACCEPTABLE_VERSION = 0x01,
+    CONN_REFUSED_ID_REJECTED = 0x02,
+    CONN_REFUSED_SERVER_UNAVAIL = 0x03,
+    CONN_REFUSED_BAD_USERNAME_PASSWORD = 0x04,
+    CONN_REFUSED_NOT_AUTHORIZED = 0x05,
+    CONN_REFUSED_UNKNOWN
+} CONNECT_RETURN_CODE;
+
+typedef struct CONNECT_ACK_TAG
+{
+    bool isSessionPresent;
+    CONNECT_RETURN_CODE returnCode;
+} CONNECT_ACK;
+
+typedef struct SUBSCRIBE_PAYLOAD_TAG
+{
+    const char* subscribeTopic;
+    QOS_VALUE qosReturn;
+} SUBSCRIBE_PAYLOAD;
+
+typedef struct SUBSCRIBE_ACK_TAG
+{
+    uint16_t packetId;
+    QOS_VALUE* qosReturn;
+    size_t qosCount;
+} SUBSCRIBE_ACK;
+
+typedef struct UNSUBSCRIBE_ACK_TAG
+{
+    uint16_t packetId;
+} UNSUBSCRIBE_ACK;
+
+typedef struct PUBLISH_ACK_TAG
+{
+    uint16_t packetId;
+} PUBLISH_ACK;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif // MQTTCONST_H
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/umqtt/src/mqtt_client.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/umqtt/src/mqtt_client.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/umqtt/src/mqtt_client.c	(revision 453)
@@ -0,0 +1,1372 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include "azure_c_shared_utility/agenttime.h"
+#include "azure_c_shared_utility/const_defines.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/platform.h"
+#include "azure_c_shared_utility/strings.h"
+#include "azure_c_shared_utility/threadapi.h"
+#include "azure_c_shared_utility/tickcounter.h"
+#include "azure_c_shared_utility/xlogging.h"
+
+#include "azure_umqtt_c/mqtt_client.h"
+#include "azure_umqtt_c/mqtt_codec.h"
+#include <inttypes.h>
+
+#define VARIABLE_HEADER_OFFSET          2
+#define RETAIN_FLAG_MASK                0x1
+#define QOS_LEAST_ONCE_FLAG_MASK        0x2
+#define QOS_EXACTLY_ONCE_FLAG_MASK      0x4
+#define DUPLICATE_FLAG_MASK             0x8
+#define CONNECT_PACKET_MASK             0xf0
+#define TIME_MAX_BUFFER                 16
+#define DEFAULT_MAX_PING_RESPONSE_TIME  80  // % of time to send pings
+#define MAX_CLOSE_RETRIES               20
+
+static const char* const TRUE_CONST = "true";
+static const char* const FALSE_CONST = "false";
+
+MU_DEFINE_ENUM_STRINGS(QOS_VALUE, QOS_VALUE_VALUES);
+
+#define MQTT_STATUS_INITIAL_STATUS      0x0000
+#define MQTT_STATUS_CLIENT_CONNECTED    0x0001
+#define MQTT_STATUS_SOCKET_CONNECTED    0x0002
+#define MQTT_STATUS_PENDING_CLOSE       0x0004
+
+#define MQTT_FLAGS_LOG_TRACE           0x0001
+#define MQTT_FLAGS_RAW_TRACE           0x0002
+
+typedef struct MQTT_CLIENT_TAG
+{
+    XIO_HANDLE xioHandle;
+    MQTTCODEC_HANDLE codec_handle;
+    CONTROL_PACKET_TYPE packetState;
+    TICK_COUNTER_HANDLE packetTickCntr;
+    tickcounter_ms_t packetSendTimeMs;
+    ON_MQTT_OPERATION_CALLBACK fnOperationCallback;
+    ON_MQTT_MESSAGE_RECV_CALLBACK fnMessageRecv;
+    void* ctx;
+    ON_MQTT_ERROR_CALLBACK fnOnErrorCallBack;
+    void* errorCBCtx;
+    ON_MQTT_DISCONNECTED_CALLBACK disconnect_cb;
+    void* disconnect_ctx;
+    QOS_VALUE qosValue;
+    uint16_t keepAliveInterval;
+    MQTT_CLIENT_OPTIONS mqttOptions;
+
+    uint16_t mqtt_status;
+    uint16_t mqtt_flags;
+
+    tickcounter_ms_t timeSincePing;
+    uint16_t maxPingRespTime;
+} MQTT_CLIENT;
+
+static bool is_trace_enabled(MQTT_CLIENT* mqtt_client)
+{
+    return (mqtt_client->mqtt_flags & MQTT_FLAGS_LOG_TRACE);
+}
+
+#ifdef ENABLE_RAW_TRACE
+static bool is_raw_trace_enabled(MQTT_CLIENT* mqtt_client)
+{
+    return (mqtt_client->mqtt_flags & MQTT_FLAGS_RAW_TRACE);
+}
+#endif // ENABLE_RAW_TRACE
+
+static void on_connection_closed(void* context)
+{
+    MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)context;
+    if (mqtt_client != NULL)
+    {
+        mqtt_client->mqtt_status &= ~MQTT_STATUS_SOCKET_CONNECTED;
+        if (mqtt_client->disconnect_cb)
+        {
+            mqtt_client->disconnect_cb(mqtt_client->disconnect_ctx);
+        }
+    }
+}
+
+static void close_connection(MQTT_CLIENT* mqtt_client)
+{
+    if (mqtt_client->mqtt_status & MQTT_STATUS_SOCKET_CONNECTED)
+    {
+        (void)xio_close(mqtt_client->xioHandle, on_connection_closed, mqtt_client);
+        if (mqtt_client->disconnect_cb == NULL)
+        {
+            size_t counter = 0;
+            do
+            {
+                xio_dowork(mqtt_client->xioHandle);
+                counter++;
+                ThreadAPI_Sleep(2);
+            } while (mqtt_client->mqtt_status & MQTT_STATUS_SOCKET_CONNECTED && counter < MAX_CLOSE_RETRIES);
+        }
+        // Clear the handle because we don't use it anymore
+        mqtt_client->xioHandle = NULL;
+    }
+    else
+    {
+        mqtt_client->mqtt_status &= ~MQTT_STATUS_SOCKET_CONNECTED;
+        if (mqtt_client->disconnect_cb)
+        {
+            mqtt_client->disconnect_cb(mqtt_client->disconnect_ctx);
+        }
+    }
+}
+
+static void set_error_callback(MQTT_CLIENT* mqtt_client, MQTT_CLIENT_EVENT_ERROR error_type)
+{
+    if (mqtt_client->fnOnErrorCallBack)
+    {
+        mqtt_client->fnOnErrorCallBack(mqtt_client, error_type, mqtt_client->errorCBCtx);
+    }
+    close_connection(mqtt_client);
+}
+
+static STRING_HANDLE construct_trace_log_handle(MQTT_CLIENT* mqtt_client)
+{
+    STRING_HANDLE trace_log;
+    if (is_trace_enabled(mqtt_client) )
+    {
+        trace_log = STRING_new();
+    }
+    else
+    {
+        trace_log = NULL;
+    }
+    return trace_log;
+}
+
+static uint16_t byteutil_read_uint16(uint8_t** buffer, size_t byteLen)
+{
+    uint16_t result = 0;
+    if (buffer != NULL && *buffer != NULL && byteLen >= 2)
+    {
+        result = 256 * (**buffer) + (*(*buffer + 1));
+        *buffer += 2; // Move the ptr
+    }
+    else
+    {
+        LogError("byteutil_read_uint16 == NULL or less than 2");
+    }
+    return result;
+}
+
+static char* byteutil_readUTF(uint8_t** buffer, size_t* byteLen)
+{
+    char* result = NULL;
+
+    const uint8_t* bufferInitial = *buffer;
+    // Get the length of the string
+    uint16_t stringLen = byteutil_read_uint16(buffer, *byteLen);
+    // Verify that byteutil_read_uint16 succeeded (by stringLen>0) and that we're
+    // not being asked to read a string longer than buffer passed in.
+    if ((stringLen > 0) && ((size_t)(stringLen + (*buffer - bufferInitial)) <= *byteLen))
+    {
+        result = (char*)malloc(stringLen + 1);
+        if (result != NULL)
+        {
+            (void)memcpy(result, *buffer, stringLen);
+            result[stringLen] = '\0';
+            *buffer += stringLen;
+            *byteLen = stringLen;
+         }
+    }
+    else
+    {
+        LogError("String passed not a valid UTF.");
+    }
+
+    return result;
+}
+
+static uint8_t byteutil_readByte(uint8_t** buffer)
+{
+    uint8_t result = 0;
+    if (buffer != NULL)
+    {
+        result = **buffer;
+        (*buffer)++;
+    }
+    else
+    {
+        LogError("readByte buffer == NULL.");
+    }
+    return result;
+}
+
+static void sendComplete(void* context, IO_SEND_RESULT send_result)
+{
+    MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)context;
+    if (mqtt_client != NULL)
+    {
+        if (send_result == IO_SEND_OK)
+        {
+            if (mqtt_client->packetState == DISCONNECT_TYPE)
+            {
+                /*Codes_SRS_MQTT_CLIENT_07_032: [If the actionResult parameter is of type MQTT_CLIENT_ON_DISCONNECT the the msgInfo value shall be NULL.]*/
+                if (mqtt_client->fnOperationCallback != NULL)
+                {
+                    mqtt_client->fnOperationCallback(mqtt_client, MQTT_CLIENT_ON_DISCONNECT, NULL, mqtt_client->ctx);
+                }
+
+                // Mark to close
+                mqtt_client->mqtt_status |= MQTT_STATUS_PENDING_CLOSE;
+            }
+        }
+        else if (send_result == IO_SEND_ERROR)
+        {
+            LogError("MQTT Send Complete Failure send_result: %d", (int)send_result);
+            set_error_callback(mqtt_client, MQTT_CLIENT_COMMUNICATION_ERROR);
+        }
+    }
+    else
+    {
+        LogError("MQTT Send Complete Failure with NULL mqtt_client");
+    }
+}
+
+#ifndef NO_LOGGING
+static void getLogTime(char* timeResult, size_t len)
+{
+    if (timeResult != NULL)
+    {
+        time_t agent_time = get_time(NULL);
+        if (agent_time == (time_t)-1)
+        {
+            timeResult[0] = '\0';
+        }
+        else
+        {
+            struct tm* tmInfo = localtime(&agent_time);
+            if (tmInfo == NULL)
+            {
+                timeResult[0] = '\0';
+            }
+            else
+            {
+                if (strftime(timeResult, len, "%H:%M:%S", tmInfo) == 0)
+                {
+                    timeResult[0] = '\0';
+                }
+            }
+        }
+    }
+}
+
+#ifdef ENABLE_RAW_TRACE
+static const char* retrievePacketType(CONTROL_PACKET_TYPE packet)
+{
+    switch (packet&CONNECT_PACKET_MASK)
+    {
+        case CONNECT_TYPE: return "CONNECT";
+        case CONNACK_TYPE:  return "CONNACK";
+        case PUBLISH_TYPE:  return "PUBLISH";
+        case PUBACK_TYPE:  return "PUBACK";
+        case PUBREC_TYPE:  return "PUBREC";
+        case PUBREL_TYPE:  return "PUBREL";
+        case SUBSCRIBE_TYPE:  return "SUBSCRIBE";
+        case SUBACK_TYPE:  return "SUBACK";
+        case UNSUBSCRIBE_TYPE:  return "UNSUBSCRIBE";
+        case UNSUBACK_TYPE:  return "UNSUBACK";
+        case PINGREQ_TYPE:  return "PINGREQ";
+        case PINGRESP_TYPE:  return "PINGRESP";
+        case DISCONNECT_TYPE:  return "DISCONNECT";
+        default:
+        case PACKET_TYPE_ERROR:
+        case UNKNOWN_TYPE:
+            return "UNKNOWN";
+    }
+}
+
+static void logOutgoingRawTrace(MQTT_CLIENT* mqtt_client, const uint8_t* data, size_t length)
+{
+    if (mqtt_client != NULL && data != NULL && length > 0 && is_raw_trace_enabled(mqtt_client))
+    {
+        char tmBuffer[TIME_MAX_BUFFER];
+        getLogTime(tmBuffer, TIME_MAX_BUFFER);
+
+        LOG(AZ_LOG_TRACE, 0, "-> %s %s: ", tmBuffer, retrievePacketType((unsigned char)data[0]));
+        size_t index = 0;
+        for (index = 0; index < length; index++)
+        {
+            LOG(AZ_LOG_TRACE, 0, "0x%02x ", data[index]);
+        }
+        LOG(AZ_LOG_TRACE, LOG_LINE, " ");
+    }
+}
+
+static void logIncomingRawTrace(MQTT_CLIENT* mqtt_client, CONTROL_PACKET_TYPE packet, uint8_t flags, const uint8_t* data, size_t length)
+{
+    if (mqtt_client != NULL && is_raw_trace_enabled(mqtt_client))
+    {
+        if (data != NULL && length > 0)
+        {
+            char tmBuffer[TIME_MAX_BUFFER];
+            getLogTime(tmBuffer, TIME_MAX_BUFFER);
+
+            LOG(AZ_LOG_TRACE, 0, "<- %s %s: 0x%02x 0x%02x ", tmBuffer, retrievePacketType((CONTROL_PACKET_TYPE)packet), (unsigned int)(packet | flags), (unsigned int)length);
+            size_t index = 0;
+            for (index = 0; index < length; index++)
+            {
+                LOG(AZ_LOG_TRACE, 0, "0x%02x ", data[index]);
+            }
+            LOG(AZ_LOG_TRACE, LOG_LINE, " ");
+        }
+        else if (packet == PINGRESP_TYPE)
+        {
+            char tmBuffer[TIME_MAX_BUFFER];
+            getLogTime(tmBuffer, TIME_MAX_BUFFER);
+            LOG(AZ_LOG_TRACE, LOG_LINE, "<- %s %s: 0x%02x 0x%02x ", tmBuffer, retrievePacketType((CONTROL_PACKET_TYPE)packet), (unsigned int)(packet | flags), (unsigned int)length);
+        }
+    }
+}
+#endif // ENABLE_RAW_TRACE
+
+static void log_outgoing_trace(MQTT_CLIENT* mqtt_client, STRING_HANDLE trace_log)
+{
+    if (mqtt_client != NULL && is_trace_enabled(mqtt_client) && trace_log != NULL)
+    {
+        char tmBuffer[TIME_MAX_BUFFER];
+        getLogTime(tmBuffer, TIME_MAX_BUFFER);
+        LOG(AZ_LOG_TRACE, LOG_LINE, "-> %s %s", tmBuffer, STRING_c_str(trace_log));
+    }
+}
+
+static void log_incoming_trace(MQTT_CLIENT* mqtt_client, STRING_HANDLE trace_log)
+{
+    if (mqtt_client != NULL && is_trace_enabled(mqtt_client) && trace_log != NULL)
+    {
+        char tmBuffer[TIME_MAX_BUFFER];
+        getLogTime(tmBuffer, TIME_MAX_BUFFER);
+        LOG(AZ_LOG_TRACE, LOG_LINE, "<- %s %s", tmBuffer, STRING_c_str(trace_log) );
+    }
+}
+#else // NO_LOGGING
+static void logOutgoingRawTrace(MQTT_CLIENT* mqtt_client, const uint8_t* data, size_t length)
+{
+    AZURE_UNREFERENCED_PARAMETER(mqtt_client);
+    AZURE_UNREFERENCED_PARAMETER(data);
+    AZURE_UNREFERENCED_PARAMETER(length);
+}
+
+static void log_outgoing_trace(MQTT_CLIENT* mqtt_client, STRING_HANDLE trace_log)
+{
+    AZURE_UNREFERENCED_PARAMETER(mqtt_client);
+    AZURE_UNREFERENCED_PARAMETER(trace_log);
+}
+
+static void log_incoming_trace(MQTT_CLIENT* mqtt_client, STRING_HANDLE trace_log)
+{
+    AZURE_UNREFERENCED_PARAMETER(mqtt_client);
+    AZURE_UNREFERENCED_PARAMETER(trace_log);
+}
+
+static void logIncomingRawTrace(MQTT_CLIENT* mqtt_client, CONTROL_PACKET_TYPE packet, uint8_t flags, const uint8_t* data, size_t length)
+{
+    AZURE_UNREFERENCED_PARAMETER(mqtt_client);
+    AZURE_UNREFERENCED_PARAMETER(packet);
+    AZURE_UNREFERENCED_PARAMETER(flags);
+    AZURE_UNREFERENCED_PARAMETER(data);
+    AZURE_UNREFERENCED_PARAMETER(length);
+}
+#endif // NO_LOGGING
+
+static int sendPacketItem(MQTT_CLIENT* mqtt_client, const unsigned char* data, size_t length)
+{
+    int result;
+
+    if (tickcounter_get_current_ms(mqtt_client->packetTickCntr, &mqtt_client->packetSendTimeMs) != 0)
+    {
+        LogError("Failure getting current ms tickcounter");
+        result = MU_FAILURE;
+    }
+    else
+    {
+        result = xio_send(mqtt_client->xioHandle, (const void*)data, length, sendComplete, mqtt_client);
+        if (result != 0)
+        {
+            LogError("Failure sending control packet data");
+            result = MU_FAILURE;
+        }
+        else
+        {
+#ifdef ENABLE_RAW_TRACE
+            logOutgoingRawTrace(mqtt_client, (const uint8_t*)data, length);
+#endif
+        }
+    }
+    return result;
+}
+
+static void onOpenComplete(void* context, IO_OPEN_RESULT open_result)
+{
+    MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)context;
+    if (mqtt_client != NULL)
+    {
+        if (open_result == IO_OPEN_OK && !(mqtt_client->mqtt_status & MQTT_STATUS_SOCKET_CONNECTED))
+        {
+            mqtt_client->packetState = CONNECT_TYPE;
+            mqtt_client->mqtt_status |= MQTT_STATUS_SOCKET_CONNECTED;
+
+            STRING_HANDLE trace_log = construct_trace_log_handle(mqtt_client);
+
+            // Send the Connect packet
+            BUFFER_HANDLE connPacket = mqtt_codec_connect(&mqtt_client->mqttOptions, trace_log);
+            if (connPacket == NULL)
+            {
+                LogError("Error: mqtt_codec_connect failed");
+            }
+            else
+            {
+                size_t size = BUFFER_length(connPacket);
+                /*Codes_SRS_MQTT_CLIENT_07_009: [On success mqtt_client_connect shall send the MQTT CONNECT to the endpoint.]*/
+                if (sendPacketItem(mqtt_client, BUFFER_u_char(connPacket), size) != 0)
+                {
+                    LogError("Error: failure sending connect packet");
+                    // Set the status to pending close because we connot continue
+                    // with CONN failing to send
+                    if (mqtt_client->fnOnErrorCallBack)
+                    {
+                        mqtt_client->fnOnErrorCallBack(mqtt_client, MQTT_CLIENT_CONNECTION_ERROR, mqtt_client->errorCBCtx);
+                    }
+                    mqtt_client->mqtt_status |= MQTT_STATUS_PENDING_CLOSE;
+                }
+                else
+                {
+                    log_outgoing_trace(mqtt_client, trace_log);
+                }
+                BUFFER_delete(connPacket);
+            }
+            if (trace_log != NULL)
+            {
+                STRING_delete(trace_log);
+            }
+        }
+        else
+        {
+            LogError("Error: failure opening connection to endpoint");
+            if (!(mqtt_client->mqtt_status & MQTT_STATUS_SOCKET_CONNECTED) && mqtt_client->fnOnErrorCallBack)
+            {
+                mqtt_client->fnOnErrorCallBack(mqtt_client, MQTT_CLIENT_CONNECTION_ERROR, mqtt_client->errorCBCtx);
+            }
+            mqtt_client->mqtt_status |= MQTT_STATUS_PENDING_CLOSE;
+        }
+    }
+    else
+    {
+        LogError("Error: mqtt_client is NULL");
+    }
+}
+
+static void onBytesReceived(void* context, const unsigned char* buffer, size_t size)
+{
+    MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)context;
+    if (mqtt_client != NULL)
+    {
+        if (mqtt_codec_bytesReceived(mqtt_client->codec_handle, buffer, size) != 0)
+        {
+            mqtt_codec_reset(mqtt_client->codec_handle);
+            set_error_callback(mqtt_client, MQTT_CLIENT_PARSE_ERROR);
+        }
+    }
+    else
+    {
+        LogError("Error: mqtt_client is NULL");
+    }
+}
+
+static void onIoError(void* context)
+{
+    MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)context;
+    if (mqtt_client != NULL && mqtt_client->fnOperationCallback)
+    {
+        /*Codes_SRS_MQTT_CLIENT_07_032: [If the actionResult parameter is of type MQTT_CLIENT_ON_DISCONNECT the the msgInfo value shall be NULL.]*/
+        /* Codes_SRS_MQTT_CLIENT_07_036: [ If an error is encountered by the ioHandle the mqtt_client shall call xio_close. ] */
+        set_error_callback(mqtt_client, MQTT_CLIENT_CONNECTION_ERROR);
+    }
+    else
+    {
+        LogError("Error invalid parameter: mqtt_client: %p", mqtt_client);
+    }
+}
+
+static void clear_mqtt_options(MQTT_CLIENT* mqtt_client)
+{
+    if (mqtt_client->mqttOptions.clientId != NULL)
+    {
+        free(mqtt_client->mqttOptions.clientId);
+        mqtt_client->mqttOptions.clientId = NULL;
+    }
+
+    if (mqtt_client->mqttOptions.willTopic != NULL)
+    {
+        free(mqtt_client->mqttOptions.willTopic);
+        mqtt_client->mqttOptions.willTopic = NULL;
+    }
+
+    if (mqtt_client->mqttOptions.willMessage != NULL)
+    {
+        free(mqtt_client->mqttOptions.willMessage);
+        mqtt_client->mqttOptions.willMessage = NULL;
+    }
+
+    if (mqtt_client->mqttOptions.username != NULL)
+    {
+        free(mqtt_client->mqttOptions.username);
+        mqtt_client->mqttOptions.username = NULL;
+    }
+
+    if (mqtt_client->mqttOptions.password != NULL)
+    {
+        free(mqtt_client->mqttOptions.password);
+        mqtt_client->mqttOptions.password = NULL;
+    }
+}
+
+static int cloneMqttOptions(MQTT_CLIENT* mqtt_client, const MQTT_CLIENT_OPTIONS* mqttOptions)
+{
+    int result = 0;
+    char* temp_option;
+
+    if (mqttOptions->clientId != NULL)
+    {
+        if (mallocAndStrcpy_s(&temp_option, mqttOptions->clientId) != 0)
+        {
+            result = MU_FAILURE;
+            LogError("mallocAndStrcpy_s clientId");
+        }
+        else
+        {
+            if (mqtt_client->mqttOptions.clientId != NULL)
+            {
+                free(mqtt_client->mqttOptions.clientId);
+            }
+            mqtt_client->mqttOptions.clientId = temp_option;
+        }
+    }
+    if (result == 0 && mqttOptions->willTopic != NULL)
+    {
+        temp_option = NULL;
+        if (mallocAndStrcpy_s(&temp_option, mqttOptions->willTopic) != 0)
+        {
+            result = MU_FAILURE;
+            LogError("mallocAndStrcpy_s willTopic");
+        }
+        else
+        {
+            if (mqtt_client->mqttOptions.willTopic != NULL)
+            {
+                free(mqtt_client->mqttOptions.willTopic);
+            }
+            mqtt_client->mqttOptions.willTopic = temp_option;
+        }
+    }
+    if (result == 0 && mqttOptions->willMessage != NULL)
+    {
+        temp_option = NULL;
+        if (mallocAndStrcpy_s(&temp_option, mqttOptions->willMessage) != 0)
+        {
+            LogError("mallocAndStrcpy_s willMessage");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if (mqtt_client->mqttOptions.willMessage != NULL)
+            {
+                free(mqtt_client->mqttOptions.willMessage);
+            }
+            mqtt_client->mqttOptions.willMessage = temp_option;
+        }
+    }
+    if (result == 0 && mqttOptions->username != NULL)
+    {
+        temp_option = NULL;
+        if (mallocAndStrcpy_s(&temp_option, mqttOptions->username) != 0)
+        {
+            LogError("mallocAndStrcpy_s username");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if (mqtt_client->mqttOptions.username != NULL)
+            {
+                free(mqtt_client->mqttOptions.username);
+            }
+            mqtt_client->mqttOptions.username = temp_option;
+        }
+    }
+    if (result == 0 && mqttOptions->password != NULL)
+    {
+        temp_option = NULL;
+        if (mallocAndStrcpy_s(&temp_option, mqttOptions->password) != 0)
+        {
+            LogError("mallocAndStrcpy_s password");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if (mqtt_client->mqttOptions.password != NULL)
+            {
+                free(mqtt_client->mqttOptions.password);
+            }
+            mqtt_client->mqttOptions.password = temp_option;
+        }
+    }
+    if (result == 0)
+    {
+        mqtt_client->mqttOptions.keepAliveInterval = mqttOptions->keepAliveInterval;
+        mqtt_client->mqttOptions.messageRetain = mqttOptions->messageRetain;
+        mqtt_client->mqttOptions.useCleanSession = mqttOptions->useCleanSession;
+        mqtt_client->mqttOptions.qualityOfServiceValue = mqttOptions->qualityOfServiceValue;
+    }
+    else
+    {
+        clear_mqtt_options(mqtt_client);
+    }
+    return result;
+}
+
+static void ProcessPublishMessage(MQTT_CLIENT* mqtt_client, uint8_t* initialPos, size_t packetLength, int flags)
+{
+    bool isDuplicateMsg = (flags & DUPLICATE_FLAG_MASK) ? true : false;
+    bool isRetainMsg = (flags & RETAIN_FLAG_MASK) ? true : false;
+    QOS_VALUE qosValue = (flags == 0) ? DELIVER_AT_MOST_ONCE : (flags & QOS_LEAST_ONCE_FLAG_MASK) ? DELIVER_AT_LEAST_ONCE : DELIVER_EXACTLY_ONCE;
+
+    uint8_t* iterator = initialPos;
+    size_t numberOfBytesToBeRead = packetLength;
+    size_t lengthOfTopicName = numberOfBytesToBeRead;
+    char* topicName = byteutil_readUTF(&iterator, &lengthOfTopicName);
+    if (topicName == NULL)
+    {
+        LogError("Publish MSG: failure reading topic name");
+        set_error_callback(mqtt_client, MQTT_CLIENT_PARSE_ERROR);
+    }
+    else
+    {
+        STRING_HANDLE trace_log = NULL;
+
+#ifndef NO_LOGGING
+        if (is_trace_enabled(mqtt_client))
+        {
+            trace_log = STRING_construct_sprintf("PUBLISH | IS_DUP: %s | RETAIN: %d | QOS: %s | TOPIC_NAME: %s", isDuplicateMsg ? TRUE_CONST : FALSE_CONST,
+                isRetainMsg ? 1 : 0, MU_ENUM_TO_STRING(QOS_VALUE, qosValue), topicName);
+        }
+#endif
+        uint16_t packetId = 0;
+        numberOfBytesToBeRead = packetLength - (iterator - initialPos);
+        if (qosValue != DELIVER_AT_MOST_ONCE)
+        {
+            packetId = byteutil_read_uint16(&iterator, numberOfBytesToBeRead);
+#ifndef NO_LOGGING
+            if (is_trace_enabled(mqtt_client))
+            {
+                STRING_sprintf(trace_log, " | PACKET_ID: %"PRIu16, packetId);
+            }
+#endif
+        }
+        if ((qosValue != DELIVER_AT_MOST_ONCE) && (packetId == 0))
+        {
+            LogError("Publish MSG: packetId=0, invalid");
+            set_error_callback(mqtt_client, MQTT_CLIENT_PARSE_ERROR);
+        }
+        else
+        {
+            numberOfBytesToBeRead = packetLength - (iterator - initialPos);
+
+            MQTT_MESSAGE_HANDLE msgHandle = mqttmessage_create_in_place(packetId, topicName, qosValue, iterator, numberOfBytesToBeRead);
+            if (msgHandle == NULL)
+            {
+                LogError("failure in mqttmessage_create");
+                set_error_callback(mqtt_client, MQTT_CLIENT_MEMORY_ERROR);
+            }
+            else if (mqttmessage_setIsDuplicateMsg(msgHandle, isDuplicateMsg) != 0 ||
+                     mqttmessage_setIsRetained(msgHandle, isRetainMsg) != 0)
+            {
+                LogError("failure setting mqtt message property");
+                set_error_callback(mqtt_client, MQTT_CLIENT_MEMORY_ERROR);
+            }
+            else
+            {
+#ifndef NO_LOGGING
+                if (is_trace_enabled(mqtt_client))
+                {
+                    STRING_sprintf(trace_log, " | PAYLOAD_LEN: %lu", (unsigned long)numberOfBytesToBeRead);
+                    log_incoming_trace(mqtt_client, trace_log);
+                }
+#endif
+                mqtt_client->fnMessageRecv(msgHandle, mqtt_client->ctx);
+
+                BUFFER_HANDLE pubRel = NULL;
+                if (qosValue == DELIVER_EXACTLY_ONCE)
+                {
+                    pubRel = mqtt_codec_publishReceived(packetId);
+                    if (pubRel == NULL)
+                    {
+                        LogError("Failed to allocate publish receive message.");
+                        set_error_callback(mqtt_client, MQTT_CLIENT_MEMORY_ERROR);
+                    }
+                }
+                else if (qosValue == DELIVER_AT_LEAST_ONCE)
+                {
+                    pubRel = mqtt_codec_publishAck(packetId);
+                    if (pubRel == NULL)
+                    {
+                        LogError("Failed to allocate publish ack message.");
+                        set_error_callback(mqtt_client, MQTT_CLIENT_MEMORY_ERROR);
+                    }
+                }
+                if (pubRel != NULL)
+                {
+                    size_t size = BUFFER_length(pubRel);
+                    if (sendPacketItem(mqtt_client, BUFFER_u_char(pubRel), size) != 0)
+                    {
+                        LogError("Failed sending publish reply.");
+                        set_error_callback(mqtt_client, MQTT_CLIENT_COMMUNICATION_ERROR);
+                    }
+                    BUFFER_delete(pubRel);
+                }
+            }
+            mqttmessage_destroy(msgHandle);
+        }
+
+        if (trace_log != NULL)
+        {
+            STRING_delete(trace_log);
+        }
+
+        free(topicName);
+    }
+}
+
+static void recvCompleteCallback(void* context, CONTROL_PACKET_TYPE packet, int flags, BUFFER_HANDLE headerData)
+{
+    MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)context;
+    if (mqtt_client != NULL)
+    {
+        size_t packetLength = 0;
+        uint8_t* iterator = NULL;
+        if (headerData != NULL)
+        {
+            packetLength = BUFFER_length(headerData);
+            iterator = BUFFER_u_char(headerData);
+        }
+
+#ifdef ENABLE_RAW_TRACE
+        logIncomingRawTrace(mqtt_client, packet, (uint8_t)flags, iterator, packetLength);
+#endif
+        if ((iterator != NULL && packetLength > 0) || packet == PINGRESP_TYPE)
+        {
+            switch (packet)
+            {
+                case CONNACK_TYPE:
+                {
+                    /*Codes_SRS_MQTT_CLIENT_07_028: [If the actionResult parameter is of type CONNECT_ACK then the msgInfo value shall be a CONNECT_ACK structure.]*/
+                    CONNECT_ACK connack = { 0 };
+                    connack.isSessionPresent = (byteutil_readByte(&iterator) == 0x1) ? true : false;
+                    uint8_t rc = byteutil_readByte(&iterator);
+                    connack.returnCode =
+                        (rc < ((uint8_t)CONN_REFUSED_UNKNOWN)) ?
+                        (CONNECT_RETURN_CODE)rc : CONN_REFUSED_UNKNOWN;
+
+#ifndef NO_LOGGING
+                    if (is_trace_enabled(mqtt_client))
+                    {
+                        STRING_HANDLE trace_log = STRING_construct_sprintf("CONNACK | SESSION_PRESENT: %s | RETURN_CODE: 0x%x", connack.isSessionPresent ? TRUE_CONST : FALSE_CONST, connack.returnCode);
+                        log_incoming_trace(mqtt_client, trace_log);
+                        STRING_delete(trace_log);
+                    }
+#endif
+                    mqtt_client->fnOperationCallback(mqtt_client, MQTT_CLIENT_ON_CONNACK, (void*)&connack, mqtt_client->ctx);
+
+                    if (connack.returnCode == CONNECTION_ACCEPTED)
+                    {
+                        mqtt_client->mqtt_status |= MQTT_STATUS_CLIENT_CONNECTED;
+                    }
+                    break;
+                }
+                case PUBLISH_TYPE:
+                {
+                    ProcessPublishMessage(mqtt_client, iterator, packetLength, flags);
+                    break;
+                }
+                case PUBACK_TYPE:
+                case PUBREC_TYPE:
+                case PUBREL_TYPE:
+                case PUBCOMP_TYPE:
+                {
+                    /*Codes_SRS_MQTT_CLIENT_07_029: [If the actionResult parameter are of types PUBACK_TYPE, PUBREC_TYPE, PUBREL_TYPE or PUBCOMP_TYPE then the msgInfo value shall be a PUBLISH_ACK structure.]*/
+                    MQTT_CLIENT_EVENT_RESULT action = (packet == PUBACK_TYPE) ? MQTT_CLIENT_ON_PUBLISH_ACK :
+                        (packet == PUBREC_TYPE) ? MQTT_CLIENT_ON_PUBLISH_RECV :
+                        (packet == PUBREL_TYPE) ? MQTT_CLIENT_ON_PUBLISH_REL : MQTT_CLIENT_ON_PUBLISH_COMP;
+
+                    PUBLISH_ACK publish_ack = { 0 };
+                    publish_ack.packetId = byteutil_read_uint16(&iterator, packetLength);
+
+#ifndef NO_LOGGING
+                    if (is_trace_enabled(mqtt_client))
+                    {
+                        STRING_HANDLE trace_log = STRING_construct_sprintf("%s | PACKET_ID: %"PRIu16, packet == PUBACK_TYPE ? "PUBACK" : (packet == PUBREC_TYPE) ? "PUBREC" : (packet == PUBREL_TYPE) ? "PUBREL" : "PUBCOMP",
+                            publish_ack.packetId);
+
+                        log_incoming_trace(mqtt_client, trace_log);
+                        STRING_delete(trace_log);
+                    }
+#endif
+                    BUFFER_HANDLE pubRel = NULL;
+                    mqtt_client->fnOperationCallback(mqtt_client, action, (void*)&publish_ack, mqtt_client->ctx);
+                    if (packet == PUBREC_TYPE)
+                    {
+                        pubRel = mqtt_codec_publishRelease(publish_ack.packetId);
+                        if (pubRel == NULL)
+                        {
+                            LogError("Failed to allocate publish release message.");
+                            set_error_callback(mqtt_client, MQTT_CLIENT_MEMORY_ERROR);
+                        }
+                    }
+                    else if (packet == PUBREL_TYPE)
+                    {
+                        pubRel = mqtt_codec_publishComplete(publish_ack.packetId);
+                        if (pubRel == NULL)
+                        {
+                            LogError("Failed to allocate publish complete message.");
+                            set_error_callback(mqtt_client, MQTT_CLIENT_MEMORY_ERROR);
+                        }
+                    }
+                    if (pubRel != NULL)
+                    {
+                        size_t size = BUFFER_length(pubRel);
+                        if (sendPacketItem(mqtt_client, BUFFER_u_char(pubRel), size) != 0)
+                        {
+                            LogError("Failed sending publish reply.");
+                            set_error_callback(mqtt_client, MQTT_CLIENT_COMMUNICATION_ERROR);
+                        }
+                        BUFFER_delete(pubRel);
+                    }
+                    break;
+                }
+                case SUBACK_TYPE:
+                {
+
+                    /*Codes_SRS_MQTT_CLIENT_07_030: [If the actionResult parameter is of type SUBACK_TYPE then the msgInfo value shall be a SUBSCRIBE_ACK structure.]*/
+                    SUBSCRIBE_ACK suback = { 0 };
+
+                    size_t remainLen = packetLength;
+                    suback.packetId = byteutil_read_uint16(&iterator, packetLength);
+                    remainLen -= 2;
+
+#ifndef NO_LOGGING
+                    STRING_HANDLE trace_log = NULL;
+                    if (is_trace_enabled(mqtt_client))
+                    {
+                        trace_log = STRING_construct_sprintf("SUBACK | PACKET_ID: %"PRIu16, suback.packetId);
+                    }
+#endif
+                    // Allocate the remaining len
+                    suback.qosReturn = (QOS_VALUE*)malloc(sizeof(QOS_VALUE)*remainLen);
+                    if (suback.qosReturn != NULL)
+                    {
+                        while (remainLen > 0)
+                        {
+                            uint8_t qosRet = byteutil_readByte(&iterator);
+                            suback.qosReturn[suback.qosCount++] =
+                                (qosRet <= ((uint8_t)DELIVER_EXACTLY_ONCE)) ?
+                                (QOS_VALUE)qosRet :  DELIVER_FAILURE;
+                            remainLen--;
+#ifndef NO_LOGGING
+                            if (is_trace_enabled(mqtt_client))
+                            {
+                                STRING_sprintf(trace_log, " | RETURN_CODE: %"PRIu16, suback.qosReturn[suback.qosCount-1]);
+                            }
+#endif
+                        }
+
+#ifndef NO_LOGGING
+                        if (is_trace_enabled(mqtt_client))
+                        {
+                            log_incoming_trace(mqtt_client, trace_log);
+                            STRING_delete(trace_log);
+                        }
+#endif
+                        mqtt_client->fnOperationCallback(mqtt_client, MQTT_CLIENT_ON_SUBSCRIBE_ACK, (void*)&suback, mqtt_client->ctx);
+                        free(suback.qosReturn);
+                    }
+                    else
+                    {
+                        LogError("allocation of quality of service value failed.");
+                        set_error_callback(mqtt_client, MQTT_CLIENT_MEMORY_ERROR);
+                    }
+                    break;
+                }
+                case UNSUBACK_TYPE:
+                {
+                    /*Codes_SRS_MQTT_CLIENT_07_031: [If the actionResult parameter is of type UNSUBACK_TYPE then the msgInfo value shall be a UNSUBSCRIBE_ACK structure.]*/
+                    UNSUBSCRIBE_ACK unsuback = { 0 };
+                    unsuback.packetId = byteutil_read_uint16(&iterator, packetLength);
+
+#ifndef NO_LOGGING
+                    if (is_trace_enabled(mqtt_client))
+                    {
+                        STRING_HANDLE trace_log = STRING_construct_sprintf("UNSUBACK | PACKET_ID: %"PRIu16, unsuback.packetId);
+                        log_incoming_trace(mqtt_client, trace_log);
+                        STRING_delete(trace_log);
+                    }
+#endif
+                    mqtt_client->fnOperationCallback(mqtt_client, MQTT_CLIENT_ON_UNSUBSCRIBE_ACK, (void*)&unsuback, mqtt_client->ctx);
+                    break;
+                }
+                case PINGRESP_TYPE:
+                    mqtt_client->timeSincePing = 0;
+#ifndef NO_LOGGING
+                    if (is_trace_enabled(mqtt_client))
+                    {
+                        STRING_HANDLE trace_log = STRING_construct_sprintf("PINGRESP");
+                        log_incoming_trace(mqtt_client, trace_log);
+                        STRING_delete(trace_log);
+                    }
+#endif
+                    // Forward ping response to operation callback
+                    mqtt_client->fnOperationCallback(mqtt_client, MQTT_CLIENT_ON_PING_RESPONSE, NULL, mqtt_client->ctx);
+                    break;
+                default:
+                    break;
+            }
+        }
+    }
+    else
+    {
+        LogError("recvCompleteCallback context failed.");
+    }
+}
+
+MQTT_CLIENT_HANDLE mqtt_client_init(ON_MQTT_MESSAGE_RECV_CALLBACK msgRecv, ON_MQTT_OPERATION_CALLBACK operation_cb, void* opCallbackCtx, ON_MQTT_ERROR_CALLBACK onErrorCallBack, void* errorCBCtx)
+{
+    MQTT_CLIENT* result;
+    /*Codes_SRS_MQTT_CLIENT_07_001: [If the parameters ON_MQTT_MESSAGE_RECV_CALLBACK is NULL then mqttclient_init shall return NULL.]*/
+    if (msgRecv == NULL || operation_cb == NULL)
+    {
+        LogError("Invalid parameter specified msgRecv: %p, operation_cb: %p", msgRecv, operation_cb);
+        result = NULL;
+    }
+    else
+    {
+        result = malloc(sizeof(MQTT_CLIENT));
+        if (result == NULL)
+        {
+            /*Codes_SRS_MQTT_CLIENT_07_002: [If any failure is encountered then mqttclient_init shall return NULL.]*/
+            LogError("mqtt_client_init failure: Allocation Failure");
+        }
+        else
+        {
+            memset(result, 0, sizeof(MQTT_CLIENT));
+            /*Codes_SRS_MQTT_CLIENT_07_003: [mqttclient_init shall allocate MQTTCLIENT_DATA_INSTANCE and return the MQTTCLIENT_HANDLE on success.]*/
+            result->packetState = UNKNOWN_TYPE;
+            result->fnOperationCallback = operation_cb;
+            result->ctx = opCallbackCtx;
+            result->fnMessageRecv = msgRecv;
+            result->fnOnErrorCallBack = onErrorCallBack;
+            result->errorCBCtx = errorCBCtx;
+            result->qosValue = DELIVER_AT_MOST_ONCE;
+            result->packetTickCntr = tickcounter_create();
+            result->maxPingRespTime = DEFAULT_MAX_PING_RESPONSE_TIME;
+            if (result->packetTickCntr == NULL)
+            {
+                /*Codes_SRS_MQTT_CLIENT_07_002: [If any failure is encountered then mqttclient_init shall return NULL.]*/
+                LogError("mqtt_client_init failure: tickcounter_create failure");
+                free(result);
+                result = NULL;
+            }
+            else
+            {
+                result->codec_handle = mqtt_codec_create(recvCompleteCallback, result);
+                if (result->codec_handle == NULL)
+                {
+                    /*Codes_SRS_MQTT_CLIENT_07_002: [If any failure is encountered then mqttclient_init shall return NULL.]*/
+                    LogError("mqtt_client_init failure: mqtt_codec_create failure");
+                    tickcounter_destroy(result->packetTickCntr);
+                    free(result);
+                    result = NULL;
+                }
+            }
+        }
+    }
+    return result;
+}
+
+void mqtt_client_deinit(MQTT_CLIENT_HANDLE handle)
+{
+    /*Codes_SRS_MQTT_CLIENT_07_004: [If the parameter handle is NULL then function mqtt_client_deinit shall do nothing.]*/
+    if (handle != NULL)
+    {
+        /*Codes_SRS_MQTT_CLIENT_07_005: [mqtt_client_deinit shall deallocate all memory allocated in this unit.]*/
+        MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)handle;
+        tickcounter_destroy(mqtt_client->packetTickCntr);
+        mqtt_codec_destroy(mqtt_client->codec_handle);
+        clear_mqtt_options(mqtt_client);
+        free(mqtt_client);
+    }
+}
+
+int mqtt_client_connect(MQTT_CLIENT_HANDLE handle, XIO_HANDLE xioHandle, MQTT_CLIENT_OPTIONS* mqttOptions)
+{
+    int result;
+    /*SRS_MQTT_CLIENT_07_006: [If any of the parameters handle, ioHandle, or mqttOptions are NULL then mqtt_client_connect shall return a non-zero value.]*/
+    if (handle == NULL || mqttOptions == NULL || xioHandle == NULL)
+    {
+        LogError("mqtt_client_connect: NULL argument (handle = %p, mqttOptions = %p, xioHandle: %p)", handle, mqttOptions, xioHandle);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)handle;
+        mqtt_client->xioHandle = xioHandle;
+        mqtt_client->packetState = UNKNOWN_TYPE;
+        mqtt_client->qosValue = mqttOptions->qualityOfServiceValue;
+        mqtt_client->keepAliveInterval = mqttOptions->keepAliveInterval;
+        mqtt_client->maxPingRespTime = (DEFAULT_MAX_PING_RESPONSE_TIME < mqttOptions->keepAliveInterval/2) ? DEFAULT_MAX_PING_RESPONSE_TIME : mqttOptions->keepAliveInterval/2;
+        if (cloneMqttOptions(mqtt_client, mqttOptions) != 0)
+        {
+            LogError("Error: Clone Mqtt Options failed");
+            result = MU_FAILURE;
+        }
+        /*Codes_SRS_MQTT_CLIENT_07_008: [mqtt_client_connect shall open the XIO_HANDLE by calling into the xio_open interface.]*/
+        else if (xio_open(xioHandle, onOpenComplete, mqtt_client, onBytesReceived, mqtt_client, onIoError, mqtt_client) != 0)
+        {
+            /*Codes_SRS_MQTT_CLIENT_07_007: [If any failure is encountered then mqtt_client_connect shall return a non-zero value.]*/
+            LogError("Error: io_open failed");
+            result = MU_FAILURE;
+            mqtt_client->xioHandle = NULL;
+            // Remove cloned options
+            clear_mqtt_options(mqtt_client);
+        }
+        else
+        {
+            result = 0;
+        }
+    }
+    return result;
+}
+
+int mqtt_client_publish(MQTT_CLIENT_HANDLE handle, MQTT_MESSAGE_HANDLE msgHandle)
+{
+    int result;
+    MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)handle;
+    if (mqtt_client == NULL || msgHandle == NULL)
+    {
+        /*Codes_SRS_MQTT_CLIENT_07_019: [If one of the parameters handle or msgHandle is NULL then mqtt_client_publish shall return a non-zero value.]*/
+        LogError("Invalid parameter specified mqtt_client: %p, msgHandle: %p", mqtt_client, msgHandle);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        /*Codes_SRS_MQTT_CLIENT_07_021: [mqtt_client_publish shall get the message information from the MQTT_MESSAGE_HANDLE.]*/
+        const APP_PAYLOAD* payload = mqttmessage_getApplicationMsg(msgHandle);
+        if (payload == NULL)
+        {
+            /*Codes_SRS_MQTT_CLIENT_07_020: [If any failure is encountered then mqtt_client_unsubscribe shall return a non-zero value.]*/
+            LogError("Error: mqttmessage_getApplicationMsg failed");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            STRING_HANDLE trace_log = construct_trace_log_handle(mqtt_client);
+
+            QOS_VALUE qos = mqttmessage_getQosType(msgHandle);
+            bool isDuplicate = mqttmessage_getIsDuplicateMsg(msgHandle);
+            bool isRetained = mqttmessage_getIsRetained(msgHandle);
+            uint16_t packetId = mqttmessage_getPacketId(msgHandle);
+            const char* topicName = mqttmessage_getTopicName(msgHandle);
+            BUFFER_HANDLE publishPacket = mqtt_codec_publish(qos, isDuplicate, isRetained, packetId, topicName, payload->message, payload->length, trace_log);
+            if (publishPacket == NULL)
+            {
+                /*Codes_SRS_MQTT_CLIENT_07_020: [If any failure is encountered then mqtt_client_unsubscribe shall return a non-zero value.]*/
+                LogError("Error: mqtt_codec_publish failed");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                mqtt_client->packetState = PUBLISH_TYPE;
+
+                /*Codes_SRS_MQTT_CLIENT_07_022: [On success mqtt_client_publish shall send the MQTT SUBCRIBE packet to the endpoint.]*/
+                size_t size = BUFFER_length(publishPacket);
+                if (sendPacketItem(mqtt_client, BUFFER_u_char(publishPacket), size) != 0)
+                {
+                    /*Codes_SRS_MQTT_CLIENT_07_020: [If any failure is encountered then mqtt_client_unsubscribe shall return a non-zero value.]*/
+                    LogError("Error: mqtt_client_publish send failed");
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    log_outgoing_trace(mqtt_client, trace_log);
+                    result = 0;
+                }
+                BUFFER_delete(publishPacket);
+            }
+            if (trace_log != NULL)
+            {
+                STRING_delete(trace_log);
+            }
+        }
+    }
+    return result;
+}
+
+int mqtt_client_subscribe(MQTT_CLIENT_HANDLE handle, uint16_t packetId, SUBSCRIBE_PAYLOAD* subscribeList, size_t count)
+{
+    int result;
+    MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)handle;
+    if (mqtt_client == NULL || subscribeList == NULL || count == 0 || packetId == 0)
+    {
+        /*Codes_SRS_MQTT_CLIENT_07_013: [If any of the parameters handle, subscribeList is NULL or count is 0 then mqtt_client_subscribe shall return a non-zero value.]*/
+        LogError("Invalid parameter specified mqtt_client: %p, subscribeList: %p, count: %lu, packetId: %d", mqtt_client, subscribeList, (unsigned long)count, packetId);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        STRING_HANDLE trace_log = construct_trace_log_handle(mqtt_client);
+
+        BUFFER_HANDLE subPacket = mqtt_codec_subscribe(packetId, subscribeList, count, trace_log);
+        if (subPacket == NULL)
+        {
+            /*Codes_SRS_MQTT_CLIENT_07_014: [If any failure is encountered then mqtt_client_subscribe shall return a non-zero value.]*/
+            LogError("Error: mqtt_codec_subscribe failed");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            mqtt_client->packetState = SUBSCRIBE_TYPE;
+
+            size_t size = BUFFER_length(subPacket);
+            /*Codes_SRS_MQTT_CLIENT_07_015: [On success mqtt_client_subscribe shall send the MQTT SUBCRIBE packet to the endpoint.]*/
+            if (sendPacketItem(mqtt_client, BUFFER_u_char(subPacket), size) != 0)
+            {
+                /*Codes_SRS_MQTT_CLIENT_07_014: [If any failure is encountered then mqtt_client_subscribe shall return a non-zero value.]*/
+                LogError("Error: mqtt_client_subscribe send failed");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                log_outgoing_trace(mqtt_client, trace_log);
+                result = 0;
+            }
+            BUFFER_delete(subPacket);
+        }
+        if (trace_log != NULL)
+        {
+            STRING_delete(trace_log);
+        }
+    }
+    return result;
+}
+
+int mqtt_client_unsubscribe(MQTT_CLIENT_HANDLE handle, uint16_t packetId, const char** unsubscribeList, size_t count)
+{
+    int result;
+    MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)handle;
+    if (mqtt_client == NULL || unsubscribeList == NULL || count == 0 || packetId == 0)
+    {
+        /*Codes_SRS_MQTT_CLIENT_07_016: [If any of the parameters handle, unsubscribeList is NULL or count is 0 then mqtt_client_unsubscribe shall return a non-zero value.]*/
+        LogError("Invalid parameter specified mqtt_client: %p, unsubscribeList: %p, count: %lu, packetId: %d", mqtt_client, unsubscribeList, (unsigned long)count, packetId);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        STRING_HANDLE trace_log = construct_trace_log_handle(mqtt_client);
+
+        BUFFER_HANDLE unsubPacket = mqtt_codec_unsubscribe(packetId, unsubscribeList, count, trace_log);
+        if (unsubPacket == NULL)
+        {
+            /*Codes_SRS_MQTT_CLIENT_07_017: [If any failure is encountered then mqtt_client_unsubscribe shall return a non-zero value.]*/
+            LogError("Error: mqtt_codec_unsubscribe failed");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            mqtt_client->packetState = UNSUBSCRIBE_TYPE;
+
+            size_t size = BUFFER_length(unsubPacket);
+            /*Codes_SRS_MQTT_CLIENT_07_018: [On success mqtt_client_unsubscribe shall send the MQTT SUBCRIBE packet to the endpoint.]*/
+            if (sendPacketItem(mqtt_client, BUFFER_u_char(unsubPacket), size) != 0)
+            {
+                /*Codes_SRS_MQTT_CLIENT_07_017: [If any failure is encountered then mqtt_client_unsubscribe shall return a non-zero value.].]*/
+                LogError("Error: mqtt_client_unsubscribe send failed");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                log_outgoing_trace(mqtt_client, trace_log);
+                result = 0;
+            }
+            BUFFER_delete(unsubPacket);
+        }
+        if (trace_log != NULL)
+        {
+            STRING_delete(trace_log);
+        }
+    }
+    return result;
+}
+
+int mqtt_client_disconnect(MQTT_CLIENT_HANDLE handle, ON_MQTT_DISCONNECTED_CALLBACK callback, void* ctx)
+{
+    int result;
+    MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)handle;
+    if (mqtt_client == NULL)
+    {
+        /*Codes_SRS_MQTT_CLIENT_07_010: [If the parameters handle is NULL then mqtt_client_disconnect shall return a non-zero value.]*/
+        result = MU_FAILURE;
+    }
+    else
+    {
+        if (mqtt_client->mqtt_status & MQTT_STATUS_CLIENT_CONNECTED)
+        {
+            BUFFER_HANDLE disconnectPacket = mqtt_codec_disconnect();
+            if (disconnectPacket == NULL)
+            {
+                /*Codes_SRS_MQTT_CLIENT_07_011: [If any failure is encountered then mqtt_client_disconnect shall return a non-zero value.]*/
+                LogError("Error: mqtt_client_disconnect failed");
+                mqtt_client->packetState = PACKET_TYPE_ERROR;
+                result = MU_FAILURE;
+            }
+            else
+            {
+                /* Codes_SRS_MQTT_CLIENT_07_037: [ if callback is not NULL callback shall be called once the mqtt connection has been disconnected ] */
+                mqtt_client->disconnect_cb = callback;
+                mqtt_client->disconnect_ctx = ctx;
+                mqtt_client->packetState = DISCONNECT_TYPE;
+
+                size_t size = BUFFER_length(disconnectPacket);
+                /*Codes_SRS_MQTT_CLIENT_07_012: [On success mqtt_client_disconnect shall send the MQTT DISCONNECT packet to the endpoint.]*/
+                if (sendPacketItem(mqtt_client, BUFFER_u_char(disconnectPacket), size) != 0)
+                {
+                    /*Codes_SRS_MQTT_CLIENT_07_011: [If any failure is encountered then mqtt_client_disconnect shall return a non-zero value.]*/
+                    LogError("Error: mqtt_client_disconnect send failed");
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    if (is_trace_enabled(mqtt_client))
+                    {
+                        STRING_HANDLE trace_log = STRING_construct("DISCONNECT");
+                        log_outgoing_trace(mqtt_client, trace_log);
+                        STRING_delete(trace_log);
+                    }
+                    result = 0;
+                }
+                BUFFER_delete(disconnectPacket);
+            }
+            clear_mqtt_options(mqtt_client);
+        }
+        else
+        {
+            // If the client is not connected then just close the underlying socket
+            mqtt_client->disconnect_cb = callback;
+            mqtt_client->disconnect_ctx = ctx;
+
+            close_connection(mqtt_client);
+            clear_mqtt_options(mqtt_client);
+            result = 0;
+        }
+    }
+    return result;
+}
+
+void mqtt_client_dowork(MQTT_CLIENT_HANDLE handle)
+{
+    MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)handle;
+    /*Codes_SRS_MQTT_CLIENT_18_001: [If the client is disconnected, mqtt_client_dowork shall do nothing.]*/
+    /*Codes_SRS_MQTT_CLIENT_07_023: [If the parameter handle is NULL then mqtt_client_dowork shall do nothing.]*/
+    if (mqtt_client != NULL && mqtt_client->xioHandle != NULL)
+    {
+        if (mqtt_client->mqtt_status & MQTT_STATUS_PENDING_CLOSE)
+        {
+            close_connection(mqtt_client);
+            // turn off pending close
+            mqtt_client->mqtt_status &= ~MQTT_STATUS_PENDING_CLOSE;
+        }
+        else
+        {
+            /*Codes_SRS_MQTT_CLIENT_07_024: [mqtt_client_dowork shall call the xio_dowork function to complete operations.]*/
+            xio_dowork(mqtt_client->xioHandle);
+
+            /*Codes_SRS_MQTT_CLIENT_07_025: [mqtt_client_dowork shall retrieve the the last packet send value and ...]*/
+            if (mqtt_client->mqtt_status & MQTT_STATUS_SOCKET_CONNECTED &&
+                mqtt_client->mqtt_status & MQTT_STATUS_CLIENT_CONNECTED &&
+                mqtt_client->keepAliveInterval > 0)
+            {
+                tickcounter_ms_t current_ms;
+                if (tickcounter_get_current_ms(mqtt_client->packetTickCntr, &current_ms) != 0)
+                {
+                    LogError("Error: tickcounter_get_current_ms failed");
+                }
+                else
+                {
+                    /* Codes_SRS_MQTT_CLIENT_07_035: [If the timeSincePing has expired past the maxPingRespTime then mqtt_client_dowork shall call the Error Callback function with the message MQTT_CLIENT_NO_PING_RESPONSE] */
+                    if (mqtt_client->timeSincePing > 0 && ((current_ms - mqtt_client->timeSincePing)/1000) > mqtt_client->maxPingRespTime)
+                    {
+                        // We haven't gotten a ping response in the alloted time
+                        set_error_callback(mqtt_client, MQTT_CLIENT_NO_PING_RESPONSE);
+                        mqtt_client->timeSincePing = 0;
+                        mqtt_client->packetSendTimeMs = 0;
+                        mqtt_client->packetState = UNKNOWN_TYPE;
+                    }
+                    else if (((current_ms - mqtt_client->packetSendTimeMs) / 1000) >= mqtt_client->keepAliveInterval)
+                    {
+                        /*Codes_SRS_MQTT_CLIENT_07_026: [if keepAliveInternal is > 0 and the send time is greater than the MQTT KeepAliveInterval then it shall construct an MQTT PINGREQ packet.]*/
+                        BUFFER_HANDLE pingPacket = mqtt_codec_ping();
+                        if (pingPacket != NULL)
+                        {
+                            size_t size = BUFFER_length(pingPacket);
+                            (void)sendPacketItem(mqtt_client, BUFFER_u_char(pingPacket), size);
+                            BUFFER_delete(pingPacket);
+                            (void)tickcounter_get_current_ms(mqtt_client->packetTickCntr, &mqtt_client->timeSincePing);
+
+                            if (is_trace_enabled(mqtt_client))
+                            {
+                                STRING_HANDLE trace_log = STRING_construct("PINGREQ");
+                                log_outgoing_trace(mqtt_client, trace_log);
+                                STRING_delete(trace_log);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+void mqtt_client_set_trace(MQTT_CLIENT_HANDLE handle, bool traceOn, bool rawBytesOn)
+{
+    AZURE_UNREFERENCED_PARAMETER(handle);
+    AZURE_UNREFERENCED_PARAMETER(traceOn);
+    AZURE_UNREFERENCED_PARAMETER(rawBytesOn);
+#ifndef NO_LOGGING
+    if (handle != NULL)
+    {
+        if (traceOn)
+        {
+            handle->mqtt_flags |= MQTT_FLAGS_LOG_TRACE;
+        }
+        else
+        {
+            handle->mqtt_flags &= ~MQTT_FLAGS_LOG_TRACE;
+        }
+#ifdef ENABLE_RAW_TRACE
+        if (rawBytesOn)
+        {
+            handle->mqtt_flags |= MQTT_FLAGS_RAW_TRACE;
+        }
+        else
+        {
+            handle->mqtt_flags &= ~MQTT_FLAGS_RAW_TRACE;
+        }
+#endif
+    }
+#endif
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/umqtt/src/mqtt_codec.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/umqtt/src/mqtt_codec.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/umqtt/src/mqtt_codec.c	(revision 453)
@@ -0,0 +1,1124 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include <limits.h>
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/buffer_.h"
+#include "azure_c_shared_utility/strings.h"
+#include "azure_macro_utils/macro_utils.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_umqtt_c/mqtt_codec.h"
+#include <inttypes.h>
+
+#define PAYLOAD_OFFSET                      5
+#define PACKET_TYPE_BYTE(p)                 (CONTROL_PACKET_TYPE)((uint8_t)(((uint8_t)(p)) & 0xf0))
+#define FLAG_VALUE_BYTE(p)                  ((uint8_t)(((uint8_t)(p)) & 0xf))
+
+#define USERNAME_FLAG                       0x80
+#define PASSWORD_FLAG                       0x40
+#define WILL_RETAIN_FLAG                    0x20
+#define WILL_QOS_FLAG_                      0x18
+#define WILL_FLAG_FLAG                      0x04
+#define CLEAN_SESSION_FLAG                  0x02
+
+#define NEXT_128_CHUNK                      0x80
+#define PUBLISH_DUP_FLAG                    0x8
+#define PUBLISH_QOS_EXACTLY_ONCE            0x4
+#define PUBLISH_QOS_AT_LEAST_ONCE           0x2
+#define PUBLISH_QOS_RETAIN                  0x1
+
+#define PROTOCOL_NUMBER                     4
+#define CONN_FLAG_BYTE_OFFSET               7
+
+#define CONNECT_FIXED_HEADER_SIZE           2
+#define CONNECT_VARIABLE_HEADER_SIZE        10
+#define SUBSCRIBE_FIXED_HEADER_FLAG         0x2
+#define UNSUBSCRIBE_FIXED_HEADER_FLAG       0x2
+
+#define MAX_SEND_SIZE                       0xFFFFFF7F // 268435455
+
+// This captures the maximum packet size for 3 digits.
+// If it's above this value then we bail out of the loop
+#define MAX_3_DIGIT_PACKET_SIZE             2097152
+
+#define CODEC_STATE_VALUES      \
+    CODEC_STATE_FIXED_HEADER,   \
+    CODEC_STATE_VAR_HEADER,     \
+    CODEC_STATE_PAYLOAD
+
+static const char* const TRUE_CONST = "true";
+static const char* const FALSE_CONST = "false";
+
+MU_DEFINE_ENUM(CODEC_STATE_RESULT, CODEC_STATE_VALUES);
+
+typedef struct MQTTCODEC_INSTANCE_TAG
+{
+    CONTROL_PACKET_TYPE currPacket;
+    CODEC_STATE_RESULT codecState;
+    size_t bufferOffset;
+    int headerFlags;
+    BUFFER_HANDLE headerData;
+    ON_PACKET_COMPLETE_CALLBACK packetComplete;
+    void* callContext;
+    uint8_t storeRemainLen[4];
+    size_t remainLenIndex;
+} MQTTCODEC_INSTANCE;
+
+typedef struct PUBLISH_HEADER_INFO_TAG
+{
+    const char* topicName;
+    uint16_t packetId;
+    const char* msgBuffer;
+    QOS_VALUE qualityOfServiceValue;
+} PUBLISH_HEADER_INFO;
+
+static const char* retrieve_qos_value(QOS_VALUE value)
+{
+    switch (value)
+    {
+        case DELIVER_AT_MOST_ONCE:
+            return "DELIVER_AT_MOST_ONCE";
+        case DELIVER_AT_LEAST_ONCE:
+            return "DELIVER_AT_LEAST_ONCE";
+        case DELIVER_EXACTLY_ONCE:
+        default:
+            return "DELIVER_EXACTLY_ONCE";
+    }
+}
+
+static void byteutil_writeByte(uint8_t** buffer, uint8_t value)
+{
+    if (buffer != NULL)
+    {
+        **buffer = value;
+        (*buffer)++;
+    }
+}
+
+static void byteutil_writeInt(uint8_t** buffer, uint16_t value)
+{
+    if (buffer != NULL)
+    {
+        **buffer = (char)(value / 256);
+        (*buffer)++;
+        **buffer = (char)(value % 256);
+        (*buffer)++;
+    }
+}
+
+static void byteutil_writeUTF(uint8_t** buffer, const char* stringData, uint16_t len)
+{
+    if (buffer != NULL)
+    {
+        byteutil_writeInt(buffer, len);
+        (void)memcpy(*buffer, stringData, len);
+        *buffer += len;
+    }
+}
+
+static CONTROL_PACKET_TYPE processControlPacketType(uint8_t pktByte, int* flags)
+{
+    CONTROL_PACKET_TYPE result;
+    result = PACKET_TYPE_BYTE(pktByte);
+    if (flags != NULL)
+    {
+        *flags = FLAG_VALUE_BYTE(pktByte);
+    }
+    return result;
+}
+
+static int addListItemsToUnsubscribePacket(BUFFER_HANDLE ctrlPacket, const char** payloadList, size_t payloadCount, STRING_HANDLE trace_log)
+{
+    int result = 0;
+    size_t index = 0;
+    for (index = 0; index < payloadCount && result == 0; index++)
+    {
+        // Add the Payload
+        size_t offsetLen = BUFFER_length(ctrlPacket);
+        size_t topicLen = strlen(payloadList[index]);
+        if (topicLen > USHRT_MAX)
+        {
+            result = MU_FAILURE;
+        }
+        else if (BUFFER_enlarge(ctrlPacket, topicLen + 2) != 0)
+        {
+            result = MU_FAILURE;
+        }
+        else
+        {
+            uint8_t* iterator = BUFFER_u_char(ctrlPacket);
+            iterator += offsetLen;
+            byteutil_writeUTF(&iterator, payloadList[index], (uint16_t)topicLen);
+        }
+        if (trace_log != NULL)
+        {
+            STRING_sprintf(trace_log, " | TOPIC_NAME: %s", payloadList[index]);
+        }
+    }
+    return result;
+}
+
+static int addListItemsToSubscribePacket(BUFFER_HANDLE ctrlPacket, SUBSCRIBE_PAYLOAD* payloadList, size_t payloadCount, STRING_HANDLE trace_log)
+{
+    int result = 0;
+    size_t index = 0;
+    for (index = 0; index < payloadCount && result == 0; index++)
+    {
+        // Add the Payload
+        size_t offsetLen = BUFFER_length(ctrlPacket);
+        size_t topicLen = strlen(payloadList[index].subscribeTopic);
+        if (topicLen > USHRT_MAX)
+        {
+            result = MU_FAILURE;
+        }
+        else if (BUFFER_enlarge(ctrlPacket, topicLen + 2 + 1) != 0)
+        {
+            result = MU_FAILURE;
+        }
+        else
+        {
+            uint8_t* iterator = BUFFER_u_char(ctrlPacket);
+            iterator += offsetLen;
+            byteutil_writeUTF(&iterator, payloadList[index].subscribeTopic, (uint16_t)topicLen);
+            *iterator = payloadList[index].qosReturn;
+
+            if (trace_log != NULL)
+            {
+                STRING_sprintf(trace_log, " | TOPIC_NAME: %s | QOS: %d", payloadList[index].subscribeTopic, (int)payloadList[index].qosReturn);
+            }
+        }
+    }
+    return result;
+}
+
+static int constructConnectVariableHeader(BUFFER_HANDLE ctrlPacket, const MQTT_CLIENT_OPTIONS* mqttOptions, STRING_HANDLE trace_log)
+{
+    int result = 0;
+    if (BUFFER_enlarge(ctrlPacket, CONNECT_VARIABLE_HEADER_SIZE) != 0)
+    {
+        result = MU_FAILURE;
+    }
+    else
+    {
+        uint8_t* iterator = BUFFER_u_char(ctrlPacket);
+        if (iterator == NULL)
+        {
+            result = MU_FAILURE;
+        }
+        else
+        {
+            if (trace_log != NULL)
+            {
+                STRING_sprintf(trace_log, " | VER: %d | KEEPALIVE: %d | FLAGS:", PROTOCOL_NUMBER, mqttOptions->keepAliveInterval);
+            }
+            byteutil_writeUTF(&iterator, "MQTT", 4);
+            byteutil_writeByte(&iterator, PROTOCOL_NUMBER);
+            byteutil_writeByte(&iterator, 0); // Flags will be entered later
+            byteutil_writeInt(&iterator, mqttOptions->keepAliveInterval);
+            result = 0;
+        }
+    }
+    return result;
+}
+
+static int constructPublishVariableHeader(BUFFER_HANDLE ctrlPacket, const PUBLISH_HEADER_INFO* publishHeader, STRING_HANDLE trace_log)
+{
+    int result = 0;
+    size_t topicLen = 0;
+    size_t spaceLen = 0;
+    size_t idLen = 0;
+
+    size_t currLen = BUFFER_length(ctrlPacket);
+
+    topicLen = strlen(publishHeader->topicName);
+    spaceLen += 2;
+
+    if (publishHeader->qualityOfServiceValue != DELIVER_AT_MOST_ONCE)
+    {
+        // Packet Id is only set if the QOS is not 0
+        idLen = 2;
+    }
+
+    if (topicLen > USHRT_MAX)
+    {
+        result = MU_FAILURE;
+    }
+    else if (BUFFER_enlarge(ctrlPacket, topicLen + idLen + spaceLen) != 0)
+    {
+        result = MU_FAILURE;
+    }
+    else
+    {
+        uint8_t* iterator = BUFFER_u_char(ctrlPacket);
+        if (iterator == NULL)
+        {
+            result = MU_FAILURE;
+        }
+        else
+        {
+            iterator += currLen;
+            /* The Topic Name MUST be present as the first field in the PUBLISH Packet Variable header.It MUST be 792 a UTF-8 encoded string [MQTT-3.3.2-1] as defined in section 1.5.3.*/
+            byteutil_writeUTF(&iterator, publishHeader->topicName, (uint16_t)topicLen);
+            if (trace_log != NULL)
+            {
+                STRING_sprintf(trace_log, " | TOPIC_NAME: %s", publishHeader->topicName);
+            }
+            if (idLen > 0)
+            {
+                if (trace_log != NULL)
+                {
+                    STRING_sprintf(trace_log, " | PACKET_ID: %"PRIu16, publishHeader->packetId);
+                }
+                byteutil_writeInt(&iterator, publishHeader->packetId);
+            }
+            result = 0;
+        }
+    }
+    return result;
+}
+
+static int constructSubscibeTypeVariableHeader(BUFFER_HANDLE ctrlPacket, uint16_t packetId)
+{
+    int result = 0;
+    if (BUFFER_enlarge(ctrlPacket, 2) != 0)
+    {
+        result = MU_FAILURE;
+    }
+    else
+    {
+        uint8_t* iterator = BUFFER_u_char(ctrlPacket);
+        if (iterator == NULL)
+        {
+            result = MU_FAILURE;
+        }
+        else
+        {
+            byteutil_writeInt(&iterator, packetId);
+            result = 0;
+        }
+    }
+    return result;
+}
+
+static BUFFER_HANDLE constructPublishReply(CONTROL_PACKET_TYPE type, uint8_t flags, uint16_t packetId)
+{
+    BUFFER_HANDLE result = BUFFER_new();
+    if (result != NULL)
+    {
+        if (BUFFER_pre_build(result, 4) != 0)
+        {
+            BUFFER_delete(result);
+            result = NULL;
+        }
+        else
+        {
+            uint8_t* iterator = BUFFER_u_char(result);
+            if (iterator == NULL)
+            {
+                BUFFER_delete(result);
+                result = NULL;
+            }
+            else
+            {
+                *iterator = (uint8_t)type | flags;
+                iterator++;
+                *iterator = 0x2;
+                iterator++;
+                byteutil_writeInt(&iterator, packetId);
+            }
+        }
+    }
+    return result;
+}
+
+static int constructFixedHeader(BUFFER_HANDLE ctrlPacket, CONTROL_PACKET_TYPE packetType, uint8_t flags)
+{
+    int result;
+    size_t packetLen = BUFFER_length(ctrlPacket);
+    uint8_t remainSize[4] ={ 0 };
+    size_t index = 0;
+
+    // Calculate the length of packet
+    do
+    {
+        uint8_t encode = packetLen % 128;
+        packetLen /= 128;
+        // if there are more data to encode, set the top bit of this byte
+        if (packetLen > 0)
+        {
+            encode |= NEXT_128_CHUNK;
+        }
+        remainSize[index++] = encode;
+    } while (packetLen > 0);
+
+    BUFFER_HANDLE fixedHeader = BUFFER_new();
+    if (fixedHeader == NULL)
+    {
+        result = MU_FAILURE;
+    }
+    else if (BUFFER_pre_build(fixedHeader, index + 1) != 0)
+    {
+        BUFFER_delete(fixedHeader);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        uint8_t* iterator = BUFFER_u_char(fixedHeader);
+        *iterator = (uint8_t)packetType | flags;
+        iterator++;
+        (void)memcpy(iterator, remainSize, index);
+
+        result = BUFFER_prepend(ctrlPacket, fixedHeader);
+        BUFFER_delete(fixedHeader);
+    }
+    return result;
+}
+
+static int constructConnPayload(BUFFER_HANDLE ctrlPacket, const MQTT_CLIENT_OPTIONS* mqttOptions, STRING_HANDLE trace_log)
+{
+    int result = 0;
+    size_t clientLen = 0;
+    size_t usernameLen = 0;
+    size_t passwordLen = 0;
+    size_t willMessageLen = 0;
+    size_t willTopicLen = 0;
+    size_t spaceLen = 0;
+    size_t currLen = 0;
+    size_t totalLen = 0;
+
+    if (mqttOptions->clientId != NULL)
+    {
+        spaceLen += 2;
+        clientLen = strlen(mqttOptions->clientId);
+    }
+    if (mqttOptions->username != NULL)
+    {
+        spaceLen += 2;
+        usernameLen = strlen(mqttOptions->username);
+    }
+    if (mqttOptions->password != NULL)
+    {
+        spaceLen += 2;
+        passwordLen = strlen(mqttOptions->password);
+    }
+    if (mqttOptions->willMessage != NULL)
+    {
+        spaceLen += 2;
+        willMessageLen = strlen(mqttOptions->willMessage);
+    }
+    if (mqttOptions->willTopic != NULL)
+    {
+        spaceLen += 2;
+        willTopicLen = strlen(mqttOptions->willTopic);
+    }
+
+    currLen = BUFFER_length(ctrlPacket);
+    totalLen = clientLen + usernameLen + passwordLen + willMessageLen + willTopicLen + spaceLen;
+
+    // Validate the Username & Password
+    if (clientLen > USHRT_MAX)
+    {
+        result = MU_FAILURE;
+    }
+    else if (usernameLen == 0 && passwordLen > 0)
+    {
+        result = MU_FAILURE;
+    }
+    else if ((willMessageLen > 0 && willTopicLen == 0) || (willTopicLen > 0 && willMessageLen == 0))
+    {
+        result = MU_FAILURE;
+    }
+    else if (BUFFER_enlarge(ctrlPacket, totalLen) != 0)
+    {
+        result = MU_FAILURE;
+    }
+    else
+    {
+        uint8_t* packet = BUFFER_u_char(ctrlPacket);
+        uint8_t* iterator = packet;
+
+        iterator += currLen;
+        byteutil_writeUTF(&iterator, mqttOptions->clientId, (uint16_t)clientLen);
+
+        // TODO: Read on the Will Topic
+        if (willMessageLen > USHRT_MAX || willTopicLen > USHRT_MAX || usernameLen > USHRT_MAX || passwordLen > USHRT_MAX)
+        {
+            result = MU_FAILURE;
+        }
+        else
+        {
+            STRING_HANDLE connect_payload_trace = NULL;
+            if (trace_log != NULL)
+            {
+                connect_payload_trace = STRING_new();
+            }
+            if (willMessageLen > 0 && willTopicLen > 0)
+            {
+                if (trace_log != NULL)
+                {
+                    (void)STRING_sprintf(connect_payload_trace, " | WILL_TOPIC: %s", mqttOptions->willTopic);
+                }
+                packet[CONN_FLAG_BYTE_OFFSET] |= WILL_FLAG_FLAG;
+                byteutil_writeUTF(&iterator, mqttOptions->willTopic, (uint16_t)willTopicLen);
+                packet[CONN_FLAG_BYTE_OFFSET] |= (mqttOptions->qualityOfServiceValue << 3);
+                if (mqttOptions->messageRetain)
+                {
+                    packet[CONN_FLAG_BYTE_OFFSET] |= WILL_RETAIN_FLAG;
+                }
+                byteutil_writeUTF(&iterator, mqttOptions->willMessage, (uint16_t)willMessageLen);
+            }
+            if (usernameLen > 0)
+            {
+                packet[CONN_FLAG_BYTE_OFFSET] |= USERNAME_FLAG;
+                byteutil_writeUTF(&iterator, mqttOptions->username, (uint16_t)usernameLen);
+                if (trace_log != NULL)
+                {
+                    (void)STRING_sprintf(connect_payload_trace, " | USERNAME: %s", mqttOptions->username);
+                }
+            }
+            if (passwordLen > 0)
+            {
+                packet[CONN_FLAG_BYTE_OFFSET] |= PASSWORD_FLAG;
+                byteutil_writeUTF(&iterator, mqttOptions->password, (uint16_t)passwordLen);
+                if (trace_log != NULL)
+                {
+                    (void)STRING_sprintf(connect_payload_trace, " | PWD: XXXX");
+                }
+            }
+            // TODO: Get the rest of the flags
+            if (trace_log != NULL)
+            {
+                (void)STRING_sprintf(connect_payload_trace, " | CLEAN: %s", mqttOptions->useCleanSession ? "1" : "0");
+            }
+            if (mqttOptions->useCleanSession)
+            {
+                packet[CONN_FLAG_BYTE_OFFSET] |= CLEAN_SESSION_FLAG;
+            }
+            if (trace_log != NULL)
+            {
+                (void)STRING_sprintf(trace_log, " %lu", packet[CONN_FLAG_BYTE_OFFSET]);
+                (void)STRING_concat_with_STRING(trace_log, connect_payload_trace);
+                STRING_delete(connect_payload_trace);
+            }
+            result = 0;
+        }
+    }
+    return result;
+}
+
+static int prepareheaderDataInfo(MQTTCODEC_INSTANCE* codecData, uint8_t remainLen)
+{
+    int result;
+    result = 0;
+    codecData->storeRemainLen[codecData->remainLenIndex++] = remainLen;
+    if (remainLen <= 0x7f)
+    {
+        int multiplier = 1;
+        int totalLen = 0;
+        size_t index = 0;
+        uint8_t encodeByte = 0;
+        do
+        {
+            encodeByte = codecData->storeRemainLen[index++];
+            totalLen += (encodeByte & 127) * multiplier;
+            multiplier *= NEXT_128_CHUNK;
+
+            if (multiplier > MAX_3_DIGIT_PACKET_SIZE)
+            {
+                result = MU_FAILURE;
+                break;
+            }
+        } while ((encodeByte & NEXT_128_CHUNK) != 0);
+
+        if (result != 0 || totalLen > MAX_SEND_SIZE)
+        {
+            LogError("Receive buffer too large for MQTT packet");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            codecData->codecState = CODEC_STATE_VAR_HEADER;
+
+            // Reset remainLen Index
+            codecData->remainLenIndex = 0;
+            memset(codecData->storeRemainLen, 0, 4 * sizeof(uint8_t));
+
+            if (totalLen > 0)
+            {
+                codecData->bufferOffset = 0;
+                codecData->headerData = BUFFER_new();
+                if (codecData->headerData == NULL)
+                {
+                    /* Codes_SRS_MQTT_CODEC_07_035: [ If any error is encountered then the packet state will be marked as error and mqtt_codec_bytesReceived shall return a non-zero value. ] */
+                    LogError("Failed BUFFER_new");
+                    result = MU_FAILURE;
+                }
+                else
+                {
+                    if (BUFFER_pre_build(codecData->headerData, totalLen) != 0)
+                    {
+                        /* Codes_SRS_MQTT_CODEC_07_035: [ If any error is encountered then the packet state will be marked as error and mqtt_codec_bytesReceived shall return a non-zero value. ] */
+                        LogError("Failed BUFFER_pre_build");
+                        result = MU_FAILURE;
+                    }
+
+                }
+            }
+        }
+    }
+    return result;
+}
+
+static void completePacketData(MQTTCODEC_INSTANCE* codecData)
+{
+    if (codecData->packetComplete != NULL)
+    {
+        codecData->packetComplete(codecData->callContext, codecData->currPacket, codecData->headerFlags, codecData->headerData);
+    }
+
+    // Clean up data
+    codecData->currPacket = UNKNOWN_TYPE;
+    codecData->codecState = CODEC_STATE_FIXED_HEADER;
+    codecData->headerFlags = 0;
+    BUFFER_delete(codecData->headerData);
+    codecData->headerData = NULL;
+}
+
+static void clear_codec_data(MQTTCODEC_INSTANCE* codec_data)
+{
+    // Clear the code instance data
+    codec_data->currPacket = UNKNOWN_TYPE;
+    codec_data->codecState = CODEC_STATE_FIXED_HEADER;
+    codec_data->headerFlags = 0;
+    codec_data->bufferOffset = 0;
+    codec_data->headerData = NULL;
+    memset(codec_data->storeRemainLen, 0, 4 * sizeof(uint8_t));
+    codec_data->remainLenIndex = 0;
+}
+
+void mqtt_codec_reset(MQTTCODEC_HANDLE handle)
+{
+    if (handle != NULL)
+    {
+        clear_codec_data(handle);
+    }
+}
+
+MQTTCODEC_HANDLE mqtt_codec_create(ON_PACKET_COMPLETE_CALLBACK packetComplete, void* callbackCtx)
+{
+    MQTTCODEC_HANDLE result;
+    result = malloc(sizeof(MQTTCODEC_INSTANCE));
+    /* Codes_SRS_MQTT_CODEC_07_001: [If a failure is encountered then mqtt_codec_create shall return NULL.] */
+    if (result != NULL)
+    {
+        /* Codes_SRS_MQTT_CODEC_07_002: [On success mqtt_codec_create shall return a MQTTCODEC_HANDLE value.] */
+        clear_codec_data(result);
+        result->packetComplete = packetComplete;
+        result->callContext = callbackCtx;
+    }
+    return result;
+}
+
+void mqtt_codec_destroy(MQTTCODEC_HANDLE handle)
+{
+    /* Codes_SRS_MQTT_CODEC_07_003: [If the handle parameter is NULL then mqtt_codec_destroy shall do nothing.] */
+    if (handle != NULL)
+    {
+        MQTTCODEC_INSTANCE* codecData = (MQTTCODEC_INSTANCE*)handle;
+        /* Codes_SRS_MQTT_CODEC_07_004: [mqtt_codec_destroy shall deallocate all memory that has been allocated by this object.] */
+        BUFFER_delete(codecData->headerData);
+        free(codecData);
+    }
+}
+
+BUFFER_HANDLE mqtt_codec_connect(const MQTT_CLIENT_OPTIONS* mqttOptions, STRING_HANDLE trace_log)
+{
+    BUFFER_HANDLE result;
+    /* Codes_SRS_MQTT_CODEC_07_008: [If the parameters mqttOptions is NULL then mqtt_codec_connect shall return a null value.] */
+    if (mqttOptions == NULL)
+    {
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_MQTT_CODEC_07_009: [mqtt_codec_connect shall construct a BUFFER_HANDLE that represents a MQTT CONNECT packet.] */
+        result = BUFFER_new();
+        if (result != NULL)
+        {
+            STRING_HANDLE varible_header_log = NULL;
+            if (trace_log != NULL)
+            {
+                varible_header_log = STRING_new();
+            }
+            // Add Variable Header Information
+            if (constructConnectVariableHeader(result, mqttOptions, varible_header_log) != 0)
+            {
+                /* Codes_SRS_MQTT_CODEC_07_010: [If any error is encountered then mqtt_codec_connect shall return NULL.] */
+                BUFFER_delete(result);
+                result = NULL;
+            }
+            else
+            {
+                if (constructConnPayload(result, mqttOptions, varible_header_log) != 0)
+                {
+                    /* Codes_SRS_MQTT_CODEC_07_010: [If any error is encountered then mqtt_codec_connect shall return NULL.] */
+                    BUFFER_delete(result);
+                    result = NULL;
+                }
+                else
+                {
+                    if (trace_log != NULL)
+                    {
+                        (void)STRING_copy(trace_log, "CONNECT");
+                    }
+                    if (constructFixedHeader(result, CONNECT_TYPE, 0) != 0)
+                    {
+                        /* Codes_SRS_MQTT_CODEC_07_010: [If any error is encountered then mqtt_codec_connect shall return NULL.] */
+                        BUFFER_delete(result);
+                        result = NULL;
+                    }
+                    else
+                    {
+                        if (trace_log != NULL)
+                        {
+                            (void)STRING_concat_with_STRING(trace_log, varible_header_log);
+                        }
+                    }
+                }
+                if (varible_header_log != NULL)
+                {
+                    STRING_delete(varible_header_log);
+                }
+            }
+        }
+    }
+    return result;
+}
+
+BUFFER_HANDLE mqtt_codec_disconnect()
+{
+    /* Codes_SRS_MQTT_CODEC_07_011: [On success mqtt_codec_disconnect shall construct a BUFFER_HANDLE that represents a MQTT DISCONNECT packet.] */
+    BUFFER_HANDLE result = BUFFER_new();
+    if (result != NULL)
+    {
+        if (BUFFER_enlarge(result, 2) != 0)
+        {
+            /* Codes_SRS_MQTT_CODEC_07_012: [If any error is encountered mqtt_codec_disconnect shall return NULL.] */
+            BUFFER_delete(result);
+            result = NULL;
+        }
+        else
+        {
+            uint8_t* iterator = BUFFER_u_char(result);
+            if (iterator == NULL)
+            {
+                /* Codes_SRS_MQTT_CODEC_07_012: [If any error is encountered mqtt_codec_disconnect shall return NULL.] */
+                BUFFER_delete(result);
+                result = NULL;
+            }
+            else
+            {
+                iterator[0] = DISCONNECT_TYPE;
+                iterator[1] = 0;
+            }
+        }
+    }
+    return result;
+}
+
+BUFFER_HANDLE mqtt_codec_publish(QOS_VALUE qosValue, bool duplicateMsg, bool serverRetain, uint16_t packetId, const char* topicName, const uint8_t* msgBuffer, size_t buffLen, STRING_HANDLE trace_log)
+{
+    BUFFER_HANDLE result;
+    /* Codes_SRS_MQTT_CODEC_07_005: [If the parameters topicName is NULL then mqtt_codec_publish shall return NULL.] */
+    if (topicName == NULL)
+    {
+        result = NULL;
+    }
+    /* Codes_SRS_MQTT_CODEC_07_036: [mqtt_codec_publish shall return NULL if the buffLen variable is greater than the MAX_SEND_SIZE (0xFFFFFF7F).] */
+    else if (buffLen > MAX_SEND_SIZE)
+    {
+        /* Codes_SRS_MQTT_CODEC_07_006: [If any error is encountered then mqtt_codec_publish shall return NULL.] */
+        result = NULL;
+    }
+    else
+    {
+        PUBLISH_HEADER_INFO publishInfo ={ 0 };
+        publishInfo.topicName = topicName;
+        publishInfo.packetId = packetId;
+        publishInfo.qualityOfServiceValue = qosValue;
+
+        uint8_t headerFlags = 0;
+        if (duplicateMsg) headerFlags |= PUBLISH_DUP_FLAG;
+        if (serverRetain) headerFlags |= PUBLISH_QOS_RETAIN;
+        if (qosValue != DELIVER_AT_MOST_ONCE)
+        {
+            if (qosValue == DELIVER_AT_LEAST_ONCE)
+            {
+                headerFlags |= PUBLISH_QOS_AT_LEAST_ONCE;
+            }
+            else
+            {
+                headerFlags |= PUBLISH_QOS_EXACTLY_ONCE;
+            }
+        }
+
+        /* Codes_SRS_MQTT_CODEC_07_007: [mqtt_codec_publish shall return a BUFFER_HANDLE that represents a MQTT PUBLISH message.] */
+        result = BUFFER_new();
+        if (result != NULL)
+        {
+            STRING_HANDLE varible_header_log = NULL;
+            if (trace_log != NULL)
+            {
+                varible_header_log = STRING_construct_sprintf(" | IS_DUP: %s | RETAIN: %d | QOS: %s", duplicateMsg ? TRUE_CONST : FALSE_CONST,
+                    serverRetain ? 1 : 0,
+                    retrieve_qos_value(publishInfo.qualityOfServiceValue) );
+            }
+
+            if (constructPublishVariableHeader(result, &publishInfo, varible_header_log) != 0)
+            {
+                /* Codes_SRS_MQTT_CODEC_07_006: [If any error is encountered then mqtt_codec_publish shall return NULL.] */
+                BUFFER_delete(result);
+                result = NULL;
+            }
+            else
+            {
+                size_t payloadOffset = BUFFER_length(result);
+                if (buffLen > 0)
+                {
+                    if (BUFFER_enlarge(result, buffLen) != 0)
+                    {
+                        /* Codes_SRS_MQTT_CODEC_07_006: [If any error is encountered then mqtt_codec_publish shall return NULL.] */
+                        BUFFER_delete(result);
+                        result = NULL;
+                    }
+                    else
+                    {
+                        uint8_t* iterator = BUFFER_u_char(result);
+                        if (iterator == NULL)
+                        {
+                            /* Codes_SRS_MQTT_CODEC_07_006: [If any error is encountered then mqtt_codec_publish shall return NULL.] */
+                            BUFFER_delete(result);
+                            result = NULL;
+                        }
+                        else
+                        {
+                            iterator += payloadOffset;
+                            // Write Message
+                            (void)memcpy(iterator, msgBuffer, buffLen);
+                            if (trace_log)
+                            {
+                                STRING_sprintf(varible_header_log, " | PAYLOAD_LEN: %lu", (unsigned long)buffLen);
+                            }
+                        }
+                    }
+                }
+
+                if (result != NULL)
+                {
+                    if (trace_log != NULL)
+                    {
+                        (void)STRING_copy(trace_log, "PUBLISH");
+                    }
+                    if (constructFixedHeader(result, PUBLISH_TYPE, headerFlags) != 0)
+                    {
+                        /* Codes_SRS_MQTT_CODEC_07_006: [If any error is encountered then mqtt_codec_publish shall return NULL.] */
+                        BUFFER_delete(result);
+                        result = NULL;
+                    }
+                    else
+                    {
+                        if (trace_log != NULL)
+                        {
+                            (void)STRING_concat_with_STRING(trace_log, varible_header_log);
+                        }
+                    }
+                }
+            }
+            if (varible_header_log != NULL)
+            {
+                STRING_delete(varible_header_log);
+            }
+        }
+    }
+    return result;
+}
+
+BUFFER_HANDLE mqtt_codec_publishAck(uint16_t packetId)
+{
+    /* Codes_SRS_MQTT_CODEC_07_013: [On success mqtt_codec_publishAck shall return a BUFFER_HANDLE representation of a MQTT PUBACK packet.] */
+    /* Codes_SRS_MQTT_CODEC_07_014 : [If any error is encountered then mqtt_codec_publishAck shall return NULL.] */
+    BUFFER_HANDLE result = constructPublishReply(PUBACK_TYPE, 0, packetId);
+    return result;
+}
+
+BUFFER_HANDLE mqtt_codec_publishReceived(uint16_t packetId)
+{
+    /* Codes_SRS_MQTT_CODEC_07_015: [On success mqtt_codec_publishRecieved shall return a BUFFER_HANDLE representation of a MQTT PUBREC packet.] */
+    /* Codes_SRS_MQTT_CODEC_07_016 : [If any error is encountered then mqtt_codec_publishRecieved shall return NULL.] */
+    BUFFER_HANDLE result = constructPublishReply(PUBREC_TYPE, 0, packetId);
+    return result;
+}
+
+BUFFER_HANDLE mqtt_codec_publishRelease(uint16_t packetId)
+{
+    /* Codes_SRS_MQTT_CODEC_07_017: [On success mqtt_codec_publishRelease shall return a BUFFER_HANDLE representation of a MQTT PUBREL packet.] */
+    /* Codes_SRS_MQTT_CODEC_07_018 : [If any error is encountered then mqtt_codec_publishRelease shall return NULL.] */
+    BUFFER_HANDLE result = constructPublishReply(PUBREL_TYPE, 2, packetId);
+    return result;
+}
+
+BUFFER_HANDLE mqtt_codec_publishComplete(uint16_t packetId)
+{
+    /* Codes_SRS_MQTT_CODEC_07_019: [On success mqtt_codec_publishComplete shall return a BUFFER_HANDLE representation of a MQTT PUBCOMP packet.] */
+    /* Codes_SRS_MQTT_CODEC_07_020 : [If any error is encountered then mqtt_codec_publishComplete shall return NULL.] */
+    BUFFER_HANDLE result = constructPublishReply(PUBCOMP_TYPE, 0, packetId);
+    return result;
+}
+
+BUFFER_HANDLE mqtt_codec_ping()
+{
+    /* Codes_SRS_MQTT_CODEC_07_021: [On success mqtt_codec_ping shall construct a BUFFER_HANDLE that represents a MQTT PINGREQ packet.] */
+    BUFFER_HANDLE result = BUFFER_new();
+    if (result != NULL)
+    {
+        if (BUFFER_enlarge(result, 2) != 0)
+        {
+            /* Codes_SRS_MQTT_CODEC_07_022: [If any error is encountered mqtt_codec_ping shall return NULL.] */
+            BUFFER_delete(result);
+            result = NULL;
+        }
+        else
+        {
+            uint8_t* iterator = BUFFER_u_char(result);
+            if (iterator == NULL)
+            {
+                /* Codes_SRS_MQTT_CODEC_07_022: [If any error is encountered mqtt_codec_ping shall return NULL.] */
+                BUFFER_delete(result);
+                result = NULL;
+            }
+            else
+            {
+                iterator[0] = PINGREQ_TYPE;
+                iterator[1] = 0;
+            }
+        }
+    }
+    return result;
+}
+
+BUFFER_HANDLE mqtt_codec_subscribe(uint16_t packetId, SUBSCRIBE_PAYLOAD* subscribeList, size_t count, STRING_HANDLE trace_log)
+{
+    BUFFER_HANDLE result;
+    /* Codes_SRS_MQTT_CODEC_07_023: [If the parameters subscribeList is NULL or if count is 0 then mqtt_codec_subscribe shall return NULL.] */
+    if (subscribeList == NULL || count == 0)
+    {
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_MQTT_CODEC_07_026: [mqtt_codec_subscribe shall return a BUFFER_HANDLE that represents a MQTT SUBSCRIBE message.]*/
+        result = BUFFER_new();
+        if (result != NULL)
+        {
+            if (constructSubscibeTypeVariableHeader(result, packetId) != 0)
+            {
+                /* Codes_SRS_MQTT_CODEC_07_025: [If any error is encountered then mqtt_codec_subscribe shall return NULL.] */
+                BUFFER_delete(result);
+                result = NULL;
+            }
+            else
+            {
+                STRING_HANDLE sub_trace = NULL;
+                if (trace_log != NULL)
+                {
+                    sub_trace = STRING_construct_sprintf(" | PACKET_ID: %"PRIu16, packetId);
+                }
+                /* Codes_SRS_MQTT_CODEC_07_024: [mqtt_codec_subscribe shall iterate through count items in the subscribeList.] */
+                if (addListItemsToSubscribePacket(result, subscribeList, count, sub_trace) != 0)
+                {
+                    /* Codes_SRS_MQTT_CODEC_07_025: [If any error is encountered then mqtt_codec_subscribe shall return NULL.] */
+                    BUFFER_delete(result);
+                    result = NULL;
+                }
+                else
+                {
+
+                    if (trace_log != NULL)
+                    {
+                        STRING_concat(trace_log, "SUBSCRIBE");
+                    }
+                    if (constructFixedHeader(result, SUBSCRIBE_TYPE, SUBSCRIBE_FIXED_HEADER_FLAG) != 0)
+                    {
+                        /* Codes_SRS_MQTT_CODEC_07_025: [If any error is encountered then mqtt_codec_subscribe shall return NULL.] */
+                        BUFFER_delete(result);
+                        result = NULL;
+                    }
+                    else
+                    {
+                        if (trace_log != NULL)
+                        {
+                            (void)STRING_concat_with_STRING(trace_log, sub_trace);
+                        }
+                    }
+                }
+                if (sub_trace != NULL)
+                {
+                    STRING_delete(sub_trace);
+                }
+            }
+        }
+    }
+    return result;
+}
+
+BUFFER_HANDLE mqtt_codec_unsubscribe(uint16_t packetId, const char** unsubscribeList, size_t count, STRING_HANDLE trace_log)
+{
+    BUFFER_HANDLE result;
+    /* Codes_SRS_MQTT_CODEC_07_027: [If the parameters unsubscribeList is NULL or if count is 0 then mqtt_codec_unsubscribe shall return NULL.] */
+    if (unsubscribeList == NULL || count == 0)
+    {
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_MQTT_CODEC_07_030: [mqtt_codec_unsubscribe shall return a BUFFER_HANDLE that represents a MQTT SUBSCRIBE message.] */
+        result = BUFFER_new();
+        if (result != NULL)
+        {
+            if (constructSubscibeTypeVariableHeader(result, packetId) != 0)
+            {
+                /* Codes_SRS_MQTT_CODEC_07_029: [If any error is encountered then mqtt_codec_unsubscribe shall return NULL.] */
+                BUFFER_delete(result);
+                result = NULL;
+            }
+            else
+            {
+                STRING_HANDLE unsub_trace = NULL;
+                if (trace_log != NULL)
+                {
+                    unsub_trace = STRING_construct_sprintf(" | PACKET_ID: %"PRIu16, packetId);
+                }
+                /* Codes_SRS_MQTT_CODEC_07_028: [mqtt_codec_unsubscribe shall iterate through count items in the unsubscribeList.] */
+                if (addListItemsToUnsubscribePacket(result, unsubscribeList, count, unsub_trace) != 0)
+                {
+                    /* Codes_SRS_MQTT_CODEC_07_029: [If any error is encountered then mqtt_codec_unsubscribe shall return NULL.] */
+                    BUFFER_delete(result);
+                    result = NULL;
+                }
+                else
+                {
+                    if (trace_log != NULL)
+                    {
+                        (void)STRING_copy(trace_log, "UNSUBSCRIBE");
+                    }
+                    if (constructFixedHeader(result, UNSUBSCRIBE_TYPE, UNSUBSCRIBE_FIXED_HEADER_FLAG) != 0)
+                    {
+                        /* Codes_SRS_MQTT_CODEC_07_029: [If any error is encountered then mqtt_codec_unsubscribe shall return NULL.] */
+                        BUFFER_delete(result);
+                        result = NULL;
+                    }
+                    else
+                    {
+                        if (trace_log != NULL)
+                        {
+                            (void)STRING_concat_with_STRING(trace_log, unsub_trace);
+                        }
+                    }
+                }
+                if (unsub_trace != NULL)
+                {
+                    STRING_delete(unsub_trace);
+                }
+            }
+        }
+    }
+    return result;
+}
+
+int mqtt_codec_bytesReceived(MQTTCODEC_HANDLE handle, const unsigned char* buffer, size_t size)
+{
+    int result;
+    MQTTCODEC_INSTANCE* codec_Data = (MQTTCODEC_INSTANCE*)handle;
+    /* Codes_SRS_MQTT_CODEC_07_031: [If the parameters handle or buffer is NULL then mqtt_codec_bytesReceived shall return a non-zero value.] */
+    if (codec_Data == NULL)
+    {
+        result = MU_FAILURE;
+    }
+    /* Codes_SRS_MQTT_CODEC_07_031: [If the parameters handle or buffer is NULL then mqtt_codec_bytesReceived shall return a non-zero value.] */
+    /* Codes_SRS_MQTT_CODEC_07_032: [If the parameters size is zero then mqtt_codec_bytesReceived shall return a non-zero value.] */
+    else if (buffer == NULL || size == 0)
+    {
+        codec_Data->currPacket = PACKET_TYPE_ERROR;
+        result = MU_FAILURE;
+    }
+    else
+    {
+        /* Codes_SRS_MQTT_CODEC_07_033: [mqtt_codec_bytesReceived constructs a sequence of bytes into the corresponding MQTT packets and on success returns zero.] */
+        result = 0;
+        size_t index = 0;
+        for (index = 0; index < size && result == 0; index++)
+        {
+            uint8_t iterator = ((int8_t*)buffer)[index];
+            if (codec_Data->codecState == CODEC_STATE_FIXED_HEADER)
+            {
+                if (codec_Data->currPacket == UNKNOWN_TYPE)
+                {
+                    codec_Data->currPacket = processControlPacketType(iterator, &codec_Data->headerFlags);
+                }
+                else
+                {
+                    if (prepareheaderDataInfo(codec_Data, iterator) != 0)
+                    {
+                        /* Codes_SRS_MQTT_CODEC_07_035: [If any error is encountered then the packet state will be marked as error and mqtt_codec_bytesReceived shall return a non-zero value.] */
+                        codec_Data->currPacket = PACKET_TYPE_ERROR;
+                        result = MU_FAILURE;
+                    }
+                    else if (codec_Data->currPacket == PINGRESP_TYPE)
+                    {
+                        /* Codes_SRS_MQTT_CODEC_07_034: [Upon a constructing a complete MQTT packet mqtt_codec_bytesReceived shall call the ON_PACKET_COMPLETE_CALLBACK function.] */
+                        completePacketData(codec_Data);
+                    }
+                }
+            }
+            else if (codec_Data->codecState == CODEC_STATE_VAR_HEADER)
+            {
+                if (codec_Data->headerData == NULL)
+                {
+                    codec_Data->codecState = CODEC_STATE_PAYLOAD;
+                }
+                else
+                {
+                    uint8_t* dataBytes = BUFFER_u_char(codec_Data->headerData);
+                    if (dataBytes == NULL)
+                    {
+                        /* Codes_SRS_MQTT_CODEC_07_035: [If any error is encountered then the packet state will be marked as error and mqtt_codec_bytesReceived shall return a non-zero value.] */
+                        codec_Data->currPacket = PACKET_TYPE_ERROR;
+                        result = MU_FAILURE;
+                    }
+                    else
+                    {
+                        // Increment the data
+                        dataBytes += codec_Data->bufferOffset++;
+                        *dataBytes = iterator;
+
+                        size_t totalLen = BUFFER_length(codec_Data->headerData);
+                        if (codec_Data->bufferOffset >= totalLen)
+                        {
+                            /* Codes_SRS_MQTT_CODEC_07_034: [Upon a constructing a complete MQTT packet mqtt_codec_bytesReceived shall call the ON_PACKET_COMPLETE_CALLBACK function.] */
+                            completePacketData(codec_Data);
+                        }
+                    }
+                }
+            }
+            else
+            {
+                /* Codes_SRS_MQTT_CODEC_07_035: [If any error is encountered then the packet state will be marked as error and mqtt_codec_bytesReceived shall return a non-zero value.] */
+                codec_Data->currPacket = PACKET_TYPE_ERROR;
+                result = MU_FAILURE;
+            }
+        }
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iot_sdk/umqtt/src/mqtt_message.c
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iot_sdk/umqtt/src/mqtt_message.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iot_sdk/umqtt/src/mqtt_message.c	(revision 453)
@@ -0,0 +1,372 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#include "azure_umqtt_c/mqtt_message.h"
+#include "azure_c_shared_utility/optimize_size.h"
+#include "azure_c_shared_utility/gballoc.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/string_token.h"
+#include "azure_macro_utils/macro_utils.h"
+
+typedef struct MQTT_MESSAGE_TAG
+{
+    uint16_t packetId;
+    QOS_VALUE qosInfo;
+
+    char* topicName;
+    APP_PAYLOAD appPayload;
+
+    const char* const_topic_name;
+    APP_PAYLOAD const_payload;
+
+    bool isDuplicateMsg;
+    bool isMessageRetained;
+} MQTT_MESSAGE;
+
+static MQTT_MESSAGE* create_msg_object(uint16_t packetId, QOS_VALUE qosValue)
+{
+    MQTT_MESSAGE* result;
+    result = (MQTT_MESSAGE*)malloc(sizeof(MQTT_MESSAGE));
+    if (result != NULL)
+    {
+        memset(result, 0, sizeof(MQTT_MESSAGE));
+        result->packetId = packetId;
+        result->isDuplicateMsg = false;
+        result->isMessageRetained = false;
+        result->qosInfo = qosValue;
+    }
+    else
+    {
+        LogError("Failure unable to allocate MQTT Message.");
+    }
+    return result;
+}
+
+MQTT_MESSAGE_HANDLE mqttmessage_create_in_place(uint16_t packetId, const char* topicName, QOS_VALUE qosValue, const uint8_t* appMsg, size_t appMsgLength)
+{
+    /* Codes_SRS_MQTTMESSAGE_07_026: [If the parameters topicName is NULL then mqttmessage_create_in_place shall return NULL.].] */
+    MQTT_MESSAGE* result;
+    if (topicName == NULL)
+    {
+        LogError("Invalid Parameter topicName: %p, packetId: %d.", topicName, packetId);
+        result = NULL;
+    }
+    else
+    {
+        result = create_msg_object(packetId, qosValue);
+        if (result == NULL)
+        {
+            /* Codes_SRS_MQTTMESSAGE_07_028: [If any memory allocation fails mqttmessage_create_in_place shall free any allocated memory and return NULL.] */
+            LogError("Failure creating message object");
+        }
+        else
+        {
+            /* Codes_SRS_MQTTMESSAGE_07_027: [mqttmessage_create_in_place shall use the a pointer to topicName or appMsg .] */
+            result->const_topic_name = topicName;
+            result->const_payload.length = appMsgLength;
+            if (result->const_payload.length > 0)
+            {
+                result->const_payload.message = (uint8_t*)appMsg;
+            }
+        }
+    }
+    /* Codes_SRS_MQTTMESSAGE_07_029: [ Upon success, mqttmessage_create_in_place shall return a NON-NULL MQTT_MESSAGE_HANDLE value.] */
+    return (MQTT_MESSAGE_HANDLE)result;
+}
+
+MQTT_MESSAGE_HANDLE mqttmessage_create(uint16_t packetId, const char* topicName, QOS_VALUE qosValue, const uint8_t* appMsg, size_t appMsgLength)
+{
+    /* Codes_SRS_MQTTMESSAGE_07_001:[If the parameters topicName is NULL is zero then mqttmessage_create shall return NULL.] */
+    MQTT_MESSAGE* result;
+    if (topicName == NULL)
+    {
+        LogError("Invalid Parameter topicName: %p, packetId: %d.", topicName, packetId);
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_MQTTMESSAGE_07_002: [mqttmessage_create shall allocate and copy the topicName and appMsg parameters.] */
+        result = create_msg_object(packetId, qosValue);
+        if (result == NULL)
+        {
+            /* Codes_SRS_MQTTMESSAGE_07_028: [If any memory allocation fails mqttmessage_create_in_place shall free any allocated memory and return NULL.] */
+            LogError("Failure creating message object");
+        }
+        else
+        {
+            if (mallocAndStrcpy_s(&result->topicName, topicName) != 0)
+            {
+                /* Codes_SRS_MQTTMESSAGE_07_003: [If any memory allocation fails mqttmessage_create shall free any allocated memory and return NULL.] */
+                LogError("Failure allocating topic name");
+                free(result);
+                result = NULL;
+            }
+            else
+            {
+                /* Codes_SRS_MQTTMESSAGE_07_002: [mqttmessage_create shall allocate and copy the topicName and appMsg parameters.] */
+                result->appPayload.length = appMsgLength;
+                if (result->appPayload.length > 0)
+                {
+                    result->appPayload.message = malloc(appMsgLength);
+                    if (result->appPayload.message == NULL)
+                    {
+                        /* Codes_SRS_MQTTMESSAGE_07_003: [If any memory allocation fails mqttmessage_create shall free any allocated memory and return NULL.] */
+                        LogError("Failure allocating message value of %lu", (unsigned long)appMsgLength);
+                        free(result->topicName);
+                        free(result);
+                        result = NULL;
+                    }
+                    else
+                    {
+                        (void)memcpy(result->appPayload.message, appMsg, appMsgLength);
+                    }
+                }
+                else
+                {
+                    result->appPayload.message = NULL;
+                }
+            }
+        }
+    }
+    /* Codes_SRS_MQTTMESSAGE_07_004: [If mqttmessage_createMessage succeeds the it shall return a NON-NULL MQTT_MESSAGE_HANDLE value.] */
+    return (MQTT_MESSAGE_HANDLE)result;
+}
+
+void mqttmessage_destroy(MQTT_MESSAGE_HANDLE handle)
+{
+    /* Codes_SRS_MQTTMESSAGE_07_005: [If the handle parameter is NULL then mqttmessage_destroyMessage shall do nothing] */
+    if (handle != NULL)
+    {
+        /* Codes_SRS_MQTTMESSAGE_07_006: [mqttmessage_destroyMessage shall free all resources associated with the MQTT_MESSAGE_HANDLE value] */
+        if (handle->topicName != NULL)
+        {
+            free(handle->topicName);
+        }
+        if (handle->appPayload.message != NULL)
+        {
+            free(handle->appPayload.message);
+        }
+        free(handle);
+    }
+}
+
+MQTT_MESSAGE_HANDLE mqttmessage_clone(MQTT_MESSAGE_HANDLE handle)
+{
+    MQTT_MESSAGE_HANDLE result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_MQTTMESSAGE_07_007: [If handle parameter is NULL then mqttmessage_clone shall return NULL.] */
+        LogError("Invalid Parameter handle: %p.", handle);
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_MQTTMESSAGE_07_008: [mqttmessage_clone shall create a new MQTT_MESSAGE_HANDLE with data content identical of the handle value.] */
+        result = mqttmessage_create(handle->packetId, handle->topicName, handle->qosInfo, handle->appPayload.message, handle->appPayload.length);
+        if (result != NULL)
+        {
+            result->isDuplicateMsg = handle->isDuplicateMsg;
+            result->isMessageRetained = handle->isMessageRetained;
+        }
+    }
+    return result;
+}
+
+uint16_t mqttmessage_getPacketId(MQTT_MESSAGE_HANDLE handle)
+{
+    uint16_t result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_MQTTMESSAGE_07_010: [If handle is NULL then mqttmessage_getPacketId shall return 0.] */
+        LogError("Invalid Parameter handle: %p.", handle);
+        result = 0;
+    }
+    else
+    {
+        /* Codes_SRS_MQTTMESSAGE_07_011: [mqttmessage_getPacketId shall return the packetId value contained in MQTT_MESSAGE_HANDLE handle.] */
+        result = handle->packetId;
+    }
+    return result;
+}
+
+const char* mqttmessage_getTopicName(MQTT_MESSAGE_HANDLE handle)
+{
+    const char* result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_MQTTMESSAGE_07_012: [If handle is NULL then mqttmessage_getTopicName shall return a NULL string.] */
+        LogError("Invalid Parameter handle: %p.", handle);
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_MQTTMESSAGE_07_013: [mqttmessage_getTopicName shall return the topicName contained in MQTT_MESSAGE_HANDLE handle.] */
+        if (handle->topicName == NULL)
+        {
+            result = handle->const_topic_name;
+        }
+        else
+        {
+            result = handle->topicName;
+        }
+    }
+    return result;
+}
+
+int mqttmessage_getTopicLevels(MQTT_MESSAGE_HANDLE handle, char*** levels, size_t* count)
+{
+    int result;
+
+    // Codes_SRS_MQTTMESSAGE_09_001: [ If `handle`, `levels` or `count` are NULL the function shall return a non-zero value. ]
+    if (handle == NULL || levels == NULL || count == NULL)
+    {
+        LogError("Invalid Parameter handle: %p, levels: %p, count: %p", handle, levels, count);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        MQTT_MESSAGE* msgInfo = (MQTT_MESSAGE*)handle;
+
+        const char* topic_name = msgInfo->topicName != NULL ? msgInfo->topicName : msgInfo->const_topic_name;
+
+        if (topic_name == NULL)
+        {
+            LogError("Topic name is NULL");
+            result = MU_FAILURE;
+        }
+        else
+        {
+            const char* delimiters[1];
+
+            delimiters[0] = "/";
+
+            // Codes_SRS_MQTTMESSAGE_09_002: [ The topic name, excluding the property bag, shall be split into individual tokens using "/" as separator ]
+            // Codes_SRS_MQTTMESSAGE_09_004: [ The split tokens shall be stored in `levels` and its count in `count` ]
+            if (StringToken_Split(topic_name, strlen(topic_name), delimiters, 1, false, levels, count) != 0)
+            {
+                // Codes_SRS_MQTTMESSAGE_09_003: [ If splitting fails the function shall return a non-zero value. ]
+                LogError("Failed splitting topic levels");
+                result = MU_FAILURE;
+            }
+            else
+            {
+                // Codes_SRS_MQTTMESSAGE_09_005: [ If no failures occur the function shall return zero. ]
+                result = 0;
+            }
+        }
+    }
+
+    return result;
+}
+
+QOS_VALUE mqttmessage_getQosType(MQTT_MESSAGE_HANDLE handle)
+{
+    QOS_VALUE result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_MQTTMESSAGE_07_014: [If handle is NULL then mqttmessage_getQosType shall return the default DELIVER_AT_MOST_ONCE value.] */
+        LogError("Invalid Parameter handle: %p.", handle);
+        result = DELIVER_AT_MOST_ONCE;
+    }
+    else
+    {
+        /* Codes_SRS_MQTTMESSAGE_07_015: [mqttmessage_getQosType shall return the QOS Type value contained in MQTT_MESSAGE_HANDLE handle.] */
+        result = handle->qosInfo;
+    }
+    return result;
+}
+
+bool mqttmessage_getIsDuplicateMsg(MQTT_MESSAGE_HANDLE handle)
+{
+    bool result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_MQTTMESSAGE_07_016: [If handle is NULL then mqttmessage_getIsDuplicateMsg shall return false.] */
+        LogError("Invalid Parameter handle: %p.", handle);
+        result = false;
+    }
+    else
+    {
+        /* Codes_SRS_MQTTMESSAGE_07_017: [mqttmessage_getIsDuplicateMsg shall return the isDuplicateMsg value contained in MQTT_MESSAGE_HANDLE handle.] */
+        result = handle->isDuplicateMsg;
+    }
+    return result;
+}
+
+bool mqttmessage_getIsRetained(MQTT_MESSAGE_HANDLE handle)
+{
+    bool result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_MQTTMESSAGE_07_018: [If handle is NULL then mqttmessage_getIsRetained shall return false.] */
+        LogError("Invalid Parameter handle: %p.", handle);
+        result = false;
+    }
+    else
+    {
+        /* Codes_SRS_MQTTMESSAGE_07_019: [mqttmessage_getIsRetained shall return the isRetained value contained in MQTT_MESSAGE_HANDLE handle.] */
+        result = handle->isMessageRetained;
+    }
+    return result;
+}
+
+int mqttmessage_setIsDuplicateMsg(MQTT_MESSAGE_HANDLE handle, bool duplicateMsg)
+{
+    int result;
+    /* Codes_SRS_MQTTMESSAGE_07_022: [If handle is NULL then mqttmessage_setIsDuplicateMsg shall return a non-zero value.] */
+    if (handle == NULL)
+    {
+        LogError("Invalid Parameter handle: %p.", handle);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        /* Codes_SRS_MQTTMESSAGE_07_023: [mqttmessage_setIsDuplicateMsg shall store the duplicateMsg value in the MQTT_MESSAGE_HANDLE handle.] */
+        handle->isDuplicateMsg = duplicateMsg;
+        result = 0;
+    }
+    return result;
+}
+
+int mqttmessage_setIsRetained(MQTT_MESSAGE_HANDLE handle, bool retainMsg)
+{
+    int result;
+    /* Codes_SRS_MQTTMESSAGE_07_024: [If handle is NULL then mqttmessage_setIsRetained shall return a non-zero value.] */
+    if (handle == NULL)
+    {
+        LogError("Invalid Parameter handle: %p.", handle);
+        result = MU_FAILURE;
+    }
+    else
+    {
+        /* Codes_SRS_MQTTMESSAGE_07_025: [mqttmessage_setIsRetained shall store the retainMsg value in the MQTT_MESSAGE_HANDLE handle.] */
+        handle->isMessageRetained = retainMsg;
+        result = 0;
+    }
+    return result;
+}
+
+const APP_PAYLOAD* mqttmessage_getApplicationMsg(MQTT_MESSAGE_HANDLE handle)
+{
+    const APP_PAYLOAD* result;
+    if (handle == NULL)
+    {
+        /* Codes_SRS_MQTTMESSAGE_07_020: [If handle is NULL or if msgLen is 0 then mqttmessage_getApplicationMsg shall return NULL.] */
+        LogError("Invalid Parameter handle: %p.", handle);
+        result = NULL;
+    }
+    else
+    {
+        /* Codes_SRS_MQTTMESSAGE_07_021: [mqttmessage_getApplicationMsg shall return the applicationMsg value contained in MQTT_MESSAGE_HANDLE handle and the length of the appMsg in the msgLen parameter.] */
+        if (handle->const_payload.length > 0)
+        {
+            result = &handle->const_payload;
+        }
+        else
+        {
+            result = &handle->appPayload;
+        }
+    }
+    return result;
+}
Index: azure_iot_hub_riscv/trunk/azure_iothub.code-workspace
===================================================================
--- azure_iot_hub_riscv/trunk/azure_iothub.code-workspace	(revision 453)
+++ azure_iot_hub_riscv/trunk/azure_iothub.code-workspace	(revision 453)
@@ -0,0 +1,32 @@
+{
+	"folders": [
+		{
+			"path": "app_iothub_client"
+		},
+		{
+			"path": "asp_baseplatform"
+		},
+		{
+			"path": "azure_iot_sdk"
+		},
+		{
+			"path": "wolfssl-4.4.0"
+		},
+		{
+			"path": "zlib-1.2.11"
+		}
+	],
+	"settings": {
+		"terminal.integrated.shell.windows": "C:\\msys64\\usr\\bin\\bash.exe",
+		"terminal.integrated.shellArgs.windows": [
+			"--login",
+			"-i"
+		],
+		"terminal.integrated.env.windows": {
+			"PATH": "C:\\xpack-riscv-none-embed-gcc-8.3.0-1.2\\bin",
+			"CHERE_INVOKING": "1",
+			"MSYS2_PATH_TYPE": "inherit",
+			"MSYSTEM": "MINGW64"
+		}
+	}
+}
Index: azure_iot_hub_riscv/trunk/tools/kflash/LICENSE
===================================================================
--- azure_iot_hub_riscv/trunk/tools/kflash/LICENSE	(revision 453)
+++ azure_iot_hub_riscv/trunk/tools/kflash/LICENSE	(revision 453)
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 Kendryte
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
Index: azure_iot_hub_riscv/trunk/tools/kflash/README.rst
===================================================================
--- azure_iot_hub_riscv/trunk/tools/kflash/README.rst	(revision 453)
+++ azure_iot_hub_riscv/trunk/tools/kflash/README.rst	(revision 453)
@@ -0,0 +1,330 @@
+kflash, A Python-based Kendryte K210 UART ISP Utility
+=====================================================
+
+Usage
+-----
+
+.. code:: bash
+
+    # kflash --help
+    usage: kflash [-h] [-p PORT] [-f FLASH] [-b BAUDRATE] [-l BOOTLOADER]
+                    [-k KEY] [-v] [-t] [-n] [-s] [-B BOARD] [-S SLOW]
+                    firmware
+
+    positional arguments:
+    firmware              firmware bin path
+
+    optional arguments:
+    -h, --help            show this help message and exit
+    -p PORT, --port PORT  COM Port
+    -f FLASH, --flash FLASH
+                            SPI Flash type, 0 for SPI3, 1 for SPI0
+    -b BAUDRATE, --baudrate BAUDRATE
+                            UART baudrate for uploading firmware
+    -l BOOTLOADER, --bootloader BOOTLOADER
+                            bootloader bin path
+    -k KEY, --key KEY     AES key in hex, if you need encrypt your firmware.
+    -v, --verbose         increase output verbosity
+    -t, --terminal        Start a terminal after finish (Python miniterm)
+    -n, --noansi          Do not use ANSI colors, recommended in Windows CMD
+    -s, --sram            Download firmware to SRAM and boot
+    -B BOARD, --Board BOARD
+                            Select dev board, e.g. kd233, dan, bit, goD, goE or
+                            trainer
+    -S SLOW, --Slow SLOW  Slow download mode
+
+Attention
+---------
+
+Maixgo with openec firmware, BOARD must choose ``-B goE``, and should choose
+sencond com port.
+
+With cmsis-dap firmware(before 2019.02.21), BOARD must use ``-B goD``.
+
+You can update `new cmsis-dap firmware <http://blog.sipeed.com/p/352.html>`__, it is same as openec.
+
+For K210 Trainer V0.01b, BOARD must choose ``-B trainer``.
+
+For KD233, BOARD must choose ``-B kd233``, and the jumper for kd233 automatic
+download circuit must be set.
+
+Installation
+------------
+
+.. code:: bash
+
+    sudo pip3 install kflash
+
+If you receive an error, please try
+
+.. code:: bash
+
+    sudo python -m pip install kflash
+    sudo python3 -m pip install kflash
+    sudo pip install kflash
+    sudo pip2 install kflash
+
+For linux users, first of all, you must add yourself to dialout group.
+Or you have to use root permission every time.
+
+.. code:: bash
+
+    sudo usermod -a -G dialout $(whoami)
+
+Sample Usage
+------------
+
+.. code:: bash
+
+    # Linux or macOS
+    # Using pip
+    kflash -B dan firmware.bin
+    kflash -B dan -t firmware.bin # Open a Serial Terminal After Finish
+    # Using source code
+    python3 kflash.py -B dan firmware.bin
+    python3 kflash.py -B dan -t firmware.bin # Open a Serial Terminal After Finish
+
+    # Windows CMD or PowerShell
+    # Using pip
+    kflash -B dan firmware.bin
+    kflash -B dan -t firmware.bin # Open a Serial Terminal After Finish
+    kflash -B dan -n -t firmware.bin # Open a Serial Terminal After Finish, do not use ANSI colors
+    # Using source code
+    python kflash.py -B dan firmware.bin
+    python kflash.py -B dan -t firmware.bin # Open a Serial Terminal After Finish
+    python kflash.py -B dan -n -t firmware.bin # Open a Serial Terminal After Finish, do not use ANSI colors
+
+    # Windows Subsystem for Linux
+    # Using pip
+    sudo kflash -B dan -p /dev/ttyS13 firmware.bin # ttyS13 Stands for the COM13 in Device Manager
+    sudo kflash -B dan -p /dev/ttyS13 -t firmware.bin # Open a Serial Terminal After Finish
+    # Using source code
+    sudo python3 kflash.py -B dan -p /dev/ttyS13 firmware.bin # ttyS13 Stands for the COM13 in Device Manager
+    sudo python3 kflash.py -B dan -p /dev/ttyS13 -t firmware.bin # Open a Serial Terminal After Finish
+
+For fast programming,
+
+.. code:: bash
+
+    # Using pip
+    # This will enable opoenec super-baudrate!
+    kflash -b 4500000 -B goE firmware.bin
+    # Trainer could use 8000000 baudrate!
+    kflash -b 8000000 -B trainer firmware.bin
+    # Dan could use 3000000 baudrate!
+    kflash -b 3000000 -B dan firmware.bin
+
+    # Using source code
+    # This will enable opoenec super-baudrate!
+    python3 kflash.py -b 4500000 -B goE firmware.bin
+    # Trainer could use 8000000 baudrate!
+    python3 kflash.py -b 8000000 -B trainer firmware.bin
+    # Dan could use 3000000 baudrate!
+    python3 kflash.py -b 3000000 -B dan firmware.bin
+
+Execute user code directly in SRAM and view in serial terminal,
+
+.. code:: bash
+
+    # Using pip
+    # For `.elf` file
+    kflash -b 115200 -B goE -s -t hello_world
+    # For `.bin` file
+    kflash -b 115200 -B goE -s -t hello_world.bin
+
+    # Using source code
+    # For `.elf` file
+    python3 kflash.py -b 115200 -B goE -s -t hello_world
+    # For `.bin` file
+    python3 kflash.py -b 115200 -B goE -s -t hello_world.bin
+
+Requirements
+------------
+
+-  python>=3 or python=2.7
+-  pyserial>=3.4
+-  pyelftools>=0.25
+
+    Python3 is recommended.
+
+If your python version below python3.4, you need:
+
+-  enum34>=1.1.6
+
+Windows Requirements
+~~~~~~~~~~~~~~~~~~~~
+
+-  Download and Install `Python3 at python.org <https://www.python.org/downloads/release/python-367/>`__
+-  Download the `get-pip.py at https://bootstrap.pypa.io/get-pip.py <https://bootstrap.pypa.io/get-pip.py>`__
+-  Start CMD or PowerShell Terminal and run the following command
+
+.. code:: bash
+
+    python get-pip.py
+    python -m pip install pyserial
+    python -m pip install pyelftools
+    # When you python version below python3.4
+    python -m pip install enum34
+
+--------------
+
+macOS Requirements
+~~~~~~~~~~~~~~~~~~
+
+.. code:: bash
+
+    # Install Homebrew, an awesome package manager for macOS
+    /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
+    brew install python
+    python3 -m pip3 install pyserial
+    python3 -m pip3 install pyelftools
+
+--------------
+
+Ubuntu, Debian Requirements
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code:: bash
+
+    sudo apt update
+    sudo apt install python3 python3-pip
+    sudo pip3 install pyserial
+    sudo pip3 install pyelftools
+
+--------------
+
+Fedora
+~~~~~~
+
+.. code:: bash
+
+    sudo dnf install python3
+    sudo python3 -m pip install pyserial
+    sudo python3 -m pip install pyelftools
+
+--------------
+
+CentOS
+~~~~~~
+
+.. code:: bash
+
+    sudo yum -y install epel-release
+    sudo yum -y install python36u python36u-pip
+    sudo ln -s /bin/python3.6 /usr/bin/python3
+    sudo ln -s /bin/pip3.6 /usr/bin/pip3
+    sudo pip3 install pyserial
+    sudo pip3 install pyelftools
+
+Trouble Shooting
+----------------
+
+Could not open port /dev/tty*: [Errno 13] Permission denied: '/dev/tty*'
+------------------------------------------------------------------------
+
+    For Windows Subsystem for Linux, you may have to use sudo due to its docker
+    like feature
+
+-  Add your self to a dialout group to use usb-to-uart devices by
+
+.. code:: bash
+
+    sudo usermod -a -G dialout $(whoami)
+
+-  Logout, and log in.
+
+--------------
+
+UART Auto Detecting is Not Working, or Select the Wrong UART Port
+-----------------------------------------------------------------
+
+Windows
+~~~~~~~
+
+-  Check the COM Number for your device at the Device Manager, such as
+   **USB-SERIAL CH340(COM13)**.
+
+.. code:: bash
+
+    # Using pip, only need once when you install
+    pip install kflash
+    kflash -p COM13 firmware.bin
+    # Or
+    kflash.exe -p COM13 firmware.bin
+    # Using source code
+    python kflash.py -p COM13 firmware.bin
+
+Windows Subsystem For Linux(WSL)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+-  Check the COM Number for your device at the Device Manager, such as
+   **USB-SERIAL CH340(COM13)**.
+
+.. code:: bash
+
+    # Using pip, only need once when you install
+    sudo pip3 install kflash
+    sudo kflash -p /dev/ttyS13 firmware.bin # You have to use *sudo* here
+    # Using source code
+    sudo python3 kflash.py -p /dev/ttyS13 firmware.bin # You have to use *sudo* here
+
+Linux
+~~~~~
+
+-  Check the USB Device Name, Usually presented as ttyUSB\*
+
+.. code:: bash
+
+    ls /dev/ttyUSB*
+
+-  It will print :
+
+.. code:: bash
+
+    $ ls /dev/ttyUSB*
+    /dev/ttyUSB0
+    /dev/ttyUSB2
+    /dev/ttyUSB13
+
+-  Choose the one you think belongs to your device, or you may try multimule
+   names.
+
+.. code:: bash
+
+    # Using pip
+    python3 kflash.py -p /dev/ttyUSB13 firmware.bin
+    # Using source code
+    kflash -p /dev/ttyUSB13 firmware.bin
+
+macOS
+~~~~~
+
+-  Check the USB Device Name, Usually presented as cu.\*
+
+.. code:: bash
+
+    ls /dev/cu.*
+
+-  It will print :
+
+.. code:: bash
+
+    $ ls /dev/ttyUSB*
+    /dev/cu.wchusbserial1410
+    /dev/cu.wchusbserial1437
+    /dev/cu.SLAB_USBtoUART2333
+
+-  Choose the one you think belongs to your device, or you may try multimule
+   names.
+
+.. code:: bash
+
+    # Using pip
+    kflash -p /dev/cu.wchusbserial1410 firmware.bin
+    # Using source code
+    python3 kflash.py -p /dev/cu.wchusbserial1410 firmware.bin
+
+You may unable to find the device even in the /dev, check the link below for
+drivers
+
+-  For K210 and Sipeed Dan -> `WCH CH34x USB2UART Chip <https://github.com/adrianmihalko/ch340g-ch34g-ch34x-mac-os-x-driver>`__
Index: azure_iot_hub_riscv/trunk/tools/kflash/kflash.py
===================================================================
--- azure_iot_hub_riscv/trunk/tools/kflash/kflash.py	(revision 453)
+++ azure_iot_hub_riscv/trunk/tools/kflash/kflash.py	(revision 453)
@@ -0,0 +1,1548 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from __future__ import (division, print_function)
+
+import sys
+import time
+import zlib
+import copy
+import struct
+import binascii
+import hashlib
+import argparse
+import math
+import zipfile, tempfile
+import json
+import re
+import os
+
+
+class KFlash:
+    print_callback = None
+
+    def __init__(self, print_callback = None):
+        self.killProcess = False
+        self.loader = None
+        KFlash.print_callback = print_callback
+
+    @staticmethod
+    def log(*args, **kwargs):
+        if KFlash.print_callback:
+            KFlash.print_callback(*args, **kwargs)
+        else:
+            print(*args, **kwargs)
+
+    def process(self, terminal=True, dev="", baudrate=1500000, board=None, sram = False, file="", callback=None, noansi=False, terminal_auto_size=False, terminal_size=(50, 1), slow_mode = False, addr=None, length=None):
+        self.killProcess = False
+        BASH_TIPS = dict(NORMAL='\033[0m',BOLD='\033[1m',DIM='\033[2m',UNDERLINE='\033[4m',
+                            DEFAULT='\033[0m', RED='\033[31m', YELLOW='\033[33m', GREEN='\033[32m',
+                            BG_DEFAULT='\033[49m', BG_WHITE='\033[107m')
+
+        ERROR_MSG   = BASH_TIPS['RED']+BASH_TIPS['BOLD']+'[ERROR]'+BASH_TIPS['NORMAL']
+        WARN_MSG    = BASH_TIPS['YELLOW']+BASH_TIPS['BOLD']+'[WARN]'+BASH_TIPS['NORMAL']
+        INFO_MSG    = BASH_TIPS['GREEN']+BASH_TIPS['BOLD']+'[INFO]'+BASH_TIPS['NORMAL']
+
+        VID_LIST_FOR_AUTO_LOOKUP = "(1A86)|(0403)|(067B)|(10C4)|(C251)|(0403)"
+        #                            WCH    FTDI    PL     CL    DAP   OPENEC
+        ISP_RECEIVE_TIMEOUT = 0.5
+
+        MAX_RETRY_TIMES = 10
+
+        ISP_FLASH_SECTOR_SIZE = 4096
+        ISP_FLASH_DATA_FRAME_SIZE = ISP_FLASH_SECTOR_SIZE * 16
+
+        def tuple2str(t):
+            ret = ""
+            for i in t:
+                ret += i+" "
+            return ret
+
+        def raise_exception(exception):
+            if self.loader:
+                try:
+                    self.loader._port.close()
+                except Exception:
+                    pass
+            raise exception
+
+        try:
+            from enum import Enum
+        except ImportError:
+            err = (ERROR_MSG,'enum34 must be installed, run '+BASH_TIPS['GREEN']+'`' + ('pip', 'pip3')[sys.version_info > (3, 0)] + ' install enum34`',BASH_TIPS['DEFAULT'])
+            err = tuple2str(err)
+            raise Exception(err)
+        try:
+            import serial
+            import serial.tools.list_ports
+        except ImportError:
+            err = (ERROR_MSG,'PySerial must be installed, run '+BASH_TIPS['GREEN']+'`' + ('pip', 'pip3')[sys.version_info > (3, 0)] + ' install pyserial`',BASH_TIPS['DEFAULT'])
+            err = tuple2str(err)
+            raise Exception(err)
+
+        class TimeoutError(Exception): pass
+
+        class ProgramFileFormat(Enum):
+            FMT_BINARY = 0
+            FMT_ELF = 1
+            FMT_KFPKG = 2
+
+        # AES is from: https://github.com/ricmoo/pyaes, Copyright by Richard Moore
+        class AES:
+            '''Encapsulates the AES block cipher.
+            You generally should not need this. Use the AESModeOfOperation classes
+            below instead.'''
+            @staticmethod
+            def _compact_word(word):
+                return (word[0] << 24) | (word[1] << 16) | (word[2] << 8) | word[3]
+
+            # Number of rounds by keysize
+            number_of_rounds = {16: 10, 24: 12, 32: 14}
+
+            # Round constant words
+            rcon = [ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 ]
+
+            # S-box and Inverse S-box (S is for Substitution)
+            S = [ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 ]
+            Si =[ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d ]
+
+            # Transformations for encryption
+            T1 = [ 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a ]
+            T2 = [ 0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5, 0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676, 0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d, 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0, 0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0, 0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc, 0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1, 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515, 0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a, 0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575, 0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a, 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0, 0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, 0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484, 0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b, 0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939, 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf, 0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, 0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585, 0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8, 0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f, 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5, 0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2, 0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec, 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717, 0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d, 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373, 0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888, 0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414, 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb, 0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a, 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c, 0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979, 0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9, 0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea, 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808, 0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6, 0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a, 0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666, 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e, 0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, 0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e, 0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494, 0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9, 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf, 0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, 0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868, 0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616 ]
+            T3 = [ 0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5, 0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76, 0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d, 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0, 0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0, 0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc, 0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1, 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15, 0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a, 0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75, 0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a, 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0, 0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, 0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384, 0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b, 0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239, 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf, 0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, 0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185, 0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8, 0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f, 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5, 0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2, 0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec, 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17, 0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d, 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673, 0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88, 0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814, 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb, 0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a, 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c, 0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279, 0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9, 0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea, 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008, 0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6, 0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a, 0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66, 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e, 0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, 0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e, 0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394, 0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9, 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df, 0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, 0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068, 0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16 ]
+            T4 = [ 0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491, 0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec, 0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa, 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb, 0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b, 0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83, 0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9, 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a, 0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f, 0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea, 0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34, 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b, 0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, 0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713, 0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6, 0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72, 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85, 0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, 0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411, 0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b, 0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05, 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1, 0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf, 0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3, 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e, 0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a, 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6, 0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b, 0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28, 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad, 0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14, 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8, 0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2, 0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049, 0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf, 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810, 0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197, 0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f, 0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc, 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c, 0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, 0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927, 0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733, 0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9, 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5, 0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, 0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0, 0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c ]
+
+            # Transformations for decryption
+            T5 = [ 0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94, 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c, 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a, 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8, 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5, 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6, 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86, 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742 ]
+            T6 = [ 0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e, 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303, 0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c, 0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3, 0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0, 0x02c32f75, 0x12814cf0, 0xa38d4697, 0xc66bd3f9, 0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259, 0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8, 0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971, 0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a, 0x1863df4a, 0x82e51a31, 0x60975133, 0x4562537f, 0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b, 0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8, 0x23ab73d3, 0xe2724b02, 0x57e31f8f, 0x2a6655ab, 0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708, 0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682, 0x2b8acf1c, 0x92a779b4, 0xf0f307f2, 0xa14e69e2, 0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe, 0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb, 0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10, 0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd, 0xb591548d, 0x0571c45d, 0x6f0406d4, 0xff605015, 0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e, 0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee, 0x47a17c0a, 0xe97c420f, 0xc9f8841e, 0x00000000, 0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72, 0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39, 0x640a0fd9, 0x21685ca6, 0xd19b5b54, 0x3a24362e, 0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91, 0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a, 0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17, 0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9, 0x8557f119, 0x4caf7507, 0xbbee99dd, 0xfda37f60, 0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e, 0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1, 0xcad731dc, 0x10426385, 0x40139722, 0x2084c611, 0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1, 0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3, 0x6c2bb316, 0x99a970b9, 0xfa119448, 0x2247e964, 0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390, 0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b, 0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf, 0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46, 0xc2f68d13, 0xe890d8b8, 0x5e2e39f7, 0xf582c3af, 0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512, 0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb, 0x09cd2678, 0xf46e5918, 0x01ec9ab7, 0xa8834f9a, 0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8, 0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c, 0xaf31a4b2, 0x312a3f23, 0x30c6a594, 0xc035a266, 0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8, 0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6, 0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604, 0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551, 0x049d5eea, 0x5d018c35, 0x73fa8774, 0x2efb0b41, 0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647, 0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c, 0xeecea927, 0x35b761c9, 0xede11ce5, 0x3c7a47b1, 0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737, 0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db, 0x81caaff3, 0x3eb968c4, 0x2c382434, 0x5fc2a340, 0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95, 0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1, 0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857 ]
+            T7 = [ 0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27, 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3, 0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502, 0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562, 0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe, 0x7502c32f, 0xf012814c, 0x97a38d46, 0xf9c66bd3, 0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552, 0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9, 0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9, 0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce, 0x4a1863df, 0x3182e51a, 0x33609751, 0x7f456253, 0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908, 0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b, 0xd323ab73, 0x02e2724b, 0x8f57e31f, 0xab2a6655, 0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337, 0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16, 0x1c2b8acf, 0xb492a779, 0xf2f0f307, 0xe2a14e69, 0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6, 0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6, 0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e, 0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6, 0x8db59154, 0x5d0571c4, 0xd46f0406, 0x15ff6050, 0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9, 0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8, 0x0a47a17c, 0x0fe97c42, 0x1ec9f884, 0x00000000, 0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a, 0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d, 0xd9640a0f, 0xa621685c, 0x54d19b5b, 0x2e3a2436, 0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b, 0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12, 0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b, 0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e, 0x198557f1, 0x074caf75, 0xddbbee99, 0x60fda37f, 0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb, 0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4, 0xdccad731, 0x85104263, 0x22401397, 0x112084c6, 0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729, 0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1, 0x166c2bb3, 0xb999a970, 0x48fa1194, 0x642247e9, 0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233, 0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4, 0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad, 0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e, 0x13c2f68d, 0xb8e890d8, 0xf75e2e39, 0xaff582c3, 0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25, 0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b, 0x7809cd26, 0x18f46e59, 0xb701ec9a, 0x9aa8834f, 0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15, 0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0, 0xb2af31a4, 0x23312a3f, 0x9430c6a5, 0x66c035a2, 0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7, 0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791, 0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496, 0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665, 0xea049d5e, 0x355d018c, 0x7473fa87, 0x412efb0b, 0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6, 0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13, 0x27eecea9, 0xc935b761, 0xe5ede11c, 0xb13c7a47, 0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7, 0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844, 0xf381caaf, 0xc43eb968, 0x342c3824, 0x405fc2a3, 0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d, 0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456, 0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8 ]
+            T8 = [ 0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b, 0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5, 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5, 0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d, 0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b, 0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95, 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e, 0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27, 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d, 0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562, 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9, 0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752, 0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66, 0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3, 0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced, 0xcf1c2b8a, 0x79b492a7, 0x07f2f0f3, 0x69e2a14e, 0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4, 0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4, 0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd, 0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d, 0x548db591, 0xc45d0571, 0x06d46f04, 0x5015ff60, 0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767, 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79, 0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x00000000, 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c, 0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736, 0x0fd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24, 0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b, 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c, 0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12, 0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814, 0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3, 0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b, 0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8, 0x31dccad7, 0x63851042, 0x97224013, 0xc6112084, 0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7, 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077, 0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247, 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22, 0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698, 0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f, 0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254, 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582, 0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf, 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb, 0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883, 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef, 0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629, 0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035, 0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533, 0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17, 0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4, 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46, 0x5eea049d, 0x8c355d01, 0x877473fa, 0x0b412efb, 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d, 0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb, 0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a, 0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73, 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678, 0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2, 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff, 0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064, 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0 ]
+
+            # Transformations for decryption key expansion
+            U1 = [ 0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f, 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba, 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3 ]
+            U2 = [ 0x00000000, 0x0b0e090d, 0x161c121a, 0x1d121b17, 0x2c382434, 0x27362d39, 0x3a24362e, 0x312a3f23, 0x58704868, 0x537e4165, 0x4e6c5a72, 0x4562537f, 0x74486c5c, 0x7f466551, 0x62547e46, 0x695a774b, 0xb0e090d0, 0xbbee99dd, 0xa6fc82ca, 0xadf28bc7, 0x9cd8b4e4, 0x97d6bde9, 0x8ac4a6fe, 0x81caaff3, 0xe890d8b8, 0xe39ed1b5, 0xfe8ccaa2, 0xf582c3af, 0xc4a8fc8c, 0xcfa6f581, 0xd2b4ee96, 0xd9bae79b, 0x7bdb3bbb, 0x70d532b6, 0x6dc729a1, 0x66c920ac, 0x57e31f8f, 0x5ced1682, 0x41ff0d95, 0x4af10498, 0x23ab73d3, 0x28a57ade, 0x35b761c9, 0x3eb968c4, 0x0f9357e7, 0x049d5eea, 0x198f45fd, 0x12814cf0, 0xcb3bab6b, 0xc035a266, 0xdd27b971, 0xd629b07c, 0xe7038f5f, 0xec0d8652, 0xf11f9d45, 0xfa119448, 0x934be303, 0x9845ea0e, 0x8557f119, 0x8e59f814, 0xbf73c737, 0xb47dce3a, 0xa96fd52d, 0xa261dc20, 0xf6ad766d, 0xfda37f60, 0xe0b16477, 0xebbf6d7a, 0xda955259, 0xd19b5b54, 0xcc894043, 0xc787494e, 0xaedd3e05, 0xa5d33708, 0xb8c12c1f, 0xb3cf2512, 0x82e51a31, 0x89eb133c, 0x94f9082b, 0x9ff70126, 0x464de6bd, 0x4d43efb0, 0x5051f4a7, 0x5b5ffdaa, 0x6a75c289, 0x617bcb84, 0x7c69d093, 0x7767d99e, 0x1e3daed5, 0x1533a7d8, 0x0821bccf, 0x032fb5c2, 0x32058ae1, 0x390b83ec, 0x241998fb, 0x2f1791f6, 0x8d764dd6, 0x867844db, 0x9b6a5fcc, 0x906456c1, 0xa14e69e2, 0xaa4060ef, 0xb7527bf8, 0xbc5c72f5, 0xd50605be, 0xde080cb3, 0xc31a17a4, 0xc8141ea9, 0xf93e218a, 0xf2302887, 0xef223390, 0xe42c3a9d, 0x3d96dd06, 0x3698d40b, 0x2b8acf1c, 0x2084c611, 0x11aef932, 0x1aa0f03f, 0x07b2eb28, 0x0cbce225, 0x65e6956e, 0x6ee89c63, 0x73fa8774, 0x78f48e79, 0x49deb15a, 0x42d0b857, 0x5fc2a340, 0x54ccaa4d, 0xf741ecda, 0xfc4fe5d7, 0xe15dfec0, 0xea53f7cd, 0xdb79c8ee, 0xd077c1e3, 0xcd65daf4, 0xc66bd3f9, 0xaf31a4b2, 0xa43fadbf, 0xb92db6a8, 0xb223bfa5, 0x83098086, 0x8807898b, 0x9515929c, 0x9e1b9b91, 0x47a17c0a, 0x4caf7507, 0x51bd6e10, 0x5ab3671d, 0x6b99583e, 0x60975133, 0x7d854a24, 0x768b4329, 0x1fd13462, 0x14df3d6f, 0x09cd2678, 0x02c32f75, 0x33e91056, 0x38e7195b, 0x25f5024c, 0x2efb0b41, 0x8c9ad761, 0x8794de6c, 0x9a86c57b, 0x9188cc76, 0xa0a2f355, 0xabacfa58, 0xb6bee14f, 0xbdb0e842, 0xd4ea9f09, 0xdfe49604, 0xc2f68d13, 0xc9f8841e, 0xf8d2bb3d, 0xf3dcb230, 0xeecea927, 0xe5c0a02a, 0x3c7a47b1, 0x37744ebc, 0x2a6655ab, 0x21685ca6, 0x10426385, 0x1b4c6a88, 0x065e719f, 0x0d507892, 0x640a0fd9, 0x6f0406d4, 0x72161dc3, 0x791814ce, 0x48322bed, 0x433c22e0, 0x5e2e39f7, 0x552030fa, 0x01ec9ab7, 0x0ae293ba, 0x17f088ad, 0x1cfe81a0, 0x2dd4be83, 0x26dab78e, 0x3bc8ac99, 0x30c6a594, 0x599cd2df, 0x5292dbd2, 0x4f80c0c5, 0x448ec9c8, 0x75a4f6eb, 0x7eaaffe6, 0x63b8e4f1, 0x68b6edfc, 0xb10c0a67, 0xba02036a, 0xa710187d, 0xac1e1170, 0x9d342e53, 0x963a275e, 0x8b283c49, 0x80263544, 0xe97c420f, 0xe2724b02, 0xff605015, 0xf46e5918, 0xc544663b, 0xce4a6f36, 0xd3587421, 0xd8567d2c, 0x7a37a10c, 0x7139a801, 0x6c2bb316, 0x6725ba1b, 0x560f8538, 0x5d018c35, 0x40139722, 0x4b1d9e2f, 0x2247e964, 0x2949e069, 0x345bfb7e, 0x3f55f273, 0x0e7fcd50, 0x0571c45d, 0x1863df4a, 0x136dd647, 0xcad731dc, 0xc1d938d1, 0xdccb23c6, 0xd7c52acb, 0xe6ef15e8, 0xede11ce5, 0xf0f307f2, 0xfbfd0eff, 0x92a779b4, 0x99a970b9, 0x84bb6bae, 0x8fb562a3, 0xbe9f5d80, 0xb591548d, 0xa8834f9a, 0xa38d4697 ]
+            U3 = [ 0x00000000, 0x0d0b0e09, 0x1a161c12, 0x171d121b, 0x342c3824, 0x3927362d, 0x2e3a2436, 0x23312a3f, 0x68587048, 0x65537e41, 0x724e6c5a, 0x7f456253, 0x5c74486c, 0x517f4665, 0x4662547e, 0x4b695a77, 0xd0b0e090, 0xddbbee99, 0xcaa6fc82, 0xc7adf28b, 0xe49cd8b4, 0xe997d6bd, 0xfe8ac4a6, 0xf381caaf, 0xb8e890d8, 0xb5e39ed1, 0xa2fe8cca, 0xaff582c3, 0x8cc4a8fc, 0x81cfa6f5, 0x96d2b4ee, 0x9bd9bae7, 0xbb7bdb3b, 0xb670d532, 0xa16dc729, 0xac66c920, 0x8f57e31f, 0x825ced16, 0x9541ff0d, 0x984af104, 0xd323ab73, 0xde28a57a, 0xc935b761, 0xc43eb968, 0xe70f9357, 0xea049d5e, 0xfd198f45, 0xf012814c, 0x6bcb3bab, 0x66c035a2, 0x71dd27b9, 0x7cd629b0, 0x5fe7038f, 0x52ec0d86, 0x45f11f9d, 0x48fa1194, 0x03934be3, 0x0e9845ea, 0x198557f1, 0x148e59f8, 0x37bf73c7, 0x3ab47dce, 0x2da96fd5, 0x20a261dc, 0x6df6ad76, 0x60fda37f, 0x77e0b164, 0x7aebbf6d, 0x59da9552, 0x54d19b5b, 0x43cc8940, 0x4ec78749, 0x05aedd3e, 0x08a5d337, 0x1fb8c12c, 0x12b3cf25, 0x3182e51a, 0x3c89eb13, 0x2b94f908, 0x269ff701, 0xbd464de6, 0xb04d43ef, 0xa75051f4, 0xaa5b5ffd, 0x896a75c2, 0x84617bcb, 0x937c69d0, 0x9e7767d9, 0xd51e3dae, 0xd81533a7, 0xcf0821bc, 0xc2032fb5, 0xe132058a, 0xec390b83, 0xfb241998, 0xf62f1791, 0xd68d764d, 0xdb867844, 0xcc9b6a5f, 0xc1906456, 0xe2a14e69, 0xefaa4060, 0xf8b7527b, 0xf5bc5c72, 0xbed50605, 0xb3de080c, 0xa4c31a17, 0xa9c8141e, 0x8af93e21, 0x87f23028, 0x90ef2233, 0x9de42c3a, 0x063d96dd, 0x0b3698d4, 0x1c2b8acf, 0x112084c6, 0x3211aef9, 0x3f1aa0f0, 0x2807b2eb, 0x250cbce2, 0x6e65e695, 0x636ee89c, 0x7473fa87, 0x7978f48e, 0x5a49deb1, 0x5742d0b8, 0x405fc2a3, 0x4d54ccaa, 0xdaf741ec, 0xd7fc4fe5, 0xc0e15dfe, 0xcdea53f7, 0xeedb79c8, 0xe3d077c1, 0xf4cd65da, 0xf9c66bd3, 0xb2af31a4, 0xbfa43fad, 0xa8b92db6, 0xa5b223bf, 0x86830980, 0x8b880789, 0x9c951592, 0x919e1b9b, 0x0a47a17c, 0x074caf75, 0x1051bd6e, 0x1d5ab367, 0x3e6b9958, 0x33609751, 0x247d854a, 0x29768b43, 0x621fd134, 0x6f14df3d, 0x7809cd26, 0x7502c32f, 0x5633e910, 0x5b38e719, 0x4c25f502, 0x412efb0b, 0x618c9ad7, 0x6c8794de, 0x7b9a86c5, 0x769188cc, 0x55a0a2f3, 0x58abacfa, 0x4fb6bee1, 0x42bdb0e8, 0x09d4ea9f, 0x04dfe496, 0x13c2f68d, 0x1ec9f884, 0x3df8d2bb, 0x30f3dcb2, 0x27eecea9, 0x2ae5c0a0, 0xb13c7a47, 0xbc37744e, 0xab2a6655, 0xa621685c, 0x85104263, 0x881b4c6a, 0x9f065e71, 0x920d5078, 0xd9640a0f, 0xd46f0406, 0xc372161d, 0xce791814, 0xed48322b, 0xe0433c22, 0xf75e2e39, 0xfa552030, 0xb701ec9a, 0xba0ae293, 0xad17f088, 0xa01cfe81, 0x832dd4be, 0x8e26dab7, 0x993bc8ac, 0x9430c6a5, 0xdf599cd2, 0xd25292db, 0xc54f80c0, 0xc8448ec9, 0xeb75a4f6, 0xe67eaaff, 0xf163b8e4, 0xfc68b6ed, 0x67b10c0a, 0x6aba0203, 0x7da71018, 0x70ac1e11, 0x539d342e, 0x5e963a27, 0x498b283c, 0x44802635, 0x0fe97c42, 0x02e2724b, 0x15ff6050, 0x18f46e59, 0x3bc54466, 0x36ce4a6f, 0x21d35874, 0x2cd8567d, 0x0c7a37a1, 0x017139a8, 0x166c2bb3, 0x1b6725ba, 0x38560f85, 0x355d018c, 0x22401397, 0x2f4b1d9e, 0x642247e9, 0x692949e0, 0x7e345bfb, 0x733f55f2, 0x500e7fcd, 0x5d0571c4, 0x4a1863df, 0x47136dd6, 0xdccad731, 0xd1c1d938, 0xc6dccb23, 0xcbd7c52a, 0xe8e6ef15, 0xe5ede11c, 0xf2f0f307, 0xfffbfd0e, 0xb492a779, 0xb999a970, 0xae84bb6b, 0xa38fb562, 0x80be9f5d, 0x8db59154, 0x9aa8834f, 0x97a38d46 ]
+            U4 = [ 0x00000000, 0x090d0b0e, 0x121a161c, 0x1b171d12, 0x24342c38, 0x2d392736, 0x362e3a24, 0x3f23312a, 0x48685870, 0x4165537e, 0x5a724e6c, 0x537f4562, 0x6c5c7448, 0x65517f46, 0x7e466254, 0x774b695a, 0x90d0b0e0, 0x99ddbbee, 0x82caa6fc, 0x8bc7adf2, 0xb4e49cd8, 0xbde997d6, 0xa6fe8ac4, 0xaff381ca, 0xd8b8e890, 0xd1b5e39e, 0xcaa2fe8c, 0xc3aff582, 0xfc8cc4a8, 0xf581cfa6, 0xee96d2b4, 0xe79bd9ba, 0x3bbb7bdb, 0x32b670d5, 0x29a16dc7, 0x20ac66c9, 0x1f8f57e3, 0x16825ced, 0x0d9541ff, 0x04984af1, 0x73d323ab, 0x7ade28a5, 0x61c935b7, 0x68c43eb9, 0x57e70f93, 0x5eea049d, 0x45fd198f, 0x4cf01281, 0xab6bcb3b, 0xa266c035, 0xb971dd27, 0xb07cd629, 0x8f5fe703, 0x8652ec0d, 0x9d45f11f, 0x9448fa11, 0xe303934b, 0xea0e9845, 0xf1198557, 0xf8148e59, 0xc737bf73, 0xce3ab47d, 0xd52da96f, 0xdc20a261, 0x766df6ad, 0x7f60fda3, 0x6477e0b1, 0x6d7aebbf, 0x5259da95, 0x5b54d19b, 0x4043cc89, 0x494ec787, 0x3e05aedd, 0x3708a5d3, 0x2c1fb8c1, 0x2512b3cf, 0x1a3182e5, 0x133c89eb, 0x082b94f9, 0x01269ff7, 0xe6bd464d, 0xefb04d43, 0xf4a75051, 0xfdaa5b5f, 0xc2896a75, 0xcb84617b, 0xd0937c69, 0xd99e7767, 0xaed51e3d, 0xa7d81533, 0xbccf0821, 0xb5c2032f, 0x8ae13205, 0x83ec390b, 0x98fb2419, 0x91f62f17, 0x4dd68d76, 0x44db8678, 0x5fcc9b6a, 0x56c19064, 0x69e2a14e, 0x60efaa40, 0x7bf8b752, 0x72f5bc5c, 0x05bed506, 0x0cb3de08, 0x17a4c31a, 0x1ea9c814, 0x218af93e, 0x2887f230, 0x3390ef22, 0x3a9de42c, 0xdd063d96, 0xd40b3698, 0xcf1c2b8a, 0xc6112084, 0xf93211ae, 0xf03f1aa0, 0xeb2807b2, 0xe2250cbc, 0x956e65e6, 0x9c636ee8, 0x877473fa, 0x8e7978f4, 0xb15a49de, 0xb85742d0, 0xa3405fc2, 0xaa4d54cc, 0xecdaf741, 0xe5d7fc4f, 0xfec0e15d, 0xf7cdea53, 0xc8eedb79, 0xc1e3d077, 0xdaf4cd65, 0xd3f9c66b, 0xa4b2af31, 0xadbfa43f, 0xb6a8b92d, 0xbfa5b223, 0x80868309, 0x898b8807, 0x929c9515, 0x9b919e1b, 0x7c0a47a1, 0x75074caf, 0x6e1051bd, 0x671d5ab3, 0x583e6b99, 0x51336097, 0x4a247d85, 0x4329768b, 0x34621fd1, 0x3d6f14df, 0x267809cd, 0x2f7502c3, 0x105633e9, 0x195b38e7, 0x024c25f5, 0x0b412efb, 0xd7618c9a, 0xde6c8794, 0xc57b9a86, 0xcc769188, 0xf355a0a2, 0xfa58abac, 0xe14fb6be, 0xe842bdb0, 0x9f09d4ea, 0x9604dfe4, 0x8d13c2f6, 0x841ec9f8, 0xbb3df8d2, 0xb230f3dc, 0xa927eece, 0xa02ae5c0, 0x47b13c7a, 0x4ebc3774, 0x55ab2a66, 0x5ca62168, 0x63851042, 0x6a881b4c, 0x719f065e, 0x78920d50, 0x0fd9640a, 0x06d46f04, 0x1dc37216, 0x14ce7918, 0x2bed4832, 0x22e0433c, 0x39f75e2e, 0x30fa5520, 0x9ab701ec, 0x93ba0ae2, 0x88ad17f0, 0x81a01cfe, 0xbe832dd4, 0xb78e26da, 0xac993bc8, 0xa59430c6, 0xd2df599c, 0xdbd25292, 0xc0c54f80, 0xc9c8448e, 0xf6eb75a4, 0xffe67eaa, 0xe4f163b8, 0xedfc68b6, 0x0a67b10c, 0x036aba02, 0x187da710, 0x1170ac1e, 0x2e539d34, 0x275e963a, 0x3c498b28, 0x35448026, 0x420fe97c, 0x4b02e272, 0x5015ff60, 0x5918f46e, 0x663bc544, 0x6f36ce4a, 0x7421d358, 0x7d2cd856, 0xa10c7a37, 0xa8017139, 0xb3166c2b, 0xba1b6725, 0x8538560f, 0x8c355d01, 0x97224013, 0x9e2f4b1d, 0xe9642247, 0xe0692949, 0xfb7e345b, 0xf2733f55, 0xcd500e7f, 0xc45d0571, 0xdf4a1863, 0xd647136d, 0x31dccad7, 0x38d1c1d9, 0x23c6dccb, 0x2acbd7c5, 0x15e8e6ef, 0x1ce5ede1, 0x07f2f0f3, 0x0efffbfd, 0x79b492a7, 0x70b999a9, 0x6bae84bb, 0x62a38fb5, 0x5d80be9f, 0x548db591, 0x4f9aa883, 0x4697a38d ]
+
+            def __init__(self, key):
+
+                if len(key) not in (16, 24, 32):
+                    raise_exception( ValueError('Invalid key size') )
+
+                rounds = self.number_of_rounds[len(key)]
+
+                # Encryption round keys
+                self._Ke = [[0] * 4 for i in range(rounds + 1)]
+
+                # Decryption round keys
+                self._Kd = [[0] * 4 for i in range(rounds + 1)]
+
+                round_key_count = (rounds + 1) * 4
+                KC = len(key) // 4
+
+                # Convert the key into ints
+                tk = [ struct.unpack('>i', key[i:i + 4])[0] for i in range(0, len(key), 4) ]
+
+                # Copy values into round key arrays
+                for i in range(0, KC):
+                    self._Ke[i // 4][i % 4] = tk[i]
+                    self._Kd[rounds - (i // 4)][i % 4] = tk[i]
+
+                # Key expansion (fips-197 section 5.2)
+                rconpointer = 0
+                t = KC
+                while t < round_key_count:
+
+                    tt = tk[KC - 1]
+                    tk[0] ^= ((self.S[(tt >> 16) & 0xFF] << 24) ^
+                              (self.S[(tt >>  8) & 0xFF] << 16) ^
+                              (self.S[ tt        & 0xFF] <<  8) ^
+                               self.S[(tt >> 24) & 0xFF]        ^
+                              (self.rcon[rconpointer] << 24))
+                    rconpointer += 1
+
+                    if KC != 8:
+                        for i in range(1, KC):
+                            tk[i] ^= tk[i - 1]
+
+                    # Key expansion for 256-bit keys is "slightly different" (fips-197)
+                    else:
+                        for i in range(1, KC // 2):
+                            tk[i] ^= tk[i - 1]
+                        tt = tk[KC // 2 - 1]
+
+                        tk[KC // 2] ^= (self.S[ tt        & 0xFF]        ^
+                                       (self.S[(tt >>  8) & 0xFF] <<  8) ^
+                                       (self.S[(tt >> 16) & 0xFF] << 16) ^
+                                       (self.S[(tt >> 24) & 0xFF] << 24))
+
+                        for i in range(KC // 2 + 1, KC):
+                            tk[i] ^= tk[i - 1]
+
+                    # Copy values into round key arrays
+                    j = 0
+                    while j < KC and t < round_key_count:
+                        self._Ke[t // 4][t % 4] = tk[j]
+                        self._Kd[rounds - (t // 4)][t % 4] = tk[j]
+                        j += 1
+                        t += 1
+
+                # Inverse-Cipher-ify the decryption round key (fips-197 section 5.3)
+                for r in range(1, rounds):
+                    for j in range(0, 4):
+                        tt = self._Kd[r][j]
+                        self._Kd[r][j] = (self.U1[(tt >> 24) & 0xFF] ^
+                                          self.U2[(tt >> 16) & 0xFF] ^
+                                          self.U3[(tt >>  8) & 0xFF] ^
+                                          self.U4[ tt        & 0xFF])
+
+            def encrypt(self, plaintext):
+                'Encrypt a block of plain text using the AES block cipher.'
+
+                if len(plaintext) != 16:
+                    raise_exception( ValueError('wrong block length') )
+
+                rounds = len(self._Ke) - 1
+                (s1, s2, s3) = [1, 2, 3]
+                a = [0, 0, 0, 0]
+
+                # Convert plaintext to (ints ^ key)
+                t = [(AES._compact_word(plaintext[4 * i:4 * i + 4]) ^ self._Ke[0][i]) for i in range(0, 4)]
+
+                # Apply round transforms
+                for r in range(1, rounds):
+                    for i in range(0, 4):
+                        a[i] = (self.T1[(t[ i          ] >> 24) & 0xFF] ^
+                                self.T2[(t[(i + s1) % 4] >> 16) & 0xFF] ^
+                                self.T3[(t[(i + s2) % 4] >>  8) & 0xFF] ^
+                                self.T4[ t[(i + s3) % 4]        & 0xFF] ^
+                                self._Ke[r][i])
+                    t = copy.copy(a)
+
+                # The last round is special
+                result = [ ]
+                for i in range(0, 4):
+                    tt = self._Ke[rounds][i]
+                    result.append((self.S[(t[ i           ] >> 24) & 0xFF] ^ (tt >> 24)) & 0xFF)
+                    result.append((self.S[(t[(i + s1) % 4] >> 16) & 0xFF] ^ (tt >> 16)) & 0xFF)
+                    result.append((self.S[(t[(i + s2) % 4] >>  8) & 0xFF] ^ (tt >>  8)) & 0xFF)
+                    result.append((self.S[ t[(i + s3) % 4]        & 0xFF] ^  tt       ) & 0xFF)
+
+                return result
+
+            def decrypt(self, ciphertext):
+                'Decrypt a block of cipher text using the AES block cipher.'
+
+                if len(ciphertext) != 16:
+                    raise_exception( ValueError('wrong block length') )
+
+                rounds = len(self._Kd) - 1
+                (s1, s2, s3) = [3, 2, 1]
+                a = [0, 0, 0, 0]
+
+                # Convert ciphertext to (ints ^ key)
+                t = [(AES._compact_word(ciphertext[4 * i:4 * i + 4]) ^ self._Kd[0][i]) for i in range(0, 4)]
+
+                # Apply round transforms
+                for r in range(1, rounds):
+                    for i in range(0, 4):
+                        a[i] = (self.T5[(t[ i          ] >> 24) & 0xFF] ^
+                                self.T6[(t[(i + s1) % 4] >> 16) & 0xFF] ^
+                                self.T7[(t[(i + s2) % 4] >>  8) & 0xFF] ^
+                                self.T8[ t[(i + s3) % 4]        & 0xFF] ^
+                                self._Kd[r][i])
+                    t = copy.copy(a)
+
+                # The last round is special
+                result = [ ]
+                for i in range(0, 4):
+                    tt = self._Kd[rounds][i]
+                    result.append((self.Si[(t[ i           ] >> 24) & 0xFF] ^ (tt >> 24)) & 0xFF)
+                    result.append((self.Si[(t[(i + s1) % 4] >> 16) & 0xFF] ^ (tt >> 16)) & 0xFF)
+                    result.append((self.Si[(t[(i + s2) % 4] >>  8) & 0xFF] ^ (tt >>  8)) & 0xFF)
+                    result.append((self.Si[ t[(i + s3) % 4]        & 0xFF] ^  tt       ) & 0xFF)
+
+                return result
+
+        class AES_128_CBC:
+
+            def __init__(self, key, iv = None):
+                self._aes = AES(key)
+                if iv is None:
+                    self._last_cipherblock = [ 0 ] * 16
+                elif len(iv) != 16:
+                    raise_exception( ValueError('initialization vector must be 16 bytes') )
+                else:
+                    self._last_cipherblock = iv
+
+
+            def encrypt(self, plaintext):
+                if len(plaintext) != 16:
+                    raise_exception( ValueError('plaintext block must be 16 bytes') )
+
+                precipherblock = [ (p ^ l) for (p, l) in zip(plaintext, self._last_cipherblock) ]
+                self._last_cipherblock = self._aes.encrypt(precipherblock)
+
+                return b''.join(map(lambda x: x.to_bytes(1, 'little'), self._last_cipherblock))
+
+            def decrypt(self, ciphertext):
+                if len(ciphertext) != 16:
+                    raise_exception( ValueError('ciphertext block must be 16 bytes') )
+
+                cipherblock = ciphertext
+                plaintext = [ (p ^ l) for (p, l) in zip(self._aes.decrypt(cipherblock), self._last_cipherblock) ]
+                self._last_cipherblock = cipherblock
+
+                return b''.join(map(lambda x: x.to_bytes(1, 'little'), plaintext))
+
+        ISP_PROG = '789cedbd0d5453c7d63f3c27c9c94910141b3058628b4440b92dd78a8aadd60b4a8862ebb57e807a6b0b3d2062d14ad552dbd21292438c68911e2028d82256b0dc5b6f5bd458d12255c4da8fdb2fc57e68d10041c50f2a105030ef9e734e02a4dee73efff5bc6bfdd7bbde275d3ff799af3d7b66f69ed933670e1dbbefe6671f5e24108186fed62f983871fd82004024c664b30821363b7bc4faed0b27ea2289285d14314b378b98ad9b4d44eba2098d4e43c4e86208ad4e4bccd1cd21e6eae612b1ba58629e6e1ef194ee29e269ddd3c47cdd7ce2afbabfee78617d9968e27aef89681142b77e002c228002168980021689810216498002169140018ba440018b28a0804532a0804572a080451e40018b8601052cf2040a58e40514b0683850c0a2114001661db4495757a1bc2c430ad1273f285e16f5ad0f8aec5010be6826f140fe4b010bfe4aa44b9b3dda86b73f706b54e7833d0ff59537553457b5ed6fffe4d6a1ce233d9ff5cdba14d3127b65fef5851d715dcb7b9febbf7ca9b5e5ea951bd77fefe8eebad37baf3f2480f00e1937d23b64fc58ef90471ef30e09887a2064dc330f848c4f7c20e491f4074202743e21e3f27d42c6eff60979e4639f9080ba5121e3be1b1532fed2a890473a4641f9d1507e34941f0de54743797f28ef0fe5fda1bc3f941f03e5c740f931507e0c947f18ca3f0ce51f86f20faf0f0a987c3bc87bb2478e8f885e42a29b0113178f2ebb39b169ee7a6fdfc9e509b3122f278a5e2e7f79d6facbeba549154931c9adc9d2572a5e89c968cdf05855b52a36f56aaac76b55afc5be7ef5f5e169fbd3e6afb9b166f89bfbdf9cffd68db728689b3140e74d8d25461ac7ea465281c403c640dd03949a5018d53a05358ef0318ed3f9504184af3148e74b0513a38cc1ba515408a13486e894d478c2cf385ee7474d20461b27e84653a1c483c650dd83d49f087fe39f74fed42384caf8884e453d4a8c313eaa1b4385110f19c3740f517f261e36fe59f7b0822002d6a38089bcc6468d9436af0f89ec60b4b4ca8e488d19e26d594d336e67444f5c8f167877d59abdb998b3e50984268ac8ce526e4448416a3ccd19a007c68661b4a91229c5284b2116ff8b168b91489f9d85d3f40d94077313f337238e439f994259acb1f22bd397ca64cca3de834b019427305a2594514bed525c07d4f22a42e2393de418ed742545f07551941962f5a76594d79c527aba9f1f119e42114448f1097f63b7e3fc09525bdc5055488f392882a72fbf5aa40bf2379288ee3c84fc8d52a4d3f83310a25b44ac2f25d2e5ef7837aca8e39e7a1f85d4ef5388d0646791a458dbe538fc4366ad781f250d270f2186542392b864e1a5f1ebe7a561e608f2dce3e365f7409a62994b1af5fb4a02e4187550b275918242a21ad21219667493236d400e521b5654fca5824422e66a7e4c71bc6faef5a1c6fb4ab6d182a5126b48906cdf0fc9b55b17618ed3650723e90de7913f25c3dc3703f7556d88e71e56b4e3dd359670d9212c276e4f1945f5d612237768c723987962188db45d2de940c218755c86512613f911648db69ba5b43fe5ec5b9fa8033f2c06147ff9e3225d30ae99de700e6a8536c5f833105adb82d85150eb3ba3df3d54983ea4055c8f32671123c53dfa45eda6f4e0f6fef82ac3464de02d69a7daa703299340272427779b23b12468774bf3180dff9cb0eb49e1a9ec3d9d2648783ebef763cd58415f0326d6e378ee39e1cff99a09c2735958a1e651a74e3fba43f39833ffa3bb34539cf91f512570ba37cdde54c769e11eb1fde26e5e1f45f6a6b3fc1369bfc8f749e5c5525a0ebd77fe4b75052572b611741bd2523cb9bc11f69f75317c4cc83c22c6a4e16227da7fe67b39eb97f275a20d9793088d067a7a82d01e943757788accd76149f9b69b55695ce9c7ede770fd7b18eac70f788924f6733f690b2dc4c8c0b6426da86122f260187e3c91733cd1577aad0ee13155a34e342b098f2c315241762069bb204b9f58d3013948134edb946ed2aa3d3b50493c49ec01cac63388b5db4704922bb6493b036f85354f6a528fd9ede4fe6b7972f6caf1b2b09c7c8da03f5f93d142da1d22c83a8cb9875bcab79318c9822d605de3b84bdcb8b7ab7d9d7cb3cef1bae9e49a75daa995984700f9dfe111f9fd501e912707f3c8eaffeff040df0ce5818e0fe681a4832d27f24ba73d09e163cebc2bd2cb9be6772ebc15d7bebcedb9e69ce6e0bed89e2a53d8964906d603792b862191f975d094dcbf5be4ed1509d2a4cb1b666d2adf247aedf2ea592f96bf48681281076bef1d31dd7827f288915edf8cca8d25060a8d290d36d11b4a90420e53ae6518fa9e99cff84be528dbcc2ae5221d5b63181755237f9c98b9f352df0acb98f4853d8a9d52515ce7f25b2fb429965f2594cf82bd793ed5217f317f7579db99a6f97dcfb5e7b45734871ac24c9f980ee5beb0d37f987f60c9962d63e9f7e4a8352106d63969eae54db35e2b7f4df4fae51767a5119a202c1b8c6a89410ef36c04c14a90a8504bdfc810eb433cd06573b6719b96ef6989d0d306a4501ab8defe294feddb812a7262417bc63b7b7c376b9680ec41a53377d49876442eb37cf81fcaf7c7aba53c9742cd9a5a96fa483cf3246fa721ef17d0d84ec45aea7d93b6c66c43ca57201473a80ccfe20de8a73c3e1cbc9b14c281a77421a59fababe24604e79c619c321dffe7410bf01d36f36409d43cf314cf5dfbae937bc8bb83b99fdb39947b4c89933be6cd52de81eaaaeee11acc51ea94d4b8633bcc28fc9aa9dd6186f5555fbfa468574c8dd28e6a8a0ea1b37966e0a53f9553345dd928c8a9fa5c1d1a3762376ef1f0a19255160c704b29e0b96dccff23b78a7c9e1bcf6be588c72c4c0cace32805edb910613c7cbd3f5e415193742d8a7abb233b4b1f43a28379bb63fccf2911935b43dd8aeccdfb38af7faa2ea4bf9b24fba75caa7d3c3df656845c86027b823bc325414495818c6161a6916be6b74bfbf65004d23f6e40c23cde00fe86779704cf3d2cf9055151288cff4b2514ac5e5f5222d553fe4625ca56ea58bfafbe31abb32a91df5375297514dd6543d08bc355df5e5e376b43f906d1a6cba984662c9ebbe2ad66db3d9f240b2541f994c2188d2accf4ce56e4d3a66ab6c0caf85981fa1f1274c5a26af36baeafc516eced256d0f6cc36b4fa84198699e35b97431212190e17d9f04a684241184f839ee39412f965d4ee067d42a063cf898b131728d7236eebfd99feb1b7c91b88144e5d44f792546dbef6c1125ae7bc7574baf6c9ca98c07bba3b435ac39181d3197ce5e965e7eaba2fd4c5b4ee737cddf37c5f52def79aef3855b2bdb57b7ad6d3e629e640a335419b28de2fa42184f06915a3c4be91bf6a2cf294c0fa2cbd4173086f4063bda16cf941547ca7347de5474d94708d29a88a0fcf8b12da591ac2d04951ed7c54fd9a78a32e576fcb25ba3200dceb65e126b1723bd361a114181d48a3cbd3609f307ba01f8631da10d952253fc1ed48b2ad64937b426c5a456a44a575f7e6dd6ebe5af8bdeb89c366b4df99a64e80bbdf647a48f3e092dafcfd34737a3cf259876a2cb920b5b75e33e8da777750a7506fc43a8db4c0465f6eeb5e8b505604d062889eb7d1f89a30f800c3fe5bd2059b19518c7a484a714a07e6566de685b6646d07b966e07cc38ad88893f68897a71f78bbab90acfbb0e76eb5d07b966e616269659539d6120989b35c6c951f49514b173f4b2ca88a0d17585f1636a85701e5ea79638ea526a4c11c493a5d6961d7d1dc7aa330a886d36aeece58c81b2c544d0a60e4153b7f2e576a75cb25467441397ec38b7f55265bf3377423e1114d52fb4d5c4e7ae313d494c376c43a9b5780cac9ba9667dc359243e538ff0589453d5362d213ed382667954a7dc81f82ef48247f8ea3b88082d21b708fd5676ea3f8d95b5b4b219f7a63eda8098d5fc48bc8ffa1f542ec15e7750213f26078431a9b62f263ebc56bd693941bf23978e4d8b92d4bda8f0ea73306bc8794c9ab567ee85ba947e654bde87d76aa827a2e8d60c2a5868e1f15c68953f79d57ccbe1004d7b0db731d9c116c2ea931fb5b2bcd0992f723bdfbbc74a9faee56568d926dd50b1eedf69113f0bcd3e556d7f9fd86de56abd6e143bb90564413dde64335f6bd6fac1b58e1d546bd3e6dd29a916dcba4207e661bd66b90d695ca9b20c28f51079910f45be34984730430217a1af0d35a619448da114b51c13c348e91bea11d7e70d2d7c9f3774097d3e526b2db19ddb3c5768716de2a7d95951235932523252033b20ced33cce9427b0e402892feca394e1dc4c6bd8948efdaae0f6d836a175fd82579a2b78b04972a7bf9bd791cccf332c4306c805ef35eb75a586db4b6d12b4eef10829eccba539229d86df65ed7d5c4879d89cc2f9f4d3f8127b5f55a6c890fa31fb346134a7e8347297d7092bc84ac89d736a8a528a30bf72932b1599790e648620f3246512d4299184b392807e652aa4c9e74ef25cc5b4a8165cff4db5a0ff173cabe2f55b2dc947665c6b39354990caeb52ad1e66ca586622c22bfd1e09e19a1fb8b918e7aea6c2040bf4781a66ee3dd46e84571612665cf063f97e4a061f16e61fd84579f2fa63edc77b4fd87f79d2de2d2205f9919750639f823cee559e0063c0e5a3ef2aa88fbcac7e2df784f43b0af25baf7acba6743c2ed2ce2a03115d026b0a6db320de6fc7de6cb5d180c4f5140a6b2625826cbde5c997403a697b687358931067cf4e0e4c16f8dec512f2758abbb15ca551b47f0bd2d9186d69ddd87dea3212f5c6cf6460b7a7a58d36648aa1df6e04ffa6df52a224092c6349231565f56eb967d2d6c1ba7fdc8b1ed5858aebc0fff2bc6261a5df7af5c75b479eedc3311f7925d73e393bd448a79f10b1197654673d76897d45ea7872cb91224faba72d8ab2ae69bc37f232b4437a22728b149f531515a56455203565417ba416d88903258102f6488002f6888102f6888002f61040017b105000f8825d5d23d822069dddc6169104f7afe8ecb66516b62804f175e464dbb282ef1465d529c7e4cd2cb2a69fe8d96559965ed15e650863ca617f91d3298cfe70b396f3b3167ed6c4683f6b56f99527cf6c3769677e7b744e681f4986f5847666adcab739ad3dcbef2919a93107703d7d481f2219c6e4ea6eeac16f64ed54c00e9b829478f0a9c7bfd12b2584c21c22a69fa6903c05fc48bf4e844b6ccac854f6e6a9c7777a04331365e5ce596e74ffe291973e88feaf7806fcb050f3948c7fceda8f57c860a63509af8782cdddae6236d3fcd8eb3baa8c0c256eb03bd638c299cac84c5f3c53043649c1f356fb1d44ead1f5b05724917a32603ce9a19e01348014a9c791a2b1313a58b5190f6196b96c56721e5fa7aa8f7f4ab1cf68129efa6634f34f4607ea99d186651525715aafe6b4fe88d9175299201f61b67d523893e910d28f0ae15b7c585ccf8735b79ce585f04d21fd84b30dc278f4cf98a3fb52a891b7b37e7e476ceb99d12e4b827dc1b8ce852c6558a49ed6b910efb1d413250b85b23765abc898bdc24eaaec862c4d1ef385103a7e9dd1ce389d6c51add6d9745a6c2dfa4692189d5ede73e6d6f76d397d159ddfb49f6bfeb9e9b9be177a5676aebeb5b67d77eea42d618650d3d986d235f50d78f4f48f7b20853d04d10f50de30a2b17416e5476874f38879341a365e7e7d79ce079ae79cbedf66da8b0c26c91a8f8d51715be9f57f23966f9525a8d27c16d09d95c1d1d1074be96f0d211799e01c21ff3baa8472703f2accaa26212698f623bd6bb6ec8c2435f40e0f8453f994e3e332afe8233c888a92f0612591d50673a47ada4e74b0ef83b2813ca8ad3ffeb1b38feed31f9123fd0113aa93f79fafc8a1d797a09f73662478beaa0b8ecb8965b2cd745c9907e655b5d3b4156b957a5a15dad4abd3b6ae8bd950b141baa935356675c56ae98b975f9ff546f91ba2cccb6b663272d0cf8861284b17ab8b56cc1b767c8505d7223e866b898eae305ae55ef7c4d05fb204f6152a80ce967ad36b76c9e079ce1767240b3cd36a24a522af6d255e248cea1874d55c73b2404c77752232a846b297506450912b4e54e096f01ed343be2d1f6bd501bd88b3201b25c176d71fff692d96819d77cd413cad9877d7e1f594e9a9b916cfb4b539a1c2c9e1f1742c45798a22c36e51a45032b55f3352b54bbebd61ae311c885235459fbc6abc6aa0d7f7a3ab4659c2cc9c73cc4ca164d6a6a5d1e52963de5b7ad22fe1088c08d7db3bc3bd76b97a5b07de5e708e53c680cc2ae38a0ecf3467ef2704f2d66eb763594d16551add528960ec5fbf20a2d7ef42570dc1509b20e5cbcf464f379a2355094b4fe2d17fe6eec0280648977d37c172d548dffe3bf1b3b1a6a151340dc60e8f5c4d4ea34864ae3258679775b71cd4d740ffd79810a1a99317d69478f8a3f46a7adeaf088ff473dc3843ce79653f671e7b21e7a2d3bb7af1d9e8cb861aa331ead993aa84cbb8e61a7ce610dc3770e610db33bf3374cbfe2dac845c484493f3faff666a0f64fe78da80cf1ac49f82857c6040fd8fd33fca9121e1a75a7dbc9ca05fbf8bf4ca09046dcc20ce300b99ec9d73c12b57c84dc32ed58e49cf692f6fab68c667080b7bf009c373ed2fb4ad6c668d1b61dd6a12d1afd9456c27e5b0e0f35f98f7e84eb3e863adaa8ed0dcef54a13c8d3b55902091f5c681be50933092892cb5ee61f33298414cf287e826b3846d9c8c74217897e8af54a2e1d47c334a61a594831ef523422f9942e8e146892ac92fcd67554749b9b9f886cfb5e214458a1215db12cb148d05b08bbc2526beccd7d22d3619db98844a8c46b11b379272646a68f901e497945e122e3547d20beb3dfa239810f101b9c8bc04cf9f9a51b4e880b75f527f8c90e3d75332d6e68354cdd5d2026486bd9efa68a30f470f34fab029a3d0d61b5baf96b6069abdad4ead3bbe186667e2ecb1efb02ca884b2907b617d8f24691bec751b4f826436e92e0bc4f8f2319d109341e5d7b2d2c8252cd544595b5a3bd9c6714489b1817ab2d6278d9e2345aa5505374baf5653cd688265aa614aad390e24b01cf2e468ed210f9c27d0ac4a616d4aa4b2ed025eb71e161f3621fa72eb282f3d11e21f171249863031b837aa8b4e713d52dd2a2594b87cf839a90fad80bef66ef76943d6ac1bfe8d907b76b8c28ac416e0f1428ab4fa9514b4a3b5a3442ac64ff9212d1733e70ff46e9472bef989cd3319f1e4cd043d5a329a0c625f9982a2642d77d8ee0844ef92aa301f567bdbd19b87f7cbea27ecf7708c544c27c14a325aac024b21c4077211fbda49076ddb89c28d3b23fbb5f4d7b6507ec5d51af97d76c31b59b40fdd1f1fbef56f4470c1135be85ddd7ee0a98aca5df35242667f7c682e3da22b80dec01074c9f4b1e6341962b7fe63b3b8d2138d7d8ff340f7db72e851694a56f994987e871aa5b7c889b80245920fcab209fbf9b7f490db8fa65fb1234ee2c7ec6ff229216f42ec3abb4a68c71b4baa147166941f435f3a2561e35250494e8ed83f6714f21f350a0d97ce2f52905287f70bb45fbd94d4969c0b8eac1ed588b89ec7e5a736de90b57bb7a12be846fac1ef62e89653a8447a88ac03ff0febcb29c4c63500c75669268ef1e563ec10f30a955eab20415fa4a02fa9f53d6c5c085192738a5a66f15e4d4beb91cfca8e9dd6171befc9d66a2c3e49de691d3bab371745d27f7b48cc6bb36a55385580ca8bb6df545de5b4f9635b1b473fb5b5b2363fe479d3f39acaa6fe6814f16835fda50c7296aec4ba55daaa5a85cb8cac9964187d2c4ae9f3627f84f5edd626af63f921bc6eb45c6ca9ae325ea8255332a9270afa3332b7161ed44ff58095812eeaf6e0eaa84e4954bc7117e9b4b4d413d569ab61ae9b594226876fa944cb0b327dab33de47e11e7722c35fab42dfbbc6b5e979e030ba0b053234e9099e8aa723b09088c5a3144e2647d518b544e84e653c8c6d807db562f583bcad1e49f9493d791e61cd996ecdd4d26be3c58c563d19663e18efd2948e927098dfe91633024d3b6d93b8ecd76fcc67d5546ed4a7ef71fcc6db934cb57a4b2e5218b6dc8b2a6672ebf2d407eea2bd31d5c65c54602bb866cd30feca32c308d71a7f74630dcc2884306f403f73567aa0fb5bdd67d8a30e2da27deab9b7287a2d89acdb2cf748b2df52ddb017edca0da7ea6107b14b4bdf684055467a5d8b87fe1489188a21f7e435deb35eb5dd83b9f4958d90967f66700adb9d81fa2dec2b46872247da47df6a90eaab49a4ff8441fa5a9210d73284fe335224fe8c1189ab49b1fe3023661946a2fe2803890f330ef58178a43e6c27d4476d84faa346b1fa4083587d3845a43eaa1483c729511fa51c1b2ddb137753bb49f5d1867bd66b204bb3ad3b3b8bbebd57529d538fe8b7ce8a584db743a7ed57d26c17ec1dc28ddd483c87024b6e40a16635a2880b96706317d2c7401cd50592ab5123b22abba1453a6d8b7092a099ab5470dee548213c870f8b1f1c935ede96d31e6618ba2e7dc28c6e8f496a4d18baea0409fbb2136cd59649cdce7d6079b27eaac10133ac88356d24d8611287a2f79483be1321c62b99e2aedcc1af662962f06bcaee202216af670b1977deb02b1d06abd9da9a3e3a3e758a302f7decfd62b5f14f44710a2deb468a8d36c7cc425932691a7b3dbda45a7e05d1dedd1205394c449ffa40f27349b529358ad7cf8c7fb25746836e4c072fd6e0886302b7b0bda351f59554423d63b243d0c79b7b6be933a944f14ba52f16df545dbb6898528eef18305be87c69a07eb2c4516d2889141f3120c56b671cb13be91ccaaf5aae256855b7074b419ddff48e2a5e559aa6909a1c8a2d124275b3f89a82ca92d0c90d3256ba4ef4bd91ee3f855409a56daaa4d2765897c5b4b5411225618d12915f42b1d52fa9d8e6b7aaf85ab53189c0927333d793f6725ef208a23489c9adbe9242a80f4c26e29cfbb7e6ef0eaa5695de52a59576d2542b3e4d10013fb1a656b50e9ec5a53de208180ba34452dc975e5b0e1e88304abfa4d6d2a752bd705b3979190981db8ce5c772b358eea6060f05b54e4467362090af0de46b5760a95fc2524309912a41754995a46a51ad525d294eaace498dca8c2173ab8d93097addb907ab53af212c6b359344b0ada350414b714a1d19c7f0de84d0e76f395bd2d488fbec420df4c02dbfb462684d37d71aa8479c885bc348247c8bf4d0a2d2be672cce9d66d937cf58e8c8d5f2d2b4e255ceb6b8da70a34172df36ac69407f6cc3f7a6476bef577fc77deabf3450ffa94b9638e1842c800edd621591ad388f82221dbd2517cd74b10de91f671c6cef178e333bd654631939d95a1ba49c6c6f3548fc12fc2ef925f9b570b2d10d220505fe3345123e7481d527a5c0e6f762f1b572c6d9570969c441bf557e57fcd2fcae73725230ea1429fa02cb4949c4aa0e9f0d1016fb74d559aa8c81c635b54e599b6ad6d49e318da9aebe72851b1ba76ff7e131bc0f0d358431e606ee9ca9dc79fad614ceaf07389e35369495cece3fa13a5e9e204ac2370e70a93083be308880fcdcac5c5644cf25d1b3abaacccfb63973e1dd40267f4a00fb81eb16bcf7e4cf8962dbe6374b3b593be55d6508334c321d3299bec4dc4c31448ca0e16f0c2dadf71d47883694affb262736a73c75566a30834f9684f32172883c7cf957fbe3f13e88f6ef42fd19fd0217a7648c708e31a7addf824b0967600f387be313666a0ed7231f50db9d3d824207f74865ded01e2146e219873586b40537571936d3816d52984d47d7cf986bb209e7a6845809a3aba4c4752cdb6d449fde60bb29c27463afb6f438ecd324789f96b904bf2529e7de93e4e7325f3e92a6fb9aa5a2291a6676e7d90d7a4a3d4322c1bda31e2741acddd28f5ba24a83fd1ab75334223ebc833b7b51502800fa793cbdd9067b69d769ef3a2ecdae4464836a813a5882f03b2ad58faa344273ccc19df8d829d9945f9cfbcebd16532ea1cdb7fa2d587ab2a3d6a53316e8a17dd49bce1e4ae8137ac8827bc89839b48706ce6e0fd6e1511fdc375937d3f06d1a7e17b9eddf9c1df1a7007bb174bbac7c9e21291f4ed2a42161076922e63e5d36d0de328f19ab424d3b1a3c5f0dc6bbff4524ca5c267097416c9aebec7deafd7abc6932eef147ded07de13acb0f8718292ffbf1dfb02c6a3f180b89c483c9e54ed9789b78dff9d454c4e74517391979ae6fe2f3d158d0e359a9f88c546fe6ad4361a6c4512c3e4bc556023e07c2bd45bf23f52653141495f5535eb1465ddc85e8a79bd0e165746c13f83afc49ebacd4728ed3b4a4cc46f107204f5184585d2641f4cf52d98255b8bdf9b93b1a54d163de9e91b6e3c48ca540933c5fd5c5e03ee98fd7c781b58ce942a5911bb574b25d16414506905478bc1d91b98ffeab3f8335dadff24bebca2b3153043e5bf56bc29a817550618e10d34b29ec83fae0f2f9d6396d8fa4a9cbc611c7be73efcb8000dc979f5a3c5f256218a859043587e6581fe8ea2e8dfcf437a899b1a1655abac026c1e5c758589b94d3c0cc258fd5ea3f6508eb16f92df1a724f2ca557f3485982e7f3c4aa71d692d7de6d993d6150137f1ceff4ccefc1c6e94b565aeb393ccdaaa1dd3e51f4476d43acfa963dbdc7530b2016b1631f7e0094e1779bd49fa37bac85b62e680866535e39ca1a67fa7b74dfa81918f7c7ee8c80fcc8961066927ece1e7e27dbb2950d0af24ec4f9329861496b2f7871b8c911dc5c1058f6565fa4c92d0cf37a358610d8aa4ddf540a7719d2695631e1566eb835d7dd56456a4333eab0cc66c4c97682067c27b62c8d91f534db5445a7fe8be837d6b3627a6a4e0057eefebbbcd1c0756ff61c5be440be6a9dbca36fb2083cd1c8f6d5ebbaf74762c331d64c4617595b142b0ef65a4a6d042e7900fe1fb37c1cda186fd0669bbd0be38fd41f05572240ee13d8982b5b738c273ba91df4af13492604ce925f498d3922366d315b145e2d8f1f6f6d547ccc56bfd6e785f53804cc5ad4a2d784c931bbd795f91ca871d64bb0df1f371e58eadb4eb5df495406656d2e5043cbf2a6f3b1cb0722cf06b25e6145ed21f9438cc7320ffe6f19edbdede6fdeba9adee22bd71fce019fdd97501f3e8caac956b435993115b61c31fbada6c7c8a4660d77222ca79516a9320624f8cb39194723cec98a6f145f25e7f0d2614f5d65b52a643d0aead6c374925da2688c40fc9901a3ad363720efe4eff2b89233bb45259412959895e86daaca5c4c2b7228c776e005dec0cd7c0b39e7c35aefb5de37fdaeaeb028ce99d1482d9d087e4e630af2a78c627fa952d8158716b1fcaeb8b85eca68fde34322c3cd36a44a5e9187df12a86b6c7d5b6f6cbf5a70c5e746fdb167c0d61ba03cde152bf0294a4a035234e2181bec8a15f814858bb1434c06ec8a59d8152bf029ca95fa1e456308e14f35f0bb62d8a5f8ad4c2fb15eb3ddf3845d31ef23b8d652bc52eca154ce9522ab72f04a617b70e84a31253db8653fb79a075e915e9f64a07f85bd5623ac77655284676ce6264ba1c831fb26caa63a771f0f94afb4fe95ecfb5dfb640a99dc9b274fd991c75a603ffd39cea96a02adca9a5006cf125513a1b99a109b5495e495c89f8663eb937662fb33e586194cff62a90d94aa49d5ce6855df3aed095bd36234116662c182bbcb93434dcef7a3912788ebc29a19b0c9de5182ef0ee0396b45add9e6002fbcf28da3ed784e9035c9da613692719e488aeadb77b4cc09ecd7b8e61039f105ce873928390e38149eda0bcfe388c2da3ff468152575f66859e1e01e6d20ffe8aff125b972fb2991eb2dab717039ade8fee584f143ce5201a621e3776f6829febfe1a4b911b79e1a8b3539f3373c1f119a497a911ebff50b6cd35c0f33f06fad52962b818f82b2dd195b964f8174f7acd76df7f8b7c1c29e7f2fff265858dddf970befaecaaa8595b64019c4bd7f7946786bf5144f23170b6f9c0cc22cbc4f08670bf362b7f29cc3a190b6ce2a67088d590bad3c403de7a27c9e2e81d75c594ab6f96c6d68b3530ac15fc974beb38cec506a713b5296abe88ebbf83e30a1f9ce824f22a2462aa770f2153bfdd3b2503e666fb1109ea020b72f129effac80447304e74f161f318bab2924d29b63a0af732a96e8b4538d0a298adcfa02bd732fca56266a746cb5b152144eda1178b62197a456b6e11eae952f91b370a044fe757c47e8524cb5b15174c4bcd90aad44eac314c26f86b892ef35f4e9b45fd78e40b74610da3f47b47812c03333fe88f19f115d9e38b6ff6e76162bfb96e46fe3af0779b1ef8bc733b839b669fd84c88efe7867de6356e7fbadb2ce31979cb330b2cbafbb66e45ea1e7eeea23b29068bb2ab9d00a76d7a29e1644e8a25d3749ecd82b065f2195f78cfd52fb175b1f08713094aae54a6dffe2af2dc23bb38ea16fd59a3a9d1ccada47d7bbde124ec3b79306bf6bd377e05549da8ed7a5dbe3229d77563a9ca58fb70d481f706d407a7443987d6e3aa537ddc4d24b06af33bc64d7fc52e9c26684253e6b7195bf6a8e861132244d2b4dea77b85a7b6d4defc02e801819dc8c7b37b6a9ca807b57e82fd79b5cf45ba861e41597a72a685764ab6a15adec15a992fa95aa667ace2d68b5045a0f982841583611eca006c977c9e5d90aefe2032e5fa9e5d76a693bf46734c272068b351234b26540bad20452926dbe6e714a09328e431f7909761a394fe44be4879385228b7604be013e2e7c4997e87608fa489767bd5e798fe7c3dffbbc1d12d94194c17fa0b7c4d7e6c6e7f1bcf22bdd5e89b835ebe34a9fec2ce54139580c53939df5cc12c885ef494fcb919943b875fe0d62a422a367c411b3be8142816d930ce0950a3664db72c41cdcac073ddf6f98f1e6b4d726bff248daf855135f96b667178f6fc352289868c4b728730aa3a57b2b450a32eb0e6e9fe94b713d8926352b4cbe28db1cb8f20c93e933f2784b97736598c40c7870d8ab9c24f4d5fb8a2bb513ae8f49777fcf83dffdac6cc6774675d1ca5898013cb678f72f57ce83a7612f7a1f9c37e1291adf0e55c845f8742c9891a65624fdf17d0f2f9d3ec2036d6b004f975c22566ce81aa14626a48f188658cfd18891ec3811085eb0d56bc35deb30c3dd95a6fed12b2cb8445d6d503ddf2f2992629a18f9710a3f7633cde27146873ea4c1516510f9642b89ed5e9a155b85f935cc62bf232a3152b29af82e51846604f6d3c65d4ec0b349757ca76856527863a5a8da5e292a86f5b5b459d05d1821a62e6a6418a390664975f8664f13779fe84a79026e015e2bf896f0eb0c3f873331ce3932e1fc503ba51b611ee5e7f965ce3cc7fb78cd71a6ec5de44c09b83b34855ce23a1be81d9a92fc57d75717763e05fc02e4a5dd964b97da907e1f8914f61e8a16db45bbb4e46c1ad9452e39163a4b46760a1a3cbba4710ee17fde12494b65f8e6ed5ff0a9a7fff9d34891310d9173a6fbb521ffc61e94993b9c9a64f6039f7da659a70d1f5e89c4f387a39287a620920c7fe822516d6b20fc8793c83a7bb8c3bff155c8af28f4130fa7e879a4881e2d169962e811e7f17b11e2bc8889a1479d07afd108fb3263d41345aacb63f73977695fd7ea42fa2d56a9f8de91a2d2cb0a4683b8d58893be25cad5d36d6eed7ed7868aa314e4447c1f86c2b71915e43a11b43dabd2d57632dad59fcdceb693c9fe4bb544497c06227cc33792447f2ebe6da9386b4125321992d7bbfa63a91d295eed2186cb26158ba7c09ad9839fabccf430b1e8f3a2cd2ff8c7372026664cee74732bfe5aa2682a0adfdc88c2e3eab92f224e23ff1c29b26a5aeff1ed9955247ba1d7e2948b99e2940bfdc2cbc5cd20072a7f861591f37f2bcf83dee115969b398c139c2b2c58fecd4ae4415a20003ecb6c989972473714cf26359b4a8a4fc0dcb064f029c67a582960469ec85259b2db16edc4db2992890a2a4b144e358bcc959c5ff4eb678699669f974ca764ebc39ab38bca936f6748269a52c08e36dfaea426aef79e8b4b8baaa94e5185b9f8452f6b69ca8e7f45689168b8e48902fe1dbc739e09e3e619f060b9ba0666dcfd062c07fefe08d7ef5ab16e3f2051ee95617bf83eb05095b8e3842c39db3cb4f6db29d113f97595b7d615e91b3539ce9e7b03fc05894ee3c1f0169bb59f88c1375714e23d4f2864c85b111f17c98e0a46ac6f082a453b8b3e2b2c9d0576d2a7d8d84d949c3312cc969aa20a54dd3a8a184ba9cbcef679500568aa591f4cf595349a0926b7c65c89cee6a903ec7d64b0f541e9dd2d46421b41fe69c1d898ad8bd85121a8aa485d7668f8d6d96408f88365873cadbe0df72a12f8dbfdb08b125519e9d5a093d4ad11994be8951651b6af32847b4f30b15777a4b038ca22ed43fda330c72db08fda98577c02cf4578fc58284ddfa8940e78fdf39b1736614e6106f06957592430221431977ebb4b546588f0f8d302568ec4fea41cb1a05edf9b4b67e3dbf4f44e23a265858825b328a757434eb08e79bc7fd0195b974e3bb01f17ad9ec98d603f77670deba5c248892c52e419484d35ab0328a4301bd19122790a8402c12b1b4721bcaf156ba9bdbe560b893c15526f09ee9bfd45781f4486581f6cb8476acd78df98d35ace1635a2080a794e355ba401c087db2b49d12cece9992bb01f28fd54210d901c32eb62d41f51d8bf454c701d65dd79ea1e2ec1520ba453cd8b67eb82777cde1fd1e260b09e64ddaed44ec47de62da15b2a45f8cbb792f825e841ea88790b1511823c611f3e9b89c163bd240f7fcb35d0cb50e26a2512f9822d796ed2cd2cf4ac73a6716da70224d5469b08fb07ca4aec3387fcb3cafc0ef0dd6add6ee3f24c5698b5627a01e5f178bab40fdf928fbd35bf1d97bd0d3687fb4d51d088a61644500128d01c3d5b3c8142ba718a2289887847e11b0c1a54308b98a00bf6390136295b1fa19db89eb34fbe5ebe4e5be5275c9dc5b4bc61734a18986d79b205f8cd2c883eee66a9dbe74e54078c23066ed18731f8167d188c658796be5c395c24686065ec26dd1385aa28c674c49c6d8ca0a217a8fed65b72619be72fd95938f42c177aca152a29f4455d25fd166728085d2fa97785a6a00b255fd43a431a74ace43b57da12bcbaf42f71a526e3f0dd25aef48d386c7fc695ce7db573f319577a210eff56e84adf8bc3b585168b347ac1afcb33334a0a0f427bec6ff5e65dd8f615cc9d7c7c49613dc2a7f2d72dcef059b429a3bed6196a41e9195fbbd2ba5062c677ae349288caf8c995e64b1019c9aeb4202282ea7324bb52a740b8c791e84ad740f89623d195be04c24d8ebdaef464081f77ec75a56f84709663b72b9d813072ec76a517e2f0bd2057fa5e1cee0b1a68150e378dad05bb10d16d9522e7f8dac2078f2fce5d1a8339652a314fdc575b4f614de7f8b8a57c75ea02c7bf34d6adc4995e6e5454f19ca634d609a1c1ba814303ba814303ba814303ba8143437483e3fa54e387fcc80fe1faec10aecf0ee1faec10ae38c46bcc1257aa508b2b5dd030573aaf51cff07d1ae7a651e7ae1ce3e3dd342a6e8846c50dd1a8b8211a153744a3e28668549c9b46c5b934c895ce6b50a22b5dd020573aaf417b5de9bc86ec76a5f31abadb95ce6b58902b5dd03057fa411cee19eb4a1734ccd57bbcfdee38e60cf3f6bbe360d448063c67ec1f0bbedaa71334c2db8409bc7facd3383de43d16962a13d1d64a29becded4f05392e68e9269b089f33da504443080a5266e691d608ed79949937c6ba237797cdf90ddef1ef9cdf2cf35a84df24a91abfb6384314f175adeb5974c182e7f22b5ada5619ec9afb86f1b6e19af9166d33616d6b29f93a4ff503b60a3e769709eb196bcfe86bb10cc470edb7fec4f54fe9c2cc8c5d26d09587b1d6f5e67d9d57fabd6015cf1f33d5612bf94d53eb0c633d85b2b7a096df52f9f2cf1d33617d63b0be8de0ca5f8cb23853b0c66940e35ab89863a6d2e7b02645501d8e2e7e349ee76e66dba95b6037bf0923fc1c8e8b1ac2f3d78b53b8349c1241118e5f393e99cab34209185f025b39c35bffc57e6e6c67cc1ee0fec889eb0771dea3b3fec8fde8e7bd0707733f3a6b30f7a331380ea7e11a48822b712afd98336d70cdff38f5cc415cf31bda819ad31a182e6f5fcc1f6bee3b957f6c70cd7d31836bee73e3de7e6a0cc77dc6bc41edfa52ce4b121b95816331675c0327e5990b359c34b33ff7ad7ba52ebf0b78a49df8ba9a8fc3357daeac63f99198a11dc8f34843660dd6b97c2d3e1570ea5cc8b5019dc31a26bc11f62535fc935a24d75ca8855da64848f189a8df4ac0ee65df605f7e7e33f8fe649747d0d7262d8dba3cb9bf37319710ce31b25095c9750bd951c5cc77de44cae1ce80f9b38e7b55aefbab09b55506e7d770c7fbaa18671ea4174e0ebb88a0a16f6a2cd056f1074664d06669159b7a51c98fd188edec14937246e2bff87df4e4662c3529c1721fb4f0b91bd049edf13fe486b95b025631c74b4b684a1a2b896db9d65c5b8fb07691b0d3a9a79cef1faf89274808c91c34c7c903d784f93cb99908c2bc48096121847edc739d9b59da2b1f71f67cc38f7ccfe39926b089ef7fe709f0e05dfbec3e5233382cbe22d7d4f3522e6072e9b7a9604273a9d1b933572dc03e6149a3126dcb6542c297742122688d058f9fe067f7e0d6973e7f2c775bd9406c59371f5bd2a8451706e50ee872c65344efa0f8b2dbcef806b4a27650fedfb9f845258d116817d43f7d499768ca607eb79ce929a87e30bf1bce7833ba6471be3d4cf8d9598b11e96ae5ceefa27fc2b17db3b1968fdee78c2d6be463b1a44c087e03f48cc599d67416a71dd5f67223bf6f9e6263d70832a844e98bb056f8834ec0aac4a5f82f61d0d716613e6fc671bf3e8ff72b99425c96958fc312b5087191979d7114f19df09d1f34024ba3bde40c37f1e10e67f8373e0c7c0853adb3edb067cfd5fd8bd0e437086dfa9508e2795faa755a5dbd2b77a35beee33ff1b98fcefed4f2c7dc36b7dc4de79cb97defc3dbee961bfde8cc3d61506ee7d307d583668eef07763e78479d9d259c217eb579f64c23d9c2cd6a0b4b1a43a086fc7f99b4e6a9b0ffdad77d868fc7ef6d8e7e2f9b9d9d85f344409e1d27b641afe1901642577e6360143147bd4d7b9a3ba1e4ce201aaaf02e2473c9b3f340ee06d96c3cc2d959fa1452c47d95e5caa7dd77c48cff9e42a9168f2adb6d47747eab8897903a513a5b17626a50a5c26e7f4db6d9b99aefca1da9b5eeb4dd5325f637ca925b84da538e0f70b595e3da9f9d0773b7e8ba8308929d000bf655c49f258473a2329df68942bab001f93314cacef2493c1f4be66efca56016be71c8df34fcdac297c0dcd5e5d411bea466172f9bf6d3270a8b671321f85de3e6d944507616438a1bba1ce26924d207cf21d86ea9a8e51e11a20e6843c5b0ebe77af59fad073a2c9bd263dbfce5871c78b71e6a086ec73bf16d5afa6e2512cefb8a856f140b89b2422dfd50378219dcdc2d12eadf21bc6366893298e14bbad1d0f8c87788b2a9cd614d50e6aacd43a414faa39a60679a476bf4d1ceb9b2ec6276b2c86763d6f4250745e52b4b0a26a3f275fe71f588cde81ee1af3c8522ba47a0f43c6530fef64ffaf6a402ef84e9544ba47fbc163d1523daa00b625b48d953a79efd9ccdb08f507dee0f1bfbea886f11ce53025556db420805a4a8035a3debf3d4c152a40b79f6d4b331787dd085602f1042b3e0c946c98007b55dac3a85570de1bceb6de11d3b834f34b19f981c24757eeff9bc3fe94308b32ff7c65bff37fe6d0dfec21c5a7da5923b2357ffbdf25d46bb87ea40cac9f8ef8a18de95453adfccc822077f4929d8938dd722aa94d32225778ef626d64df57e4aa6d776707f7380695092dcf9ea778234a7f19b073e8e3cef7c07af3f25e86f59296dbac6a76abee14b240827d50def96d21d3f38bf2017f9b258377db9ef73336616aa12d5fb2d32eeef4c2849116e1d3347c72a8b618f2fdbf728bdcb97620b414a3feefdfe86fdc5e26a19d28f9f8d74e3d9b6f1481da820585996a87ab352fc79b1faf069a43e7a1ec611628c0d227fc94174840997f620d9f781cc24a15f137e0f5c092b3c896f0090a7842f7a7fe7dffab8ee165c37cdb1eef2bd3b50f7aab4a175fbb9d7fd11d47de03cccfc2bd2f17728f8ab14fc2d0aff65cafedcf5a101287319bb4c23562cfb02b1bdbd6f11a1e19b3e40ecf22e319d2517b1d4adb7e86dbde0ed0f975f54e2f7c6ac69f471629e2e3a681f4dca65aebbde19445009c53858f9b7c7c347f7a26ad30791576a694a2e6595c0577eeb2daf7975d1d67aaa8f6d9c27ce5cfc58168ce65be11b3610ec2f77c59f3628703d7a9b94d40e973ca75cb695352a8f135a76d49fd04f6f579b7a23fb477daa0d3ff51a41b7364af9efe6ea93b748f71795ceda0f5e826e2e39ef9805d7229fb7cbe275daf5de6b2d2f55b84f2762a96f8f9bf2365ae45fb1ca9388fe86c2df9fbce5a5ad8b4eadd56949ed33b5382cd7a65bf8f8672c0a5f03a25f3579f78fd6c5281693a2eaa526517fbc8ebd92a77b273cc3243ac584431f8b944bf2e8372822d4cc323d0e3aa512d11b298265da1ca1e6708a8a0a5f6a1485671845d53994985552a25946baaf11559915b0d3839d0ea2bb1ac1f36973404c01292acc5bb6b53ae2165a013dd0fb177ac9ade18a8c0dc8eb845c8befc4d092ab9e5e5a7af8550fdacf0329323af169bdb8118d9428941b107f5feab2b25f9909a5e5910aaae92daf2cfa793bb6cae1776430c749efc868d24396b9988534b67931ca5c82c7e1315de2b6ef950a9f6ef18a6d51db761c5f5fe683eeff6d123baa17346534aa3f1697136b586ec49ced78f614d97d18ad7594bd938826cb9fcb69b1b0cd064444e3be4caf25a3e7fb10315eda2f6ac7de1b2bc9af9df0f3f5da29f7f8d40f6b93ef31b5a476d735f6950d28d0b8eb73a1adc3aecaa0ade2abb240233dda03b1af406b35b4e110f456344a64155a252273494d35d515c94ab3c4f4e7dd32bc96e01b19a6f7aae3de4778d4c32767a1255b59e8c36d274c3c5ff28e04e41d714784fb90e5fb508ffb9055c2789fa7443817110dad115137d8e671a8e358a031ea8e8232a0544ba071d9f7176a37dd190b5e7122b4c22b4ba7b50ea7ae2aec3ea8aed6ebb85007714704755077906f342df54064f4e8b2a0e835f7bcb2303f9d36f56050f4c63bd72db85f701f103175d1bb8e0d843e3c787f6bbd0dd6dabf5801d6fa711678d86fe942af6c659781a58e9073da4c0fc396fab6e4a2f2c256851cdb2911ebbbafeea4eb36c893bc3d28c04aab0ba077b8fb6bc74eb2e69348c1d96854acb5e1fe36bafb4bce460df7b7d13366b0504df8a94d8462b312d12d673d84af5bff3c60a504582953abe0ac74ef202b0d98ec6ea56bfe60a551b1899c95ce15ac3455b0d2b983fa302af67eda4c4b3cd0fa8007ff8d3e67c6132c7b4e2262974844bd5b376d0d270b44e1861cb0d643a26aa650c482dd9717ee2fa0bb0c88d48a94478a321713dbc3ed0694b84da40c352b7ccc48b71d6bd90af65041545e8524bcb91971d6b89c92b1f13e88dc0cb64cf5fc855e70cbc369cbf86b173aefaa14f4db74554a17ff075ba664822d5b17d87f078b33711aacbb23a1b33c24bc2d2b562f4772cbfc9c60de2649fb03d8daed0f80163f60ef21a21fe76c72e6e65db54fff3e56b2a9f6998bd76b37fdce5be07796e47b6bdc2c90933097b3403d67813bfedfb1408e2fc3c99f0716587c7f0bc4b9380b94519715ab4351d0c1ff608112aa4991f1a060815c1d3ace028d9c05e60cb640cc4fa7fda986b740be072e550f68d1c69adb216065f18a78b0323df8506fb1d2a6bf5cc9cbcca74fb522f2e6ae6bd8b31f730562a3e833ad22268608f97e94829c38fb6cdee85dfe54e3f1f0b395089f8d1141a67f31daf5654a7c8706f6ce176aebb4d701994bbab8bb6c788febf5b5c2871411db5d7fb3440ca339dbf49e829a387b3a698f0cf7791f29baec6ff5c77faccfdcbad0376a9beb7678b44e7b01ac204b1c1edf85b0af37da7a49d9755701bd3f26af1ae2786fa6fe4e15b7439f4e5646e2bf9483ff46967307ae1ece7ba79468338d25d26906df7549500a5fb74b37d333d6e49fc836bbeebe041323f9349b34b04de9c3fddd38e998adf8fda197e133c3c8e681fb1c993e2c388015e0c7659b5b2cce7229625739112e17db844beaa2679ae8228388cf1342f039de4763b60a69ef1910cf59948a79b3e6c9e80c706624d9e64b96c1a19fb85bb9aef7ff28ac7d52dbd46669a7705be0145f03d55b4c97af9cb5521f617cf872b2c9c65254807a86fda1626da6867ebec5b91fe8e34b357d95b9049fb1603fd9ebb4c23702cd2c544fabf716efa31e2363a68f6a45e1ab4ee3dbeb8fa9a79d0d30c5d0ca1f91be42fbd892b7d5550d134ba44a24a78653050d47cc3cdf20fb562bcf39b281d0ac000f2daebd6a8b707fa00bcffacbdb9c6bc073cd615b04298ef0b26bafeb3fa510394f7fc0f4f0ae26695245c2d0d94dd867dd4a4c545a39dfb12e2bda5fdee9182e092eb0ce95f7d1720fa48f3004d0a09a998f27fa74594aa37d92fa2368738858fdfe38a2eb9cb852f2d8f4517f22f47f37c04e840891dfcc2e2a8db61667f4ea2da687ad39e6be672cf8fecf4fb5facae8c7f4530cde1d79ba109d2d8ec92eba541b06ff7e51cb6bf9c05f596565dbc5f88657a8815e4ea2e992ac48e7373ba82e73b13f29717d4f31b8ccb7242e433f47227e37226d1e2819f923aac3b77cf00d4fe9f5fd86c02b5b98819288bc5f6de83b5c5b30b3c5f96edb07d73c70877374fa2328a74f90ec4e7f3c2def429334fe4bce4692a6d67572ee1e4a8bb36d424d4df76d57c2195c53203370fb7170995bf72d13d030b48cb09fffb198c6a543f533378fb9e6fccbb5984b8217e60252aaba9c7fc5ed04feba1bb435c1595e7da8f25bf134fcd729899870524c3825e0cbce62ad3ec97d5cbe4f2abf99c55cb20c951349ee2767d9d1a1729626aabdbb5069b27a24fc3bf7d9ba5fe7aaf1ddfda7d5be5de8d7a7d5a3e0395dad847f37a9ae1c4d9c71a574c58c96a3c9aaeb47d7a8ba8e6e54f5676721b4f06387e31dc07180df270ec76ac0278033071c8e6f000b0f391c154025871d8e6ca05169a9296b939302925f7ef9a597c77aa0a792d7a66c58e50aa2bf456b662dd1ae08d0acdd90fc72404c5ae2fa55014fbf94948c849f339d4bc1094f04a4ae4ddd10b031f1e50df004855edeb86ec37df3a5bdf4d23ae421f049dab866ddf3f44b2f273fe1c5456d5cbb2a716d521a48368809fc447f4659f7a38b23ee1fefa45f4dfdafd3273df15fa7c74ee6699240df1468b1403f11e8f6293cad12e84aa1dee593fe6bfac2cbc9892fae7b091acbf7c7cac48d691b0256266fa0570d0aa7bd949834387dfd06e8312e9c9a96969c929806bdb57ec3cb1be90da92fade5e2d7a4ae4f14867880d9d0788ee9a0f000d3ffc98fe2fe855961e84f3a382012fd8fab71fd64ff2799c5ffed9ca1c2f83c22d071029d28d07f08b447a07de13c8d13c2db85303c21022002881f4648f2978f1009900228800c2007780086013c218f1760386004c01b6d178f04fa00945700f501ea0b1805cf4a80dfc3dbd168c083007f800a3006f010e0614000602c2010a0068c03040182012180f180098050c09f008f001e058401fe0c9808780c3009100e980c9802980a88004c033c0e7802301d3003f0246026e02f804890350ae49c057436d068a01aa031d0562d600e602e2016300ff014e069c07cc8f357c002c0338085d00f8b802e86b425c0230e100fe1a5806580e510fe1be059c00ac07310f73c20019008780140039200c990be12900258054885b8d580170169803580b5809700eb203d1df032603d6003c46d04bc02c800bc0a23bc09f01ae075c01b804cc09bde3bd05b802c800e900dd0030c508601e4008cc06f33c004d802c8056c056c03bc0dc803e0fff201ef4cdc815840013c17028a006640316007f0da09280194027601de05bc072803ec069443be3d80f7017b0115804a88df07f8005005f83be01f800f01fb01ff047c04f93e067c02a8061c001c84f843000be030e053c011400de028e018e033402de038a00ef039e004e024a01e700ad000380df8027006f025e02bc0d7806f00ff027c0bf80ef03de007c08f80b320c3394023e03ce027e8a19f1fde817e81e75f01170017610c7e03da04f92f012e03ac8066400ba0156003b401ae00ae02ae01da01d70137003701b7001d80df01b7019d802e4037c00ee801f402ee00ee02fa00fd807b00c7c3dc04b050985216f164dc0221bc18ffb3fa1787e355400ea000500ef808f019e01bc045c00dc03dc0f05f1d8e870053013180c5801700eb006f02b6024a01ff001c057c05f815d00ee803785e7038548073f07c0b2083e700401860062016b014b012f00ac00078075006d80ff80af0e06f0e4728e057783e0a6807f4017c2e3a1ce30093009180f9806701ab016700af01b6007602aa003f03ae028e00ee003c80e752c05a4016e01dc03f004701df03da01f700dee0cb8f034402e2006b01d9807701af5c823a003b010720fc2da00dd007f083b830400c60392007900448bbc4977b0d70eeb2c3d10ce804f40082c1ff9f013000de071c052cb6f2693f024d139e71fae266876315e00dc049c0558843405580ed8032c047cd7c5ec3209e98fe0ef1012dd0678030789ed33c90fe06c47d7599478f001c87d058418f0205aae66852e286c4e7335293c0979bf964c09480e0e0804151339e0c98c6e786c57edd0be0af8d7d326049d4c2c5cf2f5afcd705cf4ffa37f18f3d3fc5b92e8e0d9cbbf615f0189202d625be9cba6153a0101f7bcde198058811e8daf681f07c01380e874307210eb0f9068f77010601af5c1f08e36783909e3d08476f423f102291187e12e147bafda4ffe147fd0f7fb2ffcbbf1edae96720dea92204df8ae07d9d00b12b9dfb4d4ce5c36d022d5b3d34fdffeb3fe7ffd76478f8d77f9ffcc09ad6f68b241af67f55a2fffdfdefef7f7ffffbfbdfdfff9f7e4b5fe4d755275de5465f75a39bdd68b11bdde7460fbbd1d36ef4bc1b6d73a33d6e54963694fab9d1f16e749a1b9de34697bad1556ef45537bad98d16bbd17d6ef4b01b3ded46cfbbd13637dae346656b86523f373ade8d4e73a373dce85237baca8dbeea4637bbd16237bacf8d1e76a3a7dde87937dae6467bdca86ced50eae746c7bbd1696e748e1b5dea4657b9d157dde866375aec46f7b9d1c36ef4b41b3def46dbdc688f1b95bd3494fab9d1f16e749a1b9de34697bad1556ef45537bad98d16bbd17d6ef4b01b3ded46cfbbd13637dae34665eb86523f373ade8d4e73a373dce85237baca8dbeea4637bbd16237bacf8d1e76a3a7dde87937dae6467bdca82c7d28f573a3e3dde834373ac78d2e75a3abdce8ab6e74b31b2d76a3fbdce861377ada8d9e77a36d6eb4c78dca5e1e4afddce878373acd8dce71a34bdde82a37faaa1bddec468bdde83e377ad88d9e76a3e7dd689b1bed71a3b2f543a99f1b1def46a7b9d1396ed4b92f77083fe7f61c5d946721b7dfffc9db90ff07cff9cdf8'
+        ISP_PROG = binascii.unhexlify(ISP_PROG)
+        ISP_PROG = zlib.decompress(ISP_PROG)
+
+        def printProgressBar (iteration, total, prefix = '', suffix = '', filename = '', decimals = 1, length = 100, fill = '='):
+            """
+            Call in a loop to create terminal progress bar
+            @params:
+                iteration   - Required  : current iteration (Int)
+                total       - Required  : total iterations (Int)
+                prefix      - Optional  : prefix string (Str)
+                suffix      - Optional  : suffix string (Str)
+                decimals    - Optional  : positive number of decimals in percent complete (Int)
+                length      - Optional  : character length of bar (Int)
+                fill        - Optional  : bar fill character (Str)
+            """
+            percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
+            filledLength = int(length * iteration // total)
+            bar = fill * filledLength + '-' * (length - filledLength)
+            KFlash.log('\r%s |%s| %s%% %s' % (prefix, bar, percent, suffix), end = '\r')
+            # Print New Line on Complete
+            if iteration == total:
+                KFlash.log()
+            if callback:
+                fileTypeStr = filename
+                if prefix == "Downloading ISP:":
+                    fileTypeStr = "ISP"
+                elif prefix == "Programming BIN:" and fileTypeStr == "":
+                    fileTypeStr = "BIN"
+                callback(fileTypeStr, iteration, total, suffix)
+
+        def slip_reader(port):
+            partial_packet = None
+            in_escape = False
+
+            while True:
+                waiting = port.inWaiting()
+                read_bytes = port.read(1 if waiting == 0 else waiting)
+                if read_bytes == b'':
+                    raise_exception( Exception("Timed out waiting for packet %s" % ("header" if partial_packet is None else "content")) )
+                for b in read_bytes:
+
+                    if type(b) is int:
+                        b = bytes([b])  # python 2/3 compat
+
+                    if partial_packet is None:  # waiting for packet header
+                        if b == b'\xc0':
+                            partial_packet = b""
+                        else:
+                            raise_exception( Exception('Invalid head of packet (%r)' % b) )
+                    elif in_escape:  # part-way through escape sequence
+                        in_escape = False
+                        if b == b'\xdc':
+                            partial_packet += b'\xc0'
+                        elif b == b'\xdd':
+                            partial_packet += b'\xdb'
+                        else:
+                            raise_exception( Exception('Invalid SLIP escape (%r%r)' % (b'\xdb', b)) )
+                    elif b == b'\xdb':  # start of escape sequence
+                        in_escape = True
+                    elif b == b'\xc0':  # end of packet
+                        yield partial_packet
+                        partial_packet = None
+                    else:  # normal byte in packet
+                        partial_packet += b
+
+
+        class ISPResponse:
+            class ISPOperation(Enum):
+                ISP_ECHO = 0xC1
+                ISP_NOP = 0xC2
+                ISP_MEMORY_WRITE = 0xC3
+                ISP_MEMORY_READ = 0xC4
+                ISP_MEMORY_BOOT = 0xC5
+                ISP_DEBUG_INFO = 0xD1
+                ISP_CHANGE_BAUDRATE = 0xc6
+
+            class ErrorCode(Enum):
+                ISP_RET_DEFAULT = 0
+                ISP_RET_OK = 0xE0
+                ISP_RET_BAD_DATA_LEN = 0xE1
+                ISP_RET_BAD_DATA_CHECKSUM = 0xE2
+                ISP_RET_INVALID_COMMAND = 0xE3
+
+            @staticmethod
+            def parse(data):
+                # type: (bytes) -> (int, int, str)
+                op = 0
+                reason = 0
+                text = ''
+
+                if (sys.version_info > (3, 0)):
+                    op = int(data[0])
+                    reason = int(data[1])
+                else:
+                    op = ord(data[0])
+                    reason = ord(data[1])
+
+                try:
+                    if ISPResponse.ISPOperation(op) == ISPResponse.ISPOperation.ISP_DEBUG_INFO:
+                        text = data[2:].decode()
+                except ValueError:
+                    KFlash.log('Warning: recv unknown op', op)
+
+                return (op, reason, text)
+
+
+        class FlashModeResponse:
+            class Operation(Enum):
+                ISP_DEBUG_INFO = 0xD1
+                ISP_NOP = 0xD2
+                ISP_FLASH_ERASE = 0xD3
+                ISP_FLASH_WRITE = 0xD4
+                ISP_REBOOT = 0xD5
+                ISP_UARTHS_BAUDRATE_SET = 0xD6
+                FLASHMODE_FLASH_INIT = 0xD7
+
+            class ErrorCode(Enum):
+                ISP_RET_DEFAULT = 0
+                ISP_RET_OK = 0xE0
+                ISP_RET_BAD_DATA_LEN = 0xE1
+                ISP_RET_BAD_DATA_CHECKSUM = 0xE2
+                ISP_RET_INVALID_COMMAND = 0xE3
+                ISP_RET_BAD_INITIALIZATION = 0xE4
+                ISP_RET_BAD_EXEC = 0xE5
+
+            @staticmethod
+            def parse(data):
+                # type: (bytes) -> (int, int, str)
+                op = 0
+                reason = 0
+                text = ''
+
+                if (sys.version_info > (3, 0)):
+                    op = int(data[0])
+                    reason = int(data[1])
+                else:
+                    op = ord(data[0])
+                    reason = ord(data[1])
+
+                if FlashModeResponse.Operation(op) == FlashModeResponse.Operation.ISP_DEBUG_INFO:
+                    text = data[2:].decode()
+                reason_enum = FlashModeResponse.ErrorCode(reason)
+                if (not text) or (text.strip() == ""):
+                    if reason_enum == FlashModeResponse.ErrorCode.ISP_RET_OK:
+                        text = "ok"
+                    elif reason_enum == FlashModeResponse.ErrorCode.ISP_RET_BAD_DATA_LEN:
+                        text = "bad data len"
+                    elif reason_enum == FlashModeResponse.ErrorCode.ISP_RET_BAD_DATA_CHECKSUM:
+                        print("aaa")
+                        text = "bad data checksum"
+                    elif reason_enum == FlashModeResponse.ErrorCode.ISP_RET_BAD_INITIALIZATION:
+                        text = "bad initialization"
+                    elif reason_enum == FlashModeResponse.ErrorCode.ISP_RET_INVALID_COMMAND:
+                        text = "invalid command"
+                    elif reason_enum == FlashModeResponse.ErrorCode.ISP_RET_BAD_EXEC:
+                        text = "execute cmd error"
+                    else:
+                        text = "unknown error"
+                return (op, reason, text)
+
+
+        def chunks(l, n, address=None):
+            """Yield successive n-sized chunks from l."""
+            if address != None and (address % n != 0):
+                start_pos = n - (address - address // n * n)
+                if start_pos % ISP_FLASH_SECTOR_SIZE != 0:
+                    raise_exception(Exception("data should 4KiB align"))
+                count_4k_blocks = start_pos // ISP_FLASH_SECTOR_SIZE
+                count = math.ceil((len(l) - start_pos)/n) + count_4k_blocks
+                for i in range(count):
+                    if i < count_4k_blocks:
+                        yield l[ISP_FLASH_SECTOR_SIZE*i:ISP_FLASH_SECTOR_SIZE*(i+1)]
+                    else:
+                        start = start_pos+(i-count_4k_blocks)*n
+                        yield l[start:start+n]
+            else:
+                for i in range(0, len(l), n):
+                    yield l[i:i + n]
+
+        class TerminalSize:
+            @staticmethod
+            def getTerminalSize():
+                import platform
+                current_os = platform.system()
+                tuple_xy=None
+                if current_os == 'Windows':
+                    tuple_xy = TerminalSize._getTerminalSize_windows()
+                    if tuple_xy is None:
+                        tuple_xy = TerminalSize._getTerminalSize_tput()
+                        # needed for window's python in cygwin's xterm!
+                if current_os == 'Linux' or current_os == 'Darwin' or  current_os.startswith('CYGWIN'):
+                    tuple_xy = TerminalSize._getTerminalSize_linux()
+                if tuple_xy is None:
+                    # Use default value
+                    tuple_xy = (80, 25)      # default value
+                return tuple_xy
+
+            @staticmethod
+            def _getTerminalSize_windows():
+                res=None
+                try:
+                    from ctypes import windll, create_string_buffer
+
+                    # stdin handle is -10
+                    # stdout handle is -11
+                    # stderr handle is -12
+
+                    h = windll.kernel32.GetStdHandle(-12)
+                    csbi = create_string_buffer(22)
+                    res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
+                except:
+                    return None
+                if res:
+                    import struct
+                    (bufx, bufy, curx, cury, wattr,
+                    left, top, right, bottom, maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw)
+                    sizex = right - left + 1
+                    sizey = bottom - top + 1
+                    return sizex, sizey
+                else:
+                    return None
+
+            @staticmethod
+            def _getTerminalSize_tput():
+                # get terminal width
+                # src: http://stackoverflow.com/questions/263890/how-do-i-find-the-width-height-of-a-terminal-window
+                try:
+                    import subprocess
+                    proc=subprocess.Popen(["tput", "cols"],stdin=subprocess.PIPE,stdout=subprocess.PIPE)
+                    output=proc.communicate(input=None)
+                    cols=int(output[0])
+                    proc=subprocess.Popen(["tput", "lines"],stdin=subprocess.PIPE,stdout=subprocess.PIPE)
+                    output=proc.communicate(input=None)
+                    rows=int(output[0])
+                    return (cols,rows)
+                except:
+                    return None
+
+            @staticmethod
+            def _getTerminalSize_linux():
+                def ioctl_GWINSZ(fd):
+                    try:
+                        import fcntl, termios, struct, os
+                        cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,'1234'))
+                    except:
+                        return None
+                    return cr
+                cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
+                if not cr:
+                    try:
+                        fd = os.open(os.ctermid(), os.O_RDONLY)
+                        cr = ioctl_GWINSZ(fd)
+                        os.close(fd)
+                    except:
+                        pass
+                if not cr:
+                    try:
+                        cr = (os.env['LINES'], os.env['COLUMNS'])
+                    except:
+                        return None
+                return int(cr[1]), int(cr[0])
+
+            @staticmethod
+            def get_terminal_size(fallback=(100, 24), terminal = False):
+                try:
+                    columns, rows = TerminalSize.getTerminalSize()
+                    if not terminal:
+                        if not terminal_auto_size:
+                            columns, rows = terminal_size
+                except:
+                    columns, rows = fallback
+
+                return columns, rows
+
+        class MAIXLoader:
+            def change_baudrate(self, baudrate):
+                KFlash.log(INFO_MSG,"Selected Baudrate: ", baudrate, BASH_TIPS['DEFAULT'])
+                out = struct.pack('III', 0, 4, baudrate)
+                crc32_checksum = struct.pack('I', binascii.crc32(out) & 0xFFFFFFFF)
+                out = struct.pack('HH', 0xd6, 0x00) + crc32_checksum + out
+                self.write(out)
+                time.sleep(0.05)
+                self._port.baudrate = baudrate
+                if args.Board == "goE":
+                    if baudrate >= 4500000:
+                        # OPENEC super baudrate
+                        KFlash.log(INFO_MSG, "Enable OPENEC super baudrate!!!",  BASH_TIPS['DEFAULT'])
+                        if baudrate == 4500000:
+                            self._port.baudrate = 300
+                        if baudrate == 6000000:
+                            self._port.baudrate = 250
+                        if baudrate == 7500000:
+                            self._port.baudrate = 350
+
+            def change_baudrate_stage0(self, baudrate):
+                # Dangerous, here are dinosaur infested!!!!!
+                # Don't touch this code unless you know what you are doing
+                # Stage0 baudrate is fixed
+                # Contributor: [@rgwan](https://github.com/rgwan)
+                #              rgwan <dv.xw@qq.com>
+                baudrate = 1500000
+                if args.Board == "goE" or args.Board == "trainer":
+                    KFlash.log(INFO_MSG,"Selected Stage0 Baudrate: ", baudrate, BASH_TIPS['DEFAULT'])
+                    # This is for openec, contained ft2232, goE and trainer
+                    KFlash.log(INFO_MSG,"FT2232 mode", BASH_TIPS['DEFAULT'])
+                    baudrate_stage0 = int(baudrate * 38.6 / 38)
+                    out = struct.pack('III', 0, 4, baudrate_stage0)
+                    crc32_checksum = struct.pack('I', binascii.crc32(out) & 0xFFFFFFFF)
+                    out = struct.pack('HH', 0xc6, 0x00) + crc32_checksum + out
+                    self.write(out)
+                    time.sleep(0.05)
+                    self._port.baudrate = baudrate
+
+                    retry_count = 0
+                    while 1:
+                        self.checkKillExit()
+                        retry_count = retry_count + 1
+                        if retry_count > 3:
+                            err = (ERROR_MSG,'Fast mode failed, please use slow mode by add parameter ' + BASH_TIPS['GREEN'] + '--Slow', BASH_TIPS['DEFAULT'])
+                            err = tuple2str(err)
+                            raise_exception( Exception(err) )
+                        try:
+                            self.greeting()
+                            break
+                        except TimeoutError:
+                            pass
+                elif args.Board == "dan" or args.Board == "bit" or args.Board == "kd233":
+                    KFlash.log(INFO_MSG,"CH340 mode", BASH_TIPS['DEFAULT'])
+                    # This is for CH340, contained dan, bit and kd233
+                    baudrate_stage0 = int(baudrate * 38.4 / 38)
+                    # CH340 can not use this method, test failed, take risks at your own risk
+                else:
+                    # This is for unknown board
+                    KFlash.log(WARN_MSG,"Unknown mode", BASH_TIPS['DEFAULT'])
+
+            def __init__(self, port='/dev/ttyUSB1', baudrate=115200):
+                # configure the serial connections (the parameters differs on the device you are connecting to)
+                self._port = serial.Serial(
+                    port=port,
+                    baudrate=baudrate,
+                    parity=serial.PARITY_NONE,
+                    stopbits=serial.STOPBITS_ONE,
+                    bytesize=serial.EIGHTBITS,
+                    timeout=0.1
+                )
+                KFlash.log(INFO_MSG, "Default baudrate is", baudrate, ", later it may be changed to the value you set.",  BASH_TIPS['DEFAULT'])
+
+                self._port.isOpen()
+                self._slip_reader = slip_reader(self._port)
+                self._kill_process = False
+
+            """ Read a SLIP packet from the serial port """
+
+            def read(self):
+                return next(self._slip_reader)
+
+            """ Write bytes to the serial port while performing SLIP escaping """
+
+            def write(self, packet):
+                buf = b'\xc0' \
+                      + (packet.replace(b'\xdb', b'\xdb\xdd').replace(b'\xc0', b'\xdb\xdc')) \
+                      + b'\xc0'
+                #KFlash.log('[WRITE]', binascii.hexlify(buf))
+                return self._port.write(buf)
+
+            def read_loop(self):
+                #out = b''
+                # while self._port.inWaiting() > 0:
+                #     out += self._port.read(1)
+
+                # KFlash.log(out)
+                while 1:
+                    sys.stdout.write('[RECV] raw data: ')
+                    sys.stdout.write(binascii.hexlify(self._port.read(1)).decode())
+                    sys.stdout.flush()
+
+            def recv_one_return(self, timeout_s = None):
+                timeout_init = time.time()
+                data = b''
+                if timeout_s == None:
+                    timeout_s = ISP_RECEIVE_TIMEOUT
+                # find start boarder
+                #sys.stdout.write('[RECV one return] raw data: ')
+                while 1:
+                    if time.time() - timeout_init > timeout_s:
+                        raise_exception( TimeoutError )
+                    c = self._port.read(1)
+                    #sys.stdout.write(binascii.hexlify(c).decode())
+                    sys.stdout.flush()
+                    if c == b'\xc0':
+                        break
+
+                in_escape = False
+                while 1:
+                    if time.time() - timeout_init > timeout_s:
+                        raise_exception( TimeoutError )
+                    c = self._port.read(1)
+                    #sys.stdout.write(binascii.hexlify(c).decode())
+                    sys.stdout.flush()
+                    if c == b'\xc0':
+                        break
+
+                    elif in_escape:  # part-way through escape sequence
+                        in_escape = False
+                        if c == b'\xdc':
+                            data += b'\xc0'
+                        elif c == b'\xdd':
+                            data += b'\xdb'
+                        else:
+                            raise_exception( Exception('Invalid SLIP escape (%r%r)' % (b'\xdb', c)) )
+                    elif c == b'\xdb':  # start of escape sequence
+                        in_escape = True
+
+                    data += c
+
+                #sys.stdout.write('\n')
+                return data
+
+            # kd233 or open-ec or new cmsis-dap
+            def reset_to_isp_kd233(self):
+                self._port.setDTR (False)
+                self._port.setRTS (False)
+                time.sleep(0.1)
+                #KFlash.log('-- RESET to LOW, IO16 to HIGH --')
+                # Pull reset down and keep 10ms
+                self._port.setDTR (True)
+                self._port.setRTS (False)
+                time.sleep(0.1)
+                #KFlash.log('-- IO16 to LOW, RESET to HIGH --')
+                # Pull IO16 to low and release reset
+                self._port.setRTS (True)
+                self._port.setDTR (False)
+                time.sleep(0.1)
+            def reset_to_boot_kd233(self):
+                self._port.setDTR (False)
+                self._port.setRTS (False)
+                time.sleep(0.1)
+                #KFlash.log('-- RESET to LOW --')
+                # Pull reset down and keep 10ms
+                self._port.setDTR (True)
+                self._port.setRTS (False)
+                time.sleep(0.1)
+                #KFlash.log('-- RESET to HIGH, BOOT --')
+                # Pull IO16 to low and release reset
+                self._port.setRTS (False)
+                self._port.setDTR (False)
+                time.sleep(0.1)
+
+            #dan dock
+            def reset_to_isp_dan(self):
+                self._port.setDTR (False)
+                self._port.setRTS (False)
+                time.sleep(0.1)
+                #KFlash.log('-- RESET to LOW, IO16 to HIGH --')
+                # Pull reset down and keep 10ms
+                self._port.setDTR (False)
+                self._port.setRTS (True)
+                time.sleep(0.1)
+                #KFlash.log('-- IO16 to LOW, RESET to HIGH --')
+                # Pull IO16 to low and release reset
+                self._port.setRTS (False)
+                self._port.setDTR (True)
+                time.sleep(0.1)
+            def reset_to_boot_dan(self):
+                self._port.setDTR (False)
+                self._port.setRTS (False)
+                time.sleep(0.1)
+                #KFlash.log('-- RESET to LOW --')
+                # Pull reset down and keep 10ms
+                self._port.setDTR (False)
+                self._port.setRTS (True)
+                time.sleep(0.1)
+                #KFlash.log('-- RESET to HIGH, BOOT --')
+                # Pull IO16 to low and release reset
+                self._port.setRTS (False)
+                self._port.setDTR (False)
+                time.sleep(0.1)
+
+            # maix goD for old cmsis-dap firmware
+            def reset_to_isp_goD(self):
+                self._port.setDTR (True)   ## output 0
+                self._port.setRTS (True)
+                time.sleep(0.1)
+                #KFlash.log('-- RESET to LOW --')
+                # Pull reset down and keep 10ms
+                self._port.setRTS (False)
+                self._port.setDTR (True)
+                time.sleep(0.1)
+                #KFlash.log('-- RESET to HIGH, BOOT --')
+                # Pull IO16 to low and release reset
+                self._port.setRTS (False)
+                self._port.setDTR (True)
+                time.sleep(0.1)
+            def reset_to_boot_goD(self):
+                self._port.setDTR (False)
+                self._port.setRTS (False)
+                time.sleep(0.1)
+                #KFlash.log('-- RESET to LOW --')
+                # Pull reset down and keep 10ms
+                self._port.setRTS (False)
+                self._port.setDTR (True)
+                time.sleep(0.1)
+                #KFlash.log('-- RESET to HIGH, BOOT --')
+                # Pull IO16 to low and release reset
+                self._port.setRTS (True)
+                self._port.setDTR (True)
+                time.sleep(0.1)
+
+            # maix goE for openec or new cmsis-dap  firmware
+            def reset_to_boot_maixgo(self):
+                self._port.setDTR (False)
+                self._port.setRTS (False)
+                time.sleep(0.1)
+                #KFlash.log('-- RESET to LOW --')
+                # Pull reset down and keep 10ms
+                self._port.setRTS (False)
+                self._port.setDTR (True)
+                time.sleep(0.1)
+                #KFlash.log('-- RESET to HIGH, BOOT --')
+                # Pull IO16 to low and release reset
+                self._port.setRTS (False)
+                self._port.setDTR (False)
+                time.sleep(0.1)
+
+            def greeting(self):
+                self._port.write(b'\xc0\xc2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0')
+                op, reason, text = ISPResponse.parse(self.recv_one_return())
+
+                #KFlash.log('MAIX return op:', ISPResponse.ISPOperation(op).name, 'reason:', ISPResponse.ErrorCode(reason).name)
+
+
+            def flash_greeting(self):
+                retry_count = 0
+                while 1:
+                    self.checkKillExit()
+                    try:
+                        self._port.write(b'\xc0\xd2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0')
+                    except Exception:
+                        raise_exception( Exception("Connection disconnected, try again or maybe need use Slow mode, or decrease baudrate") )
+                    retry_count = retry_count + 1
+                    try:
+                        op, reason, text = FlashModeResponse.parse(self.recv_one_return())
+                    except IndexError:
+                        if retry_count > MAX_RETRY_TIMES:
+                            err = (ERROR_MSG,"Failed to Connect to K210's Stub",BASH_TIPS['DEFAULT'])
+                            err = tuple2str(err)
+                            raise_exception( Exception(err) )
+                        KFlash.log(WARN_MSG,"Index Error, retrying...",BASH_TIPS['DEFAULT'])
+                        time.sleep(0.1)
+                        continue
+                    except TimeoutError:
+                        if retry_count > MAX_RETRY_TIMES:
+                            err = (ERROR_MSG,"Failed to Connect to K210's Stub",BASH_TIPS['DEFAULT'])
+                            err = tuple2str(err)
+                            raise_exception( Exception(err) )
+                        KFlash.log(WARN_MSG,"Timeout Error, retrying...",BASH_TIPS['DEFAULT'])
+                        time.sleep(0.1)
+                        continue
+                    except:
+                        if retry_count > MAX_RETRY_TIMES:
+                            err = (ERROR_MSG,"Failed to Connect to K210's Stub",BASH_TIPS['DEFAULT'])
+                            err = tuple2str(err)
+                            raise_exception( Exception(err) )
+                        KFlash.log(WARN_MSG,"Unexcepted Error, retrying...",BASH_TIPS['DEFAULT'])
+                        time.sleep(0.1)
+                        continue
+                    # KFlash.log('MAIX return op:', FlashModeResponse.Operation(op).name, 'reason:',
+                    #      FlashModeResponse.ErrorCode(reason).name)
+                    if FlashModeResponse.Operation(op) == FlashModeResponse.Operation.ISP_NOP and FlashModeResponse.ErrorCode(reason) == FlashModeResponse.ErrorCode.ISP_RET_OK:
+                        KFlash.log(INFO_MSG,"Boot to Flashmode Successfully",BASH_TIPS['DEFAULT'])
+                        self._port.flushInput()
+                        self._port.flushOutput()
+                        break
+                    else:
+                        if retry_count > MAX_RETRY_TIMES:
+                            err = (ERROR_MSG,"Failed to Connect to K210's Stub",BASH_TIPS['DEFAULT'])
+                            err = tuple2str(err)
+                            raise_exception( Exception(err) )
+                        KFlash.log(WARN_MSG,"Unexcepted Return recevied, retrying...",BASH_TIPS['DEFAULT'])
+                        time.sleep(0.1)
+                        continue
+
+            def boot(self, address=0x80000000):
+                KFlash.log(INFO_MSG,"Booting From " + hex(address),BASH_TIPS['DEFAULT'])
+
+                out = struct.pack('II', address, 0)
+
+                crc32_checksum = struct.pack('I', binascii.crc32(out) & 0xFFFFFFFF)
+
+                out = struct.pack('HH', 0xc5, 0x00) + crc32_checksum + out  # op: ISP_MEMORY_WRITE: 0xc3
+                self.write(out)
+
+            def recv_debug(self):
+                op, reason, text = ISPResponse.parse(self.recv_one_return())
+                #KFlash.log('[RECV] op:', ISPResponse.ISPOperation(op).name, 'reason:', ISPResponse.ErrorCode(reason).name)
+                if text:
+                    KFlash.log('-' * 30)
+                    KFlash.log(text)
+                    KFlash.log('-' * 30)
+                if ISPResponse.ErrorCode(reason) not in (ISPResponse.ErrorCode.ISP_RET_DEFAULT, ISPResponse.ErrorCode.ISP_RET_OK):
+                    KFlash.log('Failed, retry, errcode=', hex(reason))
+                    return False
+                return True
+
+            def flash_recv_debug(self):
+                op, reason, text = FlashModeResponse.parse(self.recv_one_return())
+                #KFlash.log('[Flash-RECV] op:', FlashModeResponse.Operation(op).name, 'reason:',
+                #      FlashModeResponse.ErrorCode(reason).name)
+                if text:
+                    KFlash.log('-' * 30)
+                    KFlash.log(text)
+                    KFlash.log('-' * 30)
+
+                if FlashModeResponse.ErrorCode(reason) not in (FlashModeResponse.ErrorCode.ISP_RET_OK, FlashModeResponse.ErrorCode.ISP_RET_OK):
+                    KFlash.log('Failed, retry')
+                    return False
+                return True
+
+            def init_flash(self, chip_type):
+                chip_type = int(chip_type)
+                KFlash.log(INFO_MSG,"Selected Flash: ",("In-Chip", "On-Board")[chip_type],BASH_TIPS['DEFAULT'])
+                out = struct.pack('II', chip_type, 0)
+                crc32_checksum = struct.pack('I', binascii.crc32(out) & 0xFFFFFFFF)
+                out = struct.pack('HH', 0xd7, 0x00) + crc32_checksum + out
+                '''Retry when it have error'''
+                retry_count = 0
+                while 1:
+                    self.checkKillExit()
+                    sent = self.write(out)
+                    retry_count = retry_count + 1
+                    try:
+                        op, reason, text = FlashModeResponse.parse(self.recv_one_return())
+                    except IndexError:
+                        if retry_count > MAX_RETRY_TIMES:
+                            err = (ERROR_MSG,"Failed to initialize flash",BASH_TIPS['DEFAULT'])
+                            err = tuple2str(err)
+                            raise_exception( Exception(err) )
+                        KFlash.log(WARN_MSG,"Index Error, retrying...",BASH_TIPS['DEFAULT'])
+                        time.sleep(0.1)
+                        continue
+                    except TimeoutError:
+                        if retry_count > MAX_RETRY_TIMES:
+                            err = (ERROR_MSG,"Failed to initialize flash",BASH_TIPS['DEFAULT'])
+                            err = tuple2str(err)
+                            raise_exception( Exception(err) )
+                        KFlash.log(WARN_MSG,"Timeout Error, retrying...",BASH_TIPS['DEFAULT'])
+                        time.sleep(0.1)
+                        continue
+                    except:
+                        if retry_count > MAX_RETRY_TIMES:
+                            err = (ERROR_MSG,"Failed to initialize flash",BASH_TIPS['DEFAULT'])
+                            err = tuple2str(err)
+                            raise_exception( Exception(err) )
+                        KFlash.log(WARN_MSG,"Unexcepted Error, retrying...",BASH_TIPS['DEFAULT'])
+                        time.sleep(0.1)
+                        continue
+                    # KFlash.log('MAIX return op:', FlashModeResponse.Operation(op).name, 'reason:',
+                    #      FlashModeResponse.ErrorCode(reason).name)
+                    if FlashModeResponse.Operation(op) == FlashModeResponse.Operation.FLASHMODE_FLASH_INIT and FlashModeResponse.ErrorCode(reason) == FlashModeResponse.ErrorCode.ISP_RET_OK:
+                        KFlash.log(INFO_MSG,"Initialization flash Successfully",BASH_TIPS['DEFAULT'])
+                        break
+                    else:
+                        if retry_count > MAX_RETRY_TIMES:
+                            err = (ERROR_MSG,"Failed to initialize flash",BASH_TIPS['DEFAULT'])
+                            err = tuple2str(err)
+                            raise_exception( Exception(err) )
+                        KFlash.log(WARN_MSG,"Unexcepted Return recevied, retrying...",BASH_TIPS['DEFAULT'])
+                        time.sleep(0.1)
+                        continue
+
+            def flash_dataframe(self, data, address=0x80000000):
+                DATAFRAME_SIZE = 1024
+                data_chunks = chunks(data, DATAFRAME_SIZE)
+                #KFlash.log('[DEBUG] flash dataframe | data length:', len(data))
+                total_chunk = math.ceil(len(data)/DATAFRAME_SIZE)
+
+                time_start = time.time()
+                for n, chunk in enumerate(data_chunks):
+                    self.checkKillExit()
+                    while 1:
+                        self.checkKillExit()
+                        #KFlash.log('[INFO] sending chunk', i, '@address', hex(address), 'chunklen', len(chunk))
+                        out = struct.pack('II', address, len(chunk))
+
+                        crc32_checksum = struct.pack('I', binascii.crc32(out + chunk) & 0xFFFFFFFF)
+
+                        out = struct.pack('HH', 0xc3, 0x00) + crc32_checksum + out + chunk  # op: ISP_MEMORY_WRITE: 0xc3
+                        sent = self.write(out)
+                        #KFlash.log('[INFO]', 'sent', sent, 'bytes', 'checksum', binascii.hexlify(crc32_checksum).decode())
+
+                        address += len(chunk)
+
+                        if self.recv_debug():
+                            break
+
+                    columns, lines = TerminalSize.get_terminal_size((100, 24), terminal)
+                    time_delta = time.time() - time_start
+                    speed = ''
+                    if (time_delta > 1):
+                        speed = str(int((n + 1) * DATAFRAME_SIZE / 1024.0 / time_delta)) + 'kiB/s'
+                    printProgressBar(n+1, total_chunk, prefix = 'Downloading ISP:', suffix = speed, length = columns - 35)
+
+            def dump_to_flash(self, data, address=0, size=None):
+                '''
+                typedef struct __attribute__((packed)) {
+                    uint8_t op;
+                    int32_t checksum; /* All the fields below are involved in the calculation of checksum */
+                    uint32_t address;
+                    uint32_t data_len;
+                    uint8_t data_buf[1024];
+                } isp_request_t;
+                '''
+                if size == None:
+                    DATAFRAME_SIZE = ISP_FLASH_DATA_FRAME_SIZE
+                    size = DATAFRAME_SIZE
+                data_chunks = chunks(data, size)
+                #KFlash.log('[DEBUG] flash dataframe | data length:', len(data))
+
+
+
+                for n, chunk in enumerate(data_chunks):
+                    #KFlash.log('[INFO] sending chunk', i, '@address', hex(address))
+                    out = struct.pack('II', address, len(chunk))
+
+                    crc32_checksum = struct.pack('I', binascii.crc32(out + chunk) & 0xFFFFFFFF)
+
+                    out = struct.pack('HH', 0xd4, 0x00) + crc32_checksum + out + chunk
+                    #KFlash.log("[$$$$]", binascii.hexlify(out[:32]).decode())
+                    retry_count = 0
+                    while True:
+                        try:
+                            sent = self.write(out)
+                            #KFlash.log('[INFO]', 'sent', sent, 'bytes', 'checksum', crc32_checksum)
+                            self.flash_recv_debug()
+                        except:
+                            retry_count = retry_count + 1
+                            if retry_count > MAX_RETRY_TIMES:
+                                err = (ERROR_MSG,"Error Count Exceeded, Stop Trying",BASH_TIPS['DEFAULT'])
+                                err = tuple2str(err)
+                                raise_exception( Exception(err) )
+                            continue
+                        break
+                    address += len(chunk)
+
+
+
+            def flash_erase(self, erase_addr = 0, erase_len = 0):
+                #KFlash.log('[DEBUG] erasing spi flash.')
+                cmd0 = b'\xd3\x00\x00\x00'
+                cmd = struct.pack("I", erase_addr)
+                cmd += struct.pack("I", erase_len)
+                cmd = cmd0 + struct.pack('I', binascii.crc32(cmd) & 0xFFFFFFFF) + cmd
+                self.write(cmd)
+                t = time.time()
+                op, reason, text = FlashModeResponse.parse(self.recv_one_return(timeout_s=90))
+                if FlashModeResponse.ErrorCode(reason) != FlashModeResponse.ErrorCode.ISP_RET_OK:
+                    err = (ERROR_MSG,"erase error, error code: 0x{:02X}: {}".format(reason, text))
+                    err = tuple2str(err)
+                    raise_exception( Exception(err) )
+                else:
+                    KFlash.log(INFO_MSG,"erase ok")
+                #KFlash.log('MAIX return op:', FlashModeResponse.Operation(op).name, 'reason:',
+                #      FlashModeResponse.ErrorCode(reason).name)
+
+            def install_flash_bootloader(self, data):
+                # Download flash bootloader
+                self.flash_dataframe(data, address=0x80000000)
+
+            def load_elf_to_sram(self, f):
+                try:
+                    from elftools.elf.elffile import ELFFile
+                    from elftools.elf.descriptions import describe_p_type
+                except ImportError:
+                    err = (ERROR_MSG,'pyelftools must be installed, run '+BASH_TIPS['GREEN']+'`' + ('pip', 'pip3')[sys.version_info > (3, 0)] + ' install pyelftools`',BASH_TIPS['DEFAULT'])
+                    err = tuple2str(err)
+                    raise_exception( Exception(err) )
+
+                elffile = ELFFile(f)
+                if elffile['e_entry'] != 0x80000000:
+                    KFlash.log(WARN_MSG,"ELF entry is 0x%x instead of 0x80000000" % (elffile['e_entry']), BASH_TIPS['DEFAULT'])
+
+                for segment in elffile.iter_segments():
+                    t = describe_p_type(segment['p_type'])
+                    KFlash.log(INFO_MSG, ("Program Header: Size: %d, Virtual Address: 0x%x, Type: %s" % (segment['p_filesz'], segment['p_vaddr'], t)), BASH_TIPS['DEFAULT'])
+                    if not (segment['p_vaddr'] & 0x80000000):
+                        continue
+                    if segment['p_filesz']==0 or segment['p_vaddr']==0:
+                        KFlash.log("Skipped")
+                        continue
+                    self.flash_dataframe(segment.data(), segment['p_vaddr'])
+
+            def flash_firmware(self, firmware_bin, aes_key = None, address_offset = 0, sha256Prefix = True, filename = ""):
+                # type: (bytes, bytes, int, bool) -> None
+                # Don't remove above code!
+
+                #KFlash.log('[DEBUG] flash_firmware DEBUG: aeskey=', aes_key)
+
+                if sha256Prefix == True:
+                    # Add header to the firmware
+                    # Format: SHA256(after)(32bytes) + AES_CIPHER_FLAG (1byte) + firmware_size(4bytes) + firmware_data
+                    aes_cipher_flag = b'\x01' if aes_key else b'\x00'
+
+                    # Encryption
+                    if aes_key:
+                        enc = AES_128_CBC(aes_key, iv=b'\x00'*16).encrypt
+                        padded = firmware_bin + b'\x00'*15 # zero pad
+                        firmware_bin = b''.join([enc(padded[i*16:i*16+16]) for i in range(len(padded)//16)])
+
+                    firmware_len = len(firmware_bin)
+
+                    data = aes_cipher_flag + struct.pack('I', firmware_len) + firmware_bin
+
+                    sha256_hash = hashlib.sha256(data).digest()
+
+                    firmware_with_header = data + sha256_hash
+
+                    total_len = len(firmware_with_header)
+                    # Slice download firmware
+                    data_chunks = chunks(firmware_with_header, ISP_FLASH_DATA_FRAME_SIZE)  # 4kiB for a sector, 16kiB for dataframe
+                else:
+                    total_len = len(firmware_bin)
+                    data_chunks = chunks(firmware_bin, ISP_FLASH_DATA_FRAME_SIZE, address = address_offset)
+
+                time_start = time.time()
+                write_len = 0
+                for n, chunk in enumerate(data_chunks):
+                    self.checkKillExit()
+                    # 4K align
+                    aligned_chunk = len(chunk)
+                    aligned_chunk = (ISP_FLASH_SECTOR_SIZE - (aligned_chunk % ISP_FLASH_SECTOR_SIZE))%ISP_FLASH_SECTOR_SIZE + aligned_chunk
+                    chunk = chunk.ljust(aligned_chunk, b'\x00')  # align by size of dataframe
+
+                    # Download a dataframe
+                    #KFlash.log('[INFO]', 'Write firmware data piece')
+                    chunk_len = len(chunk)
+                    self.dump_to_flash(chunk, address= write_len + address_offset, size=chunk_len)
+                    write_len += chunk_len
+                    columns, lines = TerminalSize.get_terminal_size((100, 24), terminal)
+                    time_delta = time.time() - time_start
+                    speed = ''
+                    if (time_delta > 1):
+                        speed = str(int(write_len / 1024.0 / time_delta)) + 'kiB/s'
+                    printProgressBar(write_len, total_len, prefix = 'Programming BIN:', filename=filename, suffix = speed, length = columns - 35)
+
+            def kill(self):
+                self._kill_process = True
+
+            def checkKillExit(self):
+                if self._kill_process:
+                    self._port.close()
+                    self._kill_process = False
+                    raise Exception("Cancel")
+
+        def open_terminal(reset):
+            control_signal = '0' if reset else '1'
+            control_signal_b = not reset
+            import serial.tools.miniterm
+            # For using the terminal with MaixPy the 'filter' option must be set to 'direct'
+            # because some control characters are emited
+            sys.argv = [sys.argv[0], _port, '115200', '--dtr='+control_signal, '--rts='+control_signal,  '--filter=direct']
+            serial.tools.miniterm.main(default_port=_port, default_baudrate=115200, default_dtr=control_signal_b, default_rts=control_signal_b)
+            sys.exit(0)
+
+        boards_choices = ["kd233", "dan", "bit", "bit_mic", "goE", "goD", "maixduino", "trainer"]
+        if terminal:
+            parser = argparse.ArgumentParser()
+            parser.add_argument("-p", "--port", help="COM Port", default="DEFAULT")
+            parser.add_argument("-f", "--flash", help="SPI Flash type, 0 for SPI3, 1 for SPI0", default=1)
+            parser.add_argument("-b", "--baudrate", type=int, help="UART baudrate for uploading firmware", default=115200)
+            parser.add_argument("-l", "--bootloader", help="Bootloader bin path", required=False, default=None)
+            parser.add_argument("-k", "--key", help="AES key in hex, if you need encrypt your firmware.", required=False, default=None)
+            parser.add_argument("-v", "--version", help="Print version.", action='version', version='0.8.3')
+            parser.add_argument("--verbose", help="Increase output verbosity", default=False, action="store_true")
+            parser.add_argument("-t", "--terminal", help="Start a terminal after finish (Python miniterm)", default=False, action="store_true")
+            parser.add_argument("-n", "--noansi", help="Do not use ANSI colors, recommended in Windows CMD", default=False, action="store_true")
+            parser.add_argument("-s", "--sram", help="Download firmware to SRAM and boot", default=False, action="store_true")
+            parser.add_argument("-B", "--Board",required=False, type=str, help="Select dev board, e.g. kd233, dan, bit, goD, goE or trainer")
+            parser.add_argument("-S", "--Slow",required=False, help="Slow download mode", default=False)
+            parser.add_argument("-A", "--addr",required=False, help="flash addr", type=str, default="-1")
+            parser.add_argument("-L", "--length",required=False, help="flash addr", type=str, default="-1")
+            parser.add_argument("firmware", help="firmware bin path")
+            args = parser.parse_args()
+        else:
+            args = argparse.Namespace()
+            setattr(args, "port", "DEFAULT")
+            setattr(args, "flash", 1)
+            setattr(args, "baudrate", 115200)
+            setattr(args, "bootloader", None)
+            setattr(args, "key", None)
+            setattr(args, "verbose", False)
+            setattr(args, "terminal", False)
+            setattr(args, "noansi", False)
+            setattr(args, "sram", False)
+            setattr(args, "Board", None)
+            setattr(args, "Slow", False)
+            setattr(args, "addr", -1)
+            setattr(args, "length", -1)
+
+        # udpate args for none terminal call
+        if not terminal:
+            args.port = dev
+            args.baudrate = baudrate
+            args.noansi = noansi
+            args.sram = sram
+            args.Board = board
+            args.firmware = file
+            args.Slow = slow_mode
+            args.addr = addr
+            args.length = length
+
+        if args.Board == "maixduino" or args.Board == "bit_mic":
+            args.Board = "goE"
+
+        if (args.noansi == True):
+            BASH_TIPS = dict(NORMAL='',BOLD='',DIM='',UNDERLINE='',
+                                DEFAULT='', RED='', YELLOW='', GREEN='',
+                                BG_DEFAULT='', BG_WHITE='')
+            ERROR_MSG   = BASH_TIPS['RED']+BASH_TIPS['BOLD']+'[ERROR]'+BASH_TIPS['NORMAL']
+            WARN_MSG    = BASH_TIPS['YELLOW']+BASH_TIPS['BOLD']+'[WARN]'+BASH_TIPS['NORMAL']
+            INFO_MSG    = BASH_TIPS['GREEN']+BASH_TIPS['BOLD']+'[INFO]'+BASH_TIPS['NORMAL']
+            KFlash.log(INFO_MSG,'ANSI colors not used',BASH_TIPS['DEFAULT'])
+
+        manually_set_the_board = False
+        if args.Board:
+            manually_set_the_board = True
+
+        if args.port == "DEFAULT":
+            if args.Board == "goE":
+                list_port_info = list(serial.tools.list_ports.grep("0403")) #Take the second one
+                if len(list_port_info) == 0:
+                    err = (ERROR_MSG,"No vaild COM Port found in Auto Detect, Check Your Connection or Specify One by"+BASH_TIPS['GREEN']+'`--port/-p`',BASH_TIPS['DEFAULT'])
+                    err = tuple2str(err)
+                    raise_exception( Exception(err) )
+                list_port_info.sort()
+                if len(list_port_info) == 1:
+                    _port = list_port_info[0].device
+                elif len(list_port_info) > 1:
+                    _port = list_port_info[1].device
+                KFlash.log(INFO_MSG,"COM Port Auto Detected, Selected ", _port, BASH_TIPS['DEFAULT'])
+            elif args.Board == "trainer":
+                list_port_info = list(serial.tools.list_ports.grep("0403")) #Take the first one
+                if(len(list_port_info)==0):
+                    err = (ERROR_MSG,"No vaild COM Port found in Auto Detect, Check Your Connection or Specify One by"+BASH_TIPS['GREEN']+'`--port/-p`',BASH_TIPS['DEFAULT'])
+                    err = tuple2str(err)
+                    raise_exception( Exception(err) )
+                list_port_info.sort()
+                _port = list_port_info[0].device
+                KFlash.log(INFO_MSG,"COM Port Auto Detected, Selected ", _port, BASH_TIPS['DEFAULT'])
+            else:
+                try:
+                    list_port_info = next(serial.tools.list_ports.grep(VID_LIST_FOR_AUTO_LOOKUP)) #Take the first one within the list
+                    _port = list_port_info.device
+                    KFlash.log(INFO_MSG,"COM Port Auto Detected, Selected ", _port, BASH_TIPS['DEFAULT'])
+                except StopIteration:
+                    err = (ERROR_MSG,"No vaild COM Port found in Auto Detect, Check Your Connection or Specify One by"+BASH_TIPS['GREEN']+'`--port/-p`',BASH_TIPS['DEFAULT'])
+                    err = tuple2str(err)
+                    raise_exception( Exception(err) )
+        else:
+            _port = args.port
+            KFlash.log(INFO_MSG,"COM Port Selected Manually: ", _port, BASH_TIPS['DEFAULT'])
+
+        self.loader = MAIXLoader(port=_port, baudrate=115200)
+        file_format = ProgramFileFormat.FMT_BINARY
+
+        # 0. Check firmware or cmd
+        cmds = ['erase']
+        if not args.firmware in cmds:
+            if not os.path.exists(args.firmware):
+                err = (ERROR_MSG,'Unable to find the firmware at ', args.firmware, BASH_TIPS['DEFAULT'])
+                err = tuple2str(err)
+                raise_exception( Exception(err) )
+
+            with open(args.firmware, 'rb') as f:
+                file_header = f.read(4)
+                #if file_header.startswith(bytes([0x50, 0x4B])):
+                if file_header.startswith(b'\x50\x4B'):
+                    if ".kfpkg" != os.path.splitext(args.firmware)[1]:
+                        KFlash.log(INFO_MSG, 'Find a zip file, but not with ext .kfpkg:', args.firmware, BASH_TIPS['DEFAULT'])
+                    else:
+                        file_format = ProgramFileFormat.FMT_KFPKG
+
+                #if file_header.startswith(bytes([0x7F, 0x45, 0x4C, 0x46])):
+                if file_header.startswith(b'\x7f\x45\x4c\x46'):
+                    file_format = ProgramFileFormat.FMT_ELF
+                    if args.sram:
+                        KFlash.log(INFO_MSG, 'Find an ELF file:', args.firmware, BASH_TIPS['DEFAULT'])
+                    else:
+                        err = (ERROR_MSG, 'This is an ELF file and cannot be programmed to flash directly:', args.firmware, BASH_TIPS['DEFAULT'] , '\r\nPlease retry:', args.firmware + '.bin', BASH_TIPS['DEFAULT'])
+                        err = tuple2str(err)
+                        raise_exception( Exception(err) )
+
+        # 1. Greeting.
+        KFlash.log(INFO_MSG,"Trying to Enter the ISP Mode...",BASH_TIPS['DEFAULT'])
+
+        retry_count = 0
+
+        while 1:
+            self.checkKillExit()
+            if not self.loader._port.isOpen():
+                self.loader._port.open()
+            try:
+                retry_count = retry_count + 1
+                if retry_count > 15:
+                    err = (ERROR_MSG,"No vaild Kendryte K210 found in Auto Detect, Check Your Connection or Specify One by"+BASH_TIPS['GREEN']+'`-p '+('/dev/ttyUSB0', 'COM3')[sys.platform == 'win32']+'`',BASH_TIPS['DEFAULT'])
+                    err = tuple2str(err)
+                    raise_exception( Exception(err) )
+                if args.Board == "dan" or args.Board == "bit" or args.Board == "trainer":
+                    try:
+                        KFlash.log('.', end='')
+                        self.loader.reset_to_isp_dan()
+                        self.loader.greeting()
+                        break
+                    except TimeoutError:
+                        pass
+                elif args.Board == "kd233":
+                    try:
+                        KFlash.log('_', end='')
+                        self.loader.reset_to_isp_kd233()
+                        self.loader.greeting()
+                        break
+                    except TimeoutError:
+                        pass
+                elif args.Board == "goE":
+                    try:
+                        KFlash.log('*', end='')
+                        self.loader.reset_to_isp_kd233()
+                        self.loader.greeting()
+                        break
+                    except TimeoutError:
+                        pass
+                elif args.Board == "goD":
+                    try:
+                        KFlash.log('#', end='')
+                        self.loader.reset_to_isp_goD()
+                        self.loader.greeting()
+                        break
+                    except TimeoutError:
+                        pass
+                else:
+                    try:
+                        KFlash.log('.', end='')
+                        self.loader.reset_to_isp_dan()
+                        self.loader.greeting()
+                        args.Board = "dan"
+                        KFlash.log()
+                        KFlash.log(INFO_MSG,"Automatically detected dan/bit/trainer",BASH_TIPS['DEFAULT'])
+                        break
+                    except TimeoutError:
+                        if not self.loader._port.isOpen():
+                            self.loader._port.open()
+                        pass
+                    try:
+                        KFlash.log('_', end='')
+                        self.loader.reset_to_isp_kd233()
+                        self.loader.greeting()
+                        args.Board = "kd233"
+                        KFlash.log()
+                        KFlash.log(INFO_MSG,"Automatically detected goE/kd233",BASH_TIPS['DEFAULT'])
+                        break
+                    except TimeoutError:
+                        if not self.loader._port.isOpen():
+                            self.loader._port.open()
+                        pass
+                    try:
+                        KFlash.log('.', end='')
+                        self.loader.reset_to_isp_goD()
+                        self.loader.greeting()
+                        args.Board = "goD"
+                        KFlash.log()
+                        KFlash.log(INFO_MSG,"Automatically detected goD",BASH_TIPS['DEFAULT'])
+                        break
+                    except TimeoutError:
+                        if not self.loader._port.isOpen():
+                            self.loader._port.open()
+                        pass
+                    try:
+                        # Magic, just repeat, don't remove, it may unstable, don't know why.
+                        KFlash.log('_', end='')
+                        self.loader.reset_to_isp_kd233()
+                        self.loader.greeting()
+                        args.Board = "kd233"
+                        KFlash.log()
+                        KFlash.log(INFO_MSG,"Automatically detected goE/kd233",BASH_TIPS['DEFAULT'])
+                        break
+                    except TimeoutError:
+                        if not self.loader._port.isOpen():
+                            self.loader._port.open()
+                        pass
+            except Exception as e:
+                KFlash.log()
+                raise_exception( Exception("Greeting fail, check serial port ("+str(e)+")" ) )
+
+        # Don't remove this line
+        # Dangerous, here are dinosaur infested!!!!!
+        ISP_RECEIVE_TIMEOUT = 3
+
+        KFlash.log()
+        KFlash.log(INFO_MSG,"Greeting Message Detected, Start Downloading ISP",BASH_TIPS['DEFAULT'])
+
+        if manually_set_the_board and (not args.Slow):
+            if (args.baudrate >= 1500000) or args.sram:
+                self.loader.change_baudrate_stage0(args.baudrate)
+
+        # 2. download bootloader and firmware
+        if args.sram:
+            with open(args.firmware, 'rb') as firmware_bin:
+                if file_format == ProgramFileFormat.FMT_KFPKG:
+                    err = (ERROR_MSG, "Unable to load kfpkg to SRAM")
+                    err = tuple2str(err)
+                    raise_exception( Exception(err) )
+                elif file_format == ProgramFileFormat.FMT_ELF:
+                    self.loader.load_elf_to_sram(firmware_bin)
+                else:
+                    self.loader.install_flash_bootloader(firmware_bin.read())
+        else:
+            # install bootloader at 0x80000000
+            if args.bootloader:
+                with open(args.bootloader, 'rb') as f:
+                    isp_loader = f.read()
+            else:
+                isp_loader = ISP_PROG
+            self.loader.install_flash_bootloader(isp_loader)
+
+        # Boot the code from SRAM
+        self.loader.boot()
+
+        if args.sram:
+            # Dangerous, here are dinosaur infested!!!!!
+            # Don't touch this code unless you know what you are doing
+            self.loader._port.baudrate = args.baudrate
+            KFlash.log(INFO_MSG,"Boot user code from SRAM", BASH_TIPS['DEFAULT'])
+            if(args.terminal == True):
+                open_terminal(False)
+            msg = "Burn SRAM OK"
+            raise_exception( Exception(msg) )
+
+        # Dangerous, here are dinosaur infested!!!!!
+        # Don't touch this code unless you know what you are doing
+        self.loader._port.baudrate = 115200
+
+        KFlash.log(INFO_MSG,"Wait For 0.1 second for ISP to Boot", BASH_TIPS['DEFAULT'])
+
+        time.sleep(0.1)
+
+        self.loader.flash_greeting()
+
+        if args.baudrate != 115200:
+            self.loader.change_baudrate(args.baudrate)
+            KFlash.log(INFO_MSG,"Baudrate changed, greeting with ISP again ... ", BASH_TIPS['DEFAULT'])
+            self.loader.flash_greeting()
+
+        self.loader.init_flash(args.flash)
+
+        if file_format == ProgramFileFormat.FMT_KFPKG:
+            KFlash.log(INFO_MSG,"Extracting KFPKG ... ", BASH_TIPS['DEFAULT'])
+            with tempfile.TemporaryDirectory() as tmpdir:
+                try:
+                    with zipfile.ZipFile(args.firmware) as zf:
+                        zf.extractall(tmpdir)
+                except zipfile.BadZipFile:
+                    err = (ERROR_MSG,'Unable to Decompress the kfpkg, your file might be corrupted.',BASH_TIPS['DEFAULT'])
+                    err = tuple2str(err)
+                    raise_exception( Exception(err) )
+
+                fFlashList = open(os.path.join(tmpdir, 'flash-list.json'), "r")
+                sFlashList = re.sub(r'"address": (.*),', r'"address": "\1",', fFlashList.read()) #Pack the Hex Number in json into str
+                fFlashList.close()
+                jsonFlashList = json.loads(sFlashList)
+                for lBinFiles in jsonFlashList['files']:
+                    self.checkKillExit()
+                    KFlash.log(INFO_MSG,"Writing",lBinFiles['bin'],"into","0x%08x"%int(lBinFiles['address'], 0),BASH_TIPS['DEFAULT'])
+                    with open(os.path.join(tmpdir, lBinFiles["bin"]), "rb") as firmware_bin:
+                        self.loader.flash_firmware(firmware_bin.read(), None, int(lBinFiles['address'], 0), lBinFiles['sha256Prefix'], filename=lBinFiles['bin'])
+        else:
+            if args.firmware == "erase":
+                if args.addr.lower().startswith("0x"):
+                    addr = int(args.addr, base=16)
+                else:
+                    addr = int(args.addr)
+                if args.length.lower() == "all":
+                    addr = 0
+                    length = 0xFFFFFFEE
+                    KFlash.log(INFO_MSG,"erase all")
+                else:
+                    if args.length.lower().startswith("0x"):
+                        length = int(args.length, base=16)
+                    else:
+                        length = int(args.length)
+                    KFlash.log(INFO_MSG,"erase '0x{:x}' - '0x{:x}' ({}B, {:.02}KiB, {:.02}MiB)".format(addr, addr+length, length, length/1024.0, length/1024.0/1024.0))
+                if ((addr % 4096) != 0) or ( length != 0xFFFFFFEE and (length % 4096) != 0) or addr < 0 or addr > 0x01000000 or length < 0 or ( length > 0x01000000 and length != 0xFFFFFFEE):
+                    err = (ERROR_MSG,"erase flash addr or length error, addr should >= 0x00000000, and length should >= 4096 or 'all'")
+                    err = tuple2str(err)
+                    raise_exception( Exception(err) )
+                self.loader.flash_erase(addr, length)
+            else:
+                with open(args.firmware, 'rb') as firmware_bin:
+                    if args.key:
+                        aes_key = binascii.a2b_hex(args.key)
+                        if len(aes_key) != 16:
+                            raise_exception( ValueError('AES key must by 16 bytes') )
+
+                        self.loader.flash_firmware(firmware_bin.read(), aes_key=aes_key)
+                    else:
+                        self.loader.flash_firmware(firmware_bin.read())
+
+        # 3. boot
+        if args.Board == "dan" or args.Board == "bit" or args.Board == "trainer":
+            self.loader.reset_to_boot_dan()
+        elif args.Board == "kd233":
+            self.loader.reset_to_boot_kd233()
+        elif args.Board == "goE":
+            self.loader.reset_to_boot_maixgo()
+        elif args.Board == "goD":
+            self.loader.reset_to_boot_goD()
+        else:
+            KFlash.log(WARN_MSG,"Board unknown !! please press reset to boot!!")
+
+        KFlash.log(INFO_MSG,"Rebooting...", BASH_TIPS['DEFAULT'])
+        try:
+            self.loader._port.close()
+        except Exception:
+            pass
+
+        if(args.terminal == True):
+            open_terminal(True)
+
+    def kill(self):
+        if self.loader:
+            self.loader.kill()
+        self.killProcess = True
+
+    def checkKillExit(self):
+        if self.killProcess:
+            if self.loader:
+                self.loader._port.close()
+            raise Exception("Cancel")
+
+
+def main():
+    kflash = KFlash()
+    try:
+        kflash.process()
+    except Exception as e:
+        if str(e) == "Burn SRAM OK":
+            sys.exit(0)
+        kflash.log(str(e))
+        sys.exit(1)
+
+if __name__ == '__main__':
+    main()
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/.vscode/c_cpp_properties.json
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/.vscode/c_cpp_properties.json	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/.vscode/c_cpp_properties.json	(revision 453)
@@ -0,0 +1,21 @@
+{
+    "configurations": [
+        {
+            "name": "Sipeed Maix bit",
+            "includePath": [
+                "${workspaceFolder}/../zlib-1.2.11/src",
+                "${workspaceFolder}/../wolfssl-4.4.0"
+            ],
+            "defines": [
+                "HAVE_CONFIG_H",
+                "WOLFSSL_USER_SETTINGS"
+            ],
+            "windowsSdkVersion": "10.0.17763.0",
+            "compilerPath": "C:\\xpack-riscv-none-embed-gcc-8.3.0-1.2\\bin\\riscv-none-embed-gcc.exe",
+            "cStandard": "c11",
+            "cppStandard": "c++17",
+            "intelliSenseMode": "gcc-x64"
+        }
+    ],
+    "version": 4
+}
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/.vscode/settings.json
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/.vscode/settings.json	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/.vscode/settings.json	(revision 453)
@@ -0,0 +1,17 @@
+// Place your settings in this file to overwrite default and user settings.
+{
+    "terminal.integrated.setLocaleVariables": true,
+    "terminal.integrated.shell.windows": "C:\\msys64\\usr\\bin\\bash.exe",
+    "terminal.integrated.shellArgs.windows": [
+        "--login",
+        "-i"
+    ],
+    "terminal.integrated.env.windows": {
+        "PATH": "C:\\xpack-riscv-none-embed-gcc-8.3.0-1.2\\bin",
+        "CHERE_INVOKING": "1",
+        "MSYS2_PATH_TYPE": "inherit",
+        "MSYSTEM": "MINGW64"
+    },
+    "C_Cpp.intelliSenseEngine": "Tag Parser",
+    "C_Cpp.default.intelliSenseMode": "gcc-x64"
+}
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/.vscode/tasks.json
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/.vscode/tasks.json	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/.vscode/tasks.json	(revision 453)
@@ -0,0 +1,57 @@
+{
+    // See https://go.microsoft.com/fwlink/?LinkId=733558
+    // for the documentation about the tasks.json format
+    "version": "2.0.0",
+    "name": "make",
+    "type": "shell",
+    "problemMatcher": {
+        "owner": "cpp",
+        "fileLocation": [
+            "relative",
+            "${workspaceFolder}/Debug"
+        ],
+        "pattern": {
+            "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error|fatal error):\\s+(.*)$",
+            "file": 1,
+            "line": 2,
+            "column": 3,
+            "severity": 4,
+            "message": 5
+        }
+    },
+    "tasks": [
+        {
+            "label": "build wolfssl",
+            "args": [
+                "-j",
+                "all"
+            ],
+            "linux": {
+                "command": "make"
+            },
+            "osx": {
+                "command": "make"
+            },
+            "windows": {
+                "command": "make.exe"
+            },
+            "group": "build"
+        },
+        {
+            "label": "clean wolfssl",
+            "args": [
+                "clean"
+            ],
+            "linux": {
+                "command": "make"
+            },
+            "osx": {
+                "command": "make"
+            },
+            "windows": {
+                "command": "make.exe"
+            },
+            "group": "build"
+        }
+    ]
+}
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/COPYING
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/COPYING	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/COPYING	(revision 453)
@@ -0,0 +1,339 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/LICENSING
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/LICENSING	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/LICENSING	(revision 453)
@@ -0,0 +1,11 @@
+
+wolfSSL (formerly known as CyaSSL) and wolfCrypt are either licensed for use
+under the GPLv2 or a standard commercial license. For our users who cannot use
+wolfSSL under GPLv2, a commercial license to wolfSSL and wolfCrypt is available.
+Please contact wolfSSL Inc. directly at:
+
+Email: licensing@wolfssl.com
+Phone: +1 425 245-8247
+
+More information can be found on the wolfSSL website at www.wolfssl.com.
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/Makefile
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/Makefile	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/Makefile	(revision 453)
@@ -0,0 +1,221 @@
+# This file was automagically generated by mbed.org. For more information, 
+# see http://mbed.org/handbook/Exporting-to-GCC-ARM-Embedded
+
+###############################################################################
+# Boiler-plate
+
+# cross-platform directory manipulation
+ifeq ($(shell echo $$OS),$$OS)
+    MAKEDIR = if not exist "$(1)" mkdir "$(1)"
+    RM = rmdir /S /Q "$(1)"
+else
+    MAKEDIR = '$(SHELL)' -c "mkdir -p \"$(1)\""
+    RM = '$(SHELL)' -c "rm -rf \"$(1)\""
+endif
+
+OBJDIR := Debug
+# Move to the build directory
+ifeq (,$(filter $(OBJDIR),$(notdir $(CURDIR))))
+.SUFFIXES:
+mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
+MAKETARGET = '$(MAKE)' --no-print-directory -C $(OBJDIR) -f '$(mkfile_path)' \
+		'SRCDIR=$(CURDIR)' $(MAKECMDGOALS)
+.PHONY: $(OBJDIR) clean
+all:
+	+@$(call MAKEDIR,$(OBJDIR))
+	+@$(MAKETARGET)
+$(OBJDIR): all
+Makefile : ;
+% :: $(OBJDIR) ; :
+clean :
+	$(call RM,$(OBJDIR))
+
+else
+
+# trick rules into thinking we are in the root, when we are in the bulid dir
+VPATH = ../../wolfssl-4.4.0
+
+# Boiler-plate
+###############################################################################
+# Project settings
+
+PROJECT := wolfssl
+
+
+# Project settings
+###############################################################################
+# Objects and Paths
+
+OBJECTS += src/crl.o
+OBJECTS += src/internal.o
+OBJECTS += src/keys.o
+OBJECTS += src/ocsp.o
+OBJECTS += src/sniffer.o
+OBJECTS += src/ssl.o
+OBJECTS += src/tls.o
+OBJECTS += src/tls13.o
+OBJECTS += src/wolfio.o
+OBJECTS += wolfcrypt/src/aes.o
+OBJECTS += wolfcrypt/src/arc4.o
+OBJECTS += wolfcrypt/src/asn.o
+OBJECTS += wolfcrypt/src/blake2b.o
+OBJECTS += wolfcrypt/src/camellia.o
+OBJECTS += wolfcrypt/src/coding.o
+OBJECTS += wolfcrypt/src/des3.o
+OBJECTS += wolfcrypt/src/dh.o
+OBJECTS += wolfcrypt/src/dsa.o
+OBJECTS += wolfcrypt/src/ecc.o
+OBJECTS += wolfcrypt/src/error.o
+OBJECTS += wolfcrypt/src/hash.o
+OBJECTS += wolfcrypt/src/hc128.o
+OBJECTS += wolfcrypt/src/hmac.o
+OBJECTS += wolfcrypt/src/integer.o
+OBJECTS += wolfcrypt/src/logging.o
+OBJECTS += wolfcrypt/src/md4.o
+OBJECTS += wolfcrypt/src/md5.o
+OBJECTS += wolfcrypt/src/memory.o
+OBJECTS += wolfcrypt/src/misc.o
+OBJECTS += wolfcrypt/src/pwdbased.o
+OBJECTS += wolfcrypt/src/rabbit.o
+OBJECTS += wolfcrypt/src/random.o
+OBJECTS += wolfcrypt/src/ripemd.o
+OBJECTS += wolfcrypt/src/rsa.o
+OBJECTS += wolfcrypt/src/sha.o
+OBJECTS += wolfcrypt/src/sha256.o
+OBJECTS += wolfcrypt/src/sha512.o
+OBJECTS += wolfcrypt/src/wc_encrypt.o
+OBJECTS += wolfcrypt/src/wc_port.o
+OBJECTS += wolfcrypt/src/wolfmath.o
+
+INCLUDE_PATHS += -I../../asp_baseplatform
+INCLUDE_PATHS += -I../../asp_baseplatform/include
+INCLUDE_PATHS += -I../../asp_baseplatform/arch
+INCLUDE_PATHS += -I../../asp_baseplatform/arch/riscv_gcc
+INCLUDE_PATHS += -I../../asp_baseplatform/target/k210_gcc
+INCLUDE_PATHS += -I../../asp_baseplatform/OBJ/K210_GCC/DEMO
+INCLUDE_PATHS += -I../../asp_baseplatform/monitor
+INCLUDE_PATHS += -I../../asp_baseplatform/files
+INCLUDE_PATHS += -I../../zlib-1.2.11/src
+INCLUDE_PATHS += -I../../wolfssl-4.4.0
+INCLUDE_PATHS += -I../../wolfssl-4.4.0/src
+
+# Objects and Paths
+###############################################################################
+# Tools and Flags
+
+AS      = riscv-none-embed-gcc
+CC      = riscv-none-embed-gcc
+CPP     = riscv-none-embed-g++
+AR      = riscv-none-embed-ar
+RANLIB  = riscv-none-embed-ranlib
+
+
+C_FLAGS += -std=gnu11
+C_FLAGS += -march=rv64imafdc
+C_FLAGS += -mabi=lp64d
+C_FLAGS += -mcmodel=medany
+C_FLAGS += -O2
+C_FLAGS += -fmessage-length=0
+C_FLAGS += -fsigned-char
+C_FLAGS += -ffunction-sections
+C_FLAGS += -fdata-sections
+C_FLAGS += -Wall
+C_FLAGS += -Wextra
+C_FLAGS += -Wno-unused-parameter
+C_FLAGS += -Wno-missing-field-initializers
+C_FLAGS += -Wnull-dereference
+
+C_FLAGS += -g3
+C_FLAGS += -Wstack-usage=256
+
+C_FLAGS += -DHAVE_CONFIG_H
+C_FLAGS += -DWOLFSSL_USER_SETTINGS
+C_FLAGS += -DCYASSL_USER_SETTINGS
+
+CXX_FLAGS += -std=gnu++11
+CXX_FLAGS += -march=rv64imafdc
+CXX_FLAGS += -mabi=lp64d
+CXX_FLAGS += -mcmodel=medany
+CXX_FLAGS += -O2
+CXX_FLAGS += -fmessage-length=0
+CXX_FLAGS += -fsigned-char
+CXX_FLAGS += -ffunction-sections
+CXX_FLAGS += -fdata-sections
+CXX_FLAGS += -Wall
+CXX_FLAGS += -Wextra
+CXX_FLAGS += -Wno-unused-parameter
+CXX_FLAGS += -Wno-missing-field-initializers
+CXX_FLAGS += -Wnull-dereference
+
+CXX_FLAGS += -g3
+CXX_FLAGS += -Wstack-usage=256
+
+CXX_FLAGS += -DHAVE_CONFIG_H
+CXX_FLAGS += -DWOLFSSL_USER_SETTINGS
+CXX_FLAGS += -DCYASSL_USER_SETTINGS
+
+ASM_FLAGS += -x
+ASM_FLAGS += assembler-with-cpp
+ASM_FLAGS += -march=rv64imafdc
+ASM_FLAGS += -mabi=lp64d
+ASM_FLAGS += -mcmodel=medany
+ASM_FLAGS += -O2
+ASM_FLAGS += -fmessage-length=0
+ASM_FLAGS += -fsigned-char
+ASM_FLAGS += -ffunction-sections
+ASM_FLAGS += -fdata-sections
+ASM_FLAGS += -Wall
+ASM_FLAGS += -Wextra
+ASM_FLAGS += -Wno-unused-parameter
+ASM_FLAGS += -Wno-missing-field-initializers
+ASM_FLAGS += -Wnull-dereference
+ASM_FLAGS += -g3
+ASM_FLAGS += -Wstack-usage=256
+
+
+# Tools and Flags
+###############################################################################
+# Rules
+
+.PHONY: all lst size
+
+
+all: lib$(PROJECT).a
+
+
+.s.o:
+	+@$(call MAKEDIR,$(dir $@))
+	+@echo "Assemble: $(notdir $<)"
+	@$(AS) -c $(ASM_FLAGS) -o $@ $<
+
+.S.o:
+	+@$(call MAKEDIR,$(dir $@))
+	+@echo "Assemble: $(notdir $<)"
+	@$(AS) -c $(ASM_FLAGS) -o $@ $<
+
+.c.o:
+	+@$(call MAKEDIR,$(dir $@))
+	+@echo "Compile: $(notdir $<)"
+	@$(CC) $(C_FLAGS) $(INCLUDE_PATHS) -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -c -o "$@" "$<"
+
+.cpp.o:
+	+@$(call MAKEDIR,$(dir $@))
+	+@echo "Compile: $(notdir $<)"
+	@$(CPP) $(CXX_FLAGS) $(INCLUDE_PATHS) -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -c -o "$@" "$<"
+
+lib$(PROJECT).a: $(OBJECTS)
+	rm -f lib$(PROJECT).a
+	$(AR) -rcs lib$(PROJECT).a $(OBJECTS)
+	$(RANLIB) lib$(PROJECT).a
+
+
+# Rules
+###############################################################################
+# Dependencies
+
+DEPS = $(OBJECTS:.o=.d) $(SYS_OBJECTS:.o=.d)
+-include $(DEPS)
+endif
+
+# Dependencies
+###############################################################################
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/README
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/README	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/README	(revision 453)
@@ -0,0 +1,222 @@
+*** Description ***
+
+The wolfSSL embedded SSL library (formerly CyaSSL) is a lightweight SSL/TLS
+library written in ANSI C and targeted for embedded, RTOS, and
+resource-constrained environments - primarily because of its small size, speed,
+and feature set.  It is commonly used in standard operating environments as well
+because of its royalty-free pricing and excellent cross platform support.
+wolfSSL supports industry standards up to the current TLS 1.3 and DTLS 1.2
+levels, is up to 20 times smaller than OpenSSL, and offers progressive ciphers
+such as ChaCha20, Curve25519, NTRU, and Blake2b. User benchmarking and feedback
+reports dramatically better performance when using wolfSSL over OpenSSL.
+
+wolfSSL is powered by the wolfCrypt library. Two versions of the wolfCrypt
+cryptography library have been FIPS 140-2 validated (Certificate #2425 and
+certificate #3389). For additional information, visit the wolfCrypt FIPS FAQ
+(https://www.wolfssl.com/license/fips/) or contact fips@wolfssl.com
+
+*** Why choose wolfSSL? ***
+
+There are many reasons to choose wolfSSL as your embedded SSL solution. Some of
+the top reasons include size (typical footprint sizes range from 20-100 kB),
+support for the newest standards (SSL 3.0, TLS 1.0, TLS 1.1, TLS 1.2, TLS 1.3,
+DTLS 1.0, and DTLS 1.2), current and progressive cipher support (including
+stream ciphers), multi-platform, royalty free, and an OpenSSL compatibility API
+to ease porting into existing applications which have previously used the
+OpenSSL package. For a complete feature list, see chapter 4 of the wolfSSL
+manual. (https://www.wolfssl.com/docs/wolfssl-manual/ch4/)
+
+*** Notes, Please read ***
+
+Note 1)
+wolfSSL as of 3.6.6 no longer enables SSLv3 by default.  wolfSSL also no longer
+supports static key cipher suites with PSK, RSA, or ECDH. This means if you
+plan to use TLS cipher suites you must enable DH (DH is on by default), or
+enable ECC (ECC is on by default), or you must enable static key cipher suites
+with
+
+    WOLFSSL_STATIC_DH
+    WOLFSSL_STATIC_RSA
+      or
+    WOLFSSL_STATIC_PSK
+
+though static key cipher suites are deprecated and will be removed from future
+versions of TLS.  They also lower your security by removing PFS.  Since current
+NTRU suites available do not use ephemeral keys, WOLFSSL_STATIC_RSA needs to be
+used in order to build with NTRU suites.
+
+When compiling ssl.c, wolfSSL will now issue a compiler error if no cipher
+suites are available. You can remove this error by defining
+WOLFSSL_ALLOW_NO_SUITES in the event that you desire that, i.e., you're not
+using TLS cipher suites.
+
+Note 2)
+wolfSSL takes a different approach to certificate verification than OpenSSL
+does. The default policy for the client is to verify the server, this means
+that if you don't load CAs to verify the server you'll get a connect error,
+no signer error to confirm failure (-188).
+
+If you want to mimic OpenSSL behavior of having SSL_connect succeed even if
+verifying the server fails and reducing security you can do this by calling:
+
+    wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
+
+before calling wolfSSL_new();. Though it's not recommended.
+
+Note 3)
+The enum values SHA, SHA256, SHA384, SHA512 are no longer available when
+wolfSSL is built with --enable-opensslextra (OPENSSL_EXTRA) or with the macro
+NO_OLD_SHA_NAMES. These names get mapped to the OpenSSL API for a single call
+hash function. Instead the name WC_SHA, WC_SHA256, WC_SHA384 and WC_SHA512
+should be used for the enum name.
+
+*** end Notes ***
+
+
+# wolfSSL Release 4.4.0 (04/22/2020)
+
+If you have questions about this release, feel free to contact us on our
+info@ address.
+
+Release 4.4.0 of wolfSSL embedded TLS has bug fixes and new features including:
+
+## New Feature Additions
+
+* Hexagon support.
+* DSP builds to offload ECC verify operations.
+* Certificate Manager callback support.
+* New APIs for running updates to ChaCha20/Poly1305 AEAD.
+* Support for use with Apache.
+* Add support for IBM s390x.
+* PKCS8 support for ED25519.
+* OpenVPN support.
+* Add P384 curve support to SP.
+* Add BIO and EVP API.
+* Add AES-OFB mode.
+* Add AES-CFB mode.
+* Add Curve448, X448, and Ed448.
+* Add Renesas Synergy S7G2 build and hardware acceleration.
+
+## Fixes
+
+* Fix for RSA public encrypt / private sign with RSA key sizes over 2048-bit.
+* Correct misspellings.
+* Secure renegotiation fix.
+* Fix memory leak when using ATECC and non-SECP256R1 curves for sign, verify,
+  or shared secret.
+* Fix for K64 MMCAU with `WOLFSSL_SMALL_STACK_CACHE`.
+* Fix the RSA verify only build.
+* Fix in SP C implementation for small stack.
+* Fix using the auth key id extension is set, hash might not be present.
+* Fix when flattening certificate structure to include the subject alt names.
+* Fixes for building with ECC sign/verify only.
+* Fix for ECC and no cache resistance.
+* Fix memory leak in DSA.
+* Fix build on minGW.
+* Fix `PemToDer()` call in `ProcessBuffer()` to set more than ECC.
+* Fix for using RSA without SHA-512.
+* Add some close tags to the echoserver HTTP example output.
+* Miscellaneous fixes and updates for static analysis reports.
+* Fixes for time structure support.
+* Fixes for VxWorks support.
+* Fixes for Async crypto support.
+* Fix cache resist compile to work with SP C code.
+* Fixes for Curve25519 x64 asm.
+* Fix for SP x64 div.
+* Fix for DTLS edge case where CCS and Finished come out of order and the
+  retransmit pool gets flushed.
+* Fix for infinite loop in SHA-1 with small inputs. Thanks to Peter W.
+* Fix for FIPS Hmac where `wc_HmacInit()` isn't used. `wc_HmacSetKey()` needs
+  to initialize the Hmac structure. Type is set to NONE, and checked against
+  NONE, not 0.
+* Fixes for SP RSA private operations.
+* Fixes for Xilinx SDK and Zynq UltraScale+ MPSoC
+* Fix leak when building with HAVE_AESGCM and NO_AES_DECRYPT. Thanks G.G.
+* Fixes for building ECC without ASN.
+* Fix for async TLSv1.3 issues.
+* Fix `wc_KeyPemToDer()` with PKCS1 and empty key.
+* Omit `-fomit-frame-pointer` from CFLAGS in configure.ac.
+
+## Improvements/Optimizations
+
+* Qt 5.12 and 5.13 support.
+* Added more digest types to Cryptocell RSA sign/verify.
+* Some memory usage improvements.
+* Speed improvements for mp_rand.
+* Improvements to CRL and OCSP support.
+* Refactor Poly1305 AEAD/MAC to reduce duplicate code.
+* Add blinding to RSA key gen.
+* Improvements to blinding.
+* Improvement and expansion of OpenSSL Compatibility Layer.
+* Improvements to ChaCha20.
+* Improvements to X.509 processing.
+* Improvements to ECC support.
+* Improvement in detecting 64-bit support.
+* Refactor to combine duplicate ECC parameter parsing code.
+* Improve keyFormat to be set by algId and let later key parsing produce fail.
+* Add test cases for 3072-bit and 4096-bit RSA keys.
+* Improve signature wrapper and DH test cases.
+* Improvements to the configure.ac script.
+* Added constant time RSA q modinv p.
+* Improve performance of SP Intel 64-bit asm.
+* Added a few more functions to the ABI list.
+* Improve TLS bidirectional shutdown behavior.
+* OpenSSH 8.1 support.
+* Improve performance of RSA/DH operations on x64.
+* Add support for PKCS7/CMS Enveloped data with fragmented encrypted content.
+* Example linker description for FIPS builds to enforce object ordering.
+* C# wrapper improvements. Added TLS client example and TLSv1.3 methods.
+* Allow setting MTU in DTLS.
+* Improve PKCS12 create for outputting encrypted bundles.
+* Constant time EC map to affine for private operations.
+* Improve performance of RSA public key ops with TFM.
+* Smaller table version of AES encrypt/decrypt.
+* Support IAR with position independent code (ROPI).
+* Improve speed of AArch64 assembly.
+* Support AES-CTR with AES-NI.
+* Support AES-CTR on esp32.
+* Add a no malloc option for small SP math.
+
+## This release of wolfSSL includes fixes for 2 security vulnerabilities.
+
+* For fast math, use a constant time modular inverse when mapping to affine
+  when operation involves a private key - keygen, calc shared secret, sign.
+  Thank you to Alejandro Cabrera Aldaya, Cesar Pereida Garc鱈a and
+  Billy Bob Brumley from the Network and Information Security Group (NISEC)
+  at Tampere University for the report.
+
+* Change constant time and cache resistant ECC mulmod. Ensure points being
+  operated on change to make constant time. Thank you to Pietro Borrello at
+  Sapienza University of Rome.
+
+For additional vulnerability information visit the vulnerability page at
+https://www.wolfssl.com/docs/security-vulnerabilities/
+
+See INSTALL file for build instructions.
+More info can be found on-line at https://wolfssl.com/wolfSSL/Docs.html
+
+
+
+*** Resources ***
+
+
+[wolfSSL Website](https://www.wolfssl.com/)
+
+[wolfSSL Wiki](https://github.com/wolfSSL/wolfssl/wiki)
+
+[FIPS FAQ](https://wolfssl.com/license/fips)
+
+[wolfSSL Documents](https://wolfssl.com/wolfSSL/Docs.html)
+
+[wolfSSL Manual](https://wolfssl.com/wolfSSL/Docs-wolfssl-manual-toc.html)
+
+[wolfSSL API Reference]
+(https://wolfssl.com/wolfSSL/Docs-wolfssl-manual-17-wolfssl-api-reference.html)
+
+[wolfCrypt API Reference]
+(https://wolfssl.com/wolfSSL/Docs-wolfssl-manual-18-wolfcrypt-api-reference.html)
+
+[TLS 1.3](https://www.wolfssl.com/docs/tls13/)
+
+[wolfSSL Vulnerabilities]
+(https://www.wolfssl.com/docs/security-vulnerabilities/)
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/ctaocrypt/random.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/ctaocrypt/random.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/ctaocrypt/random.h	(revision 453)
@@ -0,0 +1,39 @@
+/* random.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+#ifndef CTAO_CRYPT_RANDOM_H
+#define CTAO_CRYPT_RANDOM_H
+
+    /* for random.h compatibility */
+    #include <wolfssl/wolfcrypt/random.h>
+    #define InitRng           wc_InitRng
+    #define RNG_GenerateBlock wc_RNG_GenerateBlock
+    #define RNG_GenerateByte  wc_RNG_GenerateByte
+    #define FreeRng        wc_FreeRng
+
+	#if defined(HAVE_HASHDRBG) || defined(NO_RC4)
+	    #define RNG_HealthTest wc_RNG_HealthTest
+	#endif /* HAVE_HASHDRBG || NO_RC4 */
+
+#endif /* CTAO_CRYPT_RANDOM_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/ctaocrypt/settings.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/ctaocrypt/settings.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/ctaocrypt/settings.h	(revision 453)
@@ -0,0 +1,723 @@
+/* settings.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+/* Place OS specific preprocessor flags, defines, includes here, will be
+   included into every file because types.h includes it */
+
+
+#ifndef CTAO_CRYPT_SETTINGS_H
+#define CTAO_CRYPT_SETTINGS_H
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+/* Uncomment next line if using IPHONE */
+/* #define IPHONE */
+
+/* Uncomment next line if using ThreadX */
+/* #define THREADX */
+
+/* Uncomment next line if using Micrium ucOS */
+/* #define MICRIUM */
+
+/* Uncomment next line if using Mbed */
+/* #define MBED */
+
+/* Uncomment next line if using Microchip PIC32 ethernet starter kit */
+/* #define MICROCHIP_PIC32 */
+
+/* Uncomment next line if using Microchip TCP/IP stack, version 5 */
+/* #define MICROCHIP_TCPIP_V5 */
+
+/* Uncomment next line if using Microchip TCP/IP stack, version 6 or later */
+/* #define MICROCHIP_TCPIP */
+
+/* Uncomment next line if using PIC32MZ Crypto Engine */
+/* #define CYASSL_MICROCHIP_PIC32MZ */
+
+/* Uncomment next line if using FreeRTOS */
+/* #define FREERTOS */
+
+/* Uncomment next line if using FreeRTOS Windows Simulator */
+/* #define FREERTOS_WINSIM */
+
+/* Uncomment next line if using RTIP */
+/* #define EBSNET */
+
+/* Uncomment next line if using lwip */
+/* #define CYASSL_LWIP */
+
+/* Uncomment next line if building CyaSSL for a game console */
+/* #define CYASSL_GAME_BUILD */
+
+/* Uncomment next line if building CyaSSL for LSR */
+/* #define CYASSL_LSR */
+
+/* Uncomment next line if building CyaSSL for Freescale MQX/RTCS/MFS */
+/* #define FREESCALE_MQX */
+
+/* Uncomment next line if using STM32F2 */
+/* #define CYASSL_STM32F2 */
+
+/* Uncomment next line if using QL SEP settings */
+/* #define CYASSL_QL */
+
+/* Uncomment next line if building for EROAD */
+/* #define CYASSL_EROAD */
+
+/* Uncomment next line if building for IAR EWARM */
+/* #define CYASSL_IAR_ARM */
+
+/* Uncomment next line if using TI-RTOS settings */
+/* #define CYASSL_TIRTOS */
+
+/* Uncomment next line if building with PicoTCP */
+/* #define CYASSL_PICOTCP */
+
+/* Uncomment next line if building for PicoTCP demo bundle */
+/* #define CYASSL_PICOTCP_DEMO */
+
+#include <cyassl/ctaocrypt/visibility.h>
+
+#ifdef IPHONE
+    #define SIZEOF_LONG_LONG 8
+#endif
+
+
+#ifdef CYASSL_USER_SETTINGS
+    #include <user_settings.h>
+#endif
+
+/* for reverse compatibility after name change */
+#include <cyassl/ctaocrypt/settings_comp.h>
+
+#ifdef THREADX
+    #define SIZEOF_LONG_LONG 8
+#endif
+
+#ifdef HAVE_NETX
+    #include "nx_api.h"
+#endif
+
+#if defined(HAVE_LWIP_NATIVE) /* using LwIP native TCP socket */
+    #define CYASSL_LWIP
+    #define NO_WRITEV
+    #define SINGLE_THREADED
+    #define CYASSL_USER_IO
+    #define NO_FILESYSTEM
+#endif
+
+#if defined(CYASSL_IAR_ARM)
+    #define NO_MAIN_DRIVER
+    #define SINGLE_THREADED
+    #define USE_CERT_BUFFERS_1024
+    #define BENCH_EMBEDDED
+    #define NO_FILESYSTEM
+    #define NO_WRITEV
+    #define CYASSL_USER_IO
+    #define  BENCH_EMBEDDED
+#endif
+
+#ifdef MICROCHIP_PIC32
+    /* #define CYASSL_MICROCHIP_PIC32MZ */
+    #define SIZEOF_LONG_LONG 8
+    #define SINGLE_THREADED
+    #define CYASSL_USER_IO
+    #define NO_WRITEV
+    #define NO_DEV_RANDOM
+    #define NO_FILESYSTEM
+    #define USE_FAST_MATH
+    #define TFM_TIMING_RESISTANT
+#endif
+
+#if defined(CYASSL_MICROCHIP_PIC32MZ) || defined(WOLFSSL_MICROCHIP_PIC32MZ)
+    #ifndef NO_PIC32MZ_CRYPT
+        #define WOLFSSL_PIC32MZ_CRYPT
+    #endif
+    #ifndef NO_PIC32MZ_RNG
+        #define WOLFSSL_PIC32MZ_RNG
+    #endif
+    #ifndef NO_PIC32MZ_HASH
+        #define WOLFSSL_PIC32MZ_HASH
+    #endif
+
+    #define CYASSL_AES_COUNTER
+    #define HAVE_AESGCM
+    #define NO_BIG_INT
+#endif
+
+#ifdef MICROCHIP_TCPIP_V5
+    /* include timer functions */
+    #include "TCPIP Stack/TCPIP.h"
+#endif
+
+#ifdef MICROCHIP_TCPIP
+    /* include timer, NTP functions */
+    #ifdef MICROCHIP_MPLAB_HARMONY
+        #include "tcpip/tcpip.h"
+    #else
+        #include "system/system_services.h"
+        #include "tcpip/sntp.h"
+    #endif
+#endif
+
+#ifdef MBED
+    #define CYASSL_USER_IO
+    #define NO_FILESYSTEM
+    #define NO_CERTS
+    #define USE_CERT_BUFFERS_1024
+    #define NO_WRITEV
+    #define NO_DEV_RANDOM
+    #define NO_SHA512
+    #define NO_DH
+    #define NO_DSA
+    #define NO_HC128
+    #define HAVE_ECC
+    #define NO_SESSION_CACHE
+    #define CYASSL_CMSIS_RTOS
+#endif
+
+
+#ifdef CYASSL_EROAD
+    #define FREESCALE_MQX
+    #define FREESCALE_MMCAU
+    #define SINGLE_THREADED
+    #define NO_STDIO_FILESYSTEM
+    #define CYASSL_LEANPSK
+    #define HAVE_NULL_CIPHER
+    #define NO_OLD_TLS
+    #define NO_ASN
+    #define NO_BIG_INT
+    #define NO_RSA
+    #define NO_DSA
+    #define NO_DH
+    #define NO_CERTS
+    #define NO_PWDBASED
+    #define NO_DES3
+    #define NO_MD4
+    #define NO_RC4
+    #define NO_MD5
+    #define NO_SESSION_CACHE
+    #define NO_MAIN_DRIVER
+#endif
+
+#ifdef CYASSL_PICOTCP
+    #define errno pico_err
+    #include "pico_defines.h"
+    #include "pico_stack.h"
+    #include "pico_constants.h"
+    #define CUSTOM_RAND_GENERATE pico_rand
+#endif
+
+#ifdef CYASSL_PICOTCP_DEMO
+    #define CYASSL_STM32
+    #define USE_FAST_MATH
+    #define TFM_TIMING_RESISTANT
+    #define XMALLOC(s, h, type)  PICO_ZALLOC((s))
+    #define XFREE(p, h, type)    PICO_FREE((p))
+    #define SINGLE_THREADED
+    #define NO_WRITEV
+    #define CYASSL_USER_IO
+    #define NO_DEV_RANDOM
+    #define NO_FILESYSTEM
+#endif
+
+#ifdef FREERTOS_WINSIM
+    #define FREERTOS
+    #define USE_WINDOWS_API
+#endif
+
+
+/* Micrium will use Visual Studio for compilation but not the Win32 API */
+#if defined(_WIN32) && !defined(MICRIUM) && !defined(FREERTOS) \
+        && !defined(EBSNET) && !defined(CYASSL_EROAD) && !defined(INTIME_RTOS)
+    #define USE_WINDOWS_API
+#endif
+
+
+#if defined(CYASSL_LEANPSK) && !defined(XMALLOC_USER)
+    #include <stdlib.h>
+    #define XMALLOC(s, h, type)  malloc((s))
+    #define XFREE(p, h, type)    free((p))
+    #define XREALLOC(p, n, h, t) realloc((p), (n))
+#endif
+
+#if defined(XMALLOC_USER) && defined(SSN_BUILDING_LIBYASSL)
+    #undef  XMALLOC
+    #define XMALLOC     yaXMALLOC
+    #undef  XFREE
+    #define XFREE       yaXFREE
+    #undef  XREALLOC
+    #define XREALLOC    yaXREALLOC
+#endif
+
+
+#ifdef FREERTOS
+    #ifndef NO_WRITEV
+        #define NO_WRITEV
+    #endif
+    #ifndef NO_SHA512
+        #define NO_SHA512
+    #endif
+    #ifndef NO_DH
+        #define NO_DH
+    #endif
+    #ifndef NO_DSA
+        #define NO_DSA
+    #endif
+    #ifndef NO_HC128
+        #define NO_HC128
+    #endif
+
+    #ifndef SINGLE_THREADED
+        #include "FreeRTOS.h"
+        #include "semphr.h"
+    #endif
+#endif
+
+#ifdef CYASSL_TIRTOS
+    #define SIZEOF_LONG_LONG 8
+    #define NO_WRITEV
+    #define NO_CYASSL_DIR
+    #define USE_FAST_MATH
+    #define TFM_TIMING_RESISTANT
+    #define NO_DEV_RANDOM
+    #define NO_FILESYSTEM
+    #define USE_CERT_BUFFERS_2048
+    #define NO_ERROR_STRINGS
+    #define USER_TIME
+
+    #ifdef __IAR_SYSTEMS_ICC__
+        #pragma diag_suppress=Pa089
+    #elif !defined(__GNUC__)
+        /* Suppress the sslpro warning */
+        #pragma diag_suppress=11
+    #endif
+
+    #include <ti/ndk/nettools/mytime/mytime.h>
+#endif
+
+#ifdef EBSNET
+    #include "rtip.h"
+
+    /* #define DEBUG_CYASSL */
+    #define NO_CYASSL_DIR  /* tbd */
+
+    #if (POLLOS)
+        #define SINGLE_THREADED
+    #endif
+
+    #if (RTPLATFORM)
+        #if (!RTP_LITTLE_ENDIAN)
+            #define BIG_ENDIAN_ORDER
+        #endif
+    #else
+        #if (!KS_LITTLE_ENDIAN)
+            #define BIG_ENDIAN_ORDER
+        #endif
+    #endif
+
+    #if (WINMSP3)
+        #undef SIZEOF_LONG
+        #define SIZEOF_LONG_LONG 8
+    #else
+        #sslpro: settings.h - please implement SIZEOF_LONG and SIZEOF_LONG_LONG
+    #endif
+
+    #define XMALLOC(s, h, type) ((void *)rtp_malloc((s), SSL_PRO_MALLOC))
+    #define XFREE(p, h, type) (rtp_free(p))
+    #define XREALLOC(p, n, h, t) realloc((p), (n))
+
+#endif /* EBSNET */
+
+#ifdef CYASSL_GAME_BUILD
+    #define SIZEOF_LONG_LONG 8
+    #if defined(__PPU) || defined(__XENON)
+        #define BIG_ENDIAN_ORDER
+    #endif
+#endif
+
+#ifdef CYASSL_LSR
+    #define HAVE_WEBSERVER
+    #define SIZEOF_LONG_LONG 8
+    #define CYASSL_LOW_MEMORY
+    #define NO_WRITEV
+    #define NO_SHA512
+    #define NO_DH
+    #define NO_DSA
+    #define NO_HC128
+    #define NO_DEV_RANDOM
+    #define NO_CYASSL_DIR
+    #define NO_RABBIT
+    #ifndef NO_FILESYSTEM
+        #define LSR_FS
+        #include "inc/hw_types.h"
+        #include "fs.h"
+    #endif
+    #define CYASSL_LWIP
+    #include <errno.h>  /* for tcp errno */
+    #define CYASSL_SAFERTOS
+    #if defined(__IAR_SYSTEMS_ICC__)
+        /* enum uses enum */
+        #pragma diag_suppress=Pa089
+    #endif
+#endif
+
+#ifdef CYASSL_SAFERTOS
+    #ifndef SINGLE_THREADED
+        #include "SafeRTOS/semphr.h"
+    #endif
+
+    #include "SafeRTOS/heap.h"
+    #define XMALLOC(s, h, type)  pvPortMalloc((s))
+    #define XFREE(p, h, type)    vPortFree((p))
+    #define XREALLOC(p, n, h, t) pvPortRealloc((p), (n))
+#endif
+
+#ifdef CYASSL_LOW_MEMORY
+    #undef  RSA_LOW_MEM
+    #define RSA_LOW_MEM
+    #undef  CYASSL_SMALL_STACK
+    #define CYASSL_SMALL_STACK
+    #undef  TFM_TIMING_RESISTANT
+    #define TFM_TIMING_RESISTANT
+#endif
+
+#ifdef FREESCALE_MQX
+    #define SIZEOF_LONG_LONG 8
+    #define NO_WRITEV
+    #define NO_DEV_RANDOM
+    #define NO_RABBIT
+    #define NO_CYASSL_DIR
+    #define USE_FAST_MATH
+    #define TFM_TIMING_RESISTANT
+    #define FREESCALE_K70_RNGA
+    /* #define FREESCALE_K53_RNGB */
+    #include "mqx.h"
+    #ifndef NO_FILESYSTEM
+        #include "mfs.h"
+        #include "fio.h"
+    #endif
+    #ifndef SINGLE_THREADED
+        #include "mutex.h"
+    #endif
+
+    #define XMALLOC(s, h, t)    (void *)_mem_alloc_system((s))
+    #define XFREE(p, h, t)      {void* xp = (p); if ((xp)) _mem_free((xp));}
+    /* Note: MQX has no realloc, using fastmath above */
+#endif
+
+#ifdef CYASSL_STM32F2
+    #define SIZEOF_LONG_LONG 8
+    #define NO_DEV_RANDOM
+    #define NO_CYASSL_DIR
+    #define NO_RABBIT
+    #define STM32F2_RNG
+    #define STM32F2_CRYPTO
+    #define KEIL_INTRINSICS
+#endif
+
+#ifdef MICRIUM
+
+    #include "stdlib.h"
+    #include "net_cfg.h"
+    #include "ssl_cfg.h"
+    #include "net_secure_os.h"
+
+    #define CYASSL_TYPES
+
+    typedef CPU_INT08U byte;
+    typedef CPU_INT16U word16;
+    typedef CPU_INT32U word32;
+
+    #if (NET_SECURE_MGR_CFG_WORD_SIZE == CPU_WORD_SIZE_32)
+        #define SIZEOF_LONG        4
+        #undef  SIZEOF_LONG_LONG
+    #else
+        #undef  SIZEOF_LONG
+        #define SIZEOF_LONG_LONG   8
+    #endif
+
+    #define STRING_USER
+
+    #define XSTRLEN(pstr) ((CPU_SIZE_T)Str_Len((CPU_CHAR *)(pstr)))
+    #define XSTRNCPY(pstr_dest, pstr_src, len_max) \
+                    ((CPU_CHAR *)Str_Copy_N((CPU_CHAR *)(pstr_dest), \
+                     (CPU_CHAR *)(pstr_src), (CPU_SIZE_T)(len_max)))
+    #define XSTRNCMP(pstr_1, pstr_2, len_max) \
+                    ((CPU_INT16S)Str_Cmp_N((CPU_CHAR *)(pstr_1), \
+                     (CPU_CHAR *)(pstr_2), (CPU_SIZE_T)(len_max)))
+    #define XSTRSTR(pstr, pstr_srch) \
+                    ((CPU_CHAR *)Str_Str((CPU_CHAR *)(pstr), \
+                     (CPU_CHAR *)(pstr_srch)))
+    #define XMEMSET(pmem, data_val, size) \
+                    ((void)Mem_Set((void *)(pmem), (CPU_INT08U) (data_val), \
+                    (CPU_SIZE_T)(size)))
+    #define XMEMCPY(pdest, psrc, size) ((void)Mem_Copy((void *)(pdest), \
+                     (void *)(psrc), (CPU_SIZE_T)(size)))
+    #define XMEMCMP(pmem_1, pmem_2, size) \
+                   (((CPU_BOOLEAN)Mem_Cmp((void *)(pmem_1), (void *)(pmem_2), \
+                     (CPU_SIZE_T)(size))) ? DEF_NO : DEF_YES)
+    #define XMEMMOVE XMEMCPY
+
+#if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
+    #define MICRIUM_MALLOC
+    #define XMALLOC(s, h, type) ((void *)NetSecure_BlkGet((CPU_INT08U)(type), \
+                                 (CPU_SIZE_T)(s), (void *)0))
+    #define XFREE(p, h, type)   (NetSecure_BlkFree((CPU_INT08U)(type), \
+                                 (p), (void *)0))
+    #define XREALLOC(p, n, h, t) realloc((p), (n))
+#endif
+
+    #if (NET_SECURE_MGR_CFG_FS_EN == DEF_ENABLED)
+        #undef  NO_FILESYSTEM
+    #else
+        #define NO_FILESYSTEM
+    #endif
+
+    #if (SSL_CFG_TRACE_LEVEL == CYASSL_TRACE_LEVEL_DBG)
+        #define DEBUG_CYASSL
+    #else
+        #undef  DEBUG_CYASSL
+    #endif
+
+    #if (SSL_CFG_OPENSSL_EN == DEF_ENABLED)
+        #define OPENSSL_EXTRA
+    #else
+        #undef  OPENSSL_EXTRA
+    #endif
+
+    #if (SSL_CFG_MULTI_THREAD_EN == DEF_ENABLED)
+        #undef  SINGLE_THREADED
+    #else
+        #define SINGLE_THREADED
+    #endif
+
+    #if (SSL_CFG_DH_EN == DEF_ENABLED)
+        #undef  NO_DH
+    #else
+        #define NO_DH
+    #endif
+
+    #if (SSL_CFG_DSA_EN == DEF_ENABLED)
+        #undef  NO_DSA
+    #else
+        #define NO_DSA
+    #endif
+
+    #if (SSL_CFG_PSK_EN == DEF_ENABLED)
+        #undef  NO_PSK
+    #else
+        #define NO_PSK
+    #endif
+
+    #if (SSL_CFG_3DES_EN == DEF_ENABLED)
+        #undef  NO_DES
+    #else
+        #define NO_DES
+    #endif
+
+    #if (SSL_CFG_AES_EN == DEF_ENABLED)
+        #undef  NO_AES
+    #else
+        #define NO_AES
+    #endif
+
+    #if (SSL_CFG_RC4_EN == DEF_ENABLED)
+        #undef  NO_RC4
+    #else
+        #define NO_RC4
+    #endif
+
+    #if (SSL_CFG_RABBIT_EN == DEF_ENABLED)
+        #undef  NO_RABBIT
+    #else
+        #define NO_RABBIT
+    #endif
+
+    #if (SSL_CFG_HC128_EN == DEF_ENABLED)
+        #undef  NO_HC128
+    #else
+        #define NO_HC128
+    #endif
+
+    #if (CPU_CFG_ENDIAN_TYPE == CPU_ENDIAN_TYPE_BIG)
+        #define BIG_ENDIAN_ORDER
+    #else
+        #undef  BIG_ENDIAN_ORDER
+        #define LITTLE_ENDIAN_ORDER
+    #endif
+
+    #if (SSL_CFG_MD4_EN == DEF_ENABLED)
+        #undef  NO_MD4
+    #else
+        #define NO_MD4
+    #endif
+
+    #if (SSL_CFG_WRITEV_EN == DEF_ENABLED)
+        #undef  NO_WRITEV
+    #else
+        #define NO_WRITEV
+    #endif
+
+    #if (SSL_CFG_USER_RNG_SEED_EN == DEF_ENABLED)
+        #define NO_DEV_RANDOM
+    #else
+        #undef  NO_DEV_RANDOM
+    #endif
+
+    #if (SSL_CFG_USER_IO_EN == DEF_ENABLED)
+        #define CYASSL_USER_IO
+    #else
+        #undef  CYASSL_USER_IO
+    #endif
+
+    #if (SSL_CFG_DYNAMIC_BUFFERS_EN == DEF_ENABLED)
+        #undef  LARGE_STATIC_BUFFERS
+        #undef  STATIC_CHUNKS_ONLY
+    #else
+        #define LARGE_STATIC_BUFFERS
+        #define STATIC_CHUNKS_ONLY
+    #endif
+
+    #if (SSL_CFG_DER_LOAD_EN == DEF_ENABLED)
+        #define  CYASSL_DER_LOAD
+    #else
+        #undef   CYASSL_DER_LOAD
+    #endif
+
+    #if (SSL_CFG_DTLS_EN == DEF_ENABLED)
+        #define  CYASSL_DTLS
+    #else
+        #undef   CYASSL_DTLS
+    #endif
+
+    #if (SSL_CFG_CALLBACKS_EN == DEF_ENABLED)
+         #define CYASSL_CALLBACKS
+    #else
+         #undef  CYASSL_CALLBACKS
+    #endif
+
+    #if (SSL_CFG_FAST_MATH_EN == DEF_ENABLED)
+         #define USE_FAST_MATH
+    #else
+         #undef  USE_FAST_MATH
+    #endif
+
+    #if (SSL_CFG_TFM_TIMING_RESISTANT_EN == DEF_ENABLED)
+         #define TFM_TIMING_RESISTANT
+    #else
+         #undef  TFM_TIMING_RESISTANT
+    #endif
+
+#endif /* MICRIUM */
+
+
+#ifdef CYASSL_QL
+    #ifndef CYASSL_SEP
+        #define CYASSL_SEP
+    #endif
+    #ifndef OPENSSL_EXTRA
+        #define OPENSSL_EXTRA
+    #endif
+    #ifndef SESSION_CERTS
+        #define SESSION_CERTS
+    #endif
+    #ifndef HAVE_AESCCM
+        #define HAVE_AESCCM
+    #endif
+    #ifndef ATOMIC_USER
+        #define ATOMIC_USER
+    #endif
+    #ifndef CYASSL_DER_LOAD
+        #define CYASSL_DER_LOAD
+    #endif
+    #ifndef KEEP_PEER_CERT
+        #define KEEP_PEER_CERT
+    #endif
+    #ifndef HAVE_ECC
+        #define HAVE_ECC
+    #endif
+    #ifndef SESSION_INDEX
+        #define SESSION_INDEX
+    #endif
+#endif /* CYASSL_QL */
+
+
+#if !defined(XMALLOC_USER) && !defined(MICRIUM_MALLOC) && \
+    !defined(CYASSL_LEANPSK) && !defined(NO_CYASSL_MEMORY)
+    #define USE_CYASSL_MEMORY
+#endif
+
+
+#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS)
+    #undef  KEEP_PEER_CERT
+    #define KEEP_PEER_CERT
+#endif
+
+
+/* stream ciphers except arc4 need 32bit alignment, intel ok without */
+#ifndef XSTREAM_ALIGNMENT
+    #if defined(__x86_64__) || defined(__ia64__) || defined(__i386__)
+        #define NO_XSTREAM_ALIGNMENT
+    #else
+        #define XSTREAM_ALIGNMENT
+    #endif
+#endif
+
+
+/* FreeScale MMCAU hardware crypto has 4 byte alignment */
+#ifdef FREESCALE_MMCAU
+    #define CYASSL_MMCAU_ALIGNMENT 4
+#endif
+
+/* if using hardware crypto and have alignment requirements, specify the
+   requirement here.  The record header of SSL/TLS will prvent easy alignment.
+   This hint tries to help as much as possible.  */
+#ifndef CYASSL_GENERAL_ALIGNMENT
+    #ifdef CYASSL_AESNI
+        #define CYASSL_GENERAL_ALIGNMENT 16
+    #elif defined(XSTREAM_ALIGNMENT)
+        #define CYASSL_GENERAL_ALIGNMENT  4
+    #elif defined(FREESCALE_MMCAU)
+        #define CYASSL_GENERAL_ALIGNMENT  CYASSL_MMCAU_ALIGNMENT
+    #else
+        #define CYASSL_GENERAL_ALIGNMENT  0
+    #endif
+#endif
+
+
+#ifdef __INTEL_COMPILER
+    #pragma warning(disable:2259) /* explicit casts to smaller sizes, disable */
+#endif
+
+
+/* Place any other flags or defines here */
+
+
+#ifdef __cplusplus
+    }   /* extern "C" */
+#endif
+
+
+#endif /* CTAO_CRYPT_SETTINGS_H */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/ctaocrypt/settings_comp.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/ctaocrypt/settings_comp.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/ctaocrypt/settings_comp.h	(revision 453)
@@ -0,0 +1,72 @@
+/* settings_comp.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifndef CTAO_CRYPT_SETTINGS_C_H
+#define CTAO_CRYPT_SETTINGS_C_H
+
+
+/* since fips overrides rsa.h map compatibility here */
+#if !defined(NO_RSA)
+	#ifdef WOLFSSL_KEY_GEN
+	    #define RsaKeyToDer wc_RsaKeyToDer
+	#endif
+
+	#define RsaPrivateKeyDecode   wc_RsaPrivateKeyDecode
+	#define RsaPublicKeyDecode    wc_RsaPublicKeyDecode
+	#define RsaPublicKeyDecodeRaw wc_RsaPublicKeyDecodeRaw
+#endif /* have rsa and HAVE_FIPS */
+
+/* Macro redefinitions for compatibility */
+#ifdef HAVE_NTRU
+    #define MakeNtruCert wc_MakeNtruCert
+#endif
+#if defined(WOLFSSL_SHA512) && !defined(CYASSL_SHA512)
+    #define CYASSL_SHA512
+#endif
+#if defined(WOLFSSL_SHA384) && !defined(CYASSL_SHA384)
+    #define CYASSL_SHA384
+#endif
+#if defined(WOLFSSL_LEANPSK) && !defined(CYASSL_LEANPSK)
+    #define CYASSL_LEANPSK
+#endif
+#if defined(NO_WOLFSSL_MEMORY) && !defined(NO_CYASSL_MEMORY)
+    #define NO_CYASSL_MEMORY
+#endif
+#if defined(WOLFSSL_KEY_GEN) && !defined(CYASSL_KEY_GEN)
+    #define CYASSL_KEY_GEN
+#endif
+
+/* AES */
+#if defined(WOLFSSL_AES_DIRECT) && !defined(CYASSL_AES_DIRECT)
+    #define CYASSL_AES_DIRECT
+#endif
+#if defined(WOLFSSL_AES_COUNTER) && !defined(CYASSL_AES_COUNTER)
+    #define CYASSL_AES_COUNTER
+#endif
+
+/* DES */
+#if defined(WOLFSSL_DES_ECB) && !defined(CYASSL_DES_ECB)
+    #define CYASSL_DES_ECB
+#endif
+
+#endif /* CTAO_CRYPT_SETTINGS_C_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/ctaocrypt/sha256.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/ctaocrypt/sha256.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/ctaocrypt/sha256.h	(revision 453)
@@ -0,0 +1,46 @@
+/* sha256.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+
+
+#ifndef NO_SHA256
+
+#ifndef CTAO_CRYPT_SHA256_H
+#define CTAO_CRYPT_SHA256_H
+
+#include <wolfssl/wolfcrypt/sha256.h>
+#define InitSha256   wc_InitSha256
+#define Sha256Update wc_Sha256Update
+#define Sha256Final  wc_Sha256Final
+#define Sha256Hash   wc_Sha256Hash
+
+#ifdef WOLFSSL_SHA224
+    #define InitSha224   wc_InitSha224
+    #define Sha224Update wc_Sha224Update
+    #define Sha224Final  wc_Sha224Final
+    #define Sha224Hash   wc_Sha224Hash
+#endif
+
+#endif /* CTAO_CRYPT_SHA256_H */
+#endif /* NO_SHA256 */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/ctaocrypt/types.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/ctaocrypt/types.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/ctaocrypt/types.h	(revision 453)
@@ -0,0 +1,39 @@
+/* types.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+#ifndef CTAO_CRYPT_TYPES_H
+#define CTAO_CRYPT_TYPES_H
+
+#include <cyassl/ctaocrypt/wc_port.h>
+#include <cyassl/ctaocrypt/settings.h>
+#include <wolfssl/wolfcrypt/types.h>
+
+/* compatibility macros */
+#define CYASSL_WORD_SIZE    WOLFSSL_WORD_SIZE
+#define CYASSL_BIT_SIZE     WOLFSSL_BIT_SIZE
+#define CYASSL_MAX_16BIT    WOLFSSL_MAX_16BIT
+#define CYASSL_MAX_ERROR_SZ WOLFSSL_MAX_ERROR_SZ
+#define cyassl_word         wolfssl_word
+
+#endif /* CTAO_CRYPT_TYPES_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/ctaocrypt/visibility.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/ctaocrypt/visibility.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/ctaocrypt/visibility.h	(revision 453)
@@ -0,0 +1,73 @@
+/* visibility.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+/* Visibility control macros */
+
+#ifndef CTAO_CRYPT_VISIBILITY_H
+#define CTAO_CRYPT_VISIBILITY_H
+
+/* fips compatibility @wc_fips */
+#ifndef HAVE_FIPS
+    #include <wolfssl/wolfcrypt/visibility.h>
+    #define CYASSL_API   WOLFSSL_API
+	#define CYASSL_LOCAL WOLFSSL_LOCAL
+#else
+/* CYASSL_API is used for the public API symbols.
+        It either imports or exports (or does nothing for static builds)
+
+   CYASSL_LOCAL is used for non-API symbols (private).
+*/
+
+#if defined(BUILDING_WOLFSSL)
+    #if defined(HAVE_VISIBILITY) && HAVE_VISIBILITY
+        #define CYASSL_API   __attribute__ ((visibility("default")))
+        #define CYASSL_LOCAL __attribute__ ((visibility("hidden")))
+    #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
+        #define CYASSL_API   __global
+        #define CYASSL_LOCAL __hidden
+    #elif defined(_MSC_VER)
+        #ifdef CYASSL_DLL
+            #define CYASSL_API extern __declspec(dllexport)
+        #else
+            #define CYASSL_API
+        #endif
+        #define CYASSL_LOCAL
+    #else
+        #define CYASSL_API
+        #define CYASSL_LOCAL
+    #endif /* HAVE_VISIBILITY */
+#else /* BUILDING_WOLFSSL */
+    #if defined(_MSC_VER)
+        #ifdef CYASSL_DLL
+            #define CYASSL_API extern __declspec(dllimport)
+        #else
+            #define CYASSL_API
+        #endif
+        #define CYASSL_LOCAL
+    #else
+        #define CYASSL_API
+        #define CYASSL_LOCAL
+    #endif
+#endif /* BUILDING_WOLFSSL */
+#endif /* HAVE_FIPS */
+#endif /* CTAO_CRYPT_VISIBILITY_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/ctaocrypt/wc_port.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/ctaocrypt/wc_port.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/ctaocrypt/wc_port.h	(revision 453)
@@ -0,0 +1,32 @@
+/* port.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+#ifndef CTAO_CRYPT_PORT_H
+#define CTAO_CRYPT_PORT_H
+
+#include <cyassl/ctaocrypt/visibility.h>
+#include <wolfssl/wolfcrypt/wc_port.h>
+#define CyaSSL_Mutex wolfSSL_Mutex
+
+#endif /* CTAO_CRYPT_PORT_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/error-ssl.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/error-ssl.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/error-ssl.h	(revision 453)
@@ -0,0 +1,23 @@
+/* error-ssl.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#include <wolfssl/error-ssl.h>
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/openssl/evp.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/openssl/evp.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/openssl/evp.h	(revision 453)
@@ -0,0 +1,41 @@
+/* evp.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+/*  evp.h defines mini evp openssl compatibility layer
+ *
+ */
+
+#ifndef CYASSL_OPENSSL_EVP
+#define CYASSL_OPENSSL_EVP
+
+#define CyaSSL_StoreExternalIV       wolfSSL_StoreExternalIV
+#define CyaSSL_SetInternalIV         wolfSSL_SetInternalIV
+#define CYASSL_EVP_MD                WOLFSSL_EVP_MD
+#define CyaSSL_EVP_X_STATE           wolfSSL_EVP_X_STATE
+#define CyaSSL_EVP_X_STATE_LEN       wolfSSL_EVP_X_STATE_LEN
+#define CyaSSL_3des_iv               wolfSSL_3des_iv
+#define CyaSSL_aes_ctr_iv            wolfSSL_aes_ctr_iv
+
+#include <wolfssl/openssl/evp.h>
+#endif
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/openssl/ssl.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/openssl/ssl.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/openssl/ssl.h	(revision 453)
@@ -0,0 +1,34 @@
+/* ssl.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+/*  ssl.h defines openssl compatibility layer
+ *
+ */
+#ifndef CYASSL_OPENSSL_H_
+#define CYASSL_OPENSSL_H_
+
+#include <cyassl/ssl.h>
+#include <wolfssl/openssl/ssl.h>
+
+#endif
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/ssl.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/ssl.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/ssl.h	(revision 453)
@@ -0,0 +1,721 @@
+/* ssl.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+/*
+ * ssl.h makes wolfssl backwards compatible with cyassl
+ */
+
+#ifndef WOLFSSL_CYASSL_H_
+#define WOLFSSL_CYASSL_H_
+/*
+ * Name change
+ * include the new ssl.h
+ */
+#include <wolfssl/ssl.h>
+#include <cyassl/ctaocrypt/types.h>
+#include <cyassl/ctaocrypt/settings.h>
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+#ifdef _WIN32
+    /* wincrypt.h clashes */
+    #undef X509_NAME
+#endif
+
+#ifdef CYASSL_TIRTOS
+    #undef CYASSL_TIRTOS
+    #define CYASSL_TIRTOS WOLFSSL_TIRTOS
+#endif
+
+#define CYASSL          WOLFSSL
+#define DEBUG_CYASSL    DEBUG_WOLFSSL
+#define CYASSL_CTX      WOLFSSL_CTX
+#define CYASSL_METHOD   WOLFSSL_METHOD
+#define CYASSL_SESSION  WOLFSSL_SESSION
+
+#define CYASSL_X509       WOLFSSL_X509
+#define CYASSL_X509_NAME  WOLFSSL_X509_NAME
+#define CYASSL_X509_CHAIN WOLFSSL_X509_CHAIN
+#ifdef WOLFSSL_SNIFFER
+    #define CYASSL_SNIFFER    WOLFSSL_SNIFFER
+#endif
+
+/* redeclare guard */
+#define CYASSL_TYPES_DEFINED WOLFSSL_TYPES_DEFINED
+
+/* legacy defines */
+#define yasslIP          wolfSSLIP                                         /**/
+#define yasslPort        wolfSSLPort                                       /**/
+
+/* cyassl/ssl.h (structs) */
+#define CYASSL_RSA                WOLFSSL_RSA
+#define CYASSL_DSA                WOLFSSL_DSA
+#define CYASSL_BIO                WOLFSSL_BIO
+#define CYASSL_CIPHER             WOLFSSL_CIPHER
+#define CYASSL_MD4_CTX            WOLFSSL_MD4_CTX
+#define CYASSL_MFL_2_9            WOLFSSL_MFL_2_9                          /**/
+#define CYASSL_MFL_2_13           WOLFSSL_MFL_2_13                         /**/
+#define CYASSL_EVP_PKEY           WOLFSSL_EVP_PKEY
+#define CYASSL_X509_CRL           WOLFSSL_X509_CRL
+#define CYASSL_ASN1_TIME          WOLFSSL_ASN1_TIME
+#define CYASSL_BIO_METHOD         WOLFSSL_BIO_METHOD
+#define CYASSL_X509_STORE         WOLFSSL_X509_STORE
+#define CYASSL_X509_OBJECT        WOLFSSL_X509_OBJECT
+#define CYASSL_X509_LOOKUP        WOLFSSL_X509_LOOKUP
+#define CYASSL_ASN1_OBJECT        WOLFSSL_ASN1_OBJECT
+#define CYASSL_ASN1_STRING        WOLFSSL_ASN1_STRING
+#define CYASSL_COMP_METHOD        WOLFSSL_COMP_METHOD
+#define CYASSL_CRL_CHECKALL       WOLFSSL_CRL_CHECKALL
+#define CYASSL_ASN1_INTEGER       WOLFSSL_ASN1_INTEGER
+#define CYASSL_X509_REVOKED       WOLFSSL_X509_REVOKED
+#define CYASSL_dynlock_value      WOLFSSL_dynlock_value
+#define CYASSL_X509_EXTENSION     WOLFSSL_X509_EXTENSION
+#define CYASSL_X509_STORE_CTX     WOLFSSL_X509_STORE_CTX
+#define CYASSL_X509_LOOKUP_METHOD WOLFSSL_X509_LOOKUP_METHOD
+
+#define CyaSSL_LoadCRL            wolfSSL_LoadCRL
+#define CyaSSL_EnableCRL          wolfSSL_EnableCRL
+#define CyaSSL_SetCRL_Cb          wolfSSL_SetCRL_Cb
+
+/* cyassl/test.h */
+#ifdef CyaSSL_TEST_H
+    #define CYASSL_THREAD         WOLFSSL_THREAD
+#endif
+
+/* src/ssl.c */
+#define CYASSL_CRL                       WOLFSSL_CRL
+#define CYASSL_SSLV3                     WOLFSSL_SSLV3
+#define CYASSL_TLSV1                     WOLFSSL_TLSV1
+#define CYASSL_TLSV1_1                   WOLFSSL_TLSV1_1
+#define CYASSL_TLSV1_2                   WOLFSSL_TLSV1_2
+#define CYASSL_USER_CA                   WOLFSSL_USER_CA
+#define CYASSL_CLIENT_END                WOLFSSL_CLIENT_END
+#define CYASSL_CERT_MANAGER              WOLFSSL_CERT_MANAGER
+#define MAX_CYASSL_FILE_SIZE             MAX_WOLFSSL_FILE_SIZE
+
+#define CyaSSL_get_cipher                wolfSSL_get_cipher
+#define CyaSSL_get_ciphers               wolfSSL_get_ciphers
+#define CyaSSL_KeyPemToDer               wolfSSL_KeyPemToDer
+#define CyaSSL_get_version               wolfSSL_get_version
+#define CyaSSL_SetServerID               wolfSSL_SetServerID
+#define CyaSSL_use_old_poly              wolfSSL_use_old_poly
+#define CyaSSL_SetCertCbCtx              wolfSSL_SetCertCbCtx
+#define CyaSSL_CertPemToDer              wolfSSL_CertPemToDer
+#define CyaSSL_get_shutdown              wolfSSL_get_shutdown
+#define CyaSSL_SetMinVersion             wolfSSL_SetMinVersion
+#define CyaSSL_CTX_UnloadCAs             wolfSSL_CTX_UnloadCAs
+#define CyaSSL_session_reused            wolfSSL_session_reused
+#define CyaSSL_UnloadCertsKeys           wolfSSL_UnloadCertsKeys
+#define CyaSSL_CIPHER_get_name           wolfSSL_CIPHER_get_name
+#define CyaSSL_is_init_finished          wolfSSL_is_init_finished
+#define CyaSSL_get_alert_history         wolfSSL_get_alert_history
+#define CyaSSL_get_current_cipher        wolfSSL_get_current_cipher
+#define CyaSSL_CertManagerUnloadCAs      wolfSSL_CertManagerUnloadCAs
+#define CyaSSL_CertManagerEnableOCSP     wolfSSL_CertManagerEnableOCSP
+#define CyaSSL_CTX_check_private_key     wolfSSL_CTX_check_private_key
+#define CyaSSL_CertManagerDisableOCSP    wolfSSL_CertManagerDisableOCSP
+#define CyaSSL_get_current_cipher_suite  wolfSSL_get_current_cipher_suite
+#define CyaSSL_CTX_load_verify_locations wolfSSL_CTX_load_verify_locations
+#define CyaSSL_CTX_set_default_passwd_cb wolfSSL_CTX_set_default_passwd_cb
+
+#define CyaSSL_save_session_cache        wolfSSL_save_session_cache
+#define CyaSSL_restore_session_cache     wolfSSL_restore_session_cache
+#define CyaSSL_memsave_session_cache     wolfSSL_memsave_session_cache
+#define CyaSSL_memrestore_session_cache  wolfSSL_memrestore_session_cache
+#define CyaSSL_get_session_cache_memsize wolfSSL_get_session_cache_memsize
+
+/* certificate cache persistence, uses ctx since certs are per ctx */
+#define CyaSSL_CTX_save_cert_cache        wolfSSL_CTX_save_cert_cache
+#define CyaSSL_CTX_restore_cert_cache     wolfSSL_CTX_restore_cert_cache
+#define CyaSSL_CTX_memsave_cert_cache     wolfSSL_CTX_memsave_cert_cache
+#define CyaSSL_CTX_memrestore_cert_cache  wolfSSL_CTX_memrestore_cert_cache
+#define CyaSSL_CTX_get_cert_cache_memsize wolfSSL_CTX_get_cert_cache_memsize
+
+/* wolfSSL extensions */
+/* get wolfSSL peer X509_CHAIN */
+#define CyaSSL_get_chain_count wolfSSL_get_chain_count
+/* index cert length */
+#define CyaSSL_get_chain_length wolfSSL_get_chain_length
+/* index cert in X509 */
+#define CyaSSL_get_chain_X509 wolfSSL_get_chain_X509
+/* free X509 */
+#define CyaSSL_FreeX509 wolfSSL_FreeX509
+/* get index cert in PEM */
+#define CyaSSL_X509_get_subjectCN wolfSSL_X509_get_subjectCN
+#define CyaSSL_X509_get_der       wolfSSL_X509_get_der
+#define CyaSSL_X509_notBefore     wolfSSL_X509_notBefore
+#define CyaSSL_X509_notAfter      wolfSSL_X509_notAfter
+#define CyaSSL_X509_get_notBefore wolfSSL_X509_get_notBefore
+#define CyaSSL_X509_get_notAfter  wolfSSL_X509_get_notAfter
+#define CyaSSL_X509_version       wolfSSL_X509_version
+
+#define CyaSSL_cmp_peer_cert_to_file wolfSSL_cmp_peer_cert_to_file
+
+#define CyaSSL_X509_get_next_altname wolfSSL_X509_get_next_altname
+
+#define CyaSSL_X509_d2i wolfSSL_X509_d2i
+#ifndef NO_FILESYSTEM
+    #ifndef NO_STDIO_FILESYSTEM
+        #define CyaSSL_X509_d2i_fp wolfSSL_X509_d2i_fp
+    #endif
+#define CyaSSL_X509_load_certificate_file wolfSSL_X509_load_certificate_file
+#endif
+
+#ifdef WOLFSSL_SEP
+#define CyaSSL_X509_get_device_type      wolfSSL_X509_get_device_type
+#define CyaSSL_X509_get_hw_type          wolfSSL_X509_get_hw_type
+#define CyaSSL_X509_get_hw_serial_number wolfSSL_X509_get_hw_serial_number
+#endif
+
+#define CyaSSL_CTX_SetGenCookie wolfSSL_CTX_SetGenCookie
+#define CyaSSL_SetCookieCtx     wolfSSL_SetCookieCtx
+#define CyaSSL_GetCookieCtx     wolfSSL_GetCookieCtx
+#define CyaSSL_ERR_get_error_line_data wolfSSL_ERR_get_error_line_data
+#define CyaSSL_ERR_get_error           wolfSSL_ERR_get_error
+#define CyaSSL_ERR_clear_error         wolfSSL_ERR_clear_error
+#define CyaSSL_RAND_status             wolfSSL_RAND_status
+#define CyaSSL_RAND_bytes              wolfSSL_RAND_bytes
+#define CyaSSL_CTX_set_options         wolfSSL_CTX_set_options
+#define CyaSSL_ERR_free_strings        wolfSSL_ERR_free_strings
+#define CyaSSL_ERR_remove_state        wolfSSL_ERR_remove_state
+#define CyaSSL_EVP_cleanup             wolfSSL_EVP_cleanup
+#define CyaSSL_cleanup_all_ex_data     wolfSSL_cleanup_all_ex_data
+#define CyaSSL_CTX_set_mode            wolfSSL_CTX_set_mode
+#define CyaSSL_CTX_get_mode            wolfSSL_CTX_get_mode
+#define CyaSSL_CTX_set_default_read_ahead   wolfSSL_CTX_set_default_read_ahead
+#define CyaSSL_CTX_sess_set_cache_size      wolfSSL_CTX_sess_set_cache_size
+#define CyaSSL_CTX_set_default_verify_paths wolfSSL_CTX_set_default_verify_paths
+#define CyaSSL_CTX_set_session_id_context   wolfSSL_CTX_set_session_id_context
+#define CyaSSL_get_peer_certificate         wolfSSL_get_peer_certificate
+#define CyaSSL_BIO_printf                   wolfSSL_BIO_printf
+#define CyaSSL_ASN1_UTCTIME_print           wolfSSL_ASN1_UTCTIME_print
+#define CyaSSL_sk_num                       wolfSSL_sk_num
+#define CyaSSL_sk_value                     wolfSSL_sk_value
+
+/* stunnel 4.28 needs */
+#define CyaSSL_CTX_get_ex_data        wolfSSL_CTX_get_ex_data
+#define CyaSSL_CTX_set_ex_data        wolfSSL_CTX_set_ex_data
+#define CyaSSL_CTX_sess_set_get_cb    wolfSSL_CTX_sess_set_get_cb
+#define CyaSSL_CTX_sess_set_new_cb    wolfSSL_CTX_sess_set_new_cb
+#define CyaSSL_CTX_sess_set_remove_cb wolfSSL_CTX_sess_set_remove_cb
+
+#define CyaSSL_i2d_SSL_SESSION wolfSSL_i2d_SSL_SESSION
+#define CyaSSL_d2i_SSL_SESSION wolfSSL_d2i_SSL_SESSION
+
+#define CyaSSL_SESSION_get_timeout  wolfSSL_SESSION_get_timeout
+#define CyaSSL_SESSION_get_time     wolfSSL_SESSION_get_time
+#define CyaSSL_CTX_get_ex_new_index wolfSSL_CTX_get_ex_new_index
+
+
+/* wolfio.c */
+#define CYASSL_CBIO_ERR_ISR        WOLFSSL_CBIO_ERR_ISR
+#define CYASSL_CBIO_ERR_TIMEOUT    WOLFSSL_CBIO_ERR_TIMEOUT
+#define CYASSL_CBIO_ERR_GENERAL    WOLFSSL_CBIO_ERR_GENERAL
+#define CYASSL_CBIO_ERR_CONN_RST   WOLFSSL_CBIO_ERR_CONN_RST
+#define CYASSL_CBIO_ERR_WANT_READ  WOLFSSL_CBIO_ERR_WANT_READ
+#define CYASSL_CBIO_ERR_WANT_WRITE WOLFSSL_CBIO_ERR_WANT_WRITE
+#define CYASSL_CBIO_ERR_CONN_CLOSE WOLFSSL_CBIO_ERR_CONN_CLOSE
+
+#define CyaSSL_GetIOReadCtx        wolfSSL_GetIOReadCtx
+#define CyaSSL_GetIOWriteCtx       wolfSSL_GetIOWriteCtx
+
+/* src/tls.c */
+#define CYASSL_SERVER_END          WOLFSSL_SERVER_END
+#define CYASSL_TLS_HMAC_INNER_SZ   WOLFSSL_TLS_HMAC_INNER_SZ
+
+#define CyaSSL_DeriveTlsKeys       wolfSSL_DeriveTlsKeys
+#define CyaSSL_make_eap_keys       wolfSSL_make_eap_keys
+#define CyaSSL_MakeTlsMasterSecret wolfSSL_MakeTlsMasterSecret
+
+/* src/internal.c */
+#define CYASSL_CHAIN_CA                WOLFSSL_CHAIN_CA
+#define CYASSL_ALERT_HISTORY           WOLFSSL_ALERT_HISTORY
+#define CYASSL_SESSION_TIMEOUT         WOLFSSL_SESSION_TIMEOUT
+#define CYASSL_CBIO_ERR_CONN_RST       WOLFSSL_CBIO_ERR_CONN_RST
+
+#define cyassl_rc4                     wolfssl_rc4
+#define cyassl_aes                     wolfssl_aes
+#define cyassl_chacha                  wolfssl_chacha
+#define CyaSSL_ERR_reason_error_string wolfSSL_ERR_reason_error_string
+
+#define CyaSSL_set_ex_data  wolfSSL_set_ex_data
+#define CyaSSL_get_shutdown wolfSSL_get_shutdown
+#define CyaSSL_set_rfd      wolfSSL_set_rfd
+#define CyaSSL_set_wfd      wolfSSL_set_wfd
+#define CyaSSL_set_shutdown wolfSSL_set_shutdown
+#define CyaSSL_set_session_id_context wolfSSL_set_session_id_context
+#define CyaSSL_set_connect_state      wolfSSL_set_connect_state
+#define CyaSSL_set_accept_state       wolfSSL_set_accept_state
+#define CyaSSL_session_reused         wolfSSL_session_reused
+#define CyaSSL_SESSION_free           wolfSSL_SESSION_free
+#define CyaSSL_is_init_finished       wolfSSL_is_init_finished
+
+#define CyaSSL_get_version              wolfSSL_get_version
+#define CyaSSL_get_current_cipher_suite wolfSSL_get_current_cipher_suite
+#define CyaSSL_get_current_cipher       wolfSSL_get_current_cipher
+#define CyaSSL_CIPHER_description       wolfSSL_CIPHER_description
+#define CyaSSL_CIPHER_get_name          wolfSSL_CIPHER_get_name
+#define CyaSSL_get_cipher               wolfSSL_get_cipher
+#define CyaSSL_get1_session             wolfSSL_get1_session
+
+#define CyaSSL_X509_free      wolfSSL_X509_free
+#define CyaSSL_OPENSSL_free   wolfSSL_OPENSSL_free
+#define CyaSSL_OCSP_parse_url wolfSSL_OCSP_parse_url
+
+#define CyaSSLv23_client_method wolfSSLv23_client_method
+#define CyaSSLv2_client_method  wolfSSLv2_client_method
+#define CyaSSLv2_server_method  wolfSSLv2_server_method
+
+#define CyaSSL_MD4_Init     wolfSSL_MD4_Init
+#define CyaSSL_MD4_Update   wolfSSL_MD4_Update
+#define CyaSSL_MD4_Final    wolfSSL_MD4_Final
+
+
+#define CyaSSL_BIO_new      wolfSSL_BIO_new
+#define CyaSSL_BIO_free     wolfSSL_BIO_free
+#define CyaSSL_BIO_free_all wolfSSL_BIO_free_all
+#define CyaSSL_BIO_read     wolfSSL_BIO_read
+#define CyaSSL_BIO_write    wolfSSL_BIO_write
+#define CyaSSL_BIO_push     wolfSSL_BIO_push
+#define CyaSSL_BIO_pop      wolfSSL_BIO_pop
+#define CyaSSL_BIO_flush    wolfSSL_BIO_flush
+#define CyaSSL_BIO_pending  wolfSSL_BIO_pending
+
+#define CyaSSL_BIO_f_buffer              wolfSSL_BIO_f_buffer
+#define CyaSSL_BIO_set_write_buffer_size wolfSSL_BIO_set_write_buffer_size
+#define CyaSSL_BIO_f_ssl                 wolfSSL_BIO_f_ssl
+#define CyaSSL_BIO_new_socket            wolfSSL_BIO_new_socket
+#define CyaSSL_BIO_eof                   wolfSSL_BIO_eof
+
+#define CyaSSL_BIO_s_mem        wolfSSL_BIO_s_mem
+#define CyaSSL_BIO_f_base64     wolfSSL_BIO_f_base64
+#define CyaSSL_BIO_set_flags    wolfSSL_BIO_set_flags
+#define CyaSSL_BIO_get_mem_data wolfSSL_BIO_get_mem_data
+#define CyaSSL_BIO_new_mem_buf  wolfSSL_BIO_new_mem_buf
+
+
+#define CyaSSL_BIO_set_ssl wolfSSL_BIO_set_ssl
+#define CyaSSL_set_bio     wolfSSL_set_bio
+
+#define CyaSSL_add_all_algorithms wolfSSL_add_all_algorithms
+#define CyaSSL_RAND_screen        wolfSSL_RAND_screen
+#define CyaSSL_RAND_file_name     wolfSSL_RAND_file_name
+#define CyaSSL_RAND_write_file    wolfSSL_RAND_write_file
+#define CyaSSL_RAND_load_file     wolfSSL_RAND_load_file
+#define CyaSSL_RAND_egd           wolfSSL_RAND_egd
+#define CyaSSL_RAND_seed          wolfSSL_RAND_seed
+#define CyaSSL_RAND_add           wolfSSL_RAND_add
+
+#define CyaSSL_COMP_zlib wolfSSL_COMP_zlib
+#define CyaSSL_COMP_rle  wolfSSL_COMP_rle
+#define CyaSSL_COMP_add_compression_method  wolfSSL_COMP_add_compression_method
+#define CyaSSL_set_dynlock_create_callback  wolfSSL_set_dynlock_create_callback
+#define CyaSSL_set_dynlock_lock_callback    wolfSSL_set_dynlock_lock_callback
+#define CyaSSL_set_dynlock_destroy_callback wolfSSL_set_dynlock_destroy_callback
+#define CyaSSL_get_ex_new_index     wolfSSL_get_ex_new_index
+#define CyaSSL_set_id_callback      wolfSSL_set_id_callback
+#define CyaSSL_set_locking_callback wolfSSL_set_locking_callback
+#define CyaSSL_num_locks            wolfSSL_num_locks
+
+#define CyaSSL_X509_STORE_CTX_get_current_cert wolfSSL_X509_STORE_CTX_get_current_cert
+#define CyaSSL_X509_STORE_CTX_get_error        wolfSSL_X509_STORE_CTX_get_error
+#define CyaSSL_X509_STORE_CTX_get_error_depth  wolfSSL_X509_STORE_CTX_get_error_depth
+
+#define CyaSSL_X509_NAME_oneline            wolfSSL_X509_NAME_oneline
+#define CyaSSL_X509_get_issuer_name         wolfSSL_X509_get_issuer_name
+#define CyaSSL_X509_get_subject_name        wolfSSL_X509_get_subject_name
+#define CyaSSL_X509_ext_isSet_by_NID        wolfSSL_X509_ext_isSet_by_NID
+#define CyaSSL_X509_ext_get_critical_by_NID wolfSSL_X509_ext_get_critical_by_NID
+#define CyaSSL_X509_get_isCA                wolfSSL_X509_get_isCA
+#define CyaSSL_X509_get_isSet_pathLength    wolfSSL_X509_get_isSet_pathLength
+#define CyaSSL_X509_get_pathLength          wolfSSL_X509_get_pathLength
+#define CyaSSL_X509_get_keyUsage            wolfSSL_X509_get_keyUsage
+#define CyaSSL_X509_get_authorityKeyID      wolfSSL_X509_get_authorityKeyID
+#define CyaSSL_X509_get_subjectKeyID        wolfSSL_X509_get_subjectKeyID
+#define CyaSSL_X509_NAME_entry_count        wolfSSL_X509_NAME_entry_count
+#define CyaSSL_X509_NAME_get_text_by_NID    wolfSSL_X509_NAME_get_text_by_NID
+#define CyaSSL_X509_verify_cert             wolfSSL_X509_verify_cert
+#define CyaSSL_X509_verify_cert_error_string wolfSSL_X509_verify_cert_error_string
+#define CyaSSL_X509_get_signature_type      wolfSSL_X509_get_signature_type
+#define CyaSSL_X509_get_signature           wolfSSL_X509_get_signature
+
+#define CyaSSL_X509_LOOKUP_add_dir   wolfSSL_X509_LOOKUP_add_dir
+#define CyaSSL_X509_LOOKUP_load_file wolfSSL_X509_LOOKUP_load_file
+#define CyaSSL_X509_LOOKUP_hash_dir  wolfSSL_X509_LOOKUP_hash_dir
+#define CyaSSL_X509_LOOKUP_file      wolfSSL_X509_LOOKUP_file
+
+#define CyaSSL_X509_STORE_add_lookup wolfSSL_X509_STORE_add_lookup
+#define CyaSSL_X509_STORE_new        wolfSSL_X509_STORE_new
+#define CyaSSL_X509_STORE_free       wolfSSL_X509_STORE_free
+#define CyaSSL_X509_STORE_add_cert   wolfSSL_X509_STORE_add_cert
+#define CyaSSL_X509_STORE_set_default_paths wolfSSL_X509_STORE_set_default_paths
+#define CyaSSL_X509_STORE_get_by_subject    wolfSSL_X509_STORE_get_by_subject
+#define CyaSSL_X509_STORE_CTX_new           wolfSSL_X509_STORE_CTX_new
+#define CyaSSL_X509_STORE_CTX_init          wolfSSL_X509_STORE_CTX_init
+#define CyaSSL_X509_STORE_CTX_free          wolfSSL_X509_STORE_CTX_free
+#define CyaSSL_X509_STORE_CTX_cleanup       wolfSSL_X509_STORE_CTX_cleanup
+
+#define CyaSSL_X509_CRL_get_lastUpdate wolfSSL_X509_CRL_get_lastUpdate
+#define CyaSSL_X509_CRL_get_nextUpdate wolfSSL_X509_CRL_get_nextUpdate
+
+#define CyaSSL_X509_get_pubkey wolfSSL_X509_get_pubkey
+#define CyaSSL_X509_CRL_verify wolfSSL_X509_CRL_verify
+#define CyaSSL_X509_STORE_CTX_set_error  wolfSSL_X509_STORE_CTX_set_error
+#define CyaSSL_X509_OBJECT_free_contents wolfSSL_X509_OBJECT_free_contents
+#define CyaSSL_EVP_PKEY_free             wolfSSL_EVP_PKEY_free
+#define CyaSSL_X509_cmp_current_time     wolfSSL_X509_cmp_current_time
+#define CyaSSL_sk_X509_REVOKED_num       wolfSSL_sk_X509_REVOKED_num
+
+#define CyaSSL_X509_CRL_get_REVOKED     wolfSSL_X509_CRL_get_REVOKED
+#define CyaSSL_sk_X509_REVOKED_value    wolfSSL_sk_X509_REVOKED_value
+#define CyaSSL_X509_get_serialNumber    wolfSSL_X509_get_serialNumber
+#define CyaSSL_ASN1_TIME_print          wolfSSL_ASN1_TIME_print
+#define CyaSSL_ASN1_INTEGER_cmp         wolfSSL_ASN1_INTEGER_cmp
+#define CyaSSL_ASN1_INTEGER_get         wolfSSL_ASN1_INTEGER_get
+#define CyaSSL_load_client_CA_file      wolfSSL_load_client_CA_file
+#define CyaSSL_CTX_set_client_CA_list   wolfSSL_CTX_set_client_CA_list
+#define CyaSSL_X509_STORE_CTX_get_ex_data     wolfSSL_X509_STORE_CTX_get_ex_data
+#define CyaSSL_get_ex_data_X509_STORE_CTX_idx wolfSSL_get_ex_data_X509_STORE_CTX_idx
+#define CyaSSL_get_ex_data                    wolfSSL_get_ex_data
+
+#define CyaSSL_CTX_set_default_passwd_cb_userdata wolfSSL_CTX_set_default_passwd_cb_userdata
+#define CyaSSL_CTX_set_default_passwd_cb          wolfSSL_CTX_set_default_passwd_cb
+#define CyaSSL_CTX_set_info_callback  wolfSSL_CTX_set_info_callback
+#define CyaSSL_ERR_peek_error         wolfSSL_ERR_peek_error
+#define CyaSSL_GET_REASON             wolfSSL_GET_REASON
+#define CyaSSL_alert_type_string_long wolfSSL_alert_type_string_long
+#define CyaSSL_alert_desc_string_long wolfSSL_alert_desc_string_long
+#define CyaSSL_state_string_long      wolfSSL_state_string_long
+
+#define CyaSSL_RSA_generate_key         wolfSSL_RSA_generate_key
+#define CyaSSL_CTX_set_tmp_rsa_callback wolfSSL_CTX_set_tmp_rsa_callback
+#define CyaSSL_PEM_def_callback         wolfSSL_PEM_def_callback
+#define CyaSSL_CTX_sess_accept          wolfSSL_CTX_sess_accept
+#define CyaSSL_CTX_sess_connect         wolfSSL_CTX_sess_connect
+#define CyaSSL_CTX_sess_accept_good     wolfSSL_CTX_sess_accept_good
+#define CyaSSL_CTX_sess_connect_good    wolfSSL_CTX_sess_connect_good
+#define CyaSSL_CTX_sess_accept_renegotiate  wolfSSL_CTX_sess_accept_renegotiate
+#define CyaSSL_CTX_sess_connect_renegotiate wolfSSL_CTX_sess_connect_renegotiate
+#define CyaSSL_CTX_sess_hits                wolfSSL_CTX_sess_hits
+#define CyaSSL_CTX_sess_cb_hits             wolfSSL_CTX_sess_cb_hits
+#define CyaSSL_CTX_sess_cache_full          wolfSSL_CTX_sess_cache_full
+#define CyaSSL_CTX_sess_misses              wolfSSL_CTX_sess_misses
+#define CyaSSL_CTX_sess_timeouts            wolfSSL_CTX_sess_timeouts
+#define CyaSSL_CTX_sess_number              wolfSSL_CTX_sess_number
+#define CyaSSL_CTX_sess_get_cache_size      wolfSSL_CTX_sess_get_cache_size
+
+
+
+/* src/keys.c */
+#define cyassl_triple_des wolfssl_triple_des
+
+/* Initialization and Shutdown */
+#define CyaSSL_Init         wolfSSL_Init
+#define CyaSSL_library_init wolfSSL_library_init
+#define CyaSSL_Cleanup      wolfSSL_Cleanup
+#define CyaSSL_shutdown     wolfSSL_shutdown
+
+/* Certs and keys */
+#define CyaSSL_SetTmpDH                     wolfSSL_SetTmpDH
+#define CyaSSL_KeepArrays                   wolfSSL_KeepArrays
+#define CyaSSL_FreeArrays                   wolfSSL_FreeArrays
+#define CyaSSL_SetTmpDH_file                wolfSSL_SetTmpDH_file
+#define CyaSSL_use_PrivateKey_buffer        wolfSSL_use_PrivateKey_buffer
+#define CyaSSL_use_certificate_buffer       wolfSSL_use_certificate_buffer
+#define CyaSSL_CTX_load_verify_buffer       wolfSSL_CTX_load_verify_buffer
+#define CyaSSL_CTX_use_PrivateKey_file      wolfSSL_CTX_use_PrivateKey_file
+#define CyaSSL_CTX_use_certificate_file     wolfSSL_CTX_use_certificate_file
+#define CyaSSL_CTX_use_PrivateKey_buffer    wolfSSL_CTX_use_PrivateKey_buffer
+#define CyaSSL_CTX_use_certificate_buffer   wolfSSL_CTX_use_certificate_buffer
+#define CyaSSL_CTX_use_NTRUPrivateKey_file  wolfSSL_CTX_use_NTRUPrivateKey_file
+#define CyaSSL_use_certificate_chain_buffer wolfSSL_use_certificate_chain_buffer
+#define CyaSSL_CTX_der_load_verify_locations    \
+                                            wolfSSL_CTX_der_load_verify_locations
+#define CyaSSL_CTX_use_certificate_chain_file   \
+                                            wolfSSL_CTX_use_certificate_chain_file
+#define CyaSSL_CTX_use_certificate_chain_buffer \
+                                            wolfSSL_CTX_use_certificate_chain_buffer
+
+/* Context and Session Setup*/
+#define CyaSSL_new                        wolfSSL_new
+#define CyaSSL_free                       wolfSSL_free
+#define CyaSSL_set_fd                     wolfSSL_set_fd
+#define CyaSSL_CTX_new                    wolfSSL_CTX_new
+#define CyaSSL_CTX_free                   wolfSSL_CTX_free
+#define CyaSSL_SetVersion                 wolfSSL_SetVersion
+#define CyaSSL_set_verify                 wolfSSL_set_verify
+#define CyaSSL_set_session                wolfSSL_set_session
+#define CyaSSL_set_timeout                wolfSSL_set_timeout
+#define CyaSSL_CTX_set_verify             wolfSSL_CTX_set_verify
+#define CyaSSL_CTX_set_timeout            wolfSSL_CTX_set_timeout
+#define CyaSSL_set_cipher_list            wolfSSL_set_cipher_list
+#define CyaSSL_set_compression            wolfSSL_set_compression
+#define CyaTLSv1_client_method            wolfTLSv1_client_method
+#define CyaTLSv1_server_method            wolfTLSv1_server_method
+#define CyaSSLv3_client_method            wolfSSLv3_client_method
+#define CyaSSLv3_server_method            wolfSSLv3_server_method
+#define CyaSSLv23_client_method           wolfSSLv23_client_method
+#define CyaSSLv23_server_method           wolfSSLv23_server_method
+#define CyaDTLSv1_client_method           wolfDTLSv1_client_method
+#define CyaDTLSv1_server_method           wolfDTLSv1_server_method
+#define CyaSSL_check_domain_name          wolfSSL_check_domain_name
+#define CyaTLSv1_1_client_method          wolfTLSv1_1_client_method
+#define CyaTLSv1_1_server_method          wolfTLSv1_1_server_method
+#define CyaTLSv1_2_client_method          wolfTLSv1_2_client_method
+#define CyaTLSv1_2_server_method          wolfTLSv1_2_server_method
+#define CyaDTLSv1_2_client_method         wolfDTLSv1_2_client_method
+#define CyaDTLSv1_2_server_method         wolfDTLSv1_2_server_method
+#define CyaSSL_set_group_messages         wolfSSL_set_group_messages
+#define CyaSSL_CTX_set_cipher_list        wolfSSL_CTX_set_cipher_list
+#define CyaSSL_CTX_set_group_messages     wolfSSL_CTX_set_group_messages
+#define CyaSSL_CTX_set_session_cache_mode wolfSSL_CTX_set_session_cache_mode
+
+/* Callbacks */
+
+/*
+ * Empty comment denotes not listed in CyaSSL Manual
+ * (soon to be wolfSSL Manual)
+ */
+
+#define CyaSSL_accept_ex              wolfSSL_accept_ex
+#define CyaSSL_SetIORecv              wolfSSL_CTX_SetIORecv
+#define CyaSSL_SetIOSend              wolfSSL_CTX_SetIOSend
+#define CyaSSL_connect_ex             wolfSSL_connect_ex
+#define CyaSSL_CTX_SetCACb            wolfSSL_CTX_SetCACb
+#define CyaSSL_SetIOReadCtx           wolfSSL_SetIOReadCtx
+#define CyaSSL_SetRsaEncCtx           wolfSSL_SetRsaEncCtx
+#define CyaSSL_GetRsaEncCtx           wolfSSL_GetRsaEncCtx
+#define CyaSSL_SetRsaDecCtx           wolfSSL_SetRsaDecCtx
+#define CyaSSL_GetRsaDecCtx           wolfSSL_GetRsaDecCtx
+#define CyaSSL_SetLoggingCb           wolfSSL_SetLoggingCb
+#define CyaSSL_SetEccSignCtx          wolfSSL_SetEccSignCtx
+#define CyaSSL_GetEccSignCtx          wolfSSL_GetEccSignCtx
+#define CyaSSL_SetRsaSignCtx          wolfSSL_SetRsaSignCtx
+#define CyaSSL_GetRsaSignCtx          wolfSSL_GetRsaSignCtx
+#define CyaSSL_SetIOWriteCtx          wolfSSL_SetIOWriteCtx
+#define CyaSSL_SetIOReadFlags         wolfSSL_SetIOReadFlags
+#define CyaSSL_SetEccVerifyCtx        wolfSSL_SetEccVerifyCtx
+#define CyaSSL_GetEccVerifyCtx        wolfSSL_GetEccVerifyCtx
+#define CyaSSL_SetRsaVerifyCtx        wolfSSL_SetRsaVerifyCtx
+#define CyaSSL_GetRsaVerifyCtx        wolfSSL_GetRsaVerifyCtx
+#define CyaSSL_CTX_SetRsaEncCb        wolfSSL_CTX_SetRsaEncCb
+#define CyaSSL_CTX_SetRsaDecCb        wolfSSL_CTX_SetRsaDecCb
+#define CyaSSL_SetIOWriteFlags        wolfSSL_SetIOWriteFlags
+#define CyaSSL_SetTlsHmacInner        wolfSSL_SetTlsHmacInner
+#define CyaSSL_SetMacEncryptCtx       wolfSSL_SetMacEncryptCtx
+#define CyaSSL_GetMacEncryptCtx       wolfSSL_GetMacEncryptCtx
+#define CyaSSL_CTX_SetEccSignCb       wolfSSL_CTX_SetEccSignCb
+#define CyaSSL_CTX_SetRsaSignCb       wolfSSL_CTX_SetRsaSignCb
+#define CyaSSL_CTX_SetEccVerifyCb     wolfSSL_CTX_SetEccVerifyCb
+#define CyaSSL_CTX_SetRsaVerifyCb     wolfSSL_CTX_SetRsaVerifyCb
+#define CyaSSL_CTX_SetMacEncryptCb    wolfSSL_CTX_SetMacEncryptCb
+#define CyaSSL_SetDecryptVerifyCtx    wolfSSL_SetDecryptVerifyCtx
+#define CyaSSL_GetDecryptVerifyCtx    wolfSSL_GetDecryptVerifyCtx
+#define CyaSSL_CTX_SetDecryptVerifyCb wolfSSL_CTX_SetDecryptVerifyCb
+
+/* psk specific */
+#ifndef NO_PSK
+
+#define CyaSSL_get_psk_identity          wolfSSL_get_psk_identity          /**/
+#define CyaSSL_get_psk_identity_hint     wolfSSL_get_psk_identity_hint     /**/
+#define CyaSSL_use_psk_identity_hint     wolfSSL_use_psk_identity_hint     /**/
+#define CyaSSL_set_psk_client_callback   wolfSSL_set_psk_client_callback   /**/
+#define CyaSSL_set_psk_server_callback   wolfSSL_set_psk_server_callback   /**/
+#define CyaSSL_CTX_use_psk_identity_hint wolfSSL_CTX_use_psk_identity_hint /**/
+#define CyaSSL_CTX_set_psk_client_callback \
+                                      wolfSSL_CTX_set_psk_client_callback  /**/
+#define CyaSSL_CTX_set_psk_server_callback \
+                                      wolfSSL_CTX_set_psk_server_callback  /**/
+
+#endif
+/* end psk specific */
+
+/* Anonymous */
+#define CyaSSL_CTX_allow_anon_cipher wolfSSL_CTX_allow_anon_cipher         /**/
+
+/* Error Handling and Debugging*/
+#define CyaSSL_get_error           wolfSSL_get_error
+#define CyaSSL_want_read           wolfSSL_want_read
+#define CyaSSL_want_write          wolfSSL_want_write
+#define CyaSSL_Debugging_ON        wolfSSL_Debugging_ON
+#define CyaSSL_Debugging_OFF       wolfSSL_Debugging_OFF
+#define CyaSSL_ERR_error_string    wolfSSL_ERR_error_string
+#define CyaSSL_load_error_strings  wolfSSL_load_error_strings
+#define CyaSSL_ERR_error_string_n  wolfSSL_ERR_error_string_n
+#define CyaSSL_ERR_print_errors_fp wolfSSL_ERR_print_errors_fp
+
+/* OCSP and CRL */
+
+/*
+ * Empty comment denotes not listed in CyaSSL Manual
+ * (soon to be wolfSSL Manual)
+ */
+
+#define CYASSL_CRL_MONITOR               WOLFSSL_CRL_MONITOR               /**/
+#define CYASSL_CRL_START_MON             WOLFSSL_CRL_START_MON             /**/
+#define CYASSL_OCSP_NO_NONCE             WOLFSSL_OCSP_NO_NONCE             /**/
+#define CYASSL_OCSP_URL_OVERRIDE         WOLFSSL_OCSP_URL_OVERRIDE
+#define CYASSL_OCSP_CHECKALL             WOLFSSL_OCSP_CHECKALL
+
+#define CyaSSL_CTX_EnableOCSP            wolfSSL_CTX_EnableOCSP
+#define CyaSSL_CTX_OCSP_set_options      wolfSSL_CTX_OCSP_set_options      /**/
+#define CyaSSL_CTX_SetOCSP_OverrideURL   wolfSSL_CTX_SetOCSP_OverrideURL   /**/
+#define CyaSSL_CTX_OCSP_set_override_url wolfSSL_CTX_OCSP_set_override_url /**/
+
+/* Informational */
+#define CyaSSL_GetSide            wolfSSL_GetSide
+#define CyaSSL_IsTLSv1_1          wolfSSL_IsTLSv1_1
+#define CyaSSL_GetKeySize         wolfSSL_GetKeySize
+#define CyaSSL_GetHmacSize        wolfSSL_GetHmacSize
+#define CyaSSL_GetHmacType        wolfSSL_GetHmacType
+#define CyaSSL_GetMacSecret       wolfSSL_GetMacSecret
+#define CyaSSL_GetObjectSize      wolfSSL_GetObjectSize
+#define CyaSSL_GetBulkCipher      wolfSSL_GetBulkCipher
+#define CyaSSL_GetCipherType      wolfSSL_GetCipherType
+#define CyaSSL_GetAeadMacSize     wolfSSL_GetAeadMacSize
+#define CyaSSL_GetClientWriteIV   wolfSSL_GetClientWriteIV
+#define CyaSSL_GetServerWriteIV   wolfSSL_GetServerWriteIV
+#define CyaSSL_GetClientWriteKey  wolfSSL_GetClientWriteKey
+#define CyaSSL_GetServerWriteKey  wolfSSL_GetServerWriteKey
+#define CyaSSL_GetCipherBlockSize wolfSSL_GetCipherBlockSize
+
+/* Connection, Session, and I/O */
+#define CyaSSL_peek               wolfSSL_peek
+#define CyaSSL_read               wolfSSL_read
+#define CyaSSL_recv               wolfSSL_recv
+#define CyaSSL_send               wolfSSL_send
+#define CyaSSL_write              wolfSSL_write
+#define CyaSSL_writev             wolfSSL_writev
+#define CyaSSL_accept             wolfSSL_accept
+#define CyaSSL_get_fd             wolfSSL_get_fd
+#define CyaSSL_connect            wolfSSL_connect
+#define CyaSSL_pending            wolfSSL_pending
+#define CyaSSL_negotiate          wolfSSL_negotiate
+#define CyaSSL_get_session        wolfSSL_get_session
+#define CyaSSL_connect_cert       wolfSSL_connect_cert
+#define CyaSSL_flush_sessions     wolfSSL_flush_sessions
+#define CyaSSL_get_using_nonblock wolfSSL_get_using_nonblock
+#define CyaSSL_PrintSessionStats  wolfSSL_PrintSessionStats
+
+/* DTLS Specific */
+#define CyaSSL_dtls                     wolfSSL_dtls
+#define CyaSSL_dtls_set_peer            wolfSSL_dtls_set_peer
+#define CyaSSL_dtls_get_peer            wolfSSL_dtls_get_peer
+#define CyaSSL_dtls_got_timeout         wolfSSL_dtls_got_timeout
+#define CyaSSL_dtls_get_current_timeout wolfSSL_dtls_get_current_timeout
+#define CyaSSL_set_using_nonblock       wolfSSL_dtls_set_using_nonblock
+
+/* Certificate Manager */
+#define CyaSSL_CertManagerNew          wolfSSL_CertManagerNew
+#define CyaSSL_CertManagerFree         wolfSSL_CertManagerFree
+#define CyaSSL_CertManagerLoadCA       wolfSSL_CertManagerLoadCA
+#define CyaSSL_CertManagerVerify       wolfSSL_CertManagerVerify
+#define CyaSSL_CertManagerEnableCRL    wolfSSL_CertManagerEnableCRL
+#define CyaSSL_CertManagerDisableCRL   wolfSSL_CertManagerDisableCRL
+#define CyaSSL_CertManagerVerifyBuffer wolfSSL_CertManagerVerifyBuffer
+#ifndef NO_CERTS
+	#define CyaSSL_CertManagerCheckCRL   wolfSSL_CertManagerCheckCRL
+	#define CyaSSL_CertManagerLoadCRL    wolfSSL_CertManagerLoadCRL
+	#define CyaSSL_CertManagerSetCRL_Cb  wolfSSL_CertManagerSetCRL_Cb
+	#define CyaSSL_CertManagerCheckOCSP  wolfSSL_CertManagerCheckOCSP
+	#define CyaSSL_CertManagerSetOCSP_Cb wolfSSL_CertManagerSetOCSP_Cb
+	#define CyaSSL_CertManagerSetOCSPOverrideURL \
+                                          wolfSSL_CertManagerSetOCSPOverrideURL
+
+	#define CyaSSL_DisableCRL          wolfSSL_DisableCRL
+	#define CyaSSL_EnableOCSP          wolfSSL_EnableOCSP
+	#define CyaSSL_DisableOCSP         wolfSSL_DisableOCSP
+	#define CyaSSL_SetOCSP_OverrideURL wolfSSL_SetOCSP_OverrideURL
+	#define CyaSSL_SetOCSP_Cb          wolfSSL_SetOCSP_Cb
+
+	#define CyaSSL_CTX_EnableCRL   wolfSSL_CTX_EnableCRL
+	#define CyaSSL_CTX_DisableCRL  wolfSSL_CTX_DisableCRL
+	#define CyaSSL_CTX_LoadCRL     wolfSSL_CTX_LoadCRL
+	#define CyaSSL_CTX_SetCRL_Cb   wolfSSL_CTX_SetCRL_Cb
+	#define CyaSSL_CTX_DisableOCSP wolfSSL_CTX_DisableOCSP
+	#define CyaSSL_CTX_SetOCSP_Cb  wolfSSL_CTX_SetOCSP_Cb
+#endif /* !NO_CERTS */
+
+
+/* OpenSSL Compatibility Layer */
+#define CyaSSL_get_sessionID              wolfSSL_get_sessionID
+#define CyaSSL_get_peer_count             wolfSSL_get_peer_count
+#define CyaSSL_get_chain_cert             wolfSSL_get_chain_cert
+#define CyaSSL_get_peer_chain             wolfSSL_get_peer_chain
+#define CyaSSL_get_peer_length            wolfSSL_get_peer_length
+#define CyaSSL_get_chain_cert_pem         wolfSSL_get_chain_cert_pem
+#define CyaSSL_use_PrivateKey_file        wolfSSL_use_PrivateKey_file
+#define CyaSSL_use_certificate_file       wolfSSL_use_certificate_file
+#define CyaSSL_use_RSAPrivateKey_file     wolfSSL_use_RSAPrivateKey_file
+#define CyaSSL_X509_get_serial_number     wolfSSL_X509_get_serial_number
+#define CyaSSL_CTX_use_RSAPrivateKey_file wolfSSL_CTX_use_RSAPrivateKey_file
+#define CyaSSL_use_certificate_chain_file wolfSSL_use_certificate_chain_file
+
+/* TLS Extensions */
+#define CYASSL_SNI_HOST_NAME         WOLFSSL_SNI_HOST_NAME
+
+#define CyaSSL_UseSNI                wolfSSL_UseSNI
+#define CyaSSL_CTX_UseSNI            wolfSSL_CTX_UseSNI
+#define CyaSSL_SNI_SetOptions        wolfSSL_SNI_SetOptions
+#define CyaSSL_SNI_GetRequest        wolfSSL_SNI_GetRequest
+#define CyaSSL_UseMaxFragment        wolfSSL_UseMaxFragment
+#define CyaSSL_UseTruncatedHMAC      wolfSSL_UseTruncatedHMAC
+#define CyaSSL_UseSupportedCurve     wolfSSL_UseSupportedCurve
+#define CyaSSL_SNI_GetFromBuffer     wolfSSL_SNI_GetFromBuffer
+#define CyaSSL_CTX_SNI_SetOptions    wolfSSL_CTX_SNI_SetOptions
+#define CyaSSL_CTX_UseMaxFragment    wolfSSL_CTX_UseMaxFragment
+#define CyaSSL_CTX_UseTruncatedHMAC  wolfSSL_CTX_UseTruncatedHMAC
+#define CyaSSL_CTX_UseSupportedCurve wolfSSL_CTX_UseSupportedCurve
+
+/* End wolfssl -> cyassl -> openssl compatibility */
+
+/* JRB macro redefinitions and api calls for cryptography for reverse compat. */
+
+#ifdef WOLFSSL_SMALL_STACK
+    #define CYASSL_SMALL_STACK
+#endif
+
+
+/*
+ * wrapper around macros until they are changed in cyassl code
+ * needs investigation in regards to macros in fips
+ */
+#define NO_WOLFSSL_ALLOC_ALIGN NO_CYASSL_ALLOC_ALIGN /* @TODO */
+
+
+/* examples/client/client.h */
+#define CYASSL_THREAD WOLFSSL_THREAD
+#ifdef WOLFSSL_DTLS
+    #define CYASSL_DTLS   WOLFSSL_DTLS
+#endif
+
+/* examples/client/client.c */
+#define LIBCYASSL_VERSION_STRING LIBWOLFSSL_VERSION_STRING
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+
+#endif /* CyaSSL_openssl_h__ */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/version.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/version.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/cyassl/version.h	(revision 453)
@@ -0,0 +1,27 @@
+/* cyassl/version.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#include <wolfssl/version.h>
+
+#define LIBCYASSL_VERSION_STRING LIBWOLFSSL_VERSION_STRING
+#define LIBCYASSL_VERSION_HEX LIBWOLFSSL_VERSION_HEX
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/bio.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/bio.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/bio.c	(revision 453)
@@ -0,0 +1,1705 @@
+/* bio.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#if !defined(WOLFSSL_BIO_INCLUDED)
+    #ifndef WOLFSSL_IGNORE_FILE_WARN
+        #warning bio.c does not need to be compiled separately from ssl.c
+    #endif
+#else
+
+
+/* Helper function to decode a base64 input
+ *
+ * returns size of resulting buffer on success
+ */
+static int wolfSSL_BIO_BASE64_read(WOLFSSL_BIO* bio, void* buf, int len)
+{
+    word32 frmtSz = len;
+
+    WOLFSSL_ENTER("wolfSSL_BIO_BASE64_read");
+
+    if (Base64_Decode((const byte*)buf, (word32)len, (byte*)buf, &frmtSz) !=0) {
+        WOLFSSL_MSG("Err doing base64 decode");
+        return SSL_FATAL_ERROR;
+    }
+
+    (void)bio;
+    return (int)frmtSz;
+}
+
+
+/* Helper function to read from WOLFSSL_BIO_BIO type
+ *
+ * returns amount in bytes read on success
+ */
+static int wolfSSL_BIO_BIO_read(WOLFSSL_BIO* bio, void* buf, int len)
+{
+    int   sz;
+    char* pt;
+
+    sz = wolfSSL_BIO_nread(bio, &pt, len);
+
+    if (sz > 0) {
+        XMEMCPY(buf, pt, sz);
+    }
+
+    return sz;
+}
+
+
+/* Handles reading from a memory type BIO and advancing the state.
+ *
+ * bio  WOLFSSL_BIO to read from
+ * buf  buffer to put data from bio in
+ * len  amount of data to be read
+ *
+ * returns size read on success
+ */
+static int wolfSSL_BIO_MEMORY_read(WOLFSSL_BIO* bio, void* buf, int len)
+{
+    int   sz;
+    WOLFSSL_ENTER("wolfSSL_BIO_MEMORY_read");
+
+    sz = wolfSSL_BIO_pending(bio);
+    if (sz > 0) {
+        const unsigned char* pt = NULL;
+        int memSz;
+
+        if (sz > len) {
+            sz = len;
+        }
+        memSz = wolfSSL_BIO_get_mem_data(bio, (void*)&pt);
+        if (memSz >= sz && pt != NULL) {
+            byte* tmp;
+
+            XMEMCPY(buf, (void*)pt, sz);
+            if (memSz - sz > 0) {
+                tmp = (byte*)XMALLOC(memSz-sz, bio->heap, DYNAMIC_TYPE_OPENSSL);
+                if (tmp == NULL) {
+                    WOLFSSL_MSG("Memory error");
+                    return WOLFSSL_BIO_ERROR;
+                }
+                XMEMCPY(tmp, (void*)(pt + sz), memSz - sz);
+
+                /* reset internal bio->mem */
+                XFREE(bio->ptr, bio->heap, DYNAMIC_TYPE_OPENSSL);
+                bio->ptr    = tmp;
+                bio->num = memSz-sz;
+                if (bio->mem_buf != NULL) {
+                    bio->mem_buf->data = (char*)bio->ptr;
+                    bio->mem_buf->length = bio->num;
+                }
+            }
+            bio->wrSz  -= sz;
+        }
+        else {
+            WOLFSSL_MSG("Issue with getting bio mem pointer");
+            return 0;
+        }
+    }
+    else {
+        return WOLFSSL_BIO_ERROR;
+    }
+
+    return sz;
+}
+
+#ifndef WOLFCRYPT_ONLY
+/* Helper function to read from WOLFSSL_BIO_SSL type
+ *
+ * returns the number of bytes read on success
+ */
+static int wolfSSL_BIO_SSL_read(WOLFSSL_BIO* bio, void* buf,
+        int len, WOLFSSL_BIO* front)
+{
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_BIO_SSL_read");
+
+    /* already got eof, again is error */
+    if ((front == NULL) || front->eof)
+        return WOLFSSL_FATAL_ERROR;
+
+    bio->flags &= ~(WOLFSSL_BIO_FLAG_RETRY); /* default no retry */
+    ret = wolfSSL_read((WOLFSSL*)bio->ptr, buf, len);
+    if (ret == 0)
+        front->eof = 1;
+    else if (ret < 0) {
+        int err = wolfSSL_get_error((WOLFSSL*)bio->ptr, 0);
+        if ( !(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) ) {
+            front->eof = 1;
+        }
+        else {
+            bio->flags |= WOLFSSL_BIO_FLAG_RETRY; /* should retry */
+        }
+    }
+
+    return ret;
+}
+
+static int wolfSSL_BIO_MD_read(WOLFSSL_BIO* bio, void* buf, int sz)
+{
+    int ret = sz;
+
+    if (wolfSSL_EVP_MD_CTX_type((WOLFSSL_EVP_MD_CTX*)bio->ptr) == NID_hmac) {
+        if (wolfSSL_EVP_DigestSignUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, buf,
+                        sz) != WOLFSSL_SUCCESS)
+        {
+            ret = WOLFSSL_FATAL_ERROR;
+        }
+    }
+    else {
+        if (wolfSSL_EVP_DigestUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, buf, ret)
+                != WOLFSSL_SUCCESS) {
+            ret = WOLFSSL_FATAL_ERROR;
+        }
+    }
+    return ret;
+}
+#endif /* WOLFCRYPT_ONLY */
+
+
+/* Used to read data from a WOLFSSL_BIO structure
+ *
+ * bio  structure to read data from
+ * buf  buffer to hold the result
+ * len  length of buf buffer
+ *
+ * returns the number of bytes read on success
+ */
+int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len)
+{
+    int  ret = 0;
+    WOLFSSL_BIO* front = bio;
+    int  sz  = 0;
+
+    WOLFSSL_ENTER("wolfSSL_BIO_read");
+
+    /* info cb, abort if user returns <= 0*/
+    if (front != NULL && front->infoCb != NULL) {
+        ret = (int)front->infoCb(front, WOLFSSL_BIO_CB_READ, (const char*)buf,
+                                                                     len, 0, 1);
+        if (ret <= 0) {
+            return ret;
+        }
+    }
+
+    /* start at end of list and work backwards */
+    while ((bio != NULL) && (bio->next != NULL)) {
+        bio = bio->next;
+    }
+
+    while (bio != NULL && ret >= 0) {
+        /* check for custom read */
+        if (bio->method && bio->method->readCb) {
+            ret = bio->method->readCb(bio, (char*)buf, len);
+        }
+
+        /* formatting data */
+        if (bio->type == WOLFSSL_BIO_BASE64 && ret > 0 && sz > 0) {
+            ret = wolfSSL_BIO_BASE64_read(bio, buf, sz);
+        }
+
+        /* write BIOs */
+        if (bio && bio->type == WOLFSSL_BIO_BIO) {
+            ret = wolfSSL_BIO_BIO_read(bio, buf, len);
+        }
+
+        if (bio && bio->type == WOLFSSL_BIO_MEMORY) {
+            ret = wolfSSL_BIO_MEMORY_read(bio, buf, len);
+        }
+
+    #ifndef NO_FILESYSTEM
+        if (bio && bio->type == WOLFSSL_BIO_FILE) {
+            ret = (int)XFREAD(buf, 1, len, (XFILE)bio->ptr);
+        }
+    #endif
+
+    #ifndef WOLFCRYPT_ONLY
+        if (bio && bio->type == WOLFSSL_BIO_SSL) {
+            ret = wolfSSL_BIO_SSL_read(bio, buf, len, front);
+        }
+
+        /* data passing through BIO MD wrapper */
+        if (bio && bio->type == WOLFSSL_BIO_MD && ret > 0) {
+            ret = wolfSSL_BIO_MD_read(bio, buf, ret);
+        }
+    #endif
+
+        /* case where front of list is done */
+        if (bio == front) {
+            break; /* at front of list so be done */
+        }
+
+        if (ret > 0) {
+            sz = ret; /* adjust size for formatting */
+        }
+
+        /* previous WOLFSSL_BIO in list working towards head of list */
+        bio = bio->prev;
+    }
+
+    /* info cb, user can override return value */
+    if (front != NULL && front->infoCb != NULL) {
+        ret = (int)front->infoCb(front,
+                                 WOLFSSL_BIO_CB_READ | WOLFSSL_BIO_CB_RETURN,
+                                 (const char*)buf, len, 0, ret);
+    }
+
+    return ret;
+}
+
+
+/* Converts data into base64 output
+ *
+ * returns the resulting buffer size on success.
+ */
+static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data,
+        word32 inLen, byte* out, word32* outLen)
+{
+    byte* tmp = NULL;
+    int ret   = 0;
+
+    WOLFSSL_ENTER("wolfSSL_BIO_BASE64_write");
+
+    if (bio == NULL || data == NULL || out == NULL || outLen == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#if defined(WOLFSSL_BASE64_ENCODE)
+    tmp = (byte*)XMALLOC(*outLen, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (tmp == NULL) {
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if ((bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) ==
+            WOLFSSL_BIO_FLAG_BASE64_NO_NL) {
+        if (Base64_Encode_NoNl((const byte*)data, inLen,
+                tmp, outLen) < 0) {
+            ret = WOLFSSL_FATAL_ERROR;
+        }
+    }
+    else {
+        if (Base64_Encode((const byte*)data, inLen,
+                tmp, outLen) < 0) {
+            ret = WOLFSSL_FATAL_ERROR;
+        }
+    }
+
+    if (ret != WOLFSSL_FATAL_ERROR) {
+        ret = (int) inLen;
+        XMEMCPY(out, tmp, *outLen);
+
+    }
+    XFREE(tmp, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#else
+    (void)bio;
+    (void)data;
+    (void)inLen;
+    (void)out;
+    (void)outLen;
+    (void)tmp;
+    WOLFSSL_MSG("BASE64 encoding not compiled in");
+#endif
+    return ret;
+}
+
+
+#ifndef WOLFCRYPT_ONLY
+/* Helper function for writing to a WOLFSSL_BIO_SSL type
+ *
+ * returns the amount written in bytes on success
+ */
+static int wolfSSL_BIO_SSL_write(WOLFSSL_BIO* bio, const void* data,
+        int len, WOLFSSL_BIO* front)
+{
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_BIO_SSL_write");
+
+    if (bio->ptr == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    bio->flags &= ~(WOLFSSL_BIO_FLAG_RETRY); /* default no retry */
+    ret = wolfSSL_write((WOLFSSL*)bio->ptr, data, len);
+    if (ret == 0)
+        front->eof = 1;
+    else if (ret < 0) {
+        int err = wolfSSL_get_error((WOLFSSL*)bio->ptr, 0);
+        if ( !(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) ) {
+            front->eof = 1;
+        }
+        else {
+            bio->flags |= WOLFSSL_BIO_FLAG_RETRY; /* should retry */
+        }
+    }
+    return ret;
+}
+#endif /* WOLFCRYPT_ONLY */
+
+
+/* Writes to a WOLFSSL_BIO_BIO type.
+ *
+ * returns the amount written on success
+ */
+static int wolfSSL_BIO_BIO_write(WOLFSSL_BIO* bio, const void* data,
+        int len)
+{
+    int   sz;
+    char* buf;
+
+    WOLFSSL_ENTER("wolfSSL_BIO_BIO_write");
+
+    /* adding in sanity checks for static analysis tools */
+    if (bio == NULL || data == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    sz = wolfSSL_BIO_nwrite(bio, &buf, len);
+
+    /* test space for write */
+    if (sz <= 0) {
+        WOLFSSL_MSG("No room left to write");
+        return sz;
+    }
+
+    XMEMCPY(buf, data, sz);
+
+    return sz;
+}
+
+
+/* for complete compatibility a bio memory write allocs its own memory
+ * until the application runs out ....
+ *
+ * bio  structure to hold incoming data
+ * data buffer holding the data to be written
+ * len  length of data buffer
+ *
+ * returns the amount of data written on success and WOLFSSL_FAILURE or
+ *         WOLFSSL_BIO_ERROR for failure cases.
+ */
+static int wolfSSL_BIO_MEMORY_write(WOLFSSL_BIO* bio, const void* data,
+        int len)
+{
+    int   sz;
+    const unsigned char* buf;
+
+    WOLFSSL_ENTER("wolfSSL_BIO_MEMORY_write");
+
+    if (bio == NULL || data == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    sz = wolfSSL_BIO_pending(bio);
+    if (sz < 0) {
+        WOLFSSL_MSG("Error getting memory data");
+        return sz;
+    }
+
+    if (bio->ptr == NULL) {
+        bio->ptr = (byte*)XMALLOC(len, bio->heap, DYNAMIC_TYPE_OPENSSL);
+        if (bio->ptr == NULL) {
+            WOLFSSL_MSG("Error on malloc");
+            return WOLFSSL_FAILURE;
+        }
+        bio->num = len;
+        if (bio->mem_buf != NULL) {
+            bio->mem_buf->data = (char*)bio->ptr;
+            bio->mem_buf->length = bio->num;
+        }
+    }
+
+    /* check if will fit in current buffer size */
+    if (wolfSSL_BIO_get_mem_data(bio, (void*)&buf) < 0) {
+        return WOLFSSL_BIO_ERROR;
+    }
+    if (bio->num < sz + len) {
+        bio->ptr = (byte*)XREALLOC(bio->ptr, sz + len, bio->heap,
+            DYNAMIC_TYPE_OPENSSL);
+        if (bio->ptr == NULL) {
+            WOLFSSL_MSG("Error on realloc");
+            return WOLFSSL_FAILURE;
+        }
+        bio->num = sz + len;
+        if (bio->mem_buf != NULL) {
+            bio->mem_buf->data = (char*)bio->ptr;
+            bio->mem_buf->length = bio->num;
+        }
+    }
+
+    XMEMCPY((byte*)bio->ptr + sz, data, len);
+    bio->wrSz += len;
+
+    return len;
+}
+
+
+#ifndef WOLFCRYPT_ONLY
+/* Helper function for writing to a WOLFSSL_BIO_MD type
+ *
+ * returns the amount written in bytes on success (0)
+ */
+static int wolfSSL_BIO_MD_write(WOLFSSL_BIO* bio, const void* data, int len)
+{
+    int ret = 0;
+
+    if (bio == NULL || data == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (wolfSSL_EVP_MD_CTX_type((WOLFSSL_EVP_MD_CTX*)bio->ptr) == NID_hmac) {
+        if (wolfSSL_EVP_DigestSignUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, data,
+                    len) != WOLFSSL_SUCCESS) {
+            ret = WOLFSSL_BIO_ERROR;
+        }
+    }
+    else {
+        if (wolfSSL_EVP_DigestUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, data, len)
+                != WOLFSSL_SUCCESS) {
+            ret =  WOLFSSL_BIO_ERROR;
+        }
+    }
+    return ret;
+}
+#endif /* WOLFCRYPT_ONLY */
+
+
+/* Writes data to a WOLFSSL_BIO structure
+ *
+ * bio  structure to write to
+ * data holds the data to be written
+ * len  length of data buffer
+ *
+ * returns the amount written in bytes on success
+ */
+int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len)
+{
+    int  ret = 0;
+    int  retB64 = 0;
+    WOLFSSL_BIO* front = bio;
+    void*  frmt   = NULL;
+    word32 frmtSz = 0;
+
+    WOLFSSL_ENTER("wolfSSL_BIO_write");
+
+    /* info cb, abort if user returns <= 0*/
+    if (front != NULL && front->infoCb != NULL) {
+        ret = (int)front->infoCb(front, WOLFSSL_BIO_CB_WRITE,
+                (const char*)data, len, 0, 1);
+        if (ret <= 0) {
+            return ret;
+        }
+    }
+
+    while (bio != NULL && ret >= 0) {
+        /* check for custom write */
+        if (bio->method && bio->method->writeCb) {
+            ret = bio->method->writeCb(bio, (const char*)data, len);
+        }
+
+        /* check for formatting */
+        if (bio->type == WOLFSSL_BIO_BASE64) {
+#if defined(WOLFSSL_BASE64_ENCODE)
+            word32 sz = 0;
+
+            if (bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) {
+                if (Base64_Encode_NoNl((const byte*)data, len, NULL,
+                            &sz) != LENGTH_ONLY_E) {
+                    WOLFSSL_MSG("Error with base 64 get length");
+                    ret = SSL_FATAL_ERROR;
+                }
+            }
+            else {
+                if (Base64_Encode((const byte*)data, len, NULL, &sz) !=
+                    LENGTH_ONLY_E) {
+                    WOLFSSL_MSG("Error with base 64 get length");
+                    ret = SSL_FATAL_ERROR;
+                }
+            }
+
+            if (frmt == NULL && sz > 0 && ret != SSL_FATAL_ERROR) {
+                frmt = (void*)XMALLOC(sz, front->heap,
+                        DYNAMIC_TYPE_TMP_BUFFER);
+                if (frmt == NULL) {
+                    WOLFSSL_MSG("Memory error");
+                    ret = SSL_FATAL_ERROR;
+                }
+                frmtSz = sz;
+            }
+            else if (sz > frmtSz) {
+                frmt = (void*)XREALLOC(frmt, sz, front->heap,
+                        DYNAMIC_TYPE_TMP_BUFFER);
+                if (frmt == NULL) {
+                    WOLFSSL_MSG("Memory error");
+                    ret = SSL_FATAL_ERROR;
+                }
+                /* since frmt already existed then data should point to knew
+                   formatted buffer */
+                data = frmt;
+                len  = frmtSz;
+                frmtSz = sz;
+            }
+#endif /* defined(WOLFSSL_BASE64_ENCODE) */
+
+            if (ret >= 0) {
+                /* change so that data is formatted buffer */
+                retB64 = wolfSSL_BIO_BASE64_write(bio, data, (word32)len,
+                         (byte*)frmt, &frmtSz);
+                data = frmt;
+                len  = frmtSz;
+            }
+        }
+
+        /* write bios */
+        if (bio && bio->type == WOLFSSL_BIO_BIO) {
+            ret = wolfSSL_BIO_BIO_write(bio, data, len);
+        }
+
+        if (bio && bio->type == WOLFSSL_BIO_MEMORY) {
+            ret = wolfSSL_BIO_MEMORY_write(bio, data, len);
+        }
+
+    #ifndef NO_FILESYSTEM
+        if (bio && bio->type == WOLFSSL_BIO_FILE) {
+            ret = (int)XFWRITE(data, 1, len, (XFILE)bio->ptr);
+        }
+    #endif
+
+    #ifndef WOLFCRYPT_ONLY
+        if (bio && bio->type == WOLFSSL_BIO_SSL) {
+            /* already got eof, again is error */
+            if (front->eof) {
+                ret = SSL_FATAL_ERROR;
+            }
+            else {
+                ret = wolfSSL_BIO_SSL_write(bio, data, len, front);
+            }
+        }
+
+        if (bio && bio->type == WOLFSSL_BIO_MD) {
+            if (bio->next != NULL) { /* data passing through MD BIO */
+                ret = wolfSSL_BIO_MD_write(bio, data, len);
+            }
+        }
+    #endif /* WOLFCRYPT_ONLY */
+
+        /* advance to the next bio in list */
+        bio = bio->next;
+    }
+
+    if (frmt != NULL) {
+        XFREE(frmt, front->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+
+    /* info cb, user can override return value */
+    if (front != NULL && front->infoCb != NULL) {
+        ret = (int)front->infoCb(front,
+                                 WOLFSSL_BIO_CB_WRITE | WOLFSSL_BIO_CB_RETURN,
+                                 (const char*)data, 0, 0, ret);
+    }
+
+    if (retB64 != 0)
+        return retB64;
+    else
+        return ret;
+}
+
+
+/* Wrapper for other BIO type functions, expected to grow as OpenSSL compatibility
+ * layer grows.
+ *
+ * return info. specific to the cmd that is passed in.
+ */
+#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
+long wolfSSL_BIO_ctrl(WOLFSSL_BIO *bio, int cmd, long larg, void *parg)
+{
+    long ret;
+
+    (void)larg; /* not currently used */
+
+    WOLFSSL_ENTER("wolfSSL_BIO_ctrl");
+
+    if (bio && bio->method && bio->method->ctrlCb) {
+        return bio->method->ctrlCb(bio, cmd, larg, parg);
+    }
+
+    switch(cmd) {
+        case BIO_CTRL_PENDING:
+        case BIO_CTRL_WPENDING:
+            ret = (long)wolfSSL_BIO_ctrl_pending(bio);
+            break;
+        case BIO_CTRL_INFO:
+            ret = (long)wolfSSL_BIO_get_mem_data(bio, parg);
+            break;
+        case BIO_CTRL_FLUSH:
+            ret = (long)wolfSSL_BIO_flush(bio);
+            break;
+        case BIO_CTRL_RESET:
+            ret = (long)wolfSSL_BIO_reset(bio);
+            break;
+        default:
+            WOLFSSL_MSG("CMD not yet implemented");
+            ret = WOLFSSL_FAILURE;
+            break;
+    }
+    return ret;
+}
+#endif
+
+
+/* helper function for wolfSSL_BIO_gets
+ * size till a newline is hit
+ * returns the number of bytes including the new line character
+ */
+static int wolfSSL_getLineLength(char* in, int inSz)
+{
+    int i;
+
+    for (i = 0; i < inSz; i++) {
+        if (in[i] == '\n') {
+            return i + 1; /* includes new line character */
+        }
+    }
+
+    return inSz; /* rest of buffer is all one line */
+}
+
+
+/* Gets the next line from bio. Goes until a new line character or end of
+ * buffer is reached.
+ *
+ * bio  the structure to read a new line from
+ * buf  buffer to hold the result
+ * sz   the size of "buf" buffer
+ *
+ * returns the size of the result placed in buf on success and a 0 or negative
+ *         value in an error case.
+ */
+int wolfSSL_BIO_gets(WOLFSSL_BIO* bio, char* buf, int sz)
+{
+    int ret = WOLFSSL_BIO_UNSET;
+
+    WOLFSSL_ENTER("wolfSSL_BIO_gets");
+
+    if (bio == NULL || buf == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* not enough space for character plus terminator */
+    if (sz <= 1) {
+        return 0;
+    }
+
+    /* info cb, abort if user returns <= 0*/
+    if (bio->infoCb != NULL) {
+        ret = (int)bio->infoCb(bio, WOLFSSL_BIO_CB_GETS, buf, sz, 0, 1);
+        if (ret <= 0) {
+            return ret;
+        }
+    }
+
+    /* check if is custom method */
+    if (bio->method && bio->method->getsCb) {
+        return bio->method->getsCb(bio, buf, sz);
+    }
+
+    switch (bio->type) {
+#ifndef NO_FILESYSTEM
+        case WOLFSSL_BIO_FILE:
+            if (((XFILE)bio->ptr) == XBADFILE) {
+                return WOLFSSL_BIO_ERROR;
+            }
+
+            #if defined(MICRIUM) || defined(LSR_FS) || defined(EBSNET)
+            WOLFSSL_MSG("XFGETS not ported for this system yet");
+            ret = XFGETS(buf, sz, (XFILE)bio->ptr);
+            #else
+            if (XFGETS(buf, sz, (XFILE)bio->ptr) != NULL) {
+                ret = (int)XSTRLEN(buf);
+            }
+            else {
+                ret = WOLFSSL_BIO_ERROR;
+            }
+            #endif
+            break;
+#endif /* NO_FILESYSTEM */
+        case WOLFSSL_BIO_MEMORY:
+            {
+                const byte* c;
+                int   cSz;
+                cSz = wolfSSL_BIO_pending(bio);
+                if (cSz == 0) {
+                    ret = 0; /* Nothing to read */
+                    buf[0] = '\0';
+                    break;
+                }
+
+                if (wolfSSL_BIO_get_mem_data(bio, (void*)&c) <= 0) {
+                    ret = WOLFSSL_BIO_ERROR;
+                    break;
+                }
+
+                cSz = wolfSSL_getLineLength((char*)c, cSz);
+                /* check case where line was bigger then buffer and buffer
+                 * needs end terminator */
+                if (cSz >= sz) {
+                    cSz = sz - 1;
+                    buf[cSz] = '\0';
+                }
+                else {
+                    /* not minus 1 here because placing terminator after
+                       msg and have checked that sz is large enough */
+                    buf[cSz] = '\0';
+                }
+
+                ret = wolfSSL_BIO_MEMORY_read(bio, (void*)buf, cSz);
+                /* ret is read after the switch statement */
+                break;
+            }
+        case WOLFSSL_BIO_BIO:
+            {
+                char* c;
+                int   cSz;
+                cSz = wolfSSL_BIO_nread0(bio, &c);
+                if (cSz == 0) {
+                    ret = 0; /* Nothing to read */
+                    buf[0] = '\0';
+                    break;
+                }
+
+                cSz = wolfSSL_getLineLength(c, cSz);
+                /* check case where line was bigger then buffer and buffer
+                 * needs end terminator */
+                if (cSz >= sz) {
+                    cSz = sz - 1;
+                    buf[cSz] = '\0';
+                }
+                else {
+                    /* not minus 1 here because placing terminator after
+                       msg and have checked that sz is large enough */
+                    buf[cSz] = '\0';
+                }
+
+                ret = wolfSSL_BIO_nread(bio, &c, cSz);
+                if (ret > 0 && ret < sz) {
+                    XMEMCPY(buf, c, ret);
+                }
+                break;
+            }
+
+#ifndef WOLFCRYPT_ONLY
+        /* call final on hash */
+        case WOLFSSL_BIO_MD:
+            if (wolfSSL_EVP_MD_CTX_size((WOLFSSL_EVP_MD_CTX*)bio->ptr) > sz) {
+                WOLFSSL_MSG("Output buffer was too small for digest");
+                ret = WOLFSSL_FAILURE;
+            }
+            else {
+                unsigned int szOut = 0;
+                ret = wolfSSL_EVP_DigestFinal((WOLFSSL_EVP_MD_CTX*)bio->ptr,
+                        (unsigned char*)buf, &szOut);
+                if (ret == WOLFSSL_SUCCESS) {
+                    ret = szOut;
+                }
+            }
+            break;
+#endif /* WOLFCRYPT_ONLY */
+
+        default:
+            WOLFSSL_MSG("BIO type not supported yet with wolfSSL_BIO_gets");
+    }
+
+    /* info cb, user can override return value */
+    if (bio->infoCb != NULL) {
+        ret = (int)bio->infoCb(bio, WOLFSSL_BIO_CB_GETS | WOLFSSL_BIO_CB_RETURN,
+                               buf, sz, 0, ret);
+    }
+
+    return ret;
+}
+
+
+/* Writes a null terminated string to bio.
+ *
+ * bio  the structure to write to
+ * buf  buffer to holding input string
+ *
+ * returns the size of the result placed in bio on success and a 0 or negative
+ *         value in an error case. -2 is returned if the implementation is not
+ *         supported for the BIO type.
+ */
+int wolfSSL_BIO_puts(WOLFSSL_BIO* bio, const char* buf)
+{
+    int sz;
+
+    if (bio == NULL || buf == NULL) {
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    /* check if is custom method */
+    if (bio->method && bio->method->putsCb) {
+        return bio->method->putsCb(bio, buf);
+    }
+
+    sz = (int)XSTRLEN(buf);
+    if (sz <= 0) {
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    return wolfSSL_BIO_write(bio, buf, sz);
+}
+
+
+/* searches through bio list for a BIO of type "type"
+ * returns NULL on failure to find a given type */
+WOLFSSL_BIO* wolfSSL_BIO_find_type(WOLFSSL_BIO* bio, int type)
+{
+    WOLFSSL_BIO* local = NULL;
+    WOLFSSL_BIO* current;
+
+    WOLFSSL_ENTER("wolfSSL_BIO_find_type");
+
+    if (bio == NULL) {
+        return local;
+    }
+
+    current = bio;
+    while (current != NULL) {
+        if (current->type == type) {
+            WOLFSSL_MSG("Found matching WOLFSSL_BIO type");
+            local = current;
+            break;
+        }
+        current = current->next;
+    }
+
+    return local;
+}
+
+
+/* returns a pointer to the next WOLFSSL_BIO in the chain on success.
+ * If a failure case then NULL is returned */
+WOLFSSL_BIO* wolfSSL_BIO_next(WOLFSSL_BIO* bio)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_next");
+
+    if (bio == NULL) {
+        WOLFSSL_MSG("Bad argument passed in");
+        return NULL;
+    }
+
+    return bio->next;
+}
+
+/* BIO_wpending returns the number of bytes pending to be written. */
+size_t wolfSSL_BIO_wpending(const WOLFSSL_BIO *bio)
+{
+    WOLFSSL_ENTER("BIO_wpending");
+
+    if (bio == NULL)
+        return 0;
+
+    if (bio->type == WOLFSSL_BIO_MEMORY) {
+        return bio->wrSz;
+    }
+
+    /* type BIO_BIO then check paired buffer */
+    if (bio->type == WOLFSSL_BIO_BIO && bio->pair != NULL) {
+        WOLFSSL_BIO* pair = bio->pair;
+        return pair->wrIdx;
+    }
+
+    return 0;
+}
+
+/* Return the number of pending bytes in read and write buffers */
+size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *bio)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_ctrl_pending");
+    if (bio == NULL) {
+        return 0;
+    }
+
+    if (bio->type == WOLFSSL_BIO_MD) {
+        /* MD is a wrapper only get next bio */
+        while (bio->next != NULL) {
+            bio = bio->next;
+            if (bio->type != WOLFSSL_BIO_MD) {
+                break;
+            }
+        }
+    }
+
+#ifndef WOLFCRYPT_ONLY
+    if (bio->type == WOLFSSL_BIO_SSL && bio->ptr != NULL) {
+        return (long)wolfSSL_pending((WOLFSSL*)bio->ptr);
+    }
+#endif
+
+    if (bio->type == WOLFSSL_BIO_MEMORY) {
+        return bio->wrSz;
+    }
+
+    /* type BIO_BIO then check paired buffer */
+    if (bio->type == WOLFSSL_BIO_BIO && bio->pair != NULL) {
+        WOLFSSL_BIO* pair = bio->pair;
+        if (pair->wrIdx > 0 && pair->wrIdx <= pair->rdIdx) {
+            /* in wrap around state where beginning of buffer is being
+             * overwritten */
+            return pair->wrSz - pair->rdIdx + pair->wrIdx;
+        }
+        else {
+            /* simple case where has not wrapped around */
+            return pair->wrIdx - pair->rdIdx;
+        }
+    }
+    return 0;
+}
+
+
+long wolfSSL_BIO_get_mem_ptr(WOLFSSL_BIO *bio, WOLFSSL_BUF_MEM **ptr)
+{
+    WOLFSSL_BIO* front = bio;
+    long ret = WOLFSSL_FAILURE;
+
+    WOLFSSL_ENTER("wolfSSL_BIO_get_mem_ptr");
+
+    if (bio == NULL || ptr == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* start at end and work backwards to find a memory BIO in the BIO chain */
+    while ((bio != NULL) && (bio->next != NULL)) {
+        bio = bio->next;
+    }
+
+    while (bio != NULL) {
+
+        if (bio->type == WOLFSSL_BIO_MEMORY) {
+            *ptr = bio->mem_buf;
+            ret = WOLFSSL_SUCCESS;
+        }
+
+        if (bio == front) {
+            break;
+        }
+        bio = bio->prev;
+    }
+
+    return ret;
+}
+
+WOLFSSL_API long wolfSSL_BIO_int_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, int iarg)
+{
+    (void) bp;
+    (void) cmd;
+    (void) larg;
+    (void) iarg;
+    WOLFSSL_STUB("BIO_int_ctrl");
+    return 0;
+}
+
+
+int wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *bio, long size)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_set_write_buf_size");
+
+    if (bio == NULL || bio->type != WOLFSSL_BIO_BIO || size < 0) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* if already in pair then do not change size */
+    if (bio->pair != NULL) {
+        WOLFSSL_MSG("WOLFSSL_BIO is paired, free from pair before changing");
+        return WOLFSSL_FAILURE;
+    }
+
+    bio->wrSz  = (int)size;
+    if (bio->wrSz < 0) {
+        WOLFSSL_MSG("Unexpected negative size value");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (bio->ptr != NULL) {
+        XFREE(bio->ptr, bio->heap, DYNAMIC_TYPE_OPENSSL);
+    }
+
+    bio->ptr = (byte*)XMALLOC(bio->wrSz, bio->heap, DYNAMIC_TYPE_OPENSSL);
+    if (bio->ptr == NULL) {
+        WOLFSSL_MSG("Memory allocation error");
+        return WOLFSSL_FAILURE;
+    }
+    bio->num = bio->wrSz;
+    bio->wrIdx = 0;
+    bio->rdIdx = 0;
+    if (bio->mem_buf != NULL) {
+        bio->mem_buf->data = (char*)bio->ptr;
+        bio->mem_buf->length = bio->num;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* Joins two BIO_BIO types. The write of b1 goes to the read of b2 and vice
+ * versa. Creating something similar to a two way pipe.
+ * Reading and writing between the two BIOs is not thread safe, they are
+ * expected to be used by the same thread. */
+int wolfSSL_BIO_make_bio_pair(WOLFSSL_BIO *b1, WOLFSSL_BIO *b2)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_make_bio_pair");
+
+    if (b1 == NULL || b2 == NULL) {
+        WOLFSSL_LEAVE("wolfSSL_BIO_make_bio_pair", BAD_FUNC_ARG);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* both are expected to be of type BIO and not already paired */
+    if (b1->type != WOLFSSL_BIO_BIO || b2->type != WOLFSSL_BIO_BIO ||
+        b1->pair != NULL || b2->pair != NULL) {
+        WOLFSSL_MSG("Expected type BIO and not already paired");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* set default write size if not already set */
+    if (b1->ptr == NULL && wolfSSL_BIO_set_write_buf_size(b1,
+                            WOLFSSL_BIO_SIZE) != WOLFSSL_SUCCESS) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if (b2->ptr == NULL && wolfSSL_BIO_set_write_buf_size(b2,
+                            WOLFSSL_BIO_SIZE) != WOLFSSL_SUCCESS) {
+        return WOLFSSL_FAILURE;
+    }
+
+    b1->pair = b2;
+    b2->pair = b1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_BIO_ctrl_reset_read_request(WOLFSSL_BIO *b)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_ctrl_reset_read_request");
+
+    if (b == NULL || b->type == WOLFSSL_BIO_MEMORY) {
+        return SSL_FAILURE;
+    }
+
+    b->readRq = 0;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* Does not advance read index pointer */
+int wolfSSL_BIO_nread0(WOLFSSL_BIO *bio, char **buf)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_nread0");
+
+    if (bio == NULL || buf == NULL) {
+        WOLFSSL_MSG("NULL argument passed in");
+        return 0;
+    }
+
+    /* if paired read from pair */
+    if (bio->pair != NULL) {
+        WOLFSSL_BIO* pair = bio->pair;
+
+        /* case where have wrapped around write buffer */
+        *buf = (char*)pair->ptr + pair->rdIdx;
+        if (pair->wrIdx > 0 && pair->rdIdx >= pair->wrIdx) {
+            return pair->wrSz - pair->rdIdx;
+        }
+        else {
+            return pair->wrIdx - pair->rdIdx;
+        }
+    }
+
+    return 0;
+}
+
+
+/* similar to wolfSSL_BIO_nread0 but advances the read index */
+int wolfSSL_BIO_nread(WOLFSSL_BIO *bio, char **buf, int num)
+{
+    int sz = WOLFSSL_BIO_UNSET;
+
+    WOLFSSL_ENTER("wolfSSL_BIO_nread");
+
+    if (bio == NULL || buf == NULL) {
+        WOLFSSL_MSG("NULL argument passed in");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (bio->type == WOLFSSL_BIO_MEMORY) {
+        return SSL_FAILURE;
+    }
+
+    if (bio->pair != NULL) {
+        /* special case if asking to read 0 bytes */
+        if (num == 0) {
+            *buf = (char*)bio->pair->ptr + bio->pair->rdIdx;
+            return 0;
+        }
+
+        /* get amount able to read and set buffer pointer */
+        sz = wolfSSL_BIO_nread0(bio, buf);
+        if (sz == 0) {
+            return WOLFSSL_BIO_ERROR;
+        }
+
+        if (num < sz) {
+            sz = num;
+        }
+        bio->pair->rdIdx += sz;
+
+        /* check if have read to the end of the buffer and need to reset */
+        if (bio->pair->rdIdx == bio->pair->wrSz) {
+            bio->pair->rdIdx = 0;
+            if (bio->pair->wrIdx == bio->pair->wrSz) {
+                bio->pair->wrIdx = 0;
+            }
+        }
+
+        /* check if read up to write index, if so then reset index */
+        if (bio->pair->rdIdx == bio->pair->wrIdx) {
+            bio->pair->rdIdx = 0;
+            bio->pair->wrIdx = 0;
+        }
+    }
+
+    return sz;
+}
+
+
+int wolfSSL_BIO_nwrite(WOLFSSL_BIO *bio, char **buf, int num)
+{
+    int sz = WOLFSSL_BIO_UNSET;
+
+    WOLFSSL_ENTER("wolfSSL_BIO_nwrite");
+
+    if (bio == NULL || buf == NULL) {
+        WOLFSSL_MSG("NULL argument passed in");
+        return 0;
+    }
+
+    if (bio->type != WOLFSSL_BIO_BIO) {
+        return SSL_FAILURE;
+    }
+
+    if (bio->pair != NULL) {
+        if (num == 0) {
+            *buf = (char*)bio->ptr + bio->wrIdx;
+            return 0;
+        }
+
+        if (bio->wrIdx < bio->rdIdx) {
+            /* if wrapped around only write up to read index. In this case
+             * rdIdx is always greater then wrIdx so sz will not be negative. */
+            sz = bio->rdIdx - bio->wrIdx;
+        }
+        else if (bio->rdIdx > 0 && bio->wrIdx == bio->rdIdx) {
+            return WOLFSSL_BIO_ERROR; /* no more room to write */
+        }
+        else {
+            /* write index is past read index so write to end of buffer */
+            sz = bio->wrSz - bio->wrIdx;
+
+            if (sz <= 0) {
+                /* either an error has occurred with write index or it is at the
+                 * end of the write buffer. */
+                if (bio->rdIdx == 0) {
+                    /* no more room, nothing has been read */
+                    return WOLFSSL_BIO_ERROR;
+                }
+
+                bio->wrIdx = 0;
+
+                /* check case where read index is not at 0 */
+                if (bio->rdIdx > 0) {
+                    sz = bio->rdIdx; /* can write up to the read index */
+                }
+                else {
+                    sz = bio->wrSz; /* no restriction other then buffer size */
+                }
+            }
+        }
+
+        if (num < sz) {
+            sz = num;
+        }
+        *buf = (char*)bio->ptr + bio->wrIdx;
+        bio->wrIdx += sz;
+
+        /* if at the end of the buffer and space for wrap around then set
+         * write index back to 0 */
+        if (bio->wrIdx == bio->wrSz && bio->rdIdx > 0) {
+            bio->wrIdx = 0;
+        }
+    }
+
+    return sz;
+}
+
+
+/* Reset BIO to initial state */
+int wolfSSL_BIO_reset(WOLFSSL_BIO *bio)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_reset");
+
+    if (bio == NULL) {
+        WOLFSSL_MSG("NULL argument passed in");
+        /* -1 is consistent failure even for FILE type */
+        return WOLFSSL_BIO_ERROR;
+    }
+
+    switch (bio->type) {
+        #ifndef NO_FILESYSTEM
+        case WOLFSSL_BIO_FILE:
+            XREWIND((XFILE)bio->ptr);
+            return 0;
+        #endif
+
+        case WOLFSSL_BIO_BIO:
+            bio->rdIdx = 0;
+            bio->wrIdx = 0;
+            return 0;
+
+        case WOLFSSL_BIO_MEMORY:
+            bio->rdIdx = 0;
+            bio->wrIdx = 0;
+            bio->wrSz  = 0;
+            XFREE(bio->ptr, bio->heap, DYNAMIC_TYPE_OPENSSL);
+            bio->ptr = NULL;
+            bio->num = 0;
+            if (bio->mem_buf != NULL) {
+                bio->mem_buf->data = (char*)bio->ptr;
+                bio->mem_buf->length = bio->num;
+            }
+            return 0;
+
+#ifndef WOLFCRYPT_ONLY
+        case WOLFSSL_BIO_MD:
+            if (bio->ptr != NULL) {
+                const WOLFSSL_EVP_MD* md =
+                    wolfSSL_EVP_MD_CTX_md((WOLFSSL_EVP_MD_CTX*)bio->ptr);
+                wolfSSL_EVP_MD_CTX_init((WOLFSSL_EVP_MD_CTX*)bio->ptr);
+                wolfSSL_EVP_DigestInit((WOLFSSL_EVP_MD_CTX*)bio->ptr, md);
+            }
+            return 0;
+#endif /* WOLFCRYPT_ONLY */
+
+        default:
+            WOLFSSL_MSG("Unknown BIO type needs added to reset function");
+    }
+
+    return WOLFSSL_BIO_ERROR;
+}
+
+#ifndef NO_FILESYSTEM
+long wolfSSL_BIO_set_fp(WOLFSSL_BIO *bio, XFILE fp, int c)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_set_fp");
+
+    if (bio == NULL || fp == XBADFILE) {
+        WOLFSSL_LEAVE("wolfSSL_BIO_set_fp", BAD_FUNC_ARG);
+        return WOLFSSL_FAILURE;
+    }
+
+    if (bio->type != WOLFSSL_BIO_FILE) {
+        return WOLFSSL_FAILURE;
+    }
+
+    bio->shutdown = (byte)c;
+    bio->ptr = (XFILE)fp;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+long wolfSSL_BIO_get_fp(WOLFSSL_BIO *bio, XFILE* fp)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_get_fp");
+
+    if (bio == NULL || fp == XBADFILE) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if (bio->type != WOLFSSL_BIO_FILE) {
+        return SSL_FAILURE;
+    }
+
+    *fp = (XFILE)bio->ptr;
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* overwrites file */
+int wolfSSL_BIO_write_filename(WOLFSSL_BIO *bio, char *name)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_write_filename");
+
+    if (bio == NULL || name == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if (bio->type == WOLFSSL_BIO_FILE) {
+        if (((XFILE)bio->ptr) != XBADFILE && bio->shutdown == BIO_CLOSE) {
+            XFCLOSE((XFILE)bio->ptr);
+        }
+
+        bio->ptr = XFOPEN(name, "w");
+        if (((XFILE)bio->ptr) == XBADFILE) {
+            return WOLFSSL_FAILURE;
+        }
+        bio->shutdown = BIO_CLOSE;
+
+        return WOLFSSL_SUCCESS;
+    }
+
+    return WOLFSSL_FAILURE;
+}
+
+
+int wolfSSL_BIO_seek(WOLFSSL_BIO *bio, int ofs)
+{
+      WOLFSSL_ENTER("wolfSSL_BIO_seek");
+
+      if (bio == NULL) {
+          return -1;
+      }
+
+      /* offset ofs from beginning of file */
+      if (bio->type == WOLFSSL_BIO_FILE &&
+              XFSEEK((XFILE)bio->ptr, ofs, SEEK_SET) < 0) {
+          return -1;
+      }
+
+      return 0;
+}
+#endif /* NO_FILESYSTEM */
+
+
+long wolfSSL_BIO_set_mem_eof_return(WOLFSSL_BIO *bio, int v)
+{
+      WOLFSSL_ENTER("wolfSSL_BIO_set_mem_eof_return");
+
+      if (bio != NULL) {
+        bio->eof = v;
+      }
+
+      return 0;
+}
+
+int wolfSSL_BIO_get_len(WOLFSSL_BIO *bio)
+{
+    int len;
+#ifndef NO_FILESYSTEM
+    long memSz = 0, curr = 0;
+    XFILE file;
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_BIO_get_len");
+
+    if ((len = wolfSSL_BIO_pending(bio)) > 0) {
+    }
+#ifndef NO_FILESYSTEM
+    else if (bio->type == WOLFSSL_BIO_FILE) {
+        if (wolfSSL_BIO_get_fp(bio, &file) != WOLFSSL_SUCCESS)
+            len = BAD_FUNC_ARG;
+        if (len == 0) {
+            curr = XFTELL(file);
+            if (curr < 0) {
+                len = WOLFSSL_BAD_FILE;
+            }
+            if (XFSEEK(file, 0, XSEEK_END) != 0)
+                len = WOLFSSL_BAD_FILE;
+        }
+        if (len == 0) {
+            memSz = XFTELL(file);
+            if (memSz > MAX_WOLFSSL_FILE_SIZE || memSz < 0)
+                len = WOLFSSL_BAD_FILE;
+        }
+        if (len == 0) {
+            memSz -= curr;
+            len = (int)memSz;
+            if (XFSEEK(file, curr, SEEK_SET) != 0)
+                len = WOLFSSL_BAD_FILE;
+        }
+    }
+#endif
+    return len;
+}
+
+
+void wolfSSL_BIO_set_callback(WOLFSSL_BIO *bio, wolf_bio_info_cb callback_func)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_set_callback");
+
+    if (bio != NULL) {
+        bio->infoCb = callback_func;
+    }
+}
+
+
+wolf_bio_info_cb wolfSSL_BIO_get_callback(WOLFSSL_BIO *bio)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_get_callback");
+
+    if (bio != NULL) {
+        return bio->infoCb;
+    }
+
+    return NULL;
+}
+
+
+void wolfSSL_BIO_set_callback_arg(WOLFSSL_BIO *bio, char *arg)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_set_callback_arg");
+
+    if (bio != NULL) {
+        bio->infoArg = arg;
+    }
+}
+
+
+char* wolfSSL_BIO_get_callback_arg(const WOLFSSL_BIO *bio)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_get_callback_arg");
+
+    if (bio != NULL) {
+        return bio->infoArg;
+    }
+
+    return NULL;
+}
+
+
+/* store a user pointer in the WOLFSSL_BIO structure */
+void wolfSSL_BIO_set_data(WOLFSSL_BIO* bio, void *ptr)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_set_data");
+
+    if (bio != NULL) {
+        bio->usrCtx = ptr;
+    }
+}
+
+
+void* wolfSSL_BIO_get_data(WOLFSSL_BIO* bio)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_get_data");
+
+    if (bio != NULL)
+        return bio->usrCtx;
+
+    WOLFSSL_MSG("WOLFSSL_BIO was null");
+    return NULL;
+}
+
+/* If flag is 0 then blocking is set, if 1 then non blocking.
+ * Always returns 1
+ */
+long wolfSSL_BIO_set_nbio(WOLFSSL_BIO* bio, long on)
+{
+    #ifndef WOLFSSL_DTLS
+    (void)on;
+    #endif
+    WOLFSSL_ENTER("wolfSSL_BIO_set_nbio");
+
+    switch (bio->type) {
+        case WOLFSSL_BIO_SOCKET:
+        #ifdef XFCNTL
+            {
+                int flag = XFCNTL(bio->num, F_GETFL, 0);
+                if (on)
+                    XFCNTL(bio->num, F_SETFL, flag | O_NONBLOCK);
+                else
+                    XFCNTL(bio->num, F_SETFL, flag & ~O_NONBLOCK);
+            }
+        #endif
+            break;
+        case WOLFSSL_BIO_SSL:
+        #ifdef WOLFSSL_DTLS
+            wolfSSL_dtls_set_using_nonblock((WOLFSSL*)bio->ptr, (int)on);
+        #endif
+            break;
+
+        default:
+            WOLFSSL_MSG("Unsupported bio type for non blocking");
+            break;
+    }
+
+    return 1;
+}
+
+
+
+/* creates a new custom WOLFSSL_BIO_METHOD */
+WOLFSSL_BIO_METHOD *wolfSSL_BIO_meth_new(int type, const char *name)
+{
+    WOLFSSL_BIO_METHOD* meth;
+
+    WOLFSSL_ENTER("wolfSSL_BIO_meth_new");
+
+    meth = (WOLFSSL_BIO_METHOD*)XMALLOC(sizeof(WOLFSSL_BIO_METHOD), NULL,
+            DYNAMIC_TYPE_OPENSSL);
+    if (meth == NULL) {
+        WOLFSSL_MSG("Error allocating memory for WOLFSSL_BIO_METHOD");
+        return NULL;
+    }
+    XMEMSET(meth, 0, sizeof(WOLFSSL_BIO_METHOD));
+    meth->type = (byte)type;
+    XSTRNCPY(meth->name, name, MAX_BIO_METHOD_NAME - 1);
+
+    return meth;
+}
+
+
+void wolfSSL_BIO_meth_free(WOLFSSL_BIO_METHOD *biom)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_meth_free");
+    if (biom) {
+        XFREE(biom, NULL, DYNAMIC_TYPE_OPENSSL);
+    }
+}
+
+
+int wolfSSL_BIO_meth_set_write(WOLFSSL_BIO_METHOD *biom,
+        wolfSSL_BIO_meth_write_cb biom_write)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_meth_set_write");
+    if (biom) {
+        biom->writeCb = biom_write;
+        return WOLFSSL_SUCCESS;
+    }
+    return WOLFSSL_FAILURE;
+}
+
+
+int wolfSSL_BIO_meth_set_read(WOLFSSL_BIO_METHOD *biom,
+        wolfSSL_BIO_meth_read_cb biom_read)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_meth_set_read");
+    if (biom) {
+        biom->readCb = biom_read;
+        return WOLFSSL_SUCCESS;
+    }
+    return WOLFSSL_FAILURE;
+}
+
+
+int wolfSSL_BIO_meth_set_puts(WOLFSSL_BIO_METHOD *biom,
+        wolfSSL_BIO_meth_puts_cb biom_puts)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_meth_set_puts");
+    if (biom) {
+        biom->putsCb = biom_puts;
+        return WOLFSSL_SUCCESS;
+    }
+    return WOLFSSL_FAILURE;
+}
+
+
+int wolfSSL_BIO_meth_set_gets(WOLFSSL_BIO_METHOD *biom,
+        wolfSSL_BIO_meth_gets_cb biom_gets)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_meth_set_gets");
+    if (biom) {
+        biom->getsCb = biom_gets;
+        return WOLFSSL_SUCCESS;
+    }
+    return WOLFSSL_FAILURE;
+}
+
+
+int wolfSSL_BIO_meth_set_ctrl(WOLFSSL_BIO_METHOD *biom,
+        wolfSSL_BIO_meth_ctrl_get_cb biom_ctrl)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_meth_set_ctrl");
+    if (biom) {
+        biom->ctrlCb = biom_ctrl;
+        return WOLFSSL_SUCCESS;
+    }
+    return WOLFSSL_FAILURE;
+}
+
+
+int wolfSSL_BIO_meth_set_create(WOLFSSL_BIO_METHOD *biom,
+        wolfSSL_BIO_meth_create_cb biom_create)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_meth_set_create");
+    if (biom) {
+        biom->createCb = biom_create;
+        return WOLFSSL_SUCCESS;
+    }
+    return WOLFSSL_FAILURE;
+}
+
+
+int wolfSSL_BIO_meth_set_destroy(WOLFSSL_BIO_METHOD *biom,
+        wolfSSL_BIO_meth_destroy_cb biom_destroy)
+{
+    WOLFSSL_STUB("wolfSSL_BIO_meth_set_destroy");
+    if (biom) {
+        biom->freeCb = biom_destroy;
+        return WOLFSSL_SUCCESS;
+    }
+    return WOLFSSL_FAILURE;
+}
+
+
+/* this compatibility function can be used for multiple BIO types */
+int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio, void* p)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_get_mem_data");
+
+    if (bio == NULL)
+        return WOLFSSL_FATAL_ERROR;
+
+    if (p) {
+        *(byte**)p = (byte*)bio->ptr;
+    }
+
+    return bio->num;
+}
+
+int wolfSSL_BIO_pending(WOLFSSL_BIO* bio)
+{
+    return (int)wolfSSL_BIO_ctrl_pending(bio);
+}
+
+
+int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
+{
+    /* for wolfSSL no flushing needed */
+    WOLFSSL_ENTER("BIO_flush");
+    (void)bio;
+    return 1;
+}
+#endif /* WOLFSSL_BIO_INCLUDED */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/config.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/config.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/config.h	(revision 453)
@@ -0,0 +1,193 @@
+/* config.h.  Generated from config.in by configure.  */
+/* config.in.  Generated from configure.ac by autoheader.  */
+
+/* Define if building universal (internal helper macro) */
+/* #undef AC_APPLE_UNIVERSAL_BUILD */
+
+/* User RSA is being defined */
+#define BUILD_USER_RSA /**/
+
+/* Define to 1 to enable debugging code. */
+#define DEBUG 0
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the `getaddrinfo' function. */
+#define HAVE_GETADDRINFO 1
+
+/* Define to 1 if you have the `gethostbyname' function. */
+#define HAVE_GETHOSTBYNAME 1
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have the `gmtime_r' function. */
+#define HAVE_GMTIME_R 1
+
+/* Define to 1 if you have the `inet_ntoa' function. */
+#define HAVE_INET_NTOA 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <ippcp.h> header file. */
+/* #undef HAVE_IPPCP_H */
+
+/* Define to 1 if you have the `network' library (-lnetwork). */
+/* #undef HAVE_LIBNETWORK */
+
+/* Define to 1 if you have the `pthread' library (-lpthread). */
+/* #undef HAVE_LIBPTHREAD */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the <pcap/pcap.h> header file. */
+/* #undef HAVE_PCAP_PCAP_H */
+
+/* Define if you have POSIX threads libraries and header files. */
+#define HAVE_PTHREAD 1
+
+/* Have PTHREAD_PRIO_INHERIT. */
+#define HAVE_PTHREAD_PRIO_INHERIT 1
+
+/* Define to 1 if you have the `socket' function. */
+#define HAVE_SOCKET 1
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#define HAVE_STDDEF_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 or 0, depending whether the compiler supports simple visibility
+   declarations. */
+#define HAVE_VISIBILITY 1
+
+/* Define to 1 if the system has the type `__uint128_t'. */
+/* #undef HAVE___UINT128_T */
+
+/* Define to the sub-directory where libtool stores uninstalled libraries. */
+#define LT_OBJDIR ".libs/"
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+/* #undef NO_MINUS_C_MINUS_O */
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "https://github.com/wolfssl/wolfssl/issues"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "wolfssl"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "wolfssl 3.15.7"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "wolfssl"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL "https://www.wolfssl.com"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "3.15.7"
+
+/* Define to necessary symbol if this constant uses a non-standard name on
+   your system. */
+/* #undef PTHREAD_CREATE_JOINABLE */
+
+/* The size of `long', as computed by sizeof. */
+#define SIZEOF_LONG 4
+
+/* The size of `long long', as computed by sizeof. */
+#define SIZEOF_LONG_LONG 8
+
+/* The size of `time_t', as computed by sizeof. */
+#define SIZEOF_TIME_T 8
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* If the compiler supports a TLS storage class define it to that here */
+#define TLS __thread
+
+/* Define if the code was built from VCS. */
+#define VCS_CHECKOUT 0
+
+/* VCS system */
+#define VCS_SYSTEM "none"
+
+/* Use __declspec(dllexport) when building library */
+/* #undef WOLFSSL_DLL */
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+   significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+#  define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+/* #  undef WORDS_BIGENDIAN */
+# endif
+#endif
+
+/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
+   <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
+   #define below would cause a syntax error. */
+/* #undef _UINT8_T */
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define to the type of an unsigned integer type of width exactly 8 bits if
+   such a type exists and the standard includes do not define it. */
+/* #undef uint8_t */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/crl.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/crl.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/crl.c	(revision 453)
@@ -0,0 +1,1093 @@
+/* crl.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+  /* Name change compatibility layer no longer needs included here */
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifndef WOLFCRYPT_ONLY
+#ifdef HAVE_CRL
+
+#include <wolfssl/internal.h>
+#include <wolfssl/error-ssl.h>
+
+#include <string.h>
+
+#ifdef HAVE_CRL_MONITOR
+    #if (defined(__MACH__) || defined(__FreeBSD__) || defined(__linux__))
+        static int StopMonitor(int mfd);
+    #else
+        #error "CRL monitor only currently supported on linux or mach"
+    #endif
+#endif /* HAVE_CRL_MONITOR */
+
+
+/* Initialize CRL members */
+int InitCRL(WOLFSSL_CRL* crl, WOLFSSL_CERT_MANAGER* cm)
+{
+    WOLFSSL_ENTER("InitCRL");
+    if(cm != NULL)
+        crl->heap = cm->heap;
+    else
+        crl->heap = NULL;
+    crl->cm = cm;
+    crl->crlList = NULL;
+    crl->monitors[0].path = NULL;
+    crl->monitors[1].path = NULL;
+#ifdef HAVE_CRL_MONITOR
+    crl->tid   =  0;
+    crl->mfd   = -1;    /* mfd for bsd is kqueue fd, eventfd for linux */
+    crl->setup = 0;     /* thread setup done predicate */
+    if (pthread_cond_init(&crl->cond, 0) != 0) {
+        WOLFSSL_MSG("Pthread condition init failed");
+        return BAD_COND_E;
+    }
+#endif
+    if (wc_InitMutex(&crl->crlLock) != 0) {
+        WOLFSSL_MSG("Init Mutex failed");
+        return BAD_MUTEX_E;
+    }
+
+    return 0;
+}
+
+
+/* Initialize CRL Entry */
+static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff,
+                         int verified, void* heap)
+{
+    WOLFSSL_ENTER("InitCRL_Entry");
+
+    XMEMCPY(crle->issuerHash, dcrl->issuerHash, CRL_DIGEST_SIZE);
+    /* XMEMCPY(crle->crlHash, dcrl->crlHash, CRL_DIGEST_SIZE);
+     * copy the hash here if needed for optimized comparisons */
+    XMEMCPY(crle->lastDate, dcrl->lastDate, MAX_DATE_SIZE);
+    XMEMCPY(crle->nextDate, dcrl->nextDate, MAX_DATE_SIZE);
+    crle->lastDateFormat = dcrl->lastDateFormat;
+    crle->nextDateFormat = dcrl->nextDateFormat;
+
+    crle->certs = dcrl->certs;   /* take ownsership */
+    dcrl->certs = NULL;
+    crle->totalCerts = dcrl->totalCerts;
+    crle->verified = verified;
+    if (!verified) {
+        crle->tbsSz = dcrl->sigIndex - dcrl->certBegin;
+        crle->signatureSz = dcrl->sigLength;
+        crle->signatureOID = dcrl->signatureOID;
+        crle->toBeSigned = (byte*)XMALLOC(crle->tbsSz, heap,
+                                          DYNAMIC_TYPE_CRL_ENTRY);
+        if (crle->toBeSigned == NULL)
+            return -1;
+        crle->signature = (byte*)XMALLOC(crle->signatureSz, heap,
+                                         DYNAMIC_TYPE_CRL_ENTRY);
+        if (crle->signature == NULL) {
+            XFREE(crle->toBeSigned, heap, DYNAMIC_TYPE_CRL_ENTRY);
+            return -1;
+        }
+        XMEMCPY(crle->toBeSigned, buff + dcrl->certBegin, crle->tbsSz);
+        XMEMCPY(crle->signature, dcrl->signature, crle->signatureSz);
+    #ifndef NO_SKID
+        crle->extAuthKeyIdSet = dcrl->extAuthKeyIdSet;
+        if (crle->extAuthKeyIdSet)
+            XMEMCPY(crle->extAuthKeyId, dcrl->extAuthKeyId, KEYID_SIZE);
+    #endif
+    }
+    else {
+        crle->toBeSigned = NULL;
+        crle->signature = NULL;
+    }
+
+    (void)verified;
+    (void)heap;
+
+    return 0;
+}
+
+
+/* Free all CRL Entry resources */
+static void FreeCRL_Entry(CRL_Entry* crle, void* heap)
+{
+    RevokedCert* tmp = crle->certs;
+    RevokedCert* next;
+
+    WOLFSSL_ENTER("FreeCRL_Entry");
+
+    while (tmp) {
+        next = tmp->next;
+        XFREE(tmp, heap, DYNAMIC_TYPE_REVOKED);
+        tmp = next;
+    }
+    if (crle->signature != NULL)
+        XFREE(crle->signature, heap, DYNAMIC_TYPE_REVOKED);
+    if (crle->toBeSigned != NULL)
+        XFREE(crle->toBeSigned, heap, DYNAMIC_TYPE_REVOKED);
+
+    (void)heap;
+}
+
+
+
+/* Free all CRL resources */
+void FreeCRL(WOLFSSL_CRL* crl, int dynamic)
+{
+    CRL_Entry* tmp = crl->crlList;
+
+    WOLFSSL_ENTER("FreeCRL");
+    if (crl->monitors[0].path)
+        XFREE(crl->monitors[0].path, crl->heap, DYNAMIC_TYPE_CRL_MONITOR);
+
+    if (crl->monitors[1].path)
+        XFREE(crl->monitors[1].path, crl->heap, DYNAMIC_TYPE_CRL_MONITOR);
+
+    while(tmp) {
+        CRL_Entry* next = tmp->next;
+        FreeCRL_Entry(tmp, crl->heap);
+        XFREE(tmp, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
+        tmp = next;
+    }
+
+#ifdef HAVE_CRL_MONITOR
+    if (crl->tid != 0) {
+        WOLFSSL_MSG("stopping monitor thread");
+        if (StopMonitor(crl->mfd) == 0)
+            pthread_join(crl->tid, NULL);
+        else {
+            WOLFSSL_MSG("stop monitor failed");
+        }
+    }
+    pthread_cond_destroy(&crl->cond);
+#endif
+    wc_FreeMutex(&crl->crlLock);
+    if (dynamic)   /* free self */
+        XFREE(crl, crl->heap, DYNAMIC_TYPE_CRL);
+}
+
+
+static int CheckCertCRLList(WOLFSSL_CRL* crl, DecodedCert* cert, int *pFoundEntry)
+{
+    CRL_Entry* crle;
+    int        foundEntry = 0;
+    int        ret = 0;
+
+    if (wc_LockMutex(&crl->crlLock) != 0) {
+        WOLFSSL_MSG("wc_LockMutex failed");
+        return BAD_MUTEX_E;
+    }
+
+    crle = crl->crlList;
+
+    while (crle) {
+        if (XMEMCMP(crle->issuerHash, cert->issuerHash, CRL_DIGEST_SIZE) == 0) {
+            WOLFSSL_MSG("Found CRL Entry on list");
+
+            if (crle->verified == 0) {
+                Signer* ca = NULL;
+            #ifndef NO_SKID
+                byte extAuthKeyId[KEYID_SIZE];
+            #endif
+                byte issuerHash[CRL_DIGEST_SIZE];
+                byte* tbs;
+                word32 tbsSz = crle->tbsSz;
+                byte* sig = NULL;
+                word32 sigSz = crle->signatureSz;
+                word32 sigOID = crle->signatureOID;
+                SignatureCtx sigCtx;
+
+                tbs = (byte*)XMALLOC(tbsSz, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
+                if (tbs == NULL) {
+                    wc_UnLockMutex(&crl->crlLock);
+                    return MEMORY_E;
+                }
+                sig = (byte*)XMALLOC(sigSz, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
+                if (sig == NULL) {
+                    XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
+                    wc_UnLockMutex(&crl->crlLock);
+                    return MEMORY_E;
+                }
+
+                XMEMCPY(tbs, crle->toBeSigned, tbsSz);
+                XMEMCPY(sig, crle->signature, sigSz);
+            #ifndef NO_SKID
+                XMEMCPY(extAuthKeyId, crle->extAuthKeyId,
+                                                          sizeof(extAuthKeyId));
+            #endif
+                XMEMCPY(issuerHash, crle->issuerHash, sizeof(issuerHash));
+
+                wc_UnLockMutex(&crl->crlLock);
+
+            #ifndef NO_SKID
+                if (crle->extAuthKeyIdSet)
+                    ca = GetCA(crl->cm, extAuthKeyId);
+                if (ca == NULL)
+                    ca = GetCAByName(crl->cm, issuerHash);
+            #else /* NO_SKID */
+                ca = GetCA(crl->cm, issuerHash);
+            #endif /* NO_SKID */
+                if (ca == NULL) {
+                    XFREE(sig, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
+                    XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
+                    WOLFSSL_MSG("Did NOT find CRL issuer CA");
+                    return ASN_CRL_NO_SIGNER_E;
+                }
+
+                ret = VerifyCRL_Signature(&sigCtx, tbs, tbsSz, sig, sigSz,
+                                          sigOID, ca, crl->heap);
+
+                XFREE(sig, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
+                XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
+
+                if (wc_LockMutex(&crl->crlLock) != 0) {
+                    WOLFSSL_MSG("wc_LockMutex failed");
+                    return BAD_MUTEX_E;
+                }
+
+                crle = crl->crlList;
+                while (crle) {
+                    if (XMEMCMP(crle->issuerHash, cert->issuerHash,
+                        CRL_DIGEST_SIZE) == 0) {
+
+                        if (ret == 0)
+                            crle->verified = 1;
+                        else
+                            crle->verified = ret;
+
+                        XFREE(crle->toBeSigned, crl->heap,
+                                                        DYNAMIC_TYPE_CRL_ENTRY);
+                        crle->toBeSigned = NULL;
+                        XFREE(crle->signature, crl->heap,
+                                                        DYNAMIC_TYPE_CRL_ENTRY);
+                        crle->signature = NULL;
+                        break;
+                    }
+                    crle = crle->next;
+                }
+                if (crle == NULL || crle->verified < 0)
+                    break;
+            }
+            else if (crle->verified < 0) {
+                WOLFSSL_MSG("Cannot use CRL as it didn't verify");
+                ret = crle->verified;
+                break;
+            }
+
+            WOLFSSL_MSG("Checking next date validity");
+
+        #ifdef WOLFSSL_NO_CRL_NEXT_DATE
+            if (crle->nextDateFormat != ASN_OTHER_TYPE)
+        #endif
+            {
+            #ifndef NO_ASN_TIME
+                if (!XVALIDATE_DATE(crle->nextDate,crle->nextDateFormat, AFTER)) {
+                    WOLFSSL_MSG("CRL next date is no longer valid");
+                    ret = ASN_AFTER_DATE_E;
+                }
+            #endif
+            }
+            if (ret == 0) {
+                foundEntry = 1;
+            }
+            break;
+        }
+        crle = crle->next;
+    }
+
+    if (foundEntry) {
+        RevokedCert* rc = crle->certs;
+
+        while (rc) {
+            if (rc->serialSz == cert->serialSz &&
+                   XMEMCMP(rc->serialNumber, cert->serial, rc->serialSz) == 0) {
+                WOLFSSL_MSG("Cert revoked");
+                ret = CRL_CERT_REVOKED;
+                break;
+            }
+            rc = rc->next;
+        }
+    }
+
+    wc_UnLockMutex(&crl->crlLock);
+
+    *pFoundEntry = foundEntry;
+
+    return ret;
+}
+
+/* Is the cert ok with CRL, return 0 on success */
+int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert)
+{
+    int        foundEntry = 0;
+    int        ret = 0;
+
+    WOLFSSL_ENTER("CheckCertCRL");
+
+    ret = CheckCertCRLList(crl, cert, &foundEntry);
+
+#ifdef HAVE_CRL_IO
+    if (foundEntry == 0) {
+        /* perform embedded lookup */
+        if (crl->crlIOCb) {
+            ret = crl->crlIOCb(crl, (const char*)cert->extCrlInfo,
+                                                        cert->extCrlInfoSz);
+            if (ret == WOLFSSL_CBIO_ERR_WANT_READ) {
+                ret = WANT_READ;
+            }
+            else if (ret >= 0) {
+                /* try again */
+                ret = CheckCertCRLList(crl, cert, &foundEntry);
+            }
+        }
+    }
+#endif
+
+    if (foundEntry == 0) {
+        WOLFSSL_MSG("Couldn't find CRL for status check");
+        ret = CRL_MISSING;
+
+        if (crl->cm->cbMissingCRL) {
+            char url[256];
+
+            WOLFSSL_MSG("Issuing missing CRL callback");
+            url[0] = '\0';
+            if (cert->extCrlInfo) {
+                if (cert->extCrlInfoSz < (int)sizeof(url) -1 ) {
+                    XMEMCPY(url, cert->extCrlInfo, cert->extCrlInfoSz);
+                    url[cert->extCrlInfoSz] = '\0';
+                }
+                else  {
+                    WOLFSSL_MSG("CRL url too long");
+                }
+            }
+
+            crl->cm->cbMissingCRL(url);
+        }
+    }
+
+    return ret;
+}
+
+
+/* Add Decoded CRL, 0 on success */
+static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl, const byte* buff,
+                  int verified)
+{
+    CRL_Entry* crle;
+
+    WOLFSSL_ENTER("AddCRL");
+
+    crle = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
+    if (crle == NULL) {
+        WOLFSSL_MSG("alloc CRL Entry failed");
+        return -1;
+    }
+
+    if (InitCRL_Entry(crle, dcrl, buff, verified, crl->heap) < 0) {
+        WOLFSSL_MSG("Init CRL Entry failed");
+        XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
+        return -1;
+    }
+
+    if (wc_LockMutex(&crl->crlLock) != 0) {
+        WOLFSSL_MSG("wc_LockMutex failed");
+        FreeCRL_Entry(crle, crl->heap);
+        XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
+        return BAD_MUTEX_E;
+    }
+    crle->next = crl->crlList;
+    crl->crlList = crle;
+    wc_UnLockMutex(&crl->crlLock);
+
+    return 0;
+}
+
+
+/* Load CRL File of type, WOLFSSL_SUCCESS on ok */
+int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type,
+                  int verify)
+{
+    int          ret = WOLFSSL_SUCCESS;
+    const byte*  myBuffer = buff;    /* if DER ok, otherwise switch */
+    DerBuffer*   der = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    DecodedCRL*  dcrl;
+#else
+    DecodedCRL   dcrl[1];
+#endif
+
+    WOLFSSL_ENTER("BufferLoadCRL");
+
+    if (crl == NULL || buff == NULL || sz == 0)
+        return BAD_FUNC_ARG;
+
+    if (type == WOLFSSL_FILETYPE_PEM) {
+    #ifdef WOLFSSL_PEM_TO_DER
+        ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, NULL, NULL);
+        if (ret == 0) {
+            myBuffer = der->buffer;
+            sz = der->length;
+        }
+        else {
+            WOLFSSL_MSG("Pem to Der failed");
+            FreeDer(&der);
+            return -1;
+        }
+    #else
+        ret = NOT_COMPILED_IN;
+    #endif
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    dcrl = (DecodedCRL*)XMALLOC(sizeof(DecodedCRL), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (dcrl == NULL) {
+        FreeDer(&der);
+        return MEMORY_E;
+    }
+#endif
+
+    InitDecodedCRL(dcrl, crl->heap);
+    ret = ParseCRL(dcrl, myBuffer, (word32)sz, crl->cm);
+    if (ret != 0 && !(ret == ASN_CRL_NO_SIGNER_E && verify == NO_VERIFY)) {
+        WOLFSSL_MSG("ParseCRL error");
+    }
+    else {
+        ret = AddCRL(crl, dcrl, myBuffer, ret != ASN_CRL_NO_SIGNER_E);
+        if (ret != 0) {
+            WOLFSSL_MSG("AddCRL error");
+        }
+    }
+
+    FreeDecodedCRL(dcrl);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(dcrl, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    FreeDer(&der);
+
+    return ret ? ret : WOLFSSL_SUCCESS; /* convert 0 to WOLFSSL_SUCCESS */
+}
+
+#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL)
+int wolfSSL_X509_STORE_add_crl(WOLFSSL_X509_STORE *store, WOLFSSL_X509_CRL *newcrl)
+{
+    CRL_Entry   *crle;
+    WOLFSSL_CRL *crl;
+
+    WOLFSSL_ENTER("wolfSSL_X509_STORE_add_crl");
+    if (store == NULL || newcrl == NULL)
+        return BAD_FUNC_ARG;
+
+    crl = store->crl;
+    crle = newcrl->crlList;
+
+    if (wc_LockMutex(&crl->crlLock) != 0)
+    {
+        WOLFSSL_MSG("wc_LockMutex failed");
+        return BAD_MUTEX_E;
+    }
+    crle->next = crl->crlList;
+    crl->crlList = crle;
+    newcrl->crlList = NULL;
+    wc_UnLockMutex(&crl->crlLock);
+
+    WOLFSSL_LEAVE("wolfSSL_X509_STORE_add_crl", WOLFSSL_SUCCESS);
+
+    return WOLFSSL_SUCCESS;
+}
+#endif
+
+#ifdef HAVE_CRL_MONITOR
+
+
+/* Signal Monitor thread is setup, save status to setup flag, 0 on success */
+static int SignalSetup(WOLFSSL_CRL* crl, int status)
+{
+    int ret;
+
+    /* signal to calling thread we're setup */
+    if (wc_LockMutex(&crl->crlLock) != 0) {
+        WOLFSSL_MSG("wc_LockMutex crlLock failed");
+        return BAD_MUTEX_E;
+    }
+
+        crl->setup = status;
+        ret = pthread_cond_signal(&crl->cond);
+
+    wc_UnLockMutex(&crl->crlLock);
+
+    if (ret != 0)
+        return BAD_COND_E;
+
+    return 0;
+}
+
+
+/* read in new CRL entries and save new list */
+static int SwapLists(WOLFSSL_CRL* crl)
+{
+    int        ret;
+    CRL_Entry* newList;
+#ifdef WOLFSSL_SMALL_STACK
+    WOLFSSL_CRL* tmp;
+#else
+    WOLFSSL_CRL tmp[1];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+    tmp = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (tmp == NULL)
+        return MEMORY_E;
+#endif
+
+    if (InitCRL(tmp, crl->cm) < 0) {
+        WOLFSSL_MSG("Init tmp CRL failed");
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+        return -1;
+    }
+
+    if (crl->monitors[0].path) {
+        ret = LoadCRL(tmp, crl->monitors[0].path, WOLFSSL_FILETYPE_PEM, 0);
+        if (ret != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("PEM LoadCRL on dir change failed");
+            FreeCRL(tmp, 0);
+#ifdef WOLFSSL_SMALL_STACK
+            XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+            return -1;
+        }
+    }
+
+    if (crl->monitors[1].path) {
+        ret = LoadCRL(tmp, crl->monitors[1].path, WOLFSSL_FILETYPE_ASN1, 0);
+        if (ret != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("DER LoadCRL on dir change failed");
+            FreeCRL(tmp, 0);
+#ifdef WOLFSSL_SMALL_STACK
+            XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+            return -1;
+        }
+    }
+
+    if (wc_LockMutex(&crl->crlLock) != 0) {
+        WOLFSSL_MSG("wc_LockMutex failed");
+        FreeCRL(tmp, 0);
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+        return -1;
+    }
+
+    newList = tmp->crlList;
+
+    /* swap lists */
+    tmp->crlList  = crl->crlList;
+    crl->crlList = newList;
+
+    wc_UnLockMutex(&crl->crlLock);
+
+    FreeCRL(tmp, 0);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return 0;
+}
+
+
+#if (defined(__MACH__) || defined(__FreeBSD__))
+
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#ifdef __MACH__
+    #define XEVENT_MODE O_EVTONLY
+#elif defined(__FreeBSD__)
+    #define XEVENT_MODE EVFILT_VNODE
+#endif
+
+
+/* we need a unique kqueue user filter fd for crl in case user is doing custom
+ * events too */
+#ifndef CRL_CUSTOM_FD
+    #define CRL_CUSTOM_FD 123456
+#endif
+
+
+/* shutdown monitor thread, 0 on success */
+static int StopMonitor(int mfd)
+{
+    struct kevent change;
+
+    /* trigger custom shutdown */
+    EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL);
+    if (kevent(mfd, &change, 1, NULL, 0, NULL) < 0) {
+        WOLFSSL_MSG("kevent trigger customer event failed");
+        return -1;
+    }
+
+    return 0;
+}
+
+
+/* OS X  monitoring */
+static void* DoMonitor(void* arg)
+{
+    int fPEM, fDER;
+    struct kevent change;
+
+    WOLFSSL_CRL* crl = (WOLFSSL_CRL*)arg;
+
+    WOLFSSL_ENTER("DoMonitor");
+
+    crl->mfd = kqueue();
+    if (crl->mfd == -1) {
+        WOLFSSL_MSG("kqueue failed");
+        SignalSetup(crl, MONITOR_SETUP_E);
+        return NULL;
+    }
+
+    /* listen for custom shutdown event */
+    EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, EV_ADD, 0, 0, NULL);
+    if (kevent(crl->mfd, &change, 1, NULL, 0, NULL) < 0) {
+        WOLFSSL_MSG("kevent monitor customer event failed");
+        SignalSetup(crl, MONITOR_SETUP_E);
+        close(crl->mfd);
+        return NULL;
+    }
+
+    fPEM = -1;
+    fDER = -1;
+
+    if (crl->monitors[0].path) {
+        fPEM = open(crl->monitors[0].path, XEVENT_MODE);
+        if (fPEM == -1) {
+            WOLFSSL_MSG("PEM event dir open failed");
+            SignalSetup(crl, MONITOR_SETUP_E);
+            close(crl->mfd);
+            return NULL;
+        }
+    }
+
+    if (crl->monitors[1].path) {
+        fDER = open(crl->monitors[1].path, XEVENT_MODE);
+        if (fDER == -1) {
+            WOLFSSL_MSG("DER event dir open failed");
+            if (fPEM != -1)
+                close(fPEM);
+            close(crl->mfd);
+            SignalSetup(crl, MONITOR_SETUP_E);
+            return NULL;
+        }
+    }
+
+    if (fPEM != -1)
+        EV_SET(&change, fPEM, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT,
+                NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0);
+
+    if (fDER != -1)
+        EV_SET(&change, fDER, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT,
+                NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0);
+
+    /* signal to calling thread we're setup */
+    if (SignalSetup(crl, 1) != 0) {
+        if (fPEM != -1)
+            close(fPEM);
+        if (fDER != -1)
+            close(fDER);
+        close(crl->mfd);
+        return NULL;
+    }
+
+    for (;;) {
+        struct kevent event;
+        int           numEvents = kevent(crl->mfd, &change, 1, &event, 1, NULL);
+
+        WOLFSSL_MSG("Got kevent");
+
+        if (numEvents == -1) {
+            WOLFSSL_MSG("kevent problem, continue");
+            continue;
+        }
+
+        if (event.filter == EVFILT_USER) {
+            WOLFSSL_MSG("Got user shutdown event, breaking out");
+            break;
+        }
+
+        if (SwapLists(crl) < 0) {
+            WOLFSSL_MSG("SwapLists problem, continue");
+        }
+    }
+
+    if (fPEM != -1)
+        close(fPEM);
+    if (fDER != -1)
+        close(fDER);
+
+    close(crl->mfd);
+
+    return NULL;
+}
+
+
+#elif defined(__linux__)
+
+#include <sys/types.h>
+#include <sys/inotify.h>
+#include <sys/eventfd.h>
+#include <unistd.h>
+
+
+#ifndef max
+    static WC_INLINE int max(int a, int b)
+    {
+        return a > b ? a : b;
+    }
+#endif /* max */
+
+
+/* shutdown monitor thread, 0 on success */
+static int StopMonitor(int mfd)
+{
+    word64 w64 = 1;
+
+    /* write to our custom event */
+    if (write(mfd, &w64, sizeof(w64)) < 0) {
+        WOLFSSL_MSG("StopMonitor write failed");
+        return -1;
+    }
+
+    return 0;
+}
+
+
+/* linux monitoring */
+static void* DoMonitor(void* arg)
+{
+    int         notifyFd;
+    int         wd  = -1;
+    WOLFSSL_CRL* crl = (WOLFSSL_CRL*)arg;
+#ifdef WOLFSSL_SMALL_STACK
+    char*       buff;
+#else
+    char        buff[8192];
+#endif
+
+    WOLFSSL_ENTER("DoMonitor");
+
+    crl->mfd = eventfd(0, 0);  /* our custom shutdown event */
+    if (crl->mfd < 0) {
+        WOLFSSL_MSG("eventfd failed");
+        SignalSetup(crl, MONITOR_SETUP_E);
+        return NULL;
+    }
+
+    notifyFd = inotify_init();
+    if (notifyFd < 0) {
+        WOLFSSL_MSG("inotify failed");
+        close(crl->mfd);
+        SignalSetup(crl, MONITOR_SETUP_E);
+        return NULL;
+    }
+
+    if (crl->monitors[0].path) {
+        wd = inotify_add_watch(notifyFd, crl->monitors[0].path, IN_CLOSE_WRITE |
+                                                                IN_DELETE);
+        if (wd < 0) {
+            WOLFSSL_MSG("PEM notify add watch failed");
+            close(crl->mfd);
+            close(notifyFd);
+            SignalSetup(crl, MONITOR_SETUP_E);
+            return NULL;
+        }
+    }
+
+    if (crl->monitors[1].path) {
+        wd = inotify_add_watch(notifyFd, crl->monitors[1].path, IN_CLOSE_WRITE |
+                                                                IN_DELETE);
+        if (wd < 0) {
+            WOLFSSL_MSG("DER notify add watch failed");
+            close(crl->mfd);
+            close(notifyFd);
+            SignalSetup(crl, MONITOR_SETUP_E);
+            return NULL;
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    buff = (char*)XMALLOC(8192, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (buff == NULL)
+        return NULL;
+#endif
+
+    /* signal to calling thread we're setup */
+    if (SignalSetup(crl, 1) != 0) {
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        #endif
+
+        if (wd > 0)
+            inotify_rm_watch(notifyFd, wd);
+        close(crl->mfd);
+        close(notifyFd);
+        return NULL;
+    }
+
+    for (;;) {
+        fd_set readfds;
+        int    result;
+        int    length;
+
+        FD_ZERO(&readfds);
+        FD_SET(notifyFd, &readfds);
+        FD_SET(crl->mfd, &readfds);
+
+        result = select(max(notifyFd, crl->mfd) + 1, &readfds, NULL, NULL,NULL);
+
+        WOLFSSL_MSG("Got notify event");
+
+        if (result < 0) {
+            WOLFSSL_MSG("select problem, continue");
+            continue;
+        }
+
+        if (FD_ISSET(crl->mfd, &readfds)) {
+            WOLFSSL_MSG("got custom shutdown event, breaking out");
+            break;
+        }
+
+        length = (int) read(notifyFd, buff, 8192);
+        if (length < 0) {
+            WOLFSSL_MSG("notify read problem, continue");
+            continue;
+        }
+
+        if (SwapLists(crl) < 0) {
+            WOLFSSL_MSG("SwapLists problem, continue");
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    if (wd > 0)
+        inotify_rm_watch(notifyFd, wd);
+    close(crl->mfd);
+    close(notifyFd);
+
+    return NULL;
+}
+
+#endif /* MACH or linux */
+
+
+/* Start Monitoring the CRL path(s) in a thread */
+static int StartMonitorCRL(WOLFSSL_CRL* crl)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("StartMonitorCRL");
+
+    if (crl == NULL)
+        return BAD_FUNC_ARG;
+
+    if (crl->tid != 0) {
+        WOLFSSL_MSG("Monitor thread already running");
+        return ret;  /* that's ok, someone already started */
+    }
+
+    if (pthread_create(&crl->tid, NULL, DoMonitor, crl) != 0) {
+        WOLFSSL_MSG("Thread creation error");
+        return THREAD_CREATE_E;
+    }
+
+    /* wait for setup to complete */
+    if (wc_LockMutex(&crl->crlLock) != 0) {
+        WOLFSSL_MSG("wc_LockMutex crlLock error");
+        return BAD_MUTEX_E;
+    }
+
+        while (crl->setup == 0) {
+            if (pthread_cond_wait(&crl->cond, &crl->crlLock) != 0) {
+                ret = BAD_COND_E;
+                break;
+            }
+        }
+
+        if (crl->setup < 0)
+            ret = crl->setup;  /* store setup error */
+
+    wc_UnLockMutex(&crl->crlLock);
+
+    if (ret < 0) {
+        WOLFSSL_MSG("DoMonitor setup failure");
+        crl->tid = 0;  /* thread already done */
+    }
+
+    return ret;
+}
+
+
+#else /* HAVE_CRL_MONITOR */
+
+#ifndef NO_FILESYSTEM
+
+static int StartMonitorCRL(WOLFSSL_CRL* crl)
+{
+    (void)crl;
+
+    WOLFSSL_ENTER("StartMonitorCRL");
+    WOLFSSL_MSG("Not compiled in");
+
+    return NOT_COMPILED_IN;
+}
+
+#endif /* NO_FILESYSTEM */
+
+#endif  /* HAVE_CRL_MONITOR */
+
+#if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
+
+/* Load CRL path files of type, WOLFSSL_SUCCESS on ok */
+int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor)
+{
+    int         ret = WOLFSSL_SUCCESS;
+    char*       name = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    ReadDirCtx* readCtx = NULL;
+#else
+    ReadDirCtx  readCtx[1];
+#endif
+
+    WOLFSSL_ENTER("LoadCRL");
+    if (crl == NULL)
+        return BAD_FUNC_ARG;
+
+#ifdef WOLFSSL_SMALL_STACK
+    readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), crl->heap,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+    if (readCtx == NULL)
+        return MEMORY_E;
+#endif
+
+    /* try to load each regular file in path */
+    ret = wc_ReadDirFirst(readCtx, path, &name);
+    while (ret == 0 && name) {
+        int skip = 0;
+        if (type == WOLFSSL_FILETYPE_PEM) {
+            if (XSTRSTR(name, ".pem") == NULL) {
+                WOLFSSL_MSG("not .pem file, skipping");
+                skip = 1;
+            }
+        }
+        else {
+            if (XSTRSTR(name, ".der") == NULL &&
+                XSTRSTR(name, ".crl") == NULL)
+            {
+                WOLFSSL_MSG("not .der or .crl file, skipping");
+                skip = 1;
+            }
+        }
+
+        if (!skip && ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl,
+                                 VERIFY) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("CRL file load failed, continuing");
+        }
+
+        ret = wc_ReadDirNext(readCtx, path, &name);
+    }
+    wc_ReadDirClose(readCtx);
+    ret = WOLFSSL_SUCCESS; /* load failures not reported, for backwards compat */
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(readCtx, crl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    if (monitor & WOLFSSL_CRL_MONITOR) {
+        word32 pathLen;
+        char* pathBuf;
+
+        WOLFSSL_MSG("monitor path requested");
+
+        pathLen = (word32)XSTRLEN(path);
+        pathBuf = (char*)XMALLOC(pathLen+1, crl->heap,DYNAMIC_TYPE_CRL_MONITOR);
+        if (pathBuf) {
+            XSTRNCPY(pathBuf, path, pathLen+1);
+
+            if (type == WOLFSSL_FILETYPE_PEM) {
+                /* free old path before setting a new one */
+                if (crl->monitors[0].path) {
+                    XFREE(crl->monitors[0].path, crl->heap,
+                            DYNAMIC_TYPE_CRL_MONITOR);
+                }
+                crl->monitors[0].path = pathBuf;
+                crl->monitors[0].type = WOLFSSL_FILETYPE_PEM;
+            } else {
+                /* free old path before setting a new one */
+                if (crl->monitors[1].path) {
+                    XFREE(crl->monitors[1].path, crl->heap,
+                            DYNAMIC_TYPE_CRL_MONITOR);
+                }
+                crl->monitors[1].path = pathBuf;
+                crl->monitors[1].type = WOLFSSL_FILETYPE_ASN1;
+            }
+
+            if (monitor & WOLFSSL_CRL_START_MON) {
+                WOLFSSL_MSG("start monitoring requested");
+
+                ret = StartMonitorCRL(crl);
+            }
+        }
+        else {
+            ret = MEMORY_E;
+        }
+    }
+
+    return ret;
+}
+
+#else
+int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor)
+{
+	(void)crl;
+	(void)path;
+	(void)type;
+	(void)monitor;
+
+    /* stub for scenario where file system is not supported */
+    return NOT_COMPILED_IN;
+}
+#endif /* !NO_FILESYSTEM && !NO_WOLFSSL_DIR */
+
+#endif /* HAVE_CRL */
+#endif /* !WOLFCRYPT_ONLY */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/internal.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/internal.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/internal.c	(revision 453)
@@ -0,0 +1,29425 @@
+/* internal.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+/*
+ * WOLFSSL_SMALL_CERT_VERIFY:
+ *     Verify the certificate signature without using DecodedCert. Doubles up
+ *     on some code but allows smaller peak heap memory usage.
+ *     Cannot be used with WOLFSSL_NONBLOCK_OCSP.
+ * WOLFSSL_ALT_CERT_CHAINS:
+ *     Allows CA's to be presented by peer, but not part of a valid chain.
+ *     Default wolfSSL behavior is to require validation of all presented peer
+ *     certificates. This also allows loading intermediate CA's as trusted
+ *     and ignoring no signer failures for CA's up the chain to root.
+ */
+
+
+#ifdef EXTERNAL_OPTS_OPENVPN
+#error EXTERNAL_OPTS_OPENVPN should not be defined\
+    when building wolfSSL
+#endif
+
+#ifndef WOLFCRYPT_ONLY
+
+#include <wolfssl/internal.h>
+#include <wolfssl/error-ssl.h>
+#include <wolfssl/wolfcrypt/asn.h>
+#include <wolfssl/wolfcrypt/dh.h>
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA)
+    #include <wolfssl/wolfcrypt/srp.h>
+#endif
+
+#ifdef HAVE_LIBZ
+    #include "zlib.h"
+#endif
+
+#ifdef HAVE_NTRU
+    #include "libntruencrypt/ntru_crypto.h"
+#endif
+
+#if defined(DEBUG_WOLFSSL) || defined(SHOW_SECRETS) || \
+    defined(CHACHA_AEAD_TEST) || defined(WOLFSSL_SESSION_EXPORT_DEBUG)
+    #ifndef NO_STDIO_FILESYSTEM
+        #include <stdio.h>
+    #endif
+#endif
+
+#ifdef __sun
+    #include <sys/filio.h>
+#endif
+
+
+#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; }
+
+#ifdef _MSC_VER
+    /* disable for while(0) cases at the .c level for now */
+    #pragma warning(disable:4127)
+#endif
+
+#if defined(WOLFSSL_CALLBACKS) && !defined(LARGE_STATIC_BUFFERS)
+    #error \
+WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS
+#endif
+
+#if defined(HAVE_SECURE_RENEGOTIATION) && defined(HAVE_RENEGOTIATION_INDICATION)
+    #error Cannot use both secure-renegotiation and renegotiation-indication
+#endif
+
+#ifndef WOLFSSL_NO_TLS12
+
+#ifndef NO_WOLFSSL_CLIENT
+    static int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input, word32*,
+                                                                        word32);
+    static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, word32*,
+                                                                        word32);
+    #ifndef NO_CERTS
+        static int DoCertificateRequest(WOLFSSL* ssl, const byte* input, word32*,
+                                                                        word32);
+    #endif
+    #ifdef HAVE_SESSION_TICKET
+        static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32*,
+                                                                        word32);
+    #endif
+#endif
+
+
+#ifndef NO_WOLFSSL_SERVER
+    static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32*, word32);
+    #if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+                        defined(HAVE_ED448)) && !defined(WOLFSSL_NO_CLIENT_AUTH)
+        static int DoCertificateVerify(WOLFSSL* ssl, byte*, word32*, word32);
+    #endif
+    #ifdef WOLFSSL_DTLS
+        static int SendHelloVerifyRequest(WOLFSSL*, const byte*, byte);
+    #endif /* WOLFSSL_DTLS */
+#endif
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#ifdef WOLFSSL_DTLS
+    static WC_INLINE int DtlsCheckWindow(WOLFSSL* ssl);
+    static WC_INLINE int DtlsUpdateWindow(WOLFSSL* ssl);
+#endif
+
+
+enum processReply {
+    doProcessInit = 0,
+#ifndef NO_WOLFSSL_SERVER
+    runProcessOldClientHello,
+#endif
+    getRecordLayerHeader,
+    getData,
+    verifyEncryptedMessage,
+    decryptMessage,
+    verifyMessage,
+    runProcessingOneMessage
+};
+
+
+#ifndef WOLFSSL_NO_TLS12
+#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
+
+/* Server random bytes for TLS v1.3 described downgrade protection mechanism. */
+static const byte tls13Downgrade[7] = {
+    0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44
+};
+#define TLS13_DOWNGRADE_SZ  sizeof(tls13Downgrade)
+
+#endif /* !NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT */
+
+#if !defined(NO_OLD_TLS) && !defined(WOLFSSL_AEAD_ONLY)
+static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
+                    int padSz, int content, int verify);
+
+#endif
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#ifdef HAVE_QSH
+    int QSH_Init(WOLFSSL* ssl);
+#endif
+
+#ifdef WOLFSSL_RENESAS_TSIP_TLS
+    int tsip_useable(const WOLFSSL *ssl);
+    int tsip_generatePremasterSecret();
+    int tsip_generateEncryptPreMasterSecret(WOLFSSL *ssl, byte *out, word32 *outSz);
+#endif
+int IsTLS(const WOLFSSL* ssl)
+{
+    if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_MINOR)
+        return 1;
+
+    return 0;
+}
+
+
+int IsAtLeastTLSv1_2(const WOLFSSL* ssl)
+{
+    if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_2_MINOR)
+        return 1;
+#ifdef WOLFSSL_DTLS
+    if (ssl->version.major == DTLS_MAJOR && ssl->version.minor <= DTLSv1_2_MINOR)
+        return 1;
+#endif
+
+    return 0;
+}
+
+int IsAtLeastTLSv1_3(const ProtocolVersion pv)
+{
+    return (pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_3_MINOR);
+}
+
+static WC_INLINE int IsEncryptionOn(WOLFSSL* ssl, int isSend)
+{
+    (void)isSend;
+
+    #ifdef WOLFSSL_DTLS
+    /* For DTLS, epoch 0 is always not encrypted. */
+    if (ssl->options.dtls && !isSend && ssl->keys.curEpoch == 0)
+        return 0;
+    #endif /* WOLFSSL_DTLS */
+
+#ifdef WOLFSSL_TLS13
+    if (isSend)
+        return ssl->encrypt.setup;
+    else
+        return ssl->decrypt.setup;
+#else
+    return ssl->keys.encryptionOn;
+#endif
+}
+
+
+#if defined(WOLFSSL_DTLS) || !defined(WOLFSSL_NO_TLS12)
+/* If SCTP is not enabled returns the state of the dtls option.
+ * If SCTP is enabled returns dtls && !sctp. */
+static WC_INLINE int IsDtlsNotSctpMode(WOLFSSL* ssl)
+{
+    int result = ssl->options.dtls;
+
+    if (result) {
+#ifdef WOLFSSL_SCTP
+        result = !ssl->options.dtlsSctp;
+#endif
+    }
+
+    return result;
+}
+#endif /* DTLS || !WOLFSSL_NO_TLS12 */
+
+
+#ifdef HAVE_QSH
+/* free all structs that where used with QSH */
+static int QSH_FreeAll(WOLFSSL* ssl)
+{
+    QSHKey* key        = ssl->QSH_Key;
+    QSHKey* preKey     = NULL;
+    QSHSecret* secret  = ssl->QSH_secret;
+    QSHScheme* list    = NULL;
+    QSHScheme* preList = NULL;
+
+    /* free elements in struct */
+    while (key) {
+        preKey = key;
+        if (key->pri.buffer) {
+            ForceZero(key->pri.buffer, key->pri.length);
+            XFREE(key->pri.buffer, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
+        }
+        if (key->pub.buffer)
+            XFREE(key->pub.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        key = (QSHKey*)key->next;
+
+        /* free struct */
+        XFREE(preKey, ssl->heap, DYNAMIC_TYPE_QSH);
+    }
+
+
+    /* free all of peers QSH keys */
+    key = ssl->peerQSHKey;
+    while (key) {
+        preKey = key;
+        if (key->pri.buffer) {
+            ForceZero(key->pri.buffer, key->pri.length);
+            XFREE(key->pri.buffer, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
+        }
+        if (key->pub.buffer)
+            XFREE(key->pub.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        key = (QSHKey*)key->next;
+
+        /* free struct */
+        XFREE(preKey, ssl->heap, DYNAMIC_TYPE_QSH);
+    }
+    key = NULL;
+
+    /* free secret information */
+    if (secret) {
+        /* free up the QSHScheme list in QSHSecret */
+        if (secret->list)
+            list = secret->list;
+        while (list) {
+            preList = list;
+            if (list->PK)
+                XFREE(list->PK, ssl->heap, DYNAMIC_TYPE_SECRET);
+            list = (QSHScheme*)list->next;
+            XFREE(preList, ssl->heap, DYNAMIC_TYPE_QSH);
+        }
+
+        /* free secret buffers */
+        if (secret->SerSi) {
+            if (secret->SerSi->buffer) {
+                /* clear extra secret material that supplemented Master Secret*/
+                ForceZero(secret->SerSi->buffer, secret->SerSi->length);
+                XFREE(secret->SerSi->buffer, ssl->heap, DYNAMIC_TYPE_SECRET);
+            }
+            XFREE(secret->SerSi, ssl->heap, DYNAMIC_TYPE_SECRET);
+        }
+        if (secret->CliSi) {
+            if (secret->CliSi->buffer) {
+                /* clear extra secret material that supplemented Master Secret*/
+                ForceZero(secret->CliSi->buffer, secret->CliSi->length);
+                XFREE(secret->CliSi->buffer, ssl->heap, DYNAMIC_TYPE_SECRET);
+            }
+            XFREE(secret->CliSi, ssl->heap, DYNAMIC_TYPE_SECRET);
+        }
+    }
+    XFREE(secret, ssl->heap, DYNAMIC_TYPE_QSH);
+    secret = NULL;
+
+    return 0;
+}
+#endif
+
+
+#ifdef HAVE_NTRU
+static WOLFSSL_GLOBAL WC_RNG* rng;
+static WOLFSSL_GLOBAL wolfSSL_Mutex* rngMutex;
+
+static word32 GetEntropy(unsigned char* out, word32 num_bytes)
+{
+    int ret = 0;
+
+    if (rng == NULL) {
+        if ((rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), 0,
+                                                    DYNAMIC_TYPE_RNG)) == NULL)
+            return DRBG_OUT_OF_MEMORY;
+        wc_InitRng(rng);
+    }
+
+    if (rngMutex == NULL) {
+        if ((rngMutex = (wolfSSL_Mutex*)XMALLOC(sizeof(wolfSSL_Mutex), 0,
+                        DYNAMIC_TYPE_MUTEX)) == NULL)
+            return DRBG_OUT_OF_MEMORY;
+        wc_InitMutex(rngMutex);
+    }
+
+    ret |= wc_LockMutex(rngMutex);
+    ret |= wc_RNG_GenerateBlock(rng, out, num_bytes);
+    ret |= wc_UnLockMutex(rngMutex);
+
+    if (ret != 0)
+        return DRBG_ENTROPY_FAIL;
+
+    return DRBG_OK;
+}
+#endif /* HAVE_NTRU */
+
+#ifdef HAVE_LIBZ
+
+    /* alloc user allocs to work with zlib */
+    static void* myAlloc(void* opaque, unsigned int item, unsigned int size)
+    {
+        (void)opaque;
+        return XMALLOC(item * size, opaque, DYNAMIC_TYPE_LIBZ);
+    }
+
+
+    static void myFree(void* opaque, void* memory)
+    {
+        (void)opaque;
+        XFREE(memory, opaque, DYNAMIC_TYPE_LIBZ);
+    }
+
+
+    /* init zlib comp/decomp streams, 0 on success */
+    static int InitStreams(WOLFSSL* ssl)
+    {
+        ssl->c_stream.zalloc = (alloc_func)myAlloc;
+        ssl->c_stream.zfree  = (free_func)myFree;
+        ssl->c_stream.opaque = (voidpf)ssl->heap;
+
+        if (deflateInit(&ssl->c_stream, Z_DEFAULT_COMPRESSION) != Z_OK)
+            return ZLIB_INIT_ERROR;
+
+        ssl->didStreamInit = 1;
+
+        ssl->d_stream.zalloc = (alloc_func)myAlloc;
+        ssl->d_stream.zfree  = (free_func)myFree;
+        ssl->d_stream.opaque = (voidpf)ssl->heap;
+
+        if (inflateInit(&ssl->d_stream) != Z_OK) return ZLIB_INIT_ERROR;
+
+        return 0;
+    }
+
+
+    static void FreeStreams(WOLFSSL* ssl)
+    {
+        if (ssl->didStreamInit) {
+            deflateEnd(&ssl->c_stream);
+            inflateEnd(&ssl->d_stream);
+        }
+    }
+
+
+    /* compress in to out, return out size or error */
+    static int myCompress(WOLFSSL* ssl, byte* in, int inSz, byte* out, int outSz)
+    {
+        int    err;
+        int    currTotal = (int)ssl->c_stream.total_out;
+
+        ssl->c_stream.next_in   = in;
+        ssl->c_stream.avail_in  = inSz;
+        ssl->c_stream.next_out  = out;
+        ssl->c_stream.avail_out = outSz;
+
+        err = deflate(&ssl->c_stream, Z_SYNC_FLUSH);
+        if (err != Z_OK && err != Z_STREAM_END) return ZLIB_COMPRESS_ERROR;
+
+        return (int)ssl->c_stream.total_out - currTotal;
+    }
+
+
+    /* decompress in to out, return out size or error */
+    static int myDeCompress(WOLFSSL* ssl, byte* in,int inSz, byte* out,int outSz)
+    {
+        int    err;
+        int    currTotal = (int)ssl->d_stream.total_out;
+
+        ssl->d_stream.next_in   = in;
+        ssl->d_stream.avail_in  = inSz;
+        ssl->d_stream.next_out  = out;
+        ssl->d_stream.avail_out = outSz;
+
+        err = inflate(&ssl->d_stream, Z_SYNC_FLUSH);
+        if (err != Z_OK && err != Z_STREAM_END) return ZLIB_DECOMPRESS_ERROR;
+
+        return (int)ssl->d_stream.total_out - currTotal;
+    }
+
+#endif /* HAVE_LIBZ */
+
+
+#ifdef WOLFSSL_SESSION_EXPORT
+#ifdef WOLFSSL_DTLS
+/* serializes the cipher specs struct for exporting */
+static int ExportCipherSpecState(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
+{
+    word32 idx = 0;
+    CipherSpecs* specs;
+
+    WOLFSSL_ENTER("ExportCipherSpecState");
+
+    if (exp == NULL || ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    specs= &(ssl->specs);
+
+    if (DTLS_EXPORT_SPC_SZ > len) {
+        return BUFFER_E;
+    }
+
+    XMEMSET(exp, 0, DTLS_EXPORT_SPC_SZ);
+
+    c16toa(specs->key_size, exp + idx);      idx += OPAQUE16_LEN;
+    c16toa(specs->iv_size, exp + idx);       idx += OPAQUE16_LEN;
+    c16toa(specs->block_size, exp + idx);    idx += OPAQUE16_LEN;
+    c16toa(specs->aead_mac_size, exp + idx); idx += OPAQUE16_LEN;
+    exp[idx++] = specs->bulk_cipher_algorithm;
+    exp[idx++] = specs->cipher_type;
+    exp[idx++] = specs->mac_algorithm;
+    exp[idx++] = specs->kea;
+    exp[idx++] = specs->sig_algo;
+    exp[idx++] = specs->hash_size;
+    exp[idx++] = specs->pad_size;
+    exp[idx++] = specs->static_ecdh;
+
+    if (idx != DTLS_EXPORT_SPC_SZ) {
+        WOLFSSL_MSG("DTLS_EXPORT_SPC_SZ needs updated and export version");
+        return DTLS_EXPORT_VER_E;
+    }
+
+    WOLFSSL_LEAVE("ExportCipherSpecState", idx);
+    (void)ver;
+    return idx;
+}
+
+
+/* serializes the key struct for exporting */
+static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver,
+        byte small)
+{
+    word32 idx = 0;
+    byte   sz;
+    Keys* keys;
+
+    WOLFSSL_ENTER("ExportKeyState");
+
+    if (exp == NULL || ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    keys = &(ssl->keys);
+
+    if (DTLS_EXPORT_MIN_KEY_SZ > len) {
+        WOLFSSL_MSG("Buffer not large enough for minimum key struct size");
+        return BUFFER_E;
+    }
+
+    XMEMSET(exp, 0, DTLS_EXPORT_MIN_KEY_SZ);
+
+    c32toa(keys->peer_sequence_number_hi, exp + idx); idx += OPAQUE32_LEN;
+    c32toa(keys->peer_sequence_number_lo, exp + idx); idx += OPAQUE32_LEN;
+    c32toa(keys->sequence_number_hi, exp + idx);      idx += OPAQUE32_LEN;
+    c32toa(keys->sequence_number_lo, exp + idx);      idx += OPAQUE32_LEN;
+
+    c16toa(keys->peerSeq[0].nextEpoch, exp + idx);  idx += OPAQUE16_LEN;
+    c16toa(keys->peerSeq[0].nextSeq_hi, exp + idx); idx += OPAQUE16_LEN;
+    c32toa(keys->peerSeq[0].nextSeq_lo, exp + idx); idx += OPAQUE32_LEN;
+    c16toa(keys->curEpoch, exp + idx);   idx += OPAQUE16_LEN;
+    c16toa(keys->curSeq_hi, exp + idx);  idx += OPAQUE16_LEN;
+    c32toa(keys->curSeq_lo, exp + idx);  idx += OPAQUE32_LEN;
+    c16toa(keys->peerSeq[0].prevSeq_hi, exp + idx); idx += OPAQUE16_LEN;
+    c32toa(keys->peerSeq[0].prevSeq_lo, exp + idx); idx += OPAQUE32_LEN;
+
+    c16toa(keys->dtls_peer_handshake_number, exp + idx); idx += OPAQUE16_LEN;
+    c16toa(keys->dtls_expected_peer_handshake_number, exp + idx);
+    idx += OPAQUE16_LEN;
+
+    c16toa(keys->dtls_sequence_number_hi, exp + idx);      idx += OPAQUE16_LEN;
+    c32toa(keys->dtls_sequence_number_lo, exp + idx);      idx += OPAQUE32_LEN;
+    c16toa(keys->dtls_prev_sequence_number_hi, exp + idx); idx += OPAQUE16_LEN;
+    c32toa(keys->dtls_prev_sequence_number_lo, exp + idx); idx += OPAQUE32_LEN;
+    c16toa(keys->dtls_epoch, exp + idx);                   idx += OPAQUE16_LEN;
+    c16toa(keys->dtls_handshake_number, exp + idx);        idx += OPAQUE16_LEN;
+    c32toa(keys->encryptSz, exp + idx);                    idx += OPAQUE32_LEN;
+    c32toa(keys->padSz, exp + idx);                        idx += OPAQUE32_LEN;
+    exp[idx++] = keys->encryptionOn;
+    exp[idx++] = keys->decryptedCur;
+
+    /* from here on the buffer needs checked because is variable length that
+     * can be larger than DTLS_EXPORT_MIN_KEY_SZ */
+    {
+        word32 i;
+        if ((OPAQUE16_LEN * 2) + idx +
+                (2 * (WOLFSSL_DTLS_WINDOW_WORDS * OPAQUE32_LEN)) > len) {
+            WOLFSSL_MSG("Buffer not large enough for WOLFSSL_DTLS_WINDOW_WORDS");
+            return BUFFER_E;
+        }
+
+        c16toa(WOLFSSL_DTLS_WINDOW_WORDS, exp + idx); idx += OPAQUE16_LEN;
+        for (i = 0; i < WOLFSSL_DTLS_WINDOW_WORDS; i++) {
+            c32toa(keys->peerSeq[0].window[i], exp + idx);
+            idx += OPAQUE32_LEN;
+        }
+        c16toa(WOLFSSL_DTLS_WINDOW_WORDS, exp + idx); idx += OPAQUE16_LEN;
+        for (i = 0; i < WOLFSSL_DTLS_WINDOW_WORDS; i++) {
+            c32toa(keys->peerSeq[0].prevWindow[i], exp + idx);
+            idx += OPAQUE32_LEN;
+        }
+    }
+
+    if (idx >= len) {
+        WOLFSSL_MSG("Buffer not large enough for truncated hmac flag");
+        return BUFFER_E;
+    }
+
+#ifdef HAVE_TRUNCATED_HMAC
+    sz         = ssl->truncated_hmac ? TRUNCATED_HMAC_SZ: ssl->specs.hash_size;
+    exp[idx++] = ssl->truncated_hmac;
+#else
+    sz         = ssl->specs.hash_size;
+    exp[idx++] = 0; /* no truncated hmac */
+#endif
+
+    sz = (small)? 0: sz;
+    if (idx + (sz * 2) + OPAQUE8_LEN > len) {
+        WOLFSSL_MSG("Buffer not large enough for MAC secret");
+        return BUFFER_E;
+    }
+
+    exp[idx++] = sz;
+    if (sz > 0) {
+    #ifndef WOLFSSL_AEAD_ONLY
+        XMEMCPY(exp + idx, keys->client_write_MAC_secret, sz); idx += sz;
+        XMEMCPY(exp + idx, keys->server_write_MAC_secret, sz); idx += sz;
+    #else
+        XMEMSET(exp + idx, 0, sz); idx += sz;
+        XMEMSET(exp + idx, 0, sz); idx += sz;
+    #endif
+    }
+
+    sz = (small)? 0: ssl->specs.key_size;
+    if (idx + (sz * 2) + OPAQUE8_LEN > len) {
+        WOLFSSL_MSG("Buffer not large enough for write key");
+        return BUFFER_E;
+    }
+
+    exp[idx++] = sz;
+    if (sz > 0) {
+        XMEMCPY(exp + idx, keys->client_write_key, sz); idx += sz;
+        XMEMCPY(exp + idx, keys->server_write_key, sz); idx += sz;
+    }
+
+    sz = (small)? 0: ssl->specs.iv_size;
+    if (idx + (sz * 2) + OPAQUE8_LEN + AEAD_MAX_EXP_SZ > len) {
+        WOLFSSL_MSG("Buffer not large enough for IVs");
+        return BUFFER_E;
+    }
+
+    exp[idx++] = sz;
+    if (sz > 0) {
+        XMEMCPY(exp + idx, keys->client_write_IV, sz); idx += sz;
+        XMEMCPY(exp + idx, keys->server_write_IV, sz); idx += sz;
+    }
+    XMEMCPY(exp + idx, keys->aead_exp_IV, AEAD_MAX_EXP_SZ);
+    idx += AEAD_MAX_EXP_SZ;
+
+    sz = (small)? 0: AEAD_MAX_IMP_SZ;
+    if (idx + (sz * 2) + OPAQUE8_LEN > len) {
+        WOLFSSL_MSG("Buffer not large enough for imp IVs");
+        return BUFFER_E;
+    }
+    exp[idx++] = sz;
+    if (sz > 0) {
+        XMEMCPY(exp + idx, keys->aead_enc_imp_IV, sz); idx += sz;
+        XMEMCPY(exp + idx, keys->aead_dec_imp_IV, sz); idx += sz;
+    }
+
+    /* DTLS_EXPORT_KEY_SZ is max value. idx size can vary */
+    if (idx > DTLS_EXPORT_KEY_SZ) {
+        WOLFSSL_MSG("DTLS_EXPORT_KEY_SZ needs updated and export version");
+        return DTLS_EXPORT_VER_E;
+    }
+
+    WOLFSSL_LEAVE("ExportKeyState", idx);
+    (void)ver;
+    return idx;
+}
+
+static int ImportCipherSpecState(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
+{
+    word32 idx = 0;
+    CipherSpecs* specs;
+
+    WOLFSSL_ENTER("ImportCipherSpecState");
+
+    if (exp == NULL || ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    specs= &(ssl->specs);
+
+    if (DTLS_EXPORT_SPC_SZ > len) {
+        WOLFSSL_MSG("Buffer not large enough for max spec struct size");
+        return BUFFER_E;
+    }
+
+    ato16(exp + idx, &specs->key_size);      idx += OPAQUE16_LEN;
+    ato16(exp + idx, &specs->iv_size);       idx += OPAQUE16_LEN;
+    ato16(exp + idx, &specs->block_size);    idx += OPAQUE16_LEN;
+    ato16(exp + idx, &specs->aead_mac_size); idx += OPAQUE16_LEN;
+    specs->bulk_cipher_algorithm = exp[idx++];
+    specs->cipher_type           = exp[idx++];
+    specs->mac_algorithm         = exp[idx++];
+    specs->kea                   = exp[idx++];
+    specs->sig_algo              = exp[idx++];
+    specs->hash_size             = exp[idx++];
+    specs->pad_size              = exp[idx++];
+    specs->static_ecdh           = exp[idx++];
+
+    WOLFSSL_LEAVE("ImportCipherSpecState", idx);
+    (void)ver;
+    return idx;
+}
+
+
+static int ImportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
+{
+    word32 idx = 0;
+    byte  sz;
+    Keys* keys;
+
+    WOLFSSL_ENTER("ImportKeyState");
+
+    if (exp == NULL || ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    keys = &(ssl->keys);
+
+    /* check minimum length -- includes byte used for size indicators */
+    if (len < DTLS_EXPORT_MIN_KEY_SZ) {
+        WOLFSSL_MSG("Buffer not large enough for minimum expected size");
+        return BUFFER_E;
+    }
+    ato32(exp + idx, &keys->peer_sequence_number_hi); idx += OPAQUE32_LEN;
+    ato32(exp + idx, &keys->peer_sequence_number_lo); idx += OPAQUE32_LEN;
+    ato32(exp + idx, &keys->sequence_number_hi);      idx += OPAQUE32_LEN;
+    ato32(exp + idx, &keys->sequence_number_lo);      idx += OPAQUE32_LEN;
+
+    ato16(exp + idx, &keys->peerSeq[0].nextEpoch);  idx += OPAQUE16_LEN;
+    ato16(exp + idx, &keys->peerSeq[0].nextSeq_hi); idx += OPAQUE16_LEN;
+    ato32(exp + idx, &keys->peerSeq[0].nextSeq_lo); idx += OPAQUE32_LEN;
+    ato16(exp + idx, &keys->curEpoch);   idx += OPAQUE16_LEN;
+    ato16(exp + idx, &keys->curSeq_hi);  idx += OPAQUE16_LEN;
+    ato32(exp + idx, &keys->curSeq_lo);  idx += OPAQUE32_LEN;
+    ato16(exp + idx, &keys->peerSeq[0].prevSeq_hi); idx += OPAQUE16_LEN;
+    ato32(exp + idx, &keys->peerSeq[0].prevSeq_lo); idx += OPAQUE32_LEN;
+
+    ato16(exp + idx, &keys->dtls_peer_handshake_number); idx += OPAQUE16_LEN;
+    ato16(exp + idx, &keys->dtls_expected_peer_handshake_number);
+    idx += OPAQUE16_LEN;
+
+    ato16(exp + idx, &keys->dtls_sequence_number_hi);      idx += OPAQUE16_LEN;
+    ato32(exp + idx, &keys->dtls_sequence_number_lo);      idx += OPAQUE32_LEN;
+    ato16(exp + idx, &keys->dtls_prev_sequence_number_hi); idx += OPAQUE16_LEN;
+    ato32(exp + idx, &keys->dtls_prev_sequence_number_lo); idx += OPAQUE32_LEN;
+    ato16(exp + idx, &keys->dtls_epoch);                   idx += OPAQUE16_LEN;
+    ato16(exp + idx, &keys->dtls_handshake_number);        idx += OPAQUE16_LEN;
+    ato32(exp + idx, &keys->encryptSz);                    idx += OPAQUE32_LEN;
+    ato32(exp + idx, &keys->padSz);                        idx += OPAQUE32_LEN;
+    keys->encryptionOn = exp[idx++];
+    keys->decryptedCur = exp[idx++];
+
+    {
+        word16 i, wordCount, wordAdj = 0;
+
+        /* do window */
+        ato16(exp + idx, &wordCount);
+        idx += OPAQUE16_LEN;
+
+        if (wordCount > WOLFSSL_DTLS_WINDOW_WORDS) {
+            wordCount = WOLFSSL_DTLS_WINDOW_WORDS;
+            wordAdj = (WOLFSSL_DTLS_WINDOW_WORDS - wordCount) * sizeof(word32);
+        }
+
+        XMEMSET(keys->peerSeq[0].window, 0xFF, DTLS_SEQ_SZ);
+        for (i = 0; i < wordCount; i++) {
+            ato32(exp + idx, &keys->peerSeq[0].window[i]);
+            idx += OPAQUE32_LEN;
+        }
+        idx += wordAdj;
+
+        /* do prevWindow */
+        ato16(exp + idx, &wordCount);
+        idx += OPAQUE16_LEN;
+
+        if (wordCount > WOLFSSL_DTLS_WINDOW_WORDS) {
+            wordCount = WOLFSSL_DTLS_WINDOW_WORDS;
+            wordAdj = (WOLFSSL_DTLS_WINDOW_WORDS - wordCount) * sizeof(word32);
+        }
+
+        XMEMSET(keys->peerSeq[0].prevWindow, 0xFF, DTLS_SEQ_SZ);
+        for (i = 0; i < wordCount; i++) {
+            ato32(exp + idx, &keys->peerSeq[0].prevWindow[i]);
+            idx += OPAQUE32_LEN;
+        }
+        idx += wordAdj;
+
+    }
+
+#ifdef HAVE_TRUNCATED_HMAC
+    ssl->truncated_hmac = exp[idx++];
+#else
+    idx++; /* no truncated hmac */
+#endif
+    sz = exp[idx++];
+#ifndef WOLFSSL_AEAD_ONLY
+    if (sz > sizeof(keys->client_write_MAC_secret) || (sz * 2) + idx > len) {
+        WOLFSSL_MSG("Buffer not large enough for MAC import");
+        return BUFFER_E;
+    }
+    if (sz > 0) {
+        XMEMCPY(keys->client_write_MAC_secret, exp + idx, sz); idx += sz;
+        XMEMCPY(keys->server_write_MAC_secret, exp + idx, sz); idx += sz;
+    }
+#else
+    if (sz + idx > len) {
+        return BUFFER_E;
+    }
+    idx += sz; idx += sz;
+#endif
+
+    sz = exp[idx++];
+    if (sz > sizeof(keys->client_write_key) || (sz * 2) + idx > len) {
+        WOLFSSL_MSG("Buffer not large enough for key import");
+        return BUFFER_E;
+    }
+    if (sz > 0) {
+        XMEMCPY(keys->client_write_key, exp + idx, sz); idx += sz;
+        XMEMCPY(keys->server_write_key, exp + idx, sz); idx += sz;
+    }
+
+    sz = exp[idx++];
+    if (sz > sizeof(keys->client_write_IV) || (sz * 2) + idx > len) {
+        WOLFSSL_MSG("Buffer not large enough for write IV import");
+        return BUFFER_E;
+    }
+    if (sz > 0) {
+        XMEMCPY(keys->client_write_IV, exp + idx, sz); idx += sz;
+        XMEMCPY(keys->server_write_IV, exp + idx, sz); idx += sz;
+    }
+    XMEMCPY(keys->aead_exp_IV, exp + idx, AEAD_MAX_EXP_SZ);
+    idx += AEAD_MAX_EXP_SZ;
+
+    sz = exp[idx++];
+    if (sz > sizeof(keys->aead_enc_imp_IV) || (sz * 2) + idx > len) {
+        WOLFSSL_MSG("Buffer not large enough for imp IV import");
+        return BUFFER_E;
+    }
+    if (sz > 0) {
+        XMEMCPY(keys->aead_enc_imp_IV, exp + idx, sz); idx += sz;
+        XMEMCPY(keys->aead_dec_imp_IV, exp + idx, sz); idx += sz;
+    }
+
+    WOLFSSL_LEAVE("ImportKeyState", idx);
+    (void)ver;
+    return idx;
+}
+
+
+/* copy over necessary information from Options struct to buffer
+ * On success returns size of buffer used on failure returns a negative value */
+static int dtls_export_new(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
+{
+    int idx = 0;
+    word16 zero = 0;
+    Options* options = &ssl->options;
+
+    WOLFSSL_ENTER("dtls_export_new");
+
+    if (exp == NULL || options == NULL || len < DTLS_EXPORT_OPT_SZ) {
+        return BAD_FUNC_ARG;
+    }
+
+    XMEMSET(exp, 0, DTLS_EXPORT_OPT_SZ);
+
+    /* these options are kept and sent to indicate verify status and strength
+     * of handshake */
+    exp[idx++] = options->sendVerify;
+    exp[idx++] = options->verifyPeer;
+    exp[idx++] = options->verifyNone;
+    exp[idx++] = options->downgrade;
+#ifndef NO_DH
+    c16toa(options->minDhKeySz, exp + idx); idx += OPAQUE16_LEN;
+    c16toa(options->maxDhKeySz, exp + idx); idx += OPAQUE16_LEN;
+    c16toa(options->dhKeySz, exp + idx);    idx += OPAQUE16_LEN;
+#else
+    c16toa(zero, exp + idx); idx += OPAQUE16_LEN;
+    c16toa(zero, exp + idx); idx += OPAQUE16_LEN;
+    c16toa(zero, exp + idx); idx += OPAQUE16_LEN;
+#endif
+#ifndef NO_RSA
+    c16toa((word16)(options->minRsaKeySz), exp + idx); idx += OPAQUE16_LEN;
+#else
+    c16toa(zero, exp + idx); idx += OPAQUE16_LEN;
+#endif
+#ifdef HAVE_ECC
+    c16toa((word16)(options->minEccKeySz), exp + idx); idx += OPAQUE16_LEN;
+#else
+    c16toa(zero, exp + idx); idx += OPAQUE16_LEN;
+#endif
+
+    /* these options are kept to indicate state and behavior */
+#ifndef NO_PSK
+    exp[idx++] = options->havePSK;
+#else
+    exp[idx++] = 0;
+#endif
+    exp[idx++] = options->sessionCacheOff;
+    exp[idx++] = options->sessionCacheFlushOff;
+    exp[idx++] = options->side;
+    exp[idx++] = options->resuming;
+    exp[idx++] = options->haveSessionId;
+    exp[idx++] = options->tls;
+    exp[idx++] = options->tls1_1;
+    exp[idx++] = options->dtls;
+    exp[idx++] = options->connReset;
+    exp[idx++] = options->isClosed;
+    exp[idx++] = options->closeNotify;
+    exp[idx++] = options->sentNotify;
+    exp[idx++] = options->usingCompression;
+    exp[idx++] = options->haveRSA;
+    exp[idx++] = options->haveECC;
+    exp[idx++] = options->haveDH;
+    exp[idx++] = options->haveNTRU;
+    exp[idx++] = options->haveQSH;
+    exp[idx++] = options->haveECDSAsig;
+    exp[idx++] = options->haveStaticECC;
+    exp[idx++] = options->havePeerVerify;
+    exp[idx++] = options->usingPSK_cipher;
+    exp[idx++] = options->usingAnon_cipher;
+    exp[idx++] = options->sendAlertState;
+    exp[idx++] = options->partialWrite;
+    exp[idx++] = options->quietShutdown;
+    exp[idx++] = options->groupMessages;
+#ifdef HAVE_POLY1305
+    exp[idx++] = options->oldPoly;
+#else
+    exp[idx++] = 0;
+#endif
+#ifdef HAVE_ANON
+    exp[idx++] = options->haveAnon;
+#else
+    exp[idx++] = 0;
+#endif
+#ifdef HAVE_SESSION_TICKET
+    exp[idx++] = options->createTicket;
+    exp[idx++] = options->useTicket;
+#ifdef WOLFSSL_TLS13
+    if (ver > DTLS_EXPORT_VERSION_3) {
+        exp[idx++] = options->noTicketTls13;
+    }
+#else
+    if (ver > DTLS_EXPORT_VERSION_3) {
+        exp[idx++] = 0;
+    }
+#endif
+#else
+    exp[idx++] = 0;
+    exp[idx++] = 0;
+    if (ver > DTLS_EXPORT_VERSION_3) {
+        exp[idx++] = 0;
+    }
+#endif
+    exp[idx++] = options->processReply;
+    exp[idx++] = options->cipherSuite0;
+    exp[idx++] = options->cipherSuite;
+    exp[idx++] = options->serverState;
+    exp[idx++] = options->clientState;
+    exp[idx++] = options->handShakeState;
+    exp[idx++] = options->handShakeDone;
+    exp[idx++] = options->minDowngrade;
+    exp[idx++] = options->connectState;
+    exp[idx++] = options->acceptState;
+    exp[idx++] = options->asyncState;
+
+    /* version of connection */
+    exp[idx++] = ssl->version.major;
+    exp[idx++] = ssl->version.minor;
+
+    (void)zero;
+
+    /* check if changes were made and notify of need to update export version */
+    switch (ver) {
+        case DTLS_EXPORT_VERSION_3:
+            if (idx != DTLS_EXPORT_OPT_SZ_3) {
+                WOLFSSL_MSG("Update DTLS_EXPORT_OPT_SZ and version of export");
+                return DTLS_EXPORT_VER_E;
+            }
+            break;
+
+        case DTLS_EXPORT_VERSION:
+            if (idx != DTLS_EXPORT_OPT_SZ) {
+                WOLFSSL_MSG("Update DTLS_EXPORT_OPT_SZ and version of export");
+                return DTLS_EXPORT_VER_E;
+            }
+            break;
+
+       default:
+            WOLFSSL_MSG("New version case needs added to wolfSSL export");
+            return DTLS_EXPORT_VER_E;
+    }
+
+    WOLFSSL_LEAVE("dtls_export_new", idx);
+
+    return idx;
+}
+
+
+/* copy items from Export struct to Options struct
+ * On success returns size of buffer used on failure returns a negative value */
+static int dtls_export_load(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
+{
+    int idx = 0;
+    Options* options = &ssl->options;
+
+    switch (ver) {
+        case DTLS_EXPORT_VERSION:
+            if (len < DTLS_EXPORT_OPT_SZ) {
+                WOLFSSL_MSG("Sanity check on buffer size failed");
+                return BAD_FUNC_ARG;
+            }
+            break;
+
+        case DTLS_EXPORT_VERSION_3:
+            if (len < DTLS_EXPORT_OPT_SZ_3) {
+                WOLFSSL_MSG("Sanity check on buffer size failed");
+                return BAD_FUNC_ARG;
+            }
+            break;
+
+        default:
+            WOLFSSL_MSG("Export version not supported");
+            return BAD_FUNC_ARG;
+    }
+
+    if (exp == NULL || options == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+
+    /* these options are kept and sent to indicate verify status and strength
+     * of handshake */
+    options->sendVerify = exp[idx++];
+    options->verifyPeer = exp[idx++];
+    options->verifyNone = exp[idx++];
+    options->downgrade  = exp[idx++];
+#ifndef NO_DH
+    ato16(exp + idx, &(options->minDhKeySz)); idx += OPAQUE16_LEN;
+    ato16(exp + idx, &(options->maxDhKeySz)); idx += OPAQUE16_LEN;
+    ato16(exp + idx, &(options->dhKeySz));    idx += OPAQUE16_LEN;
+#else
+    idx += OPAQUE16_LEN;
+    idx += OPAQUE16_LEN;
+    idx += OPAQUE16_LEN;
+#endif
+#ifndef NO_RSA
+    ato16(exp + idx, (word16*)&(options->minRsaKeySz)); idx += OPAQUE16_LEN;
+#else
+    idx += OPAQUE16_LEN;
+#endif
+#ifdef HAVE_ECC
+    ato16(exp + idx, (word16*)&(options->minEccKeySz)); idx += OPAQUE16_LEN;
+#else
+    idx += OPAQUE16_LEN;
+#endif
+
+    /* these options are kept to indicate state and behavior */
+#ifndef NO_PSK
+    options->havePSK = exp[idx++];
+#else
+    idx++;
+#endif
+    options->sessionCacheOff      = exp[idx++];
+    options->sessionCacheFlushOff = exp[idx++];
+    options->side                 = exp[idx++];
+    options->resuming             = exp[idx++];
+    options->haveSessionId    = exp[idx++];
+    options->tls              = exp[idx++];
+    options->tls1_1           = exp[idx++];
+    options->dtls             = exp[idx++];
+    options->connReset        = exp[idx++];
+    options->isClosed         = exp[idx++];
+    options->closeNotify      = exp[idx++];
+    options->sentNotify       = exp[idx++];
+    options->usingCompression = exp[idx++];
+    options->haveRSA          = exp[idx++];
+    options->haveECC          = exp[idx++];
+    options->haveDH           = exp[idx++];
+    options->haveNTRU         = exp[idx++];
+    options->haveQSH          = exp[idx++];
+    options->haveECDSAsig     = exp[idx++];
+    options->haveStaticECC    = exp[idx++];
+    options->havePeerVerify   = exp[idx++];
+    options->usingPSK_cipher  = exp[idx++];
+    options->usingAnon_cipher = exp[idx++];
+    options->sendAlertState   = exp[idx++];
+    options->partialWrite     = exp[idx++];
+    options->quietShutdown    = exp[idx++];
+    options->groupMessages    = exp[idx++];
+#ifdef HAVE_POLY1305
+    options->oldPoly = exp[idx++];      /* set when to use old rfc way of poly*/
+#else
+    idx++;
+#endif
+#ifdef HAVE_ANON
+    options->haveAnon = exp[idx++];     /* User wants to allow Anon suites */
+#else
+    idx++;
+#endif
+#ifdef HAVE_SESSION_TICKET
+    options->createTicket  = exp[idx++]; /* Server to create new Ticket */
+    options->useTicket     = exp[idx++]; /* Use Ticket not session cache */
+#ifdef WOLFSSL_TLS13
+    if (ver > DTLS_EXPORT_VERSION_3) {
+        options->noTicketTls13 = exp[idx++];/* Server won't create new Ticket */
+    }
+#else
+    if (ver > DTLS_EXPORT_VERSION_3) {
+        exp[idx++] = 0;
+    }
+#endif
+#else
+    idx++;
+    idx++;
+    if (ver > DTLS_EXPORT_VERSION_3) {
+        idx++;
+    }
+#endif
+    options->processReply   = exp[idx++];
+    options->cipherSuite0   = exp[idx++];
+    options->cipherSuite    = exp[idx++];
+    options->serverState    = exp[idx++];
+    options->clientState    = exp[idx++];
+    options->handShakeState = exp[idx++];
+    options->handShakeDone  = exp[idx++];
+    options->minDowngrade   = exp[idx++];
+    options->connectState   = exp[idx++];
+    options->acceptState    = exp[idx++];
+    options->asyncState     = exp[idx++];
+
+    /* version of connection */
+    if (ssl->version.major != exp[idx++] || ssl->version.minor != exp[idx++]) {
+        WOLFSSL_MSG("Version mismatch ie DTLS v1 vs v1.2");
+        return VERSION_ERROR;
+    }
+
+    return idx;
+}
+
+#ifndef WOLFSSL_SESSION_EXPORT_NOPEER
+static int ExportPeerInfo(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
+{
+    int    idx  = 0;
+    int    ipSz = DTLS_EXPORT_IP; /* start as max size */
+    int    fam  = 0;
+    word16 port = 0;
+    char   ip[DTLS_EXPORT_IP];
+
+    if (ver != DTLS_EXPORT_VERSION) {
+        WOLFSSL_MSG("Export version not supported");
+        return BAD_FUNC_ARG;
+    }
+
+    if (ssl == NULL || exp == NULL || len < sizeof(ip) + 3 * DTLS_EXPORT_LEN) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (ssl->ctx->CBGetPeer == NULL) {
+        WOLFSSL_MSG("No get peer call back set");
+        return BAD_FUNC_ARG;
+    }
+    if (ssl->ctx->CBGetPeer(ssl, ip, &ipSz, &port, &fam) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("Get peer callback error");
+        return SOCKET_ERROR_E;
+    }
+
+    /* check that ipSz/fam is not negative or too large since user can set cb */
+    if (ipSz < 0 || ipSz > DTLS_EXPORT_IP || fam < 0) {
+        WOLFSSL_MSG("Bad ipSz or fam returned from get peer callback");
+        return SOCKET_ERROR_E;
+    }
+
+    c16toa((word16)fam, exp + idx);  idx += DTLS_EXPORT_LEN;
+    c16toa((word16)ipSz, exp + idx); idx += DTLS_EXPORT_LEN;
+    XMEMCPY(exp + idx, ip, ipSz);    idx += ipSz;
+    c16toa(port, exp + idx);         idx += DTLS_EXPORT_LEN;
+
+    return idx;
+}
+#endif /* !WOLFSSL_SESSION_EXPORT_NOPEER */
+
+
+static int ImportPeerInfo(WOLFSSL* ssl, byte* buf, word32 len, byte ver)
+{
+    word16 idx = 0;
+    word16 ipSz;
+    word16 fam;
+    word16 port;
+    char   ip[DTLS_EXPORT_IP];
+
+    if (ver != DTLS_EXPORT_VERSION && ver != DTLS_EXPORT_VERSION_3) {
+        WOLFSSL_MSG("Export version not supported");
+        return BAD_FUNC_ARG;
+    }
+
+    if (len == 0) {
+        WOLFSSL_MSG("No peer info sent");
+        return 0;
+    }
+
+    if (ssl == NULL || buf == NULL || len < 3 * DTLS_EXPORT_LEN) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* import sin family */
+    ato16(buf + idx, &fam); idx += DTLS_EXPORT_LEN;
+
+    /* import ip address idx, and ipSz are unsigned but cast for enum */
+    ato16(buf + idx, &ipSz); idx += DTLS_EXPORT_LEN;
+    if (ipSz >= sizeof(ip) || (word16)(idx + ipSz + DTLS_EXPORT_LEN) > len) {
+        return BUFFER_E;
+    }
+    XMEMSET(ip, 0, sizeof(ip));
+    XMEMCPY(ip, buf + idx, ipSz); idx += ipSz;
+    ip[ipSz] = '\0'; /* with check that ipSz less than ip this is valid */
+    ato16(buf + idx, &port); idx += DTLS_EXPORT_LEN;
+
+    /* sanity check for a function to call, then use it to import peer info */
+    if (ssl->ctx->CBSetPeer == NULL) {
+        WOLFSSL_MSG("No set peer function");
+        return BAD_FUNC_ARG;
+    }
+    if (ssl->ctx->CBSetPeer(ssl, ip, ipSz, port, fam) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("Error setting peer info");
+        return SOCKET_ERROR_E;
+    }
+
+    return idx;
+}
+
+
+/* WOLFSSL_LOCAL function that serializes the current WOLFSSL session state only
+ * buf is used to hold the serialized WOLFSSL struct and sz is the size of buf
+ * passed in.
+ * On success returns the size of serialized session state.*/
+int wolfSSL_dtls_export_state_internal(WOLFSSL* ssl, byte* buf, word32 sz)
+{
+    int ret;
+    word32 idx      = 0;
+    word32 totalLen = 0;
+
+    WOLFSSL_ENTER("wolfSSL_dtls_export_state_internal");
+
+    if (buf == NULL || ssl == NULL) {
+        WOLFSSL_LEAVE("wolfSSL_dtls_export_state_internal", BAD_FUNC_ARG);
+        return BAD_FUNC_ARG;
+    }
+
+    totalLen += DTLS_EXPORT_LEN * 2; /* 2 protocol bytes and 2 length bytes */
+    /* each of the following have a 2 byte length before data */
+    totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_MIN_KEY_SZ;
+    if (totalLen > sz) {
+        WOLFSSL_LEAVE("wolfSSL_dtls_export_state_internal", BUFFER_E);
+        return BUFFER_E;
+    }
+
+    buf[idx++] =  (byte)DTLS_EXPORT_STATE_PRO;
+    buf[idx++] = ((byte)DTLS_EXPORT_STATE_PRO & 0xF0) |
+                 ((byte)DTLS_EXPORT_VERSION & 0X0F);
+    idx += DTLS_EXPORT_LEN; /* leave room for total length */
+
+    /* export keys struct and dtls state -- variable length stored in ret */
+    idx += DTLS_EXPORT_LEN; /* leave room for length */
+    if ((ret = ExportKeyState(ssl, buf + idx, sz - idx,
+                                                 DTLS_EXPORT_VERSION, 1)) < 0) {
+        WOLFSSL_LEAVE("wolfSSL_dtls_export_state_internal", ret);
+        return ret;
+    }
+    c16toa((word16)ret, buf + idx - DTLS_EXPORT_LEN); idx += ret;
+
+    /* place total length of exported buffer minus 2 bytes protocol/version */
+    c16toa((word16)(idx - DTLS_EXPORT_LEN), buf + DTLS_EXPORT_LEN);
+
+#ifdef WOLFSSL_SESSION_EXPORT_DEBUG
+    /* if compiled with debug options then print the version, protocol, size */
+    {
+        char debug[256];
+        XSNPRINTF(debug, sizeof(debug), "Exporting DTLS session state\n"
+                   "\tVersion  : %d\n\tProtocol : %02X%01X\n\tLength of: %d\n\n"
+               , (int)DTLS_EXPORT_VERSION, buf[0], (buf[1] >> 4), idx - 2);
+        WOLFSSL_MSG(debug);
+    }
+#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */
+
+    WOLFSSL_LEAVE("wolfSSL_dtls_export_state_internal", idx);
+    return idx;
+}
+
+
+/* WOLFSSL_LOCAL function that serializes the current WOLFSSL session
+ * buf is used to hold the serialized WOLFSSL struct and sz is the size of buf
+ * passed in.
+ * On success returns the size of serialized session.*/
+int wolfSSL_dtls_export_internal(WOLFSSL* ssl, byte* buf, word32 sz)
+{
+    int ret;
+    word32 idx      = 0;
+    word32 totalLen = 0;
+
+    WOLFSSL_ENTER("wolfSSL_dtls_export_internal");
+
+    if (buf == NULL || ssl == NULL) {
+        WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", BAD_FUNC_ARG);
+        return BAD_FUNC_ARG;
+    }
+
+    totalLen += DTLS_EXPORT_LEN * 2; /* 2 protocol bytes and 2 length bytes */
+    /* each of the following have a 2 byte length before data */
+    totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_OPT_SZ;
+    totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_KEY_SZ;
+    totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_SPC_SZ;
+    totalLen += DTLS_EXPORT_LEN + ssl->buffers.dtlsCtx.peer.sz;
+
+    if (totalLen > sz) {
+        WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", BUFFER_E);
+        return BUFFER_E;
+    }
+
+    buf[idx++] =  (byte)DTLS_EXPORT_PRO;
+    buf[idx++] = ((byte)DTLS_EXPORT_PRO & 0xF0) |
+                 ((byte)DTLS_EXPORT_VERSION & 0X0F);
+
+    idx += DTLS_EXPORT_LEN; /* leave spot for length */
+
+    c16toa((word16)DTLS_EXPORT_OPT_SZ, buf + idx); idx += DTLS_EXPORT_LEN;
+    if ((ret = dtls_export_new(ssl, buf + idx, sz - idx,
+                                                    DTLS_EXPORT_VERSION)) < 0) {
+        WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret);
+        return ret;
+    }
+    idx += ret;
+
+    /* export keys struct and dtls state -- variable length stored in ret */
+    idx += DTLS_EXPORT_LEN; /* leave room for length */
+    if ((ret = ExportKeyState(ssl, buf + idx, sz - idx,
+                                                 DTLS_EXPORT_VERSION, 0)) < 0) {
+        WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret);
+        return ret;
+    }
+    c16toa((word16)ret, buf + idx - DTLS_EXPORT_LEN); idx += ret;
+
+    /* export of cipher specs struct */
+    c16toa((word16)DTLS_EXPORT_SPC_SZ, buf + idx); idx += DTLS_EXPORT_LEN;
+    if ((ret = ExportCipherSpecState(ssl, buf + idx, sz - idx,
+                                                    DTLS_EXPORT_VERSION)) < 0) {
+        WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret);
+        return ret;
+    }
+    idx += ret;
+
+    /* export of dtls peer information */
+    idx += DTLS_EXPORT_LEN;
+#ifdef WOLFSSL_SESSION_EXPORT_NOPEER
+    ret = 0; /* not saving peer port/ip information */
+#else
+    if ((ret = ExportPeerInfo(ssl, buf + idx, sz - idx,
+                                                    DTLS_EXPORT_VERSION)) < 0) {
+        WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret);
+        return ret;
+    }
+#endif
+    c16toa(ret, buf + idx - DTLS_EXPORT_LEN);
+    idx += ret;
+
+    /* place total length of exported buffer minus 2 bytes protocol/version */
+    c16toa((word16)(idx - DTLS_EXPORT_LEN), buf + DTLS_EXPORT_LEN);
+
+    /* if compiled with debug options then print the version, protocol, size */
+#ifdef WOLFSSL_SESSION_EXPORT_DEBUG
+    {
+        char debug[256];
+        XSNPRINTF(debug, sizeof(debug), "Exporting DTLS session\n"
+                   "\tVersion  : %d\n\tProtocol : %02X%01X\n\tLength of: %d\n\n"
+               , (int)DTLS_EXPORT_VERSION, buf[0], (buf[1] >> 4), idx - 2);
+        WOLFSSL_MSG(debug);
+    }
+#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */
+
+    WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", idx);
+    return idx;
+}
+
+
+/* On success return amount of buffer consumed */
+int wolfSSL_dtls_import_state_internal(WOLFSSL* ssl, byte* buf, word32 sz)
+{
+    word32 idx    = 0;
+    word16 length = 0;
+    int version;
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_dtls_import_state_internal");
+    /* check at least enough room for protocol and length */
+    if (sz < DTLS_EXPORT_LEN * 2 || ssl == NULL) {
+        WOLFSSL_LEAVE("wolfSSL_dtls_import_state_internal", BAD_FUNC_ARG);
+        return BAD_FUNC_ARG;
+    }
+
+    if (buf[idx++] !=  (byte)DTLS_EXPORT_STATE_PRO ||
+            (buf[idx] & 0xF0) != ((byte)DTLS_EXPORT_PRO & 0xF0)) {
+        WOLFSSL_MSG("Incorrect protocol");
+        return BAD_FUNC_ARG;
+    }
+    version = buf[idx++] & 0x0F;
+
+    ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
+    if (length > sz - DTLS_EXPORT_LEN) { /* subtract 2 for protocol */
+        WOLFSSL_MSG("Buffer size sanity check failed");
+        return BUFFER_E;
+    }
+
+#ifdef WOLFSSL_SESSION_EXPORT_DEBUG
+    /* if compiled with debug options then print the version, protocol, size */
+    {
+        char debug[256];
+        XSNPRINTF(debug, sizeof(debug), "Importing DTLS session state\n"
+                   "\tVersion  : %d\n\tProtocol : %02X%01X\n\tLength of: %d\n\n"
+               , (int)version, buf[0], (buf[1] >> 4), length);
+        WOLFSSL_MSG(debug);
+    }
+#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */
+
+    /* perform sanity checks and extract Options information used */
+    switch (version) {
+        case DTLS_EXPORT_VERSION:
+            break;
+
+        default:
+            WOLFSSL_MSG("Bad export state version");
+            return BAD_FUNC_ARG;
+
+    }
+
+    /* perform sanity checks and extract Keys struct */
+    if (DTLS_EXPORT_LEN + idx > sz) {
+        WOLFSSL_MSG("Import Key struct error");
+        return BUFFER_E;
+    }
+    ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
+    if (length > DTLS_EXPORT_KEY_SZ || length + idx > sz) {
+        WOLFSSL_MSG("Import Key struct error");
+        return BUFFER_E;
+    }
+    if ((ret = ImportKeyState(ssl, buf + idx, length, version)) < 0) {
+        WOLFSSL_MSG("Import Key struct error");
+        WOLFSSL_LEAVE("wolfSSL_dtls_import_state_internal", ret);
+        return ret;
+    }
+    idx += ret;
+
+    WOLFSSL_LEAVE("wolfSSL_dtls_import_state_internal", ret);
+    return ret;
+}
+
+
+/* On success return amount of buffer consumed */
+int wolfSSL_dtls_import_internal(WOLFSSL* ssl, byte* buf, word32 sz)
+{
+    word32 idx    = 0;
+    word16 length = 0;
+    int version;
+    int ret;
+    int optSz;
+
+    WOLFSSL_ENTER("wolfSSL_dtls_import_internal");
+    /* check at least enough room for protocol and length */
+    if (sz < DTLS_EXPORT_LEN * 2 || ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* sanity check on protocol ID and size of buffer */
+    if (buf[idx++]       !=  (byte)DTLS_EXPORT_PRO ||
+       (buf[idx] & 0xF0) != ((byte)DTLS_EXPORT_PRO & 0xF0)) {
+        /* don't increment on second idx to next get version */
+
+        /* check if importing state only */
+        return wolfSSL_dtls_import_state_internal(ssl, buf, sz);
+    }
+    version = buf[idx++] & 0x0F;
+
+    ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
+    if (length > sz - DTLS_EXPORT_LEN) { /* subtract 2 for protocol */
+        return BUFFER_E;
+    }
+
+    /* if compiled with debug options then print the version, protocol, size */
+#ifdef WOLFSSL_SESSION_EXPORT_DEBUG
+    {
+        char debug[256];
+        XSNPRINTF(debug, sizeof(debug), "Importing DTLS session\n"
+                   "\tVersion  : %d\n\tProtocol : %02X%01X\n\tLength of: %d\n\n"
+               , (int)version, buf[0], (buf[1] >> 4), length);
+        WOLFSSL_MSG(debug);
+    }
+#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */
+
+    /* perform sanity checks and extract Options information used */
+    switch (version) {
+        case DTLS_EXPORT_VERSION:
+            optSz = DTLS_EXPORT_OPT_SZ;
+            break;
+
+        case DTLS_EXPORT_VERSION_3:
+            WOLFSSL_MSG("Importing older version 3");
+            optSz = DTLS_EXPORT_OPT_SZ_3;
+            break;
+
+        default:
+            WOLFSSL_MSG("Bad export version");
+            return BAD_FUNC_ARG;
+
+    }
+
+    if (DTLS_EXPORT_LEN + optSz + idx > sz) {
+        WOLFSSL_MSG("Import Options struct error");
+        return BUFFER_E;
+    }
+    ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
+    if (length != optSz) {
+        WOLFSSL_MSG("Import Options struct error");
+        return BUFFER_E;
+    }
+    if ((ret = dtls_export_load(ssl, buf + idx, length, version)) < 0) {
+        WOLFSSL_MSG("Import Options struct error");
+        return ret;
+    }
+    idx += length;
+
+    /* perform sanity checks and extract Keys struct */
+    if (DTLS_EXPORT_LEN + idx > sz) {
+        WOLFSSL_MSG("Import Key struct error");
+        return BUFFER_E;
+    }
+    ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
+    if (length > DTLS_EXPORT_KEY_SZ || length + idx > sz) {
+        WOLFSSL_MSG("Import Key struct error");
+        return BUFFER_E;
+    }
+    if ((ret = ImportKeyState(ssl, buf + idx, length, version)) < 0) {
+        WOLFSSL_MSG("Import Key struct error");
+        return ret;
+    }
+    idx += ret;
+
+    /* perform sanity checks and extract CipherSpecs struct */
+    if (DTLS_EXPORT_LEN + DTLS_EXPORT_SPC_SZ + idx > sz) {
+        WOLFSSL_MSG("Import CipherSpecs struct error");
+        return BUFFER_E;
+    }
+    ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
+    if ( length != DTLS_EXPORT_SPC_SZ) {
+        WOLFSSL_MSG("Import CipherSpecs struct error");
+        return BUFFER_E;
+    }
+    if ((ret = ImportCipherSpecState(ssl, buf + idx, length, version)) < 0) {
+        WOLFSSL_MSG("Import CipherSpecs struct error");
+        return ret;
+    }
+    idx += ret;
+
+    /* perform sanity checks and extract DTLS peer info */
+    if (DTLS_EXPORT_LEN + idx > sz) {
+        WOLFSSL_MSG("Import DTLS peer info error");
+        return BUFFER_E;
+    }
+    ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
+    if (idx + length > sz) {
+        WOLFSSL_MSG("Import DTLS peer info error");
+        return BUFFER_E;
+    }
+    if ((ret = ImportPeerInfo(ssl, buf + idx, length, version)) < 0) {
+        WOLFSSL_MSG("Import Peer Addr error");
+        return ret;
+    }
+    idx += ret;
+
+    SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE);
+
+    /* set hmac function to use when verifying */
+    if (ssl->options.tls == 1 || ssl->options.tls1_1 == 1 ||
+            ssl->options.dtls == 1) {
+        ssl->hmac = TLS_hmac;
+    }
+
+    /* make sure is a valid suite used */
+    if (wolfSSL_get_cipher(ssl) == NULL) {
+        WOLFSSL_MSG("Can not match cipher suite imported");
+        return MATCH_SUITE_ERROR;
+    }
+
+    /* do not allow stream ciphers with DTLS, except for NULL cipher */
+    if (ssl->specs.cipher_type == stream &&
+        ssl->specs.bulk_cipher_algorithm != wolfssl_cipher_null) {
+        WOLFSSL_MSG("Can not import stream ciphers for DTLS");
+        return SANITY_CIPHER_E;
+    }
+
+    return idx;
+}
+#endif /* WOLFSSL_DTLS */
+#endif /* WOLFSSL_SESSION_EXPORT */
+
+
+void InitSSL_Method(WOLFSSL_METHOD* method, ProtocolVersion pv)
+{
+    method->version    = pv;
+    method->side       = WOLFSSL_CLIENT_END;
+    method->downgrade  = 0;
+}
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
+int InitSSL_Side(WOLFSSL* ssl, word16 side)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    /* set side */
+    ssl->options.side = side;
+
+    /* reset options that are side specific */
+#ifdef HAVE_NTRU
+    if (ssl->options.side == WOLFSSL_CLIENT_END) {
+        ssl->options.haveNTRU = 1;      /* always on client side */
+                                        /* server can turn on by loading key */
+    }
+#endif
+#ifdef HAVE_ECC
+    if (ssl->options.side == WOLFSSL_CLIENT_END) {
+        ssl->options.haveECDSAsig  = 1; /* always on client side */
+        ssl->options.haveECC = 1;       /* server turns on with ECC key cert */
+        ssl->options.haveStaticECC = 1; /* server can turn on by loading key */
+    }
+#elif defined(HAVE_ED25519) || defined(HAVE_ED448)
+    if (ssl->options.side == WOLFSSL_CLIENT_END) {
+        ssl->options.haveECDSAsig  = 1; /* always on client side */
+        ssl->options.haveECC  = 1;      /* server turns on with ECC key cert */
+    }
+#endif
+
+#if defined(HAVE_EXTENDED_MASTER) && !defined(NO_WOLFSSL_CLIENT)
+    if (ssl->options.side == WOLFSSL_CLIENT_END) {
+        if ((ssl->ctx->method->version.major == SSLv3_MAJOR) &&
+             (ssl->ctx->method->version.minor >= TLSv1_MINOR)) {
+            ssl->options.haveEMS = 1;
+        }
+    #ifdef WOLFSSL_DTLS
+        if (ssl->ctx->method->version.major == DTLS_MAJOR)
+            ssl->options.haveEMS = 1;
+    #endif /* WOLFSSL_DTLS */
+    }
+#endif /* HAVE_EXTENDED_MASTER && !NO_WOLFSSL_CLIENT */
+
+#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
+    if (ssl->options.dtls && ssl->options.side == WOLFSSL_SERVER_END) {
+        int ret;
+        ret = wolfSSL_DTLS_SetCookieSecret(ssl, NULL, 0);
+        if (ret != 0) {
+            WOLFSSL_MSG("DTLS Cookie Secret error");
+            return ret;
+        }
+    }
+#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */
+
+    return InitSSL_Suites(ssl);
+}
+#endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */
+
+/* Initialize SSL context, return 0 on success */
+int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap)
+{
+    int ret = 0;
+
+    XMEMSET(ctx, 0, sizeof(WOLFSSL_CTX));
+
+    ctx->method   = method;
+    ctx->refCount = 1;          /* so either CTX_free or SSL_free can release */
+    ctx->heap     = ctx;        /* defaults to self */
+    ctx->timeout  = WOLFSSL_SESSION_TIMEOUT;
+    ctx->minDowngrade = WOLFSSL_MIN_DOWNGRADE; /* current default: TLSv1_MINOR */
+
+    if (wc_InitMutex(&ctx->countMutex) < 0) {
+        WOLFSSL_MSG("Mutex error on CTX init");
+        ctx->err = CTX_INIT_MUTEX_E;
+        return BAD_MUTEX_E;
+    }
+
+#ifndef NO_DH
+    ctx->minDhKeySz  = MIN_DHKEY_SZ;
+    ctx->maxDhKeySz  = MAX_DHKEY_SZ;
+#endif
+#ifndef NO_RSA
+    ctx->minRsaKeySz = MIN_RSAKEY_SZ;
+#endif
+#ifdef HAVE_ECC
+    ctx->minEccKeySz  = MIN_ECCKEY_SZ;
+    ctx->eccTempKeySz = ECDHE_SIZE;
+#endif
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+    ctx->verifyDepth = MAX_CHAIN_DEPTH;
+#endif
+#ifdef OPENSSL_EXTRA
+    ctx->cbioFlag = WOLFSSL_CBIO_NONE;
+#endif
+
+#ifndef WOLFSSL_USER_IO
+    #ifdef MICRIUM
+        ctx->CBIORecv = MicriumReceive;
+        ctx->CBIOSend = MicriumSend;
+        #ifdef WOLFSSL_DTLS
+            if (method->version.major == DTLS_MAJOR) {
+                ctx->CBIORecv   = MicriumReceiveFrom;
+                ctx->CBIOSend   = MicriumSendTo;
+            }
+            #ifdef WOLFSSL_SESSION_EXPORT
+                #error Micrium port does not support DTLS session export yet
+            #endif
+        #endif
+    #elif defined WOLFSSL_UIP
+        ctx->CBIORecv = uIPReceive;
+        ctx->CBIOSend = uIPSend;
+        #ifdef WOLFSSL_DTLS
+        if (method->version.major == DTLS_MAJOR) {
+            ctx->CBIOSendTo = uIPSendTo;
+            ctx->CBIORecvFrom = uIPRecvFrom;
+        }
+        #endif
+    #else
+        ctx->CBIORecv = EmbedReceive;
+        ctx->CBIOSend = EmbedSend;
+        #ifdef WOLFSSL_DTLS
+            if (method->version.major == DTLS_MAJOR) {
+                ctx->CBIORecv   = EmbedReceiveFrom;
+                ctx->CBIOSend   = EmbedSendTo;
+            }
+            #ifdef WOLFSSL_SESSION_EXPORT
+            ctx->CBGetPeer = EmbedGetPeer;
+            ctx->CBSetPeer = EmbedSetPeer;
+            #endif
+        #endif
+    #endif /* MICRIUM */
+#endif /* WOLFSSL_USER_IO */
+
+#ifdef HAVE_NETX
+    ctx->CBIORecv = NetX_Receive;
+    ctx->CBIOSend = NetX_Send;
+#elif defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP)
+    ctx->CBIORecv = Mynewt_Receive;
+    ctx->CBIOSend = Mynewt_Send;
+#elif defined(WOLFSSL_GNRC)
+    ctx->CBIORecv = GNRC_ReceiveFrom;
+    ctx->CBIOSend = GNRC_SendTo;
+#endif
+
+#ifdef HAVE_NTRU
+    if (method->side == WOLFSSL_CLIENT_END)
+        ctx->haveNTRU = 1;           /* always on client side */
+                                     /* server can turn on by loading key */
+#endif
+#ifdef HAVE_ECC
+    if (method->side == WOLFSSL_CLIENT_END) {
+        ctx->haveECDSAsig  = 1;        /* always on client side */
+        ctx->haveECC  = 1;             /* server turns on with ECC key cert */
+        ctx->haveStaticECC = 1;        /* server can turn on by loading key */
+    }
+#elif defined(HAVE_ED25519) || defined(HAVE_ED448)
+    if (method->side == WOLFSSL_CLIENT_END) {
+        ctx->haveECDSAsig  = 1;        /* always on client side */
+        ctx->haveECC  = 1;             /* server turns on with ECC key cert */
+    }
+#endif
+
+    ctx->devId = INVALID_DEVID;
+
+#if defined(WOLFSSL_DTLS)
+    #ifdef WOLFSSL_SCTP
+        ctx->dtlsMtuSz = MAX_RECORD_SIZE;
+    #elif defined(WOLFSSL_DTLS_MTU)
+        ctx->dtlsMtuSz = MAX_MTU;
+    #endif
+#endif
+
+#ifndef NO_CERTS
+    ctx->cm = wolfSSL_CertManagerNew_ex(heap);
+    if (ctx->cm == NULL) {
+        WOLFSSL_MSG("Bad Cert Manager New");
+        return BAD_CERT_MANAGER_ERROR;
+    }
+    #ifdef OPENSSL_EXTRA
+    /* setup WOLFSSL_X509_STORE */
+    ctx->x509_store.cm = ctx->cm;
+    #endif
+#endif
+
+#if defined(HAVE_EXTENDED_MASTER) && !defined(NO_WOLFSSL_CLIENT)
+    if (method->side == WOLFSSL_CLIENT_END) {
+        if ((method->version.major == SSLv3_MAJOR) &&
+             (method->version.minor >= TLSv1_MINOR)) {
+
+            ctx->haveEMS = 1;
+        }
+#ifdef WOLFSSL_DTLS
+        if (method->version.major == DTLS_MAJOR)
+            ctx->haveEMS = 1;
+#endif /* WOLFSSL_DTLS */
+    }
+#endif /* HAVE_EXTENDED_MASTER && !NO_WOLFSSL_CLIENT */
+
+#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER)
+    ctx->ticketHint = SESSION_TICKET_HINT_DEFAULT;
+#endif
+
+#ifdef HAVE_WOLF_EVENT
+    ret = wolfEventQueue_Init(&ctx->event_queue);
+#endif /* HAVE_WOLF_EVENT */
+
+#ifdef WOLFSSL_EARLY_DATA
+    ctx->maxEarlyDataSz = MAX_EARLY_DATA_SZ;
+#endif
+
+    ctx->heap = heap; /* wolfSSL_CTX_load_static_memory sets */
+    ctx->verifyDepth = MAX_CHAIN_DEPTH;
+
+    return ret;
+}
+
+
+/* In case contexts are held in array and don't want to free actual ctx */
+void SSL_CtxResourceFree(WOLFSSL_CTX* ctx)
+{
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) && \
+                     defined(HAVE_TLS_EXTENSIONS) && !defined(NO_WOLFSSL_SERVER)
+    int i;
+#endif
+
+#ifdef HAVE_WOLF_EVENT
+    wolfEventQueue_Free(&ctx->event_queue);
+#endif /* HAVE_WOLF_EVENT */
+
+#ifdef WOLFSSL_STATIC_MEMORY
+    if (ctx->onHeap == 1) {
+        XFREE(ctx->method, ctx->heap, DYNAMIC_TYPE_METHOD);
+    }
+    else {
+        XFREE(ctx->method, NULL, DYNAMIC_TYPE_METHOD);
+    }
+#else
+    XFREE(ctx->method, ctx->heap, DYNAMIC_TYPE_METHOD);
+#endif
+    ctx->method = NULL;
+    if (ctx->suites) {
+        XFREE(ctx->suites, ctx->heap, DYNAMIC_TYPE_SUITES);
+        ctx->suites = NULL;
+    }
+
+#ifndef NO_DH
+    XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    ctx->serverDH_G.buffer = NULL;
+    XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    ctx->serverDH_P.buffer = NULL;
+#endif /* !NO_DH */
+
+#ifdef SINGLE_THREADED
+    if (ctx->rng) {
+        wc_FreeRng(ctx->rng);
+        XFREE(ctx->rng, ctx->heap, DYNAMIC_TYPE_RNG);
+        ctx->rng = NULL;
+    }
+#endif /* SINGLE_THREADED */
+
+#ifndef NO_CERTS
+    FreeDer(&ctx->privateKey);
+    FreeDer(&ctx->certificate);
+    #ifdef KEEP_OUR_CERT
+        if (ctx->ourCert && ctx->ownOurCert) {
+            FreeX509(ctx->ourCert);
+            XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509);
+            ctx->ourCert = NULL;
+        }
+    #endif /* KEEP_OUR_CERT */
+    FreeDer(&ctx->certChain);
+    wolfSSL_CertManagerFree(ctx->cm);
+    ctx->cm = NULL;
+    #ifdef OPENSSL_EXTRA
+    /* ctx->cm was free'd so cm of x509 store should now be NULL */
+        if (ctx->x509_store_pt != NULL) {
+            ctx->x509_store_pt->cm = NULL;
+        }
+        wolfSSL_X509_STORE_free(ctx->x509_store_pt);
+        while (ctx->ca_names != NULL) {
+            WOLFSSL_STACK *next = ctx->ca_names->next;
+            wolfSSL_X509_NAME_free(ctx->ca_names->data.name);
+            XFREE(ctx->ca_names, NULL, DYNAMIC_TYPE_OPENSSL);
+            ctx->ca_names = next;
+        }
+    #endif
+    #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+        while (ctx->x509Chain != NULL) {
+            WOLFSSL_STACK *next = ctx->x509Chain->next;
+            wolfSSL_X509_free(ctx->x509Chain->data.x509);
+            XFREE(ctx->x509Chain, NULL, DYNAMIC_TYPE_OPENSSL);
+            ctx->x509Chain = next;
+        }
+    #endif
+#endif /* !NO_CERTS */
+
+#ifdef HAVE_TLS_EXTENSIONS
+    TLSX_FreeAll(ctx->extensions, ctx->heap);
+
+#ifndef NO_WOLFSSL_SERVER
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+    if (ctx->certOcspRequest) {
+        FreeOcspRequest(ctx->certOcspRequest);
+        XFREE(ctx->certOcspRequest, ctx->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+    }
+#endif
+
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+    for (i = 0; i < MAX_CHAIN_DEPTH; i++) {
+        if (ctx->chainOcspRequest[i]) {
+            FreeOcspRequest(ctx->chainOcspRequest[i]);
+            XFREE(ctx->chainOcspRequest[i], ctx->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+            ctx->chainOcspRequest[i] = NULL;
+        }
+    }
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+#endif /* !NO_WOLFSSL_SERVER */
+
+#endif /* HAVE_TLS_EXTENSIONS */
+#ifdef OPENSSL_EXTRA
+    if(ctx->alpn_cli_protos) {
+        XFREE((void *)ctx->alpn_cli_protos, NULL, DYNAMIC_TYPE_OPENSSL);
+        ctx->alpn_cli_protos = NULL;
+    }
+#endif
+#ifdef WOLFSSL_STATIC_MEMORY
+    if (ctx->heap != NULL) {
+#ifdef WOLFSSL_HEAP_TEST
+        /* avoid dereferencing a test value */
+        if (ctx->heap != (void*)WOLFSSL_HEAP_TEST)
+#endif
+        {
+            WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)(ctx->heap);
+            wc_FreeMutex(&((WOLFSSL_HEAP*)(hint->memory))->memory_mutex);
+        }
+    }
+#endif /* WOLFSSL_STATIC_MEMORY */
+}
+
+
+void FreeSSL_Ctx(WOLFSSL_CTX* ctx)
+{
+    int refCount;
+
+    /* decrement CTX reference count */
+    if ((refCount = SSL_CTX_RefCount(ctx, -1)) < 0) {
+        /* check error state, if mutex error code then mutex init failed but
+         * CTX was still malloc'd */
+        if (ctx->err == CTX_INIT_MUTEX_E) {
+            SSL_CtxResourceFree(ctx);
+            XFREE(ctx, ctx->heap, DYNAMIC_TYPE_CTX);
+        }
+        return;
+    }
+
+    if (refCount == 0) {
+        void* heap = ctx->heap;
+        WOLFSSL_MSG("CTX ref count down to 0, doing full free");
+        SSL_CtxResourceFree(ctx);
+        wc_FreeMutex(&ctx->countMutex);
+#ifdef WOLFSSL_STATIC_MEMORY
+        if (ctx->onHeap == 0) {
+            heap = NULL;
+        }
+#endif
+        XFREE(ctx, heap, DYNAMIC_TYPE_CTX);
+        (void)heap; /* not used in some builds */
+    }
+    else {
+        (void)ctx;
+        WOLFSSL_MSG("CTX ref count not 0 yet, no free");
+    }
+}
+
+
+/* Set cipher pointers to null */
+void InitCiphers(WOLFSSL* ssl)
+{
+#ifdef BUILD_ARC4
+    ssl->encrypt.arc4 = NULL;
+    ssl->decrypt.arc4 = NULL;
+#endif
+#ifdef BUILD_DES3
+    ssl->encrypt.des3 = NULL;
+    ssl->decrypt.des3 = NULL;
+#endif
+#ifdef BUILD_AES
+    ssl->encrypt.aes = NULL;
+    ssl->decrypt.aes = NULL;
+#endif
+#ifdef HAVE_CAMELLIA
+    ssl->encrypt.cam = NULL;
+    ssl->decrypt.cam = NULL;
+#endif
+#ifdef HAVE_HC128
+    ssl->encrypt.hc128 = NULL;
+    ssl->decrypt.hc128 = NULL;
+#endif
+#ifdef BUILD_RABBIT
+    ssl->encrypt.rabbit = NULL;
+    ssl->decrypt.rabbit = NULL;
+#endif
+#ifdef HAVE_CHACHA
+    ssl->encrypt.chacha = NULL;
+    ssl->decrypt.chacha = NULL;
+#endif
+#if defined(HAVE_POLY1305) && defined(HAVE_ONE_TIME_AUTH)
+    ssl->auth.poly1305 = NULL;
+#endif
+    ssl->encrypt.setup = 0;
+    ssl->decrypt.setup = 0;
+#ifdef HAVE_ONE_TIME_AUTH
+    ssl->auth.setup    = 0;
+#endif
+#ifdef HAVE_IDEA
+    ssl->encrypt.idea = NULL;
+    ssl->decrypt.idea = NULL;
+#endif
+}
+
+
+/* Free ciphers */
+void FreeCiphers(WOLFSSL* ssl)
+{
+    (void)ssl;
+#ifdef BUILD_ARC4
+    wc_Arc4Free(ssl->encrypt.arc4);
+    wc_Arc4Free(ssl->decrypt.arc4);
+    XFREE(ssl->encrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER);
+    XFREE(ssl->decrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER);
+#endif
+#ifdef BUILD_DES3
+    wc_Des3Free(ssl->encrypt.des3);
+    wc_Des3Free(ssl->decrypt.des3);
+    XFREE(ssl->encrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER);
+    XFREE(ssl->decrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER);
+#endif
+#if defined(BUILD_AES) || defined(BUILD_AESGCM) /* See: InitKeys() in keys.c
+                                                 * on addition of BUILD_AESGCM
+                                                 * check (enc->aes, dec->aes) */
+    wc_AesFree(ssl->encrypt.aes);
+    wc_AesFree(ssl->decrypt.aes);
+    #if (defined(BUILD_AESGCM) || defined(HAVE_AESCCM)) && \
+                                                      !defined(WOLFSSL_NO_TLS12)
+        XFREE(ssl->decrypt.additional, ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+        XFREE(ssl->encrypt.additional, ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+    #endif
+    XFREE(ssl->encrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER);
+    XFREE(ssl->decrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER);
+#endif
+#ifdef CIPHER_NONCE
+    XFREE(ssl->decrypt.nonce, ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+    XFREE(ssl->encrypt.nonce, ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+#endif
+#ifdef HAVE_CAMELLIA
+    XFREE(ssl->encrypt.cam, ssl->heap, DYNAMIC_TYPE_CIPHER);
+    XFREE(ssl->decrypt.cam, ssl->heap, DYNAMIC_TYPE_CIPHER);
+#endif
+#ifdef HAVE_HC128
+    XFREE(ssl->encrypt.hc128, ssl->heap, DYNAMIC_TYPE_CIPHER);
+    XFREE(ssl->decrypt.hc128, ssl->heap, DYNAMIC_TYPE_CIPHER);
+#endif
+#ifdef BUILD_RABBIT
+    XFREE(ssl->encrypt.rabbit, ssl->heap, DYNAMIC_TYPE_CIPHER);
+    XFREE(ssl->decrypt.rabbit, ssl->heap, DYNAMIC_TYPE_CIPHER);
+#endif
+#ifdef HAVE_CHACHA
+    XFREE(ssl->encrypt.chacha, ssl->heap, DYNAMIC_TYPE_CIPHER);
+    XFREE(ssl->decrypt.chacha, ssl->heap, DYNAMIC_TYPE_CIPHER);
+#endif
+#if defined(HAVE_POLY1305) && defined(HAVE_ONE_TIME_AUTH)
+    XFREE(ssl->auth.poly1305, ssl->heap, DYNAMIC_TYPE_CIPHER);
+#endif
+#ifdef HAVE_IDEA
+    XFREE(ssl->encrypt.idea, ssl->heap, DYNAMIC_TYPE_CIPHER);
+    XFREE(ssl->decrypt.idea, ssl->heap, DYNAMIC_TYPE_CIPHER);
+#endif
+#if defined(WOLFSSL_TLS13) && defined(HAVE_NULL_CIPHER)
+    wc_HmacFree(ssl->encrypt.hmac);
+    wc_HmacFree(ssl->decrypt.hmac);
+    XFREE(ssl->encrypt.hmac, ssl->heap, DYNAMIC_TYPE_CIPHER);
+    XFREE(ssl->decrypt.hmac, ssl->heap, DYNAMIC_TYPE_CIPHER);
+#endif
+}
+
+
+void InitCipherSpecs(CipherSpecs* cs)
+{
+    XMEMSET(cs, 0, sizeof(CipherSpecs));
+
+    cs->bulk_cipher_algorithm = INVALID_BYTE;
+    cs->cipher_type           = INVALID_BYTE;
+    cs->mac_algorithm         = INVALID_BYTE;
+    cs->kea                   = INVALID_BYTE;
+    cs->sig_algo              = INVALID_BYTE;
+}
+
+#if defined(USE_ECDSA_KEYSZ_HASH_ALGO) || (defined(WOLFSSL_TLS13) && \
+                                                              defined(HAVE_ECC))
+static int GetMacDigestSize(byte macAlgo)
+{
+    switch (macAlgo) {
+    #ifndef NO_SHA
+        case sha_mac:
+            return WC_SHA_DIGEST_SIZE;
+    #endif
+    #ifndef NO_SHA256
+        case sha256_mac:
+            return WC_SHA256_DIGEST_SIZE;
+    #endif
+    #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            return WC_SHA384_DIGEST_SIZE;
+    #endif
+    #ifdef WOLFSSL_SHA512
+        case sha512_mac:
+            return WC_SHA512_DIGEST_SIZE;
+    #endif
+        default:
+            break;
+    }
+    return NOT_COMPILED_IN;
+}
+#endif /* USE_ECDSA_KEYSZ_HASH_ALGO */
+
+static WC_INLINE void AddSuiteHashSigAlgo(Suites* suites, byte macAlgo, byte sigAlgo,
+    int keySz, word16* inOutIdx)
+{
+    int addSigAlgo = 1;
+
+#ifdef USE_ECDSA_KEYSZ_HASH_ALGO
+    if (sigAlgo == ecc_dsa_sa_algo) {
+        int digestSz = GetMacDigestSize(macAlgo);
+        /* do not add sig/algos with digest size larger than key size */
+        if (digestSz <= 0 || (keySz > 0 && digestSz > keySz)) {
+            addSigAlgo = 0;
+        }
+    }
+#else
+    (void)keySz;
+#endif /* USE_ECDSA_KEYSZ_HASH_ALGO */
+
+    if (addSigAlgo) {
+#ifdef WC_RSA_PSS
+        if (sigAlgo == rsa_pss_sa_algo) {
+            /* RSA PSS is sig then mac */
+            suites->hashSigAlgo[*inOutIdx] = sigAlgo;
+            *inOutIdx += 1;
+            suites->hashSigAlgo[*inOutIdx] = macAlgo;
+            *inOutIdx += 1;
+    #ifdef WOLFSSL_TLS13
+            /* Add the certificate algorithm as well */
+            suites->hashSigAlgo[*inOutIdx] = sigAlgo;
+            *inOutIdx += 1;
+            suites->hashSigAlgo[*inOutIdx] = PSS_RSAE_TO_PSS_PSS(macAlgo);
+            *inOutIdx += 1;
+    #endif
+        }
+        else
+#endif
+        {
+            suites->hashSigAlgo[*inOutIdx] = macAlgo;
+            *inOutIdx += 1;
+            suites->hashSigAlgo[*inOutIdx] = sigAlgo;
+            *inOutIdx += 1;
+        }
+    }
+}
+
+void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, int haveRSAsig,
+                           int haveAnon, int tls1_2, int keySz)
+{
+    word16 idx = 0;
+
+    (void)tls1_2;
+    (void)keySz;
+
+#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
+    if (haveECDSAsig) {
+#ifdef HAVE_ECC
+    #ifdef WOLFSSL_SHA512
+        AddSuiteHashSigAlgo(suites, sha512_mac, ecc_dsa_sa_algo, keySz, &idx);
+    #endif
+    #ifdef WOLFSSL_SHA384
+        AddSuiteHashSigAlgo(suites, sha384_mac, ecc_dsa_sa_algo, keySz, &idx);
+    #endif
+    #ifndef NO_SHA256
+        AddSuiteHashSigAlgo(suites, sha256_mac, ecc_dsa_sa_algo, keySz, &idx);
+    #endif
+    #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \
+                                            defined(WOLFSSL_ALLOW_TLS_SHA1))
+        AddSuiteHashSigAlgo(suites, sha_mac, ecc_dsa_sa_algo, keySz, &idx);
+    #endif
+#endif
+    #ifdef HAVE_ED25519
+        AddSuiteHashSigAlgo(suites, ED25519_SA_MAJOR, ED25519_SA_MINOR, keySz,
+                                                                          &idx);
+    #endif
+    #ifdef HAVE_ED448
+        AddSuiteHashSigAlgo(suites, ED448_SA_MAJOR, ED448_SA_MINOR, keySz,
+                                                                          &idx);
+    #endif
+    }
+#endif /* HAVE_ECC || HAVE_ED25519 || defined(HAVE_ED448 */
+
+    if (haveRSAsig) {
+    #ifdef WC_RSA_PSS
+        if (tls1_2) {
+        #ifdef WOLFSSL_SHA512
+            AddSuiteHashSigAlgo(suites, sha512_mac, rsa_pss_sa_algo, keySz,
+                                                                          &idx);
+        #endif
+        #ifdef WOLFSSL_SHA384
+            AddSuiteHashSigAlgo(suites, sha384_mac, rsa_pss_sa_algo, keySz,
+                                                                          &idx);
+        #endif
+        #ifndef NO_SHA256
+            AddSuiteHashSigAlgo(suites, sha256_mac, rsa_pss_sa_algo, keySz,
+                                                                          &idx);
+        #endif
+        }
+    #endif
+    #ifdef WOLFSSL_SHA512
+        AddSuiteHashSigAlgo(suites, sha512_mac, rsa_sa_algo, keySz, &idx);
+    #endif
+    #ifdef WOLFSSL_SHA384
+        AddSuiteHashSigAlgo(suites, sha384_mac, rsa_sa_algo, keySz, &idx);
+    #endif
+    #ifndef NO_SHA256
+        AddSuiteHashSigAlgo(suites, sha256_mac, rsa_sa_algo, keySz, &idx);
+    #endif
+    #ifdef WOLFSSL_SHA224
+        AddSuiteHashSigAlgo(suites, sha224_mac, rsa_sa_algo, keySz, &idx);
+    #endif
+    #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \
+                                            defined(WOLFSSL_ALLOW_TLS_SHA1))
+        AddSuiteHashSigAlgo(suites, sha_mac, rsa_sa_algo, keySz, &idx);
+    #endif
+    }
+
+#ifdef HAVE_ANON
+    if (haveAnon) {
+        AddSuiteHashSigAlgo(suites, sha_mac, anonymous_sa_algo, keySz, &idx);
+    }
+#endif
+
+    (void)haveAnon;
+    (void)haveECDSAsig;
+    suites->hashSigAlgoSz = idx;
+}
+
+void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
+                word16 havePSK, word16 haveDH, word16 haveNTRU,
+                word16 haveECDSAsig, word16 haveECC,
+                word16 haveStaticECC, int side)
+{
+    word16 idx = 0;
+    int    tls    = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_MINOR;
+    int    tls1_2 = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_2_MINOR;
+#ifdef WOLFSSL_TLS13
+    int    tls1_3 = IsAtLeastTLSv1_3(pv);
+#endif
+    int    dtls   = 0;
+    int    haveRSAsig = 1;
+
+    (void)tls;  /* shut up compiler */
+    (void)tls1_2;
+    (void)dtls;
+    (void)haveDH;
+    (void)havePSK;
+    (void)haveNTRU;
+    (void)haveStaticECC;
+    (void)haveECC;
+    (void)side;
+    (void)haveRSA;    /* some builds won't read */
+    (void)haveRSAsig; /* non ecc builds won't read */
+
+    if (suites == NULL) {
+        WOLFSSL_MSG("InitSuites pointer error");
+        return;
+    }
+
+    if (suites->setSuites)
+        return;      /* trust user settings, don't override */
+
+#ifdef WOLFSSL_TLS13
+#ifdef BUILD_TLS_AES_128_GCM_SHA256
+    if (tls1_3) {
+        suites->suites[idx++] = TLS13_BYTE;
+        suites->suites[idx++] = TLS_AES_128_GCM_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_AES_256_GCM_SHA384
+    if (tls1_3) {
+        suites->suites[idx++] = TLS13_BYTE;
+        suites->suites[idx++] = TLS_AES_256_GCM_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256
+    if (tls1_3) {
+        suites->suites[idx++] = TLS13_BYTE;
+        suites->suites[idx++] = TLS_CHACHA20_POLY1305_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_AES_128_CCM_SHA256
+    if (tls1_3) {
+        suites->suites[idx++] = TLS13_BYTE;
+        suites->suites[idx++] = TLS_AES_128_CCM_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_AES_128_CCM_8_SHA256
+    if (tls1_3) {
+        suites->suites[idx++] = TLS13_BYTE;
+        suites->suites[idx++] = TLS_AES_128_CCM_8_SHA256;
+    }
+#endif
+
+#ifdef HAVE_NULL_CIPHER
+    #ifdef BUILD_TLS_SHA256_SHA256
+        if (tls1_3) {
+            suites->suites[idx++] = ECC_BYTE;
+            suites->suites[idx++] = TLS_SHA256_SHA256;
+        }
+    #endif
+
+    #ifdef BUILD_TLS_SHA384_SHA384
+        if (tls1_3) {
+            suites->suites[idx++] = ECC_BYTE;
+            suites->suites[idx++] = TLS_SHA384_SHA384;
+        }
+    #endif
+#endif
+#endif /* WOLFSSL_TLS13 */
+
+#ifndef WOLFSSL_NO_TLS12
+
+#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_RSA)
+    if (side == WOLFSSL_SERVER_END && haveStaticECC) {
+        haveRSA = 0;   /* can't do RSA with ECDSA key */
+    }
+
+    if (side == WOLFSSL_SERVER_END && haveECDSAsig) {
+        haveRSAsig = 0;     /* can't have RSA sig if signed by ECDSA */
+    }
+#endif /* !NO_WOLFSSL_SERVER */
+
+#ifdef WOLFSSL_DTLS
+    if (pv.major == DTLS_MAJOR) {
+        dtls   = 1;
+        tls    = 1;
+        /* May be dead assignments dependent upon configuration */
+        (void) dtls;
+        (void) tls;
+        tls1_2 = pv.minor <= DTLSv1_2_MINOR;
+    }
+#endif
+
+#ifdef HAVE_RENEGOTIATION_INDICATION
+    if (side == WOLFSSL_CLIENT_END) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_EMPTY_RENEGOTIATION_INFO_SCSV;
+    }
+#endif
+
+#ifdef BUILD_TLS_QSH
+    if (tls) {
+        suites->suites[idx++] = QSH_BYTE;
+        suites->suites[idx++] = TLS_QSH;
+    }
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
+   if (tls && haveNTRU && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_NTRU_RSA_WITH_AES_256_CBC_SHA;
+   }
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
+    if (tls && haveNTRU && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_NTRU_RSA_WITH_AES_128_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
+    if (!dtls && tls && haveNTRU && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_NTRU_RSA_WITH_RC4_128_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
+    if (tls && haveNTRU && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+    if (tls1_2 && haveECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+    if (tls1_2 && haveECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+    if (tls1_2 && haveRSA) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+    if (tls1_2 && haveRSA) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+    if (tls1_2 && haveDH && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_GCM_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
+    if (tls1_2 && haveDH && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_GCM_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384
+    if (tls1_2 && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_AES_256_GCM_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
+    if (tls1_2 && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_AES_128_GCM_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
+    if (tls1_2 && haveECC && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+    if (tls1_2 && haveECC && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
+    if (tls1_2 && haveRSAsig && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+    if (tls1_2 && haveRSAsig && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
+    if (tls1_2 && haveDH && havePSK) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_256_GCM_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA
+    if (tls1_2 && haveDH) {
+      suites->suites[idx++] = CIPHER_BYTE;
+      suites->suites[idx++] = TLS_DH_anon_WITH_AES_128_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_DH_anon_WITH_AES_256_GCM_SHA384
+    if (tls1_2 && haveDH) {
+      suites->suites[idx++] = CIPHER_BYTE;
+      suites->suites[idx++] = TLS_DH_anon_WITH_AES_256_GCM_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
+    if (tls1_2 && haveDH && havePSK) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_128_GCM_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384
+    if (tls1_2 && havePSK) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_AES_256_GCM_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256
+    if (tls1_2 && havePSK) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_AES_128_GCM_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
+    if (tls1_2 && haveECC) {
+        suites->suites[idx++] = CHACHA_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+    if (tls1_2 && haveRSA) {
+        suites->suites[idx++] = CHACHA_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+    if (tls1_2 && haveRSA) {
+        suites->suites[idx++] = CHACHA_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
+    }
+#endif
+
+/* Place as higher priority for MYSQL */
+#if defined(WOLFSSL_MYSQL_COMPATIBLE)
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+    if (tls && haveDH && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
+    }
+#endif
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+    if (tls1_2 && haveRSA) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
+    if (tls1_2 && haveECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
+    if (tls1_2 && haveRSAsig && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
+    if (tls1_2 && haveECC && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
+    if (tls1_2 && haveRSA) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
+    if (tls1_2 && haveECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
+    if (tls1_2 && haveRSAsig && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
+    if (tls1_2 && haveECC && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+    if (tls && haveECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+    if (tls && haveECC && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+    if (tls && haveECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+    if (tls && haveECC && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+    if (!dtls && tls && haveECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_RC4_128_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
+    if (!dtls && tls && haveECC && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_RC4_128_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+    if (tls && haveECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+    if (tls && haveECC && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+    if (tls && haveRSA) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+    if (tls && haveRSAsig && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_256_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+    if (tls && haveRSA) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
+    if (tls && haveRSAsig && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
+    if (!dtls && tls && haveRSA) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_RC4_128_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA
+    if (!dtls && tls && haveRSAsig && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_RSA_WITH_RC4_128_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+    if (tls && haveRSA) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+    if (tls && haveRSAsig && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM
+    if (tls1_2 && haveECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CCM;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
+    if (tls1_2 && haveECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8
+    if (tls1_2 && haveECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8
+    if (tls1_2 && haveRSA) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_AES_128_CCM_8;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8
+    if (tls1_2 && haveRSA) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_AES_256_CCM_8;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+    if (tls1_2 && haveDH && haveRSA)
+#else
+    if (tls && haveDH && haveRSA)
+#endif
+    {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+    if (tls1_2 && haveDH && haveRSA)
+#else
+    if (tls && haveDH && haveRSA)
+#endif
+    {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
+    }
+#endif
+
+/* Place as higher priority for MYSQL testing */
+#if !defined(WOLFSSL_MYSQL_COMPATIBLE)
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+    if (tls && haveDH && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
+    }
+#endif
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+    if (tls && haveDH && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+    if (tls && haveDH && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+    if (tls1_2 && haveRSA)
+#else
+    if (tls && haveRSA)
+#endif
+    {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+    if (tls1_2 && haveRSA)
+#else
+    if (tls && haveRSA)
+#endif
+    {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
+    if (tls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
+    if (tls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+    if (tls1_2 && haveECC) {
+        suites->suites[idx++] = CHACHA_BYTE;
+        suites->suites[idx++] =
+                              TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+    if (tls1_2 && haveRSA) {
+        suites->suites[idx++] = CHACHA_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+    if (tls1_2 && haveRSA) {
+        suites->suites[idx++] = CHACHA_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA
+    if (tls && haveECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_NULL_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_NULL_MD5
+    if (tls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_NULL_MD5;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_NULL_SHA
+    if (tls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_NULL_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_NULL_SHA256
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+    if (tls1_2 && haveRSA)
+#else
+    if (tls && haveRSA)
+#endif
+    {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_NULL_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
+    if (tls && havePSK) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_AES_256_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+    if (tls1_2 && haveDH && havePSK)
+#else
+    if (tls && haveDH && havePSK)
+#endif
+    {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_256_CBC_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+    if (tls1_2 && havePSK)
+#else
+    if (tls && havePSK)
+#endif
+    {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_AES_256_CBC_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+    if (tls1_2 && haveDH && havePSK)
+#else
+    if (tls && haveDH && havePSK)
+#endif
+    {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_128_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+    if (tls1_2 && havePSK)
+#else
+    if (tls1 && havePSK)
+#endif
+    {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_AES_128_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
+    if (tls && havePSK) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_AES_128_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CCM
+    if (tls && haveDH && havePSK) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_128_CCM;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CCM
+    if (tls && haveDH && havePSK) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_256_CCM;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+    if (tls1_2 && havePSK)
+#else
+    if (tls && havePSK)
+#endif
+    {
+        suites->suites[idx++] = CHACHA_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_CHACHA20_POLY1305_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+    if (tls1_2 && havePSK)
+#else
+    if (tls && havePSK)
+#endif
+    {
+        suites->suites[idx++] = CHACHA_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+    if (tls1_2 && havePSK)
+#else
+    if (tls && havePSK)
+#endif
+    {
+        suites->suites[idx++] = CHACHA_BYTE;
+        suites->suites[idx++] = TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+    if (tls1_2 && havePSK)
+#else
+    if (tls && havePSK)
+#endif
+    {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM
+    if (tls && havePSK) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_AES_128_CCM;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM
+    if (tls && havePSK) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_AES_256_CCM;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM_8
+    if (tls && havePSK) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_AES_128_CCM_8;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM_8
+    if (tls && havePSK) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_AES_256_CCM_8;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+    if (tls1_2 && haveDH && havePSK)
+#else
+    if (tls && haveDH && havePSK)
+#endif
+    {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_PSK_WITH_NULL_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_NULL_SHA384
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+    if (tls1_2 && havePSK)
+#else
+    if (tls && havePSK)
+#endif
+    {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+    if (tls1_2 && havePSK)
+#else
+    if (tls && havePSK)
+#endif
+    {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_PSK_WITH_NULL_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+    if (tls1_2 && haveDH && havePSK)
+#else
+    if (tls && haveDH && havePSK)
+#endif
+    {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_PSK_WITH_NULL_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_NULL_SHA256
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+    if (tls1_2 && havePSK)
+#else
+    if (tls && havePSK)
+#endif
+    {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_NULL_SHA
+    if (tls && havePSK) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA;
+    }
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
+    if (!dtls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = SSL_RSA_WITH_RC4_128_SHA;
+    }
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
+    if (!dtls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = SSL_RSA_WITH_RC4_128_MD5;
+    }
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
+    if (haveRSA ) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = SSL_RSA_WITH_3DES_EDE_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_MD5
+    if (!dtls && tls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_HC_128_MD5;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_SHA
+    if (!dtls && tls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_HC_128_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA
+    if (!dtls && tls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_RABBIT_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
+    if (tls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_128_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
+    if (tls && haveDH && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
+    if (tls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_256_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
+    if (tls && haveDH && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+    if (tls1_2 && haveRSA)
+#else
+    if (tls && haveRSA)
+#endif
+    {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+    if (tls1_2 && haveDH && haveRSA)
+#else
+    if (tls && haveDH && haveRSA)
+#endif
+    {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+    if (tls1_2 && haveRSA)
+#else
+    if (tls && haveRSA)
+#endif
+    {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
+#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
+    if (tls1_2 && haveDH && haveRSA)
+#else
+    if (tls && haveDH && haveRSA)
+#endif
+    {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_IDEA_CBC_SHA
+    if (haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = SSL_RSA_WITH_IDEA_CBC_SHA;
+    }
+#endif
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+    suites->suiteSz = idx;
+
+    InitSuitesHashSigAlgo(suites, haveECDSAsig | haveECC, haveRSAsig | haveRSA,
+                                                              0, tls1_2, keySz);
+}
+
+#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) || \
+    (!defined(NO_WOLFSSL_CLIENT) && (!defined(NO_DH) || defined(HAVE_ECC)))
+
+/* Decode the signature algorithm.
+ *
+ * input     The encoded signature algorithm.
+ * hashalgo  The hash algorithm.
+ * hsType    The signature type.
+ */
+static WC_INLINE void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsType)
+{
+    switch (input[0]) {
+        case NEW_SA_MAJOR:
+    #ifdef HAVE_ED25519
+            /* ED25519: 0x0807 */
+            if (input[1] == ED25519_SA_MINOR) {
+                *hsType = ed25519_sa_algo;
+                /* Hash performed as part of sign/verify operation. */
+                *hashAlgo = sha512_mac;
+            }
+            else
+    #endif
+    #ifdef HAVE_ED448
+            /* ED448: 0x0808 */
+            if (input[1] == ED448_SA_MINOR) {
+                *hsType = ed448_sa_algo;
+                /* Hash performed as part of sign/verify operation. */
+                *hashAlgo = sha512_mac;
+            }
+            else
+    #endif
+    #ifdef WC_RSA_PSS
+            /* PSS PSS signatures: 0x080[9-b] */
+            if (input[1] >= pss_sha256 && input[1] <= pss_sha512) {
+                *hsType   = rsa_pss_pss_algo;
+                *hashAlgo = PSS_PSS_HASH_TO_MAC(input[1]);
+            }
+            else
+    #endif
+            {
+                *hsType   = input[0];
+                *hashAlgo = input[1];
+            }
+            break;
+        default:
+            *hashAlgo = input[0];
+            *hsType   = input[1];
+            break;
+    }
+}
+#endif /* !NO_WOLFSSL_SERVER || !NO_CERTS */
+
+#ifndef WOLFSSL_NO_TLS12
+#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
+#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+             defined(HAVE_CURVE448) || (!defined(NO_RSA) && defined(WC_RSA_PSS))
+
+static enum wc_HashType HashAlgoToType(int hashAlgo)
+{
+    switch (hashAlgo) {
+    #ifdef WOLFSSL_SHA512
+        case sha512_mac:
+            return WC_HASH_TYPE_SHA512;
+    #endif
+    #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            return WC_HASH_TYPE_SHA384;
+    #endif
+    #ifndef NO_SHA256
+        case sha256_mac:
+            return WC_HASH_TYPE_SHA256;
+    #endif
+    #ifdef WOLFSSL_SHA224
+        case sha224_mac:
+            return WC_HASH_TYPE_SHA224;
+    #endif
+    #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \
+                             defined(WOLFSSL_ALLOW_TLS_SHA1))
+        case sha_mac:
+            return WC_HASH_TYPE_SHA;
+    #endif
+        default:
+            WOLFSSL_MSG("Bad hash sig algo");
+            break;
+    }
+
+    return WC_HASH_TYPE_NONE;
+}
+#endif /* !NO_DH || HAVE_ECC || (!NO_RSA && WC_RSA_PSS) */
+#endif /* !NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT */
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#ifndef NO_CERTS
+
+void InitX509Name(WOLFSSL_X509_NAME* name, int dynamicFlag)
+{
+    (void)dynamicFlag;
+
+    if (name != NULL) {
+        name->name        = name->staticName;
+        name->dynamicName = 0;
+        name->sz = 0;
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+        XMEMSET(&name->fullName, 0, sizeof(DecodedName));
+        XMEMSET(&name->cnEntry,  0, sizeof(WOLFSSL_X509_NAME_ENTRY));
+        XMEMSET(&name->extra,    0, sizeof(name->extra));
+        name->cnEntry.value = &(name->cnEntry.data); /* point to internal data*/
+        name->cnEntry.nid = ASN_COMMON_NAME;
+        name->x509 = NULL;
+#endif /* OPENSSL_EXTRA */
+    }
+}
+
+
+void FreeX509Name(WOLFSSL_X509_NAME* name, void* heap)
+{
+    if (name != NULL) {
+        if (name->dynamicName) {
+            XFREE(name->name, heap, DYNAMIC_TYPE_SUBJECT_CN);
+            name->name = NULL;
+        }
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+        {
+            int i;
+            if (name->fullName.fullName != NULL) {
+                XFREE(name->fullName.fullName, heap, DYNAMIC_TYPE_X509);
+                name->fullName.fullName = NULL;
+            }
+            for (i = 0; i < MAX_NAME_ENTRIES; i++) {
+                /* free ASN1 string data */
+                if (name->extra[i].set && name->extra[i].data.data != NULL) {
+                    XFREE(name->extra[i].data.data, heap, DYNAMIC_TYPE_OPENSSL);
+                }
+            }
+            wolfSSL_ASN1_OBJECT_free(&name->cnEntry.object);
+        }
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+    }
+    (void)heap;
+}
+
+
+/* Initialize wolfSSL X509 type */
+void InitX509(WOLFSSL_X509* x509, int dynamicFlag, void* heap)
+{
+    if (x509 == NULL) {
+        WOLFSSL_MSG("Null parameter passed in!");
+        return;
+    }
+
+    XMEMSET(x509, 0, sizeof(WOLFSSL_X509));
+
+    x509->heap = heap;
+    InitX509Name(&x509->issuer, 0);
+    InitX509Name(&x509->subject, 0);
+    x509->dynamicMemory  = (byte)dynamicFlag;
+    #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
+        x509->refCount = 1;
+        (void)wc_InitMutex(&x509->refMutex);
+    #endif
+}
+
+
+/* Free wolfSSL X509 type */
+void FreeX509(WOLFSSL_X509* x509)
+{
+    if (x509 == NULL)
+        return;
+
+    FreeX509Name(&x509->issuer, x509->heap);
+    FreeX509Name(&x509->subject, x509->heap);
+    if (x509->pubKey.buffer) {
+        XFREE(x509->pubKey.buffer, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        x509->pubKey.buffer = NULL;
+    }
+    FreeDer(&x509->derCert);
+    XFREE(x509->sig.buffer, x509->heap, DYNAMIC_TYPE_SIGNATURE);
+    x509->sig.buffer = NULL;
+    #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+        XFREE(x509->authKeyId, x509->heap, DYNAMIC_TYPE_X509_EXT);
+        x509->authKeyId = NULL;
+        XFREE(x509->subjKeyId, x509->heap, DYNAMIC_TYPE_X509_EXT);
+        x509->subjKeyId = NULL;
+        if (x509->authInfo != NULL) {
+            XFREE(x509->authInfo, x509->heap, DYNAMIC_TYPE_X509_EXT);
+            x509->authInfo = NULL;
+        }
+        #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+        if (x509->authInfoCaIssuer != NULL) {
+            XFREE(x509->authInfoCaIssuer, x509->heap, DYNAMIC_TYPE_X509_EXT);
+        }
+        if (x509->ext_sk != NULL) {
+            wolfSSL_sk_X509_EXTENSION_free(x509->ext_sk);
+        }
+        #endif /* OPENSSL_ALL || WOLFSSL_QT */
+        #ifdef OPENSSL_EXTRA
+        /* Free serialNumber that was set by wolfSSL_X509_get_serialNumber */
+        if (x509->serialNumber != NULL) {
+            wolfSSL_ASN1_INTEGER_free(x509->serialNumber);
+        }
+        #endif
+        if (x509->extKeyUsageSrc != NULL) {
+            XFREE(x509->extKeyUsageSrc, x509->heap, DYNAMIC_TYPE_X509_EXT);
+            x509->extKeyUsageSrc= NULL;
+        }
+    #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+    #if defined(OPENSSL_ALL)
+        if (x509->algor.algorithm) {
+            wolfSSL_ASN1_OBJECT_free(x509->algor.algorithm);
+            x509->algor.algorithm = NULL;
+        }
+        if (x509->key.algor) {
+            wolfSSL_X509_ALGOR_free(x509->key.algor);
+            x509->key.algor = NULL;
+        }
+        if (x509->key.pkey) {
+            wolfSSL_EVP_PKEY_free(x509->key.pkey);
+            x509->key.pkey = NULL;
+        }
+    #endif /* OPENSSL_ALL */
+    if (x509->altNames) {
+        FreeAltNames(x509->altNames, x509->heap);
+        x509->altNames = NULL;
+    }
+
+    #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
+        wc_FreeMutex(&x509->refMutex);
+    #endif
+}
+
+
+#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
+#if !defined(WOLFSSL_NO_TLS12)
+/* Encode the signature algorithm into buffer.
+ *
+ * hashalgo  The hash algorithm.
+ * hsType   The signature type.
+ * output    The buffer to encode into.
+ */
+static WC_INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output)
+{
+    switch (hsType) {
+#ifdef HAVE_ECC
+        case ecc_dsa_sa_algo:
+            output[0] = hashAlgo;
+            output[1] = ecc_dsa_sa_algo;
+            break;
+#endif
+#ifdef HAVE_ED25519
+        case ed25519_sa_algo:
+            output[0] = ED25519_SA_MAJOR;
+            output[1] = ED25519_SA_MINOR;
+            (void)hashAlgo;
+            break;
+#endif
+#ifdef HAVE_ED448
+        case ed448_sa_algo:
+            output[0] = ED448_SA_MAJOR;
+            output[1] = ED448_SA_MINOR;
+            (void)hashAlgo;
+            break;
+#endif
+#ifndef NO_RSA
+        case rsa_sa_algo:
+            output[0] = hashAlgo;
+            output[1] = rsa_sa_algo;
+            break;
+    #ifdef WC_RSA_PSS
+        /* PSS signatures: 0x080[4-6] */
+        case rsa_pss_sa_algo:
+            output[0] = rsa_pss_sa_algo;
+            output[1] = hashAlgo;
+            break;
+    #endif
+#endif
+    }
+    (void)hashAlgo;
+    (void)output;
+}
+#endif
+
+#if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_NO_CLIENT_AUTH)
+static void SetDigest(WOLFSSL* ssl, int hashAlgo)
+{
+    switch (hashAlgo) {
+    #ifndef NO_SHA
+        case sha_mac:
+            ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha;
+            ssl->buffers.digest.length = WC_SHA_DIGEST_SIZE;
+            break;
+    #endif /* !NO_SHA */
+    #ifndef NO_SHA256
+        case sha256_mac:
+            ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256;
+            ssl->buffers.digest.length = WC_SHA256_DIGEST_SIZE;
+            break;
+    #endif /* !NO_SHA256 */
+    #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha384;
+            ssl->buffers.digest.length = WC_SHA384_DIGEST_SIZE;
+            break;
+    #endif /* WOLFSSL_SHA384 */
+    #ifdef WOLFSSL_SHA512
+        case sha512_mac:
+            ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512;
+            ssl->buffers.digest.length = WC_SHA512_DIGEST_SIZE;
+            break;
+    #endif /* WOLFSSL_SHA512 */
+    } /* switch */
+}
+#endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_NO_CLIENT_AUTH */
+#endif /* !NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT */
+#endif /* !NO_CERTS */
+
+#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+static word32 MacSize(WOLFSSL* ssl)
+{
+#ifdef HAVE_TRUNCATED_HMAC
+    word32 digestSz = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ
+                                          : ssl->specs.hash_size;
+#else
+    word32 digestSz = ssl->specs.hash_size;
+#endif
+
+    return digestSz;
+}
+#endif /* HAVE_ENCRYPT_THEN_MAC && !WOLFSSL_AEAD_ONLY */
+
+#ifndef NO_RSA
+#ifndef WOLFSSL_NO_TLS12
+#if !defined(NO_WOLFSSL_SERVER) || (!defined(NO_WOLFSSL_CLIENT) && \
+                                               !defined(WOLFSSL_NO_CLIENT_AUTH))
+static int TypeHash(int hashAlgo)
+{
+    switch (hashAlgo) {
+    #ifdef WOLFSSL_SHA512
+        case sha512_mac:
+            return SHA512h;
+    #endif
+    #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            return SHA384h;
+    #endif
+    #ifndef NO_SHA256
+        case sha256_mac:
+            return SHA256h;
+    #endif
+    #ifdef WOLFSSL_SHA224
+        case sha224_mac:
+            return SHA224h;
+    #endif
+    #ifndef NO_SHA
+        case sha_mac:
+            return SHAh;
+    #endif
+    }
+
+    return 0;
+}
+#endif /* !NO_WOLFSSL_SERVER && !NO_WOLFSSL_CLIENT */
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#if defined(WC_RSA_PSS)
+int ConvertHashPss(int hashAlgo, enum wc_HashType* hashType, int* mgf)
+{
+    switch (hashAlgo) {
+        #ifdef WOLFSSL_SHA512
+        case sha512_mac:
+            *hashType = WC_HASH_TYPE_SHA512;
+            if (mgf != NULL)
+                *mgf = WC_MGF1SHA512;
+            break;
+        #endif
+        #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            *hashType = WC_HASH_TYPE_SHA384;
+            if (mgf != NULL)
+                *mgf = WC_MGF1SHA384;
+            break;
+        #endif
+        #ifndef NO_SHA256
+        case sha256_mac:
+            *hashType = WC_HASH_TYPE_SHA256;
+            if (mgf != NULL)
+                *mgf = WC_MGF1SHA256;
+            break;
+        #endif
+        default:
+            return BAD_FUNC_ARG;
+    }
+
+    return 0;
+}
+#endif
+
+#if !defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH)
+int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
+            word32* outSz, int sigAlgo, int hashAlgo, RsaKey* key,
+            DerBuffer* keyBufInfo)
+{
+    int ret;
+#ifdef HAVE_PK_CALLBACKS
+    const byte* keyBuf = NULL;
+    word32 keySz = 0;
+
+    if (keyBufInfo) {
+        keyBuf = keyBufInfo->buffer;
+        keySz = keyBufInfo->length;
+    }
+#endif
+
+    (void)ssl;
+    (void)keyBufInfo;
+    (void)sigAlgo;
+    (void)hashAlgo;
+
+    WOLFSSL_ENTER("RsaSign");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    if (key) {
+        ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+        if (ret != 0)
+            return ret;
+    }
+#endif
+
+#if defined(WC_RSA_PSS)
+    if (sigAlgo == rsa_pss_sa_algo) {
+        enum wc_HashType hashType = WC_HASH_TYPE_NONE;
+        int mgf = 0;
+
+        ret = ConvertHashPss(hashAlgo, &hashType, &mgf);
+        if (ret != 0)
+            return ret;
+
+    #if defined(HAVE_PK_CALLBACKS)
+        if (ssl->ctx->RsaPssSignCb) {
+            void* ctx = wolfSSL_GetRsaPssSignCtx(ssl);
+            ret = ssl->ctx->RsaPssSignCb(ssl, in, inSz, out, outSz,
+                                         TypeHash(hashAlgo), mgf,
+                                         keyBuf, keySz, ctx);
+        }
+        else
+    #endif
+        {
+            ret = wc_RsaPSS_Sign(in, inSz, out, *outSz, hashType, mgf, key,
+                                                                      ssl->rng);
+        }
+    }
+    else
+#endif
+#if defined(HAVE_PK_CALLBACKS)
+    if (ssl->ctx->RsaSignCb) {
+        void* ctx = wolfSSL_GetRsaSignCtx(ssl);
+        ret = ssl->ctx->RsaSignCb(ssl, in, inSz, out, outSz, keyBuf, keySz,
+                                                                          ctx);
+    }
+    else
+#endif /*HAVE_PK_CALLBACKS */
+        ret = wc_RsaSSL_Sign(in, inSz, out, *outSz, key, ssl->rng);
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (key && ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    /* For positive response return in outSz */
+    if (ret > 0) {
+        *outSz = ret;
+        ret = 0;
+    }
+
+    WOLFSSL_LEAVE("RsaSign", ret);
+
+    return ret;
+}
+#endif
+
+int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, int sigAlgo,
+              int hashAlgo, RsaKey* key, buffer* keyBufInfo)
+{
+    int ret;
+#ifdef HAVE_PK_CALLBACKS
+    const byte* keyBuf = NULL;
+    word32 keySz = 0;
+
+    if (keyBufInfo) {
+        keyBuf = keyBufInfo->buffer;
+        keySz = keyBufInfo->length;
+    }
+#endif
+
+    (void)ssl;
+    (void)keyBufInfo;
+    (void)sigAlgo;
+    (void)hashAlgo;
+
+    WOLFSSL_ENTER("RsaVerify");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+    if (ret != 0)
+        return ret;
+#endif
+
+#if defined(WC_RSA_PSS)
+    if (sigAlgo == rsa_pss_sa_algo) {
+        enum wc_HashType hashType = WC_HASH_TYPE_NONE;
+        int mgf = 0;
+
+        ret = ConvertHashPss(hashAlgo, &hashType, &mgf);
+        if (ret != 0)
+            return ret;
+#ifdef HAVE_PK_CALLBACKS
+        if (ssl->ctx->RsaPssVerifyCb) {
+            void* ctx = wolfSSL_GetRsaPssVerifyCtx(ssl);
+            ret = ssl->ctx->RsaPssVerifyCb(ssl, in, inSz, out,
+                                           TypeHash(hashAlgo), mgf,
+                                           keyBuf, keySz, ctx);
+        }
+        else
+#endif /*HAVE_PK_CALLBACKS */
+            ret = wc_RsaPSS_VerifyInline(in, inSz, out, hashType, mgf, key);
+    }
+    else
+#endif
+#ifdef HAVE_PK_CALLBACKS
+    if (ssl->ctx->RsaVerifyCb) {
+        void* ctx = wolfSSL_GetRsaVerifyCtx(ssl);
+        ret = ssl->ctx->RsaVerifyCb(ssl, in, inSz, out, keyBuf, keySz, ctx);
+    }
+    else
+#endif /*HAVE_PK_CALLBACKS */
+    {
+        ret = wc_RsaSSL_VerifyInline(in, inSz, out, key);
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    WOLFSSL_LEAVE("RsaVerify", ret);
+
+    return ret;
+}
+
+/* Verify RSA signature, 0 on success */
+/* This function is used to check the sign result */
+int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig, word32 sigSz,
+    const byte* plain, word32 plainSz, int sigAlgo, int hashAlgo, RsaKey* key,
+    DerBuffer* keyBufInfo)
+{
+    byte* out = NULL;  /* inline result */
+    int   ret;
+#ifdef HAVE_PK_CALLBACKS
+    const byte* keyBuf = NULL;
+    word32 keySz = 0;
+
+    if (keyBufInfo) {
+        keyBuf = keyBufInfo->buffer;
+        keySz = keyBufInfo->length;
+    }
+#endif
+
+    (void)ssl;
+    (void)keyBufInfo;
+    (void)sigAlgo;
+    (void)hashAlgo;
+
+    WOLFSSL_ENTER("VerifyRsaSign");
+
+    if (verifySig == NULL || plain == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (sigSz > ENCRYPT_LEN) {
+        WOLFSSL_MSG("Signature buffer too big");
+        return BUFFER_E;
+    }
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    if (key) {
+        ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+        if (ret != 0)
+            return ret;
+    }
+#endif
+
+#if defined(WC_RSA_PSS)
+    if (sigAlgo == rsa_pss_sa_algo) {
+        enum wc_HashType hashType = WC_HASH_TYPE_NONE;
+        int mgf = 0;
+
+        ret = ConvertHashPss(hashAlgo, &hashType, &mgf);
+        if (ret != 0)
+            return ret;
+    #ifdef HAVE_PK_CALLBACKS
+        if (ssl->ctx->RsaPssSignCheckCb) {
+            /* The key buffer includes private/public portion,
+                but only public is used */
+            /* If HSM hardware is checking the signature result you can
+                optionally skip the sign check and return 0 */
+            /* The ctx here is the RsaSignCtx set using wolfSSL_SetRsaSignCtx */
+            void* ctx = wolfSSL_GetRsaPssSignCtx(ssl);
+            ret = ssl->ctx->RsaPssSignCheckCb(ssl, verifySig, sigSz, &out,
+                                           TypeHash(hashAlgo), mgf,
+                                           keyBuf, keySz, ctx);
+            if (ret > 0) {
+                ret = wc_RsaPSS_CheckPadding(plain, plainSz, out, ret,
+                                             hashType);
+                if (ret != 0)
+                    ret = VERIFY_CERT_ERROR;
+            }
+        }
+        else
+    #endif /* HAVE_PK_CALLBACKS */
+        {
+            ret = wc_RsaPSS_VerifyInline(verifySig, sigSz, &out, hashType, mgf,
+                                         key);
+            if (ret > 0) {
+    #ifdef HAVE_SELFTEST
+                ret = wc_RsaPSS_CheckPadding(plain, plainSz, out, ret,
+                                             hashType);
+    #else
+                ret = wc_RsaPSS_CheckPadding_ex(plain, plainSz, out, ret,
+                                                hashType, -1,
+                                                mp_count_bits(&key->n));
+    #endif
+                if (ret != 0)
+                    ret = VERIFY_CERT_ERROR;
+            }
+        }
+
+    }
+    else
+#endif /* WC_RSA_PSS */
+    {
+    #ifdef HAVE_PK_CALLBACKS
+        if (ssl->ctx->RsaSignCheckCb) {
+            /* The key buffer includes private/public portion,
+                but only public is used */
+            /* If HSM hardware is checking the signature result you can
+                optionally skip the sign check and return 0 */
+            /* The ctx here is the RsaSignCtx set using wolfSSL_SetRsaSignCtx */
+            void* ctx = wolfSSL_GetRsaSignCtx(ssl);
+            ret = ssl->ctx->RsaSignCheckCb(ssl, verifySig, sigSz, &out,
+                keyBuf, keySz, ctx);
+        }
+        else
+    #endif /* HAVE_PK_CALLBACKS */
+        {
+            ret = wc_RsaSSL_VerifyInline(verifySig, sigSz, &out, key);
+        }
+
+        if (ret > 0) {
+            if (ret != (int)plainSz || !out ||
+                                            XMEMCMP(plain, out, plainSz) != 0) {
+                WOLFSSL_MSG("RSA Signature verification failed");
+                ret = RSA_SIGN_FAULT;
+            } else {
+                ret = 0;  /* RSA reset */
+            }
+        }
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (key && ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    WOLFSSL_LEAVE("VerifyRsaSign", ret);
+
+    return ret;
+}
+
+#ifndef WOLFSSL_NO_TLS12
+
+#if !defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH)
+int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, word32* outSz,
+    RsaKey* key, DerBuffer* keyBufInfo)
+{
+    int ret;
+#ifdef HAVE_PK_CALLBACKS
+    const byte* keyBuf = NULL;
+    word32 keySz = 0;
+
+    if (keyBufInfo) {
+        keyBuf = keyBufInfo->buffer;
+        keySz = keyBufInfo->length;
+    }
+#endif
+
+    (void)ssl;
+    (void)keyBufInfo;
+
+    WOLFSSL_ENTER("RsaDec");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+    if (ret != 0)
+        return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+    if (ssl->ctx->RsaDecCb) {
+        void* ctx = wolfSSL_GetRsaDecCtx(ssl);
+        ret = ssl->ctx->RsaDecCb(ssl, in, inSz, out, keyBuf, keySz, ctx);
+    }
+    else
+#endif /* HAVE_PK_CALLBACKS */
+    {
+        #ifdef WC_RSA_BLINDING
+            ret = wc_RsaSetRNG(key, ssl->rng);
+            if (ret != 0)
+                return ret;
+        #endif
+        ret = wc_RsaPrivateDecryptInline(in, inSz, out, key);
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    /* For positive response return in outSz */
+    if (ret > 0) {
+        *outSz = ret;
+        ret = 0;
+    }
+
+    WOLFSSL_LEAVE("RsaDec", ret);
+
+    return ret;
+}
+#endif /* !NO_WOLFSSL_SERVER) || !WOLFSSL_NO_CLIENT_AUTH */
+
+int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, word32* outSz,
+    RsaKey* key, buffer* keyBufInfo)
+{
+    int ret;
+#ifdef HAVE_PK_CALLBACKS
+    const byte* keyBuf = NULL;
+    word32 keySz = 0;
+
+    if (keyBufInfo) {
+        keyBuf = keyBufInfo->buffer;
+        keySz = keyBufInfo->length;
+    }
+#endif
+
+    (void)ssl;
+    (void)keyBufInfo;
+
+    WOLFSSL_ENTER("RsaEnc");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+    if (ret != 0)
+        return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+    if (ssl->ctx->RsaEncCb) {
+        void* ctx = wolfSSL_GetRsaEncCtx(ssl);
+        ret = ssl->ctx->RsaEncCb(ssl, in, inSz, out, outSz, keyBuf, keySz, ctx);
+    }
+    else
+#endif /* HAVE_PK_CALLBACKS */
+    {
+        ret = wc_RsaPublicEncrypt(in, inSz, out, *outSz, key, ssl->rng);
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    /* For positive response return in outSz */
+    if (ret > 0) {
+        *outSz = ret;
+        ret = 0;
+    }
+
+    WOLFSSL_LEAVE("RsaEnc", ret);
+
+    return ret;
+}
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#endif /* NO_RSA */
+
+#ifdef HAVE_ECC
+
+int EccSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
+    word32* outSz, ecc_key* key, DerBuffer* keyBufInfo)
+{
+    int ret;
+#ifdef HAVE_PK_CALLBACKS
+    const byte* keyBuf = NULL;
+    word32 keySz = 0;
+
+    if (keyBufInfo) {
+        keyBuf = keyBufInfo->buffer;
+        keySz = keyBufInfo->length;
+    }
+#endif
+
+    (void)ssl;
+    (void)keyBufInfo;
+
+    WOLFSSL_ENTER("EccSign");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    if (key) {
+        ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+        if (ret != 0)
+            return ret;
+    }
+#endif
+
+#if defined(HAVE_PK_CALLBACKS)
+    if (ssl->ctx->EccSignCb) {
+        void* ctx = wolfSSL_GetEccSignCtx(ssl);
+        ret = ssl->ctx->EccSignCb(ssl, in, inSz, out, outSz, keyBuf,
+            keySz, ctx);
+    }
+    else
+#endif /* HAVE_PK_CALLBACKS */
+    {
+        ret = wc_ecc_sign_hash(in, inSz, out, outSz, ssl->rng, key);
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (key && ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    WOLFSSL_LEAVE("EccSign", ret);
+
+    return ret;
+}
+
+int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out,
+    word32 outSz, ecc_key* key, buffer* keyBufInfo)
+{
+    int ret;
+#ifdef HAVE_PK_CALLBACKS
+    const byte* keyBuf = NULL;
+    word32 keySz = 0;
+
+    if (keyBufInfo) {
+        keyBuf = keyBufInfo->buffer;
+        keySz = keyBufInfo->length;
+    }
+#endif
+
+    (void)ssl;
+    (void)keyBufInfo;
+
+    WOLFSSL_ENTER("EccVerify");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+    if (ret != 0)
+        return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+    if (ssl->ctx->EccVerifyCb) {
+        void* ctx = wolfSSL_GetEccVerifyCtx(ssl);
+        ret = ssl->ctx->EccVerifyCb(ssl, in, inSz, out, outSz, keyBuf, keySz,
+            &ssl->eccVerifyRes, ctx);
+    }
+    else
+#endif /* HAVE_PK_CALLBACKS  */
+    {
+        ret = wc_ecc_verify_hash(in, inSz, out, outSz, &ssl->eccVerifyRes, key);
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+    }
+    else
+#endif /* WOLFSSL_ASYNC_CRYPT */
+    {
+        ret = (ret != 0 || ssl->eccVerifyRes == 0) ? VERIFY_SIGN_ERROR : 0;
+    }
+
+    WOLFSSL_LEAVE("EccVerify", ret);
+
+    return ret;
+}
+
+#ifdef HAVE_PK_CALLBACKS
+    /* Gets ECC key for shared secret callback testing
+     * Client side: returns peer key
+     * Server side: returns private key
+     */
+    static int EccGetKey(WOLFSSL* ssl, ecc_key** otherKey)
+    {
+        int ret = NO_PEER_KEY;
+        ecc_key* tmpKey = NULL;
+
+        if (ssl == NULL || otherKey == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        if (ssl->options.side == WOLFSSL_CLIENT_END) {
+            if (ssl->specs.static_ecdh) {
+                if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent ||
+                                           !ssl->peerEccDsaKey->dp) {
+                    return NO_PEER_KEY;
+                }
+                tmpKey = (struct ecc_key*)ssl->peerEccDsaKey;
+            }
+            else {
+                if (!ssl->peerEccKey || !ssl->peerEccKeyPresent ||
+                                        !ssl->peerEccKey->dp) {
+                    return NO_PEER_KEY;
+                }
+                tmpKey = (struct ecc_key*)ssl->peerEccKey;
+            }
+        }
+        else if (ssl->options.side == WOLFSSL_SERVER_END) {
+            if (ssl->specs.static_ecdh) {
+                if (ssl->hsKey == NULL) {
+                    return NO_PRIVATE_KEY;
+                }
+                tmpKey = (struct ecc_key*)ssl->hsKey;
+            }
+            else {
+                if (!ssl->eccTempKeyPresent) {
+                    return NO_PRIVATE_KEY;
+                }
+                tmpKey = (struct ecc_key*)ssl->eccTempKey;
+            }
+        }
+
+        if (tmpKey) {
+            *otherKey = tmpKey;
+            ret = 0;
+        }
+
+        return ret;
+    }
+#endif /* HAVE_PK_CALLBACKS */
+
+int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_key,
+        byte* pubKeyDer, word32* pubKeySz, byte* out, word32* outlen,
+        int side)
+{
+    int ret;
+#ifdef HAVE_PK_CALLBACKS
+    ecc_key* otherKey = NULL;
+#endif
+#ifdef WOLFSSL_ASYNC_CRYPT
+    WC_ASYNC_DEV* asyncDev = &priv_key->asyncDev;
+#endif
+
+    (void)ssl;
+    (void)pubKeyDer;
+    (void)pubKeySz;
+    (void)side;
+
+    WOLFSSL_ENTER("EccSharedSecret");
+
+#ifdef HAVE_PK_CALLBACKS
+    if (ssl->ctx->EccSharedSecretCb) {
+        ret = EccGetKey(ssl, &otherKey);
+        if (ret != 0)
+            return ret;
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        asyncDev = &otherKey->asyncDev;
+    #endif
+    }
+#endif
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+    if (ret != 0)
+        return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+    if (ssl->ctx->EccSharedSecretCb) {
+        void* ctx = wolfSSL_GetEccSharedSecretCtx(ssl);
+        ret = ssl->ctx->EccSharedSecretCb(ssl, otherKey, pubKeyDer,
+            pubKeySz, out, outlen, side, ctx);
+    }
+    else
+#endif
+    {
+        ret = wc_ecc_shared_secret(priv_key, pub_key, out, outlen);
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    WOLFSSL_LEAVE("EccSharedSecret", ret);
+
+    return ret;
+}
+
+int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer)
+{
+    int ret = 0;
+    int keySz = 0;
+    int ecc_curve = ECC_CURVE_DEF;
+
+    WOLFSSL_ENTER("EccMakeKey");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_NONE);
+    if (ret != 0)
+        return ret;
+#endif
+
+    /* get key size */
+    if (peer == NULL) {
+        keySz = ssl->eccTempKeySz;
+    }
+    else {
+        keySz = peer->dp->size;
+    }
+
+    /* get curve type */
+    if (ssl->ecdhCurveOID > 0) {
+        ecc_curve = wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, NULL);
+    }
+
+#ifdef HAVE_PK_CALLBACKS
+    if (ssl->ctx->EccKeyGenCb) {
+        void* ctx = wolfSSL_GetEccKeyGenCtx(ssl);
+        ret = ssl->ctx->EccKeyGenCb(ssl, key, keySz, ecc_curve, ctx);
+    }
+    else
+#endif
+    {
+        ret = wc_ecc_make_key_ex(ssl->rng, keySz, key, ecc_curve);
+    }
+
+    /* make sure the curve is set for TLS */
+    if (ret == 0 && key->dp) {
+        ssl->ecdhCurveOID = key->dp->oidSum;
+    #if defined(WOLFSSL_TLS13) || defined(HAVE_FFDHE)
+        ssl->namedGroup = 0;
+    #endif
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    WOLFSSL_LEAVE("EccMakeKey", ret);
+
+    return ret;
+}
+#endif /* HAVE_ECC */
+
+#ifdef HAVE_ED25519
+/* Check whether the key contains a public key.
+ * If not then pull it out of the leaf certificate.
+ *
+ * ssl  SSL/TLS object.
+ * returns MEMORY_E when unable to allocate memory, a parsing error, otherwise
+ * 0 on success.
+ */
+int Ed25519CheckPubKey(WOLFSSL* ssl)
+{
+    ed25519_key* key = (ed25519_key*)ssl->hsKey;
+    int ret = 0;
+
+    /* Public key required for signing. */
+    if (!key->pubKeySet) {
+        DerBuffer* leaf = ssl->buffers.certificate;
+        DecodedCert* cert = (DecodedCert*)XMALLOC(sizeof(*cert),
+                                     ssl->heap, DYNAMIC_TYPE_DCERT);
+        if (cert == NULL)
+            ret = MEMORY_E;
+
+        if (ret == 0) {
+            InitDecodedCert(cert, leaf->buffer, leaf->length, ssl->heap);
+            ret = DecodeToKey(cert, 0);
+        }
+        if (ret == 0) {
+            ret = wc_ed25519_import_public(cert->publicKey, cert->pubKeySize,
+                                                                           key);
+        }
+        if (cert != NULL) {
+            FreeDecodedCert(cert);
+            XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
+        }
+    }
+
+    return ret;
+}
+
+/* Sign the data using EdDSA and key using Ed25519.
+ *
+ * ssl    SSL object.
+ * in     Data or message to sign.
+ * inSz   Length of the data.
+ * out    Buffer to hold signature.
+ * outSz  On entry, size of the buffer. On exit, the size of the signature.
+ * key    The private Ed25519 key data.
+ * keySz  The length of the private key data in bytes.
+ * ctx    The callback context.
+ * returns 0 on success, otherwise the value is an error.
+ */
+int Ed25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
+                word32* outSz, ed25519_key* key, DerBuffer* keyBufInfo)
+{
+    int ret;
+#ifdef HAVE_PK_CALLBACKS
+    const byte* keyBuf = NULL;
+    word32 keySz = 0;
+
+    if (keyBufInfo) {
+        keyBuf = keyBufInfo->buffer;
+        keySz = keyBufInfo->length;
+    }
+#endif
+
+    (void)ssl;
+    (void)keyBufInfo;
+
+    WOLFSSL_ENTER("Ed25519Sign");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+    if (ret != 0)
+        return ret;
+#endif
+
+#if defined(HAVE_PK_CALLBACKS)
+    if (ssl->ctx->Ed25519SignCb) {
+        void* ctx = wolfSSL_GetEd25519SignCtx(ssl);
+        ret = ssl->ctx->Ed25519SignCb(ssl, in, inSz, out, outSz, keyBuf,
+            keySz, ctx);
+    }
+    else
+#endif /* HAVE_PK_CALLBACKS */
+    {
+        ret = wc_ed25519_sign_msg(in, inSz, out, outSz, key);
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    WOLFSSL_LEAVE("Ed25519Sign", ret);
+
+    return ret;
+}
+
+/* Verify the data using EdDSA and key using Ed25519.
+ *
+ * ssl    SSL object.
+ * in     Signature data.
+ * inSz   Length of the signature data in bytes.
+ * msg    Message to verify.
+ * outSz  Length of message in bytes.
+ * key    The public Ed25519 key data.
+ * keySz  The length of the private key data in bytes.
+ * ctx    The callback context.
+ * returns 0 on success, otherwise the value is an error.
+ */
+int Ed25519Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg,
+                  word32 msgSz, ed25519_key* key, buffer* keyBufInfo)
+{
+    int ret;
+#ifdef HAVE_PK_CALLBACKS
+    const byte* keyBuf = NULL;
+    word32 keySz = 0;
+
+    if (keyBufInfo) {
+        keyBuf = keyBufInfo->buffer;
+        keySz = keyBufInfo->length;
+    }
+#endif
+
+    (void)ssl;
+    (void)keyBufInfo;
+
+    WOLFSSL_ENTER("Ed25519Verify");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+    if (ret != 0)
+        return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+    if (ssl->ctx->Ed25519VerifyCb) {
+        void* ctx = wolfSSL_GetEd25519VerifyCtx(ssl);
+        ret = ssl->ctx->Ed25519VerifyCb(ssl, in, inSz, msg, msgSz, keyBuf,
+                                        keySz, &ssl->eccVerifyRes, ctx);
+    }
+    else
+#endif /* HAVE_PK_CALLBACKS  */
+    {
+        ret = wc_ed25519_verify_msg(in, inSz, msg, msgSz,
+                                    &ssl->eccVerifyRes, key);
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+    }
+    else
+#endif /* WOLFSSL_ASYNC_CRYPT */
+    {
+        ret = (ret != 0 || ssl->eccVerifyRes == 0) ? VERIFY_SIGN_ERROR : 0;
+    }
+
+    WOLFSSL_LEAVE("Ed25519Verify", ret);
+
+    return ret;
+}
+#endif /* HAVE_ED25519 */
+
+#ifndef WOLFSSL_NO_TLS12
+
+#ifdef HAVE_CURVE25519
+#ifdef HAVE_PK_CALLBACKS
+    /* Gets X25519 key for shared secret callback testing
+     * Client side: returns peer key
+     * Server side: returns private key
+     */
+    static int X25519GetKey(WOLFSSL* ssl, curve25519_key** otherKey)
+    {
+        int ret = NO_PEER_KEY;
+        struct curve25519_key* tmpKey = NULL;
+
+        if (ssl == NULL || otherKey == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        if (ssl->options.side == WOLFSSL_CLIENT_END) {
+            if (!ssl->peerX25519Key || !ssl->peerX25519KeyPresent ||
+                                       !ssl->peerX25519Key->dp) {
+                return NO_PEER_KEY;
+            }
+            tmpKey = (struct curve25519_key*)ssl->peerX25519Key;
+        }
+        else if (ssl->options.side == WOLFSSL_SERVER_END) {
+            if (!ssl->eccTempKeyPresent) {
+                return NO_PRIVATE_KEY;
+            }
+            tmpKey = (struct curve25519_key*)ssl->eccTempKey;
+        }
+
+        if (tmpKey) {
+            *otherKey = (curve25519_key *)tmpKey;
+            ret = 0;
+        }
+
+        return ret;
+    }
+#endif /* HAVE_PK_CALLBACKS */
+
+static int X25519SharedSecret(WOLFSSL* ssl, curve25519_key* priv_key,
+        curve25519_key* pub_key, byte* pubKeyDer, word32* pubKeySz,
+        byte* out, word32* outlen, int side)
+{
+    int ret;
+
+    (void)ssl;
+    (void)pubKeyDer;
+    (void)pubKeySz;
+    (void)side;
+
+    WOLFSSL_ENTER("X25519SharedSecret");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &priv_key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+    if (ret != 0)
+        return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+    if (ssl->ctx->X25519SharedSecretCb) {
+        curve25519_key* otherKey = NULL;
+
+        ret = X25519GetKey(ssl, &otherKey);
+        if (ret == 0) {
+            void* ctx = wolfSSL_GetX25519SharedSecretCtx(ssl);
+            ret = ssl->ctx->X25519SharedSecretCb(ssl, otherKey, pubKeyDer,
+                pubKeySz, out, outlen, side, ctx);
+        }
+    }
+    else
+#endif
+    {
+        ret = wc_curve25519_shared_secret_ex(priv_key, pub_key, out, outlen,
+                                             EC25519_LITTLE_ENDIAN);
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &priv_key->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    WOLFSSL_LEAVE("X25519SharedSecret", ret);
+
+    return ret;
+}
+
+static int X25519MakeKey(WOLFSSL* ssl, curve25519_key* key,
+        curve25519_key* peer)
+{
+    int ret = 0;
+
+    (void)peer;
+
+    WOLFSSL_ENTER("X25519MakeKey");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_NONE);
+    if (ret != 0)
+        return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+    if (ssl->ctx->X25519KeyGenCb) {
+        void* ctx = wolfSSL_GetX25519KeyGenCtx(ssl);
+        ret = ssl->ctx->X25519KeyGenCb(ssl, key, CURVE25519_KEYSIZE, ctx);
+    }
+    else
+#endif
+    {
+        ret = wc_curve25519_make_key(ssl->rng, CURVE25519_KEYSIZE, key);
+    }
+
+    if (ret == 0) {
+        ssl->ecdhCurveOID = ECC_X25519_OID;
+    #if defined(WOLFSSL_TLS13) || defined(HAVE_FFDHE)
+        ssl->namedGroup = 0;
+    #endif
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    WOLFSSL_LEAVE("X25519MakeKey", ret);
+
+    return ret;
+}
+#endif /* HAVE_CURVE25519 */
+
+#ifdef HAVE_ED448
+/* Check whether the key contains a public key.
+ * If not then pull it out of the leaf certificate.
+ *
+ * ssl  SSL/TLS object.
+ * returns MEMORY_E when unable to allocate memory, a parsing error, otherwise
+ * 0 on success.
+ */
+int Ed448CheckPubKey(WOLFSSL* ssl)
+{
+    ed448_key* key = (ed448_key*)ssl->hsKey;
+    int ret = 0;
+
+    /* Public key required for signing. */
+    if (!key->pubKeySet) {
+        DerBuffer* leaf = ssl->buffers.certificate;
+        DecodedCert* cert = (DecodedCert*)XMALLOC(sizeof(*cert), ssl->heap,
+            DYNAMIC_TYPE_DCERT);
+        if (cert == NULL)
+            ret = MEMORY_E;
+
+        if (ret == 0) {
+            InitDecodedCert(cert, leaf->buffer, leaf->length, ssl->heap);
+            ret = DecodeToKey(cert, 0);
+        }
+        if (ret == 0) {
+            ret = wc_ed448_import_public(cert->publicKey, cert->pubKeySize,
+                key);
+        }
+        if (cert != NULL) {
+            FreeDecodedCert(cert);
+            XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
+        }
+    }
+
+    return ret;
+}
+
+/* Sign the data using EdDSA and key using Ed448.
+ *
+ * ssl    SSL object.
+ * in     Data or message to sign.
+ * inSz   Length of the data.
+ * out    Buffer to hold signature.
+ * outSz  On entry, size of the buffer. On exit, the size of the signature.
+ * key    The private Ed448 key data.
+ * keySz  The length of the private key data in bytes.
+ * ctx    The callback context.
+ * returns 0 on success, otherwise the value is an error.
+ */
+int Ed448Sign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
+              word32* outSz, ed448_key* key, DerBuffer* keyBufInfo)
+{
+    int ret;
+#ifdef HAVE_PK_CALLBACKS
+    const byte* keyBuf = NULL;
+    word32 keySz = 0;
+
+    if (keyBufInfo) {
+        keyBuf = keyBufInfo->buffer;
+        keySz = keyBufInfo->length;
+    }
+#endif
+
+    (void)ssl;
+    (void)keyBufInfo;
+
+    WOLFSSL_ENTER("Ed448Sign");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+    if (ret != 0)
+        return ret;
+#endif
+
+#if defined(HAVE_PK_CALLBACKS)
+    if (ssl->ctx->Ed448SignCb) {
+        void* ctx = wolfSSL_GetEd448SignCtx(ssl);
+        ret = ssl->ctx->Ed448SignCb(ssl, in, inSz, out, outSz, keyBuf, keySz,
+            ctx);
+    }
+    else
+#endif /* HAVE_PK_CALLBACKS */
+    {
+        ret = wc_ed448_sign_msg(in, inSz, out, outSz, key, NULL, 0);
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    WOLFSSL_LEAVE("Ed448Sign", ret);
+
+    return ret;
+}
+
+/* Verify the data using EdDSA and key using Ed448.
+ *
+ * ssl    SSL object.
+ * in     Signature data.
+ * inSz   Length of the signature data in bytes.
+ * msg    Message to verify.
+ * outSz  Length of message in bytes.
+ * key    The public Ed448 key data.
+ * keySz  The length of the private key data in bytes.
+ * ctx    The callback context.
+ * returns 0 on success, otherwise the value is an error.
+ */
+int Ed448Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg,
+                word32 msgSz, ed448_key* key, buffer* keyBufInfo)
+{
+    int ret;
+#ifdef HAVE_PK_CALLBACKS
+    const byte* keyBuf = NULL;
+    word32 keySz = 0;
+
+    if (keyBufInfo) {
+        keyBuf = keyBufInfo->buffer;
+        keySz = keyBufInfo->length;
+    }
+#endif
+
+    (void)ssl;
+    (void)keyBufInfo;
+
+    WOLFSSL_ENTER("Ed448Verify");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+    if (ret != 0)
+        return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+    if (ssl->ctx->Ed448VerifyCb) {
+        void* ctx = wolfSSL_GetEd448VerifyCtx(ssl);
+        ret = ssl->ctx->Ed448VerifyCb(ssl, in, inSz, msg, msgSz, keyBuf, keySz,
+             &ssl->eccVerifyRes, ctx);
+    }
+    else
+#endif /* HAVE_PK_CALLBACKS  */
+    {
+        ret = wc_ed448_verify_msg(in, inSz, msg, msgSz, &ssl->eccVerifyRes, key,
+            NULL, 0);
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+    }
+    else
+#endif /* WOLFSSL_ASYNC_CRYPT */
+    {
+        ret = (ret != 0 || ssl->eccVerifyRes == 0) ? VERIFY_SIGN_ERROR : 0;
+    }
+
+    WOLFSSL_LEAVE("Ed448Verify", ret);
+
+    return ret;
+}
+#endif /* HAVE_ED448 */
+
+#ifdef HAVE_CURVE448
+#ifdef HAVE_PK_CALLBACKS
+    /* Gets X448 key for shared secret callback testing
+     * Client side: returns peer key
+     * Server side: returns private key
+     */
+    static int X448GetKey(WOLFSSL* ssl, curve448_key** otherKey)
+    {
+        int ret = NO_PEER_KEY;
+        struct curve448_key* tmpKey = NULL;
+
+        if (ssl == NULL || otherKey == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        if (ssl->options.side == WOLFSSL_CLIENT_END) {
+            if (!ssl->peerX448Key || !ssl->peerX448KeyPresent) {
+                return NO_PEER_KEY;
+            }
+            tmpKey = (struct curve448_key*)ssl->peerX448Key;
+        }
+        else if (ssl->options.side == WOLFSSL_SERVER_END) {
+            if (!ssl->eccTempKeyPresent) {
+                return NO_PRIVATE_KEY;
+            }
+            tmpKey = (struct curve448_key*)ssl->eccTempKey;
+        }
+
+        if (tmpKey) {
+            *otherKey = (curve448_key *)tmpKey;
+            ret = 0;
+        }
+
+        return ret;
+    }
+#endif /* HAVE_PK_CALLBACKS */
+
+static int X448SharedSecret(WOLFSSL* ssl, curve448_key* priv_key,
+                            curve448_key* pub_key, byte* pubKeyDer,
+                            word32* pubKeySz, byte* out, word32* outlen,
+                            int side)
+{
+    int ret;
+
+    (void)ssl;
+    (void)pubKeyDer;
+    (void)pubKeySz;
+    (void)side;
+
+    WOLFSSL_ENTER("X448SharedSecret");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &priv_key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+    if (ret != 0)
+        return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+    if (ssl->ctx->X448SharedSecretCb) {
+        curve448_key* otherKey = NULL;
+
+        ret = X448GetKey(ssl, &otherKey);
+        if (ret == 0) {
+            void* ctx = wolfSSL_GetX448SharedSecretCtx(ssl);
+            ret = ssl->ctx->X448SharedSecretCb(ssl, otherKey, pubKeyDer,
+                pubKeySz, out, outlen, side, ctx);
+        }
+    }
+    else
+#endif
+    {
+        ret = wc_curve448_shared_secret_ex(priv_key, pub_key, out, outlen,
+            EC448_LITTLE_ENDIAN);
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &priv_key->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    WOLFSSL_LEAVE("X448SharedSecret", ret);
+
+    return ret;
+}
+
+static int X448MakeKey(WOLFSSL* ssl, curve448_key* key, curve448_key* peer)
+{
+    int ret = 0;
+
+    (void)peer;
+
+    WOLFSSL_ENTER("X448MakeKey");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_NONE);
+    if (ret != 0)
+        return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+    if (ssl->ctx->X448KeyGenCb) {
+        void* ctx = wolfSSL_GetX448KeyGenCtx(ssl);
+        ret = ssl->ctx->X448KeyGenCb(ssl, key, CURVE448_KEY_SIZE, ctx);
+    }
+    else
+#endif
+    {
+        ret = wc_curve448_make_key(ssl->rng, CURVE448_KEY_SIZE, key);
+    }
+
+    if (ret == 0) {
+        ssl->ecdhCurveOID = ECC_X448_OID;
+    #if defined(WOLFSSL_TLS13) || defined(HAVE_FFDHE)
+        ssl->namedGroup = 0;
+    #endif
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    WOLFSSL_LEAVE("X448MakeKey", ret);
+
+    return ret;
+}
+#endif /* HAVE_CURVE448 */
+
+#if !defined(NO_CERTS) || !defined(NO_PSK)
+#if !defined(NO_DH)
+
+int DhGenKeyPair(WOLFSSL* ssl, DhKey* dhKey,
+    byte* priv, word32* privSz,
+    byte* pub, word32* pubSz)
+{
+    int ret;
+
+    WOLFSSL_ENTER("DhGenKeyPair");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE);
+    if (ret != 0)
+        return ret;
+#endif
+
+    ret = wc_DhGenerateKeyPair(dhKey, ssl->rng, priv, privSz, pub, pubSz);
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &dhKey->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    WOLFSSL_LEAVE("DhGenKeyPair", ret);
+
+    return ret;
+}
+
+int DhAgree(WOLFSSL* ssl, DhKey* dhKey,
+    const byte* priv, word32 privSz,
+    const byte* otherPub, word32 otherPubSz,
+    byte* agree, word32* agreeSz)
+{
+    int ret;
+
+    (void)ssl;
+
+    WOLFSSL_ENTER("DhAgree");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE);
+    if (ret != 0)
+        return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+    if (ssl->ctx->DhAgreeCb) {
+        void* ctx = wolfSSL_GetDhAgreeCtx(ssl);
+
+        WOLFSSL_MSG("Calling DhAgree Callback Function");
+        ret = ssl->ctx->DhAgreeCb(ssl, dhKey, priv, privSz,
+                    otherPub, otherPubSz, agree, agreeSz, ctx);
+    }
+    else
+#endif
+    {
+#if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
+        ret = wc_DhCheckPubValue(ssl->buffers.serverDH_P.buffer,
+                    ssl->buffers.serverDH_P.length, otherPub, otherPubSz);
+        if (ret != 0) {
+    #ifdef OPENSSL_EXTRA
+            SendAlert(ssl, alert_fatal, illegal_parameter);
+    #endif
+        }
+        else
+#endif
+        {
+            ret = wc_DhAgree(dhKey, agree, agreeSz, priv, privSz, otherPub,
+                    otherPubSz);
+        }
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &dhKey->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    WOLFSSL_LEAVE("DhAgree", ret);
+
+    return ret;
+}
+#endif /* !NO_DH */
+#endif /* !NO_CERTS || !NO_PSK */
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+
+#ifdef HAVE_PK_CALLBACKS
+int wolfSSL_IsPrivatePkSet(WOLFSSL* ssl)
+{
+    int pkcbset = 0;
+    (void)ssl;
+
+#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \
+                                                                !defined(NO_RSA)
+    if (0
+    #ifdef HAVE_ECC
+        || (ssl->ctx->EccSignCb != NULL &&
+                                        ssl->buffers.keyType == ecc_dsa_sa_algo)
+    #endif
+    #ifdef HAVE_ED25519
+        || (ssl->ctx->Ed25519SignCb != NULL &&
+                                        ssl->buffers.keyType == ed25519_sa_algo)
+    #endif
+    #ifdef HAVE_ED448
+        || (ssl->ctx->Ed448SignCb != NULL &&
+                                          ssl->buffers.keyType == ed448_sa_algo)
+    #endif
+    #ifndef NO_RSA
+        || (ssl->ctx->RsaSignCb != NULL && ssl->buffers.keyType == rsa_sa_algo)
+        || (ssl->ctx->RsaDecCb != NULL && ssl->buffers.keyType == rsa_kea)
+        #ifdef WC_RSA_PSS
+        || (ssl->ctx->RsaPssSignCb != NULL &&
+                                        ssl->buffers.keyType == rsa_pss_sa_algo)
+        #endif
+    #endif
+    ) {
+        pkcbset = 1;
+    }
+#endif
+    return pkcbset;
+}
+
+int wolfSSL_CTX_IsPrivatePkSet(WOLFSSL_CTX* ctx)
+{
+    int pkcbset = 0;
+    (void)ctx;
+#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \
+                                                                !defined(NO_RSA)
+    if (0
+    #ifdef HAVE_ECC
+        || ctx->EccSignCb != NULL
+    #endif
+    #ifdef HAVE_ED25519
+        || ctx->Ed25519SignCb != NULL
+    #endif
+    #ifdef HAVE_ED448
+        || ctx->Ed448SignCb != NULL
+    #endif
+    #ifndef NO_RSA
+        || ctx->RsaSignCb != NULL
+        || ctx->RsaDecCb != NULL
+        #ifdef WC_RSA_PSS
+        || ctx->RsaPssSignCb != NULL
+        #endif
+    #endif
+    ) {
+        pkcbset = 1;
+    }
+#endif
+    return pkcbset;
+}
+#endif /* HAVE_PK_CALLBACKS */
+
+
+int InitSSL_Suites(WOLFSSL* ssl)
+{
+    int keySz = 0;
+    byte havePSK = 0;
+    byte haveAnon = 0;
+    byte haveRSA = 0;
+    byte haveMcast = 0;
+
+    (void)haveAnon; /* Squash unused var warnings */
+    (void)haveMcast;
+
+    if (!ssl)
+        return BAD_FUNC_ARG;
+
+#ifndef NO_RSA
+    haveRSA = 1;
+#endif
+#ifndef NO_PSK
+    havePSK = (byte)ssl->options.havePSK;
+#endif /* NO_PSK */
+#ifdef HAVE_ANON
+    haveAnon = (byte)ssl->options.haveAnon;
+#endif /* HAVE_ANON*/
+#ifdef WOLFSSL_MULTICAST
+    haveMcast = (byte)ssl->options.haveMcast;
+#endif /* WOLFSSL_MULTICAST */
+
+#ifdef WOLFSSL_EARLY_DATA
+    if (ssl->options.side == WOLFSSL_SERVER_END)
+        ssl->options.maxEarlyDataSz = ssl->ctx->maxEarlyDataSz;
+#endif
+#if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
+               ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \
+                (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)))
+    ssl->options.cacheMessages = ssl->options.side == WOLFSSL_SERVER_END ||
+                                      ssl->buffers.keyType == ed25519_sa_algo ||
+                                      ssl->buffers.keyType == ed448_sa_algo;
+#endif
+
+#ifndef NO_CERTS
+    keySz = ssl->buffers.keySz;
+#endif
+
+    /* make sure server has DH parms, and add PSK if there, add NTRU too */
+    if (ssl->options.side == WOLFSSL_SERVER_END) {
+        InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
+                   ssl->options.haveDH, ssl->options.haveNTRU,
+                   ssl->options.haveECDSAsig, ssl->options.haveECC,
+                   ssl->options.haveStaticECC, ssl->options.side);
+    }
+    else {
+        InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
+                   TRUE, ssl->options.haveNTRU,
+                   ssl->options.haveECDSAsig, ssl->options.haveECC,
+                   ssl->options.haveStaticECC, ssl->options.side);
+    }
+
+#if !defined(NO_CERTS) && !defined(WOLFSSL_SESSION_EXPORT)
+    /* make sure server has cert and key unless using PSK, Anon, or
+     * Multicast. This should be true even if just switching ssl ctx */
+    if (ssl->options.side == WOLFSSL_SERVER_END &&
+            !havePSK && !haveAnon && !haveMcast) {
+
+        /* server certificate must be loaded */
+        if (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer) {
+            WOLFSSL_MSG("Server missing certificate");
+            return NO_PRIVATE_KEY;
+        }
+
+        /* allow no private key if using PK callbacks and CB is set */
+    #ifdef HAVE_PK_CALLBACKS
+        if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) {
+            WOLFSSL_MSG("Using PK for server private key");
+        }
+        else
+    #endif
+        if (!ssl->buffers.key || !ssl->buffers.key->buffer) {
+            WOLFSSL_MSG("Server missing private key");
+            return NO_PRIVATE_KEY;
+        }
+    }
+#endif
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* returns new reference count. Arg incr positive=up or negative=down */
+int SSL_CTX_RefCount(WOLFSSL_CTX* ctx, int incr)
+{
+    int refCount;
+
+    if (ctx == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (wc_LockMutex(&ctx->countMutex) != 0) {
+        WOLFSSL_MSG("Couldn't lock CTX count mutex");
+        return BAD_MUTEX_E;
+    }
+
+    ctx->refCount += incr;
+    /* make sure refCount is never negative */
+    if (ctx->refCount < 0) {
+        ctx->refCount = 0;
+    }
+    refCount = ctx->refCount;
+
+    wc_UnLockMutex(&ctx->countMutex);
+
+    return refCount;
+}
+
+/* This function inherits a WOLFSSL_CTX's fields into an SSL object.
+   It is used during initialization and to switch an ssl's CTX with
+   wolfSSL_Set_SSL_CTX.  Requires ssl->suites alloc and ssl-arrays with PSK
+   unless writeDup is on.
+
+   ssl      object to initialize
+   ctx      parent factory
+   writeDup flag indicating this is a write dup only
+
+   WOLFSSL_SUCCESS return value on success */
+int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
+{
+    int ret;
+    byte newSSL;
+
+    if (!ssl || !ctx)
+        return BAD_FUNC_ARG;
+
+#ifndef SINGLE_THREADED
+    if (ssl->suites == NULL && !writeDup)
+        return BAD_FUNC_ARG;
+#endif
+
+    newSSL = ssl->ctx == NULL; /* Assign after null check */
+
+#ifndef NO_PSK
+    if (ctx->server_hint[0] && ssl->arrays == NULL && !writeDup) {
+        return BAD_FUNC_ARG;  /* needed for copy below */
+    }
+#endif
+
+    /* decrement previous CTX reference count if exists.
+     * This should only happen if switching ctxs!*/
+    if (!newSSL) {
+        WOLFSSL_MSG("freeing old ctx to decrement reference count. Switching ctx.");
+        wolfSSL_CTX_free(ssl->ctx);
+    }
+
+    /* increment CTX reference count */
+    if ((ret = SSL_CTX_RefCount(ctx, 1)) < 0) {
+        return ret;
+    }
+    ret = WOLFSSL_SUCCESS; /* set default ret */
+
+    ssl->ctx     = ctx; /* only for passing to calls, options could change */
+    ssl->version = ctx->method->version;
+
+#ifdef HAVE_ECC
+    ssl->eccTempKeySz = ctx->eccTempKeySz;
+    ssl->ecdhCurveOID = ctx->ecdhCurveOID;
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
+    ssl->pkCurveOID = ctx->pkCurveOID;
+#endif
+
+#ifdef OPENSSL_EXTRA
+    ssl->options.mask = ctx->mask;
+    ssl->CBIS         = ctx->CBIS;
+#endif
+    ssl->timeout = ctx->timeout;
+    ssl->verifyCallback    = ctx->verifyCallback;
+    ssl->options.side      = ctx->method->side;
+    ssl->options.downgrade    = ctx->method->downgrade;
+    ssl->options.minDowngrade = ctx->minDowngrade;
+
+    ssl->options.haveDH        = ctx->haveDH;
+    ssl->options.haveNTRU      = ctx->haveNTRU;
+    ssl->options.haveECDSAsig  = ctx->haveECDSAsig;
+    ssl->options.haveECC       = ctx->haveECC;
+    ssl->options.haveStaticECC = ctx->haveStaticECC;
+
+#ifndef NO_PSK
+    ssl->options.havePSK   = ctx->havePSK;
+    ssl->options.client_psk_cb = ctx->client_psk_cb;
+    ssl->options.server_psk_cb = ctx->server_psk_cb;
+#ifdef WOLFSSL_TLS13
+    ssl->options.client_psk_tls13_cb = ctx->client_psk_tls13_cb;
+    ssl->options.server_psk_tls13_cb = ctx->server_psk_tls13_cb;
+#endif
+#endif /* NO_PSK */
+#ifdef WOLFSSL_EARLY_DATA
+    if (ssl->options.side == WOLFSSL_SERVER_END)
+        ssl->options.maxEarlyDataSz = ctx->maxEarlyDataSz;
+#endif
+
+#ifdef HAVE_ANON
+    ssl->options.haveAnon = ctx->haveAnon;
+#endif
+#ifndef NO_DH
+    ssl->options.minDhKeySz = ctx->minDhKeySz;
+    ssl->options.maxDhKeySz = ctx->maxDhKeySz;
+#endif
+#ifndef NO_RSA
+    ssl->options.minRsaKeySz = ctx->minRsaKeySz;
+#endif
+#ifdef HAVE_ECC
+    ssl->options.minEccKeySz = ctx->minEccKeySz;
+#endif
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+    ssl->options.verifyDepth = ctx->verifyDepth;
+#endif
+
+    ssl->options.sessionCacheOff      = ctx->sessionCacheOff;
+    ssl->options.sessionCacheFlushOff = ctx->sessionCacheFlushOff;
+#ifdef HAVE_EXT_CACHE
+    ssl->options.internalCacheOff     = ctx->internalCacheOff;
+#endif
+
+    ssl->options.verifyPeer     = ctx->verifyPeer;
+    ssl->options.verifyNone     = ctx->verifyNone;
+    ssl->options.failNoCert     = ctx->failNoCert;
+    ssl->options.failNoCertxPSK = ctx->failNoCertxPSK;
+    ssl->options.sendVerify     = ctx->sendVerify;
+
+    ssl->options.partialWrite  = ctx->partialWrite;
+    ssl->options.quietShutdown = ctx->quietShutdown;
+    ssl->options.groupMessages = ctx->groupMessages;
+
+#ifndef NO_DH
+    #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \
+        !defined(HAVE_SELFTEST)
+        ssl->options.dhKeyTested = ctx->dhKeyTested;
+    #endif
+    ssl->buffers.serverDH_P = ctx->serverDH_P;
+    ssl->buffers.serverDH_G = ctx->serverDH_G;
+#endif
+
+#ifndef NO_CERTS
+    /* ctx still owns certificate, certChain, key, dh, and cm */
+    ssl->buffers.certificate = ctx->certificate;
+    ssl->buffers.certChain = ctx->certChain;
+#ifdef WOLFSSL_TLS13
+    ssl->buffers.certChainCnt = ctx->certChainCnt;
+#endif
+    ssl->buffers.key      = ctx->privateKey;
+    ssl->buffers.keyType  = ctx->privateKeyType;
+    ssl->buffers.keyId    = ctx->privateKeyId;
+    ssl->buffers.keySz    = ctx->privateKeySz;
+    ssl->buffers.keyDevId = ctx->privateKeyDevId;
+#endif
+#if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
+               ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \
+                (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)))
+    ssl->options.cacheMessages = ssl->options.side == WOLFSSL_SERVER_END ||
+                                      ssl->buffers.keyType == ed25519_sa_algo ||
+                                      ssl->buffers.keyType == ed448_sa_algo;
+#endif
+
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ssl->devId = ctx->devId;
+#endif
+
+    if (writeDup == 0) {
+#ifndef NO_PSK
+        if (ctx->server_hint[0]) {   /* set in CTX */
+            XSTRNCPY(ssl->arrays->server_hint, ctx->server_hint,
+                                    sizeof(ssl->arrays->server_hint));
+            ssl->arrays->server_hint[MAX_PSK_ID_LEN] = '\0'; /* null term */
+        }
+#endif /* NO_PSK */
+
+        if (ctx->suites) {
+#ifndef SINGLE_THREADED
+            *ssl->suites = *ctx->suites;
+#else
+            ssl->suites = ctx->suites;
+#endif
+        }
+        else {
+            XMEMSET(ssl->suites, 0, sizeof(Suites));
+        }
+
+        if (ssl->options.side != WOLFSSL_NEITHER_END) {
+            /* Defer initializing suites until accept or connect */
+            ret = InitSSL_Suites(ssl);
+        }
+    }  /* writeDup check */
+
+#ifdef WOLFSSL_SESSION_EXPORT
+    #ifdef WOLFSSL_DTLS
+    ssl->dtls_export = ctx->dtls_export; /* export function for session */
+    #endif
+#endif
+
+    ssl->CBIORecv = ctx->CBIORecv;
+    ssl->CBIOSend = ctx->CBIOSend;
+#ifdef OPENSSL_EXTRA
+    ssl->readAhead = ctx->readAhead;
+#endif
+    ssl->verifyDepth = ctx->verifyDepth;
+
+    return ret;
+}
+
+int InitHandshakeHashes(WOLFSSL* ssl)
+{
+    int ret;
+
+    /* make sure existing handshake hashes are free'd */
+    if (ssl->hsHashes != NULL) {
+        FreeHandshakeHashes(ssl);
+    }
+
+    /* allocate handshake hashes */
+    ssl->hsHashes = (HS_Hashes*)XMALLOC(sizeof(HS_Hashes), ssl->heap,
+                                                           DYNAMIC_TYPE_HASHES);
+    if (ssl->hsHashes == NULL) {
+        WOLFSSL_MSG("HS_Hashes Memory error");
+        return MEMORY_E;
+    }
+    XMEMSET(ssl->hsHashes, 0, sizeof(HS_Hashes));
+
+#ifndef NO_OLD_TLS
+#ifndef NO_MD5
+    ret = wc_InitMd5_ex(&ssl->hsHashes->hashMd5, ssl->heap, ssl->devId);
+    if (ret != 0)
+        return ret;
+    #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+        wc_Md5SetFlags(&ssl->hsHashes->hashMd5, WC_HASH_FLAG_WILLCOPY);
+    #endif
+#endif
+#ifndef NO_SHA
+    ret = wc_InitSha_ex(&ssl->hsHashes->hashSha, ssl->heap, ssl->devId);
+    if (ret != 0)
+        return ret;
+    #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+        wc_ShaSetFlags(&ssl->hsHashes->hashSha, WC_HASH_FLAG_WILLCOPY);
+    #endif
+#endif
+#endif /* !NO_OLD_TLS */
+#ifndef NO_SHA256
+    ret = wc_InitSha256_ex(&ssl->hsHashes->hashSha256, ssl->heap, ssl->devId);
+    if (ret != 0)
+        return ret;
+    #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+        wc_Sha256SetFlags(&ssl->hsHashes->hashSha256, WC_HASH_FLAG_WILLCOPY);
+    #endif
+#endif
+#ifdef WOLFSSL_SHA384
+    ret = wc_InitSha384_ex(&ssl->hsHashes->hashSha384, ssl->heap, ssl->devId);
+    if (ret != 0)
+        return ret;
+    #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+        wc_Sha384SetFlags(&ssl->hsHashes->hashSha384, WC_HASH_FLAG_WILLCOPY);
+    #endif
+#endif
+#ifdef WOLFSSL_SHA512
+    ret = wc_InitSha512_ex(&ssl->hsHashes->hashSha512, ssl->heap, ssl->devId);
+    if (ret != 0)
+        return ret;
+    #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+        wc_Sha512SetFlags(&ssl->hsHashes->hashSha512, WC_HASH_FLAG_WILLCOPY);
+    #endif
+#endif
+
+    return ret;
+}
+
+void FreeHandshakeHashes(WOLFSSL* ssl)
+{
+    if (ssl->hsHashes) {
+#ifndef NO_OLD_TLS
+    #ifndef NO_MD5
+        wc_Md5Free(&ssl->hsHashes->hashMd5);
+    #endif
+    #ifndef NO_SHA
+        wc_ShaFree(&ssl->hsHashes->hashSha);
+    #endif
+#endif /* !NO_OLD_TLS */
+    #ifndef NO_SHA256
+        wc_Sha256Free(&ssl->hsHashes->hashSha256);
+    #endif
+    #ifdef WOLFSSL_SHA384
+        wc_Sha384Free(&ssl->hsHashes->hashSha384);
+    #endif
+    #ifdef WOLFSSL_SHA512
+        wc_Sha512Free(&ssl->hsHashes->hashSha512);
+    #endif
+    #if (defined(HAVE_ED25519) || defined(HAVE_ED448)) && \
+                                                !defined(WOLFSSL_NO_CLIENT_AUTH)
+        if (ssl->hsHashes->messages != NULL) {
+            XFREE(ssl->hsHashes->messages, ssl->heap, DYNAMIC_TYPE_HASHES);
+            ssl->hsHashes->messages = NULL;
+         }
+    #endif
+
+        XFREE(ssl->hsHashes, ssl->heap, DYNAMIC_TYPE_HASHES);
+        ssl->hsHashes = NULL;
+    }
+}
+
+
+/* init everything to 0, NULL, default values before calling anything that may
+   fail so that destructor has a "good" state to cleanup
+
+   ssl      object to initialize
+   ctx      parent factory
+   writeDup flag indicating this is a write dup only
+
+   0 on success */
+int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
+{
+    int  ret;
+
+    XMEMSET(ssl, 0, sizeof(WOLFSSL));
+
+#if defined(WOLFSSL_STATIC_MEMORY)
+    if (ctx->heap != NULL) {
+        WOLFSSL_HEAP_HINT* ssl_hint;
+        WOLFSSL_HEAP_HINT* ctx_hint;
+
+        /* avoid dereferencing a test value */
+    #ifdef WOLFSSL_HEAP_TEST
+        if (ctx->heap == (void*)WOLFSSL_HEAP_TEST) {
+            ssl->heap = ctx->heap;
+        }
+        else {
+    #endif
+        ssl->heap = (WOLFSSL_HEAP_HINT*)XMALLOC(sizeof(WOLFSSL_HEAP_HINT),
+                                               ctx->heap, DYNAMIC_TYPE_SSL);
+        if (ssl->heap == NULL) {
+            return MEMORY_E;
+        }
+        XMEMSET(ssl->heap, 0, sizeof(WOLFSSL_HEAP_HINT));
+        ssl_hint = ((WOLFSSL_HEAP_HINT*)(ssl->heap));
+        ctx_hint = ((WOLFSSL_HEAP_HINT*)(ctx->heap));
+
+        /* lock and check IO count / handshake count */
+        if (wc_LockMutex(&(ctx_hint->memory->memory_mutex)) != 0) {
+            WOLFSSL_MSG("Bad memory_mutex lock");
+            XFREE(ssl->heap, ctx->heap, DYNAMIC_TYPE_SSL);
+            ssl->heap = NULL; /* free and set to NULL for IO counter */
+            return BAD_MUTEX_E;
+        }
+        if (ctx_hint->memory->maxHa > 0 &&
+                           ctx_hint->memory->maxHa <= ctx_hint->memory->curHa) {
+            WOLFSSL_MSG("At max number of handshakes for static memory");
+            wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+            XFREE(ssl->heap, ctx->heap, DYNAMIC_TYPE_SSL);
+            ssl->heap = NULL; /* free and set to NULL for IO counter */
+            return MEMORY_E;
+        }
+
+        if (ctx_hint->memory->maxIO > 0 &&
+                           ctx_hint->memory->maxIO <= ctx_hint->memory->curIO) {
+            WOLFSSL_MSG("At max number of IO allowed for static memory");
+            wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+            XFREE(ssl->heap, ctx->heap, DYNAMIC_TYPE_SSL);
+            ssl->heap = NULL; /* free and set to NULL for IO counter */
+            return MEMORY_E;
+        }
+        ctx_hint->memory->curIO++;
+        ctx_hint->memory->curHa++;
+        ssl_hint->memory = ctx_hint->memory;
+        ssl_hint->haFlag = 1;
+        wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+
+        /* check if tracking stats */
+        if (ctx_hint->memory->flag & WOLFMEM_TRACK_STATS) {
+            ssl_hint->stats = (WOLFSSL_MEM_CONN_STATS*)XMALLOC(
+               sizeof(WOLFSSL_MEM_CONN_STATS), ctx->heap, DYNAMIC_TYPE_SSL);
+            if (ssl_hint->stats == NULL) {
+                return MEMORY_E;
+            }
+            XMEMSET(ssl_hint->stats, 0, sizeof(WOLFSSL_MEM_CONN_STATS));
+        }
+
+        /* check if using fixed IO buffers */
+        if (ctx_hint->memory->flag & WOLFMEM_IO_POOL_FIXED) {
+            if (wc_LockMutex(&(ctx_hint->memory->memory_mutex)) != 0) {
+                WOLFSSL_MSG("Bad memory_mutex lock");
+                return BAD_MUTEX_E;
+            }
+            if (SetFixedIO(ctx_hint->memory, &(ssl_hint->inBuf)) != 1) {
+                wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+                return MEMORY_E;
+            }
+            if (SetFixedIO(ctx_hint->memory, &(ssl_hint->outBuf)) != 1) {
+                wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+                return MEMORY_E;
+            }
+            if (ssl_hint->outBuf == NULL || ssl_hint->inBuf == NULL) {
+                WOLFSSL_MSG("Not enough memory to create fixed IO buffers");
+                wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+                return MEMORY_E;
+            }
+            wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+        }
+    #ifdef WOLFSSL_HEAP_TEST
+        }
+    #endif
+    }
+    else {
+        ssl->heap = ctx->heap;
+    }
+#else
+    ssl->heap = ctx->heap; /* carry over user heap without static memory */
+#endif /* WOLFSSL_STATIC_MEMORY */
+
+    ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer;
+    ssl->buffers.inputBuffer.bufferSize  = STATIC_BUFFER_LEN;
+
+    ssl->buffers.outputBuffer.buffer = ssl->buffers.outputBuffer.staticBuffer;
+    ssl->buffers.outputBuffer.bufferSize  = STATIC_BUFFER_LEN;
+
+#ifdef KEEP_PEER_CERT
+    InitX509(&ssl->peerCert, 0, ssl->heap);
+#endif
+
+    ssl->rfd = -1;   /* set to invalid descriptor */
+    ssl->wfd = -1;
+    ssl->devId = ctx->devId; /* device for async HW (from wolfAsync_DevOpen) */
+
+    ssl->IOCB_ReadCtx  = &ssl->rfd;  /* prevent invalid pointer access if not */
+    ssl->IOCB_WriteCtx = &ssl->wfd;  /* correctly set */
+
+#ifdef HAVE_NETX
+    ssl->IOCB_ReadCtx  = &ssl->nxCtx;  /* default NetX IO ctx, same for read */
+    ssl->IOCB_WriteCtx = &ssl->nxCtx;  /* and write */
+#elif defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP)
+    ssl->mnCtx = mynewt_ctx_new();
+    if(!ssl->mnCtx) {
+        return MEMORY_E;
+    }
+    ssl->IOCB_ReadCtx  = ssl->mnCtx;  /* default Mynewt IO ctx, same for read */
+    ssl->IOCB_WriteCtx = ssl->mnCtx;  /* and write */
+#elif defined (WOLFSSL_GNRC)
+    ssl->IOCB_ReadCtx = ssl->gnrcCtx;
+    ssl->IOCB_WriteCtx = ssl->gnrcCtx;
+#endif
+    /* initialize states */
+    ssl->options.serverState = NULL_STATE;
+    ssl->options.clientState = NULL_STATE;
+    ssl->options.connectState = CONNECT_BEGIN;
+    ssl->options.acceptState  = ACCEPT_BEGIN;
+    ssl->options.handShakeState  = NULL_STATE;
+    ssl->options.processReply = doProcessInit;
+    ssl->options.asyncState = TLS_ASYNC_BEGIN;
+    ssl->options.buildMsgState = BUILD_MSG_BEGIN;
+    ssl->encrypt.state = CIPHER_STATE_BEGIN;
+    ssl->decrypt.state = CIPHER_STATE_BEGIN;
+#ifndef NO_DH
+    #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \
+        !defined(HAVE_SELFTEST)
+        ssl->options.dhDoKeyTest = 1;
+    #endif
+#endif
+
+#ifdef WOLFSSL_DTLS
+    #ifdef WOLFSSL_SCTP
+        ssl->options.dtlsSctp           = ctx->dtlsSctp;
+    #endif
+    #if defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)
+        ssl->dtlsMtuSz                  = ctx->dtlsMtuSz;
+        ssl->dtls_expected_rx           = ssl->dtlsMtuSz;
+    #else
+        ssl->dtls_expected_rx = MAX_MTU;
+    #endif
+    ssl->dtls_timeout_init              = DTLS_TIMEOUT_INIT;
+    ssl->dtls_timeout_max               = DTLS_TIMEOUT_MAX;
+    ssl->dtls_timeout                   = ssl->dtls_timeout_init;
+    ssl->buffers.dtlsCtx.rfd            = -1;
+    ssl->buffers.dtlsCtx.wfd            = -1;
+#endif
+
+#ifndef WOLFSSL_AEAD_ONLY
+    #ifndef NO_OLD_TLS
+        ssl->hmac = SSL_hmac; /* default to SSLv3 */
+    #elif !defined(WOLFSSL_NO_TLS12)
+        ssl->hmac = TLS_hmac;
+    #endif
+#endif
+
+
+    ssl->cipher.ssl = ssl;
+
+#ifdef HAVE_EXTENDED_MASTER
+    ssl->options.haveEMS = ctx->haveEMS;
+#endif
+    ssl->options.useClientOrder = ctx->useClientOrder;
+    ssl->options.mutualAuth = ctx->mutualAuth;
+
+#ifdef WOLFSSL_TLS13
+    #ifdef HAVE_SESSION_TICKET
+        ssl->options.noTicketTls13 = ctx->noTicketTls13;
+    #endif
+    ssl->options.noPskDheKe = ctx->noPskDheKe;
+    #if defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+        ssl->options.postHandshakeAuth = ctx->postHandshakeAuth;
+    #endif
+
+    if (ctx->numGroups > 0) {
+        XMEMCPY(ssl->group, ctx->group, sizeof(*ctx->group) * ctx->numGroups);
+        ssl->numGroups = ctx->numGroups;
+    }
+#endif
+
+#ifdef HAVE_TLS_EXTENSIONS
+#ifdef HAVE_MAX_FRAGMENT
+    ssl->max_fragment = MAX_RECORD_SIZE;
+#endif
+#ifdef HAVE_ALPN
+    ssl->alpn_client_list = NULL;
+    #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+        ssl->alpnSelect    = ctx->alpnSelect;
+        ssl->alpnSelectArg = ctx->alpnSelectArg;
+    #endif
+#endif
+#ifdef HAVE_SUPPORTED_CURVES
+    ssl->options.userCurves = ctx->userCurves;
+#endif
+#endif /* HAVE_TLS_EXTENSIONS */
+
+#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+    ssl->options.disallowEncThenMac = ctx->disallowEncThenMac;
+#endif
+
+    /* default alert state (none) */
+    ssl->alert_history.last_rx.code  = -1;
+    ssl->alert_history.last_rx.level = -1;
+    ssl->alert_history.last_tx.code  = -1;
+    ssl->alert_history.last_tx.level = -1;
+
+#ifdef OPENSSL_EXTRA
+    /* copy over application session context ID */
+    ssl->sessionCtxSz = ctx->sessionCtxSz;
+    XMEMCPY(ssl->sessionCtx, ctx->sessionCtx, ctx->sessionCtxSz);
+    ssl->cbioFlag = ctx->cbioFlag;
+
+#endif
+
+    InitCiphers(ssl);
+    InitCipherSpecs(&ssl->specs);
+
+    /* all done with init, now can return errors, call other stuff */
+
+    if (!writeDup) {
+        /* arrays */
+        ssl->arrays = (Arrays*)XMALLOC(sizeof(Arrays), ssl->heap,
+                                                           DYNAMIC_TYPE_ARRAYS);
+        if (ssl->arrays == NULL) {
+            WOLFSSL_MSG("Arrays Memory error");
+            return MEMORY_E;
+        }
+        XMEMSET(ssl->arrays, 0, sizeof(Arrays));
+#if defined(WOLFSSL_TLS13) || defined(WOLFSSL_SNIFFER)
+        ssl->arrays->preMasterSz = ENCRYPT_LEN;
+        ssl->arrays->preMasterSecret = (byte*)XMALLOC(ENCRYPT_LEN, ssl->heap,
+            DYNAMIC_TYPE_SECRET);
+        if (ssl->arrays->preMasterSecret == NULL) {
+            return MEMORY_E;
+        }
+        XMEMSET(ssl->arrays->preMasterSecret, 0, ENCRYPT_LEN);
+#endif
+
+#ifdef OPENSSL_EXTRA
+    if ((ssl->param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC(
+                           sizeof(WOLFSSL_X509_VERIFY_PARAM),
+                           ssl->heap, DYNAMIC_TYPE_OPENSSL)) == NULL) {
+        WOLFSSL_MSG("ssl->param memory error");
+        return MEMORY_E;
+    }
+    XMEMSET(ssl->param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM));
+#endif
+
+#ifdef SINGLE_THREADED
+        if (ctx->suites == NULL)
+#endif
+        {
+            /* suites */
+            ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap,
+                                       DYNAMIC_TYPE_SUITES);
+            if (ssl->suites == NULL) {
+                WOLFSSL_MSG("Suites Memory error");
+                return MEMORY_E;
+            }
+        #ifdef OPENSSL_ALL
+            ssl->suites->stack = NULL;
+        #endif
+#ifdef SINGLE_THREADED
+            ssl->options.ownSuites = 1;
+#endif
+        }
+#ifdef SINGLE_THREADED
+        else {
+            ssl->options.ownSuites = 0;
+        }
+#endif
+    }
+
+    /* Initialize SSL with the appropriate fields from it's ctx */
+    /* requires valid arrays and suites unless writeDup ing */
+    if ((ret =  SetSSL_CTX(ssl, ctx, writeDup)) != WOLFSSL_SUCCESS)
+        return ret;
+
+    ssl->options.dtls = ssl->version.major == DTLS_MAJOR;
+
+#ifdef SINGLE_THREADED
+    ssl->rng = ctx->rng;   /* CTX may have one, if so use it */
+#endif
+
+    if (ssl->rng == NULL) {
+        /* RNG */
+        ssl->rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), ssl->heap,DYNAMIC_TYPE_RNG);
+        if (ssl->rng == NULL) {
+            WOLFSSL_MSG("RNG Memory error");
+            return MEMORY_E;
+        }
+        XMEMSET(ssl->rng, 0, sizeof(WC_RNG));
+        ssl->options.weOwnRng = 1;
+
+        /* FIPS RNG API does not accept a heap hint */
+#ifndef HAVE_FIPS
+        if ( (ret = wc_InitRng_ex(ssl->rng, ssl->heap, ssl->devId)) != 0) {
+            WOLFSSL_MSG("RNG Init error");
+            return ret;
+        }
+#else
+        if ( (ret = wc_InitRng(ssl->rng)) != 0) {
+            WOLFSSL_MSG("RNG Init error");
+            return ret;
+        }
+#endif
+    }
+
+#ifdef HAVE_WRITE_DUP
+    if (writeDup) {
+        /* all done */
+        return 0;
+    }
+#endif
+
+    /* hsHashes */
+    ret = InitHandshakeHashes(ssl);
+    if (ret != 0)
+        return ret;
+
+#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
+    if (ssl->options.dtls && ssl->options.side == WOLFSSL_SERVER_END) {
+        ret = wolfSSL_DTLS_SetCookieSecret(ssl, NULL, 0);
+        if (ret != 0) {
+            WOLFSSL_MSG("DTLS Cookie Secret error");
+            return ret;
+        }
+    }
+#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */
+
+#ifdef HAVE_SECRET_CALLBACK
+    ssl->sessionSecretCb  = NULL;
+    ssl->sessionSecretCtx = NULL;
+#ifdef WOLFSSL_TLS13
+    ssl->tls13SecretCb  = NULL;
+    ssl->tls13SecretCtx = NULL;
+#endif
+#endif
+
+#ifdef HAVE_SESSION_TICKET
+    ssl->session.ticket = ssl->session.staticTicket;
+#endif
+
+#ifdef WOLFSSL_MULTICAST
+    if (ctx->haveMcast) {
+        int i;
+
+        ssl->options.haveMcast = 1;
+        ssl->options.mcastID = ctx->mcastID;
+
+        /* Force the state to look like handshake has completed. */
+        /* Keying material is supplied externally. */
+        ssl->options.serverState = SERVER_FINISHED_COMPLETE;
+        ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
+        ssl->options.connectState = SECOND_REPLY_DONE;
+        ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE;
+        ssl->options.handShakeState = HANDSHAKE_DONE;
+        ssl->options.handShakeDone = 1;
+
+        for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++)
+            ssl->keys.peerSeq[i].peerId = INVALID_PEER_ID;
+    }
+#endif
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+    if (ssl->options.side == WOLFSSL_CLIENT_END) {
+        int useSecureReneg = ssl->ctx->useSecureReneg;
+        /* use secure renegotiation by default (not recommend) */
+    #ifdef WOLFSSL_SECURE_RENEGOTIATION_ON_BY_DEFAULT
+        useSecureReneg = 1;
+    #endif
+        if (useSecureReneg) {
+            ret = wolfSSL_UseSecureRenegotiation(ssl);
+            if (ret != WOLFSSL_SUCCESS)
+                return ret;
+            }
+    }
+#endif /* HAVE_SECURE_RENEGOTIATION */
+
+    return 0;
+}
+
+
+/* free use of temporary arrays */
+void FreeArrays(WOLFSSL* ssl, int keep)
+{
+    if (ssl->arrays) {
+        if (keep) {
+            /* keeps session id for user retrieval */
+            XMEMCPY(ssl->session.sessionID, ssl->arrays->sessionID, ID_LEN);
+            ssl->session.sessionIDSz = ssl->arrays->sessionIDSz;
+        }
+        if (ssl->arrays->preMasterSecret) {
+            XFREE(ssl->arrays->preMasterSecret, ssl->heap, DYNAMIC_TYPE_SECRET);
+            ssl->arrays->preMasterSecret = NULL;
+        }
+        XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS);
+        ssl->arrays->pendingMsg = NULL;
+        ForceZero(ssl->arrays, sizeof(Arrays)); /* clear arrays struct */
+    }
+    XFREE(ssl->arrays, ssl->heap, DYNAMIC_TYPE_ARRAYS);
+    ssl->arrays = NULL;
+}
+
+void FreeKey(WOLFSSL* ssl, int type, void** pKey)
+{
+    if (ssl && pKey && *pKey) {
+        switch (type) {
+        #ifndef NO_RSA
+            case DYNAMIC_TYPE_RSA:
+                wc_FreeRsaKey((RsaKey*)*pKey);
+                break;
+        #endif /* ! NO_RSA */
+        #ifdef HAVE_ECC
+            case DYNAMIC_TYPE_ECC:
+                wc_ecc_free((ecc_key*)*pKey);
+                break;
+        #endif /* HAVE_ECC */
+        #ifdef HAVE_ED25519
+            case DYNAMIC_TYPE_ED25519:
+                wc_ed25519_free((ed25519_key*)*pKey);
+                break;
+        #endif /* HAVE_ED25519 */
+        #ifdef HAVE_CURVE25519
+            case DYNAMIC_TYPE_CURVE25519:
+                wc_curve25519_free((curve25519_key*)*pKey);
+                break;
+        #endif /* HAVE_CURVE25519 */
+        #ifdef HAVE_ED448
+            case DYNAMIC_TYPE_ED448:
+                wc_ed448_free((ed448_key*)*pKey);
+                break;
+        #endif /* HAVE_ED448 */
+        #ifdef HAVE_CURVE448
+            case DYNAMIC_TYPE_CURVE448:
+                wc_curve448_free((curve448_key*)*pKey);
+                break;
+        #endif /* HAVE_CURVE448 */
+        #ifndef NO_DH
+            case DYNAMIC_TYPE_DH:
+                wc_FreeDhKey((DhKey*)*pKey);
+                break;
+        #endif /* !NO_DH */
+            default:
+                break;
+        }
+        XFREE(*pKey, ssl->heap, type);
+
+        /* Reset pointer */
+        *pKey = NULL;
+    }
+}
+
+int AllocKey(WOLFSSL* ssl, int type, void** pKey)
+{
+    int ret = BAD_FUNC_ARG;
+    int sz = 0;
+
+    if (ssl == NULL || pKey == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* Sanity check key destination */
+    if (*pKey != NULL) {
+        WOLFSSL_MSG("Key already present!");
+        return BAD_STATE_E;
+    }
+
+    /* Determine size */
+    switch (type) {
+    #ifndef NO_RSA
+        case DYNAMIC_TYPE_RSA:
+            sz = sizeof(RsaKey);
+            break;
+    #endif /* ! NO_RSA */
+    #ifdef HAVE_ECC
+        case DYNAMIC_TYPE_ECC:
+            sz = sizeof(ecc_key);
+            break;
+    #endif /* HAVE_ECC */
+    #ifdef HAVE_ED25519
+        case DYNAMIC_TYPE_ED25519:
+            sz = sizeof(ed25519_key);
+            break;
+    #endif /* HAVE_ED25519 */
+    #ifdef HAVE_CURVE25519
+        case DYNAMIC_TYPE_CURVE25519:
+            sz = sizeof(curve25519_key);
+            break;
+    #endif /* HAVE_CURVE25519 */
+    #ifdef HAVE_ED448
+        case DYNAMIC_TYPE_ED448:
+            sz = sizeof(ed448_key);
+            break;
+    #endif /* HAVE_ED448 */
+    #ifdef HAVE_CURVE448
+        case DYNAMIC_TYPE_CURVE448:
+            sz = sizeof(curve448_key);
+            break;
+    #endif /* HAVE_CURVE448 */
+    #ifndef NO_DH
+        case DYNAMIC_TYPE_DH:
+            sz = sizeof(DhKey);
+            break;
+    #endif /* !NO_DH */
+        default:
+            return BAD_FUNC_ARG;
+    }
+
+    if (sz == 0) {
+        return NOT_COMPILED_IN;
+    }
+
+    /* Allocate memory for key */
+    *pKey = XMALLOC(sz, ssl->heap, type);
+    if (*pKey == NULL) {
+        return MEMORY_E;
+    }
+
+    /* Initialize key */
+    switch (type) {
+    #ifndef NO_RSA
+        case DYNAMIC_TYPE_RSA:
+            ret = wc_InitRsaKey_ex((RsaKey*)*pKey, ssl->heap, ssl->devId);
+            break;
+    #endif /* ! NO_RSA */
+    #ifdef HAVE_ECC
+        case DYNAMIC_TYPE_ECC:
+            ret = wc_ecc_init_ex((ecc_key*)*pKey, ssl->heap, ssl->devId);
+            break;
+    #endif /* HAVE_ECC */
+    #ifdef HAVE_ED25519
+        case DYNAMIC_TYPE_ED25519:
+            wc_ed25519_init((ed25519_key*)*pKey);
+            ret = 0;
+            break;
+    #endif /* HAVE_CURVE25519 */
+    #ifdef HAVE_CURVE25519
+        case DYNAMIC_TYPE_CURVE25519:
+            wc_curve25519_init((curve25519_key*)*pKey);
+            ret = 0;
+            break;
+    #endif /* HAVE_CURVE25519 */
+    #ifdef HAVE_ED448
+        case DYNAMIC_TYPE_ED448:
+            wc_ed448_init((ed448_key*)*pKey);
+            ret = 0;
+            break;
+    #endif /* HAVE_CURVE448 */
+    #ifdef HAVE_CURVE448
+        case DYNAMIC_TYPE_CURVE448:
+            wc_curve448_init((curve448_key*)*pKey);
+            ret = 0;
+            break;
+    #endif /* HAVE_CURVE448 */
+    #ifndef NO_DH
+        case DYNAMIC_TYPE_DH:
+            ret = wc_InitDhKey_ex((DhKey*)*pKey, ssl->heap, ssl->devId);
+            break;
+    #endif /* !NO_DH */
+        default:
+            return BAD_FUNC_ARG;
+    }
+
+    /* On error free handshake key */
+    if (ret != 0) {
+        FreeKey(ssl, type, pKey);
+    }
+
+    return ret;
+}
+
+#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+    defined(HAVE_CURVE25519) || defined(HHAVE_ED448) || defined(HAVE_CURVE448)
+static int ReuseKey(WOLFSSL* ssl, int type, void* pKey)
+{
+    int ret = 0;
+
+    (void)ssl;
+
+    switch (type) {
+    #ifndef NO_RSA
+        case DYNAMIC_TYPE_RSA:
+            wc_FreeRsaKey((RsaKey*)pKey);
+            ret = wc_InitRsaKey_ex((RsaKey*)pKey, ssl->heap, ssl->devId);
+            break;
+    #endif /* ! NO_RSA */
+    #ifdef HAVE_ECC
+        case DYNAMIC_TYPE_ECC:
+            wc_ecc_free((ecc_key*)pKey);
+            ret = wc_ecc_init_ex((ecc_key*)pKey, ssl->heap, ssl->devId);
+            break;
+    #endif /* HAVE_ECC */
+    #ifdef HAVE_ED25519
+        case DYNAMIC_TYPE_ED25519:
+            wc_ed25519_free((ed25519_key*)pKey);
+            ret = wc_ed25519_init((ed25519_key*)pKey);
+            break;
+    #endif /* HAVE_CURVE25519 */
+    #ifdef HAVE_CURVE25519
+        case DYNAMIC_TYPE_CURVE25519:
+            wc_curve25519_free((curve25519_key*)pKey);
+            ret = wc_curve25519_init((curve25519_key*)pKey);
+            break;
+    #endif /* HAVE_CURVE25519 */
+    #ifdef HAVE_ED448
+        case DYNAMIC_TYPE_ED448:
+            wc_ed448_free((ed448_key*)pKey);
+            ret = wc_ed448_init((ed448_key*)pKey);
+            break;
+    #endif /* HAVE_CURVE448 */
+    #ifdef HAVE_CURVE448
+        case DYNAMIC_TYPE_CURVE448:
+            wc_curve448_free((curve448_key*)pKey);
+            ret = wc_curve448_init((curve448_key*)pKey);
+            break;
+    #endif /* HAVE_CURVE448 */
+    #ifndef NO_DH
+        case DYNAMIC_TYPE_DH:
+            wc_FreeDhKey((DhKey*)pKey);
+            ret = wc_InitDhKey_ex((DhKey*)pKey, ssl->heap, ssl->devId);
+            break;
+    #endif /* !NO_DH */
+        default:
+            return BAD_FUNC_ARG;
+    }
+
+    return ret;
+}
+#endif
+
+void FreeKeyExchange(WOLFSSL* ssl)
+{
+    /* Cleanup signature buffer */
+    if (ssl->buffers.sig.buffer) {
+        XFREE(ssl->buffers.sig.buffer, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+        ssl->buffers.sig.buffer = NULL;
+        ssl->buffers.sig.length = 0;
+    }
+
+    /* Cleanup digest buffer */
+    if (ssl->buffers.digest.buffer) {
+        XFREE(ssl->buffers.digest.buffer, ssl->heap, DYNAMIC_TYPE_DIGEST);
+        ssl->buffers.digest.buffer = NULL;
+        ssl->buffers.digest.length = 0;
+    }
+
+    /* Free handshake key */
+    FreeKey(ssl, ssl->hsType, &ssl->hsKey);
+
+#ifndef NO_DH
+    /* Free temp DH key */
+    FreeKey(ssl, DYNAMIC_TYPE_DH, (void**)&ssl->buffers.serverDH_Key);
+#endif
+
+    /* Cleanup async */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ssl->async.freeArgs) {
+        ssl->async.freeArgs(ssl, ssl->async.args);
+        ssl->async.freeArgs = NULL;
+    }
+#endif
+}
+
+
+/* Free up all memory used by Suites structure from WOLFSSL */
+void FreeSuites(WOLFSSL* ssl)
+{
+#ifdef SINGLE_THREADED
+    if (ssl->options.ownSuites)
+#endif
+    {
+    #ifdef OPENSSL_ALL
+        wolfSSL_sk_SSL_CIPHER_free(ssl->suites->stack);
+    #endif
+        XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES);
+    }
+    ssl->suites = NULL;
+}
+
+
+/* In case holding SSL object in array and don't want to free actual ssl */
+void SSL_ResourceFree(WOLFSSL* ssl)
+{
+    /* Note: any resources used during the handshake should be released in the
+     * function FreeHandshakeResources(). Be careful with the special cases
+     * like the RNG which may optionally be kept for the whole session. (For
+     * example with the RNG, it isn't used beyond the handshake except when
+     * using stream ciphers where it is retained. */
+
+    FreeCiphers(ssl);
+    FreeArrays(ssl, 0);
+    FreeKeyExchange(ssl);
+    if (ssl->options.weOwnRng) {
+        wc_FreeRng(ssl->rng);
+        XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG);
+    }
+    FreeSuites(ssl);
+    FreeHandshakeHashes(ssl);
+    XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
+
+    /* clear keys struct after session */
+    ForceZero(&ssl->keys, sizeof(Keys));
+
+#ifdef WOLFSSL_TLS13
+    if (ssl->options.tls1_3) {
+        ForceZero(&ssl->clientSecret, sizeof(ssl->clientSecret));
+        ForceZero(&ssl->serverSecret, sizeof(ssl->serverSecret));
+    }
+#endif
+
+#ifndef NO_DH
+    if (ssl->buffers.serverDH_Priv.buffer) {
+        ForceZero(ssl->buffers.serverDH_Priv.buffer,
+                                             ssl->buffers.serverDH_Priv.length);
+    }
+    XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
+    XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    /* parameters (p,g) may be owned by ctx */
+    if (ssl->buffers.weOwnDH) {
+        XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    }
+#endif /* !NO_DH */
+#ifndef NO_CERTS
+    ssl->keepCert = 0; /* make sure certificate is free'd */
+    wolfSSL_UnloadCertsKeys(ssl);
+#endif
+#ifndef NO_RSA
+    FreeKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey);
+    ssl->peerRsaKeyPresent = 0;
+#endif
+#ifdef WOLFSSL_RENESAS_TSIP_TLS
+    XFREE(ssl->peerTsipEncRsaKeyIndex, ssl->heap, DYNAMIC_TYPE_RSA);
+#endif
+    if (ssl->buffers.inputBuffer.dynamicFlag)
+        ShrinkInputBuffer(ssl, FORCED_FREE);
+    if (ssl->buffers.outputBuffer.dynamicFlag)
+        ShrinkOutputBuffer(ssl);
+#if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER)
+    XFREE(ssl->buffers.tls13CookieSecret.buffer, ssl->heap,
+          DYNAMIC_TYPE_COOKIE_PWD);
+#endif
+#ifdef WOLFSSL_DTLS
+    DtlsMsgPoolReset(ssl);
+    if (ssl->dtls_rx_msg_list != NULL) {
+        DtlsMsgListDelete(ssl->dtls_rx_msg_list, ssl->heap);
+        ssl->dtls_rx_msg_list = NULL;
+        ssl->dtls_rx_msg_list_sz = 0;
+    }
+    XFREE(ssl->buffers.dtlsCtx.peer.sa, ssl->heap, DYNAMIC_TYPE_SOCKADDR);
+    ssl->buffers.dtlsCtx.peer.sa = NULL;
+#ifndef NO_WOLFSSL_SERVER
+    XFREE(ssl->buffers.dtlsCookieSecret.buffer, ssl->heap,
+          DYNAMIC_TYPE_COOKIE_PWD);
+#endif
+#endif /* WOLFSSL_DTLS */
+#ifdef OPENSSL_EXTRA
+    if (ssl->biord != ssl->biowr)        /* only free write if different */
+        wolfSSL_BIO_free(ssl->biowr);
+    wolfSSL_BIO_free(ssl->biord);        /* always free read bio */
+    ssl->biowr = NULL;
+    ssl->biord = NULL;
+#endif
+#ifdef HAVE_LIBZ
+    FreeStreams(ssl);
+#endif
+#ifdef HAVE_ECC
+    FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccKey);
+    ssl->peerEccKeyPresent = 0;
+    FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccDsaKey);
+    ssl->peerEccDsaKeyPresent = 0;
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) ||defined(HAVE_CURVE448)
+    {
+        int dtype = 0;
+    #ifdef HAVE_ECC
+        dtype = DYNAMIC_TYPE_ECC;
+    #endif
+    #ifdef HAVE_CURVE25519
+        if (ssl->peerX25519KeyPresent
+    #ifdef HAVE_ECC
+                           || ssl->eccTempKeyPresent == DYNAMIC_TYPE_CURVE25519
+    #endif /* HAVE_ECC */
+           )
+        {
+            dtype = DYNAMIC_TYPE_CURVE25519;
+        }
+    #endif /* HAVE_CURVE25519 */
+    #ifdef HAVE_CURVE448
+        if (ssl->peerX448KeyPresent
+    #ifdef HAVE_ECC
+                             || ssl->eccTempKeyPresent == DYNAMIC_TYPE_CURVE448
+    #endif /* HAVE_ECC */
+           )
+        {
+            dtype = DYNAMIC_TYPE_CURVE448;
+        }
+    #endif /* HAVE_CURVE448 */
+        FreeKey(ssl, dtype, (void**)&ssl->eccTempKey);
+        ssl->eccTempKeyPresent = 0;
+    }
+#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+#ifdef HAVE_CURVE25519
+    FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, (void**)&ssl->peerX25519Key);
+    ssl->peerX25519KeyPresent = 0;
+#endif
+#ifdef HAVE_ED25519
+    FreeKey(ssl, DYNAMIC_TYPE_ED25519, (void**)&ssl->peerEd25519Key);
+    ssl->peerEd25519KeyPresent = 0;
+    #ifdef HAVE_PK_CALLBACKS
+        if (ssl->buffers.peerEd25519Key.buffer != NULL) {
+            XFREE(ssl->buffers.peerEd25519Key.buffer, ssl->heap,
+                                                          DYNAMIC_TYPE_ED25519);
+            ssl->buffers.peerEd25519Key.buffer = NULL;
+        }
+    #endif
+#endif
+#ifdef HAVE_CURVE448
+    FreeKey(ssl, DYNAMIC_TYPE_CURVE448, (void**)&ssl->peerX448Key);
+    ssl->peerX448KeyPresent = 0;
+#endif
+#ifdef HAVE_ED448
+    FreeKey(ssl, DYNAMIC_TYPE_ED448, (void**)&ssl->peerEd448Key);
+    ssl->peerEd448KeyPresent = 0;
+    #ifdef HAVE_PK_CALLBACKS
+        if (ssl->buffers.peerEd448Key.buffer != NULL) {
+            XFREE(ssl->buffers.peerEd448Key.buffer, ssl->heap,
+                                                            DYNAMIC_TYPE_ED448);
+            ssl->buffers.peerEd448Key.buffer = NULL;
+        }
+    #endif
+#endif
+#ifdef HAVE_PK_CALLBACKS
+    #ifdef HAVE_ECC
+        XFREE(ssl->buffers.peerEccDsaKey.buffer, ssl->heap, DYNAMIC_TYPE_ECC);
+    #endif /* HAVE_ECC */
+    #ifndef NO_RSA
+        XFREE(ssl->buffers.peerRsaKey.buffer, ssl->heap, DYNAMIC_TYPE_RSA);
+    #endif /* NO_RSA */
+#endif /* HAVE_PK_CALLBACKS */
+#ifdef HAVE_TLS_EXTENSIONS
+    TLSX_FreeAll(ssl->extensions, ssl->heap);
+
+#ifdef HAVE_ALPN
+    if (ssl->alpn_client_list != NULL) {
+        XFREE(ssl->alpn_client_list, ssl->heap, DYNAMIC_TYPE_ALPN);
+        ssl->alpn_client_list = NULL;
+    }
+#endif
+#endif /* HAVE_TLS_EXTENSIONS */
+#if defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP)
+    if (ssl->mnCtx) {
+        mynewt_ctx_clear(ssl->mnCtx);
+        ssl->mnCtx = NULL;
+    }
+#endif
+#ifdef HAVE_NETX
+    if (ssl->nxCtx.nxPacket)
+        nx_packet_release(ssl->nxCtx.nxPacket);
+#endif
+#ifdef KEEP_PEER_CERT
+    FreeX509(&ssl->peerCert);
+#endif
+
+#ifdef HAVE_SESSION_TICKET
+    if (ssl->session.isDynamic) {
+        XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+        ssl->session.ticket = ssl->session.staticTicket;
+        ssl->session.isDynamic = 0;
+        ssl->session.ticketLen = 0;
+    }
+#endif
+#ifdef HAVE_EXT_CACHE
+    wolfSSL_SESSION_free(ssl->extSession);
+#endif
+#ifdef HAVE_WRITE_DUP
+    if (ssl->dupWrite) {
+        FreeWriteDup(ssl);
+    }
+#endif
+#ifdef OPENSSL_EXTRA
+    if (ssl->param) {
+        XFREE(ssl->param, ssl->heap, DYNAMIC_TYPE_OPENSSL);
+    }
+#endif
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+    while (ssl->certReqCtx != NULL) {
+        CertReqCtx* curr = ssl->certReqCtx;
+        ssl->certReqCtx = curr->next;
+        XFREE(curr, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+#endif
+
+#ifdef WOLFSSL_STATIC_MEMORY
+    /* check if using fixed io buffers and free them */
+    if (ssl->heap != NULL) {
+    #ifdef WOLFSSL_HEAP_TEST
+    /* avoid dereferencing a test value */
+    if (ssl->heap != (void*)WOLFSSL_HEAP_TEST) {
+    #endif
+        WOLFSSL_HEAP_HINT* ssl_hint = (WOLFSSL_HEAP_HINT*)ssl->heap;
+        WOLFSSL_HEAP*      ctx_heap;
+        void* heap = ssl->ctx ? ssl->ctx->heap : ssl->heap;
+
+        ctx_heap = ssl_hint->memory;
+        if (wc_LockMutex(&(ctx_heap->memory_mutex)) != 0) {
+            WOLFSSL_MSG("Bad memory_mutex lock");
+        }
+        ctx_heap->curIO--;
+        if (FreeFixedIO(ctx_heap, &(ssl_hint->outBuf)) != 1) {
+            WOLFSSL_MSG("Error freeing fixed output buffer");
+        }
+        if (FreeFixedIO(ctx_heap, &(ssl_hint->inBuf)) != 1) {
+            WOLFSSL_MSG("Error freeing fixed output buffer");
+        }
+        if (ssl_hint->haFlag) { /* check if handshake count has been decreased*/
+            ctx_heap->curHa--;
+        }
+        wc_UnLockMutex(&(ctx_heap->memory_mutex));
+
+        /* check if tracking stats */
+        if (ctx_heap->flag & WOLFMEM_TRACK_STATS) {
+            XFREE(ssl_hint->stats, heap, DYNAMIC_TYPE_SSL);
+        }
+        XFREE(ssl->heap, heap, DYNAMIC_TYPE_SSL);
+    #ifdef WOLFSSL_HEAP_TEST
+    }
+    #endif
+    }
+#endif /* WOLFSSL_STATIC_MEMORY */
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+    wolfSSL_sk_CIPHER_free(ssl->supportedCiphers);
+    wolfSSL_sk_X509_free(ssl->peerCertChain);
+#endif
+}
+
+/* Free any handshake resources no longer needed */
+void FreeHandshakeResources(WOLFSSL* ssl)
+{
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+    if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled) {
+        WOLFSSL_MSG("Secure Renegotiation needs to retain handshake resources");
+        return;
+    }
+#endif
+
+    /* input buffer */
+    if (ssl->buffers.inputBuffer.dynamicFlag)
+        ShrinkInputBuffer(ssl, NO_FORCED_FREE);
+
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+    if (!ssl->options.tls1_3)
+#endif
+    {
+    #ifndef OPENSSL_ALL
+        /* free suites unless using compatibility layer */
+        FreeSuites(ssl);
+    #endif
+        /* hsHashes */
+        FreeHandshakeHashes(ssl);
+    }
+
+    /* RNG */
+    if (ssl->options.tls1_1 == 0
+#ifndef WOLFSSL_AEAD_ONLY
+        || ssl->specs.cipher_type == stream
+#endif
+#if defined(WOLFSSL_TLS13)
+    #if !defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+        || ssl->options.tls1_3
+    #elif !defined(HAVE_SESSION_TICKET)
+        || (ssl->options.tls1_3 && ssl->options.side == WOLFSSL_SERVER_END)
+    #endif
+#endif
+    ) {
+        if (ssl->options.weOwnRng) {
+            wc_FreeRng(ssl->rng);
+            XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG);
+            ssl->rng = NULL;
+            ssl->options.weOwnRng = 0;
+        }
+    }
+
+#ifdef WOLFSSL_DTLS
+    /* DTLS_POOL */
+    if (ssl->options.dtls) {
+        DtlsMsgPoolReset(ssl);
+        DtlsMsgListDelete(ssl->dtls_rx_msg_list, ssl->heap);
+        ssl->dtls_rx_msg_list = NULL;
+        ssl->dtls_rx_msg_list_sz = 0;
+    }
+#endif
+
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) && \
+                                                    defined(HAVE_SESSION_TICKET)
+    if (!ssl->options.tls1_3)
+#endif
+        /* arrays */
+        if (ssl->options.saveArrays == 0)
+            FreeArrays(ssl, 1);
+
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+    if (!ssl->options.tls1_3 || ssl->options.side == WOLFSSL_CLIENT_END)
+#endif
+    {
+#ifndef NO_RSA
+        /* peerRsaKey */
+        FreeKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey);
+        ssl->peerRsaKeyPresent = 0;
+#endif
+#ifdef HAVE_ECC
+        FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccDsaKey);
+        ssl->peerEccDsaKeyPresent = 0;
+#endif /* HAVE_ECC */
+#ifdef HAVE_ED25519
+        FreeKey(ssl, DYNAMIC_TYPE_ED25519, (void**)&ssl->peerEd25519Key);
+        ssl->peerEd25519KeyPresent = 0;
+#endif /* HAVE_ED25519 */
+#ifdef HAVE_ED448
+        FreeKey(ssl, DYNAMIC_TYPE_ED448, (void**)&ssl->peerEd448Key);
+        ssl->peerEd448KeyPresent = 0;
+#endif /* HAVE_ED448 */
+    }
+
+#ifdef HAVE_ECC
+    FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccKey);
+    ssl->peerEccKeyPresent = 0;
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
+    {
+        int dtype;
+    #ifdef HAVE_ECC
+        dtype = DYNAMIC_TYPE_ECC;
+    #endif
+    #ifdef HAVE_CURVE25519
+    #ifdef HAVE_ECC
+        if (ssl->peerX25519KeyPresent ||
+                              ssl->eccTempKeyPresent == DYNAMIC_TYPE_CURVE25519)
+    #endif /* HAVE_ECC */
+         {
+            dtype = DYNAMIC_TYPE_CURVE25519;
+         }
+    #endif /* HAVE_CURVE25519 */
+    #ifdef HAVE_CURVE448
+    #ifdef HAVE_ECC
+        if (ssl->peerX448KeyPresent ||
+                                ssl->eccTempKeyPresent == DYNAMIC_TYPE_CURVE448)
+    #endif /* HAVE_ECC */
+         {
+            dtype = DYNAMIC_TYPE_CURVE448;
+         }
+    #endif /* HAVE_CURVE448 */
+        FreeKey(ssl, dtype, (void**)&ssl->eccTempKey);
+        ssl->eccTempKeyPresent = 0;
+    }
+#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+#ifdef HAVE_CURVE25519
+    FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, (void**)&ssl->peerX25519Key);
+    ssl->peerX25519KeyPresent = 0;
+#endif
+#ifdef HAVE_CURVE448
+    FreeKey(ssl, DYNAMIC_TYPE_CURVE448, (void**)&ssl->peerX448Key);
+    ssl->peerX448KeyPresent = 0;
+#endif
+
+#ifndef NO_DH
+    if (ssl->buffers.serverDH_Priv.buffer) {
+        ForceZero(ssl->buffers.serverDH_Priv.buffer,
+                                             ssl->buffers.serverDH_Priv.length);
+    }
+    XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
+    ssl->buffers.serverDH_Priv.buffer = NULL;
+    XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    ssl->buffers.serverDH_Pub.buffer = NULL;
+    /* parameters (p,g) may be owned by ctx */
+    if (ssl->buffers.weOwnDH) {
+        XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        ssl->buffers.serverDH_G.buffer = NULL;
+        XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        ssl->buffers.serverDH_P.buffer = NULL;
+    }
+#endif /* !NO_DH */
+
+#ifndef NO_CERTS
+    wolfSSL_UnloadCertsKeys(ssl);
+#endif
+#ifdef HAVE_PK_CALLBACKS
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+    if (!ssl->options.tls1_3 || ssl->options.side == WOLFSSL_CLIENT_END)
+#endif
+    {
+    #ifdef HAVE_ECC
+        XFREE(ssl->buffers.peerEccDsaKey.buffer, ssl->heap, DYNAMIC_TYPE_ECC);
+        ssl->buffers.peerEccDsaKey.buffer = NULL;
+    #endif /* HAVE_ECC */
+    #ifndef NO_RSA
+        XFREE(ssl->buffers.peerRsaKey.buffer, ssl->heap, DYNAMIC_TYPE_RSA);
+        ssl->buffers.peerRsaKey.buffer = NULL;
+    #endif /* NO_RSA */
+    #ifdef HAVE_ED25519
+        XFREE(ssl->buffers.peerEd25519Key.buffer, ssl->heap,
+                                                          DYNAMIC_TYPE_ED25519);
+        ssl->buffers.peerEd25519Key.buffer = NULL;
+    #endif
+    #ifdef HAVE_ED448
+        XFREE(ssl->buffers.peerEd448Key.buffer, ssl->heap, DYNAMIC_TYPE_ED448);
+        ssl->buffers.peerEd448Key.buffer = NULL;
+    #endif
+    }
+#endif /* HAVE_PK_CALLBACKS */
+
+#ifdef HAVE_QSH
+    QSH_FreeAll(ssl);
+#endif
+
+#ifdef HAVE_SESSION_TICKET
+    if (ssl->session.isDynamic) {
+        XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+        ssl->session.ticket = ssl->session.staticTicket;
+        ssl->session.isDynamic = 0;
+        ssl->session.ticketLen = 0;
+    }
+#endif
+
+#if defined(HAVE_TLS_EXTENSIONS) && !defined(HAVE_SNI) && \
+                    !defined(HAVE_ALPN) && !defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+    /* Some extensions need to be kept for post-handshake querying. */
+    TLSX_FreeAll(ssl->extensions, ssl->heap);
+    ssl->extensions = NULL;
+#endif
+
+#ifdef WOLFSSL_STATIC_MEMORY
+    /* when done with handshake decrement current handshake count */
+    if (ssl->heap != NULL) {
+    #ifdef WOLFSSL_HEAP_TEST
+    /* avoid dereferencing a test value */
+    if (ssl->heap != (void*)WOLFSSL_HEAP_TEST) {
+    #endif
+        WOLFSSL_HEAP_HINT* ssl_hint = (WOLFSSL_HEAP_HINT*)ssl->heap;
+        WOLFSSL_HEAP*      ctx_heap;
+
+        ctx_heap = ssl_hint->memory;
+        if (wc_LockMutex(&(ctx_heap->memory_mutex)) != 0) {
+            WOLFSSL_MSG("Bad memory_mutex lock");
+        }
+        ctx_heap->curHa--;
+        ssl_hint->haFlag = 0; /* set to zero since handshake has been dec */
+        wc_UnLockMutex(&(ctx_heap->memory_mutex));
+    #ifdef WOLFSSL_HEAP_TEST
+    }
+    #endif
+    }
+#endif /* WOLFSSL_STATIC_MEMORY */
+}
+
+
+/* heap argument is the heap hint used when creating SSL */
+void FreeSSL(WOLFSSL* ssl, void* heap)
+{
+    if (ssl->ctx) {
+        FreeSSL_Ctx(ssl->ctx); /* will decrement and free underlying CTX if 0 */
+    }
+    SSL_ResourceFree(ssl);
+    XFREE(ssl, heap, DYNAMIC_TYPE_SSL);
+    (void)heap;
+}
+
+#if !defined(NO_OLD_TLS) || defined(WOLFSSL_DTLS) || \
+    ((defined(HAVE_CHACHA) || defined(HAVE_AESCCM) || defined(HAVE_AESGCM)) \
+     && defined(HAVE_AEAD))
+
+#if defined(WOLFSSL_DTLS) || !defined(WOLFSSL_NO_TLS12)
+static WC_INLINE void GetSEQIncrement(WOLFSSL* ssl, int verify, word32 seq[2])
+{
+    if (verify) {
+        seq[0] = ssl->keys.peer_sequence_number_hi;
+        seq[1] = ssl->keys.peer_sequence_number_lo++;
+        if (seq[1] > ssl->keys.peer_sequence_number_lo) {
+            /* handle rollover */
+            ssl->keys.peer_sequence_number_hi++;
+        }
+    }
+    else {
+        seq[0] = ssl->keys.sequence_number_hi;
+        seq[1] = ssl->keys.sequence_number_lo++;
+        if (seq[1] > ssl->keys.sequence_number_lo) {
+            /* handle rollover */
+            ssl->keys.sequence_number_hi++;
+        }
+    }
+}
+#endif /* WOLFSSL_DTLS || !WOLFSSL_NO_TLS12 */
+
+
+#ifdef WOLFSSL_DTLS
+static WC_INLINE void DtlsGetSEQ(WOLFSSL* ssl, int order, word32 seq[2])
+{
+    if (order == PREV_ORDER) {
+        /* Previous epoch case */
+        if (ssl->options.haveMcast) {
+        #ifdef WOLFSSL_MULTICAST
+            seq[0] = (((word32)ssl->keys.dtls_epoch - 1) << 16) |
+                     (ssl->options.mcastID << 8) |
+                     (ssl->keys.dtls_prev_sequence_number_hi & 0xFF);
+        #endif
+        }
+        else
+            seq[0] = (((word32)ssl->keys.dtls_epoch - 1) << 16) |
+                     (ssl->keys.dtls_prev_sequence_number_hi & 0xFFFF);
+        seq[1] = ssl->keys.dtls_prev_sequence_number_lo;
+    }
+    else if (order == PEER_ORDER) {
+        if (ssl->options.haveMcast) {
+        #ifdef WOLFSSL_MULTICAST
+            seq[0] = ((word32)ssl->keys.curEpoch << 16) |
+                     (ssl->keys.curPeerId << 8) |
+                     (ssl->keys.curSeq_hi & 0xFF);
+        #endif
+        }
+        else
+            seq[0] = ((word32)ssl->keys.curEpoch << 16) |
+                     (ssl->keys.curSeq_hi & 0xFFFF);
+        seq[1] = ssl->keys.curSeq_lo; /* explicit from peer */
+    }
+    else {
+        if (ssl->options.haveMcast) {
+        #ifdef WOLFSSL_MULTICAST
+            seq[0] = ((word32)ssl->keys.dtls_epoch << 16) |
+                     (ssl->options.mcastID << 8) |
+                     (ssl->keys.dtls_sequence_number_hi & 0xFF);
+        #endif
+        }
+        else
+            seq[0] = ((word32)ssl->keys.dtls_epoch << 16) |
+                     (ssl->keys.dtls_sequence_number_hi & 0xFFFF);
+        seq[1] = ssl->keys.dtls_sequence_number_lo;
+    }
+}
+
+static WC_INLINE void DtlsSEQIncrement(WOLFSSL* ssl, int order)
+{
+    word32 seq;
+
+    if (order == PREV_ORDER) {
+        seq = ssl->keys.dtls_prev_sequence_number_lo++;
+        if (seq > ssl->keys.dtls_prev_sequence_number_lo) {
+            /* handle rollover */
+            ssl->keys.dtls_prev_sequence_number_hi++;
+        }
+    }
+    else if (order == PEER_ORDER) {
+        seq = ssl->keys.peer_sequence_number_lo++;
+        if (seq > ssl->keys.peer_sequence_number_lo) {
+            /* handle rollover */
+            ssl->keys.peer_sequence_number_hi++;
+        }
+    }
+    else {
+        seq = ssl->keys.dtls_sequence_number_lo++;
+        if (seq > ssl->keys.dtls_sequence_number_lo) {
+            /* handle rollover */
+            ssl->keys.dtls_sequence_number_hi++;
+        }
+    }
+}
+#endif /* WOLFSSL_DTLS */
+
+#if defined(WOLFSSL_DTLS) || !defined(WOLFSSL_NO_TLS12)
+static WC_INLINE void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out)
+{
+    word32 seq[2] = {0, 0};
+
+    if (!ssl->options.dtls) {
+        GetSEQIncrement(ssl, verifyOrder, seq);
+    }
+    else {
+#ifdef WOLFSSL_DTLS
+        DtlsGetSEQ(ssl, verifyOrder, seq);
+#endif
+    }
+
+    c32toa(seq[0], out);
+    c32toa(seq[1], out + OPAQUE32_LEN);
+}
+#endif /* WOLFSSL_DTLS || !WOLFSSL_NO_TLS12 */
+#endif /* !NO_OLD_TLS || WOLFSSL_DTLS ||
+        *     ((HAVE_CHACHA || HAVE_AESCCM || HAVE_AESGCM) && HAVE_AEAD) */
+
+#ifdef WOLFSSL_DTLS
+
+/* functions for managing DTLS datagram reordering */
+
+/* Need to allocate space for the handshake message header. The hashing
+ * routines assume the message pointer is still within the buffer that
+ * has the headers, and will include those headers in the hash. The store
+ * routines need to take that into account as well. New will allocate
+ * extra space for the headers. */
+DtlsMsg* DtlsMsgNew(word32 sz, void* heap)
+{
+    DtlsMsg* msg;
+
+    (void)heap;
+    msg = (DtlsMsg*)XMALLOC(sizeof(DtlsMsg), heap, DYNAMIC_TYPE_DTLS_MSG);
+
+    if (msg != NULL) {
+        XMEMSET(msg, 0, sizeof(DtlsMsg));
+        msg->buf = (byte*)XMALLOC(sz + DTLS_HANDSHAKE_HEADER_SZ,
+                                                heap, DYNAMIC_TYPE_DTLS_BUFFER);
+        if (msg->buf != NULL) {
+            msg->sz = sz;
+            msg->type = no_shake;
+            msg->msg = msg->buf + DTLS_HANDSHAKE_HEADER_SZ;
+        }
+        else {
+            XFREE(msg, heap, DYNAMIC_TYPE_DTLS_MSG);
+            msg = NULL;
+        }
+    }
+
+    return msg;
+}
+
+void DtlsMsgDelete(DtlsMsg* item, void* heap)
+{
+    (void)heap;
+
+    if (item != NULL) {
+        DtlsFrag* cur = item->fragList;
+        while (cur != NULL) {
+            DtlsFrag* next = cur->next;
+            XFREE(cur, heap, DYNAMIC_TYPE_DTLS_FRAG);
+            cur = next;
+        }
+        if (item->buf != NULL)
+            XFREE(item->buf, heap, DYNAMIC_TYPE_DTLS_BUFFER);
+        XFREE(item, heap, DYNAMIC_TYPE_DTLS_MSG);
+    }
+}
+
+
+void DtlsMsgListDelete(DtlsMsg* head, void* heap)
+{
+    DtlsMsg* next;
+    while (head) {
+        next = head->next;
+        DtlsMsgDelete(head, heap);
+        head = next;
+    }
+}
+
+
+/* Create a DTLS Fragment from *begin - end, adjust new *begin and bytesLeft */
+static DtlsFrag* CreateFragment(word32* begin, word32 end, const byte* data,
+                                byte* buf, word32* bytesLeft, void* heap)
+{
+    DtlsFrag* newFrag;
+    word32 added = end - *begin + 1;
+
+    (void)heap;
+    newFrag = (DtlsFrag*)XMALLOC(sizeof(DtlsFrag), heap,
+                                 DYNAMIC_TYPE_DTLS_FRAG);
+    if (newFrag != NULL) {
+        newFrag->next = NULL;
+        newFrag->begin = *begin;
+        newFrag->end = end;
+
+        XMEMCPY(buf + *begin, data, added);
+        *bytesLeft -= added;
+        *begin = newFrag->end + 1;
+    }
+
+    return newFrag;
+}
+
+
+int DtlsMsgSet(DtlsMsg* msg, word32 seq, const byte* data, byte type,
+                                   word32 fragOffset, word32 fragSz, void* heap)
+{
+    if (msg != NULL && data != NULL && msg->fragSz <= msg->sz &&
+                                             (fragOffset + fragSz) <= msg->sz) {
+        DtlsFrag* cur = msg->fragList;
+        DtlsFrag* prev = cur;
+        DtlsFrag* newFrag;
+        word32 bytesLeft = fragSz; /* could be overlapping fragment */
+        word32 startOffset = fragOffset;
+        word32 added;
+
+        msg->seq = seq;
+        msg->type = type;
+
+        if (fragOffset == 0) {
+            XMEMCPY(msg->buf, data - DTLS_HANDSHAKE_HEADER_SZ,
+                    DTLS_HANDSHAKE_HEADER_SZ);
+            c32to24(msg->sz, msg->msg - DTLS_HANDSHAKE_FRAG_SZ);
+        }
+
+        /* if no message data, just return */
+        if (fragSz == 0)
+            return 0;
+
+        /* if list is empty add full fragment to front */
+        if (cur == NULL) {
+            newFrag = CreateFragment(&fragOffset, fragOffset + fragSz - 1, data,
+                                     msg->msg, &bytesLeft, heap);
+            if (newFrag == NULL)
+                return MEMORY_E;
+
+            msg->fragSz = fragSz;
+            msg->fragList = newFrag;
+
+            return 0;
+        }
+
+        /* add to front if before current front, up to next->begin */
+        if (fragOffset < cur->begin) {
+            word32 end = fragOffset + fragSz - 1;
+
+            if (end >= cur->begin)
+                end = cur->begin - 1;
+
+            added = end - fragOffset + 1;
+            newFrag = CreateFragment(&fragOffset, end, data, msg->msg,
+                                     &bytesLeft, heap);
+            if (newFrag == NULL)
+                return MEMORY_E;
+
+            msg->fragSz += added;
+
+            newFrag->next = cur;
+            msg->fragList = newFrag;
+        }
+
+        /* while we have bytes left, try to find a gap to fill */
+        while (bytesLeft > 0) {
+            /* get previous packet in list */
+            while (cur && (fragOffset >= cur->begin)) {
+                prev = cur;
+                cur = cur->next;
+            }
+
+            /* don't add duplicate data */
+            if (prev->end >= fragOffset) {
+                if ( (fragOffset + bytesLeft - 1) <= prev->end)
+                    return 0;
+                fragOffset = prev->end + 1;
+                bytesLeft = startOffset + fragSz - fragOffset;
+            }
+
+            if (cur == NULL)
+                /* we're at the end */
+                added = bytesLeft;
+            else
+                /* we're in between two frames */
+                added = min(bytesLeft, cur->begin - fragOffset);
+
+            /* data already there */
+            if (added == 0)
+                continue;
+
+            newFrag = CreateFragment(&fragOffset, fragOffset + added - 1,
+                                     data + fragOffset - startOffset,
+                                     msg->msg, &bytesLeft, heap);
+            if (newFrag == NULL)
+                return MEMORY_E;
+
+            msg->fragSz += added;
+
+            newFrag->next = prev->next;
+            prev->next = newFrag;
+        }
+    }
+
+    return 0;
+}
+
+
+DtlsMsg* DtlsMsgFind(DtlsMsg* head, word32 seq)
+{
+    while (head != NULL && head->seq != seq) {
+        head = head->next;
+    }
+    return head;
+}
+
+
+void DtlsMsgStore(WOLFSSL* ssl, word32 seq, const byte* data,
+        word32 dataSz, byte type, word32 fragOffset, word32 fragSz, void* heap)
+{
+    /* See if seq exists in the list. If it isn't in the list, make
+     * a new item of size dataSz, copy fragSz bytes from data to msg->msg
+     * starting at offset fragOffset, and add fragSz to msg->fragSz. If
+     * the seq is in the list and it isn't full, copy fragSz bytes from
+     * data to msg->msg starting at offset fragOffset, and add fragSz to
+     * msg->fragSz. Insertions take into account data already in the list
+     * in case there are overlaps in the handshake message due to retransmit
+     * messages. The new item should be inserted into the list in its
+     * proper position.
+     *
+     * 1. Find seq in list, or where seq should go in list. If seq not in
+     *    list, create new item and insert into list. Either case, keep
+     *    pointer to item.
+     * 2. Copy the data from the message to the stored message where it
+     *    belongs without overlaps.
+     */
+
+    DtlsMsg* head = ssl->dtls_rx_msg_list;
+
+    if (head != NULL) {
+        DtlsMsg* cur = DtlsMsgFind(head, seq);
+        if (cur == NULL) {
+            cur = DtlsMsgNew(dataSz, heap);
+            if (cur != NULL) {
+                if (DtlsMsgSet(cur, seq, data, type,
+                                                fragOffset, fragSz, heap) < 0) {
+                    DtlsMsgDelete(cur, heap);
+                }
+                else {
+                    ssl->dtls_rx_msg_list_sz++;
+                    head = DtlsMsgInsert(head, cur);
+                }
+            }
+        }
+        else {
+            /* If this fails, the data is just dropped. */
+            DtlsMsgSet(cur, seq, data, type, fragOffset, fragSz, heap);
+        }
+    }
+    else {
+        head = DtlsMsgNew(dataSz, heap);
+        if (DtlsMsgSet(head, seq, data, type, fragOffset, fragSz, heap) < 0) {
+            DtlsMsgDelete(head, heap);
+            head = NULL;
+        }
+        else {
+            ssl->dtls_rx_msg_list_sz++;
+        }
+    }
+
+    ssl->dtls_rx_msg_list = head;
+}
+
+
+/* DtlsMsgInsert() is an in-order insert. */
+DtlsMsg* DtlsMsgInsert(DtlsMsg* head, DtlsMsg* item)
+{
+    if (head == NULL || item->seq < head->seq) {
+        item->next = head;
+        head = item;
+    }
+    else if (head->next == NULL) {
+        head->next = item;
+    }
+    else {
+        DtlsMsg* cur = head->next;
+        DtlsMsg* prev = head;
+        while (cur) {
+            if (item->seq < cur->seq) {
+                item->next = cur;
+                prev->next = item;
+                break;
+            }
+            prev = cur;
+            cur = cur->next;
+        }
+        if (cur == NULL) {
+            prev->next = item;
+        }
+    }
+
+    return head;
+}
+
+
+/* DtlsMsgPoolSave() adds the message to the end of the stored transmit list. */
+int DtlsMsgPoolSave(WOLFSSL* ssl, const byte* data, word32 dataSz)
+{
+    DtlsMsg* item;
+    int ret = 0;
+
+    WOLFSSL_ENTER("DtlsMsgPoolSave()");
+
+    if (ssl->dtls_tx_msg_list_sz > DTLS_POOL_SZ) {
+        WOLFSSL_ERROR(DTLS_POOL_SZ_E);
+        return DTLS_POOL_SZ_E;
+    }
+
+    item = DtlsMsgNew(dataSz, ssl->heap);
+
+    if (item != NULL) {
+        DtlsMsg* cur = ssl->dtls_tx_msg_list;
+
+        XMEMCPY(item->buf, data, dataSz);
+        item->sz = dataSz;
+        item->seq = ssl->keys.dtls_epoch;
+
+        if (cur == NULL)
+            ssl->dtls_tx_msg_list = item;
+        else {
+            while (cur->next)
+                cur = cur->next;
+            cur->next = item;
+        }
+        ssl->dtls_tx_msg_list_sz++;
+    }
+    else
+        ret = MEMORY_E;
+
+    WOLFSSL_LEAVE("DtlsMsgPoolSave()", ret);
+    return ret;
+}
+
+
+/* DtlsMsgPoolTimeout() updates the timeout time. */
+int DtlsMsgPoolTimeout(WOLFSSL* ssl)
+{
+    int result = -1;
+    if (ssl->dtls_timeout <  ssl->dtls_timeout_max) {
+        ssl->dtls_timeout *= DTLS_TIMEOUT_MULTIPLIER;
+        result = 0;
+    }
+    WOLFSSL_LEAVE("DtlsMsgPoolTimeout()", result);
+    return result;
+}
+
+
+/* DtlsMsgPoolReset() deletes the stored transmit list and resets the timeout
+ * value. */
+void DtlsMsgPoolReset(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("DtlsMsgPoolReset()");
+    if (ssl->dtls_tx_msg_list) {
+        DtlsMsgListDelete(ssl->dtls_tx_msg_list, ssl->heap);
+        ssl->dtls_tx_msg_list = NULL;
+        ssl->dtls_tx_msg = NULL;
+        ssl->dtls_tx_msg_list_sz = 0;
+        ssl->dtls_timeout = ssl->dtls_timeout_init;
+    }
+}
+
+
+int VerifyForDtlsMsgPoolSend(WOLFSSL* ssl, byte type, word32 fragOffset)
+{
+    /**
+     * only the first message from previous flight should be valid
+     * to be used for triggering retransmission of whole DtlsMsgPool.
+     * change cipher suite type is not verified here
+     */
+    return ((fragOffset == 0) &&
+           (((ssl->options.side == WOLFSSL_SERVER_END) &&
+             ((type == client_hello) ||
+             ((ssl->options.verifyPeer) && (type == certificate)) ||
+             ((!ssl->options.verifyPeer) && (type == client_key_exchange)))) ||
+            ((ssl->options.side == WOLFSSL_CLIENT_END) &&
+             (type == server_hello))));
+}
+
+
+/* DtlsMsgPoolSend() will send the stored transmit list. The stored list is
+ * updated with new sequence numbers, and will be re-encrypted if needed. */
+int DtlsMsgPoolSend(WOLFSSL* ssl, int sendOnlyFirstPacket)
+{
+    int ret = 0;
+    DtlsMsg* pool;
+
+    WOLFSSL_ENTER("DtlsMsgPoolSend()");
+
+    pool = ssl->dtls_tx_msg == NULL ? ssl->dtls_tx_msg_list : ssl->dtls_tx_msg;
+
+    if (pool != NULL) {
+        if ((ssl->options.side == WOLFSSL_SERVER_END &&
+             !(ssl->options.acceptState == SERVER_HELLO_DONE ||
+               ssl->options.acceptState == ACCEPT_FINISHED_DONE ||
+               ssl->options.acceptState == ACCEPT_THIRD_REPLY_DONE)) ||
+            (ssl->options.side == WOLFSSL_CLIENT_END &&
+             !(ssl->options.connectState == CLIENT_HELLO_SENT ||
+               ssl->options.connectState == HELLO_AGAIN_REPLY ||
+               ssl->options.connectState == FINISHED_DONE ||
+               ssl->options.connectState == SECOND_REPLY_DONE))) {
+
+            WOLFSSL_ERROR(DTLS_RETX_OVER_TX);
+            ssl->error = DTLS_RETX_OVER_TX;
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        while (pool != NULL) {
+            if (pool->seq == 0) {
+                DtlsRecordLayerHeader* dtls;
+                int epochOrder;
+
+                dtls = (DtlsRecordLayerHeader*)pool->buf;
+                /* If the stored record's epoch is 0, and the currently set
+                 * epoch is 0, use the "current order" sequence number.
+                 * If the stored record's epoch is 0 and the currently set
+                 * epoch is not 0, the stored record is considered a "previous
+                 * order" sequence number. */
+                epochOrder = (ssl->keys.dtls_epoch == 0) ?
+                             CUR_ORDER : PREV_ORDER;
+
+                WriteSEQ(ssl, epochOrder, dtls->sequence_number);
+                DtlsSEQIncrement(ssl, epochOrder);
+                if ((ret = CheckAvailableSize(ssl, pool->sz)) != 0) {
+                    WOLFSSL_ERROR(ret);
+                    return ret;
+                }
+
+                XMEMCPY(ssl->buffers.outputBuffer.buffer,
+                        pool->buf, pool->sz);
+                ssl->buffers.outputBuffer.idx = 0;
+                ssl->buffers.outputBuffer.length = pool->sz;
+            }
+            else if (pool->seq == ssl->keys.dtls_epoch) {
+                byte*  input;
+                byte*  output;
+                int    inputSz, sendSz;
+
+                input = pool->buf;
+                inputSz = pool->sz;
+                sendSz = inputSz + MAX_MSG_EXTRA;
+
+                if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) {
+                    WOLFSSL_ERROR(ret);
+                    return ret;
+                }
+
+                output = ssl->buffers.outputBuffer.buffer +
+                         ssl->buffers.outputBuffer.length;
+                sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
+                                      handshake, 0, 0, 0);
+                if (sendSz < 0) {
+                    WOLFSSL_ERROR(BUILD_MSG_ERROR);
+                    return BUILD_MSG_ERROR;
+                }
+
+                ssl->buffers.outputBuffer.length += sendSz;
+            }
+
+            ret = SendBuffered(ssl);
+            if (ret < 0) {
+                WOLFSSL_ERROR(ret);
+                return ret;
+            }
+
+            /**
+             * on server side, retransmission is being triggered only by sending
+             * first message of given flight, in order to trigger client
+             * to retransmit its whole flight. Sending the whole previous flight
+             * could lead to retransmission of previous client flight for each
+             * server message from previous flight. Therefore one message should
+             * be enough to do the trick.
+             */
+            if (sendOnlyFirstPacket &&
+                ssl->options.side == WOLFSSL_SERVER_END) {
+
+                pool = NULL;
+            }
+            else
+                pool = pool->next;
+            ssl->dtls_tx_msg = pool;
+        }
+    }
+
+    WOLFSSL_LEAVE("DtlsMsgPoolSend()", ret);
+    return ret;
+}
+
+#endif /* WOLFSSL_DTLS */
+
+#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
+
+ProtocolVersion MakeSSLv3(void)
+{
+    ProtocolVersion pv;
+    pv.major = SSLv3_MAJOR;
+    pv.minor = SSLv3_MINOR;
+
+    return pv;
+}
+
+#endif /* WOLFSSL_ALLOW_SSLV3 && !NO_OLD_TLS */
+
+
+#ifdef WOLFSSL_DTLS
+
+ProtocolVersion MakeDTLSv1(void)
+{
+    ProtocolVersion pv;
+    pv.major = DTLS_MAJOR;
+    pv.minor = DTLS_MINOR;
+
+    return pv;
+}
+
+#ifndef WOLFSSL_NO_TLS12
+
+ProtocolVersion MakeDTLSv1_2(void)
+{
+    ProtocolVersion pv;
+    pv.major = DTLS_MAJOR;
+    pv.minor = DTLSv1_2_MINOR;
+
+    return pv;
+}
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#endif /* WOLFSSL_DTLS */
+
+
+#ifndef NO_ASN_TIME
+#if defined(USER_TICKS)
+#if 0
+    word32 LowResTimer(void)
+    {
+        /*
+        write your own clock tick function if don't want time(0)
+        needs second accuracy but doesn't have to correlated to EPOCH
+        */
+    }
+#endif
+
+#elif defined(TIME_OVERRIDES)
+
+    /* use same asn time overrides unless user wants tick override above */
+
+    #ifndef HAVE_TIME_T_TYPE
+        typedef long time_t;
+    #endif
+    extern time_t XTIME(time_t * timer);
+
+    word32 LowResTimer(void)
+    {
+        return (word32) XTIME(0);
+    }
+
+#elif defined(USE_WINDOWS_API)
+
+    word32 LowResTimer(void)
+    {
+        static int           init = 0;
+        static LARGE_INTEGER freq;
+        LARGE_INTEGER        count;
+
+        if (!init) {
+            QueryPerformanceFrequency(&freq);
+            init = 1;
+        }
+
+        QueryPerformanceCounter(&count);
+
+        return (word32)(count.QuadPart / freq.QuadPart);
+    }
+
+#elif defined(HAVE_RTP_SYS)
+
+    #include "rtptime.h"
+
+    word32 LowResTimer(void)
+    {
+        return (word32)rtp_get_system_sec();
+    }
+
+#elif defined(WOLFSSL_DEOS)
+
+    word32 LowResTimer(void)
+    {
+        const uint32_t systemTickTimeInHz = 1000000 / systemTickInMicroseconds();
+        uint32_t *systemTickPtr = systemTickPointer();
+
+        return (word32) *systemTickPtr/systemTickTimeInHz;
+    }
+
+#elif defined(MICRIUM)
+
+    word32 LowResTimer(void)
+    {
+        OS_TICK ticks = 0;
+        OS_ERR  err;
+
+        ticks = OSTimeGet(&err);
+
+        return (word32) (ticks / OSCfg_TickRate_Hz);
+    }
+
+
+#elif defined(MICROCHIP_TCPIP_V5)
+
+    word32 LowResTimer(void)
+    {
+        return (word32) (TickGet() / TICKS_PER_SECOND);
+    }
+
+
+#elif defined(MICROCHIP_TCPIP)
+
+    #if defined(MICROCHIP_MPLAB_HARMONY)
+
+        #include <system/tmr/sys_tmr.h>
+
+        word32 LowResTimer(void)
+        {
+            return (word32) (SYS_TMR_TickCountGet() /
+                             SYS_TMR_TickCounterFrequencyGet());
+        }
+
+    #else
+
+        word32 LowResTimer(void)
+        {
+            return (word32) (SYS_TICK_Get() / SYS_TICK_TicksPerSecondGet());
+        }
+
+    #endif
+
+#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
+
+    word32 LowResTimer(void)
+    {
+        TIME_STRUCT mqxTime;
+
+        _time_get_elapsed(&mqxTime);
+
+        return (word32) mqxTime.SECONDS;
+    }
+#elif defined(FREESCALE_FREE_RTOS) || defined(FREESCALE_KSDK_FREERTOS)
+
+    #include "include/task.h"
+
+    unsigned int LowResTimer(void)
+    {
+        return (unsigned int)(((float)xTaskGetTickCount())/configTICK_RATE_HZ);
+    }
+
+#elif defined(FREERTOS)
+
+    #include "task.h"
+
+    unsigned int LowResTimer(void)
+    {
+        return (unsigned int)(((float)xTaskGetTickCount())/configTICK_RATE_HZ);
+    }
+
+#elif defined(FREESCALE_KSDK_BM)
+
+    #include "lwip/sys.h" /* lwIP */
+    word32 LowResTimer(void)
+    {
+        return sys_now()/1000;
+    }
+
+#elif defined(WOLFSSL_TIRTOS)
+
+    word32 LowResTimer(void)
+    {
+        return (word32) Seconds_get();
+    }
+#elif defined(WOLFSSL_XILINX)
+    #include "xrtcpsu.h"
+
+    word32 LowResTimer(void)
+    {
+        XRtcPsu_Config* con;
+        XRtcPsu         rtc;
+
+        con = XRtcPsu_LookupConfig(XPAR_XRTCPSU_0_DEVICE_ID);
+        if (con != NULL) {
+            if (XRtcPsu_CfgInitialize(&rtc, con, con->BaseAddr)
+                    == XST_SUCCESS) {
+                return (word32)XRtcPsu_GetCurrentTime(&rtc);
+            }
+            else {
+                WOLFSSL_MSG("Unable to initialize RTC");
+            }
+        }
+
+        return 0;
+    }
+
+#elif defined(WOLFSSL_UTASKER)
+
+    word32 LowResTimer(void)
+    {
+        return (word32)(uTaskerSystemTick / TICK_RESOLUTION);
+    }
+
+#elif defined(WOLFSSL_NUCLEUS_1_2)
+
+    #define NU_TICKS_PER_SECOND 100
+
+    word32 LowResTimer(void)
+    {
+        /* returns number of 10ms ticks, so 100 ticks/sec */
+        return NU_Retrieve_Clock() / NU_TICKS_PER_SECOND;
+    }
+#elif defined(WOLFSSL_APACHE_MYNEWT)
+
+    #include "os/os_time.h"
+    word32 LowResTimer(void)
+    {
+        word32 now;
+        struct os_timeval tv;
+        os_gettimeofday(&tv, NULL);
+        now = (word32)tv.tv_sec;
+        return now;
+    }
+
+#elif defined(WOLFSSL_ZEPHYR)
+
+    word32 LowResTimer(void)
+    {
+        return k_uptime_get() / 1000;
+    }
+
+#else
+    /* Posix style time */
+    #if !defined(USER_TIME) && !defined(USE_WOLF_TM)
+    #include <time.h>
+    #endif
+
+    word32 LowResTimer(void)
+    {
+        return (word32)XTIME(0);
+    }
+#endif
+#endif /* !NO_ASN_TIME */
+#if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
+               ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \
+                (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)))
+/* Store the message for use with CertificateVerify using EdDSA.
+ *
+ * ssl   SSL/TLS object.
+ * data  Message to store.
+ * sz    Size of message to store.
+ * returns MEMORY_E if not able to reallocate, otherwise 0.
+ */
+static int EdDSA_Update(WOLFSSL* ssl, const byte* data, int sz)
+{
+    int   ret = 0;
+    byte* msgs;
+
+    if (ssl->options.cacheMessages) {
+        msgs = (byte*)XREALLOC(ssl->hsHashes->messages,
+                                                ssl->hsHashes->length + sz,
+                                                ssl->heap, DYNAMIC_TYPE_HASHES);
+        if (msgs == NULL)
+            ret = MEMORY_E;
+        if (ret == 0) {
+            ssl->hsHashes->messages = msgs;
+            XMEMCPY(msgs + ssl->hsHashes->length, data, sz);
+            ssl->hsHashes->prevLen = ssl->hsHashes->length;
+            ssl->hsHashes->length += sz;
+        }
+    }
+
+    return ret;
+}
+#endif /* (HAVE_ED25519 || HAVE_ED448) && !WOLFSSL_NO_CLIENT_AUTH */
+
+#ifndef NO_CERTS
+int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz)
+{
+    int ret = 0;
+
+    (void)output;
+    (void)sz;
+
+    if (ssl->hsHashes == NULL)
+        return BAD_FUNC_ARG;
+
+#ifdef HAVE_FUZZER
+    if (ssl->fuzzerCb)
+        ssl->fuzzerCb(ssl, output, sz, FUZZ_HASH, ssl->fuzzerCtx);
+#endif
+#ifndef NO_OLD_TLS
+    #ifndef NO_SHA
+        wc_ShaUpdate(&ssl->hsHashes->hashSha, output, sz);
+    #endif
+    #ifndef NO_MD5
+        wc_Md5Update(&ssl->hsHashes->hashMd5, output, sz);
+    #endif
+#endif /* NO_OLD_TLS */
+
+    if (IsAtLeastTLSv1_2(ssl)) {
+    #ifndef NO_SHA256
+        ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, output, sz);
+        if (ret != 0)
+            return ret;
+    #endif
+    #ifdef WOLFSSL_SHA384
+        ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, output, sz);
+        if (ret != 0)
+            return ret;
+    #endif
+    #ifdef WOLFSSL_SHA512
+        ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, output, sz);
+        if (ret != 0)
+            return ret;
+    #endif
+    #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
+               ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \
+                (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)))
+        ret = EdDSA_Update(ssl, output, sz);
+        if (ret != 0)
+            return ret;
+    #endif
+    }
+
+    return ret;
+}
+#endif /* NO_CERTS */
+
+
+/* add output to md5 and sha handshake hashes, exclude record header */
+int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz)
+{
+    int ret = 0;
+    const byte* adj;
+
+    if (ssl->hsHashes == NULL)
+        return BAD_FUNC_ARG;
+
+    adj = output + RECORD_HEADER_SZ + ivSz;
+    sz -= RECORD_HEADER_SZ;
+
+#ifdef HAVE_FUZZER
+    if (ssl->fuzzerCb)
+        ssl->fuzzerCb(ssl, output, sz, FUZZ_HASH, ssl->fuzzerCtx);
+#endif
+#ifdef WOLFSSL_DTLS
+    if (ssl->options.dtls) {
+        adj += DTLS_RECORD_EXTRA;
+        sz  -= DTLS_RECORD_EXTRA;
+    }
+#endif
+#ifndef NO_OLD_TLS
+    #ifndef NO_SHA
+        wc_ShaUpdate(&ssl->hsHashes->hashSha, adj, sz);
+    #endif
+    #ifndef NO_MD5
+        wc_Md5Update(&ssl->hsHashes->hashMd5, adj, sz);
+    #endif
+#endif
+
+    if (IsAtLeastTLSv1_2(ssl)) {
+    #ifndef NO_SHA256
+        ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, adj, sz);
+        if (ret != 0)
+            return ret;
+    #endif
+    #ifdef WOLFSSL_SHA384
+        ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, adj, sz);
+        if (ret != 0)
+            return ret;
+    #endif
+    #ifdef WOLFSSL_SHA512
+        ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, adj, sz);
+        if (ret != 0)
+            return ret;
+    #endif
+    #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
+               ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \
+                (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)))
+        ret = EdDSA_Update(ssl, adj, sz);
+        if (ret != 0)
+            return ret;
+    #endif
+    }
+
+    return ret;
+}
+
+
+/* add input to md5 and sha handshake hashes, include handshake header */
+int HashInput(WOLFSSL* ssl, const byte* input, int sz)
+{
+    int ret = 0;
+    const byte* adj;
+
+    adj = input - HANDSHAKE_HEADER_SZ;
+    sz += HANDSHAKE_HEADER_SZ;
+
+    (void)adj;
+
+#ifdef WOLFSSL_DTLS
+    if (ssl->options.dtls) {
+        adj -= DTLS_HANDSHAKE_EXTRA;
+        sz  += DTLS_HANDSHAKE_EXTRA;
+    }
+#endif
+
+    if (ssl->hsHashes == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifndef NO_OLD_TLS
+    #ifndef NO_SHA
+        wc_ShaUpdate(&ssl->hsHashes->hashSha, adj, sz);
+    #endif
+    #ifndef NO_MD5
+        wc_Md5Update(&ssl->hsHashes->hashMd5, adj, sz);
+    #endif
+#endif
+
+    if (IsAtLeastTLSv1_2(ssl)) {
+    #ifndef NO_SHA256
+        ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, adj, sz);
+        if (ret != 0)
+            return ret;
+    #endif
+    #ifdef WOLFSSL_SHA384
+        ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, adj, sz);
+        if (ret != 0)
+            return ret;
+    #endif
+    #ifdef WOLFSSL_SHA512
+        ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, adj, sz);
+        if (ret != 0)
+            return ret;
+    #endif
+    #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
+               ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \
+                (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)))
+        ret = EdDSA_Update(ssl, adj, sz);
+        if (ret != 0)
+            return ret;
+    #endif
+    }
+
+    return ret;
+}
+
+
+/* add record layer header for message */
+static void AddRecordHeader(byte* output, word32 length, byte type, WOLFSSL* ssl)
+{
+    RecordLayerHeader* rl;
+
+    /* record layer header */
+    rl = (RecordLayerHeader*)output;
+    if (rl == NULL) {
+        return;
+    }
+    rl->type    = type;
+    rl->pvMajor = ssl->version.major;       /* type and version same in each */
+#ifdef WOLFSSL_TLS13
+    if (IsAtLeastTLSv1_3(ssl->version)) {
+#ifdef WOLFSSL_TLS13_DRAFT_18
+        rl->pvMinor = TLSv1_MINOR;
+#else
+        rl->pvMinor = TLSv1_2_MINOR;
+#endif
+    }
+    else
+#endif
+        rl->pvMinor = ssl->version.minor;
+
+#ifdef WOLFSSL_ALTERNATIVE_DOWNGRADE
+    if (ssl->options.side == WOLFSSL_CLIENT_END
+    &&  ssl->options.connectState == CONNECT_BEGIN
+    && !ssl->options.resuming) {
+        rl->pvMinor = ssl->options.downgrade ? ssl->options.minDowngrade
+                                             : ssl->version.minor;
+    }
+#endif
+
+    if (!ssl->options.dtls) {
+        c16toa((word16)length, rl->length);
+    }
+    else {
+#ifdef WOLFSSL_DTLS
+        DtlsRecordLayerHeader* dtls;
+
+        /* dtls record layer header extensions */
+        dtls = (DtlsRecordLayerHeader*)output;
+        WriteSEQ(ssl, 0, dtls->sequence_number);
+        c16toa((word16)length, dtls->length);
+#endif
+    }
+}
+
+
+#if !defined(WOLFSSL_NO_TLS12) || (defined(HAVE_SESSION_TICKET) && \
+                                                    !defined(NO_WOLFSSL_SERVER))
+/* add handshake header for message */
+static void AddHandShakeHeader(byte* output, word32 length,
+                               word32 fragOffset, word32 fragLength,
+                               byte type, WOLFSSL* ssl)
+{
+    HandShakeHeader* hs;
+    (void)fragOffset;
+    (void)fragLength;
+    (void)ssl;
+
+    /* handshake header */
+    hs = (HandShakeHeader*)output;
+    if (hs == NULL)
+        return;
+
+    hs->type = type;
+    c32to24(length, hs->length);         /* type and length same for each */
+#ifdef WOLFSSL_DTLS
+    if (ssl->options.dtls) {
+        DtlsHandShakeHeader* dtls;
+
+        /* dtls handshake header extensions */
+        dtls = (DtlsHandShakeHeader*)output;
+        c16toa(ssl->keys.dtls_handshake_number++, dtls->message_seq);
+        c32to24(fragOffset, dtls->fragment_offset);
+        c32to24(fragLength, dtls->fragment_length);
+    }
+#endif
+}
+
+/* add both headers for handshake message */
+static void AddHeaders(byte* output, word32 length, byte type, WOLFSSL* ssl)
+{
+    word32 lengthAdj = HANDSHAKE_HEADER_SZ;
+    word32 outputAdj = RECORD_HEADER_SZ;
+
+#ifdef WOLFSSL_DTLS
+    if (ssl->options.dtls) {
+        lengthAdj += DTLS_HANDSHAKE_EXTRA;
+        outputAdj += DTLS_RECORD_EXTRA;
+    }
+#endif
+
+    AddRecordHeader(output, length + lengthAdj, handshake, ssl);
+    AddHandShakeHeader(output + outputAdj, length, 0, length, type, ssl);
+}
+#endif /* !WOLFSSL_NO_TLS12 || (HAVE_SESSION_TICKET && !NO_WOLFSSL_SERVER) */
+
+
+#ifndef WOLFSSL_NO_TLS12
+#if !defined(NO_CERTS) && (!defined(NO_WOLFSSL_SERVER) || \
+                                               !defined(WOLFSSL_NO_CLIENT_AUTH))
+static void AddFragHeaders(byte* output, word32 fragSz, word32 fragOffset,
+                           word32 length, byte type, WOLFSSL* ssl)
+{
+    word32 lengthAdj = HANDSHAKE_HEADER_SZ;
+    word32 outputAdj = RECORD_HEADER_SZ;
+    (void)fragSz;
+
+#ifdef WOLFSSL_DTLS
+    if (ssl->options.dtls) {
+        lengthAdj += DTLS_HANDSHAKE_EXTRA;
+        outputAdj += DTLS_RECORD_EXTRA;
+    }
+#endif
+
+    AddRecordHeader(output, fragSz + lengthAdj, handshake, ssl);
+    AddHandShakeHeader(output + outputAdj, length, fragOffset, fragSz, type, ssl);
+}
+#endif /* NO_CERTS */
+#endif /* !WOLFSSL_NO_TLS12 */
+
+
+/* return bytes received, -1 on error */
+static int wolfSSLReceive(WOLFSSL* ssl, byte* buf, word32 sz)
+{
+    int recvd;
+
+    if (ssl->CBIORecv == NULL) {
+        WOLFSSL_MSG("Your IO Recv callback is null, please set");
+        return -1;
+    }
+
+retry:
+    recvd = ssl->CBIORecv(ssl, (char *)buf, (int)sz, ssl->IOCB_ReadCtx);
+    if (recvd < 0) {
+        switch (recvd) {
+            case WOLFSSL_CBIO_ERR_GENERAL:        /* general/unknown error */
+                #if defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD)
+                    if (ssl->biord) {
+                        /* If retry and read flags are set, return WANT_READ */
+                        if ((ssl->biord->flags & WOLFSSL_BIO_FLAG_READ) &&
+                            (ssl->biord->flags & WOLFSSL_BIO_FLAG_RETRY)) {
+                            return WANT_READ;
+                        }
+                    }
+                #endif
+                return -1;
+
+            case WOLFSSL_CBIO_ERR_WANT_READ:      /* want read, would block */
+                return WANT_READ;
+
+            case WOLFSSL_CBIO_ERR_CONN_RST:       /* connection reset */
+                #ifdef USE_WINDOWS_API
+                if (ssl->options.dtls) {
+                    goto retry;
+                }
+                #endif
+                ssl->options.connReset = 1;
+                return -1;
+
+            case WOLFSSL_CBIO_ERR_ISR:            /* interrupt */
+                /* see if we got our timeout */
+                #ifdef WOLFSSL_CALLBACKS
+                    if (ssl->toInfoOn) {
+                        struct itimerval timeout;
+                        getitimer(ITIMER_REAL, &timeout);
+                        if (timeout.it_value.tv_sec == 0 &&
+                                                timeout.it_value.tv_usec == 0) {
+                            XSTRNCPY(ssl->timeoutInfo.timeoutName,
+                                    "recv() timeout", MAX_TIMEOUT_NAME_SZ);
+                            ssl->timeoutInfo.timeoutName[
+                                MAX_TIMEOUT_NAME_SZ] = '\0';
+
+                            WOLFSSL_MSG("Got our timeout");
+                            return WANT_READ;
+                        }
+                    }
+                #endif
+                goto retry;
+
+            case WOLFSSL_CBIO_ERR_CONN_CLOSE:     /* peer closed connection */
+                ssl->options.isClosed = 1;
+                return -1;
+
+            case WOLFSSL_CBIO_ERR_TIMEOUT:
+            #ifdef WOLFSSL_DTLS
+                if (IsDtlsNotSctpMode(ssl) &&
+                    !ssl->options.handShakeDone &&
+                    DtlsMsgPoolTimeout(ssl) == 0 &&
+                    DtlsMsgPoolSend(ssl, 0) == 0) {
+
+                    /* retry read for DTLS during handshake only */
+                    goto retry;
+                }
+            #endif
+                return -1;
+
+            default:
+                WOLFSSL_MSG("Unexpected recv return code");
+                return recvd;
+        }
+    }
+
+    return recvd;
+}
+
+
+/* Switch dynamic output buffer back to static, buffer is assumed clear */
+void ShrinkOutputBuffer(WOLFSSL* ssl)
+{
+    WOLFSSL_MSG("Shrinking output buffer\n");
+    XFREE(ssl->buffers.outputBuffer.buffer - ssl->buffers.outputBuffer.offset,
+          ssl->heap, DYNAMIC_TYPE_OUT_BUFFER);
+    ssl->buffers.outputBuffer.buffer = ssl->buffers.outputBuffer.staticBuffer;
+    ssl->buffers.outputBuffer.bufferSize  = STATIC_BUFFER_LEN;
+    ssl->buffers.outputBuffer.dynamicFlag = 0;
+    ssl->buffers.outputBuffer.offset      = 0;
+}
+
+
+/* Switch dynamic input buffer back to static, keep any remaining input */
+/* forced free means cleaning up */
+void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree)
+{
+    int usedLength = ssl->buffers.inputBuffer.length -
+                     ssl->buffers.inputBuffer.idx;
+    if (!forcedFree && usedLength > STATIC_BUFFER_LEN)
+        return;
+
+    WOLFSSL_MSG("Shrinking input buffer\n");
+
+    if (!forcedFree && usedLength > 0)
+        XMEMCPY(ssl->buffers.inputBuffer.staticBuffer,
+               ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx,
+               usedLength);
+
+    XFREE(ssl->buffers.inputBuffer.buffer - ssl->buffers.inputBuffer.offset,
+          ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+    ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer;
+    ssl->buffers.inputBuffer.bufferSize  = STATIC_BUFFER_LEN;
+    ssl->buffers.inputBuffer.dynamicFlag = 0;
+    ssl->buffers.inputBuffer.offset      = 0;
+    ssl->buffers.inputBuffer.idx = 0;
+    ssl->buffers.inputBuffer.length = usedLength;
+}
+
+int SendBuffered(WOLFSSL* ssl)
+{
+    if (ssl->CBIOSend == NULL) {
+        WOLFSSL_MSG("Your IO Send callback is null, please set");
+        return SOCKET_ERROR_E;
+    }
+
+#ifdef WOLFSSL_DEBUG_TLS
+    if (ssl->buffers.outputBuffer.idx == 0) {
+        WOLFSSL_MSG("Data to send");
+        WOLFSSL_BUFFER(ssl->buffers.outputBuffer.buffer,
+                       ssl->buffers.outputBuffer.length);
+    }
+#endif
+
+    while (ssl->buffers.outputBuffer.length > 0) {
+        int sent = ssl->CBIOSend(ssl,
+                                      (char*)ssl->buffers.outputBuffer.buffer +
+                                      ssl->buffers.outputBuffer.idx,
+                                      (int)ssl->buffers.outputBuffer.length,
+                                      ssl->IOCB_WriteCtx);
+        if (sent < 0) {
+            switch (sent) {
+
+                case WOLFSSL_CBIO_ERR_WANT_WRITE:        /* would block */
+                    return WANT_WRITE;
+
+                case WOLFSSL_CBIO_ERR_CONN_RST:          /* connection reset */
+                    ssl->options.connReset = 1;
+                    break;
+
+                case WOLFSSL_CBIO_ERR_ISR:               /* interrupt */
+                    /* see if we got our timeout */
+                    #ifdef WOLFSSL_CALLBACKS
+                        if (ssl->toInfoOn) {
+                            struct itimerval timeout;
+                            getitimer(ITIMER_REAL, &timeout);
+                            if (timeout.it_value.tv_sec == 0 &&
+                                                timeout.it_value.tv_usec == 0) {
+                                XSTRNCPY(ssl->timeoutInfo.timeoutName,
+                                        "send() timeout", MAX_TIMEOUT_NAME_SZ);
+                                ssl->timeoutInfo.timeoutName[
+                                    MAX_TIMEOUT_NAME_SZ] = '\0';
+
+                                WOLFSSL_MSG("Got our timeout");
+                                return WANT_WRITE;
+                            }
+                        }
+                    #endif
+                    continue;
+
+                case WOLFSSL_CBIO_ERR_CONN_CLOSE: /* epipe / conn closed */
+                    ssl->options.connReset = 1;  /* treat same as reset */
+                    break;
+
+                default:
+                    return SOCKET_ERROR_E;
+            }
+
+            return SOCKET_ERROR_E;
+        }
+
+        if (sent > (int)ssl->buffers.outputBuffer.length) {
+            WOLFSSL_MSG("SendBuffered() out of bounds read");
+            return SEND_OOB_READ_E;
+        }
+
+        ssl->buffers.outputBuffer.idx += sent;
+        ssl->buffers.outputBuffer.length -= sent;
+    }
+
+    ssl->buffers.outputBuffer.idx = 0;
+
+    if (ssl->buffers.outputBuffer.dynamicFlag)
+        ShrinkOutputBuffer(ssl);
+
+    return 0;
+}
+
+
+/* Grow the output buffer */
+static WC_INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size)
+{
+    byte* tmp;
+#if WOLFSSL_GENERAL_ALIGNMENT > 0
+    byte  hdrSz = ssl->options.dtls ? DTLS_RECORD_HEADER_SZ :
+                                      RECORD_HEADER_SZ;
+    byte align = WOLFSSL_GENERAL_ALIGNMENT;
+#else
+    const byte align = WOLFSSL_GENERAL_ALIGNMENT;
+#endif
+
+#if WOLFSSL_GENERAL_ALIGNMENT > 0
+    /* the encrypted data will be offset from the front of the buffer by
+       the header, if the user wants encrypted alignment they need
+       to define their alignment requirement */
+
+    if (align) {
+       while (align < hdrSz)
+           align *= 2;
+    }
+#endif
+
+    tmp = (byte*)XMALLOC(size + ssl->buffers.outputBuffer.length + align,
+                             ssl->heap, DYNAMIC_TYPE_OUT_BUFFER);
+    WOLFSSL_MSG("growing output buffer\n");
+
+    if (tmp == NULL)
+        return MEMORY_E;
+
+#if WOLFSSL_GENERAL_ALIGNMENT > 0
+    if (align)
+        tmp += align - hdrSz;
+#endif
+
+#ifdef WOLFSSL_STATIC_MEMORY
+    /* can be from IO memory pool which does not need copy if same buffer */
+    if (ssl->buffers.outputBuffer.length &&
+            tmp == ssl->buffers.outputBuffer.buffer) {
+        ssl->buffers.outputBuffer.bufferSize =
+            size + ssl->buffers.outputBuffer.length;
+        return 0;
+    }
+#endif
+
+    if (ssl->buffers.outputBuffer.length)
+        XMEMCPY(tmp, ssl->buffers.outputBuffer.buffer,
+               ssl->buffers.outputBuffer.length);
+
+    if (ssl->buffers.outputBuffer.dynamicFlag)
+        XFREE(ssl->buffers.outputBuffer.buffer -
+              ssl->buffers.outputBuffer.offset, ssl->heap,
+              DYNAMIC_TYPE_OUT_BUFFER);
+    ssl->buffers.outputBuffer.dynamicFlag = 1;
+
+#if WOLFSSL_GENERAL_ALIGNMENT > 0
+    if (align)
+        ssl->buffers.outputBuffer.offset = align - hdrSz;
+    else
+#endif
+        ssl->buffers.outputBuffer.offset = 0;
+
+    ssl->buffers.outputBuffer.buffer = tmp;
+    ssl->buffers.outputBuffer.bufferSize = size +
+                                           ssl->buffers.outputBuffer.length;
+    return 0;
+}
+
+
+/* Grow the input buffer, should only be to read cert or big app data */
+int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength)
+{
+    byte* tmp;
+#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0
+    byte  align = ssl->options.dtls ? WOLFSSL_GENERAL_ALIGNMENT : 0;
+    byte  hdrSz = DTLS_RECORD_HEADER_SZ;
+#else
+    const byte align = WOLFSSL_GENERAL_ALIGNMENT;
+#endif
+
+#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0
+    /* the encrypted data will be offset from the front of the buffer by
+       the dtls record header, if the user wants encrypted alignment they need
+       to define their alignment requirement. in tls we read record header
+       to get size of record and put actual data back at front, so don't need */
+
+    if (align) {
+       while (align < hdrSz)
+           align *= 2;
+    }
+#endif
+
+    if (usedLength < 0 || size < 0) {
+        WOLFSSL_MSG("GrowInputBuffer() called with negative number");
+        return BAD_FUNC_ARG;
+    }
+
+    tmp = (byte*)XMALLOC(size + usedLength + align,
+                             ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+    WOLFSSL_MSG("growing input buffer\n");
+
+    if (tmp == NULL)
+        return MEMORY_E;
+
+#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0
+    if (align)
+        tmp += align - hdrSz;
+#endif
+
+#ifdef WOLFSSL_STATIC_MEMORY
+    /* can be from IO memory pool which does not need copy if same buffer */
+    if (usedLength && tmp == ssl->buffers.inputBuffer.buffer) {
+        ssl->buffers.inputBuffer.bufferSize = size + usedLength;
+        ssl->buffers.inputBuffer.idx    = 0;
+        ssl->buffers.inputBuffer.length = usedLength;
+        return 0;
+    }
+#endif
+
+    if (usedLength)
+        XMEMCPY(tmp, ssl->buffers.inputBuffer.buffer +
+                    ssl->buffers.inputBuffer.idx, usedLength);
+
+    if (ssl->buffers.inputBuffer.dynamicFlag)
+        XFREE(ssl->buffers.inputBuffer.buffer - ssl->buffers.inputBuffer.offset,
+              ssl->heap,DYNAMIC_TYPE_IN_BUFFER);
+
+    ssl->buffers.inputBuffer.dynamicFlag = 1;
+#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0
+    if (align)
+        ssl->buffers.inputBuffer.offset = align - hdrSz;
+    else
+#endif
+        ssl->buffers.inputBuffer.offset = 0;
+
+    ssl->buffers.inputBuffer.buffer = tmp;
+    ssl->buffers.inputBuffer.bufferSize = size + usedLength;
+    ssl->buffers.inputBuffer.idx    = 0;
+    ssl->buffers.inputBuffer.length = usedLength;
+
+    return 0;
+}
+
+
+/* check available size into output buffer, make room if needed */
+int CheckAvailableSize(WOLFSSL *ssl, int size)
+{
+    if (size < 0) {
+        WOLFSSL_MSG("CheckAvailableSize() called with negative number");
+        return BAD_FUNC_ARG;
+    }
+
+    if (ssl->buffers.outputBuffer.bufferSize - ssl->buffers.outputBuffer.length
+                                             < (word32)size) {
+        if (GrowOutputBuffer(ssl, size) < 0)
+            return MEMORY_E;
+    }
+
+    return 0;
+}
+
+
+/* do all verify and sanity checks on record header */
+static int GetRecordHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                           RecordLayerHeader* rh, word16 *size)
+{
+    if (!ssl->options.dtls) {
+#ifdef HAVE_FUZZER
+        if (ssl->fuzzerCb)
+            ssl->fuzzerCb(ssl, input + *inOutIdx, RECORD_HEADER_SZ, FUZZ_HEAD,
+                    ssl->fuzzerCtx);
+#endif
+        XMEMCPY(rh, input + *inOutIdx, RECORD_HEADER_SZ);
+        *inOutIdx += RECORD_HEADER_SZ;
+        ato16(rh->length, size);
+    }
+    else {
+#ifdef WOLFSSL_DTLS
+#ifdef HAVE_FUZZER
+        if (ssl->fuzzerCb)
+            ssl->fuzzerCb(ssl, input + *inOutIdx, DTLS_RECORD_HEADER_SZ,
+                           FUZZ_HEAD, ssl->fuzzerCtx);
+#endif
+        /* type and version in same sport */
+        XMEMCPY(rh, input + *inOutIdx, ENUM_LEN + VERSION_SZ);
+        *inOutIdx += ENUM_LEN + VERSION_SZ;
+        ato16(input + *inOutIdx, &ssl->keys.curEpoch);
+        *inOutIdx += OPAQUE16_LEN;
+        if (ssl->options.haveMcast) {
+        #ifdef WOLFSSL_MULTICAST
+            ssl->keys.curPeerId = input[*inOutIdx];
+            ssl->keys.curSeq_hi = input[*inOutIdx+1];
+        #endif
+        }
+        else
+            ato16(input + *inOutIdx, &ssl->keys.curSeq_hi);
+        *inOutIdx += OPAQUE16_LEN;
+        ato32(input + *inOutIdx, &ssl->keys.curSeq_lo);
+        *inOutIdx += OPAQUE32_LEN;  /* advance past rest of seq */
+        ato16(input + *inOutIdx, size);
+        *inOutIdx += LENGTH_SZ;
+#endif
+    }
+
+#ifdef WOLFSSL_DTLS
+    if (IsDtlsNotSctpMode(ssl) && !DtlsCheckWindow(ssl)) {
+            WOLFSSL_LEAVE("GetRecordHeader()", SEQUENCE_ERROR);
+            return SEQUENCE_ERROR;
+    }
+#endif
+
+    /* catch version mismatch */
+#ifndef WOLFSSL_TLS13
+    if (rh->pvMajor != ssl->version.major || rh->pvMinor != ssl->version.minor)
+#else
+    if (rh->pvMajor != ssl->version.major ||
+        (rh->pvMinor != ssl->version.minor &&
+#ifdef WOLFSSL_TLS13_DRAFT_18
+         (!IsAtLeastTLSv1_3(ssl->version) || rh->pvMinor != TLSv1_MINOR)
+#else
+         (!IsAtLeastTLSv1_3(ssl->version) || rh->pvMinor != TLSv1_2_MINOR)
+#endif
+        ))
+#endif
+    {
+        if (ssl->options.side == WOLFSSL_SERVER_END &&
+            ssl->options.acceptState < ACCEPT_FIRST_REPLY_DONE)
+
+            WOLFSSL_MSG("Client attempting to connect with different version");
+        else if (ssl->options.side == WOLFSSL_CLIENT_END &&
+                                 ssl->options.downgrade &&
+                                 ssl->options.connectState < FIRST_REPLY_DONE)
+            WOLFSSL_MSG("Server attempting to accept with different version");
+        else if (ssl->options.dtls && rh->type == handshake)
+            /* Check the DTLS handshake message RH version later. */
+            WOLFSSL_MSG("DTLS handshake, skip RH version number check");
+        else {
+            WOLFSSL_MSG("SSL version error");
+            /* send alert per RFC5246 Appendix E. Backward Compatibility */
+            if (ssl->options.side == WOLFSSL_CLIENT_END) {
+#ifdef WOLFSSL_MYSQL_COMPATIBLE
+                SendAlert(ssl, alert_fatal, wc_protocol_version);
+#else
+                SendAlert(ssl, alert_fatal, protocol_version);
+#endif
+            }
+            return VERSION_ERROR;              /* only use requested version */
+        }
+    }
+
+    /* record layer length check */
+#ifdef HAVE_MAX_FRAGMENT
+    if (*size > (ssl->max_fragment + MAX_COMP_EXTRA + MAX_MSG_EXTRA)) {
+        SendAlert(ssl, alert_fatal, record_overflow);
+        return LENGTH_ERROR;
+    }
+#else
+    if (*size > (MAX_RECORD_SIZE + MAX_COMP_EXTRA + MAX_MSG_EXTRA))
+        return LENGTH_ERROR;
+#endif
+
+    /* verify record type here as well */
+    switch (rh->type) {
+        case handshake:
+        case change_cipher_spec:
+        case application_data:
+        case alert:
+            break;
+        case no_type:
+        default:
+            WOLFSSL_MSG("Unknown Record Type");
+            return UNKNOWN_RECORD_TYPE;
+    }
+
+    /* haven't decrypted this record yet */
+    ssl->keys.decryptedCur = 0;
+
+    return 0;
+}
+
+#ifndef WOLFSSL_NO_TLS12
+static int GetHandShakeHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                              byte *type, word32 *size, word32 totalSz)
+{
+    const byte *ptr = input + *inOutIdx;
+    (void)ssl;
+
+    *inOutIdx += HANDSHAKE_HEADER_SZ;
+    if (*inOutIdx > totalSz)
+        return BUFFER_E;
+
+    *type = ptr[0];
+    c24to32(&ptr[1], size);
+
+    return 0;
+}
+#endif
+
+#ifdef WOLFSSL_DTLS
+static int GetDtlsHandShakeHeader(WOLFSSL* ssl, const byte* input,
+                                  word32* inOutIdx, byte *type, word32 *size,
+                                  word32 *fragOffset, word32 *fragSz,
+                                  word32 totalSz)
+{
+    word32 idx = *inOutIdx;
+
+    *inOutIdx += HANDSHAKE_HEADER_SZ + DTLS_HANDSHAKE_EXTRA;
+    if (*inOutIdx > totalSz) {
+        WOLFSSL_ERROR(BUFFER_E);
+        return BUFFER_E;
+    }
+
+    *type = input[idx++];
+    c24to32(input + idx, size);
+    idx += OPAQUE24_LEN;
+
+    ato16(input + idx, &ssl->keys.dtls_peer_handshake_number);
+    idx += DTLS_HANDSHAKE_SEQ_SZ;
+
+    c24to32(input + idx, fragOffset);
+    idx += DTLS_HANDSHAKE_FRAG_SZ;
+    c24to32(input + idx, fragSz);
+
+    if (ssl->curRL.pvMajor != ssl->version.major ||
+        ssl->curRL.pvMinor != ssl->version.minor) {
+
+        if (*type != client_hello && *type != hello_verify_request) {
+            WOLFSSL_ERROR(VERSION_ERROR);
+            return VERSION_ERROR;
+        }
+        else {
+            WOLFSSL_MSG("DTLS Handshake ignoring hello or verify version");
+        }
+    }
+    return 0;
+}
+#endif
+
+
+#if !defined(NO_OLD_TLS) || \
+    (defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLS_SHA1))
+/* fill with MD5 pad size since biggest required */
+static const byte PAD1[PAD_MD5] =
+                              { 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+                                0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+                                0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+                                0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+                                0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+                                0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
+                              };
+static const byte PAD2[PAD_MD5] =
+                              { 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+                                0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+                                0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+                                0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+                                0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+                                0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c
+                              };
+#endif /* !NO_OLD_TLS || (NO_OLD_TLS && WOLFSSL_ALLOW_TLS_SHA1) */
+
+#ifndef NO_OLD_TLS
+
+/* calculate MD5 hash for finished */
+#ifdef WOLFSSL_TI_HASH
+#include <wolfssl/wolfcrypt/hash.h>
+#endif
+
+static int BuildMD5(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
+{
+    int ret;
+    byte md5_result[WC_MD5_DIGEST_SIZE];
+#ifdef WOLFSSL_SMALL_STACK
+    wc_Md5* md5 = (wc_Md5*)XMALLOC(sizeof(wc_Md5), ssl->heap, DYNAMIC_TYPE_HASHCTX);
+    if (md5 == NULL)
+        return MEMORY_E;
+#else
+    wc_Md5  md5[1];
+#endif
+
+    /* make md5 inner */
+    ret = wc_Md5Copy(&ssl->hsHashes->hashMd5, md5);
+    if (ret == 0)
+        ret = wc_Md5Update(md5, sender, SIZEOF_SENDER);
+    if (ret == 0)
+        ret = wc_Md5Update(md5, ssl->arrays->masterSecret,SECRET_LEN);
+    if (ret == 0)
+        ret = wc_Md5Update(md5, PAD1, PAD_MD5);
+    if (ret == 0)
+        ret = wc_Md5Final(md5, md5_result);
+
+    /* make md5 outer */
+    if (ret == 0) {
+        ret = wc_InitMd5_ex(md5, ssl->heap, ssl->devId);
+        if (ret == 0) {
+            ret = wc_Md5Update(md5, ssl->arrays->masterSecret,SECRET_LEN);
+            if (ret == 0)
+                ret = wc_Md5Update(md5, PAD2, PAD_MD5);
+            if (ret == 0)
+                ret = wc_Md5Update(md5, md5_result, WC_MD5_DIGEST_SIZE);
+            if (ret == 0)
+                ret = wc_Md5Final(md5, hashes->md5);
+            wc_Md5Free(md5);
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(md5, ssl->heap, DYNAMIC_TYPE_HASHCTX);
+#endif
+
+    return ret;
+}
+
+
+/* calculate SHA hash for finished */
+static int BuildSHA(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
+{
+    int ret;
+    byte sha_result[WC_SHA_DIGEST_SIZE];
+#ifdef WOLFSSL_SMALL_STACK
+    wc_Sha* sha = (wc_Sha*)XMALLOC(sizeof(wc_Sha), ssl->heap, DYNAMIC_TYPE_HASHCTX);
+    if (sha == NULL)
+        return MEMORY_E;
+#else
+    wc_Sha  sha[1];
+#endif
+    /* make sha inner */
+    ret = wc_ShaCopy(&ssl->hsHashes->hashSha, sha); /* Save current position */
+    if (ret == 0)
+        ret = wc_ShaUpdate(sha, sender, SIZEOF_SENDER);
+    if (ret == 0)
+        ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN);
+    if (ret == 0)
+        ret = wc_ShaUpdate(sha, PAD1, PAD_SHA);
+    if (ret == 0)
+        ret = wc_ShaFinal(sha, sha_result);
+
+    /* make sha outer */
+    if (ret == 0) {
+        ret = wc_InitSha_ex(sha, ssl->heap, ssl->devId);
+        if (ret == 0) {
+            ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN);
+            if (ret == 0)
+                ret = wc_ShaUpdate(sha, PAD2, PAD_SHA);
+            if (ret == 0)
+                ret = wc_ShaUpdate(sha, sha_result, WC_SHA_DIGEST_SIZE);
+            if (ret == 0)
+                ret = wc_ShaFinal(sha, hashes->sha);
+            wc_ShaFree(sha);
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(sha, ssl->heap, DYNAMIC_TYPE_HASHCTX);
+#endif
+
+    return ret;
+}
+#endif
+
+#ifndef WOLFSSL_NO_TLS12
+
+/* Finished doesn't support SHA512, not SHA512 cipher suites yet */
+static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
+{
+    int ret = 0;
+
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+#ifndef NO_TLS
+    if (ssl->options.tls) {
+        ret = BuildTlsFinished(ssl, hashes, sender);
+    }
+#endif
+#ifndef NO_OLD_TLS
+    if (!ssl->options.tls) {
+        ret = BuildMD5(ssl, hashes, sender);
+        if (ret == 0) {
+            ret = BuildSHA(ssl, hashes, sender);
+        }
+    }
+#endif
+
+    return ret;
+}
+
+#endif /* WOLFSSL_NO_TLS12 */
+
+#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
+    /* cipher requirements */
+    enum {
+        REQUIRES_RSA,
+        REQUIRES_DHE,
+        REQUIRES_ECC,
+        REQUIRES_ECC_STATIC,
+        REQUIRES_PSK,
+        REQUIRES_NTRU,
+        REQUIRES_RSA_SIG,
+        REQUIRES_AEAD
+    };
+
+
+
+    /* Does this cipher suite (first, second) have the requirement
+       an ephemeral key exchange will still require the key for signing
+       the key exchange so ECHDE_RSA requires an rsa key thus rsa_kea */
+    static int CipherRequires(byte first, byte second, int requirement)
+    {
+
+        (void)requirement;
+
+#ifndef WOLFSSL_NO_TLS12
+
+#ifdef HAVE_CHACHA
+        if (first == CHACHA_BYTE) {
+
+        switch (second) {
+        case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 :
+            if (requirement == REQUIRES_ECC)
+                return 1;
+            break;
+
+        case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            break;
+
+        case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
+            if (requirement == REQUIRES_ECC)
+                return 1;
+            break;
+
+        case TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            break;
+
+
+        case TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 :
+            if (requirement == REQUIRES_PSK)
+                return 1;
+            break;
+
+        case TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 :
+            if (requirement == REQUIRES_PSK)
+                return 1;
+            break;
+
+        case TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 :
+            if (requirement == REQUIRES_PSK)
+                return 1;
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            break;
+            }
+
+        if (requirement == REQUIRES_AEAD)
+            return 1;
+
+        }
+#endif /* HAVE_CHACHA */
+
+        /* ECC extensions */
+        if (first == ECC_BYTE) {
+
+        switch (second) {
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
+    #ifndef NO_RSA
+        case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA :
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            if (requirement == REQUIRES_RSA_SIG)
+                return 1;
+            break;
+
+    #ifndef NO_DES3
+        case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA :
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            if (requirement == REQUIRES_RSA_SIG)
+                return 1;
+            break;
+    #endif /* !NO_DES3 */
+
+    #ifndef NO_RC4
+        case TLS_ECDHE_RSA_WITH_RC4_128_SHA :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case TLS_ECDH_RSA_WITH_RC4_128_SHA :
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            if (requirement == REQUIRES_RSA_SIG)
+                return 1;
+            break;
+    #endif /* !NO_RC4 */
+    #endif /* NO_RSA */
+
+    #ifndef NO_DES3
+        case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA :
+            if (requirement == REQUIRES_ECC)
+                return 1;
+            break;
+
+        case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA :
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            break;
+    #endif /* !NO_DES3  */
+    #ifndef NO_RC4
+        case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA :
+            if (requirement == REQUIRES_ECC)
+                return 1;
+            break;
+
+        case TLS_ECDH_ECDSA_WITH_RC4_128_SHA :
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            break;
+    #endif /* !NO_RC4 */
+    #ifndef NO_RSA
+        case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA :
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            if (requirement == REQUIRES_RSA_SIG)
+                return 1;
+            break;
+    #endif /* !NO_RSA */
+
+        case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA :
+            if (requirement == REQUIRES_ECC)
+                return 1;
+            break;
+
+        case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA :
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            break;
+
+        case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA :
+            if (requirement == REQUIRES_ECC)
+                return 1;
+            break;
+
+        case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA :
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            break;
+
+        case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 :
+            if (requirement == REQUIRES_ECC)
+                return 1;
+            if (requirement == REQUIRES_AEAD)
+                return 1;
+            break;
+
+        case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 :
+            if (requirement == REQUIRES_ECC)
+                return 1;
+            if (requirement == REQUIRES_AEAD)
+                return 1;
+            break;
+
+        case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 :
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            if (requirement == REQUIRES_AEAD)
+                return 1;
+            break;
+
+        case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 :
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            if (requirement == REQUIRES_AEAD)
+                return 1;
+            break;
+#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+
+#ifndef NO_RSA
+    #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
+        case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            if (requirement == REQUIRES_AEAD)
+                return 1;
+            break;
+
+        case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            if (requirement == REQUIRES_AEAD)
+                return 1;
+            break;
+
+        case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 :
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            if (requirement == REQUIRES_RSA_SIG)
+                return 1;
+            if (requirement == REQUIRES_AEAD)
+                return 1;
+            break;
+
+        case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 :
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            if (requirement == REQUIRES_RSA_SIG)
+                return 1;
+            if (requirement == REQUIRES_AEAD)
+                return 1;
+            break;
+    #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+    #ifdef HAVE_AESCCM
+        case TLS_RSA_WITH_AES_128_CCM_8 :
+        case TLS_RSA_WITH_AES_256_CCM_8 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            if (requirement == REQUIRES_RSA_SIG)
+                return 1;
+            if (requirement == REQUIRES_AEAD)
+                return 1;
+            break;
+    #endif /* HAVE_AESCCM */
+    #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
+
+        case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 :
+        case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 :
+        case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 :
+            if (requirement == REQUIRES_RSA_SIG)
+                return 1;
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            break;
+    #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+#endif /* !NO_RSA */
+
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
+        case TLS_ECDHE_ECDSA_WITH_AES_128_CCM :
+        case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 :
+        case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 :
+            if (requirement == REQUIRES_ECC)
+                return 1;
+            if (requirement == REQUIRES_AEAD)
+                return 1;
+            break;
+
+        case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 :
+        case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 :
+            if (requirement == REQUIRES_ECC)
+                return 1;
+            break;
+
+        case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 :
+        case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 :
+            if (requirement == REQUIRES_ECC)
+                return 1;
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            break;
+#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+
+#ifndef NO_PSK
+        case TLS_PSK_WITH_AES_128_CCM:
+        case TLS_PSK_WITH_AES_256_CCM:
+        case TLS_PSK_WITH_AES_128_CCM_8:
+        case TLS_PSK_WITH_AES_256_CCM_8:
+            if (requirement == REQUIRES_PSK)
+                return 1;
+            if (requirement == REQUIRES_AEAD)
+                return 1;
+            break;
+
+        case TLS_DHE_PSK_WITH_AES_128_CCM:
+        case TLS_DHE_PSK_WITH_AES_256_CCM:
+            if (requirement == REQUIRES_PSK)
+                return 1;
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            if (requirement == REQUIRES_AEAD)
+                return 1;
+            break;
+#endif /* !NO_PSK */
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
+        case TLS_ECDHE_ECDSA_WITH_NULL_SHA :
+            if (requirement == REQUIRES_ECC)
+                return 1;
+            break;
+
+        case TLS_ECDHE_PSK_WITH_NULL_SHA256 :
+            if (requirement == REQUIRES_PSK)
+                return 1;
+            break;
+
+        case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 :
+            if (requirement == REQUIRES_PSK)
+                return 1;
+            break;
+#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+
+#if defined(WOLFSSL_TLS13) && defined(HAVE_NULL_CIPHER)
+        case TLS_SHA256_SHA256:
+            break;
+        case TLS_SHA384_SHA384:
+            break;
+#endif
+
+        default:
+            WOLFSSL_MSG("Unsupported cipher suite, CipherRequires ECC");
+            return 0;
+        }   /* switch */
+        }   /* if     */
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+        /* Distinct TLS v1.3 cipher suites with cipher and digest only. */
+        if (first == TLS13_BYTE) {
+
+            switch (second) {
+#ifdef WOLFSSL_TLS13
+            case TLS_AES_128_GCM_SHA256:
+            case TLS_AES_256_GCM_SHA384:
+            case TLS_CHACHA20_POLY1305_SHA256:
+            case TLS_AES_128_CCM_SHA256:
+            case TLS_AES_128_CCM_8_SHA256:
+                break;
+#endif
+
+            default:
+                WOLFSSL_MSG("Unsupported cipher suite, CipherRequires "
+                            "TLS v1.3");
+                return 0;
+            }
+        }
+
+#ifndef WOLFSSL_NO_TLS12
+
+        if (first != ECC_BYTE && first != CHACHA_BYTE &&
+            first != TLS13_BYTE) {   /* normal suites */
+        switch (second) {
+
+#ifndef NO_RSA
+    #ifndef NO_RC4
+        case SSL_RSA_WITH_RC4_128_SHA :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case SSL_RSA_WITH_RC4_128_MD5 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+    #endif /* NO_RC4 */
+
+        case SSL_RSA_WITH_3DES_EDE_CBC_SHA :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+    #ifdef HAVE_NTRU
+        case TLS_NTRU_RSA_WITH_RC4_128_SHA :
+            if (requirement == REQUIRES_NTRU)
+                return 1;
+            break;
+    #endif /* HAVE_NTRU */
+
+        case TLS_RSA_WITH_AES_128_CBC_SHA :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case TLS_RSA_WITH_AES_128_CBC_SHA256 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+    #ifdef HAVE_NTRU
+        case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA :
+            if (requirement == REQUIRES_NTRU)
+                return 1;
+            break;
+    #endif /* HAVE_NTRU */
+
+        case TLS_RSA_WITH_AES_256_CBC_SHA :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+    #ifdef HAVE_NTRU
+        case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA :
+            if (requirement == REQUIRES_NTRU)
+                return 1;
+            break;
+    #endif /* HAVE_NTRU */
+
+        case TLS_RSA_WITH_AES_256_CBC_SHA256 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case TLS_RSA_WITH_NULL_MD5 :
+        case TLS_RSA_WITH_NULL_SHA :
+        case TLS_RSA_WITH_NULL_SHA256 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+    #ifdef HAVE_NTRU
+        case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA :
+            if (requirement == REQUIRES_NTRU)
+                return 1;
+            break;
+    #endif /* HAVE_NTRU */
+
+    #ifdef HAVE_IDEA
+        case SSL_RSA_WITH_IDEA_CBC_SHA :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+    #endif /* HAVE_IDEA */
+#endif /* !NO_RSA */
+
+#ifndef NO_PSK
+        case TLS_PSK_WITH_AES_128_GCM_SHA256 :
+            if (requirement == REQUIRES_PSK)
+                return 1;
+            if (requirement == REQUIRES_AEAD)
+                return 1;
+            break;
+
+        case TLS_PSK_WITH_AES_256_GCM_SHA384 :
+            if (requirement == REQUIRES_PSK)
+                return 1;
+            if (requirement == REQUIRES_AEAD)
+                return 1;
+            break;
+
+        case TLS_PSK_WITH_AES_128_CBC_SHA256 :
+        case TLS_PSK_WITH_AES_256_CBC_SHA384 :
+        case TLS_PSK_WITH_AES_128_CBC_SHA :
+        case TLS_PSK_WITH_AES_256_CBC_SHA :
+        case TLS_PSK_WITH_NULL_SHA384 :
+        case TLS_PSK_WITH_NULL_SHA256 :
+        case TLS_PSK_WITH_NULL_SHA :
+            if (requirement == REQUIRES_PSK)
+                return 1;
+            break;
+
+        case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 :
+        case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 :
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            if (requirement == REQUIRES_PSK)
+                return 1;
+            if (requirement == REQUIRES_AEAD)
+                return 1;
+            break;
+
+        case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 :
+        case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 :
+        case TLS_DHE_PSK_WITH_NULL_SHA384 :
+        case TLS_DHE_PSK_WITH_NULL_SHA256 :
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            if (requirement == REQUIRES_PSK)
+                return 1;
+            break;
+#endif /* NO_PSK */
+
+#ifndef NO_RSA
+        case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            break;
+
+        case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            break;
+
+        case TLS_DHE_RSA_WITH_AES_128_CBC_SHA :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            break;
+
+        case TLS_DHE_RSA_WITH_AES_256_CBC_SHA :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            break;
+
+#ifndef NO_HC128
+        case TLS_RSA_WITH_HC_128_MD5 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case TLS_RSA_WITH_HC_128_SHA :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+#endif /* NO_HC128 */
+
+#ifndef NO_RABBIT
+        case TLS_RSA_WITH_RABBIT_SHA :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+#endif /* !NO_RABBIT */
+
+        case TLS_RSA_WITH_AES_128_GCM_SHA256 :
+        case TLS_RSA_WITH_AES_256_GCM_SHA384 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            if (requirement == REQUIRES_AEAD)
+                return 1;
+            break;
+
+        case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 :
+        case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            if (requirement == REQUIRES_AEAD)
+                return 1;
+            break;
+
+#ifdef HAVE_CAMELLIA
+        case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA :
+        case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA :
+        case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 :
+        case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA :
+        case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA :
+        case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 :
+        case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            if (requirement == REQUIRES_RSA_SIG)
+                return 1;
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            break;
+#endif /* HAVE_CAMELLIA */
+
+        case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            if (requirement == REQUIRES_RSA_SIG)
+                return 1;
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            break;
+#endif
+#ifdef HAVE_ANON
+        case TLS_DH_anon_WITH_AES_128_CBC_SHA :
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            break;
+        case TLS_DH_anon_WITH_AES_256_GCM_SHA384:
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            if (requirement == REQUIRES_AEAD)
+                return 1;
+            break;
+#endif
+#ifdef WOLFSSL_MULTICAST
+        case WDM_WITH_NULL_SHA256 :
+            break;
+#endif
+
+        default:
+            WOLFSSL_MSG("Unsupported cipher suite, CipherRequires");
+            return 0;
+        }  /* switch */
+        }  /* if ECC / Normal suites else */
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+        return 0;
+    }
+
+#endif /* !NO_WOLFSSL_SERVER && !NO_WOLFSSL_CLIENT */
+
+
+#ifndef NO_CERTS
+
+
+/* Match names with wildcards, each wildcard can represent a single name
+   component or fragment but not multiple names, i.e.,
+   *.z.com matches y.z.com but not x.y.z.com
+
+   return 1 on success */
+int MatchDomainName(const char* pattern, int len, const char* str)
+{
+    int ret = 0;
+    char p, s;
+
+    if (pattern == NULL || str == NULL || len <= 0)
+        return 0;
+
+    while (len > 0) {
+
+        p = (char)XTOLOWER((unsigned char)*pattern++);
+        if (p == '\0')
+            break;
+
+        if (p == '*') {
+            while (--len > 0 &&
+                (p = (char)XTOLOWER((unsigned char)*pattern++)) == '*') {
+            }
+
+            if (len == 0)
+                p = '\0';
+
+            while ( (s = (char)XTOLOWER((unsigned char) *str)) != '\0') {
+                if (s == p)
+                    break;
+                if (s == '.')
+                    return 0;
+                str++;
+            }
+        }
+        else {
+            if (p != (char)XTOLOWER((unsigned char) *str))
+                return 0;
+        }
+
+
+        if (len > 0) {
+            str++;
+            len--;
+        }
+    }
+
+    if (*str == '\0' && len == 0) {
+        ret = 1; /* success */
+    }
+
+    return ret;
+}
+
+
+/* try to find an altName match to domain, return 1 on success */
+int CheckAltNames(DecodedCert* dCert, char* domain)
+{
+    int        match = 0;
+    DNS_entry* altName = NULL;
+
+    WOLFSSL_MSG("Checking AltNames");
+
+    if (dCert)
+        altName = dCert->altNames;
+
+    while (altName) {
+        WOLFSSL_MSG("\tindividual AltName check");
+
+        if (MatchDomainName(altName->name, altName->len, domain)){
+            match = 1;
+            break;
+        }
+
+        altName = altName->next;
+    }
+
+    return match;
+}
+
+#ifdef OPENSSL_EXTRA
+/* Check that alternative names, if they exists, match the domain.
+ * Fail if there are wild patterns and they didn't match.
+ * Check the common name if no alternative names matched.
+ *
+ * dCert    Decoded cert to get the alternative names from.
+ * domain   Domain name to compare against.
+ * checkCN  Whether to check the common name.
+ * returns whether there was a problem in matching.
+ */
+static int CheckForAltNames(DecodedCert* dCert, char* domain, int* checkCN)
+{
+    int        match;
+    DNS_entry* altName = NULL;
+
+    WOLFSSL_MSG("Checking AltNames");
+
+    if (dCert)
+        altName = dCert->altNames;
+
+    *checkCN = altName == NULL;
+    match = 0;
+    while (altName) {
+        WOLFSSL_MSG("\tindividual AltName check");
+
+        if (MatchDomainName(altName->name, altName->len, domain)) {
+            match = 1;
+            *checkCN = 0;
+            break;
+        }
+        /* No matches and wild pattern match failed. */
+        else if (altName->name && altName->len >=1 &&
+                altName->name[0] == '*' && match == 0) {
+            match = -1;
+        }
+
+        altName = altName->next;
+    }
+
+    return match != -1;
+}
+
+/* Check the domain name matches the subject alternative name or the subject
+ * name.
+ *
+ * dcert          Decoded certificate.
+ * domainName     The domain name.
+ * domainNameLen  The length of the domain name.
+ * returns DOMAIN_NAME_MISMATCH when no match found and 0 on success.
+ */
+int CheckHostName(DecodedCert* dCert, char *domainName, size_t domainNameLen)
+{
+    int checkCN;
+
+    /* Assume name is NUL terminated. */
+    (void)domainNameLen;
+
+    if (CheckForAltNames(dCert, domainName, &checkCN) == 0) {
+        WOLFSSL_MSG("DomainName match on alt names failed too");
+        return DOMAIN_NAME_MISMATCH;
+    }
+    if (checkCN == 1) {
+        if (MatchDomainName(dCert->subjectCN, dCert->subjectCNLen,
+                            domainName) == 0) {
+            WOLFSSL_MSG("DomainName match on common name failed");
+            return DOMAIN_NAME_MISMATCH;
+        }
+    }
+
+    return 0;
+}
+
+int CheckIPAddr(DecodedCert* dCert, char* ipasc)
+{
+    WOLFSSL_MSG("Checking IPAddr");
+
+    return CheckHostName(dCert, ipasc, (size_t)XSTRLEN(ipasc));
+}
+#endif
+
+#ifdef SESSION_CERTS
+static void AddSessionCertToChain(WOLFSSL_X509_CHAIN* chain,
+    byte* certBuf, word32 certSz)
+{
+   if (chain->count < MAX_CHAIN_DEPTH &&
+                               certSz < MAX_X509_SIZE) {
+        chain->certs[chain->count].length = certSz;
+        XMEMCPY(chain->certs[chain->count].buffer, certBuf, certSz);
+        chain->count++;
+    }
+    else {
+        WOLFSSL_MSG("Couldn't store chain cert for session");
+    }
+}
+#endif
+
+#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) || \
+    defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+/* Copy parts X509 needs from Decoded cert, 0 on success */
+/* The same DecodedCert cannot be copied to WOLFSSL_X509 twice otherwise the
+ * altNames pointers could be free'd by second x509 still active by first */
+int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
+{
+    int ret = 0;
+
+    if (x509 == NULL || dCert == NULL ||
+        dCert->subjectCNLen < 0)
+        return BAD_FUNC_ARG;
+
+    x509->version = dCert->version + 1;
+
+    XSTRNCPY(x509->issuer.name, dCert->issuer, ASN_NAME_MAX);
+    x509->issuer.name[ASN_NAME_MAX - 1] = '\0';
+    x509->issuer.sz = (int)XSTRLEN(x509->issuer.name) + 1;
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+    if (dCert->issuerName.fullName != NULL) {
+        XMEMCPY(&x509->issuer.fullName,
+                                       &dCert->issuerName, sizeof(DecodedName));
+        x509->issuer.fullName.fullName = (char*)XMALLOC(
+                        dCert->issuerName.fullNameLen, x509->heap,
+                        DYNAMIC_TYPE_X509);
+        if (x509->issuer.fullName.fullName != NULL)
+            XMEMCPY(x509->issuer.fullName.fullName,
+                     dCert->issuerName.fullName, dCert->issuerName.fullNameLen);
+    }
+    x509->issuer.x509 = x509;
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+
+    XSTRNCPY(x509->subject.name, dCert->subject, ASN_NAME_MAX);
+    x509->subject.name[ASN_NAME_MAX - 1] = '\0';
+    x509->subject.sz = (int)XSTRLEN(x509->subject.name) + 1;
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+    if (dCert->subjectName.fullName != NULL) {
+        XMEMCPY(&x509->subject.fullName,
+                                      &dCert->subjectName, sizeof(DecodedName));
+        x509->subject.fullName.fullName = (char*)XMALLOC(
+                 dCert->subjectName.fullNameLen, x509->heap, DYNAMIC_TYPE_X509);
+        if (x509->subject.fullName.fullName != NULL)
+            XMEMCPY(x509->subject.fullName.fullName,
+                   dCert->subjectName.fullName, dCert->subjectName.fullNameLen);
+    }
+    x509->subject.x509 = x509;
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+    x509->subject.rawLen = min(dCert->subjectRawLen, sizeof(x509->subject.raw));
+    XMEMCPY(x509->subject.raw, dCert->subjectRaw, x509->subject.rawLen);
+#ifdef WOLFSSL_CERT_EXT
+    x509->issuer.rawLen = min(dCert->issuerRawLen, sizeof(x509->issuer.raw));
+    XMEMCPY(x509->issuer.raw, dCert->issuerRaw, x509->issuer.rawLen);
+#endif
+#endif
+
+    XMEMCPY(x509->serial, dCert->serial, EXTERNAL_SERIAL_SIZE);
+    x509->serialSz = dCert->serialSz;
+    if (dCert->subjectCN && dCert->subjectCNLen < ASN_NAME_MAX) {
+        XMEMCPY(x509->subjectCN, dCert->subjectCN, dCert->subjectCNLen);
+        x509->subjectCN[dCert->subjectCNLen] = '\0';
+    }
+    else
+        x509->subjectCN[0] = '\0';
+
+#ifdef WOLFSSL_SEP
+    {
+        int minSz = min(dCert->deviceTypeSz, EXTERNAL_SERIAL_SIZE);
+        if (minSz > 0) {
+            x509->deviceTypeSz = minSz;
+            XMEMCPY(x509->deviceType, dCert->deviceType, minSz);
+        }
+        else
+            x509->deviceTypeSz = 0;
+        minSz = min(dCert->hwTypeSz, EXTERNAL_SERIAL_SIZE);
+        if (minSz > 0) {
+            x509->hwTypeSz = minSz;
+            XMEMCPY(x509->hwType, dCert->hwType, minSz);
+        }
+        else
+            x509->hwTypeSz = 0;
+        minSz = min(dCert->hwSerialNumSz, EXTERNAL_SERIAL_SIZE);
+        if (minSz > 0) {
+            x509->hwSerialNumSz = minSz;
+            XMEMCPY(x509->hwSerialNum, dCert->hwSerialNum, minSz);
+        }
+        else
+            x509->hwSerialNumSz = 0;
+    }
+#endif /* WOLFSSL_SEP */
+    {
+        int minSz;
+        if (dCert->beforeDateLen > 0) {
+            minSz = min(dCert->beforeDate[1], MAX_DATE_SZ);
+            x509->notBefore.type = dCert->beforeDate[0];
+            x509->notBefore.length = minSz;
+            XMEMCPY(x509->notBefore.data, &dCert->beforeDate[2], minSz);
+        }
+        else
+            x509->notBefore.length = 0;
+        if (dCert->afterDateLen > 0) {
+            minSz = min(dCert->afterDate[1], MAX_DATE_SZ);
+            x509->notAfter.type = dCert->afterDate[0];
+            x509->notAfter.length = minSz;
+            XMEMCPY(x509->notAfter.data, &dCert->afterDate[2], minSz);
+        }
+        else
+            x509->notAfter.length = 0;
+    }
+
+    if (dCert->publicKey != NULL && dCert->pubKeySize != 0) {
+        x509->pubKey.buffer = (byte*)XMALLOC(
+                        dCert->pubKeySize, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        if (x509->pubKey.buffer != NULL) {
+            x509->pubKeyOID = dCert->keyOID;
+            x509->pubKey.length = dCert->pubKeySize;
+            XMEMCPY(x509->pubKey.buffer, dCert->publicKey, dCert->pubKeySize);
+        }
+        else
+            ret = MEMORY_E;
+#if defined(OPENSSL_ALL)
+        if (ret == 0) {
+            x509->key.pubKeyOID = dCert->keyOID;
+
+            if (!x509->key.algor) {
+                x509->key.algor = wolfSSL_X509_ALGOR_new();
+            } else {
+                wolfSSL_ASN1_OBJECT_free(x509->key.algor->algorithm);
+            }
+            if (!(x509->key.algor->algorithm =
+                    wolfSSL_OBJ_nid2obj(dCert->keyOID))) {
+                ret = PUBLIC_KEY_E;
+            }
+
+            wolfSSL_EVP_PKEY_free(x509->key.pkey);
+            if (!(x509->key.pkey = wolfSSL_d2i_PUBKEY(NULL,
+                                                      &dCert->publicKey,
+                                                      dCert->pubKeySize))) {
+                ret = PUBLIC_KEY_E;
+            }
+        }
+#endif
+    }
+
+    if (dCert->signature != NULL && dCert->sigLength != 0 &&
+            dCert->sigLength <= MAX_ENCODED_SIG_SZ) {
+        x509->sig.buffer = (byte*)XMALLOC(
+                          dCert->sigLength, x509->heap, DYNAMIC_TYPE_SIGNATURE);
+        if (x509->sig.buffer == NULL) {
+            ret = MEMORY_E;
+        }
+        else {
+            XMEMCPY(x509->sig.buffer, dCert->signature, dCert->sigLength);
+            x509->sig.length = dCert->sigLength;
+            x509->sigOID = dCert->signatureOID;
+        }
+#if defined(OPENSSL_ALL)
+        wolfSSL_ASN1_OBJECT_free(x509->algor.algorithm);
+        if (!(x509->algor.algorithm =
+                wolfSSL_OBJ_nid2obj(dCert->signatureOID))) {
+            ret = PUBLIC_KEY_E;
+        }
+#endif
+    }
+
+    /* store cert for potential retrieval */
+    if (AllocDer(&x509->derCert, dCert->maxIdx, CERT_TYPE, x509->heap) == 0) {
+        XMEMCPY(x509->derCert->buffer, dCert->source, dCert->maxIdx);
+    }
+    else {
+        ret = MEMORY_E;
+    }
+
+    x509->altNames       = dCert->altNames;
+    dCert->weOwnAltNames = 0;
+    x509->altNamesNext   = x509->altNames;  /* index hint */
+
+#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+    !defined(IGNORE_NAME_CONSTRAINTS)
+    /* add copies of alternate emails from dCert to X509 */
+    if (dCert->altEmailNames != NULL) {
+        DNS_entry* cur = dCert->altEmailNames;
+
+        while (cur != NULL) {
+            if (cur->type == ASN_RFC822_TYPE) {
+                DNS_entry* dnsEntry;
+                int strLen = cur->len;
+
+                dnsEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), x509->heap,
+                                        DYNAMIC_TYPE_ALTNAME);
+                if (dnsEntry == NULL) {
+                    WOLFSSL_MSG("\tOut of Memory");
+                    return MEMORY_E;
+                }
+
+                dnsEntry->type = ASN_RFC822_TYPE;
+                dnsEntry->name = (char*)XMALLOC(strLen + 1, x509->heap,
+                                         DYNAMIC_TYPE_ALTNAME);
+                if (dnsEntry->name == NULL) {
+                    WOLFSSL_MSG("\tOut of Memory");
+                    XFREE(dnsEntry, x509->heap, DYNAMIC_TYPE_ALTNAME);
+                    return MEMORY_E;
+                }
+                dnsEntry->len = strLen;
+                XMEMCPY(dnsEntry->name, cur->name, strLen);
+                dnsEntry->name[strLen] = '\0';
+
+                dnsEntry->next = x509->altNames;
+                x509->altNames = dnsEntry;
+            }
+            cur = cur->next;
+        }
+    }
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+
+    x509->isCa = dCert->isCA;
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+    x509->pathLength = dCert->pathLength;
+    x509->keyUsage = dCert->extKeyUsage;
+
+    x509->CRLdistSet = dCert->extCRLdistSet;
+    x509->CRLdistCrit = dCert->extCRLdistCrit;
+    x509->CRLInfo = dCert->extCrlInfo;
+    x509->CRLInfoSz = dCert->extCrlInfoSz;
+    x509->authInfoSet = dCert->extAuthInfoSet;
+    x509->authInfoCrit = dCert->extAuthInfoCrit;
+    if (dCert->extAuthInfo != NULL && dCert->extAuthInfoSz > 0) {
+        x509->authInfo = (byte*)XMALLOC(dCert->extAuthInfoSz, x509->heap,
+                DYNAMIC_TYPE_X509_EXT);
+        if (x509->authInfo != NULL) {
+            XMEMCPY(x509->authInfo, dCert->extAuthInfo, dCert->extAuthInfoSz);
+            x509->authInfoSz = dCert->extAuthInfoSz;
+        }
+        else {
+            ret = MEMORY_E;
+        }
+    }
+    #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+    if (dCert->extAuthInfoCaIssuer != NULL && dCert->extAuthInfoCaIssuerSz > 0) {
+        x509->authInfoCaIssuer = (byte*)XMALLOC(dCert->extAuthInfoCaIssuerSz, x509->heap,
+                DYNAMIC_TYPE_X509_EXT);
+        if (x509->authInfoCaIssuer != NULL) {
+            XMEMCPY(x509->authInfoCaIssuer, dCert->extAuthInfoCaIssuer, dCert->extAuthInfoCaIssuerSz);
+            x509->authInfoCaIssuerSz = dCert->extAuthInfoCaIssuerSz;
+        }
+        else {
+            ret = MEMORY_E;
+        }
+    }
+    #endif
+    x509->basicConstSet = dCert->extBasicConstSet;
+    x509->basicConstCrit = dCert->extBasicConstCrit;
+    x509->basicConstPlSet = dCert->pathLengthSet;
+    x509->subjAltNameSet = dCert->extSubjAltNameSet;
+    x509->subjAltNameCrit = dCert->extSubjAltNameCrit;
+    x509->authKeyIdSet = dCert->extAuthKeyIdSet;
+    x509->authKeyIdCrit = dCert->extAuthKeyIdCrit;
+    if (dCert->extAuthKeyIdSrc != NULL && dCert->extAuthKeyIdSz != 0) {
+        x509->authKeyId = (byte*)XMALLOC(dCert->extAuthKeyIdSz, x509->heap,
+                                         DYNAMIC_TYPE_X509_EXT);
+        if (x509->authKeyId != NULL) {
+            XMEMCPY(x509->authKeyId,
+                                 dCert->extAuthKeyIdSrc, dCert->extAuthKeyIdSz);
+            x509->authKeyIdSz = dCert->extAuthKeyIdSz;
+        }
+        else
+            ret = MEMORY_E;
+    }
+    x509->subjKeyIdSet = dCert->extSubjKeyIdSet;
+    x509->subjKeyIdCrit = dCert->extSubjKeyIdCrit;
+    if (dCert->extSubjKeyIdSrc != NULL && dCert->extSubjKeyIdSz != 0) {
+        x509->subjKeyId = (byte*)XMALLOC(dCert->extSubjKeyIdSz, x509->heap,
+                                         DYNAMIC_TYPE_X509_EXT);
+        if (x509->subjKeyId != NULL) {
+            XMEMCPY(x509->subjKeyId,
+                                 dCert->extSubjKeyIdSrc, dCert->extSubjKeyIdSz);
+            x509->subjKeyIdSz = dCert->extSubjKeyIdSz;
+        }
+        else
+            ret = MEMORY_E;
+    }
+    x509->keyUsageSet = dCert->extKeyUsageSet;
+    x509->keyUsageCrit = dCert->extKeyUsageCrit;
+    if (dCert->extExtKeyUsageSrc != NULL && dCert->extExtKeyUsageSz > 0) {
+        x509->extKeyUsageSrc = (byte*)XMALLOC(dCert->extExtKeyUsageSz,
+                x509->heap, DYNAMIC_TYPE_X509_EXT);
+        if (x509->extKeyUsageSrc != NULL) {
+            XMEMCPY(x509->extKeyUsageSrc, dCert->extExtKeyUsageSrc,
+                                                       dCert->extExtKeyUsageSz);
+            x509->extKeyUsageSz    = dCert->extExtKeyUsageSz;
+            x509->extKeyUsageCrit  = dCert->extExtKeyUsageCrit;
+            x509->extKeyUsageCount = dCert->extExtKeyUsageCount;
+        }
+        else {
+            ret = MEMORY_E;
+        }
+    }
+    #if defined(WOLFSSL_SEP) || defined(WOLFSSL_QT)
+        x509->certPolicySet = dCert->extCertPolicySet;
+        x509->certPolicyCrit = dCert->extCertPolicyCrit;
+    #endif /* WOLFSSL_SEP || WOLFSSL_QT */
+    #ifdef WOLFSSL_CERT_EXT
+        {
+            int i;
+            for (i = 0; i < dCert->extCertPoliciesNb && i < MAX_CERTPOL_NB; i++)
+                XMEMCPY(x509->certPolicies[i], dCert->extCertPolicies[i],
+                                                                MAX_CERTPOL_SZ);
+            x509->certPoliciesNb = dCert->extCertPoliciesNb;
+        }
+    #endif /* WOLFSSL_CERT_EXT */
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
+    x509->pkCurveOID = dCert->pkCurveOID;
+#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+
+    return ret;
+}
+
+#endif /* KEEP_PEER_CERT || SESSION_CERTS */
+
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
+     (defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) && !defined(WOLFSSL_NO_TLS12))
+static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+                      word32 status_length)
+{
+    int ret = 0;
+    OcspRequest* request;
+
+    #ifdef WOLFSSL_SMALL_STACK
+        CertStatus* status;
+        OcspResponse* response;
+    #else
+        CertStatus status[1];
+        OcspResponse response[1];
+    #endif
+
+    do {
+        #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+            if (ssl->status_request) {
+                request = (OcspRequest*)TLSX_CSR_GetRequest(ssl->extensions);
+                ssl->status_request = 0;
+                break;
+            }
+        #endif
+
+        #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+            if (ssl->status_request_v2) {
+                request = (OcspRequest*)TLSX_CSR2_GetRequest(ssl->extensions,
+                                                          WOLFSSL_CSR2_OCSP, 0);
+                ssl->status_request_v2 = 0;
+                break;
+            }
+        #endif
+
+        return BUFFER_ERROR;
+    } while(0);
+
+    if (request == NULL)
+        return BAD_CERTIFICATE_STATUS_ERROR; /* not expected */
+
+    #ifdef WOLFSSL_SMALL_STACK
+        status = (CertStatus*)XMALLOC(sizeof(CertStatus), ssl->heap,
+                                                      DYNAMIC_TYPE_OCSP_STATUS);
+        response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), ssl->heap,
+                                                     DYNAMIC_TYPE_OCSP_REQUEST);
+
+        if (status == NULL || response == NULL) {
+            if (status)
+                XFREE(status, NULL, DYNAMIC_TYPE_OCSP_STATUS);
+            if (response)
+                XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
+
+            return MEMORY_ERROR;
+        }
+    #endif
+
+    InitOcspResponse(response, status, input +*inOutIdx, status_length);
+
+    if (OcspResponseDecode(response, ssl->ctx->cm, ssl->heap, 0) != 0)
+        ret = BAD_CERTIFICATE_STATUS_ERROR;
+    else if (CompareOcspReqResp(request, response) != 0)
+        ret = BAD_CERTIFICATE_STATUS_ERROR;
+    else if (response->responseStatus != OCSP_SUCCESSFUL)
+        ret = BAD_CERTIFICATE_STATUS_ERROR;
+    else if (response->status->status == CERT_REVOKED)
+        ret = OCSP_CERT_REVOKED;
+    else if (response->status->status != CERT_GOOD)
+        ret = BAD_CERTIFICATE_STATUS_ERROR;
+
+    *inOutIdx += status_length;
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(status,   ssl->heap, DYNAMIC_TYPE_OCSP_STATUS);
+        XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+    #endif
+
+    return ret;
+}
+#endif
+
+
+
+#ifdef HAVE_PK_CALLBACKS
+
+#ifdef HAVE_ECC
+    static int SigPkCbEccVerify(const unsigned char* sig, unsigned int sigSz,
+       const unsigned char* hash, unsigned int hashSz,
+       const unsigned char* keyDer, unsigned int keySz,
+       int* result, void* ctx)
+    {
+        int ret = NOT_COMPILED_IN;
+        WOLFSSL* ssl = (WOLFSSL*)ctx;
+
+        if (ssl && ssl->ctx->EccVerifyCb) {
+            ret = ssl->ctx->EccVerifyCb(ssl, sig, sigSz, hash, hashSz,
+                keyDer, keySz, result, ssl->EccVerifyCtx);
+        }
+        return ret;
+    }
+#endif
+#ifndef NO_RSA
+    static int SigPkCbRsaVerify(unsigned char* sig, unsigned int sigSz,
+       unsigned char** out, const unsigned char* keyDer, unsigned int keySz,
+       void* ctx)
+    {
+        int ret = NOT_COMPILED_IN;
+        WOLFSSL* ssl = (WOLFSSL*)ctx;
+
+        if (ssl && ssl->ctx->RsaVerifyCb) {
+            ret = ssl->ctx->RsaVerifyCb(ssl, sig, sigSz, out, keyDer, keySz,
+                ssl->RsaVerifyCtx);
+        }
+        return ret;
+    }
+#endif
+
+int InitSigPkCb(WOLFSSL* ssl, SignatureCtx* sigCtx)
+{
+    if (ssl == NULL || sigCtx == NULL)
+        return BAD_FUNC_ARG;
+
+    /* only setup the verify callback if a PK is set */
+#ifdef HAVE_ECC
+    if (ssl->ctx->EccVerifyCb) {
+        sigCtx->pkCbEcc = SigPkCbEccVerify;
+        sigCtx->pkCtxEcc = ssl;
+    }
+#endif
+#ifndef NO_RSA
+    /* only setup the verify callback if a PK is set */
+    if (ssl->ctx->RsaVerifyCb) {
+        sigCtx->pkCbRsa = SigPkCbRsaVerify;
+        sigCtx->pkCtxRsa = ssl;
+    }
+#endif
+
+    return 0;
+}
+
+#endif /* HAVE_PK_CALLBACKS */
+
+
+#if !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)
+static void DoCertFatalAlert(WOLFSSL* ssl, int ret)
+{
+    int alertWhy;
+    if (ssl == NULL || ret == 0) {
+        return;
+    }
+
+    /* Determine alert reason */
+    alertWhy = bad_certificate;
+    if (ret == ASN_AFTER_DATE_E || ret == ASN_BEFORE_DATE_E) {
+        alertWhy = certificate_expired;
+    }
+#if (defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD))
+    else if (ret == CRL_CERT_REVOKED) {
+        alertWhy = certificate_revoked;
+    }
+#endif
+    else if (ret == NO_PEER_CERT) {
+#ifdef WOLFSSL_TLS13
+        if (ssl->options.tls1_3) {
+            alertWhy = certificate_required;
+        }
+        else
+#endif
+        {
+            alertWhy = handshake_failure;
+        }
+    }
+
+    /* send fatal alert and mark connection closed */
+    SendAlert(ssl, alert_fatal, alertWhy); /* try to send */
+    ssl->options.isClosed = 1;
+}
+
+/* WOLFSSL_ALWAYS_VERIFY_CB: Use verify callback for success or failure cases */
+/* WOLFSSL_VERIFY_CB_ALL_CERTS: Issue callback for all intermediate certificates */
+
+/* Callback is issued for certificate presented in TLS Certificate (11) packet.
+ * The intermediates are done first then peer leaf cert last. Use the
+ * store->error_depth member to determine index (0=peer, >1 intermediates)
+ */
+
+int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret,
+                                                        ProcPeerCertArgs* args)
+{
+    int verify_ok = 0, use_cb = 0;
+    void *heap = (ssl != NULL) ? ssl->heap : cm->heap;
+
+    /* Determine if verify was okay */
+    if (ret == 0) {
+        verify_ok = 1;
+    }
+
+    /* Determine if verify callback should be used */
+    if (ret != 0) {
+        if ((ssl != NULL) && (!ssl->options.verifyNone)) {
+            use_cb = 1; /* always report errors */
+        }
+    }
+#ifdef WOLFSSL_ALWAYS_VERIFY_CB
+    /* always use verify callback on peer leaf cert */
+    if (args->certIdx == 0) {
+        use_cb = 1;
+    }
+#endif
+#ifdef WOLFSSL_VERIFY_CB_ALL_CERTS
+    /* perform verify callback on other intermediate certs (not just peer) */
+    if (args->certIdx > 0) {
+        use_cb = 1;
+    }
+#endif
+#if defined(OPENSSL_EXTRA)
+    /* perform domain name check on the peer certificate */
+    if (args->dCertInit && args->dCert && (ssl != NULL) &&
+            ssl->param && ssl->param->hostName[0]) {
+        /* If altNames names is present, then subject common name is ignored */
+        if (args->dCert->altNames != NULL) {
+            if (CheckAltNames(args->dCert, ssl->param->hostName) == 0 ) {
+                if (ret == 0) {
+                    ret = DOMAIN_NAME_MISMATCH;
+                }
+            }
+        }
+        else {
+            if (args->dCert->subjectCN) {
+                if (MatchDomainName(args->dCert->subjectCN,
+                                    args->dCert->subjectCNLen,
+                                    ssl->param->hostName) == 0) {
+                    if (ret == 0) {
+                        ret = DOMAIN_NAME_MISMATCH;
+                    }
+                }
+            }
+        }
+    }
+
+    /* perform IP address check on the peer certificate */
+    if ((args->dCertInit != 0) && (args->dCert != NULL) && (ssl != NULL) &&
+        (ssl->param != NULL) && (XSTRLEN(ssl->param->ipasc) > 0)) {
+        if (CheckIPAddr(args->dCert, ssl->param->ipasc) != 0) {
+            if (ret == 0) {
+                ret = IPADDR_MISMATCH;
+            }
+        }
+    }
+#endif
+    /* if verify callback has been set */
+    if ((use_cb && (ssl != NULL) && ((ssl->verifyCallback != NULL)
+    #ifdef OPENSSL_ALL
+        || (ssl->ctx->verifyCertCb != NULL)
+    #endif
+        ))
+    #ifndef NO_WOLFSSL_CM_VERIFY
+        || (cm->verifyCallback != NULL)
+    #endif
+        ) {
+        int verifyFail = 0;
+    #ifdef WOLFSSL_SMALL_STACK
+        WOLFSSL_X509_STORE_CTX* store;
+        #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+        WOLFSSL_X509* x509;
+        #endif
+        char* domain = NULL;
+    #else
+        WOLFSSL_X509_STORE_CTX store[1];
+        #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+        WOLFSSL_X509           x509[1];
+        #endif
+        char domain[ASN_NAME_MAX];
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        store = (WOLFSSL_X509_STORE_CTX*)XMALLOC(
+            sizeof(WOLFSSL_X509_STORE_CTX), heap, DYNAMIC_TYPE_X509_STORE);
+        if (store == NULL) {
+            return MEMORY_E;
+        }
+        #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+        x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap,
+            DYNAMIC_TYPE_X509);
+        if (x509 == NULL) {
+            XFREE(store, heap, DYNAMIC_TYPE_X509);
+            return MEMORY_E;
+        }
+        #endif
+        domain = (char*)XMALLOC(ASN_NAME_MAX, heap, DYNAMIC_TYPE_STRING);
+        if (domain == NULL) {
+            XFREE(store, heap, DYNAMIC_TYPE_X509);
+            #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+            XFREE(x509, heap, DYNAMIC_TYPE_X509);
+            #endif
+            return MEMORY_E;
+        }
+    #endif /* WOLFSSL_SMALL_STACK */
+
+        XMEMSET(store, 0, sizeof(WOLFSSL_X509_STORE_CTX));
+    #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+        XMEMSET(x509, 0, sizeof(WOLFSSL_X509));
+    #endif
+        domain[0] = '\0';
+
+        /* build subject CN as string to return in store */
+        if (args->dCertInit && args->dCert && args->dCert->subjectCN) {
+            int subjectCNLen = args->dCert->subjectCNLen;
+            if (subjectCNLen > ASN_NAME_MAX-1)
+                subjectCNLen = ASN_NAME_MAX-1;
+            if (subjectCNLen > 0) {
+                XMEMCPY(domain, args->dCert->subjectCN, subjectCNLen);
+                domain[subjectCNLen] = '\0';
+            }
+        }
+
+        store->error = ret;
+        store->error_depth = args->certIdx;
+        store->discardSessionCerts = 0;
+        store->domain = domain;
+        store->userCtx = (ssl != NULL) ? ssl->verifyCbCtx : cm;
+        store->certs = args->certs;
+        store->totalCerts = args->totalCerts;
+    #if defined(HAVE_EX_DATA) || defined(FORTRESS)
+        if (wolfSSL_CRYPTO_set_ex_data(&store->ex_data, 0, ssl)
+                != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("Failed to store ssl context in WOLFSSL_X509_STORE_CTX");
+        }
+    #endif
+
+        if (ssl != NULL) {
+    #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+            if (ssl->ctx->x509_store_pt != NULL) {
+                store->store = ssl->ctx->x509_store_pt;
+            }
+            else {
+                store->store = &ssl->ctx->x509_store;
+            }
+    #if defined(OPENSSL_EXTRA)
+            store->depth = args->count;
+            store->param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC(
+                            sizeof(WOLFSSL_X509_VERIFY_PARAM),
+                            heap, DYNAMIC_TYPE_OPENSSL);
+            if (store->param == NULL) {
+        #ifdef WOLFSSL_SMALL_STACK
+                XFREE(domain, heap, DYNAMIC_TYPE_STRING);
+            #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                XFREE(x509, heap, DYNAMIC_TYPE_X509);
+            #endif
+                XFREE(store, heap, DYNAMIC_TYPE_X509_STORE);
+        #endif
+                return MEMORY_E;
+            }
+            XMEMSET(store->param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM));
+            /* Overwrite with non-default param values in SSL */
+            if (ssl->param) {
+                if (ssl->param->check_time)
+                    store->param->check_time = ssl->param->check_time;
+
+                if (ssl->param->flags)
+                    store->param->flags = ssl->param->flags;
+
+                if (ssl->param->hostName[0])
+                    XMEMCPY(store->param->hostName, ssl->param->hostName,
+                            WOLFSSL_HOST_NAME_MAX);
+
+            }
+    #endif /* defined(OPENSSL_EXTRA) */
+    #endif /* defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)*/
+    #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+        #ifdef KEEP_PEER_CERT
+            if (args->certIdx == 0) {
+                store->current_cert = &ssl->peerCert; /* use existing X509 */
+            }
+            else
+        #endif
+            {
+                InitX509(x509, 0, heap);
+                if (CopyDecodedToX509(x509, args->dCert) == 0) {
+                    store->current_cert = x509;
+                }
+                else {
+                    FreeX509(x509);
+                }
+            }
+    #endif
+    #ifdef SESSION_CERTS
+            store->sesChain = &ssl->session.chain;
+    #endif
+        }
+    #ifndef NO_WOLFSSL_CM_VERIFY
+        /* non-zero return code indicates failure override */
+        if ((cm != NULL) && (cm->verifyCallback != NULL)) {
+            store->userCtx = cm;
+            if (cm->verifyCallback(verify_ok, store)) {
+                if (ret != 0) {
+                    WOLFSSL_MSG("Verify CM callback overriding error!");
+                    ret = 0;
+                }
+            }
+            else {
+                verifyFail = 1;
+            }
+        }
+    #endif
+
+        if (ssl != NULL) {
+    #ifdef OPENSSL_ALL
+            /* non-zero return code indicates failure override */
+            if (ssl->ctx->verifyCertCb) {
+                if (ssl->ctx->verifyCertCb(store, ssl->ctx->verifyCertCbArg)) {
+                    if (ret != 0) {
+                        WOLFSSL_MSG("Verify Cert callback overriding error!");
+                        ret = 0;
+                    }
+                }
+                else {
+                    verifyFail = 1;
+                }
+            }
+    #endif
+
+            /* non-zero return code indicates failure override */
+            if (ssl->verifyCallback) {
+                if (ssl->verifyCallback(verify_ok, store)) {
+                    if (ret != 0) {
+                        WOLFSSL_MSG("Verify callback overriding error!");
+                        ret = 0;
+                    }
+                }
+                else {
+                    verifyFail = 1;
+                }
+            }
+        }
+
+        if (verifyFail) {
+            /* induce error if one not present */
+            if (ret == 0) {
+                ret = VERIFY_CERT_ERROR;
+            }
+
+            /* mark as verify error */
+            args->verifyErr = 1;
+        }
+    #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+        if (args->certIdx > 0)
+            FreeX509(x509);
+    #endif
+    #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
+        wolfSSL_sk_X509_free(store->chain);
+        store->chain = NULL;
+    #endif
+    #ifdef SESSION_CERTS
+        if ((ssl != NULL) && (store->discardSessionCerts)) {
+            WOLFSSL_MSG("Verify callback requested discard sess certs");
+            ssl->session.chain.count = 0;
+        #ifdef WOLFSSL_ALT_CERT_CHAINS
+            ssl->session.altChain.count = 0;
+        #endif
+        }
+    #endif /* SESSION_CERTS */
+#ifdef OPENSSL_EXTRA
+        if ((ssl != NULL) && (store->param)) {
+            XFREE(store->param, heap, DYNAMIC_TYPE_OPENSSL);
+        }
+#endif
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(domain, heap, DYNAMIC_TYPE_STRING);
+        #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+        XFREE(x509, heap, DYNAMIC_TYPE_X509);
+        #endif
+        XFREE(store, heap, DYNAMIC_TYPE_X509_STORE);
+    #endif
+    }
+
+    (void)heap;
+
+    return ret;
+}
+
+static void FreeProcPeerCertArgs(WOLFSSL* ssl, void* pArgs)
+{
+    ProcPeerCertArgs* args = (ProcPeerCertArgs*)pArgs;
+
+    (void)ssl;
+
+    if (args->certs) {
+        XFREE(args->certs, ssl->heap, DYNAMIC_TYPE_DER);
+        args->certs = NULL;
+    }
+#ifdef WOLFSSL_TLS13
+    if (args->exts) {
+        XFREE(args->exts, ssl->heap, DYNAMIC_TYPE_CERT_EXT);
+        args->exts = NULL;
+    }
+#endif
+    if (args->dCert) {
+        if (args->dCertInit) {
+            FreeDecodedCert(args->dCert);
+            args->dCertInit = 0;
+        }
+        XFREE(args->dCert, ssl->heap, DYNAMIC_TYPE_DCERT);
+        args->dCert = NULL;
+    }
+}
+
+static int ProcessPeerCertParse(WOLFSSL* ssl, ProcPeerCertArgs* args,
+    int certType, int verify, byte** pSubjectHash, int* pAlreadySigner)
+{
+    int ret = 0;
+    buffer* cert;
+    byte* subjectHash = NULL;
+    int alreadySigner = 0;
+#ifdef WOLFSSL_SMALL_CERT_VERIFY
+    int sigRet = 0;
+#endif
+
+    if (ssl == NULL || args == NULL)
+        return BAD_FUNC_ARG;
+
+    /* check to make sure certificate index is valid */
+    if (args->certIdx > args->count)
+        return BUFFER_E;
+
+    /* check if returning from non-blocking OCSP */
+    /* skip this section because cert is already initialized and parsed */
+#ifdef WOLFSSL_NONBLOCK_OCSP
+    if (args->lastErr == OCSP_WANT_READ) {
+        args->lastErr = 0; /* clear error */
+        return 0;
+    }
+#endif
+
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    /* we have trusted peer */
+    if (args->haveTrustPeer) {
+        return 0;
+    }
+#endif
+
+    /* get certificate buffer */
+    cert = &args->certs[args->certIdx];
+
+#ifdef WOLFSSL_SMALL_CERT_VERIFY
+    if (verify == VERIFY) {
+        /* for small cert verify, release decoded cert during signature check to
+            reduce peak memory usage */
+        if (args->dCert != NULL) {
+            if (args->dCertInit) {
+                FreeDecodedCert(args->dCert);
+                args->dCertInit = 0;
+            }
+            XFREE(args->dCert, ssl->heap, DYNAMIC_TYPE_DCERT);
+            args->dCert = NULL;
+        }
+
+        /* perform cert parsing and signature check */
+        sigRet = CheckCertSignature(cert->buffer, cert->length,
+                                         ssl->heap, ssl->ctx->cm);
+        /* fail on errors here after the ParseCertRelative call, so dCert is populated */
+
+        /* verify name only in ParseCertRelative below, signature check done */
+        verify = VERIFY_NAME;
+    }
+#endif /* WOLFSSL_SMALL_CERT_VERIFY */
+
+    /* make sure the decoded cert structure is allocated and initialized */
+    if (!args->dCertInit
+    #ifdef WOLFSSL_SMALL_CERT_VERIFY
+        || args->dCert == NULL
+    #endif
+    ) {
+    #ifdef WOLFSSL_SMALL_CERT_VERIFY
+        if (args->dCert == NULL) {
+            args->dCert = (DecodedCert*)XMALLOC(
+                                 sizeof(DecodedCert), ssl->heap,
+                                 DYNAMIC_TYPE_DCERT);
+            if (args->dCert == NULL) {
+                return MEMORY_E;
+            }
+        }
+    #endif
+
+        InitDecodedCert(args->dCert, cert->buffer, cert->length, ssl->heap);
+
+        args->dCertInit = 1;
+        args->dCert->sigCtx.devId = ssl->devId;
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        args->dCert->sigCtx.asyncCtx = ssl;
+    #endif
+
+    #ifdef HAVE_PK_CALLBACKS
+        /* setup the PK callback context */
+        ret = InitSigPkCb(ssl, &args->dCert->sigCtx);
+        if (ret != 0)
+            return ret;
+    #endif
+    }
+
+    /* Parse Certificate */
+    ret = ParseCertRelative(args->dCert, certType, verify, ssl->ctx->cm);
+    /* perform below checks for date failure cases */
+    if (ret == 0 || ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E) {
+        /* get subject and determine if already loaded */
+    #ifndef NO_SKID
+        if (args->dCert->extAuthKeyIdSet)
+            subjectHash = args->dCert->extSubjKeyId;
+        else
+    #endif
+            subjectHash = args->dCert->subjectHash;
+        alreadySigner = AlreadySigner(ssl->ctx->cm, subjectHash);
+    }
+
+#ifdef WOLFSSL_SMALL_CERT_VERIFY
+    /* get signature check failures from above */
+    if (ret == 0)
+        ret = sigRet;
+#endif
+
+    if (pSubjectHash)
+        *pSubjectHash = subjectHash;
+    if (pAlreadySigner)
+        *pAlreadySigner = alreadySigner;
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl,
+            args->dCert->sigCtx.asyncDev);
+    }
+#endif
+
+    return ret;
+}
+
+/* Check key sizes for certs. Is redundant check since
+   ProcessBuffer also performs this check. */
+static int ProcessPeerCertCheckKey(WOLFSSL* ssl, ProcPeerCertArgs* args)
+{
+    int ret = 0;
+
+    if (ssl->options.verifyNone) {
+        return ret;
+    }
+
+    switch (args->dCert->keyOID) {
+    #ifndef NO_RSA
+        case RSAk:
+            if (ssl->options.minRsaKeySz < 0 ||
+                    args->dCert->pubKeySize <
+                     (word16)ssl->options.minRsaKeySz) {
+                WOLFSSL_MSG(
+                    "RSA key size in cert chain error");
+                ret = RSA_KEY_SIZE_E;
+            }
+            break;
+    #endif /* !NO_RSA */
+    #ifdef HAVE_ECC
+        case ECDSAk:
+            if (ssl->options.minEccKeySz < 0 ||
+                    args->dCert->pubKeySize <
+                     (word16)ssl->options.minEccKeySz) {
+                WOLFSSL_MSG(
+                    "ECC key size in cert chain error");
+                ret = ECC_KEY_SIZE_E;
+            }
+            break;
+    #endif /* HAVE_ECC */
+    #ifdef HAVE_ED25519
+        case ED25519k:
+            if (ssl->options.minEccKeySz < 0 ||
+                    ED25519_KEY_SIZE < (word16)ssl->options.minEccKeySz) {
+                WOLFSSL_MSG(
+                    "ECC key size in cert chain error");
+                ret = ECC_KEY_SIZE_E;
+            }
+            break;
+    #endif /* HAVE_ED25519 */
+    #ifdef HAVE_ED448
+        case ED448k:
+            if (ssl->options.minEccKeySz < 0 ||
+                    ED448_KEY_SIZE < (word16)ssl->options.minEccKeySz) {
+                WOLFSSL_MSG(
+                    "ECC key size in cert chain error");
+                ret = ECC_KEY_SIZE_E;
+            }
+            break;
+    #endif /* HAVE_ED448 */
+        default:
+            WOLFSSL_MSG("Key size not checked");
+            /* key not being checked for size if not in
+               switch */
+            break;
+    }
+
+    return ret;
+}
+
+int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+                     word32 totalSz)
+{
+    int ret = 0;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ProcPeerCertArgs* args = (ProcPeerCertArgs*)ssl->async.args;
+    typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+    (void)sizeof(args_test);
+#elif defined(WOLFSSL_NONBLOCK_OCSP)
+    ProcPeerCertArgs* args = ssl->nonblockarg;
+#elif defined(WOLFSSL_SMALL_STACK)
+    ProcPeerCertArgs* args = NULL;
+#else
+    ProcPeerCertArgs  args[1];
+#endif
+    byte* subjectHash = NULL;
+    int alreadySigner = 0;
+
+    WOLFSSL_ENTER("ProcessPeerCerts");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
+    if (ret != WC_NOT_PENDING_E) {
+        /* Check for error */
+        if (ret < 0)
+            goto exit_ppc;
+    }
+    else
+#elif defined(WOLFSSL_NONBLOCK_OCSP)
+    if (args == NULL) {
+        args = (ProcPeerCertArgs*)XMALLOC(
+            sizeof(ProcPeerCertArgs), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        if (args == NULL) {
+            ERROR_OUT(MEMORY_E, exit_ppc);
+        }
+    }
+    if (ssl->nonblockarg == NULL) /* new args */
+#elif defined(WOLFSSL_SMALL_STACK)
+    args = (ProcPeerCertArgs*)XMALLOC(
+        sizeof(ProcPeerCertArgs), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (args == NULL) {
+        ERROR_OUT(MEMORY_E, exit_ppc);
+    }
+#endif
+    {
+        /* Reset state */
+        ret = 0;
+        ssl->options.asyncState = TLS_ASYNC_BEGIN;
+        XMEMSET(args, 0, sizeof(ProcPeerCertArgs));
+        args->idx = *inOutIdx;
+        args->begin = *inOutIdx;
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        ssl->async.freeArgs = FreeProcPeerCertArgs;
+    #elif defined(WOLFSSL_NONBLOCK_OCSP)
+        ssl->nonblockarg = args;
+    #endif
+    }
+
+    switch (ssl->options.asyncState)
+    {
+        case TLS_ASYNC_BEGIN:
+        {
+            word32 listSz;
+
+        #ifdef WOLFSSL_CALLBACKS
+            if (ssl->hsInfoOn)
+                AddPacketName(ssl, "Certificate");
+            if (ssl->toInfoOn)
+                AddLateName("Certificate", &ssl->timeoutInfo);
+        #endif
+
+        #ifdef WOLFSSL_TLS13
+            if (ssl->options.tls1_3) {
+                byte ctxSz;
+
+                /* Certificate Request Context */
+                if ((args->idx - args->begin) + OPAQUE8_LEN > totalSz)
+                    ERROR_OUT(BUFFER_ERROR, exit_ppc);
+                ctxSz = *(input + args->idx);
+                args->idx++;
+                if ((args->idx - args->begin) + ctxSz > totalSz)
+                    ERROR_OUT(BUFFER_ERROR, exit_ppc);
+            #ifndef NO_WOLFSSL_CLIENT
+                /* Must be empty when received from server. */
+                if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                    if (ctxSz != 0) {
+                        ERROR_OUT(INVALID_CERT_CTX_E, exit_ppc);
+                    }
+                }
+            #endif
+            #ifndef NO_WOLFSSL_SERVER
+                /* Must contain value sent in request. */
+                if (ssl->options.side == WOLFSSL_SERVER_END) {
+                    if (ssl->options.handShakeState != HANDSHAKE_DONE &&
+                                                                   ctxSz != 0) {
+                        ERROR_OUT(INVALID_CERT_CTX_E, exit_ppc);
+                    }
+                    else if (ssl->options.handShakeState == HANDSHAKE_DONE) {
+                #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
+                         CertReqCtx* curr = ssl->certReqCtx;
+                         CertReqCtx* prev = NULL;
+                         while (curr != NULL) {
+                             if ((ctxSz == curr->len) &&
+                                 XMEMCMP(&curr->ctx, input + args->idx, ctxSz)
+                                                                         == 0) {
+                                     if (prev != NULL)
+                                         prev->next = curr->next;
+                                     else
+                                         ssl->certReqCtx = curr->next;
+                                     XFREE(curr, ssl->heap,
+                                           DYNAMIC_TYPE_TMP_BUFFER);
+                                     break;
+                             }
+                             prev = curr;
+                             curr = curr->next;
+                        }
+                        if (curr == NULL)
+                #endif
+                            ERROR_OUT(INVALID_CERT_CTX_E, exit_ppc);
+                    }
+                }
+            #endif
+                args->idx += ctxSz;
+
+            #ifdef OPENSSL_EXTRA
+                /* allocate buffer for cert extensions */
+                args->exts = (buffer*)XMALLOC(sizeof(buffer) *
+                     (ssl->verifyDepth + 1), ssl->heap, DYNAMIC_TYPE_CERT_EXT);
+                if (args->exts == NULL) {
+                    ERROR_OUT(MEMORY_E, exit_ppc);
+                }
+            #else
+                /* allocate buffer for cert extensions */
+                args->exts = (buffer*)XMALLOC(sizeof(buffer) * MAX_CHAIN_DEPTH,
+                                            ssl->heap, DYNAMIC_TYPE_CERT_EXT);
+                if (args->exts == NULL) {
+                    ERROR_OUT(MEMORY_E, exit_ppc);
+                }
+            #endif
+            }
+        #endif
+
+            /* allocate buffer for certs */
+        #ifdef OPENSSL_EXTRA
+            args->certs = (buffer*)XMALLOC(sizeof(buffer) *
+                    (ssl->verifyDepth + 1), ssl->heap, DYNAMIC_TYPE_DER);
+            if (args->certs == NULL) {
+                ERROR_OUT(MEMORY_E, exit_ppc);
+            }
+            XMEMSET(args->certs, 0, sizeof(buffer) * (ssl->verifyDepth + 1));
+        #else
+            args->certs = (buffer*)XMALLOC(sizeof(buffer) * MAX_CHAIN_DEPTH,
+                                            ssl->heap, DYNAMIC_TYPE_DER);
+            if (args->certs == NULL) {
+                ERROR_OUT(MEMORY_E, exit_ppc);
+            }
+            XMEMSET(args->certs, 0, sizeof(buffer) * MAX_CHAIN_DEPTH);
+        #endif /* OPENSSL_EXTRA */
+
+            /* Certificate List */
+            if ((args->idx - args->begin) + OPAQUE24_LEN > totalSz) {
+                ERROR_OUT(BUFFER_ERROR, exit_ppc);
+            }
+            c24to32(input + args->idx, &listSz);
+            args->idx += OPAQUE24_LEN;
+            if (listSz > MAX_CERTIFICATE_SZ) {
+                ERROR_OUT(BUFFER_ERROR, exit_ppc);
+            }
+            if ((args->idx - args->begin) + listSz != totalSz) {
+                ERROR_OUT(BUFFER_ERROR, exit_ppc);
+            }
+
+            WOLFSSL_MSG("Loading peer's cert chain");
+            /* first put cert chain into buffer so can verify top down
+               we're sent bottom up */
+            while (listSz) {
+                word32 certSz;
+
+            #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                if (args->totalCerts > ssl->verifyDepth) {
+                    ssl->peerVerifyRet = X509_V_ERR_CERT_CHAIN_TOO_LONG;
+                    ERROR_OUT(MAX_CHAIN_ERROR, exit_ppc);
+                }
+            #else
+                if (args->totalCerts >= ssl->verifyDepth ||
+                        args->totalCerts >= MAX_CHAIN_DEPTH) {
+                    ERROR_OUT(MAX_CHAIN_ERROR, exit_ppc);
+                }
+            #endif
+
+                if ((args->idx - args->begin) + OPAQUE24_LEN > totalSz) {
+                    ERROR_OUT(BUFFER_ERROR, exit_ppc);
+                }
+
+                c24to32(input + args->idx, &certSz);
+                args->idx += OPAQUE24_LEN;
+
+                if ((args->idx - args->begin) + certSz > totalSz) {
+                    ERROR_OUT(BUFFER_ERROR, exit_ppc);
+                }
+
+                args->certs[args->totalCerts].length = certSz;
+                args->certs[args->totalCerts].buffer = input + args->idx;
+
+            #ifdef SESSION_CERTS
+                AddSessionCertToChain(&ssl->session.chain,
+                    input + args->idx, certSz);
+            #endif /* SESSION_CERTS */
+
+                args->idx += certSz;
+                listSz -= certSz + CERT_HEADER_SZ;
+
+            #ifdef WOLFSSL_TLS13
+                /* Extensions */
+                if (ssl->options.tls1_3) {
+                    word16 extSz;
+
+                    if ((args->idx - args->begin) + OPAQUE16_LEN > totalSz) {
+                        ERROR_OUT(BUFFER_ERROR, exit_ppc);
+                    }
+                    ato16(input + args->idx, &extSz);
+                    args->idx += OPAQUE16_LEN;
+                    if ((args->idx - args->begin) + extSz > totalSz) {
+                        ERROR_OUT(BUFFER_ERROR, exit_ppc);
+                    }
+                    /* Store extension data info for later processing. */
+                    args->exts[args->totalCerts].length = extSz;
+                    args->exts[args->totalCerts].buffer = input + args->idx;
+                    args->idx += extSz;
+                    listSz -= extSz + OPAQUE16_LEN;
+                    ret = TLSX_Parse(ssl, args->exts[args->totalCerts].buffer,
+                        args->exts[args->totalCerts].length, certificate, NULL);
+                    if (ret < 0) {
+                        ERROR_OUT(ret, exit_ppc);
+                    }
+                }
+            #endif
+
+                args->totalCerts++;
+                WOLFSSL_MSG("\tPut another cert into chain");
+            } /* while (listSz) */
+
+            args->count = args->totalCerts;
+            args->certIdx = 0; /* select peer cert (first one) */
+
+            if (args->count == 0 && ssl->options.mutualAuth &&
+                                      ssl->options.side == WOLFSSL_SERVER_END) {
+                ret = NO_PEER_CERT;
+                DoCertFatalAlert(ssl, ret);
+            }
+
+            args->dCertInit = 0;
+        #ifndef WOLFSSL_SMALL_CERT_VERIFY
+            args->dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap,
+                                                       DYNAMIC_TYPE_DCERT);
+            if (args->dCert == NULL) {
+                ERROR_OUT(MEMORY_E, exit_ppc);
+            }
+            XMEMSET(args->dCert, 0, sizeof(DecodedCert));
+        #endif
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_BUILD;
+        } /* case TLS_ASYNC_BEGIN */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_BUILD:
+        {
+            if (args->count > 0) {
+
+                /* check for trusted peer and get untrustedDepth */
+            #if defined(WOLFSSL_TRUST_PEER_CERT) || defined(OPENSSL_EXTRA)
+                if (args->certIdx == 0) {
+                #ifdef WOLFSSL_TRUST_PEER_CERT
+                    TrustedPeerCert* tp;
+                    int matchType = WC_MATCH_NAME;
+                #endif
+
+                    ret = ProcessPeerCertParse(ssl, args, CERT_TYPE, NO_VERIFY,
+                        &subjectHash, &alreadySigner);
+                    if (ret != 0)
+                        goto exit_ppc;
+
+                #ifdef OPENSSL_EXTRA
+                    /* Determine untrusted depth */
+                    if (!alreadySigner && (!args->dCert ||
+                            !args->dCertInit || !args->dCert->selfSigned)) {
+                        args->untrustedDepth = 1;
+                    }
+                #endif
+
+                #ifdef WOLFSSL_TRUST_PEER_CERT
+                    #ifndef NO_SKID
+                    if (args->dCert->extAuthKeyIdSet)
+                        matchType = WC_MATCH_SKID;
+                    #endif
+                    tp = GetTrustedPeer(ssl->ctx->cm, subjectHash, matchType);
+                    WOLFSSL_MSG("Checking for trusted peer cert");
+
+                    if (tp && MatchTrustedPeer(tp, args->dCert)) {
+                        WOLFSSL_MSG("Found matching trusted peer cert");
+                        args->haveTrustPeer = 1;
+                    }
+                    else if (tp == NULL) {
+                        /* no trusted peer cert */
+                        WOLFSSL_MSG("No matching trusted peer cert. Checking CAs");
+                    }
+                    else {
+                        WOLFSSL_MSG("Trusted peer cert did not match!");
+                    }
+                    if (!args->haveTrustPeer)
+                #endif
+                    {
+                        /* free cert if not trusted peer */
+                        FreeDecodedCert(args->dCert);
+                        args->dCertInit = 0;
+                    }
+                }
+            #endif /* WOLFSSL_TRUST_PEER_CERT || OPENSSL_EXTRA */
+
+                /* check certificate up to peer's first */
+                /* do not verify chain if trusted peer cert found */
+                while (args->count > 1
+                #ifdef WOLFSSL_TRUST_PEER_CERT
+                    && !args->haveTrustPeer
+                #endif /* WOLFSSL_TRUST_PEER_CERT */
+                ) {
+                    int skipAddCA = 0;
+
+                    /* select last certificate */
+                    args->certIdx = args->count - 1;
+
+                    ret = ProcessPeerCertParse(ssl, args, CERT_TYPE,
+                        !ssl->options.verifyNone ? VERIFY : NO_VERIFY,
+                        &subjectHash, &alreadySigner);
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    if (ret == WC_PENDING_E)
+                        goto exit_ppc;
+                #endif
+                    if (ret == 0) {
+                        ret = ProcessPeerCertCheckKey(ssl, args);
+                    }
+
+                    if (ret == 0 && args->dCert->isCA == 0) {
+                        WOLFSSL_MSG("Chain cert is not a CA, not adding as one");
+                    }
+                    else if (ret == 0 && ssl->options.verifyNone) {
+                        WOLFSSL_MSG("Chain cert not verified by option, "
+                            "not adding as CA");
+                    }
+                    else if (ret == 0) {
+                    #ifdef OPENSSL_EXTRA
+                        if (args->certIdx > args->untrustedDepth) {
+                            args->untrustedDepth = (char)args->certIdx + 1;
+                        }
+                    #endif
+
+                        if (alreadySigner) {
+                            WOLFSSL_MSG("Verified CA from chain and already had it");
+                        }
+                    }
+                    else {
+                        WOLFSSL_MSG("Failed to verify CA from chain");
+                    #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                        ssl->peerVerifyRet = X509_V_ERR_INVALID_CA;
+                    #endif
+                    }
+
+            #if defined(HAVE_OCSP) || defined(HAVE_CRL)
+                    if (ret == 0) {
+                        int doCrlLookup = 1;
+                #ifdef HAVE_OCSP
+                    #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+                        if (ssl->status_request_v2) {
+                            ret = TLSX_CSR2_InitRequests(ssl->extensions,
+                                                    args->dCert, 0, ssl->heap);
+                        }
+                        else /* skips OCSP and force CRL check */
+                    #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+                        if (ssl->ctx->cm->ocspEnabled &&
+                                            ssl->ctx->cm->ocspCheckAll) {
+                            WOLFSSL_MSG("Doing Non Leaf OCSP check");
+                            ret = CheckCertOCSP_ex(ssl->ctx->cm->ocsp,
+                                                    args->dCert, NULL, ssl);
+                        #ifdef WOLFSSL_NONBLOCK_OCSP
+                            if (ret == OCSP_WANT_READ) {
+                                args->lastErr = ret;
+                                goto exit_ppc;
+                            }
+                        #endif
+                            doCrlLookup = (ret == OCSP_CERT_UNKNOWN);
+                            if (ret != 0) {
+                                doCrlLookup = 0;
+                                WOLFSSL_MSG("\tOCSP Lookup not ok");
+                            }
+                        }
+                #endif /* HAVE_OCSP */
+
+                #ifdef HAVE_CRL
+                        if (ret == 0 && doCrlLookup &&
+                                    ssl->ctx->cm->crlEnabled &&
+                                                ssl->ctx->cm->crlCheckAll) {
+                            WOLFSSL_MSG("Doing Non Leaf CRL check");
+                            ret = CheckCertCRL(ssl->ctx->cm->crl, args->dCert);
+                        #ifdef WOLFSSL_NONBLOCK_OCSP
+                            if (ret == OCSP_WANT_READ) {
+                                args->lastErr = ret;
+                                goto exit_ppc;
+                            }
+                        #endif
+                            if (ret != 0) {
+                                WOLFSSL_MSG("\tCRL check not ok");
+                            }
+                        }
+                #endif /* HAVE_CRL */
+                        (void)doCrlLookup;
+                    }
+            #endif /* HAVE_OCSP || HAVE_CRL */
+
+                    /* Do verify callback */
+                    ret = DoVerifyCallback(ssl->ctx->cm, ssl, ret, args);
+
+                #ifdef WOLFSSL_ALT_CERT_CHAINS
+                    /* For alternate cert chain, its okay for a CA cert to fail
+                        with ASN_NO_SIGNER_E here. The "alternate" certificate
+                        chain mode only requires that the peer certificate
+                        validate to a trusted CA */
+                    if (ret != 0 && args->dCert->isCA) {
+                        if (ret == ASN_NO_SIGNER_E) {
+                            if (!ssl->options.usingAltCertChain) {
+                                WOLFSSL_MSG("Trying alternate cert chain");
+                                ssl->options.usingAltCertChain = 1;
+                            }
+
+                            ret = 0; /* clear error and continue */
+                        }
+
+                        /* do not add to certificate manager */
+                        skipAddCA = 1;
+                    }
+                #endif /* WOLFSSL_ALT_CERT_CHAINS */
+
+                    /* If valid CA then add to Certificate Manager */
+                    if (ret == 0 && args->dCert->isCA &&
+                            !ssl->options.verifyNone && !skipAddCA) {
+                        buffer* cert = &args->certs[args->certIdx];
+
+                        /* Is valid CA */
+                    #if defined(SESSION_CERTS) && defined(WOLFSSL_ALT_CERT_CHAINS)
+                        /* if using alternate chain, store the cert used */
+                        if (ssl->options.usingAltCertChain) {
+                            AddSessionCertToChain(&ssl->session.altChain,
+                                cert->buffer, cert->length);
+                        }
+                    #endif /* SESSION_CERTS && WOLFSSL_ALT_CERT_CHAINS */
+                        if (!alreadySigner) {
+                            DerBuffer* add = NULL;
+                            ret = AllocDer(&add, cert->length, CA_TYPE, ssl->heap);
+                            if (ret < 0)
+                                goto exit_ppc;
+
+                            XMEMCPY(add->buffer, cert->buffer, cert->length);
+
+                            /* CA already verified above in ParseCertRelative */
+                            WOLFSSL_MSG("Adding CA from chain");
+                            ret = AddCA(ssl->ctx->cm, &add, WOLFSSL_CHAIN_CA,
+                                NO_VERIFY);
+                            if (ret == WOLFSSL_SUCCESS) {
+                                ret = 0;
+                            }
+                        }
+                    }
+
+                    /* Handle error codes */
+                    if (ret != 0) {
+                        if (!ssl->options.verifyNone) {
+                            DoCertFatalAlert(ssl, ret);
+                        }
+                        ssl->error = ret; /* Report SSL error */
+
+                        if (args->lastErr == 0) {
+                            args->lastErr = ret; /* save error from last time */
+                            ret = 0; /* reset error */
+                        }
+                    }
+
+                    FreeDecodedCert(args->dCert);
+                    args->dCertInit = 0;
+                    args->count--;
+                } /* while (count > 0 && !args->haveTrustPeer) */
+            } /* if (count > 0) */
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_ppc;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_DO;
+        } /* case TLS_ASYNC_BUILD */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_DO:
+        {
+            /* peer's, may not have one if blank client cert sent by TLSv1.2 */
+            if (args->count > 0) {
+                WOLFSSL_MSG("Verifying Peer's cert");
+
+                /* select peer cert (first one) */
+                args->certIdx = 0;
+
+                ret = ProcessPeerCertParse(ssl, args, CERT_TYPE,
+                        !ssl->options.verifyNone ? VERIFY : NO_VERIFY,
+                        &subjectHash, &alreadySigner);
+            #ifdef WOLFSSL_ASYNC_CRYPT
+                if (ret == WC_PENDING_E)
+                    goto exit_ppc;
+            #endif
+                if (ret == 0) {
+                    WOLFSSL_MSG("Verified Peer's cert");
+                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                    ssl->peerVerifyRet = X509_V_OK;
+                #endif
+                #if defined(SESSION_CERTS) && defined(WOLFSSL_ALT_CERT_CHAINS)
+                    /* if using alternate chain, store the cert used */
+                    if (ssl->options.usingAltCertChain) {
+                        buffer* cert = &args->certs[args->certIdx];
+                        AddSessionCertToChain(&ssl->session.altChain,
+                            cert->buffer, cert->length);
+                    }
+                #endif /* SESSION_CERTS && WOLFSSL_ALT_CERT_CHAINS */
+
+                    /* check if fatal error */
+                    if (args->verifyErr) {
+                        args->fatal = 1;
+                        if (ret == 0) {
+                            ret = args->lastErr;
+                        }
+                    }
+                    else {
+                        args->fatal = 0;
+                    }
+                }
+                else if (ret == ASN_PARSE_E || ret == BUFFER_E) {
+                    WOLFSSL_MSG("Got Peer cert ASN PARSE or BUFFER ERROR");
+                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                    SendAlert(ssl, alert_fatal, bad_certificate);
+                    ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED;
+                #endif
+                    args->fatal = 1;
+                }
+                else {
+                    WOLFSSL_MSG("Failed to verify Peer's cert");
+                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                    ssl->peerVerifyRet = X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE;
+                #endif
+                    if (ssl->verifyCallback) {
+                        WOLFSSL_MSG(
+                            "\tCallback override available, will continue");
+                        /* check if fatal error */
+                        args->fatal = (args->verifyErr) ? 1 : 0;
+                    }
+                    else {
+                        WOLFSSL_MSG("\tNo callback override available, fatal");
+                        args->fatal = 1;
+                    #ifdef OPENSSL_EXTRA
+                        SendAlert(ssl, alert_fatal, bad_certificate);
+                    #endif
+                    }
+                }
+
+            #ifdef HAVE_SECURE_RENEGOTIATION
+                if (args->fatal == 0 && !IsAtLeastTLSv1_3(ssl->version)
+                                     && ssl->secure_renegotiation
+                                     && ssl->secure_renegotiation->enabled) {
+
+                    if (IsEncryptionOn(ssl, 0)) {
+                        /* compare against previous time */
+                        if (ssl->secure_renegotiation->subject_hash_set) {
+                            if (XMEMCMP(args->dCert->subjectHash,
+                                        ssl->secure_renegotiation->subject_hash,
+                                        KEYID_SIZE) != 0) {
+                                WOLFSSL_MSG(
+                                  "Peer sent different cert during scr, fatal");
+                                args->fatal = 1;
+                                ret = SCR_DIFFERENT_CERT_E;
+                            }
+                        }
+                    }
+
+                    /* cache peer's hash */
+                    if (args->fatal == 0) {
+                        XMEMCPY(ssl->secure_renegotiation->subject_hash,
+                                args->dCert->subjectHash, KEYID_SIZE);
+                        ssl->secure_renegotiation->subject_hash_set = 1;
+                    }
+                }
+            #endif /* HAVE_SECURE_RENEGOTIATION */
+            } /* if (count > 0) */
+
+            /* Check for error */
+            if (args->fatal && ret != 0) {
+                goto exit_ppc;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_VERIFY;
+        } /* case TLS_ASYNC_DO */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_VERIFY:
+        {
+            if (args->count > 0) {
+            #if defined(HAVE_OCSP) || defined(HAVE_CRL)
+                if (args->fatal == 0) {
+                    int doLookup = 1;
+
+                    if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+                        if (ssl->status_request) {
+                            args->fatal = TLSX_CSR_InitRequest(ssl->extensions,
+                                                    args->dCert, ssl->heap);
+                            doLookup = 0;
+                        #if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)
+                            if (ssl->options.tls1_3) {
+                                TLSX* ext = TLSX_Find(ssl->extensions,
+                                                           TLSX_STATUS_REQUEST);
+                                if (ext != NULL) {
+                                    word32 idx = 0;
+                                    CertificateStatusRequest* csr =
+                                           (CertificateStatusRequest*)ext->data;
+                                    ret = ProcessCSR(ssl, csr->response.buffer,
+                                                    &idx, csr->response.length);
+                                    if (ret < 0)
+                                        goto exit_ppc;
+                                }
+                            }
+                        #endif
+                        }
+                #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
+                #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+                        if (ssl->status_request_v2) {
+                            args->fatal = TLSX_CSR2_InitRequests(ssl->extensions,
+                                                    args->dCert, 1, ssl->heap);
+                            doLookup = 0;
+                        }
+                #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+                    }
+
+                #ifdef HAVE_OCSP
+                    if (doLookup && ssl->ctx->cm->ocspEnabled) {
+                        WOLFSSL_MSG("Doing Leaf OCSP check");
+                        ret = CheckCertOCSP_ex(ssl->ctx->cm->ocsp,
+                                                    args->dCert, NULL, ssl);
+                    #ifdef WOLFSSL_NONBLOCK_OCSP
+                        if (ret == OCSP_WANT_READ) {
+                            goto exit_ppc;
+                        }
+                    #endif
+                        doLookup = (ret == OCSP_CERT_UNKNOWN);
+                        if (ret != 0) {
+                            WOLFSSL_MSG("\tOCSP Lookup not ok");
+                            args->fatal = 0;
+                        #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                            ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED;
+                        #endif
+                        }
+                    }
+                #endif /* HAVE_OCSP */
+
+                #ifdef HAVE_CRL
+                    if (doLookup && ssl->ctx->cm->crlEnabled) {
+                        WOLFSSL_MSG("Doing Leaf CRL check");
+                        ret = CheckCertCRL(ssl->ctx->cm->crl, args->dCert);
+                    #ifdef WOLFSSL_NONBLOCK_OCSP
+                        if (ret == OCSP_WANT_READ) {
+                            goto exit_ppc;
+                        }
+                    #endif
+                        if (ret != 0) {
+                            WOLFSSL_MSG("\tCRL check not ok");
+                            args->fatal = 0;
+                        #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                            ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED;
+                        #endif
+                        }
+                    }
+                #endif /* HAVE_CRL */
+                    (void)doLookup;
+                }
+            #endif /* HAVE_OCSP || HAVE_CRL */
+
+            #ifdef KEEP_PEER_CERT
+                if (args->fatal == 0) {
+                    int copyRet = 0;
+
+                    #ifdef HAVE_SECURE_RENEGOTIATION
+                        if (ssl->secure_renegotiation &&
+                                           ssl->secure_renegotiation->enabled) {
+                            /* free old peer cert */
+                            FreeX509(&ssl->peerCert);
+                        }
+                    #endif
+
+                    /* set X509 format for peer cert */
+                    copyRet = CopyDecodedToX509(&ssl->peerCert, args->dCert);
+                    if (copyRet == MEMORY_E) {
+                        args->fatal = 1;
+                    }
+                }
+            #endif /* KEEP_PEER_CERT */
+
+            #ifndef IGNORE_KEY_EXTENSIONS
+                #if defined(OPENSSL_EXTRA)
+                  /* when compatibility layer is turned on and no verify is
+                   * set then ignore the certificate key extension */
+                    if (args->dCert->extKeyUsageSet &&
+                          args->dCert->extKeyUsageCrit == 0 &&
+                          ssl->options.verifyNone) {
+                        WOLFSSL_MSG("Not verifying certificate key usage");
+                    }
+                    else
+                #endif
+                if (args->dCert->extKeyUsageSet) {
+                    if ((ssl->specs.kea == rsa_kea) &&
+                        (ssl->options.side == WOLFSSL_CLIENT_END) &&
+                        (args->dCert->extKeyUsage & KEYUSE_KEY_ENCIPHER) == 0) {
+                        ret = KEYUSE_ENCIPHER_E;
+                    }
+                    if ((ssl->specs.sig_algo == rsa_sa_algo ||
+                            (ssl->specs.sig_algo == ecc_dsa_sa_algo &&
+                                 !ssl->specs.static_ecdh)) &&
+                        (args->dCert->extKeyUsage & KEYUSE_DIGITAL_SIG) == 0) {
+                        WOLFSSL_MSG("KeyUse Digital Sig not set");
+                        ret = KEYUSE_SIGNATURE_E;
+                    }
+                }
+
+                #if defined(OPENSSL_EXTRA)
+                    /* when compatibility layer is turned on and no verify is
+                     * set then ignore the certificate key extension */
+                    if (args->dCert->extExtKeyUsageSet &&
+                            args->dCert->extExtKeyUsageCrit == 0 &&
+                          ssl->options.verifyNone) {
+                                WOLFSSL_MSG("Not verifying certificate ext key usage");
+                    }
+                    else
+                #endif
+                if (args->dCert->extExtKeyUsageSet) {
+                    if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                        if ((args->dCert->extExtKeyUsage &
+                                (EXTKEYUSE_ANY | EXTKEYUSE_SERVER_AUTH)) == 0) {
+                            WOLFSSL_MSG("ExtKeyUse Server Auth not set");
+                            ret = EXTKEYUSE_AUTH_E;
+                        }
+                    }
+                    else {
+                        if ((args->dCert->extExtKeyUsage &
+                                (EXTKEYUSE_ANY | EXTKEYUSE_CLIENT_AUTH)) == 0) {
+                            WOLFSSL_MSG("ExtKeyUse Client Auth not set");
+                            ret = EXTKEYUSE_AUTH_E;
+                        }
+                    }
+                }
+            #endif /* IGNORE_KEY_EXTENSIONS */
+
+                if (args->fatal) {
+                    ssl->error = ret;
+                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                    SendAlert(ssl, alert_fatal, bad_certificate);
+                    ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED;
+                #endif
+                    goto exit_ppc;
+                }
+
+                ssl->options.havePeerCert = 1;
+
+                if (!ssl->options.verifyNone && ssl->buffers.domainName.buffer) {
+                #ifndef WOLFSSL_ALLOW_NO_CN_IN_SAN
+                    /* Per RFC 5280 section 4.2.1.6, "Whenever such identities
+                     * are to be bound into a certificate, the subject
+                     * alternative name extension MUST be used." */
+                    if (args->dCert->altNames) {
+                        if (CheckAltNames(args->dCert,
+                                (char*)ssl->buffers.domainName.buffer) == 0 ) {
+                            WOLFSSL_MSG("DomainName match on alt names failed");
+                            /* try to get peer key still */
+                            ret = DOMAIN_NAME_MISMATCH;
+                        }
+                    }
+                    else {
+                        if (MatchDomainName(
+                                 args->dCert->subjectCN,
+                                 args->dCert->subjectCNLen,
+                                 (char*)ssl->buffers.domainName.buffer) == 0) {
+                            WOLFSSL_MSG("DomainName match on common name failed");
+                            ret = DOMAIN_NAME_MISMATCH;
+                        }
+                    }
+                #else /* WOLFSSL_ALL_NO_CN_IN_SAN */
+                    /* Old behavior. */
+                    if (MatchDomainName(args->dCert->subjectCN,
+                                args->dCert->subjectCNLen,
+                                (char*)ssl->buffers.domainName.buffer) == 0) {
+                        WOLFSSL_MSG("DomainName match on common name failed");
+                        if (CheckAltNames(args->dCert,
+                                 (char*)ssl->buffers.domainName.buffer) == 0 ) {
+                            WOLFSSL_MSG(
+                                "DomainName match on alt names failed too");
+                            /* try to get peer key still */
+                            ret = DOMAIN_NAME_MISMATCH;
+                        }
+                    }
+                #endif /* WOLFSSL_ALL_NO_CN_IN_SAN */
+                }
+
+                /* decode peer key */
+                switch (args->dCert->keyOID) {
+                #ifndef NO_RSA
+                    case RSAk:
+                    {
+                        word32 keyIdx = 0;
+                        int keyRet = 0;
+
+                        if (ssl->peerRsaKey == NULL) {
+                            keyRet = AllocKey(ssl, DYNAMIC_TYPE_RSA,
+                                                (void**)&ssl->peerRsaKey);
+                        } else if (ssl->peerRsaKeyPresent) {
+                            keyRet = ReuseKey(ssl, DYNAMIC_TYPE_RSA,
+                                              ssl->peerRsaKey);
+                            ssl->peerRsaKeyPresent = 0;
+                        }
+
+                        if (keyRet != 0 || wc_RsaPublicKeyDecode(
+                               args->dCert->publicKey, &keyIdx, ssl->peerRsaKey,
+                                                args->dCert->pubKeySize) != 0) {
+                            ret = PEER_KEY_ERROR;
+                        }
+                        else {
+                            ssl->peerRsaKeyPresent = 1;
+                    #ifdef WOLFSSL_RENESAS_TSIP_TLS
+                        /* copy encrypted tsip key index into ssl object */
+                        if (args->dCert->tsip_encRsaKeyIdx) {
+                            if (!ssl->peerTsipEncRsaKeyIndex) {
+                                ssl->peerTsipEncRsaKeyIndex = (byte*)XMALLOC(
+                                    TSIP_TLS_ENCPUBKEY_SZ_BY_CERTVRFY,
+                                    ssl->heap, DYNAMIC_TYPE_RSA);
+                                if (!ssl->peerTsipEncRsaKeyIndex) {
+                                    args->lastErr = MEMORY_E;
+                                    goto exit_ppc;
+                                }
+                            }
+
+                            XMEMCPY(ssl->peerTsipEncRsaKeyIndex,
+                                        args->dCert->tsip_encRsaKeyIdx,
+                                        TSIP_TLS_ENCPUBKEY_SZ_BY_CERTVRFY);
+                         }
+                    #endif
+                    #ifdef HAVE_PK_CALLBACKS
+                        #ifndef NO_RSA
+                            #ifdef HAVE_SECURE_RENEGOTIATION
+                            if (ssl->buffers.peerRsaKey.buffer) {
+                                XFREE(ssl->buffers.peerRsaKey.buffer,
+                                        ssl->heap, DYNAMIC_TYPE_RSA);
+                                ssl->buffers.peerRsaKey.buffer = NULL;
+                            }
+                            #endif
+
+
+                            ssl->buffers.peerRsaKey.buffer =
+                                   (byte*)XMALLOC(args->dCert->pubKeySize,
+                                                ssl->heap, DYNAMIC_TYPE_RSA);
+                            if (ssl->buffers.peerRsaKey.buffer == NULL) {
+                                ret = MEMORY_ERROR;
+                            }
+                            else {
+                                XMEMCPY(ssl->buffers.peerRsaKey.buffer,
+                                        args->dCert->publicKey,
+                                        args->dCert->pubKeySize);
+                                ssl->buffers.peerRsaKey.length =
+                                    args->dCert->pubKeySize;
+                            }
+                        #endif /* NO_RSA */
+                    #endif /* HAVE_PK_CALLBACKS */
+                        }
+
+                        /* check size of peer RSA key */
+                        if (ret == 0 && ssl->peerRsaKeyPresent &&
+                                          !ssl->options.verifyNone &&
+                                          wc_RsaEncryptSize(ssl->peerRsaKey)
+                                              < ssl->options.minRsaKeySz) {
+                            ret = RSA_KEY_SIZE_E;
+                            WOLFSSL_MSG("Peer RSA key is too small");
+                        }
+                        break;
+                    }
+                #endif /* NO_RSA */
+                #ifdef HAVE_NTRU
+                    case NTRUk:
+                    {
+                        if (args->dCert->pubKeySize > sizeof(ssl->peerNtruKey)) {
+                            ret = PEER_KEY_ERROR;
+                        }
+                        else {
+                            XMEMCPY(ssl->peerNtruKey, args->dCert->publicKey,
+                                                      args->dCert->pubKeySize);
+                            ssl->peerNtruKeyLen =
+                                (word16)args->dCert->pubKeySize;
+                            ssl->peerNtruKeyPresent = 1;
+                        }
+                        break;
+                    }
+                #endif /* HAVE_NTRU */
+                #ifdef HAVE_ECC
+                    case ECDSAk:
+                    {
+                        int keyRet = 0;
+                        word32 idx = 0;
+
+                        if (ssl->peerEccDsaKey == NULL) {
+                            /* alloc/init on demand */
+                            keyRet = AllocKey(ssl, DYNAMIC_TYPE_ECC,
+                                    (void**)&ssl->peerEccDsaKey);
+                        } else if (ssl->peerEccDsaKeyPresent) {
+                            keyRet = ReuseKey(ssl, DYNAMIC_TYPE_ECC,
+                                              ssl->peerEccDsaKey);
+                            ssl->peerEccDsaKeyPresent = 0;
+                        }
+
+                        if (keyRet != 0 ||
+                            wc_EccPublicKeyDecode(args->dCert->publicKey, &idx,
+                                                ssl->peerEccDsaKey,
+                                                args->dCert->pubKeySize) != 0) {
+                            ret = PEER_KEY_ERROR;
+                        }
+                        else {
+                            ssl->peerEccDsaKeyPresent = 1;
+                    #ifdef HAVE_PK_CALLBACKS
+                            ssl->buffers.peerEccDsaKey.buffer =
+                                   (byte*)XMALLOC(args->dCert->pubKeySize,
+                                           ssl->heap, DYNAMIC_TYPE_ECC);
+                            if (ssl->buffers.peerEccDsaKey.buffer == NULL) {
+                                ERROR_OUT(MEMORY_ERROR, exit_ppc);
+                            }
+                            else {
+                                XMEMCPY(ssl->buffers.peerEccDsaKey.buffer,
+                                        args->dCert->publicKey,
+                                        args->dCert->pubKeySize);
+                                ssl->buffers.peerEccDsaKey.length =
+                                        args->dCert->pubKeySize;
+                            }
+                    #endif /* HAVE_PK_CALLBACKS */
+                        }
+
+                        /* check size of peer ECC key */
+                        if (ret == 0 && ssl->peerEccDsaKeyPresent &&
+                                              !ssl->options.verifyNone &&
+                                              wc_ecc_size(ssl->peerEccDsaKey)
+                                              < ssl->options.minEccKeySz) {
+                            ret = ECC_KEY_SIZE_E;
+                            WOLFSSL_MSG("Peer ECC key is too small");
+                        }
+                        break;
+                    }
+                #endif /* HAVE_ECC */
+                #ifdef HAVE_ED25519
+                    case ED25519k:
+                    {
+                        int keyRet = 0;
+                        if (ssl->peerEd25519Key == NULL) {
+                            /* alloc/init on demand */
+                            keyRet = AllocKey(ssl, DYNAMIC_TYPE_ED25519,
+                                    (void**)&ssl->peerEd25519Key);
+                        } else if (ssl->peerEd25519KeyPresent) {
+                            keyRet = ReuseKey(ssl, DYNAMIC_TYPE_ED25519,
+                                              ssl->peerEd25519Key);
+                            ssl->peerEd25519KeyPresent = 0;
+                        }
+
+                        if (keyRet != 0 ||
+                            wc_ed25519_import_public(args->dCert->publicKey,
+                                                     args->dCert->pubKeySize,
+                                                     ssl->peerEd25519Key)
+                                                                         != 0) {
+                            ret = PEER_KEY_ERROR;
+                        }
+                        else {
+                            ssl->peerEd25519KeyPresent = 1;
+                    #ifdef HAVE_PK_CALLBACKS
+                            ssl->buffers.peerEd25519Key.buffer =
+                                   (byte*)XMALLOC(args->dCert->pubKeySize,
+                                           ssl->heap, DYNAMIC_TYPE_ED25519);
+                            if (ssl->buffers.peerEd25519Key.buffer == NULL) {
+                                ERROR_OUT(MEMORY_ERROR, exit_ppc);
+                            }
+                            else {
+                                XMEMCPY(ssl->buffers.peerEd25519Key.buffer,
+                                        args->dCert->publicKey,
+                                        args->dCert->pubKeySize);
+                                ssl->buffers.peerEd25519Key.length =
+                                        args->dCert->pubKeySize;
+                            }
+                    #endif /*HAVE_PK_CALLBACKS */
+                        }
+
+                        /* check size of peer ECC key */
+                        if (ret == 0 && ssl->peerEd25519KeyPresent &&
+                                  !ssl->options.verifyNone &&
+                                  ED25519_KEY_SIZE < ssl->options.minEccKeySz) {
+                            ret = ECC_KEY_SIZE_E;
+                            WOLFSSL_MSG("Peer ECC key is too small");
+                        }
+                        break;
+                    }
+                #endif /* HAVE_ED25519 */
+                #ifdef HAVE_ED448
+                    case ED448k:
+                    {
+                        int keyRet = 0;
+                        if (ssl->peerEd448Key == NULL) {
+                            /* alloc/init on demand */
+                            keyRet = AllocKey(ssl, DYNAMIC_TYPE_ED448,
+                                    (void**)&ssl->peerEd448Key);
+                        } else if (ssl->peerEd448KeyPresent) {
+                            keyRet = ReuseKey(ssl, DYNAMIC_TYPE_ED448,
+                                    ssl->peerEd448Key);
+                            ssl->peerEd448KeyPresent = 0;
+                        }
+
+                        if (keyRet != 0 ||
+                            wc_ed448_import_public(args->dCert->publicKey,
+                                    args->dCert->pubKeySize,
+                                    ssl->peerEd448Key) != 0) {
+                            ret = PEER_KEY_ERROR;
+                        }
+                        else {
+                            ssl->peerEd448KeyPresent = 1;
+                    #ifdef HAVE_PK_CALLBACKS
+                            ssl->buffers.peerEd448Key.buffer =
+                                   (byte*)XMALLOC(args->dCert->pubKeySize,
+                                           ssl->heap, DYNAMIC_TYPE_ED448);
+                            if (ssl->buffers.peerEd448Key.buffer == NULL) {
+                                ERROR_OUT(MEMORY_ERROR, exit_ppc);
+                            }
+                            else {
+                                XMEMCPY(ssl->buffers.peerEd448Key.buffer,
+                                        args->dCert->publicKey,
+                                        args->dCert->pubKeySize);
+                                ssl->buffers.peerEd448Key.length =
+                                        args->dCert->pubKeySize;
+                            }
+                    #endif /*HAVE_PK_CALLBACKS */
+                        }
+
+                        /* check size of peer ECC key */
+                        if (ret == 0 && ssl->peerEd448KeyPresent &&
+                               !ssl->options.verifyNone &&
+                               ED448_KEY_SIZE < ssl->options.minEccKeySz) {
+                            ret = ECC_KEY_SIZE_E;
+                            WOLFSSL_MSG("Peer ECC key is too small");
+                        }
+                        break;
+                    }
+                #endif /* HAVE_ED448 */
+                    default:
+                        break;
+                }
+
+                /* args->dCert free'd in function cleanup after callback */
+            } /* if (count > 0) */
+
+            /* Check for error */
+            if (args->fatal && ret != 0) {
+                goto exit_ppc;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_FINALIZE;
+        } /* case TLS_ASYNC_VERIFY */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_FINALIZE:
+        {
+            /* load last error */
+            if (args->lastErr != 0 && ret == 0) {
+                ret = args->lastErr;
+            }
+
+        #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+            if (args->untrustedDepth > ssl->options.verifyDepth) {
+                ssl->peerVerifyRet = X509_V_ERR_CERT_CHAIN_TOO_LONG;
+                ret = MAX_CHAIN_ERROR;
+            }
+        #endif
+
+            /* Do verify callback */
+            ret = DoVerifyCallback(ssl->ctx->cm, ssl, ret, args);
+
+            if (ssl->options.verifyNone &&
+                              (ret == CRL_MISSING || ret == CRL_CERT_REVOKED)) {
+                WOLFSSL_MSG("Ignoring CRL problem based on verify setting");
+                ret = ssl->error = 0;
+            }
+
+            if (ret != 0) {
+                if (!ssl->options.verifyNone) {
+                    DoCertFatalAlert(ssl, ret);
+                }
+                ssl->error = ret; /* Report SSL error */
+            }
+
+            if (ret == 0 && ssl->options.side == WOLFSSL_CLIENT_END) {
+                ssl->options.serverState = SERVER_CERT_COMPLETE;
+            }
+
+            if (IsEncryptionOn(ssl, 0)) {
+                args->idx += ssl->keys.padSz;
+            #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+                if (ssl->options.startedETMRead)
+                    args->idx += MacSize(ssl);
+            #endif
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_END;
+        } /* case TLS_ASYNC_FINALIZE */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_END:
+        {
+            /* Set final index */
+            *inOutIdx = args->idx;
+
+            break;
+        }
+        default:
+            ret = INPUT_CASE_ERROR;
+            break;
+    } /* switch(ssl->options.asyncState) */
+
+exit_ppc:
+
+    WOLFSSL_LEAVE("ProcessPeerCerts", ret);
+
+
+#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP)
+    if (ret == WC_PENDING_E || ret == OCSP_WANT_READ) {
+        /* Mark message as not received so it can process again */
+        ssl->msgsReceived.got_certificate = 0;
+
+        return ret;
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT || WOLFSSL_NONBLOCK_OCSP */
+
+    FreeProcPeerCertArgs(ssl, args);
+
+#if defined(WOLFSSL_ASYNC_CRYPT)
+#elif defined(WOLFSSL_NONBLOCK_OCSP)
+    XFREE(args, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    ssl->nonblockarg = NULL;
+#elif defined(WOLFSSL_SMALL_STACK)
+    XFREE(args, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    FreeKeyExchange(ssl);
+
+    return ret;
+}
+#endif
+
+#ifndef WOLFSSL_NO_TLS12
+#if !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)
+
+/* handle processing of certificate (11) */
+static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+                                                                word32 size)
+{
+    int ret;
+
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_DO);
+    WOLFSSL_ENTER("DoCertificate");
+
+#ifdef SESSION_CERTS
+    /* Reset the session cert chain count in case the session resume failed. */
+    ssl->session.chain.count = 0;
+    #ifdef WOLFSSL_ALT_CERT_CHAINS
+        ssl->session.altChain.count = 0;
+    #endif
+#endif /* SESSION_CERTS */
+
+    ret = ProcessPeerCerts(ssl, input, inOutIdx, size);
+#ifdef WOLFSSL_EXTRA_ALERTS
+    if (ret == BUFFER_ERROR || ret == ASN_PARSE_E)
+        SendAlert(ssl, alert_fatal, decode_error);
+#endif
+
+#ifdef OPENSSL_EXTRA
+    ssl->options.serverState = SERVER_CERT_COMPLETE;
+#endif
+
+    WOLFSSL_LEAVE("DoCertificate", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_DO);
+
+    return ret;
+}
+
+/* handle processing of certificate_status (22) */
+static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+                                                                    word32 size)
+{
+    int    ret = 0;
+    byte   status_type;
+    word32 status_length;
+
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_STATUS_DO);
+    WOLFSSL_ENTER("DoCertificateStatus");
+
+    if (size < ENUM_LEN + OPAQUE24_LEN)
+        return BUFFER_ERROR;
+
+    status_type = input[(*inOutIdx)++];
+
+    c24to32(input + *inOutIdx, &status_length);
+    *inOutIdx += OPAQUE24_LEN;
+
+    if (size != ENUM_LEN + OPAQUE24_LEN + status_length)
+        return BUFFER_ERROR;
+
+    switch (status_type) {
+
+    #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+     || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+
+        /* WOLFSSL_CSR_OCSP overlaps with WOLFSSL_CSR2_OCSP */
+        case WOLFSSL_CSR2_OCSP:
+            ret = ProcessCSR(ssl, input, inOutIdx, status_length);
+            break;
+
+    #endif
+
+    #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+
+        case WOLFSSL_CSR2_OCSP_MULTI: {
+            OcspRequest* request;
+            word32 list_length = status_length;
+            byte   idx = 0;
+
+            #ifdef WOLFSSL_SMALL_STACK
+                CertStatus* status;
+                OcspResponse* response;
+            #else
+                CertStatus status[1];
+                OcspResponse response[1];
+            #endif
+
+            do {
+                if (ssl->status_request_v2) {
+                    ssl->status_request_v2 = 0;
+                    break;
+                }
+
+                return BUFFER_ERROR;
+            } while(0);
+
+            #ifdef WOLFSSL_SMALL_STACK
+                status = (CertStatus*)XMALLOC(sizeof(CertStatus), ssl->heap,
+                                                       DYNAMIC_TYPE_OCSP_STATUS);
+                response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), ssl->heap,
+                                                       DYNAMIC_TYPE_OCSP_REQUEST);
+
+                if (status == NULL || response == NULL) {
+                    if (status)
+                        XFREE(status, ssl->heap, DYNAMIC_TYPE_OCSP_STATUS);
+                    if (response)
+                        XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+
+                    return MEMORY_ERROR;
+                }
+            #endif
+
+            while (list_length && ret == 0) {
+                if (OPAQUE24_LEN > list_length) {
+                    ret = BUFFER_ERROR;
+                    break;
+                }
+
+                c24to32(input + *inOutIdx, &status_length);
+                *inOutIdx   += OPAQUE24_LEN;
+                list_length -= OPAQUE24_LEN;
+
+                if (status_length > list_length) {
+                    ret = BUFFER_ERROR;
+                    break;
+                }
+
+                if (status_length) {
+                    InitOcspResponse(response, status, input +*inOutIdx,
+                                                                 status_length);
+
+                    if ((OcspResponseDecode(response, ssl->ctx->cm, ssl->heap,
+                                                                        0) != 0)
+                    ||  (response->responseStatus != OCSP_SUCCESSFUL)
+                    ||  (response->status->status != CERT_GOOD))
+                        ret = BAD_CERTIFICATE_STATUS_ERROR;
+
+                    while (ret == 0) {
+                        request = (OcspRequest*)TLSX_CSR2_GetRequest(
+                                ssl->extensions, status_type, idx++);
+
+                        if (request == NULL)
+                            ret = BAD_CERTIFICATE_STATUS_ERROR;
+                        else if (CompareOcspReqResp(request, response) == 0)
+                            break;
+                        else if (idx == 1) /* server cert must be OK */
+                            ret = BAD_CERTIFICATE_STATUS_ERROR;
+                    }
+
+                    *inOutIdx   += status_length;
+                    list_length -= status_length;
+                }
+            }
+
+            #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+                ssl->status_request_v2 = 0;
+            #endif
+
+            #ifdef WOLFSSL_SMALL_STACK
+                XFREE(status,   NULL, DYNAMIC_TYPE_OCSP_STATUS);
+                XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
+            #endif
+
+        }
+        break;
+
+    #endif
+
+        default:
+            ret = BUFFER_ERROR;
+    }
+
+    if (ret != 0)
+        SendAlert(ssl, alert_fatal, bad_certificate_status_response);
+
+    if (IsEncryptionOn(ssl, 0)) {
+    #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+        if (ssl->options.startedETMRead) {
+            word32 digestSz = MacSize(ssl);
+            if (*inOutIdx + ssl->keys.padSz + digestSz > size)
+                return BUFFER_E;
+            *inOutIdx += ssl->keys.padSz + digestSz;
+        }
+        else
+    #endif
+        {
+            if (*inOutIdx + ssl->keys.padSz > size)
+                return BUFFER_E;
+            *inOutIdx += ssl->keys.padSz;
+        }
+    }
+
+    WOLFSSL_LEAVE("DoCertificateStatus", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_STATUS_DO);
+
+    return ret;
+}
+
+#endif
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#endif /* !NO_CERTS */
+
+#ifndef WOLFSSL_NO_TLS12
+
+static int DoHelloRequest(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                                                    word32 size, word32 totalSz)
+{
+    (void)input;
+
+    WOLFSSL_START(WC_FUNC_HELLO_REQUEST_DO);
+    WOLFSSL_ENTER("DoHelloRequest");
+
+    if (size) /* must be 0 */
+        return BUFFER_ERROR;
+
+    if (IsEncryptionOn(ssl, 0)) {
+    #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+        if (ssl->options.startedETMRead) {
+            word32 digestSz = MacSize(ssl);
+            if (*inOutIdx + ssl->keys.padSz + digestSz > totalSz)
+                return BUFFER_E;
+            *inOutIdx += ssl->keys.padSz + digestSz;
+        }
+        else
+    #endif
+        {
+            /* access beyond input + size should be checked against totalSz */
+            if (*inOutIdx + ssl->keys.padSz > totalSz)
+                return BUFFER_E;
+
+            *inOutIdx += ssl->keys.padSz;
+        }
+    }
+
+    if (ssl->options.side == WOLFSSL_SERVER_END) {
+        SendAlert(ssl, alert_fatal, unexpected_message); /* try */
+        return FATAL_ERROR;
+    }
+#ifdef HAVE_SECURE_RENEGOTIATION
+    else if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled) {
+        ssl->secure_renegotiation->startScr = 1;
+        WOLFSSL_LEAVE("DoHelloRequest", 0);
+        WOLFSSL_END(WC_FUNC_HELLO_REQUEST_DO);
+        return 0;
+    }
+#endif
+    else {
+        return SendAlert(ssl, alert_warning, no_renegotiation);
+    }
+}
+
+
+int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size,
+                                                      word32 totalSz, int sniff)
+{
+    word32 finishedSz = (ssl->options.tls ? TLS_FINISHED_SZ : FINISHED_SZ);
+
+    WOLFSSL_START(WC_FUNC_FINISHED_DO);
+    WOLFSSL_ENTER("DoFinished");
+
+    if (finishedSz != size)
+        return BUFFER_ERROR;
+
+    /* check against totalSz */
+    #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+        if (ssl->options.startedETMRead) {
+            if (*inOutIdx + size + ssl->keys.padSz + MacSize(ssl) > totalSz)
+                return BUFFER_E;
+        }
+        else
+    #endif
+        {
+            if (*inOutIdx + size + ssl->keys.padSz > totalSz)
+                return BUFFER_E;
+        }
+
+    #ifdef WOLFSSL_CALLBACKS
+        if (ssl->hsInfoOn) AddPacketName(ssl, "Finished");
+        if (ssl->toInfoOn) AddLateName("Finished", &ssl->timeoutInfo);
+    #endif
+
+    if (sniff == NO_SNIFF) {
+        if (XMEMCMP(input + *inOutIdx, &ssl->hsHashes->verifyHashes,size) != 0){
+            WOLFSSL_MSG("Verify finished error on hashes");
+    #ifdef WOLFSSL_EXTRA_ALERTS
+            SendAlert(ssl, alert_fatal, decrypt_error);
+    #endif
+            return VERIFY_FINISHED_ERROR;
+        }
+    }
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+    if (ssl->secure_renegotiation) {
+        /* save peer's state */
+        if (ssl->options.side == WOLFSSL_CLIENT_END)
+            XMEMCPY(ssl->secure_renegotiation->server_verify_data,
+                    input + *inOutIdx, TLS_FINISHED_SZ);
+        else
+            XMEMCPY(ssl->secure_renegotiation->client_verify_data,
+                    input + *inOutIdx, TLS_FINISHED_SZ);
+        ssl->secure_renegotiation->verifySet = 1;
+    }
+#endif
+
+    /* force input exhaustion at ProcessReply consuming padSz */
+    *inOutIdx += size + ssl->keys.padSz;
+#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+    if (ssl->options.startedETMRead)
+        *inOutIdx += MacSize(ssl);
+#endif
+
+    if (ssl->options.side == WOLFSSL_CLIENT_END) {
+        ssl->options.serverState = SERVER_FINISHED_COMPLETE;
+#ifdef OPENSSL_EXTRA
+        ssl->cbmode = SSL_CB_MODE_WRITE;
+        ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
+#endif
+        if (!ssl->options.resuming) {
+#ifdef OPENSSL_EXTRA
+            if (ssl->CBIS != NULL) {
+                ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, SSL_SUCCESS);
+            }
+#endif
+            ssl->options.handShakeState = HANDSHAKE_DONE;
+            ssl->options.handShakeDone  = 1;
+        }
+    }
+    else {
+        ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
+#ifdef OPENSSL_EXTRA
+        ssl->cbmode = SSL_CB_MODE_READ;
+        ssl->options.serverState = SERVER_FINISHED_COMPLETE;
+#endif
+        if (ssl->options.resuming) {
+#ifdef OPENSSL_EXTRA
+            if (ssl->CBIS != NULL) {
+                ssl->CBIS(ssl, SSL_CB_ACCEPT_LOOP, SSL_SUCCESS);
+            }
+#endif
+            ssl->options.handShakeState = HANDSHAKE_DONE;
+            ssl->options.handShakeDone  = 1;
+        }
+    }
+#ifdef WOLFSSL_DTLS
+    if (ssl->options.dtls) {
+        DtlsMsgPoolReset(ssl);
+    }
+#endif
+
+    WOLFSSL_LEAVE("DoFinished", 0);
+    WOLFSSL_END(WC_FUNC_FINISHED_DO);
+
+    return 0;
+}
+
+
+/* Make sure no duplicates, no fast forward, or other problems; 0 on success */
+static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
+{
+    /* verify not a duplicate, mark received, check state */
+    switch (type) {
+
+#ifndef NO_WOLFSSL_CLIENT
+        case hello_request:
+            if (ssl->msgsReceived.got_hello_request) {
+                WOLFSSL_MSG("Duplicate HelloRequest received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_hello_request = 1;
+
+            break;
+#endif
+
+#ifndef NO_WOLFSSL_SERVER
+        case client_hello:
+            if (ssl->msgsReceived.got_client_hello) {
+                WOLFSSL_MSG("Duplicate ClientHello received");
+    #ifdef WOLFSSL_EXTRA_ALERTS
+                SendAlert(ssl, alert_fatal, unexpected_message);
+    #endif
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_client_hello = 1;
+
+            break;
+#endif
+
+#ifndef NO_WOLFSSL_CLIENT
+        case server_hello:
+            if (ssl->msgsReceived.got_server_hello) {
+                WOLFSSL_MSG("Duplicate ServerHello received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_server_hello = 1;
+
+            break;
+#endif
+
+#ifndef NO_WOLFSSL_CLIENT
+        case hello_verify_request:
+            if (ssl->msgsReceived.got_hello_verify_request) {
+                WOLFSSL_MSG("Duplicate HelloVerifyRequest received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_hello_verify_request = 1;
+
+            break;
+#endif
+
+#ifndef NO_WOLFSSL_CLIENT
+        case session_ticket:
+            if (ssl->msgsReceived.got_session_ticket) {
+                WOLFSSL_MSG("Duplicate SessionTicket received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_session_ticket = 1;
+
+            break;
+#endif
+
+        case certificate:
+            if (ssl->msgsReceived.got_certificate) {
+                WOLFSSL_MSG("Duplicate Certificate received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_certificate = 1;
+
+#ifndef NO_WOLFSSL_CLIENT
+            if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                if ( ssl->msgsReceived.got_server_hello == 0) {
+                    WOLFSSL_MSG("No ServerHello before Cert");
+                    return OUT_OF_ORDER_E;
+                }
+            }
+#endif
+#ifndef NO_WOLFSSL_SERVER
+            if (ssl->options.side == WOLFSSL_SERVER_END) {
+                if ( ssl->msgsReceived.got_client_hello == 0) {
+                    WOLFSSL_MSG("No ClientHello before Cert");
+                    return OUT_OF_ORDER_E;
+                }
+            }
+#endif
+            break;
+
+#ifndef NO_WOLFSSL_CLIENT
+        case certificate_status:
+            if (ssl->msgsReceived.got_certificate_status) {
+                WOLFSSL_MSG("Duplicate CertificateSatatus received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_certificate_status = 1;
+
+            if (ssl->msgsReceived.got_certificate == 0) {
+                WOLFSSL_MSG("No Certificate before CertificateStatus");
+                return OUT_OF_ORDER_E;
+            }
+            if (ssl->msgsReceived.got_server_key_exchange != 0) {
+                WOLFSSL_MSG("CertificateStatus after ServerKeyExchange");
+                return OUT_OF_ORDER_E;
+            }
+
+            break;
+#endif
+
+#ifndef NO_WOLFSSL_CLIENT
+        case server_key_exchange:
+            if (ssl->msgsReceived.got_server_key_exchange) {
+                WOLFSSL_MSG("Duplicate ServerKeyExchange received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_server_key_exchange = 1;
+
+            if (ssl->msgsReceived.got_server_hello == 0) {
+                WOLFSSL_MSG("No ServerHello before ServerKeyExchange");
+                return OUT_OF_ORDER_E;
+            }
+            if (ssl->msgsReceived.got_certificate_status == 0) {
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+                if (ssl->status_request) {
+                    int ret;
+
+                    WOLFSSL_MSG("No CertificateStatus before ServerKeyExchange");
+                    if ((ret = TLSX_CSR_ForceRequest(ssl)) != 0)
+                        return ret;
+                }
+#endif
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+                if (ssl->status_request_v2) {
+                    int ret;
+
+                    WOLFSSL_MSG("No CertificateStatus before ServerKeyExchange");
+                    if ((ret = TLSX_CSR2_ForceRequest(ssl)) != 0)
+                        return ret;
+                }
+#endif
+            }
+
+            break;
+#endif
+
+#ifndef NO_WOLFSSL_CLIENT
+        case certificate_request:
+            if (ssl->msgsReceived.got_certificate_request) {
+                WOLFSSL_MSG("Duplicate CertificateRequest received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_certificate_request = 1;
+
+            break;
+#endif
+
+#ifndef NO_WOLFSSL_CLIENT
+        case server_hello_done:
+            if (ssl->msgsReceived.got_server_hello_done) {
+                WOLFSSL_MSG("Duplicate ServerHelloDone received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_server_hello_done = 1;
+
+            if (ssl->msgsReceived.got_certificate == 0) {
+                if (ssl->specs.kea == psk_kea ||
+                    ssl->specs.kea == dhe_psk_kea ||
+                    ssl->specs.kea == ecdhe_psk_kea ||
+                    ssl->options.usingAnon_cipher) {
+                    WOLFSSL_MSG("No Cert required");
+                } else {
+                    WOLFSSL_MSG("No Certificate before ServerHelloDone");
+                    return OUT_OF_ORDER_E;
+                }
+            }
+            if (ssl->msgsReceived.got_server_key_exchange == 0) {
+                int pskNoServerHint = 0;  /* not required in this case */
+
+                #ifndef NO_PSK
+                    if (ssl->specs.kea == psk_kea &&
+                        ssl->arrays != NULL &&
+                        ssl->arrays->server_hint[0] == 0)
+                        pskNoServerHint = 1;
+                #endif
+                if (ssl->specs.static_ecdh == 1 ||
+                    ssl->specs.kea == rsa_kea ||
+                    ssl->specs.kea == ntru_kea ||
+                    pskNoServerHint) {
+                    WOLFSSL_MSG("No KeyExchange required");
+                } else {
+                    WOLFSSL_MSG("No ServerKeyExchange before ServerDone");
+                    return OUT_OF_ORDER_E;
+                }
+            }
+            break;
+#endif
+
+#ifndef NO_WOLFSSL_SERVER
+        case certificate_verify:
+            if (ssl->msgsReceived.got_certificate_verify) {
+                WOLFSSL_MSG("Duplicate CertificateVerify received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_certificate_verify = 1;
+
+            if ( ssl->msgsReceived.got_certificate == 0) {
+                WOLFSSL_MSG("No Cert before CertVerify");
+                return OUT_OF_ORDER_E;
+            }
+            break;
+#endif
+
+#ifndef NO_WOLFSSL_SERVER
+        case client_key_exchange:
+            if (ssl->msgsReceived.got_client_key_exchange) {
+                WOLFSSL_MSG("Duplicate ClientKeyExchange received");
+    #ifdef WOLFSSL_EXTRA_ALERTS
+                SendAlert(ssl, alert_fatal, unexpected_message);
+    #endif
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_client_key_exchange = 1;
+
+            if (ssl->msgsReceived.got_client_hello == 0) {
+                WOLFSSL_MSG("No ClientHello before ClientKeyExchange");
+                return OUT_OF_ORDER_E;
+            }
+            break;
+#endif
+
+        case finished:
+            if (ssl->msgsReceived.got_finished) {
+                WOLFSSL_MSG("Duplicate Finished received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_finished = 1;
+
+            if (ssl->msgsReceived.got_change_cipher == 0) {
+                WOLFSSL_MSG("Finished received before ChangeCipher");
+    #ifdef WOLFSSL_EXTRA_ALERTS
+                SendAlert(ssl, alert_fatal, unexpected_message);
+    #endif
+                return NO_CHANGE_CIPHER_E;
+            }
+            break;
+
+        case change_cipher_hs:
+            if (ssl->msgsReceived.got_change_cipher) {
+                WOLFSSL_MSG("Duplicate ChangeCipher received");
+    #ifdef WOLFSSL_EXTRA_ALERTS
+                SendAlert(ssl, alert_fatal, unexpected_message);
+    #endif
+                return DUPLICATE_MSG_E;
+            }
+            /* DTLS is going to ignore the CCS message if the client key
+             * exchange message wasn't received yet. */
+            if (!ssl->options.dtls)
+                ssl->msgsReceived.got_change_cipher = 1;
+
+#ifndef NO_WOLFSSL_CLIENT
+            if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                if (!ssl->options.resuming) {
+                   if (ssl->msgsReceived.got_server_hello_done == 0) {
+                        WOLFSSL_MSG("No ServerHelloDone before ChangeCipher");
+                        return OUT_OF_ORDER_E;
+                   }
+                }
+                else {
+                    if (ssl->msgsReceived.got_server_hello == 0) {
+                        WOLFSSL_MSG("No ServerHello before ChangeCipher on Resume");
+                        return OUT_OF_ORDER_E;
+                    }
+                }
+                #ifdef HAVE_SESSION_TICKET
+                    if (ssl->expect_session_ticket) {
+                        WOLFSSL_MSG("Expected session ticket missing");
+                        #ifdef WOLFSSL_DTLS
+                            if (ssl->options.dtls)
+                                return OUT_OF_ORDER_E;
+                        #endif
+                        return SESSION_TICKET_EXPECT_E;
+                    }
+                #endif
+            }
+#endif
+#ifndef NO_WOLFSSL_SERVER
+            if (ssl->options.side == WOLFSSL_SERVER_END) {
+                if (!ssl->options.resuming &&
+                               ssl->msgsReceived.got_client_key_exchange == 0) {
+                    WOLFSSL_MSG("No ClientKeyExchange before ChangeCipher");
+    #ifdef WOLFSSL_EXTRA_ALERTS
+                    SendAlert(ssl, alert_fatal, unexpected_message);
+    #endif
+                    return OUT_OF_ORDER_E;
+                }
+                #ifndef NO_CERTS
+                    if (ssl->options.verifyPeer &&
+                        ssl->options.havePeerCert) {
+
+                        if (!ssl->options.havePeerVerify) {
+                            WOLFSSL_MSG("client didn't send cert verify");
+                            #ifdef WOLFSSL_DTLS
+                                if (ssl->options.dtls)
+                                    return OUT_OF_ORDER_E;
+                            #endif
+                            return NO_PEER_VERIFY;
+                        }
+                    }
+                #endif
+            }
+#endif
+            if (ssl->options.dtls)
+                ssl->msgsReceived.got_change_cipher = 1;
+            break;
+
+        default:
+            WOLFSSL_MSG("Unknown message type");
+            return SANITY_MSG_E;
+    }
+
+    return 0;
+}
+
+
+static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+                          byte type, word32 size, word32 totalSz)
+{
+    int ret = 0;
+    word32 expectedIdx;
+
+    WOLFSSL_ENTER("DoHandShakeMsgType");
+
+#ifdef WOLFSSL_TLS13
+    if (type == hello_retry_request) {
+        return DoTls13HandShakeMsgType(ssl, input, inOutIdx, type, size,
+                                       totalSz);
+    }
+#endif
+
+    /* make sure can read the message */
+    if (*inOutIdx + size > totalSz) {
+        WOLFSSL_MSG("Incomplete Data");
+        return INCOMPLETE_DATA;
+    }
+
+    expectedIdx = *inOutIdx + size +
+                  (ssl->keys.encryptionOn ? ssl->keys.padSz : 0);
+#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+    if (ssl->options.startedETMRead && ssl->keys.encryptionOn)
+        expectedIdx += MacSize(ssl);
+#endif
+
+#if !defined(WOLFSSL_NO_SERVER) && \
+    defined(HAVE_SECURE_RENEGOTIATION) && \
+    defined(HAVE_SERVER_RENEGOTIATION_INFO)
+    if (ssl->options.handShakeDone && type == client_hello &&
+            ssl->secure_renegotiation &&
+            ssl->secure_renegotiation->enabled)
+    {
+        WOLFSSL_MSG("Reset handshake state");
+        XMEMSET(&ssl->msgsReceived, 0, sizeof(MsgsReceived));
+        ssl->options.serverState = NULL_STATE;
+        ssl->options.clientState = NULL_STATE;
+        ssl->options.connectState = CONNECT_BEGIN;
+        ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE;
+        ssl->options.handShakeState = NULL_STATE;
+        ssl->secure_renegotiation->cache_status = SCR_CACHE_NEEDED;
+
+        ret = InitHandshakeHashes(ssl);
+        if (ret != 0)
+            return ret;
+    }
+#endif
+
+    /* sanity check msg received */
+    if ( (ret = SanityCheckMsgReceived(ssl, type)) != 0) {
+        WOLFSSL_MSG("Sanity Check on handshake message type received failed");
+        return ret;
+    }
+
+#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+    /* add name later, add on record and handshake header part back on */
+    if (ssl->toInfoOn) {
+        int add = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+        AddPacketInfo(ssl, 0, handshake, input + *inOutIdx - add,
+                      size + add, READ_PROTO, ssl->heap);
+        #ifdef WOLFSSL_CALLBACKS
+        AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo);
+        #endif
+    }
+#endif
+
+    if (ssl->options.handShakeState == HANDSHAKE_DONE && type != hello_request){
+        WOLFSSL_MSG("HandShake message after handshake complete");
+        SendAlert(ssl, alert_fatal, unexpected_message);
+        return OUT_OF_ORDER_E;
+    }
+
+    if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->options.dtls == 0 &&
+               ssl->options.serverState == NULL_STATE && type != server_hello) {
+        WOLFSSL_MSG("First server message not server hello");
+        SendAlert(ssl, alert_fatal, unexpected_message);
+        return OUT_OF_ORDER_E;
+    }
+
+    if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->options.dtls &&
+            type == server_hello_done &&
+            ssl->options.serverState < SERVER_HELLO_COMPLETE) {
+        WOLFSSL_MSG("Server hello done received before server hello in DTLS");
+        SendAlert(ssl, alert_fatal, unexpected_message);
+        return OUT_OF_ORDER_E;
+    }
+
+    if (ssl->options.side == WOLFSSL_SERVER_END &&
+               ssl->options.clientState == NULL_STATE && type != client_hello) {
+        WOLFSSL_MSG("First client message not client hello");
+        SendAlert(ssl, alert_fatal, unexpected_message);
+        return OUT_OF_ORDER_E;
+    }
+
+    /* above checks handshake state */
+    /* hello_request not hashed */
+    /* Also, skip hashing the client_hello message here for DTLS. It will be
+     * hashed later if the DTLS cookie is correct. */
+    if (type != hello_request &&
+            !(IsDtlsNotSctpMode(ssl) && type == client_hello)
+    #ifdef WOLFSSL_ASYNC_CRYPT
+            && ssl->error != WC_PENDING_E
+    #endif
+    #ifdef WOLFSSL_NONBLOCK_OCSP
+            && ssl->error != OCSP_WANT_READ
+    #endif
+    ) {
+        ret = HashInput(ssl, input + *inOutIdx, size);
+        if (ret != 0) {
+            WOLFSSL_MSG("Incomplete handshake hashes");
+            return ret;
+        }
+    }
+
+#ifdef OPENSSL_EXTRA
+    if (ssl->CBIS != NULL){
+        ssl->cbmode = SSL_CB_MODE_READ;
+        ssl->cbtype = type;
+        ssl->CBIS(ssl, SSL_CB_ACCEPT_LOOP, SSL_SUCCESS);
+    }
+#endif
+
+    switch (type) {
+
+    case hello_request:
+        WOLFSSL_MSG("processing hello request");
+        ret = DoHelloRequest(ssl, input, inOutIdx, size, totalSz);
+        break;
+
+#ifndef NO_WOLFSSL_CLIENT
+    case hello_verify_request:
+        WOLFSSL_MSG("processing hello verify request");
+        ret = DoHelloVerifyRequest(ssl, input,inOutIdx, size);
+        break;
+
+    case server_hello:
+        WOLFSSL_MSG("processing server hello");
+        ret = DoServerHello(ssl, input, inOutIdx, size);
+    #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
+               ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \
+                (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)))
+        if (ssl->options.resuming || !IsAtLeastTLSv1_2(ssl) ||
+                                               IsAtLeastTLSv1_3(ssl->version)) {
+
+        #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP)
+            if (ret != WC_PENDING_E && ret != OCSP_WANT_READ)
+        #endif
+            {
+                ssl->options.cacheMessages = 0;
+                if (ssl->hsHashes->messages != NULL) {
+                    XFREE(ssl->hsHashes->messages, ssl->heap,
+                        DYNAMIC_TYPE_HASHES);
+                    ssl->hsHashes->messages = NULL;
+                }
+            }
+        }
+    #endif
+        break;
+
+#ifndef NO_CERTS
+    case certificate_request:
+        WOLFSSL_MSG("processing certificate request");
+        ret = DoCertificateRequest(ssl, input, inOutIdx, size);
+        break;
+#endif
+
+    case server_key_exchange:
+        WOLFSSL_MSG("processing server key exchange");
+        ret = DoServerKeyExchange(ssl, input, inOutIdx, size);
+        break;
+
+#ifdef HAVE_SESSION_TICKET
+    case session_ticket:
+        WOLFSSL_MSG("processing session ticket");
+        ret = DoSessionTicket(ssl, input, inOutIdx, size);
+        break;
+#endif /* HAVE_SESSION_TICKET */
+#endif
+
+#if !defined(NO_CERTS) && (!defined(NO_WOLFSSL_CLIENT) || \
+                                               !defined(WOLFSSL_NO_CLIENT_AUTH))
+    case certificate:
+        WOLFSSL_MSG("processing certificate");
+        ret = DoCertificate(ssl, input, inOutIdx, size);
+        break;
+
+    case certificate_status:
+        WOLFSSL_MSG("processing certificate status");
+        ret = DoCertificateStatus(ssl, input, inOutIdx, size);
+        break;
+#endif
+
+    case server_hello_done:
+        WOLFSSL_MSG("processing server hello done");
+    #ifdef WOLFSSL_CALLBACKS
+        if (ssl->hsInfoOn)
+            AddPacketName(ssl, "ServerHelloDone");
+        if (ssl->toInfoOn)
+            AddLateName("ServerHelloDone", &ssl->timeoutInfo);
+    #endif
+        ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
+        if (IsEncryptionOn(ssl, 0)) {
+            *inOutIdx += ssl->keys.padSz;
+        #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+            if (ssl->options.startedETMRead)
+                *inOutIdx += MacSize(ssl);
+        #endif
+        }
+        if (ssl->options.resuming) {
+            WOLFSSL_MSG("Not resuming as thought");
+            ssl->options.resuming = 0;
+        }
+        break;
+
+    case finished:
+        WOLFSSL_MSG("processing finished");
+        ret = DoFinished(ssl, input, inOutIdx, size, totalSz, NO_SNIFF);
+        break;
+
+#ifndef NO_WOLFSSL_SERVER
+    case client_hello:
+        WOLFSSL_MSG("processing client hello");
+        ret = DoClientHello(ssl, input, inOutIdx, size);
+    #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
+               ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \
+                (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)))
+        if (ssl->options.resuming || !ssl->options.verifyPeer || \
+                     !IsAtLeastTLSv1_2(ssl) || IsAtLeastTLSv1_3(ssl->version)) {
+        #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP)
+            if (ret != WC_PENDING_E && ret != OCSP_WANT_READ)
+        #endif
+            {
+                ssl->options.cacheMessages = 0;
+                if (ssl->hsHashes->messages != NULL) {
+                    XFREE(ssl->hsHashes->messages, ssl->heap, DYNAMIC_TYPE_HASHES);
+                    ssl->hsHashes->messages = NULL;
+                }
+            }
+        }
+    #endif
+        if (IsEncryptionOn(ssl, 0)) {
+        #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+            if (ssl->options.startedETMRead) {
+                word32 digestSz = MacSize(ssl);
+                if (*inOutIdx + ssl->keys.padSz + digestSz > totalSz)
+                    return BUFFER_E;
+                *inOutIdx += ssl->keys.padSz + digestSz;
+            }
+            else
+        #endif
+            {
+                /* access beyond input + size should be checked against totalSz
+                 */
+                if (*inOutIdx + ssl->keys.padSz > totalSz)
+                    return BUFFER_E;
+
+                *inOutIdx += ssl->keys.padSz;
+            }
+        }
+        break;
+
+    case client_key_exchange:
+        WOLFSSL_MSG("processing client key exchange");
+        ret = DoClientKeyExchange(ssl, input, inOutIdx, size);
+        break;
+
+#if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+                        defined(HAVE_ED448)) && !defined(WOLFSSL_NO_CLIENT_AUTH)
+    case certificate_verify:
+        WOLFSSL_MSG("processing certificate verify");
+        ret = DoCertificateVerify(ssl, input, inOutIdx, size);
+        break;
+#endif /* (!NO_RSA || ECC || ED25519 || ED448) && !WOLFSSL_NO_CLIENT_AUTH */
+
+#endif /* !NO_WOLFSSL_SERVER */
+
+    default:
+        WOLFSSL_MSG("Unknown handshake message type");
+        ret = UNKNOWN_HANDSHAKE_TYPE;
+        break;
+    }
+    if (ret == 0 && expectedIdx != *inOutIdx) {
+        WOLFSSL_MSG("Extra data in handshake message");
+        if (!ssl->options.dtls)
+            SendAlert(ssl, alert_fatal, decode_error);
+        ret = DECODE_E;
+    }
+
+    if (ret == 0 && ssl->buffers.inputBuffer.dynamicFlag
+    #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP)
+        /* do not shrink input for async or non-block */
+        && ssl->error != WC_PENDING_E && ssl->error != OCSP_WANT_READ
+    #endif
+    ) {
+        ShrinkInputBuffer(ssl, NO_FORCED_FREE);
+    }
+
+#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP)
+    /* if async, offset index so this msg will be processed again */
+    if ((ret == WC_PENDING_E || ret == OCSP_WANT_READ) && *inOutIdx > 0) {
+        *inOutIdx -= HANDSHAKE_HEADER_SZ;
+    #ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls) {
+            *inOutIdx -= DTLS_HANDSHAKE_EXTRA;
+        }
+    #endif
+    }
+
+    /* make sure async error is cleared */
+    if (ret == 0 && (ssl->error == WC_PENDING_E || ssl->error == OCSP_WANT_READ)) {
+        ssl->error = 0;
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT || WOLFSSL_NONBLOCK_OCSP */
+
+    WOLFSSL_LEAVE("DoHandShakeMsgType()", ret);
+    return ret;
+}
+
+
+static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+                          word32 totalSz)
+{
+    int    ret = 0;
+    word32 inputLength;
+
+    WOLFSSL_ENTER("DoHandShakeMsg()");
+
+    if (ssl->arrays == NULL) {
+        byte   type;
+        word32 size;
+
+        if (GetHandShakeHeader(ssl,input,inOutIdx,&type, &size, totalSz) != 0)
+            return PARSE_ERROR;
+
+        ssl->options.handShakeState = type;
+
+        return DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz);
+    }
+
+    inputLength = ssl->buffers.inputBuffer.length - *inOutIdx;
+
+    /* If there is a pending fragmented handshake message,
+     * pending message size will be non-zero. */
+    if (ssl->arrays->pendingMsgSz == 0) {
+        byte   type;
+        word32 size;
+
+        if (GetHandShakeHeader(ssl,input, inOutIdx, &type, &size, totalSz) != 0)
+            return PARSE_ERROR;
+
+        /* Cap the maximum size of a handshake message to something reasonable.
+         * By default is the maximum size of a certificate message assuming
+         * nine 2048-bit RSA certificates in the chain. */
+        if (size > MAX_HANDSHAKE_SZ) {
+            WOLFSSL_MSG("Handshake message too large");
+            return HANDSHAKE_SIZE_ERROR;
+        }
+
+        /* size is the size of the certificate message payload */
+        if (inputLength - HANDSHAKE_HEADER_SZ < size) {
+            ssl->arrays->pendingMsgType = type;
+            ssl->arrays->pendingMsgSz = size + HANDSHAKE_HEADER_SZ;
+            ssl->arrays->pendingMsg = (byte*)XMALLOC(size + HANDSHAKE_HEADER_SZ,
+                                                     ssl->heap,
+                                                     DYNAMIC_TYPE_ARRAYS);
+            if (ssl->arrays->pendingMsg == NULL)
+                return MEMORY_E;
+            XMEMCPY(ssl->arrays->pendingMsg,
+                    input + *inOutIdx - HANDSHAKE_HEADER_SZ,
+                    inputLength);
+            ssl->arrays->pendingMsgOffset = inputLength;
+            *inOutIdx += inputLength - HANDSHAKE_HEADER_SZ;
+            return 0;
+        }
+
+        ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz);
+    }
+    else {
+        word32 pendSz =
+            ssl->arrays->pendingMsgSz - ssl->arrays->pendingMsgOffset;
+
+        /* Catch the case where there may be the remainder of a fragmented
+         * handshake message and the next handshake message in the same
+         * record. */
+        if (inputLength > pendSz)
+            inputLength = pendSz;
+
+        XMEMCPY(ssl->arrays->pendingMsg + ssl->arrays->pendingMsgOffset,
+                input + *inOutIdx, inputLength);
+        ssl->arrays->pendingMsgOffset += inputLength;
+        *inOutIdx += inputLength;
+
+        if (ssl->arrays->pendingMsgOffset == ssl->arrays->pendingMsgSz)
+        {
+            word32 idx = HANDSHAKE_HEADER_SZ;
+            ret = DoHandShakeMsgType(ssl,
+                                     ssl->arrays->pendingMsg,
+                                     &idx, ssl->arrays->pendingMsgType,
+                                     ssl->arrays->pendingMsgSz - idx,
+                                     ssl->arrays->pendingMsgSz);
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (ret == WC_PENDING_E) {
+                /* setup to process fragment again */
+                ssl->arrays->pendingMsgOffset -= inputLength;
+                *inOutIdx -= inputLength;
+            }
+            else
+        #endif
+            {
+                XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS);
+                ssl->arrays->pendingMsg = NULL;
+                ssl->arrays->pendingMsgSz = 0;
+            }
+        }
+    }
+
+    WOLFSSL_LEAVE("DoHandShakeMsg()", ret);
+    return ret;
+}
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#ifdef WOLFSSL_DTLS
+
+static WC_INLINE int DtlsCheckWindow(WOLFSSL* ssl)
+{
+    word32* window;
+    word16 cur_hi, next_hi;
+    word32 cur_lo, next_lo, diff;
+    int curLT;
+    WOLFSSL_DTLS_PEERSEQ* peerSeq = NULL;
+
+    if (!ssl->options.haveMcast)
+        peerSeq = ssl->keys.peerSeq;
+    else {
+#ifdef WOLFSSL_MULTICAST
+        WOLFSSL_DTLS_PEERSEQ* p;
+        int i;
+
+        for (i = 0, p = ssl->keys.peerSeq;
+             i < WOLFSSL_DTLS_PEERSEQ_SZ;
+             i++, p++) {
+
+            if (p->peerId == ssl->keys.curPeerId) {
+                peerSeq = p;
+                break;
+            }
+        }
+#endif
+    }
+
+    if (peerSeq == NULL) {
+        WOLFSSL_MSG("Could not find peer sequence");
+        return 0;
+    }
+
+    if (ssl->keys.curEpoch == peerSeq->nextEpoch) {
+        next_hi = peerSeq->nextSeq_hi;
+        next_lo = peerSeq->nextSeq_lo;
+        window = peerSeq->window;
+    }
+    else if (ssl->keys.curEpoch == peerSeq->nextEpoch - 1) {
+        next_hi = peerSeq->prevSeq_hi;
+        next_lo = peerSeq->prevSeq_lo;
+        window = peerSeq->prevWindow;
+    }
+    else {
+        return 0;
+    }
+
+    cur_hi = ssl->keys.curSeq_hi;
+    cur_lo = ssl->keys.curSeq_lo;
+
+    /* If the difference between next and cur is > 2^32, way outside window. */
+    if ((cur_hi > next_hi + 1) || (next_hi > cur_hi + 1)) {
+        WOLFSSL_MSG("Current record from way too far in the future.");
+        return 0;
+    }
+
+    if (cur_hi == next_hi) {
+        curLT = cur_lo < next_lo;
+        diff = curLT ? next_lo - cur_lo : cur_lo - next_lo;
+    }
+    else {
+        curLT = cur_hi < next_hi;
+        diff = curLT ? cur_lo - next_lo : next_lo - cur_lo;
+    }
+
+    /* Check to see that the next value is greater than the number of messages
+     * trackable in the window, and that the difference between the next
+     * expected sequence number and the received sequence number is inside the
+     * window. */
+    if ((next_hi || next_lo > DTLS_SEQ_BITS) &&
+        curLT && (diff > DTLS_SEQ_BITS)) {
+
+        WOLFSSL_MSG("Current record sequence number from the past.");
+        return 0;
+    }
+#ifndef WOLFSSL_DTLS_ALLOW_FUTURE
+    else if (!curLT && (diff > DTLS_SEQ_BITS)) {
+        WOLFSSL_MSG("Rejecting message too far into the future.");
+        return 0;
+    }
+#endif
+    else if (curLT) {
+        word32 idx = diff / DTLS_WORD_BITS;
+        word32 newDiff = diff % DTLS_WORD_BITS;
+
+        /* verify idx is valid for window array */
+        if (idx >= WOLFSSL_DTLS_WINDOW_WORDS) {
+            WOLFSSL_MSG("Invalid DTLS windows index");
+            return 0;
+        }
+
+        if (window[idx] & (1 << newDiff)) {
+            WOLFSSL_MSG("Current record sequence number already received.");
+            return 0;
+        }
+    }
+
+    return 1;
+}
+
+
+#ifdef WOLFSSL_MULTICAST
+static WC_INLINE word32 UpdateHighwaterMark(word32 cur, word32 first,
+                                         word32 second, word32 max)
+{
+    word32 newCur = 0;
+
+    if (cur < first)
+        newCur = first;
+    else if (cur < second)
+        newCur = second;
+    else if (cur < max)
+        newCur = max;
+
+    return newCur;
+}
+#endif /* WOLFSSL_MULTICAST */
+
+
+static WC_INLINE int DtlsUpdateWindow(WOLFSSL* ssl)
+{
+    word32* window;
+    word32* next_lo;
+    word16* next_hi;
+    int curLT;
+    word32 cur_lo, diff;
+    word16 cur_hi;
+    WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys.peerSeq;
+
+    cur_hi = ssl->keys.curSeq_hi;
+    cur_lo = ssl->keys.curSeq_lo;
+
+#ifdef WOLFSSL_MULTICAST
+    if (ssl->options.haveMcast) {
+        WOLFSSL_DTLS_PEERSEQ* p;
+        int i;
+
+        peerSeq = NULL;
+        for (i = 0, p = ssl->keys.peerSeq;
+             i < WOLFSSL_DTLS_PEERSEQ_SZ;
+             i++, p++) {
+
+            if (p->peerId == ssl->keys.curPeerId) {
+                peerSeq = p;
+                break;
+            }
+        }
+
+        if (peerSeq == NULL) {
+            WOLFSSL_MSG("Couldn't find that peer ID to update window.");
+            return 0;
+        }
+
+        if (p->highwaterMark && cur_lo >= p->highwaterMark) {
+            int cbError = 0;
+
+            if (ssl->ctx->mcastHwCb)
+                cbError = ssl->ctx->mcastHwCb(p->peerId,
+                                              ssl->ctx->mcastMaxSeq,
+                                              cur_lo, ssl->mcastHwCbCtx);
+            if (cbError) {
+                WOLFSSL_MSG("Multicast highwater callback returned an error.");
+                return MCAST_HIGHWATER_CB_E;
+            }
+
+            p->highwaterMark = UpdateHighwaterMark(cur_lo,
+                                                   ssl->ctx->mcastFirstSeq,
+                                                   ssl->ctx->mcastSecondSeq,
+                                                   ssl->ctx->mcastMaxSeq);
+        }
+    }
+#endif
+
+    if (ssl->keys.curEpoch == peerSeq->nextEpoch) {
+        next_hi = &peerSeq->nextSeq_hi;
+        next_lo = &peerSeq->nextSeq_lo;
+        window = peerSeq->window;
+    }
+    else {
+        next_hi = &peerSeq->prevSeq_hi;
+        next_lo = &peerSeq->prevSeq_lo;
+        window = peerSeq->prevWindow;
+    }
+
+    if (cur_hi == *next_hi) {
+        curLT = cur_lo < *next_lo;
+        diff = curLT ? *next_lo - cur_lo : cur_lo - *next_lo;
+    }
+    else {
+        curLT = cur_hi < *next_hi;
+        diff = curLT ? cur_lo - *next_lo : *next_lo - cur_lo;
+    }
+
+    if (curLT) {
+        word32 idx = diff / DTLS_WORD_BITS;
+        word32 newDiff = diff % DTLS_WORD_BITS;
+
+        if (idx < WOLFSSL_DTLS_WINDOW_WORDS)
+            window[idx] |= (1 << newDiff);
+    }
+    else {
+        if (diff >= DTLS_SEQ_BITS)
+            XMEMSET(window, 0, DTLS_SEQ_SZ);
+        else {
+            word32 idx, newDiff, temp, i;
+            word32 oldWindow[WOLFSSL_DTLS_WINDOW_WORDS];
+
+            temp = 0;
+            diff++;
+            idx = diff / DTLS_WORD_BITS;
+            newDiff = diff % DTLS_WORD_BITS;
+
+            XMEMCPY(oldWindow, window, sizeof(oldWindow));
+
+            for (i = 0; i < WOLFSSL_DTLS_WINDOW_WORDS; i++) {
+                if (i < idx)
+                    window[i] = 0;
+                else {
+                    temp |= (oldWindow[i-idx] << newDiff);
+                    window[i] = temp;
+                    temp = oldWindow[i-idx] >> (DTLS_WORD_BITS - newDiff - 1);
+                }
+            }
+        }
+        window[0] |= 1;
+        *next_lo = cur_lo + 1;
+        if (*next_lo < cur_lo)
+            (*next_hi)++;
+    }
+
+    return 1;
+}
+
+
+static int DtlsMsgDrain(WOLFSSL* ssl)
+{
+    DtlsMsg* item = ssl->dtls_rx_msg_list;
+    int ret = 0;
+
+    WOLFSSL_ENTER("DtlsMsgDrain()");
+
+    /* While there is an item in the store list, and it is the expected
+     * message, and it is complete, and there hasn't been an error in the
+     * last message... */
+    while (item != NULL &&
+            ssl->keys.dtls_expected_peer_handshake_number == item->seq &&
+            item->fragSz == item->sz &&
+            ret == 0) {
+        word32 idx = 0;
+        ssl->keys.dtls_expected_peer_handshake_number++;
+        ret = DoHandShakeMsgType(ssl, item->msg,
+                                 &idx, item->type, item->sz, item->sz);
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        if (ret == WC_PENDING_E) {
+            ssl->keys.dtls_expected_peer_handshake_number--;
+            break;
+        }
+    #endif
+        ssl->dtls_rx_msg_list = item->next;
+        DtlsMsgDelete(item, ssl->heap);
+        item = ssl->dtls_rx_msg_list;
+        ssl->dtls_rx_msg_list_sz--;
+    }
+
+    WOLFSSL_LEAVE("DtlsMsgDrain()", ret);
+    return ret;
+}
+
+
+static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+                          word32 totalSz)
+{
+    byte type;
+    word32 size;
+    word32 fragOffset, fragSz;
+    int ret = 0;
+
+    WOLFSSL_ENTER("DoDtlsHandShakeMsg()");
+
+    /* process any pending DTLS messages - this flow can happen with async */
+    if (ssl->dtls_rx_msg_list != NULL) {
+        ret = DtlsMsgDrain(ssl);
+        if (ret != 0)
+            return ret;
+
+        /* if done processing fragment exit with success */
+        if (totalSz == *inOutIdx)
+            return ret;
+    }
+
+    /* parse header */
+    if (GetDtlsHandShakeHeader(ssl, input, inOutIdx, &type,
+                               &size, &fragOffset, &fragSz, totalSz) != 0) {
+        WOLFSSL_ERROR(PARSE_ERROR);
+        return PARSE_ERROR;
+    }
+
+    /* Cap the maximum size of a handshake message to something reasonable.
+     * By default is the maximum size of a certificate message assuming
+     * nine 2048-bit RSA certificates in the chain. */
+    if (size > MAX_HANDSHAKE_SZ) {
+        WOLFSSL_MSG("Handshake message too large");
+        return HANDSHAKE_SIZE_ERROR;
+    }
+
+    /* check that we have complete fragment */
+    if (*inOutIdx + fragSz > totalSz) {
+        WOLFSSL_ERROR(INCOMPLETE_DATA);
+        return INCOMPLETE_DATA;
+    }
+
+    /* Check the handshake sequence number first. If out of order,
+     * add the current message to the list. If the message is in order,
+     * but it is a fragment, add the current message to the list, then
+     * check the head of the list to see if it is complete, if so, pop
+     * it out as the current message. If the message is complete and in
+     * order, process it. Check the head of the list to see if it is in
+     * order, if so, process it. (Repeat until list exhausted.) If the
+     * head is out of order, return for more processing.
+     */
+    if (ssl->keys.dtls_peer_handshake_number >
+                                ssl->keys.dtls_expected_peer_handshake_number) {
+        /* Current message is out of order. It will get stored in the list.
+         * Storing also takes care of defragmentation. If the messages is a
+         * client hello, we need to process this out of order; the server
+         * is not supposed to keep state, but the second client hello will
+         * have a different handshake sequence number than is expected, and
+         * the server shouldn't be expecting any particular handshake sequence
+         * number. (If the cookie changes multiple times in quick succession,
+         * the client could be sending multiple new client hello messages
+         * with newer and newer cookies.) */
+        if (type != client_hello) {
+            if (ssl->dtls_rx_msg_list_sz < DTLS_POOL_SZ) {
+                DtlsMsgStore(ssl, ssl->keys.dtls_peer_handshake_number,
+                             input + *inOutIdx, size, type,
+                             fragOffset, fragSz, ssl->heap);
+            }
+            *inOutIdx += fragSz;
+            ret = 0;
+        }
+        else {
+            ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz);
+            if (ret == 0) {
+                ssl->keys.dtls_expected_peer_handshake_number =
+                    ssl->keys.dtls_peer_handshake_number + 1;
+            }
+        }
+    }
+    else if (ssl->keys.dtls_peer_handshake_number <
+                                ssl->keys.dtls_expected_peer_handshake_number) {
+        /* Already saw this message and processed it. It can be ignored. */
+        *inOutIdx += fragSz;
+        if(type == finished ) {
+        #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+            if (ssl->options.startedETMRead) {
+                word32 digestSz = MacSize(ssl);
+                if (*inOutIdx + ssl->keys.padSz + digestSz > totalSz)
+                    return BUFFER_E;
+                *inOutIdx += ssl->keys.padSz + digestSz;
+            }
+            else
+        #endif
+            {
+                if (*inOutIdx + ssl->keys.padSz > totalSz) {
+                    WOLFSSL_ERROR(BUFFER_E);
+                    return BUFFER_E;
+                }
+                *inOutIdx += ssl->keys.padSz;
+            }
+        }
+        if (IsDtlsNotSctpMode(ssl) &&
+            VerifyForDtlsMsgPoolSend(ssl, type, fragOffset)) {
+
+            ret = DtlsMsgPoolSend(ssl, 0);
+        }
+    }
+    else if (fragSz < size) {
+        /* Since this branch is in order, but fragmented, dtls_rx_msg_list will
+         * be pointing to the message with this fragment in it. Check it to see
+         * if it is completed. */
+        if (ssl->dtls_rx_msg_list_sz < DTLS_POOL_SZ) {
+            DtlsMsgStore(ssl, ssl->keys.dtls_peer_handshake_number,
+                         input + *inOutIdx, size, type,
+                         fragOffset, fragSz, ssl->heap);
+        }
+        *inOutIdx += fragSz;
+        ret = 0;
+        if (ssl->dtls_rx_msg_list != NULL &&
+            ssl->dtls_rx_msg_list->fragSz >= ssl->dtls_rx_msg_list->sz)
+            ret = DtlsMsgDrain(ssl);
+    }
+    else {
+        /* This branch is in order next, and a complete message. */
+        ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz);
+        if (ret == 0) {
+            if (type != client_hello || !IsDtlsNotSctpMode(ssl))
+                ssl->keys.dtls_expected_peer_handshake_number++;
+            if (ssl->dtls_rx_msg_list != NULL) {
+                ret = DtlsMsgDrain(ssl);
+            }
+        }
+    }
+
+    WOLFSSL_LEAVE("DoDtlsHandShakeMsg()", ret);
+    return ret;
+}
+#endif
+
+#ifndef WOLFSSL_NO_TLS12
+
+#ifdef HAVE_AEAD
+
+#if !defined(NO_PUBLIC_GCM_SET_IV) && \
+    (((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \
+    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) || \
+    (defined(HAVE_POLY1305) && defined(HAVE_CHACHA)))
+static WC_INLINE void AeadIncrementExpIV(WOLFSSL* ssl)
+{
+    int i;
+    for (i = AEAD_MAX_EXP_SZ-1; i >= 0; i--) {
+        if (++ssl->keys.aead_exp_IV[i]) return;
+    }
+}
+#endif
+
+
+#if defined(HAVE_POLY1305) && defined(HAVE_CHACHA)
+/* Used for the older version of creating AEAD tags with Poly1305 */
+static int Poly1305TagOld(WOLFSSL* ssl, byte* additional, const byte* out,
+                       byte* cipher, word16 sz, byte* tag)
+{
+    int ret       = 0;
+    int msglen    = (sz - ssl->specs.aead_mac_size);
+    word32 keySz  = 32;
+    byte padding[8]; /* used to temporarily store lengths */
+
+#ifdef CHACHA_AEAD_TEST
+      printf("Using old version of poly1305 input.\n");
+#endif
+
+    if (msglen < 0)
+        return INPUT_CASE_ERROR;
+
+    if ((ret = wc_Poly1305SetKey(ssl->auth.poly1305, cipher, keySz)) != 0)
+        return ret;
+
+    if ((ret = wc_Poly1305Update(ssl->auth.poly1305, additional,
+                   AEAD_AUTH_DATA_SZ)) != 0)
+        return ret;
+
+    /* length of additional input plus padding */
+    XMEMSET(padding, 0, sizeof(padding));
+    padding[0] = AEAD_AUTH_DATA_SZ;
+    if ((ret = wc_Poly1305Update(ssl->auth.poly1305, padding,
+                    sizeof(padding))) != 0)
+        return ret;
+
+
+    /* add cipher info and then its length */
+    XMEMSET(padding, 0, sizeof(padding));
+    if ((ret = wc_Poly1305Update(ssl->auth.poly1305, out, msglen)) != 0)
+        return ret;
+
+    /* 32 bit size of cipher to 64 bit endian */
+    padding[0] =  msglen        & 0xff;
+    padding[1] = (msglen >>  8) & 0xff;
+    padding[2] = ((word32)msglen >> 16) & 0xff;
+    padding[3] = ((word32)msglen >> 24) & 0xff;
+    if ((ret = wc_Poly1305Update(ssl->auth.poly1305, padding, sizeof(padding)))
+        != 0)
+        return ret;
+
+    /* generate tag */
+    if ((ret = wc_Poly1305Final(ssl->auth.poly1305, tag)) != 0)
+        return ret;
+
+    return ret;
+}
+
+
+/* When the flag oldPoly is not set this follows RFC7905. When oldPoly is set
+ * the implementation follows an older draft for creating the nonce and MAC.
+ * The flag oldPoly gets set automatically depending on what cipher suite was
+ * negotiated in the handshake. This is able to be done because the IDs for the
+ * cipher suites was updated in RFC7905 giving unique values for the older
+ * draft in comparison to the more recent RFC.
+ *
+ * ssl   WOLFSSL structure to get cipher and TLS state from
+ * out   output buffer to hold encrypted data
+ * input data to encrypt
+ * sz    size of input
+ *
+ * Return 0 on success negative values in error case
+ */
+static int  ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input,
+                              word16 sz)
+{
+    const byte* additionalSrc = input - RECORD_HEADER_SZ;
+    int ret       = 0;
+    word32 msgLen = (sz - ssl->specs.aead_mac_size);
+    byte tag[POLY1305_AUTH_SZ];
+    byte add[AEAD_AUTH_DATA_SZ];
+    byte nonce[CHACHA20_NONCE_SZ];
+    byte poly[CHACHA20_256_KEY_SIZE]; /* generated key for poly1305 */
+    #ifdef CHACHA_AEAD_TEST
+        int i;
+    #endif
+
+    XMEMSET(tag,   0, sizeof(tag));
+    XMEMSET(nonce, 0, sizeof(nonce));
+    XMEMSET(poly,  0, sizeof(poly));
+    XMEMSET(add,   0, sizeof(add));
+
+    /* opaque SEQ number stored for AD */
+    WriteSEQ(ssl, CUR_ORDER, add);
+
+    if (ssl->options.oldPoly != 0) {
+        /* get nonce. SEQ should not be incremented again here */
+        XMEMCPY(nonce + CHACHA20_OLD_OFFSET, add, OPAQUE32_LEN * 2);
+    }
+
+    /* Store the type, version. Unfortunately, they are in
+     * the input buffer ahead of the plaintext. */
+    #ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls) {
+            additionalSrc -= DTLS_HANDSHAKE_EXTRA;
+        }
+    #endif
+
+    /* add TLS message size to additional data */
+    add[AEAD_AUTH_DATA_SZ - 2] = (msgLen >> 8) & 0xff;
+    add[AEAD_AUTH_DATA_SZ - 1] =  msgLen       & 0xff;
+
+    XMEMCPY(add + AEAD_TYPE_OFFSET, additionalSrc, 3);
+
+    #ifdef CHACHA_AEAD_TEST
+        printf("Encrypt Additional : ");
+        for (i = 0; i < AEAD_AUTH_DATA_SZ; i++) {
+            printf("%02x", add[i]);
+        }
+        printf("\n\n");
+        printf("input before encryption :\n");
+        for (i = 0; i < sz; i++) {
+            printf("%02x", input[i]);
+            if ((i + 1) % 16 == 0)
+                printf("\n");
+        }
+        printf("\n");
+    #endif
+
+    if (ssl->options.oldPoly == 0) {
+        /* nonce is formed by 4 0x00 byte padded to the left followed by 8 byte
+         * record sequence number XORed with client_write_IV/server_write_IV */
+        XMEMCPY(nonce, ssl->keys.aead_enc_imp_IV, CHACHA20_IMP_IV_SZ);
+        nonce[4]  ^= add[0];
+        nonce[5]  ^= add[1];
+        nonce[6]  ^= add[2];
+        nonce[7]  ^= add[3];
+        nonce[8]  ^= add[4];
+        nonce[9]  ^= add[5];
+        nonce[10] ^= add[6];
+        nonce[11] ^= add[7];
+    }
+
+    /* set the nonce for chacha and get poly1305 key */
+    if ((ret = wc_Chacha_SetIV(ssl->encrypt.chacha, nonce, 0)) != 0) {
+        ForceZero(nonce, CHACHA20_NONCE_SZ);
+        return ret;
+    }
+
+    /* create Poly1305 key using chacha20 keystream */
+    if ((ret = wc_Chacha_Process(ssl->encrypt.chacha, poly,
+                                                    poly, sizeof(poly))) != 0) {
+        ForceZero(nonce, CHACHA20_NONCE_SZ);
+        return ret;
+    }
+
+    /* set the counter after getting poly1305 key */
+    if ((ret = wc_Chacha_SetIV(ssl->encrypt.chacha, nonce, 1)) != 0) {
+        ForceZero(nonce, CHACHA20_NONCE_SZ);
+        return ret;
+    }
+    ForceZero(nonce, CHACHA20_NONCE_SZ); /* done with nonce, clear it */
+
+    /* encrypt the plain text */
+    if ((ret = wc_Chacha_Process(ssl->encrypt.chacha, out,
+                                                         input, msgLen)) != 0) {
+        ForceZero(poly, sizeof(poly));
+        return ret;
+    }
+
+    /* get the poly1305 tag using either old padding scheme or more recent */
+    if (ssl->options.oldPoly != 0) {
+        if ((ret = Poly1305TagOld(ssl, add, (const byte* )out,
+                                                         poly, sz, tag)) != 0) {
+            ForceZero(poly, sizeof(poly));
+            return ret;
+        }
+    }
+    else {
+        if ((ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly,
+                                                          sizeof(poly))) != 0) {
+            ForceZero(poly, sizeof(poly));
+            return ret;
+        }
+        if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, add,
+                            sizeof(add), out, msgLen, tag, sizeof(tag))) != 0) {
+            ForceZero(poly, sizeof(poly));
+            return ret;
+        }
+    }
+    ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */
+
+    /* append tag to ciphertext */
+    XMEMCPY(out + msgLen, tag, sizeof(tag));
+
+    AeadIncrementExpIV(ssl);
+
+    #ifdef CHACHA_AEAD_TEST
+       printf("mac tag :\n");
+        for (i = 0; i < 16; i++) {
+           printf("%02x", tag[i]);
+           if ((i + 1) % 16 == 0)
+               printf("\n");
+        }
+       printf("\n\noutput after encrypt :\n");
+        for (i = 0; i < sz; i++) {
+           printf("%02x", out[i]);
+           if ((i + 1) % 16 == 0)
+               printf("\n");
+        }
+        printf("\n");
+    #endif
+
+    return ret;
+}
+
+
+/* When the flag oldPoly is not set this follows RFC7905. When oldPoly is set
+ * the implementation follows an older draft for creating the nonce and MAC.
+ * The flag oldPoly gets set automatically depending on what cipher suite was
+ * negotiated in the handshake. This is able to be done because the IDs for the
+ * cipher suites was updated in RFC7905 giving unique values for the older
+ * draft in comparison to the more recent RFC.
+ *
+ * ssl   WOLFSSL structure to get cipher and TLS state from
+ * plain output buffer to hold decrypted data
+ * input data to decrypt
+ * sz    size of input
+ *
+ * Return 0 on success negative values in error case
+ */
+static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input,
+                           word16 sz)
+{
+    byte add[AEAD_AUTH_DATA_SZ];
+    byte nonce[CHACHA20_NONCE_SZ];
+    byte tag[POLY1305_AUTH_SZ];
+    byte poly[CHACHA20_256_KEY_SIZE]; /* generated key for mac */
+    int ret    = 0;
+    int msgLen = (sz - ssl->specs.aead_mac_size);
+
+    #ifdef CHACHA_AEAD_TEST
+       int i;
+       printf("input before decrypt :\n");
+        for (i = 0; i < sz; i++) {
+           printf("%02x", input[i]);
+           if ((i + 1) % 16 == 0)
+               printf("\n");
+        }
+        printf("\n");
+    #endif
+
+    XMEMSET(tag,   0, sizeof(tag));
+    XMEMSET(poly,  0, sizeof(poly));
+    XMEMSET(nonce, 0, sizeof(nonce));
+    XMEMSET(add,   0, sizeof(add));
+
+    /* sequence number field is 64-bits */
+    WriteSEQ(ssl, PEER_ORDER, add);
+
+    if (ssl->options.oldPoly != 0) {
+        /* get nonce, SEQ should not be incremented again here */
+        XMEMCPY(nonce + CHACHA20_OLD_OFFSET, add, OPAQUE32_LEN * 2);
+    }
+
+    /* get AD info */
+    /* Store the type, version. */
+    add[AEAD_TYPE_OFFSET] = ssl->curRL.type;
+    add[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor;
+    add[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor;
+
+    /* add TLS message size to additional data */
+    add[AEAD_AUTH_DATA_SZ - 2] = (msgLen >> 8) & 0xff;
+    add[AEAD_AUTH_DATA_SZ - 1] =  msgLen       & 0xff;
+
+    #ifdef CHACHA_AEAD_TEST
+        printf("Decrypt Additional : ");
+        for (i = 0; i < AEAD_AUTH_DATA_SZ; i++) {
+            printf("%02x", add[i]);
+        }
+        printf("\n\n");
+    #endif
+
+    if (ssl->options.oldPoly == 0) {
+        /* nonce is formed by 4 0x00 byte padded to the left followed by 8 byte
+         * record sequence number XORed with client_write_IV/server_write_IV */
+        XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, CHACHA20_IMP_IV_SZ);
+        nonce[4]  ^= add[0];
+        nonce[5]  ^= add[1];
+        nonce[6]  ^= add[2];
+        nonce[7]  ^= add[3];
+        nonce[8]  ^= add[4];
+        nonce[9]  ^= add[5];
+        nonce[10] ^= add[6];
+        nonce[11] ^= add[7];
+    }
+
+    /* set nonce and get poly1305 key */
+    if ((ret = wc_Chacha_SetIV(ssl->decrypt.chacha, nonce, 0)) != 0) {
+        ForceZero(nonce, CHACHA20_NONCE_SZ);
+        return ret;
+    }
+
+    /* use chacha20 keystream to get poly1305 key for tag */
+    if ((ret = wc_Chacha_Process(ssl->decrypt.chacha, poly,
+                                                    poly, sizeof(poly))) != 0) {
+        ForceZero(nonce, CHACHA20_NONCE_SZ);
+        return ret;
+    }
+
+    /* set counter after getting poly1305 key */
+    if ((ret = wc_Chacha_SetIV(ssl->decrypt.chacha, nonce, 1)) != 0) {
+        ForceZero(nonce, CHACHA20_NONCE_SZ);
+        return ret;
+    }
+    ForceZero(nonce, CHACHA20_NONCE_SZ); /* done with nonce, clear it */
+
+    /* get the tag using Poly1305 */
+    if (ssl->options.oldPoly != 0) {
+        if ((ret = Poly1305TagOld(ssl, add, input, poly, sz, tag)) != 0) {
+            ForceZero(poly, sizeof(poly));
+            return ret;
+        }
+    }
+    else {
+        if ((ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly,
+                                                          sizeof(poly))) != 0) {
+            ForceZero(poly, sizeof(poly));
+            return ret;
+        }
+        if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, add,
+                   sizeof(add), (byte*)input, msgLen, tag, sizeof(tag))) != 0) {
+            ForceZero(poly, sizeof(poly));
+            return ret;
+        }
+    }
+    ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */
+
+    /* check tag sent along with packet */
+    if (ConstantCompare(input + msgLen, tag, ssl->specs.aead_mac_size) != 0) {
+        WOLFSSL_MSG("MAC did not match");
+        if (!ssl->options.dtls)
+            SendAlert(ssl, alert_fatal, bad_record_mac);
+        return VERIFY_MAC_ERROR;
+    }
+
+    /* if the tag was good decrypt message */
+    if ((ret = wc_Chacha_Process(ssl->decrypt.chacha, plain,
+                                                           input, msgLen)) != 0)
+        return ret;
+
+    #ifdef CHACHA_AEAD_TEST
+       printf("plain after decrypt :\n");
+        for (i = 0; i < sz; i++) {
+           printf("%02x", plain[i]);
+           if ((i + 1) % 16 == 0)
+               printf("\n");
+        }
+        printf("\n");
+    #endif
+
+    return ret;
+}
+#endif /* HAVE_CHACHA && HAVE_POLY1305 */
+#endif /* HAVE_AEAD */
+
+
+#if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
+
+#if !defined(NO_GCM_ENCRYPT_EXTRA) && \
+    ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \
+    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)))
+/* The following type is used to share code between AES-GCM and AES-CCM. */
+    typedef int (*AesAuthEncryptFunc)(Aes* aes, byte* out,
+                                       const byte* in, word32 sz,
+                                       byte* iv, word32 ivSz,
+                                       byte* authTag, word32 authTagSz,
+                                       const byte* authIn, word32 authInSz);
+    #define AES_AUTH_ENCRYPT_FUNC AesAuthEncryptFunc
+    #define AES_GCM_ENCRYPT wc_AesGcmEncrypt_ex
+    #define AES_CCM_ENCRYPT wc_AesCcmEncrypt_ex
+#else
+    #define AES_AUTH_ENCRYPT_FUNC wc_AesAuthEncryptFunc
+    #define AES_GCM_ENCRYPT wc_AesGcmEncrypt
+    #define AES_CCM_ENCRYPT wc_AesCcmEncrypt
+#endif
+
+#endif
+
+
+static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input,
+    word16 sz, int asyncOkay)
+{
+    int ret = 0;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    WC_ASYNC_DEV* asyncDev = NULL;
+    word32 event_flags = WC_ASYNC_FLAG_CALL_AGAIN;
+#else
+    (void)asyncOkay;
+#endif
+
+    (void)out;
+    (void)input;
+    (void)sz;
+
+    switch (ssl->specs.bulk_cipher_algorithm) {
+    #ifdef BUILD_ARC4
+        case wolfssl_rc4:
+            wc_Arc4Process(ssl->encrypt.arc4, out, input, sz);
+            break;
+    #endif
+
+    #ifdef BUILD_DES3
+        case wolfssl_triple_des:
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            /* initialize event */
+            asyncDev = &ssl->encrypt.des3->asyncDev;
+            ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags);
+            if (ret != 0)
+                break;
+        #endif
+
+            ret = wc_Des3_CbcEncrypt(ssl->encrypt.des3, out, input, sz);
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (ret == WC_PENDING_E && asyncOkay) {
+                ret = wolfSSL_AsyncPush(ssl, asyncDev);
+            }
+        #endif
+            break;
+    #endif
+
+    #if defined(BUILD_AES) && defined(HAVE_AES_CBC)
+        case wolfssl_aes:
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            /* initialize event */
+            asyncDev = &ssl->encrypt.aes->asyncDev;
+            ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags);
+            if (ret != 0)
+                break;
+        #endif
+        #if defined(WOLFSSL_RENESAS_TSIP_TLS) && \
+            !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION)
+            if (tsip_useable(ssl)) {
+                ret = wc_tsip_AesCbcEncrypt(ssl->encrypt.aes, out, input, sz);
+            } else
+        #endif
+            ret = wc_AesCbcEncrypt(ssl->encrypt.aes, out, input, sz);
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (ret == WC_PENDING_E && asyncOkay) {
+                ret = wolfSSL_AsyncPush(ssl, asyncDev);
+            }
+        #endif
+            break;
+    #endif
+
+    #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
+        case wolfssl_aes_gcm:
+        case wolfssl_aes_ccm:/* GCM AEAD macros use same size as CCM */
+        {
+            AES_AUTH_ENCRYPT_FUNC aes_auth_fn;
+            const byte* additionalSrc;
+
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            /* initialize event */
+            asyncDev = &ssl->encrypt.aes->asyncDev;
+            ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags);
+            if (ret != 0)
+                break;
+        #endif
+
+        #if defined(BUILD_AESGCM) && defined(HAVE_AESCCM)
+            aes_auth_fn = (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm)
+                            ? AES_GCM_ENCRYPT : AES_CCM_ENCRYPT;
+        #elif defined(BUILD_AESGCM)
+            aes_auth_fn = AES_GCM_ENCRYPT;
+        #else
+            aes_auth_fn = AES_CCM_ENCRYPT;
+        #endif
+            additionalSrc = input - 5;
+
+            XMEMSET(ssl->encrypt.additional, 0, AEAD_AUTH_DATA_SZ);
+
+            /* sequence number field is 64-bits */
+            WriteSEQ(ssl, CUR_ORDER, ssl->encrypt.additional);
+
+            /* Store the type, version. Unfortunately, they are in
+             * the input buffer ahead of the plaintext. */
+        #ifdef WOLFSSL_DTLS
+            if (ssl->options.dtls) {
+                additionalSrc -= DTLS_HANDSHAKE_EXTRA;
+            }
+        #endif
+            XMEMCPY(ssl->encrypt.additional + AEAD_TYPE_OFFSET,
+                                                        additionalSrc, 3);
+
+            /* Store the length of the plain text minus the explicit
+             * IV length minus the authentication tag size. */
+            c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
+                                ssl->encrypt.additional + AEAD_LEN_OFFSET);
+#if !defined(NO_PUBLIC_GCM_SET_IV) && \
+    ((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \
+    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)))
+            XMEMCPY(ssl->encrypt.nonce,
+                                ssl->keys.aead_enc_imp_IV, AESGCM_IMP_IV_SZ);
+            XMEMCPY(ssl->encrypt.nonce + AESGCM_IMP_IV_SZ,
+                                ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ);
+#endif
+            ret = aes_auth_fn(ssl->encrypt.aes,
+                    out + AESGCM_EXP_IV_SZ, input + AESGCM_EXP_IV_SZ,
+                    sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
+                    ssl->encrypt.nonce, AESGCM_NONCE_SZ,
+                    out + sz - ssl->specs.aead_mac_size,
+                    ssl->specs.aead_mac_size,
+                    ssl->encrypt.additional, AEAD_AUTH_DATA_SZ);
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (ret == WC_PENDING_E && asyncOkay) {
+                ret = wolfSSL_AsyncPush(ssl, asyncDev);
+            }
+        #endif
+#if !defined(NO_PUBLIC_GCM_SET_IV) && \
+    ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \
+    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)))
+            XMEMCPY(out,
+                    ssl->encrypt.nonce + AESGCM_IMP_IV_SZ, AESGCM_EXP_IV_SZ);
+#endif
+        }
+        break;
+    #endif /* BUILD_AESGCM || HAVE_AESCCM */
+
+    #ifdef HAVE_CAMELLIA
+        case wolfssl_camellia:
+            ret = wc_CamelliaCbcEncrypt(ssl->encrypt.cam, out, input, sz);
+            break;
+    #endif
+
+    #ifdef HAVE_HC128
+        case wolfssl_hc128:
+            ret = wc_Hc128_Process(ssl->encrypt.hc128, out, input, sz);
+            break;
+    #endif
+
+    #ifdef BUILD_RABBIT
+        case wolfssl_rabbit:
+            ret = wc_RabbitProcess(ssl->encrypt.rabbit, out, input, sz);
+            break;
+    #endif
+
+    #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
+        case wolfssl_chacha:
+            ret = ChachaAEADEncrypt(ssl, out, input, sz);
+            break;
+    #endif
+
+    #ifdef HAVE_NULL_CIPHER
+        case wolfssl_cipher_null:
+            if (input != out) {
+                XMEMMOVE(out, input, sz);
+            }
+            break;
+    #endif
+
+    #ifdef HAVE_IDEA
+        case wolfssl_idea:
+            ret = wc_IdeaCbcEncrypt(ssl->encrypt.idea, out, input, sz);
+            break;
+    #endif
+
+        default:
+            WOLFSSL_MSG("wolfSSL Encrypt programming error");
+            ret = ENCRYPT_ERROR;
+    }
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* if async is not okay, then block */
+    if (ret == WC_PENDING_E && !asyncOkay) {
+        ret = wc_AsyncWait(ret, asyncDev, event_flags);
+    }
+#endif
+
+    return ret;
+}
+
+static WC_INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 sz,
+    int asyncOkay)
+{
+    int ret = 0;
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ssl->error == WC_PENDING_E) {
+        ssl->error = 0; /* clear async */
+    }
+#endif
+
+    switch (ssl->encrypt.state) {
+        case CIPHER_STATE_BEGIN:
+        {
+            if (ssl->encrypt.setup == 0) {
+                WOLFSSL_MSG("Encrypt ciphers not setup");
+                return ENCRYPT_ERROR;
+            }
+
+        #ifdef HAVE_FUZZER
+            if (ssl->fuzzerCb)
+                ssl->fuzzerCb(ssl, input, sz, FUZZ_ENCRYPT, ssl->fuzzerCtx);
+        #endif
+
+        #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
+            /* make sure AES GCM/CCM memory is allocated */
+            /* free for these happens in FreeCiphers */
+            if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm ||
+                ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) {
+                /* make sure auth iv and auth are allocated */
+                if (ssl->encrypt.additional == NULL)
+                    ssl->encrypt.additional = (byte*)XMALLOC(AEAD_AUTH_DATA_SZ,
+                                                   ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+                if (ssl->encrypt.nonce == NULL)
+                    ssl->encrypt.nonce = (byte*)XMALLOC(AESGCM_NONCE_SZ,
+                                                   ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+                if (ssl->encrypt.additional == NULL ||
+                         ssl->encrypt.nonce == NULL) {
+                    return MEMORY_E;
+                }
+            }
+        #endif /* BUILD_AESGCM || HAVE_AESCCM */
+
+            /* Advance state and proceed */
+            ssl->encrypt.state = CIPHER_STATE_DO;
+        }
+        FALL_THROUGH;
+
+        case CIPHER_STATE_DO:
+        {
+            ret = EncryptDo(ssl, out, input, sz, asyncOkay);
+
+            /* Advance state */
+            ssl->encrypt.state = CIPHER_STATE_END;
+
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            /* If pending, then leave and return will resume below */
+            if (ret == WC_PENDING_E) {
+                return ret;
+            }
+        #endif
+        }
+        FALL_THROUGH;
+
+        case CIPHER_STATE_END:
+        {
+        #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
+            if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm ||
+                ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm)
+            {
+                /* finalize authentication cipher */
+#if !defined(NO_PUBLIC_GCM_SET_IV) && \
+    ((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \
+    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)))
+                AeadIncrementExpIV(ssl);
+#endif
+                if (ssl->encrypt.nonce)
+                    ForceZero(ssl->encrypt.nonce, AESGCM_NONCE_SZ);
+            }
+        #endif /* BUILD_AESGCM || HAVE_AESCCM */
+            break;
+        }
+    }
+
+    /* Reset state */
+    ssl->encrypt.state = CIPHER_STATE_BEGIN;
+
+    return ret;
+}
+
+
+static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input,
+                           word16 sz)
+{
+    int ret = 0;
+
+    (void)plain;
+    (void)input;
+    (void)sz;
+
+    switch (ssl->specs.bulk_cipher_algorithm)
+    {
+    #ifdef BUILD_ARC4
+        case wolfssl_rc4:
+            wc_Arc4Process(ssl->decrypt.arc4, plain, input, sz);
+            break;
+    #endif
+
+    #ifdef BUILD_DES3
+        case wolfssl_triple_des:
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            /* initialize event */
+            ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.des3->asyncDev,
+                WC_ASYNC_FLAG_CALL_AGAIN);
+            if (ret != 0)
+                break;
+        #endif
+
+            ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, plain, input, sz);
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (ret == WC_PENDING_E) {
+                ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.des3->asyncDev);
+            }
+        #endif
+            break;
+    #endif
+
+    #if defined(BUILD_AES) && defined(HAVE_AES_CBC)
+        case wolfssl_aes:
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            /* initialize event */
+            ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev,
+                WC_ASYNC_FLAG_CALL_AGAIN);
+            if (ret != 0)
+                break;
+        #endif
+        #if defined(WOLFSSL_RENESAS_TSIP_TLS) && \
+            !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION)
+            if (tsip_useable(ssl)) {
+                ret = wc_tsip_AesCbcDecrypt(ssl->decrypt.aes, plain, input, sz);
+            } else
+        #endif
+            ret = wc_AesCbcDecrypt(ssl->decrypt.aes, plain, input, sz);
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (ret == WC_PENDING_E) {
+                ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev);
+            }
+        #endif
+            break;
+    #endif
+
+    #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
+        case wolfssl_aes_gcm:
+        case wolfssl_aes_ccm: /* GCM AEAD macros use same size as CCM */
+        {
+            wc_AesAuthDecryptFunc aes_auth_fn;
+
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            /* initialize event */
+            ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev,
+                WC_ASYNC_FLAG_CALL_AGAIN);
+            if (ret != 0)
+                break;
+        #endif
+
+        #if defined(BUILD_AESGCM) && defined(HAVE_AESCCM)
+            aes_auth_fn = (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm)
+                            ? wc_AesGcmDecrypt : wc_AesCcmDecrypt;
+        #elif defined(BUILD_AESGCM)
+            aes_auth_fn = wc_AesGcmDecrypt;
+        #else
+            aes_auth_fn = wc_AesCcmDecrypt;
+        #endif
+
+            XMEMSET(ssl->decrypt.additional, 0, AEAD_AUTH_DATA_SZ);
+
+            /* sequence number field is 64-bits */
+            WriteSEQ(ssl, PEER_ORDER, ssl->decrypt.additional);
+
+            ssl->decrypt.additional[AEAD_TYPE_OFFSET] = ssl->curRL.type;
+            ssl->decrypt.additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor;
+            ssl->decrypt.additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor;
+
+            c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
+                                    ssl->decrypt.additional + AEAD_LEN_OFFSET);
+            XMEMCPY(ssl->decrypt.nonce, ssl->keys.aead_dec_imp_IV,
+                                                            AESGCM_IMP_IV_SZ);
+            XMEMCPY(ssl->decrypt.nonce + AESGCM_IMP_IV_SZ, input,
+                                                            AESGCM_EXP_IV_SZ);
+            if ((ret = aes_auth_fn(ssl->decrypt.aes,
+                        plain + AESGCM_EXP_IV_SZ,
+                        input + AESGCM_EXP_IV_SZ,
+                           sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
+                        ssl->decrypt.nonce, AESGCM_NONCE_SZ,
+                        input + sz - ssl->specs.aead_mac_size,
+                        ssl->specs.aead_mac_size,
+                        ssl->decrypt.additional, AEAD_AUTH_DATA_SZ)) < 0) {
+            #ifdef WOLFSSL_ASYNC_CRYPT
+                if (ret == WC_PENDING_E) {
+                    ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev);
+                }
+            #endif
+            }
+        }
+        break;
+    #endif /* BUILD_AESGCM || HAVE_AESCCM */
+
+    #ifdef HAVE_CAMELLIA
+        case wolfssl_camellia:
+            ret = wc_CamelliaCbcDecrypt(ssl->decrypt.cam, plain, input, sz);
+            break;
+    #endif
+
+    #ifdef HAVE_HC128
+        case wolfssl_hc128:
+            ret = wc_Hc128_Process(ssl->decrypt.hc128, plain, input, sz);
+            break;
+    #endif
+
+    #ifdef BUILD_RABBIT
+        case wolfssl_rabbit:
+            ret = wc_RabbitProcess(ssl->decrypt.rabbit, plain, input, sz);
+            break;
+    #endif
+
+    #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
+        case wolfssl_chacha:
+            ret = ChachaAEADDecrypt(ssl, plain, input, sz);
+            break;
+    #endif
+
+    #ifdef HAVE_NULL_CIPHER
+        case wolfssl_cipher_null:
+            if (input != plain) {
+                XMEMMOVE(plain, input, sz);
+            }
+            break;
+    #endif
+
+    #ifdef HAVE_IDEA
+        case wolfssl_idea:
+            ret = wc_IdeaCbcDecrypt(ssl->decrypt.idea, plain, input, sz);
+            break;
+    #endif
+
+        default:
+            WOLFSSL_MSG("wolfSSL Decrypt programming error");
+            ret = DECRYPT_ERROR;
+    }
+
+    return ret;
+}
+
+static WC_INLINE int Decrypt(WOLFSSL* ssl, byte* plain, const byte* input,
+                           word16 sz)
+{
+    int ret = 0;
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ret = wolfSSL_AsyncPop(ssl, &ssl->decrypt.state);
+    if (ret != WC_NOT_PENDING_E) {
+        /* check for still pending */
+        if (ret == WC_PENDING_E)
+            return ret;
+
+        ssl->error = 0; /* clear async */
+
+        /* let failures through so CIPHER_STATE_END logic is run */
+    }
+    else
+#endif
+    {
+        /* Reset state */
+        ret = 0;
+        ssl->decrypt.state = CIPHER_STATE_BEGIN;
+    }
+
+    switch (ssl->decrypt.state) {
+        case CIPHER_STATE_BEGIN:
+        {
+            if (ssl->decrypt.setup == 0) {
+                WOLFSSL_MSG("Decrypt ciphers not setup");
+                return DECRYPT_ERROR;
+            }
+
+        #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
+            /* make sure AES GCM/CCM memory is allocated */
+            /* free for these happens in FreeCiphers */
+            if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm ||
+                ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) {
+                /* make sure auth iv and auth are allocated */
+                if (ssl->decrypt.additional == NULL)
+                    ssl->decrypt.additional = (byte*)XMALLOC(AEAD_AUTH_DATA_SZ,
+                                                   ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+                if (ssl->decrypt.nonce == NULL)
+                    ssl->decrypt.nonce = (byte*)XMALLOC(AESGCM_NONCE_SZ,
+                                                   ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+                if (ssl->decrypt.additional == NULL ||
+                         ssl->decrypt.nonce == NULL) {
+                    return MEMORY_E;
+                }
+            }
+        #endif /* BUILD_AESGCM || HAVE_AESCCM */
+
+            /* Advance state and proceed */
+            ssl->decrypt.state = CIPHER_STATE_DO;
+        }
+        FALL_THROUGH;
+        case CIPHER_STATE_DO:
+        {
+            ret = DecryptDo(ssl, plain, input, sz);
+
+            /* Advance state */
+            ssl->decrypt.state = CIPHER_STATE_END;
+
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            /* If pending, leave and return below */
+            if (ret == WC_PENDING_E) {
+                return ret;
+            }
+        #endif
+        }
+        FALL_THROUGH;
+        case CIPHER_STATE_END:
+        {
+        #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
+            /* make sure AES GCM/CCM nonce is cleared */
+            if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm ||
+                ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) {
+                if (ssl->decrypt.nonce)
+                    ForceZero(ssl->decrypt.nonce, AESGCM_NONCE_SZ);
+
+                if (ret < 0)
+                    ret = VERIFY_MAC_ERROR;
+            }
+        #endif /* BUILD_AESGCM || HAVE_AESCCM */
+            break;
+        }
+    }
+
+    /* Reset state */
+    ssl->decrypt.state = CIPHER_STATE_BEGIN;
+
+    /* handle mac error case */
+    if (ret == VERIFY_MAC_ERROR) {
+        if (!ssl->options.dtls)
+            SendAlert(ssl, alert_fatal, bad_record_mac);
+
+        #ifdef WOLFSSL_DTLS_DROP_STATS
+            ssl->macDropCount++;
+        #endif /* WOLFSSL_DTLS_DROP_STATS */
+    }
+
+    return ret;
+}
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+/* Check conditions for a cipher to have an explicit IV.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 1 if the cipher in use has an explicit IV and 0 otherwise.
+ */
+static WC_INLINE int CipherHasExpIV(WOLFSSL *ssl)
+{
+#ifdef WOLFSSL_TLS13
+    if (ssl->options.tls1_3)
+        return 0;
+#endif
+    return (ssl->specs.cipher_type == aead) &&
+            (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha);
+}
+
+/* check cipher text size for sanity */
+static int SanityCheckCipherText(WOLFSSL* ssl, word32 encryptSz)
+{
+#ifdef HAVE_TRUNCATED_HMAC
+    word32 minLength = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ
+                                           : ssl->specs.hash_size;
+#else
+    word32 minLength = ssl->specs.hash_size; /* covers stream */
+#endif
+
+#ifndef WOLFSSL_AEAD_ONLY
+    if (ssl->specs.cipher_type == block) {
+#ifdef HAVE_ENCRYPT_THEN_MAC
+        if (ssl->options.startedETMRead) {
+            if ((encryptSz - MacSize(ssl)) % ssl->specs.block_size) {
+                WOLFSSL_MSG("Block ciphertext not block size");
+                return SANITY_CIPHER_E;
+            }
+        }
+        else
+#endif
+        if (encryptSz % ssl->specs.block_size) {
+            WOLFSSL_MSG("Block ciphertext not block size");
+            return SANITY_CIPHER_E;
+        }
+
+        minLength++;  /* pad byte */
+
+        if (ssl->specs.block_size > minLength)
+            minLength = ssl->specs.block_size;
+
+        if (ssl->options.tls1_1)
+            minLength += ssl->specs.block_size;  /* explicit IV */
+    }
+    else
+#endif
+    if (ssl->specs.cipher_type == aead) {
+        minLength = ssl->specs.aead_mac_size;    /* authTag size */
+        if (CipherHasExpIV(ssl))
+            minLength += AESGCM_EXP_IV_SZ;       /* explicit IV  */
+    }
+
+    if (encryptSz < minLength) {
+        WOLFSSL_MSG("Ciphertext not minimum size");
+        return SANITY_CIPHER_E;
+    }
+
+    return 0;
+}
+
+
+#ifndef WOLFSSL_AEAD_ONLY
+/* check all length bytes for the pad value, return 0 on success */
+static int PadCheck(const byte* a, byte pad, int length)
+{
+    int i;
+    int compareSum = 0;
+
+    for (i = 0; i < length; i++) {
+        compareSum |= a[i] ^ pad;
+    }
+
+    return compareSum;
+}
+
+
+/* Mask the padding bytes with the expected values.
+ * Constant time implementation - does maximum pad size possible.
+ *
+ * data   Message data.
+ * sz     Size of the message including MAC and padding and padding length.
+ * macSz  Size of the MAC.
+ * returns 0 on success, otherwise failure.
+ */
+static byte MaskPadding(const byte* data, int sz, int macSz)
+{
+    int i;
+    int checkSz = sz - 1;
+    byte paddingSz = data[sz - 1];
+    byte mask;
+    byte good = ctMaskGT(paddingSz, sz - 1 - macSz);
+
+    if (checkSz > TLS_MAX_PAD_SZ)
+        checkSz = TLS_MAX_PAD_SZ;
+
+    for (i = 0; i < checkSz; i++) {
+        mask = ctMaskLTE(i, paddingSz);
+        good |= mask & (data[sz - 1 - i] ^ paddingSz);
+    }
+
+    return good;
+}
+
+/* Mask the MAC in the message with the MAC calculated.
+ * Constant time implementation - starts looking for MAC where maximum padding
+ * size has it.
+ *
+ * data    Message data.
+ * sz      Size of the message including MAC and padding and padding length.
+ * macSz   Size of the MAC data.
+ * expMac  Expected MAC value.
+ * returns 0 on success, otherwise failure.
+ */
+static byte MaskMac(const byte* data, int sz, int macSz, byte* expMac)
+{
+    int i, j;
+    unsigned char mac[WC_MAX_DIGEST_SIZE];
+    int scanStart = sz - 1 - TLS_MAX_PAD_SZ - macSz;
+    int macEnd = sz - 1 - data[sz - 1];
+    int macStart = macEnd - macSz;
+    int r = 0;
+    unsigned char started, notEnded;
+    unsigned char good = 0;
+
+    scanStart &= ctMaskIntGTE(scanStart, 0);
+    macStart &= ctMaskIntGTE(macStart, 0);
+
+    /* Div on Intel has different speeds depending on value.
+     * Use a bitwise AND or mod a specific value (converted to mul). */
+    if ((macSz & (macSz - 1)) == 0)
+        r = (macSz - (scanStart - macStart)) & (macSz - 1);
+#ifndef NO_SHA
+    else if (macSz == WC_SHA_DIGEST_SIZE)
+        r = (macSz - (scanStart - macStart)) % WC_SHA_DIGEST_SIZE;
+#endif
+#ifdef WOLFSSL_SHA384
+    else if (macSz == WC_SHA384_DIGEST_SIZE)
+        r = (macSz - (scanStart - macStart)) % WC_SHA384_DIGEST_SIZE;
+#endif
+
+    XMEMSET(mac, 0, macSz);
+    for (i = scanStart; i < sz; i += macSz) {
+        for (j = 0; j < macSz && j + i < sz; j++) {
+            started = ctMaskGTE(i + j, macStart);
+            notEnded = ctMaskLT(i + j, macEnd);
+            mac[j] |= started & notEnded & data[i + j];
+        }
+    }
+
+    if ((macSz & (macSz - 1)) == 0) {
+        for (i = 0; i < macSz; i++)
+            good |= expMac[i] ^ mac[(i + r) & (macSz - 1)];
+    }
+#ifndef NO_SHA
+    else if (macSz == WC_SHA_DIGEST_SIZE) {
+        for (i = 0; i < macSz; i++)
+            good |= expMac[i] ^ mac[(i + r) % WC_SHA_DIGEST_SIZE];
+    }
+#endif
+#ifdef WOLFSSL_SHA384
+    else if (macSz == WC_SHA384_DIGEST_SIZE) {
+        for (i = 0; i < macSz; i++)
+            good |= expMac[i] ^ mac[(i + r) % WC_SHA384_DIGEST_SIZE];
+    }
+#endif
+
+    return good;
+}
+
+/* timing resistant pad/verify check, return 0 on success */
+int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int macSz,
+                    int pLen, int content)
+{
+    byte verify[WC_MAX_DIGEST_SIZE];
+    byte good;
+    int  ret = 0;
+
+    good = MaskPadding(input, pLen, macSz);
+    /* 4th argument has potential to underflow, ssl->hmac function should
+     * either increment the size by (macSz + padLen + 1) before use or check on
+     * the size to make sure is valid. */
+    ret = ssl->hmac(ssl, verify, input, pLen - macSz - padLen - 1, padLen,
+                                                                    content, 1);
+    good |= MaskMac(input, pLen, ssl->specs.hash_size, verify);
+
+    /* Non-zero on failure. */
+    good = (byte)~(word32)good;
+    good &= good >> 4;
+    good &= good >> 2;
+    good &= good >> 1;
+    /* Make ret negative on masking failure. */
+    ret -= 1 - good;
+
+    /* Treat any failure as verify MAC error. */
+    if (ret != 0)
+        ret = VERIFY_MAC_ERROR;
+
+    return ret;
+}
+#endif
+
+
+int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx)
+{
+    word32 msgSz   = ssl->keys.encryptSz;
+    word32 idx     = *inOutIdx;
+    int    dataSz;
+    int    ivExtra = 0;
+    byte*  rawData = input + idx;  /* keep current  for hmac */
+#ifdef HAVE_LIBZ
+    byte   *decomp = NULL;
+#endif
+
+#ifdef WOLFSSL_EARLY_DATA
+    if (ssl->options.tls1_3 && ssl->options.handShakeDone == 0) {
+        if (ssl->options.side == WOLFSSL_SERVER_END &&
+                          ssl->earlyData != no_early_data &&
+                          ssl->options.clientState < CLIENT_FINISHED_COMPLETE) {
+            ssl->earlyDataSz += ssl->curSize;
+            if (ssl->earlyDataSz <= ssl->options.maxEarlyDataSz) {
+                WOLFSSL_MSG("Ignoring EarlyData!");
+                *inOutIdx = ssl->buffers.inputBuffer.length;
+                return 0;
+            }
+            WOLFSSL_MSG("Too much EarlyData!");
+        }
+    }
+#endif
+    if (ssl->options.handShakeDone == 0) {
+        WOLFSSL_MSG("Received App data before a handshake completed");
+        SendAlert(ssl, alert_fatal, unexpected_message);
+        return OUT_OF_ORDER_E;
+    }
+
+#ifndef WOLFSSL_AEAD_ONLY
+    if (ssl->specs.cipher_type == block) {
+        if (ssl->options.tls1_1)
+            ivExtra = ssl->specs.block_size;
+    }
+    else
+#endif
+    if (ssl->specs.cipher_type == aead) {
+        if (CipherHasExpIV(ssl))
+            ivExtra = AESGCM_EXP_IV_SZ;
+    }
+
+    dataSz = msgSz - ivExtra - ssl->keys.padSz;
+#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+    if (ssl->options.startedETMRead)
+        dataSz -= MacSize(ssl);
+#endif
+    if (dataSz < 0) {
+        WOLFSSL_MSG("App data buffer error, malicious input?");
+        SendAlert(ssl, alert_fatal, unexpected_message);
+        return BUFFER_ERROR;
+    }
+#ifdef WOLFSSL_EARLY_DATA
+    if (ssl->earlyData > early_data_ext) {
+        if (ssl->earlyDataSz + dataSz > ssl->options.maxEarlyDataSz) {
+            SendAlert(ssl, alert_fatal, unexpected_message);
+            return WOLFSSL_FATAL_ERROR;
+        }
+        ssl->earlyDataSz += dataSz;
+    }
+#endif
+
+    /* read data */
+    if (dataSz) {
+        int rawSz = dataSz;       /* keep raw size for idx adjustment */
+
+#ifdef HAVE_LIBZ
+        if (ssl->options.usingCompression) {
+            int dcomp_size = MAX_RECORD_SIZE + MAX_COMP_EXTRA;
+            decomp = XMALLOC(dcomp_size, ssl->heap, DYNAMIC_TYPE_NONE);
+            if (decomp == NULL)
+                return WOLFSSL_FATAL_ERROR;
+            dataSz = myDeCompress(ssl, rawData, dataSz, decomp, dcomp_size);
+            if (dataSz < 0) return dataSz;
+        }
+#endif
+        idx += rawSz;
+
+        ssl->buffers.clearOutputBuffer.buffer = rawData;
+        ssl->buffers.clearOutputBuffer.length = dataSz;
+    }
+
+    idx += ssl->keys.padSz;
+#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+    if (ssl->options.startedETMRead)
+        idx += MacSize(ssl);
+#endif
+
+#ifdef HAVE_LIBZ
+    /* decompress could be bigger, overwrite after verify */
+    if (ssl->options.usingCompression)
+        XMEMMOVE(rawData, decomp, dataSz);
+    XFREE(decomp, ssl->heap, DYNAMIC_TYPE_NONE);
+#endif
+
+    *inOutIdx = idx;
+    return 0;
+}
+
+
+/* process alert, return level */
+static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type,
+                   word32 totalSz)
+{
+    byte level;
+    byte code;
+    word32 dataSz = totalSz - *inOutIdx;
+
+    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+        if (ssl->hsInfoOn)
+            AddPacketName(ssl, "Alert");
+        if (ssl->toInfoOn)
+            /* add record header back on to info + alert bytes level/code */
+            AddPacketInfo(ssl, "Alert", alert, input + *inOutIdx -
+                          RECORD_HEADER_SZ, RECORD_HEADER_SZ + ALERT_SIZE,
+                          READ_PROTO, ssl->heap);
+    #endif
+
+    if (IsEncryptionOn(ssl, 0)) {
+        dataSz -= ssl->keys.padSz;
+    #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+        if (ssl->options.startedETMRead)
+            dataSz -= MacSize(ssl);
+    #endif
+    }
+
+    /* make sure can read the message */
+    if (dataSz != ALERT_SIZE) {
+#ifdef WOLFSSL_EXTRA_ALERTS
+        SendAlert(ssl, alert_fatal, unexpected_message);
+#endif
+        return BUFFER_E;
+    }
+
+    level = input[(*inOutIdx)++];
+    code  = input[(*inOutIdx)++];
+    ssl->alert_history.last_rx.code = code;
+    ssl->alert_history.last_rx.level = level;
+    *type = code;
+    if (level == alert_fatal) {
+        ssl->options.isClosed = 1;  /* Don't send close_notify */
+    }
+
+    if (++ssl->options.alertCount >= WOLFSSL_ALERT_COUNT_MAX) {
+        WOLFSSL_MSG("Alert count exceeded");
+#ifdef WOLFSSL_EXTRA_ALERTS
+        if (level != alert_warning || code != close_notify)
+            SendAlert(ssl, alert_fatal, unexpected_message);
+#endif
+        return ALERT_COUNT_E;
+    }
+
+    WOLFSSL_MSG("Got alert");
+    if (*type == close_notify) {
+        WOLFSSL_MSG("\tclose notify");
+        ssl->options.closeNotify = 1;
+    }
+#ifdef WOLFSSL_TLS13
+    if (*type == decode_error) {
+        WOLFSSL_MSG("\tdecode error");
+    }
+    if (*type == illegal_parameter) {
+        WOLFSSL_MSG("\tillegal parameter");
+    }
+#endif
+    WOLFSSL_ERROR(*type);
+    if (IsEncryptionOn(ssl, 0)) {
+        *inOutIdx += ssl->keys.padSz;
+    #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+        if (ssl->options.startedETMRead)
+            *inOutIdx += MacSize(ssl);
+    #endif
+    }
+
+    return level;
+}
+
+static int GetInputData(WOLFSSL *ssl, word32 size)
+{
+    int in;
+    int inSz;
+    int maxLength;
+    int usedLength;
+    int dtlsExtra = 0;
+
+
+    /* check max input length */
+    usedLength = ssl->buffers.inputBuffer.length - ssl->buffers.inputBuffer.idx;
+    maxLength  = ssl->buffers.inputBuffer.bufferSize - usedLength;
+    inSz       = (int)(size - usedLength);      /* from last partial read */
+
+#ifdef WOLFSSL_DTLS
+    if (ssl->options.dtls) {
+        if (size < ssl->dtls_expected_rx)
+            dtlsExtra = (int)(ssl->dtls_expected_rx - size);
+        inSz = ssl->dtls_expected_rx;
+    }
+#endif
+
+    /* check that no lengths or size values are negative */
+    if (usedLength < 0 || maxLength < 0 || inSz <= 0) {
+        return BUFFER_ERROR;
+    }
+
+    if (inSz > maxLength) {
+        if (GrowInputBuffer(ssl, size + dtlsExtra, usedLength) < 0)
+            return MEMORY_E;
+    }
+
+    /* Put buffer data at start if not there */
+    if (usedLength > 0 && ssl->buffers.inputBuffer.idx != 0)
+        XMEMMOVE(ssl->buffers.inputBuffer.buffer,
+                ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx,
+                usedLength);
+
+    /* remove processed data */
+    ssl->buffers.inputBuffer.idx    = 0;
+    ssl->buffers.inputBuffer.length = usedLength;
+
+    /* read data from network */
+    do {
+        in = wolfSSLReceive(ssl,
+                     ssl->buffers.inputBuffer.buffer +
+                     ssl->buffers.inputBuffer.length,
+                     inSz);
+        if (in == WANT_READ)
+            return WANT_READ;
+
+        if (in < 0)
+            return SOCKET_ERROR_E;
+
+        if (in > inSz)
+            return RECV_OVERFLOW_E;
+
+        ssl->buffers.inputBuffer.length += in;
+        inSz -= in;
+
+    } while (ssl->buffers.inputBuffer.length < size);
+
+#ifdef WOLFSSL_DEBUG_TLS
+    if (ssl->buffers.inputBuffer.idx == 0) {
+        WOLFSSL_MSG("Data received");
+        WOLFSSL_BUFFER(ssl->buffers.inputBuffer.buffer,
+                       ssl->buffers.inputBuffer.length);
+    }
+#endif
+
+    return 0;
+}
+
+#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+static WC_INLINE int VerifyMacEnc(WOLFSSL* ssl, const byte* input, word32 msgSz,
+                                  int content)
+{
+    int    ret;
+#ifdef HAVE_TRUNCATED_HMAC
+    word32 digestSz = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ
+                                          : ssl->specs.hash_size;
+#else
+    word32 digestSz = ssl->specs.hash_size;
+#endif
+    byte   verify[WC_MAX_DIGEST_SIZE];
+
+    WOLFSSL_MSG("Verify MAC of Encrypted Data");
+
+    if (msgSz < digestSz) {
+        return VERIFY_MAC_ERROR;
+    }
+
+    ret  = ssl->hmac(ssl, verify, input, msgSz - digestSz, -1, content, 1);
+    ret |= ConstantCompare(verify, input + msgSz - digestSz, digestSz);
+    if (ret != 0) {
+        return VERIFY_MAC_ERROR;
+    }
+
+    return 0;
+}
+#endif
+
+static WC_INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz,
+                            int content, word32* padSz)
+{
+#if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_AEAD_ONLY)
+    int    ivExtra = 0;
+    int    ret;
+    word32 pad     = 0;
+    word32 padByte = 0;
+#ifdef HAVE_TRUNCATED_HMAC
+    word32 digestSz = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ
+                                          : ssl->specs.hash_size;
+#else
+    word32 digestSz = ssl->specs.hash_size;
+#endif
+    byte   verify[WC_MAX_DIGEST_SIZE];
+
+
+    if (ssl->specs.cipher_type == block) {
+        if (ssl->options.tls1_1)
+            ivExtra = ssl->specs.block_size;
+        pad = *(input + msgSz - ivExtra - 1);
+        padByte = 1;
+
+        if (ssl->options.tls) {
+            ret = TimingPadVerify(ssl, input, pad, digestSz, msgSz - ivExtra,
+                                  content);
+            if (ret != 0)
+                return ret;
+        }
+        else {  /* sslv3, some implementations have bad padding, but don't
+                 * allow bad read */
+            int  badPadLen = 0;
+            byte dmy[sizeof(WOLFSSL) >= MAX_PAD_SIZE ? 1 : MAX_PAD_SIZE] = {0};
+            byte* dummy = sizeof(dmy) < MAX_PAD_SIZE ? (byte*) ssl : dmy;
+
+            (void)dmy;
+
+            if (pad > (msgSz - digestSz - 1)) {
+                WOLFSSL_MSG("Plain Len not long enough for pad/mac");
+                pad       = 0;  /* no bad read */
+                badPadLen = 1;
+            }
+            PadCheck(dummy, (byte)pad, MAX_PAD_SIZE);  /* timing only */
+            ret = ssl->hmac(ssl, verify, input, msgSz - digestSz - pad - 1, pad,
+                                                                    content, 1);
+            if (ConstantCompare(verify, input + msgSz - digestSz - pad - 1,
+                                digestSz) != 0)
+                return VERIFY_MAC_ERROR;
+            if (ret != 0 || badPadLen)
+                return VERIFY_MAC_ERROR;
+        }
+    }
+    else if (ssl->specs.cipher_type == stream) {
+        ret = ssl->hmac(ssl, verify, input, msgSz - digestSz, -1, content, 1);
+        if (ConstantCompare(verify, input + msgSz - digestSz, digestSz) != 0){
+            return VERIFY_MAC_ERROR;
+        }
+        if (ret != 0)
+            return VERIFY_MAC_ERROR;
+    }
+#endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_AEAD_ONLY */
+
+    if (ssl->specs.cipher_type == aead) {
+        *padSz = ssl->specs.aead_mac_size;
+    }
+#if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_AEAD_ONLY)
+    else {
+        *padSz = digestSz + pad + padByte;
+    }
+#endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_AEAD_ONLY */
+
+    (void)input;
+    (void)msgSz;
+    (void)content;
+
+    return 0;
+}
+
+
+/* process input requests, return 0 is done, 1 is call again to complete, and
+   negative number is error */
+int ProcessReply(WOLFSSL* ssl)
+{
+    int    ret = 0, type, readSz;
+    int    atomicUser = 0;
+    word32 startIdx = 0;
+#if defined(WOLFSSL_DTLS)
+    int    used;
+#endif
+
+#ifdef ATOMIC_USER
+    if (ssl->ctx->DecryptVerifyCb)
+        atomicUser = 1;
+#endif
+
+    if (ssl->error != 0 && ssl->error != WANT_READ && ssl->error != WANT_WRITE
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        && ssl->error != WC_PENDING_E
+    #endif
+    #ifdef WOLFSSL_NONBLOCK_OCSP
+        && ssl->error != OCSP_WANT_READ
+    #endif
+    ) {
+        WOLFSSL_MSG("ProcessReply retry in error state, not allowed");
+        return ssl->error;
+    }
+
+    for (;;) {
+        switch (ssl->options.processReply) {
+
+        /* in the WOLFSSL_SERVER case, get the first byte for detecting
+         * old client hello */
+        case doProcessInit:
+
+            readSz = RECORD_HEADER_SZ;
+
+        #ifdef WOLFSSL_DTLS
+            if (ssl->options.dtls)
+                readSz = DTLS_RECORD_HEADER_SZ;
+        #endif
+
+            /* get header or return error */
+            if (!ssl->options.dtls) {
+                if ((ret = GetInputData(ssl, readSz)) < 0)
+                    return ret;
+            } else {
+            #ifdef WOLFSSL_DTLS
+                /* read ahead may already have header */
+                used = ssl->buffers.inputBuffer.length -
+                       ssl->buffers.inputBuffer.idx;
+                if (used < readSz) {
+                    if ((ret = GetInputData(ssl, readSz)) < 0)
+                        return ret;
+                }
+            #endif
+            }
+
+#ifdef OLD_HELLO_ALLOWED
+
+            /* see if sending SSLv2 client hello */
+            if ( ssl->options.side == WOLFSSL_SERVER_END &&
+                 ssl->options.clientState == NULL_STATE &&
+                 ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx]
+                         != handshake) {
+                byte b0, b1;
+
+                ssl->options.processReply = runProcessOldClientHello;
+
+                /* sanity checks before getting size at front */
+                if (ssl->buffers.inputBuffer.buffer[
+                          ssl->buffers.inputBuffer.idx + OPAQUE16_LEN] != OLD_HELLO_ID) {
+                    WOLFSSL_MSG("Not a valid old client hello");
+                    return PARSE_ERROR;
+                }
+
+                if (ssl->buffers.inputBuffer.buffer[
+                          ssl->buffers.inputBuffer.idx + OPAQUE24_LEN] != SSLv3_MAJOR &&
+                    ssl->buffers.inputBuffer.buffer[
+                          ssl->buffers.inputBuffer.idx + OPAQUE24_LEN] != DTLS_MAJOR) {
+                    WOLFSSL_MSG("Not a valid version in old client hello");
+                    return PARSE_ERROR;
+                }
+
+                /* how many bytes need ProcessOldClientHello */
+                b0 =
+                ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx++];
+                b1 =
+                ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx++];
+                ssl->curSize = (word16)(((b0 & 0x7f) << 8) | b1);
+            }
+            else {
+                ssl->options.processReply = getRecordLayerHeader;
+                continue;
+            }
+            FALL_THROUGH;
+
+        /* in the WOLFSSL_SERVER case, run the old client hello */
+        case runProcessOldClientHello:
+
+            /* get sz bytes or return error */
+            if (!ssl->options.dtls) {
+                if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
+                    return ret;
+            } else {
+            #ifdef WOLFSSL_DTLS
+                /* read ahead may already have */
+                used = ssl->buffers.inputBuffer.length -
+                       ssl->buffers.inputBuffer.idx;
+                if (used < ssl->curSize)
+                    if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
+                        return ret;
+            #endif  /* WOLFSSL_DTLS */
+            }
+
+            ret = ProcessOldClientHello(ssl, ssl->buffers.inputBuffer.buffer,
+                                        &ssl->buffers.inputBuffer.idx,
+                                        ssl->buffers.inputBuffer.length -
+                                        ssl->buffers.inputBuffer.idx,
+                                        ssl->curSize);
+            if (ret < 0)
+                return ret;
+
+            else if (ssl->buffers.inputBuffer.idx ==
+                     ssl->buffers.inputBuffer.length) {
+                ssl->options.processReply = doProcessInit;
+                return 0;
+            }
+
+#endif  /* OLD_HELLO_ALLOWED */
+            FALL_THROUGH;
+
+        /* get the record layer header */
+        case getRecordLayerHeader:
+
+            ret = GetRecordHeader(ssl, ssl->buffers.inputBuffer.buffer,
+                                       &ssl->buffers.inputBuffer.idx,
+                                       &ssl->curRL, &ssl->curSize);
+#ifdef WOLFSSL_DTLS
+            if (ssl->options.dtls && ret == SEQUENCE_ERROR) {
+                WOLFSSL_MSG("Silently dropping out of order DTLS message");
+                ssl->options.processReply = doProcessInit;
+                ssl->buffers.inputBuffer.length = 0;
+                ssl->buffers.inputBuffer.idx = 0;
+#ifdef WOLFSSL_DTLS_DROP_STATS
+                ssl->replayDropCount++;
+#endif /* WOLFSSL_DTLS_DROP_STATS */
+
+                if (IsDtlsNotSctpMode(ssl) && ssl->options.dtlsHsRetain) {
+                    ret = DtlsMsgPoolSend(ssl, 0);
+                    if (ret != 0)
+                        return ret;
+                }
+
+                continue;
+            }
+#endif
+            if (ret != 0)
+                return ret;
+
+#ifdef WOLFSSL_TLS13
+            if (IsAtLeastTLSv1_3(ssl->version) && IsEncryptionOn(ssl, 0) &&
+                                        ssl->curRL.type != application_data &&
+                                        ssl->curRL.type != change_cipher_spec) {
+                SendAlert(ssl, alert_fatal, unexpected_message);
+                return PARSE_ERROR;
+            }
+#endif
+
+            ssl->options.processReply = getData;
+            FALL_THROUGH;
+
+        /* retrieve record layer data */
+        case getData:
+
+            /* get sz bytes or return error */
+            if (!ssl->options.dtls) {
+                if ((ret = GetInputData(ssl, ssl->curSize)) < 0) {
+#ifdef WOLFSSL_EXTRA_ALERTS
+                    if (ret != WANT_READ)
+                        SendAlert(ssl, alert_fatal, bad_record_mac);
+#endif
+                    return ret;
+                }
+            }
+            else {
+#ifdef WOLFSSL_DTLS
+                /* read ahead may already have */
+                used = ssl->buffers.inputBuffer.length -
+                       ssl->buffers.inputBuffer.idx;
+                if (used < ssl->curSize)
+                    if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
+                        return ret;
+#endif
+            }
+
+            if (IsEncryptionOn(ssl, 0)) {
+                int tooLong = 0;
+
+#ifdef WOLFSSL_TLS13
+                if (IsAtLeastTLSv1_3(ssl->version)) {
+                    tooLong  = ssl->curSize > MAX_TLS13_ENC_SZ;
+                    tooLong |= ssl->curSize - ssl->specs.aead_mac_size >
+                                                             MAX_TLS13_PLAIN_SZ;
+                }
+#endif
+#ifdef WOLFSSL_EXTRA_ALERTS
+                if (!IsAtLeastTLSv1_3(ssl->version))
+                    tooLong = ssl->curSize > MAX_TLS_CIPHER_SZ;
+#endif
+                if (tooLong) {
+                    WOLFSSL_MSG("Encrypted data too long");
+#if defined(WOLFSSL_TLS13) || defined(WOLFSSL_EXTRA_ALERTS)
+                    SendAlert(ssl, alert_fatal, record_overflow);
+#endif
+                    return BUFFER_ERROR;
+                }
+            }
+            ssl->keys.padSz = 0;
+
+            ssl->options.processReply = verifyEncryptedMessage;
+            startIdx = ssl->buffers.inputBuffer.idx;  /* in case > 1 msg per */
+            FALL_THROUGH;
+
+        /* verify digest of encrypted message */
+        case verifyEncryptedMessage:
+#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+            if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0 &&
+                                   !atomicUser && ssl->options.startedETMRead) {
+                ret = VerifyMacEnc(ssl, ssl->buffers.inputBuffer.buffer +
+                                   ssl->buffers.inputBuffer.idx,
+                                   ssl->curSize, ssl->curRL.type);
+            #ifdef WOLFSSL_ASYNC_CRYPT
+                if (ret == WC_PENDING_E)
+                    return ret;
+            #endif
+                if (ret < 0) {
+                    WOLFSSL_MSG("VerifyMacEnc failed");
+                    WOLFSSL_ERROR(ret);
+                #ifdef WOLFSSL_DTLS
+                    /* If in DTLS mode, if the decrypt fails for any
+                     * reason, pretend the datagram never happened. */
+                    if (ssl->options.dtls) {
+                        ssl->options.processReply = doProcessInit;
+                        ssl->buffers.inputBuffer.idx =
+                                        ssl->buffers.inputBuffer.length;
+                        #ifdef WOLFSSL_DTLS_DROP_STATS
+                            ssl->macDropCount++;
+                        #endif /* WOLFSSL_DTLS_DROP_STATS */
+                    }
+                #endif /* WOLFSSL_DTLS */
+                #ifdef WOLFSSL_EXTRA_ALERTS
+                    if (!ssl->options.dtls)
+                        SendAlert(ssl, alert_fatal, bad_record_mac);
+                #endif
+                    return DECRYPT_ERROR;
+                }
+                ssl->keys.encryptSz    = ssl->curSize;
+            }
+#endif
+            ssl->options.processReply = decryptMessage;
+            FALL_THROUGH;
+
+        /* decrypt message */
+        case decryptMessage:
+
+#if !defined(WOLFSSL_TLS13) || defined(WOLFSSL_TLS13_DRAFT_18)
+            if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0)
+#else
+            if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0 &&
+                                        (!IsAtLeastTLSv1_3(ssl->version) ||
+                                         ssl->curRL.type != change_cipher_spec))
+#endif
+            {
+                bufferStatic* in = &ssl->buffers.inputBuffer;
+
+                ret = SanityCheckCipherText(ssl, ssl->curSize);
+                if (ret < 0) {
+                #ifdef WOLFSSL_EXTRA_ALERTS
+                    SendAlert(ssl, alert_fatal, bad_record_mac);
+                #endif
+                    return ret;
+                }
+
+                if (atomicUser) {
+        #ifdef ATOMIC_USER
+            #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+                    if (ssl->options.startedETMRead) {
+                        ret = ssl->ctx->VerifyDecryptCb(ssl,
+                                     in->buffer + in->idx, in->buffer + in->idx,
+                                     ssl->curSize - MacSize(ssl),
+                                     ssl->curRL.type, 1, &ssl->keys.padSz,
+                                     ssl->DecryptVerifyCtx);
+                    }
+                    else
+            #endif
+                    {
+                        ret = ssl->ctx->DecryptVerifyCb(ssl,
+                                      in->buffer + in->idx,
+                                      in->buffer + in->idx,
+                                      ssl->curSize, ssl->curRL.type, 1,
+                                      &ssl->keys.padSz, ssl->DecryptVerifyCtx);
+                    }
+        #endif /* ATOMIC_USER */
+                }
+                else {
+                    if (!ssl->options.tls1_3) {
+        #ifndef WOLFSSL_NO_TLS12
+            #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+                    if (ssl->options.startedETMRead) {
+                        word32 digestSz = MacSize(ssl);
+                        ret = Decrypt(ssl,
+                                      in->buffer + in->idx,
+                                      in->buffer + in->idx,
+                                      ssl->curSize - digestSz);
+                         ssl->keys.padSz =
+                              in->buffer[in->idx + ssl->curSize - digestSz - 1];
+                         ssl->keys.padSz += 1;
+                         ssl->keys.decryptedCur = 1;
+                    }
+                    else
+            #endif
+                    {
+                        ret = Decrypt(ssl,
+                                      in->buffer + in->idx,
+                                      in->buffer + in->idx,
+                                      ssl->curSize);
+                    }
+        #else
+                        ret = DECRYPT_ERROR;
+        #endif
+                    }
+                    else
+                    {
+                #ifdef WOLFSSL_TLS13
+                    #if defined(WOLFSSL_TLS13_DRAFT_18) || \
+                        defined(WOLFSSL_TLS13_DRAFT_22) || \
+                        defined(WOLFSSL_TLS13_DRAFT_23)
+                        ret = DecryptTls13(ssl,
+                                           in->buffer + in->idx,
+                                           in->buffer + in->idx,
+                                           ssl->curSize, NULL, 0);
+                    #else
+                        ret = DecryptTls13(ssl,
+                                        in->buffer + in->idx,
+                                        in->buffer + in->idx,
+                                        ssl->curSize,
+                                        (byte*)&ssl->curRL, RECORD_HEADER_SZ);
+                    #endif
+                #else
+                        ret = DECRYPT_ERROR;
+                #endif /* WOLFSSL_TLS13 */
+                    }
+                }
+
+            #ifdef WOLFSSL_ASYNC_CRYPT
+                if (ret == WC_PENDING_E)
+                    return ret;
+            #endif
+
+                if (ret >= 0) {
+            #ifndef WOLFSSL_NO_TLS12
+                    /* handle success */
+                #ifndef WOLFSSL_AEAD_ONLY
+                    if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
+                        ssl->buffers.inputBuffer.idx += ssl->specs.block_size;
+                #endif
+                        /* go past TLSv1.1 IV */
+                    if (CipherHasExpIV(ssl))
+                        ssl->buffers.inputBuffer.idx += AESGCM_EXP_IV_SZ;
+            #endif
+                }
+                else {
+                    WOLFSSL_MSG("Decrypt failed");
+                    WOLFSSL_ERROR(ret);
+                #ifdef WOLFSSL_EARLY_DATA
+                    if (ssl->options.tls1_3) {
+                         if (ssl->options.side == WOLFSSL_SERVER_END &&
+                                 ssl->earlyData != no_early_data &&
+                                 ssl->options.clientState <
+                                                     CLIENT_FINISHED_COMPLETE) {
+                            ssl->earlyDataSz += ssl->curSize;
+                            if (ssl->earlyDataSz <=
+                                                  ssl->options.maxEarlyDataSz) {
+                                WOLFSSL_MSG("Ignoring EarlyData!");
+                                if (ssl->keys.peer_sequence_number_lo-- == 0)
+                                    ssl->keys.peer_sequence_number_hi--;
+                                ssl->options.processReply = doProcessInit;
+                                ssl->buffers.inputBuffer.idx =
+                                                ssl->buffers.inputBuffer.length;
+                                return 0;
+                            }
+                            WOLFSSL_MSG("Too much EarlyData!");
+                        }
+                        SendAlert(ssl, alert_fatal, bad_record_mac);
+                    }
+                #endif
+                #ifdef WOLFSSL_DTLS
+                    /* If in DTLS mode, if the decrypt fails for any
+                     * reason, pretend the datagram never happened. */
+                    if (ssl->options.dtls) {
+                        ssl->options.processReply = doProcessInit;
+                        ssl->buffers.inputBuffer.idx =
+                                        ssl->buffers.inputBuffer.length;
+                        #ifdef WOLFSSL_DTLS_DROP_STATS
+                            ssl->macDropCount++;
+                        #endif /* WOLFSSL_DTLS_DROP_STATS */
+                    }
+                #endif /* WOLFSSL_DTLS */
+                    return DECRYPT_ERROR;
+                }
+            }
+
+            ssl->options.processReply = verifyMessage;
+            FALL_THROUGH;
+
+        /* verify digest of message */
+        case verifyMessage:
+
+#if !defined(WOLFSSL_TLS13) || defined(WOLFSSL_TLS13_DRAFT_18)
+            if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0)
+#else
+            if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0 &&
+                                        (!IsAtLeastTLSv1_3(ssl->version) ||
+                                         ssl->curRL.type != change_cipher_spec))
+#endif
+            {
+                if (!atomicUser
+#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+                                && !ssl->options.startedETMRead
+#endif
+                    ) {
+                    ret = VerifyMac(ssl, ssl->buffers.inputBuffer.buffer +
+                                    ssl->buffers.inputBuffer.idx,
+                                    ssl->curSize, ssl->curRL.type,
+                                    &ssl->keys.padSz);
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    if (ret == WC_PENDING_E)
+                        return ret;
+                #endif
+                    if (ret < 0) {
+                        WOLFSSL_MSG("VerifyMac failed");
+                        WOLFSSL_ERROR(ret);
+                    #ifdef WOLFSSL_DTLS
+                        /* If in DTLS mode, if the decrypt fails for any
+                         * reason, pretend the datagram never happened. */
+                        if (ssl->options.dtls) {
+                            ssl->options.processReply = doProcessInit;
+                            ssl->buffers.inputBuffer.idx =
+                                            ssl->buffers.inputBuffer.length;
+                            #ifdef WOLFSSL_DTLS_DROP_STATS
+                                ssl->macDropCount++;
+                            #endif /* WOLFSSL_DTLS_DROP_STATS */
+                        }
+                    #endif /* WOLFSSL_DTLS */
+                    #ifdef WOLFSSL_EXTRA_ALERTS
+                        if (!ssl->options.dtls)
+                            SendAlert(ssl, alert_fatal, bad_record_mac);
+                    #endif
+                        return DECRYPT_ERROR;
+                    }
+                }
+
+                ssl->keys.encryptSz    = ssl->curSize;
+                ssl->keys.decryptedCur = 1;
+#ifdef WOLFSSL_TLS13
+                if (ssl->options.tls1_3) {
+                    word16 i = (word16)(ssl->buffers.inputBuffer.length -
+                                        ssl->keys.padSz);
+                    /* Remove padding from end of plain text. */
+                    for (--i; i > ssl->buffers.inputBuffer.idx; i--) {
+                        if (ssl->buffers.inputBuffer.buffer[i] != 0)
+                            break;
+                    }
+                    /* Get the real content type from the end of the data. */
+                    ssl->curRL.type = ssl->buffers.inputBuffer.buffer[i];
+                    ssl->keys.padSz = ssl->buffers.inputBuffer.length - i;
+                }
+#endif
+            }
+
+            ssl->options.processReply = runProcessingOneMessage;
+            FALL_THROUGH;
+
+        /* the record layer is here */
+        case runProcessingOneMessage:
+
+       #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+            if (IsEncryptionOn(ssl, 0) && ssl->options.startedETMRead) {
+                if (ssl->buffers.inputBuffer.length - ssl->keys.padSz -
+                                              ssl->buffers.inputBuffer.idx -
+                                              MacSize(ssl) > MAX_PLAINTEXT_SZ) {
+                    WOLFSSL_MSG("Plaintext too long - Encrypt-Then-MAC");
+            #if defined(WOLFSSL_EXTRA_ALERTS)
+                    SendAlert(ssl, alert_fatal, record_overflow);
+            #endif
+                    return BUFFER_ERROR;
+                }
+            }
+            else
+       #endif
+            if (ssl->buffers.inputBuffer.length - ssl->keys.padSz -
+                              ssl->buffers.inputBuffer.idx > MAX_PLAINTEXT_SZ) {
+                WOLFSSL_MSG("Plaintext too long");
+#if defined(WOLFSSL_TLS13) || defined(WOLFSSL_EXTRA_ALERTS)
+                SendAlert(ssl, alert_fatal, record_overflow);
+#endif
+                return BUFFER_ERROR;
+            }
+
+        #ifdef WOLFSSL_DTLS
+            if (IsDtlsNotSctpMode(ssl)) {
+                DtlsUpdateWindow(ssl);
+            }
+        #endif /* WOLFSSL_DTLS */
+
+            WOLFSSL_MSG("received record layer msg");
+
+            switch (ssl->curRL.type) {
+                case handshake :
+                    /* debugging in DoHandShakeMsg */
+                    if (ssl->options.dtls) {
+#ifdef WOLFSSL_DTLS
+                        ret = DoDtlsHandShakeMsg(ssl,
+                                            ssl->buffers.inputBuffer.buffer,
+                                            &ssl->buffers.inputBuffer.idx,
+                                            ssl->buffers.inputBuffer.length);
+#endif
+                    }
+                    else if (!IsAtLeastTLSv1_3(ssl->version)) {
+#ifndef WOLFSSL_NO_TLS12
+                        ret = DoHandShakeMsg(ssl,
+                                            ssl->buffers.inputBuffer.buffer,
+                                            &ssl->buffers.inputBuffer.idx,
+                                            ssl->buffers.inputBuffer.length);
+#else
+                        ret = BUFFER_ERROR;
+#endif
+                    }
+                    else {
+#ifdef WOLFSSL_TLS13
+                        ret = DoTls13HandShakeMsg(ssl,
+                                            ssl->buffers.inputBuffer.buffer,
+                                            &ssl->buffers.inputBuffer.idx,
+                                            ssl->buffers.inputBuffer.length);
+    #ifdef WOLFSSL_EARLY_DATA
+                        if (ret != 0)
+                            return ret;
+                        if (ssl->options.side == WOLFSSL_SERVER_END &&
+                                ssl->earlyData > early_data_ext &&
+                                ssl->options.handShakeState == HANDSHAKE_DONE) {
+                            ssl->earlyData = no_early_data;
+                            ssl->options.processReply = doProcessInit;
+                            return ZERO_RETURN;
+                        }
+    #endif
+#else
+                        ret = BUFFER_ERROR;
+#endif
+                    }
+                    if (ret != 0) {
+                        WOLFSSL_ERROR(ret);
+                        return ret;
+                    }
+                    break;
+
+                case change_cipher_spec:
+                    WOLFSSL_MSG("got CHANGE CIPHER SPEC");
+                    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+                        if (ssl->hsInfoOn)
+                            AddPacketName(ssl, "ChangeCipher");
+                        /* add record header back on info */
+                        if (ssl->toInfoOn) {
+                            AddPacketInfo(ssl, "ChangeCipher",
+                                change_cipher_spec,
+                                ssl->buffers.inputBuffer.buffer +
+                                ssl->buffers.inputBuffer.idx - RECORD_HEADER_SZ,
+                                1 + RECORD_HEADER_SZ, READ_PROTO, ssl->heap);
+                            #ifdef WOLFSSL_CALLBACKS
+                            AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo);
+                            #endif
+                        }
+                    #endif
+
+#ifdef WOLFSSL_TLS13
+    #ifdef WOLFSSL_TLS13_DRAFT_18
+                    if (IsAtLeastTLSv1_3(ssl->version)) {
+                        SendAlert(ssl, alert_fatal, illegal_parameter);
+                        return UNKNOWN_RECORD_TYPE;
+                    }
+    #else
+                    if (IsAtLeastTLSv1_3(ssl->version)) {
+                        word32 i = ssl->buffers.inputBuffer.idx;
+                        if (ssl->options.handShakeState == HANDSHAKE_DONE) {
+                            SendAlert(ssl, alert_fatal, unexpected_message);
+                            return UNKNOWN_RECORD_TYPE;
+                        }
+                        if (ssl->curSize != 1 ||
+                                      ssl->buffers.inputBuffer.buffer[i] != 1) {
+                            SendAlert(ssl, alert_fatal, illegal_parameter);
+                            return UNKNOWN_RECORD_TYPE;
+                        }
+                        ssl->buffers.inputBuffer.idx++;
+                        break;
+                    }
+    #endif
+#endif
+
+#ifndef WOLFSSL_NO_TLS12
+                    ret = SanityCheckMsgReceived(ssl, change_cipher_hs);
+                    if (ret != 0) {
+                        if (!ssl->options.dtls) {
+                            return ret;
+                        }
+                        else {
+                        #ifdef WOLFSSL_DTLS
+                        /* Check for duplicate CCS message in DTLS mode.
+                         * DTLS allows for duplicate messages, and it should be
+                         * skipped. Also skip if out of order. */
+                            if (ret != DUPLICATE_MSG_E && ret != OUT_OF_ORDER_E)
+                                return ret;
+
+                            if (IsDtlsNotSctpMode(ssl)) {
+                                ret = DtlsMsgPoolSend(ssl, 1);
+                                if (ret != 0)
+                                    return ret;
+                            }
+
+                            if (ssl->curSize != 1) {
+                                WOLFSSL_MSG("Malicious or corrupted"
+                                            " duplicate ChangeCipher msg");
+                                return LENGTH_ERROR;
+                            }
+                            ssl->buffers.inputBuffer.idx++;
+                            break;
+                        #endif /* WOLFSSL_DTLS */
+                        }
+                    }
+
+                    if (IsEncryptionOn(ssl, 0) && ssl->options.handShakeDone) {
+                        ssl->buffers.inputBuffer.idx += ssl->keys.padSz;
+                        ssl->curSize -= (word16) ssl->buffers.inputBuffer.idx;
+            #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+                        if (ssl->options.startedETMRead) {
+                            word32 digestSz = MacSize(ssl);
+                            ssl->buffers.inputBuffer.idx += digestSz;
+                            ssl->curSize -= digestSz;
+                        }
+            #endif
+                    }
+
+                    if (ssl->curSize != 1) {
+                        WOLFSSL_MSG("Malicious or corrupted ChangeCipher msg");
+                        return LENGTH_ERROR;
+                    }
+
+                    ssl->buffers.inputBuffer.idx++;
+                    ssl->keys.encryptionOn = 1;
+
+                    /* setup decrypt keys for following messages */
+                    /* XXX This might not be what we want to do when
+                     * receiving a CCS with multicast. We update the
+                     * key when the application updates them. */
+                    if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
+                        return ret;
+
+            #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+                    ssl->options.startedETMRead = ssl->options.encThenMac;
+            #endif
+
+                    #ifdef WOLFSSL_DTLS
+                        if (ssl->options.dtls) {
+                            WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys.peerSeq;
+#ifdef WOLFSSL_MULTICAST
+                            if (ssl->options.haveMcast) {
+                                peerSeq += ssl->keys.curPeerId;
+                                peerSeq->highwaterMark = UpdateHighwaterMark(0,
+                                        ssl->ctx->mcastFirstSeq,
+                                        ssl->ctx->mcastSecondSeq,
+                                        ssl->ctx->mcastMaxSeq);
+                            }
+#endif
+                            peerSeq->nextEpoch++;
+                            peerSeq->prevSeq_lo = peerSeq->nextSeq_lo;
+                            peerSeq->prevSeq_hi = peerSeq->nextSeq_hi;
+                            peerSeq->nextSeq_lo = 0;
+                            peerSeq->nextSeq_hi = 0;
+                            XMEMCPY(peerSeq->prevWindow, peerSeq->window,
+                                    DTLS_SEQ_SZ);
+                            XMEMSET(peerSeq->window, 0, DTLS_SEQ_SZ);
+                        }
+                    #endif
+
+                    #ifdef HAVE_LIBZ
+                        if (ssl->options.usingCompression)
+                            if ( (ret = InitStreams(ssl)) != 0)
+                                return ret;
+                    #endif
+                    ret = BuildFinished(ssl, &ssl->hsHashes->verifyHashes,
+                                       ssl->options.side == WOLFSSL_CLIENT_END ?
+                                       server : client);
+                    if (ret != 0)
+                        return ret;
+#endif /* !WOLFSSL_NO_TLS12 */
+                    break;
+
+                case application_data:
+                    WOLFSSL_MSG("got app DATA");
+                    #ifdef WOLFSSL_DTLS
+                        if (ssl->options.dtls && ssl->options.dtlsHsRetain) {
+                            FreeHandshakeResources(ssl);
+                            ssl->options.dtlsHsRetain = 0;
+                        }
+                    #endif
+                    #ifdef WOLFSSL_TLS13
+                        if (ssl->keys.keyUpdateRespond) {
+                            WOLFSSL_MSG("No KeyUpdate from peer seen");
+                            return SANITY_MSG_E;
+                        }
+                    #endif
+                    if ((ret = DoApplicationData(ssl,
+                                                ssl->buffers.inputBuffer.buffer,
+                                                &ssl->buffers.inputBuffer.idx))
+                                                                         != 0) {
+                        WOLFSSL_ERROR(ret);
+                        return ret;
+                    }
+                    break;
+
+                case alert:
+                    WOLFSSL_MSG("got ALERT!");
+                    ret = DoAlert(ssl, ssl->buffers.inputBuffer.buffer,
+                                  &ssl->buffers.inputBuffer.idx, &type,
+                                   ssl->buffers.inputBuffer.length);
+                    if (ret == alert_fatal)
+                        return FATAL_ERROR;
+                    else if (ret < 0)
+                        return ret;
+
+                    /* catch warnings that are handled as errors */
+                    if (type == close_notify)
+                        return ssl->error = ZERO_RETURN;
+
+                    if (type == decrypt_error)
+                        return FATAL_ERROR;
+                    break;
+
+                default:
+                    WOLFSSL_ERROR(UNKNOWN_RECORD_TYPE);
+                    return UNKNOWN_RECORD_TYPE;
+            }
+
+            ssl->options.processReply = doProcessInit;
+
+            /* input exhausted? */
+            if (ssl->buffers.inputBuffer.idx >= ssl->buffers.inputBuffer.length)
+                return 0;
+
+            /* more messages per record */
+            else if ((ssl->buffers.inputBuffer.idx - startIdx) < ssl->curSize) {
+                WOLFSSL_MSG("More messages in record");
+
+                ssl->options.processReply = runProcessingOneMessage;
+
+                if (IsEncryptionOn(ssl, 0)) {
+                    WOLFSSL_MSG("Bundled encrypted messages, remove middle pad");
+            #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+                    if (ssl->options.startedETMRead) {
+                        word32 digestSz = MacSize(ssl);
+                        if (ssl->buffers.inputBuffer.idx >=
+                                                   ssl->keys.padSz + digestSz) {
+                            ssl->buffers.inputBuffer.idx -=
+                                                     ssl->keys.padSz + digestSz;
+                        }
+                        else {
+                            WOLFSSL_MSG("\tmiddle padding error");
+                            return FATAL_ERROR;
+                        }
+                    }
+                    else
+             #endif
+                    {
+                        if (ssl->buffers.inputBuffer.idx >= ssl->keys.padSz) {
+                            ssl->buffers.inputBuffer.idx -= ssl->keys.padSz;
+                        }
+                        else {
+                            WOLFSSL_MSG("\tmiddle padding error");
+                            return FATAL_ERROR;
+                        }
+                    }
+                }
+
+                continue;
+            }
+            /* more records */
+            else {
+                WOLFSSL_MSG("More records in input");
+                ssl->options.processReply = doProcessInit;
+                continue;
+            }
+
+        default:
+            WOLFSSL_MSG("Bad process input state, programming error");
+            return INPUT_CASE_ERROR;
+        }
+    }
+    return FATAL_ERROR;
+}
+
+
+int SendChangeCipher(WOLFSSL* ssl)
+{
+    byte              *output;
+    int                sendSz = RECORD_HEADER_SZ + ENUM_LEN;
+    int                idx    = RECORD_HEADER_SZ;
+    int                ret;
+
+    #ifdef OPENSSL_EXTRA
+    ssl->cbmode = SSL_CB_MODE_WRITE;
+    if (ssl->options.side == WOLFSSL_SERVER_END){
+        ssl->options.serverState = SERVER_CHANGECIPHERSPEC_COMPLETE;
+        if (ssl->CBIS != NULL)
+            ssl->CBIS(ssl, SSL_CB_ACCEPT_LOOP, SSL_SUCCESS);
+    }
+    else{
+        ssl->options.clientState =
+            CLIENT_CHANGECIPHERSPEC_COMPLETE;
+        if (ssl->CBIS != NULL)
+            ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, SSL_SUCCESS);
+    }
+    #endif
+
+    #ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls) {
+            sendSz += DTLS_RECORD_EXTRA;
+            idx    += DTLS_RECORD_EXTRA;
+        }
+    #endif
+
+    /* are we in scr */
+    if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) {
+        sendSz += MAX_MSG_EXTRA;
+    }
+
+    /* check for available size */
+    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+        return ret;
+
+    /* get output buffer */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+
+    AddRecordHeader(output, 1, change_cipher_spec, ssl);
+
+    output[idx] = 1;             /* turn it on */
+
+    if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) {
+        byte input[ENUM_LEN];
+        int  inputSz = ENUM_LEN;
+
+        input[0] = 1;  /* turn it on */
+        sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
+                              change_cipher_spec, 0, 0, 0);
+        if (sendSz < 0) {
+            return sendSz;
+        }
+    }
+
+    #ifdef WOLFSSL_DTLS
+        if (IsDtlsNotSctpMode(ssl)) {
+            DtlsSEQIncrement(ssl, CUR_ORDER);
+            if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
+                return ret;
+        }
+    #endif
+    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+        if (ssl->hsInfoOn) AddPacketName(ssl, "ChangeCipher");
+        if (ssl->toInfoOn)
+            AddPacketInfo(ssl, "ChangeCipher", change_cipher_spec, output,
+                    sendSz, WRITE_PROTO, ssl->heap);
+    #endif
+    ssl->buffers.outputBuffer.length += sendSz;
+
+    if (ssl->options.groupMessages)
+        return 0;
+    #if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_DEBUG_DTLS)
+    else if (ssl->options.dtls) {
+        /* If using DTLS, force the ChangeCipherSpec message to be in the
+         * same datagram as the finished message. */
+        return 0;
+    }
+    #endif
+    else
+        return SendBuffered(ssl);
+}
+
+
+#if !defined(NO_OLD_TLS) && !defined(WOLFSSL_AEAD_ONLY)
+static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
+                    int padLen, int content, int verify)
+{
+    byte   result[WC_MAX_DIGEST_SIZE];
+    word32 digestSz = ssl->specs.hash_size;            /* actual sizes */
+    word32 padSz    = ssl->specs.pad_size;
+    int    ret      = 0;
+
+    wc_Md5 md5;
+    wc_Sha sha;
+
+    /* data */
+    byte seq[SEQ_SZ];
+    byte conLen[ENUM_LEN + LENGTH_SZ];     /* content & length */
+    const byte* macSecret = wolfSSL_GetMacSecret(ssl, verify);
+
+    (void)padLen;
+
+#ifdef HAVE_FUZZER
+    if (ssl->fuzzerCb)
+        ssl->fuzzerCb(ssl, in, sz, FUZZ_HMAC, ssl->fuzzerCtx);
+#endif
+
+    XMEMSET(seq, 0, SEQ_SZ);
+    conLen[0] = (byte)content;
+    c16toa((word16)sz, &conLen[ENUM_LEN]);
+    WriteSEQ(ssl, verify, seq);
+
+    if (ssl->specs.mac_algorithm == md5_mac) {
+        ret =  wc_InitMd5_ex(&md5, ssl->heap, ssl->devId);
+        if (ret != 0)
+            return ret;
+
+        /* inner */
+        ret =  wc_Md5Update(&md5, macSecret, digestSz);
+        ret |= wc_Md5Update(&md5, PAD1, padSz);
+        ret |= wc_Md5Update(&md5, seq, SEQ_SZ);
+        ret |= wc_Md5Update(&md5, conLen, sizeof(conLen));
+        /* in buffer */
+        ret |= wc_Md5Update(&md5, in, sz);
+        if (ret != 0)
+            return VERIFY_MAC_ERROR;
+        ret = wc_Md5Final(&md5, result);
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        /* TODO: Make non-blocking */
+        if (ret == WC_PENDING_E) {
+            ret = wc_AsyncWait(ret, &md5.asyncDev, WC_ASYNC_FLAG_NONE);
+        }
+    #endif
+        if (ret != 0)
+            return VERIFY_MAC_ERROR;
+
+        /* outer */
+        ret =  wc_Md5Update(&md5, macSecret, digestSz);
+        ret |= wc_Md5Update(&md5, PAD2, padSz);
+        ret |= wc_Md5Update(&md5, result, digestSz);
+        if (ret != 0)
+            return VERIFY_MAC_ERROR;
+        ret =  wc_Md5Final(&md5, digest);
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        /* TODO: Make non-blocking */
+        if (ret == WC_PENDING_E) {
+            ret = wc_AsyncWait(ret, &md5.asyncDev, WC_ASYNC_FLAG_NONE);
+        }
+    #endif
+        if (ret != 0)
+            return VERIFY_MAC_ERROR;
+
+        wc_Md5Free(&md5);
+    }
+    else {
+        ret =  wc_InitSha_ex(&sha, ssl->heap, ssl->devId);
+        if (ret != 0)
+            return ret;
+
+        /* inner */
+        ret =  wc_ShaUpdate(&sha, macSecret, digestSz);
+        ret |= wc_ShaUpdate(&sha, PAD1, padSz);
+        ret |= wc_ShaUpdate(&sha, seq, SEQ_SZ);
+        ret |= wc_ShaUpdate(&sha, conLen, sizeof(conLen));
+        /* in buffer */
+        ret |= wc_ShaUpdate(&sha, in, sz);
+        if (ret != 0)
+            return VERIFY_MAC_ERROR;
+        ret = wc_ShaFinal(&sha, result);
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        /* TODO: Make non-blocking */
+        if (ret == WC_PENDING_E) {
+            ret = wc_AsyncWait(ret, &sha.asyncDev, WC_ASYNC_FLAG_NONE);
+        }
+    #endif
+        if (ret != 0)
+            return VERIFY_MAC_ERROR;
+
+        /* outer */
+        ret =  wc_ShaUpdate(&sha, macSecret, digestSz);
+        ret |= wc_ShaUpdate(&sha, PAD2, padSz);
+        ret |= wc_ShaUpdate(&sha, result, digestSz);
+        if (ret != 0)
+            return VERIFY_MAC_ERROR;
+        ret =  wc_ShaFinal(&sha, digest);
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        /* TODO: Make non-blocking */
+        if (ret == WC_PENDING_E) {
+            ret = wc_AsyncWait(ret, &sha.asyncDev, WC_ASYNC_FLAG_NONE);
+        }
+    #endif
+        if (ret != 0)
+            return VERIFY_MAC_ERROR;
+
+        wc_ShaFree(&sha);
+    }
+    return 0;
+}
+#endif /* !NO_OLD_TLS && !WOLFSSL_AEAD_ONLY */
+
+
+#ifndef NO_CERTS
+
+#if !defined(NO_MD5) && !defined(NO_OLD_TLS)
+static int BuildMD5_CertVerify(WOLFSSL* ssl, byte* digest)
+{
+    int ret;
+    byte md5_result[WC_MD5_DIGEST_SIZE];
+#ifdef WOLFSSL_SMALL_STACK
+    wc_Md5* md5 = (wc_Md5*)XMALLOC(sizeof(wc_Md5), ssl->heap, DYNAMIC_TYPE_HASHCTX);
+#else
+    wc_Md5  md5[1];
+#endif
+
+    /* make md5 inner */
+    ret = wc_Md5Copy(&ssl->hsHashes->hashMd5, md5); /* Save current position */
+    if (ret == 0)
+        ret = wc_Md5Update(md5, ssl->arrays->masterSecret,SECRET_LEN);
+    if (ret == 0)
+        ret = wc_Md5Update(md5, PAD1, PAD_MD5);
+    if (ret == 0)
+        ret = wc_Md5Final(md5, md5_result);
+
+    /* make md5 outer */
+    if (ret == 0) {
+        ret = wc_InitMd5_ex(md5, ssl->heap, ssl->devId);
+        if (ret == 0) {
+            ret = wc_Md5Update(md5, ssl->arrays->masterSecret, SECRET_LEN);
+            if (ret == 0)
+                ret = wc_Md5Update(md5, PAD2, PAD_MD5);
+            if (ret == 0)
+                ret = wc_Md5Update(md5, md5_result, WC_MD5_DIGEST_SIZE);
+            if (ret == 0)
+                ret = wc_Md5Final(md5, digest);
+            wc_Md5Free(md5);
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(md5, ssl->heap, DYNAMIC_TYPE_HASHCTX);
+#endif
+
+    return ret;
+}
+#endif /* !NO_MD5 && !NO_OLD_TLS */
+
+#if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \
+                              defined(WOLFSSL_ALLOW_TLS_SHA1))
+static int BuildSHA_CertVerify(WOLFSSL* ssl, byte* digest)
+{
+    int ret;
+    byte sha_result[WC_SHA_DIGEST_SIZE];
+#ifdef WOLFSSL_SMALL_STACK
+    wc_Sha* sha = (wc_Sha*)XMALLOC(sizeof(wc_Sha), ssl->heap, DYNAMIC_TYPE_HASHCTX);
+#else
+    wc_Sha  sha[1];
+#endif
+
+    /* make sha inner */
+    ret = wc_ShaCopy(&ssl->hsHashes->hashSha, sha); /* Save current position */
+    if (ret == 0)
+        ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN);
+    if (ret == 0)
+        ret = wc_ShaUpdate(sha, PAD1, PAD_SHA);
+    if (ret == 0)
+        ret = wc_ShaFinal(sha, sha_result);
+
+    /* make sha outer */
+    if (ret == 0) {
+        ret = wc_InitSha_ex(sha, ssl->heap, ssl->devId);
+        if (ret == 0) {
+            ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN);
+            if (ret == 0)
+                ret = wc_ShaUpdate(sha, PAD2, PAD_SHA);
+            if (ret == 0)
+                ret = wc_ShaUpdate(sha, sha_result, WC_SHA_DIGEST_SIZE);
+            if (ret == 0)
+                ret = wc_ShaFinal(sha, digest);
+            wc_ShaFree(sha);
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(sha, ssl->heap, DYNAMIC_TYPE_HASHCTX);
+#endif
+
+    return ret;
+}
+#endif /* !NO_SHA && (!NO_OLD_TLS || WOLFSSL_ALLOW_TLS_SHA1) */
+
+int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes)
+{
+    int ret = 0;
+
+    (void)hashes;
+
+    if (ssl->options.tls) {
+    #if !defined(NO_MD5) && !defined(NO_OLD_TLS)
+        ret = wc_Md5GetHash(&ssl->hsHashes->hashMd5, hashes->md5);
+        if (ret != 0)
+            return ret;
+    #endif
+    #if !defined(NO_SHA)
+        ret = wc_ShaGetHash(&ssl->hsHashes->hashSha, hashes->sha);
+        if (ret != 0)
+            return ret;
+    #endif
+        if (IsAtLeastTLSv1_2(ssl)) {
+            #ifndef NO_SHA256
+                ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256,
+                                       hashes->sha256);
+                if (ret != 0)
+                    return ret;
+            #endif
+            #ifdef WOLFSSL_SHA384
+                ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384,
+                                       hashes->sha384);
+                if (ret != 0)
+                    return ret;
+            #endif
+            #ifdef WOLFSSL_SHA512
+                ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512,
+                                       hashes->sha512);
+                if (ret != 0)
+                    return ret;
+            #endif
+        }
+    }
+    else {
+    #if !defined(NO_MD5) && !defined(NO_OLD_TLS)
+        ret = BuildMD5_CertVerify(ssl, hashes->md5);
+        if (ret != 0)
+            return ret;
+    #endif
+    #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \
+                              defined(WOLFSSL_ALLOW_TLS_SHA1))
+        ret = BuildSHA_CertVerify(ssl, hashes->sha);
+        if (ret != 0)
+            return ret;
+    #endif
+    }
+
+    return ret;
+}
+
+#endif /* !NO_CERTS */
+
+#ifndef WOLFSSL_NO_TLS12
+/* Persistable BuildMessage arguments */
+typedef struct BuildMsgArgs {
+    word32 digestSz;
+    word32 sz;
+    word32 pad;
+    word32 idx;
+    word32 headerSz;
+    word16 size;
+    word32 ivSz;      /* TLSv1.1  IV */
+    byte*  iv;
+} BuildMsgArgs;
+
+static void FreeBuildMsgArgs(WOLFSSL* ssl, void* pArgs)
+{
+    BuildMsgArgs* args = (BuildMsgArgs*)pArgs;
+
+    (void)ssl;
+    (void)args;
+
+    if (args->iv) {
+        XFREE(args->iv, ssl->heap, DYNAMIC_TYPE_SALT);
+        args->iv = NULL;
+    }
+}
+#endif
+
+/* Build SSL Message, encrypted */
+int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
+             int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay)
+{
+#ifndef WOLFSSL_NO_TLS12
+    int ret = 0;
+    BuildMsgArgs* args;
+    BuildMsgArgs  lcl_args;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    args = (BuildMsgArgs*)ssl->async.args;
+    typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+    (void)sizeof(args_test);
+#endif
+#endif
+
+    WOLFSSL_ENTER("BuildMessage");
+
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef WOLFSSL_NO_TLS12
+    return BuildTls13Message(ssl, output, outSz, input, inSz, type,
+                                               hashOutput, sizeOnly, asyncOkay);
+#else
+#ifdef WOLFSSL_TLS13
+    if (ssl->options.tls1_3) {
+        return BuildTls13Message(ssl, output, outSz, input, inSz, type,
+                                 hashOutput, sizeOnly, asyncOkay);
+    }
+#endif
+
+    ret = WC_NOT_PENDING_E;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (asyncOkay) {
+        ret = wolfSSL_AsyncPop(ssl, &ssl->options.buildMsgState);
+        if (ret != WC_NOT_PENDING_E) {
+            /* Check for error */
+            if (ret < 0)
+                goto exit_buildmsg;
+        }
+    }
+    else
+#endif
+    {
+        args = &lcl_args;
+    }
+
+    /* Reset state */
+    if (ret == WC_NOT_PENDING_E) {
+        ret = 0;
+        ssl->options.buildMsgState = BUILD_MSG_BEGIN;
+        XMEMSET(args, 0, sizeof(BuildMsgArgs));
+
+        args->sz = RECORD_HEADER_SZ + inSz;
+        args->idx  = RECORD_HEADER_SZ;
+        args->headerSz = RECORD_HEADER_SZ;
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        ssl->async.freeArgs = FreeBuildMsgArgs;
+    #endif
+    }
+
+    switch (ssl->options.buildMsgState) {
+        case BUILD_MSG_BEGIN:
+        {
+            /* catch mistaken sizeOnly parameter */
+            if (!sizeOnly && (output == NULL || input == NULL) ) {
+                ERROR_OUT(BAD_FUNC_ARG, exit_buildmsg);
+            }
+            if (sizeOnly && (output || input) ) {
+                WOLFSSL_MSG("BuildMessage w/sizeOnly doesn't need input/output");
+                ERROR_OUT(BAD_FUNC_ARG, exit_buildmsg);
+            }
+
+            ssl->options.buildMsgState = BUILD_MSG_SIZE;
+        }
+        FALL_THROUGH;
+        case BUILD_MSG_SIZE:
+        {
+            args->digestSz = ssl->specs.hash_size;
+        #ifdef HAVE_TRUNCATED_HMAC
+            if (ssl->truncated_hmac)
+                args->digestSz = min(TRUNCATED_HMAC_SZ, args->digestSz);
+        #endif
+            args->sz += args->digestSz;
+
+        #ifdef WOLFSSL_DTLS
+            if (ssl->options.dtls) {
+                args->sz       += DTLS_RECORD_EXTRA;
+                args->idx      += DTLS_RECORD_EXTRA;
+                args->headerSz += DTLS_RECORD_EXTRA;
+            }
+        #endif
+
+        #ifndef WOLFSSL_AEAD_ONLY
+            if (ssl->specs.cipher_type == block) {
+                word32 blockSz = ssl->specs.block_size;
+                if (ssl->options.tls1_1) {
+                    args->ivSz = blockSz;
+                    args->sz  += args->ivSz;
+
+                    if (args->ivSz > MAX_IV_SZ)
+                        ERROR_OUT(BUFFER_E, exit_buildmsg);
+                }
+                args->sz += 1;       /* pad byte */
+            #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+                if (ssl->options.startedETMWrite) {
+                    args->pad = (args->sz - args->headerSz -
+                                                      args->digestSz) % blockSz;
+                }
+                else
+            #endif
+                    args->pad = (args->sz - args->headerSz) % blockSz;
+                #ifdef OPENSSL_EXTRA
+                if(args->pad != 0)
+                #endif
+                    args->pad = blockSz - args->pad;
+                args->sz += args->pad;
+            }
+        #endif /* WOLFSSL_AEAD_ONLY */
+
+        #ifdef HAVE_AEAD
+            if (ssl->specs.cipher_type == aead) {
+                if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha)
+                    args->ivSz = AESGCM_EXP_IV_SZ;
+
+                args->sz += (args->ivSz + ssl->specs.aead_mac_size - args->digestSz);
+            }
+        #endif
+
+            /* done with size calculations */
+            if (sizeOnly)
+                goto exit_buildmsg;
+
+            if (args->sz > (word32)outSz) {
+                WOLFSSL_MSG("Oops, want to write past output buffer size");
+                ERROR_OUT(BUFFER_E, exit_buildmsg);
+            }
+
+            if (args->ivSz > 0) {
+                args->iv = (byte*)XMALLOC(args->ivSz, ssl->heap, DYNAMIC_TYPE_SALT);
+                if (args->iv == NULL)
+                    ERROR_OUT(MEMORY_E, exit_buildmsg);
+
+                ret = wc_RNG_GenerateBlock(ssl->rng, args->iv, args->ivSz);
+                if (ret != 0)
+                    goto exit_buildmsg;
+
+            }
+#if !defined(NO_PUBLIC_GCM_SET_IV) && \
+    ((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \
+    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) && \
+    defined(HAVE_AEAD))
+            if (ssl->specs.cipher_type == aead) {
+                if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha)
+                    XMEMCPY(args->iv, ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ);
+            }
+#endif
+
+            args->size = (word16)(args->sz - args->headerSz);    /* include mac and digest */
+            AddRecordHeader(output, args->size, (byte)type, ssl);
+
+            /* write to output */
+            if (args->ivSz > 0) {
+                XMEMCPY(output + args->idx, args->iv,
+                                        min(args->ivSz, MAX_IV_SZ));
+                args->idx += args->ivSz;
+            }
+            XMEMCPY(output + args->idx, input, inSz);
+            args->idx += inSz;
+
+            ssl->options.buildMsgState = BUILD_MSG_HASH;
+        }
+        FALL_THROUGH;
+        case BUILD_MSG_HASH:
+        {
+            if (type == handshake && hashOutput) {
+                ret = HashOutput(ssl, output, args->headerSz + inSz, args->ivSz);
+                if (ret != 0)
+                    goto exit_buildmsg;
+            }
+        #ifndef WOLFSSL_AEAD_ONLY
+            if (ssl->specs.cipher_type == block) {
+                word32 tmpIdx;
+                word32 i;
+
+            #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+                if (ssl->options.startedETMWrite)
+                    tmpIdx = args->idx;
+                else
+            #endif
+                    tmpIdx = args->idx + args->digestSz;
+
+                for (i = 0; i <= args->pad; i++)
+                    output[tmpIdx++] = (byte)args->pad; /* pad byte gets pad value */
+            }
+        #endif
+
+            ssl->options.buildMsgState = BUILD_MSG_VERIFY_MAC;
+        }
+        FALL_THROUGH;
+        case BUILD_MSG_VERIFY_MAC:
+        {
+            /* User Record Layer Callback handling */
+    #ifdef ATOMIC_USER
+        #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+            if (ssl->options.startedETMWrite) {
+                if (ssl->ctx->EncryptMacCb) {
+                    ret = ssl->ctx->EncryptMacCb(ssl, output + args->idx +
+                                                 args->pad + 1, type, 0,
+                                                 output + args->headerSz,
+                                                 output + args->headerSz,
+                                                 args->size - args->digestSz,
+                                                 ssl->MacEncryptCtx);
+                    goto exit_buildmsg;
+                }
+            }
+            else
+        #endif
+            {
+                if (ssl->ctx->MacEncryptCb) {
+                    ret = ssl->ctx->MacEncryptCb(ssl, output + args->idx,
+                                    output + args->headerSz + args->ivSz, inSz,
+                                    type, 0, output + args->headerSz,
+                                    output + args->headerSz, args->size,
+                                    ssl->MacEncryptCtx);
+                    goto exit_buildmsg;
+                }
+            }
+    #endif
+
+        #ifndef WOLFSSL_AEAD_ONLY
+            if (ssl->specs.cipher_type != aead
+            #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+                                               && !ssl->options.startedETMWrite
+            #endif
+                ) {
+            #ifdef HAVE_TRUNCATED_HMAC
+                if (ssl->truncated_hmac &&
+                                        ssl->specs.hash_size > args->digestSz) {
+                #ifdef WOLFSSL_SMALL_STACK
+                    byte* hmac;
+                #else
+                    byte  hmac[WC_MAX_DIGEST_SIZE];
+                #endif
+
+                #ifdef WOLFSSL_SMALL_STACK
+                    hmac = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, ssl->heap,
+                                                           DYNAMIC_TYPE_DIGEST);
+                    if (hmac == NULL)
+                        ERROR_OUT(MEMORY_E, exit_buildmsg);
+                #endif
+
+                    ret = ssl->hmac(ssl, hmac,
+                                     output + args->headerSz + args->ivSz, inSz,
+                                     -1, type, 0);
+                    XMEMCPY(output + args->idx, hmac, args->digestSz);
+
+                #ifdef WOLFSSL_SMALL_STACK
+                    XFREE(hmac, ssl->heap, DYNAMIC_TYPE_DIGEST);
+                #endif
+                }
+                else
+            #endif
+                {
+                    ret = ssl->hmac(ssl, output + args->idx, output +
+                                args->headerSz + args->ivSz, inSz, -1, type, 0);
+                }
+            }
+        #endif /* WOLFSSL_AEAD_ONLY */
+            if (ret != 0)
+                goto exit_buildmsg;
+
+            ssl->options.buildMsgState = BUILD_MSG_ENCRYPT;
+        }
+        FALL_THROUGH;
+        case BUILD_MSG_ENCRYPT:
+        {
+    #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+            if (ssl->options.startedETMWrite) {
+                ret = Encrypt(ssl, output + args->headerSz,
+                                        output + args->headerSz,
+                                        args->size - args->digestSz, asyncOkay);
+            }
+            else
+    #endif
+            {
+                ret = Encrypt(ssl, output + args->headerSz,
+                                output + args->headerSz, args->size, asyncOkay);
+            }
+            if (ret != 0)
+                goto exit_buildmsg;
+            ssl->options.buildMsgState = BUILD_MSG_ENCRYPTED_VERIFY_MAC;
+        }
+        FALL_THROUGH;
+        case BUILD_MSG_ENCRYPTED_VERIFY_MAC:
+        {
+        #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+            if (ssl->options.startedETMWrite) {
+                WOLFSSL_MSG("Calculate MAC of Encrypted Data");
+
+            #ifdef HAVE_TRUNCATED_HMAC
+                if (ssl->truncated_hmac &&
+                                        ssl->specs.hash_size > args->digestSz) {
+                #ifdef WOLFSSL_SMALL_STACK
+                    byte* hmac = NULL;
+                #else
+                    byte  hmac[WC_MAX_DIGEST_SIZE];
+                #endif
+
+                #ifdef WOLFSSL_SMALL_STACK
+                    hmac = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, ssl->heap,
+                                                           DYNAMIC_TYPE_DIGEST);
+                    if (hmac == NULL)
+                        ERROR_OUT(MEMORY_E, exit_buildmsg);
+                #endif
+
+                    ret = ssl->hmac(ssl, hmac, output + args->headerSz,
+                                    args->ivSz + inSz + args->pad + 1, -1, type,
+                                    0);
+                    XMEMCPY(output + args->idx + args->pad + 1, hmac,
+                                                                args->digestSz);
+
+                #ifdef WOLFSSL_SMALL_STACK
+                    XFREE(hmac, ssl->heap, DYNAMIC_TYPE_DIGEST);
+                #endif
+                }
+                else
+            #endif
+                {
+                    ret = ssl->hmac(ssl, output + args->idx + args->pad + 1,
+                                    output + args->headerSz,
+                                    args->ivSz + inSz + args->pad + 1, -1, type,
+                                    0);
+                }
+            }
+        #endif /* HAVE_ENCRYPT_THEN_MAC && !WOLFSSL_AEAD_ONLY */
+        }
+    }
+
+exit_buildmsg:
+
+    WOLFSSL_LEAVE("BuildMessage", ret);
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        return ret;
+    }
+#endif
+
+    /* make sure build message state is reset */
+    ssl->options.buildMsgState = BUILD_MSG_BEGIN;
+
+    #ifdef WOLFSSL_DTLS
+        if (ret == 0 && ssl->options.dtls)
+            DtlsSEQIncrement(ssl, CUR_ORDER);
+    #endif
+
+    /* return sz on success */
+    if (ret == 0)
+        ret = args->sz;
+
+    /* Final cleanup */
+    FreeBuildMsgArgs(ssl, args);
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ssl->async.freeArgs = NULL;
+#endif
+
+    return ret;
+#endif /* !WOLFSSL_NO_TLS12 */
+}
+
+#ifndef WOLFSSL_NO_TLS12
+
+int SendFinished(WOLFSSL* ssl)
+{
+    int              sendSz,
+                     finishedSz = ssl->options.tls ? TLS_FINISHED_SZ :
+                                                     FINISHED_SZ;
+    byte             input[FINISHED_SZ + DTLS_HANDSHAKE_HEADER_SZ];  /* max */
+    byte            *output;
+    Hashes*          hashes;
+    int              ret;
+    int              headerSz = HANDSHAKE_HEADER_SZ;
+    int              outputSz;
+
+    WOLFSSL_START(WC_FUNC_FINISHED_SEND);
+    WOLFSSL_ENTER("SendFinished");
+
+    /* setup encrypt keys */
+    if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0)
+        return ret;
+
+    #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+        ssl->options.startedETMWrite = ssl->options.encThenMac;
+    #endif
+
+    /* check for available size */
+    outputSz = sizeof(input) + MAX_MSG_EXTRA;
+    if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
+        return ret;
+
+    #ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls) {
+            headerSz += DTLS_HANDSHAKE_EXTRA;
+            ssl->keys.dtls_epoch++;
+            ssl->keys.dtls_prev_sequence_number_hi =
+                    ssl->keys.dtls_sequence_number_hi;
+            ssl->keys.dtls_prev_sequence_number_lo =
+                    ssl->keys.dtls_sequence_number_lo;
+            ssl->keys.dtls_sequence_number_hi = 0;
+            ssl->keys.dtls_sequence_number_lo = 0;
+        }
+    #endif
+
+    /* get output buffer */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+
+    AddHandShakeHeader(input, finishedSz, 0, finishedSz, finished, ssl);
+
+    /* make finished hashes */
+    hashes = (Hashes*)&input[headerSz];
+    ret = BuildFinished(ssl, hashes,
+                     ssl->options.side == WOLFSSL_CLIENT_END ? client : server);
+    if (ret != 0) return ret;
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+    if (ssl->secure_renegotiation) {
+        if (ssl->options.side == WOLFSSL_CLIENT_END)
+            XMEMCPY(ssl->secure_renegotiation->client_verify_data, hashes,
+                    TLS_FINISHED_SZ);
+        else
+            XMEMCPY(ssl->secure_renegotiation->server_verify_data, hashes,
+                    TLS_FINISHED_SZ);
+    }
+#endif
+
+    #ifdef WOLFSSL_DTLS
+        if (IsDtlsNotSctpMode(ssl)) {
+            if ((ret = DtlsMsgPoolSave(ssl, input, headerSz + finishedSz)) != 0)
+                return ret;
+        }
+    #endif
+
+    sendSz = BuildMessage(ssl, output, outputSz, input, headerSz + finishedSz,
+                                                          handshake, 1, 0, 0);
+    if (sendSz < 0)
+        return BUILD_MSG_ERROR;
+
+    if (!ssl->options.resuming) {
+#ifndef NO_SESSION_CACHE
+        AddSession(ssl);    /* just try */
+#endif
+        if (ssl->options.side == WOLFSSL_SERVER_END) {
+        #ifdef OPENSSL_EXTRA
+            ssl->options.serverState = SERVER_FINISHED_COMPLETE;
+            ssl->cbmode = SSL_CB_MODE_WRITE;
+            if (ssl->CBIS != NULL)
+                ssl->CBIS(ssl, SSL_CB_HANDSHAKE_DONE, SSL_SUCCESS);
+        #endif
+            ssl->options.handShakeState = HANDSHAKE_DONE;
+            ssl->options.handShakeDone  = 1;
+        }
+    }
+    else {
+        if (ssl->options.side == WOLFSSL_CLIENT_END) {
+        #ifdef OPENSSL_EXTRA
+            ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
+            ssl->cbmode = SSL_CB_MODE_WRITE;
+            if (ssl->CBIS != NULL)
+                ssl->CBIS(ssl, SSL_CB_HANDSHAKE_DONE, SSL_SUCCESS);
+        #endif
+            ssl->options.handShakeState = HANDSHAKE_DONE;
+            ssl->options.handShakeDone  = 1;
+        }
+    }
+
+    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+        if (ssl->hsInfoOn) AddPacketName(ssl, "Finished");
+        if (ssl->toInfoOn)
+            AddPacketInfo(ssl, "Finished", handshake, output, sendSz,
+                          WRITE_PROTO, ssl->heap);
+    #endif
+
+    ssl->buffers.outputBuffer.length += sendSz;
+
+    ret = SendBuffered(ssl);
+
+    WOLFSSL_LEAVE("SendFinished", ret);
+    WOLFSSL_END(WC_FUNC_FINISHED_SEND);
+
+    return ret;
+}
+#endif /* WOLFSSL_NO_TLS12 */
+
+#ifndef NO_WOLFSSL_SERVER
+#if (!defined(WOLFSSL_NO_TLS12) && \
+        (defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
+         defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))) || \
+    (defined(WOLFSSL_TLS13) && defined(HAVE_CERTIFICATE_STATUS_REQUEST))
+/* Parses and decodes the certificate then initializes "request". In the case
+ * of !ssl->buffers.weOwnCert, ssl->ctx->certOcspRequest gets set to "request".
+ *
+ * Returns 0 on success
+ */
+static int CreateOcspRequest(WOLFSSL* ssl, OcspRequest* request,
+                             DecodedCert* cert, byte* certData, word32 length)
+{
+    int ret;
+
+    if (request != NULL)
+        XMEMSET(request, 0, sizeof(OcspRequest));
+
+    InitDecodedCert(cert, certData, length, ssl->heap);
+    /* TODO: Setup async support here */
+    ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, ssl->ctx->cm);
+    if (ret != 0) {
+        WOLFSSL_MSG("ParseCert failed");
+    }
+    if (ret == 0)
+        ret = InitOcspRequest(request, cert, 0, ssl->heap);
+    if (ret == 0) {
+        /* make sure ctx OCSP request is updated */
+        if (!ssl->buffers.weOwnCert) {
+            wolfSSL_Mutex* ocspLock = &ssl->ctx->cm->ocsp_stapling->ocspLock;
+            if (wc_LockMutex(ocspLock) == 0) {
+                if (ssl->ctx->certOcspRequest == NULL)
+                    ssl->ctx->certOcspRequest = request;
+                wc_UnLockMutex(ocspLock);
+            }
+        }
+    }
+
+    FreeDecodedCert(cert);
+
+    return ret;
+}
+
+
+/* Creates OCSP response and places it in variable "response". Memory
+ * management for "buffer* response" is up to the caller.
+ *
+ * Also creates an OcspRequest in the case that ocspRequest is null or that
+ * ssl->buffers.weOwnCert is set. In those cases managing ocspRequest free'ing
+ * is up to the caller. NOTE: in OcspCreateRequest ssl->ctx->certOcspRequest can
+ * be set to point to "ocspRequest" and it then should not be free'd since
+ * wolfSSL_CTX_free will take care of it.
+ *
+ * Returns 0 on success
+ */
+int CreateOcspResponse(WOLFSSL* ssl, OcspRequest** ocspRequest,
+                       buffer* response)
+{
+    int          ret = 0;
+    OcspRequest* request = NULL;
+    byte createdRequest  = 0;
+
+    if (ssl == NULL || ocspRequest == NULL || response == NULL)
+        return BAD_FUNC_ARG;
+
+    XMEMSET(response, 0, sizeof(*response));
+    request = *ocspRequest;
+
+    /* unable to fetch status. skip. */
+    if (ssl->ctx->cm == NULL || ssl->ctx->cm->ocspStaplingEnabled == 0)
+        return 0;
+
+    if (request == NULL || ssl->buffers.weOwnCert) {
+        DerBuffer* der = ssl->buffers.certificate;
+        #ifdef WOLFSSL_SMALL_STACK
+            DecodedCert* cert = NULL;
+        #else
+            DecodedCert  cert[1];
+        #endif
+
+        /* unable to fetch status. skip. */
+        if (der->buffer == NULL || der->length == 0)
+            return 0;
+
+    #ifdef WOLFSSL_SMALL_STACK
+        cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap,
+                                        DYNAMIC_TYPE_DCERT);
+        if (cert == NULL)
+            return MEMORY_E;
+    #endif
+        request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), ssl->heap,
+                                                     DYNAMIC_TYPE_OCSP_REQUEST);
+        if (request == NULL)
+            ret = MEMORY_E;
+
+        createdRequest = 1;
+        if (ret == 0) {
+            ret = CreateOcspRequest(ssl, request, cert, der->buffer,
+                                                                   der->length);
+        }
+
+        if (ret != 0) {
+            XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+            request = NULL;
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
+    #endif
+    }
+
+    if (ret == 0) {
+        request->ssl = ssl;
+        ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, response);
+
+        /* Suppressing, not critical */
+        if (ret == OCSP_CERT_REVOKED ||
+            ret == OCSP_CERT_UNKNOWN ||
+            ret == OCSP_LOOKUP_FAIL) {
+            ret = 0;
+        }
+    }
+
+    /* free request up if error case found otherwise return it */
+    if (ret != 0 && createdRequest) {
+        FreeOcspRequest(request);
+        XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+    }
+
+    if (ret == 0)
+        *ocspRequest = request;
+
+    return ret;
+}
+#endif
+#endif /* !NO_WOLFSSL_SERVER */
+
+#ifndef WOLFSSL_NO_TLS12
+
+#ifndef NO_CERTS
+#if !defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH)
+/* handle generation of certificate (11) */
+int SendCertificate(WOLFSSL* ssl)
+{
+    int    ret = 0;
+    word32 certSz, certChainSz, headerSz, listSz, payloadSz;
+    word32 length, maxFragment;
+
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_SEND);
+    WOLFSSL_ENTER("SendCertificate");
+
+    if (ssl->options.usingPSK_cipher || ssl->options.usingAnon_cipher)
+        return 0;  /* not needed */
+
+    if (ssl->options.sendVerify == SEND_BLANK_CERT) {
+    #ifdef OPENSSL_EXTRA
+        if (ssl->version.major == SSLv3_MAJOR
+            && ssl->version.minor == SSLv3_MINOR){
+            SendAlert(ssl, alert_warning, no_certificate);
+            return 0;
+        } else {
+    #endif
+            certSz = 0;
+            certChainSz = 0;
+            headerSz = CERT_HEADER_SZ;
+            length = CERT_HEADER_SZ;
+            listSz = 0;
+    #ifdef OPENSSL_EXTRA
+        }
+    #endif
+    }
+    else {
+        if (!ssl->buffers.certificate) {
+            WOLFSSL_MSG("Send Cert missing certificate buffer");
+            return BUFFER_ERROR;
+        }
+        certSz = ssl->buffers.certificate->length;
+        headerSz = 2 * CERT_HEADER_SZ;
+        /* list + cert size */
+        length = certSz + headerSz;
+        listSz = certSz + CERT_HEADER_SZ;
+
+        /* may need to send rest of chain, already has leading size(s) */
+        if (certSz && ssl->buffers.certChain) {
+            certChainSz = ssl->buffers.certChain->length;
+            length += certChainSz;
+            listSz += certChainSz;
+        }
+        else
+            certChainSz = 0;
+    }
+
+    payloadSz = length;
+
+    if (ssl->fragOffset != 0)
+        length -= (ssl->fragOffset + headerSz);
+
+    maxFragment = MAX_RECORD_SIZE;
+
+    if (ssl->options.dtls) {
+    #ifdef WOLFSSL_DTLS
+        /* The 100 bytes is used to account for the UDP and IP headers.
+           It can also include the record padding and MAC if the
+           SendCertificate is called for a secure renegotiation. */
+        maxFragment = MAX_MTU - DTLS_RECORD_HEADER_SZ
+                      - DTLS_HANDSHAKE_HEADER_SZ - 100;
+    #endif /* WOLFSSL_DTLS */
+    }
+
+    maxFragment = wolfSSL_GetMaxRecordSize(ssl, maxFragment);
+
+    while (length > 0 && ret == 0) {
+        byte*  output = NULL;
+        word32 fragSz = 0;
+        word32 i = RECORD_HEADER_SZ;
+        int    sendSz = RECORD_HEADER_SZ;
+
+        if (!ssl->options.dtls) {
+            if (ssl->fragOffset == 0)  {
+                if (headerSz + certSz + certChainSz <=
+                    maxFragment - HANDSHAKE_HEADER_SZ) {
+
+                    fragSz = headerSz + certSz + certChainSz;
+                }
+                else {
+                    fragSz = maxFragment - HANDSHAKE_HEADER_SZ;
+                }
+                sendSz += fragSz + HANDSHAKE_HEADER_SZ;
+                i += HANDSHAKE_HEADER_SZ;
+            }
+            else {
+                fragSz = min(length, maxFragment);
+                sendSz += fragSz;
+            }
+
+            if (IsEncryptionOn(ssl, 1))
+                sendSz += MAX_MSG_EXTRA;
+        }
+        else {
+        #ifdef WOLFSSL_DTLS
+            fragSz = min(length, maxFragment);
+            sendSz += fragSz + DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA
+                      + HANDSHAKE_HEADER_SZ;
+            i      += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA
+                      + HANDSHAKE_HEADER_SZ;
+        #endif
+        }
+
+        /* check for available size */
+        if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+            return ret;
+
+        /* get output buffer */
+        output = ssl->buffers.outputBuffer.buffer +
+                 ssl->buffers.outputBuffer.length;
+
+        if (ssl->fragOffset == 0) {
+            if (!ssl->options.dtls) {
+                AddFragHeaders(output, fragSz, 0, payloadSz, certificate, ssl);
+                if (!IsEncryptionOn(ssl, 1))
+                    HashOutputRaw(ssl, output + RECORD_HEADER_SZ,
+                                  HANDSHAKE_HEADER_SZ);
+            }
+            else {
+            #ifdef WOLFSSL_DTLS
+                AddHeaders(output, payloadSz, certificate, ssl);
+                if (!IsEncryptionOn(ssl, 1))
+                    HashOutputRaw(ssl,
+                                  output + RECORD_HEADER_SZ + DTLS_RECORD_EXTRA,
+                                  HANDSHAKE_HEADER_SZ + DTLS_HANDSHAKE_EXTRA);
+                /* Adding the headers increments these, decrement them for
+                 * actual message header. */
+                ssl->keys.dtls_handshake_number--;
+                AddFragHeaders(output, fragSz, 0, payloadSz, certificate, ssl);
+                ssl->keys.dtls_handshake_number--;
+            #endif /* WOLFSSL_DTLS */
+            }
+
+            /* list total */
+            c32to24(listSz, output + i);
+            if (!IsEncryptionOn(ssl, 1))
+                HashOutputRaw(ssl, output + i, CERT_HEADER_SZ);
+            i += CERT_HEADER_SZ;
+            length -= CERT_HEADER_SZ;
+            fragSz -= CERT_HEADER_SZ;
+            if (certSz) {
+                c32to24(certSz, output + i);
+                if (!IsEncryptionOn(ssl, 1))
+                    HashOutputRaw(ssl, output + i, CERT_HEADER_SZ);
+                i += CERT_HEADER_SZ;
+                length -= CERT_HEADER_SZ;
+                fragSz -= CERT_HEADER_SZ;
+
+                if (!IsEncryptionOn(ssl, 1)) {
+                    HashOutputRaw(ssl, ssl->buffers.certificate->buffer, certSz);
+                    if (certChainSz)
+                        HashOutputRaw(ssl, ssl->buffers.certChain->buffer,
+                                      certChainSz);
+                }
+            }
+        }
+        else {
+            if (!ssl->options.dtls) {
+                AddRecordHeader(output, fragSz, handshake, ssl);
+            }
+            else {
+            #ifdef WOLFSSL_DTLS
+                AddFragHeaders(output, fragSz, ssl->fragOffset + headerSz,
+                               payloadSz, certificate, ssl);
+                ssl->keys.dtls_handshake_number--;
+            #endif /* WOLFSSL_DTLS */
+            }
+        }
+
+        /* member */
+        if (certSz && ssl->fragOffset < certSz) {
+            word32 copySz = min(certSz - ssl->fragOffset, fragSz);
+            XMEMCPY(output + i,
+                    ssl->buffers.certificate->buffer + ssl->fragOffset, copySz);
+            i += copySz;
+            ssl->fragOffset += copySz;
+            length -= copySz;
+            fragSz -= copySz;
+        }
+        if (certChainSz && fragSz) {
+            word32 copySz = min(certChainSz + certSz - ssl->fragOffset, fragSz);
+            XMEMCPY(output + i,
+                    ssl->buffers.certChain->buffer + ssl->fragOffset - certSz,
+                    copySz);
+            i += copySz;
+            ssl->fragOffset += copySz;
+            length -= copySz;
+        }
+
+        if (IsEncryptionOn(ssl, 1)) {
+            byte* input = NULL;
+            int   inputSz = i - RECORD_HEADER_SZ; /* build msg adds rec hdr */
+
+            if (inputSz < 0) {
+                WOLFSSL_MSG("Send Cert bad inputSz");
+                return BUFFER_E;
+            }
+
+            if (inputSz > 0) {  /* clang thinks could be zero, let's help */
+                input = (byte*)XMALLOC(inputSz, ssl->heap,
+                                       DYNAMIC_TYPE_IN_BUFFER);
+                if (input == NULL)
+                    return MEMORY_E;
+                XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
+            }
+
+            sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
+                                                          handshake, 1, 0, 0);
+
+            if (inputSz > 0)
+                XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+
+            if (sendSz < 0)
+                return sendSz;
+        }
+        else {
+        #ifdef WOLFSSL_DTLS
+            if (ssl->options.dtls)
+                DtlsSEQIncrement(ssl, CUR_ORDER);
+        #endif
+        }
+
+    #ifdef WOLFSSL_DTLS
+        if (IsDtlsNotSctpMode(ssl)) {
+            if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
+                return ret;
+        }
+    #endif
+
+    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+        if (ssl->hsInfoOn)
+            AddPacketName(ssl, "Certificate");
+        if (ssl->toInfoOn)
+            AddPacketInfo(ssl, "Certificate", handshake, output, sendSz,
+                           WRITE_PROTO, ssl->heap);
+    #endif
+
+        ssl->buffers.outputBuffer.length += sendSz;
+        if (!ssl->options.groupMessages)
+            ret = SendBuffered(ssl);
+    }
+
+    if (ret != WANT_WRITE) {
+        /* Clean up the fragment offset. */
+        ssl->fragOffset = 0;
+        #ifdef WOLFSSL_DTLS
+            if (ssl->options.dtls)
+                ssl->keys.dtls_handshake_number++;
+        #endif
+        if (ssl->options.side == WOLFSSL_SERVER_END){
+            ssl->options.serverState = SERVER_CERT_COMPLETE;
+        }
+    }
+
+    WOLFSSL_LEAVE("SendCertificate", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_SEND);
+
+    return ret;
+}
+#endif /* !NO_WOLFSSL_SERVER || !WOLFSSL_NO_CLIENT_AUTH */
+
+/* handle generation of certificate_request (13) */
+int SendCertificateRequest(WOLFSSL* ssl)
+{
+    byte   *output;
+    int    ret;
+    int    sendSz;
+    word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+    word32 dnLen = 0;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+    WOLF_STACK_OF(WOLFSSL_X509_NAME)* names;
+#endif
+
+    int  typeTotal = 1;  /* only 1 for now */
+    int  reqSz = ENUM_LEN + typeTotal + REQ_HEADER_SZ;  /* add auth later */
+
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_REQUEST_SEND);
+    WOLFSSL_ENTER("SendCertificateRequest");
+
+    if (IsAtLeastTLSv1_2(ssl))
+        reqSz += LENGTH_SZ + ssl->suites->hashSigAlgoSz;
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+    /* Certificate Authorities */
+    names = ssl->ctx->ca_names;
+    while (names != NULL) {
+        byte seq[MAX_SEQ_SZ];
+
+        /* 16-bit length | SEQ | Len | DER of name */
+        dnLen += OPAQUE16_LEN + SetSequence(names->data.name->rawLen, seq) +
+                 names->data.name->rawLen;
+        names = names->next;
+    }
+    reqSz += dnLen;
+#endif
+
+    if (ssl->options.usingPSK_cipher || ssl->options.usingAnon_cipher)
+        return 0;  /* not needed */
+
+    sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + reqSz;
+
+    if (!ssl->options.dtls) {
+        if (IsEncryptionOn(ssl, 1))
+            sendSz += MAX_MSG_EXTRA;
+    }
+    else {
+    #ifdef WOLFSSL_DTLS
+        sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+        i      += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+    #endif
+    }
+    /* check for available size */
+    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+        return ret;
+
+    /* get output buffer */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+
+    AddHeaders(output, reqSz, certificate_request, ssl);
+
+    /* write to output */
+    output[i++] = (byte)typeTotal;  /* # of types */
+#ifdef HAVE_ECC
+    if ((ssl->options.cipherSuite0 == ECC_BYTE ||
+         ssl->options.cipherSuite0 == CHACHA_BYTE) &&
+                     ssl->specs.sig_algo == ecc_dsa_sa_algo) {
+        output[i++] = ecdsa_sign;
+    } else
+#endif /* HAVE_ECC */
+    {
+        output[i++] = rsa_sign;
+    }
+
+    /* supported hash/sig */
+    if (IsAtLeastTLSv1_2(ssl)) {
+        c16toa(ssl->suites->hashSigAlgoSz, &output[i]);
+        i += OPAQUE16_LEN;
+
+        XMEMCPY(&output[i],
+                         ssl->suites->hashSigAlgo, ssl->suites->hashSigAlgoSz);
+        i += ssl->suites->hashSigAlgoSz;
+    }
+
+    /* Certificate Authorities */
+    c16toa((word16)dnLen, &output[i]);  /* auth's */
+    i += REQ_HEADER_SZ;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+    names = ssl->ctx->ca_names;
+    while (names != NULL) {
+        byte seq[MAX_SEQ_SZ];
+
+        c16toa((word16)names->data.name->rawLen +
+               SetSequence(names->data.name->rawLen, seq), &output[i]);
+        i += OPAQUE16_LEN;
+        i += SetSequence(names->data.name->rawLen, output + i);
+        XMEMCPY(output + i, names->data.name->raw, names->data.name->rawLen);
+        i += names->data.name->rawLen;
+        names = names->next;
+    }
+#endif
+    (void)i;
+
+        if (IsEncryptionOn(ssl, 1)) {
+            byte* input;
+            int   inputSz = i - RECORD_HEADER_SZ; /* build msg adds rec hdr */
+
+            input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+            if (input == NULL)
+                return MEMORY_E;
+
+            XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
+            sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
+                                  handshake, 1, 0, 0);
+            XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+
+            if (sendSz < 0)
+                return sendSz;
+        } else {
+            #ifdef WOLFSSL_DTLS
+                if (ssl->options.dtls)
+                    DtlsSEQIncrement(ssl, CUR_ORDER);
+                if (IsDtlsNotSctpMode(ssl)) {
+                    if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
+                        return ret;
+                }
+            #endif
+            ret = HashOutput(ssl, output, sendSz, 0);
+            if (ret != 0)
+                return ret;
+        }
+
+    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+        if (ssl->hsInfoOn)
+            AddPacketName(ssl, "CertificateRequest");
+        if (ssl->toInfoOn)
+            AddPacketInfo(ssl, "CertificateRequest", handshake, output, sendSz,
+                    WRITE_PROTO, ssl->heap);
+    #endif
+    ssl->buffers.outputBuffer.length += sendSz;
+    if (ssl->options.groupMessages)
+        ret = 0;
+    else
+        ret = SendBuffered(ssl);
+
+    WOLFSSL_LEAVE("SendCertificateRequest", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_SEND);
+
+    return ret;
+}
+
+#ifndef NO_WOLFSSL_SERVER
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status,
+                                                                     byte count)
+{
+    byte*  output  = NULL;
+    word32 idx     = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+    word32 length  = ENUM_LEN;
+    int    sendSz  = 0;
+    int    ret     = 0;
+    int    i       = 0;
+
+    WOLFSSL_ENTER("BuildCertificateStatus");
+
+    switch (type) {
+        case WOLFSSL_CSR2_OCSP_MULTI:
+            length += OPAQUE24_LEN;
+            FALL_THROUGH; /* followed by */
+
+        case WOLFSSL_CSR2_OCSP:
+            for (i = 0; i < count; i++)
+                length += OPAQUE24_LEN + status[i].length;
+        break;
+
+        default:
+            return 0;
+    }
+
+    sendSz = idx + length;
+
+    if (ssl->keys.encryptionOn)
+        sendSz += MAX_MSG_EXTRA;
+
+    if ((ret = CheckAvailableSize(ssl, sendSz)) == 0) {
+        output = ssl->buffers.outputBuffer.buffer +
+                 ssl->buffers.outputBuffer.length;
+
+        AddHeaders(output, length, certificate_status, ssl);
+
+        output[idx++] = type;
+
+        if (type == WOLFSSL_CSR2_OCSP_MULTI) {
+            c32to24(length - (ENUM_LEN + OPAQUE24_LEN), output + idx);
+            idx += OPAQUE24_LEN;
+        }
+
+        for (i = 0; i < count; i++) {
+            c32to24(status[i].length, output + idx);
+            idx += OPAQUE24_LEN;
+
+            XMEMCPY(output + idx, status[i].buffer, status[i].length);
+            idx += status[i].length;
+        }
+
+        if (IsEncryptionOn(ssl, 1)) {
+            byte* input;
+            int   inputSz = idx - RECORD_HEADER_SZ;
+
+            input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+            if (input == NULL)
+                return MEMORY_E;
+
+            XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
+            sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
+                                                           handshake, 1, 0, 0);
+            XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+
+            if (sendSz < 0)
+                ret = sendSz;
+        }
+        else {
+            #ifdef WOLFSSL_DTLS
+                if (ssl->options.dtls)
+                    DtlsSEQIncrement(ssl, CUR_ORDER);
+            #endif
+            ret = HashOutput(ssl, output, sendSz, 0);
+        }
+
+    #ifdef WOLFSSL_DTLS
+        if (ret == 0 && IsDtlsNotSctpMode(ssl))
+            ret = DtlsMsgPoolSave(ssl, output, sendSz);
+    #endif
+
+    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+        if (ret == 0 && ssl->hsInfoOn)
+            AddPacketName(ssl, "CertificateStatus");
+        if (ret == 0 && ssl->toInfoOn)
+            AddPacketInfo(ssl, "CertificateStatus", handshake, output, sendSz,
+                    WRITE_PROTO, ssl->heap);
+    #endif
+
+        if (ret == 0) {
+            ssl->buffers.outputBuffer.length += sendSz;
+            if (!ssl->options.groupMessages)
+                ret = SendBuffered(ssl);
+        }
+    }
+
+    WOLFSSL_LEAVE("BuildCertificateStatus", ret);
+    return ret;
+}
+#endif
+#endif /* NO_WOLFSSL_SERVER */
+
+/* handle generation of certificate_status (22) */
+int SendCertificateStatus(WOLFSSL* ssl)
+{
+    int ret = 0;
+    byte status_type = 0;
+
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_STATUS_SEND);
+    WOLFSSL_ENTER("SendCertificateStatus");
+
+    (void) ssl;
+
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+    status_type = ssl->status_request;
+#endif
+
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+    status_type = status_type ? status_type : ssl->status_request_v2;
+#endif
+
+    switch (status_type) {
+
+    #ifndef NO_WOLFSSL_SERVER
+    #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+     || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+        /* case WOLFSSL_CSR_OCSP: */
+        case WOLFSSL_CSR2_OCSP:
+        {
+            OcspRequest* request = ssl->ctx->certOcspRequest;
+            buffer response;
+
+            ret = CreateOcspResponse(ssl, &request, &response);
+
+            /* if a request was successfully created and not stored in
+             * ssl->ctx then free it */
+            if (ret == 0 && request != ssl->ctx->certOcspRequest) {
+                FreeOcspRequest(request);
+                XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+                request = NULL;
+            }
+
+            if (ret == 0 && response.buffer) {
+                ret = BuildCertificateStatus(ssl, status_type, &response, 1);
+
+                XFREE(response.buffer, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+                response.buffer = NULL;
+            }
+            break;
+        }
+
+    #endif /* HAVE_CERTIFICATE_STATUS_REQUEST    */
+           /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+
+    #if defined HAVE_CERTIFICATE_STATUS_REQUEST_V2
+        case WOLFSSL_CSR2_OCSP_MULTI:
+        {
+            OcspRequest* request = ssl->ctx->certOcspRequest;
+            buffer responses[1 + MAX_CHAIN_DEPTH];
+            int i = 0;
+
+            XMEMSET(responses, 0, sizeof(responses));
+
+            ret = CreateOcspResponse(ssl, &request, &responses[0]);
+
+            /* if a request was successfully created and not stored in
+             * ssl->ctx then free it */
+            if (ret == 0 && request != ssl->ctx->certOcspRequest) {
+                FreeOcspRequest(request);
+                XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+                request = NULL;
+            }
+
+            if (ret == 0 && (!ssl->ctx->chainOcspRequest[0]
+                                              || ssl->buffers.weOwnCertChain)) {
+                buffer der;
+                word32 idx = 0;
+            #ifdef WOLFSSL_SMALL_STACK
+                DecodedCert* cert;
+            #else
+                DecodedCert  cert[1];
+            #endif
+
+            #ifdef WOLFSSL_SMALL_STACK
+                cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap,
+                                                            DYNAMIC_TYPE_DCERT);
+                if (cert == NULL)
+                    return MEMORY_E;
+            #endif
+                request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), ssl->heap,
+                                                     DYNAMIC_TYPE_OCSP_REQUEST);
+                if (request == NULL) {
+            #ifdef WOLFSSL_SMALL_STACK
+                    XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
+            #endif
+                    return MEMORY_E;
+                }
+
+                while (idx + OPAQUE24_LEN < ssl->buffers.certChain->length) {
+                    c24to32(ssl->buffers.certChain->buffer + idx, &der.length);
+                    idx += OPAQUE24_LEN;
+
+                    der.buffer = ssl->buffers.certChain->buffer + idx;
+                    idx += der.length;
+
+                    if (idx > ssl->buffers.certChain->length)
+                        break;
+
+                    ret = CreateOcspRequest(ssl, request, cert, der.buffer,
+                                                                    der.length);
+                    if (ret == 0) {
+                        request->ssl = ssl;
+                        ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling,
+                                                    request, &responses[i + 1]);
+
+                        /* Suppressing, not critical */
+                        if (ret == OCSP_CERT_REVOKED ||
+                            ret == OCSP_CERT_UNKNOWN ||
+                            ret == OCSP_LOOKUP_FAIL) {
+                            ret = 0;
+                        }
+
+
+                        i++;
+                        FreeOcspRequest(request);
+                    }
+                }
+
+                XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+            #ifdef WOLFSSL_SMALL_STACK
+                XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
+            #endif
+            }
+            else {
+                while (ret == 0 &&
+                            NULL != (request = ssl->ctx->chainOcspRequest[i])) {
+                    request->ssl = ssl;
+                    ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling,
+                                                request, &responses[++i]);
+
+                    /* Suppressing, not critical */
+                    if (ret == OCSP_CERT_REVOKED ||
+                        ret == OCSP_CERT_UNKNOWN ||
+                        ret == OCSP_LOOKUP_FAIL) {
+                        ret = 0;
+                    }
+                }
+            }
+
+            if (responses[0].buffer) {
+                if (ret == 0) {
+                    ret = BuildCertificateStatus(ssl, status_type, responses,
+                                                                   (byte)i + 1);
+                }
+
+                for (i = 0; i < 1 + MAX_CHAIN_DEPTH; i++) {
+                    if (responses[i].buffer) {
+                        XFREE(responses[i].buffer, ssl->heap,
+                                                     DYNAMIC_TYPE_OCSP_REQUEST);
+                    }
+                }
+            }
+
+            break;
+        }
+    #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+    #endif /* NO_WOLFSSL_SERVER */
+
+        default:
+            break;
+    }
+
+    WOLFSSL_LEAVE("SendCertificateStatus", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_STATUS_SEND);
+
+    return ret;
+}
+
+#endif /* !NO_CERTS */
+
+#endif /* WOLFSSL_NO_TLS12 */
+
+
+/* If secure renegotiation is disabled, this will always return false.
+ * Otherwise it checks to see if we are currently renegotiating. */
+static WC_INLINE int IsSCR(WOLFSSL* ssl)
+{
+#ifndef HAVE_SECURE_RENEGOTIATION
+    (void)ssl;
+#else /* HAVE_SECURE_RENEGOTIATION */
+    if (ssl->secure_renegotiation &&
+            ssl->secure_renegotiation->enabled &&
+            ssl->options.handShakeState != HANDSHAKE_DONE)
+        return 1;
+#endif /* HAVE_SECURE_RENEGOTIATION */
+    return 0;
+}
+
+
+int SendData(WOLFSSL* ssl, const void* data, int sz)
+{
+    int sent = 0,  /* plainText size */
+        sendSz,
+        ret,
+        dtlsExtra = 0;
+    int groupMsgs = 0;
+
+    if (ssl->error == WANT_WRITE
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        || ssl->error == WC_PENDING_E
+    #endif
+    ) {
+        ssl->error = 0;
+    }
+
+    /* don't allow write after decrypt or mac error */
+    if (ssl->error == VERIFY_MAC_ERROR || ssl->error == DECRYPT_ERROR) {
+        /* For DTLS allow these possible errors and allow the session
+            to continue despite them */
+        if (ssl->options.dtls) {
+            ssl->error = 0;
+        }
+        else {
+            WOLFSSL_MSG("Not allowing write after decrypt or mac error");
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+
+#ifdef WOLFSSL_EARLY_DATA
+    if (ssl->earlyData != no_early_data) {
+        if (ssl->options.handShakeState == HANDSHAKE_DONE) {
+            WOLFSSL_MSG("handshake complete, trying to send early data");
+            return BUILD_MSG_ERROR;
+        }
+    #ifdef WOLFSSL_EARLY_DATA_GROUP
+        groupMsgs = 1;
+    #endif
+    }
+    else
+#endif
+    if (ssl->options.handShakeState != HANDSHAKE_DONE && !IsSCR(ssl)) {
+        int err;
+        WOLFSSL_MSG("handshake not complete, trying to finish");
+        if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) {
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            /* if async would block return WANT_WRITE */
+            if (ssl->error == WC_PENDING_E) {
+                return WOLFSSL_CBIO_ERR_WANT_WRITE;
+            }
+        #endif
+            return  err;
+        }
+    }
+
+    /* last time system socket output buffer was full, try again to send */
+    if (!groupMsgs && ssl->buffers.outputBuffer.length > 0) {
+        WOLFSSL_MSG("output buffer was full, trying to send again");
+        if ( (ssl->error = SendBuffered(ssl)) < 0) {
+            WOLFSSL_ERROR(ssl->error);
+            if (ssl->error == SOCKET_ERROR_E && (ssl->options.connReset ||
+                                                 ssl->options.isClosed)) {
+                ssl->error = SOCKET_PEER_CLOSED_E;
+                WOLFSSL_ERROR(ssl->error);
+                return 0;  /* peer reset or closed */
+            }
+            return ssl->error;
+        }
+        else {
+            /* advance sent to previous sent + plain size just sent */
+            sent = ssl->buffers.prevSent + ssl->buffers.plainSz;
+            WOLFSSL_MSG("sent write buffered data");
+
+            if (sent > sz) {
+                WOLFSSL_MSG("error: write() after WANT_WRITE with short size");
+                return ssl->error = BAD_FUNC_ARG;
+            }
+        }
+    }
+
+#ifdef WOLFSSL_DTLS
+    if (ssl->options.dtls) {
+        dtlsExtra = DTLS_RECORD_EXTRA;
+    }
+#endif
+
+    for (;;) {
+        int   len;
+        byte* out;
+        byte* sendBuffer = (byte*)data + sent;  /* may switch on comp */
+        int   buffSz;                           /* may switch on comp */
+        int   outputSz;
+#ifdef HAVE_LIBZ
+        byte  *comp = NULL;
+#endif
+
+        if (sent == sz) break;
+
+        len = wolfSSL_GetMaxRecordSize(ssl, sz - sent);
+
+#ifdef WOLFSSL_DTLS
+        if (IsDtlsNotSctpMode(ssl)) {
+            len = min(len, MAX_UDP_SIZE);
+        }
+#endif
+        buffSz = len;
+
+        /* check for available size */
+        outputSz = len + COMP_EXTRA + dtlsExtra + MAX_MSG_EXTRA;
+        if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
+            return ssl->error = ret;
+
+        /* get output buffer */
+        out = ssl->buffers.outputBuffer.buffer +
+              ssl->buffers.outputBuffer.length;
+
+#ifdef HAVE_LIBZ
+        if (ssl->options.usingCompression) {
+            int comp_size = MAX_RECORD_SIZE + MAX_COMP_EXTRA;
+            comp = XMALLOC(comp_size, ssl->heap, DYNAMIC_TYPE_NONE);
+            if (comp == NULL)
+                return BUFFER_ERROR;
+            buffSz = myCompress(ssl, sendBuffer, buffSz, comp, comp_size);
+            if (buffSz < 0) {
+                return buffSz;
+            }
+            sendBuffer = comp;
+        }
+#endif
+        if (!ssl->options.tls1_3) {
+            sendSz = BuildMessage(ssl, out, outputSz, sendBuffer, buffSz,
+                                  application_data, 0, 0, 1);
+        }
+        else {
+#ifdef WOLFSSL_TLS13
+            sendSz = BuildTls13Message(ssl, out, outputSz, sendBuffer, buffSz,
+                                       application_data, 0, 0, 1);
+#else
+            sendSz = BUFFER_ERROR;
+#endif
+        }
+#ifdef HAVE_LIBZ
+        XFREE(comp, ssl->heap, DYNAMIC_TYPE_NONE);
+#endif
+        if (sendSz < 0) {
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (sendSz == WC_PENDING_E)
+                ssl->error = sendSz;
+        #endif
+            return BUILD_MSG_ERROR;
+        }
+
+        ssl->buffers.outputBuffer.length += sendSz;
+
+        if ( (ssl->error = SendBuffered(ssl)) < 0) {
+            WOLFSSL_ERROR(ssl->error);
+            /* store for next call if WANT_WRITE or user embedSend() that
+               doesn't present like WANT_WRITE */
+            ssl->buffers.plainSz  = len;
+            ssl->buffers.prevSent = sent;
+            if (ssl->error == SOCKET_ERROR_E && (ssl->options.connReset ||
+                                                 ssl->options.isClosed)) {
+                ssl->error = SOCKET_PEER_CLOSED_E;
+                WOLFSSL_ERROR(ssl->error);
+                return 0;  /* peer reset or closed */
+            }
+            return ssl->error;
+        }
+
+        sent += len;
+
+        /* only one message per attempt */
+        if (ssl->options.partialWrite == 1) {
+            WOLFSSL_MSG("Partial Write on, only sending one record");
+            break;
+        }
+    }
+
+    return sent;
+}
+
+/* process input data */
+int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek)
+{
+    int size;
+
+    WOLFSSL_ENTER("ReceiveData()");
+
+    /* reset error state */
+    if (ssl->error == WANT_READ
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        || ssl->error == WC_PENDING_E
+    #endif
+    ) {
+        ssl->error = 0;
+    }
+
+#ifdef WOLFSSL_DTLS
+    if (ssl->options.dtls) {
+        /* In DTLS mode, we forgive some errors and allow the session
+         * to continue despite them. */
+        if (ssl->error == VERIFY_MAC_ERROR || ssl->error == DECRYPT_ERROR)
+            ssl->error = 0;
+    }
+#endif /* WOLFSSL_DTLS */
+
+    if (ssl->error != 0 && ssl->error != WANT_WRITE) {
+        WOLFSSL_MSG("User calling wolfSSL_read in error state, not allowed");
+        return ssl->error;
+    }
+
+#ifdef WOLFSSL_EARLY_DATA
+    if (ssl->earlyData != no_early_data) {
+    }
+    else
+#endif
+    if (ssl->options.handShakeState != HANDSHAKE_DONE) {
+        int err;
+        WOLFSSL_MSG("Handshake not complete, trying to finish");
+        if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) {
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            /* if async would block return WANT_WRITE */
+            if (ssl->error == WC_PENDING_E) {
+                return WOLFSSL_CBIO_ERR_WANT_READ;
+            }
+        #endif
+            return  err;
+        }
+    }
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+startScr:
+    if (ssl->secure_renegotiation && ssl->secure_renegotiation->startScr) {
+        int err;
+        WOLFSSL_MSG("Need to start scr, server requested");
+        if ( (err = wolfSSL_Rehandshake(ssl)) != WOLFSSL_SUCCESS)
+            return  err;
+        ssl->secure_renegotiation->startScr = 0;  /* only start once */
+    }
+#endif
+
+    while (ssl->buffers.clearOutputBuffer.length == 0) {
+        if ( (ssl->error = ProcessReply(ssl)) < 0) {
+            WOLFSSL_ERROR(ssl->error);
+            if (ssl->error == ZERO_RETURN) {
+                WOLFSSL_MSG("Zero return, no more data coming");
+                return 0;         /* no more data coming */
+            }
+            if (ssl->error == SOCKET_ERROR_E) {
+                if (ssl->options.connReset || ssl->options.isClosed) {
+                    WOLFSSL_MSG("Peer reset or closed, connection done");
+                    ssl->error = SOCKET_PEER_CLOSED_E;
+                    WOLFSSL_ERROR(ssl->error);
+                    return 0;     /* peer reset or closed */
+                }
+            }
+            return ssl->error;
+        }
+        #ifdef HAVE_SECURE_RENEGOTIATION
+            if (ssl->secure_renegotiation &&
+                ssl->secure_renegotiation->startScr) {
+                goto startScr;
+            }
+        #endif
+    }
+
+    if (sz < (int)ssl->buffers.clearOutputBuffer.length)
+        size = sz;
+    else
+        size = ssl->buffers.clearOutputBuffer.length;
+
+    XMEMCPY(output, ssl->buffers.clearOutputBuffer.buffer, size);
+
+    if (peek == 0) {
+        ssl->buffers.clearOutputBuffer.length -= size;
+        ssl->buffers.clearOutputBuffer.buffer += size;
+    }
+
+    if (ssl->buffers.clearOutputBuffer.length == 0 &&
+                                           ssl->buffers.inputBuffer.dynamicFlag)
+       ShrinkInputBuffer(ssl, NO_FORCED_FREE);
+
+    WOLFSSL_LEAVE("ReceiveData()", size);
+    return size;
+}
+
+
+/* send alert message */
+int SendAlert(WOLFSSL* ssl, int severity, int type)
+{
+    byte input[ALERT_SIZE];
+    byte *output;
+    int  sendSz;
+    int  ret;
+    int  outputSz;
+    int  dtlsExtra = 0;
+
+    WOLFSSL_ENTER("SendAlert");
+
+#ifdef HAVE_WRITE_DUP
+    if (ssl->dupWrite && ssl->dupSide == READ_DUP_SIDE) {
+        int notifyErr = 0;
+
+        WOLFSSL_MSG("Read dup side cannot write alerts, notifying sibling");
+
+        if (type == close_notify) {
+            notifyErr = ZERO_RETURN;
+        } else if (severity == alert_fatal) {
+            notifyErr = FATAL_ERROR;
+        }
+
+        if (notifyErr != 0) {
+            return NotifyWriteSide(ssl, notifyErr);
+        }
+
+        return 0;
+    }
+#endif
+
+    /* if sendalert is called again for nonblocking */
+    if (ssl->options.sendAlertState != 0) {
+        ret = SendBuffered(ssl);
+        if (ret == 0)
+            ssl->options.sendAlertState = 0;
+        return ret;
+    }
+
+   #ifdef OPENSSL_EXTRA
+        if (ssl->CBIS != NULL) {
+            ssl->CBIS(ssl, SSL_CB_ALERT, type);
+        }
+   #endif
+   #ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls)
+           dtlsExtra = DTLS_RECORD_EXTRA;
+   #endif
+
+    /* check for available size */
+    outputSz = ALERT_SIZE + MAX_MSG_EXTRA + dtlsExtra;
+    if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
+        return ret;
+
+    /* Check output buffer */
+    if (ssl->buffers.outputBuffer.buffer == NULL)
+        return BUFFER_E;
+
+    /* get output buffer */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+
+    input[0] = (byte)severity;
+    input[1] = (byte)type;
+    ssl->alert_history.last_tx.code = type;
+    ssl->alert_history.last_tx.level = severity;
+    if (severity == alert_fatal) {
+        ssl->options.isClosed = 1;  /* Don't send close_notify */
+    }
+
+    /* only send encrypted alert if handshake actually complete, otherwise
+       other side may not be able to handle it */
+    if (IsEncryptionOn(ssl, 1) && (IsAtLeastTLSv1_3(ssl->version) ||
+                                                  ssl->options.handShakeDone)) {
+        sendSz = BuildMessage(ssl, output, outputSz, input, ALERT_SIZE, alert,
+                                                                       0, 0, 0);
+    }
+    else {
+
+        AddRecordHeader(output, ALERT_SIZE, alert, ssl);
+        output += RECORD_HEADER_SZ;
+        #ifdef WOLFSSL_DTLS
+            if (ssl->options.dtls)
+                output += DTLS_RECORD_EXTRA;
+        #endif
+        XMEMCPY(output, input, ALERT_SIZE);
+
+        sendSz = RECORD_HEADER_SZ + ALERT_SIZE;
+        #ifdef WOLFSSL_DTLS
+            if (ssl->options.dtls)
+                sendSz += DTLS_RECORD_EXTRA;
+        #endif
+    }
+    if (sendSz < 0)
+        return BUILD_MSG_ERROR;
+
+    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+        if (ssl->hsInfoOn)
+            AddPacketName(ssl, "Alert");
+        if (ssl->toInfoOn)
+            AddPacketInfo(ssl, "Alert", alert, output, sendSz, WRITE_PROTO,
+                    ssl->heap);
+    #endif
+
+    ssl->buffers.outputBuffer.length += sendSz;
+    ssl->options.sendAlertState = 1;
+
+    ret = SendBuffered(ssl);
+
+    WOLFSSL_LEAVE("SendAlert", ret);
+
+    return ret;
+}
+
+const char* wolfSSL_ERR_reason_error_string(unsigned long e)
+{
+#ifdef NO_ERROR_STRINGS
+
+    (void)e;
+    return "no support for error strings built in";
+
+#else
+
+    int error = (int)e;
+
+    /* pass to wolfCrypt */
+    if (error < MAX_CODE_E && error > MIN_CODE_E) {
+        return wc_GetErrorString(error);
+    }
+
+    switch (error) {
+
+#ifdef WOLFSSL_WPAS
+    case 0 :
+        return "ok";
+#endif
+
+    case UNSUPPORTED_SUITE :
+        return "unsupported cipher suite";
+
+    case INPUT_CASE_ERROR :
+        return "input state error";
+
+    case PREFIX_ERROR :
+        return "bad index to key rounds";
+
+    case MEMORY_ERROR :
+        return "out of memory";
+
+    case VERIFY_FINISHED_ERROR :
+        return "verify problem on finished";
+
+    case VERIFY_MAC_ERROR :
+        return "verify mac problem";
+
+    case PARSE_ERROR :
+        return "parse error on header";
+
+    case SIDE_ERROR :
+        return "wrong client/server type";
+
+    case NO_PEER_CERT :
+        return "peer didn't send cert";
+
+    case UNKNOWN_HANDSHAKE_TYPE :
+        return "weird handshake type";
+
+    case SOCKET_ERROR_E :
+        return "error state on socket";
+
+    case SOCKET_NODATA :
+        return "expected data, not there";
+
+    case INCOMPLETE_DATA :
+        return "don't have enough data to complete task";
+
+    case UNKNOWN_RECORD_TYPE :
+        return "unknown type in record hdr";
+
+    case DECRYPT_ERROR :
+        return "error during decryption";
+
+    case FATAL_ERROR :
+        return "received alert fatal error";
+
+    case ENCRYPT_ERROR :
+        return "error during encryption";
+
+    case FREAD_ERROR :
+        return "fread problem";
+
+    case NO_PEER_KEY :
+        return "need peer's key";
+
+    case NO_PRIVATE_KEY :
+        return "need the private key";
+
+    case NO_DH_PARAMS :
+        return "server missing DH params";
+
+    case RSA_PRIVATE_ERROR :
+        return "error during rsa priv op";
+
+    case MATCH_SUITE_ERROR :
+        return "can't match cipher suite";
+
+    case COMPRESSION_ERROR :
+        return "compression mismatch error";
+
+    case BUILD_MSG_ERROR :
+        return "build message failure";
+
+    case BAD_HELLO :
+        return "client hello malformed";
+
+    case DOMAIN_NAME_MISMATCH :
+        return "peer subject name mismatch";
+
+    case IPADDR_MISMATCH :
+        return "peer ip address mismatch";
+
+    case WANT_READ :
+    case WOLFSSL_ERROR_WANT_READ :
+        return "non-blocking socket wants data to be read";
+
+    case NOT_READY_ERROR :
+        return "handshake layer not ready yet, complete first";
+
+    case VERSION_ERROR :
+        return "record layer version error";
+
+    case WANT_WRITE :
+    case WOLFSSL_ERROR_WANT_WRITE :
+        return "non-blocking socket write buffer full";
+
+    case BUFFER_ERROR :
+        return "malformed buffer input error";
+
+    case VERIFY_CERT_ERROR :
+        return "verify problem on certificate";
+
+    case VERIFY_SIGN_ERROR :
+        return "verify problem based on signature";
+
+    case CLIENT_ID_ERROR :
+        return "psk client identity error";
+
+    case SERVER_HINT_ERROR:
+        return "psk server hint error";
+
+    case PSK_KEY_ERROR:
+        return "psk key callback error";
+
+    case NTRU_KEY_ERROR:
+        return "NTRU key error";
+
+    case NTRU_DRBG_ERROR:
+        return "NTRU drbg error";
+
+    case NTRU_ENCRYPT_ERROR:
+        return "NTRU encrypt error";
+
+    case NTRU_DECRYPT_ERROR:
+        return "NTRU decrypt error";
+
+    case GETTIME_ERROR:
+        return "gettimeofday() error";
+
+    case GETITIMER_ERROR:
+        return "getitimer() error";
+
+    case SIGACT_ERROR:
+        return "sigaction() error";
+
+    case SETITIMER_ERROR:
+        return "setitimer() error";
+
+    case LENGTH_ERROR:
+        return "record layer length error";
+
+    case PEER_KEY_ERROR:
+        return "cant decode peer key";
+
+    case ZERO_RETURN:
+    case WOLFSSL_ERROR_ZERO_RETURN:
+        return "peer sent close notify alert";
+
+    case ECC_CURVETYPE_ERROR:
+        return "Bad ECC Curve Type or unsupported";
+
+    case ECC_CURVE_ERROR:
+        return "Bad ECC Curve or unsupported";
+
+    case ECC_PEERKEY_ERROR:
+        return "Bad ECC Peer Key";
+
+    case ECC_MAKEKEY_ERROR:
+        return "ECC Make Key failure";
+
+    case ECC_EXPORT_ERROR:
+        return "ECC Export Key failure";
+
+    case ECC_SHARED_ERROR:
+        return "ECC DHE shared failure";
+
+    case NOT_CA_ERROR:
+        return "Not a CA by basic constraint error";
+
+    case HTTP_TIMEOUT:
+        return "HTTP timeout for OCSP or CRL req";
+
+    case BAD_CERT_MANAGER_ERROR:
+        return "Bad Cert Manager error";
+
+    case OCSP_CERT_REVOKED:
+        return "OCSP Cert revoked";
+
+    case CRL_CERT_REVOKED:
+        return "CRL Cert revoked";
+
+    case CRL_MISSING:
+        return "CRL missing, not loaded";
+
+    case MONITOR_SETUP_E:
+        return "CRL monitor setup error";
+
+    case THREAD_CREATE_E:
+        return "Thread creation problem";
+
+    case OCSP_NEED_URL:
+        return "OCSP need URL";
+
+    case OCSP_CERT_UNKNOWN:
+        return "OCSP Cert unknown";
+
+    case OCSP_LOOKUP_FAIL:
+        return "OCSP Responder lookup fail";
+
+    case MAX_CHAIN_ERROR:
+        return "Maximum Chain Depth Exceeded";
+
+    case COOKIE_ERROR:
+        return "DTLS Cookie Error";
+
+    case SEQUENCE_ERROR:
+        return "DTLS Sequence Error";
+
+    case SUITES_ERROR:
+        return "Suites Pointer Error";
+
+    case OUT_OF_ORDER_E:
+        return "Out of order message, fatal";
+
+    case BAD_KEA_TYPE_E:
+        return "Bad KEA type found";
+
+    case SANITY_CIPHER_E:
+        return "Sanity check on ciphertext failed";
+
+    case RECV_OVERFLOW_E:
+        return "Receive callback returned more than requested";
+
+    case GEN_COOKIE_E:
+        return "Generate Cookie Error";
+
+    case NO_PEER_VERIFY:
+        return "Need peer certificate verify Error";
+
+    case FWRITE_ERROR:
+        return "fwrite Error";
+
+    case CACHE_MATCH_ERROR:
+        return "Cache restore header match Error";
+
+    case UNKNOWN_SNI_HOST_NAME_E:
+        return "Unrecognized host name Error";
+
+    case UNKNOWN_MAX_FRAG_LEN_E:
+        return "Unrecognized max frag len Error";
+
+    case KEYUSE_SIGNATURE_E:
+        return "Key Use digitalSignature not set Error";
+
+    case KEYUSE_ENCIPHER_E:
+        return "Key Use keyEncipherment not set Error";
+
+    case EXTKEYUSE_AUTH_E:
+        return "Ext Key Use server/client auth not set Error";
+
+    case SEND_OOB_READ_E:
+        return "Send Callback Out of Bounds Read Error";
+
+    case SECURE_RENEGOTIATION_E:
+        return "Invalid Renegotiation Error";
+
+    case SESSION_TICKET_LEN_E:
+        return "Session Ticket Too Long Error";
+
+    case SESSION_TICKET_EXPECT_E:
+        return "Session Ticket Error";
+
+    case SESSION_SECRET_CB_E:
+        return "Session Secret Callback Error";
+
+    case NO_CHANGE_CIPHER_E:
+        return "Finished received from peer before Change Cipher Error";
+
+    case SANITY_MSG_E:
+        return "Sanity Check on message order Error";
+
+    case DUPLICATE_MSG_E:
+        return "Duplicate HandShake message Error";
+
+    case SNI_UNSUPPORTED:
+        return "Protocol version does not support SNI Error";
+
+    case SOCKET_PEER_CLOSED_E:
+        return "Peer closed underlying transport Error";
+
+    case BAD_TICKET_KEY_CB_SZ:
+        return "Bad user session ticket key callback Size Error";
+
+    case BAD_TICKET_MSG_SZ:
+        return "Bad session ticket message Size Error";
+
+    case BAD_TICKET_ENCRYPT:
+        return "Bad user ticket callback encrypt Error";
+
+    case DH_KEY_SIZE_E:
+        return "DH key too small Error";
+
+    case SNI_ABSENT_ERROR:
+        return "No Server Name Indication extension Error";
+
+    case RSA_SIGN_FAULT:
+        return "RSA Signature Fault Error";
+
+    case HANDSHAKE_SIZE_ERROR:
+        return "Handshake message too large Error";
+
+    case UNKNOWN_ALPN_PROTOCOL_NAME_E:
+        return "Unrecognized protocol name Error";
+
+    case BAD_CERTIFICATE_STATUS_ERROR:
+        return "Bad Certificate Status Message Error";
+
+    case OCSP_INVALID_STATUS:
+        return "Invalid OCSP Status Error";
+
+    case OCSP_WANT_READ:
+        return "OCSP nonblock wants read";
+
+    case RSA_KEY_SIZE_E:
+        return "RSA key too small";
+
+    case ECC_KEY_SIZE_E:
+        return "ECC key too small";
+
+    case DTLS_EXPORT_VER_E:
+        return "Version needs updated after code change or version mismatch";
+
+    case INPUT_SIZE_E:
+        return "Input size too large Error";
+
+    case CTX_INIT_MUTEX_E:
+        return "Initialize ctx mutex error";
+
+    case EXT_MASTER_SECRET_NEEDED_E:
+        return "Extended Master Secret must be enabled to resume EMS session";
+
+    case DTLS_POOL_SZ_E:
+        return "Maximum DTLS pool size exceeded";
+
+    case DECODE_E:
+        return "Decode handshake message error";
+
+    case WRITE_DUP_READ_E:
+        return "Write dup write side can't read error";
+
+    case WRITE_DUP_WRITE_E:
+        return "Write dup read side can't write error";
+
+    case INVALID_CERT_CTX_E:
+        return "Certificate context does not match request or not empty";
+
+    case BAD_KEY_SHARE_DATA:
+        return "The Key Share data contains group that wasn't in Client Hello";
+
+    case MISSING_HANDSHAKE_DATA:
+        return "The handshake message is missing required data";
+
+    case BAD_BINDER:
+        return "Binder value does not match value server calculated";
+
+    case EXT_NOT_ALLOWED:
+        return "Extension type not allowed in handshake message type";
+
+    case INVALID_PARAMETER:
+        return "The security parameter is invalid";
+
+    case UNSUPPORTED_EXTENSION:
+        return "TLS Extension not requested by the client";
+
+    case PRF_MISSING:
+        return "Pseudo-random function is not enabled";
+
+    case KEY_SHARE_ERROR:
+        return "Key share extension did not contain a valid named group";
+
+    case POST_HAND_AUTH_ERROR:
+        return "Client will not do post handshake authentication";
+
+    case HRR_COOKIE_ERROR:
+        return "Cookie does not match one sent in HelloRetryRequest";
+
+    case MCAST_HIGHWATER_CB_E:
+        return "Multicast highwater callback returned error";
+
+    case ALERT_COUNT_E:
+        return "Alert Count exceeded error";
+
+    case EXT_MISSING:
+        return "Required TLS extension missing";
+
+    case DTLS_RETX_OVER_TX:
+        return "DTLS interrupting flight transmit with retransmit";
+
+    case DH_PARAMS_NOT_FFDHE_E:
+        return "Server DH parameters were not from the FFDHE set as required";
+
+    case TCA_INVALID_ID_TYPE:
+        return "TLS Extension Trusted CA ID type invalid";
+
+    case TCA_ABSENT_ERROR:
+        return "TLS Extension Trusted CA ID response absent";
+
+    case TSIP_MAC_DIGSZ_E:
+        return "TSIP MAC size invalid, must be sized for SHA-1 or SHA-256";
+
+    case CLIENT_CERT_CB_ERROR:
+        return "Error importing client cert or key from callback";
+
+    case SSL_SHUTDOWN_ALREADY_DONE_E:
+        return "Shutdown has already occurred";
+
+    case TLS13_SECRET_CB_E:
+        return "TLS1.3 Secret Callback Error";
+
+    default :
+        return "unknown error number";
+    }
+
+#endif /* NO_ERROR_STRINGS */
+}
+
+void SetErrorString(int error, char* str)
+{
+    XSTRNCPY(str, wolfSSL_ERR_reason_error_string(error), WOLFSSL_MAX_ERROR_SZ);
+    str[WOLFSSL_MAX_ERROR_SZ-1] = 0;
+}
+
+#ifndef NO_ERROR_STRINGS
+    #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+        #define SUITE_INFO(x,y,z,w,v,u) {(x),(y),(z),(w),(v),(u)}
+    #else
+        #define SUITE_INFO(x,y,z,w,v,u) {(x),(y),(z),(w)}
+    #endif
+#else
+    #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+        #define SUITE_INFO(x,y,z,w,v,u) {(x),(z),(w),(v),(u)}
+    #else
+        #define SUITE_INFO(x,y,z,w,v,u) {(x),(z),(w)}
+    #endif
+#endif
+
+static const CipherSuiteInfo cipher_names[] =
+{
+
+#ifdef BUILD_TLS_AES_128_GCM_SHA256
+    SUITE_INFO("TLS13-AES128-GCM-SHA256","TLS_AES_128_GCM_SHA256",TLS13_BYTE,TLS_AES_128_GCM_SHA256, TLSv1_3_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_AES_256_GCM_SHA384
+    SUITE_INFO("TLS13-AES256-GCM-SHA384","TLS_AES_256_GCM_SHA384",TLS13_BYTE,TLS_AES_256_GCM_SHA384, TLSv1_3_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256
+    SUITE_INFO("TLS13-CHACHA20-POLY1305-SHA256","TLS_CHACHA20_POLY1305_SHA256",TLS13_BYTE,TLS_CHACHA20_POLY1305_SHA256, TLSv1_3_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_AES_128_CCM_SHA256
+    SUITE_INFO("TLS13-AES128-CCM-SHA256","TLS_AES_128_CCM_SHA256",TLS13_BYTE,TLS_AES_128_CCM_SHA256, TLSv1_3_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_AES_128_CCM_8_SHA256
+    SUITE_INFO("TLS13-AES128-CCM-8-SHA256","TLS_AES_128_CCM_8_SHA256",TLS13_BYTE,TLS_AES_128_CCM_8_SHA256,TLSv1_3_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_SHA256_SHA256
+    SUITE_INFO("TLS13-SHA256-SHA256","TLS_SHA256_SHA256",ECC_BYTE,TLS_SHA256_SHA256,TLSv1_3_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_SHA384_SHA384
+    SUITE_INFO("TLS13-SHA384-SHA384","TLS_SHA384_SHA384",ECC_BYTE,TLS_SHA384_SHA384,TLSv1_3_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifndef WOLFSSL_NO_TLS12
+
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
+    SUITE_INFO("RC4-SHA","SSL_RSA_WITH_RC4_128_SHA",CIPHER_BYTE,SSL_RSA_WITH_RC4_128_SHA,SSLv3_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
+    SUITE_INFO("RC4-MD5","SSL_RSA_WITH_RC4_128_MD5",CIPHER_BYTE,SSL_RSA_WITH_RC4_128_MD5,SSLv3_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
+    SUITE_INFO("DES-CBC3-SHA","SSL_RSA_WITH_3DES_EDE_CBC_SHA",CIPHER_BYTE,SSL_RSA_WITH_3DES_EDE_CBC_SHA,SSLv3_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
+    SUITE_INFO("AES128-SHA","TLS_RSA_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_AES_128_CBC_SHA,SSLv3_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
+    SUITE_INFO("AES256-SHA","TLS_RSA_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_AES_256_CBC_SHA,SSLv3_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_NULL_MD5
+    SUITE_INFO("NULL-MD5","TLS_RSA_WITH_NULL_MD5",CIPHER_BYTE,TLS_RSA_WITH_NULL_MD5,SSLv3_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_NULL_SHA
+    SUITE_INFO("NULL-SHA","TLS_RSA_WITH_NULL_SHA",CIPHER_BYTE,TLS_RSA_WITH_NULL_SHA,SSLv3_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_NULL_SHA256
+    SUITE_INFO("NULL-SHA256","TLS_RSA_WITH_NULL_SHA256",CIPHER_BYTE,TLS_RSA_WITH_NULL_SHA256,TLSv1_2_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+    SUITE_INFO("DHE-RSA-AES128-SHA","TLS_DHE_RSA_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,SSLv3_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+    SUITE_INFO("DHE-RSA-AES256-SHA","TLS_DHE_RSA_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_256_CBC_SHA,SSLv3_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
+    SUITE_INFO("DHE-PSK-AES256-GCM-SHA384","TLS_DHE_PSK_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,TLSv1_2_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
+    SUITE_INFO("DHE-PSK-AES128-GCM-SHA256","TLS_DHE_PSK_WITH_AES_128_GCM_SHA256",CIPHER_BYTE,TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,TLSv1_2_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384
+    SUITE_INFO("PSK-AES256-GCM-SHA384","TLS_PSK_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_PSK_WITH_AES_256_GCM_SHA384,TLSv1_2_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256
+    SUITE_INFO("PSK-AES128-GCM-SHA256","TLS_PSK_WITH_AES_128_GCM_SHA256",CIPHER_BYTE,TLS_PSK_WITH_AES_128_GCM_SHA256,TLSv1_2_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
+    SUITE_INFO("DHE-PSK-AES256-CBC-SHA384","TLS_DHE_PSK_WITH_AES_256_CBC_SHA384",CIPHER_BYTE,TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
+    SUITE_INFO("DHE-PSK-AES128-CBC-SHA256","TLS_DHE_PSK_WITH_AES_128_CBC_SHA256",CIPHER_BYTE,TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384
+    SUITE_INFO("PSK-AES256-CBC-SHA384","TLS_PSK_WITH_AES_256_CBC_SHA384",CIPHER_BYTE,TLS_PSK_WITH_AES_256_CBC_SHA384,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256
+    SUITE_INFO("PSK-AES128-CBC-SHA256","TLS_PSK_WITH_AES_128_CBC_SHA256",CIPHER_BYTE,TLS_PSK_WITH_AES_128_CBC_SHA256,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
+    SUITE_INFO("PSK-AES128-CBC-SHA","TLS_PSK_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_PSK_WITH_AES_128_CBC_SHA,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
+    SUITE_INFO("PSK-AES256-CBC-SHA","TLS_PSK_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_PSK_WITH_AES_256_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CCM
+    SUITE_INFO("DHE-PSK-AES128-CCM","TLS_DHE_PSK_WITH_AES_128_CCM",ECC_BYTE,TLS_DHE_PSK_WITH_AES_128_CCM,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CCM
+    SUITE_INFO("DHE-PSK-AES256-CCM","TLS_DHE_PSK_WITH_AES_256_CCM",ECC_BYTE,TLS_DHE_PSK_WITH_AES_256_CCM,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM
+    SUITE_INFO("PSK-AES128-CCM","TLS_PSK_WITH_AES_128_CCM",ECC_BYTE,TLS_PSK_WITH_AES_128_CCM,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM
+    SUITE_INFO("PSK-AES256-CCM","TLS_PSK_WITH_AES_256_CCM",ECC_BYTE,TLS_PSK_WITH_AES_256_CCM,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM_8
+    SUITE_INFO("PSK-AES128-CCM-8","TLS_PSK_WITH_AES_128_CCM_8",ECC_BYTE,TLS_PSK_WITH_AES_128_CCM_8,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM_8
+    SUITE_INFO("PSK-AES256-CCM-8","TLS_PSK_WITH_AES_256_CCM_8",ECC_BYTE,TLS_PSK_WITH_AES_256_CCM_8,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384
+    SUITE_INFO("DHE-PSK-NULL-SHA384","TLS_DHE_PSK_WITH_NULL_SHA384",CIPHER_BYTE,TLS_DHE_PSK_WITH_NULL_SHA384,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256
+    SUITE_INFO("DHE-PSK-NULL-SHA256","TLS_DHE_PSK_WITH_NULL_SHA256",CIPHER_BYTE,TLS_DHE_PSK_WITH_NULL_SHA256,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_NULL_SHA384
+    SUITE_INFO("PSK-NULL-SHA384","TLS_PSK_WITH_NULL_SHA384",CIPHER_BYTE,TLS_PSK_WITH_NULL_SHA384,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_NULL_SHA256
+    SUITE_INFO("PSK-NULL-SHA256","TLS_PSK_WITH_NULL_SHA256",CIPHER_BYTE,TLS_PSK_WITH_NULL_SHA256,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_NULL_SHA
+    SUITE_INFO("PSK-NULL-SHA","TLS_PSK_WITH_NULL_SHA",CIPHER_BYTE,TLS_PSK_WITH_NULL_SHA,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_MD5
+    SUITE_INFO("HC128-MD5","TLS_RSA_WITH_HC_128_MD5",CIPHER_BYTE,TLS_RSA_WITH_HC_128_MD5,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_SHA
+    SUITE_INFO("HC128-SHA","TLS_RSA_WITH_HC_128_SHA",CIPHER_BYTE,TLS_RSA_WITH_HC_128_SHA,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA
+    SUITE_INFO("RABBIT-SHA","TLS_RSA_WITH_RABBIT_SHA",CIPHER_BYTE,TLS_RSA_WITH_RABBIT_SHA,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
+    SUITE_INFO("NTRU-RC4-SHA","TLS_NTRU_RSA_WITH_RC4_128_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_RC4_128_SHA, TLSv1_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
+    SUITE_INFO("NTRU-DES-CBC3-SHA","TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
+    SUITE_INFO("NTRU-AES128-SHA","TLS_NTRU_RSA_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_AES_128_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
+    SUITE_INFO("NTRU-AES256-SHA","TLS_NTRU_RSA_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_AES_256_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8
+    SUITE_INFO("AES128-CCM-8","TLS_RSA_WITH_AES_128_CCM_8",ECC_BYTE,TLS_RSA_WITH_AES_128_CCM_8, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8
+    SUITE_INFO("AES256-CCM-8","TLS_RSA_WITH_AES_256_CCM_8",ECC_BYTE,TLS_RSA_WITH_AES_256_CCM_8, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM
+	SUITE_INFO("ECDHE-ECDSA-AES128-CCM","TLS_ECDHE_ECDSA_WITH_AES_128_CCM",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_CCM, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
+    SUITE_INFO("ECDHE-ECDSA-AES128-CCM-8","TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8
+    SUITE_INFO("ECDHE-ECDSA-AES256-CCM-8","TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+    SUITE_INFO("ECDHE-RSA-AES128-SHA","TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+    SUITE_INFO("ECDHE-RSA-AES256-SHA","TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+    SUITE_INFO("ECDHE-ECDSA-AES128-SHA","TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+    SUITE_INFO("ECDHE-ECDSA-AES256-SHA","TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
+    SUITE_INFO("ECDHE-RSA-RC4-SHA","TLS_ECDHE_RSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDHE_RSA_WITH_RC4_128_SHA, TLSv1_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+    SUITE_INFO("ECDHE-RSA-DES-CBC3-SHA","TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",ECC_BYTE,TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+    SUITE_INFO("ECDHE-ECDSA-RC4-SHA","TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLSv1_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+    SUITE_INFO("ECDHE-ECDSA-DES-CBC3-SHA","TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
+    SUITE_INFO("AES128-SHA256","TLS_RSA_WITH_AES_128_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_AES_128_CBC_SHA256, TLSv1_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
+    SUITE_INFO("AES256-SHA256","TLS_RSA_WITH_AES_256_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_AES_256_CBC_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+    SUITE_INFO("DHE-RSA-AES128-SHA256","TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+    SUITE_INFO("DHE-RSA-AES256-SHA256","TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
+    SUITE_INFO("ECDH-RSA-AES128-SHA","TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+    SUITE_INFO("ECDH-RSA-AES256-SHA","TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+    SUITE_INFO("ECDH-ECDSA-AES128-SHA","TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+    SUITE_INFO("ECDH-ECDSA-AES256-SHA","TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA
+    SUITE_INFO("ECDH-RSA-RC4-SHA","TLS_ECDH_RSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDH_RSA_WITH_RC4_128_SHA, TLSv1_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+    SUITE_INFO("ECDH-RSA-DES-CBC3-SHA","TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",ECC_BYTE,TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
+    SUITE_INFO("ECDH-ECDSA-RC4-SHA","TLS_ECDH_ECDSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLSv1_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+    SUITE_INFO("ECDH-ECDSA-DES-CBC3-SHA","TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",ECC_BYTE,TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
+    SUITE_INFO("AES128-GCM-SHA256","TLS_RSA_WITH_AES_128_GCM_SHA256",CIPHER_BYTE,TLS_RSA_WITH_AES_128_GCM_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384
+    SUITE_INFO("AES256-GCM-SHA384","TLS_RSA_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_RSA_WITH_AES_256_GCM_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
+    SUITE_INFO("DHE-RSA-AES128-GCM-SHA256","TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+    SUITE_INFO("DHE-RSA-AES256-GCM-SHA384","TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+    SUITE_INFO("ECDHE-RSA-AES128-GCM-SHA256","TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+    SUITE_INFO("ECDHE-RSA-AES256-GCM-SHA384","TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+    SUITE_INFO("ECDHE-ECDSA-AES128-GCM-SHA256","TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+    SUITE_INFO("ECDHE-ECDSA-AES256-GCM-SHA384","TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+    SUITE_INFO("ECDH-RSA-AES128-GCM-SHA256","TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
+    SUITE_INFO("ECDH-RSA-AES256-GCM-SHA384","TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+    SUITE_INFO("ECDH-ECDSA-AES128-GCM-SHA256","TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
+    SUITE_INFO("ECDH-ECDSA-AES256-GCM-SHA384","TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
+    SUITE_INFO("CAMELLIA128-SHA","TLS_RSA_WITH_CAMELLIA_128_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
+    SUITE_INFO("DHE-RSA-CAMELLIA128-SHA","TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
+    SUITE_INFO("CAMELLIA256-SHA","TLS_RSA_WITH_CAMELLIA_256_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
+    SUITE_INFO("DHE-RSA-CAMELLIA256-SHA","TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
+    SUITE_INFO("CAMELLIA128-SHA256","TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+    SUITE_INFO("DHE-RSA-CAMELLIA128-SHA256","TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
+    SUITE_INFO("CAMELLIA256-SHA256","TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
+    SUITE_INFO("DHE-RSA-CAMELLIA256-SHA256","TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+    SUITE_INFO("ECDHE-RSA-AES128-SHA256","TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
+    SUITE_INFO("ECDHE-ECDSA-AES128-SHA256","TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
+    SUITE_INFO("ECDH-RSA-AES128-SHA256","TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
+    SUITE_INFO("ECDH-ECDSA-AES128-SHA256","TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
+    SUITE_INFO("ECDHE-RSA-AES256-SHA384","TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
+    SUITE_INFO("ECDHE-ECDSA-AES256-SHA384","TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
+    SUITE_INFO("ECDH-RSA-AES256-SHA384","TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
+    SUITE_INFO("ECDH-ECDSA-AES256-SHA384","TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+    SUITE_INFO("ECDHE-RSA-CHACHA20-POLY1305","TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
+    SUITE_INFO("ECDHE-ECDSA-CHACHA20-POLY1305","TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+    SUITE_INFO("DHE-RSA-CHACHA20-POLY1305","TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+    SUITE_INFO("ECDHE-RSA-CHACHA20-POLY1305-OLD","TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+    SUITE_INFO("ECDHE-ECDSA-CHACHA20-POLY1305-OLD","TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+    SUITE_INFO("DHE-RSA-CHACHA20-POLY1305-OLD","TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256",CHACHA_BYTE,TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA
+    SUITE_INFO("ADH-AES128-SHA","TLS_DH_anon_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_DH_anon_WITH_AES_128_CBC_SHA, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DH_anon_WITH_AES_256_GCM_SHA384
+    SUITE_INFO("ADH-AES256-GCM-SHA384","TLS_DH_anon_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_DH_anon_WITH_AES_256_GCM_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_QSH
+    SUITE_INFO("QSH","TLS_QSH",QSH_BYTE,TLS_QSH, TLSv1_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef HAVE_RENEGOTIATION_INDICATION
+    SUITE_INFO("RENEGOTIATION-INFO","TLS_EMPTY_RENEGOTIATION_INFO_SCSV",CIPHER_BYTE,TLS_EMPTY_RENEGOTIATION_INFO_SCSV,SSLv3_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_IDEA_CBC_SHA
+    SUITE_INFO("IDEA-CBC-SHA","SSL_RSA_WITH_IDEA_CBC_SHA",CIPHER_BYTE,SSL_RSA_WITH_IDEA_CBC_SHA,SSLv3_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA
+    SUITE_INFO("ECDHE-ECDSA-NULL-SHA","TLS_ECDHE_ECDSA_WITH_NULL_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_NULL_SHA, TLSv1_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256
+    SUITE_INFO("ECDHE-PSK-NULL-SHA256","TLS_ECDHE_PSK_WITH_NULL_SHA256",ECC_BYTE,TLS_ECDHE_PSK_WITH_NULL_SHA256,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
+    SUITE_INFO("ECDHE-PSK-AES128-CBC-SHA256","TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,TLSv1_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256
+    SUITE_INFO("PSK-CHACHA20-POLY1305","TLS_PSK_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_PSK_WITH_CHACHA20_POLY1305_SHA256,TLSv1_2_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256
+    SUITE_INFO("ECDHE-PSK-CHACHA20-POLY1305","TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,TLSv1_2_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256
+    SUITE_INFO("DHE-PSK-CHACHA20-POLY1305","TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,TLSv1_2_MINOR,SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+    SUITE_INFO("EDH-RSA-DES-CBC3-SHA","TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR),
+#endif
+
+#ifdef BUILD_WDM_WITH_NULL_SHA256
+    SUITE_INFO("WDM-NULL-SHA256","WDM_WITH_NULL_SHA256",CIPHER_BYTE,WDM_WITH_NULL_SHA256, TLSv1_3_MINOR, SSLv3_MAJOR)
+#endif
+
+#endif /* WOLFSSL_NO_TLS12 */
+};
+
+
+/* returns the cipher_names array */
+const CipherSuiteInfo* GetCipherNames(void)
+{
+    return cipher_names;
+}
+
+
+/* returns the number of elements in the cipher_names array */
+int GetCipherNamesSize(void)
+{
+    return (int)(sizeof(cipher_names) / sizeof(CipherSuiteInfo));
+}
+
+
+const char* GetCipherNameInternal(const byte cipherSuite0, const byte cipherSuite)
+{
+    int i;
+    const char* nameInternal = "None";
+
+    for (i = 0; i < GetCipherNamesSize(); i++) {
+        if ((cipher_names[i].cipherSuite0 == cipherSuite0) &&
+            (cipher_names[i].cipherSuite  == cipherSuite)) {
+            nameInternal = cipher_names[i].name;
+            break;
+        }
+    }
+    return nameInternal;
+}
+
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+const char* GetCipherKeaStr(char n[][MAX_SEGMENT_SZ]) {
+    const char* keaStr = NULL;
+    const char *n0,*n1,*n2,*n3,*n4;
+    n0 = n[0];
+    n1 = n[1];
+    n2 = n[2];
+    n3 = n[3];
+    n4 = n[4];
+
+    if (XSTRNCMP(n0,"ECDHE",5) == 0 && XSTRNCMP(n1,"PSK",3) == 0)
+        keaStr = "ECDHEPSK";
+    else if (XSTRNCMP(n0,"ECDH",4) == 0)
+        keaStr = "ECDH";
+    else if (XSTRNCMP(n0,"DHE",3) == 0 && XSTRNCMP(n1,"PSK",3) == 0)
+        keaStr = "DHEPSK";
+    else if (XSTRNCMP(n0,"DHE",3) == 0)
+        keaStr = "DH";
+   else if (XSTRNCMP(n0,"RSA",3) == 0 && XSTRNCMP(n1,"PSK",3) == 0)
+        keaStr = "RSAPSK";
+    else if (XSTRNCMP(n0,"SRP",3) == 0)
+        keaStr = "SRP";
+    else if (XSTRNCMP(n0,"PSK",3) == 0)
+        keaStr = "PSK";
+    else if (XSTRNCMP(n0,"EDH",3) == 0)
+        keaStr = "EDH";
+    else if ((XSTRNCMP(n1,"SHA",3) == 0) || (XSTRNCMP(n2,"SHA",3) == 0) ||
+             (XSTRNCMP(n3,"SHA",3) == 0) || (XSTRNCMP(n4,"SHA",3) == 0) ||
+             (XSTRNCMP(n2,"RSA",3) == 0) || (XSTRNCMP(n0,"AES128",6) == 0) ||
+             (XSTRNCMP(n0,"AES256",6) == 0) || (XSTRNCMP(n1,"MD5",3) == 0))
+        keaStr = "RSA";
+    else
+        keaStr = "unknown";
+
+    return keaStr;
+}
+
+const char* GetCipherAuthStr(char n[][MAX_SEGMENT_SZ]) {
+
+    const char* authStr = NULL;
+    const char *n0,*n1,*n2;
+    n0 = n[0];
+    n1 = n[1];
+    n2 = n[2];
+
+    if ((XSTRNCMP(n0,"AES128",6) == 0) || (XSTRNCMP(n0,"AES256",6) == 0)  ||
+        ((XSTRNCMP(n0,"TLS13",5) == 0) && ((XSTRNCMP(n1,"AES128",6) == 0) ||
+         (XSTRNCMP(n1,"AES256",6) == 0) || (XSTRNCMP(n1,"CHACHA20",8) == 0))) ||
+        (XSTRNCMP(n0,"RSA",3) == 0) || (XSTRNCMP(n1,"RSA",3) == 0) ||
+        (XSTRNCMP(n1,"SHA",3) == 0) || (XSTRNCMP(n2,"SHA",3) == 0) ||
+        (XSTRNCMP(n1,"MD5",3) == 0))
+        authStr = "RSA";
+    else if (XSTRNCMP(n0,"PSK",3) == 0 || XSTRNCMP(n1,"PSK",3) == 0)
+        authStr = "PSK";
+    else if (XSTRNCMP(n0,"SRP",3) == 0 && XSTRNCMP(n1,"AES",3) == 0)
+        authStr = "SRP";
+    else if (XSTRNCMP(n1,"ECDSA",5) == 0)
+        authStr = "ECDSA";
+    else
+        authStr = "unknown";
+
+    return authStr;
+}
+
+const char* GetCipherEncStr(char n[][MAX_SEGMENT_SZ]) {
+    const char* encStr = NULL;
+    const char *n0,*n1,*n2,*n3;
+    n0 = n[0];
+    n1 = n[1];
+    n2 = n[2];
+    n3 = n[3];
+
+    if ((XSTRNCMP(n0,"AES256",6) == 0 && XSTRNCMP(n1,"GCM",3) == 0) ||
+        (XSTRNCMP(n1,"AES256",6) == 0 && XSTRNCMP(n2,"GCM",3) == 0) ||
+        (XSTRNCMP(n2,"AES256",6) == 0 && XSTRNCMP(n3,"GCM",3) == 0))
+        encStr = "AESGCM(256)";
+
+    else if ((XSTRNCMP(n0,"AES128",6) == 0 && XSTRNCMP(n1,"GCM",3) == 0) ||
+             (XSTRNCMP(n1,"AES128",6) == 0 && XSTRNCMP(n2,"GCM",3) == 0) ||
+             (XSTRNCMP(n2,"AES128",6) == 0 && XSTRNCMP(n3,"GCM",3) == 0))
+        encStr = "AESGCM(128)";
+
+    else if ((XSTRNCMP(n0,"AES128",6) == 0 && XSTRNCMP(n1,"CCM",3) == 0) ||
+             (XSTRNCMP(n1,"AES128",6) == 0 && XSTRNCMP(n2,"CCM",3) == 0) ||
+             (XSTRNCMP(n2,"AES128",6) == 0 && XSTRNCMP(n3,"CCM",3) == 0))
+        encStr = "AESCCM(128)";
+
+    else if ((XSTRNCMP(n0,"AES128",6) == 0) ||
+             (XSTRNCMP(n1,"AES128",6) == 0) ||
+             (XSTRNCMP(n2,"AES128",6) == 0) ||
+             (XSTRNCMP(n1,"AES",3) == 0 && XSTRNCMP(n2,"128",3) == 0) ||
+             (XSTRNCMP(n2,"AES",3) == 0 && XSTRNCMP(n3,"128",3) == 0))
+        encStr = "AES(128)";
+
+    else if ((XSTRNCMP(n0,"AES256",6) == 0) ||
+             (XSTRNCMP(n1,"AES256",6) == 0) ||
+             (XSTRNCMP(n2,"AES256",6) == 0) ||
+             (XSTRNCMP(n1,"AES",3) == 0 && XSTRNCMP(n2,"256",3) == 0) ||
+             (XSTRNCMP(n2,"AES",3) == 0 && XSTRNCMP(n3,"256",3) == 0))
+        encStr = "AES(256)";
+
+    else if ((XSTRNCMP(n0,"CAMELLIA256",11) == 0) ||
+             (XSTRNCMP(n2,"CAMELLIA256",11) == 0))
+        encStr = "CAMELLIA(256)";
+    else if ((XSTRNCMP(n0,"CAMELLIA128",11) == 0) ||
+             (XSTRNCMP(n2,"CAMELLIA128",11) == 0))
+        encStr = "CAMELLIA(128)";
+    else if ((XSTRNCMP(n0,"RC4",3) == 0) || (XSTRNCMP(n2,"RC4",3) == 0))
+        encStr = "RC4";
+    else if (((XSTRNCMP(n0,"DES",3) == 0)  || (XSTRNCMP(n2,"DES",3) == 0)) &&
+             ((XSTRNCMP(n1,"CBC3",4) == 0) || (XSTRNCMP(n3,"CBC3",4) == 0)))
+        encStr = "3DES";
+    else if ((XSTRNCMP(n1,"CHACHA20",8) == 0 && XSTRNCMP(n2,"POLY1305",8) == 0) ||
+             (XSTRNCMP(n2,"CHACHA20",8) == 0 && XSTRNCMP(n3,"POLY1305",8) == 0))
+        encStr = "CHACHA20/POLY1305(256)";
+    else if ((XSTRNCMP(n0,"NULL",4) == 0) || (XSTRNCMP(n1,"NULL",4) == 0) ||
+             (XSTRNCMP(n2,"NULL",4) == 0) ||
+             ((XSTRNCMP(n0,"TLS13",5) == 0) && (XSTRNCMP(n3,"",0) == 0)))
+        encStr = "None";
+    else if ((XSTRNCMP(n0,"IDEA",4) == 0))
+        encStr = "IDEA";
+    else if ((XSTRNCMP(n0,"RABBIT",4) == 0))
+        encStr = "RABBIT";
+    else if ((XSTRNCMP(n0,"HC128",5) == 0))
+        encStr = "HC128";
+    else
+        encStr = "unknown";
+
+    return encStr;
+}
+
+/* Returns the MAC string of a cipher or "unknown" on failure */
+const char* GetCipherMacStr(char n[][MAX_SEGMENT_SZ]) {
+
+    const char* macStr = NULL;
+    const char *n1,*n2,*n3,*n4;
+    n1 = n[1];
+    n2 = n[2];
+    n3 = n[3];
+    n4 = n[4];
+
+    if ((XSTRNCMP(n4,"SHA256",6) == 0) || (XSTRNCMP(n3,"SHA256",6) == 0) ||
+        (XSTRNCMP(n2,"SHA256",6) == 0) || (XSTRNCMP(n1,"SHA256",6) == 0))
+        macStr = "SHA256";
+    else if ((XSTRNCMP(n4,"SHA384",6) == 0) ||
+             (XSTRNCMP(n3,"SHA384",6) == 0) ||
+             (XSTRNCMP(n2,"SHA384",6) == 0) ||
+             (XSTRNCMP(n1,"SHA384",6) == 0))
+        macStr = "SHA384";
+    else if ((XSTRNCMP(n4,"SHA",3) == 0) || (XSTRNCMP(n3,"SHA",3) == 0) ||
+             (XSTRNCMP(n2,"SHA",3) == 0) || (XSTRNCMP(n1,"SHA",3) == 0) ||
+             (XSTRNCMP(n1,"MD5",3) == 0))
+        macStr = "SHA1";
+    else if ((XSTRNCMP(n3,"GCM",3) == 0) ||
+             (XSTRNCMP(n1,"CCM",3) == 0) ||
+             (XSTRNCMP(n2,"CCM",3) == 0) || (XSTRNCMP(n3,"CCM",3) == 0) ||
+             (XSTRNCMP(n1,"CHACHA20",8) == 0 && XSTRNCMP(n2,"POLY1305",8) == 0) ||
+             (XSTRNCMP(n2,"CHACHA20",8) == 0 && XSTRNCMP(n3,"POLY1305",8) == 0))
+        macStr = "AEAD";
+    else
+        macStr = "unknown";
+
+    return macStr;
+}
+
+/* Returns the number of bits based on the cipher enc string, or 0 on failure */
+int SetCipherBits(const char* enc) {
+    int ret = WOLFSSL_FAILURE;
+
+    if ((XSTRNCMP(enc,"AESGCM(256)",11) == 0) ||
+        (XSTRNCMP(enc,"AES(256)",8) == 0) ||
+        (XSTRNCMP(enc,"CAMELLIA(256)",13) == 0) ||
+        (XSTRNCMP(enc,"CHACHA20/POLY1305(256)",22) == 0))
+            ret = 256;
+    else if
+        ((XSTRNCMP(enc,"3DES",4) == 0))
+            ret = 168;
+    else if
+        ((XSTRNCMP(enc,"AESGCM(128)",11) == 0) ||
+         (XSTRNCMP(enc,"AES(128)",8) == 0) ||
+         (XSTRNCMP(enc,"CAMELLIA(128)",13) == 0) ||
+         (XSTRNCMP(enc,"IDEA",4) == 0) ||
+         (XSTRNCMP(enc,"RC4",3) == 0))
+            ret = 128;
+   else if
+        ((XSTRNCMP(enc,"DES",3) == 0))
+            ret = 56;
+
+    return ret;
+}
+#endif /* WOLFSSL_QT || OPENSSL_ALL */
+
+const char* GetCipherNameIana(const byte cipherSuite0, const byte cipherSuite)
+{
+#ifndef NO_ERROR_STRINGS
+    int i;
+    const char* nameIana = "NONE";
+
+    for (i = 0; i < GetCipherNamesSize(); i++) {
+        if ((cipher_names[i].cipherSuite0 == cipherSuite0) &&
+            (cipher_names[i].cipherSuite  == cipherSuite)) {
+            nameIana = cipher_names[i].name_iana;
+            break;
+        }
+    }
+    return nameIana;
+#else
+    (void)cipherSuite0;
+    (void)cipherSuite;
+    return NULL;
+#endif
+}
+
+const char* wolfSSL_get_cipher_name_internal(WOLFSSL* ssl)
+{
+    if (ssl == NULL) {
+        return NULL;
+    }
+
+    return GetCipherNameInternal(ssl->options.cipherSuite0, ssl->options.cipherSuite);
+}
+
+const char* wolfSSL_get_cipher_name_iana(WOLFSSL* ssl)
+{
+    if (ssl == NULL) {
+        return NULL;
+    }
+
+    return GetCipherNameIana(ssl->options.cipherSuite0, ssl->options.cipherSuite);
+}
+
+int GetCipherSuiteFromName(const char* name, byte* cipherSuite0,
+                           byte* cipherSuite)
+{
+    int           ret = BAD_FUNC_ARG;
+    int           i;
+    unsigned long len = (unsigned long)XSTRLEN(name);
+
+    for (i = 0; i < GetCipherNamesSize(); i++) {
+        if (XSTRNCMP(name, cipher_names[i].name, len) == 0) {
+            *cipherSuite0 = cipher_names[i].cipherSuite0;
+            *cipherSuite  = cipher_names[i].cipherSuite;
+            ret = 0;
+            break;
+        }
+    }
+
+    return ret;
+}
+
+/**
+Set the enabled cipher suites.
+
+@param [out] suites Suites structure.
+@param [in]  list   List of cipher suites, only supports full name from
+                    cipher_names[] delimited by ':'.
+
+@return true on success, else false.
+*/
+int SetCipherList(WOLFSSL_CTX* ctx, Suites* suites, const char* list)
+{
+    int       ret          = 0;
+    int       idx          = 0;
+    int       haveRSAsig   = 0;
+    int       haveECDSAsig = 0;
+    int       haveAnon     = 0;
+    const int suiteSz      = GetCipherNamesSize();
+    char*     next         = (char*)list;
+
+    if (suites == NULL || list == NULL) {
+        WOLFSSL_MSG("SetCipherList parameter error");
+        return 0;
+    }
+
+    if (next[0] == 0 || XSTRNCMP(next, "ALL", 3) == 0 ||
+                        XSTRNCMP(next, "DEFAULT", 7) == 0)
+        return 1; /* wolfSSL default */
+
+    do {
+        char*  current = next;
+        char   name[MAX_SUITE_NAME + 1];
+        int    i;
+        word32 length;
+
+        next   = XSTRSTR(next, ":");
+        length = min(sizeof(name), !next ? (word32)XSTRLEN(current) /* last */
+                                         : (word32)(next - current));
+
+        XSTRNCPY(name, current, length);
+        name[(length == sizeof(name)) ? length - 1 : length] = 0;
+
+        for (i = 0; i < suiteSz; i++) {
+            if (XSTRNCMP(name, cipher_names[i].name, sizeof(name)) == 0
+            #ifndef NO_ERROR_STRINGS
+                || XSTRNCMP(name, cipher_names[i].name_iana, sizeof(name)) == 0
+            #endif
+             ) {
+            #ifdef WOLFSSL_DTLS
+                /* don't allow stream ciphers with DTLS */
+                if (ctx->method->version.major == DTLS_MAJOR) {
+                    if (XSTRSTR(name, "RC4") ||
+                        XSTRSTR(name, "HC128") ||
+                        XSTRSTR(name, "RABBIT"))
+                    {
+                        WOLFSSL_MSG("Stream ciphers not supported with DTLS");
+                        continue;
+                    }
+
+                }
+            #endif /* WOLFSSL_DTLS */
+
+                if (idx + 1 >= WOLFSSL_MAX_SUITE_SZ) {
+                    WOLFSSL_MSG("WOLFSSL_MAX_SUITE_SZ set too low");
+                    return 0; /* suites buffer not large enough, error out */
+                }
+
+                suites->suites[idx++] = cipher_names[i].cipherSuite0;
+                suites->suites[idx++] = cipher_names[i].cipherSuite;
+                /* The suites are either ECDSA, RSA, PSK, or Anon. The RSA
+                 * suites don't necessarily have RSA in the name. */
+            #ifdef WOLFSSL_TLS13
+                if (cipher_names[i].cipherSuite0 == TLS13_BYTE ||
+                         (cipher_names[i].cipherSuite0 == ECC_BYTE &&
+                          (cipher_names[i].cipherSuite == TLS_SHA256_SHA256 ||
+                           cipher_names[i].cipherSuite == TLS_SHA384_SHA384))) {
+                #ifndef NO_RSA
+                    haveRSAsig = 1;
+                #endif
+                #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+                                                             defined(HAVE_ED448)
+                    haveECDSAsig = 1;
+                #endif
+                }
+                else
+            #endif
+            #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+                                                             defined(HAVE_ED448)
+                if ((haveECDSAsig == 0) && XSTRSTR(name, "ECDSA"))
+                    haveECDSAsig = 1;
+                else
+            #endif
+            #ifdef HAVE_ANON
+                if (XSTRSTR(name, "ADH"))
+                    haveAnon = 1;
+                else
+            #endif
+                if (haveRSAsig == 0
+                    #ifndef NO_PSK
+                        && (XSTRSTR(name, "PSK") == NULL)
+                    #endif
+                   ) {
+                    haveRSAsig = 1;
+                }
+
+                ret = 1; /* found at least one */
+                break;
+            }
+        }
+    }
+    while (next++); /* ++ needed to skip ':' */
+
+    if (ret) {
+        int keySz = 0;
+    #ifndef NO_CERTS
+        keySz = ctx->privateKeySz;
+    #endif
+        suites->setSuites = 1;
+        suites->suiteSz   = (word16)idx;
+        InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, haveAnon, 1,
+                              keySz);
+    }
+
+    (void)ctx;
+
+    return ret;
+}
+
+
+#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS)
+int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz)
+{
+    word32 i;
+    int ret = MATCH_SUITE_ERROR;
+
+    ssl->suites->sigAlgo = ssl->specs.sig_algo;
+
+    /* set defaults */
+    if (IsAtLeastTLSv1_3(ssl->version)) {
+        ssl->suites->hashAlgo = sha256_mac;
+    #ifndef NO_CERTS
+        ssl->suites->sigAlgo = ssl->buffers.keyType;
+    #endif
+    }
+#ifndef WOLFSSL_NO_TLS12
+    else if (IsAtLeastTLSv1_2(ssl)) {
+    #ifdef WOLFSSL_ALLOW_TLS_SHA1
+        ssl->suites->hashAlgo = sha_mac;
+    #else
+        ssl->suites->hashAlgo = sha256_mac;
+    #endif
+    }
+    else {
+        ssl->suites->hashAlgo = sha_mac;
+    }
+#endif
+
+    if (hashSigAlgoSz == 0)
+        return 0;
+
+    /* i+1 since peek a byte ahead for type */
+    for (i = 0; (i+1) < hashSigAlgoSz; i += HELLO_EXT_SIGALGO_SZ) {
+        byte hashAlgo = 0, sigAlgo = 0;
+
+        DecodeSigAlg(&hashSigAlgo[i], &hashAlgo, &sigAlgo);
+    #ifdef HAVE_ED25519
+        if (ssl->pkCurveOID == ECC_ED25519_OID) {
+            if (sigAlgo != ed25519_sa_algo)
+                continue;
+            if (sigAlgo == ed25519_sa_algo &&
+                                      ssl->suites->sigAlgo == ecc_dsa_sa_algo) {
+                ssl->suites->sigAlgo = sigAlgo;
+                ssl->suites->hashAlgo = sha512_mac;
+                ret = 0;
+                break;
+            }
+        }
+    #endif
+    #ifdef HAVE_ED448
+        if (ssl->pkCurveOID == ECC_ED448_OID) {
+            if (sigAlgo != ed448_sa_algo)
+                continue;
+
+            if (sigAlgo == ed448_sa_algo &&
+                                      ssl->suites->sigAlgo == ecc_dsa_sa_algo) {
+                ssl->suites->sigAlgo = sigAlgo;
+                ssl->suites->hashAlgo = sha512_mac;
+                ret = 0;
+                break;
+            }
+        }
+    #endif
+    #if defined(WOLFSSL_TLS13) && defined(HAVE_ECC)
+        if (IsAtLeastTLSv1_3(ssl->version) && sigAlgo == ssl->suites->sigAlgo &&
+                                                   sigAlgo == ecc_dsa_sa_algo) {
+
+            int digestSz = GetMacDigestSize(hashAlgo);
+            if (digestSz <= 0)
+                continue;
+
+            /* TLS 1.3 signature algorithms for ECDSA match hash length with
+             * key size.
+             */
+            if (digestSz != ssl->buffers.keySz)
+                continue;
+
+            ssl->suites->hashAlgo = hashAlgo;
+            ssl->suites->sigAlgo = sigAlgo;
+            ret = 0;
+            break; /* done selected sig/hash algorithms */
+        }
+        else
+    #endif
+    /* For ECDSA the `USE_ECDSA_KEYSZ_HASH_ALGO` build option will choose a hash
+     * algorithm that matches the ephemeral ECDHE key size or the next highest
+     * available. This workaround resolves issue with some peer's that do not
+     * properly support scenarios such as a P-256 key hashed with SHA512.
+     */
+    #if defined(HAVE_ECC) && defined(USE_ECDSA_KEYSZ_HASH_ALGO)
+        if (sigAlgo == ssl->suites->sigAlgo && sigAlgo == ecc_dsa_sa_algo) {
+            int digestSz = GetMacDigestSize(hashAlgo);
+            if (digestSz <= 0)
+                continue;
+
+            /* For ecc_dsa_sa_algo, pick hash algo that is curve size unless
+                algorithm in not compiled in, then choose next highest */
+            if (digestSz == ssl->eccTempKeySz) {
+                ssl->suites->hashAlgo = hashAlgo;
+                ssl->suites->sigAlgo = sigAlgo;
+            #if defined(WOLFSSL_TLS13) || defined(HAVE_FFDHE)
+                ssl->namedGroup = 0;
+            #endif
+                ret = 0;
+                break; /* done selected sig/hash algorithms */
+            }
+            /* not strong enough, so keep checking hashSigAlso list */
+            if (digestSz < ssl->eccTempKeySz)
+                continue;
+
+            /* mark as highest and check remainder of hashSigAlgo list */
+            ssl->suites->hashAlgo = hashAlgo;
+            ssl->suites->sigAlgo = sigAlgo;
+            ret = 0;
+        }
+        else
+    #endif
+    #ifdef WC_RSA_PSS
+        if (IsAtLeastTLSv1_3(ssl->version) &&
+                                          ssl->suites->sigAlgo == rsa_sa_algo &&
+                                          sigAlgo != rsa_pss_sa_algo) {
+            continue;
+        }
+        else if (sigAlgo == ssl->suites->sigAlgo ||
+                                        (sigAlgo == rsa_pss_sa_algo &&
+                                         (ssl->suites->sigAlgo == rsa_sa_algo)))
+    #else
+        if (sigAlgo == ssl->suites->sigAlgo)
+    #endif
+        {
+            /* pick highest available between both server and client */
+            switch (hashAlgo) {
+                case sha_mac:
+            #ifdef WOLFSSL_SHA224
+                case sha224_mac:
+            #endif
+            #ifndef NO_SHA256
+                case sha256_mac:
+            #endif
+            #ifdef WOLFSSL_SHA384
+                case sha384_mac:
+            #endif
+            #ifdef WOLFSSL_SHA512
+                case sha512_mac:
+            #endif
+                    /* not strong enough, so keep checking hashSigAlso list */
+                    if (hashAlgo < ssl->suites->hashAlgo) {
+                        ret = 0;
+                        continue;
+                    }
+                    /* mark as highest and check remainder of hashSigAlgo list */
+                    ssl->suites->hashAlgo = hashAlgo;
+                    ssl->suites->sigAlgo = sigAlgo;
+                    break;
+                default:
+                    continue;
+            }
+            ret = 0;
+            break;
+        }
+#if defined(WOLFSSL_TLS13)
+        else if (ssl->specs.sig_algo == 0 && IsAtLeastTLSv1_3(ssl->version)) {
+        }
+#endif
+        else if (ssl->specs.sig_algo == 0)
+        {
+            ssl->suites->hashAlgo = ssl->specs.mac_algorithm;
+            ret = 0;
+        }
+    }
+
+    return ret;
+}
+#endif /* !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) */
+
+#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+
+    /* Initialize HandShakeInfo */
+    void InitHandShakeInfo(HandShakeInfo* info, WOLFSSL* ssl)
+    {
+        int i;
+
+        info->ssl = ssl;
+        info->cipherName[0] = 0;
+        for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++)
+            info->packetNames[i][0] = 0;
+        info->numberPackets = 0;
+        info->negotiationError = 0;
+    }
+
+    /* Set Final HandShakeInfo parameters */
+    void FinishHandShakeInfo(HandShakeInfo* info)
+    {
+        int i;
+        int sz = GetCipherNamesSize();
+
+        for (i = 0; i < sz; i++)
+            if (info->ssl->options.cipherSuite ==
+                                            (byte)cipher_names[i].cipherSuite) {
+                if (info->ssl->options.cipherSuite0 == ECC_BYTE)
+                    continue;   /* ECC suites at end */
+                XSTRNCPY(info->cipherName, cipher_names[i].name, MAX_CIPHERNAME_SZ);
+                info->cipherName[MAX_CIPHERNAME_SZ] = '\0';
+                break;
+            }
+
+        /* error max and min are negative numbers */
+        if (info->ssl->error <= MIN_PARAM_ERR && info->ssl->error >= MAX_PARAM_ERR)
+            info->negotiationError = info->ssl->error;
+    }
+
+
+    /* Add name to info packet names, increase packet name count */
+    void AddPacketName(WOLFSSL* ssl, const char* name)
+    {
+    #ifdef WOLFSSL_CALLBACKS
+        HandShakeInfo* info = &ssl->handShakeInfo;
+        if (info->numberPackets < MAX_PACKETS_HANDSHAKE) {
+            char* packetName = info->packetNames[info->numberPackets];
+            XSTRNCPY(packetName, name, MAX_PACKETNAME_SZ);
+            packetName[MAX_PACKETNAME_SZ] = '\0';
+            info->numberPackets++;
+        }
+    #endif
+        (void)ssl;
+        (void)name;
+    }
+
+
+    #ifdef WOLFSSL_CALLBACKS
+    /* Initialize TimeoutInfo */
+    void InitTimeoutInfo(TimeoutInfo* info)
+    {
+        int i;
+
+        info->timeoutName[0] = 0;
+        info->flags          = 0;
+
+        for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++) {
+            info->packets[i].packetName[0]     = 0;
+            info->packets[i].timestamp.tv_sec  = 0;
+            info->packets[i].timestamp.tv_usec = 0;
+            info->packets[i].bufferValue       = 0;
+            info->packets[i].valueSz           = 0;
+        }
+        info->numberPackets        = 0;
+        info->timeoutValue.tv_sec  = 0;
+        info->timeoutValue.tv_usec = 0;
+    }
+
+
+    /* Free TimeoutInfo */
+    void FreeTimeoutInfo(TimeoutInfo* info, void* heap)
+    {
+        int i;
+        (void)heap;
+        for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++)
+            if (info->packets[i].bufferValue) {
+                XFREE(info->packets[i].bufferValue, heap, DYNAMIC_TYPE_INFO);
+                info->packets[i].bufferValue = 0;
+            }
+
+    }
+
+    /* Add packet name to previously added packet info */
+    void AddLateName(const char* name, TimeoutInfo* info)
+    {
+        /* make sure we have a valid previous one */
+        if (info->numberPackets > 0 && info->numberPackets <
+                                                        MAX_PACKETS_HANDSHAKE) {
+            char* packetName = info->packets[info->numberPackets-1].packetName;
+            XSTRNCPY(packetName, name, MAX_PACKETNAME_SZ);
+            packetName[MAX_PACKETNAME_SZ] = '\0';
+        }
+    }
+
+    /* Add record header to previously added packet info */
+    void AddLateRecordHeader(const RecordLayerHeader* rl, TimeoutInfo* info)
+    {
+        /* make sure we have a valid previous one */
+        if (info->numberPackets > 0 && info->numberPackets <
+                                                        MAX_PACKETS_HANDSHAKE) {
+            if (info->packets[info->numberPackets - 1].bufferValue)
+                XMEMCPY(info->packets[info->numberPackets - 1].bufferValue, rl,
+                       RECORD_HEADER_SZ);
+            else
+                XMEMCPY(info->packets[info->numberPackets - 1].value, rl,
+                       RECORD_HEADER_SZ);
+        }
+    }
+
+    #endif /* WOLFSSL_CALLBACKS */
+
+
+    /* Add PacketInfo to TimeoutInfo
+     *
+     * ssl   WOLFSSL structure sending or receiving packet
+     * name  name of packet being sent
+     * type  type of packet being sent
+     * data  data bing sent with packet
+     * sz    size of data buffer
+     * written 1 if this packet is being written to wire, 0 if being read
+     * heap  custom heap to use for mallocs/frees
+     */
+    void AddPacketInfo(WOLFSSL* ssl, const char* name, int type,
+            const byte* data, int sz, int written, void* heap)
+    {
+    #ifdef WOLFSSL_CALLBACKS
+        TimeoutInfo* info = &ssl->timeoutInfo;
+
+        if (info->numberPackets < (MAX_PACKETS_HANDSHAKE - 1)) {
+            WOLFSSL_TIMEVAL currTime;
+
+            /* may add name after */
+            if (name) {
+                char* packetName = info->packets[info->numberPackets].packetName;
+                XSTRNCPY(packetName, name, MAX_PACKETNAME_SZ);
+                packetName[MAX_PACKETNAME_SZ] = '\0';
+            }
+
+            /* add data, put in buffer if bigger than static buffer */
+            info->packets[info->numberPackets].valueSz = sz;
+            if (sz < MAX_VALUE_SZ)
+                XMEMCPY(info->packets[info->numberPackets].value, data, sz);
+            else {
+                info->packets[info->numberPackets].bufferValue =
+                                    (byte*)XMALLOC(sz, heap, DYNAMIC_TYPE_INFO);
+                if (!info->packets[info->numberPackets].bufferValue)
+                    /* let next alloc catch, just don't fill, not fatal here  */
+                    info->packets[info->numberPackets].valueSz = 0;
+                else
+                    XMEMCPY(info->packets[info->numberPackets].bufferValue,
+                           data, sz);
+            }
+            gettimeofday(&currTime, 0);
+            info->packets[info->numberPackets].timestamp.tv_sec  =
+                                                             currTime.tv_sec;
+            info->packets[info->numberPackets].timestamp.tv_usec =
+                                                             currTime.tv_usec;
+            info->numberPackets++;
+        }
+    #endif /* WOLFSSL_CALLBACKS */
+    #ifdef OPENSSL_EXTRA
+        if (ssl->protoMsgCb != NULL && sz > RECORD_HEADER_SZ) {
+            /* version from hex to dec  16 is 16^1, 256 from 16^2 and
+               4096 from 16^3 */
+            int version = (ssl->version.minor & 0X0F) +
+                          (ssl->version.minor & 0xF0) * 16  +
+                          (ssl->version.major & 0X0F) * 256 +
+                          (ssl->version.major & 0xF0) * 4096;
+
+            ssl->protoMsgCb(written, version, type,
+                         (const void *)(data + RECORD_HEADER_SZ),
+                         (size_t)(sz - RECORD_HEADER_SZ),
+                         ssl, ssl->protoMsgCtx);
+        }
+    #endif /* OPENSSL_EXTRA */
+        (void)written;
+        (void)name;
+        (void)heap;
+        (void)type;
+        (void)ssl;
+    }
+
+#endif /* WOLFSSL_CALLBACKS */
+
+#if !defined(NO_CERTS)
+
+/* Decode the private key - RSA/ECC/Ed25519/Ed448 - and creates a key object.
+ * The signature type is set as well.
+ * The maximum length of a signature is returned.
+ *
+ * ssl     The SSL/TLS object.
+ * length  The length of a signature.
+ * returns 0 on success, otherwise failure.
+ */
+int DecodePrivateKey(WOLFSSL *ssl, word16* length)
+{
+    int      ret = BAD_FUNC_ARG;
+    int      keySz;
+    word32   idx;
+
+#ifdef HAVE_PK_CALLBACKS
+    /* allow no private key if using PK callbacks and CB is set */
+    if (wolfSSL_IsPrivatePkSet(ssl)) {
+        *length = GetPrivateKeySigSize(ssl);
+        return 0;
+    }
+    else
+#endif
+
+    /* make sure private key exists */
+    if (ssl->buffers.key == NULL || ssl->buffers.key->buffer == NULL) {
+        WOLFSSL_MSG("Private key missing!");
+        ERROR_OUT(NO_PRIVATE_KEY, exit_dpk);
+    }
+
+#ifdef HAVE_PKCS11
+    if (ssl->buffers.keyDevId != INVALID_DEVID && ssl->buffers.keyId) {
+        if (ssl->buffers.keyType == rsa_sa_algo)
+            ssl->hsType = DYNAMIC_TYPE_RSA;
+        else if (ssl->buffers.keyType == ecc_dsa_sa_algo)
+            ssl->hsType = DYNAMIC_TYPE_ECC;
+        ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+        if (ret != 0) {
+            goto exit_dpk;
+        }
+
+        if (ssl->buffers.keyType == rsa_sa_algo) {
+    #ifndef NO_RSA
+            ret = wc_InitRsaKey_Id((RsaKey*)ssl->hsKey,
+                             ssl->buffers.key->buffer, ssl->buffers.key->length,
+                             ssl->heap, ssl->buffers.keyDevId);
+            if (ret == 0) {
+                if (ssl->buffers.keySz < ssl->options.minRsaKeySz) {
+                    WOLFSSL_MSG("RSA key size too small");
+                    ERROR_OUT(RSA_KEY_SIZE_E, exit_dpk);
+                }
+
+                /* Return the maximum signature length. */
+                *length = (word16)ssl->buffers.keySz;
+            }
+    #else
+            ret = NOT_COMPILED_IN;
+    #endif
+        }
+        else if (ssl->buffers.keyType == ecc_dsa_sa_algo) {
+    #ifdef HAVE_ECC
+            ret = wc_ecc_init_id((ecc_key*)ssl->hsKey, ssl->buffers.key->buffer,
+                                 ssl->buffers.key->length, ssl->heap,
+                                 ssl->buffers.keyDevId);
+            if (ret == 0) {
+                if (ssl->buffers.keySz < ssl->options.minEccKeySz) {
+                    WOLFSSL_MSG("ECC key size too small");
+                    ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk);
+                }
+
+                /* Return the maximum signature length. */
+                *length = (word16)wc_ecc_sig_size_calc(ssl->buffers.keySz);
+            }
+    #else
+            ret = NOT_COMPILED_IN;
+    #endif
+        }
+        goto exit_dpk;
+    }
+#endif
+
+#ifndef NO_RSA
+    if (ssl->buffers.keyType == rsa_sa_algo || ssl->buffers.keyType == 0) {
+        ssl->hsType = DYNAMIC_TYPE_RSA;
+        ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+        if (ret != 0) {
+            goto exit_dpk;
+        }
+
+        WOLFSSL_MSG("Trying RSA private key");
+
+        /* Set start of data to beginning of buffer. */
+        idx = 0;
+        /* Decode the key assuming it is an RSA private key. */
+        ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, &idx,
+                    (RsaKey*)ssl->hsKey, ssl->buffers.key->length);
+        if (ret == 0) {
+            WOLFSSL_MSG("Using RSA private key");
+
+            /* It worked so check it meets minimum key size requirements. */
+            keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsKey);
+            if (keySz < 0) { /* check if keySz has error case */
+                ERROR_OUT(keySz, exit_dpk);
+            }
+
+            if (keySz < ssl->options.minRsaKeySz) {
+                WOLFSSL_MSG("RSA key size too small");
+                ERROR_OUT(RSA_KEY_SIZE_E, exit_dpk);
+            }
+
+            /* Return the maximum signature length. */
+            *length = (word16)keySz;
+
+            goto exit_dpk;
+        }
+    }
+#endif /* !NO_RSA */
+
+#ifdef HAVE_ECC
+#ifndef NO_RSA
+    FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey);
+#endif /* !NO_RSA */
+
+    if (ssl->buffers.keyType == ecc_dsa_sa_algo || ssl->buffers.keyType == 0) {
+        ssl->hsType = DYNAMIC_TYPE_ECC;
+        ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+        if (ret != 0) {
+            goto exit_dpk;
+        }
+
+    #ifndef NO_RSA
+        WOLFSSL_MSG("Trying ECC private key, RSA didn't work");
+    #else
+        WOLFSSL_MSG("Trying ECC private key");
+    #endif
+
+        /* Set start of data to beginning of buffer. */
+        idx = 0;
+        /* Decode the key assuming it is an ECC private key. */
+        ret = wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &idx,
+                                     (ecc_key*)ssl->hsKey,
+                                     ssl->buffers.key->length);
+        if (ret == 0) {
+            WOLFSSL_MSG("Using ECC private key");
+
+            /* Check it meets the minimum ECC key size requirements. */
+            keySz = wc_ecc_size((ecc_key*)ssl->hsKey);
+            if (keySz < ssl->options.minEccKeySz) {
+                WOLFSSL_MSG("ECC key size too small");
+                ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk);
+            }
+
+            /* Return the maximum signature length. */
+            *length = (word16)wc_ecc_sig_size((ecc_key*)ssl->hsKey);
+
+            goto exit_dpk;
+        }
+    }
+#endif
+#ifdef HAVE_ED25519
+    #if !defined(NO_RSA) || defined(HAVE_ECC)
+        FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey);
+    #endif
+
+    if (ssl->buffers.keyType == ed25519_sa_algo || ssl->buffers.keyType == 0) {
+        ssl->hsType = DYNAMIC_TYPE_ED25519;
+        ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+        if (ret != 0) {
+            goto exit_dpk;
+        }
+
+        #ifdef HAVE_ECC
+            WOLFSSL_MSG("Trying ED25519 private key, ECC didn't work");
+        #elif !defined(NO_RSA)
+            WOLFSSL_MSG("Trying ED25519 private key, RSA didn't work");
+        #else
+            WOLFSSL_MSG("Trying ED25519 private key");
+        #endif
+
+        /* Set start of data to beginning of buffer. */
+        idx = 0;
+        /* Decode the key assuming it is an ED25519 private key. */
+        ret = wc_Ed25519PrivateKeyDecode(ssl->buffers.key->buffer, &idx,
+                                         (ed25519_key*)ssl->hsKey,
+                                         ssl->buffers.key->length);
+        if (ret == 0) {
+            WOLFSSL_MSG("Using ED25519 private key");
+
+            /* Check it meets the minimum ECC key size requirements. */
+            if (ED25519_KEY_SIZE < ssl->options.minEccKeySz) {
+                WOLFSSL_MSG("ED25519 key size too small");
+                ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk);
+            }
+
+            /* Return the maximum signature length. */
+            *length = ED25519_SIG_SIZE;
+
+            goto exit_dpk;
+        }
+    }
+#endif /* HAVE_ED25519 */
+#ifdef HAVE_ED448
+    #if !defined(NO_RSA) || defined(HAVE_ECC)
+        FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey);
+    #endif
+
+    if (ssl->buffers.keyType == ed448_sa_algo || ssl->buffers.keyType == 0) {
+        ssl->hsType = DYNAMIC_TYPE_ED448;
+        ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+        if (ret != 0) {
+            goto exit_dpk;
+        }
+
+        #ifdef HAVE_ED25519
+            WOLFSSL_MSG("Trying ED448 private key, ED25519 didn't work");
+        #elif defined(HAVE_ECC)
+            WOLFSSL_MSG("Trying ED448 private key, ECC didn't work");
+        #elif !defined(NO_RSA)
+            WOLFSSL_MSG("Trying ED448 private key, RSA didn't work");
+        #else
+            WOLFSSL_MSG("Trying ED447 private key");
+        #endif
+
+        /* Set start of data to beginning of buffer. */
+        idx = 0;
+        /* Decode the key assuming it is an ED448 private key. */
+        ret = wc_Ed448PrivateKeyDecode(ssl->buffers.key->buffer, &idx,
+                                       (ed448_key*)ssl->hsKey,
+                                       ssl->buffers.key->length);
+        if (ret == 0) {
+            WOLFSSL_MSG("Using ED448 private key");
+
+            /* Check it meets the minimum ECC key size requirements. */
+            if (ED448_KEY_SIZE < ssl->options.minEccKeySz) {
+                WOLFSSL_MSG("ED448 key size too small");
+                ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk);
+            }
+
+            /* Return the maximum signature length. */
+            *length = ED448_SIG_SIZE;
+
+            goto exit_dpk;
+        }
+    }
+#endif /* HAVE_ED448 */
+
+    (void)idx;
+    (void)keySz;
+    (void)length;
+exit_dpk:
+    return ret;
+}
+
+#endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */
+
+/* client only parts */
+#ifndef NO_WOLFSSL_CLIENT
+
+#ifndef WOLFSSL_NO_TLS12
+
+    /* handle generation of client_hello (1) */
+    int SendClientHello(WOLFSSL* ssl)
+    {
+        byte              *output;
+        word32             length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+        int                sendSz;
+        int                idSz = ssl->options.resuming
+                                ? ssl->session.sessionIDSz
+                                : 0;
+        int                ret;
+        word16             extSz = 0;
+
+#ifdef WOLFSSL_TLS13
+        if (IsAtLeastTLSv1_3(ssl->version))
+            return SendTls13ClientHello(ssl);
+#endif
+
+        WOLFSSL_START(WC_FUNC_CLIENT_HELLO_SEND);
+        WOLFSSL_ENTER("SendClientHello");
+
+        if (ssl->suites == NULL) {
+            WOLFSSL_MSG("Bad suites pointer in SendClientHello");
+            return SUITES_ERROR;
+        }
+
+#ifdef HAVE_SESSION_TICKET
+        if (ssl->options.resuming && ssl->session.ticketLen > 0) {
+            SessionTicket* ticket;
+
+            ticket = TLSX_SessionTicket_Create(0, ssl->session.ticket,
+                                             ssl->session.ticketLen, ssl->heap);
+            if (ticket == NULL) return MEMORY_E;
+
+            ret = TLSX_UseSessionTicket(&ssl->extensions, ticket, ssl->heap);
+            if (ret != WOLFSSL_SUCCESS) {
+                TLSX_SessionTicket_Free(ticket, ssl->heap);
+                return ret;
+            }
+
+            idSz = 0;
+        }
+#endif
+        length = VERSION_SZ + RAN_LEN
+               + idSz + ENUM_LEN
+               + ssl->suites->suiteSz + SUITE_LEN
+               + COMP_LEN + ENUM_LEN;
+
+#ifdef HAVE_TLS_EXTENSIONS
+        /* auto populate extensions supported unless user defined */
+        if ((ret = TLSX_PopulateExtensions(ssl, 0)) != 0)
+            return ret;
+    #ifdef HAVE_QSH
+        if (QSH_Init(ssl) != 0)
+            return MEMORY_E;
+    #endif
+        extSz = 0;
+        ret = TLSX_GetRequestSize(ssl, client_hello, &extSz);
+        if (ret != 0)
+            return ret;
+        length += extSz;
+#else
+        if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz)
+            extSz += HELLO_EXT_SZ + HELLO_EXT_SIGALGO_SZ
+                   + ssl->suites->hashSigAlgoSz;
+#ifdef HAVE_EXTENDED_MASTER
+        if (ssl->options.haveEMS)
+            extSz += HELLO_EXT_SZ;
+#endif
+        if (extSz != 0)
+            length += extSz + HELLO_EXT_SZ_SZ;
+#endif
+        sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+
+#ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls) {
+            length += ENUM_LEN;   /* cookie */
+            if (ssl->arrays->cookieSz != 0) length += ssl->arrays->cookieSz;
+            sendSz  = length + DTLS_HANDSHAKE_HEADER_SZ + DTLS_RECORD_HEADER_SZ;
+            idx    += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
+        }
+#endif
+
+        if (IsEncryptionOn(ssl, 1))
+            sendSz += MAX_MSG_EXTRA;
+
+        /* check for available size */
+        if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+            return ret;
+
+        /* get output buffer */
+        output = ssl->buffers.outputBuffer.buffer +
+                 ssl->buffers.outputBuffer.length;
+
+        AddHeaders(output, length, client_hello, ssl);
+
+        /* client hello, first version */
+        output[idx++] = ssl->version.major;
+        output[idx++] = ssl->version.minor;
+        ssl->chVersion = ssl->version;  /* store in case changed */
+
+        /* then random */
+        if (ssl->options.connectState == CONNECT_BEGIN) {
+            ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN);
+            if (ret != 0)
+                return ret;
+
+            /* store random */
+            XMEMCPY(ssl->arrays->clientRandom, output + idx, RAN_LEN);
+        } else {
+#ifdef WOLFSSL_DTLS
+            /* send same random on hello again */
+            XMEMCPY(output + idx, ssl->arrays->clientRandom, RAN_LEN);
+#endif
+        }
+        idx += RAN_LEN;
+
+        /* then session id */
+        output[idx++] = (byte)idSz;
+        if (idSz) {
+            XMEMCPY(output + idx, ssl->session.sessionID,
+                                                      ssl->session.sessionIDSz);
+            idx += ssl->session.sessionIDSz;
+        }
+
+        /* then DTLS cookie */
+#ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls) {
+            byte cookieSz = ssl->arrays->cookieSz;
+
+            output[idx++] = cookieSz;
+            if (cookieSz) {
+                XMEMCPY(&output[idx], ssl->arrays->cookie, cookieSz);
+                idx += cookieSz;
+            }
+        }
+#endif
+        /* then cipher suites */
+        c16toa(ssl->suites->suiteSz, output + idx);
+        idx += OPAQUE16_LEN;
+        XMEMCPY(output + idx, &ssl->suites->suites, ssl->suites->suiteSz);
+        idx += ssl->suites->suiteSz;
+
+        /* last, compression */
+        output[idx++] = COMP_LEN;
+        if (ssl->options.usingCompression)
+            output[idx++] = ZLIB_COMPRESSION;
+        else
+            output[idx++] = NO_COMPRESSION;
+
+#ifdef HAVE_TLS_EXTENSIONS
+        extSz = 0;
+        ret = TLSX_WriteRequest(ssl, output + idx, client_hello, &extSz);
+        if (ret != 0)
+            return ret;
+        idx += extSz;
+
+        (void)idx; /* suppress analyzer warning, keep idx current */
+#else
+        if (extSz != 0) {
+            c16toa(extSz, output + idx);
+            idx += HELLO_EXT_SZ_SZ;
+
+            if (IsAtLeastTLSv1_2(ssl)) {
+                if (ssl->suites->hashSigAlgoSz) {
+                    word16 i;
+                    /* extension type */
+                    c16toa(HELLO_EXT_SIG_ALGO, output + idx);
+                    idx += HELLO_EXT_TYPE_SZ;
+                    /* extension data length */
+                    c16toa(HELLO_EXT_SIGALGO_SZ + ssl->suites->hashSigAlgoSz,
+                           output + idx);
+                    idx += HELLO_EXT_SZ_SZ;
+                    /* sig algos length */
+                    c16toa(ssl->suites->hashSigAlgoSz, output + idx);
+                    idx += HELLO_EXT_SIGALGO_SZ;
+                    for (i=0; i < ssl->suites->hashSigAlgoSz; i++, idx++) {
+                        output[idx] = ssl->suites->hashSigAlgo[i];
+                    }
+                }
+            }
+#ifdef HAVE_EXTENDED_MASTER
+            if (ssl->options.haveEMS) {
+                c16toa(HELLO_EXT_EXTMS, output + idx);
+                idx += HELLO_EXT_TYPE_SZ;
+                c16toa(0, output + idx);
+                idx += HELLO_EXT_SZ_SZ;
+            }
+#endif
+        }
+#endif
+
+        if (IsEncryptionOn(ssl, 1)) {
+            byte* input;
+            int   inputSz = idx - RECORD_HEADER_SZ; /* build msg adds rec hdr */
+
+            input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+            if (input == NULL)
+                return MEMORY_E;
+
+            XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
+            sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
+                                  handshake, 1, 0, 0);
+            XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+
+            if (sendSz < 0)
+                return sendSz;
+        } else {
+            #ifdef WOLFSSL_DTLS
+                if (IsDtlsNotSctpMode(ssl)) {
+                    if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
+                        return ret;
+                }
+                if (ssl->options.dtls)
+                    DtlsSEQIncrement(ssl, CUR_ORDER);
+            #endif
+            ret = HashOutput(ssl, output, sendSz, 0);
+            if (ret != 0)
+                return ret;
+        }
+
+        ssl->options.clientState = CLIENT_HELLO_COMPLETE;
+#ifdef OPENSSL_EXTRA
+        ssl->cbmode = SSL_CB_MODE_WRITE;
+        if (ssl->CBIS != NULL)
+            ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, SSL_SUCCESS);
+#endif
+
+#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+        if (ssl->hsInfoOn) AddPacketName(ssl, "ClientHello");
+        if (ssl->toInfoOn)
+            AddPacketInfo(ssl, "ClientHello", handshake, output, sendSz,
+                          WRITE_PROTO, ssl->heap);
+#endif
+
+        ssl->buffers.outputBuffer.length += sendSz;
+
+        ret = SendBuffered(ssl);
+
+        WOLFSSL_LEAVE("SendClientHello", ret);
+        WOLFSSL_END(WC_FUNC_CLIENT_HELLO_SEND);
+
+        return ret;
+    }
+
+
+    /* handle processing of DTLS hello_verify_request (3) */
+    static int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input,
+                                    word32* inOutIdx, word32 size)
+    {
+        ProtocolVersion pv;
+        byte            cookieSz;
+        word32          begin = *inOutIdx;
+
+#ifdef WOLFSSL_CALLBACKS
+        if (ssl->hsInfoOn) AddPacketName(ssl, "HelloVerifyRequest");
+        if (ssl->toInfoOn) AddLateName("HelloVerifyRequest", &ssl->timeoutInfo);
+#endif
+
+#ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls) {
+            DtlsMsgPoolReset(ssl);
+        }
+#endif
+
+        if (OPAQUE16_LEN + OPAQUE8_LEN > size)
+            return BUFFER_ERROR;
+
+        XMEMCPY(&pv, input + *inOutIdx, OPAQUE16_LEN);
+        *inOutIdx += OPAQUE16_LEN;
+
+        if (pv.major != DTLS_MAJOR ||
+                         (pv.minor != DTLS_MINOR && pv.minor != DTLSv1_2_MINOR))
+            return VERSION_ERROR;
+
+        cookieSz = input[(*inOutIdx)++];
+
+        if (cookieSz) {
+            if ((*inOutIdx - begin) + cookieSz > size)
+                return BUFFER_ERROR;
+
+#ifdef WOLFSSL_DTLS
+            if (cookieSz <= MAX_COOKIE_LEN) {
+                XMEMCPY(ssl->arrays->cookie, input + *inOutIdx, cookieSz);
+                ssl->arrays->cookieSz = cookieSz;
+            }
+#endif
+            *inOutIdx += cookieSz;
+        }
+
+        ssl->options.serverState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
+        return 0;
+    }
+
+
+    static WC_INLINE int DSH_CheckSessionId(WOLFSSL* ssl)
+    {
+        int ret = 0;
+
+#ifdef HAVE_SECRET_CALLBACK
+        /* If a session secret callback exists, we are using that
+         * key instead of the saved session key. */
+        ret = ret || (ssl->sessionSecretCb != NULL);
+#endif
+
+#ifdef HAVE_SESSION_TICKET
+        /* server may send blank ticket which may not be expected to indicate
+         * existing one ok but will also be sending a new one */
+        ret = ret || (ssl->session.ticketLen > 0);
+#endif
+
+        ret = ret ||
+              (ssl->options.haveSessionId && XMEMCMP(ssl->arrays->sessionID,
+                                          ssl->session.sessionID, ID_LEN) == 0);
+
+        return ret;
+    }
+
+    /* Check the version in the received message is valid and set protocol
+     * version to use.
+     *
+     * ssl  The SSL/TLS object.
+     * pv   The protocol version from the packet.
+     * returns 0 on success, otherwise failure.
+     */
+    int CheckVersion(WOLFSSL *ssl, ProtocolVersion pv)
+    {
+    #ifdef WOLFSSL_TLS13_DRAFT
+        if (pv.major == TLS_DRAFT_MAJOR) {
+            pv.major = SSLv3_MAJOR;
+            pv.minor = TLSv1_3_MINOR;
+        }
+    #endif
+
+        #ifdef OPENSSL_EXTRA
+        if (ssl->CBIS != NULL) {
+            ssl->CBIS(ssl, SSL_CB_HANDSHAKE_START, SSL_SUCCESS);
+        }
+        #endif
+
+        if (pv.minor > ssl->version.minor) {
+            WOLFSSL_MSG("Server using higher version, fatal error");
+            return VERSION_ERROR;
+        }
+        if (pv.minor < ssl->version.minor) {
+            WOLFSSL_MSG("server using lower version");
+
+            /* Check for downgrade attack. */
+            if (!ssl->options.downgrade) {
+                WOLFSSL_MSG("\tno downgrade allowed, fatal error");
+                return VERSION_ERROR;
+            }
+            if (pv.minor < ssl->options.minDowngrade) {
+                WOLFSSL_MSG("\tversion below minimum allowed, fatal error");
+                return VERSION_ERROR;
+            }
+
+            #ifdef HAVE_SECURE_RENEGOTIATION
+                if (ssl->secure_renegotiation &&
+                                         ssl->secure_renegotiation->enabled &&
+                                         ssl->options.handShakeDone) {
+                    WOLFSSL_MSG("Server changed version during scr");
+                    return VERSION_ERROR;
+                }
+            #endif
+
+            /* Checks made - OK to downgrade. */
+            if (pv.minor == SSLv3_MINOR) {
+                /* turn off tls */
+                WOLFSSL_MSG("\tdowngrading to SSLv3");
+                ssl->options.tls    = 0;
+                ssl->options.tls1_1 = 0;
+                ssl->version.minor  = SSLv3_MINOR;
+            }
+            else if (pv.minor == TLSv1_MINOR) {
+                /* turn off tls 1.1+ */
+                WOLFSSL_MSG("\tdowngrading to TLSv1");
+                ssl->options.tls1_1 = 0;
+                ssl->version.minor  = TLSv1_MINOR;
+            }
+            else if (pv.minor == TLSv1_1_MINOR) {
+                WOLFSSL_MSG("\tdowngrading to TLSv1.1");
+                ssl->version.minor  = TLSv1_1_MINOR;
+            }
+            else if (pv.minor == TLSv1_2_MINOR) {
+                WOLFSSL_MSG("    downgrading to TLSv1.2");
+                ssl->version.minor  = TLSv1_2_MINOR;
+            }
+        }
+
+#ifdef OPENSSL_EXTRA
+        /* check if option is set to not allow the current version
+         * set from either wolfSSL_set_options or wolfSSL_CTX_set_options */
+        if (!ssl->options.dtls && ssl->options.downgrade &&
+                ssl->options.mask > 0) {
+            if (ssl->version.minor == TLSv1_2_MINOR &&
+             (ssl->options.mask & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) {
+                WOLFSSL_MSG("\tOption set to not allow TLSv1.2, Downgrading");
+                ssl->version.minor = TLSv1_1_MINOR;
+            }
+            if (ssl->version.minor == TLSv1_1_MINOR &&
+             (ssl->options.mask & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) {
+                WOLFSSL_MSG("\tOption set to not allow TLSv1.1, Downgrading");
+                ssl->options.tls1_1 = 0;
+                ssl->version.minor = TLSv1_MINOR;
+            }
+            if (ssl->version.minor == TLSv1_MINOR &&
+                (ssl->options.mask & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) {
+                WOLFSSL_MSG("\tOption set to not allow TLSv1, Downgrading");
+                ssl->options.tls    = 0;
+                ssl->options.tls1_1 = 0;
+                ssl->version.minor = SSLv3_MINOR;
+            }
+            if (ssl->version.minor == SSLv3_MINOR &&
+                (ssl->options.mask & SSL_OP_NO_SSLv3) == SSL_OP_NO_SSLv3) {
+                WOLFSSL_MSG("\tError, option set to not allow SSLv3");
+                return VERSION_ERROR;
+            }
+
+            if (ssl->version.minor < ssl->options.minDowngrade) {
+                WOLFSSL_MSG("\tversion below minimum allowed, fatal error");
+                return VERSION_ERROR;
+            }
+        }
+#endif
+
+        return 0;
+    }
+
+    /* handle processing of server_hello (2) */
+    int DoServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                      word32 helloSz)
+    {
+        byte            cs0;   /* cipher suite bytes 0, 1 */
+        byte            cs1;
+        ProtocolVersion pv;
+        byte            compression;
+        word32          i = *inOutIdx;
+        word32          begin = i;
+        int             ret;
+
+        WOLFSSL_START(WC_FUNC_SERVER_HELLO_DO);
+        WOLFSSL_ENTER("DoServerHello");
+
+#ifdef WOLFSSL_CALLBACKS
+        if (ssl->hsInfoOn) AddPacketName(ssl, "ServerHello");
+        if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo);
+#endif
+
+        /* protocol version, random and session id length check */
+        if (OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz)
+            return BUFFER_ERROR;
+
+        /* protocol version */
+        XMEMCPY(&pv, input + i, OPAQUE16_LEN);
+        i += OPAQUE16_LEN;
+
+        ret = CheckVersion(ssl, pv);
+        if (ret != 0)
+            return ret;
+
+#ifdef WOLFSSL_TLS13
+        if (IsAtLeastTLSv1_3(pv)) {
+            byte type = server_hello;
+            return DoTls13ServerHello(ssl, input, inOutIdx, helloSz, &type);
+        }
+#endif
+
+        /* random */
+        XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN);
+        i += RAN_LEN;
+
+        /* session id */
+        ssl->arrays->sessionIDSz = input[i++];
+
+        if (ssl->arrays->sessionIDSz > ID_LEN) {
+            WOLFSSL_MSG("Invalid session ID size");
+            ssl->arrays->sessionIDSz = 0;
+            return BUFFER_ERROR;
+        }
+        else if (ssl->arrays->sessionIDSz) {
+            if ((i - begin) + ssl->arrays->sessionIDSz > helloSz)
+                return BUFFER_ERROR;
+
+            XMEMCPY(ssl->arrays->sessionID, input + i,
+                                                      ssl->arrays->sessionIDSz);
+            i += ssl->arrays->sessionIDSz;
+            ssl->options.haveSessionId = 1;
+        }
+
+
+        /* suite and compression */
+        if ((i - begin) + OPAQUE16_LEN + OPAQUE8_LEN > helloSz)
+            return BUFFER_ERROR;
+
+        cs0 = input[i++];
+        cs1 = input[i++];
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+        if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled &&
+                                         ssl->options.handShakeDone) {
+            if (ssl->options.cipherSuite0 != cs0 ||
+                ssl->options.cipherSuite  != cs1) {
+                WOLFSSL_MSG("Server changed cipher suite during scr");
+                return MATCH_SUITE_ERROR;
+            }
+        }
+#endif
+
+        ssl->options.cipherSuite0 = cs0;
+        ssl->options.cipherSuite  = cs1;
+        compression = input[i++];
+
+#ifndef WOLFSSL_NO_STRICT_CIPHER_SUITE
+        {
+            word32 idx, found = 0;
+            /* confirm server_hello cipher suite is one sent in client_hello */
+            for (idx = 0; idx < ssl->suites->suiteSz; idx += 2) {
+                if (ssl->suites->suites[idx]   == cs0 &&
+                    ssl->suites->suites[idx+1] == cs1) {
+                    found = 1;
+                    break;
+                }
+            }
+            if (!found) {
+                WOLFSSL_MSG("ServerHello did not use cipher suite from ClientHello");
+                return MATCH_SUITE_ERROR;
+            }
+        }
+#endif /* !WOLFSSL_NO_STRICT_CIPHER_SUITE */
+
+        if (compression != NO_COMPRESSION && !ssl->options.usingCompression) {
+            WOLFSSL_MSG("Server forcing compression w/o support");
+            return COMPRESSION_ERROR;
+        }
+
+        if (compression != ZLIB_COMPRESSION && ssl->options.usingCompression) {
+            WOLFSSL_MSG("Server refused compression, turning off");
+            ssl->options.usingCompression = 0;  /* turn off if server refused */
+        }
+
+        *inOutIdx = i;
+
+#ifdef HAVE_TLS_EXTENSIONS
+        if ( (i - begin) < helloSz) {
+            if (TLSX_SupportExtensions(ssl)) {
+                word16 totalExtSz;
+
+                if ((i - begin) + OPAQUE16_LEN > helloSz)
+                    return BUFFER_ERROR;
+
+                ato16(&input[i], &totalExtSz);
+                i += OPAQUE16_LEN;
+
+                if ((i - begin) + totalExtSz > helloSz)
+                    return BUFFER_ERROR;
+
+                if ((ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz,
+                                                           server_hello, NULL)))
+                    return ret;
+
+                i += totalExtSz;
+                *inOutIdx = i;
+            }
+            else
+                *inOutIdx = begin + helloSz; /* skip extensions */
+        }
+        else
+            ssl->options.haveEMS = 0; /* If no extensions, no EMS */
+#else
+        {
+            int allowExt = 0;
+            byte pendingEMS = 0;
+
+            if ( (i - begin) < helloSz) {
+                if (ssl->version.major == SSLv3_MAJOR &&
+                    ssl->version.minor >= TLSv1_MINOR) {
+
+                    allowExt = 1;
+                }
+#ifdef WOLFSSL_DTLS
+                if (ssl->version.major == DTLS_MAJOR)
+                    allowExt = 1;
+#endif
+
+                if (allowExt) {
+                    word16 totalExtSz;
+
+                    if ((i - begin) + OPAQUE16_LEN > helloSz)
+                        return BUFFER_ERROR;
+
+                    ato16(&input[i], &totalExtSz);
+                    i += OPAQUE16_LEN;
+
+                    if ((i - begin) + totalExtSz > helloSz)
+                        return BUFFER_ERROR;
+
+                    while (totalExtSz) {
+                        word16 extId, extSz;
+
+                        if (OPAQUE16_LEN + OPAQUE16_LEN > totalExtSz)
+                            return BUFFER_ERROR;
+
+                        ato16(&input[i], &extId);
+                        i += OPAQUE16_LEN;
+                        ato16(&input[i], &extSz);
+                        i += OPAQUE16_LEN;
+
+                        if (OPAQUE16_LEN + OPAQUE16_LEN + extSz > totalExtSz)
+                            return BUFFER_ERROR;
+
+                        if (extId == HELLO_EXT_EXTMS)
+                            pendingEMS = 1;
+                        else
+                            i += extSz;
+
+                        totalExtSz -= OPAQUE16_LEN + OPAQUE16_LEN + extSz;
+                    }
+
+                    *inOutIdx = i;
+                }
+                else
+                    *inOutIdx = begin + helloSz; /* skip extensions */
+            }
+
+            if (!pendingEMS && ssl->options.haveEMS)
+                ssl->options.haveEMS = 0;
+        }
+#endif
+
+        ssl->options.serverState = SERVER_HELLO_COMPLETE;
+
+        if (IsEncryptionOn(ssl, 0)) {
+            *inOutIdx += ssl->keys.padSz;
+        #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+            if (ssl->options.startedETMWrite &&
+                                              ssl->specs.cipher_type == block) {
+                *inOutIdx += MacSize(ssl);
+            }
+        #endif
+        }
+
+#ifdef HAVE_SECRET_CALLBACK
+        if (ssl->sessionSecretCb != NULL) {
+            int secretSz = SECRET_LEN;
+            ret = ssl->sessionSecretCb(ssl, ssl->session.masterSecret,
+                                              &secretSz, ssl->sessionSecretCtx);
+            if (ret != 0 || secretSz != SECRET_LEN)
+                return SESSION_SECRET_CB_E;
+        }
+#endif /* HAVE_SECRET_CALLBACK */
+
+        ret = CompleteServerHello(ssl);
+
+        WOLFSSL_LEAVE("DoServerHello", ret);
+        WOLFSSL_END(WC_FUNC_SERVER_HELLO_DO);
+
+        return ret;
+    }
+
+#ifdef WOLFSSL_TLS13
+    /* returns 1 if able to do TLS 1.3 otherwise 0 */
+    static int TLSv1_3_Capable(WOLFSSL* ssl)
+    {
+    #ifndef WOLFSSL_TLS13
+        return 0;
+    #else
+        int ret = 0;
+
+        if (IsAtLeastTLSv1_3(ssl->ctx->method->version)) {
+            ret = 1;
+        }
+
+        #ifdef OPENSSL_EXTRA
+        if ((wolfSSL_get_options(ssl) & SSL_OP_NO_TLSv1_3)) {
+            /* option set at run time to disable TLS 1.3 */
+            ret = 0;
+        }
+        #endif
+        return ret;
+    #endif
+    }
+#endif /* WOLFSSL_TLS13 */
+
+    int CompleteServerHello(WOLFSSL* ssl)
+    {
+        int ret;
+
+        if (!ssl->options.resuming) {
+            byte* down = ssl->arrays->serverRandom + RAN_LEN -
+                                                         TLS13_DOWNGRADE_SZ - 1;
+            byte  vers = ssl->arrays->serverRandom[RAN_LEN - 1];
+    #ifdef WOLFSSL_TLS13
+            if (TLSv1_3_Capable(ssl)) {
+                /* TLS v1.3 capable client not allowed to downgrade when
+                 * connecting to TLS v1.3 capable server unless cipher suite
+                 * demands it.
+                 */
+                if (XMEMCMP(down, tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 &&
+                                                     (vers == 0 || vers == 1)) {
+                    SendAlert(ssl, alert_fatal, illegal_parameter);
+                    return VERSION_ERROR;
+                }
+            }
+            else
+    #endif
+            if (ssl->ctx->method->version.major == SSLv3_MAJOR &&
+                             ssl->ctx->method->version.minor == TLSv1_2_MINOR) {
+                /* TLS v1.2 capable client not allowed to downgrade when
+                 * connecting to TLS v1.2 capable server.
+                 */
+                if (XMEMCMP(down, tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 &&
+                                                                    vers == 0) {
+                    SendAlert(ssl, alert_fatal, illegal_parameter);
+                    return VERSION_ERROR;
+                }
+            }
+        }
+        else {
+            if (DSH_CheckSessionId(ssl)) {
+                if (SetCipherSpecs(ssl) == 0) {
+
+                    XMEMCPY(ssl->arrays->masterSecret,
+                            ssl->session.masterSecret, SECRET_LEN);
+            #ifdef NO_OLD_TLS
+                    ret = DeriveTlsKeys(ssl);
+            #else
+                    ret = -1; /* default value */
+                #ifndef NO_TLS
+                    if (ssl->options.tls)
+                        ret = DeriveTlsKeys(ssl);
+                #endif
+                    if (!ssl->options.tls)
+                        ret = DeriveKeys(ssl);
+            #endif /* NO_OLD_TLS */
+                    ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
+
+                    return ret;
+                }
+                else {
+                    WOLFSSL_MSG("Unsupported cipher suite, DoServerHello");
+                    return UNSUPPORTED_SUITE;
+                }
+            }
+            else {
+                WOLFSSL_MSG("Server denied resumption attempt");
+                ssl->options.resuming = 0; /* server denied resumption try */
+            }
+        }
+    #ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls) {
+            DtlsMsgPoolReset(ssl);
+        }
+    #endif
+
+        return SetCipherSpecs(ssl);
+    }
+
+#endif /* WOLFSSL_NO_TLS12 */
+
+
+    /* Make sure client setup is valid for this suite, true on success */
+    int VerifyClientSuite(WOLFSSL* ssl)
+    {
+        int  havePSK = 0;
+        byte first   = ssl->options.cipherSuite0;
+        byte second  = ssl->options.cipherSuite;
+
+        WOLFSSL_ENTER("VerifyClientSuite");
+
+        #ifndef NO_PSK
+            havePSK = ssl->options.havePSK;
+        #endif
+
+        if (CipherRequires(first, second, REQUIRES_PSK)) {
+            WOLFSSL_MSG("Requires PSK");
+            if (havePSK == 0) {
+                WOLFSSL_MSG("Don't have PSK");
+                return 0;
+            }
+        }
+
+        return 1;  /* success */
+    }
+
+#ifndef WOLFSSL_NO_TLS12
+
+#ifndef NO_CERTS
+    /* handle processing of certificate_request (13) */
+    static int DoCertificateRequest(WOLFSSL* ssl, const byte* input, word32*
+                                    inOutIdx, word32 size)
+    {
+        word16 len;
+        word32 begin = *inOutIdx;
+    #ifdef OPENSSL_EXTRA
+        int ret;
+        WOLFSSL_X509* x509 = NULL;
+        WOLFSSL_EVP_PKEY* pkey = NULL;
+    #endif
+
+        WOLFSSL_START(WC_FUNC_CERTIFICATE_REQUEST_DO);
+        WOLFSSL_ENTER("DoCertificateRequest");
+
+        #ifdef WOLFSSL_CALLBACKS
+            if (ssl->hsInfoOn)
+                AddPacketName(ssl, "CertificateRequest");
+            if (ssl->toInfoOn)
+                AddLateName("CertificateRequest", &ssl->timeoutInfo);
+        #endif
+
+        if (OPAQUE8_LEN > size)
+            return BUFFER_ERROR;
+
+        len = input[(*inOutIdx)++];
+
+        if ((*inOutIdx - begin) + len > size)
+            return BUFFER_ERROR;
+
+        /* types, read in here */
+        *inOutIdx += len;
+
+        /* signature and hash signature algorithm */
+        if (IsAtLeastTLSv1_2(ssl)) {
+            if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
+                return BUFFER_ERROR;
+
+            ato16(input + *inOutIdx, &len);
+            *inOutIdx += OPAQUE16_LEN;
+
+            if ((*inOutIdx - begin) + len > size)
+                return BUFFER_ERROR;
+
+            if (PickHashSigAlgo(ssl, input + *inOutIdx, len) != 0 &&
+                                             ssl->buffers.certificate &&
+                                             ssl->buffers.certificate->buffer) {
+            #ifdef HAVE_PK_CALLBACKS
+                if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) {
+                    WOLFSSL_MSG("Using PK for client private key");
+                    return INVALID_PARAMETER;
+                }
+            #endif
+                if (ssl->buffers.key && ssl->buffers.key->buffer) {
+                    return INVALID_PARAMETER;
+                }
+            }
+            *inOutIdx += len;
+    #ifdef WC_RSA_PSS
+            ssl->pssAlgo = 0;
+            if (ssl->suites->sigAlgo == rsa_pss_sa_algo)
+                ssl->pssAlgo |= 1 << ssl->suites->hashAlgo;
+    #endif
+        }
+
+        /* authorities */
+        if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
+            return BUFFER_ERROR;
+
+        ato16(input + *inOutIdx, &len);
+        *inOutIdx += OPAQUE16_LEN;
+
+        if ((*inOutIdx - begin) + len > size)
+            return BUFFER_ERROR;
+
+        while (len) {
+            word16 dnSz;
+
+            if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
+                return BUFFER_ERROR;
+
+            ato16(input + *inOutIdx, &dnSz);
+            *inOutIdx += OPAQUE16_LEN;
+
+            if ((*inOutIdx - begin) + dnSz > size)
+                return BUFFER_ERROR;
+
+            *inOutIdx += dnSz;
+            len -= OPAQUE16_LEN + dnSz;
+        }
+
+    #ifdef OPENSSL_EXTRA
+        /* call client cert callback if no cert has been loaded */
+        if ((ssl->ctx->CBClientCert != NULL) &&
+            (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer)) {
+
+            ret = ssl->ctx->CBClientCert(ssl, &x509, &pkey);
+            if (ret == 1) {
+                if ((wolfSSL_use_certificate(ssl, x509) != WOLFSSL_SUCCESS) ||
+                    (wolfSSL_use_PrivateKey(ssl, pkey) != WOLFSSL_SUCCESS)) {
+                    return CLIENT_CERT_CB_ERROR;
+                }
+                wolfSSL_X509_free(x509);
+                wolfSSL_EVP_PKEY_free(pkey);
+
+            } else if (ret < 0) {
+                return WOLFSSL_ERROR_WANT_X509_LOOKUP;
+            }
+        }
+    #endif
+
+        /* don't send client cert or cert verify if user hasn't provided
+           cert and private key */
+        if (ssl->buffers.certificate && ssl->buffers.certificate->buffer) {
+        #ifdef HAVE_PK_CALLBACKS
+            if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) {
+                WOLFSSL_MSG("Using PK for client private key");
+                ssl->options.sendVerify = SEND_CERT;
+            }
+        #endif
+            if (ssl->buffers.key && ssl->buffers.key->buffer) {
+                ssl->options.sendVerify = SEND_CERT;
+            }
+        }
+    #ifdef OPENSSL_EXTRA
+        else
+    #else
+        else if (IsTLS(ssl))
+    #endif
+        {
+            ssl->options.sendVerify = SEND_BLANK_CERT;
+        }
+
+        if (IsEncryptionOn(ssl, 0)) {
+            *inOutIdx += ssl->keys.padSz;
+        #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+            if (ssl->options.startedETMRead)
+                *inOutIdx += MacSize(ssl);
+        #endif
+        }
+
+        WOLFSSL_LEAVE("DoCertificateRequest", 0);
+        WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_DO);
+
+        return 0;
+    }
+#endif /* !NO_CERTS */
+
+
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
+
+    static int CheckCurveId(int tlsCurveId)
+    {
+        int ret = ECC_CURVE_ERROR;
+
+        switch (tlsCurveId) {
+    #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case WOLFSSL_ECC_SECP160R1: return ECC_SECP160R1_OID;
+        #endif /* !NO_ECC_SECP */
+        #ifdef HAVE_ECC_SECPR2
+            case WOLFSSL_ECC_SECP160R2: return ECC_SECP160R2_OID;
+        #endif /* HAVE_ECC_SECPR2 */
+        #ifdef HAVE_ECC_KOBLITZ
+            case WOLFSSL_ECC_SECP160K1: return ECC_SECP160K1_OID;
+        #endif /* HAVE_ECC_KOBLITZ */
+    #endif
+    #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case WOLFSSL_ECC_SECP192R1: return ECC_SECP192R1_OID;
+        #endif /* !NO_ECC_SECP */
+        #ifdef HAVE_ECC_KOBLITZ
+            case WOLFSSL_ECC_SECP192K1: return ECC_SECP192K1_OID;
+        #endif /* HAVE_ECC_KOBLITZ */
+    #endif
+    #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case WOLFSSL_ECC_SECP224R1: return ECC_SECP224R1_OID;
+        #endif /* !NO_ECC_SECP */
+        #ifdef HAVE_ECC_KOBLITZ
+            case WOLFSSL_ECC_SECP224K1: return ECC_SECP224K1_OID;
+        #endif /* HAVE_ECC_KOBLITZ */
+    #endif
+        #ifdef HAVE_CURVE25519
+            case WOLFSSL_ECC_X25519: return ECC_X25519_OID;
+        #endif
+    #if !defined(NO_ECC256)  || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case WOLFSSL_ECC_SECP256R1: return ECC_SECP256R1_OID;
+        #endif /* !NO_ECC_SECP */
+        #ifdef HAVE_ECC_KOBLITZ
+            case WOLFSSL_ECC_SECP256K1: return ECC_SECP256K1_OID;
+        #endif /* HAVE_ECC_KOBLITZ */
+        #ifdef HAVE_ECC_BRAINPOOL
+            case WOLFSSL_ECC_BRAINPOOLP256R1: return ECC_BRAINPOOLP256R1_OID;
+        #endif /* HAVE_ECC_BRAINPOOL */
+    #endif
+        #ifdef HAVE_CURVE448
+            case WOLFSSL_ECC_X448: return ECC_X448_OID;
+        #endif
+    #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case WOLFSSL_ECC_SECP384R1: return ECC_SECP384R1_OID;
+        #endif /* !NO_ECC_SECP */
+        #ifdef HAVE_ECC_BRAINPOOL
+            case WOLFSSL_ECC_BRAINPOOLP384R1: return ECC_BRAINPOOLP384R1_OID;
+        #endif /* HAVE_ECC_BRAINPOOL */
+    #endif
+    #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)
+        #ifdef HAVE_ECC_BRAINPOOL
+            case WOLFSSL_ECC_BRAINPOOLP512R1: return ECC_BRAINPOOLP512R1_OID;
+        #endif /* HAVE_ECC_BRAINPOOL */
+    #endif
+    #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case WOLFSSL_ECC_SECP521R1: return ECC_SECP521R1_OID;
+        #endif /* !NO_ECC_SECP */
+    #endif
+        }
+
+        return ret;
+    }
+
+#endif /* HAVE_ECC */
+
+/* Persistable DoServerKeyExchange arguments */
+typedef struct DskeArgs {
+    byte*  output; /* not allocated */
+#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+                                                             defined(HAVE_ED448)
+    byte*  verifySig;
+#endif
+    word32 idx;
+    word32 begin;
+#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+                                                             defined(HAVE_ED448)
+    word16 verifySigSz;
+#endif
+    word16 sigSz;
+    byte   sigAlgo;
+    byte   hashAlgo;
+#if !defined(NO_RSA) && defined(WC_RSA_PSS)
+    int    bits;
+#endif
+} DskeArgs;
+
+static void FreeDskeArgs(WOLFSSL* ssl, void* pArgs)
+{
+    DskeArgs* args = (DskeArgs*)pArgs;
+
+    (void)ssl;
+    (void)args;
+
+#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+                                                             defined(HAVE_ED448)
+    if (args->verifySig) {
+        XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+        args->verifySig = NULL;
+    }
+#endif
+}
+
+#ifndef NO_DH
+static int GetDhPublicKey(WOLFSSL* ssl, const byte* input, word32 size,
+                          DskeArgs* args)
+{
+    int             ret = 0;
+    word16          length;
+#ifdef HAVE_FFDHE
+    const DhParams* params = NULL;
+    int             group = 0;
+#endif
+
+    ssl->buffers.weOwnDH = 1;
+
+    ssl->buffers.serverDH_P.buffer = NULL;
+    ssl->buffers.serverDH_G.buffer = NULL;
+    ssl->buffers.serverDH_Pub.buffer = NULL;
+
+    /* p */
+    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+        ERROR_OUT(BUFFER_ERROR, exit_gdpk);
+    }
+
+    ato16(input + args->idx, &length);
+    args->idx += OPAQUE16_LEN;
+
+    if ((args->idx - args->begin) + length > size) {
+        ERROR_OUT(BUFFER_ERROR, exit_gdpk);
+    }
+
+    if (length < ssl->options.minDhKeySz) {
+        WOLFSSL_MSG("Server using a DH key that is too small");
+        SendAlert(ssl, alert_fatal, handshake_failure);
+        ERROR_OUT(DH_KEY_SIZE_E, exit_gdpk);
+    }
+    if (length > ssl->options.maxDhKeySz) {
+        WOLFSSL_MSG("Server using a DH key that is too big");
+        SendAlert(ssl, alert_fatal, handshake_failure);
+        ERROR_OUT(DH_KEY_SIZE_E, exit_gdpk);
+    }
+
+    ssl->buffers.serverDH_P.buffer =
+        (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    if (ssl->buffers.serverDH_P.buffer) {
+        ssl->buffers.serverDH_P.length = length;
+    }
+    else {
+        ERROR_OUT(MEMORY_ERROR, exit_gdpk);
+    }
+
+    XMEMCPY(ssl->buffers.serverDH_P.buffer, input + args->idx,
+                                                        length);
+    args->idx += length;
+
+    ssl->options.dhKeySz = length;
+
+    /* g */
+    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+        ERROR_OUT(BUFFER_ERROR, exit_gdpk);
+    }
+
+    ato16(input + args->idx, &length);
+    args->idx += OPAQUE16_LEN;
+
+    if ((args->idx - args->begin) + length > size) {
+        ERROR_OUT(BUFFER_ERROR, exit_gdpk);
+    }
+
+    ssl->buffers.serverDH_G.buffer =
+        (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    if (ssl->buffers.serverDH_G.buffer) {
+        ssl->buffers.serverDH_G.length = length;
+    }
+    else {
+        ERROR_OUT(MEMORY_ERROR, exit_gdpk);
+    }
+
+    XMEMCPY(ssl->buffers.serverDH_G.buffer, input + args->idx,
+                                                        length);
+    args->idx += length;
+
+    /* pub */
+    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+        ERROR_OUT(BUFFER_ERROR, exit_gdpk);
+    }
+
+    ato16(input + args->idx, &length);
+    args->idx += OPAQUE16_LEN;
+
+    if ((args->idx - args->begin) + length > size) {
+        ERROR_OUT(BUFFER_ERROR, exit_gdpk);
+    }
+
+    ssl->buffers.serverDH_Pub.buffer =
+        (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    if (ssl->buffers.serverDH_Pub.buffer) {
+        ssl->buffers.serverDH_Pub.length = length;
+    }
+    else {
+        ERROR_OUT(MEMORY_ERROR, exit_gdpk);
+    }
+
+    XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + args->idx,
+                                                        length);
+    args->idx += length;
+
+#ifdef HAVE_FFDHE
+    switch (ssl->options.dhKeySz) {
+    #ifdef HAVE_FFDHE_2048
+        case 2048/8:
+            params = wc_Dh_ffdhe2048_Get();
+            group = WOLFSSL_FFDHE_2048;
+            break;
+    #endif
+    #ifdef HAVE_FFDHE_3072
+        case 3072/8:
+            params = wc_Dh_ffdhe3072_Get();
+            group = WOLFSSL_FFDHE_3072;
+            break;
+    #endif
+    #ifdef HAVE_FFDHE_4096
+        case 4096/8:
+            params = wc_Dh_ffdhe4096_Get();
+            group = WOLFSSL_FFDHE_4096;
+            break;
+    #endif
+    #ifdef HAVE_FFDHE_6144
+        case 6144/8:
+            params = wc_Dh_ffdhe6144_Get();
+            group = WOLFSSL_FFDHE_6144;
+            break;
+    #endif
+    #ifdef HAVE_FFDHE_8192
+        case 8192/8:
+            params = wc_Dh_ffdhe8192_Get();
+            group = WOLFSSL_FFDHE_8192;
+            break;
+    #endif
+        default:
+            break;
+    }
+
+    if (params == NULL || params->g_len != ssl->buffers.serverDH_G.length ||
+            (XMEMCMP(ssl->buffers.serverDH_G.buffer, params->g,
+                    params->g_len) != 0) ||
+            (XMEMCMP(ssl->buffers.serverDH_P.buffer, params->p,
+                    params->p_len) != 0)) {
+        WOLFSSL_MSG("Server not using FFDHE parameters");
+    #ifdef WOLFSSL_REQUIRE_FFDHE
+        SendAlert(ssl, alert_fatal, handshake_failure);
+        ERROR_OUT(DH_PARAMS_NOT_FFDHE_E, exit_gdpk);
+    #endif
+    }
+    else {
+        ssl->namedGroup = group;
+    #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \
+        !defined(HAVE_SELFTEST)
+        ssl->options.dhDoKeyTest = 0;
+    #endif
+    }
+#endif /* HAVE_FFDHE */
+
+exit_gdpk:
+    return ret;
+}
+#endif
+
+/* handle processing of server_key_exchange (12) */
+static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
+                               word32* inOutIdx, word32 size)
+{
+    int ret = 0;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    DskeArgs* args = (DskeArgs*)ssl->async.args;
+    typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+    (void)sizeof(args_test);
+#else
+    DskeArgs  args[1];
+#endif
+
+    (void)input;
+    (void)size;
+
+    WOLFSSL_START(WC_FUNC_SERVER_KEY_EXCHANGE_DO);
+    WOLFSSL_ENTER("DoServerKeyExchange");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
+    if (ret != WC_NOT_PENDING_E) {
+        /* Check for error */
+        if (ret < 0)
+            goto exit_dske;
+    }
+    else
+#endif
+    {
+        /* Reset state */
+        ret = 0;
+        ssl->options.asyncState = TLS_ASYNC_BEGIN;
+        XMEMSET(args, 0, sizeof(DskeArgs));
+        args->idx = *inOutIdx;
+        args->begin = *inOutIdx;
+        args->sigAlgo = ssl->specs.sig_algo;
+        args->hashAlgo = sha_mac;
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        ssl->async.freeArgs = FreeDskeArgs;
+    #endif
+    }
+
+    switch(ssl->options.asyncState)
+    {
+        case TLS_ASYNC_BEGIN:
+        {
+        #ifdef WOLFSSL_CALLBACKS
+            if (ssl->hsInfoOn)
+                AddPacketName(ssl, "ServerKeyExchange");
+            if (ssl->toInfoOn)
+                AddLateName("ServerKeyExchange", &ssl->timeoutInfo);
+        #endif
+
+            switch(ssl->specs.kea)
+            {
+            #ifndef NO_PSK
+                case psk_kea:
+                {
+                    int srvHintLen;
+                    word16 length;
+
+                    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    ato16(input + args->idx, &length);
+                    args->idx += OPAQUE16_LEN;
+
+                    if ((args->idx - args->begin) + length > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    /* get PSK server hint from the wire */
+                    srvHintLen = min(length, MAX_PSK_ID_LEN);
+                    XMEMCPY(ssl->arrays->server_hint, input + args->idx,
+                                                                    srvHintLen);
+                    ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */
+                    args->idx += length;
+                    break;
+                }
+            #endif /* !NO_PSK */
+            #ifndef NO_DH
+                case diffie_hellman_kea:
+                {
+                    ret = GetDhPublicKey(ssl, input, size, args);
+                    if (ret != 0)
+                        goto exit_dske;
+                    break;
+                }
+            #endif /* !NO_DH */
+            #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                                          defined(HAVE_CURVE448)
+                case ecc_diffie_hellman_kea:
+                {
+                    byte b;
+                #ifdef HAVE_ECC
+                    int curveId;
+                #endif
+                    int curveOid;
+                    word16 length;
+
+                    if ((args->idx - args->begin) + ENUM_LEN + OPAQUE16_LEN +
+                                                        OPAQUE8_LEN > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    b = input[args->idx++];
+                    if (b != named_curve) {
+                        ERROR_OUT(ECC_CURVETYPE_ERROR, exit_dske);
+                    }
+
+                    args->idx += 1;   /* curve type, eat leading 0 */
+                    b = input[args->idx++];
+                    if ((curveOid = CheckCurveId(b)) < 0) {
+                        ERROR_OUT(ECC_CURVE_ERROR, exit_dske);
+                    }
+                    ssl->ecdhCurveOID = curveOid;
+                #if defined(WOLFSSL_TLS13) || defined(HAVE_FFDHE)
+                    ssl->namedGroup = 0;
+                #endif
+
+                    length = input[args->idx++];
+                    if ((args->idx - args->begin) + length > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                #ifdef HAVE_CURVE25519
+                    if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+                        if (ssl->peerX25519Key == NULL) {
+                            ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519,
+                                           (void**)&ssl->peerX25519Key);
+                            if (ret != 0) {
+                                goto exit_dske;
+                            }
+                        } else if (ssl->peerX25519KeyPresent) {
+                            ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519,
+                                           ssl->peerX25519Key);
+                            ssl->peerX25519KeyPresent = 0;
+                            if (ret != 0) {
+                                goto exit_dske;
+                            }
+                        }
+
+                        if ((ret = wc_curve25519_check_public(
+                                input + args->idx, length,
+                                EC25519_LITTLE_ENDIAN)) != 0) {
+                        #ifdef WOLFSSL_EXTRA_ALERTS
+                            if (ret == BUFFER_E)
+                                SendAlert(ssl, alert_fatal, decode_error);
+                            else if (ret == ECC_OUT_OF_RANGE_E)
+                                SendAlert(ssl, alert_fatal, bad_record_mac);
+                            else {
+                                SendAlert(ssl, alert_fatal, illegal_parameter);
+                            }
+                        #endif
+                            ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
+                        }
+
+                        if (wc_curve25519_import_public_ex(input + args->idx,
+                                length, ssl->peerX25519Key,
+                                EC25519_LITTLE_ENDIAN) != 0) {
+                            ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
+                        }
+
+                        args->idx += length;
+                        ssl->peerX25519KeyPresent = 1;
+                        break;
+                    }
+                #endif
+                #ifdef HAVE_CURVE448
+                    if (ssl->ecdhCurveOID == ECC_X448_OID) {
+                        if (ssl->peerX448Key == NULL) {
+                            ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE448,
+                                           (void**)&ssl->peerX448Key);
+                            if (ret != 0) {
+                                goto exit_dske;
+                            }
+                        } else if (ssl->peerX448KeyPresent) {
+                            ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE448,
+                                           ssl->peerX448Key);
+                            ssl->peerX448KeyPresent = 0;
+                            if (ret != 0) {
+                                goto exit_dske;
+                            }
+                        }
+
+                        if ((ret = wc_curve448_check_public(
+                                input + args->idx, length,
+                                EC448_LITTLE_ENDIAN)) != 0) {
+                        #ifdef WOLFSSL_EXTRA_ALERTS
+                            if (ret == BUFFER_E)
+                                SendAlert(ssl, alert_fatal, decode_error);
+                            else if (ret == ECC_OUT_OF_RANGE_E)
+                                SendAlert(ssl, alert_fatal, bad_record_mac);
+                            else {
+                                SendAlert(ssl, alert_fatal, illegal_parameter);
+                            }
+                        #endif
+                            ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
+                        }
+
+                        if (wc_curve448_import_public_ex(input + args->idx,
+                                length, ssl->peerX448Key,
+                                EC448_LITTLE_ENDIAN) != 0) {
+                            ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
+                        }
+
+                        args->idx += length;
+                        ssl->peerX448KeyPresent = 1;
+                        break;
+                    }
+                #endif
+                #ifdef HAVE_ECC
+                    if (ssl->peerEccKey == NULL) {
+                        ret = AllocKey(ssl, DYNAMIC_TYPE_ECC,
+                                       (void**)&ssl->peerEccKey);
+                        if (ret != 0) {
+                            goto exit_dske;
+                        }
+                    } else if (ssl->peerEccKeyPresent) {
+                        ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC, ssl->peerEccKey);
+                        ssl->peerEccKeyPresent = 0;
+                        if (ret != 0) {
+                            goto exit_dske;
+                        }
+                    }
+
+                    curveId = wc_ecc_get_oid(curveOid, NULL, NULL);
+                    if (wc_ecc_import_x963_ex(input + args->idx, length,
+                                        ssl->peerEccKey, curveId) != 0) {
+                    #ifdef WOLFSSL_EXTRA_ALERTS
+                        SendAlert(ssl, alert_fatal, illegal_parameter);
+                    #endif
+                        ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
+                    }
+
+                    args->idx += length;
+                    ssl->peerEccKeyPresent = 1;
+                #endif
+                    break;
+                }
+            #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+            #if !defined(NO_DH) && !defined(NO_PSK)
+                case dhe_psk_kea:
+                {
+                    int srvHintLen;
+                    word16 length;
+
+                    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    ato16(input + args->idx, &length);
+                    args->idx += OPAQUE16_LEN;
+
+                    if ((args->idx - args->begin) + length > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    /* get PSK server hint from the wire */
+                    srvHintLen = min(length, MAX_PSK_ID_LEN);
+                    XMEMCPY(ssl->arrays->server_hint, input + args->idx,
+                                                                srvHintLen);
+                    ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */
+                    args->idx += length;
+
+                    ret = GetDhPublicKey(ssl, input, size, args);
+                    if (ret != 0)
+                        goto exit_dske;
+                    break;
+                }
+            #endif /* !NO_DH && !NO_PSK */
+            #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                     defined(HAVE_CURVE448)) && !defined(NO_PSK)
+                case ecdhe_psk_kea:
+                {
+                    byte b;
+                    int curveOid, curveId;
+                    int srvHintLen;
+                    word16 length;
+
+                    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    ato16(input + args->idx, &length);
+                    args->idx += OPAQUE16_LEN;
+
+                    if ((args->idx - args->begin) + length > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    /* get PSK server hint from the wire */
+                    srvHintLen = min(length, MAX_PSK_ID_LEN);
+                    XMEMCPY(ssl->arrays->server_hint, input + args->idx,
+                                                                    srvHintLen);
+                    ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */
+
+                    args->idx += length;
+
+                    if ((args->idx - args->begin) + ENUM_LEN + OPAQUE16_LEN +
+                        OPAQUE8_LEN > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    /* Check curve name and ID */
+                    b = input[args->idx++];
+                    if (b != named_curve) {
+                        ERROR_OUT(ECC_CURVETYPE_ERROR, exit_dske);
+                    }
+
+                    args->idx += 1;   /* curve type, eat leading 0 */
+                    b = input[args->idx++];
+                    if ((curveOid = CheckCurveId(b)) < 0) {
+                        ERROR_OUT(ECC_CURVE_ERROR, exit_dske);
+                    }
+
+                    length = input[args->idx++];
+                    if ((args->idx - args->begin) + length > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                #ifdef HAVE_CURVE25519
+                    if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+                        if (ssl->peerX25519Key == NULL) {
+                            ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519,
+                                           (void**)&ssl->peerX25519Key);
+                            if (ret != 0) {
+                                goto exit_dske;
+                            }
+                        } else if (ssl->peerEccKeyPresent) {
+                            ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519,
+                                           ssl->peerX25519Key);
+                            ssl->peerX25519KeyPresent = 0;
+                            if (ret != 0) {
+                                goto exit_dske;
+                            }
+                        }
+
+                        if ((ret = wc_curve25519_check_public(
+                                input + args->idx, length,
+                                EC25519_LITTLE_ENDIAN)) != 0) {
+                        #ifdef WOLFSSL_EXTRA_ALERTS
+                            if (ret == BUFFER_E)
+                                SendAlert(ssl, alert_fatal, decode_error);
+                            else if (ret == ECC_OUT_OF_RANGE_E)
+                                SendAlert(ssl, alert_fatal, bad_record_mac);
+                            else {
+                                SendAlert(ssl, alert_fatal, illegal_parameter);
+                            }
+                        #endif
+                            ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
+                        }
+
+                        if (wc_curve25519_import_public_ex(input + args->idx,
+                                length, ssl->peerX25519Key,
+                                EC25519_LITTLE_ENDIAN) != 0) {
+                            ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
+                        }
+
+                        args->idx += length;
+                        ssl->peerX25519KeyPresent = 1;
+                        break;
+                    }
+                #endif
+                #ifdef HAVE_CURVE448
+                    if (ssl->ecdhCurveOID == ECC_X448_OID) {
+                        if (ssl->peerX448Key == NULL) {
+                            ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE448,
+                                           (void**)&ssl->peerX448Key);
+                            if (ret != 0) {
+                                goto exit_dske;
+                            }
+                        } else if (ssl->peerEccKeyPresent) {
+                            ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE448,
+                                           ssl->peerX448Key);
+                            ssl->peerX448KeyPresent = 0;
+                            if (ret != 0) {
+                                goto exit_dske;
+                            }
+                        }
+
+                        if ((ret = wc_curve448_check_public(
+                                input + args->idx, length,
+                                EC448_LITTLE_ENDIAN)) != 0) {
+                        #ifdef WOLFSSL_EXTRA_ALERTS
+                            if (ret == BUFFER_E)
+                                SendAlert(ssl, alert_fatal, decode_error);
+                            else if (ret == ECC_OUT_OF_RANGE_E)
+                                SendAlert(ssl, alert_fatal, bad_record_mac);
+                            else {
+                                SendAlert(ssl, alert_fatal, illegal_parameter);
+                            }
+                        #endif
+                            ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
+                        }
+
+                        if (wc_curve448_import_public_ex(input + args->idx,
+                                length, ssl->peerX448Key,
+                                EC448_LITTLE_ENDIAN) != 0) {
+                            ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
+                        }
+
+                        args->idx += length;
+                        ssl->peerX448KeyPresent = 1;
+                        break;
+                    }
+                #endif
+
+                    if (ssl->peerEccKey == NULL) {
+                        ret = AllocKey(ssl, DYNAMIC_TYPE_ECC,
+                                 (void**)&ssl->peerEccKey);
+                        if (ret != 0) {
+                            goto exit_dske;
+                        }
+                    } else if (ssl->peerEccKeyPresent) {
+                        ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC, ssl->peerEccKey);
+                        ssl->peerEccKeyPresent = 0;
+                        if (ret != 0) {
+                            goto exit_dske;
+                        }
+                    }
+
+                    curveId = wc_ecc_get_oid(curveOid, NULL, NULL);
+                    if (wc_ecc_import_x963_ex(input + args->idx, length,
+                        ssl->peerEccKey, curveId) != 0) {
+                        ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
+                    }
+
+                    args->idx += length;
+                    ssl->peerEccKeyPresent = 1;
+                    break;
+                }
+            #endif /* (HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448) && !NO_PSK */
+                default:
+                    ret = BAD_KEA_TYPE_E;
+            } /* switch(ssl->specs.kea) */
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_dske;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_BUILD;
+        } /* case TLS_ASYNC_BEGIN */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_BUILD:
+        {
+            switch(ssl->specs.kea)
+            {
+                case psk_kea:
+                case dhe_psk_kea:
+                case ecdhe_psk_kea:
+                {
+                    /* Nothing to do in this sub-state */
+                    break;
+                }
+
+                case diffie_hellman_kea:
+                case ecc_diffie_hellman_kea:
+                {
+            #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(HAVE_ED25519) \
+                                                     && !defined(HAVE_ED448)
+                    ERROR_OUT(NOT_COMPILED_IN, exit_dske);
+            #else
+                    enum wc_HashType hashType;
+                    word16  verifySz;
+
+                    if (ssl->options.usingAnon_cipher) {
+                        break;
+                    }
+
+                    verifySz = (word16)(args->idx - args->begin);
+                    if (verifySz > MAX_DH_SZ) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    if (IsAtLeastTLSv1_2(ssl)) {
+                        if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN >
+                                                                        size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dske);
+                        }
+
+                        DecodeSigAlg(&input[args->idx], &args->hashAlgo,
+                                     &args->sigAlgo);
+                        args->idx += 2;
+                        hashType = HashAlgoToType(args->hashAlgo);
+                        if (hashType == WC_HASH_TYPE_NONE) {
+                            ERROR_OUT(ALGO_ID_E, exit_dske);
+                        }
+                    } else {
+                        /* only using sha and md5 for rsa */
+                        #ifndef NO_OLD_TLS
+                            hashType = WC_HASH_TYPE_SHA;
+                            if (args->sigAlgo == rsa_sa_algo) {
+                                hashType = WC_HASH_TYPE_MD5_SHA;
+                            }
+                        #else
+                            ERROR_OUT(ALGO_ID_E, exit_dske);
+                        #endif
+                    }
+
+                    /* signature */
+                    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    ato16(input + args->idx, &args->verifySigSz);
+                    args->idx += OPAQUE16_LEN;
+
+                    if ((args->idx - args->begin) + args->verifySigSz > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    /* buffer for signature */
+                    ssl->buffers.sig.buffer = (byte*)XMALLOC(SEED_LEN + verifySz,
+                                            ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+                    if (ssl->buffers.sig.buffer == NULL) {
+                        ERROR_OUT(MEMORY_E, exit_dske);
+                    }
+                    ssl->buffers.sig.length = SEED_LEN + verifySz;
+
+                    /* build message to hash */
+                    XMEMCPY(ssl->buffers.sig.buffer,
+                        ssl->arrays->clientRandom, RAN_LEN);
+                    XMEMCPY(&ssl->buffers.sig.buffer[RAN_LEN],
+                        ssl->arrays->serverRandom, RAN_LEN);
+                    XMEMCPY(&ssl->buffers.sig.buffer[RAN_LEN * 2],
+                        input + args->begin, verifySz); /* message */
+
+                    if (args->sigAlgo != ed25519_sa_algo) {
+                        int digest_sz = wc_HashGetDigestSize(hashType);
+                        if (digest_sz <= 0) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dske);
+                        }
+                        ssl->buffers.digest.length = (unsigned int)digest_sz;
+
+                        /* buffer for hash */
+                        ssl->buffers.digest.buffer = (byte*)XMALLOC(
+                            ssl->buffers.digest.length, ssl->heap,
+                            DYNAMIC_TYPE_DIGEST);
+                        if (ssl->buffers.digest.buffer == NULL) {
+                            ERROR_OUT(MEMORY_E, exit_dske);
+                        }
+
+                        /* Perform hash */
+                        ret = wc_Hash(hashType, ssl->buffers.sig.buffer,
+                                                    ssl->buffers.sig.length,
+                                                    ssl->buffers.digest.buffer,
+                                                    ssl->buffers.digest.length);
+                        if (ret != 0) {
+                            goto exit_dske;
+                        }
+                    }
+
+                    switch (args->sigAlgo)
+                    {
+                    #ifndef NO_RSA
+                    #ifdef WC_RSA_PSS
+                        case rsa_pss_sa_algo:
+                    #endif
+                        case rsa_sa_algo:
+                        {
+                            if (ssl->peerRsaKey == NULL ||
+                                                    !ssl->peerRsaKeyPresent) {
+                                ERROR_OUT(NO_PEER_KEY, exit_dske);
+                            }
+                            break;
+                        }
+                    #endif /* !NO_RSA */
+                    #ifdef HAVE_ECC
+                        case ecc_dsa_sa_algo:
+                        {
+                            if (!ssl->peerEccDsaKeyPresent) {
+                                ERROR_OUT(NO_PEER_KEY, exit_dske);
+                            }
+                            break;
+                        }
+                    #endif /* HAVE_ECC */
+                    #if defined(HAVE_ED25519)
+                        case ed25519_sa_algo:
+                        {
+                            if (!ssl->peerEd25519KeyPresent) {
+                                ERROR_OUT(NO_PEER_KEY, exit_dske);
+                            }
+                            break;
+                        }
+                    #endif /* HAVE_ED25519 */
+                    #if defined(HAVE_ED448)
+                        case ed448_sa_algo:
+                        {
+                            if (!ssl->peerEd448KeyPresent) {
+                                ERROR_OUT(NO_PEER_KEY, exit_dske);
+                            }
+                            break;
+                        }
+                    #endif /* HAVE_ED448 */
+
+                    default:
+                        ret = ALGO_ID_E;
+                    } /* switch (args->sigAlgo) */
+
+            #endif /* NO_DH && !HAVE_ECC && !HAVE_ED25519 && !HAVE_ED448 */
+                    break;
+                }
+                default:
+                    ret = BAD_KEA_TYPE_E;
+            } /* switch(ssl->specs.kea) */
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_dske;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_DO;
+        } /* case TLS_ASYNC_BUILD */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_DO:
+        {
+            switch(ssl->specs.kea)
+            {
+                case psk_kea:
+                case dhe_psk_kea:
+                case ecdhe_psk_kea:
+                {
+                    /* Nothing to do in this sub-state */
+                    break;
+                }
+
+                case diffie_hellman_kea:
+                case ecc_diffie_hellman_kea:
+                {
+            #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(HAVE_ED25519) \
+                                                     && !defined(HAVE_ED448)
+                    ERROR_OUT(NOT_COMPILED_IN, exit_dske);
+            #else
+                    if (ssl->options.usingAnon_cipher) {
+                        break;
+                    }
+
+                    if (args->verifySig == NULL) {
+                        args->verifySig = (byte*)XMALLOC(args->verifySigSz,
+                                            ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+                        if (args->verifySig == NULL) {
+                            ERROR_OUT(MEMORY_E, exit_dske);
+                        }
+                        XMEMCPY(args->verifySig, input + args->idx,
+                                                            args->verifySigSz);
+                    }
+
+                    switch (args->sigAlgo)
+                    {
+                    #ifndef NO_RSA
+                    #ifdef WC_RSA_PSS
+                        case rsa_pss_sa_algo:
+                    #endif
+                        case rsa_sa_algo:
+                        {
+                            ret = RsaVerify(ssl,
+                                args->verifySig, args->verifySigSz,
+                                &args->output,
+                                args->sigAlgo, args->hashAlgo,
+                                ssl->peerRsaKey,
+                            #ifdef HAVE_PK_CALLBACKS
+                                &ssl->buffers.peerRsaKey
+                            #else
+                                NULL
+                            #endif
+                            );
+
+                            if (ret >= 0) {
+                                args->sigSz = (word16)ret;
+                            #ifdef WC_RSA_PSS
+                                args->bits = mp_count_bits(&ssl->peerRsaKey->n);
+                            #endif
+                                ret = 0;
+                            }
+                        #ifdef WOLFSSL_ASYNC_CRYPT
+                            if (ret != WC_PENDING_E)
+                        #endif
+                            {
+                                /* peerRsaKey */
+                                FreeKey(ssl, DYNAMIC_TYPE_RSA,
+                                                      (void**)&ssl->peerRsaKey);
+                                ssl->peerRsaKeyPresent = 0;
+                            }
+                            break;
+                        }
+                    #endif /* !NO_RSA */
+                    #ifdef HAVE_ECC
+                        case ecc_dsa_sa_algo:
+                        {
+                            ret = EccVerify(ssl,
+                                args->verifySig, args->verifySigSz,
+                                ssl->buffers.digest.buffer,
+                                ssl->buffers.digest.length,
+                                ssl->peerEccDsaKey,
+                            #ifdef HAVE_PK_CALLBACKS
+                                &ssl->buffers.peerEccDsaKey
+                            #else
+                                NULL
+                            #endif
+                            );
+
+                        #ifdef WOLFSSL_ASYNC_CRYPT
+                            if (ret != WC_PENDING_E)
+                        #endif
+                            {
+                                /* peerEccDsaKey */
+                                FreeKey(ssl, DYNAMIC_TYPE_ECC,
+                                                   (void**)&ssl->peerEccDsaKey);
+                                ssl->peerEccDsaKeyPresent = 0;
+                            }
+                            break;
+                        }
+                    #endif /* HAVE_ECC */
+                    #if defined(HAVE_ED25519)
+                        case ed25519_sa_algo:
+                        {
+                            ret = Ed25519Verify(ssl,
+                                args->verifySig, args->verifySigSz,
+                                ssl->buffers.sig.buffer,
+                                ssl->buffers.sig.length,
+                                ssl->peerEd25519Key,
+                            #ifdef HAVE_PK_CALLBACKS
+                                &ssl->buffers.peerEd25519Key
+                            #else
+                                NULL
+                            #endif
+                            );
+
+                        #ifdef WOLFSSL_ASYNC_CRYPT
+                            if (ret != WC_PENDING_E)
+                        #endif
+                            {
+                                /* peerEccDsaKey */
+                                FreeKey(ssl, DYNAMIC_TYPE_ED25519,
+                                                  (void**)&ssl->peerEd25519Key);
+                                ssl->peerEd25519KeyPresent = 0;
+                            }
+                            break;
+                        }
+                    #endif /* HAVE_ED25519 */
+                    #if defined(HAVE_ED448)
+                        case ed448_sa_algo:
+                        {
+                            ret = Ed448Verify(ssl,
+                                args->verifySig, args->verifySigSz,
+                                ssl->buffers.sig.buffer,
+                                ssl->buffers.sig.length,
+                                ssl->peerEd448Key,
+                            #ifdef HAVE_PK_CALLBACKS
+                                &ssl->buffers.peerEd448Key
+                            #else
+                                NULL
+                            #endif
+                            );
+
+                        #ifdef WOLFSSL_ASYNC_CRYPT
+                            if (ret != WC_PENDING_E)
+                        #endif
+                            {
+                                /* peerEccDsaKey */
+                                FreeKey(ssl, DYNAMIC_TYPE_ED448,
+                                                    (void**)&ssl->peerEd448Key);
+                                ssl->peerEd448KeyPresent = 0;
+                            }
+                            break;
+                        }
+                    #endif /* HAVE_ED448 */
+
+                    default:
+                        ret = ALGO_ID_E;
+                    } /* switch (sigAlgo) */
+            #endif /* NO_DH && !HAVE_ECC && !HAVE_ED25519 && !HAVE_ED448 */
+                    break;
+                }
+                default:
+                    ret = BAD_KEA_TYPE_E;
+            } /* switch(ssl->specs.kea) */
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_dske;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_VERIFY;
+        } /* case TLS_ASYNC_DO */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_VERIFY:
+        {
+            switch(ssl->specs.kea)
+            {
+                case psk_kea:
+                case dhe_psk_kea:
+                case ecdhe_psk_kea:
+                {
+                    /* Nothing to do in this sub-state */
+                    break;
+                }
+
+                case diffie_hellman_kea:
+                case ecc_diffie_hellman_kea:
+                {
+            #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(HAVE_ED25519) \
+                                                     && !defined(HAVE_ED448)
+                    ERROR_OUT(NOT_COMPILED_IN, exit_dske);
+            #else
+                    if (ssl->options.usingAnon_cipher) {
+                        break;
+                    }
+
+                    /* increment index after verify is done */
+                    args->idx += args->verifySigSz;
+
+                    switch(args->sigAlgo)
+                    {
+                    #ifndef NO_RSA
+                    #ifdef WC_RSA_PSS
+                        case rsa_pss_sa_algo:
+                        #ifdef HAVE_SELFTEST
+                            ret = wc_RsaPSS_CheckPadding(
+                                             ssl->buffers.digest.buffer,
+                                             ssl->buffers.digest.length,
+                                             args->output, args->sigSz,
+                                             HashAlgoToType(args->hashAlgo));
+                        #else
+                            ret = wc_RsaPSS_CheckPadding_ex(
+                                             ssl->buffers.digest.buffer,
+                                             ssl->buffers.digest.length,
+                                             args->output, args->sigSz,
+                                             HashAlgoToType(args->hashAlgo),
+                                             -1, args->bits);
+                        #endif
+                            if (ret != 0)
+                                return ret;
+                            break;
+                    #endif
+                        case rsa_sa_algo:
+                        {
+                            if (IsAtLeastTLSv1_2(ssl)) {
+                            #ifdef WOLFSSL_SMALL_STACK
+                                byte*  encodedSig;
+                            #else
+                                byte   encodedSig[MAX_ENCODED_SIG_SZ];
+                            #endif
+                                word32 encSigSz;
+
+                            #ifdef WOLFSSL_SMALL_STACK
+                                encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ,
+                                                ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+                                if (encodedSig == NULL) {
+                                    ERROR_OUT(MEMORY_E, exit_dske);
+                                }
+                            #endif
+
+                                encSigSz = wc_EncodeSignature(encodedSig,
+                                    ssl->buffers.digest.buffer,
+                                    ssl->buffers.digest.length,
+                                    TypeHash(args->hashAlgo));
+                                if (encSigSz != args->sigSz || !args->output ||
+                                    XMEMCMP(args->output, encodedSig,
+                                            min(encSigSz, MAX_ENCODED_SIG_SZ)) != 0) {
+                                    ret = VERIFY_SIGN_ERROR;
+                                }
+                            #ifdef WOLFSSL_SMALL_STACK
+                                XFREE(encodedSig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+                            #endif
+                                if (ret != 0) {
+                                    goto exit_dske;
+                                }
+                            }
+                            else if (args->sigSz != FINISHED_SZ ||
+                                    !args->output ||
+                                    XMEMCMP(args->output,
+                                            ssl->buffers.digest.buffer,
+                                            FINISHED_SZ) != 0) {
+                                ERROR_OUT(VERIFY_SIGN_ERROR, exit_dske);
+                            }
+                            break;
+                        }
+                    #endif /* !NO_RSA */
+                    #ifdef HAVE_ECC
+                        case ecc_dsa_sa_algo:
+                            /* Nothing to do in this algo */
+                            break;
+                    #endif /* HAVE_ECC */
+                    #if defined(HAVE_ED25519)
+                        case ed25519_sa_algo:
+                            /* Nothing to do in this algo */
+                            break;
+                    #endif /* HAVE_ED25519 */
+                    #if defined(HAVE_ED448)
+                        case ed448_sa_algo:
+                            /* Nothing to do in this algo */
+                            break;
+                    #endif /* HAVE_ED448 */
+                        default:
+                            ret = ALGO_ID_E;
+                    } /* switch (sigAlgo) */
+            #endif /* NO_DH && !HAVE_ECC && !HAVE_ED25519 && !HAVE_ED448 */
+                    break;
+                }
+                default:
+                    ret = BAD_KEA_TYPE_E;
+            } /* switch(ssl->specs.kea) */
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_dske;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_FINALIZE;
+        } /* case TLS_ASYNC_VERIFY */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_FINALIZE:
+        {
+            if (IsEncryptionOn(ssl, 0)) {
+                args->idx += ssl->keys.padSz;
+            #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+                if (ssl->options.startedETMRead)
+                    args->idx += MacSize(ssl);
+            #endif
+            }
+
+            /* QSH extensions */
+        #ifdef HAVE_QSH
+            if (ssl->peerQSHKeyPresent) {
+                word16 name;
+                int    qshSz;
+
+                /* extension name */
+                ato16(input + args->idx, &name);
+                args->idx += OPAQUE16_LEN;
+
+                if (name == TLSX_QUANTUM_SAFE_HYBRID) {
+                    /* if qshSz is larger than 0 it is the length of
+                       buffer used */
+                    if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + args->idx,
+                                                       size, 0)) < 0) {
+                        ERROR_OUT(qshSz, exit_dske);
+                    }
+                    args->idx += qshSz;
+                }
+                else {
+                    /* unknown extension sent server ignored handshake */
+                    ERROR_OUT(BUFFER_ERROR, exit_dske);
+                }
+            }
+        #endif
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_END;
+        } /* case TLS_ASYNC_FINALIZE */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_END:
+        {
+            /* return index */
+            *inOutIdx = args->idx;
+
+            ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
+            break;
+        }
+        default:
+            ret = INPUT_CASE_ERROR;
+    } /* switch(ssl->options.asyncState) */
+
+exit_dske:
+
+    WOLFSSL_LEAVE("DoServerKeyExchange", ret);
+    WOLFSSL_END(WC_FUNC_SERVER_KEY_EXCHANGE_DO);
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* Handle async operation */
+    if (ret == WC_PENDING_E) {
+        /* Mark message as not received so it can process again */
+        ssl->msgsReceived.got_server_key_exchange = 0;
+
+        return ret;
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    /* Final cleanup */
+    FreeDskeArgs(ssl, args);
+    FreeKeyExchange(ssl);
+
+    return ret;
+}
+
+
+#ifdef HAVE_QSH
+
+#ifdef HAVE_NTRU
+/* Encrypt a byte array using ntru
+   key    a struct containing the public key to use
+   bufIn  array to be encrypted
+   inSz   size of bufIn array
+   bufOut cipher text out
+   outSz  will be set to the new size of cipher text
+ */
+static int NtruSecretEncrypt(QSHKey* key, byte* bufIn, word32 inSz,
+        byte* bufOut, word16* outSz)
+{
+    int    ret;
+    DRBG_HANDLE drbg;
+
+    /* sanity checks on input arguments */
+    if (key == NULL || bufIn == NULL || bufOut == NULL || outSz == NULL)
+        return BAD_FUNC_ARG;
+
+    if (key->pub.buffer == NULL)
+        return BAD_FUNC_ARG;
+
+    switch (key->name) {
+        case WOLFSSL_NTRU_EESS439:
+        case WOLFSSL_NTRU_EESS593:
+        case WOLFSSL_NTRU_EESS743:
+            break;
+        default:
+            WOLFSSL_MSG("Unknown QSH encryption key!");
+            return -1;
+    }
+
+    /* set up ntru drbg */
+    ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg);
+    if (ret != DRBG_OK)
+        return NTRU_DRBG_ERROR;
+
+    /* encrypt the byte array */
+    ret = ntru_crypto_ntru_encrypt(drbg, key->pub.length, key->pub.buffer,
+        inSz, bufIn, outSz, bufOut);
+    ntru_crypto_drbg_uninstantiate(drbg);
+    if (ret != NTRU_OK)
+        return NTRU_ENCRYPT_ERROR;
+
+    return ret;
+}
+
+/* Decrypt a byte array using ntru
+   key    a struct containing the private key to use
+   bufIn  array to be decrypted
+   inSz   size of bufIn array
+   bufOut plain text out
+   outSz  will be set to the new size of plain text
+ */
+
+static int NtruSecretDecrypt(QSHKey* key, byte* bufIn, word32 inSz,
+        byte* bufOut, word16* outSz)
+{
+    int    ret;
+    DRBG_HANDLE drbg;
+
+    /* sanity checks on input arguments */
+    if (key == NULL || bufIn == NULL || bufOut == NULL || outSz == NULL)
+        return BAD_FUNC_ARG;
+
+    if (key->pri.buffer == NULL)
+        return BAD_FUNC_ARG;
+
+    switch (key->name) {
+        case WOLFSSL_NTRU_EESS439:
+        case WOLFSSL_NTRU_EESS593:
+        case WOLFSSL_NTRU_EESS743:
+            break;
+        default:
+            WOLFSSL_MSG("Unknown QSH decryption key!");
+            return -1;
+    }
+
+
+    /* set up drbg */
+    ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg);
+    if (ret != DRBG_OK)
+        return NTRU_DRBG_ERROR;
+
+    /* decrypt cipher text */
+    ret = ntru_crypto_ntru_decrypt(key->pri.length, key->pri.buffer,
+        inSz, bufIn, outSz, bufOut);
+    ntru_crypto_drbg_uninstantiate(drbg);
+    if (ret != NTRU_OK)
+        return NTRU_ENCRYPT_ERROR;
+
+    return ret;
+}
+#endif /* HAVE_NTRU */
+
+int QSH_Init(WOLFSSL* ssl)
+{
+    /* check so not initializing twice when running DTLS */
+    if (ssl->QSH_secret != NULL)
+        return 0;
+
+    /* malloc memory for holding generated secret information */
+    if ((ssl->QSH_secret = (QSHSecret*)XMALLOC(sizeof(QSHSecret), ssl->heap,
+                    DYNAMIC_TYPE_QSH)) == NULL)
+        return MEMORY_E;
+
+    ssl->QSH_secret->CliSi = (buffer*)XMALLOC(sizeof(buffer), ssl->heap,
+            DYNAMIC_TYPE_SECRET);
+    if (ssl->QSH_secret->CliSi == NULL)
+        return MEMORY_E;
+
+    ssl->QSH_secret->SerSi = (buffer*)XMALLOC(sizeof(buffer), ssl->heap,
+            DYNAMIC_TYPE_SECRET);
+    if (ssl->QSH_secret->SerSi == NULL)
+        return MEMORY_E;
+
+    /* initialize variables */
+    ssl->QSH_secret->list = NULL;
+    ssl->QSH_secret->CliSi->length = 0;
+    ssl->QSH_secret->CliSi->buffer = NULL;
+    ssl->QSH_secret->SerSi->length = 0;
+    ssl->QSH_secret->SerSi->buffer = NULL;
+
+    return 0;
+}
+
+
+static int QSH_Encrypt(QSHKey* key, byte* in, word32 szIn,
+                                                       byte* out, word32* szOut)
+{
+    int ret = 0;
+    word16 size = *szOut;
+
+    (void)in;
+    (void)szIn;
+    (void)out;
+    (void)szOut;
+
+    WOLFSSL_MSG("Encrypting QSH key material");
+
+    switch (key->name) {
+    #ifdef HAVE_NTRU
+        case WOLFSSL_NTRU_EESS439:
+        case WOLFSSL_NTRU_EESS593:
+        case WOLFSSL_NTRU_EESS743:
+            ret = NtruSecretEncrypt(key, in, szIn, out, &size);
+            break;
+    #endif
+        default:
+            WOLFSSL_MSG("Unknown QSH encryption key!");
+            return -1;
+    }
+
+    *szOut = size;
+
+    return ret;
+}
+
+
+/* Decrypt using Quantum Safe Handshake algorithms */
+int QSH_Decrypt(QSHKey* key, byte* in, word32 szIn, byte* out, word16* szOut)
+{
+    int ret = 0;
+    word16 size = *szOut;
+
+    (void)in;
+    (void)szIn;
+    (void)out;
+    (void)szOut;
+
+    WOLFSSL_MSG("Decrypting QSH key material");
+
+    switch (key->name) {
+    #ifdef HAVE_NTRU
+        case WOLFSSL_NTRU_EESS439:
+        case WOLFSSL_NTRU_EESS593:
+        case WOLFSSL_NTRU_EESS743:
+            ret = NtruSecretDecrypt(key, in, szIn, out, &size);
+            break;
+    #endif
+        default:
+            WOLFSSL_MSG("Unknown QSH decryption key!");
+            return -1;
+    }
+
+    *szOut = size;
+
+    return ret;
+}
+
+
+/* Get the max cipher text for corresponding encryption scheme
+   (encrypting  48 or max plain text whichever is smaller)
+ */
+static word32 QSH_MaxSecret(QSHKey* key)
+{
+    int ret = 0;
+#ifdef HAVE_NTRU
+    byte isNtru = 0;
+    word16 inSz = 48;
+    word16 outSz;
+    DRBG_HANDLE drbg = 0;
+    byte bufIn[48];
+#endif
+
+    if (key == NULL || key->pub.length == 0)
+        return 0;
+
+    switch(key->name) {
+#ifdef HAVE_NTRU
+            case WOLFSSL_NTRU_EESS439:
+                isNtru   = 1;
+                break;
+            case WOLFSSL_NTRU_EESS593:
+                isNtru   = 1;
+                break;
+            case WOLFSSL_NTRU_EESS743:
+                isNtru   = 1;
+                break;
+#endif
+        default:
+            WOLFSSL_MSG("Unknown QSH encryption scheme size!");
+            return 0;
+    }
+
+#ifdef HAVE_NTRU
+    if (isNtru) {
+        ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg);
+        if (ret != DRBG_OK)
+            return NTRU_DRBG_ERROR;
+        ret = ntru_crypto_ntru_encrypt(drbg, key->pub.length,
+                            key->pub.buffer, inSz, bufIn, &outSz, NULL);
+        if (ret != NTRU_OK) {
+            return NTRU_ENCRYPT_ERROR;
+        }
+        ntru_crypto_drbg_uninstantiate(drbg);
+        ret = outSz;
+    }
+#endif
+
+    return ret;
+}
+
+/* Generate the secret byte material for pms
+   returns length on success and -1 on fail
+ */
+static int QSH_GenerateSerCliSecret(WOLFSSL* ssl, byte isServer)
+{
+    int sz       = 0;
+    int plainSz  = 48; /* lesser of 48 and max plain text able to encrypt */
+    int offset   = 0;
+    word32 tmpSz = 0;
+    buffer* buf;
+    QSHKey* current;
+    QSHScheme* schmPre = NULL;
+    QSHScheme* schm    = NULL;
+
+    if (ssl == NULL)
+        return -1;
+
+    WOLFSSL_MSG("Generating QSH secret key material");
+
+    current = ssl->peerQSHKey;
+    /* get size of buffer needed */
+    while (current) {
+        if (current->pub.length != 0) {
+            sz += plainSz;
+        }
+        current = (QSHKey*)current->next;
+    }
+
+    /* allocate memory for buffer */
+    if (isServer) {
+        buf = ssl->QSH_secret->SerSi;
+    }
+    else {
+        buf = ssl->QSH_secret->CliSi;
+    }
+    buf->length = sz;
+    buf->buffer = (byte*)XMALLOC(sz, ssl->heap, DYNAMIC_TYPE_SECRET);
+    if (buf->buffer == NULL) {
+        WOLFSSL_ERROR(MEMORY_E);
+    }
+
+    /* create secret information */
+    sz = 0;
+    current = ssl->peerQSHKey;
+    while (current) {
+        schm = (QSHScheme*)XMALLOC(sizeof(QSHScheme), ssl->heap,
+                                                       DYNAMIC_TYPE_QSH);
+        if (schm == NULL)
+            return MEMORY_E;
+
+        /* initialize variables */
+        schm->name  = 0;
+        schm->PK    = NULL;
+        schm->PKLen = 0;
+        schm->next  = NULL;
+        if (ssl->QSH_secret->list == NULL) {
+            ssl->QSH_secret->list = schm;
+        }
+        else {
+            if (schmPre)
+                schmPre->next = schm;
+        }
+
+        tmpSz = QSH_MaxSecret(current);
+
+        if ((schm->PK = (byte*)XMALLOC(tmpSz, ssl->heap,
+                                              DYNAMIC_TYPE_SECRET)) == NULL)
+            return -1;
+
+        /* store info for writing extension */
+        schm->name = current->name;
+
+        /* no key to use for encryption */
+        if (tmpSz == 0) {
+            current = (QSHKey*)current->next;
+            continue;
+        }
+
+        if (wc_RNG_GenerateBlock(ssl->rng, buf->buffer + offset, plainSz)
+                                                                         != 0) {
+            return -1;
+        }
+        if (QSH_Encrypt(current, buf->buffer + offset, plainSz, schm->PK,
+                                                                 &tmpSz) != 0) {
+            return -1;
+        }
+        schm->PKLen = tmpSz;
+
+        sz += tmpSz;
+        offset += plainSz;
+        schmPre = schm;
+        current = (QSHKey*)current->next;
+    }
+
+    return sz;
+}
+
+
+static word32 QSH_KeyGetSize(WOLFSSL* ssl)
+{
+    word32 sz = 0;
+    QSHKey* current;
+
+    if (ssl == NULL)
+        return -1;
+
+    current = ssl->peerQSHKey;
+    sz += OPAQUE16_LEN; /* type of extension ie 0x00 0x18 */
+    sz += OPAQUE24_LEN;
+    /* get size of buffer needed */
+    while (current) {
+        sz += OPAQUE16_LEN; /* scheme id */
+        sz += OPAQUE16_LEN; /* encrypted key len*/
+        sz += QSH_MaxSecret(current);
+        current = (QSHKey*)current->next;
+    }
+
+    return sz;
+}
+
+
+/* handle QSH key Exchange
+   return 0 on success
+ */
+static word32 QSH_KeyExchangeWrite(WOLFSSL* ssl, byte isServer)
+{
+    int ret = 0;
+
+    WOLFSSL_ENTER("QSH KeyExchange");
+
+    ret = QSH_GenerateSerCliSecret(ssl, isServer);
+    if (ret < 0)
+        return MEMORY_E;
+
+    return 0;
+}
+
+#endif /* HAVE_QSH */
+
+
+typedef struct SckeArgs {
+    byte*  output; /* not allocated */
+    byte*  encSecret;
+    byte*  input;
+    word32 encSz;
+    word32 length;
+    int    sendSz;
+    int    inputSz;
+} SckeArgs;
+
+static void FreeSckeArgs(WOLFSSL* ssl, void* pArgs)
+{
+    SckeArgs* args = (SckeArgs*)pArgs;
+
+    (void)ssl;
+
+    if (args->encSecret) {
+        XFREE(args->encSecret, ssl->heap, DYNAMIC_TYPE_SECRET);
+        args->encSecret = NULL;
+    }
+    if (args->input) {
+        XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+        args->input = NULL;
+    }
+}
+
+/* handle generation client_key_exchange (16) */
+int SendClientKeyExchange(WOLFSSL* ssl)
+{
+    int ret = 0;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    SckeArgs* args = (SckeArgs*)ssl->async.args;
+    typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+    (void)sizeof(args_test);
+#else
+    SckeArgs  args[1];
+#endif
+
+    WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND);
+    WOLFSSL_ENTER("SendClientKeyExchange");
+
+#ifdef OPENSSL_EXTRA
+    ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
+    ssl->cbmode = SSL_CB_MODE_WRITE;
+    if (ssl->CBIS != NULL)
+        ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, SSL_SUCCESS);
+#endif
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
+    if (ret != WC_NOT_PENDING_E) {
+        /* Check for error */
+        if (ret < 0)
+            goto exit_scke;
+    }
+    else
+#endif
+    {
+        /* Reset state */
+        ret = 0;
+        ssl->options.asyncState = TLS_ASYNC_BEGIN;
+        XMEMSET(args, 0, sizeof(SckeArgs));
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        ssl->async.freeArgs = FreeSckeArgs;
+    #endif
+    }
+
+    switch(ssl->options.asyncState)
+    {
+        case TLS_ASYNC_BEGIN:
+        {
+            switch (ssl->specs.kea) {
+            #ifndef NO_RSA
+                case rsa_kea:
+                    if (ssl->peerRsaKey == NULL ||
+                        ssl->peerRsaKeyPresent == 0) {
+                        ERROR_OUT(NO_PEER_KEY, exit_scke);
+                    }
+                    break;
+            #endif
+            #ifndef NO_DH
+                case diffie_hellman_kea:
+                    if (ssl->buffers.serverDH_P.buffer == NULL ||
+                        ssl->buffers.serverDH_G.buffer == NULL ||
+                        ssl->buffers.serverDH_Pub.buffer == NULL) {
+                        ERROR_OUT(NO_PEER_KEY, exit_scke);
+                    }
+                    break;
+            #endif /* NO_DH */
+            #ifndef NO_PSK
+                case psk_kea:
+                    /* sanity check that PSK client callback has been set */
+                    if (ssl->options.client_psk_cb == NULL) {
+                        WOLFSSL_MSG("No client PSK callback set");
+                        ERROR_OUT(PSK_KEY_ERROR, exit_scke);
+                    }
+                    break;
+            #endif /* NO_PSK */
+            #if !defined(NO_DH) && !defined(NO_PSK)
+                case dhe_psk_kea:
+                    if (ssl->buffers.serverDH_P.buffer == NULL ||
+                        ssl->buffers.serverDH_G.buffer == NULL ||
+                        ssl->buffers.serverDH_Pub.buffer == NULL) {
+                        ERROR_OUT(NO_PEER_KEY, exit_scke);
+                    }
+
+                    /* sanity check that PSK client callback has been set */
+                    if (ssl->options.client_psk_cb == NULL) {
+                        WOLFSSL_MSG("No client PSK callback set");
+                        ERROR_OUT(PSK_KEY_ERROR, exit_scke);
+                    }
+                    break;
+            #endif /* !NO_DH && !NO_PSK */
+            #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                     defined(HAVE_CURVE448)) && !defined(NO_PSK)
+                case ecdhe_psk_kea:
+                    /* sanity check that PSK client callback has been set */
+                    if (ssl->options.client_psk_cb == NULL) {
+                        WOLFSSL_MSG("No client PSK callback set");
+                        ERROR_OUT(PSK_KEY_ERROR, exit_scke);
+                    }
+
+                #ifdef HAVE_CURVE25519
+                    if (ssl->peerX25519KeyPresent) {
+                        /* Check client ECC public key */
+                        if (!ssl->peerX25519Key || !ssl->peerX25519Key->dp) {
+                            ERROR_OUT(NO_PEER_KEY, exit_scke);
+                        }
+
+                    #ifdef HAVE_PK_CALLBACKS
+                        /* if callback then use it for shared secret */
+                        if (ssl->ctx->X25519SharedSecretCb != NULL) {
+                            break;
+                        }
+                    #endif
+
+                        /* create private key */
+                        ssl->hsType = DYNAMIC_TYPE_CURVE25519;
+                        ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+                        if (ret != 0) {
+                            goto exit_scke;
+                        }
+
+                        ret = X25519MakeKey(ssl, (curve25519_key*)ssl->hsKey,
+                                            ssl->peerX25519Key);
+                        break;
+                    }
+                #endif
+                #ifdef HAVE_CURVE448
+                    if (ssl->peerX448KeyPresent) {
+                        /* Check client ECC public key */
+                        if (!ssl->peerX448Key) {
+                            ERROR_OUT(NO_PEER_KEY, exit_scke);
+                        }
+
+                    #ifdef HAVE_PK_CALLBACKS
+                        /* if callback then use it for shared secret */
+                        if (ssl->ctx->X448SharedSecretCb != NULL) {
+                            break;
+                        }
+                    #endif
+
+                        /* create private key */
+                        ssl->hsType = DYNAMIC_TYPE_CURVE448;
+                        ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+                        if (ret != 0) {
+                            goto exit_scke;
+                        }
+
+                        ret = X448MakeKey(ssl, (curve448_key*)ssl->hsKey,
+                                          ssl->peerX448Key);
+                        break;
+                    }
+                #endif
+                    /* Check client ECC public key */
+                    if (!ssl->peerEccKey || !ssl->peerEccKeyPresent ||
+                                            !ssl->peerEccKey->dp) {
+                        ERROR_OUT(NO_PEER_KEY, exit_scke);
+                    }
+
+                #ifdef HAVE_PK_CALLBACKS
+                    /* if callback then use it for shared secret */
+                    if (ssl->ctx->EccSharedSecretCb != NULL) {
+                        break;
+                    }
+                #endif
+
+                    /* create ephemeral private key */
+                    ssl->hsType = DYNAMIC_TYPE_ECC;
+                    ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+                    if (ret != 0) {
+                        goto exit_scke;
+                    }
+
+                    ret = EccMakeKey(ssl, (ecc_key*)ssl->hsKey, ssl->peerEccKey);
+
+                    break;
+            #endif /* (HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448) && !NO_PSK */
+            #ifdef HAVE_NTRU
+                case ntru_kea:
+                    if (ssl->peerNtruKeyPresent == 0) {
+                        ERROR_OUT(NO_PEER_KEY, exit_scke);
+                    }
+                    break;
+            #endif /* HAVE_NTRU */
+            #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                                          defined(HAVE_CURVE448)
+                case ecc_diffie_hellman_kea:
+                {
+                #ifdef HAVE_ECC
+                    ecc_key* peerKey;
+                #endif
+
+            #ifdef HAVE_PK_CALLBACKS
+                    /* if callback then use it for shared secret */
+                #ifdef HAVE_CURVE25519
+                    if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+                        if (ssl->ctx->X25519SharedSecretCb != NULL)
+                            break;
+                    }
+                    else
+                #endif
+                #ifdef HAVE_CURVE448
+                    if (ssl->ecdhCurveOID == ECC_X448_OID) {
+                        if (ssl->ctx->X448SharedSecretCb != NULL)
+                            break;
+                    }
+                    else
+                #endif
+                    if (ssl->ctx->EccSharedSecretCb != NULL) {
+                        break;
+                    }
+            #endif /* HAVE_PK_CALLBACKS */
+
+                #ifdef HAVE_CURVE25519
+                    if (ssl->peerX25519KeyPresent) {
+                        if (!ssl->peerX25519Key || !ssl->peerX25519Key->dp) {
+                            ERROR_OUT(NO_PEER_KEY, exit_scke);
+                        }
+
+                        /* create private key */
+                        ssl->hsType = DYNAMIC_TYPE_CURVE25519;
+                        ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+                        if (ret != 0) {
+                            goto exit_scke;
+                        }
+
+                        ret = X25519MakeKey(ssl, (curve25519_key*)ssl->hsKey,
+                                            ssl->peerX25519Key);
+                        break;
+                    }
+                #endif
+                #ifdef HAVE_CURVE448
+                    if (ssl->peerX448KeyPresent) {
+                        if (!ssl->peerX448Key) {
+                            ERROR_OUT(NO_PEER_KEY, exit_scke);
+                        }
+
+                        /* create private key */
+                        ssl->hsType = DYNAMIC_TYPE_CURVE448;
+                        ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+                        if (ret != 0) {
+                            goto exit_scke;
+                        }
+
+                        ret = X448MakeKey(ssl, (curve448_key*)ssl->hsKey,
+                                          ssl->peerX448Key);
+                        break;
+                    }
+                #endif
+                #ifdef HAVE_ECC
+                    if (ssl->specs.static_ecdh) {
+                        /* Note: EccDsa is really fixed Ecc key here */
+                        if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent) {
+                            ERROR_OUT(NO_PEER_KEY, exit_scke);
+                        }
+                        peerKey = ssl->peerEccDsaKey;
+                    }
+                    else {
+                        if (!ssl->peerEccKey || !ssl->peerEccKeyPresent) {
+                            ERROR_OUT(NO_PEER_KEY, exit_scke);
+                        }
+                        peerKey = ssl->peerEccKey;
+                    }
+                    if (peerKey == NULL) {
+                        ERROR_OUT(NO_PEER_KEY, exit_scke);
+                    }
+
+                    /* create ephemeral private key */
+                    ssl->hsType = DYNAMIC_TYPE_ECC;
+                    ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+                    if (ret != 0) {
+                        goto exit_scke;
+                    }
+
+                    ret = EccMakeKey(ssl, (ecc_key*)ssl->hsKey, peerKey);
+                #endif
+
+                    break;
+                }
+            #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+
+                default:
+                    ret = BAD_KEA_TYPE_E;
+            } /* switch(ssl->specs.kea) */
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_scke;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_BUILD;
+        } /* case TLS_ASYNC_BEGIN */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_BUILD:
+        {
+            args->encSz = MAX_ENCRYPT_SZ;
+            args->encSecret = (byte*)XMALLOC(args->encSz, ssl->heap,
+                                                    DYNAMIC_TYPE_SECRET);
+            if (args->encSecret == NULL) {
+                ERROR_OUT(MEMORY_E, exit_scke);
+            }
+            if (ssl->arrays->preMasterSecret == NULL) {
+                ssl->arrays->preMasterSz = ENCRYPT_LEN;
+                ssl->arrays->preMasterSecret = (byte*)XMALLOC(ENCRYPT_LEN,
+                                                ssl->heap, DYNAMIC_TYPE_SECRET);
+                if (ssl->arrays->preMasterSecret == NULL) {
+                    ERROR_OUT(MEMORY_E, exit_scke);
+                }
+                XMEMSET(ssl->arrays->preMasterSecret, 0, ENCRYPT_LEN);
+            }
+
+            switch(ssl->specs.kea)
+            {
+            #ifndef NO_RSA
+                case rsa_kea:
+                {
+                    /* build PreMasterSecret with RNG data */
+                    #if defined(WOLFSSL_RENESAS_TSIP_TLS) && \
+                       !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION)
+                    if (tsip_useable(ssl)) {
+                        ret = tsip_generatePremasterSecret(
+                        &ssl->arrays->preMasterSecret[VERSION_SZ],
+                        ENCRYPT_LEN - VERSION_SZ);
+                    } else {
+                    #endif
+                        ret = wc_RNG_GenerateBlock(ssl->rng,
+                            &ssl->arrays->preMasterSecret[VERSION_SZ],
+                            SECRET_LEN - VERSION_SZ);
+                    #if defined(WOLFSSL_RENESAS_TSIP_TLS) && \
+                       !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION)
+                    }
+                    #endif
+                        if (ret != 0) {
+                            goto exit_scke;
+                        }
+
+                        ssl->arrays->preMasterSecret[0] = ssl->chVersion.major;
+                        ssl->arrays->preMasterSecret[1] = ssl->chVersion.minor;
+
+                    ssl->arrays->preMasterSz = SECRET_LEN;
+
+                    break;
+                }
+            #endif /* !NO_RSA */
+            #ifndef NO_DH
+                case diffie_hellman_kea:
+                {
+                    ssl->buffers.sig.length = ENCRYPT_LEN;
+                    ssl->buffers.sig.buffer = (byte*)XMALLOC(ENCRYPT_LEN,
+                                            ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+                    if (ssl->buffers.sig.buffer == NULL) {
+                        ERROR_OUT(MEMORY_E, exit_scke);
+                    }
+
+                    ret = AllocKey(ssl, DYNAMIC_TYPE_DH,
+                                            (void**)&ssl->buffers.serverDH_Key);
+                    if (ret != 0) {
+                        goto exit_scke;
+                    }
+
+                    #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \
+                        !defined(WOLFSSL_OLD_PRIME_CHECK)
+                    if (ssl->options.dhDoKeyTest &&
+                        !ssl->options.dhKeyTested)
+                    {
+                        ret = wc_DhSetCheckKey(ssl->buffers.serverDH_Key,
+                            ssl->buffers.serverDH_P.buffer,
+                            ssl->buffers.serverDH_P.length,
+                            ssl->buffers.serverDH_G.buffer,
+                            ssl->buffers.serverDH_G.length,
+                            NULL, 0, 0, ssl->rng);
+                        if (ret != 0) {
+                            goto exit_scke;
+                        }
+                        ssl->options.dhKeyTested = 1;
+                    }
+                    else
+                    #endif
+                    {
+                        ret = wc_DhSetKey(ssl->buffers.serverDH_Key,
+                            ssl->buffers.serverDH_P.buffer,
+                            ssl->buffers.serverDH_P.length,
+                            ssl->buffers.serverDH_G.buffer,
+                            ssl->buffers.serverDH_G.length);
+                        if (ret != 0) {
+                            goto exit_scke;
+                        }
+                    }
+
+                    /* for DH, encSecret is Yc, agree is pre-master */
+                    ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key,
+                        ssl->buffers.sig.buffer, (word32*)&ssl->buffers.sig.length,
+                        args->encSecret, &args->encSz);
+
+                    /* set the max agree result size */
+                    ssl->arrays->preMasterSz = ENCRYPT_LEN;
+                    break;
+                }
+            #endif /* !NO_DH */
+            #ifndef NO_PSK
+                case psk_kea:
+                {
+                    byte* pms = ssl->arrays->preMasterSecret;
+                    ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl,
+                        ssl->arrays->server_hint, ssl->arrays->client_identity,
+                        MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN);
+                    if (ssl->arrays->psk_keySz == 0 ||
+                        ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
+                        ERROR_OUT(PSK_KEY_ERROR, exit_scke);
+                    }
+                    ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; /* null term */
+                    args->encSz = (word32)XSTRLEN(ssl->arrays->client_identity);
+                    if (args->encSz > MAX_PSK_ID_LEN) {
+                        ERROR_OUT(CLIENT_ID_ERROR, exit_scke);
+                    }
+                    XMEMCPY(args->encSecret, ssl->arrays->client_identity,
+                                                                args->encSz);
+
+                    /* make psk pre master secret */
+                    /* length of key + length 0s + length of key + key */
+                    c16toa((word16)ssl->arrays->psk_keySz, pms);
+                    pms += OPAQUE16_LEN;
+                    XMEMSET(pms, 0, ssl->arrays->psk_keySz);
+                    pms += ssl->arrays->psk_keySz;
+                    c16toa((word16)ssl->arrays->psk_keySz, pms);
+                    pms += OPAQUE16_LEN;
+                    XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
+                    ssl->arrays->preMasterSz = (ssl->arrays->psk_keySz * 2) +
+                        (2 * OPAQUE16_LEN);
+                    ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz);
+                    ssl->arrays->psk_keySz = 0; /* No further need */
+                    break;
+                }
+            #endif /* !NO_PSK */
+            #if !defined(NO_DH) && !defined(NO_PSK)
+                case dhe_psk_kea:
+                {
+                    word32 esSz = 0;
+                    args->output = args->encSecret;
+
+                    ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl,
+                         ssl->arrays->server_hint, ssl->arrays->client_identity,
+                         MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN);
+                    if (ssl->arrays->psk_keySz == 0 ||
+                                     ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
+                        ERROR_OUT(PSK_KEY_ERROR, exit_scke);
+                    }
+                    ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; /* null term */
+                    esSz = (word32)XSTRLEN(ssl->arrays->client_identity);
+
+                    if (esSz > MAX_PSK_ID_LEN) {
+                        ERROR_OUT(CLIENT_ID_ERROR, exit_scke);
+                    }
+
+                    ssl->buffers.sig.length = ENCRYPT_LEN;
+                    ssl->buffers.sig.buffer = (byte*)XMALLOC(ENCRYPT_LEN,
+                                            ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+                    if (ssl->buffers.sig.buffer == NULL) {
+                        ERROR_OUT(MEMORY_E, exit_scke);
+                    }
+
+                    c16toa((word16)esSz, args->output);
+                    args->output += OPAQUE16_LEN;
+                    XMEMCPY(args->output, ssl->arrays->client_identity, esSz);
+                    args->output += esSz;
+                    args->encSz = esSz + OPAQUE16_LEN;
+
+                    args->length = 0;
+
+                    ret = AllocKey(ssl, DYNAMIC_TYPE_DH,
+                                            (void**)&ssl->buffers.serverDH_Key);
+                    if (ret != 0) {
+                        goto exit_scke;
+                    }
+
+                    #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \
+                        !defined(WOLFSSL_OLD_PRIME_CHECK)
+                    if (ssl->options.dhDoKeyTest &&
+                        !ssl->options.dhKeyTested)
+                    {
+                        ret = wc_DhSetCheckKey(ssl->buffers.serverDH_Key,
+                            ssl->buffers.serverDH_P.buffer,
+                            ssl->buffers.serverDH_P.length,
+                            ssl->buffers.serverDH_G.buffer,
+                            ssl->buffers.serverDH_G.length,
+                            NULL, 0, 0, ssl->rng);
+                        if (ret != 0) {
+                            goto exit_scke;
+                        }
+                        ssl->options.dhKeyTested = 1;
+                    }
+                    else
+                    #endif
+                    {
+                        ret = wc_DhSetKey(ssl->buffers.serverDH_Key,
+                            ssl->buffers.serverDH_P.buffer,
+                            ssl->buffers.serverDH_P.length,
+                            ssl->buffers.serverDH_G.buffer,
+                            ssl->buffers.serverDH_G.length);
+                        if (ret != 0) {
+                            goto exit_scke;
+                        }
+                    }
+
+                    /* for DH, encSecret is Yc, agree is pre-master */
+                    ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key,
+                        ssl->buffers.sig.buffer, (word32*)&ssl->buffers.sig.length,
+                        args->output + OPAQUE16_LEN, &args->length);
+                    break;
+                }
+            #endif /* !NO_DH && !NO_PSK */
+            #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                     defined(HAVE_CURVE448)) && !defined(NO_PSK)
+                case ecdhe_psk_kea:
+                {
+                    word32 esSz = 0;
+                    args->output = args->encSecret;
+
+                    /* Send PSK client identity */
+                    ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl,
+                         ssl->arrays->server_hint, ssl->arrays->client_identity,
+                         MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN);
+                    if (ssl->arrays->psk_keySz == 0 ||
+                                     ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
+                        ERROR_OUT(PSK_KEY_ERROR, exit_scke);
+                    }
+                    ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; /* null term */
+                    esSz = (word32)XSTRLEN(ssl->arrays->client_identity);
+                    if (esSz > MAX_PSK_ID_LEN) {
+                        ERROR_OUT(CLIENT_ID_ERROR, exit_scke);
+                    }
+
+                    /* place size and identity in output buffer sz:identity */
+                    c16toa((word16)esSz, args->output);
+                    args->output += OPAQUE16_LEN;
+                    XMEMCPY(args->output, ssl->arrays->client_identity, esSz);
+                    args->output += esSz;
+                    args->encSz = esSz + OPAQUE16_LEN;
+
+                    /* length is used for public key size */
+                    args->length = MAX_ENCRYPT_SZ;
+
+                    /* Create shared ECC key leaving room at the beginning
+                       of buffer for size of shared key. */
+                    ssl->arrays->preMasterSz = ENCRYPT_LEN - OPAQUE16_LEN;
+
+                #ifdef HAVE_CURVE25519
+                    if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+                    #ifdef HAVE_PK_CALLBACKS
+                        /* if callback then use it for shared secret */
+                        if (ssl->ctx->X25519SharedSecretCb != NULL) {
+                            break;
+                        }
+                    #endif
+
+                        ret = wc_curve25519_export_public_ex(
+                                (curve25519_key*)ssl->hsKey,
+                                args->output + OPAQUE8_LEN, &args->length,
+                                EC25519_LITTLE_ENDIAN);
+                        if (ret != 0) {
+                            ERROR_OUT(ECC_EXPORT_ERROR, exit_scke);
+                        }
+
+                        break;
+                    }
+                #endif
+                #ifdef HAVE_CURVE448
+                    if (ssl->ecdhCurveOID == ECC_X448_OID) {
+                    #ifdef HAVE_PK_CALLBACKS
+                        /* if callback then use it for shared secret */
+                        if (ssl->ctx->X448SharedSecretCb != NULL) {
+                            break;
+                        }
+                    #endif
+
+                        ret = wc_curve448_export_public_ex(
+                                (curve448_key*)ssl->hsKey,
+                                args->output + OPAQUE8_LEN, &args->length,
+                                EC448_LITTLE_ENDIAN);
+                        if (ret != 0) {
+                            ERROR_OUT(ECC_EXPORT_ERROR, exit_scke);
+                        }
+
+                        break;
+                    }
+                #endif
+                #ifdef HAVE_PK_CALLBACKS
+                    /* if callback then use it for shared secret */
+                    if (ssl->ctx->EccSharedSecretCb != NULL) {
+                        break;
+                    }
+                #endif
+
+                    /* Place ECC key in output buffer, leaving room for size */
+                    ret = wc_ecc_export_x963((ecc_key*)ssl->hsKey,
+                                    args->output + OPAQUE8_LEN, &args->length);
+                    if (ret != 0) {
+                        ERROR_OUT(ECC_EXPORT_ERROR, exit_scke);
+                    }
+
+                    break;
+                }
+            #endif /* (HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448) && !NO_PSK */
+            #ifdef HAVE_NTRU
+                case ntru_kea:
+                {
+                    ret = wc_RNG_GenerateBlock(ssl->rng,
+                                  ssl->arrays->preMasterSecret, SECRET_LEN);
+                    if (ret != 0) {
+                        goto exit_scke;
+                    }
+
+                    ssl->arrays->preMasterSz = SECRET_LEN;
+                    args->encSz = MAX_ENCRYPT_SZ;
+                    break;
+                }
+            #endif /* HAVE_NTRU */
+            #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                                          defined(HAVE_CURVE448)
+                case ecc_diffie_hellman_kea:
+                {
+                    ssl->arrays->preMasterSz = ENCRYPT_LEN;
+
+                #ifdef HAVE_CURVE25519
+                    if (ssl->hsType == DYNAMIC_TYPE_CURVE25519) {
+                    #ifdef HAVE_PK_CALLBACKS
+                        /* if callback then use it for shared secret */
+                        if (ssl->ctx->X25519SharedSecretCb != NULL) {
+                            break;
+                        }
+                    #endif
+
+                        ret = wc_curve25519_export_public_ex(
+                                (curve25519_key*)ssl->hsKey,
+                                args->encSecret + OPAQUE8_LEN, &args->encSz,
+                                EC25519_LITTLE_ENDIAN);
+                        if (ret != 0) {
+                            ERROR_OUT(ECC_EXPORT_ERROR, exit_scke);
+                        }
+
+                        break;
+                    }
+                #endif
+                #ifdef HAVE_CURVE448
+                    if (ssl->hsType == DYNAMIC_TYPE_CURVE448) {
+                    #ifdef HAVE_PK_CALLBACKS
+                        /* if callback then use it for shared secret */
+                        if (ssl->ctx->X448SharedSecretCb != NULL) {
+                            break;
+                        }
+                    #endif
+
+                        ret = wc_curve448_export_public_ex(
+                                (curve448_key*)ssl->hsKey,
+                                args->encSecret + OPAQUE8_LEN, &args->encSz,
+                                EC448_LITTLE_ENDIAN);
+                        if (ret != 0) {
+                            ERROR_OUT(ECC_EXPORT_ERROR, exit_scke);
+                        }
+
+                        break;
+                    }
+                #endif
+                #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)
+                #ifdef HAVE_PK_CALLBACKS
+                    /* if callback then use it for shared secret */
+                    if (ssl->ctx->EccSharedSecretCb != NULL) {
+                        break;
+                    }
+                #endif
+
+                    /* Place ECC key in buffer, leaving room for size */
+                    ret = wc_ecc_export_x963((ecc_key*)ssl->hsKey,
+                                args->encSecret + OPAQUE8_LEN, &args->encSz);
+                    if (ret != 0) {
+                        ERROR_OUT(ECC_EXPORT_ERROR, exit_scke);
+                    }
+                #endif /* HAVE_ECC */
+                    break;
+                }
+            #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+
+                default:
+                    ret = BAD_KEA_TYPE_E;
+            } /* switch(ssl->specs.kea) */
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_scke;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_DO;
+        } /* case TLS_ASYNC_BUILD */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_DO:
+        {
+            switch(ssl->specs.kea)
+            {
+            #ifndef NO_RSA
+                case rsa_kea:
+                {
+                    #if defined(WOLFSSL_RENESAS_TSIP_TLS) && \
+                       !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION)
+                    if (tsip_useable(ssl) &&
+                                     wc_RsaEncryptSize(ssl->peerRsaKey) == 256) {
+                        ret = tsip_generateEncryptPreMasterSecret(ssl,
+                                                            args->encSecret,
+                                                            &args->encSz);
+
+                    } else
+                    #endif
+                        ret = RsaEnc(ssl,
+                            ssl->arrays->preMasterSecret, SECRET_LEN,
+                            args->encSecret, &args->encSz,
+                            ssl->peerRsaKey,
+                        #if defined(HAVE_PK_CALLBACKS)
+                            &ssl->buffers.peerRsaKey
+                        #else
+                            NULL
+                        #endif
+                        );
+
+                    break;
+                }
+            #endif /* !NO_RSA */
+            #ifndef NO_DH
+                case diffie_hellman_kea:
+                {
+                    ret = DhAgree(ssl, ssl->buffers.serverDH_Key,
+                        ssl->buffers.sig.buffer, ssl->buffers.sig.length,
+                        ssl->buffers.serverDH_Pub.buffer,
+                        ssl->buffers.serverDH_Pub.length,
+                        ssl->arrays->preMasterSecret,
+                        &ssl->arrays->preMasterSz);
+                    break;
+                }
+            #endif /* !NO_DH */
+            #ifndef NO_PSK
+                case psk_kea:
+                {
+                    break;
+                }
+            #endif /* !NO_PSK */
+            #if !defined(NO_DH) && !defined(NO_PSK)
+                case dhe_psk_kea:
+                {
+                    ret = DhAgree(ssl, ssl->buffers.serverDH_Key,
+                        ssl->buffers.sig.buffer, ssl->buffers.sig.length,
+                        ssl->buffers.serverDH_Pub.buffer,
+                        ssl->buffers.serverDH_Pub.length,
+                        ssl->arrays->preMasterSecret + OPAQUE16_LEN,
+                        &ssl->arrays->preMasterSz);
+                    break;
+                }
+            #endif /* !NO_DH && !NO_PSK */
+            #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                     defined(HAVE_CURVE448)) && !defined(NO_PSK)
+                case ecdhe_psk_kea:
+                {
+                #ifdef HAVE_CURVE25519
+                    if (ssl->peerX25519KeyPresent) {
+                        ret = X25519SharedSecret(ssl,
+                            (curve25519_key*)ssl->hsKey, ssl->peerX25519Key,
+                            args->output + OPAQUE8_LEN, &args->length,
+                            ssl->arrays->preMasterSecret + OPAQUE16_LEN,
+                            &ssl->arrays->preMasterSz,
+                            WOLFSSL_CLIENT_END
+                        );
+                        if (!ssl->specs.static_ecdh
+                        #ifdef WOLFSSL_ASYNC_CRYPT
+                            && ret != WC_PENDING_E
+                        #endif
+                        ) {
+                            FreeKey(ssl, DYNAMIC_TYPE_CURVE25519,
+                                                   (void**)&ssl->peerX25519Key);
+                            ssl->peerX25519KeyPresent = 0;
+                        }
+                        break;
+                    }
+                #endif
+                #ifdef HAVE_CURVE448
+                    if (ssl->peerX448KeyPresent) {
+                        ret = X448SharedSecret(ssl,
+                            (curve448_key*)ssl->hsKey, ssl->peerX448Key,
+                            args->output + OPAQUE8_LEN, &args->length,
+                            ssl->arrays->preMasterSecret + OPAQUE16_LEN,
+                            &ssl->arrays->preMasterSz,
+                            WOLFSSL_CLIENT_END
+                        );
+                        if (!ssl->specs.static_ecdh
+                        #ifdef WOLFSSL_ASYNC_CRYPT
+                            && ret != WC_PENDING_E
+                        #endif
+                        ) {
+                            FreeKey(ssl, DYNAMIC_TYPE_CURVE448,
+                                                     (void**)&ssl->peerX448Key);
+                            ssl->peerX448KeyPresent = 0;
+                        }
+                        break;
+                    }
+                #endif
+                    ret = EccSharedSecret(ssl,
+                        (ecc_key*)ssl->hsKey, ssl->peerEccKey,
+                        args->output + OPAQUE8_LEN, &args->length,
+                        ssl->arrays->preMasterSecret + OPAQUE16_LEN,
+                        &ssl->arrays->preMasterSz,
+                        WOLFSSL_CLIENT_END
+                    );
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    if (ret != WC_PENDING_E)
+                #endif
+                    {
+                        FreeKey(ssl, DYNAMIC_TYPE_ECC,
+                                                      (void**)&ssl->peerEccKey);
+                        ssl->peerEccKeyPresent = 0;
+                    }
+                    break;
+                }
+            #endif /* (HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448) && !NO_PSK */
+            #ifdef HAVE_NTRU
+                case ntru_kea:
+                {
+                    word32 rc;
+                    word16 tmpEncSz = (word16)args->encSz;
+                    DRBG_HANDLE drbg;
+
+                    rc = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg);
+                    if (rc != DRBG_OK) {
+                        ERROR_OUT(NTRU_DRBG_ERROR, exit_scke);
+                    }
+                    rc = ntru_crypto_ntru_encrypt(drbg, ssl->peerNtruKeyLen,
+                                                  ssl->peerNtruKey,
+                                                  ssl->arrays->preMasterSz,
+                                                  ssl->arrays->preMasterSecret,
+                                                  &tmpEncSz,
+                                                  args->encSecret);
+                    args->encSz = tmpEncSz;
+                    ntru_crypto_drbg_uninstantiate(drbg);
+                    if (rc != NTRU_OK) {
+                        ERROR_OUT(NTRU_ENCRYPT_ERROR, exit_scke);
+                    }
+                    ret = 0;
+                    break;
+                }
+            #endif /* HAVE_NTRU */
+            #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                                          defined(HAVE_CURVE448)
+                case ecc_diffie_hellman_kea:
+                {
+                #ifdef HAVE_ECC
+                    ecc_key* peerKey;
+                #endif
+
+                #ifdef HAVE_CURVE25519
+                    if (ssl->peerX25519KeyPresent) {
+                        ret = X25519SharedSecret(ssl,
+                            (curve25519_key*)ssl->hsKey, ssl->peerX25519Key,
+                            args->encSecret + OPAQUE8_LEN, &args->encSz,
+                            ssl->arrays->preMasterSecret,
+                            &ssl->arrays->preMasterSz,
+                            WOLFSSL_CLIENT_END
+                        );
+                        if (!ssl->specs.static_ecdh
+                        #ifdef WOLFSSL_ASYNC_CRYPT
+                            && ret != WC_PENDING_E
+                        #endif
+                        ) {
+                            FreeKey(ssl, DYNAMIC_TYPE_CURVE25519,
+                                                   (void**)&ssl->peerX25519Key);
+                            ssl->peerX25519KeyPresent = 0;
+                        }
+                        break;
+                    }
+                #endif
+                #ifdef HAVE_CURVE448
+                    if (ssl->peerX448KeyPresent) {
+                        ret = X448SharedSecret(ssl,
+                            (curve448_key*)ssl->hsKey, ssl->peerX448Key,
+                            args->encSecret + OPAQUE8_LEN, &args->encSz,
+                            ssl->arrays->preMasterSecret,
+                            &ssl->arrays->preMasterSz,
+                            WOLFSSL_CLIENT_END
+                        );
+                        if (!ssl->specs.static_ecdh
+                        #ifdef WOLFSSL_ASYNC_CRYPT
+                            && ret != WC_PENDING_E
+                        #endif
+                        ) {
+                            FreeKey(ssl, DYNAMIC_TYPE_CURVE448,
+                                                     (void**)&ssl->peerX448Key);
+                            ssl->peerX448KeyPresent = 0;
+                        }
+                        break;
+                    }
+                #endif
+                #ifdef HAVE_ECC
+                    peerKey = (ssl->specs.static_ecdh) ?
+                              ssl->peerEccDsaKey : ssl->peerEccKey;
+
+                    ret = EccSharedSecret(ssl,
+                        (ecc_key*)ssl->hsKey, peerKey,
+                        args->encSecret + OPAQUE8_LEN, &args->encSz,
+                        ssl->arrays->preMasterSecret,
+                        &ssl->arrays->preMasterSz,
+                        WOLFSSL_CLIENT_END
+                    );
+                    if (!ssl->specs.static_ecdh
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                        && ret != WC_PENDING_E
+                #endif
+                     && !ssl->options.keepResources) {
+                        FreeKey(ssl, DYNAMIC_TYPE_ECC,
+                                                      (void**)&ssl->peerEccKey);
+                        ssl->peerEccKeyPresent = 0;
+                    }
+                #endif
+
+                    break;
+                }
+            #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+
+                default:
+                    ret = BAD_KEA_TYPE_E;
+            } /* switch(ssl->specs.kea) */
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_scke;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_VERIFY;
+        } /* case TLS_ASYNC_DO */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_VERIFY:
+        {
+            switch(ssl->specs.kea)
+            {
+            #ifndef NO_RSA
+                case rsa_kea:
+                {
+                    break;
+                }
+            #endif /* !NO_RSA */
+            #ifndef NO_DH
+                case diffie_hellman_kea:
+                {
+                    break;
+                }
+            #endif /* !NO_DH */
+            #ifndef NO_PSK
+                case psk_kea:
+                {
+                    break;
+                }
+            #endif /* !NO_PSK */
+            #if !defined(NO_DH) && !defined(NO_PSK)
+                case dhe_psk_kea:
+                {
+                    byte* pms = ssl->arrays->preMasterSecret;
+
+                    /* validate args */
+                    if (args->output == NULL || args->length == 0) {
+                        ERROR_OUT(BAD_FUNC_ARG, exit_scke);
+                    }
+
+                    c16toa((word16)args->length, args->output);
+                    args->encSz += args->length + OPAQUE16_LEN;
+                    c16toa((word16)ssl->arrays->preMasterSz, pms);
+                    ssl->arrays->preMasterSz += OPAQUE16_LEN;
+                    pms += ssl->arrays->preMasterSz;
+
+                    /* make psk pre master secret */
+                    /* length of key + length 0s + length of key + key */
+                    c16toa((word16)ssl->arrays->psk_keySz, pms);
+                    pms += OPAQUE16_LEN;
+                    XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
+                    ssl->arrays->preMasterSz +=
+                                         ssl->arrays->psk_keySz + OPAQUE16_LEN;
+                    ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz);
+                    ssl->arrays->psk_keySz = 0; /* No further need */
+                    break;
+                }
+            #endif /* !NO_DH && !NO_PSK */
+            #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                     defined(HAVE_CURVE448)) && !defined(NO_PSK)
+                case ecdhe_psk_kea:
+                {
+                    byte* pms = ssl->arrays->preMasterSecret;
+
+                    /* validate args */
+                    if (args->output == NULL || args->length > ENCRYPT_LEN) {
+                        ERROR_OUT(BAD_FUNC_ARG, exit_scke);
+                    }
+
+                    /* place size of public key in output buffer */
+                    *args->output = (byte)args->length;
+                    args->encSz += args->length + OPAQUE8_LEN;
+
+                    /* Create pre master secret is the concatenation of
+                       eccSize + eccSharedKey + pskSize + pskKey */
+                    c16toa((word16)ssl->arrays->preMasterSz, pms);
+                    ssl->arrays->preMasterSz += OPAQUE16_LEN;
+                    pms += ssl->arrays->preMasterSz;
+
+                    c16toa((word16)ssl->arrays->psk_keySz, pms);
+                    pms += OPAQUE16_LEN;
+                    XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
+                    ssl->arrays->preMasterSz +=
+                                          ssl->arrays->psk_keySz + OPAQUE16_LEN;
+
+                    ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz);
+                    ssl->arrays->psk_keySz = 0; /* No further need */
+                    break;
+                }
+            #endif /* (HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448) && !NO_PSK */
+            #ifdef HAVE_NTRU
+                case ntru_kea:
+                {
+                    break;
+                }
+            #endif /* HAVE_NTRU */
+            #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                                          defined(HAVE_CURVE448)
+                case ecc_diffie_hellman_kea:
+                {
+                    /* place size of public key in buffer */
+                    *args->encSecret = (byte)args->encSz;
+                    args->encSz += OPAQUE8_LEN;
+                    break;
+                }
+            #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+
+                default:
+                    ret = BAD_KEA_TYPE_E;
+            } /* switch(ssl->specs.kea) */
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_scke;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_FINALIZE;
+        } /* case TLS_ASYNC_VERIFY */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_FINALIZE:
+        {
+            word32 tlsSz = 0;
+            word32 idx = 0;
+
+        #ifdef HAVE_QSH
+            word32 qshSz = 0;
+            if (ssl->peerQSHKeyPresent) {
+                qshSz = QSH_KeyGetSize(ssl);
+            }
+        #endif
+
+            if (ssl->options.tls || ssl->specs.kea == diffie_hellman_kea) {
+                tlsSz = 2;
+            }
+
+            if (ssl->specs.kea == ecc_diffie_hellman_kea ||
+                ssl->specs.kea == dhe_psk_kea ||
+                ssl->specs.kea == ecdhe_psk_kea) { /* always off */
+                tlsSz = 0;
+            }
+
+            idx = HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+            args->sendSz = args->encSz + tlsSz + idx;
+
+        #ifdef WOLFSSL_DTLS
+            if (ssl->options.dtls) {
+                idx    += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
+                args->sendSz += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
+            }
+        #endif
+
+            if (IsEncryptionOn(ssl, 1)) {
+                args->sendSz += MAX_MSG_EXTRA;
+            }
+
+        #ifdef HAVE_QSH
+            args->encSz += qshSz;
+            args->sendSz += qshSz;
+        #endif
+
+            /* check for available size */
+            if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
+                goto exit_scke;
+            }
+
+            /* get output buffer */
+            args->output = ssl->buffers.outputBuffer.buffer +
+                           ssl->buffers.outputBuffer.length;
+
+        #ifdef HAVE_QSH
+            if (ssl->peerQSHKeyPresent) {
+                byte idxSave = idx;
+                idx = args->sendSz - qshSz;
+
+                if (QSH_KeyExchangeWrite(ssl, 0) != 0) {
+                    ERROR_OUT(MEMORY_E, exit_scke);
+                }
+
+                /* extension type */
+                c16toa(TLSX_QUANTUM_SAFE_HYBRID, args->output + idx);
+                idx += OPAQUE16_LEN;
+
+                /* write to output and check amount written */
+                if (TLSX_QSHPK_Write(ssl->QSH_secret->list,
+                            args->output + idx) > qshSz - OPAQUE16_LEN) {
+                    ERROR_OUT(MEMORY_E, exit_scke);
+                }
+
+                idx = idxSave;
+            }
+        #endif
+
+            AddHeaders(args->output, args->encSz + tlsSz, client_key_exchange, ssl);
+
+        #ifdef HAVE_QSH
+            if (ssl->peerQSHKeyPresent) {
+                args->encSz -= qshSz;
+            }
+        #endif
+            if (tlsSz) {
+                c16toa((word16)args->encSz, &args->output[idx]);
+                idx += OPAQUE16_LEN;
+            }
+            XMEMCPY(args->output + idx, args->encSecret, args->encSz);
+            idx += args->encSz;
+
+            if (IsEncryptionOn(ssl, 1)) {
+                args->inputSz = idx - RECORD_HEADER_SZ; /* buildmsg adds rechdr */
+                args->input = (byte*)XMALLOC(args->inputSz, ssl->heap,
+                                                       DYNAMIC_TYPE_IN_BUFFER);
+                if (args->input == NULL) {
+                    ERROR_OUT(MEMORY_E, exit_scke);
+                }
+
+                XMEMCPY(args->input, args->output + RECORD_HEADER_SZ,
+                                                                args->inputSz);
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_END;
+        } /* case TLS_ASYNC_FINALIZE */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_END:
+        {
+            if (IsEncryptionOn(ssl, 1)) {
+                ret = BuildMessage(ssl, args->output, args->sendSz,
+                            args->input, args->inputSz, handshake, 1, 0, 0);
+                XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+                args->input = NULL; /* make sure its not double free'd on cleanup */
+
+                if (ret >= 0) {
+                    args->sendSz = ret;
+                    ret = 0;
+                }
+            }
+            else {
+            #ifdef WOLFSSL_DTLS
+                if (ssl->options.dtls)
+                    DtlsSEQIncrement(ssl, CUR_ORDER);
+            #endif
+                ret = HashOutput(ssl, args->output, args->sendSz, 0);
+            }
+
+            if (ret != 0) {
+                goto exit_scke;
+            }
+
+        #ifdef WOLFSSL_DTLS
+            if (IsDtlsNotSctpMode(ssl)) {
+                if ((ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz)) != 0) {
+                    goto exit_scke;
+                }
+            }
+        #endif
+
+        #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+            if (ssl->hsInfoOn)
+                AddPacketName(ssl, "ClientKeyExchange");
+            if (ssl->toInfoOn)
+                AddPacketInfo(ssl, "ClientKeyExchange", handshake,
+                            args->output, args->sendSz, WRITE_PROTO, ssl->heap);
+        #endif
+
+            ssl->buffers.outputBuffer.length += args->sendSz;
+
+            if (!ssl->options.groupMessages) {
+                ret = SendBuffered(ssl);
+            }
+            if (ret == 0 || ret == WANT_WRITE) {
+                int tmpRet = MakeMasterSecret(ssl);
+                if (tmpRet != 0) {
+                    ret = tmpRet;   /* save WANT_WRITE unless more serious */
+                }
+                ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
+            }
+            break;
+        }
+        default:
+            ret = INPUT_CASE_ERROR;
+    } /* switch(ssl->options.asyncState) */
+
+exit_scke:
+
+    WOLFSSL_LEAVE("SendClientKeyExchange", ret);
+    WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND);
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* Handle async operation */
+    if (ret == WC_PENDING_E)
+        return ret;
+#endif
+
+    /* No further need for PMS */
+    if (ssl->arrays->preMasterSecret != NULL) {
+        ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz);
+    }
+    ssl->arrays->preMasterSz = 0;
+
+    /* Final cleanup */
+    FreeSckeArgs(ssl, args);
+    FreeKeyExchange(ssl);
+
+    return ret;
+}
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#ifndef NO_CERTS
+
+#ifdef HAVE_PK_CALLBACKS
+    int GetPrivateKeySigSize(WOLFSSL* ssl)
+    {
+        int sigSz = 0;
+
+        if (ssl == NULL)
+            return 0;
+
+        switch (ssl->buffers.keyType) {
+        #ifndef NO_RSA
+        #ifdef WC_RSA_PSS
+            case rsa_pss_sa_algo:
+        #endif
+            case rsa_sa_algo:
+                sigSz = ssl->buffers.keySz;
+                ssl->hsType = DYNAMIC_TYPE_RSA;
+                break;
+        #endif
+        #ifdef HAVE_ECC
+            case ecc_dsa_sa_algo:
+                sigSz = wc_ecc_sig_size_calc(ssl->buffers.keySz);
+                ssl->hsType = DYNAMIC_TYPE_ECC;
+                break;
+        #endif
+        #ifdef HAVE_ED25519
+            case ed25519_sa_algo:
+                sigSz = ED25519_SIG_SIZE; /* fixed known value */
+                ssl->hsType = DYNAMIC_TYPE_ED25519;
+                break;
+        #endif
+        #ifdef HAVE_ED448
+            case ed448_sa_algo:
+                sigSz = ED448_SIG_SIZE; /* fixed known value */
+                ssl->hsType = DYNAMIC_TYPE_ED448;
+                break;
+        #endif
+            default:
+                break;
+        }
+        return sigSz;
+    }
+#endif /* HAVE_PK_CALLBACKS */
+
+#ifndef WOLFSSL_NO_TLS12
+
+#ifndef WOLFSSL_NO_CLIENT_AUTH
+typedef struct ScvArgs {
+    byte*  output; /* not allocated */
+#ifndef NO_RSA
+    byte*  verifySig;
+#endif
+    byte*  verify; /* not allocated */
+    byte*  input;
+    word32 idx;
+    word32 extraSz;
+    word32 sigSz;
+    int    sendSz;
+    int    inputSz;
+    word16 length;
+    byte   sigAlgo;
+} ScvArgs;
+
+static void FreeScvArgs(WOLFSSL* ssl, void* pArgs)
+{
+    ScvArgs* args = (ScvArgs*)pArgs;
+
+    (void)ssl;
+
+#ifndef NO_RSA
+    if (args->verifySig) {
+        XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+        args->verifySig = NULL;
+    }
+#endif
+    if (args->input) {
+        XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+        args->input = NULL;
+    }
+}
+
+/* handle generation of certificate_verify (15) */
+int SendCertificateVerify(WOLFSSL* ssl)
+{
+    int ret = 0;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ScvArgs* args = (ScvArgs*)ssl->async.args;
+    typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+    (void)sizeof(args_test);
+#else
+    ScvArgs  args[1];
+#endif
+
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_VERIFY_SEND);
+    WOLFSSL_ENTER("SendCertificateVerify");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
+    if (ret != WC_NOT_PENDING_E) {
+        /* Check for error */
+        if (ret < 0)
+            goto exit_scv;
+    }
+    else
+#endif
+    {
+        /* Reset state */
+        ret = 0;
+        ssl->options.asyncState = TLS_ASYNC_BEGIN;
+        XMEMSET(args, 0, sizeof(ScvArgs));
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        ssl->async.freeArgs = FreeScvArgs;
+    #endif
+    }
+
+    switch(ssl->options.asyncState)
+    {
+        case TLS_ASYNC_BEGIN:
+        {
+            if (ssl->options.sendVerify == SEND_BLANK_CERT) {
+                return 0;  /* sent blank cert, can't verify */
+            }
+
+            args->sendSz = MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA;
+            if (IsEncryptionOn(ssl, 1)) {
+                args->sendSz += MAX_MSG_EXTRA;
+            }
+
+            /* check for available size */
+            if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
+                goto exit_scv;
+            }
+
+            /* get output buffer */
+            args->output = ssl->buffers.outputBuffer.buffer +
+                           ssl->buffers.outputBuffer.length;
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_BUILD;
+        } /* case TLS_ASYNC_BEGIN */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_BUILD:
+        {
+            ret = BuildCertHashes(ssl, &ssl->hsHashes->certHashes);
+            if (ret != 0) {
+                goto exit_scv;
+            }
+
+            if (ssl->buffers.key == NULL) {
+            #ifdef HAVE_PK_CALLBACKS
+                if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx))
+                    args->length = GetPrivateKeySigSize(ssl);
+                else
+            #endif
+                    ERROR_OUT(NO_PRIVATE_KEY, exit_scv);
+            }
+            else {
+                /* Decode private key. */
+                ret = DecodePrivateKey(ssl, &args->length);
+                if (ret != 0) {
+                    goto exit_scv;
+                }
+            }
+
+            if (args->length == 0) {
+                ERROR_OUT(NO_PRIVATE_KEY, exit_scv);
+            }
+
+            /* idx is used to track verify pointer offset to output */
+            args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+            args->verify = &args->output[RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ];
+            args->extraSz = 0;  /* tls 1.2 hash/sig */
+
+            /* build encoded signature buffer */
+            ssl->buffers.sig.length = MAX_ENCODED_SIG_SZ;
+            ssl->buffers.sig.buffer = (byte*)XMALLOC(ssl->buffers.sig.length,
+                                        ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+            if (ssl->buffers.sig.buffer == NULL) {
+                ERROR_OUT(MEMORY_E, exit_scv);
+            }
+
+        #ifdef WOLFSSL_DTLS
+            if (ssl->options.dtls) {
+                args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+                args->verify += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+            }
+        #endif
+
+    #ifndef NO_OLD_TLS
+        #ifndef NO_SHA
+            /* old tls default */
+            SetDigest(ssl, sha_mac);
+        #endif
+    #else
+        #ifndef NO_SHA256
+            /* new tls default */
+            SetDigest(ssl, sha256_mac);
+        #endif
+    #endif /* !NO_OLD_TLS */
+
+            if (ssl->hsType == DYNAMIC_TYPE_RSA) {
+        #ifdef WC_RSA_PSS
+                if (IsAtLeastTLSv1_2(ssl) &&
+                                (ssl->pssAlgo & (1 << ssl->suites->hashAlgo))) {
+                    args->sigAlgo = rsa_pss_sa_algo;
+                }
+                else
+        #endif
+                    args->sigAlgo = rsa_sa_algo;
+            }
+            else if (ssl->hsType == DYNAMIC_TYPE_ECC)
+                args->sigAlgo = ecc_dsa_sa_algo;
+            else if (ssl->hsType == DYNAMIC_TYPE_ED25519)
+                args->sigAlgo = ed25519_sa_algo;
+            else if (ssl->hsType == DYNAMIC_TYPE_ED448)
+                args->sigAlgo = ed448_sa_algo;
+
+            if (IsAtLeastTLSv1_2(ssl)) {
+                EncodeSigAlg(ssl->suites->hashAlgo, args->sigAlgo,
+                             args->verify);
+                args->extraSz = HASH_SIG_SIZE;
+                SetDigest(ssl, ssl->suites->hashAlgo);
+            }
+        #ifndef NO_OLD_TLS
+            else {
+                /* if old TLS load MD5 and SHA hash as value to sign */
+                XMEMCPY(ssl->buffers.sig.buffer,
+                    (byte*)ssl->hsHashes->certHashes.md5, FINISHED_SZ);
+            }
+        #endif
+
+        #ifndef NO_RSA
+            if (args->sigAlgo == rsa_sa_algo) {
+                ssl->buffers.sig.length = FINISHED_SZ;
+                args->sigSz = ENCRYPT_LEN;
+
+                if (IsAtLeastTLSv1_2(ssl)) {
+                    ssl->buffers.sig.length = wc_EncodeSignature(
+                            ssl->buffers.sig.buffer, ssl->buffers.digest.buffer,
+                            ssl->buffers.digest.length,
+                            TypeHash(ssl->suites->hashAlgo));
+                }
+
+                /* prepend hdr */
+                c16toa(args->length, args->verify + args->extraSz);
+            }
+            #ifdef WC_RSA_PSS
+            else if (args->sigAlgo == rsa_pss_sa_algo) {
+                XMEMCPY(ssl->buffers.sig.buffer, ssl->buffers.digest.buffer,
+                        ssl->buffers.digest.length);
+                ssl->buffers.sig.length = ssl->buffers.digest.length;
+                args->sigSz = ENCRYPT_LEN;
+
+                /* prepend hdr */
+                c16toa(args->length, args->verify + args->extraSz);
+            }
+            #endif
+        #endif /* !NO_RSA */
+        #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
+            if (args->sigAlgo == ed25519_sa_algo) {
+                ret = Ed25519CheckPubKey(ssl);
+                if (ret != 0)
+                    goto exit_scv;
+            }
+        #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
+        #if defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)
+            if (args->sigAlgo == ed448_sa_algo) {
+                ret = Ed448CheckPubKey(ssl);
+                if (ret != 0)
+                    goto exit_scv;
+            }
+        #endif /* HAVE_ED448 && !NO_ED448_CLIENT_AUTH */
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_DO;
+        } /* case TLS_ASYNC_BUILD */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_DO:
+        {
+        #ifdef HAVE_ECC
+           if (ssl->hsType == DYNAMIC_TYPE_ECC) {
+                ecc_key* key = (ecc_key*)ssl->hsKey;
+
+                ret = EccSign(ssl,
+                    ssl->buffers.digest.buffer, ssl->buffers.digest.length,
+                    ssl->buffers.sig.buffer, (word32*)&ssl->buffers.sig.length,
+                    key,
+            #ifdef HAVE_PK_CALLBACKS
+                    ssl->buffers.key
+            #else
+                    NULL
+            #endif
+                );
+            }
+        #endif /* HAVE_ECC */
+        #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
+           if (ssl->hsType == DYNAMIC_TYPE_ED25519) {
+                ed25519_key* key = (ed25519_key*)ssl->hsKey;
+
+                ret = Ed25519Sign(ssl,
+                    ssl->hsHashes->messages, ssl->hsHashes->length,
+                    ssl->buffers.sig.buffer, (word32*)&ssl->buffers.sig.length,
+                    key,
+            #ifdef HAVE_PK_CALLBACKS
+                    ssl->buffers.key
+            #else
+                    NULL
+            #endif
+                );
+            }
+        #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
+        #if defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)
+           if (ssl->hsType == DYNAMIC_TYPE_ED448) {
+                ed448_key* key = (ed448_key*)ssl->hsKey;
+
+                ret = Ed448Sign(ssl,
+                    ssl->hsHashes->messages, ssl->hsHashes->length,
+                    ssl->buffers.sig.buffer, (word32*)&ssl->buffers.sig.length,
+                    key,
+            #ifdef HAVE_PK_CALLBACKS
+                    ssl->buffers.key
+            #else
+                    NULL
+            #endif
+                );
+            }
+        #endif /* HAVE_ED448 && !NO_ED448_CLIENT_AUTH */
+        #ifndef NO_RSA
+            if (ssl->hsType == DYNAMIC_TYPE_RSA) {
+                RsaKey* key = (RsaKey*)ssl->hsKey;
+
+                /* restore verify pointer */
+                args->verify = &args->output[args->idx];
+
+                ret = RsaSign(ssl,
+                    ssl->buffers.sig.buffer, ssl->buffers.sig.length,
+                    args->verify + args->extraSz + VERIFY_HEADER, &args->sigSz,
+                    args->sigAlgo, ssl->suites->hashAlgo, key,
+                    ssl->buffers.key
+                );
+            }
+        #endif /* !NO_RSA */
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_scv;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_VERIFY;
+        } /* case TLS_ASYNC_DO */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_VERIFY:
+        {
+            /* restore verify pointer */
+            args->verify = &args->output[args->idx];
+
+            switch (ssl->hsType) {
+        #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
+            #ifdef HAVE_ECC
+                case DYNAMIC_TYPE_ECC:
+            #endif
+            #ifdef HAVE_ED25519
+                case DYNAMIC_TYPE_ED25519:
+            #endif
+            #ifdef HAVE_ED448
+                case DYNAMIC_TYPE_ED448:
+            #endif
+                    args->length = (word16)ssl->buffers.sig.length;
+                    /* prepend hdr */
+                    c16toa(args->length, args->verify + args->extraSz);
+                    XMEMCPY(args->verify + args->extraSz + VERIFY_HEADER,
+                            ssl->buffers.sig.buffer, ssl->buffers.sig.length);
+                    break;
+        #endif
+            #ifndef NO_RSA
+                case DYNAMIC_TYPE_RSA:
+                {
+                    RsaKey* key = (RsaKey*)ssl->hsKey;
+
+                    if (args->verifySig == NULL) {
+                        args->verifySig = (byte*)XMALLOC(args->sigSz, ssl->heap,
+                                          DYNAMIC_TYPE_SIGNATURE);
+                        if (args->verifySig == NULL) {
+                            ERROR_OUT(MEMORY_E, exit_scv);
+                        }
+                        XMEMCPY(args->verifySig, args->verify + args->extraSz +
+                                                    VERIFY_HEADER, args->sigSz);
+                    }
+
+                    /* check for signature faults */
+                    ret = VerifyRsaSign(ssl,
+                        args->verifySig, args->sigSz,
+                        ssl->buffers.sig.buffer, ssl->buffers.sig.length,
+                        args->sigAlgo, ssl->suites->hashAlgo, key,
+                        ssl->buffers.key
+                    );
+                    break;
+                }
+            #endif /* !NO_RSA */
+                default:
+                    break;
+            }
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_scv;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_FINALIZE;
+        } /* case TLS_ASYNC_VERIFY */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_FINALIZE:
+        {
+            if (args->output == NULL) {
+                ERROR_OUT(BUFFER_ERROR, exit_scv);
+            }
+            AddHeaders(args->output, (word32)args->length + args->extraSz +
+                                        VERIFY_HEADER, certificate_verify, ssl);
+
+            args->sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ +
+                           (word32)args->length + args->extraSz + VERIFY_HEADER;
+
+        #ifdef WOLFSSL_DTLS
+            if (ssl->options.dtls) {
+                args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+            }
+        #endif
+
+            if (IsEncryptionOn(ssl, 1)) {
+                args->inputSz = args->sendSz - RECORD_HEADER_SZ;
+                                /* build msg adds rec hdr */
+                args->input = (byte*)XMALLOC(args->inputSz, ssl->heap,
+                                                       DYNAMIC_TYPE_IN_BUFFER);
+                if (args->input == NULL) {
+                    ERROR_OUT(MEMORY_E, exit_scv);
+                }
+
+                XMEMCPY(args->input, args->output + RECORD_HEADER_SZ,
+                                                                args->inputSz);
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_END;
+        } /* case TLS_ASYNC_FINALIZE */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_END:
+        {
+            if (IsEncryptionOn(ssl, 1)) {
+                ret = BuildMessage(ssl, args->output,
+                                      MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA,
+                                      args->input, args->inputSz, handshake,
+                                      1, 0, 1);
+            #ifdef WOLFSSL_ASYNC_CRYPT
+                if (ret == WC_PENDING_E)
+                    goto exit_scv;
+            #endif
+
+                XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+                args->input = NULL;  /* make sure its not double free'd on cleanup */
+
+                if (ret >= 0) {
+                    args->sendSz = ret;
+                    ret = 0;
+                }
+            }
+            else {
+            #ifdef WOLFSSL_DTLS
+                if (ssl->options.dtls)
+                    DtlsSEQIncrement(ssl, CUR_ORDER);
+            #endif
+                ret = HashOutput(ssl, args->output, args->sendSz, 0);
+            }
+
+            if (ret != 0) {
+                goto exit_scv;
+            }
+
+        #ifdef WOLFSSL_DTLS
+            if (IsDtlsNotSctpMode(ssl)) {
+                ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz);
+            }
+        #endif
+
+
+        #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+            if (ssl->hsInfoOn)
+                AddPacketName(ssl, "CertificateVerify");
+            if (ssl->toInfoOn)
+                AddPacketInfo(ssl, "CertificateVerify", handshake,
+                            args->output, args->sendSz, WRITE_PROTO, ssl->heap);
+        #endif
+
+            ssl->buffers.outputBuffer.length += args->sendSz;
+
+            if (!ssl->options.groupMessages) {
+                ret = SendBuffered(ssl);
+            }
+            break;
+        }
+        default:
+            ret = INPUT_CASE_ERROR;
+    } /* switch(ssl->options.asyncState) */
+
+exit_scv:
+
+    WOLFSSL_LEAVE("SendCertificateVerify", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_SEND);
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* Handle async operation */
+    if (ret == WC_PENDING_E) {
+        return ret;
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    /* Digest is not allocated, so do this to prevent free */
+    ssl->buffers.digest.buffer = NULL;
+    ssl->buffers.digest.length = 0;
+
+    /* Final cleanup */
+    FreeScvArgs(ssl, args);
+    FreeKeyExchange(ssl);
+
+    return ret;
+}
+#endif /* WOLFSSL_NO_CLIENT_AUTH */
+
+#endif /* WOLFSSL_NO_TLS12 */
+
+#endif /* NO_CERTS */
+
+
+#ifdef HAVE_SESSION_TICKET
+int SetTicket(WOLFSSL* ssl, const byte* ticket, word32 length)
+{
+    /* Free old dynamic ticket if we already had one */
+    if (ssl->session.isDynamic) {
+        XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+        ssl->session.ticket = ssl->session.staticTicket;
+        ssl->session.isDynamic = 0;
+    }
+
+    if (length > sizeof(ssl->session.staticTicket)) {
+        byte* sessionTicket =
+                   (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+        if (sessionTicket == NULL)
+            return MEMORY_E;
+        ssl->session.ticket = sessionTicket;
+        ssl->session.isDynamic = 1;
+    }
+    ssl->session.ticketLen = (word16)length;
+
+    if (length > 0) {
+        XMEMCPY(ssl->session.ticket, ticket, length);
+        if (ssl->session_ticket_cb != NULL) {
+            ssl->session_ticket_cb(ssl,
+                                   ssl->session.ticket, ssl->session.ticketLen,
+                                   ssl->session_ticket_ctx);
+        }
+        /* Create a fake sessionID based on the ticket, this will
+         * supersede the existing session cache info. */
+        ssl->options.haveSessionId = 1;
+#ifdef WOLFSSL_TLS13
+        if (ssl->options.tls1_3) {
+            XMEMCPY(ssl->session.sessionID,
+                                 ssl->session.ticket + length - ID_LEN, ID_LEN);
+        }
+        else
+#endif
+            XMEMCPY(ssl->arrays->sessionID,
+                                 ssl->session.ticket + length - ID_LEN, ID_LEN);
+    }
+
+    return 0;
+}
+
+#ifndef WOLFSSL_NO_TLS12
+
+/* handle processing of session_ticket (4) */
+static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+    word32 size)
+{
+    word32 begin = *inOutIdx;
+    word32 lifetime;
+    word16 length;
+    int    ret;
+
+    if (ssl->expect_session_ticket == 0) {
+        WOLFSSL_MSG("Unexpected session ticket");
+        return SESSION_TICKET_EXPECT_E;
+    }
+
+    if (OPAQUE32_LEN > size)
+        return BUFFER_ERROR;
+
+    ato32(input + *inOutIdx, &lifetime);
+    *inOutIdx += OPAQUE32_LEN;
+
+    if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
+        return BUFFER_ERROR;
+
+    ato16(input + *inOutIdx, &length);
+    *inOutIdx += OPAQUE16_LEN;
+
+    if ((*inOutIdx - begin) + length > size)
+        return BUFFER_ERROR;
+
+    if ((ret = SetTicket(ssl, input + *inOutIdx, length)) != 0)
+        return ret;
+    *inOutIdx += length;
+    if (length > 0) {
+        ssl->timeout = lifetime;
+#ifndef NO_SESSION_CACHE
+        AddSession(ssl);
+#endif
+    }
+
+    if (IsEncryptionOn(ssl, 0)) {
+        *inOutIdx += ssl->keys.padSz;
+    #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+        if (ssl->options.startedETMRead)
+            *inOutIdx += MacSize(ssl);
+    #endif
+    }
+
+    ssl->expect_session_ticket = 0;
+
+    return 0;
+}
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#endif /* HAVE_SESSION_TICKET */
+
+#endif /* NO_WOLFSSL_CLIENT */
+
+#ifdef HAVE_ECC
+    /* returns the WOLFSSL_* version of the curve from the OID sum */
+    word16 GetCurveByOID(int oidSum) {
+        switch(oidSum) {
+    #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case ECC_SECP160R1_OID:
+                return WOLFSSL_ECC_SECP160R1;
+        #endif /* !NO_ECC_SECP */
+        #ifdef HAVE_ECC_SECPR2
+            case ECC_SECP160R2_OID:
+                return WOLFSSL_ECC_SECP160R2;
+        #endif /* HAVE_ECC_SECPR2 */
+        #ifdef HAVE_ECC_KOBLITZ
+            case ECC_SECP160K1_OID:
+                return WOLFSSL_ECC_SECP160K1;
+        #endif /* HAVE_ECC_KOBLITZ */
+    #endif
+    #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case ECC_SECP192R1_OID:
+                return WOLFSSL_ECC_SECP192R1;
+        #endif /* !NO_ECC_SECP */
+        #ifdef HAVE_ECC_KOBLITZ
+            case ECC_SECP192K1_OID:
+                return WOLFSSL_ECC_SECP192K1;
+        #endif /* HAVE_ECC_KOBLITZ */
+    #endif
+    #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case ECC_SECP224R1_OID:
+                return WOLFSSL_ECC_SECP224R1;
+        #endif /* !NO_ECC_SECP */
+        #ifdef HAVE_ECC_KOBLITZ
+            case ECC_SECP224K1_OID:
+                return WOLFSSL_ECC_SECP224K1;
+        #endif /* HAVE_ECC_KOBLITZ */
+    #endif
+    #if !defined(NO_ECC256)  || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case ECC_SECP256R1_OID:
+                return WOLFSSL_ECC_SECP256R1;
+        #endif /* !NO_ECC_SECP */
+        #ifdef HAVE_ECC_KOBLITZ
+            case ECC_SECP256K1_OID:
+                return WOLFSSL_ECC_SECP256K1;
+        #endif /* HAVE_ECC_KOBLITZ */
+        #ifdef HAVE_ECC_BRAINPOOL
+            case ECC_BRAINPOOLP256R1_OID:
+                return WOLFSSL_ECC_BRAINPOOLP256R1;
+        #endif /* HAVE_ECC_BRAINPOOL */
+    #endif
+    #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case ECC_SECP384R1_OID:
+                return WOLFSSL_ECC_SECP384R1;
+        #endif /* !NO_ECC_SECP */
+        #ifdef HAVE_ECC_BRAINPOOL
+            case ECC_BRAINPOOLP384R1_OID:
+                return WOLFSSL_ECC_BRAINPOOLP384R1;
+        #endif /* HAVE_ECC_BRAINPOOL */
+    #endif
+    #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)
+        #ifdef HAVE_ECC_BRAINPOOL
+            case ECC_BRAINPOOLP512R1_OID:
+                return WOLFSSL_ECC_BRAINPOOLP512R1;
+        #endif /* HAVE_ECC_BRAINPOOL */
+    #endif
+    #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case ECC_SECP521R1_OID:
+                return WOLFSSL_ECC_SECP521R1;
+        #endif /* !NO_ECC_SECP */
+    #endif
+            default:
+                WOLFSSL_MSG("Curve OID not compiled in or implemented");
+                return 0;
+        }
+    }
+#endif /* HAVE_ECC */
+
+
+#ifndef NO_WOLFSSL_SERVER
+
+#ifndef WOLFSSL_NO_TLS12
+
+    /* handle generation of server_hello (2) */
+    int SendServerHello(WOLFSSL* ssl)
+    {
+        int    ret;
+        byte   *output;
+        word16 length;
+        word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+        int    sendSz;
+        byte   sessIdSz = ID_LEN;
+        byte   echoId   = 0;  /* ticket echo id flag */
+        byte   cacheOff = 0;  /* session cache off flag */
+
+        WOLFSSL_START(WC_FUNC_SERVER_HELLO_SEND);
+        WOLFSSL_ENTER("SendServerHello");
+
+        length = VERSION_SZ + RAN_LEN
+               + ID_LEN + ENUM_LEN
+               + SUITE_LEN
+               + ENUM_LEN;
+
+#ifdef HAVE_TLS_EXTENSIONS
+        ret = TLSX_GetResponseSize(ssl, server_hello, &length);
+        if (ret != 0)
+            return ret;
+    #ifdef HAVE_SESSION_TICKET
+        if (ssl->options.useTicket) {
+            /* echo session id sz can be 0,32 or bogus len in between */
+            sessIdSz = ssl->arrays->sessionIDSz;
+            if (sessIdSz > ID_LEN) {
+                WOLFSSL_MSG("Bad bogus session id len");
+                return BUFFER_ERROR;
+            }
+            if (!IsAtLeastTLSv1_3(ssl->version))
+                length -= (ID_LEN - sessIdSz);  /* adjust ID_LEN assumption */
+            echoId = 1;
+        }
+    #endif /* HAVE_SESSION_TICKET */
+#else
+        if (ssl->options.haveEMS) {
+            length += HELLO_EXT_SZ_SZ + HELLO_EXT_SZ;
+        }
+#endif
+
+        /* is the session cache off at build or runtime */
+#ifdef NO_SESSION_CACHE
+        cacheOff = 1;
+#else
+        if (ssl->options.sessionCacheOff == 1) {
+            cacheOff = 1;
+        }
+#endif
+
+        /* if no session cache don't send a session ID unless we're echoing
+         * an ID as part of session tickets */
+        if (echoId == 0 && cacheOff == 1) {
+            length -= ID_LEN;    /* adjust ID_LEN assumption */
+            sessIdSz = 0;
+        }
+
+        sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+        #ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls) {
+            /* Server Hello should use the same sequence number as the
+             * Client Hello. */
+            ssl->keys.dtls_sequence_number_hi = ssl->keys.curSeq_hi;
+            ssl->keys.dtls_sequence_number_lo = ssl->keys.curSeq_lo;
+            idx    += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+            sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+        }
+        #endif /* WOLFSSL_DTLS */
+
+        if (IsEncryptionOn(ssl, 1))
+            sendSz += MAX_MSG_EXTRA;
+
+        /* check for available size */
+        if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+            return ret;
+
+        /* get output buffer */
+        output = ssl->buffers.outputBuffer.buffer +
+                 ssl->buffers.outputBuffer.length;
+
+        AddHeaders(output, length, server_hello, ssl);
+
+        /* now write to output */
+        /* first version */
+        output[idx++] = (byte)ssl->version.major;
+        output[idx++] = (byte)ssl->version.minor;
+
+        /* then random and session id */
+        if (!ssl->options.resuming) {
+            /* generate random part and session id */
+            ret = wc_RNG_GenerateBlock(ssl->rng, output + idx,
+                RAN_LEN + sizeof(sessIdSz) + sessIdSz);
+            if (ret != 0)
+                return ret;
+
+#ifdef WOLFSSL_TLS13
+            if (TLSv1_3_Capable(ssl)) {
+                /* TLS v1.3 capable server downgraded. */
+                XMEMCPY(output + idx + RAN_LEN - (TLS13_DOWNGRADE_SZ + 1),
+                        tls13Downgrade, TLS13_DOWNGRADE_SZ);
+                output[idx + RAN_LEN - 1] = (byte)IsAtLeastTLSv1_2(ssl);
+            }
+            else
+#endif
+            if (ssl->ctx->method->version.major == SSLv3_MAJOR &&
+                          ssl->ctx->method->version.minor == TLSv1_2_MINOR &&
+                                                       !IsAtLeastTLSv1_2(ssl)) {
+                /* TLS v1.2 capable server downgraded. */
+                XMEMCPY(output + idx + RAN_LEN - (TLS13_DOWNGRADE_SZ + 1),
+                        tls13Downgrade, TLS13_DOWNGRADE_SZ);
+                output[idx + RAN_LEN - 1] = 0;
+            }
+
+            /* store info in SSL for later */
+            XMEMCPY(ssl->arrays->serverRandom, output + idx, RAN_LEN);
+            idx += RAN_LEN;
+            output[idx++] = sessIdSz;
+            XMEMCPY(ssl->arrays->sessionID, output + idx, sessIdSz);
+            ssl->arrays->sessionIDSz = sessIdSz;
+        }
+        else {
+            /* If resuming, use info from SSL */
+            XMEMCPY(output + idx, ssl->arrays->serverRandom, RAN_LEN);
+            idx += RAN_LEN;
+            output[idx++] = sessIdSz;
+            XMEMCPY(output + idx, ssl->arrays->sessionID, sessIdSz);
+        }
+        idx += sessIdSz;
+
+#ifdef SHOW_SECRETS
+        {
+            int j;
+            printf("server random: ");
+            for (j = 0; j < RAN_LEN; j++)
+                printf("%02x", ssl->arrays->serverRandom[j]);
+            printf("\n");
+        }
+#endif
+
+        /* then cipher suite */
+        output[idx++] = ssl->options.cipherSuite0;
+        output[idx++] = ssl->options.cipherSuite;
+
+        /* then compression */
+        if (ssl->options.usingCompression)
+            output[idx++] = ZLIB_COMPRESSION;
+        else
+            output[idx++] = NO_COMPRESSION;
+
+        /* last, extensions */
+#ifdef HAVE_TLS_EXTENSIONS
+        {
+            word16 offset = 0;
+            ret = TLSX_WriteResponse(ssl, output + idx, server_hello, &offset);
+            if (ret != 0)
+                return ret;
+            idx += offset;
+        }
+#else
+#ifdef HAVE_EXTENDED_MASTER
+        if (ssl->options.haveEMS) {
+            c16toa(HELLO_EXT_SZ, output + idx);
+            idx += HELLO_EXT_SZ_SZ;
+
+            c16toa(HELLO_EXT_EXTMS, output + idx);
+            idx += HELLO_EXT_TYPE_SZ;
+            c16toa(0, output + idx);
+            /*idx += HELLO_EXT_SZ_SZ;*/
+            /* idx is not used after this point. uncomment the line above
+             * if adding any more extensions in the future. */
+        }
+#endif
+#endif
+
+        if (IsEncryptionOn(ssl, 1)) {
+            byte* input;
+            int   inputSz = idx - RECORD_HEADER_SZ; /* build msg adds rec hdr */
+
+            input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+            if (input == NULL)
+                return MEMORY_E;
+
+            XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
+            sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
+                                  handshake, 1, 0, 0);
+            XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+
+            if (sendSz < 0)
+                return sendSz;
+        } else {
+            #ifdef WOLFSSL_DTLS
+                if (ssl->options.dtls)
+                    DtlsSEQIncrement(ssl, CUR_ORDER);
+            #endif
+            ret = HashOutput(ssl, output, sendSz, 0);
+            if (ret != 0)
+                return ret;
+        }
+
+    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+        if (ssl->hsInfoOn)
+            AddPacketName(ssl, "ServerHello");
+        if (ssl->toInfoOn)
+            AddPacketInfo(ssl, "ServerHello", handshake, output, sendSz,
+                          WRITE_PROTO, ssl->heap);
+    #endif
+
+        ssl->options.serverState = SERVER_HELLO_COMPLETE;
+        ssl->buffers.outputBuffer.length += sendSz;
+
+    #ifdef WOLFSSL_DTLS
+        if (IsDtlsNotSctpMode(ssl)) {
+            if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
+                return ret;
+        }
+    #endif
+
+        if (ssl->options.groupMessages)
+            ret = 0;
+        else
+            ret = SendBuffered(ssl);
+
+        WOLFSSL_LEAVE("SendServerHello", ret);
+        WOLFSSL_END(WC_FUNC_SERVER_HELLO_SEND);
+
+        return ret;
+    }
+
+
+#if defined(HAVE_ECC)
+
+    static byte SetCurveId(ecc_key* key)
+    {
+        if (key == NULL || key->dp == NULL) {
+            WOLFSSL_MSG("SetCurveId: Invalid key!");
+            return 0;
+        }
+
+        return (byte)GetCurveByOID(key->dp->oidSum);
+    }
+
+#endif /* HAVE_ECC */
+
+    typedef struct SskeArgs {
+        byte*  output; /* not allocated */
+    #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \
+                                           (!defined(NO_DH) && !defined(NO_RSA))
+        byte*  sigDataBuf;
+    #endif
+    #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
+        byte*  exportBuf;
+    #endif
+    #ifndef NO_RSA
+        byte*  verifySig;
+    #endif
+        byte*  input;
+        word32 idx;
+        word32 tmpSigSz;
+        word32 length;
+        word32 sigSz;
+    #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \
+                                           (!defined(NO_DH) && !defined(NO_RSA))
+        word32 sigDataSz;
+    #endif
+    #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
+        word32 exportSz;
+    #endif
+    #ifdef HAVE_QSH
+        word32 qshSz;
+    #endif
+        int    sendSz;
+        int    inputSz;
+    } SskeArgs;
+
+    static void FreeSskeArgs(WOLFSSL* ssl, void* pArgs)
+    {
+        SskeArgs* args = (SskeArgs*)pArgs;
+
+        (void)ssl;
+
+    #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
+        if (args->exportBuf) {
+            XFREE(args->exportBuf, ssl->heap, DYNAMIC_TYPE_DER);
+            args->exportBuf = NULL;
+        }
+    #endif
+    #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \
+                                           (!defined(NO_DH) && !defined(NO_RSA))
+        if (args->sigDataBuf) {
+            XFREE(args->sigDataBuf, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+            args->sigDataBuf = NULL;
+        }
+    #endif
+    #ifndef NO_RSA
+        if (args->verifySig) {
+            XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+            args->verifySig = NULL;
+        }
+    #endif
+        (void)args;
+    }
+
+    /* handle generation of server_key_exchange (12) */
+    int SendServerKeyExchange(WOLFSSL* ssl)
+    {
+        int ret;
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        SskeArgs* args = (SskeArgs*)ssl->async.args;
+        typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+        (void)sizeof(args_test);
+    #else
+        SskeArgs  args[1];
+    #endif
+
+        WOLFSSL_START(WC_FUNC_SERVER_KEY_EXCHANGE_SEND);
+        WOLFSSL_ENTER("SendServerKeyExchange");
+
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
+        if (ret != WC_NOT_PENDING_E) {
+            /* Check for error */
+            if (ret < 0)
+                goto exit_sske;
+        }
+        else
+    #endif
+        {
+            /* Reset state */
+            ret = 0;
+            ssl->options.asyncState = TLS_ASYNC_BEGIN;
+            XMEMSET(args, 0, sizeof(SskeArgs));
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            ssl->async.freeArgs = FreeSskeArgs;
+        #endif
+        }
+
+        switch(ssl->options.asyncState)
+        {
+            case TLS_ASYNC_BEGIN:
+            {
+            #ifdef HAVE_QSH
+                if (ssl->peerQSHKeyPresent && ssl->options.haveQSH) {
+                    args->qshSz = QSH_KeyGetSize(ssl);
+                }
+            #endif
+
+                /* Do some checks / debug msgs */
+                switch(ssl->specs.kea)
+                {
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                     defined(HAVE_CURVE448)) && !defined(NO_PSK)
+                    case ecdhe_psk_kea:
+                    {
+                        WOLFSSL_MSG("Using ephemeral ECDH PSK");
+                        break;
+                    }
+                #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */
+                #if defined(HAVE_ECC)
+                    case ecc_diffie_hellman_kea:
+                    {
+                        if (ssl->specs.static_ecdh) {
+                            WOLFSSL_MSG("Using Static ECDH, not sending "
+                                        "ServerKeyExchange");
+                            ERROR_OUT(0, exit_sske);
+                        }
+
+                        WOLFSSL_MSG("Using ephemeral ECDH");
+                        break;
+                    }
+                #endif /* HAVE_ECC */
+                }
+
+                /* Preparing keys */
+                switch(ssl->specs.kea)
+                {
+                #ifndef NO_PSK
+                    case psk_kea:
+                    {
+                        /* Nothing to do in this sub-state */
+                        break;
+                    }
+                #endif /* !NO_PSK */
+                #if !defined(NO_DH) && (!defined(NO_PSK) || !defined(NO_RSA))
+                #if !defined(NO_PSK)
+                    case dhe_psk_kea:
+                #endif
+                #if !defined(NO_RSA)
+                    case diffie_hellman_kea:
+                #endif
+                    {
+                        /* Allocate DH key buffers and generate key */
+                        if (ssl->buffers.serverDH_P.buffer == NULL ||
+                            ssl->buffers.serverDH_G.buffer == NULL) {
+                            ERROR_OUT(NO_DH_PARAMS, exit_sske);
+                        }
+
+                        if (ssl->buffers.serverDH_Pub.buffer == NULL) {
+                            /* Free'd in SSL_ResourceFree and FreeHandshakeResources */
+                            ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC(
+                                    ssl->buffers.serverDH_P.length + OPAQUE16_LEN,
+                                    ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+                            if (ssl->buffers.serverDH_Pub.buffer == NULL) {
+                                ERROR_OUT(MEMORY_E, exit_sske);
+                            }
+                        }
+
+                        if (ssl->buffers.serverDH_Priv.buffer == NULL) {
+                            /* Free'd in SSL_ResourceFree and FreeHandshakeResources */
+                            ssl->buffers.serverDH_Priv.buffer = (byte*)XMALLOC(
+                                    ssl->buffers.serverDH_P.length + OPAQUE16_LEN,
+                                    ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
+                            if (ssl->buffers.serverDH_Priv.buffer == NULL) {
+                                ERROR_OUT(MEMORY_E, exit_sske);
+                            }
+                        }
+
+                        ssl->options.dhKeySz =
+                                (word16)ssl->buffers.serverDH_P.length;
+
+                        ret = AllocKey(ssl, DYNAMIC_TYPE_DH,
+                                            (void**)&ssl->buffers.serverDH_Key);
+                        if (ret != 0) {
+                            goto exit_sske;
+                        }
+
+                        #if !defined(WOLFSSL_OLD_PRIME_CHECK) && \
+                            !defined(HAVE_FIPS) && \
+                            !defined(HAVE_SELFTEST)
+                        if (ssl->options.dhDoKeyTest &&
+                            !ssl->options.dhKeyTested)
+                        {
+                            ret = wc_DhSetCheckKey(
+                                ssl->buffers.serverDH_Key,
+                                ssl->buffers.serverDH_P.buffer,
+                                ssl->buffers.serverDH_P.length,
+                                ssl->buffers.serverDH_G.buffer,
+                                ssl->buffers.serverDH_G.length,
+                                NULL, 0, 0, ssl->rng);
+                            if (ret != 0) {
+                                goto exit_sske;
+                            }
+                            ssl->options.dhKeyTested = 1;
+                        }
+                        else
+                        #endif
+                        {
+                            ret = wc_DhSetKey(ssl->buffers.serverDH_Key,
+                                ssl->buffers.serverDH_P.buffer,
+                                ssl->buffers.serverDH_P.length,
+                                ssl->buffers.serverDH_G.buffer,
+                                ssl->buffers.serverDH_G.length);
+                            if (ret != 0) {
+                                goto exit_sske;
+                            }
+                        }
+
+                        ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key,
+                            ssl->buffers.serverDH_Priv.buffer,
+                            (word32*)&ssl->buffers.serverDH_Priv.length,
+                            ssl->buffers.serverDH_Pub.buffer,
+                            (word32*)&ssl->buffers.serverDH_Pub.length);
+                        break;
+                    }
+                #endif /* !NO_DH && (!NO_PSK || !NO_RSA) */
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                     defined(HAVE_CURVE448)) && !defined(NO_PSK)
+                    case ecdhe_psk_kea:
+                        /* Fall through to create temp ECC key */
+                #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */
+                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                                          defined(HAVE_CURVE448)
+                    case ecc_diffie_hellman_kea:
+                    {
+                    #ifdef HAVE_CURVE25519
+                        if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+                            /* need ephemeral key now, create it if missing */
+                            if (ssl->eccTempKey == NULL) {
+                                /* alloc/init on demand */
+                                ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519,
+                                    (void**)&ssl->eccTempKey);
+                                if (ret != 0) {
+                                    goto exit_sske;
+                                }
+                            }
+
+                            if (ssl->eccTempKeyPresent == 0) {
+                                ret = X25519MakeKey(ssl,
+                                        (curve25519_key*)ssl->eccTempKey, NULL);
+                                if (ret == 0 || ret == WC_PENDING_E) {
+                                    ssl->eccTempKeyPresent =
+                                        DYNAMIC_TYPE_CURVE25519;
+                                }
+                            }
+                            break;
+                        }
+                    #endif
+                    #ifdef HAVE_CURVE448
+                        if (ssl->ecdhCurveOID == ECC_X448_OID) {
+                            /* need ephemeral key now, create it if missing */
+                            if (ssl->eccTempKey == NULL) {
+                                /* alloc/init on demand */
+                                ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE448,
+                                    (void**)&ssl->eccTempKey);
+                                if (ret != 0) {
+                                    goto exit_sske;
+                                }
+                            }
+
+                            if (ssl->eccTempKeyPresent == 0) {
+                                ret = X448MakeKey(ssl,
+                                          (curve448_key*)ssl->eccTempKey, NULL);
+                                if (ret == 0 || ret == WC_PENDING_E) {
+                                    ssl->eccTempKeyPresent =
+                                        DYNAMIC_TYPE_CURVE448;
+                                }
+                            }
+                            break;
+                        }
+                    #endif
+                    #ifdef HAVE_ECC
+                        /* need ephemeral key now, create it if missing */
+                        if (ssl->eccTempKey == NULL) {
+                            /* alloc/init on demand */
+                            ret = AllocKey(ssl, DYNAMIC_TYPE_ECC,
+                                (void**)&ssl->eccTempKey);
+                            if (ret != 0) {
+                                goto exit_sske;
+                            }
+                        }
+
+                        if (ssl->eccTempKeyPresent == 0) {
+                            ret = EccMakeKey(ssl, ssl->eccTempKey, NULL);
+                            if (ret == 0 || ret == WC_PENDING_E) {
+                                ssl->eccTempKeyPresent = DYNAMIC_TYPE_ECC;
+                            }
+                        }
+                    #endif
+                        break;
+                    }
+                #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+                    default:
+                        /* Skip ServerKeyExchange */
+                        goto exit_sske;
+                } /* switch(ssl->specs.kea) */
+
+                /* Check for error */
+                if (ret != 0) {
+                    goto exit_sske;
+                }
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_BUILD;
+            } /* case TLS_ASYNC_BEGIN */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_BUILD:
+            {
+            #if (!defined(NO_DH) && !defined(NO_RSA)) || (defined(HAVE_ECC) || \
+                             defined(HAVE_CURVE25519) || defined(HAVE_CURVE448))
+                word32 preSigSz, preSigIdx;
+            #endif
+
+                switch(ssl->specs.kea)
+                {
+                #ifndef NO_PSK
+                    case psk_kea:
+                    {
+                        args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+
+                        if (ssl->arrays->server_hint[0] == 0) {
+                            ERROR_OUT(0, exit_sske); /* don't send */
+                        }
+
+                        /* include size part */
+                        args->length = (word32)XSTRLEN(ssl->arrays->server_hint);
+                        if (args->length > MAX_PSK_ID_LEN) {
+                            ERROR_OUT(SERVER_HINT_ERROR, exit_sske);
+                        }
+
+                        args->length += HINT_LEN_SZ;
+                        args->sendSz = args->length + HANDSHAKE_HEADER_SZ +
+                                                            RECORD_HEADER_SZ;
+
+                    #ifdef HAVE_QSH
+                        args->length += args->qshSz;
+                        args->sendSz += args->qshSz;
+                    #endif
+
+                    #ifdef WOLFSSL_DTLS
+                        if (ssl->options.dtls) {
+                            args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+                            args->idx    += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+                        }
+                    #endif
+
+                        if (IsEncryptionOn(ssl, 1)) {
+                            args->sendSz += MAX_MSG_EXTRA;
+                        }
+
+                        /* check for available size */
+                        if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
+                            goto exit_sske;
+                        }
+
+                        /* get output buffer */
+                        args->output = ssl->buffers.outputBuffer.buffer +
+                                       ssl->buffers.outputBuffer.length;
+
+                        AddHeaders(args->output, args->length,
+                                                    server_key_exchange, ssl);
+
+                        /* key data */
+                    #ifdef HAVE_QSH
+                        c16toa((word16)(args->length - args->qshSz -
+                                        HINT_LEN_SZ), args->output + args->idx);
+                    #else
+                        c16toa((word16)(args->length - HINT_LEN_SZ),
+                                                      args->output + args->idx);
+                    #endif
+
+                        args->idx += HINT_LEN_SZ;
+                        XMEMCPY(args->output + args->idx,
+                                ssl->arrays->server_hint,
+                                args->length - HINT_LEN_SZ);
+                        break;
+                    }
+                #endif /* !NO_PSK */
+                #if !defined(NO_DH) && !defined(NO_PSK)
+                    case dhe_psk_kea:
+                    {
+                        word32 hintLen;
+
+                        args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+                        args->length = LENGTH_SZ * 3 + /* p, g, pub */
+                                 ssl->buffers.serverDH_P.length +
+                                 ssl->buffers.serverDH_G.length +
+                                 ssl->buffers.serverDH_Pub.length;
+
+                        /* include size part */
+                        hintLen = (word32)XSTRLEN(ssl->arrays->server_hint);
+                        if (hintLen > MAX_PSK_ID_LEN) {
+                            ERROR_OUT(SERVER_HINT_ERROR, exit_sske);
+                        }
+                        args->length += hintLen + HINT_LEN_SZ;
+                        args->sendSz = args->length + HANDSHAKE_HEADER_SZ +
+                                                            RECORD_HEADER_SZ;
+
+                    #ifdef HAVE_QSH
+                        args->length += args->qshSz;
+                        args->sendSz += args->qshSz;
+                    #endif
+                    #ifdef WOLFSSL_DTLS
+                        if (ssl->options.dtls) {
+                            args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+                            args->idx    += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+                        }
+                    #endif
+
+                        if (IsEncryptionOn(ssl, 1)) {
+                            args->sendSz += MAX_MSG_EXTRA;
+                        }
+
+                        /* check for available size */
+                        if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
+                            goto exit_sske;
+                        }
+
+                        /* get output buffer */
+                        args->output = ssl->buffers.outputBuffer.buffer +
+                                       ssl->buffers.outputBuffer.length;
+
+                        AddHeaders(args->output, args->length,
+                                                    server_key_exchange, ssl);
+
+                        /* key data */
+                        c16toa((word16)hintLen, args->output + args->idx);
+                        args->idx += HINT_LEN_SZ;
+                        XMEMCPY(args->output + args->idx,
+                                            ssl->arrays->server_hint, hintLen);
+                        args->idx += hintLen;
+
+                        /* add p, g, pub */
+                        c16toa((word16)ssl->buffers.serverDH_P.length,
+                            args->output + args->idx);
+                        args->idx += LENGTH_SZ;
+                        XMEMCPY(args->output + args->idx,
+                                ssl->buffers.serverDH_P.buffer,
+                                ssl->buffers.serverDH_P.length);
+                        args->idx += ssl->buffers.serverDH_P.length;
+
+                        /*  g */
+                        c16toa((word16)ssl->buffers.serverDH_G.length,
+                            args->output + args->idx);
+                        args->idx += LENGTH_SZ;
+                        XMEMCPY(args->output + args->idx,
+                                ssl->buffers.serverDH_G.buffer,
+                                ssl->buffers.serverDH_G.length);
+                        args->idx += ssl->buffers.serverDH_G.length;
+
+                        /*  pub */
+                        c16toa((word16)ssl->buffers.serverDH_Pub.length,
+                            args->output + args->idx);
+                        args->idx += LENGTH_SZ;
+                        XMEMCPY(args->output + args->idx,
+                                ssl->buffers.serverDH_Pub.buffer,
+                                ssl->buffers.serverDH_Pub.length);
+                        /* No need to update idx, since sizes are already set */
+                        /* args->idx += ssl->buffers.serverDH_Pub.length; */
+                        break;
+                    }
+                #endif /* !defined(NO_DH) && !defined(NO_PSK) */
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                     defined(HAVE_CURVE448)) && !defined(NO_PSK)
+                    case ecdhe_psk_kea:
+                    {
+                        word32 hintLen;
+
+                        /* curve type, named curve, length(1) */
+                        args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+                        args->length = ENUM_LEN + CURVE_LEN + ENUM_LEN;
+
+                        args->exportSz = MAX_EXPORT_ECC_SZ;
+                        args->exportBuf = (byte*)XMALLOC(args->exportSz,
+                                            ssl->heap, DYNAMIC_TYPE_DER);
+                        if (args->exportBuf == NULL) {
+                            ERROR_OUT(MEMORY_E, exit_sske);
+                        }
+                    #ifdef HAVE_CURVE25519
+                        if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+                            if (wc_curve25519_export_public_ex(
+                                    (curve25519_key*)ssl->eccTempKey,
+                                    args->exportBuf, &args->exportSz,
+                                    EC25519_LITTLE_ENDIAN) != 0) {
+                                ERROR_OUT(ECC_EXPORT_ERROR, exit_sske);
+                            }
+                        }
+                        else
+                    #endif
+                    #ifdef HAVE_CURVE448
+                        if (ssl->ecdhCurveOID == ECC_X448_OID) {
+                            if (wc_curve448_export_public_ex(
+                                    (curve448_key*)ssl->eccTempKey,
+                                    args->exportBuf, &args->exportSz,
+                                    EC448_LITTLE_ENDIAN) != 0) {
+                                ERROR_OUT(ECC_EXPORT_ERROR, exit_sske);
+                            }
+                        }
+                        else
+                    #endif
+                        {
+                            if (wc_ecc_export_x963(ssl->eccTempKey,
+                                       args->exportBuf, &args->exportSz) != 0) {
+                                ERROR_OUT(ECC_EXPORT_ERROR, exit_sske);
+                            }
+                        }
+                        args->length += args->exportSz;
+
+                        /* include size part */
+                        hintLen = (word32)XSTRLEN(ssl->arrays->server_hint);
+                        if (hintLen > MAX_PSK_ID_LEN) {
+                            ERROR_OUT(SERVER_HINT_ERROR, exit_sske);
+                        }
+                        args->length += hintLen + HINT_LEN_SZ;
+                        args->sendSz = args->length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+
+                    #ifdef HAVE_QSH
+                        args->length += args->qshSz;
+                        args->sendSz += args->qshSz;
+                    #endif
+                    #ifdef WOLFSSL_DTLS
+                        if (ssl->options.dtls) {
+                            args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+                            args->idx    += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+                        }
+                    #endif
+
+                        if (IsEncryptionOn(ssl, 1)) {
+                            args->sendSz += MAX_MSG_EXTRA;
+                        }
+
+                        /* check for available size */
+                        if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
+                            goto exit_sske;
+                        }
+
+                        /* get output buffer */
+                        args->output = ssl->buffers.outputBuffer.buffer +
+                                       ssl->buffers.outputBuffer.length;
+
+                        /* key data */
+                        c16toa((word16)hintLen, args->output + args->idx);
+                        args->idx += HINT_LEN_SZ;
+                        XMEMCPY(args->output + args->idx,
+                                            ssl->arrays->server_hint, hintLen);
+                        args->idx += hintLen;
+
+                        /* ECC key exchange data */
+                        args->output[args->idx++] = named_curve;
+                        args->output[args->idx++] = 0x00;          /* leading zero */
+                    #ifdef HAVE_CURVE25519
+                        if (ssl->ecdhCurveOID == ECC_X25519_OID)
+                            args->output[args->idx++] = WOLFSSL_ECC_X25519;
+                        else
+                    #endif
+                    #ifdef HAVE_CURVE448
+                        if (ssl->ecdhCurveOID == ECC_X448_OID)
+                            args->output[args->idx++] = WOLFSSL_ECC_X448;
+                        else
+                    #endif
+                        {
+                    #ifdef HAVE_ECC
+                            args->output[args->idx++] =
+                                                    SetCurveId(ssl->eccTempKey);
+                    #endif
+                        }
+                        args->output[args->idx++] = (byte)args->exportSz;
+                        XMEMCPY(args->output + args->idx, args->exportBuf,
+                                                                args->exportSz);
+                        break;
+                    }
+                #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */
+                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                                          defined(HAVE_CURVE448)
+                    case ecc_diffie_hellman_kea:
+                    {
+                        enum wc_HashType hashType;
+
+                        /* curve type, named curve, length(1) */
+                        args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+                        args->length = ENUM_LEN + CURVE_LEN + ENUM_LEN;
+
+                        /* Export temp ECC key and add to length */
+                        args->exportSz = MAX_EXPORT_ECC_SZ;
+                        args->exportBuf = (byte*)XMALLOC(args->exportSz,
+                                            ssl->heap, DYNAMIC_TYPE_DER);
+                        if (args->exportBuf == NULL) {
+                            ERROR_OUT(MEMORY_E, exit_sske);
+                        }
+                    #ifdef HAVE_CURVE25519
+                        if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+                            if (wc_curve25519_export_public_ex(
+                                        (curve25519_key*)ssl->eccTempKey,
+                                        args->exportBuf, &args->exportSz,
+                                        EC25519_LITTLE_ENDIAN) != 0) {
+                                ERROR_OUT(ECC_EXPORT_ERROR, exit_sske);
+                            }
+                        }
+                        else
+                    #endif
+                    #ifdef HAVE_CURVE448
+                        if (ssl->ecdhCurveOID == ECC_X448_OID) {
+                            if (wc_curve448_export_public_ex(
+                                        (curve448_key*)ssl->eccTempKey,
+                                        args->exportBuf, &args->exportSz,
+                                        EC448_LITTLE_ENDIAN) != 0) {
+                                ERROR_OUT(ECC_EXPORT_ERROR, exit_sske);
+                            }
+                        }
+                        else
+                    #endif
+                        {
+                    #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)
+                            if (wc_ecc_export_x963(ssl->eccTempKey,
+                                       args->exportBuf, &args->exportSz) != 0) {
+                                ERROR_OUT(ECC_EXPORT_ERROR, exit_sske);
+                            }
+                     #endif
+                        }
+                        args->length += args->exportSz;
+
+                        preSigSz  = args->length;
+                        preSigIdx = args->idx;
+
+                        if (ssl->buffers.key == NULL) {
+                        #ifdef HAVE_PK_CALLBACKS
+                            if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) {
+                                args->tmpSigSz = GetPrivateKeySigSize(ssl);
+                                if (args->tmpSigSz == 0) {
+                                    ERROR_OUT(NO_PRIVATE_KEY, exit_sske);
+                                }
+                            }
+                            else
+                        #endif
+                                ERROR_OUT(NO_PRIVATE_KEY, exit_sske);
+                        }
+                        else {
+                            switch(ssl->suites->sigAlgo) {
+                        #ifndef NO_RSA
+                        #ifdef WC_RSA_PSS
+                            case rsa_pss_sa_algo:
+                        #endif
+                            case rsa_sa_algo:
+                            {
+                                word16 keySz;
+
+                                ssl->buffers.keyType = rsa_sa_algo;
+                                ret = DecodePrivateKey(ssl, &keySz);
+                                if (ret != 0) {
+                                    goto exit_sske;
+                                }
+
+                                args->tmpSigSz = (word32)keySz;
+                                break;
+                            }
+                        #endif /* !NO_RSA */
+                        #ifdef HAVE_ECC
+                            case ecc_dsa_sa_algo:
+                            {
+                                word16 keySz;
+
+                                ssl->buffers.keyType = ecc_dsa_sa_algo;
+                                ret = DecodePrivateKey(ssl, &keySz);
+                                if (ret != 0) {
+                                    goto exit_sske;
+                                }
+                                /* worst case estimate */
+                                args->tmpSigSz = keySz;
+                                break;
+                            }
+                        #endif
+                        #ifdef HAVE_ED25519
+                            case ed25519_sa_algo:
+                            {
+                                word16 keySz;
+
+                                ssl->buffers.keyType = ed25519_sa_algo;
+                                ret = DecodePrivateKey(ssl, &keySz);
+                                if (ret != 0) {
+                                    goto exit_sske;
+                                }
+
+                                /* worst case estimate */
+                                args->tmpSigSz = ED25519_SIG_SIZE;
+                                break;
+                            }
+                        #endif /* HAVE_ED25519 */
+                        #ifdef HAVE_ED448
+                            case ed448_sa_algo:
+                            {
+                                word16 keySz;
+
+                                ssl->buffers.keyType = ed448_sa_algo;
+                                ret = DecodePrivateKey(ssl, &keySz);
+                                if (ret != 0) {
+                                    goto exit_sske;
+                                }
+
+                                /* worst case estimate */
+                                args->tmpSigSz = ED448_SIG_SIZE;
+                                break;
+                            }
+                        #endif /* HAVE_ED448 */
+                            default:
+                                ERROR_OUT(ALGO_ID_E, exit_sske);  /* unsupported type */
+                            } /* switch(ssl->specs.sig_algo) */
+                        }
+
+                        /* sig length */
+                        args->length += LENGTH_SZ;
+                        args->length += args->tmpSigSz;
+
+                        if (IsAtLeastTLSv1_2(ssl)) {
+                            args->length += HASH_SIG_SIZE;
+                        }
+
+                        args->sendSz = args->length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+
+                    #ifdef HAVE_QSH
+                        args->length += args->qshSz;
+                        args->sendSz += args->qshSz;
+                    #endif
+                    #ifdef WOLFSSL_DTLS
+                        if (ssl->options.dtls) {
+                            args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+                            args->idx    += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+                            preSigIdx = args->idx;
+                        }
+                    #endif
+                        if (IsEncryptionOn(ssl, 1)) {
+                            args->sendSz += MAX_MSG_EXTRA;
+                        }
+
+                        /* check for available size */
+                        if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
+                            goto exit_sske;
+                        }
+
+                        /* get output buffer */
+                        args->output = ssl->buffers.outputBuffer.buffer +
+                                       ssl->buffers.outputBuffer.length;
+
+                        /* record and message headers will be added below, when we're sure
+                           of the sig length */
+
+                        /* key exchange data */
+                        args->output[args->idx++] = named_curve;
+                        args->output[args->idx++] = 0x00;          /* leading zero */
+                    #ifdef HAVE_CURVE25519
+                        if (ssl->ecdhCurveOID == ECC_X25519_OID)
+                            args->output[args->idx++] = WOLFSSL_ECC_X25519;
+                        else
+                    #endif
+                    #ifdef HAVE_CURVE448
+                        if (ssl->ecdhCurveOID == ECC_X448_OID)
+                            args->output[args->idx++] = WOLFSSL_ECC_X448;
+                        else
+                    #endif
+                        {
+                    #ifdef HAVE_ECC
+                            args->output[args->idx++] =
+                                                    SetCurveId(ssl->eccTempKey);
+                    #endif
+                        }
+                        args->output[args->idx++] = (byte)args->exportSz;
+                        XMEMCPY(args->output + args->idx, args->exportBuf, args->exportSz);
+                        args->idx += args->exportSz;
+
+                        /* Determine hash type */
+                        if (IsAtLeastTLSv1_2(ssl)) {
+                            EncodeSigAlg(ssl->suites->hashAlgo,
+                                         ssl->suites->sigAlgo,
+                                         &args->output[args->idx]);
+                            args->idx += 2;
+
+                            hashType = HashAlgoToType(ssl->suites->hashAlgo);
+                            if (hashType == WC_HASH_TYPE_NONE) {
+                                ERROR_OUT(ALGO_ID_E, exit_sske);
+                            }
+
+                        } else {
+                            /* only using sha and md5 for rsa */
+                        #ifndef NO_OLD_TLS
+                            hashType = WC_HASH_TYPE_SHA;
+                            if (ssl->suites->sigAlgo == rsa_sa_algo) {
+                                hashType = WC_HASH_TYPE_MD5_SHA;
+                            }
+                        #else
+                            ERROR_OUT(ALGO_ID_E, exit_sske);
+                        #endif
+                        }
+
+                        /* Signature length will be written later, when we're sure what it is */
+
+                    #ifdef HAVE_FUZZER
+                        if (ssl->fuzzerCb) {
+                            ssl->fuzzerCb(ssl, args->output + preSigIdx,
+                                preSigSz, FUZZ_SIGNATURE, ssl->fuzzerCtx);
+                        }
+                    #endif
+
+                        /* Assemble buffer to hash for signature */
+                        args->sigDataSz = RAN_LEN + RAN_LEN + preSigSz;
+                        args->sigDataBuf = (byte*)XMALLOC(args->sigDataSz,
+                                            ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+                        if (args->sigDataBuf == NULL) {
+                            ERROR_OUT(MEMORY_E, exit_sske);
+                        }
+                        XMEMCPY(args->sigDataBuf, ssl->arrays->clientRandom,
+                                                                       RAN_LEN);
+                        XMEMCPY(args->sigDataBuf+RAN_LEN,
+                                            ssl->arrays->serverRandom, RAN_LEN);
+                        XMEMCPY(args->sigDataBuf+RAN_LEN+RAN_LEN,
+                                args->output + preSigIdx, preSigSz);
+
+                        if (ssl->suites->sigAlgo != ed25519_sa_algo &&
+                                        ssl->suites->sigAlgo != ed448_sa_algo) {
+                            ssl->buffers.sig.length =
+                                                 wc_HashGetDigestSize(hashType);
+                            if ((int)ssl->buffers.sig.length < 0) {
+                                ERROR_OUT(HASH_TYPE_E, exit_sske);
+                            }
+                            ssl->buffers.sig.buffer = (byte*)XMALLOC(
+                                            ssl->buffers.sig.length,
+                                            ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+                            if (ssl->buffers.sig.buffer == NULL) {
+                                ERROR_OUT(MEMORY_E, exit_sske);
+                            }
+
+                            /* Perform hash */
+                            ret = wc_Hash(hashType, args->sigDataBuf,
+                                                       args->sigDataSz,
+                                                       ssl->buffers.sig.buffer,
+                                                       ssl->buffers.sig.length);
+                            if (ret != 0) {
+                                goto exit_sske;
+                            }
+                        }
+
+                        args->sigSz = args->tmpSigSz;
+
+                        /* Sign hash to create signature */
+                        switch (ssl->suites->sigAlgo)
+                        {
+                        #ifndef NO_RSA
+                            case rsa_sa_algo:
+                            {
+                                /* For TLS 1.2 re-encode signature */
+                                if (IsAtLeastTLSv1_2(ssl)) {
+                                    byte* encodedSig = (byte*)XMALLOC(
+                                                  MAX_ENCODED_SIG_SZ, ssl->heap,
+                                                       DYNAMIC_TYPE_SIGNATURE);
+                                    if (encodedSig == NULL) {
+                                        ERROR_OUT(MEMORY_E, exit_sske);
+                                    }
+
+                                    ssl->buffers.sig.length =
+                                        wc_EncodeSignature(encodedSig,
+                                            ssl->buffers.sig.buffer,
+                                            ssl->buffers.sig.length,
+                                            TypeHash(ssl->suites->hashAlgo));
+
+                                    /* Replace sig buffer with new one */
+                                    XFREE(ssl->buffers.sig.buffer, ssl->heap,
+                                                       DYNAMIC_TYPE_SIGNATURE);
+                                    ssl->buffers.sig.buffer = encodedSig;
+                                }
+
+                                /* write sig size here */
+                                c16toa((word16)args->sigSz,
+                                    args->output + args->idx);
+                                args->idx += LENGTH_SZ;
+                                break;
+                            }
+                        #ifdef WC_RSA_PSS
+                            case rsa_pss_sa_algo:
+                                /* write sig size here */
+                                c16toa((word16)args->sigSz,
+                                    args->output + args->idx);
+                                args->idx += LENGTH_SZ;
+                                break;
+                        #endif
+                        #endif /* !NO_RSA */
+                            case ecc_dsa_sa_algo:
+                            {
+                                break;
+                            }
+                        #ifdef  HAVE_ED25519
+                            case ed25519_sa_algo:
+                                ret = Ed25519CheckPubKey(ssl);
+                                if (ret != 0)
+                                    goto exit_sske;
+                                break;
+                        #endif /* HAVE_ED25519 */
+                        #ifdef  HAVE_ED448
+                            case ed448_sa_algo:
+                                ret = Ed448CheckPubKey(ssl);
+                                if (ret != 0)
+                                    goto exit_sske;
+                                break;
+                        #endif /* HAVE_ED448 */
+                        } /* switch(ssl->specs.sig_algo) */
+                        break;
+                    }
+                #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+                #if !defined(NO_DH) && !defined(NO_RSA)
+                    case diffie_hellman_kea:
+                    {
+                        enum wc_HashType hashType;
+
+                        args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+                        args->length = LENGTH_SZ * 3;  /* p, g, pub */
+                        args->length += ssl->buffers.serverDH_P.length +
+                                        ssl->buffers.serverDH_G.length +
+                                        ssl->buffers.serverDH_Pub.length;
+
+                        preSigIdx = args->idx;
+                        preSigSz  = args->length;
+
+                        if (!ssl->options.usingAnon_cipher) {
+                            word16 keySz;
+
+                            /* sig length */
+                            args->length += LENGTH_SZ;
+
+                            if (ssl->buffers.key == NULL) {
+                            #ifdef HAVE_PK_CALLBACKS
+                                if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx))
+                                    keySz = (word32)GetPrivateKeySigSize(ssl);
+                                else
+                            #endif
+                                    ERROR_OUT(NO_PRIVATE_KEY, exit_sske);
+                            }
+                            else
+                            {
+                                if (ssl->buffers.keyType == 0)
+                                    ssl->buffers.keyType = rsa_sa_algo;
+                                ret = DecodePrivateKey(ssl, &keySz);
+                                if (ret != 0) {
+                                    goto exit_sske;
+                                }
+                            }
+
+                            if (keySz == 0) { /* test if keySz has error */
+                                ERROR_OUT(keySz, exit_sske);
+                            }
+
+                            args->tmpSigSz = (word32)keySz;
+                            args->length += args->tmpSigSz;
+
+                            if (IsAtLeastTLSv1_2(ssl)) {
+                                args->length += HASH_SIG_SIZE;
+                            }
+                        }
+
+                        args->sendSz = args->length + HANDSHAKE_HEADER_SZ +
+                                                            RECORD_HEADER_SZ;
+
+                    #ifdef HAVE_QSH
+                        args->length += args->qshSz;
+                        args->sendSz += args->qshSz;
+                    #endif
+                    #ifdef WOLFSSL_DTLS
+                        if (ssl->options.dtls) {
+                            args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+                            args->idx    += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+                            preSigIdx = args->idx;
+                        }
+                    #endif
+
+                        if (IsEncryptionOn(ssl, 1)) {
+                            args->sendSz += MAX_MSG_EXTRA;
+                        }
+
+                        /* check for available size */
+                        if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
+                            goto exit_sske;
+                        }
+
+                        /* get output buffer */
+                        args->output = ssl->buffers.outputBuffer.buffer +
+                                       ssl->buffers.outputBuffer.length;
+
+                        AddHeaders(args->output, args->length,
+                                                    server_key_exchange, ssl);
+
+                        /* add p, g, pub */
+                        c16toa((word16)ssl->buffers.serverDH_P.length,
+                                                    args->output + args->idx);
+                        args->idx += LENGTH_SZ;
+                        XMEMCPY(args->output + args->idx,
+                                              ssl->buffers.serverDH_P.buffer,
+                                              ssl->buffers.serverDH_P.length);
+                        args->idx += ssl->buffers.serverDH_P.length;
+
+                        /*  g */
+                        c16toa((word16)ssl->buffers.serverDH_G.length,
+                                                    args->output + args->idx);
+                        args->idx += LENGTH_SZ;
+                        XMEMCPY(args->output + args->idx,
+                                              ssl->buffers.serverDH_G.buffer,
+                                              ssl->buffers.serverDH_G.length);
+                        args->idx += ssl->buffers.serverDH_G.length;
+
+                        /*  pub */
+                        c16toa((word16)ssl->buffers.serverDH_Pub.length,
+                                                    args->output + args->idx);
+                        args->idx += LENGTH_SZ;
+                        XMEMCPY(args->output + args->idx,
+                                              ssl->buffers.serverDH_Pub.buffer,
+                                              ssl->buffers.serverDH_Pub.length);
+                        args->idx += ssl->buffers.serverDH_Pub.length;
+
+                    #ifdef HAVE_FUZZER
+                        if (ssl->fuzzerCb) {
+                            ssl->fuzzerCb(ssl, args->output + preSigIdx,
+                                preSigSz, FUZZ_SIGNATURE, ssl->fuzzerCtx);
+                        }
+                    #endif
+
+                        if (ssl->options.usingAnon_cipher) {
+                            break;
+                        }
+
+                        /* Determine hash type */
+                        if (IsAtLeastTLSv1_2(ssl)) {
+                            EncodeSigAlg(ssl->suites->hashAlgo,
+                                         ssl->suites->sigAlgo,
+                                         &args->output[args->idx]);
+                            args->idx += 2;
+
+                            hashType = HashAlgoToType(ssl->suites->hashAlgo);
+                            if (hashType == WC_HASH_TYPE_NONE) {
+                                ERROR_OUT(ALGO_ID_E, exit_sske);
+                            }
+                        } else {
+                            /* only using sha and md5 for rsa */
+                        #ifndef NO_OLD_TLS
+                            hashType = WC_HASH_TYPE_SHA;
+                            if (ssl->suites->sigAlgo == rsa_sa_algo) {
+                                hashType = WC_HASH_TYPE_MD5_SHA;
+                            }
+                        #else
+                            ERROR_OUT(ALGO_ID_E, exit_sske);
+                        #endif
+                        }
+
+                        /* signature size */
+                        c16toa((word16)args->tmpSigSz, args->output + args->idx);
+                        args->idx += LENGTH_SZ;
+
+                        /* Assemble buffer to hash for signature */
+                        args->sigDataSz = RAN_LEN + RAN_LEN + preSigSz;
+                        args->sigDataBuf = (byte*)XMALLOC(args->sigDataSz,
+                                            ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+                        if (args->sigDataBuf == NULL) {
+                            ERROR_OUT(MEMORY_E, exit_sske);
+                        }
+                        XMEMCPY(args->sigDataBuf, ssl->arrays->clientRandom,
+                                                                    RAN_LEN);
+                        XMEMCPY(args->sigDataBuf+RAN_LEN,
+                                        ssl->arrays->serverRandom, RAN_LEN);
+                        XMEMCPY(args->sigDataBuf+RAN_LEN+RAN_LEN,
+                            args->output + preSigIdx, preSigSz);
+
+                        if (ssl->suites->sigAlgo != ed25519_sa_algo &&
+                                        ssl->suites->sigAlgo != ed448_sa_algo) {
+                            ssl->buffers.sig.length =
+                                                 wc_HashGetDigestSize(hashType);
+                            ssl->buffers.sig.buffer = (byte*)XMALLOC(
+                                             ssl->buffers.sig.length, ssl->heap,
+                                                       DYNAMIC_TYPE_SIGNATURE);
+                            if (ssl->buffers.sig.buffer == NULL) {
+                                ERROR_OUT(MEMORY_E, exit_sske);
+                            }
+
+                            /* Perform hash */
+                            ret = wc_Hash(hashType, args->sigDataBuf,
+                                                       args->sigDataSz,
+                                                       ssl->buffers.sig.buffer,
+                                                       ssl->buffers.sig.length);
+                            if (ret != 0) {
+                                goto exit_sske;
+                            }
+                        }
+
+                        args->sigSz = args->tmpSigSz;
+
+                        /* Sign hash to create signature */
+                        switch (ssl->suites->sigAlgo)
+                        {
+                        #ifndef NO_RSA
+                            case rsa_sa_algo:
+                            {
+                                /* For TLS 1.2 re-encode signature */
+                                if (IsAtLeastTLSv1_2(ssl)) {
+                                    byte* encodedSig = (byte*)XMALLOC(
+                                                  MAX_ENCODED_SIG_SZ, ssl->heap,
+                                                       DYNAMIC_TYPE_SIGNATURE);
+                                    if (encodedSig == NULL) {
+                                        ERROR_OUT(MEMORY_E, exit_sske);
+                                    }
+
+                                    ssl->buffers.sig.length =
+                                        wc_EncodeSignature(encodedSig,
+                                            ssl->buffers.sig.buffer,
+                                            ssl->buffers.sig.length,
+                                            TypeHash(ssl->suites->hashAlgo));
+
+                                    /* Replace sig buffer with new one */
+                                    XFREE(ssl->buffers.sig.buffer, ssl->heap,
+                                                       DYNAMIC_TYPE_SIGNATURE);
+                                    ssl->buffers.sig.buffer = encodedSig;
+                                }
+                                break;
+                            }
+                        #endif /* NO_RSA */
+                        } /* switch (ssl->suites->sigAlgo) */
+                        break;
+                    }
+                #endif /* !defined(NO_DH) && !defined(NO_RSA) */
+                } /* switch(ssl->specs.kea) */
+
+                /* Check for error */
+                if (ret != 0) {
+                    goto exit_sske;
+                }
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_DO;
+            } /* case TLS_ASYNC_BUILD */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_DO:
+            {
+                switch(ssl->specs.kea)
+                {
+                #ifndef NO_PSK
+                    case psk_kea:
+                    {
+                        break;
+                    }
+                #endif /* !NO_PSK */
+                #if !defined(NO_DH) && !defined(NO_PSK)
+                    case dhe_psk_kea:
+                    {
+                        break;
+                    }
+                #endif /* !defined(NO_DH) && !defined(NO_PSK) */
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                     defined(HAVE_CURVE448)) && !defined(NO_PSK)
+                    case ecdhe_psk_kea:
+                    {
+                        break;
+                    }
+                #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */
+                #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+                                                             defined(HAVE_ED448)
+                    case ecc_diffie_hellman_kea:
+                    {
+                        /* Sign hash to create signature */
+                        switch (ssl->suites->sigAlgo)
+                        {
+                        #ifndef NO_RSA
+                        #ifdef WC_RSA_PSS
+                            case rsa_pss_sa_algo:
+                        #endif
+                            case rsa_sa_algo:
+                            {
+                                RsaKey* key = (RsaKey*)ssl->hsKey;
+
+                                ret = RsaSign(ssl,
+                                    ssl->buffers.sig.buffer,
+                                    ssl->buffers.sig.length,
+                                    args->output + args->idx,
+                                    &args->sigSz,
+                                    ssl->suites->sigAlgo, ssl->suites->hashAlgo,
+                                    key,
+                                    ssl->buffers.key
+                                );
+                                break;
+                            }
+                        #endif /* !NO_RSA */
+                        #ifdef HAVE_ECC
+                            case ecc_dsa_sa_algo:
+                            {
+                                ecc_key* key = (ecc_key*)ssl->hsKey;
+
+                                ret = EccSign(ssl,
+                                    ssl->buffers.sig.buffer,
+                                    ssl->buffers.sig.length,
+                                    args->output + LENGTH_SZ + args->idx,
+                                    &args->sigSz,
+                                    key,
+                            #ifdef HAVE_PK_CALLBACKS
+                                    ssl->buffers.key
+                            #else
+                                    NULL
+                            #endif
+                                );
+                                break;
+                            }
+                        #endif /* HAVE_ECC */
+                        #ifdef HAVE_ED25519
+                            case ed25519_sa_algo:
+                            {
+                                ed25519_key* key = (ed25519_key*)ssl->hsKey;
+
+                                ret = Ed25519Sign(ssl,
+                                    args->sigDataBuf, args->sigDataSz,
+                                    args->output + LENGTH_SZ + args->idx,
+                                    &args->sigSz,
+                                    key,
+                            #ifdef HAVE_PK_CALLBACKS
+                                    ssl->buffers.key
+                            #else
+                                    NULL
+                            #endif
+                                );
+                                break;
+                            }
+                        #endif
+                        #ifdef HAVE_ED448
+                            case ed448_sa_algo:
+                            {
+                                ed448_key* key = (ed448_key*)ssl->hsKey;
+
+                                ret = Ed448Sign(ssl,
+                                    args->sigDataBuf, args->sigDataSz,
+                                    args->output + LENGTH_SZ + args->idx,
+                                    &args->sigSz,
+                                    key,
+                            #ifdef HAVE_PK_CALLBACKS
+                                    ssl->buffers.key
+                            #else
+                                    NULL
+                            #endif
+                                );
+                                break;
+                            }
+                        #endif
+                        } /* switch(ssl->specs.sig_algo) */
+                        break;
+                    }
+                #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+                #if !defined(NO_DH) && !defined(NO_RSA)
+                    case diffie_hellman_kea:
+                    {
+                        /* Sign hash to create signature */
+                        switch (ssl->suites->sigAlgo)
+                        {
+                        #ifndef NO_RSA
+                        #ifdef WC_RSA_PSS
+                            case rsa_pss_sa_algo:
+                        #endif
+                            case rsa_sa_algo:
+                            {
+                                RsaKey* key = (RsaKey*)ssl->hsKey;
+
+                                if (ssl->options.usingAnon_cipher) {
+                                    break;
+                                }
+
+                                ret = RsaSign(ssl,
+                                    ssl->buffers.sig.buffer,
+                                    ssl->buffers.sig.length,
+                                    args->output + args->idx,
+                                    &args->sigSz,
+                                    ssl->suites->sigAlgo, ssl->suites->hashAlgo,
+                                    key,
+                                    ssl->buffers.key
+                                );
+                                break;
+                            }
+                        #endif /* NO_RSA */
+                        } /* switch (ssl->suites->sigAlgo) */
+
+                        break;
+                    }
+                #endif /* !defined(NO_DH) && !defined(NO_RSA) */
+                } /* switch(ssl->specs.kea) */
+
+                /* Check for error */
+                if (ret != 0) {
+                    goto exit_sske;
+                }
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_VERIFY;
+            } /* case TLS_ASYNC_DO */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_VERIFY:
+            {
+                switch(ssl->specs.kea)
+                {
+                #ifndef NO_PSK
+                    case psk_kea:
+                    {
+                        /* Nothing to do in this sub-state */
+                        break;
+                    }
+                #endif /* !NO_PSK */
+                #if !defined(NO_DH) && !defined(NO_PSK)
+                    case dhe_psk_kea:
+                    {
+                        /* Nothing to do in this sub-state */
+                        break;
+                    }
+                #endif /* !defined(NO_DH) && !defined(NO_PSK) */
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) ||  \
+                                     defined(HAVE_CURVE448)) && !defined(NO_PSK)
+                    case ecdhe_psk_kea:
+                    {
+                        /* Nothing to do in this sub-state */
+                        break;
+                    }
+                #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */
+                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                                          defined(HAVE_CURVE448)
+                    case ecc_diffie_hellman_kea:
+                    {
+                        switch(ssl->suites->sigAlgo)
+                        {
+                        #ifndef NO_RSA
+                        #ifdef WC_RSA_PSS
+                            case rsa_pss_sa_algo:
+                        #endif
+                            case rsa_sa_algo:
+                            {
+                                RsaKey* key = (RsaKey*)ssl->hsKey;
+
+                                if (args->verifySig == NULL) {
+                                    if (args->sigSz == 0) {
+                                        ERROR_OUT(BAD_COND_E, exit_sske);
+                                    }
+                                    args->verifySig = (byte*)XMALLOC(
+                                                    args->sigSz, ssl->heap,
+                                                    DYNAMIC_TYPE_SIGNATURE);
+                                    if (!args->verifySig) {
+                                        ERROR_OUT(MEMORY_E, exit_sske);
+                                    }
+                                    XMEMCPY(args->verifySig,
+                                        args->output + args->idx, args->sigSz);
+                                }
+
+                                /* check for signature faults */
+                                ret = VerifyRsaSign(ssl,
+                                    args->verifySig, args->sigSz,
+                                    ssl->buffers.sig.buffer,
+                                    ssl->buffers.sig.length,
+                                    ssl->suites->sigAlgo, ssl->suites->hashAlgo,
+                                    key, ssl->buffers.key
+                                );
+                                break;
+                            }
+                        #endif
+                            case ecc_dsa_sa_algo:
+                        #ifdef HAVE_ED25519
+                            case ed25519_sa_algo:
+                        #endif
+                        #ifdef HAVE_ED448
+                            case ed448_sa_algo:
+                        #endif
+                            {
+                                /* Now that we know the real sig size, write it. */
+                                c16toa((word16)args->sigSz,
+                                                    args->output + args->idx);
+
+                                /* And adjust length and sendSz from estimates */
+                                args->length += args->sigSz - args->tmpSigSz;
+                                args->sendSz += args->sigSz - args->tmpSigSz;
+                                break;
+                            }
+                            default:
+                                ERROR_OUT(ALGO_ID_E, exit_sske);  /* unsupported type */
+                        } /* switch(ssl->specs.sig_algo) */
+                        break;
+                    }
+                #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+                #if !defined(NO_DH) && !defined(NO_RSA)
+                    case diffie_hellman_kea:
+                    {
+                        switch (ssl->suites->sigAlgo)
+                        {
+                        #ifndef NO_RSA
+                        #ifndef WC_RSA_PSS
+                            case rsa_pss_sa_algo:
+                        #endif
+                            case rsa_sa_algo:
+                            {
+                                RsaKey* key = (RsaKey*)ssl->hsKey;
+
+                                if (ssl->options.usingAnon_cipher) {
+                                    break;
+                                }
+
+                                if (args->verifySig == NULL) {
+                                    if (args->sigSz == 0) {
+                                        ERROR_OUT(BAD_COND_E, exit_sske);
+                                    }
+                                    args->verifySig = (byte*)XMALLOC(
+                                                      args->sigSz, ssl->heap,
+                                                      DYNAMIC_TYPE_SIGNATURE);
+                                    if (!args->verifySig) {
+                                        ERROR_OUT(MEMORY_E, exit_sske);
+                                    }
+                                    XMEMCPY(args->verifySig,
+                                        args->output + args->idx, args->sigSz);
+                                }
+
+                                /* check for signature faults */
+                                ret = VerifyRsaSign(ssl,
+                                    args->verifySig, args->sigSz,
+                                    ssl->buffers.sig.buffer,
+                                    ssl->buffers.sig.length,
+                                    ssl->suites->sigAlgo, ssl->suites->hashAlgo,
+                                    key, ssl->buffers.key
+                                );
+                                break;
+                            }
+                        #endif
+                        } /* switch (ssl->suites->sigAlgo) */
+                        break;
+                    }
+                #endif /* !defined(NO_DH) && !defined(NO_RSA) */
+                } /* switch(ssl->specs.kea) */
+
+                /* Check for error */
+                if (ret != 0) {
+                    goto exit_sske;
+                }
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_FINALIZE;
+            } /* case TLS_ASYNC_VERIFY */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_FINALIZE:
+            {
+            #ifdef HAVE_QSH
+                if (ssl->peerQSHKeyPresent) {
+                    if (args->qshSz > 0) {
+                        args->idx = args->sendSz - args->qshSz;
+                        if (QSH_KeyExchangeWrite(ssl, 1) != 0) {
+                            ERROR_OUT(MEMORY_E, exit_sske);
+                        }
+
+                        /* extension type */
+                        c16toa(TLSX_QUANTUM_SAFE_HYBRID,
+                                                    args->output + args->idx);
+                        args->idx += OPAQUE16_LEN;
+
+                        /* write to output and check amount written */
+                        if (TLSX_QSHPK_Write(ssl->QSH_secret->list,
+                            args->output + args->idx) >
+                                                args->qshSz - OPAQUE16_LEN) {
+                            ERROR_OUT(MEMORY_E, exit_sske);
+                        }
+                    }
+                }
+            #endif
+
+            #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                                          defined(HAVE_CURVE448)
+                if (ssl->specs.kea == ecdhe_psk_kea ||
+                    ssl->specs.kea == ecc_diffie_hellman_kea) {
+                    /* Check output to make sure it was set */
+                    if (args->output) {
+                        AddHeaders(args->output, args->length,
+                                                    server_key_exchange, ssl);
+                    }
+                    else {
+                        ERROR_OUT(BUFFER_ERROR, exit_sske);
+                    }
+                }
+            #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+
+                if (IsEncryptionOn(ssl, 1)) {
+                    args->inputSz = args->length + HANDSHAKE_HEADER_SZ;
+                                                     /* buildmsg adds rechdr */
+                    args->input = (byte*)XMALLOC(args->inputSz, ssl->heap,
+                                                        DYNAMIC_TYPE_IN_BUFFER);
+                    if (args->input == NULL) {
+                        ERROR_OUT(MEMORY_E, exit_sske);
+                    }
+
+                    if (args->output == NULL) {
+                        ERROR_OUT(BUFFER_ERROR, exit_sske);
+                    }
+
+                    XMEMCPY(args->input, args->output + RECORD_HEADER_SZ,
+                                                                 args->inputSz);
+                    ret = BuildMessage(ssl, args->output, args->sendSz,
+                                args->input, args->inputSz, handshake, 1, 0, 0);
+                    XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+                    args->input = NULL;
+                        /* make sure its not double free'd on cleanup */
+
+                    if (ret >= 0) {
+                        args->sendSz = ret;
+                        ret = 0;
+                    }
+                }
+                else {
+                #ifdef WOLFSSL_DTLS
+                    if (IsDtlsNotSctpMode(ssl)) {
+                        if ((ret = DtlsMsgPoolSave(ssl,
+                                            args->output, args->sendSz)) != 0) {
+                            goto exit_sske;
+                        }
+                    }
+
+                    if (ssl->options.dtls)
+                        DtlsSEQIncrement(ssl, CUR_ORDER);
+                #endif
+
+                    ret = HashOutput(ssl, args->output, args->sendSz, 0);
+                    if (ret != 0) {
+                        goto exit_sske;
+                    }
+                }
+
+            #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+                if (ssl->hsInfoOn) {
+                    AddPacketName(ssl, "ServerKeyExchange");
+                }
+                if (ssl->toInfoOn) {
+                    AddPacketInfo(ssl, "ServerKeyExchange", handshake,
+                        args->output, args->sendSz, WRITE_PROTO, ssl->heap);
+                }
+            #endif
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_END;
+            } /* case TLS_ASYNC_FINALIZE */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_END:
+            {
+                ssl->buffers.outputBuffer.length += args->sendSz;
+                if (!ssl->options.groupMessages) {
+                    ret = SendBuffered(ssl);
+                }
+
+                ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
+                break;
+            }
+            default:
+                ret = INPUT_CASE_ERROR;
+        } /* switch(ssl->options.asyncState) */
+
+    exit_sske:
+
+        WOLFSSL_LEAVE("SendServerKeyExchange", ret);
+        WOLFSSL_END(WC_FUNC_SERVER_KEY_EXCHANGE_SEND);
+
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        /* Handle async operation */
+        if (ret == WC_PENDING_E)
+            return ret;
+    #endif /* WOLFSSL_ASYNC_CRYPT */
+
+        /* Final cleanup */
+        FreeSskeArgs(ssl, args);
+        FreeKeyExchange(ssl);
+
+        return ret;
+    }
+
+#if defined(HAVE_SERVER_RENEGOTIATION_INFO) || defined(HAVE_FALLBACK_SCSV) || \
+                                                            defined(OPENSSL_ALL)
+
+    /* search suites for specific one, idx on success, negative on error */
+#ifndef WOLFSSL_TLS13
+    static
+#endif
+    int FindSuite(Suites* suites, byte first, byte second)
+    {
+        int i;
+
+        if (suites == NULL || suites->suiteSz == 0) {
+            WOLFSSL_MSG("Suites pointer error or suiteSz 0");
+            return SUITES_ERROR;
+        }
+
+        for (i = 0; i < suites->suiteSz-1; i += SUITE_LEN) {
+            if (suites->suites[i]   == first &&
+                suites->suites[i+1] == second )
+                return i;
+        }
+
+        return MATCH_SUITE_ERROR;
+    }
+
+#endif
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+    /* Make sure server cert/key are valid for this suite, true on success */
+    static int VerifyServerSuite(WOLFSSL* ssl, word16 idx)
+    {
+        int  haveRSA = !ssl->options.haveStaticECC;
+        int  havePSK = 0;
+        byte first;
+        byte second;
+
+        WOLFSSL_ENTER("VerifyServerSuite");
+
+        if (ssl->suites == NULL) {
+            WOLFSSL_MSG("Suites pointer error");
+            return 0;
+        }
+
+        first   = ssl->suites->suites[idx];
+        second  = ssl->suites->suites[idx+1];
+
+        #ifndef NO_PSK
+            havePSK = ssl->options.havePSK;
+        #endif
+
+        if (ssl->options.haveNTRU)
+            haveRSA = 0;
+
+        if (CipherRequires(first, second, REQUIRES_RSA)) {
+            WOLFSSL_MSG("Requires RSA");
+            if (haveRSA == 0) {
+                WOLFSSL_MSG("Don't have RSA");
+                return 0;
+            }
+        }
+
+        if (CipherRequires(first, second, REQUIRES_DHE)) {
+            WOLFSSL_MSG("Requires DHE");
+            if (ssl->options.haveDH == 0) {
+                WOLFSSL_MSG("Don't have DHE");
+                return 0;
+            }
+        }
+
+        if (CipherRequires(first, second, REQUIRES_ECC)) {
+            WOLFSSL_MSG("Requires ECC");
+            if (ssl->options.haveECC == 0) {
+                WOLFSSL_MSG("Don't have ECC");
+                return 0;
+            }
+        }
+
+        if (CipherRequires(first, second, REQUIRES_ECC_STATIC)) {
+            WOLFSSL_MSG("Requires static ECC");
+            if (ssl->options.haveStaticECC == 0) {
+                WOLFSSL_MSG("Don't have static ECC");
+                return 0;
+            }
+        }
+
+        if (CipherRequires(first, second, REQUIRES_PSK)) {
+            WOLFSSL_MSG("Requires PSK");
+            if (havePSK == 0) {
+                WOLFSSL_MSG("Don't have PSK");
+                return 0;
+            }
+        }
+
+        if (CipherRequires(first, second, REQUIRES_NTRU)) {
+            WOLFSSL_MSG("Requires NTRU");
+            if (ssl->options.haveNTRU == 0) {
+                WOLFSSL_MSG("Don't have NTRU");
+                return 0;
+            }
+        }
+
+        if (CipherRequires(first, second, REQUIRES_RSA_SIG)) {
+            WOLFSSL_MSG("Requires RSA Signature");
+            if (ssl->options.side == WOLFSSL_SERVER_END &&
+                                           ssl->options.haveECDSAsig == 1) {
+                WOLFSSL_MSG("Don't have RSA Signature");
+                return 0;
+            }
+        }
+
+#if !defined(WOLFSSL_OLDTLS_AEAD_CIPHERSUITES)
+        if (CipherRequires(first, second, REQUIRES_AEAD)) {
+            WOLFSSL_MSG("Requires AEAD");
+            if (ssl->version.major == SSLv3_MAJOR &&
+                                           ssl->version.minor < TLSv1_2_MINOR) {
+                WOLFSSL_MSG("Version of SSL does not support AEAD ciphers");
+                return 0;
+            }
+
+        }
+#endif
+
+#if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                       defined(HAVE_CURVE448)) && defined(HAVE_SUPPORTED_CURVES)
+        if (!TLSX_ValidateSupportedCurves(ssl, first, second)) {
+            WOLFSSL_MSG("Don't have matching curves");
+            return 0;
+        }
+#endif
+
+        /* ECCDHE is always supported if ECC on */
+
+#ifdef HAVE_QSH
+        /* need to negotiate a classic suite in addition to TLS_QSH */
+        if (first == QSH_BYTE && second == TLS_QSH) {
+            if (TLSX_SupportExtensions(ssl)) {
+                ssl->options.haveQSH = 1; /* matched TLS_QSH */
+            }
+            else {
+                WOLFSSL_MSG("Version of SSL connection does not support "
+                            "TLS_QSH");
+            }
+            return 0;
+        }
+#endif
+
+#ifdef WOLFSSL_TLS13
+        if (IsAtLeastTLSv1_3(ssl->version) &&
+            ssl->options.side == WOLFSSL_SERVER_END) {
+            /* Try to establish a key share. */
+            int ret = TLSX_KeyShare_Establish(ssl);
+            if (ret == KEY_SHARE_ERROR)
+                ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE;
+            else if (ret != 0)
+                return 0;
+        }
+        else if (first == TLS13_BYTE || (first == ECC_BYTE &&
+                (second == TLS_SHA256_SHA256 || second == TLS_SHA384_SHA384))) {
+            /* Can't negotiate TLS 1.3 cipher suites with lower protocol
+             * version. */
+            return 0;
+        }
+#endif
+
+        return 1;
+    }
+
+#ifndef NO_WOLFSSL_SERVER
+    static int CompareSuites(WOLFSSL* ssl, Suites* peerSuites, word16 i,
+                             word16 j)
+    {
+        if (ssl->suites->suites[i]   == peerSuites->suites[j] &&
+            ssl->suites->suites[i+1] == peerSuites->suites[j+1] ) {
+
+            if (VerifyServerSuite(ssl, i)) {
+                int result;
+                WOLFSSL_MSG("Verified suite validity");
+                ssl->options.cipherSuite0 = ssl->suites->suites[i];
+                ssl->options.cipherSuite  = ssl->suites->suites[i+1];
+                result = SetCipherSpecs(ssl);
+                if (result == 0) {
+                    result = PickHashSigAlgo(ssl, peerSuites->hashSigAlgo,
+                                                     peerSuites->hashSigAlgoSz);
+                }
+                return result;
+            }
+            else {
+                WOLFSSL_MSG("Could not verify suite validity, continue");
+            }
+        }
+
+        return MATCH_SUITE_ERROR;
+    }
+
+    int MatchSuite(WOLFSSL* ssl, Suites* peerSuites)
+    {
+        int ret;
+        word16 i, j;
+
+        WOLFSSL_ENTER("MatchSuite");
+
+        /* & 0x1 equivalent % 2 */
+        if (peerSuites->suiteSz == 0 || peerSuites->suiteSz & 0x1)
+            return BUFFER_ERROR;
+
+        if (ssl->suites == NULL)
+            return SUITES_ERROR;
+
+        if (!ssl->options.useClientOrder) {
+            /* Server order */
+            for (i = 0; i < ssl->suites->suiteSz; i += 2) {
+                for (j = 0; j < peerSuites->suiteSz; j += 2) {
+                    ret = CompareSuites(ssl, peerSuites, i, j);
+                    if (ret != MATCH_SUITE_ERROR)
+                        return ret;
+                }
+            }
+        }
+        else {
+            /* Client order */
+            for (j = 0; j < peerSuites->suiteSz; j += 2) {
+                for (i = 0; i < ssl->suites->suiteSz; i += 2) {
+                    ret = CompareSuites(ssl, peerSuites, i, j);
+                    if (ret != MATCH_SUITE_ERROR)
+                        return ret;
+                }
+            }
+        }
+
+        return MATCH_SUITE_ERROR;
+    }
+#endif
+
+#ifdef OLD_HELLO_ALLOWED
+
+    /* process old style client hello, deprecate? */
+    int ProcessOldClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                              word32 inSz, word16 sz)
+    {
+        word32          idx = *inOutIdx;
+        word16          sessionSz;
+        word16          randomSz;
+        word16          i, j;
+        ProtocolVersion pv;
+        Suites          clSuites;
+        int ret = -1;
+
+        (void)inSz;
+        WOLFSSL_MSG("Got old format client hello");
+#ifdef WOLFSSL_CALLBACKS
+        if (ssl->hsInfoOn)
+            AddPacketName(ssl, "ClientHello");
+        if (ssl->toInfoOn)
+            AddLateName("ClientHello", &ssl->timeoutInfo);
+#endif
+
+        /* manually hash input since different format */
+#ifndef NO_OLD_TLS
+#ifndef NO_MD5
+        wc_Md5Update(&ssl->hsHashes->hashMd5, input + idx, sz);
+#endif
+#ifndef NO_SHA
+        wc_ShaUpdate(&ssl->hsHashes->hashSha, input + idx, sz);
+#endif
+#endif
+#ifndef NO_SHA256
+        if (IsAtLeastTLSv1_2(ssl)) {
+            int shaRet = wc_Sha256Update(&ssl->hsHashes->hashSha256,
+                                         input + idx, sz);
+            if (shaRet != 0)
+                return shaRet;
+        }
+#endif
+
+        /* does this value mean client_hello? */
+        idx++;
+
+        /* version */
+        pv.major = input[idx++];
+        pv.minor = input[idx++];
+        ssl->chVersion = pv;  /* store */
+
+        if (ssl->version.minor > pv.minor) {
+            byte haveRSA = 0;
+            byte havePSK = 0;
+            int  keySz   = 0;
+
+            if (!ssl->options.downgrade) {
+                WOLFSSL_MSG("Client trying to connect with lesser version");
+                return VERSION_ERROR;
+            }
+            if (pv.minor < ssl->options.minDowngrade) {
+                WOLFSSL_MSG("\tversion below minimum allowed, fatal error");
+                return VERSION_ERROR;
+            }
+            if (pv.minor == SSLv3_MINOR) {
+                /* turn off tls */
+                WOLFSSL_MSG("\tdowngrading to SSLv3");
+                ssl->options.tls    = 0;
+                ssl->options.tls1_1 = 0;
+                ssl->version.minor  = SSLv3_MINOR;
+            }
+            else if (pv.minor == TLSv1_MINOR) {
+                WOLFSSL_MSG("\tdowngrading to TLSv1");
+                /* turn off tls 1.1+ */
+                ssl->options.tls1_1 = 0;
+                ssl->version.minor  = TLSv1_MINOR;
+            }
+            else if (pv.minor == TLSv1_1_MINOR) {
+                WOLFSSL_MSG("\tdowngrading to TLSv1.1");
+                ssl->version.minor  = TLSv1_1_MINOR;
+            }
+            else if (pv.minor == TLSv1_2_MINOR) {
+                WOLFSSL_MSG("    downgrading to TLSv1.2");
+                ssl->version.minor  = TLSv1_2_MINOR;
+            }
+#ifndef NO_RSA
+            haveRSA = 1;
+#endif
+#ifndef NO_PSK
+            havePSK = ssl->options.havePSK;
+#endif
+#ifndef NO_CERTS
+            keySz = ssl->buffers.keySz;
+#endif
+
+            InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
+                       ssl->options.haveDH, ssl->options.haveNTRU,
+                       ssl->options.haveECDSAsig, ssl->options.haveECC,
+                       ssl->options.haveStaticECC, ssl->options.side);
+        }
+
+        /* suite size */
+        ato16(&input[idx], &clSuites.suiteSz);
+        idx += OPAQUE16_LEN;
+
+        if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ)
+            return BUFFER_ERROR;
+        clSuites.hashSigAlgoSz = 0;
+
+        /* session size */
+        ato16(&input[idx], &sessionSz);
+        idx += OPAQUE16_LEN;
+
+        if (sessionSz > ID_LEN)
+            return BUFFER_ERROR;
+
+        /* random size */
+        ato16(&input[idx], &randomSz);
+        idx += OPAQUE16_LEN;
+
+        if (randomSz > RAN_LEN)
+            return BUFFER_ERROR;
+
+        /* suites */
+        for (i = 0, j = 0; i < clSuites.suiteSz; i += 3) {
+            byte first = input[idx++];
+            if (!first) { /* implicit: skip sslv2 type */
+                XMEMCPY(&clSuites.suites[j], &input[idx], SUITE_LEN);
+                j += SUITE_LEN;
+            }
+            idx += SUITE_LEN;
+        }
+        clSuites.suiteSz = j;
+
+        /* session id */
+        if (sessionSz) {
+            XMEMCPY(ssl->arrays->sessionID, input + idx, sessionSz);
+            ssl->arrays->sessionIDSz = (byte)sessionSz;
+            idx += sessionSz;
+            ssl->options.resuming = 1;
+        }
+
+        /* random */
+        if (randomSz < RAN_LEN)
+            XMEMSET(ssl->arrays->clientRandom, 0, RAN_LEN - randomSz);
+        XMEMCPY(&ssl->arrays->clientRandom[RAN_LEN - randomSz], input + idx,
+               randomSz);
+        idx += randomSz;
+
+        if (ssl->options.usingCompression)
+            ssl->options.usingCompression = 0;  /* turn off */
+
+        ssl->options.clientState = CLIENT_HELLO_COMPLETE;
+        ssl->cbmode = SSL_CB_MODE_WRITE;
+        *inOutIdx = idx;
+
+        ssl->options.haveSessionId = 1;
+        /* DoClientHello uses same resume code */
+        if (ssl->options.resuming) {  /* let's try */
+            WOLFSSL_SESSION* session = GetSession(ssl,
+                                                  ssl->arrays->masterSecret, 1);
+            #ifdef HAVE_SESSION_TICKET
+                if (ssl->options.useTicket == 1) {
+                    session = &ssl->session;
+                }
+            #endif
+
+            if (!session) {
+                WOLFSSL_MSG("Session lookup for resume failed");
+                ssl->options.resuming = 0;
+            } else {
+            #ifdef HAVE_EXT_CACHE
+                wolfSSL_SESSION_free(session);
+            #endif
+                if (MatchSuite(ssl, &clSuites) < 0) {
+                    WOLFSSL_MSG("Unsupported cipher suite, OldClientHello");
+                    return UNSUPPORTED_SUITE;
+                }
+
+                ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->serverRandom,
+                                                                       RAN_LEN);
+                if (ret != 0)
+                    return ret;
+
+                #ifdef NO_OLD_TLS
+                    ret = DeriveTlsKeys(ssl);
+                #else
+                    #ifndef NO_TLS
+                        if (ssl->options.tls)
+                            ret = DeriveTlsKeys(ssl);
+                    #endif
+                        if (!ssl->options.tls)
+                            ret = DeriveKeys(ssl);
+                #endif
+                ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
+
+                return ret;
+            }
+        }
+
+        ret = MatchSuite(ssl, &clSuites);
+        if (ret != 0)return ret;
+        return SanityCheckMsgReceived(ssl, client_hello);
+    }
+
+#endif /* OLD_HELLO_ALLOWED */
+
+#ifndef WOLFSSL_NO_TLS12
+
+    int HandleTlsResumption(WOLFSSL* ssl, int bogusID, Suites* clSuites)
+    {
+        int ret = 0;
+        WOLFSSL_SESSION* session;
+
+        (void)bogusID;
+
+        session = GetSession(ssl, ssl->arrays->masterSecret, 1);
+        #ifdef HAVE_SESSION_TICKET
+            if (ssl->options.useTicket == 1) {
+                session = &ssl->session;
+            } else if (bogusID == 1 && ssl->options.rejectTicket == 0) {
+                WOLFSSL_MSG("Bogus session ID without session ticket");
+                return BUFFER_ERROR;
+            }
+        #endif
+
+        if (!session) {
+            WOLFSSL_MSG("Session lookup for resume failed");
+            ssl->options.resuming = 0;
+        }
+        else if (session->haveEMS != ssl->options.haveEMS) {
+            /* RFC 7627, 5.3, server-side */
+            /* if old sess didn't have EMS, but new does, full handshake */
+            if (!session->haveEMS && ssl->options.haveEMS) {
+                WOLFSSL_MSG("Attempting to resume a session that didn't "
+                            "use EMS with a new session with EMS. Do full "
+                            "handshake.");
+                ssl->options.resuming = 0;
+            }
+            /* if old sess used EMS, but new doesn't, MUST abort */
+            else if (session->haveEMS && !ssl->options.haveEMS) {
+                WOLFSSL_MSG("Trying to resume a session with EMS without "
+                            "using EMS");
+            #ifdef WOLFSSL_EXTRA_ALERTS
+                SendAlert(ssl, alert_fatal, handshake_failure);
+            #endif
+                return EXT_MASTER_SECRET_NEEDED_E;
+            }
+        #ifdef HAVE_EXT_CACHE
+            wolfSSL_SESSION_free(session);
+        #endif
+        }
+        else {
+        #ifndef NO_RESUME_SUITE_CHECK
+            int j;
+
+            /* Check client suites include the one in session */
+            for (j = 0; j < clSuites->suiteSz; j += 2) {
+                if (clSuites->suites[j] == session->cipherSuite0 &&
+                                clSuites->suites[j+1] == session->cipherSuite) {
+                    break;
+                }
+            }
+            if (j == clSuites->suiteSz) {
+                WOLFSSL_MSG("Prev session's cipher suite not in ClientHello");
+            #ifdef WOLFSSL_EXTRA_ALERTS
+                SendAlert(ssl, alert_fatal, illegal_parameter);
+            #endif
+                return UNSUPPORTED_SUITE;
+            }
+        #endif
+
+        #ifdef HAVE_EXT_CACHE
+            wolfSSL_SESSION_free(session);
+        #endif
+            if (MatchSuite(ssl, clSuites) < 0) {
+                WOLFSSL_MSG("Unsupported cipher suite, ClientHello");
+                return UNSUPPORTED_SUITE;
+            }
+
+            ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->serverRandom,
+                                                                       RAN_LEN);
+            if (ret != 0)
+                return ret;
+
+            #ifdef NO_OLD_TLS
+                ret = DeriveTlsKeys(ssl);
+            #else
+                #ifndef NO_TLS
+                    if (ssl->options.tls)
+                        ret = DeriveTlsKeys(ssl);
+                #endif
+                    if (!ssl->options.tls)
+                        ret = DeriveKeys(ssl);
+            #endif
+            ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
+        }
+
+        return ret;
+    }
+
+
+    /* handle processing of client_hello (1) */
+    int DoClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                             word32 helloSz)
+    {
+        byte            b;
+        byte            bogusID = 0;   /* flag for a bogus session id */
+        ProtocolVersion pv;
+        Suites          clSuites;
+        word32          i = *inOutIdx;
+        word32          begin = i;
+        int             ret = 0;
+#ifdef WOLFSSL_DTLS
+        Hmac            cookieHmac;
+        byte            peerCookie[MAX_COOKIE_LEN];
+        byte            peerCookieSz = 0;
+        byte            cookieType;
+        byte            cookieSz = 0;
+
+        XMEMSET(&cookieHmac, 0, sizeof(Hmac));
+#endif /* WOLFSSL_DTLS */
+
+        WOLFSSL_START(WC_FUNC_CLIENT_HELLO_DO);
+        WOLFSSL_ENTER("DoClientHello");
+
+#ifdef WOLFSSL_CALLBACKS
+        if (ssl->hsInfoOn) AddPacketName(ssl, "ClientHello");
+        if (ssl->toInfoOn) AddLateName("ClientHello", &ssl->timeoutInfo);
+#endif
+        /* protocol version, random and session id length check */
+        if (OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz)
+            return BUFFER_ERROR;
+
+        /* protocol version */
+        XMEMCPY(&pv, input + i, OPAQUE16_LEN);
+        ssl->chVersion = pv;   /* store */
+#ifdef WOLFSSL_DTLS
+        if (IsDtlsNotSctpMode(ssl)) {
+            #if defined(NO_SHA) && defined(NO_SHA256)
+                #error "DTLS needs either SHA or SHA-256"
+            #endif /* NO_SHA && NO_SHA256 */
+
+            #if !defined(NO_SHA) && defined(NO_SHA256)
+                cookieType = WC_SHA;
+                cookieSz = WC_SHA_DIGEST_SIZE;
+            #endif /* NO_SHA */
+            #ifndef NO_SHA256
+                cookieType = WC_SHA256;
+                cookieSz = WC_SHA256_DIGEST_SIZE;
+            #endif /* NO_SHA256 */
+            ret = wc_HmacSetKey(&cookieHmac, cookieType,
+                                ssl->buffers.dtlsCookieSecret.buffer,
+                                ssl->buffers.dtlsCookieSecret.length);
+            if (ret != 0) return ret;
+            ret = wc_HmacUpdate(&cookieHmac,
+                                (const byte*)ssl->buffers.dtlsCtx.peer.sa,
+                                ssl->buffers.dtlsCtx.peer.sz);
+            if (ret != 0) return ret;
+            ret = wc_HmacUpdate(&cookieHmac, input + i, OPAQUE16_LEN);
+            if (ret != 0) return ret;
+        }
+#endif /* WOLFSSL_DTLS */
+        i += OPAQUE16_LEN;
+
+        /* Legacy protocol version cannot negotiate TLS 1.3 or higher. */
+        if (pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_3_MINOR)
+            pv.minor = TLSv1_2_MINOR;
+
+        if ((!ssl->options.dtls && ssl->version.minor > pv.minor) ||
+            (ssl->options.dtls && ssl->version.minor != DTLS_MINOR
+             && ssl->version.minor != DTLSv1_2_MINOR && pv.minor != DTLS_MINOR
+             && pv.minor != DTLSv1_2_MINOR)) {
+
+            word16 haveRSA = 0;
+            word16 havePSK = 0;
+            int    keySz   = 0;
+
+            if (!ssl->options.downgrade) {
+                WOLFSSL_MSG("Client trying to connect with lesser version");
+                return VERSION_ERROR;
+            }
+            if (pv.minor < ssl->options.minDowngrade) {
+                WOLFSSL_MSG("\tversion below minimum allowed, fatal error");
+                return VERSION_ERROR;
+            }
+
+            if (pv.minor == SSLv3_MINOR) {
+                /* turn off tls */
+                WOLFSSL_MSG("\tdowngrading to SSLv3");
+                ssl->options.tls    = 0;
+                ssl->options.tls1_1 = 0;
+                ssl->version.minor  = SSLv3_MINOR;
+            }
+            else if (pv.minor == TLSv1_MINOR) {
+                /* turn off tls 1.1+ */
+                WOLFSSL_MSG("\tdowngrading to TLSv1");
+                ssl->options.tls1_1 = 0;
+                ssl->version.minor  = TLSv1_MINOR;
+            }
+            else if (pv.minor == TLSv1_1_MINOR) {
+                WOLFSSL_MSG("\tdowngrading to TLSv1.1");
+                ssl->version.minor  = TLSv1_1_MINOR;
+            }
+            else if (pv.minor == TLSv1_2_MINOR) {
+                WOLFSSL_MSG("    downgrading to TLSv1.2");
+                ssl->version.minor  = TLSv1_2_MINOR;
+            }
+#ifndef NO_RSA
+            haveRSA = 1;
+#endif
+#ifndef NO_PSK
+            havePSK = ssl->options.havePSK;
+#endif
+#ifndef NO_CERTS
+            keySz = ssl->buffers.keySz;
+#endif
+            InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
+                       ssl->options.haveDH, ssl->options.haveNTRU,
+                       ssl->options.haveECDSAsig, ssl->options.haveECC,
+                       ssl->options.haveStaticECC, ssl->options.side);
+        }
+
+#ifdef OPENSSL_EXTRA
+        /* check if option is set to not allow the current version
+         * set from either wolfSSL_set_options or wolfSSL_CTX_set_options */
+        if (!ssl->options.dtls && ssl->options.downgrade &&
+                ssl->options.mask > 0) {
+            int reset = 0;
+            if (ssl->version.minor == TLSv1_2_MINOR &&
+             (ssl->options.mask & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) {
+                WOLFSSL_MSG("\tOption set to not allow TLSv1.2, Downgrading");
+                ssl->version.minor = TLSv1_1_MINOR;
+                reset = 1;
+            }
+            if (ssl->version.minor == TLSv1_1_MINOR &&
+             (ssl->options.mask & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) {
+                WOLFSSL_MSG("\tOption set to not allow TLSv1.1, Downgrading");
+                ssl->options.tls1_1 = 0;
+                ssl->version.minor = TLSv1_MINOR;
+                reset = 1;
+            }
+            if (ssl->version.minor == TLSv1_MINOR &&
+                (ssl->options.mask & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) {
+                WOLFSSL_MSG("\tOption set to not allow TLSv1, Downgrading");
+                ssl->options.tls    = 0;
+                ssl->options.tls1_1 = 0;
+                ssl->version.minor = SSLv3_MINOR;
+                reset = 1;
+            }
+            if (ssl->version.minor == SSLv3_MINOR &&
+                (ssl->options.mask & SSL_OP_NO_SSLv3) == SSL_OP_NO_SSLv3) {
+                WOLFSSL_MSG("\tError, option set to not allow SSLv3");
+                return VERSION_ERROR;
+            }
+
+            if (ssl->version.minor < ssl->options.minDowngrade) {
+                WOLFSSL_MSG("\tversion below minimum allowed, fatal error");
+                return VERSION_ERROR;
+            }
+
+            if (reset) {
+                word16 haveRSA = 0;
+                word16 havePSK = 0;
+                int    keySz   = 0;
+
+            #ifndef NO_RSA
+                haveRSA = 1;
+            #endif
+            #ifndef NO_PSK
+                havePSK = ssl->options.havePSK;
+            #endif
+            #ifndef NO_CERTS
+                keySz = ssl->buffers.keySz;
+            #endif
+
+                /* reset cipher suites to account for TLS version change */
+                InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
+                       ssl->options.haveDH, ssl->options.haveNTRU,
+                       ssl->options.haveECDSAsig, ssl->options.haveECC,
+                       ssl->options.haveStaticECC, ssl->options.side);
+            }
+        }
+#endif
+
+        /* random */
+        XMEMCPY(ssl->arrays->clientRandom, input + i, RAN_LEN);
+#ifdef WOLFSSL_DTLS
+        if (IsDtlsNotSctpMode(ssl)) {
+            ret = wc_HmacUpdate(&cookieHmac, input + i, RAN_LEN);
+            if (ret != 0) return ret;
+        }
+#endif /* WOLFSSL_DTLS */
+        i += RAN_LEN;
+
+#ifdef SHOW_SECRETS
+        {
+            int j;
+            printf("client random: ");
+            for (j = 0; j < RAN_LEN; j++)
+                printf("%02x", ssl->arrays->clientRandom[j]);
+            printf("\n");
+        }
+#endif
+
+        /* session id */
+        b = input[i++];
+
+#ifdef HAVE_SESSION_TICKET
+        if (b > 0 && b < ID_LEN) {
+            bogusID = 1;
+            WOLFSSL_MSG("Client sent bogus session id, let's allow for echo");
+        }
+#endif
+
+        if (b == ID_LEN || bogusID) {
+            if ((i - begin) + b > helloSz)
+                return BUFFER_ERROR;
+
+            XMEMCPY(ssl->arrays->sessionID, input + i, b);
+#ifdef WOLFSSL_DTLS
+            if (IsDtlsNotSctpMode(ssl)) {
+                ret = wc_HmacUpdate(&cookieHmac, input + i - 1, b + 1);
+                if (ret != 0) return ret;
+            }
+#endif /* WOLFSSL_DTLS */
+            ssl->arrays->sessionIDSz = b;
+            i += b;
+            ssl->options.resuming = 1; /* client wants to resume */
+            WOLFSSL_MSG("Client wants to resume session");
+        }
+        else if (b) {
+            WOLFSSL_MSG("Invalid session ID size");
+            return BUFFER_ERROR; /* session ID nor 0 neither 32 bytes long */
+        }
+
+        #ifdef WOLFSSL_DTLS
+            /* cookie */
+            if (ssl->options.dtls) {
+
+                if ((i - begin) + OPAQUE8_LEN > helloSz)
+                    return BUFFER_ERROR;
+
+                peerCookieSz = input[i++];
+
+                if (peerCookieSz) {
+                    if (peerCookieSz > MAX_COOKIE_LEN)
+                        return BUFFER_ERROR;
+
+                    if ((i - begin) + peerCookieSz > helloSz)
+                        return BUFFER_ERROR;
+
+                    XMEMCPY(peerCookie, input + i, peerCookieSz);
+
+                    i += peerCookieSz;
+                }
+            }
+        #endif
+
+        /* suites */
+        if ((i - begin) + OPAQUE16_LEN > helloSz)
+            return BUFFER_ERROR;
+
+        ato16(&input[i], &clSuites.suiteSz);
+        i += OPAQUE16_LEN;
+
+        /* suites and compression length check */
+        if ((i - begin) + clSuites.suiteSz + OPAQUE8_LEN > helloSz)
+            return BUFFER_ERROR;
+
+        if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ)
+            return BUFFER_ERROR;
+
+        XMEMCPY(clSuites.suites, input + i, clSuites.suiteSz);
+
+#ifdef HAVE_SERVER_RENEGOTIATION_INFO
+        /* check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV suite */
+        if (FindSuite(&clSuites, 0, TLS_EMPTY_RENEGOTIATION_INFO_SCSV) >= 0) {
+            TLSX* extension;
+
+            /* check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV suite */
+            ret = TLSX_AddEmptyRenegotiationInfo(&ssl->extensions, ssl->heap);
+            if (ret != WOLFSSL_SUCCESS)
+                return ret;
+
+            extension = TLSX_Find(ssl->extensions, TLSX_RENEGOTIATION_INFO);
+            if (extension) {
+                ssl->secure_renegotiation =
+                                          (SecureRenegotiation*)extension->data;
+                ssl->secure_renegotiation->enabled = 1;
+            }
+        }
+#endif /* HAVE_SERVER_RENEGOTIATION_INFO */
+#if defined(HAVE_FALLBACK_SCSV) || defined(OPENSSL_ALL)
+        /* check for TLS_FALLBACK_SCSV suite */
+        if (FindSuite(&clSuites, TLS_FALLBACK_SCSV, 0) >= 0) {
+            WOLFSSL_MSG("Found Fallback SCSV");
+            if (ssl->ctx->method->version.minor > pv.minor) {
+                WOLFSSL_MSG("Client trying to connect with lesser version");
+                SendAlert(ssl, alert_fatal, inappropriate_fallback);
+                return VERSION_ERROR;
+            }
+        }
+#endif
+
+#ifdef WOLFSSL_DTLS
+        if (IsDtlsNotSctpMode(ssl)) {
+            ret = wc_HmacUpdate(&cookieHmac,
+                                    input + i - OPAQUE16_LEN,
+                                    clSuites.suiteSz + OPAQUE16_LEN);
+            if (ret != 0) return ret;
+        }
+#endif /* WOLFSSL_DTLS */
+        i += clSuites.suiteSz;
+        clSuites.hashSigAlgoSz = 0;
+
+        /* compression length */
+        b = input[i++];
+
+        if ((i - begin) + b > helloSz)
+            return BUFFER_ERROR;
+
+        if (b == 0) {
+            WOLFSSL_MSG("No compression types in list");
+#ifdef WOLFSSL_EXTRA_ALERTS
+            SendAlert(ssl, alert_fatal, decode_error);
+#endif
+            return COMPRESSION_ERROR;
+        }
+
+#ifdef WOLFSSL_DTLS
+        if (IsDtlsNotSctpMode(ssl)) {
+            byte newCookie[MAX_COOKIE_LEN];
+
+            ret = wc_HmacUpdate(&cookieHmac, input + i - 1, b + 1);
+            if (ret != 0) return ret;
+            ret = wc_HmacFinal(&cookieHmac, newCookie);
+            if (ret != 0) return ret;
+
+            /* If a cookie callback is set, call it to overwrite the cookie.
+             * This should be deprecated. The code now calculates the cookie
+             * using an HMAC as expected. */
+            if (ssl->ctx->CBIOCookie != NULL &&
+                ssl->ctx->CBIOCookie(ssl, newCookie, cookieSz,
+                                             ssl->IOCB_CookieCtx) != cookieSz) {
+                return COOKIE_ERROR;
+            }
+
+            /* Check the cookie, see if we progress the state machine. */
+            if (peerCookieSz != cookieSz ||
+                XMEMCMP(peerCookie, newCookie, cookieSz) != 0) {
+
+                /* Send newCookie to client in a HelloVerifyRequest message
+                 * and let the state machine alone. */
+                ssl->msgsReceived.got_client_hello = 0;
+                ssl->keys.dtls_handshake_number = 0;
+                ssl->keys.dtls_expected_peer_handshake_number = 0;
+                *inOutIdx += helloSz;
+                return SendHelloVerifyRequest(ssl, newCookie, cookieSz);
+            }
+
+            /* This was skipped in the DTLS case so we could handle the hello
+             * verify request. */
+            ret = HashInput(ssl, input + *inOutIdx, helloSz);
+            if (ret != 0) return ret;
+        }
+#endif /* WOLFSSL_DTLS */
+
+        {
+            /* compression match types */
+            int matchNo = 0;
+            int matchZlib = 0;
+
+            while (b--) {
+                byte comp = input[i++];
+
+                if (comp == NO_COMPRESSION) {
+                    matchNo = 1;
+                }
+                if (comp == ZLIB_COMPRESSION) {
+                    matchZlib = 1;
+                }
+            }
+
+            if (ssl->options.usingCompression == 0 && matchNo) {
+                WOLFSSL_MSG("Matched No Compression");
+            } else if (ssl->options.usingCompression && matchZlib) {
+                WOLFSSL_MSG("Matched zlib Compression");
+            } else if (ssl->options.usingCompression && matchNo) {
+                WOLFSSL_MSG("Could only match no compression, turning off");
+                ssl->options.usingCompression = 0;  /* turn off */
+            } else {
+                WOLFSSL_MSG("Could not match compression");
+#ifdef WOLFSSL_EXTRA_ALERTS
+                SendAlert(ssl, alert_fatal, illegal_parameter);
+#endif
+                return COMPRESSION_ERROR;
+            }
+        }
+
+        *inOutIdx = i;
+
+        /* tls extensions */
+        if ((i - begin) < helloSz) {
+#ifdef HAVE_TLS_EXTENSIONS
+        #ifdef HAVE_QSH
+            QSH_Init(ssl);
+        #endif
+            if (TLSX_SupportExtensions(ssl))
+#else
+            if (IsAtLeastTLSv1_2(ssl))
+#endif
+            {
+                /* Process the hello extension. Skip unsupported. */
+                word16 totalExtSz;
+
+#ifdef HAVE_TLS_EXTENSIONS
+                /* auto populate extensions supported unless user defined */
+                if ((ret = TLSX_PopulateExtensions(ssl, 1)) != 0)
+                    return ret;
+#endif
+
+                if ((i - begin) + OPAQUE16_LEN > helloSz)
+                    return BUFFER_ERROR;
+
+                ato16(&input[i], &totalExtSz);
+                i += OPAQUE16_LEN;
+
+                if ((i - begin) + totalExtSz > helloSz)
+                    return BUFFER_ERROR;
+
+#ifdef HAVE_TLS_EXTENSIONS
+                /* tls extensions */
+                if ((ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz,
+                                      client_hello, &clSuites)))
+                    return ret;
+    #ifdef WOLFSSL_TLS13
+                if (TLSX_Find(ssl->extensions,
+                                             TLSX_SUPPORTED_VERSIONS) != NULL) {
+                    WOLFSSL_MSG(
+                            "Client attempting to connect with higher version");
+                    return VERSION_ERROR;
+                }
+    #endif
+    #if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+                if((ret=SNI_Callback(ssl)))
+                    return ret;
+                ssl->options.side = WOLFSSL_SERVER_END;
+    #endif
+
+                i += totalExtSz;
+#else
+                while (totalExtSz) {
+                    word16 extId, extSz;
+
+                    if (OPAQUE16_LEN + OPAQUE16_LEN > totalExtSz)
+                        return BUFFER_ERROR;
+
+                    ato16(&input[i], &extId);
+                    i += OPAQUE16_LEN;
+                    ato16(&input[i], &extSz);
+                    i += OPAQUE16_LEN;
+
+                    if (OPAQUE16_LEN + OPAQUE16_LEN + extSz > totalExtSz)
+                        return BUFFER_ERROR;
+
+                    if (extId == HELLO_EXT_SIG_ALGO) {
+                        word16 hashSigAlgoSz;
+
+                        ato16(&input[i], &hashSigAlgoSz);
+                        i += OPAQUE16_LEN;
+
+                        if (OPAQUE16_LEN + hashSigAlgoSz > extSz)
+                            return BUFFER_ERROR;
+
+                        clSuites.hashSigAlgoSz = hashSigAlgoSz;
+                        if (clSuites.hashSigAlgoSz > WOLFSSL_MAX_SIGALGO) {
+                            WOLFSSL_MSG("ClientHello SigAlgo list exceeds max, "
+                                                                  "truncating");
+                            clSuites.hashSigAlgoSz = WOLFSSL_MAX_SIGALGO;
+                        }
+
+                        XMEMCPY(clSuites.hashSigAlgo, &input[i],
+                                                      clSuites.hashSigAlgoSz);
+
+                        i += hashSigAlgoSz;
+                    }
+#ifdef HAVE_EXTENDED_MASTER
+                    else if (extId == HELLO_EXT_EXTMS)
+                        ssl->options.haveEMS = 1;
+#endif
+                    else
+                        i += extSz;
+
+                    totalExtSz -= OPAQUE16_LEN + OPAQUE16_LEN + extSz;
+                }
+#endif
+                *inOutIdx = i;
+            }
+            else
+                *inOutIdx = begin + helloSz; /* skip extensions */
+        }
+
+        ssl->options.clientState   = CLIENT_HELLO_COMPLETE;
+        ssl->options.haveSessionId = 1;
+
+        /* ProcessOld uses same resume code */
+        if (ssl->options.resuming) {
+            ret = HandleTlsResumption(ssl, bogusID, &clSuites);
+            if (ret != 0)
+                return ret;
+
+            #ifdef HAVE_SECURE_RENEGOTIATION
+            if (ssl->secure_renegotiation &&
+                    ssl->secure_renegotiation->enabled &&
+                    IsEncryptionOn(ssl, 0))
+                ssl->secure_renegotiation->startScr = 1;
+            #endif
+
+            if (ssl->options.clientState == CLIENT_KEYEXCHANGE_COMPLETE) {
+                WOLFSSL_LEAVE("DoClientHello", ret);
+                WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO);
+
+                return ret;
+            }
+        }
+
+#if defined(HAVE_TLS_EXTENSIONS) && defined(HAVE_DH_DEFAULT_PARAMS)
+    #if defined(HAVE_FFDHE) && defined(HAVE_SUPPORTED_CURVES)
+        if (TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS) != NULL) {
+            /* Set FFDHE parameters or clear DHE parameters if FFDH parameters
+             * present and no matches in the server's list. */
+            ret = TLSX_SupportedFFDHE_Set(ssl);
+            if (ret != 0)
+                return ret;
+        }
+    #endif
+#endif
+
+        ret = MatchSuite(ssl, &clSuites);
+#ifdef WOLFSSL_EXTRA_ALERTS
+        if (ret == BUFFER_ERROR)
+            SendAlert(ssl, alert_fatal, decode_error);
+        else if (ret < 0)
+            SendAlert(ssl, alert_fatal, handshake_failure);
+#endif
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+        if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled &&
+                IsEncryptionOn(ssl, 0)) {
+            ssl->secure_renegotiation->startScr = 1;
+        }
+#endif
+        WOLFSSL_LEAVE("DoClientHello", ret);
+        WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO);
+
+        return ret;
+    }
+
+
+#if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+                        defined(HAVE_ED448)) && !defined(WOLFSSL_NO_CLIENT_AUTH)
+
+    typedef struct DcvArgs {
+        byte*  output; /* not allocated */
+        word32 sendSz;
+        word16 sz;
+        word32 sigSz;
+        word32 idx;
+        word32 begin;
+        byte   hashAlgo;
+        byte   sigAlgo;
+    } DcvArgs;
+
+    static void FreeDcvArgs(WOLFSSL* ssl, void* pArgs)
+    {
+        DcvArgs* args = (DcvArgs*)pArgs;
+
+        (void)ssl;
+        (void)args;
+    }
+
+    /* handle processing of certificate_verify (15) */
+    static int DoCertificateVerify(WOLFSSL* ssl, byte* input,
+                                word32* inOutIdx, word32 size)
+    {
+        int ret = 0;
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        DcvArgs* args = (DcvArgs*)ssl->async.args;
+        typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+        (void)sizeof(args_test);
+    #else
+        DcvArgs  args[1];
+    #endif
+
+        WOLFSSL_START(WC_FUNC_CERTIFICATE_VERIFY_DO);
+        WOLFSSL_ENTER("DoCertificateVerify");
+
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
+        if (ret != WC_NOT_PENDING_E) {
+            /* Check for error */
+            if (ret < 0)
+                goto exit_dcv;
+        }
+        else
+    #endif
+        {
+            /* Reset state */
+            ret = 0;
+            ssl->options.asyncState = TLS_ASYNC_BEGIN;
+            XMEMSET(args, 0, sizeof(DcvArgs));
+            args->hashAlgo = sha_mac;
+            args->sigAlgo = anonymous_sa_algo;
+            args->idx = *inOutIdx;
+            args->begin = *inOutIdx;
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            ssl->async.freeArgs = FreeDcvArgs;
+        #endif
+        }
+
+        switch(ssl->options.asyncState)
+        {
+            case TLS_ASYNC_BEGIN:
+            {
+            #ifdef WOLFSSL_CALLBACKS
+                if (ssl->hsInfoOn)
+                    AddPacketName(ssl, "CertificateVerify");
+                if (ssl->toInfoOn)
+                    AddLateName("CertificateVerify", &ssl->timeoutInfo);
+            #endif
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_BUILD;
+            } /* case TLS_ASYNC_BEGIN */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_BUILD:
+            {
+                if (IsAtLeastTLSv1_2(ssl)) {
+                    if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dcv);
+                    }
+
+                    DecodeSigAlg(&input[args->idx], &args->hashAlgo,
+                                 &args->sigAlgo);
+                    args->idx += 2;
+                }
+            #ifndef NO_RSA
+                else if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0)
+                    args->sigAlgo = rsa_sa_algo;
+            #endif
+            #ifdef HAVE_ECC
+                else if (ssl->peerEccDsaKeyPresent)
+                    args->sigAlgo = ecc_dsa_sa_algo;
+            #endif
+            #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
+                else if (ssl->peerEd25519KeyPresent)
+                    args->sigAlgo = ed25519_sa_algo;
+            #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
+            #if defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)
+                else if (ssl->peerEd448KeyPresent)
+                    args->sigAlgo = ed448_sa_algo;
+            #endif /* HAVE_ED448 && !NO_ED448_CLIENT_AUTH */
+
+                if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                    ERROR_OUT(BUFFER_ERROR, exit_dcv);
+                }
+
+                ato16(input + args->idx, &args->sz);
+                args->idx += OPAQUE16_LEN;
+
+                if ((args->idx - args->begin) + args->sz > size ||
+                                                    args->sz > ENCRYPT_LEN) {
+                    ERROR_OUT(BUFFER_ERROR, exit_dcv);
+                }
+
+            #ifdef HAVE_ECC
+                if (ssl->peerEccDsaKeyPresent) {
+
+                    WOLFSSL_MSG("Doing ECC peer cert verify");
+
+                /* make sure a default is defined */
+                #if !defined(NO_SHA)
+                    SetDigest(ssl, sha_mac);
+                #elif !defined(NO_SHA256)
+                    SetDigest(ssl, sha256_mac);
+                #elif defined(WOLFSSL_SHA384)
+                    SetDigest(ssl, sha384_mac);
+                #elif defined(WOLFSSL_SHA512)
+                    SetDigest(ssl, sha512_mac);
+                #else
+                    #error No digest enabled for ECC sig verify
+                #endif
+
+                    if (IsAtLeastTLSv1_2(ssl)) {
+                        if (args->sigAlgo != ecc_dsa_sa_algo) {
+                            WOLFSSL_MSG("Oops, peer sent ECC key but not in verify");
+                        }
+
+                        SetDigest(ssl, args->hashAlgo);
+                    }
+                }
+            #endif /* HAVE_ECC */
+            #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
+                if (ssl->peerEd25519KeyPresent) {
+                    WOLFSSL_MSG("Doing ED25519 peer cert verify");
+                    if (IsAtLeastTLSv1_2(ssl) &&
+                                             args->sigAlgo != ed25519_sa_algo) {
+                        WOLFSSL_MSG(
+                               "Oops, peer sent ED25519 key but not in verify");
+                    }
+                }
+            #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
+            #if defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)
+                if (ssl->peerEd448KeyPresent) {
+                    WOLFSSL_MSG("Doing ED448 peer cert verify");
+                    if (IsAtLeastTLSv1_2(ssl) &&
+                                               args->sigAlgo != ed448_sa_algo) {
+                        WOLFSSL_MSG(
+                                 "Oops, peer sent ED448 key but not in verify");
+                    }
+                }
+            #endif /* HAVE_ED448 && !NO_ED448_CLIENT_AUTH */
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_DO;
+            } /* case TLS_ASYNC_BUILD */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_DO:
+            {
+            #ifndef NO_RSA
+                if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) {
+                    WOLFSSL_MSG("Doing RSA peer cert verify");
+
+                    ret = RsaVerify(ssl,
+                        input + args->idx,
+                        args->sz,
+                        &args->output,
+                        args->sigAlgo, args->hashAlgo,
+                        ssl->peerRsaKey,
+                    #ifdef HAVE_PK_CALLBACKS
+                        &ssl->buffers.peerRsaKey
+                    #else
+                        NULL
+                    #endif
+                    );
+                    if (ret >= 0) {
+                        if (args->sigAlgo == rsa_sa_algo)
+                            args->sendSz = ret;
+                        else {
+                            args->sigSz = ret;
+                            args->sendSz = ssl->buffers.digest.length;
+                        }
+                        ret = 0;
+                    }
+                }
+            #endif /* !NO_RSA */
+            #ifdef HAVE_ECC
+                if (ssl->peerEccDsaKeyPresent) {
+                    WOLFSSL_MSG("Doing ECC peer cert verify");
+
+                    ret = EccVerify(ssl,
+                        input + args->idx, args->sz,
+                        ssl->buffers.digest.buffer, ssl->buffers.digest.length,
+                        ssl->peerEccDsaKey,
+                    #ifdef HAVE_PK_CALLBACKS
+                        &ssl->buffers.peerEccDsaKey
+                    #else
+                        NULL
+                    #endif
+                    );
+                }
+            #endif /* HAVE_ECC */
+            #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
+                if (ssl->peerEd25519KeyPresent) {
+                    WOLFSSL_MSG("Doing Ed25519 peer cert verify");
+
+                    ret = Ed25519Verify(ssl,
+                        input + args->idx, args->sz,
+                        ssl->hsHashes->messages, ssl->hsHashes->prevLen,
+                        ssl->peerEd25519Key,
+                    #ifdef HAVE_PK_CALLBACKS
+                        &ssl->buffers.peerEd25519Key
+                    #else
+                        NULL
+                    #endif
+                    );
+                }
+            #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
+            #if defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)
+                if (ssl->peerEd448KeyPresent) {
+                    WOLFSSL_MSG("Doing Ed448 peer cert verify");
+
+                    ret = Ed448Verify(ssl,
+                        input + args->idx, args->sz,
+                        ssl->hsHashes->messages, ssl->hsHashes->prevLen,
+                        ssl->peerEd448Key,
+                    #ifdef HAVE_PK_CALLBACKS
+                        &ssl->buffers.peerEd448Key
+                    #else
+                        NULL
+                    #endif
+                    );
+                }
+            #endif /* HAVE_ED448 && !NO_ED448_CLIENT_AUTH */
+
+            #ifdef WOLFSSL_ASYNC_CRYPT
+                /* handle async pending */
+                if (ret == WC_PENDING_E)
+                    goto exit_dcv;
+            #endif
+
+                /* Check for error */
+                if (ret != 0) {
+                    ret = SIG_VERIFY_E;
+                    goto exit_dcv;
+                }
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_VERIFY;
+            } /* case TLS_ASYNC_DO */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_VERIFY:
+            {
+            #ifndef NO_RSA
+                if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) {
+                    if (IsAtLeastTLSv1_2(ssl)) {
+                    #ifdef WC_RSA_PSS
+                        if (args->sigAlgo == rsa_pss_sa_algo) {
+                            SetDigest(ssl, args->hashAlgo);
+
+                        #ifdef HAVE_SELFTEST
+                            ret = wc_RsaPSS_CheckPadding(
+                                            ssl->buffers.digest.buffer,
+                                            ssl->buffers.digest.length,
+                                            args->output, args->sigSz,
+                                            HashAlgoToType(args->hashAlgo));
+                        #else
+                            ret = wc_RsaPSS_CheckPadding_ex(
+                                            ssl->buffers.digest.buffer,
+                                            ssl->buffers.digest.length,
+                                            args->output, args->sigSz,
+                                            HashAlgoToType(args->hashAlgo), -1,
+                                            mp_count_bits(&ssl->peerRsaKey->n));
+                        #endif
+                            if (ret != 0) {
+                                ret = SIG_VERIFY_E;
+                                goto exit_dcv;
+                            }
+                        }
+                        else
+                    #endif
+                        {
+                        #ifdef WOLFSSL_SMALL_STACK
+                            byte* encodedSig;
+                        #else
+                            byte  encodedSig[MAX_ENCODED_SIG_SZ];
+                        #endif
+
+                        #ifdef WOLFSSL_SMALL_STACK
+                            encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ,
+                                             ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+                            if (encodedSig == NULL) {
+                                ERROR_OUT(MEMORY_E, exit_dcv);
+                            }
+                        #endif
+
+                            if (args->sigAlgo != rsa_sa_algo) {
+                                WOLFSSL_MSG("Oops, peer sent RSA key but not "
+                                            "in verify");
+                            }
+
+                            SetDigest(ssl, args->hashAlgo);
+
+                            args->sigSz = wc_EncodeSignature(encodedSig,
+                                ssl->buffers.digest.buffer,
+                                ssl->buffers.digest.length,
+                                TypeHash(args->hashAlgo));
+
+                            if (args->sendSz != args->sigSz || !args->output ||
+                                XMEMCMP(args->output, encodedSig,
+                                    min(args->sigSz, MAX_ENCODED_SIG_SZ)) != 0) {
+                                ret = VERIFY_CERT_ERROR;
+                            }
+
+                        #ifdef WOLFSSL_SMALL_STACK
+                            XFREE(encodedSig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+                        #endif
+                        }
+                    }
+                    else {
+                        if (args->sendSz != FINISHED_SZ || !args->output ||
+                            XMEMCMP(args->output,
+                                &ssl->hsHashes->certHashes, FINISHED_SZ) != 0) {
+                            ret = VERIFY_CERT_ERROR;
+                        }
+                    }
+                }
+            #endif /* !NO_RSA */
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_FINALIZE;
+            } /* case TLS_ASYNC_VERIFY */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_FINALIZE:
+            {
+                if (IsEncryptionOn(ssl, 0)) {
+                    args->idx += ssl->keys.padSz;
+            #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+                    if (ssl->options.startedETMRead)
+                        args->idx += MacSize(ssl);
+            #endif
+                }
+
+                ssl->options.havePeerVerify = 1;
+
+                /* Set final index */
+                args->idx += args->sz;
+                *inOutIdx = args->idx;
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_END;
+            } /* case TLS_ASYNC_FINALIZE */
+
+            case TLS_ASYNC_END:
+            {
+                break;
+            }
+            default:
+                ret = INPUT_CASE_ERROR;
+        } /* switch(ssl->options.asyncState) */
+
+    exit_dcv:
+
+        WOLFSSL_LEAVE("DoCertificateVerify", ret);
+        WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_DO);
+
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        /* Handle async operation */
+        if (ret == WC_PENDING_E) {
+            /* Mark message as not received so it can process again */
+            ssl->msgsReceived.got_certificate_verify = 0;
+
+            return ret;
+        }
+    #endif /* WOLFSSL_ASYNC_CRYPT */
+    #ifdef WOLFSSL_EXTRA_ALERTS
+        if (ret == BUFFER_ERROR)
+            SendAlert(ssl, alert_fatal, decode_error);
+        else if (ret == SIG_VERIFY_E)
+            SendAlert(ssl, alert_fatal, decrypt_error);
+        else if (ret != 0)
+            SendAlert(ssl, alert_fatal, bad_certificate);
+    #endif
+        /* Digest is not allocated, so do this to prevent free */
+        ssl->buffers.digest.buffer = NULL;
+        ssl->buffers.digest.length = 0;
+
+        /* Final cleanup */
+        FreeDcvArgs(ssl, args);
+        FreeKeyExchange(ssl);
+
+        return ret;
+    }
+
+#endif /* (!NO_RSA || ECC || ED25519 || ED448) && !WOLFSSL_NO_CLIENT_AUTH */
+
+    /* handle generation of server_hello_done (14) */
+    int SendServerHelloDone(WOLFSSL* ssl)
+    {
+        byte* output;
+        int   sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+        int   ret;
+
+        WOLFSSL_START(WC_FUNC_SERVER_HELLO_DONE_SEND);
+        WOLFSSL_ENTER("SendServerHelloDone");
+
+    #ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls)
+            sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+    #endif
+
+        if (IsEncryptionOn(ssl, 1))
+            sendSz += MAX_MSG_EXTRA;
+
+        /* check for available size */
+        if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+            return ret;
+
+        /* get output buffer */
+        output = ssl->buffers.outputBuffer.buffer +
+                 ssl->buffers.outputBuffer.length;
+
+        AddHeaders(output, 0, server_hello_done, ssl);
+
+        if (IsEncryptionOn(ssl, 1)) {
+            byte* input;
+            int   inputSz = HANDSHAKE_HEADER_SZ; /* build msg adds rec hdr */
+
+            input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+            if (input == NULL)
+                return MEMORY_E;
+
+            XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
+            sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
+                                  handshake, 1, 0, 0);
+            XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+
+            if (sendSz < 0)
+                return sendSz;
+        } else {
+            #ifdef WOLFSSL_DTLS
+                if (IsDtlsNotSctpMode(ssl)) {
+                    if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
+                        return ret;
+                }
+                if (ssl->options.dtls)
+                    DtlsSEQIncrement(ssl, CUR_ORDER);
+            #endif
+            ret = HashOutput(ssl, output, sendSz, 0);
+            if (ret != 0)
+                return ret;
+        }
+
+    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+        if (ssl->hsInfoOn)
+            AddPacketName(ssl, "ServerHelloDone");
+        if (ssl->toInfoOn)
+            AddPacketInfo(ssl, "ServerHelloDone", handshake, output, sendSz,
+                    WRITE_PROTO, ssl->heap);
+    #endif
+        ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
+
+        ssl->buffers.outputBuffer.length += sendSz;
+
+        ret = SendBuffered(ssl);
+
+        WOLFSSL_LEAVE("SendServerHelloDone", ret);
+        WOLFSSL_END(WC_FUNC_SERVER_HELLO_DONE_SEND);
+
+        return ret;
+    }
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#ifdef HAVE_SESSION_TICKET
+
+#define WOLFSSL_TICKET_FIXED_SZ (WOLFSSL_TICKET_NAME_SZ + \
+                WOLFSSL_TICKET_IV_SZ + WOLFSSL_TICKET_MAC_SZ + LENGTH_SZ)
+#define WOLFSSL_TICKET_ENC_SZ (SESSION_TICKET_LEN - WOLFSSL_TICKET_FIXED_SZ)
+
+    /* our ticket format */
+    typedef struct InternalTicket {
+        ProtocolVersion pv;                    /* version when ticket created */
+        byte            suite[SUITE_LEN];      /* cipher suite when created */
+        byte            msecret[SECRET_LEN];   /* master secret */
+        word32          timestamp;             /* born on */
+        word16          haveEMS;               /* have extended master secret */
+#ifdef WOLFSSL_TLS13
+        word32          ageAdd;                /* Obfuscation of age */
+        word16          namedGroup;            /* Named group used */
+    #ifndef WOLFSSL_TLS13_DRAFT_18
+        TicketNonce     ticketNonce;           /* Ticket nonce */
+    #endif
+    #ifdef WOLFSSL_EARLY_DATA
+        word32          maxEarlyDataSz;        /* Max size of early data */
+    #endif
+#endif
+    } InternalTicket;
+
+    /* fit within SESSION_TICKET_LEN */
+    typedef struct ExternalTicket {
+        byte key_name[WOLFSSL_TICKET_NAME_SZ];  /* key context name */
+        byte iv[WOLFSSL_TICKET_IV_SZ];          /* this ticket's iv */
+        byte enc_len[LENGTH_SZ];                /* encrypted length */
+        byte enc_ticket[WOLFSSL_TICKET_ENC_SZ]; /* encrypted internal ticket */
+        byte mac[WOLFSSL_TICKET_MAC_SZ];        /* total mac */
+        /* !! if add to structure, add to TICKET_FIXED_SZ !! */
+    } ExternalTicket;
+
+    /* create a new session ticket, 0 on success */
+    int CreateTicket(WOLFSSL* ssl)
+    {
+        InternalTicket  it;
+        ExternalTicket* et = (ExternalTicket*)ssl->session.ticket;
+        int encLen;
+        int ret;
+        byte zeros[WOLFSSL_TICKET_MAC_SZ];   /* biggest cmp size */
+
+        XMEMSET(&it, 0, sizeof(it));
+
+        /* build internal */
+        it.pv.major = ssl->version.major;
+        it.pv.minor = ssl->version.minor;
+
+        it.suite[0] = ssl->options.cipherSuite0;
+        it.suite[1] = ssl->options.cipherSuite;
+
+    #ifdef WOLFSSL_EARLY_DATA
+        it.maxEarlyDataSz = ssl->options.maxEarlyDataSz;
+    #endif
+
+        if (!ssl->options.tls1_3) {
+            XMEMCPY(it.msecret, ssl->arrays->masterSecret, SECRET_LEN);
+            c32toa(LowResTimer(), (byte*)&it.timestamp);
+            it.haveEMS = ssl->options.haveEMS;
+        }
+        else {
+#ifdef WOLFSSL_TLS13
+            /* Client adds to ticket age to obfuscate. */
+            ret = wc_RNG_GenerateBlock(ssl->rng, (byte*)&it.ageAdd,
+                                                             sizeof(it.ageAdd));
+            if (ret != 0)
+                return BAD_TICKET_ENCRYPT;
+            ssl->session.ticketAdd = it.ageAdd;
+            it.namedGroup = ssl->session.namedGroup;
+            it.timestamp = TimeNowInMilliseconds();
+            /* Resumption master secret. */
+            XMEMCPY(it.msecret, ssl->session.masterSecret, SECRET_LEN);
+    #ifndef WOLFSSL_TLS13_DRAFT_18
+            XMEMCPY(&it.ticketNonce, &ssl->session.ticketNonce,
+                                                           sizeof(TicketNonce));
+    #endif
+#endif
+        }
+
+        /* build external */
+        XMEMCPY(et->enc_ticket, &it, sizeof(InternalTicket));
+
+        /* encrypt */
+        encLen = WOLFSSL_TICKET_ENC_SZ;  /* max size user can use */
+        if (ssl->ctx->ticketEncCb == NULL) {
+            ret = WOLFSSL_TICKET_RET_FATAL;
+        }
+        else {
+            ret = ssl->ctx->ticketEncCb(ssl, et->key_name, et->iv, et->mac, 1,
+                                    et->enc_ticket, sizeof(InternalTicket),
+                                    &encLen, ssl->ctx->ticketEncCtx);
+        }
+        if (ret == WOLFSSL_TICKET_RET_OK) {
+            if (encLen < (int)sizeof(InternalTicket) ||
+                encLen > WOLFSSL_TICKET_ENC_SZ) {
+                WOLFSSL_MSG("Bad user ticket encrypt size");
+                return BAD_TICKET_KEY_CB_SZ;
+            }
+
+            /* sanity checks on encrypt callback */
+
+            /* internal ticket can't be the same if encrypted */
+            if (XMEMCMP(et->enc_ticket, &it, sizeof(InternalTicket)) == 0) {
+                WOLFSSL_MSG("User ticket encrypt didn't encrypt");
+                return BAD_TICKET_ENCRYPT;
+            }
+
+            XMEMSET(zeros, 0, sizeof(zeros));
+
+            /* name */
+            if (XMEMCMP(et->key_name, zeros, WOLFSSL_TICKET_NAME_SZ) == 0) {
+                WOLFSSL_MSG("User ticket encrypt didn't set name");
+                return BAD_TICKET_ENCRYPT;
+            }
+
+            /* iv */
+            if (XMEMCMP(et->iv, zeros, WOLFSSL_TICKET_IV_SZ) == 0) {
+                WOLFSSL_MSG("User ticket encrypt didn't set iv");
+                return BAD_TICKET_ENCRYPT;
+            }
+
+            /* mac */
+            if (XMEMCMP(et->mac, zeros, WOLFSSL_TICKET_MAC_SZ) == 0) {
+                WOLFSSL_MSG("User ticket encrypt didn't set mac");
+                return BAD_TICKET_ENCRYPT;
+            }
+
+            /* set size */
+            c16toa((word16)encLen, et->enc_len);
+            ssl->session.ticketLen = (word16)(encLen + WOLFSSL_TICKET_FIXED_SZ);
+            if (encLen < WOLFSSL_TICKET_ENC_SZ) {
+                /* move mac up since whole enc buffer not used */
+                XMEMMOVE(et->enc_ticket +encLen, et->mac,WOLFSSL_TICKET_MAC_SZ);
+            }
+        }
+
+        return ret;
+    }
+
+
+    /* Parse ticket sent by client, returns callback return value */
+    int DoClientTicket(WOLFSSL* ssl, const byte* input, word32 len)
+    {
+        ExternalTicket* et;
+        InternalTicket* it;
+        int             ret;
+        int             outLen;
+        word16          inLen;
+
+        WOLFSSL_START(WC_FUNC_TICKET_DO);
+        WOLFSSL_ENTER("DoClientTicket");
+
+        if (len > SESSION_TICKET_LEN ||
+             len < (word32)(sizeof(InternalTicket) + WOLFSSL_TICKET_FIXED_SZ)) {
+            return BAD_TICKET_MSG_SZ;
+        }
+
+        et = (ExternalTicket*)input;
+        it = (InternalTicket*)et->enc_ticket;
+
+        /* decrypt */
+        ato16(et->enc_len, &inLen);
+        if (inLen > (word16)(len - WOLFSSL_TICKET_FIXED_SZ)) {
+            return BAD_TICKET_MSG_SZ;
+        }
+        outLen = inLen;   /* may be reduced by user padding */
+
+        if (ssl->ctx->ticketEncCb == NULL) {
+            ret = WOLFSSL_TICKET_RET_FATAL;
+        }
+        else {
+            ret = ssl->ctx->ticketEncCb(ssl, et->key_name, et->iv,
+                                    et->enc_ticket + inLen, 0,
+                                    et->enc_ticket, inLen, &outLen,
+                                    ssl->ctx->ticketEncCtx);
+        }
+        if (ret == WOLFSSL_TICKET_RET_FATAL || ret < 0) return ret;
+        if (outLen > (int)inLen || outLen < (int)sizeof(InternalTicket)) {
+            WOLFSSL_MSG("Bad user ticket decrypt len");
+            return BAD_TICKET_KEY_CB_SZ;
+        }
+
+        /* get master secret */
+        if (ret == WOLFSSL_TICKET_RET_OK || ret == WOLFSSL_TICKET_RET_CREATE) {
+            if (ssl->version.minor < it->pv.minor) {
+                WOLFSSL_MSG("Ticket has greater version");
+                return VERSION_ERROR;
+            }
+            else if (ssl->version.minor > it->pv.minor) {
+                if (!ssl->options.downgrade) {
+                    WOLFSSL_MSG("Ticket has lesser version");
+                    return VERSION_ERROR;
+                }
+
+                WOLFSSL_MSG("Downgrading protocol due to ticket");
+
+                if (it->pv.minor < ssl->options.minDowngrade)
+                    return VERSION_ERROR;
+                ssl->version.minor = it->pv.minor;
+            }
+
+
+            if (!IsAtLeastTLSv1_3(ssl->version)) {
+                XMEMCPY(ssl->arrays->masterSecret, it->msecret, SECRET_LEN);
+                /* Copy the haveExtendedMasterSecret property from the ticket to
+                 * the saved session, so the property may be checked later. */
+                ssl->session.haveEMS = it->haveEMS;
+            #ifndef NO_RESUME_SUITE_CHECK
+                ssl->session.cipherSuite0 = it->suite[0];
+                ssl->session.cipherSuite = it->suite[1];
+            #endif
+            }
+            else {
+#ifdef WOLFSSL_TLS13
+                /* Restore information to renegotiate. */
+                ssl->session.ticketSeen = it->timestamp;
+                ssl->session.ticketAdd = it->ageAdd;
+                ssl->session.cipherSuite0 = it->suite[0];
+                ssl->session.cipherSuite = it->suite[1];
+    #ifdef WOLFSSL_EARLY_DATA
+                ssl->session.maxEarlyDataSz = it->maxEarlyDataSz;
+    #endif
+                /* Resumption master secret. */
+                XMEMCPY(ssl->session.masterSecret, it->msecret, SECRET_LEN);
+    #ifndef WOLFSSL_TLS13_DRAFT_18
+                XMEMCPY(&ssl->session.ticketNonce, &it->ticketNonce,
+                                                           sizeof(TicketNonce));
+    #endif
+                ssl->session.namedGroup = it->namedGroup;
+#endif
+            }
+        }
+
+        WOLFSSL_LEAVE("DoClientTicket", ret);
+        WOLFSSL_END(WC_FUNC_TICKET_DO);
+
+        return ret;
+    }
+
+
+    /* send Session Ticket */
+    int SendTicket(WOLFSSL* ssl)
+    {
+        byte*              output;
+        int                ret;
+        int                sendSz;
+        word32             length = SESSION_HINT_SZ + LENGTH_SZ;
+        word32             idx    = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+
+        WOLFSSL_START(WC_FUNC_TICKET_SEND);
+        WOLFSSL_ENTER("SendTicket");
+
+        if (ssl->options.createTicket) {
+            ret = CreateTicket(ssl);
+            if (ret != 0) return ret;
+        }
+
+        length += ssl->session.ticketLen;
+        sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+
+        if (!ssl->options.dtls) {
+            if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone)
+                sendSz += MAX_MSG_EXTRA;
+        }
+        else {
+        #ifdef WOLFSSL_DTLS
+            sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+            idx    += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+        #endif
+        }
+        /* check for available size */
+        if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+            return ret;
+
+        /* get output buffer */
+        output = ssl->buffers.outputBuffer.buffer +
+                 ssl->buffers.outputBuffer.length;
+
+        AddHeaders(output, length, session_ticket, ssl);
+
+        /* hint */
+        c32toa(ssl->ctx->ticketHint, output + idx);
+        idx += SESSION_HINT_SZ;
+
+        /* length */
+        c16toa(ssl->session.ticketLen, output + idx);
+        idx += LENGTH_SZ;
+
+        /* ticket */
+        XMEMCPY(output + idx, ssl->session.ticket, ssl->session.ticketLen);
+        idx += ssl->session.ticketLen;
+
+        if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) {
+            byte* input;
+            int   inputSz = idx - RECORD_HEADER_SZ; /* build msg adds rec hdr */
+
+            input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+            if (input == NULL)
+                return MEMORY_E;
+
+            XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
+            sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
+                                  handshake, 1, 0, 0);
+            XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+
+            if (sendSz < 0)
+                return sendSz;
+        }
+        else {
+            #ifdef WOLFSSL_DTLS
+            if (ssl->options.dtls) {
+                if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
+                    return ret;
+
+                DtlsSEQIncrement(ssl, CUR_ORDER);
+            }
+            #endif
+            ret = HashOutput(ssl, output, sendSz, 0);
+            if (ret != 0)
+                return ret;
+        }
+
+        ssl->buffers.outputBuffer.length += sendSz;
+
+        ret = SendBuffered(ssl);
+
+        WOLFSSL_LEAVE("SendTicket", ret);
+        WOLFSSL_END(WC_FUNC_TICKET_SEND);
+
+        return ret;
+    }
+
+#endif /* HAVE_SESSION_TICKET */
+
+#ifndef WOLFSSL_NO_TLS12
+
+#if defined(HAVE_SECURE_RENEGOTIATION) && \
+    defined(HAVE_SERVER_RENEGOTIATION_INFO) && \
+    !defined(WOLFSSL_NO_SERVER)
+
+    /* handle generation of server's hello_request (0) */
+    int SendHelloRequest(WOLFSSL* ssl)
+    {
+        byte* output;
+        int sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+        int ret;
+
+        WOLFSSL_START(WC_FUNC_HELLO_REQUEST_SEND);
+        WOLFSSL_ENTER("SendHelloRequest");
+
+        if (IsEncryptionOn(ssl, 1))
+            sendSz += MAX_MSG_EXTRA;
+
+        /* check for available size */
+        if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+            return ret;
+
+        /* get output buffer */
+        output = ssl->buffers.outputBuffer.buffer +
+                 ssl->buffers.outputBuffer.length;
+
+        AddHeaders(output, 0, hello_request, ssl);
+
+        if (IsEncryptionOn(ssl, 1)) {
+            byte* input;
+            int   inputSz = HANDSHAKE_HEADER_SZ; /* build msg adds rec hdr */
+
+            input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+            if (input == NULL)
+                return MEMORY_E;
+
+            XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
+            sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
+                                  handshake, 0, 0, 0);
+            XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+
+            if (sendSz < 0)
+                return sendSz;
+        }
+
+        ssl->buffers.outputBuffer.length += sendSz;
+
+        ret = SendBuffered(ssl);
+
+        WOLFSSL_LEAVE("SendHelloRequest", ret);
+        WOLFSSL_END(WC_FUNC_HELLO_REQUEST_SEND);
+
+        return ret;
+    }
+
+#endif /* HAVE_SECURE_RENEGOTIATION && HAVE_SERVER_RENEGOTIATION_INFO */
+
+#ifdef WOLFSSL_DTLS
+    /* handle generation of DTLS hello_verify_request (3) */
+    static int SendHelloVerifyRequest(WOLFSSL* ssl,
+                                      const byte* cookie, byte cookieSz)
+    {
+        byte* output;
+        int   length = VERSION_SZ + ENUM_LEN + cookieSz;
+        int   idx    = DTLS_RECORD_HEADER_SZ + DTLS_HANDSHAKE_HEADER_SZ;
+        int   sendSz = length + idx;
+        int   ret;
+
+        /* check for available size */
+        if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+            return ret;
+
+        /* get output buffer */
+        output = ssl->buffers.outputBuffer.buffer +
+                 ssl->buffers.outputBuffer.length;
+
+        /* Hello Verify Request should use the same sequence number as the
+         * Client Hello. */
+        ssl->keys.dtls_sequence_number_hi = ssl->keys.curSeq_hi;
+        ssl->keys.dtls_sequence_number_lo = ssl->keys.curSeq_lo;
+        AddHeaders(output, length, hello_verify_request, ssl);
+
+#ifdef OPENSSL_EXTRA
+        output[idx++] = DTLS_MAJOR;
+        output[idx++] = DTLS_MINOR;
+#else
+        output[idx++] = ssl->version.major;
+        output[idx++] = ssl->version.minor;
+#endif
+
+        output[idx++] = cookieSz;
+        if (cookie == NULL || cookieSz == 0)
+            return COOKIE_ERROR;
+
+        XMEMCPY(output + idx, cookie, cookieSz);
+
+#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+        if (ssl->hsInfoOn)
+            AddPacketName(ssl, "HelloVerifyRequest");
+        if (ssl->toInfoOn)
+            AddPacketInfo(ssl, "HelloVerifyRequest", handshake, output,
+                          sendSz, WRITE_PROTO, ssl->heap);
+#endif
+
+        ssl->buffers.outputBuffer.length += sendSz;
+
+        return SendBuffered(ssl);
+    }
+#endif /* WOLFSSL_DTLS */
+
+    typedef struct DckeArgs {
+        byte*  output; /* not allocated */
+        word32 length;
+        word32 idx;
+        word32 begin;
+        word32 sigSz;
+    #ifndef NO_RSA
+        int    lastErr;
+    #endif
+    } DckeArgs;
+
+    static void FreeDckeArgs(WOLFSSL* ssl, void* pArgs)
+    {
+        DckeArgs* args = (DckeArgs*)pArgs;
+
+        (void)ssl;
+        (void)args;
+    }
+
+    /* handle processing client_key_exchange (16) */
+    static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+                                                                    word32 size)
+    {
+        int ret;
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        DckeArgs* args = (DckeArgs*)ssl->async.args;
+        typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+        (void)sizeof(args_test);
+    #else
+        DckeArgs  args[1];
+    #endif
+
+        (void)size;
+        (void)input;
+
+        WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_DO);
+        WOLFSSL_ENTER("DoClientKeyExchange");
+
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
+        if (ret != WC_NOT_PENDING_E) {
+            /* Check for error */
+            if (ret < 0)
+                goto exit_dcke;
+        }
+        else
+    #endif /* WOLFSSL_ASYNC_CRYPT */
+        {
+            /* Reset state */
+            ret = 0;
+            ssl->options.asyncState = TLS_ASYNC_BEGIN;
+            XMEMSET(args, 0, sizeof(DckeArgs));
+            args->idx = *inOutIdx;
+            args->begin = *inOutIdx;
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            ssl->async.freeArgs = FreeDckeArgs;
+        #endif
+        }
+
+        /* Do Client Key Exchange State Machine */
+        switch(ssl->options.asyncState)
+        {
+            case TLS_ASYNC_BEGIN:
+            {
+                /* Sanity checks */
+                if (ssl->options.side != WOLFSSL_SERVER_END) {
+                    WOLFSSL_MSG("Client received client keyexchange, attack?");
+                    WOLFSSL_ERROR(ssl->error = SIDE_ERROR);
+                    ERROR_OUT(WOLFSSL_FATAL_ERROR, exit_dcke);
+                }
+
+                if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) {
+                    WOLFSSL_MSG("Client sending keyexchange at wrong time");
+                    SendAlert(ssl, alert_fatal, unexpected_message);
+                    ERROR_OUT(OUT_OF_ORDER_E, exit_dcke);
+                }
+
+            #ifndef NO_CERTS
+                if (ssl->options.verifyPeer && ssl->options.failNoCert) {
+                    if (!ssl->options.havePeerCert) {
+                        WOLFSSL_MSG("client didn't present peer cert");
+                        ERROR_OUT(NO_PEER_CERT, exit_dcke);
+                    }
+                }
+
+                if (ssl->options.verifyPeer && ssl->options.failNoCertxPSK) {
+                    if (!ssl->options.havePeerCert &&
+                                             !ssl->options.usingPSK_cipher) {
+                        WOLFSSL_MSG("client didn't present peer cert");
+                        return NO_PEER_CERT;
+                    }
+                }
+            #endif /* !NO_CERTS */
+
+            #if defined(WOLFSSL_CALLBACKS)
+                if (ssl->hsInfoOn) {
+                    AddPacketName(ssl, "ClientKeyExchange");
+                }
+                if (ssl->toInfoOn) {
+                    AddLateName("ClientKeyExchange", &ssl->timeoutInfo);
+                }
+            #endif
+
+                if (ssl->arrays->preMasterSecret == NULL) {
+                    ssl->arrays->preMasterSz = ENCRYPT_LEN;
+                    ssl->arrays->preMasterSecret = (byte*)XMALLOC(ENCRYPT_LEN,
+                                                ssl->heap, DYNAMIC_TYPE_SECRET);
+                    if (ssl->arrays->preMasterSecret == NULL) {
+                        ERROR_OUT(MEMORY_E, exit_dcke);
+                    }
+                    XMEMSET(ssl->arrays->preMasterSecret, 0, ENCRYPT_LEN);
+                }
+
+                switch (ssl->specs.kea) {
+                #ifndef NO_RSA
+                    case rsa_kea:
+                    {
+                        break;
+                    } /* rsa_kea */
+                #endif /* !NO_RSA */
+                #ifndef NO_PSK
+                    case psk_kea:
+                    {
+                        /* sanity check that PSK server callback has been set */
+                        if (ssl->options.server_psk_cb == NULL) {
+                           WOLFSSL_MSG("No server PSK callback set");
+                           ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
+                        }
+                        break;
+                    }
+                #endif /* !NO_PSK */
+                #ifdef HAVE_NTRU
+                    case ntru_kea:
+                    {
+                        /* make sure private key exists */
+                        if (ssl->buffers.key == NULL ||
+                                            ssl->buffers.key->buffer == NULL) {
+                            ERROR_OUT(NO_PRIVATE_KEY, exit_dcke);
+                        }
+                        break;
+                    }
+                #endif /* HAVE_NTRU */
+                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                                          defined(HAVE_CURVE448)
+                    case ecc_diffie_hellman_kea:
+                    {
+                        break;
+                    }
+                #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+                #ifndef NO_DH
+                    case diffie_hellman_kea:
+                    {
+                        break;
+                    }
+                #endif /* !NO_DH */
+                #if !defined(NO_DH) && !defined(NO_PSK)
+                    case dhe_psk_kea:
+                    {
+                        /* sanity check that PSK server callback has been set */
+                        if (ssl->options.server_psk_cb == NULL) {
+                            WOLFSSL_MSG("No server PSK callback set");
+                            ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
+                        }
+                        break;
+                    }
+                #endif /* !NO_DH && !NO_PSK */
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                     defined(HAVE_CURVE448)) && !defined(NO_PSK)
+                    case ecdhe_psk_kea:
+                    {
+                        /* sanity check that PSK server callback has been set */
+                        if (ssl->options.server_psk_cb == NULL) {
+                            WOLFSSL_MSG("No server PSK callback set");
+                            ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
+                        }
+                        break;
+                    }
+                #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */
+                    default:
+                        WOLFSSL_MSG("Bad kea type");
+                        ret = BAD_KEA_TYPE_E;
+                } /* switch (ssl->specs.kea) */
+
+                /* Check for error */
+                if (ret != 0) {
+                    goto exit_dcke;
+                }
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_BUILD;
+            } /* TLS_ASYNC_BEGIN */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_BUILD:
+            {
+                switch (ssl->specs.kea) {
+                #ifndef NO_RSA
+                    case rsa_kea:
+                    {
+                        word16 keySz;
+
+                        ssl->buffers.keyType = rsa_sa_algo;
+                        ret = DecodePrivateKey(ssl, &keySz);
+                        if (ret != 0) {
+                            goto exit_dcke;
+                        }
+                        args->length = (word32)keySz;
+                        ssl->arrays->preMasterSz = SECRET_LEN;
+
+                        if (ssl->options.tls) {
+                            word16 check;
+
+                            if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                                ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                            }
+
+                            ato16(input + args->idx, &check);
+                            args->idx += OPAQUE16_LEN;
+
+                            if ((word32)check != args->length) {
+                                WOLFSSL_MSG("RSA explicit size doesn't match");
+                        #ifdef WOLFSSL_EXTRA_ALERTS
+                                SendAlert(ssl, alert_fatal, bad_record_mac);
+                        #endif
+                                ERROR_OUT(RSA_PRIVATE_ERROR, exit_dcke);
+                            }
+                        }
+
+                        if ((args->idx - args->begin) + args->length > size) {
+                            WOLFSSL_MSG("RSA message too big");
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        /* pre-load PreMasterSecret with RNG data */
+                        ret = wc_RNG_GenerateBlock(ssl->rng,
+                            &ssl->arrays->preMasterSecret[VERSION_SZ],
+                            SECRET_LEN - VERSION_SZ);
+                        if (ret != 0) {
+                            goto exit_dcke;
+                        }
+
+                        args->output = NULL;
+                        break;
+                    } /* rsa_kea */
+                #endif /* !NO_RSA */
+                #ifndef NO_PSK
+                    case psk_kea:
+                    {
+                        byte* pms = ssl->arrays->preMasterSecret;
+                        word16 ci_sz;
+
+                        if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        ato16(input + args->idx, &ci_sz);
+                        args->idx += OPAQUE16_LEN;
+
+                        if (ci_sz > MAX_PSK_ID_LEN) {
+                            ERROR_OUT(CLIENT_ID_ERROR, exit_dcke);
+                        }
+
+                        if ((args->idx - args->begin) + ci_sz > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        XMEMCPY(ssl->arrays->client_identity,
+                                                    input + args->idx, ci_sz);
+                        args->idx += ci_sz;
+
+                        ssl->arrays->client_identity[ci_sz] = '\0'; /* null term */
+                        ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl,
+                            ssl->arrays->client_identity, ssl->arrays->psk_key,
+                            MAX_PSK_KEY_LEN);
+
+                        if (ssl->arrays->psk_keySz == 0 ||
+                                ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
+                            ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
+                        }
+
+                        /* make psk pre master secret */
+                        /* length of key + length 0s + length of key + key */
+                        c16toa((word16) ssl->arrays->psk_keySz, pms);
+                        pms += OPAQUE16_LEN;
+
+                        XMEMSET(pms, 0, ssl->arrays->psk_keySz);
+                        pms += ssl->arrays->psk_keySz;
+
+                        c16toa((word16) ssl->arrays->psk_keySz, pms);
+                        pms += OPAQUE16_LEN;
+
+                        XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
+                        ssl->arrays->preMasterSz =
+                            (ssl->arrays->psk_keySz * 2) + (OPAQUE16_LEN * 2);
+                        break;
+                    }
+                #endif /* !NO_PSK */
+                #ifdef HAVE_NTRU
+                    case ntru_kea:
+                    {
+                        word16 cipherLen;
+                        word16 plainLen = ENCRYPT_LEN;
+
+                        if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        ato16(input + args->idx, &cipherLen);
+                        args->idx += OPAQUE16_LEN;
+
+                        if (cipherLen > MAX_NTRU_ENCRYPT_SZ) {
+                            ERROR_OUT(NTRU_KEY_ERROR, exit_dcke);
+                        }
+
+                        if ((args->idx - args->begin) + cipherLen > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        if (NTRU_OK != ntru_crypto_ntru_decrypt(
+                                    (word16) ssl->buffers.key->length,
+                                    ssl->buffers.key->buffer, cipherLen,
+                                    input + args->idx, &plainLen,
+                                    ssl->arrays->preMasterSecret)) {
+                            ERROR_OUT(NTRU_DECRYPT_ERROR, exit_dcke);
+                        }
+
+                        if (plainLen != SECRET_LEN) {
+                            ERROR_OUT(NTRU_DECRYPT_ERROR, exit_dcke);
+                        }
+
+                        args->idx += cipherLen;
+                        ssl->arrays->preMasterSz = plainLen;
+                        break;
+                    }
+                #endif /* HAVE_NTRU */
+                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                                          defined(HAVE_CURVE448)
+                    case ecc_diffie_hellman_kea:
+                    {
+                    #ifdef HAVE_ECC
+                        ecc_key* private_key = ssl->eccTempKey;
+
+                        /* handle static private key */
+                        if (ssl->specs.static_ecdh &&
+                                          ssl->ecdhCurveOID != ECC_X25519_OID &&
+                                          ssl->ecdhCurveOID != ECC_X448_OID) {
+                            word16 keySz;
+
+                            ssl->buffers.keyType = ecc_dsa_sa_algo;
+                            ret = DecodePrivateKey(ssl, &keySz);
+                            if (ret != 0) {
+                                goto exit_dcke;
+                            }
+                            private_key = (ecc_key*)ssl->hsKey;
+                        }
+                    #endif
+
+                        /* import peer ECC key */
+                        if ((args->idx - args->begin) + OPAQUE8_LEN > size) {
+                        #ifdef WOLFSSL_EXTRA_ALERTS
+                            SendAlert(ssl, alert_fatal, decode_error);
+                        #endif
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        args->length = input[args->idx++];
+
+                        if ((args->idx - args->begin) + args->length > size) {
+                        #ifdef WOLFSSL_EXTRA_ALERTS
+                            SendAlert(ssl, alert_fatal, decode_error);
+                        #endif
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                    #ifdef HAVE_CURVE25519
+                        if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+                        #ifdef HAVE_PK_CALLBACKS
+                            /* if callback then use it for shared secret */
+                            if (ssl->ctx->X25519SharedSecretCb != NULL) {
+                                break;
+                            }
+                        #endif
+                            if (ssl->peerX25519Key == NULL) {
+                                /* alloc/init on demand */
+                                ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519,
+                                    (void**)&ssl->peerX25519Key);
+                                if (ret != 0) {
+                                    goto exit_dcke;
+                                }
+                            } else if (ssl->peerX25519KeyPresent) {
+                                ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519,
+                                               ssl->peerX25519Key);
+                                ssl->peerX25519KeyPresent = 0;
+                                if (ret != 0) {
+                                    goto exit_dcke;
+                                }
+                            }
+
+                            if ((ret = wc_curve25519_check_public(
+                                    input + args->idx, args->length,
+                                    EC25519_LITTLE_ENDIAN)) != 0) {
+                        #ifdef WOLFSSL_EXTRA_ALERTS
+                                if (ret == BUFFER_E)
+                                    SendAlert(ssl, alert_fatal, decode_error);
+                                else if (ret == ECC_OUT_OF_RANGE_E)
+                                    SendAlert(ssl, alert_fatal, bad_record_mac);
+                                else {
+                                    SendAlert(ssl, alert_fatal,
+                                                             illegal_parameter);
+                                }
+                        #endif
+                                ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
+                            }
+
+                            if (wc_curve25519_import_public_ex(
+                                    input + args->idx, args->length,
+                                    ssl->peerX25519Key,
+                                    EC25519_LITTLE_ENDIAN)) {
+                        #ifdef WOLFSSL_EXTRA_ALERTS
+                                SendAlert(ssl, alert_fatal, illegal_parameter);
+                        #endif
+                                ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
+                            }
+
+                            ssl->arrays->preMasterSz = CURVE25519_KEYSIZE;
+
+                            ssl->peerX25519KeyPresent = 1;
+
+                            break;
+                        }
+                    #endif
+                    #ifdef HAVE_CURVE448
+                        if (ssl->ecdhCurveOID == ECC_X448_OID) {
+                        #ifdef HAVE_PK_CALLBACKS
+                            /* if callback then use it for shared secret */
+                            if (ssl->ctx->X448SharedSecretCb != NULL) {
+                                break;
+                            }
+                        #endif
+                            if (ssl->peerX448Key == NULL) {
+                                /* alloc/init on demand */
+                                ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE448,
+                                    (void**)&ssl->peerX448Key);
+                                if (ret != 0) {
+                                    goto exit_dcke;
+                                }
+                            } else if (ssl->peerX448KeyPresent) {
+                                ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE448,
+                                               ssl->peerX448Key);
+                                ssl->peerX448KeyPresent = 0;
+                                if (ret != 0) {
+                                    goto exit_dcke;
+                                }
+                            }
+
+                            if ((ret = wc_curve448_check_public(
+                                    input + args->idx, args->length,
+                                    EC448_LITTLE_ENDIAN)) != 0) {
+                        #ifdef WOLFSSL_EXTRA_ALERTS
+                                if (ret == BUFFER_E)
+                                    SendAlert(ssl, alert_fatal, decode_error);
+                                else if (ret == ECC_OUT_OF_RANGE_E)
+                                    SendAlert(ssl, alert_fatal, bad_record_mac);
+                                else {
+                                    SendAlert(ssl, alert_fatal,
+                                                             illegal_parameter);
+                                }
+                        #endif
+                                ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
+                            }
+
+                            if (wc_curve448_import_public_ex(
+                                    input + args->idx, args->length,
+                                    ssl->peerX448Key,
+                                    EC448_LITTLE_ENDIAN)) {
+                        #ifdef WOLFSSL_EXTRA_ALERTS
+                                SendAlert(ssl, alert_fatal, illegal_parameter);
+                        #endif
+                                ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
+                            }
+
+                            ssl->arrays->preMasterSz = CURVE448_KEY_SIZE;
+
+                            ssl->peerX448KeyPresent = 1;
+
+                            break;
+                        }
+                    #endif
+                #ifdef HAVE_ECC
+                    #ifdef HAVE_PK_CALLBACKS
+                        /* if callback then use it for shared secret */
+                        if (ssl->ctx->EccSharedSecretCb != NULL) {
+                            break;
+                        }
+                    #endif
+
+                        if (!ssl->specs.static_ecdh &&
+                            ssl->eccTempKeyPresent == 0) {
+                            WOLFSSL_MSG("Ecc ephemeral key not made correctly");
+                            ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke);
+                        }
+
+                        if (ssl->peerEccKey == NULL) {
+                            /* alloc/init on demand */
+                            ret = AllocKey(ssl, DYNAMIC_TYPE_ECC,
+                                (void**)&ssl->peerEccKey);
+                            if (ret != 0) {
+                                goto exit_dcke;
+                            }
+                        } else if (ssl->peerEccKeyPresent) {
+                            ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC,
+                                           ssl->peerEccKey);
+                            ssl->peerEccKeyPresent = 0;
+                            if (ret != 0) {
+                                goto exit_dcke;
+                            }
+                        }
+
+                        if (wc_ecc_import_x963_ex(input + args->idx,
+                                                  args->length, ssl->peerEccKey,
+                                                  private_key->dp->id)) {
+                        #ifdef WOLFSSL_EXTRA_ALERTS
+                            SendAlert(ssl, alert_fatal, illegal_parameter);
+                        #endif
+                            ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
+                        }
+
+                        ssl->arrays->preMasterSz = private_key->dp->size;
+
+                        ssl->peerEccKeyPresent = 1;
+                #endif /* HAVE_ECC */
+
+                        break;
+                    }
+                #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+                #ifndef NO_DH
+                    case diffie_hellman_kea:
+                    {
+                        word16 clientPubSz;
+
+                        if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        ato16(input + args->idx, &clientPubSz);
+                        args->idx += OPAQUE16_LEN;
+
+                        if ((args->idx - args->begin) + clientPubSz > size) {
+                        #ifdef WOLFSSL_EXTRA_ALERTS
+                            SendAlert(ssl, alert_fatal, decode_error);
+                        #endif
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        args->sigSz = clientPubSz;
+
+                        ret = AllocKey(ssl, DYNAMIC_TYPE_DH,
+                                            (void**)&ssl->buffers.serverDH_Key);
+                        if (ret != 0) {
+                            goto exit_dcke;
+                        }
+
+                        ret = wc_DhSetKey(ssl->buffers.serverDH_Key,
+                            ssl->buffers.serverDH_P.buffer,
+                            ssl->buffers.serverDH_P.length,
+                            ssl->buffers.serverDH_G.buffer,
+                            ssl->buffers.serverDH_G.length);
+
+                        /* set the max agree result size */
+                        ssl->arrays->preMasterSz = ENCRYPT_LEN;
+                        break;
+                    }
+                #endif /* !NO_DH */
+                #if !defined(NO_DH) && !defined(NO_PSK)
+                    case dhe_psk_kea:
+                    {
+                        word16 clientSz;
+
+                        /* Read in the PSK hint */
+                        if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        ato16(input + args->idx, &clientSz);
+                        args->idx += OPAQUE16_LEN;
+                        if (clientSz > MAX_PSK_ID_LEN) {
+                            ERROR_OUT(CLIENT_ID_ERROR, exit_dcke);
+                        }
+
+                        if ((args->idx - args->begin) + clientSz > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        XMEMCPY(ssl->arrays->client_identity, input + args->idx,
+                                                                    clientSz);
+                        args->idx += clientSz;
+                        ssl->arrays->client_identity[clientSz] = '\0'; /* null term */
+
+                        /* Read in the DHE business */
+                        if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        ato16(input + args->idx, &clientSz);
+                        args->idx += OPAQUE16_LEN;
+
+                        if ((args->idx - args->begin) + clientSz > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        args->sigSz = clientSz;
+
+                        ret = AllocKey(ssl, DYNAMIC_TYPE_DH,
+                                            (void**)&ssl->buffers.serverDH_Key);
+                        if (ret != 0) {
+                            goto exit_dcke;
+                        }
+
+                        ret = wc_DhSetKey(ssl->buffers.serverDH_Key,
+                            ssl->buffers.serverDH_P.buffer,
+                            ssl->buffers.serverDH_P.length,
+                            ssl->buffers.serverDH_G.buffer,
+                            ssl->buffers.serverDH_G.length);
+
+                        break;
+                    }
+                #endif /* !NO_DH && !NO_PSK */
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                     defined(HAVE_CURVE448)) && !defined(NO_PSK)
+                    case ecdhe_psk_kea:
+                    {
+                        word16 clientSz;
+
+                        /* Read in the PSK hint */
+                        if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        ato16(input + args->idx, &clientSz);
+                        args->idx += OPAQUE16_LEN;
+                        if (clientSz > MAX_PSK_ID_LEN) {
+                            ERROR_OUT(CLIENT_ID_ERROR, exit_dcke);
+                        }
+                        if ((args->idx - args->begin) + clientSz > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        XMEMCPY(ssl->arrays->client_identity,
+                                                   input + args->idx, clientSz);
+                        args->idx += clientSz;
+                        ssl->arrays->client_identity[clientSz] = '\0'; /* null term */
+
+                        /* import peer ECC key */
+                        if ((args->idx - args->begin) + OPAQUE8_LEN > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        args->length = input[args->idx++];
+
+                        if ((args->idx - args->begin) + args->length > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        args->sigSz = ENCRYPT_LEN - OPAQUE16_LEN;
+
+                    #ifdef HAVE_CURVE25519
+                        if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+                        #ifdef HAVE_PK_CALLBACKS
+                            /* if callback then use it for shared secret */
+                            if (ssl->ctx->X25519SharedSecretCb != NULL) {
+                                break;
+                            }
+                        #endif
+
+                            if (ssl->eccTempKeyPresent == 0) {
+                                WOLFSSL_MSG(
+                                     "X25519 ephemeral key not made correctly");
+                                ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke);
+                            }
+
+                            if (ssl->peerX25519Key == NULL) {
+                                /* alloc/init on demand */
+                                ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519,
+                                    (void**)&ssl->peerX25519Key);
+                                if (ret != 0) {
+                                    goto exit_dcke;
+                                }
+                            } else if (ssl->peerX25519KeyPresent) {
+                                ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519,
+                                               ssl->peerX25519Key);
+                                ssl->peerX25519KeyPresent = 0;
+                                if (ret != 0) {
+                                    goto exit_dcke;
+                                }
+                            }
+
+                            if ((ret = wc_curve25519_check_public(
+                                    input + args->idx, args->length,
+                                    EC25519_LITTLE_ENDIAN)) != 0) {
+                        #ifdef WOLFSSL_EXTRA_ALERTS
+                                if (ret == BUFFER_E)
+                                    SendAlert(ssl, alert_fatal, decode_error);
+                                else if (ret == ECC_OUT_OF_RANGE_E)
+                                    SendAlert(ssl, alert_fatal, bad_record_mac);
+                                else {
+                                    SendAlert(ssl, alert_fatal,
+                                                             illegal_parameter);
+                                }
+                        #endif
+                                ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
+                            }
+
+                            if (wc_curve25519_import_public_ex(
+                                    input + args->idx, args->length,
+                                    ssl->peerX25519Key,
+                                    EC25519_LITTLE_ENDIAN)) {
+                                ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
+                            }
+
+                            ssl->peerX25519KeyPresent = 1;
+
+                            break;
+                        }
+                    #endif
+                    #ifdef HAVE_CURVE448
+                        if (ssl->ecdhCurveOID == ECC_X448_OID) {
+                        #ifdef HAVE_PK_CALLBACKS
+                            /* if callback then use it for shared secret */
+                            if (ssl->ctx->X448SharedSecretCb != NULL) {
+                                break;
+                            }
+                        #endif
+
+                            if (ssl->eccTempKeyPresent == 0) {
+                                WOLFSSL_MSG(
+                                       "X448 ephemeral key not made correctly");
+                                ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke);
+                            }
+
+                            if (ssl->peerX448Key == NULL) {
+                                /* alloc/init on demand */
+                                ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE448,
+                                    (void**)&ssl->peerX448Key);
+                                if (ret != 0) {
+                                    goto exit_dcke;
+                                }
+                            } else if (ssl->peerX448KeyPresent) {
+                                ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE448,
+                                               ssl->peerX448Key);
+                                ssl->peerX448KeyPresent = 0;
+                                if (ret != 0) {
+                                    goto exit_dcke;
+                                }
+                            }
+
+                            if ((ret = wc_curve448_check_public(
+                                    input + args->idx, args->length,
+                                    EC448_LITTLE_ENDIAN)) != 0) {
+                        #ifdef WOLFSSL_EXTRA_ALERTS
+                                if (ret == BUFFER_E)
+                                    SendAlert(ssl, alert_fatal, decode_error);
+                                else if (ret == ECC_OUT_OF_RANGE_E)
+                                    SendAlert(ssl, alert_fatal, bad_record_mac);
+                                else {
+                                    SendAlert(ssl, alert_fatal,
+                                                             illegal_parameter);
+                                }
+                        #endif
+                                ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
+                            }
+
+                            if (wc_curve448_import_public_ex(
+                                    input + args->idx, args->length,
+                                    ssl->peerX448Key,
+                                    EC448_LITTLE_ENDIAN)) {
+                                ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
+                            }
+
+                            ssl->peerX448KeyPresent = 1;
+
+                            break;
+                        }
+                    #endif
+                    #ifdef HAVE_PK_CALLBACKS
+                        /* if callback then use it for shared secret */
+                        if (ssl->ctx->EccSharedSecretCb != NULL) {
+                            break;
+                        }
+                    #endif
+
+                        if (ssl->eccTempKeyPresent == 0) {
+                            WOLFSSL_MSG("Ecc ephemeral key not made correctly");
+                            ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke);
+                        }
+
+                        if (ssl->peerEccKey == NULL) {
+                            /* alloc/init on demand */
+                            ret = AllocKey(ssl, DYNAMIC_TYPE_ECC,
+                                (void**)&ssl->peerEccKey);
+                            if (ret != 0) {
+                                goto exit_dcke;
+                            }
+                        }
+                        else if (ssl->peerEccKeyPresent) {
+                            ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC,
+                                           ssl->peerEccKey);
+                            ssl->peerEccKeyPresent = 0;
+                            if (ret != 0) {
+                                goto exit_dcke;
+                            }
+                        }
+                        if (wc_ecc_import_x963_ex(input + args->idx,
+                                 args->length, ssl->peerEccKey,
+                                 ssl->eccTempKey->dp->id)) {
+                            ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
+                        }
+
+                        ssl->peerEccKeyPresent = 1;
+                        break;
+                    }
+                #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */
+                    default:
+                        ret = BAD_KEA_TYPE_E;
+                } /* switch (ssl->specs.kea) */
+
+                /* Check for error */
+                if (ret != 0) {
+                    goto exit_dcke;
+                }
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_DO;
+            } /* TLS_ASYNC_BUILD */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_DO:
+            {
+                switch (ssl->specs.kea) {
+                #ifndef NO_RSA
+                    case rsa_kea:
+                    {
+                        RsaKey* key = (RsaKey*)ssl->hsKey;
+
+                        ret = RsaDec(ssl,
+                            input + args->idx,
+                            args->length,
+                            &args->output,
+                            &args->sigSz,
+                            key,
+                        #ifdef HAVE_PK_CALLBACKS
+                            ssl->buffers.key
+                        #else
+                            NULL
+                        #endif
+                        );
+
+                        /*  Errors that can occur here that should be
+                         *  indistinguishable:
+                         *       RSA_BUFFER_E, RSA_PAD_E and RSA_PRIVATE_ERROR
+                         */
+                    #ifdef WOLFSSL_ASYNC_CRYPT
+                        if (ret == WC_PENDING_E)
+                            goto exit_dcke;
+                    #endif
+                        if (ret == BAD_FUNC_ARG)
+                            goto exit_dcke;
+
+                        args->lastErr = ret - (SECRET_LEN - args->sigSz);
+                        ret = 0;
+                        break;
+                    } /* rsa_kea */
+                #endif /* !NO_RSA */
+                #ifndef NO_PSK
+                    case psk_kea:
+                    {
+                        break;
+                    }
+                #endif /* !NO_PSK */
+                #ifdef HAVE_NTRU
+                    case ntru_kea:
+                    {
+                        break;
+                    }
+                #endif /* HAVE_NTRU */
+                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                                          defined(HAVE_CURVE448)
+                    case ecc_diffie_hellman_kea:
+                    {
+                        void* private_key = ssl->eccTempKey;
+                        (void)private_key;
+
+                    #ifdef HAVE_CURVE25519
+                        if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+                            ret = X25519SharedSecret(ssl,
+                                (curve25519_key*)private_key,
+                                ssl->peerX25519Key,
+                                input + args->idx, &args->length,
+                                ssl->arrays->preMasterSecret,
+                                &ssl->arrays->preMasterSz,
+                                WOLFSSL_SERVER_END
+                            );
+                            break;
+                        }
+                    #endif
+                    #ifdef HAVE_CURVE448
+                        if (ssl->ecdhCurveOID == ECC_X448_OID) {
+                            ret = X448SharedSecret(ssl,
+                                (curve448_key*)private_key,
+                                ssl->peerX448Key,
+                                input + args->idx, &args->length,
+                                ssl->arrays->preMasterSecret,
+                                &ssl->arrays->preMasterSz,
+                                WOLFSSL_SERVER_END
+                            );
+                            break;
+                        }
+                    #endif
+                    #ifdef HAVE_ECC
+                        if (ssl->specs.static_ecdh) {
+                            private_key = ssl->hsKey;
+                        }
+
+                        /* Generate shared secret */
+                        ret = EccSharedSecret(ssl,
+                            (ecc_key*)private_key, ssl->peerEccKey,
+                            input + args->idx, &args->length,
+                            ssl->arrays->preMasterSecret,
+                            &ssl->arrays->preMasterSz,
+                            WOLFSSL_SERVER_END
+                        );
+                    #ifdef WOLFSSL_ASYNC_CRYPT
+                        if (ret != WC_PENDING_E)
+                    #endif
+                        {
+                            FreeKey(ssl, DYNAMIC_TYPE_ECC,
+                                                      (void**)&ssl->peerEccKey);
+                            ssl->peerEccKeyPresent = 0;
+                        }
+                    #endif
+                        break;
+                    }
+                #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+                #ifndef NO_DH
+                    case diffie_hellman_kea:
+                    {
+                        ret = DhAgree(ssl, ssl->buffers.serverDH_Key,
+                            ssl->buffers.serverDH_Priv.buffer,
+                            ssl->buffers.serverDH_Priv.length,
+                            input + args->idx,
+                            (word16)args->sigSz,
+                            ssl->arrays->preMasterSecret,
+                            &ssl->arrays->preMasterSz);
+                        break;
+                    }
+                #endif /* !NO_DH */
+                #if !defined(NO_DH) && !defined(NO_PSK)
+                    case dhe_psk_kea:
+                    {
+                        ret = DhAgree(ssl, ssl->buffers.serverDH_Key,
+                            ssl->buffers.serverDH_Priv.buffer,
+                            ssl->buffers.serverDH_Priv.length,
+                            input + args->idx,
+                            (word16)args->sigSz,
+                            ssl->arrays->preMasterSecret + OPAQUE16_LEN,
+                            &ssl->arrays->preMasterSz);
+                        break;
+                    }
+                #endif /* !NO_DH && !NO_PSK */
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                     defined(HAVE_CURVE448)) && !defined(NO_PSK)
+                    case ecdhe_psk_kea:
+                    {
+                    #ifdef HAVE_CURVE25519
+                        if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+                            ret = X25519SharedSecret(ssl,
+                                (curve25519_key*)ssl->eccTempKey,
+                                ssl->peerX25519Key,
+                                input + args->idx, &args->length,
+                                ssl->arrays->preMasterSecret + OPAQUE16_LEN,
+                                &args->sigSz,
+                                WOLFSSL_SERVER_END
+                            );
+                        #ifdef WOLFSSL_ASYNC_CRYPT
+                            if (ret != WC_PENDING_E)
+                        #endif
+                            {
+                                FreeKey(ssl, DYNAMIC_TYPE_CURVE25519,
+                                                   (void**)&ssl->peerX25519Key);
+                                ssl->peerX25519KeyPresent = 0;
+                            }
+                            break;
+                        }
+                    #endif
+                    #ifdef HAVE_CURVE448
+                        if (ssl->ecdhCurveOID == ECC_X448_OID) {
+                            ret = X448SharedSecret(ssl,
+                                (curve448_key*)ssl->eccTempKey,
+                                ssl->peerX448Key,
+                                input + args->idx, &args->length,
+                                ssl->arrays->preMasterSecret + OPAQUE16_LEN,
+                                &args->sigSz,
+                                WOLFSSL_SERVER_END
+                            );
+                        #ifdef WOLFSSL_ASYNC_CRYPT
+                            if (ret != WC_PENDING_E)
+                        #endif
+                            {
+                                FreeKey(ssl, DYNAMIC_TYPE_CURVE448,
+                                                     (void**)&ssl->peerX448Key);
+                                ssl->peerX448KeyPresent = 0;
+                            }
+                            break;
+                        }
+                    #endif
+                        /* Generate shared secret */
+                        ret = EccSharedSecret(ssl,
+                            ssl->eccTempKey, ssl->peerEccKey,
+                            input + args->idx, &args->length,
+                            ssl->arrays->preMasterSecret + OPAQUE16_LEN,
+                            &args->sigSz,
+                            WOLFSSL_SERVER_END
+                        );
+                        if (!ssl->specs.static_ecdh
+                    #ifdef WOLFSSL_ASYNC_CRYPT
+                            && ret != WC_PENDING_E
+                    #endif
+                        ) {
+                            FreeKey(ssl, DYNAMIC_TYPE_ECC,
+                                                      (void**)&ssl->peerEccKey);
+                            ssl->peerEccKeyPresent = 0;
+                        }
+                        break;
+                    }
+                #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */
+                    default:
+                        ret = BAD_KEA_TYPE_E;
+                } /* switch (ssl->specs.kea) */
+
+                /* Check for error */
+                if (ret != 0) {
+                    goto exit_dcke;
+                }
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_VERIFY;
+            } /* TLS_ASYNC_DO */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_VERIFY:
+            {
+                switch (ssl->specs.kea) {
+                #ifndef NO_RSA
+                    case rsa_kea:
+                    {
+                        byte mask;
+                        int i;
+
+                        /* Add the signature length to idx */
+                        args->idx += args->length;
+
+                    #ifdef DEBUG_WOLFSSL
+                        /* check version (debug warning message only) */
+                        if (args->output != NULL) {
+                            if (args->output[0] != ssl->chVersion.major ||
+                                args->output[1] != ssl->chVersion.minor) {
+                                WOLFSSL_MSG("preMasterSecret version mismatch");
+                            }
+                        }
+                    #endif
+
+                        /* RFC5246 7.4.7.1:
+                         * Treat incorrectly formatted message blocks and/or
+                         * mismatched version numbers in a manner
+                         * indistinguishable from correctly formatted RSA blocks
+                         */
+
+                        ret = args->lastErr;
+                        args->lastErr = 0; /* reset */
+                        /* On error 'ret' will be negative - top bit set */
+                        mask = ((unsigned int)ret >>
+                                                   ((sizeof(ret) * 8) - 1)) - 1;
+
+                        /* build PreMasterSecret */
+                        ssl->arrays->preMasterSecret[0] = ssl->chVersion.major;
+                        ssl->arrays->preMasterSecret[1] = ssl->chVersion.minor;
+
+                        if (args->output != NULL) {
+                            /* Use random secret on error */
+                            for (i = VERSION_SZ; i < SECRET_LEN; i++) {
+                                ssl->arrays->preMasterSecret[i] =
+                                     ctMaskSel(mask, args->output[i],
+                                               ssl->arrays->preMasterSecret[i]);
+                            }
+                        }
+                        /* preMasterSecret has RNG and version set
+                         * return proper length and ignore error
+                         * error will be caught as decryption error
+                         */
+                        args->sigSz = SECRET_LEN;
+                        ret = 0;
+                        break;
+                    } /* rsa_kea */
+                #endif /* !NO_RSA */
+                #ifndef NO_PSK
+                    case psk_kea:
+                    {
+                        break;
+                    }
+                #endif /* !NO_PSK */
+                #ifdef HAVE_NTRU
+                    case ntru_kea:
+                    {
+                        break;
+                    }
+                #endif /* HAVE_NTRU */
+                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                                          defined(HAVE_CURVE448)
+                    case ecc_diffie_hellman_kea:
+                    {
+                        /* skip past the imported peer key */
+                        args->idx += args->length;
+                        break;
+                    }
+                #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+                #ifndef NO_DH
+                    case diffie_hellman_kea:
+                    {
+                        args->idx += (word16)args->sigSz;
+                        break;
+                    }
+                #endif /* !NO_DH */
+                #if !defined(NO_DH) && !defined(NO_PSK)
+                    case dhe_psk_kea:
+                    {
+                        byte* pms = ssl->arrays->preMasterSecret;
+                        word16 clientSz = (word16)args->sigSz;
+
+                        args->idx += clientSz;
+                        c16toa((word16)ssl->arrays->preMasterSz, pms);
+                        ssl->arrays->preMasterSz += OPAQUE16_LEN;
+                        pms += ssl->arrays->preMasterSz;
+
+                        /* Use the PSK hint to look up the PSK and add it to the
+                         * preMasterSecret here. */
+                        ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl,
+                            ssl->arrays->client_identity, ssl->arrays->psk_key,
+                            MAX_PSK_KEY_LEN);
+
+                        if (ssl->arrays->psk_keySz == 0 ||
+                                ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
+                            ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
+                        }
+
+                        c16toa((word16) ssl->arrays->psk_keySz, pms);
+                        pms += OPAQUE16_LEN;
+
+                        XMEMCPY(pms, ssl->arrays->psk_key,
+                                                    ssl->arrays->psk_keySz);
+                        ssl->arrays->preMasterSz += ssl->arrays->psk_keySz +
+                                                                OPAQUE16_LEN;
+                        break;
+                    }
+                #endif /* !NO_DH && !NO_PSK */
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                     defined(HAVE_CURVE448)) && !defined(NO_PSK)
+                    case ecdhe_psk_kea:
+                    {
+                        byte* pms = ssl->arrays->preMasterSecret;
+                        word16 clientSz = (word16)args->sigSz;
+
+                        /* skip past the imported peer key */
+                        args->idx += args->length;
+
+                        /* Add preMasterSecret */
+                        c16toa(clientSz, pms);
+                        ssl->arrays->preMasterSz = OPAQUE16_LEN + clientSz;
+                        pms += ssl->arrays->preMasterSz;
+
+                        /* Use the PSK hint to look up the PSK and add it to the
+                         * preMasterSecret here. */
+                        ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl,
+                            ssl->arrays->client_identity, ssl->arrays->psk_key,
+                            MAX_PSK_KEY_LEN);
+
+                        if (ssl->arrays->psk_keySz == 0 ||
+                                   ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
+                            ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
+                        }
+
+                        c16toa((word16) ssl->arrays->psk_keySz, pms);
+                        pms += OPAQUE16_LEN;
+
+                        XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
+                        ssl->arrays->preMasterSz +=
+                                      ssl->arrays->psk_keySz + OPAQUE16_LEN;
+                        break;
+                    }
+                #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */
+                    default:
+                        ret = BAD_KEA_TYPE_E;
+                } /* switch (ssl->specs.kea) */
+
+                /* Check for error */
+                if (ret != 0) {
+                    goto exit_dcke;
+                }
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_FINALIZE;
+            } /* TLS_ASYNC_VERIFY */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_FINALIZE:
+            {
+                if (IsEncryptionOn(ssl, 0)) {
+                    args->idx += ssl->keys.padSz;
+            #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+                    if (ssl->options.startedETMRead)
+                        args->idx += MacSize(ssl);
+            #endif
+                }
+
+            #ifdef HAVE_QSH
+                word16 name;
+
+                if (ssl->options.haveQSH) {
+                    /* extension name */
+                    ato16(input + args->idx, &name);
+                    args->idx += OPAQUE16_LEN;
+
+                    if (name == TLSX_QUANTUM_SAFE_HYBRID) {
+                        int    qshSz;
+                        /* if qshSz is larger than 0 it is the
+                           length of buffer used */
+                        if ((qshSz = TLSX_QSHCipher_Parse(ssl,
+                                input + args->idx,
+                                size - args->idx + args->begin, 1)) < 0) {
+                            ERROR_OUT(qshSz, exit_dcke);
+                        }
+                        args->idx += qshSz;
+                    }
+                    else {
+                        /* unknown extension sent client ignored handshake */
+                        ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                    }
+                }
+            #endif /* HAVE_QSH */
+                ret = MakeMasterSecret(ssl);
+
+                /* Check for error */
+                if (ret != 0) {
+                    goto exit_dcke;
+                }
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_END;
+            } /* TLS_ASYNC_FINALIZE */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_END:
+            {
+                /* Set final index */
+                *inOutIdx = args->idx;
+
+                ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
+            #ifndef NO_CERTS
+                if (ssl->options.verifyPeer) {
+                    ret = BuildCertHashes(ssl, &ssl->hsHashes->certHashes);
+                }
+            #endif
+                break;
+            } /* TLS_ASYNC_END */
+            default:
+                ret = INPUT_CASE_ERROR;
+        } /* switch(ssl->options.asyncState) */
+
+    exit_dcke:
+
+        WOLFSSL_LEAVE("DoClientKeyExchange", ret);
+        WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_DO);
+
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        /* Handle async operation */
+        if (ret == WC_PENDING_E) {
+            /* Mark message as not received so it can process again */
+            ssl->msgsReceived.got_client_key_exchange = 0;
+
+            return ret;
+        }
+    #endif /* WOLFSSL_ASYNC_CRYPT */
+
+        /* Cleanup PMS */
+        if (ssl->arrays->preMasterSecret != NULL) {
+            ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz);
+        }
+        ssl->arrays->preMasterSz = 0;
+
+        /* Final cleanup */
+        FreeDckeArgs(ssl, args);
+        FreeKeyExchange(ssl);
+
+        return ret;
+    }
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \
+    defined(WOLFSSL_HAPROXY)
+    int SNI_Callback(WOLFSSL* ssl)
+    {
+        /* Stunnel supports a custom sni callback to switch an SSL's ctx
+        * when SNI is received. Call it now if exists */
+        if(ssl && ssl->ctx && ssl->ctx->sniRecvCb) {
+            WOLFSSL_MSG("Calling custom sni callback");
+            if(ssl->ctx->sniRecvCb(ssl, NULL, ssl->ctx->sniRecvCbArg)
+                    == alert_fatal) {
+                WOLFSSL_MSG("Error in custom sni callback. Fatal alert");
+                SendAlert(ssl, alert_fatal, unrecognized_name);
+                return FATAL_ERROR;
+            }
+        }
+        return 0;
+    }
+#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
+
+#endif /* NO_WOLFSSL_SERVER */
+
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+int wolfSSL_AsyncPop(WOLFSSL* ssl, byte* state)
+{
+    int ret = 0;
+    WC_ASYNC_DEV* asyncDev;
+    WOLF_EVENT* event;
+
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* check for pending async */
+    asyncDev = ssl->async.dev;
+    if (asyncDev) {
+        /* grab event pointer */
+        event = &asyncDev->event;
+
+        ret = wolfAsync_EventPop(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL);
+        if (ret != WC_NOT_PENDING_E && ret != WC_PENDING_E) {
+
+            /* advance key share state if doesn't need called again */
+            if (state && (asyncDev->event.flags & WC_ASYNC_FLAG_CALL_AGAIN) == 0) {
+                (*state)++;
+            }
+
+            /* clear event */
+            XMEMSET(&asyncDev->event, 0, sizeof(WOLF_EVENT));
+
+            /* clear async dev */
+            ssl->async.dev = NULL;
+        }
+    }
+    else {
+        ret = WC_NOT_PENDING_E;
+    }
+
+    WOLFSSL_LEAVE("wolfSSL_AsyncPop", ret);
+
+    return ret;
+}
+
+int wolfSSL_AsyncInit(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev, word32 flags)
+{
+    int ret;
+    WOLF_EVENT* event;
+
+    if (ssl == NULL || asyncDev == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* grab event pointer */
+    event = &asyncDev->event;
+
+    /* init event */
+    ret = wolfAsync_EventInit(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL, ssl, flags);
+
+    WOLFSSL_LEAVE("wolfSSL_AsyncInit", ret);
+
+    return ret;
+}
+
+int wolfSSL_AsyncPush(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev)
+{
+    int ret;
+    WOLF_EVENT* event;
+
+    if (ssl == NULL || asyncDev == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* grab event pointer */
+    event = &asyncDev->event;
+
+    /* store reference to active async operation */
+    ssl->async.dev = asyncDev;
+
+    /* place event into queue */
+    ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, event);
+
+    /* success means return WC_PENDING_E */
+    if (ret == 0) {
+        ret = WC_PENDING_E;
+    }
+
+    WOLFSSL_LEAVE("wolfSSL_AsyncPush", ret);
+
+    return ret;
+}
+
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+
+/* return the max record size */
+int wolfSSL_GetMaxRecordSize(WOLFSSL* ssl, int maxFragment)
+{
+    (void) ssl; /* Avoid compiler warnings */
+
+    if (maxFragment > MAX_RECORD_SIZE) {
+        maxFragment = MAX_RECORD_SIZE;
+    }
+
+#ifdef HAVE_MAX_FRAGMENT
+    if ((ssl->max_fragment != 0) && ((word16)maxFragment > ssl->max_fragment)) {
+        maxFragment = ssl->max_fragment;
+    }
+#endif /* HAVE_MAX_FRAGMENT */
+#ifdef WOLFSSL_DTLS
+    if ((ssl->options.dtls) && (maxFragment > MAX_UDP_SIZE)) {
+        maxFragment = MAX_UDP_SIZE;
+    }
+#endif
+
+    return maxFragment;
+}
+
+
+#undef ERROR_OUT
+
+#endif /* WOLFCRYPT_ONLY */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/keys.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/keys.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/keys.c	(revision 453)
@@ -0,0 +1,3607 @@
+/* keys.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+/* Name change compatibility layer no longer needs to be included here */
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifndef WOLFCRYPT_ONLY
+
+#include <wolfssl/internal.h>
+#include <wolfssl/error-ssl.h>
+#if defined(SHOW_SECRETS) || defined(CHACHA_AEAD_TEST)
+    #ifndef NO_STDIO_FILESYSTEM
+        #include <stdio.h>
+    #endif
+#endif
+
+#if defined(WOLFSSL_RENESAS_TSIP_TLS) && \
+    !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION)
+ int tsip_useable(const WOLFSSL *ssl);
+#endif
+int SetCipherSpecs(WOLFSSL* ssl)
+{
+#ifndef NO_WOLFSSL_CLIENT
+    if (ssl->options.side == WOLFSSL_CLIENT_END) {
+        /* server side verified before SetCipherSpecs call */
+        if (VerifyClientSuite(ssl) != 1) {
+            WOLFSSL_MSG("SetCipherSpecs() client has an unusable suite");
+            return UNSUPPORTED_SUITE;
+        }
+    }
+#endif /* NO_WOLFSSL_CLIENT */
+
+    /* Chacha extensions, 0xcc */
+    if (ssl->options.cipherSuite0 == CHACHA_BYTE) {
+
+    switch (ssl->options.cipherSuite) {
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+    case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256:
+        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
+        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
+        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
+        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
+        ssl->options.oldPoly             = 1; /* use old poly1305 padding */
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+    case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256:
+        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
+        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
+        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
+        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
+        ssl->options.oldPoly             = 1; /* use old poly1305 padding */
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+    case TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256:
+        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
+        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
+        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
+        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
+        ssl->options.oldPoly             = 1; /* use old poly1305 padding */
+
+        break;
+#endif
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+    case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
+        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
+        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
+        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
+        ssl->options.oldPoly             = 0; /* use recent padding RFC */
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
+    case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
+        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
+        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
+        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
+        ssl->options.oldPoly             = 0; /* use recent padding RFC */
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+    case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
+        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
+        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
+        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
+        ssl->options.oldPoly             = 0; /* use recent padding RFC */
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256
+    case TLS_PSK_WITH_CHACHA20_POLY1305_SHA256:
+        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
+        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
+        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
+        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
+
+        ssl->options.oldPoly             = 0; /* use recent padding RFC */
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256
+    case TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
+        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecdhe_psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
+        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
+        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
+        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
+
+        ssl->options.oldPoly             = 0; /* use recent padding RFC */
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256
+    case TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
+        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = dhe_psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
+        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
+        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
+        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
+
+        ssl->options.oldPoly             = 0; /* use recent padding RFC */
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+    default:
+        WOLFSSL_MSG("Unsupported cipher suite, SetCipherSpecs ChaCha");
+        return UNSUPPORTED_SUITE;
+    }
+    }
+
+    /* ECC extensions, AES-CCM or TLS 1.3 Integrity-only */
+    if (ssl->options.cipherSuite0 == ECC_BYTE) {
+
+    switch (ssl->options.cipherSuite) {
+
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+    case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
+    case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+    case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+    case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = DES3_KEY_SIZE;
+        ssl->specs.block_size            = DES_BLOCK_SIZE;
+        ssl->specs.iv_size               = DES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
+    case TLS_ECDHE_RSA_WITH_RC4_128_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_rc4;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = RC4_KEY_SIZE;
+        ssl->specs.iv_size               = 0;
+        ssl->specs.block_size            = 0;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+    case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+    case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+    case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256
+    case TLS_ECDHE_PSK_WITH_NULL_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecdhe_psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = 0;
+        ssl->specs.block_size            = 0;
+        ssl->specs.iv_size               = 0;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
+    case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecdhe_psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
+
+#if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && defined(HAVE_ED25519)) \
+                      || (defined(HAVE_CURVE448) && defined(HAVE_ED448))
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
+    case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
+    case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+    case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = DES3_KEY_SIZE;
+        ssl->specs.block_size            = DES_BLOCK_SIZE;
+        ssl->specs.iv_size               = DES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+    case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_rc4;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = RC4_KEY_SIZE;
+        ssl->specs.iv_size               = 0;
+        ssl->specs.block_size            = 0;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+    case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+    case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+    case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+    case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM
+    case TLS_ECDHE_ECDSA_WITH_AES_128_CCM :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_CCM_16_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
+    case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_CCM_8_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8
+    case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_CCM_8_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA
+    case TLS_ECDHE_ECDSA_WITH_NULL_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = 0;
+        ssl->specs.block_size            = 0;
+        ssl->specs.iv_size               = 0;
+
+    break;
+#endif
+
+#endif /* HAVE_ECC || (CURVE25519 && ED25519) || (CURVE448 && ED448) */
+
+#if defined(HAVE_ECC)
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
+    case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
+    case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
+    case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
+    case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
+    case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+    case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = DES3_KEY_SIZE;
+        ssl->specs.block_size            = DES_BLOCK_SIZE;
+        ssl->specs.iv_size               = DES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA
+    case TLS_ECDH_RSA_WITH_RC4_128_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_rc4;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = RC4_KEY_SIZE;
+        ssl->specs.iv_size               = 0;
+        ssl->specs.block_size            = 0;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+    case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = DES3_KEY_SIZE;
+        ssl->specs.block_size            = DES_BLOCK_SIZE;
+        ssl->specs.iv_size               = DES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
+    case TLS_ECDH_ECDSA_WITH_RC4_128_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_rc4;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = RC4_KEY_SIZE;
+        ssl->specs.iv_size               = 0;
+        ssl->specs.block_size            = 0;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+    case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+    case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+    case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+    case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
+    case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+    case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
+    case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        break;
+#endif
+
+#endif /* HAVE_ECC */
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8
+    case TLS_RSA_WITH_AES_128_CCM_8 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_CCM_8_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8
+    case TLS_RSA_WITH_AES_256_CCM_8 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_CCM_8_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM_8
+    case TLS_PSK_WITH_AES_128_CCM_8 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_CCM_8_AUTH_SZ;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM_8
+    case TLS_PSK_WITH_AES_256_CCM_8 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_CCM_8_AUTH_SZ;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM
+    case TLS_PSK_WITH_AES_128_CCM :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_CCM_16_AUTH_SZ;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM
+    case TLS_PSK_WITH_AES_256_CCM :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_CCM_16_AUTH_SZ;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CCM
+    case TLS_DHE_PSK_WITH_AES_128_CCM :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = dhe_psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_CCM_16_AUTH_SZ;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CCM
+    case TLS_DHE_PSK_WITH_AES_256_CCM :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = dhe_psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_CCM_16_AUTH_SZ;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#if defined(WOLFSSL_TLS13) && defined(HAVE_NULL_CIPHER)
+    #ifdef BUILD_TLS_SHA256_SHA256
+    case TLS_SHA256_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = 0;
+        ssl->specs.sig_algo              = 0;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = WC_SHA256_DIGEST_SIZE / 2;
+        ssl->specs.block_size            = 0;
+        ssl->specs.iv_size               = HMAC_NONCE_SZ;
+        ssl->specs.aead_mac_size         = WC_SHA256_DIGEST_SIZE;
+
+        break;
+    #endif
+
+    #ifdef BUILD_TLS_SHA384_SHA384
+    case TLS_SHA384_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = 0;
+        ssl->specs.sig_algo              = 0;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = WC_SHA384_DIGEST_SIZE / 2;
+        ssl->specs.block_size            = 0;
+        ssl->specs.iv_size               = HMAC_NONCE_SZ;
+        ssl->specs.aead_mac_size         = WC_SHA384_DIGEST_SIZE;
+
+        break;
+    #endif
+#endif
+
+    default:
+        WOLFSSL_MSG("Unsupported cipher suite, SetCipherSpecs ECC");
+        return UNSUPPORTED_SUITE;
+    }   /* switch */
+    }   /* if     */
+
+    /* TLSi v1.3 cipher suites, 0x13 */
+    if (ssl->options.cipherSuite0 == TLS13_BYTE) {
+        switch (ssl->options.cipherSuite) {
+
+#ifdef WOLFSSL_TLS13
+    #ifdef BUILD_TLS_AES_128_GCM_SHA256
+        case TLS_AES_128_GCM_SHA256 :
+            ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+            ssl->specs.cipher_type           = aead;
+            ssl->specs.mac_algorithm         = sha256_mac;
+            ssl->specs.kea                   = 0;
+            ssl->specs.sig_algo              = 0;
+            ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+            ssl->specs.pad_size              = PAD_SHA;
+            ssl->specs.static_ecdh           = 0;
+            ssl->specs.key_size              = AES_128_KEY_SIZE;
+            ssl->specs.block_size            = AES_BLOCK_SIZE;
+            ssl->specs.iv_size               = AESGCM_NONCE_SZ;
+            ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+            break;
+    #endif
+
+    #ifdef BUILD_TLS_AES_256_GCM_SHA384
+        case TLS_AES_256_GCM_SHA384 :
+            ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+            ssl->specs.cipher_type           = aead;
+            ssl->specs.mac_algorithm         = sha384_mac;
+            ssl->specs.kea                   = 0;
+            ssl->specs.sig_algo              = 0;
+            ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+            ssl->specs.pad_size              = PAD_SHA;
+            ssl->specs.static_ecdh           = 0;
+            ssl->specs.key_size              = AES_256_KEY_SIZE;
+            ssl->specs.block_size            = AES_BLOCK_SIZE;
+            ssl->specs.iv_size               = AESGCM_NONCE_SZ;
+            ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+            break;
+    #endif
+
+    #ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256
+        case TLS_CHACHA20_POLY1305_SHA256 :
+            ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
+            ssl->specs.cipher_type           = aead;
+            ssl->specs.mac_algorithm         = sha256_mac;
+            ssl->specs.kea                   = 0;
+            ssl->specs.sig_algo              = 0;
+            ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+            ssl->specs.pad_size              = PAD_SHA;
+            ssl->specs.static_ecdh           = 0;
+            ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
+            ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
+            ssl->specs.iv_size               = CHACHA20_IV_SIZE;
+            ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
+            ssl->options.oldPoly             = 0; /* use recent padding RFC */
+
+            break;
+    #endif
+
+    #ifdef BUILD_TLS_AES_128_CCM_SHA256
+        case TLS_AES_128_CCM_SHA256 :
+            ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
+            ssl->specs.cipher_type           = aead;
+            ssl->specs.mac_algorithm         = sha256_mac;
+            ssl->specs.kea                   = 0;
+            ssl->specs.sig_algo              = 0;
+            ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+            ssl->specs.pad_size              = PAD_SHA;
+            ssl->specs.static_ecdh           = 0;
+            ssl->specs.key_size              = AES_128_KEY_SIZE;
+            ssl->specs.block_size            = AES_BLOCK_SIZE;
+            ssl->specs.iv_size               = AESGCM_NONCE_SZ;
+            ssl->specs.aead_mac_size         = AES_CCM_16_AUTH_SZ;
+
+            break;
+    #endif
+
+    #ifdef BUILD_TLS_AES_128_CCM_8_SHA256
+        case TLS_AES_128_CCM_8_SHA256 :
+            ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
+            ssl->specs.cipher_type           = aead;
+            ssl->specs.mac_algorithm         = sha256_mac;
+            ssl->specs.kea                   = 0;
+            ssl->specs.sig_algo              = 0;
+            ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+            ssl->specs.pad_size              = PAD_SHA;
+            ssl->specs.static_ecdh           = 0;
+            ssl->specs.key_size              = AES_128_KEY_SIZE;
+            ssl->specs.block_size            = AES_BLOCK_SIZE;
+            ssl->specs.iv_size               = AESGCM_NONCE_SZ;
+            ssl->specs.aead_mac_size         = AES_CCM_8_AUTH_SZ;
+
+            break;
+    #endif
+#endif /* WOLFSSL_TLS13 */
+        }
+    }
+
+    if (ssl->options.cipherSuite0 != ECC_BYTE &&
+            ssl->options.cipherSuite0 != CHACHA_BYTE &&
+            ssl->options.cipherSuite0 != TLS13_BYTE) {   /* normal suites */
+    switch (ssl->options.cipherSuite) {
+
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
+    case SSL_RSA_WITH_RC4_128_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_rc4;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = RC4_KEY_SIZE;
+        ssl->specs.iv_size               = 0;
+        ssl->specs.block_size            = 0;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
+    case TLS_NTRU_RSA_WITH_RC4_128_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_rc4;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ntru_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = RC4_KEY_SIZE;
+        ssl->specs.iv_size               = 0;
+        ssl->specs.block_size            = 0;
+
+        break;
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
+    case SSL_RSA_WITH_RC4_128_MD5 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_rc4;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = md5_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_MD5_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_MD5;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = RC4_KEY_SIZE;
+        ssl->specs.iv_size               = 0;
+        ssl->specs.block_size            = 0;
+
+        break;
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
+    case SSL_RSA_WITH_3DES_EDE_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = DES3_KEY_SIZE;
+        ssl->specs.block_size            = DES_BLOCK_SIZE;
+        ssl->specs.iv_size               = DES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
+    case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ntru_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = DES3_KEY_SIZE;
+        ssl->specs.block_size            = DES_BLOCK_SIZE;
+        ssl->specs.iv_size               = DES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
+    case TLS_RSA_WITH_AES_128_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
+    case TLS_RSA_WITH_AES_128_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_NULL_MD5
+    case TLS_RSA_WITH_NULL_MD5 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = md5_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_MD5_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_MD5;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = 0;
+        ssl->specs.block_size            = 0;
+        ssl->specs.iv_size               = 0;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_NULL_SHA
+    case TLS_RSA_WITH_NULL_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = 0;
+        ssl->specs.block_size            = 0;
+        ssl->specs.iv_size               = 0;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_NULL_SHA256
+    case TLS_RSA_WITH_NULL_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = 0;
+        ssl->specs.block_size            = 0;
+        ssl->specs.iv_size               = 0;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
+    case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ntru_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
+    case TLS_RSA_WITH_AES_256_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
+    case TLS_RSA_WITH_AES_256_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
+    case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ntru_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256
+    case TLS_PSK_WITH_AES_128_GCM_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384
+    case TLS_PSK_WITH_AES_256_GCM_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_DH_anon_WITH_AES_256_GCM_SHA384
+    case TLS_DH_anon_WITH_AES_256_GCM_SHA384:
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+         ssl->options.usingAnon_cipher    = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
+    case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = dhe_psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
+    case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = dhe_psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256
+    case TLS_PSK_WITH_AES_128_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384
+    case TLS_PSK_WITH_AES_256_CBC_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
+    case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = dhe_psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
+    case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = dhe_psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
+    case TLS_PSK_WITH_AES_128_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
+    case TLS_PSK_WITH_AES_256_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_NULL_SHA256
+    case TLS_PSK_WITH_NULL_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = 0;
+        ssl->specs.block_size            = 0;
+        ssl->specs.iv_size               = 0;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_NULL_SHA384
+    case TLS_PSK_WITH_NULL_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = 0;
+        ssl->specs.block_size            = 0;
+        ssl->specs.iv_size               = 0;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_NULL_SHA
+    case TLS_PSK_WITH_NULL_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = 0;
+        ssl->specs.block_size            = 0;
+        ssl->specs.iv_size               = 0;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256
+    case TLS_DHE_PSK_WITH_NULL_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = dhe_psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = 0;
+        ssl->specs.block_size            = 0;
+        ssl->specs.iv_size               = 0;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384
+    case TLS_DHE_PSK_WITH_NULL_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = dhe_psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = 0;
+        ssl->specs.block_size            = 0;
+        ssl->specs.iv_size               = 0;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+    case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+    case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = DES3_KEY_SIZE;
+        ssl->specs.block_size            = DES_BLOCK_SIZE;
+        ssl->specs.iv_size               = DES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+    case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+    case TLS_DHE_RSA_WITH_AES_128_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+    case TLS_DHE_RSA_WITH_AES_256_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_MD5
+    case TLS_RSA_WITH_HC_128_MD5 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_hc128;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = md5_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_MD5_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_MD5;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = HC_128_KEY_SIZE;
+        ssl->specs.block_size            = 0;
+        ssl->specs.iv_size               = HC_128_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_SHA
+        case TLS_RSA_WITH_HC_128_SHA :
+            ssl->specs.bulk_cipher_algorithm = wolfssl_hc128;
+            ssl->specs.cipher_type           = stream;
+            ssl->specs.mac_algorithm         = sha_mac;
+            ssl->specs.kea                   = rsa_kea;
+            ssl->specs.sig_algo              = rsa_sa_algo;
+            ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+            ssl->specs.pad_size              = PAD_SHA;
+            ssl->specs.static_ecdh           = 0;
+            ssl->specs.key_size              = HC_128_KEY_SIZE;
+            ssl->specs.block_size            = 0;
+            ssl->specs.iv_size               = HC_128_IV_SIZE;
+
+            break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA
+    case TLS_RSA_WITH_RABBIT_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_rabbit;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = RABBIT_KEY_SIZE;
+        ssl->specs.block_size            = 0;
+        ssl->specs.iv_size               = RABBIT_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
+    case TLS_RSA_WITH_AES_128_GCM_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384
+    case TLS_RSA_WITH_AES_256_GCM_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
+    case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+    case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
+    case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_camellia;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CAMELLIA_128_KEY_SIZE;
+        ssl->specs.block_size            = CAMELLIA_BLOCK_SIZE;
+        ssl->specs.iv_size               = CAMELLIA_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
+    case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_camellia;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CAMELLIA_256_KEY_SIZE;
+        ssl->specs.block_size            = CAMELLIA_BLOCK_SIZE;
+        ssl->specs.iv_size               = CAMELLIA_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
+    case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_camellia;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CAMELLIA_128_KEY_SIZE;
+        ssl->specs.block_size            = CAMELLIA_BLOCK_SIZE;
+        ssl->specs.iv_size               = CAMELLIA_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
+    case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_camellia;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CAMELLIA_256_KEY_SIZE;
+        ssl->specs.block_size            = CAMELLIA_BLOCK_SIZE;
+        ssl->specs.iv_size               = CAMELLIA_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
+    case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_camellia;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CAMELLIA_128_KEY_SIZE;
+        ssl->specs.block_size            = CAMELLIA_BLOCK_SIZE;
+        ssl->specs.iv_size               = CAMELLIA_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
+    case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_camellia;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CAMELLIA_256_KEY_SIZE;
+        ssl->specs.block_size            = CAMELLIA_BLOCK_SIZE;
+        ssl->specs.iv_size               = CAMELLIA_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+    case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_camellia;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CAMELLIA_128_KEY_SIZE;
+        ssl->specs.block_size            = CAMELLIA_BLOCK_SIZE;
+        ssl->specs.iv_size               = CAMELLIA_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
+    case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_camellia;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CAMELLIA_256_KEY_SIZE;
+        ssl->specs.block_size            = CAMELLIA_BLOCK_SIZE;
+        ssl->specs.iv_size               = CAMELLIA_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA
+    case TLS_DH_anon_WITH_AES_128_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        ssl->options.usingAnon_cipher    = 1;
+        break;
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_IDEA_CBC_SHA
+        case SSL_RSA_WITH_IDEA_CBC_SHA :
+            ssl->specs.bulk_cipher_algorithm = wolfssl_idea;
+            ssl->specs.cipher_type           = block;
+            ssl->specs.mac_algorithm         = sha_mac;
+            ssl->specs.kea                   = rsa_kea;
+            ssl->specs.sig_algo              = rsa_sa_algo;
+            ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+            ssl->specs.pad_size              = PAD_SHA;
+            ssl->specs.static_ecdh           = 0;
+            ssl->specs.key_size              = IDEA_KEY_SIZE;
+            ssl->specs.block_size            = IDEA_BLOCK_SIZE;
+            ssl->specs.iv_size               = IDEA_IV_SIZE;
+
+            break;
+#endif
+
+#ifdef BUILD_WDM_WITH_NULL_SHA256
+        case WDM_WITH_NULL_SHA256 :
+            ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
+            ssl->specs.cipher_type           = stream;
+            ssl->specs.mac_algorithm         = sha256_mac;
+            ssl->specs.kea                   = no_kea;
+            ssl->specs.sig_algo              = anonymous_sa_algo;
+            ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+            ssl->specs.pad_size              = PAD_SHA;
+
+            break;
+#endif
+
+    default:
+        WOLFSSL_MSG("Unsupported cipher suite, SetCipherSpecs");
+        return UNSUPPORTED_SUITE;
+    }  /* switch */
+    }  /* if ECC / Normal suites else */
+
+    /* set TLS if it hasn't been turned off */
+    if (ssl->version.major == 3 && ssl->version.minor >= 1) {
+#ifndef NO_TLS
+        ssl->options.tls = 1;
+    #if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_AEAD_ONLY)
+        ssl->hmac = TLS_hmac;
+    #endif
+        if (ssl->version.minor >= 2) {
+            ssl->options.tls1_1 = 1;
+            if (ssl->version.minor >= 4)
+                ssl->options.tls1_3 = 1;
+        }
+#endif
+    }
+
+#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+    if (IsAtLeastTLSv1_3(ssl->version) || ssl->specs.cipher_type != block)
+       ssl->options.encThenMac = 0;
+#endif
+
+#if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_AEAD_ONLY)
+    if (ssl->options.dtls)
+        ssl->hmac = TLS_hmac;
+#endif
+
+    return 0;
+}
+
+
+enum KeyStuff {
+    MASTER_ROUNDS = 3,
+    PREFIX        = 3,     /* up to three letters for master prefix */
+    KEY_PREFIX    = 9      /* up to 9 prefix letters for key rounds */
+
+
+};
+
+#ifndef NO_OLD_TLS
+/* true or false, zero for error */
+static int SetPrefix(byte* sha_input, int idx)
+{
+    switch (idx) {
+    case 0:
+        XMEMCPY(sha_input, "A", 1);
+        break;
+    case 1:
+        XMEMCPY(sha_input, "BB", 2);
+        break;
+    case 2:
+        XMEMCPY(sha_input, "CCC", 3);
+        break;
+    case 3:
+        XMEMCPY(sha_input, "DDDD", 4);
+        break;
+    case 4:
+        XMEMCPY(sha_input, "EEEEE", 5);
+        break;
+    case 5:
+        XMEMCPY(sha_input, "FFFFFF", 6);
+        break;
+    case 6:
+        XMEMCPY(sha_input, "GGGGGGG", 7);
+        break;
+    case 7:
+        XMEMCPY(sha_input, "HHHHHHHH", 8);
+        break;
+    case 8:
+        XMEMCPY(sha_input, "IIIIIIIII", 9);
+        break;
+    default:
+        WOLFSSL_MSG("Set Prefix error, bad input");
+        return 0;
+    }
+    return 1;
+}
+#endif
+
+
+static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
+                   int side, void* heap, int devId, WC_RNG* rng, int tls13)
+{
+    (void)rng;
+    (void)tls13;
+
+#ifdef BUILD_ARC4
+    if (specs->bulk_cipher_algorithm == wolfssl_rc4) {
+        word32 sz = specs->key_size;
+        if (enc && enc->arc4 == NULL) {
+            enc->arc4 = (Arc4*)XMALLOC(sizeof(Arc4), heap, DYNAMIC_TYPE_CIPHER);
+            if (enc->arc4 == NULL)
+                 return MEMORY_E;
+        }
+        if (dec && dec->arc4 == NULL) {
+            dec->arc4 = (Arc4*)XMALLOC(sizeof(Arc4), heap, DYNAMIC_TYPE_CIPHER);
+            if (dec->arc4 == NULL)
+                return MEMORY_E;
+        }
+
+        if (enc) {
+            if (wc_Arc4Init(enc->arc4, heap, devId) != 0) {
+                WOLFSSL_MSG("Arc4Init failed in SetKeys");
+                return ASYNC_INIT_E;
+            }
+        }
+        if (dec) {
+            if (wc_Arc4Init(dec->arc4, heap, devId) != 0) {
+                WOLFSSL_MSG("Arc4Init failed in SetKeys");
+                return ASYNC_INIT_E;
+            }
+        }
+
+        if (side == WOLFSSL_CLIENT_END) {
+            if (enc)
+                wc_Arc4SetKey(enc->arc4, keys->client_write_key, sz);
+            if (dec)
+                wc_Arc4SetKey(dec->arc4, keys->server_write_key, sz);
+        }
+        else {
+            if (enc)
+                wc_Arc4SetKey(enc->arc4, keys->server_write_key, sz);
+            if (dec)
+                wc_Arc4SetKey(dec->arc4, keys->client_write_key, sz);
+        }
+        if (enc)
+            enc->setup = 1;
+        if (dec)
+            dec->setup = 1;
+    }
+#endif /* BUILD_ARC4 */
+
+
+#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
+    /* Check that the max implicit iv size is suffecient */
+    #if (AEAD_MAX_IMP_SZ < 12) /* CHACHA20_IMP_IV_SZ */
+        #error AEAD_MAX_IMP_SZ is too small for ChaCha20
+    #endif
+    #if (MAX_WRITE_IV_SZ < 12) /* CHACHA20_IMP_IV_SZ */
+        #error MAX_WRITE_IV_SZ is too small for ChaCha20
+    #endif
+
+    if (specs->bulk_cipher_algorithm == wolfssl_chacha) {
+        int chachaRet;
+        if (enc && enc->chacha == NULL)
+            enc->chacha =
+                    (ChaCha*)XMALLOC(sizeof(ChaCha), heap, DYNAMIC_TYPE_CIPHER);
+        if (enc && enc->chacha == NULL)
+            return MEMORY_E;
+        if (dec && dec->chacha == NULL)
+            dec->chacha =
+                    (ChaCha*)XMALLOC(sizeof(ChaCha), heap, DYNAMIC_TYPE_CIPHER);
+        if (dec && dec->chacha == NULL)
+            return MEMORY_E;
+        if (side == WOLFSSL_CLIENT_END) {
+            if (enc) {
+                chachaRet = wc_Chacha_SetKey(enc->chacha, keys->client_write_key,
+                                          specs->key_size);
+                XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV,
+                        CHACHA20_IMP_IV_SZ);
+                if (chachaRet != 0) return chachaRet;
+            }
+            if (dec) {
+                chachaRet = wc_Chacha_SetKey(dec->chacha, keys->server_write_key,
+                                          specs->key_size);
+                XMEMCPY(keys->aead_dec_imp_IV, keys->server_write_IV,
+                        CHACHA20_IMP_IV_SZ);
+                if (chachaRet != 0) return chachaRet;
+            }
+        }
+        else {
+            if (enc) {
+                chachaRet = wc_Chacha_SetKey(enc->chacha, keys->server_write_key,
+                                          specs->key_size);
+                XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV,
+                        CHACHA20_IMP_IV_SZ);
+                if (chachaRet != 0) return chachaRet;
+            }
+            if (dec) {
+                chachaRet = wc_Chacha_SetKey(dec->chacha, keys->client_write_key,
+                                          specs->key_size);
+                XMEMCPY(keys->aead_dec_imp_IV, keys->client_write_IV,
+                        CHACHA20_IMP_IV_SZ);
+                if (chachaRet != 0) return chachaRet;
+            }
+        }
+
+        if (enc)
+            enc->setup = 1;
+        if (dec)
+            dec->setup = 1;
+    }
+#endif /* HAVE_CHACHA && HAVE_POLY1305 */
+
+
+#ifdef HAVE_HC128
+    /* check that buffer sizes are sufficient */
+    #if (MAX_WRITE_IV_SZ < 16) /* HC_128_IV_SIZE */
+        #error MAX_WRITE_IV_SZ too small for HC128
+    #endif
+
+    if (specs->bulk_cipher_algorithm == wolfssl_hc128) {
+        int hcRet;
+        if (enc && enc->hc128 == NULL)
+            enc->hc128 =
+                      (HC128*)XMALLOC(sizeof(HC128), heap, DYNAMIC_TYPE_CIPHER);
+        if (enc && enc->hc128 == NULL)
+            return MEMORY_E;
+        if (dec && dec->hc128 == NULL)
+            dec->hc128 =
+                      (HC128*)XMALLOC(sizeof(HC128), heap, DYNAMIC_TYPE_CIPHER);
+        if (dec && dec->hc128 == NULL)
+            return MEMORY_E;
+        if (side == WOLFSSL_CLIENT_END) {
+            if (enc) {
+                hcRet = wc_Hc128_SetKey(enc->hc128, keys->client_write_key,
+                                     keys->client_write_IV);
+                if (hcRet != 0) return hcRet;
+            }
+            if (dec) {
+                hcRet = wc_Hc128_SetKey(dec->hc128, keys->server_write_key,
+                                     keys->server_write_IV);
+                if (hcRet != 0) return hcRet;
+            }
+        }
+        else {
+            if (enc) {
+                hcRet = wc_Hc128_SetKey(enc->hc128, keys->server_write_key,
+                                     keys->server_write_IV);
+                if (hcRet != 0) return hcRet;
+            }
+            if (dec) {
+                hcRet = wc_Hc128_SetKey(dec->hc128, keys->client_write_key,
+                                     keys->client_write_IV);
+                if (hcRet != 0) return hcRet;
+            }
+        }
+        if (enc)
+            enc->setup = 1;
+        if (dec)
+            dec->setup = 1;
+    }
+#endif /* HAVE_HC128 */
+
+#ifdef BUILD_RABBIT
+    /* check that buffer sizes are sufficient */
+    #if (MAX_WRITE_IV_SZ < 8) /* RABBIT_IV_SIZE */
+        #error MAX_WRITE_IV_SZ too small for RABBIT
+    #endif
+
+    if (specs->bulk_cipher_algorithm == wolfssl_rabbit) {
+        int rabRet;
+        if (enc && enc->rabbit == NULL)
+            enc->rabbit =
+                    (Rabbit*)XMALLOC(sizeof(Rabbit), heap, DYNAMIC_TYPE_CIPHER);
+        if (enc && enc->rabbit == NULL)
+            return MEMORY_E;
+        if (dec && dec->rabbit == NULL)
+            dec->rabbit =
+                    (Rabbit*)XMALLOC(sizeof(Rabbit), heap, DYNAMIC_TYPE_CIPHER);
+        if (dec && dec->rabbit == NULL)
+            return MEMORY_E;
+        if (side == WOLFSSL_CLIENT_END) {
+            if (enc) {
+                rabRet = wc_RabbitSetKey(enc->rabbit, keys->client_write_key,
+                                      keys->client_write_IV);
+                if (rabRet != 0) return rabRet;
+            }
+            if (dec) {
+                rabRet = wc_RabbitSetKey(dec->rabbit, keys->server_write_key,
+                                      keys->server_write_IV);
+                if (rabRet != 0) return rabRet;
+            }
+        }
+        else {
+            if (enc) {
+                rabRet = wc_RabbitSetKey(enc->rabbit, keys->server_write_key,
+                                      keys->server_write_IV);
+                if (rabRet != 0) return rabRet;
+            }
+            if (dec) {
+                rabRet = wc_RabbitSetKey(dec->rabbit, keys->client_write_key,
+                                      keys->client_write_IV);
+                if (rabRet != 0) return rabRet;
+            }
+        }
+        if (enc)
+            enc->setup = 1;
+        if (dec)
+            dec->setup = 1;
+    }
+#endif /* BUILD_RABBIT */
+
+#ifdef BUILD_DES3
+    /* check that buffer sizes are sufficient */
+    #if (MAX_WRITE_IV_SZ < 8) /* DES_IV_SIZE */
+        #error MAX_WRITE_IV_SZ too small for 3DES
+    #endif
+
+    if (specs->bulk_cipher_algorithm == wolfssl_triple_des) {
+        int desRet = 0;
+
+        if (enc) {
+            if (enc->des3 == NULL)
+                enc->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER);
+            if (enc->des3 == NULL)
+                return MEMORY_E;
+            XMEMSET(enc->des3, 0, sizeof(Des3));
+        }
+        if (dec) {
+            if (dec->des3 == NULL)
+                dec->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER);
+            if (dec->des3 == NULL)
+                return MEMORY_E;
+            XMEMSET(dec->des3, 0, sizeof(Des3));
+        }
+
+        if (enc) {
+            if (wc_Des3Init(enc->des3, heap, devId) != 0) {
+                WOLFSSL_MSG("Des3Init failed in SetKeys");
+                return ASYNC_INIT_E;
+            }
+        }
+        if (dec) {
+            if (wc_Des3Init(dec->des3, heap, devId) != 0) {
+                WOLFSSL_MSG("Des3Init failed in SetKeys");
+                return ASYNC_INIT_E;
+            }
+        }
+
+        if (side == WOLFSSL_CLIENT_END) {
+            if (enc) {
+                desRet = wc_Des3_SetKey(enc->des3, keys->client_write_key,
+                                     keys->client_write_IV, DES_ENCRYPTION);
+                if (desRet != 0) return desRet;
+            }
+            if (dec) {
+                desRet = wc_Des3_SetKey(dec->des3, keys->server_write_key,
+                                     keys->server_write_IV, DES_DECRYPTION);
+                if (desRet != 0) return desRet;
+            }
+        }
+        else {
+            if (enc) {
+                desRet = wc_Des3_SetKey(enc->des3, keys->server_write_key,
+                                     keys->server_write_IV, DES_ENCRYPTION);
+                if (desRet != 0) return desRet;
+            }
+            if (dec) {
+                desRet = wc_Des3_SetKey(dec->des3, keys->client_write_key,
+                                     keys->client_write_IV, DES_DECRYPTION);
+                if (desRet != 0) return desRet;
+            }
+        }
+        if (enc)
+            enc->setup = 1;
+        if (dec)
+            dec->setup = 1;
+    }
+#endif /* BUILD_DES3 */
+
+#ifdef BUILD_AES
+    /* check that buffer sizes are sufficient */
+    #if (MAX_WRITE_IV_SZ < 16) /* AES_IV_SIZE */
+        #error MAX_WRITE_IV_SZ too small for AES
+    #endif
+
+    if (specs->bulk_cipher_algorithm == wolfssl_aes) {
+        int aesRet = 0;
+
+        if (enc) {
+            if (enc->aes == NULL)
+                enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER);
+            if (enc->aes == NULL)
+                return MEMORY_E;
+            XMEMSET(enc->aes, 0, sizeof(Aes));
+        }
+        if (dec) {
+            if (dec->aes == NULL)
+                dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER);
+            if (dec->aes == NULL)
+                return MEMORY_E;
+            XMEMSET(dec->aes, 0, sizeof(Aes));
+        }
+        if (enc) {
+            if (wc_AesInit(enc->aes, heap, devId) != 0) {
+                WOLFSSL_MSG("AesInit failed in SetKeys");
+                return ASYNC_INIT_E;
+            }
+        }
+        if (dec) {
+            if (wc_AesInit(dec->aes, heap, devId) != 0) {
+                WOLFSSL_MSG("AesInit failed in SetKeys");
+                return ASYNC_INIT_E;
+            }
+        }
+
+        if (side == WOLFSSL_CLIENT_END) {
+            if (enc) {
+                aesRet = wc_AesSetKey(enc->aes, keys->client_write_key,
+                                   specs->key_size, keys->client_write_IV,
+                                   AES_ENCRYPTION);
+                if (aesRet != 0) return aesRet;
+            }
+            if (dec) {
+                aesRet = wc_AesSetKey(dec->aes, keys->server_write_key,
+                                   specs->key_size, keys->server_write_IV,
+                                   AES_DECRYPTION);
+                if (aesRet != 0) return aesRet;
+            }
+        }
+        else {
+            if (enc) {
+                aesRet = wc_AesSetKey(enc->aes, keys->server_write_key,
+                                   specs->key_size, keys->server_write_IV,
+                                   AES_ENCRYPTION);
+                if (aesRet != 0) return aesRet;
+            }
+            if (dec) {
+                aesRet = wc_AesSetKey(dec->aes, keys->client_write_key,
+                                   specs->key_size, keys->client_write_IV,
+                                   AES_DECRYPTION);
+                if (aesRet != 0) return aesRet;
+            }
+        }
+        if (enc)
+            enc->setup = 1;
+        if (dec)
+            dec->setup = 1;
+    }
+#endif /* BUILD_AES */
+
+#ifdef BUILD_AESGCM
+    /* check that buffer sizes are sufficient */
+    #if (AEAD_MAX_IMP_SZ < 4) /* AESGCM_IMP_IV_SZ */
+        #error AEAD_MAX_IMP_SZ too small for AESGCM
+    #endif
+    #if (AEAD_MAX_EXP_SZ < 8) /* AESGCM_EXP_IV_SZ */
+        #error AEAD_MAX_EXP_SZ too small for AESGCM
+    #endif
+    #if (MAX_WRITE_IV_SZ < 4) /* AESGCM_IMP_IV_SZ */
+        #error MAX_WRITE_IV_SZ too small for AESGCM
+    #endif
+
+    if (specs->bulk_cipher_algorithm == wolfssl_aes_gcm) {
+        int gcmRet;
+
+        if (enc) {
+            if (enc->aes == NULL)
+                enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER);
+            if (enc->aes == NULL)
+                return MEMORY_E;
+            XMEMSET(enc->aes, 0, sizeof(Aes));
+        }
+        if (dec) {
+            if (dec->aes == NULL)
+                dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER);
+            if (dec->aes == NULL)
+                return MEMORY_E;
+            XMEMSET(dec->aes, 0, sizeof(Aes));
+        }
+
+        if (enc) {
+            if (wc_AesInit(enc->aes, heap, devId) != 0) {
+                WOLFSSL_MSG("AesInit failed in SetKeys");
+                return ASYNC_INIT_E;
+            }
+        }
+        if (dec) {
+            if (wc_AesInit(dec->aes, heap, devId) != 0) {
+                WOLFSSL_MSG("AesInit failed in SetKeys");
+                return ASYNC_INIT_E;
+            }
+        }
+
+        if (side == WOLFSSL_CLIENT_END) {
+            if (enc) {
+                gcmRet = wc_AesGcmSetKey(enc->aes, keys->client_write_key,
+                                      specs->key_size);
+                if (gcmRet != 0) return gcmRet;
+                XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV,
+                        AEAD_MAX_IMP_SZ);
+#if !defined(NO_PUBLIC_GCM_SET_IV) && \
+    ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \
+    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)))
+                if (!tls13) {
+                    gcmRet = wc_AesGcmSetIV(enc->aes, AESGCM_NONCE_SZ,
+                            keys->client_write_IV, AESGCM_IMP_IV_SZ, rng);
+                    if (gcmRet != 0) return gcmRet;
+                }
+#endif
+            }
+            if (dec) {
+                gcmRet = wc_AesGcmSetKey(dec->aes, keys->server_write_key,
+                                      specs->key_size);
+                if (gcmRet != 0) return gcmRet;
+                XMEMCPY(keys->aead_dec_imp_IV, keys->server_write_IV,
+                        AEAD_MAX_IMP_SZ);
+            }
+        }
+        else {
+            if (enc) {
+                gcmRet = wc_AesGcmSetKey(enc->aes, keys->server_write_key,
+                                      specs->key_size);
+                if (gcmRet != 0) return gcmRet;
+                XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV,
+                        AEAD_MAX_IMP_SZ);
+#if !defined(NO_PUBLIC_GCM_SET_IV) && \
+    ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \
+    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)))
+                if (!tls13) {
+                    gcmRet = wc_AesGcmSetIV(enc->aes, AESGCM_NONCE_SZ,
+                            keys->server_write_IV, AESGCM_IMP_IV_SZ, rng);
+                    if (gcmRet != 0) return gcmRet;
+                }
+#endif
+            }
+            if (dec) {
+                gcmRet = wc_AesGcmSetKey(dec->aes, keys->client_write_key,
+                                      specs->key_size);
+                if (gcmRet != 0) return gcmRet;
+                XMEMCPY(keys->aead_dec_imp_IV, keys->client_write_IV,
+                        AEAD_MAX_IMP_SZ);
+            }
+        }
+        if (enc)
+            enc->setup = 1;
+        if (dec)
+            dec->setup = 1;
+    }
+#endif /* BUILD_AESGCM */
+
+#ifdef HAVE_AESCCM
+    /* check that buffer sizes are sufficient (CCM is same size as GCM) */
+    #if (AEAD_MAX_IMP_SZ < 4) /* AESGCM_IMP_IV_SZ */
+        #error AEAD_MAX_IMP_SZ too small for AESCCM
+    #endif
+    #if (AEAD_MAX_EXP_SZ < 8) /* AESGCM_EXP_IV_SZ */
+        #error AEAD_MAX_EXP_SZ too small for AESCCM
+    #endif
+    #if (MAX_WRITE_IV_SZ < 4) /* AESGCM_IMP_IV_SZ */
+        #error MAX_WRITE_IV_SZ too small for AESCCM
+    #endif
+
+    if (specs->bulk_cipher_algorithm == wolfssl_aes_ccm) {
+        int CcmRet;
+
+        if (enc) {
+            if (enc->aes == NULL)
+                enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER);
+            if (enc->aes == NULL)
+                return MEMORY_E;
+            XMEMSET(enc->aes, 0, sizeof(Aes));
+        }
+        if (dec) {
+            if (dec->aes == NULL)
+                dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER);
+            if (dec->aes == NULL)
+                return MEMORY_E;
+            XMEMSET(dec->aes, 0, sizeof(Aes));
+        }
+
+        if (enc) {
+            if (wc_AesInit(enc->aes, heap, devId) != 0) {
+                WOLFSSL_MSG("AesInit failed in SetKeys");
+                return ASYNC_INIT_E;
+            }
+        }
+        if (dec) {
+            if (wc_AesInit(dec->aes, heap, devId) != 0) {
+                WOLFSSL_MSG("AesInit failed in SetKeys");
+                return ASYNC_INIT_E;
+            }
+        }
+
+        if (side == WOLFSSL_CLIENT_END) {
+            if (enc) {
+                CcmRet = wc_AesCcmSetKey(enc->aes, keys->client_write_key,
+                                         specs->key_size);
+                if (CcmRet != 0) {
+                    return CcmRet;
+                }
+                XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV,
+                        AEAD_MAX_IMP_SZ);
+#if !defined(NO_PUBLIC_CCM_SET_NONCE) && \
+    ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \
+    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)))
+                if (!tls13) {
+                    CcmRet = wc_AesCcmSetNonce(enc->aes, keys->client_write_IV,
+                            AEAD_MAX_IMP_SZ);
+                    if (CcmRet != 0) return CcmRet;
+                }
+#endif
+            }
+            if (dec) {
+                CcmRet = wc_AesCcmSetKey(dec->aes, keys->server_write_key,
+                                         specs->key_size);
+                if (CcmRet != 0) {
+                    return CcmRet;
+                }
+                XMEMCPY(keys->aead_dec_imp_IV, keys->server_write_IV,
+                        AEAD_MAX_IMP_SZ);
+            }
+        }
+        else {
+            if (enc) {
+                CcmRet = wc_AesCcmSetKey(enc->aes, keys->server_write_key,
+                                         specs->key_size);
+                if (CcmRet != 0) {
+                    return CcmRet;
+                }
+                XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV,
+                        AEAD_MAX_IMP_SZ);
+#if !defined(NO_PUBLIC_CCM_SET_NONCE) && \
+    ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \
+    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)))
+                if (!tls13) {
+                    CcmRet = wc_AesCcmSetNonce(enc->aes, keys->server_write_IV,
+                            AEAD_MAX_IMP_SZ);
+                    if (CcmRet != 0) return CcmRet;
+                }
+#endif
+            }
+            if (dec) {
+                CcmRet = wc_AesCcmSetKey(dec->aes, keys->client_write_key,
+                                         specs->key_size);
+                if (CcmRet != 0) {
+                    return CcmRet;
+                }
+                XMEMCPY(keys->aead_dec_imp_IV, keys->client_write_IV,
+                        AEAD_MAX_IMP_SZ);
+            }
+        }
+        if (enc)
+            enc->setup = 1;
+        if (dec)
+            dec->setup = 1;
+    }
+#endif /* HAVE_AESCCM */
+
+#ifdef HAVE_CAMELLIA
+    /* check that buffer sizes are sufficient */
+    #if (MAX_WRITE_IV_SZ < 16) /* CAMELLIA_IV_SIZE */
+        #error MAX_WRITE_IV_SZ too small for CAMELLIA
+    #endif
+
+    if (specs->bulk_cipher_algorithm == wolfssl_camellia) {
+        int camRet;
+
+        if (enc && enc->cam == NULL)
+            enc->cam =
+                (Camellia*)XMALLOC(sizeof(Camellia), heap, DYNAMIC_TYPE_CIPHER);
+        if (enc && enc->cam == NULL)
+            return MEMORY_E;
+
+        if (dec && dec->cam == NULL)
+            dec->cam =
+                (Camellia*)XMALLOC(sizeof(Camellia), heap, DYNAMIC_TYPE_CIPHER);
+        if (dec && dec->cam == NULL)
+            return MEMORY_E;
+
+        if (side == WOLFSSL_CLIENT_END) {
+            if (enc) {
+                camRet = wc_CamelliaSetKey(enc->cam, keys->client_write_key,
+                                        specs->key_size, keys->client_write_IV);
+                if (camRet != 0) return camRet;
+            }
+            if (dec) {
+                camRet = wc_CamelliaSetKey(dec->cam, keys->server_write_key,
+                                        specs->key_size, keys->server_write_IV);
+                if (camRet != 0) return camRet;
+            }
+        }
+        else {
+            if (enc) {
+                camRet = wc_CamelliaSetKey(enc->cam, keys->server_write_key,
+                                        specs->key_size, keys->server_write_IV);
+                if (camRet != 0) return camRet;
+            }
+            if (dec) {
+                camRet = wc_CamelliaSetKey(dec->cam, keys->client_write_key,
+                                        specs->key_size, keys->client_write_IV);
+                if (camRet != 0) return camRet;
+            }
+        }
+        if (enc)
+            enc->setup = 1;
+        if (dec)
+            dec->setup = 1;
+    }
+#endif /* HAVE_CAMELLIA */
+
+#ifdef HAVE_IDEA
+    /* check that buffer sizes are sufficient */
+    #if (MAX_WRITE_IV_SZ < 8) /* IDEA_IV_SIZE */
+        #error MAX_WRITE_IV_SZ too small for IDEA
+    #endif
+
+    if (specs->bulk_cipher_algorithm == wolfssl_idea) {
+        int ideaRet;
+
+        if (enc && enc->idea == NULL)
+            enc->idea = (Idea*)XMALLOC(sizeof(Idea), heap, DYNAMIC_TYPE_CIPHER);
+        if (enc && enc->idea == NULL)
+            return MEMORY_E;
+
+        if (dec && dec->idea == NULL)
+            dec->idea = (Idea*)XMALLOC(sizeof(Idea), heap, DYNAMIC_TYPE_CIPHER);
+        if (dec && dec->idea == NULL)
+            return MEMORY_E;
+
+        if (side == WOLFSSL_CLIENT_END) {
+            if (enc) {
+                ideaRet = wc_IdeaSetKey(enc->idea, keys->client_write_key,
+                                        specs->key_size, keys->client_write_IV,
+                                        IDEA_ENCRYPTION);
+                if (ideaRet != 0) return ideaRet;
+            }
+            if (dec) {
+                ideaRet = wc_IdeaSetKey(dec->idea, keys->server_write_key,
+                                        specs->key_size, keys->server_write_IV,
+                                        IDEA_DECRYPTION);
+                if (ideaRet != 0) return ideaRet;
+            }
+        }
+        else {
+            if (enc) {
+                ideaRet = wc_IdeaSetKey(enc->idea, keys->server_write_key,
+                                        specs->key_size, keys->server_write_IV,
+                                        IDEA_ENCRYPTION);
+                if (ideaRet != 0) return ideaRet;
+            }
+            if (dec) {
+                ideaRet = wc_IdeaSetKey(dec->idea, keys->client_write_key,
+                                        specs->key_size, keys->client_write_IV,
+                                        IDEA_DECRYPTION);
+                if (ideaRet != 0) return ideaRet;
+            }
+        }
+        if (enc)
+            enc->setup = 1;
+        if (dec)
+            dec->setup = 1;
+    }
+#endif /* HAVE_IDEA */
+
+#ifdef HAVE_NULL_CIPHER
+    if (specs->bulk_cipher_algorithm == wolfssl_cipher_null) {
+    #ifdef WOLFSSL_TLS13
+        if (tls13) {
+            int hmacRet;
+            int hashType = WC_HASH_TYPE_NONE;
+
+            switch (specs->mac_algorithm) {
+                case sha256_mac:
+                    hashType = WC_SHA256;
+                    break;
+                case sha384_mac:
+                    hashType = WC_SHA384;
+                    break;
+                default:
+                    break;
+            }
+
+            if (enc && enc->hmac == NULL) {
+                enc->hmac = (Hmac*)XMALLOC(sizeof(Hmac), heap,
+                                                           DYNAMIC_TYPE_CIPHER);
+                if (enc->hmac == NULL)
+                    return MEMORY_E;
+            }
+
+            if (dec && dec->hmac == NULL) {
+                dec->hmac = (Hmac*)XMALLOC(sizeof(Hmac), heap,
+                                                           DYNAMIC_TYPE_CIPHER);
+                if (dec->hmac == NULL)
+                    return MEMORY_E;
+            }
+
+            if (enc) {
+                if (wc_HmacInit(enc->hmac, heap, devId) != 0) {
+                    WOLFSSL_MSG("HmacInit failed in SetKeys");
+                    return ASYNC_INIT_E;
+                }
+            }
+            if (dec) {
+                if (wc_HmacInit(dec->hmac, heap, devId) != 0) {
+                    WOLFSSL_MSG("HmacInit failed in SetKeys");
+                    return ASYNC_INIT_E;
+                }
+            }
+
+            if (side == WOLFSSL_CLIENT_END) {
+                if (enc) {
+                    hmacRet = wc_HmacSetKey(enc->hmac, hashType,
+                                       keys->client_write_key, specs->key_size);
+                    if (hmacRet != 0) return hmacRet;
+                }
+                if (dec) {
+                    hmacRet = wc_HmacSetKey(dec->hmac, hashType,
+                                       keys->server_write_key, specs->key_size);
+                    if (hmacRet != 0) return hmacRet;
+                }
+            }
+            else {
+                if (enc) {
+                    hmacRet = wc_HmacSetKey(enc->hmac, hashType,
+                                       keys->server_write_key, specs->key_size);
+                    if (hmacRet != 0) return hmacRet;
+                }
+                if (dec) {
+                    hmacRet = wc_HmacSetKey(dec->hmac, hashType,
+                                       keys->client_write_key, specs->key_size);
+                    if (hmacRet != 0) return hmacRet;
+                }
+            }
+        }
+    #endif
+        if (enc)
+            enc->setup = 1;
+        if (dec)
+            dec->setup = 1;
+    }
+#endif
+
+    if (enc) {
+        keys->sequence_number_hi      = 0;
+        keys->sequence_number_lo      = 0;
+    }
+    if (dec) {
+        keys->peer_sequence_number_hi = 0;
+        keys->peer_sequence_number_lo = 0;
+    }
+    (void)side;
+    (void)heap;
+    (void)enc;
+    (void)dec;
+    (void)specs;
+    (void)devId;
+
+    return 0;
+}
+
+
+#ifdef HAVE_ONE_TIME_AUTH
+/* set one time authentication keys */
+static int SetAuthKeys(OneTimeAuth* authentication, Keys* keys,
+                       CipherSpecs* specs, void* heap, int devId)
+{
+
+#ifdef HAVE_POLY1305
+        /* set up memory space for poly1305 */
+        if (authentication && authentication->poly1305 == NULL)
+            authentication->poly1305 =
+                (Poly1305*)XMALLOC(sizeof(Poly1305), heap, DYNAMIC_TYPE_CIPHER);
+        if (authentication && authentication->poly1305 == NULL)
+            return MEMORY_E;
+        if (authentication)
+            authentication->setup = 1;
+#endif
+        (void)authentication;
+        (void)heap;
+        (void)keys;
+        (void)specs;
+        (void)devId;
+
+        return 0;
+}
+#endif /* HAVE_ONE_TIME_AUTH */
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+/* function name is for cache_status++
+ * This function was added because of error incrementing enum type when
+ * compiling with a C++ compiler.
+ */
+static void CacheStatusPP(SecureRenegotiation* cache)
+{
+    switch (cache->cache_status) {
+        case SCR_CACHE_NULL:
+            cache->cache_status = SCR_CACHE_NEEDED;
+            break;
+
+        case SCR_CACHE_NEEDED:
+            cache->cache_status = SCR_CACHE_COPY;
+            break;
+
+        case SCR_CACHE_COPY:
+            cache->cache_status = SCR_CACHE_PARTIAL;
+            break;
+
+        case SCR_CACHE_PARTIAL:
+            cache->cache_status = SCR_CACHE_COMPLETE;
+            break;
+
+        case SCR_CACHE_COMPLETE:
+            WOLFSSL_MSG("SCR Cache state Complete");
+            break;
+
+        default:
+            WOLFSSL_MSG("Unknown cache state!!");
+    }
+}
+#endif /* HAVE_SECURE_RENEGOTIATION */
+
+
+/* Set wc_encrypt/wc_decrypt or both sides of key setup
+ * note: use wc_encrypt to avoid shadowing global encrypt
+ * declared in unistd.h
+ */
+int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side)
+{
+    int ret, copy = 0;
+    Ciphers* wc_encrypt = NULL;
+    Ciphers* wc_decrypt = NULL;
+    Keys*    keys    = &ssl->keys;
+
+    (void)copy;
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+    if (ssl->secure_renegotiation && ssl->secure_renegotiation->cache_status) {
+        keys = &ssl->secure_renegotiation->tmp_keys;
+        copy = 1;
+    }
+#endif /* HAVE_SECURE_RENEGOTIATION */
+
+    switch (side) {
+        case ENCRYPT_SIDE_ONLY:
+#ifdef WOLFSSL_DEBUG_TLS
+            WOLFSSL_MSG("Provisioning ENCRYPT key");
+            if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                WOLFSSL_BUFFER(ssl->keys.client_write_key, ssl->specs.key_size);
+            }
+            else {
+                WOLFSSL_BUFFER(ssl->keys.server_write_key, ssl->specs.key_size);
+            }
+#endif
+            wc_encrypt = &ssl->encrypt;
+            break;
+
+        case DECRYPT_SIDE_ONLY:
+#ifdef WOLFSSL_DEBUG_TLS
+            WOLFSSL_MSG("Provisioning DECRYPT key");
+            if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                WOLFSSL_BUFFER(ssl->keys.server_write_key, ssl->specs.key_size);
+            }
+            else {
+                WOLFSSL_BUFFER(ssl->keys.client_write_key, ssl->specs.key_size);
+            }
+#endif
+            wc_decrypt = &ssl->decrypt;
+            break;
+
+        case ENCRYPT_AND_DECRYPT_SIDE:
+#ifdef WOLFSSL_DEBUG_TLS
+            WOLFSSL_MSG("Provisioning ENCRYPT key");
+            if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                WOLFSSL_BUFFER(ssl->keys.client_write_key, ssl->specs.key_size);
+            }
+            else {
+                WOLFSSL_BUFFER(ssl->keys.server_write_key, ssl->specs.key_size);
+            }
+            WOLFSSL_MSG("Provisioning DECRYPT key");
+            if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                WOLFSSL_BUFFER(ssl->keys.server_write_key, ssl->specs.key_size);
+            }
+            else {
+                WOLFSSL_BUFFER(ssl->keys.client_write_key, ssl->specs.key_size);
+            }
+#endif
+            wc_encrypt = &ssl->encrypt;
+            wc_decrypt = &ssl->decrypt;
+            break;
+
+        default:
+            return BAD_FUNC_ARG;
+    }
+
+#ifdef HAVE_ONE_TIME_AUTH
+    if (!ssl->auth.setup && ssl->specs.bulk_cipher_algorithm == wolfssl_chacha){
+        ret = SetAuthKeys(&ssl->auth, keys, &ssl->specs, ssl->heap, ssl->devId);
+        if (ret != 0)
+           return ret;
+    }
+#endif
+
+#if defined(WOLFSSL_RENESAS_TSIP_TLS) && \
+    !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION)
+    /* check if keys for TSIP has been created */
+    if (tsip_useable(ssl) == 1)
+        ret = 0;
+    else
+#endif
+    ret = SetKeys(wc_encrypt, wc_decrypt, keys, &ssl->specs, ssl->options.side,
+                  ssl->heap, ssl->devId, ssl->rng, ssl->options.tls1_3);
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+    if (copy) {
+        int clientCopy = 0;
+
+        if (ssl->options.side == WOLFSSL_CLIENT_END && wc_encrypt)
+            clientCopy = 1;
+        else if (ssl->options.side == WOLFSSL_SERVER_END && wc_decrypt)
+            clientCopy = 1;
+
+        if (clientCopy) {
+    #ifndef WOLFSSL_AEAD_ONLY
+            XMEMCPY(ssl->keys.client_write_MAC_secret,
+                    keys->client_write_MAC_secret, WC_MAX_DIGEST_SIZE);
+    #endif
+            XMEMCPY(ssl->keys.client_write_key,
+                    keys->client_write_key, AES_256_KEY_SIZE);
+            XMEMCPY(ssl->keys.client_write_IV,
+                    keys->client_write_IV, MAX_WRITE_IV_SZ);
+        } else {
+    #ifndef WOLFSSL_AEAD_ONLY
+            XMEMCPY(ssl->keys.server_write_MAC_secret,
+                    keys->server_write_MAC_secret, WC_MAX_DIGEST_SIZE);
+    #endif
+            XMEMCPY(ssl->keys.server_write_key,
+                    keys->server_write_key, AES_256_KEY_SIZE);
+            XMEMCPY(ssl->keys.server_write_IV,
+                    keys->server_write_IV, MAX_WRITE_IV_SZ);
+        }
+        if (wc_encrypt) {
+            ssl->keys.sequence_number_hi = keys->sequence_number_hi;
+            ssl->keys.sequence_number_lo = keys->sequence_number_lo;
+            #ifdef HAVE_AEAD
+                if (ssl->specs.cipher_type == aead) {
+                    /* Initialize the AES-GCM/CCM explicit IV to a zero. */
+                    XMEMCPY(ssl->keys.aead_exp_IV, keys->aead_exp_IV,
+                            AEAD_MAX_EXP_SZ);
+
+                    /* Initialize encrypt implicit IV by encrypt side */
+                    if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                        XMEMCPY(ssl->keys.aead_enc_imp_IV,
+                                keys->client_write_IV, AEAD_MAX_IMP_SZ);
+                    } else {
+                        XMEMCPY(ssl->keys.aead_enc_imp_IV,
+                                keys->server_write_IV, AEAD_MAX_IMP_SZ);
+                    }
+                }
+            #endif
+        }
+        if (wc_decrypt) {
+            ssl->keys.peer_sequence_number_hi = keys->peer_sequence_number_hi;
+            ssl->keys.peer_sequence_number_lo = keys->peer_sequence_number_lo;
+            #ifdef HAVE_AEAD
+                if (ssl->specs.cipher_type == aead) {
+                    /* Initialize decrypt implicit IV by decrypt side */
+                    if (ssl->options.side == WOLFSSL_SERVER_END) {
+                        XMEMCPY(ssl->keys.aead_dec_imp_IV,
+                                keys->client_write_IV, AEAD_MAX_IMP_SZ);
+                    } else {
+                        XMEMCPY(ssl->keys.aead_dec_imp_IV,
+                                keys->server_write_IV, AEAD_MAX_IMP_SZ);
+                    }
+                }
+            #endif
+        }
+        CacheStatusPP(ssl->secure_renegotiation);
+    }
+#endif /* HAVE_SECURE_RENEGOTIATION */
+
+    return ret;
+}
+
+
+/* TLS can call too */
+int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side)
+{
+    int sz, i = 0;
+    Keys* keys = &ssl->keys;
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+    if (ssl->secure_renegotiation && ssl->secure_renegotiation->cache_status ==
+                                                            SCR_CACHE_NEEDED) {
+        keys = &ssl->secure_renegotiation->tmp_keys;
+        CacheStatusPP(ssl->secure_renegotiation);
+    }
+#endif /* HAVE_SECURE_RENEGOTIATION */
+
+#ifdef WOLFSSL_MULTICAST
+    if (ssl->options.haveMcast) {
+        /* Use the same keys for encrypt and decrypt. */
+        if (ssl->specs.cipher_type != aead) {
+            sz = ssl->specs.hash_size;
+    #ifndef WOLFSSL_AEAD_ONLY
+            XMEMCPY(keys->client_write_MAC_secret,&keyData[i], sz);
+            XMEMCPY(keys->server_write_MAC_secret,&keyData[i], sz);
+    #endif
+            i += sz;
+        }
+        sz = ssl->specs.key_size;
+        XMEMCPY(keys->client_write_key, &keyData[i], sz);
+        XMEMCPY(keys->server_write_key, &keyData[i], sz);
+        i += sz;
+
+        sz = ssl->specs.iv_size;
+        XMEMCPY(keys->client_write_IV, &keyData[i], sz);
+        XMEMCPY(keys->server_write_IV, &keyData[i], sz);
+
+#ifdef HAVE_AEAD
+        if (ssl->specs.cipher_type == aead) {
+            /* Initialize the AES-GCM/CCM explicit IV to a zero. */
+            XMEMSET(keys->aead_exp_IV, 0, AEAD_MAX_EXP_SZ);
+        }
+#endif /* HAVE_AEAD */
+
+        return 0;
+    }
+#endif /* WOLFSSL_MULTICAST */
+
+    if (ssl->specs.cipher_type != aead) {
+        sz = ssl->specs.hash_size;
+        if (side & PROVISION_CLIENT) {
+    #ifndef WOLFSSL_AEAD_ONLY
+            XMEMCPY(keys->client_write_MAC_secret,&keyData[i], sz);
+    #endif
+            i += sz;
+        }
+        if (side & PROVISION_SERVER) {
+    #ifndef WOLFSSL_AEAD_ONLY
+            XMEMCPY(keys->server_write_MAC_secret,&keyData[i], sz);
+    #endif
+            i += sz;
+        }
+    }
+    sz = ssl->specs.key_size;
+    if (side & PROVISION_CLIENT) {
+        XMEMCPY(keys->client_write_key, &keyData[i], sz);
+        i += sz;
+    }
+    if (side & PROVISION_SERVER) {
+        XMEMCPY(keys->server_write_key, &keyData[i], sz);
+        i += sz;
+    }
+
+    sz = ssl->specs.iv_size;
+    if (side & PROVISION_CLIENT) {
+        XMEMCPY(keys->client_write_IV, &keyData[i], sz);
+        i += sz;
+    }
+    if (side & PROVISION_SERVER)
+        XMEMCPY(keys->server_write_IV, &keyData[i], sz);
+
+#ifdef HAVE_AEAD
+    if (ssl->specs.cipher_type == aead) {
+        /* Initialize the AES-GCM/CCM explicit IV to a zero. */
+        XMEMSET(keys->aead_exp_IV, 0, AEAD_MAX_EXP_SZ);
+    }
+#endif
+
+    return 0;
+}
+
+#ifndef NO_OLD_TLS
+int DeriveKeys(WOLFSSL* ssl)
+{
+    int    length = 2 * ssl->specs.hash_size +
+                    2 * ssl->specs.key_size  +
+                    2 * ssl->specs.iv_size;
+    int    rounds = (length + WC_MD5_DIGEST_SIZE - 1 ) / WC_MD5_DIGEST_SIZE, i;
+    int    ret = 0;
+
+#ifdef WOLFSSL_SMALL_STACK
+    byte*  shaOutput;
+    byte*  md5Input;
+    byte*  shaInput;
+    byte*  keyData;
+    wc_Md5* md5;
+    wc_Sha* sha;
+#else
+    byte   shaOutput[WC_SHA_DIGEST_SIZE];
+    byte   md5Input[SECRET_LEN + WC_SHA_DIGEST_SIZE];
+    byte   shaInput[KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN];
+    byte   keyData[KEY_PREFIX * WC_MD5_DIGEST_SIZE];
+    wc_Md5 md5[1];
+    wc_Sha sha[1];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+    shaOutput = (byte*)XMALLOC(WC_SHA_DIGEST_SIZE,
+                                            NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    md5Input  = (byte*)XMALLOC(SECRET_LEN + WC_SHA_DIGEST_SIZE,
+                                            NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    shaInput  = (byte*)XMALLOC(KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN,
+                                            NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    keyData   = (byte*)XMALLOC(KEY_PREFIX * WC_MD5_DIGEST_SIZE,
+                                            NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    md5       =  (wc_Md5*)XMALLOC(sizeof(wc_Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    sha       =  (wc_Sha*)XMALLOC(sizeof(wc_Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+    if (shaOutput == NULL || md5Input == NULL || shaInput == NULL ||
+        keyData   == NULL || md5      == NULL || sha      == NULL) {
+        if (shaOutput) XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (md5Input)  XFREE(md5Input,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (shaInput)  XFREE(shaInput,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (keyData)   XFREE(keyData,   NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (md5)       XFREE(md5,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (sha)       XFREE(sha,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+        return MEMORY_E;
+    }
+#endif
+
+    ret = wc_InitMd5(md5);
+    if (ret == 0) {
+        ret = wc_InitSha(sha);
+    }
+    if (ret == 0) {
+        XMEMCPY(md5Input, ssl->arrays->masterSecret, SECRET_LEN);
+
+        for (i = 0; i < rounds; ++i) {
+            int j   = i + 1;
+            int idx = j;
+
+            if (!SetPrefix(shaInput, i)) {
+                ret = PREFIX_ERROR;
+                break;
+            }
+
+            XMEMCPY(shaInput + idx, ssl->arrays->masterSecret, SECRET_LEN);
+            idx += SECRET_LEN;
+            XMEMCPY(shaInput + idx, ssl->arrays->serverRandom, RAN_LEN);
+            idx += RAN_LEN;
+            XMEMCPY(shaInput + idx, ssl->arrays->clientRandom, RAN_LEN);
+            if (ret == 0) {
+                ret = wc_ShaUpdate(sha, shaInput,
+                    (KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN) - KEY_PREFIX + j);
+            }
+            if (ret == 0) {
+                ret = wc_ShaFinal(sha, shaOutput);
+            }
+
+            XMEMCPY(md5Input + SECRET_LEN, shaOutput, WC_SHA_DIGEST_SIZE);
+            if (ret == 0) {
+                ret = wc_Md5Update(md5, md5Input, SECRET_LEN + WC_SHA_DIGEST_SIZE);
+            }
+            if (ret == 0) {
+                ret = wc_Md5Final(md5, keyData + i * WC_MD5_DIGEST_SIZE);
+            }
+        }
+
+        if (ret == 0)
+            ret = StoreKeys(ssl, keyData, PROVISION_CLIENT_SERVER);
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(md5Input,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(shaInput,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(keyData,   NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(md5,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(sha,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return ret;
+}
+
+
+static int CleanPreMaster(WOLFSSL* ssl)
+{
+    int i, ret, sz = ssl->arrays->preMasterSz;
+
+    for (i = 0; i < sz; i++)
+        ssl->arrays->preMasterSecret[i] = 0;
+
+    ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->preMasterSecret, sz);
+    if (ret != 0)
+        return ret;
+
+    for (i = 0; i < sz; i++)
+        ssl->arrays->preMasterSecret[i] = 0;
+
+    XFREE(ssl->arrays->preMasterSecret, ssl->heap, DYNAMIC_TYPE_SECRET);
+    ssl->arrays->preMasterSecret = NULL;
+    ssl->arrays->preMasterSz = 0;
+
+    return 0;
+}
+
+
+/* Create and store the master secret see page 32, 6.1 */
+static int MakeSslMasterSecret(WOLFSSL* ssl)
+{
+    int    i, ret;
+    word32 idx;
+    word32 pmsSz = ssl->arrays->preMasterSz;
+
+#ifdef WOLFSSL_SMALL_STACK
+    byte*  shaOutput;
+    byte*  md5Input;
+    byte*  shaInput;
+    wc_Md5* md5;
+    wc_Sha* sha;
+#else
+    byte   shaOutput[WC_SHA_DIGEST_SIZE];
+    byte   md5Input[ENCRYPT_LEN + WC_SHA_DIGEST_SIZE];
+    byte   shaInput[PREFIX + ENCRYPT_LEN + 2 * RAN_LEN];
+    wc_Md5 md5[1];
+    wc_Sha sha[1];
+#endif
+
+#ifdef SHOW_SECRETS
+    {
+        word32 j;
+        printf("pre master secret: ");
+        for (j = 0; j < pmsSz; j++)
+            printf("%02x", ssl->arrays->preMasterSecret[j]);
+        printf("\n");
+    }
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+    shaOutput = (byte*)XMALLOC(WC_SHA_DIGEST_SIZE,
+                                            NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    md5Input  = (byte*)XMALLOC(ENCRYPT_LEN + WC_SHA_DIGEST_SIZE,
+                                            NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    shaInput  = (byte*)XMALLOC(PREFIX + ENCRYPT_LEN + 2 * RAN_LEN,
+                                            NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    md5       =  (wc_Md5*)XMALLOC(sizeof(wc_Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    sha       =  (wc_Sha*)XMALLOC(sizeof(wc_Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+    if (shaOutput == NULL || md5Input == NULL || shaInput == NULL ||
+                             md5      == NULL || sha      == NULL) {
+        if (shaOutput) XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (md5Input)  XFREE(md5Input,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (shaInput)  XFREE(shaInput,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (md5)       XFREE(md5,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (sha)       XFREE(sha,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+        return MEMORY_E;
+    }
+#endif
+
+    ret = wc_InitMd5(md5);
+    if (ret == 0) {
+        ret = wc_InitSha(sha);
+    }
+    if (ret == 0) {
+        XMEMCPY(md5Input, ssl->arrays->preMasterSecret, pmsSz);
+
+        for (i = 0; i < MASTER_ROUNDS; ++i) {
+            byte prefix[KEY_PREFIX];      /* only need PREFIX bytes but static */
+            if (!SetPrefix(prefix, i)) {  /* analysis thinks will overrun      */
+                ret = PREFIX_ERROR;
+                break;
+            }
+
+            idx = 0;
+            XMEMCPY(shaInput, prefix, i + 1);
+            idx += i + 1;
+
+            XMEMCPY(shaInput + idx, ssl->arrays->preMasterSecret, pmsSz);
+            idx += pmsSz;
+            XMEMCPY(shaInput + idx, ssl->arrays->clientRandom, RAN_LEN);
+            idx += RAN_LEN;
+            XMEMCPY(shaInput + idx, ssl->arrays->serverRandom, RAN_LEN);
+            idx += RAN_LEN;
+            if (ret == 0) {
+                ret = wc_ShaUpdate(sha, shaInput, idx);
+            }
+            if (ret == 0) {
+                ret = wc_ShaFinal(sha, shaOutput);
+            }
+            idx = pmsSz;  /* preSz */
+            XMEMCPY(md5Input + idx, shaOutput, WC_SHA_DIGEST_SIZE);
+            idx += WC_SHA_DIGEST_SIZE;
+            if (ret == 0) {
+                ret = wc_Md5Update(md5, md5Input, idx);
+            }
+            if (ret == 0) {
+                ret = wc_Md5Final(md5,
+                            &ssl->arrays->masterSecret[i * WC_MD5_DIGEST_SIZE]);
+            }
+        }
+
+#ifdef SHOW_SECRETS
+        {
+            word32 j;
+            printf("master secret: ");
+            for (j = 0; j < SECRET_LEN; j++)
+                printf("%02x", ssl->arrays->masterSecret[j]);
+            printf("\n");
+        }
+#endif
+
+        if (ret == 0)
+            ret = DeriveKeys(ssl);
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(md5Input,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(shaInput,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(md5,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(sha,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    if (ret == 0)
+        ret = CleanPreMaster(ssl);
+    else
+        CleanPreMaster(ssl);
+
+    return ret;
+}
+#endif
+
+
+/* Master wrapper, doesn't use SSL stack space in TLS mode */
+int MakeMasterSecret(WOLFSSL* ssl)
+{
+    /* append secret to premaster : premaster | SerSi | CliSi */
+#ifdef HAVE_QSH
+    word32 offset = 0;
+
+    if (ssl->peerQSHKeyPresent) {
+        offset += ssl->arrays->preMasterSz;
+        ssl->arrays->preMasterSz += ssl->QSH_secret->CliSi->length +
+                                                 ssl->QSH_secret->SerSi->length;
+        /* test and set flag if QSH has been used */
+        if (ssl->QSH_secret->CliSi->length > 0 ||
+                ssl->QSH_secret->SerSi->length > 0)
+            ssl->isQSH = 1;
+
+        /* append secrets to the premaster */
+        if (ssl->QSH_secret->SerSi != NULL) {
+            XMEMCPY(ssl->arrays->preMasterSecret + offset,
+                ssl->QSH_secret->SerSi->buffer, ssl->QSH_secret->SerSi->length);
+        }
+        offset += ssl->QSH_secret->SerSi->length;
+        if (ssl->QSH_secret->CliSi != NULL) {
+            XMEMCPY(ssl->arrays->preMasterSecret + offset,
+                ssl->QSH_secret->CliSi->buffer, ssl->QSH_secret->CliSi->length);
+        }
+
+        /* show secret SerSi and CliSi */
+        #ifdef SHOW_SECRETS
+        {
+            word32 j;
+            printf("QSH generated secret material\n");
+            printf("SerSi        : ");
+            for (j = 0; j < ssl->QSH_secret->SerSi->length; j++) {
+                printf("%02x", ssl->QSH_secret->SerSi->buffer[j]);
+            }
+            printf("\n");
+            printf("CliSi        : ");
+            for (j = 0; j < ssl->QSH_secret->CliSi->length; j++) {
+                printf("%02x", ssl->QSH_secret->CliSi->buffer[j]);
+            }
+            printf("\n");
+        }
+        #endif
+    }
+#endif
+
+#ifndef NO_OLD_TLS
+    if (ssl->options.tls) return MakeTlsMasterSecret(ssl);
+    return MakeSslMasterSecret(ssl);
+#elif !defined(WOLFSSL_NO_TLS12)
+    return MakeTlsMasterSecret(ssl);
+#else
+    (void)ssl;
+    return 0;
+#endif
+}
+
+#endif /* WOLFCRYPT_ONLY */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/ocsp.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/ocsp.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/ocsp.c	(revision 453)
@@ -0,0 +1,1100 @@
+/* ocsp.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+  /* Name change compatibility layer no longer needs to be included here */
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifndef WOLFCRYPT_ONLY
+#ifdef HAVE_OCSP
+
+#include <wolfssl/error-ssl.h>
+#include <wolfssl/ocsp.h>
+#include <wolfssl/internal.h>
+
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+
+int InitOCSP(WOLFSSL_OCSP* ocsp, WOLFSSL_CERT_MANAGER* cm)
+{
+    WOLFSSL_ENTER("InitOCSP");
+
+    ForceZero(ocsp, sizeof(WOLFSSL_OCSP));
+
+    if (wc_InitMutex(&ocsp->ocspLock) != 0)
+        return BAD_MUTEX_E;
+
+    ocsp->cm = cm;
+
+    return 0;
+}
+
+
+static int InitOcspEntry(OcspEntry* entry, OcspRequest* request)
+{
+    WOLFSSL_ENTER("InitOcspEntry");
+
+    ForceZero(entry, sizeof(OcspEntry));
+
+    XMEMCPY(entry->issuerHash,    request->issuerHash,    OCSP_DIGEST_SIZE);
+    XMEMCPY(entry->issuerKeyHash, request->issuerKeyHash, OCSP_DIGEST_SIZE);
+
+    return 0;
+}
+
+
+static void FreeOcspEntry(OcspEntry* entry, void* heap)
+{
+    CertStatus *status, *next;
+
+    WOLFSSL_ENTER("FreeOcspEntry");
+
+    for (status = entry->status; status; status = next) {
+        next = status->next;
+
+        if (status->rawOcspResponse)
+            XFREE(status->rawOcspResponse, heap, DYNAMIC_TYPE_OCSP_STATUS);
+
+        XFREE(status, heap, DYNAMIC_TYPE_OCSP_STATUS);
+    }
+
+    (void)heap;
+}
+
+
+void FreeOCSP(WOLFSSL_OCSP* ocsp, int dynamic)
+{
+    OcspEntry *entry, *next;
+
+    WOLFSSL_ENTER("FreeOCSP");
+
+    for (entry = ocsp->ocspList; entry; entry = next) {
+        next = entry->next;
+        FreeOcspEntry(entry, ocsp->cm->heap);
+        XFREE(entry, ocsp->cm->heap, DYNAMIC_TYPE_OCSP_ENTRY);
+    }
+
+    wc_FreeMutex(&ocsp->ocspLock);
+
+    if (dynamic)
+        XFREE(ocsp, ocsp->cm->heap, DYNAMIC_TYPE_OCSP);
+
+}
+
+
+static int xstat2err(int st)
+{
+    switch (st) {
+        case CERT_GOOD:
+            return 0;
+        case CERT_REVOKED:
+            return OCSP_CERT_REVOKED;
+        default:
+            return OCSP_CERT_UNKNOWN;
+    }
+}
+
+int CheckCertOCSP_ex(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuffer, WOLFSSL* ssl)
+{
+    int ret = OCSP_LOOKUP_FAIL;
+
+#ifdef WOLFSSL_SMALL_STACK
+    OcspRequest* ocspRequest;
+#else
+    OcspRequest ocspRequest[1];
+#endif
+
+    WOLFSSL_ENTER("CheckCertOCSP");
+
+
+#ifdef WOLFSSL_SMALL_STACK
+    ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+    if (ocspRequest == NULL) {
+        WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
+        return MEMORY_E;
+    }
+#endif
+
+    if (InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce,
+                                                         ocsp->cm->heap) == 0) {
+        ocspRequest->ssl = ssl;
+        ret = CheckOcspRequest(ocsp, ocspRequest, responseBuffer);
+
+        FreeOcspRequest(ocspRequest);
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    WOLFSSL_LEAVE("CheckCertOCSP", ret);
+    return ret;
+}
+int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuffer)
+{
+    return CheckCertOCSP_ex(ocsp, cert, responseBuffer, NULL);
+}
+
+static int GetOcspEntry(WOLFSSL_OCSP* ocsp, OcspRequest* request,
+                                                              OcspEntry** entry)
+{
+    WOLFSSL_ENTER("GetOcspEntry");
+
+    *entry = NULL;
+
+    if (wc_LockMutex(&ocsp->ocspLock) != 0) {
+        WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E);
+        return BAD_MUTEX_E;
+    }
+
+    for (*entry = ocsp->ocspList; *entry; *entry = (*entry)->next)
+        if (XMEMCMP((*entry)->issuerHash,    request->issuerHash,
+                                                         OCSP_DIGEST_SIZE) == 0
+        &&  XMEMCMP((*entry)->issuerKeyHash, request->issuerKeyHash,
+                                                         OCSP_DIGEST_SIZE) == 0)
+            break;
+
+    if (*entry == NULL) {
+        *entry = (OcspEntry*)XMALLOC(sizeof(OcspEntry),
+                                       ocsp->cm->heap, DYNAMIC_TYPE_OCSP_ENTRY);
+        if (*entry) {
+            InitOcspEntry(*entry, request);
+            (*entry)->next = ocsp->ocspList;
+            ocsp->ocspList = *entry;
+        }
+    }
+
+    wc_UnLockMutex(&ocsp->ocspLock);
+
+    return *entry ? 0 : MEMORY_ERROR;
+}
+
+
+/* Mallocs responseBuffer->buffer and is up to caller to free on success
+ *
+ * Returns OCSP status
+ */
+static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request,
+                  OcspEntry* entry, CertStatus** status, buffer* responseBuffer)
+{
+    int ret = OCSP_INVALID_STATUS;
+
+    WOLFSSL_ENTER("GetOcspStatus");
+
+    *status = NULL;
+
+    if (wc_LockMutex(&ocsp->ocspLock) != 0) {
+        WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E);
+        return BAD_MUTEX_E;
+    }
+
+    for (*status = entry->status; *status; *status = (*status)->next)
+        if ((*status)->serialSz == request->serialSz
+        &&  !XMEMCMP((*status)->serial, request->serial, (*status)->serialSz))
+            break;
+
+    if (responseBuffer && *status && !(*status)->rawOcspResponse) {
+        /* force fetching again */
+        ret = OCSP_INVALID_STATUS;
+    }
+    else if (*status) {
+#ifndef NO_ASN_TIME
+        if (XVALIDATE_DATE((*status)->thisDate,
+                                             (*status)->thisDateFormat, BEFORE)
+        &&  ((*status)->nextDate[0] != 0)
+        &&  XVALIDATE_DATE((*status)->nextDate,
+                                             (*status)->nextDateFormat, AFTER))
+#endif
+        {
+            ret = xstat2err((*status)->status);
+
+            if (responseBuffer) {
+                responseBuffer->buffer = (byte*)XMALLOC(
+                   (*status)->rawOcspResponseSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+                if (responseBuffer->buffer) {
+                    responseBuffer->length = (*status)->rawOcspResponseSz;
+                    XMEMCPY(responseBuffer->buffer,
+                            (*status)->rawOcspResponse,
+                            (*status)->rawOcspResponseSz);
+                }
+            }
+        }
+    }
+
+    wc_UnLockMutex(&ocsp->ocspLock);
+
+    return ret;
+}
+
+/* Check that the response for validity. Store result in status.
+ *
+ * ocsp           Context object for OCSP status.
+ * response       OCSP response message data.
+ * responseSz     Length of OCSP response message data.
+ * reponseBuffer  Buffer object to return the response with.
+ * status         The certificate status object.
+ * entry          The OCSP entry for this certificate.
+ * returns OCSP_LOOKUP_FAIL when the response is bad and 0 otherwise.
+ */
+WOLFSSL_LOCAL int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz,
+                                    WOLFSSL_BUFFER_INFO *responseBuffer, CertStatus *status,
+                                    OcspEntry *entry, OcspRequest *ocspRequest)
+{
+#ifdef WOLFSSL_SMALL_STACK
+    CertStatus*   newStatus;
+    OcspResponse* ocspResponse;
+#else
+    CertStatus    newStatus[1];
+    OcspResponse  ocspResponse[1];
+#endif
+    int           ret;
+    int           validated      = 0;    /* ocsp validation flag */
+
+#ifdef WOLFSSL_SMALL_STACK
+    newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+    ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+
+    if (newStatus == NULL || ocspResponse == NULL) {
+        if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+        WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
+        return MEMORY_E;
+    }
+#endif
+    XMEMSET(newStatus, 0, sizeof(CertStatus));
+
+    InitOcspResponse(ocspResponse, newStatus, response, responseSz);
+    ret = OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap, 0);
+    if (ret != 0) {
+        ocsp->error = ret;
+        WOLFSSL_LEAVE("OcspResponseDecode failed", ocsp->error);
+        goto end;
+    }
+
+    if (ocspResponse->responseStatus != OCSP_SUCCESSFUL) {
+        WOLFSSL_MSG("OcspResponse status bad");
+        goto end;
+    }
+    if (ocspRequest != NULL) {
+        ret = CompareOcspReqResp(ocspRequest, ocspResponse);
+        if (ret != 0) {
+            goto end;
+        }
+    }
+
+    if (responseBuffer) {
+        responseBuffer->buffer = (byte*)XMALLOC(responseSz, ocsp->cm->heap,
+                                                DYNAMIC_TYPE_TMP_BUFFER);
+
+        if (responseBuffer->buffer) {
+            responseBuffer->length = responseSz;
+            XMEMCPY(responseBuffer->buffer, response, responseSz);
+        }
+    }
+
+    ret = xstat2err(ocspResponse->status->status);
+    if (ret == 0) {
+        validated = 1;
+    }
+
+    if (wc_LockMutex(&ocsp->ocspLock) != 0) {
+        ret = BAD_MUTEX_E;
+        goto end;
+    }
+
+    if (status != NULL) {
+        if (status->rawOcspResponse) {
+            XFREE(status->rawOcspResponse, ocsp->cm->heap,
+                  DYNAMIC_TYPE_OCSP_STATUS);
+        }
+
+        /* Replace existing certificate entry with updated */
+        newStatus->next = status->next;
+        XMEMCPY(status, newStatus, sizeof(CertStatus));
+    }
+    else {
+        /* Save new certificate entry */
+        status = (CertStatus*)XMALLOC(sizeof(CertStatus),
+                                      ocsp->cm->heap, DYNAMIC_TYPE_OCSP_STATUS);
+        if (status != NULL) {
+            XMEMCPY(status, newStatus, sizeof(CertStatus));
+            status->next  = entry->status;
+            entry->status = status;
+            entry->totalStatus++;
+        }
+    }
+
+    if (status && responseBuffer && responseBuffer->buffer) {
+        status->rawOcspResponse = (byte*)XMALLOC(responseBuffer->length,
+                                                 ocsp->cm->heap,
+                                                 DYNAMIC_TYPE_OCSP_STATUS);
+
+        if (status->rawOcspResponse) {
+            status->rawOcspResponseSz = responseBuffer->length;
+            XMEMCPY(status->rawOcspResponse, responseBuffer->buffer,
+                    responseBuffer->length);
+        }
+    }
+
+    wc_UnLockMutex(&ocsp->ocspLock);
+
+end:
+    if (ret == 0 && validated == 1) {
+        WOLFSSL_MSG("New OcspResponse validated");
+    } else if (ret != OCSP_CERT_REVOKED) {
+        ret = OCSP_LOOKUP_FAIL;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(newStatus,    NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+    return ret;
+}
+
+/* 0 on success */
+int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest,
+                                                      buffer* responseBuffer)
+{
+    OcspEntry*  entry          = NULL;
+    CertStatus* status         = NULL;
+    byte*       request        = NULL;
+    int         requestSz      = 2048;
+    int         responseSz     = 0;
+    byte*       response       = NULL;
+    const char* url            = NULL;
+    int         urlSz          = 0;
+    int         ret            = -1;
+    WOLFSSL*    ssl;
+    void*       ioCtx;
+
+    WOLFSSL_ENTER("CheckOcspRequest");
+
+    if (ocsp == NULL || ocspRequest == NULL)
+        return BAD_FUNC_ARG;
+
+    if (responseBuffer) {
+        responseBuffer->buffer = NULL;
+        responseBuffer->length = 0;
+    }
+
+    ret = GetOcspEntry(ocsp, ocspRequest, &entry);
+    if (ret != 0)
+        return ret;
+
+    ret = GetOcspStatus(ocsp, ocspRequest, entry, &status, responseBuffer);
+    if (ret != OCSP_INVALID_STATUS)
+        return ret;
+
+    /* get SSL and IOCtx */
+    ssl = (WOLFSSL*)ocspRequest->ssl;
+    ioCtx = (ssl && ssl->ocspIOCtx != NULL) ?
+                                        ssl->ocspIOCtx : ocsp->cm->ocspIOCtx;
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+    if (ocsp->statusCb != NULL && ssl != NULL) {
+        ret = ocsp->statusCb(ssl, ioCtx);
+        if (ret == 0) {
+            ret = wolfSSL_get_ocsp_response(ssl, &response);
+            ret = CheckOcspResponse(ocsp, response, ret, responseBuffer, status,
+                                entry, NULL);
+            if (response != NULL)
+                XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL);
+            return ret;
+        }
+        WOLFSSL_LEAVE("CheckOcspRequest", ocsp->error);
+        return OCSP_LOOKUP_FAIL;
+    }
+#endif
+
+    if (ocsp->cm->ocspUseOverrideURL) {
+        url = ocsp->cm->ocspOverrideURL;
+        if (url != NULL && url[0] != '\0')
+            urlSz = (int)XSTRLEN(url);
+        else
+            return OCSP_NEED_URL;
+    }
+    else if (ocspRequest->urlSz != 0 && ocspRequest->url != NULL) {
+        url = (const char *)ocspRequest->url;
+        urlSz = ocspRequest->urlSz;
+    }
+    else {
+        /* cert doesn't have extAuthInfo, assuming CERT_GOOD */
+        return 0;
+    }
+
+    request = (byte*)XMALLOC(requestSz, ocsp->cm->heap, DYNAMIC_TYPE_OCSP);
+    if (request == NULL) {
+        WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
+        if (responseBuffer) {
+            XFREE(responseBuffer->buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            responseBuffer->buffer = NULL;
+        }
+        return MEMORY_ERROR;
+    }
+
+    requestSz = EncodeOcspRequest(ocspRequest, request, requestSz);
+    if (requestSz > 0 && ocsp->cm->ocspIOCb) {
+        responseSz = ocsp->cm->ocspIOCb(ioCtx, url, urlSz,
+                                        request, requestSz, &response);
+    }
+    if (responseSz == WOLFSSL_CBIO_ERR_WANT_READ) {
+        ret = OCSP_WANT_READ;
+    }
+
+    XFREE(request, ocsp->cm->heap, DYNAMIC_TYPE_OCSP);
+
+    if (responseSz >= 0 && response) {
+        ret = CheckOcspResponse(ocsp, response, responseSz, responseBuffer, status,
+                            entry, ocspRequest);
+    }
+
+    if (response != NULL && ocsp->cm->ocspRespFreeCb)
+        ocsp->cm->ocspRespFreeCb(ioCtx, response);
+
+    /* Keep responseBuffer in the case of getting to response check. Caller
+     * should free responseBuffer after checking OCSP return value in "ret" */
+    WOLFSSL_LEAVE("CheckOcspRequest", ret);
+    return ret;
+}
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
+    defined(WOLFSSL_APACHE_HTTPD)
+
+int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs,
+    WOLFSSL_OCSP_CERTID* id, int* status, int* reason,
+    WOLFSSL_ASN1_TIME** revtime, WOLFSSL_ASN1_TIME** thisupd,
+    WOLFSSL_ASN1_TIME** nextupd)
+{
+    if (bs == NULL || id == NULL)
+        return WOLFSSL_FAILURE;
+
+    /* Only supporting one certificate status in asn.c. */
+    if (CompareOcspReqResp(id, bs) != 0)
+        return WOLFSSL_FAILURE;
+
+    if (status != NULL)
+        *status = bs->status->status;
+    if (thisupd != NULL)
+        *thisupd = &bs->status->thisDateParsed;
+    if (nextupd != NULL)
+        *nextupd = &bs->status->nextDateParsed;
+
+    /* TODO: Not needed for Nginx. */
+    if (reason != NULL)
+        *reason = 0;
+    if (revtime != NULL)
+        *revtime = NULL;
+
+    return WOLFSSL_SUCCESS;
+}
+
+const char *wolfSSL_OCSP_cert_status_str(long s)
+{
+    switch (s) {
+        case CERT_GOOD:
+            return "good";
+        case CERT_REVOKED:
+            return "revoked";
+        case CERT_UNKNOWN:
+            return "unknown";
+        default:
+            return "(UNKNOWN)";
+    }
+}
+
+int wolfSSL_OCSP_check_validity(WOLFSSL_ASN1_TIME* thisupd,
+    WOLFSSL_ASN1_TIME* nextupd, long sec, long maxsec)
+{
+    (void)thisupd;
+    (void)nextupd;
+    (void)sec;
+    (void)maxsec;
+    /* Dates validated in DecodeSingleResponse. */
+    return WOLFSSL_SUCCESS;
+}
+
+void wolfSSL_OCSP_CERTID_free(WOLFSSL_OCSP_CERTID* certId)
+{
+    FreeOcspRequest(certId);
+    XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL);
+}
+
+WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id(
+    const WOLFSSL_EVP_MD *dgst, const WOLFSSL_X509 *subject,
+    const WOLFSSL_X509 *issuer)
+{
+    WOLFSSL_OCSP_CERTID* certId;
+    DecodedCert cert;
+    WOLFSSL_CERT_MANAGER* cm;
+    int ret;
+    DerBuffer* derCert = NULL;
+
+    (void)dgst;
+
+    cm = wolfSSL_CertManagerNew();
+    if (cm == NULL)
+        return NULL;
+
+    ret = AllocDer(&derCert, issuer->derCert->length,
+        issuer->derCert->type, NULL);
+    if (ret == 0) {
+        /* AddCA() frees the buffer. */
+        XMEMCPY(derCert->buffer, issuer->derCert->buffer,
+                issuer->derCert->length);
+        AddCA(cm, &derCert, WOLFSSL_USER_CA, 1);
+    }
+
+    certId = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID), NULL,
+                                           DYNAMIC_TYPE_OPENSSL);
+    if (certId != NULL) {
+        InitDecodedCert(&cert, subject->derCert->buffer,
+                        subject->derCert->length, NULL);
+        if (ParseCertRelative(&cert, CERT_TYPE, VERIFY_OCSP, cm) != 0) {
+            XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL);
+            certId = NULL;
+        }
+        else {
+            ret = InitOcspRequest(certId, &cert, 0, NULL);
+            if (ret != 0) {
+                XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL);
+                certId = NULL;
+            }
+        }
+        FreeDecodedCert(&cert);
+    }
+
+    wolfSSL_CertManagerFree(cm);
+
+    return certId;
+}
+
+void wolfSSL_OCSP_BASICRESP_free(WOLFSSL_OCSP_BASICRESP* basicResponse)
+{
+    wolfSSL_OCSP_RESPONSE_free(basicResponse);
+}
+
+/* Signature verified in DecodeBasicOcspResponse.
+ * But no store available to verify certificate. */
+int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP *bs,
+    WOLF_STACK_OF(WOLFSSL_X509) *certs, WOLFSSL_X509_STORE *st, unsigned long flags)
+{
+    DecodedCert cert;
+    int         ret = WOLFSSL_SUCCESS;
+
+    (void)certs;
+
+    if (flags & OCSP_NOVERIFY)
+        return WOLFSSL_SUCCESS;
+
+#ifdef OPENSSL_EXTRA
+    if (bs->verifyError != OCSP_VERIFY_ERROR_NONE)
+        return WOLFSSL_FAILURE;
+#endif
+
+    InitDecodedCert(&cert, bs->cert, bs->certSz, NULL);
+    if (ParseCertRelative(&cert, CERT_TYPE, VERIFY, st->cm) < 0)
+        ret = WOLFSSL_FAILURE;
+    FreeDecodedCert(&cert);
+
+    return ret;
+}
+
+void wolfSSL_OCSP_RESPONSE_free(OcspResponse* response)
+{
+    if (response->status != NULL)
+        XFREE(response->status, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (response->source != NULL)
+        XFREE(response->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL);
+}
+
+OcspResponse* wolfSSL_d2i_OCSP_RESPONSE_bio(WOLFSSL_BIO* bio,
+    OcspResponse** response)
+{
+    byte*         data;
+    byte*         p;
+    int           len;
+    int           dataAlloced = 0;
+    OcspResponse* ret = NULL;
+
+    if (bio == NULL)
+        return NULL;
+
+    if (bio->type == WOLFSSL_BIO_MEMORY) {
+        len = wolfSSL_BIO_get_mem_data(bio, &data);
+        if (len <= 0 || data == NULL) {
+            return NULL;
+        }
+    }
+#ifndef NO_FILESYSTEM
+    else if (bio->type == WOLFSSL_BIO_FILE) {
+        long fcur;
+        long flen;
+
+        if (bio->ptr == NULL)
+            return NULL;
+
+        fcur = XFTELL((XFILE)bio->ptr);
+        if (fcur < 0)
+            return NULL;
+        if(XFSEEK((XFILE)bio->ptr, 0, SEEK_END) != 0)
+            return NULL;
+        flen = XFTELL((XFILE)bio->ptr);
+        if (flen < 0)
+            return NULL;
+        if (XFSEEK((XFILE)bio->ptr, fcur, SEEK_SET) != 0)
+            return NULL;
+
+        /* check calculated length */
+        fcur = flen - fcur;
+        if (fcur > MAX_WOLFSSL_FILE_SIZE || fcur <= 0)
+            return NULL;
+
+        data = (byte*)XMALLOC(fcur, 0, DYNAMIC_TYPE_TMP_BUFFER);
+        if (data == NULL)
+            return NULL;
+        dataAlloced = 1;
+
+        len = wolfSSL_BIO_read(bio, (char *)data, (int)flen);
+    }
+#endif
+    else
+        return NULL;
+
+    if (len > 0) {
+        p = data;
+        ret = wolfSSL_d2i_OCSP_RESPONSE(response, (const unsigned char **)&p,
+            len);
+    }
+
+    if (dataAlloced)
+        XFREE(data, 0, DYNAMIC_TYPE_TMP_BUFFER);
+
+    return ret;
+}
+
+OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response,
+    const unsigned char** data, int len)
+{
+    OcspResponse *resp = NULL;
+    word32 idx = 0;
+    int length = 0;
+
+    if (data == NULL)
+        return NULL;
+
+    if (response != NULL)
+        resp = *response;
+    if (resp == NULL) {
+        resp = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL,
+                                      DYNAMIC_TYPE_OPENSSL);
+        if (resp == NULL)
+            return NULL;
+        XMEMSET(resp, 0, sizeof(OcspResponse));
+    }
+
+    resp->source = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (resp->source == NULL) {
+        XFREE(resp, NULL, DYNAMIC_TYPE_OPENSSL);
+        return NULL;
+    }
+    resp->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+    if (resp->status == NULL) {
+        XFREE(resp->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(resp, NULL, DYNAMIC_TYPE_OPENSSL);
+        return NULL;
+    }
+
+    XMEMCPY(resp->source, *data, len);
+    resp->maxIdx = len;
+
+    if (OcspResponseDecode(resp, NULL, NULL, 1) != 0) {
+        wolfSSL_OCSP_RESPONSE_free(resp);
+        return NULL;
+    }
+
+    if (GetSequence(*data, &idx, &length, len) >= 0)
+        (*data) += idx + length;
+
+    return resp;
+}
+
+int wolfSSL_i2d_OCSP_RESPONSE(OcspResponse* response,
+    unsigned char** data)
+{
+    if (data == NULL)
+        return response->maxIdx;
+
+    XMEMCPY(*data, response->source, response->maxIdx);
+    return response->maxIdx;
+}
+
+int wolfSSL_OCSP_response_status(OcspResponse *response)
+{
+    return response->responseStatus;
+}
+
+const char *wolfSSL_OCSP_response_status_str(long s)
+{
+    switch (s) {
+        case OCSP_SUCCESSFUL:
+            return "successful";
+        case OCSP_MALFORMED_REQUEST:
+            return "malformedrequest";
+        case OCSP_INTERNAL_ERROR:
+            return "internalerror";
+        case OCSP_TRY_LATER:
+            return "trylater";
+        case OCSP_SIG_REQUIRED:
+            return "sigrequired";
+        case OCSP_UNAUTHROIZED:
+            return "unauthorized";
+        default:
+            return "(UNKNOWN)";
+    }
+}
+
+WOLFSSL_OCSP_BASICRESP* wolfSSL_OCSP_response_get1_basic(OcspResponse* response)
+{
+    WOLFSSL_OCSP_BASICRESP* bs;
+
+    bs = (WOLFSSL_OCSP_BASICRESP*)XMALLOC(sizeof(WOLFSSL_OCSP_BASICRESP), NULL,
+                                          DYNAMIC_TYPE_OPENSSL);
+    if (bs == NULL)
+        return NULL;
+
+    XMEMCPY(bs, response, sizeof(OcspResponse));
+    bs->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
+                                      DYNAMIC_TYPE_TMP_BUFFER);
+    bs->source = (byte*)XMALLOC(bs->maxIdx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (bs->status == NULL || bs->source == NULL) {
+        if (bs->status) XFREE(bs->status, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (bs->source) XFREE(bs->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        wolfSSL_OCSP_RESPONSE_free(bs);
+        bs = NULL;
+    }
+    else {
+        XMEMCPY(bs->status, response->status, sizeof(CertStatus));
+        XMEMCPY(bs->source, response->source, response->maxIdx);
+    }
+    return bs;
+}
+
+OcspRequest* wolfSSL_OCSP_REQUEST_new(void)
+{
+    OcspRequest* request;
+
+    request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL,
+                                    DYNAMIC_TYPE_OPENSSL);
+    if (request != NULL)
+        XMEMSET(request, 0, sizeof(OcspRequest));
+
+    return request;
+}
+
+void wolfSSL_OCSP_REQUEST_free(OcspRequest* request)
+{
+    FreeOcspRequest(request);
+    XFREE(request, NULL, DYNAMIC_TYPE_OPENSSL);
+}
+
+int wolfSSL_i2d_OCSP_REQUEST(OcspRequest* request, unsigned char** data)
+{
+    int size;
+
+    size = EncodeOcspRequest(request, NULL, 0);
+    if (size <= 0 || data == NULL)
+        return size;
+
+    return EncodeOcspRequest(request, *data, size);
+}
+
+WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req,
+    WOLFSSL_OCSP_CERTID *cid)
+{
+    if (req == NULL || cid == NULL)
+        return NULL;
+
+    FreeOcspRequest(req);
+    XMEMCPY(req, cid, sizeof(OcspRequest));
+
+    if (cid->serial != NULL) {
+        req->serial = (byte*)XMALLOC(cid->serialSz, NULL,
+                                     DYNAMIC_TYPE_OCSP_REQUEST);
+        req->url = (byte*)XMALLOC(cid->urlSz, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
+        if (req->serial == NULL || req->url == NULL) {
+            FreeOcspRequest(req);
+            return NULL;
+        }
+
+        XMEMCPY(req->serial, cid->serial, cid->serialSz);
+        XMEMCPY(req->url, cid->url, cid->urlSz);
+    }
+
+    wolfSSL_OCSP_REQUEST_free(cid);
+
+    return req;
+}
+
+WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_CERTID_dup(WOLFSSL_OCSP_CERTID* id)
+{
+    WOLFSSL_OCSP_CERTID* certId;
+
+    if (id == NULL) {
+        return NULL;
+    }
+
+    certId = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID),
+        id->heap, DYNAMIC_TYPE_OPENSSL);
+    if (certId) {
+        XMEMCPY(certId, id, sizeof(WOLFSSL_OCSP_CERTID));
+    }
+    return certId;
+}
+#endif
+
+#if defined(OPENSSL_ALL) || defined(APACHE_HTTPD)
+int wolfSSL_i2d_OCSP_REQUEST_bio(WOLFSSL_BIO* out,
+        WOLFSSL_OCSP_REQUEST *req)
+{
+    int size = -1;
+    unsigned char* data = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_i2d_OCSP_REQUEST_bio");
+    if (out == NULL || req == NULL)
+        return WOLFSSL_FAILURE;
+
+    size = wolfSSL_i2d_OCSP_REQUEST(req, NULL);
+    if (size > 0) {
+        data = (unsigned char*) XMALLOC(size, out->heap,
+                DYNAMIC_TYPE_TMP_BUFFER);
+    }
+
+    if (data != NULL) {
+        size = wolfSSL_i2d_OCSP_REQUEST(req, &data);
+    }
+
+    if (size <= 0) {
+        XFREE(data, out->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_FAILURE;
+    }
+
+    if (wolfSSL_BIO_write(out, data, size) == (int)size) {
+        XFREE(data, out->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_SUCCESS;
+    }
+
+    XFREE(data, out->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    return WOLFSSL_FAILURE;
+}
+#endif /* OPENSSL_ALL || APACHE_HTTPD */
+
+#ifdef OPENSSL_EXTRA
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_OCSP_REQUEST_add_ext(OcspRequest* req, WOLFSSL_X509_EXTENSION* ext,
+        int idx)
+{
+    WOLFSSL_STUB("wolfSSL_OCSP_REQUEST_add_ext");
+    (void)req;
+    (void)ext;
+    (void)idx;
+    return WOLFSSL_FATAL_ERROR;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+OcspResponse* wolfSSL_OCSP_response_create(int status,
+    WOLFSSL_OCSP_BASICRESP* bs)
+{
+    WOLFSSL_STUB("wolfSSL_OCSP_response_create");
+    (void)status;
+    (void)bs;
+    return NULL;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+const char* wolfSSL_OCSP_crl_reason_str(long s)
+{
+    WOLFSSL_STUB("wolfSSL_OCSP_crl_reason_str");
+    (void)s;
+    return NULL;
+}
+#endif
+
+/* Returns elements of an OCSP_CERTID struct. Currently only supports
+ * returning the serial number, and returns an error if user requests
+ * any of name, pmd, and/or keyHash.
+ * Return 1 on success, 0 on failure */
+int wolfSSL_OCSP_id_get0_info(WOLFSSL_ASN1_STRING **name,
+  WOLFSSL_ASN1_OBJECT **pmd, WOLFSSL_ASN1_STRING **keyHash,
+  WOLFSSL_ASN1_INTEGER **serial, WOLFSSL_OCSP_CERTID *cid)
+{
+    int i = 0;
+    WOLFSSL_ASN1_INTEGER* ser;
+
+    WOLFSSL_ENTER("wolfSSL_OCSP_id_get0_info");
+
+    if (cid == NULL)
+        return 0;
+
+    /* build up ASN1_INTEGER for serial */
+    if (serial != NULL) {
+        ser = wolfSSL_ASN1_INTEGER_new();
+        if (ser == NULL)
+            return 0;
+
+        if (cid->serialSz > (WOLFSSL_ASN1_INTEGER_MAX - 2)) {
+            /* allocate data buffer, +2 for type and length */
+            ser->data = (unsigned char*)XMALLOC(cid->serialSz + 2, NULL,
+                DYNAMIC_TYPE_OPENSSL);
+            if (ser->data == NULL) {
+                wolfSSL_ASN1_INTEGER_free(ser);
+                return 0;
+            }
+            ser->dataMax = cid->serialSz + 2;
+            ser->isDynamic = 1;
+        } else {
+            /* Use array instead of dynamic memory */
+            ser->data    = ser->intData;
+            ser->dataMax = WOLFSSL_ASN1_INTEGER_MAX;
+        }
+
+        #ifdef WOLFSSL_QT
+            /* Serial number starts at 0 index of ser->data */
+            XMEMCPY(&ser->data[i], cid->serial, cid->serialSz);
+            ser->length = cid->serialSz;
+        #else
+            ser->data[i++] = ASN_INTEGER;
+            i += SetLength(cid->serialSz, ser->data + i);
+            XMEMCPY(&ser->data[i], cid->serial, cid->serialSz);
+        #endif
+
+        cid->serialInt = ser;
+        *serial = cid->serialInt;
+    }
+
+    /* Not needed for Apache, return error if user is requesting */
+    if (name != NULL || pmd != NULL || keyHash != NULL) {
+        if (name != NULL)
+            *name = NULL;
+
+        if (pmd != NULL)
+            *pmd = NULL;
+
+        if (keyHash != NULL)
+            *keyHash = NULL;
+        return 0;
+    }
+
+    return 1;
+}
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_OCSP_request_add1_nonce(OcspRequest* req, unsigned char* val,
+        int sz)
+{
+    WOLFSSL_STUB("wolfSSL_OCSP_request_add1_nonce");
+    (void)req;
+    (void)val;
+    (void)sz;
+    return WOLFSSL_FATAL_ERROR;
+}
+#endif
+
+/* Returns result of OCSP nonce comparison. Return values:
+ *  1 - nonces are both present and equal
+ *  2 - both nonces are absent
+ *  3 - nonce only present in response
+ * -1 - nonce only present in request
+ *  0 - both nonces present and equal
+ */
+int wolfSSL_OCSP_check_nonce(OcspRequest* req, WOLFSSL_OCSP_BASICRESP* bs)
+{
+    byte* reqNonce = NULL;
+    byte* rspNonce = NULL;
+    int reqNonceSz = 0;
+    int rspNonceSz = 0;
+
+    WOLFSSL_ENTER("wolfSSL_OCSP_check_nonce");
+
+    if (req != NULL) {
+        reqNonce = req->nonce;
+        reqNonceSz = req->nonceSz;
+    }
+
+    if (bs != NULL) {
+        rspNonce = bs->nonce;
+        rspNonceSz = bs->nonceSz;
+    }
+
+    /* nonce absent in both req and rsp */
+    if (reqNonce == NULL && rspNonce == NULL)
+        return 2;
+
+    /* nonce present in rsp only */
+    if (reqNonce == NULL && rspNonce != NULL)
+        return 3;
+
+    /* nonce present in req only */
+    if (reqNonce != NULL && rspNonce == NULL)
+        return -1;
+
+    /* nonces are present and equal, return 1. Extra NULL check for fixing
+        scan-build warning. */
+    if (reqNonceSz == rspNonceSz && reqNonce && rspNonce) {
+        if (XMEMCMP(reqNonce, rspNonce, reqNonceSz) == 0)
+            return 1;
+    }
+
+    /* nonces are present but not equal */
+    return 0;
+}
+#endif /* OPENSSL_EXTRA */
+
+#else /* HAVE_OCSP */
+
+
+#ifdef _MSC_VER
+    /* 4206 warning for blank file */
+    #pragma warning(disable: 4206)
+#endif
+
+
+#endif /* HAVE_OCSP */
+#endif /* WOLFCRYPT_ONLY */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/sniffer.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/sniffer.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/sniffer.c	(revision 453)
@@ -0,0 +1,4611 @@
+/* sniffer.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifndef WOLFCRYPT_ONLY
+#ifdef WOLFSSL_SNIFFER
+
+#include <assert.h>
+#include <time.h>
+
+#ifndef _WIN32
+  #include <arpa/inet.h>
+#else
+  #include <WS2tcpip.h>
+#endif
+
+#ifdef _WIN32
+    #define SNPRINTF _snprintf
+#else
+    #define SNPRINTF snprintf
+#endif
+
+#include <wolfssl/openssl/ssl.h>
+#include <wolfssl/internal.h>
+#include <wolfssl/error-ssl.h>
+#include <wolfssl/sniffer.h>
+#include <wolfssl/sniffer_error.h>
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+#ifdef WOLF_CRYPTO_CB
+    #include <wolfssl/wolfcrypt/cryptocb.h>
+    #ifdef HAVE_INTEL_QA_SYNC
+        #include <wolfssl/wolfcrypt/port/intel/quickassist_sync.h>
+    #endif
+    #ifdef HAVE_CAVIUM_OCTEON_SYNC
+        #include <wolfssl/wolfcrypt/port/cavium/cavium_octeon_sync.h>
+    #endif
+#endif
+
+
+#ifndef WOLFSSL_SNIFFER_TIMEOUT
+    #define WOLFSSL_SNIFFER_TIMEOUT 900
+    /* Cache unclosed Sessions for 15 minutes since last used */
+#endif
+
+/* Misc constants */
+enum {
+    MAX_SERVER_ADDRESS = 128, /* maximum server address length */
+    MAX_SERVER_NAME    = 128, /* maximum server name length */
+    MAX_ERROR_LEN      = 80,  /* maximum error length */
+    ETHER_IF_ADDR_LEN  = 6,   /* ethernet interface address length */
+    LOCAL_IF_ADDR_LEN  = 4,   /* localhost interface address length, !windows */
+    TCP_PROTO          = 6,   /* TCP_PROTOCOL */
+    IP_HDR_SZ          = 20,  /* IPv4 header length, min */
+    IP6_HDR_SZ         = 40,  /* IPv6 header length, min */
+    TCP_HDR_SZ         = 20,  /* TCP header length, min */
+    IPV4               = 4,   /* IP version 4 */
+    IPV6               = 6,   /* IP version 6 */
+    TCP_PROTOCOL       = 6,   /* TCP Protocol id */
+    NO_NEXT_HEADER     = 59,  /* IPv6 no headers follow */
+    TRACE_MSG_SZ       = 80,  /* Trace Message buffer size */
+    HASH_SIZE          = 499, /* Session Hash Table Rows */
+    PSEUDO_HDR_SZ      = 12,  /* TCP Pseudo Header size in bytes */
+    FATAL_ERROR_STATE  =  1,  /* SnifferSession fatal error state */
+    TICKET_HINT_LEN    = 4,   /* Session Ticket Hint length */
+    EXT_TYPE_SZ        = 2,   /* Extension length */
+    MAX_INPUT_SZ       = MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA +
+                         MTU_EXTRA,  /* Max input sz of reassembly */
+    EXT_MASTER_SECRET  = 0x17, /* Extended Master Secret Extension ID */
+    TICKET_EXT_ID      = 0x23 /* Session Ticket Extension ID */
+};
+
+
+#ifdef _WIN32
+
+static HMODULE dllModule;  /* for error string resources */
+
+BOOL APIENTRY DllMain( HMODULE hModule,
+                       DWORD  ul_reason_for_call,
+                       LPVOID lpReserved
+                     )
+{
+	static int didInit = 0;
+
+    switch (ul_reason_for_call)
+    {
+    case DLL_PROCESS_ATTACH:
+		if (didInit == 0) {
+            dllModule = hModule;
+			ssl_InitSniffer();
+			didInit = 1;
+		}
+        break;
+    case DLL_THREAD_ATTACH:
+        break;
+    case DLL_THREAD_DETACH:
+        break;
+    case DLL_PROCESS_DETACH:
+		if (didInit) {
+			ssl_FreeSniffer();
+			didInit = 0;
+		}
+        break;
+    }
+    return TRUE;
+}
+
+#endif /* _WIN32 */
+
+
+static WOLFSSL_GLOBAL int TraceOn = 0;         /* Trace is off by default */
+static WOLFSSL_GLOBAL FILE* TraceFile = 0;
+
+
+/* windows uses .rc table for this */
+#ifndef _WIN32
+
+static const char* const msgTable[] =
+{
+    /* 1 */
+    "Out of Memory",
+    "New SSL Sniffer Server Registered",
+    "Checking IP Header",
+    "SSL Sniffer Server Not Registered",
+    "Checking TCP Header",
+
+    /* 6 */
+    "SSL Sniffer Server Port Not Registered",
+    "RSA Private Decrypt Error",
+    "RSA Private Decode Error",
+    "Set Cipher Spec Error",
+    "Server Hello Input Malformed",
+
+    /* 11 */
+    "Couldn't Resume Session Error",
+    "Server Did Resumption",
+    "Client Hello Input Malformed",
+    "Client Trying to Resume",
+    "Handshake Input Malformed",
+
+    /* 16 */
+    "Got Hello Verify msg",
+    "Got Server Hello msg",
+    "Got Cert Request msg",
+    "Got Server Key Exchange msg",
+    "Got Cert msg",
+
+    /* 21 */
+    "Got Server Hello Done msg",
+    "Got Finished msg",
+    "Got Client Hello msg",
+    "Got Client Key Exchange msg",
+    "Got Cert Verify msg",
+
+    /* 26 */
+    "Got Unknown Handshake msg",
+    "New SSL Sniffer Session created",
+    "Couldn't create new SSL",
+    "Got a Packet to decode",
+    "No data present",
+
+    /* 31 */
+    "Session Not Found",
+    "Got an Old Client Hello msg",
+    "Old Client Hello Input Malformed",
+    "Old Client Hello OK",
+    "Bad Old Client Hello",
+
+    /* 36 */
+    "Bad Record Header",
+    "Record Header Input Malformed",
+    "Got a HandShake msg",
+    "Bad HandShake msg",
+    "Got a Change Cipher Spec msg",
+
+    /* 41 */
+    "Got Application Data msg",
+    "Bad Application Data",
+    "Got an Alert msg",
+    "Another msg to Process",
+    "Removing Session From Table",
+
+    /* 46 */
+    "Bad Key File",
+    "Wrong IP Version",
+    "Wrong Protocol type",
+    "Packet Short for header processing",
+    "Got Unknown Record Type",
+
+    /* 51 */
+    "Can't Open Trace File",
+    "Session in Fatal Error State",
+    "Partial SSL record received",
+    "Buffer Error, malformed input",
+    "Added to Partial Input",
+
+    /* 56 */
+    "Received a Duplicate Packet",
+    "Received an Out of Order Packet",
+    "Received an Overlap Duplicate Packet",
+    "Received an Overlap Reassembly Begin Duplicate Packet",
+    "Received an Overlap Reassembly End Duplicate Packet",
+
+    /* 61 */
+    "Missed the Client Hello Entirely",
+    "Got Hello Request msg",
+    "Got Session Ticket msg",
+    "Bad Input",
+    "Bad Decrypt Type",
+
+    /* 66 */
+    "Bad Finished Message Processing",
+    "Bad Compression Type",
+    "Bad DeriveKeys Error",
+    "Saw ACK for Missing Packet Error",
+    "Bad Decrypt Operation",
+
+    /* 71 */
+    "Decrypt Keys Not Set Up",
+    "Late Key Load Error",
+    "Got Certificate Status msg",
+    "RSA Key Missing Error",
+    "Secure Renegotiation Not Supported",
+
+    /* 76 */
+    "Get Session Stats Failure",
+    "Reassembly Buffer Size Exceeded",
+    "Dropping Lost Fragment",
+    "Dropping Partial Record",
+    "Clear ACK Fault",
+
+    /* 81 */
+    "Bad Decrypt Size",
+    "Extended Master Secret Hash Error",
+    "Handshake Message Split Across TLS Records",
+    "ECC Private Decode Error",
+    "ECC Public Decode Error",
+
+    /* 86 */
+    "Watch callback not set",
+    "Watch hash failed",
+    "Watch callback failed",
+    "Bad Certificate Message",
+    "Store data callback not set",
+
+    /* 91 */
+    "No data destination Error",
+    "Store data callback failed",
+    "Loading chain input"
+};
+
+
+/* *nix version uses table above */
+static void GetError(int idx, char* str)
+{
+    XSTRNCPY(str, msgTable[idx - 1], MAX_ERROR_LEN-1);
+    str[MAX_ERROR_LEN-1] = '\0';
+}
+
+
+#else /* _WIN32 */
+
+
+/* Windows version uses .rc table */
+static void GetError(int idx, char* buffer)
+{
+    if (!LoadStringA(dllModule, idx, buffer, MAX_ERROR_LEN))
+        buffer[0] = 0;
+}
+
+
+#endif /* _WIN32 */
+
+
+/* Packet Buffer for reassembly list and ready list */
+typedef struct PacketBuffer {
+    word32  begin;      /* relative sequence begin */
+    word32  end;        /* relative sequence end   */
+    byte*   data;       /* actual data             */
+    struct PacketBuffer* next; /* next on reassembly list or ready list */
+} PacketBuffer;
+
+
+#ifdef HAVE_SNI
+
+/* NamedKey maps a SNI name to a specific private key */
+typedef struct NamedKey {
+    char             name[MAX_SERVER_NAME];      /* server DNS name */
+    word32           nameSz;                     /* size of server DNS name */
+    byte*            key;                        /* DER private key */
+    word32           keySz;                      /* size of DER private key */
+    struct NamedKey* next;                       /* for list */
+} NamedKey;
+
+#endif
+
+
+typedef struct IpAddrInfo {
+    int version;
+    union {
+        word32 ip4;
+        byte   ip6[16];
+    };
+} IpAddrInfo;
+
+
+/* Sniffer Server holds info for each server/port monitored */
+typedef struct SnifferServer {
+    SSL_CTX*       ctx;                          /* SSL context */
+    char           address[MAX_SERVER_ADDRESS];  /* passed in server address */
+    IpAddrInfo     server;                       /* network order address */
+    int            port;                         /* server port */
+#ifdef HAVE_SNI
+    NamedKey*      namedKeys;                    /* mapping of names and keys */
+    wolfSSL_Mutex  namedKeysMutex;               /* mutex for namedKey list */
+#endif
+    struct SnifferServer* next;                  /* for list */
+} SnifferServer;
+
+
+/* Session Flags */
+typedef struct Flags {
+    byte           side;            /* which end is current packet headed */
+    byte           serverCipherOn;  /* indicates whether cipher is active */
+    byte           clientCipherOn;  /* indicates whether cipher is active */
+    byte           resuming;        /* did this session come from resumption */
+    byte           cached;          /* have we cached this session yet */
+    byte           clientHello;     /* processed client hello yet, for SSLv2 */
+    byte           finCount;        /* get both FINs before removing */
+    byte           fatalError;      /* fatal error state */
+    byte           cliAckFault;     /* client acked unseen data from server */
+    byte           srvAckFault;     /* server acked unseen data from client */
+    byte           cliSkipPartial;  /* client skips partial data to catch up */
+    byte           srvSkipPartial;  /* server skips partial data to catch up */
+#ifdef HAVE_EXTENDED_MASTER
+    byte           expectEms;       /* expect extended master secret */
+#endif
+} Flags;
+
+
+/* Out of Order FIN capture */
+typedef struct FinCaputre {
+    word32 cliFinSeq;               /* client relative sequence FIN  0 is no */
+    word32 srvFinSeq;               /* server relative sequence FIN, 0 is no */
+    byte   cliCounted;              /* did we count yet, detects duplicates */
+    byte   srvCounted;              /* did we count yet, detects duplicates */
+} FinCaputre;
+
+
+typedef struct HsHashes {
+#ifndef NO_OLD_TLS
+#ifndef NO_SHA
+    wc_Sha hashSha;
+#endif
+#ifndef NO_MD5
+    wc_Md5 hashMd5;
+#endif
+#endif
+#ifndef NO_SHA256
+    wc_Sha256 hashSha256;
+#endif
+#ifdef WOLFSSL_SHA384
+    wc_Sha384 hashSha384;
+#endif
+} HsHashes;
+
+
+/* Sniffer Session holds info for each client/server SSL/TLS session */
+typedef struct SnifferSession {
+    SnifferServer* context;         /* server context */
+    SSL*           sslServer;       /* SSL server side decode */
+    SSL*           sslClient;       /* SSL client side decode */
+    IpAddrInfo     server;          /* server address in network byte order */
+    IpAddrInfo     client;          /* client address in network byte order */
+    word16         srvPort;         /* server port */
+    word16         cliPort;         /* client port */
+    word32         cliSeqStart;     /* client start sequence */
+    word32         srvSeqStart;     /* server start sequence */
+    word32         cliExpected;     /* client expected sequence (relative) */
+    word32         srvExpected;     /* server expected sequence (relative) */
+    FinCaputre     finCaputre;      /* retain out of order FIN s */
+    Flags          flags;           /* session flags */
+    time_t         lastUsed;          /* last used ticks */
+    word32         keySz;           /* size of the private key */
+    PacketBuffer*  cliReassemblyList; /* client out of order packets */
+    PacketBuffer*  srvReassemblyList; /* server out of order packets */
+    word32         cliReassemblyMemory; /* client packet memory used */
+    word32         srvReassemblyMemory; /* server packet memory used */
+    struct SnifferSession* next;      /* for hash table list */
+    byte*          ticketID;          /* mac ID of session ticket */
+#ifdef HAVE_SNI
+    const char*    sni;             /* server name indication */
+#endif
+#ifdef HAVE_EXTENDED_MASTER
+    HsHashes*       hash;
+#endif
+} SnifferSession;
+
+
+/* Sniffer Server List and mutex */
+static WOLFSSL_GLOBAL SnifferServer* ServerList = 0;
+static WOLFSSL_GLOBAL wolfSSL_Mutex ServerListMutex;
+
+
+/* Session Hash Table, mutex, and count */
+static WOLFSSL_GLOBAL SnifferSession* SessionTable[HASH_SIZE];
+static WOLFSSL_GLOBAL wolfSSL_Mutex SessionMutex;
+static WOLFSSL_GLOBAL int SessionCount = 0;
+
+/* Recovery of missed data switches and stats */
+static WOLFSSL_GLOBAL wolfSSL_Mutex RecoveryMutex; /* for stats */
+static WOLFSSL_GLOBAL int RecoveryEnabled    = 0;  /* global switch */
+static WOLFSSL_GLOBAL int MaxRecoveryMemory  = -1;
+                                           /* per session max recovery memory */
+static WOLFSSL_GLOBAL word32 MissedDataSessions = 0;
+                                            /* # of sessions with missed data */
+
+/* Connection Info Callback */
+static WOLFSSL_GLOBAL SSLConnCb ConnectionCb;
+static WOLFSSL_GLOBAL void* ConnectionCbCtx = NULL;
+
+#ifdef WOLFSSL_SNIFFER_STATS
+/* Sessions Statistics */
+static WOLFSSL_GLOBAL SSLStats SnifferStats;
+static WOLFSSL_GLOBAL wolfSSL_Mutex StatsMutex;
+#endif
+
+#ifdef WOLFSSL_SNIFFER_WATCH
+/* Watch Key Callback */
+static WOLFSSL_GLOBAL SSLWatchCb WatchCb;
+static WOLFSSL_GLOBAL void* WatchCbCtx = NULL;
+#endif
+
+#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
+/* Store Data Callback */
+static WOLFSSL_GLOBAL SSLStoreDataCb StoreDataCb;
+#endif
+
+
+static void UpdateMissedDataSessions(void)
+{
+    wc_LockMutex(&RecoveryMutex);
+    MissedDataSessions += 1;
+    wc_UnLockMutex(&RecoveryMutex);
+}
+
+
+#ifdef WOLFSSL_SNIFFER_STATS
+#define LOCK_STAT() do { wc_LockMutex(&StatsMutex); } while (0)
+#define UNLOCK_STAT() do { wc_UnLockMutex(&StatsMutex); } while (0)
+#define NOLOCK_ADD_TO_STAT(x,y) do { TraceStat(#x, y); x += y; } while (0)
+#define NOLOCK_INC_STAT(x) NOLOCK_ADD_TO_STAT(x,1)
+#define ADD_TO_STAT(x,y) do { LOCK_STAT(); \
+    NOLOCK_ADD_TO_STAT(x,y); UNLOCK_STAT(); } while (0)
+#define INC_STAT(x) do { LOCK_STAT(); \
+    NOLOCK_INC_STAT(x); UNLOCK_STAT(); } while (0)
+#endif
+
+
+#ifdef WOLF_CRYPTO_CB
+    static WOLFSSL_GLOBAL int CryptoDeviceId = INVALID_DEVID;
+#endif
+
+
+/* Initialize overall Sniffer */
+void ssl_InitSniffer(void)
+{
+    wolfSSL_Init();
+    wc_InitMutex(&ServerListMutex);
+    wc_InitMutex(&SessionMutex);
+    wc_InitMutex(&RecoveryMutex);
+#ifdef WOLFSSL_SNIFFER_STATS
+    XMEMSET(&SnifferStats, 0, sizeof(SSLStats));
+    wc_InitMutex(&StatsMutex);
+#endif
+#ifdef WOLF_CRYPTO_CB
+    #ifdef HAVE_INTEL_QA_SYNC
+    CryptoDeviceId = wc_CryptoCb_InitIntelQa();
+    if (INVALID_DEVID == CryptoDeviceId) {
+        printf("Couldn't init the Intel QA\n");
+    }
+    #endif
+    #ifdef HAVE_CAVIUM_OCTEON_SYNC
+    CryptoDeviceId = wc_CryptoCb_InitOcteon();
+    if (INVALID_DEVID == CryptoDeviceId) {
+        printf("Couldn't init the Intel QA\n");
+    }
+    #endif
+#endif
+}
+
+
+#ifdef HAVE_SNI
+
+/* Free Named Key and the zero out the private key it holds */
+static void FreeNamedKey(NamedKey* in)
+{
+    if (in) {
+        if (in->key) {
+            ForceZero(in->key, in->keySz);
+            XFREE(in->key, NULL, DYNAMIC_TYPE_X509);
+        }
+        XFREE(in, NULL, DYNAMIC_TYPE_SNIFFER_NAMED_KEY);
+    }
+}
+
+
+static void FreeNamedKeyList(NamedKey* in)
+{
+    NamedKey* next;
+
+    while (in) {
+        next = in->next;
+        FreeNamedKey(in);
+        in = next;
+    }
+}
+
+#endif
+
+
+/* Free Sniffer Server's resources/self */
+static void FreeSnifferServer(SnifferServer* srv)
+{
+    if (srv) {
+#ifdef HAVE_SNI
+        wc_LockMutex(&srv->namedKeysMutex);
+        FreeNamedKeyList(srv->namedKeys);
+        wc_UnLockMutex(&srv->namedKeysMutex);
+        wc_FreeMutex(&srv->namedKeysMutex);
+#endif
+        SSL_CTX_free(srv->ctx);
+    }
+    XFREE(srv, NULL, DYNAMIC_TYPE_SNIFFER_SERVER);
+}
+
+
+/* free PacketBuffer's resources/self */
+static void FreePacketBuffer(PacketBuffer* del)
+{
+    if (del) {
+        XFREE(del->data, NULL, DYNAMIC_TYPE_SNIFFER_PB_BUFFER);
+        XFREE(del, NULL, DYNAMIC_TYPE_SNIFFER_PB);
+    }
+}
+
+
+/* remove PacketBuffer List */
+static void FreePacketList(PacketBuffer* in)
+{
+    if (in) {
+        PacketBuffer* del;
+        PacketBuffer* packet = in;
+
+        while (packet) {
+            del = packet;
+            packet = packet->next;
+            FreePacketBuffer(del);
+        }
+    }
+}
+
+
+/* Free Sniffer Session's resources/self */
+static void FreeSnifferSession(SnifferSession* session)
+{
+    if (session) {
+        SSL_free(session->sslClient);
+        SSL_free(session->sslServer);
+
+        FreePacketList(session->cliReassemblyList);
+        FreePacketList(session->srvReassemblyList);
+
+        XFREE(session->ticketID, NULL, DYNAMIC_TYPE_SNIFFER_TICKET_ID);
+#ifdef HAVE_EXTENDED_MASTER
+        XFREE(session->hash, NULL, DYNAMIC_TYPE_HASHES);
+#endif
+    }
+    XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
+}
+
+
+/* Free overall Sniffer */
+void ssl_FreeSniffer(void)
+{
+    SnifferServer*  srv;
+    SnifferServer*  removeServer;
+    SnifferSession* session;
+    SnifferSession* removeSession;
+    int i;
+
+    wc_LockMutex(&ServerListMutex);
+    wc_LockMutex(&SessionMutex);
+
+    srv = ServerList;
+    while (srv) {
+        removeServer = srv;
+        srv = srv->next;
+        FreeSnifferServer(removeServer);
+    }
+
+    for (i = 0; i < HASH_SIZE; i++) {
+        session = SessionTable[i];
+        while (session) {
+            removeSession = session;
+            session = session->next;
+            FreeSnifferSession(removeSession);
+        }
+    }
+
+    wc_UnLockMutex(&SessionMutex);
+    wc_UnLockMutex(&ServerListMutex);
+
+    wc_FreeMutex(&RecoveryMutex);
+    wc_FreeMutex(&SessionMutex);
+    wc_FreeMutex(&ServerListMutex);
+
+#ifdef WOLF_CRYPTO_CB
+#ifdef HAVE_INTEL_QA_SYNC
+    wc_CryptoCb_CleanupIntelQa(&CryptoDeviceId);
+#endif
+#ifdef HAVE_CAVIUM_OCTEON_SYNC
+    wc_CryptoCb_CleanupOcteon(&CryptoDeviceId);
+#endif
+#endif
+
+    if (TraceFile) {
+        TraceOn = 0;
+        fclose(TraceFile);
+        TraceFile = NULL;
+    }
+
+    wolfSSL_Cleanup();
+}
+
+
+#ifdef HAVE_EXTENDED_MASTER
+
+static int HashInit(HsHashes* hash)
+{
+    int ret = 0;
+
+    XMEMSET(hash, 0, sizeof(HsHashes));
+
+#ifndef NO_OLD_TLS
+#ifndef NO_SHA
+    if (ret == 0)
+        ret = wc_InitSha(&hash->hashSha);
+#endif
+#ifndef NO_MD5
+    if (ret == 0) {
+        ret = wc_InitMd5(&hash->hashMd5);
+    }
+#endif
+#endif
+#ifndef NO_SHA256
+    if (ret == 0)
+        ret = wc_InitSha256(&hash->hashSha256);
+#endif
+#ifdef WOLFSSL_SHA384
+    if (ret == 0)
+        ret = wc_InitSha384(&hash->hashSha384);
+#endif
+
+    return ret;
+}
+
+
+static int HashUpdate(HsHashes* hash, const byte* input, int sz)
+{
+    int ret = 0;
+
+    input -= HANDSHAKE_HEADER_SZ;
+    sz += HANDSHAKE_HEADER_SZ;
+
+#ifndef NO_OLD_TLS
+#ifndef NO_SHA
+    if (ret == 0)
+        ret = wc_ShaUpdate(&hash->hashSha, input, sz);
+#endif
+#ifndef NO_MD5
+    if (ret == 0) {
+        ret = wc_Md5Update(&hash->hashMd5, input, sz);
+    }
+#endif
+#endif
+#ifndef NO_SHA256
+    if (ret == 0)
+        ret = wc_Sha256Update(&hash->hashSha256, input, sz);
+#endif
+#ifdef WOLFSSL_SHA384
+    if (ret == 0)
+        ret = wc_Sha384Update(&hash->hashSha384, input, sz);
+#endif
+
+    return ret;
+}
+
+
+static int HashCopy(HS_Hashes* d, HsHashes* s)
+{
+#ifndef NO_OLD_TLS
+#ifndef NO_SHA
+        XMEMCPY(&d->hashSha, &s->hashSha, sizeof(wc_Sha));
+#endif
+#ifndef NO_MD5
+        XMEMCPY(&d->hashMd5, &s->hashMd5, sizeof(wc_Md5));
+#endif
+#endif
+
+#ifndef NO_SHA256
+        XMEMCPY(&d->hashSha256, &s->hashSha256, sizeof(wc_Sha256));
+#endif
+#ifdef WOLFSSL_SHA384
+        XMEMCPY(&d->hashSha384, &s->hashSha384, sizeof(wc_Sha384));
+#endif
+
+    return 0;
+}
+
+#endif
+
+
+/* Initialize a SnifferServer */
+static void InitSnifferServer(SnifferServer* sniffer)
+{
+    XMEMSET(sniffer, 0, sizeof(SnifferServer));
+}
+
+
+/* Initialize session flags */
+static void InitFlags(Flags* flags)
+{
+    XMEMSET(flags, 0, sizeof(Flags));
+}
+
+
+/* Initialize FIN Capture */
+static void InitFinCapture(FinCaputre* cap)
+{
+    XMEMSET(cap, 0, sizeof(FinCaputre));
+}
+
+
+/* Initialize a Sniffer Session */
+static void InitSession(SnifferSession* session)
+{
+    XMEMSET(session, 0, sizeof(SnifferSession));
+    InitFlags(&session->flags);
+    InitFinCapture(&session->finCaputre);
+}
+
+
+/* IP Info from IP Header */
+typedef struct IpInfo {
+    int    length;        /* length of this header */
+    int    total;         /* total length of fragment */
+    IpAddrInfo src;       /* network order source address */
+    IpAddrInfo dst;       /* network order destination address */
+} IpInfo;
+
+
+/* TCP Info from TCP Header */
+typedef struct TcpInfo {
+    int    srcPort;       /* source port */
+    int    dstPort;       /* source port */
+    int    length;        /* length of this header */
+    word32 sequence;      /* sequence number */
+    word32 ackNumber;     /* ack number */
+    byte   fin;           /* FIN set */
+    byte   rst;           /* RST set */
+    byte   syn;           /* SYN set */
+    byte   ack;           /* ACK set */
+} TcpInfo;
+
+
+/* Tcp Pseudo Header for Checksum calculation */
+typedef struct TcpPseudoHdr {
+    word32  src;        /* source address */
+    word32  dst;        /* destination address */
+    byte    rsv;        /* reserved, always 0 */
+    byte    protocol;   /* IP protocol */
+    word16  length;     /* tcp header length + data length (doesn't include */
+                        /* pseudo header length) network order */
+} TcpPseudoHdr;
+
+
+/* Password Setting Callback */
+static int SetPassword(char* passwd, int sz, int rw, void* userdata)
+{
+    (void)rw;
+    XSTRNCPY(passwd, (const char*)userdata, sz);
+    return (int)XSTRLEN((const char*)userdata);
+}
+
+
+/* Ethernet Header */
+typedef struct EthernetHdr {
+    byte   dst[ETHER_IF_ADDR_LEN];    /* destination host address */
+    byte   src[ETHER_IF_ADDR_LEN];    /* source  host address */
+    word16 type;                      /* IP, ARP, etc */
+} EthernetHdr;
+
+
+/* IPv4 Header */
+typedef struct IpHdr {
+    byte    ver_hl;              /* version/header length */
+    byte    tos;                 /* type of service */
+    word16  length;              /* total length */
+    word16  id;                  /* identification */
+    word16  offset;              /* fragment offset field */
+    byte    ttl;                 /* time to live */
+    byte    protocol;            /* protocol */
+    word16  sum;                 /* checksum */
+    word32  src;                 /* source address */
+    word32  dst;                 /* destination address */
+} IpHdr;
+
+
+/* IPv6 Header */
+typedef struct Ip6Hdr {
+    byte    ver_hl;              /* version/traffic class high */
+    byte    tc_fl;               /* traffic class low/flow label high */
+    word16  fl;                  /* flow label low */
+    word16  length;              /* payload length */
+    byte    next_header;         /* next header (6 for TCP, any other skip) */
+    byte    hl;                  /* hop limit */
+    byte    src[16];             /* source address */
+    byte    dst[16];             /* destination address */
+} Ip6Hdr;
+
+
+/* IPv6 extension header */
+typedef struct Ip6ExtHdr {
+    byte next_header;            /* next header (6 for TCP, any other skip) */
+    byte length;                 /* length in 8-octet units - 1 */
+    byte reserved[6];
+} Ip6ExtHdr;
+
+
+#define IP_HL(ip)      ( (((ip)->ver_hl) & 0x0f) * 4)
+#define IP_V(ip)       ( ((ip)->ver_hl) >> 4)
+
+/* TCP Header */
+typedef struct TcpHdr {
+    word16  srcPort;            /* source port */
+    word16  dstPort;            /* destination port */
+    word32  sequence;           /* sequence number */
+    word32  ack;                /* acknowledgment number */
+    byte    offset;             /* data offset, reserved */
+    byte    flags;              /* option flags */
+    word16  window;             /* window */
+    word16  sum;                /* checksum */
+    word16  urgent;             /* urgent pointer */
+} TcpHdr;
+
+#define TCP_LEN(tcp)  ( (((tcp)->offset & 0xf0) >> 4) * 4)
+#define TCP_FIN 0x01
+#define TCP_SYN 0x02
+#define TCP_RST 0x04
+#define TCP_ACK 0x10
+
+
+
+
+
+/* Use platform specific GetError to write to trace file if tracing */
+static void Trace(int idx)
+{
+    if (TraceOn) {
+        char myBuffer[MAX_ERROR_LEN];
+        GetError(idx, myBuffer);
+        fprintf(TraceFile, "\t%s\n", myBuffer);
+#ifdef DEBUG_SNIFFER
+        fprintf(stderr,    "\t%s\n", myBuffer);
+#endif
+    }
+}
+
+
+/* Show TimeStamp for beginning of packet Trace */
+static void TraceHeader(void)
+{
+    if (TraceOn) {
+        time_t ticks = time(NULL);
+        fprintf(TraceFile, "\n%s", ctime(&ticks));
+    }
+}
+
+
+/* Show Set Server info for Trace */
+static void TraceSetServer(const char* srv, int port, const char* keyFile)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tTrying to install a new Sniffer Server with\n");
+        fprintf(TraceFile, "\tserver: %s, port: %d, keyFile: %s\n", srv, port,
+                                                                    keyFile);
+    }
+}
+
+
+#ifdef HAVE_SNI
+
+/* Show Set Named Server info for Trace */
+static void TraceSetNamedServer(const char* name,
+                                 const char* srv, int port, const char* keyFile)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tTrying to install a new Sniffer Server with\n");
+        fprintf(TraceFile, "\tname: %s, server: %s, port: %d, keyFile: %s\n",
+                                                      name, srv, port, keyFile);
+    }
+}
+
+#endif
+
+
+/* Trace got packet number */
+static void TracePacket(void)
+{
+    if (TraceOn) {
+        static word32 packetNumber = 0;
+        fprintf(TraceFile, "\tGot a Packet to decode, packet %u\n",
+                ++packetNumber);
+    }
+}
+
+
+/* Convert network byte order address into human readable */
+static const char* IpToS(int version, void* src, char* dst)
+{
+    return inet_ntop(version, src, dst, TRACE_MSG_SZ);
+}
+
+
+/* Show destination and source address from Ip Hdr for packet Trace */
+static void TraceIP(IpHdr* iphdr)
+{
+    if (TraceOn) {
+        char src[TRACE_MSG_SZ];
+        char dst[TRACE_MSG_SZ];
+        fprintf(TraceFile, "\tdst:%s src:%s\n",
+                IpToS(AF_INET, &iphdr->dst, dst),
+                IpToS(AF_INET, &iphdr->src, src));
+    }
+}
+
+
+/* Show destination and source address from Ip6Hdr for packet Trace */
+static void TraceIP6(Ip6Hdr* iphdr)
+{
+    if (TraceOn) {
+        char src[TRACE_MSG_SZ];
+        char dst[TRACE_MSG_SZ];
+        fprintf(TraceFile, "\tdst: %s src: %s\n",
+                IpToS(AF_INET6, iphdr->dst, dst),
+                IpToS(AF_INET6, iphdr->src, src));
+    }
+}
+
+
+/* Show destination and source port from Tcp Hdr for packet Trace */
+static void TraceTcp(TcpHdr* tcphdr)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tdstPort:%u srcPort:%u\n", ntohs(tcphdr->dstPort),
+                ntohs(tcphdr->srcPort));
+    }
+}
+
+
+/* Show sequence and payload length for Trace */
+static void TraceSequence(word32 seq, int len)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tSequence:%u, payload length:%d\n", seq, len);
+    }
+}
+
+
+/* Show sequence and payload length for Trace */
+static void TraceAck(word32 ack, word32 expected)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tAck:%u Expected:%u\n", ack, expected);
+    }
+}
+
+
+/* Show relative expected and relative received sequences */
+static void TraceRelativeSequence(word32 expected, word32 got)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tExpected sequence:%u, received sequence:%u\n",
+                expected, got);
+    }
+}
+
+
+/* Show server sequence startup from SYN */
+static void TraceServerSyn(word32 seq)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tServer SYN, Sequence Start:%u\n", seq);
+    }
+}
+
+
+/* Show client sequence startup from SYN */
+static void TraceClientSyn(word32 seq)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tClient SYN, Sequence Start:%u\n", seq);
+    }
+}
+
+
+/* Show client FIN capture */
+static void TraceClientFin(word32 finSeq, word32 relSeq)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tClient FIN capture:%u, current SEQ:%u\n",
+                finSeq, relSeq);
+    }
+}
+
+
+/* Show server FIN capture */
+static void TraceServerFin(word32 finSeq, word32 relSeq)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tServer FIN capture:%u, current SEQ:%u\n",
+                finSeq, relSeq);
+    }
+}
+
+
+/* Show number of SSL data bytes decoded, could be 0 (ok) */
+static void TraceGotData(int bytes)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\t%d bytes of SSL App data processed\n", bytes);
+    }
+}
+
+
+/* Show bytes added to old SSL App data */
+static void TraceAddedData(int newBytes, int existingBytes)
+{
+    if (TraceOn) {
+        fprintf(TraceFile,
+                "\t%d bytes added to %d existing bytes in User Buffer\n",
+                newBytes, existingBytes);
+    }
+}
+
+
+/* Show Stale Session */
+static void TraceStaleSession(void)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tFound a stale session\n");
+    }
+}
+
+
+/* Show Finding Stale Sessions */
+static void TraceFindingStale(void)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tTrying to find Stale Sessions\n");
+    }
+}
+
+
+/* Show Removed Session */
+static void TraceRemovedSession(void)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tRemoved it\n");
+    }
+}
+
+
+/* Show SSLInfo if provided and is valid. */
+static void TraceSessionInfo(SSLInfo* sslInfo)
+{
+    if (TraceOn) {
+        if (sslInfo != NULL && sslInfo->isValid) {
+            fprintf(TraceFile,
+                    "\tver:(%u %u) suiteId:(%02x %02x) suiteName:(%s) "
+                    #ifdef HAVE_SNI
+                    "sni:(%s) "
+                    #endif
+                    "keySize:(%u)\n",
+                    sslInfo->protocolVersionMajor,
+                    sslInfo->protocolVersionMinor,
+                    sslInfo->serverCipherSuite0,
+                    sslInfo->serverCipherSuite,
+                    sslInfo->serverCipherSuiteName,
+                    #ifdef HAVE_SNI
+                    sslInfo->serverNameIndication,
+                    #endif
+                    sslInfo->keySize);
+        }
+    }
+}
+
+
+#ifdef WOLFSSL_SNIFFER_STATS
+
+/* Show value added to a named statistic. */
+static void TraceStat(const char* name, int add)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tAdding %d to %s\n", add, name);
+    }
+}
+
+#endif
+
+
+/* Set user error string */
+static void SetError(int idx, char* error, SnifferSession* session, int fatal)
+{
+    GetError(idx, error);
+    Trace(idx);
+    if (session && fatal == FATAL_ERROR_STATE)
+        session->flags.fatalError = 1;
+}
+
+
+/* Compare IpAddrInfo structs */
+static WC_INLINE int MatchAddr(IpAddrInfo l, IpAddrInfo r)
+{
+    if (l.version == r.version) {
+        if (l.version == IPV4)
+            return (l.ip4 == r.ip4);
+        else if (l.version == IPV6)
+            return (0 == XMEMCMP(l.ip6, r.ip6, sizeof(l.ip6)));
+    }
+    return 0;
+}
+
+
+#ifndef WOLFSSL_SNIFFER_WATCH
+
+/* See if this IPV4 network order address has been registered */
+/* return 1 is true, 0 is false */
+static int IsServerRegistered(word32 addr)
+{
+    int ret = 0;     /* false */
+    SnifferServer* sniffer;
+
+    wc_LockMutex(&ServerListMutex);
+
+    sniffer = ServerList;
+    while (sniffer) {
+        if (sniffer->server.ip4 == addr) {
+            ret = 1;
+            break;
+        }
+        sniffer = sniffer->next;
+    }
+
+    wc_UnLockMutex(&ServerListMutex);
+
+    return ret;
+}
+
+
+/* See if this port has been registered to watch */
+/* See if this IPV4 network order address has been registered */
+/* return 1 is true, 0 is false */
+static int IsServerRegistered6(byte* addr)
+{
+    int ret = 0;     /* false */
+    SnifferServer* sniffer;
+
+    wc_LockMutex(&ServerListMutex);
+
+    sniffer = ServerList;
+    while (sniffer) {
+        if (sniffer->server.version == IPV6 &&
+                0 == XMEMCMP(sniffer->server.ip6, addr, sizeof(sniffer->server.ip6))) {
+            ret = 1;
+            break;
+        }
+        sniffer = sniffer->next;
+    }
+
+    wc_UnLockMutex(&ServerListMutex);
+
+    return ret;
+}
+
+
+/* See if this port has been registered to watch */
+/* return 1 is true, 0 is false */
+static int IsPortRegistered(word32 port)
+{
+    int ret = 0;    /* false */
+    SnifferServer* sniffer;
+
+    wc_LockMutex(&ServerListMutex);
+
+    sniffer = ServerList;
+    while (sniffer) {
+        if (sniffer->port == (int)port) {
+            ret = 1;
+            break;
+        }
+        sniffer = sniffer->next;
+    }
+
+    wc_UnLockMutex(&ServerListMutex);
+
+    return ret;
+}
+
+#endif
+
+
+/* Get SnifferServer from IP and Port */
+static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo)
+{
+    SnifferServer* sniffer;
+
+    wc_LockMutex(&ServerListMutex);
+
+    sniffer = ServerList;
+
+#ifndef WOLFSSL_SNIFFER_WATCH
+    while (sniffer) {
+        if (sniffer->port == tcpInfo->srcPort &&
+                MatchAddr(sniffer->server, ipInfo->src))
+            break;
+        if (sniffer->port == tcpInfo->dstPort &&
+                MatchAddr(sniffer->server, ipInfo->dst))
+            break;
+
+        sniffer = sniffer->next;
+    }
+#else
+    (void)ipInfo;
+    (void)tcpInfo;
+#endif
+
+    wc_UnLockMutex(&ServerListMutex);
+
+    return sniffer;
+}
+
+
+/* Hash the Session Info, return hash row */
+static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo)
+{
+    word32 hash = 1;
+
+    if (ipInfo->src.version == IPV4) {
+        hash *= ipInfo->src.ip4 * ipInfo->dst.ip4;
+    }
+    else if (ipInfo->src.version == IPV6) {
+        word32* x;
+        word32  y;
+        x = (word32*)ipInfo->src.ip6;
+        y = x[0] ^ x[1] ^ x[2] ^ x[3];
+        hash *= y;
+        x = (word32*)ipInfo->dst.ip6;
+        y = x[0] ^ x[1] ^ x[2] ^ x[3];
+        hash *= y;
+    }
+    hash *= tcpInfo->srcPort * tcpInfo->dstPort;
+
+    return hash % HASH_SIZE;
+}
+
+
+/* Get Existing SnifferSession from IP and Port */
+static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo)
+{
+    SnifferSession* session;
+    time_t          currTime = time(NULL);
+    word32          row = SessionHash(ipInfo, tcpInfo);
+
+    assert(row <= HASH_SIZE);
+
+    wc_LockMutex(&SessionMutex);
+
+    session = SessionTable[row];
+    while (session) {
+        if (MatchAddr(session->server, ipInfo->src) &&
+            MatchAddr(session->client, ipInfo->dst) &&
+                    session->srvPort == tcpInfo->srcPort &&
+                    session->cliPort == tcpInfo->dstPort)
+            break;
+
+        if (MatchAddr(session->client, ipInfo->src) &&
+            MatchAddr(session->server, ipInfo->dst) &&
+                    session->cliPort == tcpInfo->srcPort &&
+                    session->srvPort == tcpInfo->dstPort)
+            break;
+
+        session = session->next;
+    }
+
+    if (session)
+        session->lastUsed= currTime; /* keep session alive, remove stale will */
+                                     /* leave alone */
+    wc_UnLockMutex(&SessionMutex);
+
+    /* determine side */
+    if (session) {
+        if (MatchAddr(ipInfo->dst, session->server) &&
+            tcpInfo->dstPort == session->srvPort) {
+
+            session->flags.side = WOLFSSL_SERVER_END;
+        }
+        else {
+            session->flags.side = WOLFSSL_CLIENT_END;
+        }
+    }
+
+    return session;
+}
+
+
+#if defined(HAVE_SNI) || defined(WOLFSSL_SNIFFER_WATCH)
+
+static int LoadKeyFile(byte** keyBuf, word32* keyBufSz,
+                const char* keyFile, int typeKey,
+                const char* password)
+{
+    byte* loadBuf;
+    long fileSz = 0;
+    XFILE file;
+    int ret;
+
+    if (keyBuf == NULL || keyBufSz == NULL || keyFile == NULL) {
+        return -1;
+    }
+
+    file = XFOPEN(keyFile, "rb");
+    if (file == XBADFILE) return -1;
+    if(XFSEEK(file, 0, XSEEK_END) != 0) {
+        XFCLOSE(file);
+        return -1;
+    }
+    fileSz = XFTELL(file);
+    if (fileSz > MAX_WOLFSSL_FILE_SIZE || fileSz < 0) {
+        XFCLOSE(file);
+        return -1;
+    }
+    XREWIND(file);
+
+    loadBuf = (byte*)XMALLOC(fileSz, NULL, DYNAMIC_TYPE_FILE);
+    if (loadBuf == NULL) {
+        XFCLOSE(file);
+        return -1;
+    }
+
+    ret = (int)XFREAD(loadBuf, 1, fileSz, file);
+    XFCLOSE(file);
+
+    if (ret != fileSz) {
+        XFREE(loadBuf, NULL, DYNAMIC_TYPE_FILE);
+        return -1;
+    }
+
+    if (typeKey == WOLFSSL_FILETYPE_PEM) {
+        byte* saveBuf   = (byte*)XMALLOC(fileSz, NULL, DYNAMIC_TYPE_X509);
+        int   saveBufSz = 0;
+
+        ret = -1;
+        if (saveBuf != NULL) {
+            saveBufSz = wc_KeyPemToDer(loadBuf, (int)fileSz,
+                                                saveBuf, (int)fileSz, password);
+            if (saveBufSz < 0) {
+                saveBufSz = 0;
+                XFREE(saveBuf, NULL, DYNAMIC_TYPE_X509);
+                saveBuf = NULL;
+            }
+            else
+                ret = 0;
+        }
+
+        ForceZero(loadBuf, (word32)fileSz);
+        XFREE(loadBuf, NULL, DYNAMIC_TYPE_FILE);
+
+        if (saveBuf) {
+            *keyBuf = saveBuf;
+            *keyBufSz = (word32)saveBufSz;
+        }
+    }
+    else {
+        *keyBuf = loadBuf;
+        *keyBufSz = (word32)fileSz;
+    }
+
+    if (ret < 0) {
+        return -1;
+    }
+
+    return ret;
+}
+
+#endif
+
+
+#ifdef WOLFSSL_SNIFFER_WATCH
+
+static int CreateWatchSnifferServer(char* error)
+{
+    SnifferServer* sniffer;
+
+    sniffer = (SnifferServer*)XMALLOC(sizeof(SnifferServer), NULL,
+            DYNAMIC_TYPE_SNIFFER_SERVER);
+    if (sniffer == NULL) {
+        SetError(MEMORY_STR, error, NULL, 0);
+        return -1;
+    }
+    InitSnifferServer(sniffer);
+    sniffer->ctx = SSL_CTX_new(TLSv1_2_client_method());
+    if (!sniffer->ctx) {
+        SetError(MEMORY_STR, error, NULL, 0);
+        FreeSnifferServer(sniffer);
+        return -1;
+    }
+#ifdef WOLF_CRYPTO_CB
+    if (CryptoDeviceId != INVALID_DEVID)
+	    wolfSSL_CTX_SetDevId(sniffer->ctx, CryptoDeviceId);
+#endif
+    ServerList = sniffer;
+
+    return 0;
+}
+
+#endif
+
+
+static int SetNamedPrivateKey(const char* name, const char* address, int port,
+            const char* keyFile, int typeKey, const char* password, char* error)
+{
+    SnifferServer* sniffer;
+    int            ret;
+    int            type = (typeKey == FILETYPE_PEM) ? WOLFSSL_FILETYPE_PEM :
+                                                      WOLFSSL_FILETYPE_ASN1;
+    int            isNew = 0;
+    IpAddrInfo     serverIp;
+
+#ifdef HAVE_SNI
+    NamedKey* namedKey = NULL;
+#endif
+
+    (void)name;
+#ifdef HAVE_SNI
+    if (name != NULL) {
+        namedKey = (NamedKey*)XMALLOC(sizeof(NamedKey),
+                NULL, DYNAMIC_TYPE_SNIFFER_NAMED_KEY);
+        if (namedKey == NULL) {
+            SetError(MEMORY_STR, error, NULL, 0);
+            return -1;
+        }
+        XMEMSET(namedKey, 0, sizeof(NamedKey));
+
+        namedKey->nameSz = (word32)XSTRLEN(name);
+        if (namedKey->nameSz > sizeof(namedKey->name)-1)
+            namedKey->nameSz = sizeof(namedKey->name)-1;
+        XSTRNCPY(namedKey->name, name, namedKey->nameSz);
+        namedKey->name[MAX_SERVER_NAME-1] = '\0';
+
+        ret = LoadKeyFile(&namedKey->key, &namedKey->keySz,
+                          keyFile, type, password);
+        if (ret < 0) {
+            SetError(KEY_FILE_STR, error, NULL, 0);
+            FreeNamedKey(namedKey);
+            return -1;
+        }
+    }
+#endif
+
+    serverIp.version = IPV4;
+    serverIp.ip4 = inet_addr(address);
+    if (serverIp.ip4 == INADDR_NONE) {
+        if (inet_pton(AF_INET6, address, serverIp.ip6) == 1) {
+            serverIp.version = IPV6;
+        }
+    }
+    sniffer = ServerList;
+    while (sniffer != NULL &&
+            (!MatchAddr(sniffer->server, serverIp) || sniffer->port != port)) {
+        sniffer = sniffer->next;
+    }
+
+    if (sniffer == NULL) {
+        isNew = 1;
+        sniffer = (SnifferServer*)XMALLOC(sizeof(SnifferServer),
+                NULL, DYNAMIC_TYPE_SNIFFER_SERVER);
+        if (sniffer == NULL) {
+            SetError(MEMORY_STR, error, NULL, 0);
+#ifdef HAVE_SNI
+            FreeNamedKey(namedKey);
+#endif
+            return -1;
+        }
+        InitSnifferServer(sniffer);
+
+        XSTRNCPY(sniffer->address, address, MAX_SERVER_ADDRESS-1);
+        sniffer->address[MAX_SERVER_ADDRESS-1] = '\0';
+        sniffer->server = serverIp;
+        sniffer->port = port;
+
+        sniffer->ctx = SSL_CTX_new(TLSv1_2_client_method());
+        if (!sniffer->ctx) {
+            SetError(MEMORY_STR, error, NULL, 0);
+#ifdef HAVE_SNI
+            FreeNamedKey(namedKey);
+#endif
+            FreeSnifferServer(sniffer);
+            return -1;
+        }
+    }
+
+    if (name == NULL) {
+        if (password) {
+    #ifdef WOLFSSL_ENCRYPTED_KEYS
+            SSL_CTX_set_default_passwd_cb(sniffer->ctx, SetPassword);
+            SSL_CTX_set_default_passwd_cb_userdata(
+                                                 sniffer->ctx, (void*)password);
+    #endif
+        }
+        ret = SSL_CTX_use_PrivateKey_file(sniffer->ctx, keyFile, type);
+        if (ret != WOLFSSL_SUCCESS) {
+            SetError(KEY_FILE_STR, error, NULL, 0);
+            if (isNew)
+                FreeSnifferServer(sniffer);
+            return -1;
+        }
+	#ifdef WOLF_CRYPTO_CB
+		wolfSSL_CTX_SetDevId(sniffer->ctx, CryptoDeviceId);
+	#endif
+    }
+#ifdef HAVE_SNI
+    else {
+        wc_LockMutex(&sniffer->namedKeysMutex);
+        namedKey->next = sniffer->namedKeys;
+        sniffer->namedKeys = namedKey;
+        wc_UnLockMutex(&sniffer->namedKeysMutex);
+    }
+#endif
+
+    if (isNew) {
+        sniffer->next = ServerList;
+        ServerList = sniffer;
+    }
+
+    return 0;
+}
+
+
+#ifdef HAVE_SNI
+
+/* Sets the private key for a specific name, server and port  */
+/* returns 0 on success, -1 on error */
+int ssl_SetNamedPrivateKey(const char* name,
+                           const char* address, int port,
+                           const char* keyFile, int typeKey,
+                           const char* password, char* error)
+{
+    int ret;
+
+    TraceHeader();
+    TraceSetNamedServer(name, address, port, keyFile);
+
+    wc_LockMutex(&ServerListMutex);
+    ret = SetNamedPrivateKey(name, address, port, keyFile,
+                             typeKey, password, error);
+    wc_UnLockMutex(&ServerListMutex);
+
+    if (ret == 0)
+        Trace(NEW_SERVER_STR);
+
+    return ret;
+}
+
+#endif
+
+
+/* Sets the private key for a specific server and port  */
+/* returns 0 on success, -1 on error */
+int ssl_SetPrivateKey(const char* address, int port, const char* keyFile,
+                      int typeKey, const char* password, char* error)
+{
+    int ret;
+
+    TraceHeader();
+    TraceSetServer(address, port, keyFile);
+
+    wc_LockMutex(&ServerListMutex);
+    ret = SetNamedPrivateKey(NULL, address, port, keyFile,
+                             typeKey, password, error);
+    wc_UnLockMutex(&ServerListMutex);
+
+    if (ret == 0)
+        Trace(NEW_SERVER_STR);
+
+    return ret;
+}
+
+
+/* Check IP Header for IPV6, TCP, and a registered server address */
+/* returns 0 on success, -1 on error */
+static int CheckIp6Hdr(Ip6Hdr* iphdr, IpInfo* info, int length, char* error)
+{
+    int        version = IP_V(iphdr);
+    int        exthdrsz = IP6_HDR_SZ;
+
+    TraceIP6(iphdr);
+    Trace(IP_CHECK_STR);
+
+    if (version != IPV6) {
+        SetError(BAD_IPVER_STR, error, NULL, 0);
+        return -1;
+    }
+
+    /* Here, we need to move onto next header if not TCP. */
+    if (iphdr->next_header != TCP_PROTOCOL) {
+        Ip6ExtHdr* exthdr = (Ip6ExtHdr*)((byte*)iphdr + IP6_HDR_SZ);
+        do {
+            int hdrsz = (exthdr->length + 1) * 8;
+            if (hdrsz > length - exthdrsz) {
+                SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
+                return -1;
+            }
+            exthdrsz += hdrsz;
+            exthdr = (Ip6ExtHdr*)((byte*)exthdr + hdrsz);
+        }
+        while (exthdr->next_header != TCP_PROTOCOL &&
+                exthdr->next_header != NO_NEXT_HEADER);
+    }
+
+#ifndef WOLFSSL_SNIFFER_WATCH
+    if (!IsServerRegistered6(iphdr->src) && !IsServerRegistered6(iphdr->dst)) {
+        SetError(SERVER_NOT_REG_STR, error, NULL, 0);
+        return -1;
+    }
+#endif
+
+    info->length = exthdrsz;
+    info->total = ntohs(iphdr->length) + info->length;
+        /* IPv6 doesn't include its own header size in the length like v4. */
+    info->src.version = IPV6;
+    XMEMCPY(info->src.ip6, iphdr->src, sizeof(info->src.ip6));
+    info->dst.version = IPV6;
+    XMEMCPY(info->dst.ip6, iphdr->dst, sizeof(info->dst.ip6));
+
+    return 0;
+}
+
+
+/* Check IP Header for IPV4, TCP, and a registered server address */
+/* If header IPv6, pass to CheckIp6Hdr(). */
+/* returns 0 on success, -1 on error */
+static int CheckIpHdr(IpHdr* iphdr, IpInfo* info, int length, char* error)
+{
+    int    version = IP_V(iphdr);
+
+    if (version == IPV6)
+        return CheckIp6Hdr((Ip6Hdr*)iphdr, info, length, error);
+
+    TraceIP(iphdr);
+    Trace(IP_CHECK_STR);
+
+    if (version != IPV4) {
+        SetError(BAD_IPVER_STR, error, NULL, 0);
+        return -1;
+    }
+
+    if (iphdr->protocol != TCP_PROTOCOL) {
+        SetError(BAD_PROTO_STR, error, NULL, 0);
+        return -1;
+    }
+
+#ifndef WOLFSSL_SNIFFER_WATCH
+    if (!IsServerRegistered(iphdr->src) && !IsServerRegistered(iphdr->dst)) {
+        SetError(SERVER_NOT_REG_STR, error, NULL, 0);
+        return -1;
+    }
+#endif
+
+    info->length  = IP_HL(iphdr);
+    info->total   = ntohs(iphdr->length);
+    info->src.version = IPV4;
+    info->src.ip4 = iphdr->src;
+    info->dst.version = IPV4;
+    info->dst.ip4 = iphdr->dst;
+
+    if (info->total == 0)
+        info->total = length;  /* reassembled may be off */
+
+    return 0;
+}
+
+
+/* Check TCP Header for a registered port */
+/* returns 0 on success, -1 on error */
+static int CheckTcpHdr(TcpHdr* tcphdr, TcpInfo* info, char* error)
+{
+    TraceTcp(tcphdr);
+    Trace(TCP_CHECK_STR);
+    info->srcPort   = ntohs(tcphdr->srcPort);
+    info->dstPort   = ntohs(tcphdr->dstPort);
+    info->length    = TCP_LEN(tcphdr);
+    info->sequence  = ntohl(tcphdr->sequence);
+    info->fin       = tcphdr->flags & TCP_FIN;
+    info->rst       = tcphdr->flags & TCP_RST;
+    info->syn       = tcphdr->flags & TCP_SYN;
+    info->ack       = tcphdr->flags & TCP_ACK;
+    if (info->ack)
+        info->ackNumber = ntohl(tcphdr->ack);
+
+#ifndef WOLFSSL_SNIFFER_WATCH
+    if (!IsPortRegistered(info->srcPort) && !IsPortRegistered(info->dstPort)) {
+        SetError(SERVER_PORT_NOT_REG_STR, error, NULL, 0);
+        return -1;
+    }
+#else
+    (void)error;
+#endif
+
+    return 0;
+}
+
+
+/* Decode Record Layer Header */
+static int GetRecordHeader(const byte* input, RecordLayerHeader* rh, int* size)
+{
+    XMEMCPY(rh, input, RECORD_HEADER_SZ);
+    *size = (rh->length[0] << 8) | rh->length[1];
+
+    if (*size > (MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA))
+        return LENGTH_ERROR;
+
+    return 0;
+}
+
+
+/* Copies the session's information to the provided sslInfo. Skip copy if
+ * SSLInfo is not provided. */
+static void CopySessionInfo(SnifferSession* session, SSLInfo* sslInfo)
+{
+    if (NULL != sslInfo) {
+        XMEMSET(sslInfo, 0, sizeof(SSLInfo));
+
+        /* Pass back Session Info after we have processed the Server Hello. */
+        if (0 != session->sslServer->options.cipherSuite) {
+            const char* pCipher;
+
+            sslInfo->isValid = 1;
+            sslInfo->protocolVersionMajor = session->sslServer->version.major;
+            sslInfo->protocolVersionMinor = session->sslServer->version.minor;
+            sslInfo->serverCipherSuite0 =
+                        session->sslServer->options.cipherSuite0;
+            sslInfo->serverCipherSuite =
+                        session->sslServer->options.cipherSuite;
+
+            pCipher = wolfSSL_get_cipher(session->sslServer);
+            if (NULL != pCipher) {
+                XSTRNCPY((char*)sslInfo->serverCipherSuiteName, pCipher,
+                         sizeof(sslInfo->serverCipherSuiteName));
+                sslInfo->serverCipherSuiteName
+                         [sizeof(sslInfo->serverCipherSuiteName) - 1] = '\0';
+            }
+            sslInfo->keySize = session->keySz;
+            #ifdef HAVE_SNI
+            if (NULL != session->sni) {
+                XSTRNCPY((char*)sslInfo->serverNameIndication,
+                         session->sni, sizeof(sslInfo->serverNameIndication));
+                sslInfo->serverNameIndication
+                         [sizeof(sslInfo->serverNameIndication) - 1] = '\0';
+            }
+            #endif
+            TraceSessionInfo(sslInfo);
+        }
+    }
+}
+
+
+/* Call the session connection start callback. */
+static void CallConnectionCb(SnifferSession* session)
+{
+    if (ConnectionCb != NULL) {
+        SSLInfo info;
+        CopySessionInfo(session, &info);
+        ConnectionCb((const void*)session, &info, ConnectionCbCtx);
+    }
+}
+
+
+/* Process Client Key Exchange, RSA or static ECDH */
+static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
+                                    SnifferSession* session, char* error)
+{
+    word32 idx = 0;
+    int tryEcc = 0;
+    int ret;
+
+    if (session->sslServer->buffers.key == NULL ||
+        session->sslServer->buffers.key->buffer == NULL ||
+        session->sslServer->buffers.key->length == 0) {
+
+        SetError(RSA_KEY_MISSING_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+    {
+        RsaKey key;
+        int length;
+
+        ret = wc_InitRsaKey(&key, 0);
+        if (ret == 0) {
+            ret = wc_RsaPrivateKeyDecode(
+                    session->sslServer->buffers.key->buffer,
+                    &idx, &key, session->sslServer->buffers.key->length);
+            if (ret != 0) {
+                tryEcc = 1;
+                #ifndef HAVE_ECC
+                    SetError(RSA_DECODE_STR, error, session, FATAL_ERROR_STATE);
+                #else
+                    /* If we can do ECC, this isn't fatal. Not loading an ECC
+                     * key will be fatal, though. */
+                    SetError(RSA_DECODE_STR, error, session, 0);
+                #endif
+            }
+        }
+
+        if (ret == 0) {
+            length = wc_RsaEncryptSize(&key);
+            if (IsTLS(session->sslServer)) {
+                input += 2;     /* tls pre length */
+            }
+
+            if (length > *sslBytes) {
+                SetError(PARTIAL_INPUT_STR, error, session, FATAL_ERROR_STATE);
+                ret = -1;
+            }
+        }
+
+        #ifdef WC_RSA_BLINDING
+        if (ret == 0) {
+            ret = wc_RsaSetRNG(&key, session->sslServer->rng);
+            if (ret != 0) {
+                SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE);
+            }
+        }
+        #endif
+
+        if (ret == 0) {
+            session->keySz = length * WOLFSSL_BIT_SIZE;
+            /* length is the key size in bytes */
+            session->sslServer->arrays->preMasterSz = SECRET_LEN;
+
+            do {
+            #ifdef WOLFSSL_ASYNC_CRYPT
+                ret = wc_AsyncWait(ret, &key.asyncDev,
+                        WC_ASYNC_FLAG_CALL_AGAIN);
+            #endif
+                if (ret >= 0) {
+                    ret = wc_RsaPrivateDecrypt(input, length,
+                          session->sslServer->arrays->preMasterSecret,
+                          session->sslServer->arrays->preMasterSz, &key);
+                }
+            } while (ret == WC_PENDING_E);
+
+            if (ret != SECRET_LEN) {
+                SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE);
+            }
+        }
+
+        wc_FreeRsaKey(&key);
+    }
+
+    if (tryEcc) {
+#ifdef HAVE_ECC
+        ecc_key key;
+        ecc_key pubKey;
+        int length, keyInit = 0, pubKeyInit = 0;
+
+        idx = 0;
+        ret = wc_ecc_init(&key);
+        if (ret == 0) {
+            keyInit = 1;
+            ret = wc_ecc_init(&pubKey);
+        }
+        if (ret == 0) {
+            pubKeyInit = 1;
+            ret = wc_EccPrivateKeyDecode(
+                    session->sslServer->buffers.key->buffer,
+                    &idx, &key, session->sslServer->buffers.key->length);
+            if (ret != 0) {
+                SetError(ECC_DECODE_STR, error, session, FATAL_ERROR_STATE);
+            }
+        }
+
+        if (ret == 0) {
+            length = wc_ecc_size(&key) * 2 + 1;
+            /* The length should be 2 times the key size (x and y), plus 1
+             * for the type byte. */
+            if (IsTLS(session->sslServer)) {
+                input += 1; /* Don't include the TLS length for the key. */
+            }
+
+            if (length + 1 > *sslBytes) {
+                SetError(PARTIAL_INPUT_STR,
+                        error, session, FATAL_ERROR_STATE);
+                ret = -1;
+            }
+        }
+
+        if (ret == 0) {
+            ret = wc_ecc_import_x963_ex(input, length, &pubKey, ECC_CURVE_DEF);
+            if (ret != 0) {
+                SetError(ECC_PUB_DECODE_STR, error, session, FATAL_ERROR_STATE);
+            }
+        }
+
+        if (ret == 0) {
+            session->keySz = ((length - 1) / 2) * WOLFSSL_BIT_SIZE;
+            /* Length is in bytes. Subtract 1 for the ECC key type. Divide
+             * by two as the key is in (x,y) coordinates, where x and y are
+             * the same size, the key size. Convert from bytes to bits. */
+            session->sslServer->arrays->preMasterSz = ENCRYPT_LEN;
+
+            do {
+            #ifdef WOLFSSL_ASYNC_CRYPT
+                ret = wc_AsyncWait(ret, &key.asyncDev,
+                        WC_ASYNC_FLAG_CALL_AGAIN);
+            #endif
+                if (ret >= 0) {
+                    ret = wc_ecc_shared_secret(&key, &pubKey,
+                          session->sslServer->arrays->preMasterSecret,
+                          &session->sslServer->arrays->preMasterSz);
+                }
+            } while (ret == WC_PENDING_E);
+        }
+
+#ifdef WOLFSSL_SNIFFER_STATS
+        if (ret != 0)
+            INC_STAT(SnifferStats.sslKeyFails);
+#endif
+
+        if (keyInit)
+            wc_ecc_free(&key);
+        if (pubKeyInit)
+            wc_ecc_free(&pubKey);
+#endif
+    }
+
+    /* store for client side as well */
+    XMEMCPY(session->sslClient->arrays->preMasterSecret,
+           session->sslServer->arrays->preMasterSecret,
+           session->sslServer->arrays->preMasterSz);
+    session->sslClient->arrays->preMasterSz =
+        session->sslServer->arrays->preMasterSz;
+
+    #ifdef SHOW_SECRETS
+    {
+        word32 i;
+        printf("pre master secret: ");
+        for (i = 0; i < session->sslServer->arrays->preMasterSz; i++)
+            printf("%02x", session->sslServer->arrays->preMasterSecret[i]);
+        printf("\n");
+    }
+    #endif
+
+    if (SetCipherSpecs(session->sslServer) != 0) {
+        SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+    if (SetCipherSpecs(session->sslClient) != 0) {
+        SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+    ret  = MakeMasterSecret(session->sslServer);
+    ret += MakeMasterSecret(session->sslClient);
+    ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE);
+    ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE);
+
+    if (ret != 0) {
+        SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+#ifdef SHOW_SECRETS
+    {
+        int i;
+        printf("server master secret: ");
+        for (i = 0; i < SECRET_LEN; i++)
+            printf("%02x", session->sslServer->arrays->masterSecret[i]);
+        printf("\n");
+
+        printf("client master secret: ");
+        for (i = 0; i < SECRET_LEN; i++)
+            printf("%02x", session->sslClient->arrays->masterSecret[i]);
+        printf("\n");
+
+        printf("server suite = %d\n", session->sslServer->options.cipherSuite);
+        printf("client suite = %d\n", session->sslClient->options.cipherSuite);
+    }
+#endif
+
+    CallConnectionCb(session);
+
+    return ret;
+}
+
+
+/* Process Session Ticket */
+static int ProcessSessionTicket(const byte* input, int* sslBytes,
+                                SnifferSession* session, char* error)
+{
+    word16 len;
+
+    /* make sure can read through hint and len */
+    if (TICKET_HINT_LEN + LENGTH_SZ > *sslBytes) {
+        SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+    input     += TICKET_HINT_LEN;  /* skip over hint */
+    *sslBytes -= TICKET_HINT_LEN;
+
+    len = (word16)((input[0] << 8) | input[1]);
+    input     += LENGTH_SZ;
+    *sslBytes -= LENGTH_SZ;
+
+    /* make sure can read through ticket */
+    if (len > *sslBytes || len < ID_LEN) {
+        SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+    /* store session with macID as sessionID */
+    session->sslServer->options.haveSessionId = 1;
+    XMEMCPY(session->sslServer->arrays->sessionID, input + len - ID_LEN,ID_LEN);
+
+    return 0;
+}
+
+
+/* Process Server Hello */
+static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
+                              SnifferSession* session, char* error)
+{
+    ProtocolVersion pv;
+    byte            b, b0;
+    int             toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
+    int             doResume     = 0;
+    int             initialBytes = *sslBytes;
+
+    (void)msgSz;
+    (void)initialBytes;
+
+    /* make sure we didn't miss ClientHello */
+    if (session->flags.clientHello == 0) {
+        SetError(MISSED_CLIENT_HELLO_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+    /* make sure can read through session len */
+    if (toRead > *sslBytes) {
+        SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+    XMEMCPY(&pv, input, VERSION_SZ);
+    input     += VERSION_SZ;
+    *sslBytes -= VERSION_SZ;
+
+    session->sslServer->version = pv;
+    session->sslClient->version = pv;
+
+    XMEMCPY(session->sslServer->arrays->serverRandom, input, RAN_LEN);
+    XMEMCPY(session->sslClient->arrays->serverRandom, input, RAN_LEN);
+    input    += RAN_LEN;
+    *sslBytes -= RAN_LEN;
+
+    b = *input++;
+    *sslBytes -= 1;
+
+    /* make sure can read through compression */
+    if ( (b + SUITE_LEN + ENUM_LEN) > *sslBytes) {
+        SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+    if (b) {
+        XMEMCPY(session->sslServer->arrays->sessionID, input, ID_LEN);
+        session->sslServer->options.haveSessionId = 1;
+    }
+    input     += b;
+    *sslBytes -= b;
+
+    /* cipher suite */
+    b0 = *input++;  /* first byte, ECC or not */
+    session->sslServer->options.cipherSuite0 = b0;
+    session->sslClient->options.cipherSuite0 = b0;
+    b = *input++;
+    session->sslServer->options.cipherSuite = b;
+    session->sslClient->options.cipherSuite = b;
+    *sslBytes -= SUITE_LEN;
+
+#ifdef WOLFSSL_SNIFFER_STATS
+    {
+        const CipherSuiteInfo* suites = GetCipherNames();
+        int suitesSz = GetCipherNamesSize();
+        int match = 0;
+
+        while (suitesSz) {
+            if (b0 == suites->cipherSuite0 && b == suites->cipherSuite) {
+                match = 1;
+                break;
+            }
+            suites++;
+            suitesSz--;
+        }
+        if (!match)
+            INC_STAT(SnifferStats.sslCiphersUnsupported);
+    }
+#endif /* WOLFSSL_SNIFFER_STATS */
+
+    /* compression */
+    b = *input++;
+    *sslBytes -= ENUM_LEN;
+
+    if (b) {
+        SetError(BAD_COMPRESSION_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+#ifdef HAVE_EXTENDED_MASTER
+    /* extensions */
+    if ((initialBytes - *sslBytes) < msgSz) {
+        word16 len;
+
+        /* skip extensions until extended master secret */
+        /* make sure can read len */
+        if (SUITE_LEN > *sslBytes) {
+            SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+        len = (word16)((input[0] << 8) | input[1]);
+        input     += SUITE_LEN;
+        *sslBytes -= SUITE_LEN;
+        /* make sure can read through all extensions */
+        if (len > *sslBytes) {
+            SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+
+        while (len >= EXT_TYPE_SZ + LENGTH_SZ) {
+            byte   extType[EXT_TYPE_SZ];
+            word16 extLen;
+
+            extType[0] = input[0];
+            extType[1] = input[1];
+            input     += EXT_TYPE_SZ;
+            *sslBytes -= EXT_TYPE_SZ;
+
+            extLen = (word16)((input[0] << 8) | input[1]);
+            input     += LENGTH_SZ;
+            *sslBytes -= LENGTH_SZ;
+
+            /* make sure can read through individual extension */
+            if (extLen > *sslBytes) {
+                SetError(SERVER_HELLO_INPUT_STR, error, session,
+                         FATAL_ERROR_STATE);
+                return -1;
+            }
+
+            if (extType[0] == 0x00 && extType[1] == EXT_MASTER_SECRET) {
+                session->flags.expectEms = 1;
+            }
+
+            input     += extLen;
+            *sslBytes -= extLen;
+            len       -= extLen + EXT_TYPE_SZ + LENGTH_SZ;
+        }
+    }
+
+    if (!session->flags.expectEms) {
+        XFREE(session->hash, NULL, DYNAMIC_TYPE_HASHES);
+        session->hash = NULL;
+    }
+#endif
+
+    if (session->sslServer->options.haveSessionId) {
+        if (XMEMCMP(session->sslServer->arrays->sessionID,
+                    session->sslClient->arrays->sessionID, ID_LEN) == 0)
+            doResume = 1;
+    }
+    else if (session->sslClient->options.haveSessionId == 0 &&
+             session->sslServer->options.haveSessionId == 0 &&
+             session->ticketID)
+        doResume = 1;
+
+    if (session->ticketID && doResume) {
+        /* use ticketID to retrieve from session, prefer over sessionID */
+        XMEMCPY(session->sslServer->arrays->sessionID,session->ticketID,ID_LEN);
+        session->sslServer->options.haveSessionId = 1;  /* may not have
+                                                           actual sessionID */
+    }
+
+    if (doResume ) {
+        int ret = 0;
+        SSL_SESSION* resume = GetSession(session->sslServer,
+                                  session->sslServer->arrays->masterSecret, 0);
+        if (resume == NULL) {
+#ifdef WOLFSSL_SNIFFER_STATS
+            INC_STAT(SnifferStats.sslResumeMisses);
+#endif
+            SetError(BAD_SESSION_RESUME_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+        /* make sure client has master secret too */
+        XMEMCPY(session->sslClient->arrays->masterSecret,
+               session->sslServer->arrays->masterSecret, SECRET_LEN);
+        session->flags.resuming = 1;
+
+        Trace(SERVER_DID_RESUMPTION_STR);
+#ifdef WOLFSSL_SNIFFER_STATS
+        INC_STAT(SnifferStats.sslResumedConns);
+        INC_STAT(SnifferStats.sslResumptionValid);
+#endif
+        if (SetCipherSpecs(session->sslServer) != 0) {
+            SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+
+        if (SetCipherSpecs(session->sslClient) != 0) {
+            SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+
+        if (session->sslServer->options.tls) {
+            ret =  DeriveTlsKeys(session->sslServer);
+            ret += DeriveTlsKeys(session->sslClient);
+        }
+        else {
+            ret =  DeriveKeys(session->sslServer);
+            ret += DeriveKeys(session->sslClient);
+        }
+        ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE);
+        ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE);
+
+        if (ret != 0) {
+            SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+    }
+    else {
+#ifdef WOLFSSL_SNIFFER_STATS
+        INC_STAT(SnifferStats.sslStandardConns);
+#endif
+    }
+#ifdef SHOW_SECRETS
+    {
+        int i;
+        printf("cipher suite = 0x%02x\n",
+               session->sslServer->options.cipherSuite);
+        printf("server random: ");
+        for (i = 0; i < RAN_LEN; i++)
+            printf("%02x", session->sslServer->arrays->serverRandom[i]);
+        printf("\n");
+    }
+#endif
+    return 0;
+}
+
+
+/* Process normal Client Hello */
+static int ProcessClientHello(const byte* input, int* sslBytes,
+                              SnifferSession* session, char* error)
+{
+    byte   bLen;
+    word16 len;
+    int    toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
+
+#ifdef HAVE_SNI
+    {
+        byte name[MAX_SERVER_NAME];
+        word32 nameSz = sizeof(name);
+        int ret;
+
+        ret = wolfSSL_SNI_GetFromBuffer(
+                             input - HANDSHAKE_HEADER_SZ - RECORD_HEADER_SZ,
+                             *sslBytes + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ,
+                             WOLFSSL_SNI_HOST_NAME, name, &nameSz);
+
+        if (ret == WOLFSSL_SUCCESS) {
+            NamedKey* namedKey;
+
+            if (nameSz > sizeof(name) - 1)
+                nameSz = sizeof(name) - 1;
+            name[nameSz] = 0;
+            wc_LockMutex(&session->context->namedKeysMutex);
+            namedKey = session->context->namedKeys;
+            while (namedKey != NULL) {
+                if (nameSz == namedKey->nameSz &&
+                           XSTRNCMP((char*)name, namedKey->name, nameSz) == 0) {
+                    if (wolfSSL_use_PrivateKey_buffer(session->sslServer,
+                                            namedKey->key, namedKey->keySz,
+                                            WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) {
+                        wc_UnLockMutex(&session->context->namedKeysMutex);
+                        SetError(CLIENT_HELLO_LATE_KEY_STR, error, session,
+                                                             FATAL_ERROR_STATE);
+                        return -1;
+                    }
+                    session->sni = namedKey->name;
+                    break;
+                }
+                else
+                    namedKey = namedKey->next;
+            }
+            wc_UnLockMutex(&session->context->namedKeysMutex);
+        }
+    }
+#endif
+
+    session->flags.clientHello = 1;  /* don't process again */
+
+    /* make sure can read up to session len */
+    if (toRead > *sslBytes) {
+        SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+    /* skip, get negotiated one from server hello */
+    input     += VERSION_SZ;
+    *sslBytes -= VERSION_SZ;
+
+    XMEMCPY(session->sslServer->arrays->clientRandom, input, RAN_LEN);
+    XMEMCPY(session->sslClient->arrays->clientRandom, input, RAN_LEN);
+
+    input     += RAN_LEN;
+    *sslBytes -= RAN_LEN;
+
+    /* store session in case trying to resume */
+    bLen = *input++;
+    *sslBytes -= ENUM_LEN;
+    if (bLen) {
+        if (ID_LEN > *sslBytes) {
+            SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+        Trace(CLIENT_RESUME_TRY_STR);
+        XMEMCPY(session->sslClient->arrays->sessionID, input, ID_LEN);
+        session->sslClient->options.haveSessionId = 1;
+    }
+#ifdef SHOW_SECRETS
+    {
+        int i;
+        printf("client random: ");
+        for (i = 0; i < RAN_LEN; i++)
+            printf("%02x", session->sslServer->arrays->clientRandom[i]);
+        printf("\n");
+    }
+#endif
+
+    input     += bLen;
+    *sslBytes -= bLen;
+
+    /* skip cipher suites */
+    /* make sure can read len */
+    if (SUITE_LEN > *sslBytes) {
+        SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+    len = (word16)((input[0] << 8) | input[1]);
+    input     += SUITE_LEN;
+    *sslBytes -= SUITE_LEN;
+    /* make sure can read suites + comp len */
+    if (len + ENUM_LEN > *sslBytes) {
+        SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+    input     += len;
+    *sslBytes -= len;
+
+    /* skip compression */
+    bLen       = *input++;
+    *sslBytes -= ENUM_LEN;
+    /* make sure can read len */
+    if (bLen > *sslBytes) {
+        SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+    input     += bLen;
+    *sslBytes -= bLen;
+
+    if (*sslBytes == 0) {
+        /* no extensions */
+        return 0;
+    }
+
+    /* skip extensions until session ticket */
+    /* make sure can read len */
+    if (SUITE_LEN > *sslBytes) {
+        SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+    len = (word16)((input[0] << 8) | input[1]);
+    input     += SUITE_LEN;
+    *sslBytes -= SUITE_LEN;
+    /* make sure can read through all extensions */
+    if (len > *sslBytes) {
+        SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+    while (len >= EXT_TYPE_SZ + LENGTH_SZ) {
+        byte   extType[EXT_TYPE_SZ];
+        word16 extLen;
+
+        extType[0] = input[0];
+        extType[1] = input[1];
+        input     += EXT_TYPE_SZ;
+        *sslBytes -= EXT_TYPE_SZ;
+
+        extLen = (word16)((input[0] << 8) | input[1]);
+        input     += LENGTH_SZ;
+        *sslBytes -= LENGTH_SZ;
+
+        /* make sure can read through individual extension */
+        if (extLen > *sslBytes) {
+            SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+
+        if (extType[0] == 0x00 && extType[1] == TICKET_EXT_ID) {
+
+            /* make sure can read through ticket if there is a non blank one */
+            if (extLen && extLen < ID_LEN) {
+                SetError(CLIENT_HELLO_INPUT_STR, error, session,
+                         FATAL_ERROR_STATE);
+                return -1;
+            }
+
+            if (extLen) {
+                if (session->ticketID == 0) {
+                    session->ticketID = (byte*)XMALLOC(ID_LEN,
+                            NULL, DYNAMIC_TYPE_SNIFFER_TICKET_ID);
+                    if (session->ticketID == 0) {
+                        SetError(MEMORY_STR, error, session,
+                                 FATAL_ERROR_STATE);
+                        return -1;
+                    }
+                }
+                XMEMCPY(session->ticketID, input + extLen - ID_LEN, ID_LEN);
+            }
+        }
+
+        input     += extLen;
+        *sslBytes -= extLen;
+        len       -= extLen + EXT_TYPE_SZ + LENGTH_SZ;
+    }
+
+    return 0;
+}
+
+
+#ifdef WOLFSSL_SNIFFER_WATCH
+
+/* Process Certificate */
+static int ProcessCertificate(const byte* input, int* sslBytes,
+        SnifferSession* session, char* error)
+{
+    Sha256 sha;
+    const byte* certChain;
+    word32 certChainSz;
+    word32 certSz;
+    int ret;
+    byte digest[SHA256_DIGEST_SIZE];
+
+    /* If the receiver is the server, this is the client certificate message,
+     * and it should be ignored at this point. */
+    if (session->flags.side == WOLFSSL_SERVER_END)
+        return 0;
+
+    if (WatchCb == NULL) {
+        SetError(WATCH_CB_MISSING_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+    if (*sslBytes < CERT_HEADER_SZ) {
+        SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+    ato24(input, &certChainSz);
+    *sslBytes -= CERT_HEADER_SZ;
+    input += CERT_HEADER_SZ;
+
+    if (*sslBytes < (int)certChainSz) {
+        SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+    certChain = input;
+
+    ato24(input, &certSz);
+    input += OPAQUE24_LEN;
+    if (*sslBytes < (int)certSz) {
+        SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+    *sslBytes -= certChainSz;
+
+    ret = wc_InitSha256(&sha);
+    if (ret == 0)
+        ret = wc_Sha256Update(&sha, input, certSz);
+    if (ret == 0)
+        ret = wc_Sha256Final(&sha, digest);
+    if (ret != 0) {
+        SetError(WATCH_HASH_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+    ret = WatchCb((void*)session, digest, sizeof(digest),
+            certChain, certChainSz, WatchCbCtx, error);
+    if (ret != 0) {
+#ifdef WOLFSSL_SNIFFER_STATS
+        INC_STAT(SnifferStats.sslKeysUnmatched);
+#endif
+        SetError(WATCH_FAIL_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+    else {
+#ifdef WOLFSSL_SNIFFER_STATS
+        INC_STAT(SnifferStats.sslKeyMatches);
+#endif
+    }
+
+    return 0;
+}
+
+#endif
+
+
+/* Process Finished */
+static int ProcessFinished(const byte* input, int size, int* sslBytes,
+                           SnifferSession* session, char* error)
+{
+    SSL*   ssl;
+    word32 inOutIdx = 0;
+    int    ret;
+
+    if (session->flags.side == WOLFSSL_SERVER_END)
+        ssl = session->sslServer;
+    else
+        ssl = session->sslClient;
+
+    ret = DoFinished(ssl, input, &inOutIdx, (word32) size, (word32) *sslBytes,
+                                                                         SNIFF);
+    *sslBytes -= (int)inOutIdx;
+
+    if (ret < 0) {
+        SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE);
+        return ret;
+    }
+
+    if (ret == 0 && session->flags.cached == 0) {
+        if (session->sslServer->options.haveSessionId) {
+            WOLFSSL_SESSION* sess = GetSession(session->sslServer, NULL, 0);
+            if (sess == NULL) {
+                AddSession(session->sslServer);  /* don't re add */
+#ifdef WOLFSSL_SNIFFER_STATS
+                INC_STAT(SnifferStats.sslResumptionInserts);
+#endif
+            }
+            session->flags.cached = 1;
+         }
+    }
+
+    /* If receiving a finished message from one side, free the resources
+     * from the other side's tracker. */
+    if (session->flags.side == WOLFSSL_SERVER_END)
+        FreeHandshakeResources(session->sslClient);
+    else
+        FreeHandshakeResources(session->sslServer);
+
+    return ret;
+}
+
+
+/* Process HandShake input */
+static int DoHandShake(const byte* input, int* sslBytes,
+                       SnifferSession* session, char* error)
+{
+    byte type;
+    int  size;
+    int  ret = 0;
+    int  startBytes;
+
+    if (*sslBytes < HANDSHAKE_HEADER_SZ) {
+        SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+    type = input[0];
+    size = (input[1] << 16) | (input[2] << 8) | input[3];
+
+    input     += HANDSHAKE_HEADER_SZ;
+    *sslBytes -= HANDSHAKE_HEADER_SZ;
+    startBytes = *sslBytes;
+
+    if (*sslBytes < size) {
+        Trace(SPLIT_HANDSHAKE_MSG_STR);
+        *sslBytes = 0;
+        return ret;
+    }
+
+    /* A session's arrays are released when the handshake is completed. */
+    if (session->sslServer->arrays == NULL &&
+        session->sslClient->arrays == NULL) {
+
+        SetError(NO_SECURE_RENEGOTIATION, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+#ifdef HAVE_EXTENDED_MASTER
+    if (session->hash) {
+        if (HashUpdate(session->hash, input, size) != 0) {
+            SetError(EXTENDED_MASTER_HASH_STR, error,
+                     session, FATAL_ERROR_STATE);
+            return -1;
+        }
+    }
+#endif
+
+    switch (type) {
+        case hello_verify_request:
+            Trace(GOT_HELLO_VERIFY_STR);
+            break;
+        case hello_request:
+            Trace(GOT_HELLO_REQUEST_STR);
+            break;
+        case session_ticket:
+            Trace(GOT_SESSION_TICKET_STR);
+            ret = ProcessSessionTicket(input, sslBytes, session, error);
+            break;
+        case server_hello:
+            Trace(GOT_SERVER_HELLO_STR);
+            ret = ProcessServerHello(size, input, sslBytes, session, error);
+            break;
+        case certificate_request:
+            Trace(GOT_CERT_REQ_STR);
+            break;
+        case server_key_exchange:
+#ifdef WOLFSSL_SNIFFER_STATS
+            INC_STAT(SnifferStats.sslEphemeralMisses);
+#endif
+            Trace(GOT_SERVER_KEY_EX_STR);
+            /* can't know temp key passively */
+            SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
+            ret = -1;
+            break;
+        case certificate:
+            Trace(GOT_CERT_STR);
+            if (session->flags.side == WOLFSSL_SERVER_END) {
+#ifdef WOLFSSL_SNIFFER_STATS
+                INC_STAT(SnifferStats.sslClientAuthConns);
+#endif
+            }
+#ifdef WOLFSSL_SNIFFER_WATCH
+            ret = ProcessCertificate(input, sslBytes, session, error);
+#endif
+            break;
+        case server_hello_done:
+            Trace(GOT_SERVER_HELLO_DONE_STR);
+            break;
+        case finished:
+            Trace(GOT_FINISHED_STR);
+            ret = ProcessFinished(input, size, sslBytes, session, error);
+            break;
+        case client_hello:
+            Trace(GOT_CLIENT_HELLO_STR);
+            ret = ProcessClientHello(input, sslBytes, session, error);
+            break;
+        case client_key_exchange:
+            Trace(GOT_CLIENT_KEY_EX_STR);
+#ifdef HAVE_EXTENDED_MASTER
+            if (session->flags.expectEms && session->hash != NULL) {
+                if (HashCopy(session->sslServer->hsHashes,
+                             session->hash) == 0 &&
+                    HashCopy(session->sslClient->hsHashes,
+                             session->hash) == 0) {
+
+                    session->sslServer->options.haveEMS = 1;
+                    session->sslClient->options.haveEMS = 1;
+                }
+                else {
+                    SetError(EXTENDED_MASTER_HASH_STR, error,
+                             session, FATAL_ERROR_STATE);
+                    ret = -1;
+                }
+                XMEMSET(session->hash, 0, sizeof(HsHashes));
+                XFREE(session->hash, NULL, DYNAMIC_TYPE_HASHES);
+                session->hash = NULL;
+            }
+            else {
+                session->sslServer->options.haveEMS = 0;
+                session->sslClient->options.haveEMS = 0;
+            }
+#endif
+            if (ret == 0)
+                ret = ProcessClientKeyExchange(input, sslBytes, session, error);
+            break;
+        case certificate_verify:
+            Trace(GOT_CERT_VER_STR);
+            break;
+        case certificate_status:
+            Trace(GOT_CERT_STATUS_STR);
+            break;
+        default:
+            SetError(GOT_UNKNOWN_HANDSHAKE_STR, error, session, 0);
+            return -1;
+    }
+
+    *sslBytes = startBytes - size;  /* actual bytes of full process */
+
+    return ret;
+}
+
+
+/* Decrypt input into plain output, 0 on success */
+static int Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz)
+{
+    int ret = 0;
+
+    (void)output;
+    (void)input;
+    (void)sz;
+
+    switch (ssl->specs.bulk_cipher_algorithm) {
+        #ifdef BUILD_ARC4
+        case wolfssl_rc4:
+            wc_Arc4Process(ssl->decrypt.arc4, output, input, sz);
+            break;
+        #endif
+
+        #ifdef BUILD_DES3
+        case wolfssl_triple_des:
+            ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, output, input, sz);
+            break;
+        #endif
+
+        #ifdef BUILD_AES
+        case wolfssl_aes:
+            ret = wc_AesCbcDecrypt(ssl->decrypt.aes, output, input, sz);
+            break;
+        #endif
+
+        #ifdef HAVE_HC128
+        case wolfssl_hc128:
+            wc_Hc128_Process(ssl->decrypt.hc128, output, input, sz);
+            break;
+        #endif
+
+        #ifdef BUILD_RABBIT
+        case wolfssl_rabbit:
+            wc_RabbitProcess(ssl->decrypt.rabbit, output, input, sz);
+            break;
+        #endif
+
+        #ifdef HAVE_CAMELLIA
+        case wolfssl_camellia:
+            wc_CamelliaCbcDecrypt(ssl->decrypt.cam, output, input, sz);
+            break;
+        #endif
+
+        #ifdef HAVE_IDEA
+        case wolfssl_idea:
+            wc_IdeaCbcDecrypt(ssl->decrypt.idea, output, input, sz);
+            break;
+        #endif
+
+        #ifdef HAVE_AESGCM
+        case wolfssl_aes_gcm:
+            if (sz >= (word32)(AESGCM_EXP_IV_SZ + ssl->specs.aead_mac_size))
+            {
+                /* scratch buffer, sniffer ignores auth tag*/
+                byte authTag[WOLFSSL_MIN_AUTH_TAG_SZ];
+
+                byte nonce[AESGCM_NONCE_SZ];
+                XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AESGCM_IMP_IV_SZ);
+                XMEMCPY(nonce + AESGCM_IMP_IV_SZ, input, AESGCM_EXP_IV_SZ);
+
+                if (wc_AesGcmEncrypt(ssl->decrypt.aes,
+                            output,
+                            input + AESGCM_EXP_IV_SZ,
+                            sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
+                            nonce, AESGCM_NONCE_SZ,
+                            authTag, sizeof(authTag),
+                            NULL, 0) < 0) {
+                    Trace(BAD_DECRYPT);
+                    ret = -1;
+                }
+                ForceZero(nonce, AESGCM_NONCE_SZ);
+            }
+            else {
+                Trace(BAD_DECRYPT_SIZE);
+                ret = -1;
+            }
+            break;
+         #endif
+
+        #ifdef HAVE_NULL_CIPHER
+        case wolfssl_cipher_null:
+            XMEMCPY(output, input, sz);
+            break;
+        #endif
+
+        default:
+            Trace(BAD_DECRYPT_TYPE);
+            ret = -1;
+            break;
+    }
+
+    return ret;
+}
+
+
+/* Decrypt input message into output, adjust output steam if needed */
+static const byte* DecryptMessage(SSL* ssl, const byte* input, word32 sz,
+                                  byte* output, int* error, int* advance)
+{
+    int ivExtra = 0;
+
+    int ret = Decrypt(ssl, output, input, sz);
+    if (ret != 0) {
+        *error = ret;
+        return NULL;
+    }
+    ssl->keys.encryptSz = sz;
+    if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) {
+        output += ssl->specs.block_size;     /* go past TLSv1.1 IV */
+        ivExtra = ssl->specs.block_size;
+        *advance = ssl->specs.block_size;
+    }
+
+    if (ssl->specs.cipher_type == aead) {
+        *advance = ssl->specs.aead_mac_size;
+        ssl->keys.padSz = ssl->specs.aead_mac_size;
+    }
+    else
+        ssl->keys.padSz = ssl->specs.hash_size;
+
+    if (ssl->specs.cipher_type == block)
+        ssl->keys.padSz += *(output + sz - ivExtra - 1) + 1;
+
+    return output;
+}
+
+
+/* remove session from table, use rowHint if no info (means we have a lock) */
+static void RemoveSession(SnifferSession* session, IpInfo* ipInfo,
+                        TcpInfo* tcpInfo, word32 rowHint)
+{
+    SnifferSession* previous = 0;
+    SnifferSession* current;
+    word32          row = rowHint;
+    int             haveLock = 0;
+
+    if (ipInfo && tcpInfo)
+        row = SessionHash(ipInfo, tcpInfo);
+    else
+        haveLock = 1;
+
+    assert(row <= HASH_SIZE);
+    Trace(REMOVE_SESSION_STR);
+
+    if (!haveLock)
+        wc_LockMutex(&SessionMutex);
+
+    current = SessionTable[row];
+
+    while (current) {
+        if (current == session) {
+            if (previous)
+                previous->next = current->next;
+            else
+                SessionTable[row] = current->next;
+            FreeSnifferSession(session);
+            TraceRemovedSession();
+            break;
+        }
+        previous = current;
+        current  = current->next;
+    }
+
+    if (!haveLock)
+        wc_UnLockMutex(&SessionMutex);
+}
+
+
+/* Remove stale sessions from the Session Table, have a lock */
+static void RemoveStaleSessions(void)
+{
+    word32 i;
+    SnifferSession* session;
+
+    for (i = 0; i < HASH_SIZE; i++) {
+        session = SessionTable[i];
+        while (session) {
+            SnifferSession* next = session->next;
+            if (time(NULL) >= session->lastUsed + WOLFSSL_SNIFFER_TIMEOUT) {
+                TraceStaleSession();
+                RemoveSession(session, NULL, NULL, i);
+            }
+            session = next;
+        }
+    }
+}
+
+
+/* Create a new Sniffer Session */
+static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
+                                     char* error)
+{
+    SnifferSession* session = 0;
+    int row;
+
+    Trace(NEW_SESSION_STR);
+    /* create a new one */
+    session = (SnifferSession*)XMALLOC(sizeof(SnifferSession),
+            NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
+    if (session == NULL) {
+        SetError(MEMORY_STR, error, NULL, 0);
+        return 0;
+    }
+    InitSession(session);
+#ifdef HAVE_EXTENDED_MASTER
+    {
+        HsHashes* newHash = (HsHashes*)XMALLOC(sizeof(HsHashes),
+                NULL, DYNAMIC_TYPE_HASHES);
+        if (newHash == NULL) {
+            SetError(MEMORY_STR, error, NULL, 0);
+            XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
+            return 0;
+        }
+        if (HashInit(newHash) != 0) {
+            SetError(EXTENDED_MASTER_HASH_STR, error, NULL, 0);
+            XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
+            return 0;
+        }
+        session->hash = newHash;
+    }
+#endif
+    session->server  = ipInfo->dst;
+    session->client  = ipInfo->src;
+    session->srvPort = (word16)tcpInfo->dstPort;
+    session->cliPort = (word16)tcpInfo->srcPort;
+    session->cliSeqStart = tcpInfo->sequence;
+    session->cliExpected = 1;  /* relative */
+    session->lastUsed= time(NULL);
+    session->keySz = 0;
+#ifdef HAVE_SNI
+    session->sni = NULL;
+#endif
+
+    session->context = GetSnifferServer(ipInfo, tcpInfo);
+    if (session->context == NULL) {
+        SetError(SERVER_NOT_REG_STR, error, NULL, 0);
+        XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
+        return 0;
+    }
+
+    session->sslServer = SSL_new(session->context->ctx);
+    if (session->sslServer == NULL) {
+        SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE);
+        XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
+        return 0;
+    }
+    session->sslClient = SSL_new(session->context->ctx);
+    if (session->sslClient == NULL) {
+        SSL_free(session->sslServer);
+        session->sslServer = 0;
+
+        SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE);
+        XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
+        return 0;
+    }
+    /* put server back into server mode */
+    session->sslServer->options.side = WOLFSSL_SERVER_END;
+
+    row = SessionHash(ipInfo, tcpInfo);
+
+    /* add it to the session table */
+    wc_LockMutex(&SessionMutex);
+
+    session->next = SessionTable[row];
+    SessionTable[row] = session;
+
+    SessionCount++;
+
+    if ( (SessionCount % HASH_SIZE) == 0) {
+        TraceFindingStale();
+        RemoveStaleSessions();
+    }
+
+    wc_UnLockMutex(&SessionMutex);
+
+    /* CreateSession is called in response to a SYN packet, we know this
+     * is headed to the server. Also we know the server is one we care
+     * about as we've passed the GetSnifferServer() successfully. */
+    session->flags.side = WOLFSSL_SERVER_END;
+
+    return session;
+}
+
+
+#ifdef OLD_HELLO_ALLOWED
+
+/* Process Old Client Hello Input */
+static int DoOldHello(SnifferSession* session, const byte* sslFrame,
+                      int* rhSize, int* sslBytes, char* error)
+{
+    const byte* input = sslFrame;
+    byte        b0, b1;
+    word32      idx = 0;
+    int         ret;
+
+    Trace(GOT_OLD_CLIENT_HELLO_STR);
+    session->flags.clientHello = 1;    /* don't process again */
+    b0 = *input++;
+    b1 = *input++;
+    *sslBytes -= 2;
+    *rhSize = ((b0 & 0x7f) << 8) | b1;
+
+    if (*rhSize > *sslBytes) {
+        SetError(OLD_CLIENT_INPUT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+    ret = ProcessOldClientHello(session->sslServer, input, &idx, *sslBytes,
+                                (word16)*rhSize);
+    if (ret < 0 && ret != MATCH_SUITE_ERROR) {
+        SetError(BAD_OLD_CLIENT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+    Trace(OLD_CLIENT_OK_STR);
+    XMEMCPY(session->sslClient->arrays->clientRandom,
+           session->sslServer->arrays->clientRandom, RAN_LEN);
+
+    *sslBytes -= *rhSize;
+    return 0;
+}
+
+#endif /* OLD_HELLO_ALLOWED */
+
+
+#if 0
+/* Calculate the TCP checksum, see RFC 1071 */
+/* return 0 for success, -1 on error */
+/* can be called from decode() with
+   TcpChecksum(&ipInfo, &tcpInfo, sslBytes, packet + ipInfo.length);
+   could also add a 64bit version if type available and using this
+*/
+int TcpChecksum(IpInfo* ipInfo, TcpInfo* tcpInfo, int dataLen,
+                const byte* packet)
+{
+    TcpPseudoHdr  pseudo;
+    int           count = PSEUDO_HDR_SZ;
+    const word16* data = (word16*)&pseudo;
+    word32        sum = 0;
+    word16        checksum;
+
+    pseudo.src = ipInfo->src;
+    pseudo.dst = ipInfo->dst;
+    pseudo.rsv = 0;
+    pseudo.protocol = TCP_PROTO;
+    pseudo.length = htons(tcpInfo->length + dataLen);
+
+    /* pseudo header sum */
+    while (count >= 2) {
+        sum   += *data++;
+        count -= 2;
+    }
+
+    count = tcpInfo->length + dataLen;
+    data = (word16*)packet;
+
+    /* main sum */
+    while (count > 1) {
+        sum   += *data++;
+        count -=2;
+    }
+
+    /* get left-over, if any */
+    packet = (byte*)data;
+    if (count > 0) {
+        sum += *packet;
+    }
+
+    /* fold 32bit sum into 16 bits */
+    while (sum >> 16)
+        sum = (sum & 0xffff) + (sum >> 16);
+
+    checksum = (word16)~sum;
+    /* checksum should now equal 0, since included already calcd checksum */
+    /* field, but tcp checksum offloading could negate calculation */
+    if (checksum == 0)
+        return 0;
+    return -1;
+}
+#endif
+
+
+/* Check IP and TCP headers, set payload */
+/* returns 0 on success, -1 on error */
+static int CheckHeaders(IpInfo* ipInfo, TcpInfo* tcpInfo, const byte* packet,
+                  int length, const byte** sslFrame, int* sslBytes, char* error)
+{
+    TraceHeader();
+    TracePacket();
+
+    /* ip header */
+    if (length < IP_HDR_SZ) {
+        SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
+        return -1;
+    }
+    if (CheckIpHdr((IpHdr*)packet, ipInfo, length, error) != 0)
+        return -1;
+
+    /* tcp header */
+    if (length < (ipInfo->length + TCP_HDR_SZ)) {
+        SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
+        return -1;
+    }
+    if (CheckTcpHdr((TcpHdr*)(packet + ipInfo->length), tcpInfo, error) != 0)
+        return -1;
+
+    /* setup */
+    *sslFrame = packet + ipInfo->length + tcpInfo->length;
+    if (*sslFrame > packet + length) {
+        SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
+        return -1;
+    }
+    /* We only care about the data in the TCP/IP record. There may be extra
+     * data after the IP record for the FCS for Ethernet. */
+    *sslBytes = (int)(packet + ipInfo->total - *sslFrame);
+
+    return 0;
+}
+
+
+/* Create or Find existing session */
+/* returns 0 on success (continue), -1 on error, 1 on success (end) */
+static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes,
+                        SnifferSession** session, char* error)
+{
+    /* create a new SnifferSession on client SYN */
+    if (tcpInfo->syn && !tcpInfo->ack) {
+        TraceClientSyn(tcpInfo->sequence);
+#ifdef WOLFSSL_SNIFFER_STATS
+        INC_STAT(SnifferStats.sslEncryptedConns);
+#endif
+        *session = CreateSession(ipInfo, tcpInfo, error);
+        if (*session == NULL) {
+            *session = GetSnifferSession(ipInfo, tcpInfo);
+            /* already had existing, so OK */
+            if (*session)
+                return 1;
+
+            SetError(MEMORY_STR, error, NULL, 0);
+            return -1;
+        }
+        return 1;
+    }
+    /* get existing sniffer session */
+    else {
+        *session = GetSnifferSession(ipInfo, tcpInfo);
+        if (*session == NULL) {
+            /* don't worry about extraneous RST or duplicate FINs */
+            if (tcpInfo->fin || tcpInfo->rst)
+                return 1;
+            /* don't worry about duplicate ACKs either */
+            if (sslBytes == 0 && tcpInfo->ack)
+                return 1;
+
+#ifdef WOLFSSL_SNIFFER_STATS
+            LOCK_STAT();
+            NOLOCK_INC_STAT(SnifferStats.sslDecryptedPackets);
+            NOLOCK_ADD_TO_STAT(SnifferStats.sslDecryptedBytes, sslBytes);
+            UNLOCK_STAT();
+#endif
+
+            SetError(BAD_SESSION_STR, error, NULL, 0);
+            return -1;
+        }
+    }
+    return 0;
+}
+
+
+/* Create a Packet Buffer from *begin - end, adjust new *begin and bytesLeft */
+static PacketBuffer* CreateBuffer(word32* begin, word32 end, const byte* data,
+                                  int* bytesLeft)
+{
+    PacketBuffer* pb;
+
+    int added = end - *begin + 1;
+    assert(*begin <= end);
+
+    pb = (PacketBuffer*)XMALLOC(sizeof(PacketBuffer),
+            NULL, DYNAMIC_TYPE_SNIFFER_PB);
+    if (pb == NULL) return NULL;
+
+    pb->next  = 0;
+    pb->begin = *begin;
+    pb->end   = end;
+    pb->data = (byte*)XMALLOC(added, NULL, DYNAMIC_TYPE_SNIFFER_PB_BUFFER);
+
+    if (pb->data == NULL) {
+        XFREE(pb, NULL, DYNAMIC_TYPE_SNIFFER_PB);
+        return NULL;
+    }
+    XMEMCPY(pb->data, data, added);
+
+    *bytesLeft -= added;
+    *begin      = pb->end + 1;
+
+    return pb;
+}
+
+
+/* Add sslFrame to Reassembly List */
+/* returns 1 (end) on success, -1, on error */
+static int AddToReassembly(byte from, word32 seq, const byte* sslFrame,
+                           int sslBytes, SnifferSession* session, char* error)
+{
+    PacketBuffer*  add;
+    PacketBuffer** front = (from == WOLFSSL_SERVER_END) ?
+                       &session->cliReassemblyList: &session->srvReassemblyList;
+    PacketBuffer*  curr = *front;
+    PacketBuffer*  prev = curr;
+
+    word32* reassemblyMemory = (from == WOLFSSL_SERVER_END) ?
+                  &session->cliReassemblyMemory : &session->srvReassemblyMemory;
+    word32  startSeq = seq;
+    word32  added;
+    int     bytesLeft = sslBytes;  /* could be overlapping fragment */
+
+    /* if list is empty add full frame to front */
+    if (!curr) {
+        if (MaxRecoveryMemory != -1 &&
+                      (int)(*reassemblyMemory + sslBytes) > MaxRecoveryMemory) {
+            SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+        add = CreateBuffer(&seq, seq + sslBytes - 1, sslFrame, &bytesLeft);
+        if (add == NULL) {
+            SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+        *front = add;
+        *reassemblyMemory += sslBytes;
+        return 1;
+    }
+
+    /* add to front if before current front, up to next->begin */
+    if (seq < curr->begin) {
+        word32 end = seq + sslBytes - 1;
+
+        if (end >= curr->begin)
+            end = curr->begin - 1;
+
+        if (MaxRecoveryMemory -1 &&
+                      (int)(*reassemblyMemory + sslBytes) > MaxRecoveryMemory) {
+            SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+        add = CreateBuffer(&seq, end, sslFrame, &bytesLeft);
+        if (add == NULL) {
+            SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+        add->next = curr;
+        *front = add;
+        *reassemblyMemory += sslBytes;
+    }
+
+    /* while we have bytes left, try to find a gap to fill */
+    while (bytesLeft > 0) {
+        /* get previous packet in list */
+        while (curr && (seq >= curr->begin)) {
+            prev = curr;
+            curr = curr->next;
+        }
+
+        /* don't add  duplicate data */
+        if (prev->end >= seq) {
+            if ( (seq + bytesLeft - 1) <= prev->end)
+                return 1;
+            seq = prev->end + 1;
+            bytesLeft = startSeq + sslBytes - seq;
+        }
+
+        if (!curr)
+            /* we're at the end */
+            added = bytesLeft;
+        else
+            /* we're in between two frames */
+            added = min((word32)bytesLeft, curr->begin - seq);
+
+        /* data already there */
+        if (added == 0)
+            continue;
+
+        if (MaxRecoveryMemory != -1 &&
+                         (int)(*reassemblyMemory + added) > MaxRecoveryMemory) {
+            SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+        add = CreateBuffer(&seq, seq + added - 1, &sslFrame[seq - startSeq],
+                           &bytesLeft);
+        if (add == NULL) {
+            SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+        add->next  = prev->next;
+        prev->next = add;
+        *reassemblyMemory += added;
+    }
+    return 1;
+}
+
+
+/* Add out of order FIN capture */
+/* returns 1 for success (end) */
+static int AddFinCapture(SnifferSession* session, word32 sequence)
+{
+    if (session->flags.side == WOLFSSL_SERVER_END) {
+        if (session->finCaputre.cliCounted == 0)
+            session->finCaputre.cliFinSeq = sequence;
+    }
+    else {
+        if (session->finCaputre.srvCounted == 0)
+            session->finCaputre.srvFinSeq = sequence;
+    }
+    return 1;
+}
+
+
+/* Adjust incoming sequence based on side */
+/* returns 0 on success (continue), -1 on error, 1 on success (end) */
+static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
+                          int* sslBytes, const byte** sslFrame, char* error)
+{
+    word32  seqStart = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                     session->cliSeqStart :session->srvSeqStart;
+    word32  real     = tcpInfo->sequence - seqStart;
+    word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                  &session->cliExpected : &session->srvExpected;
+    PacketBuffer* reassemblyList = (session->flags.side == WOLFSSL_SERVER_END) ?
+                        session->cliReassemblyList : session->srvReassemblyList;
+    byte  skipPartial = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                session->flags.srvSkipPartial :
+                                session->flags.cliSkipPartial;
+
+    /* handle rollover of sequence */
+    if (tcpInfo->sequence < seqStart)
+        real = 0xffffffffU - seqStart + tcpInfo->sequence;
+
+    TraceRelativeSequence(*expected, real);
+
+    if (real < *expected) {
+        Trace(DUPLICATE_STR);
+        if (real + *sslBytes > *expected) {
+            int overlap = *expected - real;
+            Trace(OVERLAP_DUPLICATE_STR);
+
+            /* adjust to expected, remove duplicate */
+            *sslFrame += overlap;
+            *sslBytes -= overlap;
+
+            /* The following conditional block is duplicated below. It is the
+             * same action but for a different setup case. If changing this
+             * block be sure to also update the block below. */
+            if (reassemblyList) {
+                word32 newEnd = *expected + *sslBytes;
+
+                if (newEnd > reassemblyList->begin) {
+                    Trace(OVERLAP_REASSEMBLY_BEGIN_STR);
+
+                    /* remove bytes already on reassembly list */
+                    *sslBytes -= newEnd - reassemblyList->begin;
+                }
+                if (newEnd > reassemblyList->end) {
+                    Trace(OVERLAP_REASSEMBLY_END_STR);
+
+                    /* may be past reassembly list end (could have more on list)
+                       so try to add what's past the front->end */
+                    AddToReassembly(session->flags.side, reassemblyList->end +1,
+                                *sslFrame + reassemblyList->end - *expected + 1,
+                                 newEnd - reassemblyList->end, session, error);
+                }
+            }
+        }
+        else
+            return 1;
+    }
+    else if (real > *expected) {
+        Trace(OUT_OF_ORDER_STR);
+        if (*sslBytes > 0) {
+            int addResult = AddToReassembly(session->flags.side, real,
+                                          *sslFrame, *sslBytes, session, error);
+            if (skipPartial) {
+                *sslBytes = 0;
+                return 0;
+            }
+            else
+                return addResult;
+        }
+        else if (tcpInfo->fin)
+            return AddFinCapture(session, real);
+    }
+    else if (*sslBytes > 0) {
+        if (skipPartial) {
+            AddToReassembly(session->flags.side, real,
+                                          *sslFrame, *sslBytes, session, error);
+            *expected += *sslBytes;
+            *sslBytes = 0;
+            if (tcpInfo->fin)
+                *expected += 1;
+            return 0;
+        }
+        /* The following conditional block is duplicated above. It is the
+         * same action but for a different setup case. If changing this
+         * block be sure to also update the block above. */
+        else if (reassemblyList) {
+            word32 newEnd = *expected + *sslBytes;
+
+            if (newEnd > reassemblyList->begin) {
+                Trace(OVERLAP_REASSEMBLY_BEGIN_STR);
+
+                /* remove bytes already on reassembly list */
+                *sslBytes -= newEnd - reassemblyList->begin;
+            }
+            if (newEnd > reassemblyList->end) {
+                Trace(OVERLAP_REASSEMBLY_END_STR);
+
+                /* may be past reassembly list end (could have more on list)
+                   so try to add what's past the front->end */
+                AddToReassembly(session->flags.side, reassemblyList->end +1,
+                            *sslFrame + reassemblyList->end - *expected + 1,
+                             newEnd - reassemblyList->end, session, error);
+            }
+        }
+    }
+    /* got expected sequence */
+    *expected += *sslBytes;
+    if (tcpInfo->fin)
+        *expected += 1;
+
+    return 0;
+}
+
+
+static int FindNextRecordInAssembly(SnifferSession* session,
+                                    const byte** sslFrame, int* sslBytes,
+                                    const byte** end, char* error)
+{
+    PacketBuffer**     front = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                    &session->cliReassemblyList :
+                                    &session->srvReassemblyList;
+    PacketBuffer*       curr = *front;
+    PacketBuffer*       prev = NULL;
+    byte*        skipPartial = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                    &session->flags.srvSkipPartial :
+                                    &session->flags.cliSkipPartial;
+    word32* reassemblyMemory = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                    &session->cliReassemblyMemory :
+                                    &session->srvReassemblyMemory;
+    SSL*                 ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                    session->sslServer :
+                                    session->sslClient;
+    ProtocolVersion       pv = ssl->version;
+    word32*         expected = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                    &session->cliExpected :
+                                    &session->srvExpected;
+
+    while (curr != NULL) {
+        *expected = curr->end + 1;
+
+        if (curr->data[0] == application_data &&
+            curr->data[1] == pv.major &&
+            curr->data[2] == pv.minor) {
+
+            if (ssl->buffers.inputBuffer.length > 0)
+                Trace(DROPPING_PARTIAL_RECORD);
+
+            *sslBytes = curr->end - curr->begin + 1;
+            if ( (word32)*sslBytes > ssl->buffers.inputBuffer.bufferSize) {
+                if (GrowInputBuffer(ssl, *sslBytes, 0) < 0) {
+                    SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
+                    return -1;
+                }
+            }
+
+            XMEMCPY(ssl->buffers.inputBuffer.buffer, curr->data, *sslBytes);
+
+            *front = curr->next;
+            *reassemblyMemory -= *sslBytes;
+            FreePacketBuffer(curr);
+
+            ssl->buffers.inputBuffer.length = *sslBytes;
+            *sslFrame = ssl->buffers.inputBuffer.buffer;
+            *end = *sslFrame + *sslBytes;
+            *skipPartial = 0;
+
+            return 0;
+        }
+        else if (ssl->specs.cipher_type == block) {
+            if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes) {
+#ifdef BUILD_AES
+                wc_AesSetIV(ssl->decrypt.aes,
+                            curr->data + curr->end - curr->begin
+                                       - ssl->specs.block_size + 1);
+#endif
+            }
+            else if (ssl->specs.bulk_cipher_algorithm == wolfssl_triple_des) {
+#ifdef BUILD_DES3
+                wc_Des3_SetIV(ssl->decrypt.des3,
+                              curr->data + curr->end - curr->begin
+                                         - ssl->specs.block_size + 1);
+#endif
+            }
+        }
+
+        Trace(DROPPING_LOST_FRAG_STR);
+#ifdef WOLFSSL_SNIFFER_STATS
+        INC_STAT(SnifferStats.sslDecodeFails);
+#endif
+        prev = curr;
+        curr = curr->next;
+        *reassemblyMemory -= (prev->end - prev->begin + 1);
+        FreePacketBuffer(prev);
+    }
+
+    *front = curr;
+
+    return 0;
+}
+
+
+static int FixSequence(TcpInfo* tcpInfo, SnifferSession* session)
+{
+    word32*   expected = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                &session->srvExpected : &session->cliExpected;
+    PacketBuffer* list = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                session->srvReassemblyList :
+                                session->cliReassemblyList;
+    byte*  skipPartial = (session->flags.side != WOLFSSL_SERVER_END) ?
+                                &session->flags.srvSkipPartial :
+                                &session->flags.cliSkipPartial;
+
+    *skipPartial = 1;
+    if (list != NULL)
+        *expected = list->begin;
+    else {
+        word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                session->srvSeqStart : session->cliSeqStart;
+        word32     real = tcpInfo->ackNumber - seqStart;
+
+        *expected = real;
+    }
+
+    return 1;
+}
+
+
+/* Check latest ack number for missing packets
+   return 0 ok, <0 on error */
+static int CheckAck(TcpInfo* tcpInfo, SnifferSession* session)
+{
+    if (tcpInfo->ack) {
+        word32  seqStart = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                     session->srvSeqStart :session->cliSeqStart;
+        word32  real     = tcpInfo->ackNumber - seqStart;
+        word32  expected = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                  session->srvExpected : session->cliExpected;
+
+        /* handle rollover of sequence */
+        if (tcpInfo->ackNumber < seqStart)
+            real = 0xffffffffU - seqStart + tcpInfo->ackNumber;
+
+        TraceAck(real, expected);
+
+        if (real > expected)
+            return -1;  /* we missed a packet, ACKing data we never saw */
+    }
+    return 0;
+}
+
+
+/* Check TCP Sequence status */
+/* returns 0 on success (continue), -1 on error, 1 on success (end) */
+static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo,
+                         SnifferSession* session, int* sslBytes,
+                         const byte** sslFrame, char* error)
+{
+    int actualLen;
+    byte* ackFault = (session->flags.side == WOLFSSL_SERVER_END) ?
+                        &session->flags.cliAckFault :
+                        &session->flags.srvAckFault;
+
+    /* init SEQ from server to client */
+    if (tcpInfo->syn && tcpInfo->ack) {
+        session->srvSeqStart = tcpInfo->sequence;
+        session->srvExpected = 1;
+        TraceServerSyn(tcpInfo->sequence);
+        return 1;
+    }
+
+    /* adjust potential ethernet trailer */
+    actualLen = ipInfo->total - ipInfo->length - tcpInfo->length;
+    if (*sslBytes > actualLen) {
+        *sslBytes = actualLen;
+    }
+
+    TraceSequence(tcpInfo->sequence, *sslBytes);
+    if (CheckAck(tcpInfo, session) < 0) {
+        if (!RecoveryEnabled) {
+            UpdateMissedDataSessions();
+            SetError(ACK_MISSED_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+        else {
+            SetError(ACK_MISSED_STR, error, session, 0);
+            if (*ackFault == 0) {
+                *ackFault = 1;
+                UpdateMissedDataSessions();
+            }
+            return FixSequence(tcpInfo, session);
+        }
+    }
+
+    if (*ackFault) {
+        Trace(CLEAR_ACK_FAULT);
+        *ackFault = 0;
+    }
+
+    return AdjustSequence(tcpInfo, session, sslBytes, sslFrame, error);
+}
+
+
+/* Check Status before record processing */
+/* returns 0 on success (continue), -1 on error, 1 on success (end) */
+static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
+                          const byte** sslFrame, SnifferSession** session,
+                          int* sslBytes, const byte** end,
+                          void* vChain, word32 chainSz, char* error)
+{
+    word32 length;
+    SSL*  ssl = ((*session)->flags.side == WOLFSSL_SERVER_END) ?
+                                  (*session)->sslServer : (*session)->sslClient;
+    byte  skipPartial = ((*session)->flags.side == WOLFSSL_SERVER_END) ?
+                        (*session)->flags.srvSkipPartial :
+                        (*session)->flags.cliSkipPartial;
+    /* remove SnifferSession on 2nd FIN or RST */
+    if (tcpInfo->fin || tcpInfo->rst) {
+        /* flag FIN and RST */
+        if (tcpInfo->fin)
+            (*session)->flags.finCount += 1;
+        else if (tcpInfo->rst)
+            (*session)->flags.finCount += 2;
+
+        if ((*session)->flags.finCount >= 2) {
+            RemoveSession(*session, ipInfo, tcpInfo, 0);
+            *session = NULL;
+            return 1;
+        }
+    }
+
+    if ((*session)->flags.fatalError == FATAL_ERROR_STATE) {
+        SetError(FATAL_ERROR_STR, error, NULL, 0);
+        return -1;
+    }
+
+    if (skipPartial) {
+        if (FindNextRecordInAssembly(*session,
+                                     sslFrame, sslBytes, end, error) < 0) {
+            return -1;
+        }
+    }
+
+    if (*sslBytes == 0) {
+        Trace(NO_DATA_STR);
+        return 1;
+    }
+
+    /* if current partial data, add to end of partial */
+    /* if skipping, the data is already at the end of partial */
+    if ( !skipPartial && (length = ssl->buffers.inputBuffer.length) ) {
+        Trace(PARTIAL_ADD_STR);
+
+        if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) {
+            if (GrowInputBuffer(ssl, *sslBytes, length) < 0) {
+                SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE);
+                return -1;
+            }
+        }
+        if (vChain == NULL) {
+            XMEMCPY(&ssl->buffers.inputBuffer.buffer[length],
+                    *sslFrame, *sslBytes);
+            *sslBytes += length;
+            ssl->buffers.inputBuffer.length = *sslBytes;
+            *sslFrame = ssl->buffers.inputBuffer.buffer;
+            *end = *sslFrame + *sslBytes;
+        }
+    }
+
+    if (vChain != NULL) {
+#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT
+        struct iovec* chain = (struct iovec*)vChain;
+        word32 i, offset, headerSz, qty, remainder;
+
+        Trace(CHAIN_INPUT_STR);
+        headerSz = (word32)*sslFrame - (word32)chain[0].iov_base;
+        remainder = *sslBytes;
+
+        if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) {
+            if (GrowInputBuffer(ssl, *sslBytes, length) < 0) {
+                SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE);
+                return -1;
+            }
+        }
+
+        qty = min(*sslBytes, (word32)chain[0].iov_len - headerSz);
+        XMEMCPY(&ssl->buffers.inputBuffer.buffer[length],
+               (byte*)chain[0].iov_base + headerSz, qty);
+        offset = length;
+        for (i = 1; i < chainSz; i++) {
+            offset += qty;
+            remainder -= qty;
+
+            if (chain[i].iov_len > remainder)
+                qty = remainder;
+            else
+                qty = (word32)chain[i].iov_len;
+            XMEMCPY(ssl->buffers.inputBuffer.buffer + offset,
+                    chain[i].iov_base, qty);
+        }
+
+        *sslBytes += length;
+        ssl->buffers.inputBuffer.length = *sslBytes;
+        *sslFrame = ssl->buffers.inputBuffer.buffer;
+        *end = *sslFrame + *sslBytes;
+#endif
+        (void)chainSz;
+    }
+
+    if ((*session)->flags.clientHello == 0 && **sslFrame != handshake) {
+        /* Sanity check the packet for an old style client hello. */
+        int rhSize = (((*sslFrame)[0] & 0x7f) << 8) | ((*sslFrame)[1]);
+
+        if ((rhSize <= (*sslBytes - 2)) &&
+            (*sslFrame)[2] == OLD_HELLO_ID && (*sslFrame)[3] == SSLv3_MAJOR) {
+#ifdef OLD_HELLO_ALLOWED
+        int ret = DoOldHello(*session, *sslFrame, &rhSize, sslBytes, error);
+        if (ret < 0)
+            return -1;  /* error already set */
+        if (*sslBytes <= 0)
+            return 1;
+#endif
+        }
+        else {
+#ifdef STARTTLS_ALLOWED
+            if (ssl->buffers.inputBuffer.dynamicFlag) {
+                ssl->buffers.inputBuffer.length = 0;
+                ShrinkInputBuffer(ssl, NO_FORCED_FREE);
+            }
+            return 1;
+#endif
+        }
+    }
+
+    return 0;
+}
+
+
+/* See if input on the reassembly list is ready for consuming */
+/* returns 1 for TRUE, 0 for FALSE */
+static int HaveMoreInput(SnifferSession* session, const byte** sslFrame,
+                         int* sslBytes, const byte** end, char* error)
+{
+    /* sequence and reassembly based on from, not to */
+    int            moreInput = 0;
+    PacketBuffer** front = (session->flags.side == WOLFSSL_SERVER_END) ?
+                      &session->cliReassemblyList : &session->srvReassemblyList;
+    word32*        expected = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                  &session->cliExpected : &session->srvExpected;
+    /* buffer is on receiving end */
+    word32*        length = (session->flags.side == WOLFSSL_SERVER_END) ?
+                               &session->sslServer->buffers.inputBuffer.length :
+                               &session->sslClient->buffers.inputBuffer.length;
+    byte**         myBuffer = (session->flags.side == WOLFSSL_SERVER_END) ?
+                               &session->sslServer->buffers.inputBuffer.buffer :
+                               &session->sslClient->buffers.inputBuffer.buffer;
+    word32*       bufferSize = (session->flags.side == WOLFSSL_SERVER_END) ?
+                           &session->sslServer->buffers.inputBuffer.bufferSize :
+                           &session->sslClient->buffers.inputBuffer.bufferSize;
+    SSL*               ssl  = (session->flags.side == WOLFSSL_SERVER_END) ?
+                            session->sslServer : session->sslClient;
+    word32*     reassemblyMemory = (session->flags.side == WOLFSSL_SERVER_END) ?
+                  &session->cliReassemblyMemory : &session->srvReassemblyMemory;
+
+    while (*front && ((*front)->begin == *expected) ) {
+        word32 room = *bufferSize - *length;
+        word32 packetLen = (*front)->end - (*front)->begin + 1;
+
+        if (packetLen > room && *bufferSize < MAX_INPUT_SZ) {
+            if (GrowInputBuffer(ssl, packetLen, *length) < 0) {
+                SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
+                return 0;
+            }
+            room = *bufferSize - *length;   /* bufferSize is now bigger */
+        }
+
+        if (packetLen <= room) {
+            PacketBuffer* del = *front;
+            byte*         buf = *myBuffer;
+
+            XMEMCPY(&buf[*length], (*front)->data, packetLen);
+            *length   += packetLen;
+            *expected += packetLen;
+
+            /* remove used packet */
+            *front = (*front)->next;
+
+            *reassemblyMemory -= packetLen;
+            FreePacketBuffer(del);
+
+            moreInput = 1;
+        }
+        else
+            break;
+    }
+    if (moreInput) {
+        *sslFrame = *myBuffer;
+        *sslBytes = *length;
+        *end      = *myBuffer + *length;
+    }
+    return moreInput;
+}
+
+
+
+/* Process Message(s) from sslFrame */
+/* return Number of bytes on success, 0 for no data yet, and -1 on error */
+static int ProcessMessage(const byte* sslFrame, SnifferSession* session,
+                          int sslBytes, byte** data, const byte* end,
+                          void* ctx, char* error)
+{
+    const byte*       sslBegin = sslFrame;
+    const byte*       recordEnd;   /* end of record indicator */
+    const byte*       inRecordEnd; /* indicator from input stream not decrypt */
+    RecordLayerHeader rh;
+    int               rhSize = 0;
+    int               ret;
+    int               errCode = 0;
+    int               decoded = 0;      /* bytes stored for user in data */
+    int               notEnough;        /* notEnough bytes yet flag */
+    int               decrypted = 0;    /* was current msg decrypted */
+    SSL*              ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                        session->sslServer : session->sslClient;
+doMessage:
+    notEnough = 0;
+    if (sslBytes < 0) {
+        SetError(PACKET_HDR_SHORT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+    if (sslBytes >= RECORD_HEADER_SZ) {
+        if (GetRecordHeader(sslFrame, &rh, &rhSize) != 0) {
+            SetError(BAD_RECORD_HDR_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+    }
+    else
+        notEnough = 1;
+
+    if (notEnough || rhSize > (sslBytes - RECORD_HEADER_SZ)) {
+        /* don't have enough input yet to process full SSL record */
+        Trace(PARTIAL_INPUT_STR);
+
+        /* store partial if not there already or we advanced */
+        if (ssl->buffers.inputBuffer.length == 0 || sslBegin != sslFrame) {
+            if (sslBytes > (int)ssl->buffers.inputBuffer.bufferSize) {
+                if (GrowInputBuffer(ssl, sslBytes, 0) < 0) {
+                    SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
+                    return -1;
+                }
+            }
+            XMEMMOVE(ssl->buffers.inputBuffer.buffer, sslFrame, sslBytes);
+            ssl->buffers.inputBuffer.length = sslBytes;
+        }
+        if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error))
+            goto doMessage;
+        return decoded;
+    }
+    sslFrame += RECORD_HEADER_SZ;
+    sslBytes -= RECORD_HEADER_SZ;
+    recordEnd = sslFrame + rhSize;   /* may have more than one record */
+    inRecordEnd = recordEnd;
+
+    /* decrypt if needed */
+    if ((session->flags.side == WOLFSSL_SERVER_END &&
+                                               session->flags.serverCipherOn)
+     || (session->flags.side == WOLFSSL_CLIENT_END &&
+                                               session->flags.clientCipherOn)) {
+        int ivAdvance = 0;  /* TLSv1.1 advance amount */
+        if (ssl->decrypt.setup != 1) {
+            SetError(DECRYPT_KEYS_NOT_SETUP, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+        if (CheckAvailableSize(ssl, rhSize) < 0) {
+            SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+        sslFrame = DecryptMessage(ssl, sslFrame, rhSize,
+                                  ssl->buffers.outputBuffer.buffer, &errCode,
+                                  &ivAdvance);
+        recordEnd = sslFrame - ivAdvance + rhSize;  /* sslFrame moved so
+                                                       should recordEnd */
+        decrypted = 1;
+
+#ifdef WOLFSSL_SNIFFER_STATS
+        if (errCode != 0) {
+            INC_STAT(SnifferStats.sslKeyFails);
+        }
+        else {
+            LOCK_STAT();
+            NOLOCK_INC_STAT(SnifferStats.sslDecryptedPackets);
+            NOLOCK_ADD_TO_STAT(SnifferStats.sslDecryptedBytes, sslBytes);
+            UNLOCK_STAT();
+        }
+#endif
+        if (errCode != 0) {
+            SetError(BAD_DECRYPT, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+    }
+
+doPart:
+
+    switch ((enum ContentType)rh.type) {
+        case handshake:
+            {
+                int startIdx = sslBytes;
+                int used;
+
+                Trace(GOT_HANDSHAKE_STR);
+                ret = DoHandShake(sslFrame, &sslBytes, session, error);
+                if (ret != 0) {
+                    if (session->flags.fatalError == 0)
+                        SetError(BAD_HANDSHAKE_STR, error, session,
+                                 FATAL_ERROR_STATE);
+                    return -1;
+                }
+
+                /* DoHandShake now fully decrements sslBytes to remaining */
+                used = startIdx - sslBytes;
+                sslFrame += used;
+                if (decrypted)
+                    sslFrame += ssl->keys.padSz;
+            }
+            break;
+        case change_cipher_spec:
+            if (session->flags.side == WOLFSSL_SERVER_END)
+                session->flags.serverCipherOn = 1;
+            else
+                session->flags.clientCipherOn = 1;
+            Trace(GOT_CHANGE_CIPHER_STR);
+            ssl->options.handShakeState = HANDSHAKE_DONE;
+            ssl->options.handShakeDone  = 1;
+
+            sslFrame += 1;
+            sslBytes -= 1;
+
+            break;
+        case application_data:
+            Trace(GOT_APP_DATA_STR);
+            {
+                word32 inOutIdx = 0;
+
+                ret = DoApplicationData(ssl, (byte*)sslFrame, &inOutIdx);
+                if (ret == 0) {
+                    ret = ssl->buffers.clearOutputBuffer.length;
+                    TraceGotData(ret);
+                    if (ret) {  /* may be blank message */
+                        if (data != NULL) {
+                            byte* tmpData;  /* don't leak on realloc free */
+                            /* add an extra byte at end of allocation in case
+                             * user wants to null terminate plaintext */
+                            tmpData = (byte*)XREALLOC(*data, decoded + ret + 1,
+                                    NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                            if (tmpData == NULL) {
+                                ForceZero(*data, decoded);
+                                XFREE(*data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                                *data = NULL;
+                                SetError(MEMORY_STR, error, session,
+                                         FATAL_ERROR_STATE);
+                                return -1;
+                            }
+                            *data = tmpData;
+                            XMEMCPY(*data + decoded,
+                                    ssl->buffers.clearOutputBuffer.buffer, ret);
+                        }
+                        else {
+#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
+                            if (StoreDataCb) {
+                                const byte* buf;
+                                word32 offset = 0;
+                                word32 bufSz;
+                                int stored;
+
+                                buf = ssl->buffers.clearOutputBuffer.buffer;
+                                bufSz = ssl->buffers.clearOutputBuffer.length;
+                                do {
+                                    stored = StoreDataCb(buf, bufSz, offset,
+                                            ctx);
+                                    if (stored <= 0) {
+                                        return -1;
+                                    }
+                                    offset += stored;
+                                } while (offset < bufSz);
+                            }
+                            else {
+                                SetError(STORE_DATA_CB_MISSING_STR, error,
+                                        session, FATAL_ERROR_STATE);
+                                return -1;
+                            }
+#else
+                            (void)ctx;
+                            SetError(NO_DATA_DEST_STR, error, session,
+                                    FATAL_ERROR_STATE);
+                            return -1;
+#endif
+                        }
+                        TraceAddedData(ret, decoded);
+                        decoded += ret;
+                        ssl->buffers.clearOutputBuffer.length = 0;
+                    }
+                }
+                else {
+                    SetError(BAD_APP_DATA_STR, error,session,FATAL_ERROR_STATE);
+                    return -1;
+                }
+                if (ssl->buffers.outputBuffer.dynamicFlag)
+                    ShrinkOutputBuffer(ssl);
+
+                sslFrame += inOutIdx;
+                sslBytes -= inOutIdx;
+            }
+            break;
+        case alert:
+            Trace(GOT_ALERT_STR);
+#ifdef WOLFSSL_SNIFFER_STATS
+            INC_STAT(SnifferStats.sslAlerts);
+#endif
+            sslFrame += rhSize;
+            sslBytes -= rhSize;
+            break;
+        case no_type:
+        default:
+            SetError(GOT_UNKNOWN_RECORD_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+    }
+
+    /* do we have another msg in record ? */
+    if (sslFrame < recordEnd) {
+        Trace(ANOTHER_MSG_STR);
+        goto doPart;
+    }
+
+    /* back to input stream instead of potential decrypt buffer */
+    recordEnd = inRecordEnd;
+
+    /* do we have more records ? */
+    if (recordEnd < end) {
+        Trace(ANOTHER_MSG_STR);
+        sslFrame = recordEnd;
+        sslBytes = (int)(end - recordEnd);
+        goto doMessage;
+    }
+
+    /* clear used input */
+    ssl->buffers.inputBuffer.length = 0;
+
+    /* could have more input ready now */
+    if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error))
+        goto doMessage;
+
+    if (ssl->buffers.inputBuffer.dynamicFlag)
+        ShrinkInputBuffer(ssl, NO_FORCED_FREE);
+
+    return decoded;
+}
+
+
+/* See if we need to process any pending FIN captures */
+/* Return 0=normal, else = session removed */
+static int CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo,
+                            SnifferSession* session)
+{
+    int ret = 0;
+    if (session->finCaputre.cliFinSeq && session->finCaputre.cliFinSeq <=
+                                         session->cliExpected) {
+        if (session->finCaputre.cliCounted == 0) {
+            session->flags.finCount += 1;
+            session->finCaputre.cliCounted = 1;
+            TraceClientFin(session->finCaputre.cliFinSeq, session->cliExpected);
+        }
+    }
+
+    if (session->finCaputre.srvFinSeq && session->finCaputre.srvFinSeq <=
+                                         session->srvExpected) {
+        if (session->finCaputre.srvCounted == 0) {
+            session->flags.finCount += 1;
+            session->finCaputre.srvCounted = 1;
+            TraceServerFin(session->finCaputre.srvFinSeq, session->srvExpected);
+        }
+    }
+
+    if (session->flags.finCount >= 2) {
+        RemoveSession(session, ipInfo, tcpInfo, 0);
+        ret = 1;
+    }
+    return ret;
+}
+
+
+/* If session is in fatal error state free resources now
+   return true if removed, 0 otherwise */
+static int RemoveFatalSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
+                              SnifferSession* session, char* error)
+{
+    if (session && session->flags.fatalError == FATAL_ERROR_STATE) {
+        RemoveSession(session, ipInfo, tcpInfo, 0);
+        SetError(FATAL_ERROR_STR, error, NULL, 0);
+        return 1;
+    }
+    return 0;
+}
+
+
+/* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */
+/* returns Number of bytes on success, 0 for no data yet, and -1 on error */
+static int ssl_DecodePacketInternal(const byte* packet, int length,
+                                    void* vChain, word32 chainSz,
+                                    byte** data, SSLInfo* sslInfo,
+                                    void* ctx, char* error)
+{
+    TcpInfo           tcpInfo;
+    IpInfo            ipInfo;
+    const byte*       sslFrame;
+    const byte*       end;
+    int               sslBytes;                /* ssl bytes unconsumed */
+    int               ret;
+    SnifferSession*   session = 0;
+
+#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT
+    if (packet == NULL && vChain != NULL) {
+        struct iovec* chain = (struct iovec*)vChain;
+        word32 i;
+
+        length = 0;
+        for (i = 0; i < chainSz; i++)
+            length += chain[i].iov_len;
+        packet = (const byte*)chain[0].iov_base;
+    }
+#endif
+
+    if (CheckHeaders(&ipInfo, &tcpInfo, packet, length, &sslFrame, &sslBytes,
+                     error) != 0)
+        return -1;
+
+    end = sslFrame + sslBytes;
+
+    ret = CheckSession(&ipInfo, &tcpInfo, sslBytes, &session, error);
+    if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
+    else if (ret == -1) return -1;
+    else if (ret ==  1) {
+#ifdef WOLFSSL_SNIFFER_STATS
+        if (sslBytes > 0) {
+            LOCK_STAT();
+            NOLOCK_INC_STAT(SnifferStats.sslEncryptedPackets);
+            NOLOCK_ADD_TO_STAT(SnifferStats.sslEncryptedBytes, sslBytes);
+            UNLOCK_STAT();
+        }
+        else
+            INC_STAT(SnifferStats.sslDecryptedPackets);
+#endif
+         return  0;   /* done for now */
+    }
+
+    ret = CheckSequence(&ipInfo, &tcpInfo, session, &sslBytes, &sslFrame,error);
+    if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
+    else if (ret == -1) return -1;
+    else if (ret ==  1) {
+#ifdef WOLFSSL_SNIFFER_STATS
+        INC_STAT(SnifferStats.sslDecryptedPackets);
+#endif
+        return  0;   /* done for now */
+    }
+
+    ret = CheckPreRecord(&ipInfo, &tcpInfo, &sslFrame, &session, &sslBytes,
+                         &end, vChain, chainSz, error);
+    if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
+    else if (ret == -1) return -1;
+    else if (ret ==  1) {
+#ifdef WOLFSSL_SNIFFER_STATS
+        INC_STAT(SnifferStats.sslDecryptedPackets);
+#endif
+        return  0;   /* done for now */
+    }
+
+#ifdef WOLFSSL_SNIFFER_STATS
+    if (sslBytes > 0) {
+        LOCK_STAT();
+        NOLOCK_INC_STAT(SnifferStats.sslEncryptedPackets);
+        NOLOCK_ADD_TO_STAT(SnifferStats.sslEncryptedBytes, sslBytes);
+        UNLOCK_STAT();
+    }
+    else
+        INC_STAT(SnifferStats.sslDecryptedPackets);
+#endif
+
+    ret = ProcessMessage(sslFrame, session, sslBytes, data, end, ctx, error);
+    if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
+    if (CheckFinCapture(&ipInfo, &tcpInfo, session) == 0) {
+        CopySessionInfo(session, sslInfo);
+    }
+
+    return ret;
+}
+
+
+/* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */
+/* returns Number of bytes on success, 0 for no data yet, and -1 on error */
+/* Also returns Session Info if available */
+int ssl_DecodePacketWithSessionInfo(const unsigned char* packet, int length,
+    unsigned char** data, SSLInfo* sslInfo, char* error)
+{
+    return ssl_DecodePacketInternal(packet, length, NULL, 0, data, sslInfo,
+            NULL, error);
+}
+
+
+/* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */
+/* returns Number of bytes on success, 0 for no data yet, and -1 on error */
+int ssl_DecodePacket(const byte* packet, int length, byte** data, char* error)
+{
+    return ssl_DecodePacketInternal(packet, length, NULL, 0, data, NULL, NULL,
+            error);
+}
+
+
+#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
+
+int ssl_DecodePacketWithSessionInfoStoreData(const unsigned char* packet,
+        int length, void* ctx, SSLInfo* sslInfo, char* error)
+{
+    return ssl_DecodePacketInternal(packet, length, NULL, 0, NULL, sslInfo,
+            ctx, error);
+}
+
+#endif
+
+
+#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT
+
+int ssl_DecodePacketWithChain(void* vChain, word32 chainSz, byte** data,
+        char* error)
+{
+    return ssl_DecodePacketInternal(NULL, 0, vChain, chainSz, data, NULL, NULL,
+            error);
+}
+
+#endif
+
+
+#if defined(WOLFSSL_SNIFFER_CHAIN_INPUT) && \
+     defined(WOLFSSL_SNIFFER_STORE_DATA_CB)
+
+int ssl_DecodePacketWithChainSessionInfoStoreData(void* vChain, word32 chainSz,
+        void* ctx, SSLInfo* sslInfo, char* error)
+{
+    return ssl_DecodePacketInternal(NULL, 0, vChain, chainSz, NULL, sslInfo,
+            ctx, error);
+}
+
+#endif
+
+
+/* Deallocator for the decoded data buffer. */
+/* returns 0 on success, -1 on error */
+int ssl_FreeDecodeBuffer(byte** data, char* error)
+{
+    return ssl_FreeZeroDecodeBuffer(data, 0, error);
+}
+
+
+/* Deallocator for the decoded data buffer, zeros out buffer. */
+/* returns 0 on success, -1 on error */
+int ssl_FreeZeroDecodeBuffer(byte** data, int sz, char* error)
+{
+    (void)error;
+
+    if (sz < 0) {
+        return -1;
+    }
+
+    if (data != NULL) {
+        ForceZero(*data, (word32)sz);
+        XFREE(*data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        *data = NULL;
+    }
+
+    return 0;
+}
+
+
+/* Enables (if traceFile)/ Disables debug tracing */
+/* returns 0 on success, -1 on error */
+int ssl_Trace(const char* traceFile, char* error)
+{
+    if (traceFile) {
+        /* Don't try to reopen the file */
+        if (TraceFile == NULL) {
+            TraceFile = fopen(traceFile, "a");
+            if (!TraceFile) {
+                SetError(BAD_TRACE_FILE_STR, error, NULL, 0);
+                return -1;
+             }
+            TraceOn = 1;
+        }
+    }
+    else
+        TraceOn = 0;
+
+    return 0;
+}
+
+
+/* Enables/Disables Recovery of missed data if later packets allow
+ * maxMemory is number of bytes to use for reassembly buffering per session,
+ * -1 means unlimited
+ * returns 0 on success, -1 on error */
+int ssl_EnableRecovery(int onOff, int maxMemory, char* error)
+{
+    (void)error;
+
+    RecoveryEnabled = onOff;
+    if (onOff)
+        MaxRecoveryMemory = maxMemory;
+
+    return 0;
+}
+
+
+
+#ifdef WOLFSSL_SESSION_STATS
+
+int ssl_GetSessionStats(unsigned int* active,     unsigned int* total,
+                        unsigned int* peak,       unsigned int* maxSessions,
+                        unsigned int* missedData, unsigned int* reassemblyMem,
+                        char* error)
+{
+    int ret;
+
+    if (missedData) {
+        wc_LockMutex(&RecoveryMutex);
+        *missedData = MissedDataSessions;
+        wc_UnLockMutex(&RecoveryMutex);
+    }
+
+    if (reassemblyMem) {
+        SnifferSession* session;
+        int i;
+
+        *reassemblyMem = 0;
+        wc_LockMutex(&SessionMutex);
+        for (i = 0; i < HASH_SIZE; i++) {
+            session = SessionTable[i];
+            while (session) {
+                *reassemblyMem += session->cliReassemblyMemory;
+                *reassemblyMem += session->srvReassemblyMemory;
+                session = session->next;
+            }
+        }
+        wc_UnLockMutex(&SessionMutex);
+    }
+
+    ret = wolfSSL_get_session_stats(active, total, peak, maxSessions);
+
+    if (ret == WOLFSSL_SUCCESS)
+        return 0;
+    else {
+        SetError(BAD_SESSION_STATS, error, NULL, 0);
+        return -1;
+    }
+}
+
+#endif
+
+
+
+int ssl_SetConnectionCb(SSLConnCb cb)
+{
+    ConnectionCb = cb;
+    return 0;
+}
+
+
+
+int ssl_SetConnectionCtx(void* ctx)
+{
+    ConnectionCbCtx = ctx;
+    return 0;
+}
+
+
+#ifdef WOLFSSL_SNIFFER_STATS
+
+/* Resets the statistics tracking global structure.
+ * returns 0 on success, -1 on error */
+int ssl_ResetStatistics(void)
+{
+    wc_LockMutex(&StatsMutex);
+    XMEMSET(&SnifferStats, 0, sizeof(SSLStats));
+    wc_UnLockMutex(&StatsMutex);
+    return 0;
+}
+
+
+/* Copies the SSL statistics into the provided stats record.
+ * returns 0 on success, -1 on error */
+int ssl_ReadStatistics(SSLStats* stats)
+{
+    if (stats == NULL)
+        return -1;
+
+    LOCK_STAT();
+    XMEMCPY(stats, &SnifferStats, sizeof(SSLStats));
+    UNLOCK_STAT();
+    return 0;
+}
+
+/* Copies the SSL statistics into the provided stats record then
+ * resets the statistics tracking global structure.
+ * returns 0 on success, -1 on error */
+int ssl_ReadResetStatistics(SSLStats* stats)
+{
+    if (stats == NULL)
+        return -1;
+
+    LOCK_STAT();
+    XMEMCPY(stats, &SnifferStats, sizeof(SSLStats));
+    XMEMSET(&SnifferStats, 0, sizeof(SSLStats));
+    UNLOCK_STAT();
+    return 0;
+}
+
+#endif /* WOLFSSL_SNIFFER_STATS */
+
+
+#ifdef WOLFSSL_SNIFFER_WATCH
+
+int ssl_SetWatchKeyCallback_ex(SSLWatchCb cb, int devId, char* error)
+{
+    (void)devId;
+    WatchCb = cb;
+    return CreateWatchSnifferServer(error);
+}
+
+
+int ssl_SetWatchKeyCallback(SSLWatchCb cb, char* error)
+{
+    WatchCb = cb;
+    return CreateWatchSnifferServer(error);
+}
+
+
+int ssl_SetWatchKeyCtx(void* ctx, char* error)
+{
+    (void)error;
+    WatchCbCtx = ctx;
+    return 0;
+}
+
+
+int ssl_SetWatchKey_buffer(void* vSniffer, const byte* key, word32 keySz,
+        int keyType, char* error)
+{
+    SnifferSession* sniffer;
+    int ret;
+
+    if (vSniffer == NULL) {
+        return -1;
+    }
+    if (key == NULL || keySz == 0) {
+        return -1;
+    }
+
+    sniffer = (SnifferSession*)vSniffer;
+    /* Remap the keyType from what the user can use to
+     * what wolfSSL_use_PrivateKey_buffer expects. */
+    keyType = (keyType == FILETYPE_PEM) ? WOLFSSL_FILETYPE_PEM :
+                                          WOLFSSL_FILETYPE_ASN1;
+
+    ret = wolfSSL_use_PrivateKey_buffer(sniffer->sslServer,
+            key, keySz, keyType);
+    if (ret != WOLFSSL_SUCCESS) {
+        SetError(KEY_FILE_STR, error, sniffer, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+    return 0;
+}
+
+
+int ssl_SetWatchKey_file(void* vSniffer, const char* keyFile, int keyType,
+        const char* password, char* error)
+{
+    byte* keyBuf = NULL;
+    word32 keyBufSz = 0;
+    int ret;
+
+    if (vSniffer == NULL) {
+        return -1;
+    }
+    if (keyFile == NULL) {
+        return -1;
+    }
+
+    /* Remap the keyType from what the user can use to
+     * what LoadKeyFile expects. */
+    keyType = (keyType == FILETYPE_PEM) ? WOLFSSL_FILETYPE_PEM :
+                                          WOLFSSL_FILETYPE_ASN1;
+
+    ret = LoadKeyFile(&keyBuf, &keyBufSz, keyFile, keyType, password);
+    if (ret < 0) {
+        SetError(KEY_FILE_STR, error, NULL, 0);
+        XFREE(keyBuf, NULL, DYNAMIC_TYPE_X509);
+        return -1;
+    }
+
+    ret = ssl_SetWatchKey_buffer(vSniffer, keyBuf, keyBufSz, FILETYPE_DER,
+            error);
+    XFREE(keyBuf, NULL, DYNAMIC_TYPE_X509);
+
+    return ret;
+}
+
+#endif /* WOLFSSL_SNIFFER_WATCH */
+
+
+#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
+
+int ssl_SetStoreDataCallback(SSLStoreDataCb cb)
+{
+    StoreDataCb = cb;
+    return 0;
+}
+
+#endif /* WOLFSSL_SNIFFER_STORE_DATA_CB */
+
+#endif /* WOLFSSL_SNIFFER */
+#endif /* WOLFCRYPT_ONLY */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/ssl.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/ssl.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/ssl.c	(revision 453)
@@ -0,0 +1,47707 @@
+/* ssl.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+#if defined(OPENSSL_EXTRA) && !defined(_WIN32)
+    /* turn on GNU extensions for XVASPRINTF with wolfSSL_BIO_printf */
+    #undef  _GNU_SOURCE
+    #define _GNU_SOURCE
+#endif
+
+#if !defined(WOLFCRYPT_ONLY) || defined(OPENSSL_EXTRA) || \
+    defined(OPENSSL_EXTRA_X509_SMALL)
+
+#ifdef HAVE_ERRNO_H
+    #include <errno.h>
+#endif
+
+#include <wolfssl/internal.h>
+#include <wolfssl/error-ssl.h>
+#include <wolfssl/wolfcrypt/coding.h>
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+
+#if !defined(WOLFSSL_ALLOW_NO_SUITES) && !defined(WOLFCRYPT_ONLY)
+    #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(WOLFSSL_STATIC_RSA) \
+                && !defined(WOLFSSL_STATIC_DH) && !defined(WOLFSSL_STATIC_PSK) \
+                && !defined(HAVE_ED25519) && !defined(HAVE_ED448)
+        #error "No cipher suites defined because DH disabled, ECC disabled, and no static suites defined. Please see top of README"
+    #endif
+    #ifdef WOLFSSL_CERT_GEN
+        /* need access to Cert struct for creating certificate */
+        #include <wolfssl/wolfcrypt/asn_public.h>
+    #endif
+#endif
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \
+        defined(HAVE_WEBSERVER) || defined(WOLFSSL_KEY_GEN)
+    #include <wolfssl/openssl/evp.h>
+    /* openssl headers end, wolfssl internal headers next */
+#endif
+
+#include <wolfssl/wolfcrypt/wc_encrypt.h>
+
+#ifndef NO_RSA
+    #include <wolfssl/wolfcrypt/rsa.h>
+#endif
+
+#ifdef OPENSSL_EXTRA
+    /* openssl headers begin */
+    #include <wolfssl/openssl/aes.h>
+    #include <wolfssl/openssl/hmac.h>
+    #include <wolfssl/openssl/crypto.h>
+    #include <wolfssl/openssl/des.h>
+    #include <wolfssl/openssl/bn.h>
+    #include <wolfssl/openssl/buffer.h>
+    #include <wolfssl/openssl/dh.h>
+    #include <wolfssl/openssl/rsa.h>
+    #include <wolfssl/openssl/pem.h>
+    #include <wolfssl/openssl/ec.h>
+    #include <wolfssl/openssl/ec25519.h>
+    #include <wolfssl/openssl/ed25519.h>
+    #include <wolfssl/openssl/ec448.h>
+    #include <wolfssl/openssl/ed448.h>
+    #include <wolfssl/openssl/ecdsa.h>
+    #include <wolfssl/openssl/ecdh.h>
+    #include <wolfssl/openssl/err.h>
+    #include <wolfssl/openssl/opensslv.h>
+    #include <wolfssl/openssl/rc4.h>
+    #include <wolfssl/openssl/stack.h>
+    #include <wolfssl/openssl/x509v3.h>
+    #include <wolfssl/openssl/x509_vfy.h>
+    /* openssl headers end, wolfssl internal headers next */
+    #include <wolfssl/wolfcrypt/hmac.h>
+    #include <wolfssl/wolfcrypt/random.h>
+    #include <wolfssl/wolfcrypt/des3.h>
+    #include <wolfssl/wolfcrypt/md4.h>
+    #include <wolfssl/wolfcrypt/md5.h>
+    #include <wolfssl/wolfcrypt/arc4.h>
+    #include <wolfssl/wolfcrypt/idea.h>
+    #include <wolfssl/wolfcrypt/curve25519.h>
+    #include <wolfssl/wolfcrypt/ed25519.h>
+    #include <wolfssl/wolfcrypt/curve448.h>
+    #if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL)
+        #include <wolfssl/openssl/ocsp.h>
+    #endif /* WITH_STUNNEL */
+    #if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
+        #include <wolfssl/wolfcrypt/sha512.h>
+    #endif
+    #if defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA256) \
+        && !defined(WC_NO_RNG)
+        #include <wolfssl/wolfcrypt/srp.h>
+    #endif
+    #if defined(HAVE_FIPS) || defined(HAVE_SELFTEST)
+        #include <wolfssl/wolfcrypt/pkcs7.h>
+    #endif
+    #if defined(OPENSSL_ALL) && defined(HAVE_PKCS7)
+        #include <wolfssl/openssl/pkcs7.h>
+    #endif /* OPENSSL_ALL && HAVE_PKCS7 */
+#endif
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+    int SetIndividualInternal(WOLFSSL_BIGNUM* bn, mp_int* mpi);
+    int SetIndividualExternal(WOLFSSL_BIGNUM** bn, mp_int* mpi);
+    int oid2nid(word32 oid, int grp);
+#endif
+
+#if defined(WOLFSSL_QT)
+    #include <wolfssl/wolfcrypt/sha.h>
+#endif
+
+#ifdef NO_ASN
+    #include <wolfssl/wolfcrypt/dh.h>
+#endif
+#endif /* !WOLFCRYPT_ONLY || OPENSSL_EXTRA */
+
+#define WOLFSSL_EVP_INCLUDED
+#include "wolfcrypt/src/evp.c"
+
+#ifdef OPENSSL_EXTRA
+/* Global pointer to constant BN on */
+static WOLFSSL_BIGNUM* bn_one = NULL;
+#endif
+
+#ifndef WOLFCRYPT_ONLY
+
+#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC)
+const WOLF_EC_NIST_NAME kNistCurves[] = {
+    {XSTR_SIZEOF("P-192"),   "P-192",   NID_X9_62_prime192v1},
+    {XSTR_SIZEOF("P-256"),   "P-256",   NID_X9_62_prime256v1},
+    {XSTR_SIZEOF("P-112"),   "P-112",   NID_secp112r1},
+    {XSTR_SIZEOF("P-112-2"), "P-112-2", NID_secp112r2},
+    {XSTR_SIZEOF("P-128"),   "P-128",   NID_secp128r1},
+    {XSTR_SIZEOF("P-128-2"), "P-128-2", NID_secp128r2},
+    {XSTR_SIZEOF("P-160"),   "P-160",   NID_secp160r1},
+    {XSTR_SIZEOF("P-160-2"), "P-160-2", NID_secp160r2},
+    {XSTR_SIZEOF("P-224"),   "P-224",   NID_secp224r1},
+    {XSTR_SIZEOF("P-384"),   "P-384",   NID_secp384r1},
+    {XSTR_SIZEOF("P-521"),   "P-521",   NID_secp521r1},
+    {XSTR_SIZEOF("K-160"),   "K-160",   NID_secp160k1},
+    {XSTR_SIZEOF("K-192"),   "K-192",   NID_secp192k1},
+    {XSTR_SIZEOF("K-224"),   "K-224",   NID_secp224k1},
+    {XSTR_SIZEOF("K-256"),   "K-256",   NID_secp256k1},
+    {XSTR_SIZEOF("B-160"),   "B-160",   NID_brainpoolP160r1},
+    {XSTR_SIZEOF("B-192"),   "B-192",   NID_brainpoolP192r1},
+    {XSTR_SIZEOF("B-224"),   "B-224",   NID_brainpoolP224r1},
+    {XSTR_SIZEOF("B-256"),   "B-256",   NID_brainpoolP256r1},
+    {XSTR_SIZEOF("B-320"),   "B-320",   NID_brainpoolP320r1},
+    {XSTR_SIZEOF("B-384"),   "B-384",   NID_brainpoolP384r1},
+    {XSTR_SIZEOF("B-512"),   "B-512",   NID_brainpoolP512r1},
+    {0,                     NULL,      0},
+};
+#endif
+
+#if defined(WOLFSSL_RENESAS_TSIP_TLS)
+    /* for root ca verification */
+int tsip_tls_RootCertVerify(const byte *cert, word32 cert_len,
+                            word32 key_n_start, word32 key_n_len,
+                            word32 key_e_start, word32 key_e_len,
+                            word32 cm_row);
+byte tsip_rootCAverified( );
+#endif
+
+#ifdef WOLFSSL_SESSION_EXPORT
+#ifdef WOLFSSL_DTLS
+int wolfSSL_dtls_import(WOLFSSL* ssl, unsigned char* buf, unsigned int sz)
+{
+    WOLFSSL_ENTER("wolfSSL_session_import");
+
+    if (ssl == NULL || buf == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* sanity checks on buffer and protocol are done in internal function */
+    return wolfSSL_dtls_import_internal(ssl, buf, sz);
+}
+
+
+/* Sets the function to call for serializing the session. This function is
+ * called right after the handshake is completed. */
+int wolfSSL_CTX_dtls_set_export(WOLFSSL_CTX* ctx, wc_dtls_export func)
+{
+
+    WOLFSSL_ENTER("wolfSSL_CTX_dtls_set_export");
+
+    /* purposefully allow func to be NULL */
+    if (ctx == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    ctx->dtls_export = func;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* Sets the function in WOLFSSL struct to call for serializing the session. This
+ * function is called right after the handshake is completed. */
+int wolfSSL_dtls_set_export(WOLFSSL* ssl, wc_dtls_export func)
+{
+
+    WOLFSSL_ENTER("wolfSSL_dtls_set_export");
+
+    /* purposefully allow func to be NULL */
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    ssl->dtls_export = func;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* This function allows for directly serializing a session rather than using
+ * callbacks. It has less overhead by removing a temporary buffer and gives
+ * control over when the session gets serialized. When using callbacks the
+ * session is always serialized immediately after the handshake is finished.
+ *
+ * buf is the argument to contain the serialized session
+ * sz  is the size of the buffer passed in
+ * ssl is the WOLFSSL struct to serialize
+ * returns the size of serialized session on success, 0 on no action, and
+ *         negative value on error */
+int wolfSSL_dtls_export(WOLFSSL* ssl, unsigned char* buf, unsigned int* sz)
+{
+    WOLFSSL_ENTER("wolfSSL_dtls_export");
+
+    if (ssl == NULL || sz == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (buf == NULL) {
+        *sz = MAX_EXPORT_BUFFER;
+        return 0;
+    }
+
+    /* if not DTLS do nothing */
+    if (!ssl->options.dtls) {
+        WOLFSSL_MSG("Currently only DTLS export is supported");
+        return 0;
+    }
+
+    /* copy over keys, options, and dtls state struct */
+    return wolfSSL_dtls_export_internal(ssl, buf, *sz);
+}
+
+
+/* This function is similar to wolfSSL_dtls_export but only exports the portion
+ * of the WOLFSSL structure related to the state of the connection, i.e. peer
+ * sequence number, epoch, AEAD state etc.
+ *
+ * buf is the argument to contain the serialized state, if null then set "sz" to
+ *     buffer size required
+ * sz  is the size of the buffer passed in
+ * ssl is the WOLFSSL struct to serialize
+ * returns the size of serialized session on success, 0 on no action, and
+ *         negative value on error */
+int wolfSSL_dtls_export_state_only(WOLFSSL* ssl, unsigned char* buf,
+        unsigned int* sz)
+{
+    WOLFSSL_ENTER("wolfSSL_dtls_export_state_only");
+
+    if (ssl == NULL || sz == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (buf == NULL) {
+        *sz = MAX_EXPORT_STATE_BUFFER;
+        return 0;
+    }
+
+    /* if not DTLS do nothing */
+    if (!ssl->options.dtls) {
+        WOLFSSL_MSG("Currently only DTLS export state is supported");
+        return 0;
+    }
+
+    /* copy over keys, options, and dtls state struct */
+    return wolfSSL_dtls_export_state_internal(ssl, buf, *sz);
+}
+
+
+/* returns 0 on success */
+int wolfSSL_send_session(WOLFSSL* ssl)
+{
+    int ret;
+    byte* buf;
+    word16 bufSz = MAX_EXPORT_BUFFER;
+
+    WOLFSSL_ENTER("wolfSSL_send_session");
+
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    buf = (byte*)XMALLOC(bufSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (buf == NULL) {
+        return MEMORY_E;
+    }
+
+    /* if not DTLS do nothing */
+    if (!ssl->options.dtls) {
+        XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        WOLFSSL_MSG("Currently only DTLS export is supported");
+        return 0;
+    }
+
+    /* copy over keys, options, and dtls state struct */
+    ret = wolfSSL_dtls_export_internal(ssl, buf, bufSz);
+    if (ret < 0) {
+        XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return ret;
+    }
+
+    /* if no error ret has size of buffer */
+    ret = ssl->dtls_export(ssl, buf, ret, NULL);
+    if (ret != WOLFSSL_SUCCESS) {
+        XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return ret;
+    }
+
+    XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    return 0;
+}
+#endif /* WOLFSSL_DTLS */
+#endif /* WOLFSSL_SESSION_EXPORT */
+
+/* prevent multiple mutex initializations */
+static volatile WOLFSSL_GLOBAL int initRefCount = 0;
+static WOLFSSL_GLOBAL wolfSSL_Mutex count_mutex;   /* init ref count mutex */
+
+/* Create a new WOLFSSL_CTX struct and return the pointer to created struct.
+   WOLFSSL_METHOD pointer passed in is given to ctx to manage.
+   This function frees the passed in WOLFSSL_METHOD struct on failure and on
+   success is freed when ctx is freed.
+ */
+WOLFSSL_CTX* wolfSSL_CTX_new_ex(WOLFSSL_METHOD* method, void* heap)
+{
+    WOLFSSL_CTX* ctx = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_CTX_new_ex");
+
+    if (initRefCount == 0) {
+        /* user no longer forced to call Init themselves */
+        int ret = wolfSSL_Init();
+        if (ret != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("wolfSSL_Init failed");
+            WOLFSSL_LEAVE("WOLFSSL_CTX_new", 0);
+            if (method != NULL) {
+                XFREE(method, heap, DYNAMIC_TYPE_METHOD);
+            }
+            return NULL;
+        }
+    }
+
+    if (method == NULL)
+        return ctx;
+
+    ctx = (WOLFSSL_CTX*) XMALLOC(sizeof(WOLFSSL_CTX), heap, DYNAMIC_TYPE_CTX);
+    if (ctx) {
+        int ret;
+
+        ret = InitSSL_Ctx(ctx, method, heap);
+    #ifdef WOLFSSL_STATIC_MEMORY
+        if (heap != NULL) {
+            ctx->onHeap = 1; /* free the memory back to heap when done */
+        }
+    #endif
+        if (ret < 0) {
+            WOLFSSL_MSG("Init CTX failed");
+            wolfSSL_CTX_free(ctx);
+            ctx = NULL;
+        }
+#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) \
+                           && !defined(NO_SHA256) && !defined(WC_NO_RNG)
+        else {
+            ctx->srp = (Srp*) XMALLOC(sizeof(Srp), heap, DYNAMIC_TYPE_SRP);
+            if (ctx->srp == NULL){
+                WOLFSSL_MSG("Init CTX failed");
+                wolfSSL_CTX_free(ctx);
+                return NULL;
+            }
+            XMEMSET(ctx->srp, 0, sizeof(Srp));
+        }
+#endif
+    }
+    else {
+        WOLFSSL_MSG("Alloc CTX failed, method freed");
+        XFREE(method, heap, DYNAMIC_TYPE_METHOD);
+    }
+
+
+    WOLFSSL_LEAVE("WOLFSSL_CTX_new", 0);
+    return ctx;
+}
+
+
+WOLFSSL_ABI
+WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD* method)
+{
+#ifdef WOLFSSL_HEAP_TEST
+    /* if testing the heap hint then set top level CTX to have test value */
+    return wolfSSL_CTX_new_ex(method, (void*)WOLFSSL_HEAP_TEST);
+#else
+    return wolfSSL_CTX_new_ex(method, NULL);
+#endif
+}
+
+#ifdef OPENSSL_EXTRA
+/* increases CTX reference count to track proper time to "free" */
+int wolfSSL_CTX_up_ref(WOLFSSL_CTX* ctx)
+{
+    int refCount = SSL_CTX_RefCount(ctx, 1);
+    return ((refCount > 1) ? 1 : 0);
+}
+#endif
+
+WOLFSSL_ABI
+void wolfSSL_CTX_free(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_ENTER("SSL_CTX_free");
+    if (ctx) {
+#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) \
+&& !defined(NO_SHA256) && !defined(WC_NO_RNG)
+        if (ctx->srp != NULL){
+            if (ctx->srp_password != NULL){
+                XFREE(ctx->srp_password, ctx->heap, DYNAMIC_TYPE_SRP);
+                ctx->srp_password = NULL;
+            }
+            wc_SrpTerm(ctx->srp);
+            XFREE(ctx->srp, ctx->heap, DYNAMIC_TYPE_SRP);
+            ctx->srp = NULL;
+        }
+#endif
+        FreeSSL_Ctx(ctx);
+    }
+
+    WOLFSSL_LEAVE("SSL_CTX_free", 0);
+}
+
+
+#ifdef HAVE_ENCRYPT_THEN_MAC
+/**
+ * Sets whether Encrypt-Then-MAC extension can be negotiated against context.
+ * The default value: enabled.
+ *
+ * ctx  SSL/TLS context.
+ * set  Whether to allow or not: 1 is allow and 0 is disallow.
+ * returns WOLFSSL_SUCCESS
+ */
+int wolfSSL_CTX_AllowEncryptThenMac(WOLFSSL_CTX *ctx, int set)
+{
+    ctx->disallowEncThenMac = !set;
+    return WOLFSSL_SUCCESS;
+}
+
+/**
+ * Sets whether Encrypt-Then-MAC extension can be negotiated against context.
+ * The default value comes from context.
+ *
+ * ctx  SSL/TLS context.
+ * set  Whether to allow or not: 1 is allow and 0 is disallow.
+ * returns WOLFSSL_SUCCESS
+ */
+int wolfSSL_AllowEncryptThenMac(WOLFSSL *ssl, int set)
+{
+    ssl->options.disallowEncThenMac = !set;
+    return WOLFSSL_SUCCESS;
+}
+#endif
+
+#ifdef SINGLE_THREADED
+/* no locking in single threaded mode, allow a CTX level rng to be shared with
+ * WOLFSSL objects, WOLFSSL_SUCCESS on ok */
+int wolfSSL_CTX_new_rng(WOLFSSL_CTX* ctx)
+{
+    WC_RNG* rng;
+    int     ret;
+
+    if (ctx == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), ctx->heap, DYNAMIC_TYPE_RNG);
+    if (rng == NULL) {
+        return MEMORY_E;
+    }
+
+#ifndef HAVE_FIPS
+    ret = wc_InitRng_ex(rng, ctx->heap, ctx->devId);
+#else
+    ret = wc_InitRng(rng);
+#endif
+    if (ret != 0) {
+        XFREE(rng, ctx->heap, DYNAMIC_TYPE_RNG);
+        return ret;
+    }
+
+    ctx->rng = rng;
+    return WOLFSSL_SUCCESS;
+}
+#endif
+
+
+WOLFSSL_ABI
+WOLFSSL* wolfSSL_new(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL* ssl = NULL;
+    int ret = 0;
+
+    (void)ret;
+    WOLFSSL_ENTER("SSL_new");
+
+    if (ctx == NULL)
+        return ssl;
+
+    ssl = (WOLFSSL*) XMALLOC(sizeof(WOLFSSL), ctx->heap, DYNAMIC_TYPE_SSL);
+    if (ssl)
+        if ( (ret = InitSSL(ssl, ctx, 0)) < 0) {
+            FreeSSL(ssl, ctx->heap);
+            ssl = 0;
+        }
+
+    WOLFSSL_LEAVE("SSL_new", ret);
+    return ssl;
+}
+
+
+WOLFSSL_ABI
+void wolfSSL_free(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("SSL_free");
+    if (ssl)
+        FreeSSL(ssl, ssl->ctx->heap);
+    WOLFSSL_LEAVE("SSL_free", 0);
+}
+
+
+int wolfSSL_is_server(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+    return ssl->options.side == WOLFSSL_SERVER_END;
+}
+
+#ifdef HAVE_WRITE_DUP
+
+/*
+ * Release resources around WriteDup object
+ *
+ * ssl WOLFSSL object
+ *
+ * no return, destruction so make best attempt
+*/
+void FreeWriteDup(WOLFSSL* ssl)
+{
+    int doFree = 0;
+
+    WOLFSSL_ENTER("FreeWriteDup");
+
+    if (ssl->dupWrite) {
+        if (wc_LockMutex(&ssl->dupWrite->dupMutex) == 0) {
+            ssl->dupWrite->dupCount--;
+            if (ssl->dupWrite->dupCount == 0) {
+                doFree = 1;
+            } else {
+                WOLFSSL_MSG("WriteDup count not zero, no full free");
+            }
+            wc_UnLockMutex(&ssl->dupWrite->dupMutex);
+        }
+    }
+
+    if (doFree) {
+        WOLFSSL_MSG("Doing WriteDup full free, count to zero");
+        wc_FreeMutex(&ssl->dupWrite->dupMutex);
+        XFREE(ssl->dupWrite, ssl->heap, DYNAMIC_TYPE_WRITEDUP);
+    }
+}
+
+
+/*
+ * duplicate existing ssl members into dup needed for writing
+ *
+ * dup write only WOLFSSL
+ * ssl existing WOLFSSL
+ *
+ * 0 on success
+*/
+static int DupSSL(WOLFSSL* dup, WOLFSSL* ssl)
+{
+    /* shared dupWrite setup */
+    ssl->dupWrite = (WriteDup*)XMALLOC(sizeof(WriteDup), ssl->heap,
+                                       DYNAMIC_TYPE_WRITEDUP);
+    if (ssl->dupWrite == NULL) {
+        return MEMORY_E;
+    }
+    XMEMSET(ssl->dupWrite, 0, sizeof(WriteDup));
+
+    if (wc_InitMutex(&ssl->dupWrite->dupMutex) != 0) {
+        XFREE(ssl->dupWrite, ssl->heap, DYNAMIC_TYPE_WRITEDUP);
+        ssl->dupWrite = NULL;
+        return BAD_MUTEX_E;
+    }
+    ssl->dupWrite->dupCount = 2;    /* both sides have a count to start */
+    dup->dupWrite = ssl->dupWrite; /* each side uses */
+
+    /* copy write parts over to dup writer */
+    XMEMCPY(&dup->specs,   &ssl->specs,   sizeof(CipherSpecs));
+    XMEMCPY(&dup->options, &ssl->options, sizeof(Options));
+    XMEMCPY(&dup->keys,    &ssl->keys,    sizeof(Keys));
+    XMEMCPY(&dup->encrypt, &ssl->encrypt, sizeof(Ciphers));
+    /* dup side now owns encrypt/write ciphers */
+    XMEMSET(&ssl->encrypt, 0, sizeof(Ciphers));
+
+    dup->IOCB_WriteCtx = ssl->IOCB_WriteCtx;
+    dup->wfd    = ssl->wfd;
+    dup->wflags = ssl->wflags;
+    dup->hmac   = ssl->hmac;
+#ifdef HAVE_TRUNCATED_HMAC
+    dup->truncated_hmac = ssl->truncated_hmac;
+#endif
+
+    /* unique side dup setup */
+    dup->dupSide = WRITE_DUP_SIDE;
+    ssl->dupSide = READ_DUP_SIDE;
+
+    return 0;
+}
+
+
+/*
+ * duplicate a WOLFSSL object post handshake for writing only
+ * turn existing object into read only.  Allows concurrent access from two
+ * different threads.
+ *
+ * ssl existing WOLFSSL object
+ *
+ * return dup'd WOLFSSL object on success
+*/
+WOLFSSL* wolfSSL_write_dup(WOLFSSL* ssl)
+{
+    WOLFSSL* dup = NULL;
+    int ret = 0;
+
+    (void)ret;
+    WOLFSSL_ENTER("wolfSSL_write_dup");
+
+    if (ssl == NULL) {
+        return ssl;
+    }
+
+    if (ssl->options.handShakeDone == 0) {
+        WOLFSSL_MSG("wolfSSL_write_dup called before handshake complete");
+        return NULL;
+    }
+
+    if (ssl->dupWrite) {
+        WOLFSSL_MSG("wolfSSL_write_dup already called once");
+        return NULL;
+    }
+
+    dup = (WOLFSSL*) XMALLOC(sizeof(WOLFSSL), ssl->ctx->heap, DYNAMIC_TYPE_SSL);
+    if (dup) {
+        if ( (ret = InitSSL(dup, ssl->ctx, 1)) < 0) {
+            FreeSSL(dup, ssl->ctx->heap);
+            dup = NULL;
+        } else if ( (ret = DupSSL(dup, ssl)) < 0) {
+            FreeSSL(dup, ssl->ctx->heap);
+            dup = NULL;
+        }
+    }
+
+    WOLFSSL_LEAVE("wolfSSL_write_dup", ret);
+
+    return dup;
+}
+
+
+/*
+ * Notify write dup side of fatal error or close notify
+ *
+ * ssl WOLFSSL object
+ * err Notify err
+ *
+ * 0 on success
+*/
+int NotifyWriteSide(WOLFSSL* ssl, int err)
+{
+    int ret;
+
+    WOLFSSL_ENTER("NotifyWriteSide");
+
+    ret = wc_LockMutex(&ssl->dupWrite->dupMutex);
+    if (ret == 0) {
+        ssl->dupWrite->dupErr = err;
+        ret = wc_UnLockMutex(&ssl->dupWrite->dupMutex);
+    }
+
+    return ret;
+}
+
+
+#endif /* HAVE_WRITE_DUP */
+
+
+#ifdef HAVE_POLY1305
+/* set if to use old poly 1 for yes 0 to use new poly */
+int wolfSSL_use_old_poly(WOLFSSL* ssl, int value)
+{
+    (void)ssl;
+    (void)value;
+
+#ifndef WOLFSSL_NO_TLS12
+    WOLFSSL_ENTER("SSL_use_old_poly");
+    WOLFSSL_MSG("Warning SSL connection auto detects old/new and this function"
+            "is depreciated");
+    ssl->options.oldPoly = (word16)value;
+    WOLFSSL_LEAVE("SSL_use_old_poly", 0);
+#endif
+    return 0;
+}
+#endif
+
+
+WOLFSSL_ABI
+int wolfSSL_set_fd(WOLFSSL* ssl, int fd)
+{
+    int ret;
+
+    WOLFSSL_ENTER("SSL_set_fd");
+
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    ret = wolfSSL_set_read_fd(ssl, fd);
+    if (ret == WOLFSSL_SUCCESS) {
+        ret = wolfSSL_set_write_fd(ssl, fd);
+    }
+
+    return ret;
+}
+
+
+int wolfSSL_set_read_fd(WOLFSSL* ssl, int fd)
+{
+    WOLFSSL_ENTER("SSL_set_read_fd");
+
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    ssl->rfd = fd;      /* not used directly to allow IO callbacks */
+    ssl->IOCB_ReadCtx  = &ssl->rfd;
+
+    #ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls) {
+            ssl->IOCB_ReadCtx = &ssl->buffers.dtlsCtx;
+            ssl->buffers.dtlsCtx.rfd = fd;
+        }
+    #endif
+
+    WOLFSSL_LEAVE("SSL_set_read_fd", WOLFSSL_SUCCESS);
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_set_write_fd(WOLFSSL* ssl, int fd)
+{
+    WOLFSSL_ENTER("SSL_set_write_fd");
+
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    ssl->wfd = fd;      /* not used directly to allow IO callbacks */
+    ssl->IOCB_WriteCtx  = &ssl->wfd;
+
+    #ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls) {
+            ssl->IOCB_WriteCtx = &ssl->buffers.dtlsCtx;
+            ssl->buffers.dtlsCtx.wfd = fd;
+        }
+    #endif
+
+    WOLFSSL_LEAVE("SSL_set_write_fd", WOLFSSL_SUCCESS);
+    return WOLFSSL_SUCCESS;
+}
+
+
+/**
+  * Get the name of cipher at priority level passed in.
+  */
+char* wolfSSL_get_cipher_list(int priority)
+{
+    const CipherSuiteInfo* ciphers = GetCipherNames();
+
+    if (priority >= GetCipherNamesSize() || priority < 0) {
+        return 0;
+    }
+
+    return (char*)ciphers[priority].name;
+}
+
+
+/**
+  * Get the name of cipher at priority level passed in.
+  */
+char* wolfSSL_get_cipher_list_ex(WOLFSSL* ssl, int priority)
+{
+
+    if (ssl == NULL) {
+        return NULL;
+    }
+    else {
+        const char* cipher;
+
+        if ((cipher = wolfSSL_get_cipher_name_internal(ssl)) != NULL) {
+            if (priority == 0) {
+                return (char*)cipher;
+            }
+            else {
+                return NULL;
+            }
+        }
+        else {
+            return wolfSSL_get_cipher_list(priority);
+        }
+    }
+}
+
+
+int wolfSSL_get_ciphers(char* buf, int len)
+{
+    const CipherSuiteInfo* ciphers = GetCipherNames();
+    int ciphersSz = GetCipherNamesSize();
+    int i;
+    int cipherNameSz;
+
+    if (buf == NULL || len <= 0)
+        return BAD_FUNC_ARG;
+
+    /* Add each member to the buffer delimited by a : */
+    for (i = 0; i < ciphersSz; i++) {
+        cipherNameSz = (int)XSTRLEN(ciphers[i].name);
+        if (cipherNameSz + 1 < len) {
+            XSTRNCPY(buf, ciphers[i].name, len);
+            buf += cipherNameSz;
+
+            if (i < ciphersSz - 1)
+                *buf++ = ':';
+            *buf = 0;
+
+            len -= cipherNameSz + 1;
+        }
+        else
+            return BUFFER_E;
+    }
+    return WOLFSSL_SUCCESS;
+}
+
+
+#ifndef NO_ERROR_STRINGS
+/* places a list of all supported cipher suites in TLS_* format into "buf"
+ * return WOLFSSL_SUCCESS on success */
+int wolfSSL_get_ciphers_iana(char* buf, int len)
+{
+    const CipherSuiteInfo* ciphers = GetCipherNames();
+    int ciphersSz = GetCipherNamesSize();
+    int i;
+    int cipherNameSz;
+
+    if (buf == NULL || len <= 0)
+        return BAD_FUNC_ARG;
+
+    /* Add each member to the buffer delimited by a : */
+    for (i = 0; i < ciphersSz; i++) {
+        cipherNameSz = (int)XSTRLEN(ciphers[i].name_iana);
+        if (cipherNameSz + 1 < len) {
+            XSTRNCPY(buf, ciphers[i].name_iana, len);
+            buf += cipherNameSz;
+
+            if (i < ciphersSz - 1)
+                *buf++ = ':';
+            *buf = 0;
+
+            len -= cipherNameSz + 1;
+        }
+        else
+            return BUFFER_E;
+    }
+    return WOLFSSL_SUCCESS;
+}
+#endif /* NO_ERROR_STRINGS */
+
+
+const char* wolfSSL_get_shared_ciphers(WOLFSSL* ssl, char* buf, int len)
+{
+    const char* cipher;
+
+    if (ssl == NULL)
+        return NULL;
+
+    cipher = wolfSSL_get_cipher_name_iana(ssl);
+    len = min(len, (int)(XSTRLEN(cipher) + 1));
+    XMEMCPY(buf, cipher, len);
+    return buf;
+}
+
+int wolfSSL_get_fd(const WOLFSSL* ssl)
+{
+    int fd = -1;
+    WOLFSSL_ENTER("SSL_get_fd");
+    if (ssl) {
+        fd = ssl->rfd;
+    }
+    WOLFSSL_LEAVE("SSL_get_fd", fd);
+    return fd;
+}
+
+
+int wolfSSL_dtls(WOLFSSL* ssl)
+{
+    int dtlsOpt = 0;
+    if (ssl)
+        dtlsOpt = ssl->options.dtls;
+    return dtlsOpt;
+}
+
+#if !defined(NO_CERTS)
+/* Set whether mutual authentication is required for connections.
+ * Server side only.
+ *
+ * ctx  The SSL/TLS CTX object.
+ * req  1 to indicate required and 0 when not.
+ * returns BAD_FUNC_ARG when ctx is NULL, SIDE_ERROR when not a server and
+ * 0 on success.
+ */
+int wolfSSL_CTX_mutual_auth(WOLFSSL_CTX* ctx, int req)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+    if (ctx->method->side == WOLFSSL_CLIENT_END)
+        return SIDE_ERROR;
+
+    ctx->mutualAuth = (byte)req;
+
+    return 0;
+}
+
+/* Set whether mutual authentication is required for the connection.
+ * Server side only.
+ *
+ * ssl  The SSL/TLS object.
+ * req  1 to indicate required and 0 when not.
+ * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3,
+ * SIDE_ERROR when not a client and 0 on success.
+ */
+int wolfSSL_mutual_auth(WOLFSSL* ssl, int req)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+    if (ssl->options.side == WOLFSSL_SERVER_END)
+        return SIDE_ERROR;
+
+    ssl->options.mutualAuth = (word16)req;
+
+    return 0;
+}
+#endif /* NO_CERTS */
+
+#ifndef WOLFSSL_LEANPSK
+int wolfSSL_dtls_set_peer(WOLFSSL* ssl, void* peer, unsigned int peerSz)
+{
+#ifdef WOLFSSL_DTLS
+    void* sa;
+
+    if (ssl == NULL)
+        return WOLFSSL_FAILURE;
+
+    sa = (void*)XMALLOC(peerSz, ssl->heap, DYNAMIC_TYPE_SOCKADDR);
+    if (sa != NULL) {
+        if (ssl->buffers.dtlsCtx.peer.sa != NULL) {
+            XFREE(ssl->buffers.dtlsCtx.peer.sa,ssl->heap,DYNAMIC_TYPE_SOCKADDR);
+            ssl->buffers.dtlsCtx.peer.sa = NULL;
+        }
+        XMEMCPY(sa, peer, peerSz);
+        ssl->buffers.dtlsCtx.peer.sa = sa;
+        ssl->buffers.dtlsCtx.peer.sz = peerSz;
+        return WOLFSSL_SUCCESS;
+    }
+    return WOLFSSL_FAILURE;
+#else
+    (void)ssl;
+    (void)peer;
+    (void)peerSz;
+    return WOLFSSL_NOT_IMPLEMENTED;
+#endif
+}
+
+int wolfSSL_dtls_get_peer(WOLFSSL* ssl, void* peer, unsigned int* peerSz)
+{
+#ifdef WOLFSSL_DTLS
+    if (ssl == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if (peer != NULL && peerSz != NULL
+            && *peerSz >= ssl->buffers.dtlsCtx.peer.sz
+            && ssl->buffers.dtlsCtx.peer.sa != NULL) {
+        *peerSz = ssl->buffers.dtlsCtx.peer.sz;
+        XMEMCPY(peer, ssl->buffers.dtlsCtx.peer.sa, *peerSz);
+        return WOLFSSL_SUCCESS;
+    }
+    return WOLFSSL_FAILURE;
+#else
+    (void)ssl;
+    (void)peer;
+    (void)peerSz;
+    return WOLFSSL_NOT_IMPLEMENTED;
+#endif
+}
+
+
+#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS)
+
+int wolfSSL_CTX_dtls_set_sctp(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_dtls_set_sctp()");
+
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    ctx->dtlsSctp = 1;
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_dtls_set_sctp(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_dtls_set_sctp()");
+
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    ssl->options.dtlsSctp = 1;
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* WOLFSSL_DTLS && WOLFSSL_SCTP */
+
+#if (defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)) && \
+                                                           defined(WOLFSSL_DTLS)
+
+int wolfSSL_CTX_dtls_set_mtu(WOLFSSL_CTX* ctx, word16 newMtu)
+{
+    if (ctx == NULL || newMtu > MAX_RECORD_SIZE)
+        return BAD_FUNC_ARG;
+
+    ctx->dtlsMtuSz = newMtu;
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_dtls_set_mtu(WOLFSSL* ssl, word16 newMtu)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    if (newMtu > MAX_RECORD_SIZE) {
+        ssl->error = BAD_FUNC_ARG;
+        return WOLFSSL_FAILURE;
+    }
+
+    ssl->dtlsMtuSz = newMtu;
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* WOLFSSL_DTLS && (WOLFSSL_SCTP || WOLFSSL_DTLS_MTU) */
+
+
+#ifdef WOLFSSL_DTLS_DROP_STATS
+
+int wolfSSL_dtls_get_drop_stats(WOLFSSL* ssl,
+                                word32* macDropCount, word32* replayDropCount)
+{
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_dtls_get_drop_stats()");
+
+    if (ssl == NULL)
+        ret = BAD_FUNC_ARG;
+    else {
+        ret = WOLFSSL_SUCCESS;
+        if (macDropCount != NULL)
+            *macDropCount = ssl->macDropCount;
+        if (replayDropCount != NULL)
+            *replayDropCount = ssl->replayDropCount;
+    }
+
+    WOLFSSL_LEAVE("wolfSSL_dtls_get_drop_stats()", ret);
+    return ret;
+}
+
+#endif /* WOLFSSL_DTLS_DROP_STATS */
+
+
+#if defined(WOLFSSL_MULTICAST)
+
+int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX* ctx, word16 id)
+{
+    int ret = 0;
+
+    WOLFSSL_ENTER("wolfSSL_CTX_mcast_set_member_id()");
+
+    if (ctx == NULL || id > 255)
+        ret = BAD_FUNC_ARG;
+
+    if (ret == 0) {
+        ctx->haveEMS = 0;
+        ctx->haveMcast = 1;
+        ctx->mcastID = (byte)id;
+#ifndef WOLFSSL_USER_IO
+        ctx->CBIORecv = EmbedReceiveFromMcast;
+#endif /* WOLFSSL_USER_IO */
+
+        ret = WOLFSSL_SUCCESS;
+    }
+    WOLFSSL_LEAVE("wolfSSL_CTX_mcast_set_member_id()", ret);
+    return ret;
+}
+
+int wolfSSL_mcast_get_max_peers(void)
+{
+    return WOLFSSL_MULTICAST_PEERS;
+}
+
+#ifdef WOLFSSL_DTLS
+static WC_INLINE word32 UpdateHighwaterMark(word32 cur, word32 first,
+                                         word32 second, word32 max)
+{
+    word32 newCur = 0;
+
+    if (cur < first)
+        newCur = first;
+    else if (cur < second)
+        newCur = second;
+    else if (cur < max)
+        newCur = max;
+
+    return newCur;
+}
+#endif /* WOLFSSL_DTLS */
+
+
+int wolfSSL_set_secret(WOLFSSL* ssl, word16 epoch,
+                       const byte* preMasterSecret, word32 preMasterSz,
+                       const byte* clientRandom, const byte* serverRandom,
+                       const byte* suite)
+{
+    int ret = 0;
+
+    WOLFSSL_ENTER("wolfSSL_set_secret()");
+
+    if (ssl == NULL || preMasterSecret == NULL ||
+        preMasterSz == 0 || preMasterSz > ENCRYPT_LEN ||
+        clientRandom == NULL || serverRandom == NULL || suite == NULL) {
+
+        ret = BAD_FUNC_ARG;
+    }
+
+    if (ret == 0) {
+        XMEMCPY(ssl->arrays->preMasterSecret, preMasterSecret, preMasterSz);
+        ssl->arrays->preMasterSz = preMasterSz;
+        XMEMCPY(ssl->arrays->clientRandom, clientRandom, RAN_LEN);
+        XMEMCPY(ssl->arrays->serverRandom, serverRandom, RAN_LEN);
+        ssl->options.cipherSuite0 = suite[0];
+        ssl->options.cipherSuite = suite[1];
+
+        ret = SetCipherSpecs(ssl);
+    }
+
+    if (ret == 0)
+        ret = MakeTlsMasterSecret(ssl);
+
+    if (ret == 0) {
+        ssl->keys.encryptionOn = 1;
+        ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE);
+    }
+
+    if (ret == 0) {
+        if (ssl->options.dtls) {
+        #ifdef WOLFSSL_DTLS
+            WOLFSSL_DTLS_PEERSEQ* peerSeq;
+            int i;
+
+            ssl->keys.dtls_epoch = epoch;
+            for (i = 0, peerSeq = ssl->keys.peerSeq;
+                 i < WOLFSSL_DTLS_PEERSEQ_SZ;
+                 i++, peerSeq++) {
+
+                peerSeq->nextEpoch = epoch;
+                peerSeq->prevSeq_lo = peerSeq->nextSeq_lo;
+                peerSeq->prevSeq_hi = peerSeq->nextSeq_hi;
+                peerSeq->nextSeq_lo = 0;
+                peerSeq->nextSeq_hi = 0;
+                XMEMCPY(peerSeq->prevWindow, peerSeq->window, DTLS_SEQ_SZ);
+                XMEMSET(peerSeq->window, 0, DTLS_SEQ_SZ);
+                peerSeq->highwaterMark = UpdateHighwaterMark(0,
+                        ssl->ctx->mcastFirstSeq,
+                        ssl->ctx->mcastSecondSeq,
+                        ssl->ctx->mcastMaxSeq);
+            }
+        #else
+            (void)epoch;
+        #endif
+        }
+        FreeHandshakeResources(ssl);
+        ret = WOLFSSL_SUCCESS;
+    }
+    else {
+        if (ssl)
+            ssl->error = ret;
+        ret = WOLFSSL_FATAL_ERROR;
+    }
+    WOLFSSL_LEAVE("wolfSSL_set_secret()", ret);
+    return ret;
+}
+
+
+#ifdef WOLFSSL_DTLS
+
+int wolfSSL_mcast_peer_add(WOLFSSL* ssl, word16 peerId, int remove)
+{
+    WOLFSSL_DTLS_PEERSEQ* p = NULL;
+    int ret = WOLFSSL_SUCCESS;
+    int i;
+
+    WOLFSSL_ENTER("wolfSSL_mcast_peer_add()");
+    if (ssl == NULL || peerId > 255)
+        return BAD_FUNC_ARG;
+
+    if (!remove) {
+        /* Make sure it isn't already present, while keeping the first
+         * open spot. */
+        for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) {
+            if (ssl->keys.peerSeq[i].peerId == INVALID_PEER_ID)
+                p = &ssl->keys.peerSeq[i];
+            if (ssl->keys.peerSeq[i].peerId == peerId) {
+                WOLFSSL_MSG("Peer ID already in multicast peer list.");
+                p = NULL;
+            }
+        }
+
+        if (p != NULL) {
+            XMEMSET(p, 0, sizeof(WOLFSSL_DTLS_PEERSEQ));
+            p->peerId = peerId;
+            p->highwaterMark = UpdateHighwaterMark(0,
+                ssl->ctx->mcastFirstSeq,
+                ssl->ctx->mcastSecondSeq,
+                ssl->ctx->mcastMaxSeq);
+        }
+        else {
+            WOLFSSL_MSG("No room in peer list.");
+            ret = -1;
+        }
+    }
+    else {
+        for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) {
+            if (ssl->keys.peerSeq[i].peerId == peerId)
+                p = &ssl->keys.peerSeq[i];
+        }
+
+        if (p != NULL) {
+            p->peerId = INVALID_PEER_ID;
+        }
+        else {
+            WOLFSSL_MSG("Peer not found in list.");
+        }
+    }
+
+    WOLFSSL_LEAVE("wolfSSL_mcast_peer_add()", ret);
+    return ret;
+}
+
+
+/* If peerId is in the list of peers and its last sequence number is non-zero,
+ * return 1, otherwise return 0. */
+int wolfSSL_mcast_peer_known(WOLFSSL* ssl, unsigned short peerId)
+{
+    int known = 0;
+    int i;
+
+    WOLFSSL_ENTER("wolfSSL_mcast_peer_known()");
+
+    if (ssl == NULL || peerId > 255) {
+        return BAD_FUNC_ARG;
+    }
+
+    for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) {
+        if (ssl->keys.peerSeq[i].peerId == peerId) {
+            if (ssl->keys.peerSeq[i].nextSeq_hi ||
+                ssl->keys.peerSeq[i].nextSeq_lo) {
+
+                known = 1;
+            }
+            break;
+        }
+    }
+
+    WOLFSSL_LEAVE("wolfSSL_mcast_peer_known()", known);
+    return known;
+}
+
+
+int wolfSSL_CTX_mcast_set_highwater_cb(WOLFSSL_CTX* ctx, word32 maxSeq,
+                                       word32 first, word32 second,
+                                       CallbackMcastHighwater cb)
+{
+    if (ctx == NULL || (second && first > second) ||
+        first > maxSeq || second > maxSeq || cb == NULL) {
+
+        return BAD_FUNC_ARG;
+    }
+
+    ctx->mcastHwCb = cb;
+    ctx->mcastFirstSeq = first;
+    ctx->mcastSecondSeq = second;
+    ctx->mcastMaxSeq = maxSeq;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_mcast_set_highwater_ctx(WOLFSSL* ssl, void* ctx)
+{
+    if (ssl == NULL || ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    ssl->mcastHwCbCtx = ctx;
+
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* WOLFSSL_DTLS */
+
+#endif /* WOLFSSL_MULTICAST */
+
+
+#endif /* WOLFSSL_LEANPSK */
+
+
+/* return underlying connect or accept, WOLFSSL_SUCCESS on ok */
+int wolfSSL_negotiate(WOLFSSL* ssl)
+{
+    int err = WOLFSSL_FATAL_ERROR;
+
+    WOLFSSL_ENTER("wolfSSL_negotiate");
+#ifndef NO_WOLFSSL_SERVER
+    if (ssl->options.side == WOLFSSL_SERVER_END) {
+#ifdef WOLFSSL_TLS13
+        if (IsAtLeastTLSv1_3(ssl->version))
+            err = wolfSSL_accept_TLSv13(ssl);
+        else
+#endif
+            err = wolfSSL_accept(ssl);
+    }
+#endif
+
+#ifndef NO_WOLFSSL_CLIENT
+    if (ssl->options.side == WOLFSSL_CLIENT_END) {
+#ifdef WOLFSSL_TLS13
+        if (IsAtLeastTLSv1_3(ssl->version))
+            err = wolfSSL_connect_TLSv13(ssl);
+        else
+#endif
+            err = wolfSSL_connect(ssl);
+    }
+#endif
+
+    (void)ssl;
+
+    WOLFSSL_LEAVE("wolfSSL_negotiate", err);
+
+    return err;
+}
+
+
+WOLFSSL_ABI
+WC_RNG* wolfSSL_GetRNG(WOLFSSL* ssl)
+{
+    if (ssl) {
+        return ssl->rng;
+    }
+
+    return NULL;
+}
+
+
+#ifndef WOLFSSL_LEANPSK
+/* object size based on build */
+int wolfSSL_GetObjectSize(void)
+{
+#ifdef SHOW_SIZES
+    printf("sizeof suites           = %lu\n", (unsigned long)sizeof(Suites));
+    printf("sizeof ciphers(2)       = %lu\n", (unsigned long)sizeof(Ciphers));
+#ifndef NO_RC4
+    printf("\tsizeof arc4         = %lu\n", (unsigned long)sizeof(Arc4));
+#endif
+    printf("\tsizeof aes          = %lu\n", (unsigned long)sizeof(Aes));
+#ifndef NO_DES3
+    printf("\tsizeof des3         = %lu\n", (unsigned long)sizeof(Des3));
+#endif
+#ifndef NO_RABBIT
+    printf("\tsizeof rabbit       = %lu\n", (unsigned long)sizeof(Rabbit));
+#endif
+#ifdef HAVE_CHACHA
+    printf("\tsizeof chacha       = %lu\n", (unsigned long)sizeof(ChaCha));
+#endif
+    printf("sizeof cipher specs     = %lu\n", (unsigned long)sizeof(CipherSpecs));
+    printf("sizeof keys             = %lu\n", (unsigned long)sizeof(Keys));
+    printf("sizeof Hashes(2)        = %lu\n", (unsigned long)sizeof(Hashes));
+#ifndef NO_MD5
+    printf("\tsizeof MD5          = %lu\n", (unsigned long)sizeof(wc_Md5));
+#endif
+#ifndef NO_SHA
+    printf("\tsizeof SHA          = %lu\n", (unsigned long)sizeof(wc_Sha));
+#endif
+#ifdef WOLFSSL_SHA224
+    printf("\tsizeof SHA224       = %lu\n", (unsigned long)sizeof(wc_Sha224));
+#endif
+#ifndef NO_SHA256
+    printf("\tsizeof SHA256       = %lu\n", (unsigned long)sizeof(wc_Sha256));
+#endif
+#ifdef WOLFSSL_SHA384
+    printf("\tsizeof SHA384       = %lu\n", (unsigned long)sizeof(wc_Sha384));
+#endif
+#ifdef WOLFSSL_SHA384
+    printf("\tsizeof SHA512       = %lu\n", (unsigned long)sizeof(wc_Sha512));
+#endif
+    printf("sizeof Buffers          = %lu\n", (unsigned long)sizeof(Buffers));
+    printf("sizeof Options          = %lu\n", (unsigned long)sizeof(Options));
+    printf("sizeof Arrays           = %lu\n", (unsigned long)sizeof(Arrays));
+#ifndef NO_RSA
+    printf("sizeof RsaKey           = %lu\n", (unsigned long)sizeof(RsaKey));
+#endif
+#ifdef HAVE_ECC
+    printf("sizeof ecc_key          = %lu\n", (unsigned long)sizeof(ecc_key));
+#endif
+    printf("sizeof WOLFSSL_CIPHER    = %lu\n", (unsigned long)sizeof(WOLFSSL_CIPHER));
+    printf("sizeof WOLFSSL_SESSION   = %lu\n", (unsigned long)sizeof(WOLFSSL_SESSION));
+    printf("sizeof WOLFSSL           = %lu\n", (unsigned long)sizeof(WOLFSSL));
+    printf("sizeof WOLFSSL_CTX       = %lu\n", (unsigned long)sizeof(WOLFSSL_CTX));
+#endif
+
+    return sizeof(WOLFSSL);
+}
+
+int wolfSSL_CTX_GetObjectSize(void)
+{
+    return sizeof(WOLFSSL_CTX);
+}
+
+int wolfSSL_METHOD_GetObjectSize(void)
+{
+    return sizeof(WOLFSSL_METHOD);
+}
+#endif
+
+
+#ifdef WOLFSSL_STATIC_MEMORY
+
+int wolfSSL_CTX_load_static_memory(WOLFSSL_CTX** ctx, wolfSSL_method_func method,
+                                   unsigned char* buf, unsigned int sz,
+                                   int flag, int max)
+{
+    WOLFSSL_HEAP*      heap;
+    WOLFSSL_HEAP_HINT* hint;
+    word32 idx = 0;
+
+    if (ctx == NULL || buf == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (*ctx == NULL && method == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (*ctx == NULL || (*ctx)->heap == NULL) {
+        if (sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT) > sz - idx) {
+            return BUFFER_E; /* not enough memory for structures */
+        }
+        heap = (WOLFSSL_HEAP*)buf;
+        idx += sizeof(WOLFSSL_HEAP);
+        if (wolfSSL_init_memory_heap(heap) != 0) {
+            return WOLFSSL_FAILURE;
+        }
+        hint = (WOLFSSL_HEAP_HINT*)(buf + idx);
+        idx += sizeof(WOLFSSL_HEAP_HINT);
+        XMEMSET(hint, 0, sizeof(WOLFSSL_HEAP_HINT));
+        hint->memory = heap;
+
+        if (*ctx && (*ctx)->heap == NULL) {
+            (*ctx)->heap = (void*)hint;
+        }
+    }
+    else {
+#ifdef WOLFSSL_HEAP_TEST
+        /* do not load in memory if test has been set */
+        if ((*ctx)->heap == (void*)WOLFSSL_HEAP_TEST) {
+            return WOLFSSL_SUCCESS;
+        }
+#endif
+        hint = (WOLFSSL_HEAP_HINT*)((*ctx)->heap);
+        heap = hint->memory;
+    }
+
+    if (wolfSSL_load_static_memory(buf + idx, sz - idx, flag, heap) != 1) {
+        WOLFSSL_MSG("Error partitioning memory");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* create ctx if needed */
+    if (*ctx == NULL) {
+        *ctx = wolfSSL_CTX_new_ex(method(hint), hint);
+        if (*ctx == NULL) {
+            WOLFSSL_MSG("Error creating ctx");
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+    /* determine what max applies too */
+    if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) {
+        heap->maxIO = max;
+    }
+    else { /* general memory used in handshakes */
+        heap->maxHa = max;
+    }
+
+    heap->flag |= flag;
+
+    (void)max;
+    (void)method;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_is_static_memory(WOLFSSL* ssl, WOLFSSL_MEM_CONN_STATS* mem_stats)
+{
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+    WOLFSSL_ENTER("wolfSSL_is_static_memory");
+
+    /* fill out statistics if wanted and WOLFMEM_TRACK_STATS flag */
+    if (mem_stats != NULL && ssl->heap != NULL) {
+        WOLFSSL_HEAP_HINT* hint = ((WOLFSSL_HEAP_HINT*)(ssl->heap));
+        WOLFSSL_HEAP* heap      = hint->memory;
+        if (heap->flag & WOLFMEM_TRACK_STATS && hint->stats != NULL) {
+            XMEMCPY(mem_stats, hint->stats, sizeof(WOLFSSL_MEM_CONN_STATS));
+        }
+    }
+
+    return (ssl->heap) ? 1 : 0;
+}
+
+
+int wolfSSL_CTX_is_static_memory(WOLFSSL_CTX* ctx, WOLFSSL_MEM_STATS* mem_stats)
+{
+    if (ctx == NULL) {
+        return BAD_FUNC_ARG;
+    }
+    WOLFSSL_ENTER("wolfSSL_CTX_is_static_memory");
+
+    /* fill out statistics if wanted */
+    if (mem_stats != NULL && ctx->heap != NULL) {
+        WOLFSSL_HEAP* heap = ((WOLFSSL_HEAP_HINT*)(ctx->heap))->memory;
+        if (wolfSSL_GetMemStats(heap, mem_stats) != 1) {
+            return MEMORY_E;
+        }
+    }
+
+    return (ctx->heap) ? 1 : 0;
+}
+
+#endif /* WOLFSSL_STATIC_MEMORY */
+
+
+/* return max record layer size plaintext input size */
+int wolfSSL_GetMaxOutputSize(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_GetMaxOutputSize");
+
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    if (ssl->options.handShakeState != HANDSHAKE_DONE) {
+        WOLFSSL_MSG("Handshake not complete yet");
+        return BAD_FUNC_ARG;
+    }
+
+    return wolfSSL_GetMaxRecordSize(ssl, OUTPUT_RECORD_SIZE);
+}
+
+
+/* return record layer size of plaintext input size */
+int wolfSSL_GetOutputSize(WOLFSSL* ssl, int inSz)
+{
+    int maxSize;
+
+    WOLFSSL_ENTER("wolfSSL_GetOutputSize");
+
+    if (inSz < 0)
+        return BAD_FUNC_ARG;
+
+    maxSize = wolfSSL_GetMaxOutputSize(ssl);
+    if (maxSize < 0)
+        return maxSize;   /* error */
+    if (inSz > maxSize)
+        return INPUT_SIZE_E;
+
+    return BuildMessage(ssl, NULL, 0, NULL, inSz, application_data, 0, 1, 0);
+}
+
+
+#ifdef HAVE_ECC
+int wolfSSL_CTX_SetMinEccKey_Sz(WOLFSSL_CTX* ctx, short keySz)
+{
+    if (ctx == NULL || keySz < 0 || keySz % 8 != 0) {
+        WOLFSSL_MSG("Key size must be divisible by 8 or ctx was null");
+        return BAD_FUNC_ARG;
+    }
+
+    ctx->minEccKeySz     = keySz / 8;
+#ifndef NO_CERTS
+    ctx->cm->minEccKeySz = keySz / 8;
+#endif
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_SetMinEccKey_Sz(WOLFSSL* ssl, short keySz)
+{
+    if (ssl == NULL || keySz < 0 || keySz % 8 != 0) {
+        WOLFSSL_MSG("Key size must be divisible by 8 or ssl was null");
+        return BAD_FUNC_ARG;
+    }
+
+    ssl->options.minEccKeySz = keySz / 8;
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* !NO_RSA */
+
+#ifndef NO_RSA
+int wolfSSL_CTX_SetMinRsaKey_Sz(WOLFSSL_CTX* ctx, short keySz)
+{
+    if (ctx == NULL || keySz < 0 || keySz % 8 != 0) {
+        WOLFSSL_MSG("Key size must be divisible by 8 or ctx was null");
+        return BAD_FUNC_ARG;
+    }
+
+    ctx->minRsaKeySz     = keySz / 8;
+    ctx->cm->minRsaKeySz = keySz / 8;
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_SetMinRsaKey_Sz(WOLFSSL* ssl, short keySz)
+{
+    if (ssl == NULL || keySz < 0 || keySz % 8 != 0) {
+        WOLFSSL_MSG("Key size must be divisible by 8 or ssl was null");
+        return BAD_FUNC_ARG;
+    }
+
+    ssl->options.minRsaKeySz = keySz / 8;
+    return WOLFSSL_SUCCESS;
+}
+#endif /* !NO_RSA */
+
+#ifndef NO_DH
+/* server Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */
+int wolfSSL_SetTmpDH(WOLFSSL* ssl, const unsigned char* p, int pSz,
+                    const unsigned char* g, int gSz)
+{
+    WOLFSSL_ENTER("wolfSSL_SetTmpDH");
+
+    if (ssl == NULL || p == NULL || g == NULL)
+        return BAD_FUNC_ARG;
+
+    if ((word16)pSz < ssl->options.minDhKeySz)
+        return DH_KEY_SIZE_E;
+    if ((word16)pSz > ssl->options.maxDhKeySz)
+        return DH_KEY_SIZE_E;
+
+    /* this function is for server only */
+    if (ssl->options.side == WOLFSSL_CLIENT_END)
+        return SIDE_ERROR;
+
+    #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \
+        !defined(HAVE_SELFTEST)
+        ssl->options.dhKeyTested = 0;
+        ssl->options.dhDoKeyTest = 1;
+    #endif
+
+    if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) {
+        XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        ssl->buffers.serverDH_P.buffer = NULL;
+    }
+    if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) {
+        XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        ssl->buffers.serverDH_G.buffer = NULL;
+    }
+
+    ssl->buffers.weOwnDH = 1;  /* SSL owns now */
+    ssl->buffers.serverDH_P.buffer = (byte*)XMALLOC(pSz, ssl->heap,
+                                                    DYNAMIC_TYPE_PUBLIC_KEY);
+    if (ssl->buffers.serverDH_P.buffer == NULL)
+            return MEMORY_E;
+
+    ssl->buffers.serverDH_G.buffer = (byte*)XMALLOC(gSz, ssl->heap,
+                                                    DYNAMIC_TYPE_PUBLIC_KEY);
+    if (ssl->buffers.serverDH_G.buffer == NULL) {
+        XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        ssl->buffers.serverDH_P.buffer = NULL;
+        return MEMORY_E;
+    }
+
+    ssl->buffers.serverDH_P.length = pSz;
+    ssl->buffers.serverDH_G.length = gSz;
+
+    XMEMCPY(ssl->buffers.serverDH_P.buffer, p, pSz);
+    XMEMCPY(ssl->buffers.serverDH_G.buffer, g, gSz);
+
+    ssl->options.haveDH = 1;
+
+    if (ssl->options.side != WOLFSSL_NEITHER_END) {
+        word16 havePSK;
+        word16 haveRSA;
+        int    keySz   = 0;
+
+    #ifndef NO_PSK
+        havePSK = ssl->options.havePSK;
+    #else
+        havePSK = 0;
+    #endif
+    #ifdef NO_RSA
+        haveRSA = 0;
+    #else
+        haveRSA = 1;
+    #endif
+    #ifndef NO_CERTS
+        keySz = ssl->buffers.keySz;
+    #endif
+        InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
+                   ssl->options.haveDH, ssl->options.haveNTRU,
+                   ssl->options.haveECDSAsig, ssl->options.haveECC,
+                   ssl->options.haveStaticECC, ssl->options.side);
+    }
+
+    WOLFSSL_LEAVE("wolfSSL_SetTmpDH", 0);
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+#if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \
+    !defined(HAVE_SELFTEST)
+/* Enables or disables the session's DH key prime test. */
+int wolfSSL_SetEnableDhKeyTest(WOLFSSL* ssl, int enable)
+{
+    WOLFSSL_ENTER("wolfSSL_SetEnableDhKeyTest");
+
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    if (!enable)
+        ssl->options.dhDoKeyTest = 0;
+    else
+        ssl->options.dhDoKeyTest = 1;
+
+    WOLFSSL_LEAVE("wolfSSL_SetEnableDhKeyTest", WOLFSSL_SUCCESS);
+    return WOLFSSL_SUCCESS;
+}
+#endif
+
+
+/* server ctx Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */
+int wolfSSL_CTX_SetTmpDH(WOLFSSL_CTX* ctx, const unsigned char* p, int pSz,
+                         const unsigned char* g, int gSz)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_SetTmpDH");
+    if (ctx == NULL || p == NULL || g == NULL) return BAD_FUNC_ARG;
+
+    if ((word16)pSz < ctx->minDhKeySz)
+        return DH_KEY_SIZE_E;
+    if ((word16)pSz > ctx->maxDhKeySz)
+        return DH_KEY_SIZE_E;
+
+    #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \
+        !defined(HAVE_SELFTEST)
+    {
+        DhKey checkKey;
+        WC_RNG rng;
+        int error, freeKey = 0;
+
+        error = wc_InitRng(&rng);
+        if (!error)
+            error = wc_InitDhKey(&checkKey);
+        if (!error) {
+            freeKey = 1;
+            error = wc_DhSetCheckKey(&checkKey,
+                                 p, pSz, g, gSz, NULL, 0, 0, &rng);
+        }
+        if (freeKey)
+            wc_FreeDhKey(&checkKey);
+        wc_FreeRng(&rng);
+        if (error)
+            return error;
+
+        ctx->dhKeyTested = 1;
+    }
+    #endif
+
+    XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    ctx->serverDH_P.buffer = NULL;
+    XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    ctx->serverDH_G.buffer = NULL;
+
+    ctx->serverDH_P.buffer = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    if (ctx->serverDH_P.buffer == NULL)
+       return MEMORY_E;
+
+    ctx->serverDH_G.buffer = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    if (ctx->serverDH_G.buffer == NULL) {
+        XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        ctx->serverDH_P.buffer = NULL;
+        return MEMORY_E;
+    }
+
+    ctx->serverDH_P.length = pSz;
+    ctx->serverDH_G.length = gSz;
+
+    XMEMCPY(ctx->serverDH_P.buffer, p, pSz);
+    XMEMCPY(ctx->serverDH_G.buffer, g, gSz);
+
+    ctx->haveDH = 1;
+
+    WOLFSSL_LEAVE("wolfSSL_CTX_SetTmpDH", 0);
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_CTX_SetMinDhKey_Sz(WOLFSSL_CTX* ctx, word16 keySz)
+{
+    if (ctx == NULL || keySz > 16000 || keySz % 8 != 0)
+        return BAD_FUNC_ARG;
+
+    ctx->minDhKeySz = keySz / 8;
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_SetMinDhKey_Sz(WOLFSSL* ssl, word16 keySz)
+{
+    if (ssl == NULL || keySz > 16000 || keySz % 8 != 0)
+        return BAD_FUNC_ARG;
+
+    ssl->options.minDhKeySz = keySz / 8;
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_CTX_SetMaxDhKey_Sz(WOLFSSL_CTX* ctx, word16 keySz)
+{
+    if (ctx == NULL || keySz > 16000 || keySz % 8 != 0)
+        return BAD_FUNC_ARG;
+
+    ctx->maxDhKeySz = keySz / 8;
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_SetMaxDhKey_Sz(WOLFSSL* ssl, word16 keySz)
+{
+    if (ssl == NULL || keySz > 16000 || keySz % 8 != 0)
+        return BAD_FUNC_ARG;
+
+    ssl->options.maxDhKeySz = keySz / 8;
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_GetDhKey_Sz(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    return (ssl->options.dhKeySz * 8);
+}
+
+#endif /* !NO_DH */
+
+
+WOLFSSL_ABI
+int wolfSSL_write(WOLFSSL* ssl, const void* data, int sz)
+{
+    int ret;
+
+    WOLFSSL_ENTER("SSL_write()");
+
+    if (ssl == NULL || data == NULL || sz < 0)
+        return BAD_FUNC_ARG;
+
+#ifdef WOLFSSL_EARLY_DATA
+    if (ssl->earlyData != no_early_data && (ret = wolfSSL_negotiate(ssl)) < 0) {
+        ssl->error = ret;
+        return WOLFSSL_FATAL_ERROR;
+    }
+    ssl->earlyData = no_early_data;
+#endif
+
+#ifdef HAVE_WRITE_DUP
+    { /* local variable scope */
+        int dupErr = 0;   /* local copy */
+
+        ret = 0;
+
+        if (ssl->dupWrite && ssl->dupSide == READ_DUP_SIDE) {
+            WOLFSSL_MSG("Read dup side cannot write");
+            return WRITE_DUP_WRITE_E;
+        }
+        if (ssl->dupWrite) {
+            if (wc_LockMutex(&ssl->dupWrite->dupMutex) != 0) {
+                return BAD_MUTEX_E;
+            }
+            dupErr = ssl->dupWrite->dupErr;
+            ret = wc_UnLockMutex(&ssl->dupWrite->dupMutex);
+        }
+
+        if (ret != 0) {
+            ssl->error = ret;  /* high priority fatal error */
+            return WOLFSSL_FATAL_ERROR;
+        }
+        if (dupErr != 0) {
+            WOLFSSL_MSG("Write dup error from other side");
+            ssl->error = dupErr;
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+#endif
+
+#ifdef HAVE_ERRNO_H
+    errno = 0;
+#endif
+
+    #ifdef OPENSSL_EXTRA
+    if (ssl->CBIS != NULL) {
+        ssl->CBIS(ssl, SSL_CB_WRITE, SSL_SUCCESS);
+        ssl->cbmode = SSL_CB_WRITE;
+    }
+    #endif
+    ret = SendData(ssl, data, sz);
+
+    WOLFSSL_LEAVE("SSL_write()", ret);
+
+    if (ret < 0)
+        return WOLFSSL_FATAL_ERROR;
+    else
+        return ret;
+}
+
+static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek)
+{
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_read_internal()");
+
+    if (ssl == NULL || data == NULL || sz < 0)
+        return BAD_FUNC_ARG;
+
+#ifdef HAVE_WRITE_DUP
+    if (ssl->dupWrite && ssl->dupSide == WRITE_DUP_SIDE) {
+        WOLFSSL_MSG("Write dup side cannot read");
+        return WRITE_DUP_READ_E;
+    }
+#endif
+
+#ifdef HAVE_ERRNO_H
+        errno = 0;
+#endif
+
+#ifdef WOLFSSL_DTLS
+    if (ssl->options.dtls) {
+        ssl->dtls_expected_rx = max(sz + 100, MAX_MTU);
+#ifdef WOLFSSL_SCTP
+        if (ssl->options.dtlsSctp)
+#endif
+#if defined(WOLLSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)
+            ssl->dtls_expected_rx = max(ssl->dtls_expected_rx, ssl->dtlsMtuSz);
+#endif
+    }
+#endif
+
+    sz = wolfSSL_GetMaxRecordSize(ssl, sz);
+
+    ret = ReceiveData(ssl, (byte*)data, sz, peek);
+
+#ifdef HAVE_WRITE_DUP
+    if (ssl->dupWrite) {
+        if (ssl->error != 0 && ssl->error != WANT_READ
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            && ssl->error != WC_PENDING_E
+        #endif
+        ) {
+            int notifyErr;
+
+            WOLFSSL_MSG("Notifying write side of fatal read error");
+            notifyErr  = NotifyWriteSide(ssl, ssl->error);
+            if (notifyErr < 0) {
+                ret = ssl->error = notifyErr;
+            }
+        }
+    }
+#endif
+
+    WOLFSSL_LEAVE("wolfSSL_read_internal()", ret);
+
+    if (ret < 0)
+        return WOLFSSL_FATAL_ERROR;
+    else
+        return ret;
+}
+
+
+int wolfSSL_peek(WOLFSSL* ssl, void* data, int sz)
+{
+    WOLFSSL_ENTER("wolfSSL_peek()");
+
+    return wolfSSL_read_internal(ssl, data, sz, TRUE);
+}
+
+
+WOLFSSL_ABI
+int wolfSSL_read(WOLFSSL* ssl, void* data, int sz)
+{
+    WOLFSSL_ENTER("wolfSSL_read()");
+
+    #ifdef OPENSSL_EXTRA
+    if (ssl->CBIS != NULL) {
+        ssl->CBIS(ssl, SSL_CB_READ, SSL_SUCCESS);
+        ssl->cbmode = SSL_CB_READ;
+    }
+    #endif
+    return wolfSSL_read_internal(ssl, data, sz, FALSE);
+}
+
+
+#ifdef WOLFSSL_MULTICAST
+
+int wolfSSL_mcast_read(WOLFSSL* ssl, word16* id, void* data, int sz)
+{
+    int ret = 0;
+
+    WOLFSSL_ENTER("wolfSSL_mcast_read()");
+
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    ret = wolfSSL_read_internal(ssl, data, sz, FALSE);
+    if (ssl->options.dtls && ssl->options.haveMcast && id != NULL)
+        *id = ssl->keys.curPeerId;
+    return ret;
+}
+
+#endif /* WOLFSSL_MULTICAST */
+
+
+/* helpers to set the device id, WOLFSSL_SUCCESS on ok */
+WOLFSSL_ABI
+int wolfSSL_SetDevId(WOLFSSL* ssl, int devId)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    ssl->devId = devId;
+
+    return WOLFSSL_SUCCESS;
+}
+
+WOLFSSL_ABI
+int wolfSSL_CTX_SetDevId(WOLFSSL_CTX* ctx, int devId)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    ctx->devId = devId;
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* helpers to get device id and heap */
+WOLFSSL_ABI
+int wolfSSL_CTX_GetDevId(WOLFSSL_CTX* ctx, WOLFSSL* ssl)
+{
+    int devId = INVALID_DEVID;
+    if (ctx != NULL)
+        devId = ctx->devId;
+    else if (ssl != NULL)
+        devId = ssl->devId;
+    return devId;
+}
+void* wolfSSL_CTX_GetHeap(WOLFSSL_CTX* ctx, WOLFSSL* ssl)
+{
+    void* heap = NULL;
+    if (ctx != NULL)
+        heap = ctx->heap;
+    else if (ssl != NULL)
+        heap = ssl->heap;
+    return heap;
+}
+
+
+#ifdef HAVE_SNI
+
+WOLFSSL_ABI
+int wolfSSL_UseSNI(WOLFSSL* ssl, byte type, const void* data, word16 size)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    return TLSX_UseSNI(&ssl->extensions, type, data, size, ssl->heap);
+}
+
+
+WOLFSSL_ABI
+int wolfSSL_CTX_UseSNI(WOLFSSL_CTX* ctx, byte type, const void* data,
+                                                                    word16 size)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    return TLSX_UseSNI(&ctx->extensions, type, data, size, ctx->heap);
+}
+
+#ifndef NO_WOLFSSL_SERVER
+
+void wolfSSL_SNI_SetOptions(WOLFSSL* ssl, byte type, byte options)
+{
+    if (ssl && ssl->extensions)
+        TLSX_SNI_SetOptions(ssl->extensions, type, options);
+}
+
+
+void wolfSSL_CTX_SNI_SetOptions(WOLFSSL_CTX* ctx, byte type, byte options)
+{
+    if (ctx && ctx->extensions)
+        TLSX_SNI_SetOptions(ctx->extensions, type, options);
+}
+
+
+byte wolfSSL_SNI_Status(WOLFSSL* ssl, byte type)
+{
+    return TLSX_SNI_Status(ssl ? ssl->extensions : NULL, type);
+}
+
+
+word16 wolfSSL_SNI_GetRequest(WOLFSSL* ssl, byte type, void** data)
+{
+    if (data)
+        *data = NULL;
+
+    if (ssl && ssl->extensions)
+        return TLSX_SNI_GetRequest(ssl->extensions, type, data);
+
+    return 0;
+}
+
+
+int wolfSSL_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz,
+                              byte type, byte* sni, word32* inOutSz)
+{
+    if (clientHello && helloSz > 0 && sni && inOutSz && *inOutSz > 0)
+        return TLSX_SNI_GetFromBuffer(clientHello, helloSz, type, sni, inOutSz);
+
+    return BAD_FUNC_ARG;
+}
+
+#endif /* NO_WOLFSSL_SERVER */
+
+#endif /* HAVE_SNI */
+
+
+#ifdef HAVE_TRUSTED_CA
+
+WOLFSSL_API int wolfSSL_UseTrustedCA(WOLFSSL* ssl, byte type,
+            const byte* certId, word32 certIdSz)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    if (type == WOLFSSL_TRUSTED_CA_PRE_AGREED) {
+        if (certId != NULL || certIdSz != 0)
+            return BAD_FUNC_ARG;
+    }
+    else if (type == WOLFSSL_TRUSTED_CA_X509_NAME) {
+        if (certId == NULL || certIdSz == 0)
+            return BAD_FUNC_ARG;
+    }
+    #ifndef NO_SHA
+    else if (type == WOLFSSL_TRUSTED_CA_KEY_SHA1 ||
+            type == WOLFSSL_TRUSTED_CA_CERT_SHA1) {
+        if (certId == NULL || certIdSz != WC_SHA_DIGEST_SIZE)
+            return BAD_FUNC_ARG;
+    }
+    #endif
+    else
+        return BAD_FUNC_ARG;
+
+    return TLSX_UseTrustedCA(&ssl->extensions,
+            type, certId, certIdSz, ssl->heap);
+}
+
+#endif /* HAVE_TRUSTED_CA */
+
+
+#ifdef HAVE_MAX_FRAGMENT
+#ifndef NO_WOLFSSL_CLIENT
+
+int wolfSSL_UseMaxFragment(WOLFSSL* ssl, byte mfl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+#ifdef WOLFSSL_ALLOW_MAX_FRAGMENT_ADJUST
+    /* The following is a non-standard way to reconfigure the max packet size
+        post-handshake for wolfSSL_write/woflSSL_read */
+    if (ssl->options.handShakeState == HANDSHAKE_DONE) {
+        switch (mfl) {
+            case WOLFSSL_MFL_2_8 : ssl->max_fragment =  256; break;
+            case WOLFSSL_MFL_2_9 : ssl->max_fragment =  512; break;
+            case WOLFSSL_MFL_2_10: ssl->max_fragment = 1024; break;
+            case WOLFSSL_MFL_2_11: ssl->max_fragment = 2048; break;
+            case WOLFSSL_MFL_2_12: ssl->max_fragment = 4096; break;
+            case WOLFSSL_MFL_2_13: ssl->max_fragment = 8192; break;
+            default: ssl->max_fragment = MAX_RECORD_SIZE; break;
+        }
+        return WOLFSSL_SUCCESS;
+    }
+#endif /* WOLFSSL_MAX_FRAGMENT_ADJUST */
+
+    /* This call sets the max fragment TLS extension, which gets sent to server.
+        The server_hello response is what sets the `ssl->max_fragment` in
+        TLSX_MFL_Parse */
+    return TLSX_UseMaxFragment(&ssl->extensions, mfl, ssl->heap);
+}
+
+
+int wolfSSL_CTX_UseMaxFragment(WOLFSSL_CTX* ctx, byte mfl)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    return TLSX_UseMaxFragment(&ctx->extensions, mfl, ctx->heap);
+}
+
+#endif /* NO_WOLFSSL_CLIENT */
+#endif /* HAVE_MAX_FRAGMENT */
+
+#ifdef HAVE_TRUNCATED_HMAC
+#ifndef NO_WOLFSSL_CLIENT
+
+int wolfSSL_UseTruncatedHMAC(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    return TLSX_UseTruncatedHMAC(&ssl->extensions, ssl->heap);
+}
+
+
+int wolfSSL_CTX_UseTruncatedHMAC(WOLFSSL_CTX* ctx)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    return TLSX_UseTruncatedHMAC(&ctx->extensions, ctx->heap);
+}
+
+#endif /* NO_WOLFSSL_CLIENT */
+#endif /* HAVE_TRUNCATED_HMAC */
+
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+
+int wolfSSL_UseOCSPStapling(WOLFSSL* ssl, byte status_type, byte options)
+{
+    if (ssl == NULL || ssl->options.side != WOLFSSL_CLIENT_END)
+        return BAD_FUNC_ARG;
+
+    return TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type,
+                                          options, NULL, ssl->heap, ssl->devId);
+}
+
+
+int wolfSSL_CTX_UseOCSPStapling(WOLFSSL_CTX* ctx, byte status_type,
+                                                                   byte options)
+{
+    if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END)
+        return BAD_FUNC_ARG;
+
+    return TLSX_UseCertificateStatusRequest(&ctx->extensions, status_type,
+                                          options, NULL, ctx->heap, ctx->devId);
+}
+
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
+
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+
+int wolfSSL_UseOCSPStaplingV2(WOLFSSL* ssl, byte status_type, byte options)
+{
+    if (ssl == NULL || ssl->options.side != WOLFSSL_CLIENT_END)
+        return BAD_FUNC_ARG;
+
+    return TLSX_UseCertificateStatusRequestV2(&ssl->extensions, status_type,
+                                                options, ssl->heap, ssl->devId);
+}
+
+
+int wolfSSL_CTX_UseOCSPStaplingV2(WOLFSSL_CTX* ctx, byte status_type,
+                                                                   byte options)
+{
+    if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END)
+        return BAD_FUNC_ARG;
+
+    return TLSX_UseCertificateStatusRequestV2(&ctx->extensions, status_type,
+                                                options, ctx->heap, ctx->devId);
+}
+
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+
+/* Elliptic Curves */
+#if defined(HAVE_SUPPORTED_CURVES) && !defined(NO_WOLFSSL_CLIENT)
+
+int wolfSSL_UseSupportedCurve(WOLFSSL* ssl, word16 name)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    switch (name) {
+        case WOLFSSL_ECC_SECP160K1:
+        case WOLFSSL_ECC_SECP160R1:
+        case WOLFSSL_ECC_SECP160R2:
+        case WOLFSSL_ECC_SECP192K1:
+        case WOLFSSL_ECC_SECP192R1:
+        case WOLFSSL_ECC_SECP224K1:
+        case WOLFSSL_ECC_SECP224R1:
+        case WOLFSSL_ECC_SECP256K1:
+        case WOLFSSL_ECC_SECP256R1:
+        case WOLFSSL_ECC_SECP384R1:
+        case WOLFSSL_ECC_SECP521R1:
+        case WOLFSSL_ECC_BRAINPOOLP256R1:
+        case WOLFSSL_ECC_BRAINPOOLP384R1:
+        case WOLFSSL_ECC_BRAINPOOLP512R1:
+        case WOLFSSL_ECC_X25519:
+        case WOLFSSL_ECC_X448:
+
+        case WOLFSSL_FFDHE_2048:
+        case WOLFSSL_FFDHE_3072:
+        case WOLFSSL_FFDHE_4096:
+        case WOLFSSL_FFDHE_6144:
+        case WOLFSSL_FFDHE_8192:
+            break;
+
+        default:
+            return BAD_FUNC_ARG;
+    }
+
+    ssl->options.userCurves = 1;
+
+    return TLSX_UseSupportedCurve(&ssl->extensions, name, ssl->heap);
+}
+
+
+int wolfSSL_CTX_UseSupportedCurve(WOLFSSL_CTX* ctx, word16 name)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    switch (name) {
+        case WOLFSSL_ECC_SECP160K1:
+        case WOLFSSL_ECC_SECP160R1:
+        case WOLFSSL_ECC_SECP160R2:
+        case WOLFSSL_ECC_SECP192K1:
+        case WOLFSSL_ECC_SECP192R1:
+        case WOLFSSL_ECC_SECP224K1:
+        case WOLFSSL_ECC_SECP224R1:
+        case WOLFSSL_ECC_SECP256K1:
+        case WOLFSSL_ECC_SECP256R1:
+        case WOLFSSL_ECC_SECP384R1:
+        case WOLFSSL_ECC_SECP521R1:
+        case WOLFSSL_ECC_BRAINPOOLP256R1:
+        case WOLFSSL_ECC_BRAINPOOLP384R1:
+        case WOLFSSL_ECC_BRAINPOOLP512R1:
+        case WOLFSSL_ECC_X25519:
+        case WOLFSSL_ECC_X448:
+        case WOLFSSL_FFDHE_2048:
+        case WOLFSSL_FFDHE_3072:
+        case WOLFSSL_FFDHE_4096:
+        case WOLFSSL_FFDHE_6144:
+        case WOLFSSL_FFDHE_8192:
+            break;
+
+        default:
+            return BAD_FUNC_ARG;
+    }
+
+    ctx->userCurves = 1;
+
+    return TLSX_UseSupportedCurve(&ctx->extensions, name, ctx->heap);
+}
+
+#endif /* HAVE_SUPPORTED_CURVES && !NO_WOLFSSL_CLIENT */
+
+/* QSH quantum safe handshake */
+#ifdef HAVE_QSH
+/* returns 1 if QSH has been used 0 otherwise */
+int wolfSSL_isQSH(WOLFSSL* ssl)
+{
+    /* if no ssl struct than QSH was not used */
+    if (ssl == NULL)
+        return 0;
+
+    return ssl->isQSH;
+}
+
+
+int wolfSSL_UseSupportedQSH(WOLFSSL* ssl, word16 name)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    switch (name) {
+    #ifdef HAVE_NTRU
+        case WOLFSSL_NTRU_EESS439:
+        case WOLFSSL_NTRU_EESS593:
+        case WOLFSSL_NTRU_EESS743:
+            break;
+    #endif
+        default:
+            return BAD_FUNC_ARG;
+    }
+
+    ssl->user_set_QSHSchemes = 1;
+
+    return TLSX_UseQSHScheme(&ssl->extensions, name, NULL, 0, ssl->heap);
+}
+
+#ifndef NO_WOLFSSL_CLIENT
+    /* user control over sending client public key in hello
+       when flag = 1 will send keys if flag is 0 or function is not called
+       then will not send keys in the hello extension
+       return 0 on success
+     */
+    int wolfSSL_UseClientQSHKeys(WOLFSSL* ssl, unsigned char flag)
+    {
+        if (ssl == NULL)
+            return BAD_FUNC_ARG;
+
+        ssl->sendQSHKeys = flag;
+
+        return 0;
+    }
+#endif /* NO_WOLFSSL_CLIENT */
+#endif /* HAVE_QSH */
+
+/* Application-Layer Protocol Negotiation */
+#ifdef HAVE_ALPN
+
+WOLFSSL_ABI
+int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list,
+                    word32 protocol_name_listSz, byte options)
+{
+    char    *list, *ptr, *token[WOLFSSL_MAX_ALPN_NUMBER]={NULL};
+    word16  len;
+    int     idx = 0;
+    int     ret = WOLFSSL_FAILURE;
+
+    WOLFSSL_ENTER("wolfSSL_UseALPN");
+
+    if (ssl == NULL || protocol_name_list == NULL)
+        return BAD_FUNC_ARG;
+
+    if (protocol_name_listSz > (WOLFSSL_MAX_ALPN_NUMBER *
+                                WOLFSSL_MAX_ALPN_PROTO_NAME_LEN +
+                                WOLFSSL_MAX_ALPN_NUMBER)) {
+        WOLFSSL_MSG("Invalid arguments, protocol name list too long");
+        return BAD_FUNC_ARG;
+    }
+
+    if (!(options & WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) &&
+        !(options & WOLFSSL_ALPN_FAILED_ON_MISMATCH)) {
+            WOLFSSL_MSG("Invalid arguments, options not supported");
+            return BAD_FUNC_ARG;
+        }
+
+
+    list = (char *)XMALLOC(protocol_name_listSz+1, ssl->heap,
+                           DYNAMIC_TYPE_ALPN);
+    if (list == NULL) {
+        WOLFSSL_MSG("Memory failure");
+        return MEMORY_ERROR;
+    }
+
+    XSTRNCPY(list, protocol_name_list, protocol_name_listSz);
+    list[protocol_name_listSz] = '\0';
+
+    /* read all protocol name from the list */
+    token[idx] = XSTRTOK(list, ",", &ptr);
+    while (idx < WOLFSSL_MAX_ALPN_NUMBER && token[idx] != NULL)
+        token[++idx] = XSTRTOK(NULL, ",", &ptr);
+
+    /* add protocol name list in the TLS extension in reverse order */
+    while ((idx--) > 0) {
+        len = (word16)XSTRLEN(token[idx]);
+
+        ret = TLSX_UseALPN(&ssl->extensions, token[idx], len, options,
+                                                                     ssl->heap);
+        if (ret != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("TLSX_UseALPN failure");
+            break;
+        }
+    }
+
+    XFREE(list, ssl->heap, DYNAMIC_TYPE_ALPN);
+
+    return ret;
+}
+
+int wolfSSL_ALPN_GetProtocol(WOLFSSL* ssl, char **protocol_name, word16 *size)
+{
+    return TLSX_ALPN_GetRequest(ssl ? ssl->extensions : NULL,
+                               (void **)protocol_name, size);
+}
+
+int wolfSSL_ALPN_GetPeerProtocol(WOLFSSL* ssl, char **list, word16 *listSz)
+{
+    if (list == NULL || listSz == NULL)
+        return BAD_FUNC_ARG;
+
+    if (ssl->alpn_client_list == NULL)
+        return BUFFER_ERROR;
+
+    *listSz = (word16)XSTRLEN(ssl->alpn_client_list);
+    if (*listSz == 0)
+        return BUFFER_ERROR;
+
+    *list = (char *)XMALLOC((*listSz)+1, ssl->heap, DYNAMIC_TYPE_TLSX);
+    if (*list == NULL)
+        return MEMORY_ERROR;
+
+    XSTRNCPY(*list, ssl->alpn_client_list, (*listSz)+1);
+    (*list)[*listSz] = 0;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* used to free memory allocated by wolfSSL_ALPN_GetPeerProtocol */
+int wolfSSL_ALPN_FreePeerProtocol(WOLFSSL* ssl, char **list)
+{
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    XFREE(*list, ssl->heap, DYNAMIC_TYPE_TLSX);
+    *list = NULL;
+
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* HAVE_ALPN */
+
+/* Secure Renegotiation */
+#ifdef HAVE_SECURE_RENEGOTIATION
+
+/* user is forcing ability to use secure renegotiation, we discourage it */
+int wolfSSL_UseSecureRenegotiation(WOLFSSL* ssl)
+{
+    int ret = BAD_FUNC_ARG;
+
+    if (ssl)
+        ret = TLSX_UseSecureRenegotiation(&ssl->extensions, ssl->heap);
+
+    if (ret == WOLFSSL_SUCCESS) {
+        TLSX* extension = TLSX_Find(ssl->extensions, TLSX_RENEGOTIATION_INFO);
+
+        if (extension)
+            ssl->secure_renegotiation = (SecureRenegotiation*)extension->data;
+    }
+
+    return ret;
+}
+
+int wolfSSL_CTX_UseSecureRenegotiation(WOLFSSL_CTX* ctx)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    ctx->useSecureReneg = 1;
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* do a secure renegotiation handshake, user forced, we discourage */
+static int _Rehandshake(WOLFSSL* ssl)
+{
+    int ret;
+
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    if (ssl->secure_renegotiation == NULL) {
+        WOLFSSL_MSG("Secure Renegotiation not forced on by user");
+        return SECURE_RENEGOTIATION_E;
+    }
+
+    if (ssl->secure_renegotiation->enabled == 0) {
+        WOLFSSL_MSG("Secure Renegotiation not enabled at extension level");
+        return SECURE_RENEGOTIATION_E;
+    }
+
+    /* If the client started the renegotiation, the server will already
+     * have processed the client's hello. */
+    if (ssl->options.side != WOLFSSL_SERVER_END ||
+        ssl->options.acceptState != ACCEPT_FIRST_REPLY_DONE) {
+
+        if (ssl->options.handShakeState != HANDSHAKE_DONE) {
+            WOLFSSL_MSG("Can't renegotiate until previous handshake complete");
+            return SECURE_RENEGOTIATION_E;
+        }
+
+#ifndef NO_FORCE_SCR_SAME_SUITE
+        /* force same suite */
+        if (ssl->suites) {
+            ssl->suites->suiteSz = SUITE_LEN;
+            ssl->suites->suites[0] = ssl->options.cipherSuite0;
+            ssl->suites->suites[1] = ssl->options.cipherSuite;
+        }
+#endif
+
+        /* reset handshake states */
+        ssl->options.sendVerify = 0;
+        ssl->options.serverState = NULL_STATE;
+        ssl->options.clientState = NULL_STATE;
+        ssl->options.connectState  = CONNECT_BEGIN;
+        ssl->options.acceptState   = ACCEPT_BEGIN_RENEG;
+        ssl->options.handShakeState = NULL_STATE;
+        ssl->options.processReply  = 0;  /* TODO, move states in internal.h */
+
+        XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived));
+
+        ssl->secure_renegotiation->cache_status = SCR_CACHE_NEEDED;
+
+#if !defined(NO_WOLFSSL_SERVER) && defined(HAVE_SERVER_RENEGOTIATION_INFO)
+        if (ssl->options.side == WOLFSSL_SERVER_END) {
+            ret = SendHelloRequest(ssl);
+            if (ret != 0) {
+                ssl->error = ret;
+                return WOLFSSL_FATAL_ERROR;
+            }
+        }
+#endif /* NO_WOLFSSL_SERVER && HAVE_SERVER_RENEGOTIATION_INFO */
+
+        ret = InitHandshakeHashes(ssl);
+        if (ret != 0) {
+            ssl->error = ret;
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+    ret = wolfSSL_negotiate(ssl);
+    ssl->secure_rene_count++;
+    return ret;
+}
+
+
+/* do a secure renegotiation handshake, user forced, we discourage */
+int wolfSSL_Rehandshake(WOLFSSL* ssl)
+{
+    int ret = WOLFSSL_SUCCESS;
+    WOLFSSL_ENTER("wolfSSL_Rehandshake");
+
+    if (ssl->options.side == WOLFSSL_SERVER_END) {
+        /* Reset option to send certificate verify. */
+        ssl->options.sendVerify = 0;
+    }
+    else {
+        /* Reset resuming flag to do full secure handshake. */
+        ssl->options.resuming = 0;
+        #ifdef HAVE_SESSION_TICKET
+            /* Clearing the ticket. */
+            ret = wolfSSL_UseSessionTicket(ssl);
+        #endif
+    }
+
+    if (ret == WOLFSSL_SUCCESS)
+        ret = _Rehandshake(ssl);
+
+    return ret;
+}
+
+
+#ifndef NO_WOLFSSL_CLIENT
+
+/* do a secure resumption handshake, user forced, we discourage */
+int wolfSSL_SecureResume(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_SecureResume");
+
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    if (ssl->options.side == WOLFSSL_SERVER_END) {
+        ssl->error = SIDE_ERROR;
+        return SSL_FATAL_ERROR;
+    }
+
+    return _Rehandshake(ssl);
+}
+
+#endif /* NO_WOLFSSL_CLIENT */
+
+long wolfSSL_SSL_get_secure_renegotiation_support(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_SSL_get_secure_renegotiation_support");
+
+    if (!ssl || !ssl->secure_renegotiation)
+        return WOLFSSL_FAILURE;
+    return ssl->secure_renegotiation->enabled;
+}
+
+#endif /* HAVE_SECURE_RENEGOTIATION */
+
+/* Session Ticket */
+#if !defined(NO_WOLFSSL_SERVER) && defined(HAVE_SESSION_TICKET)
+/* WOLFSSL_SUCCESS on ok */
+int wolfSSL_CTX_set_TicketEncCb(WOLFSSL_CTX* ctx, SessionTicketEncCb cb)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    ctx->ticketEncCb = cb;
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* set hint interval, WOLFSSL_SUCCESS on ok */
+int wolfSSL_CTX_set_TicketHint(WOLFSSL_CTX* ctx, int hint)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    ctx->ticketHint = hint;
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* set user context, WOLFSSL_SUCCESS on ok */
+int wolfSSL_CTX_set_TicketEncCtx(WOLFSSL_CTX* ctx, void* userCtx)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    ctx->ticketEncCtx = userCtx;
+
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_SESSION_TICKET) */
+
+/* Session Ticket */
+#if !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_SESSION_TICKET)
+int wolfSSL_UseSessionTicket(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    return TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap);
+}
+
+int wolfSSL_CTX_UseSessionTicket(WOLFSSL_CTX* ctx)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    return TLSX_UseSessionTicket(&ctx->extensions, NULL, ctx->heap);
+}
+
+WOLFSSL_API int wolfSSL_get_SessionTicket(WOLFSSL* ssl,
+                                          byte* buf, word32* bufSz)
+{
+    if (ssl == NULL || buf == NULL || bufSz == NULL || *bufSz == 0)
+        return BAD_FUNC_ARG;
+
+    if (ssl->session.ticketLen <= *bufSz) {
+        XMEMCPY(buf, ssl->session.ticket, ssl->session.ticketLen);
+        *bufSz = ssl->session.ticketLen;
+    }
+    else
+        *bufSz = 0;
+
+    return WOLFSSL_SUCCESS;
+}
+
+WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL* ssl, const byte* buf,
+                                          word32 bufSz)
+{
+    if (ssl == NULL || (buf == NULL && bufSz > 0))
+        return BAD_FUNC_ARG;
+
+    if (bufSz > 0) {
+        /* Ticket will fit into static ticket */
+        if(bufSz <= SESSION_TICKET_LEN) {
+            if (ssl->session.isDynamic) {
+                XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+                ssl->session.isDynamic = 0;
+                ssl->session.ticket = ssl->session.staticTicket;
+            }
+        } else { /* Ticket requires dynamic ticket storage */
+            if (ssl->session.ticketLen < bufSz) { /* is dyn buffer big enough */
+                if(ssl->session.isDynamic)
+                    XFREE(ssl->session.ticket, ssl->heap,
+                            DYNAMIC_TYPE_SESSION_TICK);
+                ssl->session.ticket = (byte*)XMALLOC(bufSz, ssl->heap,
+                        DYNAMIC_TYPE_SESSION_TICK);
+                if(!ssl->session.ticket) {
+                    ssl->session.ticket = ssl->session.staticTicket;
+                    ssl->session.isDynamic = 0;
+                    return MEMORY_ERROR;
+                }
+                ssl->session.isDynamic = 1;
+            }
+        }
+        XMEMCPY(ssl->session.ticket, buf, bufSz);
+    }
+    ssl->session.ticketLen = (word16)bufSz;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+WOLFSSL_API int wolfSSL_set_SessionTicket_cb(WOLFSSL* ssl,
+                                            CallbackSessionTicket cb, void* ctx)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    ssl->session_ticket_cb = cb;
+    ssl->session_ticket_ctx = ctx;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif
+
+
+#ifdef HAVE_EXTENDED_MASTER
+#ifndef NO_WOLFSSL_CLIENT
+
+int wolfSSL_CTX_DisableExtendedMasterSecret(WOLFSSL_CTX* ctx)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    ctx->haveEMS = 0;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_DisableExtendedMasterSecret(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    ssl->options.haveEMS = 0;
+
+    return WOLFSSL_SUCCESS;
+}
+
+#endif
+#endif
+
+
+#ifndef WOLFSSL_LEANPSK
+
+int wolfSSL_send(WOLFSSL* ssl, const void* data, int sz, int flags)
+{
+    int ret;
+    int oldFlags;
+
+    WOLFSSL_ENTER("wolfSSL_send()");
+
+    if (ssl == NULL || data == NULL || sz < 0)
+        return BAD_FUNC_ARG;
+
+    oldFlags = ssl->wflags;
+
+    ssl->wflags = flags;
+    ret = wolfSSL_write(ssl, data, sz);
+    ssl->wflags = oldFlags;
+
+    WOLFSSL_LEAVE("wolfSSL_send()", ret);
+
+    return ret;
+}
+
+
+int wolfSSL_recv(WOLFSSL* ssl, void* data, int sz, int flags)
+{
+    int ret;
+    int oldFlags;
+
+    WOLFSSL_ENTER("wolfSSL_recv()");
+
+    if (ssl == NULL || data == NULL || sz < 0)
+        return BAD_FUNC_ARG;
+
+    oldFlags = ssl->rflags;
+
+    ssl->rflags = flags;
+    ret = wolfSSL_read(ssl, data, sz);
+    ssl->rflags = oldFlags;
+
+    WOLFSSL_LEAVE("wolfSSL_recv()", ret);
+
+    return ret;
+}
+#endif
+
+
+/* WOLFSSL_SUCCESS on ok */
+WOLFSSL_ABI
+int wolfSSL_shutdown(WOLFSSL* ssl)
+{
+    int  ret = WOLFSSL_FATAL_ERROR;
+    WOLFSSL_ENTER("SSL_shutdown()");
+
+    if (ssl == NULL)
+        return WOLFSSL_FATAL_ERROR;
+
+    if (ssl->options.quietShutdown) {
+        WOLFSSL_MSG("quiet shutdown, no close notify sent");
+        ret = WOLFSSL_SUCCESS;
+    }
+    else {
+        /* try to send close notify, not an error if can't */
+        if (!ssl->options.isClosed && !ssl->options.connReset &&
+                                      !ssl->options.sentNotify) {
+            ssl->error = SendAlert(ssl, alert_warning, close_notify);
+            if (ssl->error < 0) {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+            ssl->options.sentNotify = 1;  /* don't send close_notify twice */
+            if (ssl->options.closeNotify)
+                ret = WOLFSSL_SUCCESS;
+            else {
+                ret = WOLFSSL_SHUTDOWN_NOT_DONE;
+                WOLFSSL_LEAVE("SSL_shutdown()", ret);
+                return ret;
+            }
+        }
+
+#ifdef WOLFSSL_SHUTDOWNONCE
+        if (ssl->options.isClosed || ssl->options.connReset) {
+            /* Shutdown has already occurred.
+             * Caller is free to ignore this error. */
+            return SSL_SHUTDOWN_ALREADY_DONE_E;
+        }
+#endif
+
+        /* call wolfSSL_shutdown again for bidirectional shutdown */
+        if (ssl->options.sentNotify && !ssl->options.closeNotify) {
+            ret = ProcessReply(ssl);
+            if (ret == ZERO_RETURN) {
+                /* simulate OpenSSL behavior */
+                ssl->error = WOLFSSL_ERROR_SYSCALL;
+                ret = WOLFSSL_SUCCESS;
+            } else if (ssl->error == WOLFSSL_ERROR_NONE) {
+                ret = WOLFSSL_SHUTDOWN_NOT_DONE;
+            } else {
+                WOLFSSL_ERROR(ssl->error);
+                ret = WOLFSSL_FATAL_ERROR;
+            }
+        }
+    }
+
+#ifdef OPENSSL_EXTRA
+    /* reset WOLFSSL structure state for possible re-use */
+    if (ret == WOLFSSL_SUCCESS) {
+        if (wolfSSL_clear(ssl) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("could not clear WOLFSSL");
+            ret = WOLFSSL_FATAL_ERROR;
+        }
+    }
+#endif
+
+    WOLFSSL_LEAVE("SSL_shutdown()", ret);
+
+    return ret;
+}
+
+
+/* get current error state value */
+int wolfSSL_state(WOLFSSL* ssl)
+{
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    return ssl->error;
+}
+
+
+WOLFSSL_ABI
+int wolfSSL_get_error(WOLFSSL* ssl, int ret)
+{
+    WOLFSSL_ENTER("SSL_get_error");
+
+    if (ret > 0)
+        return WOLFSSL_ERROR_NONE;
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    WOLFSSL_LEAVE("SSL_get_error", ssl->error);
+
+    /* make sure converted types are handled in SetErrorString() too */
+    if (ssl->error == WANT_READ)
+        return WOLFSSL_ERROR_WANT_READ;         /* convert to OpenSSL type */
+    else if (ssl->error == WANT_WRITE)
+        return WOLFSSL_ERROR_WANT_WRITE;        /* convert to OpenSSL type */
+    else if (ssl->error == ZERO_RETURN)
+        return WOLFSSL_ERROR_ZERO_RETURN;       /* convert to OpenSSL type */
+    return ssl->error;
+}
+
+
+/* retrieve alert history, WOLFSSL_SUCCESS on ok */
+int wolfSSL_get_alert_history(WOLFSSL* ssl, WOLFSSL_ALERT_HISTORY *h)
+{
+    if (ssl && h) {
+        *h = ssl->alert_history;
+    }
+    return WOLFSSL_SUCCESS;
+}
+
+#ifdef OPENSSL_EXTRA
+/* returns SSL_WRITING, SSL_READING or SSL_NOTHING */
+int wolfSSL_want(WOLFSSL* ssl)
+{
+    int rw_state = SSL_NOTHING;
+    if (ssl) {
+        if (ssl->error == WANT_READ)
+            rw_state = SSL_READING;
+        else if (ssl->error == WANT_WRITE)
+            rw_state = SSL_WRITING;
+    }
+    return rw_state;
+}
+#endif
+
+/* return TRUE if current error is want read */
+int wolfSSL_want_read(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("SSL_want_read");
+    if (ssl->error == WANT_READ)
+        return 1;
+
+    return 0;
+}
+
+
+/* return TRUE if current error is want write */
+int wolfSSL_want_write(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("SSL_want_write");
+    if (ssl->error == WANT_WRITE)
+        return 1;
+
+    return 0;
+}
+
+
+char* wolfSSL_ERR_error_string(unsigned long errNumber, char* data)
+{
+    static wcchar msg = "Please supply a buffer for error string";
+
+    WOLFSSL_ENTER("ERR_error_string");
+    if (data) {
+        SetErrorString((int)errNumber, data);
+        return data;
+    }
+
+    return (char*)msg;
+}
+
+
+void wolfSSL_ERR_error_string_n(unsigned long e, char* buf, unsigned long len)
+{
+    WOLFSSL_ENTER("wolfSSL_ERR_error_string_n");
+    if (len >= WOLFSSL_MAX_ERROR_SZ)
+        wolfSSL_ERR_error_string(e, buf);
+    else {
+        char tmp[WOLFSSL_MAX_ERROR_SZ];
+
+        WOLFSSL_MSG("Error buffer too short, truncating");
+        if (len) {
+            wolfSSL_ERR_error_string(e, tmp);
+            XMEMCPY(buf, tmp, len-1);
+            buf[len-1] = '\0';
+        }
+    }
+}
+
+
+/* don't free temporary arrays at end of handshake */
+void wolfSSL_KeepArrays(WOLFSSL* ssl)
+{
+    if (ssl)
+        ssl->options.saveArrays = 1;
+}
+
+
+/* user doesn't need temporary arrays anymore, Free */
+void wolfSSL_FreeArrays(WOLFSSL* ssl)
+{
+    if (ssl && ssl->options.handShakeState == HANDSHAKE_DONE) {
+        ssl->options.saveArrays = 0;
+        FreeArrays(ssl, 1);
+    }
+}
+
+/* Set option to indicate that the resources are not to be freed after
+ * handshake.
+ *
+ * ssl  The SSL/TLS object.
+ * returns BAD_FUNC_ARG when ssl is NULL and 0 on success.
+ */
+int wolfSSL_KeepHandshakeResources(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    ssl->options.keepResources = 1;
+
+    return 0;
+}
+
+/* Free the handshake resources after handshake.
+ *
+ * ssl  The SSL/TLS object.
+ * returns BAD_FUNC_ARG when ssl is NULL and 0 on success.
+ */
+int wolfSSL_FreeHandshakeResources(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    FreeHandshakeResources(ssl);
+
+    return 0;
+}
+
+/* Use the client's order of preference when matching cipher suites.
+ *
+ * ssl  The SSL/TLS context object.
+ * returns BAD_FUNC_ARG when ssl is NULL and 0 on success.
+ */
+int wolfSSL_CTX_UseClientSuites(WOLFSSL_CTX* ctx)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    ctx->useClientOrder = 1;
+
+    return 0;
+}
+
+/* Use the client's order of preference when matching cipher suites.
+ *
+ * ssl  The SSL/TLS object.
+ * returns BAD_FUNC_ARG when ssl is NULL and 0 on success.
+ */
+int wolfSSL_UseClientSuites(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    ssl->options.useClientOrder = 1;
+
+    return 0;
+}
+
+const byte* wolfSSL_GetMacSecret(WOLFSSL* ssl, int verify)
+{
+#ifndef WOLFSSL_AEAD_ONLY
+    if (ssl == NULL)
+        return NULL;
+
+    if ( (ssl->options.side == WOLFSSL_CLIENT_END && !verify) ||
+         (ssl->options.side == WOLFSSL_SERVER_END &&  verify) )
+        return ssl->keys.client_write_MAC_secret;
+    else
+        return ssl->keys.server_write_MAC_secret;
+#else
+    (void)ssl;
+    (void)verify;
+
+    return NULL;
+#endif
+}
+
+
+#ifdef ATOMIC_USER
+
+void  wolfSSL_CTX_SetMacEncryptCb(WOLFSSL_CTX* ctx, CallbackMacEncrypt cb)
+{
+    if (ctx)
+        ctx->MacEncryptCb = cb;
+}
+
+
+void  wolfSSL_SetMacEncryptCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->MacEncryptCtx = ctx;
+}
+
+
+void* wolfSSL_GetMacEncryptCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->MacEncryptCtx;
+
+    return NULL;
+}
+
+
+void  wolfSSL_CTX_SetDecryptVerifyCb(WOLFSSL_CTX* ctx, CallbackDecryptVerify cb)
+{
+    if (ctx)
+        ctx->DecryptVerifyCb = cb;
+}
+
+
+void  wolfSSL_SetDecryptVerifyCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->DecryptVerifyCtx = ctx;
+}
+
+
+void* wolfSSL_GetDecryptVerifyCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->DecryptVerifyCtx;
+
+    return NULL;
+}
+
+#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+/**
+ * Set the callback, against the context, that encrypts then MACs.
+ *
+ * ctx  SSL/TLS context.
+ * cb   Callback function to use with Encrypt-Then-MAC.
+ */
+void  wolfSSL_CTX_SetEncryptMacCb(WOLFSSL_CTX* ctx, CallbackEncryptMac cb)
+{
+    if (ctx)
+        ctx->EncryptMacCb = cb;
+}
+
+/**
+ * Set the context to use with callback that encrypts then MACs.
+ *
+ * ssl  SSL/TLS object.
+ * ctx  Callback function's context.
+ */
+void  wolfSSL_SetEncryptMacCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->EncryptMacCtx = ctx;
+}
+
+/**
+ * Get the context being used with callback that encrypts then MACs.
+ *
+ * ssl  SSL/TLS object.
+ * returns callback function's context or NULL if SSL/TLS object is NULL.
+ */
+void* wolfSSL_GetEncryptMacCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->EncryptMacCtx;
+
+    return NULL;
+}
+
+
+/**
+ * Set the callback, against the context, that MAC verifies then decrypts.
+ *
+ * ctx  SSL/TLS context.
+ * cb   Callback function to use with Encrypt-Then-MAC.
+ */
+void  wolfSSL_CTX_SetVerifyDecryptCb(WOLFSSL_CTX* ctx, CallbackVerifyDecrypt cb)
+{
+    if (ctx)
+        ctx->VerifyDecryptCb = cb;
+}
+
+/**
+ * Set the context to use with callback that MAC verifies then decrypts.
+ *
+ * ssl  SSL/TLS object.
+ * ctx  Callback function's context.
+ */
+void  wolfSSL_SetVerifyDecryptCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->VerifyDecryptCtx = ctx;
+}
+
+/**
+ * Get the context being used with callback that MAC verifies then decrypts.
+ *
+ * ssl  SSL/TLS object.
+ * returns callback function's context or NULL if SSL/TLS object is NULL.
+ */
+void* wolfSSL_GetVerifyDecryptCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->VerifyDecryptCtx;
+
+    return NULL;
+}
+#endif /* HAVE_ENCRYPT_THEN_MAC !WOLFSSL_AEAD_ONLY */
+
+
+
+const byte* wolfSSL_GetClientWriteKey(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->keys.client_write_key;
+
+    return NULL;
+}
+
+
+const byte* wolfSSL_GetClientWriteIV(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->keys.client_write_IV;
+
+    return NULL;
+}
+
+
+const byte* wolfSSL_GetServerWriteKey(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->keys.server_write_key;
+
+    return NULL;
+}
+
+
+const byte* wolfSSL_GetServerWriteIV(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->keys.server_write_IV;
+
+    return NULL;
+}
+
+int wolfSSL_GetKeySize(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->specs.key_size;
+
+    return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_GetIVSize(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->specs.iv_size;
+
+    return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_GetBulkCipher(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->specs.bulk_cipher_algorithm;
+
+    return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_GetCipherType(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+#ifndef WOLFSSL_AEAD_ONLY
+    if (ssl->specs.cipher_type == block)
+        return WOLFSSL_BLOCK_TYPE;
+    if (ssl->specs.cipher_type == stream)
+        return WOLFSSL_STREAM_TYPE;
+#endif
+    if (ssl->specs.cipher_type == aead)
+        return WOLFSSL_AEAD_TYPE;
+
+    return -1;
+}
+
+
+int wolfSSL_GetCipherBlockSize(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    return ssl->specs.block_size;
+}
+
+
+int wolfSSL_GetAeadMacSize(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    return ssl->specs.aead_mac_size;
+}
+
+
+int wolfSSL_IsTLSv1_1(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    if (ssl->options.tls1_1)
+        return 1;
+
+    return 0;
+}
+
+
+int wolfSSL_GetSide(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->options.side;
+
+    return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_GetHmacSize(WOLFSSL* ssl)
+{
+    /* AEAD ciphers don't have HMAC keys */
+    if (ssl)
+        return (ssl->specs.cipher_type != aead) ? ssl->specs.hash_size : 0;
+
+    return BAD_FUNC_ARG;
+}
+
+#endif /* ATOMIC_USER */
+
+#ifndef NO_CERTS
+
+WOLFSSL_CERT_MANAGER* wolfSSL_CTX_GetCertManager(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_CERT_MANAGER* cm = NULL;
+    if (ctx)
+        cm = ctx->cm;
+    return cm;
+}
+
+WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew_ex(void* heap)
+{
+    WOLFSSL_CERT_MANAGER* cm;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerNew");
+
+    cm = (WOLFSSL_CERT_MANAGER*) XMALLOC(sizeof(WOLFSSL_CERT_MANAGER), heap,
+                                         DYNAMIC_TYPE_CERT_MANAGER);
+    if (cm) {
+        XMEMSET(cm, 0, sizeof(WOLFSSL_CERT_MANAGER));
+
+        if (wc_InitMutex(&cm->caLock) != 0) {
+            WOLFSSL_MSG("Bad mutex init");
+            wolfSSL_CertManagerFree(cm);
+            return NULL;
+        }
+
+        #ifdef WOLFSSL_TRUST_PEER_CERT
+        if (wc_InitMutex(&cm->tpLock) != 0) {
+            WOLFSSL_MSG("Bad mutex init");
+            wolfSSL_CertManagerFree(cm);
+            return NULL;
+        }
+        #endif
+
+        /* set default minimum key size allowed */
+        #ifndef NO_RSA
+            cm->minRsaKeySz = MIN_RSAKEY_SZ;
+        #endif
+        #ifdef HAVE_ECC
+            cm->minEccKeySz = MIN_ECCKEY_SZ;
+        #endif
+            cm->heap = heap;
+    }
+
+    return cm;
+}
+
+
+WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew(void)
+{
+    return wolfSSL_CertManagerNew_ex(NULL);
+}
+
+
+void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER* cm)
+{
+    WOLFSSL_ENTER("wolfSSL_CertManagerFree");
+
+    if (cm) {
+        #ifdef HAVE_CRL
+            if (cm->crl)
+                FreeCRL(cm->crl, 1);
+        #endif
+        #ifdef HAVE_OCSP
+            if (cm->ocsp)
+                FreeOCSP(cm->ocsp, 1);
+            XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL);
+        #if !defined(NO_WOLFSSL_SERVER) && \
+            (defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
+             defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
+            if (cm->ocsp_stapling)
+                FreeOCSP(cm->ocsp_stapling, 1);
+        #endif
+        #endif
+        FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
+        wc_FreeMutex(&cm->caLock);
+
+        #ifdef WOLFSSL_TRUST_PEER_CERT
+        FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, cm->heap);
+        wc_FreeMutex(&cm->tpLock);
+        #endif
+
+        XFREE(cm, cm->heap, DYNAMIC_TYPE_CERT_MANAGER);
+    }
+
+}
+
+#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM)
+#if defined(WOLFSSL_SIGNER_DER_CERT)
+/******************************************************************************
+* wolfSSL_CertManagerGetCerts - retrieve stack of X509 certificates in a
+* certificate manager (CM).
+*
+* RETURNS:
+* returns stack of X509 certs on success, otherwise returns a NULL.
+*/
+WOLFSSL_STACK* wolfSSL_CertManagerGetCerts(WOLFSSL_CERT_MANAGER* cm)
+{
+    WOLFSSL_STACK* sk = NULL;
+    Signer* signers = NULL;
+    word32  row = 0;
+    DecodedCert* dCert = NULL;
+    WOLFSSL_X509* x509 = NULL;
+    int found = 0;
+
+    if (cm == NULL)
+        return NULL;
+
+    sk = wolfSSL_sk_X509_new();
+
+    if (sk == NULL) {
+        return NULL;
+    }
+
+    if (wc_LockMutex(&cm->caLock) != 0) {
+        goto error_init;
+    }
+
+    for (row = 0; row < CA_TABLE_SIZE; row++) {
+        signers = cm->caTable[row];
+        while (signers && signers->derCert && signers->derCert->buffer) {
+
+            dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap,
+                                          DYNAMIC_TYPE_DCERT);
+            if (dCert == NULL) {
+                goto error;
+            }
+
+            XMEMSET(dCert, 0, sizeof(DecodedCert));
+
+            InitDecodedCert(dCert, signers->derCert->buffer,
+                            signers->derCert->length, cm->heap);
+
+            /* Parse Certificate */
+            if (ParseCert(dCert, CERT_TYPE, NO_VERIFY, cm)) {
+                goto error;
+            }
+
+            x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), cm->heap,
+                    DYNAMIC_TYPE_X509);
+
+            if (x509 == NULL) {
+                goto error;
+            }
+
+            InitX509(x509, 1, NULL);
+
+            if (CopyDecodedToX509(x509, dCert) == 0) {
+
+                if (wolfSSL_sk_X509_push(sk, x509) != SSL_SUCCESS) {
+                    WOLFSSL_MSG("Unable to load x509 into stack");
+                    FreeX509(x509);
+                    XFREE(x509, cm->heap, DYNAMIC_TYPE_X509);
+                    goto error;
+                }
+            }
+            else {
+                goto error;
+            }
+
+            found = 1;
+
+            signers = signers->next;
+
+            FreeDecodedCert(dCert);
+            XFREE(dCert, cm->heap, DYNAMIC_TYPE_DCERT);
+            dCert = NULL;
+        }
+    }
+    wc_UnLockMutex(&cm->caLock);
+
+    if (!found) {
+       goto error_init;
+    }
+
+    return sk;
+
+error:
+    wc_UnLockMutex(&cm->caLock);
+
+error_init:
+
+    if (dCert) {
+        FreeDecodedCert(dCert);
+        XFREE(dCert, cm->heap, DYNAMIC_TYPE_DCERT);
+    }
+
+    if (sk)
+        wolfSSL_sk_X509_free(sk);
+
+    return NULL;
+}
+#endif /* WOLFSSL_SIGNER_DER_CERT */
+
+/******************************************************************************
+* wolfSSL_X509_STORE_GetCerts - retrieve stack of X509 in a certificate store ctx
+*
+* This API can be used in SSL verify callback function to view cert chain
+* See examples/client/client.c and myVerify() function in test.h
+*
+* RETURNS:
+* returns stack of X509 certs on success, otherwise returns a NULL.
+*/
+WOLFSSL_STACK* wolfSSL_X509_STORE_GetCerts(WOLFSSL_X509_STORE_CTX* s)
+{
+    int  certIdx = 0;
+    WOLFSSL_BUFFER_INFO* cert = NULL;
+    DecodedCert* dCert = NULL;
+    WOLFSSL_X509* x509 = NULL;
+    WOLFSSL_STACK* sk = NULL;
+    int found = 0;
+
+    if (s == NULL) {
+        return NULL;
+    }
+
+    sk = wolfSSL_sk_X509_new();
+
+    if (sk == NULL) {
+        return NULL;
+    }
+
+    for (certIdx = s->totalCerts - 1; certIdx >= 0; certIdx--) {
+        /* get certificate buffer */
+        cert = &s->certs[certIdx];
+
+        dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
+
+        if (dCert == NULL) {
+            goto error;
+        }
+        XMEMSET(dCert, 0, sizeof(DecodedCert));
+
+        InitDecodedCert(dCert, cert->buffer, cert->length, NULL);
+
+        /* Parse Certificate */
+        if (ParseCert(dCert, CERT_TYPE, NO_VERIFY, NULL)){
+            goto error;
+        }
+        x509 = wolfSSL_X509_new();
+
+        if (x509 == NULL) {
+            goto error;
+        }
+        InitX509(x509, 1, NULL);
+
+        if (CopyDecodedToX509(x509, dCert) == 0) {
+
+            if (wolfSSL_sk_X509_push(sk, x509) != SSL_SUCCESS) {
+                WOLFSSL_MSG("Unable to load x509 into stack");
+                wolfSSL_X509_free(x509);
+                goto error;
+            }
+        }
+        else {
+            goto error;
+        }
+        found = 1;
+
+        FreeDecodedCert(dCert);
+        XFREE(dCert, NULL, DYNAMIC_TYPE_DCERT);
+        dCert = NULL;
+    }
+
+    if (!found) {
+        wolfSSL_sk_X509_free(sk);
+        sk = NULL;
+    }
+    return sk;
+
+error:
+    if (dCert) {
+        FreeDecodedCert(dCert);
+        XFREE(dCert, NULL, DYNAMIC_TYPE_DCERT);
+    }
+
+    if (sk)
+        wolfSSL_sk_X509_free(sk);
+
+    return NULL;
+}
+#endif /* OPENSSL_EXTRA && !NO_FILESYSTEM */
+
+/* Unload the CA signer list */
+int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm)
+{
+    WOLFSSL_ENTER("wolfSSL_CertManagerUnloadCAs");
+
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    if (wc_LockMutex(&cm->caLock) != 0)
+        return BAD_MUTEX_E;
+
+    FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
+
+    wc_UnLockMutex(&cm->caLock);
+
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+#ifdef WOLFSSL_TRUST_PEER_CERT
+int wolfSSL_CertManagerUnload_trust_peers(WOLFSSL_CERT_MANAGER* cm)
+{
+    WOLFSSL_ENTER("wolfSSL_CertManagerUnload_trust_peers");
+
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    if (wc_LockMutex(&cm->tpLock) != 0)
+        return BAD_MUTEX_E;
+
+    FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, cm->heap);
+
+    wc_UnLockMutex(&cm->tpLock);
+
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* WOLFSSL_TRUST_PEER_CERT */
+
+#endif /* NO_CERTS */
+
+#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)
+
+void wolfSSL_ERR_print_errors_fp(XFILE fp, int err)
+{
+    char data[WOLFSSL_MAX_ERROR_SZ + 1];
+
+    WOLFSSL_ENTER("wolfSSL_ERR_print_errors_fp");
+    SetErrorString(err, data);
+    fprintf(fp, "%s", data);
+}
+
+#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
+void wolfSSL_ERR_dump_errors_fp(XFILE fp)
+{
+    wc_ERR_print_errors_fp(fp);
+}
+
+void wolfSSL_ERR_print_errors_cb (int (*cb)(const char *str, size_t len,
+                                            void *u), void *u)
+{
+    wc_ERR_print_errors_cb(cb, u);
+}
+#endif
+#endif
+
+WOLFSSL_ABI
+int wolfSSL_pending(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("SSL_pending");
+    return ssl->buffers.clearOutputBuffer.length;
+}
+
+
+#ifndef WOLFSSL_LEANPSK
+/* turn on handshake group messages for context */
+int wolfSSL_CTX_set_group_messages(WOLFSSL_CTX* ctx)
+{
+    if (ctx == NULL)
+       return BAD_FUNC_ARG;
+
+    ctx->groupMessages = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_CLIENT
+/* connect enough to get peer cert chain */
+int wolfSSL_connect_cert(WOLFSSL* ssl)
+{
+    int  ret;
+
+    if (ssl == NULL)
+        return WOLFSSL_FAILURE;
+
+    ssl->options.certOnly = 1;
+    ret = wolfSSL_connect(ssl);
+    ssl->options.certOnly   = 0;
+
+    return ret;
+}
+#endif
+
+
+#ifndef WOLFSSL_LEANPSK
+/* turn on handshake group messages for ssl object */
+int wolfSSL_set_group_messages(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+       return BAD_FUNC_ARG;
+
+    ssl->options.groupMessages = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* make minVersion the internal equivalent SSL version */
+static int SetMinVersionHelper(byte* minVersion, int version)
+{
+#ifdef NO_TLS
+    (void)minVersion;
+#endif
+
+    switch (version) {
+#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
+        case WOLFSSL_SSLV3:
+            *minVersion = SSLv3_MINOR;
+            break;
+#endif
+
+#ifndef NO_TLS
+    #ifndef NO_OLD_TLS
+        #ifdef WOLFSSL_ALLOW_TLSV10
+        case WOLFSSL_TLSV1:
+            *minVersion = TLSv1_MINOR;
+            break;
+        #endif
+
+        case WOLFSSL_TLSV1_1:
+            *minVersion = TLSv1_1_MINOR;
+            break;
+    #endif
+    #ifndef WOLFSSL_NO_TLS12
+        case WOLFSSL_TLSV1_2:
+            *minVersion = TLSv1_2_MINOR;
+            break;
+    #endif
+#endif
+    #ifdef WOLFSSL_TLS13
+        case WOLFSSL_TLSV1_3:
+            *minVersion = TLSv1_3_MINOR;
+            break;
+    #endif
+
+        default:
+            WOLFSSL_MSG("Bad function argument");
+            return BAD_FUNC_ARG;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* Set minimum downgrade version allowed, WOLFSSL_SUCCESS on ok */
+WOLFSSL_ABI
+int wolfSSL_CTX_SetMinVersion(WOLFSSL_CTX* ctx, int version)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_SetMinVersion");
+
+    if (ctx == NULL) {
+        WOLFSSL_MSG("Bad function argument");
+        return BAD_FUNC_ARG;
+    }
+
+    return SetMinVersionHelper(&ctx->minDowngrade, version);
+}
+
+
+/* Set minimum downgrade version allowed, WOLFSSL_SUCCESS on ok */
+int wolfSSL_SetMinVersion(WOLFSSL* ssl, int version)
+{
+    WOLFSSL_ENTER("wolfSSL_SetMinVersion");
+
+    if (ssl == NULL) {
+        WOLFSSL_MSG("Bad function argument");
+        return BAD_FUNC_ARG;
+    }
+
+    return SetMinVersionHelper(&ssl->options.minDowngrade, version);
+}
+
+
+/* Function to get version as WOLFSSL_ enum value for wolfSSL_SetVersion */
+int wolfSSL_GetVersion(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    if (ssl->version.major == SSLv3_MAJOR) {
+        switch (ssl->version.minor) {
+            case SSLv3_MINOR :
+                return WOLFSSL_SSLV3;
+            case TLSv1_MINOR :
+                return WOLFSSL_TLSV1;
+            case TLSv1_1_MINOR :
+                return WOLFSSL_TLSV1_1;
+            case TLSv1_2_MINOR :
+                return WOLFSSL_TLSV1_2;
+            case TLSv1_3_MINOR :
+                return WOLFSSL_TLSV1_3;
+            default:
+                break;
+        }
+    }
+
+    return VERSION_ERROR;
+}
+
+int wolfSSL_SetVersion(WOLFSSL* ssl, int version)
+{
+    word16 haveRSA = 1;
+    word16 havePSK = 0;
+    int    keySz   = 0;
+
+    WOLFSSL_ENTER("wolfSSL_SetVersion");
+
+    if (ssl == NULL) {
+        WOLFSSL_MSG("Bad function argument");
+        return BAD_FUNC_ARG;
+    }
+
+    switch (version) {
+#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
+        case WOLFSSL_SSLV3:
+            ssl->version = MakeSSLv3();
+            break;
+#endif
+
+#ifndef NO_TLS
+    #ifndef NO_OLD_TLS
+        #ifdef WOLFSSL_ALLOW_TLSV10
+        case WOLFSSL_TLSV1:
+            ssl->version = MakeTLSv1();
+            break;
+        #endif
+
+        case WOLFSSL_TLSV1_1:
+            ssl->version = MakeTLSv1_1();
+            break;
+    #endif
+    #ifndef WOLFSSL_NO_TLS12
+        case WOLFSSL_TLSV1_2:
+            ssl->version = MakeTLSv1_2();
+            break;
+    #endif
+#endif
+#ifdef WOLFSSL_TLS13
+        case WOLFSSL_TLSV1_3:
+            ssl->version = MakeTLSv1_3();
+            break;
+
+#endif
+
+        default:
+            WOLFSSL_MSG("Bad function argument");
+            return BAD_FUNC_ARG;
+    }
+
+    #ifdef NO_RSA
+        haveRSA = 0;
+    #endif
+    #ifndef NO_PSK
+        havePSK = ssl->options.havePSK;
+    #endif
+    #ifndef NO_CERTS
+        keySz = ssl->buffers.keySz;
+    #endif
+
+    InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
+               ssl->options.haveDH, ssl->options.haveNTRU,
+               ssl->options.haveECDSAsig, ssl->options.haveECC,
+               ssl->options.haveStaticECC, ssl->options.side);
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* !leanpsk */
+
+
+#if !defined(NO_CERTS) || !defined(NO_SESSION_CACHE)
+
+/* Make a work from the front of random hash */
+static WC_INLINE word32 MakeWordFromHash(const byte* hashID)
+{
+    return ((word32)hashID[0] << 24) | ((word32)hashID[1] << 16) |
+        (hashID[2] <<  8) | hashID[3];
+}
+
+#endif /* !NO_CERTS || !NO_SESSION_CACHE */
+
+
+#ifndef NO_CERTS
+
+/* hash is the SHA digest of name, just use first 32 bits as hash */
+static WC_INLINE word32 HashSigner(const byte* hash)
+{
+    return MakeWordFromHash(hash) % CA_TABLE_SIZE;
+}
+
+
+/* does CA already exist on signer list */
+int AlreadySigner(WOLFSSL_CERT_MANAGER* cm, byte* hash)
+{
+    Signer* signers;
+    int     ret = 0;
+    word32  row;
+
+    if (cm == NULL || hash == NULL) {
+        return ret;
+    }
+
+    row = HashSigner(hash);
+
+    if (wc_LockMutex(&cm->caLock) != 0) {
+        return ret;
+    }
+    signers = cm->caTable[row];
+    while (signers) {
+        byte* subjectHash;
+
+    #ifndef NO_SKID
+        subjectHash = signers->subjectKeyIdHash;
+    #else
+        subjectHash = signers->subjectNameHash;
+    #endif
+
+        if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
+            ret = 1; /* success */
+            break;
+        }
+        signers = signers->next;
+    }
+    wc_UnLockMutex(&cm->caLock);
+
+    return ret;
+}
+
+
+#ifdef WOLFSSL_TRUST_PEER_CERT
+/* hash is the SHA digest of name, just use first 32 bits as hash */
+static WC_INLINE word32 TrustedPeerHashSigner(const byte* hash)
+{
+    return MakeWordFromHash(hash) % TP_TABLE_SIZE;
+}
+
+/* does trusted peer already exist on signer list */
+int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, byte* hash)
+{
+    TrustedPeerCert* tp;
+    int     ret = 0;
+    word32  row = TrustedPeerHashSigner(hash);
+
+    if (wc_LockMutex(&cm->tpLock) != 0)
+        return  ret;
+    tp = cm->tpTable[row];
+    while (tp) {
+        byte* subjectHash;
+        #ifndef NO_SKID
+            subjectHash = tp->subjectKeyIdHash;
+        #else
+            subjectHash = tp->subjectNameHash;
+        #endif
+        if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
+            ret = 1;
+            break;
+        }
+        tp = tp->next;
+    }
+    wc_UnLockMutex(&cm->tpLock);
+
+    return ret;
+}
+
+
+/* return Trusted Peer if found, otherwise NULL
+    type is what to match on
+ */
+TrustedPeerCert* GetTrustedPeer(void* vp, byte* hash, int type)
+{
+    WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
+    TrustedPeerCert* ret = NULL;
+    TrustedPeerCert* tp  = NULL;
+    word32  row;
+
+    if (cm == NULL || hash == NULL)
+        return NULL;
+
+    row = TrustedPeerHashSigner(hash);
+
+    if (wc_LockMutex(&cm->tpLock) != 0)
+        return ret;
+
+    tp = cm->tpTable[row];
+    while (tp) {
+        byte* subjectHash;
+        switch (type) {
+            #ifndef NO_SKID
+            case WC_MATCH_SKID:
+                subjectHash = tp->subjectKeyIdHash;
+                break;
+            #endif
+            case WC_MATCH_NAME:
+                subjectHash = tp->subjectNameHash;
+                break;
+            default:
+                WOLFSSL_MSG("Unknown search type");
+                wc_UnLockMutex(&cm->tpLock);
+                return NULL;
+        }
+        if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
+            ret = tp;
+            break;
+        }
+        tp = tp->next;
+    }
+    wc_UnLockMutex(&cm->tpLock);
+
+    return ret;
+}
+
+
+int MatchTrustedPeer(TrustedPeerCert* tp, DecodedCert* cert)
+{
+    if (tp == NULL || cert == NULL)
+        return BAD_FUNC_ARG;
+
+    /* subject key id or subject hash has been compared when searching
+       tpTable for the cert from function GetTrustedPeer */
+
+    /* compare signatures */
+    if (tp->sigLen == cert->sigLength) {
+        if (XMEMCMP(tp->sig, cert->signature, cert->sigLength)) {
+            return WOLFSSL_FAILURE;
+        }
+    }
+    else {
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* WOLFSSL_TRUST_PEER_CERT */
+
+
+/* return CA if found, otherwise NULL */
+Signer* GetCA(void* vp, byte* hash)
+{
+    WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
+    Signer* ret = NULL;
+    Signer* signers;
+    word32  row = HashSigner(hash);
+
+    if (cm == NULL)
+        return NULL;
+
+    if (wc_LockMutex(&cm->caLock) != 0)
+        return ret;
+
+    signers = cm->caTable[row];
+    while (signers) {
+        byte* subjectHash;
+        #ifndef NO_SKID
+            subjectHash = signers->subjectKeyIdHash;
+        #else
+            subjectHash = signers->subjectNameHash;
+        #endif
+        if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
+            ret = signers;
+            break;
+        }
+        signers = signers->next;
+    }
+    wc_UnLockMutex(&cm->caLock);
+
+    return ret;
+}
+
+
+#ifndef NO_SKID
+/* return CA if found, otherwise NULL. Walk through hash table. */
+Signer* GetCAByName(void* vp, byte* hash)
+{
+    WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
+    Signer* ret = NULL;
+    Signer* signers;
+    word32  row;
+
+    if (cm == NULL)
+        return NULL;
+
+    if (wc_LockMutex(&cm->caLock) != 0)
+        return ret;
+
+    for (row = 0; row < CA_TABLE_SIZE && ret == NULL; row++) {
+        signers = cm->caTable[row];
+        while (signers && ret == NULL) {
+            if (XMEMCMP(hash, signers->subjectNameHash,
+                        SIGNER_DIGEST_SIZE) == 0) {
+                ret = signers;
+            }
+            signers = signers->next;
+        }
+    }
+    wc_UnLockMutex(&cm->caLock);
+
+    return ret;
+}
+#endif
+
+
+#ifdef WOLFSSL_TRUST_PEER_CERT
+/* add a trusted peer cert to linked list */
+int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify)
+{
+    int ret, row;
+    TrustedPeerCert* peerCert;
+    DecodedCert* cert;
+    DerBuffer*   der = *pDer;
+    byte* subjectHash = NULL;
+
+    WOLFSSL_MSG("Adding a Trusted Peer Cert");
+
+    cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap,
+                                 DYNAMIC_TYPE_DCERT);
+    if (cert == NULL)
+        return MEMORY_E;
+
+    InitDecodedCert(cert, der->buffer, der->length, cm->heap);
+    if ((ret = ParseCert(cert, TRUSTED_PEER_TYPE, verify, cm)) != 0) {
+        FreeDecodedCert(cert);
+        XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
+        return ret;
+    }
+    WOLFSSL_MSG("\tParsed new trusted peer cert");
+
+    peerCert = (TrustedPeerCert*)XMALLOC(sizeof(TrustedPeerCert), cm->heap,
+                                                             DYNAMIC_TYPE_CERT);
+    if (peerCert == NULL) {
+        FreeDecodedCert(cert);
+        XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
+        return MEMORY_E;
+    }
+    XMEMSET(peerCert, 0, sizeof(TrustedPeerCert));
+
+#ifndef NO_SKID
+    if (cert->extAuthKeyIdSet) {
+        subjectHash = cert->extSubjKeyId;
+    }
+    else {
+        subjectHash = cert->subjectHash;
+    }
+#else
+    subjectHash = cert->subjectHash;
+#endif
+
+    #ifndef IGNORE_NAME_CONSTRAINTS
+        if (peerCert->permittedNames)
+            FreeNameSubtrees(peerCert->permittedNames, cm->heap);
+        if (peerCert->excludedNames)
+            FreeNameSubtrees(peerCert->excludedNames, cm->heap);
+    #endif
+
+    if (AlreadyTrustedPeer(cm, subjectHash)) {
+        WOLFSSL_MSG("\tAlready have this CA, not adding again");
+        FreeTrustedPeer(peerCert, cm->heap);
+        (void)ret;
+    }
+    else {
+        /* add trusted peer signature */
+        peerCert->sigLen = cert->sigLength;
+        peerCert->sig = XMALLOC(cert->sigLength, cm->heap,
+                                                        DYNAMIC_TYPE_SIGNATURE);
+        if (peerCert->sig == NULL) {
+            FreeDecodedCert(cert);
+            XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
+            FreeTrustedPeer(peerCert, cm->heap);
+            return MEMORY_E;
+        }
+        XMEMCPY(peerCert->sig, cert->signature, cert->sigLength);
+
+        /* add trusted peer name */
+        peerCert->nameLen = cert->subjectCNLen;
+        peerCert->name    = cert->subjectCN;
+        #ifndef IGNORE_NAME_CONSTRAINTS
+            peerCert->permittedNames = cert->permittedNames;
+            peerCert->excludedNames  = cert->excludedNames;
+        #endif
+
+        /* add SKID when available and hash of name */
+        #ifndef NO_SKID
+            XMEMCPY(peerCert->subjectKeyIdHash, cert->extSubjKeyId,
+                    SIGNER_DIGEST_SIZE);
+        #endif
+            XMEMCPY(peerCert->subjectNameHash, cert->subjectHash,
+                    SIGNER_DIGEST_SIZE);
+            peerCert->next    = NULL; /* If Key Usage not set, all uses valid. */
+            cert->subjectCN = 0;
+        #ifndef IGNORE_NAME_CONSTRAINTS
+            cert->permittedNames = NULL;
+            cert->excludedNames = NULL;
+        #endif
+
+        #ifndef NO_SKID
+            if (cert->extAuthKeyIdSet) {
+                row = TrustedPeerHashSigner(peerCert->subjectKeyIdHash);
+            }
+            else {
+                row = TrustedPeerHashSigner(peerCert->subjectNameHash);
+            }
+        #else
+            row = TrustedPeerHashSigner(peerCert->subjectNameHash);
+        #endif
+
+            if (wc_LockMutex(&cm->tpLock) == 0) {
+                peerCert->next = cm->tpTable[row];
+                cm->tpTable[row] = peerCert;   /* takes ownership */
+                wc_UnLockMutex(&cm->tpLock);
+            }
+            else {
+                WOLFSSL_MSG("\tTrusted Peer Cert Mutex Lock failed");
+                FreeDecodedCert(cert);
+                XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
+                FreeTrustedPeer(peerCert, cm->heap);
+                return BAD_MUTEX_E;
+            }
+        }
+
+    WOLFSSL_MSG("\tFreeing parsed trusted peer cert");
+    FreeDecodedCert(cert);
+    XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
+    WOLFSSL_MSG("\tFreeing der trusted peer cert");
+    FreeDer(&der);
+    WOLFSSL_MSG("\t\tOK Freeing der trusted peer cert");
+    WOLFSSL_LEAVE("AddTrustedPeer", ret);
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* WOLFSSL_TRUST_PEER_CERT */
+
+
+/* owns der, internal now uses too */
+/* type flag ids from user or from chain received during verify
+   don't allow chain ones to be added w/o isCA extension */
+int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
+{
+    int         ret;
+    Signer*     signer = NULL;
+    word32      row;
+    byte*       subjectHash;
+#ifdef WOLFSSL_SMALL_STACK
+    DecodedCert* cert = NULL;
+#else
+    DecodedCert  cert[1];
+#endif
+    DerBuffer*   der = *pDer;
+
+    WOLFSSL_MSG("Adding a CA");
+
+    if (cm == NULL) {
+        FreeDer(pDer);
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
+                                 DYNAMIC_TYPE_DCERT);
+    if (cert == NULL) {
+        FreeDer(pDer);
+        return MEMORY_E;
+    }
+#endif
+
+    InitDecodedCert(cert, der->buffer, der->length, cm->heap);
+    ret = ParseCert(cert, CA_TYPE, verify, cm);
+    WOLFSSL_MSG("\tParsed new CA");
+
+#ifndef NO_SKID
+    subjectHash = cert->extSubjKeyId;
+#else
+    subjectHash = cert->subjectHash;
+#endif
+
+    /* check CA key size */
+    if (verify) {
+        switch (cert->keyOID) {
+            #ifndef NO_RSA
+            case RSAk:
+                if (cm->minRsaKeySz < 0 ||
+                                   cert->pubKeySize < (word16)cm->minRsaKeySz) {
+                    ret = RSA_KEY_SIZE_E;
+                    WOLFSSL_MSG("\tCA RSA key size error");
+                }
+                break;
+            #endif /* !NO_RSA */
+            #ifdef HAVE_ECC
+            case ECDSAk:
+                if (cm->minEccKeySz < 0 ||
+                                   cert->pubKeySize < (word16)cm->minEccKeySz) {
+                    ret = ECC_KEY_SIZE_E;
+                    WOLFSSL_MSG("\tCA ECC key size error");
+                }
+                break;
+            #endif /* HAVE_ECC */
+            #ifdef HAVE_ED25519
+            case ED25519k:
+                if (cm->minEccKeySz < 0 ||
+                                   ED25519_KEY_SIZE < (word16)cm->minEccKeySz) {
+                    ret = ECC_KEY_SIZE_E;
+                    WOLFSSL_MSG("\tCA ECC key size error");
+                }
+                break;
+            #endif /* HAVE_ED25519 */
+            #ifdef HAVE_ED448
+            case ED448k:
+                if (cm->minEccKeySz < 0 ||
+                                     ED448_KEY_SIZE < (word16)cm->minEccKeySz) {
+                    ret = ECC_KEY_SIZE_E;
+                    WOLFSSL_MSG("\tCA ECC key size error");
+                }
+                break;
+            #endif /* HAVE_ED448 */
+
+            default:
+                WOLFSSL_MSG("\tNo key size check done on CA");
+                break; /* no size check if key type is not in switch */
+        }
+    }
+
+    if (ret == 0 && cert->isCA == 0 && type != WOLFSSL_USER_CA) {
+        WOLFSSL_MSG("\tCan't add as CA if not actually one");
+        ret = NOT_CA_ERROR;
+    }
+#ifndef ALLOW_INVALID_CERTSIGN
+    else if (ret == 0 && cert->isCA == 1 && type != WOLFSSL_USER_CA &&
+        !cert->selfSigned && (cert->extKeyUsage & KEYUSE_KEY_CERT_SIGN) == 0) {
+        /* Intermediate CA certs are required to have the keyCertSign
+        * extension set. User loaded root certs are not. */
+        WOLFSSL_MSG("\tDoesn't have key usage certificate signing");
+        ret = NOT_CA_ERROR;
+    }
+#endif
+    else if (ret == 0 && AlreadySigner(cm, subjectHash)) {
+        WOLFSSL_MSG("\tAlready have this CA, not adding again");
+        (void)ret;
+    }
+    else if (ret == 0) {
+        /* take over signer parts */
+        signer = MakeSigner(cm->heap);
+        if (!signer)
+            ret = MEMORY_ERROR;
+    }
+    if (ret == 0 && signer != NULL) {
+    #ifdef WOLFSSL_SIGNER_DER_CERT
+        ret = AllocDer(&signer->derCert, der->length, der->type, NULL);
+    }
+    if (ret == 0 && signer != NULL) {
+        XMEMCPY(signer->derCert->buffer, der->buffer, der->length);
+    #endif
+        signer->keyOID         = cert->keyOID;
+        if (cert->pubKeyStored) {
+            signer->publicKey      = cert->publicKey;
+            signer->pubKeySize     = cert->pubKeySize;
+        }
+        if (cert->subjectCNStored) {
+            signer->nameLen        = cert->subjectCNLen;
+            signer->name           = cert->subjectCN;
+        }
+        signer->pathLength     = cert->pathLength;
+        signer->maxPathLen     = cert->maxPathLen;
+        signer->pathLengthSet  = cert->pathLengthSet;
+        signer->selfSigned     = cert->selfSigned;
+    #ifndef IGNORE_NAME_CONSTRAINTS
+        signer->permittedNames = cert->permittedNames;
+        signer->excludedNames  = cert->excludedNames;
+    #endif
+    #ifndef NO_SKID
+        XMEMCPY(signer->subjectKeyIdHash, cert->extSubjKeyId,
+                SIGNER_DIGEST_SIZE);
+    #endif
+        XMEMCPY(signer->subjectNameHash, cert->subjectHash,
+                SIGNER_DIGEST_SIZE);
+    #ifdef HAVE_OCSP
+        XMEMCPY(signer->subjectKeyHash, cert->subjectKeyHash,
+                KEYID_SIZE);
+    #endif
+        signer->keyUsage = cert->extKeyUsageSet ? cert->extKeyUsage
+                                                : 0xFFFF;
+        signer->next    = NULL; /* If Key Usage not set, all uses valid. */
+        cert->publicKey = 0;    /* in case lock fails don't free here.   */
+        cert->subjectCN = 0;
+    #ifndef IGNORE_NAME_CONSTRAINTS
+        cert->permittedNames = NULL;
+        cert->excludedNames = NULL;
+    #endif
+
+    #ifndef NO_SKID
+        row = HashSigner(signer->subjectKeyIdHash);
+    #else
+        row = HashSigner(signer->subjectNameHash);
+    #endif
+
+        if (wc_LockMutex(&cm->caLock) == 0) {
+            signer->next = cm->caTable[row];
+            cm->caTable[row] = signer;   /* takes ownership */
+            wc_UnLockMutex(&cm->caLock);
+            if (cm->caCacheCallback)
+                cm->caCacheCallback(der->buffer, (int)der->length, type);
+        }
+        else {
+            WOLFSSL_MSG("\tCA Mutex Lock failed");
+            ret = BAD_MUTEX_E;
+            FreeSigner(signer, cm->heap);
+        }
+    }
+#if defined(WOLFSSL_RENESAS_TSIP_TLS)
+    /* Verify CA by TSIP so that generated tsip key is going to be able to */
+    /* be used for peer's cert verification                                */
+    /* TSIP is only able to handle USER CA, and only one CA.               */
+    /* Therefore, it doesn't need to call TSIP again if there is already   */
+    /* verified CA.                                                        */
+    if ( ret == 0 && signer != NULL ) {
+        signer->cm_idx = row;
+        if (type == WOLFSSL_USER_CA && tsip_rootCAverified() == 0 ) {
+            if ((ret = tsip_tls_RootCertVerify(cert->source, cert->maxIdx,
+                 cert->sigCtx.pubkey_n_start, cert->sigCtx.pubkey_n_len - 1,
+                 cert->sigCtx.pubkey_e_start, cert->sigCtx.pubkey_e_len - 1,
+                 row/* cm index */))
+                != 0)
+                WOLFSSL_MSG("tsip_tls_RootCertVerify() failed");
+            else
+                WOLFSSL_MSG("tsip_tls_RootCertVerify() succeed");
+        }
+    }
+#endif
+    WOLFSSL_MSG("\tFreeing Parsed CA");
+    FreeDecodedCert(cert);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
+#endif
+    WOLFSSL_MSG("\tFreeing der CA");
+    FreeDer(pDer);
+    WOLFSSL_MSG("\t\tOK Freeing der CA");
+
+    WOLFSSL_LEAVE("AddCA", ret);
+
+    return ret == 0 ? WOLFSSL_SUCCESS : ret;
+}
+
+#endif /* !NO_CERTS */
+
+
+#ifndef NO_SESSION_CACHE
+
+    /* basic config gives a cache with 33 sessions, adequate for clients and
+       embedded servers
+
+       TITAN_SESSION_CACHE allows just over 2 million sessions, for servers
+       with titanic amounts of memory with long session ID timeouts and high
+       levels of traffic.
+
+       HUGE_SESSION_CACHE yields 65,791 sessions, for servers under heavy load,
+       allows over 13,000 new sessions per minute or over 200 new sessions per
+       second
+
+       BIG_SESSION_CACHE yields 20,027 sessions
+
+       MEDIUM_SESSION_CACHE allows 1055 sessions, adequate for servers that
+       aren't under heavy load, basically allows 200 new sessions per minute
+
+       SMALL_SESSION_CACHE only stores 6 sessions, good for embedded clients
+       or systems where the default of nearly 3kB is too much RAM, this define
+       uses less than 500 bytes RAM
+
+       default SESSION_CACHE stores 33 sessions (no XXX_SESSION_CACHE defined)
+    */
+    #if defined(TITAN_SESSION_CACHE)
+        #define SESSIONS_PER_ROW 31
+        #define SESSION_ROWS 64937
+    #elif defined(HUGE_SESSION_CACHE)
+        #define SESSIONS_PER_ROW 11
+        #define SESSION_ROWS 5981
+    #elif defined(BIG_SESSION_CACHE)
+        #define SESSIONS_PER_ROW 7
+        #define SESSION_ROWS 2861
+    #elif defined(MEDIUM_SESSION_CACHE)
+        #define SESSIONS_PER_ROW 5
+        #define SESSION_ROWS 211
+    #elif defined(SMALL_SESSION_CACHE)
+        #define SESSIONS_PER_ROW 2
+        #define SESSION_ROWS 3
+    #else
+        #define SESSIONS_PER_ROW 3
+        #define SESSION_ROWS 11
+    #endif
+
+    typedef struct SessionRow {
+        int nextIdx;                           /* where to place next one   */
+        int totalCount;                        /* sessions ever on this row */
+        WOLFSSL_SESSION Sessions[SESSIONS_PER_ROW];
+    } SessionRow;
+
+    static WOLFSSL_GLOBAL SessionRow SessionCache[SESSION_ROWS];
+
+    #if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS)
+        static WOLFSSL_GLOBAL word32 PeakSessions;
+    #endif
+
+    static WOLFSSL_GLOBAL wolfSSL_Mutex session_mutex; /* SessionCache mutex */
+
+    #ifndef NO_CLIENT_CACHE
+
+        typedef struct ClientSession {
+            word16 serverRow;            /* SessionCache Row id */
+            word16 serverIdx;            /* SessionCache Idx (column) */
+        } ClientSession;
+
+        typedef struct ClientRow {
+            int nextIdx;                /* where to place next one   */
+            int totalCount;             /* sessions ever on this row */
+            ClientSession Clients[SESSIONS_PER_ROW];
+        } ClientRow;
+
+        static WOLFSSL_GLOBAL ClientRow ClientCache[SESSION_ROWS];
+                                                     /* Client Cache */
+                                                     /* uses session mutex */
+    #endif  /* NO_CLIENT_CACHE */
+
+#endif /* NO_SESSION_CACHE */
+
+WOLFSSL_ABI
+int wolfSSL_Init(void)
+{
+    WOLFSSL_ENTER("wolfSSL_Init");
+
+    if (initRefCount == 0) {
+        /* Initialize crypto for use with TLS connection */
+        if (wolfCrypt_Init() != 0) {
+            WOLFSSL_MSG("Bad wolfCrypt Init");
+            return WC_INIT_E;
+        }
+
+#ifdef OPENSSL_EXTRA
+        if (wolfSSL_RAND_seed(NULL, 0) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("wolfSSL_RAND_Seed failed");
+            return WC_INIT_E;
+        }
+#endif
+
+#ifndef NO_SESSION_CACHE
+        if (wc_InitMutex(&session_mutex) != 0) {
+            WOLFSSL_MSG("Bad Init Mutex session");
+            return BAD_MUTEX_E;
+        }
+#endif
+        if (wc_InitMutex(&count_mutex) != 0) {
+            WOLFSSL_MSG("Bad Init Mutex count");
+            return BAD_MUTEX_E;
+        }
+    }
+
+    if (wc_LockMutex(&count_mutex) != 0) {
+        WOLFSSL_MSG("Bad Lock Mutex count");
+        return BAD_MUTEX_E;
+    }
+
+    initRefCount++;
+    wc_UnLockMutex(&count_mutex);
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+
+#ifndef NO_CERTS
+
+/* process user cert chain to pass during the handshake */
+static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff,
+                         long sz, int format, int type, WOLFSSL* ssl,
+                         long* used, EncryptedInfo* info, int verify)
+{
+    int ret = 0;
+    void* heap = wolfSSL_CTX_GetHeap(ctx, ssl);
+#ifdef WOLFSSL_TLS13
+    int cnt = 0;
+#endif
+
+    if ((type == CA_TYPE) && (ctx == NULL)) {
+        WOLFSSL_MSG("Need context for CA load");
+        return BAD_FUNC_ARG;
+    }
+
+    /* we may have a user cert chain, try to consume */
+    if ((type == CERT_TYPE || type == CA_TYPE) && (info->consumed < sz)) {
+    #ifdef WOLFSSL_SMALL_STACK
+        byte   staticBuffer[1];                 /* force heap usage */
+    #else
+        byte   staticBuffer[FILE_BUFFER_SIZE];  /* tmp chain buffer */
+    #endif
+        byte*  chainBuffer = staticBuffer;
+        int    dynamicBuffer = 0;
+        word32 bufferSz;
+        long   consumed = info->consumed;
+        word32 idx = 0;
+        int    gotOne = 0;
+
+        /* Calculate max possible size, including max headers */
+        bufferSz = (word32)(sz - consumed) + (CERT_HEADER_SZ * MAX_CHAIN_DEPTH);
+        if (bufferSz > sizeof(staticBuffer)) {
+            WOLFSSL_MSG("Growing Tmp Chain Buffer");
+            /* will shrink to actual size */
+            chainBuffer = (byte*)XMALLOC(bufferSz, heap, DYNAMIC_TYPE_FILE);
+            if (chainBuffer == NULL) {
+                return MEMORY_E;
+            }
+            dynamicBuffer = 1;
+        }
+
+        WOLFSSL_MSG("Processing Cert Chain");
+        while (consumed < sz) {
+            DerBuffer* part = NULL;
+            word32 remain = (word32)(sz - consumed);
+            info->consumed = 0;
+
+            if (format == WOLFSSL_FILETYPE_PEM) {
+            #ifdef WOLFSSL_PEM_TO_DER
+                ret = PemToDer(buff + consumed, remain, type, &part,
+                               heap, info, NULL);
+            #else
+                ret = NOT_COMPILED_IN;
+            #endif
+            }
+            else {
+                int length = remain;
+                if (format == WOLFSSL_FILETYPE_ASN1) {
+                    /* get length of der (read sequence) */
+                    word32 inOutIdx = 0;
+                    if (GetSequence(buff + consumed, &inOutIdx, &length,
+                            remain) < 0) {
+                        ret = ASN_NO_PEM_HEADER;
+                    }
+                    length += inOutIdx; /* include leading sequence */
+                }
+                info->consumed = length;
+                if (ret == 0) {
+                    ret = AllocDer(&part, length, type, heap);
+                    if (ret == 0) {
+                        XMEMCPY(part->buffer, buff + consumed, length);
+                    }
+                }
+            }
+            if (ret == 0) {
+                gotOne = 1;
+#ifdef WOLFSSL_TLS13
+                cnt++;
+#endif
+                if ((idx + part->length + CERT_HEADER_SZ) > bufferSz) {
+                    WOLFSSL_MSG("   Cert Chain bigger than buffer");
+                    ret = BUFFER_E;
+                }
+                else {
+                    c32to24(part->length, &chainBuffer[idx]);
+                    idx += CERT_HEADER_SZ;
+                    XMEMCPY(&chainBuffer[idx], part->buffer, part->length);
+                    idx += part->length;
+                    consumed  += info->consumed;
+                    if (used)
+                        *used += info->consumed;
+                }
+
+                /* add CA's to certificate manager */
+                if (type == CA_TYPE) {
+                    /* verify CA unless user set to no verify */
+                    ret = AddCA(ctx->cm, &part, WOLFSSL_USER_CA, verify);
+                    gotOne = 0; /* don't exit loop for CA type */
+                }
+            }
+
+            FreeDer(&part);
+
+            if (ret == ASN_NO_PEM_HEADER && gotOne) {
+                WOLFSSL_MSG("We got one good cert, so stuff at end ok");
+                break;
+            }
+
+            if (ret < 0) {
+                WOLFSSL_MSG("   Error in Cert in Chain");
+                if (dynamicBuffer)
+                    XFREE(chainBuffer, heap, DYNAMIC_TYPE_FILE);
+                return ret;
+            }
+            WOLFSSL_MSG("   Consumed another Cert in Chain");
+        }
+        WOLFSSL_MSG("Finished Processing Cert Chain");
+
+        /* only retain actual size used */
+        ret = 0;
+        if (idx > 0) {
+            if (ssl) {
+                if (ssl->buffers.weOwnCertChain) {
+                    FreeDer(&ssl->buffers.certChain);
+                }
+                ret = AllocDer(&ssl->buffers.certChain, idx, type, heap);
+                if (ret == 0) {
+                    XMEMCPY(ssl->buffers.certChain->buffer, chainBuffer,
+                            idx);
+                    ssl->buffers.weOwnCertChain = 1;
+                }
+            #ifdef WOLFSSL_TLS13
+                ssl->buffers.certChainCnt = cnt;
+            #endif
+            } else if (ctx) {
+                FreeDer(&ctx->certChain);
+                ret = AllocDer(&ctx->certChain, idx, type, heap);
+                if (ret == 0) {
+                    XMEMCPY(ctx->certChain->buffer, chainBuffer, idx);
+                }
+            #ifdef WOLFSSL_TLS13
+                ctx->certChainCnt = cnt;
+            #endif
+            }
+        }
+
+        if (dynamicBuffer)
+            XFREE(chainBuffer, heap, DYNAMIC_TYPE_FILE);
+    }
+
+    return ret;
+}
+
+static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der,
+    int* keySz, word32* idx, int* resetSuites, int* keyFormat, void* heap, int devId)
+{
+    int ret = 0;
+
+    (void)heap;
+    (void)devId;
+
+    if (ctx == NULL && ssl == NULL)
+        ret = BAD_FUNC_ARG;
+    if (!der || !keySz || !idx || !resetSuites || !keyFormat)
+        ret = BAD_FUNC_ARG;
+
+#ifndef NO_RSA
+    if (ret == 0 && (*keyFormat == 0 || *keyFormat == RSAk)) {
+        /* make sure RSA key can be used */
+    #ifdef WOLFSSL_SMALL_STACK
+        RsaKey* key;
+    #else
+        RsaKey  key[1];
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        key = (RsaKey*)XMALLOC(sizeof(RsaKey), heap, DYNAMIC_TYPE_RSA);
+        if (key == NULL)
+            return MEMORY_E;
+    #endif
+
+        ret = wc_InitRsaKey_ex(key, heap, devId);
+        if (ret == 0) {
+            *idx = 0;
+            if (wc_RsaPrivateKeyDecode(der->buffer, idx, key, der->length)
+                != 0) {
+            #if !defined(HAVE_ECC) && !defined(HAVE_ED25519) && \
+                                                            !defined(HAVE_ED448)
+                WOLFSSL_MSG("RSA decode failed and ECC/ED25519/ED448 not "
+                            "enabled to try");
+                ret = WOLFSSL_BAD_FILE;
+            #endif
+            }
+            else {
+                /* check that the size of the RSA key is enough */
+                int minRsaSz = ssl ? ssl->options.minRsaKeySz :
+                    ctx->minRsaKeySz;
+                *keySz = wc_RsaEncryptSize((RsaKey*)key);
+                if (*keySz < minRsaSz) {
+                    ret = RSA_KEY_SIZE_E;
+                    WOLFSSL_MSG("Private Key size too small");
+                }
+
+                if (ssl) {
+                    ssl->buffers.keyType = rsa_sa_algo;
+                    ssl->buffers.keySz = *keySz;
+                }
+                else {
+                    ctx->privateKeyType = rsa_sa_algo;
+                    ctx->privateKeySz = *keySz;
+                }
+
+                *keyFormat = RSAk;
+
+                if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
+                    ssl->options.haveStaticECC = 0;
+                    *resetSuites = 1;
+                }
+            }
+
+            wc_FreeRsaKey(key);
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(key, heap, DYNAMIC_TYPE_RSA);
+    #endif
+    }
+#endif
+#ifdef HAVE_ECC
+    if (ret == 0 && (*keyFormat == 0 || *keyFormat == ECDSAk)) {
+        /* make sure ECC key can be used */
+    #ifdef WOLFSSL_SMALL_STACK
+        ecc_key* key;
+    #else
+        ecc_key  key[1];
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        key = (ecc_key*)XMALLOC(sizeof(ecc_key), heap, DYNAMIC_TYPE_ECC);
+        if (key == NULL)
+            return MEMORY_E;
+    #endif
+
+        if (wc_ecc_init_ex(key, heap, devId) == 0) {
+            *idx = 0;
+            if (wc_EccPrivateKeyDecode(der->buffer, idx, key,
+                                                        der->length) == 0) {
+                /* check for minimum ECC key size and then free */
+                int minKeySz = ssl ? ssl->options.minEccKeySz :
+                                                        ctx->minEccKeySz;
+                *keySz = wc_ecc_size(key);
+                if (*keySz < minKeySz) {
+                    WOLFSSL_MSG("ECC private key too small");
+                    ret = ECC_KEY_SIZE_E;
+                }
+
+                *keyFormat = ECDSAk;
+                if (ssl) {
+                    ssl->options.haveStaticECC = 1;
+                    ssl->buffers.keyType = ecc_dsa_sa_algo;
+                    ssl->buffers.keySz = *keySz;
+                }
+                else {
+                    ctx->haveStaticECC = 1;
+                    ctx->privateKeyType = ecc_dsa_sa_algo;
+                    ctx->privateKeySz = *keySz;
+                }
+
+                if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
+                    *resetSuites = 1;
+                }
+            }
+
+            wc_ecc_free(key);
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(key, heap, DYNAMIC_TYPE_ECC);
+    #endif
+    }
+#endif /* HAVE_ECC */
+#ifdef HAVE_ED25519
+    if (ret == 0 && (*keyFormat == 0 || *keyFormat == ED25519k)) {
+        /* make sure Ed25519 key can be used */
+    #ifdef WOLFSSL_SMALL_STACK
+        ed25519_key* key;
+    #else
+        ed25519_key  key[1];
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        key = (ed25519_key*)XMALLOC(sizeof(ed25519_key), heap,
+                                                      DYNAMIC_TYPE_ED25519);
+        if (key == NULL)
+            return MEMORY_E;
+    #endif
+
+        ret = wc_ed25519_init(key);
+        if (ret == 0) {
+            *idx = 0;
+            if (wc_Ed25519PrivateKeyDecode(der->buffer, idx, key,
+                                                        der->length) == 0) {
+                /* check for minimum key size and then free */
+                int minKeySz = ssl ? ssl->options.minEccKeySz :
+                                                           ctx->minEccKeySz;
+                *keySz = ED25519_KEY_SIZE;
+                if (*keySz < minKeySz) {
+                    WOLFSSL_MSG("ED25519 private key too small");
+                    ret = ECC_KEY_SIZE_E;
+                }
+                if (ret == 0) {
+                    if (ssl) {
+                        ssl->buffers.keyType = ed25519_sa_algo;
+                        ssl->buffers.keySz = *keySz;
+                    }
+                    else if (ctx) {
+                        ctx->privateKeyType = ed25519_sa_algo;
+                        ctx->privateKeySz = *keySz;
+                    }
+
+                    *keyFormat = ED25519k;
+                    if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
+                        *resetSuites = 1;
+                    }
+                }
+            }
+
+            wc_ed25519_free(key);
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(key, heap, DYNAMIC_TYPE_ED25519);
+    #endif
+    }
+#endif /* HAVE_ED25519 */
+#ifdef HAVE_ED448
+    if (ret == 0 && (*keyFormat == 0 || *keyFormat == ED448k)) {
+        /* make sure Ed448 key can be used */
+    #ifdef WOLFSSL_SMALL_STACK
+        ed448_key* key = NULL;
+    #else
+        ed448_key  key[1];
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        key = (ed448_key*)XMALLOC(sizeof(ed448_key), heap, DYNAMIC_TYPE_ED448);
+        if (key == NULL)
+            return MEMORY_E;
+    #endif
+
+        ret = wc_ed448_init(key);
+        if (ret == 0) {
+            *idx = 0;
+            if (wc_Ed448PrivateKeyDecode(der->buffer, idx, key,
+                                                            der->length) != 0) {
+                ret = WOLFSSL_BAD_FILE;
+            }
+
+            if (ret == 0) {
+                /* check for minimum key size and then free */
+                int minKeySz = ssl ? ssl->options.minEccKeySz :
+                                                               ctx->minEccKeySz;
+                *keySz = ED448_KEY_SIZE;
+                if (*keySz < minKeySz) {
+                    WOLFSSL_MSG("ED448 private key too small");
+                    ret = ECC_KEY_SIZE_E;
+                }
+            }
+            if (ret == 0) {
+                if (ssl) {
+                    ssl->buffers.keyType = ed448_sa_algo;
+                    ssl->buffers.keySz = *keySz;
+                }
+                else if (ctx) {
+                    ctx->privateKeyType = ed448_sa_algo;
+                    ctx->privateKeySz = *keySz;
+                }
+
+                *keyFormat = ED448k;
+                if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
+                    *resetSuites = 1;
+                }
+            }
+
+            wc_ed448_free(key);
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(key, heap, DYNAMIC_TYPE_ED448);
+    #endif
+    }
+#endif /* HAVE_ED448 */
+    return ret;
+}
+
+/* process the buffer buff, length sz, into ctx of format and type
+   used tracks bytes consumed, userChain specifies a user cert chain
+   to pass during the handshake */
+int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
+                         long sz, int format, int type, WOLFSSL* ssl,
+                         long* used, int userChain, int verify)
+{
+    DerBuffer*    der = NULL;        /* holds DER or RAW (for NTRU) */
+    int           ret = 0;
+    int           done = 0;
+    int           keyFormat = 0;
+    int           resetSuites = 0;
+    void*         heap = wolfSSL_CTX_GetHeap(ctx, ssl);
+    int           devId = wolfSSL_CTX_GetDevId(ctx, ssl);
+    word32        idx = 0;
+    int           keySz = 0;
+#if (defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED)) || \
+     defined(HAVE_PKCS8)
+    word32        algId = 0;
+#endif
+#ifdef WOLFSSL_SMALL_STACK
+    EncryptedInfo* info = NULL;
+#else
+    EncryptedInfo  info[1];
+#endif
+
+    (void)devId;
+    (void)idx;
+    (void)keySz;
+
+    if (used)
+        *used = sz;     /* used bytes default to sz, PEM chain may shorten*/
+
+    /* check args */
+    if (format != WOLFSSL_FILETYPE_ASN1 && format != WOLFSSL_FILETYPE_PEM
+                                    && format != WOLFSSL_FILETYPE_RAW)
+        return WOLFSSL_BAD_FILETYPE;
+
+    if (ctx == NULL && ssl == NULL)
+        return BAD_FUNC_ARG;
+
+#ifdef WOLFSSL_SMALL_STACK
+    info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), heap,
+                                   DYNAMIC_TYPE_ENCRYPTEDINFO);
+    if (info == NULL)
+        return MEMORY_E;
+#endif
+
+    XMEMSET(info, 0, sizeof(EncryptedInfo));
+#if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED)
+    if (ctx) {
+        info->passwd_cb       = ctx->passwd_cb;
+        info->passwd_userdata = ctx->passwd_userdata;
+    }
+#endif
+
+    if (format == WOLFSSL_FILETYPE_PEM) {
+    #ifdef WOLFSSL_PEM_TO_DER
+        ret = PemToDer(buff, sz, type, &der, heap, info, &keyFormat);
+    #else
+        ret = NOT_COMPILED_IN;
+    #endif
+    }
+    else {
+        /* ASN1 (DER) or RAW (NTRU) */
+        int length = (int)sz;
+        if (format == WOLFSSL_FILETYPE_ASN1) {
+            /* get length of der (read sequence or octet string) */
+            word32 inOutIdx = 0;
+            if (GetSequence(buff, &inOutIdx, &length, (word32)sz) >= 0) {
+                length += inOutIdx; /* include leading sequence */
+            }
+            /* get length using octect string (allowed for private key types) */
+            else if (type == PRIVATEKEY_TYPE &&
+                    GetOctetString(buff, &inOutIdx, &length, (word32)sz) >= 0) {
+                length += inOutIdx; /* include leading oct string */
+            }
+            else {
+                ret = ASN_PARSE_E;
+            }
+        }
+
+        info->consumed = length;
+
+        if (ret == 0) {
+            ret = AllocDer(&der, (word32)length, type, heap);
+            if (ret == 0) {
+                XMEMCPY(der->buffer, buff, length);
+            }
+
+        #ifdef HAVE_PKCS8
+            /* if private key try and remove PKCS8 header */
+            if (type == PRIVATEKEY_TYPE) {
+                if ((ret = ToTraditional_ex(der->buffer, der->length, &algId)) > 0) {
+                    /* Found PKCS8 header */
+                    /* ToTraditional_ex moves buff and returns adjusted length */
+                    der->length = ret;
+                }
+                ret = 0; /* failures should be ignored */
+            }
+        #endif
+        }
+    }
+
+    if (used) {
+        *used = info->consumed;
+    }
+
+    /* process user chain */
+    if (ret >= 0) {
+        /* Chain should have server cert first, then intermediates, then root.
+         * First certificate in chain is processed below after ProcessUserChain
+         *   and is loaded into ssl->buffers.certificate.
+         * Remainder are processed using ProcessUserChain and are loaded into
+         *   ssl->buffers.certChain. */
+        if (userChain) {
+            ret = ProcessUserChain(ctx, buff, sz, format, type, ssl, used, info,
+                                   verify);
+        }
+    }
+
+    /* info is only used for private key with DER or PEM, so free now */
+    if (ret < 0 || type != PRIVATEKEY_TYPE || format == WOLFSSL_FILETYPE_RAW) {
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO);
+    #endif
+    }
+
+    /* check for error */
+    if (ret < 0) {
+        FreeDer(&der);
+        done = 1;
+    }
+
+    if (done == 1) {
+        /* No operation, just skip the next section */
+    }
+    /* Handle DER owner */
+    else if (type == CA_TYPE) {
+        if (ctx == NULL) {
+            WOLFSSL_MSG("Need context for CA load");
+            FreeDer(&der);
+            return BAD_FUNC_ARG;
+        }
+        /* verify CA unless user set to no verify */
+        ret = AddCA(ctx->cm, &der, WOLFSSL_USER_CA, verify);
+        done = 1;
+    }
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    else if (type == TRUSTED_PEER_TYPE) {
+        if (ctx == NULL) {
+            WOLFSSL_MSG("Need context for trusted peer cert load");
+            FreeDer(&der);
+            return BAD_FUNC_ARG;
+        }
+        /* add trusted peer cert */
+        ret = AddTrustedPeer(ctx->cm, &der, !ctx->verifyNone);
+        done = 1;
+    }
+#endif /* WOLFSSL_TRUST_PEER_CERT */
+    else if (type == CERT_TYPE) {
+        if (ssl) {
+             /* Make sure previous is free'd */
+            if (ssl->buffers.weOwnCert) {
+                FreeDer(&ssl->buffers.certificate);
+            #ifdef KEEP_OUR_CERT
+                FreeX509(ssl->ourCert);
+                if (ssl->ourCert) {
+                    XFREE(ssl->ourCert, ssl->heap, DYNAMIC_TYPE_X509);
+                    ssl->ourCert = NULL;
+                }
+            #endif
+            }
+            ssl->buffers.certificate = der;
+        #ifdef KEEP_OUR_CERT
+            ssl->keepCert = 1; /* hold cert for ssl lifetime */
+        #endif
+            ssl->buffers.weOwnCert = 1;
+        }
+        else if (ctx) {
+            FreeDer(&ctx->certificate); /* Make sure previous is free'd */
+        #ifdef KEEP_OUR_CERT
+            if (ctx->ourCert) {
+                if (ctx->ownOurCert) {
+                    FreeX509(ctx->ourCert);
+                    XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509);
+                }
+                ctx->ourCert = NULL;
+            }
+        #endif
+            ctx->certificate = der;
+        }
+    }
+    else if (type == PRIVATEKEY_TYPE) {
+        if (ssl) {
+             /* Make sure previous is free'd */
+            if (ssl->buffers.weOwnKey) {
+                FreeDer(&ssl->buffers.key);
+            }
+            ssl->buffers.key = der;
+            ssl->buffers.weOwnKey = 1;
+        }
+        else if (ctx) {
+            FreeDer(&ctx->privateKey);
+            ctx->privateKey = der;
+        }
+    }
+    else {
+        FreeDer(&der);
+        return WOLFSSL_BAD_CERTTYPE;
+    }
+
+    if (done == 1) {
+        /* No operation, just skip the next section */
+    }
+    else if (type == PRIVATEKEY_TYPE && format != WOLFSSL_FILETYPE_RAW) {
+    #if defined(WOLFSSL_ENCRYPTED_KEYS) || defined(HAVE_PKCS8)
+        keyFormat = algId;
+    #endif
+
+        ret = ProcessBufferTryDecode(ctx, ssl, der, &keySz, &idx, &resetSuites,
+                &keyFormat, heap, devId);
+
+    #if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED)
+        /* for WOLFSSL_FILETYPE_PEM, PemToDer manages the decryption */
+        /* If private key type PKCS8 header wasn't already removed (algoId == 0) */
+        if ((ret != 0 || keyFormat == 0)
+            && format != WOLFSSL_FILETYPE_PEM && info->passwd_cb && algId == 0)
+        {
+            int   passwordSz = NAME_SZ;
+        #ifndef WOLFSSL_SMALL_STACK
+            char  password[NAME_SZ];
+        #else
+            char* password = (char*)XMALLOC(passwordSz, heap, DYNAMIC_TYPE_STRING);
+            if (password == NULL) {
+            #ifdef WOLFSSL_SMALL_STACK
+                XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO);
+            #endif
+                FreeDer(&der);
+                return MEMORY_E;
+            }
+        #endif
+            /* get password */
+            ret = info->passwd_cb(password, passwordSz, PEM_PASS_READ,
+                info->passwd_userdata);
+            if (ret >= 0) {
+                passwordSz = ret;
+
+                /* PKCS8 decrypt */
+                ret = ToTraditionalEnc(der->buffer, der->length,
+                                       password, passwordSz, &algId);
+                if (ret >= 0) {
+                    der->length = ret;
+                }
+                /* ignore failures and try parsing as unencrypted */
+
+                ForceZero(password, passwordSz);
+            }
+
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(password, heap, DYNAMIC_TYPE_STRING);
+        #endif
+            ret = ProcessBufferTryDecode(ctx, ssl, der, &keySz, &idx,
+                &resetSuites, &keyFormat, heap, devId);
+        }
+    #endif /* WOLFSSL_ENCRYPTED_KEYS && !NO_PWDBASED */
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO);
+    #endif
+
+        if (ret != 0)
+            return ret;
+        if (keyFormat == 0)
+            return WOLFSSL_BAD_FILE;
+
+        (void)devId;
+    }
+    else if (type == CERT_TYPE) {
+    #ifdef WOLFSSL_SMALL_STACK
+        DecodedCert* cert;
+    #else
+        DecodedCert  cert[1];
+    #endif
+    #ifdef HAVE_PK_CALLBACKS
+        int keyType = 0;
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), heap,
+                                     DYNAMIC_TYPE_DCERT);
+        if (cert == NULL)
+            return MEMORY_E;
+    #endif
+
+        WOLFSSL_MSG("Checking cert signature type");
+        InitDecodedCert(cert, der->buffer, der->length, heap);
+
+        if (DecodeToKey(cert, 0) < 0) {
+            WOLFSSL_MSG("Decode to key failed");
+            FreeDecodedCert(cert);
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(cert, heap, DYNAMIC_TYPE_DCERT);
+        #endif
+            return WOLFSSL_BAD_FILE;
+        }
+
+        if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
+            resetSuites = 1;
+        }
+        if (ssl && ssl->ctx->haveECDSAsig) {
+            WOLFSSL_MSG("SSL layer setting cert, CTX had ECDSA, turning off");
+            ssl->options.haveECDSAsig = 0;   /* may turn back on next */
+        }
+
+        switch (cert->signatureOID) {
+            case CTC_SHAwECDSA:
+            case CTC_SHA256wECDSA:
+            case CTC_SHA384wECDSA:
+            case CTC_SHA512wECDSA:
+                WOLFSSL_MSG("ECDSA cert signature");
+                if (ssl)
+                    ssl->options.haveECDSAsig = 1;
+                else if (ctx)
+                    ctx->haveECDSAsig = 1;
+                break;
+            case CTC_ED25519:
+                WOLFSSL_MSG("ED25519 cert signature");
+                if (ssl)
+                    ssl->options.haveECDSAsig = 1;
+                else if (ctx)
+                    ctx->haveECDSAsig = 1;
+                break;
+            case CTC_ED448:
+                WOLFSSL_MSG("ED448 cert signature");
+                if (ssl)
+                    ssl->options.haveECDSAsig = 1;
+                else if (ctx)
+                    ctx->haveECDSAsig = 1;
+                break;
+            default:
+                WOLFSSL_MSG("Not ECDSA cert signature");
+                break;
+        }
+
+    #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
+        if (ssl) {
+            ssl->pkCurveOID = cert->pkCurveOID;
+        #ifndef WC_STRICT_SIG
+            if (cert->keyOID == ECDSAk) {
+                ssl->options.haveECC = 1;
+            }
+            #ifdef HAVE_ED25519
+                else if (cert->keyOID == ED25519k) {
+                    ssl->options.haveECC = 1;
+                }
+            #endif
+            #ifdef HAVE_ED448
+                else if (cert->keyOID == ED448k) {
+                    ssl->options.haveECC = 1;
+                }
+            #endif
+        #else
+            ssl->options.haveECC = ssl->options.haveECDSAsig;
+        #endif
+        }
+        else if (ctx) {
+            ctx->pkCurveOID = cert->pkCurveOID;
+        #ifndef WC_STRICT_SIG
+            if (cert->keyOID == ECDSAk) {
+                ctx->haveECC = 1;
+            }
+            #ifdef HAVE_ED25519
+                else if (cert->keyOID == ED25519k) {
+                    ctx->haveECC = 1;
+                }
+            #endif
+            #ifdef HAVE_ED448
+                else if (cert->keyOID == ED448k) {
+                    ctx->haveECC = 1;
+                }
+            #endif
+        #else
+            ctx->haveECC = ctx->haveECDSAsig;
+        #endif
+        }
+    #endif
+
+        /* check key size of cert unless specified not to */
+        switch (cert->keyOID) {
+        #ifndef NO_RSA
+            case RSAk:
+            #ifdef HAVE_PK_CALLBACKS
+                keyType = rsa_sa_algo;
+            #endif
+            #ifdef HAVE_PKCS11
+                if (ctx) {
+                    ctx->privateKeyType = rsa_sa_algo;
+                }
+                else {
+                    ssl->buffers.keyType = rsa_sa_algo;
+                }
+            #endif
+                /* Determine RSA key size by parsing public key */
+                idx = 0;
+                ret = wc_RsaPublicKeyDecode_ex(cert->publicKey, &idx,
+                    cert->pubKeySize, NULL, (word32*)&keySz, NULL, NULL);
+                if (ret < 0)
+                    break;
+
+                if (ssl && !ssl->options.verifyNone) {
+                    if (ssl->options.minRsaKeySz < 0 ||
+                          keySz < (int)ssl->options.minRsaKeySz) {
+                        ret = RSA_KEY_SIZE_E;
+                        WOLFSSL_MSG("Certificate RSA key size too small");
+                    }
+                }
+                else if (ctx && !ctx->verifyNone) {
+                    if (ctx->minRsaKeySz < 0 ||
+                                  keySz < (int)ctx->minRsaKeySz) {
+                        ret = RSA_KEY_SIZE_E;
+                        WOLFSSL_MSG("Certificate RSA key size too small");
+                    }
+                }
+                break;
+        #endif /* !NO_RSA */
+        #ifdef HAVE_ECC
+            case ECDSAk:
+            #ifdef HAVE_PK_CALLBACKS
+                keyType = ecc_dsa_sa_algo;
+            #endif
+            #ifdef HAVE_PKCS11
+                if (ctx) {
+                    ctx->privateKeyType = ecc_dsa_sa_algo;
+                }
+                else {
+                    ssl->buffers.keyType = ecc_dsa_sa_algo;
+                }
+            #endif
+                /* Determine ECC key size based on curve */
+                keySz = wc_ecc_get_curve_size_from_id(
+                    wc_ecc_get_oid(cert->pkCurveOID, NULL, NULL));
+
+                if (ssl && !ssl->options.verifyNone) {
+                    if (ssl->options.minEccKeySz < 0 ||
+                          keySz < (int)ssl->options.minEccKeySz) {
+                        ret = ECC_KEY_SIZE_E;
+                        WOLFSSL_MSG("Certificate ECC key size error");
+                    }
+                }
+                else if (ctx && !ctx->verifyNone) {
+                    if (ctx->minEccKeySz < 0 ||
+                                  keySz < (int)ctx->minEccKeySz) {
+                        ret = ECC_KEY_SIZE_E;
+                        WOLFSSL_MSG("Certificate ECC key size error");
+                    }
+                }
+                break;
+        #endif /* HAVE_ECC */
+        #ifdef HAVE_ED25519
+            case ED25519k:
+            #ifdef HAVE_PK_CALLBACKS
+                keyType = ed25519_sa_algo;
+            #endif
+            #ifdef HAVE_PKCS11
+                if (ctx) {
+                    ctx->privateKeyType = ed25519_sa_algo;
+                }
+                else {
+                    ssl->buffers.keyType = ed25519_sa_algo;
+                }
+            #endif
+                /* ED25519 is fixed key size */
+                keySz = ED25519_KEY_SIZE;
+                if (ssl && !ssl->options.verifyNone) {
+                    if (ssl->options.minEccKeySz < 0 ||
+                          keySz < (int)ssl->options.minEccKeySz) {
+                        ret = ECC_KEY_SIZE_E;
+                        WOLFSSL_MSG("Certificate Ed key size error");
+                    }
+                }
+                else if (ctx && !ctx->verifyNone) {
+                    if (ctx->minEccKeySz < 0 ||
+                                  keySz < (int)ctx->minEccKeySz) {
+                        ret = ECC_KEY_SIZE_E;
+                        WOLFSSL_MSG("Certificate ECC key size error");
+                    }
+                }
+                break;
+        #endif /* HAVE_ED25519 */
+        #ifdef HAVE_ED448
+            case ED448k:
+            #ifdef HAVE_PK_CALLBACKS
+                keyType = ed448_sa_algo;
+            #endif
+            #ifdef HAVE_PKCS11
+                if (ctx) {
+                    ctx->privateKeyType = ed448_sa_algo;
+                }
+                else {
+                    ssl->buffers.keyType = ed448_sa_algo;
+                }
+            #endif
+                /* ED448 is fixed key size */
+                keySz = ED448_KEY_SIZE;
+                if (ssl && !ssl->options.verifyNone) {
+                    if (ssl->options.minEccKeySz < 0 ||
+                          keySz < (int)ssl->options.minEccKeySz) {
+                        ret = ECC_KEY_SIZE_E;
+                        WOLFSSL_MSG("Certificate Ed key size error");
+                    }
+                }
+                else if (ctx && !ctx->verifyNone) {
+                    if (ctx->minEccKeySz < 0 ||
+                                  keySz < (int)ctx->minEccKeySz) {
+                        ret = ECC_KEY_SIZE_E;
+                        WOLFSSL_MSG("Certificate ECC key size error");
+                    }
+                }
+                break;
+        #endif /* HAVE_ED448 */
+
+            default:
+                WOLFSSL_MSG("No key size check done on certificate");
+                break; /* do no check if not a case for the key */
+        }
+
+    #ifdef HAVE_PK_CALLBACKS
+        if (ssl && ssl->buffers.keyType == 0) {
+            ssl->buffers.keyType = keyType;
+            ssl->buffers.keySz = keySz;
+        }
+        else if (ctx && ctx->privateKeyType == 0) {
+            ctx->privateKeyType = keyType;
+            ctx->privateKeySz = keySz;
+        }
+    #endif
+
+        FreeDecodedCert(cert);
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(cert, heap, DYNAMIC_TYPE_DCERT);
+    #endif
+
+        if (ret != 0) {
+            done = 1;
+        }
+    }
+
+    if (done == 1) {
+    #ifndef NO_WOLFSSL_CM_VERIFY
+        if ((type == CA_TYPE) || (type == CERT_TYPE)) {
+            /* Call to over-ride status */
+            if ((ctx != NULL) && (ctx->cm != NULL) &&
+                (ctx->cm->verifyCallback != NULL)) {
+                ret = CM_VerifyBuffer_ex(ctx->cm, buff,
+                        sz, format, (ret == WOLFSSL_SUCCESS ? 0 : ret));
+            }
+        }
+    #endif /* NO_WOLFSSL_CM_VERIFY */
+
+        return ret;
+    }
+
+
+    if (ssl && resetSuites) {
+        word16 havePSK = 0;
+        word16 haveRSA = 0;
+
+        #ifndef NO_PSK
+        if (ssl->options.havePSK) {
+            havePSK = 1;
+        }
+        #endif
+        #ifndef NO_RSA
+            haveRSA = 1;
+        #endif
+        #ifndef NO_CERTS
+            keySz = ssl->buffers.keySz;
+        #endif
+
+        /* let's reset suites */
+        InitSuites(ssl->suites, ssl->version, keySz, haveRSA,
+                   havePSK, ssl->options.haveDH, ssl->options.haveNTRU,
+                   ssl->options.haveECDSAsig, ssl->options.haveECC,
+                   ssl->options.haveStaticECC, ssl->options.side);
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* CA PEM file for verification, may have multiple/chain certs to process */
+static int ProcessChainBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
+                        long sz, int format, int type, WOLFSSL* ssl, int verify)
+{
+    long used   = 0;
+    int  ret    = 0;
+    int  gotOne = 0;
+
+    WOLFSSL_MSG("Processing CA PEM file");
+    while (used < sz) {
+        long consumed = 0;
+
+        ret = ProcessBuffer(ctx, buff + used, sz - used, format, type, ssl,
+                            &consumed, 0, verify);
+
+        if (ret < 0) {
+#if defined(WOLFSSL_WPAS) && defined(HAVE_CRL)
+            DerBuffer*    der = NULL;
+            EncryptedInfo info;
+
+            WOLFSSL_MSG("Trying a CRL");
+            if (PemToDer(buff + used, sz - used, CRL_TYPE, &der, NULL, &info,
+                                                                   NULL) == 0) {
+                WOLFSSL_MSG("   Processed a CRL");
+                wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, der->buffer,
+                                            der->length, WOLFSSL_FILETYPE_ASN1);
+                FreeDer(&der);
+                used += info.consumed;
+                continue;
+            }
+#endif
+
+            if (consumed > 0) { /* Made progress in file */
+                WOLFSSL_ERROR(ret);
+                WOLFSSL_MSG("CA Parse failed, with progress in file.");
+                WOLFSSL_MSG("Search for other certs in file");
+            }
+            else {
+                WOLFSSL_MSG("CA Parse failed, no progress in file.");
+                WOLFSSL_MSG("Do not continue search for other certs in file");
+                break;
+            }
+        }
+        else {
+            WOLFSSL_MSG("   Processed a CA");
+            gotOne = 1;
+        }
+        used += consumed;
+    }
+
+    if (gotOne) {
+        WOLFSSL_MSG("Processed at least one valid CA. Other stuff OK");
+        return WOLFSSL_SUCCESS;
+    }
+    return ret;
+}
+
+
+static WC_INLINE WOLFSSL_METHOD* cm_pick_method(void)
+{
+    #ifndef NO_WOLFSSL_CLIENT
+        #if !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_SSLV3)
+            return wolfSSLv3_client_method();
+        #elif !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLSV10)
+            return wolfTLSv1_client_method();
+        #elif !defined(NO_OLD_TLS)
+            return wolfTLSv1_1_client_method();
+        #elif !defined(WOLFSSL_NO_TLS12)
+            return wolfTLSv1_2_client_method();
+        #elif defined(WOLFSSL_TLS13)
+            return wolfTLSv1_3_client_method();
+        #else
+            return NULL;
+        #endif
+    #elif !defined(NO_WOLFSSL_SERVER)
+        #if !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_SSLV3)
+            return wolfSSLv3_server_method();
+        #elif !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLSV10)
+            return wolfTLSv1_server_method();
+        #elif !defined(NO_OLD_TLS)
+            return wolfTLSv1_1_server_method();
+        #elif !defined(WOLFSSL_NO_TLS12)
+            return wolfTLSv1_2_server_method();
+        #elif defined(WOLFSSL_TLS13)
+            return wolfTLSv1_3_server_method();
+        #else
+            return NULL;
+        #endif
+    #else
+        return NULL;
+    #endif
+}
+
+
+/* like load verify locations, 1 for success, < 0 for error */
+int wolfSSL_CertManagerLoadCABuffer(WOLFSSL_CERT_MANAGER* cm,
+                                   const unsigned char* in, long sz, int format)
+{
+    int ret = WOLFSSL_FATAL_ERROR;
+    WOLFSSL_CTX* tmp;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCABuffer");
+
+    if (cm == NULL) {
+        WOLFSSL_MSG("No CertManager error");
+        return ret;
+    }
+    tmp = wolfSSL_CTX_new(cm_pick_method());
+
+    if (tmp == NULL) {
+        WOLFSSL_MSG("CTX new failed");
+        return ret;
+    }
+
+    /* for tmp use */
+    wolfSSL_CertManagerFree(tmp->cm);
+    tmp->cm = cm;
+
+    ret = wolfSSL_CTX_load_verify_buffer(tmp, in, sz, format);
+
+    /* don't loose our good one */
+    tmp->cm = NULL;
+    wolfSSL_CTX_free(tmp);
+
+    return ret;
+}
+
+#ifdef HAVE_CRL
+
+int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER* cm,
+                                   const unsigned char* buff, long sz, int type)
+{
+    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRLBuffer");
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    if (cm->crl == NULL) {
+        if (wolfSSL_CertManagerEnableCRL(cm, 0) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("Enable CRL failed");
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+
+    return BufferLoadCRL(cm->crl, buff, sz, type, VERIFY);
+}
+
+int wolfSSL_CertManagerFreeCRL(WOLFSSL_CERT_MANAGER* cm)
+{
+    WOLFSSL_ENTER("wolfSSL_CertManagerFreeCRL");
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+    if (cm->crl != NULL){
+        FreeCRL(cm->crl, 1);
+        cm->crl = NULL;
+    }
+    return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_CTX_LoadCRLBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
+                              long sz, int type)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_LoadCRLBuffer");
+
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    return wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, buff, sz, type);
+}
+
+
+int wolfSSL_LoadCRLBuffer(WOLFSSL* ssl, const unsigned char* buff,
+                          long sz, int type)
+{
+    WOLFSSL_ENTER("wolfSSL_LoadCRLBuffer");
+
+    if (ssl == NULL || ssl->ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    return wolfSSL_CertManagerLoadCRLBuffer(ssl->ctx->cm, buff, sz, type);
+}
+
+
+#endif /* HAVE_CRL */
+
+/* turn on CRL if off and compiled in, set options */
+int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER* cm, int options)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    (void)options;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerEnableCRL");
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    #ifdef HAVE_CRL
+        if (cm->crl == NULL) {
+            cm->crl = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), cm->heap,
+                                            DYNAMIC_TYPE_CRL);
+            if (cm->crl == NULL)
+                return MEMORY_E;
+
+            if (InitCRL(cm->crl, cm) != 0) {
+                WOLFSSL_MSG("Init CRL failed");
+                FreeCRL(cm->crl, 1);
+                cm->crl = NULL;
+                return WOLFSSL_FAILURE;
+            }
+
+        #ifdef HAVE_CRL_IO
+            cm->crl->crlIOCb = EmbedCrlLookup;
+        #endif
+        }
+
+        cm->crlEnabled = 1;
+        if (options & WOLFSSL_CRL_CHECKALL)
+            cm->crlCheckAll = 1;
+    #else
+        ret = NOT_COMPILED_IN;
+    #endif
+
+    return ret;
+}
+
+
+int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER* cm)
+{
+    WOLFSSL_ENTER("wolfSSL_CertManagerDisableCRL");
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    cm->crlEnabled = 0;
+
+    return WOLFSSL_SUCCESS;
+}
+
+#ifndef NO_WOLFSSL_CM_VERIFY
+void wolfSSL_CertManagerSetVerify(WOLFSSL_CERT_MANAGER* cm, VerifyCallback vc)
+{
+    WOLFSSL_ENTER("wolfSSL_CertManagerSetVerify");
+    if (cm == NULL)
+        return;
+
+    cm->verifyCallback = vc;
+}
+#endif /* NO_WOLFSSL_CM_VERIFY */
+
+/* Verify the certificate, WOLFSSL_SUCCESS for ok, < 0 for error */
+int CM_VerifyBuffer_ex(WOLFSSL_CERT_MANAGER* cm, const byte* buff,
+                                    long sz, int format, int err_val)
+{
+    int ret = 0;
+    DerBuffer* der = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    DecodedCert* cert;
+#else
+    DecodedCert  cert[1];
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerVerifyBuffer");
+
+#ifdef WOLFSSL_SMALL_STACK
+    cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap,
+                                 DYNAMIC_TYPE_DCERT);
+    if (cert == NULL)
+        return MEMORY_E;
+#endif
+
+    if (format == WOLFSSL_FILETYPE_PEM) {
+#ifdef WOLFSSL_PEM_TO_DER
+        ret = PemToDer(buff, sz, CERT_TYPE, &der, cm->heap, NULL, NULL);
+        if (ret != 0) {
+            FreeDer(&der);
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
+        #endif
+            return ret;
+        }
+        InitDecodedCert(cert, der->buffer, der->length, cm->heap);
+#else
+        ret = NOT_COMPILED_IN;
+#endif
+    }
+    else {
+        InitDecodedCert(cert, (byte*)buff, (word32)sz, cm->heap);
+    }
+
+    if (ret == 0)
+        ret = ParseCertRelative(cert, CERT_TYPE, 1, cm);
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+    /* ret needs to be self-singer error for Qt compat */
+    if (ret == ASN_NO_SIGNER_E && cert->selfSigned)
+        ret = ASN_SELF_SIGNED_E;
+#endif
+
+#ifdef HAVE_CRL
+    if (ret == 0 && cm->crlEnabled)
+        ret = CheckCertCRL(cm->crl, cert);
+#endif
+
+#ifndef NO_WOLFSSL_CM_VERIFY
+    /* if verify callback has been set */
+    if (cm->verifyCallback) {
+        buffer certBuf;
+    #ifdef WOLFSSL_SMALL_STACK
+        ProcPeerCertArgs* args;
+        args = (ProcPeerCertArgs*)XMALLOC(
+            sizeof(ProcPeerCertArgs), cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        if (args == NULL) {
+            XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
+            return MEMORY_E;
+        }
+    #else
+        ProcPeerCertArgs  args[1];
+    #endif
+
+        certBuf.buffer = (byte*)buff;
+        certBuf.length = (unsigned int)sz;
+        XMEMSET(args, 0, sizeof(ProcPeerCertArgs));
+
+        args->totalCerts = 1;
+        args->certs = &certBuf;
+        args->dCert = cert;
+        args->dCertInit = 1;
+
+        if (err_val != 0) {
+            ret = err_val;
+        }
+        ret = DoVerifyCallback(cm, NULL, ret, args);
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(args, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+    }
+#else
+    (void)err_val;
+#endif
+
+    FreeDecodedCert(cert);
+    FreeDer(&der);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
+#endif
+
+    return ret == 0 ? WOLFSSL_SUCCESS : ret;
+}
+
+/* Verify the certificate, WOLFSSL_SUCCESS for ok, < 0 for error */
+int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, const byte* buff,
+                                    long sz, int format)
+{
+    return CM_VerifyBuffer_ex(cm, buff, sz, format, 0);
+}
+/* turn on OCSP if off and compiled in, set options */
+int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER* cm, int options)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    (void)options;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSP");
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    #ifdef HAVE_OCSP
+        if (cm->ocsp == NULL) {
+            cm->ocsp = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP), cm->heap,
+                                              DYNAMIC_TYPE_OCSP);
+            if (cm->ocsp == NULL)
+                return MEMORY_E;
+
+            if (InitOCSP(cm->ocsp, cm) != 0) {
+                WOLFSSL_MSG("Init OCSP failed");
+                FreeOCSP(cm->ocsp, 1);
+                cm->ocsp = NULL;
+                return WOLFSSL_FAILURE;
+            }
+        }
+        cm->ocspEnabled = 1;
+        if (options & WOLFSSL_OCSP_URL_OVERRIDE)
+            cm->ocspUseOverrideURL = 1;
+        if (options & WOLFSSL_OCSP_NO_NONCE)
+            cm->ocspSendNonce = 0;
+        else
+            cm->ocspSendNonce = 1;
+        if (options & WOLFSSL_OCSP_CHECKALL)
+            cm->ocspCheckAll = 1;
+        #ifndef WOLFSSL_USER_IO
+            cm->ocspIOCb = EmbedOcspLookup;
+            cm->ocspRespFreeCb = EmbedOcspRespFree;
+            cm->ocspIOCtx = cm->heap;
+        #endif /* WOLFSSL_USER_IO */
+    #else
+        ret = NOT_COMPILED_IN;
+    #endif
+
+    return ret;
+}
+
+
+int wolfSSL_CertManagerDisableOCSP(WOLFSSL_CERT_MANAGER* cm)
+{
+    WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSP");
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    cm->ocspEnabled = 0;
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* turn on OCSP Stapling if off and compiled in, set options */
+int wolfSSL_CertManagerEnableOCSPStapling(WOLFSSL_CERT_MANAGER* cm)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSPStapling");
+
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+    #ifndef NO_WOLFSSL_SERVER
+    if (cm->ocsp_stapling == NULL) {
+        cm->ocsp_stapling = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP),
+                                               cm->heap, DYNAMIC_TYPE_OCSP);
+        if (cm->ocsp_stapling == NULL)
+            return MEMORY_E;
+
+        if (InitOCSP(cm->ocsp_stapling, cm) != 0) {
+            WOLFSSL_MSG("Init OCSP failed");
+            FreeOCSP(cm->ocsp_stapling, 1);
+            cm->ocsp_stapling = NULL;
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+    #ifndef WOLFSSL_USER_IO
+        cm->ocspIOCb = EmbedOcspLookup;
+        cm->ocspRespFreeCb = EmbedOcspRespFree;
+        cm->ocspIOCtx = cm->heap;
+    #endif /* WOLFSSL_USER_IO */
+    #endif /* NO_WOLFSSL_SERVER */
+    cm->ocspStaplingEnabled = 1;
+#else
+    ret = NOT_COMPILED_IN;
+#endif
+
+    return ret;
+}
+
+int wolfSSL_CertManagerDisableOCSPStapling(WOLFSSL_CERT_MANAGER* cm)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSPStapling");
+
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+    cm->ocspStaplingEnabled = 0;
+#else
+    ret = NOT_COMPILED_IN;
+#endif
+    return ret;
+}
+
+#ifdef HAVE_OCSP
+/* check CRL if enabled, WOLFSSL_SUCCESS  */
+int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER* cm, byte* der, int sz)
+{
+    int ret;
+#ifdef WOLFSSL_SMALL_STACK
+    DecodedCert* cert = NULL;
+#else
+    DecodedCert  cert[1];
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerCheckOCSP");
+
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    if (cm->ocspEnabled == 0)
+        return WOLFSSL_SUCCESS;
+
+#ifdef WOLFSSL_SMALL_STACK
+    cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
+    if (cert == NULL)
+        return MEMORY_E;
+#endif
+
+    InitDecodedCert(cert, der, sz, NULL);
+
+    if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_OCSP, cm)) != 0) {
+        WOLFSSL_MSG("ParseCert failed");
+    }
+    else if ((ret = CheckCertOCSP(cm->ocsp, cert, NULL)) != 0) {
+        WOLFSSL_MSG("CheckCertOCSP failed");
+    }
+
+    FreeDecodedCert(cert);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
+#endif
+
+    return ret == 0 ? WOLFSSL_SUCCESS : ret;
+}
+
+WOLFSSL_API int wolfSSL_CertManagerCheckOCSPResponse(WOLFSSL_CERT_MANAGER *cm,
+                                                    byte *response, int responseSz, buffer *responseBuffer,
+                                                    CertStatus *status, OcspEntry *entry, OcspRequest *ocspRequest)
+{
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerCheckOCSP_Staple");
+    if (cm == NULL || response == NULL)
+        return BAD_FUNC_ARG;
+    if (cm->ocspEnabled == 0)
+        return WOLFSSL_SUCCESS;
+
+    ret = CheckOcspResponse(cm->ocsp, response, responseSz, responseBuffer, status,
+                        entry, ocspRequest);
+
+    return ret == 0 ? WOLFSSL_SUCCESS : ret;
+}
+
+int wolfSSL_CertManagerSetOCSPOverrideURL(WOLFSSL_CERT_MANAGER* cm,
+                                          const char* url)
+{
+    WOLFSSL_ENTER("wolfSSL_CertManagerSetOCSPOverrideURL");
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL);
+    if (url != NULL) {
+        int urlSz = (int)XSTRLEN(url) + 1;
+        cm->ocspOverrideURL = (char*)XMALLOC(urlSz, cm->heap, DYNAMIC_TYPE_URL);
+        if (cm->ocspOverrideURL != NULL) {
+            XMEMCPY(cm->ocspOverrideURL, url, urlSz);
+        }
+        else
+            return MEMORY_E;
+    }
+    else
+        cm->ocspOverrideURL = NULL;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_CertManagerSetOCSP_Cb(WOLFSSL_CERT_MANAGER* cm,
+                        CbOCSPIO ioCb, CbOCSPRespFree respFreeCb, void* ioCbCtx)
+{
+    WOLFSSL_ENTER("wolfSSL_CertManagerSetOCSP_Cb");
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    cm->ocspIOCb = ioCb;
+    cm->ocspRespFreeCb = respFreeCb;
+    cm->ocspIOCtx = ioCbCtx;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_EnableOCSP(WOLFSSL* ssl, int options)
+{
+    WOLFSSL_ENTER("wolfSSL_EnableOCSP");
+    if (ssl)
+        return wolfSSL_CertManagerEnableOCSP(ssl->ctx->cm, options);
+    else
+        return BAD_FUNC_ARG;
+}
+
+int wolfSSL_DisableOCSP(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_DisableOCSP");
+    if (ssl)
+        return wolfSSL_CertManagerDisableOCSP(ssl->ctx->cm);
+    else
+        return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_EnableOCSPStapling(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_EnableOCSPStapling");
+    if (ssl)
+        return wolfSSL_CertManagerEnableOCSPStapling(ssl->ctx->cm);
+    else
+        return BAD_FUNC_ARG;
+}
+
+int wolfSSL_DisableOCSPStapling(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_DisableOCSPStapling");
+    if (ssl)
+        return wolfSSL_CertManagerDisableOCSPStapling(ssl->ctx->cm);
+    else
+        return BAD_FUNC_ARG;
+}
+
+int wolfSSL_SetOCSP_OverrideURL(WOLFSSL* ssl, const char* url)
+{
+    WOLFSSL_ENTER("wolfSSL_SetOCSP_OverrideURL");
+    if (ssl)
+        return wolfSSL_CertManagerSetOCSPOverrideURL(ssl->ctx->cm, url);
+    else
+        return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_SetOCSP_Cb(WOLFSSL* ssl,
+                        CbOCSPIO ioCb, CbOCSPRespFree respFreeCb, void* ioCbCtx)
+{
+    WOLFSSL_ENTER("wolfSSL_SetOCSP_Cb");
+    if (ssl) {
+        ssl->ocspIOCtx = ioCbCtx; /* use SSL specific ioCbCtx */
+        return wolfSSL_CertManagerSetOCSP_Cb(ssl->ctx->cm,
+                                             ioCb, respFreeCb, NULL);
+    }
+    else
+        return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_CTX_EnableOCSP(WOLFSSL_CTX* ctx, int options)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSP");
+    if (ctx)
+        return wolfSSL_CertManagerEnableOCSP(ctx->cm, options);
+    else
+        return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_CTX_DisableOCSP(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSP");
+    if (ctx)
+        return wolfSSL_CertManagerDisableOCSP(ctx->cm);
+    else
+        return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_CTX_SetOCSP_OverrideURL(WOLFSSL_CTX* ctx, const char* url)
+{
+    WOLFSSL_ENTER("wolfSSL_SetOCSP_OverrideURL");
+    if (ctx)
+        return wolfSSL_CertManagerSetOCSPOverrideURL(ctx->cm, url);
+    else
+        return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_CTX_SetOCSP_Cb(WOLFSSL_CTX* ctx, CbOCSPIO ioCb,
+                           CbOCSPRespFree respFreeCb, void* ioCbCtx)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_SetOCSP_Cb");
+    if (ctx)
+        return wolfSSL_CertManagerSetOCSP_Cb(ctx->cm, ioCb,
+                                             respFreeCb, ioCbCtx);
+    else
+        return BAD_FUNC_ARG;
+}
+
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+int wolfSSL_CTX_EnableOCSPStapling(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSPStapling");
+    if (ctx)
+        return wolfSSL_CertManagerEnableOCSPStapling(ctx->cm);
+    else
+        return BAD_FUNC_ARG;
+}
+
+int wolfSSL_CTX_DisableOCSPStapling(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSPStapling");
+    if (ctx)
+        return wolfSSL_CertManagerDisableOCSPStapling(ctx->cm);
+    else
+        return BAD_FUNC_ARG;
+}
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST || HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+
+#endif /* HAVE_OCSP */
+
+/* macro to get verify settings for AddCA */
+#define GET_VERIFY_SETTING_CTX(ctx) \
+    (ctx && ctx->verifyNone ? NO_VERIFY : VERIFY)
+#define GET_VERIFY_SETTING_SSL(ssl) \
+    (ssl && ssl->options.verifyNone ? NO_VERIFY : VERIFY)
+
+#ifndef NO_FILESYSTEM
+
+/* process a file with name fname into ctx of format and type
+   userChain specifies a user certificate chain to pass during handshake */
+int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type,
+                WOLFSSL* ssl, int userChain, WOLFSSL_CRL* crl, int verify)
+{
+#ifdef WOLFSSL_SMALL_STACK
+    byte   staticBuffer[1]; /* force heap usage */
+#else
+    byte   staticBuffer[FILE_BUFFER_SIZE];
+#endif
+    byte*  myBuffer = staticBuffer;
+    int    dynamic = 0;
+    int    ret;
+    long   sz = 0;
+    XFILE  file;
+    void*  heapHint = wolfSSL_CTX_GetHeap(ctx, ssl);
+    const char* header = NULL;
+    const char* footer = NULL;
+
+    (void)crl;
+    (void)heapHint;
+
+    if (fname == NULL) return WOLFSSL_BAD_FILE;
+
+    file = XFOPEN(fname, "rb");
+    if (file == XBADFILE) return WOLFSSL_BAD_FILE;
+    if (XFSEEK(file, 0, XSEEK_END) != 0) {
+        XFCLOSE(file);
+        return WOLFSSL_BAD_FILE;
+    }
+    sz = XFTELL(file);
+    XREWIND(file);
+
+    if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) {
+        WOLFSSL_MSG("ProcessFile file size error");
+        XFCLOSE(file);
+        return WOLFSSL_BAD_FILE;
+    }
+
+    if (sz > (long)sizeof(staticBuffer)) {
+        WOLFSSL_MSG("Getting dynamic buffer");
+        myBuffer = (byte*)XMALLOC(sz, heapHint, DYNAMIC_TYPE_FILE);
+        if (myBuffer == NULL) {
+            XFCLOSE(file);
+            return WOLFSSL_BAD_FILE;
+        }
+        dynamic = 1;
+    }
+
+    if ( (ret = (int)XFREAD(myBuffer, 1, sz, file)) != sz)
+        ret = WOLFSSL_BAD_FILE;
+    else {
+        /* Try to detect type by parsing cert header and footer */
+        if (type == DETECT_CERT_TYPE) {
+            if (wc_PemGetHeaderFooter(CA_TYPE, &header, &footer) == 0 &&
+               (XSTRNSTR((char*)myBuffer, header, (int)sz) != NULL)) {
+                type = CA_TYPE;
+            }
+#ifdef HAVE_CRL
+            else if (wc_PemGetHeaderFooter(CRL_TYPE, &header, &footer) == 0 &&
+                    (XSTRNSTR((char*)myBuffer, header, (int)sz) != NULL)) {
+                type = CRL_TYPE;
+            }
+#endif
+            else if (wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer) == 0 &&
+                    (XSTRNSTR((char*)myBuffer, header, (int)sz) != NULL)) {
+                type = CERT_TYPE;
+            }
+            else {
+                WOLFSSL_MSG("Failed to detect certificate type");
+                if (dynamic)
+                    XFREE(myBuffer, heapHint, DYNAMIC_TYPE_FILE);
+                XFCLOSE(file);
+                return WOLFSSL_BAD_CERTTYPE;
+            }
+        }
+        if ((type == CA_TYPE || type == TRUSTED_PEER_TYPE)
+                                          && format == WOLFSSL_FILETYPE_PEM) {
+            ret = ProcessChainBuffer(ctx, myBuffer, sz, format, type, ssl,
+                                     verify);
+        }
+#ifdef HAVE_CRL
+        else if (type == CRL_TYPE)
+            ret = BufferLoadCRL(crl, myBuffer, sz, format, verify);
+#endif
+        else
+            ret = ProcessBuffer(ctx, myBuffer, sz, format, type, ssl, NULL,
+                                userChain, verify);
+    }
+
+    XFCLOSE(file);
+    if (dynamic)
+        XFREE(myBuffer, heapHint, DYNAMIC_TYPE_FILE);
+
+    return ret;
+}
+
+/* loads file then loads each file in path, no c_rehash */
+int wolfSSL_CTX_load_verify_locations_ex(WOLFSSL_CTX* ctx, const char* file,
+                                     const char* path, word32 flags)
+{
+    int ret = WOLFSSL_SUCCESS;
+#ifndef NO_WOLFSSL_DIR
+    int fileRet;
+    int successCount = 0;
+    int failCount = 0;
+#endif
+    int verify;
+
+    WOLFSSL_MSG("wolfSSL_CTX_load_verify_locations_ex");
+
+    if (ctx == NULL || (file == NULL && path == NULL)) {
+        return WOLFSSL_FAILURE;
+    }
+
+    verify = GET_VERIFY_SETTING_CTX(ctx);
+    if (flags & WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY)
+        verify = VERIFY_SKIP_DATE;
+
+    if (file) {
+        ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, CA_TYPE, NULL, 0,
+                          NULL, verify);
+#ifndef NO_WOLFSSL_DIR
+        if (ret == WOLFSSL_SUCCESS)
+            successCount++;
+#endif
+    }
+
+    if (ret == WOLFSSL_SUCCESS && path) {
+#ifndef NO_WOLFSSL_DIR
+        char* name = NULL;
+    #ifdef WOLFSSL_SMALL_STACK
+        ReadDirCtx* readCtx;
+        readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), ctx->heap,
+                                                       DYNAMIC_TYPE_DIRCTX);
+        if (readCtx == NULL)
+            return MEMORY_E;
+    #else
+        ReadDirCtx readCtx[1];
+    #endif
+
+        /* try to load each regular file in path */
+        fileRet = wc_ReadDirFirst(readCtx, path, &name);
+        while (fileRet == 0 && name) {
+            WOLFSSL_MSG(name); /* log file name */
+            ret = ProcessFile(ctx, name, WOLFSSL_FILETYPE_PEM, CA_TYPE,
+                              NULL, 0, NULL, verify);
+            if (ret != WOLFSSL_SUCCESS) {
+                /* handle flags for ignoring errors, skipping expired certs or
+                   by PEM certificate header error */
+                if ( (flags & WOLFSSL_LOAD_FLAG_IGNORE_ERR) ||
+                    ((flags & WOLFSSL_LOAD_FLAG_PEM_CA_ONLY) &&
+                       (ret == ASN_NO_PEM_HEADER))) {
+                    /* Do not fail here if a certificate fails to load,
+                       continue to next file */
+                    ret = WOLFSSL_SUCCESS;
+                }
+                else {
+                    WOLFSSL_ERROR(ret);
+                    WOLFSSL_MSG("Load CA file failed, continuing");
+                    failCount++;
+                }
+            }
+            else {
+                successCount++;
+            }
+            fileRet = wc_ReadDirNext(readCtx, path, &name);
+        }
+        wc_ReadDirClose(readCtx);
+
+        /* pass directory read failure to response code */
+        if (fileRet != WC_READDIR_NOFILE) {
+            ret = fileRet;
+        }
+        /* report failure if no files were loaded or there were failures */
+        else if (successCount == 0 || failCount > 0) {
+            /* use existing error code if exists */
+            if (ret == WOLFSSL_SUCCESS)
+                ret = WOLFSSL_FAILURE;
+        }
+        else {
+            ret = WOLFSSL_SUCCESS;
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(readCtx, ctx->heap, DYNAMIC_TYPE_DIRCTX);
+    #endif
+#else
+        ret = NOT_COMPILED_IN;
+        (void)flags;
+#endif
+    }
+
+    return ret;
+}
+
+WOLFSSL_ABI
+int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX* ctx, const char* file,
+                                     const char* path)
+{
+    return wolfSSL_CTX_load_verify_locations_ex(ctx, file, path,
+        WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS);
+}
+
+
+#ifdef WOLFSSL_TRUST_PEER_CERT
+/* Used to specify a peer cert to match when connecting
+    ctx : the ctx structure to load in peer cert
+    file: the string name of cert file
+    type: type of format such as PEM/DER
+ */
+int wolfSSL_CTX_trust_peer_cert(WOLFSSL_CTX* ctx, const char* file, int type)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_trust_peer_cert");
+
+    if (ctx == NULL || file == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    return ProcessFile(ctx, file, type, TRUSTED_PEER_TYPE, NULL, 0, NULL,
+                       GET_VERIFY_SETTING_CTX(ctx));
+}
+#endif /* WOLFSSL_TRUST_PEER_CERT */
+
+
+/* Verify the certificate, WOLFSSL_SUCCESS for ok, < 0 for error */
+int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* fname,
+                             int format)
+{
+    int    ret = WOLFSSL_FATAL_ERROR;
+#ifdef WOLFSSL_SMALL_STACK
+    byte   staticBuffer[1]; /* force heap usage */
+#else
+    byte   staticBuffer[FILE_BUFFER_SIZE];
+#endif
+    byte*  myBuffer = staticBuffer;
+    int    dynamic = 0;
+    long   sz = 0;
+    XFILE  file = XFOPEN(fname, "rb");
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerVerify");
+
+    if (file == XBADFILE) return WOLFSSL_BAD_FILE;
+    if(XFSEEK(file, 0, XSEEK_END) != 0) {
+        XFCLOSE(file);
+        return WOLFSSL_BAD_FILE;
+    }
+    sz = XFTELL(file);
+    XREWIND(file);
+
+    if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) {
+        WOLFSSL_MSG("CertManagerVerify file size error");
+        XFCLOSE(file);
+        return WOLFSSL_BAD_FILE;
+    }
+
+    if (sz > (long)sizeof(staticBuffer)) {
+        WOLFSSL_MSG("Getting dynamic buffer");
+        myBuffer = (byte*) XMALLOC(sz, cm->heap, DYNAMIC_TYPE_FILE);
+        if (myBuffer == NULL) {
+            XFCLOSE(file);
+            return WOLFSSL_BAD_FILE;
+        }
+        dynamic = 1;
+    }
+
+    if ( (ret = (int)XFREAD(myBuffer, 1, sz, file)) != sz)
+        ret = WOLFSSL_BAD_FILE;
+    else
+        ret = wolfSSL_CertManagerVerifyBuffer(cm, myBuffer, sz, format);
+
+    XFCLOSE(file);
+    if (dynamic)
+        XFREE(myBuffer, cm->heap, DYNAMIC_TYPE_FILE);
+
+    return ret;
+}
+
+
+/* like load verify locations, 1 for success, < 0 for error */
+int wolfSSL_CertManagerLoadCA(WOLFSSL_CERT_MANAGER* cm, const char* file,
+                             const char* path)
+{
+    int ret = WOLFSSL_FATAL_ERROR;
+    WOLFSSL_CTX* tmp;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCA");
+
+    if (cm == NULL) {
+        WOLFSSL_MSG("No CertManager error");
+        return ret;
+    }
+    tmp = wolfSSL_CTX_new(cm_pick_method());
+
+    if (tmp == NULL) {
+        WOLFSSL_MSG("CTX new failed");
+        return ret;
+    }
+
+    /* for tmp use */
+    wolfSSL_CertManagerFree(tmp->cm);
+    tmp->cm = cm;
+
+    ret = wolfSSL_CTX_load_verify_locations(tmp, file, path);
+
+    /* don't lose our good one */
+    tmp->cm = NULL;
+    wolfSSL_CTX_free(tmp);
+
+    return ret;
+}
+
+#ifndef NO_CHECK_PRIVATE_KEY
+/* Check private against public in certificate for match
+ *
+ * ctx  WOLFSSL_CTX structure to check private key in
+ *
+ * Returns SSL_SUCCESS on good private key and SSL_FAILURE if miss matched. */
+int wolfSSL_CTX_check_private_key(const WOLFSSL_CTX* ctx)
+{
+#ifdef WOLFSSL_SMALL_STACK
+    DecodedCert* der = NULL;
+#else
+    DecodedCert  der[1];
+#endif
+    word32 size;
+    byte*  buff;
+    int    ret;
+
+    WOLFSSL_ENTER("wolfSSL_CTX_check_private_key");
+
+    if (ctx == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+#ifndef NO_CERTS
+#ifdef WOLFSSL_SMALL_STACK
+    der = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
+    if (der == NULL)
+        return MEMORY_E;
+#endif
+
+    size = ctx->certificate->length;
+    buff = ctx->certificate->buffer;
+    InitDecodedCert(der, buff, size, ctx->heap);
+    if (ParseCertRelative(der, CERT_TYPE, NO_VERIFY, NULL) != 0) {
+        FreeDecodedCert(der);
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(der, NULL, DYNAMIC_TYPE_DCERT);
+    #endif
+        return WOLFSSL_FAILURE;
+    }
+
+    size = ctx->privateKey->length;
+    buff = ctx->privateKey->buffer;
+    ret  = wc_CheckPrivateKey(buff, size, der);
+    FreeDecodedCert(der);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(der, NULL, DYNAMIC_TYPE_DCERT);
+#endif
+
+    if (ret == 1) {
+        return WOLFSSL_SUCCESS;
+    }
+    else {
+        return WOLFSSL_FAILURE;
+    }
+#else
+    WOLFSSL_MSG("NO_CERTS is defined, can not check private key");
+    return WOLFSSL_FAILURE;
+#endif
+}
+#endif /* !NO_CHECK_PRIVATE_KEY */
+
+
+#ifdef HAVE_CRL
+
+/* check CRL if enabled, WOLFSSL_SUCCESS  */
+int wolfSSL_CertManagerCheckCRL(WOLFSSL_CERT_MANAGER* cm, byte* der, int sz)
+{
+    int ret = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    DecodedCert* cert = NULL;
+#else
+    DecodedCert  cert[1];
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerCheckCRL");
+
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    if (cm->crlEnabled == 0)
+        return WOLFSSL_SUCCESS;
+
+#ifdef WOLFSSL_SMALL_STACK
+    cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
+    if (cert == NULL)
+        return MEMORY_E;
+#endif
+
+    InitDecodedCert(cert, der, sz, NULL);
+
+    if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_CRL, cm)) != 0) {
+        WOLFSSL_MSG("ParseCert failed");
+    }
+    else if ((ret = CheckCertCRL(cm->crl, cert)) != 0) {
+        WOLFSSL_MSG("CheckCertCRL failed");
+    }
+
+    FreeDecodedCert(cert);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
+#endif
+
+    return ret == 0 ? WOLFSSL_SUCCESS : ret;
+}
+
+
+int wolfSSL_CertManagerSetCRL_Cb(WOLFSSL_CERT_MANAGER* cm, CbMissingCRL cb)
+{
+    WOLFSSL_ENTER("wolfSSL_CertManagerSetCRL_Cb");
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    cm->cbMissingCRL = cb;
+
+    return WOLFSSL_SUCCESS;
+}
+
+#ifdef HAVE_CRL_IO
+int wolfSSL_CertManagerSetCRL_IOCb(WOLFSSL_CERT_MANAGER* cm, CbCrlIO cb)
+{
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    cm->crl->crlIOCb = cb;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif
+
+int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER* cm, const char* path,
+                              int type, int monitor)
+{
+    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRL");
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    if (cm->crl == NULL) {
+        if (wolfSSL_CertManagerEnableCRL(cm, 0) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("Enable CRL failed");
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+
+    return LoadCRL(cm->crl, path, type, monitor);
+}
+
+int wolfSSL_EnableCRL(WOLFSSL* ssl, int options)
+{
+    WOLFSSL_ENTER("wolfSSL_EnableCRL");
+    if (ssl)
+        return wolfSSL_CertManagerEnableCRL(ssl->ctx->cm, options);
+    else
+        return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_DisableCRL(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_DisableCRL");
+    if (ssl)
+        return wolfSSL_CertManagerDisableCRL(ssl->ctx->cm);
+    else
+        return BAD_FUNC_ARG;
+}
+
+int wolfSSL_LoadCRL(WOLFSSL* ssl, const char* path, int type, int monitor)
+{
+    WOLFSSL_ENTER("wolfSSL_LoadCRL");
+    if (ssl)
+        return wolfSSL_CertManagerLoadCRL(ssl->ctx->cm, path, type, monitor);
+    else
+        return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_SetCRL_Cb(WOLFSSL* ssl, CbMissingCRL cb)
+{
+    WOLFSSL_ENTER("wolfSSL_SetCRL_Cb");
+    if (ssl)
+        return wolfSSL_CertManagerSetCRL_Cb(ssl->ctx->cm, cb);
+    else
+        return BAD_FUNC_ARG;
+}
+
+#ifdef HAVE_CRL_IO
+int wolfSSL_SetCRL_IOCb(WOLFSSL* ssl, CbCrlIO cb)
+{
+    WOLFSSL_ENTER("wolfSSL_SetCRL_Cb");
+    if (ssl)
+        return wolfSSL_CertManagerSetCRL_IOCb(ssl->ctx->cm, cb);
+    else
+        return BAD_FUNC_ARG;
+}
+#endif
+
+int wolfSSL_CTX_EnableCRL(WOLFSSL_CTX* ctx, int options)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_EnableCRL");
+    if (ctx)
+        return wolfSSL_CertManagerEnableCRL(ctx->cm, options);
+    else
+        return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_CTX_DisableCRL(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_DisableCRL");
+    if (ctx)
+        return wolfSSL_CertManagerDisableCRL(ctx->cm);
+    else
+        return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_CTX_LoadCRL(WOLFSSL_CTX* ctx, const char* path,
+                        int type, int monitor)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_LoadCRL");
+    if (ctx)
+        return wolfSSL_CertManagerLoadCRL(ctx->cm, path, type, monitor);
+    else
+        return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_CTX_SetCRL_Cb(WOLFSSL_CTX* ctx, CbMissingCRL cb)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_SetCRL_Cb");
+    if (ctx)
+        return wolfSSL_CertManagerSetCRL_Cb(ctx->cm, cb);
+    else
+        return BAD_FUNC_ARG;
+}
+
+#ifdef HAVE_CRL_IO
+int wolfSSL_CTX_SetCRL_IOCb(WOLFSSL_CTX* ctx, CbCrlIO cb)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_SetCRL_IOCb");
+    if (ctx)
+        return wolfSSL_CertManagerSetCRL_IOCb(ctx->cm, cb);
+    else
+        return BAD_FUNC_ARG;
+}
+#endif
+
+
+#endif /* HAVE_CRL */
+
+
+#ifdef WOLFSSL_DER_LOAD
+
+/* Add format parameter to allow DER load of CA files */
+int wolfSSL_CTX_der_load_verify_locations(WOLFSSL_CTX* ctx, const char* file,
+                                          int format)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_der_load_verify_locations");
+    if (ctx == NULL || file == NULL)
+        return WOLFSSL_FAILURE;
+
+    if (ProcessFile(ctx, file, format, CA_TYPE, NULL, 0, NULL,
+                    GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) {
+        return WOLFSSL_SUCCESS;
+    }
+
+    return WOLFSSL_FAILURE;
+}
+
+#endif /* WOLFSSL_DER_LOAD */
+
+
+
+WOLFSSL_ABI
+int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX* ctx, const char* file,
+                                     int format)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_file");
+
+    if (ProcessFile(ctx, file, format, CERT_TYPE, NULL, 0, NULL,
+                    GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) {
+        return WOLFSSL_SUCCESS;
+    }
+
+    return WOLFSSL_FAILURE;
+}
+
+
+WOLFSSL_ABI
+int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX* ctx, const char* file,
+                                    int format)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_file");
+
+    if (ProcessFile(ctx, file, format, PRIVATEKEY_TYPE, NULL, 0, NULL,
+                    GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) {
+        return WOLFSSL_SUCCESS;
+    }
+
+    return WOLFSSL_FAILURE;
+}
+
+
+/* Sets the max chain depth when verifying a certificate chain. Default depth
+ * is set to MAX_CHAIN_DEPTH.
+ *
+ * ctx   WOLFSSL_CTX structure to set depth in
+ * depth max depth
+ */
+void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx, int depth) {
+    WOLFSSL_ENTER("wolfSSL_CTX_set_verify_depth");
+
+    if (ctx == NULL || depth < 0 || depth > MAX_CHAIN_DEPTH) {
+        WOLFSSL_MSG("Bad depth argument, too large or less than 0");
+        return;
+    }
+
+    ctx->verifyDepth = (byte)depth;
+}
+
+
+/* get cert chaining depth using ssl struct */
+long wolfSSL_get_verify_depth(WOLFSSL* ssl)
+{
+    if(ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+#ifndef OPENSSL_EXTRA
+    return MAX_CHAIN_DEPTH;
+#else
+    return ssl->options.verifyDepth;
+#endif
+}
+
+
+/* get cert chaining depth using ctx struct */
+long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx)
+{
+    if (ctx == NULL) {
+        return BAD_FUNC_ARG;
+    }
+#ifndef OPENSSL_EXTRA
+    return MAX_CHAIN_DEPTH;
+#else
+    return ctx->verifyDepth;
+#endif
+}
+
+
+WOLFSSL_ABI
+int wolfSSL_CTX_use_certificate_chain_file(WOLFSSL_CTX* ctx, const char* file)
+{
+    /* process up to MAX_CHAIN_DEPTH plus subject cert */
+    WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file");
+
+    if (ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, CERT_TYPE, NULL, 1, NULL,
+                    GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) {
+        return WOLFSSL_SUCCESS;
+    }
+
+   return WOLFSSL_FAILURE;
+}
+
+
+int wolfSSL_CTX_use_certificate_chain_file_format(WOLFSSL_CTX* ctx,
+                                                  const char* file, int format)
+{
+    /* process up to MAX_CHAIN_DEPTH plus subject cert */
+    WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file_format");
+
+    if (ProcessFile(ctx, file, format, CERT_TYPE, NULL, 1, NULL,
+                    GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) {
+        return WOLFSSL_SUCCESS;
+    }
+
+   return WOLFSSL_FAILURE;
+}
+
+
+#ifndef NO_DH
+
+/* server Diffie-Hellman parameters */
+static int wolfSSL_SetTmpDH_file_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
+                                        const char* fname, int format)
+{
+#ifdef WOLFSSL_SMALL_STACK
+    byte   staticBuffer[1]; /* force heap usage */
+#else
+    byte   staticBuffer[FILE_BUFFER_SIZE];
+#endif
+    byte*  myBuffer = staticBuffer;
+    int    dynamic = 0;
+    int    ret;
+    long   sz = 0;
+    XFILE  file;
+
+    if (ctx == NULL || fname == NULL)
+        return BAD_FUNC_ARG;
+
+    file = XFOPEN(fname, "rb");
+    if (file == XBADFILE) return WOLFSSL_BAD_FILE;
+    if(XFSEEK(file, 0, XSEEK_END) != 0) {
+        XFCLOSE(file);
+        return WOLFSSL_BAD_FILE;
+    }
+    sz = XFTELL(file);
+    XREWIND(file);
+
+    if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) {
+        WOLFSSL_MSG("SetTmpDH file size error");
+        XFCLOSE(file);
+        return WOLFSSL_BAD_FILE;
+    }
+
+    if (sz > (long)sizeof(staticBuffer)) {
+        WOLFSSL_MSG("Getting dynamic buffer");
+        myBuffer = (byte*) XMALLOC(sz, ctx->heap, DYNAMIC_TYPE_FILE);
+        if (myBuffer == NULL) {
+            XFCLOSE(file);
+            return WOLFSSL_BAD_FILE;
+        }
+        dynamic = 1;
+    }
+
+    if ( (ret = (int)XFREAD(myBuffer, 1, sz, file)) != sz)
+        ret = WOLFSSL_BAD_FILE;
+    else {
+        if (ssl)
+            ret = wolfSSL_SetTmpDH_buffer(ssl, myBuffer, sz, format);
+        else
+            ret = wolfSSL_CTX_SetTmpDH_buffer(ctx, myBuffer, sz, format);
+    }
+
+    XFCLOSE(file);
+    if (dynamic)
+        XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE);
+
+    return ret;
+}
+
+/* server Diffie-Hellman parameters */
+int wolfSSL_SetTmpDH_file(WOLFSSL* ssl, const char* fname, int format)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    return wolfSSL_SetTmpDH_file_wrapper(ssl->ctx, ssl, fname, format);
+}
+
+
+/* server Diffie-Hellman parameters */
+int wolfSSL_CTX_SetTmpDH_file(WOLFSSL_CTX* ctx, const char* fname, int format)
+{
+    return wolfSSL_SetTmpDH_file_wrapper(ctx, NULL, fname, format);
+}
+
+#endif /* NO_DH */
+
+#endif /* NO_FILESYSTEM */
+
+#ifdef OPENSSL_EXTRA
+/* put SSL type in extra for now, not very common */
+
+/* Converts a DER format key read from "bio" to a PKCS8 structure.
+ *
+ * bio  input bio to read DER from
+ * pkey If not NULL then this pointer will be overwritten with a new PKCS8
+ *      structure.
+ *
+ * returns a WOLFSSL_PKCS8_PRIV_KEY_INFO pointer on success and NULL in fail
+ *         case.
+ */
+WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY_bio(WOLFSSL_BIO* bio,
+        WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey)
+{
+    WOLFSSL_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL;
+#ifdef WOLFSSL_PEM_TO_DER
+    unsigned char* mem = NULL;
+    int memSz;
+    int keySz;
+    word32 algId;
+
+    WOLFSSL_MSG("wolfSSL_d2i_PKCS8_PKEY_bio()");
+
+    if (bio == NULL) {
+        return NULL;
+    }
+
+    if ((memSz = wolfSSL_BIO_get_mem_data(bio, &mem)) < 0) {
+        return NULL;
+    }
+
+    if ((keySz = wc_KeyPemToDer(mem, memSz, mem, memSz, NULL)) < 0) {
+        WOLFSSL_MSG("Not PEM format");
+        keySz = memSz;
+        if ((keySz = ToTraditional_ex((byte*)mem, (word32)keySz, &algId)) < 0) {
+            return NULL;
+        }
+    }
+
+    pkcs8 = wolfSSL_EVP_PKEY_new();
+    if (pkcs8 == NULL) {
+        return NULL;
+    }
+
+    pkcs8->pkey.ptr = (char*)XMALLOC(keySz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+    if (pkcs8->pkey.ptr == NULL) {
+        wolfSSL_EVP_PKEY_free(pkcs8);
+        return NULL;
+    }
+    XMEMCPY(pkcs8->pkey.ptr, mem, keySz);
+    pkcs8->pkey_sz = keySz;
+
+    if (pkey != NULL) {
+        *pkey = pkcs8;
+    }
+#else
+    (void)bio;
+    (void)pkey;
+#endif /* WOLFSSL_PEM_TO_DER */
+
+    return pkcs8;
+}
+
+
+/* expecting DER format public key
+ *
+ * bio  input bio to read DER from
+ * out  If not NULL then this pointer will be overwritten with a new
+ * WOLFSSL_EVP_PKEY pointer
+ *
+ * returns a WOLFSSL_EVP_PKEY pointer on success and NULL in fail case.
+ */
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio,
+                                         WOLFSSL_EVP_PKEY** out)
+{
+    unsigned char* mem;
+    long memSz;
+    WOLFSSL_EVP_PKEY* pkey = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY_bio()");
+
+    if (bio == NULL) {
+        return NULL;
+    }
+    (void)out;
+
+    memSz = wolfSSL_BIO_pending(bio);
+    if (memSz <= 0) {
+        return NULL;
+    }
+
+    mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (mem == NULL) {
+        return NULL;
+    }
+
+    if (wolfSSL_BIO_read(bio, mem, (int)memSz) == memSz) {
+        pkey = wolfSSL_d2i_PUBKEY(NULL, (const unsigned char**)&mem, memSz);
+        if (out != NULL && pkey != NULL) {
+            *out = pkey;
+        }
+    }
+
+    XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    return pkey;
+}
+
+
+
+/* Converts a DER encoded public key to a WOLFSSL_EVP_PKEY structure.
+ *
+ * out  pointer to new WOLFSSL_EVP_PKEY structure. Can be NULL
+ * in   DER buffer to convert
+ * inSz size of in buffer
+ *
+ * returns a pointer to a new WOLFSSL_EVP_PKEY structure on success and NULL
+ *         on fail
+ */
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY(WOLFSSL_EVP_PKEY** out,
+                                     const unsigned char** in, long inSz)
+{
+    WOLFSSL_EVP_PKEY* pkey = NULL;
+    const unsigned char* mem;
+    long memSz = inSz;
+
+    WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY");
+
+    if (in == NULL || inSz < 0) {
+        WOLFSSL_MSG("Bad argument");
+        return NULL;
+    }
+    mem = *in;
+
+    #if !defined(NO_RSA)
+    {
+        RsaKey rsa;
+        word32 keyIdx = 0;
+
+        /* test if RSA key */
+        if (wc_InitRsaKey(&rsa, NULL) == 0 &&
+            wc_RsaPublicKeyDecode(mem, &keyIdx, &rsa, (word32)memSz) == 0) {
+            wc_FreeRsaKey(&rsa);
+            pkey = wolfSSL_EVP_PKEY_new();
+            if (pkey != NULL) {
+                pkey->pkey_sz = keyIdx;
+                pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL,
+                        DYNAMIC_TYPE_PUBLIC_KEY);
+                if (pkey->pkey.ptr == NULL) {
+                    wolfSSL_EVP_PKEY_free(pkey);
+                    return NULL;
+                }
+                XMEMCPY(pkey->pkey.ptr, mem, keyIdx);
+                pkey->type = EVP_PKEY_RSA;
+                if (out != NULL) {
+                    *out = pkey;
+                }
+
+                pkey->ownRsa = 1;
+                pkey->rsa = wolfSSL_RSA_new();
+                if (pkey->rsa == NULL) {
+                    wolfSSL_EVP_PKEY_free(pkey);
+                    return NULL;
+                }
+
+                if (wolfSSL_RSA_LoadDer_ex(pkey->rsa,
+                            (const unsigned char*)pkey->pkey.ptr,
+                            pkey->pkey_sz, WOLFSSL_RSA_LOAD_PUBLIC) != 1) {
+                    wolfSSL_EVP_PKEY_free(pkey);
+                    return NULL;
+                }
+
+                return pkey;
+            }
+        }
+        wc_FreeRsaKey(&rsa);
+    }
+    #endif /* NO_RSA */
+
+    #ifdef HAVE_ECC
+    {
+        word32  keyIdx = 0;
+        ecc_key ecc;
+
+        if (wc_ecc_init(&ecc) == 0 &&
+            wc_EccPublicKeyDecode(mem, &keyIdx, &ecc, (word32)memSz) == 0) {
+            wc_ecc_free(&ecc);
+            pkey = wolfSSL_EVP_PKEY_new();
+            if (pkey != NULL) {
+                pkey->pkey_sz = keyIdx;
+                pkey->pkey.ptr = (char*)XMALLOC(keyIdx, NULL,
+                        DYNAMIC_TYPE_PUBLIC_KEY);
+                if (pkey->pkey.ptr == NULL) {
+                    wolfSSL_EVP_PKEY_free(pkey);
+                    return NULL;
+                }
+                XMEMCPY(pkey->pkey.ptr, mem, keyIdx);
+                pkey->type = EVP_PKEY_EC;
+                if (out != NULL) {
+                    *out = pkey;
+                }
+
+                pkey->ownEcc = 1;
+                pkey->ecc = wolfSSL_EC_KEY_new();
+                if (pkey->ecc == NULL) {
+                    wolfSSL_EVP_PKEY_free(pkey);
+                    return NULL;
+                }
+
+                if (wolfSSL_EC_KEY_LoadDer_ex(pkey->ecc,
+                            (const unsigned char*)pkey->pkey.ptr,
+                            pkey->pkey_sz, WOLFSSL_EC_KEY_LOAD_PUBLIC) != 1) {
+                    wolfSSL_EVP_PKEY_free(pkey);
+                    return NULL;
+                }
+
+                return pkey;
+            }
+        }
+        wc_ecc_free(&ecc);
+    }
+    #endif /* HAVE_ECC */
+
+    #if !defined(NO_DSA)
+    {
+        DsaKey dsa;
+        word32 keyIdx = 0;
+
+        /* test if DSA key */
+        if (wc_InitDsaKey(&dsa) == 0 &&
+            wc_DsaPublicKeyDecode(mem, &keyIdx, &dsa, (word32)memSz) == 0) {
+            wc_FreeDsaKey(&dsa);
+            pkey = wolfSSL_EVP_PKEY_new();
+
+            if (pkey != NULL) {
+                pkey->pkey_sz = keyIdx;
+                pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL,
+                        DYNAMIC_TYPE_PUBLIC_KEY);
+                if (pkey->pkey.ptr == NULL) {
+                    wolfSSL_EVP_PKEY_free(pkey);
+                    return NULL;
+                }
+                XMEMCPY(pkey->pkey.ptr, mem, keyIdx);
+                pkey->type = EVP_PKEY_DSA;
+                if (out != NULL) {
+                    *out = pkey;
+                }
+
+                pkey->ownDsa = 1;
+                pkey->dsa = wolfSSL_DSA_new();
+                if (pkey->dsa == NULL) {
+                    wolfSSL_EVP_PKEY_free(pkey);
+                    return NULL;
+                }
+
+
+                if (wolfSSL_DSA_LoadDer_ex(pkey->dsa,
+                            (const unsigned char*)pkey->pkey.ptr,
+                            pkey->pkey_sz, WOLFSSL_DSA_LOAD_PUBLIC) != 1) {
+                    wolfSSL_EVP_PKEY_free(pkey);
+                    return NULL;
+                }
+
+                return pkey;
+            }
+        }
+        wc_FreeDsaKey(&dsa);
+    }
+    #endif /* NO_DSA */
+
+    #if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
+    {
+        DhKey dh;
+        word32 keyIdx = 0;
+
+        /* test if DH key */
+        if (wc_InitDhKey(&dh) == 0 &&
+            wc_DhKeyDecode(mem, &keyIdx, &dh, (word32)memSz) == 0) {
+            wc_FreeDhKey(&dh);
+            pkey = wolfSSL_EVP_PKEY_new();
+
+            if (pkey != NULL) {
+                pkey->pkey_sz = (int)memSz;
+                pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL,
+                        DYNAMIC_TYPE_PUBLIC_KEY);
+                if (pkey->pkey.ptr == NULL) {
+                    wolfSSL_EVP_PKEY_free(pkey);
+                    return NULL;
+                }
+                XMEMCPY(pkey->pkey.ptr, mem, memSz);
+                pkey->type = EVP_PKEY_DH;
+                if (out != NULL) {
+                    *out = pkey;
+                }
+
+                pkey->ownDh = 1;
+                pkey->dh = wolfSSL_DH_new();
+                if (pkey->dh == NULL) {
+                    wolfSSL_EVP_PKEY_free(pkey);
+                    return NULL;
+                }
+
+                if (wolfSSL_DH_LoadDer(pkey->dh,
+                            (const unsigned char*)pkey->pkey.ptr,
+                            pkey->pkey_sz) != WOLFSSL_SUCCESS) {
+                    wolfSSL_EVP_PKEY_free(pkey);
+                    return NULL;
+                }
+
+                return pkey;
+            }
+        }
+        wc_FreeDhKey(&dh);
+    }
+    #endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */
+
+    return pkey;
+}
+
+
+/* Reads in a DER format key. If PKCS8 headers are found they are stripped off.
+ *
+ * type  type of key
+ * out   newly created WOLFSSL_EVP_PKEY structure
+ * in    pointer to input key DER
+ * inSz  size of in buffer
+ *
+ * On success a non null pointer is returned and the pointer in is advanced the
+ * same number of bytes read.
+ */
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out,
+        const unsigned char **in, long inSz)
+{
+    WOLFSSL_EVP_PKEY* local;
+    word32 idx = 0;
+    int    ret;
+    word32 algId;
+
+    WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey");
+
+    if (in == NULL || inSz < 0) {
+        WOLFSSL_MSG("Bad argument");
+        return NULL;
+    }
+
+    /* Check if input buffer has PKCS8 header. In the case that it does not
+     * have a PKCS8 header then do not error out. */
+    if ((ret = ToTraditionalInline_ex((const byte*)(*in), &idx, (word32)inSz,
+                                                                 &algId)) > 0) {
+        WOLFSSL_MSG("Found and removed PKCS8 header");
+    }
+    else {
+        if (ret != ASN_PARSE_E) {
+            WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 header");
+            return NULL;
+        }
+    }
+
+    if (out != NULL && *out != NULL) {
+        wolfSSL_EVP_PKEY_free(*out);
+        *out = NULL;
+    }
+    local = wolfSSL_EVP_PKEY_new();
+    if (local == NULL) {
+        return NULL;
+    }
+
+    /* sanity check on idx before use */
+    if ((int)idx > inSz) {
+        WOLFSSL_MSG("Issue with index pointer");
+        wolfSSL_EVP_PKEY_free(local);
+        local = NULL;
+        return NULL;
+    }
+
+    local->type     = type;
+    local->pkey_sz  = (int)inSz - idx;
+    local->pkey.ptr = (char*)XMALLOC(inSz - idx, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+    if (local->pkey.ptr == NULL) {
+        wolfSSL_EVP_PKEY_free(local);
+        local = NULL;
+        return NULL;
+    }
+    else {
+        XMEMCPY(local->pkey.ptr, *in + idx, inSz - idx);
+    }
+
+    switch (type) {
+#ifndef NO_RSA
+        case EVP_PKEY_RSA:
+            local->ownRsa = 1;
+            local->rsa = wolfSSL_RSA_new();
+            if (local->rsa == NULL) {
+                wolfSSL_EVP_PKEY_free(local);
+                return NULL;
+            }
+            if (wolfSSL_RSA_LoadDer_ex(local->rsa,
+                      (const unsigned char*)local->pkey.ptr, local->pkey_sz,
+                      WOLFSSL_RSA_LOAD_PRIVATE) != SSL_SUCCESS) {
+                wolfSSL_EVP_PKEY_free(local);
+                return NULL;
+            }
+            break;
+#endif /* NO_RSA */
+#ifdef HAVE_ECC
+        case EVP_PKEY_EC:
+            local->ownEcc = 1;
+            local->ecc = wolfSSL_EC_KEY_new();
+            if (local->ecc == NULL) {
+                wolfSSL_EVP_PKEY_free(local);
+                return NULL;
+            }
+            if (wolfSSL_EC_KEY_LoadDer(local->ecc,
+                      (const unsigned char*)local->pkey.ptr, local->pkey_sz)
+                      != SSL_SUCCESS) {
+                wolfSSL_EVP_PKEY_free(local);
+                return NULL;
+            }
+            break;
+#endif /* HAVE_ECC */
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+#ifndef NO_DSA
+        case EVP_PKEY_DSA:
+            local->ownDsa = 1;
+            local->dsa = wolfSSL_DSA_new();
+            if (local->dsa == NULL) {
+                wolfSSL_EVP_PKEY_free(local);
+                return NULL;
+            }
+            if (wolfSSL_DSA_LoadDer(local->dsa,
+                    (const unsigned char*)local->pkey.ptr, local->pkey_sz)
+                    != SSL_SUCCESS) {
+                wolfSSL_EVP_PKEY_free(local);
+                return NULL;
+            }
+            break;
+#endif /* NO_DSA */
+#ifndef NO_DH
+        case EVP_PKEY_DH:
+            local->ownDh = 1;
+            local->dh = wolfSSL_DH_new();
+            if (local->dh == NULL) {
+                wolfSSL_EVP_PKEY_free(local);
+                return NULL;
+            }
+            if (wolfSSL_DH_LoadDer(local->dh,
+                      (const unsigned char*)local->pkey.ptr, local->pkey_sz)
+                      != SSL_SUCCESS) {
+                wolfSSL_EVP_PKEY_free(local);
+                return NULL;
+            }
+            break;
+#endif /* HAVE_DH */
+#endif /* WOLFSSL_QT || OPENSSL_ALL */
+        default:
+            WOLFSSL_MSG("Unsupported key type");
+            wolfSSL_EVP_PKEY_free(local);
+            return NULL;
+    }
+
+    /* advance pointer with success */
+    if (local != NULL) {
+        if ((idx + local->pkey_sz) <= (word32)inSz) {
+            *in = *in + idx + local->pkey_sz;
+        }
+
+        if (out != NULL) {
+            *out = local;
+        }
+    }
+
+    return local;
+}
+
+#ifndef NO_CERTS
+
+int wolfSSL_check_private_key(const WOLFSSL* ssl)
+{
+    DecodedCert der;
+    word32 size;
+    byte*  buff;
+    int    ret;
+
+    if (ssl == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    size = ssl->buffers.certificate->length;
+    buff = ssl->buffers.certificate->buffer;
+    InitDecodedCert(&der, buff, size, ssl->heap);
+#ifdef HAVE_PK_CALLBACKS
+    ret = InitSigPkCb((WOLFSSL*)ssl, &der.sigCtx);
+    if (ret != 0) {
+        FreeDecodedCert(&der);
+        return ret;
+    }
+#endif
+
+    if (ParseCertRelative(&der, CERT_TYPE, NO_VERIFY, NULL) != 0) {
+        FreeDecodedCert(&der);
+        return WOLFSSL_FAILURE;
+    }
+
+    size = ssl->buffers.key->length;
+    buff = ssl->buffers.key->buffer;
+    ret  = wc_CheckPrivateKey(buff, size, &der);
+    FreeDecodedCert(&der);
+    return ret;
+}
+
+#if defined(OPENSSL_ALL)
+/* Returns the number of X509V3 extensions in X509 object, or 0 on failure */
+int wolfSSL_X509_get_ext_count(const WOLFSSL_X509* passedCert)
+{
+    int extCount = 0;
+    int length = 0;
+    int outSz = 0;
+    const byte* rawCert;
+    int sz = 0;
+    word32 idx = 0;
+    DecodedCert cert;
+    const byte* input;
+
+    WOLFSSL_ENTER("wolfSSL_X509_get_ext_count()");
+    if (passedCert == NULL) {
+        WOLFSSL_MSG("\tNot passed a certificate");
+        return WOLFSSL_FAILURE;
+    }
+
+    rawCert = wolfSSL_X509_get_der((WOLFSSL_X509*)passedCert, &outSz);
+    if (rawCert == NULL) {
+        WOLFSSL_MSG("\tpassedCert has no internal DerBuffer set.");
+        return WOLFSSL_FAILURE;
+    }
+    InitDecodedCert(&cert, rawCert, (word32)outSz, 0);
+
+    if (ParseCert(&cert, CA_TYPE, NO_VERIFY, NULL) < 0) {
+        WOLFSSL_MSG("\tCertificate parsing failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    input = cert.extensions;
+    sz = cert.extensionsSz;
+
+    if (input == NULL || sz == 0) {
+        WOLFSSL_MSG("\tsz or input NULL error");
+        FreeDecodedCert(&cert);
+        return WOLFSSL_FAILURE;
+    }
+
+    if (input[idx++] != ASN_EXTENSIONS) {
+        WOLFSSL_MSG("\tfail: should be an EXTENSIONS");
+        FreeDecodedCert(&cert);
+        return WOLFSSL_FAILURE;
+    }
+
+    if (GetLength(input, &idx, &length, sz) < 0) {
+        WOLFSSL_MSG("\tfail: invalid length");
+        FreeDecodedCert(&cert);
+        return WOLFSSL_FAILURE;
+    }
+
+    if (GetSequence(input, &idx, &length, sz) < 0) {
+        WOLFSSL_MSG("\tfail: should be a SEQUENCE (1)");
+        FreeDecodedCert(&cert);
+        return WOLFSSL_FAILURE;
+    }
+
+    while (idx < (word32)sz) {
+        if (GetSequence(input, &idx, &length, sz) < 0) {
+            WOLFSSL_MSG("\tfail: should be a SEQUENCE");
+            FreeDecodedCert(&cert);
+            return WOLFSSL_FAILURE;
+        }
+        idx += length;
+        extCount++;
+    }
+    FreeDecodedCert(&cert);
+    return extCount;
+}
+
+/* Creates and returns pointer to a new X509_EXTENSION object in memory */
+WOLFSSL_X509_EXTENSION* wolfSSL_X509_EXTENSION_new(void)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_new");
+
+    WOLFSSL_X509_EXTENSION* newExt;
+    newExt = (WOLFSSL_X509_EXTENSION*)XMALLOC(sizeof(WOLFSSL_X509_EXTENSION),
+              NULL, DYNAMIC_TYPE_X509_EXT);
+    if (newExt == NULL)
+        return NULL;
+    XMEMSET(newExt, 0, sizeof(WOLFSSL_X509_EXTENSION));
+
+    return newExt;
+}
+
+void wolfSSL_X509_EXTENSION_free(WOLFSSL_X509_EXTENSION* x)
+{
+    WOLFSSL_ASN1_STRING asn1;
+    WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_free");
+    if (x == NULL)
+        return;
+
+    if (x->obj != NULL)
+        wolfSSL_ASN1_OBJECT_free(x->obj);
+
+    asn1 = x->value;
+    if (asn1.length > 0 && asn1.data != NULL && asn1.isDynamic)
+        XFREE(asn1.data, NULL, DYNAMIC_TYPE_OPENSSL);
+
+    wolfSSL_sk_free(x->ext_sk);
+
+    XFREE(x, NULL, DYNAMIC_TYPE_X509_EXT);
+}
+
+/* Creates and returns a new WOLFSSL_X509_EXTENSION stack. */
+WOLFSSL_STACK* wolfSSL_sk_new_x509_ext(void)
+{
+    WOLFSSL_STACK* sk;
+    WOLFSSL_ENTER("wolfSSL_sk_new_x509_ext");
+
+    sk = wolfSSL_sk_new_null();
+    if (sk) {
+        sk->type = STACK_TYPE_X509_EXT;
+    }
+    return sk;
+}
+
+/* return 1 on success 0 on fail */
+int wolfSSL_sk_X509_EXTENSION_push(WOLFSSL_STACK* sk,WOLFSSL_X509_EXTENSION* ext)
+{
+    WOLFSSL_STACK* node;
+
+    WOLFSSL_ENTER("wolfSSL_sk_X509_EXTENSION_push");
+
+    if (sk == NULL || ext == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* no previous values in stack */
+    if (sk->data.ext == NULL) {
+        sk->data.ext = ext;
+        sk->num += 1;
+        return WOLFSSL_SUCCESS;
+    }
+
+    /* stack already has value(s) create a new node and add more */
+    node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+                                                             DYNAMIC_TYPE_X509);
+    if (node == NULL) {
+        WOLFSSL_MSG("Memory error");
+        return WOLFSSL_FAILURE;
+    }
+    XMEMSET(node, 0, sizeof(WOLFSSL_STACK));
+
+    /* push new obj onto head of stack */
+    node->data.ext  = sk->data.ext;
+    node->next      = sk->next;
+    node->type      = sk->type;
+    sk->next        = node;
+    sk->data.ext    = ext;
+    sk->num        += 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* Free the structure for X509_EXTENSION stack
+ *
+ * sk  stack to free nodes in
+ */
+void wolfSSL_sk_X509_EXTENSION_free(WOLFSSL_STACK* sk)
+{
+    WOLFSSL_STACK* node;
+
+    WOLFSSL_ENTER("wolfSSL_sk_X509_EXTENSION_free");
+
+    if (sk == NULL) {
+        return;
+    }
+
+    /* parse through stack freeing each node */
+    node = sk->next;
+    while ((node != NULL) && (sk->num > 1)) {
+        WOLFSSL_STACK* tmp = node;
+        node = node->next;
+
+        wolfSSL_X509_EXTENSION_free(tmp->data.ext);
+        XFREE(tmp, NULL, DYNAMIC_TYPE_X509);
+        sk->num -= 1;
+    }
+
+    /* free head of stack */
+    if (sk->num == 1) {
+        wolfSSL_X509_EXTENSION_free(sk->data.ext);
+    }
+    XFREE(sk, NULL, DYNAMIC_TYPE_X509);
+}
+
+int wolfSSL_ASN1_BIT_STRING_set_bit(WOLFSSL_ASN1_BIT_STRING* str, int pos,
+    int val)
+{
+    int bytes_cnt, bit;
+    byte* temp;
+
+    if (!str || (val != 0 && val != 1) || pos < 0) {
+        return WOLFSSL_FAILURE;
+    }
+
+    bytes_cnt = pos/8;
+    bit = 1<<(7-(pos%8));
+
+    if (bytes_cnt+1 > str->length) {
+        if (!(temp = (byte*)XREALLOC(str->data, bytes_cnt+1, NULL,
+                DYNAMIC_TYPE_OPENSSL))) {
+            return WOLFSSL_FAILURE;
+        }
+        XMEMSET(temp+str->length, 0, bytes_cnt+1 - str->length);
+        str->data = temp;
+        str->length = bytes_cnt+1;
+    }
+
+    str->data[bytes_cnt] &= ~bit;
+    str->data[bytes_cnt] |= val ? bit : 0;
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* Gets the X509_EXTENSION* ext based on it's location in WOLFSSL_X509* x509.
+ *
+ * x509   : The X509 structure to look for the extension.
+ * loc    : Location of the extension. If the extension is found at the given
+ * location, a new X509_EXTENSION structure is populated with extension-specific
+ * data based on the extension type.
+
+ * Returns NULL on error or pointer to X509_EXTENSION structure containing the
+ * extension. The returned X509_EXTENSION should not be free'd by caller.
+ * The returned X509_EXTENSION is pushed onto a stack inside the x509 argument.
+ * This is later free'd when x509 is free'd.
+ *
+ * NOTE: for unknown extension NIDs, a X509_EXTENSION is populated with the
+ * extension oid as the ASN1_OBJECT (QT compatibility)
+ */
+WOLFSSL_X509_EXTENSION* wolfSSL_X509_get_ext(const WOLFSSL_X509* x509, int loc)
+{
+    WOLFSSL_X509_EXTENSION* ext = NULL;
+    WOLFSSL_ENTER("wolfSSL_X509_get_ext");
+    if (x509 == NULL)
+        return NULL;
+
+   ext = wolfSSL_X509_set_ext((WOLFSSL_X509*) x509, loc);
+   return ext;
+}
+
+/* Pushes a new X509_EXTENSION* ext onto the stack inside WOLFSSL_X509* x509.
+ * This is currently a helper function for wolfSSL_X509_get_ext
+ * Caller does not free the returned WOLFSSL_X509_EXTENSION*
+ */
+WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc)
+{
+    int extCount = 0, length = 0, outSz = 0, sz = 0, ret = 0;
+    int objSz = 0, isSet = 0;
+    const byte* rawCert;
+    const byte* input;
+    byte* oidBuf;
+    word32 oid, idx = 0, tmpIdx = 0;
+    WOLFSSL_X509_EXTENSION* ext = NULL;
+    WOLFSSL_ASN1_INTEGER* a;
+    WOLFSSL_STACK* sk;
+    DecodedCert cert;
+
+    WOLFSSL_ENTER("wolfSSL_X509_set_ext");
+
+    if(x509 == NULL){
+        WOLFSSL_MSG("\tNot passed a certificate");
+        return NULL;
+    }
+
+    if(loc <0 || (loc > wolfSSL_X509_get_ext_count(x509))){
+        WOLFSSL_MSG("\tBad location argument");
+        return NULL;
+    }
+
+    ext = wolfSSL_X509_EXTENSION_new();
+    if (ext == NULL) {
+        WOLFSSL_MSG("\tX509_EXTENSION_new() failed");
+        return NULL;
+    }
+
+    rawCert = wolfSSL_X509_get_der((WOLFSSL_X509*)x509, &outSz);
+    if (rawCert == NULL) {
+        WOLFSSL_MSG("\tX509_get_der() failed");
+        wolfSSL_X509_EXTENSION_free(ext);
+        return NULL;
+    }
+
+    InitDecodedCert( &cert, rawCert, (word32)outSz, 0);
+
+    if (ParseCert(&cert, CA_TYPE, NO_VERIFY, NULL) < 0) {
+        WOLFSSL_MSG("\tCertificate parsing failed");
+        wolfSSL_X509_EXTENSION_free(ext);
+        return NULL;
+    }
+
+    input = cert.extensions;
+    sz = cert.extensionsSz;
+
+    if (input == NULL || sz == 0) {
+        WOLFSSL_MSG("\tfail: should be an EXTENSIONS");
+        wolfSSL_X509_EXTENSION_free(ext);
+        FreeDecodedCert(&cert);
+        return NULL;
+    }
+
+    if (input[idx++] != ASN_EXTENSIONS) {
+        WOLFSSL_MSG("\tfail: should be an EXTENSIONS");
+        wolfSSL_X509_EXTENSION_free(ext);
+        FreeDecodedCert(&cert);
+        return NULL;
+    }
+
+    if (GetLength(input, &idx, &length, sz) < 0) {
+        WOLFSSL_MSG("\tfail: invalid length");
+        wolfSSL_X509_EXTENSION_free(ext);
+        FreeDecodedCert(&cert);
+        return NULL;
+    }
+
+    if (GetSequence(input, &idx, &length, sz) < 0) {
+        WOLFSSL_MSG("\tfail: should be a SEQUENCE (1)");
+        wolfSSL_X509_EXTENSION_free(ext);
+        FreeDecodedCert(&cert);
+        return NULL;
+    }
+
+    while (idx < (word32)sz) {
+        oid = 0;
+
+        if (GetSequence(input, &idx, &length, sz) < 0) {
+            WOLFSSL_MSG("\tfail: should be a SEQUENCE");
+            wolfSSL_X509_EXTENSION_free(ext);
+            FreeDecodedCert(&cert);
+            return NULL;
+        }
+
+        tmpIdx = idx;
+        ret = GetObjectId(input, &idx, &oid, oidCertExtType, sz);
+        if (ret < 0) {
+            WOLFSSL_MSG("\tfail: OBJECT ID");
+            wolfSSL_X509_EXTENSION_free(ext);
+            FreeDecodedCert(&cert);
+            return NULL;
+        }
+        idx = tmpIdx;
+
+        /* Continue while loop until extCount == loc or idx > sz */
+        if (extCount != loc) {
+            idx += length;
+            extCount++;
+            continue;
+        }
+        /* extCount == loc. Now get the extension. */
+        /* Check if extension has been set */
+        isSet = wolfSSL_X509_ext_isSet_by_NID((WOLFSSL_X509*)x509, oid);
+        ext->obj = wolfSSL_OBJ_nid2obj(oid);
+        if (ext->obj == NULL) {
+            WOLFSSL_MSG("\tfail: Invalid OBJECT");
+            wolfSSL_X509_EXTENSION_free(ext);
+            FreeDecodedCert(&cert);
+            return NULL;
+        }
+        ext->obj->nid = oid;
+
+        switch (oid) {
+            case BASIC_CA_OID:
+                if (!isSet)
+                    break;
+                /* Set pathlength */
+                a = wolfSSL_ASN1_INTEGER_new();
+                if (a == NULL) {
+                    wolfSSL_X509_EXTENSION_free(ext);
+                    FreeDecodedCert(&cert);
+                    return NULL;
+                }
+                a->length = x509->pathLength;
+
+                /* Save ASN1_INTEGER in x509 extension */
+                ext->obj->pathlen = a;
+
+                ext->obj->ca = x509->isCa;
+                ext->crit = x509->basicConstCrit;
+                break;
+
+            case AUTH_INFO_OID:
+                if (!isSet)
+                    break;
+
+                /* Create a stack to hold both the caIssuer and ocsp objects
+                    in X509_EXTENSION structure */
+                sk = (WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)*)XMALLOC(
+                            sizeof(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)),
+                            NULL, DYNAMIC_TYPE_ASN1);
+                if (sk == NULL) {
+                    WOLFSSL_MSG("Failed to malloc stack");
+                    wolfSSL_X509_EXTENSION_free(ext);
+                    FreeDecodedCert(&cert);
+                    return NULL;
+                }
+                XMEMSET(sk, 0, sizeof(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)));
+                sk->type = STACK_TYPE_OBJ;
+
+                /* Add CaIssuers object to stack */
+                if (x509->authInfoCaIssuer != NULL &&
+                    x509->authInfoCaIssuerSz > 0)
+                {
+                    WOLFSSL_ASN1_OBJECT* obj;
+                    obj = wolfSSL_ASN1_OBJECT_new();
+                    if (obj == NULL) {
+                        WOLFSSL_MSG("Error creating ASN1 object");
+                        wolfSSL_sk_ASN1_OBJECT_free(sk);
+                        wolfSSL_X509_EXTENSION_free(ext);
+                        FreeDecodedCert(&cert);
+                        return NULL;
+                    }
+                    obj->obj = (byte*)x509->authInfoCaIssuer;
+                    obj->objSz = x509->authInfoCaIssuerSz;
+                    obj->grp = oidCertAuthInfoType;
+                    obj->nid = AIA_CA_ISSUER_OID;
+
+                    ret = wolfSSL_sk_ASN1_OBJECT_push(sk, obj);
+                    if (ret != WOLFSSL_SUCCESS) {
+                        WOLFSSL_MSG("Error pushing ASN1 object onto stack");
+                        wolfSSL_ASN1_OBJECT_free(obj);
+                        wolfSSL_sk_ASN1_OBJECT_free(sk);
+                        wolfSSL_X509_EXTENSION_free(ext);
+                        FreeDecodedCert(&cert);
+                        return NULL;
+                    }
+                }
+
+                /* Add OCSP object to stack */
+                if (x509->authInfo != NULL &&
+                    x509->authInfoSz > 0)
+                {
+                    WOLFSSL_ASN1_OBJECT* obj;
+                    obj = wolfSSL_ASN1_OBJECT_new();
+                    if (obj == NULL) {
+                        WOLFSSL_MSG("Error creating ASN1 object");
+                        wolfSSL_sk_ASN1_OBJECT_free(sk);
+                        wolfSSL_X509_EXTENSION_free(ext);
+                        FreeDecodedCert(&cert);
+                        return NULL;
+                    }
+                    obj->obj = x509->authInfo;
+                    obj->objSz = x509->authInfoSz;
+                    obj->grp = oidCertAuthInfoType;
+                    obj->nid = AIA_OCSP_OID;
+
+                    ret = wolfSSL_sk_ASN1_OBJECT_push(sk, obj);
+                    if (ret != WOLFSSL_SUCCESS) {
+                        WOLFSSL_MSG("Error pushing ASN1 object onto stack");
+                        wolfSSL_ASN1_OBJECT_free(obj);
+                        wolfSSL_sk_ASN1_OBJECT_free(sk);
+                        wolfSSL_X509_EXTENSION_free(ext);
+                        FreeDecodedCert(&cert);
+                        return NULL;
+                    }
+                }
+                ext->ext_sk = sk;
+                ext->crit = x509->authInfoCrit;
+                break;
+
+            case AUTH_KEY_OID:
+                if (!isSet)
+                    break;
+
+                ret = wolfSSL_ASN1_STRING_set(&ext->value, x509->authKeyId,
+                                        x509->authKeyIdSz);
+                if (ret != WOLFSSL_SUCCESS) {
+                    WOLFSSL_MSG("ASN1_STRING_set() failed");
+                    wolfSSL_X509_EXTENSION_free(ext);
+                    FreeDecodedCert(&cert);
+                    return NULL;
+                }
+                ext->crit = x509->authKeyIdCrit;
+                break;
+
+            case SUBJ_KEY_OID:
+                if (!isSet)
+                    break;
+
+                ret = wolfSSL_ASN1_STRING_set(&ext->value, x509->subjKeyId,
+                                        x509->subjKeyIdSz);
+                if (ret != WOLFSSL_SUCCESS) {
+                    WOLFSSL_MSG("ASN1_STRING_set() failed");
+                    wolfSSL_X509_EXTENSION_free(ext);
+                    FreeDecodedCert(&cert);
+                    return NULL;
+                }
+                ext->crit = x509->subjKeyIdCrit;
+                break;
+
+            case CERT_POLICY_OID:
+                if (!isSet)
+                    break;
+                ext->crit = x509->certPolicyCrit;
+                break;
+
+            case KEY_USAGE_OID:
+                if (!isSet)
+                    break;
+
+                ret = wolfSSL_ASN1_STRING_set(&ext->value,
+                                  (byte*)&(x509->keyUsage), sizeof(word16));
+                if (ret != WOLFSSL_SUCCESS) {
+                    WOLFSSL_MSG("ASN1_STRING_set() failed");
+                    wolfSSL_X509_EXTENSION_free(ext);
+                    FreeDecodedCert(&cert);
+                    return NULL;
+                }
+                ext->crit = x509->keyUsageCrit;
+                break;
+
+            case EXT_KEY_USAGE_OID:
+                if (!isSet)
+                    break;
+                ext->crit = x509->keyUsageCrit;
+                break;
+
+            case CRL_DIST_OID:
+                if (!isSet)
+                    break;
+                ext->crit = x509->CRLdistCrit;
+                break;
+
+            case ALT_NAMES_OID:
+            {
+                WOLFSSL_GENERAL_NAME* gn = NULL;
+                DNS_entry* dns = NULL;
+                if (!isSet)
+                    break;
+
+                sk = (WOLF_STACK_OF(WOLFSSL_GENERAL_NAME)*)XMALLOC(
+                          sizeof(WOLF_STACK_OF(WOLFSSL_GENERAL_NAME)), NULL,
+                                                         DYNAMIC_TYPE_ASN1);
+                if (sk == NULL) {
+                    return NULL;
+                }
+                XMEMSET(sk, 0, sizeof(WOLF_STACK_OF(WOLFSSL_GENERAL_NAME)));
+                sk->type = STACK_TYPE_GEN_NAME;
+
+                if (x509->subjAltNameSet && x509->altNames != NULL) {
+                    /* alt names are DNS_entry structs */
+                    dns = x509->altNames;
+                    /* Currently only support GEN_DNS type */
+                    while (dns != NULL) {
+                        gn = wolfSSL_GENERAL_NAME_new();
+                        if (gn == NULL) {
+                            WOLFSSL_MSG("Error creating GENERAL_NAME");
+                            wolfSSL_sk_free(sk);
+                            return NULL;
+                        }
+
+                        gn->type = dns->type;
+                        gn->d.ia5->length = dns->len;
+                        if (wolfSSL_ASN1_STRING_set(gn->d.ia5, dns->name,
+                                    gn->d.ia5->length) != WOLFSSL_SUCCESS) {
+                            WOLFSSL_MSG("ASN1_STRING_set failed");
+                            wolfSSL_GENERAL_NAME_free(gn);
+                            wolfSSL_sk_free(sk);
+                            return NULL;
+                        }
+
+                        dns = dns->next;
+                        /* last dns in list add at end of function */
+                        if (dns != NULL) {
+                            if (wolfSSL_sk_GENERAL_NAME_push(sk, gn) !=
+                                                          WOLFSSL_SUCCESS) {
+                            WOLFSSL_MSG("Error pushing onto stack");
+                            wolfSSL_GENERAL_NAME_free(gn);
+                            wolfSSL_sk_free(sk);
+                            sk = NULL;
+                            }
+                        }
+                    }
+                    if (wolfSSL_sk_GENERAL_NAME_push(sk,gn) !=
+                                                          WOLFSSL_SUCCESS) {
+                        WOLFSSL_MSG("Error pushing onto stack");
+                        wolfSSL_GENERAL_NAME_free(gn);
+                        wolfSSL_sk_free(sk);
+                        sk = NULL;
+                    }
+                }
+                ext->ext_sk = sk;
+                ext->crit = x509->subjAltNameCrit;
+                break;
+            }
+
+            default:
+                WOLFSSL_MSG("Unknown extension type found, parsing OID");
+                /* If the extension type is not recognized/supported,
+                    set the ASN1_OBJECT in the extension with the
+                    parsed oid for access in later function calls */
+
+                /* Get OID from input */
+                if (GetASNObjectId(input, &idx, &length, sz) != 0) {
+                    WOLFSSL_MSG("Failed to Get ASN Object Id");
+                    wolfSSL_X509_EXTENSION_free(ext);
+                    FreeDecodedCert(&cert);
+                    return NULL;
+                }
+                oidBuf = (byte*)XMALLOC(length+1+MAX_LENGTH_SZ, NULL,
+                                    DYNAMIC_TYPE_TMP_BUFFER);
+                if (oidBuf == NULL) {
+                    WOLFSSL_MSG("Failed to malloc tmp buffer");
+                    wolfSSL_X509_EXTENSION_free(ext);
+                    FreeDecodedCert(&cert);
+                    return NULL;
+                }
+                oidBuf[0] = ASN_OBJECT_ID;
+                objSz++;
+                objSz += SetLength(length, oidBuf + 1);
+                objSz += length;
+
+                /* Set object size and reallocate space in object buffer */
+                ext->obj->objSz = objSz;
+                if(((ext->obj->dynamic & WOLFSSL_ASN1_DYNAMIC_DATA) != 0) ||
+                   (ext->obj->obj == NULL)) {
+                        ext->obj->obj =(byte*)XREALLOC((byte*)ext->obj->obj,
+                                             ext->obj->objSz,
+                                             NULL,DYNAMIC_TYPE_ASN1);
+                    if (ext->obj->obj == NULL) {
+                        wolfSSL_ASN1_OBJECT_free(ext->obj);
+                        wolfSSL_X509_EXTENSION_free(ext);
+                        FreeDecodedCert(&cert);
+                        return NULL;
+                    }
+                    ext->obj->dynamic |= WOLFSSL_ASN1_DYNAMIC_DATA;
+                } else {
+                    ext->obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA;
+                }
+                /* Get OID from input and copy to ASN1_OBJECT buffer */
+                XMEMCPY(oidBuf+2, input+idx, length);
+                XMEMCPY((byte*)ext->obj->obj, oidBuf, ext->obj->objSz);
+                XFREE(oidBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                oidBuf = NULL;
+                ext->obj->grp = oidCertExtType;
+                ext->crit = 0;
+
+                /* Get extension data and copy as ASN1_STRING */
+                tmpIdx = idx + length;
+                if ((tmpIdx >= (word32)sz) || (input[tmpIdx++] != ASN_OCTET_STRING)) {
+                    WOLFSSL_MSG("Error decoding unknown extension data");
+                    wolfSSL_ASN1_OBJECT_free(ext->obj);
+                    wolfSSL_X509_EXTENSION_free(ext);
+                    FreeDecodedCert(&cert);
+                    return NULL;
+                }
+
+                if (GetLength(input, &tmpIdx, &length, sz) <= 0) {
+                    WOLFSSL_MSG("Error: Invalid Input Length.");
+                    wolfSSL_ASN1_OBJECT_free(ext->obj);
+                    wolfSSL_X509_EXTENSION_free(ext);
+                    FreeDecodedCert(&cert);
+                    return NULL;
+                }
+                ext->value.data = (char*)XMALLOC(length, NULL, DYNAMIC_TYPE_ASN1);
+                ext->value.isDynamic = 1;
+                if (ext->value.data == NULL) {
+                    WOLFSSL_MSG("Failed to malloc ASN1_STRING data");
+                    wolfSSL_X509_EXTENSION_free(ext);
+                    FreeDecodedCert(&cert);
+                    return NULL;
+                }
+                XMEMCPY(ext->value.data,input+tmpIdx,length);
+                ext->value.length = length;
+        } /* switch(oid) */
+
+        break; /* Got the Extension. Now exit while loop. */
+
+    } /* while(idx < sz) */
+
+    /* Store the new extension in a stack inside x509
+     * The extensions on the stack are free'd internally when FreeX509 is called
+     */
+    if (x509->ext_sk == NULL)
+        x509->ext_sk = wolfSSL_sk_new_x509_ext();
+    if (x509->ext_sk != NULL)
+        wolfSSL_sk_X509_EXTENSION_push(x509->ext_sk, ext);
+
+    FreeDecodedCert(&cert);
+    return ext;
+}
+
+/* Return 0 on success and 1 on failure. Copies ext data to bio, using indent
+ *  to pad the output. flag is ignored. */
+int wolfSSL_X509V3_EXT_print(WOLFSSL_BIO *out, WOLFSSL_X509_EXTENSION *ext,
+        unsigned long flag, int indent)
+{
+    ASN1_OBJECT* obj;
+    ASN1_STRING* str;
+    int nid;
+    const int sz = CTC_NAME_SIZE*2;
+    int rc = WOLFSSL_FAILURE;
+    char tmp[CTC_NAME_SIZE*2];
+    WOLFSSL_ENTER("wolfSSL_X509V3_EXT_print");
+
+    if ((out == NULL) || (ext == NULL)) {
+        WOLFSSL_MSG("NULL parameter error");
+        return rc;
+    }
+
+    obj = wolfSSL_X509_EXTENSION_get_object(ext);
+    if (obj == NULL) {
+        WOLFSSL_MSG("Error getting ASN1_OBJECT from X509_EXTENSION");
+        return rc;
+    }
+
+    str = wolfSSL_X509_EXTENSION_get_data(ext);
+    if (obj == NULL) {
+        WOLFSSL_MSG("Error getting ASN1_STRING from X509_EXTENSION");
+        return rc;
+    }
+
+    /* Print extension based on the type */
+    nid = wolfSSL_OBJ_obj2nid(obj);
+    switch (nid) {
+        case BASIC_CA_OID:
+        {
+            char isCa[] = "TRUE";
+            char notCa[] = "FALSE";
+            XSNPRINTF(tmp, sz, "%*sCA:%s", indent, "",
+                                                    obj->ca ? isCa : notCa);
+            break;
+        }
+        case ALT_NAMES_OID:
+        {
+            WOLFSSL_STACK* sk;
+            char* val;
+            int len;
+            tmp[0] = '\0'; /* Make sure tmp is null-terminated */
+
+            sk = ext->ext_sk;
+            while (sk != NULL) {
+                if (sk->type == STACK_TYPE_GEN_NAME && sk->data.gn) {
+                    /* str is GENERAL_NAME for subject alternative name ext */
+                    str = sk->data.gn->d.ia5;
+                    len = str->length + 2; /* + 2 for NULL char and "," */
+                    if (len > sz) {
+                        WOLFSSL_MSG("len greater than buffer size");
+                        return rc;
+                    }
+
+                    val = (char*)XMALLOC(len + indent, NULL,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+                    if (val == NULL) {
+                        WOLFSSL_MSG("Memory error");
+                        return rc;
+                    }
+                    if (sk->next)
+                        XSNPRINTF(val, len, "%*s%s, ", indent, "", str->strData);
+                    else
+                        XSNPRINTF(val, len, "%*s%s", indent, "", str->strData);
+
+                    XSTRNCAT(tmp, val, len);
+                    XFREE(val, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                }
+                sk = sk->next;
+            }
+            break;
+        }
+        case AUTH_KEY_OID:
+        case SUBJ_KEY_OID:
+        {
+            char* asn1str;
+            asn1str = wolfSSL_i2s_ASN1_STRING(NULL, str);
+            XSNPRINTF(tmp, sz, "%*s%s", indent, "", asn1str);
+            XFREE(asn1str, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            break;
+        }
+        case AUTH_INFO_OID:
+        case CERT_POLICY_OID:
+        case CRL_DIST_OID:
+        case KEY_USAGE_OID:
+            WOLFSSL_MSG("X509V3_EXT_print not yet implemented for ext type");
+            break;
+
+        default:
+            XSNPRINTF(tmp, sz, "%*s%s", indent, "", str->strData);
+    }
+
+    if (wolfSSL_BIO_write(out, tmp, (int)XSTRLEN(tmp)) == (int)XSTRLEN(tmp)) {
+        rc = WOLFSSL_SUCCESS;
+    }
+    (void) flag;
+
+    return rc;
+}
+
+/* Returns crit flag in X509_EXTENSION object */
+int wolfSSL_X509_EXTENSION_get_critical(const WOLFSSL_X509_EXTENSION* ex)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_get_critical");
+    if (ex == NULL)
+        return BAD_FUNC_ARG;
+    return ex->crit;
+}
+
+/* Creates v3_ext_method for a given X509v3 extension
+ *
+ * ex   : The X509_EXTENSION used to create v3_ext_method. If the extension is
+ * not NULL, get the NID of the extension object and populate the
+ * extension type-specific X509V3_EXT_* function(s) in v3_ext_method.
+ *
+ * Returns NULL on error or pointer to the v3_ext_method populated with extension
+ * type-specific X509V3_EXT_* function(s).
+ *
+ * NOTE: NID_subject_key_identifier is currently the only extension implementing
+ * the X509V3_EXT_* functions, as it is the only type called directly by QT. The
+ * other extension types return a pointer to a v3_ext_method struct that contains
+ * only the NID.
+ */
+const WOLFSSL_v3_ext_method* wolfSSL_X509V3_EXT_get(WOLFSSL_X509_EXTENSION* ex)
+{
+    int nid;
+    WOLFSSL_v3_ext_method method;
+
+    WOLFSSL_ENTER("wolfSSL_X509V3_EXT_get");
+    if ((ex == NULL) || (ex->obj == NULL)) {
+        WOLFSSL_MSG("Passed an invalid X509_EXTENSION*");
+        return NULL;
+    }
+    /* Initialize all methods to NULL */
+    method.d2i = NULL;
+    method.i2v = NULL;
+    method.i2s = NULL;
+    method.i2r = NULL;
+
+    nid = ex->obj->nid;
+    if (nid <= 0) {
+        WOLFSSL_MSG("Failed to get nid from passed extension object");
+        return NULL;
+    }
+
+    switch (nid) {
+        case NID_basic_constraints:
+            break;
+        case NID_subject_key_identifier:
+            method.i2s = (X509V3_EXT_I2S)wolfSSL_i2s_ASN1_STRING;
+            break;
+        case NID_key_usage:
+            WOLFSSL_MSG("i2v function not yet implemented for Key Usage");
+            break;
+        case NID_authority_key_identifier:
+            WOLFSSL_MSG("i2v function not yet implemented for Auth Key Id");
+            break;
+        case NID_info_access:
+            WOLFSSL_MSG("i2v function not yet implemented for Info Access");
+            break;
+        case NID_ext_key_usage:
+            WOLFSSL_MSG("i2v function not yet implemented for Ext Key Usage");
+            break;
+        case NID_certificate_policies:
+            WOLFSSL_MSG("r2i function not yet implemented for Cert Policies");
+            break;
+        case NID_crl_distribution_points:
+            WOLFSSL_MSG("r2i function not yet implemented for CRL Dist Points");
+            break;
+        default:
+            /* If extension type is unknown, return NULL -- QT makes call to
+                X509_EXTENSION_get_data() if there is no v3_ext_method */
+            WOLFSSL_MSG("X509V3_EXT_get(): Unknown extension type found");
+            return NULL;
+    }
+
+    method.ext_nid = nid;
+    ex->ext_method = method;
+
+    return (const WOLFSSL_v3_ext_method*)&ex->ext_method;
+}
+
+/* Parses and returns an x509v3 extension internal structure.
+ *
+ * ext   : The X509_EXTENSION for parsing internal structure. If extension is
+ * not NULL, get the NID of the extension object and create a new
+ * extension-specific internal structure based on the extension type.
+ *
+ * Returns NULL on error or if NID is not found, otherwise returns a pointer to
+ * the extension type-specific X509_EXTENSION internal structure.
+ * Return is expected to be free'd by caller.
+ */
+void* wolfSSL_X509V3_EXT_d2i(WOLFSSL_X509_EXTENSION* ext)
+{
+    const WOLFSSL_v3_ext_method* method;
+    int ret;
+    WOLFSSL_ASN1_OBJECT* object;
+    WOLFSSL_BASIC_CONSTRAINTS* bc;
+    WOLFSSL_AUTHORITY_KEYID* akey;
+    WOLFSSL_ASN1_STRING* asn1String, *newString;
+    WOLFSSL_AUTHORITY_INFO_ACCESS* aia;
+    WOLFSSL_STACK* sk;
+
+    WOLFSSL_ENTER("wolfSSL_X509V3_EXT_d2i");
+
+    if(ext == NULL) {
+        WOLFSSL_MSG("Bad function Argument");
+        return NULL;
+    }
+
+    /* extract extension info */
+    method = wolfSSL_X509V3_EXT_get(ext);
+    if (method == NULL) {
+        WOLFSSL_MSG("wolfSSL_X509V3_EXT_get error");
+        return NULL;
+    }
+    object = wolfSSL_X509_EXTENSION_get_object(ext);
+    if (object == NULL) {
+        WOLFSSL_MSG("X509_EXTENSION_get_object failed");
+        return NULL;
+    }
+
+    /* Return pointer to proper internal structure based on NID */
+    switch (object->type) {
+        /* basicConstraints */
+        case (NID_basic_constraints):
+            WOLFSSL_MSG("basicConstraints");
+            /* Allocate new BASIC_CONSTRAINTS structure */
+            bc = (WOLFSSL_BASIC_CONSTRAINTS*)
+                  XMALLOC(sizeof(WOLFSSL_BASIC_CONSTRAINTS), NULL,
+                  DYNAMIC_TYPE_X509_EXT);
+            if (bc == NULL) {
+                WOLFSSL_MSG("Failed to malloc basic constraints");
+                return NULL;
+            }
+            /* Copy pathlen and CA into BASIC_CONSTRAINTS from object */
+            bc->ca = object->ca;
+            if (object->pathlen->length > 0) {
+                bc->pathlen = wolfSSL_ASN1_INTEGER_dup(object->pathlen);
+                if (bc->pathlen == NULL) {
+                    WOLFSSL_MSG("Failed to duplicate ASN1_INTEGER");
+                    XFREE(bc, NULL, DYNAMIC_TYPE_X509_EXT);
+                    return NULL;
+                }
+            }
+            else
+                bc->pathlen = NULL;
+            return bc;
+
+        /* subjectKeyIdentifier */
+        case (NID_subject_key_identifier):
+            WOLFSSL_MSG("subjectKeyIdentifier");
+            asn1String = wolfSSL_X509_EXTENSION_get_data(ext);
+            if (asn1String == NULL) {
+                WOLFSSL_MSG("X509_EXTENSION_get_data() failed");
+                return NULL;
+            }
+            newString = wolfSSL_ASN1_STRING_new();
+            if (newString == NULL) {
+                WOLFSSL_MSG("Failed to malloc ASN1_STRING");
+                return NULL;
+            }
+            ret = wolfSSL_ASN1_STRING_set(newString, asn1String->data,
+                                                            asn1String->length);
+            if (ret != WOLFSSL_SUCCESS) {
+                WOLFSSL_MSG("ASN1_STRING_set() failed");
+                wolfSSL_ASN1_STRING_free(newString);
+                return NULL;
+            };
+            newString->type = asn1String->type;
+            return newString;
+
+        /* authorityKeyIdentifier */
+        case (NID_authority_key_identifier):
+            WOLFSSL_MSG("AuthorityKeyIdentifier");
+
+            akey = (WOLFSSL_AUTHORITY_KEYID*)
+                    XMALLOC(sizeof(WOLFSSL_AUTHORITY_KEYID), NULL,
+                    DYNAMIC_TYPE_X509_EXT);
+            if (akey == NULL) {
+                WOLFSSL_MSG("Failed to malloc authority key id");
+                return NULL;
+            }
+
+            akey->keyid = wolfSSL_ASN1_STRING_new();
+            if (akey->keyid == NULL) {
+                WOLFSSL_MSG("ASN1_STRING_new() failed");
+                wolfSSL_AUTHORITY_KEYID_free(akey);
+                return NULL;
+            }
+
+            asn1String = wolfSSL_X509_EXTENSION_get_data(ext);
+            if (asn1String == NULL) {
+                WOLFSSL_MSG("X509_EXTENSION_get_data() failed");
+                wolfSSL_AUTHORITY_KEYID_free(akey);
+                return NULL;
+            }
+
+            ret = wolfSSL_ASN1_STRING_set(akey->keyid, asn1String->data,
+                                                            asn1String->length);
+            if (ret != WOLFSSL_SUCCESS) {
+                WOLFSSL_MSG("ASN1_STRING_set() failed");
+                wolfSSL_AUTHORITY_KEYID_free(akey);
+                return NULL;
+            };
+            akey->keyid->type   = asn1String->type;
+
+            /* For now, set issuer and serial to NULL. This may need to be
+                updated for future use */
+            akey->issuer = NULL;
+            akey->serial = NULL;
+            return akey;
+
+        /* keyUsage */
+        case (NID_key_usage):
+            WOLFSSL_MSG("keyUsage");
+            /* This may need to be updated for future use. The i2v method for
+                keyUsage is not currently set. For now, return the ASN1_STRING
+                representation of KeyUsage bit string */
+            asn1String = wolfSSL_X509_EXTENSION_get_data(ext);
+            if (asn1String == NULL) {
+                WOLFSSL_MSG("X509_EXTENSION_get_data() failed");
+                return NULL;
+            }
+            newString = wolfSSL_ASN1_STRING_new();
+            if (newString == NULL) {
+                WOLFSSL_MSG("Failed to malloc ASN1_STRING");
+                return NULL;
+            }
+            ret = wolfSSL_ASN1_STRING_set(newString, asn1String->data,
+                                                            asn1String->length);
+            if (ret != WOLFSSL_SUCCESS) {
+                WOLFSSL_MSG("ASN1_STRING_set() failed");
+                wolfSSL_ASN1_STRING_free(newString);
+                return NULL;
+            };
+            newString->type = asn1String->type;
+            return newString;
+
+        /* extKeyUsage */
+        case (NID_ext_key_usage):
+            WOLFSSL_MSG("extKeyUsage not supported yet");
+            return NULL;
+
+        /* certificatePolicies */
+        case (NID_certificate_policies):
+            WOLFSSL_MSG("certificatePolicies not supported yet");
+            return NULL;
+
+        /* cRLDistributionPoints */
+        case (NID_crl_distribution_points):
+            WOLFSSL_MSG("cRLDistributionPoints not supported yet");
+            return NULL;
+
+        /* authorityInfoAccess */
+        case (NID_info_access):
+            WOLFSSL_MSG("AuthorityInfoAccess");
+
+            sk = ext->ext_sk;
+            if (sk == NULL) {
+                WOLFSSL_MSG("ACCESS_DESCRIPTION stack NULL");
+                return NULL;
+            }
+
+            /* AUTHORITY_INFO_ACCESS is a stack of ACCESS_DESCRIPTION entries */
+            aia = wolfSSL_sk_new_null();
+            if (aia == NULL) {
+                WOLFSSL_MSG("Failed to malloc AUTHORITY_INFO_ACCESS");
+                return NULL;
+            }
+            aia->type = STACK_TYPE_ACCESS_DESCRIPTION;
+
+            while (sk) {
+                WOLFSSL_ACCESS_DESCRIPTION* ad;
+                WOLFSSL_ASN1_OBJECT* aiaEntry;
+
+                if (sk->type != STACK_TYPE_OBJ) {
+                    sk = sk->next;
+                    continue;
+                }
+
+                aiaEntry = sk->data.obj;
+
+                /* ACCESS_DESCRIPTION has two members, method and location.
+                Method: ASN1_OBJECT as either AIA_OCSP_OID or AIA_CA_ISSUER_OID
+                Location: GENERAL_NAME structure containing the URI. */
+
+                ad = (WOLFSSL_ACCESS_DESCRIPTION*)
+                        XMALLOC(sizeof(WOLFSSL_ACCESS_DESCRIPTION), NULL,
+                        DYNAMIC_TYPE_X509_EXT);
+                if (ad == NULL) {
+                    WOLFSSL_MSG("Failed to malloc ACCESS_DESCRIPTION");
+                    XFREE(aia, NULL, DYNAMIC_TYPE_X509_EXT);
+                    return NULL;
+                }
+                XMEMSET(ad, 0, sizeof(WOLFSSL_ACCESS_DESCRIPTION));
+
+                /* Create new ASN1_OBJECT from oid */
+                ad->method = wolfSSL_OBJ_nid2obj(aiaEntry->nid);
+                if (ad->method == NULL) {
+                    WOLFSSL_MSG("OBJ_nid2obj() failed");
+                    XFREE(aia, NULL, DYNAMIC_TYPE_X509_EXT);
+                    XFREE(ad, NULL, DYNAMIC_TYPE_X509_EXT);
+                    return NULL;
+                }
+
+                /* Allocate memory for GENERAL NAME */
+                ad->location = (WOLFSSL_GENERAL_NAME*)
+                                XMALLOC(sizeof(WOLFSSL_GENERAL_NAME), NULL,
+                                DYNAMIC_TYPE_OPENSSL);
+                if (ad->location == NULL) {
+                    WOLFSSL_MSG("Failed to malloc GENERAL_NAME");
+                    wolfSSL_ASN1_OBJECT_free(ad->method);
+                    XFREE(aia, NULL, DYNAMIC_TYPE_X509_EXT);
+                    XFREE(ad, NULL, DYNAMIC_TYPE_X509_EXT);
+                    return NULL;
+                }
+                XMEMSET(ad->location, 0, sizeof(WOLFSSL_GENERAL_NAME));
+                ad->location->type = GEN_URI;
+                ad->location->d.uniformResourceIdentifier =
+                                    wolfSSL_ASN1_STRING_new();
+                /* Set the URI in GENERAL_NAME */
+                ret = wolfSSL_ASN1_STRING_set(
+                                    ad->location->d.uniformResourceIdentifier,
+                                    aiaEntry->obj, aiaEntry->objSz);
+                if (ret != WOLFSSL_SUCCESS) {
+                    WOLFSSL_MSG("ASN1_STRING_set() failed");
+                    wolfSSL_ASN1_OBJECT_free(ad->method);
+                    XFREE(aia, NULL, DYNAMIC_TYPE_X509_EXT);
+                    XFREE(ad, NULL, DYNAMIC_TYPE_X509_EXT);
+                    return NULL;
+                }
+                /* Push to AUTHORITY_INFO_ACCESS stack */
+                ret = wolfSSL_sk_ACCESS_DESCRIPTION_push(aia, ad);
+                if (ret != WOLFSSL_SUCCESS) {
+                    WOLFSSL_MSG("Error pushing ASN1 AD onto stack");
+                    wolfSSL_sk_ACCESS_DESCRIPTION_pop_free(aia, NULL);
+                    wolfSSL_ASN1_OBJECT_free(ad->method);
+                    XFREE(aia, NULL, DYNAMIC_TYPE_X509_EXT);
+                    XFREE(ad, NULL, DYNAMIC_TYPE_X509_EXT);
+                    return NULL;
+                }
+
+                sk = sk->next;
+            }
+            return aia;
+
+        default:
+            WOLFSSL_MSG("Extension NID not in table, returning NULL");
+            break;
+    }
+    return NULL;
+}
+
+/* Looks for the extension matching the passed in nid
+ *
+ * x509 : certificate to get parse through for extension.
+ * nid : Extension OID to be found.
+ * lastPos : Start search from extension after lastPos.
+ *           Set to -1 to search from index 0.
+ * return >= 0 If successful the extension index is returned.
+ * return -1 If extension is not found or error is encountered.
+ */
+int wolfSSL_X509_get_ext_by_NID(const WOLFSSL_X509* x509, int nid, int lastPos)
+{
+    int extCount = 0, length = 0, outSz = 0, sz = 0, ret = 0;
+    int isSet = 0, found = 0, loc;
+    const byte* rawCert;
+    const byte* input;
+    word32 oid, idx = 0, tmpIdx = 0;
+    DecodedCert cert;
+
+    WOLFSSL_ENTER("wolfSSL_X509_get_ext_by_NID");
+
+    if(x509 == NULL){
+        WOLFSSL_MSG("\tNot passed a certificate");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if(lastPos < -1 || (lastPos > (wolfSSL_X509_get_ext_count(x509) - 1))){
+        WOLFSSL_MSG("\tBad location argument");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    loc = lastPos + 1;
+
+    rawCert = wolfSSL_X509_get_der((WOLFSSL_X509*)x509, &outSz);
+    if (rawCert == NULL) {
+        WOLFSSL_MSG("\tX509_get_der() failed");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    InitDecodedCert( &cert, rawCert, (word32)outSz, 0);
+
+    if (ParseCert(&cert, CA_TYPE, NO_VERIFY, NULL) < 0) {
+        WOLFSSL_MSG("\tCertificate parsing failed");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    input = cert.extensions;
+    sz = cert.extensionsSz;
+
+    if (input == NULL || sz == 0) {
+        WOLFSSL_MSG("\tfail: should be an EXTENSIONS");
+        FreeDecodedCert(&cert);
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (input[idx++] != ASN_EXTENSIONS) {
+        WOLFSSL_MSG("\tfail: should be an EXTENSIONS");
+        FreeDecodedCert(&cert);
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (GetLength(input, &idx, &length, sz) < 0) {
+        WOLFSSL_MSG("\tfail: invalid length");
+        FreeDecodedCert(&cert);
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (GetSequence(input, &idx, &length, sz) < 0) {
+        WOLFSSL_MSG("\tfail: should be a SEQUENCE (1)");
+        FreeDecodedCert(&cert);
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    while (idx < (word32)sz) {
+        oid = 0;
+
+        if (GetSequence(input, &idx, &length, sz) < 0) {
+            WOLFSSL_MSG("\tfail: should be a SEQUENCE");
+            FreeDecodedCert(&cert);
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        tmpIdx = idx;
+        ret = GetObjectId(input, &idx, &oid, oidCertExtType, sz);
+        if (ret < 0) {
+            WOLFSSL_MSG("\tfail: OBJECT ID");
+            FreeDecodedCert(&cert);
+            return WOLFSSL_FATAL_ERROR;
+        }
+        idx = tmpIdx;
+
+        if (extCount >= loc) {
+            /* extCount >= loc. Now check if extension has been set */
+            isSet = wolfSSL_X509_ext_isSet_by_NID((WOLFSSL_X509*)x509, oid);
+
+            if (isSet && ((word32)nid == oid)) {
+                found = 1;
+                break;
+            }
+        }
+
+        idx += length;
+        extCount++;
+    } /* while(idx < sz) */
+
+    FreeDecodedCert(&cert);
+
+    return found ? extCount : WOLFSSL_FATAL_ERROR;
+}
+
+
+#endif /* OPENSSL_ALL */
+
+WOLFSSL_ASN1_BIT_STRING* wolfSSL_ASN1_BIT_STRING_new(void)
+{
+    WOLFSSL_ASN1_BIT_STRING* str;
+
+    str = (WOLFSSL_ASN1_BIT_STRING*)XMALLOC(sizeof(WOLFSSL_ASN1_BIT_STRING),
+                                                  NULL, DYNAMIC_TYPE_OPENSSL);
+    if (str) {
+        XMEMSET(str, 0, sizeof(WOLFSSL_ASN1_BIT_STRING));
+    }
+    return str;
+}
+
+void wolfSSL_ASN1_BIT_STRING_free(WOLFSSL_ASN1_BIT_STRING* str)
+{
+    if (str) {
+        if (str->data) {
+            XFREE(str->data, NULL, DYNAMIC_TYPE_OPENSSL);
+            str->data = NULL;
+        }
+        XFREE(str, NULL, DYNAMIC_TYPE_OPENSSL);
+    }
+}
+
+int wolfSSL_ASN1_BIT_STRING_get_bit(const WOLFSSL_ASN1_BIT_STRING* str, int i)
+{
+    if (!str || !str->data || str->length <= (i/8) || i < 0) {
+        return WOLFSSL_FAILURE;
+    }
+
+    return (str->data[i/8] & (1<<(7-(i%8)))) ? 1 : 0;
+}
+
+/* Looks for the extension matching the passed in nid
+ *
+ * c   : if not null then is set to status value -2 if multiple occurrences
+ *       of the extension are found, -1 if not found, 0 if found and not
+ *       critical, and 1 if found and critical.
+ * nid : Extension OID to be found.
+ * idx : if NULL return first extension found match, otherwise start search at
+ *       idx location and set idx to the location of extension returned.
+ * returns NULL or a pointer to an WOLFSSL_ASN1_BIT_STRING (for KEY_USAGE_OID)
+ * or WOLFSSL_STACK (for other)
+ * holding extension structure
+ *
+ * NOTE code for decoding extensions is in asn.c DecodeCertExtensions --
+ * use already decoded extension in this function to avoid decoding twice.
+ * Currently we do not make use of idx since getting pre decoded extensions.
+ */
+void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, int nid, int* c,
+    int* idx)
+{
+    void* ret = NULL;
+    WOLFSSL_STACK* sk = NULL;
+    WOLFSSL_ASN1_OBJECT* obj = NULL;
+    WOLFSSL_GENERAL_NAME* gn = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_X509_get_ext_d2i");
+
+    if (x509 == NULL) {
+        return NULL;
+    }
+
+    if (c != NULL) {
+        *c = -1; /* default to not found */
+    }
+
+    switch (nid) {
+        case BASIC_CA_OID:
+            if (x509->basicConstSet) {
+                obj = wolfSSL_ASN1_OBJECT_new();
+                if (obj == NULL) {
+                    WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+                    return NULL;
+                }
+                if (c != NULL) {
+                    *c = x509->basicConstCrit;
+                }
+                obj->type = BASIC_CA_OID;
+                obj->grp  = oidCertExtType;
+                obj->nid  = nid;
+                obj->dynamic |= WOLFSSL_ASN1_DYNAMIC;
+            #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) || \
+                    defined(WOLFSSL_APACHE_HTTPD)
+                obj->ca = x509->isCa;
+            #endif
+            }
+            else {
+                WOLFSSL_MSG("No Basic Constraint set");
+            }
+            return obj;
+
+        case ALT_NAMES_OID:
+        {
+            DNS_entry* dns = NULL;
+            /* Malloc GENERAL_NAME stack */
+            sk = (WOLF_STACK_OF(WOLFSSL_GENERAL_NAME)*)XMALLOC(
+                        sizeof(WOLF_STACK_OF(WOLFSSL_GENERAL_NAME)), NULL,
+                                                         DYNAMIC_TYPE_ASN1);
+            if (sk == NULL) {
+                return NULL;
+            }
+            XMEMSET(sk, 0, sizeof(WOLF_STACK_OF(WOLFSSL_GENERAL_NAME)));
+            sk->type = STACK_TYPE_GEN_NAME;
+
+            if (x509->subjAltNameSet && x509->altNames != NULL) {
+                /* alt names are DNS_entry structs */
+                if (c != NULL) {
+                    if (x509->altNames->next != NULL) {
+                        *c = -2; /* more then one found */
+                    }
+                    else {
+                        *c = x509->subjAltNameCrit;
+                    }
+                }
+
+                dns = x509->altNames;
+                /* Currently only support GEN_DNS type */
+                while (dns != NULL) {
+                    gn = wolfSSL_GENERAL_NAME_new();
+                    if (gn == NULL) {
+                        WOLFSSL_MSG("Error creating GENERAL_NAME");
+                        wolfSSL_sk_free(sk);
+                        return NULL;
+                    }
+
+                    gn->type = dns->type;
+                    gn->d.ia5->length = dns->len;
+                    if (wolfSSL_ASN1_STRING_set(gn->d.ia5, dns->name,
+                                gn->d.ia5->length) != WOLFSSL_SUCCESS) {
+                        WOLFSSL_MSG("ASN1_STRING_set failed");
+                        wolfSSL_GENERAL_NAME_free(gn);
+                        wolfSSL_sk_free(sk);
+                        return NULL;
+                    }
+
+                    dns = dns->next;
+                    /* last dns in list add at end of function */
+                    if (dns != NULL) {
+                        if (wolfSSL_sk_GENERAL_NAME_push(sk, gn) !=
+                                                          WOLFSSL_SUCCESS) {
+                            WOLFSSL_MSG("Error pushing ASN1 object onto stack");
+                            wolfSSL_GENERAL_NAME_free(gn);
+                            wolfSSL_sk_free(sk);
+                            sk = NULL;
+                        }
+                    }
+                }
+            }
+            else {
+                WOLFSSL_MSG("No Alt Names set");
+            }
+
+            break;
+        }
+
+        case CRL_DIST_OID:
+            if (x509->CRLdistSet && x509->CRLInfo != NULL) {
+                if (c != NULL) {
+                    *c = x509->CRLdistCrit;
+                }
+                obj = wolfSSL_ASN1_OBJECT_new();
+                if (obj == NULL) {
+                    WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+                    return NULL;
+                }
+                obj->type  = CRL_DIST_OID;
+                obj->grp   = oidCertExtType;
+                obj->obj   = x509->CRLInfo;
+                obj->objSz = x509->CRLInfoSz;
+                obj->dynamic |= WOLFSSL_ASN1_DYNAMIC;
+                obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA ;
+            }
+            else {
+                WOLFSSL_MSG("No CRL dist set");
+            }
+            break;
+
+        case AUTH_INFO_OID:
+            if (x509->authInfoSet && x509->authInfo != NULL) {
+                if (c != NULL) {
+                    *c = x509->authInfoCrit;
+                }
+                obj = wolfSSL_ASN1_OBJECT_new();
+                if (obj == NULL) {
+                    WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+                    return NULL;
+                }
+                obj->type  = AUTH_INFO_OID;
+                obj->grp   = oidCertExtType;
+                obj->obj   = x509->authInfo;
+                obj->objSz = x509->authInfoSz;
+                obj->dynamic |= WOLFSSL_ASN1_DYNAMIC;
+                obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA;
+            }
+            else {
+                WOLFSSL_MSG("No Auth Info set");
+            }
+            break;
+
+        case AUTH_KEY_OID:
+            if (x509->authKeyIdSet) {
+                if (c != NULL) {
+                    *c = x509->authKeyIdCrit;
+                }
+                obj = wolfSSL_ASN1_OBJECT_new();
+                if (obj == NULL) {
+                    WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+                    return NULL;
+                }
+                obj->type  = AUTH_KEY_OID;
+                obj->grp   = oidCertExtType;
+                obj->obj   = x509->authKeyId;
+                obj->objSz = x509->authKeyIdSz;
+                obj->dynamic |= WOLFSSL_ASN1_DYNAMIC;
+                obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA;
+            }
+            else {
+                WOLFSSL_MSG("No Auth Key set");
+            }
+            break;
+
+        case SUBJ_KEY_OID:
+            if (x509->subjKeyIdSet) {
+                if (c != NULL) {
+                    *c = x509->subjKeyIdCrit;
+                }
+                obj = wolfSSL_ASN1_OBJECT_new();
+                if (obj == NULL) {
+                    WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+                    return NULL;
+                }
+                obj->type  = SUBJ_KEY_OID;
+                obj->grp   = oidCertExtType;
+                obj->obj   = x509->subjKeyId;
+                obj->objSz = x509->subjKeyIdSz;
+                obj->dynamic |= WOLFSSL_ASN1_DYNAMIC;
+                obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA;
+            }
+            else {
+                WOLFSSL_MSG("No Subject Key set");
+            }
+            break;
+
+        case CERT_POLICY_OID:
+        {
+        #ifdef WOLFSSL_CERT_EXT
+            int i;
+
+            if (x509->certPoliciesNb > 0) {
+                if (c != NULL) {
+                    if (x509->certPoliciesNb > 1) {
+                        *c = -2;
+                    }
+                    else {
+                        *c = 0;
+                    }
+                }
+
+                sk = wolfSSL_sk_new_asn1_obj();
+                if (sk == NULL) {
+                    return NULL;
+                }
+
+                for (i = 0; i < x509->certPoliciesNb - 1; i++) {
+                    obj = wolfSSL_ASN1_OBJECT_new();
+                    if (obj == NULL) {
+                        WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+                        wolfSSL_sk_ASN1_OBJECT_free(sk);
+                        return NULL;
+                    }
+                    obj->type  = CERT_POLICY_OID;
+                    obj->grp   = oidCertExtType;
+                    obj->obj   = (byte*)(x509->certPolicies[i]);
+                    obj->objSz = MAX_CERTPOL_SZ;
+                    obj->dynamic |= WOLFSSL_ASN1_DYNAMIC;
+                    obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA;
+                    if (wolfSSL_sk_ASN1_OBJECT_push(sk, obj)
+                                                           != WOLFSSL_SUCCESS) {
+                        WOLFSSL_MSG("Error pushing ASN1 object onto stack");
+                        wolfSSL_ASN1_OBJECT_free(obj);
+                        wolfSSL_sk_ASN1_OBJECT_free(sk);
+                        sk = NULL;
+                    }
+                }
+                obj = wolfSSL_ASN1_OBJECT_new();
+                if (obj == NULL) {
+                    WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+                    wolfSSL_sk_ASN1_OBJECT_free(sk);
+                    return NULL;
+                }
+                obj->type  = CERT_POLICY_OID;
+                obj->grp   = oidCertExtType;
+                obj->obj   = (byte*)(x509->certPolicies[i]);
+                obj->objSz = MAX_CERTPOL_SZ;
+                obj->dynamic |= WOLFSSL_ASN1_DYNAMIC;
+                obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA;
+            }
+            else {
+                WOLFSSL_MSG("No Cert Policy set");
+            }
+        #elif defined(WOLFSSL_SEP)
+            if (x509->certPolicySet) {
+                if (c != NULL) {
+                    *c = x509->certPolicyCrit;
+                }
+                obj = wolfSSL_ASN1_OBJECT_new();
+                if (obj == NULL) {
+                    WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+                    return NULL;
+                }
+                obj->type  = CERT_POLICY_OID;
+                obj->grp   = oidCertExtType;
+                obj->dynamic |= WOLFSSL_ASN1_DYNAMIC;
+            }
+            else {
+                WOLFSSL_MSG("No Cert Policy set");
+            }
+        #else
+            WOLFSSL_MSG("wolfSSL not built with WOLFSSL_SEP or WOLFSSL_CERT_EXT");
+        #endif
+            break;
+        }
+        case KEY_USAGE_OID:
+        {
+            WOLFSSL_ASN1_BIT_STRING* bit_str = NULL;
+            if (x509->keyUsageSet) {
+                if (c != NULL) {
+                    *c = x509->keyUsageCrit;
+                }
+
+                bit_str = wolfSSL_ASN1_BIT_STRING_new();
+                if (bit_str == NULL) {
+                    WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_BIT_STRING struct");
+                    return NULL;
+                }
+
+                bit_str->type = KEY_USAGE_OID;
+                bit_str->flags = 0;
+                bit_str->length = sizeof(word16);
+                bit_str->data = (byte*)XMALLOC(bit_str->length, NULL, DYNAMIC_TYPE_OPENSSL);
+                if (bit_str->data == NULL) {
+                    wolfSSL_ASN1_BIT_STRING_free(bit_str);
+                    return NULL;
+                }
+                XMEMCPY(bit_str->data, &x509->keyUsage, bit_str->length);
+            }
+            else {
+                WOLFSSL_MSG("No Key Usage set");
+            }
+            /* don't add stack of and return bit string directly */
+            return bit_str;
+        }
+        case INHIBIT_ANY_OID:
+            WOLFSSL_MSG("INHIBIT ANY extension not supported");
+            break;
+
+        case EXT_KEY_USAGE_OID:
+            if (x509->extKeyUsageSrc != NULL) {
+                if (c != NULL) {
+                    if (x509->extKeyUsageCount > 1) {
+                        *c = -2;
+                    }
+                    else {
+                        *c = x509->extKeyUsageCrit;
+                    }
+                }
+                obj = wolfSSL_ASN1_OBJECT_new();
+                if (obj == NULL) {
+                    WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+                    return NULL;
+                }
+                obj->type  = EXT_KEY_USAGE_OID;
+                obj->grp   = oidCertExtType;
+                obj->obj   = x509->extKeyUsageSrc;
+                obj->objSz = x509->extKeyUsageSz;
+                obj->dynamic |= WOLFSSL_ASN1_DYNAMIC;
+                obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA;
+            }
+            else {
+                WOLFSSL_MSG("No Extended Key Usage set");
+            }
+            break;
+
+        case NAME_CONS_OID:
+            WOLFSSL_MSG("Name Constraint OID extension not supported");
+            break;
+
+        case PRIV_KEY_USAGE_PERIOD_OID:
+            WOLFSSL_MSG("Private Key Usage Period extension not supported");
+            break;
+
+        case SUBJECT_INFO_ACCESS:
+            WOLFSSL_MSG("Subject Info Access extension not supported");
+            break;
+
+        case POLICY_MAP_OID:
+            WOLFSSL_MSG("Policy Map extension not supported");
+            break;
+
+        case POLICY_CONST_OID:
+            WOLFSSL_MSG("Policy Constraint extension not supported");
+            break;
+
+        case ISSUE_ALT_NAMES_OID:
+            WOLFSSL_MSG("Issue Alt Names extension not supported");
+            break;
+
+        case TLS_FEATURE_OID:
+            WOLFSSL_MSG("TLS Feature extension not supported");
+            break;
+
+        default:
+            WOLFSSL_MSG("Unsupported/Unknown extension OID");
+    }
+
+    /* make sure stack of is allocated */
+    if ((obj || gn) && sk == NULL) {
+        sk = wolfSSL_sk_new_asn1_obj();
+        if (sk == NULL) {
+            goto err;
+        }
+    }
+    if (obj && wolfSSL_sk_ASN1_OBJECT_push(sk, obj) == WOLFSSL_SUCCESS) {
+        /* obj pushed successfully on stack */
+    }
+    else if (gn && wolfSSL_sk_GENERAL_NAME_push(sk, gn) == WOLFSSL_SUCCESS) {
+        /* gn pushed successfully on stack */
+    }
+    else {
+        /* Nothing to push or push failed */
+        WOLFSSL_MSG("Error pushing ASN1_OBJECT or GENERAL_NAME object onto stack "
+                    "or nothing to push.");
+        goto err;
+    }
+    ret = sk;
+
+    (void)idx;
+
+    return ret;
+
+err:
+    if (obj) {
+        wolfSSL_ASN1_OBJECT_free(obj);
+    }
+    if (gn) {
+        wolfSSL_GENERAL_NAME_free(gn);
+    }
+    if (sk) {
+        wolfSSL_sk_ASN1_OBJECT_free(sk);
+    }
+    return NULL;
+}
+
+
+int wolfSSL_X509_add_altname(WOLFSSL_X509* x509, const char* name, int type)
+{
+    DNS_entry* newAltName = NULL;
+    char* nameCopy = NULL;
+    word32 nameSz;
+
+    if (x509 == NULL)
+        return WOLFSSL_FAILURE;
+
+    if (name == NULL)
+        return WOLFSSL_SUCCESS;
+
+    nameSz = (word32)XSTRLEN(name);
+    if (nameSz == 0)
+        return WOLFSSL_SUCCESS;
+
+    newAltName = (DNS_entry*)XMALLOC(sizeof(DNS_entry),
+            x509->heap, DYNAMIC_TYPE_ALTNAME);
+    if (newAltName == NULL)
+        return WOLFSSL_FAILURE;
+
+    nameCopy = (char*)XMALLOC(nameSz + 1, x509->heap, DYNAMIC_TYPE_ALTNAME);
+    if (nameCopy == NULL) {
+        XFREE(newAltName, x509->heap, DYNAMIC_TYPE_ALTNAME);
+        return WOLFSSL_FAILURE;
+    }
+
+    XMEMCPY(nameCopy, name, nameSz + 1);
+
+    newAltName->next = x509->altNames;
+    newAltName->type = type;
+    newAltName->len = nameSz;
+    newAltName->name = nameCopy;
+    x509->altNames = newAltName;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_X509_add_ext(WOLFSSL_X509 *x509, WOLFSSL_X509_EXTENSION *ext, int loc)
+{
+    WOLFSSL_STUB("wolfSSL_X509_add_ext");
+    (void)x509;
+    (void)ext;
+    (void)loc;
+    return WOLFSSL_FAILURE;
+}
+
+/* currently LHASH is not implemented (and not needed for Apache port) */
+WOLFSSL_X509_EXTENSION* wolfSSL_X509V3_EXT_conf_nid(
+        WOLF_LHASH_OF(CONF_VALUE)* conf, WOLFSSL_X509V3_CTX* ctx, int nid,
+        char* value)
+{
+    WOLFSSL_STUB("wolfSSL_X509V3_EXT_conf_nid");
+
+    if (conf != NULL) {
+        WOLFSSL_MSG("Handling LHASH not implemented yet");
+        return NULL;
+    }
+
+    (void)conf;
+    (void)ctx;
+    (void)nid;
+    (void)value;
+    return NULL;
+}
+
+void wolfSSL_X509V3_set_ctx_nodb(WOLFSSL_X509V3_CTX* ctx)
+{
+    WOLFSSL_STUB("wolfSSL_X509V3_set_ctx_nodb");
+    (void)ctx;
+}
+#endif /* !NO_WOLFSSL_STUB */
+
+/* Returns pointer to ASN1_OBJECT from an X509_EXTENSION object */
+WOLFSSL_ASN1_OBJECT* wolfSSL_X509_EXTENSION_get_object \
+    (WOLFSSL_X509_EXTENSION* ext)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_get_object");
+    if(ext == NULL)
+        return NULL;
+    return ext->obj;
+}
+
+/* Returns pointer to ASN1_STRING in X509_EXTENSION object */
+WOLFSSL_ASN1_STRING* wolfSSL_X509_EXTENSION_get_data(WOLFSSL_X509_EXTENSION* ext)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_get_data");
+    if (ext == NULL)
+        return NULL;
+    return &ext->value;
+}
+
+#if !defined(NO_PWDBASED)
+int wolfSSL_X509_digest(const WOLFSSL_X509* x509, const WOLFSSL_EVP_MD* digest,
+        unsigned char* buf, unsigned int* len)
+{
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_X509_digest");
+
+    if (x509 == NULL || digest == NULL) {
+        WOLFSSL_MSG("Null argument found");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (x509->derCert == NULL) {
+        WOLFSSL_MSG("No DER certificate stored in X509");
+        return WOLFSSL_FAILURE;
+    }
+
+    ret = wolfSSL_EVP_Digest(x509->derCert->buffer, x509->derCert->length, buf,
+                              len, digest, NULL);
+    WOLFSSL_LEAVE("wolfSSL_X509_digest", ret);
+    return ret;
+}
+#endif
+
+int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey)
+{
+    WOLFSSL_ENTER("wolfSSL_use_PrivateKey");
+    if (ssl == NULL || pkey == NULL ) {
+        return WOLFSSL_FAILURE;
+    }
+
+    return wolfSSL_use_PrivateKey_buffer(ssl, (unsigned char*)pkey->pkey.ptr,
+                                         pkey->pkey_sz, WOLFSSL_FILETYPE_ASN1);
+}
+
+
+int wolfSSL_use_PrivateKey_ASN1(int pri, WOLFSSL* ssl, const unsigned char* der,
+                                long derSz)
+{
+    WOLFSSL_ENTER("wolfSSL_use_PrivateKey_ASN1");
+    if (ssl == NULL || der == NULL ) {
+        return WOLFSSL_FAILURE;
+    }
+
+    (void)pri; /* type of private key */
+    return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, WOLFSSL_FILETYPE_ASN1);
+}
+/******************************************************************************
+* wolfSSL_CTX_use_PrivateKey_ASN1 - loads a private key buffer into the SSL ctx
+*
+* RETURNS:
+* returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE
+*/
+
+int wolfSSL_CTX_use_PrivateKey_ASN1(int pri, WOLFSSL_CTX* ctx,
+                                            unsigned char* der, long derSz)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_ASN1");
+    if (ctx == NULL || der == NULL ) {
+        return WOLFSSL_FAILURE;
+    }
+
+    (void)pri; /* type of private key */
+    return wolfSSL_CTX_use_PrivateKey_buffer(ctx, der, derSz, WOLFSSL_FILETYPE_ASN1);
+}
+
+
+#ifndef NO_RSA
+int wolfSSL_use_RSAPrivateKey_ASN1(WOLFSSL* ssl, unsigned char* der, long derSz)
+{
+    WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_ASN1");
+    if (ssl == NULL || der == NULL ) {
+        return WOLFSSL_FAILURE;
+    }
+
+    return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, WOLFSSL_FILETYPE_ASN1);
+}
+#endif
+
+int wolfSSL_use_certificate(WOLFSSL* ssl, WOLFSSL_X509* x509)
+{
+    long idx;
+
+    WOLFSSL_ENTER("wolfSSL_use_certificate");
+    if (x509 != NULL && ssl != NULL && x509->derCert != NULL) {
+        if (ProcessBuffer(NULL, x509->derCert->buffer, x509->derCert->length,
+                          WOLFSSL_FILETYPE_ASN1, CERT_TYPE, ssl, &idx, 0,
+                          GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) {
+            return WOLFSSL_SUCCESS;
+        }
+    }
+
+    (void)idx;
+    return WOLFSSL_FAILURE;
+}
+
+#endif /* NO_CERTS */
+
+#endif /* OPENSSL_EXTRA */
+
+#ifndef NO_CERTS
+int wolfSSL_use_certificate_ASN1(WOLFSSL* ssl, const unsigned char* der,
+                                 int derSz)
+{
+    long idx;
+
+    WOLFSSL_ENTER("wolfSSL_use_certificate_ASN1");
+    if (der != NULL && ssl != NULL) {
+        if (ProcessBuffer(NULL, der, derSz, WOLFSSL_FILETYPE_ASN1, CERT_TYPE,
+                ssl, &idx, 0, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) {
+            return WOLFSSL_SUCCESS;
+        }
+    }
+
+    (void)idx;
+    return WOLFSSL_FAILURE;
+}
+
+#ifndef NO_FILESYSTEM
+
+WOLFSSL_ABI
+int wolfSSL_use_certificate_file(WOLFSSL* ssl, const char* file, int format)
+{
+    WOLFSSL_ENTER("wolfSSL_use_certificate_file");
+
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (ProcessFile(ssl->ctx, file, format, CERT_TYPE,
+                ssl, 0, NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) {
+        return WOLFSSL_SUCCESS;
+    }
+
+    return WOLFSSL_FAILURE;
+}
+
+
+WOLFSSL_ABI
+int wolfSSL_use_PrivateKey_file(WOLFSSL* ssl, const char* file, int format)
+{
+    WOLFSSL_ENTER("wolfSSL_use_PrivateKey_file");
+
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (ProcessFile(ssl->ctx, file, format, PRIVATEKEY_TYPE,
+                ssl, 0, NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) {
+        return WOLFSSL_SUCCESS;
+    }
+
+    return WOLFSSL_FAILURE;
+}
+
+
+WOLFSSL_ABI
+int wolfSSL_use_certificate_chain_file(WOLFSSL* ssl, const char* file)
+{
+    /* process up to MAX_CHAIN_DEPTH plus subject cert */
+    WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file");
+
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (ProcessFile(ssl->ctx, file, WOLFSSL_FILETYPE_PEM, CERT_TYPE,
+               ssl, 1, NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) {
+        return WOLFSSL_SUCCESS;
+    }
+
+   return WOLFSSL_FAILURE;
+}
+
+int wolfSSL_use_certificate_chain_file_format(WOLFSSL* ssl, const char* file,
+                                              int format)
+{
+    /* process up to MAX_CHAIN_DEPTH plus subject cert */
+    WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file_format");
+
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (ProcessFile(ssl->ctx, file, format, CERT_TYPE, ssl, 1,
+                    NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) {
+        return WOLFSSL_SUCCESS;
+    }
+    return WOLFSSL_FAILURE;
+}
+
+#endif /* !NO_FILESYSTEM */
+#endif /* !NO_CERTS */
+
+#ifdef HAVE_ECC
+
+/* Set Temp CTX EC-DHE size in octets, should be 20 - 66 for 160 - 521 bit */
+int wolfSSL_CTX_SetTmpEC_DHE_Sz(WOLFSSL_CTX* ctx, word16 sz)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    if (sz == 0) {
+        /* applies only to ECDSA */
+        if (ctx->privateKeyType != ecc_dsa_sa_algo)
+            return WOLFSSL_SUCCESS;
+
+        if (ctx->privateKeySz == 0) {
+            WOLFSSL_MSG("Must set private key/cert first");
+            return BAD_FUNC_ARG;
+        }
+
+        sz = (word16)ctx->privateKeySz;
+    }
+
+    /* check size */
+    if (sz < ECC_MINSIZE || sz > ECC_MAXSIZE)
+        return BAD_FUNC_ARG;
+
+    ctx->eccTempKeySz = sz;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* Set Temp SSL EC-DHE size in octets, should be 20 - 66 for 160 - 521 bit */
+int wolfSSL_SetTmpEC_DHE_Sz(WOLFSSL* ssl, word16 sz)
+{
+    if (ssl == NULL || sz < ECC_MINSIZE || sz > ECC_MAXSIZE)
+        return BAD_FUNC_ARG;
+
+    ssl->eccTempKeySz = sz;
+
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* HAVE_ECC */
+
+
+#ifdef OPENSSL_EXTRA
+
+#ifndef NO_FILESYSTEM
+int wolfSSL_CTX_use_RSAPrivateKey_file(WOLFSSL_CTX* ctx,const char* file,
+                                   int format)
+{
+    WOLFSSL_ENTER("SSL_CTX_use_RSAPrivateKey_file");
+
+    return wolfSSL_CTX_use_PrivateKey_file(ctx, file, format);
+}
+
+
+int wolfSSL_use_RSAPrivateKey_file(WOLFSSL* ssl, const char* file, int format)
+{
+    WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_file");
+
+    return wolfSSL_use_PrivateKey_file(ssl, file, format);
+}
+#endif /* NO_FILESYSTEM */
+
+
+/* Copies the master secret over to out buffer. If outSz is 0 returns the size
+ * of master secret.
+ *
+ * ses : a session from completed TLS/SSL handshake
+ * out : buffer to hold copy of master secret
+ * outSz : size of out buffer
+ * returns : number of bytes copied into out buffer on success
+ *           less then or equal to 0 is considered a failure case
+ */
+int wolfSSL_SESSION_get_master_key(const WOLFSSL_SESSION* ses,
+        unsigned char* out, int outSz)
+{
+    int size;
+
+    if (outSz == 0) {
+        return SECRET_LEN;
+    }
+
+    if (ses == NULL || out == NULL || outSz < 0) {
+        return 0;
+    }
+
+    if (outSz > SECRET_LEN) {
+        size = SECRET_LEN;
+    }
+    else {
+        size = outSz;
+    }
+
+    XMEMCPY(out, ses->masterSecret, size);
+    return size;
+}
+
+
+int wolfSSL_SESSION_get_master_key_length(const WOLFSSL_SESSION* ses)
+{
+    (void)ses;
+    return SECRET_LEN;
+}
+
+#endif /* OPENSSL_EXTRA */
+
+#ifndef NO_FILESYSTEM
+#ifdef HAVE_NTRU
+
+int wolfSSL_CTX_use_NTRUPrivateKey_file(WOLFSSL_CTX* ctx, const char* file)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_use_NTRUPrivateKey_file");
+
+    if (ctx == NULL)
+        return WOLFSSL_FAILURE;
+
+    if (ProcessFile(ctx, file, WOLFSSL_FILETYPE_RAW, PRIVATEKEY_TYPE, NULL, 0,
+                    NULL, GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) {
+        ctx->haveNTRU = 1;
+        return WOLFSSL_SUCCESS;
+    }
+
+    return WOLFSSL_FAILURE;
+}
+
+#endif /* HAVE_NTRU */
+
+
+#endif /* NO_FILESYSTEM */
+
+
+void wolfSSL_CTX_set_verify(WOLFSSL_CTX* ctx, int mode, VerifyCallback vc)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_set_verify");
+    if (ctx == NULL)
+        return;
+
+    if (mode & WOLFSSL_VERIFY_PEER) {
+        ctx->verifyPeer = 1;
+        ctx->verifyNone = 0;  /* in case previously set */
+    }
+
+    if (mode == WOLFSSL_VERIFY_NONE) {
+        ctx->verifyNone = 1;
+        ctx->verifyPeer = 0;  /* in case previously set */
+    }
+
+    if (mode & WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT) {
+        ctx->failNoCert = 1;
+    }
+
+    if (mode & WOLFSSL_VERIFY_FAIL_EXCEPT_PSK) {
+        ctx->failNoCert    = 0; /* fail on all is set to fail on PSK */
+        ctx->failNoCertxPSK = 1;
+    }
+
+    ctx->verifyCallback = vc;
+}
+
+#ifdef OPENSSL_ALL
+void wolfSSL_CTX_set_cert_verify_callback(WOLFSSL_CTX* ctx,
+    CertVerifyCallback cb, void* arg)
+{
+    WOLFSSL_ENTER("SSL_CTX_set_cert_verify_callback");
+    if (ctx == NULL)
+        return;
+
+    ctx->verifyCertCb = cb;
+    ctx->verifyCertCbArg = arg;
+}
+#endif
+
+
+void wolfSSL_set_verify(WOLFSSL* ssl, int mode, VerifyCallback vc)
+{
+    WOLFSSL_ENTER("wolfSSL_set_verify");
+    if (ssl == NULL)
+        return;
+
+    if (mode & WOLFSSL_VERIFY_PEER) {
+        ssl->options.verifyPeer = 1;
+        ssl->options.verifyNone = 0;  /* in case previously set */
+    }
+
+    if (mode == WOLFSSL_VERIFY_NONE) {
+        ssl->options.verifyNone = 1;
+        ssl->options.verifyPeer = 0;  /* in case previously set */
+    }
+
+    if (mode & WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT)
+        ssl->options.failNoCert = 1;
+
+    if (mode & WOLFSSL_VERIFY_FAIL_EXCEPT_PSK) {
+        ssl->options.failNoCert    = 0; /* fail on all is set to fail on PSK */
+        ssl->options.failNoCertxPSK = 1;
+    }
+
+    ssl->verifyCallback = vc;
+}
+
+void wolfSSL_set_verify_result(WOLFSSL *ssl, long v)
+{
+    WOLFSSL_ENTER("wolfSSL_set_verify_result");
+
+    if (ssl == NULL)
+        return;
+
+#ifdef OPENSSL_ALL
+    ssl->verifyCallbackResult = v;
+#else
+    (void)v;
+    WOLFSSL_STUB("wolfSSL_set_verify_result");
+#endif
+}
+
+/* store user ctx for verify callback */
+void wolfSSL_SetCertCbCtx(WOLFSSL* ssl, void* ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_SetCertCbCtx");
+    if (ssl)
+        ssl->verifyCbCtx = ctx;
+}
+
+
+/* store context CA Cache addition callback */
+void wolfSSL_CTX_SetCACb(WOLFSSL_CTX* ctx, CallbackCACache cb)
+{
+    if (ctx && ctx->cm)
+        ctx->cm->caCacheCallback = cb;
+}
+
+
+#if defined(PERSIST_CERT_CACHE)
+
+#if !defined(NO_FILESYSTEM)
+
+/* Persist cert cache to file */
+int wolfSSL_CTX_save_cert_cache(WOLFSSL_CTX* ctx, const char* fname)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_save_cert_cache");
+
+    if (ctx == NULL || fname == NULL)
+        return BAD_FUNC_ARG;
+
+    return CM_SaveCertCache(ctx->cm, fname);
+}
+
+
+/* Persist cert cache from file */
+int wolfSSL_CTX_restore_cert_cache(WOLFSSL_CTX* ctx, const char* fname)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_restore_cert_cache");
+
+    if (ctx == NULL || fname == NULL)
+        return BAD_FUNC_ARG;
+
+    return CM_RestoreCertCache(ctx->cm, fname);
+}
+
+#endif /* NO_FILESYSTEM */
+
+/* Persist cert cache to memory */
+int wolfSSL_CTX_memsave_cert_cache(WOLFSSL_CTX* ctx, void* mem,
+                                   int sz, int* used)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_memsave_cert_cache");
+
+    if (ctx == NULL || mem == NULL || used == NULL || sz <= 0)
+        return BAD_FUNC_ARG;
+
+    return CM_MemSaveCertCache(ctx->cm, mem, sz, used);
+}
+
+
+/* Restore cert cache from memory */
+int wolfSSL_CTX_memrestore_cert_cache(WOLFSSL_CTX* ctx, const void* mem, int sz)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_memrestore_cert_cache");
+
+    if (ctx == NULL || mem == NULL || sz <= 0)
+        return BAD_FUNC_ARG;
+
+    return CM_MemRestoreCertCache(ctx->cm, mem, sz);
+}
+
+
+/* get how big the the cert cache save buffer needs to be */
+int wolfSSL_CTX_get_cert_cache_memsize(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_get_cert_cache_memsize");
+
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    return CM_GetCertCacheMemSize(ctx->cm);
+}
+
+#endif /* PERSIST_CERT_CACHE */
+#endif /* !NO_CERTS */
+
+
+#ifndef NO_SESSION_CACHE
+
+WOLFSSL_ABI
+WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("SSL_get_session");
+    if (ssl)
+        return GetSession(ssl, 0, 1);
+
+    return NULL;
+}
+
+
+WOLFSSL_ABI
+int wolfSSL_set_session(WOLFSSL* ssl, WOLFSSL_SESSION* session)
+{
+    WOLFSSL_ENTER("SSL_set_session");
+    if (session)
+        return SetSession(ssl, session);
+
+    return WOLFSSL_FAILURE;
+}
+
+
+#ifndef NO_CLIENT_CACHE
+
+/* Associate client session with serverID, find existing or store for saving
+   if newSession flag on, don't reuse existing session
+   WOLFSSL_SUCCESS on ok */
+int wolfSSL_SetServerID(WOLFSSL* ssl, const byte* id, int len, int newSession)
+{
+    WOLFSSL_SESSION* session = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_SetServerID");
+
+    if (ssl == NULL || id == NULL || len <= 0)
+        return BAD_FUNC_ARG;
+
+    if (newSession == 0) {
+        session = GetSessionClient(ssl, id, len);
+        if (session) {
+            if (SetSession(ssl, session) != WOLFSSL_SUCCESS) {
+    #ifdef HAVE_EXT_CACHE
+                wolfSSL_SESSION_free(session);
+    #endif
+                WOLFSSL_MSG("SetSession failed");
+                session = NULL;
+            }
+        }
+    }
+
+    if (session == NULL) {
+        WOLFSSL_MSG("Valid ServerID not cached already");
+
+        ssl->session.idLen = (word16)min(SERVER_ID_LEN, (word32)len);
+        XMEMCPY(ssl->session.serverID, id, ssl->session.idLen);
+    }
+    #ifdef HAVE_EXT_CACHE
+    else
+        wolfSSL_SESSION_free(session);
+    #endif
+
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* NO_CLIENT_CACHE */
+
+#if defined(PERSIST_SESSION_CACHE)
+
+/* for persistence, if changes to layout need to increment and modify
+   save_session_cache() and restore_session_cache and memory versions too */
+#define WOLFSSL_CACHE_VERSION 2
+
+/* Session Cache Header information */
+typedef struct {
+    int version;     /* cache layout version id */
+    int rows;        /* session rows */
+    int columns;     /* session columns */
+    int sessionSz;   /* sizeof WOLFSSL_SESSION */
+} cache_header_t;
+
+/* current persistence layout is:
+
+   1) cache_header_t
+   2) SessionCache
+   3) ClientCache
+
+   update WOLFSSL_CACHE_VERSION if change layout for the following
+   PERSISTENT_SESSION_CACHE functions
+*/
+
+
+/* get how big the the session cache save buffer needs to be */
+int wolfSSL_get_session_cache_memsize(void)
+{
+    int sz  = (int)(sizeof(SessionCache) + sizeof(cache_header_t));
+
+    #ifndef NO_CLIENT_CACHE
+        sz += (int)(sizeof(ClientCache));
+    #endif
+
+    return sz;
+}
+
+
+/* Persist session cache to memory */
+int wolfSSL_memsave_session_cache(void* mem, int sz)
+{
+    int i;
+    cache_header_t cache_header;
+    SessionRow*    row  = (SessionRow*)((byte*)mem + sizeof(cache_header));
+#ifndef NO_CLIENT_CACHE
+    ClientRow*     clRow;
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_memsave_session_cache");
+
+    if (sz < wolfSSL_get_session_cache_memsize()) {
+        WOLFSSL_MSG("Memory buffer too small");
+        return BUFFER_E;
+    }
+
+    cache_header.version   = WOLFSSL_CACHE_VERSION;
+    cache_header.rows      = SESSION_ROWS;
+    cache_header.columns   = SESSIONS_PER_ROW;
+    cache_header.sessionSz = (int)sizeof(WOLFSSL_SESSION);
+    XMEMCPY(mem, &cache_header, sizeof(cache_header));
+
+    if (wc_LockMutex(&session_mutex) != 0) {
+        WOLFSSL_MSG("Session cache mutex lock failed");
+        return BAD_MUTEX_E;
+    }
+
+    for (i = 0; i < cache_header.rows; ++i)
+        XMEMCPY(row++, SessionCache + i, sizeof(SessionRow));
+
+#ifndef NO_CLIENT_CACHE
+    clRow = (ClientRow*)row;
+    for (i = 0; i < cache_header.rows; ++i)
+        XMEMCPY(clRow++, ClientCache + i, sizeof(ClientRow));
+#endif
+
+    wc_UnLockMutex(&session_mutex);
+
+    WOLFSSL_LEAVE("wolfSSL_memsave_session_cache", WOLFSSL_SUCCESS);
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* Restore the persistent session cache from memory */
+int wolfSSL_memrestore_session_cache(const void* mem, int sz)
+{
+    int    i;
+    cache_header_t cache_header;
+    SessionRow*    row  = (SessionRow*)((byte*)mem + sizeof(cache_header));
+#ifndef NO_CLIENT_CACHE
+    ClientRow*     clRow;
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_memrestore_session_cache");
+
+    if (sz < wolfSSL_get_session_cache_memsize()) {
+        WOLFSSL_MSG("Memory buffer too small");
+        return BUFFER_E;
+    }
+
+    XMEMCPY(&cache_header, mem, sizeof(cache_header));
+    if (cache_header.version   != WOLFSSL_CACHE_VERSION ||
+        cache_header.rows      != SESSION_ROWS ||
+        cache_header.columns   != SESSIONS_PER_ROW ||
+        cache_header.sessionSz != (int)sizeof(WOLFSSL_SESSION)) {
+
+        WOLFSSL_MSG("Session cache header match failed");
+        return CACHE_MATCH_ERROR;
+    }
+
+    if (wc_LockMutex(&session_mutex) != 0) {
+        WOLFSSL_MSG("Session cache mutex lock failed");
+        return BAD_MUTEX_E;
+    }
+
+    for (i = 0; i < cache_header.rows; ++i)
+        XMEMCPY(SessionCache + i, row++, sizeof(SessionRow));
+
+#ifndef NO_CLIENT_CACHE
+    clRow = (ClientRow*)row;
+    for (i = 0; i < cache_header.rows; ++i)
+        XMEMCPY(ClientCache + i, clRow++, sizeof(ClientRow));
+#endif
+
+    wc_UnLockMutex(&session_mutex);
+
+    WOLFSSL_LEAVE("wolfSSL_memrestore_session_cache", WOLFSSL_SUCCESS);
+
+    return WOLFSSL_SUCCESS;
+}
+
+#if !defined(NO_FILESYSTEM)
+
+/* Persist session cache to file */
+/* doesn't use memsave because of additional memory use */
+int wolfSSL_save_session_cache(const char *fname)
+{
+    XFILE  file;
+    int    ret;
+    int    rc = WOLFSSL_SUCCESS;
+    int    i;
+    cache_header_t cache_header;
+
+    WOLFSSL_ENTER("wolfSSL_save_session_cache");
+
+    file = XFOPEN(fname, "w+b");
+    if (file == XBADFILE) {
+        WOLFSSL_MSG("Couldn't open session cache save file");
+        return WOLFSSL_BAD_FILE;
+    }
+    cache_header.version   = WOLFSSL_CACHE_VERSION;
+    cache_header.rows      = SESSION_ROWS;
+    cache_header.columns   = SESSIONS_PER_ROW;
+    cache_header.sessionSz = (int)sizeof(WOLFSSL_SESSION);
+
+    /* cache header */
+    ret = (int)XFWRITE(&cache_header, sizeof cache_header, 1, file);
+    if (ret != 1) {
+        WOLFSSL_MSG("Session cache header file write failed");
+        XFCLOSE(file);
+        return FWRITE_ERROR;
+    }
+
+    if (wc_LockMutex(&session_mutex) != 0) {
+        WOLFSSL_MSG("Session cache mutex lock failed");
+        XFCLOSE(file);
+        return BAD_MUTEX_E;
+    }
+
+    /* session cache */
+    for (i = 0; i < cache_header.rows; ++i) {
+        ret = (int)XFWRITE(SessionCache + i, sizeof(SessionRow), 1, file);
+        if (ret != 1) {
+            WOLFSSL_MSG("Session cache member file write failed");
+            rc = FWRITE_ERROR;
+            break;
+        }
+    }
+
+#ifndef NO_CLIENT_CACHE
+    /* client cache */
+    for (i = 0; i < cache_header.rows; ++i) {
+        ret = (int)XFWRITE(ClientCache + i, sizeof(ClientRow), 1, file);
+        if (ret != 1) {
+            WOLFSSL_MSG("Client cache member file write failed");
+            rc = FWRITE_ERROR;
+            break;
+        }
+    }
+#endif /* NO_CLIENT_CACHE */
+
+    wc_UnLockMutex(&session_mutex);
+
+    XFCLOSE(file);
+    WOLFSSL_LEAVE("wolfSSL_save_session_cache", rc);
+
+    return rc;
+}
+
+
+/* Restore the persistent session cache from file */
+/* doesn't use memstore because of additional memory use */
+int wolfSSL_restore_session_cache(const char *fname)
+{
+    XFILE  file;
+    int    rc = WOLFSSL_SUCCESS;
+    int    ret;
+    int    i;
+    cache_header_t cache_header;
+
+    WOLFSSL_ENTER("wolfSSL_restore_session_cache");
+
+    file = XFOPEN(fname, "rb");
+    if (file == XBADFILE) {
+        WOLFSSL_MSG("Couldn't open session cache save file");
+        return WOLFSSL_BAD_FILE;
+    }
+    /* cache header */
+    ret = (int)XFREAD(&cache_header, sizeof cache_header, 1, file);
+    if (ret != 1) {
+        WOLFSSL_MSG("Session cache header file read failed");
+        XFCLOSE(file);
+        return FREAD_ERROR;
+    }
+    if (cache_header.version   != WOLFSSL_CACHE_VERSION ||
+        cache_header.rows      != SESSION_ROWS ||
+        cache_header.columns   != SESSIONS_PER_ROW ||
+        cache_header.sessionSz != (int)sizeof(WOLFSSL_SESSION)) {
+
+        WOLFSSL_MSG("Session cache header match failed");
+        XFCLOSE(file);
+        return CACHE_MATCH_ERROR;
+    }
+
+    if (wc_LockMutex(&session_mutex) != 0) {
+        WOLFSSL_MSG("Session cache mutex lock failed");
+        XFCLOSE(file);
+        return BAD_MUTEX_E;
+    }
+
+    /* session cache */
+    for (i = 0; i < cache_header.rows; ++i) {
+        ret = (int)XFREAD(SessionCache + i, sizeof(SessionRow), 1, file);
+        if (ret != 1) {
+            WOLFSSL_MSG("Session cache member file read failed");
+            XMEMSET(SessionCache, 0, sizeof SessionCache);
+            rc = FREAD_ERROR;
+            break;
+        }
+    }
+
+#ifndef NO_CLIENT_CACHE
+    /* client cache */
+    for (i = 0; i < cache_header.rows; ++i) {
+        ret = (int)XFREAD(ClientCache + i, sizeof(ClientRow), 1, file);
+        if (ret != 1) {
+            WOLFSSL_MSG("Client cache member file read failed");
+            XMEMSET(ClientCache, 0, sizeof ClientCache);
+            rc = FREAD_ERROR;
+            break;
+        }
+    }
+
+#endif /* NO_CLIENT_CACHE */
+
+    wc_UnLockMutex(&session_mutex);
+
+    XFCLOSE(file);
+    WOLFSSL_LEAVE("wolfSSL_restore_session_cache", rc);
+
+    return rc;
+}
+
+#endif /* !NO_FILESYSTEM */
+#endif /* PERSIST_SESSION_CACHE */
+#endif /* NO_SESSION_CACHE */
+
+
+void wolfSSL_load_error_strings(void)   /* compatibility only */
+{}
+
+
+int wolfSSL_library_init(void)
+{
+    WOLFSSL_ENTER("SSL_library_init");
+    if (wolfSSL_Init() == WOLFSSL_SUCCESS)
+        return WOLFSSL_SUCCESS;
+    else
+        return WOLFSSL_FATAL_ERROR;
+}
+
+
+#ifdef HAVE_SECRET_CALLBACK
+
+int wolfSSL_set_session_secret_cb(WOLFSSL* ssl, SessionSecretCb cb, void* ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_set_session_secret_cb");
+    if (ssl == NULL)
+        return WOLFSSL_FATAL_ERROR;
+
+    ssl->sessionSecretCb = cb;
+    ssl->sessionSecretCtx = ctx;
+    /* If using a pre-set key, assume session resumption. */
+    ssl->session.sessionIDSz = 0;
+    ssl->options.resuming = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+#endif
+
+
+#ifndef NO_SESSION_CACHE
+
+/* on by default if built in but allow user to turn off */
+WOLFSSL_ABI
+long wolfSSL_CTX_set_session_cache_mode(WOLFSSL_CTX* ctx, long mode)
+{
+    WOLFSSL_ENTER("SSL_CTX_set_session_cache_mode");
+    if (mode == WOLFSSL_SESS_CACHE_OFF)
+        ctx->sessionCacheOff = 1;
+
+    if ((mode & WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR) != 0)
+        ctx->sessionCacheFlushOff = 1;
+
+#ifdef HAVE_EXT_CACHE
+    if ((mode & WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE) != 0)
+        ctx->internalCacheOff = 1;
+#endif
+
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* NO_SESSION_CACHE */
+
+
+#if !defined(NO_CERTS)
+#if defined(PERSIST_CERT_CACHE)
+
+
+#define WOLFSSL_CACHE_CERT_VERSION 1
+
+typedef struct {
+    int version;                 /* cache cert layout version id */
+    int rows;                    /* hash table rows, CA_TABLE_SIZE */
+    int columns[CA_TABLE_SIZE];  /* columns per row on list */
+    int signerSz;                /* sizeof Signer object */
+} CertCacheHeader;
+
+/* current cert persistence layout is:
+
+   1) CertCacheHeader
+   2) caTable
+
+   update WOLFSSL_CERT_CACHE_VERSION if change layout for the following
+   PERSIST_CERT_CACHE functions
+*/
+
+
+/* Return memory needed to persist this signer, have lock */
+static WC_INLINE int GetSignerMemory(Signer* signer)
+{
+    int sz = sizeof(signer->pubKeySize) + sizeof(signer->keyOID)
+           + sizeof(signer->nameLen)    + sizeof(signer->subjectNameHash);
+
+#if !defined(NO_SKID)
+        sz += (int)sizeof(signer->subjectKeyIdHash);
+#endif
+
+    /* add dynamic bytes needed */
+    sz += signer->pubKeySize;
+    sz += signer->nameLen;
+
+    return sz;
+}
+
+
+/* Return memory needed to persist this row, have lock */
+static WC_INLINE int GetCertCacheRowMemory(Signer* row)
+{
+    int sz = 0;
+
+    while (row) {
+        sz += GetSignerMemory(row);
+        row = row->next;
+    }
+
+    return sz;
+}
+
+
+/* get the size of persist cert cache, have lock */
+static WC_INLINE int GetCertCacheMemSize(WOLFSSL_CERT_MANAGER* cm)
+{
+    int sz;
+    int i;
+
+    sz = sizeof(CertCacheHeader);
+
+    for (i = 0; i < CA_TABLE_SIZE; i++)
+        sz += GetCertCacheRowMemory(cm->caTable[i]);
+
+    return sz;
+}
+
+
+/* Store cert cache header columns with number of items per list, have lock */
+static WC_INLINE void SetCertHeaderColumns(WOLFSSL_CERT_MANAGER* cm, int* columns)
+{
+    int     i;
+    Signer* row;
+
+    for (i = 0; i < CA_TABLE_SIZE; i++) {
+        int count = 0;
+        row = cm->caTable[i];
+
+        while (row) {
+            ++count;
+            row = row->next;
+        }
+        columns[i] = count;
+    }
+}
+
+
+/* Restore whole cert row from memory, have lock, return bytes consumed,
+   < 0 on error, have lock */
+static WC_INLINE int RestoreCertRow(WOLFSSL_CERT_MANAGER* cm, byte* current,
+                                 int row, int listSz, const byte* end)
+{
+    int idx = 0;
+
+    if (listSz < 0) {
+        WOLFSSL_MSG("Row header corrupted, negative value");
+        return PARSE_ERROR;
+    }
+
+    while (listSz) {
+        Signer* signer;
+        byte*   publicKey;
+        byte*   start = current + idx;  /* for end checks on this signer */
+        int     minSz = sizeof(signer->pubKeySize) + sizeof(signer->keyOID) +
+                      sizeof(signer->nameLen) + sizeof(signer->subjectNameHash);
+        #ifndef NO_SKID
+                minSz += (int)sizeof(signer->subjectKeyIdHash);
+        #endif
+
+        if (start + minSz > end) {
+            WOLFSSL_MSG("Would overread restore buffer");
+            return BUFFER_E;
+        }
+        signer = MakeSigner(cm->heap);
+        if (signer == NULL)
+            return MEMORY_E;
+
+        /* pubKeySize */
+        XMEMCPY(&signer->pubKeySize, current + idx, sizeof(signer->pubKeySize));
+        idx += (int)sizeof(signer->pubKeySize);
+
+        /* keyOID */
+        XMEMCPY(&signer->keyOID, current + idx, sizeof(signer->keyOID));
+        idx += (int)sizeof(signer->keyOID);
+
+        /* pulicKey */
+        if (start + minSz + signer->pubKeySize > end) {
+            WOLFSSL_MSG("Would overread restore buffer");
+            FreeSigner(signer, cm->heap);
+            return BUFFER_E;
+        }
+        publicKey = (byte*)XMALLOC(signer->pubKeySize, cm->heap,
+                                   DYNAMIC_TYPE_KEY);
+        if (publicKey == NULL) {
+            FreeSigner(signer, cm->heap);
+            return MEMORY_E;
+        }
+
+        XMEMCPY(publicKey, current + idx, signer->pubKeySize);
+        signer->publicKey = publicKey;
+        idx += signer->pubKeySize;
+
+        /* nameLen */
+        XMEMCPY(&signer->nameLen, current + idx, sizeof(signer->nameLen));
+        idx += (int)sizeof(signer->nameLen);
+
+        /* name */
+        if (start + minSz + signer->pubKeySize + signer->nameLen > end) {
+            WOLFSSL_MSG("Would overread restore buffer");
+            FreeSigner(signer, cm->heap);
+            return BUFFER_E;
+        }
+        signer->name = (char*)XMALLOC(signer->nameLen, cm->heap,
+                                      DYNAMIC_TYPE_SUBJECT_CN);
+        if (signer->name == NULL) {
+            FreeSigner(signer, cm->heap);
+            return MEMORY_E;
+        }
+
+        XMEMCPY(signer->name, current + idx, signer->nameLen);
+        idx += signer->nameLen;
+
+        /* subjectNameHash */
+        XMEMCPY(signer->subjectNameHash, current + idx, SIGNER_DIGEST_SIZE);
+        idx += SIGNER_DIGEST_SIZE;
+
+        #ifndef NO_SKID
+            /* subjectKeyIdHash */
+            XMEMCPY(signer->subjectKeyIdHash, current + idx,SIGNER_DIGEST_SIZE);
+            idx += SIGNER_DIGEST_SIZE;
+        #endif
+
+        signer->next = cm->caTable[row];
+        cm->caTable[row] = signer;
+
+        --listSz;
+    }
+
+    return idx;
+}
+
+
+/* Store whole cert row into memory, have lock, return bytes added */
+static WC_INLINE int StoreCertRow(WOLFSSL_CERT_MANAGER* cm, byte* current, int row)
+{
+    int     added  = 0;
+    Signer* list   = cm->caTable[row];
+
+    while (list) {
+        XMEMCPY(current + added, &list->pubKeySize, sizeof(list->pubKeySize));
+        added += (int)sizeof(list->pubKeySize);
+
+        XMEMCPY(current + added, &list->keyOID,     sizeof(list->keyOID));
+        added += (int)sizeof(list->keyOID);
+
+        XMEMCPY(current + added, list->publicKey, list->pubKeySize);
+        added += list->pubKeySize;
+
+        XMEMCPY(current + added, &list->nameLen, sizeof(list->nameLen));
+        added += (int)sizeof(list->nameLen);
+
+        XMEMCPY(current + added, list->name, list->nameLen);
+        added += list->nameLen;
+
+        XMEMCPY(current + added, list->subjectNameHash, SIGNER_DIGEST_SIZE);
+        added += SIGNER_DIGEST_SIZE;
+
+        #ifndef NO_SKID
+            XMEMCPY(current + added, list->subjectKeyIdHash,SIGNER_DIGEST_SIZE);
+            added += SIGNER_DIGEST_SIZE;
+        #endif
+
+        list = list->next;
+    }
+
+    return added;
+}
+
+
+/* Persist cert cache to memory, have lock */
+static WC_INLINE int DoMemSaveCertCache(WOLFSSL_CERT_MANAGER* cm,
+                                     void* mem, int sz)
+{
+    int realSz;
+    int ret = WOLFSSL_SUCCESS;
+    int i;
+
+    WOLFSSL_ENTER("DoMemSaveCertCache");
+
+    realSz = GetCertCacheMemSize(cm);
+    if (realSz > sz) {
+        WOLFSSL_MSG("Mem output buffer too small");
+        ret = BUFFER_E;
+    }
+    else {
+        byte*           current;
+        CertCacheHeader hdr;
+
+        hdr.version  = WOLFSSL_CACHE_CERT_VERSION;
+        hdr.rows     = CA_TABLE_SIZE;
+        SetCertHeaderColumns(cm, hdr.columns);
+        hdr.signerSz = (int)sizeof(Signer);
+
+        XMEMCPY(mem, &hdr, sizeof(CertCacheHeader));
+        current = (byte*)mem + sizeof(CertCacheHeader);
+
+        for (i = 0; i < CA_TABLE_SIZE; ++i)
+            current += StoreCertRow(cm, current, i);
+    }
+
+    return ret;
+}
+
+
+#if !defined(NO_FILESYSTEM)
+
+/* Persist cert cache to file */
+int CM_SaveCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
+{
+    XFILE file;
+    int   rc = WOLFSSL_SUCCESS;
+    int   memSz;
+    byte* mem;
+
+    WOLFSSL_ENTER("CM_SaveCertCache");
+
+    file = XFOPEN(fname, "w+b");
+    if (file == XBADFILE) {
+       WOLFSSL_MSG("Couldn't open cert cache save file");
+       return WOLFSSL_BAD_FILE;
+    }
+
+    if (wc_LockMutex(&cm->caLock) != 0) {
+        WOLFSSL_MSG("wc_LockMutex on caLock failed");
+        XFCLOSE(file);
+        return BAD_MUTEX_E;
+    }
+
+    memSz = GetCertCacheMemSize(cm);
+    mem   = (byte*)XMALLOC(memSz, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (mem == NULL) {
+        WOLFSSL_MSG("Alloc for tmp buffer failed");
+        rc = MEMORY_E;
+    } else {
+        rc = DoMemSaveCertCache(cm, mem, memSz);
+        if (rc == WOLFSSL_SUCCESS) {
+            int ret = (int)XFWRITE(mem, memSz, 1, file);
+            if (ret != 1) {
+                WOLFSSL_MSG("Cert cache file write failed");
+                rc = FWRITE_ERROR;
+            }
+        }
+        XFREE(mem, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+
+    wc_UnLockMutex(&cm->caLock);
+    XFCLOSE(file);
+
+    return rc;
+}
+
+
+/* Restore cert cache from file */
+int CM_RestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
+{
+    XFILE file;
+    int   rc = WOLFSSL_SUCCESS;
+    int   ret;
+    int   memSz;
+    byte* mem;
+
+    WOLFSSL_ENTER("CM_RestoreCertCache");
+
+    file = XFOPEN(fname, "rb");
+    if (file == XBADFILE) {
+       WOLFSSL_MSG("Couldn't open cert cache save file");
+       return WOLFSSL_BAD_FILE;
+    }
+
+    if(XFSEEK(file, 0, XSEEK_END) != 0) {
+        XFCLOSE(file);
+        return WOLFSSL_BAD_FILE;
+    }
+    memSz = (int)XFTELL(file);
+    XREWIND(file);
+
+    if (memSz > MAX_WOLFSSL_FILE_SIZE || memSz <= 0) {
+        WOLFSSL_MSG("CM_RestoreCertCache file size error");
+        XFCLOSE(file);
+        return WOLFSSL_BAD_FILE;
+    }
+
+    mem = (byte*)XMALLOC(memSz, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (mem == NULL) {
+        WOLFSSL_MSG("Alloc for tmp buffer failed");
+        XFCLOSE(file);
+        return MEMORY_E;
+    }
+
+    ret = (int)XFREAD(mem, memSz, 1, file);
+    if (ret != 1) {
+        WOLFSSL_MSG("Cert file read error");
+        rc = FREAD_ERROR;
+    } else {
+        rc = CM_MemRestoreCertCache(cm, mem, memSz);
+        if (rc != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("Mem restore cert cache failed");
+        }
+    }
+
+    XFREE(mem, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    XFCLOSE(file);
+
+    return rc;
+}
+
+#endif /* NO_FILESYSTEM */
+
+
+/* Persist cert cache to memory */
+int CM_MemSaveCertCache(WOLFSSL_CERT_MANAGER* cm, void* mem, int sz, int* used)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("CM_MemSaveCertCache");
+
+    if (wc_LockMutex(&cm->caLock) != 0) {
+        WOLFSSL_MSG("wc_LockMutex on caLock failed");
+        return BAD_MUTEX_E;
+    }
+
+    ret = DoMemSaveCertCache(cm, mem, sz);
+    if (ret == WOLFSSL_SUCCESS)
+        *used  = GetCertCacheMemSize(cm);
+
+    wc_UnLockMutex(&cm->caLock);
+
+    return ret;
+}
+
+
+/* Restore cert cache from memory */
+int CM_MemRestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const void* mem, int sz)
+{
+    int ret = WOLFSSL_SUCCESS;
+    int i;
+    CertCacheHeader* hdr = (CertCacheHeader*)mem;
+    byte*            current = (byte*)mem + sizeof(CertCacheHeader);
+    byte*            end     = (byte*)mem + sz;  /* don't go over */
+
+    WOLFSSL_ENTER("CM_MemRestoreCertCache");
+
+    if (current > end) {
+        WOLFSSL_MSG("Cert Cache Memory buffer too small");
+        return BUFFER_E;
+    }
+
+    if (hdr->version  != WOLFSSL_CACHE_CERT_VERSION ||
+        hdr->rows     != CA_TABLE_SIZE ||
+        hdr->signerSz != (int)sizeof(Signer)) {
+
+        WOLFSSL_MSG("Cert Cache Memory header mismatch");
+        return CACHE_MATCH_ERROR;
+    }
+
+    if (wc_LockMutex(&cm->caLock) != 0) {
+        WOLFSSL_MSG("wc_LockMutex on caLock failed");
+        return BAD_MUTEX_E;
+    }
+
+    FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
+
+    for (i = 0; i < CA_TABLE_SIZE; ++i) {
+        int added = RestoreCertRow(cm, current, i, hdr->columns[i], end);
+        if (added < 0) {
+            WOLFSSL_MSG("RestoreCertRow error");
+            ret = added;
+            break;
+        }
+        current += added;
+    }
+
+    wc_UnLockMutex(&cm->caLock);
+
+    return ret;
+}
+
+
+/* get how big the the cert cache save buffer needs to be */
+int CM_GetCertCacheMemSize(WOLFSSL_CERT_MANAGER* cm)
+{
+    int sz;
+
+    WOLFSSL_ENTER("CM_GetCertCacheMemSize");
+
+    if (wc_LockMutex(&cm->caLock) != 0) {
+        WOLFSSL_MSG("wc_LockMutex on caLock failed");
+        return BAD_MUTEX_E;
+    }
+
+    sz = GetCertCacheMemSize(cm);
+
+    wc_UnLockMutex(&cm->caLock);
+
+    return sz;
+}
+
+#endif /* PERSIST_CERT_CACHE */
+#endif /* NO_CERTS */
+
+#ifdef OPENSSL_EXTRA
+
+
+/* removes all cipher suites from the list that contain "toRemove"
+ * returns the new list size on success
+ */
+static int wolfSSL_remove_ciphers(char* list, int sz, const char* toRemove)
+{
+    int idx = 0;
+    char* next = (char*)list;
+    int totalSz = sz;
+
+    if (list == NULL) {
+        return 0;
+    }
+
+    do {
+        char*  current = next;
+        char   name[MAX_SUITE_NAME + 1];
+        word32 length;
+
+        next   = XSTRSTR(next, ":");
+        length = min(sizeof(name), !next ? (word32)XSTRLEN(current) /* last */
+                                         : (word32)(next - current));
+
+        XSTRNCPY(name, current, length);
+        name[(length == sizeof(name)) ? length - 1 : length] = 0;
+
+        if (XSTRSTR(name, toRemove)) {
+            XMEMMOVE(list + idx, list + idx + length, totalSz - (idx + length));
+            totalSz -= length;
+            list[totalSz] = '\0';
+            next = current;
+        }
+        else {
+            idx += length;
+        }
+    } while (next++); /* ++ needed to skip ':' */
+
+    return totalSz;
+}
+
+/* parse some bulk lists like !eNULL / !aNULL
+ *
+ * returns WOLFSSL_SUCCESS on success and sets the cipher suite list
+ */
+static int wolfSSL_parse_cipher_list(WOLFSSL_CTX* ctx, Suites* suites,
+        const char* list)
+{
+    int       ret          = 0;
+    const int suiteSz      = GetCipherNamesSize();
+    char*     next         = (char*)list;
+    const CipherSuiteInfo* names = GetCipherNames();
+    char*     localList    = NULL;
+    int sz = 0;
+
+    if (suites == NULL || list == NULL) {
+        WOLFSSL_MSG("NULL argument");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* does list contain eNULL or aNULL? */
+    if (XSTRSTR(list, "aNULL") || XSTRSTR(list, "eNULL")) {
+        do {
+            char*  current = next;
+            char   name[MAX_SUITE_NAME + 1];
+            int    i;
+            word32 length;
+
+            next   = XSTRSTR(next, ":");
+            length = min(sizeof(name), !next ? (word32)XSTRLEN(current) /*last*/
+                                             : (word32)(next - current));
+
+            XSTRNCPY(name, current, length);
+            name[(length == sizeof(name)) ? length - 1 : length] = 0;
+
+            /* check for "not" case */
+            if (name[0] == '!' && suiteSz > 0) {
+                /* populate list with all suites if not already created */
+                if (localList == NULL) {
+                    for (i = 0; i < suiteSz; i++) {
+                        sz += (int)XSTRLEN(names[i].name) + 2;
+                    }
+                    localList = (char*)XMALLOC(sz, ctx->heap,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+                    if (localList == NULL) {
+                        return WOLFSSL_FAILURE;
+                    }
+                    wolfSSL_get_ciphers(localList, sz);
+                    sz = (int)XSTRLEN(localList);
+                }
+
+                if (XSTRSTR(name, "eNULL")) {
+                    wolfSSL_remove_ciphers(localList, sz, "-NULL");
+                }
+            }
+        }
+        while (next++); /* ++ needed to skip ':' */
+
+        ret = SetCipherList(ctx, suites, localList);
+        XFREE(localList, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return (ret)? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
+    }
+    else {
+        return (SetCipherList(ctx, suites, list)) ? WOLFSSL_SUCCESS :
+            WOLFSSL_FAILURE;
+    }
+}
+
+#endif
+
+
+int wolfSSL_CTX_set_cipher_list(WOLFSSL_CTX* ctx, const char* list)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_set_cipher_list");
+
+    if (ctx == NULL)
+        return WOLFSSL_FAILURE;
+
+    /* alloc/init on demand only */
+    if (ctx->suites == NULL) {
+        ctx->suites = (Suites*)XMALLOC(sizeof(Suites), ctx->heap,
+                                       DYNAMIC_TYPE_SUITES);
+        if (ctx->suites == NULL) {
+            WOLFSSL_MSG("Memory alloc for Suites failed");
+            return WOLFSSL_FAILURE;
+        }
+        XMEMSET(ctx->suites, 0, sizeof(Suites));
+    }
+
+#ifdef OPENSSL_EXTRA
+    return wolfSSL_parse_cipher_list(ctx, ctx->suites, list);
+#else
+    return (SetCipherList(ctx, ctx->suites, list)) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
+#endif
+}
+
+
+int wolfSSL_set_cipher_list(WOLFSSL* ssl, const char* list)
+{
+    WOLFSSL_ENTER("wolfSSL_set_cipher_list");
+#ifdef SINGLE_THREADED
+    if (ssl->ctx->suites == ssl->suites) {
+        ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap,
+                                       DYNAMIC_TYPE_SUITES);
+        if (ssl->suites == NULL) {
+            WOLFSSL_MSG("Suites Memory error");
+            return MEMORY_E;
+        }
+        ssl->options.ownSuites = 1;
+    }
+#endif
+
+#ifdef OPENSSL_EXTRA
+    return wolfSSL_parse_cipher_list(ssl->ctx, ssl->suites, list);
+#else
+    return (SetCipherList(ssl->ctx, ssl->suites, list)) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
+#endif
+}
+
+
+int wolfSSL_dtls_get_using_nonblock(WOLFSSL* ssl)
+{
+    int useNb = 0;
+
+    if (ssl == NULL)
+        return WOLFSSL_FAILURE;
+
+    WOLFSSL_ENTER("wolfSSL_dtls_get_using_nonblock");
+    if (ssl->options.dtls) {
+#ifdef WOLFSSL_DTLS
+        useNb = ssl->options.dtlsUseNonblock;
+#endif
+    }
+    else {
+        WOLFSSL_MSG("wolfSSL_dtls_get_using_nonblock() is "
+                    "DEPRECATED for non-DTLS use.");
+    }
+    return useNb;
+}
+
+
+#ifndef WOLFSSL_LEANPSK
+
+void wolfSSL_dtls_set_using_nonblock(WOLFSSL* ssl, int nonblock)
+{
+    (void)nonblock;
+
+    WOLFSSL_ENTER("wolfSSL_dtls_set_using_nonblock");
+
+    if (ssl == NULL)
+        return;
+
+    if (ssl->options.dtls) {
+#ifdef WOLFSSL_DTLS
+        ssl->options.dtlsUseNonblock = (nonblock != 0);
+#endif
+    }
+    else {
+        WOLFSSL_MSG("wolfSSL_dtls_set_using_nonblock() is "
+                    "DEPRECATED for non-DTLS use.");
+    }
+}
+
+
+#ifdef WOLFSSL_DTLS
+
+int wolfSSL_dtls_get_current_timeout(WOLFSSL* ssl)
+{
+    int timeout = 0;
+    if (ssl)
+        timeout = ssl->dtls_timeout;
+
+    WOLFSSL_LEAVE("wolfSSL_dtls_get_current_timeout()", timeout);
+    return timeout;
+}
+
+int wolfSSL_DTLSv1_get_timeout(WOLFSSL* ssl, WOLFSSL_TIMEVAL* timeleft)
+{
+    if (ssl && timeleft) {
+        XMEMSET(timeleft, 0, sizeof(WOLFSSL_TIMEVAL));
+        timeleft->tv_sec = ssl->dtls_timeout;
+    }
+    return 0;
+}
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_DTLSv1_handle_timeout(WOLFSSL* ssl)
+{
+    WOLFSSL_STUB("SSL_DTLSv1_handle_timeout");
+    (void)ssl;
+    return 0;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_DTLSv1_set_initial_timeout_duration(WOLFSSL* ssl, word32 duration_ms)
+{
+    WOLFSSL_STUB("SSL_DTLSv1_set_initial_timeout_duration");
+    (void)ssl;
+    (void)duration_ms;
+}
+#endif
+
+/* user may need to alter init dtls recv timeout, WOLFSSL_SUCCESS on ok */
+int wolfSSL_dtls_set_timeout_init(WOLFSSL* ssl, int timeout)
+{
+    if (ssl == NULL || timeout < 0)
+        return BAD_FUNC_ARG;
+
+    if (timeout > ssl->dtls_timeout_max) {
+        WOLFSSL_MSG("Can't set dtls timeout init greater than dtls timeout max");
+        return BAD_FUNC_ARG;
+    }
+
+    ssl->dtls_timeout_init = timeout;
+    ssl->dtls_timeout = timeout;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* user may need to alter max dtls recv timeout, WOLFSSL_SUCCESS on ok */
+int wolfSSL_dtls_set_timeout_max(WOLFSSL* ssl, int timeout)
+{
+    if (ssl == NULL || timeout < 0)
+        return BAD_FUNC_ARG;
+
+    if (timeout < ssl->dtls_timeout_init) {
+        WOLFSSL_MSG("Can't set dtls timeout max less than dtls timeout init");
+        return BAD_FUNC_ARG;
+    }
+
+    ssl->dtls_timeout_max = timeout;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_dtls_got_timeout(WOLFSSL* ssl)
+{
+    int result = WOLFSSL_SUCCESS;
+    WOLFSSL_ENTER("wolfSSL_dtls_got_timeout()");
+
+    if (ssl == NULL)
+        return WOLFSSL_FATAL_ERROR;
+
+    if (!ssl->options.handShakeDone &&
+        (DtlsMsgPoolTimeout(ssl) < 0 || DtlsMsgPoolSend(ssl, 0) < 0)) {
+
+        result = WOLFSSL_FATAL_ERROR;
+    }
+
+    WOLFSSL_LEAVE("wolfSSL_dtls_got_timeout()", result);
+    return result;
+}
+
+
+/* retransmit all the saves messages, WOLFSSL_SUCCESS on ok */
+int wolfSSL_dtls_retransmit(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_dtls_retransmit()");
+
+    if (ssl == NULL)
+        return WOLFSSL_FATAL_ERROR;
+
+    if (!ssl->options.handShakeDone) {
+        int result = DtlsMsgPoolSend(ssl, 0);
+        if (result < 0) {
+            ssl->error = result;
+            WOLFSSL_ERROR(result);
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+
+    return 0;
+}
+
+#endif /* DTLS */
+#endif /* LEANPSK */
+
+
+#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
+
+/* Not an SSL function, return 0 for success, error code otherwise */
+/* Prereq: ssl's RNG needs to be initialized. */
+int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
+                                 const byte* secret, word32 secretSz)
+{
+    int ret = 0;
+
+    WOLFSSL_ENTER("wolfSSL_DTLS_SetCookieSecret");
+
+    if (ssl == NULL) {
+        WOLFSSL_MSG("need a SSL object");
+        return BAD_FUNC_ARG;
+    }
+
+    if (secret != NULL && secretSz == 0) {
+        WOLFSSL_MSG("can't have a new secret without a size");
+        return BAD_FUNC_ARG;
+    }
+
+    /* If secretSz is 0, use the default size. */
+    if (secretSz == 0)
+        secretSz = COOKIE_SECRET_SZ;
+
+    if (secretSz != ssl->buffers.dtlsCookieSecret.length) {
+        byte* newSecret;
+
+        if (ssl->buffers.dtlsCookieSecret.buffer != NULL) {
+            ForceZero(ssl->buffers.dtlsCookieSecret.buffer,
+                      ssl->buffers.dtlsCookieSecret.length);
+            XFREE(ssl->buffers.dtlsCookieSecret.buffer,
+                  ssl->heap, DYNAMIC_TYPE_NONE);
+        }
+
+        newSecret = (byte*)XMALLOC(secretSz, ssl->heap,DYNAMIC_TYPE_COOKIE_PWD);
+        if (newSecret == NULL) {
+            ssl->buffers.dtlsCookieSecret.buffer = NULL;
+            ssl->buffers.dtlsCookieSecret.length = 0;
+            WOLFSSL_MSG("couldn't allocate new cookie secret");
+            return MEMORY_ERROR;
+        }
+        ssl->buffers.dtlsCookieSecret.buffer = newSecret;
+        ssl->buffers.dtlsCookieSecret.length = secretSz;
+    }
+
+    /* If the supplied secret is NULL, randomly generate a new secret. */
+    if (secret == NULL) {
+        ret = wc_RNG_GenerateBlock(ssl->rng,
+                             ssl->buffers.dtlsCookieSecret.buffer, secretSz);
+    }
+    else
+        XMEMCPY(ssl->buffers.dtlsCookieSecret.buffer, secret, secretSz);
+
+    WOLFSSL_LEAVE("wolfSSL_DTLS_SetCookieSecret", 0);
+    return ret;
+}
+
+#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */
+
+
+/* EITHER SIDE METHODS */
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
+    WOLFSSL_METHOD* wolfSSLv23_method(void)
+    {
+        return wolfSSLv23_method_ex(NULL);
+    }
+    WOLFSSL_METHOD* wolfSSLv23_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* m = NULL;
+        WOLFSSL_ENTER("SSLv23_method");
+    #if !defined(NO_WOLFSSL_CLIENT)
+        m = wolfSSLv23_client_method_ex(heap);
+    #elif !defined(NO_WOLFSSL_SERVER)
+        m = wolfSSLv23_server_method_ex(heap);
+    #endif
+        if (m != NULL) {
+            m->side = WOLFSSL_NEITHER_END;
+        }
+
+        return m;
+    }
+
+    #ifdef WOLFSSL_ALLOW_SSLV3
+    WOLFSSL_METHOD* wolfSSLv3_method(void)
+    {
+        return wolfSSLv3_method_ex(NULL);
+    }
+    WOLFSSL_METHOD* wolfSSLv3_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* m = NULL;
+        WOLFSSL_ENTER("SSLv3_method");
+    #if !defined(NO_WOLFSSL_CLIENT)
+        m = wolfSSLv3_client_method_ex(heap);
+    #elif !defined(NO_WOLFSSL_SERVER)
+        m = wolfSSLv3_server_method_ex(heap);
+    #endif
+        if (m != NULL) {
+            m->side = WOLFSSL_NEITHER_END;
+        }
+
+        return m;
+    }
+    #endif
+#endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */
+
+/* client only parts */
+#ifndef NO_WOLFSSL_CLIENT
+
+    #ifdef OPENSSL_EXTRA
+    WOLFSSL_METHOD* wolfSSLv2_client_method(void)
+    {
+        WOLFSSL_STUB("wolfSSLv2_client_method");
+        return NULL;
+    }
+    #endif
+
+    #ifdef WOLFSSL_ALLOW_SSLV3
+    WOLFSSL_METHOD* wolfSSLv3_client_method(void)
+    {
+        return wolfSSLv3_client_method_ex(NULL);
+    }
+    WOLFSSL_METHOD* wolfSSLv3_client_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* method =
+                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+                                                     heap, DYNAMIC_TYPE_METHOD);
+        (void)heap;
+        WOLFSSL_ENTER("SSLv3_client_method_ex");
+        if (method)
+            InitSSL_Method(method, MakeSSLv3());
+        return method;
+    }
+    #endif /* WOLFSSL_ALLOW_SSLV3 */
+
+
+    WOLFSSL_METHOD* wolfSSLv23_client_method(void)
+    {
+        return wolfSSLv23_client_method_ex(NULL);
+    }
+    WOLFSSL_METHOD* wolfSSLv23_client_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* method =
+                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+                                                     heap, DYNAMIC_TYPE_METHOD);
+        (void)heap;
+        WOLFSSL_ENTER("SSLv23_client_method_ex");
+        if (method) {
+    #if !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512)
+        #if defined(WOLFSSL_TLS13)
+            InitSSL_Method(method, MakeTLSv1_3());
+        #elif !defined(WOLFSSL_NO_TLS12)
+            InitSSL_Method(method, MakeTLSv1_2());
+        #elif !defined(NO_OLD_TLS)
+            InitSSL_Method(method, MakeTLSv1_1());
+        #endif
+    #else
+        #ifndef NO_OLD_TLS
+            InitSSL_Method(method, MakeTLSv1_1());
+        #endif
+    #endif
+    #if !defined(NO_OLD_TLS) || defined(WOLFSSL_TLS13)
+            method->downgrade = 1;
+    #endif
+        }
+        return method;
+    }
+
+
+    #if defined(WOLFSSL_DTLS) || !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS) || \
+        defined(WOLFSSL_ALLOW_SSLV3)
+    /* If SCTP is not enabled returns the state of the dtls option.
+     * If SCTP is enabled returns dtls && !sctp. */
+    static WC_INLINE int IsDtlsNotSctpMode(WOLFSSL* ssl)
+    {
+        int result = ssl->options.dtls;
+
+        if (result) {
+        #ifdef WOLFSSL_SCTP
+            result = !ssl->options.dtlsSctp;
+        #endif
+        }
+
+        return result;
+    }
+    #endif /* WOLFSSL_DTLS || !WOLFSSL_NO_TLS12 || !NO_OLD_TLS */
+
+
+    /* please see note at top of README if you get an error from connect */
+    WOLFSSL_ABI
+    int wolfSSL_connect(WOLFSSL* ssl)
+    {
+    #if !(defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13))
+        int neededState;
+    #endif
+
+        WOLFSSL_ENTER("SSL_connect()");
+
+        #ifdef HAVE_ERRNO_H
+            errno = 0;
+        #endif
+
+        if (ssl == NULL)
+            return BAD_FUNC_ARG;
+
+    #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
+        if (ssl->options.side == WOLFSSL_NEITHER_END) {
+            ssl->error = InitSSL_Side(ssl, WOLFSSL_CLIENT_END);
+            if (ssl->error != WOLFSSL_SUCCESS) {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+            ssl->error = 0; /* expected to be zero here */
+        }
+
+    #ifdef OPENSSL_EXTRA
+        if (ssl->CBIS != NULL) {
+            ssl->CBIS(ssl, SSL_ST_CONNECT, SSL_SUCCESS);
+            ssl->cbmode = SSL_CB_WRITE;
+        }
+    #endif
+    #endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */
+
+    #if defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13)
+        return wolfSSL_connect_TLSv13(ssl);
+    #else
+        #ifdef WOLFSSL_TLS13
+        if (ssl->options.tls1_3)
+            return wolfSSL_connect_TLSv13(ssl);
+        #endif
+
+        if (ssl->options.side != WOLFSSL_CLIENT_END) {
+            WOLFSSL_ERROR(ssl->error = SIDE_ERROR);
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        #ifdef WOLFSSL_DTLS
+        if (ssl->version.major == DTLS_MAJOR) {
+            ssl->options.dtls   = 1;
+            ssl->options.tls    = 1;
+            ssl->options.tls1_1 = 1;
+        }
+        #endif
+
+        if (ssl->buffers.outputBuffer.length > 0
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            /* do not send buffered or advance state if last error was an 
+                async pending operation */
+            && ssl->error != WC_PENDING_E
+        #endif
+        ) {
+            if ( (ssl->error = SendBuffered(ssl)) == 0) {
+                /* fragOffset is non-zero when sending fragments. On the last
+                 * fragment, fragOffset is zero again, and the state can be
+                 * advanced. */
+                if (ssl->fragOffset == 0) {
+                    ssl->options.connectState++;
+                    WOLFSSL_MSG("connect state: "
+                                "Advanced from last buffered fragment send");
+                }
+                else {
+                    WOLFSSL_MSG("connect state: "
+                                "Not advanced, more fragments to send");
+                }
+            }
+            else {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+        }
+
+        switch (ssl->options.connectState) {
+
+        case CONNECT_BEGIN :
+            /* always send client hello first */
+            if ( (ssl->error = SendClientHello(ssl)) != 0) {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+            ssl->options.connectState = CLIENT_HELLO_SENT;
+            WOLFSSL_MSG("connect state: CLIENT_HELLO_SENT");
+            FALL_THROUGH;
+
+        case CLIENT_HELLO_SENT :
+            neededState = ssl->options.resuming ? SERVER_FINISHED_COMPLETE :
+                                          SERVER_HELLODONE_COMPLETE;
+            #ifdef WOLFSSL_DTLS
+                /* In DTLS, when resuming, we can go straight to FINISHED,
+                 * or do a cookie exchange and then skip to FINISHED, assume
+                 * we need the cookie exchange first. */
+                if (IsDtlsNotSctpMode(ssl))
+                    neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
+            #endif
+            /* get response */
+            while (ssl->options.serverState < neededState) {
+                #ifdef WOLFSSL_TLS13
+                    if (ssl->options.tls1_3)
+                        return wolfSSL_connect_TLSv13(ssl);
+                #endif
+                if ( (ssl->error = ProcessReply(ssl)) < 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+                /* if resumption failed, reset needed state */
+                else if (neededState == SERVER_FINISHED_COMPLETE)
+                    if (!ssl->options.resuming) {
+                        if (!IsDtlsNotSctpMode(ssl))
+                            neededState = SERVER_HELLODONE_COMPLETE;
+                        else
+                            neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
+                    }
+            }
+
+            ssl->options.connectState = HELLO_AGAIN;
+            WOLFSSL_MSG("connect state: HELLO_AGAIN");
+            FALL_THROUGH;
+
+        case HELLO_AGAIN :
+            if (ssl->options.certOnly)
+                return WOLFSSL_SUCCESS;
+
+        #ifdef WOLFSSL_TLS13
+            if (ssl->options.tls1_3)
+                return wolfSSL_connect_TLSv13(ssl);
+        #endif
+
+            #ifdef WOLFSSL_DTLS
+            if (ssl->options.serverState ==
+                    SERVER_HELLOVERIFYREQUEST_COMPLETE) {
+                if (IsDtlsNotSctpMode(ssl)) {
+                    /* re-init hashes, exclude first hello and verify request */
+                    if ((ssl->error = InitHandshakeHashes(ssl)) != 0) {
+                        WOLFSSL_ERROR(ssl->error);
+                        return WOLFSSL_FATAL_ERROR;
+                    }
+                    if ( (ssl->error = SendClientHello(ssl)) != 0) {
+                        WOLFSSL_ERROR(ssl->error);
+                        return WOLFSSL_FATAL_ERROR;
+                    }
+                }
+            }
+            #endif
+
+            ssl->options.connectState = HELLO_AGAIN_REPLY;
+            WOLFSSL_MSG("connect state: HELLO_AGAIN_REPLY");
+            FALL_THROUGH;
+
+        case HELLO_AGAIN_REPLY :
+            #ifdef WOLFSSL_DTLS
+                if (IsDtlsNotSctpMode(ssl)) {
+                    neededState = ssl->options.resuming ?
+                           SERVER_FINISHED_COMPLETE : SERVER_HELLODONE_COMPLETE;
+
+                    /* get response */
+                    while (ssl->options.serverState < neededState) {
+                        if ( (ssl->error = ProcessReply(ssl)) < 0) {
+                            WOLFSSL_ERROR(ssl->error);
+                            return WOLFSSL_FATAL_ERROR;
+                        }
+                        /* if resumption failed, reset needed state */
+                        if (neededState == SERVER_FINISHED_COMPLETE) {
+                            if (!ssl->options.resuming)
+                                neededState = SERVER_HELLODONE_COMPLETE;
+                        }
+                    }
+                }
+            #endif
+
+            ssl->options.connectState = FIRST_REPLY_DONE;
+            WOLFSSL_MSG("connect state: FIRST_REPLY_DONE");
+            FALL_THROUGH;
+
+        case FIRST_REPLY_DONE :
+            #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH)
+                #ifdef WOLFSSL_TLS13
+                    if (ssl->options.tls1_3)
+                        return wolfSSL_connect_TLSv13(ssl);
+                #endif
+                if (ssl->options.sendVerify) {
+                    if ( (ssl->error = SendCertificate(ssl)) != 0) {
+                        WOLFSSL_ERROR(ssl->error);
+                        return WOLFSSL_FATAL_ERROR;
+                    }
+                    WOLFSSL_MSG("sent: certificate");
+                }
+
+            #endif
+            ssl->options.connectState = FIRST_REPLY_FIRST;
+            WOLFSSL_MSG("connect state: FIRST_REPLY_FIRST");
+            FALL_THROUGH;
+
+        case FIRST_REPLY_FIRST :
+        #ifdef WOLFSSL_TLS13
+            if (ssl->options.tls1_3)
+                return wolfSSL_connect_TLSv13(ssl);
+        #endif
+            if (!ssl->options.resuming) {
+                if ( (ssl->error = SendClientKeyExchange(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+                WOLFSSL_MSG("sent: client key exchange");
+            }
+
+            ssl->options.connectState = FIRST_REPLY_SECOND;
+            WOLFSSL_MSG("connect state: FIRST_REPLY_SECOND");
+            FALL_THROUGH;
+
+        case FIRST_REPLY_SECOND :
+            #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH)
+                if (ssl->options.sendVerify) {
+                    if ( (ssl->error = SendCertificateVerify(ssl)) != 0) {
+                        WOLFSSL_ERROR(ssl->error);
+                        return WOLFSSL_FATAL_ERROR;
+                    }
+                    WOLFSSL_MSG("sent: certificate verify");
+                }
+            #endif /* !NO_CERTS && !WOLFSSL_NO_CLIENT_AUTH */
+            ssl->options.connectState = FIRST_REPLY_THIRD;
+            WOLFSSL_MSG("connect state: FIRST_REPLY_THIRD");
+            FALL_THROUGH;
+
+        case FIRST_REPLY_THIRD :
+            if ( (ssl->error = SendChangeCipher(ssl)) != 0) {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+            WOLFSSL_MSG("sent: change cipher spec");
+            ssl->options.connectState = FIRST_REPLY_FOURTH;
+            WOLFSSL_MSG("connect state: FIRST_REPLY_FOURTH");
+            FALL_THROUGH;
+
+        case FIRST_REPLY_FOURTH :
+            if ( (ssl->error = SendFinished(ssl)) != 0) {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+            WOLFSSL_MSG("sent: finished");
+            ssl->options.connectState = FINISHED_DONE;
+            WOLFSSL_MSG("connect state: FINISHED_DONE");
+            FALL_THROUGH;
+
+        case FINISHED_DONE :
+            /* get response */
+            while (ssl->options.serverState < SERVER_FINISHED_COMPLETE)
+                if ( (ssl->error = ProcessReply(ssl)) < 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+
+            ssl->options.connectState = SECOND_REPLY_DONE;
+            WOLFSSL_MSG("connect state: SECOND_REPLY_DONE");
+            FALL_THROUGH;
+
+        case SECOND_REPLY_DONE:
+#ifndef NO_HANDSHAKE_DONE_CB
+            if (ssl->hsDoneCb) {
+                int cbret = ssl->hsDoneCb(ssl, ssl->hsDoneCtx);
+                if (cbret < 0) {
+                    ssl->error = cbret;
+                    WOLFSSL_MSG("HandShake Done Cb don't continue error");
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+#endif /* NO_HANDSHAKE_DONE_CB */
+
+            if (!ssl->options.dtls) {
+                if (!ssl->options.keepResources) {
+                    FreeHandshakeResources(ssl);
+                }
+            }
+#ifdef WOLFSSL_DTLS
+            else {
+                ssl->options.dtlsHsRetain = 1;
+            }
+#endif /* WOLFSSL_DTLS */
+
+            WOLFSSL_LEAVE("SSL_connect()", WOLFSSL_SUCCESS);
+            return WOLFSSL_SUCCESS;
+
+        default:
+            WOLFSSL_MSG("Unknown connect state ERROR");
+            return WOLFSSL_FATAL_ERROR; /* unknown connect state */
+        }
+    #endif /* !WOLFSSL_NO_TLS12 */
+    }
+
+#endif /* NO_WOLFSSL_CLIENT */
+
+
+/* server only parts */
+#ifndef NO_WOLFSSL_SERVER
+
+    #ifdef OPENSSL_EXTRA
+    WOLFSSL_METHOD* wolfSSLv2_server_method(void)
+    {
+        WOLFSSL_STUB("wolfSSLv2_server_method");
+        return 0;
+    }
+    #endif
+
+    #ifdef WOLFSSL_ALLOW_SSLV3
+    WOLFSSL_METHOD* wolfSSLv3_server_method(void)
+    {
+        return wolfSSLv3_server_method_ex(NULL);
+    }
+    WOLFSSL_METHOD* wolfSSLv3_server_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* method =
+                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+                                                     heap, DYNAMIC_TYPE_METHOD);
+        (void)heap;
+        WOLFSSL_ENTER("SSLv3_server_method_ex");
+        if (method) {
+            InitSSL_Method(method, MakeSSLv3());
+            method->side = WOLFSSL_SERVER_END;
+        }
+        return method;
+    }
+    #endif /* WOLFSSL_ALLOW_SSLV3 */
+
+    WOLFSSL_METHOD* wolfSSLv23_server_method(void)
+    {
+        return wolfSSLv23_server_method_ex(NULL);
+    }
+
+    WOLFSSL_METHOD* wolfSSLv23_server_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* method =
+                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+                                                     heap, DYNAMIC_TYPE_METHOD);
+        (void)heap;
+        WOLFSSL_ENTER("SSLv23_server_method_ex");
+        if (method) {
+    #if !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512)
+        #ifdef WOLFSSL_TLS13
+            InitSSL_Method(method, MakeTLSv1_3());
+        #elif !defined(WOLFSSL_NO_TLS12)
+            InitSSL_Method(method, MakeTLSv1_2());
+        #elif !defined(NO_OLD_TLS)
+            InitSSL_Method(method, MakeTLSv1_1());
+        #endif
+    #else
+        #ifndef NO_OLD_TLS
+            InitSSL_Method(method, MakeTLSv1_1());
+        #else
+            #error Must have SHA256, SHA384 or SHA512 enabled for TLS 1.2
+        #endif
+    #endif
+    #if !defined(NO_OLD_TLS) || defined(WOLFSSL_TLS13)
+            method->downgrade = 1;
+    #endif
+            method->side      = WOLFSSL_SERVER_END;
+        }
+        return method;
+    }
+
+
+    int wolfSSL_accept(WOLFSSL* ssl)
+    {
+#if !(defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13))
+        word16 havePSK = 0;
+        word16 haveAnon = 0;
+        word16 haveMcast = 0;
+#endif
+
+        if (ssl == NULL)
+            return WOLFSSL_FATAL_ERROR;
+
+    #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
+        if (ssl->options.side == WOLFSSL_NEITHER_END) {
+            WOLFSSL_MSG("Setting WOLFSSL_SSL to be server side");
+            ssl->error = InitSSL_Side(ssl, WOLFSSL_SERVER_END);
+            if (ssl->error != WOLFSSL_SUCCESS) {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+            ssl->error = 0; /* expected to be zero here */
+        }
+    #endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */
+
+#if defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13)
+        return wolfSSL_accept_TLSv13(ssl);
+#else
+    #ifdef WOLFSSL_TLS13
+        if (ssl->options.tls1_3)
+            return wolfSSL_accept_TLSv13(ssl);
+    #endif
+        WOLFSSL_ENTER("SSL_accept()");
+
+        #ifdef HAVE_ERRNO_H
+            errno = 0;
+        #endif
+
+        #ifndef NO_PSK
+            havePSK = ssl->options.havePSK;
+        #endif
+        (void)havePSK;
+
+        #ifdef HAVE_ANON
+            haveAnon = ssl->options.haveAnon;
+        #endif
+        (void)haveAnon;
+
+        #ifdef WOLFSSL_MULTICAST
+            haveMcast = ssl->options.haveMcast;
+        #endif
+        (void)haveMcast;
+
+        if (ssl->options.side != WOLFSSL_SERVER_END) {
+            WOLFSSL_ERROR(ssl->error = SIDE_ERROR);
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+    #ifndef NO_CERTS
+        /* in case used set_accept_state after init */
+        /* allow no private key if using PK callbacks and CB is set */
+        if (!havePSK && !haveAnon && !haveMcast) {
+            if (!ssl->buffers.certificate ||
+                !ssl->buffers.certificate->buffer) {
+
+                WOLFSSL_MSG("accept error: server cert required");
+                WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY);
+                return WOLFSSL_FATAL_ERROR;
+            }
+
+        #ifdef HAVE_PK_CALLBACKS
+            if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) {
+                WOLFSSL_MSG("Using PK for server private key");
+            }
+            else
+        #endif
+            if (!ssl->buffers.key || !ssl->buffers.key->buffer) {
+                WOLFSSL_MSG("accept error: server key required");
+                WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY);
+                return WOLFSSL_FATAL_ERROR;
+            }
+        }
+    #endif
+
+    #ifdef WOLFSSL_DTLS
+        if (ssl->version.major == DTLS_MAJOR) {
+            ssl->options.dtls   = 1;
+            ssl->options.tls    = 1;
+            ssl->options.tls1_1 = 1;
+        }
+    #endif
+
+        if (ssl->buffers.outputBuffer.length > 0
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            /* do not send buffered or advance state if last error was an 
+                async pending operation */
+            && ssl->error != WC_PENDING_E
+        #endif
+        ) {
+            if ( (ssl->error = SendBuffered(ssl)) == 0) {
+                /* fragOffset is non-zero when sending fragments. On the last
+                 * fragment, fragOffset is zero again, and the state can be
+                 * advanced. */
+                if (ssl->fragOffset == 0) {
+                    ssl->options.acceptState++;
+                    WOLFSSL_MSG("accept state: "
+                                "Advanced from last buffered fragment send");
+                }
+                else {
+                    WOLFSSL_MSG("accept state: "
+                                "Not advanced, more fragments to send");
+                }
+            }
+            else {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+        }
+
+        switch (ssl->options.acceptState) {
+
+        case ACCEPT_BEGIN :
+#ifdef HAVE_SECURE_RENEGOTIATION
+        case ACCEPT_BEGIN_RENEG:
+#endif
+            /* get response */
+            while (ssl->options.clientState < CLIENT_HELLO_COMPLETE)
+                if ( (ssl->error = ProcessReply(ssl)) < 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+#ifdef WOLFSSL_TLS13
+            ssl->options.acceptState = ACCEPT_CLIENT_HELLO_DONE;
+            WOLFSSL_MSG("accept state ACCEPT_CLIENT_HELLO_DONE");
+            FALL_THROUGH;
+
+        case ACCEPT_CLIENT_HELLO_DONE :
+            if (ssl->options.tls1_3) {
+                return wolfSSL_accept_TLSv13(ssl);
+            }
+#endif
+            ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE;
+            WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE");
+            FALL_THROUGH;
+
+        case ACCEPT_FIRST_REPLY_DONE :
+            if ( (ssl->error = SendServerHello(ssl)) != 0) {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+            ssl->options.acceptState = SERVER_HELLO_SENT;
+            WOLFSSL_MSG("accept state SERVER_HELLO_SENT");
+            FALL_THROUGH;
+
+        case SERVER_HELLO_SENT :
+        #ifdef WOLFSSL_TLS13
+            if (ssl->options.tls1_3) {
+                return wolfSSL_accept_TLSv13(ssl);
+            }
+        #endif
+            #ifndef NO_CERTS
+                if (!ssl->options.resuming)
+                    if ( (ssl->error = SendCertificate(ssl)) != 0) {
+                        WOLFSSL_ERROR(ssl->error);
+                        return WOLFSSL_FATAL_ERROR;
+                    }
+            #endif
+            ssl->options.acceptState = CERT_SENT;
+            WOLFSSL_MSG("accept state CERT_SENT");
+            FALL_THROUGH;
+
+        case CERT_SENT :
+            #ifndef NO_CERTS
+            if (!ssl->options.resuming)
+                if ( (ssl->error = SendCertificateStatus(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            #endif
+            ssl->options.acceptState = CERT_STATUS_SENT;
+            WOLFSSL_MSG("accept state CERT_STATUS_SENT");
+            FALL_THROUGH;
+
+        case CERT_STATUS_SENT :
+        #ifdef WOLFSSL_TLS13
+            if (ssl->options.tls1_3) {
+                return wolfSSL_accept_TLSv13(ssl);
+            }
+        #endif
+            if (!ssl->options.resuming)
+                if ( (ssl->error = SendServerKeyExchange(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            ssl->options.acceptState = KEY_EXCHANGE_SENT;
+            WOLFSSL_MSG("accept state KEY_EXCHANGE_SENT");
+            FALL_THROUGH;
+
+        case KEY_EXCHANGE_SENT :
+            #ifndef NO_CERTS
+                if (!ssl->options.resuming) {
+                    if (ssl->options.verifyPeer) {
+                        if ( (ssl->error = SendCertificateRequest(ssl)) != 0) {
+                            WOLFSSL_ERROR(ssl->error);
+                            return WOLFSSL_FATAL_ERROR;
+                        }
+                    }
+                }
+            #endif
+            ssl->options.acceptState = CERT_REQ_SENT;
+            WOLFSSL_MSG("accept state CERT_REQ_SENT");
+            FALL_THROUGH;
+
+        case CERT_REQ_SENT :
+            if (!ssl->options.resuming)
+                if ( (ssl->error = SendServerHelloDone(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            ssl->options.acceptState = SERVER_HELLO_DONE;
+            WOLFSSL_MSG("accept state SERVER_HELLO_DONE");
+            FALL_THROUGH;
+
+        case SERVER_HELLO_DONE :
+            if (!ssl->options.resuming) {
+                while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE)
+                    if ( (ssl->error = ProcessReply(ssl)) < 0) {
+                        WOLFSSL_ERROR(ssl->error);
+                        return WOLFSSL_FATAL_ERROR;
+                    }
+            }
+            ssl->options.acceptState = ACCEPT_SECOND_REPLY_DONE;
+            WOLFSSL_MSG("accept state  ACCEPT_SECOND_REPLY_DONE");
+            FALL_THROUGH;
+
+        case ACCEPT_SECOND_REPLY_DONE :
+#ifdef HAVE_SESSION_TICKET
+            if (ssl->options.createTicket) {
+                if ( (ssl->error = SendTicket(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+#endif /* HAVE_SESSION_TICKET */
+            ssl->options.acceptState = TICKET_SENT;
+            WOLFSSL_MSG("accept state  TICKET_SENT");
+            FALL_THROUGH;
+
+        case TICKET_SENT:
+            if ( (ssl->error = SendChangeCipher(ssl)) != 0) {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+            ssl->options.acceptState = CHANGE_CIPHER_SENT;
+            WOLFSSL_MSG("accept state  CHANGE_CIPHER_SENT");
+            FALL_THROUGH;
+
+        case CHANGE_CIPHER_SENT :
+            if ( (ssl->error = SendFinished(ssl)) != 0) {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+
+            ssl->options.acceptState = ACCEPT_FINISHED_DONE;
+            WOLFSSL_MSG("accept state ACCEPT_FINISHED_DONE");
+            FALL_THROUGH;
+
+        case ACCEPT_FINISHED_DONE :
+            if (ssl->options.resuming)
+                while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE)
+                    if ( (ssl->error = ProcessReply(ssl)) < 0) {
+                        WOLFSSL_ERROR(ssl->error);
+                        return WOLFSSL_FATAL_ERROR;
+                    }
+
+            ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE;
+            WOLFSSL_MSG("accept state ACCEPT_THIRD_REPLY_DONE");
+            FALL_THROUGH;
+
+        case ACCEPT_THIRD_REPLY_DONE :
+#ifndef NO_HANDSHAKE_DONE_CB
+            if (ssl->hsDoneCb) {
+                int cbret = ssl->hsDoneCb(ssl, ssl->hsDoneCtx);
+                if (cbret < 0) {
+                    ssl->error = cbret;
+                    WOLFSSL_MSG("HandShake Done Cb don't continue error");
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+#endif /* NO_HANDSHAKE_DONE_CB */
+
+            if (!ssl->options.dtls) {
+                if (!ssl->options.keepResources) {
+                    FreeHandshakeResources(ssl);
+                }
+            }
+#ifdef WOLFSSL_DTLS
+            else {
+                ssl->options.dtlsHsRetain = 1;
+            }
+#endif /* WOLFSSL_DTLS */
+
+#ifdef WOLFSSL_SESSION_EXPORT
+            if (ssl->dtls_export) {
+                if ((ssl->error = wolfSSL_send_session(ssl)) != 0) {
+                    WOLFSSL_MSG("Export DTLS session error");
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+#endif
+
+            WOLFSSL_LEAVE("SSL_accept()", WOLFSSL_SUCCESS);
+            return WOLFSSL_SUCCESS;
+
+        default :
+            WOLFSSL_MSG("Unknown accept state ERROR");
+            return WOLFSSL_FATAL_ERROR;
+        }
+#endif /* !WOLFSSL_NO_TLS12 */
+    }
+
+#endif /* NO_WOLFSSL_SERVER */
+
+
+#ifndef NO_HANDSHAKE_DONE_CB
+
+int wolfSSL_SetHsDoneCb(WOLFSSL* ssl, HandShakeDoneCb cb, void* user_ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_SetHsDoneCb");
+
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    ssl->hsDoneCb  = cb;
+    ssl->hsDoneCtx = user_ctx;
+
+
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* NO_HANDSHAKE_DONE_CB */
+
+WOLFSSL_ABI
+int wolfSSL_Cleanup(void)
+{
+    int ret = WOLFSSL_SUCCESS;
+    int release = 0;
+
+    WOLFSSL_ENTER("wolfSSL_Cleanup");
+
+    if (initRefCount == 0)
+        return ret;  /* possibly no init yet, but not failure either way */
+
+    if (wc_LockMutex(&count_mutex) != 0) {
+        WOLFSSL_MSG("Bad Lock Mutex count");
+        return BAD_MUTEX_E;
+    }
+
+    release = initRefCount-- == 1;
+    if (initRefCount < 0)
+        initRefCount = 0;
+
+    wc_UnLockMutex(&count_mutex);
+
+    if (!release)
+        return ret;
+
+#ifdef OPENSSL_EXTRA
+    if (bn_one) {
+        wolfSSL_BN_free(bn_one);
+        bn_one = NULL;
+    }
+#endif
+
+#ifndef NO_SESSION_CACHE
+    if (wc_FreeMutex(&session_mutex) != 0)
+        ret = BAD_MUTEX_E;
+#endif
+    if (wc_FreeMutex(&count_mutex) != 0)
+        ret = BAD_MUTEX_E;
+
+#ifdef OPENSSL_EXTRA
+    wolfSSL_RAND_Cleanup();
+#endif
+
+    if (wolfCrypt_Cleanup() != 0) {
+        WOLFSSL_MSG("Error with wolfCrypt_Cleanup call");
+        ret = WC_CLEANUP_E;
+    }
+
+    return ret;
+}
+
+
+#ifndef NO_SESSION_CACHE
+
+
+/* some session IDs aren't random after all, let's make them random */
+static WC_INLINE word32 HashSession(const byte* sessionID, word32 len, int* error)
+{
+    byte digest[WC_MAX_DIGEST_SIZE];
+
+#ifndef NO_MD5
+    *error =  wc_Md5Hash(sessionID, len, digest);
+#elif !defined(NO_SHA)
+    *error =  wc_ShaHash(sessionID, len, digest);
+#elif !defined(NO_SHA256)
+    *error =  wc_Sha256Hash(sessionID, len, digest);
+#else
+    #error "We need a digest to hash the session IDs"
+#endif
+
+    return *error == 0 ? MakeWordFromHash(digest) : 0; /* 0 on failure */
+}
+
+
+WOLFSSL_ABI
+void wolfSSL_flush_sessions(WOLFSSL_CTX* ctx, long tm)
+{
+    /* static table now, no flushing needed */
+    (void)ctx;
+    (void)tm;
+}
+
+
+/* set ssl session timeout in seconds */
+WOLFSSL_ABI
+int wolfSSL_set_timeout(WOLFSSL* ssl, unsigned int to)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    if (to == 0)
+        to = WOLFSSL_SESSION_TIMEOUT;
+    ssl->timeout = to;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* set ctx session timeout in seconds */
+WOLFSSL_ABI
+int wolfSSL_CTX_set_timeout(WOLFSSL_CTX* ctx, unsigned int to)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    if (to == 0)
+        to = WOLFSSL_SESSION_TIMEOUT;
+    ctx->timeout = to;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+#ifndef NO_CLIENT_CACHE
+
+/* Get Session from Client cache based on id/len, return NULL on failure */
+WOLFSSL_SESSION* GetSessionClient(WOLFSSL* ssl, const byte* id, int len)
+{
+    WOLFSSL_SESSION* ret = NULL;
+    word32          row;
+    int             idx;
+    int             count;
+    int             error = 0;
+
+    WOLFSSL_ENTER("GetSessionClient");
+
+    if (ssl->ctx->sessionCacheOff)
+        return NULL;
+
+    if (ssl->options.side == WOLFSSL_SERVER_END)
+        return NULL;
+
+    len = min(SERVER_ID_LEN, (word32)len);
+
+#ifdef HAVE_EXT_CACHE
+    if (ssl->ctx->get_sess_cb != NULL) {
+        int copy = 0;
+        ret = ssl->ctx->get_sess_cb(ssl, (byte*)id, len, &copy);
+        if (ret != NULL)
+            return ret;
+    }
+
+    if (ssl->ctx->internalCacheOff)
+        return NULL;
+#endif
+
+    row = HashSession(id, len, &error) % SESSION_ROWS;
+    if (error != 0) {
+        WOLFSSL_MSG("Hash session failed");
+        return NULL;
+    }
+
+    if (wc_LockMutex(&session_mutex) != 0) {
+        WOLFSSL_MSG("Lock session mutex failed");
+        return NULL;
+    }
+
+    /* start from most recently used */
+    count = min((word32)ClientCache[row].totalCount, SESSIONS_PER_ROW);
+    idx = ClientCache[row].nextIdx - 1;
+    if (idx < 0)
+        idx = SESSIONS_PER_ROW - 1; /* if back to front, the previous was end */
+
+    for (; count > 0; --count, idx = idx ? idx - 1 : SESSIONS_PER_ROW - 1) {
+        WOLFSSL_SESSION* current;
+        ClientSession   clSess;
+
+        if (idx >= SESSIONS_PER_ROW || idx < 0) { /* sanity check */
+            WOLFSSL_MSG("Bad idx");
+            break;
+        }
+
+        clSess = ClientCache[row].Clients[idx];
+
+        current = &SessionCache[clSess.serverRow].Sessions[clSess.serverIdx];
+        if (XMEMCMP(current->serverID, id, len) == 0) {
+            WOLFSSL_MSG("Found a serverid match for client");
+            if (LowResTimer() < (current->bornOn + current->timeout)) {
+                WOLFSSL_MSG("Session valid");
+                ret = current;
+                break;
+            } else {
+                WOLFSSL_MSG("Session timed out");  /* could have more for id */
+            }
+        } else {
+            WOLFSSL_MSG("ServerID not a match from client table");
+        }
+    }
+
+    wc_UnLockMutex(&session_mutex);
+
+    return ret;
+}
+
+#endif /* NO_CLIENT_CACHE */
+
+/* Restore the master secret and session information for certificates.
+ *
+ * ssl                  The SSL/TLS object.
+ * session              The cached session to restore.
+ * masterSecret         The master secret from the cached session.
+ * restoreSessionCerts  Restoring session certificates is required.
+ */
+static WC_INLINE void RestoreSession(WOLFSSL* ssl, WOLFSSL_SESSION* session,
+        byte* masterSecret, byte restoreSessionCerts)
+{
+    (void)ssl;
+    (void)restoreSessionCerts;
+
+    if (masterSecret)
+        XMEMCPY(masterSecret, session->masterSecret, SECRET_LEN);
+#ifdef SESSION_CERTS
+    /* If set, we should copy the session certs into the ssl object
+     * from the session we are returning so we can resume */
+    if (restoreSessionCerts) {
+        ssl->session.chain        = session->chain;
+        ssl->session.version      = session->version;
+    #ifdef NO_RESUME_SUITE_CHECK
+        ssl->session.cipherSuite0 = session->cipherSuite0;
+        ssl->session.cipherSuite  = session->cipherSuite;
+    #endif
+    }
+#endif /* SESSION_CERTS */
+#if !defined(NO_RESUME_SUITE_CHECK) || \
+                        (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET))
+    ssl->session.cipherSuite0 = session->cipherSuite0;
+    ssl->session.cipherSuite  = session->cipherSuite;
+#endif
+}
+
+WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret,
+        byte restoreSessionCerts)
+{
+    WOLFSSL_SESSION* ret = 0;
+    const byte*  id = NULL;
+    word32       row;
+    int          idx;
+    int          count;
+    int          error = 0;
+
+    (void)       restoreSessionCerts;
+
+    if (ssl->options.sessionCacheOff)
+        return NULL;
+
+    if (ssl->options.haveSessionId == 0)
+        return NULL;
+
+#ifdef HAVE_SESSION_TICKET
+    if (ssl->options.side == WOLFSSL_SERVER_END && ssl->options.useTicket == 1)
+        return NULL;
+#endif
+
+    if (!ssl->options.tls1_3 && ssl->arrays != NULL)
+        id = ssl->arrays->sessionID;
+    else
+        id = ssl->session.sessionID;
+
+#ifdef HAVE_EXT_CACHE
+    if (ssl->ctx->get_sess_cb != NULL) {
+        int copy = 0;
+        /* Attempt to retrieve the session from the external cache. */
+        ret = ssl->ctx->get_sess_cb(ssl, (byte*)id, ID_LEN, &copy);
+        if (ret != NULL) {
+            RestoreSession(ssl, ret, masterSecret, restoreSessionCerts);
+            return ret;
+        }
+    }
+
+    if (ssl->ctx->internalCacheOff)
+        return NULL;
+#endif
+
+    row = HashSession(id, ID_LEN, &error) % SESSION_ROWS;
+    if (error != 0) {
+        WOLFSSL_MSG("Hash session failed");
+        return NULL;
+    }
+
+    if (wc_LockMutex(&session_mutex) != 0)
+        return 0;
+
+    /* start from most recently used */
+    count = min((word32)SessionCache[row].totalCount, SESSIONS_PER_ROW);
+    idx = SessionCache[row].nextIdx - 1;
+    if (idx < 0)
+        idx = SESSIONS_PER_ROW - 1; /* if back to front, the previous was end */
+
+    for (; count > 0; --count, idx = idx ? idx - 1 : SESSIONS_PER_ROW - 1) {
+        WOLFSSL_SESSION* current;
+
+        if (idx >= SESSIONS_PER_ROW || idx < 0) { /* sanity check */
+            WOLFSSL_MSG("Bad idx");
+            break;
+        }
+
+        current = &SessionCache[row].Sessions[idx];
+        if (XMEMCMP(current->sessionID, id, ID_LEN) == 0) {
+            WOLFSSL_MSG("Found a session match");
+            if (LowResTimer() < (current->bornOn + current->timeout)) {
+                WOLFSSL_MSG("Session valid");
+                ret = current;
+                RestoreSession(ssl, ret, masterSecret, restoreSessionCerts);
+            } else {
+                WOLFSSL_MSG("Session timed out");
+            }
+            break;  /* no more sessionIDs whether valid or not that match */
+        } else {
+            WOLFSSL_MSG("SessionID not a match at this idx");
+        }
+    }
+
+    wc_UnLockMutex(&session_mutex);
+
+    return ret;
+}
+
+
+static int GetDeepCopySession(WOLFSSL* ssl, WOLFSSL_SESSION* copyFrom)
+{
+    WOLFSSL_SESSION* copyInto = &ssl->session;
+    void* tmpBuff             = NULL;
+    int ticketLen             = 0;
+    int doDynamicCopy         = 0;
+    int ret                   = WOLFSSL_SUCCESS;
+
+    (void)ticketLen;
+    (void)doDynamicCopy;
+    (void)tmpBuff;
+
+    if (!ssl || !copyFrom)
+        return BAD_FUNC_ARG;
+
+#ifdef HAVE_SESSION_TICKET
+    /* Free old dynamic ticket if we had one to avoid leak */
+    if (copyInto->isDynamic) {
+        XFREE(copyInto->ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+        copyInto->ticket = copyInto->staticTicket;
+        copyInto->isDynamic = 0;
+    }
+#endif
+
+    if (wc_LockMutex(&session_mutex) != 0)
+        return BAD_MUTEX_E;
+
+#ifdef HAVE_SESSION_TICKET
+    /* Size of ticket to alloc if needed; Use later for alloc outside lock */
+    doDynamicCopy = copyFrom->isDynamic;
+    ticketLen = copyFrom->ticketLen;
+#endif
+
+    *copyInto = *copyFrom;
+
+    /* Default ticket to non dynamic. This will avoid crash if we fail below */
+#ifdef HAVE_SESSION_TICKET
+    copyInto->ticket = copyInto->staticTicket;
+    copyInto->isDynamic = 0;
+#endif
+
+#ifndef NO_RESUME_SUITE_CHECK
+    copyInto->cipherSuite0   = copyFrom->cipherSuite0;
+    copyInto->cipherSuite    = copyFrom->cipherSuite;
+#endif
+
+    if (wc_UnLockMutex(&session_mutex) != 0) {
+        return BAD_MUTEX_E;
+    }
+
+#ifdef HAVE_SESSION_TICKET
+#ifdef WOLFSSL_TLS13
+    if (wc_LockMutex(&session_mutex) != 0) {
+        XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+        return BAD_MUTEX_E;
+    }
+
+#ifdef NO_RESUME_SUITE_CHECK
+    copyInto->cipherSuite0   = copyFrom->cipherSuite0;
+    copyInto->cipherSuite    = copyFrom->cipherSuite;
+#endif
+    copyInto->namedGroup     = copyFrom->namedGroup;
+    copyInto->ticketSeen     = copyFrom->ticketSeen;
+    copyInto->ticketAdd      = copyFrom->ticketAdd;
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    XMEMCPY(&copyInto->ticketNonce, &copyFrom->ticketNonce,
+                                                           sizeof(TicketNonce));
+#endif
+#ifdef WOLFSSL_EARLY_DATA
+    copyInto->maxEarlyDataSz = copyFrom->maxEarlyDataSz;
+#endif
+    XMEMCPY(copyInto->masterSecret, copyFrom->masterSecret, SECRET_LEN);
+
+    if (wc_UnLockMutex(&session_mutex) != 0) {
+        if (ret == WOLFSSL_SUCCESS)
+            ret = BAD_MUTEX_E;
+    }
+#endif
+    /* If doing dynamic copy, need to alloc outside lock, then inside a lock
+     * confirm the size still matches and memcpy */
+    if (doDynamicCopy) {
+        tmpBuff = (byte*)XMALLOC(ticketLen, ssl->heap,
+                                                     DYNAMIC_TYPE_SESSION_TICK);
+        if (!tmpBuff)
+            return MEMORY_ERROR;
+
+        if (wc_LockMutex(&session_mutex) != 0) {
+            XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+            return BAD_MUTEX_E;
+        }
+
+        if ((word16)ticketLen != copyFrom->ticketLen) {
+            /* Another thread modified the ssl-> session ticket during alloc.
+             * Treat as error, since ticket different than when copy requested */
+            ret = VAR_STATE_CHANGE_E;
+        }
+
+        if (ret == WOLFSSL_SUCCESS) {
+            copyInto->ticket = (byte*)tmpBuff;
+            copyInto->isDynamic = 1;
+            XMEMCPY(copyInto->ticket, copyFrom->ticket, ticketLen);
+        }
+    } else {
+        /* Need to ensure ticket pointer gets updated to own buffer
+         * and is not pointing to buff of session copied from */
+        copyInto->ticket = copyInto->staticTicket;
+    }
+
+    if (doDynamicCopy) {
+        if (wc_UnLockMutex(&session_mutex) != 0) {
+            if (ret == WOLFSSL_SUCCESS)
+                ret = BAD_MUTEX_E;
+        }
+    }
+
+    if (ret != WOLFSSL_SUCCESS) {
+        /* cleanup */
+        if (tmpBuff)
+            XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+        copyInto->ticket = copyInto->staticTicket;
+        copyInto->isDynamic = 0;
+    }
+#endif /* HAVE_SESSION_TICKET */
+    return ret;
+}
+
+
+int SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session)
+{
+    if (ssl->options.sessionCacheOff)
+        return WOLFSSL_FAILURE;
+
+#ifdef OPENSSL_EXTRA
+    /* check for application context id */
+    if (ssl->sessionCtxSz > 0) {
+        if (XMEMCMP(ssl->sessionCtx, session->sessionCtx, ssl->sessionCtxSz)) {
+            /* context id did not match! */
+            WOLFSSL_MSG("Session context did not match");
+            return SSL_FAILURE;
+        }
+    }
+#endif /* OPENSSL_EXTRA */
+
+    if (LowResTimer() < (session->bornOn + session->timeout)) {
+        int ret = GetDeepCopySession(ssl, session);
+        if (ret == WOLFSSL_SUCCESS) {
+            ssl->options.resuming = 1;
+
+#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
+                               defined(HAVE_SESSION_TICKET))
+            ssl->version              = session->version;
+#endif
+#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \
+                        (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET))
+            ssl->options.cipherSuite0 = session->cipherSuite0;
+            ssl->options.cipherSuite  = session->cipherSuite;
+#endif
+        }
+
+        return ret;
+    }
+    return WOLFSSL_FAILURE;  /* session timed out */
+}
+
+
+#ifdef WOLFSSL_SESSION_STATS
+static int get_locked_session_stats(word32* active, word32* total,
+                                    word32* peak);
+#endif
+
+int AddSession(WOLFSSL* ssl)
+{
+    word32 row = 0;
+    word32 idx = 0;
+    int    error = 0;
+#ifdef HAVE_SESSION_TICKET
+    byte*  tmpBuff = NULL;
+    int    ticLen  = 0;
+#endif
+    WOLFSSL_SESSION* session;
+    int i;
+    int overwrite = 0;
+
+    if (ssl->options.sessionCacheOff)
+        return 0;
+
+    if (ssl->options.haveSessionId == 0)
+        return 0;
+
+#ifdef HAVE_SESSION_TICKET
+    if (ssl->options.side == WOLFSSL_SERVER_END && ssl->options.useTicket == 1)
+        return 0;
+#endif
+
+#ifdef HAVE_SESSION_TICKET
+    ticLen = ssl->session.ticketLen;
+    /* Alloc Memory here so if Malloc fails can exit outside of lock */
+    if(ticLen > SESSION_TICKET_LEN) {
+        tmpBuff = (byte*)XMALLOC(ticLen, ssl->heap,
+                DYNAMIC_TYPE_SESSION_TICK);
+        if(!tmpBuff)
+            return MEMORY_E;
+    }
+#endif
+
+#ifdef HAVE_EXT_CACHE
+    if (ssl->options.internalCacheOff) {
+        /* Create a new session object to be stored. */
+        session = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), NULL,
+                                            DYNAMIC_TYPE_OPENSSL);
+        if (session == NULL) {
+#ifdef HAVE_SESSION_TICKET
+            XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+#endif
+            return MEMORY_E;
+        }
+        XMEMSET(session, 0, sizeof(WOLFSSL_SESSION));
+        session->isAlloced = 1;
+    }
+    else
+#endif
+    {
+        /* Use the session object in the cache for external cache if required.
+         */
+#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)
+        if (ssl->options.tls1_3) {
+            row = HashSession(ssl->session.sessionID, ID_LEN, &error) %
+                    SESSION_ROWS;
+        }
+        else
+#endif
+        {
+            row = HashSession(ssl->arrays->sessionID, ID_LEN, &error) %
+                    SESSION_ROWS;
+        }
+        if (error != 0) {
+            WOLFSSL_MSG("Hash session failed");
+#ifdef HAVE_SESSION_TICKET
+            XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+#endif
+            return error;
+        }
+
+        if (wc_LockMutex(&session_mutex) != 0) {
+#ifdef HAVE_SESSION_TICKET
+            XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+#endif
+            return BAD_MUTEX_E;
+        }
+
+        for (i=0; i<SESSIONS_PER_ROW; i++) {
+            if (ssl->options.tls1_3) {
+                if (XMEMCMP(ssl->session.sessionID, SessionCache[row].Sessions[i].sessionID, ID_LEN) == 0) {
+                    WOLFSSL_MSG("Session already exists. Overwriting.");
+                    overwrite = 1;
+                    idx = i;
+                    break;
+                }
+            }
+            else {
+                if (XMEMCMP(ssl->arrays->sessionID, SessionCache[row].Sessions[i].sessionID, ID_LEN) == 0) {
+                    WOLFSSL_MSG("Session already exists. Overwriting.");
+                    overwrite = 1;
+                    idx = i;
+                    break;
+                }
+            }
+        }
+
+        if (!overwrite) {
+            idx = SessionCache[row].nextIdx++;
+        }
+#ifdef SESSION_INDEX
+        ssl->sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx;
+#endif
+        session = &SessionCache[row].Sessions[idx];
+    }
+
+    if (!ssl->options.tls1_3)
+        XMEMCPY(session->masterSecret, ssl->arrays->masterSecret, SECRET_LEN);
+    else
+        XMEMCPY(session->masterSecret, ssl->session.masterSecret, SECRET_LEN);
+    session->haveEMS = ssl->options.haveEMS;
+#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)
+    if (ssl->options.tls1_3) {
+        XMEMCPY(session->sessionID, ssl->session.sessionID, ID_LEN);
+        session->sessionIDSz = ID_LEN;
+    }
+    else
+#endif
+    {
+        XMEMCPY(session->sessionID, ssl->arrays->sessionID, ID_LEN);
+        session->sessionIDSz = ssl->arrays->sessionIDSz;
+    }
+
+#ifdef OPENSSL_EXTRA
+    /* If using compatibility layer then check for and copy over session context
+     * id. */
+    if (ssl->sessionCtxSz > 0 && ssl->sessionCtxSz < ID_LEN) {
+        XMEMCPY(session->sessionCtx, ssl->sessionCtx, ssl->sessionCtxSz);
+    }
+#endif
+
+    session->timeout = ssl->timeout;
+    session->bornOn  = LowResTimer();
+
+#ifdef HAVE_SESSION_TICKET
+    /* Check if another thread modified ticket since alloc */
+    if ((word16)ticLen != ssl->session.ticketLen) {
+        error = VAR_STATE_CHANGE_E;
+    }
+
+    if (error == 0) {
+        /* Cleanup cache row's old Dynamic buff if exists */
+        if(session->isDynamic) {
+            XFREE(session->ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+            session->ticket = NULL;
+        }
+
+        /* If too large to store in static buffer, use dyn buffer */
+        if (ticLen > SESSION_TICKET_LEN) {
+            session->ticket = tmpBuff;
+            session->isDynamic = 1;
+        } else {
+            session->ticket = session->staticTicket;
+            session->isDynamic = 0;
+        }
+
+        session->ticketLen = (word16)ticLen;
+        XMEMCPY(session->ticket, ssl->session.ticket, ticLen);
+    } else { /* cleanup, reset state */
+        session->ticket    = session->staticTicket;
+        session->isDynamic = 0;
+        session->ticketLen = 0;
+        if (tmpBuff) {
+            XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+            tmpBuff = NULL;
+        }
+    }
+#endif
+
+#ifdef SESSION_CERTS
+    if (error == 0) {
+        if (!overwrite || ssl->session.chain.count > 0) {
+            /*
+             * If we are overwriting and no certs present in ssl->session.chain
+             * then keep the old chain.
+             */
+            session->chain.count = ssl->session.chain.count;
+            XMEMCPY(session->chain.certs, ssl->session.chain.certs,
+                    sizeof(x509_buffer) * session->chain.count);
+        }
+    }
+#endif /* SESSION_CERTS */
+#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
+                               defined(HAVE_SESSION_TICKET))
+    if (error == 0) {
+        session->version      = ssl->version;
+    }
+#endif /* SESSION_CERTS || (WOLFSSL_TLS13 & HAVE_SESSION_TICKET) */
+#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \
+                        (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET))
+    if (error == 0) {
+        session->cipherSuite0 = ssl->options.cipherSuite0;
+        session->cipherSuite  = ssl->options.cipherSuite;
+    }
+#endif
+#if defined(WOLFSSL_TLS13)
+    if (error == 0) {
+        session->namedGroup     = ssl->session.namedGroup;
+    }
+#endif
+#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)
+    if (error == 0) {
+        session->ticketSeen     = ssl->session.ticketSeen;
+        session->ticketAdd      = ssl->session.ticketAdd;
+#ifndef WOLFSSL_TLS13_DRAFT_18
+        XMEMCPY(&session->ticketNonce, &ssl->session.ticketNonce,
+                                                           sizeof(TicketNonce));
+#endif
+    #ifdef WOLFSSL_EARLY_DATA
+        session->maxEarlyDataSz = ssl->session.maxEarlyDataSz;
+    #endif
+    }
+#endif /* WOLFSSL_TLS13 && HAVE_SESSION_TICKET */
+#ifdef HAVE_EXT_CACHE
+    if (!ssl->options.internalCacheOff)
+#endif
+    {
+        if (error == 0) {
+            SessionCache[row].totalCount++;
+            if (SessionCache[row].nextIdx == SESSIONS_PER_ROW)
+                SessionCache[row].nextIdx = 0;
+        }
+    }
+#ifndef NO_CLIENT_CACHE
+    if (error == 0) {
+        if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->session.idLen) {
+            word32 clientRow, clientIdx;
+
+            WOLFSSL_MSG("Adding client cache entry");
+
+            session->idLen = ssl->session.idLen;
+            XMEMCPY(session->serverID, ssl->session.serverID,
+                    ssl->session.idLen);
+
+#ifdef HAVE_EXT_CACHE
+            if (!ssl->options.internalCacheOff)
+#endif
+            {
+                clientRow = HashSession(ssl->session.serverID,
+                        ssl->session.idLen, &error) % SESSION_ROWS;
+                if (error != 0) {
+                    WOLFSSL_MSG("Hash session failed");
+                } else {
+                    clientIdx = ClientCache[clientRow].nextIdx++;
+
+                    ClientCache[clientRow].Clients[clientIdx].serverRow =
+                                                                   (word16)row;
+                    ClientCache[clientRow].Clients[clientIdx].serverIdx =
+                                                                   (word16)idx;
+
+                    ClientCache[clientRow].totalCount++;
+                    if (ClientCache[clientRow].nextIdx == SESSIONS_PER_ROW)
+                        ClientCache[clientRow].nextIdx = 0;
+                }
+            }
+        }
+        else
+            session->idLen = 0;
+    }
+#endif /* NO_CLIENT_CACHE */
+
+#if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS)
+#ifdef HAVE_EXT_CACHE
+    if (!ssl->options.internalCacheOff)
+#endif
+    {
+        if (error == 0) {
+            word32 active = 0;
+
+            error = get_locked_session_stats(&active, NULL, NULL);
+            if (error == WOLFSSL_SUCCESS) {
+                error = 0;  /* back to this function ok */
+
+                if (active > PeakSessions)
+                    PeakSessions = active;
+            }
+        }
+    }
+#endif /* defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) */
+
+#ifdef HAVE_EXT_CACHE
+    if (!ssl->options.internalCacheOff)
+#endif
+    {
+        if (wc_UnLockMutex(&session_mutex) != 0)
+            return BAD_MUTEX_E;
+    }
+
+#ifdef HAVE_EXT_CACHE
+    if (error == 0 && ssl->ctx->new_sess_cb != NULL)
+        ssl->ctx->new_sess_cb(ssl, session);
+    if (ssl->options.internalCacheOff)
+        wolfSSL_SESSION_free(session);
+#endif
+
+    return error;
+}
+
+
+#ifdef SESSION_INDEX
+
+int wolfSSL_GetSessionIndex(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_GetSessionIndex");
+    WOLFSSL_LEAVE("wolfSSL_GetSessionIndex", ssl->sessionIndex);
+    return ssl->sessionIndex;
+}
+
+
+int wolfSSL_GetSessionAtIndex(int idx, WOLFSSL_SESSION* session)
+{
+    int row, col, result = WOLFSSL_FAILURE;
+
+    WOLFSSL_ENTER("wolfSSL_GetSessionAtIndex");
+
+    row = idx >> SESSIDX_ROW_SHIFT;
+    col = idx & SESSIDX_IDX_MASK;
+
+    if (wc_LockMutex(&session_mutex) != 0) {
+        return BAD_MUTEX_E;
+    }
+
+    if (row < SESSION_ROWS &&
+        col < (int)min(SessionCache[row].totalCount, SESSIONS_PER_ROW)) {
+        XMEMCPY(session,
+                 &SessionCache[row].Sessions[col], sizeof(WOLFSSL_SESSION));
+        result = WOLFSSL_SUCCESS;
+    }
+
+    if (wc_UnLockMutex(&session_mutex) != 0)
+        result = BAD_MUTEX_E;
+
+    WOLFSSL_LEAVE("wolfSSL_GetSessionAtIndex", result);
+    return result;
+}
+
+#endif /* SESSION_INDEX */
+
+#if defined(SESSION_CERTS)
+
+WOLFSSL_X509_CHAIN* wolfSSL_SESSION_get_peer_chain(WOLFSSL_SESSION* session)
+{
+    WOLFSSL_X509_CHAIN* chain = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_SESSION_get_peer_chain");
+    if (session)
+        chain = &session->chain;
+
+    WOLFSSL_LEAVE("wolfSSL_SESSION_get_peer_chain", chain ? 1 : 0);
+    return chain;
+}
+
+
+#ifdef OPENSSL_EXTRA
+/* gets the peer certificate associated with the session passed in
+ * returns null on failure, the caller should not free the returned pointer */
+WOLFSSL_X509* wolfSSL_SESSION_get0_peer(WOLFSSL_SESSION* session)
+{
+    WOLFSSL_ENTER("wolfSSL_SESSION_get_peer_chain");
+    if (session) {
+        int count;
+
+        count = wolfSSL_get_chain_count(&session->chain);
+        if (count < 1 || count >= MAX_CHAIN_DEPTH) {
+            WOLFSSL_MSG("bad count found");
+            return NULL;
+        }
+
+        if (session->peer == NULL) {
+            session->peer = wolfSSL_get_chain_X509(&session->chain, 0);
+        }
+        return session->peer;
+    }
+    WOLFSSL_MSG("No session passed in");
+
+    return NULL;
+}
+#endif /* OPENSSL_EXTRA */
+#endif /* SESSION_INDEX && SESSION_CERTS */
+
+
+#ifdef WOLFSSL_SESSION_STATS
+
+/* requires session_mutex lock held, WOLFSSL_SUCCESS on ok */
+static int get_locked_session_stats(word32* active, word32* total, word32* peak)
+{
+    int result = WOLFSSL_SUCCESS;
+    int i;
+    int count;
+    int idx;
+    word32 now   = 0;
+    word32 seen  = 0;
+    word32 ticks = LowResTimer();
+
+    (void)peak;
+
+    WOLFSSL_ENTER("get_locked_session_stats");
+
+    for (i = 0; i < SESSION_ROWS; i++) {
+        seen += SessionCache[i].totalCount;
+
+        if (active == NULL)
+            continue;  /* no need to calculate what we can't set */
+
+        count = min((word32)SessionCache[i].totalCount, SESSIONS_PER_ROW);
+        idx   = SessionCache[i].nextIdx - 1;
+        if (idx < 0)
+            idx = SESSIONS_PER_ROW - 1; /* if back to front previous was end */
+
+        for (; count > 0; --count, idx = idx ? idx - 1 : SESSIONS_PER_ROW - 1) {
+            if (idx >= SESSIONS_PER_ROW || idx < 0) {  /* sanity check */
+                WOLFSSL_MSG("Bad idx");
+                break;
+            }
+
+            /* if not expired then good */
+            if (ticks < (SessionCache[i].Sessions[idx].bornOn +
+                         SessionCache[i].Sessions[idx].timeout) ) {
+                now++;
+            }
+        }
+    }
+
+    if (active)
+        *active = now;
+
+    if (total)
+        *total = seen;
+
+#ifdef WOLFSSL_PEAK_SESSIONS
+    if (peak)
+        *peak = PeakSessions;
+#endif
+
+    WOLFSSL_LEAVE("get_locked_session_stats", result);
+
+    return result;
+}
+
+
+/* return WOLFSSL_SUCCESS on ok */
+int wolfSSL_get_session_stats(word32* active, word32* total, word32* peak,
+                              word32* maxSessions)
+{
+    int result = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_get_session_stats");
+
+    if (maxSessions) {
+        *maxSessions = SESSIONS_PER_ROW * SESSION_ROWS;
+
+        if (active == NULL && total == NULL && peak == NULL)
+            return result;  /* we're done */
+    }
+
+    /* user must provide at least one query value */
+    if (active == NULL && total == NULL && peak == NULL)
+        return BAD_FUNC_ARG;
+
+    if (wc_LockMutex(&session_mutex) != 0) {
+        return BAD_MUTEX_E;
+    }
+
+    result = get_locked_session_stats(active, total, peak);
+
+    if (wc_UnLockMutex(&session_mutex) != 0)
+        result = BAD_MUTEX_E;
+
+    WOLFSSL_LEAVE("wolfSSL_get_session_stats", result);
+
+    return result;
+}
+
+#endif /* WOLFSSL_SESSION_STATS */
+
+
+    #ifdef PRINT_SESSION_STATS
+
+    /* WOLFSSL_SUCCESS on ok */
+    int wolfSSL_PrintSessionStats(void)
+    {
+        word32 totalSessionsSeen = 0;
+        word32 totalSessionsNow = 0;
+        word32 peak = 0;
+        word32 maxSessions = 0;
+        int    i;
+        int    ret;
+        double E;               /* expected freq */
+        double chiSquare = 0;
+
+        ret = wolfSSL_get_session_stats(&totalSessionsNow, &totalSessionsSeen,
+                                        &peak, &maxSessions);
+        if (ret != WOLFSSL_SUCCESS)
+            return ret;
+        printf("Total Sessions Seen = %d\n", totalSessionsSeen);
+        printf("Total Sessions Now  = %d\n", totalSessionsNow);
+#ifdef WOLFSSL_PEAK_SESSIONS
+        printf("Peak  Sessions      = %d\n", peak);
+#endif
+        printf("Max   Sessions      = %d\n", maxSessions);
+
+        E = (double)totalSessionsSeen / SESSION_ROWS;
+
+        for (i = 0; i < SESSION_ROWS; i++) {
+            double diff = SessionCache[i].totalCount - E;
+            diff *= diff;                /* square    */
+            diff /= E;                   /* normalize */
+
+            chiSquare += diff;
+        }
+        printf("  chi-square = %5.1f, d.f. = %d\n", chiSquare,
+                                                     SESSION_ROWS - 1);
+        #if (SESSION_ROWS == 11)
+            printf(" .05 p value =  18.3, chi-square should be less\n");
+        #elif (SESSION_ROWS == 211)
+            printf(".05 p value  = 244.8, chi-square should be less\n");
+        #elif (SESSION_ROWS == 5981)
+            printf(".05 p value  = 6161.0, chi-square should be less\n");
+        #elif (SESSION_ROWS == 3)
+            printf(".05 p value  =   6.0, chi-square should be less\n");
+        #elif (SESSION_ROWS == 2861)
+            printf(".05 p value  = 2985.5, chi-square should be less\n");
+        #endif
+        printf("\n");
+
+        return ret;
+    }
+
+    #endif /* SESSION_STATS */
+
+#else  /* NO_SESSION_CACHE */
+
+/* No session cache version */
+WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret,
+        byte restoreSessionCerts)
+{
+    (void)ssl;
+    (void)masterSecret;
+    (void)restoreSessionCerts;
+
+    return NULL;
+}
+
+#endif /* NO_SESSION_CACHE */
+
+
+/* call before SSL_connect, if verifying will add name check to
+   date check and signature check */
+WOLFSSL_ABI
+int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn)
+{
+    WOLFSSL_ENTER("wolfSSL_check_domain_name");
+
+    if (ssl == NULL || dn == NULL) {
+        WOLFSSL_MSG("Bad function argument: NULL");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (ssl->buffers.domainName.buffer)
+        XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
+
+    ssl->buffers.domainName.length = (word32)XSTRLEN(dn);
+    ssl->buffers.domainName.buffer = (byte*)XMALLOC(
+            ssl->buffers.domainName.length + 1, ssl->heap, DYNAMIC_TYPE_DOMAIN);
+
+    if (ssl->buffers.domainName.buffer) {
+        unsigned char* domainName = ssl->buffers.domainName.buffer;
+        XMEMCPY(domainName, dn, ssl->buffers.domainName.length);
+        domainName[ssl->buffers.domainName.length] = '\0';
+        return WOLFSSL_SUCCESS;
+    }
+    else {
+        ssl->error = MEMORY_ERROR;
+        return WOLFSSL_FAILURE;
+    }
+}
+
+
+/* turn on wolfSSL zlib compression
+   returns WOLFSSL_SUCCESS for success, else error (not built in)
+*/
+int wolfSSL_set_compression(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_set_compression");
+    (void)ssl;
+#ifdef HAVE_LIBZ
+    ssl->options.usingCompression = 1;
+    return WOLFSSL_SUCCESS;
+#else
+    return NOT_COMPILED_IN;
+#endif
+}
+
+
+#ifndef USE_WINDOWS_API
+    #ifndef NO_WRITEV
+
+        /* simulate writev semantics, doesn't actually do block at a time though
+           because of SSL_write behavior and because front adds may be small */
+        int wolfSSL_writev(WOLFSSL* ssl, const struct iovec* iov, int iovcnt)
+        {
+        #ifdef WOLFSSL_SMALL_STACK
+            byte   staticBuffer[1]; /* force heap usage */
+        #else
+            byte   staticBuffer[FILE_BUFFER_SIZE];
+        #endif
+            byte* myBuffer  = staticBuffer;
+            int   dynamic   = 0;
+            int   sending   = 0;
+            int   idx       = 0;
+            int   i;
+            int   ret;
+
+            WOLFSSL_ENTER("wolfSSL_writev");
+
+            for (i = 0; i < iovcnt; i++)
+                sending += (int)iov[i].iov_len;
+
+            if (sending > (int)sizeof(staticBuffer)) {
+                myBuffer = (byte*)XMALLOC(sending, ssl->heap,
+                                                           DYNAMIC_TYPE_WRITEV);
+                if (!myBuffer)
+                    return MEMORY_ERROR;
+
+                dynamic = 1;
+            }
+
+            for (i = 0; i < iovcnt; i++) {
+                XMEMCPY(&myBuffer[idx], iov[i].iov_base, iov[i].iov_len);
+                idx += (int)iov[i].iov_len;
+            }
+
+            ret = wolfSSL_write(ssl, myBuffer, sending);
+
+            if (dynamic)
+                XFREE(myBuffer, ssl->heap, DYNAMIC_TYPE_WRITEV);
+
+            return ret;
+        }
+    #endif
+#endif
+
+
+#ifdef WOLFSSL_CALLBACKS
+
+    typedef struct itimerval Itimerval;
+
+    /* don't keep calling simple functions while setting up timer and signals
+       if no inlining these are the next best */
+
+    #define AddTimes(a, b, c)                       \
+        do {                                        \
+            c.tv_sec  = a.tv_sec  + b.tv_sec;       \
+            c.tv_usec = a.tv_usec + b.tv_usec;      \
+            if (c.tv_usec >=  1000000) {            \
+                c.tv_sec++;                         \
+                c.tv_usec -= 1000000;               \
+            }                                       \
+        } while (0)
+
+
+    #define SubtractTimes(a, b, c)                  \
+        do {                                        \
+            c.tv_sec  = a.tv_sec  - b.tv_sec;       \
+            c.tv_usec = a.tv_usec - b.tv_usec;      \
+            if (c.tv_usec < 0) {                    \
+                c.tv_sec--;                         \
+                c.tv_usec += 1000000;               \
+            }                                       \
+        } while (0)
+
+    #define CmpTimes(a, b, cmp)                     \
+        ((a.tv_sec  ==  b.tv_sec) ?                 \
+            (a.tv_usec cmp b.tv_usec) :             \
+            (a.tv_sec  cmp b.tv_sec))               \
+
+
+    /* do nothing handler */
+    static void myHandler(int signo)
+    {
+        (void)signo;
+        return;
+    }
+
+
+    static int wolfSSL_ex_wrapper(WOLFSSL* ssl, HandShakeCallBack hsCb,
+                                 TimeoutCallBack toCb, WOLFSSL_TIMEVAL timeout)
+    {
+        int       ret        = WOLFSSL_FATAL_ERROR;
+        int       oldTimerOn = 0;   /* was timer already on */
+        WOLFSSL_TIMEVAL startTime;
+        WOLFSSL_TIMEVAL endTime;
+        WOLFSSL_TIMEVAL totalTime;
+        Itimerval myTimeout;
+        Itimerval oldTimeout; /* if old timer adjust from total time to reset */
+        struct sigaction act, oact;
+
+        #define ERR_OUT(x) { ssl->hsInfoOn = 0; ssl->toInfoOn = 0; return x; }
+
+        if (hsCb) {
+            ssl->hsInfoOn = 1;
+            InitHandShakeInfo(&ssl->handShakeInfo, ssl);
+        }
+        if (toCb) {
+            ssl->toInfoOn = 1;
+            InitTimeoutInfo(&ssl->timeoutInfo);
+
+            if (gettimeofday(&startTime, 0) < 0)
+                ERR_OUT(GETTIME_ERROR);
+
+            /* use setitimer to simulate getitimer, init 0 myTimeout */
+            myTimeout.it_interval.tv_sec  = 0;
+            myTimeout.it_interval.tv_usec = 0;
+            myTimeout.it_value.tv_sec     = 0;
+            myTimeout.it_value.tv_usec    = 0;
+            if (setitimer(ITIMER_REAL, &myTimeout, &oldTimeout) < 0)
+                ERR_OUT(SETITIMER_ERROR);
+
+            if (oldTimeout.it_value.tv_sec || oldTimeout.it_value.tv_usec) {
+                oldTimerOn = 1;
+
+                /* is old timer going to expire before ours */
+                if (CmpTimes(oldTimeout.it_value, timeout, <)) {
+                    timeout.tv_sec  = oldTimeout.it_value.tv_sec;
+                    timeout.tv_usec = oldTimeout.it_value.tv_usec;
+                }
+            }
+            myTimeout.it_value.tv_sec  = timeout.tv_sec;
+            myTimeout.it_value.tv_usec = timeout.tv_usec;
+
+            /* set up signal handler, don't restart socket send/recv */
+            act.sa_handler = myHandler;
+            sigemptyset(&act.sa_mask);
+            act.sa_flags = 0;
+#ifdef SA_INTERRUPT
+            act.sa_flags |= SA_INTERRUPT;
+#endif
+            if (sigaction(SIGALRM, &act, &oact) < 0)
+                ERR_OUT(SIGACT_ERROR);
+
+            if (setitimer(ITIMER_REAL, &myTimeout, 0) < 0)
+                ERR_OUT(SETITIMER_ERROR);
+        }
+
+        /* do main work */
+#ifndef NO_WOLFSSL_CLIENT
+        if (ssl->options.side == WOLFSSL_CLIENT_END)
+            ret = wolfSSL_connect(ssl);
+#endif
+#ifndef NO_WOLFSSL_SERVER
+        if (ssl->options.side == WOLFSSL_SERVER_END)
+            ret = wolfSSL_accept(ssl);
+#endif
+
+        /* do callbacks */
+        if (toCb) {
+            if (oldTimerOn) {
+                gettimeofday(&endTime, 0);
+                SubtractTimes(endTime, startTime, totalTime);
+                /* adjust old timer for elapsed time */
+                if (CmpTimes(totalTime, oldTimeout.it_value, <))
+                    SubtractTimes(oldTimeout.it_value, totalTime,
+                                  oldTimeout.it_value);
+                else {
+                    /* reset value to interval, may be off */
+                    oldTimeout.it_value.tv_sec = oldTimeout.it_interval.tv_sec;
+                    oldTimeout.it_value.tv_usec =oldTimeout.it_interval.tv_usec;
+                }
+                /* keep iter the same whether there or not */
+            }
+            /* restore old handler */
+            if (sigaction(SIGALRM, &oact, 0) < 0)
+                ret = SIGACT_ERROR;    /* more pressing error, stomp */
+            else
+                /* use old settings which may turn off (expired or not there) */
+                if (setitimer(ITIMER_REAL, &oldTimeout, 0) < 0)
+                    ret = SETITIMER_ERROR;
+
+            /* if we had a timeout call callback */
+            if (ssl->timeoutInfo.timeoutName[0]) {
+                ssl->timeoutInfo.timeoutValue.tv_sec  = timeout.tv_sec;
+                ssl->timeoutInfo.timeoutValue.tv_usec = timeout.tv_usec;
+                (toCb)(&ssl->timeoutInfo);
+            }
+            /* clean up */
+            FreeTimeoutInfo(&ssl->timeoutInfo, ssl->heap);
+            ssl->toInfoOn = 0;
+        }
+        if (hsCb) {
+            FinishHandShakeInfo(&ssl->handShakeInfo);
+            (hsCb)(&ssl->handShakeInfo);
+            ssl->hsInfoOn = 0;
+        }
+        return ret;
+    }
+
+
+#ifndef NO_WOLFSSL_CLIENT
+
+    int wolfSSL_connect_ex(WOLFSSL* ssl, HandShakeCallBack hsCb,
+                          TimeoutCallBack toCb, WOLFSSL_TIMEVAL timeout)
+    {
+        WOLFSSL_ENTER("wolfSSL_connect_ex");
+        return wolfSSL_ex_wrapper(ssl, hsCb, toCb, timeout);
+    }
+
+#endif
+
+
+#ifndef NO_WOLFSSL_SERVER
+
+    int wolfSSL_accept_ex(WOLFSSL* ssl, HandShakeCallBack hsCb,
+                         TimeoutCallBack toCb, WOLFSSL_TIMEVAL timeout)
+    {
+        WOLFSSL_ENTER("wolfSSL_accept_ex");
+        return wolfSSL_ex_wrapper(ssl, hsCb, toCb, timeout);
+    }
+
+#endif
+
+#endif /* WOLFSSL_CALLBACKS */
+
+
+#ifndef NO_PSK
+
+    void wolfSSL_CTX_set_psk_client_callback(WOLFSSL_CTX* ctx,
+                                         wc_psk_client_callback cb)
+    {
+        WOLFSSL_ENTER("SSL_CTX_set_psk_client_callback");
+
+        if (ctx == NULL)
+            return;
+
+        ctx->havePSK = 1;
+        ctx->client_psk_cb = cb;
+    }
+
+
+    void wolfSSL_set_psk_client_callback(WOLFSSL* ssl,wc_psk_client_callback cb)
+    {
+        byte haveRSA = 1;
+        int  keySz   = 0;
+
+        WOLFSSL_ENTER("SSL_set_psk_client_callback");
+
+        if (ssl == NULL)
+            return;
+
+        ssl->options.havePSK = 1;
+        ssl->options.client_psk_cb = cb;
+
+        #ifdef NO_RSA
+            haveRSA = 0;
+        #endif
+        #ifndef NO_CERTS
+            keySz = ssl->buffers.keySz;
+        #endif
+        InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE,
+                   ssl->options.haveDH, ssl->options.haveNTRU,
+                   ssl->options.haveECDSAsig, ssl->options.haveECC,
+                   ssl->options.haveStaticECC, ssl->options.side);
+    }
+
+
+    void wolfSSL_CTX_set_psk_server_callback(WOLFSSL_CTX* ctx,
+                                         wc_psk_server_callback cb)
+    {
+        WOLFSSL_ENTER("SSL_CTX_set_psk_server_callback");
+        if (ctx == NULL)
+            return;
+        ctx->havePSK = 1;
+        ctx->server_psk_cb = cb;
+    }
+
+
+    void wolfSSL_set_psk_server_callback(WOLFSSL* ssl,wc_psk_server_callback cb)
+    {
+        byte haveRSA = 1;
+        int  keySz   = 0;
+
+        WOLFSSL_ENTER("SSL_set_psk_server_callback");
+        if (ssl == NULL)
+            return;
+
+        ssl->options.havePSK = 1;
+        ssl->options.server_psk_cb = cb;
+
+        #ifdef NO_RSA
+            haveRSA = 0;
+        #endif
+        #ifndef NO_CERTS
+            keySz = ssl->buffers.keySz;
+        #endif
+        InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE,
+                   ssl->options.haveDH, ssl->options.haveNTRU,
+                   ssl->options.haveECDSAsig, ssl->options.haveECC,
+                   ssl->options.haveStaticECC, ssl->options.side);
+    }
+
+
+    const char* wolfSSL_get_psk_identity_hint(const WOLFSSL* ssl)
+    {
+        WOLFSSL_ENTER("SSL_get_psk_identity_hint");
+
+        if (ssl == NULL || ssl->arrays == NULL)
+            return NULL;
+
+        return ssl->arrays->server_hint;
+    }
+
+
+    const char* wolfSSL_get_psk_identity(const WOLFSSL* ssl)
+    {
+        WOLFSSL_ENTER("SSL_get_psk_identity");
+
+        if (ssl == NULL || ssl->arrays == NULL)
+            return NULL;
+
+        return ssl->arrays->client_identity;
+    }
+
+
+    int wolfSSL_CTX_use_psk_identity_hint(WOLFSSL_CTX* ctx, const char* hint)
+    {
+        WOLFSSL_ENTER("SSL_CTX_use_psk_identity_hint");
+        if (hint == 0)
+            ctx->server_hint[0] = '\0';
+        else {
+            /* Qt does not call CTX_set_*_psk_callbacks where havePSK is set */
+            #ifdef WOLFSSL_QT
+            ctx->havePSK=1;
+            #endif
+            XSTRNCPY(ctx->server_hint, hint, MAX_PSK_ID_LEN);
+            ctx->server_hint[MAX_PSK_ID_LEN] = '\0'; /* null term */
+        }
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    int wolfSSL_use_psk_identity_hint(WOLFSSL* ssl, const char* hint)
+    {
+        WOLFSSL_ENTER("SSL_use_psk_identity_hint");
+
+        if (ssl == NULL || ssl->arrays == NULL)
+            return WOLFSSL_FAILURE;
+
+        if (hint == 0)
+            ssl->arrays->server_hint[0] = 0;
+        else {
+            XSTRNCPY(ssl->arrays->server_hint, hint,
+                                            sizeof(ssl->arrays->server_hint)-1);
+            ssl->arrays->server_hint[sizeof(ssl->arrays->server_hint)-1] = '\0';
+        }
+        return WOLFSSL_SUCCESS;
+    }
+
+#endif /* NO_PSK */
+
+
+#ifdef HAVE_ANON
+
+    int wolfSSL_CTX_allow_anon_cipher(WOLFSSL_CTX* ctx)
+    {
+        WOLFSSL_ENTER("wolfSSL_CTX_allow_anon_cipher");
+
+        if (ctx == NULL)
+            return WOLFSSL_FAILURE;
+
+        ctx->haveAnon = 1;
+
+        return WOLFSSL_SUCCESS;
+    }
+
+#endif /* HAVE_ANON */
+
+
+#ifndef NO_CERTS
+/* used to be defined on NO_FILESYSTEM only, but are generally useful */
+
+    int wolfSSL_CTX_load_verify_buffer_ex(WOLFSSL_CTX* ctx,
+                                         const unsigned char* in,
+                                         long sz, int format, int userChain,
+                                         word32 flags)
+    {
+        int verify;
+
+        WOLFSSL_ENTER("wolfSSL_CTX_load_verify_buffer_ex");
+
+        verify = GET_VERIFY_SETTING_CTX(ctx);
+        if (flags & WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY)
+            verify = VERIFY_SKIP_DATE;
+
+        if (format == WOLFSSL_FILETYPE_PEM)
+            return ProcessChainBuffer(ctx, in, sz, format, CA_TYPE, NULL,
+                                      verify);
+        else
+            return ProcessBuffer(ctx, in, sz, format, CA_TYPE, NULL, NULL,
+                                 userChain, verify);
+    }
+
+    /* wolfSSL extension allows DER files to be loaded from buffers as well */
+    int wolfSSL_CTX_load_verify_buffer(WOLFSSL_CTX* ctx,
+                                       const unsigned char* in,
+                                       long sz, int format)
+    {
+        return wolfSSL_CTX_load_verify_buffer_ex(ctx, in, sz, format, 0,
+            WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS);
+    }
+
+    int wolfSSL_CTX_load_verify_chain_buffer_format(WOLFSSL_CTX* ctx,
+                                       const unsigned char* in,
+                                       long sz, int format)
+    {
+        return wolfSSL_CTX_load_verify_buffer_ex(ctx, in, sz, format, 1,
+            WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS);
+    }
+
+
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    int wolfSSL_CTX_trust_peer_buffer(WOLFSSL_CTX* ctx,
+                                       const unsigned char* in,
+                                       long sz, int format)
+    {
+        WOLFSSL_ENTER("wolfSSL_CTX_trust_peer_buffer");
+
+        /* sanity check on arguments */
+        if (sz < 0 || in == NULL || ctx == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        if (format == WOLFSSL_FILETYPE_PEM)
+            return ProcessChainBuffer(ctx, in, sz, format, TRUSTED_PEER_TYPE,
+                                      NULL, GET_VERIFY_SETTING_CTX(ctx));
+        else
+            return ProcessBuffer(ctx, in, sz, format, TRUSTED_PEER_TYPE, NULL,
+                                 NULL, 0, GET_VERIFY_SETTING_CTX(ctx));
+    }
+#endif /* WOLFSSL_TRUST_PEER_CERT */
+
+
+    int wolfSSL_CTX_use_certificate_buffer(WOLFSSL_CTX* ctx,
+                                 const unsigned char* in, long sz, int format)
+    {
+        WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_buffer");
+        return ProcessBuffer(ctx, in, sz, format, CERT_TYPE, NULL, NULL, 0,
+                             GET_VERIFY_SETTING_CTX(ctx));
+    }
+
+
+    int wolfSSL_CTX_use_PrivateKey_buffer(WOLFSSL_CTX* ctx,
+                                 const unsigned char* in, long sz, int format)
+    {
+        WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_buffer");
+        return ProcessBuffer(ctx, in, sz, format, PRIVATEKEY_TYPE, NULL, NULL,
+                             0, GET_VERIFY_SETTING_CTX(ctx));
+    }
+
+#ifdef HAVE_PKCS11
+    int wolfSSL_CTX_use_PrivateKey_id(WOLFSSL_CTX* ctx, const unsigned char* id,
+                                      long sz, int devId, long keySz)
+    {
+        int ret = WOLFSSL_FAILURE;
+
+        FreeDer(&ctx->privateKey);
+        if (AllocDer(&ctx->privateKey, (word32)sz, PRIVATEKEY_TYPE,
+                                                              ctx->heap) == 0) {
+            XMEMCPY(ctx->privateKey->buffer, id, sz);
+            ctx->privateKeyId = 1;
+            ctx->privateKeySz = (word32)keySz;
+            if (devId != INVALID_DEVID)
+                ctx->privateKeyDevId = devId;
+            else
+                ctx->privateKeyDevId = ctx->devId;
+
+            ret = WOLFSSL_SUCCESS;
+        }
+
+        return ret;
+    }
+#endif
+
+    int wolfSSL_CTX_use_certificate_chain_buffer_format(WOLFSSL_CTX* ctx,
+                                 const unsigned char* in, long sz, int format)
+    {
+        WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_buffer_format");
+        return ProcessBuffer(ctx, in, sz, format, CERT_TYPE, NULL, NULL, 1,
+                             GET_VERIFY_SETTING_CTX(ctx));
+    }
+
+    int wolfSSL_CTX_use_certificate_chain_buffer(WOLFSSL_CTX* ctx,
+                                 const unsigned char* in, long sz)
+    {
+        return wolfSSL_CTX_use_certificate_chain_buffer_format(ctx, in, sz,
+                                                            WOLFSSL_FILETYPE_PEM);
+    }
+
+
+#ifndef NO_DH
+
+    /* server wrapper for ctx or ssl Diffie-Hellman parameters */
+    static int wolfSSL_SetTmpDH_buffer_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
+                                               const unsigned char* buf,
+                                               long sz, int format)
+    {
+        DerBuffer* der = NULL;
+        int    ret      = 0;
+        word32 pSz = MAX_DH_SIZE;
+        word32 gSz = MAX_DH_SIZE;
+    #ifdef WOLFSSL_SMALL_STACK
+        byte*  p = NULL;
+        byte*  g = NULL;
+    #else
+        byte   p[MAX_DH_SIZE];
+        byte   g[MAX_DH_SIZE];
+    #endif
+
+        if (ctx == NULL || buf == NULL)
+            return BAD_FUNC_ARG;
+
+        ret = AllocDer(&der, 0, DH_PARAM_TYPE, ctx->heap);
+        if (ret != 0) {
+            return ret;
+        }
+        der->buffer = (byte*)buf;
+        der->length = (word32)sz;
+
+    #ifdef WOLFSSL_SMALL_STACK
+        p = (byte*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+        g = (byte*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+
+        if (p == NULL || g == NULL) {
+            XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+            XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+            return MEMORY_E;
+        }
+    #endif
+
+        if (format != WOLFSSL_FILETYPE_ASN1 && format != WOLFSSL_FILETYPE_PEM)
+            ret = WOLFSSL_BAD_FILETYPE;
+        else {
+            if (format == WOLFSSL_FILETYPE_PEM) {
+#ifdef WOLFSSL_PEM_TO_DER
+                FreeDer(&der);
+                ret = PemToDer(buf, sz, DH_PARAM_TYPE, &der, ctx->heap,
+                               NULL, NULL);
+    #ifdef WOLFSSL_WPAS
+        #ifndef NO_DSA
+                if (ret < 0) {
+                    ret = PemToDer(buf, sz, DSA_PARAM_TYPE, &der, ctx->heap,
+                               NULL, NULL);
+                }
+        #endif
+    #endif /* WOLFSSL_WPAS */
+#else
+                ret = NOT_COMPILED_IN;
+#endif /* WOLFSSL_PEM_TO_DER */
+            }
+
+            if (ret == 0) {
+                if (wc_DhParamsLoad(der->buffer, der->length, p, &pSz, g, &gSz) < 0)
+                    ret = WOLFSSL_BAD_FILETYPE;
+                else if (ssl)
+                    ret = wolfSSL_SetTmpDH(ssl, p, pSz, g, gSz);
+                else
+                    ret = wolfSSL_CTX_SetTmpDH(ctx, p, pSz, g, gSz);
+            }
+        }
+
+        FreeDer(&der);
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+        XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+    #endif
+
+        return ret;
+    }
+
+
+    /* server Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */
+    int wolfSSL_SetTmpDH_buffer(WOLFSSL* ssl, const unsigned char* buf, long sz,
+                               int format)
+    {
+        if (ssl == NULL)
+            return BAD_FUNC_ARG;
+
+        return wolfSSL_SetTmpDH_buffer_wrapper(ssl->ctx, ssl, buf, sz, format);
+    }
+
+
+    /* server ctx Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */
+    int wolfSSL_CTX_SetTmpDH_buffer(WOLFSSL_CTX* ctx, const unsigned char* buf,
+                                   long sz, int format)
+    {
+        return wolfSSL_SetTmpDH_buffer_wrapper(ctx, NULL, buf, sz, format);
+    }
+
+#endif /* NO_DH */
+
+
+    int wolfSSL_use_certificate_buffer(WOLFSSL* ssl,
+                                 const unsigned char* in, long sz, int format)
+    {
+        WOLFSSL_ENTER("wolfSSL_use_certificate_buffer");
+        if (ssl == NULL)
+            return BAD_FUNC_ARG;
+
+        return ProcessBuffer(ssl->ctx, in, sz, format, CERT_TYPE, ssl, NULL, 0,
+                             GET_VERIFY_SETTING_SSL(ssl));
+    }
+
+
+    int wolfSSL_use_PrivateKey_buffer(WOLFSSL* ssl,
+                                 const unsigned char* in, long sz, int format)
+    {
+        WOLFSSL_ENTER("wolfSSL_use_PrivateKey_buffer");
+        if (ssl == NULL)
+            return BAD_FUNC_ARG;
+
+        return ProcessBuffer(ssl->ctx, in, sz, format, PRIVATEKEY_TYPE,
+                             ssl, NULL, 0, GET_VERIFY_SETTING_SSL(ssl));
+    }
+
+#ifdef HAVE_PKCS11
+    int wolfSSL_use_PrivateKey_id(WOLFSSL* ssl, const unsigned char* id,
+                                  long sz, int devId, long keySz)
+    {
+        int ret = WOLFSSL_FAILURE;
+
+        if (ssl->buffers.weOwnKey)
+            FreeDer(&ssl->buffers.key);
+        if (AllocDer(&ssl->buffers.key, (word32)sz, PRIVATEKEY_TYPE,
+                                                            ssl->heap) == 0) {
+            XMEMCPY(ssl->buffers.key->buffer, id, sz);
+            ssl->buffers.weOwnKey = 1;
+            ssl->buffers.keyId = 1;
+            ssl->buffers.keySz = (word32)keySz;
+            if (devId != INVALID_DEVID)
+                ssl->buffers.keyDevId = devId;
+            else
+                ssl->buffers.keyDevId = ssl->devId;
+
+            ret = WOLFSSL_SUCCESS;
+        }
+
+        return ret;
+    }
+#endif
+
+    int wolfSSL_use_certificate_chain_buffer_format(WOLFSSL* ssl,
+                                 const unsigned char* in, long sz, int format)
+    {
+        WOLFSSL_ENTER("wolfSSL_use_certificate_chain_buffer_format");
+        if (ssl == NULL)
+            return BAD_FUNC_ARG;
+
+        return ProcessBuffer(ssl->ctx, in, sz, format, CERT_TYPE,
+                             ssl, NULL, 1, GET_VERIFY_SETTING_SSL(ssl));
+    }
+
+    int wolfSSL_use_certificate_chain_buffer(WOLFSSL* ssl,
+                                 const unsigned char* in, long sz)
+    {
+        return wolfSSL_use_certificate_chain_buffer_format(ssl, in, sz,
+                                                            WOLFSSL_FILETYPE_PEM);
+    }
+
+
+    /* unload any certs or keys that SSL owns, leave CTX as is
+       WOLFSSL_SUCCESS on ok */
+    int wolfSSL_UnloadCertsKeys(WOLFSSL* ssl)
+    {
+        if (ssl == NULL) {
+            WOLFSSL_MSG("Null function arg");
+            return BAD_FUNC_ARG;
+        }
+
+        if (ssl->buffers.weOwnCert && !ssl->keepCert) {
+            WOLFSSL_MSG("Unloading cert");
+            FreeDer(&ssl->buffers.certificate);
+            #ifdef KEEP_OUR_CERT
+                FreeX509(ssl->ourCert);
+                if (ssl->ourCert) {
+                    XFREE(ssl->ourCert, ssl->heap, DYNAMIC_TYPE_X509);
+                    ssl->ourCert = NULL;
+                }
+            #endif
+            ssl->buffers.weOwnCert = 0;
+        }
+
+        if (ssl->buffers.weOwnCertChain) {
+            WOLFSSL_MSG("Unloading cert chain");
+            FreeDer(&ssl->buffers.certChain);
+            ssl->buffers.weOwnCertChain = 0;
+        }
+
+        if (ssl->buffers.weOwnKey) {
+            WOLFSSL_MSG("Unloading key");
+            FreeDer(&ssl->buffers.key);
+            ssl->buffers.weOwnKey = 0;
+        }
+
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    int wolfSSL_CTX_UnloadCAs(WOLFSSL_CTX* ctx)
+    {
+        WOLFSSL_ENTER("wolfSSL_CTX_UnloadCAs");
+
+        if (ctx == NULL)
+            return BAD_FUNC_ARG;
+
+        return wolfSSL_CertManagerUnloadCAs(ctx->cm);
+    }
+
+
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    int wolfSSL_CTX_Unload_trust_peers(WOLFSSL_CTX* ctx)
+    {
+        WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers");
+
+        if (ctx == NULL)
+            return BAD_FUNC_ARG;
+
+        return wolfSSL_CertManagerUnload_trust_peers(ctx->cm);
+    }
+#endif /* WOLFSSL_TRUST_PEER_CERT */
+/* old NO_FILESYSTEM end */
+#endif /* !NO_CERTS */
+
+
+#ifdef OPENSSL_EXTRA
+
+    int wolfSSL_add_all_algorithms(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_add_all_algorithms");
+        if (wolfSSL_Init() == WOLFSSL_SUCCESS)
+            return WOLFSSL_SUCCESS;
+        else
+            return WOLFSSL_FATAL_ERROR;
+    }
+
+    int wolfSSL_OpenSSL_add_all_algorithms_noconf(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_OpenSSL_add_all_algorithms_noconf");
+
+        if  (wolfSSL_add_all_algorithms() == WOLFSSL_FATAL_ERROR)
+            return WOLFSSL_FATAL_ERROR;
+
+        return  WOLFSSL_SUCCESS;
+    }
+
+    int wolfSSL_OpenSSL_add_all_algorithms_conf(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_OpenSSL_add_all_algorithms_conf");
+        /* This function is currently the same as
+        wolfSSL_OpenSSL_add_all_algorithms_noconf since we do not employ
+        the use of a wolfssl.cnf type configuration file and is only used for
+        OpenSSL compatability. */
+
+        if (wolfSSL_add_all_algorithms() == WOLFSSL_FATAL_ERROR) {
+            return WOLFSSL_FATAL_ERROR;
+        }
+        return WOLFSSL_SUCCESS;
+    }
+
+   /* returns previous set cache size which stays constant */
+    long wolfSSL_CTX_sess_set_cache_size(WOLFSSL_CTX* ctx, long sz)
+    {
+        /* cache size fixed at compile time in wolfSSL */
+        (void)ctx;
+        (void)sz;
+        WOLFSSL_MSG("session cache is set at compile time");
+        #ifndef NO_SESSION_CACHE
+            return (long)(SESSIONS_PER_ROW * SESSION_ROWS);
+        #else
+            return 0;
+        #endif
+    }
+
+#endif
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA)
+    void wolfSSL_CTX_set_quiet_shutdown(WOLFSSL_CTX* ctx, int mode)
+    {
+        WOLFSSL_ENTER("wolfSSL_CTX_set_quiet_shutdown");
+        if (mode)
+            ctx->quietShutdown = 1;
+    }
+
+
+    void wolfSSL_set_quiet_shutdown(WOLFSSL* ssl, int mode)
+    {
+        WOLFSSL_ENTER("wolfSSL_CTX_set_quiet_shutdown");
+        if (mode)
+            ssl->options.quietShutdown = 1;
+    }
+#endif
+
+#ifdef OPENSSL_EXTRA
+    void wolfSSL_set_bio(WOLFSSL* ssl, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr)
+    {
+        WOLFSSL_ENTER("wolfSSL_set_bio");
+
+        if (ssl == NULL) {
+            WOLFSSL_MSG("Bad argument, ssl was NULL");
+            return;
+        }
+
+        /* if WOLFSSL_BIO is socket type then set WOLFSSL socket to use */
+        if (rd != NULL && rd->type == WOLFSSL_BIO_SOCKET) {
+            wolfSSL_set_rfd(ssl, rd->num);
+        }
+        if (wr != NULL && wr->type == WOLFSSL_BIO_SOCKET) {
+            wolfSSL_set_wfd(ssl, wr->num);
+        }
+
+        /* free any existing WOLFSSL_BIOs in use */
+        if (ssl->biord != NULL) {
+            if (ssl->biord != ssl->biowr) {
+                if (ssl->biowr != NULL) {
+                    wolfSSL_BIO_free(ssl->biowr);
+                    ssl->biowr = NULL;
+                }
+            }
+            wolfSSL_BIO_free(ssl->biord);
+            ssl->biord = NULL;
+        }
+
+
+        ssl->biord = rd;
+        ssl->biowr = wr;
+
+        /* set SSL to use BIO callbacks instead */
+        if (((ssl->cbioFlag & WOLFSSL_CBIO_RECV) == 0) &&
+            (rd != NULL && rd->type != WOLFSSL_BIO_SOCKET)) {
+            ssl->CBIORecv = BioReceive;
+        }
+        if (((ssl->cbioFlag & WOLFSSL_CBIO_SEND) == 0) &&
+            (wr != NULL && wr->type != WOLFSSL_BIO_SOCKET)) {
+            ssl->CBIOSend = BioSend;
+        }
+
+        /* User programs should always retry reading from these BIOs */
+        if (rd) {
+            /* User writes to rd */
+            BIO_set_retry_write(rd);
+        }
+        if (wr) {
+            /* User reads from wr */
+            BIO_set_retry_read(wr);
+        }
+    }
+#endif
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || defined(HAVE_WEBSERVER)
+    void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX* ctx,
+                                       WOLF_STACK_OF(WOLFSSL_X509_NAME)* names)
+    {
+        WOLFSSL_ENTER("wolfSSL_CTX_set_client_CA_list");
+    #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA)
+        if (ctx != NULL)
+            ctx->ca_names = names;
+    #else
+        (void)ctx;
+        (void)names;
+    #endif
+    }
+
+
+    /* returns the CA's set on server side or the CA's sent from server when
+     * on client side */
+#if defined(SESSION_CERTS) && defined(OPENSSL_ALL)
+    WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get_client_CA_list(
+            const WOLFSSL* ssl)
+    {
+        WOLFSSL_ENTER("wolfSSL_get_client_CA_list");
+
+        if (ssl == NULL) {
+            WOLFSSL_MSG("Bad argument passed to wolfSSL_get_client_CA_list");
+            return NULL;
+        }
+
+        /* return list of CAs sent from the server */
+        if (ssl->options.side == WOLFSSL_CLIENT_END) {
+            WOLF_STACK_OF(WOLFSSL_X509)* sk;
+
+            sk = wolfSSL_get_peer_cert_chain(ssl);
+            if (sk != NULL) {
+                WOLF_STACK_OF(WOLFSSL_X509_NAME)* ret;
+                WOLFSSL_X509* x509;
+
+                ret = wolfSSL_sk_X509_NAME_new(NULL);
+                do {
+                    x509 = wolfSSL_sk_X509_pop(sk);
+                    if (x509 != NULL) {
+                        if (wolfSSL_X509_get_isCA(x509)) {
+                            if (wolfSSL_sk_X509_NAME_push(ret,
+                                    wolfSSL_X509_get_subject_name(x509)) != 0) {
+                                WOLFSSL_MSG("Error pushing X509 name to stack");
+                                /* continue on to try other certificates and
+                                 * do not fail out here */
+                            }
+                        }
+                        wolfSSL_X509_free(x509);
+                    }
+                } while (x509 != NULL);
+                wolfSSL_sk_X509_free(sk);
+                return ret;
+            }
+            return NULL;
+        }
+        else {
+            /* currently only can be set in the CTX */
+            return ssl->ctx->ca_names;
+        }
+    }
+#endif /* SESSION_CERTS */
+
+
+    #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \
+        defined(WOLFSSL_NGINX) || defined (WOLFSSL_HAPROXY)
+    /* registers client cert callback, called during handshake if server
+       requests client auth but user has not loaded client cert/key */
+    void wolfSSL_CTX_set_client_cert_cb(WOLFSSL_CTX *ctx, client_cert_cb cb)
+    {
+        WOLFSSL_ENTER("wolfSSL_CTX_set_client_cert_cb");
+
+        if (ctx != NULL) {
+            ctx->CBClientCert = cb;
+        }
+    }
+    #endif /* OPENSSL_ALL || OPENSSL_EXTRA || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
+
+#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA || HAVE_WEBSERVER */
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA)
+    WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_CTX_get_client_CA_list(
+            const WOLFSSL_CTX *s)
+    {
+        WOLFSSL_ENTER("wolfSSL_CTX_get_client_CA_list");
+
+        if (s == NULL)
+            return NULL;
+
+        return s->ca_names;
+    }
+#endif
+
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+    #if !defined(NO_RSA) && !defined(NO_CERTS)
+    WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char* fname)
+    {
+        /* The webserver build is using this to load a CA into the server
+         * for client authentication as an option. Have this return NULL in
+         * that case. If OPENSSL_EXTRA is enabled, go ahead and include
+         * the function. */
+    #ifdef OPENSSL_EXTRA
+        WOLFSSL_STACK *list = NULL;
+        WOLFSSL_STACK *node;
+        WOLFSSL_BIO* bio;
+        WOLFSSL_X509 *cert = NULL;
+        WOLFSSL_X509_NAME *subjectName = NULL;
+        unsigned long err;
+
+        WOLFSSL_ENTER("wolfSSL_load_client_CA_file");
+
+        bio = wolfSSL_BIO_new_file(fname, "r");
+        if (bio == NULL)
+            return NULL;
+
+        /* Read each certificate in the chain out of the file. */
+        while (wolfSSL_PEM_read_bio_X509(bio, &cert, NULL, NULL) != NULL) {
+            subjectName = wolfSSL_X509_get_subject_name(cert);
+            if (subjectName == NULL)
+                break;
+
+            node = wolfSSL_sk_new_node(NULL);
+            if (node == NULL)
+                break;
+            node->type = STACK_TYPE_X509_NAME;
+
+            /* Need a persistent copy of the subject name. */
+            node->data.name = wolfSSL_X509_NAME_dup(subjectName);
+            /*
+             * Original cert will be freed so make sure not to try to access
+             * it in the future.
+             */
+            node->data.name->x509 = NULL;
+
+            /* Put node on the front of the list. */
+            node->num  = (list == NULL) ? 1 : list->num + 1;
+            node->next = list;
+            list = node;
+
+            wolfSSL_X509_free(cert);
+            cert = NULL;
+        }
+
+        err = wolfSSL_ERR_peek_last_error();
+
+        if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
+                ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
+            /*
+             * wolfSSL_PEM_read_bio_X509 pushes an ASN_NO_PEM_HEADER error
+             * to the error queue on file end. This should not be left
+             * for the caller to find so we clear the last error.
+             */
+            wc_RemoveErrorNode(-1);
+        }
+
+        wolfSSL_X509_free(cert);
+        wolfSSL_BIO_free(bio);
+        return list;
+    #else
+        (void)fname;
+        return NULL;
+    #endif
+    }
+    #endif
+#endif
+
+#ifdef OPENSSL_EXTRA
+    #if !defined(NO_RSA) && !defined(NO_CERTS)
+    int wolfSSL_CTX_add_client_CA(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
+    {
+        WOLFSSL_STACK *node = NULL;
+        WOLFSSL_X509_NAME *subjectName = NULL;
+
+        WOLFSSL_ENTER("wolfSSL_CTX_add_client_CA");
+
+        if (ctx == NULL || x509 == NULL){
+            WOLFSSL_MSG("Bad argument");
+            return SSL_FAILURE;
+        }
+
+        subjectName = wolfSSL_X509_get_subject_name(x509);
+        if (subjectName == NULL){
+            WOLFSSL_MSG("invalid x509 data");
+            return SSL_FAILURE;
+        }
+
+        /* Alloc stack struct */
+        node = (WOLF_STACK_OF(WOLFSSL_X509_NAME)*)XMALLOC(
+                                           sizeof(WOLF_STACK_OF(WOLFSSL_X509_NAME)),
+                                           NULL, DYNAMIC_TYPE_OPENSSL);
+        if (node == NULL){
+            WOLFSSL_MSG("memory allocation error");
+            return SSL_FAILURE;
+        }
+        XMEMSET(node, 0, sizeof(WOLF_STACK_OF(WOLFSSL_X509_NAME)));
+
+        /* Alloc and copy WOLFSSL_X509_NAME */
+        node->data.name = (WOLFSSL_X509_NAME*)XMALLOC(
+                                              sizeof(WOLFSSL_X509_NAME),
+                                              NULL, DYNAMIC_TYPE_OPENSSL);
+        if (node->data.name == NULL) {
+            XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL);
+            WOLFSSL_MSG("memory allocation error");
+            return SSL_FAILURE;
+        }
+        XMEMCPY(node->data.name, subjectName, sizeof(WOLFSSL_X509_NAME));
+        XMEMSET(subjectName, 0, sizeof(WOLFSSL_X509_NAME));
+
+        /* push new node onto head of stack */
+        node->num = (ctx->ca_names == NULL) ? 1 : ctx->ca_names->num + 1;
+        node->next = ctx->ca_names;
+        ctx->ca_names = node;
+        return SSL_SUCCESS;
+    }
+    #endif
+
+    #ifndef NO_WOLFSSL_STUB
+    int wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX* ctx)
+    {
+        /* TODO:, not needed in goahead */
+        (void)ctx;
+        WOLFSSL_STUB("SSL_CTX_set_default_verify_paths");
+        return SSL_NOT_IMPLEMENTED;
+    }
+    #endif
+
+    #if defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA256) \
+        && !defined(WC_NO_RNG)
+    static const byte srp_N[] = {
+        0xEE, 0xAF, 0x0A, 0xB9, 0xAD, 0xB3, 0x8D, 0xD6, 0x9C, 0x33, 0xF8,
+        0x0A, 0xFA, 0x8F, 0xC5, 0xE8, 0x60, 0x72, 0x61, 0x87, 0x75, 0xFF,
+        0x3C, 0x0B, 0x9E, 0xA2, 0x31, 0x4C, 0x9C, 0x25, 0x65, 0x76, 0xD6,
+        0x74, 0xDF, 0x74, 0x96, 0xEA, 0x81, 0xD3, 0x38, 0x3B, 0x48, 0x13,
+        0xD6, 0x92, 0xC6, 0xE0, 0xE0, 0xD5, 0xD8, 0xE2, 0x50, 0xB9, 0x8B,
+        0xE4, 0x8E, 0x49, 0x5C, 0x1D, 0x60, 0x89, 0xDA, 0xD1, 0x5D, 0xC7,
+        0xD7, 0xB4, 0x61, 0x54, 0xD6, 0xB6, 0xCE, 0x8E, 0xF4, 0xAD, 0x69,
+        0xB1, 0x5D, 0x49, 0x82, 0x55, 0x9B, 0x29, 0x7B, 0xCF, 0x18, 0x85,
+        0xC5, 0x29, 0xF5, 0x66, 0x66, 0x0E, 0x57, 0xEC, 0x68, 0xED, 0xBC,
+        0x3C, 0x05, 0x72, 0x6C, 0xC0, 0x2F, 0xD4, 0xCB, 0xF4, 0x97, 0x6E,
+        0xAA, 0x9A, 0xFD, 0x51, 0x38, 0xFE, 0x83, 0x76, 0x43, 0x5B, 0x9F,
+        0xC6, 0x1D, 0x2F, 0xC0, 0xEB, 0x06, 0xE3
+    };
+    static const byte srp_g[] = {
+        0x02
+    };
+
+    int wolfSSL_CTX_set_srp_username(WOLFSSL_CTX* ctx, char* username)
+    {
+        int r = 0;
+        SrpSide srp_side = SRP_CLIENT_SIDE;
+        WC_RNG rng;
+        byte salt[SRP_SALT_SIZE];
+
+        WOLFSSL_ENTER("wolfSSL_CTX_set_srp_username");
+        if (ctx == NULL || ctx->srp == NULL || username==NULL)
+            return SSL_FAILURE;
+
+        if (ctx->method->side == WOLFSSL_SERVER_END){
+            srp_side = SRP_SERVER_SIDE;
+        } else if (ctx->method->side == WOLFSSL_CLIENT_END){
+            srp_side = SRP_CLIENT_SIDE;
+        } else {
+            WOLFSSL_MSG("Init CTX failed");
+            return SSL_FAILURE;
+        }
+
+        if (wc_SrpInit(ctx->srp, SRP_TYPE_SHA256, srp_side) < 0){
+            WOLFSSL_MSG("Init CTX failed");
+            XFREE(ctx->srp, ctx->heap, DYNAMIC_TYPE_SRP);
+            wolfSSL_CTX_free(ctx);
+            return SSL_FAILURE;
+        }
+        r = wc_SrpSetUsername(ctx->srp, (const byte*)username,
+                              (word32)XSTRLEN(username));
+        if (r < 0) {
+            WOLFSSL_MSG("fail to set srp username.");
+            return SSL_FAILURE;
+        }
+
+        /* if wolfSSL_CTX_set_srp_password has already been called, */
+        /* execute wc_SrpSetPassword here */
+        if (ctx->srp_password != NULL){
+            if (wc_InitRng(&rng) < 0){
+                WOLFSSL_MSG("wc_InitRng failed");
+                return SSL_FAILURE;
+            }
+            XMEMSET(salt, 0, sizeof(salt)/sizeof(salt[0]));
+            if (wc_RNG_GenerateBlock(&rng, salt,
+                                     sizeof(salt)/sizeof(salt[0])) <  0){
+                WOLFSSL_MSG("wc_RNG_GenerateBlock failed");
+                wc_FreeRng(&rng);
+                return SSL_FAILURE;
+            }
+            if (wc_SrpSetParams(ctx->srp, srp_N, sizeof(srp_N)/sizeof(srp_N[0]),
+                                srp_g, sizeof(srp_g)/sizeof(srp_g[0]),
+                                salt, sizeof(salt)/sizeof(salt[0])) < 0){
+                WOLFSSL_MSG("wc_SrpSetParam failed");
+                wc_FreeRng(&rng);
+                return SSL_FAILURE;
+            }
+            r = wc_SrpSetPassword(ctx->srp,
+                     (const byte*)ctx->srp_password,
+                     (word32)XSTRLEN((char *)ctx->srp_password));
+            if (r < 0) {
+                WOLFSSL_MSG("fail to set srp password.");
+                return SSL_FAILURE;
+            }
+            wc_FreeRng(&rng);
+            XFREE(ctx->srp_password, ctx->heap, DYNAMIC_TYPE_SRP);
+            ctx->srp_password = NULL;
+        }
+
+        return SSL_SUCCESS;
+    }
+
+    int wolfSSL_CTX_set_srp_password(WOLFSSL_CTX* ctx, char* password)
+    {
+        int r;
+        WC_RNG rng;
+        byte salt[SRP_SALT_SIZE];
+
+        WOLFSSL_ENTER("wolfSSL_CTX_set_srp_password");
+        if (ctx == NULL || ctx->srp == NULL || password == NULL)
+            return SSL_FAILURE;
+
+        if (ctx->srp->user != NULL){
+            if (wc_InitRng(&rng) < 0){
+                WOLFSSL_MSG("wc_InitRng failed");
+                return SSL_FAILURE;
+            }
+            XMEMSET(salt, 0, sizeof(salt)/sizeof(salt[0]));
+            if (wc_RNG_GenerateBlock(&rng, salt,
+                                     sizeof(salt)/sizeof(salt[0])) <  0){
+                WOLFSSL_MSG("wc_RNG_GenerateBlock failed");
+                wc_FreeRng(&rng);
+                return SSL_FAILURE;
+            }
+            if (wc_SrpSetParams(ctx->srp, srp_N, sizeof(srp_N)/sizeof(srp_N[0]),
+                                srp_g, sizeof(srp_g)/sizeof(srp_g[0]),
+                                salt, sizeof(salt)/sizeof(salt[0])) < 0){
+                WOLFSSL_MSG("wc_SrpSetParam failed");
+                wc_FreeRng(&rng);
+                return SSL_FAILURE;
+            }
+            r = wc_SrpSetPassword(ctx->srp, (const byte*)password,
+                                  (word32)XSTRLEN(password));
+            if (r < 0) {
+                WOLFSSL_MSG("wc_SrpSetPassword failed.");
+                wc_FreeRng(&rng);
+                return SSL_FAILURE;
+            }
+            if (ctx->srp_password != NULL){
+                XFREE(ctx->srp_password,NULL,
+                      DYNAMIC_TYPE_SRP);
+                ctx->srp_password = NULL;
+            }
+            wc_FreeRng(&rng);
+        } else {
+            /* save password for wolfSSL_set_srp_username */
+            if (ctx->srp_password != NULL)
+                XFREE(ctx->srp_password,ctx->heap, DYNAMIC_TYPE_SRP);
+
+            ctx->srp_password = (byte*)XMALLOC(XSTRLEN(password) + 1, ctx->heap,
+                                               DYNAMIC_TYPE_SRP);
+            if (ctx->srp_password == NULL){
+                WOLFSSL_MSG("memory allocation error");
+                return SSL_FAILURE;
+            }
+            XMEMCPY(ctx->srp_password, password, XSTRLEN(password) + 1);
+        }
+        return SSL_SUCCESS;
+    }
+    #endif /* WOLFCRYPT_HAVE_SRP && !NO_SHA256 && !WC_NO_RNG */
+
+    /* keyblock size in bytes or -1 */
+    int wolfSSL_get_keyblock_size(WOLFSSL* ssl)
+    {
+        if (ssl == NULL)
+            return WOLFSSL_FATAL_ERROR;
+
+        return 2 * (ssl->specs.key_size + ssl->specs.iv_size +
+                    ssl->specs.hash_size);
+    }
+
+
+    /* store keys returns WOLFSSL_SUCCESS or -1 on error */
+    int wolfSSL_get_keys(WOLFSSL* ssl, unsigned char** ms, unsigned int* msLen,
+                                     unsigned char** sr, unsigned int* srLen,
+                                     unsigned char** cr, unsigned int* crLen)
+    {
+        if (ssl == NULL || ssl->arrays == NULL)
+            return WOLFSSL_FATAL_ERROR;
+
+        *ms = ssl->arrays->masterSecret;
+        *sr = ssl->arrays->serverRandom;
+        *cr = ssl->arrays->clientRandom;
+
+        *msLen = SECRET_LEN;
+        *srLen = RAN_LEN;
+        *crLen = RAN_LEN;
+
+        return WOLFSSL_SUCCESS;
+    }
+
+#endif /* OPENSSL_EXTRA */
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA)
+    void wolfSSL_set_accept_state(WOLFSSL* ssl)
+    {
+        WOLFSSL_ENTER("wolfSSL_set_accept_state");
+        if (ssl->options.side == WOLFSSL_CLIENT_END) {
+    #ifdef HAVE_ECC
+            ecc_key key;
+            word32 idx = 0;
+
+            if (ssl->options.haveStaticECC && ssl->buffers.key != NULL) {
+                if (wc_ecc_init(&key) >= 0) {
+                    if (wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &idx, &key,
+                                                   ssl->buffers.key->length) != 0) {
+                        ssl->options.haveECDSAsig = 0;
+                        ssl->options.haveECC = 0;
+                        ssl->options.haveStaticECC = 0;
+                    }
+                    wc_ecc_free(&key);
+                }
+            }
+    #endif
+
+    #ifndef NO_DH
+            if (!ssl->options.haveDH && ssl->ctx->haveDH) {
+                ssl->buffers.serverDH_P = ssl->ctx->serverDH_P;
+                ssl->buffers.serverDH_G = ssl->ctx->serverDH_G;
+                ssl->options.haveDH = 1;
+            }
+    #endif
+        }
+
+        if (InitSSL_Side(ssl, WOLFSSL_SERVER_END) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("Error initializing server side");
+        }
+    }
+
+#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA */
+
+    /* return true if connection established */
+    int wolfSSL_is_init_finished(WOLFSSL* ssl)
+    {
+        if (ssl == NULL)
+            return 0;
+
+        if (ssl->options.handShakeState == HANDSHAKE_DONE)
+            return 1;
+
+        return 0;
+    }
+
+#ifdef OPENSSL_EXTRA
+
+    void wolfSSL_CTX_set_tmp_rsa_callback(WOLFSSL_CTX* ctx,
+                                      WOLFSSL_RSA*(*f)(WOLFSSL*, int, int))
+    {
+        /* wolfSSL verifies all these internally */
+        (void)ctx;
+        (void)f;
+    }
+
+
+    void wolfSSL_set_shutdown(WOLFSSL* ssl, int opt)
+    {
+        WOLFSSL_ENTER("wolfSSL_set_shutdown");
+        if(ssl==NULL) {
+            WOLFSSL_MSG("Shutdown not set. ssl is null");
+            return;
+        }
+
+        ssl->options.sentNotify =  (opt&WOLFSSL_SENT_SHUTDOWN) > 0;
+        ssl->options.closeNotify = (opt&WOLFSSL_RECEIVED_SHUTDOWN) > 0;
+    }
+
+
+    long wolfSSL_CTX_get_options(WOLFSSL_CTX* ctx)
+    {
+        WOLFSSL_ENTER("wolfSSL_CTX_get_options");
+        WOLFSSL_MSG("wolfSSL options are set through API calls and macros");
+        if(ctx == NULL)
+            return BAD_FUNC_ARG;
+        return ctx->mask;
+    }
+
+#endif
+
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+
+    static long wolf_set_options(long old_op, long op);
+    long wolfSSL_CTX_set_options(WOLFSSL_CTX* ctx, long opt)
+    {
+        WOLFSSL_ENTER("SSL_CTX_set_options");
+
+        if (ctx == NULL)
+            return BAD_FUNC_ARG;
+
+        ctx->mask = wolf_set_options(ctx->mask, opt);
+
+        return ctx->mask;
+    }
+
+#endif
+
+#ifdef OPENSSL_EXTRA
+
+    long wolfSSL_CTX_clear_options(WOLFSSL_CTX* ctx, long opt)
+    {
+        WOLFSSL_ENTER("SSL_CTX_clear_options");
+        if(ctx == NULL)
+            return BAD_FUNC_ARG;
+        ctx->mask &= ~opt;
+        return ctx->mask;
+    }
+
+    int wolfSSL_set_rfd(WOLFSSL* ssl, int rfd)
+    {
+        WOLFSSL_ENTER("SSL_set_rfd");
+        ssl->rfd = rfd;      /* not used directly to allow IO callbacks */
+
+        ssl->IOCB_ReadCtx  = &ssl->rfd;
+
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    int wolfSSL_set_wfd(WOLFSSL* ssl, int wfd)
+    {
+        WOLFSSL_ENTER("SSL_set_wfd");
+        ssl->wfd = wfd;      /* not used directly to allow IO callbacks */
+
+        ssl->IOCB_WriteCtx  = &ssl->wfd;
+
+        return WOLFSSL_SUCCESS;
+    }
+
+#ifndef NO_CERTS
+
+    WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(WOLFSSL_CTX* ctx)
+    {
+        if (ctx == NULL) {
+            return NULL;
+        }
+
+        return &ctx->x509_store;
+    }
+
+    void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, WOLFSSL_X509_STORE* str)
+    {
+        if (ctx == NULL || str == NULL) {
+            return;
+        }
+
+        /* free cert manager if have one */
+        if (ctx->cm != NULL) {
+            wolfSSL_CertManagerFree(ctx->cm);
+        }
+        ctx->cm               = str->cm;
+
+        /* free existing store if it exists */
+        if (ctx->x509_store_pt != NULL) {
+            /* cert manager was free'd a little earlier in this function */
+            ctx->x509_store_pt->cm = NULL;
+        }
+        wolfSSL_X509_STORE_free(ctx->x509_store_pt);
+        ctx->x509_store.cache = str->cache;
+        ctx->x509_store_pt    = str; /* take ownership of store and free it
+                                        with CTX free */
+    }
+
+
+    WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get_current_cert(
+                                                    WOLFSSL_X509_STORE_CTX* ctx)
+    {
+        WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_current_cert");
+        if (ctx)
+            return ctx->current_cert;
+        return NULL;
+    }
+
+
+    int wolfSSL_X509_STORE_CTX_get_error(WOLFSSL_X509_STORE_CTX* ctx)
+    {
+        WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_error");
+        if (ctx != NULL)
+            return ctx->error;
+        return 0;
+    }
+
+
+    int wolfSSL_X509_STORE_CTX_get_error_depth(WOLFSSL_X509_STORE_CTX* ctx)
+    {
+        WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_error_depth");
+        if(ctx)
+            return ctx->error_depth;
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    void wolfSSL_X509_STORE_CTX_set_verify_cb(WOLFSSL_X509_STORE_CTX *ctx,
+                                  WOLFSSL_X509_STORE_CTX_verify_cb verify_cb)
+    {
+        WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_verify_cb");
+        if(ctx == NULL)
+            return;
+        ctx->verify_cb = verify_cb;
+    }
+
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+    void wolfSSL_X509_STORE_set_verify_cb(WOLFSSL_X509_STORE *st,
+                                 WOLFSSL_X509_STORE_CTX_verify_cb verify_cb)
+    {
+        WOLFSSL_ENTER("WOLFSSL_X509_STORE_set_verify_cb");
+        if (st != NULL) {
+            st->verify_cb = verify_cb;
+        }
+    }
+#endif
+
+
+#endif /* !NO_CERTS */
+
+    WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_md(void)
+    {
+        static WOLFSSL_BIO_METHOD meth;
+
+        WOLFSSL_ENTER("wolfSSL_BIO_f_md");
+        meth.type = WOLFSSL_BIO_MD;
+
+        return &meth;
+    }
+
+    /* return the context and initialize the BIO state */
+    int wolfSSL_BIO_get_md_ctx(WOLFSSL_BIO *bio, WOLFSSL_EVP_MD_CTX **mdcp)
+    {
+        int ret = WOLFSSL_FAILURE;
+
+        if ((bio != NULL) && (mdcp != NULL)) {
+            *mdcp = (WOLFSSL_EVP_MD_CTX*)bio->ptr;
+            ret = WOLFSSL_SUCCESS;
+        }
+
+        return ret;
+    }
+
+    WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_buffer(void)
+    {
+        static WOLFSSL_BIO_METHOD meth;
+
+        WOLFSSL_ENTER("BIO_f_buffer");
+        meth.type = WOLFSSL_BIO_BUFFER;
+
+        return &meth;
+    }
+
+    #ifndef NO_WOLFSSL_STUB
+    long wolfSSL_BIO_set_write_buffer_size(WOLFSSL_BIO* bio, long size)
+    {
+        /* wolfSSL has internal buffer, compatibility only */
+        WOLFSSL_ENTER("BIO_set_write_buffer_size");
+        WOLFSSL_STUB("BIO_set_write_buffer_size");
+        (void)bio;
+        return size;
+    }
+    #endif
+
+    WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_bio(void)
+    {
+        static WOLFSSL_BIO_METHOD bio_meth;
+
+        WOLFSSL_ENTER("wolfSSL_BIO_s_bio");
+        bio_meth.type = WOLFSSL_BIO_BIO;
+
+        return &bio_meth;
+    }
+
+
+#ifndef NO_FILESYSTEM
+    WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_file(void)
+    {
+        static WOLFSSL_BIO_METHOD file_meth;
+
+        WOLFSSL_ENTER("wolfSSL_BIO_s_file");
+        file_meth.type = WOLFSSL_BIO_FILE;
+
+        return &file_meth;
+    }
+#endif
+
+
+    WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_ssl(void)
+    {
+        static WOLFSSL_BIO_METHOD meth;
+
+        WOLFSSL_ENTER("wolfSSL_BIO_f_ssl");
+        meth.type = WOLFSSL_BIO_SSL;
+
+        return &meth;
+    }
+
+
+    WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_socket(void)
+    {
+        static WOLFSSL_BIO_METHOD meth;
+
+        WOLFSSL_ENTER("wolfSSL_BIO_s_socket");
+        meth.type = WOLFSSL_BIO_SOCKET;
+
+        return &meth;
+    }
+
+
+    WOLFSSL_BIO* wolfSSL_BIO_new_socket(int sfd, int closeF)
+    {
+        WOLFSSL_BIO* bio = wolfSSL_BIO_new(wolfSSL_BIO_s_socket());
+
+        WOLFSSL_ENTER("BIO_new_socket");
+        if (bio) {
+            bio->type  = WOLFSSL_BIO_SOCKET;
+            bio->shutdown = (byte)closeF;
+            bio->num   = sfd;
+        }
+        return bio;
+    }
+
+
+    int wolfSSL_BIO_eof(WOLFSSL_BIO* b)
+    {
+        WOLFSSL_ENTER("BIO_eof");
+        if ((b != NULL) && (b->eof))
+            return 1;
+
+        return 0;
+    }
+
+
+    long wolfSSL_BIO_set_ssl(WOLFSSL_BIO* b, WOLFSSL* ssl, int closeF)
+    {
+        WOLFSSL_ENTER("wolfSSL_BIO_set_ssl");
+
+        if (b != NULL) {
+            b->ptr   = ssl;
+            b->shutdown = (byte)closeF;
+    /* add to ssl for bio free if SSL_free called before/instead of free_all? */
+        }
+
+        return 0;
+    }
+
+#ifndef NO_FILESYSTEM
+    long wolfSSL_BIO_set_fd(WOLFSSL_BIO* b, int fd, int closeF)
+    {
+        WOLFSSL_ENTER("wolfSSL_BIO_set_fd");
+
+        if (b != NULL) {
+            b->num = fd;
+            b->shutdown = (byte)closeF;
+        }
+
+        return WOLFSSL_SUCCESS;
+    }
+#endif
+
+    /* Sets the close flag */
+    int wolfSSL_BIO_set_close(WOLFSSL_BIO *b, long flag)
+    {
+        WOLFSSL_ENTER("wolfSSL_BIO_set_close");
+        if (b != NULL) {
+            b->shutdown = (byte)flag;
+        }
+
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    WOLFSSL_BIO* wolfSSL_BIO_new(WOLFSSL_BIO_METHOD* method)
+    {
+        WOLFSSL_BIO* bio;
+
+        WOLFSSL_ENTER("wolfSSL_BIO_new");
+        if (method == NULL) {
+            WOLFSSL_MSG("Bad method pointer passed in");
+            return NULL;
+        }
+
+        bio = (WOLFSSL_BIO*) XMALLOC(sizeof(WOLFSSL_BIO), 0,
+                DYNAMIC_TYPE_OPENSSL);
+        if (bio) {
+            XMEMSET(bio, 0, sizeof(WOLFSSL_BIO));
+            bio->type = (byte)method->type;
+            bio->method = method;
+            bio->shutdown = BIO_CLOSE; /* default to close things */
+            bio->init = 1;
+            if (method->type != WOLFSSL_BIO_FILE &&
+                    method->type != WOLFSSL_BIO_SOCKET &&
+                    method->type != WOLFSSL_BIO_MD) {
+                bio->mem_buf =(WOLFSSL_BUF_MEM*)XMALLOC(sizeof(WOLFSSL_BUF_MEM),
+                                                       0, DYNAMIC_TYPE_OPENSSL);
+                if (bio->mem_buf == NULL) {
+                    WOLFSSL_MSG("Memory error");
+                    wolfSSL_BIO_free(bio);
+                    return NULL;
+                }
+                bio->mem_buf->data = (char*)bio->ptr;
+            }
+
+            if (method->type == WOLFSSL_BIO_MD) {
+                bio->ptr = wolfSSL_EVP_MD_CTX_new();
+                if (bio->ptr == NULL) {
+                    WOLFSSL_MSG("Memory error");
+                    wolfSSL_BIO_free(bio);
+                    return NULL;
+                }
+            }
+
+            /* check if is custom method */
+            if (method->createCb) {
+                method->createCb(bio);
+            }
+        }
+        return bio;
+    }
+
+    WOLFSSL_BIO* wolfSSL_BIO_new_mem_buf(const void* buf, int len)
+    {
+        WOLFSSL_BIO* bio = NULL;
+
+        if (buf == NULL || len < 0) {
+            return bio;
+        }
+
+        bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem());
+        if (bio == NULL) {
+            return bio;
+        }
+
+        bio->num = bio->wrSz = len;
+        bio->ptr = (byte*)XMALLOC(len, 0, DYNAMIC_TYPE_OPENSSL);
+        if (bio->ptr == NULL) {
+            wolfSSL_BIO_free(bio);
+            return NULL;
+        }
+        if (bio->mem_buf != NULL) {
+            bio->mem_buf->data = (char*)bio->ptr;
+            bio->mem_buf->length = bio->num;
+        }
+
+        XMEMCPY(bio->ptr, buf, len);
+
+        return bio;
+    }
+
+    /*
+     * Note : If the flag BIO_NOCLOSE is set then freeing memory buffers is up
+     *        to the application.
+     * Returns 1 on success, 0 on failure
+     */
+    int wolfSSL_BIO_free(WOLFSSL_BIO* bio)
+    {
+        int ret;
+
+        /* unchain?, doesn't matter in goahead since from free all */
+        WOLFSSL_ENTER("wolfSSL_BIO_free");
+        if (bio) {
+
+            if (bio->infoCb) {
+                /* info callback is called before free */
+                ret = (int)bio->infoCb(bio, WOLFSSL_BIO_CB_FREE, NULL, 0, 0, 1);
+                if (ret <= 0) {
+                    return ret;
+                }
+            }
+
+            /* call custom set free callback */
+            if (bio->method && bio->method->freeCb) {
+                bio->method->freeCb(bio);
+            }
+
+            /* remove from pair by setting the paired bios pair to NULL */
+            if (bio->pair != NULL) {
+                bio->pair->pair = NULL;
+            }
+
+            if (bio->shutdown) {
+                if (bio->type == WOLFSSL_BIO_SSL && bio->ptr)
+                    wolfSSL_free((WOLFSSL*)bio->ptr);
+            #ifdef CloseSocket
+                if (bio->type == WOLFSSL_BIO_SOCKET && bio->num)
+                    CloseSocket(bio->num);
+            #endif
+            }
+
+        #ifndef NO_FILESYSTEM
+            if (bio->type == WOLFSSL_BIO_FILE && bio->shutdown == BIO_CLOSE) {
+                if (bio->ptr) {
+                    XFCLOSE((XFILE)bio->ptr);
+                }
+            }
+        #endif
+
+            if (bio->shutdown != BIO_NOCLOSE) {
+                if (bio->type == WOLFSSL_BIO_MEMORY && bio->ptr != NULL) {
+                    if (bio->mem_buf != NULL) {
+                        if (bio->mem_buf->data != (char*)bio->ptr) {
+                            XFREE(bio->ptr, bio->heap, DYNAMIC_TYPE_OPENSSL);
+                            bio->ptr = NULL;
+                        }
+                    }
+                    else {
+                        XFREE(bio->ptr, bio->heap, DYNAMIC_TYPE_OPENSSL);
+                        bio->ptr = NULL;
+                    }
+                }
+                if (bio->mem_buf != NULL) {
+                    wolfSSL_BUF_MEM_free(bio->mem_buf);
+                    bio->mem_buf = NULL;
+                }
+            }
+
+            if (bio->type == WOLFSSL_BIO_MD) {
+                wolfSSL_EVP_MD_CTX_free((WOLFSSL_EVP_MD_CTX*)bio->ptr);
+            }
+
+            XFREE(bio, 0, DYNAMIC_TYPE_OPENSSL);
+        }
+        return 1;
+    }
+
+    /* like BIO_free, but no return value */
+    void wolfSSL_BIO_vfree(WOLFSSL_BIO* bio)
+    {
+        wolfSSL_BIO_free(bio);
+    }
+
+
+    int wolfSSL_BIO_free_all(WOLFSSL_BIO* bio)
+    {
+        WOLFSSL_ENTER("BIO_free_all");
+        while (bio) {
+            WOLFSSL_BIO* next = bio->next;
+            wolfSSL_BIO_free(bio);
+            bio = next;
+        }
+        return 0;
+    }
+
+
+    WOLFSSL_BIO* wolfSSL_BIO_push(WOLFSSL_BIO* top, WOLFSSL_BIO* append)
+    {
+        WOLFSSL_ENTER("BIO_push");
+        top->next    = append;
+        append->prev = top;
+
+        return top;
+    }
+#endif /* OPENSSL_EXTRA */
+
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+
+    void wolfSSL_CTX_set_default_passwd_cb_userdata(WOLFSSL_CTX* ctx,
+                                                   void* userdata)
+    {
+        WOLFSSL_ENTER("SSL_CTX_set_default_passwd_cb_userdata");
+        if (ctx)
+            ctx->passwd_userdata = userdata;
+    }
+
+
+    void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX* ctx,pem_password_cb* cb)
+    {
+        WOLFSSL_ENTER("SSL_CTX_set_default_passwd_cb");
+        if (ctx)
+            ctx->passwd_cb = cb;
+    }
+
+    pem_password_cb* wolfSSL_CTX_get_default_passwd_cb(WOLFSSL_CTX *ctx)
+    {
+        if (ctx == NULL || ctx->passwd_cb == NULL) {
+            return NULL;
+        }
+
+        return ctx->passwd_cb;
+    }
+
+
+    void* wolfSSL_CTX_get_default_passwd_cb_userdata(WOLFSSL_CTX *ctx)
+    {
+        if (ctx == NULL) {
+            return NULL;
+        }
+
+        return ctx->passwd_userdata;
+    }
+
+#endif /* WOLFSSL_ENCRYPTED_KEYS */
+
+
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+    int wolfSSL_num_locks(void)
+    {
+        return 0;
+    }
+
+    void wolfSSL_set_locking_callback(void (*f)(int, int, const char*, int))
+    {
+        WOLFSSL_ENTER("wolfSSL_set_locking_callback");
+
+        if (wc_SetMutexCb(f) != 0) {
+            WOLFSSL_MSG("Error when setting mutex call back");
+        }
+    }
+
+
+    typedef unsigned long (idCb)(void);
+    static idCb* inner_idCb = NULL;
+
+    unsigned long wolfSSL_thread_id(void)
+    {
+        if (inner_idCb != NULL) {
+            return inner_idCb();
+        }
+        else {
+            return 0;
+        }
+    }
+
+
+    void wolfSSL_set_id_callback(unsigned long (*f)(void))
+    {
+        inner_idCb = f;
+    }
+
+    unsigned long wolfSSL_ERR_get_error(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_ERR_get_error");
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+        {
+            unsigned long ret = wolfSSL_ERR_peek_error_line_data(NULL, NULL,
+                                                                 NULL, NULL);
+            wc_RemoveErrorNode(-1);
+            return ret;
+        }
+#elif (defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE))
+        {
+            int ret = wc_PullErrorNode(NULL, NULL, NULL);
+
+            if (ret < 0) {
+                if (ret == BAD_STATE_E) return 0; /* no errors in queue */
+                WOLFSSL_MSG("Error with pulling error node!");
+                WOLFSSL_LEAVE("wolfSSL_ERR_get_error", ret);
+                ret = 0 - ret; /* return absolute value of error */
+
+                /* panic and try to clear out nodes */
+                wc_ClearErrorNodes();
+            }
+
+            return (unsigned long)ret;
+        }
+#else
+        return (unsigned long)(0 - NOT_COMPILED_IN);
+#endif
+    }
+
+#if (defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE))
+    /* print out and clear all errors */
+    void wolfSSL_ERR_print_errors(WOLFSSL_BIO* bio)
+    {
+        const char* file = NULL;
+        const char* reason = NULL;
+        int ret;
+        int line = 0;
+        char buf[WOLFSSL_MAX_ERROR_SZ * 2];
+
+        WOLFSSL_ENTER("wolfSSL_ERR_print_errors");
+
+        if (bio == NULL) {
+            WOLFSSL_MSG("BIO passed in was null");
+            return;
+        }
+
+        do {
+        ret = wc_PeekErrorNode(0, &file, &reason, &line);
+        if (ret >= 0) {
+            const char* r = wolfSSL_ERR_reason_error_string(0 - ret);
+            XSNPRINTF(buf, sizeof(buf), "error:%d:wolfSSL library:%s:%s:%d\n",
+                    ret, r, file, line);
+            wolfSSL_BIO_write(bio, buf, (int)XSTRLEN(buf));
+            wc_RemoveErrorNode(0);
+        }
+        } while (ret >= 0);
+    }
+#endif /* OPENSSL_EXTRA || DEBUG_WOLFSSL_VERBOSE */
+
+#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */
+
+#ifdef OPENSSL_EXTRA
+
+#if !defined(NO_WOLFSSL_SERVER)
+size_t wolfSSL_get_server_random(const WOLFSSL *ssl, unsigned char *out,
+                                                                   size_t outSz)
+{
+    size_t size;
+
+    /* return max size of buffer */
+    if (outSz == 0) {
+        return RAN_LEN;
+    }
+
+    if (ssl == NULL || out == NULL) {
+        return 0;
+    }
+
+    if (ssl->options.saveArrays == 0 || ssl->arrays == NULL) {
+        WOLFSSL_MSG("Arrays struct not saved after handshake");
+        return 0;
+    }
+
+    if (outSz > RAN_LEN) {
+        size = RAN_LEN;
+    }
+    else {
+        size = outSz;
+    }
+
+    XMEMCPY(out, ssl->arrays->serverRandom, size);
+    return size;
+}
+
+
+/* Used to get the peer ephemeral public key sent during the connection
+ * NOTE: currently wolfSSL_KeepHandshakeResources(WOLFSSL* ssl) must be called
+ *       before the ephemeral key is stored.
+ * return WOLFSSL_SUCCESS on success */
+int wolfSSL_get_server_tmp_key(const WOLFSSL* ssl, WOLFSSL_EVP_PKEY** pkey)
+{
+    WOLFSSL_EVP_PKEY* ret = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_get_server_tmp_key");
+
+    if (ssl == NULL || pkey == NULL) {
+        WOLFSSL_MSG("Bad argument passed in");
+        return WOLFSSL_FAILURE;
+    }
+
+#ifdef HAVE_ECC
+    if (ssl->peerEccKey != NULL) {
+        unsigned char* der;
+        const unsigned char* pt;
+        unsigned int   derSz = 0;
+        int sz;
+
+        if (wc_ecc_export_x963(ssl->peerEccKey, NULL, &derSz) !=
+                LENGTH_ONLY_E) {
+            WOLFSSL_MSG("get ecc der size failed");
+            return WOLFSSL_FAILURE;
+        }
+
+        derSz += MAX_SEQ_SZ + (2 * MAX_ALGO_SZ) + MAX_SEQ_SZ + TRAILING_ZERO;
+        der = (unsigned char*)XMALLOC(derSz, ssl->heap, DYNAMIC_TYPE_KEY);
+        if (der == NULL) {
+            WOLFSSL_MSG("Memory error");
+            return WOLFSSL_FAILURE;
+        }
+
+        if ((sz = wc_EccPublicKeyToDer(ssl->peerEccKey, der, derSz, 1)) <= 0) {
+            WOLFSSL_MSG("get ecc der failed");
+            XFREE(der, ssl->heap, DYNAMIC_TYPE_KEY);
+            return WOLFSSL_FAILURE;
+        }
+        pt = der; /* in case pointer gets advanced */
+        ret = wolfSSL_d2i_PUBKEY(NULL, &pt, sz);
+        XFREE(der, ssl->heap, DYNAMIC_TYPE_KEY);
+    }
+#endif
+
+    *pkey = ret;
+    if (ret == NULL)
+        return WOLFSSL_FAILURE;
+    else
+        return WOLFSSL_SUCCESS;
+}
+
+#endif /* !NO_WOLFSSL_SERVER */
+
+int wolfSSL_CTX_set_min_proto_version(WOLFSSL_CTX* ctx, int version)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_set_min_proto_version");
+
+    if (ctx == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    switch (version) {
+#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
+        case SSL3_VERSION:
+            ctx->minDowngrade = SSLv3_MINOR;
+            break;
+#endif
+#ifndef NO_TLS
+    #ifndef NO_OLD_TLS
+        #ifdef WOLFSSL_ALLOW_TLSV10
+        case TLS1_VERSION:
+            ctx->minDowngrade = TLSv1_MINOR;
+            break;
+        #endif
+        case TLS1_1_VERSION:
+            ctx->minDowngrade = TLSv1_1_MINOR;
+            break;
+    #endif
+    #ifndef WOLFSSL_NO_TLS12
+        case TLS1_2_VERSION:
+            ctx->minDowngrade = TLSv1_2_MINOR;
+            break;
+    #endif
+    #ifdef WOLFSSL_TLS13
+        case TLS1_3_VERSION:
+            ctx->minDowngrade = TLSv1_3_MINOR;
+            break;
+    #endif
+#endif
+#ifdef WOLFSSL_DTLS
+    #ifndef NO_OLD_TLS
+        case DTLS1_VERSION:
+            ctx->minDowngrade = DTLS_MINOR;
+            break;
+    #endif
+        case DTLS1_2_VERSION:
+            ctx->minDowngrade = DTLSv1_2_MINOR;
+            break;
+#endif
+        default:
+            return BAD_FUNC_ARG;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_CTX_set_max_proto_version(WOLFSSL_CTX* ctx, int ver)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_set_max_proto_version");
+
+    /* supported only at compile-time only */
+    (void)ctx;
+    (void)ver;
+    return WOLFSSL_SUCCESS;
+}
+
+
+#if !defined(NO_WOLFSSL_CLIENT)
+/* Return the amount of random bytes copied over or error case.
+ * ssl : ssl struct after handshake
+ * out : buffer to hold random bytes
+ * outSz : either 0 (return max buffer sz) or size of out buffer
+ *
+ * NOTE: wolfSSL_KeepArrays(ssl) must be called to retain handshake information.
+ */
+size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out,
+                                                                   size_t outSz)
+{
+    size_t size;
+
+    /* return max size of buffer */
+    if (outSz == 0) {
+        return RAN_LEN;
+    }
+
+    if (ssl == NULL || out == NULL) {
+        return 0;
+    }
+
+    if (ssl->options.saveArrays == 0 || ssl->arrays == NULL) {
+        WOLFSSL_MSG("Arrays struct not saved after handshake");
+        return 0;
+    }
+
+    if (outSz > RAN_LEN) {
+        size = RAN_LEN;
+    }
+    else {
+        size = outSz;
+    }
+
+    XMEMCPY(out, ssl->arrays->clientRandom, size);
+    return size;
+}
+#endif /* !NO_WOLFSSL_CLIENT */
+
+
+    unsigned long wolfSSLeay(void)
+    {
+        return SSLEAY_VERSION_NUMBER;
+    }
+
+    unsigned long wolfSSL_OpenSSL_version_num(void)
+    {
+        return OPENSSL_VERSION_NUMBER;
+    }
+
+    const char* wolfSSLeay_version(int type)
+    {
+        static const char* version = "SSLeay wolfSSL compatibility";
+        (void)type;
+        return version;
+    }
+
+
+#ifndef NO_MD5
+    int wolfSSL_MD5_Init(WOLFSSL_MD5_CTX* md5)
+    {
+        int ret;
+        typedef char md5_test[sizeof(MD5_CTX) >= sizeof(wc_Md5) ? 1 : -1];
+        (void)sizeof(md5_test);
+
+        WOLFSSL_ENTER("MD5_Init");
+        ret = wc_InitMd5((wc_Md5*)md5);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_MD5_Update(WOLFSSL_MD5_CTX* md5, const void* input,
+                           unsigned long sz)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("wolfSSL_MD5_Update");
+        ret = wc_Md5Update((wc_Md5*)md5, (const byte*)input, (word32)sz);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_MD5_Final(byte* input, WOLFSSL_MD5_CTX* md5)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("MD5_Final");
+        ret = wc_Md5Final((wc_Md5*)md5, input);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+#endif /* !NO_MD5 */
+
+
+#ifndef NO_SHA
+    int wolfSSL_SHA_Init(WOLFSSL_SHA_CTX* sha)
+    {
+        int ret;
+
+        typedef char sha_test[sizeof(SHA_CTX) >= sizeof(wc_Sha) ? 1 : -1];
+        (void)sizeof(sha_test);
+
+        WOLFSSL_ENTER("SHA_Init");
+        ret = wc_InitSha((wc_Sha*)sha);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA_Update(WOLFSSL_SHA_CTX* sha, const void* input,
+                           unsigned long sz)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA_Update");
+        ret = wc_ShaUpdate((wc_Sha*)sha, (const byte*)input, (word32)sz);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA_Final(byte* input, WOLFSSL_SHA_CTX* sha)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA_Final");
+        ret = wc_ShaFinal((wc_Sha*)sha, input);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA1_Init(WOLFSSL_SHA_CTX* sha)
+    {
+        WOLFSSL_ENTER("SHA1_Init");
+        return SHA_Init(sha);
+    }
+
+
+    int wolfSSL_SHA1_Update(WOLFSSL_SHA_CTX* sha, const void* input,
+                            unsigned long sz)
+    {
+        WOLFSSL_ENTER("SHA1_Update");
+        return SHA_Update(sha, input, sz);
+    }
+
+
+    int wolfSSL_SHA1_Final(byte* input, WOLFSSL_SHA_CTX* sha)
+    {
+        WOLFSSL_ENTER("SHA1_Final");
+        return SHA_Final(input, sha);
+    }
+#endif /* !NO_SHA */
+
+#ifdef WOLFSSL_SHA224
+
+    int wolfSSL_SHA224_Init(WOLFSSL_SHA224_CTX* sha)
+    {
+        int ret;
+
+        typedef char sha_test[sizeof(SHA224_CTX) >= sizeof(wc_Sha224) ? 1 : -1];
+        (void)sizeof(sha_test);
+
+        WOLFSSL_ENTER("SHA224_Init");
+        ret = wc_InitSha224((wc_Sha224*)sha);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA224_Update(WOLFSSL_SHA224_CTX* sha, const void* input,
+                           unsigned long sz)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA224_Update");
+        ret = wc_Sha224Update((wc_Sha224*)sha, (const byte*)input, (word32)sz);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA224_Final(byte* input, WOLFSSL_SHA224_CTX* sha)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA224_Final");
+        ret = wc_Sha224Final((wc_Sha224*)sha, input);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+#endif /* WOLFSSL_SHA224 */
+
+
+    int wolfSSL_SHA256_Init(WOLFSSL_SHA256_CTX* sha256)
+    {
+        int ret;
+
+        typedef char sha_test[sizeof(SHA256_CTX) >= sizeof(wc_Sha256) ? 1 : -1];
+        (void)sizeof(sha_test);
+
+        WOLFSSL_ENTER("SHA256_Init");
+        ret = wc_InitSha256((wc_Sha256*)sha256);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA256_Update(WOLFSSL_SHA256_CTX* sha, const void* input,
+                              unsigned long sz)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA256_Update");
+        ret = wc_Sha256Update((wc_Sha256*)sha, (const byte*)input, (word32)sz);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA256_Final(byte* input, WOLFSSL_SHA256_CTX* sha)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA256_Final");
+        ret = wc_Sha256Final((wc_Sha256*)sha, input);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+#ifdef WOLFSSL_SHA384
+
+    int wolfSSL_SHA384_Init(WOLFSSL_SHA384_CTX* sha)
+    {
+        int ret;
+
+        typedef char sha_test[sizeof(SHA384_CTX) >= sizeof(wc_Sha384) ? 1 : -1];
+        (void)sizeof(sha_test);
+
+        WOLFSSL_ENTER("SHA384_Init");
+        ret = wc_InitSha384((wc_Sha384*)sha);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA384_Update(WOLFSSL_SHA384_CTX* sha, const void* input,
+                           unsigned long sz)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA384_Update");
+        ret = wc_Sha384Update((wc_Sha384*)sha, (const byte*)input, (word32)sz);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA384_Final(byte* input, WOLFSSL_SHA384_CTX* sha)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA384_Final");
+        ret = wc_Sha384Final((wc_Sha384*)sha, input);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+#endif /* WOLFSSL_SHA384 */
+
+
+#ifdef WOLFSSL_SHA512
+
+    int wolfSSL_SHA512_Init(WOLFSSL_SHA512_CTX* sha)
+    {
+        int ret;
+
+        typedef char sha_test[sizeof(SHA512_CTX) >= sizeof(wc_Sha512) ? 1 : -1];
+        (void)sizeof(sha_test);
+
+        WOLFSSL_ENTER("SHA512_Init");
+        ret = wc_InitSha512((wc_Sha512*)sha);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA512_Update(WOLFSSL_SHA512_CTX* sha, const void* input,
+                           unsigned long sz)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA512_Update");
+        ret = wc_Sha512Update((wc_Sha512*)sha, (const byte*)input, (word32)sz);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA512_Final(byte* input, WOLFSSL_SHA512_CTX* sha)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA512_Final");
+        ret = wc_Sha512Final((wc_Sha512*)sha, input);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+#endif /* WOLFSSL_SHA512 */
+
+#ifdef WOLFSSL_SHA3
+#ifndef WOLFSSL_NOSHA3_224
+
+    int wolfSSL_SHA3_224_Init(WOLFSSL_SHA3_224_CTX* sha)
+    {
+        int ret;
+
+        typedef char sha_test[sizeof(SHA3_224_CTX) >= sizeof(wc_Sha3) ? 1 : -1];
+        (void)sizeof(sha_test);
+
+        WOLFSSL_ENTER("SHA3_224_Init");
+        ret = wc_InitSha3_224((wc_Sha3*)sha, NULL, 0);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA3_224_Update(WOLFSSL_SHA3_224_CTX* sha, const void* input,
+                           unsigned long sz)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA3_224_Update");
+        ret = wc_Sha3_224_Update((wc_Sha3*)sha, (const byte*)input, (word32)sz);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA3_224_Final(byte* input, WOLFSSL_SHA3_224_CTX* sha)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA3_224_Final");
+        ret = wc_Sha3_224_Final((wc_Sha3*)sha, input);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+#endif /* WOLFSSL_NOSHA3_224 */
+
+
+#ifndef WOLFSSL_NOSHA3_256
+    int wolfSSL_SHA3_256_Init(WOLFSSL_SHA3_256_CTX* sha3_256)
+    {
+        int ret;
+
+        typedef char sha_test[sizeof(SHA3_256_CTX) >= sizeof(wc_Sha3) ? 1 : -1];
+        (void)sizeof(sha_test);
+
+        WOLFSSL_ENTER("SHA3_256_Init");
+        ret = wc_InitSha3_256((wc_Sha3*)sha3_256, NULL, 0);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA3_256_Update(WOLFSSL_SHA3_256_CTX* sha, const void* input,
+                              unsigned long sz)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA3_256_Update");
+        ret = wc_Sha3_256_Update((wc_Sha3*)sha, (const byte*)input, (word32)sz);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA3_256_Final(byte* input, WOLFSSL_SHA3_256_CTX* sha)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA3_256_Final");
+        ret = wc_Sha3_256_Final((wc_Sha3*)sha, input);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+#endif /* WOLFSSL_NOSHA3_256 */
+
+
+    int wolfSSL_SHA3_384_Init(WOLFSSL_SHA3_384_CTX* sha)
+    {
+        int ret;
+
+        typedef char sha_test[sizeof(SHA3_384_CTX) >= sizeof(wc_Sha3) ? 1 : -1];
+        (void)sizeof(sha_test);
+
+        WOLFSSL_ENTER("SHA3_384_Init");
+        ret = wc_InitSha3_384((wc_Sha3*)sha, NULL, 0);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA3_384_Update(WOLFSSL_SHA3_384_CTX* sha, const void* input,
+                           unsigned long sz)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA3_384_Update");
+        ret = wc_Sha3_384_Update((wc_Sha3*)sha, (const byte*)input, (word32)sz);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA3_384_Final(byte* input, WOLFSSL_SHA3_384_CTX* sha)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA3_384_Final");
+        ret = wc_Sha3_384_Final((wc_Sha3*)sha, input);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+
+#ifndef WOLFSSL_NOSHA3_512
+
+    int wolfSSL_SHA3_512_Init(WOLFSSL_SHA3_512_CTX* sha)
+    {
+        int ret;
+
+        typedef char sha_test[sizeof(SHA3_512_CTX) >= sizeof(wc_Sha3) ? 1 : -1];
+        (void)sizeof(sha_test);
+
+        WOLFSSL_ENTER("SHA3_512_Init");
+        ret = wc_InitSha3_512((wc_Sha3*)sha, NULL, 0);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA3_512_Update(WOLFSSL_SHA3_512_CTX* sha, const void* input,
+                           unsigned long sz)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA3_512_Update");
+        ret = wc_Sha3_512_Update((wc_Sha3*)sha, (const byte*)input, (word32)sz);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA3_512_Final(byte* input, WOLFSSL_SHA3_512_CTX* sha)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA3_512_Final");
+        ret = wc_Sha3_512_Final((wc_Sha3*)sha, input);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+#endif /* WOLFSSL_NOSHA3_512 */
+#endif /* WOLFSSL_SHA3 */
+
+    /* store for external read of iv, WOLFSSL_SUCCESS on success */
+    int  wolfSSL_StoreExternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx)
+    {
+        WOLFSSL_ENTER("wolfSSL_StoreExternalIV");
+
+        if (ctx == NULL) {
+            WOLFSSL_MSG("Bad function argument");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        switch (ctx->cipherType) {
+
+#ifndef NO_AES
+#ifdef HAVE_AES_CBC
+            case AES_128_CBC_TYPE :
+            case AES_192_CBC_TYPE :
+            case AES_256_CBC_TYPE :
+                WOLFSSL_MSG("AES CBC");
+                XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE);
+                break;
+#endif
+#ifdef HAVE_AESGCM
+            case AES_128_GCM_TYPE :
+            case AES_192_GCM_TYPE :
+            case AES_256_GCM_TYPE :
+                WOLFSSL_MSG("AES GCM");
+                XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE);
+                break;
+#endif /* HAVE_AESGCM */
+#ifdef HAVE_AES_ECB
+            case AES_128_ECB_TYPE :
+            case AES_192_ECB_TYPE :
+            case AES_256_ECB_TYPE :
+                WOLFSSL_MSG("AES ECB");
+                break;
+#endif
+#ifdef WOLFSSL_AES_COUNTER
+            case AES_128_CTR_TYPE :
+            case AES_192_CTR_TYPE :
+            case AES_256_CTR_TYPE :
+                WOLFSSL_MSG("AES CTR");
+                XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE);
+                break;
+#endif /* WOLFSSL_AES_COUNTER */
+#ifdef WOLFSSL_AES_CFB
+#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS)
+            case AES_128_CFB1_TYPE:
+            case AES_192_CFB1_TYPE:
+            case AES_256_CFB1_TYPE:
+                WOLFSSL_MSG("AES CFB1");
+                break;
+            case AES_128_CFB8_TYPE:
+            case AES_192_CFB8_TYPE:
+            case AES_256_CFB8_TYPE:
+                WOLFSSL_MSG("AES CFB8");
+                break;
+#endif /* !HAVE_SELFTEST && !HAVE_FIPS */
+            case AES_128_CFB128_TYPE:
+            case AES_192_CFB128_TYPE:
+            case AES_256_CFB128_TYPE:
+                WOLFSSL_MSG("AES CFB128");
+                break;
+#endif /* WOLFSSL_AES_CFB */
+#if defined(WOLFSSL_AES_OFB)
+            case AES_128_OFB_TYPE:
+            case AES_192_OFB_TYPE:
+            case AES_256_OFB_TYPE:
+                WOLFSSL_MSG("AES OFB");
+                break;
+#endif /* WOLFSSL_AES_OFB */
+#ifdef WOLFSSL_AES_XTS
+            case AES_128_XTS_TYPE:
+            case AES_256_XTS_TYPE:
+                WOLFSSL_MSG("AES XTS");
+                break;
+#endif /* WOLFSSL_AES_XTS */
+#endif /* NO_AES */
+
+#ifndef NO_DES3
+            case DES_CBC_TYPE :
+                WOLFSSL_MSG("DES CBC");
+                XMEMCPY(ctx->iv, &ctx->cipher.des.reg, DES_BLOCK_SIZE);
+                break;
+
+            case DES_EDE3_CBC_TYPE :
+                WOLFSSL_MSG("DES EDE3 CBC");
+                XMEMCPY(ctx->iv, &ctx->cipher.des3.reg, DES_BLOCK_SIZE);
+                break;
+#endif
+#ifdef WOLFSSL_DES_ECB
+            case DES_ECB_TYPE :
+                WOLFSSL_MSG("DES ECB");
+                break;
+            case DES_EDE3_ECB_TYPE :
+                WOLFSSL_MSG("DES3 ECB");
+                break;
+#endif
+
+#ifdef HAVE_IDEA
+            case IDEA_CBC_TYPE :
+                WOLFSSL_MSG("IDEA CBC");
+                XMEMCPY(ctx->iv, &ctx->cipher.idea.reg, IDEA_BLOCK_SIZE);
+                break;
+#endif
+            case ARC4_TYPE :
+                WOLFSSL_MSG("ARC4");
+                break;
+
+            case NULL_CIPHER_TYPE :
+                WOLFSSL_MSG("NULL");
+                break;
+
+            default: {
+                WOLFSSL_MSG("bad type");
+                return WOLFSSL_FATAL_ERROR;
+            }
+        }
+        return WOLFSSL_SUCCESS;
+    }
+
+    /* set internal IV from external, WOLFSSL_SUCCESS on success */
+    int  wolfSSL_SetInternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx)
+    {
+
+        WOLFSSL_ENTER("wolfSSL_SetInternalIV");
+
+        if (ctx == NULL) {
+            WOLFSSL_MSG("Bad function argument");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        switch (ctx->cipherType) {
+
+#ifndef NO_AES
+#ifdef HAVE_AES_CBC
+            case AES_128_CBC_TYPE :
+            case AES_192_CBC_TYPE :
+            case AES_256_CBC_TYPE :
+                WOLFSSL_MSG("AES CBC");
+                XMEMCPY(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE);
+                break;
+#endif
+#ifdef HAVE_AESGCM
+            case AES_128_GCM_TYPE :
+            case AES_192_GCM_TYPE :
+            case AES_256_GCM_TYPE :
+                WOLFSSL_MSG("AES GCM");
+                XMEMCPY(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE);
+                break;
+#endif
+#ifdef HAVE_AES_ECB
+            case AES_128_ECB_TYPE :
+            case AES_192_ECB_TYPE :
+            case AES_256_ECB_TYPE :
+                WOLFSSL_MSG("AES ECB");
+                break;
+#endif
+#ifdef WOLFSSL_AES_COUNTER
+            case AES_128_CTR_TYPE :
+            case AES_192_CTR_TYPE :
+            case AES_256_CTR_TYPE :
+                WOLFSSL_MSG("AES CTR");
+                XMEMCPY(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE);
+                break;
+#endif
+
+#endif /* NO_AES */
+
+#ifndef NO_DES3
+            case DES_CBC_TYPE :
+                WOLFSSL_MSG("DES CBC");
+                XMEMCPY(&ctx->cipher.des.reg, ctx->iv, DES_BLOCK_SIZE);
+                break;
+
+            case DES_EDE3_CBC_TYPE :
+                WOLFSSL_MSG("DES EDE3 CBC");
+                XMEMCPY(&ctx->cipher.des3.reg, ctx->iv, DES_BLOCK_SIZE);
+                break;
+#endif
+#ifdef WOLFSSL_DES_ECB
+            case DES_ECB_TYPE :
+                WOLFSSL_MSG("DES ECB");
+                break;
+            case DES_EDE3_ECB_TYPE :
+                WOLFSSL_MSG("DES3 ECB");
+                break;
+#endif
+
+#ifdef HAVE_IDEA
+            case IDEA_CBC_TYPE :
+                WOLFSSL_MSG("IDEA CBC");
+                XMEMCPY(&ctx->cipher.idea.reg, ctx->iv, IDEA_BLOCK_SIZE);
+                break;
+#endif
+            case ARC4_TYPE :
+                WOLFSSL_MSG("ARC4");
+                break;
+
+            case NULL_CIPHER_TYPE :
+                WOLFSSL_MSG("NULL");
+                break;
+
+            default: {
+                WOLFSSL_MSG("bad type");
+                return WOLFSSL_FATAL_ERROR;
+            }
+        }
+        return WOLFSSL_SUCCESS;
+    }
+
+    unsigned char* wolfSSL_HMAC(const WOLFSSL_EVP_MD* evp_md, const void* key,
+                                int key_len, const unsigned char* d, int n,
+                                unsigned char* md, unsigned int* md_len)
+    {
+        int type;
+        int mdlen;
+        unsigned char* ret = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+        Hmac* hmac = NULL;
+#else
+        Hmac  hmac[1];
+#endif
+        void* heap = NULL;
+
+        WOLFSSL_ENTER("wolfSSL_HMAC");
+        if (!md) {
+            WOLFSSL_MSG("Static buffer not supported, pass in md buffer");
+            return NULL;  /* no static buffer support */
+        }
+
+#ifndef NO_MD5
+        if (XSTRNCMP(evp_md, "MD5", 3) == 0) {
+            type = WC_MD5;
+            mdlen = WC_MD5_DIGEST_SIZE;
+        } else
+#endif
+#ifdef WOLFSSL_SHA224
+        if (XSTRNCMP(evp_md, "SHA224", 6) == 0) {
+            type = WC_SHA224;
+            mdlen = WC_SHA224_DIGEST_SIZE;
+        } else
+#endif
+#ifndef NO_SHA256
+        if (XSTRNCMP(evp_md, "SHA256", 6) == 0) {
+            type = WC_SHA256;
+            mdlen = WC_SHA256_DIGEST_SIZE;
+        } else
+#endif
+#ifdef WOLFSSL_SHA384
+        if (XSTRNCMP(evp_md, "SHA384", 6) == 0) {
+            type = WC_SHA384;
+            mdlen = WC_SHA384_DIGEST_SIZE;
+        } else
+#endif
+#ifdef WOLFSSL_SHA512
+        if (XSTRNCMP(evp_md, "SHA512", 6) == 0) {
+            type = WC_SHA512;
+            mdlen = WC_SHA512_DIGEST_SIZE;
+        } else
+#endif
+#ifdef WOLFSSL_SHA3
+    #ifndef WOLFSSL_NOSHA3_224
+        if (XSTRNCMP(evp_md, "SHA3_224", 8) == 0) {
+            type = WC_SHA3_224;
+            mdlen = WC_SHA3_224_DIGEST_SIZE;
+        } else
+    #endif
+    #ifndef WOLFSSL_NOSHA3_256
+        if (XSTRNCMP(evp_md, "SHA3_256", 8) == 0) {
+            type = WC_SHA3_256;
+            mdlen = WC_SHA3_256_DIGEST_SIZE;
+        } else
+    #endif
+        if (XSTRNCMP(evp_md, "SHA3_384", 8) == 0) {
+            type = WC_SHA3_384;
+            mdlen = WC_SHA3_384_DIGEST_SIZE;
+        } else
+    #ifndef WOLFSSL_NOSHA3_512
+        if (XSTRNCMP(evp_md, "SHA3_512", 8) == 0) {
+            type = WC_SHA3_512;
+            mdlen = WC_SHA3_512_DIGEST_SIZE;
+        } else
+    #endif
+#endif
+#ifndef NO_SHA
+        if (XSTRNCMP(evp_md, "SHA", 3) == 0) {
+            type = WC_SHA;
+            mdlen = WC_SHA_DIGEST_SIZE;
+        } else
+#endif
+        {
+            return NULL;
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        hmac = (Hmac*)XMALLOC(sizeof(Hmac), heap, DYNAMIC_TYPE_HMAC);
+        if (hmac == NULL)
+            return NULL;
+    #endif
+
+        if (wc_HmacInit(hmac, heap, INVALID_DEVID) == 0) {
+            if (wc_HmacSetKey(hmac, type, (const byte*)key, key_len) == 0) {
+                if (wc_HmacUpdate(hmac, d, n) == 0) {
+                    if (wc_HmacFinal(hmac, md) == 0) {
+                        if (md_len)
+                            *md_len = mdlen;
+                        ret = md;
+                    }
+                }
+            }
+            wc_HmacFree(hmac);
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(hmac, heap, DYNAMIC_TYPE_HMAC);
+    #endif
+
+        (void)evp_md;
+        return ret;
+    }
+
+    void wolfSSL_ERR_clear_error(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_ERR_clear_error");
+
+#if defined(DEBUG_WOLFSSL) || defined(WOLFSSL_NGINX) || \
+    defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
+        wc_ClearErrorNodes();
+#endif
+    }
+
+
+    int wolfSSL_RAND_status(void)
+    {
+        return WOLFSSL_SUCCESS;  /* wolfCrypt provides enough seed internally */
+    }
+
+
+    #ifndef NO_WOLFSSL_STUB
+    void wolfSSL_RAND_add(const void* add, int len, double entropy)
+    {
+        (void)add;
+        (void)len;
+        (void)entropy;
+        WOLFSSL_STUB("RAND_add");
+        /* wolfSSL seeds/adds internally, use explicit RNG if you want
+           to take control */
+    }
+    #endif
+
+#ifndef NO_DES3
+    /* 0 on ok */
+    int wolfSSL_DES_key_sched(WOLFSSL_const_DES_cblock* key,
+                              WOLFSSL_DES_key_schedule* schedule)
+    {
+        WOLFSSL_ENTER("wolfSSL_DES_key_sched");
+
+        if (key == NULL || schedule == NULL) {
+            WOLFSSL_MSG("Null argument passed in");
+        }
+        else {
+            XMEMCPY(schedule, key, sizeof(WOLFSSL_const_DES_cblock));
+        }
+
+        return 0;
+    }
+
+
+    /* intended to behave similar to Kerberos mit_des_cbc_cksum
+     * return the last 4 bytes of cipher text */
+    WOLFSSL_DES_LONG wolfSSL_DES_cbc_cksum(const unsigned char* in,
+            WOLFSSL_DES_cblock* out, long length, WOLFSSL_DES_key_schedule* sc,
+            WOLFSSL_const_DES_cblock* iv)
+    {
+        WOLFSSL_DES_LONG ret;
+        unsigned char* tmp;
+        unsigned char* data   = (unsigned char*)in;
+        long           dataSz = length;
+        byte dynamicFlag = 0; /* when padding the buffer created needs free'd */
+
+        WOLFSSL_ENTER("wolfSSL_DES_cbc_cksum");
+
+        if (in == NULL || out == NULL || sc == NULL || iv == NULL) {
+            WOLFSSL_MSG("Bad argument passed in");
+            return 0;
+        }
+
+        /* if input length is not a multiple of DES_BLOCK_SIZE pad with 0s */
+        if (dataSz % DES_BLOCK_SIZE) {
+            dataSz += DES_BLOCK_SIZE - (dataSz % DES_BLOCK_SIZE);
+            data = (unsigned char*)XMALLOC(dataSz, NULL,
+                                           DYNAMIC_TYPE_TMP_BUFFER);
+            if (data == NULL) {
+                WOLFSSL_MSG("Issue creating temporary buffer");
+                return 0;
+            }
+            dynamicFlag = 1; /* set to free buffer at end */
+            XMEMCPY(data, in, length);
+            XMEMSET(data + length, 0, dataSz - length); /* padding */
+        }
+
+        tmp = (unsigned char*)XMALLOC(dataSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (tmp == NULL) {
+            WOLFSSL_MSG("Issue creating temporary buffer");
+            if (dynamicFlag == 1) {
+                XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            }
+            return 0;
+        }
+
+        wolfSSL_DES_cbc_encrypt(data, tmp, dataSz, sc,
+                (WOLFSSL_DES_cblock*)iv, 1);
+        XMEMCPY((unsigned char*)out, tmp + (dataSz - DES_BLOCK_SIZE),
+                DES_BLOCK_SIZE);
+
+        ret = (((*((unsigned char*)out + 4) & 0xFF) << 24)|
+               ((*((unsigned char*)out + 5) & 0xFF) << 16)|
+               ((*((unsigned char*)out + 6) & 0xFF) << 8) |
+               (*((unsigned char*)out + 7) & 0xFF));
+
+        XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (dynamicFlag == 1) {
+            XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        }
+
+        return ret;
+    }
+
+
+    void wolfSSL_DES_cbc_encrypt(const unsigned char* input,
+                                 unsigned char* output, long length,
+                                 WOLFSSL_DES_key_schedule* schedule,
+                                 WOLFSSL_DES_cblock* ivec, int enc)
+    {
+        Des myDes;
+        byte lastblock[DES_BLOCK_SIZE];
+        int  lb_sz;
+        long  blk;
+
+        WOLFSSL_ENTER("DES_cbc_encrypt");
+
+        /* OpenSSL compat, no ret */
+        wc_Des_SetKey(&myDes, (const byte*)schedule, (const byte*)ivec, !enc);
+        lb_sz = length%DES_BLOCK_SIZE;
+        blk   = length/DES_BLOCK_SIZE;
+
+        if (enc){
+            wc_Des_CbcEncrypt(&myDes, output, input, (word32)blk*DES_BLOCK_SIZE);
+            if(lb_sz){
+                XMEMSET(lastblock, 0, DES_BLOCK_SIZE);
+                XMEMCPY(lastblock, input+length-lb_sz, lb_sz);
+                wc_Des_CbcEncrypt(&myDes, output+blk*DES_BLOCK_SIZE,
+                    lastblock, (word32)DES_BLOCK_SIZE);
+            }
+        }
+        else {
+            wc_Des_CbcDecrypt(&myDes, output, input, (word32)blk*DES_BLOCK_SIZE);
+            if(lb_sz){
+                wc_Des_CbcDecrypt(&myDes, lastblock, input+length-lb_sz, (word32)DES_BLOCK_SIZE);
+                XMEMCPY(output+length-lb_sz, lastblock, lb_sz);
+            }
+        }
+    }
+
+
+    /* WOLFSSL_DES_key_schedule is a unsigned char array of size 8 */
+    void wolfSSL_DES_ede3_cbc_encrypt(const unsigned char* input,
+                                      unsigned char* output, long sz,
+                                      WOLFSSL_DES_key_schedule* ks1,
+                                      WOLFSSL_DES_key_schedule* ks2,
+                                      WOLFSSL_DES_key_schedule* ks3,
+                                      WOLFSSL_DES_cblock* ivec, int enc)
+    {
+        int ret;
+        Des3 des;
+        byte key[24];/* EDE uses 24 size key */
+        byte lastblock[DES_BLOCK_SIZE];
+        int  lb_sz;
+        long  blk;
+
+        WOLFSSL_ENTER("wolfSSL_DES_ede3_cbc_encrypt");
+
+        XMEMSET(key, 0, sizeof(key));
+        XMEMCPY(key, *ks1, DES_BLOCK_SIZE);
+        XMEMCPY(&key[DES_BLOCK_SIZE], *ks2, DES_BLOCK_SIZE);
+        XMEMCPY(&key[DES_BLOCK_SIZE * 2], *ks3, DES_BLOCK_SIZE);
+        lb_sz = sz%DES_BLOCK_SIZE;
+        blk   = sz/DES_BLOCK_SIZE;
+
+        /* OpenSSL compat, no ret */
+        (void)wc_Des3Init(&des, NULL, INVALID_DEVID);
+
+        if (enc) {
+            wc_Des3_SetKey(&des, key, (const byte*)ivec, DES_ENCRYPTION);
+            ret = wc_Des3_CbcEncrypt(&des, output, input, (word32)blk*DES_BLOCK_SIZE);
+        #if defined(WOLFSSL_ASYNC_CRYPT)
+            ret = wc_AsyncWait(ret, &des.asyncDev, WC_ASYNC_FLAG_NONE);
+        #endif
+            (void)ret; /* ignore return codes for processing */
+            if(lb_sz){
+                XMEMSET(lastblock, 0, DES_BLOCK_SIZE);
+                XMEMCPY(lastblock, input+sz-lb_sz, lb_sz);
+                ret = wc_Des3_CbcEncrypt(&des, output+blk*DES_BLOCK_SIZE,
+                    lastblock, (word32)DES_BLOCK_SIZE);
+            #if defined(WOLFSSL_ASYNC_CRYPT)
+                ret = wc_AsyncWait(ret, &des.asyncDev, WC_ASYNC_FLAG_NONE);
+            #endif
+                (void)ret; /* ignore return codes for processing */
+            }
+        }
+        else {
+            wc_Des3_SetKey(&des, key, (const byte*)ivec, DES_DECRYPTION);
+            ret = wc_Des3_CbcDecrypt(&des, output, input, (word32)blk*DES_BLOCK_SIZE);
+        #if defined(WOLFSSL_ASYNC_CRYPT)
+            ret = wc_AsyncWait(ret, &des.asyncDev, WC_ASYNC_FLAG_NONE);
+        #endif
+            (void)ret; /* ignore return codes for processing */
+            if(lb_sz){
+                ret = wc_Des3_CbcDecrypt(&des, lastblock, input+sz-lb_sz, (word32)DES_BLOCK_SIZE);
+            #if defined(WOLFSSL_ASYNC_CRYPT)
+                ret = wc_AsyncWait(ret, &des.asyncDev, WC_ASYNC_FLAG_NONE);
+            #endif
+                (void)ret; /* ignore return codes for processing */
+                XMEMCPY(output+sz-lb_sz, lastblock, lb_sz);
+            }
+        }
+        wc_Des3Free(&des);
+    }
+
+
+    /* correctly sets ivec for next call */
+    void wolfSSL_DES_ncbc_encrypt(const unsigned char* input,
+                     unsigned char* output, long length,
+                     WOLFSSL_DES_key_schedule* schedule, WOLFSSL_DES_cblock* ivec,
+                     int enc)
+    {
+        Des myDes;
+        byte lastblock[DES_BLOCK_SIZE];
+        int  lb_sz;
+        long idx = length;
+        long blk;
+
+        WOLFSSL_ENTER("DES_ncbc_encrypt");
+
+        /* OpenSSL compat, no ret */
+        wc_Des_SetKey(&myDes, (const byte*)schedule, (const byte*)ivec, !enc);
+        lb_sz = length%DES_BLOCK_SIZE;
+        blk   = length/DES_BLOCK_SIZE;
+        idx  -= sizeof(DES_cblock);
+        if (lb_sz) {
+            idx += DES_BLOCK_SIZE - lb_sz;
+        }
+        if (enc){
+            wc_Des_CbcEncrypt(&myDes, output, input,
+                    (word32)blk * DES_BLOCK_SIZE);
+            if (lb_sz){
+                XMEMSET(lastblock, 0, DES_BLOCK_SIZE);
+                XMEMCPY(lastblock, input+length-lb_sz, lb_sz);
+                wc_Des_CbcEncrypt(&myDes, output + blk * DES_BLOCK_SIZE,
+                    lastblock, (word32)DES_BLOCK_SIZE);
+            }
+            XMEMCPY(ivec, output + idx, sizeof(DES_cblock));
+        } else {
+            WOLFSSL_DES_cblock tmp;
+            XMEMCPY(tmp, input + idx, sizeof(DES_cblock));
+            wc_Des_CbcDecrypt(&myDes, output, input,
+                    (word32)blk * DES_BLOCK_SIZE);
+            if (lb_sz){
+                wc_Des_CbcDecrypt(&myDes, lastblock, input + length - lb_sz,
+                        (word32)DES_BLOCK_SIZE);
+                XMEMCPY(output+length-lb_sz, lastblock, lb_sz);
+            }
+            XMEMCPY(ivec, tmp, sizeof(WOLFSSL_DES_cblock));
+        }
+
+    }
+
+#endif /* NO_DES3 */
+
+    void wolfSSL_ERR_free_strings(void)
+    {
+        /* handled internally */
+    }
+
+    void wolfSSL_cleanup_all_ex_data(void)
+    {
+        /* nothing to do here */
+    }
+
+    int wolfSSL_clear(WOLFSSL* ssl)
+    {
+        if (ssl == NULL) {
+            return WOLFSSL_FAILURE;
+        }
+
+        ssl->options.isClosed = 0;
+        ssl->options.connReset = 0;
+        ssl->options.sentNotify = 0;
+        ssl->options.sendVerify = 0;
+        ssl->options.serverState = NULL_STATE;
+        ssl->options.clientState = NULL_STATE;
+        ssl->options.connectState = CONNECT_BEGIN;
+        ssl->options.acceptState  = ACCEPT_BEGIN;
+        ssl->options.handShakeState  = NULL_STATE;
+        ssl->options.handShakeDone = 0;
+        /* ssl->options.processReply = doProcessInit; */
+
+        ssl->keys.encryptionOn = 0;
+        XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived));
+
+        if (ssl->hsHashes != NULL) {
+#ifndef NO_OLD_TLS
+#ifndef NO_MD5
+            if (wc_InitMd5_ex(&ssl->hsHashes->hashMd5, ssl->heap,
+                    ssl->devId) != 0) {
+                return WOLFSSL_FAILURE;
+            }
+        #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+            wc_Md5SetFlags(&ssl->hsHashes->hashMd5, WC_HASH_FLAG_WILLCOPY);
+        #endif
+#endif
+#ifndef NO_SHA
+            if (wc_InitSha_ex(&ssl->hsHashes->hashSha, ssl->heap,
+                    ssl->devId) != 0) {
+                return WOLFSSL_FAILURE;
+            }
+        #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+            wc_ShaSetFlags(&ssl->hsHashes->hashSha, WC_HASH_FLAG_WILLCOPY);
+        #endif
+#endif
+#endif
+#ifndef NO_SHA256
+            if (wc_InitSha256_ex(&ssl->hsHashes->hashSha256, ssl->heap,
+                    ssl->devId) != 0) {
+                return WOLFSSL_FAILURE;
+            }
+        #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+            wc_Sha256SetFlags(&ssl->hsHashes->hashSha256, WC_HASH_FLAG_WILLCOPY);
+        #endif
+#endif
+#ifdef WOLFSSL_SHA384
+            if (wc_InitSha384_ex(&ssl->hsHashes->hashSha384, ssl->heap,
+                    ssl->devId) != 0) {
+                return WOLFSSL_FAILURE;
+            }
+        #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+            wc_Sha384SetFlags(&ssl->hsHashes->hashSha384, WC_HASH_FLAG_WILLCOPY);
+        #endif
+#endif
+#ifdef WOLFSSL_SHA512
+            if (wc_InitSha512_ex(&ssl->hsHashes->hashSha512, ssl->heap,
+                    ssl->devId) != 0) {
+                return WOLFSSL_FAILURE;
+            }
+        #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+            wc_Sha512SetFlags(&ssl->hsHashes->hashSha512, WC_HASH_FLAG_WILLCOPY);
+        #endif
+#endif
+        }
+#ifdef SESSION_CERTS
+        ssl->session.chain.count = 0;
+#endif
+#ifdef KEEP_PEER_CERT
+        FreeX509(&ssl->peerCert);
+        InitX509(&ssl->peerCert, 0, ssl->heap);
+#endif
+
+        return WOLFSSL_SUCCESS;
+    }
+
+    long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION* ses, long t)
+    {
+        word32 tmptime;
+        if (!ses || t < 0)
+            return BAD_FUNC_ARG;
+
+        tmptime = t & 0xFFFFFFFF;
+
+        ses->timeout = tmptime;
+
+        return WOLFSSL_SUCCESS;
+    }
+
+#endif
+
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+    long wolfSSL_CTX_set_mode(WOLFSSL_CTX* ctx, long mode)
+    {
+        /* WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is wolfSSL default mode */
+
+        WOLFSSL_ENTER("SSL_CTX_set_mode");
+        switch(mode) {
+            case SSL_MODE_ENABLE_PARTIAL_WRITE:
+                ctx->partialWrite = 1;
+                break;
+            #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+            case SSL_MODE_RELEASE_BUFFERS:
+                WOLFSSL_MSG("SSL_MODE_RELEASE_BUFFERS not implemented.");
+                break;
+            #endif
+            default:
+                WOLFSSL_MSG("Mode Not Implemented");
+        }
+
+        /* SSL_MODE_AUTO_RETRY
+         * Should not return -1 with renegotiation on read/write */
+
+        return mode;
+    }
+#endif
+
+#ifdef OPENSSL_EXTRA
+
+    #ifndef NO_WOLFSSL_STUB
+    long wolfSSL_SSL_get_mode(WOLFSSL* ssl)
+    {
+        /* TODO: */
+        (void)ssl;
+        WOLFSSL_STUB("SSL_get_mode");
+        return 0;
+    }
+    #endif
+
+    #ifndef NO_WOLFSSL_STUB
+    long wolfSSL_CTX_get_mode(WOLFSSL_CTX* ctx)
+    {
+        /* TODO: */
+        (void)ctx;
+        WOLFSSL_STUB("SSL_CTX_get_mode");
+        return 0;
+    }
+    #endif
+
+    #ifndef NO_WOLFSSL_STUB
+    void wolfSSL_CTX_set_default_read_ahead(WOLFSSL_CTX* ctx, int m)
+    {
+        /* TODO: maybe? */
+        (void)ctx;
+        (void)m;
+        WOLFSSL_STUB("SSL_CTX_set_default_read_ahead");
+    }
+    #endif
+
+
+    /* Storing app session context id, this value is inherited by WOLFSSL
+     * objects created from WOLFSSL_CTX. Any session that is imported with a
+     * different session context id will be rejected.
+     *
+     * ctx         structure to set context in
+     * sid_ctx     value of context to set
+     * sid_ctx_len length of sid_ctx buffer
+     *
+     * Returns SSL_SUCCESS in success case and SSL_FAILURE when failing
+     */
+    int wolfSSL_CTX_set_session_id_context(WOLFSSL_CTX* ctx,
+                                           const unsigned char* sid_ctx,
+                                           unsigned int sid_ctx_len)
+    {
+        WOLFSSL_ENTER("SSL_CTX_set_session_id_context");
+
+        /* No application specific context needed for wolfSSL */
+        if (sid_ctx_len > ID_LEN || ctx == NULL || sid_ctx == NULL) {
+            return SSL_FAILURE;
+        }
+        XMEMCPY(ctx->sessionCtx, sid_ctx, sid_ctx_len);
+        ctx->sessionCtxSz = (byte)sid_ctx_len;
+
+        return SSL_SUCCESS;
+    }
+
+
+
+    /* Storing app session context id. Any session that is imported with a
+     * different session context id will be rejected.
+     *
+     * ssl  structure to set context in
+     * id   value of context to set
+     * len  length of sid_ctx buffer
+     *
+     * Returns SSL_SUCCESS in success case and SSL_FAILURE when failing
+     */
+    int wolfSSL_set_session_id_context(WOLFSSL* ssl, const unsigned char* id,
+                                   unsigned int len)
+    {
+        WOLFSSL_ENTER("wolfSSL_set_session_id_context");
+
+        if (len > ID_LEN || ssl == NULL || id == NULL) {
+            return SSL_FAILURE;
+        }
+        XMEMCPY(ssl->sessionCtx, id, len);
+        ssl->sessionCtxSz = (byte)len;
+
+        return SSL_SUCCESS;
+    }
+
+
+    long wolfSSL_CTX_sess_get_cache_size(WOLFSSL_CTX* ctx)
+    {
+        (void)ctx;
+        #ifndef NO_SESSION_CACHE
+            return (long)(SESSIONS_PER_ROW * SESSION_ROWS);
+        #else
+            return 0;
+        #endif
+    }
+
+
+    /* returns the unsigned error value and increments the pointer into the
+     * error queue.
+     *
+     * file  pointer to file name
+     * line  gets set to line number of error when not NULL
+     */
+    unsigned long wolfSSL_ERR_get_error_line(const char** file, int* line)
+    {
+    #ifdef DEBUG_WOLFSSL
+        int ret = wc_PullErrorNode(file, NULL, line);
+        if (ret < 0) {
+            if (ret == BAD_STATE_E) return 0; /* no errors in queue */
+            WOLFSSL_MSG("Issue getting error node");
+            WOLFSSL_LEAVE("wolfSSL_ERR_get_error_line", ret);
+            ret = 0 - ret; /* return absolute value of error */
+
+            /* panic and try to clear out nodes */
+            wc_ClearErrorNodes();
+        }
+        return (unsigned long)ret;
+    #else
+        (void)file;
+        (void)line;
+
+        return 0;
+    #endif
+    }
+
+
+#if (defined(DEBUG_WOLFSSL) || defined(OPENSSL_EXTRA)) && \
+    (!defined(_WIN32) && !defined(NO_ERROR_QUEUE))
+    static const char WOLFSSL_SYS_ACCEPT_T[]  = "accept";
+    static const char WOLFSSL_SYS_BIND_T[]    = "bind";
+    static const char WOLFSSL_SYS_CONNECT_T[] = "connect";
+    static const char WOLFSSL_SYS_FOPEN_T[]   = "fopen";
+    static const char WOLFSSL_SYS_FREAD_T[]   = "fread";
+    static const char WOLFSSL_SYS_GETADDRINFO_T[] = "getaddrinfo";
+    static const char WOLFSSL_SYS_GETSOCKOPT_T[]  = "getsockopt";
+    static const char WOLFSSL_SYS_GETSOCKNAME_T[] = "getsockname";
+    static const char WOLFSSL_SYS_GETHOSTBYNAME_T[] = "gethostbyname";
+    static const char WOLFSSL_SYS_GETNAMEINFO_T[]   = "getnameinfo";
+    static const char WOLFSSL_SYS_GETSERVBYNAME_T[] = "getservbyname";
+    static const char WOLFSSL_SYS_IOCTLSOCKET_T[]   = "ioctlsocket";
+    static const char WOLFSSL_SYS_LISTEN_T[]        = "listen";
+    static const char WOLFSSL_SYS_OPENDIR_T[]       = "opendir";
+    static const char WOLFSSL_SYS_SETSOCKOPT_T[]    = "setsockopt";
+    static const char WOLFSSL_SYS_SOCKET_T[]        = "socket";
+
+    /* switch with int mapped to function name for compatibility */
+    static const char* wolfSSL_ERR_sys_func(int fun)
+    {
+        switch (fun) {
+            case WOLFSSL_SYS_ACCEPT:      return WOLFSSL_SYS_ACCEPT_T;
+            case WOLFSSL_SYS_BIND:        return WOLFSSL_SYS_BIND_T;
+            case WOLFSSL_SYS_CONNECT:     return WOLFSSL_SYS_CONNECT_T;
+            case WOLFSSL_SYS_FOPEN:       return WOLFSSL_SYS_FOPEN_T;
+            case WOLFSSL_SYS_FREAD:       return WOLFSSL_SYS_FREAD_T;
+            case WOLFSSL_SYS_GETADDRINFO: return WOLFSSL_SYS_GETADDRINFO_T;
+            case WOLFSSL_SYS_GETSOCKOPT:  return WOLFSSL_SYS_GETSOCKOPT_T;
+            case WOLFSSL_SYS_GETSOCKNAME: return WOLFSSL_SYS_GETSOCKNAME_T;
+            case WOLFSSL_SYS_GETHOSTBYNAME: return WOLFSSL_SYS_GETHOSTBYNAME_T;
+            case WOLFSSL_SYS_GETNAMEINFO: return WOLFSSL_SYS_GETNAMEINFO_T;
+            case WOLFSSL_SYS_GETSERVBYNAME: return WOLFSSL_SYS_GETSERVBYNAME_T;
+            case WOLFSSL_SYS_IOCTLSOCKET: return WOLFSSL_SYS_IOCTLSOCKET_T;
+            case WOLFSSL_SYS_LISTEN:      return WOLFSSL_SYS_LISTEN_T;
+            case WOLFSSL_SYS_OPENDIR:     return WOLFSSL_SYS_OPENDIR_T;
+            case WOLFSSL_SYS_SETSOCKOPT:  return WOLFSSL_SYS_SETSOCKOPT_T;
+            case WOLFSSL_SYS_SOCKET:      return WOLFSSL_SYS_SOCKET_T;
+            default:
+                return "NULL";
+        }
+    }
+#endif /* DEBUG_WOLFSSL */
+
+
+    /* @TODO when having an error queue this needs to push to the queue */
+    void wolfSSL_ERR_put_error(int lib, int fun, int err, const char* file,
+            int line)
+    {
+        WOLFSSL_ENTER("wolfSSL_ERR_put_error");
+
+        #if !defined(DEBUG_WOLFSSL) && !defined(OPENSSL_EXTRA)
+        (void)fun;
+        (void)err;
+        (void)file;
+        (void)line;
+        WOLFSSL_MSG("Not compiled in debug mode");
+        #elif defined(OPENSSL_EXTRA) && \
+                (defined(_WIN32) || defined(NO_ERROR_QUEUE))
+        (void)fun;
+        (void)file;
+        (void)line;
+        WOLFSSL_ERROR(err);
+        #else
+        WOLFSSL_ERROR_LINE(err, wolfSSL_ERR_sys_func(fun), (unsigned int)line,
+            file, NULL);
+        #endif
+        (void)lib;
+    }
+
+
+    /* Similar to wolfSSL_ERR_get_error_line but takes in a flags argument for
+     * more flexibility.
+     *
+     * file  output pointer to file where error happened
+     * line  output to line number of error
+     * data  output data. Is a string if ERR_TXT_STRING flag is used
+     * flags bit flag to adjust data output
+     *
+     * Returns the error value or 0 if no errors are in the queue
+     */
+    unsigned long wolfSSL_ERR_get_error_line_data(const char** file, int* line,
+                                                  const char** data, int *flags)
+    {
+        int ret;
+
+        WOLFSSL_STUB("wolfSSL_ERR_get_error_line_data");
+
+        if (flags != NULL) {
+            if ((*flags & ERR_TXT_STRING) == ERR_TXT_STRING) {
+                ret = wc_PullErrorNode(file, data, line);
+                if (ret < 0) {
+                    if (ret == BAD_STATE_E) return 0; /* no errors in queue */
+                    WOLFSSL_MSG("Error with pulling error node!");
+                    WOLFSSL_LEAVE("wolfSSL_ERR_get_error_line_data", ret);
+                    ret = 0 - ret; /* return absolute value of error */
+
+                    /* panic and try to clear out nodes */
+                    wc_ClearErrorNodes();
+                }
+
+                return (unsigned long)ret;
+            }
+        }
+
+        ret = wc_PullErrorNode(file, NULL, line);
+        if (ret < 0) {
+            if (ret == BAD_STATE_E) return 0; /* no errors in queue */
+            WOLFSSL_MSG("Error with pulling error node!");
+            WOLFSSL_LEAVE("wolfSSL_ERR_get_error_line_data", ret);
+            ret = 0 - ret; /* return absolute value of error */
+
+            /* panic and try to clear out nodes */
+            wc_ClearErrorNodes();
+        }
+
+        return (unsigned long)ret;
+    }
+
+#endif /* OPENSSL_EXTRA */
+
+
+#if (defined(KEEP_PEER_CERT) && defined(SESSION_CERTS)) || \
+                                   (defined(OPENSSL_ALL) && defined(HAVE_PKCS7))
+    /* Decode the X509 DER encoded certificate into a WOLFSSL_X509 object.
+     *
+     * x509  WOLFSSL_X509 object to decode into.
+     * in    X509 DER data.
+     * len   Length of the X509 DER data.
+     * returns the new certificate on success, otherwise NULL.
+     */
+    static int DecodeToX509(WOLFSSL_X509* x509, const byte* in, int len)
+    {
+        int          ret;
+    #ifdef WOLFSSL_SMALL_STACK
+        DecodedCert* cert;
+    #else
+        DecodedCert  cert[1];
+    #endif
+        if (x509 == NULL || in == NULL || len <= 0)
+            return BAD_FUNC_ARG;
+
+    #ifdef WOLFSSL_SMALL_STACK
+        cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
+                                     DYNAMIC_TYPE_DCERT);
+        if (cert == NULL)
+            return MEMORY_E;
+    #endif
+
+        /* Create a DecodedCert object and copy fields into WOLFSSL_X509 object.
+         */
+        InitDecodedCert(cert, (byte*)in, len, NULL);
+        if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL)) == 0) {
+        /* Check if x509 was not previously initialized by wolfSSL_X509_new() */
+            if (x509->dynamicMemory != TRUE)
+                InitX509(x509, 0, NULL);
+            ret = CopyDecodedToX509(x509, cert);
+            FreeDecodedCert(cert);
+        }
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
+    #endif
+
+        return ret;
+    }
+#endif /* (KEEP_PEER_CERT && SESSION_CERTS) || (OPENSSL_ALL && HAVE_PKCS7) */
+
+
+#ifdef KEEP_PEER_CERT
+    WOLFSSL_ABI
+    WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL* ssl)
+    {
+        WOLFSSL_ENTER("SSL_get_peer_certificate");
+        if (ssl == NULL)
+            return NULL;
+
+        if (ssl->peerCert.issuer.sz)
+            return &ssl->peerCert;
+#ifdef SESSION_CERTS
+        else if (ssl->session.chain.count > 0) {
+            if (DecodeToX509(&ssl->peerCert, ssl->session.chain.certs[0].buffer,
+                    ssl->session.chain.certs[0].length) == 0) {
+                return &ssl->peerCert;
+            }
+        }
+#endif
+        return 0;
+    }
+
+#endif /* KEEP_PEER_CERT */
+
+#if defined(SESSION_CERTS)
+/*  Return stack of peer certs.
+ *      If Qt or OPENSSL_ALL is defined then return ssl->peerCertChain.
+ *      All other cases return &ssl->session.chain
+ * ssl->peerCertChain is type WOLFSSL_STACK*
+ * ssl->session.chain is type WOLFSSL_X509_CHAIN
+ * Caller does not need to free return. The stack is Free'd when WOLFSSL* ssl is.
+ */
+WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL* ssl)
+{
+    WOLFSSL_STACK* sk;
+    WOLFSSL_ENTER("wolfSSL_get_peer_cert_chain");
+
+    if (ssl == NULL)
+        return NULL;
+
+    #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+        if (ssl->peerCertChain == NULL)
+            wolfSSL_set_peer_cert_chain((WOLFSSL*) ssl);
+        sk = ssl->peerCertChain;
+    #else
+        sk = (WOLF_STACK_OF(WOLFSSL_X509)* )&ssl->session.chain;
+    #endif
+
+    if (sk == NULL) {
+        WOLFSSL_MSG("Error: Null Peer Cert Chain");
+    }
+    return sk;
+}
+
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+/* Builds up and creates a stack of peer certificates for ssl->peerCertChain
+    based off of the ssl session chain. Returns stack of WOLFSSL_X509 certs or
+    NULL on failure */
+WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl)
+{
+    WOLFSSL_STACK* sk;
+    WOLFSSL_X509* x509;
+    int i = 0;
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_set_peer_cert_chain");
+    if ((ssl == NULL) || (ssl->session.chain.count == 0))
+        return NULL;
+
+    sk = wolfSSL_sk_X509_new();
+    i = ssl->session.chain.count-1;
+    for (; i >= 0; i--) {
+        /* For servers, the peer certificate chain does not include the peer
+            certificate, so do not add it to the stack */
+        if (ssl->options.side == WOLFSSL_SERVER_END && i == 0)
+            continue;
+        x509 = wolfSSL_X509_new();
+        if (x509 == NULL) {
+            WOLFSSL_MSG("Error Creating X509");
+            return NULL;
+        }
+        ret = DecodeToX509(x509, ssl->session.chain.certs[i].buffer,
+                             ssl->session.chain.certs[i].length);
+
+        if (ret != 0 || wolfSSL_sk_X509_push(sk, x509) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("Error decoding cert");
+            wolfSSL_X509_free(x509);
+            wolfSSL_sk_X509_free(sk);
+            return NULL;
+        }
+    }
+
+    if (sk == NULL) {
+        WOLFSSL_MSG("Null session chain");
+    }
+    /* This is Free'd when ssl is Free'd */
+    ssl->peerCertChain = sk;
+    return sk;
+}
+#endif /* OPENSSL_ALL || WOLFSSL_QT */
+#endif /* SESSION_CERTS */
+
+#ifndef NO_CERTS
+#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) || \
+    defined(OPENSSL_EXTRA)  || defined(OPENSSL_EXTRA_X509_SMALL)
+
+/* user externally called free X509, if dynamic go ahead with free, otherwise
+ * don't */
+static void ExternalFreeX509(WOLFSSL_X509* x509)
+{
+    int doFree = 0;
+
+    WOLFSSL_ENTER("ExternalFreeX509");
+    if (x509) {
+        if (x509->dynamicMemory) {
+        #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
+            if (wc_LockMutex(&x509->refMutex) != 0) {
+                WOLFSSL_MSG("Couldn't lock x509 mutex");
+            }
+            /* only free if all references to it are done */
+            x509->refCount--;
+            if (x509->refCount == 0)
+                doFree = 1;
+            wc_UnLockMutex(&x509->refMutex);
+        #else
+            doFree = 1;
+        #endif /* OPENSSL_EXTRA */
+
+            if (doFree) {
+                FreeX509(x509);
+                XFREE(x509, x509->heap, DYNAMIC_TYPE_X509);
+            }
+        } else {
+            WOLFSSL_MSG("free called on non dynamic object, not freeing");
+        }
+    }
+}
+
+/* Frees an external WOLFSSL_X509 structure */
+WOLFSSL_ABI
+void wolfSSL_X509_free(WOLFSSL_X509* x509)
+{
+    WOLFSSL_ENTER("wolfSSL_FreeX509");
+    ExternalFreeX509(x509);
+}
+
+
+/* copy name into in buffer, at most sz bytes, if buffer is null will
+   malloc buffer, call responsible for freeing                     */
+WOLFSSL_ABI
+char* wolfSSL_X509_NAME_oneline(WOLFSSL_X509_NAME* name, char* in, int sz)
+{
+    int copySz;
+
+    if (name == NULL) {
+        WOLFSSL_MSG("WOLFSSL_X509_NAME pointer was NULL");
+        return NULL;
+    }
+
+    copySz = min(sz, name->sz);
+
+    WOLFSSL_ENTER("wolfSSL_X509_NAME_oneline");
+    if (!name->sz) return in;
+
+    if (!in) {
+    #ifdef WOLFSSL_STATIC_MEMORY
+        WOLFSSL_MSG("Using static memory -- please pass in a buffer");
+        return NULL;
+    #else
+        in = (char*)XMALLOC(name->sz, NULL, DYNAMIC_TYPE_OPENSSL);
+        if (!in ) return in;
+        copySz = name->sz;
+    #endif
+    }
+
+    if (copySz <= 0)
+        return in;
+
+    XMEMCPY(in, name->name, copySz - 1);
+    in[copySz - 1] = 0;
+
+    return in;
+}
+
+#if defined(OPENSSL_EXTRA) && defined(XSNPRINTF)
+/* Copies X509 subject name into a buffer, with comma-separated name entries
+ *   (matching OpenSSL v1.0.0 format)
+ * Example Output for Issuer:
+ *
+ * C=US, ST=Montana, L=Bozeman, O=Sawtooth, OU=Consulting,
+ *  CN=www.wolfssl.com, emailAddress=info@wolfssl.com
+ */
+char* wolfSSL_X509_get_name_oneline(WOLFSSL_X509_NAME* name, char* in, int sz)
+{
+    WOLFSSL_X509_NAME_ENTRY* entry;
+    int nameSz, strSz, count, i, idx = 0;
+    int totalSz = 0;
+    char *str;
+    char tmpBuf[256];
+    char buf[80];
+    const char* sn;
+    WOLFSSL_ENTER("wolfSSL_X509_get_name_oneline");
+
+    if (name == NULL) {
+        WOLFSSL_MSG("wolfSSL_X509_get_subject_name failed");
+        return NULL;
+    }
+    #ifdef WOLFSSL_STATIC_MEMORY
+    if (!in) {
+        WOLFSSL_MSG("Using static memory -- please pass in a buffer");
+        return NULL;
+    }
+    #endif
+
+    tmpBuf[0] = '\0'; /* Make sure tmpBuf is NULL terminated */
+    /* Loop through X509 name entries and copy new format to buffer */
+    count = wolfSSL_X509_NAME_entry_count(name);
+    for (i = 0; i < count; i++) {
+
+        /* Get name entry and size */
+        entry = wolfSSL_X509_NAME_get_entry(name, i);
+        if (entry == NULL) {
+            WOLFSSL_MSG("X509_NAME_get_entry failed");
+            return NULL;
+        }
+        nameSz = wolfSSL_X509_NAME_get_text_by_NID(name, entry->nid, buf,
+                                                                   sizeof(buf));
+        if (nameSz < 0) {
+            WOLFSSL_MSG("X509_NAME_get_text_by_NID failed");
+            return NULL;
+        }
+
+        /* Get short name */
+        sn = wolfSSL_OBJ_nid2sn(entry->nid);
+        if (sn == NULL) {
+            WOLFSSL_MSG("OBJ_nid2sn failed");
+            return NULL;
+        }
+
+        /* Copy sn and name text to buffer
+         * Add extra strSz for '=', ',', ' ' and '\0' characters in XSNPRINTF.
+         */
+        if (i != count - 1) {
+            strSz = (int)XSTRLEN(sn) + nameSz + 4;
+            totalSz+= strSz;
+            str = (char*)XMALLOC(strSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            if (str == NULL) {
+                WOLFSSL_MSG("Memory error");
+                return NULL;
+            }
+            XSNPRINTF(str, strSz, "%s=%s, ", sn, buf);
+        }
+        else {
+            /* Copy last name entry
+            * Add extra strSz for '=' and '\0' characters in XSNPRINTF.
+            */
+            strSz = (int)XSTRLEN(sn) + nameSz + 2;
+            totalSz+= strSz;
+            str = (char*)XMALLOC(strSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            if (str == NULL) {
+                WOLFSSL_MSG("Memory error");
+                return NULL;
+            }
+            XSNPRINTF(str, strSz, "%s=%s", sn, buf);
+        }
+        /* Copy string to tmpBuf */
+        XSTRNCAT(tmpBuf, str, strSz);
+        idx += strSz;
+        XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+
+    /* Allocate space based on total string size if no buffer was provided */
+    if (!in) {
+        in = (char*)XMALLOC(totalSz+1, NULL, DYNAMIC_TYPE_OPENSSL);
+        if (in == NULL) {
+            WOLFSSL_MSG("Memory error");
+            return in;
+        }
+    }
+    else {
+        if (totalSz > sz) {
+            WOLFSSL_MSG("Memory error");
+            return NULL;
+        }
+    }
+
+    XMEMCPY(in, tmpBuf, totalSz);
+    in[totalSz] = '\0';
+
+    return in;
+}
+#endif
+
+
+/* Wraps wolfSSL_X509_d2i
+ *
+ * returns a WOLFSSL_X509 structure pointer on success and NULL on fail
+ */
+WOLFSSL_X509* wolfSSL_d2i_X509(WOLFSSL_X509** x509, const unsigned char** in,
+        int len)
+{
+    WOLFSSL_X509* newX509 = NULL;
+
+    newX509 = wolfSSL_X509_d2i(x509, *in, len);
+    if (newX509 != NULL) {
+        *in += newX509->derCert->length;
+    }
+    return newX509;
+}
+
+
+WOLFSSL_X509* wolfSSL_X509_d2i(WOLFSSL_X509** x509, const byte* in, int len)
+{
+    WOLFSSL_X509 *newX509 = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_X509_d2i");
+
+    if (in != NULL && len != 0) {
+    #ifdef WOLFSSL_SMALL_STACK
+        DecodedCert* cert;
+    #else
+        DecodedCert  cert[1];
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
+                                     DYNAMIC_TYPE_DCERT);
+        if (cert == NULL)
+            return NULL;
+    #endif
+
+        InitDecodedCert(cert, (byte*)in, len, NULL);
+        if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0) {
+            newX509 = wolfSSL_X509_new();
+            if (newX509 != NULL) {
+                if (CopyDecodedToX509(newX509, cert) != 0) {
+                    wolfSSL_X509_free(newX509);
+                    newX509 = NULL;
+                }
+            }
+        }
+        FreeDecodedCert(cert);
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
+    #endif
+    }
+
+    if (x509 != NULL)
+        *x509 = newX509;
+
+    return newX509;
+}
+#endif /* KEEP_PEER_CERT || SESSION_CERTS || OPENSSL_EXTRA ||
+          OPENSSL_EXTRA_X509_SMALL */
+
+
+
+#if defined(OPENSSL_ALL) || defined(KEEP_OUR_CERT) || defined(KEEP_PEER_CERT) || \
+    defined(SESSION_CERTS)
+    /* return the next, if any, altname from the peer cert */
+    WOLFSSL_ABI
+    char* wolfSSL_X509_get_next_altname(WOLFSSL_X509* cert)
+    {
+        char* ret = NULL;
+        WOLFSSL_ENTER("wolfSSL_X509_get_next_altname");
+
+        /* don't have any to work with */
+        if (cert == NULL || cert->altNames == NULL)
+            return NULL;
+
+        /* already went through them */
+        if (cert->altNamesNext == NULL)
+            return NULL;
+
+        ret = cert->altNamesNext->name;
+        cert->altNamesNext = cert->altNamesNext->next;
+
+        return ret;
+    }
+
+    int wolfSSL_X509_get_isCA(WOLFSSL_X509* x509)
+    {
+        int isCA = 0;
+
+        WOLFSSL_ENTER("wolfSSL_X509_get_isCA");
+
+        if (x509 != NULL)
+            isCA = x509->isCa;
+
+        WOLFSSL_LEAVE("wolfSSL_X509_get_isCA", isCA);
+
+        return isCA;
+    }
+
+    int wolfSSL_X509_get_signature(WOLFSSL_X509* x509,
+                                                 unsigned char* buf, int* bufSz)
+    {
+        WOLFSSL_ENTER("wolfSSL_X509_get_signature");
+        if (x509 == NULL || bufSz == NULL || (*bufSz < (int)x509->sig.length &&
+                    buf != NULL))
+            return WOLFSSL_FATAL_ERROR;
+
+        if (buf != NULL)
+            XMEMCPY(buf, x509->sig.buffer, x509->sig.length);
+        *bufSz = x509->sig.length;
+
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    /* Getter function that copies over the DER public key buffer to "buf" and
+     * sets the size in bufSz. If "buf" is NULL then just bufSz is set to needed
+     * buffer size. "bufSz" passed in should initially be set by the user to be
+     * the size of "buf". This gets checked to make sure the buffer is large
+     * enough to hold the public key.
+     *
+     * Note: this is the X.509 form of key with "header" info.
+     * return WOLFSSL_SUCCESS on success
+     */
+    int wolfSSL_X509_get_pubkey_buffer(WOLFSSL_X509* x509,
+                                                unsigned char* buf, int* bufSz)
+    {
+    #ifdef WOLFSSL_SMALL_STACK
+        DecodedCert* cert;
+    #else
+        DecodedCert cert[1];
+    #endif
+        word32 idx;
+        const byte*  der;
+        int length = 0;
+        int    ret, derSz = 0;
+        int badDate = 0;
+        const byte* pubKeyX509 = NULL;
+        int   pubKeyX509Sz = 0;
+
+        WOLFSSL_ENTER("wolfSSL_X509_get_pubkey_buffer");
+        if (x509 == NULL || bufSz == NULL) {
+            WOLFSSL_LEAVE("wolfSSL_X509_get_pubkey_buffer", BAD_FUNC_ARG);
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+
+    #ifdef WOLFSSL_SMALL_STACK
+        cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert),
+                                       x509->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        if (cert == NULL) {
+            WOLFSSL_LEAVE("wolfSSL_X509_get_pubkey_buffer", MEMORY_E);
+            return WOLFSSL_FATAL_ERROR;
+        }
+    #endif
+
+        der = wolfSSL_X509_get_der(x509, &derSz);
+        InitDecodedCert(cert, der, derSz, NULL);
+        ret = wc_GetPubX509(cert, 0, &badDate);
+        if (ret >= 0) {
+            idx = cert->srcIdx;
+            pubKeyX509 = cert->source + cert->srcIdx;
+            ret = GetSequence(cert->source, &cert->srcIdx, &length,
+                    cert->maxIdx);
+            pubKeyX509Sz = length + (cert->srcIdx - idx);
+        }
+
+        FreeDecodedCert(cert);
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(cert, x509->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+
+        if (ret < 0) {
+            WOLFSSL_LEAVE("wolfSSL_X509_get_pubkey_buffer", ret);
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        if (buf != NULL) {
+            if (pubKeyX509Sz > *bufSz) {
+                WOLFSSL_LEAVE("wolfSSL_X509_get_pubkey_buffer", BUFFER_E);
+                return WOLFSSL_FATAL_ERROR;
+            }
+            XMEMCPY(buf, pubKeyX509, pubKeyX509Sz);
+        }
+        *bufSz = pubKeyX509Sz;
+
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    /* Getter function for the public key OID value
+     * return public key OID stored in WOLFSSL_X509 structure */
+    int wolfSSL_X509_get_pubkey_type(WOLFSSL_X509* x509)
+    {
+        if (x509 == NULL)
+            return WOLFSSL_FAILURE;
+        return x509->pubKeyOID;
+    }
+
+    /* write X509 serial number in unsigned binary to buffer
+       buffer needs to be at least EXTERNAL_SERIAL_SIZE (32) for all cases
+       return WOLFSSL_SUCCESS on success */
+    int wolfSSL_X509_get_serial_number(WOLFSSL_X509* x509,
+                                       byte* in, int* inOutSz)
+    {
+        WOLFSSL_ENTER("wolfSSL_X509_get_serial_number");
+        if (x509 == NULL || in == NULL ||
+                                   inOutSz == NULL || *inOutSz < x509->serialSz)
+            return BAD_FUNC_ARG;
+
+        XMEMCPY(in, x509->serial, x509->serialSz);
+        *inOutSz = x509->serialSz;
+
+        return WOLFSSL_SUCCESS;
+    }
+
+    /* not an openssl compatibility function - getting for derCert */
+    const byte* wolfSSL_X509_get_der(WOLFSSL_X509* x509, int* outSz)
+    {
+        WOLFSSL_ENTER("wolfSSL_X509_get_der");
+
+        if (x509 == NULL || x509->derCert == NULL || outSz == NULL)
+            return NULL;
+
+        *outSz = (int)x509->derCert->length;
+        return x509->derCert->buffer;
+    }
+
+    /* used by JSSE (not a standard compatibility function) */
+    /* this is not thread safe */
+    WOLFSSL_ABI
+    const byte* wolfSSL_X509_notBefore(WOLFSSL_X509* x509)
+    {
+        static byte notBeforeData[CTC_DATE_SIZE]; /* temp buffer for date */
+        WOLFSSL_ENTER("wolfSSL_X509_notBefore");
+
+        if (x509 == NULL)
+            return NULL;
+
+        XMEMSET(notBeforeData, 0, sizeof(notBeforeData));
+        notBeforeData[0] = (byte)x509->notBefore.type;
+        notBeforeData[1] = (byte)x509->notBefore.length;
+        XMEMCPY(&notBeforeData[2], x509->notBefore.data, x509->notBefore.length);
+
+        return notBeforeData;
+    }
+    /* used by JSSE (not a standard compatibility function) */
+    /* this is not thread safe */
+    WOLFSSL_ABI
+    const byte* wolfSSL_X509_notAfter(WOLFSSL_X509* x509)
+    {
+        static byte notAfterData[CTC_DATE_SIZE]; /* temp buffer for date */
+        WOLFSSL_ENTER("wolfSSL_X509_notAfter");
+
+        if (x509 == NULL)
+            return NULL;
+
+        XMEMSET(notAfterData, 0, sizeof(notAfterData));
+        notAfterData[0] = (byte)x509->notAfter.type;
+        notAfterData[1] = (byte)x509->notAfter.length;
+        XMEMCPY(&notAfterData[2], x509->notAfter.data, x509->notAfter.length);
+
+        return notAfterData;
+    }
+
+    #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) && !defined(NO_WOLFSSL_STUB)
+    WOLFSSL_ASN1_TIME* wolfSSL_X509_gmtime_adj(WOLFSSL_ASN1_TIME *s, long adj)
+    {
+        (void) s;
+        (void) adj;
+        WOLFSSL_STUB("wolfSSL_X509_gmtime_adj");
+        return NULL;
+    }
+    #endif
+
+    /* get the buffer to be signed (tbs) from the WOLFSSL_X509 certificate
+     *
+     * outSz : gets set to the size of the buffer
+     * returns a pointer to the internal buffer at the location of TBS on
+     *         on success and NULL on failure.
+     */
+    const unsigned char* wolfSSL_X509_get_tbs(WOLFSSL_X509* x509, int* outSz)
+    {
+        int sz = 0, len;
+        unsigned int idx = 0, tmpIdx;
+        const unsigned char* der = NULL;
+        const unsigned char* tbs = NULL;
+
+        if (x509 == NULL || outSz == NULL) {
+            return NULL;
+        }
+
+        der = wolfSSL_X509_get_der(x509, &sz);
+        if (der == NULL) {
+            return NULL;
+        }
+
+        if (GetSequence(der, &idx, &len, sz) < 0) {
+            return NULL;
+        }
+        tbs = der + idx;
+        tmpIdx = idx;
+        if (GetSequence(der, &idx, &len, sz) < 0) {
+            return NULL;
+        }
+        *outSz = len + (idx - tmpIdx);
+        return tbs;
+    }
+
+    int wolfSSL_X509_version(WOLFSSL_X509* x509)
+    {
+        WOLFSSL_ENTER("wolfSSL_X509_version");
+
+        if (x509 == NULL)
+            return 0;
+
+        return x509->version;
+    }
+
+#ifdef WOLFSSL_SEP
+
+/* copy oid into in buffer, at most *inOutSz bytes, if buffer is null will
+   malloc buffer, call responsible for freeing. Actual size returned in
+   *inOutSz. Requires inOutSz be non-null */
+byte* wolfSSL_X509_get_device_type(WOLFSSL_X509* x509, byte* in, int *inOutSz)
+{
+    int copySz;
+
+    WOLFSSL_ENTER("wolfSSL_X509_get_dev_type");
+    if (inOutSz == NULL) return NULL;
+    if (!x509->deviceTypeSz) return in;
+
+    copySz = min(*inOutSz, x509->deviceTypeSz);
+
+    if (!in) {
+    #ifdef WOLFSSL_STATIC_MEMORY
+        WOLFSSL_MSG("Using static memory -- please pass in a buffer");
+        return NULL;
+    #else
+        in = (byte*)XMALLOC(x509->deviceTypeSz, 0, DYNAMIC_TYPE_OPENSSL);
+        if (!in) return in;
+        copySz = x509->deviceTypeSz;
+    #endif
+    }
+
+    XMEMCPY(in, x509->deviceType, copySz);
+    *inOutSz = copySz;
+
+    return in;
+}
+
+
+byte* wolfSSL_X509_get_hw_type(WOLFSSL_X509* x509, byte* in, int* inOutSz)
+{
+    int copySz;
+
+    WOLFSSL_ENTER("wolfSSL_X509_get_hw_type");
+    if (inOutSz == NULL) return NULL;
+    if (!x509->hwTypeSz) return in;
+
+    copySz = min(*inOutSz, x509->hwTypeSz);
+
+    if (!in) {
+    #ifdef WOLFSSL_STATIC_MEMORY
+        WOLFSSL_MSG("Using static memory -- please pass in a buffer");
+        return NULL;
+    #else
+        in = (byte*)XMALLOC(x509->hwTypeSz, 0, DYNAMIC_TYPE_OPENSSL);
+        if (!in) return in;
+        copySz = x509->hwTypeSz;
+    #endif
+    }
+
+    XMEMCPY(in, x509->hwType, copySz);
+    *inOutSz = copySz;
+
+    return in;
+}
+
+
+byte* wolfSSL_X509_get_hw_serial_number(WOLFSSL_X509* x509,byte* in,
+                                        int* inOutSz)
+{
+    int copySz;
+
+    WOLFSSL_ENTER("wolfSSL_X509_get_hw_serial_number");
+    if (inOutSz == NULL) return NULL;
+    if (!x509->hwTypeSz) return in;
+
+    copySz = min(*inOutSz, x509->hwSerialNumSz);
+
+    if (!in) {
+    #ifdef WOLFSSL_STATIC_MEMORY
+        WOLFSSL_MSG("Using static memory -- please pass in a buffer");
+        return NULL;
+    #else
+        in = (byte*)XMALLOC(x509->hwSerialNumSz, 0, DYNAMIC_TYPE_OPENSSL);
+        if (!in) return in;
+        copySz = x509->hwSerialNumSz;
+    #endif
+    }
+
+    XMEMCPY(in, x509->hwSerialNum, copySz);
+    *inOutSz = copySz;
+
+    return in;
+}
+
+#endif /* WOLFSSL_SEP */
+
+/* require OPENSSL_EXTRA since wolfSSL_X509_free is wrapped by OPENSSL_EXTRA */
+#if !defined(NO_CERTS) && defined(OPENSSL_EXTRA)
+
+WOLFSSL_ASN1_TIME* wolfSSL_X509_get_notBefore(const WOLFSSL_X509* x509)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_get_notBefore");
+
+    if (x509 == NULL)
+        return NULL;
+
+    return (WOLFSSL_ASN1_TIME*)&x509->notBefore;
+}
+
+
+WOLFSSL_ASN1_TIME* wolfSSL_X509_get_notAfter(const WOLFSSL_X509* x509)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_get_notAfter");
+
+    if (x509 == NULL)
+        return NULL;
+
+    return (WOLFSSL_ASN1_TIME*)&x509->notAfter;
+}
+
+
+/* return 1 on success 0 on fail */
+int wolfSSL_sk_X509_push(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, WOLFSSL_X509* x509)
+{
+    WOLFSSL_STACK* node;
+    WOLFSSL_ENTER("wolfSSL_sk_X509_push");
+
+    if (sk == NULL || x509 == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* no previous values in stack */
+    if (sk->data.x509 == NULL) {
+        sk->data.x509 = x509;
+        sk->num += 1;
+        return WOLFSSL_SUCCESS;
+    }
+
+    /* stack already has value(s) create a new node and add more */
+    node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+                                                             DYNAMIC_TYPE_X509);
+    if (node == NULL) {
+        WOLFSSL_MSG("Memory error");
+        return WOLFSSL_FAILURE;
+    }
+    XMEMSET(node, 0, sizeof(WOLFSSL_STACK));
+
+    /* push new x509 onto head of stack */
+    node->data.x509 = sk->data.x509;
+    node->next      = sk->next;
+    node->type      = sk->type;
+    sk->next        = node;
+    sk->data.x509   = x509;
+    sk->num        += 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+WOLFSSL_X509* wolfSSL_sk_X509_pop(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk) {
+    WOLFSSL_STACK* node;
+    WOLFSSL_X509*  x509;
+
+    if (sk == NULL) {
+        return NULL;
+    }
+
+    node = sk->next;
+    x509 = sk->data.x509;
+
+    if (node != NULL) { /* update sk and remove node from stack */
+        sk->data.x509 = node->data.x509;
+        sk->next = node->next;
+        XFREE(node, NULL, DYNAMIC_TYPE_X509);
+    }
+    else { /* last x509 in stack */
+        sk->data.x509 = NULL;
+    }
+
+    if (sk->num > 0) {
+        sk->num -= 1;
+    }
+
+    return x509;
+}
+
+/* Getter function for WOLFSSL_X509 pointer
+ *
+ * sk is the stack to retrieve pointer from
+ * i  is the index value in stack
+ *
+ * returns a pointer to a WOLFSSL_X509 structure on success and NULL on
+ *         fail
+ */
+WOLFSSL_X509* wolfSSL_sk_X509_value(STACK_OF(WOLFSSL_X509)* sk, int i)
+{
+    WOLFSSL_ENTER("wolfSSL_sk_X509_value");
+
+    for (; sk != NULL && i > 0; i--)
+        sk = sk->next;
+
+    if (i != 0 || sk == NULL)
+        return NULL;
+    return sk->data.x509;
+}
+
+WOLFSSL_X509* wolfSSL_sk_X509_shift(WOLF_STACK_OF(WOLFSSL_X509)* sk)
+{
+    return wolfSSL_sk_X509_pop(sk);
+}
+
+#ifndef NO_WOLFSSL_STUB
+void* wolfSSL_sk_X509_OBJECT_value(WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* sk, int x)
+{
+    (void) sk;
+    (void) x;
+    return NULL;
+}
+#endif
+
+
+/* Free's all nodes in X509 stack. This is different then wolfSSL_sk_X509_free
+ * in that it allows for choosing the function to use when freeing an X509s.
+ *
+ * sk  stack to free nodes in
+ * f   X509 free function
+ */
+void wolfSSL_sk_X509_pop_free(STACK_OF(WOLFSSL_X509)* sk,
+    void (*f) (WOLFSSL_X509*))
+{
+    WOLFSSL_STACK* node;
+
+    WOLFSSL_ENTER("wolfSSL_sk_X509_pop_free");
+
+    if (sk == NULL) {
+        return;
+    }
+
+    /* parse through stack freeing each node */
+    node = sk->next;
+    while (node && sk->num > 1) {
+        WOLFSSL_STACK* tmp = node;
+        node = node->next;
+
+        if (f)
+            f(tmp->data.x509);
+        else
+            wolfSSL_X509_free(tmp->data.x509);
+        tmp->data.x509 = NULL;
+        XFREE(tmp, NULL, DYNAMIC_TYPE_X509);
+        sk->num -= 1;
+    }
+
+    /* free head of stack */
+    if (sk->num == 1) {
+        if (f)
+            f(sk->data.x509);
+        else
+            wolfSSL_X509_free(sk->data.x509);
+        sk->data.x509 = NULL;
+    }
+    XFREE(sk, NULL, DYNAMIC_TYPE_X509);
+}
+
+
+/* free structure for x509 stack */
+void wolfSSL_sk_X509_free(WOLF_STACK_OF(WOLFSSL_X509)* sk)
+{
+    wolfSSL_sk_X509_pop_free(sk, NULL);
+}
+
+#endif /* NO_CERTS && OPENSSL_EXTRA */
+
+#if defined(OPENSSL_ALL) || defined (WOLFSSL_QT)
+/* return 1 on success 0 on fail */
+int wolfSSL_sk_ACCESS_DESCRIPTION_push(WOLF_STACK_OF(ACCESS_DESCRIPTION)* sk,
+                                              WOLFSSL_ACCESS_DESCRIPTION* access)
+{
+    WOLFSSL_STACK* node;
+
+    WOLFSSL_ENTER("wolfSSL_sk_ACCESS_DESCRIPTION_push");
+
+    if (sk == NULL || access == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* no previous values in stack */
+    if (sk->data.access == NULL) {
+        sk->data.access = access;
+        sk->num += 1;
+        return WOLFSSL_SUCCESS;
+    }
+
+    /* stack already has value(s) create a new node and add more */
+    node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+                                   DYNAMIC_TYPE_ASN1);
+    if (node == NULL) {
+        WOLFSSL_MSG("Memory error");
+        return WOLFSSL_FAILURE;
+    }
+    XMEMSET(node, 0, sizeof(WOLFSSL_STACK));
+
+    /* push new obj onto head of stack */
+    node->data.access  = sk->data.access;
+    node->next         = sk->next;
+    node->type         = sk->type;
+    sk->next           = node;
+    sk->data.access    = access;
+    sk->num            += 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* Frees all nodes in ACCESS_DESCRIPTION stack
+*
+* sk stack of nodes to free
+* f  free function to use, not called with wolfSSL
+*/
+void wolfSSL_sk_ACCESS_DESCRIPTION_pop_free(WOLFSSL_STACK* sk,
+    void (*f) (WOLFSSL_ACCESS_DESCRIPTION*))
+{
+   WOLFSSL_STACK* node;
+
+   WOLFSSL_ENTER("wolfSSL_sk_ACCESS_DESCRIPTION_pop_free");
+
+   if (sk == NULL) {
+       return;
+   }
+
+   /* parse through stack freeing each node */
+   node = sk->next;
+   while (node && sk->num > 1) {
+       WOLFSSL_STACK* tmp = node;
+       node = node->next;
+
+       if (f)
+           f(tmp->data.access);
+       else
+           wolfSSL_ACCESS_DESCRIPTION_free(tmp->data.access);
+       tmp->data.access = NULL;
+       XFREE(tmp, NULL, DYNAMIC_TYPE_ASN1);
+       sk->num -= 1;
+   }
+
+   /* free head of stack */
+   if (sk->num == 1) {
+        if (f)
+            f(sk->data.access);
+        else {
+            if(sk->data.access->method) {
+
+               wolfSSL_ASN1_OBJECT_free(sk->data.access->method);
+            }
+            if(sk->data.access->location) {
+               wolfSSL_GENERAL_NAME_free(sk->data.access->location);
+            }
+        }
+        sk->data.access = NULL;
+   }
+   XFREE(sk, NULL, DYNAMIC_TYPE_ASN1);
+}
+
+void wolfSSL_sk_ACCESS_DESCRIPTION_free(WOLFSSL_STACK* sk)
+{
+    wolfSSL_sk_ACCESS_DESCRIPTION_pop_free(sk, NULL);
+}
+
+void wolfSSL_ACCESS_DESCRIPTION_free(WOLFSSL_ACCESS_DESCRIPTION* access)
+{
+    WOLFSSL_ENTER("wolfSSL_ACCESS_DESCRIPTION_free");
+    if (access == NULL)
+        return;
+
+    if (access->method)
+        wolfSSL_ASN1_OBJECT_free(access->method);
+    if (access->location)
+        wolfSSL_GENERAL_NAME_free(access->location);
+
+    /* access = NULL, don't try to access or double free it */
+}
+#endif
+
+#ifdef OPENSSL_EXTRA
+
+/* create a generic wolfSSL stack node
+ * returns a new WOLFSSL_STACK structure on success */
+WOLFSSL_STACK* wolfSSL_sk_new_node(void* heap)
+{
+    WOLFSSL_STACK* sk;
+    WOLFSSL_ENTER("wolfSSL_sk_new_node");
+
+    sk = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), heap,
+                                                          DYNAMIC_TYPE_OPENSSL);
+    if (sk != NULL) {
+        XMEMSET(sk, 0, sizeof(*sk));
+        sk->heap = heap;
+    }
+
+    return sk;
+}
+
+/* free's node but does not free internal data such as in->data.x509 */
+void wolfSSL_sk_free_node(WOLFSSL_STACK* in)
+{
+    if (in != NULL) {
+        XFREE(in, in->heap, DYNAMIC_TYPE_OPENSSL);
+    }
+}
+
+/* pushes node "in" onto "stack" and returns pointer to the new stack on success
+ * also handles internal "num" for number of nodes on stack
+ * return WOLFSSL_SUCCESS on success
+ */
+int wolfSSL_sk_push_node(WOLFSSL_STACK** stack, WOLFSSL_STACK* in)
+{
+    if (stack == NULL || in == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if (*stack == NULL) {
+        in->num = 1;
+        *stack = in;
+        return WOLFSSL_SUCCESS;
+    }
+
+    in->num  = (*stack)->num + 1;
+    in->next = *stack;
+    *stack   = in;
+    return WOLFSSL_SUCCESS;
+}
+
+/* return 1 on success 0 on fail */
+int wolfSSL_sk_push(WOLFSSL_STACK* sk, const void *data)
+{
+    int ret = WOLFSSL_FAILURE;
+    WOLFSSL_ENTER("wolfSSL_sk_push");
+
+    switch (sk->type) {
+    #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+        case STACK_TYPE_X509:
+            ret = wolfSSL_sk_X509_push(sk, (WOLFSSL_X509*) data);
+            break;
+        #ifndef NO_WOLFSSL_STUB
+        case STACK_TYPE_CIPHER:
+            ret = wolfSSL_sk_CIPHER_push(sk, (WOLFSSL_CIPHER*) data);
+            break;
+        #endif
+        case STACK_TYPE_GEN_NAME:
+            ret = wolfSSL_sk_ASN1_OBJECT_push(sk, (WOLFSSL_ASN1_OBJECT*) data);
+            break;
+        case STACK_TYPE_ACCESS_DESCRIPTION:
+            ret = wolfSSL_sk_ACCESS_DESCRIPTION_push(sk,
+                                            (WOLFSSL_ACCESS_DESCRIPTION*) data);
+            break;
+        case STACK_TYPE_NULL:
+            ret = wolfSSL_sk_GENERIC_push(sk, (void*) data);
+            break;
+        case STACK_TYPE_OBJ:
+            ret = wolfSSL_sk_ASN1_OBJECT_push(sk, (WOLFSSL_ASN1_OBJECT*) data);
+            break;
+    #endif
+        default:
+            ret = wolfSSL_sk_ASN1_OBJECT_push(sk, (WOLFSSL_ASN1_OBJECT*) data);
+            break;
+    }
+
+    return ret;
+}
+
+/* Creates and returns new GENERAL_NAME structure */
+WOLFSSL_GENERAL_NAME* wolfSSL_GENERAL_NAME_new(void)
+{
+    WOLFSSL_GENERAL_NAME* gn;
+    WOLFSSL_ENTER("GENERAL_NAME_new");
+
+    gn = (WOLFSSL_GENERAL_NAME*)XMALLOC(sizeof(WOLFSSL_GENERAL_NAME), NULL,
+                                                             DYNAMIC_TYPE_ASN1);
+    if (gn == NULL) {
+        return NULL;
+    }
+    XMEMSET(gn, 0, sizeof(WOLFSSL_GENERAL_NAME));
+
+    gn->d.ia5 = wolfSSL_ASN1_STRING_new();
+    if (gn->d.ia5 == NULL) {
+        WOLFSSL_MSG("Issue creating ASN1_STRING struct");
+        wolfSSL_GENERAL_NAME_free(gn);
+        return NULL;
+    }
+    return gn;
+}
+
+/* return 1 on success 0 on fail */
+int wolfSSL_sk_GENERAL_NAME_push(WOLF_STACK_OF(WOLFSSL_GENERAL_NAME)* sk,
+                                                      WOLFSSL_GENERAL_NAME* gn)
+{
+    WOLFSSL_STACK* node;
+    WOLFSSL_ENTER("wolfSSL_sk_GENERAL_NAME_push");
+
+    if (sk == NULL || gn == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* no previous values in stack */
+    if (sk->data.gn == NULL) {
+        sk->data.gn = gn;
+        sk->num += 1;
+
+        return WOLFSSL_SUCCESS;
+    }
+
+    /* stack already has value(s) create a new node and add more */
+    node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+                                                             DYNAMIC_TYPE_ASN1);
+    if (node == NULL) {
+        WOLFSSL_MSG("Memory error");
+        return WOLFSSL_FAILURE;
+    }
+    XMEMSET(node, 0, sizeof(WOLFSSL_STACK));
+
+    /* push new obj onto head of stack */
+    node->data.gn = sk->data.gn;
+    node->next    = sk->next;
+    sk->next      = node;
+    sk->data.gn   = gn;
+    sk->num      += 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* Returns the general name at index i from the stack
+ *
+ * sk  stack to get general name from
+ * idx index to get
+ *
+ * return a pointer to the internal node of the stack
+ */
+WOLFSSL_GENERAL_NAME* wolfSSL_sk_GENERAL_NAME_value(WOLFSSL_STACK* sk, int idx)
+{
+    WOLFSSL_STACK* ret;
+
+    if (sk == NULL) {
+        return NULL;
+    }
+
+    ret = wolfSSL_sk_get_node(sk, idx);
+    if (ret != NULL) {
+        return ret->data.gn;
+    }
+    return NULL;
+}
+
+/* Gets the number of nodes in the stack
+ *
+ * sk  stack to get the number of nodes from
+ *
+ * returns the number of nodes, -1 if no nodes
+ */
+int wolfSSL_sk_GENERAL_NAME_num(WOLFSSL_STACK* sk)
+{
+    WOLFSSL_ENTER("wolfSSL_sk_GENERAL_NAME_num");
+
+    if (sk == NULL) {
+        return -1;
+    }
+
+    return (int)sk->num;
+}
+
+/* Frees all nodes in a GENERAL NAME stack
+ *
+ * sk stack of nodes to free
+ * f  free function to use, not called with wolfSSL
+ */
+void wolfSSL_sk_GENERAL_NAME_pop_free(WOLFSSL_STACK* sk,
+        void (*f) (WOLFSSL_GENERAL_NAME*))
+{
+    WOLFSSL_STACK* node;
+
+    WOLFSSL_ENTER("wolfSSL_sk_GENERAL_NAME_pop_free");
+
+    if (sk == NULL) {
+        return;
+    }
+
+    /* parse through stack freeing each node */
+    node = sk->next;
+    while (node && sk->num > 1) {
+        WOLFSSL_STACK* tmp = node;
+        node = node->next;
+
+        if (f)
+            f(tmp->data.gn);
+        else
+            wolfSSL_GENERAL_NAME_free(tmp->data.gn);
+        XFREE(tmp, NULL, DYNAMIC_TYPE_ASN1);
+        sk->num -= 1;
+    }
+
+    /* free head of stack */
+    if (sk->num == 1) {
+        if (f)
+            f(sk->data.gn);
+        else
+            wolfSSL_GENERAL_NAME_free(sk->data.gn);
+    }
+    XFREE(sk, NULL, DYNAMIC_TYPE_ASN1);
+}
+
+void wolfSSL_sk_GENERAL_NAME_free(WOLFSSL_STACK* sk)
+{
+    WOLFSSL_ENTER("sk_GENERAL_NAME_free");
+    wolfSSL_sk_GENERAL_NAME_pop_free(sk, NULL);
+}
+
+
+/* returns the number of nodes in stack on success and WOLFSSL_FATAL_ERROR
+ * on fail */
+int wolfSSL_sk_ACCESS_DESCRIPTION_num(WOLFSSL_STACK* sk)
+{
+    if (sk == NULL) {
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    return (int)sk->num;
+}
+
+#ifndef NO_WOLFSSL_STUB
+/* similar to call to sk_ACCESS_DESCRIPTION_pop_free */
+void wolfSSL_AUTHORITY_INFO_ACCESS_free(
+        WOLF_STACK_OF(WOLFSSL_ACCESS_DESCRIPTION)* sk)
+{
+    WOLFSSL_STUB("wolfSSL_AUTHORITY_INFO_ACCESS_free");
+    (void)sk;
+}
+#endif
+
+/* returns the node at index "idx", NULL if not found */
+WOLFSSL_STACK* wolfSSL_sk_get_node(WOLFSSL_STACK* sk, int idx)
+{
+    int i;
+    WOLFSSL_STACK* ret = NULL;
+    WOLFSSL_STACK* current;
+
+    current = sk;
+    for (i = 0; i <= idx && current != NULL; i++) {
+        if (i == idx) {
+            ret = current;
+            break;
+        }
+        current = current->next;
+    }
+    return ret;
+}
+
+/* returns NULL on fail and pointer to internal data on success */
+WOLFSSL_ACCESS_DESCRIPTION* wolfSSL_sk_ACCESS_DESCRIPTION_value(
+        WOLFSSL_STACK* sk, int idx)
+{
+    WOLFSSL_STACK* ret;
+
+    if (sk == NULL) {
+        return NULL;
+    }
+
+    ret = wolfSSL_sk_get_node(sk, idx);
+    if (ret != NULL) {
+        return ret->data.access;
+    }
+    return NULL;
+}
+
+/* Frees GENERAL_NAME objects.
+*/
+void wolfSSL_GENERAL_NAME_free(WOLFSSL_GENERAL_NAME* name)
+{
+    WOLFSSL_ENTER("wolfSSL_GENERAL_NAME_Free");
+    if(name != NULL) {
+        if (name->d.dNSName != NULL) {
+            wolfSSL_ASN1_STRING_free(name->d.dNSName);
+            name->d.dNSName = NULL;
+        }
+        if (name->d.uniformResourceIdentifier != NULL) {
+            wolfSSL_ASN1_STRING_free(name->d.uniformResourceIdentifier);
+            name->d.uniformResourceIdentifier = NULL;
+        }
+        if (name->d.iPAddress != NULL) {
+            wolfSSL_ASN1_STRING_free(name->d.iPAddress);
+            name->d.iPAddress = NULL;
+        }
+        if (name->d.registeredID != NULL) {
+            wolfSSL_ASN1_OBJECT_free(name->d.registeredID);
+            name->d.registeredID = NULL;
+        }
+        if (name->d.ia5 != NULL) {
+            wolfSSL_ASN1_STRING_free(name->d.ia5);
+            name->d.ia5 = NULL;
+        }
+        XFREE(name, NULL, DYNAMIC_TYPE_OPENSSL);
+    }
+}
+
+void wolfSSL_GENERAL_NAMES_free(WOLFSSL_GENERAL_NAMES *gens)
+{
+    WOLFSSL_STACK* node;
+
+    WOLFSSL_ENTER("wolfSSL_GENERAL_NAMES_free");
+
+    if (gens == NULL) {
+        return;
+    }
+
+    /* parse through stack freeing each node */
+    node = gens->next;
+    while (gens->num > 1) {
+        WOLFSSL_STACK* tmp = node;
+        node = node->next;
+
+        wolfSSL_ASN1_OBJECT_free(tmp->data.obj);
+        XFREE(tmp, NULL, DYNAMIC_TYPE_ASN1);
+        gens->num -= 1;
+    }
+
+    /* free head of stack */
+    if (gens->num == 1) {
+        wolfSSL_ASN1_OBJECT_free(gens->data.obj);
+    }
+    XFREE(gens, NULL, DYNAMIC_TYPE_ASN1);
+}
+
+#if defined(OPENSSL_ALL)
+WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* wolfSSL_sk_X509_EXTENSION_new_null(void)
+{
+    WOLFSSL_STACK* sk = wolfSSL_sk_new_node(NULL);
+    if (sk) {
+        sk->type = STACK_TYPE_X509_EXT;
+    }
+
+    return (WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)*)sk;;
+}
+
+/* returns the number of nodes on the stack */
+int wolfSSL_sk_X509_EXTENSION_num(WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk)
+{
+    if (sk != NULL) {
+        return (int)sk->num;
+    }
+    return WOLFSSL_FATAL_ERROR;
+}
+
+
+/* returns null on failure and pointer to internal value on success */
+WOLFSSL_X509_EXTENSION* wolfSSL_sk_X509_EXTENSION_value(
+        WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk, int idx)
+{
+    WOLFSSL_STACK* ret;
+
+    if (sk == NULL) {
+        return NULL;
+    }
+
+    ret = wolfSSL_sk_get_node(sk, idx);
+    if (ret != NULL) {
+        return ret->data.ext;
+    }
+    return NULL;
+}
+
+/* frees all of the nodes and the values in stack */
+void wolfSSL_sk_X509_EXTENSION_pop_free(
+        WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk,
+        void (*f) (WOLFSSL_X509_EXTENSION*))
+{
+    WOLFSSL_STACK* current;
+
+    if (sk == NULL) {
+        return;
+    }
+
+    current = sk;
+    while (current != NULL) {
+        WOLFSSL_STACK* toFree = current;
+        current = current->next;
+
+        if (f)
+            f(toFree->data.ext);
+        wolfSSL_sk_free_node(toFree);
+    }
+}
+
+#if defined(HAVE_ECC)
+/* Copies ecc_key into new WOLFSSL_EC_KEY object
+ *
+ * src  : EC_KEY to duplicate. If EC_KEY is not null, create new EC_KEY and copy
+ * internal ecc_key from src to dup.
+ *
+ * Returns pointer to duplicate EC_KEY.
+ */
+WOLFSSL_EC_KEY *wolfSSL_EC_KEY_dup(const WOLFSSL_EC_KEY *src)
+{
+    WOLFSSL_EC_KEY *dup;
+    ecc_key *key, *srcKey;
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_dup");
+
+    if (src == NULL || src->internal == NULL || src->group == NULL || \
+       src->pub_key == NULL || src->priv_key == NULL) {
+
+        WOLFSSL_MSG("src NULL error");
+        return NULL;
+    }
+
+    dup = wolfSSL_EC_KEY_new();
+    if (dup == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_new error");
+        return NULL;
+    }
+
+    key = (ecc_key*)dup->internal;
+    if (key == NULL) {
+        WOLFSSL_MSG("ecc_key NULL error");
+        wolfSSL_EC_KEY_free(dup);
+        return NULL;
+    }
+    srcKey = (ecc_key*)src->internal;
+
+    /* ecc_key */
+    /* copy pubkey */
+    ret = wc_ecc_copy_point(&srcKey->pubkey, &key->pubkey);
+    if (ret != MP_OKAY) {
+        WOLFSSL_MSG("wc_ecc_copy_point error");
+        wolfSSL_EC_KEY_free(dup);
+        return NULL;
+    }
+
+    /* copy private key k */
+    ret = mp_copy(&srcKey->k, &key->k);
+    if (ret != MP_OKAY) {
+        WOLFSSL_MSG("mp_copy error");
+        wolfSSL_EC_KEY_free(dup);
+        return NULL;
+    }
+
+    /* copy domain parameters */
+    if (srcKey->dp) {
+        ret = wc_ecc_set_curve(key, 0, srcKey->dp->id);
+        if (ret != 0) {
+            WOLFSSL_MSG("wc_ecc_set_curve error");
+            return NULL;
+        }
+    }
+
+    key->type  = srcKey->type;
+    key->idx   = srcKey->idx;
+    key->state = srcKey->state;
+    key->flags = srcKey->flags;
+
+    /* Copy group */
+    if (dup->group == NULL) {
+        WOLFSSL_MSG("EC_GROUP_new_by_curve_name error");
+        wolfSSL_EC_KEY_free(dup);
+        return NULL;
+    }
+
+    dup->group->curve_idx = src->group->curve_idx;
+    dup->group->curve_nid = src->group->curve_nid;
+    dup->group->curve_oid = src->group->curve_oid;
+
+    /* Copy public key */
+    if (src->pub_key->internal == NULL || dup->pub_key->internal == NULL) {
+        WOLFSSL_MSG("NULL pub_key error");
+        wolfSSL_EC_KEY_free(dup);
+        return NULL;
+    }
+
+    /* Copy public key internal */
+    ret = wc_ecc_copy_point((ecc_point*)src->pub_key->internal, \
+                            (ecc_point*)dup->pub_key->internal);
+    if (ret != MP_OKAY) {
+        WOLFSSL_MSG("ecc_copy_point error");
+        wolfSSL_EC_KEY_free(dup);
+        return NULL;
+    }
+
+    /* Copy X, Y, Z */
+    dup->pub_key->X = wolfSSL_BN_dup(src->pub_key->X);
+    if (!dup->pub_key->X && src->pub_key->X) {
+        WOLFSSL_MSG("Error copying EC_POINT");
+        wolfSSL_EC_KEY_free(dup);
+        return NULL;
+    }
+    dup->pub_key->Y = wolfSSL_BN_dup(src->pub_key->Y);
+    if (!dup->pub_key->Y && src->pub_key->Y) {
+        WOLFSSL_MSG("Error copying EC_POINT");
+        wolfSSL_EC_KEY_free(dup);
+        return NULL;
+    }
+    dup->pub_key->Z = wolfSSL_BN_dup(src->pub_key->Z);
+    if (!dup->pub_key->Z && src->pub_key->Z) {
+        WOLFSSL_MSG("Error copying EC_POINT");
+        wolfSSL_EC_KEY_free(dup);
+        return NULL;
+    }
+
+    dup->pub_key->inSet = src->pub_key->inSet;
+    dup->pub_key->exSet = src->pub_key->exSet;
+
+    /* Copy private key */
+    if (src->priv_key->internal == NULL || dup->priv_key->internal == NULL) {
+        WOLFSSL_MSG("NULL priv_key error");
+        wolfSSL_EC_KEY_free(dup);
+        return NULL;
+    }
+
+    /* Free priv_key before call to dup function */
+    wolfSSL_BN_free(dup->priv_key);
+    dup->priv_key = wolfSSL_BN_dup(src->priv_key);
+    if (dup->priv_key == NULL) {
+        WOLFSSL_MSG("BN_dup error");
+        wolfSSL_EC_KEY_free(dup);
+        return NULL;
+    }
+
+    return dup;
+
+}
+#endif /* HAVE_ECC */
+
+#if !defined(NO_DH)
+int wolfSSL_DH_check(const WOLFSSL_DH *dh, int *codes)
+{
+    int isPrime = MP_NO, codeTmp = 0;
+    WC_RNG rng;
+
+    WOLFSSL_ENTER("wolfSSL_DH_check");
+    if (dh == NULL){
+        return WOLFSSL_FAILURE;
+    }
+
+    if (dh->g == NULL || dh->g->internal == NULL){
+        codeTmp = DH_NOT_SUITABLE_GENERATOR;
+    }
+
+    if (dh->p == NULL || dh->p->internal == NULL){
+        codeTmp = DH_CHECK_P_NOT_PRIME;
+    }
+    else
+    {
+        /* test if dh->p has prime */
+        if (wc_InitRng(&rng) == 0){
+            mp_prime_is_prime_ex((mp_int*)dh->p->internal,8,&isPrime,&rng);
+        }
+        else {
+            WOLFSSL_MSG("Error initializing rng\n");
+            return WOLFSSL_FAILURE;
+        }
+        wc_FreeRng(&rng);
+        if (isPrime != MP_YES){
+            codeTmp = DH_CHECK_P_NOT_PRIME;
+        }
+    }
+    /* User may choose to enter NULL for codes if they don't want to check it*/
+    if (codes != NULL){
+        *codes = codeTmp;
+    }
+
+    /* if codeTmp was set,some check was flagged invalid */
+    if (codeTmp){
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* Converts DER encoded DH parameters to a WOLFSSL_DH structure.
+ *
+ * dh   : structure to copy DH parameters into.
+ * pp   : DER encoded DH parameters
+ * length   : length to copy
+ *
+ * Returns pointer to WOLFSSL_DH structure on success, or NULL on failure
+ */
+WOLFSSL_DH *wolfSSL_d2i_DHparams(WOLFSSL_DH **dh, const unsigned char **pp,
+                                                                    long length)
+{
+    WOLFSSL_DH *newDH = NULL;
+    int ret;
+    word32 idx = 0;
+
+    WOLFSSL_ENTER("wolfSSL_d2i_DHparams");
+
+    if (pp == NULL || length <= 0) {
+        WOLFSSL_MSG("bad argument");
+        return NULL;
+    }
+
+    if ((newDH = wolfSSL_DH_new()) == NULL) {
+        WOLFSSL_MSG("wolfSSL_DH_new() failed");
+        return NULL;
+    }
+
+    ret = wc_DhKeyDecode(*pp, &idx, (DhKey*)newDH->internal, (word32)length);
+    if (ret != 0) {
+        WOLFSSL_MSG("DhKeyDecode() failed");
+        wolfSSL_DH_free(newDH);
+        return NULL;
+    }
+    newDH->inSet = 1;
+
+    if (SetDhExternal(newDH) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("SetDhExternal failed");
+        wolfSSL_DH_free(newDH);
+        return NULL;
+    }
+
+    *pp += length;
+    if (dh != NULL){
+        *dh = newDH;
+    }
+
+    return newDH;
+}
+
+/* Converts internal WOLFSSL_DH structure to DER encoded DH.
+ *
+ * dh   : structure to copy DH parameters from.
+ * out  : DER buffer for DH parameters
+ *
+ * Returns size of DER on success and WOLFSSL_FAILURE if error
+ */
+int wolfSSL_i2d_DHparams(const WOLFSSL_DH *dh, unsigned char **out)
+{
+    word32 len;
+    int ret = 0;
+
+    WOLFSSL_ENTER("wolfSSL_i2d_DHparams");
+
+    if (dh == NULL) {
+        WOLFSSL_MSG("Bad parameters");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* Get total length */
+    len = 2 + mp_leading_bit((mp_int*)dh->p->internal) +
+              mp_unsigned_bin_size((mp_int*)dh->p->internal) +
+          2 + mp_leading_bit((mp_int*)dh->g->internal) +
+              mp_unsigned_bin_size((mp_int*)dh->g->internal);
+
+    /* Two bytes required for length if ASN.1 SEQ data greater than 127 bytes
+     * and less than 256 bytes.
+     */
+    len = ((len > 127) ? 2 : 1) + len;
+
+    if (out != NULL && *out != NULL) {
+        ret = StoreDHparams(*out, &len, (mp_int*)dh->p->internal,
+                                        (mp_int*)dh->g->internal);
+        if (ret != MP_OKAY) {
+            WOLFSSL_MSG("StoreDHparams error");
+            len = 0;
+        }
+        else{
+            *out += len;
+        }
+    }
+    return (int)len;
+}
+#endif /* !NO_DH */
+
+#endif /* OPENSSL_ALL */
+
+#endif /* OPENSSL_EXTRA */
+
+#ifndef NO_FILESYSTEM
+
+#ifndef NO_STDIO_FILESYSTEM
+
+WOLFSSL_X509* wolfSSL_X509_d2i_fp(WOLFSSL_X509** x509, XFILE file)
+{
+    WOLFSSL_X509* newX509 = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_X509_d2i_fp");
+
+    if (file != XBADFILE) {
+        byte* fileBuffer = NULL;
+        long sz = 0;
+
+        if (XFSEEK(file, 0, XSEEK_END) != 0)
+            return NULL;
+        sz = XFTELL(file);
+        XREWIND(file);
+
+        if (sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) {
+            WOLFSSL_MSG("X509_d2i file size error");
+            return NULL;
+        }
+
+        fileBuffer = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE);
+        if (fileBuffer != NULL) {
+            int ret = (int)XFREAD(fileBuffer, 1, sz, file);
+            if (ret == sz) {
+                newX509 = wolfSSL_X509_d2i(NULL, fileBuffer, (int)sz);
+            }
+            XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE);
+        }
+    }
+
+    if (x509 != NULL)
+        *x509 = newX509;
+
+    return newX509;
+}
+
+#endif /* NO_STDIO_FILESYSTEM */
+
+WOLFSSL_ABI
+WOLFSSL_X509* wolfSSL_X509_load_certificate_file(const char* fname, int format)
+{
+#ifdef WOLFSSL_SMALL_STACK
+    byte  staticBuffer[1]; /* force heap usage */
+#else
+    byte  staticBuffer[FILE_BUFFER_SIZE];
+#endif
+    byte* fileBuffer = staticBuffer;
+    int   dynamic = 0;
+    int   ret;
+    long  sz = 0;
+    XFILE file;
+
+    WOLFSSL_X509* x509 = NULL;
+
+    /* Check the inputs */
+    if ((fname == NULL) ||
+        (format != WOLFSSL_FILETYPE_ASN1 && format != WOLFSSL_FILETYPE_PEM))
+        return NULL;
+
+    file = XFOPEN(fname, "rb");
+    if (file == XBADFILE)
+        return NULL;
+
+    if (XFSEEK(file, 0, XSEEK_END) != 0){
+        XFCLOSE(file);
+        return NULL;
+    }
+    sz = XFTELL(file);
+    XREWIND(file);
+
+    if (sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) {
+        WOLFSSL_MSG("X509_load_certificate_file size error");
+        XFCLOSE(file);
+        return NULL;
+    }
+
+    if (sz > (long)sizeof(staticBuffer)) {
+        fileBuffer = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE);
+        if (fileBuffer == NULL) {
+            XFCLOSE(file);
+            return NULL;
+        }
+        dynamic = 1;
+    }
+
+    ret = (int)XFREAD(fileBuffer, 1, sz, file);
+    if (ret != sz) {
+        XFCLOSE(file);
+        if (dynamic)
+            XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE);
+        return NULL;
+    }
+
+    XFCLOSE(file);
+
+    x509 = wolfSSL_X509_load_certificate_buffer(fileBuffer, (int)sz, format);
+
+    if (dynamic)
+        XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE);
+
+    return x509;
+}
+
+#endif /* NO_FILESYSTEM */
+
+
+WOLFSSL_X509* wolfSSL_X509_load_certificate_buffer(
+    const unsigned char* buf, int sz, int format)
+{
+    int ret;
+    WOLFSSL_X509* x509 = NULL;
+    DerBuffer* der = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_X509_load_certificate_ex");
+
+    if (format == WOLFSSL_FILETYPE_PEM) {
+    #ifdef WOLFSSL_PEM_TO_DER
+        if (PemToDer(buf, sz, CERT_TYPE, &der, NULL, NULL, NULL) != 0) {
+            FreeDer(&der);
+        }
+    #else
+        ret = NOT_COMPILED_IN;
+    #endif
+    }
+    else {
+        ret = AllocDer(&der, (word32)sz, CERT_TYPE, NULL);
+        if (ret == 0) {
+            XMEMCPY(der->buffer, buf, sz);
+        }
+    }
+
+    /* At this point we want `der` to have the certificate in DER format */
+    /* ready to be decoded. */
+    if (der != NULL && der->buffer != NULL) {
+    #ifdef WOLFSSL_SMALL_STACK
+        DecodedCert* cert;
+    #else
+        DecodedCert  cert[1];
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
+                                     DYNAMIC_TYPE_DCERT);
+        if (cert != NULL)
+    #endif
+        {
+            InitDecodedCert(cert, der->buffer, der->length, NULL);
+            if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0) {
+                x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL,
+                                                             DYNAMIC_TYPE_X509);
+                if (x509 != NULL) {
+                    InitX509(x509, 1, NULL);
+                    if (CopyDecodedToX509(x509, cert) != 0) {
+                        wolfSSL_X509_free(x509);
+                        x509 = NULL;
+                    }
+                }
+            }
+
+            FreeDecodedCert(cert);
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
+        #endif
+        }
+
+        FreeDer(&der);
+    }
+
+    return x509;
+}
+
+#endif /* KEEP_PEER_CERT || SESSION_CERTS */
+
+/* OPENSSL_EXTRA is needed for wolfSSL_X509_d21 function
+   KEEP_OUR_CERT is to insure ability for returning ssl certificate */
+#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+    defined(KEEP_OUR_CERT)
+WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl)
+{
+    if (ssl == NULL) {
+        return NULL;
+    }
+
+    if (ssl->buffers.weOwnCert) {
+        if (ssl->ourCert == NULL) {
+            if (ssl->buffers.certificate == NULL) {
+                WOLFSSL_MSG("Certificate buffer not set!");
+                return NULL;
+            }
+            #ifndef WOLFSSL_X509_STORE_CERTS
+            ssl->ourCert = wolfSSL_X509_d2i(NULL,
+                                              ssl->buffers.certificate->buffer,
+                                              ssl->buffers.certificate->length);
+            #endif
+        }
+        return ssl->ourCert;
+    }
+    else { /* if cert not owned get parent ctx cert or return null */
+        if (ssl->ctx) {
+            if (ssl->ctx->ourCert == NULL) {
+                if (ssl->ctx->certificate == NULL) {
+                    WOLFSSL_MSG("Ctx Certificate buffer not set!");
+                    return NULL;
+                }
+                #ifndef WOLFSSL_X509_STORE_CERTS
+                ssl->ctx->ourCert = wolfSSL_X509_d2i(NULL,
+                                               ssl->ctx->certificate->buffer,
+                                               ssl->ctx->certificate->length);
+                #endif
+                ssl->ctx->ownOurCert = 1;
+            }
+            return ssl->ctx->ourCert;
+        }
+    }
+
+    return NULL;
+}
+#endif /* OPENSSL_EXTRA && KEEP_OUR_CERT */
+#endif /* NO_CERTS */
+
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+#ifndef NO_ASN
+void wolfSSL_ASN1_OBJECT_free(WOLFSSL_ASN1_OBJECT* obj)
+{
+    if (obj == NULL) {
+        return;
+    }
+    if ((obj->obj != NULL) && ((obj->dynamic & WOLFSSL_ASN1_DYNAMIC_DATA) != 0)) {
+        WOLFSSL_MSG("Freeing ASN1 data");
+        XFREE((void*)obj->obj, obj->heap, DYNAMIC_TYPE_ASN1);
+        obj->obj = NULL;
+    }
+    #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+    if (obj->pathlen != NULL) {
+        wolfSSL_ASN1_INTEGER_free(obj->pathlen);
+        obj->pathlen = NULL;
+    }
+    #endif
+    if ((obj->dynamic & WOLFSSL_ASN1_DYNAMIC) != 0) {
+        WOLFSSL_MSG("Freeing ASN1 OBJECT");
+        XFREE(obj, NULL, DYNAMIC_TYPE_ASN1);
+    }
+}
+#endif /* NO_ASN */
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+
+#ifdef OPENSSL_EXTRA
+#ifndef NO_ASN
+WOLFSSL_ASN1_OBJECT* wolfSSL_ASN1_OBJECT_new(void)
+{
+    WOLFSSL_ASN1_OBJECT* obj;
+
+    obj = (WOLFSSL_ASN1_OBJECT*)XMALLOC(sizeof(WOLFSSL_ASN1_OBJECT), NULL,
+                                        DYNAMIC_TYPE_ASN1);
+    if (obj == NULL) {
+        return NULL;
+    }
+
+    XMEMSET(obj, 0, sizeof(WOLFSSL_ASN1_OBJECT));
+    obj->d.ia5 = &(obj->d.ia5_internal);
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+    obj->d.iPAddress = &(obj->d.iPAddress_internal);
+#endif
+    obj->dynamic |= WOLFSSL_ASN1_DYNAMIC;
+    return obj;
+}
+
+/* Creates and returns a new WOLFSSL_CIPHER stack. */
+WOLFSSL_STACK* wolfSSL_sk_new_asn1_obj(void)
+{
+    WOLFSSL_STACK* sk;
+    WOLFSSL_ENTER("wolfSSL_sk_new_asn1_obj");
+
+    sk = wolfSSL_sk_new_null();
+    if (sk == NULL)
+        return NULL;
+    sk->type = STACK_TYPE_OBJ;
+
+    return sk;
+}
+
+/* return 1 on success 0 on fail */
+int wolfSSL_sk_ASN1_OBJECT_push(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk,
+                                              WOLFSSL_ASN1_OBJECT* obj)
+{
+    WOLFSSL_STACK* node;
+
+    WOLFSSL_ENTER("wolfSSL_sk_ASN1_OBJECT_push");
+
+    if (sk == NULL || obj == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* no previous values in stack */
+    if (sk->data.obj == NULL) {
+        sk->data.obj = obj;
+        sk->num += 1;
+        return WOLFSSL_SUCCESS;
+    }
+
+    /* stack already has value(s) create a new node and add more */
+    node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+                                                             DYNAMIC_TYPE_ASN1);
+    if (node == NULL) {
+        WOLFSSL_MSG("Memory error");
+        return WOLFSSL_FAILURE;
+    }
+    XMEMSET(node, 0, sizeof(WOLFSSL_STACK));
+
+    /* push new obj onto head of stack */
+    node->data.obj  = sk->data.obj;
+    node->next      = sk->next;
+    node->type      = sk->type;
+    sk->next        = node;
+    sk->data.obj    = obj;
+    sk->num        += 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+WOLFSSL_ASN1_OBJECT* wolfSSL_sk_ASN1_OBJECT_pop(
+                                        WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk)
+{
+    WOLFSSL_STACK* node;
+    WOLFSSL_ASN1_OBJECT* obj;
+
+    if (sk == NULL) {
+        return NULL;
+    }
+
+    node = sk->next;
+    obj = sk->data.obj;
+
+    if (node != NULL) { /* update sk and remove node from stack */
+        sk->data.obj = node->data.obj;
+        sk->next = node->next;
+        XFREE(node, NULL, DYNAMIC_TYPE_ASN1);
+    }
+    else { /* last obj in stack */
+        sk->data.obj = NULL;
+    }
+
+    if (sk->num > 0) {
+        sk->num -= 1;
+    }
+
+    return obj;
+}
+
+
+/* Free the structure for ASN1_OBJECT stack
+ *
+ * sk  stack to free nodes in
+ */
+void wolfSSL_sk_ASN1_OBJECT_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk)
+{
+    wolfSSL_sk_ASN1_OBJECT_pop_free(sk, NULL);
+}
+
+/* Free's all nodes in ASN1_OBJECT stack.
+ * This is different then wolfSSL_ASN1_OBJECT_free in that it allows for
+ * choosing the function to use when freeing an ASN1_OBJECT stack.
+ *
+ * sk  stack to free nodes in
+ * f   X509 free function
+ */
+void wolfSSL_sk_ASN1_OBJECT_pop_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk,
+                                     void (*f) (WOLFSSL_ASN1_OBJECT*))
+{
+    WOLFSSL_STACK* node;
+
+    WOLFSSL_ENTER("wolfSSL_sk_ASN1_OBJECT_pop_free");
+
+    if (sk == NULL) {
+        WOLFSSL_MSG("Parameter error");
+        return;
+    }
+
+    /* parse through stack freeing each node */
+    node = sk->next;
+    while (node && sk->num > 1) {
+        WOLFSSL_STACK* tmp = node;
+        node = node->next;
+
+        if (f)
+            f(tmp->data.obj);
+        else
+            wolfSSL_ASN1_OBJECT_free(tmp->data.obj);
+        tmp->data.obj = NULL;
+        XFREE(tmp, NULL, DYNAMIC_TYPE_ASN1);
+        sk->num -= 1;
+    }
+
+    /* free head of stack */
+    if (sk->num == 1) {
+        if (f)
+            f(sk->data.obj);
+        else
+            wolfSSL_ASN1_OBJECT_free(sk->data.obj);
+        sk->data.obj = NULL;
+    }
+    XFREE(sk, NULL, DYNAMIC_TYPE_ASN1);
+}
+
+int wolfSSL_ASN1_STRING_to_UTF8(unsigned char **out, WOLFSSL_ASN1_STRING *in)
+{
+    /*
+       ASN1_STRING_to_UTF8() converts the string in to UTF8 format,
+       the converted data is allocated in a buffer in *out.
+       The length of out is returned or a negative error code.
+       The buffer *out should be free using OPENSSL_free().
+       */
+    unsigned char* buf;
+    unsigned char* inPtr;
+    int inLen;
+
+    if (!out || !in) {
+        return -1;
+    }
+
+    inPtr = wolfSSL_ASN1_STRING_data(in);
+    inLen = wolfSSL_ASN1_STRING_length(in);
+    if (!inPtr || inLen < 0) {
+        return -1;
+    }
+    buf = (unsigned char*)XMALLOC(inLen + 1, NULL, DYNAMIC_TYPE_OPENSSL);
+    if (!buf) {
+        return -1;
+    }
+    XMEMCPY(buf, inPtr, inLen + 1);
+    *out = buf;
+    return inLen;
+}
+
+/* Returns string representation of ASN1_STRING */
+char* wolfSSL_i2s_ASN1_STRING(WOLFSSL_v3_ext_method *method,
+    const WOLFSSL_ASN1_STRING *s)
+{
+    int i;
+    int tmpSz = 100;
+    int valSz = 5;
+    char* tmp;
+    char val[5];
+    unsigned char* str;
+
+    WOLFSSL_ENTER("wolfSSL_i2s_ASN1_STRING");
+    (void)method;
+
+    if(s == NULL || s->data == NULL) {
+        WOLFSSL_MSG("Bad Function Argument");
+        return NULL;
+    }
+    str = (unsigned char*)XMALLOC(s->length, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (str == NULL) {
+        WOLFSSL_MSG("Memory Error");
+        return NULL;
+    }
+    XMEMCPY(str, (unsigned char*)s->data, s->length);
+
+    tmp = (char*)XMALLOC(tmpSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (tmp == NULL) {
+        WOLFSSL_MSG("Memory Error");
+        XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return NULL;
+    }
+    XMEMSET(tmp, 0, tmpSz);
+
+    for (i = 0; i < tmpSz && i < (s->length - 1); i++) {
+        XSNPRINTF(val, valSz - 1, "%02X:", str[i]);
+        XSTRNCAT(tmp, val, valSz);
+    }
+    XSNPRINTF(val, valSz - 1, "%02X", str[i]);
+    XSTRNCAT(tmp, val, valSz);
+    XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+    return tmp;
+}
+#endif /* NO_ASN */
+
+void wolfSSL_set_connect_state(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_set_connect_state");
+    if (ssl == NULL) {
+        WOLFSSL_MSG("WOLFSSL struct pointer passed in was null");
+        return;
+    }
+
+    #ifndef NO_DH
+    /* client creates its own DH parameters on handshake */
+    if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) {
+        XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap,
+            DYNAMIC_TYPE_PUBLIC_KEY);
+    }
+    ssl->buffers.serverDH_P.buffer = NULL;
+    if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) {
+        XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap,
+            DYNAMIC_TYPE_PUBLIC_KEY);
+    }
+    ssl->buffers.serverDH_G.buffer = NULL;
+    #endif
+
+    if (InitSSL_Side(ssl, WOLFSSL_CLIENT_END) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("Error initializing client side");
+    }
+}
+#endif /* OPENSSL_EXTRA */
+
+
+int wolfSSL_get_shutdown(const WOLFSSL* ssl)
+{
+    int isShutdown = 0;
+
+    WOLFSSL_ENTER("wolfSSL_get_shutdown");
+
+    if (ssl) {
+        /* in OpenSSL, WOLFSSL_SENT_SHUTDOWN = 1, when closeNotifySent   *
+         * WOLFSSL_RECEIVED_SHUTDOWN = 2, from close notify or fatal err */
+        isShutdown = ((ssl->options.closeNotify||ssl->options.connReset) << 1)
+                    | (ssl->options.sentNotify);
+    }
+    return isShutdown;
+}
+
+
+int wolfSSL_session_reused(WOLFSSL* ssl)
+{
+    int resuming = 0;
+    if (ssl)
+        resuming = ssl->options.resuming;
+    return resuming;
+}
+
+#if defined(OPENSSL_EXTRA) || defined(HAVE_EXT_CACHE)
+WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session)
+{
+#ifdef HAVE_EXT_CACHE
+    WOLFSSL_SESSION* copy;
+
+    WOLFSSL_ENTER("wolfSSL_SESSION_dup");
+
+    if (session == NULL)
+        return NULL;
+#ifdef HAVE_SESSION_TICKET
+    if (session->isDynamic && !session->ticket) {
+        WOLFSSL_MSG("Session dynamic flag is set but ticket pointer is null");
+        return NULL;
+    }
+#endif
+
+    copy = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), NULL,
+            DYNAMIC_TYPE_OPENSSL);
+    if (copy != NULL) {
+        XMEMCPY(copy, session, sizeof(WOLFSSL_SESSION));
+        copy->isAlloced = 1;
+#ifdef HAVE_SESSION_TICKET
+        if (session->isDynamic) {
+            copy->ticket = (byte*)XMALLOC(session->ticketLen, NULL,
+                                                    DYNAMIC_TYPE_SESSION_TICK);
+            XMEMCPY(copy->ticket, session->ticket, session->ticketLen);
+        } else {
+            copy->ticket = copy->staticTicket;
+        }
+#endif
+#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
+        copy->peer = wolfSSL_X509_dup(session->peer);
+#endif
+    }
+    return copy;
+#else
+    WOLFSSL_MSG("wolfSSL_SESSION_dup was called "
+                "but HAVE_EXT_CACHE is not defined");
+    (void)session;
+    return NULL;
+#endif /* HAVE_EXT_CACHE */
+}
+
+void wolfSSL_SESSION_free(WOLFSSL_SESSION* session)
+{
+    if (session == NULL)
+        return;
+
+#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
+    if (session->peer) {
+        wolfSSL_X509_free(session->peer);
+    }
+#endif
+
+#ifdef HAVE_EXT_CACHE
+    if (session->isAlloced) {
+    #ifdef HAVE_SESSION_TICKET
+        if (session->isDynamic)
+            XFREE(session->ticket, NULL, DYNAMIC_TYPE_SESSION_TICK);
+    #endif
+        XFREE(session, NULL, DYNAMIC_TYPE_OPENSSL);
+    }
+#else
+    /* No need to free since cache is static */
+    (void)session;
+#endif
+}
+#endif
+
+
+/* helper function that takes in a protocol version struct and returns string */
+static const char* wolfSSL_internal_get_version(ProtocolVersion* version)
+{
+    WOLFSSL_ENTER("wolfSSL_get_version");
+
+    if (version == NULL) {
+        return "Bad arg";
+    }
+
+    if (version->major == SSLv3_MAJOR) {
+        switch (version->minor) {
+        #ifndef NO_OLD_TLS
+            #ifdef WOLFSSL_ALLOW_SSLV3
+            case SSLv3_MINOR :
+                return "SSLv3";
+            #endif
+            #ifdef WOLFSSL_ALLOW_TLSV10
+            case TLSv1_MINOR :
+                return "TLSv1";
+            #endif
+            case TLSv1_1_MINOR :
+                return "TLSv1.1";
+        #endif
+            case TLSv1_2_MINOR :
+                return "TLSv1.2";
+        #ifdef WOLFSSL_TLS13
+            case TLSv1_3_MINOR :
+            #ifdef WOLFSSL_TLS13_DRAFT
+                #ifdef WOLFSSL_TLS13_DRAFT_18
+                    return "TLSv1.3 (Draft 18)";
+                #elif defined(WOLFSSL_TLS13_DRAFT_22)
+                    return "TLSv1.3 (Draft 22)";
+                #elif defined(WOLFSSL_TLS13_DRAFT_23)
+                    return "TLSv1.3 (Draft 23)";
+                #elif defined(WOLFSSL_TLS13_DRAFT_26)
+                    return "TLSv1.3 (Draft 26)";
+                #else
+                    return "TLSv1.3 (Draft 28)";
+                #endif
+            #else
+                return "TLSv1.3";
+            #endif
+        #endif
+            default:
+                return "unknown";
+        }
+    }
+#ifdef WOLFSSL_DTLS
+    else if (version->major == DTLS_MAJOR) {
+        switch (version->minor) {
+            case DTLS_MINOR :
+                return "DTLS";
+            case DTLSv1_2_MINOR :
+                return "DTLSv1.2";
+            default:
+                return "unknown";
+        }
+    }
+#endif /* WOLFSSL_DTLS */
+    return "unknown";
+}
+
+
+const char* wolfSSL_get_version(WOLFSSL* ssl)
+{
+    if (ssl == NULL) {
+        WOLFSSL_MSG("Bad argument");
+        return "unknown";
+    }
+
+    return wolfSSL_internal_get_version(&ssl->version);
+}
+
+
+/* current library version */
+const char* wolfSSL_lib_version(void)
+{
+    return LIBWOLFSSL_VERSION_STRING;
+}
+
+
+/* current library version in hex */
+word32 wolfSSL_lib_version_hex(void)
+{
+    return LIBWOLFSSL_VERSION_HEX;
+}
+
+
+int wolfSSL_get_current_cipher_suite(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("SSL_get_current_cipher_suite");
+    if (ssl)
+        return (ssl->options.cipherSuite0 << 8) | ssl->options.cipherSuite;
+    return 0;
+}
+
+WOLFSSL_CIPHER* wolfSSL_get_current_cipher(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("SSL_get_current_cipher");
+    if (ssl) {
+        ssl->cipher.cipherSuite0 = ssl->options.cipherSuite0;
+        ssl->cipher.cipherSuite  = ssl->options.cipherSuite;
+        return &ssl->cipher;
+    }
+    else
+        return NULL;
+}
+
+
+const char* wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher)
+{
+    WOLFSSL_ENTER("wolfSSL_CIPHER_get_name");
+
+    if (cipher == NULL) {
+        return NULL;
+    }
+
+    #if !defined(WOLFSSL_CIPHER_INTERNALNAME) && !defined(NO_ERROR_STRINGS) && \
+        !defined(WOLFSSL_QT)
+        return GetCipherNameIana(cipher->cipherSuite0, cipher->cipherSuite);
+    #else
+        return wolfSSL_get_cipher_name_from_suite(cipher->cipherSuite0,
+                cipher->cipherSuite);
+    #endif
+}
+
+const char*  wolfSSL_CIPHER_get_version(const WOLFSSL_CIPHER* cipher)
+{
+    WOLFSSL_ENTER("SSL_CIPHER_get_version");
+
+    if (cipher == NULL || cipher->ssl == NULL) {
+        return NULL;
+    }
+
+    return wolfSSL_get_version(cipher->ssl);
+}
+
+const char* wolfSSL_SESSION_CIPHER_get_name(WOLFSSL_SESSION* session)
+{
+    if (session == NULL) {
+        return NULL;
+    }
+
+#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \
+                        (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET))
+    #if !defined(WOLFSSL_CIPHER_INTERNALNAME) && !defined(NO_ERROR_STRINGS)
+        return GetCipherNameIana(session->cipherSuite0, session->cipherSuite);
+    #else
+        return GetCipherNameInternal(session->cipherSuite0, session->cipherSuite);
+    #endif
+#else
+    return NULL;
+#endif
+}
+
+const char* wolfSSL_get_cipher(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_get_cipher");
+    return wolfSSL_CIPHER_get_name(wolfSSL_get_current_cipher(ssl));
+}
+
+/* gets cipher name in the format DHE-RSA-... rather then TLS_DHE... */
+const char* wolfSSL_get_cipher_name(WOLFSSL* ssl)
+{
+    /* get access to cipher_name_idx in internal.c */
+    return wolfSSL_get_cipher_name_internal(ssl);
+}
+
+const char* wolfSSL_get_cipher_name_from_suite(const byte cipherSuite0,
+    const byte cipherSuite)
+{
+    return GetCipherNameInternal(cipherSuite0, cipherSuite);
+}
+
+const char* wolfSSL_get_cipher_name_iana_from_suite(const byte cipherSuite0,
+        const byte cipherSuite)
+{
+    return GetCipherNameIana(cipherSuite0, cipherSuite);
+}
+
+
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+/* Creates and returns a new WOLFSSL_CIPHER stack. */
+WOLFSSL_STACK* wolfSSL_sk_new_cipher(void)
+{
+    WOLFSSL_STACK* sk;
+    WOLFSSL_ENTER("wolfSSL_sk_new_cipher");
+
+    sk = wolfSSL_sk_new_null();
+    if (sk == NULL)
+        return NULL;
+    sk->type = STACK_TYPE_CIPHER;
+
+    return sk;
+}
+
+#ifndef NO_WOLFSSL_STUB
+/* Keep as stubs for now */
+/* return 1 on success 0 on fail */
+int wolfSSL_sk_CIPHER_push(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk,
+                                                      WOLFSSL_CIPHER* cipher)
+{
+    WOLFSSL_STUB("wolfSSL_sk_CIPHER_push");
+    (void)sk;
+    (void)cipher;
+    return 0;
+}
+
+
+WOLFSSL_CIPHER* wolfSSL_sk_CIPHER_pop(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk)
+{
+    WOLFSSL_STUB("wolfSSL_sk_CIPHER_pop");
+    (void)sk;
+    return NULL;
+}
+#endif /* NO_WOLFSSL_STUB */
+#endif /* WOLFSSL_QT || OPENSSL_ALL */
+
+word32 wolfSSL_CIPHER_get_id(const WOLFSSL_CIPHER* cipher)
+{
+    word16 cipher_id = 0;
+
+    WOLFSSL_ENTER("SSL_CIPHER_get_id");
+
+    if (cipher && cipher->ssl) {
+        cipher_id = (cipher->ssl->options.cipherSuite0 << 8) |
+                     cipher->ssl->options.cipherSuite;
+    }
+
+    return cipher_id;
+}
+
+const WOLFSSL_CIPHER* wolfSSL_get_cipher_by_value(word16 value)
+{
+    const WOLFSSL_CIPHER* cipher = NULL;
+    byte cipherSuite0, cipherSuite;
+    WOLFSSL_ENTER("SSL_get_cipher_by_value");
+
+    /* extract cipher id information */
+    cipherSuite =   (value       & 0xFF);
+    cipherSuite0 = ((value >> 8) & 0xFF);
+
+    /* TODO: lookup by cipherSuite0 / cipherSuite */
+    (void)cipherSuite0;
+    (void)cipherSuite;
+
+    return cipher;
+}
+
+
+#if defined(OPENSSL_ALL)
+/* Free the structure for WOLFSSL_CIPHER stack
+ *
+ * sk  stack to free nodes in
+ */
+void wolfSSL_sk_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk)
+{
+    WOLFSSL_STACK* node;
+    WOLFSSL_STACK* tmp;
+    WOLFSSL_ENTER("wolfSSL_sk_CIPHER_free");
+
+    if (sk == NULL)
+        return;
+
+    /* parse through stack freeing each node */
+    node = sk->next;
+    while (node) {
+        tmp  = node;
+        node = node->next;
+        XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL);
+    }
+
+    /* free head of stack */
+    XFREE(sk, NULL, DYNAMIC_TYPE_ASN1);
+}
+#endif
+
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) || \
+                                                                 !defined(NO_DH)
+#ifdef HAVE_FFDHE
+static const char* wolfssl_ffdhe_name(word16 group)
+{
+    const char* str = NULL;
+    switch (group) {
+        case WOLFSSL_FFDHE_2048:
+            str = "FFDHE_2048";
+            break;
+        case WOLFSSL_FFDHE_3072:
+            str = "FFDHE_3072";
+            break;
+        case WOLFSSL_FFDHE_4096:
+            str = "FFDHE_4096";
+            break;
+        case WOLFSSL_FFDHE_6144:
+            str = "FFDHE_6144";
+            break;
+        case WOLFSSL_FFDHE_8192:
+            str = "FFDHE_8192";
+            break;
+    }
+    return str;
+}
+#endif
+/* Return the name of the curve used for key exchange as a printable string.
+ *
+ * ssl  The SSL/TLS object.
+ * returns NULL if ECDH was not used, otherwise the name as a string.
+ */
+const char* wolfSSL_get_curve_name(WOLFSSL* ssl)
+{
+    const char* cName = NULL;
+
+    if (ssl == NULL)
+        return NULL;
+
+#ifdef HAVE_FFDHE
+    if (ssl->namedGroup != 0) {
+        cName = wolfssl_ffdhe_name(ssl->namedGroup);
+    }
+#endif
+
+#ifdef HAVE_CURVE25519
+    if (ssl->ecdhCurveOID == ECC_X25519_OID && cName == NULL) {
+        cName = "X25519";
+    }
+#endif
+
+#ifdef HAVE_CURVE448
+    if (ssl->ecdhCurveOID == ECC_X448_OID && cName == NULL) {
+        cName = "X448";
+    }
+#endif
+
+#ifdef HAVE_ECC
+    if (ssl->ecdhCurveOID != 0 && cName == NULL) {
+        cName = wc_ecc_get_name(wc_ecc_get_oid(ssl->ecdhCurveOID, NULL,
+                                NULL));
+    }
+#endif
+
+    return cName;
+}
+#endif
+
+
+#if defined(OPENSSL_EXTRA_X509_SMALL) || defined(KEEP_PEER_CERT) || \
+    defined(SESSION_CERTS)
+/* Smaller subset of X509 compatibility functions. Avoid increasing the size of
+ * this subset and its memory usage */
+
+#if !defined(NO_CERTS)
+/* returns a pointer to a new WOLFSSL_X509 structure on success and NULL on
+ * fail
+ */
+WOLFSSL_X509* wolfSSL_X509_new(void)
+{
+    WOLFSSL_X509* x509;
+
+    x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL,
+            DYNAMIC_TYPE_X509);
+    if (x509 != NULL) {
+        InitX509(x509, 1, NULL);
+    }
+
+    return x509;
+}
+
+WOLFSSL_ABI
+WOLFSSL_X509_NAME* wolfSSL_X509_get_subject_name(WOLFSSL_X509* cert)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_get_subject_name");
+    if (cert && cert->subject.sz != 0)
+        return &cert->subject;
+    return NULL;
+}
+
+#if defined(OPENSSL_EXTRA) && !defined(NO_SHA)
+/******************************************************************************
+* wolfSSL_X509_subject_name_hash - compute the hash digest of the raw subject name
+*
+* RETURNS:
+* The beginning of the hash digest. Otherwise, returns zero.
+* Note:
+* Returns a different hash value from OpenSSL's X509_subject_name_hash() API
+* depending on the subject name.
+*/
+unsigned long wolfSSL_X509_subject_name_hash(const WOLFSSL_X509* x509)
+{
+    word32 ret = 0;
+    int retHash;
+    WOLFSSL_X509_NAME *subjectName = NULL;
+
+#ifdef WOLFSSL_PIC32MZ_HASH
+        byte digest[PIC32_DIGEST_SIZE];
+#else
+        byte digest[WC_SHA_DIGEST_SIZE];
+#endif
+
+    if (x509 == NULL){
+        return WOLFSSL_FAILURE;
+    }
+
+    subjectName = wolfSSL_X509_get_subject_name((WOLFSSL_X509*)x509);
+
+    if (subjectName != NULL){
+        retHash = wc_ShaHash((const byte*)subjectName->name,
+                             (word32)subjectName->sz, digest);
+
+        if(retHash != 0){
+            WOLFSSL_MSG("Hash of X509 subjectName has failed");
+            return WOLFSSL_FAILURE;
+        }
+        ret = MakeWordFromHash(digest);
+    }
+
+    return (unsigned long)ret;
+}
+#endif
+
+WOLFSSL_ABI
+WOLFSSL_X509_NAME* wolfSSL_X509_get_issuer_name(WOLFSSL_X509* cert)
+{
+    WOLFSSL_ENTER("X509_get_issuer_name");
+    if (cert && cert->issuer.sz != 0)
+        return &cert->issuer;
+    return NULL;
+}
+
+
+int wolfSSL_X509_get_signature_type(WOLFSSL_X509* x509)
+{
+    int type = 0;
+
+    WOLFSSL_ENTER("wolfSSL_X509_get_signature_type");
+
+    if (x509 != NULL)
+        type = x509->sigOID;
+
+    return type;
+}
+
+#if defined(OPENSSL_EXTRA_X509_SMALL)
+
+/* Used to get a string from the WOLFSSL_X509_NAME structure that
+ * corresponds with the NID value passed in.
+ *
+ * name structure to get string from
+ * nid  NID value to search for
+ * buf  [out] buffer to hold results. If NULL then the buffer size minus the
+ *      null char is returned.
+ * len  size of "buf" passed in
+ *
+ * returns the length of string found, not including the NULL terminator.
+ *         It's possible the function could return a negative value in the
+ *         case that len is less than or equal to 0. A negative value is
+ *         considered an error case.
+ */
+int wolfSSL_X509_NAME_get_text_by_NID(WOLFSSL_X509_NAME* name,
+                                      int nid, char* buf, int len)
+{
+    char *text = NULL;
+    int textSz = 0;
+
+    WOLFSSL_ENTER("wolfSSL_X509_NAME_get_text_by_NID");
+
+    switch (nid) {
+        case ASN_COMMON_NAME:
+            text = name->fullName.fullName + name->fullName.cnIdx;
+            textSz = name->fullName.cnLen;
+            break;
+        case ASN_SUR_NAME:
+            text = name->fullName.fullName + name->fullName.snIdx;
+            textSz = name->fullName.snLen;
+            break;
+        case ASN_SERIAL_NUMBER:
+            text = name->fullName.fullName + name->fullName.serialIdx;
+            textSz = name->fullName.serialLen;
+            break;
+        case ASN_COUNTRY_NAME:
+            text = name->fullName.fullName + name->fullName.cIdx;
+            textSz = name->fullName.cLen;
+            break;
+        case ASN_LOCALITY_NAME:
+            text = name->fullName.fullName + name->fullName.lIdx;
+            textSz = name->fullName.lLen;
+            break;
+        case ASN_STATE_NAME:
+            text = name->fullName.fullName + name->fullName.stIdx;
+            textSz = name->fullName.stLen;
+            break;
+        case ASN_ORG_NAME:
+            text = name->fullName.fullName + name->fullName.oIdx;
+            textSz = name->fullName.oLen;
+            break;
+        case ASN_ORGUNIT_NAME:
+            text = name->fullName.fullName + name->fullName.ouIdx;
+            textSz = name->fullName.ouLen;
+            break;
+        case ASN_DOMAIN_COMPONENT:
+            text = name->fullName.fullName + name->fullName.dcIdx[0];
+            textSz = name->fullName.dcLen[0];
+            break;
+        case NID_emailAddress:
+            text = name->fullName.fullName + name->fullName.emailIdx;
+            textSz = name->fullName.emailLen;
+            break;
+    #ifdef WOLFSSL_CERT_EXT
+        case ASN_BUS_CAT:
+            text = name->fullName.fullName + name->fullName.bcIdx;
+            textSz = name->fullName.bcLen;
+            break;
+    #endif
+        default:
+            WOLFSSL_MSG("Entry type not found");
+            return WOLFSSL_FATAL_ERROR;
+    }
+
+    /* if buf is NULL return size of buffer needed (minus null char) */
+    if (buf == NULL) {
+        return textSz;
+    }
+
+    if (buf != NULL && text != NULL) {
+        textSz = min(textSz + 1, len); /* + 1 to account for null char */
+        if (textSz > 0) {
+            XMEMCPY(buf, text, textSz - 1);
+            buf[textSz - 1] = '\0';
+        }
+    }
+
+    WOLFSSL_LEAVE("wolfSSL_X509_NAME_get_text_by_NID", textSz);
+    return (textSz - 1); /* do not include null character in size */
+}
+
+/* Creates a new WOLFSSL_EVP_PKEY structure that has the public key from x509
+ *
+ * returns a pointer to the created WOLFSSL_EVP_PKEY on success and NULL on fail
+ */
+WOLFSSL_EVP_PKEY* wolfSSL_X509_get_pubkey(WOLFSSL_X509* x509)
+{
+    WOLFSSL_EVP_PKEY* key = NULL;
+    WOLFSSL_ENTER("X509_get_pubkey");
+    if (x509 != NULL) {
+        key = wolfSSL_EVP_PKEY_new_ex(x509->heap);
+        if (key != NULL) {
+            if (x509->pubKeyOID == RSAk) {
+                key->type = EVP_PKEY_RSA;
+            }
+            else if (x509->pubKeyOID == DSAk) {
+                key->type = EVP_PKEY_DSA;
+            }
+            else {
+                key->type = EVP_PKEY_EC;
+            }
+            key->save_type = 0;
+            key->pkey.ptr = (char*)XMALLOC(
+                        x509->pubKey.length, x509->heap,
+                                                       DYNAMIC_TYPE_PUBLIC_KEY);
+            if (key->pkey.ptr == NULL) {
+                wolfSSL_EVP_PKEY_free(key);
+                return NULL;
+            }
+            XMEMCPY(key->pkey.ptr, x509->pubKey.buffer, x509->pubKey.length);
+            key->pkey_sz = x509->pubKey.length;
+
+            #ifdef HAVE_ECC
+                key->pkey_curve = (int)x509->pkCurveOID;
+            #endif /* HAVE_ECC */
+
+            /* decode RSA key */
+            #ifndef NO_RSA
+            if (key->type == EVP_PKEY_RSA) {
+                key->ownRsa = 1;
+                key->rsa = wolfSSL_RSA_new();
+                if (key->rsa == NULL) {
+                    wolfSSL_EVP_PKEY_free(key);
+                    return NULL;
+                }
+
+                if (wolfSSL_RSA_LoadDer_ex(key->rsa,
+                            (const unsigned char*)key->pkey.ptr, key->pkey_sz,
+                            WOLFSSL_RSA_LOAD_PUBLIC) != SSL_SUCCESS) {
+                    wolfSSL_EVP_PKEY_free(key);
+                    return NULL;
+                }
+            }
+            #endif /* NO_RSA */
+
+            /* decode ECC key */
+            #if defined(HAVE_ECC) && defined(OPENSSL_EXTRA)
+            if (key->type == EVP_PKEY_EC) {
+                word32 idx = 0;
+
+                key->ownEcc = 1;
+                key->ecc = wolfSSL_EC_KEY_new();
+                if (key->ecc == NULL || key->ecc->internal == NULL) {
+                    wolfSSL_EVP_PKEY_free(key);
+                    return NULL;
+                }
+
+                /* not using wolfSSL_EC_KEY_LoadDer because public key in x509
+                 * is in the format of x963 (no sequence at start of buffer) */
+                if (wc_EccPublicKeyDecode((const unsigned char*)key->pkey.ptr,
+                        &idx, (ecc_key*)key->ecc->internal, key->pkey_sz) < 0) {
+                    WOLFSSL_MSG("wc_EccPublicKeyDecode failed");
+                    wolfSSL_EVP_PKEY_free(key);
+                    return NULL;
+                }
+
+                if (SetECKeyExternal(key->ecc) != SSL_SUCCESS) {
+                    WOLFSSL_MSG("SetECKeyExternal failed");
+                    wolfSSL_EVP_PKEY_free(key);
+                    return NULL;
+                }
+
+                key->ecc->inSet = 1;
+            }
+            #endif /* HAVE_ECC */
+
+            #ifndef NO_DSA
+            if (key->type == EVP_PKEY_DSA) {
+                key->ownDsa = 1;
+                key->dsa = wolfSSL_DSA_new();
+                if (key->dsa == NULL) {
+                    wolfSSL_EVP_PKEY_free(key);
+                    return NULL;
+                }
+
+                if (wolfSSL_DSA_LoadDer_ex(key->dsa,
+                            (const unsigned char*)key->pkey.ptr, key->pkey_sz, \
+                            WOLFSSL_DSA_LOAD_PUBLIC) != SSL_SUCCESS) {
+                    wolfSSL_DSA_free(key->dsa);
+                    key->dsa = NULL;
+                    wolfSSL_EVP_PKEY_free(key);
+                    return NULL;
+                }
+            }
+            #endif /* NO_DSA */
+        }
+    }
+    return key;
+}
+#endif /* OPENSSL_EXTRA_X509_SMALL */
+#endif /* !NO_CERTS */
+
+/* End of smaller subset of X509 compatibility functions. Avoid increasing the
+ * size of this subset and its memory usage */
+#endif /* OPENSSL_EXTRA_X509_SMALL */
+
+#if defined(OPENSSL_ALL)
+/* Takes two WOLFSSL_X509* certificates and performs a Sha hash of each, if the
+   * has values are the same, then it will do an XMEMCMP to confirm they are
+   * identical. Returns a 0 when certificates match, returns a negative number
+   * when certificates are not a match.
+*/
+int wolfSSL_X509_cmp(const WOLFSSL_X509 *a, const WOLFSSL_X509 *b)
+{
+        const byte* derA;
+        const byte* derB;
+        int retHashA;
+        int retHashB;
+        int outSzA = 0;
+        int outSzB = 0;
+
+        #ifdef WOLFSSL_PIC32MZ_HASH
+            byte digestA[PIC32_DIGEST_SIZE];
+            byte digestB[PIC32_DIGEST_SIZE];
+        #else
+            byte digestA[WC_SHA_DIGEST_SIZE];
+            byte digestB[WC_SHA_DIGEST_SIZE];
+        #endif
+
+        if (a == NULL || b == NULL){
+            return BAD_FUNC_ARG;
+        }
+
+        derA = wolfSSL_X509_get_der((WOLFSSL_X509*)a, &outSzA);
+        if(derA == NULL){
+            WOLFSSL_MSG("wolfSSL_X509_get_der - certificate A has failed");
+            return WOLFSSL_FATAL_ERROR;
+        }
+        derB = wolfSSL_X509_get_der((WOLFSSL_X509*)b, &outSzB);
+        if(derB == NULL){
+            WOLFSSL_MSG("wolfSSL_X509_get_der - certificate B has failed");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        retHashA = wc_ShaHash(derA, (word32)outSzA, digestA);
+        if(retHashA != 0){
+            WOLFSSL_MSG("Hash of certificate A has failed");
+            return WOLFSSL_FATAL_ERROR;
+        }
+        retHashB = wc_ShaHash(derB, (word32)outSzB, digestB);
+        if(retHashB != 0){
+            WOLFSSL_MSG("Hash of certificate B has failed");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        if (outSzA == outSzB){
+            #ifdef WOLFSSL_PIC32MZ_HASH
+            if(XMEMCMP(digestA, digestB, PIC32_DIGEST_SIZE) != 0){
+                return WOLFSSL_FATAL_ERROR;
+            }
+            #else
+            if(XMEMCMP(digestA, digestB, WC_SHA_DIGEST_SIZE) != 0){
+                return WOLFSSL_FATAL_ERROR;
+            }
+            #endif
+            else{
+                WOLFSSL_LEAVE("wolfSSL_X509_cmp", 0);
+                return 0;
+            }
+        }
+        else{
+            WOLFSSL_LEAVE("wolfSSL_X509_cmp", WOLFSSL_FATAL_ERROR);
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+#endif
+
+#if defined(OPENSSL_EXTRA)
+#if !defined(NO_CERTS)
+    int wolfSSL_X509_ext_isSet_by_NID(WOLFSSL_X509* x509, int nid)
+    {
+        int isSet = 0;
+
+        WOLFSSL_ENTER("wolfSSL_X509_ext_isSet_by_NID");
+
+        if (x509 != NULL) {
+            switch (nid) {
+                case BASIC_CA_OID: isSet = x509->basicConstSet; break;
+                case ALT_NAMES_OID: isSet = x509->subjAltNameSet; break;
+                case AUTH_KEY_OID: isSet = x509->authKeyIdSet; break;
+                case SUBJ_KEY_OID: isSet = x509->subjKeyIdSet; break;
+                case KEY_USAGE_OID: isSet = x509->keyUsageSet; break;
+                case CRL_DIST_OID: isSet = x509->CRLdistSet; break;
+                case EXT_KEY_USAGE_OID: isSet = ((x509->extKeyUsageSrc) ? 1 : 0);
+                    break;
+                case AUTH_INFO_OID: isSet = x509->authInfoSet; break;
+                #if defined(WOLFSSL_SEP) || defined(WOLFSSL_QT)
+                    case CERT_POLICY_OID: isSet = x509->certPolicySet; break;
+                #endif /* WOLFSSL_SEP || WOLFSSL_QT */
+                default:
+                    WOLFSSL_MSG("NID not in table");
+            }
+        }
+
+        WOLFSSL_LEAVE("wolfSSL_X509_ext_isSet_by_NID", isSet);
+
+        return isSet;
+    }
+
+
+    int wolfSSL_X509_ext_get_critical_by_NID(WOLFSSL_X509* x509, int nid)
+    {
+        int crit = 0;
+
+        WOLFSSL_ENTER("wolfSSL_X509_ext_get_critical_by_NID");
+
+        if (x509 != NULL) {
+            switch (nid) {
+                case BASIC_CA_OID: crit = x509->basicConstCrit; break;
+                case ALT_NAMES_OID: crit = x509->subjAltNameCrit; break;
+                case AUTH_KEY_OID: crit = x509->authKeyIdCrit; break;
+                case SUBJ_KEY_OID: crit = x509->subjKeyIdCrit; break;
+                case KEY_USAGE_OID: crit = x509->keyUsageCrit; break;
+                case CRL_DIST_OID: crit= x509->CRLdistCrit; break;
+                #if defined(WOLFSSL_SEP) || defined(WOLFSSL_QT)
+                    case CERT_POLICY_OID: crit = x509->certPolicyCrit; break;
+                #endif /* WOLFSSL_SEP || WOLFSSL_QT */
+            }
+        }
+
+        WOLFSSL_LEAVE("wolfSSL_X509_ext_get_critical_by_NID", crit);
+
+        return crit;
+    }
+
+
+    int wolfSSL_X509_get_isSet_pathLength(WOLFSSL_X509* x509)
+    {
+        int isSet = 0;
+
+        WOLFSSL_ENTER("wolfSSL_X509_get_isSet_pathLength");
+
+        if (x509 != NULL)
+            isSet = x509->basicConstPlSet;
+
+        WOLFSSL_LEAVE("wolfSSL_X509_get_isSet_pathLength", isSet);
+
+        return isSet;
+    }
+
+
+    word32 wolfSSL_X509_get_pathLength(WOLFSSL_X509* x509)
+    {
+        word32 pathLength = 0;
+
+        WOLFSSL_ENTER("wolfSSL_X509_get_pathLength");
+
+        if (x509 != NULL)
+            pathLength = x509->pathLength;
+
+        WOLFSSL_LEAVE("wolfSSL_X509_get_pathLength", pathLength);
+
+        return pathLength;
+    }
+
+
+    unsigned int wolfSSL_X509_get_keyUsage(WOLFSSL_X509* x509)
+    {
+        word16 usage = 0;
+
+        WOLFSSL_ENTER("wolfSSL_X509_get_keyUsage");
+
+        if (x509 != NULL)
+            usage = x509->keyUsage;
+
+        WOLFSSL_LEAVE("wolfSSL_X509_get_keyUsage", usage);
+
+        return usage;
+    }
+
+
+    byte* wolfSSL_X509_get_authorityKeyID(WOLFSSL_X509* x509,
+                                          byte* dst, int* dstLen)
+    {
+        byte *id = NULL;
+        int copySz = 0;
+
+        WOLFSSL_ENTER("wolfSSL_X509_get_authorityKeyID");
+
+        if (x509 != NULL) {
+            if (x509->authKeyIdSet) {
+                copySz = min(dstLen != NULL ? *dstLen : 0,
+                             (int)x509->authKeyIdSz);
+                id = x509->authKeyId;
+            }
+
+            if (dst != NULL && dstLen != NULL && id != NULL && copySz > 0) {
+                XMEMCPY(dst, id, copySz);
+                id = dst;
+                *dstLen = copySz;
+            }
+        }
+
+        WOLFSSL_LEAVE("wolfSSL_X509_get_authorityKeyID", copySz);
+
+        return id;
+    }
+
+
+    byte* wolfSSL_X509_get_subjectKeyID(WOLFSSL_X509* x509,
+                                        byte* dst, int* dstLen)
+    {
+        byte *id = NULL;
+        int copySz = 0;
+
+        WOLFSSL_ENTER("wolfSSL_X509_get_subjectKeyID");
+
+        if (x509 != NULL) {
+            if (x509->subjKeyIdSet) {
+                copySz = min(dstLen != NULL ? *dstLen : 0,
+                                                        (int)x509->subjKeyIdSz);
+                id = x509->subjKeyId;
+            }
+
+            if (dst != NULL && dstLen != NULL && id != NULL && copySz > 0) {
+                XMEMCPY(dst, id, copySz);
+                id = dst;
+                *dstLen = copySz;
+            }
+        }
+
+        WOLFSSL_LEAVE("wolfSSL_X509_get_subjectKeyID", copySz);
+
+        return id;
+    }
+
+
+    int wolfSSL_X509_NAME_entry_count(WOLFSSL_X509_NAME* name)
+    {
+        int count = 0;
+
+        WOLFSSL_ENTER("wolfSSL_X509_NAME_entry_count");
+
+        if (name != NULL)
+            count = name->fullName.locSz;
+
+        WOLFSSL_LEAVE("wolfSSL_X509_NAME_entry_count", count);
+        return count;
+    }
+
+
+
+    int wolfSSL_X509_NAME_get_index_by_NID(WOLFSSL_X509_NAME* name,
+                                          int nid, int pos)
+    {
+        int value = nid, i;
+
+        WOLFSSL_ENTER("wolfSSL_X509_NAME_get_index_by_NID");
+
+        if (name == NULL || pos >= DN_NAMES_MAX + DOMAIN_COMPONENT_MAX) {
+            return BAD_FUNC_ARG;
+        }
+
+        if (value == NID_emailAddress) {
+            value = ASN_EMAIL_NAME;
+        }
+
+        i = pos + 1; /* start search after index passed in */
+        if (i < 0) {
+            i = 0;
+        }
+
+        for (;i < name->fullName.locSz &&
+                i < DN_NAMES_MAX + DOMAIN_COMPONENT_MAX; i++) {
+            if (name->fullName.loc[i] == value) {
+                return i;
+            }
+        }
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+
+    WOLFSSL_ASN1_STRING*  wolfSSL_X509_NAME_ENTRY_get_data(
+                                                    WOLFSSL_X509_NAME_ENTRY* in)
+    {
+        WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_get_data");
+        if (in == NULL)
+            return NULL;
+
+        return in->value;
+    }
+
+
+    /* Creates a new WOLFSSL_ASN1_STRING structure.
+     *
+     * returns a pointer to the new structure created on success or NULL if fail
+     */
+    WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_new(void)
+    {
+        WOLFSSL_ASN1_STRING* asn1;
+
+        WOLFSSL_ENTER("wolfSSL_ASN1_STRING_new");
+
+        asn1 = (WOLFSSL_ASN1_STRING*)XMALLOC(sizeof(WOLFSSL_ASN1_STRING), NULL,
+                DYNAMIC_TYPE_OPENSSL);
+        if (asn1 != NULL) {
+            XMEMSET(asn1, 0, sizeof(WOLFSSL_ASN1_STRING));
+        }
+
+        return asn1; /* no check for null because error case is returning null*/
+    }
+
+
+    /* used to free a WOLFSSL_ASN1_STRING structure */
+    void wolfSSL_ASN1_STRING_free(WOLFSSL_ASN1_STRING* asn1)
+    {
+        WOLFSSL_ENTER("wolfSSL_ASN1_STRING_free");
+
+        if (asn1 != NULL) {
+            if (asn1->length > 0 && asn1->data != NULL && asn1->isDynamic) {
+                XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL);
+            }
+            XFREE(asn1, NULL, DYNAMIC_TYPE_OPENSSL);
+        }
+    }
+
+
+    /* Creates a new WOLFSSL_ASN1_STRING structure given the input type.
+     *
+     * type is the type of set when WOLFSSL_ASN1_STRING is created
+     *
+     * returns a pointer to the new structure created on success or NULL if fail
+     */
+    WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_type_new(int type)
+    {
+        WOLFSSL_ASN1_STRING* asn1;
+
+        WOLFSSL_ENTER("wolfSSL_ASN1_STRING_type_new");
+
+        asn1 = wolfSSL_ASN1_STRING_new();
+        if (asn1 == NULL) {
+            return NULL;
+        }
+        asn1->type = type;
+
+        return asn1;
+    }
+
+
+/******************************************************************************
+* wolfSSL_ASN1_STRING_type - returns the type of <asn1>
+*
+* RETURNS:
+* returns the type set for <asn1>. Otherwise, returns WOLFSSL_FAILURE.
+*/
+    int wolfSSL_ASN1_STRING_type(const WOLFSSL_ASN1_STRING* asn1)
+    {
+
+        WOLFSSL_ENTER("wolfSSL_ASN1_STRING_type");
+
+        if (asn1 == NULL) {
+            return WOLFSSL_FAILURE;
+        }
+
+        return asn1->type;
+    }
+
+    /* if dataSz is negative then use XSTRLEN to find length of data
+     * return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure */
+    /* `data` can be NULL and only buffer will be allocated */
+    int wolfSSL_ASN1_STRING_set(WOLFSSL_ASN1_STRING* asn1, const void* data,
+            int dataSz)
+    {
+        int sz;
+
+        WOLFSSL_ENTER("wolfSSL_ASN1_STRING_set");
+
+        if (asn1 == NULL || (data == NULL && dataSz < 0)) {
+            return WOLFSSL_FAILURE;
+        }
+
+        if (dataSz < 0) {
+            sz = (int)XSTRLEN((const char*)data) + 1; /* +1 for null */
+        }
+        else {
+            sz = dataSz;
+        }
+
+        if (sz < 0) {
+            return WOLFSSL_FAILURE;
+        }
+
+        /* free any existing data before copying */
+        if (asn1->data != NULL && asn1->isDynamic) {
+            XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL);
+            asn1->data = NULL;
+        }
+
+        if (sz > CTC_NAME_SIZE) {
+            /* create new data buffer and copy over */
+            asn1->data = (char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_OPENSSL);
+            if (asn1->data == NULL) {
+                return WOLFSSL_FAILURE;
+            }
+            asn1->isDynamic = 1;
+        }
+        else {
+            XMEMSET(asn1->strData, 0, CTC_NAME_SIZE);
+            asn1->data = asn1->strData;
+            asn1->isDynamic = 0;
+        }
+        if (data != NULL) {
+            XMEMCPY(asn1->data, data, sz);
+            asn1->data[sz] = '\0';
+        }
+        asn1->length = sz;
+
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    unsigned char* wolfSSL_ASN1_STRING_data(WOLFSSL_ASN1_STRING* asn)
+    {
+        WOLFSSL_ENTER("wolfSSL_ASN1_STRING_data");
+
+        if (asn) {
+            return (unsigned char*)asn->data;
+        }
+        else {
+            return NULL;
+        }
+    }
+
+
+    int wolfSSL_ASN1_STRING_length(WOLFSSL_ASN1_STRING* asn)
+    {
+        WOLFSSL_ENTER("wolfSSL_ASN1_STRING_length");
+
+        if (asn) {
+            return asn->length;
+        }
+        else {
+            return 0;
+        }
+    }
+
+#ifndef NO_WOLFSSL_STUB
+    WOLFSSL_ASN1_STRING* wolfSSL_d2i_DISPLAYTEXT(WOLFSSL_ASN1_STRING **asn,
+                                             const unsigned char **in, long len)
+    {
+        WOLFSSL_STUB("d2i_DISPLAYTEXT");
+        (void)asn;
+        (void)in;
+        (void)len;
+        return NULL;
+    }
+#endif
+
+#ifdef XSNPRINTF /* a snprintf function needs to be available */
+    /* Writes the human readable form of x509 to bio.
+     *
+     * bio  WOLFSSL_BIO to write to.
+     * x509 Certificate to write.
+     *
+     * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure
+     */
+    int wolfSSL_X509_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509* x509,
+        unsigned long nmflags, unsigned long cflag)
+    {
+        WOLFSSL_ENTER("wolfSSL_X509_print_ex");
+
+    #ifndef NO_WOLFSSL_STUB
+        /* flags currently not supported */
+        (void)nmflags;
+        (void)cflag;
+    #endif
+
+        if (bio == NULL || x509 == NULL) {
+            return WOLFSSL_FAILURE;
+        }
+
+        if (wolfSSL_BIO_write(bio, "Certificate:\n",
+                      (int)XSTRLEN("Certificate:\n")) <= 0) {
+                return WOLFSSL_FAILURE;
+        }
+
+        if (wolfSSL_BIO_write(bio, "    Data:\n",
+                      (int)XSTRLEN("    Data:\n")) <= 0) {
+                return WOLFSSL_FAILURE;
+        }
+
+        /* print version of cert */
+        {
+            int version;
+            char tmp[20];
+
+            if ((version = wolfSSL_X509_version(x509)) < 0) {
+                WOLFSSL_MSG("Error getting X509 version");
+                return WOLFSSL_FAILURE;
+            }
+            if (wolfSSL_BIO_write(bio, "        Version:",
+                          (int)XSTRLEN("        Version:")) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+            XSNPRINTF(tmp, sizeof(tmp), " %d (0x%x)\n", version, (byte)version-1);
+            if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+        }
+
+        /* print serial number out */
+        {
+            unsigned char serial[32];
+            int  sz = sizeof(serial);
+
+            XMEMSET(serial, 0, sz);
+            if (wolfSSL_X509_get_serial_number(x509, serial, &sz)
+                    != WOLFSSL_SUCCESS) {
+                WOLFSSL_MSG("Error getting x509 serial number");
+                return WOLFSSL_FAILURE;
+            }
+            if (wolfSSL_BIO_write(bio, "        Serial Number:",
+                          (int)XSTRLEN("        Serial Number:")) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+
+            /* if serial can fit into byte than print on the same line */
+            if (sz <= (int)sizeof(byte)) {
+                char tmp[17];
+                XSNPRINTF(tmp, sizeof(tmp), " %d (0x%x)\n", serial[0],serial[0]);
+                if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                    return WOLFSSL_FAILURE;
+                }
+            }
+            else {
+                int i;
+                char tmp[100];
+                int  tmpSz = 100;
+                char val[5];
+                int  valSz = 5;
+
+                /* serial is larger than int size so print off hex values */
+                if (wolfSSL_BIO_write(bio, "\n            ",
+                              (int)XSTRLEN("\n            ")) <= 0) {
+                    return WOLFSSL_FAILURE;
+                }
+                tmp[0] = '\0';
+                for (i = 0; i < sz - 1 && (3 * i) < tmpSz - valSz; i++) {
+                    XSNPRINTF(val, sizeof(val) - 1, "%02x:", serial[i]);
+                    val[3] = '\0'; /* make sure is null terminated */
+                    XSTRNCAT(tmp, val, valSz);
+                }
+                XSNPRINTF(val, sizeof(val) - 1, "%02x\n", serial[i]);
+                val[3] = '\0'; /* make sure is null terminated */
+                XSTRNCAT(tmp, val, valSz);
+                if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                    return WOLFSSL_FAILURE;
+                }
+            }
+        }
+
+        /* print signature algo */
+        {
+            int oid;
+            const char* sig;
+
+            if ((oid = wolfSSL_X509_get_signature_type(x509)) <= 0) {
+                WOLFSSL_MSG("Error getting x509 signature type");
+                return WOLFSSL_FAILURE;
+            }
+            if (wolfSSL_BIO_write(bio, "        Signature Algorithm: ",
+                          (int)XSTRLEN("        Signature Algorithm: ")) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+            sig = GetSigName(oid);
+            if (wolfSSL_BIO_write(bio, sig, (int)XSTRLEN(sig)) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+            if (wolfSSL_BIO_write(bio, "\n", (int)XSTRLEN("\n")) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+        }
+
+        /* print issuer */
+        {
+            char* issuer;
+        #ifdef WOLFSSL_SMALL_STACK
+            char* buff  = NULL;
+            int   issSz = 0;
+        #else
+            char buff[256];
+            int  issSz = 256;
+        #endif
+
+        #if defined(WOLFSSL_QT)
+            issuer = wolfSSL_X509_get_name_oneline(
+                               wolfSSL_X509_get_issuer_name(x509), buff, issSz);
+        #else
+            issuer = wolfSSL_X509_NAME_oneline(
+                               wolfSSL_X509_get_issuer_name(x509), buff, issSz);
+        #endif
+
+            if (wolfSSL_BIO_write(bio, "        Issuer: ",
+                          (int)XSTRLEN("        Issuer: ")) <= 0) {
+                #ifdef WOLFSSL_SMALL_STACK
+                XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL);
+                #endif
+                return WOLFSSL_FAILURE;
+            }
+            if (issuer != NULL) {
+                if (wolfSSL_BIO_write(bio, issuer, (int)XSTRLEN(issuer)) <= 0) {
+                    #ifdef WOLFSSL_SMALL_STACK
+                    XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL);
+                    #endif
+                    return WOLFSSL_FAILURE;
+                }
+            }
+            #ifdef WOLFSSL_SMALL_STACK
+            XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL);
+            #endif
+            if (wolfSSL_BIO_write(bio, "\n", (int)XSTRLEN("\n")) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+        }
+
+    #ifndef NO_ASN_TIME
+        /* print validity */
+        {
+            char tmp[80];
+
+            if (wolfSSL_BIO_write(bio, "        Validity\n",
+                          (int)XSTRLEN("        Validity\n")) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+
+            if (wolfSSL_BIO_write(bio, "            Not Before: ",
+                          (int)XSTRLEN("            Not Before: ")) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+            if (x509->notBefore.length > 0) {
+                if (GetTimeString(x509->notBefore.data, ASN_UTC_TIME,
+                    tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) {
+                    if (GetTimeString(x509->notBefore.data, ASN_GENERALIZED_TIME,
+                    tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) {
+                        WOLFSSL_MSG("Error getting not before date");
+                        return WOLFSSL_FAILURE;
+                    }
+                }
+            }
+            else {
+                XSTRNCPY(tmp, "Not Set", sizeof(tmp)-1);
+            }
+            tmp[sizeof(tmp) - 1] = '\0'; /* make sure null terminated */
+            if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+
+            if (wolfSSL_BIO_write(bio, "\n            Not After : ",
+                          (int)XSTRLEN("\n            Not After : ")) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+            if (x509->notAfter.length > 0) {
+                if (GetTimeString(x509->notAfter.data, ASN_UTC_TIME,
+                    tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) {
+                    if (GetTimeString(x509->notAfter.data, ASN_GENERALIZED_TIME,
+                        tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) {
+                        WOLFSSL_MSG("Error getting not after date");
+                        return WOLFSSL_FAILURE;
+                    }
+                }
+            }
+            else {
+                XSTRNCPY(tmp, "Not Set", sizeof(tmp)-1);
+            }
+            tmp[sizeof(tmp) - 1] = '\0'; /* make sure null terminated */
+            if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+        }
+    #endif
+
+        /* print subject */
+        {
+            char* subject;
+        #ifdef WOLFSSL_SMALL_STACK
+            char* buff  = NULL;
+            int   subSz = 0;
+        #else
+            char buff[256];
+            int  subSz = 256;
+        #endif
+
+        #if defined(WOLFSSL_QT)
+            subject = wolfSSL_X509_get_name_oneline(
+                              wolfSSL_X509_get_subject_name(x509), buff, subSz);
+        #else
+            subject = wolfSSL_X509_NAME_oneline(
+                              wolfSSL_X509_get_subject_name(x509), buff, subSz);
+        #endif
+
+            if (wolfSSL_BIO_write(bio, "\n        Subject: ",
+                          (int)XSTRLEN("\n        Subject: ")) <= 0) {
+                #ifdef WOLFSSL_SMALL_STACK
+                XFREE(subject, NULL, DYNAMIC_TYPE_OPENSSL);
+                #endif
+                return WOLFSSL_FAILURE;
+            }
+            if (subject != NULL) {
+                if (wolfSSL_BIO_write(bio, subject, (int)XSTRLEN(subject)) <= 0) {
+                    #ifdef WOLFSSL_SMALL_STACK
+                    XFREE(subject, NULL, DYNAMIC_TYPE_OPENSSL);
+                    #endif
+                    return WOLFSSL_FAILURE;
+                }
+            }
+            #ifdef WOLFSSL_SMALL_STACK
+            XFREE(subject, NULL, DYNAMIC_TYPE_OPENSSL);
+            #endif
+        }
+
+        /* get and print public key */
+        if (wolfSSL_BIO_write(bio, "\n        Subject Public Key Info:\n",
+                      (int)XSTRLEN("\n        Subject Public Key Info:\n")) <= 0) {
+            return WOLFSSL_FAILURE;
+        }
+        {
+        #if (!defined(NO_RSA) && !defined(HAVE_USER_RSA)) || defined(HAVE_ECC)
+            char tmp[100];
+        #endif
+
+            switch (x509->pubKeyOID) {
+            #ifndef NO_RSA
+                case RSAk:
+                    if (wolfSSL_BIO_write(bio,
+                                "            Public Key Algorithm: rsaEncryption\n",
+                   (int)XSTRLEN("            Public Key Algorithm: rsaEncryption\n")) <= 0) {
+                        return WOLFSSL_FAILURE;
+                    }
+                #ifdef HAVE_USER_RSA
+                    if (wolfSSL_BIO_write(bio,
+                        "                Build without user RSA to print key\n",
+           (int)XSTRLEN("                Build without user RSA to print key\n"))
+                        <= 0) {
+                        return WOLFSSL_FAILURE;
+                    }
+                #else
+                    {
+                        RsaKey rsa;
+                        word32 idx = 0;
+                        int  sz;
+                        byte lbit = 0;
+                        int  rawLen;
+                        unsigned char* rawKey;
+
+                        if (wc_InitRsaKey(&rsa, NULL) != 0) {
+                            WOLFSSL_MSG("wc_InitRsaKey failure");
+                            return WOLFSSL_FAILURE;
+                        }
+                        if (wc_RsaPublicKeyDecode(x509->pubKey.buffer,
+                                &idx, &rsa, x509->pubKey.length) != 0) {
+                            WOLFSSL_MSG("Error decoding RSA key");
+                            wc_FreeRsaKey(&rsa);
+                            return WOLFSSL_FAILURE;
+                        }
+                        if ((sz = wc_RsaEncryptSize(&rsa)) < 0) {
+                            WOLFSSL_MSG("Error getting RSA key size");
+                            wc_FreeRsaKey(&rsa);
+                            return WOLFSSL_FAILURE;
+                        }
+                        XSNPRINTF(tmp, sizeof(tmp) - 1, "%s%s: (%d bit)\n%s\n",
+                                "                ", "Public-Key", 8 * sz,
+                                "                Modulus:");
+                        tmp[sizeof(tmp) - 1] = '\0';
+                        if (wolfSSL_BIO_write(bio, tmp,
+                                                      (int)XSTRLEN(tmp)) <= 0) {
+                            wc_FreeRsaKey(&rsa);
+                            return WOLFSSL_FAILURE;
+                        }
+
+                        /* print out modulus */
+                        XSNPRINTF(tmp, sizeof(tmp) - 1,"                    ");
+                        tmp[sizeof(tmp) - 1] = '\0';
+                        if (mp_leading_bit(&rsa.n)) {
+                            lbit = 1;
+                            XSTRNCAT(tmp, "00", 3);
+                        }
+
+                        rawLen = mp_unsigned_bin_size(&rsa.n);
+                        rawKey = (unsigned char*)XMALLOC(rawLen, NULL,
+                                DYNAMIC_TYPE_TMP_BUFFER);
+                        if (rawKey == NULL) {
+                            WOLFSSL_MSG("Memory error");
+                            wc_FreeRsaKey(&rsa);
+                            return WOLFSSL_FAILURE;
+                        }
+                        mp_to_unsigned_bin(&rsa.n, rawKey);
+                        for (idx = 0; idx < (word32)rawLen; idx++) {
+                            char val[5];
+                            int valSz = 5;
+
+                            if ((idx == 0) && !lbit) {
+                                XSNPRINTF(val, valSz - 1, "%02x", rawKey[idx]);
+                            }
+                            else if ((idx != 0) && (((idx + lbit) % 15) == 0)) {
+                                tmp[sizeof(tmp) - 1] = '\0';
+                                if (wolfSSL_BIO_write(bio, tmp,
+                                                      (int)XSTRLEN(tmp)) <= 0) {
+                                    XFREE(rawKey, NULL,
+                                        DYNAMIC_TYPE_TMP_BUFFER);
+                                    wc_FreeRsaKey(&rsa);
+                                    return WOLFSSL_FAILURE;
+                                }
+                                XSNPRINTF(tmp, sizeof(tmp) - 1,
+                                        ":\n                    ");
+                                XSNPRINTF(val, valSz - 1, "%02x", rawKey[idx]);
+                            }
+                            else {
+                                XSNPRINTF(val, valSz - 1, ":%02x", rawKey[idx]);
+                            }
+                            XSTRNCAT(tmp, val, valSz);
+                        }
+                        XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+                        /* print out remaining modulus values */
+                        if ((idx > 0) && (((idx - 1 + lbit) % 15) != 0)) {
+                            tmp[sizeof(tmp) - 1] = '\0';
+                            if (wolfSSL_BIO_write(bio, tmp,
+                                                      (int)XSTRLEN(tmp)) <= 0) {
+                                return WOLFSSL_FAILURE;
+                            }
+                        }
+
+                        /* print out exponent values */
+                        rawLen = mp_unsigned_bin_size(&rsa.e);
+                        if (rawLen < 0) {
+                            WOLFSSL_MSG("Error getting exponent size");
+                            wc_FreeRsaKey(&rsa);
+                            return WOLFSSL_FAILURE;
+                        }
+
+                        if ((word32)rawLen < sizeof(word32)) {
+                            rawLen = sizeof(word32);
+                        }
+                        rawKey = (unsigned char*)XMALLOC(rawLen, NULL,
+                                DYNAMIC_TYPE_TMP_BUFFER);
+                        if (rawKey == NULL) {
+                            WOLFSSL_MSG("Memory error");
+                            wc_FreeRsaKey(&rsa);
+                            return WOLFSSL_FAILURE;
+                        }
+                        XMEMSET(rawKey, 0, rawLen);
+                        mp_to_unsigned_bin(&rsa.e, rawKey);
+                        if ((word32)rawLen <= sizeof(word32)) {
+                            idx = *(word32*)rawKey;
+                        #ifdef BIG_ENDIAN_ORDER
+                            idx = ByteReverseWord32(idx);
+                        #endif
+                        }
+                        XSNPRINTF(tmp, sizeof(tmp) - 1,
+                            "\n                Exponent: %d (0x%x)\n",idx, idx);
+                        if (wolfSSL_BIO_write(bio, tmp,
+                                                      (int)XSTRLEN(tmp)) <= 0) {
+                            XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                            wc_FreeRsaKey(&rsa);
+                            return WOLFSSL_FAILURE;
+                        }
+                        XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                        wc_FreeRsaKey(&rsa);
+                    }
+                #endif /* HAVE_USER_RSA */
+                    break;
+            #endif /* NO_RSA */
+
+            #ifdef HAVE_ECC
+                case ECDSAk:
+                    {
+                        word32 i;
+                        ecc_key ecc;
+
+                        if (wolfSSL_BIO_write(bio,
+                                "            Public Key Algorithm: EC\n",
+                   (int)XSTRLEN("            Public Key Algorithm: EC\n")) <= 0) {
+                        return WOLFSSL_FAILURE;
+                        }
+                        if (wc_ecc_init_ex(&ecc, x509->heap, INVALID_DEVID)
+                                != 0) {
+                            return WOLFSSL_FAILURE;
+                        }
+
+                        i = 0;
+                        if (wc_EccPublicKeyDecode(x509->pubKey.buffer, &i,
+                                              &ecc, x509->pubKey.length) != 0) {
+                            wc_ecc_free(&ecc);
+                            return WOLFSSL_FAILURE;
+                        }
+                        XSNPRINTF(tmp, sizeof(tmp) - 1, "%s%s: (%d bit)\n%s\n",
+                                "                 ", "Public-Key",
+                                8 * wc_ecc_size(&ecc),
+                                "                 pub:");
+                        tmp[sizeof(tmp) - 1] = '\0';
+                        if (wolfSSL_BIO_write(bio, tmp,
+                                                      (int)XSTRLEN(tmp)) <= 0) {
+                            wc_ecc_free(&ecc);
+                            return WOLFSSL_FAILURE;
+                        }
+                        XSNPRINTF(tmp, sizeof(tmp) - 1,"                     ");
+                        {
+                            word32 derSz;
+                            byte*  der;
+
+                            derSz = wc_ecc_size(&ecc) * WOLFSSL_BIT_SIZE;
+                            der = (byte*)XMALLOC(derSz, x509->heap,
+                                    DYNAMIC_TYPE_TMP_BUFFER);
+                            if (der == NULL) {
+                                wc_ecc_free(&ecc);
+                                return WOLFSSL_FAILURE;
+                            }
+
+                            if (wc_ecc_export_x963(&ecc, der, &derSz) != 0) {
+                                wc_ecc_free(&ecc);
+                                XFREE(der, x509->heap, DYNAMIC_TYPE_TMP_BUFFER);
+                                return WOLFSSL_FAILURE;
+                            }
+                            for (i = 0; i < derSz; i++) {
+                                char val[5];
+                                int valSz = 5;
+
+                                if (i == 0) {
+                                    XSNPRINTF(val, valSz - 1, "%02x", der[i]);
+                                }
+                                else if ((i % 15) == 0) {
+                                    tmp[sizeof(tmp) - 1] = '\0';
+                                    if (wolfSSL_BIO_write(bio, tmp,
+                                                (int)XSTRLEN(tmp)) <= 0) {
+                                        wc_ecc_free(&ecc);
+                                        XFREE(der, x509->heap,
+                                                DYNAMIC_TYPE_TMP_BUFFER);
+                                        return WOLFSSL_FAILURE;
+                                    }
+                                    XSNPRINTF(tmp, sizeof(tmp) - 1,
+                                        ":\n                     ");
+                                    XSNPRINTF(val, valSz - 1, "%02x", der[i]);
+                                }
+                                else {
+                                    XSNPRINTF(val, valSz - 1, ":%02x", der[i]);
+                                }
+                                XSTRNCAT(tmp, val, valSz);
+                            }
+
+                            /* print out remaining modulus values */
+                            if ((i > 0) && (((i - 1) % 15) != 0)) {
+                                tmp[sizeof(tmp) - 1] = '\0';
+                                if (wolfSSL_BIO_write(bio, tmp,
+                                                      (int)XSTRLEN(tmp)) <= 0) {
+                                    wc_ecc_free(&ecc);
+                                    XFREE(der, x509->heap,
+                                                DYNAMIC_TYPE_TMP_BUFFER);
+                                    return WOLFSSL_FAILURE;
+                                }
+                            }
+
+                            XFREE(der, x509->heap, DYNAMIC_TYPE_TMP_BUFFER);
+                        }
+                        XSNPRINTF(tmp, sizeof(tmp) - 1, "\n%s%s: %s\n",
+                                "                ", "ASN1 OID",
+                                ecc.dp->name);
+                        if (wolfSSL_BIO_write(bio, tmp,
+                                                      (int)XSTRLEN(tmp)) <= 0) {
+                            wc_ecc_free(&ecc);
+                            return WOLFSSL_FAILURE;
+                        }
+                        wc_ecc_free(&ecc);
+                    }
+                    break;
+            #endif /* HAVE_ECC */
+                default:
+                    WOLFSSL_MSG("Unknown key type");
+                    return WOLFSSL_FAILURE;
+            }
+        }
+
+        /* print out extensions */
+        if (wolfSSL_BIO_write(bio, "        X509v3 extensions:\n",
+                      (int)XSTRLEN("        X509v3 extensions:\n")) <= 0) {
+            return WOLFSSL_FAILURE;
+        }
+
+        /* print subject key id */
+        if (x509->subjKeyIdSet && x509->subjKeyId != NULL &&
+                x509->subjKeyIdSz > 0) {
+            char tmp[100];
+            word32 i;
+            char val[5];
+            int valSz = 5;
+
+
+            if (wolfSSL_BIO_write(bio,
+                        "            X509v3 Subject Key Identifier: \n",
+           (int)XSTRLEN("            X509v3 Subject Key Identifier: \n"))
+                 <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+
+            XSNPRINTF(tmp, sizeof(tmp) - 1, "                ");
+            for (i = 0; i < sizeof(tmp) && i < (x509->subjKeyIdSz - 1); i++) {
+                XSNPRINTF(val, valSz - 1, "%02X:", x509->subjKeyId[i]);
+                XSTRNCAT(tmp, val, valSz);
+            }
+            XSNPRINTF(val, valSz - 1, "%02X\n", x509->subjKeyId[i]);
+            XSTRNCAT(tmp, val, valSz);
+            if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+        }
+
+        /* printf out authority key id */
+        if (x509->authKeyIdSet && x509->authKeyId != NULL &&
+                x509->authKeyIdSz > 0) {
+            char tmp[100];
+            word32 i;
+            char val[5];
+            int valSz = 5;
+            int len = 0;
+
+            if (wolfSSL_BIO_write(bio,
+                        "            X509v3 Authority Key Identifier: \n",
+           (int)XSTRLEN("            X509v3 Authority Key Identifier: \n"))
+                 <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+
+            XSNPRINTF(tmp, sizeof(tmp) - 1, "                keyid");
+            for (i = 0; i < x509->authKeyIdSz; i++) {
+                /* check if buffer is almost full */
+                if (XSTRLEN(tmp) >= sizeof(tmp) - valSz) {
+                    if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                        return WOLFSSL_FAILURE;
+                    }
+                    tmp[0] = '\0';
+                }
+                XSNPRINTF(val, valSz - 1, ":%02X", x509->authKeyId[i]);
+                XSTRNCAT(tmp, val, valSz);
+            }
+            len = (int)XSTRLEN("\n");
+            XSTRNCAT(tmp, "\n", len + 1);
+            if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+        }
+
+        /* print basic constraint */
+        if (x509->basicConstSet) {
+            char tmp[100];
+
+            if (wolfSSL_BIO_write(bio,
+                        "\n            X509v3 Basic Constraints: \n",
+           (int)XSTRLEN("\n            X509v3 Basic Constraints: \n"))
+                 <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+            XSNPRINTF(tmp, sizeof(tmp),
+                    "                CA:%s\n",
+                    (x509->isCa)? "TRUE": "FALSE");
+            if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+        }
+
+        /* print out signature */
+        if (x509->sig.length > 0) {
+            unsigned char* sig;
+            int sigSz;
+            int i;
+            char tmp[100];
+            int sigOid = wolfSSL_X509_get_signature_type(x509);
+
+            if (wolfSSL_BIO_write(bio,
+                                "    Signature Algorithm: ",
+                   (int)XSTRLEN("    Signature Algorithm: ")) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+            XSNPRINTF(tmp, sizeof(tmp) - 1,"%s\n", GetSigName(sigOid));
+            tmp[sizeof(tmp) - 1] = '\0';
+            if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+
+            sigSz = (int)x509->sig.length;
+            sig = (unsigned char*)XMALLOC(sigSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            if (sig == NULL) {
+                return WOLFSSL_FAILURE;
+            }
+
+            if (wolfSSL_X509_get_signature(x509, sig, &sigSz) <= 0) {
+                XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                return WOLFSSL_FAILURE;
+            }
+            XSNPRINTF(tmp, sizeof(tmp) - 1,"        ");
+            tmp[sizeof(tmp) - 1] = '\0';
+            for (i = 0; i < sigSz; i++) {
+                char val[5];
+                int valSz = 5;
+
+                if (i == 0) {
+                    XSNPRINTF(val, valSz - 1, "%02x", sig[i]);
+                }
+                else if (((i % 18) == 0)) {
+                    tmp[sizeof(tmp) - 1] = '\0';
+                    if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp))
+                            <= 0) {
+                        XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                        return WOLFSSL_FAILURE;
+                    }
+                    XSNPRINTF(tmp, sizeof(tmp) - 1,
+                            ":\n        ");
+                    XSNPRINTF(val, valSz - 1, "%02x", sig[i]);
+                }
+                else {
+                    XSNPRINTF(val, valSz - 1, ":%02x", sig[i]);
+                }
+                XSTRNCAT(tmp, val, valSz);
+            }
+            XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+            /* print out remaining sig values */
+            if ((i > 0) && (((i - 1) % 18) != 0)) {
+                    tmp[sizeof(tmp) - 1] = '\0';
+                    if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp))
+                            <= 0) {
+                        return WOLFSSL_FAILURE;
+                    }
+            }
+        }
+
+        /* done with print out */
+        if (wolfSSL_BIO_write(bio, "\n\0", (int)XSTRLEN("\n\0")) <= 0) {
+            return WOLFSSL_FAILURE;
+        }
+
+        return WOLFSSL_SUCCESS;
+    }
+    int wolfSSL_X509_print(WOLFSSL_BIO* bio, WOLFSSL_X509* x509)
+    {
+        return wolfSSL_X509_print_ex(bio, x509, 0, 0);
+    }
+
+#endif /* XSNPRINTF */
+
+#endif /* NO_CERTS */
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+/* Creates cipher->description based on cipher->offset
+ * cipher->offset is set in wolfSSL_get_ciphers_compat when it is added
+ * to a stack of ciphers.
+ * @param [in] cipher: A cipher from a stack of ciphers.
+ * return WOLFSSL_SUCCESS if cipher->description is set, else WOLFSSL_FAILURE
+ */
+int wolfSSL_sk_CIPHER_description(WOLFSSL_CIPHER* cipher)
+{
+    int ret = WOLFSSL_FAILURE;
+    int i,j,k;
+    int strLen;
+    unsigned long offset;
+    char* dp;
+    const char* name;
+    const char *keaStr, *authStr, *encStr, *macStr, *protocol;
+    char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}};
+    unsigned char len = MAX_DESCRIPTION_SZ-1;
+    const CipherSuiteInfo* cipher_names;
+    ProtocolVersion pv;
+    WOLFSSL_ENTER("wolfSSL_sk_CIPHER_description");
+
+    if (cipher == NULL)
+        return WOLFSSL_FAILURE;
+
+    dp = cipher->description;
+    if (dp == NULL)
+        return WOLFSSL_FAILURE;
+
+    cipher_names = GetCipherNames();
+
+    offset = cipher->offset;
+    pv.major = cipher_names[offset].major;
+    pv.minor = cipher_names[offset].minor;
+    protocol = wolfSSL_internal_get_version(&pv);
+
+    name = cipher_names[offset].name;
+
+    if (name == NULL)
+        return ret;
+
+    /* Segment cipher name into n[n0,n1,n2,n4]
+     * These are used later for comparisons to create:
+     * keaStr, authStr, encStr, macStr
+     *
+     * If cipher_name = ECDHE-ECDSA-AES256-SHA
+     * then n0 = "ECDHE", n1 = "ECDSA", n2 = "AES256", n3 = "SHA"
+     * and n = [n0,n1,n2,n3,0]
+     */
+    strLen = (int)XSTRLEN(name);
+
+    for (i = 0, j = 0, k = 0; i <= strLen; i++) {
+        if (k > MAX_SEGMENTS || j > MAX_SEGMENT_SZ)
+            break;
+
+        if (name[i] != '-' && name[i] != '\0') {
+            n[k][j] = name[i]; /* Fill kth segment string until '-' */
+            j++;
+        }
+        else {
+            n[k][j] = '\0';
+            j = 0;
+            k++;
+        }
+    }
+    /* keaStr */
+    keaStr = GetCipherKeaStr(n);
+    /* authStr */
+    authStr = GetCipherAuthStr(n);
+    /* encStr */
+    encStr = GetCipherEncStr(n);
+    if ((cipher->bits = SetCipherBits(encStr)) == WOLFSSL_FAILURE) {
+       WOLFSSL_MSG("Cipher Bits Not Set.");
+    }
+    /* macStr */
+    macStr = GetCipherMacStr(n);
+
+
+    /* Build up the string by copying onto the end. */
+    XSTRNCPY(dp, name, len);
+    dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+    len -= (int)strLen; dp += strLen;
+
+    XSTRNCPY(dp, " ", len);
+    dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+    len -= (int)strLen; dp += strLen;
+    XSTRNCPY(dp, protocol, len);
+    dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+    len -= (int)strLen; dp += strLen;
+
+    XSTRNCPY(dp, " Kx=", len);
+    dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+    len -= (int)strLen; dp += strLen;
+    XSTRNCPY(dp, keaStr, len);
+    dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+    len -= (int)strLen; dp += strLen;
+
+    XSTRNCPY(dp, " Au=", len);
+    dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+    len -= (int)strLen; dp += strLen;
+    XSTRNCPY(dp, authStr, len);
+    dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+    len -= (int)strLen; dp += strLen;
+
+    XSTRNCPY(dp, " Enc=", len);
+    dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+    len -= (int)strLen; dp += strLen;
+    XSTRNCPY(dp, encStr, len);
+    dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+    len -= (int)strLen; dp += strLen;
+
+    XSTRNCPY(dp, " Mac=", len);
+    dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+    len -= (int)strLen; dp += strLen;
+    XSTRNCPY(dp, macStr, len);
+    dp[len-1] = '\0';
+
+    return WOLFSSL_SUCCESS;
+}
+#endif
+
+char* wolfSSL_CIPHER_description(const WOLFSSL_CIPHER* cipher, char* in,
+                                 int len)
+{
+    char *ret = in;
+    const char *keaStr, *authStr, *encStr, *macStr;
+    size_t strLen;
+    WOLFSSL_ENTER("wolfSSL_CIPHER_description");
+
+    if (cipher == NULL || in == NULL)
+        return NULL;
+
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+    /* if cipher is in the stack from wolfSSL_get_ciphers_compat then
+     * Return the description based on cipher_names[cipher->offset]
+     */
+    if (cipher->in_stack == TRUE) {
+        wolfSSL_sk_CIPHER_description((WOLFSSL_CIPHER*)cipher);
+        XSTRNCPY(in,cipher->description,len);
+        return ret;
+    }
+#endif
+
+    /* Get the cipher description based on the SSL session cipher */
+    switch (cipher->ssl->specs.kea) {
+        case no_kea:
+            keaStr = "None";
+            break;
+#ifndef NO_RSA
+        case rsa_kea:
+            keaStr = "RSA";
+            break;
+#endif
+#ifndef NO_DH
+        case diffie_hellman_kea:
+            keaStr = "DHE";
+            break;
+#endif
+        case fortezza_kea:
+            keaStr = "FZ";
+            break;
+#ifndef NO_PSK
+        case psk_kea:
+            keaStr = "PSK";
+            break;
+    #ifndef NO_DH
+        case dhe_psk_kea:
+            keaStr = "DHEPSK";
+            break;
+    #endif
+    #ifdef HAVE_ECC
+        case ecdhe_psk_kea:
+            keaStr = "ECDHEPSK";
+            break;
+    #endif
+#endif
+#ifdef HAVE_NTRU
+        case ntru_kea:
+            keaStr = "NTRU";
+            break;
+#endif
+#ifdef HAVE_ECC
+        case ecc_diffie_hellman_kea:
+            keaStr = "ECDHE";
+            break;
+        case ecc_static_diffie_hellman_kea:
+            keaStr = "ECDH";
+            break;
+#endif
+        default:
+            keaStr = "unknown";
+            break;
+    }
+
+    switch (cipher->ssl->specs.sig_algo) {
+        case anonymous_sa_algo:
+            authStr = "None";
+            break;
+#ifndef NO_RSA
+        case rsa_sa_algo:
+            authStr = "RSA";
+            break;
+#endif
+#ifndef NO_DSA
+        case dsa_sa_algo:
+            authStr = "DSA";
+            break;
+#endif
+#ifdef HAVE_ECC
+        case ecc_dsa_sa_algo:
+            authStr = "ECDSA";
+            break;
+#endif
+        default:
+            authStr = "unknown";
+            break;
+    }
+
+    switch (cipher->ssl->specs.bulk_cipher_algorithm) {
+        case wolfssl_cipher_null:
+            encStr = "None";
+            break;
+#ifndef NO_RC4
+        case wolfssl_rc4:
+            encStr = "RC4(128)";
+            break;
+#endif
+#ifndef NO_DES3
+        case wolfssl_triple_des:
+            encStr = "3DES(168)";
+            break;
+#endif
+#ifdef HAVE_IDEA
+        case wolfssl_idea:
+            encStr = "IDEA(128)";
+            break;
+#endif
+#ifndef NO_AES
+        case wolfssl_aes:
+            if (cipher->ssl->specs.key_size == 128)
+                encStr = "AES(128)";
+            else if (cipher->ssl->specs.key_size == 256)
+                encStr = "AES(256)";
+            else
+                encStr = "AES(?)";
+            break;
+    #ifdef HAVE_AESGCM
+        case wolfssl_aes_gcm:
+            if (cipher->ssl->specs.key_size == 128)
+                encStr = "AESGCM(128)";
+            else if (cipher->ssl->specs.key_size == 256)
+                encStr = "AESGCM(256)";
+            else
+                encStr = "AESGCM(?)";
+            break;
+    #endif
+    #ifdef HAVE_AESCCM
+        case wolfssl_aes_ccm:
+            if (cipher->ssl->specs.key_size == 128)
+                encStr = "AESCCM(128)";
+            else if (cipher->ssl->specs.key_size == 256)
+                encStr = "AESCCM(256)";
+            else
+                encStr = "AESCCM(?)";
+            break;
+    #endif
+#endif
+#ifdef HAVE_CHACHA
+        case wolfssl_chacha:
+            encStr = "CHACHA20/POLY1305(256)";
+            break;
+#endif
+#ifdef HAVE_CAMELLIA
+        case wolfssl_camellia:
+            if (cipher->ssl->specs.key_size == 128)
+                encStr = "Camellia(128)";
+            else if (cipher->ssl->specs.key_size == 256)
+                encStr = "Camellia(256)";
+            else
+                encStr = "Camellia(?)";
+            break;
+#endif
+#if defined(HAVE_HC128) && !defined(NO_HC128)
+        case wolfssl_hc128:
+            encStr = "HC128(128)";
+            break;
+#endif
+#if defined(HAVE_RABBIT) && !defined(NO_RABBIT)
+        case wolfssl_rabbit:
+            encStr = "RABBIT(128)";
+            break;
+#endif
+        default:
+            encStr = "unknown";
+            break;
+    }
+
+    switch (cipher->ssl->specs.mac_algorithm) {
+        case no_mac:
+            macStr = "None";
+            break;
+#ifndef NO_MD5
+        case md5_mac:
+            macStr = "MD5";
+            break;
+#endif
+#ifndef NO_SHA
+        case sha_mac:
+            macStr = "SHA1";
+            break;
+#endif
+#ifdef HAVE_SHA224
+        case sha224_mac:
+            macStr = "SHA224";
+            break;
+#endif
+#ifndef NO_SHA256
+        case sha256_mac:
+            macStr = "SHA256";
+            break;
+#endif
+#ifdef HAVE_SHA384
+        case sha384_mac:
+            macStr = "SHA384";
+            break;
+#endif
+#ifdef HAVE_SHA512
+        case sha512_mac:
+            macStr = "SHA512";
+            break;
+#endif
+        default:
+            macStr = "unknown";
+            break;
+    }
+
+    /* Build up the string by copying onto the end. */
+    XSTRNCPY(in, wolfSSL_CIPHER_get_name(cipher), len);
+    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+
+    XSTRNCPY(in, " ", len);
+    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+    XSTRNCPY(in, wolfSSL_get_version(cipher->ssl), len);
+    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+
+    XSTRNCPY(in, " Kx=", len);
+    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+    XSTRNCPY(in, keaStr, len);
+    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+
+    XSTRNCPY(in, " Au=", len);
+    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+    XSTRNCPY(in, authStr, len);
+    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+
+    XSTRNCPY(in, " Enc=", len);
+    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+    XSTRNCPY(in, encStr, len);
+    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+
+    XSTRNCPY(in, " Mac=", len);
+    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+    XSTRNCPY(in, macStr, len);
+    in[len-1] = '\0';
+
+    return ret;
+}
+
+
+#ifndef NO_SESSION_CACHE
+
+WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl)
+{
+    if (ssl == NULL) {
+        return NULL;
+    }
+
+    /* sessions are stored statically, no need for reference count */
+    return wolfSSL_get_session(ssl);
+}
+
+#endif /* NO_SESSION_CACHE */
+
+
+
+/* was do nothing */
+/*
+void OPENSSL_free(void* buf)
+{
+    (void)buf;
+}
+*/
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_OCSP_parse_url(char* url, char** host, char** port, char** path,
+                   int* ssl)
+{
+    (void)url;
+    (void)host;
+    (void)port;
+    (void)path;
+    (void)ssl;
+    WOLFSSL_STUB("OCSP_parse_url");
+    return 0;
+}
+#endif
+
+#ifndef NO_MD4
+
+void wolfSSL_MD4_Init(WOLFSSL_MD4_CTX* md4)
+{
+    /* make sure we have a big enough buffer */
+    typedef char ok[sizeof(md4->buffer) >= sizeof(Md4) ? 1 : -1];
+    (void) sizeof(ok);
+
+    WOLFSSL_ENTER("MD4_Init");
+    wc_InitMd4((Md4*)md4);
+}
+
+
+void wolfSSL_MD4_Update(WOLFSSL_MD4_CTX* md4, const void* data,
+                       unsigned long len)
+{
+    WOLFSSL_ENTER("MD4_Update");
+    wc_Md4Update((Md4*)md4, (const byte*)data, (word32)len);
+}
+
+
+void wolfSSL_MD4_Final(unsigned char* digest, WOLFSSL_MD4_CTX* md4)
+{
+    WOLFSSL_ENTER("MD4_Final");
+    wc_Md4Final((Md4*)md4, digest);
+}
+
+#endif /* NO_MD4 */
+
+
+/* Removes a WOLFSSL_BIO struct from the WOLFSSL_BIO linked list.
+ *
+ * bio is the WOLFSSL_BIO struct in the list and removed.
+ *
+ * The return WOLFSSL_BIO struct is the next WOLFSSL_BIO in the list or NULL if
+ * there is none.
+ */
+WOLFSSL_BIO* wolfSSL_BIO_pop(WOLFSSL_BIO* bio)
+{
+    if (bio == NULL) {
+        WOLFSSL_MSG("Bad argument passed in");
+        return NULL;
+    }
+
+    if (bio->prev != NULL) {
+        bio->prev->next = bio->next;
+    }
+
+    if (bio->next != NULL) {
+        bio->next->prev = bio->prev;
+    }
+
+    return bio->next;
+}
+
+
+
+WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_mem(void)
+{
+    static WOLFSSL_BIO_METHOD meth;
+
+    WOLFSSL_ENTER("wolfSSL_BIO_s_mem");
+    meth.type = WOLFSSL_BIO_MEMORY;
+
+    return &meth;
+}
+
+
+WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_base64(void)
+{
+    static WOLFSSL_BIO_METHOD meth;
+
+    WOLFSSL_ENTER("wolfSSL_BIO_f_base64");
+    meth.type = WOLFSSL_BIO_BASE64;
+
+    return &meth;
+}
+
+
+/* Set the flag for the bio.
+ *
+ * bio   the structure to set the flag in
+ * flags the flag to use
+ */
+void wolfSSL_BIO_set_flags(WOLFSSL_BIO* bio, int flags)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_set_flags");
+
+    if (bio != NULL) {
+        bio->flags |= flags;
+    }
+}
+
+void wolfSSL_BIO_clear_flags(WOLFSSL_BIO *bio, int flags)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_clear_flags");
+    if (bio != NULL) {
+        bio->flags &= ~flags;
+    }
+}
+
+/* Set ex_data for WOLFSSL_BIO
+ *
+ * bio  : BIO structure to set ex_data in
+ * idx  : Index of ex_data to set
+ * data : Data to set in ex_data
+ *
+ * Returns WOLFSSL_SUCCESS on success or WOLFSSL_FAILURE on failure
+ */
+int wolfSSL_BIO_set_ex_data(WOLFSSL_BIO *bio, int idx, void *data)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_set_ex_data");
+    #ifdef HAVE_EX_DATA
+    if (bio != NULL && idx < MAX_EX_DATA) {
+        return wolfSSL_CRYPTO_set_ex_data(&bio->ex_data, idx, data);
+    }
+    #else
+    (void)bio;
+    (void)idx;
+    (void)data;
+    #endif
+    return WOLFSSL_FAILURE;
+}
+
+/* Get ex_data in WOLFSSL_BIO at given index
+ *
+ * bio  : BIO structure to get ex_data from
+ * idx  : Index of ex_data to get data from
+ *
+ * Returns void pointer to ex_data on success or NULL on failure
+ */
+void *wolfSSL_BIO_get_ex_data(WOLFSSL_BIO *bio, int idx)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_get_ex_data");
+    #ifdef HAVE_EX_DATA
+    if (bio != NULL && idx < MAX_EX_DATA && idx >= 0) {
+        return wolfSSL_CRYPTO_get_ex_data(&bio->ex_data, idx);
+    }
+    #else
+    (void)bio;
+    (void)idx;
+    #endif
+    return NULL;
+}
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_RAND_screen(void)
+{
+    WOLFSSL_STUB("RAND_screen");
+}
+#endif
+
+
+
+int wolfSSL_RAND_load_file(const char* fname, long len)
+{
+    (void)fname;
+    /* wolfCrypt provides enough entropy internally or will report error */
+    if (len == -1)
+        return 1024;
+    else
+        return (int)len;
+}
+
+
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_COMP_METHOD* wolfSSL_COMP_zlib(void)
+{
+    WOLFSSL_STUB("COMP_zlib");
+    return 0;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_COMP_METHOD* wolfSSL_COMP_rle(void)
+{
+    WOLFSSL_STUB("COMP_rle");
+    return 0;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_COMP_add_compression_method(int method, void* data)
+{
+    (void)method;
+    (void)data;
+    WOLFSSL_STUB("COMP_add_compression_method");
+    return 0;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_set_dynlock_create_callback(WOLFSSL_dynlock_value* (*f)(
+                                                          const char*, int))
+{
+    WOLFSSL_STUB("CRYPTO_set_dynlock_create_callback");
+    (void)f;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_set_dynlock_lock_callback(
+             void (*f)(int, WOLFSSL_dynlock_value*, const char*, int))
+{
+    WOLFSSL_STUB("CRYPTO_set_set_dynlock_lock_callback");
+    (void)f;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_set_dynlock_destroy_callback(
+                  void (*f)(WOLFSSL_dynlock_value*, const char*, int))
+{
+    WOLFSSL_STUB("CRYPTO_set_set_dynlock_destroy_callback");
+    (void)f;
+}
+#endif
+
+
+const char* wolfSSL_X509_verify_cert_error_string(long err)
+{
+    return wolfSSL_ERR_reason_error_string(err);
+}
+
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_X509_LOOKUP_add_dir(WOLFSSL_X509_LOOKUP* lookup, const char* dir,
+                               long len)
+{
+    (void)lookup;
+    (void)dir;
+    (void)len;
+    WOLFSSL_STUB("X509_LOOKUP_add_dir");
+    return 0;
+}
+#endif
+
+int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP* lookup,
+                                 const char* file, long type)
+{
+#if !defined(NO_FILESYSTEM) && \
+    (defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM))
+    int           ret = WOLFSSL_FAILURE;
+    XFILE         fp;
+    long          sz;
+    byte*         pem = NULL;
+    byte*         curr = NULL;
+    byte*         prev = NULL;
+    WOLFSSL_X509* x509;
+    const char* header = NULL;
+    const char* footer = NULL;
+
+    if (type != X509_FILETYPE_PEM)
+        return BAD_FUNC_ARG;
+
+    fp = XFOPEN(file, "r");
+    if (fp == XBADFILE)
+        return BAD_FUNC_ARG;
+
+    if(XFSEEK(fp, 0, XSEEK_END) != 0) {
+        XFCLOSE(fp);
+        return WOLFSSL_BAD_FILE;
+    }
+    sz = XFTELL(fp);
+    XREWIND(fp);
+
+    if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) {
+        WOLFSSL_MSG("X509_LOOKUP_load_file size error");
+        goto end;
+    }
+
+    pem = (byte*)XMALLOC(sz, 0, DYNAMIC_TYPE_PEM);
+    if (pem == NULL) {
+        ret = MEMORY_ERROR;
+        goto end;
+    }
+
+    /* Read in file which may be CRLs or certificates. */
+    if (XFREAD(pem, (size_t)sz, 1, fp) != 1)
+        goto end;
+
+    prev = curr = pem;
+    do {
+        /* get PEM header and footer based on type */
+        if (wc_PemGetHeaderFooter(CRL_TYPE, &header, &footer) == 0 &&
+                XSTRNSTR((char*)curr, header, (unsigned int)sz) != NULL) {
+#ifdef HAVE_CRL
+            WOLFSSL_CERT_MANAGER* cm = lookup->store->cm;
+
+            if (cm->crl == NULL) {
+                if (wolfSSL_CertManagerEnableCRL(cm, 0) != WOLFSSL_SUCCESS) {
+                    WOLFSSL_MSG("Enable CRL failed");
+                    goto end;
+                }
+            }
+
+            ret = BufferLoadCRL(cm->crl, curr, sz, WOLFSSL_FILETYPE_PEM,
+                NO_VERIFY);
+            if (ret != WOLFSSL_SUCCESS)
+                goto end;
+#endif
+            curr = (byte*)XSTRNSTR((char*)curr, footer, (unsigned int)sz);
+        }
+        else if (wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer) == 0 &&
+                XSTRNSTR((char*)curr, header, (unsigned int)sz) != NULL) {
+            x509 = wolfSSL_X509_load_certificate_buffer(curr, (int)sz,
+                                                        WOLFSSL_FILETYPE_PEM);
+            if (x509 == NULL)
+                 goto end;
+            ret = wolfSSL_X509_STORE_add_cert(lookup->store, x509);
+            wolfSSL_X509_free(x509);
+            if (ret != WOLFSSL_SUCCESS)
+                goto end;
+            curr = (byte*)XSTRNSTR((char*)curr, footer, (unsigned int)sz);
+        }
+        else
+            goto end;
+
+        if (curr == NULL)
+            goto end;
+
+        curr++;
+        sz -= (long)(curr - prev);
+        prev = curr;
+    }
+    while (ret == WOLFSSL_SUCCESS);
+
+end:
+    if (pem != NULL)
+        XFREE(pem, 0, DYNAMIC_TYPE_PEM);
+    XFCLOSE(fp);
+    return ret;
+#else
+    (void)lookup;
+    (void)file;
+    (void)type;
+    return WOLFSSL_FAILURE;
+#endif
+}
+
+WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_hash_dir(void)
+{
+    /* Method implementation in functions. */
+    static WOLFSSL_X509_LOOKUP_METHOD meth = { 1 };
+    return &meth;
+}
+
+WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_file(void)
+{
+    /* Method implementation in functions. */
+    static WOLFSSL_X509_LOOKUP_METHOD meth = { 0 };
+    return &meth;
+}
+
+
+WOLFSSL_X509_LOOKUP* wolfSSL_X509_STORE_add_lookup(WOLFSSL_X509_STORE* store,
+                                               WOLFSSL_X509_LOOKUP_METHOD* m)
+{
+    WOLFSSL_ENTER("SSL_X509_STORE_add_lookup");
+    if (store == NULL)
+        return NULL;
+
+    /* Method is a dummy value and is not needed. */
+    (void)m;
+    /* Make sure the lookup has a back reference to the store. */
+    store->lookup.store = store;
+    return &store->lookup;
+}
+
+
+#ifndef NO_CERTS
+/* Converts the X509 to DER format and outputs it into bio.
+ *
+ * bio  is the structure to hold output DER
+ * x509 certificate to create DER from
+ *
+ * returns WOLFSSL_SUCCESS on success
+ */
+int wolfSSL_i2d_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509* x509)
+{
+    WOLFSSL_ENTER("wolfSSL_i2d_X509_bio");
+
+    if (bio == NULL || x509 == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if (x509->derCert != NULL) {
+        word32 len = x509->derCert->length;
+        byte*  der = x509->derCert->buffer;
+
+        if (wolfSSL_BIO_write(bio, der, len) == (int)len) {
+            return SSL_SUCCESS;
+        }
+    }
+
+    return WOLFSSL_FAILURE;
+}
+
+
+/* Converts an internal structure to a DER buffer
+ *
+ * x509 structure to get DER buffer from
+ * out  buffer to hold result. If NULL then *out is NULL then a new buffer is
+ *      created.
+ *
+ * returns the size of the DER result on success
+ */
+int wolfSSL_i2d_X509(WOLFSSL_X509* x509, unsigned char** out)
+{
+    const unsigned char* der;
+    int derSz = 0;
+
+    WOLFSSL_ENTER("wolfSSL_i2d_X509");
+
+    if (x509 == NULL) {
+        WOLFSSL_LEAVE("wolfSSL_i2d_X509", BAD_FUNC_ARG);
+        return BAD_FUNC_ARG;
+    }
+
+    der = wolfSSL_X509_get_der(x509, &derSz);
+    if (der == NULL) {
+        WOLFSSL_LEAVE("wolfSSL_i2d_X509", MEMORY_E);
+        return MEMORY_E;
+    }
+
+    if (out != NULL && *out == NULL) {
+        *out = (unsigned char*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_OPENSSL);
+        if (*out == NULL) {
+            WOLFSSL_LEAVE("wolfSSL_i2d_X509", MEMORY_E);
+            return MEMORY_E;
+        }
+    }
+
+    if (out != NULL)
+        XMEMCPY(*out, der, derSz);
+
+    WOLFSSL_LEAVE("wolfSSL_i2d_X509", derSz);
+    return derSz;
+}
+
+
+/* Converts the DER from bio and creates a WOLFSSL_X509 structure from it.
+ *
+ * bio  is the structure holding DER
+ * x509 certificate to create from DER. Can be NULL
+ *
+ * returns pointer to WOLFSSL_X509 structure on success and NULL on fail
+ */
+WOLFSSL_X509* wolfSSL_d2i_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509** x509)
+{
+    WOLFSSL_X509* localX509 = NULL;
+    unsigned char* mem  = NULL;
+    int    ret;
+    word32 size;
+
+    WOLFSSL_ENTER("wolfSSL_d2i_X509_bio");
+
+    if (bio == NULL) {
+        WOLFSSL_MSG("Bad Function Argument bio is NULL");
+        return NULL;
+    }
+
+    ret = wolfSSL_BIO_get_mem_data(bio, &mem);
+    if (mem == NULL || ret <= 0) {
+        WOLFSSL_MSG("Failed to get data from bio struct");
+        return NULL;
+    }
+    size = ret;
+
+    localX509 = wolfSSL_X509_d2i(NULL, mem, size);
+    if (localX509 == NULL) {
+        return NULL;
+    }
+
+    if (x509 != NULL) {
+        *x509 = localX509;
+    }
+
+    return localX509;
+}
+
+
+#if !defined(NO_ASN) && !defined(NO_PWDBASED)
+WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, WC_PKCS12** pkcs12)
+{
+    WC_PKCS12* localPkcs12    = NULL;
+    unsigned char* mem  = NULL;
+    int ret;
+    word32 size;
+
+    WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_bio");
+
+    if (bio == NULL) {
+        WOLFSSL_MSG("Bad Function Argument bio is NULL");
+        return NULL;
+    }
+
+    localPkcs12 = wc_PKCS12_new();
+    if (localPkcs12 == NULL) {
+        WOLFSSL_MSG("Memory error");
+        return NULL;
+    }
+
+    if (pkcs12 != NULL) {
+        *pkcs12 = localPkcs12;
+    }
+
+    ret = wolfSSL_BIO_get_mem_data(bio, &mem);
+    if (mem == NULL || ret <= 0) {
+        WOLFSSL_MSG("Failed to get data from bio struct");
+        wc_PKCS12_free(localPkcs12);
+        if (pkcs12 != NULL) {
+            *pkcs12 = NULL;
+        }
+        return NULL;
+    }
+    size = ret;
+
+    ret = wc_d2i_PKCS12(mem, size, localPkcs12);
+    if (ret < 0) {
+        WOLFSSL_MSG("Failed to get PKCS12 sequence");
+        wc_PKCS12_free(localPkcs12);
+        if (pkcs12 != NULL) {
+            *pkcs12 = NULL;
+        }
+        return NULL;
+    }
+
+    return localPkcs12;
+}
+
+/* Converts the PKCS12 to DER format and outputs it into bio.
+ *
+ * bio is the structure to hold output DER
+ * pkcs12 structure to create DER from
+ *
+ * return 1 for success or 0 if an error occurs
+ */
+int wolfSSL_i2d_PKCS12_bio(WOLFSSL_BIO *bio, WC_PKCS12 *pkcs12)
+{
+    int ret = WOLFSSL_FAILURE;
+
+    WOLFSSL_ENTER("wolfSSL_i2d_PKCS12_bio");
+
+    if ((bio != NULL) && (pkcs12 != NULL)) {
+        word32 certSz = 0;
+        byte *certDer = NULL;
+
+        certSz = wc_i2d_PKCS12(pkcs12, &certDer, NULL);
+        if ((certSz > 0) && (certDer != NULL)) {
+            if (wolfSSL_BIO_write(bio, certDer, certSz) == (int)certSz) {
+                ret = SSL_SUCCESS;
+            }
+        }
+
+        if (certDer != NULL) {
+            XFREE(certDer, NULL, DYNAMIC_TYPE_PKCS);
+        }
+    }
+
+    return ret;
+}
+
+/* helper function to get raw pointer to DER buffer from WOLFSSL_EVP_PKEY */
+static int wolfSSL_EVP_PKEY_get_der(WOLFSSL_EVP_PKEY* key, unsigned char** der)
+{
+    if (!key)
+        return WOLFSSL_FAILURE;
+    if (der)
+        *der = (unsigned char*)key->pkey.ptr;
+    return key->pkey_sz;
+}
+
+/* Copies unencrypted DER key buffer into "der". If "der" is null then the size
+ * of buffer needed is returned
+ * NOTE: This also advances the "der" pointer to be at the end of buffer.
+ *
+ * Returns size of key buffer on success
+ */
+int wolfSSL_i2d_PrivateKey(WOLFSSL_EVP_PKEY* key, unsigned char** der)
+{
+    if (key == NULL) {
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (key->pkey_sz <= 0 || !key->pkey.ptr) {
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (der != NULL) {
+        /* since this function signature has no size value passed in it is
+         * assumed that the user has allocated a large enough buffer */
+        XMEMCPY(*der, key->pkey.ptr, key->pkey_sz);
+        *der += key->pkey_sz;
+    }
+    return key->pkey_sz;
+}
+
+/* Creates a new WC_PKCS12 structure
+ *
+ * pass  password to use
+ * name  friendlyName to use
+ * pkey  private key to go into PKCS12 bundle
+ * cert  certificate to go into PKCS12 bundle
+ * ca    extra certificates that can be added to bundle. Can be NULL
+ * keyNID  type of encryption to use on the key (-1 means no encryption)
+ * certNID type of encryption to use on the certificate
+ * itt     number of iterations with encryption
+ * macItt  number of iterations with mac creation
+ * keyType flag for signature and/or encryption key
+ *
+ * returns a pointer to a new WC_PKCS12 structure on success and NULL on fail
+ */
+WC_PKCS12* wolfSSL_PKCS12_create(char* pass, char* name,
+        WOLFSSL_EVP_PKEY* pkey, WOLFSSL_X509* cert,
+        WOLF_STACK_OF(WOLFSSL_X509)* ca,
+        int keyNID, int certNID, int itt, int macItt, int keyType)
+{
+    WC_PKCS12*      pkcs12;
+    WC_DerCertList* list = NULL;
+    word32 passSz;
+    byte* keyDer;
+    word32 keyDerSz;
+    byte* certDer;
+    int certDerSz;
+
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_PKCS12_create()");
+
+    if (pass == NULL || pkey == NULL || cert == NULL) {
+        WOLFSSL_LEAVE("wolfSSL_PKCS12_create()", BAD_FUNC_ARG);
+        return NULL;
+    }
+    passSz = (word32)XSTRLEN(pass);
+
+    if ((ret = wolfSSL_EVP_PKEY_get_der(pkey, &keyDer)) < 0) {
+        WOLFSSL_LEAVE("wolfSSL_PKCS12_create", ret);
+        return NULL;
+    }
+    keyDerSz = ret;
+
+    certDer = (byte*)wolfSSL_X509_get_der(cert, &certDerSz);
+    if (certDer == NULL) {
+        return NULL;
+    }
+
+    if (ca != NULL) {
+        WC_DerCertList* cur;
+        unsigned long numCerts = ca->num;
+        byte* curDer;
+        int   curDerSz = 0;
+        WOLFSSL_STACK* sk = ca;
+
+        while (numCerts > 0 && sk != NULL) {
+            cur = (WC_DerCertList*)XMALLOC(sizeof(WC_DerCertList), NULL,
+                    DYNAMIC_TYPE_PKCS);
+            if (cur == NULL) {
+                wc_FreeCertList(list, NULL);
+                return NULL;
+            }
+
+            curDer = (byte*)wolfSSL_X509_get_der(sk->data.x509, &curDerSz);
+            if (curDer == NULL || curDerSz < 0) {
+                XFREE(cur, NULL, DYNAMIC_TYPE_PKCS);
+                wc_FreeCertList(list, NULL);
+                return NULL;
+            }
+
+            cur->buffer = (byte*)XMALLOC(curDerSz, NULL, DYNAMIC_TYPE_PKCS);
+            if (cur->buffer == NULL) {
+                XFREE(cur, NULL, DYNAMIC_TYPE_PKCS);
+                wc_FreeCertList(list, NULL);
+                return NULL;
+            }
+            XMEMCPY(cur->buffer, curDer, curDerSz);
+            cur->bufferSz = curDerSz;
+            cur->next = list;
+            list = cur;
+
+            sk = sk->next;
+            numCerts--;
+        }
+    }
+
+    pkcs12 = wc_PKCS12_create(pass, passSz, name, keyDer, keyDerSz,
+            certDer, certDerSz, list, keyNID, certNID, itt, macItt,
+            keyType, NULL);
+
+    if (ca != NULL) {
+        wc_FreeCertList(list, NULL);
+    }
+
+    return pkcs12;
+}
+
+
+/* return WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE on failure */
+int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw,
+      WOLFSSL_EVP_PKEY** pkey, WOLFSSL_X509** cert, WOLF_STACK_OF(WOLFSSL_X509)** ca)
+{
+    DecodedCert DeCert;
+    void* heap = NULL;
+    int ret;
+    byte* certData = NULL;
+    word32 certDataSz;
+    byte* pk = NULL;
+    word32 pkSz;
+    WC_DerCertList* certList = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_PKCS12_parse");
+
+    /* make sure we init return args */
+    if (pkey) *pkey = NULL;
+    if (cert) *cert = NULL;
+    if (ca)   *ca = NULL;
+
+    if (pkcs12 == NULL || psw == NULL || pkey == NULL || cert == NULL) {
+        WOLFSSL_MSG("Bad argument value");
+        return WOLFSSL_FAILURE;
+    }
+
+    heap  = wc_PKCS12_GetHeap(pkcs12);
+
+    if (ca == NULL) {
+        ret = wc_PKCS12_parse(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz,
+            NULL);
+    }
+    else {
+        ret = wc_PKCS12_parse(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz,
+            &certList);
+    }
+    if (ret < 0) {
+        WOLFSSL_LEAVE("wolfSSL_PKCS12_parse", ret);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* Decode cert and place in X509 stack struct */
+    if (certList != NULL) {
+        WC_DerCertList* current = certList;
+
+        *ca = (WOLF_STACK_OF(WOLFSSL_X509)*)XMALLOC(sizeof(WOLF_STACK_OF(WOLFSSL_X509)),
+                                               heap, DYNAMIC_TYPE_X509);
+        if (*ca == NULL) {
+            if (pk != NULL) {
+                XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+            }
+            if (certData != NULL) {
+                XFREE(*cert, heap, DYNAMIC_TYPE_PKCS); *cert = NULL;
+            }
+            /* Free up WC_DerCertList and move on */
+            while (current != NULL) {
+                WC_DerCertList* next = current->next;
+
+                XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS);
+                XFREE(current, heap, DYNAMIC_TYPE_PKCS);
+                current = next;
+            }
+            return WOLFSSL_FAILURE;
+        }
+        XMEMSET(*ca, 0, sizeof(WOLF_STACK_OF(WOLFSSL_X509)));
+
+        /* add list of DER certs as X509's to stack */
+        while (current != NULL) {
+            WC_DerCertList*  toFree = current;
+            WOLFSSL_X509* x509;
+
+            x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap,
+                                                             DYNAMIC_TYPE_X509);
+            InitX509(x509, 1, heap);
+            InitDecodedCert(&DeCert, current->buffer, current->bufferSz, heap);
+            if (ParseCertRelative(&DeCert, CERT_TYPE, NO_VERIFY, NULL) != 0) {
+                WOLFSSL_MSG("Issue with parsing certificate");
+                FreeDecodedCert(&DeCert);
+                wolfSSL_X509_free(x509);
+            }
+            else {
+                if ((ret = CopyDecodedToX509(x509, &DeCert)) != 0) {
+                    WOLFSSL_MSG("Failed to copy decoded cert");
+                    FreeDecodedCert(&DeCert);
+                    wolfSSL_X509_free(x509);
+                    wolfSSL_sk_X509_free(*ca); *ca = NULL;
+                    if (pk != NULL) {
+                        XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+                    }
+                    if (certData != NULL) {
+                        XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
+                    }
+                    /* Free up WC_DerCertList */
+                    while (current != NULL) {
+                        WC_DerCertList* next = current->next;
+
+                        XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS);
+                        XFREE(current, heap, DYNAMIC_TYPE_PKCS);
+                        current = next;
+                    }
+                    return WOLFSSL_FAILURE;
+                }
+                FreeDecodedCert(&DeCert);
+
+                if (wolfSSL_sk_X509_push(*ca, x509) != 1) {
+                    WOLFSSL_MSG("Failed to push x509 onto stack");
+                    wolfSSL_X509_free(x509);
+                    wolfSSL_sk_X509_free(*ca); *ca = NULL;
+                    if (pk != NULL) {
+                        XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+                    }
+                    if (certData != NULL) {
+                        XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
+                    }
+
+                    /* Free up WC_DerCertList */
+                    while (current != NULL) {
+                        WC_DerCertList* next = current->next;
+
+                        XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS);
+                        XFREE(current, heap, DYNAMIC_TYPE_PKCS);
+                        current = next;
+                    }
+                    return WOLFSSL_FAILURE;
+                }
+            }
+            current = current->next;
+            XFREE(toFree->buffer, heap, DYNAMIC_TYPE_PKCS);
+            XFREE(toFree, heap, DYNAMIC_TYPE_PKCS);
+        }
+    }
+
+
+    /* Decode cert and place in X509 struct */
+    if (certData != NULL) {
+        *cert = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap,
+                                                             DYNAMIC_TYPE_X509);
+        if (*cert == NULL) {
+            if (pk != NULL) {
+                XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+            }
+            if (ca != NULL) {
+                wolfSSL_sk_X509_free(*ca); *ca = NULL;
+            }
+            XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
+            return WOLFSSL_FAILURE;
+        }
+        InitX509(*cert, 1, heap);
+        InitDecodedCert(&DeCert, certData, certDataSz, heap);
+        if (ParseCertRelative(&DeCert, CERT_TYPE, NO_VERIFY, NULL) != 0) {
+            WOLFSSL_MSG("Issue with parsing certificate");
+        }
+        if ((ret = CopyDecodedToX509(*cert, &DeCert)) != 0) {
+            WOLFSSL_MSG("Failed to copy decoded cert");
+            FreeDecodedCert(&DeCert);
+            if (pk != NULL) {
+                XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+            }
+            if (ca != NULL) {
+                wolfSSL_sk_X509_free(*ca); *ca = NULL;
+            }
+            wolfSSL_X509_free(*cert); *cert = NULL;
+            return WOLFSSL_FAILURE;
+        }
+        FreeDecodedCert(&DeCert);
+        XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
+    }
+
+
+    /* get key type */
+    ret = BAD_STATE_E;
+    if (pk != NULL) { /* decode key if present */
+        *pkey = wolfSSL_EVP_PKEY_new_ex(heap);
+        if (*pkey == NULL) {
+            wolfSSL_X509_free(*cert); *cert = NULL;
+            if (ca != NULL) {
+                wolfSSL_sk_X509_free(*ca); *ca = NULL;
+            }
+            XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+            return WOLFSSL_FAILURE;
+        }
+        #ifndef NO_RSA
+        {
+            word32 keyIdx = 0;
+            RsaKey key;
+
+            if (wc_InitRsaKey(&key, heap) != 0) {
+                ret = BAD_STATE_E;
+            }
+            else {
+                if ((ret = wc_RsaPrivateKeyDecode(pk, &keyIdx, &key, pkSz))
+                                                                         == 0) {
+                    (*pkey)->type = EVP_PKEY_RSA;
+                    (*pkey)->rsa  = wolfSSL_RSA_new();
+                    (*pkey)->ownRsa = 1; /* we own RSA */
+                    if ((*pkey)->rsa == NULL) {
+                        WOLFSSL_MSG("issue creating EVP RSA key");
+                        wolfSSL_X509_free(*cert); *cert = NULL;
+                        if (ca != NULL) {
+                            wolfSSL_sk_X509_free(*ca); *ca = NULL;
+                        }
+                        wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL;
+                        XFREE(pk, heap, DYNAMIC_TYPE_PKCS);
+                        return WOLFSSL_FAILURE;
+                    }
+                    if ((ret = wolfSSL_RSA_LoadDer_ex((*pkey)->rsa, pk, pkSz,
+                                    WOLFSSL_RSA_LOAD_PRIVATE)) != SSL_SUCCESS) {
+                        WOLFSSL_MSG("issue loading RSA key");
+                        wolfSSL_X509_free(*cert); *cert = NULL;
+                        if (ca != NULL) {
+                            wolfSSL_sk_X509_free(*ca); *ca = NULL;
+                        }
+                        wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL;
+                        XFREE(pk, heap, DYNAMIC_TYPE_PKCS);
+                        return WOLFSSL_FAILURE;
+                    }
+
+                    WOLFSSL_MSG("Found PKCS12 RSA key");
+                    ret = 0; /* set in success state for upcoming ECC check */
+                }
+                wc_FreeRsaKey(&key);
+            }
+        }
+        #endif /* NO_RSA */
+
+        #ifdef HAVE_ECC
+        {
+            word32  keyIdx = 0;
+            ecc_key key;
+
+            if (ret != 0) { /* if is in fail state check if ECC key */
+                if (wc_ecc_init(&key) != 0) {
+                    wolfSSL_X509_free(*cert); *cert = NULL;
+                    if (ca != NULL) {
+                        wolfSSL_sk_X509_free(*ca); *ca = NULL;
+                    }
+                    wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL;
+                    XFREE(pk, heap, DYNAMIC_TYPE_PKCS);
+                    return WOLFSSL_FAILURE;
+                }
+
+                if ((ret = wc_EccPrivateKeyDecode(pk, &keyIdx, &key, pkSz))
+                                                                         != 0) {
+                    wolfSSL_X509_free(*cert); *cert = NULL;
+                    if (ca != NULL) {
+                        wolfSSL_sk_X509_free(*ca); *ca = NULL;
+                    }
+                    wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL;
+                    XFREE(pk, heap, DYNAMIC_TYPE_PKCS);
+                    WOLFSSL_MSG("Bad PKCS12 key format");
+                    return WOLFSSL_FAILURE;
+                }
+                (*pkey)->type = EVP_PKEY_EC;
+                (*pkey)->pkey_curve = key.dp->oidSum;
+                wc_ecc_free(&key);
+                WOLFSSL_MSG("Found PKCS12 ECC key");
+            }
+        }
+        #else
+        if (ret != 0) { /* if is in fail state and no ECC then fail */
+            wolfSSL_X509_free(*cert); *cert = NULL;
+            if (ca != NULL) {
+                wolfSSL_sk_X509_free(*ca); *ca = NULL;
+            }
+            wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL;
+            XFREE(pk, heap, DYNAMIC_TYPE_PKCS);
+            WOLFSSL_MSG("Bad PKCS12 key format");
+            return WOLFSSL_FAILURE;
+        }
+        #endif /* HAVE_ECC */
+
+        (*pkey)->save_type = 0;
+        (*pkey)->pkey_sz   = pkSz;
+        (*pkey)->pkey.ptr  = (char*)pk;
+    }
+
+    (void)ret;
+    (void)ca;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* !defined(NO_ASN) && !defined(NO_PWDBASED) */
+
+
+/* no-op function. Was initially used for adding encryption algorithms available
+ * for PKCS12 */
+void wolfSSL_PKCS12_PBE_add(void)
+{
+    WOLFSSL_ENTER("wolfSSL_PKCS12_PBE_add");
+}
+
+
+
+WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get_chain(WOLFSSL_X509_STORE_CTX* ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_chain");
+
+    if (ctx == NULL) {
+        return NULL;
+    }
+
+#ifdef SESSION_CERTS
+    /* if chain is null but sesChain is available then populate stack */
+    if (ctx->chain == NULL && ctx->sesChain != NULL) {
+        int i;
+        WOLFSSL_X509_CHAIN* c = ctx->sesChain;
+        WOLFSSL_STACK*     sk = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK),
+                                    NULL, DYNAMIC_TYPE_X509);
+
+        if (sk == NULL) {
+            return NULL;
+        }
+
+        XMEMSET(sk, 0, sizeof(WOLFSSL_STACK));
+        ctx->chain = sk;
+
+        for (i = 0; i < c->count && i < MAX_CHAIN_DEPTH; i++) {
+            WOLFSSL_X509* x509 = wolfSSL_get_chain_X509(c, i);
+
+            if (x509 == NULL) {
+                WOLFSSL_MSG("Unable to get x509 from chain");
+                wolfSSL_sk_X509_free(sk);
+                return NULL;
+            }
+
+            if (wolfSSL_sk_X509_push(sk, x509) != SSL_SUCCESS) {
+                WOLFSSL_MSG("Unable to load x509 into stack");
+                wolfSSL_sk_X509_free(sk);
+                wolfSSL_X509_free(x509);
+                return NULL;
+            }
+        }
+
+#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA)
+        /* add CA used to verify top of chain to the list */
+        if (c->count > 0) {
+            WOLFSSL_X509* x509 = wolfSSL_get_chain_X509(c, c->count - 1);
+            if (x509 != NULL) {
+                WOLFSSL_X509* issuer = NULL;
+                if (wolfSSL_X509_STORE_CTX_get1_issuer(&issuer, ctx, x509)
+                        == WOLFSSL_SUCCESS) {
+                    /* check that the certificate being looked up is not self
+                     * signed and that a issuer was found */
+                    if (issuer != NULL && wolfSSL_X509_NAME_cmp(&x509->issuer,
+                                &x509->subject) != 0) {
+                        if (wolfSSL_sk_X509_push(sk, issuer) != SSL_SUCCESS) {
+                            WOLFSSL_MSG("Unable to load CA x509 into stack");
+                            wolfSSL_sk_X509_free(sk);
+                            wolfSSL_X509_free(issuer);
+                            return NULL;
+                        }
+                    }
+                    else {
+                        WOLFSSL_MSG("Certificate is self signed");
+                        if (issuer != NULL)
+                            wolfSSL_X509_free(issuer);
+                    }
+                }
+                else {
+                    WOLFSSL_MSG("Could not find CA for certificate");
+                }
+            }
+        }
+#endif
+
+    }
+#endif /* SESSION_CERTS */
+
+    return ctx->chain;
+}
+
+/* make shallow copy of the stack, data pointers are copied by reference */
+WOLFSSL_STACK* wolfSSL_sk_X509_dup(WOLFSSL_STACK* sk)
+{
+    unsigned long i;
+    WOLFSSL_STACK* dup = NULL;
+    WOLFSSL_STACK* node = NULL;
+    WOLFSSL_STACK *dIdx = NULL, *sIdx = sk;
+
+    if (sk == NULL) {
+        return NULL;
+    }
+
+    for (i = 0; i < sk->num; i++) {
+
+        node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+                                         DYNAMIC_TYPE_X509);
+        if (node == NULL) {
+            if (i != 0) {
+                wolfSSL_sk_free(dup);
+            }
+            WOLFSSL_MSG("Memory error");
+            return NULL;
+        }
+        XMEMSET(node, 0, sizeof(WOLFSSL_STACK));
+
+        /* copy sk node to new node, data by reference */
+        node->data.x509 = sIdx->data.x509;
+        node->num = sIdx->num;
+
+        /* insert node into list, progress idx */
+        if (i == 0) {
+            dup = node;
+        } else {
+            dIdx->next = node;
+        }
+
+        dIdx = node;
+        sIdx = sIdx->next;
+    }
+
+    return dup;
+}
+
+
+/* like X509_STORE_CTX_get_chain(), but return a copy with data reference
+   counts increased */
+WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get1_chain(WOLFSSL_X509_STORE_CTX* ctx)
+{
+    unsigned long i;
+    WOLFSSL_STACK* ref;
+    WOLFSSL_STACK* dup;
+
+    if (ctx == NULL) {
+        return NULL;
+    }
+
+    /* get chain in ctx */
+    ref = wolfSSL_X509_STORE_CTX_get_chain(ctx);
+    if (ref == NULL) {
+        return ref;
+    }
+
+    /* create duplicate of ctx chain */
+    dup = wolfSSL_sk_X509_dup(ref);
+    if (dup == NULL) {
+        return NULL;
+    }
+
+    /* increase ref counts of inner data X509 */
+    ref = dup;
+    for (i = 0; i < dup->num && ref != NULL; i++) {
+        if (wc_LockMutex(&ref->data.x509->refMutex) != 0) {
+            WOLFSSL_MSG("Failed to lock x509 mutex");
+        }
+        ref->data.x509->refCount++;
+        wc_UnLockMutex(&ref->data.x509->refMutex);
+        ref = ref->next;
+    }
+
+    return dup;
+}
+
+
+int wolfSSL_X509_STORE_add_cert(WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509)
+{
+    int result = WOLFSSL_FATAL_ERROR;
+
+    WOLFSSL_ENTER("wolfSSL_X509_STORE_add_cert");
+    if (store != NULL && store->cm != NULL && x509 != NULL
+                                                && x509->derCert != NULL) {
+        DerBuffer* derCert = NULL;
+
+        result = AllocDer(&derCert, x509->derCert->length,
+            x509->derCert->type, NULL);
+        if (result == 0) {
+            /* AddCA() frees the buffer. */
+            XMEMCPY(derCert->buffer,
+                            x509->derCert->buffer, x509->derCert->length);
+            result = AddCA(store->cm, &derCert, WOLFSSL_USER_CA, VERIFY);
+        }
+    }
+
+    WOLFSSL_LEAVE("wolfSSL_X509_STORE_add_cert", result);
+
+    if (result != WOLFSSL_SUCCESS) {
+        result = WOLFSSL_FATAL_ERROR;
+    }
+
+    return result;
+}
+
+WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void)
+{
+    WOLFSSL_X509_STORE* store = NULL;
+    WOLFSSL_ENTER("SSL_X509_STORE_new");
+
+    if ((store = (WOLFSSL_X509_STORE*)XMALLOC(sizeof(WOLFSSL_X509_STORE), NULL,
+                                    DYNAMIC_TYPE_X509_STORE)) == NULL)
+        goto err_exit;
+
+    XMEMSET(store, 0, sizeof(WOLFSSL_X509_STORE));
+    store->isDynamic = 1;
+
+    if ((store->cm = wolfSSL_CertManagerNew()) == NULL)
+        goto err_exit;
+
+#ifdef HAVE_CRL
+    store->crl = NULL;
+    if ((store->crl = (WOLFSSL_X509_CRL *)XMALLOC(sizeof(WOLFSSL_X509_CRL),
+                                        NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL)
+        goto err_exit;
+    if (InitCRL(store->crl, NULL) < 0)
+        goto err_exit;
+#endif
+
+#ifdef OPENSSL_EXTRA
+    if ((store->param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC(
+                           sizeof(WOLFSSL_X509_VERIFY_PARAM),
+                           NULL,DYNAMIC_TYPE_OPENSSL)) == NULL)
+        goto err_exit;
+
+#endif
+
+    return store;
+
+err_exit:
+    if (store == NULL)
+        return NULL;
+
+    wolfSSL_X509_STORE_free(store);
+
+    return NULL;
+}
+
+
+void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE* store)
+{
+    if (store != NULL && store->isDynamic) {
+        if (store->cm != NULL)
+            wolfSSL_CertManagerFree(store->cm);
+#ifdef HAVE_CRL
+        if (store->crl != NULL)
+            wolfSSL_X509_CRL_free(store->crl);
+#endif
+#ifdef OPENSSL_EXTRA
+        if (store->param != NULL)
+            XFREE(store->param, NULL, DYNAMIC_TYPE_OPENSSL);
+#endif
+        XFREE(store, NULL, DYNAMIC_TYPE_X509_STORE);
+    }
+}
+
+
+int wolfSSL_X509_STORE_set_flags(WOLFSSL_X509_STORE* store, unsigned long flag)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_X509_STORE_set_flags");
+
+    if (store == NULL)
+        return WOLFSSL_FAILURE;
+
+    if ((flag & WOLFSSL_CRL_CHECKALL) || (flag & WOLFSSL_CRL_CHECK)) {
+        ret = wolfSSL_CertManagerEnableCRL(store->cm, (int)flag);
+    }
+
+    (void)store;
+    (void)flag;
+
+    return ret;
+}
+
+
+int wolfSSL_X509_STORE_set_default_paths(WOLFSSL_X509_STORE* store)
+{
+    (void)store;
+    return WOLFSSL_SUCCESS;
+}
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_X509_STORE_get_by_subject(WOLFSSL_X509_STORE_CTX* ctx, int idx,
+                            WOLFSSL_X509_NAME* name, WOLFSSL_X509_OBJECT* obj)
+{
+    (void)ctx;
+    (void)idx;
+    (void)name;
+    (void)obj;
+    WOLFSSL_STUB("X509_STORE_get_by_subject");
+    return 0;
+}
+#endif
+
+WOLFSSL_X509_STORE_CTX* wolfSSL_X509_STORE_CTX_new(void)
+{
+    WOLFSSL_X509_STORE_CTX* ctx;
+    WOLFSSL_ENTER("X509_STORE_CTX_new");
+
+    ctx = (WOLFSSL_X509_STORE_CTX*)XMALLOC(sizeof(WOLFSSL_X509_STORE_CTX), NULL,
+                                    DYNAMIC_TYPE_X509_CTX);
+    if (ctx != NULL) {
+        ctx->param = NULL;
+        wolfSSL_X509_STORE_CTX_init(ctx, NULL, NULL, NULL);
+    }
+
+    return ctx;
+}
+
+
+int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx,
+     WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509, WOLF_STACK_OF(WOLFSSL_X509)* sk)
+{
+    WOLFSSL_X509* x509_cert;
+    int ret = 0;
+    (void)sk;
+    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_init");
+
+    if (ctx != NULL) {
+        ctx->store = store;
+        #ifndef WOLFSSL_X509_STORE_CERTS
+        ctx->current_cert = x509;
+        #else
+        if(x509 != NULL){
+            ctx->current_cert = wolfSSL_X509_d2i(NULL, x509->derCert->buffer,x509->derCert->length);
+            if(ctx->current_cert == NULL)
+                return WOLFSSL_FATAL_ERROR;
+        } else
+            ctx->current_cert = NULL;
+        #endif
+
+        ctx->chain  = sk;
+        /* Add intermediate certificates from stack to store */
+        while (sk != NULL) {
+            x509_cert = sk->data.x509;
+            if (x509_cert != NULL && x509_cert->isCa) {
+                ret = wolfSSL_X509_STORE_add_cert(store, x509_cert);
+                if (ret < 0) {
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+            sk = sk->next;
+        }
+
+        ctx->sesChain = NULL;
+        ctx->domain = NULL;
+#if defined(HAVE_EX_DATA) || defined(FORTRESS)
+        XMEMSET(&ctx->ex_data, 0, sizeof(ctx->ex_data));
+#endif
+        ctx->userCtx = NULL;
+        ctx->error = 0;
+        ctx->error_depth = 0;
+        ctx->discardSessionCerts = 0;
+#ifdef OPENSSL_EXTRA
+        if (ctx->param == NULL) {
+            ctx->param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC(
+                           sizeof(WOLFSSL_X509_VERIFY_PARAM),
+                           NULL,DYNAMIC_TYPE_OPENSSL);
+            if (ctx->param == NULL){
+                WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_init failed");
+                return SSL_FATAL_ERROR;
+            }
+        }
+#endif
+        return SSL_SUCCESS;
+    }
+    return WOLFSSL_FATAL_ERROR;
+}
+
+
+void wolfSSL_X509_STORE_CTX_free(WOLFSSL_X509_STORE_CTX* ctx)
+{
+    WOLFSSL_ENTER("X509_STORE_CTX_free");
+    if (ctx != NULL) {
+    #if !defined(OPENSSL_ALL) && !defined(WOLFSSL_QT)
+        if (ctx->store != NULL)
+            wolfSSL_X509_STORE_free(ctx->store);
+        #ifndef WOLFSSL_KEEP_STORE_CERTS
+        if (ctx->current_cert != NULL)
+            wolfSSL_FreeX509(ctx->current_cert);
+        #endif
+    #endif /* !OPENSSL_ALL && !WOLFSSL_QT */
+#ifdef OPENSSL_EXTRA
+        if (ctx->param != NULL){
+            XFREE(ctx->param,NULL,DYNAMIC_TYPE_OPENSSL);
+        }
+#endif
+        XFREE(ctx, NULL, DYNAMIC_TYPE_X509_CTX);
+    }
+}
+
+
+void wolfSSL_X509_STORE_CTX_cleanup(WOLFSSL_X509_STORE_CTX* ctx)
+{
+    (void)ctx;
+    /* Do nothing */
+}
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+/* Returns corresponding X509 error from internal ASN error <e> */
+static int GetX509Error(int e)
+{
+    switch (e) {
+        case ASN_BEFORE_DATE_E:
+            return X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
+        case ASN_AFTER_DATE_E:
+            return X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD;
+        case ASN_NO_SIGNER_E:
+            return X509_V_ERR_INVALID_CA;
+        case ASN_SELF_SIGNED_E:
+            return X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
+        case ASN_PATHLEN_INV_E:
+        case ASN_PATHLEN_SIZE_E:
+            return X509_V_ERR_PATH_LENGTH_EXCEEDED;
+        case ASN_SIG_OID_E:
+        case ASN_SIG_CONFIRM_E:
+        case ASN_SIG_HASH_E:
+        case ASN_SIG_KEY_E:
+            return X509_V_ERR_CERT_SIGNATURE_FAILURE;
+        default:
+            WOLFSSL_MSG("Error not configured or implemented yet");
+            return e;
+    }
+}
+#endif
+
+/* Verifies certificate chain using WOLFSSL_X509_STORE_CTX
+ * returns 0 on success or < 0 on failure.
+ */
+int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
+{
+    int ret = 0;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+    int depth = 0;
+    int error;
+    byte *afterDate, *beforeDate;
+#endif
+    WOLFSSL_ENTER("wolfSSL_X509_verify_cert");
+
+    if (ctx != NULL && ctx->store != NULL && ctx->store->cm != NULL
+         && ctx->current_cert != NULL && ctx->current_cert->derCert != NULL) {
+            ret = wolfSSL_CertManagerVerifyBuffer(ctx->store->cm,
+                    ctx->current_cert->derCert->buffer,
+                    ctx->current_cert->derCert->length,
+                    WOLFSSL_FILETYPE_ASN1);
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+        /* If there was an error, process it and add it to CTX */
+        if (ret < 0) {
+            /* Get corresponding X509 error */
+            error = GetX509Error(ret);
+            /* Set error depth */
+            if (ctx->chain)
+                depth = (int)ctx->chain->num;
+
+            wolfSSL_X509_STORE_CTX_set_error(ctx, error);
+            wolfSSL_X509_STORE_CTX_set_error_depth(ctx, depth);
+            ctx->store->verify_cb(0, ctx);
+        }
+
+        error = 0;
+        /* wolfSSL_CertManagerVerifyBuffer only returns ASN_AFTER_DATE_E or
+         ASN_BEFORE_DATE_E if there are no additional errors found in the
+         cert. Therefore, check if the cert is expired or not yet valid
+         in order to return the correct expected error. */
+        afterDate = ctx->current_cert->notAfter.data;
+        beforeDate = ctx->current_cert->notBefore.data;
+
+        if (ValidateDate(afterDate, ctx->current_cert->notAfter.type,
+                                                                   AFTER) < 1) {
+            error = X509_V_ERR_CERT_HAS_EXPIRED;
+        }
+        else if (ValidateDate(beforeDate, ctx->current_cert->notBefore.type,
+                                                                  BEFORE) < 1) {
+            error = X509_V_ERR_CERT_NOT_YET_VALID;
+        }
+
+        if (error != 0 ) {
+            wolfSSL_X509_STORE_CTX_set_error(ctx, error);
+            wolfSSL_X509_STORE_CTX_set_error_depth(ctx, depth);
+            if (ctx->store && ctx->store->verify_cb)
+                ctx->store->verify_cb(0, ctx);
+        }
+#endif /* OPENSSL_ALL || WOLFSSL_QT */
+        return ret;
+    }
+    return WOLFSSL_FATAL_ERROR;
+}
+
+
+/* Use the public key to verify the signature. Note: this only verifies
+ * the certificate signature.
+ * returns WOLFSSL_SUCCESS on successful signature verification */
+int wolfSSL_X509_verify(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey)
+{
+    int ret;
+    const byte* der;
+    int derSz = 0;
+    int type;
+
+    if (x509 == NULL || pkey == NULL) {
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    der = wolfSSL_X509_get_der(x509, &derSz);
+    if (der == NULL) {
+        WOLFSSL_MSG("Error getting WOLFSSL_X509 DER");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    switch (pkey->type) {
+        case EVP_PKEY_RSA:
+            type = RSAk;
+            break;
+
+        case EVP_PKEY_EC:
+            type = ECDSAk;
+            break;
+
+        case EVP_PKEY_DSA:
+            type = DSAk;
+            break;
+
+        default:
+            WOLFSSL_MSG("Unknown pkey key type");
+            return WOLFSSL_FATAL_ERROR;
+    }
+
+    ret = CheckCertSignaturePubKey(der, derSz, x509->heap,
+            (unsigned char*)pkey->pkey.ptr, pkey->pkey_sz, type);
+    if (ret == 0) {
+        return WOLFSSL_SUCCESS;
+    }
+    return WOLFSSL_FAILURE;
+}
+#endif /* NO_CERTS */
+
+#if !defined(NO_FILESYSTEM)
+static void *wolfSSL_d2i_X509_fp_ex(XFILE file, void **x509, int type)
+{
+    void *newx509 = NULL;
+    byte *fileBuffer = NULL;
+    long sz = 0;
+
+    /* init variable */
+    if (x509)
+        *x509 = NULL;
+
+    /* argument check */
+    if (file == XBADFILE) {
+        return NULL;
+    }
+
+    /* determine file size */
+    if (XFSEEK(file, 0, XSEEK_END) != 0) {
+        return NULL;
+    }
+    sz = XFTELL(file);
+    XREWIND(file);
+
+    if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) {
+        WOLFSSL_MSG("d2i_X509_fp_ex file size error");
+        return NULL;
+    }
+
+    fileBuffer = (byte *)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE);
+    if (fileBuffer != NULL) {
+        if ((long)XFREAD(fileBuffer, 1, sz, file) != sz) {
+            WOLFSSL_MSG("File read failed");
+            goto err_exit;
+        }
+        if (type == CERT_TYPE) {
+            newx509 = (void *)wolfSSL_X509_d2i(NULL, fileBuffer, (int)sz);
+        }
+    #ifdef HAVE_CRL
+        else if (type == CRL_TYPE) {
+            newx509 = (void *)wolfSSL_d2i_X509_CRL(NULL, fileBuffer, (int)sz);
+        }
+    #endif
+    #if !defined(NO_ASN) && !defined(NO_PWDBASED)
+        else if (type == PKCS12_TYPE) {
+            if ((newx509 = wc_PKCS12_new()) == NULL) {
+                goto err_exit;
+            }
+            if (wc_d2i_PKCS12(fileBuffer, (int)sz, (WC_PKCS12*)newx509) < 0) {
+                goto err_exit;
+            }
+        }
+    #endif
+        else {
+            goto err_exit;
+        }
+        if (newx509 == NULL) {
+            WOLFSSL_MSG("X509 failed");
+            goto err_exit;
+        }
+    }
+
+    if (x509)
+        *x509 = newx509;
+
+    goto _exit;
+
+err_exit:
+#if !defined(NO_ASN) && !defined(NO_PWDBASED)
+    if ((newx509 != NULL) && (type == PKCS12_TYPE)) {
+        wc_PKCS12_free((WC_PKCS12*)newx509);
+        newx509 = NULL;
+    }
+#endif
+_exit:
+    if (fileBuffer != NULL)
+        XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE);
+
+    return newx509;
+}
+
+WOLFSSL_X509_PKCS12 *wolfSSL_d2i_PKCS12_fp(XFILE fp, WOLFSSL_X509_PKCS12 **pkcs12)
+{
+    WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_fp");
+    return (WOLFSSL_X509_PKCS12 *)wolfSSL_d2i_X509_fp_ex(fp, (void **)pkcs12, PKCS12_TYPE);
+}
+
+WOLFSSL_X509 *wolfSSL_d2i_X509_fp(XFILE fp, WOLFSSL_X509 **x509)
+{
+    WOLFSSL_ENTER("wolfSSL_d2i_X509_fp");
+    return (WOLFSSL_X509 *)wolfSSL_d2i_X509_fp_ex(fp, (void **)x509, CERT_TYPE);
+}
+#endif /* !NO_FILESYSTEM */
+
+
+#ifdef HAVE_CRL
+#ifndef NO_FILESYSTEM
+WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL_fp(XFILE fp, WOLFSSL_X509_CRL **crl)
+{
+    WOLFSSL_ENTER("wolfSSL_d2i_X509_CRL_fp");
+    return (WOLFSSL_X509_CRL *)wolfSSL_d2i_X509_fp_ex(fp, (void **)crl, CRL_TYPE);
+}
+#endif /* !NO_FILESYSTEM */
+
+
+WOLFSSL_X509_CRL* wolfSSL_d2i_X509_CRL(WOLFSSL_X509_CRL** crl,
+        const unsigned char* in, int len)
+{
+    WOLFSSL_X509_CRL *newcrl = NULL;
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_d2i_X509_CRL");
+
+    if (in == NULL) {
+        WOLFSSL_MSG("Bad argument value");
+    } else {
+        newcrl = (WOLFSSL_X509_CRL*)XMALLOC(sizeof(WOLFSSL_X509_CRL), NULL,
+                DYNAMIC_TYPE_TMP_BUFFER);
+        if (newcrl == NULL){
+            WOLFSSL_MSG("New CRL allocation failed");
+        } else {
+            ret = InitCRL(newcrl, NULL);
+            if (ret < 0) {
+                WOLFSSL_MSG("Init tmp CRL failed");
+            } else {
+                ret = BufferLoadCRL(newcrl, in, len, WOLFSSL_FILETYPE_ASN1,
+                    NO_VERIFY);
+                if (ret != WOLFSSL_SUCCESS) {
+                    WOLFSSL_MSG("Buffer Load CRL failed");
+                } else {
+                    if (crl) {
+                        *crl = newcrl;
+                    }
+                }
+            }
+        }
+    }
+
+    if((ret != WOLFSSL_SUCCESS) && (newcrl != NULL)) {
+        wolfSSL_X509_CRL_free(newcrl);
+        newcrl = NULL;
+    }
+
+    return newcrl;
+}
+
+void wolfSSL_X509_CRL_free(WOLFSSL_X509_CRL *crl)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_CRL_free");
+
+    FreeCRL(crl, 1);
+    return;
+}
+#endif /* HAVE_CRL */
+
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_lastUpdate(WOLFSSL_X509_CRL* crl)
+{
+    (void)crl;
+    WOLFSSL_STUB("X509_CRL_get_lastUpdate");
+    return 0;
+}
+#endif
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_nextUpdate(WOLFSSL_X509_CRL* crl)
+{
+    (void)crl;
+    WOLFSSL_STUB("X509_CRL_get_nextUpdate");
+    return 0;
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_X509_CRL_verify(WOLFSSL_X509_CRL* crl, WOLFSSL_EVP_PKEY* key)
+{
+    (void)crl;
+    (void)key;
+    WOLFSSL_STUB("X509_CRL_verify");
+    return 0;
+}
+#endif
+#endif /* OPENSSL_EXTRA */
+
+#ifdef OPENSSL_EXTRA
+
+/* Gets pointer to X509_STORE that was used to create context.
+ *
+ * Return valid pointer on success, NULL if ctx was NULL or not initialized
+ */
+WOLFSSL_X509_STORE* wolfSSL_X509_STORE_CTX_get0_store(
+        WOLFSSL_X509_STORE_CTX* ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get0_store");
+
+    if (ctx == NULL)
+        return NULL;
+
+    return ctx->store;
+}
+
+WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get0_cert(WOLFSSL_X509_STORE_CTX* ctx)
+{
+    if (ctx == NULL)
+        return NULL;
+
+    return ctx->current_cert;
+}
+
+void wolfSSL_X509_STORE_CTX_set_time(WOLFSSL_X509_STORE_CTX* ctx,
+                                    unsigned long flags,
+                                    time_t t)
+{
+    (void)flags;
+
+    if (ctx == NULL || ctx->param == NULL)
+        return;
+
+    ctx->param->check_time = t;
+    ctx->param->flags |= WOLFSSL_USE_CHECK_TIME;
+}
+
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_X509_STORE_CTX_set_purpose(WOLFSSL_X509_STORE_CTX *ctx,
+                                       int purpose)
+{
+    (void)ctx;
+    (void)purpose;
+    WOLFSSL_STUB("wolfSSL_X509_STORE_CTX_set_purpose");
+    return 0;
+}
+#endif
+#endif /* WOLFSSL_QT || OPENSSL_ALL */
+
+#ifndef NO_WOLFSSL_STUB
+/* Returns default file name and path of config file. However
+   a wolfssl.cnf file is not currently supported */
+char* wolfSSL_CONF_get1_default_config_file(void)
+{
+    WOLFSSL_ENTER("wolfSSL_CONF_get1_default_config_file");
+    WOLFSSL_STUB("CONF_get1_default_config_file");
+    return NULL;
+}
+#endif
+/******************************************************************************
+* wolfSSL_X509_VERIFY_PARAM_set1_host - sets the DNS hostname to name
+* hostnames is cleared if name is NULL or empty.
+*
+* RETURNS:
+*
+*/
+int wolfSSL_X509_VERIFY_PARAM_set1_host(WOLFSSL_X509_VERIFY_PARAM* pParam,
+                                         const char* name,
+                                         unsigned int nameSz)
+{
+    unsigned int sz = 0;
+
+    if (pParam == NULL)
+        return WOLFSSL_FAILURE;
+
+    XMEMSET(pParam->hostName, 0, WOLFSSL_HOST_NAME_MAX);
+
+    if (name == NULL)
+        return WOLFSSL_SUCCESS;
+
+    sz = (unsigned int)XSTRLEN(name);
+
+    /* If name is NUL-terminated, namelen can be set to zero. */
+    if(nameSz == 0 || nameSz > sz)
+        nameSz = sz;
+
+    if (nameSz > 0 && name[nameSz - 1] == '\0')
+        nameSz--;
+
+    if (nameSz > WOLFSSL_HOST_NAME_MAX-1)
+        nameSz = WOLFSSL_HOST_NAME_MAX-1;
+
+    if (nameSz > 0)
+        XMEMCPY(pParam->hostName, name, nameSz);
+
+        pParam->hostName[nameSz] = '\0';
+
+    return WOLFSSL_SUCCESS;
+}
+/******************************************************************************
+* wolfSSL_get0_param - return a pointer to the SSL verification parameters
+*
+* RETURNS:
+* returns pointer to the SSL verification parameters on success,
+* otherwise returns NULL
+*/
+WOLFSSL_X509_VERIFY_PARAM* wolfSSL_get0_param(WOLFSSL* ssl)
+{
+    if (ssl == NULL) {
+        return NULL;
+    }
+    return ssl->param;
+}
+
+/* Set the host flag in the X509_VERIFY_PARAM structure */
+void wolfSSL_X509_VERIFY_PARAM_set_hostflags(WOLFSSL_X509_VERIFY_PARAM* param,
+                                             unsigned int flags)
+{
+    if (param != NULL) {
+        param->hostFlags = flags;
+    }
+}
+
+/* Sets the expected IP address to ipasc.
+ *
+ * param is a pointer to the X509_VERIFY_PARAM structure
+ * ipasc is a NULL-terminated string with N.N.N.N for IPv4 and
+ *       HH:HH ... HH:HH for IPv6. There is no validation performed on the
+ *       parameter, and it must be an exact match with the IP in the cert.
+ *
+ * return 1 for success and 0 for failure*/
+int wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(WOLFSSL_X509_VERIFY_PARAM *param,
+        const char *ipasc)
+{
+    int ret = WOLFSSL_FAILURE;
+
+    if (param != NULL) {
+        if (ipasc == NULL) {
+            param->ipasc[0] = '\0';
+        }
+        else {
+            XSTRNCPY(param->ipasc, ipasc, WOLFSSL_MAX_IPSTR-1);
+            param->ipasc[WOLFSSL_MAX_IPSTR-1] = '\0';
+        }
+        ret = WOLFSSL_SUCCESS;
+    }
+
+    return ret;
+}
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_X509_OBJECT_free_contents(WOLFSSL_X509_OBJECT* obj)
+{
+    (void)obj;
+    WOLFSSL_STUB("X509_OBJECT_free_contents");
+}
+#endif
+
+#ifndef NO_ASN_TIME
+int wolfSSL_X509_cmp_current_time(const WOLFSSL_ASN1_TIME* asnTime)
+{
+    return wolfSSL_X509_cmp_time(asnTime, NULL);
+}
+
+/* return -1 if asnTime is earlier than or equal to cmpTime, and 1 otherwise
+ * return 0 on error
+ */
+int wolfSSL_X509_cmp_time(const WOLFSSL_ASN1_TIME* asnTime, time_t* cmpTime)
+{
+    int ret = WOLFSSL_FAILURE, i = 0;
+    time_t tmpTime, *pTime = &tmpTime;
+    byte data_ptr[MAX_TIME_STRING_SZ], inv = 0;
+    struct tm ts, *tmpTs, *ct;
+#if defined(NEED_TMP_TIME)
+    /* for use with gmtime_r */
+    struct tm tmpTimeStorage;
+
+    tmpTs = &tmpTimeStorage;
+#else
+    tmpTs = NULL;
+#endif
+    (void)tmpTs;
+
+    if (asnTime == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if (cmpTime == NULL) {
+        /* Use current time */
+        *pTime = XTIME(0);
+    }
+    else {
+        pTime = cmpTime;
+    }
+
+    /* Convert ASN1_time to time_t */
+    XMEMSET(&ts, 0, sizeof(struct tm));
+
+    /* Check type */
+    if (asnTime->type == ASN_UTC_TIME) {
+        /* 2-digit year */
+        XMEMCPY(data_ptr, &asnTime->data[i], ASN_UTC_TIME_SIZE);
+        ts.tm_year = (data_ptr[i] - '0') * 10; i++;
+        ts.tm_year += data_ptr[i] - '0'; i++;
+        if (ts.tm_year < 70) {
+            ts.tm_year += 100;
+        }
+    }
+    else if (asnTime->type == ASN_GENERALIZED_TIME) {
+        /* 4-digit year */
+        XMEMCPY(data_ptr, &asnTime->data[i], ASN_GENERALIZED_TIME_SIZE);
+        ts.tm_year = (data_ptr[i] - '0') * 1000; i++;
+        ts.tm_year += (data_ptr[i] - '0') * 100; i++;
+        ts.tm_year += (data_ptr[i] - '0') * 10; i++;
+        ts.tm_year += data_ptr[i] - '0'; i++;
+        ts.tm_year -= 1900;
+    }
+    else {
+        /* Invalid type */
+        inv = 1;
+    }
+
+    if (inv != 1) {
+        ts.tm_mon = (data_ptr[i] - '0') * 10; i++;
+        ts.tm_mon += (data_ptr[i] - '0') - 1; i++; /* January is 0 not 1 */
+        ts.tm_mday = (data_ptr[i] - '0') * 10; i++;
+        ts.tm_mday += (data_ptr[i] - '0'); i++;
+        ts.tm_hour = (data_ptr[i] - '0') * 10; i++;
+        ts.tm_hour += (data_ptr[i] - '0'); i++;
+        ts.tm_min = (data_ptr[i] - '0') * 10; i++;
+        ts.tm_min += (data_ptr[i] - '0'); i++;
+        ts.tm_sec = (data_ptr[i] - '0') * 10; i++;
+        ts.tm_sec += (data_ptr[i] - '0');
+
+        /* Convert to time struct*/
+        ct = XGMTIME(pTime, tmpTs);
+
+        if (ct == NULL)
+            return GETTIME_ERROR;
+
+        /* DateGreaterThan returns 1 for >; 0 for <= */
+        ret = DateGreaterThan(&ts, ct) ? 1 : -1;
+    }
+
+    return ret;
+}
+#endif /* !NO_ASN_TIME */
+
+#if defined(OPENSSL_EXTRA) && !defined(NO_ASN_TIME) && !defined(USER_TIME) && \
+    !defined(TIME_OVERRIDES)
+WOLFSSL_ASN1_TIME *wolfSSL_X509_time_adj_ex(WOLFSSL_ASN1_TIME *asnTime,
+    int offset_day, long offset_sec, time_t *in_tm)
+{
+    /* get current time if in_tm is null */
+    time_t t = in_tm ? *in_tm : XTIME(0);
+    return wolfSSL_ASN1_TIME_adj(asnTime, t, offset_day, offset_sec);
+}
+
+WOLFSSL_ASN1_TIME *wolfSSL_X509_time_adj(WOLFSSL_ASN1_TIME *asnTime,
+    long offset_sec, time_t *in_tm)
+{
+    return wolfSSL_X509_time_adj_ex(asnTime, 0, offset_sec, in_tm);
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_sk_X509_REVOKED_num(WOLFSSL_X509_REVOKED* revoked)
+{
+    (void)revoked;
+    WOLFSSL_STUB("sk_X509_REVOKED_num");
+    return 0;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_X509_REVOKED* wolfSSL_X509_CRL_get_REVOKED(WOLFSSL_X509_CRL* crl)
+{
+    (void)crl;
+    WOLFSSL_STUB("X509_CRL_get_REVOKED");
+    return 0;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_X509_REVOKED* wolfSSL_sk_X509_REVOKED_value(
+                                    WOLFSSL_X509_REVOKED* revoked, int value)
+{
+    (void)revoked;
+    (void)value;
+    WOLFSSL_STUB("sk_X509_REVOKED_value");
+    return 0;
+}
+#endif
+
+/* Used to create a new WOLFSSL_ASN1_INTEGER structure.
+ * returns a pointer to new structure on success and NULL on failure
+ */
+WOLFSSL_ASN1_INTEGER* wolfSSL_ASN1_INTEGER_new(void)
+{
+    WOLFSSL_ASN1_INTEGER* a;
+
+    a = (WOLFSSL_ASN1_INTEGER*)XMALLOC(sizeof(WOLFSSL_ASN1_INTEGER), NULL,
+                                       DYNAMIC_TYPE_OPENSSL);
+    if (a == NULL) {
+        return NULL;
+    }
+
+    XMEMSET(a, 0, sizeof(WOLFSSL_ASN1_INTEGER));
+    a->data    = a->intData;
+    a->dataMax = WOLFSSL_ASN1_INTEGER_MAX;
+    a->length  = 0;
+    return a;
+}
+
+
+/* free's internal elements of WOLFSSL_ASN1_INTEGER and free's "in" itself */
+void wolfSSL_ASN1_INTEGER_free(WOLFSSL_ASN1_INTEGER* in)
+{
+    if (in != NULL) {
+        if (in->isDynamic) {
+            XFREE(in->data, NULL, DYNAMIC_TYPE_OPENSSL);
+        }
+        XFREE(in, NULL, DYNAMIC_TYPE_OPENSSL);
+    }
+}
+
+
+/* Duplicate all WOLFSSL_ASN1_INTEGER members from src to dup
+ *  src : WOLFSSL_ASN1_INTEGER to duplicate
+ *  Returns pointer to duplicate WOLFSSL_ASN1_INTEGER
+ */
+WOLFSSL_ASN1_INTEGER* wolfSSL_ASN1_INTEGER_dup(const WOLFSSL_ASN1_INTEGER* src)
+{
+    WOLFSSL_ASN1_INTEGER* dup;
+    WOLFSSL_ENTER("wolfSSL_ASN1_INTEGER_dup");
+    if (!src)
+        return NULL;
+
+    dup = wolfSSL_ASN1_INTEGER_new();
+
+    if (dup == NULL)
+        return NULL;
+
+    dup->negative  = src->negative;
+    dup->dataMax   = src->dataMax;
+    dup->isDynamic = src->isDynamic;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+    dup->length    = src->length;
+#endif
+    XSTRNCPY((char*)dup->intData,(const char*)src->intData,WOLFSSL_ASN1_INTEGER_MAX);
+
+    if (dup->isDynamic && src->data && dup->dataMax) {
+        dup->data = (unsigned char*)
+            XMALLOC(src->dataMax,NULL,DYNAMIC_TYPE_OPENSSL);
+        if (dup->data == NULL) {
+            wolfSSL_ASN1_INTEGER_free(dup);
+            return NULL;
+        }
+        XMEMCPY(dup->data,src->data,dup->dataMax);
+    }
+    return dup;
+}
+
+
+/* sets the value of WOLFSSL_ASN1_INTEGER a to the long value v. */
+int wolfSSL_ASN1_INTEGER_set(WOLFSSL_ASN1_INTEGER *a, long v)
+{
+    int ret = WOLFSSL_SUCCESS; /* return 1 for success and 0 for failure */
+    int j;
+    unsigned int i = 0;
+    unsigned char tmp[sizeof(long)+1] = {0};
+
+    if (a != NULL) {
+        /* dynamically create data buffer, +2 for type and length */
+        a->data = (unsigned char*)XMALLOC((sizeof(long)+1) + 2, NULL,
+                DYNAMIC_TYPE_OPENSSL);
+        if (a->data == NULL) {
+            wolfSSL_ASN1_INTEGER_free(a);
+            ret = WOLFSSL_FAILURE;
+        }
+        else {
+            a->dataMax   = (int)(sizeof(long)+1) + 2;
+            a->isDynamic = 1;
+        }
+    }
+    else {
+        /* Invalid parameter */
+        ret = WOLFSSL_FAILURE;
+    }
+
+
+    if (ret != WOLFSSL_FAILURE) {
+        /* Set type */
+        a->data[i++] = ASN_INTEGER;
+
+        /* Check for negative */
+        if (v < 0) {
+            a->negative = 1;
+            v *= -1;
+        }
+
+        /* Create char buffer */
+        for (j = 0; j < (int)sizeof(long); j++) {
+            if (v == 0) {
+                break;
+            }
+            tmp[j] = (unsigned char)(v & 0xff);
+            v >>= 8;
+        }
+
+        /* Set length */
+        a->data[i++] = (unsigned char)((j == 0) ? ++j : j);
+        /* +2 for type and length */
+        a->length = j + 2;
+
+        /* Copy to data */
+        for (; j > 0; j--) {
+            a->data[i++] = tmp[j-1];
+        }
+    }
+
+    return ret;
+}
+
+
+WOLFSSL_ASN1_INTEGER* wolfSSL_X509_get_serialNumber(WOLFSSL_X509* x509)
+{
+    WOLFSSL_ASN1_INTEGER* a;
+    int i = 0;
+
+    WOLFSSL_ENTER("wolfSSL_X509_get_serialNumber");
+
+    a = wolfSSL_ASN1_INTEGER_new();
+    if (a == NULL)
+        return NULL;
+
+    /* Make sure there is space for the data, ASN.1 type and length. */
+    if (x509->serialSz > (WOLFSSL_ASN1_INTEGER_MAX - 2)) {
+        /* dynamically create data buffer, +2 for type and length */
+        a->data = (unsigned char*)XMALLOC(x509->serialSz + 2, NULL,
+                DYNAMIC_TYPE_OPENSSL);
+        if (a->data == NULL) {
+            wolfSSL_ASN1_INTEGER_free(a);
+            return NULL;
+        }
+        a->dataMax   = x509->serialSz + 2;
+        a->isDynamic = 1;
+    } else {
+        /* Use array instead of dynamic memory */
+        a->data    = a->intData;
+        a->dataMax = WOLFSSL_ASN1_INTEGER_MAX;
+    }
+
+    #ifdef WOLFSSL_QT
+        XMEMCPY(&a->data[i], x509->serial, x509->serialSz);
+        a->length = x509->serialSz;
+    #else
+        a->data[i++] = ASN_INTEGER;
+        i += SetLength(x509->serialSz, a->data + i);
+        XMEMCPY(&a->data[i], x509->serial, x509->serialSz);
+        a->length = x509->serialSz + 2;
+    #endif
+
+    x509->serialNumber = a;
+
+    return a;
+}
+
+#endif /* OPENSSL_EXTRA */
+
+#if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || \
+    defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
+#ifndef NO_ASN_TIME
+int wolfSSL_ASN1_TIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_TIME* asnTime)
+{
+    char buf[MAX_TIME_STRING_SZ];
+    int  ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_ASN1_TIME_print");
+
+    if (bio == NULL || asnTime == NULL) {
+        WOLFSSL_MSG("NULL function argument");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (wolfSSL_ASN1_TIME_to_string((WOLFSSL_ASN1_TIME*)asnTime, buf,
+                sizeof(buf)) == NULL) {
+        XMEMSET(buf, 0, MAX_TIME_STRING_SZ);
+        XMEMCPY(buf, "Bad time value", 14);
+        ret = WOLFSSL_FAILURE;
+    }
+
+    if (wolfSSL_BIO_write(bio, buf, (int)XSTRLEN(buf)) <= 0) {
+        WOLFSSL_MSG("Unable to write to bio");
+        return WOLFSSL_FAILURE;
+    }
+
+    return ret;
+}
+
+char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* t, char* buf, int len)
+{
+    WOLFSSL_ENTER("wolfSSL_ASN1_TIME_to_string");
+
+    if (t == NULL || buf == NULL || len < 5) {
+        WOLFSSL_MSG("Bad argument");
+        return NULL;
+    }
+
+    if (t->length > len) {
+        WOLFSSL_MSG("Length of date is longer then buffer");
+        return NULL;
+    }
+
+    if (!GetTimeString(t->data, t->type, buf, len)) {
+        return NULL;
+    }
+
+    return buf;
+}
+#endif /* !NO_ASN_TIME */
+#endif /* WOLFSSL_MYSQL_COMPATIBLE || WOLFSSL_NGINX || WOLFSSL_HAPROXY ||
+    OPENSSL_EXTRA*/
+
+
+#ifdef OPENSSL_EXTRA
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_ASN1_INTEGER_cmp(const WOLFSSL_ASN1_INTEGER* a,
+                            const WOLFSSL_ASN1_INTEGER* b)
+{
+    (void)a;
+    (void)b;
+    WOLFSSL_STUB("ASN1_INTEGER_cmp");
+    return 0;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+long wolfSSL_ASN1_INTEGER_get(const WOLFSSL_ASN1_INTEGER* i)
+{
+    (void)i;
+    WOLFSSL_STUB("ASN1_INTEGER_get");
+    return 0;
+}
+#endif
+
+/* get X509_STORE_CTX ex_data, max idx is MAX_EX_DATA */
+void* wolfSSL_X509_STORE_CTX_get_ex_data(WOLFSSL_X509_STORE_CTX* ctx, int idx)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_ex_data");
+    #if defined(HAVE_EX_DATA) || defined(FORTRESS)
+    if (ctx != NULL) {
+        return wolfSSL_CRYPTO_get_ex_data(&ctx->ex_data, idx);
+    }
+    #else
+    (void)ctx;
+    (void)idx;
+    #endif
+    return NULL;
+}
+
+
+/* set X509_STORE_CTX ex_data, max idx is MAX_EX_DATA. Return WOLFSSL_SUCCESS
+ * on success, WOLFSSL_FAILURE on error. */
+int wolfSSL_X509_STORE_CTX_set_ex_data(WOLFSSL_X509_STORE_CTX* ctx, int idx,
+                                       void *data)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_ex_data");
+    #if defined(HAVE_EX_DATA) || defined(FORTRESS)
+    if (ctx != NULL)
+    {
+        return wolfSSL_CRYPTO_set_ex_data(&ctx->ex_data, idx, data);
+    }
+    #else
+    (void)ctx;
+    (void)idx;
+    (void)data;
+    #endif
+    return WOLFSSL_FAILURE;
+}
+
+#if defined(WOLFSSL_APACHE_HTTPD) || defined(OPENSSL_ALL)
+void wolfSSL_X509_STORE_CTX_set_depth(WOLFSSL_X509_STORE_CTX* ctx, int depth)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_depth");
+    if (ctx)
+        ctx->depth = depth;
+}
+#endif
+
+
+WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get0_current_issuer(
+        WOLFSSL_X509_STORE_CTX* ctx)
+{
+    int ret;
+    WOLFSSL_X509* issuer;
+
+    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get0_current_issuer");
+
+    if (ctx == NULL) {
+        return NULL;
+    }
+
+    ret = wolfSSL_X509_STORE_CTX_get1_issuer(&issuer, ctx, ctx->current_cert);
+    if (ret == WOLFSSL_SUCCESS) {
+        return issuer;
+    }
+
+    return NULL;
+}
+
+
+/* Gets an index to store SSL structure at.
+ *
+ * Returns positive index on success and negative values on failure
+ */
+int wolfSSL_get_ex_data_X509_STORE_CTX_idx(void)
+{
+    WOLFSSL_ENTER("wolfSSL_get_ex_data_X509_STORE_CTX_idx");
+
+    /* store SSL at index 0 */
+    return 0;
+}
+
+
+/* Set an error stat in the X509 STORE CTX
+ *
+ */
+void wolfSSL_X509_STORE_CTX_set_error(WOLFSSL_X509_STORE_CTX* ctx, int er)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_error");
+
+    if (ctx != NULL) {
+        ctx->error = er;
+    }
+}
+
+/* Set the error depth in the X509 STORE CTX */
+void wolfSSL_X509_STORE_CTX_set_error_depth(WOLFSSL_X509_STORE_CTX* ctx,
+                                                                      int depth)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_error_depth");
+
+    if (ctx != NULL) {
+        ctx->error_depth = depth;
+    }
+}
+
+/* Sets a function callback that will send information about the state of all
+ * WOLFSSL objects that have been created by the WOLFSSL_CTX structure passed
+ * in.
+ *
+ * ctx WOLFSSL_CTX structure to set callback function in
+ * f   callback function to use
+ */
+void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX* ctx,
+       void (*f)(const WOLFSSL* ssl, int type, int val))
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_set_info_callback");
+    if (ctx == NULL) {
+        WOLFSSL_MSG("Bad function argument");
+    }
+    else {
+        ctx->CBIS = f;
+    }
+}
+
+
+unsigned long wolfSSL_ERR_peek_error(void)
+{
+    WOLFSSL_ENTER("wolfSSL_ERR_peek_error");
+
+    return wolfSSL_ERR_peek_error_line_data(NULL, NULL, NULL, NULL);
+}
+
+int wolfSSL_ERR_GET_LIB(unsigned long err)
+{
+    switch (err) {
+    case PEM_R_NO_START_LINE:
+    case PEM_R_PROBLEMS_GETTING_PASSWORD:
+    case PEM_R_BAD_PASSWORD_READ:
+    case PEM_R_BAD_DECRYPT:
+        return ERR_LIB_PEM;
+    case EVP_R_BAD_DECRYPT:
+    case EVP_R_BN_DECODE_ERROR:
+    case EVP_R_DECODE_ERROR:
+    case EVP_R_PRIVATE_KEY_DECODE_ERROR:
+        return ERR_LIB_EVP;
+    default:
+        return 0;
+    }
+}
+
+/* This function is to find global error values that are the same through out
+ * all library version. With wolfSSL having only one set of error codes the
+ * return value is pretty straight forward. The only thing needed is all wolfSSL
+ * error values are typically negative.
+ *
+ * Returns the error reason
+ */
+int wolfSSL_ERR_GET_REASON(unsigned long err)
+{
+    int ret = (int)err;
+
+    WOLFSSL_ENTER("wolfSSL_ERR_GET_REASON");
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+    /* Nginx looks for this error to know to stop parsing certificates. */
+    if (err == ((ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE))
+        return PEM_R_NO_START_LINE;
+#endif
+
+    /* check if error value is in range of wolfSSL errors */
+    ret = 0 - ret; /* setting as negative value */
+    /* wolfCrypt range is less than MAX (-100)
+       wolfSSL range is MIN (-300) and lower */
+    if (ret < MAX_CODE_E && ret > MIN_CODE_E) {
+        return ret;
+    }
+    else {
+        WOLFSSL_MSG("Not in range of typical error values");
+        ret = (int)err;
+    }
+
+    return ret;
+}
+
+
+/* returns a string that describes the alert
+ *
+ * alertID the alert value to look up
+ */
+const char* wolfSSL_alert_type_string_long(int alertID)
+{
+    WOLFSSL_ENTER("wolfSSL_alert_type_string_long");
+
+    switch (alertID) {
+        case close_notify:
+            {
+                static const char close_notify_str[] =
+                    "close_notify";
+                return close_notify_str;
+            }
+
+        case unexpected_message:
+            {
+                static const char unexpected_message_str[] =
+                    "unexpected_message";
+                return unexpected_message_str;
+            }
+
+        case bad_record_mac:
+            {
+                static const char bad_record_mac_str[] =
+                    "bad_record_mac";
+                return bad_record_mac_str;
+            }
+
+        case record_overflow:
+            {
+                static const char record_overflow_str[] =
+                    "record_overflow";
+                return record_overflow_str;
+            }
+
+        case decompression_failure:
+            {
+                static const char decompression_failure_str[] =
+                    "decompression_failure";
+                return decompression_failure_str;
+            }
+
+        case handshake_failure:
+            {
+                static const char handshake_failure_str[] =
+                    "handshake_failure";
+                return handshake_failure_str;
+            }
+
+        case no_certificate:
+            {
+                static const char no_certificate_str[] =
+                    "no_certificate";
+                return no_certificate_str;
+            }
+
+        case bad_certificate:
+            {
+                static const char bad_certificate_str[] =
+                    "bad_certificate";
+                return bad_certificate_str;
+            }
+
+        case unsupported_certificate:
+            {
+                static const char unsupported_certificate_str[] =
+                    "unsupported_certificate";
+                return unsupported_certificate_str;
+            }
+
+        case certificate_revoked:
+            {
+                static const char certificate_revoked_str[] =
+                    "certificate_revoked";
+                return certificate_revoked_str;
+            }
+
+        case certificate_expired:
+            {
+                static const char certificate_expired_str[] =
+                    "certificate_expired";
+                return certificate_expired_str;
+            }
+
+        case certificate_unknown:
+            {
+                static const char certificate_unknown_str[] =
+                    "certificate_unknown";
+                return certificate_unknown_str;
+            }
+
+        case illegal_parameter:
+            {
+                static const char illegal_parameter_str[] =
+                    "illegal_parameter";
+                return illegal_parameter_str;
+            }
+
+        case unknown_ca:
+            {
+                static const char unknown_ca_str[] =
+                    "unknown_ca";
+                return unknown_ca_str;
+            }
+
+        case decode_error:
+            {
+                static const char decode_error_str[] =
+                    "decode_error";
+                return decode_error_str;
+            }
+
+        case decrypt_error:
+            {
+                static const char decrypt_error_str[] =
+                    "decrypt_error";
+                return decrypt_error_str;
+            }
+
+    #ifdef WOLFSSL_MYSQL_COMPATIBLE
+    /* catch name conflict for enum protocol with MYSQL build */
+        case wc_protocol_version:
+            {
+                static const char wc_protocol_version_str[] =
+                    "wc_protocol_version";
+                return wc_protocol_version_str;
+            }
+
+    #else
+        case protocol_version:
+            {
+                static const char protocol_version_str[] =
+                    "protocol_version";
+                return protocol_version_str;
+            }
+
+    #endif
+        case no_renegotiation:
+            {
+                static const char no_renegotiation_str[] =
+                    "no_renegotiation";
+                return no_renegotiation_str;
+            }
+
+        case unrecognized_name:
+            {
+                static const char unrecognized_name_str[] =
+                    "unrecognized_name";
+                return unrecognized_name_str;
+            }
+
+        case bad_certificate_status_response:
+            {
+                static const char bad_certificate_status_response_str[] =
+                    "bad_certificate_status_response";
+                return bad_certificate_status_response_str;
+            }
+
+        case no_application_protocol:
+            {
+                static const char no_application_protocol_str[] =
+                    "no_application_protocol";
+                return no_application_protocol_str;
+            }
+
+        default:
+            WOLFSSL_MSG("Unknown Alert");
+            return NULL;
+    }
+}
+
+
+const char* wolfSSL_alert_desc_string_long(int alertID)
+{
+    WOLFSSL_ENTER("wolfSSL_alert_desc_string_long");
+    return wolfSSL_alert_type_string_long(alertID);
+}
+
+
+/* Gets the current state of the WOLFSSL structure
+ *
+ * ssl WOLFSSL structure to get state of
+ *
+ * Returns a human readable string of the WOLFSSL structure state
+ */
+const char* wolfSSL_state_string_long(const WOLFSSL* ssl)
+{
+
+    static const char* OUTPUT_STR[14][6][3] = {
+        {
+            {"SSLv3 Initialization","SSLv3 Initialization","SSLv3 Initialization"},
+            {"TLSv1 Initialization","TLSv2 Initialization","TLSv2 Initialization"},
+            {"TLSv1_1 Initialization","TLSv1_1 Initialization","TLSv1_1 Initialization"},
+            {"TLSv1_2 Initialization","TLSv1_2 Initialization","TLSv1_2 Initialization"},
+            {"DTLSv1 Initialization","DTLSv1 Initialization","DTLSv1 Initialization"},
+            {"DTLSv1_2 Initialization","DTLSv1_2 Initialization","DTLSv1_2 Initialization"},
+        },
+        {
+            {"SSLv3 read Server Hello Verify Request",
+             "SSLv3 write Server Hello Verify Request",
+             "SSLv3 Server Hello Verify Request"},
+            {"TLSv1 read Server Hello Verify Request",
+             "TLSv1 write Server Hello Verify Request",
+             "TLSv1 Server Hello Verify Request"},
+            {"TLSv1_1 read Server Hello Verify Request",
+            "TLSv1_1 write Server Hello Verify Request",
+             "TLSv1_1 Server Hello Verify Request"},
+            {"TLSv1_2 read Server Hello Verify Request",
+            "TLSv1_2 write Server Hello Verify Request",
+             "TLSv1_2 Server Hello Verify Request"},
+            {"DTLSv1 read Server Hello Verify Request",
+             "DTLSv1 write Server Hello Verify Request",
+             "DTLSv1 Server Hello Verify Request"},
+            {"DTLSv1_2 read Server Hello Verify Request",
+             "DTLSv1_2 write Server Hello Verify Request",
+             "DTLSv1_2 Server Hello Verify Request"},
+        },
+        {
+            {"SSLv3 read Server Hello",
+             "SSLv3 write Server Hello",
+             "SSLv3 Server Hello"},
+            {"TLSv1 read Server Hello",
+             "TLSv1 write Server Hello",
+             "TLSv1 Server Hello"},
+            {"TLSv1_1 read Server Hello",
+            "TLSv1_1 write Server Hello",
+             "TLSv1_1 Server Hello"},
+            {"TLSv1_2 read Server Hello",
+            "TLSv1_2 write Server Hello",
+             "TLSv1_2 Server Hello"},
+            {"DTLSv1 read Server Hello",
+            "DTLSv1 write Server Hello",
+             "DTLSv1 Server Hello"},
+            {"DTLSv1_2 read Server Hello"
+             "DTLSv1_2 write Server Hello",
+             "DTLSv1_2 Server Hello",
+            },
+        },
+        {
+            {"SSLv3 read Server Session Ticket",
+             "SSLv3 write Server Session Ticket",
+             "SSLv3 Server Session Ticket"},
+            {"TLSv1 read Server Session Ticket",
+             "TLSv1 write Server Session Ticket",
+             "TLSv1 Server Session Ticket"},
+            {"TLSv1_1 read Server Session Ticket",
+             "TLSv1_1 write Server Session Ticket",
+             "TLSv1_1 Server Session Ticket"},
+            {"TLSv1_2 read Server Session Ticket",
+             "TLSv1_2 write Server Session Ticket",
+             "TLSv1_2 Server Session Ticket"},
+            {"DTLSv1 read Server Session Ticket",
+             "DTLSv1 write Server Session Ticket",
+             "DTLSv1 Server Session Ticket"},
+            {"DTLSv1_2 read Server Session Ticket",
+             "DTLSv1_2 write Server Session Ticket",
+             "DTLSv1_2 Server Session Ticket"},
+        },
+        {
+            {"SSLv3 read Server Cert",
+             "SSLv3 write Server Cert",
+             "SSLv3 Server Cert"},
+            {"TLSv1 read Server Cert",
+             "TLSv1 write Server Cert",
+             "TLSv1 Server Cert"},
+            {"TLSv1_1 read Server Cert",
+             "TLSv1_1 write Server Cert",
+             "TLSv1_1 Server Cert"},
+            {"TLSv1_2 read Server Cert",
+             "TLSv1_2 write Server Cert",
+             "TLSv1_2 Server Cert"},
+            {"DTLSv1 read Server Cert",
+             "DTLSv1 write Server Cert",
+             "DTLSv1 Server Cert"},
+            {"DTLSv1_2 read Server Cert",
+             "DTLSv1_2 write Server Cert",
+             "DTLSv1_2 Server Cert"},
+        },
+        {
+            {"SSLv3 read Server Key Exchange",
+             "SSLv3 write Server Key Exchange",
+             "SSLv3 Server Key Exchange"},
+            {"TLSv1 read Server Key Exchange",
+             "TLSv1 write Server Key Exchange",
+             "TLSv1 Server Key Exchange"},
+            {"TLSv1_1 read Server Key Exchange",
+             "TLSv1_1 write Server Key Exchange",
+             "TLSv1_1 Server Key Exchange"},
+            {"TLSv1_2 read Server Key Exchange",
+             "TLSv1_2 write Server Key Exchange",
+             "TLSv1_2 Server Key Exchange"},
+            {"DTLSv1 read Server Key Exchange",
+             "DTLSv1 write Server Key Exchange",
+             "DTLSv1 Server Key Exchange"},
+            {"DTLSv1_2 read Server Key Exchange",
+             "DTLSv1_2 write Server Key Exchange",
+             "DTLSv1_2 Server Key Exchange"},
+        },
+        {
+            {"SSLv3 read Server Hello Done",
+             "SSLv3 write Server Hello Done",
+             "SSLv3 Server Hello Done"},
+            {"TLSv1 read Server Hello Done",
+             "TLSv1 write Server Hello Done",
+             "TLSv1 Server Hello Done"},
+            {"TLSv1_1 read Server Hello Done",
+             "TLSv1_1 write Server Hello Done",
+             "TLSv1_1 Server Hello Done"},
+            {"TLSv1_2 read Server Hello Done",
+             "TLSv1_2 write Server Hello Done",
+             "TLSv1_2 Server Hello Done"},
+            {"DTLSv1 read Server Hello Done",
+             "DTLSv1 write Server Hello Done",
+             "DTLSv1 Server Hello Done"},
+            {"DTLSv1_2 read Server Hello Done",
+             "DTLSv1_2 write Server Hello Done",
+             "DTLSv1_2 Server Hello Done"},
+        },
+        {
+            {"SSLv3 read Server Change CipherSpec",
+             "SSLv3 write Server Change CipherSpec",
+             "SSLv3 Server Change CipherSpec"},
+            {"TLSv1 read Server Change CipherSpec",
+             "TLSv1 write Server Change CipherSpec",
+             "TLSv1 Server Change CipherSpec"},
+            {"TLSv1_1 read Server Change CipherSpec",
+             "TLSv1_1 write Server Change CipherSpec",
+             "TLSv1_1 Server Change CipherSpec"},
+            {"TLSv1_2 read Server Change CipherSpec",
+             "TLSv1_2 write Server Change CipherSpec",
+             "TLSv1_2 Server Change CipherSpec"},
+            {"DTLSv1 read Server Change CipherSpec",
+             "DTLSv1 write Server Change CipherSpec",
+             "DTLSv1 Server Change CipherSpec"},
+            {"DTLSv1_2 read Server Change CipherSpec",
+             "DTLSv1_2 write Server Change CipherSpec",
+             "DTLSv1_2 Server Change CipherSpec"},
+        },
+        {
+            {"SSLv3 read Server Finished",
+             "SSLv3 write Server Finished",
+             "SSLv3 Server Finished"},
+            {"TLSv1 read Server Finished",
+             "TLSv1 write Server Finished",
+             "TLSv1 Server Finished"},
+            {"TLSv1_1 read Server Finished",
+             "TLSv1_1 write Server Finished",
+             "TLSv1_1 Server Finished"},
+            {"TLSv1_2 read Server Finished",
+             "TLSv1_2 write Server Finished",
+             "TLSv1_2 Server Finished"},
+            {"DTLSv1 read Server Finished",
+             "DTLSv1 write Server Finished",
+             "DTLSv1 Server Finished"},
+            {"DTLSv1_2 read Server Finished",
+             "DTLSv1_2 write Server Finished",
+             "DTLSv1_2 Server Finished"},
+        },
+        {
+            {"SSLv3 read Client Hello",
+             "SSLv3 write Client Hello",
+             "SSLv3 Client Hello"},
+            {"TLSv1 read Client Hello",
+             "TLSv1 write Client Hello",
+             "TLSv1 Client Hello"},
+            {"TLSv1_1 read Client Hello",
+             "TLSv1_1 write Client Hello",
+             "TLSv1_1 Client Hello"},
+            {"TLSv1_2 read Client Hello",
+             "TLSv1_2 write Client Hello",
+             "TLSv1_2 Client Hello"},
+            {"DTLSv1 read Client Hello",
+             "DTLSv1 write Client Hello",
+             "DTLSv1 Client Hello"},
+            {"DTLSv1_2 read Client Hello",
+             "DTLSv1_2 write Client Hello",
+             "DTLSv1_2 Client Hello"},
+        },
+        {
+            {"SSLv3 read Client Key Exchange",
+             "SSLv3 write Client Key Exchange",
+             "SSLv3 Client Key Exchange"},
+            {"TLSv1 read Client Key Exchange",
+             "TLSv1 write Client Key Exchange",
+             "TLSv1 Client Key Exchange"},
+            {"TLSv1_1 read Client Key Exchange",
+             "TLSv1_1 write Client Key Exchange",
+             "TLSv1_1 Client Key Exchange"},
+            {"TLSv1_2 read Client Key Exchange",
+             "TLSv1_2 write Client Key Exchange",
+             "TLSv1_2 Client Key Exchange"},
+            {"DTLSv1 read Client Key Exchange",
+             "DTLSv1 write Client Key Exchange",
+             "DTLSv1 Client Key Exchange"},
+            {"DTLSv1_2 read Client Key Exchange",
+             "DTLSv1_2 write Client Key Exchange",
+             "DTLSv1_2 Client Key Exchange"},
+        },
+        {
+            {"SSLv3 read Client Change CipherSpec",
+             "SSLv3 write Client Change CipherSpec",
+             "SSLv3 Client Change CipherSpec"},
+            {"TLSv1 read Client Change CipherSpec",
+             "TLSv1 write Client Change CipherSpec",
+             "TLSv1 Client Change CipherSpec"},
+            {"TLSv1_1 read Client Change CipherSpec",
+             "TLSv1_1 write Client Change CipherSpec",
+             "TLSv1_1 Client Change CipherSpec"},
+            {"TLSv1_2 read Client Change CipherSpec",
+             "TLSv1_2 write Client Change CipherSpec",
+             "TLSv1_2 Client Change CipherSpec"},
+            {"DTLSv1 read Client Change CipherSpec",
+             "DTLSv1 write Client Change CipherSpec",
+             "DTLSv1 Client Change CipherSpec"},
+            {"DTLSv1_2 read Client Change CipherSpec",
+             "DTLSv1_2 write Client Change CipherSpec",
+             "DTLSv1_2 Client Change CipherSpec"},
+        },
+        {
+            {"SSLv3 read Client Finished",
+             "SSLv3 write Client Finished",
+             "SSLv3 Client Finished"},
+            {"TLSv1 read Client Finished",
+             "TLSv1 write Client Finished",
+             "TLSv1 Client Finished"},
+            {"TLSv1_1 read Client Finished",
+             "TLSv1_1 write Client Finished",
+             "TLSv1_1 Client Finished"},
+            {"TLSv1_2 read Client Finished",
+             "TLSv1_2 write Client Finished",
+             "TLSv1_2 Client Finished"},
+            {"DTLSv1 read Client Finished",
+             "DTLSv1 write Client Finished",
+             "DTLSv1 Client Finished"},
+            {"DTLSv1_2 read Client Finished",
+             "DTLSv1_2 write Client Finished",
+             "DTLSv1_2 Client Finished"},
+        },
+        {
+            {"SSLv3 Handshake Done",
+             "SSLv3 Handshake Done",
+             "SSLv3 Handshake Done"},
+            {"TLSv1 Handshake Done",
+             "TLSv1 Handshake Done",
+             "TLSv1 Handshake Done"},
+            {"TLSv1_1 Handshake Done",
+             "TLSv1_1 Handshake Done",
+             "TLSv1_1 Handshake Done"},
+            {"TLSv1_2 Handshake Done",
+             "TLSv1_2 Handshake Done",
+             "TLSv1_2 Handshake Done"},
+            {"DTLSv1 Handshake Done",
+             "DTLSv1 Handshake Done",
+             "DTLSv1 Handshake Done"},
+            {"DTLSv1_2 Handshake Done"
+             "DTLSv1_2 Handshake Done"
+             "DTLSv1_2 Handshake Done"}
+        }
+    };
+    enum ProtocolVer {
+        SSL_V3 = 0,
+        TLS_V1,
+        TLS_V1_1,
+        TLS_V1_2,
+        DTLS_V1,
+        DTLS_V1_2,
+        UNKNOWN = 100
+    };
+
+    enum IOMode {
+        SS_READ = 0,
+        SS_WRITE,
+        SS_NEITHER
+    };
+
+    enum SslState {
+        ss_null_state = 0,
+        ss_server_helloverify,
+        ss_server_hello,
+        ss_sessionticket,
+        ss_server_cert,
+        ss_server_keyexchange,
+        ss_server_hellodone,
+        ss_server_changecipherspec,
+        ss_server_finished,
+        ss_client_hello,
+        ss_client_keyexchange,
+        ss_client_changecipherspec,
+        ss_client_finished,
+        ss_handshake_done
+    };
+
+    int protocol = 0;
+    int cbmode = 0;
+    int state = 0;
+
+    WOLFSSL_ENTER("wolfSSL_state_string_long");
+    if (ssl == NULL) {
+        WOLFSSL_MSG("Null argument passed in");
+        return NULL;
+    }
+
+    /* Get state of callback */
+    if (ssl->cbmode == SSL_CB_MODE_WRITE){
+        cbmode =  SS_WRITE;
+    } else if (ssl->cbmode == SSL_CB_MODE_READ){
+        cbmode =  SS_READ;
+    } else {
+        cbmode =  SS_NEITHER;
+    }
+
+    /* Get protocol version */
+    switch (ssl->version.major){
+        case SSLv3_MAJOR:
+            switch (ssl->version.minor){
+                case TLSv1_MINOR:
+                    protocol = TLS_V1;
+                    break;
+                case TLSv1_1_MINOR:
+                    protocol = TLS_V1_1;
+                    break;
+                case TLSv1_2_MINOR:
+                    protocol = TLS_V1_2;
+                    break;
+                case SSLv3_MINOR:
+                    protocol = SSL_V3;
+                    break;
+                default:
+                    protocol = UNKNOWN;
+            }
+            break;
+        case DTLS_MAJOR:
+            switch (ssl->version.minor){
+        case DTLS_MINOR:
+            protocol = DTLS_V1;
+            break;
+        case DTLSv1_2_MINOR:
+            protocol = DTLS_V1_2;
+            break;
+        default:
+            protocol = UNKNOWN;
+    }
+    break;
+    default:
+        protocol = UNKNOWN;
+    }
+
+    /* accept process */
+    if (ssl->cbmode == SSL_CB_MODE_READ){
+        state = ssl->cbtype;
+        switch (state) {
+            case hello_verify_request:
+                state = ss_server_helloverify;
+                break;
+            case session_ticket:
+                state = ss_sessionticket;
+                break;
+            case server_hello:
+                state = ss_server_hello;
+                break;
+            case server_hello_done:
+                state = ss_server_hellodone;
+                break;
+            case certificate:
+                state = ss_server_cert;
+                break;
+            case server_key_exchange:
+                state = ss_server_keyexchange;
+                break;
+            case client_hello:
+                state = ss_client_hello;
+                break;
+            case client_key_exchange:
+                state = ss_client_keyexchange;
+                break;
+            case finished:
+                if (ssl->options.side == WOLFSSL_SERVER_END)
+                    state = ss_client_finished;
+                else if (ssl->options.side == WOLFSSL_CLIENT_END)
+                    state = ss_server_finished;
+                else {
+                    WOLFSSL_MSG("Unknown State");
+                    state = ss_null_state;
+                }
+                break;
+            default:
+                WOLFSSL_MSG("Unknown State");
+                state = ss_null_state;
+        }
+    } else {
+        /* Send process */
+        if (ssl->options.side == WOLFSSL_SERVER_END)
+            state = ssl->options.serverState;
+        else
+            state = ssl->options.clientState;
+
+        switch(state){
+            case SERVER_HELLOVERIFYREQUEST_COMPLETE:
+                state = ss_server_helloverify;
+                break;
+            case SERVER_HELLO_COMPLETE:
+                state = ss_server_hello;
+                break;
+            case SERVER_CERT_COMPLETE:
+                state = ss_server_cert;
+                break;
+            case SERVER_KEYEXCHANGE_COMPLETE:
+                state = ss_server_keyexchange;
+                break;
+            case SERVER_HELLODONE_COMPLETE:
+                state = ss_server_hellodone;
+                break;
+            case SERVER_CHANGECIPHERSPEC_COMPLETE:
+                state = ss_server_changecipherspec;
+                break;
+            case SERVER_FINISHED_COMPLETE:
+                state = ss_server_finished;
+                break;
+            case CLIENT_HELLO_COMPLETE:
+                state = ss_client_hello;
+                break;
+            case CLIENT_KEYEXCHANGE_COMPLETE:
+                state = ss_client_keyexchange;
+                break;
+            case CLIENT_CHANGECIPHERSPEC_COMPLETE:
+                state = ss_client_changecipherspec;
+                break;
+            case CLIENT_FINISHED_COMPLETE:
+                state = ss_client_finished;
+                break;
+            case HANDSHAKE_DONE:
+                state = ss_handshake_done;
+                break;
+            default:
+                WOLFSSL_MSG("Unknown State");
+                state = ss_null_state;
+        }
+    }
+
+    if (protocol == UNKNOWN)
+        return NULL;
+    else
+        return OUTPUT_STR[state][protocol][cbmode];
+}
+
+/*
+ * Sets default PEM callback password if null is passed into
+ * the callback parameter of a PEM_read_bio_* function.
+ *
+ * Returns callback phrase size on success or WOLFSSL_FAILURE otherwise.
+ */
+int wolfSSL_PEM_def_callback(char* name, int num, int w, void* key)
+{
+    int sz;
+    (void)w;
+    WOLFSSL_ENTER("wolfSSL_PEM_def_callback");
+
+    /* We assume that the user passes a default password as userdata */
+    if (key) {
+        sz = (int)XSTRLEN((const char*)key);
+        sz = (sz > num) ? num : sz;
+        XMEMCPY(name, key, sz);
+        return sz;
+    } else {
+        WOLFSSL_MSG("Error, default password cannot be created.");
+        return WOLFSSL_FAILURE;
+    }
+}
+
+#endif /* OPENSSL_EXTRA */
+
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+static long wolf_set_options(long old_op, long op)
+{
+    /* if SSL_OP_ALL then turn all bug workarounds on */
+    if ((op & SSL_OP_ALL) == SSL_OP_ALL) {
+        WOLFSSL_MSG("\tSSL_OP_ALL");
+    }
+
+    /* by default cookie exchange is on with DTLS */
+    if ((op & SSL_OP_COOKIE_EXCHANGE) == SSL_OP_COOKIE_EXCHANGE) {
+        WOLFSSL_MSG("\tSSL_OP_COOKIE_EXCHANGE : on by default");
+    }
+
+    if ((op & WOLFSSL_OP_NO_SSLv2) == WOLFSSL_OP_NO_SSLv2) {
+        WOLFSSL_MSG("\tWOLFSSL_OP_NO_SSLv2 : wolfSSL does not support SSLv2");
+    }
+
+#ifdef SSL_OP_NO_TLSv1_3
+    if ((op & SSL_OP_NO_TLSv1_3) == SSL_OP_NO_TLSv1_3) {
+        WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_3");
+    }
+#endif
+
+    if ((op & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) {
+        WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_2");
+    }
+
+    if ((op & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) {
+        WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_1");
+    }
+
+    if ((op & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) {
+        WOLFSSL_MSG("\tSSL_OP_NO_TLSv1");
+    }
+
+    if ((op & SSL_OP_NO_SSLv3) == SSL_OP_NO_SSLv3) {
+        WOLFSSL_MSG("\tSSL_OP_NO_SSLv3");
+    }
+
+    if ((op & SSL_OP_CIPHER_SERVER_PREFERENCE) == SSL_OP_CIPHER_SERVER_PREFERENCE) {
+        WOLFSSL_MSG("\tSSL_OP_CIPHER_SERVER_PREFERENCE");
+    }
+
+    if ((op & SSL_OP_NO_COMPRESSION) == SSL_OP_NO_COMPRESSION) {
+    #ifdef HAVE_LIBZ
+        WOLFSSL_MSG("SSL_OP_NO_COMPRESSION");
+    #else
+        WOLFSSL_MSG("SSL_OP_NO_COMPRESSION: compression not compiled in");
+    #endif
+    }
+
+    return old_op | op;
+}
+#endif
+
+#ifdef OPENSSL_EXTRA
+long wolfSSL_set_options(WOLFSSL* ssl, long op)
+{
+    word16 haveRSA = 1;
+    word16 havePSK = 0;
+    int    keySz   = 0;
+
+    WOLFSSL_ENTER("wolfSSL_set_options");
+
+    if (ssl == NULL) {
+        return 0;
+    }
+
+    ssl->options.mask = wolf_set_options(ssl->options.mask, op);
+
+#ifdef SSL_OP_NO_TLSv1_3
+    if ((ssl->options.mask & SSL_OP_NO_TLSv1_3) == SSL_OP_NO_TLSv1_3) {
+        if (ssl->version.minor == TLSv1_3_MINOR)
+            ssl->version.minor = TLSv1_2_MINOR;
+    }
+#endif
+
+    if ((ssl->options.mask & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) {
+        if (ssl->version.minor == TLSv1_2_MINOR)
+            ssl->version.minor = TLSv1_1_MINOR;
+    }
+
+    if ((ssl->options.mask & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) {
+        if (ssl->version.minor == TLSv1_1_MINOR)
+            ssl->version.minor = TLSv1_MINOR;
+    }
+
+    if ((ssl->options.mask & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) {
+        if (ssl->version.minor == TLSv1_MINOR)
+            ssl->version.minor = SSLv3_MINOR;
+    }
+
+    if ((ssl->options.mask & SSL_OP_NO_COMPRESSION) == SSL_OP_NO_COMPRESSION) {
+    #ifdef HAVE_LIBZ
+        ssl->options.usingCompression = 0;
+    #endif
+    }
+
+    /* in the case of a version change the cipher suites should be reset */
+#ifndef NO_PSK
+    havePSK = ssl->options.havePSK;
+#endif
+#ifdef NO_RSA
+    haveRSA = 0;
+#endif
+#ifndef NO_CERTS
+    keySz = ssl->buffers.keySz;
+#endif
+
+    InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
+                       ssl->options.haveDH, ssl->options.haveNTRU,
+                       ssl->options.haveECDSAsig, ssl->options.haveECC,
+                       ssl->options.haveStaticECC, ssl->options.side);
+
+    return ssl->options.mask;
+}
+
+
+long wolfSSL_get_options(const WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_get_options");
+    if(ssl == NULL)
+        return WOLFSSL_FAILURE;
+    return ssl->options.mask;
+}
+
+long wolfSSL_clear_options(WOLFSSL* ssl, long opt)
+{
+    WOLFSSL_ENTER("SSL_clear_options");
+    if(ssl == NULL)
+        return WOLFSSL_FAILURE;
+    ssl->options.mask &= ~opt;
+    return ssl->options.mask;
+}
+
+
+#if defined(HAVE_SECURE_RENEGOTIATION) \
+        || defined(HAVE_SERVER_RENEGOTIATION_INFO)
+/* clears the counter for number of renegotiations done
+ * returns the current count before it is cleared */
+long wolfSSL_clear_num_renegotiations(WOLFSSL *s)
+{
+    long total;
+
+    WOLFSSL_ENTER("wolfSSL_clear_num_renegotiations");
+    if (s == NULL)
+        return 0;
+
+    total = s->secure_rene_count;
+    s->secure_rene_count = 0;
+    return total;
+}
+
+
+/* return the number of renegotiations since wolfSSL_new */
+long wolfSSL_total_renegotiations(WOLFSSL *s)
+{
+    WOLFSSL_ENTER("wolfSSL_total_renegotiations");
+    return wolfSSL_num_renegotiations(s);
+}
+
+
+/* return the number of renegotiations since wolfSSL_new */
+long wolfSSL_num_renegotiations(WOLFSSL* s)
+{
+    if (s == NULL) {
+        return 0;
+    }
+
+    return s->secure_rene_count;
+}
+#endif /* HAVE_SECURE_RENEGOTIATION || HAVE_SERVER_RENEGOTIATION_INFO */
+
+#ifndef NO_DH
+long wolfSSL_set_tmp_dh(WOLFSSL *ssl, WOLFSSL_DH *dh)
+{
+    int pSz, gSz;
+    byte *p, *g;
+    int ret = 0;
+
+    WOLFSSL_ENTER("wolfSSL_set_tmp_dh");
+
+    if (!ssl || !dh)
+        return BAD_FUNC_ARG;
+
+    /* Get needed size for p and g */
+    pSz = wolfSSL_BN_bn2bin(dh->p, NULL);
+    gSz = wolfSSL_BN_bn2bin(dh->g, NULL);
+
+    if (pSz <= 0 || gSz <= 0)
+        return WOLFSSL_FATAL_ERROR;
+
+    p = (byte*)XMALLOC(pSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    if (!p)
+        return MEMORY_E;
+
+    g = (byte*)XMALLOC(gSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    if (!g) {
+        XFREE(p, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        return MEMORY_E;
+    }
+
+    pSz = wolfSSL_BN_bn2bin(dh->p, p);
+    gSz = wolfSSL_BN_bn2bin(dh->g, g);
+
+    if (pSz >= 0 && gSz >= 0) /* Conversion successful */
+        ret = wolfSSL_SetTmpDH(ssl, p, pSz, g, gSz);
+
+    XFREE(p, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    XFREE(g, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+
+    return pSz > 0 && gSz > 0 ? ret : WOLFSSL_FATAL_ERROR;
+}
+#endif /* !NO_DH */
+
+
+#ifdef HAVE_PK_CALLBACKS
+long wolfSSL_set_tlsext_debug_arg(WOLFSSL* ssl, void *arg)
+{
+    if (ssl == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    ssl->loggingCtx = arg;
+    return WOLFSSL_SUCCESS;
+}
+#endif /* HAVE_PK_CALLBACKS */
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY)
+const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *sess, unsigned int *sid_ctx_length)
+{
+    const byte *c = wolfSSL_SESSION_get_id((SSL_SESSION *)sess, sid_ctx_length);
+    return c;
+}
+#endif
+
+/*** TBD ***/
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_API int wolfSSL_sk_SSL_COMP_zero(WOLFSSL_STACK* st)
+{
+    (void)st;
+    WOLFSSL_STUB("wolfSSL_sk_SSL_COMP_zero");
+    /* wolfSSL_set_options(ssl, SSL_OP_NO_COMPRESSION); */
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type)
+{
+    WOLFSSL_ENTER("wolfSSL_set_tlsext_status_type");
+
+    if (s == NULL){
+        return BAD_FUNC_ARG;
+    }
+
+    if (type == TLSEXT_STATUSTYPE_ocsp){
+        int r = 0;
+        r = TLSX_UseCertificateStatusRequest(&s->extensions, type, 0, s,
+                                                             s->heap, s->devId);
+        return (long)r;
+    } else {
+        WOLFSSL_MSG(
+       "SSL_set_tlsext_status_type only supports TLSEXT_STATUSTYPE_ocsp type.");
+        return SSL_FAILURE;
+    }
+
+}
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
+
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_API long wolfSSL_get_tlsext_status_exts(WOLFSSL *s, void *arg)
+{
+    (void)s;
+    (void)arg;
+    WOLFSSL_STUB("wolfSSL_get_tlsext_status_exts");
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+/*** TBD ***/
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_API long wolfSSL_set_tlsext_status_exts(WOLFSSL *s, void *arg)
+{
+    (void)s;
+    (void)arg;
+    WOLFSSL_STUB("wolfSSL_set_tlsext_status_exts");
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+/*** TBD ***/
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_API long wolfSSL_get_tlsext_status_ids(WOLFSSL *s, void *arg)
+{
+    (void)s;
+    (void)arg;
+    WOLFSSL_STUB("wolfSSL_get_tlsext_status_ids");
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+/*** TBD ***/
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_API long wolfSSL_set_tlsext_status_ids(WOLFSSL *s, void *arg)
+{
+    (void)s;
+    (void)arg;
+    WOLFSSL_STUB("wolfSSL_set_tlsext_status_ids");
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+/*** TBD ***/
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_API int SSL_SESSION_set1_id(WOLFSSL_SESSION *s, const unsigned char *sid, unsigned int sid_len)
+{
+    (void)s;
+    (void)sid;
+    (void)sid_len;
+    WOLFSSL_STUB("SSL_SESSION_set1_id");
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API int SSL_SESSION_set1_id_context(WOLFSSL_SESSION *s, const unsigned char *sid_ctx, unsigned int sid_ctx_len)
+{
+    (void)s;
+    (void)sid_ctx;
+    (void)sid_ctx_len;
+    WOLFSSL_STUB("SSL_SESSION_set1_id_context");
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD) \
+    || defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_WPAS)
+WOLFSSL_X509_ALGOR* wolfSSL_X509_ALGOR_new(void)
+{
+    WOLFSSL_X509_ALGOR* ret;
+    ret = (WOLFSSL_X509_ALGOR*)XMALLOC(sizeof(WOLFSSL_X509_ALGOR), NULL,
+                                       DYNAMIC_TYPE_OPENSSL);
+    if (ret) {
+        XMEMSET(ret, 0, sizeof(WOLFSSL_X509_ALGOR));
+    }
+    return ret;
+}
+
+void wolfSSL_X509_ALGOR_free(WOLFSSL_X509_ALGOR *alg)
+{
+    if (alg) {
+        wolfSSL_ASN1_OBJECT_free(alg->algorithm);
+        wolfSSL_ASN1_TYPE_free(alg->parameter);
+        XFREE(alg, NULL, DYNAMIC_TYPE_OPENSSL);
+    }
+}
+
+/* Returns X509_ALGOR struct with signature algorithm */
+const WOLFSSL_X509_ALGOR* wolfSSL_X509_get0_tbs_sigalg(const WOLFSSL_X509 *x509)
+{
+    WOLFSSL_ENTER("X509_get0_tbs_sigalg");
+
+    if (x509 == NULL) {
+        WOLFSSL_MSG("x509 struct NULL error");
+        return NULL;
+    }
+
+    return &x509->algor;
+}
+
+/* Sets paobj pointer to X509_ALGOR signature algorithm */
+void wolfSSL_X509_ALGOR_get0(const WOLFSSL_ASN1_OBJECT **paobj, int *pptype,
+                            const void **ppval, const WOLFSSL_X509_ALGOR *algor)
+{
+    WOLFSSL_ENTER("X509_ALGOR_get0");
+
+    if (!algor) {
+        WOLFSSL_MSG("algor object is NULL");
+        return;
+    }
+
+    if (paobj)
+        *paobj = algor->algorithm;
+    if (ppval)
+        *ppval = algor->algorithm;
+    if (pptype) {
+        if (algor->parameter) {
+            *pptype = algor->parameter->type;
+        }
+        else {
+            /* Default to V_ASN1_OBJECT */
+            *pptype = V_ASN1_OBJECT;
+        }
+    }
+}
+
+/**
+ * Populate algor members.
+ *
+ * @param algor The object to be set
+ * @param aobj The value to be set in algor->algorithm
+ * @param ptype The type of algor->parameter
+ * @param pval The value of algor->parameter
+ * @return WOLFSSL_SUCCESS on success
+ *         WOLFSSL_FAILURE on missing parameters or bad malloc
+ */
+int wolfSSL_X509_ALGOR_set0(WOLFSSL_X509_ALGOR *algor, WOLFSSL_ASN1_OBJECT *aobj,
+                            int ptype, void *pval)
+{
+    if (!algor) {
+        return WOLFSSL_FAILURE;
+    }
+    if (aobj) {
+        algor->algorithm = aobj;
+    }
+    if (pval) {
+        if (!algor->parameter) {
+            algor->parameter = wolfSSL_ASN1_TYPE_new();
+            if (!algor->parameter) {
+                return WOLFSSL_FAILURE;
+            }
+        }
+        wolfSSL_ASN1_TYPE_set(algor->parameter, ptype, pval);
+    }
+    return WOLFSSL_SUCCESS;
+}
+
+/**
+ * Set `a` in a smart way.
+ *
+ * @param a Object to set
+ * @param type The type of object in value
+ * @param value Object to set
+ */
+void wolfSSL_ASN1_TYPE_set(WOLFSSL_ASN1_TYPE *a, int type, void *value)
+{
+    if (!a || !value) {
+        return;
+    }
+    switch (type) {
+        case V_ASN1_OBJECT:
+            a->value.object = value;
+            break;
+        case V_ASN1_UTCTIME:
+            a->value.utctime = value;
+            break;
+        case V_ASN1_GENERALIZEDTIME:
+            a->value.generalizedtime = value;
+            break;
+        default:
+            WOLFSSL_MSG("Unknown or unsupported ASN1_TYPE");
+            return;
+    }
+    a->type = type;
+}
+
+/**
+ * Allocate a new WOLFSSL_ASN1_TYPE object.
+ *
+ * @return New zero'ed WOLFSSL_ASN1_TYPE object
+ */
+WOLFSSL_ASN1_TYPE* wolfSSL_ASN1_TYPE_new(void)
+{
+    WOLFSSL_ASN1_TYPE* ret = (WOLFSSL_ASN1_TYPE*)XMALLOC(sizeof(WOLFSSL_ASN1_TYPE),
+                                                        NULL, DYNAMIC_TYPE_OPENSSL);
+    if (!ret)
+        return NULL;
+    XMEMSET(ret, 0, sizeof(WOLFSSL_ASN1_TYPE));
+    return ret;
+}
+
+/**
+ * Free WOLFSSL_ASN1_TYPE and all its members.
+ *
+ * @param at Object to free
+ */
+void wolfSSL_ASN1_TYPE_free(WOLFSSL_ASN1_TYPE* at)
+{
+    if (at) {
+        switch (at->type) {
+            case V_ASN1_OBJECT:
+                wolfSSL_ASN1_OBJECT_free(at->value.object);
+                break;
+            case V_ASN1_UTCTIME:
+                wolfSSL_ASN1_TIME_free(at->value.utctime);
+                break;
+            case V_ASN1_GENERALIZEDTIME:
+                wolfSSL_ASN1_TIME_free(at->value.generalizedtime);
+                break;
+            default:
+                WOLFSSL_MSG("Unknown or unsupported ASN1_TYPE");
+                break;
+        }
+        XFREE(at, NULL, DYNAMIC_TYPE_OPENSSL);
+    }
+}
+
+/**
+ * Allocate a new WOLFSSL_X509_PUBKEY object.
+ *
+ * @return New zero'ed WOLFSSL_X509_PUBKEY object
+ */
+WOLFSSL_X509_PUBKEY *wolfSSL_X509_PUBKEY_new(void)
+{
+    WOLFSSL_X509_PUBKEY *ret;
+    ret = (WOLFSSL_X509_PUBKEY*)XMALLOC(sizeof(WOLFSSL_X509_PUBKEY), NULL,
+                                        DYNAMIC_TYPE_OPENSSL);
+    if (!ret) {
+        return NULL;
+    }
+    XMEMSET(ret, 0, sizeof(WOLFSSL_X509_PUBKEY));
+    ret->algor = wolfSSL_X509_ALGOR_new();
+    if (!ret->algor) {
+        wolfSSL_X509_PUBKEY_free(ret);
+        return NULL;
+    }
+    return ret;
+}
+
+/**
+ * Free WOLFSSL_X509_PUBKEY and all its members.
+ *
+ * @param at Object to free
+ */
+void wolfSSL_X509_PUBKEY_free(WOLFSSL_X509_PUBKEY *x)
+{
+    if (x) {
+        if (x->algor) {
+            wolfSSL_X509_ALGOR_free(x->algor);
+        }
+        if (x->pkey) {
+            wolfSSL_EVP_PKEY_free(x->pkey);
+        }
+        XFREE(x, NULL, DYNAMIC_TYPE_OPENSSL);
+    }
+}
+
+/* Returns X509_PUBKEY structure containing X509_ALGOR and EVP_PKEY */
+WOLFSSL_X509_PUBKEY* wolfSSL_X509_get_X509_PUBKEY(const WOLFSSL_X509* x509)
+{
+    WOLFSSL_ENTER("X509_get_X509_PUBKEY");
+
+    if (x509 == NULL) {
+        WOLFSSL_MSG("x509 struct NULL error");
+        return NULL;
+    }
+
+    return (WOLFSSL_X509_PUBKEY*)&x509->key;
+}
+
+/* Sets ppkalg pointer to X509_PUBKEY algorithm. Returns WOLFSSL_SUCCESS on
+    success or WOLFSSL_FAILURE on error. */
+int wolfSSL_X509_PUBKEY_get0_param(WOLFSSL_ASN1_OBJECT **ppkalg,
+     const unsigned char **pk, int *ppklen, WOLFSSL_X509_ALGOR **pa,
+     WOLFSSL_X509_PUBKEY *pub)
+{
+    WOLFSSL_ENTER("X509_PUBKEY_get0_param");
+
+    if (!pub || !pub->pubKeyOID) {
+        WOLFSSL_MSG("X509_PUBKEY struct not populated");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (!pub->algor) {
+        if (!(pub->algor = wolfSSL_X509_ALGOR_new())) {
+            return WOLFSSL_FAILURE;
+        }
+        pub->algor->algorithm = wolfSSL_OBJ_nid2obj(pub->pubKeyOID);
+        if (pub->algor->algorithm == NULL) {
+            WOLFSSL_MSG("Failed to create object from NID");
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+    if (pa)
+        *pa = pub->algor;
+    if (ppkalg)
+        *ppkalg = pub->algor->algorithm;
+    if (pk)
+        wolfSSL_EVP_PKEY_get_der(pub->pkey, (unsigned char **)pk);
+    if (ppklen)
+        *ppklen = wolfSSL_EVP_PKEY_get_der(pub->pkey, NULL);
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* Returns a pointer to the pkey when passed a key */
+WOLFSSL_EVP_PKEY* wolfSSL_X509_PUBKEY_get(WOLFSSL_X509_PUBKEY* key)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_PUBKEY_get");
+    if(key == NULL || key->pkey == NULL){
+        WOLFSSL_LEAVE("wolfSSL_X509_PUBKEY_get", BAD_FUNC_ARG);
+        return NULL;
+    }
+    WOLFSSL_LEAVE("wolfSSL_X509_PUBKEY_get", WOLFSSL_SUCCESS);
+    return key->pkey;
+}
+
+int wolfSSL_X509_PUBKEY_set(WOLFSSL_X509_PUBKEY **x, WOLFSSL_EVP_PKEY *key)
+{
+    WOLFSSL_X509_PUBKEY *pk = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_X509_PUBKEY_set");
+
+    if (!x || !key) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if (!(pk = wolfSSL_X509_PUBKEY_new())) {
+        return WOLFSSL_FAILURE;
+    }
+
+    switch (key->type) {
+#ifndef NO_RSA
+    case EVP_PKEY_RSA:
+        pk->algor->algorithm= wolfSSL_OBJ_nid2obj(RSAk);
+        break;
+#endif
+#ifndef NO_DSA
+    case EVP_PKEY_DSA:
+        pk->algor->algorithm = wolfSSL_OBJ_nid2obj(DSAk);
+        break;
+#endif
+#ifdef HAVE_ECC
+    case EVP_PKEY_EC:
+        pk->algor->algorithm = wolfSSL_OBJ_nid2obj(ECDSAk);
+        break;
+#endif
+    default:
+        WOLFSSL_MSG("Unknown key type");
+        goto error;
+    }
+
+    if (!pk->algor->algorithm) {
+        WOLFSSL_MSG("Failed to create algorithm object");
+        goto error;
+    }
+
+    if (!wolfSSL_EVP_PKEY_up_ref(key)) {
+        WOLFSSL_MSG("Failed to up key reference");
+        goto error;
+    }
+    pk->pkey = key;
+
+    wolfSSL_X509_PUBKEY_free(*x);
+    *x = pk;
+    return WOLFSSL_SUCCESS;
+error:
+    if (pk) {
+        wolfSSL_X509_PUBKEY_free(pk);
+    }
+    return WOLFSSL_FAILURE;
+}
+
+#endif /* OPENSSL_ALL || WOLFSSL_APACHE_HTTPD || WOLFSSL_HAPROXY*/
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_get_privatekey(const WOLFSSL *ssl)
+{
+    (void)ssl;
+    WOLFSSL_STUB("SSL_get_privatekey");
+    return NULL;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API int i2t_ASN1_OBJECT(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a)
+{
+    (void)buf;
+    (void)buf_len;
+    (void)a;
+    WOLFSSL_STUB("i2t_ASN1_OBJECT");
+    return -1;
+}
+#endif
+
+/* Return number of bytes written to BIO on success. 0 on failure. */
+WOLFSSL_API int wolfSSL_i2a_ASN1_OBJECT(WOLFSSL_BIO *bp,
+                                        WOLFSSL_ASN1_OBJECT *a)
+{
+    int length = 0;
+    word32 idx = 0;
+    const char null_str[] = "NULL";
+
+    WOLFSSL_ENTER("wolfSSL_i2a_ASN1_OBJECT");
+
+    if (bp == NULL)
+        return WOLFSSL_FAILURE;
+
+    if (a == NULL) {
+        /* Write "NULL" */
+        if (wolfSSL_BIO_write(bp, null_str, (int)XSTRLEN(null_str)) ==
+                (int)XSTRLEN(null_str)) {
+            return (int)XSTRLEN(null_str);
+        }
+        else {
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+
+    if ((a->obj == NULL) || (a->obj[idx++] != ASN_OBJECT_ID)) {
+        WOLFSSL_MSG("Bad ASN1 Object");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (GetLength((const byte*)a->obj, &idx, &length,
+                   a->objSz) < 0 || length < 0) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if (wolfSSL_BIO_write(bp, a->obj + idx, length) == (int)length) {
+        return length;
+    }
+
+    return WOLFSSL_FAILURE;
+}
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY)
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API size_t SSL_get_finished(const WOLFSSL *s, void *buf, size_t count)
+{
+    (void)s;
+    (void)buf;
+    (void)count;
+    WOLFSSL_STUB("SSL_get_finished");
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API size_t SSL_get_peer_finished(const WOLFSSL *s, void *buf, size_t count)
+{
+    (void)s;
+    (void)buf;
+    (void)count;
+    WOLFSSL_STUB("SSL_get_peer_finished");
+    return WOLFSSL_FAILURE;
+}
+#endif
+#endif /* WOLFSSL_HAPROXY */
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API void SSL_CTX_set_tmp_dh_callback(WOLFSSL_CTX *ctx, WOLFSSL_DH *(*dh) (WOLFSSL *ssl, int is_export, int keylength))
+{
+    (void)ctx;
+    (void)dh;
+    WOLFSSL_STUB("SSL_CTX_set_tmp_dh_callback");
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API WOLF_STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void)
+{
+    WOLFSSL_STUB("SSL_COMP_get_compression_methods");
+    return NULL;
+}
+#endif
+
+
+int wolfSSL_sk_SSL_CIPHER_num(const WOLF_STACK_OF(WOLFSSL_CIPHER)* p)
+{
+    WOLFSSL_ENTER("wolfSSL_sk_SSL_CIPHER_num");
+    if (p == NULL) {
+        return WOLFSSL_FATAL_ERROR;
+    }
+    return (int)p->num;
+}
+
+#if !defined(NO_FILESYSTEM)
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PrivateKey(XFILE fp, WOLFSSL_EVP_PKEY **x, pem_password_cb *cb, void *u)
+{
+    (void)fp;
+    (void)x;
+    (void)cb;
+    (void)u;
+    WOLFSSL_STUB("PEM_read_PrivateKey");
+    return NULL;
+}
+#endif
+#endif
+
+#if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
+/* Loads certificate(s) files in pem format into X509_STORE struct from either
+ * a file or directory.
+ * Returns WOLFSSL_SUCCESS on success or WOLFSSL_FAILURE if an error occurs.
+ */
+WOLFSSL_API int wolfSSL_X509_STORE_load_locations(WOLFSSL_X509_STORE *str,
+                                              const char *file, const char *dir)
+{
+    WOLFSSL_CTX* ctx;
+    char *name = NULL;
+    int ret = WOLFSSL_SUCCESS;
+    int successes = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    ReadDirCtx* readCtx = NULL;
+#else
+    ReadDirCtx  readCtx[1];
+#endif
+
+    WOLFSSL_ENTER("X509_STORE_load_locations");
+
+    if (str == NULL || str->cm == NULL || (file == NULL  && dir == NULL))
+        return WOLFSSL_FAILURE;
+
+    /* tmp ctx for setting our cert manager */
+    ctx = wolfSSL_CTX_new(cm_pick_method());
+    if (ctx == NULL)
+        return WOLFSSL_FAILURE;
+
+    wolfSSL_CertManagerFree(ctx->cm);
+    ctx->cm = str->cm;
+
+#ifdef HAVE_CRL
+    if (str->cm->crl == NULL) {
+        if (wolfSSL_CertManagerEnableCRL(str->cm, 0) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("Enable CRL failed");
+            wolfSSL_CTX_free(ctx);
+            return WOLFSSL_FAILURE;
+        }
+    }
+#endif
+
+    /* Load individual file */
+    if (file) {
+        /* Try to process file with type DETECT_CERT_TYPE to parse the
+           correct certificate header and footer type */
+        ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, DETECT_CERT_TYPE,
+                                                      NULL, 0, str->cm->crl, 0);
+        if (ret != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("Failed to load file");
+            ret = WOLFSSL_FAILURE;
+        }
+    }
+
+    /* Load files in dir */
+    if (dir && ret == WOLFSSL_SUCCESS) {
+        #ifdef WOLFSSL_SMALL_STACK
+            readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), ctx->heap,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+            if (readCtx == NULL) {
+                WOLFSSL_MSG("Memory error");
+                return WOLFSSL_FAILURE;
+            }
+        #endif
+
+        /* try to load each regular file in dir */
+        ret = wc_ReadDirFirst(readCtx, dir, &name);
+        while (ret == 0 && name) {
+            WOLFSSL_MSG(name);
+            /* Try to process file with type DETECT_CERT_TYPE to parse the
+               correct certificate header and footer type */
+            ret = ProcessFile(ctx, name, WOLFSSL_FILETYPE_PEM, DETECT_CERT_TYPE,
+                                                      NULL, 0, str->cm->crl, 0);
+            /* Not failing on load errors */
+            if (ret != WOLFSSL_SUCCESS)
+                WOLFSSL_MSG("Failed to load file in path, continuing");
+            else
+                successes++;
+
+            ret = wc_ReadDirNext(readCtx, dir, &name);
+        }
+        wc_ReadDirClose(readCtx);
+
+        /* Success if at least one file in dir was loaded */
+        if (successes > 0)
+            ret = WOLFSSL_SUCCESS;
+        else {
+            WOLFSSL_ERROR(ret);
+            ret = WOLFSSL_FAILURE;
+        }
+
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(readCtx, ctx->heap, DYNAMIC_TYPE_DIRCTX);
+        #endif
+    }
+
+    ctx->cm = NULL;
+    wolfSSL_CTX_free(ctx);
+
+    return ret;
+}
+#endif /* !NO_FILESYSTEM && !NO_WOLFSSL_DIR */
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API WOLFSSL_CIPHER* wolfSSL_sk_SSL_CIPHER_value(void *ciphers, int idx)
+{
+    (void)ciphers;
+    (void)idx;
+    WOLFSSL_STUB("wolfSSL_sk_SSL_CIPHER_value");
+    return NULL;
+}
+#endif
+
+WOLFSSL_API void ERR_load_SSL_strings(void)
+{
+
+}
+
+#ifdef HAVE_OCSP
+WOLFSSL_API long wolfSSL_get_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char **resp)
+{
+    if (s == NULL || resp == NULL)
+        return 0;
+
+    *resp = s->ocspResp;
+    return s->ocspRespSz;
+}
+
+WOLFSSL_API long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char *resp, int len)
+{
+    if (s == NULL)
+        return WOLFSSL_FAILURE;
+
+    s->ocspResp   = resp;
+    s->ocspRespSz = len;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* HAVE_OCSP */
+
+#endif /* OPENSSL_EXTRA */
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+long wolfSSL_get_verify_result(const WOLFSSL *ssl)
+{
+    if (ssl == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    return ssl->peerVerifyRet;
+}
+#endif
+
+#ifdef OPENSSL_EXTRA
+
+#ifndef NO_WOLFSSL_STUB
+/* shows the number of accepts attempted by CTX in it's lifetime */
+long wolfSSL_CTX_sess_accept(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_STUB("wolfSSL_CTX_sess_accept");
+    (void)ctx;
+    return 0;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+/* shows the number of connects attempted CTX in it's lifetime */
+long wolfSSL_CTX_sess_connect(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_STUB("wolfSSL_CTX_sess_connect");
+    (void)ctx;
+    return 0;
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_STUB
+/* shows the number of accepts completed by CTX in it's lifetime */
+long wolfSSL_CTX_sess_accept_good(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_STUB("wolfSSL_CTX_sess_accept_good");
+    (void)ctx;
+    return 0;
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_STUB
+/* shows the number of connects completed by CTX in it's lifetime */
+long wolfSSL_CTX_sess_connect_good(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_STUB("wolfSSL_CTX_sess_connect_good");
+    (void)ctx;
+    return 0;
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_STUB
+/* shows the number of renegotiation accepts attempted by CTX */
+long wolfSSL_CTX_sess_accept_renegotiate(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_STUB("wolfSSL_CTX_sess_accept_renegotiate");
+    (void)ctx;
+    return 0;
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_STUB
+/* shows the number of renegotiation accepts attempted by CTX */
+long wolfSSL_CTX_sess_connect_renegotiate(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_STUB("wolfSSL_CTX_sess_connect_renegotiate");
+    (void)ctx;
+    return 0;
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_STUB
+long wolfSSL_CTX_sess_hits(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_STUB("wolfSSL_CTX_sess_hits");
+    (void)ctx;
+    return 0;
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_STUB
+long wolfSSL_CTX_sess_cb_hits(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_STUB("wolfSSL_CTX_sess_cb_hits");
+    (void)ctx;
+    return 0;
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_STUB
+long wolfSSL_CTX_sess_cache_full(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_STUB("wolfSSL_CTX_sess_cache_full");
+    (void)ctx;
+    return 0;
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_STUB
+long wolfSSL_CTX_sess_misses(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_STUB("wolfSSL_CTX_sess_misses");
+    (void)ctx;
+    return 0;
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_STUB
+long wolfSSL_CTX_sess_timeouts(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_STUB("wolfSSL_CTX_sess_timeouts");
+    (void)ctx;
+    return 0;
+}
+#endif
+
+
+/* Return the total number of sessions */
+long wolfSSL_CTX_sess_number(WOLFSSL_CTX* ctx)
+{
+    word32 total = 0;
+
+    WOLFSSL_ENTER("wolfSSL_CTX_sess_number");
+    (void)ctx;
+
+#ifdef WOLFSSL_SESSION_STATS
+    if (wolfSSL_get_session_stats(NULL, &total, NULL, NULL) != SSL_SUCCESS) {
+        WOLFSSL_MSG("Error getting session stats");
+    }
+#else
+    WOLFSSL_MSG("Please use macro WOLFSSL_SESSION_STATS for session stats");
+#endif
+
+    return (long)total;
+}
+
+
+#ifndef NO_CERTS
+long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
+{
+    byte* chain = NULL;
+    long  chainSz = 0;
+    int   derSz;
+    const byte* der;
+    int   ret;
+    int   idx = 0;
+    DerBuffer *derBuffer = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_CTX_add_extra_chain_cert");
+
+    if (ctx == NULL || x509 == NULL) {
+        WOLFSSL_MSG("Bad Argument");
+        return WOLFSSL_FAILURE;
+    }
+
+    der = wolfSSL_X509_get_der(x509, &derSz);
+    if (der == NULL || derSz <= 0) {
+        WOLFSSL_MSG("Error getting X509 DER");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (ctx->certificate == NULL) {
+        WOLFSSL_ENTER("wolfSSL_use_certificate_chain_buffer_format");
+
+        /* Process buffer makes first certificate the leaf. */
+        ret = ProcessBuffer(ctx, der, derSz, WOLFSSL_FILETYPE_ASN1, CERT_TYPE,
+                            NULL, NULL, 1, GET_VERIFY_SETTING_CTX(ctx));
+        if (ret != WOLFSSL_SUCCESS) {
+            WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret);
+            return WOLFSSL_FAILURE;
+        }
+    }
+    else {
+        /* TODO: Do this elsewhere. */
+        ret = AllocDer(&derBuffer, derSz, CERT_TYPE, ctx->heap);
+        if (ret != 0) {
+            WOLFSSL_MSG("Memory Error");
+            return WOLFSSL_FAILURE;
+        }
+        XMEMCPY(derBuffer->buffer, der, derSz);
+        ret = AddCA(ctx->cm, &derBuffer, WOLFSSL_USER_CA,
+            GET_VERIFY_SETTING_CTX(ctx));
+        if (ret != WOLFSSL_SUCCESS) {
+            WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret);
+            return WOLFSSL_FAILURE;
+        }
+
+        /* adding cert to existing chain */
+        if (ctx->certChain != NULL && ctx->certChain->length > 0) {
+            chainSz += ctx->certChain->length;
+        }
+        chainSz += OPAQUE24_LEN + derSz;
+
+        chain = (byte*)XMALLOC(chainSz, ctx->heap, DYNAMIC_TYPE_DER);
+        if (chain == NULL) {
+            WOLFSSL_MSG("Memory Error");
+            return WOLFSSL_FAILURE;
+        }
+
+        if (ctx->certChain != NULL && ctx->certChain->length > 0) {
+            XMEMCPY(chain, ctx->certChain->buffer, ctx->certChain->length);
+            idx = ctx->certChain->length;
+        }
+        c32to24(derSz, chain + idx);
+        idx += OPAQUE24_LEN,
+        XMEMCPY(chain + idx, der, derSz);
+        idx += derSz;
+#ifdef WOLFSSL_TLS13
+        ctx->certChainCnt++;
+#endif
+
+        FreeDer(&ctx->certChain);
+        ret = AllocDer(&ctx->certChain, idx, CERT_TYPE, ctx->heap);
+        if (ret == 0) {
+            XMEMCPY(ctx->certChain->buffer, chain, idx);
+        }
+    }
+
+    /* on success WOLFSSL_X509 memory is responsibility of ctx */
+    wolfSSL_X509_free(x509);
+    if (chain != NULL)
+        XFREE(chain, ctx->heap, DYNAMIC_TYPE_DER);
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+long wolfSSL_CTX_set_tlsext_status_arg(WOLFSSL_CTX* ctx, void* arg)
+{
+    if (ctx == NULL || ctx->cm == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    ctx->cm->ocspIOCtx = arg;
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* NO_CERTS */
+
+
+/* Get the session cache mode for CTX
+ *
+ * ctx  WOLFSSL_CTX struct to get cache mode from
+ *
+ * Returns a bit mask that has the session cache mode */
+WOLFSSL_API long wolfSSL_CTX_get_session_cache_mode(WOLFSSL_CTX* ctx)
+{
+    long m = 0;
+
+    WOLFSSL_ENTER("SSL_CTX_set_session_cache_mode");
+
+    if (ctx == NULL) {
+        return m;
+    }
+
+    if (ctx->sessionCacheOff != 1) {
+        m |= SSL_SESS_CACHE_SERVER;
+    }
+
+    if (ctx->sessionCacheFlushOff == 1) {
+        m |= SSL_SESS_CACHE_NO_AUTO_CLEAR;
+    }
+
+#ifdef HAVE_EXT_CACHE
+    if (ctx->internalCacheOff == 1) {
+        m |= SSL_SESS_CACHE_NO_INTERNAL_STORE;
+    }
+#endif
+
+    return m;
+}
+
+
+int wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX* ctx)
+{
+    if (ctx == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    return ctx->readAhead;
+}
+
+
+int wolfSSL_CTX_set_read_ahead(WOLFSSL_CTX* ctx, int v)
+{
+    if (ctx == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    ctx->readAhead = (byte)v;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+long wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg(WOLFSSL_CTX* ctx,
+        void* arg)
+{
+    if (ctx == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    ctx->userPRFArg = arg;
+    return WOLFSSL_SUCCESS;
+}
+
+
+#ifndef NO_DES3
+/* 0 on success */
+int wolfSSL_DES_set_key(WOLFSSL_const_DES_cblock* myDes,
+                                               WOLFSSL_DES_key_schedule* key)
+{
+#ifdef WOLFSSL_CHECK_DESKEY
+    return wolfSSL_DES_set_key_checked(myDes, key);
+#else
+    wolfSSL_DES_set_key_unchecked(myDes, key);
+    return 0;
+#endif
+}
+
+
+
+/* return true in fail case (1) */
+static int DES_check(word32 mask, word32 mask2, unsigned char* key)
+{
+    word32 value[2];
+
+    /* sanity check on length made in wolfSSL_DES_set_key_checked */
+    value[0] = mask;
+    value[1] = mask2;
+    return (XMEMCMP(value, key, sizeof(value)) == 0)? 1: 0;
+}
+
+
+/* check that the key is odd parity and is not a weak key
+ * returns -1 if parity is wrong, -2 if weak/null key and 0 on success */
+int wolfSSL_DES_set_key_checked(WOLFSSL_const_DES_cblock* myDes,
+                                               WOLFSSL_DES_key_schedule* key)
+{
+    if (myDes == NULL || key == NULL) {
+        WOLFSSL_MSG("Bad argument passed to wolfSSL_DES_set_key_checked");
+        return -2;
+    }
+    else {
+        word32 sz = sizeof(WOLFSSL_DES_key_schedule);
+
+        /* sanity check before call to DES_check */
+        if (sz != (sizeof(word32) * 2)) {
+            WOLFSSL_MSG("Unexpected WOLFSSL_DES_key_schedule size");
+            return -2;
+        }
+
+        /* check odd parity */
+        if (wolfSSL_DES_check_key_parity(myDes) != 1) {
+            WOLFSSL_MSG("Odd parity test fail");
+            return -1;
+        }
+
+        if (wolfSSL_DES_is_weak_key(myDes) == 1) {
+            WOLFSSL_MSG("Weak key found");
+            return -2;
+        }
+
+        /* passed tests, now copy over key */
+        XMEMCPY(key, myDes, sizeof(WOLFSSL_const_DES_cblock));
+
+        return 0;
+    }
+}
+
+
+/* check is not weak. Weak key list from Nist "Recommendation for the Triple
+ * Data Encryption Algorithm (TDEA) Block Cipher"
+ *
+ * returns 1 if is weak 0 if not
+ */
+int wolfSSL_DES_is_weak_key(WOLFSSL_const_DES_cblock* key)
+{
+    word32 mask, mask2;
+
+    WOLFSSL_ENTER("wolfSSL_DES_is_weak_key");
+
+    if (key == NULL) {
+        WOLFSSL_MSG("NULL key passed in");
+        return 1;
+    }
+
+    mask = 0x01010101; mask2 = 0x01010101;
+    if (DES_check(mask, mask2, *key)) {
+        WOLFSSL_MSG("Weak key found");
+        return 1;
+    }
+
+    mask = 0xFEFEFEFE; mask2 = 0xFEFEFEFE;
+    if (DES_check(mask, mask2, *key)) {
+        WOLFSSL_MSG("Weak key found");
+        return 1;
+    }
+
+    mask = 0xE0E0E0E0; mask2 = 0xF1F1F1F1;
+    if (DES_check(mask, mask2, *key)) {
+        WOLFSSL_MSG("Weak key found");
+        return 1;
+    }
+
+    mask = 0x1F1F1F1F; mask2 = 0x0E0E0E0E;
+    if (DES_check(mask, mask2, *key)) {
+        WOLFSSL_MSG("Weak key found");
+        return 1;
+    }
+
+    /* semi-weak *key check (list from same Nist paper) */
+    mask  = 0x011F011F; mask2 = 0x010E010E;
+    if (DES_check(mask, mask2, *key) ||
+       DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) {
+        WOLFSSL_MSG("Weak key found");
+        return 1;
+    }
+
+    mask  = 0x01E001E0; mask2 = 0x01F101F1;
+    if (DES_check(mask, mask2, *key) ||
+       DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) {
+        WOLFSSL_MSG("Weak key found");
+        return 1;
+    }
+
+    mask  = 0x01FE01FE; mask2 = 0x01FE01FE;
+    if (DES_check(mask, mask2, *key) ||
+       DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) {
+        WOLFSSL_MSG("Weak key found");
+        return 1;
+    }
+
+    mask  = 0x1FE01FE0; mask2 = 0x0EF10EF1;
+    if (DES_check(mask, mask2, *key) ||
+       DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) {
+        WOLFSSL_MSG("Weak key found");
+        return 1;
+    }
+
+    mask  = 0x1FFE1FFE; mask2 = 0x0EFE0EFE;
+    if (DES_check(mask, mask2, *key) ||
+       DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) {
+        WOLFSSL_MSG("Weak key found");
+        return 1;
+    }
+
+    return 0;
+}
+
+
+void wolfSSL_DES_set_key_unchecked(WOLFSSL_const_DES_cblock* myDes,
+                                               WOLFSSL_DES_key_schedule* key)
+{
+    if (myDes != NULL && key != NULL) {
+        XMEMCPY(key, myDes, sizeof(WOLFSSL_const_DES_cblock));
+    }
+}
+
+
+/* Sets the parity of the DES key for use */
+void wolfSSL_DES_set_odd_parity(WOLFSSL_DES_cblock* myDes)
+{
+    word32 i;
+    word32 sz = sizeof(WOLFSSL_DES_cblock);
+
+    WOLFSSL_ENTER("wolfSSL_DES_set_odd_parity");
+
+    for (i = 0; i < sz; i++) {
+        unsigned char c = (*myDes)[i];
+        if ((
+            ((c >> 1) & 0x01) ^
+            ((c >> 2) & 0x01) ^
+            ((c >> 3) & 0x01) ^
+            ((c >> 4) & 0x01) ^
+            ((c >> 5) & 0x01) ^
+            ((c >> 6) & 0x01) ^
+            ((c >> 7) & 0x01)) == (c & 0x01)) {
+            WOLFSSL_MSG("Flipping parity bit");
+            (*myDes)[i] = c ^ 0x01;
+        }
+    }
+}
+
+int wolfSSL_DES_check_key_parity(WOLFSSL_DES_cblock *myDes)
+{
+    word32 i;
+    word32 sz = sizeof(WOLFSSL_DES_cblock);
+
+    WOLFSSL_ENTER("wolfSSL_DES_check_key_parity");
+
+    for (i = 0; i < sz; i++) {
+        unsigned char c = (*myDes)[i];
+        if ((
+            ((c >> 1) & 0x01) ^
+            ((c >> 2) & 0x01) ^
+            ((c >> 3) & 0x01) ^
+            ((c >> 4) & 0x01) ^
+            ((c >> 5) & 0x01) ^
+            ((c >> 6) & 0x01) ^
+            ((c >> 7) & 0x01)) == (c & 0x01)) {
+            return 0;
+        }
+    }
+    return 1;
+}
+
+#ifdef WOLFSSL_DES_ECB
+/* Encrypt or decrypt input message desa with key and get output in desb.
+ * if enc is DES_ENCRYPT,input message is encrypted or
+ * if enc is DES_DECRYPT,input message is decrypted.
+ * */
+void wolfSSL_DES_ecb_encrypt(WOLFSSL_DES_cblock* desa,
+             WOLFSSL_DES_cblock* desb, WOLFSSL_DES_key_schedule* key, int enc)
+{
+    Des myDes;
+
+    WOLFSSL_ENTER("wolfSSL_DES_ecb_encrypt");
+
+    if (desa == NULL || key == NULL || desb == NULL ||
+        (enc != DES_ENCRYPT && enc != DES_DECRYPT)) {
+        WOLFSSL_MSG("Bad argument passed to wolfSSL_DES_ecb_encrypt");
+    } else {
+        if (wc_Des_SetKey(&myDes, (const byte*) key,
+                           (const byte*) NULL, !enc) != 0) {
+            WOLFSSL_MSG("wc_Des_SetKey return error.");
+            return;
+        }
+        if (enc){
+            if (wc_Des_EcbEncrypt(&myDes, (byte*) desb, (const byte*) desa,
+                        sizeof(WOLFSSL_DES_cblock)) != 0){
+                WOLFSSL_MSG("wc_Des_EcbEncrypt return error.");
+            }
+        } else {
+            if (wc_Des_EcbDecrypt(&myDes, (byte*) desb, (const byte*) desa,
+                        sizeof(WOLFSSL_DES_cblock)) != 0){
+                WOLFSSL_MSG("wc_Des_EcbDecrpyt return error.");
+            }
+        }
+    }
+}
+#endif
+#endif /* NO_DES3 */
+
+#ifndef NO_RC4
+/* Set the key state for Arc4 structure.
+ *
+ * key  Arc4 structure to use
+ * len  length of data buffer
+ * data initial state to set Arc4 structure
+ */
+void wolfSSL_RC4_set_key(WOLFSSL_RC4_KEY* key, int len,
+        const unsigned char* data)
+{
+    typedef char rc4_test[sizeof(WOLFSSL_RC4_KEY) >= sizeof(Arc4) ? 1 : -1];
+    (void)sizeof(rc4_test);
+
+    WOLFSSL_ENTER("wolfSSL_RC4_set_key");
+
+    if (key == NULL || len < 0) {
+        WOLFSSL_MSG("bad argument passed in");
+        return;
+    }
+
+    XMEMSET(key, 0, sizeof(WOLFSSL_RC4_KEY));
+    wc_Arc4SetKey((Arc4*)key, data, (word32)len);
+}
+
+
+/* Encrypt/decrypt with Arc4 structure.
+ *
+ * len length of buffer to encrypt/decrypt (in/out)
+ * in  buffer to encrypt/decrypt
+ * out results of encryption/decryption
+ */
+void wolfSSL_RC4(WOLFSSL_RC4_KEY* key, size_t len,
+        const unsigned char* in, unsigned char* out)
+{
+    WOLFSSL_ENTER("wolfSSL_RC4");
+
+    if (key == NULL || in == NULL || out == NULL) {
+        WOLFSSL_MSG("Bad argument passed in");
+        return;
+    }
+
+    wc_Arc4Process((Arc4*)key, out, in, (word32)len);
+}
+#endif /* NO_RC4 */
+
+#ifndef NO_AES
+
+#ifdef WOLFSSL_AES_DIRECT
+/* AES encrypt direct, it is expected to be blocks of AES_BLOCK_SIZE for input.
+ *
+ * input  Data to encrypt
+ * output Encrypted data after done
+ * key    AES key to use for encryption
+ */
+void wolfSSL_AES_encrypt(const unsigned char* input, unsigned char* output,
+        AES_KEY *key)
+{
+    WOLFSSL_ENTER("wolfSSL_AES_encrypt");
+
+    if (input == NULL || output == NULL || key == NULL) {
+        WOLFSSL_MSG("Null argument passed in");
+        return;
+    }
+
+    wc_AesEncryptDirect((Aes*)key, output, input);
+}
+
+
+/* AES decrypt direct, it is expected to be blocks of AES_BLOCK_SIZE for input.
+ *
+ * input  Data to decrypt
+ * output Decrypted data after done
+ * key    AES key to use for encryption
+ */
+void wolfSSL_AES_decrypt(const unsigned char* input, unsigned char* output,
+        AES_KEY *key)
+{
+    WOLFSSL_ENTER("wolfSSL_AES_decrypt");
+
+    if (input == NULL || output == NULL || key == NULL) {
+        WOLFSSL_MSG("Null argument passed in");
+        return;
+    }
+
+    wc_AesDecryptDirect((Aes*)key, output, input);
+}
+#endif /* WOLFSSL_AES_DIRECT */
+
+/* Setup of an AES key to use for encryption.
+ *
+ * key  key in bytes to use for encryption
+ * bits size of key in bits
+ * aes  AES structure to initialize
+ */
+int wolfSSL_AES_set_encrypt_key(const unsigned char *key, const int bits,
+        AES_KEY *aes)
+{
+    typedef char aes_test[sizeof(AES_KEY) >= sizeof(Aes) ? 1 : -1];
+    (void)sizeof(aes_test);
+
+    WOLFSSL_ENTER("wolfSSL_AES_set_encrypt_key");
+
+    if (key == NULL || aes == NULL) {
+        WOLFSSL_MSG("Null argument passed in");
+        return -1;
+    }
+
+    XMEMSET(aes, 0, sizeof(AES_KEY));
+    if (wc_AesSetKey((Aes*)aes, key, ((bits)/8), NULL, AES_ENCRYPTION) != 0) {
+        WOLFSSL_MSG("Error in setting AES key");
+        return -1;
+    }
+    return 0;
+}
+
+
+/* Setup of an AES key to use for decryption.
+ *
+ * key  key in bytes to use for decryption
+ * bits size of key in bits
+ * aes  AES structure to initialize
+ */
+int wolfSSL_AES_set_decrypt_key(const unsigned char *key, const int bits,
+        AES_KEY *aes)
+{
+    typedef char aes_test[sizeof(AES_KEY) >= sizeof(Aes) ? 1 : -1];
+    (void)sizeof(aes_test);
+
+    WOLFSSL_ENTER("wolfSSL_AES_set_decrypt_key");
+
+    if (key == NULL || aes == NULL) {
+        WOLFSSL_MSG("Null argument passed in");
+        return -1;
+    }
+
+    XMEMSET(aes, 0, sizeof(AES_KEY));
+    if (wc_AesSetKey((Aes*)aes, key, ((bits)/8), NULL, AES_DECRYPTION) != 0) {
+        WOLFSSL_MSG("Error in setting AES key");
+        return -1;
+    }
+    return 0;
+}
+
+
+#ifdef HAVE_AES_ECB
+/* Encrypt/decrypt a 16 byte block of data using the key passed in.
+ *
+ * in  buffer to encrypt/decrypt
+ * out buffer to hold result of encryption/decryption
+ * key AES structure to use with encryption/decryption
+ * enc AES_ENCRPT for encryption and AES_DECRYPT for decryption
+ */
+void wolfSSL_AES_ecb_encrypt(const unsigned char *in, unsigned char* out,
+                             AES_KEY *key, const int enc)
+{
+    Aes* aes;
+
+    WOLFSSL_ENTER("wolfSSL_AES_ecb_encrypt");
+
+    if (key == NULL || in == NULL || out == NULL) {
+        WOLFSSL_MSG("Error, Null argument passed in");
+        return;
+    }
+
+    aes = (Aes*)key;
+    if (enc == AES_ENCRYPT) {
+        if (wc_AesEcbEncrypt(aes, out, in, AES_BLOCK_SIZE) != 0) {
+            WOLFSSL_MSG("Error with AES CBC encrypt");
+        }
+    }
+    else {
+    #ifdef HAVE_AES_DECRYPT
+        if (wc_AesEcbDecrypt(aes, out, in, AES_BLOCK_SIZE) != 0) {
+            WOLFSSL_MSG("Error with AES CBC decrypt");
+        }
+    #else
+        WOLFSSL_MSG("AES decryption not compiled in");
+    #endif
+    }
+}
+#endif /* HAVE_AES_ECB */
+
+#ifdef HAVE_AES_CBC
+/* Encrypt data using key and iv passed in. iv gets updated to most recent iv
+ * state after encryption/decryption.
+ *
+ * in  buffer to encrypt/decrypt
+ * out buffer to hold result of encryption/decryption
+ * len length of input buffer
+ * key AES structure to use with encryption/decryption
+ * iv  iv to use with operation
+ * enc AES_ENCRPT for encryption and AES_DECRYPT for decryption
+ */
+void wolfSSL_AES_cbc_encrypt(const unsigned char *in, unsigned char* out,
+        size_t len, AES_KEY *key, unsigned char* iv, const int enc)
+{
+    Aes* aes;
+
+    WOLFSSL_ENTER("wolfSSL_AES_cbc_encrypt");
+
+    if (key == NULL || in == NULL || out == NULL || iv == NULL || len == 0) {
+        WOLFSSL_MSG("Error, Null argument passed in");
+        return;
+    }
+
+    aes = (Aes*)key;
+    if (wc_AesSetIV(aes, (const byte*)iv) != 0) {
+        WOLFSSL_MSG("Error with setting iv");
+        return;
+    }
+
+    if (enc == AES_ENCRYPT) {
+        if (wc_AesCbcEncrypt(aes, out, in, (word32)len) != 0) {
+            WOLFSSL_MSG("Error with AES CBC encrypt");
+        }
+    }
+    else {
+        if (wc_AesCbcDecrypt(aes, out, in, (word32)len) != 0) {
+            WOLFSSL_MSG("Error with AES CBC decrypt");
+        }
+    }
+
+    /* to be compatible copy iv to iv buffer after completing operation */
+    XMEMCPY(iv, (byte*)(aes->reg), AES_BLOCK_SIZE);
+}
+#endif /* HAVE_AES_CBC */
+
+
+/* Encrypt data using CFB mode with key and iv passed in. iv gets updated to
+ * most recent iv state after encryption/decryption.
+ *
+ * in  buffer to encrypt/decrypt
+ * out buffer to hold result of encryption/decryption
+ * len length of input buffer
+ * key AES structure to use with encryption/decryption
+ * iv  iv to use with operation
+ * num contains the amount of block used
+ * enc AES_ENCRPT for encryption and AES_DECRYPT for decryption
+ */
+void wolfSSL_AES_cfb128_encrypt(const unsigned char *in, unsigned char* out,
+        size_t len, AES_KEY *key, unsigned char* iv, int* num,
+        const int enc)
+{
+#ifndef WOLFSSL_AES_CFB
+    WOLFSSL_MSG("CFB mode not enabled please use macro WOLFSSL_AES_CFB");
+    (void)in;
+    (void)out;
+    (void)len;
+    (void)key;
+    (void)iv;
+    (void)num;
+    (void)enc;
+
+    return;
+#else
+    Aes* aes;
+
+    WOLFSSL_ENTER("wolfSSL_AES_cbc_encrypt");
+    if (key == NULL || in == NULL || out == NULL || iv == NULL) {
+        WOLFSSL_MSG("Error, Null argument passed in");
+        return;
+    }
+
+    aes = (Aes*)key;
+    if (wc_AesSetIV(aes, (const byte*)iv) != 0) {
+        WOLFSSL_MSG("Error with setting iv");
+        return;
+    }
+
+    if (enc == AES_ENCRYPT) {
+        if (wc_AesCfbEncrypt(aes, out, in, (word32)len) != 0) {
+            WOLFSSL_MSG("Error with AES CBC encrypt");
+        }
+    }
+    else {
+        if (wc_AesCfbDecrypt(aes, out, in, (word32)len) != 0) {
+            WOLFSSL_MSG("Error with AES CBC decrypt");
+        }
+    }
+
+    /* to be compatible copy iv to iv buffer after completing operation */
+    XMEMCPY(iv, (byte*)(aes->reg), AES_BLOCK_SIZE);
+
+    /* store number of left over bytes to num */
+    *num = (aes->left)? AES_BLOCK_SIZE - aes->left : 0;
+#endif /* WOLFSSL_AES_CFB */
+}
+#endif /* NO_AES */
+
+#ifndef NO_FILESYSTEM
+    #ifdef __clang__
+        #pragma clang diagnostic push
+        #pragma clang diagnostic ignored "-Wformat-nonliteral"
+    #endif
+#endif
+
+#if !defined(NO_FILESYSTEM) && defined (OPENSSL_EXTRA)
+/* returns amount printed on success, negative in fail case */
+int wolfSSL_BIO_vprintf(WOLFSSL_BIO* bio, const char* format, va_list args)
+{
+    int ret = -1;
+
+    if (bio == NULL)
+        return WOLFSSL_FATAL_ERROR;
+
+    switch (bio->type) {
+        case WOLFSSL_BIO_FILE:
+            if (bio->ptr == NULL) {
+                va_end(args);
+                return -1;
+            }
+            ret = vfprintf((XFILE)bio->ptr, format, args);
+            break;
+
+        case WOLFSSL_BIO_MEMORY:
+    #if defined(OPENSSL_EXTRA) && !defined(_WIN32)
+        case WOLFSSL_BIO_SSL:
+            {
+                int count;
+                char* pt = NULL;
+                va_list copy;
+
+                va_copy(copy, args);
+                count = vsnprintf(NULL, 0, format, args);
+                if (count >= 0)
+                {
+                    pt = (char*)XMALLOC(count + 1, bio->heap,
+                                        DYNAMIC_TYPE_TMP_BUFFER);
+                    if (pt != NULL)
+                    {
+                        count = vsnprintf(pt, count + 1, format, copy);
+                        if (count >= 0)
+                        {
+                            ret = wolfSSL_BIO_write(bio, pt, count);
+                        }
+                        XFREE(pt, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+                    }
+                }
+                va_end(copy);
+            }
+            break;
+    #endif
+
+        default:
+            WOLFSSL_MSG("Unsupported WOLFSSL_BIO type for wolfSSL_BIO_printf");
+            break;
+    }
+
+    return ret;
+}
+
+/* returns amount printed on success, negative in fail case */
+int wolfSSL_BIO_printf(WOLFSSL_BIO* bio, const char* format, ...)
+{
+    int ret;
+    va_list args;
+    va_start(args, format);
+
+    ret = wolfSSL_BIO_vprintf(bio, format, args);
+
+    va_end(args);
+
+    return ret;
+}
+
+#endif /* !defined(NO_FILESYSTEM) && defined (OPENSSL_EXTRA) */
+
+#if !defined(NO_FILESYSTEM) && defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
+#undef  LINE_LEN
+#define LINE_LEN 16
+int wolfSSL_BIO_dump(WOLFSSL_BIO *bio, const char *buf, int length)
+{
+    int ret = 0;
+
+    if (bio == NULL)
+        return 0;
+
+#ifndef NO_FILESYSTEM
+    if (bio->type == WOLFSSL_BIO_FILE) {
+        int i;
+        char line[80];
+
+        if (!buf) {
+            return fputs("\tNULL", (XFILE)bio->ptr);
+        }
+
+        sprintf(line, "\t");
+        for (i = 0; i < LINE_LEN; i++) {
+            if (i < length)
+                sprintf(line + 1 + i * 3,"%02x ", buf[i]);
+            else
+                sprintf(line + 1 + i * 3, "   ");
+        }
+        sprintf(line + 1 + LINE_LEN * 3, "| ");
+        for (i = 0; i < LINE_LEN; i++) {
+            if (i < length) {
+                sprintf(line + 3 + LINE_LEN * 3 + i,
+                     "%c", 31 < buf[i] && buf[i] < 127 ? buf[i] : '.');
+            }
+        }
+        ret += fputs(line, (XFILE)bio->ptr);
+
+        if (length > LINE_LEN)
+            ret += wolfSSL_BIO_dump(bio, buf + LINE_LEN, length - LINE_LEN);
+    }
+#else
+    (void)buf;
+    (void)length;
+#endif
+
+    return ret;
+}
+
+#ifndef NO_ASN_TIME
+int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_UTCTIME* a)
+{
+    WOLFSSL_ENTER("ASN1_UTCTIME_print");
+    if (bio == NULL || a == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+    if (a->type != ASN_UTC_TIME) {
+        WOLFSSL_MSG("Error, not UTC_TIME");
+        return WOLFSSL_FAILURE;
+    }
+
+    return wolfSSL_ASN1_TIME_print(bio, a);
+}
+
+/* Checks the ASN1 syntax of "a"
+ * returns WOLFSSL_SUCCESS (1)  if correct otherwise WOLFSSL_FAILURE (0) */
+int wolfSSL_ASN1_TIME_check(const WOLFSSL_ASN1_TIME* a)
+{
+    char buf[MAX_TIME_STRING_SZ];
+
+    WOLFSSL_ENTER("wolfSSL_ASN1_TIME_check");
+
+    /* if can parse the WOLFSSL_ASN1_TIME passed in then consider syntax good */
+    if (wolfSSL_ASN1_TIME_to_string((WOLFSSL_ASN1_TIME*)a, buf,
+                MAX_TIME_STRING_SZ) == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+    return WOLFSSL_SUCCESS;
+}
+#endif /* !NO_ASN_TIME */
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_ASN1_TIME_diff(int *pday, int *psec,
+                   const WOLFSSL_ASN1_TIME *from, const WOLFSSL_ASN1_TIME *to)
+{
+    WOLFSSL_STUB("wolfSSL_ASN1_TIME_diff");
+    (void)pday;
+    (void)psec;
+    (void)from;
+    (void)to;
+    return 0;
+}
+
+WOLFSSL_API WOLFSSL_ASN1_TIME *wolfSSL_ASN1_TIME_set(WOLFSSL_ASN1_TIME *s, time_t t)
+{
+    WOLFSSL_STUB("wolfSSL_ASN1_TIME_set");
+    (void)s;
+    (void)t;
+    return s;
+}
+#endif /* !NO_WOLFSSL_STUB */
+
+/* Return the month as a string.
+ *
+ * n  The number of the month as a two characters (1 based).
+ * returns the month as a string.
+ */
+static WC_INLINE const char* MonthStr(const char* n)
+{
+    static const char monthStr[12][4] = {
+            "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+            "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+    return monthStr[(n[0] - '0') * 10 + (n[1] - '0') - 1];
+}
+
+int wolfSSL_ASN1_GENERALIZEDTIME_print(WOLFSSL_BIO* bio,
+    const WOLFSSL_ASN1_GENERALIZEDTIME* asnTime)
+{
+    const char* p;
+    WOLFSSL_ENTER("wolfSSL_ASN1_GENERALIZEDTIME_print");
+
+    if (bio == NULL || asnTime == NULL)
+        return BAD_FUNC_ARG;
+
+    if (asnTime->type != ASN_GENERALIZED_TIME) {
+        WOLFSSL_MSG("Error, not GENERALIZED_TIME");
+        return WOLFSSL_FAILURE;
+    }
+    p = (const char *)(asnTime->data);
+    /* GetTimeString not always available. */
+    wolfSSL_BIO_write(bio, MonthStr(p + 4), 3);
+    wolfSSL_BIO_write(bio, " ", 1);
+    /* Day */
+    wolfSSL_BIO_write(bio, p + 6, 2);
+    wolfSSL_BIO_write(bio, " ", 1);
+    /* Hour */
+    wolfSSL_BIO_write(bio, p + 8, 2);
+    wolfSSL_BIO_write(bio, ":", 1);
+    /* Min */
+    wolfSSL_BIO_write(bio, p + 10, 2);
+    wolfSSL_BIO_write(bio, ":", 1);
+    /* Secs */
+    wolfSSL_BIO_write(bio, p + 12, 2);
+    wolfSSL_BIO_write(bio, " ", 1);
+    wolfSSL_BIO_write(bio, p, 4);
+
+    return 0;
+}
+
+void wolfSSL_ASN1_GENERALIZEDTIME_free(WOLFSSL_ASN1_TIME* asn1Time)
+{
+    WOLFSSL_ENTER("wolfSSL_ASN1_GENERALIZEDTIME_free");
+    if (asn1Time == NULL)
+        return;
+    XMEMSET(asn1Time->data, 0, sizeof(asn1Time->data));
+}
+
+int wolfSSL_sk_num(WOLFSSL_STACK* sk)
+{
+    WOLFSSL_ENTER("wolfSSL_sk_num");
+    if (sk == NULL)
+        return 0;
+    return (int)sk->num;
+}
+
+void* wolfSSL_sk_value(WOLFSSL_STACK* sk, int i)
+{
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+    int offset = i;
+#endif
+    WOLFSSL_ENTER("wolfSSL_sk_value");
+
+    for (; sk != NULL && i > 0; i--)
+        sk = sk->next;
+    if (sk == NULL)
+        return NULL;
+
+    switch (sk->type) {
+        case STACK_TYPE_X509:
+            return (void*)sk->data.x509;
+        case STACK_TYPE_CIPHER:
+        #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+            sk->data.cipher.offset = offset;
+        #endif
+            return (void*)&sk->data.cipher;
+        case STACK_TYPE_GEN_NAME:
+            return (void*)sk->data.gn;
+        case STACK_TYPE_ACCESS_DESCRIPTION:
+            return (void*)sk->data.access;
+        case STACK_TYPE_OBJ:
+            return (void*)sk->data.obj;
+        case STACK_TYPE_X509_EXT:
+            return (void*)sk->data.ext;
+        case STACK_TYPE_CONF_VALUE:
+            return (void*)sk->data.conf->value;
+        case STACK_TYPE_NULL:
+        default:
+            return (void*)sk->data.generic;
+    }
+}
+
+/* Free the structure for ASN1_OBJECT stack */
+void wolfSSL_sk_free(WOLFSSL_STACK* sk)
+{
+    WOLFSSL_ENTER("wolfSSL_sk_free");
+
+    if (sk == NULL) {
+        WOLFSSL_MSG("Error, BAD_FUNC_ARG");
+        return;
+    }
+
+    switch (sk->type) {
+        case STACK_TYPE_X509:
+            wolfSSL_sk_X509_free(sk);
+            break;
+        #if defined(OPENSSL_ALL)
+        case STACK_TYPE_CIPHER:
+            wolfSSL_sk_CIPHER_free(sk);
+            break;
+        #endif
+        case STACK_TYPE_GEN_NAME:
+            wolfSSL_sk_GENERAL_NAME_free(sk);
+            break;
+        #if defined(OPENSSL_ALL) || defined (WOLFSSL_QT)
+        case STACK_TYPE_ACCESS_DESCRIPTION:
+            wolfSSL_sk_ACCESS_DESCRIPTION_free(sk);
+            break;
+        #endif
+        case STACK_TYPE_OBJ:
+            wolfSSL_sk_ASN1_OBJECT_free(sk);
+            break;
+        #ifdef OPENSSL_ALL
+        case STACK_TYPE_X509_INFO:
+            wolfSSL_sk_X509_INFO_free(sk);
+            break;
+        case STACK_TYPE_X509_NAME:
+            wolfSSL_sk_X509_NAME_free(sk);
+            break;
+        case STACK_TYPE_CONF_VALUE:
+            wolfSSL_sk_CONF_VALUE_free(sk);
+            break;
+        #endif
+        case STACK_TYPE_NULL:
+        default:
+            wolfSSL_sk_GENERIC_free(sk);
+    }
+}
+/* Frees each node in the stack and frees the stack.
+ * Does not free any internal members of the stack nodes.
+ */
+void wolfSSL_sk_GENERIC_pop_free(WOLFSSL_STACK* sk,
+    void (*f) (void*))
+{
+    WOLFSSL_STACK* node;
+    WOLFSSL_STACK* tmp;
+    WOLFSSL_ENTER("wolfSSL_sk_GENERIC_pop_free");
+
+    if (sk == NULL)
+        return;
+
+    /* parse through stack freeing each node */
+    node = sk->next;
+    while (node) {
+        tmp  = node;
+        node = node->next;
+        if (f)
+            f(tmp->data.generic);
+        tmp->data.generic = NULL;
+        XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL);
+    }
+
+    /* free head of stack */
+    XFREE(sk, NULL, DYNAMIC_TYPE_ASN1);
+}
+
+/* return 1 on success 0 on fail */
+int wolfSSL_sk_GENERIC_push(WOLFSSL_STACK* sk, void* generic)
+{
+    WOLFSSL_STACK* node;
+
+    WOLFSSL_ENTER("wolfSSL_sk_GENERIC_push");
+
+    if (sk == NULL || generic == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* no previous values in stack */
+    if (sk->data.generic == NULL) {
+        sk->data.generic = generic;
+        sk->num += 1;
+        return WOLFSSL_SUCCESS;
+    }
+
+    /* stack already has value(s) create a new node and add more */
+    node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK),NULL,DYNAMIC_TYPE_SSL);
+    if (node == NULL) {
+        WOLFSSL_MSG("Memory error");
+        return WOLFSSL_FAILURE;
+    }
+    XMEMSET(node, 0, sizeof(WOLFSSL_STACK));
+
+    /* push new node onto head of stack */
+    node->type         = sk->type;
+    node->data.generic = sk->data.generic;
+    node->next         = sk->next;
+    sk->next           = node;
+    sk->data.generic   = generic;
+    sk->num           += 1;
+
+    return WOLFSSL_SUCCESS;
+}
+void wolfSSL_sk_GENERIC_free(WOLFSSL_STACK* sk)
+{
+    wolfSSL_sk_GENERIC_pop_free(sk, NULL);
+}
+
+
+/* Free all nodes in a stack */
+void wolfSSL_sk_pop_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk,
+                                                       wolfSSL_sk_freefunc func)
+{
+    WOLFSSL_ENTER("wolfSSL_sk_pop_free");
+
+    if (sk == NULL) {
+        WOLFSSL_MSG("Error, BAD_FUNC_ARG");
+        return;
+    }
+
+    switch(sk->type) {
+        #if defined(OPENSSL_ALL) || defined (WOLFSSL_QT)
+        case STACK_TYPE_ACCESS_DESCRIPTION:
+            wolfSSL_sk_ACCESS_DESCRIPTION_pop_free(sk,
+                                                wolfSSL_ACCESS_DESCRIPTION_free);
+            break;
+        #endif
+        case STACK_TYPE_X509:
+            wolfSSL_sk_X509_pop_free(sk,(void (*)(WOLFSSL_X509*))func);
+            break;
+        case STACK_TYPE_OBJ:
+            wolfSSL_sk_ASN1_OBJECT_pop_free(sk,
+                                          (void (*)(WOLFSSL_ASN1_OBJECT*))func);
+            break;
+        case STACK_TYPE_GEN_NAME:
+            wolfSSL_sk_GENERAL_NAME_pop_free(sk,
+                                         (void (*)(WOLFSSL_GENERAL_NAME*))func);
+            break;
+        #ifdef OPENSSL_ALL
+        case STACK_TYPE_X509_NAME:
+            wolfSSL_sk_X509_NAME_pop_free(sk,
+                                         (void (*)(WOLFSSL_X509_NAME*))func);
+            break;
+        case STACK_TYPE_X509_EXT:
+            wolfSSL_sk_X509_EXTENSION_pop_free(sk,
+                                       (void (*)(WOLFSSL_X509_EXTENSION*))func);
+            break;
+        #endif
+        #if defined(OPENSSL_ALL)
+        case STACK_TYPE_X509_INFO:
+            wolfSSL_sk_X509_INFO_pop_free(sk,
+                                            (void (*)(WOLFSSL_X509_INFO*))func);
+            break;
+        #endif
+        default:
+            wolfSSL_sk_GENERIC_pop_free(sk,
+                                          (void (*)(void*))func);
+            break;
+    }
+}
+
+#if defined(OPENSSL_ALL)
+/* Free the structure for WOLFSSL_CONF_VALUE stack
+ *
+ * sk  stack to free nodes in
+ */
+void wolfSSL_sk_CONF_VALUE_free(WOLF_STACK_OF(WOLFSSL_CONF_VALUE)* sk)
+{
+    WOLFSSL_STACK* node;
+    WOLFSSL_STACK* tmp;
+    WOLFSSL_ENTER("wolfSSL_sk_CONF_VALUE_free");
+
+    if (sk == NULL)
+        return;
+
+    /* parse through stack freeing each node */
+    node = sk->next;
+    while (node) {
+        tmp  = node;
+        node = node->next;
+        XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL);
+    }
+
+    /* free head of stack */
+    XFREE(sk, NULL, DYNAMIC_TYPE_ASN1);
+}
+#endif
+
+/* Creates and returns a new null stack. */
+WOLFSSL_STACK* wolfSSL_sk_new_null(void)
+{
+    WOLFSSL_STACK* sk;
+    WOLFSSL_ENTER("wolfSSL_sk_new_null");
+
+    sk = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+                                 DYNAMIC_TYPE_OPENSSL);
+    if (sk == NULL) {
+        WOLFSSL_MSG("WOLFSSL_STACK memory error");
+        return NULL;
+    }
+
+    XMEMSET(sk, 0, sizeof(WOLFSSL_STACK));
+    sk->type = STACK_TYPE_NULL;
+
+    return sk;
+}
+
+/* frees the wolfSSL_BASIC_CONSTRAINTS object */
+void wolfSSL_BASIC_CONSTRAINTS_free(WOLFSSL_BASIC_CONSTRAINTS *bc)
+{
+    WOLFSSL_ENTER("wolfSSL_BASIC_CONSTRAINTS_free");
+    if (bc == NULL) {
+        WOLFSSL_MSG("Argument is NULL");
+        return;
+    }
+    if (bc->pathlen) {
+        wolfSSL_ASN1_INTEGER_free(bc->pathlen);
+    }
+    XFREE(bc, NULL, DYNAMIC_TYPE_OPENSSL);
+}
+
+/* frees the wolfSSL_AUTHORITY_KEYID object */
+void wolfSSL_AUTHORITY_KEYID_free(WOLFSSL_AUTHORITY_KEYID *id)
+{
+    WOLFSSL_ENTER("wolfSSL_AUTHORITY_KEYID_free");
+    if(id == NULL) {
+        WOLFSSL_MSG("Argument is NULL");
+        return;
+    }
+    if (id->keyid) {
+        wolfSSL_ASN1_STRING_free(id->keyid);
+    }
+    if (id->issuer) {
+        wolfSSL_ASN1_OBJECT_free(id->issuer);
+    }
+    if (id->serial) {
+        wolfSSL_ASN1_INTEGER_free(id->serial);
+    }
+    XFREE(id, NULL, DYNAMIC_TYPE_OPENSSL);
+}
+
+int wolfSSL_sk_SSL_COMP_num(WOLF_STACK_OF(WOLFSSL_COMP)* sk)
+{
+    if (sk == NULL)
+        return 0;
+    return (int)sk->num;
+}
+
+#endif /* OPENSSL_EXTRA */
+
+#if defined(OPENSSL_EXTRA) || defined(HAVE_EXT_CACHE)
+/* stunnel 4.28 needs
+ *
+ * Callback that is called if a session tries to resume but could not find
+ * the session to resume it.
+ */
+void wolfSSL_CTX_sess_set_get_cb(WOLFSSL_CTX* ctx,
+                    WOLFSSL_SESSION*(*f)(WOLFSSL*, unsigned char*, int, int*))
+{
+    if (ctx == NULL)
+        return;
+
+#ifdef HAVE_EXT_CACHE
+    ctx->get_sess_cb = f;
+#else
+    (void)f;
+#endif
+}
+
+void wolfSSL_CTX_sess_set_new_cb(WOLFSSL_CTX* ctx,
+                             int (*f)(WOLFSSL*, WOLFSSL_SESSION*))
+{
+    if (ctx == NULL)
+        return;
+
+#ifdef HAVE_EXT_CACHE
+    ctx->new_sess_cb = f;
+#else
+    (void)f;
+#endif
+}
+
+void wolfSSL_CTX_sess_set_remove_cb(WOLFSSL_CTX* ctx, void (*f)(WOLFSSL_CTX*,
+                                                        WOLFSSL_SESSION*))
+{
+    if (ctx == NULL)
+        return;
+
+#ifdef HAVE_EXT_CACHE
+    ctx->rem_sess_cb = f;
+#else
+    (void)f;
+#endif
+}
+#endif /* OPENSSL_EXTRA || HAVE_EXT_CACHE */
+
+#ifdef OPENSSL_EXTRA
+
+/*
+ *
+ * Note: It is expected that the importing and exporting function have been
+ *       built with the same settings. For example if session tickets was
+ *       enabled with the wolfSSL library exporting a session then it is
+ *       expected to be turned on with the wolfSSL library importing the session.
+ */
+int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p)
+{
+    int size = 0;
+#ifdef HAVE_EXT_CACHE
+    int idx = 0;
+#ifdef SESSION_CERTS
+    int i;
+#endif
+    unsigned char *data;
+
+    if (sess == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* bornOn | timeout | sessionID len | sessionID | masterSecret | haveEMS */
+    size += OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN + sess->sessionIDSz +
+            SECRET_LEN + OPAQUE8_LEN;
+#ifdef SESSION_CERTS
+    /* Peer chain */
+    size += OPAQUE8_LEN;
+    for (i = 0; i < sess->chain.count; i++)
+        size += OPAQUE16_LEN + sess->chain.certs[i].length;
+#endif
+#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
+                               defined(HAVE_SESSION_TICKET))
+    /* Protocol version */
+    size += OPAQUE16_LEN;
+#endif
+#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \
+                        (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET))
+    /* cipher suite */
+    size += OPAQUE16_LEN;
+#endif
+#ifndef NO_CLIENT_CACHE
+    /* ServerID len | ServerID */
+    size += OPAQUE16_LEN + sess->idLen;
+#endif
+#ifdef OPENSSL_EXTRA
+    /* session context ID len | session context ID */
+    size += OPAQUE8_LEN + sess->sessionCtxSz;
+#endif
+#ifdef WOLFSSL_TLS13
+    /* namedGroup */
+    size += OPAQUE16_LEN;
+#endif
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+#ifdef WOLFSSL_TLS13
+    /* ticketSeen | ticketAdd */
+    size += OPAQUE32_LEN + OPAQUE32_LEN;
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    /* ticketNonce */
+    size += OPAQUE8_LEN + sess->ticketNonce.len;
+#endif
+#endif
+#ifdef WOLFSSL_EARLY_DATA
+    size += OPAQUE32_LEN;
+#endif
+#endif
+#ifdef HAVE_SESSION_TICKET
+    /* ticket len | ticket */
+    size += OPAQUE16_LEN + sess->ticketLen;
+#endif
+
+    if (p != NULL) {
+        if (*p == NULL)
+            *p = (unsigned char*)XMALLOC(size, NULL, DYNAMIC_TYPE_OPENSSL);
+        if (*p == NULL)
+            return 0;
+        data = *p;
+
+        c32toa(sess->bornOn, data + idx); idx += OPAQUE32_LEN;
+        c32toa(sess->timeout, data + idx); idx += OPAQUE32_LEN;
+        data[idx++] = sess->sessionIDSz;
+        XMEMCPY(data + idx, sess->sessionID, sess->sessionIDSz);
+        idx += sess->sessionIDSz;
+        XMEMCPY(data + idx, sess->masterSecret, SECRET_LEN); idx += SECRET_LEN;
+        data[idx++] = (byte)sess->haveEMS;
+#ifdef SESSION_CERTS
+        data[idx++] = (byte)sess->chain.count;
+        for (i = 0; i < sess->chain.count; i++) {
+            c16toa((word16)sess->chain.certs[i].length, data + idx);
+            idx += OPAQUE16_LEN;
+            XMEMCPY(data + idx, sess->chain.certs[i].buffer,
+                    sess->chain.certs[i].length);
+            idx += sess->chain.certs[i].length;
+        }
+#endif
+#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
+                               defined(HAVE_SESSION_TICKET))
+        data[idx++] = sess->version.major;
+        data[idx++] = sess->version.minor;
+#endif
+#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \
+                        (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET))
+        data[idx++] = sess->cipherSuite0;
+        data[idx++] = sess->cipherSuite;
+#endif
+#ifndef NO_CLIENT_CACHE
+        c16toa(sess->idLen, data + idx); idx += OPAQUE16_LEN;
+        XMEMCPY(data + idx, sess->serverID, sess->idLen);
+        idx += sess->idLen;
+#endif
+#ifdef OPENSSL_EXTRA
+        data[idx++] = sess->sessionCtxSz;
+        XMEMCPY(data + idx, sess->sessionCtx, sess->sessionCtxSz);
+        idx += sess->sessionCtxSz;
+#endif
+#ifdef WOLFSSL_TLS13
+        c16toa(sess->namedGroup, data + idx);
+        idx += OPAQUE16_LEN;
+#endif
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+#ifdef WOLFSSL_TLS13
+    c32toa(sess->ticketSeen, data + idx);
+    idx += OPAQUE32_LEN;
+    c32toa(sess->ticketAdd, data + idx);
+    idx += OPAQUE32_LEN;
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    data[idx++] = sess->ticketNonce.len;
+    XMEMCPY(data + idx, sess->ticketNonce.data, sess->ticketNonce.len);
+    idx += sess->ticketNonce.len;
+#endif
+#endif
+#ifdef WOLFSSL_EARLY_DATA
+        c32toa(sess->maxEarlyDataSz, data + idx);
+        idx += OPAQUE32_LEN;
+#endif
+#endif
+#ifdef HAVE_SESSION_TICKET
+        c16toa(sess->ticketLen, data + idx); idx += OPAQUE16_LEN;
+        XMEMCPY(data + idx, sess->ticket, sess->ticketLen);
+        idx += sess->ticketLen;
+#endif
+    }
+#endif
+
+    (void)sess;
+    (void)p;
+#ifdef HAVE_EXT_CACHE
+    (void)idx;
+#endif
+
+    return size;
+}
+
+
+/* TODO: no function to free new session.
+ *
+ * Note: It is expected that the importing and exporting function have been
+ *       built with the same settings. For example if session tickets was
+ *       enabled with the wolfSSL library exporting a session then it is
+ *       expected to be turned on with the wolfSSL library importing the session.
+ */
+WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess,
+                                const unsigned char** p, long i)
+{
+    WOLFSSL_SESSION* s = NULL;
+    int ret = 0;
+#if defined(HAVE_EXT_CACHE)
+    int idx;
+    byte* data;
+#ifdef SESSION_CERTS
+    int j;
+    word16 length;
+#endif
+#endif
+
+    (void)p;
+    (void)i;
+    (void)ret;
+
+    if (sess != NULL)
+        s = *sess;
+
+#ifdef HAVE_EXT_CACHE
+    if (p == NULL || *p == NULL)
+        return NULL;
+
+    if (s == NULL) {
+        s = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), NULL,
+                                      DYNAMIC_TYPE_OPENSSL);
+        if (s == NULL)
+            return NULL;
+        XMEMSET(s, 0, sizeof(WOLFSSL_SESSION));
+        s->isAlloced = 1;
+#ifdef HAVE_SESSION_TICKET
+        s->isDynamic = 0;
+#endif
+    }
+
+    idx = 0;
+    data = (byte*)*p;
+
+    /* bornOn | timeout | sessionID len */
+    if (i < OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN) {
+        ret = BUFFER_ERROR;
+        goto end;
+    }
+    ato32(data + idx, &s->bornOn); idx += OPAQUE32_LEN;
+    ato32(data + idx, &s->timeout); idx += OPAQUE32_LEN;
+    s->sessionIDSz = data[idx++];
+
+    /* sessionID | secret | haveEMS */
+    if (i - idx < s->sessionIDSz + SECRET_LEN + OPAQUE8_LEN) {
+        ret = BUFFER_ERROR;
+        goto end;
+    }
+    XMEMCPY(s->sessionID, data + idx, s->sessionIDSz);
+    idx  += s->sessionIDSz;
+    XMEMCPY(s->masterSecret, data + idx, SECRET_LEN); idx += SECRET_LEN;
+    s->haveEMS = data[idx++];
+
+#ifdef SESSION_CERTS
+    /* Certificate chain */
+    if (i - idx == 0) {
+        ret = BUFFER_ERROR;
+        goto end;
+    }
+    s->chain.count = data[idx++];
+    for (j = 0; j < s->chain.count; j++) {
+        if (i - idx < OPAQUE16_LEN) {
+            ret = BUFFER_ERROR;
+            goto end;
+        }
+        ato16(data + idx, &length); idx += OPAQUE16_LEN;
+        s->chain.certs[j].length = length;
+        if (i - idx < length) {
+            ret = BUFFER_ERROR;
+            goto end;
+        }
+        XMEMCPY(s->chain.certs[j].buffer, data + idx, length);
+        idx += length;
+    }
+#endif
+#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
+                               defined(HAVE_SESSION_TICKET))
+    /* Protocol Version */
+    if (i - idx < OPAQUE16_LEN) {
+        ret = BUFFER_ERROR;
+        goto end;
+    }
+    s->version.major = data[idx++];
+    s->version.minor = data[idx++];
+#endif
+#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \
+                        (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET))
+    /* Cipher suite */
+    if (i - idx < OPAQUE16_LEN) {
+        ret = BUFFER_ERROR;
+        goto end;
+    }
+    s->cipherSuite0 = data[idx++];
+    s->cipherSuite = data[idx++];
+#endif
+#ifndef NO_CLIENT_CACHE
+    /* ServerID len */
+    if (i - idx < OPAQUE16_LEN) {
+        ret = BUFFER_ERROR;
+        goto end;
+    }
+    ato16(data + idx, &s->idLen); idx += OPAQUE16_LEN;
+
+    /* ServerID */
+    if (i - idx < s->idLen) {
+        ret = BUFFER_ERROR;
+        goto end;
+    }
+    XMEMCPY(s->serverID, data + idx, s->idLen); idx += s->idLen;
+#endif
+#ifdef OPENSSL_EXTRA
+    /* byte for length of session context ID */
+    if (i - idx < OPAQUE8_LEN) {
+        ret = BUFFER_ERROR;
+        goto end;
+    }
+    s->sessionCtxSz = data[idx++];
+
+    /* app session context ID */
+    if (i - idx < s->sessionCtxSz) {
+        ret = BUFFER_ERROR;
+        goto end;
+    }
+    XMEMCPY(s->sessionCtx, data + idx, s->sessionCtxSz); idx += s->sessionCtxSz;
+#endif
+#ifdef WOLFSSL_TLS13
+    if (i - idx < OPAQUE16_LEN) {
+        ret = BUFFER_ERROR;
+        goto end;
+    }
+    ato16(data + idx, &s->namedGroup);
+    idx += OPAQUE16_LEN;
+#endif
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+#ifdef WOLFSSL_TLS13
+    if (i - idx < (OPAQUE32_LEN * 2)) {
+        ret = BUFFER_ERROR;
+        goto end;
+    }
+    ato32(data + idx, &s->ticketSeen);
+    idx += OPAQUE32_LEN;
+    ato32(data + idx, &s->ticketAdd);
+    idx += OPAQUE32_LEN;
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    if (i - idx < OPAQUE8_LEN) {
+        ret = BUFFER_ERROR;
+        goto end;
+    }
+    s->ticketNonce.len = data[idx++];
+
+    if (i - idx < s->ticketNonce.len) {
+        ret = BUFFER_ERROR;
+        goto end;
+    }
+    XMEMCPY(s->ticketNonce.data, data + idx, s->ticketNonce.len);
+    idx += s->ticketNonce.len;
+#endif
+#endif
+#ifdef WOLFSSL_EARLY_DATA
+    if (i - idx < OPAQUE32_LEN) {
+        ret = BUFFER_ERROR;
+        goto end;
+    }
+    ato32(data + idx, &s->maxEarlyDataSz);
+    idx += OPAQUE32_LEN;
+#endif
+#endif
+#ifdef HAVE_SESSION_TICKET
+    /* ticket len */
+    if (i - idx < OPAQUE16_LEN) {
+        ret = BUFFER_ERROR;
+        goto end;
+    }
+    ato16(data + idx, &s->ticketLen); idx += OPAQUE16_LEN;
+
+    /* Dispose of ol dynamic ticket and ensure space for new ticket. */
+    if (s->isDynamic)
+        XFREE(s->ticket, NULL, DYNAMIC_TYPE_SESSION_TICK);
+    if (s->ticketLen <= SESSION_TICKET_LEN)
+        s->ticket = s->staticTicket;
+    else {
+        s->ticket = (byte*)XMALLOC(s->ticketLen, NULL,
+                                   DYNAMIC_TYPE_SESSION_TICK);
+        if (s->ticket == NULL) {
+            ret = MEMORY_ERROR;
+            goto end;
+        }
+        s->isDynamic = 1;
+    }
+
+    /* ticket */
+    if (i - idx < s->ticketLen) {
+        ret = BUFFER_ERROR;
+        goto end;
+    }
+    XMEMCPY(s->ticket, data + idx, s->ticketLen); idx += s->ticketLen;
+#endif
+    (void)idx;
+
+    if (sess != NULL)
+        *sess = s;
+
+    *p += idx;
+
+end:
+    if (ret != 0 && (sess == NULL || *sess != s))
+        wolfSSL_SESSION_free(s);
+#endif
+    return s;
+}
+
+
+long wolfSSL_SESSION_get_timeout(const WOLFSSL_SESSION* sess)
+{
+    long timeout = 0;
+    WOLFSSL_ENTER("wolfSSL_SESSION_get_timeout");
+    if (sess)
+        timeout = sess->timeout;
+    return timeout;
+}
+
+
+long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION* sess)
+{
+    long bornOn = 0;
+    WOLFSSL_ENTER("wolfSSL_SESSION_get_time");
+    if (sess)
+        bornOn = sess->bornOn;
+    return bornOn;
+}
+
+
+#endif /* OPENSSL_EXTRA */
+
+
+#ifdef KEEP_PEER_CERT
+char*  wolfSSL_X509_get_subjectCN(WOLFSSL_X509* x509)
+{
+    if (x509 == NULL)
+        return NULL;
+
+    return x509->subjectCN;
+}
+#endif /* KEEP_PEER_CERT */
+
+#ifdef OPENSSL_EXTRA
+
+#if defined(FORTRESS) && !defined(NO_FILESYSTEM)
+int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname)
+{
+    int ret = WOLFSSL_FATAL_ERROR;
+
+    WOLFSSL_ENTER("wolfSSL_cmp_peer_cert_to_file");
+    if (ssl != NULL && fname != NULL)
+    {
+    #ifdef WOLFSSL_SMALL_STACK
+        byte           staticBuffer[1]; /* force heap usage */
+    #else
+        byte           staticBuffer[FILE_BUFFER_SIZE];
+    #endif
+        byte*          myBuffer  = staticBuffer;
+        int            dynamic   = 0;
+        XFILE          file;
+        long           sz        = 0;
+        WOLFSSL_CTX*   ctx       = ssl->ctx;
+        WOLFSSL_X509*  peer_cert = &ssl->peerCert;
+        DerBuffer*     fileDer = NULL;
+
+        file = XFOPEN(fname, "rb");
+        if (file == XBADFILE)
+            return WOLFSSL_BAD_FILE;
+
+        if (XFSEEK(file, 0, XSEEK_END) != 0) {
+            XFCLOSE(file);
+            return WOLFSSL_BAD_FILE;
+        }
+        sz = XFTELL(file);
+        XREWIND(file);
+
+        if (sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) {
+            WOLFSSL_MSG("cmp_peer_cert_to_file size error");
+            XFCLOSE(file);
+            return WOLFSSL_BAD_FILE;
+        }
+
+        if (sz > (long)sizeof(staticBuffer)) {
+            WOLFSSL_MSG("Getting dynamic buffer");
+            myBuffer = (byte*)XMALLOC(sz, ctx->heap, DYNAMIC_TYPE_FILE);
+            dynamic = 1;
+        }
+
+        if ((myBuffer != NULL) &&
+            (sz > 0) &&
+            (XFREAD(myBuffer, 1, sz, file) == (size_t)sz) &&
+            (PemToDer(myBuffer, (long)sz, CERT_TYPE,
+                      &fileDer, ctx->heap, NULL, NULL) == 0) &&
+            (fileDer->length != 0) &&
+            (fileDer->length == peer_cert->derCert->length) &&
+            (XMEMCMP(peer_cert->derCert->buffer, fileDer->buffer,
+                                                fileDer->length) == 0))
+        {
+            ret = 0;
+        }
+
+        FreeDer(&fileDer);
+
+        if (dynamic)
+            XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE);
+
+        XFCLOSE(file);
+    }
+
+    return ret;
+}
+#endif
+#endif /* OPENSSL_EXTRA */
+#endif /* !WOLFCRYPT_ONLY */
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+const WOLFSSL_ObjectInfo wolfssl_object_info[] = {
+#ifndef NO_CERTS
+    /* oidCertExtType */
+    { NID_basic_constraints, BASIC_CA_OID, oidCertExtType, "basicConstraints",
+                                                "X509v3 Basic Constraints"},
+    { NID_subject_alt_name, ALT_NAMES_OID, oidCertExtType, "subjectAltName",
+                                         "X509v3 Subject Alternative Name"},
+    { CRL_DIST_OID, CRL_DIST_OID, oidCertExtType, "crlDistributionPoints",
+                                          "X509v3 CRL Distribution Points"},
+    { NID_info_access, AUTH_INFO_OID, oidCertExtType, "authorityInfoAccess",
+                                            "Authority Information Access"},
+    { NID_authority_key_identifier, AUTH_KEY_OID, oidCertExtType,
+               "authorityKeyIdentifier", "X509v3 Authority Key Identifier"},
+    { NID_subject_key_identifier, SUBJ_KEY_OID, oidCertExtType,
+                   "subjectKeyIdentifier", "X509v3 Subject Key Identifier"},
+    { NID_key_usage, KEY_USAGE_OID, oidCertExtType, "keyUsage",
+                                                        "X509v3 Key Usage"},
+    { NID_inhibit_any_policy, INHIBIT_ANY_OID, oidCertExtType,
+                           "inhibitAnyPolicy", "X509v3 Inhibit Any Policy"},
+    { NID_ext_key_usage, KEY_USAGE_OID, oidCertExtType,
+                           "extendedKeyUsage", "X509v3 Extended Key Usage"},
+    { NID_name_constraints, NAME_CONS_OID, oidCertExtType,
+                              "nameConstraints", "X509v3 Name Constraints"},
+    { NID_certificate_policies, CERT_POLICY_OID, oidCertExtType,
+                      "certificatePolicies", "X509v3 Certificate Policies"},
+
+    /* oidCertAuthInfoType */
+    { AIA_OCSP_OID, AIA_OCSP_OID, oidCertAuthInfoType, "authorityInfoAccess",
+                                            "Authority Information Access"},
+    { AIA_CA_ISSUER_OID, AIA_CA_ISSUER_OID, oidCertAuthInfoType,
+                                                 "caIssuers", "CA Issuers"},
+
+    /* oidCertPolicyType */
+    { NID_any_policy, CP_ANY_OID, oidCertPolicyType, "anyPolicy",
+                                                       "X509v3 Any Policy"},
+
+    /* oidCertAltNameType */
+    { NID_hw_name_oid, HW_NAME_OID, oidCertAltNameType, "Hardware name",""},
+
+    /* oidCertKeyUseType */
+    { NID_anyExtendedKeyUsage, EKU_ANY_OID, oidCertKeyUseType,
+                           "anyExtendedKeyUsage", "Any Extended Key Usage"},
+    { EKU_SERVER_AUTH_OID, EKU_SERVER_AUTH_OID, oidCertKeyUseType,
+                             "serverAuth", "TLS Web Server Authentication"},
+    { EKU_CLIENT_AUTH_OID, EKU_CLIENT_AUTH_OID, oidCertKeyUseType,
+                             "clientAuth", "TLS Web Client Authentication"},
+    { EKU_OCSP_SIGN_OID, EKU_OCSP_SIGN_OID, oidCertKeyUseType,
+                                             "OCSPSigning", "OCSP Signing"},
+
+    /* oidCertNameType */
+    { NID_commonName, NID_commonName, oidCertNameType, "CN", "commonName"},
+    { NID_surname, NID_surname, oidCertNameType, "SN", "surname"},
+    { NID_serialNumber, NID_serialNumber, oidCertNameType, "serialNumber",
+                                                            "serialNumber"},
+    { NID_countryName, NID_countryName, oidCertNameType, "C", "countryName"},
+    { NID_localityName, NID_localityName, oidCertNameType, "L", "localityName"},
+    { NID_stateOrProvinceName, NID_stateOrProvinceName, oidCertNameType, "ST",
+                                                        "stateOrProvinceName"},
+    { NID_organizationName, NID_organizationName, oidCertNameType, "O",
+                                                        "organizationName"},
+    { NID_organizationalUnitName, NID_organizationalUnitName, oidCertNameType,
+                                                "OU", "organizationalUnitName"},
+    { NID_emailAddress, NID_emailAddress, oidCertNameType, "emailAddress",
+                                                            "emailAddress"},
+    { NID_domainComponent, NID_domainComponent, oidCertNameType, "DC",
+                                                            "domainComponent"},
+    { NID_businessCategory, NID_businessCategory, oidCertNameType, "businessCategory",
+                                                            "businessCategory"},
+    { NID_jurisdictionCountryName, NID_jurisdictionCountryName, oidCertNameType, "jurisdictionC",
+                                                            "jurisdictionCountryName"},
+    { NID_jurisdictionStateOrProvinceName, NID_jurisdictionStateOrProvinceName,
+            oidCertNameType, "jurisdictionST", "jurisdictionStateOrProvinceName"},
+#endif
+#ifdef OPENSSL_EXTRA /* OPENSSL_EXTRA_X509_SMALL only needs the above */
+        /* oidHashType */
+    #ifdef WOLFSSL_MD2
+        { NID_md2, MD2h, oidHashType, "MD2", "md2"},
+    #endif
+    #ifdef WOLFSSL_MD5
+        { NID_md5, MD5h, oidHashType, "MD5", "md5"},
+    #endif
+    #ifndef NO_SHA
+        { NID_sha1, SHAh, oidHashType, "SHA1", "sha1"},
+    #endif
+    #ifdef WOLFSSL_SHA224
+        { NID_sha224, SHA224h, oidHashType, "SHA224", "sha224"},
+    #endif
+    #ifndef NO_SHA256
+        { NID_sha256, SHA256h, oidHashType, "SHA256", "sha256"},
+    #endif
+    #ifdef WOLFSSL_SHA384
+        { NID_sha384, SHA384h, oidHashType, "SHA384", "sha384"},
+    #endif
+    #ifdef WOLFSSL_SHA512
+        { NID_sha512, SHA512h, oidHashType, "SHA512", "sha512"},
+    #endif
+
+        /* oidSigType */
+    #ifndef NO_DSA
+        #ifndef NO_SHA
+        { CTC_SHAwDSA, CTC_SHAwDSA, oidSigType, "DSA-SHA1", "dsaWithSHA1"},
+        #endif
+    #endif /* NO_DSA */
+    #ifndef NO_RSA
+        #ifdef WOLFSSL_MD2
+        { CTC_MD2wRSA, CTC_MD2wRSA, oidSigType, "RSA-MD2",
+                                                        "md2WithRSAEncryption"},
+        #endif
+        #ifndef NO_MD5
+        { CTC_MD5wRSA, CTC_MD5wRSA, oidSigType, "RSA-MD5",
+                                                        "md5WithRSAEncryption"},
+        #endif
+        #ifndef NO_SHA
+        { CTC_SHAwRSA, CTC_SHAwRSA, oidSigType, "RSA-SHA1",
+                                                       "sha1WithRSAEncryption"},
+        #endif
+        #ifdef WOLFSSL_SHA224
+        { CTC_SHA224wRSA, CTC_SHA224wRSA, oidSigType, "RSA-SHA224",
+                                                     "sha224WithRSAEncryption"},
+        #endif
+        #ifndef NO_SHA256
+        { CTC_SHA256wRSA, CTC_SHA256wRSA, oidSigType, "RSA-SHA256",
+                                                     "sha256WithRSAEncryption"},
+        #endif
+        #ifdef WOLFSSL_SHA384
+        { CTC_SHA384wRSA, CTC_SHA384wRSA, oidSigType, "RSA-SHA384",
+                                                     "sha384WithRSAEncryption"},
+        #endif
+        #ifdef WOLFSSL_SHA512
+        { CTC_SHA512wRSA, CTC_SHA512wRSA, oidSigType, "RSA-SHA512",
+                                                     "sha512WithRSAEncryption"},
+        #endif
+    #endif /* NO_RSA */
+    #ifdef HAVE_ECC
+        #ifndef NO_SHA
+        { CTC_SHAwECDSA, CTC_SHAwECDSA, oidSigType, "ecdsa-with-SHA1", "shaWithECDSA"},
+        #endif
+        #ifdef WOLFSSL_SHA224
+        { CTC_SHA224wECDSA, CTC_SHA224wECDSA, oidSigType, "ecdsa-with-SHA224","sha224WithECDSA"},
+        #endif
+        #ifndef NO_SHA256
+        { CTC_SHA256wECDSA, CTC_SHA256wECDSA, oidSigType, "ecdsa-with-SHA256","sha256WithECDSA"},
+        #endif
+        #ifdef WOLFSSL_SHA384
+        { CTC_SHA384wECDSA, CTC_SHA384wECDSA, oidSigType, "ecdsa-with-SHA384","sha384WithECDSA"},
+        #endif
+        #ifdef WOLFSSL_SHA512
+        { CTC_SHA512wECDSA, CTC_SHA512wECDSA, oidSigType, "ecdsa-with-SHA512","sha512WithECDSA"},
+        #endif
+    #endif /* HAVE_ECC */
+
+        /* oidKeyType */
+    #ifndef NO_DSA
+        { DSAk, DSAk, oidKeyType, "DSA", "dsaEncryption"},
+        { NID_dsa, DSAk, oidKeyType, "DSA", "dsaEncryption"},
+    #endif /* NO_DSA */
+    #ifndef NO_RSA
+        { RSAk, RSAk, oidKeyType, "RSA", "rsaEncryption"},
+        { NID_rsaEncryption, RSAk, oidKeyType, "RSA", "rsaEncryption"},
+    #endif /* NO_RSA */
+    #ifdef HAVE_NTRU
+        { NTRUk, NTRUk, oidKeyType, "NTRU", "ntruEncryption"},
+    #endif /* HAVE_NTRU */
+    #ifdef HAVE_ECC
+        { ECDSAk, ECDSAk, oidKeyType, "ECDSA", "ecdsaEncryption"},
+        { NID_X9_62_id_ecPublicKey, ECDSAk, oidKeyType, "id-ecPublicKey",
+                                                        "id-ecPublicKey"},
+    #endif /* HAVE_ECC */
+    #ifndef NO_DH
+        { NID_dhKeyAgreement, DHk, oidKeyType, "dhKeyAgreement", "dhKeyAgreement"},
+    #endif
+
+        /* oidCurveType */
+    #ifdef HAVE_ECC
+        { NID_X9_62_prime192v1, ECC_SECP192R1_OID, oidCurveType, "prime192v1", "prime192v1"},
+        { NID_X9_62_prime192v2, ECC_PRIME192V2_OID, oidCurveType, "prime192v2", "prime192v2"},
+        { NID_X9_62_prime192v3, ECC_PRIME192V3_OID, oidCurveType, "prime192v3", "prime192v3"},
+
+        { NID_X9_62_prime239v1, ECC_PRIME239V1_OID, oidCurveType, "prime239v1", "prime239v1"},
+        { NID_X9_62_prime239v2, ECC_PRIME239V2_OID, oidCurveType, "prime239v2", "prime239v2"},
+        { NID_X9_62_prime239v3, ECC_PRIME239V3_OID, oidCurveType, "prime239v3", "prime239v3"},
+
+        { NID_X9_62_prime256v1, ECC_SECP256R1_OID, oidCurveType, "prime256v1", "prime256v1"},
+
+        { NID_secp112r1, ECC_SECP112R1_OID,  oidCurveType, "secp112r1", "secp112r1"},
+        { NID_secp112r2, ECC_SECP112R2_OID,  oidCurveType, "secp112r2", "secp112r2"},
+
+        { NID_secp128r1, ECC_SECP128R1_OID,  oidCurveType, "secp128r1", "secp128r1"},
+        { NID_secp128r2, ECC_SECP128R2_OID,  oidCurveType, "secp128r2", "secp128r2"},
+
+        { NID_secp160r1, ECC_SECP160R1_OID,  oidCurveType, "secp160r1", "secp160r1"},
+        { NID_secp160r2, ECC_SECP160R2_OID,  oidCurveType, "secp160r2", "secp160r2"},
+
+        { NID_secp224r1, ECC_SECP224R1_OID,  oidCurveType, "secp224r1", "secp224r1"},
+        { NID_secp384r1, ECC_SECP384R1_OID,  oidCurveType, "secp384r1", "secp384r1"},
+        { NID_secp521r1, ECC_SECP521R1_OID,  oidCurveType, "secp521r1", "secp521r1"},
+
+        { NID_secp160k1, ECC_SECP160K1_OID,  oidCurveType, "secp160k1", "secp160k1"},
+        { NID_secp192k1, ECC_SECP192K1_OID,  oidCurveType, "secp192k1", "secp192k1"},
+        { NID_secp224k1, ECC_SECP224K1_OID,  oidCurveType, "secp224k1", "secp224k1"},
+        { NID_secp256k1, ECC_SECP256K1_OID,  oidCurveType, "secp256k1", "secp256k1"},
+
+        { NID_brainpoolP160r1, ECC_BRAINPOOLP160R1_OID,  oidCurveType, "brainpoolP160r1", "brainpoolP160r1"},
+        { NID_brainpoolP192r1, ECC_BRAINPOOLP192R1_OID,  oidCurveType, "brainpoolP192r1", "brainpoolP192r1"},
+        { NID_brainpoolP224r1, ECC_BRAINPOOLP224R1_OID,  oidCurveType, "brainpoolP224r1", "brainpoolP224r1"},
+        { NID_brainpoolP256r1, ECC_BRAINPOOLP256R1_OID,  oidCurveType, "brainpoolP256r1", "brainpoolP256r1"},
+        { NID_brainpoolP320r1, ECC_BRAINPOOLP320R1_OID,  oidCurveType, "brainpoolP320r1", "brainpoolP320r1"},
+        { NID_brainpoolP384r1, ECC_BRAINPOOLP384R1_OID,  oidCurveType, "brainpoolP384r1", "brainpoolP384r1"},
+        { NID_brainpoolP512r1, ECC_BRAINPOOLP512R1_OID,  oidCurveType, "brainpoolP512r1", "brainpoolP512r1"},
+    #endif /* HAVE_ECC */
+
+        /* oidBlkType */
+    #ifdef WOLFSSL_AES_128
+        { AES128CBCb, AES128CBCb, oidBlkType, "AES-128-CBC", "aes-128-cbc"},
+    #endif
+    #ifdef WOLFSSL_AES_192
+        { AES192CBCb, AES192CBCb, oidBlkType, "AES-192-CBC", "aes-192-cbc"},
+    #endif
+    #ifdef WOLFSSL_AES_256
+        { AES256CBCb, AES256CBCb, oidBlkType, "AES-256-CBC", "aes-256-cbc"},
+    #endif
+    #ifndef NO_DES3
+        { NID_des, DESb, oidBlkType, "DES-CBC", "des-cbc"},
+        { NID_des3, DES3b, oidBlkType, "DES-EDE3-CBC", "des-ede3-cbc"},
+    #endif /* !NO_DES3 */
+
+        /* oidOcspType */
+    #ifdef HAVE_OCSP
+        { NID_id_pkix_OCSP_basic, OCSP_BASIC_OID, oidOcspType, "basicOCSPResponse",
+                                                         "Basic OCSP Response"},
+        { OCSP_NONCE_OID, OCSP_NONCE_OID, oidOcspType, "Nonce",
+                                                                  "OCSP Nonce"},
+    #endif /* HAVE_OCSP */
+
+    #ifndef NO_PWDBASED
+        /* oidKdfType */
+        { PBKDF2_OID, PBKDF2_OID, oidKdfType, "PBKDFv2", "PBKDF2"},
+
+        /* oidPBEType */
+        { PBE_SHA1_RC4_128, PBE_SHA1_RC4_128, oidPBEType,
+                                 "PBE-SHA1-RC4-128", "pbeWithSHA1And128BitRC4"},
+        { PBE_SHA1_DES, PBE_SHA1_DES, oidPBEType, "PBE-SHA1-DES",
+                                                       "pbeWithSHA1AndDES-CBC"},
+        { PBE_SHA1_DES3, PBE_SHA1_DES3, oidPBEType, "PBE-SHA1-3DES",
+                                            "pbeWithSHA1And3-KeyTripleDES-CBC"},
+    #endif
+
+        /* oidKeyWrapType */
+    #ifdef WOLFSSL_AES_128
+        { AES128_WRAP, AES128_WRAP, oidKeyWrapType, "AES-128 wrap", "aes128-wrap"},
+    #endif
+    #ifdef WOLFSSL_AES_192
+        { AES192_WRAP, AES192_WRAP, oidKeyWrapType, "AES-192 wrap", "aes192-wrap"},
+    #endif
+    #ifdef WOLFSSL_AES_256
+        { AES256_WRAP, AES256_WRAP, oidKeyWrapType, "AES-256 wrap", "aes256-wrap"},
+    #endif
+
+    #ifndef NO_PKCS7
+        #ifndef NO_DH
+        /* oidCmsKeyAgreeType */
+            #ifndef NO_SHA
+        { dhSinglePass_stdDH_sha1kdf_scheme, dhSinglePass_stdDH_sha1kdf_scheme,
+                oidCmsKeyAgreeType, "dhSinglePass-stdDH-sha1kdf-scheme", "dhSinglePass-stdDH-sha1kdf-scheme"},
+            #endif
+            #ifdef WOLFSSL_SHA224
+        { dhSinglePass_stdDH_sha224kdf_scheme,
+                dhSinglePass_stdDH_sha224kdf_scheme, oidCmsKeyAgreeType,
+                "dhSinglePass-stdDH-sha224kdf-scheme", "dhSinglePass-stdDH-sha224kdf-scheme"},
+            #endif
+            #ifndef NO_SHA256
+        { dhSinglePass_stdDH_sha256kdf_scheme,
+                        dhSinglePass_stdDH_sha256kdf_scheme, oidCmsKeyAgreeType,
+                        "dhSinglePass-stdDH-sha256kdf-scheme", "dhSinglePass-stdDH-sha256kdf-scheme"},
+            #endif
+            #ifdef WOLFSSL_SHA384
+        { dhSinglePass_stdDH_sha384kdf_scheme,
+                        dhSinglePass_stdDH_sha384kdf_scheme, oidCmsKeyAgreeType,
+                        "dhSinglePass-stdDH-sha384kdf-scheme", "dhSinglePass-stdDH-sha384kdf-scheme"},
+            #endif
+            #ifdef WOLFSSL_SHA512
+        { dhSinglePass_stdDH_sha512kdf_scheme,
+                        dhSinglePass_stdDH_sha512kdf_scheme, oidCmsKeyAgreeType,
+                        "dhSinglePass-stdDH-sha512kdf-scheme", "dhSinglePass-stdDH-sha512kdf-scheme"},
+            #endif
+        #endif
+    #endif
+    #if defined(WOLFSSL_APACHE_HTTPD)
+        /* "1.3.6.1.5.5.7.8.7" */
+        { NID_id_on_dnsSRV, NID_id_on_dnsSRV, oidCertNameType,
+            WOLFSSL_SN_DNS_SRV, WOLFSSL_LN_DNS_SRV },
+
+        /* "1.3.6.1.4.1.311.20.2.3" */
+        { NID_ms_upn, WOLFSSL_MS_UPN_SUM, oidCertExtType, WOLFSSL_SN_MS_UPN,
+            WOLFSSL_LN_MS_UPN },
+
+        /* "1.3.6.1.5.5.7.1.24" */
+        { NID_tlsfeature, WOLFSSL_TLS_FEATURE_SUM, oidTlsExtType,
+            WOLFSSL_SN_TLS_FEATURE, WOLFSSL_LN_TLS_FEATURE },
+    #endif
+#endif /* OPENSSL_EXTRA */
+};
+
+#define WOLFSSL_OBJECT_INFO_SZ \
+                (sizeof(wolfssl_object_info) / sizeof(*wolfssl_object_info))
+const size_t wolfssl_object_info_sz = WOLFSSL_OBJECT_INFO_SZ;
+#endif
+#if defined(OPENSSL_EXTRA) || \
+    (defined(OPENSSL_EXTRA_X509_SMALL) && !defined(NO_RSA))
+static WC_RNG globalRNG;
+static int initGlobalRNG = 0;
+#endif
+#if defined(OPENSSL_EXTRA) && \
+    !defined(NO_RSA) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
+WC_RNG* WOLFSSL_RSA_GetRNG(WOLFSSL_RSA *rsa, WC_RNG **tmpRNG, int *initTmpRng)
+{
+    WC_RNG* rng = NULL;
+
+    if (!rsa || !initTmpRng) {
+        return NULL;
+    }
+    *initTmpRng = 0;
+
+#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && \
+    !defined(HAVE_FAST_RSA) && defined(WC_RSA_BLINDING)
+    rng = ((RsaKey*)rsa->internal)->rng;
+#endif
+    if (rng == NULL && tmpRNG) {
+        if (!*tmpRNG) {
+#ifdef WOLFSSL_SMALL_STACK
+            *tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            if (*tmpRNG == NULL)
+                return NULL;
+#else
+            WOLFSSL_MSG("*tmpRNG is null");
+            return NULL;
+#endif
+        }
+
+        if (wc_InitRng(*tmpRNG) == 0) {
+            rng = *tmpRNG;
+            *initTmpRng = 1;
+        }
+        else {
+            WOLFSSL_MSG("Bad RNG Init, trying global");
+            if (initGlobalRNG == 0)
+                WOLFSSL_MSG("Global RNG no Init");
+            else
+                rng = &globalRNG;
+#ifdef WOLFSSL_SMALL_STACK
+            if (*tmpRNG)
+                XFREE(*tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            *tmpRNG = NULL;
+#endif
+        }
+    }
+    return rng;
+}
+#endif
+#ifndef WOLFCRYPT_ONLY
+
+#ifdef OPENSSL_EXTRA
+
+/* Not thread safe! Can be called multiple times.
+ * Checks if the global RNG has been created. If not then one is created.
+ *
+ * Returns SSL_SUCCESS when no error is encountered.
+ */
+static int wolfSSL_RAND_Init(void)
+{
+    if (initGlobalRNG == 0) {
+        if (wc_InitRng(&globalRNG) < 0) {
+            WOLFSSL_MSG("wolfSSL Init Global RNG failed");
+            return 0;
+        }
+        initGlobalRNG = 1;
+    }
+
+    return SSL_SUCCESS;
+}
+
+
+/* SSL_SUCCESS on ok */
+int wolfSSL_RAND_seed(const void* seed, int len)
+{
+
+    WOLFSSL_MSG("wolfSSL_RAND_seed");
+
+    (void)seed;
+    (void)len;
+
+    return wolfSSL_RAND_Init();
+}
+
+
+/* Returns the path for reading seed data from.
+ * Uses the env variable $RANDFILE first if set, if not then used $HOME/.rnd
+ *
+ * Note uses stdlib by default unless XGETENV macro is overwritten
+ *
+ * fname buffer to hold path
+ * len   length of fname buffer
+ *
+ * Returns a pointer to fname on success and NULL on failure
+ */
+const char* wolfSSL_RAND_file_name(char* fname, unsigned long len)
+{
+#ifndef NO_FILESYSTEM
+    char* rt;
+    char ap[] = "/.rnd";
+
+    WOLFSSL_ENTER("wolfSSL_RAND_file_name");
+
+    if (fname == NULL) {
+        return NULL;
+    }
+
+    XMEMSET(fname, 0, len);
+    /* if access to stdlib.h */
+    if ((rt = XGETENV("RANDFILE")) != NULL) {
+        if (len > XSTRLEN(rt)) {
+            XMEMCPY(fname, rt, XSTRLEN(rt));
+        }
+        else {
+            WOLFSSL_MSG("RANDFILE too large for buffer");
+            rt = NULL;
+        }
+    }
+
+    /* $RANDFILE was not set or is too large, check $HOME */
+    if (rt == NULL) {
+        WOLFSSL_MSG("Environment variable RANDFILE not set");
+        if ((rt = XGETENV("HOME")) == NULL) {
+            WOLFSSL_MSG("Environment variable HOME not set");
+            return NULL;
+        }
+
+        if (len > XSTRLEN(rt) +  XSTRLEN(ap)) {
+            fname[0] = '\0';
+            XSTRNCAT(fname, rt, len);
+            XSTRNCAT(fname, ap, len - XSTRLEN(rt));
+            return fname;
+        }
+        else {
+            WOLFSSL_MSG("HOME too large for buffer");
+            return NULL;
+        }
+    }
+
+    return fname;
+#else
+    /* no filesystem defined */
+    WOLFSSL_ENTER("wolfSSL_RAND_file_name");
+    WOLFSSL_MSG("No filesystem feature enabled, not compiled in");
+    (void)fname;
+    (void)len;
+    return NULL;
+#endif
+}
+
+
+/* Writes 1024 bytes from the RNG to the given file name.
+ *
+ * fname name of file to write to
+ *
+ * Returns the number of bytes written
+ */
+int wolfSSL_RAND_write_file(const char* fname)
+{
+    int bytes = 0;
+
+    WOLFSSL_ENTER("RAND_write_file");
+
+    if (fname == NULL) {
+        return SSL_FAILURE;
+    }
+
+#ifndef NO_FILESYSTEM
+    {
+    #ifndef WOLFSSL_SMALL_STACK
+        unsigned char buf[1024];
+    #else
+        unsigned char* buf = (unsigned char *)XMALLOC(1024, NULL,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+        if (buf == NULL) {
+            WOLFSSL_MSG("malloc failed");
+            return SSL_FAILURE;
+        }
+    #endif
+        bytes = 1024; /* default size of buf */
+
+        if (initGlobalRNG == 0 && wolfSSL_RAND_Init() != SSL_SUCCESS) {
+            WOLFSSL_MSG("No RNG to use");
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        #endif
+            return 0;
+        }
+
+        if (wc_RNG_GenerateBlock(&globalRNG, buf, bytes) != 0) {
+            WOLFSSL_MSG("Error generating random buffer");
+            bytes = 0;
+        }
+        else {
+            XFILE f;
+
+            f = XFOPEN(fname, "wb");
+            if (f == XBADFILE) {
+                WOLFSSL_MSG("Error opening the file");
+                bytes = 0;
+            }
+            else {
+                XFWRITE(buf, 1, bytes, f);
+                XFCLOSE(f);
+            }
+        }
+        ForceZero(buf, bytes);
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+    }
+#endif
+
+    return bytes;
+}
+
+#ifndef FREERTOS_TCP
+
+/* These constant values are protocol values made by egd */
+#if defined(USE_WOLFSSL_IO) && !defined(USE_WINDOWS_API)
+    #define WOLFSSL_EGD_NBLOCK 0x01
+    #include <sys/un.h>
+#endif
+
+/* This collects entropy from the path nm and seeds the global PRNG with it.
+ * Makes a call to wolfSSL_RAND_Init which is not thread safe.
+ *
+ * nm is the file path to the egd server
+ *
+ * Returns the number of bytes read.
+ */
+int wolfSSL_RAND_egd(const char* nm)
+{
+#if defined(USE_WOLFSSL_IO) && !defined(USE_WINDOWS_API) && !defined(HAVE_FIPS) && \
+    defined(HAVE_HASHDRBG)
+    struct sockaddr_un rem;
+    int fd;
+    int ret = WOLFSSL_SUCCESS;
+    word32 bytes = 0;
+    word32 idx   = 0;
+#ifndef WOLFSSL_SMALL_STACK
+    unsigned char buf[256];
+#else
+    unsigned char* buf;
+    buf = (unsigned char*)XMALLOC(256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (buf == NULL) {
+        WOLFSSL_MSG("Not enough memory");
+        return WOLFSSL_FATAL_ERROR;
+    }
+#endif
+
+    if (nm == NULL) {
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    fd = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (fd < 0) {
+        WOLFSSL_MSG("Error creating socket");
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+        return WOLFSSL_FATAL_ERROR;
+    }
+    if (ret == WOLFSSL_SUCCESS) {
+        rem.sun_family = AF_UNIX;
+        XSTRNCPY(rem.sun_path, nm, sizeof(rem.sun_path) - 1);
+        rem.sun_path[sizeof(rem.sun_path)-1] = '\0';
+    }
+
+    /* connect to egd server */
+    if (ret == WOLFSSL_SUCCESS) {
+        if (connect(fd, (struct sockaddr*)&rem, sizeof(struct sockaddr_un))
+                == -1) {
+            WOLFSSL_MSG("error connecting to egd server");
+            ret = WOLFSSL_FATAL_ERROR;
+        }
+    }
+
+    while (ret == WOLFSSL_SUCCESS && bytes < 255 && idx + 2 < 256) {
+        if (ret == WOLFSSL_SUCCESS) {
+            buf[idx]     = WOLFSSL_EGD_NBLOCK;
+            buf[idx + 1] = 255 - bytes; /* request 255 bytes from server */
+            ret = (int)write(fd, buf + idx, 2);
+            if (ret <= 0 || ret != 2) {
+                if (errno == EAGAIN) {
+                    ret = WOLFSSL_SUCCESS;
+                    continue;
+                }
+                WOLFSSL_MSG("error requesting entropy from egd server");
+                ret = WOLFSSL_FATAL_ERROR;
+                break;
+            }
+        }
+
+        /* attempting to read */
+        buf[idx] = 0;
+        ret = (int)read(fd, buf + idx, 256 - bytes);
+        if (ret == 0) {
+            WOLFSSL_MSG("error reading entropy from egd server");
+            ret = WOLFSSL_FATAL_ERROR;
+            break;
+        }
+        if (ret > 0 && buf[idx] > 0) {
+            bytes += buf[idx]; /* egd stores amount sent in first byte */
+            if (bytes + idx > 255 || buf[idx] > ret) {
+                WOLFSSL_MSG("Buffer error");
+                ret = WOLFSSL_FATAL_ERROR;
+                break;
+            }
+            XMEMMOVE(buf + idx, buf + idx + 1, buf[idx]);
+            idx = bytes;
+            ret = WOLFSSL_SUCCESS;
+            if (bytes >= 255) {
+                break;
+            }
+        }
+        else {
+            if (errno == EAGAIN || errno == EINTR) {
+                WOLFSSL_MSG("EGD would read");
+                ret = WOLFSSL_SUCCESS; /* try again */
+            }
+            else if (buf[idx] == 0) {
+                /* if egd returned 0 then there is no more entropy to be had.
+                   Do not try more reads. */
+                ret = WOLFSSL_SUCCESS;
+                break;
+            }
+            else {
+                WOLFSSL_MSG("Error with read");
+                ret = WOLFSSL_FATAL_ERROR;
+            }
+        }
+    }
+
+    if (bytes > 0 && ret == WOLFSSL_SUCCESS) {
+        wolfSSL_RAND_Init(); /* call to check global RNG is created */
+        if (wc_RNG_DRBG_Reseed(&globalRNG, (const byte*) buf, bytes)
+                != 0) {
+            WOLFSSL_MSG("Error with reseeding DRBG structure");
+            ret = WOLFSSL_FATAL_ERROR;
+        }
+        #ifdef SHOW_SECRETS
+        { /* print out entropy found */
+            word32 i;
+            printf("EGD Entropy = ");
+            for (i = 0; i < bytes; i++) {
+                printf("%02X", buf[i]);
+            }
+            printf("\n");
+        }
+        #endif
+    }
+
+    ForceZero(buf, bytes);
+    #ifdef WOLFSSL_SMALL_STACK
+    XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+    close(fd);
+
+    if (ret == WOLFSSL_SUCCESS) {
+        return bytes;
+    }
+    else {
+        return ret;
+    }
+#else
+    WOLFSSL_MSG("Type of socket needed is not available");
+    WOLFSSL_MSG("\tor using mode where DRBG API is not available");
+    (void)nm;
+
+    return WOLFSSL_FATAL_ERROR;
+#endif /* USE_WOLFSSL_IO && !USE_WINDOWS_API && !HAVE_FIPS && HAVE_HASHDRBG */
+}
+
+#endif /* !FREERTOS_TCP */
+
+void wolfSSL_RAND_Cleanup(void)
+{
+    WOLFSSL_ENTER("wolfSSL_RAND_Cleanup()");
+
+    if (initGlobalRNG != 0) {
+        wc_FreeRng(&globalRNG);
+        initGlobalRNG = 0;
+    }
+}
+
+
+int wolfSSL_RAND_pseudo_bytes(unsigned char* buf, int num)
+{
+    return wolfSSL_RAND_bytes(buf, num);
+}
+
+
+/* SSL_SUCCESS on ok */
+int wolfSSL_RAND_bytes(unsigned char* buf, int num)
+{
+    int     ret = 0;
+    int     initTmpRng = 0;
+    WC_RNG* rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG* tmpRNG;
+#else
+    WC_RNG  tmpRNG[1];
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_RAND_bytes");
+
+#ifdef WOLFSSL_SMALL_STACK
+    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+    if (tmpRNG == NULL)
+        return ret;
+#endif
+
+    if (initGlobalRNG)
+        rng = &globalRNG;
+    else if(wc_InitRng(tmpRNG) == 0) {
+        rng = tmpRNG;
+        initTmpRng = 1;
+    }
+    if (rng) {
+        if (wc_RNG_GenerateBlock(rng, buf, num) != 0)
+            WOLFSSL_MSG("Bad wc_RNG_GenerateBlock");
+        else
+            ret = WOLFSSL_SUCCESS;
+    }
+
+    if (initTmpRng)
+        wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+    return ret;
+}
+
+
+int wolfSSL_RAND_poll(void)
+{
+    byte  entropy[16];
+    int  ret = 0;
+    word32 entropy_sz = 16;
+
+    WOLFSSL_ENTER("wolfSSL_RAND_poll");
+    if (initGlobalRNG == 0){
+        WOLFSSL_MSG("Global RNG no Init");
+        return  WOLFSSL_FAILURE;
+    }
+    ret = wc_GenerateSeed(&globalRNG.seed, entropy, entropy_sz);
+    if (ret != 0){
+        WOLFSSL_MSG("Bad wc_RNG_GenerateBlock");
+        ret = WOLFSSL_FAILURE;
+    }else
+        ret = WOLFSSL_SUCCESS;
+
+    return ret;
+}
+#endif /* OPENSSL_EXTRA */
+
+
+
+#ifdef OPENSSL_EXTRA
+
+WOLFSSL_ASN1_INTEGER* wolfSSL_BN_to_ASN1_INTEGER(const WOLFSSL_BIGNUM *bn, WOLFSSL_ASN1_INTEGER *ai)
+{
+    WOLFSSL_ASN1_INTEGER* a;
+    int len;
+    WOLFSSL_ENTER("wolfSSL_BN_to_ASN1_INTEGER");
+
+    if (ai == NULL) {
+        a = wolfSSL_ASN1_INTEGER_new();
+
+        if (a == NULL)
+            return NULL;
+
+        a->type = V_ASN1_INTEGER;
+    }
+    else {
+        a = ai;
+    }
+    if (a) {
+        if (wolfSSL_BN_is_negative(bn) && !wolfSSL_BN_is_zero(bn)) {
+            a->type |= V_ASN1_NEG_INTEGER;
+            a->negative = 1;
+        }
+
+        len = wolfSSL_BN_num_bytes(bn);
+        if (len == 0)
+            len = 1;
+
+        /* allocate buffer */
+        if (len > (int)sizeof(a->intData)) {
+            /* create new data buffer and copy over */
+            a->data = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL);
+            if (a->data == NULL) {
+                if (a != ai)
+                    wolfSSL_ASN1_INTEGER_free(a);
+                return NULL;
+            }
+            a->isDynamic = 1;
+        }
+        else {
+            XMEMSET(a->intData, 0, sizeof(a->intData));
+            a->data = a->intData;
+        }
+        a->length = len;
+
+        /* populate data */
+        if (wolfSSL_BN_is_zero(bn)) {
+            a->data[0] = 0;
+        }
+        else {
+            len = wolfSSL_BN_bn2bin(bn, a->data);
+        }
+        a->length = len;
+    }
+
+    return a;
+}
+
+#ifdef OPENSSL_ALL
+void *wolfSSL_ASN1_item_new(const WOLFSSL_ASN1_ITEM *template)
+{
+    void *ret = NULL;
+    const WOLFSSL_ASN1_TEMPLATE *member = NULL;
+    size_t i;
+    WOLFSSL_ENTER("wolfSSL_ASN1_item_new");
+    if (!template) {
+        return NULL;
+    }
+    if (!(ret = XMALLOC(template->size, NULL, DYNAMIC_TYPE_OPENSSL))) {
+        return NULL;
+    }
+    XMEMSET(ret, 0, template->size);
+    for (member = template->members, i = 0; i < template->mcount;
+            member++, i++) {
+        switch (member->type) {
+            case WOLFSSL_X509_ALGOR_ASN1:
+            {
+                WOLFSSL_X509_ALGOR* algor = wolfSSL_X509_ALGOR_new();
+                if (!algor) {
+                    goto error;
+                }
+                *(WOLFSSL_X509_ALGOR**)(((byte*)ret) + member->offset) = algor;
+                break;
+            }
+            case WOLFSSL_ASN1_BIT_STRING_ASN1:
+            {
+                WOLFSSL_ASN1_BIT_STRING* bit_str = wolfSSL_ASN1_BIT_STRING_new();
+                if (!bit_str) {
+                    goto error;
+                }
+                *(WOLFSSL_ASN1_BIT_STRING**)(((byte*)ret) + member->offset) = bit_str;
+                break;
+            }
+            default:
+                WOLFSSL_MSG("Type not supported in wolfSSL_ASN1_item_new");
+                goto error;
+        }
+    }
+    return ret;
+error:
+    wolfSSL_ASN1_item_free(ret, template);
+    return NULL;
+}
+
+void wolfSSL_ASN1_item_free(void *val, const WOLFSSL_ASN1_ITEM *template)
+{
+    const WOLFSSL_ASN1_TEMPLATE *member = NULL;
+    size_t i;
+    WOLFSSL_ENTER("wolfSSL_ASN1_item_free");
+    if (val) {
+        for (member = template->members, i = 0; i < template->mcount;
+                member++, i++) {
+            switch (member->type) {
+                case WOLFSSL_X509_ALGOR_ASN1:
+                {
+                    WOLFSSL_X509_ALGOR* algor = *(WOLFSSL_X509_ALGOR**)
+                                                 (((byte*)val) + member->offset);
+                    if (algor) {
+                        wolfSSL_X509_ALGOR_free(algor);
+                    }
+                    break;
+                }
+                case WOLFSSL_ASN1_BIT_STRING_ASN1:
+                {
+                    WOLFSSL_ASN1_BIT_STRING* bit_str = *(WOLFSSL_ASN1_BIT_STRING**)
+                                                        (((byte*)val) + member->offset);
+                    if (bit_str) {
+                        wolfSSL_ASN1_BIT_STRING_free(bit_str);
+                    }
+                    break;
+                }
+                default:
+                    WOLFSSL_MSG("Type not supported in wolfSSL_ASN1_item_free");
+            }
+        }
+        XFREE(val, NULL, DYNAMIC_TYPE_OPENSSL);
+    }
+}
+
+#define bufLenOrNull(buf, len) (buf ? buf + len : NULL)
+
+static int i2dProcessMembers(const void *src, byte *buf,
+                          const WOLFSSL_ASN1_TEMPLATE *members, size_t mcount)
+{
+    const WOLFSSL_ASN1_TEMPLATE *member = NULL;
+    int len = 0, ret;
+    size_t i;
+    WOLFSSL_ENTER("processMembers");
+    for (member = members, i = 0; i < mcount; member++, i++) {
+        switch (member->type) {
+            case WOLFSSL_X509_ALGOR_ASN1:
+            {
+                word32 oid = 0;
+                word32 idx = 0;
+                const WOLFSSL_X509_ALGOR* algor = *(const WOLFSSL_X509_ALGOR**)
+                                                   (((byte*)src) + member->offset);
+                if (!algor->algorithm) {
+                    WOLFSSL_LEAVE("processMembers", WOLFSSL_FAILURE);
+                    return WOLFSSL_FAILURE;
+                }
+
+                if (GetObjectId(algor->algorithm->obj, &idx, &oid,
+                        algor->algorithm->grp, algor->algorithm->objSz) < 0) {
+                    WOLFSSL_MSG("Issue getting OID of object");
+                    return -1;
+                }
+
+                ret = SetAlgoID(oid, bufLenOrNull(buf, len),
+                                algor->algorithm->grp, 0);
+                if (!ret) {
+                    return WOLFSSL_FAILURE;
+                }
+                len += ret;
+                break;
+            }
+            case WOLFSSL_ASN1_BIT_STRING_ASN1:
+            {
+                const WOLFSSL_ASN1_BIT_STRING* bit_str;
+                bit_str = *(const WOLFSSL_ASN1_BIT_STRING**)
+                           (((byte*)src) + member->offset);
+                len += SetBitString(bit_str->length, 0, bufLenOrNull(buf, len));
+                if (buf && bit_str->data) {
+                    XMEMCPY(buf + len, bit_str->data, bit_str->length);
+                }
+                len += bit_str->length;
+                break;
+            }
+            default:
+                WOLFSSL_MSG("Type not support in processMembers");
+                WOLFSSL_LEAVE("processMembers", WOLFSSL_FAILURE);
+                return WOLFSSL_FAILURE;
+        }
+    }
+    WOLFSSL_LEAVE("processMembers", len);
+    return len;
+}
+
+int wolfSSL_ASN1_item_i2d(const void *src, byte **dest,
+                          const WOLFSSL_ASN1_ITEM *template)
+{
+    int len = 0;
+    byte *buf = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_ASN1_item_i2d");
+
+    if (!src || !template) {
+        WOLFSSL_LEAVE("wolfSSL_ASN1_item_i2d", WOLFSSL_FAILURE);
+        return WOLFSSL_FAILURE;
+    }
+
+    if (dest && !*dest) {
+        len = wolfSSL_ASN1_item_i2d(src, NULL, template);
+        if (!len) {
+            goto error;
+        }
+        buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_ASN1);
+        if (!buf) {
+            goto error;
+        }
+        len = 0;
+    }
+
+    switch (template->type) {
+        case ASN_SEQUENCE:
+        {
+            int seq_len = i2dProcessMembers(src, NULL, template->members,
+                                         template->mcount);
+            if (!seq_len) {
+                goto error;
+            }
+            len += SetSequence(seq_len, bufLenOrNull(buf, len));
+            if (buf &&
+                    i2dProcessMembers(src, bufLenOrNull(buf, len), template->members,
+                                   template->mcount) != seq_len) {
+                WOLFSSL_MSG("Inconsistent sequence length");
+                goto error;
+            }
+            len += seq_len;
+            break;
+        }
+        default:
+            WOLFSSL_MSG("Type not supported in wolfSSL_ASN1_item_i2d");
+            goto error;
+    }
+
+    if (dest && !*dest) {
+        *dest = buf;
+    }
+    else if (dest && *dest && buf) {
+        /* *dest length is not checked because the user is responsible
+         * for providing a long enough buffer */
+        XMEMCPY(*dest, buf, len);
+    }
+
+    WOLFSSL_LEAVE("wolfSSL_ASN1_item_i2d", len);
+    return len;
+error:
+    if (buf) {
+        XFREE(buf, NULL, DYNAMIC_TYPE_ASN1);
+    }
+    WOLFSSL_LEAVE("wolfSSL_ASN1_item_i2d", WOLFSSL_FAILURE);
+    return WOLFSSL_FAILURE;
+}
+#endif /* OPENSSL_ALL */
+
+#ifndef NO_DH
+
+static void InitwolfSSL_DH(WOLFSSL_DH* dh)
+{
+    if (dh) {
+        XMEMSET(dh, 0, sizeof(WOLFSSL_DH));
+    }
+}
+
+
+WOLFSSL_DH* wolfSSL_DH_new(void)
+{
+    WOLFSSL_DH* external;
+    DhKey*     key;
+
+    WOLFSSL_MSG("wolfSSL_DH_new");
+
+    key = (DhKey*) XMALLOC(sizeof(DhKey), NULL, DYNAMIC_TYPE_DH);
+    if (key == NULL) {
+        WOLFSSL_MSG("wolfSSL_DH_new malloc DhKey failure");
+        return NULL;
+    }
+
+    external = (WOLFSSL_DH*) XMALLOC(sizeof(WOLFSSL_DH), NULL,
+                                    DYNAMIC_TYPE_DH);
+    if (external == NULL) {
+        WOLFSSL_MSG("wolfSSL_DH_new malloc WOLFSSL_DH failure");
+        XFREE(key, NULL, DYNAMIC_TYPE_DH);
+        return NULL;
+    }
+
+    InitwolfSSL_DH(external);
+    if (wc_InitDhKey(key) != 0) {
+        WOLFSSL_MSG("wolfSSL_DH_new InitDhKey failure");
+        XFREE(key, NULL, DYNAMIC_TYPE_DH);
+        XFREE(external, NULL, DYNAMIC_TYPE_DH);
+        return NULL;
+    }
+    external->internal = key;
+
+    return external;
+}
+
+
+void wolfSSL_DH_free(WOLFSSL_DH* dh)
+{
+    WOLFSSL_MSG("wolfSSL_DH_free");
+
+    if (dh) {
+        if (dh->internal) {
+            wc_FreeDhKey((DhKey*)dh->internal);
+            XFREE(dh->internal, NULL, DYNAMIC_TYPE_DH);
+            dh->internal = NULL;
+        }
+        wolfSSL_BN_free(dh->priv_key);
+        wolfSSL_BN_free(dh->pub_key);
+        wolfSSL_BN_free(dh->g);
+        wolfSSL_BN_free(dh->p);
+        wolfSSL_BN_free(dh->q);
+        InitwolfSSL_DH(dh);  /* set back to NULLs for safety */
+
+        XFREE(dh, NULL, DYNAMIC_TYPE_DH);
+    }
+}
+
+int SetDhInternal(WOLFSSL_DH* dh)
+{
+    int            ret = WOLFSSL_FATAL_ERROR;
+    int            pSz = 1024;
+    int            gSz = 1024;
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+    int            privSz = 256; /* Up to 2048-bit */
+    int            pubSz  = 256;
+#endif
+#ifdef WOLFSSL_SMALL_STACK
+    unsigned char* p   = NULL;
+    unsigned char* g   = NULL;
+    #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+        unsigned char* priv_key = NULL;
+        unsigned char* pub_key = NULL;
+    #endif
+#else
+    unsigned char  p[1024];
+    unsigned char  g[1024];
+    #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+        unsigned char priv_key[256];
+        unsigned char pub_key[256];
+    #endif
+#endif
+
+    WOLFSSL_ENTER("SetDhInternal");
+
+    if (dh == NULL || dh->p == NULL || dh->g == NULL)
+        WOLFSSL_MSG("Bad function arguments");
+    else if (wolfSSL_BN_bn2bin(dh->p, NULL) > pSz)
+        WOLFSSL_MSG("Bad p internal size");
+    else if (wolfSSL_BN_bn2bin(dh->g, NULL) > gSz)
+        WOLFSSL_MSG("Bad g internal size");
+    #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+    else if (wolfSSL_BN_bn2bin(dh->priv_key, NULL) > privSz)
+        WOLFSSL_MSG("Bad private key internal size");
+    else if (wolfSSL_BN_bn2bin(dh->pub_key, NULL) > privSz)
+        WOLFSSL_MSG("Bad public key internal size");
+    #endif
+    else {
+    #ifdef WOLFSSL_SMALL_STACK
+        p = (unsigned char*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+        g = (unsigned char*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+
+    #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+        priv_key = (unsigned char*)XMALLOC(privSz,NULL,DYNAMIC_TYPE_PRIVATE_KEY);
+        pub_key  = (unsigned char*)XMALLOC(pubSz,NULL,DYNAMIC_TYPE_PUBLIC_KEY);
+    #endif
+
+        if (p == NULL || g == NULL) {
+            XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+            XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+            return ret;
+        }
+    #endif /* WOLFSSL_SMALL_STACK */
+
+    #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+        privSz = wolfSSL_BN_bn2bin(dh->priv_key, priv_key);
+        pubSz  = wolfSSL_BN_bn2bin(dh->pub_key,  pub_key);
+        if (privSz <= 0) {
+            WOLFSSL_MSG("No private key size.");
+        }
+        if (pubSz <= 0) {
+            WOLFSSL_MSG("No public key size.");
+        }
+        if (privSz > 0 || pubSz > 0) {
+            ret = wc_DhSetFullKeys((DhKey*)dh->internal,priv_key,privSz,
+                                    pub_key,pubSz);
+            if (ret == WOLFSSL_FAILURE) {
+                WOLFSSL_MSG("Failed setting private or public key.");
+            }
+        }
+    #endif /* WOLFSSL_QT || OPENSSL_ALL */
+
+        pSz = wolfSSL_BN_bn2bin(dh->p, p);
+        gSz = wolfSSL_BN_bn2bin(dh->g, g);
+
+        if (pSz <= 0 || gSz <= 0)
+            WOLFSSL_MSG("Bad BN2bin set");
+        else if (wc_DhSetKey((DhKey*)dh->internal, p, pSz, g, gSz) < 0)
+            WOLFSSL_MSG("Bad DH SetKey");
+        else {
+            dh->inSet = 1;
+            ret = WOLFSSL_SUCCESS;
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+        XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+        #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+            XFREE(priv_key, NULL, DYNAMIC_TYPE_PRIVATE_KEY);
+            XFREE(pub_key,  NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+        #endif
+    #endif
+    }
+
+
+    return ret;
+}
+
+#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH))
+/* Set the members of DhKey into WOLFSSL_DH
+ * DhKey was populated from wc_DhKeyDecode
+ */
+int SetDhExternal(WOLFSSL_DH *dh)
+{
+    DhKey *key;
+    WOLFSSL_MSG("Entering SetDhExternal");
+
+    if (dh == NULL || dh->internal == NULL) {
+        WOLFSSL_MSG("dh key NULL error");
+    }
+
+    key = (DhKey*)dh->internal;
+
+    if (SetIndividualExternal(&dh->p, &key->p) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("dh param p error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (SetIndividualExternal(&dh->g, &key->g) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("dh param g error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (SetIndividualExternal(&dh->priv_key, &key->priv) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("No DH Private Key");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (SetIndividualExternal(&dh->pub_key, &key->pub) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("No DH Public Key");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    dh->exSet = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */
+
+/* return code compliant with OpenSSL :
+ *   DH prime size in bytes if success, 0 if error
+ */
+int wolfSSL_DH_size(WOLFSSL_DH* dh)
+{
+    WOLFSSL_MSG("wolfSSL_DH_size");
+
+    if (dh == NULL)
+        return WOLFSSL_FATAL_ERROR;
+
+    return wolfSSL_BN_num_bytes(dh->p);
+}
+
+/* This sets a big number with the 768-bit prime from RFC 2409.
+ *
+ * bn  if not NULL then the big number structure is used. If NULL then a new
+ *     big number structure is created.
+ *
+ * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure.
+ */
+WOLFSSL_BIGNUM* wolfSSL_DH_768_prime(WOLFSSL_BIGNUM* bn)
+{
+    const char prm[] = {
+        "FFFFFFFFFFFFFFFFC90FDAA22168C234"
+        "C4C6628B80DC1CD129024E088A67CC74"
+        "020BBEA63B139B22514A08798E3404DD"
+        "EF9519B3CD3A431B302B0A6DF25F1437"
+        "4FE1356D6D51C245E485B576625E7EC6"
+        "F44C42E9A63A3620FFFFFFFFFFFFFFFF"
+    };
+
+    WOLFSSL_ENTER("wolfSSL_DH_768_prime");
+
+    if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) {
+        WOLFSSL_MSG("Error converting DH 768 prime to big number");
+        return NULL;
+    }
+
+    return bn;
+}
+
+/* This sets a big number with the 1024-bit prime from RFC 2409.
+ *
+ * bn  if not NULL then the big number structure is used. If NULL then a new
+ *     big number structure is created.
+ *
+ * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure.
+ */
+WOLFSSL_BIGNUM* wolfSSL_DH_1024_prime(WOLFSSL_BIGNUM* bn)
+{
+    const char prm[] = {
+        "FFFFFFFFFFFFFFFFC90FDAA22168C234"
+        "C4C6628B80DC1CD129024E088A67CC74"
+        "020BBEA63B139B22514A08798E3404DD"
+        "EF9519B3CD3A431B302B0A6DF25F1437"
+        "4FE1356D6D51C245E485B576625E7EC6"
+        "F44C42E9A637ED6B0BFF5CB6F406B7ED"
+        "EE386BFB5A899FA5AE9F24117C4B1FE6"
+        "49286651ECE65381FFFFFFFFFFFFFFFF"
+    };
+
+    WOLFSSL_ENTER("wolfSSL_DH_1024_prime");
+
+    if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) {
+        WOLFSSL_MSG("Error converting DH 1024 prime to big number");
+        return NULL;
+    }
+
+    return bn;
+}
+
+/* This sets a big number with the 1536-bit prime from RFC 3526.
+ *
+ * bn  if not NULL then the big number structure is used. If NULL then a new
+ *     big number structure is created.
+ *
+ * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure.
+ */
+WOLFSSL_BIGNUM* wolfSSL_DH_1536_prime(WOLFSSL_BIGNUM* bn)
+{
+    const char prm[] = {
+        "FFFFFFFFFFFFFFFFC90FDAA22168C234"
+        "C4C6628B80DC1CD129024E088A67CC74"
+        "020BBEA63B139B22514A08798E3404DD"
+        "EF9519B3CD3A431B302B0A6DF25F1437"
+        "4FE1356D6D51C245E485B576625E7EC6"
+        "F44C42E9A637ED6B0BFF5CB6F406B7ED"
+        "EE386BFB5A899FA5AE9F24117C4B1FE6"
+        "49286651ECE45B3DC2007CB8A163BF05"
+        "98DA48361C55D39A69163FA8FD24CF5F"
+        "83655D23DCA3AD961C62F356208552BB"
+        "9ED529077096966D670C354E4ABC9804"
+        "F1746C08CA237327FFFFFFFFFFFFFFFF"
+    };
+
+    WOLFSSL_ENTER("wolfSSL_DH_1536_prime");
+
+    if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) {
+        WOLFSSL_MSG("Error converting DH 1536 prime to big number");
+        return NULL;
+    }
+
+    return bn;
+}
+
+/* This sets a big number with the 2048-bit prime from RFC 3526.
+ *
+ * bn  if not NULL then the big number structure is used. If NULL then a new
+ *     big number structure is created.
+ *
+ * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure.
+ */
+WOLFSSL_BIGNUM* wolfSSL_DH_2048_prime(WOLFSSL_BIGNUM* bn)
+{
+    const char prm[] = {
+        "FFFFFFFFFFFFFFFFC90FDAA22168C234"
+        "C4C6628B80DC1CD129024E088A67CC74"
+        "020BBEA63B139B22514A08798E3404DD"
+        "EF9519B3CD3A431B302B0A6DF25F1437"
+        "4FE1356D6D51C245E485B576625E7EC6"
+        "F44C42E9A637ED6B0BFF5CB6F406B7ED"
+        "EE386BFB5A899FA5AE9F24117C4B1FE6"
+        "49286651ECE45B3DC2007CB8A163BF05"
+        "98DA48361C55D39A69163FA8FD24CF5F"
+        "83655D23DCA3AD961C62F356208552BB"
+        "9ED529077096966D670C354E4ABC9804"
+        "F1746C08CA18217C32905E462E36CE3B"
+        "E39E772C180E86039B2783A2EC07A28F"
+        "B5C55DF06F4C52C9DE2BCBF695581718"
+        "3995497CEA956AE515D2261898FA0510"
+        "15728E5A8AACAA68FFFFFFFFFFFFFFFF"
+    };
+
+    WOLFSSL_ENTER("wolfSSL_DH_2048_prime");
+
+    if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) {
+        WOLFSSL_MSG("Error converting DH 2048 prime to big number");
+        return NULL;
+    }
+
+    return bn;
+}
+
+/* This sets a big number with the 3072-bit prime from RFC 3526.
+ *
+ * bn  if not NULL then the big number structure is used. If NULL then a new
+ *     big number structure is created.
+ *
+ * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure.
+ */
+WOLFSSL_BIGNUM* wolfSSL_DH_3072_prime(WOLFSSL_BIGNUM* bn)
+{
+    const char prm[] = {
+        "FFFFFFFFFFFFFFFFC90FDAA22168C234"
+        "C4C6628B80DC1CD129024E088A67CC74"
+        "020BBEA63B139B22514A08798E3404DD"
+        "EF9519B3CD3A431B302B0A6DF25F1437"
+        "4FE1356D6D51C245E485B576625E7EC6"
+        "F44C42E9A637ED6B0BFF5CB6F406B7ED"
+        "EE386BFB5A899FA5AE9F24117C4B1FE6"
+        "49286651ECE45B3DC2007CB8A163BF05"
+        "98DA48361C55D39A69163FA8FD24CF5F"
+        "83655D23DCA3AD961C62F356208552BB"
+        "9ED529077096966D670C354E4ABC9804"
+        "F1746C08CA18217C32905E462E36CE3B"
+        "E39E772C180E86039B2783A2EC07A28F"
+        "B5C55DF06F4C52C9DE2BCBF695581718"
+        "3995497CEA956AE515D2261898FA0510"
+        "15728E5A8AAAC42DAD33170D04507A33"
+        "A85521ABDF1CBA64ECFB850458DBEF0A"
+        "8AEA71575D060C7DB3970F85A6E1E4C7"
+        "ABF5AE8CDB0933D71E8C94E04A25619D"
+        "CEE3D2261AD2EE6BF12FFA06D98A0864"
+        "D87602733EC86A64521F2B18177B200C"
+        "BBE117577A615D6C770988C0BAD946E2"
+        "08E24FA074E5AB3143DB5BFCE0FD108E"
+        "4B82D120A93AD2CAFFFFFFFFFFFFFFFF"
+    };
+
+    WOLFSSL_ENTER("wolfSSL_DH_3072_prime");
+
+    if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) {
+        WOLFSSL_MSG("Error converting DH 3072 prime to big number");
+        return NULL;
+    }
+
+    return bn;
+}
+
+/* This sets a big number with the 4096-bit prime from RFC 3526.
+ *
+ * bn  if not NULL then the big number structure is used. If NULL then a new
+ *     big number structure is created.
+ *
+ * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure.
+ */
+WOLFSSL_BIGNUM* wolfSSL_DH_4096_prime(WOLFSSL_BIGNUM* bn)
+{
+    const char prm[] = {
+        "FFFFFFFFFFFFFFFFC90FDAA22168C234"
+        "C4C6628B80DC1CD129024E088A67CC74"
+        "020BBEA63B139B22514A08798E3404DD"
+        "EF9519B3CD3A431B302B0A6DF25F1437"
+        "4FE1356D6D51C245E485B576625E7EC6"
+        "F44C42E9A637ED6B0BFF5CB6F406B7ED"
+        "EE386BFB5A899FA5AE9F24117C4B1FE6"
+        "49286651ECE45B3DC2007CB8A163BF05"
+        "98DA48361C55D39A69163FA8FD24CF5F"
+        "83655D23DCA3AD961C62F356208552BB"
+        "9ED529077096966D670C354E4ABC9804"
+        "F1746C08CA18217C32905E462E36CE3B"
+        "E39E772C180E86039B2783A2EC07A28F"
+        "B5C55DF06F4C52C9DE2BCBF695581718"
+        "3995497CEA956AE515D2261898FA0510"
+        "15728E5A8AAAC42DAD33170D04507A33"
+        "A85521ABDF1CBA64ECFB850458DBEF0A"
+        "8AEA71575D060C7DB3970F85A6E1E4C7"
+        "ABF5AE8CDB0933D71E8C94E04A25619D"
+        "CEE3D2261AD2EE6BF12FFA06D98A0864"
+        "D87602733EC86A64521F2B18177B200C"
+        "BBE117577A615D6C770988C0BAD946E2"
+        "08E24FA074E5AB3143DB5BFCE0FD108E"
+        "4B82D120A92108011A723C12A787E6D7"
+        "88719A10BDBA5B2699C327186AF4E23C"
+        "1A946834B6150BDA2583E9CA2AD44CE8"
+        "DBBBC2DB04DE8EF92E8EFC141FBECAA6"
+        "287C59474E6BC05D99B2964FA090C3A2"
+        "233BA186515BE7ED1F612970CEE2D7AF"
+        "B81BDD762170481CD0069127D5B05AA9"
+        "93B4EA988D8FDDC186FFB7DC90A6C08F"
+        "4DF435C934063199FFFFFFFFFFFFFFFF"
+    };
+
+    WOLFSSL_ENTER("wolfSSL_DH_4096_prime");
+
+    if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) {
+        WOLFSSL_MSG("Error converting DH 4096 prime to big number");
+        return NULL;
+    }
+
+    return bn;
+}
+
+/* This sets a big number with the 6144-bit prime from RFC 3526.
+ *
+ * bn  if not NULL then the big number structure is used. If NULL then a new
+ *     big number structure is created.
+ *
+ * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure.
+ */
+WOLFSSL_BIGNUM* wolfSSL_DH_6144_prime(WOLFSSL_BIGNUM* bn)
+{
+    const char prm[] = {
+        "FFFFFFFFFFFFFFFFC90FDAA22168C234"
+        "C4C6628B80DC1CD129024E088A67CC74"
+        "020BBEA63B139B22514A08798E3404DD"
+        "EF9519B3CD3A431B302B0A6DF25F1437"
+        "4FE1356D6D51C245E485B576625E7EC6"
+        "F44C42E9A637ED6B0BFF5CB6F406B7ED"
+        "EE386BFB5A899FA5AE9F24117C4B1FE6"
+        "49286651ECE45B3DC2007CB8A163BF05"
+        "98DA48361C55D39A69163FA8FD24CF5F"
+        "83655D23DCA3AD961C62F356208552BB"
+        "9ED529077096966D670C354E4ABC9804"
+        "F1746C08CA18217C32905E462E36CE3B"
+        "E39E772C180E86039B2783A2EC07A28F"
+        "B5C55DF06F4C52C9DE2BCBF695581718"
+        "3995497CEA956AE515D2261898FA0510"
+        "15728E5A8AAAC42DAD33170D04507A33"
+        "A85521ABDF1CBA64ECFB850458DBEF0A"
+        "8AEA71575D060C7DB3970F85A6E1E4C7"
+        "ABF5AE8CDB0933D71E8C94E04A25619D"
+        "CEE3D2261AD2EE6BF12FFA06D98A0864"
+        "D87602733EC86A64521F2B18177B200C"
+        "BBE117577A615D6C770988C0BAD946E2"
+        "08E24FA074E5AB3143DB5BFCE0FD108E"
+        "4B82D120A92108011A723C12A787E6D7"
+        "88719A10BDBA5B2699C327186AF4E23C"
+        "1A946834B6150BDA2583E9CA2AD44CE8"
+        "DBBBC2DB04DE8EF92E8EFC141FBECAA6"
+        "287C59474E6BC05D99B2964FA090C3A2"
+        "233BA186515BE7ED1F612970CEE2D7AF"
+        "B81BDD762170481CD0069127D5B05AA9"
+        "93B4EA988D8FDDC186FFB7DC90A6C08F"
+        "4DF435C93402849236C3FAB4D27C7026"
+        "C1D4DCB2602646DEC9751E763DBA37BD"
+        "F8FF9406AD9E530EE5DB382F413001AE"
+        "B06A53ED9027D831179727B0865A8918"
+        "DA3EDBEBCF9B14ED44CE6CBACED4BB1B"
+        "DB7F1447E6CC254B332051512BD7AF42"
+        "6FB8F401378CD2BF5983CA01C64B92EC"
+        "F032EA15D1721D03F482D7CE6E74FEF6"
+        "D55E702F46980C82B5A84031900B1C9E"
+        "59E7C97FBEC7E8F323A97A7E36CC88BE"
+        "0F1D45B7FF585AC54BD407B22B4154AA"
+        "CC8F6D7EBF48E1D814CC5ED20F8037E0"
+        "A79715EEF29BE32806A1D58BB7C5DA76"
+        "F550AA3D8A1FBFF0EB19CCB1A313D55C"
+        "DA56C9EC2EF29632387FE8D76E3C0468"
+        "043E8F663F4860EE12BF2D5B0B7474D6"
+        "E694F91E6DCC4024FFFFFFFFFFFFFFFF"
+    };
+
+    WOLFSSL_ENTER("wolfSSL_DH_6144_prime");
+
+    if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) {
+        WOLFSSL_MSG("Error converting DH 6144 prime to big number");
+        return NULL;
+    }
+
+    return bn;
+}
+
+
+/* This sets a big number with the 8192-bit prime from RFC 3526.
+ *
+ * bn  if not NULL then the big number structure is used. If NULL then a new
+ *     big number structure is created.
+ *
+ * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure.
+ */
+WOLFSSL_BIGNUM* wolfSSL_DH_8192_prime(WOLFSSL_BIGNUM* bn)
+{
+    const char prm[] = {
+        "FFFFFFFFFFFFFFFFC90FDAA22168C234"
+        "C4C6628B80DC1CD129024E088A67CC74"
+        "020BBEA63B139B22514A08798E3404DD"
+        "EF9519B3CD3A431B302B0A6DF25F1437"
+        "4FE1356D6D51C245E485B576625E7EC6"
+        "F44C42E9A637ED6B0BFF5CB6F406B7ED"
+        "EE386BFB5A899FA5AE9F24117C4B1FE6"
+        "49286651ECE45B3DC2007CB8A163BF05"
+        "98DA48361C55D39A69163FA8FD24CF5F"
+        "83655D23DCA3AD961C62F356208552BB"
+        "9ED529077096966D670C354E4ABC9804"
+        "F1746C08CA18217C32905E462E36CE3B"
+        "E39E772C180E86039B2783A2EC07A28F"
+        "B5C55DF06F4C52C9DE2BCBF695581718"
+        "3995497CEA956AE515D2261898FA0510"
+        "15728E5A8AAAC42DAD33170D04507A33"
+        "A85521ABDF1CBA64ECFB850458DBEF0A"
+        "8AEA71575D060C7DB3970F85A6E1E4C7"
+        "ABF5AE8CDB0933D71E8C94E04A25619D"
+        "CEE3D2261AD2EE6BF12FFA06D98A0864"
+        "D87602733EC86A64521F2B18177B200C"
+        "BBE117577A615D6C770988C0BAD946E2"
+        "08E24FA074E5AB3143DB5BFCE0FD108E"
+        "4B82D120A92108011A723C12A787E6D7"
+        "88719A10BDBA5B2699C327186AF4E23C"
+        "1A946834B6150BDA2583E9CA2AD44CE8"
+        "DBBBC2DB04DE8EF92E8EFC141FBECAA6"
+        "287C59474E6BC05D99B2964FA090C3A2"
+        "233BA186515BE7ED1F612970CEE2D7AF"
+        "B81BDD762170481CD0069127D5B05AA9"
+        "93B4EA988D8FDDC186FFB7DC90A6C08F"
+        "4DF435C93402849236C3FAB4D27C7026"
+        "C1D4DCB2602646DEC9751E763DBA37BD"
+        "F8FF9406AD9E530EE5DB382F413001AE"
+        "B06A53ED9027D831179727B0865A8918"
+        "DA3EDBEBCF9B14ED44CE6CBACED4BB1B"
+        "DB7F1447E6CC254B332051512BD7AF42"
+        "6FB8F401378CD2BF5983CA01C64B92EC"
+        "F032EA15D1721D03F482D7CE6E74FEF6"
+        "D55E702F46980C82B5A84031900B1C9E"
+        "59E7C97FBEC7E8F323A97A7E36CC88BE"
+        "0F1D45B7FF585AC54BD407B22B4154AA"
+        "CC8F6D7EBF48E1D814CC5ED20F8037E0"
+        "A79715EEF29BE32806A1D58BB7C5DA76"
+        "F550AA3D8A1FBFF0EB19CCB1A313D55C"
+        "DA56C9EC2EF29632387FE8D76E3C0468"
+        "043E8F663F4860EE12BF2D5B0B7474D6"
+        "E694F91E6DBE115974A3926F12FEE5E4"
+        "38777CB6A932DF8CD8BEC4D073B931BA"
+        "3BC832B68D9DD300741FA7BF8AFC47ED"
+        "2576F6936BA424663AAB639C5AE4F568"
+        "3423B4742BF1C978238F16CBE39D652D"
+        "E3FDB8BEFC848AD922222E04A4037C07"
+        "13EB57A81A23F0C73473FC646CEA306B"
+        "4BCBC8862F8385DDFA9D4B7FA2C087E8"
+        "79683303ED5BDD3A062B3CF5B3A278A6"
+        "6D2A13F83F44F82DDF310EE074AB6A36"
+        "4597E899A0255DC164F31CC50846851D"
+        "F9AB48195DED7EA1B1D510BD7EE74D73"
+        "FAF36BC31ECFA268359046F4EB879F92"
+        "4009438B481C6CD7889A002ED5EE382B"
+        "C9190DA6FC026E479558E4475677E9AA"
+        "9E3050E2765694DFC81F56E880B96E71"
+        "60C980DD98EDD3DFFFFFFFFFFFFFFFFF"
+    };
+
+    WOLFSSL_ENTER("wolfSSL_DH_8192_prime");
+
+    if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) {
+        WOLFSSL_MSG("Error converting DH 8192 prime to big number");
+        return NULL;
+    }
+
+    return bn;
+}
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_DH_generate_key(WOLFSSL_DH* dh)
+{
+    int            ret    = WOLFSSL_FAILURE;
+    word32         pubSz  = 0;
+    word32         privSz = 0;
+    int            initTmpRng = 0;
+    WC_RNG*        rng    = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG*        tmpRNG;
+#else
+    WC_RNG         tmpRNG[1];
+#endif
+    unsigned char* pub    = NULL;
+    unsigned char* priv   = NULL;
+
+    WOLFSSL_MSG("wolfSSL_DH_generate_key");
+
+#ifdef WOLFSSL_SMALL_STACK
+    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+    if (tmpRNG == NULL) {
+        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+        return ret;
+    }
+#endif
+
+    if (dh == NULL || dh->p == NULL || dh->g == NULL)
+        WOLFSSL_MSG("Bad function arguments");
+    else if (dh->inSet == 0 && SetDhInternal(dh) != WOLFSSL_SUCCESS)
+            WOLFSSL_MSG("Bad DH set internal");
+    else if (wc_InitRng(tmpRNG) == 0) {
+        rng = tmpRNG;
+        initTmpRng = 1;
+    }
+    else {
+        WOLFSSL_MSG("Bad RNG Init, trying global");
+        if (initGlobalRNG == 0)
+            WOLFSSL_MSG("Global RNG no Init");
+        else
+            rng = &globalRNG;
+    }
+
+    if (rng) {
+        pubSz = wolfSSL_BN_num_bytes(dh->p);
+        if (dh->length) {
+            privSz = dh->length/8; /* to bytes */
+        } else {
+            privSz = pubSz;
+        }
+        pub   = (unsigned char*)XMALLOC(pubSz,  NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+        priv  = (unsigned char*)XMALLOC(privSz, NULL, DYNAMIC_TYPE_PRIVATE_KEY);
+        if (pub == NULL || priv == NULL) {
+            WOLFSSL_MSG("Unable to malloc memory");
+        }
+        else if (wc_DhGenerateKeyPair((DhKey*)dh->internal, rng, priv, &privSz,
+                                                               pub, &pubSz) < 0)
+            WOLFSSL_MSG("Bad wc_DhGenerateKeyPair");
+        else {
+            if (dh->pub_key)
+                wolfSSL_BN_free(dh->pub_key);
+
+            dh->pub_key = wolfSSL_BN_new();
+            if (dh->pub_key == NULL) {
+                WOLFSSL_MSG("Bad DH new pub");
+            }
+            if (dh->priv_key)
+                wolfSSL_BN_free(dh->priv_key);
+
+            dh->priv_key = wolfSSL_BN_new();
+
+            if (dh->priv_key == NULL) {
+                WOLFSSL_MSG("Bad DH new priv");
+            }
+
+            if (dh->pub_key && dh->priv_key) {
+               if (wolfSSL_BN_bin2bn(pub, pubSz, dh->pub_key) == NULL)
+                   WOLFSSL_MSG("Bad DH bn2bin error pub");
+               else if (wolfSSL_BN_bin2bn(priv, privSz, dh->priv_key) == NULL)
+                   WOLFSSL_MSG("Bad DH bn2bin error priv");
+               else
+                   ret = WOLFSSL_SUCCESS;
+            }
+        }
+    }
+
+    if (initTmpRng)
+        wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+    XFREE(pub,    NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+    XFREE(priv,   NULL, DYNAMIC_TYPE_PRIVATE_KEY);
+
+    return ret;
+}
+
+
+/* return code compliant with OpenSSL :
+ *   size of shared secret if success, -1 if error
+ */
+int wolfSSL_DH_compute_key(unsigned char* key, WOLFSSL_BIGNUM* otherPub,
+                          WOLFSSL_DH* dh)
+{
+    int            ret    = WOLFSSL_FATAL_ERROR;
+    word32         keySz  = 0;
+    int            pubSz  = 1024;
+    int            privSz = 1024;
+#ifdef WOLFSSL_SMALL_STACK
+    unsigned char* pub;
+    unsigned char* priv   = NULL;
+#else
+    unsigned char  pub [1024];
+    unsigned char  priv[1024];
+#endif
+
+    WOLFSSL_MSG("wolfSSL_DH_compute_key");
+
+#ifdef WOLFSSL_SMALL_STACK
+    pub = (unsigned char*)XMALLOC(pubSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+    if (pub == NULL)
+        return ret;
+
+    priv = (unsigned char*)XMALLOC(privSz, NULL, DYNAMIC_TYPE_PRIVATE_KEY);
+    if (priv == NULL) {
+        XFREE(pub, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+        return ret;
+    }
+#endif
+
+    if (dh == NULL || dh->priv_key == NULL || otherPub == NULL)
+        WOLFSSL_MSG("Bad function arguments");
+    else if ((keySz = (word32)DH_size(dh)) == 0)
+        WOLFSSL_MSG("Bad DH_size");
+    else if (wolfSSL_BN_bn2bin(dh->priv_key, NULL) > (int)privSz)
+        WOLFSSL_MSG("Bad priv internal size");
+    else if (wolfSSL_BN_bn2bin(otherPub, NULL) > (int)pubSz)
+        WOLFSSL_MSG("Bad otherPub size");
+    else {
+        privSz = wolfSSL_BN_bn2bin(dh->priv_key, priv);
+        pubSz  = wolfSSL_BN_bn2bin(otherPub, pub);
+        if (dh->inSet == 0 && SetDhInternal(dh) != SSL_SUCCESS){
+                WOLFSSL_MSG("Bad DH set internal");
+        }
+        if (privSz <= 0 || pubSz <= 0)
+            WOLFSSL_MSG("Bad BN2bin set");
+        else if (wc_DhAgree((DhKey*)dh->internal, key, &keySz,
+                            priv, privSz, pub, pubSz) < 0)
+            WOLFSSL_MSG("wc_DhAgree failed");
+        else
+            ret = (int)keySz;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(pub,  NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+    XFREE(priv, NULL, DYNAMIC_TYPE_PRIVATE_KEY);
+#endif
+
+    return ret;
+}
+
+
+#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L
+/* ownership of p,q,and g get taken over by "dh" on success and should be free'd
+ * with a call to wolfSSL_DH_free -- not individually.
+ *
+ * returns WOLFSSL_SUCCESS on success
+ */
+int wolfSSL_DH_set0_pqg(WOLFSSL_DH *dh, WOLFSSL_BIGNUM *p,
+    WOLFSSL_BIGNUM *q, WOLFSSL_BIGNUM *g)
+{
+    int ret;
+    WOLFSSL_ENTER("wolfSSL_DH_set0_pqg");
+
+    /* q can be NULL */
+    if (dh == NULL || p == NULL || g == NULL) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* free existing internal DH structure and recreate with new p / g */
+    if (dh->inSet) {
+        ret = wc_FreeDhKey((DhKey*)dh->internal);
+        if (ret != 0) {
+            WOLFSSL_MSG("Unable to free internal DH key");
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+    wolfSSL_BN_free(dh->p);
+    wolfSSL_BN_free(dh->q);
+    wolfSSL_BN_free(dh->g);
+    wolfSSL_BN_free(dh->pub_key);
+    wolfSSL_BN_free(dh->priv_key);
+
+    dh->p = p;
+    dh->q = q;
+    dh->g = g;
+
+    ret = SetDhInternal(dh);
+    if (ret != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("Unable to set internal DH key");
+        dh->p = NULL;
+        dh->q = NULL;
+        dh->g = NULL;
+        dh->inSet = 0;
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* v1.1.0 or later */
+
+#endif /* NO_DH */
+
+
+#ifndef NO_DSA
+static void InitwolfSSL_DSA(WOLFSSL_DSA* dsa)
+{
+    if (dsa) {
+        dsa->p        = NULL;
+        dsa->q        = NULL;
+        dsa->g        = NULL;
+        dsa->pub_key  = NULL;
+        dsa->priv_key = NULL;
+        dsa->internal = NULL;
+        dsa->inSet    = 0;
+        dsa->exSet    = 0;
+    }
+}
+
+
+WOLFSSL_DSA* wolfSSL_DSA_new(void)
+{
+    WOLFSSL_DSA* external;
+    DsaKey*     key;
+
+    WOLFSSL_MSG("wolfSSL_DSA_new");
+
+    key = (DsaKey*) XMALLOC(sizeof(DsaKey), NULL, DYNAMIC_TYPE_DSA);
+    if (key == NULL) {
+        WOLFSSL_MSG("wolfSSL_DSA_new malloc DsaKey failure");
+        return NULL;
+    }
+
+    external = (WOLFSSL_DSA*) XMALLOC(sizeof(WOLFSSL_DSA), NULL,
+                                    DYNAMIC_TYPE_DSA);
+    if (external == NULL) {
+        WOLFSSL_MSG("wolfSSL_DSA_new malloc WOLFSSL_DSA failure");
+        XFREE(key, NULL, DYNAMIC_TYPE_DSA);
+        return NULL;
+    }
+
+    InitwolfSSL_DSA(external);
+    if (wc_InitDsaKey(key) != 0) {
+        WOLFSSL_MSG("wolfSSL_DSA_new InitDsaKey failure");
+        XFREE(key, NULL, DYNAMIC_TYPE_DSA);
+        wolfSSL_DSA_free(external);
+        return NULL;
+    }
+    external->internal = key;
+
+    return external;
+}
+
+
+void wolfSSL_DSA_free(WOLFSSL_DSA* dsa)
+{
+    WOLFSSL_MSG("wolfSSL_DSA_free");
+
+    if (dsa) {
+        if (dsa->internal) {
+            FreeDsaKey((DsaKey*)dsa->internal);
+            XFREE(dsa->internal, NULL, DYNAMIC_TYPE_DSA);
+            dsa->internal = NULL;
+        }
+        wolfSSL_BN_free(dsa->priv_key);
+        wolfSSL_BN_free(dsa->pub_key);
+        wolfSSL_BN_free(dsa->g);
+        wolfSSL_BN_free(dsa->q);
+        wolfSSL_BN_free(dsa->p);
+        InitwolfSSL_DSA(dsa);  /* set back to NULLs for safety */
+
+        XFREE(dsa, NULL, DYNAMIC_TYPE_DSA);
+
+        /* dsa = NULL, don't try to access or double free it */
+    }
+}
+
+#endif /* NO_DSA */
+#endif /* OPENSSL_EXTRA */
+
+#ifdef OPENSSL_EXTRA
+
+#ifndef NO_DSA
+/* wolfSSL -> OpenSSL */
+int SetDsaExternal(WOLFSSL_DSA* dsa)
+{
+    DsaKey* key;
+    WOLFSSL_MSG("Entering SetDsaExternal");
+
+    if (dsa == NULL || dsa->internal == NULL) {
+        WOLFSSL_MSG("dsa key NULL error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    key = (DsaKey*)dsa->internal;
+
+    if (SetIndividualExternal(&dsa->p, &key->p) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("dsa p key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (SetIndividualExternal(&dsa->q, &key->q) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("dsa q key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (SetIndividualExternal(&dsa->g, &key->g) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("dsa g key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (SetIndividualExternal(&dsa->pub_key, &key->y) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("dsa y key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (SetIndividualExternal(&dsa->priv_key, &key->x) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("dsa x key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    dsa->exSet = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* Openssl -> WolfSSL */
+int SetDsaInternal(WOLFSSL_DSA* dsa)
+{
+    DsaKey* key;
+    WOLFSSL_MSG("Entering SetDsaInternal");
+
+    if (dsa == NULL || dsa->internal == NULL) {
+        WOLFSSL_MSG("dsa key NULL error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    key = (DsaKey*)dsa->internal;
+
+    if (dsa->p != NULL &&
+        SetIndividualInternal(dsa->p, &key->p) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa p key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (dsa->q != NULL &&
+        SetIndividualInternal(dsa->q, &key->q) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa q key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (dsa->g != NULL &&
+        SetIndividualInternal(dsa->g, &key->g) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa g key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (dsa->pub_key != NULL) {
+        if (SetIndividualInternal(dsa->pub_key, &key->y) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("rsa pub_key error");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        /* public key */
+        key->type = DSA_PUBLIC;
+    }
+
+    if (dsa->priv_key != NULL) {
+        if (SetIndividualInternal(dsa->priv_key, &key->x) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("rsa priv_key error");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        /* private key */
+        key->type = DSA_PRIVATE;
+    }
+
+    dsa->inSet = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* NO_DSA */
+#endif /* OPENSSL_EXTRA */
+
+
+#ifdef OPENSSL_EXTRA
+#if !defined(NO_RSA)
+/* Generates a RSA key of length len
+ *
+ * len  length of RSA key i.e. 2048
+ * e    e to use when generating RSA key
+ * f    callback function for generation details
+ * data user callback argument
+ *
+ * Note: Because of wc_MakeRsaKey an RSA key size generated can be slightly
+ *       rounded down. For example generating a key of size 2999 with e =
+ *       65537 will make a key of size 374 instead of 375.
+ * Returns a new RSA key on success and NULL on failure
+ */
+WOLFSSL_RSA* wolfSSL_RSA_generate_key(int len, unsigned long e,
+                                      void(*f)(int, int, void*), void* data)
+{
+    WOLFSSL_RSA*    rsa = NULL;
+    WOLFSSL_BIGNUM* bn  = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_RSA_generate_key");
+
+    (void)f;
+    (void)data;
+
+    if (len < 0) {
+        WOLFSSL_MSG("Bad argument: length was less than 0");
+        return NULL;
+    }
+
+    bn = wolfSSL_BN_new();
+    if (bn == NULL) {
+        WOLFSSL_MSG("Error creating big number");
+        return NULL;
+    }
+
+    if (wolfSSL_BN_set_word(bn, (WOLFSSL_BN_ULONG)e) != SSL_SUCCESS) {
+        WOLFSSL_MSG("Error using e value");
+        wolfSSL_BN_free(bn);
+        return NULL;
+    }
+
+    rsa = wolfSSL_RSA_new();
+    if (rsa == NULL) {
+        WOLFSSL_MSG("memory error");
+    }
+    else {
+        if (wolfSSL_RSA_generate_key_ex(rsa, len, bn, NULL) != SSL_SUCCESS){
+            wolfSSL_RSA_free(rsa);
+            rsa = NULL;
+        }
+    }
+    wolfSSL_BN_free(bn);
+
+    return rsa;
+}
+
+
+/* return compliant with OpenSSL
+ *   1 if success, 0 if error
+ */
+int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA* rsa, int bits, WOLFSSL_BIGNUM* bn,
+                                void* cb)
+{
+    int ret = WOLFSSL_FAILURE;
+
+    (void)cb;
+    (void)bn;
+    (void)bits;
+
+    WOLFSSL_ENTER("wolfSSL_RSA_generate_key_ex");
+
+    if (rsa == NULL || rsa->internal == NULL) {
+        /* bit size checked during make key call */
+        WOLFSSL_MSG("bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+#ifdef WOLFSSL_KEY_GEN
+    {
+    #ifdef WOLFSSL_SMALL_STACK
+        WC_RNG* rng;
+    #else
+        WC_RNG  rng[1];
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+        if (rng == NULL)
+            return WOLFSSL_FAILURE;
+    #endif
+
+        if (wc_InitRng(rng) < 0)
+            WOLFSSL_MSG("RNG init failed");
+        else if (wc_MakeRsaKey((RsaKey*)rsa->internal, bits,
+                    wolfSSL_BN_get_word(bn), rng) != MP_OKAY)
+            WOLFSSL_MSG("wc_MakeRsaKey failed");
+        else if (SetRsaExternal(rsa) != WOLFSSL_SUCCESS)
+            WOLFSSL_MSG("SetRsaExternal failed");
+        else {
+            rsa->inSet = 1;
+            ret = WOLFSSL_SUCCESS;
+        }
+
+        wc_FreeRng(rng);
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(rng, NULL, DYNAMIC_TYPE_RNG);
+    #endif
+    }
+#else
+    WOLFSSL_MSG("No Key Gen built in");
+#endif
+    return ret;
+}
+#endif /* NO_RSA */
+
+#ifndef NO_DSA
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_DSA_generate_key(WOLFSSL_DSA* dsa)
+{
+    int ret = WOLFSSL_FAILURE;
+
+    WOLFSSL_ENTER("wolfSSL_DSA_generate_key");
+
+    if (dsa == NULL || dsa->internal == NULL) {
+        WOLFSSL_MSG("Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (dsa->inSet == 0) {
+        WOLFSSL_MSG("No DSA internal set, do it");
+
+        if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetDsaInternal failed");
+            return ret;
+        }
+    }
+
+#ifdef WOLFSSL_KEY_GEN
+    {
+        int initTmpRng = 0;
+        WC_RNG *rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+        WC_RNG *tmpRNG;
+#else
+        WC_RNG tmpRNG[1];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+        tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+        if (tmpRNG == NULL)
+            return WOLFSSL_FATAL_ERROR;
+#endif
+        if (wc_InitRng(tmpRNG) == 0) {
+            rng = tmpRNG;
+            initTmpRng = 1;
+        }
+        else {
+            WOLFSSL_MSG("Bad RNG Init, trying global");
+            if (initGlobalRNG == 0)
+                WOLFSSL_MSG("Global RNG no Init");
+            else
+                rng = &globalRNG;
+        }
+
+        if (rng) {
+            if (wc_MakeDsaKey(rng, (DsaKey*)dsa->internal) != MP_OKAY)
+                WOLFSSL_MSG("wc_MakeDsaKey failed");
+            else if (SetDsaExternal(dsa) != WOLFSSL_SUCCESS)
+                WOLFSSL_MSG("SetDsaExternal failed");
+            else
+                ret = WOLFSSL_SUCCESS;
+        }
+
+        if (initTmpRng)
+            wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+    }
+#else /* WOLFSSL_KEY_GEN */
+    WOLFSSL_MSG("No Key Gen built in");
+#endif
+    return ret;
+}
+
+
+/* Returns a pointer to a new WOLFSSL_DSA structure on success and NULL on fail
+ */
+WOLFSSL_DSA* wolfSSL_DSA_generate_parameters(int bits, unsigned char* seed,
+        int seedLen, int* counterRet, unsigned long* hRet,
+        WOLFSSL_BN_CB cb, void* CBArg)
+{
+    WOLFSSL_DSA* dsa;
+
+    WOLFSSL_ENTER("wolfSSL_DSA_generate_parameters()");
+
+    (void)cb;
+    (void)CBArg;
+    dsa = wolfSSL_DSA_new();
+    if (dsa == NULL) {
+        return NULL;
+    }
+
+    if (wolfSSL_DSA_generate_parameters_ex(dsa, bits, seed, seedLen,
+                                  counterRet, hRet, NULL) != SSL_SUCCESS) {
+        wolfSSL_DSA_free(dsa);
+        return NULL;
+    }
+
+    return dsa;
+}
+
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_DSA_generate_parameters_ex(WOLFSSL_DSA* dsa, int bits,
+                                       unsigned char* seed, int seedLen,
+                                       int* counterRet,
+                                       unsigned long* hRet, void* cb)
+{
+    int ret = WOLFSSL_FAILURE;
+
+    (void)bits;
+    (void)seed;
+    (void)seedLen;
+    (void)counterRet;
+    (void)hRet;
+    (void)cb;
+
+    WOLFSSL_ENTER("wolfSSL_DSA_generate_parameters_ex");
+
+    if (dsa == NULL || dsa->internal == NULL) {
+        WOLFSSL_MSG("Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+#ifdef WOLFSSL_KEY_GEN
+    {
+        int initTmpRng = 0;
+        WC_RNG *rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+        WC_RNG *tmpRNG;
+#else
+        WC_RNG tmpRNG[1];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+        tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+        if (tmpRNG == NULL)
+            return WOLFSSL_FATAL_ERROR;
+#endif
+        if (wc_InitRng(tmpRNG) == 0) {
+            rng = tmpRNG;
+            initTmpRng = 1;
+        }
+        else {
+            WOLFSSL_MSG("Bad RNG Init, trying global");
+            if (initGlobalRNG == 0)
+                WOLFSSL_MSG("Global RNG no Init");
+            else
+                rng = &globalRNG;
+        }
+
+        if (rng) {
+            if (wc_MakeDsaParameters(rng, bits,
+                                     (DsaKey*)dsa->internal) != MP_OKAY)
+                WOLFSSL_MSG("wc_MakeDsaParameters failed");
+            else if (SetDsaExternal(dsa) != WOLFSSL_SUCCESS)
+                WOLFSSL_MSG("SetDsaExternal failed");
+            else
+                ret = WOLFSSL_SUCCESS;
+        }
+
+        if (initTmpRng)
+            wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+    }
+#else /* WOLFSSL_KEY_GEN */
+    WOLFSSL_MSG("No Key Gen built in");
+#endif
+
+    return ret;
+}
+
+WOLFSSL_DSA_SIG* wolfSSL_DSA_SIG_new(void)
+{
+    WOLFSSL_DSA_SIG* sig;
+    WOLFSSL_ENTER("wolfSSL_DSA_SIG_new");
+    sig = (WOLFSSL_DSA_SIG*)XMALLOC(sizeof(WOLFSSL_DSA_SIG), NULL, DYNAMIC_TYPE_OPENSSL);
+    if (sig)
+        XMEMSET(sig, 0, sizeof(WOLFSSL_DSA_SIG));
+    return sig;
+}
+
+void wolfSSL_DSA_SIG_free(WOLFSSL_DSA_SIG *sig)
+{
+    WOLFSSL_ENTER("wolfSSL_DSA_SIG_free");
+    if (sig) {
+        if (sig->r) {
+            wolfSSL_BN_free(sig->r);
+        }
+        if (sig->s) {
+            wolfSSL_BN_free(sig->s);
+        }
+        XFREE(sig, NULL, DYNAMIC_TYPE_OPENSSL);
+    }
+}
+
+/* return WOLFSSL_SUCCESS on success, < 0 otherwise */
+int wolfSSL_DSA_do_sign(const unsigned char* d, unsigned char* sigRet,
+                       WOLFSSL_DSA* dsa)
+{
+    int     ret = WOLFSSL_FATAL_ERROR;
+    int     initTmpRng = 0;
+    WC_RNG* rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG* tmpRNG = NULL;
+#else
+    WC_RNG  tmpRNG[1];
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_DSA_do_sign");
+
+    if (d == NULL || sigRet == NULL || dsa == NULL) {
+        WOLFSSL_MSG("Bad function arguments");
+        return ret;
+    }
+
+    if (dsa->inSet == 0)
+    {
+        WOLFSSL_MSG("No DSA internal set, do it");
+
+        if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetDsaInternal failed");
+            return ret;
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+    if (tmpRNG == NULL)
+        return WOLFSSL_FATAL_ERROR;
+#endif
+
+    if (wc_InitRng(tmpRNG) == 0) {
+        rng = tmpRNG;
+        initTmpRng = 1;
+    }
+    else {
+        WOLFSSL_MSG("Bad RNG Init, trying global");
+        if (initGlobalRNG == 0)
+            WOLFSSL_MSG("Global RNG no Init");
+        else
+            rng = &globalRNG;
+    }
+
+    if (rng) {
+        if (DsaSign(d, sigRet, (DsaKey*)dsa->internal, rng) < 0)
+            WOLFSSL_MSG("DsaSign failed");
+        else
+            ret = WOLFSSL_SUCCESS;
+    }
+
+    if (initTmpRng)
+        wc_FreeRng(tmpRNG);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+    return ret;
+}
+
+#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS)
+WOLFSSL_DSA_SIG* wolfSSL_DSA_do_sign_ex(const unsigned char* digest,
+                                        int outLen, WOLFSSL_DSA* dsa)
+{
+    WOLFSSL_DSA_SIG* sig = NULL;
+    byte sigBin[DSA_SIG_SIZE];
+
+    WOLFSSL_ENTER("wolfSSL_DSA_do_sign_ex");
+
+    if (!digest || !dsa || outLen != WC_SHA_DIGEST_SIZE) {
+        WOLFSSL_MSG("Bad function arguments");
+        return NULL;
+    }
+
+    if (wolfSSL_DSA_do_sign(digest, sigBin, dsa) != WOLFSSL_SUCCESS) {
+        return NULL;
+    }
+
+    if (!(sig = wolfSSL_DSA_SIG_new())) {
+        goto error;
+    }
+
+    if (!(sig->r = wolfSSL_BN_bin2bn(sigBin, DSA_HALF_SIZE, NULL))) {
+        goto error;
+    }
+
+    if (!(sig->s = wolfSSL_BN_bin2bn(sigBin + DSA_HALF_SIZE, DSA_HALF_SIZE, NULL))) {
+        goto error;
+    }
+
+    return sig;
+error:
+    if (sig) {
+        wolfSSL_DSA_SIG_free(sig);
+    }
+    return NULL;
+}
+#endif /* !HAVE_SELFTEST && !HAVE_FIPS */
+
+int wolfSSL_DSA_do_verify(const unsigned char* d, unsigned char* sig,
+                        WOLFSSL_DSA* dsa, int *dsacheck)
+{
+    int    ret = WOLFSSL_FATAL_ERROR;
+
+    WOLFSSL_ENTER("wolfSSL_DSA_do_verify");
+
+    if (d == NULL || sig == NULL || dsa == NULL) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FATAL_ERROR;
+    }
+    if (dsa->inSet == 0)
+    {
+        WOLFSSL_MSG("No DSA internal set, do it");
+
+        if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetDsaInternal failed");
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+
+    ret = DsaVerify(d, sig, (DsaKey*)dsa->internal, dsacheck);
+    if (ret != 0 || *dsacheck != 1) {
+        WOLFSSL_MSG("DsaVerify failed");
+        return ret;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS)
+int wolfSSL_DSA_do_verify_ex(const unsigned char* digest, int digest_len,
+                             WOLFSSL_DSA_SIG* sig, WOLFSSL_DSA* dsa)
+{
+    int dsacheck, sz;
+    byte sigBin[DSA_SIG_SIZE];
+    byte* sigBinPtr = sigBin;
+
+    WOLFSSL_ENTER("wolfSSL_DSA_do_verify_ex");
+
+    if (!digest || !sig || !dsa || digest_len != WC_SHA_DIGEST_SIZE) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (!sig->r || !sig->s) {
+        WOLFSSL_MSG("No signature found in DSA_SIG");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* front pad with zeros */
+    if (!(sz = wolfSSL_BN_num_bytes(sig->r))) {
+        return WOLFSSL_FAILURE;
+    }
+    while (sz++ < DSA_HALF_SIZE) {
+        *sigBinPtr++ = 0;
+    }
+
+    if (wolfSSL_BN_bn2bin(sig->r, sigBinPtr) == WOLFSSL_FATAL_ERROR) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* Move to s */
+    sigBinPtr = sigBin + DSA_HALF_SIZE;
+
+    /* front pad with zeros */
+    if (!(sz = wolfSSL_BN_num_bytes(sig->s))) {
+        return WOLFSSL_FAILURE;
+    }
+    while (sz++ < DSA_HALF_SIZE) {
+        *sigBinPtr++ = 0;
+    }
+
+    if (wolfSSL_BN_bn2bin(sig->s, sigBinPtr) == WOLFSSL_FATAL_ERROR) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if (wolfSSL_DSA_do_verify(digest, sigBin, dsa, &dsacheck) != WOLFSSL_SUCCESS ||
+            dsacheck != 1) {
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* !HAVE_SELFTEST && !HAVE_FIPS */
+#endif /* NO_DSA */
+
+
+#if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+
+#ifdef DEBUG_SIGN
+static void show(const char *title, const unsigned char *out, unsigned int outlen)
+{
+    const unsigned char *pt;
+    printf("%s[%d] = \n", title, (int)outlen);
+    outlen = outlen>100?100:outlen;
+    for (pt = out; pt < out + outlen;
+            printf("%c", ((*pt)&0x6f)>='A'?((*pt)&0x6f):'.'), pt++);
+    printf("\n");
+}
+#else
+#define show(a,b,c)
+#endif
+
+/* return SSL_SUCCESS on ok, 0 otherwise */
+int wolfSSL_RSA_sign(int type, const unsigned char* m,
+                           unsigned int mLen, unsigned char* sigRet,
+                           unsigned int* sigLen, WOLFSSL_RSA* rsa)
+{
+    return wolfSSL_RSA_sign_ex(type, m, mLen, sigRet, sigLen, rsa, 1);
+}
+
+int wolfSSL_RSA_sign_ex(int type, const unsigned char* m,
+                           unsigned int mLen, unsigned char* sigRet,
+                           unsigned int* sigLen, WOLFSSL_RSA* rsa, int flag)
+{
+    word32  outLen;
+    word32  signSz;
+    int     initTmpRng = 0;
+    WC_RNG* rng        = NULL;
+    int     ret        = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG* tmpRNG     = NULL;
+    byte*   encodedSig = NULL;
+#else
+    WC_RNG  tmpRNG[1];
+    byte    encodedSig[MAX_ENCODED_SIG_SZ];
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_RSA_sign");
+
+    if (m == NULL || sigRet == NULL || sigLen == NULL || rsa == NULL) {
+        WOLFSSL_MSG("Bad function arguments");
+        return 0;
+    }
+    show("Message to Sign", m, mLen);
+
+    switch (type) {
+    #ifdef WOLFSSL_MD2
+        case NID_md2:       type = MD2h;    break;
+    #endif
+    #ifndef NO_MD5
+        case NID_md5:       type = MD5h;    break;
+    #endif
+    #ifndef NO_SHA
+        case NID_sha1:      type = SHAh;    break;
+    #endif
+    #ifndef NO_SHA256
+        case NID_sha256:    type = SHA256h; break;
+    #endif
+    #ifdef WOLFSSL_SHA384
+        case NID_sha384:    type = SHA384h; break;
+    #endif
+    #ifdef WOLFSSL_SHA512
+        case NID_sha512:    type = SHA512h; break;
+    #endif
+    #ifndef WOLFSSL_NOSHA3_224
+        case NID_sha3_224:  type = SHA3_224h; break;
+    #endif
+    #ifndef WOLFSSL_NOSHA3_256
+        case NID_sha3_256:  type = SHA3_256h; break;
+    #endif
+    #ifndef WOLFSSL_NOSHA3_384
+        case NID_sha3_384:  type = SHA3_384h; break;
+    #endif
+    #ifndef WOLFSSL_NOSHA3_512
+        case NID_sha3_512:  type = SHA3_512h; break;
+    #endif
+        default:
+            WOLFSSL_MSG("This NID (md type) not configured or not implemented");
+            return 0;
+    }
+
+    if (rsa->inSet == 0)
+    {
+        WOLFSSL_MSG("No RSA internal set, do it");
+
+        if (SetRsaInternal(rsa) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetRsaInternal failed");
+            return 0;
+        }
+    }
+
+    outLen = (word32)wolfSSL_BN_num_bytes(rsa->n);
+
+#ifdef WOLFSSL_SMALL_STACK
+    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+    if (tmpRNG == NULL)
+        return 0;
+
+    encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL,
+                                                   DYNAMIC_TYPE_SIGNATURE);
+    if (encodedSig == NULL) {
+        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+        return 0;
+    }
+#endif
+
+    if (outLen == 0)
+        WOLFSSL_MSG("Bad RSA size");
+    else if (wc_InitRng(tmpRNG) == 0) {
+        rng = tmpRNG;
+        initTmpRng = 1;
+    }
+    else {
+        WOLFSSL_MSG("Bad RNG Init, trying global");
+
+        if (initGlobalRNG == 0)
+            WOLFSSL_MSG("Global RNG no Init");
+        else
+            rng = &globalRNG;
+    }
+
+    if (rng) {
+
+        signSz = wc_EncodeSignature(encodedSig, m, mLen, type);
+        if (signSz == 0) {
+            WOLFSSL_MSG("Bad Encode Signature");
+        }
+        else {
+            show("Encoded Message", encodedSig, signSz);
+            if (flag != 0) {
+                ret = wc_RsaSSL_Sign(encodedSig, signSz, sigRet, outLen,
+                                (RsaKey*)rsa->internal, rng);
+                if (ret <= 0) {
+                    WOLFSSL_MSG("Bad Rsa Sign");
+                    ret = 0;
+                }
+                else {
+                    *sigLen = (unsigned int)ret;
+                    ret = SSL_SUCCESS;
+                    show("Signature", sigRet, *sigLen);
+                }
+            } else {
+                ret = SSL_SUCCESS;
+                XMEMCPY(sigRet, encodedSig, signSz);
+                *sigLen = signSz;
+            }
+        }
+
+    }
+
+    if (initTmpRng)
+        wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(tmpRNG,     NULL, DYNAMIC_TYPE_RNG);
+    XFREE(encodedSig, NULL, DYNAMIC_TYPE_SIGNATURE);
+#endif
+
+    if (ret == WOLFSSL_SUCCESS)
+        WOLFSSL_MSG("wolfSSL_RSA_sign success");
+    else {
+        WOLFSSL_MSG("wolfSSL_RSA_sign failed");
+    }
+    return ret;
+}
+
+
+/* returns WOLFSSL_SUCCESS on successful verify and WOLFSSL_FAILURE on fail */
+int wolfSSL_RSA_verify(int type, const unsigned char* m,
+                               unsigned int mLen, const unsigned char* sig,
+                               unsigned int sigLen, WOLFSSL_RSA* rsa)
+{
+    int     ret;
+    unsigned char *sigRet ;
+    unsigned char *sigDec ;
+    unsigned int   len;
+
+    WOLFSSL_ENTER("wolfSSL_RSA_verify");
+    if ((m == NULL) || (sig == NULL)) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    sigRet = (unsigned char *)XMALLOC(sigLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (sigRet == NULL) {
+        WOLFSSL_MSG("Memory failure");
+        return WOLFSSL_FAILURE;
+    }
+    sigDec = (unsigned char *)XMALLOC(sigLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (sigDec == NULL) {
+        WOLFSSL_MSG("Memory failure");
+        XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_FAILURE;
+    }
+    /* get non-encrypted signature to be compared with decrypted signature */
+    ret = wolfSSL_RSA_sign_ex(type, m, mLen, sigRet, &len, rsa, 0);
+    if (ret <= 0) {
+        WOLFSSL_MSG("Message Digest Error");
+        XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_FAILURE;
+    }
+    show("Encoded Message", sigRet, len);
+    /* decrypt signature */
+    ret = wc_RsaSSL_Verify(sig, sigLen, (unsigned char *)sigDec, sigLen,
+        (RsaKey*)rsa->internal);
+    if (ret <= 0) {
+        WOLFSSL_MSG("RSA Decrypt error");
+        XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_FAILURE;
+    }
+    show("Decrypted Signature", sigDec, ret);
+
+    if ((int)len == ret && XMEMCMP(sigRet, sigDec, ret) == 0) {
+        WOLFSSL_MSG("wolfSSL_RSA_verify success");
+        XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_SUCCESS;
+    }
+    else {
+        WOLFSSL_MSG("wolfSSL_RSA_verify failed");
+        XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_FAILURE;
+    }
+}
+
+void wolfSSL_RSA_get0_key(const WOLFSSL_RSA *r, const WOLFSSL_BIGNUM **n,
+    const WOLFSSL_BIGNUM **e, const WOLFSSL_BIGNUM **d)
+{
+    WOLFSSL_ENTER("wolfSSL_RSA_get0_key");
+
+    if (r != NULL) {
+        if (n != NULL)
+            *n = r->n;
+        if (e != NULL)
+            *e = r->e;
+        if (d != NULL)
+            *d = r->d;
+    } else {
+        if (n != NULL)
+            *n = NULL;
+        if (e != NULL)
+            *e = NULL;
+        if (d != NULL)
+            *d = NULL;
+    }
+}
+
+/* generate p-1 and q-1, WOLFSSL_SUCCESS on ok */
+int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa)
+{
+    int    err;
+    mp_int tmp;
+
+    WOLFSSL_MSG("wolfSSL_RsaGenAdd");
+
+    if (rsa == NULL || rsa->p == NULL || rsa->q == NULL || rsa->d == NULL ||
+                       rsa->dmp1 == NULL || rsa->dmq1 == NULL) {
+        WOLFSSL_MSG("rsa no init error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (mp_init(&tmp) != MP_OKAY) {
+        WOLFSSL_MSG("mp_init error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    err = mp_sub_d((mp_int*)rsa->p->internal, 1, &tmp);
+    if (err != MP_OKAY) {
+        WOLFSSL_MSG("mp_sub_d error");
+    }
+    else
+        err = mp_mod((mp_int*)rsa->d->internal, &tmp,
+                     (mp_int*)rsa->dmp1->internal);
+
+    if (err != MP_OKAY) {
+        WOLFSSL_MSG("mp_mod error");
+    }
+    else
+        err = mp_sub_d((mp_int*)rsa->q->internal, 1, &tmp);
+    if (err != MP_OKAY) {
+        WOLFSSL_MSG("mp_sub_d error");
+    }
+    else
+        err = mp_mod((mp_int*)rsa->d->internal, &tmp,
+                     (mp_int*)rsa->dmq1->internal);
+
+    mp_clear(&tmp);
+
+    if (err == MP_OKAY)
+        return WOLFSSL_SUCCESS;
+    else
+        return WOLFSSL_FATAL_ERROR;
+}
+#endif /* !NO_RSA && !HAVE_USER_RSA */
+
+WOLFSSL_HMAC_CTX* wolfSSL_HMAC_CTX_new(void)
+{
+    return (WOLFSSL_HMAC_CTX*)XMALLOC(sizeof(WOLFSSL_HMAC_CTX), NULL,
+        DYNAMIC_TYPE_OPENSSL);
+}
+
+int wolfSSL_HMAC_CTX_Init(WOLFSSL_HMAC_CTX* ctx)
+{
+    WOLFSSL_MSG("wolfSSL_HMAC_CTX_Init");
+
+    if (ctx != NULL) {
+        /* wc_HmacSetKey sets up ctx->hmac */
+        XMEMSET(ctx, 0, sizeof(WOLFSSL_HMAC_CTX));
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_HMAC_Init_ex(WOLFSSL_HMAC_CTX* ctx, const void* key,
+                             int keylen, const EVP_MD* type, WOLFSSL_ENGINE* e)
+{
+    WOLFSSL_ENTER("wolfSSL_HMAC_Init_ex");
+
+    /* WOLFSSL_ENGINE not used, call wolfSSL_HMAC_Init */
+    (void)e;
+    return wolfSSL_HMAC_Init(ctx, key, keylen, type);
+}
+
+
+/* helper function for Deep copy of internal wolfSSL hmac structure
+ * returns WOLFSSL_SUCCESS on success */
+int wolfSSL_HmacCopy(Hmac* des, Hmac* src)
+{
+    void* heap;
+
+#ifndef HAVE_FIPS
+    heap = src->heap;
+#else
+    heap = NULL;
+#endif
+    if (wc_HmacInit(des, heap, 0) != 0) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* requires that hash structures have no dynamic parts to them */
+    switch (src->macType) {
+    #ifndef NO_MD5
+        case WC_MD5:
+            wc_Md5Copy(&src->hash.md5, &des->hash.md5);
+            break;
+    #endif /* !NO_MD5 */
+
+    #ifndef NO_SHA
+        case WC_SHA:
+            wc_ShaCopy(&src->hash.sha, &des->hash.sha);
+            break;
+    #endif /* !NO_SHA */
+
+    #ifdef WOLFSSL_SHA224
+        case WC_SHA224:
+            wc_Sha224Copy(&src->hash.sha224, &des->hash.sha224);
+            break;
+    #endif /* WOLFSSL_SHA224 */
+
+    #ifndef NO_SHA256
+        case WC_SHA256:
+            wc_Sha256Copy(&src->hash.sha256, &des->hash.sha256);
+            break;
+    #endif /* !NO_SHA256 */
+
+    #ifdef WOLFSSL_SHA384
+        case WC_SHA384:
+            wc_Sha384Copy(&src->hash.sha384, &des->hash.sha384);
+            break;
+    #endif /* WOLFSSL_SHA384 */
+    #ifdef WOLFSSL_SHA512
+        case WC_SHA512:
+            wc_Sha512Copy(&src->hash.sha512, &des->hash.sha512);
+            break;
+    #endif /* WOLFSSL_SHA512 */
+
+        default:
+            return WOLFSSL_FAILURE;
+    }
+
+    XMEMCPY((byte*)des->ipad, (byte*)src->ipad, WC_HMAC_BLOCK_SIZE);
+    XMEMCPY((byte*)des->opad, (byte*)src->opad, WC_HMAC_BLOCK_SIZE);
+    XMEMCPY((byte*)des->innerHash, (byte*)src->innerHash, WC_MAX_DIGEST_SIZE);
+#ifndef HAVE_FIPS
+    des->heap    = heap;
+#endif
+    des->macType = src->macType;
+    des->innerHashKeyed = src->innerHashKeyed;
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    XMEMCPY(&des->asyncDev, &src->asyncDev, sizeof(WC_ASYNC_DEV));
+    des->keyLen = src->keyLen;
+    #ifdef HAVE_CAVIUM
+        des->data = (byte*)XMALLOC(src->dataLen, des->heap,
+                DYNAMIC_TYPE_HMAC);
+        if (des->data == NULL) {
+            return BUFFER_E;
+        }
+        XMEMCPY(des->data, src->data, src->dataLen);
+        des->dataLen = src->dataLen;
+    #endif /* HAVE_CAVIUM */
+#endif /* WOLFSSL_ASYNC_CRYPT */
+        return WOLFSSL_SUCCESS;
+}
+
+
+/* Deep copy of information from src to des structure
+ *
+ * des destination to copy information to
+ * src structure to get information from
+ *
+ * Returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on error
+ */
+int wolfSSL_HMAC_CTX_copy(WOLFSSL_HMAC_CTX* des, WOLFSSL_HMAC_CTX* src)
+{
+    WOLFSSL_ENTER("wolfSSL_HMAC_CTX_copy");
+
+    if (des == NULL || src == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    des->type = src->type;
+    XMEMCPY((byte *)&des->save_ipad, (byte *)&src->hmac.ipad,
+                                        WC_HMAC_BLOCK_SIZE);
+    XMEMCPY((byte *)&des->save_opad, (byte *)&src->hmac.opad,
+                                        WC_HMAC_BLOCK_SIZE);
+
+    return wolfSSL_HmacCopy(&des->hmac, &src->hmac);
+}
+
+
+#if defined(HAVE_FIPS) && \
+    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
+
+static int _HMAC_Init(Hmac* hmac, int type, void* heap)
+{
+    int ret = 0;
+
+    switch (type) {
+    #ifndef NO_MD5
+        case WC_MD5:
+            ret = wc_InitMd5(&hmac->hash.md5);
+            break;
+    #endif /* !NO_MD5 */
+
+    #ifndef NO_SHA
+        case WC_SHA:
+            ret = wc_InitSha(&hmac->hash.sha);
+            break;
+    #endif /* !NO_SHA */
+
+    #ifdef WOLFSSL_SHA224
+        case WC_SHA224:
+            ret = wc_InitSha224(&hmac->hash.sha224);
+            break;
+    #endif /* WOLFSSL_SHA224 */
+
+    #ifndef NO_SHA256
+        case WC_SHA256:
+            ret = wc_InitSha256(&hmac->hash.sha256);
+            break;
+    #endif /* !NO_SHA256 */
+
+    #ifdef WOLFSSL_SHA384
+        case WC_SHA384:
+            ret = wc_InitSha384(&hmac->hash.sha384);
+            break;
+    #endif /* WOLFSSL_SHA384 */
+    #ifdef WOLFSSL_SHA512
+        case WC_SHA512:
+            ret = wc_InitSha512(&hmac->hash.sha512);
+            break;
+    #endif /* WOLFSSL_SHA512 */
+
+    #ifdef WOLFSSL_SHA3
+        case WC_SHA3_224:
+            ret = wc_InitSha3_224(&hmac->hash.sha3, heap, INVALID_DEVID);
+            break;
+        case WC_SHA3_256:
+            ret = wc_InitSha3_256(&hmac->hash.sha3, heap, INVALID_DEVID);
+            break;
+        case WC_SHA3_384:
+            ret = wc_InitSha3_384(&hmac->hash.sha3, heap, INVALID_DEVID);
+            break;
+        case WC_SHA3_512:
+            ret = wc_InitSha3_512(&hmac->hash.sha3, heap, INVALID_DEVID);
+            break;
+    #endif
+
+        default:
+            ret = BAD_FUNC_ARG;
+            break;
+    }
+
+    (void)heap;
+
+    return ret;
+}
+
+#else
+    #define _HMAC_Init _InitHmac
+#endif
+
+
+int wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key, int keylen,
+                  const EVP_MD* type)
+{
+    int hmac_error = 0;
+    void* heap = NULL;
+
+    WOLFSSL_MSG("wolfSSL_HMAC_Init");
+
+    if (ctx == NULL) {
+        WOLFSSL_MSG("no ctx on init");
+        return WOLFSSL_FAILURE;
+    }
+
+#ifndef HAVE_FIPS
+    heap = ctx->hmac.heap;
+#endif
+
+    if (type) {
+        WOLFSSL_MSG("init has type");
+
+#ifndef NO_MD5
+        if (XSTRNCMP(type, "MD5", 3) == 0) {
+            WOLFSSL_MSG("md5 hmac");
+            ctx->type = WC_MD5;
+        }
+        else
+#endif
+#ifdef WOLFSSL_SHA224
+        if (XSTRNCMP(type, "SHA224", 6) == 0) {
+            WOLFSSL_MSG("sha224 hmac");
+            ctx->type = WC_SHA224;
+        }
+        else
+#endif
+#ifndef NO_SHA256
+        if (XSTRNCMP(type, "SHA256", 6) == 0) {
+            WOLFSSL_MSG("sha256 hmac");
+            ctx->type = WC_SHA256;
+        }
+        else
+#endif
+#ifdef WOLFSSL_SHA384
+        if (XSTRNCMP(type, "SHA384", 6) == 0) {
+            WOLFSSL_MSG("sha384 hmac");
+            ctx->type = WC_SHA384;
+        }
+        else
+#endif
+#ifdef WOLFSSL_SHA512
+        if (XSTRNCMP(type, "SHA512", 6) == 0) {
+            WOLFSSL_MSG("sha512 hmac");
+            ctx->type = WC_SHA512;
+        }
+        else
+#endif
+
+#ifndef NO_SHA
+        /* has to be last since would pick or 256, 384, or 512 too */
+        if (XSTRNCMP(type, "SHA", 3) == 0) {
+            WOLFSSL_MSG("sha hmac");
+            ctx->type = WC_SHA;
+        }
+        else
+#endif
+        {
+            WOLFSSL_MSG("bad init type");
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+    if (key && keylen) {
+        WOLFSSL_MSG("keying hmac");
+
+        if (wc_HmacInit(&ctx->hmac, NULL, INVALID_DEVID) == 0) {
+            hmac_error = wc_HmacSetKey(&ctx->hmac, ctx->type, (const byte*)key,
+                                       (word32)keylen);
+            if (hmac_error < 0){
+                wc_HmacFree(&ctx->hmac);
+                return WOLFSSL_FAILURE;
+            }
+            XMEMCPY((byte *)&ctx->save_ipad, (byte *)&ctx->hmac.ipad,
+                                        WC_HMAC_BLOCK_SIZE);
+            XMEMCPY((byte *)&ctx->save_opad, (byte *)&ctx->hmac.opad,
+                                        WC_HMAC_BLOCK_SIZE);
+        }
+        /* OpenSSL compat, no error */
+    } else if(ctx->type >= 0) { /* MD5 == 0 */
+        WOLFSSL_MSG("recover hmac");
+        wc_HmacFree(&ctx->hmac);
+        if (wc_HmacInit(&ctx->hmac, NULL, INVALID_DEVID) == 0) {
+            ctx->hmac.macType = (byte)ctx->type;
+            ctx->hmac.innerHashKeyed = 0;
+            XMEMCPY((byte *)&ctx->hmac.ipad, (byte *)&ctx->save_ipad,
+                                       WC_HMAC_BLOCK_SIZE);
+            XMEMCPY((byte *)&ctx->hmac.opad, (byte *)&ctx->save_opad,
+                                       WC_HMAC_BLOCK_SIZE);
+            if ((hmac_error = _HMAC_Init(&ctx->hmac, ctx->hmac.macType, heap))
+                    !=0) {
+               return hmac_error;
+            }
+        }
+    }
+
+    (void)hmac_error;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_HMAC_Update(WOLFSSL_HMAC_CTX* ctx, const unsigned char* data,
+                    int len)
+{
+    int hmac_error = 0;
+
+    WOLFSSL_MSG("wolfSSL_HMAC_Update");
+
+    if (ctx == NULL) {
+        WOLFSSL_MSG("no ctx");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (data) {
+        WOLFSSL_MSG("updating hmac");
+        hmac_error = wc_HmacUpdate(&ctx->hmac, data, (word32)len);
+        if (hmac_error < 0){
+            WOLFSSL_MSG("hmac update error");
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_HMAC_Final(WOLFSSL_HMAC_CTX* ctx, unsigned char* hash,
+                   unsigned int* len)
+{
+    int hmac_error;
+
+    WOLFSSL_MSG("wolfSSL_HMAC_Final");
+
+    /* "len" parameter is optional. */
+    if (ctx == NULL || hash == NULL) {
+        WOLFSSL_MSG("invalid parameter");
+        return WOLFSSL_FAILURE;
+    }
+
+    WOLFSSL_MSG("final hmac");
+    hmac_error = wc_HmacFinal(&ctx->hmac, hash);
+    if (hmac_error < 0){
+        WOLFSSL_MSG("final hmac error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (len) {
+        WOLFSSL_MSG("setting output len");
+        switch (ctx->type) {
+            #ifndef NO_MD5
+            case WC_MD5:
+                *len = WC_MD5_DIGEST_SIZE;
+                break;
+            #endif
+
+            #ifndef NO_SHA
+            case WC_SHA:
+                *len = WC_SHA_DIGEST_SIZE;
+                break;
+            #endif
+
+            #ifdef WOLFSSL_SHA224
+            case WC_SHA224:
+                *len = WC_SHA224_DIGEST_SIZE;
+                break;
+            #endif
+
+            #ifndef NO_SHA256
+            case WC_SHA256:
+                *len = WC_SHA256_DIGEST_SIZE;
+                break;
+            #endif
+
+            #ifdef WOLFSSL_SHA384
+            case WC_SHA384:
+                *len = WC_SHA384_DIGEST_SIZE;
+                break;
+            #endif
+
+            #ifdef WOLFSSL_SHA512
+            case WC_SHA512:
+                *len = WC_SHA512_DIGEST_SIZE;
+                break;
+            #endif
+
+            default:
+                WOLFSSL_MSG("bad hmac type");
+                return WOLFSSL_FAILURE;
+        }
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_HMAC_cleanup(WOLFSSL_HMAC_CTX* ctx)
+{
+    WOLFSSL_MSG("wolfSSL_HMAC_cleanup");
+
+    if (ctx)
+        wc_HmacFree(&ctx->hmac);
+
+    return SSL_SUCCESS;
+}
+
+
+void wolfSSL_HMAC_CTX_free(WOLFSSL_HMAC_CTX* ctx)
+{
+    if (!ctx) {
+        return;
+    }
+    wolfSSL_HMAC_cleanup(ctx);
+    XFREE(ctx, NULL, DYNAMIC_TYPE_OPENSSL);
+}
+
+size_t wolfSSL_HMAC_size(const WOLFSSL_HMAC_CTX *ctx)
+{
+    if (!ctx) {
+        return 0;
+    }
+
+    return (size_t)wc_HashGetDigestSize((enum wc_HashType)ctx->hmac.macType);
+}
+
+#ifndef NO_DES3
+
+void wolfSSL_3des_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset,
+                            unsigned char* iv, int len)
+{
+    (void)len;
+
+    WOLFSSL_MSG("wolfSSL_3des_iv");
+
+    if (ctx == NULL || iv == NULL) {
+        WOLFSSL_MSG("Bad function argument");
+        return;
+    }
+
+    if (doset)
+        wc_Des3_SetIV(&ctx->cipher.des3, iv);  /* OpenSSL compat, no ret */
+    else
+        XMEMCPY(iv, &ctx->cipher.des3.reg, DES_BLOCK_SIZE);
+}
+
+#endif /* NO_DES3 */
+
+
+#ifndef NO_AES
+
+void wolfSSL_aes_ctr_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset,
+                      unsigned char* iv, int len)
+{
+    (void)len;
+
+    WOLFSSL_MSG("wolfSSL_aes_ctr_iv");
+
+    if (ctx == NULL || iv == NULL) {
+        WOLFSSL_MSG("Bad function argument");
+        return;
+    }
+
+    if (doset)
+       (void)wc_AesSetIV(&ctx->cipher.aes, iv);  /* OpenSSL compat, no ret */
+    else
+        XMEMCPY(iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE);
+}
+
+#endif /* NO_AES */
+
+
+/* Free the dynamically allocated data.
+ *
+ * p  Pointer to dynamically allocated memory.
+ */
+void wolfSSL_OPENSSL_free(void* p)
+{
+    WOLFSSL_MSG("wolfSSL_OPENSSL_free");
+
+    XFREE(p, NULL, DYNAMIC_TYPE_OPENSSL);
+}
+
+void *wolfSSL_OPENSSL_malloc(size_t a)
+{
+  return XMALLOC(a, NULL, DYNAMIC_TYPE_OPENSSL);
+}
+
+#if defined(WOLFSSL_KEY_GEN) && defined(WOLFSSL_PEM_TO_DER)
+
+static int EncryptDerKey(byte *der, int *derSz, const EVP_CIPHER* cipher,
+                         unsigned char* passwd, int passwdSz, byte **cipherInfo)
+{
+    int ret, paddingSz;
+    word32 idx, cipherInfoSz;
+#ifdef WOLFSSL_SMALL_STACK
+    EncryptedInfo* info = NULL;
+#else
+    EncryptedInfo  info[1];
+#endif
+
+    WOLFSSL_ENTER("EncryptDerKey");
+
+    if (der == NULL || derSz == NULL || cipher == NULL ||
+        passwd == NULL || cipherInfo == NULL)
+        return BAD_FUNC_ARG;
+
+#ifdef WOLFSSL_SMALL_STACK
+    info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
+                                   DYNAMIC_TYPE_ENCRYPTEDINFO);
+    if (info == NULL) {
+        WOLFSSL_MSG("malloc failed");
+        return WOLFSSL_FAILURE;
+    }
+#endif
+
+    XMEMSET(info, 0, sizeof(EncryptedInfo));
+
+    /* set the cipher name on info */
+    XSTRNCPY(info->name, cipher, NAME_SZ-1);
+    info->name[NAME_SZ-1] = '\0'; /* null term */
+
+    ret = wc_EncryptedInfoGet(info, info->name);
+    if (ret != 0) {
+        WOLFSSL_MSG("unsupported cipher");
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
+    #endif
+        return WOLFSSL_FAILURE;
+    }
+
+    /* Generate a random salt */
+    if (wolfSSL_RAND_bytes(info->iv, info->ivSz) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("generate iv failed");
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
+#endif
+        return WOLFSSL_FAILURE;
+    }
+
+    /* add the padding before encryption */
+    paddingSz = ((*derSz)/info->ivSz + 1) * info->ivSz - (*derSz);
+    if (paddingSz == 0)
+        paddingSz = info->ivSz;
+    XMEMSET(der+(*derSz), (byte)paddingSz, paddingSz);
+    (*derSz) += paddingSz;
+
+    /* encrypt buffer */
+    if (wc_BufferKeyEncrypt(info, der, *derSz, passwd, passwdSz, WC_MD5) != 0) {
+        WOLFSSL_MSG("encrypt key failed");
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
+#endif
+        return WOLFSSL_FAILURE;
+    }
+
+    /* create cipher info : 'cipher_name,Salt(hex)' */
+    cipherInfoSz = (word32)(2*info->ivSz + XSTRLEN(info->name) + 2);
+    *cipherInfo = (byte*)XMALLOC(cipherInfoSz, NULL,
+                                DYNAMIC_TYPE_STRING);
+    if (*cipherInfo == NULL) {
+        WOLFSSL_MSG("malloc failed");
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
+#endif
+        return WOLFSSL_FAILURE;
+    }
+    XSTRNCPY((char*)*cipherInfo, info->name, cipherInfoSz);
+    XSTRNCAT((char*)*cipherInfo, ",", 2);
+
+    idx = (word32)XSTRLEN((char*)*cipherInfo);
+    cipherInfoSz -= idx;
+    ret = Base16_Encode(info->iv, info->ivSz, *cipherInfo+idx, &cipherInfoSz);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
+#endif
+    if (ret != 0) {
+        WOLFSSL_MSG("Base16_Encode failed");
+        XFREE(*cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* WOLFSSL_KEY_GEN || WOLFSSL_PEM_TO_DER */
+
+#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+static int wolfSSL_RSA_To_Der(WOLFSSL_RSA* rsa, byte** outBuf, int publicKey)
+{
+    int derSz  = 0;
+    int ret;
+    byte* derBuf;
+
+    WOLFSSL_ENTER("wolfSSL_RSA_To_Der");
+
+    if (!rsa || (publicKey != 0 && publicKey != 1)) {
+        WOLFSSL_LEAVE("wolfSSL_RSA_To_Der", BAD_FUNC_ARG);
+        return BAD_FUNC_ARG;
+    }
+
+    if (rsa->inSet == 0) {
+        if ((ret = SetRsaInternal(rsa)) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetRsaInternal() Failed");
+            WOLFSSL_LEAVE("wolfSSL_RSA_To_Der", ret);
+            return ret;
+        }
+    }
+
+    if (publicKey) {
+        if ((derSz = wc_RsaPublicKeyDerSize((RsaKey *)rsa->internal, 1)) < 0) {
+            WOLFSSL_MSG("wc_RsaPublicKeyDerSize failed");
+            WOLFSSL_LEAVE("wolfSSL_RSA_To_Der", derSz);
+            return derSz;
+        }
+    }
+    else {
+        if ((derSz = wc_RsaKeyToDer((RsaKey*)rsa->internal, NULL, 0)) < 0) {
+            WOLFSSL_MSG("wc_RsaKeyToDer failed");
+            WOLFSSL_LEAVE("wolfSSL_RSA_To_Der", derSz);
+            return derSz;
+        }
+    }
+
+    if (outBuf) {
+        if (!(derBuf = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER))) {
+            WOLFSSL_MSG("malloc failed");
+            WOLFSSL_LEAVE("wolfSSL_RSA_To_Der", MEMORY_ERROR);
+            return MEMORY_ERROR;
+        }
+
+        /* Key to DER */
+        if (publicKey) {
+            derSz = wc_RsaKeyToPublicDer((RsaKey*)rsa->internal, derBuf, derSz);
+        }
+        else {
+            derSz = wc_RsaKeyToDer((RsaKey*)rsa->internal, derBuf, derSz);
+        }
+
+        if (derSz < 0) {
+            WOLFSSL_MSG("wc_RsaKeyToPublicDer failed");
+            XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        }
+        else {
+            if (*outBuf) {
+                XMEMCPY(*outBuf, derBuf, derSz);
+                XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            }
+            else {
+                *outBuf = derBuf;
+            }
+        }
+    }
+
+    WOLFSSL_LEAVE("wolfSSL_RSA_To_Der", derSz);
+    return derSz;
+}
+#endif
+
+#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN)
+#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_RSA)
+
+/* Takes a WOLFSSL_RSA key and writes it out to a WOLFSSL_BIO
+ *
+ * bio    the WOLFSSL_BIO to write to
+ * key    the WOLFSSL_RSA key to write out
+ * cipher cipher used
+ * passwd password string if used
+ * len    length of password string
+ * cb     password callback to use
+ * arg    null terminated string for passphrase
+ */
+int wolfSSL_PEM_write_bio_RSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_RSA* key,
+                                        const WOLFSSL_EVP_CIPHER* cipher,
+                                        unsigned char* passwd, int len,
+                                        pem_password_cb* cb, void* arg)
+{
+    int ret;
+    WOLFSSL_EVP_PKEY* pkey;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_write_bio_RSAPrivateKey");
+
+    if (bio == NULL || key == NULL) {
+        WOLFSSL_MSG("Bad Function Arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap);
+    if (pkey == NULL) {
+        WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    pkey->type   = EVP_PKEY_RSA;
+    pkey->rsa    = key;
+    pkey->ownRsa = 0;
+#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+    /* similar to how wolfSSL_PEM_write_mem_RSAPrivateKey finds DER of key */
+    {
+        int derSz;
+        byte* derBuf = NULL;
+
+        if ((derSz = wolfSSL_RSA_To_Der(key, &derBuf, 0)) < 0) {
+            WOLFSSL_MSG("wolfSSL_RSA_To_Der failed");
+            return WOLFSSL_FAILURE;
+        }
+
+        pkey->pkey.ptr = (char*)XMALLOC(derSz, bio->heap,
+                DYNAMIC_TYPE_TMP_BUFFER);
+        if (pkey->pkey.ptr == NULL) {
+            WOLFSSL_MSG("key malloc failed");
+            XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            wolfSSL_EVP_PKEY_free(pkey);
+            return WOLFSSL_FAILURE;
+        }
+        pkey->pkey_sz = derSz;
+        XMEMCPY(pkey->pkey.ptr, derBuf, derSz);
+        XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+#endif
+
+    ret = wolfSSL_PEM_write_bio_PrivateKey(bio, pkey, cipher, passwd, len,
+                                        cb, arg);
+
+    wolfSSL_EVP_PKEY_free(pkey);
+
+    return ret;
+}
+
+#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+/* Takes an RSA public key and writes it out to a WOLFSSL_BIO
+ * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
+ */
+int wolfSSL_PEM_write_bio_RSA_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa)
+{
+    int ret = 0, derSz = 0;
+    byte *derBuf = NULL;
+    WOLFSSL_EVP_PKEY* pkey = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_write_bio_RSA_PUBKEY");
+
+    if (bio == NULL || rsa == NULL) {
+        WOLFSSL_MSG("Bad Function Arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* Initialize pkey structure */
+    pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap);
+    if (pkey == NULL) {
+        WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    pkey->type   = EVP_PKEY_RSA;
+    pkey->rsa    = rsa;
+    pkey->ownRsa = 0;
+
+    if ((derSz = wolfSSL_RSA_To_Der(rsa, &derBuf, 1)) < 0) {
+        WOLFSSL_MSG("wolfSSL_RSA_To_Der failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    pkey->pkey.ptr = (char*)XMALLOC(derSz, bio->heap,
+            DYNAMIC_TYPE_TMP_BUFFER);
+    if (pkey->pkey.ptr == NULL) {
+        WOLFSSL_MSG("key malloc failed");
+        XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        wolfSSL_EVP_PKEY_free(pkey);
+        return WOLFSSL_FAILURE;
+    }
+    pkey->pkey_sz = derSz;
+    XMEMCPY(pkey->pkey.ptr, derBuf, derSz);
+    XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    ret = wolfSSL_PEM_write_bio_PUBKEY(bio, pkey);
+    wolfSSL_EVP_PKEY_free(pkey);
+
+    return ret;
+}
+#endif
+
+
+/* Reads an RSA public key from a WOLFSSL_BIO into a WOLFSSL_RSA
+ * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
+ */
+WOLFSSL_RSA *wolfSSL_PEM_read_bio_RSA_PUBKEY(WOLFSSL_BIO* bio,WOLFSSL_RSA** rsa,
+                                                pem_password_cb* cb, void *pass)
+{
+    WOLFSSL_EVP_PKEY* pkey;
+    WOLFSSL_RSA* local;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_read_bio_RSA_PUBKEY");
+
+    pkey = wolfSSL_PEM_read_bio_PUBKEY(bio, NULL, cb, pass);
+    if (pkey == NULL) {
+        return NULL;
+    }
+
+    /* Since the WOLFSSL_RSA structure is being taken from WOLFSSL_EVP_PKEY the
+     * flag indicating that the WOLFSSL_RSA structure is owned should be FALSE
+     * to avoid having it free'd */
+    pkey->ownRsa = 0;
+    local = pkey->rsa;
+    if (rsa != NULL){
+        *rsa = local;
+    }
+
+    wolfSSL_EVP_PKEY_free(pkey);
+    return local;
+}
+
+#endif /* defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) && !defined(NO_RSA) */
+
+/* Takes a public key and writes it out to a WOLFSSL_BIO
+ * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
+ */
+int wolfSSL_PEM_write_bio_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key)
+{
+    byte* keyDer;
+    int pemSz;
+    int ret;
+    byte* tmp;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PUBKEY");
+
+    if (bio == NULL || key == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    keyDer = (byte*)key->pkey.ptr;
+
+    pemSz = wc_DerToPem(keyDer, key->pkey_sz, NULL, 0, PUBLICKEY_TYPE);
+    if (pemSz < 0) {
+        WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PUBKEY", pemSz);
+        return WOLFSSL_FAILURE;
+    }
+    tmp = (byte*)XMALLOC(pemSz, bio->heap, DYNAMIC_TYPE_OPENSSL);
+    if (tmp == NULL) {
+        return MEMORY_E;
+    }
+
+    ret = wc_DerToPemEx(keyDer, key->pkey_sz, tmp, pemSz,
+                        NULL, PUBLICKEY_TYPE);
+    if (ret < 0) {
+        WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PUBKEY", ret);
+        XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL);
+        return WOLFSSL_FAILURE;
+    }
+
+    ret = wolfSSL_BIO_write(bio, tmp, pemSz);
+    XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL);
+    if (ret != pemSz) {
+        WOLFSSL_MSG("Unable to write full PEM to BIO");
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* Takes a private key and writes it out to a WOLFSSL_BIO
+ * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
+ */
+int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key,
+                                        const WOLFSSL_EVP_CIPHER* cipher,
+                                        unsigned char* passwd, int len,
+                                        pem_password_cb* cb, void* arg)
+{
+    byte* keyDer;
+    int pemSz;
+    int type;
+    int ret;
+    byte* tmp;
+
+    (void)cipher;
+    (void)passwd;
+    (void)len;
+    (void)cb;
+    (void)arg;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PrivateKey");
+
+    if (bio == NULL || key == NULL) {
+        WOLFSSL_MSG("Bad Function Arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    keyDer = (byte*)key->pkey.ptr;
+
+    switch (key->type) {
+#ifndef NO_RSA
+        case EVP_PKEY_RSA:
+            type = PRIVATEKEY_TYPE;
+            break;
+#endif
+
+#ifndef NO_DSA
+        case EVP_PKEY_DSA:
+            type = DSA_PRIVATEKEY_TYPE;
+            break;
+#endif
+
+#ifdef HAVE_ECC
+        case EVP_PKEY_EC:
+            type = ECC_PRIVATEKEY_TYPE;
+            break;
+#endif
+
+#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
+        case EVP_PKEY_DH:
+            type = DH_PRIVATEKEY_TYPE;
+            break;
+#endif
+
+        default:
+            WOLFSSL_MSG("Unknown Key type!");
+            type = PRIVATEKEY_TYPE;
+    }
+
+    pemSz = wc_DerToPem(keyDer, key->pkey_sz, NULL, 0, type);
+    if (pemSz < 0) {
+        WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PrivateKey", pemSz);
+        return WOLFSSL_FAILURE;
+    }
+    tmp = (byte*)XMALLOC(pemSz, bio->heap, DYNAMIC_TYPE_OPENSSL);
+    if (tmp == NULL) {
+        return MEMORY_E;
+    }
+
+    ret = wc_DerToPemEx(keyDer, key->pkey_sz, tmp, pemSz,
+                                NULL, type);
+    if (ret < 0) {
+        WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PrivateKey", ret);
+        XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL);
+        return WOLFSSL_FAILURE;
+    }
+
+    ret = wolfSSL_BIO_write(bio, tmp, pemSz);
+    XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL);
+    if (ret != pemSz) {
+        WOLFSSL_MSG("Unable to write full PEM to BIO");
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) */
+
+#if (defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA)) && \
+    (defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM))
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_PEM_write_mem_RSAPrivateKey(RSA* rsa, const EVP_CIPHER* cipher,
+                                        unsigned char* passwd, int passwdSz,
+                                        unsigned char **pem, int *plen)
+{
+    byte *derBuf = NULL, *tmp, *cipherInfo = NULL;
+    int  derSz = 0;
+    const int type = PRIVATEKEY_TYPE;
+    const char* header = NULL;
+    const char* footer = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_write_mem_RSAPrivateKey");
+
+    if (pem == NULL || plen == NULL || rsa == NULL || rsa->internal == NULL) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (wc_PemGetHeaderFooter(type, &header, &footer) != 0)
+        return WOLFSSL_FAILURE;
+
+    if (rsa->inSet == 0) {
+        WOLFSSL_MSG("No RSA internal set, do it");
+
+        if (SetRsaInternal(rsa) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetRsaInternal failed");
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+    if ((derSz = wolfSSL_RSA_To_Der(rsa, &derBuf, 0)) < 0) {
+        WOLFSSL_MSG("wolfSSL_RSA_To_Der failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* encrypt DER buffer if required */
+    if (passwd != NULL && passwdSz > 0 && cipher != NULL) {
+        int ret;
+
+        ret = EncryptDerKey(derBuf, &derSz, cipher,
+                            passwd, passwdSz, &cipherInfo);
+        if (ret != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("EncryptDerKey failed");
+            XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+            return ret;
+        }
+
+        /* tmp buffer with a max size */
+        *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
+            (int)XSTRLEN(footer) + 1 + HEADER_ENCRYPTED_KEY_SIZE;
+    }
+    else {
+        /* tmp buffer with a max size */
+        *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
+            (int)XSTRLEN(footer) + 1;
+    }
+
+    tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_PEM);
+    if (tmp == NULL) {
+        WOLFSSL_MSG("malloc failed");
+        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+        if (cipherInfo != NULL)
+            XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* DER to PEM */
+    *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, type);
+    if (*plen <= 0) {
+        WOLFSSL_MSG("wc_DerToPemEx failed");
+        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+        if (cipherInfo != NULL)
+            XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+        return WOLFSSL_FAILURE;
+    }
+    XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+    if (cipherInfo != NULL)
+        XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+
+    *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY);
+    if (*pem == NULL) {
+        WOLFSSL_MSG("malloc failed");
+        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+        return WOLFSSL_FAILURE;
+    }
+    XMEMSET(*pem, 0, (*plen)+1);
+
+    if (XMEMCPY(*pem, tmp, *plen) == NULL) {
+        WOLFSSL_MSG("XMEMCPY failed");
+        XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
+        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+        return WOLFSSL_FAILURE;
+    }
+    XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+#ifndef NO_FILESYSTEM
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_PEM_write_RSAPrivateKey(XFILE fp, WOLFSSL_RSA *rsa,
+                                    const EVP_CIPHER *enc,
+                                    unsigned char *kstr, int klen,
+                                    pem_password_cb *cb, void *u)
+{
+    byte *pem;
+    int  plen, ret;
+
+    (void)cb;
+    (void)u;
+
+    WOLFSSL_MSG("wolfSSL_PEM_write_RSAPrivateKey");
+
+    if (fp == XBADFILE || rsa == NULL || rsa->internal == NULL)
+    {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    ret = wolfSSL_PEM_write_mem_RSAPrivateKey(rsa, enc, kstr, klen, &pem, &plen);
+    if (ret != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("wolfSSL_PEM_write_mem_RSAPrivateKey failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    ret = (int)XFWRITE(pem, plen, 1, fp);
+    if (ret != 1) {
+        WOLFSSL_MSG("RSA private key file write failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
+    return WOLFSSL_SUCCESS;
+}
+#endif /* NO_FILESYSTEM */
+#endif /* WOLFSSL_KEY_GEN && !NO_RSA && !HAVE_USER_RSA && WOLFSSL_PEM_TO_DER */
+
+
+#ifdef HAVE_ECC
+
+#ifdef ALT_ECC_SIZE
+static int SetIndividualInternalEcc(WOLFSSL_BIGNUM* bn, mp_int* mpi)
+{
+    WOLFSSL_MSG("Entering SetIndividualInternal");
+
+    if (bn == NULL || bn->internal == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (mpi == NULL) {
+        WOLFSSL_MSG("mpi NULL error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (mp_copy((mp_int*)bn->internal, mpi) != MP_OKAY) {
+        WOLFSSL_MSG("mp_copy error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* ALT_ECC_SIZE */
+
+/* EC_POINT Openssl -> WolfSSL */
+static int SetECPointInternal(WOLFSSL_EC_POINT *p)
+{
+    ecc_point* point;
+    WOLFSSL_ENTER("SetECPointInternal");
+
+    if (p == NULL || p->internal == NULL) {
+        WOLFSSL_MSG("ECPoint NULL error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    point = (ecc_point*)p->internal;
+
+#ifndef ALT_ECC_SIZE
+    if (p->X != NULL && SetIndividualInternal(p->X, point->x) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("ecc point X error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (p->Y != NULL && SetIndividualInternal(p->Y, point->y) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("ecc point Y error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (p->Z != NULL && SetIndividualInternal(p->Z, point->z) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("ecc point Z error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+#else
+    if (p->X != NULL && SetIndividualInternalEcc(p->X, point->x) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("ecc point X error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (p->Y != NULL && SetIndividualInternalEcc(p->Y, point->y) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("ecc point Y error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (p->Z != NULL && SetIndividualInternalEcc(p->Z, point->z) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("ecc point Z error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+#endif
+
+    p->inSet = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* EC_POINT WolfSSL -> OpenSSL */
+static int SetECPointExternal(WOLFSSL_EC_POINT *p)
+{
+    ecc_point* point;
+
+    WOLFSSL_ENTER("SetECPointExternal");
+
+    if (p == NULL || p->internal == NULL) {
+        WOLFSSL_MSG("ECPoint NULL error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    point = (ecc_point*)p->internal;
+
+    if (SetIndividualExternal(&p->X, point->x) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("ecc point X error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (SetIndividualExternal(&p->Y, point->y) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("ecc point Y error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (SetIndividualExternal(&p->Z, point->z) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("ecc point Z error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    p->exSet = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* EC_KEY wolfSSL -> OpenSSL */
+int SetECKeyExternal(WOLFSSL_EC_KEY* eckey)
+{
+    ecc_key* key;
+
+    WOLFSSL_ENTER("SetECKeyExternal");
+
+    if (eckey == NULL || eckey->internal == NULL) {
+        WOLFSSL_MSG("ec key NULL error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    key = (ecc_key*)eckey->internal;
+
+    /* set group (OID, nid and idx) */
+    eckey->group->curve_oid = ecc_sets[key->idx].oidSum;
+    eckey->group->curve_nid = ecc_sets[key->idx].id;
+    eckey->group->curve_idx = key->idx;
+
+    if (eckey->pub_key->internal != NULL) {
+        /* set the internal public key */
+        if (wc_ecc_copy_point(&key->pubkey,
+                             (ecc_point*)eckey->pub_key->internal) != MP_OKAY) {
+            WOLFSSL_MSG("SetECKeyExternal ecc_copy_point failed");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        /* set the external pubkey (point) */
+        if (SetECPointExternal(eckey->pub_key) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetECKeyExternal SetECPointExternal failed");
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+
+    /* set the external privkey */
+    if (key->type == ECC_PRIVATEKEY) {
+        if (SetIndividualExternal(&eckey->priv_key, &key->k) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("ec priv key error");
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+
+    eckey->exSet = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* EC_KEY Openssl -> WolfSSL */
+int SetECKeyInternal(WOLFSSL_EC_KEY* eckey)
+{
+    ecc_key* key;
+
+    WOLFSSL_ENTER("SetECKeyInternal");
+
+    if (eckey == NULL || eckey->internal == NULL || eckey->group == NULL) {
+        WOLFSSL_MSG("ec key NULL error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    key = (ecc_key*)eckey->internal;
+
+    /* validate group */
+    if ((eckey->group->curve_idx < 0) ||
+        (wc_ecc_is_valid_idx(eckey->group->curve_idx) == 0)) {
+        WOLFSSL_MSG("invalid curve idx");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    /* set group (idx of curve and corresponding domain parameters) */
+    key->idx = eckey->group->curve_idx;
+    key->dp = &ecc_sets[key->idx];
+
+    /* set pubkey (point) */
+    if (eckey->pub_key != NULL) {
+        if (SetECPointInternal(eckey->pub_key) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("ec key pub error");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        /* copy over the public point to key */
+        if (wc_ecc_copy_point((ecc_point*)eckey->pub_key->internal, &key->pubkey) != MP_OKAY) {
+            WOLFSSL_MSG("wc_ecc_copy_point error");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        /* public key */
+        key->type = ECC_PUBLICKEY;
+    }
+
+    /* set privkey */
+    if (eckey->priv_key != NULL) {
+        if (SetIndividualInternal(eckey->priv_key, &key->k) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("ec key priv error");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        /* private key */
+        key->type = ECC_PRIVATEKEY;
+    }
+
+    eckey->inSet = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+WOLFSSL_EC_POINT *wolfSSL_EC_KEY_get0_public_key(const WOLFSSL_EC_KEY *key)
+{
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_public_key");
+
+    if (key == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_get0_public_key Bad arguments");
+        return NULL;
+    }
+
+    return key->pub_key;
+}
+
+const WOLFSSL_EC_GROUP *wolfSSL_EC_KEY_get0_group(const WOLFSSL_EC_KEY *key)
+{
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_group");
+
+    if (key == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_get0_group Bad arguments");
+        return NULL;
+    }
+
+    return key->group;
+}
+
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_EC_KEY_set_private_key(WOLFSSL_EC_KEY *key,
+                                   const WOLFSSL_BIGNUM *priv_key)
+{
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_set_private_key");
+
+    if (key == NULL || priv_key == NULL) {
+        WOLFSSL_MSG("Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* free key if previously set */
+    if (key->priv_key != NULL)
+        wolfSSL_BN_free(key->priv_key);
+
+    key->priv_key = wolfSSL_BN_dup(priv_key);
+    if (key->priv_key == NULL) {
+        WOLFSSL_MSG("key ecc priv key NULL");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("SetECKeyInternal failed");
+        wolfSSL_BN_free(key->priv_key);
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+WOLFSSL_BIGNUM *wolfSSL_EC_KEY_get0_private_key(const WOLFSSL_EC_KEY *key)
+{
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_private_key");
+
+    if (key == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_get0_private_key Bad arguments");
+        return NULL;
+    }
+
+    if (wolfSSL_BN_is_zero(key->priv_key)) {
+        /* return NULL if not set */
+        return NULL;
+    }
+
+    return key->priv_key;
+}
+
+WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_by_curve_name(int nid)
+{
+    WOLFSSL_EC_KEY *key;
+    int x;
+    int eccEnum;
+
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_new_by_curve_name");
+
+    /* If NID passed in is OpenSSL type, convert it to ecc_curve_id enum */
+    eccEnum = NIDToEccEnum(nid);
+    if (eccEnum == -1)
+        eccEnum = nid;
+
+    key = wolfSSL_EC_KEY_new();
+    if (key == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_new failure");
+        return NULL;
+    }
+
+    /* set the nid of the curve */
+    key->group->curve_nid = eccEnum;
+
+    /* search and set the corresponding internal curve idx */
+    for (x = 0; ecc_sets[x].size != 0; x++)
+        if (ecc_sets[x].id == key->group->curve_nid) {
+            key->group->curve_idx = x;
+            key->group->curve_oid = ecc_sets[x].oidSum;
+            break;
+        }
+
+    return key;
+}
+
+const char* wolfSSL_EC_curve_nid2nist(int nid)
+{
+    const WOLF_EC_NIST_NAME* nist_name;
+    for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) {
+        if (nist_name->nid == nid) {
+            return kNistCurves->name;
+        }
+    }
+    return NULL;
+}
+
+#ifdef WOLFSSL_TLS13
+static int populate_groups(int* groups, int max_count, char *list)
+{
+    char *end;
+    int len;
+    int count = 0;
+    const WOLF_EC_NIST_NAME* nist_name;
+
+    if (!groups || !list) {
+        return -1;
+    }
+
+    for (end = list; ; list = ++end) {
+        if (count > max_count) {
+            WOLFSSL_MSG("Too many curves in list");
+            return -1;
+        }
+        while (*end != ':' && *end != '\0') end++;
+        len = (int)(end - list); /* end points to char after end
+                                  * of curve name so no need for -1 */
+        if ((len < kNistCurves_MIN_NAME_LEN) ||
+                (len > kNistCurves_MAX_NAME_LEN)) {
+            WOLFSSL_MSG("Unrecognized curve name in list");
+            return -1;
+        }
+        for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) {
+            if (len == nist_name->name_len &&
+                    XSTRNCMP(list, nist_name->name, nist_name->name_len) == 0) {
+                break;
+            }
+        }
+        if (!nist_name->name) {
+            WOLFSSL_MSG("Unrecognized curve name in list");
+            return -1;
+        }
+        groups[count++] = nist_name->nid;
+        if (*end == '\0') break;
+    }
+
+    return count;
+}
+
+int wolfSSL_CTX_set1_groups_list(WOLFSSL_CTX *ctx, char *list)
+{
+    int groups[WOLFSSL_MAX_GROUP_COUNT];
+    int count;
+
+    if (!ctx || !list) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if ((count = populate_groups(groups,
+            WOLFSSL_MAX_GROUP_COUNT, list)) == -1) {
+        return WOLFSSL_FAILURE;
+    }
+
+    return wolfSSL_CTX_set_groups(ctx, groups, count) == WOLFSSL_SUCCESS ?
+            WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
+}
+
+int wolfSSL_set1_groups_list(WOLFSSL *ssl, char *list)
+{
+    int groups[WOLFSSL_MAX_GROUP_COUNT];
+    int count;
+
+    if (!ssl || !list) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if ((count = populate_groups(groups,
+            WOLFSSL_MAX_GROUP_COUNT, list)) == -1) {
+        return WOLFSSL_FAILURE;
+    }
+
+    return wolfSSL_set_groups(ssl, groups, count) == WOLFSSL_SUCCESS ?
+            WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
+}
+#endif /* WOLFSSL_TLS13 */
+
+static void InitwolfSSL_ECKey(WOLFSSL_EC_KEY* key)
+{
+    if (key) {
+        key->group    = NULL;
+        key->pub_key  = NULL;
+        key->priv_key = NULL;
+        key->internal = NULL;
+        key->inSet    = 0;
+        key->exSet    = 0;
+    }
+}
+
+WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new(void)
+{
+    WOLFSSL_EC_KEY *external;
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_new");
+
+    external = (WOLFSSL_EC_KEY*)XMALLOC(sizeof(WOLFSSL_EC_KEY), NULL,
+                                        DYNAMIC_TYPE_ECC);
+    if (external == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_KEY failure");
+        return NULL;
+    }
+    XMEMSET(external, 0, sizeof(WOLFSSL_EC_KEY));
+
+    InitwolfSSL_ECKey(external);
+
+    external->internal = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL,
+                                           DYNAMIC_TYPE_ECC);
+    if (external->internal == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc ecc key failure");
+        goto error;
+    }
+    XMEMSET(external->internal, 0, sizeof(ecc_key));
+
+    if (wc_ecc_init((ecc_key*)external->internal) != 0) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_new init ecc key failure");
+        goto error;
+    }
+
+    /* curve group */
+    external->group = wolfSSL_EC_GROUP_new_by_curve_name(ECC_CURVE_DEF);
+    if (external->group == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_GROUP failure");
+        goto error;
+    }
+
+    /* public key */
+    external->pub_key = wolfSSL_EC_POINT_new(external->group);
+    if (external->pub_key == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_POINT_new failure");
+        goto error;
+    }
+
+    /* private key */
+    external->priv_key = wolfSSL_BN_new();
+    if (external->priv_key == NULL) {
+        WOLFSSL_MSG("wolfSSL_BN_new failure");
+        goto error;
+    }
+
+    return external;
+error:
+    wolfSSL_EC_KEY_free(external);
+    return NULL;
+}
+
+void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key)
+{
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_free");
+
+    if (key != NULL) {
+        if (key->internal != NULL) {
+            wc_ecc_free((ecc_key*)key->internal);
+            XFREE(key->internal, NULL, DYNAMIC_TYPE_ECC);
+        }
+        wolfSSL_BN_free(key->priv_key);
+        wolfSSL_EC_POINT_free(key->pub_key);
+        wolfSSL_EC_GROUP_free(key->group);
+        InitwolfSSL_ECKey(key); /* set back to NULLs for safety */
+
+        XFREE(key, NULL, DYNAMIC_TYPE_ECC);
+        /* key = NULL, don't try to access or double free it */
+    }
+}
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_EC_KEY_set_group(WOLFSSL_EC_KEY *key, WOLFSSL_EC_GROUP *group)
+{
+    (void)key;
+    (void)group;
+
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_set_group");
+    WOLFSSL_STUB("EC_KEY_set_group");
+
+    return -1;
+}
+#endif
+
+int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key)
+{
+    int     initTmpRng = 0;
+    WC_RNG* rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG* tmpRNG = NULL;
+#else
+    WC_RNG  tmpRNG[1];
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_generate_key");
+
+    if (key == NULL || key->internal == NULL ||
+        key->group == NULL || key->group->curve_idx < 0) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key Bad arguments");
+        return 0;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+    if (tmpRNG == NULL)
+        return 0;
+#endif
+
+    if (wc_InitRng(tmpRNG) == 0) {
+        rng = tmpRNG;
+        initTmpRng = 1;
+    }
+    else {
+        WOLFSSL_MSG("Bad RNG Init, trying global");
+        if (initGlobalRNG == 0)
+            WOLFSSL_MSG("Global RNG no Init");
+        else
+            rng = &globalRNG;
+    }
+
+    if (rng == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key failed to set RNG");
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+        return 0;
+    }
+
+    if (wc_ecc_make_key_ex(rng, 0, (ecc_key*)key->internal,
+                                        key->group->curve_nid) != MP_OKAY) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key wc_ecc_make_key failed");
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+        return 0;
+    }
+
+    if (initTmpRng)
+        wc_FreeRng(tmpRNG);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+    if (SetECKeyExternal(key) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key SetECKeyExternal failed");
+        return 0;
+    }
+
+    return 1;
+}
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_EC_KEY_set_asn1_flag(WOLFSSL_EC_KEY *key, int asn1_flag)
+{
+    (void)key;
+    (void)asn1_flag;
+
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_set_asn1_flag");
+    WOLFSSL_STUB("EC_KEY_set_asn1_flag");
+}
+#endif
+
+static int setupPoint(const WOLFSSL_EC_POINT *p) {
+    if (!p) {
+        return WOLFSSL_FAILURE;
+    }
+    if (p->inSet == 0) {
+        WOLFSSL_MSG("No ECPoint internal set, do it");
+
+        if (SetECPointInternal((WOLFSSL_EC_POINT *)p) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetECPointInternal SetECPointInternal failed");
+            return WOLFSSL_FAILURE;
+        }
+    }
+    return WOLFSSL_SUCCESS;
+}
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_EC_KEY_set_public_key(WOLFSSL_EC_KEY *key,
+                                  const WOLFSSL_EC_POINT *pub)
+{
+    ecc_point *pub_p, *key_p;
+
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_set_public_key");
+
+    if (key == NULL || key->internal == NULL ||
+        pub == NULL || pub->internal == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (key->inSet == 0) {
+        if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetECKeyInternal failed");
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+    if (setupPoint(pub) != WOLFSSL_SUCCESS) {
+        return WOLFSSL_FAILURE;
+    }
+
+    pub_p = (ecc_point*)pub->internal;
+    key_p = (ecc_point*)key->pub_key->internal;
+
+    /* create new point if required */
+    if (key_p == NULL)
+        key_p = wc_ecc_new_point();
+
+    if (key_p == NULL) {
+        WOLFSSL_MSG("key ecc point NULL");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (wc_ecc_copy_point(pub_p, key_p) != MP_OKAY) {
+        WOLFSSL_MSG("ecc_copy_point failure");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (SetECPointExternal(key->pub_key) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("SetECKeyInternal failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("SetECKeyInternal failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    wolfSSL_EC_POINT_dump("pub", pub);
+    wolfSSL_EC_POINT_dump("key->pub_key", key->pub_key);
+
+    return WOLFSSL_SUCCESS;
+}
+/* End EC_KEY */
+
+int wolfSSL_ECDSA_size(const WOLFSSL_EC_KEY *key)
+{
+    const EC_GROUP *group;
+    int bits, bytes;
+    word32 headerSz = 4;   /* 2*ASN_TAG + 2*LEN(ENUM) */
+
+    if (!key) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if (!(group = wolfSSL_EC_KEY_get0_group(key))) {
+        return WOLFSSL_FAILURE;
+    }
+    if ((bits = wolfSSL_EC_GROUP_order_bits(group)) == 0) {
+        return WOLFSSL_FAILURE;
+    }
+    bytes = (bits + 7) / 8; /* bytes needed to hold bits */
+    return headerSz +
+            2 + /* possible leading zeroes in r and s */
+            bytes + bytes + /* r and s */
+            2;
+}
+
+int wolfSSL_ECDSA_sign(int type, const unsigned char *digest,
+                       int digestSz, unsigned char *sig,
+                       unsigned int *sigSz, WOLFSSL_EC_KEY *key)
+{
+    int ret = WOLFSSL_SUCCESS;
+    WC_RNG* rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG* tmpRNG = NULL;
+#else
+    WC_RNG  tmpRNG[1];
+#endif
+    int initTmpRng = 0;
+
+    WOLFSSL_ENTER("wolfSSL_ECDSA_sign");
+
+    if (!key) {
+        return WOLFSSL_FAILURE;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+    if (tmpRNG == NULL)
+        return WOLFSSL_FAILURE;
+#endif
+
+    if (wc_InitRng(tmpRNG) == 0) {
+        rng = tmpRNG;
+        initTmpRng = 1;
+    }
+    else {
+        WOLFSSL_MSG("Bad RNG Init, trying global");
+        if (initGlobalRNG == 0) {
+            WOLFSSL_MSG("Global RNG no Init");
+        }
+        else {
+            rng = &globalRNG;
+        }
+    }
+    if (rng) {
+        if (wc_ecc_sign_hash(digest, digestSz, sig, sigSz, rng, (ecc_key*)key->internal) != MP_OKAY) {
+            ret = WOLFSSL_FAILURE;
+        }
+        if (initTmpRng) {
+            wc_FreeRng(tmpRNG);
+        }
+    } else {
+        ret = WOLFSSL_FAILURE;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    if (tmpRNG)
+        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+    (void)type;
+    return ret;
+}
+
+#ifndef HAVE_SELFTEST
+/* ECC point compression types were not included in selftest ecc.h */
+
+char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group,
+                                 const WOLFSSL_EC_POINT* point, int form,
+                                 WOLFSSL_BN_CTX* ctx)
+{
+    static const char* hexDigit = "0123456789ABCDEF";
+    char* hex = NULL;
+    int id;
+    int i, sz, len;
+
+    (void)ctx;
+
+    if (group == NULL || point == NULL)
+        return NULL;
+
+    id = wc_ecc_get_curve_id(group->curve_idx);
+
+    if ((sz = wc_ecc_get_curve_size_from_id(id)) < 0)
+        return NULL;
+
+    len = sz + 1;
+    if (form == POINT_CONVERSION_UNCOMPRESSED)
+        len += sz;
+
+    hex = (char*)XMALLOC(2 * len + 1, NULL, DYNAMIC_TYPE_ECC);
+    if (hex == NULL)
+        return NULL;
+    XMEMSET(hex, 0, 2 * len + 1);
+
+    /* Put in x-ordinate after format byte. */
+    i = sz - mp_unsigned_bin_size((mp_int*)point->X->internal) + 1;
+    if (mp_to_unsigned_bin((mp_int*)point->X->internal, (byte*)(hex + i)) < 0) {
+        XFREE(hex,  NULL, DYNAMIC_TYPE_ECC);
+        return NULL;
+    }
+
+    if (form == POINT_CONVERSION_COMPRESSED) {
+        hex[0] = mp_isodd((mp_int*)point->Y->internal) ? ECC_POINT_COMP_ODD :
+                                                         ECC_POINT_COMP_EVEN;
+    }
+    else {
+        hex[0] = ECC_POINT_UNCOMP;
+        /* Put in y-ordinate after x-ordinate */
+        i = 1 + 2 * sz - mp_unsigned_bin_size((mp_int*)point->Y->internal);
+        if (mp_to_unsigned_bin((mp_int*)point->Y->internal,
+                                                        (byte*)(hex + i)) < 0) {
+            XFREE(hex,  NULL, DYNAMIC_TYPE_ECC);
+            return NULL;
+        }
+    }
+
+    for (i = len-1; i >= 0; i--) {
+        byte b = hex[i];
+        hex[i * 2 + 1] = hexDigit[b  & 0xf];
+        hex[i * 2    ] = hexDigit[b >>   4];
+    }
+
+    return hex;
+}
+
+#endif /* HAVE_SELFTEST */
+
+void wolfSSL_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *p)
+{
+#if defined(DEBUG_WOLFSSL)
+    char *num;
+
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_dump");
+
+    if (!WOLFSSL_IS_DEBUG_ON() || wolfSSL_GetLoggingCb()) {
+        return;
+    }
+
+    if (p == NULL) {
+        printf("%s = NULL", msg);
+        return;
+    }
+
+    printf("%s:\n\tinSet=%d, exSet=%d\n", msg, p->inSet, p->exSet);
+    num = wolfSSL_BN_bn2hex(p->X);
+    printf("\tX = %s\n", num);
+    XFREE(num, NULL, DYNAMIC_TYPE_ECC);
+    num = wolfSSL_BN_bn2hex(p->Y);
+    printf("\tY = %s\n", num);
+    XFREE(num, NULL, DYNAMIC_TYPE_ECC);
+    num = wolfSSL_BN_bn2hex(p->Z);
+    printf("\tZ = %s\n", num);
+    XFREE(num, NULL, DYNAMIC_TYPE_ECC);
+#else
+    (void)msg;
+    (void)p;
+#endif
+}
+
+/* Start EC_GROUP */
+
+/* return code compliant with OpenSSL :
+ *   0 if equal, 1 if not and -1 in case of error
+ */
+int wolfSSL_EC_GROUP_cmp(const WOLFSSL_EC_GROUP *a, const WOLFSSL_EC_GROUP *b,
+                         WOLFSSL_BN_CTX *ctx)
+{
+    (void)ctx;
+
+    WOLFSSL_ENTER("wolfSSL_EC_GROUP_cmp");
+
+    if (a == NULL || b == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_GROUP_cmp Bad arguments");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    /* ok */
+    if ((a->curve_idx == b->curve_idx) && (a->curve_nid == b->curve_nid))
+        return 0;
+
+    /* ko */
+    return 1;
+}
+
+#endif /* HAVE_ECC */
+#endif /* OPENSSL_EXTRA */
+
+#if defined(HAVE_ECC) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
+const WOLFSSL_EC_METHOD* wolfSSL_EC_GROUP_method_of(
+                                                const WOLFSSL_EC_GROUP *group)
+{
+    return group;
+}
+
+int wolfSSL_EC_METHOD_get_field_type(const WOLFSSL_EC_METHOD *meth)
+{
+    if (meth) {
+        return NID_X9_62_prime_field;
+    }
+    return WOLFSSL_FAILURE;
+}
+
+void wolfSSL_EC_GROUP_free(WOLFSSL_EC_GROUP *group)
+{
+    WOLFSSL_ENTER("wolfSSL_EC_GROUP_free");
+
+    XFREE(group, NULL, DYNAMIC_TYPE_ECC);
+    /* group = NULL, don't try to access or double free it */
+}
+#endif
+
+#ifdef OPENSSL_EXTRA
+#ifdef HAVE_ECC
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_EC_GROUP_set_asn1_flag(WOLFSSL_EC_GROUP *group, int flag)
+{
+    (void)group;
+    (void)flag;
+
+    WOLFSSL_ENTER("wolfSSL_EC_GROUP_set_asn1_flag");
+    WOLFSSL_STUB("EC_GROUP_set_asn1_flag");
+}
+#endif
+
+WOLFSSL_EC_GROUP *wolfSSL_EC_GROUP_new_by_curve_name(int nid)
+{
+    WOLFSSL_EC_GROUP *g;
+    int x;
+    int eccEnum;
+
+    WOLFSSL_ENTER("wolfSSL_EC_GROUP_new_by_curve_name");
+
+    /* If NID passed in is OpenSSL type, convert it to ecc_curve_id enum */
+    eccEnum = NIDToEccEnum(nid);
+    if (eccEnum == -1)
+        eccEnum = nid;
+
+
+    /* curve group */
+    g = (WOLFSSL_EC_GROUP*) XMALLOC(sizeof(WOLFSSL_EC_GROUP), NULL,
+                                    DYNAMIC_TYPE_ECC);
+    if (g == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_GROUP_new_by_curve_name malloc failure");
+        return NULL;
+    }
+    XMEMSET(g, 0, sizeof(WOLFSSL_EC_GROUP));
+
+    /* set the nid of the curve */
+    g->curve_nid = eccEnum;
+
+    if (eccEnum > ECC_CURVE_DEF) {
+        /* search and set the corresponding internal curve idx */
+        for (x = 0; ecc_sets[x].size != 0; x++)
+            if (ecc_sets[x].id == g->curve_nid) {
+                g->curve_idx = x;
+                g->curve_oid = ecc_sets[x].oidSum;
+                break;
+            }
+    }
+
+    return g;
+}
+
+/* return code compliant with OpenSSL :
+ *   the curve nid if success, 0 if error
+ */
+int wolfSSL_EC_GROUP_get_curve_name(const WOLFSSL_EC_GROUP *group)
+{
+    int nid;
+    WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_curve_name");
+
+    if (group == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_curve_name Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* If curve_nid is ECC Enum type, return corresponding OpenSSL nid */
+    if ((nid = EccEnumToNID(group->curve_nid)) != -1)
+        return nid;
+
+    return group->curve_nid;
+}
+
+/* return code compliant with OpenSSL :
+ *   the degree of the curve if success, 0 if error
+ */
+int wolfSSL_EC_GROUP_get_degree(const WOLFSSL_EC_GROUP *group)
+{
+    int nid;
+    int tmp;
+
+    WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_degree");
+
+    if (group == NULL || group->curve_idx < 0) {
+        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_degree Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* If curve_nid passed in is an ecc_curve_id enum, convert it to the
+        corresponding OpenSSL NID */
+    tmp = EccEnumToNID(group->curve_nid);
+    if (tmp != -1){
+        nid = tmp;
+    }
+    else{
+        nid = group->curve_nid;
+    }
+
+    switch(nid) {
+        case NID_secp112r1:
+        case NID_secp112r2:
+            return 112;
+        case NID_secp128r1:
+        case NID_secp128r2:
+            return 128;
+        case NID_secp160k1:
+        case NID_secp160r1:
+        case NID_secp160r2:
+        case NID_brainpoolP160r1:
+            return 160;
+        case NID_secp192k1:
+        case NID_brainpoolP192r1:
+        case NID_X9_62_prime192v1:
+            return 192;
+        case NID_secp224k1:
+        case NID_secp224r1:
+        case NID_brainpoolP224r1:
+            return 224;
+        case NID_secp256k1:
+        case NID_brainpoolP256r1:
+        case NID_X9_62_prime256v1:
+            return 256;
+        case NID_brainpoolP320r1:
+            return 320;
+        case NID_secp384r1:
+        case NID_brainpoolP384r1:
+            return 384;
+        case NID_secp521r1:
+            return 521;
+        case NID_brainpoolP512r1:
+            return 512;
+        default:
+            return WOLFSSL_FAILURE;
+    }
+}
+
+/* Converts OpenSSL NID value of ECC curves to the associated enum values in
+   ecc_curve_id, used by ecc_sets[].*/
+int NIDToEccEnum(int n)
+{
+    WOLFSSL_ENTER("NIDToEccEnum()");
+
+    switch(n) {
+        case NID_X9_62_prime192v1:
+            return ECC_SECP192R1;
+        case NID_X9_62_prime192v2:
+            return ECC_PRIME192V2;
+        case NID_X9_62_prime192v3:
+            return ECC_PRIME192V3;
+        case NID_X9_62_prime239v1:
+            return ECC_PRIME239V1;
+        case NID_X9_62_prime239v2:
+            return ECC_PRIME239V2;
+        case NID_X9_62_prime239v3:
+            return ECC_PRIME239V3;
+        case NID_X9_62_prime256v1:
+            return ECC_SECP256R1;
+        case NID_secp112r1:
+            return ECC_SECP112R1;
+        case NID_secp112r2:
+            return ECC_SECP112R2;
+        case NID_secp128r1:
+            return ECC_SECP128R1;
+        case NID_secp128r2:
+            return ECC_SECP128R2;
+        case NID_secp160r1:
+            return ECC_SECP160R1;
+        case NID_secp160r2:
+            return ECC_SECP160R2;
+        case NID_secp224r1:
+            return ECC_SECP224R1;
+        case NID_secp384r1:
+            return ECC_SECP384R1;
+        case NID_secp521r1:
+            return ECC_SECP521R1;
+        case NID_secp160k1:
+            return ECC_SECP160K1;
+        case NID_secp192k1:
+            return ECC_SECP192K1;
+        case NID_secp224k1:
+            return ECC_SECP224K1;
+        case NID_secp256k1:
+            return ECC_SECP256K1;
+        case NID_brainpoolP160r1:
+            return ECC_BRAINPOOLP160R1;
+        case NID_brainpoolP192r1:
+            return ECC_BRAINPOOLP192R1;
+        case NID_brainpoolP224r1:
+            return ECC_BRAINPOOLP224R1;
+        case NID_brainpoolP256r1:
+            return ECC_BRAINPOOLP256R1;
+        case NID_brainpoolP320r1:
+            return ECC_BRAINPOOLP320R1;
+        case NID_brainpoolP384r1:
+            return ECC_BRAINPOOLP384R1;
+        case NID_brainpoolP512r1:
+            return ECC_BRAINPOOLP512R1;
+        default:
+            WOLFSSL_MSG("NID not found");
+            return -1;
+    }
+}
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_EC_GROUP_get_order(const WOLFSSL_EC_GROUP *group,
+                               WOLFSSL_BIGNUM *order, WOLFSSL_BN_CTX *ctx)
+{
+    (void)ctx;
+
+    if (group == NULL || order == NULL || order->internal == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (mp_init((mp_int*)order->internal) != MP_OKAY) {
+        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_init failure");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (mp_read_radix((mp_int*)order->internal,
+                  ecc_sets[group->curve_idx].order, MP_RADIX_HEX) != MP_OKAY) {
+        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_read order failure");
+        mp_clear((mp_int*)order->internal);
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_EC_GROUP_order_bits(const WOLFSSL_EC_GROUP *group)
+{
+    int ret;
+    mp_int order;
+
+    if (group == NULL || group->curve_idx < 0) {
+        WOLFSSL_MSG("wolfSSL_EC_GROUP_order_bits NULL error");
+        return 0;
+    }
+
+    ret = mp_init(&order);
+    if (ret == 0) {
+        ret = mp_read_radix(&order, ecc_sets[group->curve_idx].order,
+            MP_RADIX_HEX);
+        if (ret == 0)
+            ret = mp_count_bits(&order);
+        mp_clear(&order);
+    }
+
+    return ret;
+}
+
+/* End EC_GROUP */
+
+/* Start EC_POINT */
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_ECPoint_i2d(const WOLFSSL_EC_GROUP *group,
+                        const WOLFSSL_EC_POINT *p,
+                        unsigned char *out, unsigned int *len)
+{
+    int err;
+
+    WOLFSSL_ENTER("wolfSSL_ECPoint_i2d");
+
+    if (group == NULL || p == NULL || len == NULL) {
+        WOLFSSL_MSG("wolfSSL_ECPoint_i2d NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (setupPoint(p) != WOLFSSL_SUCCESS) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if (out != NULL) {
+        wolfSSL_EC_POINT_dump("i2d p", p);
+    }
+
+    err = wc_ecc_export_point_der(group->curve_idx, (ecc_point*)p->internal,
+                                  out, len);
+    if (err != MP_OKAY && !(out == NULL && err == LENGTH_ONLY_E)) {
+        WOLFSSL_MSG("wolfSSL_ECPoint_i2d wc_ecc_export_point_der failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_ECPoint_d2i(unsigned char *in, unsigned int len,
+                        const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *p)
+{
+    WOLFSSL_ENTER("wolfSSL_ECPoint_d2i");
+
+    if (group == NULL || p == NULL || p->internal == NULL || in == NULL) {
+        WOLFSSL_MSG("wolfSSL_ECPoint_d2i NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+#ifndef HAVE_SELFTEST
+    if (wc_ecc_import_point_der_ex(in, len, group->curve_idx,
+                                   (ecc_point*)p->internal, 0) != MP_OKAY) {
+        WOLFSSL_MSG("wc_ecc_import_point_der_ex failed");
+        return WOLFSSL_FAILURE;
+    }
+#else
+    /* ECC_POINT_UNCOMP is not defined CAVP self test so use magic number */
+    if (in[0] == 0x04) {
+        if (wc_ecc_import_point_der(in, len, group->curve_idx,
+                                    (ecc_point*)p->internal) != MP_OKAY) {
+            WOLFSSL_MSG("wc_ecc_import_point_der failed");
+            return WOLFSSL_FAILURE;
+        }
+    }
+    else {
+        WOLFSSL_MSG("Only uncompressed points supported with HAVE_SELFTEST");
+        return WOLFSSL_FAILURE;
+    }
+#endif
+
+    /* Set new external point */
+    if (SetECPointExternal(p) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("SetECPointExternal failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    wolfSSL_EC_POINT_dump("d2i p", p);
+
+    return WOLFSSL_SUCCESS;
+}
+
+size_t wolfSSL_EC_POINT_point2oct(const WOLFSSL_EC_GROUP *group,
+                                  const WOLFSSL_EC_POINT *p,
+                                  char form,
+                                  byte *buf, size_t len, WOLFSSL_BN_CTX *ctx)
+{
+    word32 min_len = (word32)len;
+#ifndef HAVE_SELFTEST
+    int compressed = form == POINT_CONVERSION_COMPRESSED ? 1 : 0;
+#endif /* !HAVE_SELFTEST */
+
+    WOLFSSL_ENTER("EC_POINT_point2oct");
+
+    if (!group || !p) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if (setupPoint(p) != WOLFSSL_SUCCESS) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if (wolfSSL_EC_POINT_is_at_infinity(group, p)) {
+        /* encodes to a single 0 octet */
+        if (buf != NULL) {
+            if (len < 1) {
+                ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
+                return WOLFSSL_FAILURE;
+            }
+            buf[0] = 0;
+        }
+        return 1;
+    }
+
+    if (form != POINT_CONVERSION_UNCOMPRESSED
+#ifndef HAVE_SELFTEST
+            && form != POINT_CONVERSION_COMPRESSED
+#endif /* !HAVE_SELFTEST */
+            ) {
+        WOLFSSL_MSG("Unsupported curve form");
+        return WOLFSSL_FAILURE;
+    }
+
+#ifndef HAVE_SELFTEST
+    if (wc_ecc_export_point_der_ex(group->curve_idx, (ecc_point*)p->internal,
+               buf, &min_len, compressed) != (buf ? MP_OKAY : LENGTH_ONLY_E)) {
+        return WOLFSSL_FAILURE;
+    }
+#else
+    if (wc_ecc_export_point_der(group->curve_idx, (ecc_point*)p->internal,
+                                buf, &min_len) != (buf ? MP_OKAY : LENGTH_ONLY_E)) {
+        return WOLFSSL_FAILURE;
+    }
+#endif /* !HAVE_SELFTEST */
+
+    (void)ctx;
+
+    return (size_t)min_len;
+}
+
+int wolfSSL_EC_POINT_oct2point(const WOLFSSL_EC_GROUP *group,
+                               WOLFSSL_EC_POINT *p, const unsigned char *buf,
+                               size_t len, WOLFSSL_BN_CTX *ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_oct2point");
+
+    if (!group || !p) {
+        return WOLFSSL_FAILURE;
+    }
+
+    (void)ctx;
+
+    return wolfSSL_ECPoint_d2i((unsigned char*)buf, (unsigned int)len, group, p);
+}
+
+int wolfSSL_i2o_ECPublicKey(const WOLFSSL_EC_KEY *in, unsigned char **out)
+{
+    size_t len;
+    unsigned char *tmp = NULL;
+    char form;
+    WOLFSSL_ENTER("wolfSSL_i2o_ECPublicKey");
+
+    if (!in) {
+        WOLFSSL_MSG("wolfSSL_i2o_ECPublicKey Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* Default to compressed form if not set */
+    form = in->form == POINT_CONVERSION_UNCOMPRESSED ?
+            POINT_CONVERSION_UNCOMPRESSED:
+            POINT_CONVERSION_COMPRESSED;
+
+    len = wolfSSL_EC_POINT_point2oct(in->group, in->pub_key, form,
+                                     NULL, 0, NULL);
+
+    if (len != WOLFSSL_FAILURE && out) {
+        if (!*out) {
+            if (!(tmp = (unsigned char*)XMALLOC(len, NULL,
+                                                DYNAMIC_TYPE_OPENSSL))) {
+                WOLFSSL_MSG("malloc failed");
+                return WOLFSSL_FAILURE;
+            }
+            *out = tmp;
+        }
+
+        if (wolfSSL_EC_POINT_point2oct(in->group, in->pub_key, form, *out,
+                                       len, NULL) == WOLFSSL_FAILURE) {
+            if (tmp) {
+                XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL);
+                *out = NULL;
+            }
+            return WOLFSSL_FAILURE;
+        }
+
+        if (!tmp) {
+            /* Move buffer forward if it was not alloced in this function */
+            *out += len;
+        }
+    }
+
+    return (int)len;
+}
+
+void wolfSSL_EC_KEY_set_conv_form(WOLFSSL_EC_KEY *eckey, char form)
+{
+    if (eckey && (form == POINT_CONVERSION_COMPRESSED ||
+                  form == POINT_CONVERSION_UNCOMPRESSED)) {
+        eckey->form = form;
+    }
+}
+
+
+/* wolfSSL_EC_POINT_point2bn should return "in" if not null */
+WOLFSSL_BIGNUM *wolfSSL_EC_POINT_point2bn(const WOLFSSL_EC_GROUP *group,
+                                          const WOLFSSL_EC_POINT *p,
+                                          char form,
+                                          WOLFSSL_BIGNUM *in, WOLFSSL_BN_CTX *ctx)
+{
+    size_t len;
+    byte *buf;
+    WOLFSSL_BIGNUM *ret = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_oct2point");
+
+    if (!group || !p) {
+        return NULL;
+    }
+
+    if ((len = wolfSSL_EC_POINT_point2oct(group, p, form,
+                                          NULL, 0, ctx)) == WOLFSSL_FAILURE) {
+        return NULL;
+    }
+
+    if (!(buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER))) {
+        WOLFSSL_MSG("malloc failed");
+        return NULL;
+    }
+
+    if (wolfSSL_EC_POINT_point2oct(group, p, form,
+                                   buf, len, ctx) == len) {
+        ret = wolfSSL_BN_bin2bn(buf, (int)len, in);
+    }
+
+    XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+    return ret;
+}
+
+WOLFSSL_EC_POINT *wolfSSL_EC_POINT_new(const WOLFSSL_EC_GROUP *group)
+{
+    WOLFSSL_EC_POINT *p;
+
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_new");
+
+    if (group == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_POINT_new NULL error");
+        return NULL;
+    }
+
+    p = (WOLFSSL_EC_POINT *)XMALLOC(sizeof(WOLFSSL_EC_POINT), NULL,
+                                    DYNAMIC_TYPE_ECC);
+    if (p == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_POINT_new malloc ecc point failure");
+        return NULL;
+    }
+    XMEMSET(p, 0, sizeof(WOLFSSL_EC_POINT));
+
+    p->internal = wc_ecc_new_point();
+    if (p->internal == NULL) {
+        WOLFSSL_MSG("ecc_new_point failure");
+        XFREE(p, NULL, DYNAMIC_TYPE_ECC);
+        return NULL;
+    }
+
+    return p;
+}
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_EC_POINT_get_affine_coordinates_GFp(const WOLFSSL_EC_GROUP *group,
+                                                const WOLFSSL_EC_POINT *point,
+                                                WOLFSSL_BIGNUM *x,
+                                                WOLFSSL_BIGNUM *y,
+                                                WOLFSSL_BN_CTX *ctx)
+{
+    mp_digit mp;
+    mp_int modulus;
+    (void)ctx;
+
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_get_affine_coordinates_GFp");
+
+    if (group == NULL || point == NULL || point->internal == NULL ||
+        x == NULL || y == NULL || wolfSSL_EC_POINT_is_at_infinity(group, point)) {
+        WOLFSSL_MSG("wolfSSL_EC_POINT_get_affine_coordinates_GFp NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (setupPoint(point) != WOLFSSL_SUCCESS) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if (!wolfSSL_BN_is_one(point->Z)) {
+        if (mp_init(&modulus) != MP_OKAY) {
+            WOLFSSL_MSG("mp_init failed");
+            return WOLFSSL_FAILURE;
+        }
+        /* Map the Jacobian point back to affine space */
+        if (mp_read_radix(&modulus, ecc_sets[group->curve_idx].prime, MP_RADIX_HEX) != MP_OKAY) {
+            WOLFSSL_MSG("mp_read_radix failed");
+            mp_clear(&modulus);
+            return WOLFSSL_FAILURE;
+        }
+        if (mp_montgomery_setup(&modulus, &mp) != MP_OKAY) {
+            WOLFSSL_MSG("mp_montgomery_setup failed");
+            mp_clear(&modulus);
+            return WOLFSSL_FAILURE;
+        }
+        if (ecc_map((ecc_point*)point->internal, &modulus, mp) != MP_OKAY) {
+            WOLFSSL_MSG("ecc_map failed");
+            mp_clear(&modulus);
+            return WOLFSSL_FAILURE;
+        }
+        if (SetECPointExternal((WOLFSSL_EC_POINT *)point) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetECPointExternal failed");
+            mp_clear(&modulus);
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+    BN_copy(x, point->X);
+    BN_copy(y, point->Y);
+    mp_clear(&modulus);
+
+    return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_EC_POINT_set_affine_coordinates_GFp(const WOLFSSL_EC_GROUP *group,
+                                                WOLFSSL_EC_POINT *point,
+                                                const WOLFSSL_BIGNUM *x,
+                                                const WOLFSSL_BIGNUM *y,
+                                                WOLFSSL_BN_CTX *ctx)
+{
+    (void)ctx;
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_set_affine_coordinates_GFp");
+
+    if (group == NULL || point == NULL || point->internal == NULL ||
+        x == NULL || y == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_POINT_set_affine_coordinates_GFp NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (!point->X) {
+        point->X = wolfSSL_BN_new();
+    }
+    if (!point->Y) {
+        point->Y = wolfSSL_BN_new();
+    }
+    if (!point->Z) {
+        point->Z = wolfSSL_BN_new();
+    }
+    if (!point->X || !point->Y || !point->Z) {
+        WOLFSSL_MSG("wolfSSL_BN_new failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    BN_copy(point->X, x);
+    BN_copy(point->Y, y);
+    BN_copy(point->Z, wolfSSL_BN_value_one());
+
+    if (SetECPointInternal((WOLFSSL_EC_POINT *)point) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("SetECPointInternal failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+#if !defined(WOLFSSL_ATECC508A) && !defined(HAVE_SELFTEST)
+/* Calculate the value: generator * n + q * m
+ * return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_EC_POINT_mul(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r,
+                         const WOLFSSL_BIGNUM *n, const WOLFSSL_EC_POINT *q,
+                         const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx)
+{
+    mp_int a, prime;
+    int ret = WOLFSSL_FAILURE;
+    ecc_point* result = NULL;
+    ecc_point* tmp = NULL;
+
+    (void)ctx;
+
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_mul");
+
+    if (!group || !r) {
+        WOLFSSL_MSG("wolfSSL_EC_POINT_mul NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (!(result = wc_ecc_new_point())) {
+        WOLFSSL_MSG("wolfSSL_EC_POINT_new error");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* read the curve prime and a */
+    if (mp_init_multi(&prime, &a, NULL, NULL, NULL, NULL) != MP_OKAY) {
+        WOLFSSL_MSG("mp_init_multi error");
+        goto cleanup;
+    }
+
+    if (q && setupPoint(q) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("setupPoint error");
+        goto cleanup;
+    }
+
+    if (mp_read_radix(&prime, ecc_sets[group->curve_idx].prime, MP_RADIX_HEX)
+            != MP_OKAY) {
+        WOLFSSL_MSG("mp_read_radix prime error");
+        goto cleanup;
+    }
+
+    if (mp_read_radix(&a, ecc_sets[group->curve_idx].Af, MP_RADIX_HEX)
+            != MP_OKAY) {
+        WOLFSSL_MSG("mp_read_radix a error");
+        goto cleanup;
+    }
+
+    if (n) {
+        /* load generator */
+        if (wc_ecc_get_generator(result, group->curve_idx)
+                != MP_OKAY) {
+            WOLFSSL_MSG("wc_ecc_get_generator error");
+            goto cleanup;
+        }
+    }
+
+    if (n && q && m) {
+        /* r = generator * n + q * m */
+#ifdef ECC_SHAMIR
+        if (ecc_mul2add(result, (mp_int*)n->internal,
+                        (ecc_point*)q->internal, (mp_int*)m->internal,
+                        result, &a, &prime, NULL)
+                != MP_OKAY) {
+            WOLFSSL_MSG("ecc_mul2add error");
+            goto cleanup;
+        }
+#else
+        mp_digit mp = 0;
+        if (mp_montgomery_setup(&prime, &mp) != MP_OKAY) {
+            WOLFSSL_MSG("mp_montgomery_setup nqm error");
+            goto cleanup;
+        }
+        if (!(tmp = wc_ecc_new_point())) {
+            WOLFSSL_MSG("wolfSSL_EC_POINT_new nqm error");
+            goto cleanup;
+        }
+        /* r = generator * n */
+        if (wc_ecc_mulmod((mp_int*)n->internal, result, result, &a, &prime, 1)
+                != MP_OKAY) {
+            WOLFSSL_MSG("wc_ecc_mulmod nqm error");
+            goto cleanup;
+        }
+        /* tmp = q * m */
+        if (wc_ecc_mulmod((mp_int*)m->internal, (ecc_point*)q->internal,
+                tmp, &a, &prime, 1) != MP_OKAY) {
+            WOLFSSL_MSG("wc_ecc_mulmod nqm error");
+            goto cleanup;
+        }
+        /* result = result + tmp */
+        if (ecc_projective_add_point(tmp, result, result, &a, &prime, mp)
+                != MP_OKAY) {
+            WOLFSSL_MSG("wc_ecc_mulmod nqm error");
+            goto cleanup;
+        }
+        if (ecc_map(result, &prime, mp) != MP_OKAY) {
+            WOLFSSL_MSG("ecc_map nqm error");
+            goto cleanup;
+        }
+#endif
+    }
+    else if (n) {
+        /* r = generator * n */
+        if (wc_ecc_mulmod((mp_int*)n->internal, result, result, &a, &prime, 1)
+                != MP_OKAY) {
+            WOLFSSL_MSG("wc_ecc_mulmod gn error");
+            goto cleanup;
+        }
+    }
+    else if (q && m) {
+        /* r = q * m */
+        if (wc_ecc_mulmod((mp_int*)m->internal, (ecc_point*)q->internal,
+                           result, &a, &prime, 1) != MP_OKAY) {
+            WOLFSSL_MSG("wc_ecc_mulmod qm error");
+            goto cleanup;
+        }
+    }
+
+    /* copy to destination */
+    if (wc_ecc_copy_point(result, (ecc_point*)r->internal)) {
+        WOLFSSL_MSG("wc_ecc_copy_point error");
+        goto cleanup;
+    }
+    r->inSet = 1;
+    if (SetECPointExternal(r) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("SetECPointExternal error");
+        goto cleanup;
+    }
+
+    ret = WOLFSSL_SUCCESS;
+cleanup:
+    mp_clear(&a);
+    mp_clear(&prime);
+    wc_ecc_del_point(result);
+    wc_ecc_del_point(tmp);
+    return ret;
+}
+#endif /* !defined(WOLFSSL_ATECC508A) && defined(ECC_SHAMIR) &&
+        * !defined(HAVE_SELFTEST) */
+
+void wolfSSL_EC_POINT_clear_free(WOLFSSL_EC_POINT *p)
+{
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_clear_free");
+
+    wolfSSL_EC_POINT_free(p);
+}
+
+/* return code compliant with OpenSSL :
+ *   0 if equal, 1 if not and -1 in case of error
+ */
+int wolfSSL_EC_POINT_cmp(const WOLFSSL_EC_GROUP *group,
+                         const WOLFSSL_EC_POINT *a, const WOLFSSL_EC_POINT *b,
+                         WOLFSSL_BN_CTX *ctx)
+{
+    int ret;
+
+    (void)ctx;
+
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_cmp");
+
+    if (group == NULL || a == NULL || a->internal == NULL || b == NULL ||
+        b->internal == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_POINT_cmp Bad arguments");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    ret = wc_ecc_cmp_point((ecc_point*)a->internal, (ecc_point*)b->internal);
+    if (ret == MP_EQ)
+        return 0;
+    else if (ret == MP_LT || ret == MP_GT)
+        return 1;
+
+    return WOLFSSL_FATAL_ERROR;
+}
+
+int wolfSSL_EC_POINT_copy(WOLFSSL_EC_POINT *dest, const WOLFSSL_EC_POINT *src)
+{
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_copy");
+
+    if (!dest || !src) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if (setupPoint(src) != WOLFSSL_SUCCESS) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if (wc_ecc_copy_point((ecc_point*) dest->internal,
+                          (ecc_point*) src->internal) != MP_OKAY) {
+        return WOLFSSL_FAILURE;
+    }
+
+    dest->inSet = 1;
+
+    if (SetECPointExternal(dest) != WOLFSSL_SUCCESS) {
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* HAVE_ECC */
+#endif /* OPENSSL_EXTRA */
+
+#if defined(HAVE_ECC) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
+void wolfSSL_EC_POINT_free(WOLFSSL_EC_POINT *p)
+{
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_free");
+
+    if (p != NULL) {
+        if (p->internal != NULL) {
+            wc_ecc_del_point((ecc_point*)p->internal);
+            p->internal = NULL;
+        }
+
+        wolfSSL_BN_free(p->X);
+        wolfSSL_BN_free(p->Y);
+        wolfSSL_BN_free(p->Z);
+        p->X = NULL;
+        p->Y = NULL;
+        p->Z = NULL;
+        p->inSet = p->exSet = 0;
+
+        XFREE(p, NULL, DYNAMIC_TYPE_ECC);
+        /* p = NULL, don't try to access or double free it */
+    }
+}
+#endif
+
+#ifdef OPENSSL_EXTRA
+#ifdef HAVE_ECC
+/* return code compliant with OpenSSL :
+ *   1 if point at infinity, 0 else
+ */
+int wolfSSL_EC_POINT_is_at_infinity(const WOLFSSL_EC_GROUP *group,
+                                    const WOLFSSL_EC_POINT *point)
+{
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_is_at_infinity");
+
+    if (group == NULL || point == NULL || point->internal == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_POINT_is_at_infinity NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (setupPoint(point) != WOLFSSL_SUCCESS) {
+        return WOLFSSL_FAILURE;
+    }
+
+    ret = wc_ecc_point_is_at_infinity((ecc_point*)point->internal);
+    if (ret < 0) {
+        WOLFSSL_MSG("ecc_point_is_at_infinity failure");
+        return WOLFSSL_FAILURE;
+    }
+
+    return ret;
+}
+
+/* End EC_POINT */
+
+size_t wolfSSL_EC_get_builtin_curves(WOLFSSL_EC_BUILTIN_CURVE *r, size_t nitems)
+{
+    size_t i, min_nitems;
+#ifdef HAVE_SELFTEST
+    size_t ecc_sets_count;
+    for (i = 0; ecc_sets[i].size != 0 && ecc_sets[i].name != NULL; i++);
+    ecc_sets_count = i;
+#endif
+
+    if (r == NULL || nitems == 0)
+        return ecc_sets_count;
+
+    min_nitems = nitems < ecc_sets_count ? nitems : ecc_sets_count;
+
+    for (i = 0; i < min_nitems; i++) {
+        r[i].nid = EccEnumToNID(ecc_sets[i].id);
+        r[i].comment = wolfSSL_OBJ_nid2sn(r[i].nid);
+    }
+
+    return ecc_sets_count;
+}
+
+/* Start ECDSA_SIG */
+void wolfSSL_ECDSA_SIG_free(WOLFSSL_ECDSA_SIG *sig)
+{
+    WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_free");
+
+    if (sig) {
+        wolfSSL_BN_free(sig->r);
+        wolfSSL_BN_free(sig->s);
+
+        XFREE(sig, NULL, DYNAMIC_TYPE_ECC);
+    }
+}
+
+WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_SIG_new(void)
+{
+    WOLFSSL_ECDSA_SIG *sig;
+
+    WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_new");
+
+    sig = (WOLFSSL_ECDSA_SIG*) XMALLOC(sizeof(WOLFSSL_ECDSA_SIG), NULL,
+                                       DYNAMIC_TYPE_ECC);
+    if (sig == NULL) {
+        WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA signature failure");
+        return NULL;
+    }
+
+    sig->s = NULL;
+    sig->r = wolfSSL_BN_new();
+    if (sig->r == NULL) {
+        WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA r failure");
+        wolfSSL_ECDSA_SIG_free(sig);
+        return NULL;
+    }
+
+    sig->s = wolfSSL_BN_new();
+    if (sig->s == NULL) {
+        WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA s failure");
+        wolfSSL_ECDSA_SIG_free(sig);
+        return NULL;
+    }
+
+    return sig;
+}
+
+/* return signature structure on success, NULL otherwise */
+WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_do_sign(const unsigned char *d, int dlen,
+                                         WOLFSSL_EC_KEY *key)
+{
+    WOLFSSL_ECDSA_SIG *sig = NULL;
+    int     initTmpRng = 0;
+    WC_RNG* rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG* tmpRNG = NULL;
+#else
+    WC_RNG  tmpRNG[1];
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_ECDSA_do_sign");
+
+    if (d == NULL || key == NULL || key->internal == NULL) {
+        WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Bad arguments");
+        return NULL;
+    }
+
+    /* set internal key if not done */
+    if (key->inSet == 0)
+    {
+        WOLFSSL_MSG("wolfSSL_ECDSA_do_sign No EC key internal set, do it");
+
+        if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("wolfSSL_ECDSA_do_sign SetECKeyInternal failed");
+            return NULL;
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+    if (tmpRNG == NULL)
+        return NULL;
+#endif
+
+    if (wc_InitRng(tmpRNG) == 0) {
+        rng = tmpRNG;
+        initTmpRng = 1;
+    }
+    else {
+        WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Bad RNG Init, trying global");
+        if (initGlobalRNG == 0)
+            WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Global RNG no Init");
+        else
+            rng = &globalRNG;
+    }
+
+    if (rng) {
+        mp_int sig_r, sig_s;
+
+        if (mp_init_multi(&sig_r, &sig_s, NULL, NULL, NULL, NULL) == MP_OKAY) {
+            if (wc_ecc_sign_hash_ex(d, dlen, rng, (ecc_key*)key->internal,
+                                    &sig_r, &sig_s) != MP_OKAY) {
+                WOLFSSL_MSG("wc_ecc_sign_hash_ex failed");
+            }
+            else {
+                /* put signature blob in ECDSA structure */
+                sig = wolfSSL_ECDSA_SIG_new();
+                if (sig == NULL)
+                    WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new failed");
+                else if (SetIndividualExternal(&(sig->r), &sig_r)!=WOLFSSL_SUCCESS){
+                    WOLFSSL_MSG("ecdsa r key error");
+                    wolfSSL_ECDSA_SIG_free(sig);
+                    sig = NULL;
+                }
+                else if (SetIndividualExternal(&(sig->s), &sig_s)!=WOLFSSL_SUCCESS){
+                    WOLFSSL_MSG("ecdsa s key error");
+                    wolfSSL_ECDSA_SIG_free(sig);
+                    sig = NULL;
+                }
+
+            }
+            mp_free(&sig_r);
+            mp_free(&sig_s);
+        }
+    }
+
+    if (initTmpRng)
+        wc_FreeRng(tmpRNG);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+    return sig;
+}
+
+/* return code compliant with OpenSSL :
+ *   1 for a valid signature, 0 for an invalid signature and -1 on error
+ */
+int wolfSSL_ECDSA_do_verify(const unsigned char *d, int dlen,
+                            const WOLFSSL_ECDSA_SIG *sig, WOLFSSL_EC_KEY *key)
+{
+    int check_sign = 0;
+
+    WOLFSSL_ENTER("wolfSSL_ECDSA_do_verify");
+
+    if (d == NULL || sig == NULL || key == NULL || key->internal == NULL) {
+        WOLFSSL_MSG("wolfSSL_ECDSA_do_verify Bad arguments");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    /* set internal key if not done */
+    if (key->inSet == 0)
+    {
+        WOLFSSL_MSG("No EC key internal set, do it");
+
+        if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetECKeyInternal failed");
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+
+    if (wc_ecc_verify_hash_ex((mp_int*)sig->r->internal,
+                              (mp_int*)sig->s->internal, d, dlen, &check_sign,
+                              (ecc_key *)key->internal) != MP_OKAY) {
+        WOLFSSL_MSG("wc_ecc_verify_hash failed");
+        return WOLFSSL_FATAL_ERROR;
+    }
+    else if (check_sign == 0) {
+        WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected");
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+WOLFSSL_ECDSA_SIG *wolfSSL_d2i_ECDSA_SIG(WOLFSSL_ECDSA_SIG **sig,
+                                         const unsigned char **pp, long len)
+{
+    WOLFSSL_ECDSA_SIG *s = NULL;
+
+    if (pp == NULL)
+        return NULL;
+
+    if (sig != NULL)
+        s = *sig;
+    if (s == NULL) {
+        s = wolfSSL_ECDSA_SIG_new();
+        if (s == NULL)
+            return NULL;
+    }
+
+    /* DecodeECC_DSA_Sig calls mp_init, so free these */
+    mp_free((mp_int*)s->r->internal);
+    mp_free((mp_int*)s->s->internal);
+
+    if (DecodeECC_DSA_Sig(*pp, (word32)len, (mp_int*)s->r->internal,
+                                          (mp_int*)s->s->internal) != MP_OKAY) {
+        if (sig == NULL || *sig == NULL)
+            wolfSSL_ECDSA_SIG_free(s);
+        return NULL;
+    }
+
+    *pp += len;
+    if (sig != NULL)
+        *sig = s;
+    return s;
+}
+
+int wolfSSL_i2d_ECDSA_SIG(const WOLFSSL_ECDSA_SIG *sig, unsigned char **pp)
+{
+    word32 len;
+
+    if (sig == NULL)
+        return 0;
+
+    /* ASN.1: SEQ + INT + INT
+     *   ASN.1 Integer must be a positive value - prepend zero if number has
+     *   top bit set.
+     */
+    len = 2 + mp_leading_bit((mp_int*)sig->r->internal) +
+              mp_unsigned_bin_size((mp_int*)sig->r->internal) +
+          2 + mp_leading_bit((mp_int*)sig->s->internal) +
+              mp_unsigned_bin_size((mp_int*)sig->s->internal);
+    /* Two bytes required for length if ASN.1 SEQ data greater than 127 bytes
+     * and less than 256 bytes.
+     */
+    len = 1 + ((len > 127) ? 2 : 1) + len;
+    if (pp != NULL && *pp != NULL) {
+        if (StoreECC_DSA_Sig(*pp, &len, (mp_int*)sig->r->internal,
+                                        (mp_int*)sig->s->internal) != MP_OKAY) {
+            len = 0;
+        }
+        else
+            *pp += len;
+    }
+
+    return (int)len;
+}
+/* End ECDSA_SIG */
+
+/* Start ECDH */
+/* return code compliant with OpenSSL :
+ *   length of computed key if success, -1 if error
+ */
+int wolfSSL_ECDH_compute_key(void *out, size_t outlen,
+                             const WOLFSSL_EC_POINT *pub_key,
+                             WOLFSSL_EC_KEY *ecdh,
+                             void *(*KDF) (const void *in, size_t inlen,
+                                           void *out, size_t *outlen))
+{
+    word32 len;
+    (void)KDF;
+
+    (void)KDF;
+
+    WOLFSSL_ENTER("wolfSSL_ECDH_compute_key");
+
+    if (out == NULL || pub_key == NULL || pub_key->internal == NULL ||
+        ecdh == NULL || ecdh->internal == NULL) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    /* set internal key if not done */
+    if (ecdh->inSet == 0)
+    {
+        WOLFSSL_MSG("No EC key internal set, do it");
+
+        if (SetECKeyInternal(ecdh) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetECKeyInternal failed");
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+
+    len = (word32)outlen;
+
+    if (wc_ecc_shared_secret_ssh((ecc_key*)ecdh->internal,
+                                 (ecc_point*)pub_key->internal,
+                                 (byte *)out, &len) != MP_OKAY) {
+        WOLFSSL_MSG("wc_ecc_shared_secret failed");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    return len;
+}
+/* End ECDH */
+
+#if !defined(NO_FILESYSTEM)
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_PEM_write_EC_PUBKEY(XFILE fp, WOLFSSL_EC_KEY *x)
+{
+    (void)fp;
+    (void)x;
+    WOLFSSL_STUB("PEM_write_EC_PUBKEY");
+    WOLFSSL_MSG("wolfSSL_PEM_write_EC_PUBKEY not implemented");
+
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+/* Uses the same format of input as wolfSSL_PEM_read_bio_PrivateKey but expects
+ * the results to be an EC key.
+ *
+ * bio  structure to read EC private key from
+ * ec   if not null is then set to the result
+ * cb   password callback for reading PEM
+ * pass password string
+ *
+ * returns a pointer to a new WOLFSSL_EC_KEY struct on success and NULL on fail
+ */
+
+WOLFSSL_EC_KEY* wolfSSL_PEM_read_bio_EC_PUBKEY(WOLFSSL_BIO* bio,
+                                               WOLFSSL_EC_KEY** ec,
+                                               pem_password_cb* cb, void *pass)
+{
+    WOLFSSL_EVP_PKEY* pkey;
+    WOLFSSL_EC_KEY* local;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_read_bio_EC_PUBKEY");
+
+    pkey = wolfSSL_PEM_read_bio_PUBKEY(bio, NULL, cb, pass);
+    if (pkey == NULL) {
+        return NULL;
+    }
+
+    /* Since the WOLFSSL_EC_KEY structure is being taken from WOLFSSL_EVP_PKEY the
+     * flag indicating that the WOLFSSL_EC_KEY structure is owned should be FALSE
+     * to avoid having it free'd */
+    pkey->ownEcc = 0;
+    local = pkey->ecc;
+    if (ec != NULL) {
+        *ec = local;
+    }
+
+    wolfSSL_EVP_PKEY_free(pkey);
+    return local;
+}
+
+/* Reads a private EC key from a WOLFSSL_BIO into a WOLFSSL_EC_KEY.
+ * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
+ */
+WOLFSSL_EC_KEY* wolfSSL_PEM_read_bio_ECPrivateKey(WOLFSSL_BIO* bio,
+                                                  WOLFSSL_EC_KEY** ec,
+                                                  pem_password_cb* cb,
+                                                  void *pass)
+{
+    WOLFSSL_EVP_PKEY* pkey;
+    WOLFSSL_EC_KEY* local;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_read_bio_ECPrivateKey");
+
+    pkey = wolfSSL_PEM_read_bio_PrivateKey(bio, NULL, cb, pass);
+    if (pkey == NULL) {
+        return NULL;
+    }
+
+    /* Since the WOLFSSL_EC_KEY structure is being taken from WOLFSSL_EVP_PKEY the
+     * flag indicating that the WOLFSSL_EC_KEY structure is owned should be FALSE
+     * to avoid having it free'd */
+    pkey->ownEcc = 0;
+    local = pkey->ecc;
+    if (ec != NULL) {
+        *ec = local;
+    }
+
+    wolfSSL_EVP_PKEY_free(pkey);
+    return local;
+}
+#endif /* NO_FILESYSTEM */
+
+#if defined(WOLFSSL_KEY_GEN)
+/* Takes a public WOLFSSL_EC_KEY and writes it out to WOLFSSL_BIO
+ * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
+ */
+int wolfSSL_PEM_write_bio_EC_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec)
+{
+    int ret = 0, der_max_len = 0, derSz = 0;
+    byte *derBuf;
+    WOLFSSL_EVP_PKEY* pkey;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_write_bio_EC_PUBKEY");
+
+    if (bio == NULL || ec == NULL) {
+        WOLFSSL_MSG("Bad Function Arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* Initialize pkey structure */
+    pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap);
+    if (pkey == NULL) {
+        WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* Set pkey info */
+    pkey->ecc    = ec;
+    pkey->ownEcc = 0; /* pkey does not own ECC */
+    pkey->type = EVP_PKEY_EC;
+
+    /* 4 > size of pub, priv + ASN.1 additional information */
+    der_max_len = 4 * wc_ecc_size((ecc_key*)ec->internal) + AES_BLOCK_SIZE;
+
+    derBuf = (byte*)XMALLOC(der_max_len, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (derBuf == NULL) {
+        WOLFSSL_MSG("Malloc failed");
+        wolfSSL_EVP_PKEY_free(pkey);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* convert key to der format */
+    derSz = wc_EccPublicKeyToDer((ecc_key*)ec->internal, derBuf, der_max_len, 1);
+    if (derSz < 0) {
+        WOLFSSL_MSG("wc_EccPublicKeyToDer failed");
+        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+        wolfSSL_EVP_PKEY_free(pkey);
+        return WOLFSSL_FAILURE;
+    }
+
+    pkey->pkey.ptr = (char*)XMALLOC(derSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (pkey->pkey.ptr == NULL) {
+        WOLFSSL_MSG("key malloc failed");
+        XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        wolfSSL_EVP_PKEY_free(pkey);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* add der info to the evp key */
+    pkey->pkey_sz = derSz;
+    XMEMCPY(pkey->pkey.ptr, derBuf, derSz);
+    XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+    if((ret = wolfSSL_PEM_write_bio_PUBKEY(bio, pkey)) != WOLFSSL_SUCCESS){
+        WOLFSSL_MSG("wolfSSL_PEM_write_bio_PUBKEY failed");
+    }
+    wolfSSL_EVP_PKEY_free(pkey);
+
+    return ret;
+}
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_PEM_write_bio_ECPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec,
+                                       const EVP_CIPHER* cipher,
+                                       unsigned char* passwd, int len,
+                                       pem_password_cb* cb, void* arg)
+{
+    int ret = 0, der_max_len = 0, derSz = 0;
+    byte *derBuf;
+    WOLFSSL_EVP_PKEY* pkey;
+    WOLFSSL_ENTER("WOLFSSL_PEM_write_bio_ECPrivateKey");
+
+    if (bio == NULL || ec == NULL) {
+        WOLFSSL_MSG("Bad Function Arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* Initialize pkey structure */
+    pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap);
+    if (pkey == NULL) {
+        WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* Set pkey info */
+    pkey->ecc    = ec;
+    pkey->ownEcc = 0; /* pkey does not own ECC */
+    pkey->type = EVP_PKEY_EC;
+
+    /* 4 > size of pub, priv + ASN.1 additional informations
+     */
+    der_max_len = 4 * wc_ecc_size((ecc_key*)ec->internal) + AES_BLOCK_SIZE;
+
+    derBuf = (byte*)XMALLOC(der_max_len, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (derBuf == NULL) {
+        WOLFSSL_MSG("Malloc failed");
+        wolfSSL_EVP_PKEY_free(pkey);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* convert key to der format */
+    derSz = wc_EccKeyToDer((ecc_key*)ec->internal, derBuf, der_max_len);
+    if (derSz < 0) {
+        WOLFSSL_MSG("wc_EccKeyToDer failed");
+        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+        wolfSSL_EVP_PKEY_free(pkey);
+        return WOLFSSL_FAILURE;
+    }
+
+    pkey->pkey.ptr = (char*)XMALLOC(derSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (pkey->pkey.ptr == NULL) {
+        WOLFSSL_MSG("key malloc failed");
+        XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        wolfSSL_EVP_PKEY_free(pkey);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* add der info to the evp key */
+    pkey->pkey_sz = derSz;
+    XMEMCPY(pkey->pkey.ptr, derBuf, derSz);
+    XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+    ret = wolfSSL_PEM_write_bio_PrivateKey(bio, pkey, cipher, passwd, len,
+                                        cb, arg);
+    wolfSSL_EVP_PKEY_free(pkey);
+
+    return ret;
+}
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ecc,
+                                       const EVP_CIPHER* cipher,
+                                       unsigned char* passwd, int passwdSz,
+                                       unsigned char **pem, int *plen)
+{
+#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
+    byte *derBuf, *tmp, *cipherInfo = NULL;
+    int  der_max_len = 0, derSz = 0;
+    const int type = ECC_PRIVATEKEY_TYPE;
+    const char* header = NULL;
+    const char* footer = NULL;
+
+    WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey");
+
+    if (pem == NULL || plen == NULL || ecc == NULL || ecc->internal == NULL) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (wc_PemGetHeaderFooter(type, &header, &footer) != 0)
+        return WOLFSSL_FAILURE;
+
+    if (ecc->inSet == 0) {
+        WOLFSSL_MSG("No ECC internal set, do it");
+
+        if (SetECKeyInternal(ecc) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetECKeyInternal failed");
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+    /* 4 > size of pub, priv + ASN.1 additional information */
+    der_max_len = 4 * wc_ecc_size((ecc_key*)ecc->internal) + AES_BLOCK_SIZE;
+
+    derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_DER);
+    if (derBuf == NULL) {
+        WOLFSSL_MSG("malloc failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* Key to DER */
+    derSz = wc_EccKeyToDer((ecc_key*)ecc->internal, derBuf, der_max_len);
+    if (derSz < 0) {
+        WOLFSSL_MSG("wc_EccKeyToDer failed");
+        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* encrypt DER buffer if required */
+    if (passwd != NULL && passwdSz > 0 && cipher != NULL) {
+        int ret;
+
+        ret = EncryptDerKey(derBuf, &derSz, cipher,
+                            passwd, passwdSz, &cipherInfo);
+        if (ret != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("EncryptDerKey failed");
+            XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+            return ret;
+        }
+
+        /* tmp buffer with a max size */
+        *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
+            (int)XSTRLEN(footer) + 1 + HEADER_ENCRYPTED_KEY_SIZE;
+    }
+    else { /* tmp buffer with a max size */
+        *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
+            (int)XSTRLEN(footer) + 1;
+    }
+
+    tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_PEM);
+    if (tmp == NULL) {
+        WOLFSSL_MSG("malloc failed");
+        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+        if (cipherInfo != NULL)
+            XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* DER to PEM */
+    *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, type);
+    if (*plen <= 0) {
+        WOLFSSL_MSG("wc_DerToPemEx failed");
+        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+        if (cipherInfo != NULL)
+            XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+        return WOLFSSL_FAILURE;
+    }
+    XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+    if (cipherInfo != NULL)
+        XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+
+    *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY);
+    if (*pem == NULL) {
+        WOLFSSL_MSG("malloc failed");
+        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+        return WOLFSSL_FAILURE;
+    }
+    XMEMSET(*pem, 0, (*plen)+1);
+
+    if (XMEMCPY(*pem, tmp, *plen) == NULL) {
+        WOLFSSL_MSG("XMEMCPY failed");
+        XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
+        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+        return WOLFSSL_FAILURE;
+    }
+    XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+
+    return WOLFSSL_SUCCESS;
+#else
+    (void)ecc;
+    (void)cipher;
+    (void)passwd;
+    (void)passwdSz;
+    (void)pem;
+    (void)plen;
+    return WOLFSSL_FAILURE;
+#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
+}
+
+#ifndef NO_FILESYSTEM
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_PEM_write_ECPrivateKey(XFILE fp, WOLFSSL_EC_KEY *ecc,
+                                   const EVP_CIPHER *enc,
+                                   unsigned char *kstr, int klen,
+                                   pem_password_cb *cb, void *u)
+{
+    byte *pem;
+    int  plen, ret;
+
+    (void)cb;
+    (void)u;
+
+    WOLFSSL_MSG("wolfSSL_PEM_write_ECPrivateKey");
+
+    if (fp == XBADFILE || ecc == NULL || ecc->internal == NULL) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    ret = wolfSSL_PEM_write_mem_ECPrivateKey(ecc, enc, kstr, klen, &pem, &plen);
+    if (ret != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    ret = (int)XFWRITE(pem, plen, 1, fp);
+    if (ret != 1) {
+        WOLFSSL_MSG("ECC private key file write failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* NO_FILESYSTEM */
+#endif /* defined(WOLFSSL_KEY_GEN) */
+
+#endif /* HAVE_ECC */
+
+
+#ifndef NO_DSA
+
+#if defined(WOLFSSL_KEY_GEN)
+
+/* Takes a DSA Privatekey and writes it out to a WOLFSSL_BIO
+ * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
+ */
+int wolfSSL_PEM_write_bio_DSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_DSA* dsa,
+                                       const EVP_CIPHER* cipher,
+                                       unsigned char* passwd, int len,
+                                       pem_password_cb* cb, void* arg)
+{
+    int ret = 0, der_max_len = 0, derSz = 0;
+    byte *derBuf;
+    WOLFSSL_EVP_PKEY* pkey;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_write_bio_DSAPrivateKey");
+
+    if (bio == NULL || dsa == NULL) {
+        WOLFSSL_MSG("Bad Function Arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap);
+    if (pkey == NULL) {
+        WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    pkey->type   = EVP_PKEY_DSA;
+    pkey->dsa    = dsa;
+    pkey->ownDsa = 0;
+
+    /* 4 > size of pub, priv, p, q, g + ASN.1 additional information */
+    der_max_len = 4 * wolfSSL_BN_num_bytes(dsa->g) + AES_BLOCK_SIZE;
+
+    derBuf = (byte*)XMALLOC(der_max_len, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (derBuf == NULL) {
+        WOLFSSL_MSG("Malloc failed");
+        wolfSSL_EVP_PKEY_free(pkey);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* convert key to der format */
+    derSz = wc_DsaKeyToDer((DsaKey*)dsa->internal, derBuf, der_max_len);
+    if (derSz < 0) {
+        WOLFSSL_MSG("wc_DsaKeyToDer failed");
+        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+        wolfSSL_EVP_PKEY_free(pkey);
+        return WOLFSSL_FAILURE;
+    }
+
+    pkey->pkey.ptr = (char*)XMALLOC(derSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (pkey->pkey.ptr == NULL) {
+        WOLFSSL_MSG("key malloc failed");
+        XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        wolfSSL_EVP_PKEY_free(pkey);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* add der info to the evp key */
+    pkey->pkey_sz = derSz;
+    XMEMCPY(pkey->pkey.ptr, derBuf, derSz);
+    XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+    ret = wolfSSL_PEM_write_bio_PrivateKey(bio, pkey, cipher, passwd, len,
+                                        cb, arg);
+    wolfSSL_EVP_PKEY_free(pkey);
+
+    return ret;
+}
+
+#ifndef HAVE_SELFTEST
+/* Takes a DSA public key and writes it out to a WOLFSSL_BIO
+ * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
+ */
+int wolfSSL_PEM_write_bio_DSA_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_DSA* dsa)
+{
+    int ret = 0, derMax = 0, derSz = 0;
+    byte *derBuf;
+    WOLFSSL_EVP_PKEY* pkey;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_write_bio_DSA_PUBKEY");
+
+    if (bio == NULL || dsa == NULL) {
+        WOLFSSL_MSG("Bad function arguements");
+        return WOLFSSL_FAILURE;
+    }
+
+    pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap);
+    if (pkey == NULL) {
+        WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    pkey->type   = EVP_PKEY_DSA;
+    pkey->dsa    = dsa;
+    pkey->ownDsa = 0;
+
+    /* 4 > size of pub, priv, p, q, g + ASN.1 additional information */
+    derMax = 4 * wolfSSL_BN_num_bytes(dsa->g) + AES_BLOCK_SIZE;
+
+    derBuf = (byte*)XMALLOC(derMax, bio->heap, DYNAMIC_TYPE_DER);
+    if (derBuf == NULL) {
+        WOLFSSL_MSG("malloc failed");
+        wolfSSL_EVP_PKEY_free(pkey);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* Key to DER */
+    derSz = wc_DsaKeyToPublicDer((DsaKey*)dsa->internal, derBuf, derMax);
+    if (derSz < 0) {
+        WOLFSSL_MSG("wc_DsaKeyToDer failed");
+        XFREE(derBuf, bio->heap, DYNAMIC_TYPE_DER);
+        wolfSSL_EVP_PKEY_free(pkey);
+        return WOLFSSL_FAILURE;
+    }
+
+    pkey->pkey.ptr = (char*)XMALLOC(derSz, bio->heap, DYNAMIC_TYPE_DER);
+
+    if (pkey->pkey.ptr == NULL) {
+        WOLFSSL_MSG("key malloc failed");
+        XFREE(derBuf, bio->heap, DYNAMIC_TYPE_DER);
+        wolfSSL_EVP_PKEY_free(pkey);
+        return WOLFSSL_FAILURE;
+    }
+    pkey->pkey_sz = derSz;
+    XMEMSET(pkey->pkey.ptr, 0, derSz);
+
+    if (XMEMCPY(pkey->pkey.ptr, derBuf, derSz) == NULL) {
+        WOLFSSL_MSG("XMEMCPY failed");
+        XFREE(derBuf, bio->heap, DYNAMIC_TYPE_DER);
+        XFREE(pkey->pkey.ptr, bio->heap, DYNAMIC_TYPE_DER);
+        wolfSSL_EVP_PKEY_free(pkey);
+        return WOLFSSL_FAILURE;
+    }
+    XFREE(derBuf, bio->heap, DYNAMIC_TYPE_DER);
+    ret = wolfSSL_PEM_write_bio_PUBKEY(bio, pkey);
+    wolfSSL_EVP_PKEY_free(pkey);
+    return ret;
+}
+#endif /* HAVE_SELFTEST */
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa,
+                                        const EVP_CIPHER* cipher,
+                                        unsigned char* passwd, int passwdSz,
+                                        unsigned char **pem, int *plen)
+{
+#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
+    byte *derBuf, *tmp, *cipherInfo = NULL;
+    int  der_max_len = 0, derSz = 0;
+    const int type = DSA_PRIVATEKEY_TYPE;
+    const char* header = NULL;
+    const char* footer = NULL;
+
+    WOLFSSL_MSG("wolfSSL_PEM_write_mem_DSAPrivateKey");
+
+    if (pem == NULL || plen == NULL || dsa == NULL || dsa->internal == NULL) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (wc_PemGetHeaderFooter(type, &header, &footer) != 0)
+        return WOLFSSL_FAILURE;
+
+    if (dsa->inSet == 0) {
+        WOLFSSL_MSG("No DSA internal set, do it");
+
+        if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetDsaInternal failed");
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+    /* 4 > size of pub, priv, p, q, g + ASN.1 additional information */
+    der_max_len = 4 * wolfSSL_BN_num_bytes(dsa->g) + AES_BLOCK_SIZE;
+
+    derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_DER);
+    if (derBuf == NULL) {
+        WOLFSSL_MSG("malloc failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* Key to DER */
+    derSz = wc_DsaKeyToDer((DsaKey*)dsa->internal, derBuf, der_max_len);
+    if (derSz < 0) {
+        WOLFSSL_MSG("wc_DsaKeyToDer failed");
+        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* encrypt DER buffer if required */
+    if (passwd != NULL && passwdSz > 0 && cipher != NULL) {
+        int ret;
+
+        ret = EncryptDerKey(derBuf, &derSz, cipher,
+                            passwd, passwdSz, &cipherInfo);
+        if (ret != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("EncryptDerKey failed");
+            XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+            return ret;
+        }
+
+        /* tmp buffer with a max size */
+        *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
+            (int)XSTRLEN(footer) + 1 + HEADER_ENCRYPTED_KEY_SIZE;
+    }
+    else { /* tmp buffer with a max size */
+        *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
+            (int)XSTRLEN(footer) + 1;
+    }
+
+    tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_PEM);
+    if (tmp == NULL) {
+        WOLFSSL_MSG("malloc failed");
+        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+        if (cipherInfo != NULL)
+            XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* DER to PEM */
+    *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, type);
+    if (*plen <= 0) {
+        WOLFSSL_MSG("wc_DerToPemEx failed");
+        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+        if (cipherInfo != NULL)
+            XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+        return WOLFSSL_FAILURE;
+    }
+    XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+    if (cipherInfo != NULL)
+        XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+
+    *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY);
+    if (*pem == NULL) {
+        WOLFSSL_MSG("malloc failed");
+        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+        return WOLFSSL_FAILURE;
+    }
+    XMEMSET(*pem, 0, (*plen)+1);
+
+    if (XMEMCPY(*pem, tmp, *plen) == NULL) {
+        WOLFSSL_MSG("XMEMCPY failed");
+        XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
+        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+        return WOLFSSL_FAILURE;
+    }
+    XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+
+    return WOLFSSL_SUCCESS;
+#else
+    (void)dsa;
+    (void)cipher;
+    (void)passwd;
+    (void)passwdSz;
+    (void)pem;
+    (void)plen;
+    return WOLFSSL_FAILURE;
+#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
+}
+
+#ifndef NO_FILESYSTEM
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_PEM_write_DSAPrivateKey(XFILE fp, WOLFSSL_DSA *dsa,
+                                    const EVP_CIPHER *enc,
+                                    unsigned char *kstr, int klen,
+                                    pem_password_cb *cb, void *u)
+{
+    byte *pem;
+    int  plen, ret;
+
+    (void)cb;
+    (void)u;
+
+    WOLFSSL_MSG("wolfSSL_PEM_write_DSAPrivateKey");
+
+    if (fp == XBADFILE || dsa == NULL || dsa->internal == NULL) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    ret = wolfSSL_PEM_write_mem_DSAPrivateKey(dsa, enc, kstr, klen, &pem, &plen);
+    if (ret != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("wolfSSL_PEM_write_mem_DSAPrivateKey failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    ret = (int)XFWRITE(pem, plen, 1, fp);
+    if (ret != 1) {
+        WOLFSSL_MSG("DSA private key file write failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* NO_FILESYSTEM */
+#endif /* defined(WOLFSSL_KEY_GEN) */
+
+#ifndef NO_FILESYSTEM
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_PEM_write_DSA_PUBKEY(XFILE fp, WOLFSSL_DSA *x)
+{
+    (void)fp;
+    (void)x;
+    WOLFSSL_STUB("PEM_write_DSA_PUBKEY");
+    WOLFSSL_MSG("wolfSSL_PEM_write_DSA_PUBKEY not implemented");
+
+    return WOLFSSL_FAILURE;
+}
+#endif
+#endif /* NO_FILESYSTEM */
+
+#endif /* #ifndef NO_DSA */
+
+static int pem_read_bio_key(WOLFSSL_BIO* bio, pem_password_cb* cb, void* pass,
+                            int keyType, int* eccFlag, DerBuffer** der)
+{
+#ifdef WOLFSSL_SMALL_STACK
+    EncryptedInfo* info = NULL;
+#else
+    EncryptedInfo info[1];
+#endif /* WOLFSSL_SMALL_STACK */
+    pem_password_cb* localCb = NULL;
+    char* mem = NULL;
+    int memSz = 0;
+    int ret;
+
+    if(cb) {
+        localCb = cb;
+    } else {
+        if(pass) {
+            localCb = wolfSSL_PEM_def_callback;
+        }
+    }
+
+    if ((ret = wolfSSL_BIO_pending(bio)) > 0) {
+        memSz = ret;
+        mem = (char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_OPENSSL);
+        if (mem == NULL) {
+            WOLFSSL_MSG("Memory error");
+            ret = MEMORY_E;
+        }
+        if (ret >= 0) {
+            if ((ret = wolfSSL_BIO_read(bio, mem, memSz)) <= 0) {
+                XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
+                mem = NULL;
+                ret = MEMORY_E;
+            }
+        }
+    }
+    else if (bio->type == WOLFSSL_BIO_FILE) {
+        int sz  = 100; /* read from file by 100 byte chunks */
+        int idx = 0;
+        char* tmp = (char*)XMALLOC(sz, bio->heap, DYNAMIC_TYPE_OPENSSL);
+        memSz = 0;
+        if (tmp == NULL) {
+            WOLFSSL_MSG("Memory error");
+            ret = MEMORY_E;
+        }
+
+        while (ret >= 0 && (sz = wolfSSL_BIO_read(bio, tmp, sz)) > 0) {
+            char* newMem;
+            if (memSz + sz < 0) {
+                /* sanity check */
+                break;
+            }
+            newMem = (char*)XREALLOC(mem, memSz + sz, bio->heap,
+                    DYNAMIC_TYPE_OPENSSL);
+            if (newMem == NULL) {
+                WOLFSSL_MSG("Memory error");
+                XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
+                mem = NULL;
+                XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL);
+                tmp = NULL;
+                ret = MEMORY_E;
+                break;
+            }
+            mem = newMem;
+            XMEMCPY(mem + idx, tmp, sz);
+            memSz += sz;
+            idx   += sz;
+            sz = 100; /* read another 100 byte chunk from file */
+        }
+        XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL);
+        tmp = NULL;
+        if (memSz <= 0) {
+            WOLFSSL_MSG("No data to read from bio");
+            if (mem != NULL) {
+                XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
+                mem = NULL;
+            }
+            ret = BUFFER_E;
+        }
+    }
+    else {
+        WOLFSSL_MSG("No data to read from bio");
+        ret = NOT_COMPILED_IN;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    if (ret >= 0) {
+        info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
+                                       DYNAMIC_TYPE_TMP_BUFFER);
+        if (info == NULL) {
+            WOLFSSL_MSG("Error getting memory for EncryptedInfo structure");
+            XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
+            mem = NULL;
+            ret = MEMORY_E;
+        }
+    }
+#endif
+
+    if (ret >= 0) {
+        XMEMSET(info, 0, sizeof(EncryptedInfo));
+        info->passwd_cb       = localCb;
+        info->passwd_userdata = pass;
+        ret = PemToDer((const unsigned char*)mem, memSz, keyType, der,
+            NULL, info, eccFlag);
+
+        if (ret < 0) {
+            WOLFSSL_MSG("Bad Pem To Der");
+        }
+        else {
+            /* write left over data back to bio */
+            if ((memSz - (int)info->consumed) > 0 &&
+                    bio->type != WOLFSSL_BIO_FILE) {
+                if (wolfSSL_BIO_write(bio, mem + (int)info->consumed,
+                                       memSz - (int)info->consumed) <= 0) {
+                    WOLFSSL_MSG("Unable to advance bio read pointer");
+                }
+            }
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+    XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
+
+    return ret;
+}
+
+WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio,
+                                                  WOLFSSL_EVP_PKEY** key,
+                                                  pem_password_cb* cb,
+                                                  void* pass)
+{
+    WOLFSSL_EVP_PKEY* pkey = NULL;
+    DerBuffer*         der = NULL;
+    int             keyFormat = 0;
+    int                 type = -1;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_read_bio_PrivateKey");
+
+    if (bio == NULL)
+        return pkey;
+
+    if (pem_read_bio_key(bio, cb, pass, PRIVATEKEY_TYPE, &keyFormat,
+                                                                   &der) >= 0) {
+        const unsigned char* ptr = der->buffer;
+
+        if (keyFormat) {
+            /* keyFormat is Key_Sum enum */
+            if (keyFormat == RSAk)
+                type = EVP_PKEY_RSA;
+            else if (keyFormat == ECDSAk)
+                type =  EVP_PKEY_EC;
+            else if (keyFormat == DSAk)
+                type = EVP_PKEY_DSA;
+            else if (keyFormat == DHk)
+                type = EVP_PKEY_DH;
+        }
+        else {
+            /* Default to RSA if format is not set */
+            type = EVP_PKEY_RSA;
+        }
+
+        /* handle case where reuse is attempted */
+        if (key != NULL && *key != NULL)
+            pkey = *key;
+
+        wolfSSL_d2i_PrivateKey(type, &pkey, &ptr, der->length);
+        if (pkey == NULL) {
+            WOLFSSL_MSG("Error loading DER buffer into WOLFSSL_EVP_PKEY");
+        }
+    }
+
+    FreeDer(&der);
+
+    if (key != NULL && pkey != NULL)
+        *key = pkey;
+
+    WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_PrivateKey", 0);
+
+    return pkey;
+}
+
+WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_bio_PUBKEY(WOLFSSL_BIO* bio,
+                                              WOLFSSL_EVP_PKEY **key,
+                                              pem_password_cb *cb, void *pass)
+{
+    WOLFSSL_EVP_PKEY* pkey = NULL;
+    DerBuffer*        der = NULL;
+    int               keyFormat = 0;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_read_bio_PUBKEY");
+
+    if (bio == NULL)
+        return pkey;
+
+    if (pem_read_bio_key(bio, cb, pass, PUBLICKEY_TYPE, &keyFormat, &der) >= 0) {
+        const unsigned char* ptr = der->buffer;
+
+        /* handle case where reuse is attempted */
+        if (key != NULL && *key != NULL)
+            pkey = *key;
+
+        wolfSSL_d2i_PUBKEY(&pkey, &ptr, der->length);
+        if (pkey == NULL) {
+            WOLFSSL_MSG("Error loading DER buffer into WOLFSSL_EVP_PKEY");
+        }
+    }
+
+    FreeDer(&der);
+
+    if (key != NULL && pkey != NULL)
+        *key = pkey;
+
+    WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_PUBKEY", 0);
+
+    return pkey;
+}
+
+
+#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_RSA)
+/* Uses the same format of input as wolfSSL_PEM_read_bio_PrivateKey but expects
+ * the results to be an RSA key.
+ *
+ * bio  structure to read RSA private key from
+ * rsa  if not null is then set to the result
+ * cb   password callback for reading PEM
+ * pass password string
+ *
+ * returns a pointer to a new WOLFSSL_RSA structure on success and NULL on fail
+ */
+WOLFSSL_RSA* wolfSSL_PEM_read_bio_RSAPrivateKey(WOLFSSL_BIO* bio,
+        WOLFSSL_RSA** rsa, pem_password_cb* cb, void* pass)
+{
+    WOLFSSL_EVP_PKEY* pkey;
+    WOLFSSL_RSA* local;
+
+    WOLFSSL_ENTER("PEM_read_bio_RSAPrivateKey");
+
+    pkey = wolfSSL_PEM_read_bio_PrivateKey(bio, NULL, cb, pass);
+    if (pkey == NULL) {
+        return NULL;
+    }
+
+    /* Since the WOLFSSL_RSA structure is being taken from WOLFSSL_EVP_PEKY the
+     * flag indicating that the WOLFSSL_RSA structure is owned should be FALSE
+     * to avoid having it free'd */
+    pkey->ownRsa = 0;
+    local = pkey->rsa;
+    if (rsa != NULL) {
+        *rsa = local;
+    }
+
+    wolfSSL_EVP_PKEY_free(pkey);
+    return local;
+}
+#endif /* OPENSSL_EXTRA || OPENSSL_ALL || !NO_RSA */
+
+#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && (!defined(NO_CERTS) && \
+       !defined(NO_FILESYSTEM) && !defined(NO_DSA) && defined(WOLFSSL_KEY_GEN))
+/* Uses the same format of input as wolfSSL_PEM_read_bio_PrivateKey but expects
+ * the results to be an DSA key.
+ *
+ * bio  structure to read DSA private key from
+ * dsa  if not null is then set to the result
+ * cb   password callback for reading PEM
+ * pass password string
+ *
+ * returns a pointer to a new WOLFSSL_DSA structure on success and NULL on fail
+ */
+WOLFSSL_DSA* wolfSSL_PEM_read_bio_DSAPrivateKey(WOLFSSL_BIO* bio,
+                                                WOLFSSL_DSA** dsa,
+                                                pem_password_cb* cb,void *pass)
+{
+    WOLFSSL_EVP_PKEY* pkey = NULL;
+    WOLFSSL_DSA* local;
+    WOLFSSL_ENTER("wolfSSL_PEM_read_bio_DSAPrivateKey");
+
+
+    pkey = wolfSSL_PEM_read_bio_PrivateKey(bio, NULL, cb, pass);
+    if (pkey == NULL) {
+        WOLFSSL_MSG("Error in PEM_read_bio_PrivateKey");
+         return NULL;
+     }
+     /* Since the WOLFSSL_DSA structure is being taken from WOLFSSL_EVP_PKEY the
+     * flag indicating that the WOLFSSL_DSA structure is owned should be FALSE
+     * to avoid having it free'd */
+    pkey->ownDsa = 0;
+    local = pkey->dsa;
+    if (dsa != NULL) {
+        *dsa = local;
+    }
+     wolfSSL_EVP_PKEY_free(pkey);
+    return local;
+}
+
+/* Reads an DSA public key from a WOLFSSL_BIO into a WOLFSSL_DSA.
+ * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
+ */
+WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSA_PUBKEY(WOLFSSL_BIO* bio,WOLFSSL_DSA** dsa,
+                                                pem_password_cb* cb, void *pass)
+{
+    WOLFSSL_EVP_PKEY* pkey;
+    WOLFSSL_DSA* local;
+    WOLFSSL_ENTER("wolfSSL_PEM_read_bio_DSA_PUBKEY");
+
+    pkey = wolfSSL_PEM_read_bio_PUBKEY(bio, NULL, cb, pass);
+    if (pkey == NULL) {
+        WOLFSSL_MSG("wolfSSL_PEM_read_bio_PUBKEY failed");
+        return NULL;
+    }
+
+    /* Since the WOLFSSL_DSA structure is being taken from WOLFSSL_EVP_PKEY the
+     * flag indicating that the WOLFSSL_DSA structure is owned should be FALSE
+     * to avoid having it free'd */
+    pkey->ownDsa = 0;
+    local = pkey->dsa;
+    if (dsa != NULL) {
+        *dsa = local;
+    }
+
+    wolfSSL_EVP_PKEY_free(pkey);
+    return local;
+}
+#endif
+
+#ifdef HAVE_ECC
+/* returns a new WOLFSSL_EC_GROUP structure on success and NULL on fail */
+WOLFSSL_EC_GROUP* wolfSSL_PEM_read_bio_ECPKParameters(WOLFSSL_BIO* bio,
+        WOLFSSL_EC_GROUP** group, pem_password_cb* cb, void* pass)
+{
+    WOLFSSL_EVP_PKEY* pkey;
+    WOLFSSL_EC_GROUP* ret = NULL;
+
+    /* check on if bio is null is done in wolfSSL_PEM_read_bio_PrivateKey */
+    pkey = wolfSSL_PEM_read_bio_PrivateKey(bio, NULL, cb, pass);
+    if (pkey != NULL) {
+        if (pkey->type != EVP_PKEY_EC) {
+            WOLFSSL_MSG("Unexpected key type");
+        }
+        else {
+            ret = (WOLFSSL_EC_GROUP*)wolfSSL_EC_KEY_get0_group(pkey->ecc);
+
+            /* set ecc group to null so it is not free'd when pkey is free'd */
+            pkey->ecc->group = NULL;
+        }
+    }
+
+    (void)group;
+    wolfSSL_EVP_PKEY_free(pkey);
+    return ret;
+}
+#endif /* HAVE_ECC */
+
+#if !defined(NO_FILESYSTEM)
+WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PUBKEY(XFILE fp, EVP_PKEY **x,
+                                          pem_password_cb *cb, void *u)
+{
+    (void)fp;
+    (void)x;
+    (void)cb;
+    (void)u;
+
+    WOLFSSL_MSG("wolfSSL_PEM_read_PUBKEY not implemented");
+
+    return NULL;
+}
+#endif /* NO_FILESYSTEM */
+
+#ifndef NO_RSA
+
+#if defined(XSNPRINTF) && !defined(HAVE_FAST_RSA)
+/* snprintf() must be available */
+
+/******************************************************************************
+* wolfSSL_RSA_print - writes the human readable form of RSA to bio
+*
+* RETURNS:
+* returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE
+*/
+int wolfSSL_RSA_print(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa, int offset)
+{
+    char tmp[100] = {0};
+    word32 idx = 0;
+    int  sz = 0;
+    byte lbit = 0;
+    int  rawLen = 0;
+    byte* rawKey = NULL;
+    RsaKey* iRsa = NULL;
+    int i = 0;
+    mp_int *rsaElem = NULL;
+    char rsaStr[][20] = { "Modulus:",
+                          "PublicExponent:",
+                          "PrivateExponent:",
+                          "Prime1:",
+                          "Prime2:",
+                          "Exponent1:",
+                          "Exponent2:",
+                          "Coefficient:"
+                        };
+
+    WOLFSSL_ENTER("wolfSSL_RSA_print");
+    (void)offset;
+
+    if (bio == NULL || rsa == NULL) {
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if ((sz = wolfSSL_RSA_size(rsa)) < 0) {
+        WOLFSSL_MSG("Error getting RSA key size");
+        return WOLFSSL_FAILURE;
+    }
+    iRsa = (RsaKey*)rsa->internal;
+
+    XSNPRINTF(tmp, sizeof(tmp) - 1, "\n%s: (%d bit)",
+            "RSA Private-Key", 8 * sz);
+    tmp[sizeof(tmp) - 1] = '\0';
+    if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+        return WOLFSSL_FAILURE;
+    }
+
+    for (i=0; i<RSA_INTS; i++) {
+        switch(i) {
+            case 0:
+                /* Print out modulus */
+                rsaElem = &iRsa->n;
+                break;
+            case 1:
+                rsaElem = &iRsa->e;
+                break;
+            case 2:
+                rsaElem = &iRsa->d;
+                break;
+            case 3:
+                rsaElem = &iRsa->p;
+                break;
+            case 4:
+                rsaElem = &iRsa->q;
+                break;
+            case 5:
+                rsaElem = &iRsa->dP;
+                break;
+            case 6:
+                rsaElem = &iRsa->dQ;
+                break;
+            case 7:
+                rsaElem = &iRsa->u;
+                break;
+            default:
+                WOLFSSL_MSG("Bad index value");
+        }
+
+        if (i == 1) {
+            /* Print out exponent values */
+            rawLen = mp_unsigned_bin_size(rsaElem);
+            if (rawLen < 0) {
+                WOLFSSL_MSG("Error getting exponent size");
+                return WOLFSSL_FAILURE;
+            }
+
+            if ((word32)rawLen < sizeof(word32)) {
+                rawLen = sizeof(word32);
+            }
+            rawKey = (byte*)XMALLOC(rawLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            if (rawKey == NULL) {
+                WOLFSSL_MSG("Memory error");
+                return WOLFSSL_FAILURE;
+            }
+            XMEMSET(rawKey, 0, rawLen);
+            mp_to_unsigned_bin(rsaElem, rawKey);
+            if ((word32)rawLen <= sizeof(word32)) {
+                idx = *(word32*)rawKey;
+                #ifdef BIG_ENDIAN_ORDER
+                    idx = ByteReverseWord32(idx);
+                #endif
+            }
+            XSNPRINTF(tmp, sizeof(tmp) - 1, "\nExponent: %d (0x%x)", idx, idx);
+            if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                return WOLFSSL_FAILURE;
+            }
+            XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        }
+        else {
+            XSNPRINTF(tmp, sizeof(tmp) - 1, "\n%s\n    ", rsaStr[i]);
+            tmp[sizeof(tmp) - 1] = '\0';
+            if (mp_leading_bit(rsaElem)) {
+                lbit = 1;
+                XSTRNCAT(tmp, "00", 3);
+            }
+
+            rawLen = mp_unsigned_bin_size(rsaElem);
+            rawKey = (byte*)XMALLOC(rawLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            if (rawKey == NULL) {
+                WOLFSSL_MSG("Memory error");
+                return WOLFSSL_FAILURE;
+            }
+            mp_to_unsigned_bin(rsaElem, rawKey);
+            for (idx = 0; idx < (word32)rawLen; idx++) {
+                char val[5];
+                int  valSz = 5;
+
+                if ((idx == 0) && !lbit) {
+                    XSNPRINTF(val, valSz - 1, "%02x", rawKey[idx]);
+                }
+                else if ((idx != 0) && (((idx + lbit) % 15) == 0)) {
+                    tmp[sizeof(tmp) - 1] = '\0';
+                    if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                        XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                        return WOLFSSL_FAILURE;
+                    }
+                    XSNPRINTF(tmp, sizeof(tmp) - 1,
+                            ":\n    ");
+                    XSNPRINTF(val, valSz - 1, "%02x", rawKey[idx]);
+                }
+                else {
+                    XSNPRINTF(val, valSz - 1, ":%02x", rawKey[idx]);
+                }
+                XSTRNCAT(tmp, val, valSz);
+            }
+            XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+            /* print out remaining values */
+            if ((idx > 0) && (((idx - 1 + lbit) % 15) != 0)) {
+                tmp[sizeof(tmp) - 1] = '\0';
+                if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                    return WOLFSSL_FAILURE;
+                }
+            }
+            lbit = 0;
+        }
+
+    }
+    /* done with print out */
+    if (wolfSSL_BIO_write(bio, "\n\0", (int)XSTRLEN("\n\0")) <= 0) {
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* XSNPRINTF */
+
+#if !defined(NO_FILESYSTEM)
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_RSA *wolfSSL_PEM_read_RSAPublicKey(XFILE fp, WOLFSSL_RSA **x,
+                                           pem_password_cb *cb, void *u)
+{
+    (void)fp;
+    (void)x;
+    (void)cb;
+    (void)u;
+    WOLFSSL_STUB("PEM_read_RSAPublicKey");
+    WOLFSSL_MSG("wolfSSL_PEM_read_RSAPublicKey not implemented");
+
+    return NULL;
+}
+#endif
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_PEM_write_RSAPublicKey(XFILE fp, WOLFSSL_RSA *x)
+{
+    (void)fp;
+    (void)x;
+    WOLFSSL_STUB("PEM_write_RSAPublicKey");
+    WOLFSSL_MSG("wolfSSL_PEM_write_RSAPublicKey not implemented");
+
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_PEM_write_RSA_PUBKEY(XFILE fp, WOLFSSL_RSA *x)
+{
+    (void)fp;
+    (void)x;
+    WOLFSSL_STUB("PEM_write_RSA_PUBKEY");
+    WOLFSSL_MSG("wolfSSL_PEM_write_RSA_PUBKEY not implemented");
+
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+#endif /* NO_FILESYSTEM */
+
+WOLFSSL_RSA *wolfSSL_d2i_RSAPublicKey(WOLFSSL_RSA **r, const unsigned char **pp,
+    long len)
+{
+    WOLFSSL_RSA *rsa = NULL;
+
+    WOLFSSL_ENTER("d2i_RSAPublicKey");
+
+    if (pp == NULL) {
+        WOLFSSL_MSG("Bad argument");
+        return NULL;
+    }
+    if ((rsa = wolfSSL_RSA_new()) == NULL) {
+        WOLFSSL_MSG("RSA_new failed");
+        return NULL;
+    }
+
+    if (wolfSSL_RSA_LoadDer_ex(rsa, *pp, (int)len, WOLFSSL_RSA_LOAD_PUBLIC)
+                                                         != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("RSA_LoadDer failed");
+        wolfSSL_RSA_free(rsa);
+        rsa = NULL;
+    }
+    if (r != NULL)
+        *r = rsa;
+
+    return rsa;
+}
+
+/* Converts an RSA private key from DER format to an RSA structure.
+Returns pointer to the RSA structure on success and NULL if error. */
+WOLFSSL_RSA *wolfSSL_d2i_RSAPrivateKey(WOLFSSL_RSA **r,
+                                       const unsigned char **derBuf, long derSz)
+{
+    WOLFSSL_RSA *rsa = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_d2i_RSAPrivateKey");
+
+    /* check for bad functions arguments */
+    if (derBuf == NULL) {
+        WOLFSSL_MSG("Bad argument");
+        return NULL;
+    }
+    if ((rsa = wolfSSL_RSA_new()) == NULL) {
+        WOLFSSL_MSG("RSA_new failed");
+        return NULL;
+    }
+
+    if (wolfSSL_RSA_LoadDer_ex(rsa, *derBuf, (int)derSz,
+                                 WOLFSSL_RSA_LOAD_PRIVATE) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("RSA_LoadDer failed");
+        wolfSSL_RSA_free(rsa);
+        rsa = NULL;
+    }
+    if (r != NULL)
+        *r = rsa;
+
+    return rsa;
+}
+
+#if !defined(HAVE_FAST_RSA) && defined(WOLFSSL_KEY_GEN) && \
+    !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+/* Converts an internal RSA structure to DER format.
+ * If "pp" is null then buffer size only is returned.
+ * If "*pp" is null then a created buffer is set in *pp and the caller is
+ *  responsible for free'ing it.
+ * Returns size of DER on success and WOLFSSL_FAILURE if error
+ */
+int wolfSSL_i2d_RSAPrivateKey(WOLFSSL_RSA *rsa, unsigned char **pp)
+{
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_i2d_RSAPrivateKey");
+
+    /* check for bad functions arguments */
+    if (rsa == NULL) {
+        WOLFSSL_MSG("Bad Function Arguments");
+        return BAD_FUNC_ARG;
+    }
+
+    if ((ret = wolfSSL_RSA_To_Der(rsa, pp, 0)) < 0) {
+        WOLFSSL_MSG("wolfSSL_RSA_To_Der failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    return ret; /* returns size of DER if successful */
+}
+
+
+int wolfSSL_i2d_RSAPublicKey(WOLFSSL_RSA *rsa, const unsigned char **pp)
+{
+    int ret;
+
+    /* check for bad functions arguments */
+    if (rsa == NULL) {
+        WOLFSSL_MSG("Bad Function Arguments");
+        return BAD_FUNC_ARG;
+    }
+
+    if ((ret = wolfSSL_RSA_To_Der(rsa, (byte**)pp, 1)) < 0) {
+        WOLFSSL_MSG("wolfSSL_RSA_To_Der failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    return ret;
+}
+#endif /* !defined(HAVE_FAST_RSA) && defined(WOLFSSL_KEY_GEN) && \
+        * !defined(NO_RSA) && !defined(HAVE_USER_RSA) */
+
+#endif /* !NO_RSA */
+#endif /* OPENSSL_EXTRA */
+
+#if !defined(NO_RSA) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
+/* return WOLFSSL_SUCCESS if success, WOLFSSL_FATAL_ERROR if error */
+int wolfSSL_RSA_LoadDer(WOLFSSL_RSA* rsa, const unsigned char* derBuf, int derSz)
+{
+  return wolfSSL_RSA_LoadDer_ex(rsa, derBuf, derSz, WOLFSSL_RSA_LOAD_PRIVATE);
+}
+
+
+int wolfSSL_RSA_LoadDer_ex(WOLFSSL_RSA* rsa, const unsigned char* derBuf,
+                                                     int derSz, int opt)
+{
+
+    word32 idx = 0;
+    int    ret;
+
+    WOLFSSL_ENTER("wolfSSL_RSA_LoadDer");
+
+    if (rsa == NULL || rsa->internal == NULL || derBuf == NULL || derSz <= 0) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (opt == WOLFSSL_RSA_LOAD_PRIVATE) {
+        ret = wc_RsaPrivateKeyDecode(derBuf, &idx, (RsaKey*)rsa->internal, derSz);
+    }
+    else {
+        ret = wc_RsaPublicKeyDecode(derBuf, &idx, (RsaKey*)rsa->internal, derSz);
+    }
+
+    if (ret < 0) {
+        if (opt == WOLFSSL_RSA_LOAD_PRIVATE) {
+             WOLFSSL_MSG("RsaPrivateKeyDecode failed");
+        }
+        else {
+             WOLFSSL_MSG("RsaPublicKeyDecode failed");
+        }
+        return SSL_FATAL_ERROR;
+    }
+
+    if (SetRsaExternal(rsa) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("SetRsaExternal failed");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    rsa->inSet = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+#if defined(WC_RSA_PSS) && (defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || \
+        defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX))
+static int hash2mgf(enum wc_HashType hType)
+{
+    switch (hType) {
+#ifndef NO_SHA
+    case WC_HASH_TYPE_SHA:
+        return WC_MGF1SHA1;
+#endif
+#ifndef NO_SHA256
+#ifdef WOLFSSL_SHA224
+    case WC_HASH_TYPE_SHA224:
+        return WC_MGF1SHA224;
+#endif
+    case WC_HASH_TYPE_SHA256:
+        return WC_MGF1SHA256;
+#endif
+#ifdef WOLFSSL_SHA384
+    case WC_HASH_TYPE_SHA384:
+        return WC_MGF1SHA384;
+#endif
+#ifdef WOLFSSL_SHA512
+    case WC_HASH_TYPE_SHA512:
+        return WC_MGF1SHA512;
+#endif
+    case WC_HASH_TYPE_NONE:
+    case WC_HASH_TYPE_MD2:
+    case WC_HASH_TYPE_MD4:
+    case WC_HASH_TYPE_MD5:
+    case WC_HASH_TYPE_MD5_SHA:
+    case WC_HASH_TYPE_SHA3_224:
+    case WC_HASH_TYPE_SHA3_256:
+    case WC_HASH_TYPE_SHA3_384:
+    case WC_HASH_TYPE_SHA3_512:
+    case WC_HASH_TYPE_BLAKE2B:
+    case WC_HASH_TYPE_BLAKE2S:
+    default:
+        WOLFSSL_MSG("Unrecognized or unsupported hash function");
+        return WC_MGF1NONE;
+    }
+}
+
+/*
+ *                                +-----------+
+ *                                |     M     |
+ *                                +-----------+
+ *                                      |
+ *                                      V
+ *                                    Hash
+ *                                      |
+ *                                      V
+ *                        +--------+----------+----------+
+ *                   M' = |Padding1|  mHash   |   salt   |
+ *                        +--------+----------+----------+
+ *                                       |
+ *             +--------+----------+     V
+ *       DB =  |Padding2|maskedseed|   Hash
+ *             +--------+----------+     |
+ *                       |               |
+ *                       V               |    +--+
+ *                      xor <--- MGF <---|    |bc|
+ *                       |               |    +--+
+ *                       |               |      |
+ *                       V               V      V
+ *             +-------------------+----------+--+
+ *       EM =  |    maskedDB       |maskedseed|bc|
+ *             +-------------------+----------+--+
+ * Diagram taken from https://tools.ietf.org/html/rfc3447#section-9.1
+ */
+int wolfSSL_RSA_padding_add_PKCS1_PSS(WOLFSSL_RSA *rsa, unsigned char *EM,
+                                      const unsigned char *mHash,
+                                      const WOLFSSL_EVP_MD *hashAlg, int saltLen)
+{
+    int hashLen, emLen, mgf;
+    int ret = WOLFSSL_FAILURE;
+    int initTmpRng = 0;
+    WC_RNG *rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG* tmpRNG = NULL;
+#else
+    WC_RNG  _tmpRNG[1];
+    WC_RNG* tmpRNG = _tmpRNG;
+#endif
+    enum wc_HashType hashType;
+
+    WOLFSSL_ENTER("wolfSSL_RSA_padding_add_PKCS1_PSS");
+
+    if (!rsa || !EM || !mHash || !hashAlg) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if (!(rng = WOLFSSL_RSA_GetRNG(rsa, (WC_RNG**)&tmpRNG, &initTmpRng))) {
+        WOLFSSL_MSG("WOLFSSL_RSA_GetRNG error");
+        goto cleanup;
+    }
+
+    if (!rsa->exSet && SetRsaExternal(rsa) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("SetRsaExternal error");
+        goto cleanup;
+    }
+
+    hashType = wolfSSL_EVP_md2macType(hashAlg);
+    if (hashType < WC_HASH_TYPE_NONE || hashType > WC_HASH_TYPE_MAX) {
+        WOLFSSL_MSG("wolfSSL_EVP_md2macType error");
+        goto cleanup;
+    }
+
+   if ((mgf = hash2mgf(hashType)) == WC_MGF1NONE) {
+       WOLFSSL_MSG("hash2mgf error");
+       goto cleanup;
+   }
+
+    if ((hashLen = wolfSSL_EVP_MD_size(hashAlg)) < 0) {
+        WOLFSSL_MSG("wolfSSL_EVP_MD_size error");
+        goto cleanup;
+    }
+
+    if ((emLen = wolfSSL_RSA_size(rsa)) <= 0) {
+        WOLFSSL_MSG("wolfSSL_RSA_size error");
+        goto cleanup;
+    }
+
+    switch (saltLen) {
+    /* Negative saltLen values are treated differently */
+        case RSA_PSS_SALTLEN_DIGEST:
+            saltLen = hashLen;
+            break;
+        case RSA_PSS_SALTLEN_MAX_SIGN:
+        case RSA_PSS_SALTLEN_MAX:
+            saltLen = emLen - hashLen - 2;
+            break;
+        default:
+            if (saltLen < 0) {
+                /* Not any currently implemented negative value */
+                WOLFSSL_MSG("invalid saltLen");
+                goto cleanup;
+            }
+    }
+
+    if (wc_RsaPad_ex(mHash, wolfSSL_EVP_MD_size(hashAlg), EM, emLen,
+                     RSA_BLOCK_TYPE_1, rng, WC_RSA_PSS_PAD,
+                     wolfSSL_EVP_md2macType(hashAlg), mgf, NULL, 0, saltLen,
+                     wolfSSL_BN_num_bits(rsa->n), NULL) != MP_OKAY) {
+        WOLFSSL_MSG("wc_RsaPad_ex error");
+        goto cleanup;
+    }
+
+    ret = WOLFSSL_SUCCESS;
+cleanup:
+    if (initTmpRng)
+        wc_FreeRng(tmpRNG);
+#ifdef WOLFSSL_SMALL_STACK
+    if (tmpRNG)
+        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return ret;
+}
+
+/*
+ * Refer to wolfSSL_RSA_padding_add_PKCS1_PSS
+ * for an explanation of the parameters.
+ */
+int wolfSSL_RSA_verify_PKCS1_PSS(WOLFSSL_RSA *rsa, const unsigned char *mHash,
+                                 const WOLFSSL_EVP_MD *hashAlg,
+                                 const unsigned char *EM, int saltLen)
+{
+    int hashLen, mgf, emLen, mPrimeLen;
+    enum wc_HashType hashType;
+    byte *mPrime = NULL;
+    byte *buf = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_RSA_verify_PKCS1_PSS");
+
+    if (!rsa || !mHash || !hashAlg || !EM) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if ((hashLen = wolfSSL_EVP_MD_size(hashAlg)) < 0) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if ((emLen = wolfSSL_RSA_size(rsa)) <= 0) {
+        WOLFSSL_MSG("wolfSSL_RSA_size error");
+        return WOLFSSL_FAILURE;
+    }
+
+    switch (saltLen) {
+    /* Negative saltLen values are treated differently */
+        case RSA_PSS_SALTLEN_DIGEST:
+            saltLen = hashLen;
+            break;
+        case RSA_PSS_SALTLEN_MAX_SIGN:
+        case RSA_PSS_SALTLEN_MAX:
+            saltLen = emLen - hashLen - 2;
+            break;
+        default:
+            if (saltLen < 0) {
+                /* Not any currently implemented negative value */
+                WOLFSSL_MSG("invalid saltLen");
+                return WOLFSSL_FAILURE;
+            }
+    }
+
+    if (!rsa->exSet && SetRsaExternal(rsa) != WOLFSSL_SUCCESS) {
+        return WOLFSSL_FAILURE;
+    }
+
+    hashType = wolfSSL_EVP_md2macType(hashAlg);
+    if (hashType < WC_HASH_TYPE_NONE || hashType > WC_HASH_TYPE_MAX) {
+        WOLFSSL_MSG("wolfSSL_EVP_md2macType error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if ((mgf = hash2mgf(hashType)) == WC_MGF1NONE) {
+        WOLFSSL_MSG("hash2mgf error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if ((hashLen = wolfSSL_EVP_MD_size(hashAlg)) < 0) {
+        WOLFSSL_MSG("wolfSSL_EVP_MD_size error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (!(buf = (byte*)XMALLOC(emLen, NULL, DYNAMIC_TYPE_TMP_BUFFER))) {
+        WOLFSSL_MSG("malloc error");
+        return WOLFSSL_FAILURE;
+    }
+    XMEMCPY(buf, EM, emLen);
+
+    /* Remove and verify the PSS padding */
+    if ((mPrimeLen = wc_RsaUnPad_ex(buf, emLen, &mPrime,
+                                    RSA_BLOCK_TYPE_1, WC_RSA_PSS_PAD, hashType,
+                                    mgf, NULL, 0, saltLen,
+                                    wolfSSL_BN_num_bits(rsa->n), NULL)) < 0) {
+        WOLFSSL_MSG("wc_RsaPad_ex error");
+        XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* Verify the hash is correct */
+    if (wc_RsaPSS_CheckPadding_ex(mHash, hashLen, mPrime, mPrimeLen, hashType,
+                                  saltLen, wolfSSL_BN_num_bits(rsa->n))
+                                  != MP_OKAY) {
+        WOLFSSL_MSG("wc_RsaPSS_CheckPadding_ex error");
+        XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_FAILURE;
+    }
+    XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    return WOLFSSL_SUCCESS;
+}
+#endif
+
+#if defined(OPENSSL_EXTRA)
+WOLFSSL_RSA_METHOD *wolfSSL_RSA_meth_new(const char *name, int flags)
+{
+    int name_len;
+    WOLFSSL_RSA_METHOD* meth;
+
+    if (name == NULL) {
+        return NULL;
+    }
+
+    meth = (WOLFSSL_RSA_METHOD*)XMALLOC(sizeof(WOLFSSL_RSA_METHOD), NULL,
+        DYNAMIC_TYPE_OPENSSL);
+    name_len = (int)XSTRLEN(name);
+    if (!meth) {
+        return NULL;
+    }
+    meth->flags = flags;
+    meth->name = (char*)XMALLOC(name_len+1, NULL, DYNAMIC_TYPE_OPENSSL);
+    if (!meth->name) {
+        XFREE(meth, NULL, DYNAMIC_TYPE_OPENSSL);
+        return NULL;
+    }
+    XMEMCPY(meth->name, name, name_len+1);
+
+    return meth;
+}
+
+void wolfSSL_RSA_meth_free(WOLFSSL_RSA_METHOD *meth)
+{
+    if (meth) {
+        XFREE(meth->name, NULL, DYNAMIC_TYPE_OPENSSL);
+        XFREE(meth, NULL, DYNAMIC_TYPE_OPENSSL);
+    }
+}
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_RSA_meth_set(WOLFSSL_RSA_METHOD *rsa, void* p)
+{
+    (void)rsa;
+    (void)p;
+    WOLFSSL_STUB("RSA_METHOD is not implemented.");
+    return 1;
+}
+#endif
+
+int wolfSSL_RSA_set_method(WOLFSSL_RSA *rsa, WOLFSSL_RSA_METHOD *meth)
+{
+    if (rsa)
+        rsa->meth = meth;
+    return 1;
+}
+
+const WOLFSSL_RSA_METHOD* wolfSSL_RSA_get_method(const WOLFSSL_RSA *rsa)
+{
+    if (!rsa) {
+        return NULL;
+    }
+    return rsa->meth;
+}
+
+const WOLFSSL_RSA_METHOD* wolfSSL_RSA_get_default_method(void)
+{
+    return wolfSSL_RSA_meth_new("wolfSSL RSA", 0);
+}
+
+int wolfSSL_RSA_flags(const WOLFSSL_RSA *r)
+{
+    if (r && r->meth) {
+        return r->meth->flags;
+    } else {
+        return 0;
+    }
+}
+
+void wolfSSL_RSA_set_flags(WOLFSSL_RSA *r, int flags)
+{
+    if (r && r->meth) {
+        r->meth->flags = flags;
+    }
+}
+
+#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+WOLFSSL_RSA* wolfSSL_RSAPublicKey_dup(WOLFSSL_RSA *rsa)
+{
+    int derSz = 0;
+    byte *derBuf = NULL;
+    WOLFSSL_RSA* local;
+
+    WOLFSSL_ENTER("wolfSSL_RSAPublicKey_dup");
+
+    if (!rsa) {
+        return NULL;
+    }
+
+    local = wolfSSL_RSA_new();
+    if (local == NULL) {
+        WOLFSSL_MSG("Error creating a new WOLFSSL_RSA structure");
+        return NULL;
+    }
+
+    if ((derSz = wolfSSL_RSA_To_Der(rsa, &derBuf, 1)) < 0) {
+        WOLFSSL_MSG("wolfSSL_RSA_To_Der failed");
+        return NULL;
+    }
+
+    if (wolfSSL_RSA_LoadDer_ex(local,
+                derBuf, derSz,
+                WOLFSSL_RSA_LOAD_PUBLIC) != SSL_SUCCESS) {
+        wolfSSL_RSA_free(local);
+        local = NULL;
+    }
+    XFREE(derBuf, NULL, DYNAMIC_TYPE_ASN1);
+    return local;
+}
+#endif
+
+void* wolfSSL_RSA_get_ex_data(const WOLFSSL_RSA *rsa, int idx)
+{
+    WOLFSSL_ENTER("wolfSSL_RSA_get_ex_data");
+#ifdef HAVE_EX_DATA
+    if (rsa) {
+        return wolfSSL_CRYPTO_get_ex_data(&rsa->ex_data, idx);
+    }
+#else
+    (void)rsa;
+    (void)idx;
+#endif
+    return NULL;
+}
+
+int wolfSSL_RSA_set_ex_data(WOLFSSL_RSA *rsa, int idx, void *data)
+{
+    WOLFSSL_ENTER("wolfSSL_RSA_set_ex_data");
+    #ifdef HAVE_EX_DATA
+    if (rsa) {
+        return wolfSSL_CRYPTO_set_ex_data(&rsa->ex_data, idx, data);
+    }
+    #else
+    (void)rsa;
+    (void)idx;
+    (void)data;
+    #endif
+    return WOLFSSL_FAILURE;
+}
+
+int wolfSSL_RSA_set0_key(WOLFSSL_RSA *r, WOLFSSL_BIGNUM *n, WOLFSSL_BIGNUM *e,
+                         WOLFSSL_BIGNUM *d)
+{
+    /* If the fields n and e in r are NULL, the corresponding input
+     * parameters MUST be non-NULL for n and e.  d may be
+     * left NULL (in case only the public key is used).
+     */
+    if ((!r->n && !n) || (!r->e && !e))
+        return 0;
+
+    if (n) {
+        wolfSSL_BN_free(r->n);
+        r->n = n;
+    }
+    if (e) {
+        wolfSSL_BN_free(r->e);
+        r->e = e;
+    }
+    if (d) {
+        wolfSSL_BN_clear_free(r->d);
+        r->d = d;
+    }
+
+    return 1;
+}
+#endif /* OPENSSL_EXTRA */
+#endif /* NO_RSA */
+
+#ifdef OPENSSL_EXTRA
+#ifndef NO_DSA
+/* return WOLFSSL_SUCCESS if success, WOLFSSL_FATAL_ERROR if error */
+int wolfSSL_DSA_LoadDer(WOLFSSL_DSA* dsa, const unsigned char* derBuf, int derSz)
+{
+    word32 idx = 0;
+    int    ret;
+
+    WOLFSSL_ENTER("wolfSSL_DSA_LoadDer");
+
+    if (dsa == NULL || dsa->internal == NULL || derBuf == NULL || derSz <= 0) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    ret = DsaPrivateKeyDecode(derBuf, &idx, (DsaKey*)dsa->internal, derSz);
+    if (ret < 0) {
+        WOLFSSL_MSG("DsaPrivateKeyDecode failed");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (SetDsaExternal(dsa) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("SetDsaExternal failed");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    dsa->inSet = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* Loads DSA key from DER buffer. opt = DSA_LOAD_PRIVATE or DSA_LOAD_PUBLIC.
+    returns 1 on success, or 0 on failure.  */
+int wolfSSL_DSA_LoadDer_ex(WOLFSSL_DSA* dsa, const unsigned char* derBuf,
+                                                            int derSz, int opt)
+{
+    word32 idx = 0;
+    int    ret;
+
+    WOLFSSL_ENTER("wolfSSL_DSA_LoadDer");
+
+    if (dsa == NULL || dsa->internal == NULL || derBuf == NULL || derSz <= 0) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (opt == WOLFSSL_DSA_LOAD_PRIVATE) {
+        ret = DsaPrivateKeyDecode(derBuf, &idx, (DsaKey*)dsa->internal, derSz);
+    }
+    else {
+        ret = DsaPublicKeyDecode(derBuf, &idx, (DsaKey*)dsa->internal, derSz);
+    }
+
+    if (ret < 0 && opt == WOLFSSL_DSA_LOAD_PRIVATE) {
+        WOLFSSL_MSG("DsaPrivateKeyDecode failed");
+        return WOLFSSL_FATAL_ERROR;
+    }
+    else if (ret < 0 && opt == WOLFSSL_DSA_LOAD_PUBLIC) {
+        WOLFSSL_MSG("DsaPublicKeyDecode failed");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (SetDsaExternal(dsa) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("SetDsaExternal failed");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    dsa->inSet = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* !NO_DSA */
+
+#ifdef HAVE_ECC
+/* return WOLFSSL_SUCCESS if success, WOLFSSL_FATAL_ERROR if error */
+int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key, const unsigned char* derBuf,
+                           int derSz)
+{
+    return wolfSSL_EC_KEY_LoadDer_ex(key, derBuf, derSz,
+                                     WOLFSSL_EC_KEY_LOAD_PRIVATE);
+}
+
+int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf,
+                              int derSz, int opt)
+{
+    word32 idx = 0;
+    int    ret;
+
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_LoadDer");
+
+    if (key == NULL || key->internal == NULL || derBuf == NULL || derSz <= 0) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) {
+        ret = wc_EccPrivateKeyDecode(derBuf, &idx, (ecc_key*)key->internal,
+                                     derSz);
+    }
+    else {
+        ret = wc_EccPublicKeyDecode(derBuf, &idx, (ecc_key*)key->internal,
+                                    derSz);
+    }
+    if (ret < 0) {
+        if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) {
+            WOLFSSL_MSG("wc_EccPrivateKeyDecode failed");
+        }
+        else {
+            WOLFSSL_MSG("wc_EccPublicKeyDecode failed");
+        }
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (SetECKeyExternal(key) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("SetECKeyExternal failed");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    key->inSet = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* HAVE_ECC */
+
+#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH))
+/* return WOLFSSL_SUCCESS if success, WOLFSSL_FATAL_ERROR if error */
+int wolfSSL_DH_LoadDer(WOLFSSL_DH* dh, const unsigned char* derBuf, int derSz)
+{
+    word32 idx = 0;
+    int    ret;
+
+    if (dh == NULL || dh->internal == NULL || derBuf == NULL || derSz <= 0) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    ret = wc_DhKeyDecode(derBuf, &idx, (DhKey*)dh->internal, (word32)derSz);
+    if (ret < 0) {
+        WOLFSSL_MSG("wc_DhKeyDecode failed");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (SetDhExternal(dh) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("SetDhExternal failed");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* ! NO_DH && WOLFSSL_QT || OPENSSL_ALL */
+
+#endif /* OPENSSL_EXTRA */
+
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
+
+/* increments ref count of WOLFSSL_RSA. Return 1 on success, 0 on error */
+int wolfSSL_RSA_up_ref(WOLFSSL_RSA* rsa)
+{
+    if (rsa) {
+        if (wc_LockMutex(&rsa->refMutex) != 0) {
+            WOLFSSL_MSG("Failed to lock x509 mutex");
+        }
+        rsa->refCount++;
+        wc_UnLockMutex(&rsa->refMutex);
+
+        return 1;
+    }
+
+    return 0;
+}
+
+/* increments ref count of WOLFSSL_X509. Return 1 on success, 0 on error */
+int wolfSSL_X509_up_ref(WOLFSSL_X509* x509)
+{
+    if (x509) {
+        if (wc_LockMutex(&x509->refMutex) != 0) {
+            WOLFSSL_MSG("Failed to lock x509 mutex");
+        }
+        x509->refCount++;
+        wc_UnLockMutex(&x509->refMutex);
+
+        return 1;
+    }
+
+    return 0;
+}
+
+#endif /* OPENSSL_EXTRA || OPENSSL_ALL */
+
+
+#ifdef WOLFSSL_ALT_CERT_CHAINS
+int wolfSSL_is_peer_alt_cert_chain(const WOLFSSL* ssl)
+{
+    int isUsing = 0;
+    if (ssl)
+        isUsing = ssl->options.usingAltCertChain;
+    return isUsing;
+}
+#endif /* WOLFSSL_ALT_CERT_CHAINS */
+
+
+#ifdef SESSION_CERTS
+
+#ifdef WOLFSSL_ALT_CERT_CHAINS
+/* Get peer's alternate certificate chain */
+WOLFSSL_X509_CHAIN* wolfSSL_get_peer_alt_chain(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_get_peer_alt_chain");
+    if (ssl)
+        return &ssl->session.altChain;
+
+    return 0;
+}
+#endif /* WOLFSSL_ALT_CERT_CHAINS */
+
+
+/* Get peer's certificate chain */
+WOLFSSL_X509_CHAIN* wolfSSL_get_peer_chain(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_get_peer_chain");
+    if (ssl)
+        return &ssl->session.chain;
+
+    return 0;
+}
+
+
+/* Get peer's certificate chain total count */
+int wolfSSL_get_chain_count(WOLFSSL_X509_CHAIN* chain)
+{
+    WOLFSSL_ENTER("wolfSSL_get_chain_count");
+    if (chain)
+        return chain->count;
+
+    return 0;
+}
+
+
+/* Get peer's ASN.1 DER certificate at index (idx) length in bytes */
+int wolfSSL_get_chain_length(WOLFSSL_X509_CHAIN* chain, int idx)
+{
+    WOLFSSL_ENTER("wolfSSL_get_chain_length");
+    if (chain)
+        return chain->certs[idx].length;
+
+    return 0;
+}
+
+
+/* Get peer's ASN.1 DER certificate at index (idx) */
+byte* wolfSSL_get_chain_cert(WOLFSSL_X509_CHAIN* chain, int idx)
+{
+    WOLFSSL_ENTER("wolfSSL_get_chain_cert");
+    if (chain)
+        return chain->certs[idx].buffer;
+
+    return 0;
+}
+
+
+/* Get peer's wolfSSL X509 certificate at index (idx) */
+WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN* chain, int idx)
+{
+    int          ret;
+    WOLFSSL_X509* x509 = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    DecodedCert* cert = NULL;
+#else
+    DecodedCert  cert[1];
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_get_chain_X509");
+    if (chain != NULL) {
+    #ifdef WOLFSSL_SMALL_STACK
+        cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
+                                                       DYNAMIC_TYPE_DCERT);
+        if (cert != NULL)
+    #endif
+        {
+            InitDecodedCert(cert, chain->certs[idx].buffer,
+                                  chain->certs[idx].length, NULL);
+
+            if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL)) != 0) {
+                WOLFSSL_MSG("Failed to parse cert");
+            }
+            else {
+                x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL,
+                                                             DYNAMIC_TYPE_X509);
+                if (x509 == NULL) {
+                    WOLFSSL_MSG("Failed alloc X509");
+                }
+                else {
+                    InitX509(x509, 1, NULL);
+
+                    if ((ret = CopyDecodedToX509(x509, cert)) != 0) {
+                        WOLFSSL_MSG("Failed to copy decoded");
+                        wolfSSL_X509_free(x509);
+                        x509 = NULL;
+                    }
+                }
+            }
+
+            FreeDecodedCert(cert);
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
+        #endif
+        }
+    }
+    (void)ret;
+
+    return x509;
+}
+
+
+/* Get peer's PEM certificate at index (idx), output to buffer if inLen big
+   enough else return error (-1). If buffer is NULL only calculate
+   outLen. Output length is in *outLen WOLFSSL_SUCCESS on ok */
+int  wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN* chain, int idx,
+                               unsigned char* buf, int inLen, int* outLen)
+{
+#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
+    const char* header = NULL;
+    const char* footer = NULL;
+    int headerLen;
+    int footerLen;
+    int i;
+    int err;
+    word32 szNeeded = 0;
+
+    WOLFSSL_ENTER("wolfSSL_get_chain_cert_pem");
+    if (!chain || !outLen || idx < 0 || idx >= wolfSSL_get_chain_count(chain))
+        return BAD_FUNC_ARG;
+
+    err = wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer);
+    if (err != 0)
+        return err;
+
+    headerLen = (int)XSTRLEN(header);
+    footerLen = (int)XSTRLEN(footer);
+
+    /* Null output buffer return size needed in outLen */
+    if(!buf) {
+        if(Base64_Encode(chain->certs[idx].buffer, chain->certs[idx].length,
+                    NULL, &szNeeded) != LENGTH_ONLY_E)
+            return WOLFSSL_FAILURE;
+        *outLen = szNeeded + headerLen + footerLen;
+        return LENGTH_ONLY_E;
+    }
+
+    /* don't even try if inLen too short */
+    if (inLen < headerLen + footerLen + chain->certs[idx].length)
+        return BAD_FUNC_ARG;
+
+    /* header */
+    if (XMEMCPY(buf, header, headerLen) == NULL)
+        return WOLFSSL_FATAL_ERROR;
+
+    i = headerLen;
+
+    /* body */
+    *outLen = inLen;  /* input to Base64_Encode */
+    if ( (err = Base64_Encode(chain->certs[idx].buffer,
+                       chain->certs[idx].length, buf + i, (word32*)outLen)) < 0)
+        return err;
+    i += *outLen;
+
+    /* footer */
+    if ( (i + footerLen) > inLen)
+        return BAD_FUNC_ARG;
+    if (XMEMCPY(buf + i, footer, footerLen) == NULL)
+        return WOLFSSL_FATAL_ERROR;
+    *outLen += headerLen + footerLen;
+
+    return WOLFSSL_SUCCESS;
+#else
+    (void)chain;
+    (void)idx;
+    (void)buf;
+    (void)inLen;
+    (void)outLen;
+    return WOLFSSL_FAILURE;
+#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
+}
+
+
+/* get session ID */
+WOLFSSL_ABI
+const byte* wolfSSL_get_sessionID(const WOLFSSL_SESSION* session)
+{
+    WOLFSSL_ENTER("wolfSSL_get_sessionID");
+    if (session)
+        return session->sessionID;
+
+    return NULL;
+}
+
+
+#endif /* SESSION_CERTS */
+
+#ifdef HAVE_FUZZER
+void wolfSSL_SetFuzzerCb(WOLFSSL* ssl, CallbackFuzzer cbf, void* fCtx)
+{
+    if (ssl) {
+        ssl->fuzzerCb  = cbf;
+        ssl->fuzzerCtx = fCtx;
+    }
+}
+#endif
+
+#ifndef NO_CERTS
+#ifdef  HAVE_PK_CALLBACKS
+
+#ifdef HAVE_ECC
+void  wolfSSL_CTX_SetEccKeyGenCb(WOLFSSL_CTX* ctx, CallbackEccKeyGen cb)
+{
+    if (ctx)
+        ctx->EccKeyGenCb = cb;
+}
+void  wolfSSL_SetEccKeyGenCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->EccKeyGenCtx = ctx;
+}
+void* wolfSSL_GetEccKeyGenCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->EccKeyGenCtx;
+
+    return NULL;
+}
+
+WOLFSSL_ABI
+void  wolfSSL_CTX_SetEccSignCb(WOLFSSL_CTX* ctx, CallbackEccSign cb)
+{
+    if (ctx)
+        ctx->EccSignCb = cb;
+}
+void  wolfSSL_SetEccSignCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->EccSignCtx = ctx;
+}
+void* wolfSSL_GetEccSignCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->EccSignCtx;
+
+    return NULL;
+}
+
+void  wolfSSL_CTX_SetEccVerifyCb(WOLFSSL_CTX* ctx, CallbackEccVerify cb)
+{
+    if (ctx)
+        ctx->EccVerifyCb = cb;
+}
+void  wolfSSL_SetEccVerifyCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->EccVerifyCtx = ctx;
+}
+void* wolfSSL_GetEccVerifyCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->EccVerifyCtx;
+
+    return NULL;
+}
+
+void wolfSSL_CTX_SetEccSharedSecretCb(WOLFSSL_CTX* ctx, CallbackEccSharedSecret cb)
+{
+    if (ctx)
+        ctx->EccSharedSecretCb = cb;
+}
+void  wolfSSL_SetEccSharedSecretCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->EccSharedSecretCtx = ctx;
+}
+void* wolfSSL_GetEccSharedSecretCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->EccSharedSecretCtx;
+
+    return NULL;
+}
+#endif /* HAVE_ECC */
+
+#ifdef HAVE_ED25519
+void  wolfSSL_CTX_SetEd25519SignCb(WOLFSSL_CTX* ctx, CallbackEd25519Sign cb)
+{
+    if (ctx)
+        ctx->Ed25519SignCb = cb;
+}
+void  wolfSSL_SetEd25519SignCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->Ed25519SignCtx = ctx;
+}
+void* wolfSSL_GetEd25519SignCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->Ed25519SignCtx;
+
+    return NULL;
+}
+
+void  wolfSSL_CTX_SetEd25519VerifyCb(WOLFSSL_CTX* ctx, CallbackEd25519Verify cb)
+{
+    if (ctx)
+        ctx->Ed25519VerifyCb = cb;
+}
+void  wolfSSL_SetEd25519VerifyCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->Ed25519VerifyCtx = ctx;
+}
+void* wolfSSL_GetEd25519VerifyCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->Ed25519VerifyCtx;
+
+    return NULL;
+}
+#endif /* HAVE_ED25519 */
+
+#ifdef HAVE_CURVE25519
+void wolfSSL_CTX_SetX25519KeyGenCb(WOLFSSL_CTX* ctx,
+        CallbackX25519KeyGen cb)
+{
+    if (ctx)
+        ctx->X25519KeyGenCb = cb;
+}
+void  wolfSSL_SetX25519KeyGenCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->X25519KeyGenCtx = ctx;
+}
+void* wolfSSL_GetX25519KeyGenCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->X25519KeyGenCtx;
+
+    return NULL;
+}
+
+void wolfSSL_CTX_SetX25519SharedSecretCb(WOLFSSL_CTX* ctx,
+        CallbackX25519SharedSecret cb)
+{
+    if (ctx)
+        ctx->X25519SharedSecretCb = cb;
+}
+void  wolfSSL_SetX25519SharedSecretCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->X25519SharedSecretCtx = ctx;
+}
+void* wolfSSL_GetX25519SharedSecretCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->X25519SharedSecretCtx;
+
+    return NULL;
+}
+#endif /* HAVE_CURVE25519 */
+
+#ifdef HAVE_ED448
+void  wolfSSL_CTX_SetEd448SignCb(WOLFSSL_CTX* ctx, CallbackEd448Sign cb)
+{
+    if (ctx)
+        ctx->Ed448SignCb = cb;
+}
+void  wolfSSL_SetEd448SignCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->Ed448SignCtx = ctx;
+}
+void* wolfSSL_GetEd448SignCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->Ed448SignCtx;
+
+    return NULL;
+}
+
+void  wolfSSL_CTX_SetEd448VerifyCb(WOLFSSL_CTX* ctx, CallbackEd448Verify cb)
+{
+    if (ctx)
+        ctx->Ed448VerifyCb = cb;
+}
+void  wolfSSL_SetEd448VerifyCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->Ed448VerifyCtx = ctx;
+}
+void* wolfSSL_GetEd448VerifyCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->Ed448VerifyCtx;
+
+    return NULL;
+}
+#endif /* HAVE_ED448 */
+
+#ifdef HAVE_CURVE448
+void wolfSSL_CTX_SetX448KeyGenCb(WOLFSSL_CTX* ctx,
+        CallbackX448KeyGen cb)
+{
+    if (ctx)
+        ctx->X448KeyGenCb = cb;
+}
+void  wolfSSL_SetX448KeyGenCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->X448KeyGenCtx = ctx;
+}
+void* wolfSSL_GetX448KeyGenCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->X448KeyGenCtx;
+
+    return NULL;
+}
+
+void wolfSSL_CTX_SetX448SharedSecretCb(WOLFSSL_CTX* ctx,
+        CallbackX448SharedSecret cb)
+{
+    if (ctx)
+        ctx->X448SharedSecretCb = cb;
+}
+void  wolfSSL_SetX448SharedSecretCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->X448SharedSecretCtx = ctx;
+}
+void* wolfSSL_GetX448SharedSecretCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->X448SharedSecretCtx;
+
+    return NULL;
+}
+#endif /* HAVE_CURVE448 */
+
+#ifndef NO_RSA
+void  wolfSSL_CTX_SetRsaSignCb(WOLFSSL_CTX* ctx, CallbackRsaSign cb)
+{
+    if (ctx)
+        ctx->RsaSignCb = cb;
+}
+void  wolfSSL_CTX_SetRsaSignCheckCb(WOLFSSL_CTX* ctx, CallbackRsaVerify cb)
+{
+    if (ctx)
+        ctx->RsaSignCheckCb = cb;
+}
+void  wolfSSL_SetRsaSignCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->RsaSignCtx = ctx;
+}
+void* wolfSSL_GetRsaSignCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->RsaSignCtx;
+
+    return NULL;
+}
+
+
+void  wolfSSL_CTX_SetRsaVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaVerify cb)
+{
+    if (ctx)
+        ctx->RsaVerifyCb = cb;
+}
+void  wolfSSL_SetRsaVerifyCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->RsaVerifyCtx = ctx;
+}
+void* wolfSSL_GetRsaVerifyCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->RsaVerifyCtx;
+
+    return NULL;
+}
+
+#ifdef WC_RSA_PSS
+void  wolfSSL_CTX_SetRsaPssSignCb(WOLFSSL_CTX* ctx, CallbackRsaPssSign cb)
+{
+    if (ctx)
+        ctx->RsaPssSignCb = cb;
+}
+void  wolfSSL_CTX_SetRsaPssSignCheckCb(WOLFSSL_CTX* ctx, CallbackRsaPssVerify cb)
+{
+    if (ctx)
+        ctx->RsaPssSignCheckCb = cb;
+}
+void  wolfSSL_SetRsaPssSignCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->RsaPssSignCtx = ctx;
+}
+void* wolfSSL_GetRsaPssSignCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->RsaPssSignCtx;
+
+    return NULL;
+}
+
+void  wolfSSL_CTX_SetRsaPssVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaPssVerify cb)
+{
+    if (ctx)
+        ctx->RsaPssVerifyCb = cb;
+}
+void  wolfSSL_SetRsaPssVerifyCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->RsaPssVerifyCtx = ctx;
+}
+void* wolfSSL_GetRsaPssVerifyCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->RsaPssVerifyCtx;
+
+    return NULL;
+}
+#endif /* WC_RSA_PSS */
+
+void  wolfSSL_CTX_SetRsaEncCb(WOLFSSL_CTX* ctx, CallbackRsaEnc cb)
+{
+    if (ctx)
+        ctx->RsaEncCb = cb;
+}
+void  wolfSSL_SetRsaEncCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->RsaEncCtx = ctx;
+}
+void* wolfSSL_GetRsaEncCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->RsaEncCtx;
+
+    return NULL;
+}
+
+void  wolfSSL_CTX_SetRsaDecCb(WOLFSSL_CTX* ctx, CallbackRsaDec cb)
+{
+    if (ctx)
+        ctx->RsaDecCb = cb;
+}
+void  wolfSSL_SetRsaDecCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->RsaDecCtx = ctx;
+}
+void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->RsaDecCtx;
+
+    return NULL;
+}
+#endif /* NO_RSA */
+
+#endif /* HAVE_PK_CALLBACKS */
+#endif /* NO_CERTS */
+
+#if defined(HAVE_PK_CALLBACKS) && !defined(NO_DH)
+void wolfSSL_CTX_SetDhAgreeCb(WOLFSSL_CTX* ctx, CallbackDhAgree cb)
+{
+    if (ctx)
+        ctx->DhAgreeCb = cb;
+}
+void wolfSSL_SetDhAgreeCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->DhAgreeCtx = ctx;
+}
+void* wolfSSL_GetDhAgreeCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->DhAgreeCtx;
+
+    return NULL;
+}
+#endif /* HAVE_PK_CALLBACKS && !NO_DH */
+
+
+#ifdef WOLFSSL_HAVE_WOLFSCEP
+    /* Used by autoconf to see if wolfSCEP is available */
+    void wolfSSL_wolfSCEP(void) {}
+#endif
+
+
+#ifdef WOLFSSL_HAVE_CERT_SERVICE
+    /* Used by autoconf to see if cert service is available */
+    void wolfSSL_cert_service(void) {}
+#endif
+
+#ifdef OPENSSL_EXTRA
+    #ifndef NO_CERTS
+    void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME *name)
+    {
+        WOLFSSL_ENTER("wolfSSL_X509_NAME_free");
+        FreeX509Name(name, NULL);
+        XFREE(name, NULL, DYNAMIC_TYPE_X509);
+    }
+
+
+    /* Malloc's a new WOLFSSL_X509_NAME structure
+     *
+     * returns NULL on failure, otherwise returns a new structure.
+     */
+    WOLFSSL_X509_NAME* wolfSSL_X509_NAME_new(void)
+    {
+        WOLFSSL_X509_NAME* name;
+
+        WOLFSSL_ENTER("wolfSSL_X509_NAME_new");
+
+        name = (WOLFSSL_X509_NAME*)XMALLOC(sizeof(WOLFSSL_X509_NAME), NULL,
+                DYNAMIC_TYPE_X509);
+        if (name != NULL) {
+            InitX509Name(name, 1);
+        }
+        return name;
+    }
+
+    /* Creates a duplicate of a WOLFSSL_X509_NAME structure.
+       Returns a new WOLFSSL_X509_NAME structure or NULL on failure */
+    WOLFSSL_X509_NAME* wolfSSL_X509_NAME_dup(WOLFSSL_X509_NAME *name)
+    {
+        WOLFSSL_X509_NAME* dup = NULL;
+
+        WOLFSSL_ENTER("wolfSSL_X509_NAME_dup");
+
+        if (name == NULL) {
+            WOLFSSL_MSG("NULL parameter");
+            return NULL;
+        }
+
+        if (!(dup = wolfSSL_X509_NAME_new())) {
+            return NULL;
+        }
+
+        /* copy contents */
+        XMEMCPY(dup, name, sizeof(WOLFSSL_X509_NAME));
+        InitX509Name(dup, 1);
+        dup->sz = name->sz;
+
+        /* handle dynamic portions */
+        if (name->dynamicName) {
+            if (!(dup->name = (char*)XMALLOC(name->sz, 0,
+                                             DYNAMIC_TYPE_OPENSSL))) {
+                goto err;
+            }
+        }
+        XMEMCPY(dup->name, name->name, name->sz);
+    #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+        !defined(NO_ASN)
+        if (!(dup->fullName.fullName = (char*)XMALLOC(name->fullName.fullNameLen,
+                                                   0, DYNAMIC_TYPE_OPENSSL))) {
+            goto err;
+        }
+        XMEMCPY(dup->fullName.fullName, name->fullName.fullName,
+            name->fullName.fullNameLen);
+    #endif
+
+        return dup;
+
+    err:
+        if (dup) {
+            if (dup->dynamicName && dup->name) {
+                XFREE(dup->name, 0, DYNAMIC_TYPE_OPENSSL);
+                dup->name = NULL;
+            }
+        #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+            !defined(NO_ASN)
+            if (dup->fullName.fullName &&
+                dup->fullName.fullName != name->fullName.fullName) {
+                XFREE(dup->fullName.fullName, 0, DYNAMIC_TYPE_OPENSSL);
+                dup->fullName.fullName = NULL;
+            }
+        #endif
+            wolfSSL_X509_NAME_free(dup);
+        }
+        return NULL;
+    }
+
+#if defined(WOLFSSL_CERT_GEN)
+    /* helper function for CopyX509NameToCertName()
+     *
+     * returns WOLFSSL_SUCCESS on success
+     */
+    static int CopyX509NameEntry(char* out, int mx, char* in, int inLen)
+    {
+        if (inLen > mx) {
+            WOLFSSL_MSG("Name too long");
+            XMEMCPY(out, in, mx);
+        }
+        else {
+            XMEMCPY(out, in, inLen);
+            out[inLen] = '\0';
+        }
+
+        /* make sure is null terminated */
+        out[mx-1] = '\0';
+
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    /* Helper function to copy cert name from a WOLFSSL_X509_NAME structure to
+     * a CertName structure.
+     *
+     * returns WOLFSSL_SUCCESS on success and a negative error value on failure
+     */
+    static int CopyX509NameToCertName(WOLFSSL_X509_NAME* n, CertName* cName)
+    {
+        DecodedName* dn = NULL;
+
+        if (n == NULL || cName == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        dn = &(n->fullName);
+
+        /* initialize cert name */
+        cName->country[0] = '\0';
+        cName->countryEnc = CTC_PRINTABLE;
+        cName->state[0] = '\0';
+        cName->stateEnc = CTC_UTF8;
+        cName->locality[0] = '\0';
+        cName->localityEnc = CTC_UTF8;
+        cName->sur[0] = '\0';
+        cName->surEnc = CTC_UTF8;
+        cName->org[0] = '\0';
+        cName->orgEnc = CTC_UTF8;
+        cName->unit[0] = '\0';
+        cName->unitEnc = CTC_UTF8;
+        cName->commonName[0] = '\0';
+        cName->commonNameEnc = CTC_UTF8;
+        cName->serialDev[0] = '\0';
+        cName->serialDevEnc = CTC_PRINTABLE;
+    #ifdef WOLFSSL_CERT_EXT
+        cName->busCat[0] = '\0';
+        cName->busCatEnc = CTC_UTF8;
+        cName->joiC[0] = '\0';
+        cName->joiCEnc = CTC_PRINTABLE;
+        cName->joiSt[0] = '\0';
+        cName->joiStEnc = CTC_PRINTABLE;
+    #endif
+        cName->email[0] = '\0';
+
+
+        /* ASN_COUNTRY_NAME */
+        WOLFSSL_MSG("Copy Country Name");
+        if (CopyX509NameEntry(cName->country, CTC_NAME_SIZE, dn->fullName + dn->cIdx,
+                    dn->cLen) != SSL_SUCCESS) {
+            return BUFFER_E;
+        }
+
+        /* ASN_ORGUNIT_NAME */
+        WOLFSSL_MSG("Copy Org Unit Name");
+        if (CopyX509NameEntry(cName->unit, CTC_NAME_SIZE, dn->fullName + dn->ouIdx,
+                    dn->ouLen) != SSL_SUCCESS) {
+            return BUFFER_E;
+        }
+
+        /* ASN_ORG_NAME */
+        WOLFSSL_MSG("Copy Org Name");
+        if (CopyX509NameEntry(cName->org, CTC_NAME_SIZE, dn->fullName + dn->oIdx,
+                    dn->oLen) != SSL_SUCCESS) {
+            return BUFFER_E;
+        }
+
+        /* ASN_STATE_NAME */
+        WOLFSSL_MSG("Copy State Name");
+        if (CopyX509NameEntry(cName->state, CTC_NAME_SIZE, dn->fullName + dn->stIdx,
+                    dn->stLen) != SSL_SUCCESS) {
+            return BUFFER_E;
+        }
+
+        /* ASN_LOCALITY_NAME */
+        WOLFSSL_MSG("Copy Locality Name");
+        if (CopyX509NameEntry(cName->locality, CTC_NAME_SIZE,
+                    dn->fullName + dn->lIdx, dn->lLen)
+                    != SSL_SUCCESS) {
+            return BUFFER_E;
+        }
+
+        /* ASN_SUR_NAME */
+        WOLFSSL_MSG("Copy Sur Name");
+        if (CopyX509NameEntry(cName->sur, CTC_NAME_SIZE, dn->fullName + dn->snIdx,
+                    dn->snLen) != SSL_SUCCESS) {
+            return BUFFER_E;
+        }
+
+        /* ASN_COMMON_NAME */
+        WOLFSSL_MSG("Copy Common Name");
+        if (CopyX509NameEntry(cName->commonName, CTC_NAME_SIZE,
+                    dn->fullName + dn->cnIdx, dn->cnLen)
+                    != SSL_SUCCESS) {
+            return BUFFER_E;
+        }
+
+        /* ASN_SERIAL_NUMBER */
+        WOLFSSL_MSG("Copy Serial Number of Device");
+        if (CopyX509NameEntry(cName->serialDev, CTC_NAME_SIZE,
+                    dn->fullName + dn->serialIdx, dn->serialLen)
+                    != SSL_SUCCESS) {
+            return BUFFER_E;
+        }
+
+    #ifdef WOLFSSL_CERT_EXT
+        /* ASN_BUS_CAT */
+        WOLFSSL_MSG("Copy Business Category");
+        if (CopyX509NameEntry(cName->busCat, CTC_NAME_SIZE,
+                    dn->fullName + dn->bcIdx, dn->bcLen)
+                    != SSL_SUCCESS) {
+            return BUFFER_E;
+        }
+
+        /* JoI Country */
+        WOLFSSL_MSG("Copy Jurisdiction of Incorporation Country");
+        if (CopyX509NameEntry(cName->joiC, CTC_NAME_SIZE,
+                    dn->fullName + dn->jcIdx, dn->jcLen)
+                    != SSL_SUCCESS) {
+            return BUFFER_E;
+        }
+
+        /* JoI State */
+        WOLFSSL_MSG("Copy Jurisdiction of Incorporation State");
+        if (CopyX509NameEntry(cName->joiSt, CTC_NAME_SIZE,
+                    dn->fullName + dn->jsIdx, dn->jsLen)
+                    != SSL_SUCCESS) {
+            return BUFFER_E;
+        }
+    #endif
+
+        WOLFSSL_MSG("Copy Email");
+        if (CopyX509NameEntry(cName->email, CTC_NAME_SIZE,
+                    dn->fullName + dn->emailIdx, dn->emailLen)
+                    != SSL_SUCCESS) {
+            return BUFFER_E;
+        }
+
+        return WOLFSSL_SUCCESS;
+    }
+
+#ifdef WOLFSSL_CERT_REQ
+    static int ReqCertFromX509(Cert* cert, WOLFSSL_X509* req)
+    {
+        int ret;
+
+        if (wc_InitCert(cert) != 0)
+            return WOLFSSL_FAILURE;
+
+        ret = CopyX509NameToCertName(&req->subject, &cert->subject);
+        if (ret == WOLFSSL_SUCCESS) {
+            cert->version = req->version;
+            cert->isCA = req->isCa;
+#ifdef WOLFSSL_CERT_EXT
+            if (req->subjKeyIdSz != 0) {
+                XMEMCPY(cert->skid, req->subjKeyId, req->subjKeyIdSz);
+                cert->skidSz = req->subjKeyIdSz;
+            }
+            if (req->keyUsageSet)
+                cert->keyUsage = req->keyUsage;
+            /* Extended Key Usage not supported. */
+#endif
+        }
+
+        return ret;
+    }
+#endif
+
+    /* convert a WOLFSSL_X509 to a Cert structure for writing out */
+    static int CertFromX509(Cert* cert, WOLFSSL_X509* x509)
+    {
+        int ret;
+        #ifdef WOLFSSL_CERT_EXT
+        int i;
+        #endif
+
+        WOLFSSL_ENTER("wolfSSL_X509_to_Cert()");
+
+        if (x509 == NULL || cert == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        wc_InitCert(cert);
+
+        cert->version = (int)wolfSSL_X509_get_version(x509);
+
+    #ifdef WOLFSSL_ALT_NAMES
+        if (x509->notBefore.length > 0) {
+            if ((x509->notBefore.length + 2) < CTC_DATE_SIZE) {
+                cert->beforeDate[0] = x509->notBefore.type;
+                cert->beforeDate[1] = x509->notBefore.length;
+                XMEMCPY(&cert->beforeDate[2], x509->notBefore.data,
+                        x509->notBefore.length);
+                cert->beforeDateSz = x509->notBefore.length + 2;
+            }
+            else {
+                WOLFSSL_MSG("Not before date too large");
+                return WOLFSSL_FAILURE;
+            }
+        }
+        else {
+            cert->beforeDateSz = 0;
+        }
+        if (x509->notAfter.length > 0) {
+            if ((x509->notAfter.length + 2) < CTC_DATE_SIZE) {
+                cert->afterDate[0] = x509->notAfter.type;
+                cert->afterDate[1] = x509->notAfter.length;
+                XMEMCPY(&cert->afterDate[2], x509->notAfter.data,
+                        x509->notAfter.length);
+                cert->afterDateSz = x509->notAfter.length + 2;
+            }
+            else {
+                WOLFSSL_MSG("Not after date too large");
+                return WOLFSSL_FAILURE;
+            }
+        }
+        else {
+            cert->afterDateSz = 0;
+        }
+
+        cert->altNamesSz = FlattenAltNames(cert->altNames,
+                sizeof(cert->altNames), x509->altNames);
+
+    #endif /* WOLFSSL_ALT_NAMES */
+
+        cert->sigType = wolfSSL_X509_get_signature_type(x509);
+        cert->keyType = x509->pubKeyOID;
+        cert->isCA    = wolfSSL_X509_get_isCA(x509);
+
+    #ifdef WOLFSSL_CERT_EXT
+        if (x509->subjKeyIdSz < CTC_MAX_SKID_SIZE) {
+            XMEMCPY(cert->skid, x509->subjKeyId, x509->subjKeyIdSz);
+            cert->skidSz = (int)x509->subjKeyIdSz;
+        }
+        else {
+            WOLFSSL_MSG("Subject Key ID too large");
+            return WOLFSSL_FAILURE;
+        }
+
+        if (x509->authKeyIdSz < CTC_MAX_AKID_SIZE) {
+            XMEMCPY(cert->akid, x509->authKeyId, x509->authKeyIdSz);
+            cert->akidSz = (int)x509->authKeyIdSz;
+        }
+        else {
+            WOLFSSL_MSG("Auth Key ID too large");
+            return WOLFSSL_FAILURE;
+        }
+
+        for (i = 0; i < x509->certPoliciesNb; i++) {
+            /* copy the smaller of MAX macros, by default they are currently equal*/
+            if ((int)CTC_MAX_CERTPOL_SZ <= (int)MAX_CERTPOL_SZ) {
+                XMEMCPY(cert->certPolicies[i], x509->certPolicies[i],
+                        CTC_MAX_CERTPOL_SZ);
+            }
+            else {
+                XMEMCPY(cert->certPolicies[i], x509->certPolicies[i],
+                        MAX_CERTPOL_SZ);
+            }
+        }
+        cert->certPoliciesNb = (word16)x509->certPoliciesNb;
+
+        cert->keyUsage = x509->keyUsage;
+    #endif /* WOLFSSL_CERT_EXT */
+
+    #ifdef WOLFSSL_CERT_REQ
+        /* copy over challenge password for REQ certs */
+        XMEMCPY(cert->challengePw, x509->challengePw, CTC_NAME_SIZE);
+    #endif
+
+        if (x509->serialSz <= CTC_SERIAL_SIZE) {
+            XMEMCPY(cert->serial, x509->serial, x509->serialSz);
+        }
+        else {
+            WOLFSSL_MSG("Serial size error");
+            return WOLFSSL_FAILURE;
+        }
+
+        /* copy over Name structures */
+        if (x509->issuerSet)
+            cert->selfSigned = 0;
+        if ((ret = CopyX509NameToCertName(&(x509->issuer), &(cert->issuer)))
+            != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("Error copying over issuer names");
+            WOLFSSL_LEAVE("wolfSSL_X509_to_Cert()", ret);
+            return WOLFSSL_FAILURE;
+        }
+        if ((ret = CopyX509NameToCertName(&(x509->subject), &(cert->subject)))
+            != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("Error copying over subject names");
+            WOLFSSL_LEAVE("wolfSSL_X509_to_Cert()", ret);
+            return WOLFSSL_FAILURE;
+        }
+
+        cert->heap = x509->heap;
+
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    /* returns the sig type to use on success i.e CTC_SHAwRSA and WOLFSSL_FALURE
+     * on fail case */
+    static int wolfSSL_sigTypeFromPKEY(WOLFSSL_EVP_MD* md,
+            WOLFSSL_EVP_PKEY* pkey)
+    {
+        int hashType;
+        int sigType = WOLFSSL_FAILURE;
+
+        /* Convert key type and hash algorithm to a signature algorithm */
+        if (wolfSSL_EVP_get_hashinfo(md, &hashType, NULL) == WOLFSSL_FAILURE)
+            return WOLFSSL_FAILURE;
+
+
+        if (pkey->type == EVP_PKEY_RSA) {
+            switch (hashType) {
+                case WC_HASH_TYPE_SHA:
+                    sigType = CTC_SHAwRSA;
+                    break;
+                case WC_HASH_TYPE_SHA224:
+                    sigType = CTC_SHA224wRSA;
+                    break;
+                case WC_HASH_TYPE_SHA256:
+                    sigType = CTC_SHA256wRSA;
+                    break;
+                case WC_HASH_TYPE_SHA384:
+                    sigType = CTC_SHA384wRSA;
+                    break;
+                case WC_HASH_TYPE_SHA512:
+                    sigType = CTC_SHA512wRSA;
+                    break;
+                default:
+                    return WOLFSSL_FAILURE;
+            }
+        }
+        else if (pkey->type == EVP_PKEY_EC) {
+            switch (hashType) {
+                case WC_HASH_TYPE_SHA:
+                    sigType = CTC_SHAwECDSA;
+                    break;
+                case WC_HASH_TYPE_SHA224:
+                    sigType = CTC_SHA224wECDSA;
+                    break;
+                case WC_HASH_TYPE_SHA256:
+                    sigType = CTC_SHA256wECDSA;
+                    break;
+                case WC_HASH_TYPE_SHA384:
+                    sigType = CTC_SHA384wECDSA;
+                    break;
+                case WC_HASH_TYPE_SHA512:
+                    sigType = CTC_SHA512wECDSA;
+                    break;
+                default:
+                    return WOLFSSL_FAILURE;
+            }
+        }
+        else
+            return WOLFSSL_FAILURE;
+        return sigType;
+    }
+
+
+    /* generates DER buffer from WOLFSSL_X509
+     * If req == 1 then creates a request DER buffer
+     *
+     * updates derSz with certificate body size on success
+     * return WOLFSSL_SUCCESS on success
+     */
+    static int wolfSSL_X509_make_der(WOLFSSL_X509* x509, int req,
+            unsigned char* der, int* derSz)
+    {
+        int ret;
+        Cert cert;
+        void* key = NULL;
+        int type = -1;
+    #ifndef NO_RSA
+        RsaKey rsa;
+    #endif
+    #ifdef HAVE_ECC
+        ecc_key ecc;
+    #endif
+        WC_RNG rng;
+        word32 idx = 0;
+
+        if (x509 == NULL || der == NULL || derSz == NULL)
+            return BAD_FUNC_ARG;
+
+    #ifndef WOLFSSL_CERT_REQ
+        if (req) {
+            WOLFSSL_MSG("WOLFSSL_CERT_REQ needed for certificate request");
+            return WOLFSSL_FAILURE;
+        }
+    #endif
+
+    #ifdef WOLFSSL_CERT_REQ
+        if (req) {
+            if (ReqCertFromX509(&cert, x509) != WOLFSSL_SUCCESS)
+                return WOLFSSL_FAILURE;
+        }
+        else
+    #endif
+        {
+            /* Create a Cert that has the certificate fields. */
+            if (CertFromX509(&cert, x509) != WOLFSSL_SUCCESS)
+                return WOLFSSL_FAILURE;
+        }
+
+        /* Create a public key object from requests public key. */
+    #ifndef NO_RSA
+        if (x509->pubKeyOID == RSAk) {
+            type = RSA_TYPE;
+            ret = wc_InitRsaKey(&rsa, x509->heap);
+            if (ret != 0)
+                return ret;
+            ret = wc_RsaPublicKeyDecode(x509->pubKey.buffer, &idx, &rsa,
+                                                           x509->pubKey.length);
+            if (ret != 0) {
+                wc_FreeRsaKey(&rsa);
+                return ret;
+            }
+            key = (void*)&rsa;
+        }
+    #endif
+    #ifdef HAVE_ECC
+        if (x509->pubKeyOID == ECDSAk) {
+            type = ECC_TYPE;
+            ret = wc_ecc_init(&ecc);
+            if (ret != 0)
+                return ret;
+            ret = wc_EccPublicKeyDecode(x509->pubKey.buffer, &idx, &ecc,
+                                                           x509->pubKey.length);
+            if (ret != 0) {
+                wc_ecc_free(&ecc);
+                return ret;
+            }
+            key = (void*)&ecc;
+        }
+    #endif
+        if (key == NULL)
+            return WOLFSSL_FAILURE;
+
+        /* Make the body of the certificate request. */
+    #ifdef WOLFSSL_CERT_REQ
+        if (req) {
+            ret = wc_MakeCertReq_ex(&cert, der, *derSz, type, key);
+        }
+        else
+    #endif
+        {
+            ret = wc_InitRng(&rng);
+            if (ret != 0)
+                return WOLFSSL_FAILURE;
+
+            ret = wc_MakeCert_ex(&cert, der, *derSz, type, key, &rng);
+            wc_FreeRng(&rng);
+        }
+        if (ret < 0) {
+            return ret;
+        }
+
+        /* Dispose of the public key object. */
+    #ifndef NO_RSA
+        if (x509->pubKeyOID == RSAk)
+            wc_FreeRsaKey(&rsa);
+    #endif
+    #ifdef HAVE_ECC
+        if (x509->pubKeyOID == ECDSAk)
+            wc_ecc_free(&ecc);
+    #endif
+        *derSz = ret;
+
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    /* signs a der buffer for the WOLFSSL_X509 structure using the PKEY and MD
+     * hash passed in
+     *
+     * WARNING: this free's and replaces the existing DER buffer in the
+     *          WOLFSSL_X509 with the newly signed buffer.
+     * returns size of signed buffer on success and negative values on fail
+     */
+    static int wolfSSL_X509_resign_cert(WOLFSSL_X509* x509, int req,
+            unsigned char* der, int derSz, int certBodySz, WOLFSSL_EVP_MD* md,
+            WOLFSSL_EVP_PKEY* pkey)
+    {
+        int ret;
+        void* key = NULL;
+        int type = -1;
+        int sigType;
+        WC_RNG rng;
+
+        sigType = wolfSSL_sigTypeFromPKEY(md, pkey);
+        if (sigType == WOLFSSL_FAILURE)
+            return WOLFSSL_FATAL_ERROR;
+
+
+        /* Get the private key object and type from pkey. */
+    #ifndef NO_RSA
+        if (pkey->type == EVP_PKEY_RSA) {
+            type = RSA_TYPE;
+            key = pkey->rsa->internal;
+        }
+    #endif
+    #ifdef HAVE_ECC
+        if (pkey->type == EVP_PKEY_EC) {
+            type = ECC_TYPE;
+            key = pkey->ecc->internal;
+        }
+    #endif
+
+        /* Sign the certificate request body. */
+        ret = wc_InitRng(&rng);
+        if (ret != 0)
+            return ret;
+        ret = wc_SignCert_ex(certBodySz, sigType, der, derSz, type, key, &rng);
+        wc_FreeRng(&rng);
+        if (ret < 0)
+            return ret;
+
+        /* Put in the new certificate encoding into the x509 object. */
+        FreeDer(&x509->derCert);
+        type = CERT_TYPE;
+    #ifdef WOLFSSL_REQ_CERT
+        if (req) {
+            type = CERTREQ_TYPE;
+        }
+    #endif
+
+        if (AllocDer(&x509->derCert, ret, type, NULL) != 0)
+            return WOLFSSL_FATAL_ERROR;
+        XMEMCPY(x509->derCert->buffer, der, ret);
+        x509->derCert->length = ret;
+
+        (void)req;
+        return ret;
+    }
+
+
+    /* returns the size of signature on success */
+    int wolfSSL_X509_sign(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey,
+            const WOLFSSL_EVP_MD* md)
+    {
+        int  ret;
+        byte der[4096]; /* @TODO dynamic set based on expected cert size */
+        int  derSz = sizeof(der);
+
+        WOLFSSL_ENTER("wolfSSL_X509_sign");
+
+        if (x509 == NULL || pkey == NULL || md == NULL)
+            return WOLFSSL_FAILURE;
+
+        x509->sigOID = wolfSSL_sigTypeFromPKEY((WOLFSSL_EVP_MD*)md, pkey);
+        if ((ret = wolfSSL_X509_make_der(x509, 0, der, &derSz)) !=
+                WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("Unable to make DER for X509");
+            WOLFSSL_LEAVE("wolfSSL_X509_sign", ret);
+            return WOLFSSL_FAILURE;
+        }
+
+        ret = wolfSSL_X509_resign_cert(x509, 0, der, sizeof(der), derSz,
+                (WOLFSSL_EVP_MD*)md, pkey);
+        if (ret <= 0) {
+            WOLFSSL_LEAVE("wolfSSL_X509_sign", ret);
+            return WOLFSSL_FAILURE;
+        }
+
+        return ret;
+    }
+
+
+    /* Converts the x509 name structure into DER format.
+     *
+     * out  pointer to either a pre setup buffer or a pointer to null for
+     *      creating a dynamic buffer. In the case that a pre-existing buffer is
+     *      used out will be incremented the size of the DER buffer on success.
+     *
+     * returns the size of the buffer on success, or negative value with failure
+     */
+    int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* name, unsigned char** out)
+    {
+        CertName cName;
+        unsigned char buf[256]; /* ASN_MAX_NAME */
+        int sz;
+        WOLFSSL_ENTER("wolfSSL_i2d_X509_NAME");
+
+        if (out == NULL || name == NULL) {
+            return BAD_FUNC_ARG;
+        }
+        XMEMSET(&cName, 0, sizeof(CertName));
+
+        if (CopyX509NameToCertName(name, &cName) != SSL_SUCCESS) {
+            WOLFSSL_MSG("Error converting x509 name to internal CertName");
+            return SSL_FATAL_ERROR;
+        }
+
+        sz = SetName(buf, sizeof(buf), &cName);
+        if (sz < 0) {
+            return sz;
+        }
+
+        /* using buffer passed in */
+        if (*out != NULL) {
+            XMEMCPY(*out, buf, sz);
+            *out += sz;
+        }
+        else {
+            *out = (unsigned char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_OPENSSL);
+            if (*out == NULL) {
+                return MEMORY_E;
+            }
+            XMEMCPY(*out, buf, sz);
+        }
+
+        return sz;
+    }
+#endif /* WOLFSSL_CERT_GEN */
+
+
+    /* Compares the two X509 names. If the size of x is larger then y then a
+     * positive value is returned if x is smaller a negative value is returned.
+     * In the case that the sizes are equal a the value of strcmp between the
+     * two names is returned.
+     *
+     * x First name for comparison
+     * y Second name to compare with x
+     */
+    int wolfSSL_X509_NAME_cmp(const WOLFSSL_X509_NAME* x,
+            const WOLFSSL_X509_NAME* y)
+    {
+        const char* _x;
+        const char* _y;
+        WOLFSSL_ENTER("wolfSSL_X509_NAME_cmp");
+
+        if (x == NULL || y == NULL) {
+            WOLFSSL_MSG("Bad argument passed in");
+            return -2;
+        }
+
+        if (x == y) {
+            return 0; /* match */
+        }
+
+        if (x->sz != y->sz) {
+            return x->sz - y->sz;
+        }
+
+        /*
+         * If the name member is not set or is immediately null terminated then
+         * compare the staticName member
+         */
+        _x = (x->name && *x->name) ? x->name : x->staticName;
+        _y = (y->name && *y->name) ? y->name : y->staticName;
+
+        return XSTRNCMP(_x, _y, x->sz); /* y sz is the same */
+    }
+
+
+    WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 **x,
+                                                 pem_password_cb *cb, void *u)
+    {
+        WOLFSSL_X509* x509 = NULL;
+#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
+        unsigned char* pem = NULL;
+        int pemSz;
+        long  i = 0, l;
+        const char* footer = NULL;
+
+        WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509");
+
+        if (bp == NULL) {
+            WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_X509", BAD_FUNC_ARG);
+            return NULL;
+        }
+
+        if ((l = wolfSSL_BIO_get_len(bp)) <= 0) {
+    #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+            /* No certificate in buffer */
+            WOLFSSL_ERROR(ASN_NO_PEM_HEADER);
+    #endif
+            return NULL;
+        }
+
+        pem = (unsigned char*)XMALLOC(l, 0, DYNAMIC_TYPE_PEM);
+        if (pem == NULL)
+            return NULL;
+
+        i = 0;
+        if (wc_PemGetHeaderFooter(CERT_TYPE, NULL, &footer) != 0) {
+            XFREE(pem, 0, DYNAMIC_TYPE_PEM);
+            return NULL;
+        }
+
+        /* TODO: Inefficient
+         * reading in one byte at a time until see "END CERTIFICATE"
+         */
+        while ((l = wolfSSL_BIO_read(bp, (char *)&pem[i], 1)) == 1) {
+            i++;
+            if (i > 26 && XMEMCMP((char *)&pem[i-26], footer, 25) == 0) {
+                if (pem[i-1] == '\r') {
+                    /* found \r , Windows line ending is \r\n so try to read one
+                     * more byte for \n, ignoring return value */
+                    (void)wolfSSL_BIO_read(bp, (char *)&pem[i++], 1);
+                }
+                break;
+            }
+        }
+    #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+        if (l == 0)
+            WOLFSSL_ERROR(ASN_NO_PEM_HEADER);
+    #endif
+        pemSz = (int)i;
+        x509 = wolfSSL_X509_load_certificate_buffer(pem, pemSz,
+                                                              WOLFSSL_FILETYPE_PEM);
+
+        if (x != NULL) {
+            *x = x509;
+        }
+
+        XFREE(pem, NULL, DYNAMIC_TYPE_PEM);
+
+#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
+        (void)bp;
+        (void)x;
+        (void)cb;
+        (void)u;
+
+        return x509;
+    }
+
+    WOLFSSL_X509_CRL *wolfSSL_PEM_read_bio_X509_CRL(WOLFSSL_BIO *bp,
+            WOLFSSL_X509_CRL **x, pem_password_cb *cb, void *u)
+    {
+#if defined(WOLFSSL_PEM_TO_DER) && defined(HAVE_CRL)
+        unsigned char* pem = NULL;
+        int pemSz;
+        int derSz;
+        DerBuffer* der = NULL;
+        WOLFSSL_X509_CRL* crl = NULL;
+
+        if ((pemSz = wolfSSL_BIO_get_len(bp)) <= 0) {
+            goto err;
+        }
+
+        pem = (unsigned char*)XMALLOC(pemSz, 0, DYNAMIC_TYPE_PEM);
+        if (pem == NULL) {
+            goto err;
+        }
+
+        if (wolfSSL_BIO_read(bp, pem, pemSz) != pemSz) {
+            goto err;
+        }
+
+        if((PemToDer(pem, pemSz, CRL_TYPE, &der, NULL, NULL, NULL)) < 0) {
+            goto err;
+        }
+        derSz = der->length;
+        if((crl = wolfSSL_d2i_X509_CRL(x, der->buffer, derSz)) == NULL) {
+            goto err;
+        }
+
+err:
+        if(pem != NULL) {
+            XFREE(pem, 0, DYNAMIC_TYPE_PEM);
+        }
+        if(der != NULL) {
+            FreeDer(&der);
+        }
+
+        (void)cb;
+        (void)u;
+
+        return crl;
+#else
+        (void)bp;
+        (void)x;
+        (void)cb;
+        (void)u;
+
+        return NULL;
+#endif
+    }
+
+#if !defined(NO_FILESYSTEM)
+    static void* wolfSSL_PEM_read_X509_ex(XFILE fp, void **x,
+        pem_password_cb *cb, void *u, int type)
+    {
+        unsigned char* pem = NULL;
+        int pemSz;
+        long i = 0, l;
+        void *newx509;
+        int derSz;
+        DerBuffer* der = NULL;
+
+        WOLFSSL_ENTER("wolfSSL_PEM_read_X509");
+
+        if (fp == XBADFILE) {
+            WOLFSSL_LEAVE("wolfSSL_PEM_read_X509", BAD_FUNC_ARG);
+            return NULL;
+        }
+        /* Read cert from file */
+        i = XFTELL(fp);
+        if (i < 0) {
+            WOLFSSL_LEAVE("wolfSSL_PEM_read_X509", BAD_FUNC_ARG);
+            return NULL;
+        }
+
+        if (XFSEEK(fp, 0, XSEEK_END) != 0)
+            return NULL;
+        l = XFTELL(fp);
+        if (l < 0)
+            return NULL;
+        if (XFSEEK(fp, i, SEEK_SET) != 0)
+            return NULL;
+        pemSz = (int)(l - i);
+
+        /* check calculated length */
+        if (pemSz > MAX_WOLFSSL_FILE_SIZE || pemSz < 0) {
+            WOLFSSL_MSG("PEM_read_X509_ex file size error");
+            return NULL;
+        }
+
+        /* allocate pem buffer */
+        pem = (unsigned char*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_PEM);
+        if (pem == NULL)
+            return NULL;
+
+        if ((int)XFREAD((char *)pem, 1, pemSz, fp) != pemSz)
+            goto err_exit;
+
+        switch (type) {
+            case CERT_TYPE:
+                newx509 = (void *)wolfSSL_X509_load_certificate_buffer(pem,
+                    pemSz, WOLFSSL_FILETYPE_PEM);
+                break;
+
+        #ifdef HAVE_CRL
+            case CRL_TYPE:
+                if ((PemToDer(pem, pemSz, CRL_TYPE, &der, NULL, NULL, NULL)) < 0)
+                    goto err_exit;
+                derSz = der->length;
+                newx509 = (void*)wolfSSL_d2i_X509_CRL((WOLFSSL_X509_CRL **)x,
+                    (const unsigned char *)der->buffer, derSz);
+                if (newx509 == NULL)
+                    goto err_exit;
+                FreeDer(&der);
+                break;
+        #endif
+
+            default:
+                goto err_exit;
+        }
+        if (x != NULL) {
+            *x = newx509;
+        }
+        XFREE(pem, NULL, DYNAMIC_TYPE_PEM);
+        return newx509;
+
+    err_exit:
+        if (pem != NULL)
+            XFREE(pem, NULL, DYNAMIC_TYPE_PEM);
+        if (der != NULL)
+            FreeDer(&der);
+
+        /* unused */
+        (void)cb;
+        (void)u;
+	    (void)derSz;
+
+        return NULL;
+    }
+
+    WOLFSSL_API WOLFSSL_X509* wolfSSL_PEM_read_X509(XFILE fp, WOLFSSL_X509 **x,
+                                                    pem_password_cb *cb, void *u)
+    {
+        return (WOLFSSL_X509* )wolfSSL_PEM_read_X509_ex(fp, (void **)x, cb, u, CERT_TYPE);
+    }
+
+#if defined(HAVE_CRL)
+    WOLFSSL_API WOLFSSL_X509_CRL* wolfSSL_PEM_read_X509_CRL(XFILE fp, WOLFSSL_X509_CRL **crl,
+                                                    pem_password_cb *cb, void *u)
+    {
+        return (WOLFSSL_X509_CRL* )wolfSSL_PEM_read_X509_ex(fp, (void **)crl, cb, u, CRL_TYPE);
+    }
+#endif
+
+    int wolfSSL_PEM_write_X509(XFILE fp, WOLFSSL_X509* x)
+    {
+        int ret;
+        WOLFSSL_BIO* bio;
+
+        if (x == NULL)
+            return 0;
+
+        bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file());
+        if (bio == NULL)
+            return 0;
+
+        if (wolfSSL_BIO_set_fp(bio, fp, BIO_NOCLOSE) != WOLFSSL_SUCCESS) {
+            wolfSSL_BIO_free(bio);
+            bio = NULL;
+        }
+
+        ret = wolfSSL_PEM_write_bio_X509(bio, x);
+
+        if (bio != NULL)
+            wolfSSL_BIO_free(bio);
+
+        return ret;
+    }
+#endif /* !NO_FILESYSTEM */
+
+    #define PEM_BEGIN              "-----BEGIN "
+    #define PEM_BEGIN_SZ           11
+    #define PEM_END                "-----END "
+    #define PEM_END_SZ             9
+    #define PEM_HDR_FIN            "-----"
+    #define PEM_HDR_FIN_SZ         5
+    #define PEM_HDR_FIN_EOL_NEWLINE   "-----\n"
+    #define PEM_HDR_FIN_EOL_NULL_TERM "-----\0"
+    #define PEM_HDR_FIN_EOL_SZ     6
+
+    int wolfSSL_PEM_read_bio(WOLFSSL_BIO* bio, char **name, char **header,
+                             unsigned char **data, long *len)
+    {
+        int ret = WOLFSSL_SUCCESS;
+        char pem[256];
+        int pemLen;
+        char* p;
+        char* nameStr = NULL;
+        int nameLen = 0;
+        char* headerStr = NULL;
+        int headerLen;
+        int headerFound = 0;
+        unsigned char* der = NULL;
+        word32 derLen = 0;
+
+        if (bio == NULL || name == NULL || header == NULL || data == NULL ||
+                                                                  len == NULL) {
+            return WOLFSSL_FAILURE;
+        }
+
+        /* Find header line. */
+        pem[sizeof(pem) - 1] = '\0';
+        while ((pemLen = wolfSSL_BIO_gets(bio, pem, sizeof(pem) - 1)) > 0) {
+            if (XSTRNCMP(pem, PEM_BEGIN, PEM_BEGIN_SZ) == 0)
+                break;
+        }
+        if (pemLen <= 0)
+            ret = WOLFSSL_FAILURE;
+        /* Have a header line. */
+        if (ret == WOLFSSL_SUCCESS) {
+            while (pem[pemLen - 1] == '\r' || pem[pemLen - 1] == '\n')
+                pemLen--;
+            pem[pemLen] = '\0';
+            if (XSTRNCMP(pem + pemLen - PEM_HDR_FIN_SZ, PEM_HDR_FIN,
+                                                         PEM_HDR_FIN_SZ) != 0) {
+                ret = WOLFSSL_FAILURE;
+            }
+        }
+
+        /* Get out name. */
+        if (ret == WOLFSSL_SUCCESS) {
+            nameLen = pemLen - PEM_BEGIN_SZ - PEM_HDR_FIN_SZ;
+            nameStr = (char*)XMALLOC(nameLen + 1, NULL,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+            if (nameStr == NULL)
+                ret = WOLFSSL_FAILURE;
+        }
+        if (ret == WOLFSSL_SUCCESS) {
+            XSTRNCPY(nameStr, pem + PEM_BEGIN_SZ, nameLen);
+            nameStr[nameLen] = '\0';
+
+            /* Get header of PEM - encryption header. */
+            headerLen = 0;
+            while ((pemLen = wolfSSL_BIO_gets(bio, pem, sizeof(pem) - 1)) > 0) {
+                while (pemLen > 0 && (pem[pemLen - 1] == '\r' ||
+                                                     pem[pemLen - 1] == '\n')) {
+                    pemLen--;
+                }
+                pem[pemLen++] = '\n';
+                pem[pemLen] = '\0';
+
+                /* Header separator is a blank line. */
+                if (pem[0] == '\n') {
+                    headerFound = 1;
+                    break;
+                }
+
+                /* Didn't find a blank line - no header. */
+                if (XSTRNCMP(pem, PEM_END, PEM_END_SZ) == 0) {
+                    der = (unsigned char*)headerStr;
+                    derLen = headerLen;
+                    /* Empty header - empty string. */
+                    headerStr = (char*)XMALLOC(1, NULL,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+                    if (headerStr == NULL)
+                        ret = WOLFSSL_FAILURE;
+                    else
+                        headerStr[0] = '\0';
+                    break;
+                }
+
+                p = (char*)XREALLOC(headerStr, headerLen + pemLen + 1, NULL,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+                if (p == NULL) {
+                    ret = WOLFSSL_FAILURE;
+                    break;
+                }
+
+                headerStr = p;
+                XMEMCPY(headerStr + headerLen, pem, pemLen + 1);
+                headerLen += pemLen;
+            }
+            if (pemLen <= 0)
+                ret = WOLFSSL_FAILURE;
+        }
+
+        /* Get body of PEM - if there was a header */
+        if (ret == WOLFSSL_SUCCESS && headerFound) {
+            derLen = 0;
+            while ((pemLen = wolfSSL_BIO_gets(bio, pem, sizeof(pem) - 1)) > 0) {
+                while (pemLen > 0 && (pem[pemLen - 1] == '\r' ||
+                                                     pem[pemLen - 1] == '\n')) {
+                    pemLen--;
+                }
+                pem[pemLen++] = '\n';
+                pem[pemLen] = '\0';
+
+                if (XSTRNCMP(pem, PEM_END, PEM_END_SZ) == 0)
+                    break;
+
+                p = (char*)XREALLOC(der, derLen + pemLen + 1, NULL,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+                if (p == NULL) {
+                    ret = WOLFSSL_FAILURE;
+                    break;
+                }
+
+                der = (unsigned char*)p;
+                XMEMCPY(der + derLen, pem, pemLen + 1);
+                derLen += pemLen;
+            }
+            if (pemLen <= 0)
+                ret = WOLFSSL_FAILURE;
+        }
+
+        /* Check trailer. */
+        if (ret == WOLFSSL_SUCCESS) {
+            if (XSTRNCMP(pem + PEM_END_SZ, nameStr, nameLen) != 0)
+                ret = WOLFSSL_FAILURE;
+        }
+        if (ret == WOLFSSL_SUCCESS) {
+            if (XSTRNCMP(pem + PEM_END_SZ + nameLen,
+                    PEM_HDR_FIN_EOL_NEWLINE,
+                    PEM_HDR_FIN_EOL_SZ) != 0 &&
+                XSTRNCMP(pem + PEM_END_SZ + nameLen,
+                        PEM_HDR_FIN_EOL_NULL_TERM,
+                        PEM_HDR_FIN_EOL_SZ) != 0) {
+                ret = WOLFSSL_FAILURE;
+            }
+        }
+
+        /* Base64 decode body. */
+        if (ret == WOLFSSL_SUCCESS) {
+            if (Base64_Decode(der, derLen, der, &derLen) != 0)
+                ret = WOLFSSL_FAILURE;
+        }
+
+        if (ret == WOLFSSL_SUCCESS) {
+            *name = nameStr;
+            *header = headerStr;
+            *data = der;
+            *len = derLen;
+            nameStr = NULL;
+            headerStr = NULL;
+            der = NULL;
+        }
+
+        if (nameStr != NULL)
+            XFREE(nameStr, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (headerStr != NULL)
+            XFREE(headerStr, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (der != NULL)
+            XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+        return ret;
+    }
+
+    int wolfSSL_PEM_write_bio(WOLFSSL_BIO* bio, const char *name,
+                              const char *header, const unsigned char *data,
+                              long len)
+    {
+        int err = 0;
+        int outSz = 0;
+        int nameLen;
+        int headerLen;
+        byte* pem = NULL;
+        word32 pemLen;
+        word32 derLen = (word32)len;
+
+        if (bio == NULL || name == NULL || header == NULL || data == NULL)
+            return 0;
+
+        nameLen = (int)XSTRLEN(name);
+        headerLen = (int)XSTRLEN(header);
+
+        pemLen = (derLen + 2) / 3 * 4;
+        pemLen += (pemLen + 63) / 64;
+
+        pem = (byte*)XMALLOC(pemLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        err = pem == NULL;
+        if (!err)
+            err = Base64_Encode(data, derLen, pem, &pemLen) != 0;
+
+        if (!err) {
+            err = wolfSSL_BIO_write(bio, PEM_BEGIN, PEM_BEGIN_SZ) !=
+                                                              (int)PEM_BEGIN_SZ;
+        }
+        if (!err)
+            err = wolfSSL_BIO_write(bio, name, nameLen) != nameLen;
+        if (!err) {
+            err = wolfSSL_BIO_write(bio, PEM_HDR_FIN_EOL_NEWLINE,
+                    PEM_HDR_FIN_EOL_SZ) != (int)PEM_HDR_FIN_EOL_SZ;
+        }
+        if (!err && headerLen > 0) {
+            err = wolfSSL_BIO_write(bio, header, headerLen) != headerLen;
+            /* Blank line after a header and before body. */
+            if (!err)
+                err = wolfSSL_BIO_write(bio, "\n", 1) != 1;
+            headerLen++;
+        }
+        if (!err)
+            err = wolfSSL_BIO_write(bio, pem, pemLen) != (int)pemLen;
+        if (!err)
+            err = wolfSSL_BIO_write(bio, PEM_END, PEM_END_SZ) !=
+                                                                (int)PEM_END_SZ;
+        if (!err)
+            err = wolfSSL_BIO_write(bio, name, nameLen) != nameLen;
+        if (!err) {
+            err = wolfSSL_BIO_write(bio, PEM_HDR_FIN_EOL_NEWLINE,
+                    PEM_HDR_FIN_EOL_SZ) != (int)PEM_HDR_FIN_EOL_SZ;
+        }
+
+        if (!err) {
+            outSz = PEM_BEGIN_SZ + nameLen + PEM_HDR_FIN_EOL_SZ + headerLen +
+                             pemLen + PEM_END_SZ + nameLen + PEM_HDR_FIN_EOL_SZ;
+        }
+
+        if (pem != NULL)
+            XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+        return outSz;
+    }
+
+#if !defined(NO_FILESYSTEM)
+    int wolfSSL_PEM_read(XFILE fp, char **name, char **header,
+                         unsigned char **data, long *len)
+    {
+        int ret;
+        WOLFSSL_BIO* bio;
+
+        if (name == NULL || header == NULL || data == NULL || len == NULL)
+            return WOLFSSL_FAILURE;
+
+        bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file());
+        if (bio == NULL)
+            return 0;
+
+        if (wolfSSL_BIO_set_fp(bio, fp, BIO_NOCLOSE) != WOLFSSL_SUCCESS) {
+            wolfSSL_BIO_free(bio);
+            bio = NULL;
+        }
+
+        ret = wolfSSL_PEM_read_bio(bio, name, header, data, len);
+
+        if (bio != NULL)
+            wolfSSL_BIO_free(bio);
+
+        return ret;
+    }
+
+    int wolfSSL_PEM_write(XFILE fp, const char *name, const char *header,
+                          const unsigned char *data, long len)
+    {
+        int ret;
+        WOLFSSL_BIO* bio;
+
+        if (name == NULL || header == NULL || data == NULL)
+            return 0;
+
+        bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file());
+        if (bio == NULL)
+            return 0;
+
+        if (wolfSSL_BIO_set_fp(bio, fp, BIO_NOCLOSE) != WOLFSSL_SUCCESS) {
+            wolfSSL_BIO_free(bio);
+            bio = NULL;
+        }
+
+        ret = wolfSSL_PEM_write_bio(bio, name, header, data, len);
+
+        if (bio != NULL)
+            wolfSSL_BIO_free(bio);
+
+        return ret;
+    }
+#endif
+
+    int wolfSSL_PEM_get_EVP_CIPHER_INFO(char* header, EncryptedInfo* cipher)
+    {
+        if (header == NULL || cipher == NULL)
+            return WOLFSSL_FAILURE;
+
+        XMEMSET(cipher, 0, sizeof(*cipher));
+
+        if (wc_EncryptedInfoParse(cipher, &header, XSTRLEN(header)) != 0)
+            return WOLFSSL_FAILURE;
+
+        return WOLFSSL_SUCCESS;
+    }
+
+    int wolfSSL_PEM_do_header(EncryptedInfo* cipher, unsigned char* data,
+                              long* len, pem_password_cb* callback, void* ctx)
+    {
+        int ret = WOLFSSL_SUCCESS;
+        char password[NAME_SZ];
+        int passwordSz;
+
+        if (cipher == NULL || data == NULL || len == NULL || callback == NULL)
+            return WOLFSSL_FAILURE;
+
+        passwordSz = callback(password, sizeof(password), PEM_PASS_READ, ctx);
+        if (passwordSz < 0)
+            ret = WOLFSSL_FAILURE;
+
+        if (ret == WOLFSSL_SUCCESS) {
+            if (wc_BufferKeyDecrypt(cipher, data, (word32)*len, (byte*)password,
+                                                     passwordSz, WC_MD5) != 0) {
+                ret = WOLFSSL_FAILURE;
+            }
+        }
+
+        if (passwordSz > 0)
+            XMEMSET(password, 0, passwordSz);
+
+        return ret;
+    }
+
+    /*
+     * bp : bio to read X509 from
+     * x  : x509 to write to
+     * cb : password call back for reading PEM
+     * u  : password
+     * _AUX is for working with a trusted X509 certificate
+     */
+    WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509_AUX(WOLFSSL_BIO *bp,
+                               WOLFSSL_X509 **x, pem_password_cb *cb, void *u) {
+        WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509");
+
+        /* AUX info is; trusted/rejected uses, friendly name, private key id,
+         * and potentially a stack of "other" info. wolfSSL does not store
+         * friendly name or private key id yet in WOLFSSL_X509 for human
+         * readability and does not support extra trusted/rejected uses for
+         * root CA. */
+        return wolfSSL_PEM_read_bio_X509(bp, x, cb, u);
+    }
+
+
+#ifdef OPENSSL_ALL
+    /* create and return a new WOLFSSL_X509_PKEY structure or NULL on failure */
+    static WOLFSSL_X509_PKEY* wolfSSL_X509_PKEY_new(void* heap)
+    {
+        WOLFSSL_X509_PKEY* ret;
+
+        ret = (WOLFSSL_X509_PKEY*)XMALLOC(sizeof(WOLFSSL_X509_PKEY), heap,
+            DYNAMIC_TYPE_KEY);
+        if (ret != NULL) {
+            XMEMSET(ret, 0, sizeof(WOLFSSL_X509_PKEY));
+            ret->heap = heap;
+        }
+        return ret;
+    }
+
+
+    /* sets the values of X509_PKEY based on certificate passed in
+     * return WOLFSSL_SUCCESS on success */
+    static int wolfSSL_X509_PKEY_set(WOLFSSL_X509_PKEY* xPkey,
+            WOLFSSL_X509* x509)
+    {
+        if (xPkey == NULL || x509 == NULL) {
+            return BAD_FUNC_ARG;
+        }
+        wolfSSL_EVP_PKEY_free(xPkey->dec_pkey);
+        xPkey->dec_pkey = wolfSSL_X509_get_pubkey(x509);
+        if (xPkey->dec_pkey == NULL) {
+            return WOLFSSL_FAILURE;
+        }
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    /* free up all memory used by "xPkey" passed in */
+    static void wolfSSL_X509_PKEY_free(WOLFSSL_X509_PKEY* xPkey)
+    {
+        if (xPkey != NULL) {
+            wolfSSL_EVP_PKEY_free(xPkey->dec_pkey);
+        }
+        XFREE(xPkey, xPkey->heap, DYNAMIC_TYPE_KEY);
+    }
+
+
+    /* Takes control of x509 on success
+     * helper function to break out code needed to set WOLFSSL_X509_INFO up
+     * free's "info" passed in if is not defaults
+     *
+     * returns WOLFSSL_SUCCESS on success
+     */
+    static int wolfSSL_X509_INFO_set(WOLFSSL_X509_INFO* info,
+            WOLFSSL_X509* x509)
+    {
+        if (info == NULL || x509 == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        /* check is fresh "info" passed in, if not free it */
+        if (info->x509 != NULL || info->x_pkey != NULL) {
+            WOLFSSL_X509_INFO* tmp;
+
+            tmp = wolfSSL_X509_INFO_new();
+            if (tmp == NULL) {
+                WOLFSSL_MSG("Unable to create new structure");
+                return MEMORY_E;
+            }
+            wolfSSL_X509_INFO_free(info);
+            info = tmp;
+        }
+
+        info->x509 = x509;
+
+        //@TODO info->num
+        //@TODO info->enc_cipher
+        //@TODO info->enc_len
+        //@TODO info->enc_data
+        //@TODO info->crl
+
+        info->x_pkey = wolfSSL_X509_PKEY_new(x509->heap);
+        return wolfSSL_X509_PKEY_set(info->x_pkey, x509);
+    }
+
+
+    /*
+     * bio WOLFSSL_BIO to read certificates from
+     * sk  possible stack to push more X509_INFO structs to. Can be NULL
+     * cb  callback password for encrypted PEM certificates
+     * u   user input such as password
+     *
+     * returns stack on success and NULL or default stack passed in on fail
+     */
+    WOLF_STACK_OF(WOLFSSL_X509_INFO)* wolfSSL_PEM_X509_INFO_read_bio(
+        WOLFSSL_BIO* bio, WOLF_STACK_OF(WOLFSSL_X509_INFO)* sk,
+        pem_password_cb* cb, void* u)
+    {
+        WOLF_STACK_OF(WOLFSSL_X509_INFO)* localSk;
+        WOLFSSL_X509* x509 = NULL;
+        int ret = WOLFSSL_SUCCESS;
+
+        WOLFSSL_ENTER("wolfSSL_PEM_X509_INFO_read_bio");
+
+        /* attempt to used passed in stack or create a new one */
+        if (sk != NULL) {
+            localSk = sk;
+        }
+        else {
+            localSk = wolfSSL_sk_X509_INFO_new_null();
+        }
+        if (localSk == NULL) {
+            WOLFSSL_LEAVE("wolfSSL_PEM_X509_INFO_read_bio", MEMORY_E);
+            return NULL;
+        }
+
+        /* parse through BIO and push new info's found onto stack */
+        do {
+            x509 = wolfSSL_PEM_read_bio_X509(bio, NULL, cb, u);
+            if (x509 != NULL) {
+                WOLFSSL_X509_INFO* current;
+
+                current = wolfSSL_X509_INFO_new();
+                if (current == NULL) {
+                    WOLFSSL_LEAVE("wolfSSL_PEM_X509_INFO_read_bio", MEMORY_E);
+                    return NULL;
+                }
+                ret = wolfSSL_X509_INFO_set(current, x509);
+                if (ret  != WOLFSSL_SUCCESS) {
+                    wolfSSL_X509_free(x509);
+                }
+                else {
+                    wolfSSL_sk_X509_INFO_push(localSk, current);
+                }
+            }
+        } while (x509 != NULL && ret == WOLFSSL_SUCCESS);
+        WOLFSSL_LEAVE("wolfSSL_PEM_X509_INFO_read_bio", ret);
+        return localSk;
+    }
+#endif /* OPENSSL_ALL */
+
+    void wolfSSL_X509_NAME_ENTRY_free(WOLFSSL_X509_NAME_ENTRY* ne)
+    {
+        WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_free");
+        if (ne != NULL) {
+            if (ne->value != NULL && ne->value != &(ne->data)) {
+                wolfSSL_ASN1_STRING_free(ne->value);
+            }
+            XFREE(ne, NULL, DYNAMIC_TYPE_NAME_ENTRY);
+        }
+    }
+
+
+    WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_new(void)
+    {
+        WOLFSSL_X509_NAME_ENTRY* ne;
+
+        ne = (WOLFSSL_X509_NAME_ENTRY*)XMALLOC(sizeof(WOLFSSL_X509_NAME_ENTRY),
+                NULL, DYNAMIC_TYPE_NAME_ENTRY);
+        if (ne != NULL) {
+            XMEMSET(ne, 0, sizeof(WOLFSSL_X509_NAME_ENTRY));
+            ne->value = &(ne->data);
+        }
+
+        return ne;
+    }
+
+
+    /* Create a new WOLFSSL_X509_NAME_ENTRY structure based on the text passed
+     * in. Returns NULL on failure */
+    WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_create_by_txt(
+            WOLFSSL_X509_NAME_ENTRY **neIn, const char *txt, int type,
+            const unsigned char *data, int dataSz)
+    {
+        int nid = -1;
+        WOLFSSL_X509_NAME_ENTRY* ne = NULL;
+
+        WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_create_by_txt()");
+
+        if (txt == NULL) {
+            return NULL;
+        }
+
+        if (neIn != NULL) {
+            ne = *neIn;
+        }
+
+        nid = wolfSSL_OBJ_txt2nid(txt);
+        if (nid == NID_undef) {
+            WOLFSSL_MSG("Unable to find text");
+            ne = NULL;
+        }
+        else {
+            if (ne == NULL) {
+                ne = wolfSSL_X509_NAME_ENTRY_new();
+                if (ne == NULL) {
+                    return NULL;
+                }
+            }
+            ne->nid = nid;
+            ne->value = wolfSSL_ASN1_STRING_type_new(type);
+            if (ne->value != NULL) {
+                wolfSSL_ASN1_STRING_set(ne->value, (const void*)data, dataSz);
+                ne->set = 1;
+            }
+        }
+
+        return ne;
+    }
+
+
+    WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_create_by_NID(
+            WOLFSSL_X509_NAME_ENTRY** out, int nid, int type,
+            const unsigned char* data, int dataSz)
+    {
+        WOLFSSL_X509_NAME_ENTRY* ne;
+
+        WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_create_by_NID()");
+
+        ne = wolfSSL_X509_NAME_ENTRY_new();
+        if (ne == NULL) {
+            return NULL;
+        }
+
+        ne->nid = nid;
+        ne->value = wolfSSL_ASN1_STRING_type_new(type);
+        wolfSSL_ASN1_STRING_set(ne->value, (const void*)data, dataSz);
+        ne->set = 1;
+
+        if (out != NULL) {
+            *out = ne;
+        }
+
+        return ne;
+    }
+
+    static int RebuildFullNameAdd(DecodedName* dName, char* data)
+    {
+        int totalLen = 0;
+        int i;
+        char* fullName;
+        int idx;
+
+        if (dName->cnLen != 0)
+            totalLen += dName->cnLen + 4;
+        if (dName->snLen != 0)
+            totalLen += dName->snLen + 4;
+        if (dName->cLen != 0)
+            totalLen += dName->cLen + 3;
+        if (dName->lLen != 0)
+            totalLen += dName->lLen + 3;
+        if (dName->stLen != 0)
+            totalLen += dName->stLen + 4;
+        if (dName->oLen != 0)
+            totalLen += dName->oLen + 3;
+        if (dName->ouLen != 0)
+            totalLen += dName->ouLen + 4;
+        if (dName->emailLen != 0)
+            totalLen += dName->emailLen + 14;
+        if (dName->uidLen != 0)
+            totalLen += dName->uidLen + 5;
+        if (dName->serialLen != 0)
+            totalLen += dName->serialLen + 14;
+        if (dName->dcNum != 0) {
+            for (i = 0; i < dName->dcNum; i++)
+                totalLen += dName->dcLen[i] + 4;
+        }
+
+        fullName = (char*)XMALLOC(totalLen + 1, NULL, DYNAMIC_TYPE_X509);
+        if (fullName == NULL)
+            return MEMORY_E;
+
+        idx = 0;
+        dName->entryCount = 0;
+        if (dName->cnLen != 0) {
+            dName->entryCount++;
+            XMEMCPY(fullName + idx, WOLFSSL_COMMON_NAME, 4);
+            idx += 4;
+            if (dName->cnIdx == -1)
+                XMEMCPY(fullName + idx, data, dName->cnLen);
+            else {
+                XMEMCPY(fullName + idx, dName->fullName + dName->cnIdx,
+                                                                  dName->cnLen);
+            }
+            dName->cnIdx = idx;
+            idx += dName->cnLen;
+        }
+        if (dName->snLen != 0) {
+            dName->entryCount++;
+            XMEMCPY(fullName + idx, WOLFSSL_SUR_NAME, 4);
+            idx += 4;
+            if (dName->snIdx == -1)
+                XMEMCPY(fullName + idx, data, dName->snLen);
+            else {
+                XMEMCPY(fullName + idx, dName->fullName + dName->snIdx,
+                                                                  dName->snLen);
+            }
+            dName->snIdx = idx;
+            idx += dName->snLen;
+        }
+        if (dName->cLen != 0) {
+            dName->entryCount++;
+            XMEMCPY(fullName + idx, WOLFSSL_COUNTRY_NAME, 3);
+            idx += 3;
+            if (dName->cIdx == -1)
+                XMEMCPY(fullName + idx, data, dName->cLen);
+            else {
+                XMEMCPY(fullName + idx, dName->fullName + dName->cIdx,
+                                                                   dName->cLen);
+            }
+            dName->cIdx = idx;
+            idx += dName->cLen;
+        }
+        if (dName->lLen != 0) {
+            dName->entryCount++;
+            XMEMCPY(fullName + idx, WOLFSSL_LOCALITY_NAME, 3);
+            idx += 3;
+            if (dName->lIdx == -1)
+                XMEMCPY(fullName + idx, data, dName->lLen);
+            else {
+                XMEMCPY(fullName + idx, dName->fullName + dName->lIdx,
+                                                                   dName->lLen);
+            }
+            dName->lIdx = idx;
+            idx += dName->lLen;
+        }
+        if (dName->stLen != 0) {
+            dName->entryCount++;
+            XMEMCPY(fullName + idx, WOLFSSL_STATE_NAME, 4);
+            idx += 4;
+            if (dName->stIdx == -1)
+                XMEMCPY(fullName + idx, data, dName->stLen);
+            else {
+                XMEMCPY(fullName + idx, dName->fullName + dName->stIdx,
+                                                                  dName->stLen);
+            }
+            dName->stIdx = idx;
+            idx += dName->stLen;
+        }
+        if (dName->oLen != 0) {
+            dName->entryCount++;
+            XMEMCPY(fullName + idx, WOLFSSL_ORG_NAME, 3);
+            idx += 3;
+            if (dName->oIdx == -1)
+                XMEMCPY(fullName + idx, data, dName->oLen);
+            else {
+                XMEMCPY(fullName + idx, dName->fullName + dName->oIdx,
+                                                                   dName->oLen);
+            }
+            dName->oIdx = idx;
+            idx += dName->oLen;
+        }
+        if (dName->ouLen != 0) {
+            dName->entryCount++;
+            XMEMCPY(fullName + idx, WOLFSSL_ORGUNIT_NAME, 4);
+            idx += 4;
+            if (dName->ouIdx == -1)
+                XMEMCPY(fullName + idx, data, dName->ouLen);
+            else {
+                XMEMCPY(fullName + idx, dName->fullName + dName->ouIdx,
+                                                                  dName->ouLen);
+            }
+            dName->ouIdx = idx;
+            idx += dName->ouLen;
+        }
+        if (dName->emailLen != 0) {
+            dName->entryCount++;
+            XMEMCPY(fullName + idx, "/emailAddress=", 14);
+            idx += 14;
+            if (dName->emailIdx == -1)
+                XMEMCPY(fullName + idx, data, dName->emailLen);
+            else {
+                XMEMCPY(fullName + idx, dName->fullName + dName->emailIdx,
+                                                               dName->emailLen);
+            }
+            dName->emailIdx = idx;
+            idx += dName->emailLen;
+        }
+        if (dName->dcNum != 0) {
+            for (i = 0; i < dName->dcNum; i++) {
+                dName->entryCount++;
+                XMEMCPY(fullName + idx, WOLFSSL_DOMAIN_COMPONENT, 4);
+                idx += 4;
+                XMEMCPY(fullName + idx, dName->fullName + dName->dcIdx[i],
+                                                               dName->dcLen[i]);
+                dName->dcIdx[i] = idx;
+                idx += dName->dcLen[i];
+            }
+        }
+        if (dName->uidLen != 0) {
+            dName->entryCount++;
+            XMEMCPY(fullName + idx, "/UID=", 5);
+            idx += 5;
+            if (dName->uidIdx == -1)
+                XMEMCPY(fullName + idx, data, dName->uidLen);
+            else {
+                XMEMCPY(fullName + idx, dName->fullName + dName->uidIdx,
+                                                                 dName->uidLen);
+            }
+            dName->uidIdx = idx;
+            idx += dName->uidLen;
+        }
+        if (dName->serialLen != 0) {
+            dName->entryCount++;
+            XMEMCPY(fullName + idx, WOLFSSL_SERIAL_NUMBER, 14);
+            idx += 14;
+            if (dName->serialIdx == -1)
+                XMEMCPY(fullName + idx, data, dName->serialLen);
+            else {
+                XMEMCPY(fullName + idx, dName->fullName + dName->serialIdx,
+                                                              dName->serialLen);
+            }
+            dName->serialIdx = idx;
+            idx += dName->serialLen;
+        }
+
+        if (dName->fullName != NULL)
+            XFREE(dName->fullName, NULL, DYNAMIC_TYPE_X509);
+        dName->fullName = fullName;
+        dName->fullNameLen = idx + 1;
+
+        return 0;
+    }
+
+    /* Copies entry into name. With it being copied freeing entry becomes the
+     * callers responsibility.
+     * returns 1 for success and 0 for error */
+    int wolfSSL_X509_NAME_add_entry(WOLFSSL_X509_NAME* name,
+            WOLFSSL_X509_NAME_ENTRY* entry, int idx, int set)
+    {
+        int i;
+        int fullName = 1;
+
+        WOLFSSL_ENTER("wolfSSL_X509_NAME_add_entry()");
+
+        switch (entry->nid) {
+            case ASN_COMMON_NAME:
+                name->fullName.cnIdx = -1;
+                name->fullName.cnLen = entry->value->length;
+                name->fullName.cnNid = entry->nid;
+                break;
+            case ASN_SUR_NAME:
+                name->fullName.snIdx = -1;
+                name->fullName.snLen = entry->value->length;
+                name->fullName.snNid = entry->nid;
+                break;
+            case ASN_SERIAL_NUMBER:
+                name->fullName.serialIdx = -1;
+                name->fullName.serialLen = entry->value->length;
+                name->fullName.serialNid = entry->nid;
+                break;
+            case ASN_COUNTRY_NAME:
+                name->fullName.cIdx = -1;
+                name->fullName.cLen = entry->value->length;
+                name->fullName.cNid = entry->nid;
+                break;
+            case ASN_LOCALITY_NAME:
+                name->fullName.lIdx = -1;
+                name->fullName.lLen = entry->value->length;
+                name->fullName.lNid = entry->nid;
+                break;
+            case ASN_STATE_NAME:
+                name->fullName.stIdx = -1;
+                name->fullName.stLen = entry->value->length;
+                name->fullName.stNid = entry->nid;
+                break;
+            case ASN_ORG_NAME:
+                name->fullName.oIdx = -1;
+                name->fullName.oLen = entry->value->length;
+                name->fullName.oNid = entry->nid;
+                break;
+            case ASN_ORGUNIT_NAME:
+                name->fullName.ouIdx = -1;
+                name->fullName.ouLen = entry->value->length;
+                name->fullName.ouNid = entry->nid;
+                break;
+            case NID_emailAddress:
+                name->fullName.emailIdx = -1;
+                name->fullName.emailLen = entry->value->length;
+                name->fullName.emailNid = entry->nid;
+                break;
+            case ASN_USER_ID:
+                name->fullName.uidIdx = -1;
+                name->fullName.uidLen = entry->value->length;
+                name->fullName.uidNid = entry->nid;
+                break;
+            case ASN_DOMAIN_COMPONENT:
+                name->fullName.dcIdx[0] = -1;
+                name->fullName.dcLen[0] = entry->value->length;
+                break;
+            default:
+                fullName = 0;
+                break;
+        }
+
+        if (fullName) {
+            int nid = entry->nid;
+
+            if (nid == NID_emailAddress) {
+                nid = (int)ASN_EMAIL_NAME;
+            }
+
+            if (idx >= DN_NAMES_MAX + DOMAIN_COMPONENT_MAX) {
+                return WOLFSSL_FAILURE;
+            }
+
+            if (idx >= 0) {
+                name->fullName.loc[idx] = nid;
+                if (idx == name->fullName.locSz) {
+                    name->fullName.locSz += 1;
+                }
+            }
+
+            /* place at end */
+            if (idx < 0 && name->fullName.locSz + 1
+                    < DN_NAMES_MAX + DOMAIN_COMPONENT_MAX) {
+                name->fullName.loc[name->fullName.locSz] = nid;
+                name->fullName.locSz += 1;
+            }
+
+            if (RebuildFullNameAdd(&name->fullName, entry->value->data) != 0)
+                return WOLFSSL_FAILURE;
+        }
+        else {
+            for (i = 0; i < MAX_NAME_ENTRIES; i++) {
+                if (name->extra[i].set != 1) { /* not set so overwritten */
+                    WOLFSSL_X509_NAME_ENTRY* current = &(name->extra[i]);
+                    WOLFSSL_ASN1_STRING*     str;
+
+                    WOLFSSL_MSG("Found place for name entry");
+
+                    XMEMCPY(current, entry, sizeof(WOLFSSL_X509_NAME_ENTRY));
+                    str = entry->value;
+                    XMEMCPY(&(current->data), str, sizeof(WOLFSSL_ASN1_STRING));
+                    current->value = &(current->data);
+                    current->data.data = (char*)XMALLOC(str->length,
+                           name->x509->heap, DYNAMIC_TYPE_OPENSSL);
+
+                    if (current->data.data == NULL) {
+                        return SSL_FAILURE;
+                    }
+                    XMEMCPY(current->data.data, str->data, str->length);
+
+                    /* make sure is null terminated */
+                    current->data.data[str->length - 1] = '\0';
+
+                    current->set = 1; /* make sure now listed as set */
+                    break;
+                }
+            }
+
+            if (i == MAX_NAME_ENTRIES) {
+                WOLFSSL_MSG("No spot found for name entry");
+                return SSL_FAILURE;
+            }
+        }
+
+        (void)idx;
+        (void)set;
+        return SSL_SUCCESS;
+    }
+
+    int wolfSSL_X509_NAME_add_entry_by_txt(WOLFSSL_X509_NAME *name,
+                                           const char *field, int type,
+                                           const unsigned char *bytes, int len,
+                                           int loc, int set)
+    {
+        int ret = WOLFSSL_FAILURE;
+        int nid;
+        WOLFSSL_X509_NAME_ENTRY* entry;
+
+        (void)type;
+        WOLFSSL_ENTER("wolfSSL_X509_NAME_add_entry_by_txt");
+
+        if (name == NULL || field == NULL)
+            return WOLFSSL_FAILURE;
+
+        if ((nid = wolfSSL_OBJ_txt2nid(field)) == NID_undef)
+            return WOLFSSL_FAILURE;
+
+        entry = wolfSSL_X509_NAME_ENTRY_create_by_NID(NULL,
+                  nid, type, (unsigned char*)bytes, len);
+        if (entry == NULL)
+            return WOLFSSL_FAILURE;
+
+        ret = wolfSSL_X509_NAME_add_entry(name, entry, loc, set);
+        wolfSSL_X509_NAME_ENTRY_free(entry);
+
+        return ret;
+    }
+
+    int wolfSSL_X509_NAME_add_entry_by_NID(WOLFSSL_X509_NAME *name, int nid,
+                                           int type, const unsigned char *bytes,
+                                           int len, int loc, int set)
+    {
+        int ret;
+        WOLFSSL_X509_NAME_ENTRY* entry;
+        entry = wolfSSL_X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len);
+        if (entry == NULL)
+            return WOLFSSL_FAILURE;
+        ret = wolfSSL_X509_NAME_add_entry(name, entry, loc, set);
+        wolfSSL_X509_NAME_ENTRY_free(entry);
+        return ret;
+    }
+    #endif /* !NO_CERTS */
+
+
+    /* NID variables are dependent on compatibility header files currently
+     *
+     * returns a pointer to a new WOLFSSL_ASN1_OBJECT struct on success and NULL
+     *         on fail
+     */
+
+    WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_nid2obj(int id)
+    {
+        return wolfSSL_OBJ_nid2obj_ex(id, NULL);
+    }
+
+
+    WOLFSSL_LOCAL WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_nid2obj_ex(int id,
+                                                WOLFSSL_ASN1_OBJECT* arg_obj)
+    {
+        word32 oidSz = 0;
+        const byte* oid;
+        word32 type = 0;
+        WOLFSSL_ASN1_OBJECT* obj = arg_obj;
+        byte objBuf[MAX_OID_SZ + MAX_LENGTH_SZ + 1]; /* +1 for object tag */
+        word32 objSz = 0;
+        const char* sName = NULL;
+        int i;
+
+        WOLFSSL_ENTER("wolfSSL_OBJ_nid2obj()");
+
+        for (i = 0; i < (int)WOLFSSL_OBJECT_INFO_SZ; i++) {
+            if (wolfssl_object_info[i].nid == id) {
+                id = wolfssl_object_info[i].id;
+                sName = wolfssl_object_info[i].sName;
+                type = wolfssl_object_info[i].type;
+                break;
+            }
+        }
+        if (i == (int)WOLFSSL_OBJECT_INFO_SZ) {
+            WOLFSSL_MSG("NID not in table");
+        #ifdef WOLFSSL_QT
+            sName = NULL;
+            type = id;
+        #else
+            return NULL;
+        #endif
+        }
+
+    #ifdef HAVE_ECC
+         if (type == 0 && wc_ecc_get_oid(id, &oid, &oidSz) > 0) {
+             type = oidCurveType;
+         }
+    #endif /* HAVE_ECC */
+
+        if (sName != NULL) {
+            if (XSTRLEN(sName) > WOLFSSL_MAX_SNAME - 1) {
+                WOLFSSL_MSG("Attempted short name is too large");
+                return NULL;
+            }
+        }
+
+        oid = OidFromId(id, type, &oidSz);
+
+        /* set object ID to buffer */
+        if (obj == NULL){
+            obj = wolfSSL_ASN1_OBJECT_new();
+            if (obj == NULL) {
+                WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+                return NULL;
+            }
+            obj->dynamic |= WOLFSSL_ASN1_DYNAMIC;
+        } else {
+            obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC;
+        }
+        obj->type    = id;
+        obj->grp     = type;
+
+        obj->sName[0] = '\0';
+        if (sName != NULL) {
+            XMEMCPY(obj->sName, (char*)sName, XSTRLEN((char*)sName));
+        }
+
+        objBuf[0] = ASN_OBJECT_ID; objSz++;
+        objSz += SetLength(oidSz, objBuf + 1);
+        XMEMCPY(objBuf + objSz, oid, oidSz);
+        objSz     += oidSz;
+        obj->objSz = objSz;
+        if(((obj->dynamic & WOLFSSL_ASN1_DYNAMIC_DATA) != 0) ||
+                                                           (obj->obj == NULL)) {
+            obj->obj = (byte*)XREALLOC((byte*)obj->obj, obj->objSz, NULL,
+                                                             DYNAMIC_TYPE_ASN1);
+            if (obj->obj == NULL) {
+                wolfSSL_ASN1_OBJECT_free(obj);
+                return NULL;
+            }
+            obj->dynamic |= WOLFSSL_ASN1_DYNAMIC_DATA ;
+        } else {
+            obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA ;
+        }
+        XMEMCPY((byte*)obj->obj, objBuf, obj->objSz);
+
+        (void)type;
+
+        return obj;
+    }
+
+    static const char* oid_translate_num_to_str(const char* oid)
+    {
+        const struct oid_dict {
+            const char* num;
+            const char* desc;
+        } oid_dict[] = {
+            { "2.5.29.37.0",       "Any Extended Key Usage" },
+            { "1.3.6.1.5.5.7.3.1", "TLS Web Server Authentication" },
+            { "1.3.6.1.5.5.7.3.2", "TLS Web Client Authentication" },
+            { "1.3.6.1.5.5.7.3.3", "Code Signing" },
+            { "1.3.6.1.5.5.7.3.4", "E-mail Protection" },
+            { "1.3.6.1.5.5.7.3.8", "Time Stamping" },
+            { "1.3.6.1.5.5.7.3.9", "OCSP Signing" },
+            { NULL, NULL }
+        };
+        const struct oid_dict* idx;
+
+        for (idx = oid_dict; idx->num != NULL; idx++) {
+            if (!XSTRNCMP(oid, idx->num, XSTRLEN(idx->num))) {
+                return idx->desc;
+            }
+        }
+        return NULL;
+    }
+
+    /* if no_name is one than use numerical form otherwise can be short name.
+     *
+     * returns the buffer size on success
+     */
+    int wolfSSL_OBJ_obj2txt(char *buf, int bufLen, WOLFSSL_ASN1_OBJECT *a, int no_name)
+    {
+        int bufSz;
+        const char* desc;
+
+        WOLFSSL_ENTER("wolfSSL_OBJ_obj2txt()");
+
+        if (buf == NULL || bufLen <= 1 || a == NULL) {
+            WOLFSSL_MSG("Bad input argument");
+            return WOLFSSL_FAILURE;
+        }
+
+        if (no_name == 1) {
+            int    length;
+            word32 idx = 0;
+            byte   tag;
+
+            if (GetASNTag(a->obj, &idx, &tag, a->objSz) != 0) {
+                return WOLFSSL_FAILURE;
+            }
+
+            if (tag != ASN_OBJECT_ID) {
+                WOLFSSL_MSG("Bad ASN1 Object");
+                return WOLFSSL_FAILURE;
+            }
+
+            if (GetLength((const byte*)a->obj, &idx, &length,
+                           a->objSz) < 0 || length < 0) {
+                return ASN_PARSE_E;
+            }
+
+            if (bufLen < MAX_OID_STRING_SZ) {
+                bufSz = bufLen - 1;
+            }
+            else {
+                bufSz = MAX_OID_STRING_SZ;
+            }
+
+            if ((bufSz = DecodePolicyOID(buf, (word32)bufSz, a->obj + idx,
+                        (word32)length)) <= 0) {
+                WOLFSSL_MSG("Error decoding OID");
+                return WOLFSSL_FAILURE;
+            }
+
+        }
+        else { /* return short name */
+            if (XSTRLEN(a->sName) + 1 < (word32)bufLen - 1) {
+                bufSz = (int)XSTRLEN(a->sName);
+            }
+            else {
+                bufSz = bufLen - 1;
+            }
+            if (bufSz) {
+                XMEMCPY(buf, a->sName, bufSz);
+            }
+            else if (wolfSSL_OBJ_obj2txt(buf, bufLen, a, 1)) {
+                if ((desc = oid_translate_num_to_str(buf))) {
+                    bufSz = (int)XSTRLEN(desc);
+                    XMEMCPY(buf, desc, min(bufSz, bufLen));
+                }
+            }
+            else if (a->type == GEN_DNS || a->type == GEN_EMAIL || a->type == GEN_URI) {
+                bufSz = (int)XSTRLEN((const char*)a->obj);
+                XMEMCPY(buf, a->obj, min(bufSz, bufLen));
+            }
+        }
+
+        buf[bufSz] = '\0';
+        #ifdef WOLFSSL_QT
+            /* For unknown extension types, QT expects the short name to be the
+                text representation of the oid */
+            if (XSTRLEN(a->sName) == 0) {
+                XMEMCPY(a->sName, buf, bufSz);
+            }
+        #endif
+        return bufSz;
+    }
+#endif /* OPENSSL_EXTRA */
+
+#if defined(OPENSSL_EXTRA) && !defined(NO_ASN)
+    /* DN_Tags to strings */
+    static const struct DN_Tag_Strings {
+        enum DN_Tags tag;
+        const char* str;
+    } dn_tag_strings[] = {
+           { ASN_COMMON_NAME,      "CN" },
+           { ASN_SUR_NAME,         "SN" },
+           { ASN_SERIAL_NUMBER,    "serialNumber" },
+           { ASN_COUNTRY_NAME,     "C" },
+           { ASN_LOCALITY_NAME,    "L" },
+           { ASN_STATE_NAME,       "ST" },
+           { ASN_ORG_NAME,         "O"},
+           { ASN_ORGUNIT_NAME,     "OU"},
+           { ASN_BUS_CAT,          "businessCategory"},
+           { ASN_EMAIL_NAME,       "emailAddress"},
+           { ASN_USER_ID,          "UID"},
+           { ASN_DOMAIN_COMPONENT, "DC"},
+           { ASN_DN_NULL,          NULL }
+    };
+
+    int wolfSSL_X509_NAME_get_index_by_OBJ(WOLFSSL_X509_NAME *name,
+                                           const WOLFSSL_ASN1_OBJECT *obj,
+                                           int idx) {
+        const struct DN_Tag_Strings* dn;
+        enum DN_Tags tag = ASN_DN_NULL;
+
+        if (!name || idx >= name->fullName.locSz ||
+                !obj || !obj->obj) {
+            return -1;
+        }
+
+        if (idx < 0) {
+            idx = 0;
+        }
+        for (dn = dn_tag_strings; dn->str != NULL; dn++) {
+            /* Find the DN_Tags number for the name */
+            if (XSTRNCMP((const char*) obj->sName, dn->str, obj->objSz - 1) == 0) {
+                tag = dn->tag;
+                break;
+            }
+        }
+        if (!tag) {
+            /* Unable to identify desired name */
+            return -1;
+        }
+        for (idx++; idx < name->fullName.locSz; idx++) {
+            /* Find index of desired name */
+            if ((enum DN_Tags)name->fullName.loc[idx] == tag) {
+                return idx;
+            }
+        }
+        return -1;
+    }
+#endif
+
+#if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \
+    defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \
+    defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \
+    defined(WOLFSSL_HAPROXY)
+
+#ifndef NO_SHA
+    /* One shot SHA1 hash of message.
+     *
+     * d  message to hash
+     * n  size of d buffer
+     * md buffer to hold digest. Should be SHA_DIGEST_SIZE.
+     *
+     * Note: if md is null then a static buffer of SHA_DIGEST_SIZE is used.
+     *       When the static buffer is used this function is not thread safe.
+     *
+     * Returns a pointer to the message digest on success and NULL on failure.
+     */
+    unsigned char *wolfSSL_SHA1(const unsigned char *d, size_t n,
+            unsigned char *md)
+    {
+        static byte dig[WC_SHA_DIGEST_SIZE];
+        wc_Sha sha;
+
+        WOLFSSL_ENTER("wolfSSL_SHA1");
+
+        if (wc_InitSha_ex(&sha, NULL, 0) != 0) {
+            WOLFSSL_MSG("SHA1 Init failed");
+            return NULL;
+        }
+
+        if (wc_ShaUpdate(&sha, (const byte*)d, (word32)n) != 0) {
+            WOLFSSL_MSG("SHA1 Update failed");
+            return NULL;
+        }
+
+        if (wc_ShaFinal(&sha, dig) != 0) {
+            WOLFSSL_MSG("SHA1 Final failed");
+            return NULL;
+        }
+
+        wc_ShaFree(&sha);
+
+        if (md != NULL) {
+            XMEMCPY(md, dig, WC_SHA_DIGEST_SIZE);
+            return md;
+        }
+        else {
+            return (unsigned char*)dig;
+        }
+    }
+#endif /* ! NO_SHA */
+
+#ifndef NO_SHA256
+    /* One shot SHA256 hash of message.
+     *
+     * d  message to hash
+     * n  size of d buffer
+     * md buffer to hold digest. Should be WC_SHA256_DIGEST_SIZE.
+     *
+     * Note: if md is null then a static buffer of WC_SHA256_DIGEST_SIZE is used.
+     *       When the static buffer is used this function is not thread safe.
+     *
+     * Returns a pointer to the message digest on success and NULL on failure.
+     */
+    unsigned char *wolfSSL_SHA256(const unsigned char *d, size_t n,
+            unsigned char *md)
+    {
+        static byte dig[WC_SHA256_DIGEST_SIZE];
+        wc_Sha256 sha;
+
+        WOLFSSL_ENTER("wolfSSL_SHA256");
+
+        if (wc_InitSha256_ex(&sha, NULL, 0) != 0) {
+            WOLFSSL_MSG("SHA256 Init failed");
+            return NULL;
+        }
+
+        if (wc_Sha256Update(&sha, (const byte*)d, (word32)n) != 0) {
+            WOLFSSL_MSG("SHA256 Update failed");
+            return NULL;
+        }
+
+        if (wc_Sha256Final(&sha, dig) != 0) {
+            WOLFSSL_MSG("SHA256 Final failed");
+            return NULL;
+        }
+
+        wc_Sha256Free(&sha);
+
+        if (md != NULL) {
+            XMEMCPY(md, dig, WC_SHA256_DIGEST_SIZE);
+            return md;
+        }
+        else {
+            return (unsigned char*)dig;
+        }
+    }
+#endif /* ! NO_SHA256 */
+
+#ifdef WOLFSSL_SHA384
+     /* One shot SHA384 hash of message.
+      *
+      * d  message to hash
+      * n  size of d buffer
+      * md buffer to hold digest. Should be WC_SHA256_DIGEST_SIZE.
+      *
+      * Note: if md is null then a static buffer of WC_SHA256_DIGEST_SIZE is used.
+      *       When the static buffer is used this function is not thread safe.
+      *
+      * Returns a pointer to the message digest on success and NULL on failure.
+      */
+     unsigned char *wolfSSL_SHA384(const unsigned char *d, size_t n,
+             unsigned char *md)
+     {
+         static byte dig[WC_SHA384_DIGEST_SIZE];
+         wc_Sha384 sha;
+
+         WOLFSSL_ENTER("wolfSSL_SHA384");
+
+         if (wc_InitSha384_ex(&sha, NULL, 0) != 0) {
+             WOLFSSL_MSG("SHA384 Init failed");
+             return NULL;
+         }
+
+         if (wc_Sha384Update(&sha, (const byte*)d, (word32)n) != 0) {
+             WOLFSSL_MSG("SHA384 Update failed");
+             return NULL;
+         }
+
+         if (wc_Sha384Final(&sha, dig) != 0) {
+             WOLFSSL_MSG("SHA384 Final failed");
+             return NULL;
+         }
+
+         wc_Sha384Free(&sha);
+
+         if (md != NULL) {
+             XMEMCPY(md, dig, WC_SHA384_DIGEST_SIZE);
+             return md;
+         }
+         else {
+             return (unsigned char*)dig;
+         }
+     }
+#endif /* WOLFSSL_SHA384  */
+
+
+#if defined(WOLFSSL_SHA512)
+     /* One shot SHA512 hash of message.
+      *
+      * d  message to hash
+      * n  size of d buffer
+      * md buffer to hold digest. Should be WC_SHA256_DIGEST_SIZE.
+      *
+      * Note: if md is null then a static buffer of WC_SHA256_DIGEST_SIZE is used.
+      *       When the static buffer is used this function is not thread safe.
+      *
+      * Returns a pointer to the message digest on success and NULL on failure.
+      */
+     unsigned char *wolfSSL_SHA512(const unsigned char *d, size_t n,
+             unsigned char *md)
+     {
+         static byte dig[WC_SHA512_DIGEST_SIZE];
+         wc_Sha512 sha;
+
+         WOLFSSL_ENTER("wolfSSL_SHA512");
+
+         if (wc_InitSha512_ex(&sha, NULL, 0) != 0) {
+             WOLFSSL_MSG("SHA512 Init failed");
+             return NULL;
+         }
+
+         if (wc_Sha512Update(&sha, (const byte*)d, (word32)n) != 0) {
+             WOLFSSL_MSG("SHA512 Update failed");
+             return NULL;
+         }
+
+         if (wc_Sha512Final(&sha, dig) != 0) {
+             WOLFSSL_MSG("SHA512 Final failed");
+             return NULL;
+         }
+
+         wc_Sha512Free(&sha);
+
+         if (md != NULL) {
+             XMEMCPY(md, dig, WC_SHA512_DIGEST_SIZE);
+             return md;
+         }
+         else {
+             return (unsigned char*)dig;
+         }
+     }
+#endif /* defined(WOLFSSL_SHA512)  */
+#endif /* OPENSSL_EXTRA */
+
+#ifndef WOLFCRYPT_ONLY
+#if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \
+    defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \
+    defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \
+    defined(WOLFSSL_HAPROXY)
+
+    char wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("wolfSSL_CTX_use_certificate");
+
+        FreeDer(&ctx->certificate); /* Make sure previous is free'd */
+        ret = AllocDer(&ctx->certificate, x->derCert->length, CERT_TYPE,
+                       ctx->heap);
+        if (ret != 0)
+            return 0;
+
+        XMEMCPY(ctx->certificate->buffer, x->derCert->buffer,
+                x->derCert->length);
+#ifdef KEEP_OUR_CERT
+        if (ctx->ourCert != NULL && ctx->ownOurCert) {
+            FreeX509(ctx->ourCert);
+            XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509);
+        }
+        #ifndef WOLFSSL_X509_STORE_CERTS
+        ctx->ourCert = x;
+        #else
+        ctx->ourCert = wolfSSL_X509_d2i(NULL, x->derCert->buffer,x->derCert->length);
+        if(ctx->ourCert == NULL){
+            return 0;
+        }
+        #endif
+
+        ctx->ownOurCert = 0;
+#endif
+
+        /* Update the available options with public keys. */
+        switch (x->pubKeyOID) {
+            case RSAk:
+                ctx->haveRSA = 1;
+                break;
+        #ifdef HAVE_ED25519
+            case ED25519k:
+        #endif
+        #ifdef HAVE_ED448
+            case ED448k:
+        #endif
+            case ECDSAk:
+                ctx->haveECC = 1;
+        #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
+                ctx->pkCurveOID = x->pkCurveOID;
+        #endif
+                break;
+        }
+
+        return WOLFSSL_SUCCESS;
+    }
+
+    int wolfSSL_CTX_add1_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
+    {
+        int ret;
+        if (ctx == NULL || x509 == NULL || x509->derCert == NULL) {
+            return WOLFSSL_FAILURE;
+        }
+
+        ret = wolfSSL_CTX_load_verify_buffer(ctx, x509->derCert->buffer,
+            x509->derCert->length, WOLFSSL_FILETYPE_ASN1);
+
+        return (ret == 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
+    }
+
+    int wolfSSL_BIO_read_filename(WOLFSSL_BIO *b, const char *name) {
+    #ifndef NO_FILESYSTEM
+        XFILE fp;
+
+        WOLFSSL_ENTER("wolfSSL_BIO_new_file");
+
+        if ((wolfSSL_BIO_get_fp(b, &fp) == WOLFSSL_SUCCESS) && (fp != XBADFILE))
+        {
+            XFCLOSE(fp);
+        }
+
+        fp = XFOPEN(name, "r");
+        if (fp == XBADFILE)
+            return WOLFSSL_BAD_FILE;
+
+        if (wolfSSL_BIO_set_fp(b, fp, BIO_CLOSE) != WOLFSSL_SUCCESS) {
+            XFCLOSE(fp);
+            return WOLFSSL_BAD_FILE;
+        }
+
+        /* file is closed when bio is free'd */
+        return WOLFSSL_SUCCESS;
+    #else
+        (void)name;
+        (void)b;
+        return WOLFSSL_NOT_IMPLEMENTED;
+    #endif
+    }
+
+    /* Return the corresponding short name for the nid <n>.
+     * or NULL if short name can't be found.
+     */
+    const char * wolfSSL_OBJ_nid2sn(int n) {
+        const WOLFSSL_ObjectInfo *obj_info = wolfssl_object_info;
+        size_t i;
+        WOLFSSL_ENTER("wolfSSL_OBJ_nid2sn");
+        for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++, obj_info++) {
+            if (obj_info->nid == n) {
+                return obj_info->sName;
+            }
+        }
+        WOLFSSL_MSG("SN not found");
+        return NULL;
+    }
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+    int wolfSSL_OBJ_sn2nid(const char *sn) {
+        WOLFSSL_ENTER("wolfSSL_OBJ_sn2nid");
+        if (sn == NULL)
+            return NID_undef;
+        return wc_OBJ_sn2nid(sn);
+    }
+#endif
+
+
+    /* Gets the NID value that corresponds with the ASN1 object.
+     *
+     * o ASN1 object to get NID of
+     *
+     * Return NID on success and a negative value on failure
+     */
+    int wolfSSL_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o)
+    {
+        word32 oid = 0;
+        word32 idx = 0;
+
+        WOLFSSL_ENTER("wolfSSL_OBJ_obj2nid");
+
+        if (o == NULL) {
+            return -1;
+        }
+
+        #ifdef WOLFSSL_QT
+        if (o->grp == oidCertExtType) {
+            /* If nid is an unknown extension, return NID_undef */
+            if (wolfSSL_OBJ_nid2sn(o->nid) == NULL)
+                return NID_undef;
+        }
+        #endif
+
+        if (o->nid > 0)
+            return o->nid;
+        if (GetObjectId(o->obj, &idx, &oid, o->grp, o->objSz) < 0) {
+            WOLFSSL_MSG("Issue getting OID of object");
+            return -1;
+        }
+
+        return oid2nid(oid, o->grp);
+    }
+
+    /* Returns the long name that corresponds with an ASN1_OBJECT nid value.
+     *  n : NID value of ASN1_OBJECT to search */
+    const char* wolfSSL_OBJ_nid2ln(int n)
+    {
+        const WOLFSSL_ObjectInfo *obj_info = wolfssl_object_info;
+        size_t i;
+        WOLFSSL_ENTER("wolfSSL_OBJ_nid2ln");
+        for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++, obj_info++) {
+            if (obj_info->nid == n) {
+                return obj_info->lName;
+            }
+        }
+        WOLFSSL_MSG("NID not found in table");
+        return NULL;
+    }
+
+    /* Return the corresponding NID for the long name <ln>
+     * or NID_undef if NID can't be found.
+     */
+    int wolfSSL_OBJ_ln2nid(const char *ln)
+    {
+        const WOLFSSL_ObjectInfo *obj_info = wolfssl_object_info;
+        size_t i, lnlen;
+        WOLFSSL_ENTER("wolfSSL_OBJ_ln2nid");
+        if (ln && (lnlen = XSTRLEN(ln)) > 0) {
+            /* Accept input like "/commonName=" */
+            if (ln[0] == '/') {
+                ln++;
+                lnlen--;
+            }
+            if (lnlen) {
+                if (ln[lnlen-1] == '=') {
+                    lnlen--;
+                }
+                for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++, obj_info++) {
+                    if (lnlen == XSTRLEN(obj_info->lName) &&
+                            XSTRNCMP(ln, obj_info->lName, lnlen) == 0) {
+                        return obj_info->nid;
+                    }
+                }
+            }
+        }
+        return NID_undef;
+    }
+
+    /* compares two objects, return 0 if equal */
+    int wolfSSL_OBJ_cmp(const WOLFSSL_ASN1_OBJECT* a,
+                        const WOLFSSL_ASN1_OBJECT* b)
+    {
+        WOLFSSL_ENTER("wolfSSL_OBJ_cmp");
+
+        if (a != NULL && b != NULL &&
+            a->obj != NULL && b->obj != NULL &&
+            a->objSz == b->objSz) {
+            return XMEMCMP(a->obj, b->obj, a->objSz);
+        }
+
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    /* Gets the NID value that is related to the OID string passed in. Example
+     * string would be "2.5.29.14" for subject key ID.
+     *
+     * returns NID value on success and NID_undef on error
+     */
+    int wolfSSL_OBJ_txt2nid(const char* s)
+    {
+        unsigned int i;
+    #ifdef WOLFSSL_CERT_EXT
+        int ret;
+        unsigned int sum = 0;
+        unsigned int outSz = MAX_OID_SZ;
+        unsigned char out[MAX_OID_SZ];
+    #endif
+
+        WOLFSSL_ENTER("OBJ_txt2nid");
+
+        if (s == NULL) {
+            return NID_undef;
+        }
+
+    #ifdef WOLFSSL_CERT_EXT
+        ret = EncodePolicyOID(out, &outSz, s, NULL);
+        if (ret == 0) {
+            /* sum OID */
+            for (i = 0; i < outSz; i++) {
+                sum += out[i];
+            }
+        }
+    #endif /* WOLFSSL_CERT_EXT */
+
+        /* get the group that the OID's sum is in
+         * @TODO possible conflict with multiples */
+        for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++) {
+            int len;
+        #ifdef WOLFSSL_CERT_EXT
+            if (ret == 0) {
+                if (wolfssl_object_info[i].id == (int)sum) {
+                    return wolfssl_object_info[i].nid;
+                }
+            }
+        #endif
+
+            /* try as a short name */
+            len = (int)XSTRLEN(s);
+            if (XSTRNCMP(wolfssl_object_info[i].sName, s, len) == 0) {
+                return wolfssl_object_info[i].nid;
+            }
+
+            /* try as a long name */
+            if (XSTRNCMP(wolfssl_object_info[i].lName, s, len) == 0) {
+                return wolfssl_object_info[i].nid;
+            }
+        }
+
+        return NID_undef;
+    }
+
+    /* Creates new ASN1_OBJECT from short name, long name, or text
+     * representation of oid. If no_name is 0, then short name, long name, and
+     * numerical value of oid are interpreted. If no_name is 1, then only the
+     * numerical value of the oid is interpreted.
+     *
+     * Returns pointer to ASN1_OBJECT on success, or NULL on error.
+     */
+#if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN)
+    WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_txt2obj(const char* s, int no_name)
+    {
+        int len, i, ret;
+        int nid = NID_undef;
+        unsigned int outSz = MAX_OID_SZ;
+        unsigned char out[MAX_OID_SZ];
+        unsigned int sum = 0;
+
+        WOLFSSL_ENTER("wolfSSL_OBJ_txt2obj");
+
+        if (s == NULL)
+            return NULL;
+
+        /* If s is numerical value, try to sum oid */
+        ret = EncodePolicyOID(out, &outSz, s, NULL);
+        if (ret == 0) {
+            for (i = 0; i < (int)outSz; i++) {
+                sum += out[i];
+            }
+        }
+
+        len = (int)XSTRLEN(s);
+
+        /* TODO: update short names in wolfssl_object_info and check OID sums
+           are correct */
+        for (i = 0; i < (int)WOLFSSL_OBJECT_INFO_SZ; i++) {
+            /* Short name, long name, and numerical value are interpreted */
+            if (no_name == 0 && ((XSTRNCMP(s, wolfssl_object_info[i].sName, len) == 0) ||
+                                 (XSTRNCMP(s, wolfssl_object_info[i].lName, len) == 0) ||
+                                 (wolfssl_object_info[i].id == (int)sum)))
+                    nid = wolfssl_object_info[i].nid;
+            /* Only numerical value is interpreted */
+            else if (no_name == 1 && wolfssl_object_info[i].id == (int)sum)
+                    nid = wolfssl_object_info[i].nid;
+        }
+
+        if (nid != NID_undef)
+            return wolfSSL_OBJ_nid2obj(nid);
+
+        return NULL;
+    }
+#endif
+
+    /* compatibility function. Its intended use is to remove OID's from an
+     * internal table that have been added with OBJ_create. wolfSSL manages its
+     * own internal OID values and does not currently support OBJ_create. */
+    void wolfSSL_OBJ_cleanup(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_OBJ_cleanup()");
+    }
+
+    #ifndef NO_WOLFSSL_STUB
+    int wolfSSL_OBJ_create(const char *oid, const char *sn, const char *ln)
+    {
+        (void)oid;
+        (void)sn;
+        (void)ln;
+        WOLFSSL_STUB("wolfSSL_OBJ_create");
+        return WOLFSSL_FAILURE;
+    }
+    #endif
+
+    void wolfSSL_set_verify_depth(WOLFSSL *ssl, int depth)
+    {
+    #if !defined(OPENSSL_EXTRA) && !defined(NO_WOLFSSL_STUB)
+        (void)ssl;
+        (void)depth;
+        WOLFSSL_STUB("wolfSSL_set_verify_depth");
+    #else
+        WOLFSSL_ENTER("wolfSSL_set_verify_depth");
+        ssl->options.verifyDepth = (byte)depth;
+    #endif
+    }
+
+
+    WOLFSSL_ASN1_OBJECT * wolfSSL_X509_NAME_ENTRY_get_object(WOLFSSL_X509_NAME_ENTRY *ne) {
+        WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_get_object");
+        if (ne == NULL) return NULL;
+        if (wolfSSL_OBJ_nid2obj_ex(ne->nid, &ne->object) != NULL) {
+            ne->object.nid = ne->nid;
+            return &ne->object;
+        }
+        return NULL;
+    }
+
+
+    /* looks up the DN given the location "loc". "loc" is the number indicating
+     * the order that the DN was parsed as, 0 is first DN parsed.
+     *
+     * returns the setup WOLFSSL_X509_NAME pointer on success and NULL on fail
+     */
+    static WOLFSSL_X509_NAME* wolfSSL_nameByLoc(WOLFSSL_X509_NAME *name, int loc)
+    {
+        char* pt = NULL;
+        int sz = 0;
+
+        switch (name->fullName.loc[loc])
+        {
+        case ASN_COMMON_NAME:
+            sz = name->fullName.cnLen;
+            pt = &name->fullName.fullName[name->fullName.cnIdx];
+            name->cnEntry.nid           = name->fullName.cnNid;
+            break;
+        case ASN_COUNTRY_NAME:
+            sz = name->fullName.cLen;
+            pt = &name->fullName.fullName[name->fullName.cIdx];
+            name->cnEntry.nid           = name->fullName.cNid;
+            break;
+        case ASN_LOCALITY_NAME:
+            sz = name->fullName.lLen;
+            pt = &name->fullName.fullName[name->fullName.lIdx];
+            name->cnEntry.nid           = name->fullName.lNid;
+            break;
+        case ASN_STATE_NAME:
+            sz = name->fullName.stLen;
+            pt = &name->fullName.fullName[name->fullName.stIdx];
+            name->cnEntry.nid           = name->fullName.stNid;
+            break;
+        case ASN_ORG_NAME:
+            sz = name->fullName.oLen;
+            pt = &name->fullName.fullName[name->fullName.oIdx];
+            name->cnEntry.nid           = name->fullName.oNid;
+            break;
+        case ASN_ORGUNIT_NAME:
+            sz = name->fullName.ouLen;
+            pt = &name->fullName.fullName[name->fullName.ouIdx];
+            name->cnEntry.nid           = name->fullName.ouNid;
+            break;
+        case ASN_EMAIL_NAME:
+            sz = name->fullName.emailLen;
+            pt = &name->fullName.fullName[name->fullName.emailIdx];
+            name->cnEntry.nid           = name->fullName.emailNid;
+            break;
+        case ASN_SUR_NAME:
+            sz = name->fullName.snLen;
+            pt = &name->fullName.fullName[name->fullName.snIdx];
+            name->cnEntry.nid           = name->fullName.snNid;
+            break;
+        case ASN_USER_ID:
+            sz = name->fullName.uidLen;
+            pt = &name->fullName.fullName[name->fullName.uidIdx];
+            name->cnEntry.nid           = name->fullName.uidNid;
+            break;
+        case ASN_SERIAL_NUMBER:
+            sz = name->fullName.serialLen;
+            pt = &name->fullName.fullName[name->fullName.serialIdx];
+            name->cnEntry.nid           = name->fullName.serialNid;
+            break;
+#ifdef WOLFSSL_CERT_EXT
+        case ASN_BUS_CAT:
+            sz = name->fullName.bcLen;
+            pt = &name->fullName.fullName[name->fullName.bcIdx];
+            break;
+#endif
+
+        case ASN_DOMAIN_COMPONENT:
+            /* get index of DC i.e. first or second or ... case */
+            {
+                int idx = 0, i;
+                for (i = 0; i < loc; i++) {
+                    if (name->fullName.loc[i] == ASN_DOMAIN_COMPONENT) {
+                        idx++;
+                    }
+                }
+
+                /* check that index is not larger than max buffer size or larger
+                 * than the number of domain components parsed */
+                if (idx >= DOMAIN_COMPONENT_MAX || idx > name->fullName.dcNum) {
+                    WOLFSSL_MSG("Index was larger then domain buffer");
+                    return NULL;
+                }
+                pt = &name->fullName.fullName[name->fullName.dcIdx[idx]],
+                sz = name->fullName.dcLen[idx];
+                name->cnEntry.nid         = ASN_DOMAIN_COMPONENT;
+                name->cnEntry.data.type   = CTC_UTF8;
+            }
+            break;
+
+        default:
+            return NULL;
+        }
+
+        /* -1 to leave room for trailing terminator 0 */
+        if (sz == 0 || sz >= CTC_NAME_SIZE - 1)
+            return NULL;
+        if (wolfSSL_ASN1_STRING_set(name->cnEntry.value, pt, sz) !=
+                WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("Error setting local ASN1 string data");
+            return NULL;
+        }
+        name->cnEntry.value->type   = CTC_UTF8;
+        name->cnEntry.set           = 1;
+        return name;
+    }
+
+
+    WOLFSSL_X509_NAME_ENTRY *wolfSSL_X509_NAME_get_entry(
+                                             WOLFSSL_X509_NAME *name, int loc)
+    {
+        WOLFSSL_ENTER("wolfSSL_X509_NAME_get_entry");
+
+        if (name == NULL) {
+            return NULL;
+        }
+
+        if (loc < 0) {
+            WOLFSSL_MSG("Bad argument");
+            return NULL;
+        }
+
+        if (loc <= DN_NAMES_MAX + name->fullName.dcNum) {
+            if (wolfSSL_nameByLoc(name, loc) != NULL)
+                return &name->cnEntry;
+        }
+        /* DC component */
+        if (name->fullName.dcMode) {
+            if (name->fullName.fullName != NULL){
+                if (loc == name->fullName.dcNum){
+                    name->cnEntry.data.data
+                        = &name->fullName.fullName[name->fullName.cIdx];
+                    name->cnEntry.data.length = name->fullName.cLen;
+                    name->cnEntry.nid         = ASN_COUNTRY_NAME;
+                } else {
+                    name->cnEntry.data.data
+                        = &name->fullName.fullName[name->fullName.dcIdx[loc]];
+                    name->cnEntry.data.length = name->fullName.dcLen[loc];
+                    name->cnEntry.nid         = ASN_DOMAIN_COMPONENT;
+                }
+            }
+            name->cnEntry.data.type = CTC_UTF8;
+        /* common name index case */
+        } else if (loc == name->fullName.cnIdx && name->x509 != NULL) {
+            /* get CN shortcut from x509 since it has null terminator */
+            name->cnEntry.data.data   = name->x509->subjectCN;
+            name->cnEntry.data.length = name->fullName.cnLen;
+            name->cnEntry.data.type   = CTC_UTF8;
+            name->cnEntry.nid         = ASN_COMMON_NAME;
+            name->cnEntry.set         = 1;
+        } else {
+            WOLFSSL_MSG("loc passed in is not in range of parsed DN's");
+            return NULL;
+        }
+        return &name->cnEntry;
+    }
+
+    #ifndef NO_WOLFSSL_STUB
+    int wolfSSL_X509_check_private_key(WOLFSSL_X509 *x509, WOLFSSL_EVP_PKEY *key)
+    {
+        (void) x509;
+        (void) key;
+        WOLFSSL_ENTER("wolfSSL_X509_check_private_key");
+        WOLFSSL_STUB("X509_check_private_key");
+
+        return WOLFSSL_SUCCESS;
+    }
+
+    WOLF_STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list(
+        WOLF_STACK_OF(WOLFSSL_X509_NAME) *sk)
+    {
+        (void) sk;
+        WOLFSSL_ENTER("wolfSSL_dup_CA_list");
+        WOLFSSL_STUB("SSL_dup_CA_list");
+
+        return NULL;
+    }
+
+    #endif
+
+#endif /* OPENSSL_ALL || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE ||
+    HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_POCO_LIB || WOLFSSL_HAPROXY */
+#endif /* OPENSSL_EXTRA */
+
+#ifndef WOLFCRYPT_ONLY
+
+#ifdef OPENSSL_EXTRA
+
+/* wolfSSL uses negative values for error states. This function returns an
+ * unsigned type so the value returned is the absolute value of the error.
+ */
+unsigned long wolfSSL_ERR_peek_last_error_line(const char **file, int *line)
+{
+    WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error");
+
+    (void)line;
+    (void)file;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(DEBUG_WOLFSSL) || \
+    defined(WOLFSSL_HAPROXY)
+    {
+        int ret;
+
+        if ((ret = wc_PeekErrorNode(-1, file, NULL, line)) < 0) {
+            WOLFSSL_MSG("Issue peeking at error node in queue");
+            return 0;
+        }
+    #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+        if (ret == -ASN_NO_PEM_HEADER)
+            return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE;
+    #endif
+        return (unsigned long)ret;
+    }
+#else
+    return (unsigned long)(0 - NOT_COMPILED_IN);
+#endif
+}
+
+
+#ifndef NO_CERTS
+int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey");
+
+    if (ctx == NULL || pkey == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if (pkey->pkey.ptr != NULL) {
+        /* ptr for WOLFSSL_EVP_PKEY struct is expected to be DER format */
+        return wolfSSL_CTX_use_PrivateKey_buffer(ctx,
+                                       (const unsigned char*)pkey->pkey.ptr,
+                                       pkey->pkey_sz, SSL_FILETYPE_ASN1);
+    }
+
+    WOLFSSL_MSG("wolfSSL private key not set");
+    return BAD_FUNC_ARG;
+}
+#endif /* !NO_CERTS */
+
+
+#if defined(HAVE_EX_DATA) || defined(FORTRESS)
+void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX* ctx, int idx)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_get_ex_data");
+    #ifdef HAVE_EX_DATA
+    if(ctx != NULL) {
+        return wolfSSL_CRYPTO_get_ex_data(&ctx->ex_data, idx);
+    }
+    #else
+    (void)ctx;
+    (void)idx;
+    #endif
+    return NULL;
+}
+
+int wolfSSL_CTX_get_ex_new_index(long idx, void* arg, void* a, void* b,
+                                void* c)
+{
+    static int ctx_idx = 0;
+
+    WOLFSSL_ENTER("wolfSSL_CTX_get_ex_new_index");
+    (void)idx;
+    (void)arg;
+    (void)a;
+    (void)b;
+    (void)c;
+
+    return ctx_idx++;
+}
+
+/* Return the index that can be used for the WOLFSSL structure to store
+ * application data.
+ *
+ */
+int wolfSSL_get_ex_new_index(long argValue, void* arg,
+        WOLFSSL_CRYPTO_EX_new* cb1, WOLFSSL_CRYPTO_EX_dup* cb2,
+        WOLFSSL_CRYPTO_EX_free* cb3)
+{
+    static int ssl_idx = 0;
+
+    WOLFSSL_ENTER("wolfSSL_get_ex_new_index");
+
+    (void)argValue;
+    (void)arg;
+    (void)cb1;
+    (void)cb2;
+    (void)cb3;
+
+    return ssl_idx++;
+}
+
+
+int wolfSSL_CTX_set_ex_data(WOLFSSL_CTX* ctx, int idx, void* data)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_set_ex_data");
+    #ifdef HAVE_EX_DATA
+    if (ctx != NULL)
+    {
+        return wolfSSL_CRYPTO_set_ex_data(&ctx->ex_data, idx, data);
+    }
+    #else
+    (void)ctx;
+    (void)idx;
+    (void)data;
+    #endif
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+
+/* Returns char* to app data stored in ex[0].
+ *
+ * ssl WOLFSSL structure to get app data from
+ */
+void* wolfSSL_get_app_data(const WOLFSSL *ssl)
+{
+    /* checkout exdata stuff... */
+    WOLFSSL_ENTER("wolfSSL_get_app_data");
+
+    return wolfSSL_get_ex_data(ssl, 0);
+}
+
+
+/* Set ex array 0 to have app data
+ *
+ * ssl WOLFSSL struct to set app data in
+ * arg data to be stored
+ *
+ * Returns SSL_SUCCESS on success and SSL_FAILURE on failure
+ */
+int wolfSSL_set_app_data(WOLFSSL *ssl, void* arg) {
+    WOLFSSL_ENTER("wolfSSL_set_app_data");
+
+    return wolfSSL_set_ex_data(ssl, 0, arg);
+}
+
+
+int wolfSSL_set_ex_data(WOLFSSL* ssl, int idx, void* data)
+{
+    WOLFSSL_ENTER("wolfSSL_set_ex_data");
+#if defined(HAVE_EX_DATA) || defined(FORTRESS)
+    if (ssl != NULL)
+    {
+        return wolfSSL_CRYPTO_set_ex_data(&ssl->ex_data, idx, data);
+    }
+#else
+    WOLFSSL_MSG("HAVE_EX_DATA macro is not defined");
+    (void)ssl;
+    (void)idx;
+    (void)data;
+#endif
+    return WOLFSSL_FAILURE;
+}
+
+
+
+void* wolfSSL_get_ex_data(const WOLFSSL* ssl, int idx)
+{
+    WOLFSSL_ENTER("wolfSSL_get_ex_data");
+#if defined(HAVE_EX_DATA) || defined(FORTRESS)
+    if (ssl != NULL) {
+        return wolfSSL_CRYPTO_get_ex_data(&ssl->ex_data, idx);
+    }
+#else
+    WOLFSSL_MSG("HAVE_EX_DATA macro is not defined");
+    (void)ssl;
+    (void)idx;
+#endif
+    return 0;
+}
+
+#ifndef NO_DSA
+WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSAparams(WOLFSSL_BIO *bp, WOLFSSL_DSA **x,
+        pem_password_cb *cb, void *u)
+{
+    WOLFSSL_DSA* dsa;
+    DsaKey* key;
+    int    length;
+    unsigned char*  buf;
+    word32 bufSz;
+    int ret;
+    word32 idx = 0;
+    DerBuffer* pDer;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_read_bio_DSAparams");
+
+    ret = wolfSSL_BIO_get_mem_data(bp, &buf);
+    if (ret <= 0) {
+        WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_DSAparams", ret);
+        return NULL;
+    }
+
+    bufSz = (word32)ret;
+
+    if (cb != NULL || u != NULL) {
+        /*
+         * cb is for a call back when encountering encrypted PEM files
+         * if cb == NULL and u != NULL then u = null terminated password string
+         */
+        WOLFSSL_MSG("Not yet supporting call back or password for encrypted PEM");
+    }
+
+    if ((ret = PemToDer(buf, (long)bufSz, DSA_PARAM_TYPE, &pDer, NULL, NULL,
+                    NULL)) < 0 ) {
+        WOLFSSL_MSG("Issue converting from PEM to DER");
+        return NULL;
+    }
+
+    if ((ret = GetSequence(pDer->buffer, &idx, &length, pDer->length)) < 0) {
+        WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_DSAparams", ret);
+        FreeDer(&pDer);
+        return NULL;
+    }
+
+    dsa = wolfSSL_DSA_new();
+    if (dsa == NULL) {
+        FreeDer(&pDer);
+        WOLFSSL_MSG("Error creating DSA struct");
+        return NULL;
+    }
+
+    key = (DsaKey*)dsa->internal;
+    if (key == NULL) {
+        FreeDer(&pDer);
+        wolfSSL_DSA_free(dsa);
+        WOLFSSL_MSG("Error finding DSA key struct");
+        return NULL;
+    }
+
+    if (GetInt(&key->p,  pDer->buffer, &idx, pDer->length) < 0 ||
+        GetInt(&key->q,  pDer->buffer, &idx, pDer->length) < 0 ||
+        GetInt(&key->g,  pDer->buffer, &idx, pDer->length) < 0 ) {
+        WOLFSSL_MSG("dsa key error");
+        FreeDer(&pDer);
+        wolfSSL_DSA_free(dsa);
+        return NULL;
+    }
+
+    if (SetIndividualExternal(&dsa->p, &key->p) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("dsa p key error");
+        FreeDer(&pDer);
+        wolfSSL_DSA_free(dsa);
+        return NULL;
+    }
+
+    if (SetIndividualExternal(&dsa->q, &key->q) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("dsa q key error");
+        FreeDer(&pDer);
+        wolfSSL_DSA_free(dsa);
+        return NULL;
+    }
+
+    if (SetIndividualExternal(&dsa->g, &key->g) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("dsa g key error");
+        FreeDer(&pDer);
+        wolfSSL_DSA_free(dsa);
+        return NULL;
+    }
+
+    if (x != NULL) {
+        *x = dsa;
+    }
+
+    FreeDer(&pDer);
+    return dsa;
+}
+#endif /* NO_DSA */
+#endif /* OPENSSL_EXTRA */
+#endif /* WOLFCRYPT_ONLY */
+
+#if defined(OPENSSL_EXTRA)
+
+/* Begin functions for openssl/buffer.h */
+WOLFSSL_BUF_MEM* wolfSSL_BUF_MEM_new(void)
+{
+    WOLFSSL_BUF_MEM* buf;
+    buf = (WOLFSSL_BUF_MEM*)XMALLOC(sizeof(WOLFSSL_BUF_MEM), NULL,
+                                                        DYNAMIC_TYPE_OPENSSL);
+    if (buf) {
+        XMEMSET(buf, 0, sizeof(WOLFSSL_BUF_MEM));
+    }
+    return buf;
+}
+
+
+/* returns length of buffer on success */
+int wolfSSL_BUF_MEM_grow(WOLFSSL_BUF_MEM* buf, size_t len)
+{
+    int len_int = (int)len;
+    int mx;
+
+    /* verify provided arguments */
+    if (buf == NULL || len_int < 0) {
+        return 0; /* BAD_FUNC_ARG; */
+    }
+
+    /* check to see if fits in existing length */
+    if (buf->length > len) {
+        buf->length = len;
+        return len_int;
+    }
+
+    /* check to see if fits in max buffer */
+    if (buf->max >= len) {
+        if (buf->data != NULL) {
+            XMEMSET(&buf->data[buf->length], 0, len - buf->length);
+        }
+        buf->length = len;
+        return len_int;
+    }
+
+    /* expand size, to handle growth */
+    mx = (len_int + 3) / 3 * 4;
+
+    /* use realloc */
+    buf->data = (char*)XREALLOC(buf->data, mx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (buf->data == NULL) {
+        return 0; /* ERR_R_MALLOC_FAILURE; */
+    }
+
+    buf->max = mx;
+    XMEMSET(&buf->data[buf->length], 0, len - buf->length);
+    buf->length = len;
+
+    return len_int;
+}
+
+void wolfSSL_BUF_MEM_free(WOLFSSL_BUF_MEM* buf)
+{
+    if (buf) {
+        if (buf->data) {
+            XFREE(buf->data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            buf->data = NULL;
+        }
+        buf->max = 0;
+        buf->length = 0;
+        XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL);
+    }
+}
+/* End Functions for openssl/buffer.h */
+
+#endif /* OPENSSL_EXTRA */
+
+
+#if defined(HAVE_LIGHTY) || defined(HAVE_STUNNEL) \
+    || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_EXTRA)
+
+WOLFSSL_BIO *wolfSSL_BIO_new_file(const char *filename, const char *mode)
+{
+#ifndef NO_FILESYSTEM
+    WOLFSSL_BIO* bio;
+    XFILE fp;
+
+    WOLFSSL_ENTER("wolfSSL_BIO_new_file");
+
+    fp = XFOPEN(filename, mode);
+    if (fp == XBADFILE)
+        return NULL;
+
+    bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file());
+    if (bio == NULL) {
+        XFCLOSE(fp);
+        return bio;
+    }
+
+    if (wolfSSL_BIO_set_fp(bio, fp, BIO_CLOSE) != WOLFSSL_SUCCESS) {
+        XFCLOSE(fp);
+        wolfSSL_BIO_free(bio);
+        bio = NULL;
+    }
+
+    /* file is closed when BIO is free'd */
+    return bio;
+#else
+    (void)filename;
+    (void)mode;
+    return NULL;
+#endif /* NO_FILESYSTEM */
+}
+
+#ifndef NO_FILESYSTEM
+WOLFSSL_BIO* wolfSSL_BIO_new_fp(XFILE fp, int close_flag)
+{
+    WOLFSSL_BIO* bio;
+
+    WOLFSSL_ENTER("wolfSSL_BIO_new_fp");
+
+    bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file());
+    if (bio == NULL) {
+        return bio;
+    }
+
+    if (wolfSSL_BIO_set_fp(bio, fp, close_flag) != WOLFSSL_SUCCESS) {
+        wolfSSL_BIO_free(bio);
+        bio = NULL;
+    }
+
+    /* file is closed when BIO is free'd or by user depending on flag */
+    return bio;
+}
+#endif
+
+
+#ifndef NO_DH
+WOLFSSL_DH *wolfSSL_PEM_read_bio_DHparams(WOLFSSL_BIO *bio, WOLFSSL_DH **x,
+        pem_password_cb *cb, void *u)
+{
+#ifndef NO_FILESYSTEM
+    WOLFSSL_DH* localDh = NULL;
+    unsigned char* mem  = NULL;
+    word32 size;
+    long   sz;
+    int    ret;
+    DerBuffer *der = NULL;
+    byte*  p = NULL;
+    byte*  g = NULL;
+    word32 pSz = MAX_DH_SIZE;
+    word32 gSz = MAX_DH_SIZE;
+    int    memAlloced = 0;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_read_bio_DHparams");
+    (void)cb;
+    (void)u;
+
+    if (bio == NULL) {
+        WOLFSSL_MSG("Bad Function Argument bio is NULL");
+        return NULL;
+    }
+
+    if (bio->type == WOLFSSL_BIO_MEMORY) {
+        /* Use the buffer directly. */
+        ret = wolfSSL_BIO_get_mem_data(bio, &mem);
+        if (mem == NULL || ret <= 0) {
+            WOLFSSL_MSG("Failed to get data from bio struct");
+            goto end;
+        }
+        size = ret;
+    }
+    else if (bio->type == WOLFSSL_BIO_FILE) {
+        /* Read whole file into a new buffer. */
+        if (XFSEEK((XFILE)bio->ptr, 0, SEEK_END) != 0)
+            goto end;
+        sz = XFTELL((XFILE)bio->ptr);
+        if (XFSEEK((XFILE)bio->ptr, 0, SEEK_SET) != 0)
+            goto end;
+        if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0L) {
+            WOLFSSL_MSG("PEM_read_bio_DHparams file size error");
+            goto end;
+        }
+        mem = (unsigned char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_PEM);
+        if (mem == NULL)
+            goto end;
+        memAlloced = 1;
+
+        if (wolfSSL_BIO_read(bio, (char *)mem, (int)sz) <= 0)
+            goto end;
+        size = (word32)sz;
+    }
+    else {
+        WOLFSSL_MSG("BIO type not supported for reading DH parameters");
+        goto end;
+    }
+
+    ret = PemToDer(mem, size, DH_PARAM_TYPE, &der, NULL, NULL, NULL);
+    if (ret != 0)
+        goto end;
+
+    /* Use the object passed in, otherwise allocate a new object */
+    if (x != NULL)
+        localDh = *x;
+    if (localDh == NULL) {
+        localDh = wolfSSL_DH_new();
+        if (localDh == NULL)
+            goto end;
+    }
+
+    /* Load data in manually */
+    p = (byte*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+    g = (byte*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+    if (p == NULL || g == NULL)
+        goto end;
+
+    /* Extract the p and g as data from the DER encoded DH parameters. */
+    ret = wc_DhParamsLoad(der->buffer, der->length, p, &pSz, g, &gSz);
+    if (ret != 0) {
+        if (x != NULL && localDh != *x)
+            XFREE(localDh, NULL, DYNAMIC_TYPE_OPENSSL);
+        localDh = NULL;
+        goto end;
+    }
+
+    if (x != NULL)
+        *x = localDh;
+
+    /* Put p and g in as big numbers. */
+    if (localDh->p != NULL) {
+        wolfSSL_BN_free(localDh->p);
+        localDh->p = NULL;
+    }
+    if (localDh->g != NULL) {
+        wolfSSL_BN_free(localDh->g);
+        localDh->g = NULL;
+    }
+    localDh->p = wolfSSL_BN_bin2bn(p, pSz, NULL);
+    localDh->g = wolfSSL_BN_bin2bn(g, gSz, NULL);
+    if (localDh->p == NULL || localDh->g == NULL) {
+        if (x != NULL && localDh != *x)
+            wolfSSL_DH_free(localDh);
+        localDh = NULL;
+    }
+
+    if (localDh != NULL && localDh->inSet == 0) {
+        if (SetDhInternal(localDh) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("Unable to set internal DH structure");
+            wolfSSL_DH_free(localDh);
+            localDh = NULL;
+        }
+    }
+
+end:
+    if (memAlloced) XFREE(mem, NULL, DYNAMIC_TYPE_PEM);
+    if (der != NULL) FreeDer(&der);
+    XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+    XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+    return localDh;
+#else
+    (void)bio;
+    (void)x;
+    (void)cb;
+    (void)u;
+    return NULL;
+#endif
+}
+
+#ifndef NO_FILESYSTEM
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH)
+/* Convert DH key parameters to DER format, write to output (outSz)
+ * If output is NULL then max expected size is set to outSz and LENGTH_ONLY_E is
+ * returned.
+ *
+ * Note : static function due to redefinition complications with DhKey and FIPS
+ * version 2 build.
+ *
+ * return bytes written on success */
+int wc_DhParamsToDer(DhKey* key, byte* out, word32* outSz)
+{
+    word32 sz = 0, idx = 0;
+    int pSz = 0, gSz = 0, ret;
+    byte scratch[MAX_LENGTH_SZ];
+
+    if (key == NULL || outSz == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    pSz = mp_unsigned_bin_size(&key->p);
+    if (pSz < 0) {
+        return pSz;
+    }
+    if (mp_leading_bit(&key->p)) {
+        pSz++;
+    }
+
+    gSz = mp_unsigned_bin_size(&key->g);
+    if (gSz < 0) {
+        return gSz;
+    }
+    if (mp_leading_bit(&key->g)) {
+        gSz++;
+    }
+
+    sz  = ASN_TAG_SZ; /* Integer */
+    sz += SetLength(pSz, scratch);
+    sz += ASN_TAG_SZ; /* Integer */
+    sz += SetLength(gSz, scratch);
+    sz += gSz + pSz;
+
+    if (out == NULL) {
+        byte seqScratch[MAX_SEQ_SZ];
+
+        *outSz = sz + SetSequence(sz, seqScratch);
+        return LENGTH_ONLY_E;
+    }
+
+    if (*outSz < MAX_SEQ_SZ || *outSz < sz) {
+        return BUFFER_E;
+    }
+
+    idx += SetSequence(sz, out);
+    if (*outSz < idx + sz) {
+        return BUFFER_E;
+    }
+
+    out[idx++] = ASN_INTEGER;
+    idx += SetLength(pSz, out + idx);
+    if (mp_leading_bit(&key->p)) {
+        out[idx++] = 0x00;
+        pSz -= 1; /* subtract 1 from size to account for leading 0 */
+    }
+    ret = mp_to_unsigned_bin(&key->p, out + idx);
+    if (ret != MP_OKAY) {
+        return BUFFER_E;
+    }
+    idx += pSz;
+
+    out[idx++] = ASN_INTEGER;
+    idx += SetLength(gSz, out + idx);
+    if (mp_leading_bit(&key->g)) {
+        out[idx++] = 0x00;
+        gSz -= 1; /* subtract 1 from size to account for leading 0 */
+    }
+    ret = mp_to_unsigned_bin(&key->g, out + idx);
+    if (ret != MP_OKAY) {
+        return BUFFER_E;
+    }
+    idx += gSz;
+    return idx;
+}
+
+int wc_DhPubKeyToDer(DhKey*  key, byte* out, word32* outSz)
+{
+    word32 sz = 0;
+    word32 paramSz = 0;
+    int ret;
+    int pubSz = 0;
+    int idx = 0;
+    byte scratch[MAX_ALGO_SZ];
+
+    /* Get size of entire key */
+
+    /*  SEQUENCE               <--| SetAlgoId
+     *      OBJECT IDENTIFIER  <--|
+     *      SEQUENCE     <--
+     *          INTEGER    | wc_DhParamsToDer
+     *          INTEGER  <--
+     */
+    ret = wc_DhParamsToDer(key, NULL, &paramSz);
+    if (ret != LENGTH_ONLY_E)
+        return ASN_PARSE_E;
+    sz += paramSz;
+    sz += SetAlgoID(DHk, scratch, oidKeyType, paramSz);
+
+    /*  BIT STRING
+     *      INTEGER
+     */
+    pubSz = mp_unsigned_bin_size(&key->pub);
+    if (pubSz < 0)
+        return pubSz;
+
+    if (mp_leading_bit(&key->pub))
+        pubSz++;
+
+    sz += ASN_TAG_SZ; /* Integer */
+    sz += SetLength(pubSz, scratch);
+    sz += pubSz;
+
+    sz += SetBitString(pubSz, 0, scratch);
+
+    if (out == NULL) {
+        /* Uppermost SEQUENCE */
+        *outSz = sz + SetSequence(sz, scratch);
+        return LENGTH_ONLY_E;
+    }
+    /* end get size of entire key */
+
+    /* Check for indexing errors */
+    if (*outSz < MAX_SEQ_SZ || *outSz < sz) {
+        return BUFFER_E;
+    }
+
+    /* Build Up Entire Key */
+
+    idx += SetSequence(sz, out);
+
+    idx += SetAlgoID(DHk, out+idx, oidKeyType, paramSz);
+    ret = wc_DhParamsToDer(key, out+idx, &paramSz);
+    if (ret < 0)
+        return ret;
+    idx += ret;
+
+    /* BIT STRING
+     *   INTEGER
+     */
+    idx += SetBitString(pubSz, 0, out+idx);
+
+    out[idx++] = ASN_INTEGER;
+    idx += SetLength(pubSz, out + idx);
+    if (mp_leading_bit(&key->pub)) {
+        out[idx++] = 0x00;
+        pubSz -= 1; /* subtract 1 from size to account for leading 0 */
+    }
+    ret = mp_to_unsigned_bin(&key->pub, out + idx);
+    if (ret != MP_OKAY) {
+        return BUFFER_E;
+    }
+    idx += pubSz;
+
+    return idx;
+}
+
+int wc_DhPrivKeyToDer(DhKey* key, byte* out, word32* outSz)
+{
+    word32 sz = 0;
+    word32 paramSz = 0;
+    int ret;
+    int privSz = 0;
+    int idx = 0;
+    byte scratch[MAX_ALGO_SZ];
+
+    /* Get size of entire key */
+
+    /*  INTEGER 0 */
+    sz += ASN_TAG_SZ; /* Integer */
+    sz += SetLength(1, scratch);
+    sz += 1;
+
+    /*  SEQUENCE               <--| SetAlgoId
+     *      OBJECT IDENTIFIER  <--|
+     *      SEQUENCE       <--
+     *          INTEGER       | wc_DhParamsToDer
+     *          INTEGER     <--
+     */
+    ret = wc_DhParamsToDer(key, NULL, &paramSz);
+    if (ret != LENGTH_ONLY_E)
+        return ASN_PARSE_E;
+    sz += paramSz;
+    sz += SetAlgoID(DHk, scratch, oidKeyType, paramSz);
+
+    /*  OCTET STRING
+     *      INTEGER
+     */
+    privSz = mp_unsigned_bin_size(&key->priv);
+    if (privSz < 0)
+        return privSz;
+    else if (privSz > 256) /* Key is larger than 2048 */
+        return ASN_VERSION_E;
+
+    if (mp_leading_bit(&key->priv))
+        privSz++;
+
+    sz += ASN_TAG_SZ; /* Integer */
+    sz += SetLength(privSz, scratch);
+    sz += privSz;
+
+    sz += SetOctetString(privSz + ASN_OCTET_STRING, scratch);
+
+    if (out == NULL) {
+        /* Uppermost SEQUENCE */
+        *outSz = sz + SetSequence(sz, scratch);
+        return LENGTH_ONLY_E;
+    }
+    /* end get size of entire key */
+
+    /* Check for indexing errors */
+    if (*outSz < MAX_SEQ_SZ || *outSz < sz) {
+        return BUFFER_E;
+    }
+
+    /* Build Up Entire Key */
+
+    idx += SetSequence(sz, out);
+
+    /* INTEGER 0 */
+    out[idx++] = ASN_INTEGER;
+    idx += SetLength(1, out+idx);
+    out[idx++] = 0;
+
+    idx += SetAlgoID(DHk, out+idx, oidKeyType, paramSz);
+    ret = wc_DhParamsToDer(key, out+idx, &paramSz);
+    if (ret < 0)
+        return ret;
+    idx += ret;
+
+    /* OCTET STRING
+     *   INTEGER
+     */
+    if (privSz == 256) {
+        idx += SetOctetString(privSz + ASN_OCTET_STRING, out+idx);
+    } else if (privSz == 128) {
+        idx += SetOctetString(privSz + ASN_OCTET_STRING-1, out+idx);
+    } else if (privSz == 64) {
+        idx += SetOctetString(privSz + ASN_OCTET_STRING-2, out+idx);
+    } else {
+        WOLFSSL_MSG("Unsupported key size");
+        return ASN_VERSION_E;
+    }
+
+    out[idx++] = ASN_INTEGER;
+    idx += SetLength(privSz, out + idx);
+    if (mp_leading_bit(&key->priv)) {
+        out[idx++] = 0x00;
+        privSz -= 1; /* subtract 1 from size to account for leading 0 */
+    }
+    ret = mp_to_unsigned_bin(&key->priv, out + idx);
+    if (ret != MP_OKAY) {
+        return BUFFER_E;
+    }
+    idx += privSz;
+
+    return idx;
+}
+
+/* Writes the DH parameters in PEM format from "dh" out to the file pointer
+ * passed in.
+ *
+ * returns WOLFSSL_SUCCESS on success
+ */
+int wolfSSL_PEM_write_DHparams(XFILE fp, WOLFSSL_DH* dh)
+{
+    int ret;
+    word32 derSz = 0, pemSz = 0;
+    byte *der, *pem;
+    DhKey* key;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_write_DHparams");
+
+    if (dh == NULL) {
+        WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", BAD_FUNC_ARG);
+        return WOLFSSL_FAILURE;
+    }
+
+    if (dh->inSet == 0) {
+        if (SetDhInternal(dh) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("Unable to set internal DH structure");
+            return WOLFSSL_FAILURE;
+        }
+    }
+    key = (DhKey*)dh->internal;
+    ret = wc_DhParamsToDer(key, NULL, &derSz);
+    if (ret != LENGTH_ONLY_E) {
+        WOLFSSL_MSG("Failed to get size of DH params");
+        WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", ret);
+        return WOLFSSL_FAILURE;
+    }
+
+    der = (byte*)XMALLOC(derSz, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (der == NULL) {
+        WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", MEMORY_E);
+        return WOLFSSL_FAILURE;
+    }
+    ret = wc_DhParamsToDer(key, der, &derSz);
+    if (ret <= 0) {
+        WOLFSSL_MSG("Failed to export DH params");
+        WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", ret);
+        XFREE(der, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* convert to PEM */
+    ret = wc_DerToPem(der, derSz, NULL, 0, DH_PARAM_TYPE);
+    if (ret < 0) {
+        WOLFSSL_MSG("Failed to convert DH params to PEM");
+        WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", ret);
+        XFREE(der, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return ret;
+    }
+    pemSz = (word32)ret;
+
+    pem = (byte*)XMALLOC(pemSz, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (pem == NULL) {
+        WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", MEMORY_E);
+        XFREE(der, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return ret;
+    }
+    ret = wc_DerToPem(der, derSz, pem, pemSz, DH_PARAM_TYPE);
+    XFREE(der, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (ret < 0) {
+        WOLFSSL_MSG("Failed to convert DH params to PEM");
+        WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", ret);
+        XFREE(pem, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return ret;
+    }
+
+    ret = (int)XFWRITE(pem, 1, pemSz, fp);
+    XFREE(pem, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (ret <= 0) {
+        WOLFSSL_MSG("Failed to write to file");
+        WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", ret);
+        return WOLFSSL_FAILURE;
+    }
+
+    WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", WOLFSSL_SUCCESS);
+    return WOLFSSL_SUCCESS;
+}
+#endif /* WOLFSSL_QT || OPENSSL_ALL */
+#endif /* !NO_FILESYSTEM */
+#endif /* !NO_DH */
+
+#ifdef WOLFSSL_CERT_GEN
+
+#ifdef WOLFSSL_CERT_REQ
+/* writes the x509 from x to the WOLFSSL_BIO bp
+ *
+ * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on fail
+ */
+int wolfSSL_PEM_write_bio_X509_REQ(WOLFSSL_BIO *bp, WOLFSSL_X509 *x)
+{
+    byte* pem;
+    int   pemSz = 0;
+    const unsigned char* der;
+    int derSz;
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509_REQ()");
+
+    if (x == NULL || bp == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    der = wolfSSL_X509_get_der(x, &derSz);
+    if (der == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* get PEM size */
+    pemSz = wc_DerToPemEx(der, derSz, NULL, 0, NULL, CERTREQ_TYPE);
+    if (pemSz < 0) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* create PEM buffer and convert from DER */
+    pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (pem == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+    if (wc_DerToPemEx(der, derSz, pem, pemSz, NULL, CERTREQ_TYPE) < 0) {
+        XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* write the PEM to BIO */
+    ret = wolfSSL_BIO_write(bp, pem, pemSz);
+    XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+    if (ret <= 0) return WOLFSSL_FAILURE;
+    return WOLFSSL_SUCCESS;
+}
+#endif /* WOLFSSL_CERT_REQ */
+
+
+/* writes the x509 from x to the WOLFSSL_BIO bp
+ *
+ * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on fail
+ */
+int wolfSSL_PEM_write_bio_X509_AUX(WOLFSSL_BIO *bp, WOLFSSL_X509 *x)
+{
+    byte* pem;
+    int   pemSz = 0;
+    const unsigned char* der;
+    int derSz;
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509_AUX()");
+
+    if (bp == NULL || x == NULL) {
+        WOLFSSL_MSG("NULL argument passed in");
+        return WOLFSSL_FAILURE;
+    }
+
+    der = wolfSSL_X509_get_der(x, &derSz);
+    if (der == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* get PEM size */
+    pemSz = wc_DerToPemEx(der, derSz, NULL, 0, NULL, CERT_TYPE);
+    if (pemSz < 0) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* create PEM buffer and convert from DER */
+    pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (pem == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+    if (wc_DerToPemEx(der, derSz, pem, pemSz, NULL, CERT_TYPE) < 0) {
+        XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* write the PEM to BIO */
+    ret = wolfSSL_BIO_write(bp, pem, pemSz);
+    XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+    if (ret <= 0) return WOLFSSL_FAILURE;
+    return WOLFSSL_SUCCESS;
+}
+#endif /* WOLFSSL_CERT_GEN */
+
+int wolfSSL_PEM_write_bio_X509(WOLFSSL_BIO *bio, WOLFSSL_X509 *cert)
+{
+    byte* pem;
+    int   pemSz = 0;
+    const unsigned char* der;
+    int derSz;
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509_AUX()");
+
+    if (bio == NULL || cert == NULL) {
+        WOLFSSL_MSG("NULL argument passed in");
+        return WOLFSSL_FAILURE;
+    }
+
+    der = wolfSSL_X509_get_der(cert, &derSz);
+    if (der == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* get PEM size */
+    pemSz = wc_DerToPemEx(der, derSz, NULL, 0, NULL, CERT_TYPE);
+    if (pemSz < 0) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* create PEM buffer and convert from DER */
+    pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (pem == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+    if (wc_DerToPemEx(der, derSz, pem, pemSz, NULL, CERT_TYPE) < 0) {
+        XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* write the PEM to BIO */
+    ret = wolfSSL_BIO_write(bio, pem, pemSz);
+    XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+    if (ret <= 0) return WOLFSSL_FAILURE;
+    return WOLFSSL_SUCCESS;
+}
+
+
+#if defined(OPENSSL_EXTRA) && !defined(NO_DH)
+/* Initialize ctx->dh with dh's params. Return WOLFSSL_SUCCESS on ok */
+long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX* ctx, WOLFSSL_DH* dh)
+{
+    int pSz, gSz;
+    byte *p, *g;
+    int ret=0;
+
+    WOLFSSL_ENTER("wolfSSL_CTX_set_tmp_dh");
+
+    if(!ctx || !dh)
+        return BAD_FUNC_ARG;
+
+    /* Get needed size for p and g */
+    pSz = wolfSSL_BN_bn2bin(dh->p, NULL);
+    gSz = wolfSSL_BN_bn2bin(dh->g, NULL);
+
+    if(pSz <= 0 || gSz <= 0)
+        return WOLFSSL_FATAL_ERROR;
+
+    p = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    if(!p)
+        return MEMORY_E;
+
+    g = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    if(!g) {
+        XFREE(p, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        return MEMORY_E;
+    }
+
+    pSz = wolfSSL_BN_bn2bin(dh->p, p);
+    gSz = wolfSSL_BN_bn2bin(dh->g, g);
+
+    if(pSz >= 0 && gSz >= 0) /* Conversion successful */
+        ret = wolfSSL_CTX_SetTmpDH(ctx, p, pSz, g, gSz);
+
+    XFREE(p, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    XFREE(g, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+
+    return pSz > 0 && gSz > 0 ? ret : WOLFSSL_FATAL_ERROR;
+}
+#endif /* OPENSSL_EXTRA && !NO_DH */
+
+
+/* returns the enum value associated with handshake state
+ *
+ * ssl the WOLFSSL structure to get state of
+ */
+int wolfSSL_get_state(const WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_get_state");
+
+    if (ssl == NULL) {
+        WOLFSSL_MSG("Null argument passed in");
+        return SSL_FAILURE;
+    }
+
+    return ssl->options.handShakeState;
+}
+#endif /* HAVE_LIGHTY || HAVE_STUNNEL || WOLFSSL_MYSQL_COMPATIBLE */
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || defined(WOLFSSL_HAPROXY) \
+    || defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT)
+
+long wolfSSL_ctrl(WOLFSSL* ssl, int cmd, long opt, void* pt)
+{
+    WOLFSSL_ENTER("wolfSSL_ctrl");
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    switch (cmd) {
+        #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+        case SSL_CTRL_SET_TLSEXT_HOSTNAME:
+            WOLFSSL_MSG("Entering Case: SSL_CTRL_SET_TLSEXT_HOSTNAME.");
+        #ifdef HAVE_SNI
+            if (pt == NULL) {
+                WOLFSSL_MSG("Passed in NULL Host Name.");
+                break;
+            }
+            return wolfSSL_set_tlsext_host_name(ssl, (const char*) pt);
+        #else
+            WOLFSSL_MSG("SNI not enabled.");
+            break;
+        #endif /* HAVE_SNI */
+        #endif /* WOLFSSL_NGINX || WOLFSSL_QT || OPENSSL_ALL */
+        default:
+            WOLFSSL_MSG("Case not implemented.");
+    }
+    (void)opt;
+    (void)pt;
+    return WOLFSSL_FAILURE;
+}
+
+long wolfSSL_CTX_ctrl(WOLFSSL_CTX* ctx, int cmd, long opt, void* pt)
+{
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+    long ctrl_opt;
+#endif
+    long ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_CTX_ctrl");
+    if (ctx == NULL)
+        return WOLFSSL_FAILURE;
+
+    switch (cmd) {
+    case SSL_CTRL_CHAIN:
+#ifdef SESSION_CERTS
+    {
+        /*
+         * We don't care about opt here because a copy of the certificate is
+         * stored anyway so increasing the reference counter is not necessary.
+         * Just check to make sure that it is set to one of the correct values.
+         */
+        WOLF_STACK_OF(WOLFSSL_X509)* sk = (WOLF_STACK_OF(WOLFSSL_X509)*) pt;
+        WOLFSSL_X509* x509;
+        int i;
+        if (opt != 0 && opt != 1) {
+            ret = WOLFSSL_FAILURE;
+            break;
+        }
+        /* Clear certificate chain */
+        FreeDer(&ctx->certChain);
+        if (sk) {
+            for (i = 0; i < wolfSSL_sk_X509_num(sk); i++) {
+                x509 = wolfSSL_sk_X509_value(sk, i);
+                /* Prevent wolfSSL_CTX_add_extra_chain_cert from freeing cert */
+                if (wolfSSL_X509_up_ref(x509) != 1) {
+                    WOLFSSL_MSG("Error increasing reference count");
+                    continue;
+                }
+                if (wolfSSL_CTX_add_extra_chain_cert(ctx, x509) !=
+                        WOLFSSL_SUCCESS) {
+                    WOLFSSL_MSG("Error adding certificate to context");
+                    /* Decrease reference count on failure */
+                    wolfSSL_X509_free(x509);
+                }
+            }
+        }
+        /* Free previous chain */
+        wolfSSL_sk_X509_free(ctx->x509Chain);
+        ctx->x509Chain = sk;
+        if (sk) {
+            for (i = 0; i < wolfSSL_sk_X509_num(sk); i++) {
+                x509 = wolfSSL_sk_X509_value(sk, i);
+                /* On successful setting of new chain up all refs */
+                if (wolfSSL_X509_up_ref(x509) != 1) {
+                    WOLFSSL_MSG("Error increasing reference count");
+                    continue;
+                }
+            }
+        }
+    }
+#else
+        WOLFSSL_MSG("Session certificates not compiled in");
+        ret = WOLFSSL_FAILURE;
+#endif
+        break;
+
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+    case SSL_CTRL_OPTIONS:
+        WOLFSSL_MSG("Entering Case: SSL_CTRL_OPTIONS.");
+        ctrl_opt = wolfSSL_CTX_set_options(ctx, opt);
+
+        #ifdef WOLFSSL_QT
+        /* Set whether to use client or server cipher preference */
+        if ((ctrl_opt & SSL_OP_CIPHER_SERVER_PREFERENCE)
+                     == SSL_OP_CIPHER_SERVER_PREFERENCE) {
+            WOLFSSL_MSG("Using Server's Cipher Preference.");
+            ctx->useClientOrder = FALSE;
+        } else {
+            WOLFSSL_MSG("Using Client's Cipher Preference.");
+            ctx->useClientOrder = TRUE;
+        }
+        #endif /* WOLFSSL_QT */
+
+        return ctrl_opt;
+#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */
+    case SSL_CTRL_EXTRA_CHAIN_CERT:
+        WOLFSSL_MSG("Entering Case: SSL_CTRL_EXTRA_CHAIN_CERT.");
+        if (pt == NULL) {
+            WOLFSSL_MSG("Passed in x509 pointer NULL.");
+            ret = WOLFSSL_FAILURE;
+            break;
+        }
+        return wolfSSL_CTX_add_extra_chain_cert(ctx, (WOLFSSL_X509*)pt);
+
+#ifndef NO_DH
+    case SSL_CTRL_SET_TMP_DH:
+        WOLFSSL_MSG("Entering Case: SSL_CTRL_SET_TMP_DH.");
+        if (pt == NULL) {
+            WOLFSSL_MSG("Passed in DH pointer NULL.");
+            ret = WOLFSSL_FAILURE;
+            break;
+        }
+        return wolfSSL_CTX_set_tmp_dh(ctx, (WOLFSSL_DH*)pt);
+#endif
+
+#ifdef HAVE_ECC
+    case SSL_CTRL_SET_TMP_ECDH:
+        WOLFSSL_MSG("Entering Case: SSL_CTRL_SET_TMP_ECDH.");
+        if (pt == NULL) {
+            WOLFSSL_MSG("Passed in ECDH pointer NULL.");
+            ret = WOLFSSL_FAILURE;
+            break;
+        }
+        return wolfSSL_SSL_CTX_set_tmp_ecdh(ctx, (WOLFSSL_EC_KEY*)pt);
+#endif
+    case SSL_CTRL_MODE:
+        wolfSSL_CTX_set_mode(ctx,opt);
+        break;
+
+    default:
+        WOLFSSL_MSG("CTX_ctrl cmd not implemented");
+        ret = WOLFSSL_FAILURE;
+        break;
+    }
+
+    (void)ctx;
+    (void)cmd;
+    (void)opt;
+    (void)pt;
+    WOLFSSL_LEAVE("wolfSSL_CTX_ctrl", (int)ret);
+    return ret;
+}
+
+#ifndef WOLFSSL_NO_STUB
+long wolfSSL_CTX_callback_ctrl(WOLFSSL_CTX* ctx, int cmd, void (*fp)(void))
+{
+    (void) ctx;
+    (void) cmd;
+    (void) fp;
+    WOLFSSL_STUB("wolfSSL_CTX_callback_ctrl");
+    return WOLFSSL_FAILURE;
+
+}
+#endif /* WOLFSSL_NO_STUB */
+
+#ifndef NO_WOLFSSL_STUB
+long wolfSSL_CTX_clear_extra_chain_certs(WOLFSSL_CTX* ctx)
+{
+    return wolfSSL_CTX_ctrl(ctx, SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS, 0l, NULL);
+}
+#endif
+
+/* Returns the verifyCallback from the ssl structure if successful.
+Returns NULL otherwise. */
+VerifyCallback wolfSSL_get_verify_callback(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_get_verify_callback()");
+    if (ssl) {
+        return ssl->verifyCallback;
+    }
+    return NULL;
+}
+
+/* Creates a new bio pair.
+Returns WOLFSSL_SUCCESS if no error, WOLFSSL_FAILURE otherwise.*/
+int wolfSSL_BIO_new_bio_pair(WOLFSSL_BIO **bio1_p, size_t writebuf1,
+                                         WOLFSSL_BIO **bio2_p, size_t writebuf2)
+{
+    WOLFSSL_BIO *bio1 = NULL, *bio2 = NULL;
+    int ret = 1;
+
+    WOLFSSL_ENTER("wolfSSL_BIO_new_bio_pair()");
+
+    if (bio1_p == NULL || bio2_p == NULL) {
+        WOLFSSL_MSG("Bad Function Argument");
+        return BAD_FUNC_ARG;
+    }
+
+    /* set up the new bio structures and write buf sizes */
+    if ((bio1 = wolfSSL_BIO_new(wolfSSL_BIO_s_bio())) == NULL) {
+        WOLFSSL_MSG("Bio allocation failed");
+        ret = WOLFSSL_FAILURE;
+    }
+    if (ret) {
+        if ((bio2 = wolfSSL_BIO_new(wolfSSL_BIO_s_bio())) == NULL) {
+            WOLFSSL_MSG("Bio allocation failed");
+            ret = WOLFSSL_FAILURE;
+        }
+    }
+    if (ret && writebuf1) {
+        if (!(ret = wolfSSL_BIO_set_write_buf_size(bio1, writebuf1))) {
+            WOLFSSL_MSG("wolfSSL_BIO_set_write_buf() failure");
+        }
+    }
+    if (ret && writebuf2) {
+        if (!(ret = wolfSSL_BIO_set_write_buf_size(bio2, writebuf2))) {
+            WOLFSSL_MSG("wolfSSL_BIO_set_write_buf() failure");
+        }
+    }
+
+    if (ret) {
+        if ((ret = wolfSSL_BIO_make_bio_pair(bio1, bio2))) {
+            *bio1_p = bio1;
+            *bio2_p = bio2;
+        }
+    }
+    if (!ret) {
+        wolfSSL_BIO_free(bio1);
+        bio1 = NULL;
+        wolfSSL_BIO_free(bio2);
+        bio2 = NULL;
+    }
+    return ret;
+}
+
+
+#if !defined(HAVE_FAST_RSA) && defined(WOLFSSL_KEY_GEN) && \
+    !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+/* Converts an rsa key from a bio buffer into an internal rsa structure.
+Returns a pointer to the new WOLFSSL_RSA structure. */
+WOLFSSL_RSA* wolfSSL_d2i_RSAPrivateKey_bio(WOLFSSL_BIO *bio, WOLFSSL_RSA **out)
+{
+    const unsigned char* bioMem = NULL;
+    int bioMemSz = 0;
+    WOLFSSL_RSA* key = NULL;
+    unsigned char maxKeyBuf[4096];
+    unsigned char* bufPtr = NULL;
+    unsigned char* extraBioMem = NULL;
+    int extraBioMemSz = 0;
+    int derLength = 0;
+    int j = 0, i = 0;
+
+    WOLFSSL_ENTER("wolfSSL_d2i_RSAPrivateKey_bio()");
+
+    if (bio == NULL) {
+        WOLFSSL_MSG("Bad Function Argument");
+        return NULL;
+    }
+    (void)out;
+
+    bioMemSz = wolfSSL_BIO_pending(bio);
+    if (bioMemSz <= 0) {
+        WOLFSSL_MSG("wolfSSL_BIO_pending() failure");
+        return NULL;
+    }
+
+    bioMem = (unsigned char*)XMALLOC(bioMemSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (bioMem == NULL) {
+        WOLFSSL_MSG("Malloc failure");
+        return NULL;
+    }
+
+    bufPtr = maxKeyBuf;
+    if (wolfSSL_BIO_read(bio, (unsigned char*)bioMem, (int)bioMemSz) == bioMemSz) {
+        const byte* bioMemPt = bioMem; /* leave bioMem pointer unaltered */
+        if ((key = wolfSSL_d2i_RSAPrivateKey(NULL, &bioMemPt, bioMemSz)) == NULL) {
+            XFREE((unsigned char*)bioMem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            return NULL;
+        }
+
+        /* This function is used to get the total length of the rsa key. */
+        derLength = wolfSSL_i2d_RSAPrivateKey(key, &bufPtr);
+
+        /* Write extra data back into bio object if necessary. */
+        extraBioMemSz = (bioMemSz - derLength);
+        if (extraBioMemSz > 0) {
+            extraBioMem = (unsigned char *)XMALLOC(extraBioMemSz, NULL,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+            if (extraBioMem == NULL) {
+                WOLFSSL_MSG("Malloc failure");
+                XFREE((unsigned char*)extraBioMem, bio->heap,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+                XFREE((unsigned char*)bioMem, bio->heap,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+                return NULL;
+            }
+
+            for (i = derLength; i < bioMemSz; i++) {
+                *(extraBioMem + j) = *(bioMem + i);
+                j++;
+            }
+
+            wolfSSL_BIO_write(bio, extraBioMem, extraBioMemSz);
+            if (wolfSSL_BIO_pending(bio) <= 0) {
+                WOLFSSL_MSG("Failed to write memory to bio");
+                XFREE((unsigned char*)extraBioMem, bio->heap,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+                XFREE((unsigned char*)bioMem, bio->heap,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+                return NULL;
+            }
+            XFREE((unsigned char*)extraBioMem, bio->heap,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+        }
+
+        if (out != NULL && key != NULL) {
+            *out = key;
+        }
+    }
+    XFREE((unsigned char*)bioMem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    return key;
+}
+#endif
+
+
+/* Adds the ASN1 certificate to the user ctx.
+Returns WOLFSSL_SUCCESS if no error, returns WOLFSSL_FAILURE otherwise.*/
+int wolfSSL_CTX_use_certificate_ASN1(WOLFSSL_CTX *ctx, int derSz,
+                                                       const unsigned char *der)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_ASN1()");
+    if (der != NULL && ctx != NULL) {
+        if (wolfSSL_CTX_use_certificate_buffer(ctx, der, derSz,
+                                      WOLFSSL_FILETYPE_ASN1) == WOLFSSL_SUCCESS) {
+            return WOLFSSL_SUCCESS;
+        }
+
+    }
+    return WOLFSSL_FAILURE;
+}
+
+
+#if !defined(HAVE_FAST_RSA) && defined(WOLFSSL_KEY_GEN) && \
+    !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+/* Adds the rsa private key to the user ctx.
+Returns WOLFSSL_SUCCESS if no error, returns WOLFSSL_FAILURE otherwise.*/
+int wolfSSL_CTX_use_RSAPrivateKey(WOLFSSL_CTX* ctx, WOLFSSL_RSA* rsa)
+{
+    int ret;
+    int derSize;
+    unsigned char maxDerBuf[4096];
+    unsigned char* key = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_CTX_use_RSAPrivateKey()");
+
+    if (ctx == NULL || rsa == NULL) {
+        WOLFSSL_MSG("one or more inputs were NULL");
+        return BAD_FUNC_ARG;
+    }
+    key = maxDerBuf;
+    /* convert RSA struct to der encoded buffer and get the size */
+    if ((derSize = wolfSSL_i2d_RSAPrivateKey(rsa, &key)) <= 0) {
+        WOLFSSL_MSG("wolfSSL_i2d_RSAPrivateKey() failure");
+        return WOLFSSL_FAILURE;
+    }
+    ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx, (const unsigned char*)maxDerBuf,
+                                                    derSize, SSL_FILETYPE_ASN1);
+    if (ret != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("wolfSSL_CTX_USE_PrivateKey_buffer() failure");
+        return WOLFSSL_FAILURE;
+    }
+    return ret;
+}
+#endif /* NO_RSA && !HAVE_FAST_RSA */
+
+
+/* Converts EVP_PKEY data from a bio buffer to a WOLFSSL_EVP_PKEY structure.
+Returns pointer to private EVP_PKEY struct upon success, NULL if there
+is a failure.*/
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_bio(WOLFSSL_BIO* bio,
+                                                         WOLFSSL_EVP_PKEY** out)
+{
+    unsigned char* mem = NULL;
+    int memSz = 0;
+    WOLFSSL_EVP_PKEY* key = NULL;
+    int i = 0, j = 0;
+    unsigned char* extraBioMem = NULL;
+    int extraBioMemSz = 0;
+    int derLength = 0;
+
+    WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_bio()");
+
+    if (bio == NULL) {
+        return NULL;
+    }
+    (void)out;
+
+    memSz = wolfSSL_BIO_pending(bio);
+    if (memSz <= 0) {
+        WOLFSSL_MSG("wolfSSL_BIO_pending() failure");
+        return NULL;
+    }
+
+    mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (mem == NULL) {
+        WOLFSSL_MSG("Malloc failure");
+        return NULL;
+    }
+
+    if (wolfSSL_BIO_read(bio, (unsigned char*)mem, memSz) == memSz) {
+        /* Determines key type and returns the new private EVP_PKEY object */
+        if ((key = wolfSSL_d2i_PrivateKey_EVP(NULL, &mem, (long)memSz)) == NULL) {
+            WOLFSSL_MSG("wolfSSL_d2i_PrivateKey_EVP() failure");
+            XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            return NULL;
+        }
+
+        /* Write extra data back into bio object if necessary. */
+        derLength = key->pkey_sz;
+        extraBioMemSz = (memSz - derLength);
+        if (extraBioMemSz > 0) {
+            extraBioMem = (unsigned char *)XMALLOC(extraBioMemSz, NULL,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+            if (extraBioMem == NULL) {
+                WOLFSSL_MSG("Malloc failure");
+                XFREE((unsigned char*)extraBioMem, bio->heap,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+                XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+                return NULL;
+            }
+
+            for (i = derLength; i < memSz; i++) {
+                *(extraBioMem + j) = *(mem + i);
+                j++;
+            }
+
+            wolfSSL_BIO_write(bio, extraBioMem, extraBioMemSz);
+            if (wolfSSL_BIO_pending(bio) <= 0) {
+                WOLFSSL_MSG("Failed to write memory to bio");
+                XFREE((unsigned char*)extraBioMem, bio->heap,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+                XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+                return NULL;
+            }
+            XFREE((unsigned char*)extraBioMem, bio->heap,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+        }
+
+        if (out != NULL) {
+            *out = key;
+        }
+    }
+    XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    return key;
+}
+
+
+/* Converts a DER encoded private key to a WOLFSSL_EVP_PKEY structure.
+ * returns a pointer to a new WOLFSSL_EVP_PKEY structure on success and NULL
+ * on fail */
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_EVP(WOLFSSL_EVP_PKEY** out,
+                                                  unsigned char** in, long inSz)
+{
+    WOLFSSL_EVP_PKEY* pkey = NULL;
+    const unsigned char* mem;
+    long memSz = inSz;
+
+    WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_EVP()");
+
+    if (in == NULL || *in == NULL || inSz < 0) {
+        WOLFSSL_MSG("Bad argument");
+        return NULL;
+    }
+    mem = *in;
+
+    #if !defined(NO_RSA)
+    {
+        RsaKey rsa;
+        word32 keyIdx = 0;
+
+        /* test if RSA key */
+        if (wc_InitRsaKey(&rsa, NULL) == 0 &&
+            wc_RsaPrivateKeyDecode(mem, &keyIdx, &rsa, (word32)memSz) == 0) {
+            wc_FreeRsaKey(&rsa);
+            pkey = wolfSSL_EVP_PKEY_new();
+            if (pkey != NULL) {
+                pkey->pkey_sz = keyIdx;
+                pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL,
+                        DYNAMIC_TYPE_PRIVATE_KEY);
+                if (pkey->pkey.ptr == NULL) {
+                    wolfSSL_EVP_PKEY_free(pkey);
+                    return NULL;
+                }
+                XMEMCPY(pkey->pkey.ptr, mem, keyIdx);
+                pkey->type = EVP_PKEY_RSA;
+                if (out != NULL) {
+                    *out = pkey;
+                }
+
+                pkey->ownRsa = 1;
+                pkey->rsa = wolfSSL_RSA_new();
+                if (pkey->rsa == NULL) {
+                    wolfSSL_EVP_PKEY_free(pkey);
+                    return NULL;
+                }
+
+                if (wolfSSL_RSA_LoadDer_ex(pkey->rsa,
+                            (const unsigned char*)pkey->pkey.ptr,
+                            pkey->pkey_sz, WOLFSSL_RSA_LOAD_PRIVATE) != 1) {
+                    wolfSSL_EVP_PKEY_free(pkey);
+                    return NULL;
+                }
+
+                return pkey;
+            }
+        }
+        wc_FreeRsaKey(&rsa);
+    }
+    #endif /* NO_RSA */
+
+    #ifdef HAVE_ECC
+    {
+        word32  keyIdx = 0;
+        ecc_key ecc;
+
+        /* test if ecc key */
+        if (wc_ecc_init(&ecc) == 0 &&
+            wc_EccPrivateKeyDecode(mem, &keyIdx, &ecc, (word32)memSz) == 0) {
+            wc_ecc_free(&ecc);
+            pkey = wolfSSL_EVP_PKEY_new();
+            if (pkey != NULL) {
+                pkey->pkey_sz = keyIdx;
+                pkey->pkey.ptr = (char*)XMALLOC(keyIdx, NULL,
+                        DYNAMIC_TYPE_PRIVATE_KEY);
+                if (pkey->pkey.ptr == NULL) {
+                    wolfSSL_EVP_PKEY_free(pkey);
+                    return NULL;
+                }
+                XMEMCPY(pkey->pkey.ptr, mem, keyIdx);
+                pkey->type = EVP_PKEY_EC;
+                if (out != NULL) {
+                    *out = pkey;
+                }
+                return pkey;
+            }
+        }
+        wc_ecc_free(&ecc);
+    }
+    #endif /* HAVE_ECC */
+    return pkey;
+}
+#endif /* OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_QT */
+
+
+/* stunnel compatibility functions*/
+#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || \
+                             defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) || \
+                             defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_OPENSSH)))
+void wolfSSL_ERR_remove_thread_state(void* pid)
+{
+    (void) pid;
+    return;
+}
+
+#ifndef NO_FILESYSTEM
+/***TBD ***/
+void wolfSSL_print_all_errors_fp(XFILE fp)
+{
+    (void)fp;
+}
+#endif
+
+int wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION* session, int idx, void* data)
+{
+    WOLFSSL_ENTER("wolfSSL_SESSION_set_ex_data");
+#ifdef HAVE_EX_DATA
+    if(session != NULL) {
+        return wolfSSL_CRYPTO_set_ex_data(&session->ex_data, idx, data);
+    }
+#else
+    (void)session;
+    (void)idx;
+    (void)data;
+#endif
+    return WOLFSSL_FAILURE;
+}
+
+
+int wolfSSL_SESSION_get_ex_new_index(long idx, void* data, void* cb1,
+       void* cb2, CRYPTO_free_func* cb3)
+{
+    WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_new_index");
+    (void)idx;
+    (void)cb1;
+    (void)cb2;
+    (void)cb3;
+    if (XSTRNCMP((const char*)data, "redirect index", 14) == 0) {
+        return 0;
+    }
+    else if (XSTRNCMP((const char*)data, "addr index", 10) == 0) {
+        return 1;
+    }
+    return WOLFSSL_FAILURE;
+}
+
+
+void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION* session, int idx)
+{
+    WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_data");
+#ifdef HAVE_EX_DATA
+    if (session != NULL) {
+        return wolfSSL_CRYPTO_get_ex_data(&session->ex_data, idx);
+    }
+#else
+    (void)session;
+    (void)idx;
+#endif
+    return NULL;
+}
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_CRYPTO_set_mem_ex_functions(void *(*m) (size_t, const char *, int),
+                                void *(*r) (void *, size_t, const char *,
+                                            int), void (*f) (void *))
+{
+    (void) m;
+    (void) r;
+    (void) f;
+    WOLFSSL_ENTER("wolfSSL_CRYPTO_set_mem_ex_functions");
+    WOLFSSL_STUB("CRYPTO_set_mem_ex_functions");
+
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+
+void wolfSSL_CRYPTO_cleanup_all_ex_data(void){
+    WOLFSSL_ENTER("CRYPTO_cleanup_all_ex_data");
+}
+
+
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_DH *wolfSSL_DH_generate_parameters(int prime_len, int generator,
+                           void (*callback) (int, int, void *), void *cb_arg)
+{
+    (void)prime_len;
+    (void)generator;
+    (void)callback;
+    (void)cb_arg;
+    WOLFSSL_ENTER("wolfSSL_DH_generate_parameters");
+    WOLFSSL_STUB("DH_generate_parameters");
+
+    return NULL;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_DH_generate_parameters_ex(WOLFSSL_DH* dh, int prime_len, int generator,
+                           void (*callback) (int, int, void *))
+{
+    (void)prime_len;
+    (void)generator;
+    (void)callback;
+    (void)dh;
+    WOLFSSL_ENTER("wolfSSL_DH_generate_parameters_ex");
+    WOLFSSL_STUB("DH_generate_parameters_ex");
+
+    return -1;
+}
+#endif
+
+void wolfSSL_ERR_load_crypto_strings(void)
+{
+    WOLFSSL_ENTER("wolfSSL_ERR_load_crypto_strings");
+    /* Do nothing */
+    return;
+}
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_FIPS_mode(void)
+{
+    WOLFSSL_ENTER("wolfSSL_FIPS_mode");
+    WOLFSSL_STUB("FIPS_mode");
+
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_FIPS_mode_set(int r)
+{
+    (void)r;
+    WOLFSSL_ENTER("wolfSSL_FIPS_mode_set");
+    WOLFSSL_STUB("FIPS_mode_set");
+
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_RAND_set_rand_method(const void *meth)
+{
+    (void) meth;
+    WOLFSSL_ENTER("wolfSSL_RAND_set_rand_method");
+    WOLFSSL_STUB("RAND_set_rand_method");
+
+    /* if implemented RAND_bytes and RAND_pseudo_bytes need updated
+     * those two functions will call the respective functions from meth */
+    return SSL_FAILURE;
+}
+#endif
+
+int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits)
+{
+    int ret = WOLFSSL_FAILURE;
+    WOLFSSL_ENTER("wolfSSL_CIPHER_get_bits");
+
+    #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+    (void)alg_bits;
+    if (c!= NULL)
+        ret = c->bits;
+    #else
+    if (c != NULL && c->ssl != NULL) {
+        ret = 8 * c->ssl->specs.key_size;
+        if (alg_bits != NULL) {
+            *alg_bits = ret;
+        }
+    }
+    #endif
+    return ret;
+}
+
+#if defined(OPENSSL_ALL)
+WOLFSSL_X509_INFO* wolfSSL_X509_INFO_new(void)
+{
+    WOLFSSL_X509_INFO* info;
+    info = (WOLFSSL_X509_INFO*)XMALLOC(sizeof(WOLFSSL_X509_INFO), NULL,
+        DYNAMIC_TYPE_X509);
+    if (info) {
+        XMEMSET(info, 0, sizeof(*info));
+    }
+    return info;
+}
+
+void wolfSSL_X509_INFO_free(WOLFSSL_X509_INFO* info)
+{
+    if (info == NULL)
+        return;
+
+    if (info->x509) {
+        wolfSSL_X509_free(info->x509);
+        info->x509 = NULL;
+    }
+#ifdef HAVE_CRL
+    if (info->crl) {
+        wolfSSL_X509_CRL_free(info->crl);
+        info->crl = NULL;
+    }
+#endif
+    wolfSSL_X509_PKEY_free(info->x_pkey);
+    info->x_pkey = NULL;
+
+    XFREE(info, NULL, DYNAMIC_TYPE_X509);
+}
+#endif
+
+WOLFSSL_STACK* wolfSSL_sk_X509_INFO_new_null(void)
+{
+    WOLFSSL_STACK* sk = wolfSSL_sk_new_node(NULL);
+    if (sk) {
+        sk->type = STACK_TYPE_X509_INFO;
+    }
+    return sk;
+}
+
+
+/* returns value less than 0 on fail to match
+ * On a successful match the priority level found is returned
+ */
+int wolfSSL_sk_SSL_CIPHER_find(
+        WOLF_STACK_OF(WOLFSSL_CIPHER)* sk, const WOLFSSL_CIPHER* toFind)
+{
+    WOLFSSL_STACK* next;
+    int i, sz;
+
+    if (sk == NULL || toFind == NULL) {
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    sz   = wolfSSL_sk_SSL_CIPHER_num(sk);
+    next = sk;
+    for (i = 0; i < sz && next != NULL; i++) {
+        if (next->data.cipher.cipherSuite0 == toFind->cipherSuite0 &&
+                next->data.cipher.cipherSuite == toFind->cipherSuite) {
+            return sz - i; /* reverse because stack pushed highest on first */
+        }
+        next = next->next;
+    }
+    return WOLFSSL_FATAL_ERROR;
+}
+
+
+/* copies over data of "in" to "out" */
+static void wolfSSL_CIPHER_copy(WOLFSSL_CIPHER* in, WOLFSSL_CIPHER* out)
+{
+    if (in == NULL || out == NULL)
+        return;
+
+    out->cipherSuite  = in->cipherSuite;
+    out->cipherSuite0 = in->cipherSuite0;
+}
+
+
+/* create duplicate of stack and return the new stack
+ * returns null on failure */
+WOLF_STACK_OF(WOLFSSL_CIPHER)* wolfSSL_sk_SSL_CIPHER_dup(
+        WOLF_STACK_OF(WOLFSSL_CIPHER)* in)
+{
+    WOLFSSL_STACK* current;
+    WOLF_STACK_OF(WOLFSSL_CIPHER)* ret = NULL;
+    int i, sz;
+
+    sz = wolfSSL_sk_SSL_CIPHER_num(in);
+    current = in;
+    for (i = 0; i < sz && current != NULL; i++) {
+        WOLFSSL_STACK* add = wolfSSL_sk_new_node(in->heap);
+        if (add != NULL) {
+            add->type = STACK_TYPE_CIPHER;
+            wolfSSL_CIPHER_copy(&(current->data.cipher), &(add->data.cipher));
+            add->num = i+1;
+            add->next = ret;
+            ret = add;
+            current = current->next;
+        }
+    }
+    return ret;
+}
+
+/* nothing to do yet */
+static void wolfSSL_CIPHER_free(WOLFSSL_CIPHER* in)
+{
+    (void)in;
+}
+
+
+/* free's all nodes in the stack and there data */
+void wolfSSL_sk_SSL_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk)
+{
+    WOLFSSL_STACK* current = sk;
+
+    while (current != NULL) {
+        WOLFSSL_STACK* toFree = current;
+        current = current->next;
+
+        wolfSSL_CIPHER_free(&(toFree->data.cipher));
+        wolfSSL_sk_free_node(toFree);
+    }
+}
+
+
+int wolfSSL_sk_X509_INFO_num(const WOLF_STACK_OF(WOLFSSL_X509_INFO) *sk)
+{
+    WOLFSSL_ENTER("wolfSSL_sk_X509_INFO_num");
+
+    if (sk == NULL)
+        return -1;
+    return (int)sk->num;
+}
+
+WOLFSSL_X509_INFO* wolfSSL_sk_X509_INFO_value(const WOLF_STACK_OF(WOLFSSL_X509_INFO) *sk, int i)
+{
+    WOLFSSL_ENTER("wolfSSL_sk_X509_INFO_value");
+
+    for (; sk != NULL && i > 0; i--)
+        sk = sk->next;
+
+    if (i != 0 || sk == NULL)
+        return NULL;
+    return sk->data.info;
+}
+
+WOLFSSL_X509_INFO* wolfSSL_sk_X509_INFO_pop(WOLF_STACK_OF(WOLFSSL_X509_INFO)* sk)
+{
+    WOLFSSL_STACK* node;
+    WOLFSSL_X509_INFO* info;
+
+    if (sk == NULL) {
+        return NULL;
+    }
+
+    node = sk->next;
+    info = sk->data.info;
+
+    if (node != NULL) { /* update sk and remove node from stack */
+        sk->data.info = node->data.info;
+        sk->next = node->next;
+        XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL);
+    }
+    else { /* last x509 in stack */
+        sk->data.info = NULL;
+    }
+
+    if (sk->num > 0) {
+        sk->num -= 1;
+    }
+
+    return info;
+}
+
+#if defined(OPENSSL_ALL)
+void wolfSSL_sk_X509_INFO_pop_free(WOLF_STACK_OF(WOLFSSL_X509_INFO)* sk,
+    void (*f) (WOLFSSL_X509_INFO*))
+{
+    WOLFSSL_STACK* node;
+
+    WOLFSSL_ENTER("wolfSSL_sk_X509_INFO_pop_free");
+
+    if (sk == NULL) {
+        return;
+    }
+
+    /* parse through stack freeing each node */
+    node = sk->next;
+    while (node && sk->num > 1) {
+        WOLFSSL_STACK* tmp = node;
+        node = node->next;
+
+        if (f)
+            f(tmp->data.info);
+        else
+            wolfSSL_X509_INFO_free(tmp->data.info);
+        tmp->data.info = NULL;
+        XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL);
+        sk->num -= 1;
+    }
+
+    /* free head of stack */
+    if (sk->num == 1) {
+        if (f)
+            f(sk->data.info);
+        else
+            wolfSSL_X509_INFO_free(sk->data.info);
+        sk->data.info = NULL;
+    }
+    XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL);
+}
+
+void wolfSSL_sk_X509_INFO_free(WOLF_STACK_OF(WOLFSSL_X509_INFO) *sk)
+{
+    wolfSSL_sk_X509_INFO_pop_free(sk, NULL);
+}
+
+
+/* Adds the WOLFSSL_X509_INFO to the stack "sk". "sk" takes control of "in" and
+ * tries to free it when the stack is free'd.
+ *
+ * return 1 on success 0 on fail
+ */
+int wolfSSL_sk_X509_INFO_push(WOLF_STACK_OF(WOLFSSL_X509_INFO)* sk,
+                                                      WOLFSSL_X509_INFO* in)
+{
+    WOLFSSL_STACK* node;
+
+    if (sk == NULL || in == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* no previous values in stack */
+    if (sk->data.info == NULL) {
+        sk->data.info = in;
+        sk->num += 1;
+        return WOLFSSL_SUCCESS;
+    }
+
+    /* stack already has value(s) create a new node and add more */
+    node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+            DYNAMIC_TYPE_X509);
+    if (node == NULL) {
+        WOLFSSL_MSG("Memory error");
+        return WOLFSSL_FAILURE;
+    }
+    XMEMSET(node, 0, sizeof(WOLFSSL_STACK));
+
+    /* push new obj onto head of stack */
+    node->data.info = sk->data.info;
+    node->next      = sk->next;
+    node->type      = sk->type;
+    sk->next        = node;
+    sk->data.info   = in;
+    sk->num        += 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_sk_X509_NAME_new(wolf_sk_compare_cb cb)
+{
+    WOLFSSL_STACK* sk;
+
+    WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_new");
+
+    sk = wolfSSL_sk_new_node(NULL);
+    if (sk != NULL) {
+        sk->type = STACK_TYPE_X509_NAME;
+        sk->comp = cb;
+    }
+
+    return sk;
+}
+
+int wolfSSL_sk_X509_NAME_push(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk,
+    WOLFSSL_X509_NAME* name)
+{
+    WOLFSSL_STACK* node;
+
+    WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_push");
+
+    if (sk == NULL || name == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* no previous values in stack */
+    if (sk->data.name == NULL) {
+        sk->data.name = name;
+        sk->num += 1;
+        return 0;
+    }
+
+    /* stack already has value(s) create a new node and add more */
+    node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+        DYNAMIC_TYPE_OPENSSL);
+    if (node == NULL) {
+        WOLFSSL_MSG("Memory error");
+        return MEMORY_E;
+    }
+    XMEMSET(node, 0, sizeof(WOLFSSL_STACK));
+
+    /* push new obj onto head of stack */
+    node->data.name = sk->data.name;
+    node->next      = sk->next;
+    sk->type        = STACK_TYPE_X509_NAME;
+    sk->next        = node;
+    sk->data.name   = name;
+    sk->num        += 1;
+
+    return 0;
+}
+
+/* return index of found, or negative to indicate not found */
+int wolfSSL_sk_X509_NAME_find(const WOLF_STACK_OF(WOLFSSL_X509_NAME) *sk,
+    WOLFSSL_X509_NAME *name)
+{
+    int i;
+
+    WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_find");
+
+    if (sk == NULL)
+        return BAD_FUNC_ARG;
+
+    for (i = 0; sk; i++, sk = sk->next) {
+        if (wolfSSL_X509_NAME_cmp(sk->data.name, name) == 0) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+int wolfSSL_sk_X509_OBJECT_num(const WOLF_STACK_OF(WOLFSSL_X509_OBJECT) *s)
+{
+    WOLFSSL_ENTER("wolfSSL_sk_X509_OBJECT_num");
+    if (s) {
+        return (int)s->num;
+    } else {
+        return 0;
+    }
+}
+
+
+int wolfSSL_sk_X509_NAME_set_cmp_func(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk,
+    wolf_sk_compare_cb cb)
+{
+    WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_set_cmp_func");
+
+    if (sk == NULL)
+        return BAD_FUNC_ARG;
+
+    sk->comp = cb;
+    return 0;
+}
+#endif /* OPENSSL_ALL */
+
+int wolfSSL_sk_X509_NAME_num(const WOLF_STACK_OF(WOLFSSL_X509_NAME) *sk)
+{
+    WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_num");
+
+    if (sk == NULL)
+        return BAD_FUNC_ARG;
+
+    return (int)sk->num;
+}
+
+/* Getter function for WOLFSSL_X509_NAME pointer
+ *
+ * sk is the stack to retrieve pointer from
+ * i  is the index value in stack
+ *
+ * returns a pointer to a WOLFSSL_X509_NAME structure on success and NULL on
+ *         fail
+ */
+WOLFSSL_X509_NAME* wolfSSL_sk_X509_NAME_value(const STACK_OF(WOLFSSL_X509_NAME)* sk,
+    int i)
+{
+    WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_value");
+
+    for (; sk != NULL && i > 0; i--) {
+        sk = sk->next;
+    }
+
+    if (i != 0 || sk == NULL)
+        return NULL;
+
+    return sk->data.name;
+}
+
+WOLFSSL_X509_NAME* wolfSSL_sk_X509_NAME_pop(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk)
+{
+    WOLFSSL_STACK* node;
+    WOLFSSL_X509_NAME* name;
+
+    if (sk == NULL) {
+        return NULL;
+    }
+
+    node = sk->next;
+    name = sk->data.name;
+
+    if (node != NULL) { /* update sk and remove node from stack */
+        sk->data.name = node->data.name;
+        sk->next = node->next;
+        XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL);
+    }
+    else { /* last x509 in stack */
+        sk->data.name = NULL;
+    }
+
+    if (sk->num > 0) {
+        sk->num -= 1;
+    }
+
+    return name;
+}
+
+void wolfSSL_sk_X509_NAME_pop_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk,
+    void (*f) (WOLFSSL_X509_NAME*))
+{
+    WOLFSSL_STACK* node;
+    WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_pop_free");
+
+    if (sk == NULL)
+        return;
+
+    node = sk->next;
+    while (node && sk->num > 1) {
+        WOLFSSL_STACK* tmp = node;
+        node = node->next;
+        if (f)
+            f(tmp->data.name);
+        else
+            wolfSSL_X509_NAME_free(tmp->data.name);
+        tmp->data.name = NULL;
+        XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL);
+        sk->num -= 1;
+    }
+
+    /* free head of stack */
+    if (sk->num == 1) {
+        if (f)
+            f(sk->data.name);
+        else
+            wolfSSL_X509_NAME_free(sk->data.name);
+        sk->data.name = NULL;
+    }
+
+    XFREE(sk, sk->heap, DYNAMIC_TYPE_OPENSSL);
+}
+
+/* Free only the sk structure, NOT X509_NAME members */
+void wolfSSL_sk_X509_NAME_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk)
+{
+    WOLFSSL_STACK* node;
+    WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_free");
+
+    if (sk == NULL)
+        return;
+
+    node = sk->next;
+    while (sk->num > 1) {
+        WOLFSSL_STACK* tmp = node;
+        node = node->next;
+        XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL);
+        sk->num -= 1;
+    }
+
+    XFREE(sk, sk->heap, DYNAMIC_TYPE_OPENSSL);
+}
+
+#if defined(WOLFSSL_APACHE_HTTPD) || defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+/* Helper function for X509_NAME_print_ex. Sets *buf to string for domain
+   name attribute based on NID. Returns size of buf */
+static int get_dn_attr_by_nid(int n, const char** buf)
+{
+    int len = 0;
+    const char *str;
+
+    switch(n)
+    {
+        case NID_commonName :
+            str = "CN";
+            len = 2;
+            break;
+        case NID_countryName:
+            str = "C";
+            len = 1;
+            break;
+        case NID_localityName:
+            str = "L";
+            len = 1;
+            break;
+        case NID_stateOrProvinceName:
+            str = "ST";
+            len = 2;
+            break;
+        case NID_organizationName:
+            str = "O";
+            len = 1;
+            break;
+        case NID_organizationalUnitName:
+            str = "OU";
+            len = 2;
+            break;
+        case NID_emailAddress:
+            str = "emailAddress";
+            len = 12;
+            break;
+        default:
+            WOLFSSL_MSG("Attribute type not found");
+            str = NULL;
+
+    }
+    if (buf != NULL)
+        *buf = str;
+    return len;
+}
+#endif
+
+/*
+ * The BIO output of  wolfSSL_X509_NAME_print_ex does NOT include the null terminator
+ */
+int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509_NAME* name,
+                int indent, unsigned long flags)
+{
+#if defined(WOLFSSL_APACHE_HTTPD) || defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+    int count = 0, len = 0, totalSz = 0, tmpSz = 0;
+    char tmp[ASN_NAME_MAX];
+    char fullName[ASN_NAME_MAX];
+    const char *buf = NULL;
+    WOLFSSL_X509_NAME_ENTRY* ne;
+    WOLFSSL_ASN1_STRING* str;
+#endif
+    int i;
+    (void)flags;
+    WOLFSSL_ENTER("wolfSSL_X509_NAME_print_ex");
+
+    for (i = 0; i < indent; i++) {
+        if (wolfSSL_BIO_write(bio, " ", 1) != 1)
+            return WOLFSSL_FAILURE;
+    }
+
+#if defined(WOLFSSL_APACHE_HTTPD) || defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+    /* If XN_FLAG_DN_REV is present, print X509_NAME in reverse order */
+    if (flags == (XN_FLAG_RFC2253 & ~XN_FLAG_DN_REV)) {
+        fullName[0] = '\0';
+        count = wolfSSL_X509_NAME_entry_count(name);
+        for (i = 0; i < count; i++) {
+            ne = wolfSSL_X509_NAME_get_entry(name, count - i - 1);
+            if (ne == NULL)
+                return WOLFSSL_FAILURE;
+
+            str = wolfSSL_X509_NAME_ENTRY_get_data(ne);
+            if (str == NULL)
+                return WOLFSSL_FAILURE;
+
+            len = get_dn_attr_by_nid(ne->nid, &buf);
+            if (len == 0 || buf == NULL)
+                return WOLFSSL_FAILURE;
+
+            tmpSz = str->length + len + 2; /* + 2 for '=' and comma */
+            if (tmpSz > ASN_NAME_MAX) {
+                WOLFSSL_MSG("Size greater than ASN_NAME_MAX");
+                return WOLFSSL_FAILURE;
+            }
+
+            if (i < count - 1) {
+                /* tmpSz+1 for last null char */
+                XSNPRINTF(tmp, tmpSz+1, "%s=%s,", buf, str->data);
+                XSTRNCAT(fullName, tmp, tmpSz);
+            }
+            else {
+                XSNPRINTF(tmp, tmpSz, "%s=%s", buf, str->data);
+                XSTRNCAT(fullName, tmp, tmpSz-1);
+                tmpSz--; /* Don't include null char in tmpSz */
+            }
+            totalSz += tmpSz;
+        }
+        if (wolfSSL_BIO_write(bio, fullName, totalSz) != totalSz)
+            return WOLFSSL_FAILURE;
+        return WOLFSSL_SUCCESS;
+    }
+#else
+    if (flags == XN_FLAG_RFC2253) {
+        if (wolfSSL_BIO_write(bio, name->name + 1, name->sz - 2)
+                                                                != name->sz - 2)
+            return WOLFSSL_FAILURE;
+    }
+#endif /* WOLFSSL_APACHE_HTTPD || OPENSSL_ALL || WOLFSSL_NGINX */
+    else if (wolfSSL_BIO_write(bio, name->name, name->sz - 1) != name->sz - 1)
+        return WOLFSSL_FAILURE;
+
+    return WOLFSSL_SUCCESS;
+}
+
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_ASN1_BIT_STRING* wolfSSL_X509_get0_pubkey_bitstr(const WOLFSSL_X509* x)
+{
+    (void)x;
+    WOLFSSL_ENTER("wolfSSL_X509_get0_pubkey_bitstr");
+    WOLFSSL_STUB("X509_get0_pubkey_bitstr");
+
+    return NULL;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session)
+{
+    (void)ctx;
+    (void)session;
+    WOLFSSL_ENTER("wolfSSL_CTX_add_session");
+    WOLFSSL_STUB("SSL_CTX_add_session");
+
+    return WOLFSSL_SUCCESS;
+}
+#endif
+
+
+int wolfSSL_version(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_version");
+    if (ssl->version.major == SSLv3_MAJOR) {
+        switch (ssl->version.minor) {
+            case SSLv3_MINOR :
+                return SSL3_VERSION;
+            case TLSv1_MINOR :
+                return TLS1_VERSION;
+            case TLSv1_1_MINOR :
+                return TLS1_1_VERSION;
+            case TLSv1_2_MINOR :
+                return TLS1_2_VERSION;
+            case TLSv1_3_MINOR :
+                return TLS1_3_VERSION;
+            default:
+                return WOLFSSL_FAILURE;
+        }
+    }
+    else if (ssl->version.major == DTLS_MAJOR) {
+        switch (ssl->version.minor) {
+            case DTLS_MINOR :
+                return DTLS1_VERSION;
+            case DTLSv1_2_MINOR :
+                return DTLS1_2_VERSION;
+            default:
+                return WOLFSSL_FAILURE;
+        }
+    }
+    return WOLFSSL_FAILURE;
+}
+
+
+int wolfSSL_X509_NAME_get_sz(WOLFSSL_X509_NAME* name)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_NAME_get_sz");
+    if(!name)
+        return -1;
+    return name->sz;
+}
+
+#ifdef HAVE_SNI
+int wolfSSL_set_tlsext_host_name(WOLFSSL* ssl, const char* host_name)
+{
+    int ret;
+    WOLFSSL_ENTER("wolfSSL_set_tlsext_host_name");
+    ret = wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME,
+            host_name, (word16)XSTRLEN(host_name));
+    WOLFSSL_LEAVE("wolfSSL_set_tlsext_host_name", ret);
+    return ret;
+}
+
+
+#ifndef NO_WOLFSSL_SERVER
+const char * wolfSSL_get_servername(WOLFSSL* ssl, byte type)
+{
+    void * serverName = NULL;
+    if (ssl == NULL)
+        return NULL;
+    TLSX_SNI_GetRequest(ssl->extensions, type, &serverName);
+    return (const char *)serverName;
+}
+#endif /* NO_WOLFSSL_SERVER */
+#endif /* HAVE_SNI */
+
+WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
+{
+    if (ssl && ctx && SetSSL_CTX(ssl, ctx, 0) == WOLFSSL_SUCCESS)
+        return ssl->ctx;
+    return NULL;
+}
+
+
+VerifyCallback wolfSSL_CTX_get_verify_callback(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_get_verify_callback");
+    if(ctx)
+        return ctx->verifyCallback;
+    return NULL;
+}
+
+
+void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX* ctx, CallbackSniRecv cb)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_set_servername_callback");
+    if (ctx)
+        ctx->sniRecvCb = cb;
+}
+
+int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX* ctx,
+                                               CallbackSniRecv cb)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_set_tlsext_servername_callback");
+    if (ctx) {
+        ctx->sniRecvCb = cb;
+        return WOLFSSL_SUCCESS;
+    }
+    return WOLFSSL_FAILURE;
+}
+
+int wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX* ctx, void* arg)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_set_servername_arg");
+    if (ctx) {
+        ctx->sniRecvCbArg = arg;
+        return WOLFSSL_SUCCESS;
+    }
+    return WOLFSSL_FAILURE;
+}
+
+void wolfSSL_ERR_load_BIO_strings(void) {
+    WOLFSSL_ENTER("ERR_load_BIO_strings");
+    /* do nothing */
+}
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_THREADID_set_callback(void(*threadid_func)(void*))
+{
+    WOLFSSL_ENTER("wolfSSL_THREADID_set_callback");
+    WOLFSSL_STUB("CRYPTO_THREADID_set_callback");
+    (void)threadid_func;
+    return;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_THREADID_set_numeric(void* id, unsigned long val)
+{
+    WOLFSSL_ENTER("wolfSSL_THREADID_set_numeric");
+    WOLFSSL_STUB("CRYPTO_THREADID_set_numeric");
+    (void)id;
+    (void)val;
+    return;
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_STUB
+WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs(
+    WOLFSSL_X509_STORE_CTX* ctx, WOLFSSL_X509_NAME* name)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_STORE_get1_certs");
+    WOLFSSL_STUB("X509_STORE_get1_certs");
+    (void)ctx;
+    (void)name;
+    return NULL;
+}
+
+WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* wolfSSL_X509_STORE_get0_objects(
+    WOLFSSL_X509_STORE* store)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_STORE_get0_objects");
+    WOLFSSL_STUB("wolfSSL_X509_STORE_get0_objects");
+    (void)store;
+    return NULL;
+}
+
+WOLFSSL_X509_OBJECT* wolfSSL_sk_X509_OBJECT_delete(
+    WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* sk, int i)
+{
+    WOLFSSL_ENTER("wolfSSL_sk_X509_OBJECT_delete");
+    WOLFSSL_STUB("wolfSSL_sk_X509_OBJECT_delete");
+    (void)sk;
+    (void)i;
+    return NULL;
+}
+
+void wolfSSL_X509_OBJECT_free(WOLFSSL_X509_OBJECT *a)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_OBJECT_free");
+    WOLFSSL_STUB("wolfSSL_X509_OBJECT_free");
+    (void)a;
+}
+
+#endif
+
+
+#endif /* OPENSSL_ALL || (OPENSSL_EXTRA && (HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_LIGHTY)) */
+
+
+#if defined(OPENSSL_EXTRA)
+
+int wolfSSL_sk_X509_num(const WOLF_STACK_OF(WOLFSSL_X509) *s)
+{
+    WOLFSSL_ENTER("wolfSSL_sk_X509_num");
+
+    if (s == NULL)
+        return -1;
+    return (int)s->num;
+}
+
+unsigned long wolfSSL_ERR_peek_last_error(void)
+{
+    WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error");
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_NGINX)
+    {
+        int ret;
+
+        if ((ret = wc_PeekErrorNode(-1, NULL, NULL, NULL)) < 0) {
+            WOLFSSL_MSG("Issue peeking at error node in queue");
+            return 0;
+        }
+        if (ret == -ASN_NO_PEM_HEADER)
+            return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE;
+        return (unsigned long)ret;
+    }
+#else
+    return (unsigned long)(0 - NOT_COMPILED_IN);
+#endif
+}
+
+#endif /* OPENSSL_EXTRA */
+
+WOLFSSL_CTX* wolfSSL_get_SSL_CTX(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_get_SSL_CTX");
+    return ssl->ctx;
+}
+
+#if defined(OPENSSL_ALL) || \
+    defined(OPENSSL_EXTRA) || defined(HAVE_STUNNEL) || \
+    defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+
+const byte* wolfSSL_SESSION_get_id(WOLFSSL_SESSION* sess, unsigned int* idLen)
+{
+    WOLFSSL_ENTER("wolfSSL_SESSION_get_id");
+    if(!sess || !idLen) {
+        WOLFSSL_MSG("Bad func args. Please provide idLen");
+        return NULL;
+    }
+    *idLen = sess->sessionIDSz;
+    return sess->sessionID;
+}
+
+#if (defined(HAVE_SESSION_TICKET) || defined(SESSION_CERTS)) && \
+    !defined(NO_FILESYSTEM)
+
+#if defined(SESSION_CERTS) || \
+   (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET))
+/* returns a pointer to the protocol used by the session */
+static const char* wolfSSL_SESSION_get_protocol(const WOLFSSL_SESSION* in)
+{
+    return wolfSSL_internal_get_version((ProtocolVersion*)&in->version);
+}
+#endif
+
+/* returns true (non 0) if the session has EMS (extended master secret) */
+static int wolfSSL_SESSION_haveEMS(const WOLFSSL_SESSION* in)
+{
+    if (in == NULL)
+        return 0;
+    return in->haveEMS;
+}
+
+#if defined(HAVE_SESSION_TICKET)
+/* prints out the ticket to bio passed in
+ * return WOLFSSL_SUCCESS on success
+ */
+static int wolfSSL_SESSION_print_ticket(WOLFSSL_BIO* bio,
+        const WOLFSSL_SESSION* in, const char* tab)
+{
+    unsigned short i, j, z, sz;
+    short tag = 0;
+    byte* pt;
+
+
+    if (in == NULL || bio == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    sz = in->ticketLen;
+    pt = in->ticket;
+
+    if (wolfSSL_BIO_printf(bio, "%s\n", (sz == 0)? " NONE": "") <= 0)
+        return WOLFSSL_FAILURE;
+
+    for (i = 0; i < sz;) {
+        char asc[16];
+
+        if (sz - i < 16) {
+            if (wolfSSL_BIO_printf(bio, "%s%04X -", tab, tag + (sz - i)) <= 0)
+                return WOLFSSL_FAILURE;
+        }
+        else {
+            if (wolfSSL_BIO_printf(bio, "%s%04X -", tab, tag) <= 0)
+                return WOLFSSL_FAILURE;
+        }
+        for (j = 0; i < sz && j < 8; j++,i++) {
+            asc[j] =  ((pt[i])&0x6f)>='A'?((pt[i])&0x6f):'.';
+            if (wolfSSL_BIO_printf(bio, " %02X", pt[i]) <= 0)
+                return WOLFSSL_FAILURE;
+        }
+
+        if (i < sz) {
+            asc[j] =  ((pt[i])&0x6f)>='A'?((pt[i])&0x6f):'.';
+            if (wolfSSL_BIO_printf(bio, "-%02X", pt[i]) <= 0)
+                return WOLFSSL_FAILURE;
+            j++;
+            i++;
+        }
+
+        for (; i < sz && j < 16; j++,i++) {
+            asc[j] =  ((pt[i])&0x6f)>='A'?((pt[i])&0x6f):'.';
+            if (wolfSSL_BIO_printf(bio, " %02X", pt[i]) <= 0)
+                return WOLFSSL_FAILURE;
+        }
+
+        /* pad out spacing */
+        for (z = j; z < 17; z++) {
+            if (wolfSSL_BIO_printf(bio, "   ") <= 0)
+                return WOLFSSL_FAILURE;
+        }
+
+        for (z = 0; z < j; z++) {
+            if (wolfSSL_BIO_printf(bio, "%c", asc[z]) <= 0)
+                return WOLFSSL_FAILURE;
+        }
+        if (wolfSSL_BIO_printf(bio, "\n") <= 0)
+            return WOLFSSL_FAILURE;
+
+        tag += 16;
+    }
+    return WOLFSSL_SUCCESS;
+}
+#endif /* HAVE_SESSION_TICKET */
+
+
+/* prints out the session information in human readable form
+ * return WOLFSSL_SUCCESS on success
+ */
+int wolfSSL_SESSION_print(WOLFSSL_BIO *bp, const WOLFSSL_SESSION *x)
+{
+    const unsigned char* pt;
+    unsigned char buf[SECRET_LEN];
+    unsigned int sz = 0, i;
+    int ret;
+    WOLFSSL_SESSION* session = (WOLFSSL_SESSION*)x;
+
+    if (session == NULL) {
+        WOLFSSL_MSG("Bad NULL argument");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (wolfSSL_BIO_printf(bp, "%s\n", "SSL-Session:") <= 0)
+        return WOLFSSL_FAILURE;
+
+#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
+                               defined(HAVE_SESSION_TICKET))
+    if (wolfSSL_BIO_printf(bp, "    Protocol  : %s\n",
+            wolfSSL_SESSION_get_protocol(session)) <= 0)
+        return WOLFSSL_FAILURE;
+#endif
+
+    if (wolfSSL_BIO_printf(bp, "    Cipher    : %s\n",
+            wolfSSL_SESSION_CIPHER_get_name(session)) <= 0)
+        return WOLFSSL_FAILURE;
+
+    pt = wolfSSL_SESSION_get_id(session, &sz);
+    if (wolfSSL_BIO_printf(bp, "    Session-ID: ") <= 0)
+        return WOLFSSL_FAILURE;
+
+    for (i = 0; i < sz; i++) {
+        if (wolfSSL_BIO_printf(bp, "%02X", pt[i]) <= 0)
+            return WOLFSSL_FAILURE;
+    }
+    if (wolfSSL_BIO_printf(bp, "\n") <= 0)
+        return WOLFSSL_FAILURE;
+
+    if (wolfSSL_BIO_printf(bp, "    Session-ID-ctx: \n") <= 0)
+        return WOLFSSL_FAILURE;
+
+    ret = wolfSSL_SESSION_get_master_key(x, buf, sizeof(buf));
+    if (wolfSSL_BIO_printf(bp, "    Master-Key: ") <= 0)
+        return WOLFSSL_FAILURE;
+
+    if (ret > 0) {
+        sz = (unsigned int)ret;
+        for (i = 0; i < sz; i++) {
+            if (wolfSSL_BIO_printf(bp, "%02X", buf[i]) <= 0)
+                return WOLFSSL_FAILURE;
+        }
+    }
+    if (wolfSSL_BIO_printf(bp, "\n") <= 0)
+        return WOLFSSL_FAILURE;
+
+    /* @TODO PSK identity hint and SRP */
+
+    if (wolfSSL_BIO_printf(bp, "    TLS session ticket:") <= 0)
+        return WOLFSSL_FAILURE;
+
+#ifdef HAVE_SESSION_TICKET
+    if (wolfSSL_SESSION_print_ticket(bp, x, "    ") != WOLFSSL_SUCCESS)
+        return WOLFSSL_FAILURE;
+#endif
+
+    if (wolfSSL_BIO_printf(bp, "    Start Time: %ld\n",
+                wolfSSL_SESSION_get_time(x)) <= 0)
+        return WOLFSSL_FAILURE;
+
+    if (wolfSSL_BIO_printf(bp, "    Timeout   : %ld (sec)\n",
+            wolfSSL_SESSION_get_timeout(x)) <= 0)
+        return WOLFSSL_FAILURE;
+
+    /* @TODO verify return code print */
+
+    if (wolfSSL_BIO_printf(bp, "    Extended master secret: %s\n",
+            (wolfSSL_SESSION_haveEMS(session) == 0)? "no" : "yes") <= 0)
+        return WOLFSSL_FAILURE;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* (HAVE_SESSION_TICKET || SESSION_CERTS) && !NO_FILESYSTEM */
+
+#endif /* OPENSSL_ALL || OPENSSL_EXTRA || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
+
+#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && defined(HAVE_STUNNEL)) \
+    || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX)
+
+int wolfSSL_CTX_get_verify_mode(WOLFSSL_CTX* ctx)
+{
+    int mode = 0;
+    WOLFSSL_ENTER("wolfSSL_CTX_get_verify_mode");
+
+    if(!ctx)
+        return WOLFSSL_FATAL_ERROR;
+
+    if (ctx->verifyPeer)
+        mode |= WOLFSSL_VERIFY_PEER;
+    else if (ctx->verifyNone)
+        mode |= WOLFSSL_VERIFY_NONE;
+
+    if (ctx->failNoCert)
+        mode |= WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT;
+
+    if (ctx->failNoCertxPSK)
+        mode |= WOLFSSL_VERIFY_FAIL_EXCEPT_PSK;
+
+    WOLFSSL_LEAVE("wolfSSL_CTX_get_verify_mode", mode);
+    return mode;
+}
+
+#endif
+#if defined(OPENSSL_EXTRA) && defined(HAVE_CURVE25519)
+/* return 1 if success, 0 if error
+ * output keys are little endian format
+ */
+int wolfSSL_EC25519_generate_key(unsigned char *priv, unsigned int *privSz,
+                                 unsigned char *pub, unsigned int *pubSz)
+{
+#ifndef WOLFSSL_KEY_GEN
+    WOLFSSL_MSG("No Key Gen built in");
+    (void) priv;
+    (void) privSz;
+    (void) pub;
+    (void) pubSz;
+    return WOLFSSL_FAILURE;
+#else /* WOLFSSL_KEY_GEN */
+    int ret = WOLFSSL_FAILURE;
+    int initTmpRng = 0;
+    WC_RNG *rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG *tmpRNG = NULL;
+#else
+    WC_RNG tmpRNG[1];
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_EC25519_generate_key");
+
+    if (priv == NULL || privSz == NULL || *privSz < CURVE25519_KEYSIZE ||
+        pub == NULL || pubSz == NULL || *pubSz < CURVE25519_KEYSIZE) {
+        WOLFSSL_MSG("Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+    if (tmpRNG == NULL)
+        return WOLFSSL_FAILURE;
+#endif
+    if (wc_InitRng(tmpRNG) == 0) {
+        rng = tmpRNG;
+        initTmpRng = 1;
+    }
+    else {
+        WOLFSSL_MSG("Bad RNG Init, trying global");
+        if (initGlobalRNG == 0)
+            WOLFSSL_MSG("Global RNG no Init");
+        else
+            rng = &globalRNG;
+    }
+
+    if (rng) {
+        curve25519_key key;
+
+        if (wc_curve25519_init(&key) != MP_OKAY)
+            WOLFSSL_MSG("wc_curve25519_init failed");
+        else if (wc_curve25519_make_key(rng, CURVE25519_KEYSIZE, &key)!=MP_OKAY)
+            WOLFSSL_MSG("wc_curve25519_make_key failed");
+        /* export key pair */
+        else if (wc_curve25519_export_key_raw_ex(&key, priv, privSz, pub,
+                                                 pubSz, EC25519_LITTLE_ENDIAN)
+                 != MP_OKAY)
+            WOLFSSL_MSG("wc_curve25519_export_key_raw_ex failed");
+        else
+            ret = WOLFSSL_SUCCESS;
+
+        wc_curve25519_free(&key);
+    }
+
+    if (initTmpRng)
+        wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+    return ret;
+#endif /* WOLFSSL_KEY_GEN */
+}
+
+/* return 1 if success, 0 if error
+ * input and output keys are little endian format
+ */
+int wolfSSL_EC25519_shared_key(unsigned char *shared, unsigned int *sharedSz,
+                               const unsigned char *priv, unsigned int privSz,
+                               const unsigned char *pub, unsigned int pubSz)
+{
+#ifndef WOLFSSL_KEY_GEN
+    WOLFSSL_MSG("No Key Gen built in");
+    (void) shared;
+    (void) sharedSz;
+    (void) priv;
+    (void) privSz;
+    (void) pub;
+    (void) pubSz;
+    return WOLFSSL_FAILURE;
+#else /* WOLFSSL_KEY_GEN */
+    int ret = WOLFSSL_FAILURE;
+    curve25519_key privkey, pubkey;
+
+    WOLFSSL_ENTER("wolfSSL_EC25519_shared_key");
+
+    if (shared == NULL || sharedSz == NULL || *sharedSz < CURVE25519_KEYSIZE ||
+        priv == NULL || privSz < CURVE25519_KEYSIZE ||
+        pub == NULL || pubSz < CURVE25519_KEYSIZE) {
+        WOLFSSL_MSG("Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* import private key */
+    if (wc_curve25519_init(&privkey) != MP_OKAY) {
+        WOLFSSL_MSG("wc_curve25519_init privkey failed");
+        return ret;
+    }
+    if (wc_curve25519_import_private_ex(priv, privSz, &privkey,
+                                        EC25519_LITTLE_ENDIAN) != MP_OKAY) {
+        WOLFSSL_MSG("wc_curve25519_import_private_ex failed");
+        wc_curve25519_free(&privkey);
+        return ret;
+    }
+
+    /* import public key */
+    if (wc_curve25519_init(&pubkey) != MP_OKAY) {
+        WOLFSSL_MSG("wc_curve25519_init pubkey failed");
+        wc_curve25519_free(&privkey);
+        return ret;
+    }
+    if (wc_curve25519_import_public_ex(pub, pubSz, &pubkey,
+                                       EC25519_LITTLE_ENDIAN) != MP_OKAY) {
+        WOLFSSL_MSG("wc_curve25519_import_public_ex failed");
+        wc_curve25519_free(&privkey);
+        wc_curve25519_free(&pubkey);
+        return ret;
+    }
+
+    if (wc_curve25519_shared_secret_ex(&privkey, &pubkey,
+                                       shared, sharedSz,
+                                       EC25519_LITTLE_ENDIAN) != MP_OKAY)
+        WOLFSSL_MSG("wc_curve25519_shared_secret_ex failed");
+    else
+        ret = WOLFSSL_SUCCESS;
+
+    wc_curve25519_free(&privkey);
+    wc_curve25519_free(&pubkey);
+
+    return ret;
+#endif /* WOLFSSL_KEY_GEN */
+}
+#endif /* OPENSSL_EXTRA && HAVE_CURVE25519 */
+
+#if defined(OPENSSL_EXTRA) && defined(HAVE_ED25519)
+/* return 1 if success, 0 if error
+ * output keys are little endian format
+ */
+int wolfSSL_ED25519_generate_key(unsigned char *priv, unsigned int *privSz,
+                                 unsigned char *pub, unsigned int *pubSz)
+{
+#ifndef WOLFSSL_KEY_GEN
+    WOLFSSL_MSG("No Key Gen built in");
+    (void) priv;
+    (void) privSz;
+    (void) pub;
+    (void) pubSz;
+    return WOLFSSL_FAILURE;
+#else /* WOLFSSL_KEY_GEN */
+    int ret = WOLFSSL_FAILURE;
+    int initTmpRng = 0;
+    WC_RNG *rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG *tmpRNG = NULL;
+#else
+    WC_RNG tmpRNG[1];
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_ED25519_generate_key");
+
+    if (priv == NULL || privSz == NULL || *privSz < ED25519_PRV_KEY_SIZE ||
+        pub == NULL || pubSz == NULL || *pubSz < ED25519_PUB_KEY_SIZE) {
+        WOLFSSL_MSG("Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+    if (tmpRNG == NULL)
+        return WOLFSSL_FATAL_ERROR;
+#endif
+    if (wc_InitRng(tmpRNG) == 0) {
+        rng = tmpRNG;
+        initTmpRng = 1;
+    }
+    else {
+        WOLFSSL_MSG("Bad RNG Init, trying global");
+        if (initGlobalRNG == 0)
+            WOLFSSL_MSG("Global RNG no Init");
+        else
+            rng = &globalRNG;
+    }
+
+    if (rng) {
+        ed25519_key key;
+
+        if (wc_ed25519_init(&key) != MP_OKAY)
+            WOLFSSL_MSG("wc_ed25519_init failed");
+        else if (wc_ed25519_make_key(rng, ED25519_KEY_SIZE, &key)!=MP_OKAY)
+            WOLFSSL_MSG("wc_ed25519_make_key failed");
+        /* export private key */
+        else if (wc_ed25519_export_key(&key, priv, privSz, pub, pubSz)!=MP_OKAY)
+            WOLFSSL_MSG("wc_ed25519_export_key failed");
+        else
+            ret = WOLFSSL_SUCCESS;
+
+        wc_ed25519_free(&key);
+    }
+
+    if (initTmpRng)
+        wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+    return ret;
+#endif /* WOLFSSL_KEY_GEN */
+}
+
+/* return 1 if success, 0 if error
+ * input and output keys are little endian format
+ * priv is a buffer containing private and public part of key
+ */
+int wolfSSL_ED25519_sign(const unsigned char *msg, unsigned int msgSz,
+                         const unsigned char *priv, unsigned int privSz,
+                         unsigned char *sig, unsigned int *sigSz)
+{
+#ifndef WOLFSSL_KEY_GEN
+    WOLFSSL_MSG("No Key Gen built in");
+    (void) msg;
+    (void) msgSz;
+    (void) priv;
+    (void) privSz;
+    (void) sig;
+    (void) sigSz;
+    return WOLFSSL_FAILURE;
+#else /* WOLFSSL_KEY_GEN */
+    ed25519_key key;
+    int ret = WOLFSSL_FAILURE;
+
+    WOLFSSL_ENTER("wolfSSL_ED25519_sign");
+
+    if (priv == NULL || privSz != ED25519_PRV_KEY_SIZE ||
+        msg == NULL || sig == NULL || *sigSz < ED25519_SIG_SIZE) {
+        WOLFSSL_MSG("Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* import key */
+    if (wc_ed25519_init(&key) != MP_OKAY) {
+        WOLFSSL_MSG("wc_curve25519_init failed");
+        return ret;
+    }
+    if (wc_ed25519_import_private_key(priv, privSz/2,
+                                      priv+(privSz/2), ED25519_PUB_KEY_SIZE,
+                                      &key) != MP_OKAY){
+        WOLFSSL_MSG("wc_ed25519_import_private failed");
+        wc_ed25519_free(&key);
+        return ret;
+    }
+
+    if (wc_ed25519_sign_msg(msg, msgSz, sig, sigSz, &key) != MP_OKAY)
+        WOLFSSL_MSG("wc_curve25519_shared_secret_ex failed");
+    else
+        ret = WOLFSSL_SUCCESS;
+
+    wc_ed25519_free(&key);
+
+    return ret;
+#endif /* WOLFSSL_KEY_GEN */
+}
+
+/* return 1 if success, 0 if error
+ * input and output keys are little endian format
+ * pub is a buffer containing public part of key
+ */
+int wolfSSL_ED25519_verify(const unsigned char *msg, unsigned int msgSz,
+                           const unsigned char *pub, unsigned int pubSz,
+                           const unsigned char *sig, unsigned int sigSz)
+{
+#ifndef WOLFSSL_KEY_GEN
+    WOLFSSL_MSG("No Key Gen built in");
+    (void) msg;
+    (void) msgSz;
+    (void) pub;
+    (void) pubSz;
+    (void) sig;
+    (void) sigSz;
+    return WOLFSSL_FAILURE;
+#else /* WOLFSSL_KEY_GEN */
+    ed25519_key key;
+    int ret = WOLFSSL_FAILURE, check = 0;
+
+    WOLFSSL_ENTER("wolfSSL_ED25519_verify");
+
+    if (pub == NULL || pubSz != ED25519_PUB_KEY_SIZE ||
+        msg == NULL || sig == NULL || sigSz != ED25519_SIG_SIZE) {
+        WOLFSSL_MSG("Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* import key */
+    if (wc_ed25519_init(&key) != MP_OKAY) {
+        WOLFSSL_MSG("wc_curve25519_init failed");
+        return ret;
+    }
+    if (wc_ed25519_import_public(pub, pubSz, &key) != MP_OKAY){
+        WOLFSSL_MSG("wc_ed25519_import_public failed");
+        wc_ed25519_free(&key);
+        return ret;
+    }
+
+    if ((ret = wc_ed25519_verify_msg((byte*)sig, sigSz, msg, msgSz,
+                                     &check, &key)) != MP_OKAY) {
+        WOLFSSL_MSG("wc_ed25519_verify_msg failed");
+    }
+    else if (!check)
+        WOLFSSL_MSG("wc_ed25519_verify_msg failed (signature invalid)");
+    else
+        ret = WOLFSSL_SUCCESS;
+
+    wc_ed25519_free(&key);
+
+    return ret;
+#endif /* WOLFSSL_KEY_GEN */
+}
+
+#endif /* OPENSSL_EXTRA && HAVE_ED25519 */
+
+#if defined(OPENSSL_EXTRA) && defined(HAVE_CURVE448)
+/* return 1 if success, 0 if error
+ * output keys are little endian format
+ */
+int wolfSSL_EC448_generate_key(unsigned char *priv, unsigned int *privSz,
+                               unsigned char *pub, unsigned int *pubSz)
+{
+#ifndef WOLFSSL_KEY_GEN
+    WOLFSSL_MSG("No Key Gen built in");
+    (void) priv;
+    (void) privSz;
+    (void) pub;
+    (void) pubSz;
+    return WOLFSSL_FAILURE;
+#else /* WOLFSSL_KEY_GEN */
+    int ret = WOLFSSL_FAILURE;
+    int initTmpRng = 0;
+    WC_RNG *rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG *tmpRNG = NULL;
+#else
+    WC_RNG tmpRNG[1];
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_EC448_generate_key");
+
+    if (priv == NULL || privSz == NULL || *privSz < CURVE448_KEY_SIZE ||
+        pub == NULL || pubSz == NULL || *pubSz < CURVE448_KEY_SIZE) {
+        WOLFSSL_MSG("Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+    if (tmpRNG == NULL)
+        return WOLFSSL_FAILURE;
+#endif
+    if (wc_InitRng(tmpRNG) == 0) {
+        rng = tmpRNG;
+        initTmpRng = 1;
+    }
+    else {
+        WOLFSSL_MSG("Bad RNG Init, trying global");
+        if (initGlobalRNG == 0)
+            WOLFSSL_MSG("Global RNG no Init");
+        else
+            rng = &globalRNG;
+    }
+
+    if (rng) {
+        curve448_key key;
+
+        if (wc_curve448_init(&key) != MP_OKAY)
+            WOLFSSL_MSG("wc_curve448_init failed");
+        else if (wc_curve448_make_key(rng, CURVE448_KEY_SIZE, &key)!=MP_OKAY)
+            WOLFSSL_MSG("wc_curve448_make_key failed");
+        /* export key pair */
+        else if (wc_curve448_export_key_raw_ex(&key, priv, privSz, pub, pubSz,
+                                               EC448_LITTLE_ENDIAN)
+                 != MP_OKAY)
+            WOLFSSL_MSG("wc_curve448_export_key_raw_ex failed");
+        else
+            ret = WOLFSSL_SUCCESS;
+
+        wc_curve448_free(&key);
+    }
+
+    if (initTmpRng)
+        wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+    return ret;
+#endif /* WOLFSSL_KEY_GEN */
+}
+
+/* return 1 if success, 0 if error
+ * input and output keys are little endian format
+ */
+int wolfSSL_EC448_shared_key(unsigned char *shared, unsigned int *sharedSz,
+                             const unsigned char *priv, unsigned int privSz,
+                             const unsigned char *pub, unsigned int pubSz)
+{
+#ifndef WOLFSSL_KEY_GEN
+    WOLFSSL_MSG("No Key Gen built in");
+    (void) shared;
+    (void) sharedSz;
+    (void) priv;
+    (void) privSz;
+    (void) pub;
+    (void) pubSz;
+    return WOLFSSL_FAILURE;
+#else /* WOLFSSL_KEY_GEN */
+    int ret = WOLFSSL_FAILURE;
+    curve448_key privkey, pubkey;
+
+    WOLFSSL_ENTER("wolfSSL_EC448_shared_key");
+
+    if (shared == NULL || sharedSz == NULL || *sharedSz < CURVE448_KEY_SIZE ||
+            priv == NULL || privSz < CURVE448_KEY_SIZE ||
+            pub == NULL || pubSz < CURVE448_KEY_SIZE) {
+        WOLFSSL_MSG("Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* import private key */
+    if (wc_curve448_init(&privkey) != MP_OKAY) {
+        WOLFSSL_MSG("wc_curve448_init privkey failed");
+        return ret;
+    }
+    if (wc_curve448_import_private_ex(priv, privSz, &privkey,
+                                      EC448_LITTLE_ENDIAN) != MP_OKAY) {
+        WOLFSSL_MSG("wc_curve448_import_private_ex failed");
+        wc_curve448_free(&privkey);
+        return ret;
+    }
+
+    /* import public key */
+    if (wc_curve448_init(&pubkey) != MP_OKAY) {
+        WOLFSSL_MSG("wc_curve448_init pubkey failed");
+        wc_curve448_free(&privkey);
+        return ret;
+    }
+    if (wc_curve448_import_public_ex(pub, pubSz, &pubkey,
+                                     EC448_LITTLE_ENDIAN) != MP_OKAY) {
+        WOLFSSL_MSG("wc_curve448_import_public_ex failed");
+        wc_curve448_free(&privkey);
+        wc_curve448_free(&pubkey);
+        return ret;
+    }
+
+    if (wc_curve448_shared_secret_ex(&privkey, &pubkey, shared, sharedSz,
+                                     EC448_LITTLE_ENDIAN) != MP_OKAY)
+        WOLFSSL_MSG("wc_curve448_shared_secret_ex failed");
+    else
+        ret = WOLFSSL_SUCCESS;
+
+    wc_curve448_free(&privkey);
+    wc_curve448_free(&pubkey);
+
+    return ret;
+#endif /* WOLFSSL_KEY_GEN */
+}
+#endif /* OPENSSL_EXTRA && HAVE_CURVE448 */
+
+#if defined(OPENSSL_EXTRA) && defined(HAVE_ED448)
+/* return 1 if success, 0 if error
+ * output keys are little endian format
+ */
+int wolfSSL_ED448_generate_key(unsigned char *priv, unsigned int *privSz,
+                               unsigned char *pub, unsigned int *pubSz)
+{
+#ifndef WOLFSSL_KEY_GEN
+    WOLFSSL_MSG("No Key Gen built in");
+    (void) priv;
+    (void) privSz;
+    (void) pub;
+    (void) pubSz;
+    return WOLFSSL_FAILURE;
+#else /* WOLFSSL_KEY_GEN */
+    int ret = WOLFSSL_FAILURE;
+    int initTmpRng = 0;
+    WC_RNG *rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG *tmpRNG = NULL;
+#else
+    WC_RNG tmpRNG[1];
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_ED448_generate_key");
+
+    if (priv == NULL || privSz == NULL || *privSz < ED448_PRV_KEY_SIZE ||
+            pub == NULL || pubSz == NULL || *pubSz < ED448_PUB_KEY_SIZE) {
+        WOLFSSL_MSG("Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+    if (tmpRNG == NULL)
+        return WOLFSSL_FATAL_ERROR;
+#endif
+    if (wc_InitRng(tmpRNG) == 0) {
+        rng = tmpRNG;
+        initTmpRng = 1;
+    }
+    else {
+        WOLFSSL_MSG("Bad RNG Init, trying global");
+        if (initGlobalRNG == 0)
+            WOLFSSL_MSG("Global RNG no Init");
+        else
+            rng = &globalRNG;
+    }
+
+    if (rng) {
+        ed448_key key;
+
+        if (wc_ed448_init(&key) != MP_OKAY)
+            WOLFSSL_MSG("wc_ed448_init failed");
+        else if (wc_ed448_make_key(rng, ED448_KEY_SIZE, &key) != MP_OKAY)
+            WOLFSSL_MSG("wc_ed448_make_key failed");
+        /* export private key */
+        else if (wc_ed448_export_key(&key, priv, privSz, pub, pubSz) != MP_OKAY)
+            WOLFSSL_MSG("wc_ed448_export_key failed");
+        else
+            ret = WOLFSSL_SUCCESS;
+
+        wc_ed448_free(&key);
+    }
+
+    if (initTmpRng)
+        wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+    return ret;
+#endif /* WOLFSSL_KEY_GEN */
+}
+
+/* return 1 if success, 0 if error
+ * input and output keys are little endian format
+ * priv is a buffer containing private and public part of key
+ */
+int wolfSSL_ED448_sign(const unsigned char *msg, unsigned int msgSz,
+                       const unsigned char *priv, unsigned int privSz,
+                       unsigned char *sig, unsigned int *sigSz)
+{
+#ifndef WOLFSSL_KEY_GEN
+    WOLFSSL_MSG("No Key Gen built in");
+    (void) msg;
+    (void) msgSz;
+    (void) priv;
+    (void) privSz;
+    (void) sig;
+    (void) sigSz;
+    return WOLFSSL_FAILURE;
+#else /* WOLFSSL_KEY_GEN */
+    ed448_key key;
+    int ret = WOLFSSL_FAILURE;
+
+    WOLFSSL_ENTER("wolfSSL_ED448_sign");
+
+    if (priv == NULL || privSz != ED448_PRV_KEY_SIZE || msg == NULL ||
+            sig == NULL || *sigSz < ED448_SIG_SIZE) {
+        WOLFSSL_MSG("Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* import key */
+    if (wc_ed448_init(&key) != MP_OKAY) {
+        WOLFSSL_MSG("wc_curve448_init failed");
+        return ret;
+    }
+    if (wc_ed448_import_private_key(priv, privSz/2, priv+(privSz/2),
+                                    ED448_PUB_KEY_SIZE, &key) != MP_OKAY){
+        WOLFSSL_MSG("wc_ed448_import_private failed");
+        wc_ed448_free(&key);
+        return ret;
+    }
+
+    if (wc_ed448_sign_msg(msg, msgSz, sig, sigSz, &key) != MP_OKAY)
+        WOLFSSL_MSG("wc_curve448_shared_secret_ex failed");
+    else
+        ret = WOLFSSL_SUCCESS;
+
+    wc_ed448_free(&key);
+
+    return ret;
+#endif /* WOLFSSL_KEY_GEN */
+}
+
+/* return 1 if success, 0 if error
+ * input and output keys are little endian format
+ * pub is a buffer containing public part of key
+ */
+int wolfSSL_ED448_verify(const unsigned char *msg, unsigned int msgSz,
+                         const unsigned char *pub, unsigned int pubSz,
+                         const unsigned char *sig, unsigned int sigSz)
+{
+#ifndef WOLFSSL_KEY_GEN
+    WOLFSSL_MSG("No Key Gen built in");
+    (void) msg;
+    (void) msgSz;
+    (void) pub;
+    (void) pubSz;
+    (void) sig;
+    (void) sigSz;
+    return WOLFSSL_FAILURE;
+#else /* WOLFSSL_KEY_GEN */
+    ed448_key key;
+    int ret = WOLFSSL_FAILURE, check = 0;
+
+    WOLFSSL_ENTER("wolfSSL_ED448_verify");
+
+    if (pub == NULL || pubSz != ED448_PUB_KEY_SIZE || msg == NULL ||
+            sig == NULL || sigSz != ED448_SIG_SIZE) {
+        WOLFSSL_MSG("Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* import key */
+    if (wc_ed448_init(&key) != MP_OKAY) {
+        WOLFSSL_MSG("wc_curve448_init failed");
+        return ret;
+    }
+    if (wc_ed448_import_public(pub, pubSz, &key) != MP_OKAY){
+        WOLFSSL_MSG("wc_ed448_import_public failed");
+        wc_ed448_free(&key);
+        return ret;
+    }
+
+    if ((ret = wc_ed448_verify_msg((byte*)sig, sigSz, msg, msgSz, &check,
+                                   &key)) != MP_OKAY) {
+        WOLFSSL_MSG("wc_ed448_verify_msg failed");
+    }
+    else if (!check)
+        WOLFSSL_MSG("wc_ed448_verify_msg failed (signature invalid)");
+    else
+        ret = WOLFSSL_SUCCESS;
+
+    wc_ed448_free(&key);
+
+    return ret;
+#endif /* WOLFSSL_KEY_GEN */
+}
+
+#endif /* OPENSSL_EXTRA && HAVE_ED448 */
+
+#ifdef WOLFSSL_JNI
+
+int wolfSSL_set_jobject(WOLFSSL* ssl, void* objPtr)
+{
+    WOLFSSL_ENTER("wolfSSL_set_jobject");
+    if (ssl != NULL)
+    {
+        ssl->jObjectRef = objPtr;
+        return WOLFSSL_SUCCESS;
+    }
+    return WOLFSSL_FAILURE;
+}
+
+void* wolfSSL_get_jobject(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_get_jobject");
+    if (ssl != NULL)
+        return ssl->jObjectRef;
+    return NULL;
+}
+
+#endif /* WOLFSSL_JNI */
+
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+int wolfSSL_CTX_AsyncPoll(WOLFSSL_CTX* ctx, WOLF_EVENT** events, int maxEvents,
+    WOLF_EVENT_FLAG flags, int* eventCount)
+{
+    if (ctx == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    return wolfAsync_EventQueuePoll(&ctx->event_queue, NULL,
+                                        events, maxEvents, flags, eventCount);
+}
+
+int wolfSSL_AsyncPoll(WOLFSSL* ssl, WOLF_EVENT_FLAG flags)
+{
+    int ret, eventCount = 0;
+    WOLF_EVENT* events[1];
+
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    ret = wolfAsync_EventQueuePoll(&ssl->ctx->event_queue, ssl,
+        events, sizeof(events)/sizeof(*events), flags, &eventCount);
+    if (ret == 0) {
+        ret = eventCount;
+    }
+
+    return ret;
+}
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+#ifdef OPENSSL_EXTRA
+unsigned long wolfSSL_ERR_peek_error_line_data(const char **file, int *line,
+                                               const char **data, int *flags)
+{
+    WOLFSSL_ENTER("wolfSSL_ERR_peek_error_line_data");
+
+    (void)line;
+    (void)file;
+
+    /* No data or flags stored - error display only in Nginx. */
+    if (data != NULL) {
+        *data = "";
+    }
+    if (flags != NULL) {
+        *flags = 0;
+    }
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \
+    defined(WOLFSSL_OPENSSH) || defined(WOLFSSL_HAPROXY) || \
+    defined(WOLFSSL_MYSQL_COMPATIBLE)
+    {
+        int ret = 0;
+
+        while (1) {
+            if ((ret = wc_PeekErrorNode(-1, file, NULL, line)) < 0) {
+                WOLFSSL_MSG("Issue peeking at error node in queue");
+                return 0;
+            }
+            /* OpenSSL uses positive error codes */
+            if (ret < 0) {
+                ret = -ret;
+            }
+
+            if (ret == -ASN_NO_PEM_HEADER)
+                return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE;
+            if (ret != WANT_READ && ret != WANT_WRITE &&
+                    ret != ZERO_RETURN && ret != WOLFSSL_ERROR_ZERO_RETURN &&
+                    ret != SOCKET_PEER_CLOSED_E && ret != SOCKET_ERROR_E)
+                break;
+
+            wc_RemoveErrorNode(-1);
+        }
+
+        return (unsigned long)ret;
+    }
+#else
+    return (unsigned long)(0 - NOT_COMPILED_IN);
+#endif
+}
+#endif
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+
+/* returns a pointer to internal cipher suite list. Should not be free'd by
+ * caller.
+ */
+WOLF_STACK_OF(WOLFSSL_CIPHER) *wolfSSL_get_ciphers_compat(const WOLFSSL *ssl)
+{
+    WOLF_STACK_OF(WOLFSSL_CIPHER)* ret = NULL;
+    Suites* suites;
+
+    WOLFSSL_ENTER("wolfSSL_get_ciphers_compat");
+    if (ssl == NULL || (ssl->suites == NULL && ssl->ctx->suites == NULL)) {
+        return NULL;
+    }
+
+    if (ssl->suites != NULL) {
+        suites = ssl->suites;
+    }
+    else {
+        suites = ssl->ctx->suites;
+    }
+
+    /* check if stack needs populated */
+    if (suites->stack == NULL) {
+        int i;
+        for (i = 0; i < suites->suiteSz; i+=2) {
+            WOLFSSL_STACK* add = wolfSSL_sk_new_node(ssl->heap);
+            if (add != NULL) {
+                add->type = STACK_TYPE_CIPHER;
+                add->data.cipher.cipherSuite0 = suites->suites[i];
+                add->data.cipher.cipherSuite  = suites->suites[i+1];
+                #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+                /* in_stack is checked in wolfSSL_CIPHER_description */
+                add->data.cipher.in_stack = 1;
+                #endif
+
+                add->next = ret;
+                if (ret != NULL) {
+                    add->num = ret->num + 1;
+                }
+                else {
+                    add->num = 1;
+                }
+                ret = add;
+            }
+        }
+        suites->stack = ret;
+    }
+    return suites->stack;
+}
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_OPENSSL_config(char *config_name)
+{
+    (void)config_name;
+    WOLFSSL_STUB("OPENSSL_config");
+}
+#endif /* !NO_WOLFSSL_STUB */
+#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \
+    || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY)
+int wolfSSL_X509_get_ex_new_index(int idx, void *arg, void *a, void *b, void *c)
+{
+    static int x509_idx = 0;
+
+    WOLFSSL_ENTER("wolfSSL_X509_get_ex_new_index");
+    (void)idx;
+    (void)arg;
+    (void)a;
+    (void)b;
+    (void)c;
+
+    return x509_idx++;
+}
+
+#if defined(HAVE_EX_DATA) || defined(FORTRESS)
+void* wolfSSL_CRYPTO_get_ex_data(const WOLFSSL_CRYPTO_EX_DATA* ex_data, int idx)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_get_ex_data");
+#ifdef MAX_EX_DATA
+    if(ex_data && idx < MAX_EX_DATA && idx >= 0) {
+        return ex_data->ex_data[idx];
+    }
+#else
+    (void)ex_data;
+    (void)idx;
+#endif
+    return NULL;
+}
+
+int wolfSSL_CRYPTO_set_ex_data(WOLFSSL_CRYPTO_EX_DATA* ex_data, int idx, void *data)
+{
+    WOLFSSL_ENTER("wolfSSL_CRYPTO_set_ex_data");
+#ifdef MAX_EX_DATA
+    if (ex_data && idx < MAX_EX_DATA && idx >= 0) {
+        ex_data->ex_data[idx] = data;
+        return WOLFSSL_SUCCESS;
+    }
+#else
+    (void)ex_data;
+    (void)idx;
+    (void)data;
+#endif
+    return WOLFSSL_FAILURE;
+}
+#endif /* defined(HAVE_EX_DATA) || defined(FORTRESS) */
+
+void *wolfSSL_X509_get_ex_data(X509 *x509, int idx)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_get_ex_data");
+    #ifdef HAVE_EX_DATA
+    if (x509 != NULL) {
+        return wolfSSL_CRYPTO_get_ex_data(&x509->ex_data, idx);
+    }
+    #else
+    (void)x509;
+    (void)idx;
+    #endif
+    return NULL;
+}
+
+int wolfSSL_X509_set_ex_data(X509 *x509, int idx, void *data)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_set_ex_data");
+    #ifdef HAVE_EX_DATA
+    if (x509 != NULL)
+    {
+        return wolfSSL_CRYPTO_set_ex_data(&x509->ex_data, idx, data);
+    }
+    #else
+    (void)x509;
+    (void)idx;
+    (void)data;
+    #endif
+    return WOLFSSL_FAILURE;
+}
+
+int wolfSSL_X509_NAME_digest(const WOLFSSL_X509_NAME *name,
+        const WOLFSSL_EVP_MD *type, unsigned char *md, unsigned int *len)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_NAME_digest");
+
+    if (name == NULL || type == NULL)
+        return WOLFSSL_FAILURE;
+
+#if !defined(NO_FILESYSTEM) && !defined(NO_PWDBASED)
+    return wolfSSL_EVP_Digest((unsigned char*)name->fullName.fullName,
+                              name->fullName.fullNameLen, md, len, type, NULL);
+#else
+    (void)md;
+    (void)len;
+    return NOT_COMPILED_IN;
+#endif
+}
+
+long wolfSSL_SSL_CTX_get_timeout(const WOLFSSL_CTX *ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_SSL_CTX_get_timeout");
+
+    if (ctx == NULL)
+        return 0;
+
+    return ctx->timeout;
+}
+
+
+/* returns the time in seconds of the current timeout */
+long wolfSSL_get_timeout(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_get_timeout");
+
+    if (ssl == NULL)
+        return 0;
+    return ssl->timeout;
+}
+
+#ifdef HAVE_ECC
+int wolfSSL_SSL_CTX_set_tmp_ecdh(WOLFSSL_CTX *ctx, WOLFSSL_EC_KEY *ecdh)
+{
+    WOLFSSL_ENTER("wolfSSL_SSL_CTX_set_tmp_ecdh");
+
+    if (ctx == NULL || ecdh == NULL)
+        return BAD_FUNC_ARG;
+
+    ctx->ecdhCurveOID = ecdh->group->curve_oid;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif
+
+/* Assumes that the session passed in is from the cache. */
+int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *ctx, WOLFSSL_SESSION *s)
+{
+    WOLFSSL_ENTER("wolfSSL_SSL_CTX_remove_session");
+
+    if (ctx == NULL || s == NULL)
+        return BAD_FUNC_ARG;
+
+#ifdef HAVE_EXT_CACHE
+    if (!ctx->internalCacheOff)
+#endif
+    {
+        /* Don't remove session just timeout session. */
+        s->timeout = 0;
+    }
+
+#ifdef HAVE_EXT_CACHE
+    if (ctx->rem_sess_cb != NULL)
+        ctx->rem_sess_cb(ctx, s);
+#endif
+
+    return 0;
+}
+
+BIO *wolfSSL_SSL_get_rbio(const WOLFSSL *s)
+{
+    WOLFSSL_ENTER("wolfSSL_SSL_get_rbio");
+    /* Nginx sets the buffer size if the read BIO is different to write BIO.
+     * The setting buffer size doesn't do anything so return NULL for both.
+     */
+    if (s == NULL)
+        return NULL;
+
+    return s->biord;
+}
+BIO *wolfSSL_SSL_get_wbio(const WOLFSSL *s)
+{
+    WOLFSSL_ENTER("wolfSSL_SSL_get_wbio");
+    (void)s;
+    /* Nginx sets the buffer size if the read BIO is different to write BIO.
+     * The setting buffer size doesn't do anything so return NULL for both.
+     */
+    if (s == NULL)
+        return NULL;
+
+    return s->biowr;
+}
+
+int wolfSSL_SSL_do_handshake(WOLFSSL *s)
+{
+    WOLFSSL_ENTER("wolfSSL_SSL_do_handshake");
+
+    if (s == NULL)
+        return WOLFSSL_FAILURE;
+
+    if (s->options.side == WOLFSSL_CLIENT_END) {
+    #ifndef NO_WOLFSSL_CLIENT
+        return wolfSSL_connect(s);
+    #else
+        WOLFSSL_MSG("Client not compiled in");
+        return WOLFSSL_FAILURE;
+    #endif
+    }
+
+#ifndef NO_WOLFSSL_SERVER
+    return wolfSSL_accept(s);
+#else
+    WOLFSSL_MSG("Server not compiled in");
+    return WOLFSSL_FAILURE;
+#endif
+}
+
+int wolfSSL_SSL_in_init(WOLFSSL *ssl)
+{
+    WOLFSSL_ENTER("SSL_in_init");
+
+    if (ssl == NULL)
+        return WOLFSSL_FAILURE;
+
+    if (ssl->options.side == WOLFSSL_CLIENT_END) {
+        return ssl->options.connectState < SECOND_REPLY_DONE;
+    }
+    return ssl->options.acceptState < ACCEPT_THIRD_REPLY_DONE;
+}
+
+int wolfSSL_SSL_in_connect_init(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("SSL_connect_init");
+
+    if (ssl == NULL)
+        return WOLFSSL_FAILURE;
+
+    if (ssl->options.side == WOLFSSL_CLIENT_END) {
+        return ssl->options.connectState > CONNECT_BEGIN &&
+            ssl->options.connectState < SECOND_REPLY_DONE;
+    }
+
+    return ssl->options.acceptState > ACCEPT_BEGIN &&
+        ssl->options.acceptState < ACCEPT_THIRD_REPLY_DONE;
+}
+
+#ifndef NO_SESSION_CACHE
+
+WOLFSSL_SESSION *wolfSSL_SSL_get0_session(const WOLFSSL *ssl)
+{
+    WOLFSSL_SESSION *session;
+
+    WOLFSSL_ENTER("wolfSSL_SSL_get0_session");
+
+    if (ssl == NULL) {
+        return NULL;
+    }
+
+    session = wolfSSL_get_session((WOLFSSL*)ssl);
+
+#ifdef HAVE_EXT_CACHE
+    ((WOLFSSL*)ssl)->extSession = session;
+#endif
+
+    return session;
+}
+
+#endif /* NO_SESSION_CACHE */
+
+int wolfSSL_X509_check_host(X509 *x, const char *chk, size_t chklen,
+                    unsigned int flags, char **peername)
+{
+    int         ret;
+    DecodedCert dCert;
+
+    WOLFSSL_ENTER("wolfSSL_X509_check_host");
+
+    /* flags and peername not needed for Nginx. */
+    (void)flags;
+    (void)peername;
+
+    if (flags == WOLFSSL_NO_WILDCARDS) {
+        WOLFSSL_MSG("X509_CHECK_FLAG_NO_WILDCARDS not yet implemented");
+        return WOLFSSL_FAILURE;
+    }
+
+    InitDecodedCert(&dCert, x->derCert->buffer, x->derCert->length, NULL);
+    ret = ParseCertRelative(&dCert, CERT_TYPE, 0, NULL);
+    if (ret != 0) {
+        FreeDecodedCert(&dCert);
+        return WOLFSSL_FAILURE;
+    }
+
+    ret = CheckHostName(&dCert, (char *)chk, chklen);
+    FreeDecodedCert(&dCert);
+    if (ret != 0)
+        return WOLFSSL_FAILURE;
+    return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_i2a_ASN1_INTEGER(BIO *bp, const WOLFSSL_ASN1_INTEGER *a)
+{
+    static char num[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
+                            '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+    int    i;
+    word32 j;
+    word32 len = 0;
+
+    WOLFSSL_ENTER("wolfSSL_i2a_ASN1_INTEGER");
+
+    if (bp == NULL || a == NULL)
+        return WOLFSSL_FAILURE;
+
+    /* Skip ASN.1 INTEGER (type) byte. */
+    i = 1;
+    /* When indefinite length, can't determine length with data available. */
+    if (a->data[i] == 0x80)
+        return 0;
+    /* One length byte if less than 0x80. */
+    if (a->data[i] < 0x80)
+        len = a->data[i++];
+    /* Multiple length byte if greater than 0x80. */
+    else if (a->data[i] > 0x80) {
+        switch (a->data[i++] - 0x80) {
+            case 4:
+                len |= a->data[i++] << 24;
+                FALL_THROUGH;
+            case 3:
+                len |= a->data[i++] << 16;
+                FALL_THROUGH;
+            case 2:
+                len |= a->data[i++] <<  8;
+                FALL_THROUGH;
+            case 1:
+                len |= a->data[i++];
+                break;
+            default:
+                /* Not supporting greater than 4 bytes of length. */
+                return 0;
+        }
+    }
+
+    /* Zero length integer is the value zero. */
+    if (len == 0) {
+        wolfSSL_BIO_write(bp, "00", 2);
+        return 2;
+    }
+
+    /* Don't do negative - just write out every byte. */
+    for (j = 0; j < len; i++,j++) {
+        wolfSSL_BIO_write(bp, &num[a->data[i] >> 4], 1);
+        wolfSSL_BIO_write(bp, &num[a->data[i] & 0xf], 1);
+    }
+
+    /* Two nibbles written for each byte. */
+    return len * 2;
+}
+
+
+#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER)
+/* Expected return values from implementations of OpenSSL ticket key callback.
+ */
+#define TICKET_KEY_CB_RET_FAILURE    -1
+#define TICKET_KEY_CB_RET_NOT_FOUND   0
+#define TICKET_KEY_CB_RET_OK          1
+#define TICKET_KEY_CB_RET_RENEW       2
+
+/* The ticket key callback as used in OpenSSL is stored here. */
+static int (*ticketKeyCb)(WOLFSSL *ssl, unsigned char *name, unsigned char *iv,
+    WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc) = NULL;
+
+/* Implementation of session ticket encryption/decryption using OpenSSL
+ * callback to initialize the cipher and HMAC.
+ *
+ * ssl           The SSL/TLS object.
+ * keyName       The key name - used to identify the key to be used.
+ * iv            The IV to use.
+ * mac           The MAC of the encrypted data.
+ * enc           Encrypt ticket.
+ * encTicket     The ticket data.
+ * encTicketLen  The length of the ticket data.
+ * encLen        The encrypted/decrypted ticket length - output length.
+ * ctx           Ignored. Application specific data.
+ * returns WOLFSSL_TICKET_RET_OK to indicate success,
+ *         WOLFSSL_TICKET_RET_CREATE if a new ticket is required and
+ *         WOLFSSL_TICKET_RET_FATAL on error.
+ */
+static int wolfSSL_TicketKeyCb(WOLFSSL* ssl,
+                                  unsigned char keyName[WOLFSSL_TICKET_NAME_SZ],
+                                  unsigned char iv[WOLFSSL_TICKET_IV_SZ],
+                                  unsigned char mac[WOLFSSL_TICKET_MAC_SZ],
+                                  int enc, unsigned char* encTicket,
+                                  int encTicketLen, int* encLen, void* ctx)
+{
+    byte                    digest[WC_MAX_DIGEST_SIZE];
+    WOLFSSL_EVP_CIPHER_CTX  evpCtx;
+    WOLFSSL_HMAC_CTX        hmacCtx;
+    unsigned int            mdSz = 0;
+    int                     len = 0;
+    int                     ret = WOLFSSL_TICKET_RET_FATAL;
+    int                     res;
+
+    (void)ctx;
+
+    if (ticketKeyCb == NULL)
+        return WOLFSSL_TICKET_RET_FATAL;
+
+    wolfSSL_EVP_CIPHER_CTX_init(&evpCtx);
+    /* Initialize the cipher and HMAC. */
+    res = ticketKeyCb(ssl, keyName, iv, &evpCtx, &hmacCtx, enc);
+    if (res != TICKET_KEY_CB_RET_OK && res != TICKET_KEY_CB_RET_RENEW)
+        return WOLFSSL_TICKET_RET_FATAL;
+
+    if (enc)
+    {
+        /* Encrypt in place. */
+        if (!wolfSSL_EVP_CipherUpdate(&evpCtx, encTicket, &len,
+                                      encTicket, encTicketLen))
+            goto end;
+        encTicketLen = len;
+        if (!wolfSSL_EVP_EncryptFinal(&evpCtx, &encTicket[encTicketLen], &len))
+            goto end;
+        /* Total length of encrypted data. */
+        encTicketLen += len;
+        *encLen = encTicketLen;
+
+        /* HMAC the encrypted data into the parameter 'mac'. */
+        if (!wolfSSL_HMAC_Update(&hmacCtx, encTicket, encTicketLen))
+            goto end;
+#ifdef WOLFSSL_SHA512
+        /* Check for SHA512, which would overrun the mac buffer */
+        if (hmacCtx.hmac.macType == WC_SHA512)
+            goto end;
+#endif
+        if (!wolfSSL_HMAC_Final(&hmacCtx, mac, &mdSz))
+            goto end;
+    }
+    else
+    {
+        /* HMAC the encrypted data and compare it to the passed in data. */
+        if (!wolfSSL_HMAC_Update(&hmacCtx, encTicket, encTicketLen))
+            goto end;
+        if (!wolfSSL_HMAC_Final(&hmacCtx, digest, &mdSz))
+            goto end;
+        if (XMEMCMP(mac, digest, mdSz) != 0)
+            goto end;
+
+        /* Decrypt the ticket data in place. */
+        if (!wolfSSL_EVP_CipherUpdate(&evpCtx, encTicket, &len,
+                                      encTicket, encTicketLen))
+            goto end;
+        encTicketLen = len;
+        if (!wolfSSL_EVP_DecryptFinal(&evpCtx, &encTicket[encTicketLen], &len))
+            goto end;
+        /* Total length of decrypted data. */
+        *encLen = encTicketLen + len;
+    }
+
+    ret = (res == TICKET_KEY_CB_RET_RENEW) ? WOLFSSL_TICKET_RET_CREATE :
+                                             WOLFSSL_TICKET_RET_OK;
+end:
+    return ret;
+}
+
+/* Set the callback to use when encrypting/decrypting tickets.
+ *
+ * ctx  The SSL/TLS context object.
+ * cb   The OpenSSL session ticket callback.
+ * returns WOLFSSL_SUCCESS to indicate success.
+ */
+int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *ctx, int (*cb)(
+    WOLFSSL *ssl, unsigned char *name, unsigned char *iv,
+    WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc))
+{
+    /* Store callback in a global. */
+    ticketKeyCb = cb;
+    /* Set the ticket encryption callback to be a wrapper around OpenSSL
+     * callback.
+     */
+    ctx->ticketEncCb = wolfSSL_TicketKeyCb;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* HAVE_SESSION_TICKET */
+
+#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY ||
+    OPENSSL_EXTRA || HAVE_LIGHTY */
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+#ifdef HAVE_OCSP
+/* Not an OpenSSL API. */
+int wolfSSL_get_ocsp_response(WOLFSSL* ssl, byte** response)
+{
+    *response = ssl->ocspResp;
+    return ssl->ocspRespSz;
+}
+
+/* Not an OpenSSL API. */
+char* wolfSSL_get_ocsp_url(WOLFSSL* ssl)
+{
+    return ssl->url;
+}
+
+/* Not an OpenSSL API. */
+int wolfSSL_set_ocsp_url(WOLFSSL* ssl, char* url)
+{
+    if (ssl == NULL)
+        return WOLFSSL_FAILURE;
+
+    ssl->url = url;
+    return WOLFSSL_SUCCESS;
+}
+#endif /* OCSP */
+#endif /* OPENSSL_ALL / WOLFSSL_NGINX  / WOLFSSL_HAPROXY */
+
+#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
+    defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
+int wolfSSL_CTX_get_extra_chain_certs(WOLFSSL_CTX* ctx, WOLF_STACK_OF(X509)** chain)
+{
+    word32         idx;
+    word32         length;
+    WOLFSSL_STACK* node;
+    WOLFSSL_STACK* last = NULL;
+
+    if (ctx == NULL || chain == NULL) {
+        chain = NULL;
+        return WOLFSSL_FAILURE;
+    }
+    if (ctx->x509Chain != NULL) {
+        *chain = ctx->x509Chain;
+        return WOLFSSL_SUCCESS;
+    }
+
+    /* If there are no chains then success! */
+    *chain = NULL;
+    if (ctx->certChain == NULL || ctx->certChain->length == 0) {
+        return WOLFSSL_SUCCESS;
+    }
+
+    /* Create a new stack of WOLFSSL_X509 object from chain buffer. */
+    for (idx = 0; idx < ctx->certChain->length; ) {
+        node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+                                       DYNAMIC_TYPE_OPENSSL);
+        if (node == NULL)
+            return WOLFSSL_FAILURE;
+        node->next = NULL;
+
+        /* 3 byte length | X509 DER data */
+        ato24(ctx->certChain->buffer + idx, &length);
+        idx += 3;
+
+        /* Create a new X509 from DER encoded data. */
+        node->data.x509 = wolfSSL_X509_d2i(NULL, ctx->certChain->buffer + idx,
+            length);
+        if (node->data.x509 == NULL) {
+            XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL);
+            /* Return as much of the chain as we created. */
+            ctx->x509Chain = *chain;
+            return WOLFSSL_FAILURE;
+        }
+        idx += length;
+
+        /* Add object to the end of the stack. */
+        if (last == NULL) {
+            node->num = 1;
+            *chain = node;
+        }
+        else {
+            (*chain)->num++;
+            last->next = node;
+        }
+
+        last = node;
+    }
+
+    ctx->x509Chain = *chain;
+
+    return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx,
+    int(*cb)(WOLFSSL*, void*))
+{
+    if (ctx == NULL || ctx->cm == NULL)
+        return WOLFSSL_FAILURE;
+
+#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+                               ||  defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
+    /* Ensure stapling is on for callback to be used. */
+    wolfSSL_CTX_EnableOCSPStapling(ctx);
+
+    if (ctx->cm->ocsp_stapling == NULL)
+        return WOLFSSL_FAILURE;
+
+    ctx->cm->ocsp_stapling->statusCb = cb;
+#else
+    (void)cb;
+#endif
+
+    return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer,
+    WOLFSSL_X509_STORE_CTX *ctx, WOLFSSL_X509 *x)
+{
+    WOLFSSL_STACK* node;
+    Signer* ca = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    DecodedCert* cert = NULL;
+#else
+    DecodedCert  cert[1];
+#endif
+
+    if (issuer == NULL || ctx == NULL || x == NULL)
+        return WOLFSSL_FATAL_ERROR;
+
+    if (ctx->chain != NULL) {
+        for (node = ctx->chain; node != NULL; node = node->next) {
+            if (wolfSSL_X509_check_issued(node->data.x509, x) == X509_V_OK) {
+                *issuer = x;
+                return WOLFSSL_SUCCESS;
+            }
+        }
+    }
+
+
+#ifdef WOLFSSL_SMALL_STACK
+    cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
+    if (cert == NULL)
+        return WOLFSSL_FAILURE;
+#endif
+
+    /* Use existing CA retrieval APIs that use DecodedCert. */
+    InitDecodedCert(cert, x->derCert->buffer, x->derCert->length, NULL);
+    if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0) {
+    #ifndef NO_SKID
+        if (cert->extAuthKeyIdSet)
+            ca = GetCA(ctx->store->cm, cert->extAuthKeyId);
+        if (ca == NULL)
+            ca = GetCAByName(ctx->store->cm, cert->issuerHash);
+    #else /* NO_SKID */
+        ca = GetCA(ctx->store->cm, cert->issuerHash);
+    #endif /* NO SKID */
+    }
+    FreeDecodedCert(cert);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
+#endif
+
+    if (ca == NULL)
+        return WOLFSSL_FAILURE;
+
+#ifdef WOLFSSL_SIGNER_DER_CERT
+    /* populate issuer with Signer DER */
+    *issuer = wolfSSL_X509_d2i(issuer, ca->derCert->buffer,
+                               ca->derCert->length);
+    if (*issuer == NULL)
+        return WOLFSSL_FAILURE;
+#else
+    /* Create an empty certificate as CA doesn't have a certificate. */
+    *issuer = (WOLFSSL_X509 *)XMALLOC(sizeof(WOLFSSL_X509), 0,
+        DYNAMIC_TYPE_OPENSSL);
+    if (*issuer == NULL)
+        return WOLFSSL_FAILURE;
+
+    InitX509((*issuer), 1, NULL);
+#endif
+
+    /* Result is ignored when passed to wolfSSL_OCSP_cert_to_id(). */
+
+    return WOLFSSL_SUCCESS;
+}
+
+void wolfSSL_X509_email_free(WOLF_STACK_OF(WOLFSSL_STRING) *sk)
+{
+    WOLFSSL_STACK *curr;
+
+    while (sk != NULL) {
+        curr = sk;
+        sk = sk->next;
+
+        XFREE(curr, NULL, DYNAMIC_TYPE_OPENSSL);
+    }
+}
+
+WOLF_STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ocsp(WOLFSSL_X509 *x)
+{
+    WOLFSSL_STACK* list = NULL;
+    char*          url;
+
+    if (x->authInfoSz == 0)
+        return NULL;
+
+    list = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK) + x->authInfoSz + 1,
+                                   NULL, DYNAMIC_TYPE_OPENSSL);
+    if (list == NULL)
+        return NULL;
+
+    url = (char*)list;
+    url += sizeof(WOLFSSL_STACK);
+    XMEMCPY(url, x->authInfo, x->authInfoSz);
+    url[x->authInfoSz] = '\0';
+
+    list->data.string = url;
+    list->next = NULL;
+
+    return list;
+}
+
+int wolfSSL_X509_check_issued(WOLFSSL_X509 *issuer, WOLFSSL_X509 *subject)
+{
+    WOLFSSL_X509_NAME *issuerName = wolfSSL_X509_get_issuer_name(subject);
+    WOLFSSL_X509_NAME *subjectName = wolfSSL_X509_get_subject_name(issuer);
+
+    if (issuerName == NULL || subjectName == NULL)
+        return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
+
+    /* Literal matching of encoded names and key ids. */
+    if (issuerName->sz != subjectName->sz ||
+           XMEMCMP(issuerName->name, subjectName->name, subjectName->sz) != 0) {
+        return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
+    }
+
+    if (subject->authKeyId != NULL && issuer->subjKeyId != NULL) {
+        if (subject->authKeyIdSz != issuer->subjKeyIdSz ||
+                XMEMCMP(subject->authKeyId, issuer->subjKeyId,
+                        issuer->subjKeyIdSz) != 0) {
+            return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
+        }
+    }
+
+    return X509_V_OK;
+}
+
+WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509 *x)
+{
+    return wolfSSL_X509_d2i(NULL, x->derCert->buffer, x->derCert->length);
+}
+
+char* wolfSSL_sk_WOLFSSL_STRING_value(WOLF_STACK_OF(WOLFSSL_STRING)* strings,
+    int idx)
+{
+    for (; idx > 0 && strings != NULL; idx--)
+        strings = strings->next;
+    if (strings == NULL)
+        return NULL;
+    return strings->data.string;
+}
+#endif /* WOLFSSL_NGINX || WOLFSSL_HAPROXY || OPENSSL_EXTRA || OPENSSL_ALL */
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+#ifdef HAVE_ALPN
+void wolfSSL_get0_alpn_selected(const WOLFSSL *ssl, const unsigned char **data,
+                                unsigned int *len)
+{
+    word16 nameLen;
+
+    if (ssl != NULL && data != NULL && len != NULL) {
+        TLSX_ALPN_GetRequest(ssl->extensions, (void **)data, &nameLen);
+        *len = nameLen;
+    }
+}
+
+int wolfSSL_select_next_proto(unsigned char **out, unsigned char *outLen,
+                              const unsigned char *in, unsigned int inLen,
+                              const unsigned char *clientNames,
+                              unsigned int clientLen)
+{
+    unsigned int i, j;
+    byte lenIn, lenClient;
+
+    if (out == NULL || outLen == NULL || in == NULL || clientNames == NULL)
+        return OPENSSL_NPN_UNSUPPORTED;
+
+    for (i = 0; i < inLen; i += lenIn) {
+        lenIn = in[i++];
+        for (j = 0; j < clientLen; j += lenClient) {
+            lenClient = clientNames[j++];
+
+            if (lenIn != lenClient)
+                continue;
+
+            if (XMEMCMP(in + i, clientNames + j, lenIn) == 0) {
+                *out = (unsigned char *)(in + i);
+                *outLen = lenIn;
+                return OPENSSL_NPN_NEGOTIATED;
+            }
+        }
+    }
+
+    *out = (unsigned char *)clientNames + 1;
+    *outLen = clientNames[0];
+    return OPENSSL_NPN_NO_OVERLAP;
+}
+
+void wolfSSL_CTX_set_alpn_select_cb(WOLFSSL_CTX *ctx,
+                                    int (*cb) (WOLFSSL *ssl,
+                                               const unsigned char **out,
+                                               unsigned char *outlen,
+                                               const unsigned char *in,
+                                               unsigned int inlen,
+                                               void *arg), void *arg)
+{
+    if (ctx != NULL) {
+        ctx->alpnSelect = cb;
+        ctx->alpnSelectArg = arg;
+    }
+}
+
+void wolfSSL_CTX_set_next_protos_advertised_cb(WOLFSSL_CTX *s,
+                                           int (*cb) (WOLFSSL *ssl,
+                                                      const unsigned char
+                                                      **out,
+                                                      unsigned int *outlen,
+                                                      void *arg), void *arg)
+{
+    (void)s;
+    (void)cb;
+    (void)arg;
+    WOLFSSL_STUB("wolfSSL_CTX_set_next_protos_advertised_cb");
+}
+
+void wolfSSL_CTX_set_next_proto_select_cb(WOLFSSL_CTX *s,
+                                      int (*cb) (WOLFSSL *ssl,
+                                                 unsigned char **out,
+                                                 unsigned char *outlen,
+                                                 const unsigned char *in,
+                                                 unsigned int inlen,
+                                                 void *arg), void *arg)
+{
+    (void)s;
+    (void)cb;
+    (void)arg;
+    WOLFSSL_STUB("wolfSSL_CTX_set_next_proto_select_cb");
+}
+
+void wolfSSL_get0_next_proto_negotiated(const WOLFSSL *s, const unsigned char **data,
+                                    unsigned *len)
+{
+    (void)s;
+    (void)data;
+    (void)len;
+    WOLFSSL_STUB("wolfSSL_get0_next_proto_negotiated");
+}
+#endif /* HAVE_ALPN */
+
+#endif /* WOLFSSL_NGINX  / WOLFSSL_HAPROXY */
+
+#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC)
+int wolfSSL_CTX_set1_curves_list(WOLFSSL_CTX* ctx, const char* names)
+{
+    int idx, start = 0, len;
+    word16 curve;
+    char name[MAX_CURVE_NAME_SZ];
+
+    /* Disable all curves so that only the ones the user wants are enabled. */
+    ctx->disabledCurves = 0xFFFFFFFFUL;
+    for (idx = 1; names[idx-1] != '\0'; idx++) {
+        if (names[idx] != ':' && names[idx] != '\0')
+            continue;
+
+        len = idx - 1 - start;
+        if (len > MAX_CURVE_NAME_SZ - 1)
+            return WOLFSSL_FAILURE;
+
+        XMEMCPY(name, names + start, len);
+        name[len] = 0;
+
+        if ((XSTRNCMP(name, "prime256v1", len) == 0) ||
+                                      (XSTRNCMP(name, "secp256r1", len) == 0) ||
+                                      (XSTRNCMP(name, "P-256", len) == 0)) {
+            curve = WOLFSSL_ECC_SECP256R1;
+        }
+        else if ((XSTRNCMP(name, "secp384r1", len) == 0) ||
+                                          (XSTRNCMP(name, "P-384", len) == 0)) {
+            curve = WOLFSSL_ECC_SECP384R1;
+        }
+        else if ((XSTRNCMP(name, "secp521r1", len) == 0) ||
+                                          (XSTRNCMP(name, "P-521", len) == 0)) {
+            curve = WOLFSSL_ECC_SECP521R1;
+        }
+        else if (XSTRNCMP(name, "X25519", len) == 0) {
+            curve = WOLFSSL_ECC_X25519;
+        }
+        else if (XSTRNCMP(name, "X448", len) == 0) {
+            curve = WOLFSSL_ECC_X448;
+        }
+        else {
+        #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
+            int   ret;
+            const ecc_set_type *eccSet;
+
+            ret = wc_ecc_get_curve_idx_from_name(name);
+            if (ret < 0) {
+                WOLFSSL_MSG("Could not find name in set");
+                return WOLFSSL_FAILURE;
+            }
+
+            eccSet = wc_ecc_get_curve_params(ret);
+            if (eccSet == NULL) {
+                WOLFSSL_MSG("NULL set returned");
+                return WOLFSSL_FAILURE;
+            }
+
+            curve = GetCurveByOID(eccSet->oidSum);
+        #else
+            WOLFSSL_MSG("API not present to search farther using name");
+            return WOLFSSL_FAILURE;
+        #endif
+        }
+
+        if (curve > (sizeof(word32) * WOLFSSL_BIT_SIZE)) {
+            /* shift left more than size of ctx->disabledCurves causes static
+             * analysis report */
+            WOLFSSL_MSG("curve value is too large for upcoming shift");
+            return WOLFSSL_FAILURE;
+        }
+
+    #if defined(HAVE_SUPPORTED_CURVES) && !defined(NO_WOLFSSL_CLIENT)
+        /* set the supported curve so client TLS extension contains only the
+         * desired curves */
+        if (wolfSSL_CTX_UseSupportedCurve(ctx, curve) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("Unable to set supported curve");
+            return WOLFSSL_FAILURE;
+        }
+    #endif
+
+        /* Switch the bit to off and therefore is enabled. */
+        ctx->disabledCurves &= ~(1U << curve);
+        start = idx + 1;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_set1_curves_list(WOLFSSL* ssl, const char* names)
+{
+    if (ssl == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+    return wolfSSL_CTX_set1_curves_list(ssl->ctx, names);
+}
+#endif /* OPENSSL_EXTRA && HAVE_ECC */
+
+#ifdef OPENSSL_EXTRA
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_CTX_set_msg_callback(WOLFSSL_CTX *ctx, SSL_Msg_Cb cb)
+{
+    WOLFSSL_STUB("SSL_CTX_set_msg_callback");
+    (void)ctx;
+    (void)cb;
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+
+/* Sets a callback for when sending and receiving protocol messages.
+ *
+ * ssl WOLFSSL structure to set callback in
+ * cb  callback to use
+ *
+ * return SSL_SUCCESS on success and SSL_FAILURE with error case
+ */
+int wolfSSL_set_msg_callback(WOLFSSL *ssl, SSL_Msg_Cb cb)
+{
+    WOLFSSL_ENTER("wolfSSL_set_msg_callback");
+
+    if (ssl == NULL) {
+        return SSL_FAILURE;
+    }
+
+    if (cb != NULL) {
+        ssl->toInfoOn = 1;
+    }
+
+    ssl->protoMsgCb = cb;
+    return SSL_SUCCESS;
+}
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_CTX_set_msg_callback_arg(WOLFSSL_CTX *ctx, void* arg)
+{
+    WOLFSSL_STUB("SSL_CTX_set_msg_callback_arg");
+    (void)ctx;
+    (void)arg;
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+int wolfSSL_set_msg_callback_arg(WOLFSSL *ssl, void* arg)
+{
+    WOLFSSL_ENTER("wolfSSL_set_msg_callback_arg");
+    if (ssl == NULL)
+        return WOLFSSL_FAILURE;
+
+    ssl->protoMsgCtx = arg;
+    return WOLFSSL_SUCCESS;
+}
+
+void *wolfSSL_OPENSSL_memdup(const void *data, size_t siz, const char* file, int line)
+{
+    void *ret;
+    (void)file;
+    (void)line;
+
+    if (data == NULL || siz >= INT_MAX)
+        return NULL;
+
+    ret = OPENSSL_malloc(siz);
+    if (ret == NULL) {
+        return NULL;
+    }
+    return XMEMCPY(ret, data, siz);
+}
+
+int wolfSSL_CTX_set_alpn_protos(WOLFSSL_CTX *ctx, const unsigned char *p,
+                            unsigned int p_len)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_set_alpn_protos");
+    if(ctx == NULL)
+        return BAD_FUNC_ARG;
+    if((void *)ctx->alpn_cli_protos != NULL)
+        wolfSSL_OPENSSL_free((void *)ctx->alpn_cli_protos);
+    ctx->alpn_cli_protos =
+        (const unsigned char *)wolfSSL_OPENSSL_memdup(p, p_len, NULL, 0);
+    if (ctx->alpn_cli_protos == NULL) {
+        return SSL_FAILURE;
+    }
+    ctx->alpn_cli_protos_len = p_len;
+
+    return SSL_SUCCESS;
+}
+
+
+#ifdef HAVE_ALPN
+/* Sets the ALPN extension protos
+ *
+ * example format is
+ * unsigned char p[] = {
+ *      8, 'h', 't', 't', 'p', '/', '1', '.', '1'
+ * };
+ *
+ * returns WOLFSSL_SUCCESS on success */
+int wolfSSL_set_alpn_protos(WOLFSSL* ssl,
+        const unsigned char* p, unsigned int p_len)
+{
+    WOLFSSL_BIO* bio;
+    char* pt;
+
+    unsigned int sz;
+    unsigned int idx = 0;
+    int alpn_opt = WOLFSSL_ALPN_CONTINUE_ON_MISMATCH;
+    WOLFSSL_ENTER("wolfSSL_set_alpn_protos");
+
+    if (ssl == NULL || p_len <= 1) {
+        return WOLFSSL_FAILURE;
+    }
+
+    bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem());
+    if (bio == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* convert into comma separated list */
+    while (idx < p_len - 1) {
+        unsigned int i;
+
+        sz = p[idx++];
+        if (idx + sz > p_len) {
+            WOLFSSL_MSG("Bad list format");
+            wolfSSL_BIO_free(bio);
+            return WOLFSSL_FAILURE;
+        }
+        if (sz > 0) {
+            for (i = 0; i < sz; i++) {
+                wolfSSL_BIO_write(bio, &p[idx++], 1);
+            }
+            if (idx < p_len - 1)
+                wolfSSL_BIO_write(bio, ",", 1);
+        }
+    }
+    wolfSSL_BIO_write(bio, "\0", 1);
+
+    /* clears out all current ALPN extensions set */
+    TLSX_Remove(&ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL, ssl->heap);
+
+    if ((sz = wolfSSL_BIO_get_mem_data(bio, &pt)) > 0) {
+        wolfSSL_UseALPN(ssl, pt, sz, alpn_opt);
+    }
+    wolfSSL_BIO_free(bio);
+    return WOLFSSL_SUCCESS;
+}
+#endif /* HAVE_ALPN */
+#endif
+
+#endif /* WOLFCRYPT_ONLY */
+
+#if defined(OPENSSL_EXTRA)
+
+#define WOLFSSL_BIO_INCLUDED
+#include "src/bio.c"
+
+int oid2nid(word32 oid, int grp)
+{
+    /* get OID type */
+    switch (grp) {
+        /* oidHashType */
+        case oidHashType:
+            switch (oid) {
+            #ifdef WOLFSSL_MD2
+                case MD2h:
+                    return NID_md2;
+            #endif
+            #ifndef NO_MD5
+                case MD5h:
+                    return NID_md5;
+            #endif
+            #ifndef NO_SHA
+                case SHAh:
+                    return NID_sha1;
+            #endif
+                case SHA224h:
+                    return NID_sha224;
+            #ifndef NO_SHA256
+                case SHA256h:
+                    return NID_sha256;
+            #endif
+            #ifdef WOLFSSL_SHA384
+                case SHA384h:
+                    return NID_sha384;
+            #endif
+            #ifdef WOLFSSL_SHA512
+                case SHA512h:
+                    return NID_sha512;
+            #endif
+            }
+            break;
+
+        /*  oidSigType */
+        case oidSigType:
+            switch (oid) {
+            #ifndef NO_DSA
+                case CTC_SHAwDSA:
+                    return CTC_SHAwDSA;
+            #endif /* NO_DSA */
+            #ifndef NO_RSA
+                case CTC_MD2wRSA:
+                    return CTC_MD2wRSA;
+                case CTC_MD5wRSA:
+                    return CTC_MD5wRSA;
+                case CTC_SHAwRSA:
+                    return CTC_SHAwRSA;
+                case CTC_SHA224wRSA:
+                    return CTC_SHA224wRSA;
+                case CTC_SHA256wRSA:
+                    return CTC_SHA256wRSA;
+                case CTC_SHA384wRSA:
+                    return CTC_SHA384wRSA;
+                case CTC_SHA512wRSA:
+                    return CTC_SHA512wRSA;
+            #endif /* NO_RSA */
+            #ifdef HAVE_ECC
+                case CTC_SHAwECDSA:
+                    return CTC_SHAwECDSA;
+                case CTC_SHA224wECDSA:
+                    return CTC_SHA224wECDSA;
+                case CTC_SHA256wECDSA:
+                    return CTC_SHA256wECDSA;
+                case CTC_SHA384wECDSA:
+                    return CTC_SHA384wECDSA;
+                case CTC_SHA512wECDSA:
+                    return CTC_SHA512wECDSA;
+            #endif /* HAVE_ECC */
+            }
+            break;
+
+        /* oidKeyType */
+        case oidKeyType:
+            switch (oid) {
+            #ifndef NO_DSA
+                case DSAk:
+                    return DSAk;
+            #endif /* NO_DSA */
+            #ifndef NO_RSA
+                case RSAk:
+                    return RSAk;
+            #endif /* NO_RSA */
+            #ifdef HAVE_NTRU
+                case NTRUk:
+                    return NTRUk;
+            #endif /* HAVE_NTRU */
+            #ifdef HAVE_ECC
+                case ECDSAk:
+                    return ECDSAk;
+            #endif /* HAVE_ECC */
+            }
+            break;
+
+
+    #ifdef HAVE_ECC
+        case oidCurveType:
+            switch (oid) {
+            case ECC_SECP192R1_OID:
+                return NID_X9_62_prime192v1;
+            case ECC_PRIME192V2_OID:
+                return NID_X9_62_prime192v2;
+            case ECC_PRIME192V3_OID:
+                return NID_X9_62_prime192v3;
+            case ECC_PRIME239V1_OID:
+                return NID_X9_62_prime239v1;
+            case ECC_PRIME239V2_OID:
+                return NID_X9_62_prime239v2;
+            case ECC_PRIME239V3_OID:
+                return NID_X9_62_prime239v3;
+            case ECC_SECP256R1_OID:
+                return NID_X9_62_prime256v1;
+            case ECC_SECP112R1_OID:
+                return NID_secp112r1;
+            case ECC_SECP112R2_OID:
+                return NID_secp112r2;
+            case ECC_SECP128R1_OID:
+                return NID_secp128r1;
+            case ECC_SECP128R2_OID:
+                return NID_secp128r2;
+            case ECC_SECP160R1_OID:
+                return NID_secp160r1;
+            case ECC_SECP160R2_OID:
+                return NID_secp160r2;
+            case ECC_SECP224R1_OID:
+                return NID_secp224r1;
+            case ECC_SECP384R1_OID:
+                return NID_secp384r1;
+            case ECC_SECP521R1_OID:
+                return NID_secp521r1;
+            case ECC_SECP160K1_OID:
+                return NID_secp160k1;
+            case ECC_SECP192K1_OID:
+                return NID_secp192k1;
+            case ECC_SECP224K1_OID:
+                return NID_secp224k1;
+            case ECC_SECP256K1_OID:
+                return NID_secp256k1;
+            case ECC_BRAINPOOLP160R1_OID:
+                return NID_brainpoolP160r1;
+            case ECC_BRAINPOOLP192R1_OID:
+                return NID_brainpoolP192r1;
+            case ECC_BRAINPOOLP224R1_OID:
+                return NID_brainpoolP224r1;
+            case ECC_BRAINPOOLP256R1_OID:
+                return NID_brainpoolP256r1;
+            case ECC_BRAINPOOLP320R1_OID:
+                return NID_brainpoolP320r1;
+            case ECC_BRAINPOOLP384R1_OID:
+                return NID_brainpoolP384r1;
+            case ECC_BRAINPOOLP512R1_OID:
+                return NID_brainpoolP512r1;
+            }
+            break;
+    #endif /* HAVE_ECC */
+
+        /* oidBlkType */
+        case oidBlkType:
+            switch (oid) {
+            #ifdef WOLFSSL_AES_128
+                case AES128CBCb:
+                    return AES128CBCb;
+            #endif
+            #ifdef WOLFSSL_AES_192
+                case AES192CBCb:
+                    return AES192CBCb;
+            #endif
+            #ifdef WOLFSSL_AES_256
+                case AES256CBCb:
+                    return AES256CBCb;
+            #endif
+            #ifndef NO_DES3
+                case DESb:
+                    return NID_des;
+                case DES3b:
+                    return NID_des3;
+            #endif
+            }
+            break;
+
+    #ifdef HAVE_OCSP
+        case oidOcspType:
+            switch (oid) {
+                case OCSP_BASIC_OID:
+                    return NID_id_pkix_OCSP_basic;
+                case OCSP_NONCE_OID:
+                    return OCSP_NONCE_OID;
+            }
+            break;
+    #endif /* HAVE_OCSP */
+
+        /* oidCertExtType */
+        case oidCertExtType:
+            switch (oid) {
+                case BASIC_CA_OID:
+                    return BASIC_CA_OID;
+                case ALT_NAMES_OID:
+                    return ALT_NAMES_OID;
+                case CRL_DIST_OID:
+                    return CRL_DIST_OID;
+                case AUTH_INFO_OID:
+                    return AUTH_INFO_OID;
+                case AUTH_KEY_OID:
+                    return AUTH_KEY_OID;
+                case SUBJ_KEY_OID:
+                    return SUBJ_KEY_OID;
+                case INHIBIT_ANY_OID:
+                    return INHIBIT_ANY_OID;
+                case KEY_USAGE_OID:
+                    return NID_key_usage;
+                case NAME_CONS_OID:
+                    return NID_name_constraints;
+                case CERT_POLICY_OID:
+                    return NID_certificate_policies;
+            }
+            break;
+
+        /* oidCertAuthInfoType */
+        case oidCertAuthInfoType:
+            switch (oid) {
+                case AIA_OCSP_OID:
+                    return AIA_OCSP_OID;
+                case AIA_CA_ISSUER_OID:
+                    return AIA_CA_ISSUER_OID;
+            }
+            break;
+
+        /* oidCertPolicyType */
+        case oidCertPolicyType:
+            switch (oid) {
+                case CP_ANY_OID:
+                    return NID_any_policy;
+            }
+            break;
+
+        /* oidCertAltNameType */
+        case oidCertAltNameType:
+            switch (oid) {
+                case HW_NAME_OID:
+                    return NID_hw_name_oid;
+            }
+            break;
+
+        /* oidCertKeyUseType */
+        case oidCertKeyUseType:
+            switch (oid) {
+                case EKU_ANY_OID:
+                    return NID_anyExtendedKeyUsage;
+                case EKU_SERVER_AUTH_OID:
+                    return EKU_SERVER_AUTH_OID;
+                case EKU_CLIENT_AUTH_OID:
+                    return EKU_CLIENT_AUTH_OID;
+                case EKU_OCSP_SIGN_OID:
+                    return EKU_OCSP_SIGN_OID;
+            }
+            break;
+
+        /* oidKdfType */
+        case oidKdfType:
+            switch (oid) {
+                case PBKDF2_OID:
+                    return PBKDF2_OID;
+            }
+            break;
+
+        /* oidPBEType */
+        case oidPBEType:
+            switch (oid) {
+                case PBE_SHA1_RC4_128:
+                    return PBE_SHA1_RC4_128;
+                case PBE_SHA1_DES:
+                    return PBE_SHA1_DES;
+                case PBE_SHA1_DES3:
+                    return PBE_SHA1_DES3;
+            }
+            break;
+
+        /* oidKeyWrapType */
+        case oidKeyWrapType:
+            switch (oid) {
+            #ifdef WOLFSSL_AES_128
+                case AES128_WRAP:
+                    return AES128_WRAP;
+            #endif
+            #ifdef WOLFSSL_AES_192
+                case AES192_WRAP:
+                    return AES192_WRAP;
+            #endif
+            #ifdef WOLFSSL_AES_256
+                case AES256_WRAP:
+                    return AES256_WRAP;
+            #endif
+            }
+            break;
+
+        /* oidCmsKeyAgreeType */
+        case oidCmsKeyAgreeType:
+            switch (oid) {
+                #ifndef NO_SHA
+                case dhSinglePass_stdDH_sha1kdf_scheme:
+                    return dhSinglePass_stdDH_sha1kdf_scheme;
+                #endif
+                #ifdef WOLFSSL_SHA224
+                case dhSinglePass_stdDH_sha224kdf_scheme:
+                    return dhSinglePass_stdDH_sha224kdf_scheme;
+                #endif
+                #ifndef NO_SHA256
+                case dhSinglePass_stdDH_sha256kdf_scheme:
+                    return dhSinglePass_stdDH_sha256kdf_scheme;
+                #endif
+                #ifdef WOLFSSL_SHA384
+                case dhSinglePass_stdDH_sha384kdf_scheme:
+                    return dhSinglePass_stdDH_sha384kdf_scheme;
+                #endif
+                #ifdef WOLFSSL_SHA512
+                case dhSinglePass_stdDH_sha512kdf_scheme:
+                    return dhSinglePass_stdDH_sha512kdf_scheme;
+                #endif
+            }
+            break;
+
+        default:
+            WOLFSSL_MSG("NID not in table");
+            return -1;
+    }
+
+    return -1;
+}
+
+
+/* when calling SetIndividualInternal, mpi should be cleared by caller if no
+ * longer used. ie mp_free(mpi). This is to free data when fastmath is
+ * disabled since a copy of mpi is made by this function and placed into bn.
+ */
+int SetIndividualInternal(WOLFSSL_BIGNUM* bn, mp_int* mpi)
+{
+    WOLFSSL_MSG("Entering SetIndividualInternal");
+
+    if (bn == NULL || bn->internal == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (mpi == NULL || (mp_init(mpi) != MP_OKAY)) {
+        WOLFSSL_MSG("mpi NULL error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (mp_copy((mp_int*)bn->internal, mpi) != MP_OKAY) {
+        WOLFSSL_MSG("mp_copy error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+#ifndef NO_ASN
+WOLFSSL_BIGNUM *wolfSSL_ASN1_INTEGER_to_BN(const WOLFSSL_ASN1_INTEGER *ai,
+                                       WOLFSSL_BIGNUM *bn)
+{
+    mp_int mpi;
+    word32 idx = 0;
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_ASN1_INTEGER_to_BN");
+
+    if (ai == NULL) {
+        return NULL;
+    }
+
+    ret = GetInt(&mpi, ai->data, &idx, ai->dataMax);
+    if (ret != 0) {
+    #ifdef WOLFSSL_QT
+        mp_init(&mpi); /* must init mpi */
+        /* Serial number in QT starts at index 0 of data */
+        if (mp_read_unsigned_bin(&mpi, (byte*)ai->data, ai->length) != 0) {
+                mp_clear(&mpi);
+                return NULL;
+            }
+    #else
+        /* expecting ASN1 format for INTEGER */
+        WOLFSSL_LEAVE("wolfSSL_ASN1_INTEGER_to_BN", ret);
+        return NULL;
+    #endif
+    }
+
+    /* mp_clear needs called because mpi is copied and causes memory leak with
+     * --disable-fastmath */
+    ret = SetIndividualExternal(&bn, &mpi);
+    mp_clear(&mpi);
+
+    if (ret != WOLFSSL_SUCCESS) {
+        return NULL;
+    }
+    return bn;
+}
+#endif /* !NO_ASN */
+
+#if !defined(NO_DSA) && !defined(NO_DH)
+WOLFSSL_DH *wolfSSL_DSA_dup_DH(const WOLFSSL_DSA *dsa)
+{
+    WOLFSSL_DH* dh;
+    DhKey*      key;
+
+    WOLFSSL_ENTER("wolfSSL_DSA_dup_DH");
+
+    if (dsa == NULL) {
+        return NULL;
+    }
+
+    dh = wolfSSL_DH_new();
+    if (dh == NULL) {
+        return NULL;
+    }
+    key = (DhKey*)dh->internal;
+
+    if (dsa->p != NULL &&
+        SetIndividualInternal(((WOLFSSL_DSA*)dsa)->p, &key->p) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa p key error");
+        wolfSSL_DH_free(dh);
+        return NULL;
+    }
+    if (dsa->g != NULL &&
+        SetIndividualInternal(((WOLFSSL_DSA*)dsa)->g, &key->g) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa g key error");
+        wolfSSL_DH_free(dh);
+        return NULL;
+    }
+
+    if (SetIndividualExternal(&dh->p, &key->p) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("dsa p key error");
+        wolfSSL_DH_free(dh);
+        return NULL;
+    }
+    if (SetIndividualExternal(&dh->g, &key->g) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("dsa g key error");
+        wolfSSL_DH_free(dh);
+        return NULL;
+    }
+
+    return dh;
+}
+#endif /* !NO_DSA && !NO_DH */
+
+
+#ifndef NO_RSA
+#if !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
+/* Openssl -> WolfSSL */
+int SetRsaInternal(WOLFSSL_RSA* rsa)
+{
+    RsaKey* key;
+    WOLFSSL_MSG("Entering SetRsaInternal");
+
+    if (rsa == NULL || rsa->internal == NULL) {
+        WOLFSSL_MSG("rsa key NULL error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    key = (RsaKey*)rsa->internal;
+
+    if (SetIndividualInternal(rsa->n, &key->n) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa n key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (SetIndividualInternal(rsa->e, &key->e) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa e key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    /* public key */
+    key->type = RSA_PUBLIC;
+
+    if (rsa->d != NULL) {
+        if (SetIndividualInternal(rsa->d, &key->d) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("rsa d key error");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        /* private key */
+        key->type = RSA_PRIVATE;
+    }
+
+    if (rsa->p != NULL &&
+        SetIndividualInternal(rsa->p, &key->p) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa p key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (rsa->q != NULL &&
+        SetIndividualInternal(rsa->q, &key->q) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa q key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+#ifndef RSA_LOW_MEM
+    if (rsa->dmp1 != NULL &&
+        SetIndividualInternal(rsa->dmp1, &key->dP) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa dP key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (rsa->dmq1 != NULL &&
+        SetIndividualInternal(rsa->dmq1, &key->dQ) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa dQ key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (rsa->iqmp != NULL &&
+        SetIndividualInternal(rsa->iqmp, &key->u) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa u key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+#endif /* !RSA_LOW_MEM */
+
+    rsa->inSet = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* SSL_SUCCESS on ok */
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_RSA_blinding_on(WOLFSSL_RSA* rsa, WOLFSSL_BN_CTX* bn)
+{
+    (void)rsa;
+    (void)bn;
+    WOLFSSL_STUB("RSA_blinding_on");
+    WOLFSSL_MSG("wolfSSL_RSA_blinding_on");
+
+    return WOLFSSL_SUCCESS;  /* on by default */
+}
+#endif
+
+/* return compliant with OpenSSL
+ *   size of encrypted data if success , -1 if error
+ */
+int wolfSSL_RSA_public_encrypt(int len, const unsigned char* fr,
+                            unsigned char* to, WOLFSSL_RSA* rsa, int padding)
+{
+    int initTmpRng = 0;
+    WC_RNG *rng = NULL;
+    int outLen;
+    int ret = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG* tmpRNG = NULL;
+#else
+    WC_RNG  _tmpRNG[1];
+    WC_RNG* tmpRNG = _tmpRNG;
+#endif
+#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
+    int  mgf = WC_MGF1NONE;
+    enum wc_HashType hash = WC_HASH_TYPE_NONE;
+#endif
+
+    WOLFSSL_MSG("wolfSSL_RSA_public_encrypt");
+
+    /* Check and remap the padding to internal values, if needed. */
+#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
+    if (padding == RSA_PKCS1_PADDING)
+        padding = WC_RSA_PKCSV15_PAD;
+    else if (padding == RSA_PKCS1_OAEP_PADDING) {
+        padding = WC_RSA_OAEP_PAD;
+        hash = WC_HASH_TYPE_SHA;
+        mgf = WC_MGF1SHA1;
+    }
+    else if (padding == RSA_PKCS1_PSS_PADDING) {
+        padding = WC_RSA_PSS_PAD;
+        hash = WC_HASH_TYPE_SHA256;
+        mgf  = WC_MGF1SHA256;
+    }
+    else if (padding == RSA_NO_PADDING) {
+        padding = WC_RSA_NO_PAD;
+    }
+#else
+    if (padding == RSA_PKCS1_PADDING)
+      ;
+#endif
+    else {
+        WOLFSSL_MSG("wolfSSL_RSA_public_encrypt unsupported padding");
+        return 0;
+    }
+
+    if (rsa->inSet == 0)
+    {
+        if (SetRsaInternal(rsa) != SSL_SUCCESS) {
+            WOLFSSL_MSG("SetRsaInternal failed");
+            return 0;
+        }
+    }
+
+    outLen = wolfSSL_RSA_size(rsa);
+
+    rng = WOLFSSL_RSA_GetRNG(rsa, (WC_RNG**)&tmpRNG, &initTmpRng);
+
+    if (outLen == 0) {
+        WOLFSSL_MSG("Bad RSA size");
+    }
+
+    if (rng) {
+#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
+        ret = wc_RsaPublicEncrypt_ex(fr, len, to, outLen,
+                             (RsaKey*)rsa->internal, rng, padding,
+                             hash, mgf, NULL, 0);
+#else
+        ret = wc_RsaPublicEncrypt(fr, len, to, outLen,
+                             (RsaKey*)rsa->internal, rng);
+#endif
+        if (ret <= 0) {
+            WOLFSSL_MSG("Bad Rsa Encrypt");
+        }
+        if (len <= 0) {
+            WOLFSSL_MSG("Bad Rsa Encrypt");
+        }
+    }
+
+    if (initTmpRng)
+        wc_FreeRng(tmpRNG);
+#ifdef WOLFSSL_SMALL_STACK
+    if (tmpRNG)
+        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    if (ret >= 0)
+        WOLFSSL_MSG("wolfSSL_RSA_public_encrypt success");
+    else {
+        WOLFSSL_MSG("wolfSSL_RSA_public_encrypt failed");
+        ret = WOLFSSL_FATAL_ERROR; /* return -1 on error case */
+    }
+    return ret;
+}
+
+
+
+
+/* return compliant with OpenSSL
+ *   size of plain recovered data if success , -1 if error
+ */
+int wolfSSL_RSA_private_decrypt(int len, const unsigned char* fr,
+                            unsigned char* to, WOLFSSL_RSA* rsa, int padding)
+{
+    int outLen;
+    int ret = 0;
+  #if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
+    int mgf = WC_MGF1NONE;
+    enum wc_HashType hash = WC_HASH_TYPE_NONE;
+  #endif
+
+    WOLFSSL_MSG("wolfSSL_RSA_private_decrypt");
+
+#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
+    if (padding == RSA_PKCS1_PADDING)
+        padding = WC_RSA_PKCSV15_PAD;
+    else if (padding == RSA_PKCS1_OAEP_PADDING) {
+        padding = WC_RSA_OAEP_PAD;
+        hash = WC_HASH_TYPE_SHA;
+        mgf = WC_MGF1SHA1;
+    }
+    else if (padding == RSA_PKCS1_PSS_PADDING) {
+        padding = WC_RSA_PSS_PAD;
+        hash = WC_HASH_TYPE_SHA256;
+        mgf  = WC_MGF1SHA256;
+    }
+    else if (padding == RSA_NO_PADDING) {
+        padding = WC_RSA_NO_PAD;
+    }
+#else
+    if (padding == RSA_PKCS1_PADDING)
+        ;
+#endif
+    else {
+        WOLFSSL_MSG("wolfSSL_RSA_private_decrypt unsupported padding");
+        return 0;
+    }
+
+    if (rsa->inSet == 0)
+    {
+        if (SetRsaInternal(rsa) != SSL_SUCCESS) {
+            WOLFSSL_MSG("SetRsaInternal failed");
+            return 0;
+        }
+    }
+
+    outLen = wolfSSL_RSA_size(rsa);
+    if (outLen == 0) {
+        WOLFSSL_MSG("Bad RSA size");
+    }
+
+    /* size of 'to' buffer must be size of RSA key */
+#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
+    ret = wc_RsaPrivateDecrypt_ex(fr, len, to, outLen,
+                            (RsaKey*)rsa->internal, padding,
+                            hash, mgf, NULL, 0);
+#else
+    ret = wc_RsaPrivateDecrypt(fr, len, to, outLen,
+                            (RsaKey*)rsa->internal);
+#endif
+
+    if (len <= 0) {
+        WOLFSSL_MSG("Bad Rsa Decrypt");
+    }
+
+    if (ret > 0)
+        WOLFSSL_MSG("wolfSSL_RSA_private_decrypt success");
+    else {
+        WOLFSSL_MSG("wolfSSL_RSA_private_decrypt failed");
+        ret = WOLFSSL_FATAL_ERROR;
+    }
+    return ret;
+}
+
+#if !defined(_WIN32) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
+int wolfSSL_RSA_public_decrypt(int flen, const unsigned char* from,
+                          unsigned char* to, WOLFSSL_RSA* rsa, int padding)
+{
+    int tlen = 0;
+    int pad_type;
+
+    WOLFSSL_ENTER("wolfSSL_RSA_public_decrypt");
+
+    if (rsa == NULL || rsa->internal == NULL || from == NULL) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    switch (padding) {
+    case RSA_PKCS1_PADDING:
+        pad_type = WC_RSA_PKCSV15_PAD;
+        break;
+    case RSA_PKCS1_OAEP_PADDING:
+        pad_type = WC_RSA_OAEP_PAD;
+        break;
+    case RSA_PKCS1_PSS_PADDING:
+        pad_type = WC_RSA_PSS_PAD;
+        break;
+    case RSA_NO_PADDING:
+        pad_type = WC_RSA_NO_PAD;
+        break;
+    default:
+        WOLFSSL_MSG("wolfSSL_RSA_public_decrypt unsupported padding");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (rsa->inSet == 0)
+    {
+        WOLFSSL_MSG("No RSA internal set, do it");
+
+        if (SetRsaInternal(rsa) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetRsaInternal failed");
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+    /* size of 'to' buffer must be size of RSA key */
+    tlen = wc_RsaSSL_Verify_ex(from, flen, to, wolfSSL_RSA_size(rsa),
+                               (RsaKey*)rsa->internal, pad_type);
+    if (tlen <= 0)
+        WOLFSSL_MSG("wolfSSL_RSA_public_decrypt failed");
+    else {
+        WOLFSSL_MSG("wolfSSL_RSA_public_decrypt success");
+    }
+    return tlen;
+}
+#endif /* !defined(_WIN32) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) */
+
+/* RSA private encrypt calls wc_RsaSSL_Sign. Similar function set up as RSA
+ * public decrypt.
+ *
+ * len  Length of input buffer
+ * in   Input buffer to sign
+ * out  Output buffer (expected to be greater than or equal to RSA key size)
+ * rsa     Key to use for encryption
+ * padding Type of RSA padding to use.
+ */
+int wolfSSL_RSA_private_encrypt(int len, unsigned char* in,
+                            unsigned char* out, WOLFSSL_RSA* rsa, int padding)
+{
+    int sz = 0;
+    WC_RNG* rng = NULL;
+#if !defined(WC_RSA_BLINDING) || defined(HAVE_USER_RSA)
+    WC_RNG rng_lcl;
+#endif
+    RsaKey* key;
+
+    WOLFSSL_MSG("wolfSSL_RSA_private_encrypt");
+
+    if (len < 0 || rsa == NULL || rsa->internal == NULL || in == NULL) {
+        WOLFSSL_MSG("Bad function arguments");
+        return 0;
+    }
+
+    if (padding != RSA_PKCS1_PADDING && padding != RSA_PKCS1_PSS_PADDING) {
+        WOLFSSL_MSG("wolfSSL_RSA_private_encrypt unsupported padding");
+        return 0;
+    }
+
+    if (rsa->inSet == 0)
+    {
+        WOLFSSL_MSG("Setting internal RSA structure");
+
+        if (SetRsaInternal(rsa) != SSL_SUCCESS) {
+            WOLFSSL_MSG("SetRsaInternal failed");
+            return 0;
+        }
+    }
+
+    key = (RsaKey*)rsa->internal;
+#if defined(WC_RSA_BLINDING) && !defined(HAVE_USER_RSA)
+    rng = key->rng;
+#else
+    rng = &rng_lcl;
+    #ifndef HAVE_FIPS
+    if (wc_InitRng_ex(rng, key->heap, INVALID_DEVID) != 0)
+    #else
+    if (wc_InitRng(rng) != 0)
+    #endif
+    {
+        WOLFSSL_MSG("Error with random number");
+        return SSL_FATAL_ERROR;
+    }
+#endif
+
+    /* size of output buffer must be size of RSA key */
+    sz = wc_RsaSSL_Sign(in, (word32)len, out, wolfSSL_RSA_size(rsa), key, rng);
+    #if !defined(WC_RSA_BLINDING) || defined(HAVE_USER_RSA)
+    if (wc_FreeRng(rng) != 0) {
+        WOLFSSL_MSG("Error freeing random number generator");
+        return SSL_FATAL_ERROR;
+    }
+    #endif
+    if (sz <= 0) {
+        WOLFSSL_LEAVE("wolfSSL_RSA_private_encrypt", sz);
+        return 0;
+    }
+
+    return sz;
+}
+#endif /* HAVE_USER_RSA */
+#endif
+
+
+/* frees all nodes in the current threads error queue
+ *
+ * id  thread id. ERR_remove_state is depreciated and id is ignored. The
+ *     current threads queue will be free'd.
+ */
+void wolfSSL_ERR_remove_state(unsigned long id)
+{
+    WOLFSSL_ENTER("wolfSSL_ERR_remove_state");
+    (void)id;
+    if (wc_ERR_remove_state() != 0) {
+        WOLFSSL_MSG("Error with removing the state");
+    }
+}
+
+
+WOLFSSL_BN_CTX* wolfSSL_BN_CTX_new(void)
+{
+    static int ctx;  /* wolfcrypt doesn't now need ctx */
+
+    WOLFSSL_MSG("wolfSSL_BN_CTX_new");
+    return (WOLFSSL_BN_CTX*)&ctx;
+
+}
+
+void wolfSSL_BN_CTX_init(WOLFSSL_BN_CTX* ctx)
+{
+    (void)ctx;
+    WOLFSSL_MSG("wolfSSL_BN_CTX_init");
+}
+
+
+void wolfSSL_BN_CTX_free(WOLFSSL_BN_CTX* ctx)
+{
+    (void)ctx;
+    WOLFSSL_MSG("wolfSSL_BN_CTX_free");
+    /* do free since static ctx that does nothing */
+}
+
+/* WOLFSSL_SUCCESS on ok */
+int wolfSSL_BN_sub(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a,
+                  const WOLFSSL_BIGNUM* b)
+{
+    WOLFSSL_MSG("wolfSSL_BN_sub");
+
+    if (r == NULL || a == NULL || b == NULL)
+        return 0;
+
+    if (mp_sub((mp_int*)a->internal,(mp_int*)b->internal,
+               (mp_int*)r->internal) == MP_OKAY)
+        return WOLFSSL_SUCCESS;
+
+    WOLFSSL_MSG("wolfSSL_BN_sub mp_sub failed");
+    return 0;
+}
+
+/* WOLFSSL_SUCCESS on ok */
+int wolfSSL_BN_mod(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a,
+                  const WOLFSSL_BIGNUM* b, const WOLFSSL_BN_CTX* c)
+{
+    (void)c;
+    WOLFSSL_MSG("wolfSSL_BN_mod");
+
+    if (r == NULL || a == NULL || b == NULL)
+        return 0;
+
+    if (mp_mod((mp_int*)a->internal,(mp_int*)b->internal,
+               (mp_int*)r->internal) == MP_OKAY)
+        return WOLFSSL_SUCCESS;
+
+    WOLFSSL_MSG("wolfSSL_BN_mod mp_mod failed");
+    return 0;
+}
+
+
+/* r = (a^p) % m */
+int wolfSSL_BN_mod_exp(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a,
+      const WOLFSSL_BIGNUM *p, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx)
+{
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_BN_mod_exp");
+
+    (void) ctx;
+    if (r == NULL || a == NULL || p == NULL || m == NULL) {
+        WOLFSSL_MSG("Bad Argument");
+        return WOLFSSL_FAILURE;
+    }
+
+    if ((ret = mp_exptmod((mp_int*)a->internal,(mp_int*)p->internal,
+               (mp_int*)m->internal, (mp_int*)r->internal)) == MP_OKAY) {
+        return WOLFSSL_SUCCESS;
+    }
+
+    WOLFSSL_LEAVE("wolfSSL_BN_mod_exp", ret);
+    (void)ret;
+
+    return WOLFSSL_FAILURE;
+}
+
+/* r = (a * p) % m */
+int wolfSSL_BN_mod_mul(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a,
+        const WOLFSSL_BIGNUM *p, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx)
+{
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_BN_mod_mul");
+
+    (void) ctx;
+    if (r == NULL || a == NULL || p == NULL || m == NULL) {
+        WOLFSSL_MSG("Bad Argument");
+        return SSL_FAILURE;
+    }
+
+    if ((ret = mp_mulmod((mp_int*)a->internal,(mp_int*)p->internal,
+               (mp_int*)m->internal, (mp_int*)r->internal)) == MP_OKAY) {
+        return SSL_SUCCESS;
+    }
+
+    WOLFSSL_LEAVE("wolfSSL_BN_mod_mul", ret);
+    (void)ret;
+
+    return SSL_FAILURE;
+}
+
+#ifdef OPENSSL_EXTRA
+const WOLFSSL_BIGNUM* wolfSSL_BN_value_one(void)
+{
+    WOLFSSL_MSG("wolfSSL_BN_value_one");
+
+    if (bn_one == NULL) {
+        bn_one = wolfSSL_BN_new();
+        if (bn_one) {
+            if (mp_set_int((mp_int*)bn_one->internal, 1) != MP_OKAY) {
+                /* handle error by freeing BN and returning NULL */
+                wolfSSL_BN_free(bn_one);
+                bn_one = NULL;
+            }
+        }
+    }
+
+    return bn_one;
+}
+#endif
+
+/* return compliant with OpenSSL
+ *   size of BIGNUM in bytes, 0 if error */
+int wolfSSL_BN_num_bytes(const WOLFSSL_BIGNUM* bn)
+{
+    WOLFSSL_ENTER("wolfSSL_BN_num_bytes");
+
+    if (bn == NULL || bn->internal == NULL)
+        return WOLFSSL_FAILURE;
+
+    return mp_unsigned_bin_size((mp_int*)bn->internal);
+}
+
+/* return compliant with OpenSSL
+ *   size of BIGNUM in bits, 0 if error */
+int wolfSSL_BN_num_bits(const WOLFSSL_BIGNUM* bn)
+{
+    WOLFSSL_ENTER("wolfSSL_BN_num_bits");
+
+    if (bn == NULL || bn->internal == NULL)
+        return WOLFSSL_FAILURE;
+
+    return mp_count_bits((mp_int*)bn->internal);
+}
+
+int wolfSSL_BN_is_negative(const WOLFSSL_BIGNUM* bn)
+{
+    if (bn == NULL)
+        return WOLFSSL_FAILURE;
+
+    return mp_isneg((mp_int*)bn->internal);
+}
+
+/* return compliant with OpenSSL
+ *   1 if BIGNUM is zero, 0 else */
+int wolfSSL_BN_is_zero(const WOLFSSL_BIGNUM* bn)
+{
+    WOLFSSL_MSG("wolfSSL_BN_is_zero");
+
+    if (bn == NULL || bn->internal == NULL)
+        return WOLFSSL_FAILURE;
+
+    if (mp_iszero((mp_int*)bn->internal) == MP_YES)
+        return WOLFSSL_SUCCESS;
+
+    return WOLFSSL_FAILURE;
+}
+
+/* return compliant with OpenSSL
+ *   1 if BIGNUM is one, 0 else */
+int wolfSSL_BN_is_one(const WOLFSSL_BIGNUM* bn)
+{
+    WOLFSSL_MSG("wolfSSL_BN_is_one");
+
+    if (bn == NULL || bn->internal == NULL)
+        return WOLFSSL_FAILURE;
+
+    if (mp_cmp_d((mp_int*)bn->internal, 1) == MP_EQ)
+        return WOLFSSL_SUCCESS;
+
+    return WOLFSSL_FAILURE;
+}
+
+/* return compliant with OpenSSL
+ *   1 if BIGNUM is odd, 0 else */
+int wolfSSL_BN_is_odd(const WOLFSSL_BIGNUM* bn)
+{
+    WOLFSSL_MSG("wolfSSL_BN_is_odd");
+
+    if (bn == NULL || bn->internal == NULL)
+        return WOLFSSL_FAILURE;
+
+    if (mp_isodd((mp_int*)bn->internal) == MP_YES)
+        return WOLFSSL_SUCCESS;
+
+    return WOLFSSL_FAILURE;
+}
+
+/* return compliant with OpenSSL
+ *   1 if BIGNUM is word, 0 else */
+int wolfSSL_BN_is_word(const WOLFSSL_BIGNUM* bn, WOLFSSL_BN_ULONG w)
+{
+    WOLFSSL_ENTER("wolfSSL_BN_is_word");
+
+    if (bn == NULL || bn->internal == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (mp_isword((mp_int*)bn->internal, w) == MP_YES) {
+         return WOLFSSL_SUCCESS;
+    }
+
+    return WOLFSSL_FAILURE;
+}
+
+/* return compliant with OpenSSL
+ *   -1 if a < b, 0 if a == b and 1 if a > b
+ */
+int wolfSSL_BN_cmp(const WOLFSSL_BIGNUM* a, const WOLFSSL_BIGNUM* b)
+{
+    int ret;
+
+    WOLFSSL_MSG("wolfSSL_BN_cmp");
+
+    if (a == NULL || a->internal == NULL || b == NULL || b->internal == NULL)
+        return WOLFSSL_FATAL_ERROR;
+
+    ret = mp_cmp((mp_int*)a->internal, (mp_int*)b->internal);
+
+    return (ret == MP_EQ ? 0 : (ret == MP_GT ? 1 : -1));
+}
+
+/* return compliant with OpenSSL
+ *   length of BIGNUM in bytes, -1 if error */
+int wolfSSL_BN_bn2bin(const WOLFSSL_BIGNUM* bn, unsigned char* r)
+{
+    WOLFSSL_MSG("wolfSSL_BN_bn2bin");
+
+    if (bn == NULL || bn->internal == NULL) {
+        WOLFSSL_MSG("NULL bn error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (r == NULL)
+        return mp_unsigned_bin_size((mp_int*)bn->internal);
+
+    if (mp_to_unsigned_bin((mp_int*)bn->internal, r) != MP_OKAY) {
+        WOLFSSL_MSG("mp_to_unsigned_bin error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    return mp_unsigned_bin_size((mp_int*)bn->internal);
+}
+
+
+WOLFSSL_BIGNUM* wolfSSL_BN_bin2bn(const unsigned char* str, int len,
+                            WOLFSSL_BIGNUM* ret)
+{
+    int weOwn = 0;
+
+    WOLFSSL_MSG("wolfSSL_BN_bin2bn");
+
+    /* if ret is null create a BN */
+    if (ret == NULL) {
+        ret = wolfSSL_BN_new();
+        weOwn = 1;
+        if (ret == NULL)
+            return NULL;
+    }
+
+    /* check ret and ret->internal then read in value */
+    if (ret && ret->internal) {
+        if (mp_read_unsigned_bin((mp_int*)ret->internal, str, len) != 0) {
+            WOLFSSL_MSG("mp_read_unsigned_bin failure");
+            if (weOwn)
+                wolfSSL_BN_free(ret);
+            return NULL;
+        }
+    } else {
+        return NULL;
+    }
+
+    return ret;
+}
+
+/* return compliant with OpenSSL
+ *   1 if success, 0 if error */
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_mask_bits(WOLFSSL_BIGNUM* bn, int n)
+{
+    (void)bn;
+    (void)n;
+    WOLFSSL_ENTER("wolfSSL_BN_mask_bits");
+    WOLFSSL_STUB("BN_mask_bits");
+    return SSL_FAILURE;
+}
+#endif
+
+
+/* WOLFSSL_SUCCESS on ok */
+int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom)
+{
+    int           ret    = 0;
+    int           len    = bits / 8;
+    int           initTmpRng = 0;
+    WC_RNG*       rng    = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG*       tmpRNG = NULL;
+    byte*         buff   = NULL;
+#else
+    WC_RNG        tmpRNG[1];
+    byte          buff[1024];
+#endif
+
+    (void)top;
+    (void)bottom;
+    WOLFSSL_MSG("wolfSSL_BN_rand");
+
+    if (bits % 8)
+        len++;
+
+#ifdef WOLFSSL_SMALL_STACK
+    buff   = (byte*)XMALLOC(1024,        NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    tmpRNG = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+    if (buff == NULL || tmpRNG == NULL) {
+        XFREE(buff,   NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+        return ret;
+    }
+#endif
+
+    if (bn == NULL || bn->internal == NULL)
+        WOLFSSL_MSG("Bad function arguments");
+    else if (wc_InitRng(tmpRNG) == 0) {
+        rng = tmpRNG;
+        initTmpRng = 1;
+    }
+    else if (initGlobalRNG)
+        rng = &globalRNG;
+
+    if (rng) {
+        if (wc_RNG_GenerateBlock(rng, buff, len) != 0)
+            WOLFSSL_MSG("Bad wc_RNG_GenerateBlock");
+        else {
+            buff[0]     |= 0x80 | 0x40;
+            buff[len-1] |= 0x01;
+
+            if (mp_read_unsigned_bin((mp_int*)bn->internal,buff,len) != MP_OKAY)
+                WOLFSSL_MSG("mp read bin failed");
+            else
+                ret = WOLFSSL_SUCCESS;
+        }
+    }
+
+    if (initTmpRng)
+        wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(buff,   NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+    return ret;
+}
+
+
+/* WOLFSSL_SUCCESS on ok
+ * code is same as wolfSSL_BN_rand except for how top and bottom is handled.
+ * top -1 then leave most sig bit alone
+ * top 0 then most sig is set to 1
+ * top is 1 then first two most sig bits are 1
+ *
+ * bottom is hot then odd number */
+int wolfSSL_BN_pseudo_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom)
+{
+    int           ret    = 0;
+    int           len    = bits / 8;
+    int           initTmpRng = 0;
+    WC_RNG*       rng    = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG*       tmpRNG = NULL;
+    byte*         buff   = NULL;
+#else
+    WC_RNG        tmpRNG[1];
+    byte          buff[1024];
+#endif
+
+    WOLFSSL_MSG("wolfSSL_BN_rand");
+
+    if (bits % 8)
+        len++;
+
+#ifdef WOLFSSL_SMALL_STACK
+    buff   = (byte*)XMALLOC(1024,        NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    tmpRNG = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (buff == NULL || tmpRNG == NULL) {
+        XFREE(buff,   NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return ret;
+    }
+#endif
+
+    if (bn == NULL || bn->internal == NULL)
+        WOLFSSL_MSG("Bad function arguments");
+    else if (wc_InitRng(tmpRNG) == 0) {
+        rng = tmpRNG;
+        initTmpRng = 1;
+    }
+    else if (initGlobalRNG)
+        rng = &globalRNG;
+
+    if (rng) {
+        if (wc_RNG_GenerateBlock(rng, buff, len) != 0)
+            WOLFSSL_MSG("Bad wc_RNG_GenerateBlock");
+        else {
+            switch (top) {
+                case -1:
+                    break;
+
+                case 0:
+                    buff[0] |= 0x80;
+                    break;
+
+                case 1:
+                    buff[0] |= 0x80 | 0x40;
+                    break;
+            }
+
+            if (bottom == 1) {
+                buff[len-1] |= 0x01;
+            }
+
+            if (mp_read_unsigned_bin((mp_int*)bn->internal,buff,len) != MP_OKAY)
+                WOLFSSL_MSG("mp read bin failed");
+            else
+                ret = WOLFSSL_SUCCESS;
+        }
+    }
+
+    if (initTmpRng)
+        wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(buff,   NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return ret;
+}
+
+/* return code compliant with OpenSSL :
+ *   1 if bit set, 0 else
+ */
+int wolfSSL_BN_is_bit_set(const WOLFSSL_BIGNUM* bn, int n)
+{
+    if (bn == NULL || bn->internal == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    return mp_is_bit_set((mp_int*)bn->internal, (mp_digit)n);
+}
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 else
+ */
+int wolfSSL_BN_set_bit(WOLFSSL_BIGNUM* bn, int n)
+{
+    if (bn == NULL || bn->internal == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (mp_set_bit((mp_int*)bn->internal, n) != MP_OKAY) {
+        WOLFSSL_MSG("mp_set_bit error");
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_BN_clear_bit(WOLFSSL_BIGNUM* bn, int n)
+{
+    int ret = WOLFSSL_FAILURE;
+#ifndef WOLFSSL_SMALL_STACK
+    mp_int tmp[1];
+#else
+    mp_int* tmp = NULL;
+#endif
+
+    if (bn == NULL || bn->internal == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        goto cleanup;
+    }
+    if (mp_is_bit_set((mp_int*)bn->internal, n)) {
+#ifdef WOLFSSL_SMALL_STACK
+       tmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
+       if (tmp == NULL) {
+           goto cleanup;
+       }
+#endif
+        if (mp_init(tmp) != MP_OKAY) {
+            goto cleanup;
+        }
+        if (mp_set_bit(tmp, n) != MP_OKAY) {
+            goto cleanup;
+        }
+        if (mp_sub((mp_int*)bn->internal, tmp, (mp_int*)bn->internal) != MP_OKAY) {
+            goto cleanup;
+        }
+    }
+
+    ret = WOLFSSL_SUCCESS;
+cleanup:
+    mp_clear(tmp);
+#ifdef WOLFSSL_SMALL_STACK
+    if (tmp)
+        XFREE(tmp, NULL, DYNAMIC_TYPE_BIGINT);
+#endif
+    return ret;
+}
+
+
+/* WOLFSSL_SUCCESS on ok */
+/* Note on use: this function expects str to be an even length. It is
+ * converting pairs of bytes into 8-bit values. As an example, the RSA
+ * public exponent is commonly 0x010001. To get it to convert, you need
+ * to pass in the string "010001", it will fail if you use "10001". This
+ * is an affect of how Base16_Decode() works.
+ */
+int wolfSSL_BN_hex2bn(WOLFSSL_BIGNUM** bn, const char* str)
+{
+    int     ret     = 0;
+    word32  decSz   = 1024;
+#ifdef WOLFSSL_SMALL_STACK
+    byte*   decoded;
+#else
+    byte    decoded[1024];
+#endif
+    int     weOwn = 0;
+    int     strLen;
+
+    WOLFSSL_MSG("wolfSSL_BN_hex2bn");
+
+#ifdef WOLFSSL_SMALL_STACK
+    decoded = (byte*)XMALLOC(decSz, NULL, DYNAMIC_TYPE_DER);
+    if (decoded == NULL)
+        return ret;
+#endif
+
+    if (str == NULL || str[0] == '\0') {
+        WOLFSSL_MSG("Bad function argument");
+        ret = WOLFSSL_FAILURE;
+    } else {
+        strLen = (int)XSTRLEN(str);
+        /* ignore trailing new lines */
+        while (str[strLen-1] == '\n' && strLen > 0) strLen--;
+
+        if (Base16_Decode((byte*)str, strLen, decoded, &decSz) < 0)
+            WOLFSSL_MSG("Bad Base16_Decode error");
+        else if (bn == NULL)
+            ret = decSz;
+        else {
+            if (*bn == NULL) {
+                *bn = wolfSSL_BN_new();
+                if (*bn != NULL) {
+                    weOwn = 1;
+                }
+            }
+
+            if (*bn == NULL)
+                WOLFSSL_MSG("BN new failed");
+            else if (wolfSSL_BN_bin2bn(decoded, decSz, *bn) == NULL) {
+                WOLFSSL_MSG("Bad bin2bn error");
+                if (weOwn == 1) {
+                    wolfSSL_BN_free(*bn); /* Free new BN */
+                }
+            }
+            else
+                ret = WOLFSSL_SUCCESS;
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(decoded, NULL, DYNAMIC_TYPE_DER);
+#endif
+
+    return ret;
+}
+
+
+WOLFSSL_BIGNUM* wolfSSL_BN_dup(const WOLFSSL_BIGNUM* bn)
+{
+    WOLFSSL_BIGNUM* ret;
+
+    WOLFSSL_MSG("wolfSSL_BN_dup");
+
+    if (bn == NULL || bn->internal == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return NULL;
+    }
+
+    ret = wolfSSL_BN_new();
+    if (ret == NULL) {
+        WOLFSSL_MSG("bn new error");
+        return NULL;
+    }
+
+    if (mp_copy((mp_int*)bn->internal, (mp_int*)ret->internal) != MP_OKAY) {
+        WOLFSSL_MSG("mp_copy error");
+        wolfSSL_BN_free(ret);
+        return NULL;
+    }
+
+    ret->neg = bn->neg;
+
+    return ret;
+}
+
+
+WOLFSSL_BIGNUM* wolfSSL_BN_copy(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* bn)
+{
+    WOLFSSL_MSG("wolfSSL_BN_copy");
+
+    if (r == NULL || bn == NULL) {
+        WOLFSSL_MSG("r or bn NULL error");
+        return NULL;
+    }
+
+    if (mp_copy((mp_int*)bn->internal, (mp_int*)r->internal) != MP_OKAY) {
+        WOLFSSL_MSG("mp_copy error");
+        return NULL;
+    }
+
+    r->neg = bn->neg;
+
+    return r;
+}
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 else
+ */
+int wolfSSL_BN_set_word(WOLFSSL_BIGNUM* bn, WOLFSSL_BN_ULONG w)
+{
+    WOLFSSL_MSG("wolfSSL_BN_set_word");
+
+    if (bn == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (mp_set_int((mp_int*)bn->internal, w) != MP_OKAY) {
+        WOLFSSL_MSG("mp_init_set_int error");
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* Returns the big number as an unsigned long if possible.
+ *
+ * bn  big number structure to get value from
+ *
+ * Returns value or 0xFFFFFFFFL if bigger than unsigned long.
+ */
+unsigned long wolfSSL_BN_get_word(const WOLFSSL_BIGNUM* bn)
+{
+    mp_int* mp;
+
+    WOLFSSL_MSG("wolfSSL_BN_get_word");
+
+    if (bn == NULL) {
+        WOLFSSL_MSG("Invalid argument");
+        return 0;
+    }
+
+    if (wolfSSL_BN_num_bytes(bn) > (int)sizeof(unsigned long)) {
+        WOLFSSL_MSG("bignum is larger than unsigned long");
+        return 0xFFFFFFFFL;
+    }
+    mp = (mp_int*)bn->internal;
+
+    return (unsigned long)(mp->dp[0]);
+}
+
+/* return code compliant with OpenSSL :
+ *   number length in decimal if success, 0 if error
+ */
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_BN_dec2bn(WOLFSSL_BIGNUM** bn, const char* str)
+{
+    (void)bn;
+    (void)str;
+
+    WOLFSSL_MSG("wolfSSL_BN_dec2bn");
+    WOLFSSL_STUB("BN_dec2bn");
+    return SSL_FAILURE;
+}
+#endif
+
+#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY)
+char *wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM *bn)
+{
+    int len = 0;
+    char *buf;
+
+    WOLFSSL_MSG("wolfSSL_BN_bn2dec");
+
+    if (bn == NULL || bn->internal == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return NULL;
+    }
+
+    if (mp_radix_size((mp_int*)bn->internal, MP_RADIX_DEC, &len) != MP_OKAY) {
+        WOLFSSL_MSG("mp_radix_size failure");
+        return NULL;
+    }
+
+    buf = (char*) XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL);
+    if (buf == NULL) {
+        WOLFSSL_MSG("BN_bn2dec malloc buffer failure");
+        return NULL;
+    }
+
+    if (mp_todecimal((mp_int*)bn->internal, buf) != MP_OKAY) {
+        XFREE(buf, NULL, DYNAMIC_TYPE_ECC);
+        return NULL;
+    }
+
+    return buf;
+}
+#else
+char* wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM* bn)
+{
+    (void)bn;
+
+    WOLFSSL_MSG("wolfSSL_BN_bn2dec");
+
+    return NULL;
+}
+#endif /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) */
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 else
+ */
+int wolfSSL_BN_lshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n)
+{
+    WOLFSSL_MSG("wolfSSL_BN_lshift");
+
+    if (r == NULL || r->internal == NULL || bn == NULL || bn->internal == NULL){
+        WOLFSSL_MSG("bn NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (mp_mul_2d((mp_int*)bn->internal, n, (mp_int*)r->internal) != MP_OKAY) {
+        WOLFSSL_MSG("mp_mul_2d error");
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 else
+ */
+int wolfSSL_BN_rshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n)
+{
+    WOLFSSL_MSG("wolfSSL_BN_rshift");
+
+    if (r == NULL || r->internal == NULL || bn == NULL || bn->internal == NULL){
+        WOLFSSL_MSG("bn NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (mp_div_2d((mp_int*)bn->internal, n,
+                  (mp_int*)r->internal, NULL) != MP_OKAY) {
+        WOLFSSL_MSG("mp_mul_2d error");
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 else
+ */
+int wolfSSL_BN_add_word(WOLFSSL_BIGNUM *bn, WOLFSSL_BN_ULONG w)
+{
+    WOLFSSL_MSG("wolfSSL_BN_add_word");
+
+    if (bn == NULL || bn->internal == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (mp_add_d((mp_int*)bn->internal, w, (mp_int*)bn->internal) != MP_OKAY) {
+        WOLFSSL_MSG("mp_add_d error");
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 else
+ */
+int wolfSSL_BN_add(WOLFSSL_BIGNUM *r, WOLFSSL_BIGNUM *a, WOLFSSL_BIGNUM *b)
+{
+    WOLFSSL_MSG("wolfSSL_BN_add");
+
+    if (r == NULL || r->internal == NULL || a == NULL || a->internal == NULL ||
+        b == NULL || b->internal == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (mp_add((mp_int*)a->internal, (mp_int*)b->internal,
+               (mp_int*)r->internal) != MP_OKAY) {
+        WOLFSSL_MSG("mp_add_d error");
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* r = a + b (mod m) */
+int wolfSSL_BN_mod_add(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a,
+                       const WOLFSSL_BIGNUM *b, const WOLFSSL_BIGNUM *m,
+                       WOLFSSL_BN_CTX *ctx)
+{
+    (void)ctx;
+    WOLFSSL_MSG("wolfSSL_BN_add");
+
+    if (r == NULL || r->internal == NULL ||
+            a == NULL || a->internal == NULL ||
+            b == NULL || b->internal == NULL ||
+            m == NULL || m->internal == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (mp_addmod((mp_int*)a->internal, (mp_int*)b->internal,
+                  (mp_int*)m->internal, (mp_int*)r->internal) != MP_OKAY) {
+        WOLFSSL_MSG("mp_add_d error");
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+#ifdef WOLFSSL_KEY_GEN
+
+/* return code compliant with OpenSSL :
+ *   1 if prime, 0 if not, -1 if error
+ */
+int wolfSSL_BN_is_prime_ex(const WOLFSSL_BIGNUM *bn, int nbchecks,
+                           WOLFSSL_BN_CTX *ctx, WOLFSSL_BN_GENCB *cb)
+{
+    WC_RNG*        rng    = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG*        tmpRNG = NULL;
+#else
+    WC_RNG         tmpRNG[1];
+#endif
+    int            initTmpRng = 0;
+    int            res = MP_NO;
+
+    (void)ctx;
+    (void)cb;
+
+    WOLFSSL_MSG("wolfSSL_BN_is_prime_ex");
+
+    if (bn == NULL || bn->internal == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+    if (tmpRNG == NULL)
+        return WOLFSSL_FAILURE;
+#endif
+    if (wc_InitRng(tmpRNG) == 0) {
+        rng = tmpRNG;
+        initTmpRng = 1;
+    }
+    else {
+        WOLFSSL_MSG("Bad RNG Init, trying global");
+        if (initGlobalRNG == 0) {
+            WOLFSSL_MSG("Global RNG no Init");
+        }
+        else
+            rng = &globalRNG;
+    }
+
+    if (rng) {
+        if (mp_prime_is_prime_ex((mp_int*)bn->internal,
+                                 nbchecks, &res, rng) != MP_OKAY) {
+            WOLFSSL_MSG("mp_prime_is_prime_ex error");
+            res = MP_NO;
+        }
+    }
+
+    if (initTmpRng)
+        wc_FreeRng(tmpRNG);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+    if (res != MP_YES) {
+        WOLFSSL_MSG("mp_prime_is_prime_ex not prime");
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* return code compliant with OpenSSL :
+ *   (bn mod w) if success, -1 if error
+ */
+WOLFSSL_BN_ULONG wolfSSL_BN_mod_word(const WOLFSSL_BIGNUM *bn,
+                                     WOLFSSL_BN_ULONG w)
+{
+    WOLFSSL_BN_ULONG ret = 0;
+
+    WOLFSSL_MSG("wolfSSL_BN_mod_word");
+
+    if (bn == NULL || bn->internal == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return (WOLFSSL_BN_ULONG)WOLFSSL_FATAL_ERROR;
+    }
+
+    if (mp_mod_d((mp_int*)bn->internal, w, &ret) != MP_OKAY) {
+        WOLFSSL_MSG("mp_add_d error");
+        return (WOLFSSL_BN_ULONG)WOLFSSL_FATAL_ERROR;
+    }
+
+    return ret;
+}
+#endif /* #ifdef WOLFSSL_KEY_GEN */
+
+char *wolfSSL_BN_bn2hex(const WOLFSSL_BIGNUM *bn)
+{
+    int len = 0;
+    char *buf;
+
+    WOLFSSL_ENTER("wolfSSL_BN_bn2hex");
+
+    if (bn == NULL || bn->internal == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return NULL;
+    }
+
+    if (mp_radix_size((mp_int*)bn->internal, MP_RADIX_HEX, &len) != MP_OKAY) {
+        WOLFSSL_MSG("mp_radix_size failure");
+        return NULL;
+    }
+    len += 1; /* add one for null terminator */
+
+    buf = (char*)XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL);
+    if (buf == NULL) {
+        WOLFSSL_MSG("BN_bn2hex malloc buffer failure");
+        return NULL;
+    }
+
+    if (mp_tohex((mp_int*)bn->internal, buf) != MP_OKAY) {
+        XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL);
+        return NULL;
+    }
+
+    return buf;
+}
+
+#ifndef NO_FILESYSTEM
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_BN_print_fp(XFILE fp, const WOLFSSL_BIGNUM *bn)
+{
+    char *buf;
+
+    WOLFSSL_ENTER("wolfSSL_BN_print_fp");
+
+    if (fp == XBADFILE || bn == NULL || bn->internal == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    buf = wolfSSL_BN_bn2hex(bn);
+    if (buf == NULL) {
+        WOLFSSL_MSG("wolfSSL_BN_bn2hex failure");
+        return WOLFSSL_FAILURE;
+    }
+
+    fprintf(fp, "%s", buf);
+    XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL);
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* !NO_FILESYSTEM */
+
+
+WOLFSSL_BIGNUM *wolfSSL_BN_CTX_get(WOLFSSL_BN_CTX *ctx)
+{
+    /* ctx is not used, return new Bignum */
+    (void)ctx;
+
+    WOLFSSL_ENTER("wolfSSL_BN_CTX_get");
+
+    return wolfSSL_BN_new();
+}
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_BN_CTX_start(WOLFSSL_BN_CTX *ctx)
+{
+    (void)ctx;
+
+    WOLFSSL_ENTER("wolfSSL_BN_CTX_start");
+    WOLFSSL_STUB("BN_CTX_start");
+    WOLFSSL_MSG("wolfSSL_BN_CTX_start TBD");
+}
+#endif
+
+
+WOLFSSL_BIGNUM *wolfSSL_BN_mod_inverse(WOLFSSL_BIGNUM *r,
+                                       WOLFSSL_BIGNUM *a,
+                                       const WOLFSSL_BIGNUM *n,
+                                       WOLFSSL_BN_CTX *ctx)
+{
+    int dynamic = 0;
+
+    /* ctx is not used */
+    (void)ctx;
+
+    WOLFSSL_ENTER("wolfSSL_BN_mod_inverse");
+
+    /* check parameter */
+    if (r == NULL) {
+        r = wolfSSL_BN_new();
+        if (r == NULL){
+            WOLFSSL_MSG("WolfSSL_BN_new() failed");
+            return NULL;
+        }
+        dynamic = 1;
+    }
+
+    if (a == NULL) {
+        WOLFSSL_MSG("a NULL error");
+        if (dynamic == 1) {
+            wolfSSL_BN_free(r);
+        }
+        return NULL;
+    }
+
+    if (n == NULL) {
+        WOLFSSL_MSG("n NULL error");
+        if (dynamic == 1) {
+            wolfSSL_BN_free(r);
+        }
+        return NULL;
+    }
+
+    /* Compute inverse of a modulo n and return r */
+    if (mp_invmod((mp_int *)a->internal,(mp_int *)n->internal,
+                  (mp_int*)r->internal) == MP_VAL){
+        WOLFSSL_MSG("mp_invmod() error");
+        if (dynamic == 1) {
+            wolfSSL_BN_free(r);
+        }
+        return NULL;
+    }
+
+    return  r;
+}
+#endif  /* OPENSSL_EXTRA */
+#if (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) && !defined(NO_ASN)
+static int unprintable_char(char c)
+{
+    const unsigned char last_unprintable = 31;
+    const unsigned char LF = 10;
+    const unsigned char CR = 13;
+
+    if (c <= last_unprintable && c != LF && c != CR) {
+        return 1;
+    }
+    return 0;
+}
+
+int wolfSSL_ASN1_STRING_print(WOLFSSL_BIO *out, WOLFSSL_ASN1_STRING *str)
+{
+    int i;
+
+    WOLFSSL_ENTER("wolfSSL_ASN1_STRING_print");
+    if (out == NULL || str == NULL)
+           return WOLFSSL_FAILURE;
+
+    for (i=0; i < str->length; i++) {
+        if (unprintable_char(str->data[i])) {
+            str->data[i] = '.';
+        }
+    }
+
+    if (wolfSSL_BIO_write(out, str->data, str->length) != str->length){
+        return WOLFSSL_FAILURE;
+    }
+
+    return str->length;
+}
+#endif /* (WOLFSSL_QT || OPENSSL_ALL) && !NO_ASN */
+
+#if defined(OPENSSL_EXTRA)
+int wolfSSL_X509_check_ca(WOLFSSL_X509 *x509)
+{
+    WOLFSSL_ENTER("X509_check_ca");
+
+    if (x509 == NULL)
+        return WOLFSSL_FAILURE;
+    if (x509->isCa)
+        return 1;
+    if (x509->extKeyUsageCrit)
+        return 4;
+
+    return 0;
+}
+
+
+const char *wolfSSL_ASN1_tag2str(int tag)
+{
+    static const char *const tag_label[31] = {
+        "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", "NULL",
+        "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", "ENUMERATED",
+        "<ASN1 11>", "UTF8STRING", "<ASN1 13>", "<ASN1 14>", "<ASN1 15>",
+        "SEQUENCE", "SET", "NUMERICSTRING", "PRINTABLESTRING", "T61STRING",
+        "VIDEOTEXTSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME",
+        "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", "UNIVERSALSTRING",
+        "<ASN1 29>", "BMPSTRING"
+    };
+
+    if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
+        tag &= ~0x100;
+    if (tag < 0 || tag > 30)
+        return "(unknown)";
+    return tag_label[tag];
+}
+
+static int check_esc_char(char c, char *esc)
+{
+    char *ptr;
+
+    ptr = esc;
+    while(*ptr != 0){
+        if (c == *ptr)
+            return 1;
+        ptr++;
+    }
+    return 0;
+}
+
+int wolfSSL_ASN1_STRING_print_ex(WOLFSSL_BIO *out, WOLFSSL_ASN1_STRING *str,
+                                 unsigned long flags)
+{
+    size_t str_len = 0, type_len = 0;
+    unsigned char *typebuf = NULL;
+    const char *hash="#";
+
+    WOLFSSL_ENTER("wolfSSL_ASN1_STRING_PRINT_ex");
+    if (out == NULL || str == NULL)
+        return WOLFSSL_FAILURE;
+
+    /* add ASN1 type tag */
+    if (flags & ASN1_STRFLGS_SHOW_TYPE){
+        const char *tag = wolfSSL_ASN1_tag2str(str->type);
+        /* colon len + tag len + null*/
+        type_len = XSTRLEN(tag) + 2;
+        typebuf = (unsigned char *)XMALLOC(type_len , NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (typebuf == NULL){
+            WOLFSSL_MSG("memory alloc failed.");
+            return WOLFSSL_FAILURE;
+        }
+        XMEMSET(typebuf, 0, type_len);
+        XSNPRINTF((char*)typebuf, (size_t)type_len , "%s:", tag);
+        type_len--;
+    }
+
+    /* dump hex */
+    if (flags & ASN1_STRFLGS_DUMP_ALL){
+        static const char hex_char[] = { '0', '1', '2', '3', '4', '5', '6',
+                                         '7','8', '9', 'A', 'B', 'C', 'D',
+                                         'E', 'F' };
+        char hex_tmp[4];
+        char *str_ptr, *str_end;
+
+        if (type_len > 0){
+            if (wolfSSL_BIO_write(out, typebuf, (int)type_len) != (int)type_len){
+                XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                return WOLFSSL_FAILURE;
+            }
+            str_len += type_len;
+        }
+        if (wolfSSL_BIO_write(out, hash, 1) != 1){
+            goto err_exit;
+        }
+        str_len++;
+        if (flags & ASN1_STRFLGS_DUMP_DER){
+            hex_tmp[0] = hex_char[str->type >> 4];
+            hex_tmp[1] = hex_char[str->type & 0xf];
+            hex_tmp[2] = hex_char[str->length >> 4];
+            hex_tmp[3] = hex_char[str->length & 0xf];
+            if (wolfSSL_BIO_write(out, hex_tmp, 4) != 4){
+                goto err_exit;
+            }
+            str_len += 4;
+            XMEMSET(hex_tmp, 0, 4);
+        }
+
+        str_ptr = str->data;
+        str_end = str->data + str->length;
+        while (str_ptr < str_end){
+            hex_tmp[0] = hex_char[*str_ptr >> 4];
+            hex_tmp[1] = hex_char[*str_ptr & 0xf];
+            if (wolfSSL_BIO_write(out, hex_tmp, 2) != 2){
+                goto err_exit;
+            }
+            str_ptr++;
+            str_len += 2;
+        }
+        if (type_len > 0)
+            XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+        return (int)str_len;
+    }
+
+    if (type_len > 0){
+        if (wolfSSL_BIO_write(out, typebuf, (int)type_len) != (int)type_len){
+            XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            return WOLFSSL_FAILURE;
+        }
+        str_len += type_len;
+    }
+
+    if (flags & ASN1_STRFLGS_ESC_2253){
+        char esc_ch[] = "+;<>\\";
+        char* esc_ptr;
+
+        esc_ptr = str->data;
+        while (*esc_ptr != 0){
+            if (check_esc_char(*esc_ptr, esc_ch)){
+                if (wolfSSL_BIO_write(out,"\\", 1) != 1)
+                    goto err_exit;
+                str_len++;
+            }
+            if (wolfSSL_BIO_write(out, esc_ptr, 1) != 1)
+                goto err_exit;
+            str_len++;
+            esc_ptr++;
+        }
+        if (type_len > 0)
+            XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return (int)str_len;
+    }
+
+    if (wolfSSL_BIO_write(out, str->data, str->length) != str->length){
+        goto err_exit;
+    }
+    str_len += str->length;
+    if (type_len > 0)
+        XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+    return (int)str_len;
+
+err_exit:
+    if (type_len > 0)
+        XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    return WOLFSSL_FAILURE;
+}
+
+#if !defined(NO_ASN_TIME) && !defined(USER_TIME) && !defined(TIME_OVERRIDES)
+WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_new(void)
+{
+    WOLFSSL_ASN1_TIME* ret = (WOLFSSL_ASN1_TIME*)
+            XMALLOC(sizeof(WOLFSSL_ASN1_TIME), NULL, DYNAMIC_TYPE_OPENSSL);
+    if (!ret)
+        return NULL;
+    XMEMSET(ret, 0, sizeof(WOLFSSL_ASN1_TIME));
+    return ret;
+}
+
+void wolfSSL_ASN1_TIME_free(WOLFSSL_ASN1_TIME* t)
+{
+    if (t) {
+        XFREE(t, NULL, DYNAMIC_TYPE_OPENSSL);
+    }
+}
+
+WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_adj(WOLFSSL_ASN1_TIME *s, time_t t,
+                                    int offset_day, long offset_sec)
+{
+    const time_t sec_per_day = 24*60*60;
+    struct tm* ts = NULL;
+    struct tm* tmpTime;
+    time_t t_adj = 0;
+    time_t offset_day_sec = 0;
+#if defined(NEED_TMP_TIME)
+    struct tm tmpTimeStorage;
+
+    tmpTime = &tmpTimeStorage;
+#else
+    tmpTime = NULL;
+#endif
+    (void)tmpTime;
+
+    WOLFSSL_ENTER("wolfSSL_ASN1_TIME_adj");
+
+    if (s == NULL){
+        s = wolfSSL_ASN1_TIME_new();
+        if (s == NULL){
+            return NULL;
+        }
+    }
+
+    /* compute GMT time with offset */
+    offset_day_sec = offset_day * sec_per_day;
+    t_adj          = t + offset_day_sec + offset_sec;
+    ts             = (struct tm *)XGMTIME(&t_adj, tmpTime);
+    if (ts == NULL){
+        WOLFSSL_MSG("failed to get time data.");
+        XFREE(s, NULL, DYNAMIC_TYPE_OPENSSL);
+        return NULL;
+    }
+
+    /* create ASN1 time notation */
+    /* UTC Time */
+    if (ts->tm_year >= 50 && ts->tm_year < 150){
+        char utc_str[ASN_UTC_TIME_SIZE];
+        int utc_year = 0,utc_mon,utc_day,utc_hour,utc_min,utc_sec;
+
+        s->type = V_ASN1_UTCTIME;
+        s->length = ASN_UTC_TIME_SIZE;
+
+        if (ts->tm_year >= 50 && ts->tm_year < 100){
+            utc_year = ts->tm_year;
+        } else if (ts->tm_year >= 100 && ts->tm_year < 150){
+            utc_year = ts->tm_year - 100;
+        }
+        utc_mon  = ts->tm_mon + 1;
+        utc_day  = ts->tm_mday;
+        utc_hour = ts->tm_hour;
+        utc_min  = ts->tm_min;
+        utc_sec  = ts->tm_sec;
+        XSNPRINTF((char *)utc_str, sizeof(utc_str),
+                  "%02d%02d%02d%02d%02d%02dZ",
+                  utc_year, utc_mon, utc_day, utc_hour, utc_min, utc_sec);
+        XMEMCPY(s->data, (byte *)utc_str, s->length);
+    /* GeneralizedTime */
+    } else {
+        char gt_str[ASN_GENERALIZED_TIME_MAX];
+        int gt_year,gt_mon,gt_day,gt_hour,gt_min,gt_sec;
+
+        s->type = V_ASN1_GENERALIZEDTIME;
+        s->length = ASN_GENERALIZED_TIME_SIZE;
+
+        gt_year = ts->tm_year + 1900;
+        gt_mon  = ts->tm_mon + 1;
+        gt_day  = ts->tm_mday;
+        gt_hour = ts->tm_hour;
+        gt_min  = ts->tm_min;
+        gt_sec  = ts->tm_sec;
+        XSNPRINTF((char *)gt_str, sizeof(gt_str),
+                  "%4d%02d%02d%02d%02d%02dZ",
+                  gt_year, gt_mon, gt_day, gt_hour, gt_min,gt_sec);
+        XMEMCPY(s->data, (byte *)gt_str, s->length);
+    }
+
+    return s;
+}
+#endif /* !NO_ASN_TIME && !USER_TIME && !TIME_OVERRIDES */
+
+#ifndef NO_ASN_TIME
+/* not a compatibility function - length getter for opaque type */
+int wolfSSL_ASN1_TIME_get_length(WOLFSSL_ASN1_TIME *t)
+{
+    WOLFSSL_ENTER("wolfSSL_ASN1_TIME_get_length");
+    if (t == NULL)
+        return WOLFSSL_FAILURE;
+    return t->length;
+}
+/* not a compatibility function - data getter for opaque type */
+unsigned char* wolfSSL_ASN1_TIME_get_data(WOLFSSL_ASN1_TIME *t)
+{
+    WOLFSSL_ENTER("wolfSSL_ASN1_TIME_get_data");
+    if (t == NULL)
+        return NULL;
+    return t->data;
+}
+
+WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_to_generalizedtime(WOLFSSL_ASN1_TIME *t,
+                                                        WOLFSSL_ASN1_TIME **out)
+{
+    int time_type = 0;
+    WOLFSSL_ASN1_TIME *ret = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_ASN1_TIME_to_generalizedtime");
+    if (t == NULL) {
+        WOLFSSL_MSG("Invalid ASN_TIME value");
+    } else {
+        time_type = t->type;
+        if (time_type != ASN_UTC_TIME && time_type != ASN_GENERALIZED_TIME){
+            WOLFSSL_MSG("Invalid ASN_TIME type.");
+        } else {
+            if (out == NULL || *out == NULL) {
+                ret = wolfSSL_ASN1_TIME_new();
+                if (ret == NULL){
+                    WOLFSSL_MSG("memory alloc failed.");
+                }
+            } else {
+                ret = *out;
+            }
+        }
+    }
+
+    if (ret != NULL) {
+        if (time_type == ASN_GENERALIZED_TIME){
+            XMEMCPY(ret->data, t->data, ASN_GENERALIZED_TIME_SIZE);
+        } else { /* ASN_UTC_TIME */
+            /* convert UTC to generalized time */
+            ret->type = ASN_GENERALIZED_TIME;
+            ret->length = ASN_GENERALIZED_TIME_SIZE;
+            if (t->data[0] >= '5') {
+                ret->data[0] = '1'; ret->data[1] = '9';
+            } else {
+                ret->data[0] = '2'; ret->data[1] = '0';
+            }
+            XMEMCPY(&ret->data[2], t->data, ASN_UTC_TIME_SIZE);
+        }
+    }
+
+    return ret;
+}
+#endif /* !NO_ASN_TIME */
+
+#ifndef NO_ASN
+int wolfSSL_i2c_ASN1_INTEGER(WOLFSSL_ASN1_INTEGER *a, unsigned char **pp)
+{
+    unsigned char *pptr = NULL;
+    char pad = 0 ;
+    unsigned char pad_val = 0;
+    int ret_size = 0;
+    unsigned char data1 = 0;
+    unsigned char neg = 0;
+    int i = 0;
+
+    WOLFSSL_ENTER("wolfSSL_i2c_ASN1_INTEGER");
+    if (a == NULL)
+        return WOLFSSL_FAILURE;
+
+    ret_size = a->intData[1];
+    if (ret_size == 0)
+        ret_size = 1;
+    else{
+        ret_size = (int)a->intData[1];
+        neg = a->negative;
+        data1 = a->intData[2];
+        if (ret_size == 1 && data1 == 0)
+            neg = 0;
+        /* 0x80 or greater positive number in first byte */
+        if (!neg && (data1 > 127)){
+            pad = 1;
+            pad_val = 0;
+        } else if (neg){
+            /* negative number */
+            if (data1 > 128){
+                pad = 1;
+                pad_val = 0xff;
+            } else if (data1 == 128){
+                for (i = 3; i < a->intData[1] + 2; i++){
+                    if (a->intData[i]){
+                        pad = 1;
+                        pad_val = 0xff;
+                        break;
+                    }
+                }
+            }
+        }
+        ret_size += (int)pad;
+    }
+    if (pp == NULL)
+        return ret_size;
+
+    pptr = *pp;
+    if (pad)
+        *(pptr++) = pad_val;
+    if (a->intData[1] == 0)
+        *(pptr++) = 0;
+    else if (!neg){
+        /* positive number */
+        for (i=0; i < a->intData[1]; i++){
+            *pptr = a->intData[i+2];
+            pptr++;
+        }
+    } else {
+        /* negative number */
+        int str_len = 0;
+
+        /* 0 padding from end of buffer */
+        str_len = (int)a->intData[1];
+        pptr += a->intData[1] - 1;
+        while (!a->intData[str_len + 2] && str_len > 1){
+            *(pptr--) = 0;
+            str_len--;
+        }
+        /* 2's complement next octet */
+        *(pptr--) = ((a->intData[str_len + 1]) ^ 0xff) + 1;
+        str_len--;
+        /* Complement any octets left */
+        while (str_len > 0){
+            *(pptr--) = a->intData[str_len + 1] ^ 0xff;
+            str_len--;
+        }
+    }
+    *pp += ret_size;
+    return ret_size;
+}
+#endif /* !NO_ASN */
+
+
+#ifndef NO_CERTS
+int wolfSSL_X509_CA_num(WOLFSSL_X509_STORE* store)
+{
+    int i = 0;
+    int cnt_ret = 0;
+    Signer **table;
+
+    WOLFSSL_ENTER("wolfSSL_X509_CA_num");
+    if (store == NULL || store->cm == NULL){
+        WOLFSSL_MSG("invalid parameter");
+        return WOLFSSL_FAILURE;
+    }
+
+    table = store->cm->caTable;
+    if (table){
+        if (wc_LockMutex(&store->cm->caLock) == 0){
+            for (i = 0; i < CA_TABLE_SIZE; i++) {
+                Signer* signer = table[i];
+                while (signer) {
+                    Signer* next = signer->next;
+                    cnt_ret++;
+                    signer = next;
+                }
+            }
+            wc_UnLockMutex(&store->cm->caLock);
+        }
+    }
+
+    return cnt_ret;
+}
+#endif /* !NO_CERTS */
+
+long wolfSSL_X509_get_version(const WOLFSSL_X509 *x509)
+{
+    int version = 0;
+
+    WOLFSSL_ENTER("wolfSSL_X509_get_version");
+
+    if (x509 == NULL){
+        WOLFSSL_MSG("invalid parameter");
+        return 0L;
+    }
+    version = x509->version;
+    if (version != 0)
+        return (long)version - 1L;
+
+    return 0L;
+}
+
+
+int wolfSSL_X509_get_signature_nid(const WOLFSSL_X509 *x)
+{
+    if (x == NULL)
+        return 0;
+
+    return oid2nid(x->sigOID, oidSigType);
+}
+#endif  /* OPENSSL_EXTRA */
+
+#if defined(OPENSSL_EXTRA) && !defined(NO_RSA)
+/* return compliant with OpenSSL
+ *   RSA modulus size in bytes, -1 if error
+ */
+int wolfSSL_RSA_size(const WOLFSSL_RSA* rsa)
+{
+    WOLFSSL_ENTER("wolfSSL_RSA_size");
+
+    if (rsa == NULL)
+        return WOLFSSL_FATAL_ERROR;
+    if (rsa->inSet == 0)
+    {
+        if (SetRsaInternal((WOLFSSL_RSA*)rsa) != SSL_SUCCESS) {
+            WOLFSSL_MSG("SetRsaInternal failed");
+            return 0;
+        }
+    }
+    return wc_RsaEncryptSize((RsaKey*)rsa->internal);
+}
+#endif
+
+#if !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) && \
+    !defined(NO_RSA) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
+/* WolfSSL -> OpenSSL */
+int SetRsaExternal(WOLFSSL_RSA* rsa)
+{
+    RsaKey* key;
+    WOLFSSL_MSG("Entering SetRsaExternal");
+
+    if (rsa == NULL || rsa->internal == NULL) {
+        WOLFSSL_MSG("rsa key NULL error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    key = (RsaKey*)rsa->internal;
+
+    if (SetIndividualExternal(&rsa->n, &key->n) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa n key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (SetIndividualExternal(&rsa->e, &key->e) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa e key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (key->type == RSA_PRIVATE) {
+        if (SetIndividualExternal(&rsa->d, &key->d) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("rsa d key error");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        if (SetIndividualExternal(&rsa->p, &key->p) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("rsa p key error");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        if (SetIndividualExternal(&rsa->q, &key->q) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("rsa q key error");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+    #ifndef RSA_LOW_MEM
+        if (SetIndividualExternal(&rsa->dmp1, &key->dP) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("rsa dP key error");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        if (SetIndividualExternal(&rsa->dmq1, &key->dQ) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("rsa dQ key error");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        if (SetIndividualExternal(&rsa->iqmp, &key->u) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("rsa u key error");
+            return WOLFSSL_FATAL_ERROR;
+        }
+    #endif /* !RSA_LOW_MEM */
+    }
+    rsa->exSet = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+/* when calling SetIndividualExternal, mpi should be cleared by caller if no
+ * longer used. ie mp_free(mpi). This is to free data when fastmath is
+ * disabled since a copy of mpi is made by this function and placed into bn.
+ */
+int SetIndividualExternal(WOLFSSL_BIGNUM** bn, mp_int* mpi)
+{
+    byte dynamic = 0;
+
+    WOLFSSL_MSG("Entering SetIndividualExternal");
+
+    if (mpi == NULL || bn == NULL) {
+        WOLFSSL_MSG("mpi NULL error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (*bn == NULL) {
+        *bn = wolfSSL_BN_new();
+        if (*bn == NULL) {
+            WOLFSSL_MSG("SetIndividualExternal alloc failed");
+            return WOLFSSL_FATAL_ERROR;
+        }
+        dynamic = 1;
+    }
+
+    if (mp_copy(mpi, (mp_int*)((*bn)->internal)) != MP_OKAY) {
+        WOLFSSL_MSG("mp_copy error");
+        if (dynamic == 1) {
+            wolfSSL_BN_free(*bn);
+        }
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+static void InitwolfSSL_BigNum(WOLFSSL_BIGNUM* bn)
+{
+    if (bn) {
+        XMEMSET(bn, 0, sizeof(WOLFSSL_BIGNUM));
+        bn->neg      = 0;
+        bn->internal = NULL;
+    }
+}
+
+
+WOLFSSL_BIGNUM* wolfSSL_BN_new(void)
+{
+    WOLFSSL_BIGNUM* external;
+    mp_int*        mpi;
+
+    WOLFSSL_MSG("wolfSSL_BN_new");
+
+#if !defined(USE_FAST_MATH) || defined(HAVE_WOLF_BIGINT)
+    mpi = (mp_int*) XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
+    if (mpi == NULL) {
+        WOLFSSL_MSG("wolfSSL_BN_new malloc mpi failure");
+        return NULL;
+    }
+#endif
+
+    external = (WOLFSSL_BIGNUM*) XMALLOC(sizeof(WOLFSSL_BIGNUM), NULL,
+                                        DYNAMIC_TYPE_BIGINT);
+    if (external == NULL) {
+        WOLFSSL_MSG("wolfSSL_BN_new malloc WOLFSSL_BIGNUM failure");
+#if !defined(USE_FAST_MATH) || defined(HAVE_WOLF_BIGINT)
+        XFREE(mpi, NULL, DYNAMIC_TYPE_BIGINT);
+#endif
+        return NULL;
+    }
+
+#if defined(USE_FAST_MATH) && !defined(HAVE_WOLF_BIGINT)
+    mpi = &external->fp;
+#endif
+
+    InitwolfSSL_BigNum(external);
+    if (mp_init(mpi) != MP_OKAY) {
+        wolfSSL_BN_free(external);
+        return NULL;
+    }
+    external->internal = mpi;
+
+    return external;
+}
+
+
+#if defined(USE_FAST_MATH) && !defined(HAVE_WOLF_BIGINT)
+/* This function works without BN_free only with TFM */
+void wolfSSL_BN_init(WOLFSSL_BIGNUM* bn)
+{
+    if(bn == NULL)return;
+    WOLFSSL_MSG("wolfSSL_BN_init");
+    InitwolfSSL_BigNum(bn);
+    if (mp_init(&bn->fp) != MP_OKAY)
+        return;
+    bn->internal = (void *)&bn->fp;
+}
+#endif
+
+void wolfSSL_BN_free(WOLFSSL_BIGNUM* bn)
+{
+    WOLFSSL_MSG("wolfSSL_BN_free");
+    if (bn) {
+        if (bn->internal) {
+            mp_int* bni = (mp_int*)bn->internal;
+            mp_free(bni);
+#if !defined(USE_FAST_MATH) || defined(HAVE_WOLF_BIGINT)
+            XFREE(bn->internal, NULL, DYNAMIC_TYPE_BIGINT);
+#endif
+            bn->internal = NULL;
+        }
+        XFREE(bn, NULL, DYNAMIC_TYPE_BIGINT);
+        /* bn = NULL, don't try to access or double free it */
+    }
+}
+
+void wolfSSL_BN_clear_free(WOLFSSL_BIGNUM* bn)
+{
+    WOLFSSL_MSG("wolfSSL_BN_clear_free");
+    if (bn) {
+        if (bn->internal) {
+            mp_int* bni = (mp_int*)bn->internal;
+            mp_forcezero(bni);
+        }
+        wolfSSL_BN_free(bn);
+    }
+}
+
+void wolfSSL_BN_clear(WOLFSSL_BIGNUM* bn)
+{
+    WOLFSSL_MSG("wolfSSL_BN_clear");
+    if (bn && bn->internal) {
+        mp_forcezero((mp_int*)bn->internal);
+    }
+}
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+
+#if !defined(NO_RSA) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
+static void InitwolfSSL_Rsa(WOLFSSL_RSA* rsa)
+{
+    if (rsa) {
+        XMEMSET(rsa, 0, sizeof(WOLFSSL_RSA));
+    }
+}
+
+
+void wolfSSL_RSA_free(WOLFSSL_RSA* rsa)
+{
+    WOLFSSL_ENTER("wolfSSL_RSA_free");
+
+    if (rsa) {
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
+        int doFree = 0;
+        if (wc_LockMutex(&rsa->refMutex) != 0) {
+            WOLFSSL_MSG("Couldn't lock rsa mutex");
+        }
+
+        /* only free if all references to it are done */
+        rsa->refCount--;
+        if (rsa->refCount == 0) {
+            doFree = 1;
+        }
+        wc_UnLockMutex(&rsa->refMutex);
+
+        if (!doFree) {
+            return;
+        }
+
+        wc_FreeMutex(&rsa->refMutex);
+#endif
+
+        if (rsa->internal) {
+#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && \
+    !defined(HAVE_FAST_RSA) && defined(WC_RSA_BLINDING)
+            WC_RNG* rng;
+
+            /* check if RNG is owned before freeing it */
+            if (rsa->ownRng) {
+                rng = ((RsaKey*)rsa->internal)->rng;
+                if (rng != NULL && rng != &globalRNG) {
+                    wc_FreeRng(rng);
+                    XFREE(rng, NULL, DYNAMIC_TYPE_RNG);
+                }
+            }
+#endif /* WC_RSA_BLINDING */
+            wc_FreeRsaKey((RsaKey*)rsa->internal);
+            XFREE(rsa->internal, NULL, DYNAMIC_TYPE_RSA);
+            rsa->internal = NULL;
+        }
+        wolfSSL_BN_free(rsa->iqmp);
+        wolfSSL_BN_free(rsa->dmq1);
+        wolfSSL_BN_free(rsa->dmp1);
+        wolfSSL_BN_free(rsa->q);
+        wolfSSL_BN_free(rsa->p);
+        wolfSSL_BN_free(rsa->d);
+        wolfSSL_BN_free(rsa->e);
+        wolfSSL_BN_free(rsa->n);
+
+    #ifdef WC_RSA_BLINDING
+        if (rsa->rng && wc_FreeRng(rsa->rng) != 0) {
+            WOLFSSL_MSG("Issue freeing rng");
+        }
+        XFREE(rsa->rng, NULL, DYNAMIC_TYPE_RNG);
+    #endif
+
+#if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY)
+        if (rsa->meth) {
+            wolfSSL_RSA_meth_free(rsa->meth);
+        }
+#endif
+
+        InitwolfSSL_Rsa(rsa);  /* set back to NULLs for safety */
+
+        XFREE(rsa, NULL, DYNAMIC_TYPE_RSA);
+
+        /* rsa = NULL, don't try to access or double free it */
+    }
+}
+
+WOLFSSL_RSA* wolfSSL_RSA_new(void)
+{
+    WOLFSSL_RSA* external;
+    RsaKey*     key;
+
+    WOLFSSL_ENTER("wolfSSL_RSA_new");
+
+    key = (RsaKey*) XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA);
+    if (key == NULL) {
+        WOLFSSL_MSG("wolfSSL_RSA_new malloc RsaKey failure");
+        return NULL;
+    }
+
+    external = (WOLFSSL_RSA*) XMALLOC(sizeof(WOLFSSL_RSA), NULL,
+                                     DYNAMIC_TYPE_RSA);
+    if (external == NULL) {
+        WOLFSSL_MSG("wolfSSL_RSA_new malloc WOLFSSL_RSA failure");
+        XFREE(key, NULL, DYNAMIC_TYPE_RSA);
+        return NULL;
+    }
+
+    InitwolfSSL_Rsa(external);
+    if (wc_InitRsaKey(key, NULL) != 0) {
+        WOLFSSL_MSG("InitRsaKey WOLFSSL_RSA failure");
+        XFREE(external, NULL, DYNAMIC_TYPE_RSA);
+        XFREE(key, NULL, DYNAMIC_TYPE_RSA);
+        return NULL;
+    }
+
+#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && \
+    !defined(HAVE_FAST_RSA) && defined(WC_RSA_BLINDING)
+    {
+        WC_RNG* rng;
+
+        rng = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+        if (rng != NULL && wc_InitRng(rng) != 0) {
+            WOLFSSL_MSG("InitRng failure, attempting to use global RNG");
+            XFREE(rng, NULL, DYNAMIC_TYPE_RNG);
+            rng = NULL;
+        }
+
+        external->ownRng = 1;
+        if (rng == NULL && initGlobalRNG) {
+            external->ownRng = 0;
+            rng = &globalRNG;
+        }
+
+        if (rng == NULL) {
+            WOLFSSL_MSG("wolfSSL_RSA_new no WC_RNG for blinding");
+            XFREE(external, NULL, DYNAMIC_TYPE_RSA);
+            XFREE(key, NULL, DYNAMIC_TYPE_RSA);
+            return NULL;
+        }
+
+        wc_RsaSetRNG(key, rng);
+    }
+#else
+    XMEMSET(key, 0, sizeof(RsaKey));
+#endif /* WC_RSA_BLINDING */
+
+    external->internal = key;
+    external->inSet = 0;
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
+    external->refCount = 1;
+    wc_InitMutex(&external->refMutex);
+#endif
+    return external;
+}
+#endif /* !NO_RSA && (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL) */
+
+#if defined(OPENSSL_ALL) && defined(HAVE_PKCS7)
+PKCS7* wolfSSL_PKCS7_new(void)
+{
+    WOLFSSL_PKCS7* pkcs7;
+    int ret = 0;
+
+    pkcs7 = (WOLFSSL_PKCS7*)XMALLOC(sizeof(*pkcs7), NULL, DYNAMIC_TYPE_PKCS7);
+    if (pkcs7 != NULL) {
+        XMEMSET(pkcs7, 0, sizeof(*pkcs7));
+        ret = wc_PKCS7_Init(&pkcs7->pkcs7, NULL, INVALID_DEVID);
+    }
+
+    if (ret != 0 && pkcs7 != NULL)
+        XFREE(pkcs7, NULL, DYNAMIC_TYPE_PKCS7);
+
+    return (PKCS7*)pkcs7;
+}
+/******************************************************************************
+* wolfSSL_PKCS7_SIGNED_new - allocates PKCS7 and initialize it for a signed data
+*
+* RETURNS:
+* returns pointer to the PKCS7 structure on success, otherwise returns NULL
+*/
+PKCS7_SIGNED* wolfSSL_PKCS7_SIGNED_new(void)
+{
+    byte signedData[]= { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02};
+    PKCS7* pkcs7 = NULL;
+
+    if ((pkcs7 = wolfSSL_PKCS7_new()) == NULL)
+        return NULL;
+    pkcs7->contentOID = SIGNED_DATA;
+    if ((wc_PKCS7_SetContentType(pkcs7, signedData, sizeof(signedData))) < 0) {
+        if (pkcs7) {
+            wolfSSL_PKCS7_free(pkcs7);
+            return NULL;
+        }
+    }
+    return pkcs7;
+}
+
+void wolfSSL_PKCS7_free(PKCS7* pkcs7)
+{
+    WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7;
+
+    if (p7 != NULL) {
+        if (p7->data != NULL)
+            XFREE(p7->data, NULL, DYNAMIC_TYPE_PKCS7);
+        wc_PKCS7_Free(&p7->pkcs7);
+        XFREE(p7, NULL, DYNAMIC_TYPE_PKCS7);
+    }
+}
+void wolfSSL_PKCS7_SIGNED_free(PKCS7_SIGNED* p7)
+{
+    wolfSSL_PKCS7_free(p7);
+    return;
+}
+PKCS7* wolfSSL_d2i_PKCS7(PKCS7** p7, const unsigned char** in, int len)
+{
+    WOLFSSL_PKCS7* pkcs7 = NULL;
+    word32 idx = 0;
+
+    if (in == NULL)
+        return NULL;
+
+    if ((pkcs7 = (WOLFSSL_PKCS7*)wolfSSL_PKCS7_new()) == NULL)
+        return NULL;
+
+    if (GetSequence(*in, &idx, &pkcs7->len, len) < 0) {
+        wolfSSL_PKCS7_free((PKCS7*)pkcs7);
+        return NULL;
+    }
+    pkcs7->len += idx;
+
+    pkcs7->data = (byte*)XMALLOC(pkcs7->len, NULL, DYNAMIC_TYPE_PKCS7);
+    if (pkcs7->data == NULL) {
+        wolfSSL_PKCS7_free((PKCS7*)pkcs7);
+        return NULL;
+    }
+    XMEMCPY(pkcs7->data, *in, pkcs7->len);
+    *in += pkcs7->len;
+
+    if (p7 != NULL)
+        *p7 = (PKCS7*)pkcs7;
+    return (PKCS7*)pkcs7;
+}
+
+PKCS7* wolfSSL_d2i_PKCS7_bio(WOLFSSL_BIO* bio, PKCS7** p7)
+{
+    WOLFSSL_PKCS7* pkcs7;
+
+    if (bio == NULL)
+        return NULL;
+
+    if ((pkcs7 = (WOLFSSL_PKCS7*)wolfSSL_PKCS7_new()) == NULL)
+        return NULL;
+
+    pkcs7->len = wolfSSL_BIO_pending(bio);
+    pkcs7->data = (byte*)XMALLOC(pkcs7->len, NULL, DYNAMIC_TYPE_PKCS7);
+    if (pkcs7->data == NULL) {
+        wolfSSL_PKCS7_free((PKCS7*)pkcs7);
+        return NULL;
+    }
+
+    if (wolfSSL_BIO_read(bio, pkcs7->data, pkcs7->len) != pkcs7->len) {
+        wolfSSL_PKCS7_free((PKCS7*)pkcs7);
+        return NULL;
+    }
+
+    if (p7 != NULL)
+        *p7 = (PKCS7*)pkcs7;
+    return (PKCS7*)pkcs7;
+}
+
+int wolfSSL_PKCS7_verify(PKCS7* pkcs7, WOLFSSL_STACK* certs,
+                         WOLFSSL_X509_STORE* store, WOLFSSL_BIO* in,
+                         WOLFSSL_BIO* out, int flags)
+{
+    int ret = 0;
+    unsigned char* mem = NULL;
+    int memSz = 0;
+    WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7;
+
+    if (pkcs7 == NULL)
+        return WOLFSSL_FAILURE;
+
+    if (in != NULL) {
+        if ((memSz = wolfSSL_BIO_get_mem_data(in, &mem)) < 0)
+            return WOLFSSL_FAILURE;
+
+        p7->pkcs7.content = mem;
+        p7->pkcs7.contentSz = memSz;
+    }
+
+    /* certs is the list of certificates to find the cert with issuer/serial. */
+    (void)certs;
+    /* store is the certificate store to use to verify signer certificate
+     * associated with the signers.
+     */
+    (void)store;
+
+    ret = wc_PKCS7_VerifySignedData_ex(&p7->pkcs7, NULL, 0, p7->data, p7->len,
+                                                                       NULL, 0);
+    if (ret != 0)
+        return WOLFSSL_FAILURE;
+
+    if ((flags & PKCS7_NOVERIFY) != PKCS7_NOVERIFY) {
+        /* All signer certificates are verified. */
+        return WOLFSSL_FAILURE;
+    }
+
+    if (out != NULL)
+       wolfSSL_BIO_write(out, p7->pkcs7.content, p7->pkcs7.contentSz);
+
+    return WOLFSSL_SUCCESS;
+}
+
+WOLFSSL_STACK* wolfSSL_PKCS7_get0_signers(PKCS7* pkcs7, WOLFSSL_STACK* certs,
+                                          int flags)
+{
+    WOLFSSL_STACK* signers = NULL;
+    WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7;
+
+    if (p7 == NULL)
+        return NULL;
+    /* Only PKCS#7 messages with a single cert that is the verifying certificate
+     * is supported.
+     */
+    if ((flags | PKCS7_NOINTERN) == PKCS7_NOINTERN)
+        return NULL;
+
+    signers = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+                                                             DYNAMIC_TYPE_X509);
+    if (signers == NULL)
+        return NULL;
+
+    signers->num = 1;
+    signers->data.x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL,
+                                                             DYNAMIC_TYPE_X509);
+    if (signers->data.x509 == NULL) {
+        XFREE(signers, NULL, DYNAMIC_TYPE_X509);
+        return NULL;
+    }
+
+    if (DecodeToX509(signers->data.x509, p7->pkcs7.singleCert,
+                                                 p7->pkcs7.singleCertSz) != 0) {
+        XFREE(signers->data.x509, NULL, DYNAMIC_TYPE_X509);
+        XFREE(signers, NULL, DYNAMIC_TYPE_X509);
+        return NULL;
+    }
+
+    (void)certs;
+
+    return signers;
+}
+
+/******************************************************************************
+* wolfSSL_PEM_write_bio_PKCS7 - writes the PKCS7 data to BIO
+*
+* RETURNS:
+* returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE
+*/
+
+int wolfSSL_PEM_write_bio_PKCS7(WOLFSSL_BIO* bio, PKCS7* p7)
+{
+#ifdef WOLFSSL_SMALL_STACK
+    byte* outputHead;
+    byte* outputFoot;
+#else
+    byte outputHead[2048];
+    byte outputFoot[2048];
+#endif
+    word32 outputHeadSz = 2048;
+    word32 outputFootSz = 2048;
+    word32 outputSz = 0;
+    byte*  output = NULL;
+    byte*  pem = NULL;
+    int    pemSz = -1;
+    enum wc_HashType hashType;
+    byte hashBuf[WC_MAX_DIGEST_SIZE];
+    word32 hashSz = -1;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PKCS7()");
+
+    if (bio == NULL || p7 == NULL)
+        return WOLFSSL_FAILURE;
+
+#ifdef WOLFSSL_SMALL_STACK
+    outputHead = (byte*)XMALLOC(outputHeadSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (outputHead == NULL)
+        return MEMORY_E;
+
+    outputFoot = (byte*)XMALLOC(outputFootSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (outputFoot == NULL)
+        goto error;
+
+#endif
+
+    XMEMSET(hashBuf, 0, WC_MAX_DIGEST_SIZE);
+    XMEMSET(outputHead, 0, outputHeadSz);
+    XMEMSET(outputFoot, 0, outputFootSz);
+
+    hashType = wc_OidGetHash(p7->hashOID);
+    hashSz = wc_HashGetDigestSize(hashType);
+    if (hashSz > WC_MAX_DIGEST_SIZE)
+        return WOLFSSL_FAILURE;
+
+    /* only SIGNED_DATA is supported */
+    switch (p7->contentOID) {
+        case SIGNED_DATA:
+            break;
+        default:
+            WOLFSSL_MSG("Unknown PKCS#7 Type");
+            return WOLFSSL_FAILURE;
+    };
+
+    if ((wc_PKCS7_EncodeSignedData_ex(p7, hashBuf, hashSz,
+        outputHead, &outputHeadSz, outputFoot, &outputFootSz)) != 0)
+        return WOLFSSL_FAILURE;
+
+    outputSz = outputHeadSz + p7->contentSz + outputFootSz;
+    output = (byte*)XMALLOC(outputSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+    if (!output)
+         return WOLFSSL_FAILURE;
+
+    XMEMSET(output, 0, outputSz);
+    outputSz = 0;
+    XMEMCPY(&output[outputSz], outputHead, outputHeadSz);
+    outputSz += outputHeadSz;
+    XMEMCPY(&output[outputSz], p7->content, p7->contentSz);
+    outputSz += p7->contentSz;
+    XMEMCPY(&output[outputSz], outputFoot, outputFootSz);
+    outputSz += outputFootSz;
+
+    /* get PEM size */
+    pemSz = wc_DerToPemEx(output, outputSz, NULL, 0, NULL, CERT_TYPE);
+    if (pemSz < 0)
+        goto error;
+
+    pemSz++; /* for '\0'*/
+
+    /* create PEM buffer and convert from DER to PEM*/
+    if ((pem = (byte*)XMALLOC(pemSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER)) == NULL)
+        goto error;
+
+    XMEMSET(pem, 0, pemSz);
+
+    if (wc_DerToPemEx(output, outputSz, pem, pemSz, NULL, CERT_TYPE) < 0) {
+        goto error;
+    }
+    if ((wolfSSL_BIO_write(bio, pem, pemSz) == pemSz)) {
+        XFREE(output, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(pem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(outputHead, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(outputFoot, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+        return WOLFSSL_SUCCESS;
+    }
+
+error:
+#ifdef WOLFSSL_SMALL_STACK
+    if (outputHead) {
+        XFREE(outputHead, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+    if (outputFoot) {
+        XFREE(outputFoot, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+#endif
+    if (output) {
+        XFREE(output, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+    if (pem) {
+        XFREE(pem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+    return WOLFSSL_FAILURE;
+}
+#endif /* OPENSSL_ALL && HAVE_PKCS7 */
+
+#if defined(OPENSSL_EXTRA)
+WOLFSSL_STACK* wolfSSL_sk_X509_new(void)
+{
+    WOLFSSL_STACK* s = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+                                                             DYNAMIC_TYPE_X509);
+    if (s != NULL) {
+        XMEMSET(s, 0, sizeof(*s));
+        s->type = STACK_TYPE_X509;
+    }
+
+    return s;
+}
+#endif
+
+#ifdef OPENSSL_ALL
+int wolfSSL_PEM_write_bio_PKCS8PrivateKey(WOLFSSL_BIO* bio,
+                                          WOLFSSL_EVP_PKEY* pkey,
+                                          const WOLFSSL_EVP_CIPHER* enc,
+                                          char* passwd, int passwdSz,
+                                          pem_password_cb* cb, void* ctx)
+{
+    int ret = 0;
+    char password[NAME_SZ];
+    byte* key = NULL;
+    word32 keySz;
+    byte* pem = NULL;
+    int pemSz;
+    int type = PKCS8_PRIVATEKEY_TYPE;
+    int algId;
+    const byte* curveOid;
+    word32 oidSz;
+    int encAlgId;
+
+    if (bio == NULL || pkey == NULL)
+        return -1;
+
+    keySz = pkey->pkey_sz + 128;
+    key = (byte*)XMALLOC(keySz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (key == NULL)
+        ret = MEMORY_E;
+
+    if (ret == 0 && enc != NULL && passwd == NULL) {
+        passwdSz = cb(password, sizeof(password), 1, ctx);
+        if (passwdSz < 0)
+            ret = WOLFSSL_FAILURE;
+        passwd = password;
+    }
+
+    if (ret == 0 && enc != NULL) {
+        WC_RNG rng;
+        ret = wc_InitRng(&rng);
+        if (ret == 0) {
+        #ifndef NO_DES3
+            if (enc == EVP_DES_CBC)
+                encAlgId = DESb;
+            else if (enc == EVP_DES_EDE3_CBC)
+                encAlgId = DES3b;
+            else
+        #endif
+        #if !defined(NO_AES) && defined(HAVE_AES_CBC)
+            #ifdef WOLFSSL_AES_256
+            if (enc == EVP_AES_256_CBC)
+                encAlgId = AES256CBCb;
+            else
+            #endif
+        #endif
+                ret = -1;
+            if (ret == 0) {
+                ret = TraditionalEnc((byte*)pkey->pkey.ptr, pkey->pkey_sz, key,
+                                       &keySz, passwd, passwdSz, PKCS5, PBES2,
+                                       encAlgId, NULL, 0, WC_PKCS12_ITT_DEFAULT,
+                                       &rng, NULL);
+                if (ret > 0) {
+                    keySz = ret;
+                    ret = 0;
+                }
+            }
+            wc_FreeRng(&rng);
+        }
+        type = PKCS8_ENC_PRIVATEKEY_TYPE;
+    }
+    if (ret == 0 && enc == NULL) {
+        type = PKCS8_PRIVATEKEY_TYPE;
+        if (pkey->type == EVP_PKEY_EC) {
+            algId = ECDSAk;
+            ret = wc_ecc_get_oid(pkey->ecc->group->curve_oid, &curveOid,
+                                                                        &oidSz);
+        }
+        else {
+            algId = RSAk;
+            curveOid = NULL;
+            oidSz = 0;
+        }
+
+        if (ret >= 0) {
+            ret = wc_CreatePKCS8Key(key, &keySz, (byte*)pkey->pkey.ptr,
+                                         pkey->pkey_sz, algId, curveOid, oidSz);
+            keySz = ret;
+        }
+    }
+
+    if (password == passwd)
+        XMEMSET(password, 0, passwdSz);
+
+    if (ret >= 0) {
+        pemSz = 2 * keySz + 2 * 64;
+        pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (pem == NULL)
+            ret = MEMORY_E;
+    }
+
+    if (ret >= 0)
+        ret = wc_DerToPemEx(key, keySz, pem, pemSz, NULL, type);
+
+    if (key != NULL)
+        XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+    if (ret >= 0) {
+        if (wolfSSL_BIO_write(bio, pem, ret) != ret)
+            ret = -1;
+    }
+
+    if (pem != NULL)
+        XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+    return ret < 0 ? 0 : ret;
+
+}
+
+static int bio_get_data(WOLFSSL_BIO* bio, byte** data)
+{
+    int ret = 0;
+    byte* mem = NULL;
+#ifndef NO_FILESYSTEM
+    long memSz;
+    XFILE file;
+    long curr;
+#endif
+
+    if ((ret = wolfSSL_BIO_pending(bio)) > 0) {
+    }
+#ifndef NO_FILESYSTEM
+    else if (bio->type == WOLFSSL_BIO_FILE) {
+        if (wolfSSL_BIO_get_fp(bio, &file) != WOLFSSL_SUCCESS)
+            ret = BAD_FUNC_ARG;
+        if (ret == 0) {
+            curr = XFTELL(file);
+            if (curr < 0) {
+                ret = WOLFSSL_BAD_FILE;
+            }
+            if (XFSEEK(file, 0, XSEEK_END) != 0)
+                ret = WOLFSSL_BAD_FILE;
+        }
+        if (ret == 0) {
+            memSz = XFTELL(file);
+            if (memSz > MAX_WOLFSSL_FILE_SIZE || memSz < 0) {
+                ret = WOLFSSL_BAD_FILE;
+            }
+        }
+        if (ret == 0) {
+            memSz -= curr;
+            ret = (int)memSz;
+            if (XFSEEK(file, curr, SEEK_SET) != 0)
+                ret = WOLFSSL_BAD_FILE;
+        }
+    }
+#endif
+
+    if (ret > 0) {
+        mem = (byte*)XMALLOC(ret, bio->heap, DYNAMIC_TYPE_OPENSSL);
+        if (mem == NULL) {
+            WOLFSSL_MSG("Memory error");
+            ret = MEMORY_E;
+        }
+        if (ret >= 0) {
+            if ((ret = wolfSSL_BIO_read(bio, mem, ret)) <= 0) {
+                XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
+                ret = MEMORY_E;
+                mem = NULL;
+            }
+        }
+    }
+
+    *data = mem;
+
+    return ret;
+}
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_BIO_set_init(WOLFSSL_BIO* bio, int init)
+{
+    WOLFSSL_STUB("wolfSSL_BIO_set_init");
+    (void)bio;
+    (void)init;
+}
+
+void wolfSSL_BIO_set_shutdown(WOLFSSL_BIO* bio, int shut)
+{
+    WOLFSSL_STUB("wolfSSL_BIO_set_shutdown");
+    (void)bio;
+    (void)shut;
+
+}
+int wolfSSL_BIO_get_shutdown(WOLFSSL_BIO* bio)
+{
+    WOLFSSL_STUB("wolfSSL_BIO_get_shutdown");
+    (void)bio;
+    return 0;
+}
+#endif /* NO_WOLFSSL_STUB */
+
+void wolfSSL_BIO_clear_retry_flags(WOLFSSL_BIO* bio)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_clear_retry_flags");
+
+    if (bio)
+        bio->flags &= ~(WOLFSSL_BIO_FLAG_READ|WOLFSSL_BIO_FLAG_RETRY);
+}
+
+int wolfSSL_BIO_should_retry(WOLFSSL_BIO *bio)
+{
+    int ret = 0;
+    if (bio != NULL) {
+        ret = (int)(bio->flags & WOLFSSL_BIO_FLAG_RETRY);
+    }
+
+    return ret;
+}
+
+/* DER data is PKCS#8 encrypted. */
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PKCS8PrivateKey_bio(WOLFSSL_BIO* bio,
+                                                  WOLFSSL_EVP_PKEY** pkey,
+                                                  pem_password_cb* cb,
+                                                  void* ctx)
+{
+    int ret;
+    byte* der;
+    int len;
+    byte* p;
+    char password[NAME_SZ];
+    int passwordSz;
+    word32 algId;
+    WOLFSSL_EVP_PKEY* key;
+
+    if ((len = bio_get_data(bio, &der)) < 0)
+        return NULL;
+
+    if (cb != NULL) {
+        passwordSz = cb(password, sizeof(password), PEM_PASS_READ, ctx);
+        if (passwordSz < 0) {
+            XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL);
+            return NULL;
+        }
+
+        ret = ToTraditionalEnc(der, len, password, passwordSz, &algId);
+        if (ret < 0) {
+            XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL);
+            return NULL;
+        }
+
+        XMEMSET(password, 0, passwordSz);
+    }
+
+    p = der;
+    key = wolfSSL_d2i_PrivateKey_EVP(pkey, &p, len);
+    XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL);
+    return key;
+}
+
+/* Detect which type of key it is before decoding. */
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_AutoPrivateKey(WOLFSSL_EVP_PKEY** pkey,
+                                             const unsigned char** pp,
+                                             long length)
+{
+    int ret;
+    WOLFSSL_EVP_PKEY* key = NULL;
+    const byte* der = *pp;
+    word32 idx = 0;
+    int len = 0;
+    word32 end = 0;
+    int cnt = 0;
+    int type;
+    word32 algId;
+    word32 keyLen = (word32)length;
+
+    /* Take off PKCS#8 wrapper if found. */
+    if ((len = ToTraditionalInline_ex(der, &idx, keyLen, &algId)) >= 0) {
+        der += idx;
+        keyLen = len;
+    }
+    idx = 0;
+    len = 0;
+
+    /* Use the number of elements in the outer sequence to determine key type.
+     */
+    ret = GetSequence(der, &idx, &len, keyLen);
+    if (ret >= 0) {
+        end = idx + len;
+        while (ret >= 0 && idx < end) {
+            /* Skip type */
+            idx++;
+            /* Get length and skip over - keeping count */
+            len = 0;
+            ret = GetLength(der, &idx, &len, keyLen);
+            if (ret >= 0) {
+                if (idx + len > end)
+                    ret = ASN_PARSE_E;
+                else {
+                    idx += len;
+                    cnt++;
+                }
+            }
+        }
+    }
+
+    if (ret >= 0) {
+        /* ECC includes version, private[, curve][, public key] */
+        if (cnt >= 2 && cnt <= 4)
+            type = EVP_PKEY_EC;
+        else
+            type = EVP_PKEY_RSA;
+
+        key = wolfSSL_d2i_PrivateKey(type, pkey, &der, keyLen);
+        *pp = der;
+    }
+
+    return key;
+}
+#endif
+
+#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \
+    defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ)
+int wolfSSL_X509_set_subject_name(WOLFSSL_X509 *cert, WOLFSSL_X509_NAME *name)
+{
+    int i;
+    WOLFSSL_X509_NAME_ENTRY* ne;
+
+    WOLFSSL_ENTER("X509_set_subject_name");
+    if (cert == NULL || name == NULL)
+        return WOLFSSL_FAILURE;
+
+    FreeX509Name(&cert->subject, cert->heap);
+    InitX509Name(&cert->subject, 0);
+    if (name->dynamicName) {
+        cert->subject.name = (char*)XMALLOC(name->sz, cert->heap,
+                                                       DYNAMIC_TYPE_SUBJECT_CN);
+        if (cert->subject.name == NULL)
+            return WOLFSSL_FAILURE;
+    }
+    XMEMCPY(cert->subject.name, name->name, name->sz);
+    cert->subject.sz = name->sz;
+
+    for (i = 0; i < 10; i++) {
+        ne = wolfSSL_X509_NAME_get_entry(name, i);
+        if (ne != NULL)
+            wolfSSL_X509_NAME_add_entry(&cert->subject, ne, i, 1);
+    }
+    cert->subject.x509 = cert;
+    cert->subject.name = cert->subject.fullName.fullName;
+    cert->subject.sz = cert->subject.fullName.fullNameLen;
+
+    return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_X509_set_issuer_name(WOLFSSL_X509 *cert, WOLFSSL_X509_NAME *name)
+{
+    int i;
+    WOLFSSL_X509_NAME_ENTRY* ne;
+
+    WOLFSSL_ENTER("X509_set_issuer_name");
+    if (cert == NULL || name == NULL)
+        return WOLFSSL_FAILURE;
+
+    FreeX509Name(&cert->issuer, cert->heap);
+    InitX509Name(&cert->issuer, 0);
+    if (name->dynamicName) {
+        cert->issuer.name = (char*)XMALLOC(name->sz, cert->heap,
+                                                       DYNAMIC_TYPE_SUBJECT_CN);
+        if (cert->issuer.name == NULL)
+            return WOLFSSL_FAILURE;
+    }
+    XMEMCPY(cert->issuer.name, name->name, name->sz);
+    cert->issuer.sz = name->sz;
+
+    for (i = 0; i < 10; i++) {
+        ne = wolfSSL_X509_NAME_get_entry(name, i);
+        if (ne != NULL)
+            wolfSSL_X509_NAME_add_entry(&cert->issuer, ne, i, 1);
+    }
+    cert->issuer.x509 = cert;
+    cert->issuer.name = cert->issuer.fullName.fullName;
+    cert->issuer.sz = cert->issuer.fullName.fullNameLen;
+    cert->issuerSet = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_X509_set_notAfter(WOLFSSL_X509* x509, const WOLFSSL_ASN1_TIME* t)
+{
+    if (x509 == NULL || t == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    XMEMCPY(&x509->notAfter, t, sizeof(WOLFSSL_ASN1_TIME));
+
+    return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_X509_set_notBefore(WOLFSSL_X509* x509, const WOLFSSL_ASN1_TIME* t)
+{
+    if (x509 == NULL || t == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    XMEMCPY(&x509->notBefore, t, sizeof(WOLFSSL_ASN1_TIME));
+
+    return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_X509_set_serialNumber(WOLFSSL_X509* x509, WOLFSSL_ASN1_INTEGER* s)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_set_serialNumber");
+    if (!x509 || !s || s->dataMax >= EXTERNAL_SERIAL_SIZE)
+        return WOLFSSL_FAILURE;
+
+    if (s->isDynamic)
+        XSTRNCPY((char*)x509->serial,(char*)s->data,s->dataMax);
+    else
+        XSTRNCPY((char*)x509->serial,(char*)s->intData,s->dataMax);
+
+    x509->serial[s->dataMax] = 0;
+    x509->serialSz = s->dataMax;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_X509_set_pubkey(WOLFSSL_X509 *cert, WOLFSSL_EVP_PKEY *pkey)
+{
+    byte* p;
+    WOLFSSL_ENTER("wolfSSL_X509_set_pubkey");
+
+    if (cert == NULL || pkey == NULL)
+        return WOLFSSL_FAILURE;
+
+    if (pkey->type == EVP_PKEY_RSA)
+        cert->pubKeyOID = RSAk;
+    else if (pkey->type == EVP_PKEY_EC)
+        cert->pubKeyOID = ECDSAk;
+    else
+        return WOLFSSL_FAILURE;
+
+    p = (byte*)XMALLOC(pkey->pkey_sz, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    if (p == NULL)
+        return WOLFSSL_FAILURE;
+
+    if (cert->pubKey.buffer != NULL)
+        XFREE(cert->pubKey.buffer, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    cert->pubKey.buffer = p;
+    XMEMCPY(cert->pubKey.buffer, pkey->pkey.ptr, pkey->pkey_sz);
+    cert->pubKey.length = pkey->pkey_sz;
+
+    return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_X509_set_version(WOLFSSL_X509* x509, long v)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_set_version");
+    if ((x509 == NULL) || (v < 0) || (v > INT_MAX)) {
+        return WOLFSSL_FAILURE;
+    }
+    x509->version = (int) v + 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* OPENSSL_EXTRA && !NO_CERTS && WOLFSSL_CERT_GEN && WOLFSSL_CERT_REQ */
+
+#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \
+    defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ)
+
+void wolfSSL_X509V3_set_ctx(WOLFSSL_X509V3_CTX* ctx, WOLFSSL_X509* issuer,
+        WOLFSSL_X509* subject, WOLFSSL_X509* req, WOLFSSL_X509_CRL* crl,
+        int flag)
+{
+    int ret = WOLFSSL_SUCCESS;
+    WOLFSSL_ENTER("wolfSSL_X509V3_set_ctx");
+    if (!ctx || !ctx->x509)
+        return;
+
+    /* Set parameters in ctx as long as ret == WOLFSSL_SUCCESS */
+    if (issuer)
+        ret = wolfSSL_X509_set_issuer_name(ctx->x509,&issuer->issuer);
+
+    if (subject && ret == WOLFSSL_SUCCESS)
+        ret = wolfSSL_X509_set_subject_name(ctx->x509,&subject->subject);
+
+    if (req && ret == WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("req not implemented.");
+    }
+
+    if (crl && ret == WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("crl not implemented.");
+    }
+
+    if (flag && ret == WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("flag not implemented.");
+    }
+
+    if (!ret) {
+        WOLFSSL_MSG("Error setting WOLFSSL_X509V3_CTX parameters.");
+    }
+}
+
+int wolfSSL_i2d_X509_REQ(WOLFSSL_X509* req, unsigned char** out)
+{
+    const unsigned char* der;
+    int derSz = 0;
+    WOLFSSL_ENTER("wolfSSL_i2d_X509_REQ");
+
+    if (req == NULL || out == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    der = wolfSSL_X509_get_der(req, &derSz);
+    if (der == NULL) {
+        return MEMORY_E;
+    }
+
+    if (*out == NULL) {
+        *out = (unsigned char*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_OPENSSL);
+        if (*out == NULL) {
+            return MEMORY_E;
+        }
+    }
+
+    XMEMCPY(*out, der, derSz);
+
+    return derSz;
+}
+
+WOLFSSL_X509* wolfSSL_X509_REQ_new(void)
+{
+    return wolfSSL_X509_new();
+}
+
+void wolfSSL_X509_REQ_free(WOLFSSL_X509* req)
+{
+    wolfSSL_X509_free(req);
+}
+
+int wolfSSL_X509_REQ_sign(WOLFSSL_X509 *req, WOLFSSL_EVP_PKEY *pkey,
+                          const WOLFSSL_EVP_MD *md)
+{
+    byte der[2048];
+    int derSz = sizeof(der);
+
+    if (req == NULL || pkey == NULL || md == NULL)
+        return WOLFSSL_FAILURE;
+
+    /* Create a Cert that has the certificate request fields. */
+    req->sigOID = wolfSSL_sigTypeFromPKEY((WOLFSSL_EVP_MD*)md, pkey);
+    if (wolfSSL_X509_make_der(req, 1, der, &derSz) != WOLFSSL_SUCCESS) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if (wolfSSL_X509_resign_cert(req, 1, der, sizeof(der), derSz,
+            (WOLFSSL_EVP_MD*)md, pkey) <= 0) {
+        return WOLFSSL_FAILURE;
+    }
+    return WOLFSSL_SUCCESS;
+}
+
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_X509_REQ_add_extensions(WOLFSSL_X509* req,
+        WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* ext)
+{
+    (void)req;
+    (void)ext;
+    return WOLFSSL_FATAL_ERROR;
+}
+#endif
+
+int wolfSSL_X509_REQ_set_subject_name(WOLFSSL_X509 *req,
+                                      WOLFSSL_X509_NAME *name)
+{
+    return wolfSSL_X509_set_subject_name(req, name);
+}
+
+int wolfSSL_X509_REQ_set_pubkey(WOLFSSL_X509 *req, WOLFSSL_EVP_PKEY *pkey)
+{
+    return wolfSSL_X509_set_pubkey(req, pkey);
+}
+#endif /* OPENSSL_EXTRA && !NO_CERTS && WOLFSSL_CERT_GEN && WOLFSSL_CERT_REQ */
+
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/tls.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/tls.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/tls.c	(revision 453)
@@ -0,0 +1,11755 @@
+/* tls.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifndef WOLFCRYPT_ONLY
+
+#include <wolfssl/ssl.h>
+#include <wolfssl/internal.h>
+#include <wolfssl/error-ssl.h>
+#include <wolfssl/wolfcrypt/hmac.h>
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+#ifdef HAVE_CURVE25519
+    #include <wolfssl/wolfcrypt/curve25519.h>
+#endif
+#ifdef HAVE_CURVE448
+    #include <wolfssl/wolfcrypt/curve448.h>
+#endif
+#ifdef HAVE_NTRU
+    #include "libntruencrypt/ntru_crypto.h"
+    #include <wolfssl/wolfcrypt/random.h>
+#endif
+
+#ifdef HAVE_QSH
+    static int TLSX_AddQSHKey(QSHKey** list, QSHKey* key);
+    static byte* TLSX_QSHKeyFind_Pub(QSHKey* qsh, word16* pubLen, word16 name);
+#if defined(HAVE_NTRU)
+    static int TLSX_CreateNtruKey(WOLFSSL* ssl, int type);
+#endif
+#endif /* HAVE_QSH */
+
+#if (!defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_TLS13) && \
+        !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)) || \
+    (defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES))
+static int TLSX_KeyShare_IsSupported(int namedGroup);
+#endif
+
+#if ((!defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_TLS13) && \
+        !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)) || \
+    (defined(WOLFSSL_TLS13) && !defined(HAVE_ECC) && !defined(HAVE_CURVE25519) \
+        && !defined(HAVE_CURVE448) && defined(HAVE_SUPPORTED_CURVES)) || \
+    ((defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+        defined(HAVE_CURVE448)) && defined(HAVE_SUPPORTED_CURVES))) && \
+     defined(HAVE_TLS_EXTENSIONS)
+static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions);
+#endif
+
+
+#ifndef NO_TLS
+
+/* Digest enable checks */
+#ifdef NO_OLD_TLS /* TLS 1.2 only */
+    #if defined(NO_SHA256) && !defined(WOLFSSL_SHA384) && \
+            !defined(WOLFSSL_SHA512)
+        #error Must have SHA256, SHA384 or SHA512 enabled for TLS 1.2
+    #endif
+#else  /* TLS 1.1 or older */
+    #if defined(NO_MD5) && defined(NO_SHA)
+        #error Must have SHA1 and MD5 enabled for old TLS
+    #endif
+#endif
+
+#ifdef WOLFSSL_TLS13
+    #if !defined(NO_DH) && \
+        !defined(HAVE_FFDHE_2048) && !defined(HAVE_FFDHE_3072) && \
+        !defined(HAVE_FFDHE_4096) && !defined(HAVE_FFDHE_6144) && \
+        !defined(HAVE_FFDHE_8192)
+        #error Please configure your TLS 1.3 DH key size using either: HAVE_FFDHE_2048, HAVE_FFDHE_3072, HAVE_FFDHE_4096, HAVE_FFDHE_6144 or HAVE_FFDHE_8192
+    #endif
+    #if !defined(NO_RSA) && !defined(WC_RSA_PSS)
+        #error The build option WC_RSA_PSS is required for TLS 1.3 with RSA
+    #endif
+    #ifndef HAVE_TLS_EXTENSIONS
+        #ifndef _MSC_VER
+            #error "The build option HAVE_TLS_EXTENSIONS is required for TLS 1.3"
+        #else
+            #pragma message("Error: The build option HAVE_TLS_EXTENSIONS is required for TLS 1.3")
+        #endif
+    #endif
+#endif
+
+/* Warn if secrets logging is enabled */
+#if defined(SHOW_SECRETS) || defined(WOLFSSL_SSLKEYLOGFILE)
+    #ifndef _MSC_VER
+        #warning The SHOW_SECRETS and WOLFSSL_SSLKEYLOGFILE options should only be used for debugging and never in a production environment
+    #else
+        #pragma message("Warning: The SHOW_SECRETS and WOLFSSL_SSLKEYLOGFILE options should only be used for debugging and never in a production environment")
+    #endif
+#endif
+
+/* Optional Pre-Master-Secret logging for Wireshark */
+#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SSLKEYLOGFILE)
+#ifndef WOLFSSL_SSLKEYLOGFILE_OUTPUT
+    #define WOLFSSL_SSLKEYLOGFILE_OUTPUT "sslkeylog.log"
+#endif
+#endif
+
+#ifndef WOLFSSL_NO_TLS12
+
+#ifdef WOLFSSL_SHA384
+    #define HSHASH_SZ WC_SHA384_DIGEST_SIZE
+#else
+    #define HSHASH_SZ FINISHED_SZ
+#endif
+
+#ifdef WOLFSSL_RENESAS_TSIP_TLS
+    int tsip_useable(const WOLFSSL *ssl);
+    int tsip_generateMasterSecret(const byte *pre,
+                                const byte *cr,const byte *sr,
+                                byte *ms/* out */);
+    int tsip_generateSeesionKey(WOLFSSL *ssl);
+    int tsip_generateVerifyData(const byte *ms, const byte *side,
+                                const byte *handshake_hash,
+                                byte *hashes /* out */);
+#endif
+
+int BuildTlsHandshakeHash(WOLFSSL* ssl, byte* hash, word32* hashLen)
+{
+    int ret = 0;
+    word32 hashSz = FINISHED_SZ;
+
+    if (ssl == NULL || hash == NULL || hashLen == NULL || *hashLen < HSHASH_SZ)
+        return BAD_FUNC_ARG;
+
+    /* for constant timing perform these even if error */
+#ifndef NO_OLD_TLS
+    ret |= wc_Md5GetHash(&ssl->hsHashes->hashMd5, hash);
+    ret |= wc_ShaGetHash(&ssl->hsHashes->hashSha, &hash[WC_MD5_DIGEST_SIZE]);
+#endif
+
+    if (IsAtLeastTLSv1_2(ssl)) {
+#ifndef NO_SHA256
+        if (ssl->specs.mac_algorithm <= sha256_mac ||
+            ssl->specs.mac_algorithm == blake2b_mac) {
+            ret |= wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash);
+            hashSz = WC_SHA256_DIGEST_SIZE;
+        }
+#endif
+#ifdef WOLFSSL_SHA384
+        if (ssl->specs.mac_algorithm == sha384_mac) {
+            ret |= wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash);
+            hashSz = WC_SHA384_DIGEST_SIZE;
+        }
+#endif
+    }
+
+    *hashLen = hashSz;
+
+    if (ret != 0)
+        ret = BUILD_MSG_ERROR;
+
+    return ret;
+}
+
+
+int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
+{
+    int ret;
+    const byte* side;
+    word32 hashSz = HSHASH_SZ;
+#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
+    DECLARE_VAR(handshake_hash, byte, HSHASH_SZ, ssl->heap);
+    if (handshake_hash == NULL)
+        return MEMORY_E;
+#else
+    byte handshake_hash[HSHASH_SZ];
+#endif
+
+    ret = BuildTlsHandshakeHash(ssl, handshake_hash, &hashSz);
+    if (ret == 0) {
+        if (XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0)
+            side = tls_client;
+        else
+            side = tls_server;
+
+#ifdef WOLFSSL_HAVE_PRF
+#if defined(WOLFSSL_RENESAS_TSIP_TLS) && \
+    !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION)
+        if (tsip_useable(ssl)) {
+            ret = tsip_generateVerifyData(ssl->arrays->tsip_masterSecret,
+                            side, handshake_hash, (byte*)hashes /* out */);
+        } else
+#endif
+        ret = wc_PRF_TLS((byte*)hashes, TLS_FINISHED_SZ, ssl->arrays->masterSecret,
+                   SECRET_LEN, side, FINISHED_LABEL_SZ, handshake_hash, hashSz,
+                   IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm,
+                   ssl->heap, ssl->devId);
+#else
+        /* Pseudo random function must be enabled in the configuration. */
+        ret = PRF_MISSING;
+        WOLFSSL_MSG("Pseudo-random function is not enabled");
+
+        (void)side;
+        (void)hashes;
+#endif
+    }
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
+    FREE_VAR(handshake_hash, ssl->heap);
+#endif
+
+    return ret;
+}
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#ifndef NO_OLD_TLS
+
+#ifdef WOLFSSL_ALLOW_TLSV10
+ProtocolVersion MakeTLSv1(void)
+{
+    ProtocolVersion pv;
+    pv.major = SSLv3_MAJOR;
+    pv.minor = TLSv1_MINOR;
+
+    return pv;
+}
+#endif /* WOLFSSL_ALLOW_TLSV10 */
+
+
+ProtocolVersion MakeTLSv1_1(void)
+{
+    ProtocolVersion pv;
+    pv.major = SSLv3_MAJOR;
+    pv.minor = TLSv1_1_MINOR;
+
+    return pv;
+}
+
+#endif /* !NO_OLD_TLS */
+
+
+#ifndef WOLFSSL_NO_TLS12
+
+ProtocolVersion MakeTLSv1_2(void)
+{
+    ProtocolVersion pv;
+    pv.major = SSLv3_MAJOR;
+    pv.minor = TLSv1_2_MINOR;
+
+    return pv;
+}
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#ifdef WOLFSSL_TLS13
+/* The TLS v1.3 protocol version.
+ *
+ * returns the protocol version data for TLS v1.3.
+ */
+ProtocolVersion MakeTLSv1_3(void)
+{
+    ProtocolVersion pv;
+    pv.major = SSLv3_MAJOR;
+    pv.minor = TLSv1_3_MINOR;
+
+    return pv;
+}
+#endif
+
+#ifndef WOLFSSL_NO_TLS12
+
+#ifdef HAVE_EXTENDED_MASTER
+static const byte ext_master_label[EXT_MASTER_LABEL_SZ + 1] =
+                                                      "extended master secret";
+#endif
+static const byte master_label[MASTER_LABEL_SZ + 1] = "master secret";
+static const byte key_label   [KEY_LABEL_SZ + 1]    = "key expansion";
+
+static int _DeriveTlsKeys(byte* key_dig, word32 key_dig_len,
+                         const byte* ms, word32 msLen,
+                         const byte* sr, const byte* cr,
+                         int tls1_2, int hash_type,
+                         void* heap, int devId)
+{
+    int ret;
+#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
+    DECLARE_VAR(seed, byte, SEED_LEN, heap);
+    if (seed == NULL)
+        return MEMORY_E;
+#else
+    byte seed[SEED_LEN];
+#endif
+
+    XMEMCPY(seed,           sr, RAN_LEN);
+    XMEMCPY(seed + RAN_LEN, cr, RAN_LEN);
+
+#ifdef WOLFSSL_HAVE_PRF
+    ret = wc_PRF_TLS(key_dig, key_dig_len, ms, msLen, key_label, KEY_LABEL_SZ,
+               seed, SEED_LEN, tls1_2, hash_type, heap, devId);
+#else
+    /* Pseudo random function must be enabled in the configuration. */
+    ret = PRF_MISSING;
+    WOLFSSL_MSG("Pseudo-random function is not enabled");
+
+    (void)key_dig;
+    (void)key_dig_len;
+    (void)ms;
+    (void)msLen;
+    (void)tls1_2;
+    (void)hash_type;
+    (void)heap;
+    (void)devId;
+    (void)key_label;
+    (void)master_label;
+#ifdef HAVE_EXTENDED_MASTER
+    (void)ext_master_label;
+#endif
+#endif
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
+    FREE_VAR(seed, heap);
+#endif
+
+    return ret;
+}
+
+/* External facing wrapper so user can call as well, 0 on success */
+int wolfSSL_DeriveTlsKeys(byte* key_dig, word32 key_dig_len,
+                         const byte* ms, word32 msLen,
+                         const byte* sr, const byte* cr,
+                         int tls1_2, int hash_type)
+{
+    return _DeriveTlsKeys(key_dig, key_dig_len, ms, msLen, sr, cr, tls1_2,
+        hash_type, NULL, INVALID_DEVID);
+}
+
+
+int DeriveTlsKeys(WOLFSSL* ssl)
+{
+    int   ret;
+    int   key_dig_len = 2 * ssl->specs.hash_size +
+                        2 * ssl->specs.key_size  +
+                        2 * ssl->specs.iv_size;
+#ifdef WOLFSSL_SMALL_STACK
+    byte* key_dig;
+#else
+    byte  key_dig[MAX_PRF_DIG];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+    key_dig = (byte*)XMALLOC(MAX_PRF_DIG, ssl->heap, DYNAMIC_TYPE_DIGEST);
+    if (key_dig == NULL) {
+        return MEMORY_E;
+    }
+#endif
+#if defined(WOLFSSL_RENESAS_TSIP_TLS) && \
+    !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION)
+    if (tsip_useable(ssl))
+        ret = tsip_generateSeesionKey(ssl);
+    else {
+#endif
+    ret = _DeriveTlsKeys(key_dig, key_dig_len,
+                         ssl->arrays->masterSecret, SECRET_LEN,
+                         ssl->arrays->serverRandom, ssl->arrays->clientRandom,
+                         IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm,
+                         ssl->heap, ssl->devId);
+    if (ret == 0)
+        ret = StoreKeys(ssl, key_dig, PROVISION_CLIENT_SERVER);
+#if defined(WOLFSSL_RENESAS_TSIP_TLS) && \
+    !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION)
+    }
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(key_dig, ssl->heap, DYNAMIC_TYPE_DIGEST);
+#endif
+
+    return ret;
+}
+
+static int _MakeTlsMasterSecret(byte* ms, word32 msLen,
+                               const byte* pms, word32 pmsLen,
+                               const byte* cr, const byte* sr,
+                               int tls1_2, int hash_type,
+                               void* heap, int devId)
+{
+    int ret;
+#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
+    DECLARE_VAR(seed, byte, SEED_LEN, heap);
+    if (seed == NULL)
+        return MEMORY_E;
+#else
+    byte seed[SEED_LEN];
+#endif
+
+    XMEMCPY(seed,           cr, RAN_LEN);
+    XMEMCPY(seed + RAN_LEN, sr, RAN_LEN);
+
+#ifdef WOLFSSL_HAVE_PRF
+    ret = wc_PRF_TLS(ms, msLen, pms, pmsLen, master_label, MASTER_LABEL_SZ,
+               seed, SEED_LEN, tls1_2, hash_type, heap, devId);
+#else
+    /* Pseudo random function must be enabled in the configuration. */
+    ret = PRF_MISSING;
+    WOLFSSL_MSG("Pseudo-random function is not enabled");
+
+    (void)ms;
+    (void)msLen;
+    (void)pms;
+    (void)pmsLen;
+    (void)tls1_2;
+    (void)hash_type;
+    (void)heap;
+    (void)devId;
+#endif
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
+    FREE_VAR(seed, heap);
+#endif
+
+    return ret;
+}
+
+/* External facing wrapper so user can call as well, 0 on success */
+int wolfSSL_MakeTlsMasterSecret(byte* ms, word32 msLen,
+                               const byte* pms, word32 pmsLen,
+                               const byte* cr, const byte* sr,
+                               int tls1_2, int hash_type)
+{
+    return _MakeTlsMasterSecret(ms, msLen, pms, pmsLen, cr, sr, tls1_2,
+        hash_type, NULL, INVALID_DEVID);
+}
+
+
+#ifdef HAVE_EXTENDED_MASTER
+
+static int _MakeTlsExtendedMasterSecret(byte* ms, word32 msLen,
+                                        const byte* pms, word32 pmsLen,
+                                        const byte* sHash, word32 sHashLen,
+                                        int tls1_2, int hash_type,
+                                        void* heap, int devId)
+{
+    int ret;
+
+#ifdef WOLFSSL_HAVE_PRF
+    ret = wc_PRF_TLS(ms, msLen, pms, pmsLen, ext_master_label, EXT_MASTER_LABEL_SZ,
+               sHash, sHashLen, tls1_2, hash_type, heap, devId);
+#else
+    /* Pseudo random function must be enabled in the configuration. */
+    ret = PRF_MISSING;
+    WOLFSSL_MSG("Pseudo-random function is not enabled");
+
+    (void)ms;
+    (void)msLen;
+    (void)pms;
+    (void)pmsLen;
+    (void)sHash;
+    (void)sHashLen;
+    (void)tls1_2;
+    (void)hash_type;
+    (void)heap;
+    (void)devId;
+#endif
+    return ret;
+}
+
+/* External facing wrapper so user can call as well, 0 on success */
+int wolfSSL_MakeTlsExtendedMasterSecret(byte* ms, word32 msLen,
+                                        const byte* pms, word32 pmsLen,
+                                        const byte* sHash, word32 sHashLen,
+                                        int tls1_2, int hash_type)
+{
+    return _MakeTlsExtendedMasterSecret(ms, msLen, pms, pmsLen, sHash, sHashLen,
+        tls1_2, hash_type, NULL, INVALID_DEVID);
+}
+
+#endif /* HAVE_EXTENDED_MASTER */
+
+
+int MakeTlsMasterSecret(WOLFSSL* ssl)
+{
+    int ret;
+
+#ifdef HAVE_EXTENDED_MASTER
+    if (ssl->options.haveEMS) {
+        word32 hashSz = HSHASH_SZ;
+    #ifdef WOLFSSL_SMALL_STACK
+        byte* handshake_hash = (byte*)XMALLOC(HSHASH_SZ, ssl->heap,
+                                              DYNAMIC_TYPE_DIGEST);
+        if (handshake_hash == NULL)
+            return MEMORY_E;
+    #else
+        byte handshake_hash[HSHASH_SZ];
+    #endif
+
+        ret = BuildTlsHandshakeHash(ssl, handshake_hash, &hashSz);
+        if (ret == 0) {
+            ret = _MakeTlsExtendedMasterSecret(
+                ssl->arrays->masterSecret, SECRET_LEN,
+                ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz,
+                handshake_hash, hashSz,
+                IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm,
+                ssl->heap, ssl->devId);
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(handshake_hash, ssl->heap, DYNAMIC_TYPE_DIGEST);
+    #endif
+    }
+    else
+#endif /* HAVE_EXTENDED_MASTER */
+    {
+#if defined(WOLFSSL_RENESAS_TSIP_TLS) && \
+    !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION)
+        if (tsip_useable(ssl)) {
+            ret = tsip_generateMasterSecret(
+                            &ssl->arrays->preMasterSecret[VERSION_SZ],
+                            ssl->arrays->clientRandom,
+                            ssl->arrays->serverRandom,
+                            ssl->arrays->tsip_masterSecret);
+        } else
+#endif
+        ret = _MakeTlsMasterSecret(ssl->arrays->masterSecret, SECRET_LEN,
+              ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz,
+              ssl->arrays->clientRandom, ssl->arrays->serverRandom,
+              IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm,
+              ssl->heap, ssl->devId);
+    }
+    if (ret == 0) {
+    #ifdef SHOW_SECRETS
+        /* Wireshark Pre-Master-Secret Format:
+         *  CLIENT_RANDOM <clientrandom> <mastersecret>
+         */
+        const char* CLIENT_RANDOM_LABEL = "CLIENT_RANDOM";
+        int i, pmsPos = 0;
+        char pmsBuf[13 + 1 + 64 + 1 + 96 + 1 + 1];
+
+        XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "%s ",
+            CLIENT_RANDOM_LABEL);
+        pmsPos += XSTRLEN(CLIENT_RANDOM_LABEL) + 1;
+        for (i = 0; i < RAN_LEN; i++) {
+            XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "%02x",
+                ssl->arrays->clientRandom[i]);
+            pmsPos += 2;
+        }
+        XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, " ");
+        pmsPos += 1;
+        for (i = 0; i < SECRET_LEN; i++) {
+            XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "%02x",
+                ssl->arrays->masterSecret[i]);
+            pmsPos += 2;
+        }
+        XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "\n");
+        pmsPos += 1;
+
+        /* print master secret */
+        puts(pmsBuf);
+
+        #if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SSLKEYLOGFILE)
+        {
+            FILE* f = XFOPEN(WOLFSSL_SSLKEYLOGFILE_OUTPUT, "a");
+            if (f != XBADFILE) {
+                XFWRITE(pmsBuf, 1, pmsPos, f);
+                XFCLOSE(f);
+            }
+        }
+        #endif
+    #endif /* SHOW_SECRETS */
+
+        ret = DeriveTlsKeys(ssl);
+    }
+
+    return ret;
+}
+
+
+/* Used by EAP-TLS and EAP-TTLS to derive keying material from
+ * the master_secret. */
+int wolfSSL_make_eap_keys(WOLFSSL* ssl, void* msk, unsigned int len,
+                                                              const char* label)
+{
+    int   ret;
+#ifdef WOLFSSL_SMALL_STACK
+    byte* seed;
+#else
+    byte  seed[SEED_LEN];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+    seed = (byte*)XMALLOC(SEED_LEN, ssl->heap, DYNAMIC_TYPE_SEED);
+    if (seed == NULL)
+        return MEMORY_E;
+#endif
+
+    /*
+     * As per RFC-5281, the order of the client and server randoms is reversed
+     * from that used by the TLS protocol to derive keys.
+     */
+    XMEMCPY(seed,           ssl->arrays->clientRandom, RAN_LEN);
+    XMEMCPY(seed + RAN_LEN, ssl->arrays->serverRandom, RAN_LEN);
+
+#ifdef WOLFSSL_HAVE_PRF
+    ret = wc_PRF_TLS((byte*)msk, len, ssl->arrays->masterSecret, SECRET_LEN,
+              (const byte *)label, (word32)XSTRLEN(label), seed, SEED_LEN,
+              IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm,
+              ssl->heap, ssl->devId);
+#else
+    /* Pseudo random function must be enabled in the configuration. */
+    ret = PRF_MISSING;
+    WOLFSSL_MSG("Pseudo-random function is not enabled");
+
+    (void)msk;
+    (void)len;
+    (void)label;
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(seed, ssl->heap, DYNAMIC_TYPE_SEED);
+#endif
+
+    return ret;
+}
+
+
+static WC_INLINE void GetSEQIncrement(WOLFSSL* ssl, int verify, word32 seq[2])
+{
+    if (verify) {
+        seq[0] = ssl->keys.peer_sequence_number_hi;
+        seq[1] = ssl->keys.peer_sequence_number_lo++;
+        if (seq[1] > ssl->keys.peer_sequence_number_lo) {
+            /* handle rollover */
+            ssl->keys.peer_sequence_number_hi++;
+        }
+    }
+    else {
+        seq[0] = ssl->keys.sequence_number_hi;
+        seq[1] = ssl->keys.sequence_number_lo++;
+        if (seq[1] > ssl->keys.sequence_number_lo) {
+            /* handle rollover */
+            ssl->keys.sequence_number_hi++;
+        }
+    }
+}
+
+
+#ifdef WOLFSSL_DTLS
+static WC_INLINE void DtlsGetSEQ(WOLFSSL* ssl, int order, word32 seq[2])
+{
+    if (order == PREV_ORDER) {
+        /* Previous epoch case */
+        seq[0] = (((word32)ssl->keys.dtls_epoch - 1) << 16) |
+                 (ssl->keys.dtls_prev_sequence_number_hi & 0xFFFF);
+        seq[1] = ssl->keys.dtls_prev_sequence_number_lo;
+    }
+    else if (order == PEER_ORDER) {
+        seq[0] = ((word32)ssl->keys.curEpoch << 16) |
+                 (ssl->keys.curSeq_hi & 0xFFFF);
+        seq[1] = ssl->keys.curSeq_lo; /* explicit from peer */
+    }
+    else {
+        seq[0] = ((word32)ssl->keys.dtls_epoch << 16) |
+                 (ssl->keys.dtls_sequence_number_hi & 0xFFFF);
+        seq[1] = ssl->keys.dtls_sequence_number_lo;
+    }
+}
+#endif /* WOLFSSL_DTLS */
+
+
+static WC_INLINE void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out)
+{
+    word32 seq[2] = {0, 0};
+
+    if (!ssl->options.dtls) {
+        GetSEQIncrement(ssl, verifyOrder, seq);
+    }
+    else {
+#ifdef WOLFSSL_DTLS
+        DtlsGetSEQ(ssl, verifyOrder, seq);
+#endif
+    }
+
+    c32toa(seq[0], out);
+    c32toa(seq[1], out + OPAQUE32_LEN);
+}
+
+
+/*** end copy ***/
+
+
+/* return HMAC digest type in wolfSSL format */
+int wolfSSL_GetHmacType(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    switch (ssl->specs.mac_algorithm) {
+        #ifndef NO_MD5
+        case md5_mac:
+        {
+            return WC_MD5;
+        }
+        #endif
+        #ifndef NO_SHA256
+        case sha256_mac:
+        {
+            return WC_SHA256;
+        }
+        #endif
+        #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+        {
+            return WC_SHA384;
+        }
+
+        #endif
+        #ifndef NO_SHA
+        case sha_mac:
+        {
+            return WC_SHA;
+        }
+        #endif
+        #ifdef HAVE_BLAKE2
+        case blake2b_mac:
+        {
+            return BLAKE2B_ID;
+        }
+        #endif
+        default:
+        {
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+}
+
+
+int wolfSSL_SetTlsHmacInner(WOLFSSL* ssl, byte* inner, word32 sz, int content,
+                           int verify)
+{
+    if (ssl == NULL || inner == NULL)
+        return BAD_FUNC_ARG;
+
+    XMEMSET(inner, 0, WOLFSSL_TLS_HMAC_INNER_SZ);
+
+    WriteSEQ(ssl, verify, inner);
+    inner[SEQ_SZ] = (byte)content;
+    inner[SEQ_SZ + ENUM_LEN]            = ssl->version.major;
+    inner[SEQ_SZ + ENUM_LEN + ENUM_LEN] = ssl->version.minor;
+    c16toa((word16)sz, inner + SEQ_SZ + ENUM_LEN + VERSION_SZ);
+
+    return 0;
+}
+
+
+#ifndef WOLFSSL_AEAD_ONLY
+#if !defined(WOLFSSL_NO_HASH_RAW) && !defined(HAVE_FIPS) && \
+    !defined(HAVE_SELFTEST)
+
+/* Update the hash in the HMAC.
+ *
+ * hmac  HMAC object.
+ * data  Data to be hashed.
+ * sz    Size of data to hash.
+ * returns 0 on success, otherwise failure.
+ */
+static int Hmac_HashUpdate(Hmac* hmac, const byte* data, word32 sz)
+{
+    int ret = BAD_FUNC_ARG;
+
+    switch (hmac->macType) {
+    #ifndef NO_SHA
+        case WC_SHA:
+            ret = wc_ShaUpdate(&hmac->hash.sha, data, sz);
+            break;
+    #endif /* !NO_SHA */
+
+    #ifndef NO_SHA256
+        case WC_SHA256:
+            ret = wc_Sha256Update(&hmac->hash.sha256, data, sz);
+            break;
+    #endif /* !NO_SHA256 */
+
+    #ifdef WOLFSSL_SHA384
+        case WC_SHA384:
+            ret = wc_Sha384Update(&hmac->hash.sha384, data, sz);
+            break;
+    #endif /* WOLFSSL_SHA384 */
+
+    #ifdef WOLFSSL_SHA512
+        case WC_SHA512:
+            ret = wc_Sha512Update(&hmac->hash.sha512, data, sz);
+            break;
+    #endif /* WOLFSSL_SHA512 */
+    }
+
+    return ret;
+}
+
+/* Finalize the hash but don't put the EOC, padding or length in.
+ *
+ * hmac  HMAC object.
+ * hash  Hash result.
+ * returns 0 on success, otherwise failure.
+ */
+static int Hmac_HashFinalRaw(Hmac* hmac, unsigned char* hash)
+{
+    int ret = BAD_FUNC_ARG;
+
+    switch (hmac->macType) {
+    #ifndef NO_SHA
+        case WC_SHA:
+            ret = wc_ShaFinalRaw(&hmac->hash.sha, hash);
+            break;
+    #endif /* !NO_SHA */
+
+    #ifndef NO_SHA256
+        case WC_SHA256:
+            ret = wc_Sha256FinalRaw(&hmac->hash.sha256, hash);
+            break;
+    #endif /* !NO_SHA256 */
+
+    #ifdef WOLFSSL_SHA384
+        case WC_SHA384:
+            ret = wc_Sha384FinalRaw(&hmac->hash.sha384, hash);
+            break;
+    #endif /* WOLFSSL_SHA384 */
+
+    #ifdef WOLFSSL_SHA512
+        case WC_SHA512:
+            ret = wc_Sha512FinalRaw(&hmac->hash.sha512, hash);
+            break;
+    #endif /* WOLFSSL_SHA512 */
+    }
+
+    return ret;
+}
+
+/* Finalize the HMAC by performing outer hash.
+ *
+ * hmac  HMAC object.
+ * mac   MAC result.
+ * returns 0 on success, otherwise failure.
+ */
+static int Hmac_OuterHash(Hmac* hmac, unsigned char* mac)
+{
+    int ret = BAD_FUNC_ARG;
+    wc_HashAlg hash;
+    enum wc_HashType hashType = (enum wc_HashType)hmac->macType;
+    int digestSz = wc_HashGetDigestSize(hashType);
+    int blockSz = wc_HashGetBlockSize(hashType);
+
+    if ((digestSz >= 0) && (blockSz >= 0)) {
+        ret = wc_HashInit(&hash, hashType);
+    }
+    if (ret == 0) {
+        ret = wc_HashUpdate(&hash, hashType, (byte*)hmac->opad,
+            blockSz);
+        if (ret == 0)
+            ret = wc_HashUpdate(&hash, hashType, (byte*)hmac->innerHash,
+                digestSz);
+        if (ret == 0)
+            ret = wc_HashFinal(&hash, hashType, mac);
+        wc_HashFree(&hash, hashType);
+    }
+
+    return ret;
+}
+
+/* Calculate the HMAC of the header + message data.
+ * Constant time implementation using wc_Sha*FinalRaw().
+ *
+ * hmac    HMAC object.
+ * digest  MAC result.
+ * in      Message data.
+ * sz      Size of the message data.
+ * header  Constructed record header with length of handshake data.
+ * returns 0 on success, otherwise failure.
+ */
+static int Hmac_UpdateFinal_CT(Hmac* hmac, byte* digest, const byte* in,
+                               word32 sz, byte* header)
+{
+    byte lenBytes[8];
+    int  i, j, k;
+    int  blockBits, blockMask;
+    int  lastBlockLen, macLen, extraLen, eocIndex;
+    int  blocks, safeBlocks, lenBlock, eocBlock;
+    int  maxLen;
+    int  blockSz, padSz;
+    int  ret;
+    word32 realLen;
+    byte extraBlock;
+
+    switch (hmac->macType) {
+    #ifndef NO_SHA
+        case WC_SHA:
+            blockSz = WC_SHA_BLOCK_SIZE;
+            blockBits = 6;
+            macLen = WC_SHA_DIGEST_SIZE;
+            padSz = WC_SHA_BLOCK_SIZE - WC_SHA_PAD_SIZE + 1;
+            break;
+    #endif /* !NO_SHA */
+
+    #ifndef NO_SHA256
+        case WC_SHA256:
+            blockSz = WC_SHA256_BLOCK_SIZE;
+            blockBits = 6;
+            macLen = WC_SHA256_DIGEST_SIZE;
+            padSz = WC_SHA256_BLOCK_SIZE - WC_SHA256_PAD_SIZE + 1;
+            break;
+    #endif /* !NO_SHA256 */
+
+    #ifdef WOLFSSL_SHA384
+        case WC_SHA384:
+            blockSz = WC_SHA384_BLOCK_SIZE;
+            blockBits = 7;
+            macLen = WC_SHA384_DIGEST_SIZE;
+            padSz = WC_SHA384_BLOCK_SIZE - WC_SHA384_PAD_SIZE + 1;
+            break;
+    #endif /* WOLFSSL_SHA384 */
+
+    #ifdef WOLFSSL_SHA512
+        case WC_SHA512:
+            blockSz = WC_SHA512_BLOCK_SIZE;
+            blockBits = 7;
+            macLen = WC_SHA512_DIGEST_SIZE;
+            padSz = WC_SHA512_BLOCK_SIZE - WC_SHA512_PAD_SIZE + 1;
+            break;
+    #endif /* WOLFSSL_SHA512 */
+
+        default:
+            return BAD_FUNC_ARG;
+    }
+    blockMask = blockSz - 1;
+
+    /* Size of data to HMAC if padding length byte is zero. */
+    maxLen = WOLFSSL_TLS_HMAC_INNER_SZ + sz - 1 - macLen;
+    /* Complete data (including padding) has block for EOC and/or length. */
+    extraBlock = ctSetLTE((maxLen + padSz) & blockMask, padSz);
+    /* Total number of blocks for data including padding. */
+    blocks = ((maxLen + blockSz - 1) >> blockBits) + extraBlock;
+    /* Up to last 6 blocks can be hashed safely. */
+    safeBlocks = blocks - 6;
+
+    /* Length of message data. */
+    realLen = maxLen - in[sz - 1];
+    /* Number of message bytes in last block. */
+    lastBlockLen = realLen & blockMask;
+    /* Number of padding bytes in last block. */
+    extraLen = ((blockSz * 2 - padSz - lastBlockLen) & blockMask) + 1;
+    /* Number of blocks to create for hash. */
+    lenBlock = (realLen + extraLen) >> blockBits;
+    /* Block containing EOC byte. */
+    eocBlock = realLen >> blockBits;
+    /* Index of EOC byte in block. */
+    eocIndex = realLen & blockMask;
+
+    /* Add length of hmac's ipad to total length. */
+    realLen += blockSz;
+    /* Length as bits - 8 bytes bigendian. */
+    c32toa(realLen >> ((sizeof(word32) * 8) - 3), lenBytes);
+    c32toa(realLen << 3, lenBytes + sizeof(word32));
+
+    ret = Hmac_HashUpdate(hmac, (unsigned char*)hmac->ipad, blockSz);
+    if (ret != 0)
+        return ret;
+
+    XMEMSET(hmac->innerHash, 0, macLen);
+
+    if (safeBlocks > 0) {
+        ret = Hmac_HashUpdate(hmac, header, WOLFSSL_TLS_HMAC_INNER_SZ);
+        if (ret != 0)
+            return ret;
+        ret = Hmac_HashUpdate(hmac, in, safeBlocks * blockSz -
+                                                     WOLFSSL_TLS_HMAC_INNER_SZ);
+        if (ret != 0)
+            return ret;
+    }
+    else
+        safeBlocks = 0;
+
+    XMEMSET(digest, 0, macLen);
+    k = safeBlocks * blockSz;
+    for (i = safeBlocks; i < blocks; i++) {
+        unsigned char hashBlock[WC_MAX_BLOCK_SIZE];
+        unsigned char isEocBlock = ctMaskEq(i, eocBlock);
+        unsigned char isOutBlock = ctMaskEq(i, lenBlock);
+
+        for (j = 0; j < blockSz; j++, k++) {
+            unsigned char atEoc = ctMaskEq(j, eocIndex) & isEocBlock;
+            unsigned char pastEoc = ctMaskGT(j, eocIndex) & isEocBlock;
+            unsigned char b = 0;
+
+            if (k < WOLFSSL_TLS_HMAC_INNER_SZ)
+                b = header[k];
+            else if (k < maxLen)
+                b = in[k - WOLFSSL_TLS_HMAC_INNER_SZ];
+
+            b = ctMaskSel(atEoc, 0x80, b);
+            b &= (unsigned char)~(word32)pastEoc;
+            b &= ((unsigned char)~(word32)isOutBlock) | isEocBlock;
+
+            if (j >= blockSz - 8) {
+                b = ctMaskSel(isOutBlock, lenBytes[j - (blockSz - 8)], b);
+            }
+
+            hashBlock[j] = b;
+        }
+
+        ret = Hmac_HashUpdate(hmac, hashBlock, blockSz);
+        if (ret != 0)
+            return ret;
+        ret = Hmac_HashFinalRaw(hmac, hashBlock);
+        if (ret != 0)
+            return ret;
+        for (j = 0; j < macLen; j++)
+            ((unsigned char*)hmac->innerHash)[j] |= hashBlock[j] & isOutBlock;
+    }
+
+    ret = Hmac_OuterHash(hmac, digest);
+
+    return ret;
+}
+
+#endif
+
+#if defined(WOLFSSL_NO_HASH_RAW) || defined(HAVE_FIPS) || \
+    defined(HAVE_SELFTEST) || defined(HAVE_BLAKE2)
+
+/* Calculate the HMAC of the header + message data.
+ * Constant time implementation using normal hashing operations.
+ * Update-Final need to be constant time.
+ *
+ * hmac    HMAC object.
+ * digest  MAC result.
+ * in      Message data.
+ * sz      Size of the message data.
+ * header  Constructed record header with length of handshake data.
+ * returns 0 on success, otherwise failure.
+ */
+static int Hmac_UpdateFinal(Hmac* hmac, byte* digest, const byte* in,
+                            word32 sz, byte* header)
+{
+    byte       dummy[WC_MAX_BLOCK_SIZE] = {0};
+    int        ret;
+    word32     msgSz, blockSz, macSz, padSz, maxSz, realSz;
+    word32     currSz, offset = 0;
+    int        msgBlocks, blocks, blockBits;
+    int        i;
+
+    switch (hmac->macType) {
+    #ifndef NO_SHA
+        case WC_SHA:
+            blockSz = WC_SHA_BLOCK_SIZE;
+            blockBits = 6;
+            macSz = WC_SHA_DIGEST_SIZE;
+            padSz = WC_SHA_BLOCK_SIZE - WC_SHA_PAD_SIZE + 1;
+            break;
+    #endif /* !NO_SHA */
+
+    #ifndef NO_SHA256
+        case WC_SHA256:
+            blockSz = WC_SHA256_BLOCK_SIZE;
+            blockBits = 6;
+            macSz = WC_SHA256_DIGEST_SIZE;
+            padSz = WC_SHA256_BLOCK_SIZE - WC_SHA256_PAD_SIZE + 1;
+            break;
+    #endif /* !NO_SHA256 */
+
+    #ifdef WOLFSSL_SHA384
+        case WC_SHA384:
+            blockSz = WC_SHA384_BLOCK_SIZE;
+            blockBits = 7;
+            macSz = WC_SHA384_DIGEST_SIZE;
+            padSz = WC_SHA384_BLOCK_SIZE - WC_SHA384_PAD_SIZE + 1;
+            break;
+    #endif /* WOLFSSL_SHA384 */
+
+    #ifdef WOLFSSL_SHA512
+        case WC_SHA512:
+            blockSz = WC_SHA512_BLOCK_SIZE;
+            blockBits = 7;
+            macSz = WC_SHA512_DIGEST_SIZE;
+            padSz = WC_SHA512_BLOCK_SIZE - WC_SHA512_PAD_SIZE + 1;
+            break;
+    #endif /* WOLFSSL_SHA512 */
+
+    #ifdef HAVE_BLAKE2
+        case WC_HASH_TYPE_BLAKE2B:
+            blockSz = BLAKE2B_BLOCKBYTES;
+            blockBits = 7;
+            macSz = BLAKE2B_256;
+            padSz = 0;
+            break;
+    #endif /* HAVE_BLAK2 */
+
+        default:
+            return BAD_FUNC_ARG;
+    }
+
+    msgSz = sz - (1 + in[sz - 1] + macSz);
+    /* Make negative result 0 */
+    msgSz &= ~(0 - (msgSz >> 31));
+    realSz = WOLFSSL_TLS_HMAC_INNER_SZ + msgSz;
+    maxSz = WOLFSSL_TLS_HMAC_INNER_SZ + (sz - 1) - macSz;
+
+    /* Calculate #blocks processed in HMAC for max and real data. */
+    blocks      = maxSz >> blockBits;
+    blocks     += ((maxSz + padSz) % blockSz) < padSz;
+    msgBlocks   = realSz >> blockBits;
+    /* #Extra blocks to process. */
+    blocks -= msgBlocks + (((realSz + padSz) % blockSz) < padSz);
+    /* Calculate whole blocks. */
+    msgBlocks--;
+
+    ret = wc_HmacUpdate(hmac, header, WOLFSSL_TLS_HMAC_INNER_SZ);
+    if (ret == 0) {
+        /* Fill the rest of the block with any available data. */
+        currSz = ctMaskLT(msgSz, blockSz) & msgSz;
+        currSz |= ctMaskGTE(msgSz, blockSz) & blockSz;
+        currSz -= WOLFSSL_TLS_HMAC_INNER_SZ;
+        currSz &= ~(0 - (currSz >> 31));
+        ret = wc_HmacUpdate(hmac, in, currSz);
+        offset = currSz;
+    }
+    if (ret == 0) {
+        /* Do the hash operations on a block basis. */
+        for (i = 0; i < msgBlocks; i++, offset += blockSz) {
+            ret = wc_HmacUpdate(hmac, in + offset, blockSz);
+            if (ret != 0)
+                break;
+        }
+    }
+    if (ret == 0)
+        ret = wc_HmacUpdate(hmac, in + offset, msgSz - offset);
+    if (ret == 0)
+        ret = wc_HmacFinal(hmac, digest);
+    if (ret == 0) {
+        /* Do the dummy hash operations. Do at least one. */
+        for (i = 0; i < blocks + 1; i++) {
+            ret = wc_HmacUpdate(hmac, dummy, blockSz);
+            if (ret != 0)
+                break;
+        }
+    }
+
+    return ret;
+}
+
+#endif
+
+int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, int padSz,
+             int content, int verify)
+{
+    Hmac   hmac;
+    byte   myInner[WOLFSSL_TLS_HMAC_INNER_SZ];
+    int    ret = 0;
+#ifdef HAVE_TRUNCATED_HMAC
+    word32 hashSz = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ
+                                        : ssl->specs.hash_size;
+#else
+    word32 hashSz = ssl->specs.hash_size;
+#endif
+
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+#ifdef HAVE_FUZZER
+    /* Fuzz "in" buffer with sz to be used in HMAC algorithm */
+    if (ssl->fuzzerCb) {
+        if (verify && padSz >= 0) {
+            ssl->fuzzerCb(ssl, in, sz + hashSz + padSz + 1, FUZZ_HMAC,
+                          ssl->fuzzerCtx);
+        }
+        else {
+            ssl->fuzzerCb(ssl, in, sz, FUZZ_HMAC, ssl->fuzzerCtx);
+        }
+    }
+#endif
+
+    wolfSSL_SetTlsHmacInner(ssl, myInner, sz, content, verify);
+#if defined(WOLFSSL_RENESAS_TSIP_TLS) && \
+    !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION)
+    if (tsip_useable(ssl)) {
+        if (ssl->specs.hash_size == WC_SHA_DIGEST_SIZE)
+            ret = tsip_Sha1Hmac(ssl, myInner, WOLFSSL_TLS_HMAC_INNER_SZ,
+                                                        in, sz, digest, verify);
+        else if (ssl->specs.hash_size == WC_SHA256_DIGEST_SIZE)
+            ret = tsip_Sha256Hmac(ssl, myInner, WOLFSSL_TLS_HMAC_INNER_SZ,
+                                                        in, sz, digest, verify);
+        else
+            ret = TSIP_MAC_DIGSZ_E;
+
+        return ret;
+    }
+#endif
+    ret = wc_HmacInit(&hmac, ssl->heap, ssl->devId);
+    if (ret != 0)
+        return ret;
+
+    ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl),
+                                              wolfSSL_GetMacSecret(ssl, verify),
+                                              ssl->specs.hash_size);
+    if (ret == 0) {
+        /* Constant time verification required. */
+        if (verify && padSz >= 0) {
+#if !defined(WOLFSSL_NO_HASH_RAW) && !defined(HAVE_FIPS) && \
+    !defined(HAVE_SELFTEST)
+    #ifdef HAVE_BLAKE2
+            if (wolfSSL_GetHmacType(ssl) == WC_HASH_TYPE_BLAKE2B) {
+                ret = Hmac_UpdateFinal(&hmac, digest, in,
+                                              sz + hashSz + padSz + 1, myInner);
+            }
+            else
+    #endif
+            {
+                ret = Hmac_UpdateFinal_CT(&hmac, digest, in,
+                                              sz + hashSz + padSz + 1, myInner);
+            }
+#else
+            ret = Hmac_UpdateFinal(&hmac, digest, in, sz + hashSz + padSz + 1,
+                                                                       myInner);
+#endif
+        }
+        else {
+            ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner));
+            if (ret == 0)
+                ret = wc_HmacUpdate(&hmac, in, sz);                /* content */
+            if (ret == 0)
+                ret = wc_HmacFinal(&hmac, digest);
+        }
+    }
+
+    wc_HmacFree(&hmac);
+
+    return ret;
+}
+#endif /* WOLFSSL_AEAD_ONLY */
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#ifdef HAVE_TLS_EXTENSIONS
+
+/**
+ * The TLSX semaphore is used to calculate the size of the extensions to be sent
+ * from one peer to another.
+ */
+
+/** Supports up to 64 flags. Increase as needed. */
+#define SEMAPHORE_SIZE 8
+
+/**
+ * Converts the extension type (id) to an index in the semaphore.
+ *
+ * Official reference for TLS extension types:
+ *   http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xml
+ *
+ * Motivation:
+ *   Previously, we used the extension type itself as the index of that
+ *   extension in the semaphore as the extension types were declared
+ *   sequentially, but maintain a semaphore as big as the number of available
+ *   extensions is no longer an option since the release of renegotiation_info.
+ *
+ * How to update:
+ *   Assign extension types that extrapolate the number of available semaphores
+ *   to the first available index going backwards in the semaphore array.
+ *   When adding a new extension type that don't extrapolate the number of
+ *   available semaphores, check for a possible collision with with a
+ *   'remapped' extension type.
+ */
+static WC_INLINE word16 TLSX_ToSemaphore(word16 type)
+{
+    switch (type) {
+
+        case TLSX_RENEGOTIATION_INFO: /* 0xFF01 */
+            return 63;
+
+        default:
+            if (type > 62) {
+                /* This message SHOULD only happens during the adding of
+                   new TLS extensions in which its IANA number overflows
+                   the current semaphore's range, or if its number already
+                   is assigned to be used by another extension.
+                   Use this check value for the new extension and decrement
+                   the check value by one. */
+                WOLFSSL_MSG("### TLSX semaphore collision or overflow detected!");
+            }
+    }
+
+    return type;
+}
+
+/** Checks if a specific light (tls extension) is not set in the semaphore. */
+#define IS_OFF(semaphore, light) \
+    (!(((semaphore)[(light) / 8] &  (byte) (0x01 << ((light) % 8)))))
+
+/** Turn on a specific light (tls extension) in the semaphore. */
+/* the semaphore marks the extensions already written to the message */
+#define TURN_ON(semaphore, light) \
+    ((semaphore)[(light) / 8] |= (byte) (0x01 << ((light) % 8)))
+
+/** Turn off a specific light (tls extension) in the semaphore. */
+#define TURN_OFF(semaphore, light) \
+    ((semaphore)[(light) / 8] &= (byte) ~(0x01 << ((light) % 8)))
+
+/** Creates a new extension. */
+static TLSX* TLSX_New(TLSX_Type type, void* data, void* heap)
+{
+    TLSX* extension = (TLSX*)XMALLOC(sizeof(TLSX), heap, DYNAMIC_TYPE_TLSX);
+
+    (void)heap;
+
+    if (extension) {
+        extension->type = type;
+        extension->data = data;
+        extension->resp = 0;
+        extension->next = NULL;
+    }
+
+    return extension;
+}
+
+/**
+ * Creates a new extension and pushes it to the provided list.
+ * Checks for duplicate extensions, keeps the newest.
+ */
+static int TLSX_Push(TLSX** list, TLSX_Type type, void* data, void* heap)
+{
+    TLSX* extension = TLSX_New(type, data, heap);
+
+    if (extension == NULL)
+        return MEMORY_E;
+
+    /* pushes the new extension on the list. */
+    extension->next = *list;
+    *list = extension;
+
+    /* remove duplicate extensions, there should be only one of each type. */
+    do {
+        if (extension->next && extension->next->type == type) {
+            TLSX *next = extension->next;
+
+            extension->next = next->next;
+            next->next = NULL;
+
+            TLSX_FreeAll(next, heap);
+
+            /* there is no way to occur more than
+             * two extensions of the same type.
+             */
+            break;
+        }
+    } while ((extension = extension->next));
+
+    return 0;
+}
+
+#ifndef NO_WOLFSSL_CLIENT
+
+int TLSX_CheckUnsupportedExtension(WOLFSSL* ssl, TLSX_Type type);
+
+int TLSX_CheckUnsupportedExtension(WOLFSSL* ssl, TLSX_Type type)
+{
+    TLSX *extension = TLSX_Find(ssl->extensions, type);
+
+    if (!extension)
+        extension = TLSX_Find(ssl->ctx->extensions, type);
+
+    return extension == NULL;
+}
+
+int TLSX_HandleUnsupportedExtension(WOLFSSL* ssl);
+
+int TLSX_HandleUnsupportedExtension(WOLFSSL* ssl)
+{
+    SendAlert(ssl, alert_fatal, unsupported_extension);
+    return UNSUPPORTED_EXTENSION;
+}
+
+#else
+
+#define TLSX_CheckUnsupportedExtension(ssl, type) 0
+#define TLSX_HandleUnsupportedExtension(ssl) 0
+
+#endif
+
+/** Mark an extension to be sent back to the client. */
+void TLSX_SetResponse(WOLFSSL* ssl, TLSX_Type type);
+
+void TLSX_SetResponse(WOLFSSL* ssl, TLSX_Type type)
+{
+    TLSX *extension = TLSX_Find(ssl->extensions, type);
+
+    if (extension)
+        extension->resp = 1;
+}
+
+/******************************************************************************/
+/* Application-Layer Protocol Negotiation                                     */
+/******************************************************************************/
+
+#ifdef HAVE_ALPN
+/** Creates a new ALPN object, providing protocol name to use. */
+static ALPN* TLSX_ALPN_New(char *protocol_name, word16 protocol_nameSz,
+                                                                     void* heap)
+{
+    ALPN *alpn;
+
+    WOLFSSL_ENTER("TLSX_ALPN_New");
+
+    if (protocol_name == NULL ||
+        protocol_nameSz > WOLFSSL_MAX_ALPN_PROTO_NAME_LEN) {
+        WOLFSSL_MSG("Invalid arguments");
+        return NULL;
+    }
+
+    alpn = (ALPN*)XMALLOC(sizeof(ALPN), heap, DYNAMIC_TYPE_TLSX);
+    if (alpn == NULL) {
+        WOLFSSL_MSG("Memory failure");
+        return NULL;
+    }
+
+    alpn->next = NULL;
+    alpn->negotiated = 0;
+    alpn->options = 0;
+
+    alpn->protocol_name = (char*)XMALLOC(protocol_nameSz + 1,
+                                         heap, DYNAMIC_TYPE_TLSX);
+    if (alpn->protocol_name == NULL) {
+        WOLFSSL_MSG("Memory failure");
+        XFREE(alpn, heap, DYNAMIC_TYPE_TLSX);
+        return NULL;
+    }
+
+    XMEMCPY(alpn->protocol_name, protocol_name, protocol_nameSz);
+    alpn->protocol_name[protocol_nameSz] = 0;
+
+    (void)heap;
+
+    return alpn;
+}
+
+/** Releases an ALPN object. */
+static void TLSX_ALPN_Free(ALPN *alpn, void* heap)
+{
+    (void)heap;
+
+    if (alpn == NULL)
+        return;
+
+    XFREE(alpn->protocol_name, heap, DYNAMIC_TYPE_TLSX);
+    XFREE(alpn, heap, DYNAMIC_TYPE_TLSX);
+}
+
+/** Releases all ALPN objects in the provided list. */
+static void TLSX_ALPN_FreeAll(ALPN *list, void* heap)
+{
+    ALPN* alpn;
+
+    while ((alpn = list)) {
+        list = alpn->next;
+        TLSX_ALPN_Free(alpn, heap);
+    }
+}
+
+/** Tells the buffered size of the ALPN objects in a list. */
+static word16 TLSX_ALPN_GetSize(ALPN *list)
+{
+    ALPN* alpn;
+    word16 length = OPAQUE16_LEN; /* list length */
+
+    while ((alpn = list)) {
+        list = alpn->next;
+
+        length++; /* protocol name length is on one byte */
+        length += (word16)XSTRLEN(alpn->protocol_name);
+    }
+
+    return length;
+}
+
+/** Writes the ALPN objects of a list in a buffer. */
+static word16 TLSX_ALPN_Write(ALPN *list, byte *output)
+{
+    ALPN* alpn;
+    word16 length = 0;
+    word16 offset = OPAQUE16_LEN; /* list length offset */
+
+    while ((alpn = list)) {
+        list = alpn->next;
+
+        length = (word16)XSTRLEN(alpn->protocol_name);
+
+        /* protocol name length */
+        output[offset++] = (byte)length;
+
+        /* protocol name value */
+        XMEMCPY(output + offset, alpn->protocol_name, length);
+
+        offset += length;
+    }
+
+    /* writing list length */
+    c16toa(offset - OPAQUE16_LEN, output);
+
+    return offset;
+}
+
+/** Finds a protocol name in the provided ALPN list */
+static ALPN* TLSX_ALPN_Find(ALPN *list, char *protocol_name, word16 size)
+{
+    ALPN *alpn;
+
+    if (list == NULL || protocol_name == NULL)
+        return NULL;
+
+    alpn = list;
+    while (alpn != NULL && (
+           (word16)XSTRLEN(alpn->protocol_name) != size ||
+           XSTRNCMP(alpn->protocol_name, protocol_name, size)))
+        alpn = alpn->next;
+
+    return alpn;
+}
+
+/** Set the ALPN matching client and server requirements */
+static int TLSX_SetALPN(TLSX** extensions, const void* data, word16 size,
+                                                                     void* heap)
+{
+    ALPN *alpn;
+    int  ret;
+
+    if (extensions == NULL || data == NULL)
+        return BAD_FUNC_ARG;
+
+    alpn = TLSX_ALPN_New((char *)data, size, heap);
+    if (alpn == NULL) {
+        WOLFSSL_MSG("Memory failure");
+        return MEMORY_E;
+    }
+
+    alpn->negotiated = 1;
+
+    ret = TLSX_Push(extensions, TLSX_APPLICATION_LAYER_PROTOCOL, (void*)alpn,
+                                                                          heap);
+    if (ret != 0) {
+        TLSX_ALPN_Free(alpn, heap);
+        return ret;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+/** Parses a buffer of ALPN extensions and set the first one matching
+ * client and server requirements */
+static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, byte *input, word16 length,
+                                 byte isRequest)
+{
+    word16  size = 0, offset = 0, idx = 0;
+    int     r = BUFFER_ERROR;
+    byte    match = 0;
+    TLSX    *extension;
+    ALPN    *alpn = NULL, *list;
+
+    if (OPAQUE16_LEN > length)
+        return BUFFER_ERROR;
+
+    ato16(input, &size);
+    offset += OPAQUE16_LEN;
+
+    if (size == 0)
+        return BUFFER_ERROR;
+
+    extension = TLSX_Find(ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL);
+    if (extension == NULL)
+        extension = TLSX_Find(ssl->ctx->extensions,
+                                               TLSX_APPLICATION_LAYER_PROTOCOL);
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+    if (ssl->alpnSelect != NULL) {
+        const byte* out;
+        unsigned char outLen;
+
+        if (ssl->alpnSelect(ssl, &out, &outLen, input + offset, size,
+                            ssl->alpnSelectArg) == 0) {
+            WOLFSSL_MSG("ALPN protocol match");
+            if (TLSX_UseALPN(&ssl->extensions, (char*)out, outLen, 0, ssl->heap)
+                                                           == WOLFSSL_SUCCESS) {
+                if (extension == NULL) {
+                    extension = TLSX_Find(ssl->extensions,
+                                          TLSX_APPLICATION_LAYER_PROTOCOL);
+                }
+            }
+        }
+    }
+#endif
+
+    if (extension == NULL || extension->data == NULL) {
+        return isRequest ? 0
+                         : TLSX_HandleUnsupportedExtension(ssl);
+    }
+
+    /* validating alpn list length */
+    if (length != OPAQUE16_LEN + size)
+        return BUFFER_ERROR;
+
+    list = (ALPN*)extension->data;
+
+    /* keep the list sent by client */
+    if (isRequest) {
+        if (ssl->alpn_client_list != NULL)
+            XFREE(ssl->alpn_client_list, ssl->heap, DYNAMIC_TYPE_ALPN);
+
+        ssl->alpn_client_list = (char *)XMALLOC(size, ssl->heap,
+                                                DYNAMIC_TYPE_ALPN);
+        if (ssl->alpn_client_list == NULL)
+            return MEMORY_ERROR;
+    }
+
+    for (size = 0; offset < length; offset += size) {
+
+        size = input[offset++];
+        if (offset + size > length || size == 0)
+            return BUFFER_ERROR;
+
+        if (isRequest) {
+            XMEMCPY(ssl->alpn_client_list+idx, (char*)input + offset, size);
+            idx += size;
+            ssl->alpn_client_list[idx++] = ',';
+        }
+
+        if (!match) {
+            alpn = TLSX_ALPN_Find(list, (char*)input + offset, size);
+            if (alpn != NULL) {
+                WOLFSSL_MSG("ALPN protocol match");
+                match = 1;
+
+                /* skip reading other values if not required */
+                if (!isRequest)
+                    break;
+            }
+        }
+    }
+
+    if (isRequest)
+        ssl->alpn_client_list[idx-1] = 0;
+
+    if (!match) {
+        WOLFSSL_MSG("No ALPN protocol match");
+
+        /* do nothing if no protocol match between client and server and option
+         is set to continue (like OpenSSL) */
+        if (list->options & WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) {
+            WOLFSSL_MSG("Continue on mismatch");
+            return 0;
+        }
+
+        SendAlert(ssl, alert_fatal, no_application_protocol);
+        return UNKNOWN_ALPN_PROTOCOL_NAME_E;
+    }
+
+    /* set the matching negotiated protocol */
+    r = TLSX_SetALPN(&ssl->extensions,
+                     alpn->protocol_name,
+                     (word16)XSTRLEN(alpn->protocol_name),
+                     ssl->heap);
+    if (r != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("TLSX_UseALPN failed");
+        return BUFFER_ERROR;
+    }
+
+    /* reply to ALPN extension sent from client */
+    if (isRequest) {
+#ifndef NO_WOLFSSL_SERVER
+        TLSX_SetResponse(ssl, TLSX_APPLICATION_LAYER_PROTOCOL);
+#endif
+    }
+
+    return 0;
+}
+
+/** Add a protocol name to the list of accepted usable ones */
+int TLSX_UseALPN(TLSX** extensions, const void* data, word16 size, byte options,
+                                                                     void* heap)
+{
+    ALPN *alpn;
+    TLSX *extension;
+    int  ret;
+
+    if (extensions == NULL || data == NULL)
+        return BAD_FUNC_ARG;
+
+    alpn = TLSX_ALPN_New((char *)data, size, heap);
+    if (alpn == NULL) {
+        WOLFSSL_MSG("Memory failure");
+        return MEMORY_E;
+    }
+
+    /* Set Options of ALPN */
+    alpn->options = options;
+
+    extension = TLSX_Find(*extensions, TLSX_APPLICATION_LAYER_PROTOCOL);
+    if (extension == NULL) {
+        ret = TLSX_Push(extensions, TLSX_APPLICATION_LAYER_PROTOCOL,
+                                                             (void*)alpn, heap);
+        if (ret != 0) {
+            TLSX_ALPN_Free(alpn, heap);
+            return ret;
+        }
+    }
+    else {
+        /* push new ALPN object to extension data. */
+        alpn->next = (ALPN*)extension->data;
+        extension->data = (void*)alpn;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+/** Get the protocol name set by the server */
+int TLSX_ALPN_GetRequest(TLSX* extensions, void** data, word16 *dataSz)
+{
+    TLSX *extension;
+    ALPN *alpn;
+
+    if (extensions == NULL || data == NULL || dataSz == NULL)
+        return BAD_FUNC_ARG;
+
+    extension = TLSX_Find(extensions, TLSX_APPLICATION_LAYER_PROTOCOL);
+    if (extension == NULL) {
+        WOLFSSL_MSG("TLS extension not found");
+        return WOLFSSL_ALPN_NOT_FOUND;
+    }
+
+    alpn = (ALPN *)extension->data;
+    if (alpn == NULL) {
+        WOLFSSL_MSG("ALPN extension not found");
+        *data = NULL;
+        *dataSz = 0;
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (alpn->negotiated != 1) {
+
+        /* consider as an error */
+        if (alpn->options & WOLFSSL_ALPN_FAILED_ON_MISMATCH) {
+            WOLFSSL_MSG("No protocol match with peer -> Failed");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        /* continue without negotiated protocol */
+        WOLFSSL_MSG("No protocol match with peer -> Continue");
+        return WOLFSSL_ALPN_NOT_FOUND;
+    }
+
+    if (alpn->next != NULL) {
+        WOLFSSL_MSG("Only one protocol name must be accepted");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    *data = alpn->protocol_name;
+    *dataSz = (word16)XSTRLEN((char*)*data);
+
+    return WOLFSSL_SUCCESS;
+}
+
+#define ALPN_FREE_ALL     TLSX_ALPN_FreeAll
+#define ALPN_GET_SIZE     TLSX_ALPN_GetSize
+#define ALPN_WRITE        TLSX_ALPN_Write
+#define ALPN_PARSE        TLSX_ALPN_ParseAndSet
+
+#else /* HAVE_ALPN */
+
+#define ALPN_FREE_ALL(list, heap)
+#define ALPN_GET_SIZE(list)     0
+#define ALPN_WRITE(a, b)        0
+#define ALPN_PARSE(a, b, c, d)  0
+
+#endif /* HAVE_ALPN */
+
+/******************************************************************************/
+/* Server Name Indication                                                     */
+/******************************************************************************/
+
+#ifdef HAVE_SNI
+
+/** Creates a new SNI object. */
+static SNI* TLSX_SNI_New(byte type, const void* data, word16 size, void* heap)
+{
+    SNI* sni = (SNI*)XMALLOC(sizeof(SNI), heap, DYNAMIC_TYPE_TLSX);
+
+    (void)heap;
+
+    if (sni) {
+        sni->type = type;
+        sni->next = NULL;
+
+    #ifndef NO_WOLFSSL_SERVER
+        sni->options = 0;
+        sni->status  = WOLFSSL_SNI_NO_MATCH;
+    #endif
+
+        switch (sni->type) {
+            case WOLFSSL_SNI_HOST_NAME:
+                sni->data.host_name = (char*)XMALLOC(size + 1, heap,
+                                                     DYNAMIC_TYPE_TLSX);
+                if (sni->data.host_name) {
+                    XSTRNCPY(sni->data.host_name, (const char*)data, size);
+                    sni->data.host_name[size] = '\0';
+                } else {
+                    XFREE(sni, heap, DYNAMIC_TYPE_TLSX);
+                    sni = NULL;
+                }
+            break;
+
+            default: /* invalid type */
+                XFREE(sni, heap, DYNAMIC_TYPE_TLSX);
+                sni = NULL;
+        }
+    }
+
+    return sni;
+}
+
+/** Releases a SNI object. */
+static void TLSX_SNI_Free(SNI* sni, void* heap)
+{
+    if (sni) {
+        switch (sni->type) {
+            case WOLFSSL_SNI_HOST_NAME:
+                XFREE(sni->data.host_name, heap, DYNAMIC_TYPE_TLSX);
+            break;
+        }
+
+        XFREE(sni, heap, DYNAMIC_TYPE_TLSX);
+    }
+    (void)heap;
+}
+
+/** Releases all SNI objects in the provided list. */
+static void TLSX_SNI_FreeAll(SNI* list, void* heap)
+{
+    SNI* sni;
+
+    while ((sni = list)) {
+        list = sni->next;
+        TLSX_SNI_Free(sni, heap);
+    }
+}
+
+/** Tells the buffered size of the SNI objects in a list. */
+static word16 TLSX_SNI_GetSize(SNI* list)
+{
+    SNI* sni;
+    word16 length = OPAQUE16_LEN; /* list length */
+
+    while ((sni = list)) {
+        list = sni->next;
+
+        length += ENUM_LEN + OPAQUE16_LEN; /* sni type + sni length */
+
+        switch (sni->type) {
+            case WOLFSSL_SNI_HOST_NAME:
+                length += (word16)XSTRLEN((char*)sni->data.host_name);
+            break;
+        }
+    }
+
+    return length;
+}
+
+/** Writes the SNI objects of a list in a buffer. */
+static word16 TLSX_SNI_Write(SNI* list, byte* output)
+{
+    SNI* sni;
+    word16 length = 0;
+    word16 offset = OPAQUE16_LEN; /* list length offset */
+
+    while ((sni = list)) {
+        list = sni->next;
+
+        output[offset++] = sni->type; /* sni type */
+
+        switch (sni->type) {
+            case WOLFSSL_SNI_HOST_NAME:
+                length = (word16)XSTRLEN((char*)sni->data.host_name);
+
+                c16toa(length, output + offset); /* sni length */
+                offset += OPAQUE16_LEN;
+
+                XMEMCPY(output + offset, sni->data.host_name, length);
+
+                offset += length;
+            break;
+        }
+    }
+
+    c16toa(offset - OPAQUE16_LEN, output); /* writing list length */
+
+    return offset;
+}
+
+/** Finds a SNI object in the provided list. */
+static SNI* TLSX_SNI_Find(SNI *list, byte type)
+{
+    SNI* sni = list;
+
+    while (sni && sni->type != type)
+        sni = sni->next;
+
+    return sni;
+}
+
+/** Sets the status of a SNI object. */
+static void TLSX_SNI_SetStatus(TLSX* extensions, byte type, byte status)
+{
+    TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME);
+    SNI* sni = TLSX_SNI_Find(extension ? (SNI*)extension->data : NULL, type);
+
+    if (sni)
+        sni->status = status;
+}
+
+/** Gets the status of a SNI object. */
+byte TLSX_SNI_Status(TLSX* extensions, byte type)
+{
+    TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME);
+    SNI* sni = TLSX_SNI_Find(extension ? (SNI*)extension->data : NULL, type);
+
+    if (sni)
+        return sni->status;
+
+    return 0;
+}
+
+/** Parses a buffer of SNI extensions. */
+static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length,
+                                                                 byte isRequest)
+{
+#ifndef NO_WOLFSSL_SERVER
+    word16 size = 0;
+    word16 offset = 0;
+    int cacheOnly = 0;
+    SNI *sni = NULL;
+    byte type;
+    int matchStat;
+    byte matched;
+#endif
+
+    TLSX *extension = TLSX_Find(ssl->extensions, TLSX_SERVER_NAME);
+
+    if (!extension)
+        extension = TLSX_Find(ssl->ctx->extensions, TLSX_SERVER_NAME);
+
+    if (!isRequest) {
+        #ifndef NO_WOLFSSL_CLIENT
+            if (!extension || !extension->data)
+                return TLSX_HandleUnsupportedExtension(ssl);
+
+            if (length > 0)
+                return BUFFER_ERROR; /* SNI response MUST be empty. */
+
+            /* This call enables wolfSSL_SNI_GetRequest() to be called in the
+             * client side to fetch the used SNI. It will only work if the SNI
+             * was set at the SSL object level. Right now we only support one
+             * name type, WOLFSSL_SNI_HOST_NAME, but in the future, the
+             * inclusion of other name types will turn this method inaccurate,
+             * as the extension response doesn't contains information of which
+             * name was accepted.
+             */
+            TLSX_SNI_SetStatus(ssl->extensions, WOLFSSL_SNI_HOST_NAME,
+                                                        WOLFSSL_SNI_REAL_MATCH);
+
+            return 0;
+        #endif
+    }
+
+#ifndef NO_WOLFSSL_SERVER
+    if (!extension || !extension->data) {
+        #if defined(WOLFSSL_ALWAYS_KEEP_SNI) && !defined(NO_WOLFSSL_SERVER)
+            /* This will keep SNI even though TLSX_UseSNI has not been called.
+            * Enable it so that the received sni is available to functions
+            * that use a custom callback when SNI is received.
+            */
+
+            cacheOnly = 1;
+            WOLFSSL_MSG("Forcing SSL object to store SNI parameter");
+        #else
+            /* Skipping, SNI not enabled at server side. */
+            return 0;
+        #endif
+    }
+
+    if (OPAQUE16_LEN > length)
+        return BUFFER_ERROR;
+
+    ato16(input, &size);
+    offset += OPAQUE16_LEN;
+
+    /* validating sni list length */
+    if (length != OPAQUE16_LEN + size || size == 0)
+        return BUFFER_ERROR;
+
+    /* SNI was badly specified and only one type is now recognized and allowed.
+     * Only one SNI value per type (RFC6066), so, no loop. */
+    type = input[offset++];
+    if (type != WOLFSSL_SNI_HOST_NAME)
+        return BUFFER_ERROR;
+
+    if (offset + OPAQUE16_LEN > length)
+        return BUFFER_ERROR;
+    ato16(input + offset, &size);
+    offset += OPAQUE16_LEN;
+
+    if (offset + size != length || size == 0)
+        return BUFFER_ERROR;
+
+    if (!cacheOnly && !(sni = TLSX_SNI_Find((SNI*)extension->data, type)))
+        return 0; /* not using this type of SNI. */
+
+#ifdef WOLFSSL_TLS13
+    /* Don't process the second ClientHello SNI extension if there
+     * was problems with the first.
+     */
+    if (!cacheOnly && sni->status != 0)
+        return 0;
+#endif
+    matched = cacheOnly || (XSTRLEN(sni->data.host_name) == size &&
+         XSTRNCMP(sni->data.host_name, (const char*)input + offset, size) == 0);
+
+    if (matched || sni->options & WOLFSSL_SNI_ANSWER_ON_MISMATCH) {
+        int r = TLSX_UseSNI(&ssl->extensions, type, input + offset, size,
+                                                                     ssl->heap);
+        if (r != WOLFSSL_SUCCESS)
+            return r; /* throws error. */
+
+        if (cacheOnly) {
+            WOLFSSL_MSG("Forcing storage of SNI, Fake match");
+            matchStat = WOLFSSL_SNI_FORCE_KEEP;
+        }
+        else if (matched) {
+            WOLFSSL_MSG("SNI did match!");
+            matchStat = WOLFSSL_SNI_REAL_MATCH;
+        }
+        else {
+            WOLFSSL_MSG("fake SNI match from ANSWER_ON_MISMATCH");
+            matchStat = WOLFSSL_SNI_FAKE_MATCH;
+        }
+
+        TLSX_SNI_SetStatus(ssl->extensions, type, (byte)matchStat);
+
+        if(!cacheOnly)
+            TLSX_SetResponse(ssl, TLSX_SERVER_NAME);
+    }
+    else if (!(sni->options & WOLFSSL_SNI_CONTINUE_ON_MISMATCH)) {
+        SendAlert(ssl, alert_fatal, unrecognized_name);
+
+        return UNKNOWN_SNI_HOST_NAME_E;
+    }
+#else
+    (void)input;
+#endif
+
+    return 0;
+}
+
+static int TLSX_SNI_VerifyParse(WOLFSSL* ssl,  byte isRequest)
+{
+    (void)ssl;
+
+    if (isRequest) {
+    #ifndef NO_WOLFSSL_SERVER
+        TLSX* ctx_ext = TLSX_Find(ssl->ctx->extensions, TLSX_SERVER_NAME);
+        TLSX* ssl_ext = TLSX_Find(ssl->extensions,      TLSX_SERVER_NAME);
+        SNI* ctx_sni = ctx_ext ? (SNI*)ctx_ext->data : NULL;
+        SNI* ssl_sni = ssl_ext ? (SNI*)ssl_ext->data : NULL;
+        SNI* sni = NULL;
+
+        for (; ctx_sni; ctx_sni = ctx_sni->next) {
+            if (ctx_sni->options & WOLFSSL_SNI_ABORT_ON_ABSENCE) {
+                sni = TLSX_SNI_Find(ssl_sni, ctx_sni->type);
+
+                if (sni) {
+                    if (sni->status != WOLFSSL_SNI_NO_MATCH)
+                        continue;
+
+                    /* if ssl level overrides ctx level, it is ok. */
+                    if ((sni->options & WOLFSSL_SNI_ABORT_ON_ABSENCE) == 0)
+                        continue;
+                }
+
+                SendAlert(ssl, alert_fatal, handshake_failure);
+                return SNI_ABSENT_ERROR;
+            }
+        }
+
+        for (; ssl_sni; ssl_sni = ssl_sni->next) {
+            if (ssl_sni->options & WOLFSSL_SNI_ABORT_ON_ABSENCE) {
+                if (ssl_sni->status != WOLFSSL_SNI_NO_MATCH)
+                    continue;
+
+                SendAlert(ssl, alert_fatal, handshake_failure);
+                return SNI_ABSENT_ERROR;
+            }
+        }
+    #endif /* NO_WOLFSSL_SERVER */
+    }
+
+    return 0;
+}
+
+int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size,
+                                                                     void* heap)
+{
+    TLSX* extension;
+    SNI* sni = NULL;
+
+    if (extensions == NULL || data == NULL)
+        return BAD_FUNC_ARG;
+
+    if ((sni = TLSX_SNI_New(type, data, size, heap)) == NULL)
+        return MEMORY_E;
+
+    extension = TLSX_Find(*extensions, TLSX_SERVER_NAME);
+    if (!extension) {
+        int ret = TLSX_Push(extensions, TLSX_SERVER_NAME, (void*)sni, heap);
+
+        if (ret != 0) {
+            TLSX_SNI_Free(sni, heap);
+            return ret;
+        }
+    }
+    else {
+        /* push new SNI object to extension data. */
+        sni->next = (SNI*)extension->data;
+        extension->data = (void*)sni;
+
+        /* remove duplicate SNI, there should be only one of each type. */
+        do {
+            if (sni->next && sni->next->type == type) {
+                SNI* next = sni->next;
+
+                sni->next = next->next;
+                TLSX_SNI_Free(next, heap);
+
+                /* there is no way to occur more than
+                 * two SNIs of the same type.
+                 */
+                break;
+            }
+        } while ((sni = sni->next));
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+#ifndef NO_WOLFSSL_SERVER
+
+/** Tells the SNI requested by the client. */
+word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type, void** data)
+{
+    TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME);
+    SNI* sni = TLSX_SNI_Find(extension ? (SNI*)extension->data : NULL, type);
+
+    if (sni && sni->status != WOLFSSL_SNI_NO_MATCH) {
+        switch (sni->type) {
+            case WOLFSSL_SNI_HOST_NAME:
+                if (data) {
+                    *data = sni->data.host_name;
+                    return (word16)XSTRLEN((char*)*data);
+                }
+        }
+    }
+
+    return 0;
+}
+
+/** Sets the options for a SNI object. */
+void TLSX_SNI_SetOptions(TLSX* extensions, byte type, byte options)
+{
+    TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME);
+    SNI* sni = TLSX_SNI_Find(extension ? (SNI*)extension->data : NULL, type);
+
+    if (sni)
+        sni->options = options;
+}
+
+/** Retrieves a SNI request from a client hello buffer. */
+int TLSX_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz,
+                           byte type, byte* sni, word32* inOutSz)
+{
+    word32 offset = 0;
+    word32 len32 = 0;
+    word16 len16 = 0;
+
+    if (helloSz < RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + CLIENT_HELLO_FIRST)
+        return INCOMPLETE_DATA;
+
+    /* TLS record header */
+    if ((enum ContentType) clientHello[offset++] != handshake) {
+
+        /* checking for SSLv2.0 client hello according to: */
+        /* http://tools.ietf.org/html/rfc4346#appendix-E.1 */
+        if ((enum HandShakeType) clientHello[++offset] == client_hello) {
+            offset += ENUM_LEN + VERSION_SZ; /* skip version */
+
+            ato16(clientHello + offset, &len16);
+            offset += OPAQUE16_LEN;
+
+            if (len16 % 3) /* cipher_spec_length must be multiple of 3 */
+                return BUFFER_ERROR;
+
+            ato16(clientHello + offset, &len16);
+            /* Returning SNI_UNSUPPORTED do not increment offset here */
+
+            if (len16 != 0) /* session_id_length must be 0 */
+                return BUFFER_ERROR;
+
+            return SNI_UNSUPPORTED;
+        }
+
+        return BUFFER_ERROR;
+    }
+
+    if (clientHello[offset++] != SSLv3_MAJOR)
+        return BUFFER_ERROR;
+
+    if (clientHello[offset++] < TLSv1_MINOR)
+        return SNI_UNSUPPORTED;
+
+    ato16(clientHello + offset, &len16);
+    offset += OPAQUE16_LEN;
+
+    if (offset + len16 > helloSz)
+        return INCOMPLETE_DATA;
+
+    /* Handshake header */
+    if ((enum HandShakeType) clientHello[offset] != client_hello)
+        return BUFFER_ERROR;
+
+    c24to32(clientHello + offset + 1, &len32);
+    offset += HANDSHAKE_HEADER_SZ;
+
+    if (offset + len32 > helloSz)
+        return BUFFER_ERROR;
+
+    /* client hello */
+    offset += VERSION_SZ + RAN_LEN; /* version, random */
+
+    if (helloSz < offset + clientHello[offset])
+        return BUFFER_ERROR;
+
+    offset += ENUM_LEN + clientHello[offset]; /* skip session id */
+
+    /* cypher suites */
+    if (helloSz < offset + OPAQUE16_LEN)
+        return BUFFER_ERROR;
+
+    ato16(clientHello + offset, &len16);
+    offset += OPAQUE16_LEN;
+
+    if (helloSz < offset + len16)
+        return BUFFER_ERROR;
+
+    offset += len16; /* skip cypher suites */
+
+    /* compression methods */
+    if (helloSz < offset + 1)
+        return BUFFER_ERROR;
+
+    if (helloSz < offset + clientHello[offset])
+        return BUFFER_ERROR;
+
+    offset += ENUM_LEN + clientHello[offset]; /* skip compression methods */
+
+    /* extensions */
+    if (helloSz < offset + OPAQUE16_LEN)
+        return 0; /* no extensions in client hello. */
+
+    ato16(clientHello + offset, &len16);
+    offset += OPAQUE16_LEN;
+
+    if (helloSz < offset + len16)
+        return BUFFER_ERROR;
+
+    while (len16 >= OPAQUE16_LEN + OPAQUE16_LEN) {
+        word16 extType;
+        word16 extLen;
+
+        ato16(clientHello + offset, &extType);
+        offset += OPAQUE16_LEN;
+
+        ato16(clientHello + offset, &extLen);
+        offset += OPAQUE16_LEN;
+
+        if (helloSz < offset + extLen)
+            return BUFFER_ERROR;
+
+        if (extType != TLSX_SERVER_NAME) {
+            offset += extLen; /* skip extension */
+        } else {
+            word16 listLen;
+
+            ato16(clientHello + offset, &listLen);
+            offset += OPAQUE16_LEN;
+
+            if (helloSz < offset + listLen)
+                return BUFFER_ERROR;
+
+            while (listLen > ENUM_LEN + OPAQUE16_LEN) {
+                byte   sniType = clientHello[offset++];
+                word16 sniLen;
+
+                ato16(clientHello + offset, &sniLen);
+                offset += OPAQUE16_LEN;
+
+                if (helloSz < offset + sniLen)
+                    return BUFFER_ERROR;
+
+                if (sniType != type) {
+                    offset  += sniLen;
+                    listLen -= min(ENUM_LEN + OPAQUE16_LEN + sniLen, listLen);
+                    continue;
+                }
+
+                *inOutSz = min(sniLen, *inOutSz);
+                XMEMCPY(sni, clientHello + offset, *inOutSz);
+
+                return WOLFSSL_SUCCESS;
+            }
+        }
+
+        len16 -= min(2 * OPAQUE16_LEN + extLen, len16);
+    }
+
+    return len16 ? BUFFER_ERROR : 0;
+}
+
+#endif
+
+#define SNI_FREE_ALL     TLSX_SNI_FreeAll
+#define SNI_GET_SIZE     TLSX_SNI_GetSize
+#define SNI_WRITE        TLSX_SNI_Write
+#define SNI_PARSE        TLSX_SNI_Parse
+#define SNI_VERIFY_PARSE TLSX_SNI_VerifyParse
+
+#else
+
+#define SNI_FREE_ALL(list, heap)
+#define SNI_GET_SIZE(list)     0
+#define SNI_WRITE(a, b)        0
+#define SNI_PARSE(a, b, c, d)  0
+#define SNI_VERIFY_PARSE(a, b) 0
+
+#endif /* HAVE_SNI */
+
+/******************************************************************************/
+/* Trusted CA Key Indication                                                  */
+/******************************************************************************/
+
+#ifdef HAVE_TRUSTED_CA
+
+/** Creates a new TCA object. */
+static TCA* TLSX_TCA_New(byte type, const byte* id, word16 idSz, void* heap)
+{
+    TCA* tca = (TCA*)XMALLOC(sizeof(TCA), heap, DYNAMIC_TYPE_TLSX);
+
+    if (tca) {
+        XMEMSET(tca, 0, sizeof(TCA));
+        tca->type = type;
+
+        switch (type) {
+            case WOLFSSL_TRUSTED_CA_PRE_AGREED:
+                break;
+
+            #ifndef NO_SHA
+            case WOLFSSL_TRUSTED_CA_KEY_SHA1:
+            case WOLFSSL_TRUSTED_CA_CERT_SHA1:
+                if (idSz == WC_SHA_DIGEST_SIZE &&
+                        (tca->id =
+                            (byte*)XMALLOC(idSz, heap, DYNAMIC_TYPE_TLSX))) {
+                    XMEMCPY(tca->id, id, idSz);
+                    tca->idSz = idSz;
+                }
+                else {
+                    XFREE(tca, heap, DYNAMIC_TYPE_TLSX);
+                    tca = NULL;
+                }
+                break;
+            #endif
+
+            case WOLFSSL_TRUSTED_CA_X509_NAME:
+                if (idSz > 0 &&
+                        (tca->id =
+                            (byte*)XMALLOC(idSz, heap, DYNAMIC_TYPE_TLSX))) {
+                    XMEMCPY(tca->id, id, idSz);
+                    tca->idSz = idSz;
+                }
+                else {
+                    XFREE(tca, heap, DYNAMIC_TYPE_TLSX);
+                    tca = NULL;
+                }
+                break;
+
+            default: /* invalid type */
+                XFREE(tca, heap, DYNAMIC_TYPE_TLSX);
+                tca = NULL;
+        }
+    }
+
+    (void)heap;
+
+    return tca;
+}
+
+/** Releases a TCA object. */
+static void TLSX_TCA_Free(TCA* tca, void* heap)
+{
+    (void)heap;
+
+    if (tca) {
+        if (tca->id)
+            XFREE(tca->id, heap, DYNAMIC_TYPE_TLSX);
+        XFREE(tca, heap, DYNAMIC_TYPE_TLSX);
+    }
+}
+
+/** Releases all TCA objects in the provided list. */
+static void TLSX_TCA_FreeAll(TCA* list, void* heap)
+{
+    TCA* tca;
+
+    while ((tca = list)) {
+        list = tca->next;
+        TLSX_TCA_Free(tca, heap);
+    }
+}
+
+/** Tells the buffered size of the TCA objects in a list. */
+static word16 TLSX_TCA_GetSize(TCA* list)
+{
+    TCA* tca;
+    word16 length = OPAQUE16_LEN; /* list length */
+
+    while ((tca = list)) {
+        list = tca->next;
+
+        length += ENUM_LEN; /* tca type */
+
+        switch (tca->type) {
+            case WOLFSSL_TRUSTED_CA_PRE_AGREED:
+                break;
+            case WOLFSSL_TRUSTED_CA_KEY_SHA1:
+            case WOLFSSL_TRUSTED_CA_CERT_SHA1:
+                length += tca->idSz;
+                break;
+            case WOLFSSL_TRUSTED_CA_X509_NAME:
+                length += OPAQUE16_LEN + tca->idSz;
+                break;
+        }
+    }
+
+    return length;
+}
+
+/** Writes the TCA objects of a list in a buffer. */
+static word16 TLSX_TCA_Write(TCA* list, byte* output)
+{
+    TCA* tca;
+    word16 offset = OPAQUE16_LEN; /* list length offset */
+
+    while ((tca = list)) {
+        list = tca->next;
+
+        output[offset++] = tca->type; /* tca type */
+
+        switch (tca->type) {
+            case WOLFSSL_TRUSTED_CA_PRE_AGREED:
+                break;
+            #ifndef NO_SHA
+            case WOLFSSL_TRUSTED_CA_KEY_SHA1:
+            case WOLFSSL_TRUSTED_CA_CERT_SHA1:
+                if (tca->id != NULL) {
+                    XMEMCPY(output + offset, tca->id, tca->idSz);
+                    offset += tca->idSz;
+                }
+                else {
+                    /* ID missing. Set to an empty string. */
+                    c16toa(0, output + offset);
+                    offset += OPAQUE16_LEN;
+                }
+                break;
+            #endif
+            case WOLFSSL_TRUSTED_CA_X509_NAME:
+                if (tca->id != NULL) {
+                    c16toa(tca->idSz, output + offset); /* tca length */
+                    offset += OPAQUE16_LEN;
+                    XMEMCPY(output + offset, tca->id, tca->idSz);
+                    offset += tca->idSz;
+                }
+                else {
+                    /* ID missing. Set to an empty string. */
+                    c16toa(0, output + offset);
+                    offset += OPAQUE16_LEN;
+                }
+                break;
+            default:
+                /* ID unknown. Set to an empty string. */
+                c16toa(0, output + offset);
+                offset += OPAQUE16_LEN;
+        }
+    }
+
+    c16toa(offset - OPAQUE16_LEN, output); /* writing list length */
+
+    return offset;
+}
+
+#ifndef NO_WOLFSSL_SERVER
+static TCA* TLSX_TCA_Find(TCA *list, byte type, const byte* id, word16 idSz)
+{
+    TCA* tca = list;
+
+    while (tca && tca->type != type && type != WOLFSSL_TRUSTED_CA_PRE_AGREED &&
+           idSz != tca->idSz && !XMEMCMP(id, tca->id, idSz))
+        tca = tca->next;
+
+    return tca;
+}
+#endif /* NO_WOLFSSL_SERVER */
+
+/** Parses a buffer of TCA extensions. */
+static int TLSX_TCA_Parse(WOLFSSL* ssl, const byte* input, word16 length,
+                          byte isRequest)
+{
+#ifndef NO_WOLFSSL_SERVER
+    word16 size = 0;
+    word16 offset = 0;
+#endif
+
+    TLSX *extension = TLSX_Find(ssl->extensions, TLSX_TRUSTED_CA_KEYS);
+
+    if (!extension)
+        extension = TLSX_Find(ssl->ctx->extensions, TLSX_TRUSTED_CA_KEYS);
+
+    if (!isRequest) {
+        #ifndef NO_WOLFSSL_CLIENT
+            if (!extension || !extension->data)
+                return TLSX_HandleUnsupportedExtension(ssl);
+
+            if (length > 0)
+                return BUFFER_ERROR; /* TCA response MUST be empty. */
+
+            /* Set the flag that we're good for keys */
+            TLSX_SetResponse(ssl, TLSX_TRUSTED_CA_KEYS);
+
+            return 0;
+        #endif
+    }
+
+#ifndef NO_WOLFSSL_SERVER
+    if (!extension || !extension->data) {
+        /* Skipping, TCA not enabled at server side. */
+        return 0;
+    }
+
+    if (OPAQUE16_LEN > length)
+        return BUFFER_ERROR;
+
+    ato16(input, &size);
+    offset += OPAQUE16_LEN;
+
+    /* validating tca list length */
+    if (length != OPAQUE16_LEN + size)
+        return BUFFER_ERROR;
+
+    for (size = 0; offset < length; offset += size) {
+        TCA *tca = NULL;
+        byte type;
+        const byte* id = NULL;
+        word16 idSz = 0;
+
+        if (offset + ENUM_LEN > length)
+            return BUFFER_ERROR;
+
+        type = input[offset++];
+
+        switch (type) {
+            case WOLFSSL_TRUSTED_CA_PRE_AGREED:
+                break;
+            #ifndef NO_SHA
+            case WOLFSSL_TRUSTED_CA_KEY_SHA1:
+            case WOLFSSL_TRUSTED_CA_CERT_SHA1:
+                if (offset + WC_SHA_DIGEST_SIZE > length)
+                    return BUFFER_ERROR;
+                idSz = WC_SHA_DIGEST_SIZE;
+                id = input + offset;
+                offset += idSz;
+                break;
+            #endif
+            case WOLFSSL_TRUSTED_CA_X509_NAME:
+                if (offset + OPAQUE16_LEN > length)
+                    return BUFFER_ERROR;
+                ato16(input + offset, &idSz);
+                offset += OPAQUE16_LEN;
+                if ((offset > length) || (idSz > length - offset))
+                    return BUFFER_ERROR;
+                id = input + offset;
+                offset += idSz;
+                break;
+            default:
+                return TCA_INVALID_ID_TYPE;
+        }
+
+        /* Find the type/ID in the TCA list. */
+        tca = TLSX_TCA_Find((TCA*)extension->data, type, id, idSz);
+        if (tca != NULL) {
+            /* Found it. Set the response flag and break out of the loop. */
+            TLSX_SetResponse(ssl, TLSX_TRUSTED_CA_KEYS);
+            break;
+        }
+    }
+#else
+    (void)input;
+#endif
+
+    return 0;
+}
+
+/* Checks to see if the server sent a response for the TCA. */
+static int TLSX_TCA_VerifyParse(WOLFSSL* ssl, byte isRequest)
+{
+    (void)ssl;
+
+    if (!isRequest) {
+    #ifndef NO_WOLFSSL_CLIENT
+        TLSX* extension = TLSX_Find(ssl->extensions, TLSX_TRUSTED_CA_KEYS);
+
+        if (extension && !extension->resp) {
+            SendAlert(ssl, alert_fatal, handshake_failure);
+            return TCA_ABSENT_ERROR;
+        }
+    #endif /* NO_WOLFSSL_CLIENT */
+    }
+
+    return 0;
+}
+
+int TLSX_UseTrustedCA(TLSX** extensions, byte type,
+                    const byte* id, word16 idSz, void* heap)
+{
+    TLSX* extension;
+    TCA* tca = NULL;
+
+    if (extensions == NULL)
+        return BAD_FUNC_ARG;
+
+    if ((tca = TLSX_TCA_New(type, id, idSz, heap)) == NULL)
+        return MEMORY_E;
+
+    extension = TLSX_Find(*extensions, TLSX_TRUSTED_CA_KEYS);
+    if (!extension) {
+        int ret = TLSX_Push(extensions, TLSX_TRUSTED_CA_KEYS, (void*)tca, heap);
+
+        if (ret != 0) {
+            TLSX_TCA_Free(tca, heap);
+            return ret;
+        }
+    }
+    else {
+        /* push new TCA object to extension data. */
+        tca->next = (TCA*)extension->data;
+        extension->data = (void*)tca;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+#define TCA_FREE_ALL     TLSX_TCA_FreeAll
+#define TCA_GET_SIZE     TLSX_TCA_GetSize
+#define TCA_WRITE        TLSX_TCA_Write
+#define TCA_PARSE        TLSX_TCA_Parse
+#define TCA_VERIFY_PARSE TLSX_TCA_VerifyParse
+
+#else /* HAVE_TRUSTED_CA */
+
+#define TCA_FREE_ALL(list, heap)
+#define TCA_GET_SIZE(list)     0
+#define TCA_WRITE(a, b)        0
+#define TCA_PARSE(a, b, c, d)  0
+#define TCA_VERIFY_PARSE(a, b) 0
+
+#endif /* HAVE_TRUSTED_CA */
+
+/******************************************************************************/
+/* Max Fragment Length Negotiation                                            */
+/******************************************************************************/
+
+#ifdef HAVE_MAX_FRAGMENT
+
+static word16 TLSX_MFL_Write(byte* data, byte* output)
+{
+    output[0] = data[0];
+
+    return ENUM_LEN;
+}
+
+static int TLSX_MFL_Parse(WOLFSSL* ssl, byte* input, word16 length,
+                                                                 byte isRequest)
+{
+    if (length != ENUM_LEN)
+        return BUFFER_ERROR;
+
+#ifdef WOLFSSL_OLD_UNSUPPORTED_EXTENSION
+    (void) isRequest;
+#else
+    if (!isRequest)
+        if (TLSX_CheckUnsupportedExtension(ssl, TLSX_MAX_FRAGMENT_LENGTH))
+            return TLSX_HandleUnsupportedExtension(ssl);
+#endif
+
+    switch (*input) {
+        case WOLFSSL_MFL_2_8 : ssl->max_fragment =  256; break;
+        case WOLFSSL_MFL_2_9 : ssl->max_fragment =  512; break;
+        case WOLFSSL_MFL_2_10: ssl->max_fragment = 1024; break;
+        case WOLFSSL_MFL_2_11: ssl->max_fragment = 2048; break;
+        case WOLFSSL_MFL_2_12: ssl->max_fragment = 4096; break;
+        case WOLFSSL_MFL_2_13: ssl->max_fragment = 8192; break;
+
+        default:
+            SendAlert(ssl, alert_fatal, illegal_parameter);
+
+            return UNKNOWN_MAX_FRAG_LEN_E;
+    }
+
+#ifndef NO_WOLFSSL_SERVER
+    if (isRequest) {
+        int ret = TLSX_UseMaxFragment(&ssl->extensions, *input, ssl->heap);
+
+        if (ret != WOLFSSL_SUCCESS)
+            return ret; /* throw error */
+
+        TLSX_SetResponse(ssl, TLSX_MAX_FRAGMENT_LENGTH);
+    }
+#endif
+
+    return 0;
+}
+
+int TLSX_UseMaxFragment(TLSX** extensions, byte mfl, void* heap)
+{
+    byte* data = NULL;
+    int ret = 0;
+
+    if (extensions == NULL || mfl < WOLFSSL_MFL_MIN || mfl > WOLFSSL_MFL_MAX)
+        return BAD_FUNC_ARG;
+
+    data = (byte*)XMALLOC(ENUM_LEN, heap, DYNAMIC_TYPE_TLSX);
+    if (data == NULL)
+        return MEMORY_E;
+
+    data[0] = mfl;
+
+    ret = TLSX_Push(extensions, TLSX_MAX_FRAGMENT_LENGTH, data, heap);
+    if (ret != 0) {
+        XFREE(data, heap, DYNAMIC_TYPE_TLSX);
+        return ret;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+#define MFL_FREE_ALL(data, heap) XFREE(data, (heap), DYNAMIC_TYPE_TLSX)
+#define MFL_GET_SIZE(data) ENUM_LEN
+#define MFL_WRITE          TLSX_MFL_Write
+#define MFL_PARSE          TLSX_MFL_Parse
+
+#else
+
+#define MFL_FREE_ALL(a, b)
+#define MFL_GET_SIZE(a)       0
+#define MFL_WRITE(a, b)       0
+#define MFL_PARSE(a, b, c, d) 0
+
+#endif /* HAVE_MAX_FRAGMENT */
+
+/******************************************************************************/
+/* Truncated HMAC                                                             */
+/******************************************************************************/
+
+#ifdef HAVE_TRUNCATED_HMAC
+
+static int TLSX_THM_Parse(WOLFSSL* ssl, byte* input, word16 length,
+                                                                 byte isRequest)
+{
+    if (length != 0 || input == NULL)
+        return BUFFER_ERROR;
+
+    if (!isRequest) {
+    #ifndef WOLFSSL_OLD_UNSUPPORTED_EXTENSION
+        if (TLSX_CheckUnsupportedExtension(ssl, TLSX_TRUNCATED_HMAC))
+            return TLSX_HandleUnsupportedExtension(ssl);
+    #endif
+    }
+    else {
+        #ifndef NO_WOLFSSL_SERVER
+            int ret = TLSX_UseTruncatedHMAC(&ssl->extensions, ssl->heap);
+
+            if (ret != WOLFSSL_SUCCESS)
+                return ret; /* throw error */
+
+            TLSX_SetResponse(ssl, TLSX_TRUNCATED_HMAC);
+        #endif
+    }
+
+    ssl->truncated_hmac = 1;
+
+    return 0;
+}
+
+int TLSX_UseTruncatedHMAC(TLSX** extensions, void* heap)
+{
+    int ret = 0;
+
+    if (extensions == NULL)
+        return BAD_FUNC_ARG;
+
+    ret = TLSX_Push(extensions, TLSX_TRUNCATED_HMAC, NULL, heap);
+    if (ret != 0)
+        return ret;
+
+    return WOLFSSL_SUCCESS;
+}
+
+#define THM_PARSE TLSX_THM_Parse
+
+#else
+
+#define THM_PARSE(a, b, c, d) 0
+
+#endif /* HAVE_TRUNCATED_HMAC */
+
+/******************************************************************************/
+/* Certificate Status Request                                                 */
+/******************************************************************************/
+
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+
+static void TLSX_CSR_Free(CertificateStatusRequest* csr, void* heap)
+{
+    switch (csr->status_type) {
+        case WOLFSSL_CSR_OCSP:
+            FreeOcspRequest(&csr->request.ocsp);
+        break;
+    }
+
+    XFREE(csr, heap, DYNAMIC_TYPE_TLSX);
+    (void)heap;
+}
+
+static word16 TLSX_CSR_GetSize(CertificateStatusRequest* csr, byte isRequest)
+{
+    word16 size = 0;
+
+    /* shut up compiler warnings */
+    (void) csr; (void) isRequest;
+
+#ifndef NO_WOLFSSL_CLIENT
+    if (isRequest) {
+        switch (csr->status_type) {
+            case WOLFSSL_CSR_OCSP:
+                size += ENUM_LEN + 2 * OPAQUE16_LEN;
+
+                if (csr->request.ocsp.nonceSz)
+                    size += OCSP_NONCE_EXT_SZ;
+            break;
+        }
+    }
+#endif
+#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)
+    if (!isRequest && csr->ssl->options.tls1_3)
+        return OPAQUE8_LEN + OPAQUE24_LEN + csr->response.length;
+#endif
+
+    return size;
+}
+
+static word16 TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output,
+                                                                 byte isRequest)
+{
+    /* shut up compiler warnings */
+    (void) csr; (void) output; (void) isRequest;
+
+#ifndef NO_WOLFSSL_CLIENT
+    if (isRequest) {
+        word16 offset = 0;
+        word16 length = 0;
+
+        /* type */
+        output[offset++] = csr->status_type;
+
+        switch (csr->status_type) {
+            case WOLFSSL_CSR_OCSP:
+                /* responder id list */
+                c16toa(0, output + offset);
+                offset += OPAQUE16_LEN;
+
+                /* request extensions */
+                if (csr->request.ocsp.nonceSz)
+                    length = (word16)EncodeOcspRequestExtensions(
+                                                 &csr->request.ocsp,
+                                                 output + offset + OPAQUE16_LEN,
+                                                 OCSP_NONCE_EXT_SZ);
+
+                c16toa(length, output + offset);
+                offset += OPAQUE16_LEN + length;
+
+            break;
+        }
+
+        return offset;
+    }
+#endif
+#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)
+    if (!isRequest && csr->ssl->options.tls1_3) {
+        word16 offset = 0;
+        output[offset++] = csr->status_type;
+        c32to24(csr->response.length, output + offset);
+        offset += OPAQUE24_LEN;
+        XMEMCPY(output + offset, csr->response.buffer, csr->response.length);
+        offset += csr->response.length;
+        return offset;
+    }
+#endif
+
+    return 0;
+}
+
+static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length,
+                                                                 byte isRequest)
+{
+    int ret;
+
+    /* shut up compiler warnings */
+    (void) ssl; (void) input;
+
+    if (!isRequest) {
+#ifndef NO_WOLFSSL_CLIENT
+        TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST);
+        CertificateStatusRequest* csr = extension ?
+                              (CertificateStatusRequest*)extension->data : NULL;
+
+        if (!csr) {
+            /* look at context level */
+            extension = TLSX_Find(ssl->ctx->extensions, TLSX_STATUS_REQUEST);
+            csr = extension ? (CertificateStatusRequest*)extension->data : NULL;
+
+            if (!csr) /* unexpected extension */
+                return TLSX_HandleUnsupportedExtension(ssl);
+
+            /* enable extension at ssl level */
+            ret = TLSX_UseCertificateStatusRequest(&ssl->extensions,
+                                     csr->status_type, csr->options, ssl,
+                                     ssl->heap, ssl->devId);
+            if (ret != WOLFSSL_SUCCESS)
+                return ret;
+
+            switch (csr->status_type) {
+                case WOLFSSL_CSR_OCSP:
+                    /* propagate nonce */
+                    if (csr->request.ocsp.nonceSz) {
+                        OcspRequest* request =
+                             (OcspRequest*)TLSX_CSR_GetRequest(ssl->extensions);
+
+                        if (request) {
+                            XMEMCPY(request->nonce, csr->request.ocsp.nonce,
+                                                    csr->request.ocsp.nonceSz);
+                            request->nonceSz = csr->request.ocsp.nonceSz;
+                        }
+                    }
+                break;
+            }
+        }
+
+        ssl->status_request = 1;
+
+    #ifdef WOLFSSL_TLS13
+        if (ssl->options.tls1_3) {
+            word32       resp_length;
+            word32       offset = 0;
+
+            /* Get the new extension potentially created above. */
+            extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST);
+            csr = extension ? (CertificateStatusRequest*)extension->data : NULL;
+            if (csr == NULL)
+                return MEMORY_ERROR;
+
+            ret = 0;
+            if (OPAQUE8_LEN + OPAQUE24_LEN > length)
+                ret = BUFFER_ERROR;
+            if (ret == 0 && input[offset++] != WOLFSSL_CSR_OCSP)
+                ret = BAD_CERTIFICATE_STATUS_ERROR;
+            if (ret == 0) {
+                c24to32(input + offset, &resp_length);
+                offset += OPAQUE24_LEN;
+                if (offset + resp_length != length)
+                    ret = BUFFER_ERROR;
+            }
+        #if !defined(NO_WOLFSSL_SERVER)
+            if (ret == 0) {
+                csr->response.buffer = input + offset;
+                csr->response.length = resp_length;
+            }
+        #endif
+
+            return ret;
+        }
+        else
+    #endif
+        {
+            /* extension_data MUST be empty. */
+            return length ? BUFFER_ERROR : 0;
+        }
+#endif
+    }
+    else {
+#ifndef NO_WOLFSSL_SERVER
+        byte   status_type;
+        word16 offset = 0;
+        word16 size = 0;
+
+        if (length == 0)
+            return 0;
+        if (length < ENUM_LEN)
+            return BUFFER_ERROR;
+
+        status_type = input[offset++];
+
+        switch (status_type) {
+            case WOLFSSL_CSR_OCSP: {
+
+                /* skip responder_id_list */
+                if (length - offset < OPAQUE16_LEN)
+                    return BUFFER_ERROR;
+
+                ato16(input + offset, &size);
+                offset += OPAQUE16_LEN + size;
+
+                /* skip request_extensions */
+                if (length - offset < OPAQUE16_LEN)
+                    return BUFFER_ERROR;
+
+                ato16(input + offset, &size);
+                offset += OPAQUE16_LEN + size;
+
+                if (offset > length)
+                    return BUFFER_ERROR;
+
+                /* is able to send OCSP response? */
+                if (ssl->ctx->cm == NULL || !ssl->ctx->cm->ocspStaplingEnabled)
+                    return 0;
+            }
+            break;
+
+            /* unknown status type */
+            default:
+                return 0;
+        }
+
+        /* if using status_request and already sending it, skip this one */
+        #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+        if (ssl->status_request_v2)
+            return 0;
+        #endif
+
+        /* accept the first good status_type and return */
+        ret = TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type,
+                                                 0, ssl, ssl->heap, ssl->devId);
+        if (ret != WOLFSSL_SUCCESS)
+            return ret; /* throw error */
+
+    #if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)
+        if (ssl->options.tls1_3) {
+            OcspRequest* request;
+            TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST);
+            CertificateStatusRequest* csr = extension ?
+                (CertificateStatusRequest*)extension->data : NULL;
+            if (csr == NULL)
+                return MEMORY_ERROR;
+
+            request = &csr->request.ocsp;
+            ret = CreateOcspResponse(ssl, &request, &csr->response);
+            if (ret != 0)
+                return ret;
+            if (csr->response.buffer)
+                TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST);
+        }
+        else
+    #endif
+            TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST);
+        ssl->status_request = status_type;
+#endif
+    }
+
+    return 0;
+}
+
+int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert, void* heap)
+{
+    TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST);
+    CertificateStatusRequest* csr = extension ?
+        (CertificateStatusRequest*)extension->data : NULL;
+    int ret = 0;
+
+    if (csr) {
+        switch (csr->status_type) {
+            case WOLFSSL_CSR_OCSP: {
+                byte nonce[MAX_OCSP_NONCE_SZ];
+                int  nonceSz = csr->request.ocsp.nonceSz;
+
+                /* preserve nonce */
+                XMEMCPY(nonce, csr->request.ocsp.nonce, nonceSz);
+
+                if ((ret = InitOcspRequest(&csr->request.ocsp, cert, 0, heap))
+                                                                           != 0)
+                    return ret;
+
+                /* restore nonce */
+                XMEMCPY(csr->request.ocsp.nonce, nonce, nonceSz);
+                csr->request.ocsp.nonceSz = nonceSz;
+            }
+            break;
+        }
+    }
+
+    return ret;
+}
+
+void* TLSX_CSR_GetRequest(TLSX* extensions)
+{
+    TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST);
+    CertificateStatusRequest* csr = extension ?
+                              (CertificateStatusRequest*)extension->data : NULL;
+
+    if (csr) {
+        switch (csr->status_type) {
+            case WOLFSSL_CSR_OCSP:
+                return &csr->request.ocsp;
+            break;
+        }
+    }
+
+    return NULL;
+}
+
+int TLSX_CSR_ForceRequest(WOLFSSL* ssl)
+{
+    TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST);
+    CertificateStatusRequest* csr = extension ?
+                              (CertificateStatusRequest*)extension->data : NULL;
+
+    if (csr) {
+        switch (csr->status_type) {
+            case WOLFSSL_CSR_OCSP:
+                if (ssl->ctx->cm->ocspEnabled) {
+                    csr->request.ocsp.ssl = ssl;
+                    return CheckOcspRequest(ssl->ctx->cm->ocsp,
+                                                      &csr->request.ocsp, NULL);
+                }
+                else
+                    return OCSP_LOOKUP_FAIL;
+        }
+    }
+
+    return 0;
+}
+
+int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type,
+                                         byte options, WOLFSSL* ssl, void* heap,
+                                                                      int devId)
+{
+    CertificateStatusRequest* csr = NULL;
+    int ret = 0;
+
+    if (!extensions || status_type != WOLFSSL_CSR_OCSP)
+        return BAD_FUNC_ARG;
+
+    csr = (CertificateStatusRequest*)
+             XMALLOC(sizeof(CertificateStatusRequest), heap, DYNAMIC_TYPE_TLSX);
+    if (!csr)
+        return MEMORY_E;
+
+    ForceZero(csr, sizeof(CertificateStatusRequest));
+
+    csr->status_type = status_type;
+    csr->options     = options;
+    csr->ssl         = ssl;
+
+    switch (csr->status_type) {
+        case WOLFSSL_CSR_OCSP:
+            if (options & WOLFSSL_CSR_OCSP_USE_NONCE) {
+                WC_RNG rng;
+
+            #ifndef HAVE_FIPS
+                ret = wc_InitRng_ex(&rng, heap, devId);
+            #else
+                ret = wc_InitRng(&rng);
+                (void)devId;
+            #endif
+                if (ret == 0) {
+                    if (wc_RNG_GenerateBlock(&rng, csr->request.ocsp.nonce,
+                                                        MAX_OCSP_NONCE_SZ) == 0)
+                        csr->request.ocsp.nonceSz = MAX_OCSP_NONCE_SZ;
+
+                    wc_FreeRng(&rng);
+                }
+            }
+        break;
+    }
+
+    if ((ret = TLSX_Push(extensions, TLSX_STATUS_REQUEST, csr, heap)) != 0) {
+        XFREE(csr, heap, DYNAMIC_TYPE_TLSX);
+        return ret;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+#define CSR_FREE_ALL TLSX_CSR_Free
+#define CSR_GET_SIZE TLSX_CSR_GetSize
+#define CSR_WRITE    TLSX_CSR_Write
+#define CSR_PARSE    TLSX_CSR_Parse
+
+#else
+
+#define CSR_FREE_ALL(data, heap)
+#define CSR_GET_SIZE(a, b)    0
+#define CSR_WRITE(a, b, c)    0
+#define CSR_PARSE(a, b, c, d) 0
+
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
+
+/******************************************************************************/
+/* Certificate Status Request v2                                              */
+/******************************************************************************/
+
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+
+static void TLSX_CSR2_FreeAll(CertificateStatusRequestItemV2* csr2, void* heap)
+{
+    CertificateStatusRequestItemV2* next;
+
+    for (; csr2; csr2 = next) {
+        next = csr2->next;
+
+        switch (csr2->status_type) {
+            case WOLFSSL_CSR2_OCSP:
+            case WOLFSSL_CSR2_OCSP_MULTI:
+                while(csr2->requests--)
+                    FreeOcspRequest(&csr2->request.ocsp[csr2->requests]);
+            break;
+        }
+
+        XFREE(csr2, heap, DYNAMIC_TYPE_TLSX);
+    }
+    (void)heap;
+}
+
+static word16 TLSX_CSR2_GetSize(CertificateStatusRequestItemV2* csr2,
+                                                                 byte isRequest)
+{
+    word16 size = 0;
+
+    /* shut up compiler warnings */
+    (void) csr2; (void) isRequest;
+
+#ifndef NO_WOLFSSL_CLIENT
+    if (isRequest) {
+        CertificateStatusRequestItemV2* next;
+
+        for (size = OPAQUE16_LEN; csr2; csr2 = next) {
+            next = csr2->next;
+
+            switch (csr2->status_type) {
+                case WOLFSSL_CSR2_OCSP:
+                case WOLFSSL_CSR2_OCSP_MULTI:
+                    size += ENUM_LEN + 3 * OPAQUE16_LEN;
+
+                    if (csr2->request.ocsp[0].nonceSz)
+                        size += OCSP_NONCE_EXT_SZ;
+                break;
+            }
+        }
+    }
+#endif
+
+    return size;
+}
+
+static word16 TLSX_CSR2_Write(CertificateStatusRequestItemV2* csr2,
+                                                   byte* output, byte isRequest)
+{
+    /* shut up compiler warnings */
+    (void) csr2; (void) output; (void) isRequest;
+
+#ifndef NO_WOLFSSL_CLIENT
+    if (isRequest) {
+        word16 offset;
+        word16 length;
+
+        for (offset = OPAQUE16_LEN; csr2 != NULL; csr2 = csr2->next) {
+            /* status_type */
+            output[offset++] = csr2->status_type;
+
+            /* request */
+            switch (csr2->status_type) {
+                case WOLFSSL_CSR2_OCSP:
+                case WOLFSSL_CSR2_OCSP_MULTI:
+                    /* request_length */
+                    length = 2 * OPAQUE16_LEN;
+
+                    if (csr2->request.ocsp[0].nonceSz)
+                        length += OCSP_NONCE_EXT_SZ;
+
+                    c16toa(length, output + offset);
+                    offset += OPAQUE16_LEN;
+
+                    /* responder id list */
+                    c16toa(0, output + offset);
+                    offset += OPAQUE16_LEN;
+
+                    /* request extensions */
+                    length = 0;
+
+                    if (csr2->request.ocsp[0].nonceSz)
+                        length = (word16)EncodeOcspRequestExtensions(
+                                                 &csr2->request.ocsp[0],
+                                                 output + offset + OPAQUE16_LEN,
+                                                 OCSP_NONCE_EXT_SZ);
+
+                    c16toa(length, output + offset);
+                    offset += OPAQUE16_LEN + length;
+                break;
+            }
+        }
+
+        /* list size */
+        c16toa(offset - OPAQUE16_LEN, output);
+
+        return offset;
+    }
+#endif
+
+    return 0;
+}
+
+static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length,
+                                                                 byte isRequest)
+{
+    int ret;
+
+    /* shut up compiler warnings */
+    (void) ssl; (void) input;
+
+    if (!isRequest) {
+#ifndef NO_WOLFSSL_CLIENT
+        TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST_V2);
+        CertificateStatusRequestItemV2* csr2 = extension ?
+                        (CertificateStatusRequestItemV2*)extension->data : NULL;
+
+        if (!csr2) {
+            /* look at context level */
+            extension = TLSX_Find(ssl->ctx->extensions, TLSX_STATUS_REQUEST_V2);
+            csr2 = extension ?
+                        (CertificateStatusRequestItemV2*)extension->data : NULL;
+
+            if (!csr2) /* unexpected extension */
+                return TLSX_HandleUnsupportedExtension(ssl);
+
+            /* enable extension at ssl level */
+            for (; csr2; csr2 = csr2->next) {
+                ret = TLSX_UseCertificateStatusRequestV2(&ssl->extensions,
+                                    csr2->status_type, csr2->options, ssl->heap,
+                                                                    ssl->devId);
+                if (ret != WOLFSSL_SUCCESS)
+                    return ret;
+
+                switch (csr2->status_type) {
+                    case WOLFSSL_CSR2_OCSP:
+                        /* followed by */
+                    case WOLFSSL_CSR2_OCSP_MULTI:
+                        /* propagate nonce */
+                        if (csr2->request.ocsp[0].nonceSz) {
+                            OcspRequest* request =
+                             (OcspRequest*)TLSX_CSR2_GetRequest(ssl->extensions,
+                                                          csr2->status_type, 0);
+
+                            if (request) {
+                                XMEMCPY(request->nonce,
+                                        csr2->request.ocsp[0].nonce,
+                                        csr2->request.ocsp[0].nonceSz);
+
+                                request->nonceSz =
+                                                  csr2->request.ocsp[0].nonceSz;
+                            }
+                        }
+                    break;
+                }
+            }
+        }
+
+        ssl->status_request_v2 = 1;
+
+        return length ? BUFFER_ERROR : 0; /* extension_data MUST be empty. */
+#endif
+    }
+    else {
+#ifndef NO_WOLFSSL_SERVER
+        byte   status_type;
+        word16 request_length;
+        word16 offset = 0;
+        word16 size = 0;
+
+        /* list size */
+        if (offset + OPAQUE16_LEN >= length) {
+            return BUFFER_E;
+        }
+
+        ato16(input + offset, &request_length);
+        offset += OPAQUE16_LEN;
+
+        if (length - OPAQUE16_LEN != request_length)
+            return BUFFER_ERROR;
+
+        while (length > offset) {
+            if (length - offset < ENUM_LEN + OPAQUE16_LEN)
+                return BUFFER_ERROR;
+
+            status_type = input[offset++];
+
+            ato16(input + offset, &request_length);
+            offset += OPAQUE16_LEN;
+
+            if (length - offset < request_length)
+                return BUFFER_ERROR;
+
+            switch (status_type) {
+                case WOLFSSL_CSR2_OCSP:
+                case WOLFSSL_CSR2_OCSP_MULTI:
+                    /* skip responder_id_list */
+                    if (length - offset < OPAQUE16_LEN)
+                        return BUFFER_ERROR;
+
+                    ato16(input + offset, &size);
+                    if (length - offset < size)
+                        return BUFFER_ERROR;
+
+                    offset += OPAQUE16_LEN + size;
+                    /* skip request_extensions */
+                    if (length - offset < OPAQUE16_LEN)
+                        return BUFFER_ERROR;
+
+                    ato16(input + offset, &size);
+                    if (length - offset < size)
+                        return BUFFER_ERROR;
+
+                    offset += OPAQUE16_LEN + size;
+                    if (offset > length)
+                        return BUFFER_ERROR;
+
+                    /* is able to send OCSP response? */
+                    if (ssl->ctx->cm == NULL
+                    || !ssl->ctx->cm->ocspStaplingEnabled)
+                        continue;
+                break;
+
+                default:
+                    /* unknown status type, skipping! */
+                    offset += request_length;
+                    continue;
+            }
+
+            /* if using status_request and already sending it, skip this one */
+            #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+            if (ssl->status_request)
+                return 0;
+            #endif
+
+            /* accept the first good status_type and return */
+            ret = TLSX_UseCertificateStatusRequestV2(&ssl->extensions,
+                                         status_type, 0, ssl->heap, ssl->devId);
+            if (ret != WOLFSSL_SUCCESS)
+                return ret; /* throw error */
+
+            TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST_V2);
+            ssl->status_request_v2 = status_type;
+
+            return 0;
+        }
+#endif
+    }
+
+    return 0;
+}
+
+int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert, byte isPeer,
+                                                                     void* heap)
+{
+    TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST_V2);
+    CertificateStatusRequestItemV2* csr2 = extension ?
+        (CertificateStatusRequestItemV2*)extension->data : NULL;
+    int ret = 0;
+
+    for (; csr2; csr2 = csr2->next) {
+        switch (csr2->status_type) {
+            case WOLFSSL_CSR2_OCSP:
+                if (!isPeer || csr2->requests != 0)
+                    break;
+
+                FALL_THROUGH; /* followed by */
+
+            case WOLFSSL_CSR2_OCSP_MULTI: {
+                if (csr2->requests < 1 + MAX_CHAIN_DEPTH) {
+                    byte nonce[MAX_OCSP_NONCE_SZ];
+                    int  nonceSz = csr2->request.ocsp[0].nonceSz;
+
+                    /* preserve nonce, replicating nonce of ocsp[0] */
+                    XMEMCPY(nonce, csr2->request.ocsp[0].nonce, nonceSz);
+
+                    if ((ret = InitOcspRequest(
+                                      &csr2->request.ocsp[csr2->requests], cert,
+                                                                 0, heap)) != 0)
+                        return ret;
+
+                    /* restore nonce */
+                    XMEMCPY(csr2->request.ocsp[csr2->requests].nonce,
+                                                                nonce, nonceSz);
+                    csr2->request.ocsp[csr2->requests].nonceSz = nonceSz;
+                    csr2->requests++;
+                }
+            }
+            break;
+        }
+    }
+
+    (void)cert;
+    return ret;
+}
+
+void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type, byte idx)
+{
+    TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST_V2);
+    CertificateStatusRequestItemV2* csr2 = extension ?
+                        (CertificateStatusRequestItemV2*)extension->data : NULL;
+
+    for (; csr2; csr2 = csr2->next) {
+        if (csr2->status_type == status_type) {
+            switch (csr2->status_type) {
+                case WOLFSSL_CSR2_OCSP:
+                    /* followed by */
+
+                case WOLFSSL_CSR2_OCSP_MULTI:
+                    /* requests are initialized in the reverse order */
+                    return idx < csr2->requests
+                         ? &csr2->request.ocsp[csr2->requests - idx - 1]
+                         : NULL;
+                break;
+            }
+        }
+    }
+
+    return NULL;
+}
+
+int TLSX_CSR2_ForceRequest(WOLFSSL* ssl)
+{
+    TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST_V2);
+    CertificateStatusRequestItemV2* csr2 = extension ?
+                        (CertificateStatusRequestItemV2*)extension->data : NULL;
+
+    /* forces only the first one */
+    if (csr2) {
+        switch (csr2->status_type) {
+            case WOLFSSL_CSR2_OCSP:
+                /* followed by */
+
+            case WOLFSSL_CSR2_OCSP_MULTI:
+                if (ssl->ctx->cm->ocspEnabled) {
+                    csr2->request.ocsp[0].ssl = ssl;
+                    return CheckOcspRequest(ssl->ctx->cm->ocsp,
+                                                  &csr2->request.ocsp[0], NULL);
+                }
+                else
+                    return OCSP_LOOKUP_FAIL;
+        }
+    }
+
+    return 0;
+}
+
+int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, byte status_type,
+                                           byte options, void* heap, int devId)
+{
+    TLSX* extension = NULL;
+    CertificateStatusRequestItemV2* csr2 = NULL;
+    int ret = 0;
+
+    if (!extensions)
+        return BAD_FUNC_ARG;
+
+    if (status_type != WOLFSSL_CSR2_OCSP
+    &&  status_type != WOLFSSL_CSR2_OCSP_MULTI)
+        return BAD_FUNC_ARG;
+
+    csr2 = (CertificateStatusRequestItemV2*)
+       XMALLOC(sizeof(CertificateStatusRequestItemV2), heap, DYNAMIC_TYPE_TLSX);
+    if (!csr2)
+        return MEMORY_E;
+
+    ForceZero(csr2, sizeof(CertificateStatusRequestItemV2));
+
+    csr2->status_type = status_type;
+    csr2->options     = options;
+    csr2->next        = NULL;
+
+    switch (csr2->status_type) {
+        case WOLFSSL_CSR2_OCSP:
+        case WOLFSSL_CSR2_OCSP_MULTI:
+            if (options & WOLFSSL_CSR2_OCSP_USE_NONCE) {
+                WC_RNG rng;
+
+            #ifndef HAVE_FIPS
+                ret = wc_InitRng_ex(&rng, heap, devId);
+            #else
+                ret = wc_InitRng(&rng);
+                (void)devId;
+            #endif
+                if (ret == 0) {
+                    if (wc_RNG_GenerateBlock(&rng, csr2->request.ocsp[0].nonce,
+                                                        MAX_OCSP_NONCE_SZ) == 0)
+                        csr2->request.ocsp[0].nonceSz = MAX_OCSP_NONCE_SZ;
+
+                    wc_FreeRng(&rng);
+                }
+            }
+        break;
+    }
+
+    /* append new item */
+    if ((extension = TLSX_Find(*extensions, TLSX_STATUS_REQUEST_V2))) {
+        CertificateStatusRequestItemV2* last =
+                               (CertificateStatusRequestItemV2*)extension->data;
+
+        for (; last->next; last = last->next);
+
+        last->next = csr2;
+    }
+    else if ((ret = TLSX_Push(extensions, TLSX_STATUS_REQUEST_V2, csr2,heap))) {
+        XFREE(csr2, heap, DYNAMIC_TYPE_TLSX);
+        return ret;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+#define CSR2_FREE_ALL TLSX_CSR2_FreeAll
+#define CSR2_GET_SIZE TLSX_CSR2_GetSize
+#define CSR2_WRITE    TLSX_CSR2_Write
+#define CSR2_PARSE    TLSX_CSR2_Parse
+
+#else
+
+#define CSR2_FREE_ALL(data, heap)
+#define CSR2_GET_SIZE(a, b)    0
+#define CSR2_WRITE(a, b, c)    0
+#define CSR2_PARSE(a, b, c, d) 0
+
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+
+/******************************************************************************/
+/* Supported Elliptic Curves                                                  */
+/******************************************************************************/
+
+#ifdef HAVE_SUPPORTED_CURVES
+
+#if !defined(HAVE_ECC) && !defined(HAVE_CURVE25519) && !defined(HAVE_CURVE448) \
+                       && !defined(HAVE_FFDHE)
+#error Elliptic Curves Extension requires Elliptic Curve Cryptography. \
+       Use --enable-ecc in the configure script or define HAVE_ECC. \
+       Alternatively use FFDHE for DH ciperhsuites.
+#endif
+
+static int TLSX_SupportedCurve_New(SupportedCurve** curve, word16 name,
+                                                                     void* heap)
+{
+    if (curve == NULL)
+        return BAD_FUNC_ARG;
+
+    (void)heap;
+
+    *curve = (SupportedCurve*)XMALLOC(sizeof(SupportedCurve), heap,
+                                                             DYNAMIC_TYPE_TLSX);
+    if (*curve == NULL)
+        return MEMORY_E;
+
+    (*curve)->name = name;
+    (*curve)->next = NULL;
+
+    return 0;
+}
+
+static int TLSX_PointFormat_New(PointFormat** point, byte format, void* heap)
+{
+    if (point == NULL)
+        return BAD_FUNC_ARG;
+
+    (void)heap;
+
+    *point = (PointFormat*)XMALLOC(sizeof(PointFormat), heap,
+                                                             DYNAMIC_TYPE_TLSX);
+    if (*point == NULL)
+        return MEMORY_E;
+
+    (*point)->format = format;
+    (*point)->next = NULL;
+
+    return 0;
+}
+
+static void TLSX_SupportedCurve_FreeAll(SupportedCurve* list, void* heap)
+{
+    SupportedCurve* curve;
+
+    while ((curve = list)) {
+        list = curve->next;
+        XFREE(curve, heap, DYNAMIC_TYPE_TLSX);
+    }
+    (void)heap;
+}
+
+static void TLSX_PointFormat_FreeAll(PointFormat* list, void* heap)
+{
+    PointFormat* point;
+
+    while ((point = list)) {
+        list = point->next;
+        XFREE(point, heap, DYNAMIC_TYPE_TLSX);
+    }
+    (void)heap;
+}
+
+static int TLSX_SupportedCurve_Append(SupportedCurve* list, word16 name,
+                                                                     void* heap)
+{
+    int ret = BAD_FUNC_ARG;
+
+    while (list) {
+        if (list->name == name) {
+            ret = 0; /* curve already in use */
+            break;
+        }
+
+        if (list->next == NULL) {
+            ret = TLSX_SupportedCurve_New(&list->next, name, heap);
+            break;
+        }
+
+        list = list->next;
+    }
+
+    return ret;
+}
+
+static int TLSX_PointFormat_Append(PointFormat* list, byte format, void* heap)
+{
+    int ret = BAD_FUNC_ARG;
+
+    while (list) {
+        if (list->format == format) {
+            ret = 0; /* format already in use */
+            break;
+        }
+
+        if (list->next == NULL) {
+            ret = TLSX_PointFormat_New(&list->next, format, heap);
+            break;
+        }
+
+        list = list->next;
+    }
+
+    return ret;
+}
+
+#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_CLIENT)
+
+static void TLSX_SupportedCurve_ValidateRequest(WOLFSSL* ssl, byte* semaphore)
+{
+    word16 i;
+
+    for (i = 0; i < ssl->suites->suiteSz; i+= 2) {
+        if (ssl->suites->suites[i] == TLS13_BYTE)
+            return;
+        if (ssl->suites->suites[i] == ECC_BYTE ||
+                ssl->suites->suites[i] == CHACHA_BYTE) {
+        #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                                          defined(HAVE_CURVE448)
+            return;
+        #endif
+        }
+        else {
+        #ifdef HAVE_FFDHE
+            return;
+        #endif
+        }
+    }
+
+    /* turns semaphore on to avoid sending this extension. */
+    TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_GROUPS));
+}
+
+static void TLSX_PointFormat_ValidateRequest(WOLFSSL* ssl, byte* semaphore)
+{
+    word16 i;
+
+    for (i = 0; i < ssl->suites->suiteSz; i+= 2) {
+        if (ssl->suites->suites[i] == TLS13_BYTE)
+            return;
+        if (ssl->suites->suites[i] == ECC_BYTE ||
+                ssl->suites->suites[i] == CHACHA_BYTE) {
+        #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                                          defined(HAVE_CURVE448)
+            return;
+        #endif
+        }
+        else {
+        #ifdef HAVE_FFDHE
+            return;
+        #endif
+        }
+    }
+
+    /* turns semaphore on to avoid sending this extension. */
+    TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS));
+}
+
+#endif
+
+#ifndef NO_WOLFSSL_SERVER
+
+static void TLSX_PointFormat_ValidateResponse(WOLFSSL* ssl, byte* semaphore)
+{
+#if defined(HAVE_FFDHE) || defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                                          defined(HAVE_CURVE448)
+    (void)semaphore;
+#endif
+
+    if (ssl->options.cipherSuite0 == TLS13_BYTE)
+        return;
+    if (ssl->options.cipherSuite0 == ECC_BYTE ||
+        ssl->options.cipherSuite0 == CHACHA_BYTE) {
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
+        return;
+#endif
+    }
+    else {
+#ifdef HAVE_FFDHE
+        return;
+#endif
+    }
+
+#if !defined(HAVE_FFDHE) || (!defined(HAVE_ECC) && !defined(HAVE_CURVE25519) \
+                                                     && !defined(HAVE_CURVE448))
+    /* turns semaphore on to avoid sending this extension. */
+    TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS));
+#endif
+}
+
+#endif
+#ifndef NO_WOLFSSL_CLIENT
+
+static word16 TLSX_SupportedCurve_GetSize(SupportedCurve* list)
+{
+    SupportedCurve* curve;
+    word16 length = OPAQUE16_LEN; /* list length */
+
+    while ((curve = list)) {
+        list = curve->next;
+        length += OPAQUE16_LEN; /* curve length */
+    }
+
+    return length;
+}
+
+#endif
+
+static word16 TLSX_PointFormat_GetSize(PointFormat* list)
+{
+    PointFormat* point;
+    word16 length = ENUM_LEN; /* list length */
+
+    while ((point = list)) {
+        list = point->next;
+        length += ENUM_LEN; /* format length */
+    }
+
+    return length;
+}
+
+#ifndef NO_WOLFSSL_CLIENT
+
+static word16 TLSX_SupportedCurve_Write(SupportedCurve* list, byte* output)
+{
+    word16 offset = OPAQUE16_LEN;
+
+    while (list) {
+        c16toa(list->name, output + offset);
+        offset += OPAQUE16_LEN;
+        list = list->next;
+    }
+
+    c16toa(offset - OPAQUE16_LEN, output); /* writing list length */
+
+    return offset;
+}
+
+#endif
+
+static word16 TLSX_PointFormat_Write(PointFormat* list, byte* output)
+{
+    word16 offset = ENUM_LEN;
+
+    while (list) {
+        output[offset++] = list->format;
+        list = list->next;
+    }
+
+    output[0] = (byte)(offset - ENUM_LEN);
+
+    return offset;
+}
+
+#if !defined(NO_WOLFSSL_SERVER) || (defined(WOLFSSL_TLS13) && \
+                                         !defined(WOLFSSL_NO_SERVER_GROUPS_EXT))
+
+static int TLSX_SupportedCurve_Parse(WOLFSSL* ssl, byte* input, word16 length,
+                                                                 byte isRequest)
+{
+    word16 offset;
+    word16 name;
+    int ret;
+
+    if(!isRequest && !IsAtLeastTLSv1_3(ssl->version)) {
+#ifdef WOLFSSL_ALLOW_SERVER_SC_EXT
+        return 0;
+#else
+        return BUFFER_ERROR; /* servers doesn't send this extension. */
+#endif
+    }
+
+    if (OPAQUE16_LEN > length || length % OPAQUE16_LEN)
+        return BUFFER_ERROR;
+
+    ato16(input, &offset);
+
+    /* validating curve list length */
+    if (length != OPAQUE16_LEN + offset)
+        return BUFFER_ERROR;
+
+    offset = OPAQUE16_LEN;
+    if (offset == length)
+        return 0;
+
+#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)
+    if (!isRequest) {
+        TLSX* extension;
+        SupportedCurve* curve;
+
+        extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS);
+        if (extension != NULL) {
+            /* Replace client list with server list of supported groups. */
+            curve = (SupportedCurve*)extension->data;
+            extension->data = NULL;
+            TLSX_SupportedCurve_FreeAll(curve, ssl->heap);
+
+            ato16(input + offset, &name);
+            offset += OPAQUE16_LEN;
+
+            ret = TLSX_SupportedCurve_New(&curve, name, ssl->heap);
+            if (ret != 0)
+                return ret; /* throw error */
+            extension->data = (void*)curve;
+        }
+    }
+#endif
+
+    for (; offset < length; offset += OPAQUE16_LEN) {
+        ato16(input + offset, &name);
+
+        ret = TLSX_UseSupportedCurve(&ssl->extensions, name, ssl->heap);
+        if (ret != WOLFSSL_SUCCESS)
+            return ret; /* throw error */
+    }
+
+    return 0;
+}
+
+#endif
+
+#if !defined(NO_WOLFSSL_SERVER)
+
+#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)
+
+/* Checks the priority of the groups on the server and set the supported groups
+ * response if there is a group not advertised by the client that is preferred.
+ *
+ * ssl  SSL/TLS object.
+ * returns 0 on success, otherwise an error.
+ */
+int TLSX_SupportedCurve_CheckPriority(WOLFSSL* ssl)
+{
+    int ret;
+    TLSX* extension;
+    TLSX* priority = NULL;
+    TLSX* ext = NULL;
+    word16 name;
+    SupportedCurve* curve;
+
+    extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS);
+    /* May be doing PSK with no key exchange. */
+    if (extension == NULL)
+        return 0;
+
+    if ((ret = TLSX_PopulateSupportedGroups(ssl, &priority)) != WOLFSSL_SUCCESS)
+        return ret;
+
+    ext = TLSX_Find(priority, TLSX_SUPPORTED_GROUPS);
+    curve = (SupportedCurve*)ext->data;
+    name = curve->name;
+
+    curve = (SupportedCurve*)extension->data;
+    while (curve != NULL) {
+        if (curve->name == name)
+            break;
+        curve = curve->next;
+    }
+
+    if (curve == NULL) {
+        /* Couldn't find the preferred group in client list. */
+        extension->resp = 1;
+
+        /* Send server list back and free client list. */
+        curve = (SupportedCurve*)extension->data;
+        extension->data = ext->data;
+        ext->data = curve;
+    }
+
+    TLSX_FreeAll(priority, ssl->heap);
+
+    return 0;
+}
+
+#endif
+
+#if defined(HAVE_FFDHE) && !defined(WOLFSSL_NO_TLS12)
+/* Set the highest priority common FFDHE group on the server as compared to
+ * client extensions.
+ *
+ * ssl    SSL/TLS object.
+ * returns 0 on success, otherwise an error.
+ */
+int TLSX_SupportedFFDHE_Set(WOLFSSL* ssl)
+{
+    int ret = 0;
+    TLSX* extension;
+    TLSX* priority = NULL;
+    TLSX* ext = NULL;
+    SupportedCurve* serverGroup;
+    SupportedCurve* clientGroup;
+    SupportedCurve* group;
+    const DhParams* params = NULL;
+    int found = 0;
+
+    extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS);
+    /* May be doing PSK with no key exchange. */
+    if (extension == NULL)
+        return 0;
+    clientGroup = (SupportedCurve*)extension->data;
+    for (group = clientGroup; group != NULL; group = group->next) {
+        if (group->name >= MIN_FFHDE_GROUP && group->name <= MAX_FFHDE_GROUP) {
+            found = 1;
+            break;
+        }
+    }
+    if (!found)
+        return 0;
+
+    if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) {
+        XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap,
+                                                       DYNAMIC_TYPE_PUBLIC_KEY);
+    }
+    if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) {
+        XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap,
+                                                       DYNAMIC_TYPE_PUBLIC_KEY);
+    }
+    ssl->buffers.serverDH_P.buffer = NULL;
+    ssl->buffers.serverDH_G.buffer = NULL;
+    ssl->buffers.weOwnDH = 0;
+    ssl->options.haveDH = 0;
+
+
+    if ((ret = TLSX_PopulateSupportedGroups(ssl, &priority)) != WOLFSSL_SUCCESS)
+        return ret;
+    ret = 0;
+
+    ext = TLSX_Find(priority, TLSX_SUPPORTED_GROUPS);
+    serverGroup = (SupportedCurve*)ext->data;
+
+    for (; serverGroup != NULL; serverGroup = serverGroup->next) {
+        if ((serverGroup->name & NAMED_DH_MASK) != NAMED_DH_MASK)
+            continue;
+
+        for (group = clientGroup; group != NULL; group = group->next) {
+            if (serverGroup->name != group->name)
+                continue;
+
+            switch (serverGroup->name) {
+            #ifdef HAVE_FFDHE_2048
+                case WOLFSSL_FFDHE_2048:
+                    params = wc_Dh_ffdhe2048_Get();
+                    break;
+            #endif
+            #ifdef HAVE_FFDHE_3072
+                case WOLFSSL_FFDHE_3072:
+                    params = wc_Dh_ffdhe3072_Get();
+                    break;
+            #endif
+            #ifdef HAVE_FFDHE_4096
+                case WOLFSSL_FFDHE_4096:
+                    params = wc_Dh_ffdhe4096_Get();
+                    break;
+            #endif
+            #ifdef HAVE_FFDHE_6144
+                case WOLFSSL_FFDHE_6144:
+                    params = wc_Dh_ffdhe6144_Get();
+                    break;
+            #endif
+            #ifdef HAVE_FFDHE_8192
+                case WOLFSSL_FFDHE_8192:
+                    params = wc_Dh_ffdhe8192_Get();
+                    break;
+            #endif
+            }
+            if (params == NULL)
+                return BAD_FUNC_ARG;
+            if (params->p_len >= ssl->options.minDhKeySz &&
+                                     params->p_len <= ssl->options.maxDhKeySz) {
+                break;
+            }
+        }
+
+        if (group != NULL && serverGroup->name == group->name)
+            break;
+    }
+
+    if (serverGroup) {
+        ssl->buffers.serverDH_P.buffer = (unsigned char *)params->p;
+        ssl->buffers.serverDH_P.length = params->p_len;
+        ssl->buffers.serverDH_G.buffer = (unsigned char *)params->g;
+        ssl->buffers.serverDH_G.length = params->g_len;
+        ssl->namedGroup = serverGroup->name;
+    #if !defined(WOLFSSL_OLD_PRIME_CHECK) && \
+        !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
+        ssl->options.dhDoKeyTest = 0;
+    #endif
+        ssl->options.haveDH = 1;
+    }
+
+    TLSX_FreeAll(priority, ssl->heap);
+
+    return ret;
+}
+#endif /* HAVE_FFDHE && !WOLFSSL_NO_TLS12 */
+
+#endif /* !NO_WOLFSSL_SERVER */
+
+#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)
+/* Return the preferred group.
+ *
+ * ssl             SSL/TLS object.
+ * checkSupported  Whether to check for the first supported group.
+ * returns BAD_FUNC_ARG if no group found, otherwise the group.
+ */
+int TLSX_SupportedCurve_Preferred(WOLFSSL* ssl, int checkSupported)
+{
+    TLSX* extension;
+    SupportedCurve* curve;
+
+    extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS);
+    if (extension == NULL)
+        return BAD_FUNC_ARG;
+
+    curve = (SupportedCurve*)extension->data;
+    while (curve != NULL) {
+        if (!checkSupported || TLSX_KeyShare_IsSupported(curve->name))
+            return curve->name;
+        curve = curve->next;
+    }
+
+    return BAD_FUNC_ARG;
+}
+
+#endif
+
+#ifndef NO_WOLFSSL_SERVER
+
+static int TLSX_PointFormat_Parse(WOLFSSL* ssl, byte* input, word16 length,
+                                                                 byte isRequest)
+{
+    int ret;
+
+    /* validating formats list length */
+    if (ENUM_LEN > length || length != (word16)ENUM_LEN + input[0])
+        return BUFFER_ERROR;
+
+    if (isRequest) {
+        /* adding uncompressed point format to response */
+        ret = TLSX_UsePointFormat(&ssl->extensions, WOLFSSL_EC_PF_UNCOMPRESSED,
+                                                                     ssl->heap);
+        if (ret != WOLFSSL_SUCCESS)
+            return ret; /* throw error */
+
+        TLSX_SetResponse(ssl, TLSX_EC_POINT_FORMATS);
+    }
+
+    return 0;
+}
+
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
+int TLSX_ValidateSupportedCurves(WOLFSSL* ssl, byte first, byte second) {
+    TLSX*           extension = NULL;
+    SupportedCurve* curve     = NULL;
+    word32          oid       = 0;
+    word32          pkOid     = 0;
+    word32          defOid    = 0;
+    word32          defSz     = 80; /* Maximum known curve size is 66. */
+    word32          nextOid   = 0;
+    word32          nextSz    = 80; /* Maximum known curve size is 66. */
+    word32          currOid   = ssl->ecdhCurveOID;
+    int             ephmSuite = 0;
+    word16          octets    = 0; /* according to 'ecc_set_type ecc_sets[];' */
+    int             sig       = 0; /* validate signature */
+    int             key       = 0; /* validate key       */
+
+    (void)oid;
+
+    if (first == ECC_BYTE || first == CHACHA_BYTE)
+        extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS);
+    if (!extension)
+        return 1; /* no suite restriction */
+
+    for (curve = (SupportedCurve*)extension->data;
+         curve && !(sig && key);
+         curve = curve->next) {
+
+    #ifdef OPENSSL_EXTRA
+        /* skip if name is not in supported ECC range */
+        if (curve->name > WOLFSSL_ECC_X448)
+            continue;
+        /* skip if curve is disabled by user */
+        if (ssl->ctx->disabledCurves & (1 << curve->name))
+            continue;
+    #endif
+
+        /* find supported curve */
+        switch (curve->name) {
+#ifdef HAVE_ECC
+    #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case WOLFSSL_ECC_SECP160R1:
+                pkOid = oid = ECC_SECP160R1_OID;
+                octets = 20;
+                break;
+        #endif /* !NO_ECC_SECP */
+        #ifdef HAVE_ECC_SECPR2
+            case WOLFSSL_ECC_SECP160R2:
+                pkOid = oid = ECC_SECP160R2_OID;
+                octets = 20;
+                break;
+        #endif /* HAVE_ECC_SECPR2 */
+        #ifdef HAVE_ECC_KOBLITZ
+            case WOLFSSL_ECC_SECP160K1:
+                pkOid = oid = ECC_SECP160K1_OID;
+                octets = 20;
+                break;
+        #endif /* HAVE_ECC_KOBLITZ */
+    #endif
+    #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case WOLFSSL_ECC_SECP192R1:
+                pkOid = oid = ECC_SECP192R1_OID;
+                octets = 24;
+                break;
+        #endif /* !NO_ECC_SECP */
+        #ifdef HAVE_ECC_KOBLITZ
+            case WOLFSSL_ECC_SECP192K1:
+                pkOid = oid = ECC_SECP192K1_OID;
+                octets = 24;
+                break;
+        #endif /* HAVE_ECC_KOBLITZ */
+    #endif
+    #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case WOLFSSL_ECC_SECP224R1:
+                pkOid = oid = ECC_SECP224R1_OID;
+                octets = 28;
+                break;
+        #endif /* !NO_ECC_SECP */
+        #ifdef HAVE_ECC_KOBLITZ
+            case WOLFSSL_ECC_SECP224K1:
+                pkOid = oid = ECC_SECP224K1_OID;
+                octets = 28;
+                break;
+        #endif /* HAVE_ECC_KOBLITZ */
+    #endif
+    #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case WOLFSSL_ECC_SECP256R1:
+                pkOid = oid = ECC_SECP256R1_OID;
+                octets = 32;
+                break;
+        #endif /* !NO_ECC_SECP */
+    #endif /* !NO_ECC256 || HAVE_ALL_CURVES */
+#endif
+        #ifdef HAVE_CURVE25519
+            case WOLFSSL_ECC_X25519:
+                oid = ECC_X25519_OID;
+            #ifdef HAVE_ED25519
+                pkOid = ECC_ED25519_OID;
+            #else
+                pkOid = ECC_X25519_OID;
+            #endif
+                octets = 32;
+                break;
+        #endif /* HAVE_CURVE25519 */
+#ifdef HAVE_ECC
+    #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES)
+        #ifdef HAVE_ECC_KOBLITZ
+            case WOLFSSL_ECC_SECP256K1:
+                pkOid = oid = ECC_SECP256K1_OID;
+                octets = 32;
+                break;
+        #endif /* HAVE_ECC_KOBLITZ */
+        #ifdef HAVE_ECC_BRAINPOOL
+            case WOLFSSL_ECC_BRAINPOOLP256R1:
+                pkOid = oid = ECC_BRAINPOOLP256R1_OID;
+                octets = 32;
+                break;
+        #endif /* HAVE_ECC_BRAINPOOL */
+    #endif
+#endif
+        #ifdef HAVE_CURVE448
+            case WOLFSSL_ECC_X448:
+                oid = ECC_X448_OID;
+            #ifdef HAVE_ED448
+                pkOid = ECC_ED448_OID;
+            #else
+                pkOid = ECC_X448_OID;
+            #endif
+                octets = 57;
+                break;
+        #endif /* HAVE_CURVE448 */
+#ifdef HAVE_ECC
+    #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case WOLFSSL_ECC_SECP384R1:
+                pkOid = oid = ECC_SECP384R1_OID;
+                octets = 48;
+                break;
+        #endif /* !NO_ECC_SECP */
+        #ifdef HAVE_ECC_BRAINPOOL
+            case WOLFSSL_ECC_BRAINPOOLP384R1:
+                pkOid = oid = ECC_BRAINPOOLP384R1_OID;
+                octets = 48;
+                break;
+        #endif /* HAVE_ECC_BRAINPOOL */
+    #endif
+    #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)
+        #ifdef HAVE_ECC_BRAINPOOL
+            case WOLFSSL_ECC_BRAINPOOLP512R1:
+                pkOid = oid = ECC_BRAINPOOLP512R1_OID;
+                octets = 64;
+                break;
+        #endif /* HAVE_ECC_BRAINPOOL */
+    #endif
+    #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case WOLFSSL_ECC_SECP521R1:
+                pkOid = oid = ECC_SECP521R1_OID;
+                octets = 66;
+                break;
+        #endif /* !NO_ECC_SECP */
+    #endif
+#endif
+            default: continue; /* unsupported curve */
+        }
+
+    #ifdef HAVE_ECC
+        /* Set default Oid */
+        if (defOid == 0 && ssl->eccTempKeySz <= octets && defSz > octets) {
+            defOid = oid;
+            defSz = octets;
+        }
+
+        /* The eccTempKeySz is the preferred ephemeral key size */
+        if (currOid == 0 && ssl->eccTempKeySz == octets)
+            currOid = oid;
+        if ((nextOid == 0 || nextSz > octets) && ssl->eccTempKeySz <= octets) {
+            nextOid = oid;
+            nextSz  = octets;
+        }
+    #else
+        if (defOid == 0 && defSz > octets) {
+            defOid = oid;
+            defSz = octets;
+        }
+
+        if (currOid == 0)
+            currOid = oid;
+        if (nextOid == 0 || nextSz > octets) {
+            nextOid = oid;
+            nextSz  = octets;
+        }
+    #endif
+
+        if (first == ECC_BYTE) {
+            switch (second) {
+                /* ECDHE_ECDSA */
+                case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
+                case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
+                case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
+                case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
+                case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
+                case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
+                case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+                case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
+                case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
+                case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8:
+                    sig |= ssl->pkCurveOID == pkOid;
+                    key |= ssl->ecdhCurveOID == oid;
+                    ephmSuite = 1;
+                break;
+
+#ifdef WOLFSSL_STATIC_DH
+                /* ECDH_ECDSA */
+                case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
+                case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
+                case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
+                case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
+                case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
+                case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
+                case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
+                case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
+                    if (oid == ECC_X25519_OID && defOid == oid) {
+                        defOid = 0;
+                        defSz = 80;
+                    }
+                    if (oid == ECC_X448_OID && defOid == oid) {
+                        defOid = 0;
+                        defSz = 80;
+                    }
+                    sig |= ssl->pkCurveOID == pkOid;
+                    key |= ssl->pkCurveOID == oid;
+                break;
+#endif /* WOLFSSL_STATIC_DH */
+#ifndef NO_RSA
+                /* ECDHE_RSA */
+                case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
+                case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
+                case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
+                case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
+                case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+                case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
+                case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+                case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
+                    sig = 1;
+                    key |= ssl->ecdhCurveOID == oid;
+                    ephmSuite = 1;
+                break;
+
+#ifdef WOLFSSL_STATIC_DH
+                /* ECDH_RSA */
+                case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
+                case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
+                case TLS_ECDH_RSA_WITH_RC4_128_SHA:
+                case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
+                case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
+                case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
+                case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
+                case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
+                    if (oid == ECC_X25519_OID && defOid == oid) {
+                        defOid = 0;
+                        defSz = 80;
+                    }
+                    if (oid == ECC_X448_OID && defOid == oid) {
+                        defOid = 0;
+                        defSz = 80;
+                    }
+                    sig = 1;
+                    key |= ssl->pkCurveOID == pkOid;
+                break;
+#endif /* WOLFSSL_STATIC_DH */
+#endif
+                default:
+                    if (oid == ECC_X25519_OID && defOid == oid) {
+                        defOid = 0;
+                        defSz = 80;
+                    }
+                    if (oid == ECC_X448_OID && defOid == oid) {
+                        defOid = 0;
+                        defSz = 80;
+                    }
+                    if (oid != ECC_X25519_OID && oid != ECC_X448_OID) {
+                        sig = 1;
+                    }
+                    key = 1;
+                break;
+            }
+        }
+
+        /* ChaCha20-Poly1305 ECC cipher suites */
+        if (first == CHACHA_BYTE) {
+            switch (second) {
+                /* ECDHE_ECDSA */
+                case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 :
+                case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
+                    sig |= ssl->pkCurveOID == pkOid;
+                    key |= ssl->ecdhCurveOID == oid;
+                    ephmSuite = 1;
+                break;
+#ifndef NO_RSA
+                /* ECDHE_RSA */
+                case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 :
+                case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
+                    sig = 1;
+                    key |= ssl->ecdhCurveOID == oid;
+                    ephmSuite = 1;
+                break;
+#endif
+                default:
+                    sig = 1;
+                    key = 1;
+                break;
+            }
+        }
+    }
+
+    /* Choose the default if it is at the required strength. */
+#ifdef HAVE_ECC
+    if (ssl->ecdhCurveOID == 0 && defSz == ssl->eccTempKeySz)
+#else
+    if (ssl->ecdhCurveOID == 0)
+#endif
+    {
+        key = 1;
+        ssl->ecdhCurveOID = defOid;
+    }
+    /* Choose any curve at the required strength. */
+    if (ssl->ecdhCurveOID == 0) {
+        key = 1;
+        ssl->ecdhCurveOID = currOid;
+    }
+    /* Choose the default if it is at the next highest strength. */
+    if (ssl->ecdhCurveOID == 0 && defSz == nextSz)
+        ssl->ecdhCurveOID = defOid;
+    /* Choose any curve at the next highest strength. */
+    if (ssl->ecdhCurveOID == 0)
+        ssl->ecdhCurveOID = nextOid;
+    /* No curve and ephemeral ECC suite requires a matching curve. */
+    if (ssl->ecdhCurveOID == 0 && ephmSuite)
+        key = 0;
+
+    return sig && key;
+}
+#endif
+
+#endif /* NO_WOLFSSL_SERVER */
+
+int TLSX_UseSupportedCurve(TLSX** extensions, word16 name, void* heap)
+{
+    TLSX* extension = NULL;
+    SupportedCurve* curve = NULL;
+    int ret;
+
+    if (extensions == NULL)
+        return BAD_FUNC_ARG;
+
+    extension = TLSX_Find(*extensions, TLSX_SUPPORTED_GROUPS);
+
+    if (!extension) {
+        ret = TLSX_SupportedCurve_New(&curve, name, heap);
+        if (ret != 0)
+            return ret;
+
+        ret = TLSX_Push(extensions, TLSX_SUPPORTED_GROUPS, curve, heap);
+        if (ret != 0) {
+            XFREE(curve, heap, DYNAMIC_TYPE_TLSX);
+            return ret;
+        }
+    }
+    else {
+        ret = TLSX_SupportedCurve_Append((SupportedCurve*)extension->data, name,
+                                                                          heap);
+        if (ret != 0)
+            return ret;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+int TLSX_UsePointFormat(TLSX** extensions, byte format, void* heap)
+{
+    TLSX* extension = NULL;
+    PointFormat* point = NULL;
+    int ret = 0;
+
+    if (extensions == NULL)
+        return BAD_FUNC_ARG;
+
+    extension = TLSX_Find(*extensions, TLSX_EC_POINT_FORMATS);
+
+    if (!extension) {
+        ret = TLSX_PointFormat_New(&point, format, heap);
+        if (ret != 0)
+            return ret;
+
+        ret = TLSX_Push(extensions, TLSX_EC_POINT_FORMATS, point, heap);
+        if (ret != 0) {
+            XFREE(point, heap, DYNAMIC_TYPE_TLSX);
+            return ret;
+        }
+    }
+    else {
+        ret = TLSX_PointFormat_Append((PointFormat*)extension->data, format,
+                                                                          heap);
+        if (ret != 0)
+            return ret;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+#define EC_FREE_ALL         TLSX_SupportedCurve_FreeAll
+#define EC_VALIDATE_REQUEST TLSX_SupportedCurve_ValidateRequest
+
+#ifndef NO_WOLFSSL_CLIENT
+#define EC_GET_SIZE TLSX_SupportedCurve_GetSize
+#define EC_WRITE    TLSX_SupportedCurve_Write
+#else
+#define EC_GET_SIZE(list)         0
+#define EC_WRITE(a, b)            0
+#endif
+
+#if !defined(NO_WOLFSSL_SERVER) || (defined(WOLFSSL_TLS13) && \
+                                         !defined(WOLFSSL_NO_SERVER_GROUPS_EXT))
+#define EC_PARSE TLSX_SupportedCurve_Parse
+#else
+#define EC_PARSE(a, b, c, d)      0
+#endif
+
+#define PF_FREE_ALL          TLSX_PointFormat_FreeAll
+#define PF_VALIDATE_REQUEST  TLSX_PointFormat_ValidateRequest
+#define PF_VALIDATE_RESPONSE TLSX_PointFormat_ValidateResponse
+
+#define PF_GET_SIZE TLSX_PointFormat_GetSize
+#define PF_WRITE    TLSX_PointFormat_Write
+
+#ifndef NO_WOLFSSL_SERVER
+#define PF_PARSE TLSX_PointFormat_Parse
+#else
+#define PF_PARSE(a, b, c, d)      0
+#endif
+
+#else
+
+#define EC_FREE_ALL(list, heap)
+#define EC_GET_SIZE(list)         0
+#define EC_WRITE(a, b)            0
+#define EC_PARSE(a, b, c, d)      0
+#define EC_VALIDATE_REQUEST(a, b)
+
+#define PF_FREE_ALL(list, heap)
+#define PF_GET_SIZE(list)         0
+#define PF_WRITE(a, b)            0
+#define PF_PARSE(a, b, c, d)      0
+#define PF_VALIDATE_REQUEST(a, b)
+#define PF_VALIDATE_RESPONSE(a, b)
+
+#endif /* HAVE_SUPPORTED_CURVES */
+
+/******************************************************************************/
+/* Renegotiation Indication                                                   */
+/******************************************************************************/
+
+#if defined(HAVE_SECURE_RENEGOTIATION) \
+ || defined(HAVE_SERVER_RENEGOTIATION_INFO)
+
+static byte TLSX_SecureRenegotiation_GetSize(SecureRenegotiation* data,
+                                                                  int isRequest)
+{
+    byte length = OPAQUE8_LEN; /* empty info length */
+
+    /* data will be NULL for HAVE_SERVER_RENEGOTIATION_INFO only */
+    if (data && data->enabled && data->verifySet) {
+        /* client sends client_verify_data only */
+        length += TLS_FINISHED_SZ;
+
+        /* server also sends server_verify_data */
+        if (!isRequest)
+            length += TLS_FINISHED_SZ;
+    }
+
+    return length;
+}
+
+static word16 TLSX_SecureRenegotiation_Write(SecureRenegotiation* data,
+                                                    byte* output, int isRequest)
+{
+    word16 offset = OPAQUE8_LEN; /* RenegotiationInfo length */
+    if (data && data->enabled && data->verifySet) {
+        /* client sends client_verify_data only */
+        XMEMCPY(output + offset, data->client_verify_data, TLS_FINISHED_SZ);
+        offset += TLS_FINISHED_SZ;
+
+        /* server also sends server_verify_data */
+        if (!isRequest) {
+            XMEMCPY(output + offset, data->server_verify_data, TLS_FINISHED_SZ);
+            offset += TLS_FINISHED_SZ;
+        }
+    }
+
+    output[0] = (byte)(offset - 1);  /* info length - self */
+
+    return offset;
+}
+
+static int TLSX_SecureRenegotiation_Parse(WOLFSSL* ssl, byte* input,
+                                                  word16 length, byte isRequest)
+{
+    int ret = SECURE_RENEGOTIATION_E;
+
+    if (length >= OPAQUE8_LEN) {
+        if (isRequest) {
+        #ifndef NO_WOLFSSL_SERVER
+            if (ssl->secure_renegotiation == NULL) {
+                ret = wolfSSL_UseSecureRenegotiation(ssl);
+                if (ret == WOLFSSL_SUCCESS)
+                    ret = 0;
+            }
+            if (ret != 0 && ret != SECURE_RENEGOTIATION_E) {
+            }
+            else if (!ssl->secure_renegotiation->enabled) {
+                if (*input == 0) {
+                    input++; /* get past size */
+
+                    ssl->secure_renegotiation->enabled = 1;
+                    TLSX_SetResponse(ssl, TLSX_RENEGOTIATION_INFO);
+                    ret = 0;
+                }
+                else {
+                    /* already in error state */
+                    WOLFSSL_MSG("SCR client verify data present");
+                }
+            }
+            else if (*input == TLS_FINISHED_SZ) {
+                if (length < TLS_FINISHED_SZ + 1) {
+                    WOLFSSL_MSG("SCR malformed buffer");
+                    ret = BUFFER_E;
+                }
+                else {
+                    input++; /* get past size */
+
+                    /* validate client verify data */
+                    if (XMEMCMP(input,
+                            ssl->secure_renegotiation->client_verify_data,
+                            TLS_FINISHED_SZ) == 0) {
+                        WOLFSSL_MSG("SCR client verify data match");
+                        TLSX_SetResponse(ssl, TLSX_RENEGOTIATION_INFO);
+                        ret = 0;  /* verified */
+                    } else {
+                        /* already in error state */
+                        WOLFSSL_MSG("SCR client verify data Failure");
+                    }
+                }
+            }
+        #endif
+        }
+        else {
+        #ifndef NO_WOLFSSL_CLIENT
+            if (!ssl->secure_renegotiation->enabled) {
+                if (*input == 0) {
+                    ssl->secure_renegotiation->enabled = 1;
+                    ret = 0;
+                }
+            }
+            else if (*input == 2 * TLS_FINISHED_SZ &&
+                     length == 2 * TLS_FINISHED_SZ + OPAQUE8_LEN) {
+                input++;  /* get past size */
+
+                /* validate client and server verify data */
+                if (XMEMCMP(input,
+                            ssl->secure_renegotiation->client_verify_data,
+                            TLS_FINISHED_SZ) == 0 &&
+                    XMEMCMP(input + TLS_FINISHED_SZ,
+                            ssl->secure_renegotiation->server_verify_data,
+                            TLS_FINISHED_SZ) == 0) {
+                    WOLFSSL_MSG("SCR client and server verify data match");
+                    ret = 0;  /* verified */
+                } else {
+                    /* already in error state */
+                    WOLFSSL_MSG("SCR client and server verify data Failure");
+                }
+            }
+        #endif
+        }
+    }
+
+    if (ret != 0) {
+        SendAlert(ssl, alert_fatal, handshake_failure);
+    }
+
+    return ret;
+}
+
+int TLSX_UseSecureRenegotiation(TLSX** extensions, void* heap)
+{
+    int ret = 0;
+    SecureRenegotiation* data;
+
+    data = (SecureRenegotiation*)XMALLOC(sizeof(SecureRenegotiation), heap,
+                                                             DYNAMIC_TYPE_TLSX);
+    if (data == NULL)
+        return MEMORY_E;
+
+    XMEMSET(data, 0, sizeof(SecureRenegotiation));
+
+    ret = TLSX_Push(extensions, TLSX_RENEGOTIATION_INFO, data, heap);
+    if (ret != 0) {
+        XFREE(data, heap, DYNAMIC_TYPE_TLSX);
+        return ret;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+#ifdef HAVE_SERVER_RENEGOTIATION_INFO
+
+int TLSX_AddEmptyRenegotiationInfo(TLSX** extensions, void* heap)
+{
+    int ret;
+
+    /* send empty renegotiation_info extension */
+    TLSX* ext = TLSX_Find(*extensions, TLSX_RENEGOTIATION_INFO);
+    if (ext == NULL) {
+        ret = TLSX_UseSecureRenegotiation(extensions, heap);
+        if (ret != WOLFSSL_SUCCESS)
+            return ret;
+
+        ext = TLSX_Find(*extensions, TLSX_RENEGOTIATION_INFO);
+    }
+    if (ext)
+        ext->resp = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* HAVE_SERVER_RENEGOTIATION_INFO */
+
+
+#define SCR_FREE_ALL(data, heap) XFREE(data, (heap), DYNAMIC_TYPE_TLSX)
+#define SCR_GET_SIZE       TLSX_SecureRenegotiation_GetSize
+#define SCR_WRITE          TLSX_SecureRenegotiation_Write
+#define SCR_PARSE          TLSX_SecureRenegotiation_Parse
+
+#else
+
+#define SCR_FREE_ALL(a, heap)
+#define SCR_GET_SIZE(a, b)    0
+#define SCR_WRITE(a, b, c)    0
+#define SCR_PARSE(a, b, c, d) 0
+
+#endif /* HAVE_SECURE_RENEGOTIATION */
+
+/******************************************************************************/
+/* Session Tickets                                                            */
+/******************************************************************************/
+
+#ifdef HAVE_SESSION_TICKET
+
+#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_CLIENT)
+static void TLSX_SessionTicket_ValidateRequest(WOLFSSL* ssl)
+{
+    TLSX*          extension = TLSX_Find(ssl->extensions, TLSX_SESSION_TICKET);
+    SessionTicket* ticket    = extension ?
+                                         (SessionTicket*)extension->data : NULL;
+
+    if (ticket) {
+        /* TODO validate ticket timeout here! */
+        if (ticket->lifetime == 0xfffffff) {
+            /* send empty ticket on timeout */
+            TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap);
+        }
+    }
+}
+#endif /* WLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */
+
+
+static word16 TLSX_SessionTicket_GetSize(SessionTicket* ticket, int isRequest)
+{
+    (void)isRequest;
+    return ticket ? ticket->size : 0;
+}
+
+static word16 TLSX_SessionTicket_Write(SessionTicket* ticket, byte* output,
+                                                                  int isRequest)
+{
+    word16 offset = 0; /* empty ticket */
+
+    if (isRequest && ticket) {
+        XMEMCPY(output + offset, ticket->data, ticket->size);
+        offset += ticket->size;
+    }
+
+    return offset;
+}
+
+
+static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, byte* input, word16 length,
+                                                                 byte isRequest)
+{
+    int ret = 0;
+
+    (void) input; /* avoid unused parameter if NO_WOLFSSL_SERVER defined */
+
+    if (!isRequest) {
+        if (TLSX_CheckUnsupportedExtension(ssl, TLSX_SESSION_TICKET))
+            return TLSX_HandleUnsupportedExtension(ssl);
+
+        if (length != 0)
+            return BUFFER_ERROR;
+
+#ifndef NO_WOLFSSL_CLIENT
+        ssl->expect_session_ticket = 1;
+#endif
+    }
+#ifndef NO_WOLFSSL_SERVER
+    else {
+        /* server side */
+        if (ssl->ctx->ticketEncCb == NULL) {
+            WOLFSSL_MSG("Client sent session ticket, server has no callback");
+            return 0;
+        }
+
+        if (length == 0) {
+            /* blank ticket */
+            ret = TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap);
+            if (ret == WOLFSSL_SUCCESS) {
+                ret = 0;
+                TLSX_SetResponse(ssl, TLSX_SESSION_TICKET);  /* send blank ticket */
+                ssl->options.createTicket = 1;  /* will send ticket msg */
+                ssl->options.useTicket    = 1;
+                ssl->options.resuming     = 0;  /* no standard resumption */
+                ssl->arrays->sessionIDSz  = 0;  /* no echo on blank ticket */
+            }
+        } else {
+            /* got actual ticket from client */
+            ret = DoClientTicket(ssl, input, length);
+            if (ret == WOLFSSL_TICKET_RET_OK) {    /* use ticket to resume */
+                WOLFSSL_MSG("Using existing client ticket");
+                ssl->options.useTicket = 1;
+                ssl->options.resuming  = 1;
+            } else if (ret == WOLFSSL_TICKET_RET_CREATE) {
+                WOLFSSL_MSG("Using existing client ticket, creating new one");
+                ret = TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap);
+                if (ret == WOLFSSL_SUCCESS) {
+                    ret = 0;
+                    TLSX_SetResponse(ssl, TLSX_SESSION_TICKET);
+                                                    /* send blank ticket */
+                    ssl->options.createTicket = 1;  /* will send ticket msg */
+                    ssl->options.useTicket    = 1;
+                    ssl->options.resuming     = 1;
+                }
+            } else if (ret == WOLFSSL_TICKET_RET_REJECT) {
+                WOLFSSL_MSG("Process client ticket rejected, not using");
+                ssl->options.rejectTicket = 1;
+                ret = 0;  /* not fatal */
+            } else if (ret == WOLFSSL_TICKET_RET_FATAL || ret < 0) {
+                WOLFSSL_MSG("Process client ticket fatal error, not using");
+            }
+        }
+    }
+#endif /* NO_WOLFSSL_SERVER */
+
+    return ret;
+}
+
+WOLFSSL_LOCAL SessionTicket* TLSX_SessionTicket_Create(word32 lifetime,
+                                            byte* data, word16 size, void* heap)
+{
+    SessionTicket* ticket = (SessionTicket*)XMALLOC(sizeof(SessionTicket),
+                                                       heap, DYNAMIC_TYPE_TLSX);
+    if (ticket) {
+        ticket->data = (byte*)XMALLOC(size, heap, DYNAMIC_TYPE_TLSX);
+        if (ticket->data == NULL) {
+            XFREE(ticket, heap, DYNAMIC_TYPE_TLSX);
+            return NULL;
+        }
+
+        XMEMCPY(ticket->data, data, size);
+        ticket->size     = size;
+        ticket->lifetime = lifetime;
+    }
+
+    (void)heap;
+
+    return ticket;
+}
+WOLFSSL_LOCAL void TLSX_SessionTicket_Free(SessionTicket* ticket, void* heap)
+{
+    if (ticket) {
+        XFREE(ticket->data, heap, DYNAMIC_TYPE_TLSX);
+        XFREE(ticket,       heap, DYNAMIC_TYPE_TLSX);
+    }
+
+    (void)heap;
+}
+
+int TLSX_UseSessionTicket(TLSX** extensions, SessionTicket* ticket, void* heap)
+{
+    int ret = 0;
+
+    if (extensions == NULL)
+        return BAD_FUNC_ARG;
+
+    /* If the ticket is NULL, the client will request a new ticket from the
+       server. Otherwise, the client will use it in the next client hello. */
+    if ((ret = TLSX_Push(extensions, TLSX_SESSION_TICKET, (void*)ticket, heap))
+                                                                           != 0)
+        return ret;
+
+    return WOLFSSL_SUCCESS;
+}
+
+#define WOLF_STK_VALIDATE_REQUEST TLSX_SessionTicket_ValidateRequest
+#define WOLF_STK_GET_SIZE         TLSX_SessionTicket_GetSize
+#define WOLF_STK_WRITE            TLSX_SessionTicket_Write
+#define WOLF_STK_PARSE            TLSX_SessionTicket_Parse
+#define WOLF_STK_FREE(stk, heap)  TLSX_SessionTicket_Free((SessionTicket*)stk,(heap))
+
+#else
+
+#define WOLF_STK_FREE(a, b)
+#define WOLF_STK_VALIDATE_REQUEST(a)
+#define WOLF_STK_GET_SIZE(a, b)      0
+#define WOLF_STK_WRITE(a, b, c)      0
+#define WOLF_STK_PARSE(a, b, c, d)   0
+
+#endif /* HAVE_SESSION_TICKET */
+
+/******************************************************************************/
+/* Quantum-Safe-Hybrid                                                        */
+/******************************************************************************/
+
+#ifdef HAVE_QSH
+#if defined(HAVE_NTRU)
+static WC_RNG* gRng;
+static wolfSSL_Mutex* gRngMutex;
+#endif
+
+static void TLSX_QSH_FreeAll(QSHScheme* list, void* heap)
+{
+    QSHScheme* current;
+
+    while ((current = list)) {
+        list = current->next;
+        XFREE(current, heap, DYNAMIC_TYPE_TLSX);
+    }
+
+    (void)heap;
+}
+
+static int TLSX_QSH_Append(QSHScheme** list, word16 name, byte* pub,
+                                                                  word16 pubLen)
+{
+    QSHScheme* temp;
+
+    if (list == NULL)
+        return BAD_FUNC_ARG;
+
+    if ((temp = (QSHScheme*)XMALLOC(sizeof(QSHScheme), NULL,
+                                                    DYNAMIC_TYPE_TLSX)) == NULL)
+        return MEMORY_E;
+
+    temp->name  = name;
+    temp->PK    = pub;
+    temp->PKLen = pubLen;
+    temp->next  = *list;
+
+    *list = temp;
+
+    return 0;
+}
+
+
+/* request for server's public key : 02 indicates 0-2 requested */
+static byte TLSX_QSH_SerPKReq(byte* output, byte isRequest)
+{
+    if (isRequest) {
+        /* only request one public key from the server */
+        output[0] = 0x01;
+
+        return OPAQUE8_LEN;
+    }
+    else {
+        return 0;
+    }
+}
+
+#ifndef NO_WOLFSSL_CLIENT
+
+/* check for TLS_QSH suite */
+static void TLSX_QSH_ValidateRequest(WOLFSSL* ssl, byte* semaphore)
+{
+    int i;
+
+    for (i = 0; i < ssl->suites->suiteSz; i+= 2)
+        if (ssl->suites->suites[i] == QSH_BYTE)
+            return;
+
+    /* No QSH suite found */
+    TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_QUANTUM_SAFE_HYBRID));
+}
+
+
+/* return the size of the QSH hello extension
+   list      the list of QSHScheme structs containing id and key
+   isRequest if 1 then is being sent to the server
+ */
+word16 TLSX_QSH_GetSize(QSHScheme* list, byte isRequest)
+{
+    QSHScheme* temp = list;
+    word16 length = 0;
+
+    /* account for size of scheme list and public key list */
+    if (isRequest)
+        length = OPAQUE16_LEN;
+    length += OPAQUE24_LEN;
+
+    /* for each non null element in list add size */
+    while ((temp)) {
+        /* add public key info Scheme | Key Length | Key */
+        length += OPAQUE16_LEN;
+        length += OPAQUE16_LEN;
+        length += temp->PKLen;
+
+        /* if client add name size for scheme list
+           advance to next QSHScheme struct in list */
+        if (isRequest)
+            length += OPAQUE16_LEN;
+        temp = temp->next;
+    }
+
+    /* add length for request server public keys */
+    if (isRequest)
+        length += OPAQUE8_LEN;
+
+    return length;
+}
+
+
+/* write out a list of QSHScheme IDs */
+static word16 TLSX_QSH_Write(QSHScheme* list, byte* output)
+{
+    QSHScheme* current = list;
+    word16 length      = 0;
+
+    length += OPAQUE16_LEN;
+
+    while (current) {
+        c16toa(current->name, output + length);
+        length += OPAQUE16_LEN;
+        current = (QSHScheme*)current->next;
+    }
+
+    c16toa(length - OPAQUE16_LEN, output); /* writing list length */
+
+    return length;
+}
+
+
+/* write public key list in extension */
+static word16 TLSX_QSHPK_WriteR(QSHScheme* format, byte* output)
+{
+    word32 offset = 0;
+    word16 public_len = 0;
+
+    if (!format)
+        return offset;
+
+    /* write scheme ID */
+    c16toa(format->name, output + offset);
+    offset += OPAQUE16_LEN;
+
+    /* write public key matching scheme */
+    public_len = format->PKLen;
+    c16toa(public_len, output + offset);
+    offset += OPAQUE16_LEN;
+    if (format->PK) {
+        XMEMCPY(output+offset, format->PK, public_len);
+    }
+
+    return public_len + offset;
+}
+
+word16 TLSX_QSHPK_Write(QSHScheme* list, byte* output)
+{
+    QSHScheme* current = list;
+    word32 length = 0;
+    word24 toWire;
+
+    length += OPAQUE24_LEN;
+
+    while (current) {
+        length += TLSX_QSHPK_WriteR(current, output + length);
+        current = (QSHScheme*)current->next;
+    }
+    /* length of public keys sent */
+    c32to24(length - OPAQUE24_LEN, toWire);
+    output[0] = toWire[0];
+    output[1] = toWire[1];
+    output[2] = toWire[2];
+
+    return length;
+}
+
+#endif /* NO_WOLFSSL_CLIENT */
+#ifndef NO_WOLFSSL_SERVER
+
+static void TLSX_QSHAgreement(TLSX** extensions, void* heap)
+{
+    TLSX* extension = TLSX_Find(*extensions, TLSX_QUANTUM_SAFE_HYBRID);
+    QSHScheme* format = NULL;
+    QSHScheme* del    = NULL;
+    QSHScheme* prev   = NULL;
+
+    if (extension == NULL)
+        return;
+
+    format = (QSHScheme*)extension->data;
+    while (format) {
+        if (format->PKLen == 0) {
+            /* case of head */
+            if (format == extension->data) {
+                extension->data = format->next;
+            }
+            if (prev)
+                prev->next = format->next;
+            del = format;
+            format = format->next;
+            XFREE(del, heap, DYNAMIC_TYPE_TMP_BUFFER);
+            del = NULL;
+        } else {
+            prev   = format;
+            format = format->next;
+        }
+    }
+
+    (void)heap;
+}
+
+
+/* Parse in hello extension
+   input     the byte stream to process
+   length    length of total extension found
+   isRequest set to 1 if being sent to the server
+ */
+static int TLSX_QSH_Parse(WOLFSSL* ssl, byte* input, word16 length,
+                                                                 byte isRequest)
+{
+    byte   numKeys    = 0;
+    word16 offset     = 0;
+    word16 schemSz    = 0;
+    word16 offset_len = 0;
+    word32 offset_pk  = 0;
+    word16 name  = 0;
+    word16 PKLen = 0;
+    byte*  PK = NULL;
+    int r;
+
+
+    if (OPAQUE16_LEN > length)
+        return BUFFER_ERROR;
+
+    if (isRequest) {
+        ato16(input, &schemSz);
+
+        /* list of public keys available for QSH schemes */
+        offset_len = schemSz + OPAQUE16_LEN;
+    }
+
+    offset_pk = ((input[offset_len] << 16)   & 0xFF00000) |
+                (((input[offset_len + 1]) << 8) & 0xFF00) |
+                (input[offset_len + 2] & 0xFF);
+    offset_len += OPAQUE24_LEN;
+
+    /* check buffer size */
+    if (offset_pk > length)
+        return BUFFER_ERROR;
+
+    /* set maximum number of keys the client will accept */
+    if (!isRequest)
+        numKeys = (ssl->maxRequest < 1)? 1 : ssl->maxRequest;
+
+    /* hello extension read list of scheme ids */
+    if (isRequest) {
+
+        /* read in request for public keys */
+        ssl->minRequest = (input[length -1] >> 4) & 0xFF;
+        ssl->maxRequest = input[length -1] & 0x0F;
+
+        /* choose the min between min requested by client and 1 */
+        numKeys = (ssl->minRequest > 1) ? ssl->minRequest : 1;
+
+        if (ssl->minRequest > ssl->maxRequest)
+            return BAD_FUNC_ARG;
+
+        offset  += OPAQUE16_LEN;
+        schemSz += offset;
+
+        /* check buffer size */
+        if (schemSz > length)
+            return BUFFER_ERROR;
+
+        while ((offset < schemSz) && numKeys) {
+            /* Scheme ID list */
+            ato16(input + offset, &name);
+            offset += OPAQUE16_LEN;
+
+            /* validate we have scheme id */
+            if (ssl->user_set_QSHSchemes &&
+                    !TLSX_ValidateQSHScheme(&ssl->extensions, name)) {
+                continue;
+            }
+
+            /* server create keys on demand */
+            if ((r = TLSX_CreateNtruKey(ssl, name)) != 0) {
+                WOLFSSL_MSG("Error creating ntru keys");
+                return r;
+            }
+
+            /* peer sent an agreed upon scheme */
+            r = TLSX_UseQSHScheme(&ssl->extensions, name, NULL, 0, ssl->heap);
+
+            if (r != WOLFSSL_SUCCESS) return r; /* throw error */
+
+            numKeys--;
+        }
+
+        /* choose the min between min requested by client and 1 */
+        numKeys = (ssl->minRequest > 1) ? ssl->minRequest : 1;
+    }
+
+    /* QSHPK struct */
+    offset_pk += offset_len;
+    while ((offset_len < offset_pk) && numKeys) {
+        QSHKey * temp;
+
+        if ((temp = (QSHKey*)XMALLOC(sizeof(QSHKey), ssl->heap,
+                                                    DYNAMIC_TYPE_TLSX)) == NULL)
+            return MEMORY_E;
+
+        /* initialize */
+        temp->next = NULL;
+        temp->pub.buffer = NULL;
+        temp->pub.length = 0;
+        temp->pri.buffer = NULL;
+        temp->pri.length = 0;
+
+        /* scheme id */
+        ato16(input + offset_len, &(temp->name));
+        offset_len += OPAQUE16_LEN;
+
+        /* public key length */
+        ato16(input + offset_len, &PKLen);
+        temp->pub.length = PKLen;
+        offset_len += OPAQUE16_LEN;
+
+
+        if (isRequest) {
+            /* validate we have scheme id */
+            if (ssl->user_set_QSHSchemes &&
+                    (!TLSX_ValidateQSHScheme(&ssl->extensions, temp->name))) {
+                offset_len += PKLen;
+                XFREE(temp, ssl->heap, DYNAMIC_TYPE_TLSX);
+                continue;
+            }
+        }
+
+        /* read in public key */
+        if (PKLen > 0) {
+            temp->pub.buffer = (byte*)XMALLOC(temp->pub.length,
+                                            ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+            XMEMCPY(temp->pub.buffer, input + offset_len, temp->pub.length);
+            offset_len += PKLen;
+        }
+        else {
+            PK = NULL;
+        }
+
+        /* use own key when adding to extensions list for sending reply */
+        PKLen = 0;
+        PK = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, &PKLen, temp->name);
+        r  = TLSX_UseQSHScheme(&ssl->extensions, temp->name, PK, PKLen,
+                                                                     ssl->heap);
+
+        /* store peers key */
+        ssl->peerQSHKeyPresent = 1;
+        if (TLSX_AddQSHKey(&ssl->peerQSHKey, temp) != 0)
+            return MEMORY_E;
+
+        if (temp->pub.length == 0) {
+            XFREE(temp, ssl->heap, DYNAMIC_TYPE_TLSX);
+        }
+
+        if (r != WOLFSSL_SUCCESS) {return r;} /* throw error */
+
+        numKeys--;
+    }
+
+    /* reply to a QSH extension sent from client */
+    if (isRequest) {
+        TLSX_SetResponse(ssl, TLSX_QUANTUM_SAFE_HYBRID);
+        /* only use schemes we have key generated for -- free the rest */
+        TLSX_QSHAgreement(&ssl->extensions, ssl->heap);
+    }
+
+    return 0;
+}
+
+
+/* Used for parsing in QSHCipher structs on Key Exchange */
+int TLSX_QSHCipher_Parse(WOLFSSL* ssl, const byte* input, word16 length,
+                                                                  byte isServer)
+{
+    QSHKey* key;
+    word16 Max_Secret_Len = 48;
+    word16 offset     = 0;
+    word16 offset_len = 0;
+    word32 offset_pk  = 0;
+    word16 name       = 0;
+    word16 secretLen  = 0;
+    byte*  secret     = NULL;
+    word16 buffLen    = 0;
+    byte buff[145]; /* size enough for 3 secrets */
+    buffer* buf;
+
+    /* pointer to location where secret should be stored */
+    if (isServer) {
+        buf = ssl->QSH_secret->CliSi;
+    }
+    else {
+        buf = ssl->QSH_secret->SerSi;
+    }
+
+    offset_pk = ((input[offset_len] << 16)    & 0xFF0000) |
+                (((input[offset_len + 1]) << 8) & 0xFF00) |
+                (input[offset_len + 2] & 0xFF);
+    offset_len += OPAQUE24_LEN;
+
+    /* validating extension list length -- check if trying to read over edge
+       of buffer */
+    if (length < (offset_pk + OPAQUE24_LEN)) {
+        return BUFFER_ERROR;
+    }
+
+    /* QSHCipherList struct */
+    offset_pk += offset_len;
+    while (offset_len < offset_pk) {
+
+        /* scheme id */
+        ato16(input + offset_len, &name);
+        offset_len += OPAQUE16_LEN;
+
+        /* public key length */
+        ato16(input + offset_len, &secretLen);
+        offset_len += OPAQUE16_LEN;
+
+        /* read in public key */
+        if (secretLen > 0) {
+            secret = (byte*)(input + offset_len);
+            offset_len += secretLen;
+        }
+        else {
+            secret = NULL;
+        }
+
+        /* no secret sent */
+        if (secret == NULL)
+            continue;
+
+        /* find corresponding key */
+        key = ssl->QSH_Key;
+        while (key) {
+            if (key->name == name)
+                break;
+            else
+                key = (QSHKey*)key->next;
+        }
+
+        /* if we do not have the key than there was a big issue negotiation */
+        if (key == NULL) {
+            WOLFSSL_MSG("key was null for decryption!!!\n");
+            return MEMORY_E;
+        }
+
+        /* Decrypt sent secret */
+        buffLen = Max_Secret_Len;
+        QSH_Decrypt(key, secret, secretLen, buff + offset, &buffLen);
+        offset += buffLen;
+    }
+
+    /* allocate memory for buffer */
+    buf->length = offset;
+    buf->buffer = (byte*)XMALLOC(offset, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (buf->buffer == NULL)
+        return MEMORY_E;
+
+    /* store secrets */
+    XMEMCPY(buf->buffer, buff, offset);
+    ForceZero(buff, offset);
+
+    return offset_len;
+}
+
+
+/* return 1 on success */
+int TLSX_ValidateQSHScheme(TLSX** extensions, word16 theirs) {
+    TLSX* extension = TLSX_Find(*extensions, TLSX_QUANTUM_SAFE_HYBRID);
+    QSHScheme* format    = NULL;
+
+    /* if no extension is sent then do not use QSH */
+    if (!extension) {
+        WOLFSSL_MSG("No QSH Extension");
+        return 0;
+    }
+
+    for (format = (QSHScheme*)extension->data; format; format = format->next) {
+        if (format->name == theirs) {
+            WOLFSSL_MSG("Found Matching QSH Scheme");
+            return 1; /* have QSH */
+        }
+    }
+
+    return 0;
+}
+#endif /* NO_WOLFSSL_SERVER */
+
+/* test if the QSH Scheme is implemented
+   return 1 if yes 0 if no */
+static int TLSX_HaveQSHScheme(word16 name)
+{
+    switch(name) {
+        #ifdef HAVE_NTRU
+            case WOLFSSL_NTRU_EESS439:
+            case WOLFSSL_NTRU_EESS593:
+            case WOLFSSL_NTRU_EESS743:
+                    return 1;
+        #endif
+            case WOLFSSL_LWE_XXX:
+            case WOLFSSL_HFE_XXX:
+                    return 0; /* not supported yet */
+
+        default:
+            return 0;
+    }
+}
+
+
+/* Add a QSHScheme struct to list of usable ones */
+int TLSX_UseQSHScheme(TLSX** extensions, word16 name, byte* pKey, word16 pkeySz,
+                                                                     void* heap)
+{
+    TLSX*      extension = NULL;
+    QSHScheme* format    = NULL;
+    int        ret       = 0;
+
+    /* sanity check */
+    if (extensions == NULL || (pKey == NULL && pkeySz != 0))
+        return BAD_FUNC_ARG;
+
+    extension = TLSX_Find(*extensions, TLSX_QUANTUM_SAFE_HYBRID);
+
+    /* if scheme is implemented than add */
+    if (TLSX_HaveQSHScheme(name)) {
+        if ((ret = TLSX_QSH_Append(&format, name, pKey, pkeySz)) != 0)
+            return ret;
+
+        extension = TLSX_Find(*extensions, TLSX_QUANTUM_SAFE_HYBRID);
+        if (!extension) {
+            if ((ret = TLSX_Push(extensions, TLSX_QUANTUM_SAFE_HYBRID, format,
+                                                                  heap)) != 0) {
+                XFREE(format, 0, DYNAMIC_TYPE_TLSX);
+                return ret;
+            }
+        }
+        else {
+            /* push new QSH object to extension data. */
+            format->next = (QSHScheme*)extension->data;
+            extension->data = (void*)format;
+
+            /* look for another format of the same name to remove (replacement) */
+            do {
+                if (format->next && (format->next->name == name)) {
+                    QSHScheme* next = format->next;
+
+                    format->next = next->next;
+                    XFREE(next, 0, DYNAMIC_TYPE_TLSX);
+
+                    break;
+                }
+            } while ((format = format->next));
+        }
+    }
+    return WOLFSSL_SUCCESS;
+}
+
+#define QSH_FREE_ALL         TLSX_QSH_FreeAll
+#define QSH_VALIDATE_REQUEST TLSX_QSH_ValidateRequest
+
+#ifndef NO_WOLFSSL_CLIENT
+#define QSH_GET_SIZE TLSX_QSH_GetSize
+#define QSH_WRITE    TLSX_QSH_Write
+#else
+#define QSH_GET_SIZE(list, a)      0
+#define QSH_WRITE(a, b)            0
+#endif
+
+#ifndef NO_WOLFSSL_SERVER
+#define QSH_PARSE TLSX_QSH_Parse
+#else
+#define QSH_PARSE(a, b, c, d)      0
+#endif
+
+#define QSHPK_WRITE TLSX_QSHPK_Write
+#define QSH_SERREQ TLSX_QSH_SerPKReq
+#else
+
+#define QSH_FREE_ALL(list, heap)
+#define QSH_GET_SIZE(list, a)      0
+#define QSH_WRITE(a, b)            0
+#define QSH_PARSE(a, b, c, d)      0
+#define QSHPK_WRITE(a, b)          0
+#define QSH_SERREQ(a, b)           0
+#define QSH_VALIDATE_REQUEST(a, b)
+
+#endif /* HAVE_QSH */
+
+#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+/******************************************************************************/
+/* Encrypt-then-MAC                                                           */
+/******************************************************************************/
+
+#ifndef WOLFSSL_NO_TLS12
+static int TLSX_EncryptThenMac_Use(WOLFSSL* ssl);
+
+/**
+ * Get the size of the Encrypt-Then-MAC extension.
+ *
+ * msgType  Type of message to put extension into.
+ * pSz      Size of extension data.
+ * return SANITY_MSG_E when the message is not allowed to have extension and
+ *        0 otherwise.
+ */
+static int TLSX_EncryptThenMac_GetSize(byte msgType, word16* pSz)
+{
+    (void)pSz;
+
+    if (msgType != client_hello && msgType != server_hello) {
+        return SANITY_MSG_E;
+    }
+
+    /* Empty extension */
+
+    return 0;
+}
+
+/**
+ * Write the Encrypt-Then-MAC extension.
+ *
+ * data     Unused
+ * output   Extension data buffer. Unused.
+ * msgType  Type of message to put extension into.
+ * pSz      Size of extension data.
+ * return SANITY_MSG_E when the message is not allowed to have extension and
+ *        0 otherwise.
+ */
+static int TLSX_EncryptThenMac_Write(void* data, byte* output, byte msgType,
+                                     word16* pSz)
+{
+    (void)data;
+    (void)output;
+    (void)pSz;
+
+    if (msgType != client_hello && msgType != server_hello) {
+        return SANITY_MSG_E;
+    }
+
+    /* Empty extension */
+
+    return 0;
+}
+
+/**
+ * Parse the Encrypt-Then-MAC extension.
+ *
+ * ssl      SSL object
+ * input    Extension data buffer.
+ * length   Length of this extension's data.
+ * msgType  Type of message to extension appeared in.
+ * return SANITY_MSG_E when the message is not allowed to have extension,
+ *        BUFFER_ERROR when the extension's data is invalid,
+ *        MEMORY_E when unable to allocate memory and
+ *        0 otherwise.
+ */
+static int TLSX_EncryptThenMac_Parse(WOLFSSL* ssl, byte* input, word16 length,
+                                     byte msgType)
+{
+    int ret;
+
+    (void)input;
+
+    if (msgType != client_hello && msgType != server_hello) {
+        return SANITY_MSG_E;
+    }
+
+    /* Empty extension */
+    if (length != 0)
+        return BUFFER_ERROR;
+
+    if (msgType == client_hello) {
+        /* Check the user hasn't disallowed use of Encrypt-Then-Mac. */
+        if (!ssl->options.disallowEncThenMac) {
+            ssl->options.encThenMac = 1;
+            /* Set the extension reply. */
+            ret = TLSX_EncryptThenMac_Use(ssl);
+            if (ret != 0)
+                return ret;
+            TLSX_SetResponse(ssl, TLSX_ENCRYPT_THEN_MAC);
+        }
+        return 0;
+    }
+
+    /* Server Hello */
+    if (ssl->options.disallowEncThenMac)
+        return SANITY_MSG_E;
+
+    ssl->options.encThenMac = 1;
+    return 0;
+
+}
+
+/**
+ * Add the Encrypt-Then-MAC extension to list.
+ *
+ * ssl      SSL object
+ * return MEMORY_E when unable to allocate memory and 0 otherwise.
+ */
+static int TLSX_EncryptThenMac_Use(WOLFSSL* ssl)
+{
+    int   ret = 0;
+    TLSX* extension;
+
+    /* Find the Encrypt-Then-Mac extension if it exists. */
+    extension = TLSX_Find(ssl->extensions, TLSX_ENCRYPT_THEN_MAC);
+    if (extension == NULL) {
+        /* Push new Encrypt-Then-Mac extension. */
+        ret = TLSX_Push(&ssl->extensions, TLSX_ENCRYPT_THEN_MAC, NULL,
+            ssl->heap);
+        if (ret != 0)
+            return ret;
+    }
+
+    return 0;
+}
+
+#define ETM_GET_SIZE  TLSX_EncryptThenMac_GetSize
+#define ETM_WRITE     TLSX_EncryptThenMac_Write
+#define ETM_PARSE     TLSX_EncryptThenMac_Parse
+
+#else
+
+#define ETM_GET_SIZE(a, b)    0
+#define ETM_WRITE(a, b, c, d) 0
+#define ETM_PARSE(a, b, c, d) 0
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#endif /* HAVE_ENCRYPT_THEN_MAC && !WOLFSSL_AEAD_ONLY */
+
+/******************************************************************************/
+/* Supported Versions                                                         */
+/******************************************************************************/
+
+#ifdef WOLFSSL_TLS13
+/* Return the size of the SupportedVersions extension's data.
+ *
+ * data       The SSL/TLS object.
+ * msgType The type of the message this extension is being written into.
+ * returns the length of data that will be in the extension.
+ */
+static int TLSX_SupportedVersions_GetSize(void* data, byte msgType, word16* pSz)
+{
+    WOLFSSL* ssl = (WOLFSSL*)data;
+
+    if (msgType == client_hello) {
+        /* TLS v1.2 and TLS v1.3  */
+        int cnt = 0;
+
+        #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+            if ((ssl->options.mask & SSL_OP_NO_TLSv1_3) == 0)
+        #endif
+                cnt++;
+
+        if (ssl->options.downgrade) {
+#ifndef WOLFSSL_NO_TLS12
+        #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+            if ((ssl->options.mask & SSL_OP_NO_TLSv1_2) == 0)
+        #endif
+                cnt++;
+#endif
+
+#ifndef NO_OLD_TLS
+        #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+            if ((ssl->options.mask & SSL_OP_NO_TLSv1_1) == 0)
+        #endif
+                cnt++;
+    #ifdef WOLFSSL_ALLOW_TLSV10
+        #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+            if ((ssl->options.mask & SSL_OP_NO_TLSv1) == 0)
+        #endif
+                cnt++;
+    #endif
+#endif
+        }
+
+        *pSz += (word16)(OPAQUE8_LEN + cnt * OPAQUE16_LEN);
+    }
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    else if (msgType == server_hello || msgType == hello_retry_request)
+        *pSz += OPAQUE16_LEN;
+#endif
+    else
+        return SANITY_MSG_E;
+
+    return 0;
+}
+
+/* Writes the SupportedVersions extension into the buffer.
+ *
+ * data    The SSL/TLS object.
+ * output  The buffer to write the extension into.
+ * msgType The type of the message this extension is being written into.
+ * returns the length of data that was written.
+ */
+static int TLSX_SupportedVersions_Write(void* data, byte* output,
+                                        byte msgType, word16* pSz)
+{
+    WOLFSSL* ssl = (WOLFSSL*)data;
+    byte major;
+    byte* cnt;
+
+    if (msgType == client_hello) {
+        major = ssl->ctx->method->version.major;
+
+
+        cnt = output++;
+        *cnt = 0;
+        #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+            if ((ssl->options.mask & SSL_OP_NO_TLSv1_3) == 0)
+        #endif
+            {
+                *cnt += OPAQUE16_LEN;
+#ifdef WOLFSSL_TLS13_DRAFT
+                /* The TLS draft major number. */
+                *(output++) = TLS_DRAFT_MAJOR;
+                /* Version of draft supported. */
+                *(output++) = TLS_DRAFT_MINOR;
+#else
+                *(output++) = major;
+                *(output++) = (byte)TLSv1_3_MINOR;
+#endif
+            }
+        if (ssl->options.downgrade) {
+#ifndef WOLFSSL_NO_TLS12
+        #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+            if ((ssl->options.mask & SSL_OP_NO_TLSv1_2) == 0)
+        #endif
+            {
+                *cnt += OPAQUE16_LEN;
+                *(output++) = major;
+                *(output++) = (byte)TLSv1_2_MINOR;
+            }
+#endif
+
+#ifndef NO_OLD_TLS
+        #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+            if ((ssl->options.mask & SSL_OP_NO_TLSv1_1) == 0)
+        #endif
+            {
+                *cnt += OPAQUE16_LEN;
+                *(output++) = major;
+                *(output++) = (byte)TLSv1_1_MINOR;
+            }
+    #ifdef WOLFSSL_ALLOW_TLSV10
+        #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+            if ((ssl->options.mask & SSL_OP_NO_TLSv1) == 0)
+        #endif
+            {
+                *cnt += OPAQUE16_LEN;
+                *(output++) = major;
+                *(output++) = (byte)TLSv1_MINOR;
+            }
+    #endif
+#endif
+        }
+
+        *pSz += (word16)(OPAQUE8_LEN + *cnt);
+    }
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    else if (msgType == server_hello || msgType == hello_retry_request) {
+    #ifdef WOLFSSL_TLS13_DRAFT
+        if (ssl->version.major == SSLv3_MAJOR &&
+                                          ssl->version.minor == TLSv1_3_MINOR) {
+            output[0] = TLS_DRAFT_MAJOR;
+            output[1] = TLS_DRAFT_MINOR;
+        }
+        else
+    #endif
+        {
+            output[0] = ssl->version.major;
+            output[1] = ssl->version.minor;
+        }
+
+        *pSz += OPAQUE16_LEN;
+    }
+#endif
+    else
+        return SANITY_MSG_E;
+
+    return 0;
+}
+
+/* Parse the SupportedVersions extension.
+ *
+ * ssl     The SSL/TLS object.
+ * input   The buffer with the extension data.
+ * length  The length of the extension data.
+ * msgType The type of the message this extension is being parsed from.
+ * returns 0 on success, otherwise failure.
+ */
+static int TLSX_SupportedVersions_Parse(WOLFSSL* ssl, byte* input,
+                                        word16 length, byte msgType)
+{
+    ProtocolVersion pv = ssl->ctx->method->version;
+    int i;
+    int len;
+    byte major, minor;
+    int newMinor = 0;
+    int set = 0;
+
+    if (msgType == client_hello) {
+        /* Must contain a length and at least one version. */
+        if (length < OPAQUE8_LEN + OPAQUE16_LEN || (length & 1) != 1)
+            return BUFFER_ERROR;
+
+        len = *input;
+
+        /* Protocol version array must fill rest of data. */
+        if (length != (word16)OPAQUE8_LEN + len)
+            return BUFFER_ERROR;
+
+        input++;
+
+        /* Find first match. */
+        for (i = 0; i < len; i += OPAQUE16_LEN) {
+            major = input[i];
+            minor = input[i + OPAQUE8_LEN];
+
+#ifdef WOLFSSL_TLS13_DRAFT
+            if (major == TLS_DRAFT_MAJOR && minor == TLS_DRAFT_MINOR) {
+                major = SSLv3_MAJOR;
+                minor = TLSv1_3_MINOR;
+            }
+#else
+            if (major == TLS_DRAFT_MAJOR)
+                continue;
+#endif
+
+            if (major != pv.major)
+                continue;
+
+            /* No upgrade allowed. */
+            if (minor > ssl->version.minor)
+                    continue;
+            /* Check downgrade. */
+            if (minor < ssl->version.minor) {
+                if (!ssl->options.downgrade)
+                    continue;
+
+                if (minor < ssl->options.minDowngrade)
+                    continue;
+
+                if (newMinor == 0 && minor > ssl->options.oldMinor) {
+                    /* Downgrade the version. */
+                    ssl->version.minor = minor;
+                }
+            }
+
+            if (minor >= TLSv1_3_MINOR) {
+                if (!ssl->options.tls1_3) {
+                    ssl->options.tls1_3 = 1;
+                    TLSX_Push(&ssl->extensions, TLSX_SUPPORTED_VERSIONS, ssl,
+                              ssl->heap);
+#ifndef WOLFSSL_TLS13_DRAFT_18
+                    TLSX_SetResponse(ssl, TLSX_SUPPORTED_VERSIONS);
+#endif
+                }
+                if (minor > newMinor) {
+                    ssl->version.minor = minor;
+                    newMinor = minor;
+                }
+            }
+            else if (minor > ssl->options.oldMinor)
+                ssl->options.oldMinor = minor;
+
+            set = 1;
+        }
+        if (!set) {
+ #ifdef WOLFSSL_MYSQL_COMPATIBLE
+            SendAlert(ssl, alert_fatal, wc_protocol_version);
+ #else
+            SendAlert(ssl, alert_fatal, protocol_version);
+ #endif
+            return VERSION_ERROR;
+        }
+    }
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    else if (msgType == server_hello || msgType == hello_retry_request) {
+        /* Must contain one version. */
+        if (length != OPAQUE16_LEN)
+            return BUFFER_ERROR;
+
+        major = input[0];
+        minor = input[OPAQUE8_LEN];
+
+    #ifdef WOLFSSL_TLS13_DRAFT
+        if (major == TLS_DRAFT_MAJOR && minor == TLS_DRAFT_MINOR) {
+            major = SSLv3_MAJOR;
+            minor = TLSv1_3_MINOR;
+        }
+    #endif
+
+        if (major != pv.major)
+            return VERSION_ERROR;
+
+        /* Can't downgrade with this extension below TLS v1.3. */
+        if (minor < TLSv1_3_MINOR)
+            return VERSION_ERROR;
+
+        /* Version is TLS v1.2 to handle downgrading from TLS v1.3+. */
+        if (ssl->options.downgrade && ssl->version.minor == TLSv1_2_MINOR) {
+            /* Set minor version back to TLS v1.3+ */
+            ssl->version.minor = ssl->ctx->method->version.minor;
+        }
+
+        /* No upgrade allowed. */
+        if (ssl->version.minor < minor)
+            return VERSION_ERROR;
+
+        /* Check downgrade. */
+        if (ssl->version.minor > minor) {
+            if (!ssl->options.downgrade)
+                return VERSION_ERROR;
+
+            if (minor < ssl->options.minDowngrade)
+                return VERSION_ERROR;
+
+            /* Downgrade the version. */
+            ssl->version.minor = minor;
+        }
+    }
+#endif
+    else
+        return SANITY_MSG_E;
+
+    return 0;
+}
+
+/* Sets a new SupportedVersions extension into the extension list.
+ *
+ * extensions  The list of extensions.
+ * data        The extensions specific data.
+ * heap        The heap used for allocation.
+ * returns 0 on success, otherwise failure.
+ */
+static int TLSX_SetSupportedVersions(TLSX** extensions, const void* data,
+                                     void* heap)
+{
+    if (extensions == NULL || data == NULL)
+        return BAD_FUNC_ARG;
+
+    return TLSX_Push(extensions, TLSX_SUPPORTED_VERSIONS, (void *)data, heap);
+}
+
+#define SV_GET_SIZE  TLSX_SupportedVersions_GetSize
+#define SV_WRITE     TLSX_SupportedVersions_Write
+#define SV_PARSE     TLSX_SupportedVersions_Parse
+
+#else
+
+#define SV_GET_SIZE(a, b, c) 0
+#define SV_WRITE(a, b, c, d) 0
+#define SV_PARSE(a, b, c, d) 0
+
+#endif /* WOLFSSL_TLS13 */
+
+#if defined(WOLFSSL_TLS13)
+
+/******************************************************************************/
+/* Cookie                                                                     */
+/******************************************************************************/
+
+/* Free the cookie data.
+ *
+ * cookie  Cookie data.
+ * heap    The heap used for allocation.
+ */
+static void TLSX_Cookie_FreeAll(Cookie* cookie, void* heap)
+{
+    (void)heap;
+
+    if (cookie != NULL)
+        XFREE(cookie, heap, DYNAMIC_TYPE_TLSX);
+}
+
+/* Get the size of the encoded Cookie extension.
+ * In messages: ClientHello and HelloRetryRequest.
+ *
+ * cookie   The cookie to write.
+ * msgType  The type of the message this extension is being written into.
+ * returns the number of bytes of the encoded Cookie extension.
+ */
+static int TLSX_Cookie_GetSize(Cookie* cookie, byte msgType, word16* pSz)
+{
+    if (msgType == client_hello || msgType == hello_retry_request)
+        *pSz += OPAQUE16_LEN + cookie->len;
+    else
+        return SANITY_MSG_E;
+    return 0;
+}
+
+/* Writes the Cookie extension into the output buffer.
+ * Assumes that the the output buffer is big enough to hold data.
+ * In messages: ClientHello and HelloRetryRequest.
+ *
+ * cookie   The cookie to write.
+ * output   The buffer to write into.
+ * msgType  The type of the message this extension is being written into.
+ * returns the number of bytes written into the buffer.
+ */
+static int TLSX_Cookie_Write(Cookie* cookie, byte* output, byte msgType,
+                             word16* pSz)
+{
+    if (msgType == client_hello || msgType == hello_retry_request) {
+        c16toa(cookie->len, output);
+        output += OPAQUE16_LEN;
+        XMEMCPY(output, &cookie->data, cookie->len);
+        *pSz += OPAQUE16_LEN + cookie->len;
+    }
+    else
+        return SANITY_MSG_E;
+    return 0;
+}
+
+/* Parse the Cookie extension.
+ * In messages: ClientHello and HelloRetryRequest.
+ *
+ * ssl      The SSL/TLS object.
+ * input    The extension data.
+ * length   The length of the extension data.
+ * msgType  The type of the message this extension is being parsed from.
+ * returns 0 on success and other values indicate failure.
+ */
+static int TLSX_Cookie_Parse(WOLFSSL* ssl, byte* input, word16 length,
+                                 byte msgType)
+{
+    word16  len;
+    word16  idx = 0;
+    TLSX*   extension;
+    Cookie* cookie;
+
+    if (msgType != client_hello && msgType != hello_retry_request)
+        return SANITY_MSG_E;
+
+    /* Message contains length and Cookie which must be at least one byte
+     * in length.
+     */
+    if (length < OPAQUE16_LEN + 1)
+        return BUFFER_E;
+    ato16(input + idx, &len);
+    idx += OPAQUE16_LEN;
+    if (length - idx != len)
+        return BUFFER_E;
+
+    if (msgType == hello_retry_request)
+        return TLSX_Cookie_Use(ssl, input + idx, len, NULL, 0, 0);
+
+    /* client_hello */
+    extension = TLSX_Find(ssl->extensions, TLSX_COOKIE);
+    if (extension == NULL)
+        return HRR_COOKIE_ERROR;
+
+    cookie = (Cookie*)extension->data;
+    if (cookie->len != len || XMEMCMP(&cookie->data, input + idx, len) != 0)
+        return HRR_COOKIE_ERROR;
+
+    /* Request seen. */
+    extension->resp = 0;
+
+    return 0;
+}
+
+/* Use the data to create a new Cookie object in the extensions.
+ *
+ * ssl    SSL/TLS object.
+ * data   Cookie data.
+ * len    Length of cookie data in bytes.
+ * mac    MAC data.
+ * macSz  Length of MAC data in bytes.
+ * resp   Indicates the extension will go into a response (HelloRetryRequest).
+ * returns 0 on success and other values indicate failure.
+ */
+int TLSX_Cookie_Use(WOLFSSL* ssl, byte* data, word16 len, byte* mac,
+                    byte macSz, int resp)
+{
+    int     ret = 0;
+    TLSX*   extension;
+    Cookie* cookie;
+
+    /* Find the cookie extension if it exists. */
+    extension = TLSX_Find(ssl->extensions, TLSX_COOKIE);
+    if (extension == NULL) {
+        /* Push new cookie extension. */
+        ret = TLSX_Push(&ssl->extensions, TLSX_COOKIE, NULL, ssl->heap);
+        if (ret != 0)
+            return ret;
+
+        extension = TLSX_Find(ssl->extensions, TLSX_COOKIE);
+        if (extension == NULL)
+            return MEMORY_E;
+    }
+
+    /* The Cookie structure has one byte for cookie data already. */
+    cookie = (Cookie*)XMALLOC(sizeof(Cookie) + len + macSz - 1, ssl->heap,
+                              DYNAMIC_TYPE_TLSX);
+    if (cookie == NULL)
+        return MEMORY_E;
+
+    cookie->len = len + macSz;
+    XMEMCPY(&cookie->data, data, len);
+    if (mac != NULL)
+        XMEMCPY(&cookie->data + len, mac, macSz);
+
+    extension->data = (void*)cookie;
+    extension->resp = (byte)resp;
+
+    return 0;
+}
+
+#define CKE_FREE_ALL  TLSX_Cookie_FreeAll
+#define CKE_GET_SIZE  TLSX_Cookie_GetSize
+#define CKE_WRITE     TLSX_Cookie_Write
+#define CKE_PARSE     TLSX_Cookie_Parse
+
+#else
+
+#define CKE_FREE_ALL(a, b)    0
+#define CKE_GET_SIZE(a, b, c) 0
+#define CKE_WRITE(a, b, c, d) 0
+#define CKE_PARSE(a, b, c, d) 0
+
+#endif
+#if !defined(WOLFSSL_NO_SIGALG)
+/******************************************************************************/
+/* Signature Algorithms                                                       */
+/******************************************************************************/
+
+/* Return the size of the SignatureAlgorithms extension's data.
+ *
+ * data  Unused
+ * returns the length of data that will be in the extension.
+ */
+
+static word16 TLSX_SignatureAlgorithms_GetSize(void* data)
+{
+    WOLFSSL* ssl = (WOLFSSL*)data;
+
+    return OPAQUE16_LEN + ssl->suites->hashSigAlgoSz;
+}
+
+/* Creates a bit string of supported hash algorithms with RSA PSS.
+ * The bit string is used when determining which signature algorithm to use
+ * when creating the CertificateVerify message.
+ * Note: Valid data has an even length as each signature algorithm is two bytes.
+ *
+ * ssl     The SSL/TLS object.
+ * input   The buffer with the list of supported signature algorithms.
+ * length  The length of the list in bytes.
+ * returns 0 on success, BUFFER_ERROR when the length is not even.
+ */
+static int TLSX_SignatureAlgorithms_MapPss(WOLFSSL *ssl, byte* input,
+                                                                  word16 length)
+{
+    word16 i;
+
+    if ((length & 1) == 1)
+        return BUFFER_ERROR;
+
+    ssl->pssAlgo = 0;
+    for (i = 0; i < length; i += 2) {
+        if (input[i] == rsa_pss_sa_algo && input[i + 1] <= sha512_mac)
+            ssl->pssAlgo |= 1 << input[i + 1];
+    #ifdef WOLFSSL_TLS13
+        if (input[i] == rsa_pss_sa_algo && input[i + 1] >= pss_sha256 &&
+                                                   input[i + 1] <= pss_sha512) {
+            ssl->pssAlgo |= 1 << input[i + 1];
+        }
+    #endif
+    }
+
+    return 0;
+}
+
+/* Writes the SignatureAlgorithms extension into the buffer.
+ *
+ * data    Unused
+ * output  The buffer to write the extension into.
+ * returns the length of data that was written.
+ */
+static word16 TLSX_SignatureAlgorithms_Write(void* data, byte* output)
+{
+    WOLFSSL* ssl = (WOLFSSL*)data;
+
+    c16toa(ssl->suites->hashSigAlgoSz, output);
+    XMEMCPY(output + OPAQUE16_LEN, ssl->suites->hashSigAlgo,
+            ssl->suites->hashSigAlgoSz);
+
+    TLSX_SignatureAlgorithms_MapPss(ssl, output + OPAQUE16_LEN,
+                                    ssl->suites->hashSigAlgoSz);
+
+    return OPAQUE16_LEN + ssl->suites->hashSigAlgoSz;
+}
+
+/* Parse the SignatureAlgorithms extension.
+ *
+ * ssl     The SSL/TLS object.
+ * input   The buffer with the extension data.
+ * length  The length of the extension data.
+ * returns 0 on success, otherwise failure.
+ */
+static int TLSX_SignatureAlgorithms_Parse(WOLFSSL *ssl, byte* input,
+                                  word16 length, byte isRequest, Suites* suites)
+{
+    word16 len;
+
+    if (!isRequest)
+        return BUFFER_ERROR;
+
+    /* Must contain a length and at least algorithm. */
+    if (length < OPAQUE16_LEN + OPAQUE16_LEN || (length & 1) != 0)
+        return BUFFER_ERROR;
+
+    ato16(input, &len);
+    input += OPAQUE16_LEN;
+
+    /* Algorithm array must fill rest of data. */
+    if (length != OPAQUE16_LEN + len)
+        return BUFFER_ERROR;
+
+    /* truncate hashSigAlgo list if too long */
+    suites->hashSigAlgoSz = len;
+    if (suites->hashSigAlgoSz > WOLFSSL_MAX_SIGALGO) {
+        WOLFSSL_MSG("TLSX SigAlgo list exceeds max, truncating");
+        suites->hashSigAlgoSz = WOLFSSL_MAX_SIGALGO;
+    }
+    XMEMCPY(suites->hashSigAlgo, input, suites->hashSigAlgoSz);
+
+    return TLSX_SignatureAlgorithms_MapPss(ssl, input, len);
+}
+
+/* Sets a new SignatureAlgorithms extension into the extension list.
+ *
+ * extensions  The list of extensions.
+ * data        The extensions specific data.
+ * heap        The heap used for allocation.
+ * returns 0 on success, otherwise failure.
+ */
+static int TLSX_SetSignatureAlgorithms(TLSX** extensions, const void* data,
+                                       void* heap)
+{
+    if (extensions == NULL)
+        return BAD_FUNC_ARG;
+
+    return TLSX_Push(extensions, TLSX_SIGNATURE_ALGORITHMS, (void *)data, heap);
+}
+
+#define SA_GET_SIZE  TLSX_SignatureAlgorithms_GetSize
+#define SA_WRITE     TLSX_SignatureAlgorithms_Write
+#define SA_PARSE     TLSX_SignatureAlgorithms_Parse
+#endif
+/******************************************************************************/
+/* Signature Algorithms Certificate                                           */
+/******************************************************************************/
+
+#ifdef WOLFSSL_TLS13
+#if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22)
+/* Return the size of the SignatureAlgorithms extension's data.
+ *
+ * data  Unused
+ * returns the length of data that will be in the extension.
+ */
+static word16 TLSX_SignatureAlgorithmsCert_GetSize(void* data)
+{
+    WOLFSSL* ssl = (WOLFSSL*)data;
+
+    return OPAQUE16_LEN + ssl->certHashSigAlgoSz;
+}
+
+/* Writes the SignatureAlgorithmsCert extension into the buffer.
+ *
+ * data    Unused
+ * output  The buffer to write the extension into.
+ * returns the length of data that was written.
+ */
+static word16 TLSX_SignatureAlgorithmsCert_Write(void* data, byte* output)
+{
+    WOLFSSL* ssl = (WOLFSSL*)data;
+
+    c16toa(ssl->certHashSigAlgoSz, output);
+    XMEMCPY(output + OPAQUE16_LEN, ssl->certHashSigAlgo,
+            ssl->certHashSigAlgoSz);
+
+    return OPAQUE16_LEN + ssl->certHashSigAlgoSz;
+}
+
+/* Parse the SignatureAlgorithmsCert extension.
+ *
+ * ssl     The SSL/TLS object.
+ * input   The buffer with the extension data.
+ * length  The length of the extension data.
+ * returns 0 on success, otherwise failure.
+ */
+static int TLSX_SignatureAlgorithmsCert_Parse(WOLFSSL *ssl, byte* input,
+                                              word16 length, byte isRequest)
+{
+    word16 len;
+
+    if (!isRequest)
+        return BUFFER_ERROR;
+
+    /* Must contain a length and at least algorithm. */
+    if (length < OPAQUE16_LEN + OPAQUE16_LEN || (length & 1) != 0)
+        return BUFFER_ERROR;
+
+    ato16(input, &len);
+    input += OPAQUE16_LEN;
+
+    /* Algorithm array must fill rest of data. */
+    if (length != OPAQUE16_LEN + len)
+        return BUFFER_ERROR;
+
+    /* truncate hashSigAlgo list if too long */
+    ssl->certHashSigAlgoSz = len;
+    if (ssl->certHashSigAlgoSz > WOLFSSL_MAX_SIGALGO) {
+        WOLFSSL_MSG("TLSX SigAlgo list exceeds max, truncating");
+        ssl->certHashSigAlgoSz = WOLFSSL_MAX_SIGALGO;
+    }
+    XMEMCPY(ssl->certHashSigAlgo, input, ssl->certHashSigAlgoSz);
+
+    return 0;
+}
+
+/* Sets a new SignatureAlgorithmsCert extension into the extension list.
+ *
+ * extensions  The list of extensions.
+ * data        The extensions specific data.
+ * heap        The heap used for allocation.
+ * returns 0 on success, otherwise failure.
+ */
+static int TLSX_SetSignatureAlgorithmsCert(TLSX** extensions, const void* data,
+                                                                     void* heap)
+{
+    if (extensions == NULL)
+        return BAD_FUNC_ARG;
+
+    return TLSX_Push(extensions, TLSX_SIGNATURE_ALGORITHMS_CERT, (void *)data,
+                                                                          heap);
+}
+
+#define SAC_GET_SIZE  TLSX_SignatureAlgorithmsCert_GetSize
+#define SAC_WRITE     TLSX_SignatureAlgorithmsCert_Write
+#define SAC_PARSE     TLSX_SignatureAlgorithmsCert_Parse
+#endif /* !WOLFSSL_TLS13_DRAFT_18 && !WOLFSSL_TLS13_DRAFT_22 */
+#endif /* WOLFSSL_TLS13 */
+
+
+/******************************************************************************/
+/* Key Share                                                                  */
+/******************************************************************************/
+
+#ifdef WOLFSSL_TLS13
+/* Create a key share entry using named Diffie-Hellman parameters group.
+ * Generates a key pair.
+ *
+ * ssl   The SSL/TLS object.
+ * kse   The key share entry object.
+ * returns 0 on success, otherwise failure.
+ */
+static int TLSX_KeyShare_GenDhKey(WOLFSSL *ssl, KeyShareEntry* kse)
+{
+    int             ret;
+#ifndef NO_DH
+    byte*           keyData;
+    void*           key = NULL;
+    word32          keySz;
+    word32          dataSz;
+    const DhParams* params;
+#ifdef WOLFSSL_SMALL_STACK
+    DhKey*          dhKey = NULL;
+#else
+    DhKey           dhKey[1];
+#endif
+
+    /* TODO: [TLS13] The key size should come from wolfcrypt. */
+    /* Pick the parameters from the named group. */
+    switch (kse->group) {
+    #ifdef HAVE_FFDHE_2048
+        case WOLFSSL_FFDHE_2048:
+            params = wc_Dh_ffdhe2048_Get();
+            keySz = 29;
+            break;
+    #endif
+    #ifdef HAVE_FFDHE_3072
+        case WOLFSSL_FFDHE_3072:
+            params = wc_Dh_ffdhe3072_Get();
+            keySz = 34;
+            break;
+    #endif
+    #ifdef HAVE_FFDHE_4096
+        case WOLFSSL_FFDHE_4096:
+            params = wc_Dh_ffdhe4096_Get();
+            keySz = 39;
+            break;
+    #endif
+    #ifdef HAVE_FFDHE_6144
+        case WOLFSSL_FFDHE_6144:
+            params = wc_Dh_ffdhe6144_Get();
+            keySz = 46;
+            break;
+    #endif
+    #ifdef HAVE_FFDHE_8192
+        case WOLFSSL_FFDHE_8192:
+            params = wc_Dh_ffdhe8192_Get();
+            keySz = 52;
+            break;
+    #endif
+        default:
+            return BAD_FUNC_ARG;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    dhKey = (DhKey*)XMALLOC(sizeof(DhKey), ssl->heap, DYNAMIC_TYPE_DH);
+    if (dhKey == NULL)
+        return MEMORY_E;
+#endif
+
+    ret = wc_InitDhKey_ex(dhKey, ssl->heap, ssl->devId);
+    if (ret != 0) {
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH);
+    #endif
+        return ret;
+    }
+
+    /* Allocate space for the public key. */
+    dataSz = params->p_len;
+    keyData = (byte*)XMALLOC(dataSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    if (keyData == NULL) {
+        ret = MEMORY_E;
+        goto end;
+    }
+    /* Allocate space for the private key. */
+    key = (byte*)XMALLOC(keySz, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
+    if (key == NULL) {
+        ret = MEMORY_E;
+        goto end;
+    }
+
+    /* Set key */
+    ret = wc_DhSetKey(dhKey,
+        (byte*)params->p, params->p_len,
+        (byte*)params->g, params->g_len);
+    if (ret != 0)
+        goto end;
+
+    /* Generate a new key pair. */
+    ret = wc_DhGenerateKeyPair(dhKey, ssl->rng, (byte*)key, &keySz, keyData,
+                               &dataSz);
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* TODO: Make this function non-blocking */
+    if (ret == WC_PENDING_E) {
+        ret = wc_AsyncWait(ret, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE);
+    }
+#endif
+    if (ret != 0)
+        goto end;
+
+    if (params->p_len != dataSz) {
+        /* Pad the front of the key data with zeros. */
+        XMEMMOVE(keyData + params->p_len - dataSz, keyData, dataSz);
+        XMEMSET(keyData, 0, params->p_len - dataSz);
+    }
+
+    kse->pubKey = keyData;
+    kse->pubKeyLen = params->p_len;
+    kse->key = key;
+    kse->keyLen = keySz;
+
+#ifdef WOLFSSL_DEBUG_TLS
+    WOLFSSL_MSG("Public DH Key");
+    WOLFSSL_BUFFER(keyData, params->p_len);
+#endif
+
+end:
+
+    wc_FreeDhKey(dhKey);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH);
+#endif
+
+    if (ret != 0) {
+        /* Data owned by key share entry otherwise. */
+        if (keyData != NULL)
+            XFREE(keyData, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        if (key != NULL)
+            XFREE(key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
+    }
+#else
+    (void)ssl;
+    (void)kse;
+
+    ret = NOT_COMPILED_IN;
+#endif
+
+    return ret;
+}
+
+/* Create a key share entry using X25519 parameters group.
+ * Generates a key pair.
+ *
+ * ssl   The SSL/TLS object.
+ * kse   The key share entry object.
+ * returns 0 on success, otherwise failure.
+ */
+static int TLSX_KeyShare_GenX25519Key(WOLFSSL *ssl, KeyShareEntry* kse)
+{
+    int             ret;
+#ifdef HAVE_CURVE25519
+    byte*           keyData = NULL;
+    word32          dataSize = CURVE25519_KEYSIZE;
+    curve25519_key* key;
+
+    /* Allocate an ECC key to hold private key. */
+    key = (curve25519_key*)XMALLOC(sizeof(curve25519_key), ssl->heap,
+                                                      DYNAMIC_TYPE_PRIVATE_KEY);
+    if (key == NULL) {
+        WOLFSSL_MSG("EccTempKey Memory error");
+        return MEMORY_E;
+    }
+
+    /* Make an ECC key. */
+    ret = wc_curve25519_init(key);
+    if (ret != 0)
+        goto end;
+    ret = wc_curve25519_make_key(ssl->rng, CURVE25519_KEYSIZE, key);
+    if (ret != 0)
+        goto end;
+
+    /* Allocate space for the public key. */
+    keyData = (byte*)XMALLOC(CURVE25519_KEYSIZE, ssl->heap,
+                                                       DYNAMIC_TYPE_PUBLIC_KEY);
+    if (keyData == NULL) {
+        WOLFSSL_MSG("Key data Memory error");
+        ret = MEMORY_E;
+        goto end;
+    }
+
+    /* Export public key. */
+    if (wc_curve25519_export_public_ex(key, keyData, &dataSize,
+                                                  EC25519_LITTLE_ENDIAN) != 0) {
+        ret = ECC_EXPORT_ERROR;
+        goto end;
+    }
+
+    kse->pubKey = keyData;
+    kse->pubKeyLen = CURVE25519_KEYSIZE;
+    kse->key = key;
+
+#ifdef WOLFSSL_DEBUG_TLS
+    WOLFSSL_MSG("Public Curve25519 Key");
+    WOLFSSL_BUFFER(keyData, dataSize);
+#endif
+
+end:
+    if (ret != 0) {
+        /* Data owned by key share entry otherwise. */
+        if (keyData != NULL)
+            XFREE(keyData, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        wc_curve25519_free(key);
+        XFREE(key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
+    }
+#else
+    (void)ssl;
+    (void)kse;
+
+    ret = NOT_COMPILED_IN;
+#endif /* HAVE_CURVE25519 */
+
+    return ret;
+}
+
+/* Create a key share entry using X448 parameters group.
+ * Generates a key pair.
+ *
+ * ssl   The SSL/TLS object.
+ * kse   The key share entry object.
+ * returns 0 on success, otherwise failure.
+ */
+static int TLSX_KeyShare_GenX448Key(WOLFSSL *ssl, KeyShareEntry* kse)
+{
+    int             ret;
+#ifdef HAVE_CURVE448
+    byte*           keyData = NULL;
+    word32          dataSize = CURVE448_KEY_SIZE;
+    curve448_key*   key;
+
+    /* Allocate an ECC key to hold private key. */
+    key = (curve448_key*)XMALLOC(sizeof(curve448_key), ssl->heap,
+                                                      DYNAMIC_TYPE_PRIVATE_KEY);
+    if (key == NULL) {
+        WOLFSSL_MSG("EccTempKey Memory error");
+        return MEMORY_E;
+    }
+
+    /* Make an ECC key. */
+    ret = wc_curve448_init(key);
+    if (ret != 0)
+        goto end;
+    ret = wc_curve448_make_key(ssl->rng, CURVE448_KEY_SIZE, key);
+    if (ret != 0)
+        goto end;
+
+    /* Allocate space for the public key. */
+    keyData = (byte*)XMALLOC(CURVE448_KEY_SIZE, ssl->heap,
+                                                       DYNAMIC_TYPE_PUBLIC_KEY);
+    if (keyData == NULL) {
+        WOLFSSL_MSG("Key data Memory error");
+        ret = MEMORY_E;
+        goto end;
+    }
+
+    /* Export public key. */
+    if (wc_curve448_export_public_ex(key, keyData, &dataSize,
+                                                    EC448_LITTLE_ENDIAN) != 0) {
+        ret = ECC_EXPORT_ERROR;
+        goto end;
+    }
+
+    kse->pubKey = keyData;
+    kse->pubKeyLen = CURVE448_KEY_SIZE;
+    kse->key = key;
+
+#ifdef WOLFSSL_DEBUG_TLS
+    WOLFSSL_MSG("Public Curve448 Key");
+    WOLFSSL_BUFFER(keyData, dataSize);
+#endif
+
+end:
+    if (ret != 0) {
+        /* Data owned by key share entry otherwise. */
+        if (keyData != NULL)
+            XFREE(keyData, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        wc_curve448_free(key);
+        XFREE(key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
+    }
+#else
+    (void)ssl;
+    (void)kse;
+
+    ret = NOT_COMPILED_IN;
+#endif /* HAVE_CURVE448 */
+
+    return ret;
+}
+
+/* Create a key share entry using named elliptic curve parameters group.
+ * Generates a key pair.
+ *
+ * ssl   The SSL/TLS object.
+ * kse   The key share entry object.
+ * returns 0 on success, otherwise failure.
+ */
+static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse)
+{
+    int      ret;
+#ifdef HAVE_ECC
+    byte*    keyData = NULL;
+    word32   dataSize;
+    byte*    keyPtr = NULL;
+    word32   keySize;
+    ecc_key* eccKey;
+    word16   curveId;
+
+    /* TODO: [TLS13] The key sizes should come from wolfcrypt. */
+    /* Translate named group to a curve id. */
+    switch (kse->group) {
+    #if !defined(NO_ECC256)  || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+        case WOLFSSL_ECC_SECP256R1:
+            curveId = ECC_SECP256R1;
+            keySize = 32;
+            dataSize = keySize * 2 + 1;
+            break;
+        #endif /* !NO_ECC_SECP */
+    #endif
+    #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+        case WOLFSSL_ECC_SECP384R1:
+            curveId = ECC_SECP384R1;
+            keySize = 48;
+            dataSize = keySize * 2 + 1;
+            break;
+        #endif /* !NO_ECC_SECP */
+    #endif
+    #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+        case WOLFSSL_ECC_SECP521R1:
+            curveId = ECC_SECP521R1;
+            keySize = 66;
+            dataSize = keySize * 2 + 1;
+            break;
+        #endif /* !NO_ECC_SECP */
+    #endif
+    #ifdef HAVE_X448
+        case WOLFSSL_ECC_X448:
+            curveId = ECC_X448;
+            dataSize = keySize = 56;
+            break;
+    #endif
+        default:
+            return BAD_FUNC_ARG;
+    }
+
+    /* Allocate an ECC key to hold private key. */
+    keyPtr = (byte*)XMALLOC(sizeof(ecc_key), ssl->heap,
+                                                      DYNAMIC_TYPE_PRIVATE_KEY);
+    if (keyPtr == NULL) {
+        WOLFSSL_MSG("EccTempKey Memory error");
+        return MEMORY_E;
+    }
+    eccKey = (ecc_key*)keyPtr;
+
+    /* Make an ECC key. */
+    ret = wc_ecc_init_ex(eccKey, ssl->heap, ssl->devId);
+    if (ret != 0)
+        goto end;
+    ret = wc_ecc_make_key_ex(ssl->rng, keySize, eccKey, curveId);
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* TODO: Make this function non-blocking */
+    if (ret == WC_PENDING_E) {
+        ret = wc_AsyncWait(ret, &eccKey->asyncDev, WC_ASYNC_FLAG_NONE);
+    }
+#endif
+    if (ret != 0)
+        goto end;
+
+    /* Allocate space for the public key. */
+    keyData = (byte*)XMALLOC(dataSize, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    if (keyData == NULL) {
+        WOLFSSL_MSG("Key data Memory error");
+        ret = MEMORY_E;
+        goto end;
+    }
+
+    /* Export public key. */
+    if (wc_ecc_export_x963(eccKey, keyData, &dataSize) != 0) {
+        ret = ECC_EXPORT_ERROR;
+        goto end;
+    }
+
+    kse->pubKey = keyData;
+    kse->pubKeyLen = dataSize;
+    kse->key = keyPtr;
+
+#ifdef WOLFSSL_DEBUG_TLS
+    WOLFSSL_MSG("Public ECC Key");
+    WOLFSSL_BUFFER(keyData, dataSize);
+#endif
+
+end:
+    if (ret != 0) {
+        /* Data owned by key share entry otherwise. */
+        if (keyPtr != NULL)
+            XFREE(keyPtr, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
+        if (keyData != NULL)
+            XFREE(keyData, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    }
+#else
+    (void)ssl;
+    (void)kse;
+
+    ret = NOT_COMPILED_IN;
+#endif /* HAVE_ECC */
+
+    return ret;
+}
+
+/* Generate a secret/key using the key share entry.
+ *
+ * ssl  The SSL/TLS object.
+ * kse  The key share entry holding peer data.
+ */
+static int TLSX_KeyShare_GenKey(WOLFSSL *ssl, KeyShareEntry *kse)
+{
+    /* Named FFHE groups have a bit set to identify them. */
+    if ((kse->group & NAMED_DH_MASK) == NAMED_DH_MASK)
+        return TLSX_KeyShare_GenDhKey(ssl, kse);
+    if (kse->group == WOLFSSL_ECC_X25519)
+        return TLSX_KeyShare_GenX25519Key(ssl, kse);
+    if (kse->group == WOLFSSL_ECC_X448)
+        return TLSX_KeyShare_GenX448Key(ssl, kse);
+    return TLSX_KeyShare_GenEccKey(ssl, kse);
+}
+
+/* Free the key share dynamic data.
+ *
+ * list  The linked list of key share entry objects.
+ * heap  The heap used for allocation.
+ */
+static void TLSX_KeyShare_FreeAll(KeyShareEntry* list, void* heap)
+{
+    KeyShareEntry* current;
+
+    while ((current = list) != NULL) {
+        list = current->next;
+        if ((current->group & NAMED_DH_MASK) == 0) {
+            if (current->group == WOLFSSL_ECC_X25519) {
+#ifdef HAVE_CURVE25519
+                wc_curve25519_free((curve25519_key*)current->key);
+#endif
+            }
+            else if (current->group == WOLFSSL_ECC_X448) {
+#ifdef HAVE_CURVE448
+                wc_curve448_free((curve448_key*)current->key);
+#endif
+            }
+            else {
+#ifdef HAVE_ECC
+                wc_ecc_free((ecc_key*)(current->key));
+#endif
+            }
+        }
+        if (current->key != NULL)
+            XFREE(current->key, heap, DYNAMIC_TYPE_PRIVATE_KEY);
+        XFREE(current->pubKey, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        XFREE(current->ke, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        XFREE(current, heap, DYNAMIC_TYPE_TLSX);
+    }
+
+    (void)heap;
+}
+
+/* Get the size of the encoded key share extension.
+ *
+ * list     The linked list of key share extensions.
+ * msgType  The type of the message this extension is being written into.
+ * returns the number of bytes of the encoded key share extension.
+ */
+static word16 TLSX_KeyShare_GetSize(KeyShareEntry* list, byte msgType)
+{
+    word16         len = 0;
+    byte           isRequest = (msgType == client_hello);
+    KeyShareEntry* current;
+
+    /* The named group the server wants to use. */
+    if (msgType == hello_retry_request)
+        return OPAQUE16_LEN;
+
+    /* List of key exchange groups. */
+    if (isRequest)
+        len += OPAQUE16_LEN;
+    while ((current = list) != NULL) {
+        list = current->next;
+
+        if (!isRequest && current->key == NULL)
+            continue;
+
+        len += KE_GROUP_LEN + OPAQUE16_LEN + current->pubKeyLen;
+    }
+
+    return len;
+}
+
+/* Writes the key share extension into the output buffer.
+ * Assumes that the the output buffer is big enough to hold data.
+ *
+ * list     The linked list of key share entries.
+ * output   The buffer to write into.
+ * msgType  The type of the message this extension is being written into.
+ * returns the number of bytes written into the buffer.
+ */
+static word16 TLSX_KeyShare_Write(KeyShareEntry* list, byte* output,
+                                  byte msgType)
+{
+    word16         i = 0;
+    byte           isRequest = (msgType == client_hello);
+    KeyShareEntry* current;
+
+    if (msgType == hello_retry_request) {
+        c16toa(list->group, output);
+        return OPAQUE16_LEN;
+    }
+
+    /* ClientHello has a list but ServerHello is only the chosen. */
+    if (isRequest)
+        i += OPAQUE16_LEN;
+
+    /* Write out all in the list. */
+    while ((current = list) != NULL) {
+        list = current->next;
+
+        if (!isRequest && current->key == NULL)
+            continue;
+
+        c16toa(current->group, &output[i]);
+        i += KE_GROUP_LEN;
+        c16toa((word16)(current->pubKeyLen), &output[i]);
+        i += OPAQUE16_LEN;
+        XMEMCPY(&output[i], current->pubKey, current->pubKeyLen);
+        i += (word16)current->pubKeyLen;
+    }
+    /* Write the length of the list if required. */
+    if (isRequest)
+        c16toa(i - OPAQUE16_LEN, output);
+
+    return i;
+}
+
+/* Process the DH key share extension on the client side.
+ *
+ * ssl            The SSL/TLS object.
+ * keyShareEntry  The key share entry object to use to calculate shared secret.
+ * returns 0 on success and other values indicate failure.
+ */
+static int TLSX_KeyShare_ProcessDh(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
+{
+#ifndef NO_DH
+    int             ret;
+    const DhParams* params;
+#ifdef WOLFSSL_SMALL_STACK
+    DhKey*          dhKey = NULL;
+#else
+    DhKey           dhKey[1];
+#endif
+
+    switch (keyShareEntry->group) {
+    #ifdef HAVE_FFDHE_2048
+        case WOLFSSL_FFDHE_2048:
+            params = wc_Dh_ffdhe2048_Get();
+            break;
+    #endif
+    #ifdef HAVE_FFDHE_3072
+        case WOLFSSL_FFDHE_3072:
+            params = wc_Dh_ffdhe3072_Get();
+            break;
+    #endif
+    #ifdef HAVE_FFDHE_4096
+        case WOLFSSL_FFDHE_4096:
+            params = wc_Dh_ffdhe4096_Get();
+            break;
+    #endif
+    #ifdef HAVE_FFDHE_6144
+        case WOLFSSL_FFDHE_6144:
+            params = wc_Dh_ffdhe6144_Get();
+            break;
+    #endif
+    #ifdef HAVE_FFDHE_8192
+        case WOLFSSL_FFDHE_8192:
+            params = wc_Dh_ffdhe8192_Get();
+            break;
+    #endif
+        default:
+            return PEER_KEY_ERROR;
+    }
+
+#ifdef WOLFSSL_DEBUG_TLS
+    WOLFSSL_MSG("Peer DH Key");
+    WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen);
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+    dhKey = (DhKey*)XMALLOC(sizeof(DhKey), ssl->heap, DYNAMIC_TYPE_DH);
+    if (dhKey == NULL)
+        return MEMORY_E;
+#endif
+
+    ret = wc_InitDhKey_ex(dhKey, ssl->heap, ssl->devId);
+    if (ret != 0) {
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH);
+    #endif
+        return ret;
+    }
+
+    /* Set key */
+    ret = wc_DhSetKey(dhKey, (byte*)params->p, params->p_len, (byte*)params->g,
+                                                                 params->g_len);
+    if (ret != 0) {
+        wc_FreeDhKey(dhKey);
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH);
+    #endif
+        return ret;
+    }
+
+    ret = wc_DhCheckPubKey(dhKey, keyShareEntry->ke, keyShareEntry->keLen);
+    if (ret != 0) {
+        wc_FreeDhKey(dhKey);
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH);
+    #endif
+        return PEER_KEY_ERROR;
+    }
+
+    /* Derive secret from private key and peer's public key. */
+    ret = wc_DhAgree(dhKey,
+        ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz,
+        (const byte*)keyShareEntry->key, keyShareEntry->keyLen,
+        keyShareEntry->ke, keyShareEntry->keLen);
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* TODO: Make this function non-blocking */
+    if (ret == WC_PENDING_E) {
+        ret = wc_AsyncWait(ret, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE);
+    }
+#endif
+    /* RFC 8446 Section 7.4.1:
+     *     ... left-padded with zeros up to the size of the prime. ...
+     */
+    if (params->p_len > ssl->arrays->preMasterSz) {
+        word32 diff = params->p_len - ssl->arrays->preMasterSz;
+        XMEMMOVE(ssl->arrays->preMasterSecret + diff,
+                        ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz);
+        XMEMSET(ssl->arrays->preMasterSecret, 0, diff);
+        ssl->arrays->preMasterSz = params->p_len;
+    }
+
+    ssl->options.dhKeySz = params->p_len;
+
+    wc_FreeDhKey(dhKey);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH);
+#endif
+    if (keyShareEntry->key != NULL) {
+        XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
+        keyShareEntry->key = NULL;
+    }
+    XFREE(keyShareEntry->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    keyShareEntry->pubKey = NULL;
+    XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    keyShareEntry->ke = NULL;
+
+    return ret;
+#else
+    (void)ssl;
+    (void)keyShareEntry;
+    return PEER_KEY_ERROR;
+#endif
+}
+
+/* Process the X25519 key share extension on the client side.
+ *
+ * ssl            The SSL/TLS object.
+ * keyShareEntry  The key share entry object to use to calculate shared secret.
+ * returns 0 on success and other values indicate failure.
+ */
+static int TLSX_KeyShare_ProcessX25519(WOLFSSL* ssl,
+                                       KeyShareEntry* keyShareEntry)
+{
+    int ret;
+
+#ifdef HAVE_CURVE25519
+    curve25519_key* key = (curve25519_key*)keyShareEntry->key;
+    curve25519_key* peerX25519Key;
+
+#ifdef HAVE_ECC
+    if (ssl->peerEccKey != NULL) {
+        wc_ecc_free(ssl->peerEccKey);
+        ssl->peerEccKey = NULL;
+    }
+#endif
+
+    peerX25519Key = (curve25519_key*)XMALLOC(sizeof(curve25519_key), ssl->heap,
+                                                             DYNAMIC_TYPE_TLSX);
+    if (peerX25519Key == NULL) {
+        WOLFSSL_MSG("PeerEccKey Memory error");
+        return MEMORY_ERROR;
+    }
+    ret = wc_curve25519_init(peerX25519Key);
+    if (ret != 0) {
+        XFREE(peerX25519Key, ssl->heap, DYNAMIC_TYPE_TLSX);
+        return ret;
+    }
+#ifdef WOLFSSL_DEBUG_TLS
+    WOLFSSL_MSG("Peer Curve25519 Key");
+    WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen);
+#endif
+
+    if (wc_curve25519_check_public(keyShareEntry->ke, keyShareEntry->keLen,
+                                                  EC25519_LITTLE_ENDIAN) != 0) {
+        ret = ECC_PEERKEY_ERROR;
+    }
+
+    if (ret == 0) {
+        if (wc_curve25519_import_public_ex(keyShareEntry->ke,
+                                            keyShareEntry->keLen, peerX25519Key,
+                                            EC25519_LITTLE_ENDIAN) != 0) {
+            ret = ECC_PEERKEY_ERROR;
+        }
+    }
+
+    if (ret == 0) {
+        ssl->ecdhCurveOID = ECC_X25519_OID;
+
+        ret = wc_curve25519_shared_secret_ex(key, peerX25519Key,
+                                                   ssl->arrays->preMasterSecret,
+                                                   &ssl->arrays->preMasterSz,
+                                                   EC25519_LITTLE_ENDIAN);
+    }
+
+    wc_curve25519_free(peerX25519Key);
+    XFREE(peerX25519Key, ssl->heap, DYNAMIC_TYPE_TLSX);
+    wc_curve25519_free((curve25519_key*)keyShareEntry->key);
+    if (keyShareEntry->key != NULL) {
+        XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
+        keyShareEntry->key = NULL;
+    }
+#else
+    (void)ssl;
+    (void)keyShareEntry;
+
+    ret = PEER_KEY_ERROR;
+#endif /* HAVE_CURVE25519 */
+
+    return ret;
+}
+
+/* Process the X448 key share extension on the client side.
+ *
+ * ssl            The SSL/TLS object.
+ * keyShareEntry  The key share entry object to use to calculate shared secret.
+ * returns 0 on success and other values indicate failure.
+ */
+static int TLSX_KeyShare_ProcessX448(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
+{
+    int ret;
+
+#ifdef HAVE_CURVE448
+    curve448_key* key = (curve448_key*)keyShareEntry->key;
+    curve448_key* peerX448Key;
+
+#ifdef HAVE_ECC
+    if (ssl->peerEccKey != NULL) {
+        wc_ecc_free(ssl->peerEccKey);
+        ssl->peerEccKey = NULL;
+    }
+#endif
+
+    peerX448Key = (curve448_key*)XMALLOC(sizeof(curve448_key), ssl->heap,
+                                                             DYNAMIC_TYPE_TLSX);
+    if (peerX448Key == NULL) {
+        WOLFSSL_MSG("PeerEccKey Memory error");
+        return MEMORY_ERROR;
+    }
+    ret = wc_curve448_init(peerX448Key);
+    if (ret != 0) {
+        XFREE(peerX448Key, ssl->heap, DYNAMIC_TYPE_TLSX);
+        return ret;
+    }
+#ifdef WOLFSSL_DEBUG_TLS
+    WOLFSSL_MSG("Peer Curve448 Key");
+    WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen);
+#endif
+
+    if (wc_curve448_check_public(keyShareEntry->ke, keyShareEntry->keLen,
+                                                    EC448_LITTLE_ENDIAN) != 0) {
+        ret = ECC_PEERKEY_ERROR;
+    }
+
+    if (ret == 0) {
+        if (wc_curve448_import_public_ex(keyShareEntry->ke,
+                                              keyShareEntry->keLen, peerX448Key,
+                                              EC448_LITTLE_ENDIAN) != 0) {
+            ret = ECC_PEERKEY_ERROR;
+        }
+    }
+
+    if (ret == 0) {
+        ssl->ecdhCurveOID = ECC_X448_OID;
+
+        ret = wc_curve448_shared_secret_ex(key, peerX448Key,
+                                                   ssl->arrays->preMasterSecret,
+                                                   &ssl->arrays->preMasterSz,
+                                                   EC448_LITTLE_ENDIAN);
+    }
+
+    wc_curve448_free(peerX448Key);
+    XFREE(peerX448Key, ssl->heap, DYNAMIC_TYPE_TLSX);
+    wc_curve448_free((curve448_key*)keyShareEntry->key);
+    if (keyShareEntry->key != NULL) {
+        XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
+        keyShareEntry->key = NULL;
+    }
+#else
+    (void)ssl;
+    (void)keyShareEntry;
+
+    ret = PEER_KEY_ERROR;
+#endif /* HAVE_CURVE448 */
+
+    return ret;
+}
+
+/* Process the ECC key share extension on the client side.
+ *
+ * ssl            The SSL/TLS object.
+ * keyShareEntry  The key share entry object to use to calculate shared secret.
+ * returns 0 on success and other values indicate failure.
+ */
+static int TLSX_KeyShare_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
+{
+    int ret;
+
+#ifdef HAVE_ECC
+    int curveId;
+    ecc_key* keyShareKey = (ecc_key*)keyShareEntry->key;
+
+    if (ssl->peerEccKey != NULL)
+        wc_ecc_free(ssl->peerEccKey);
+
+    ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), ssl->heap,
+                                        DYNAMIC_TYPE_ECC);
+    if (ssl->peerEccKey == NULL) {
+        WOLFSSL_MSG("PeerEccKey Memory error");
+        return MEMORY_ERROR;
+    }
+    ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, ssl->devId);
+    if (ret != 0)
+        return ret;
+
+    /* find supported curve */
+    switch (keyShareEntry->group) {
+    #if !defined(NO_ECC256)  || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+        case WOLFSSL_ECC_SECP256R1:
+            curveId = ECC_SECP256R1;
+            break;
+        #endif /* !NO_ECC_SECP */
+    #endif
+    #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+        case WOLFSSL_ECC_SECP384R1:
+            curveId = ECC_SECP384R1;
+            break;
+        #endif /* !NO_ECC_SECP */
+    #endif
+    #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+        case WOLFSSL_ECC_SECP521R1:
+            curveId = ECC_SECP521R1;
+            break;
+        #endif /* !NO_ECC_SECP */
+    #endif
+    #ifdef HAVE_X448
+        case WOLFSSL_ECC_X448:
+            curveId = ECC_X448;
+            break;
+    #endif
+        default:
+            /* unsupported curve */
+            return ECC_PEERKEY_ERROR;
+    }
+
+#ifdef WOLFSSL_DEBUG_TLS
+    WOLFSSL_MSG("Peer ECC Key");
+    WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen);
+#endif
+
+    /* Point is validated by import function. */
+    if (wc_ecc_import_x963_ex(keyShareEntry->ke, keyShareEntry->keLen,
+                              ssl->peerEccKey, curveId) != 0) {
+        return ECC_PEERKEY_ERROR;
+    }
+    ssl->ecdhCurveOID = ssl->peerEccKey->dp->oidSum;
+
+    do {
+    #if defined(WOLFSSL_ASYNC_CRYPT)
+        ret = wc_AsyncWait(ret, &keyShareKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+    #endif
+        if (ret >= 0)
+            ret = wc_ecc_shared_secret(keyShareKey, ssl->peerEccKey,
+                ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz);
+    } while (ret == WC_PENDING_E);
+
+#if 0
+    /* TODO: Switch to support async here and use: */
+    ret = EccSharedSecret(ssl, keyShareEntry->key, ssl->peerEccKey,
+        keyShareEntry->ke, &keyShareEntry->keLen,
+        ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz,
+        ssl->options.side
+    );
+#endif
+
+    wc_ecc_free(ssl->peerEccKey);
+    XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC);
+    ssl->peerEccKey = NULL;
+    wc_ecc_free((ecc_key*)(keyShareEntry->key));
+    if (keyShareEntry->key != NULL) {
+        XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
+        keyShareEntry->key = NULL;
+    }
+
+#else
+    (void)ssl;
+    (void)keyShareEntry;
+
+    ret = PEER_KEY_ERROR;
+#endif /* HAVE_ECC */
+
+    return ret;
+}
+
+/* Process the key share extension on the client side.
+ *
+ * ssl            The SSL/TLS object.
+ * keyShareEntry  The key share entry object to use to calculate shared secret.
+ * returns 0 on success and other values indicate failure.
+ */
+static int TLSX_KeyShare_Process(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
+{
+    int ret;
+
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+    ssl->session.namedGroup = (byte)keyShareEntry->group;
+#endif
+    /* Use Key Share Data from server. */
+    if (keyShareEntry->group & NAMED_DH_MASK)
+        ret = TLSX_KeyShare_ProcessDh(ssl, keyShareEntry);
+    else if (keyShareEntry->group == WOLFSSL_ECC_X25519)
+        ret = TLSX_KeyShare_ProcessX25519(ssl, keyShareEntry);
+    else if (keyShareEntry->group == WOLFSSL_ECC_X448)
+        ret = TLSX_KeyShare_ProcessX448(ssl, keyShareEntry);
+    else
+        ret = TLSX_KeyShare_ProcessEcc(ssl, keyShareEntry);
+
+#ifdef WOLFSSL_DEBUG_TLS
+    WOLFSSL_MSG("KE Secret");
+    WOLFSSL_BUFFER(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz);
+#endif
+
+    return ret;
+}
+
+/* Parse an entry of the KeyShare extension.
+ *
+ * ssl     The SSL/TLS object.
+ * input   The extension data.
+ * length  The length of the extension data.
+ * kse     The new key share entry object.
+ * returns a positive number to indicate amount of data parsed and a negative
+ * number on error.
+ */
+static int TLSX_KeyShareEntry_Parse(WOLFSSL* ssl, byte* input, word16 length,
+                                    KeyShareEntry **kse)
+{
+    int    ret;
+    word16 group;
+    word16 keLen;
+    int    offset = 0;
+    byte*  ke;
+
+    if (length < OPAQUE16_LEN + OPAQUE16_LEN)
+        return BUFFER_ERROR;
+    /* Named group */
+    ato16(&input[offset], &group);
+    offset += OPAQUE16_LEN;
+    /* Key exchange data - public key. */
+    ato16(&input[offset], &keLen);
+    offset += OPAQUE16_LEN;
+    if (keLen == 0)
+        return INVALID_PARAMETER;
+    if (keLen > length - offset)
+        return BUFFER_ERROR;
+
+    /* Store a copy in the key share object. */
+    ke = (byte*)XMALLOC(keLen, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    if (ke == NULL)
+        return MEMORY_E;
+    XMEMCPY(ke, &input[offset], keLen);
+
+    /* Populate a key share object in the extension. */
+    ret = TLSX_KeyShare_Use(ssl, group, keLen, ke, kse);
+    if (ret != 0) {
+        XFREE(ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        return ret;
+    }
+
+    /* Total length of the parsed data. */
+    return offset + keLen;
+}
+
+/* Searches the groups sent for the specified named group.
+ *
+ * ssl    SSL/TLS object.
+ * name   Group name to match.
+ * returns 1 when the extension has the group name and 0 otherwise.
+ */
+static int TLSX_KeyShare_Find(WOLFSSL* ssl, word16 group)
+{
+    TLSX*          extension;
+    KeyShareEntry* list;
+
+    extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
+    if (extension == NULL) {
+        extension = TLSX_Find(ssl->ctx->extensions, TLSX_KEY_SHARE);
+        if (extension == NULL)
+            return 0;
+    }
+
+    list = (KeyShareEntry*)extension->data;
+    while (list != NULL) {
+        if (list->group == group)
+            return 1;
+        list = list->next;
+    }
+
+    return 0;
+}
+
+
+/* Searches the supported groups extension for the specified named group.
+ *
+ * ssl   The SSL/TLS object.
+ * name  The group name to match.
+ * returns 1 when the extension has the group name and 0 otherwise.
+ */
+static int TLSX_SupportedGroups_Find(WOLFSSL* ssl, word16 name)
+{
+#ifdef HAVE_SUPPORTED_CURVES
+    TLSX*          extension;
+    SupportedCurve* curve = NULL;
+
+    if ((extension = TLSX_Find(ssl->extensions,
+                                              TLSX_SUPPORTED_GROUPS)) == NULL) {
+        if ((extension = TLSX_Find(ssl->ctx->extensions,
+                                              TLSX_SUPPORTED_GROUPS)) == NULL) {
+            return 0;
+        }
+    }
+
+    for (curve = (SupportedCurve*)extension->data; curve; curve = curve->next) {
+        if (curve->name == name)
+            return 1;
+    }
+#endif
+
+    (void)ssl;
+    (void)name;
+
+    return 0;
+}
+
+
+/* Parse the KeyShare extension.
+ * Different formats in different messages.
+ *
+ * ssl      The SSL/TLS object.
+ * input    The extension data.
+ * length   The length of the extension data.
+ * msgType  The type of the message this extension is being parsed from.
+ * returns 0 on success and other values indicate failure.
+ */
+static int TLSX_KeyShare_Parse(WOLFSSL* ssl, byte* input, word16 length,
+                               byte msgType)
+{
+    int ret;
+    KeyShareEntry *keyShareEntry = NULL;
+    word16 group;
+
+    if (msgType == client_hello) {
+        int    offset = 0;
+        word16 len;
+        TLSX*  extension;
+
+        /* Add a KeyShare extension if it doesn't exist. */
+        extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
+        if (extension == NULL) {
+            /* Push new KeyShare extension. */
+            ret = TLSX_Push(&ssl->extensions, TLSX_KEY_SHARE, NULL, ssl->heap);
+            if (ret != 0)
+                return ret;
+        }
+
+        if (length < OPAQUE16_LEN)
+            return BUFFER_ERROR;
+
+        /* ClientHello contains zero or more key share entries. */
+        ato16(input, &len);
+        if (len != length - OPAQUE16_LEN)
+            return BUFFER_ERROR;
+        offset += OPAQUE16_LEN;
+
+        while (offset < (int)length) {
+            ret = TLSX_KeyShareEntry_Parse(ssl, &input[offset], length - offset,
+                                                                &keyShareEntry);
+            if (ret < 0)
+                return ret;
+
+            offset += ret;
+        }
+
+        ret = 0;
+    }
+    else if (msgType == server_hello) {
+        int len;
+
+        if (length < OPAQUE16_LEN)
+            return BUFFER_ERROR;
+
+        /* The data is the named group the server wants to use. */
+        ato16(input, &group);
+
+        /* Check the selected group was supported by ClientHello extensions. */
+        if (!TLSX_SupportedGroups_Find(ssl, group))
+            return BAD_KEY_SHARE_DATA;
+
+        /* Check if the group was sent. */
+        if (!TLSX_KeyShare_Find(ssl, group))
+            return BAD_KEY_SHARE_DATA;
+
+        /* ServerHello contains one key share entry. */
+        len = TLSX_KeyShareEntry_Parse(ssl, input, length, &keyShareEntry);
+        if (len != (int)length)
+            return BUFFER_ERROR;
+
+        /* Not in list sent if there isn't a private key. */
+        if (keyShareEntry == NULL || keyShareEntry->key == NULL)
+            return BAD_KEY_SHARE_DATA;
+
+        /* Process the entry to calculate the secret. */
+        ret = TLSX_KeyShare_Process(ssl, keyShareEntry);
+        if (ret == 0)
+            ssl->session.namedGroup = ssl->namedGroup = group;
+    }
+    else if (msgType == hello_retry_request) {
+        if (length != OPAQUE16_LEN)
+            return BUFFER_ERROR;
+
+        /* The data is the named group the server wants to use. */
+        ato16(input, &group);
+
+        /* Check the selected group was supported by ClientHello extensions. */
+        if (!TLSX_SupportedGroups_Find(ssl, group))
+            return BAD_KEY_SHARE_DATA;
+
+        /* Check if the group was sent. */
+        if (TLSX_KeyShare_Find(ssl, group))
+            return BAD_KEY_SHARE_DATA;
+
+        /* Clear out unusable key shares. */
+        ret = TLSX_KeyShare_Empty(ssl);
+        if (ret != 0)
+            return ret;
+
+        /* Try to use the server's group. */
+        ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL);
+    }
+    else {
+        /* Not a message type that is allowed to have this extension. */
+        return SANITY_MSG_E;
+    }
+
+    return ret;
+}
+
+/* Create a new key share entry and put it into the list.
+ *
+ * list           The linked list of key share entries.
+ * group          The named group.
+ * heap           The memory to allocate with.
+ * keyShareEntry  The new key share entry object.
+ * returns 0 on success and other values indicate failure.
+ */
+static int TLSX_KeyShare_New(KeyShareEntry** list, int group, void *heap,
+                             KeyShareEntry** keyShareEntry)
+{
+    KeyShareEntry* kse;
+    KeyShareEntry** next;
+
+    kse = (KeyShareEntry*)XMALLOC(sizeof(KeyShareEntry), heap,
+                                  DYNAMIC_TYPE_TLSX);
+    if (kse == NULL)
+        return MEMORY_E;
+
+    XMEMSET(kse, 0, sizeof(*kse));
+    kse->group = (word16)group;
+
+    /* Add it to the back and maintain the links. */
+    while (*list != NULL) {
+        /* Assign to temporary to work around compiler bug found by customer. */
+        next = &((*list)->next);
+        list = next;
+    }
+    *list = kse;
+    *keyShareEntry = kse;
+
+    (void)heap;
+
+    return 0;
+}
+
+/* Use the data to create a new key share object in the extensions.
+ *
+ * ssl    The SSL/TLS object.
+ * group  The named group.
+ * len    The length of the public key data.
+ * data   The public key data.
+ * kse    The new key share entry object.
+ * returns 0 on success and other values indicate failure.
+ */
+int TLSX_KeyShare_Use(WOLFSSL* ssl, word16 group, word16 len, byte* data,
+                      KeyShareEntry **kse)
+{
+    int            ret = 0;
+    TLSX*          extension;
+    KeyShareEntry* keyShareEntry = NULL;
+
+    /* Find the KeyShare extension if it exists. */
+    extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
+    if (extension == NULL) {
+        /* Push new KeyShare extension. */
+        ret = TLSX_Push(&ssl->extensions, TLSX_KEY_SHARE, NULL, ssl->heap);
+        if (ret != 0)
+            return ret;
+
+        extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
+        if (extension == NULL)
+            return MEMORY_E;
+    }
+    extension->resp = 0;
+
+    /* Try to find the key share entry with this group. */
+    keyShareEntry = (KeyShareEntry*)extension->data;
+    while (keyShareEntry != NULL) {
+        if (keyShareEntry->group == group)
+            break;
+        keyShareEntry = keyShareEntry->next;
+    }
+
+    /* Create a new key share entry if not found. */
+    if (keyShareEntry == NULL) {
+        ret = TLSX_KeyShare_New((KeyShareEntry**)&extension->data, group,
+                                ssl->heap, &keyShareEntry);
+        if (ret != 0)
+            return ret;
+    }
+
+    if (data != NULL) {
+        if (keyShareEntry->ke != NULL) {
+            XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        }
+        keyShareEntry->ke = data;
+        keyShareEntry->keLen = len;
+    }
+    else {
+        /* Generate a key pair. */
+        ret = TLSX_KeyShare_GenKey(ssl, keyShareEntry);
+        if (ret != 0)
+            return ret;
+    }
+
+    if (kse != NULL)
+        *kse = keyShareEntry;
+
+    return 0;
+}
+
+/* Set an empty Key Share extension.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 0 on success and other values indicate failure.
+ */
+int TLSX_KeyShare_Empty(WOLFSSL* ssl)
+{
+    int   ret = 0;
+    TLSX* extension;
+
+    /* Find the KeyShare extension if it exists. */
+    extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
+    if (extension == NULL) {
+        /* Push new KeyShare extension. */
+        ret = TLSX_Push(&ssl->extensions, TLSX_KEY_SHARE, NULL, ssl->heap);
+    }
+    else if (extension->data != NULL) {
+        TLSX_KeyShare_FreeAll((KeyShareEntry*)extension->data, ssl->heap);
+        extension->data = NULL;
+    }
+
+    return ret;
+}
+
+/* Returns whether this group is supported.
+ *
+ * namedGroup  The named group to check.
+ * returns 1 when supported or 0 otherwise.
+ */
+static int TLSX_KeyShare_IsSupported(int namedGroup)
+{
+    switch (namedGroup) {
+    #ifdef HAVE_FFDHE_2048
+        case WOLFSSL_FFDHE_2048:
+            break;
+    #endif
+    #ifdef HAVE_FFDHE_3072
+        case WOLFSSL_FFDHE_3072:
+            break;
+    #endif
+    #ifdef HAVE_FFDHE_4096
+        case WOLFSSL_FFDHE_4096:
+            break;
+    #endif
+    #ifdef HAVE_FFDHE_6144
+        case WOLFSSL_FFDHE_6144:
+            break;
+    #endif
+    #ifdef HAVE_FFDHE_8192
+        case WOLFSSL_FFDHE_8192:
+            break;
+    #endif
+    #if !defined(NO_ECC256)  || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+        case WOLFSSL_ECC_SECP256R1:
+            break;
+        #endif /* !NO_ECC_SECP */
+    #endif
+    #ifdef HAVE_CURVE25519
+        case WOLFSSL_ECC_X25519:
+            break;
+    #endif
+    #ifdef HAVE_CURVE448
+        case WOLFSSL_ECC_X448:
+            break;
+    #endif
+    #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+        case WOLFSSL_ECC_SECP384R1:
+            break;
+        #endif /* !NO_ECC_SECP */
+    #endif
+    #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+        case WOLFSSL_ECC_SECP521R1:
+            break;
+        #endif /* !NO_ECC_SECP */
+    #endif
+        default:
+            return 0;
+    }
+
+    return 1;
+}
+
+/* Examines the application specified group ranking and returns the rank of the
+ * group.
+ * If no group ranking set then all groups are rank 0 (highest).
+ *
+ * ssl    The SSL/TLS object.
+ * group  The group to check ranking for.
+ * returns ranking from 0 to MAX_GROUP_COUNT-1 or -1 when group not in list.
+ */
+static int TLSX_KeyShare_GroupRank(WOLFSSL* ssl, int group)
+{
+    byte i;
+
+    if (ssl->numGroups == 0) {
+#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES)
+    #if !defined(NO_ECC256)  || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            ssl->group[ssl->numGroups++] = WOLFSSL_ECC_SECP256R1;
+        #endif
+    #endif
+#endif
+    #ifndef HAVE_FIPS
+        #if defined(HAVE_CURVE25519)
+            ssl->group[ssl->numGroups++] = WOLFSSL_ECC_X25519;
+        #endif
+    #endif
+    #ifndef HAVE_FIPS
+        #if defined(HAVE_CURVE448)
+            ssl->group[ssl->numGroups++] = WOLFSSL_ECC_X448;
+        #endif
+    #endif
+#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES)
+    #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            ssl->group[ssl->numGroups++] = WOLFSSL_ECC_SECP384R1;
+        #endif
+    #endif
+    #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            ssl->group[ssl->numGroups++] = WOLFSSL_ECC_SECP521R1;
+        #endif
+    #endif
+#endif
+            /* Add FFDHE supported groups. */
+        #ifdef HAVE_FFDHE_2048
+            ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_2048;
+        #endif
+        #ifdef HAVE_FFDHE_3072
+            ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_3072;
+        #endif
+        #ifdef HAVE_FFDHE_4096
+            ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_4096;
+        #endif
+        #ifdef HAVE_FFDHE_6144
+            ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_6144;
+        #endif
+        #ifdef HAVE_FFDHE_8192
+            ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_8192;
+        #endif
+    }
+
+    for (i = 0; i < ssl->numGroups; i++)
+        if (ssl->group[i] == (word16)group)
+            return i;
+
+    return -1;
+}
+
+/* Set a key share that is supported by the client into extensions.
+ *
+ * ssl  The SSL/TLS object.
+ * returns BAD_KEY_SHARE_DATA if no supported group has a key share,
+ * 0 if a supported group has a key share and other values indicate an error.
+ */
+static int TLSX_KeyShare_SetSupported(WOLFSSL* ssl)
+{
+    int             ret;
+#ifdef HAVE_SUPPORTED_CURVES
+    TLSX*           extension;
+    SupportedCurve* curve = NULL;
+    SupportedCurve* preferredCurve = NULL;
+    int             preferredRank = WOLFSSL_MAX_GROUP_COUNT;
+    int             rank;
+
+    extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS);
+    if (extension != NULL)
+        curve = (SupportedCurve*)extension->data;
+    /* Use server's preference order. */
+    for (; curve != NULL; curve = curve->next) {
+        if (!TLSX_KeyShare_IsSupported(curve->name))
+            continue;
+
+        rank = TLSX_KeyShare_GroupRank(ssl, curve->name);
+        if (rank == -1)
+            continue;
+        if (rank < preferredRank) {
+            preferredCurve = curve;
+            preferredRank = rank;
+        }
+    }
+    curve = preferredCurve;
+
+    if (curve == NULL)
+        return BAD_KEY_SHARE_DATA;
+
+    /* Delete the old key share data list. */
+    extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
+    if (extension != NULL) {
+        TLSX_KeyShare_FreeAll((KeyShareEntry*)extension->data, ssl->heap);
+        extension->data = NULL;
+    }
+
+    /* Add in the chosen group. */
+    ret = TLSX_KeyShare_Use(ssl, curve->name, 0, NULL, NULL);
+    if (ret != 0)
+        return ret;
+
+    /* Set extension to be in response. */
+    extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
+    extension->resp = 1;
+#else
+
+    (void)ssl;
+    ret = NOT_COMPILED_IN;
+#endif
+
+    return ret;
+}
+
+/* Ensure there is a key pair that can be used for key exchange.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 0 on success and other values indicate failure.
+ */
+int TLSX_KeyShare_Establish(WOLFSSL *ssl)
+{
+    int            ret;
+    TLSX*          extension;
+    KeyShareEntry* clientKSE = NULL;
+    KeyShareEntry* serverKSE;
+    KeyShareEntry* list = NULL;
+    KeyShareEntry* preferredKSE = NULL;
+    int preferredRank = WOLFSSL_MAX_GROUP_COUNT;
+    int rank;
+
+    /* Find the KeyShare extension if it exists. */
+    extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
+    if (extension != NULL)
+        list = (KeyShareEntry*)extension->data;
+
+    if (extension && extension->resp == 1)
+        return 0;
+
+    /* Use server's preference order. */
+    for (clientKSE = list; clientKSE != NULL; clientKSE = clientKSE->next) {
+        if (clientKSE->ke == NULL)
+            continue;
+
+        /* Check consistency now - extensions in any order. */
+        if (!TLSX_SupportedGroups_Find(ssl, clientKSE->group))
+            return BAD_KEY_SHARE_DATA;
+
+    #ifdef OPENSSL_EXTRA
+        if ((clientKSE->group & NAMED_DH_MASK) == 0) {
+            /* Check if server supports group. */
+            if (ssl->ctx->disabledCurves & (1 << clientKSE->group))
+                continue;
+        }
+    #endif
+        if (!TLSX_KeyShare_IsSupported(clientKSE->group))
+            continue;
+
+        rank = TLSX_KeyShare_GroupRank(ssl, clientKSE->group);
+        if (rank == -1)
+            continue;
+        if (rank < preferredRank) {
+            preferredKSE = clientKSE;
+            preferredRank = rank;
+        }
+    }
+    clientKSE = preferredKSE;
+
+    /* No supported group found - send HelloRetryRequest. */
+    if (clientKSE == NULL) {
+        ret = TLSX_KeyShare_SetSupported(ssl);
+        /* Return KEY_SHARE_ERROR to indicate HelloRetryRequest required. */
+        if (ret == 0)
+            return KEY_SHARE_ERROR;
+        return ret;
+    }
+
+    list = NULL;
+    /* Generate a new key pair. */
+    ret = TLSX_KeyShare_New(&list, clientKSE->group, ssl->heap, &serverKSE);
+    if (ret != 0)
+        return ret;
+
+    if (clientKSE->key == NULL) {
+        ret = TLSX_KeyShare_GenKey(ssl, serverKSE);
+        if (ret != 0)
+            return ret;
+    }
+    else {
+        serverKSE->key = clientKSE->key;
+        serverKSE->keyLen = clientKSE->keyLen;
+        serverKSE->pubKey = clientKSE->pubKey;
+        serverKSE->pubKeyLen = clientKSE->pubKeyLen;
+        clientKSE->key = NULL;
+        clientKSE->pubKey = NULL;
+    }
+    serverKSE->ke = clientKSE->ke;
+    serverKSE->keLen = clientKSE->keLen;
+    clientKSE->ke = NULL;
+    clientKSE->keLen = 0;
+
+    TLSX_KeyShare_FreeAll((KeyShareEntry*)extension->data, ssl->heap);
+    extension->data = (void *)serverKSE;
+
+    extension->resp = 1;
+
+    return 0;
+}
+
+/* Derive the shared secret of the key exchange.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 0 on success and other values indicate failure.
+ */
+int TLSX_KeyShare_DeriveSecret(WOLFSSL *ssl)
+{
+    int            ret;
+    TLSX*          extension;
+    KeyShareEntry* list = NULL;
+
+    /* Find the KeyShare extension if it exists. */
+    extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
+    if (extension != NULL)
+        list = (KeyShareEntry*)extension->data;
+
+    if (list == NULL)
+        return KEY_SHARE_ERROR;
+
+    /* Calculate secret. */
+    ret = TLSX_KeyShare_Process(ssl, list);
+    if (ret != 0)
+        return ret;
+
+    return ret;
+}
+
+#define KS_FREE_ALL  TLSX_KeyShare_FreeAll
+#define KS_GET_SIZE  TLSX_KeyShare_GetSize
+#define KS_WRITE     TLSX_KeyShare_Write
+#define KS_PARSE     TLSX_KeyShare_Parse
+
+#else
+
+#define KS_FREE_ALL(a, b)
+#define KS_GET_SIZE(a, b)    0
+#define KS_WRITE(a, b, c)    0
+#define KS_PARSE(a, b, c, d) 0
+
+#endif /* WOLFSSL_TLS13 */
+
+/******************************************************************************/
+/* Pre-Shared Key                                                             */
+/******************************************************************************/
+
+#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK))
+/* Free the pre-shared key dynamic data.
+ *
+ * list  The linked list of key share entry objects.
+ * heap  The heap used for allocation.
+ */
+static void TLSX_PreSharedKey_FreeAll(PreSharedKey* list, void* heap)
+{
+    PreSharedKey* current;
+
+    while ((current = list) != NULL) {
+        list = current->next;
+        XFREE(current->identity, heap, DYNAMIC_TYPE_TLSX);
+        XFREE(current, heap, DYNAMIC_TYPE_TLSX);
+    }
+
+    (void)heap;
+}
+
+/* Get the size of the encoded pre shared key extension.
+ *
+ * list     The linked list of pre-shared key extensions.
+ * msgType  The type of the message this extension is being written into.
+ * returns the number of bytes of the encoded pre-shared key extension or
+ * SANITY_MSG_E to indicate invalid message type.
+ */
+static int TLSX_PreSharedKey_GetSize(PreSharedKey* list, byte msgType,
+                                     word16* pSz)
+{
+    if (msgType == client_hello) {
+        /* Length of identities + Length of binders. */
+        word16 len = OPAQUE16_LEN + OPAQUE16_LEN;
+        while (list != NULL) {
+            /* Each entry has: identity, ticket age and binder. */
+            len += OPAQUE16_LEN + list->identityLen + OPAQUE32_LEN +
+                   OPAQUE8_LEN + list->binderLen;
+            list = list->next;
+        }
+        *pSz += len;
+        return 0;
+    }
+
+    if (msgType == server_hello) {
+        *pSz += OPAQUE16_LEN;
+        return 0;
+    }
+
+    return SANITY_MSG_E;
+}
+
+/* The number of bytes to be written for the binders.
+ *
+ * list     The linked list of pre-shared key extensions.
+ * msgType  The type of the message this extension is being written into.
+ * returns the number of bytes of the encoded pre-shared key extension or
+ * SANITY_MSG_E to indicate invalid message type.
+ */
+int TLSX_PreSharedKey_GetSizeBinders(PreSharedKey* list, byte msgType,
+                                     word16* pSz)
+{
+    word16 len;
+
+    if (msgType != client_hello)
+        return SANITY_MSG_E;
+
+    /* Length of all binders. */
+    len = OPAQUE16_LEN;
+    while (list != NULL) {
+        len += OPAQUE8_LEN + list->binderLen;
+        list = list->next;
+    }
+
+    *pSz = len;
+    return 0;
+}
+
+/* Writes the pre-shared key extension into the output buffer - binders only.
+ * Assumes that the the output buffer is big enough to hold data.
+ *
+ * list     The linked list of key share entries.
+ * output   The buffer to write into.
+ * msgType  The type of the message this extension is being written into.
+ * returns the number of bytes written into the buffer.
+ */
+int TLSX_PreSharedKey_WriteBinders(PreSharedKey* list, byte* output,
+                                   byte msgType, word16* pSz)
+{
+    PreSharedKey* current = list;
+    word16 idx = 0;
+    word16 lenIdx;
+    word16 len;
+
+    if (msgType != client_hello)
+        return SANITY_MSG_E;
+
+    /* Skip length of all binders. */
+    lenIdx = idx;
+    idx += OPAQUE16_LEN;
+    while (current != NULL) {
+        /* Binder data length. */
+        output[idx++] = current->binderLen;
+        /* Binder data. */
+        XMEMCPY(output + idx, current->binder, current->binderLen);
+        idx += current->binderLen;
+
+        current = current->next;
+    }
+    /* Length of the binders. */
+    len = idx - lenIdx - OPAQUE16_LEN;
+    c16toa(len, output + lenIdx);
+
+    *pSz = idx;
+    return 0;
+}
+
+
+/* Writes the pre-shared key extension into the output buffer.
+ * Assumes that the the output buffer is big enough to hold data.
+ *
+ * list     The linked list of key share entries.
+ * output   The buffer to write into.
+ * msgType  The type of the message this extension is being written into.
+ * returns the number of bytes written into the buffer.
+ */
+static int TLSX_PreSharedKey_Write(PreSharedKey* list, byte* output,
+                                   byte msgType, word16* pSz)
+{
+    if (msgType == client_hello) {
+        PreSharedKey* current = list;
+        word16 idx = 0;
+        word16 lenIdx;
+        word16 len;
+        int ret;
+
+        /* Write identites only. Binders after HMACing over this. */
+        lenIdx = idx;
+        idx += OPAQUE16_LEN;
+        while (current != NULL) {
+            /* Identity length */
+            c16toa(current->identityLen, output + idx);
+            idx += OPAQUE16_LEN;
+            /* Identity data */
+            XMEMCPY(output + idx, current->identity, current->identityLen);
+            idx += current->identityLen;
+
+            /* Obfuscated ticket age. */
+            c32toa(current->ticketAge, output + idx);
+            idx += OPAQUE32_LEN;
+
+            current = current->next;
+        }
+        /* Length of the identites. */
+        len = idx - lenIdx - OPAQUE16_LEN;
+        c16toa(len, output + lenIdx);
+
+        /* Don't include binders here.
+         * The binders are based on the hash of all the ClientHello data up to
+         * and include the identities written above.
+         */
+        ret = TLSX_PreSharedKey_GetSizeBinders(list, msgType, &len);
+        if (ret < 0)
+            return ret;
+        *pSz += idx + len;
+    }
+    else if (msgType == server_hello) {
+        word16 i;
+
+        /* Find the index of the chosen identity. */
+        for (i=0; list != NULL && !list->chosen; i++)
+            list = list->next;
+        if (list == NULL)
+            return BUILD_MSG_ERROR;
+
+        /* The index of the identity chosen by the server from the list supplied
+         * by the client.
+         */
+        c16toa(i, output);
+        *pSz += OPAQUE16_LEN;
+    }
+    else
+        return SANITY_MSG_E;
+
+    return 0;
+}
+
+/* Parse the pre-shared key extension.
+ * Different formats in different messages.
+ *
+ * ssl      The SSL/TLS object.
+ * input    The extension data.
+ * length   The length of the extension data.
+ * msgType  The type of the message this extension is being parsed from.
+ * returns 0 on success and other values indicate failure.
+ */
+static int TLSX_PreSharedKey_Parse(WOLFSSL* ssl, byte* input, word16 length,
+                                   byte msgType)
+{
+    TLSX*         extension;
+    PreSharedKey* list;
+
+    if (msgType == client_hello) {
+        int    ret;
+        word16 len;
+        word16 idx = 0;
+
+        TLSX_Remove(&ssl->extensions, TLSX_PRE_SHARED_KEY, ssl->heap);
+
+        /* Length of identities and of binders. */
+        if (length - idx < OPAQUE16_LEN + OPAQUE16_LEN)
+            return BUFFER_E;
+
+        /* Length of identities. */
+        ato16(input + idx, &len);
+        idx += OPAQUE16_LEN;
+        if (len < MIN_PSK_ID_LEN || length - idx < len)
+            return BUFFER_E;
+
+        /* Create a pre-shared key object for each identity. */
+        while (len > 0) {
+            byte*  identity;
+            word16 identityLen;
+            word32 age;
+
+            if (len < OPAQUE16_LEN)
+                return BUFFER_E;
+
+            /* Length of identity. */
+            ato16(input + idx, &identityLen);
+            idx += OPAQUE16_LEN;
+            if (len < OPAQUE16_LEN + identityLen + OPAQUE32_LEN ||
+                    identityLen > MAX_PSK_ID_LEN)
+                return BUFFER_E;
+            /* Cache identity pointer. */
+            identity = input + idx;
+            idx += identityLen;
+            /* Ticket age. */
+            ato32(input + idx, &age);
+            idx += OPAQUE32_LEN;
+
+            ret = TLSX_PreSharedKey_Use(ssl, identity, identityLen, age, no_mac,
+                                        0, 0, 1, NULL);
+            if (ret != 0)
+                return ret;
+
+            /* Done with this identity. */
+            len -= OPAQUE16_LEN + identityLen + OPAQUE32_LEN;
+        }
+
+        /* Find the list of identities sent to server. */
+        extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY);
+        if (extension == NULL)
+            return PSK_KEY_ERROR;
+        list = (PreSharedKey*)extension->data;
+
+        /* Length of binders. */
+        if (idx + OPAQUE16_LEN > length)
+            return BUFFER_E;
+        ato16(input + idx, &len);
+        idx += OPAQUE16_LEN;
+        if (len < MIN_PSK_BINDERS_LEN || length - idx < len)
+            return BUFFER_E;
+
+        /* Set binder for each identity. */
+        while (list != NULL && len > 0) {
+            /* Length of binder */
+            list->binderLen = input[idx++];
+            if (list->binderLen < WC_SHA256_DIGEST_SIZE ||
+                    list->binderLen > WC_MAX_DIGEST_SIZE)
+                return BUFFER_E;
+            if (len < OPAQUE8_LEN + list->binderLen)
+                return BUFFER_E;
+
+            /* Copy binder into static buffer. */
+            XMEMCPY(list->binder, input + idx, list->binderLen);
+            idx += list->binderLen;
+
+            /* Done with binder entry. */
+            len -= OPAQUE8_LEN + list->binderLen;
+
+            /* Next identity. */
+            list = list->next;
+        }
+        if (list != NULL || len != 0)
+            return BUFFER_E;
+
+        return 0;
+    }
+
+    if (msgType == server_hello) {
+        word16 idx;
+
+        /* Index of identity chosen by server. */
+        if (length != OPAQUE16_LEN)
+            return BUFFER_E;
+        ato16(input, &idx);
+
+    #ifdef WOLFSSL_EARLY_DATA
+        ssl->options.pskIdIndex = idx + 1;
+    #endif
+
+        /* Find the list of identities sent to server. */
+        extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY);
+        if (extension == NULL)
+            return PSK_KEY_ERROR;
+        list = (PreSharedKey*)extension->data;
+
+        /* Mark the identity as chosen. */
+        for (; list != NULL && idx > 0; idx--)
+            list = list->next;
+        if (list == NULL)
+            return PSK_KEY_ERROR;
+        list->chosen = 1;
+
+    #ifdef HAVE_SESSION_TICKET
+        if (list->resumption) {
+           /* Check that the session's details are the same as the server's. */
+           if (ssl->options.cipherSuite0  != ssl->session.cipherSuite0       ||
+               ssl->options.cipherSuite   != ssl->session.cipherSuite        ||
+               ssl->session.version.major != ssl->ctx->method->version.major ||
+               ssl->session.version.minor != ssl->ctx->method->version.minor) {
+               return PSK_KEY_ERROR;
+           }
+        }
+    #endif
+
+        return 0;
+    }
+
+    return SANITY_MSG_E;
+}
+
+/* Create a new pre-shared key and put it into the list.
+ *
+ * list          The linked list of pre-shared key.
+ * identity      The identity.
+ * len           The length of the identity data.
+ * heap          The memory to allocate with.
+ * preSharedKey  The new pre-shared key object.
+ * returns 0 on success and other values indicate failure.
+ */
+static int TLSX_PreSharedKey_New(PreSharedKey** list, byte* identity,
+                                 word16 len, void *heap,
+                                 PreSharedKey** preSharedKey)
+{
+    PreSharedKey* psk;
+    PreSharedKey** next;
+
+    psk = (PreSharedKey*)XMALLOC(sizeof(PreSharedKey), heap, DYNAMIC_TYPE_TLSX);
+    if (psk == NULL)
+        return MEMORY_E;
+    XMEMSET(psk, 0, sizeof(*psk));
+
+    /* Make a copy of the identity data. */
+    psk->identity = (byte*)XMALLOC(len, heap, DYNAMIC_TYPE_TLSX);
+    if (psk->identity == NULL) {
+        XFREE(psk, heap, DYNAMIC_TYPE_TLSX);
+        return MEMORY_E;
+    }
+    XMEMCPY(psk->identity, identity, len);
+    psk->identityLen = len;
+
+    /* Add it to the end and maintain the links. */
+    while (*list != NULL) {
+        /* Assign to temporary to work around compiler bug found by customer. */
+        next = &((*list)->next);
+        list = next;
+    }
+    *list = psk;
+    *preSharedKey = psk;
+
+    (void)heap;
+
+    return 0;
+}
+
+static WC_INLINE byte GetHmacLength(int hmac)
+{
+    switch (hmac) {
+    #ifndef NO_SHA256
+        case sha256_mac:
+            return WC_SHA256_DIGEST_SIZE;
+    #endif
+    #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            return WC_SHA384_DIGEST_SIZE;
+    #endif
+    #ifdef WOLFSSL_SHA512
+        case sha512_mac:
+            return WC_SHA512_DIGEST_SIZE;
+    #endif
+    }
+    return 0;
+}
+
+/* Use the data to create a new pre-shared key object in the extensions.
+ *
+ * ssl           The SSL/TLS object.
+ * identity      The identity.
+ * len           The length of the identity data.
+ * age           The age of the identity.
+ * hmac          The HMAC algorithm.
+ * ciphersuite0  The first byte of the ciphersuite to use.
+ * ciphersuite   The second byte of the ciphersuite to use.
+ * resumption    The PSK is for resumption of a session.
+ * preSharedKey  The new pre-shared key object.
+ * returns 0 on success and other values indicate failure.
+ */
+int TLSX_PreSharedKey_Use(WOLFSSL* ssl, byte* identity, word16 len, word32 age,
+                          byte hmac, byte cipherSuite0,
+                          byte cipherSuite, byte resumption,
+                          PreSharedKey **preSharedKey)
+{
+    int           ret = 0;
+    TLSX*         extension;
+    PreSharedKey* psk = NULL;
+
+    /* Find the pre-shared key extension if it exists. */
+    extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY);
+    if (extension == NULL) {
+        /* Push new pre-shared key extension. */
+        ret = TLSX_Push(&ssl->extensions, TLSX_PRE_SHARED_KEY, NULL, ssl->heap);
+        if (ret != 0)
+            return ret;
+
+        extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY);
+        if (extension == NULL)
+            return MEMORY_E;
+    }
+
+    /* Try to find the pre-shared key with this identity. */
+    psk = (PreSharedKey*)extension->data;
+    while (psk != NULL) {
+        if ((psk->identityLen == len) &&
+               (XMEMCMP(psk->identity, identity, len) == 0)) {
+            break;
+        }
+        psk = psk->next;
+    }
+
+    /* Create a new pre-shared key object if not found. */
+    if (psk == NULL) {
+        ret = TLSX_PreSharedKey_New((PreSharedKey**)&extension->data, identity,
+                                    len, ssl->heap, &psk);
+        if (ret != 0)
+            return ret;
+    }
+
+    /* Update/set age and HMAC algorithm. */
+    psk->ticketAge    = age;
+    psk->hmac         = hmac;
+    psk->cipherSuite0 = cipherSuite0;
+    psk->cipherSuite  = cipherSuite;
+    psk->resumption   = resumption;
+    psk->binderLen    = GetHmacLength(psk->hmac);
+
+    if (preSharedKey != NULL)
+        *preSharedKey = psk;
+
+    return 0;
+}
+
+#define PSK_FREE_ALL  TLSX_PreSharedKey_FreeAll
+#define PSK_GET_SIZE  TLSX_PreSharedKey_GetSize
+#define PSK_WRITE     TLSX_PreSharedKey_Write
+#define PSK_PARSE     TLSX_PreSharedKey_Parse
+
+#else
+
+#define PSK_FREE_ALL(a, b)
+#define PSK_GET_SIZE(a, b, c) 0
+#define PSK_WRITE(a, b, c, d) 0
+#define PSK_PARSE(a, b, c, d) 0
+
+#endif
+
+/******************************************************************************/
+/* PSK Key Exchange Modes                                                     */
+/******************************************************************************/
+
+#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK))
+/* Get the size of the encoded PSK KE modes extension.
+ * Only in ClientHello.
+ *
+ * modes    The PSK KE mode bit string.
+ * msgType  The type of the message this extension is being written into.
+ * returns the number of bytes of the encoded PSK KE mode extension.
+ */
+static int TLSX_PskKeModes_GetSize(byte modes, byte msgType, word16* pSz)
+{
+    if (msgType == client_hello) {
+        /* Format: Len | Modes* */
+        word16 len = OPAQUE8_LEN;
+        /* Check whether each possible mode is to be written. */
+        if (modes & (1 << PSK_KE))
+            len += OPAQUE8_LEN;
+        if (modes & (1 << PSK_DHE_KE))
+            len += OPAQUE8_LEN;
+        *pSz += len;
+        return 0;
+    }
+
+    return SANITY_MSG_E;
+}
+
+/* Writes the PSK KE modes extension into the output buffer.
+ * Assumes that the the output buffer is big enough to hold data.
+ * Only in ClientHello.
+ *
+ * modes    The PSK KE mode bit string.
+ * output   The buffer to write into.
+ * msgType  The type of the message this extension is being written into.
+ * returns the number of bytes written into the buffer.
+ */
+static int TLSX_PskKeModes_Write(byte modes, byte* output, byte msgType,
+                                 word16* pSz)
+{
+    if (msgType == client_hello) {
+        /* Format: Len | Modes* */
+        int idx = OPAQUE8_LEN;
+
+        /* Write out each possible mode. */
+        if (modes & (1 << PSK_KE))
+            output[idx++] = PSK_KE;
+        if (modes & (1 << PSK_DHE_KE))
+            output[idx++] = PSK_DHE_KE;
+        /* Write out length of mode list. */
+        output[0] = idx - OPAQUE8_LEN;
+
+        *pSz += idx;
+        return 0;
+    }
+
+    return SANITY_MSG_E;
+}
+
+/* Parse the PSK KE modes extension.
+ * Only in ClientHello.
+ *
+ * ssl      The SSL/TLS object.
+ * input    The extension data.
+ * length   The length of the extension data.
+ * msgType  The type of the message this extension is being parsed from.
+ * returns 0 on success and other values indicate failure.
+ */
+static int TLSX_PskKeModes_Parse(WOLFSSL* ssl, byte* input, word16 length,
+                                 byte msgType)
+{
+    int    ret;
+
+    if (msgType == client_hello) {
+        /* Format: Len | Modes* */
+        int   idx = 0;
+        word16 len;
+        byte  modes = 0;
+
+        /* Ensure length byte exists. */
+        if (length < OPAQUE8_LEN)
+            return BUFFER_E;
+
+        /* Get length of mode list and ensure that is the only data. */
+        len = input[0];
+        if (length - OPAQUE8_LEN != len)
+            return BUFFER_E;
+
+        idx = OPAQUE8_LEN;
+        /* Set a bit for each recognized modes. */
+        while (len > 0) {
+            /* Ignore unrecognized modes.  */
+            if (input[idx] <= PSK_DHE_KE)
+               modes |= 1 << input[idx];
+            idx++;
+            len--;
+        }
+
+        ret = TLSX_PskKeModes_Use(ssl, modes);
+        if (ret != 0)
+            return ret;
+
+        return 0;
+    }
+
+    return SANITY_MSG_E;
+}
+
+/* Use the data to create a new PSK Key Exchange Modes object in the extensions.
+ *
+ * ssl    The SSL/TLS object.
+ * modes  The PSK key exchange modes.
+ * returns 0 on success and other values indicate failure.
+ */
+int TLSX_PskKeModes_Use(WOLFSSL* ssl, byte modes)
+{
+    int           ret = 0;
+    TLSX*         extension;
+
+    /* Find the PSK key exchange modes extension if it exists. */
+    extension = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES);
+    if (extension == NULL) {
+        /* Push new PSK key exchange modes extension. */
+        ret = TLSX_Push(&ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES, NULL,
+            ssl->heap);
+        if (ret != 0)
+            return ret;
+
+        extension = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES);
+        if (extension == NULL)
+            return MEMORY_E;
+    }
+
+    extension->val = modes;
+
+    return 0;
+}
+
+#define PKM_GET_SIZE  TLSX_PskKeModes_GetSize
+#define PKM_WRITE     TLSX_PskKeModes_Write
+#define PKM_PARSE     TLSX_PskKeModes_Parse
+
+#else
+
+#define PKM_GET_SIZE(a, b, c) 0
+#define PKM_WRITE(a, b, c, d) 0
+#define PKM_PARSE(a, b, c, d) 0
+
+#endif
+
+/******************************************************************************/
+/* Post-Handshake Authentication                                              */
+/******************************************************************************/
+
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+/* Get the size of the encoded Post-Handshake Authentication extension.
+ * Only in ClientHello.
+ *
+ * msgType  The type of the message this extension is being written into.
+ * returns the number of bytes of the encoded Post-Handshake Authentication
+ * extension.
+ */
+static int TLSX_PostHandAuth_GetSize(byte msgType, word16* pSz)
+{
+    if (msgType == client_hello) {
+        *pSz += 0;
+        return 0;
+    }
+
+    return SANITY_MSG_E;
+}
+
+/* Writes the Post-Handshake Authentication extension into the output buffer.
+ * Assumes that the the output buffer is big enough to hold data.
+ * Only in ClientHello.
+ *
+ * output   The buffer to write into.
+ * msgType  The type of the message this extension is being written into.
+ * returns the number of bytes written into the buffer.
+ */
+static int TLSX_PostHandAuth_Write(byte* output, byte msgType, word16* pSz)
+{
+    (void)output;
+
+    if (msgType == client_hello) {
+        *pSz += 0;
+        return 0;
+    }
+
+    return SANITY_MSG_E;
+}
+
+/* Parse the Post-Handshake Authentication extension.
+ * Only in ClientHello.
+ *
+ * ssl      The SSL/TLS object.
+ * input    The extension data.
+ * length   The length of the extension data.
+ * msgType  The type of the message this extension is being parsed from.
+ * returns 0 on success and other values indicate failure.
+ */
+static int TLSX_PostHandAuth_Parse(WOLFSSL* ssl, byte* input, word16 length,
+                                 byte msgType)
+{
+    (void)input;
+
+    if (msgType == client_hello) {
+        /* Ensure extension is empty. */
+        if (length != 0)
+            return BUFFER_E;
+
+        ssl->options.postHandshakeAuth = 1;
+        return 0;
+    }
+
+    return SANITY_MSG_E;
+}
+
+/* Create a new Post-handshake authentication object in the extensions.
+ *
+ * ssl    The SSL/TLS object.
+ * returns 0 on success and other values indicate failure.
+ */
+static int TLSX_PostHandAuth_Use(WOLFSSL* ssl)
+{
+    int   ret = 0;
+    TLSX* extension;
+
+    /* Find the PSK key exchange modes extension if it exists. */
+    extension = TLSX_Find(ssl->extensions, TLSX_POST_HANDSHAKE_AUTH);
+    if (extension == NULL) {
+        /* Push new Post-handshake Authentication extension. */
+        ret = TLSX_Push(&ssl->extensions, TLSX_POST_HANDSHAKE_AUTH, NULL,
+            ssl->heap);
+        if (ret != 0)
+            return ret;
+    }
+
+    return 0;
+}
+
+#define PHA_GET_SIZE  TLSX_PostHandAuth_GetSize
+#define PHA_WRITE     TLSX_PostHandAuth_Write
+#define PHA_PARSE     TLSX_PostHandAuth_Parse
+
+#else
+
+#define PHA_GET_SIZE(a, b)    0
+#define PHA_WRITE(a, b, c)    0
+#define PHA_PARSE(a, b, c, d) 0
+
+#endif
+
+/******************************************************************************/
+/* Early Data Indication                                                      */
+/******************************************************************************/
+
+#ifdef WOLFSSL_EARLY_DATA
+/* Get the size of the encoded Early Data Indication extension.
+ * In messages: ClientHello, EncryptedExtensions and NewSessionTicket.
+ *
+ * msgType  The type of the message this extension is being written into.
+ * returns the number of bytes of the encoded Early Data Indication extension.
+ */
+static int TLSX_EarlyData_GetSize(byte msgType, word16* pSz)
+{
+    int ret = 0;
+
+    if (msgType == client_hello || msgType == encrypted_extensions)
+        *pSz += 0;
+    else if (msgType == session_ticket)
+        *pSz += OPAQUE32_LEN;
+    else
+        ret = SANITY_MSG_E;
+
+    return ret;
+}
+
+/* Writes the Early Data Indicator extension into the output buffer.
+ * Assumes that the the output buffer is big enough to hold data.
+ * In messages: ClientHello, EncryptedExtensions and NewSessionTicket.
+ *
+ * max      The maximum early data size.
+ * output   The buffer to write into.
+ * msgType  The type of the message this extension is being written into.
+ * returns the number of bytes written into the buffer.
+ */
+static int TLSX_EarlyData_Write(word32 max, byte* output, byte msgType,
+                                word16* pSz)
+{
+    if (msgType == client_hello || msgType == encrypted_extensions)
+        return 0;
+    else if (msgType == session_ticket) {
+        c32toa(max, output);
+        *pSz += OPAQUE32_LEN;
+        return 0;
+    }
+
+    return SANITY_MSG_E;
+}
+
+/* Parse the Early Data Indicator extension.
+ * In messages: ClientHello, EncryptedExtensions and NewSessionTicket.
+ *
+ * ssl      The SSL/TLS object.
+ * input    The extension data.
+ * length   The length of the extension data.
+ * msgType  The type of the message this extension is being parsed from.
+ * returns 0 on success and other values indicate failure.
+ */
+static int TLSX_EarlyData_Parse(WOLFSSL* ssl, byte* input, word16 length,
+                                 byte msgType)
+{
+    if (msgType == client_hello) {
+        if (length != 0)
+            return BUFFER_E;
+
+        if (ssl->earlyData == expecting_early_data)
+            return TLSX_EarlyData_Use(ssl, 0);
+        ssl->earlyData = early_data_ext;
+        return 0;
+    }
+    if (msgType == encrypted_extensions) {
+        if (length != 0)
+            return BUFFER_E;
+
+        /* Ensure the index of PSK identity chosen by server is 0.
+         * Index is plus one to handle 'not set' value of 0.
+         */
+        if (ssl->options.pskIdIndex != 1)
+            return PSK_KEY_ERROR;
+
+        return TLSX_EarlyData_Use(ssl, 1);
+    }
+    if (msgType == session_ticket) {
+        word32 maxSz;
+
+        if (length != OPAQUE32_LEN)
+            return BUFFER_E;
+        ato32(input, &maxSz);
+
+        ssl->session.maxEarlyDataSz = maxSz;
+        return 0;
+    }
+
+    return SANITY_MSG_E;
+}
+
+/* Use the data to create a new Early Data object in the extensions.
+ *
+ * ssl  The SSL/TLS object.
+ * max  The maximum early data size.
+ * returns 0 on success and other values indicate failure.
+ */
+int TLSX_EarlyData_Use(WOLFSSL* ssl, word32 max)
+{
+    int   ret = 0;
+    TLSX* extension;
+
+    /* Find the early data extension if it exists. */
+    extension = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA);
+    if (extension == NULL) {
+        /* Push new early data extension. */
+        ret = TLSX_Push(&ssl->extensions, TLSX_EARLY_DATA, NULL, ssl->heap);
+        if (ret != 0)
+            return ret;
+
+        extension = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA);
+        if (extension == NULL)
+            return MEMORY_E;
+    }
+
+    extension->resp = 1;
+    extension->val  = max;
+
+    return 0;
+}
+
+#define EDI_GET_SIZE  TLSX_EarlyData_GetSize
+#define EDI_WRITE     TLSX_EarlyData_Write
+#define EDI_PARSE     TLSX_EarlyData_Parse
+
+#else
+
+#define EDI_GET_SIZE(a, b)    0
+#define EDI_WRITE(a, b, c, d) 0
+#define EDI_PARSE(a, b, c, d) 0
+
+#endif
+
+/******************************************************************************/
+/* TLS Extensions Framework                                                   */
+/******************************************************************************/
+
+/** Finds an extension in the provided list. */
+TLSX* TLSX_Find(TLSX* list, TLSX_Type type)
+{
+    TLSX* extension = list;
+
+    while (extension && extension->type != type)
+        extension = extension->next;
+
+    return extension;
+}
+
+/** Remove an extension. */
+void TLSX_Remove(TLSX** list, TLSX_Type type, void* heap)
+{
+    TLSX* extension = *list;
+    TLSX** next = list;
+
+    while (extension && extension->type != type) {
+        next = &extension->next;
+        extension = extension->next;
+    }
+
+    if (extension) {
+        *next = extension->next;
+        extension->next = NULL;
+        TLSX_FreeAll(extension, heap);
+    }
+}
+
+/** Releases all extensions in the provided list. */
+void TLSX_FreeAll(TLSX* list, void* heap)
+{
+    TLSX* extension;
+
+    while ((extension = list)) {
+        list = extension->next;
+
+        switch (extension->type) {
+
+            case TLSX_SERVER_NAME:
+                SNI_FREE_ALL((SNI*)extension->data, heap);
+                break;
+
+            case TLSX_TRUSTED_CA_KEYS:
+                TCA_FREE_ALL((TCA*)extension->data, heap);
+                break;
+
+            case TLSX_MAX_FRAGMENT_LENGTH:
+                MFL_FREE_ALL(extension->data, heap);
+                break;
+
+            case TLSX_TRUNCATED_HMAC:
+                /* Nothing to do. */
+                break;
+
+            case TLSX_SUPPORTED_GROUPS:
+                EC_FREE_ALL((SupportedCurve*)extension->data, heap);
+                break;
+
+            case TLSX_EC_POINT_FORMATS:
+                PF_FREE_ALL((PointFormat*)extension->data, heap);
+                break;
+
+            case TLSX_STATUS_REQUEST:
+                CSR_FREE_ALL((CertificateStatusRequest*)extension->data, heap);
+                break;
+
+            case TLSX_STATUS_REQUEST_V2:
+                CSR2_FREE_ALL((CertificateStatusRequestItemV2*)extension->data,
+                        heap);
+                break;
+
+            case TLSX_RENEGOTIATION_INFO:
+                SCR_FREE_ALL(extension->data, heap);
+                break;
+
+            case TLSX_SESSION_TICKET:
+                WOLF_STK_FREE(extension->data, heap);
+                break;
+
+            case TLSX_QUANTUM_SAFE_HYBRID:
+                QSH_FREE_ALL((QSHScheme*)extension->data, heap);
+                break;
+
+            case TLSX_APPLICATION_LAYER_PROTOCOL:
+                ALPN_FREE_ALL((ALPN*)extension->data, heap);
+                break;
+#if !defined(WOLFSSL_NO_SIGALG)
+            case TLSX_SIGNATURE_ALGORITHMS:
+                break;
+#endif
+#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+            case TLSX_ENCRYPT_THEN_MAC:
+                break;
+#endif
+#ifdef WOLFSSL_TLS13
+            case TLSX_SUPPORTED_VERSIONS:
+                break;
+
+            case TLSX_COOKIE:
+                CKE_FREE_ALL((Cookie*)extension->data, heap);
+                break;
+
+    #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+            case TLSX_PRE_SHARED_KEY:
+                PSK_FREE_ALL((PreSharedKey*)extension->data, heap);
+                break;
+
+            case TLSX_PSK_KEY_EXCHANGE_MODES:
+                break;
+    #endif
+
+    #ifdef WOLFSSL_EARLY_DATA
+            case TLSX_EARLY_DATA:
+                break;
+    #endif
+
+    #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
+            case TLSX_POST_HANDSHAKE_AUTH:
+                break;
+    #endif
+
+    #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22)
+            case TLSX_SIGNATURE_ALGORITHMS_CERT:
+                break;
+    #endif
+
+            case TLSX_KEY_SHARE:
+                KS_FREE_ALL((KeyShareEntry*)extension->data, heap);
+                break;
+#endif
+        }
+
+        XFREE(extension, heap, DYNAMIC_TYPE_TLSX);
+    }
+
+    (void)heap;
+}
+
+/** Checks if the tls extensions are supported based on the protocol version. */
+int TLSX_SupportExtensions(WOLFSSL* ssl) {
+    return ssl && (IsTLS(ssl) || ssl->version.major == DTLS_MAJOR);
+}
+
+/** Tells the buffered size of the extensions in a list. */
+static int TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType,
+                        word16* pLength)
+{
+    int    ret = 0;
+    TLSX*  extension;
+    word16 length = 0;
+    byte   isRequest = (msgType == client_hello ||
+                        msgType == certificate_request);
+
+    while ((extension = list)) {
+        list = extension->next;
+
+        /* only extensions marked as response are sent back to the client. */
+        if (!isRequest && !extension->resp)
+            continue; /* skip! */
+
+        /* ssl level extensions are expected to override ctx level ones. */
+        if (!IS_OFF(semaphore, TLSX_ToSemaphore(extension->type)))
+            continue; /* skip! */
+
+        /* extension type + extension data length. */
+        length += HELLO_EXT_TYPE_SZ + OPAQUE16_LEN;
+
+
+        switch (extension->type) {
+
+            case TLSX_SERVER_NAME:
+                /* SNI only sends the name on the request. */
+                if (isRequest)
+                    length += SNI_GET_SIZE((SNI*)extension->data);
+                break;
+
+            case TLSX_TRUSTED_CA_KEYS:
+                /* TCA only sends the list on the request. */
+                if (isRequest)
+                    length += TCA_GET_SIZE((TCA*)extension->data);
+                break;
+
+            case TLSX_MAX_FRAGMENT_LENGTH:
+                length += MFL_GET_SIZE(extension->data);
+                break;
+
+            case TLSX_TRUNCATED_HMAC:
+                /* always empty. */
+                break;
+
+            case TLSX_SUPPORTED_GROUPS:
+                length += EC_GET_SIZE((SupportedCurve*)extension->data);
+                break;
+
+            case TLSX_EC_POINT_FORMATS:
+                length += PF_GET_SIZE((PointFormat*)extension->data);
+                break;
+
+            case TLSX_STATUS_REQUEST:
+                length += CSR_GET_SIZE(
+                         (CertificateStatusRequest*)extension->data, isRequest);
+                break;
+
+            case TLSX_STATUS_REQUEST_V2:
+                length += CSR2_GET_SIZE(
+                        (CertificateStatusRequestItemV2*)extension->data,
+                        isRequest);
+                break;
+
+            case TLSX_RENEGOTIATION_INFO:
+                length += SCR_GET_SIZE((SecureRenegotiation*)extension->data,
+                        isRequest);
+                break;
+
+            case TLSX_SESSION_TICKET:
+                length += WOLF_STK_GET_SIZE((SessionTicket*)extension->data,
+                        isRequest);
+                break;
+
+            case TLSX_QUANTUM_SAFE_HYBRID:
+                length += QSH_GET_SIZE((QSHScheme*)extension->data, isRequest);
+                break;
+
+            case TLSX_APPLICATION_LAYER_PROTOCOL:
+                length += ALPN_GET_SIZE((ALPN*)extension->data);
+                break;
+#if !defined(WOLFSSL_NO_SIGALG)
+            case TLSX_SIGNATURE_ALGORITHMS:
+                length += SA_GET_SIZE(extension->data);
+                break;
+#endif
+#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+            case TLSX_ENCRYPT_THEN_MAC:
+                ret = ETM_GET_SIZE(msgType, &length);
+                break;
+#endif /* HAVE_ENCRYPT_THEN_MAC */
+#ifdef WOLFSSL_TLS13
+            case TLSX_SUPPORTED_VERSIONS:
+                ret = SV_GET_SIZE(extension->data, msgType, &length);
+                break;
+
+            case TLSX_COOKIE:
+                ret = CKE_GET_SIZE((Cookie*)extension->data, msgType, &length);
+                break;
+
+    #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+            case TLSX_PRE_SHARED_KEY:
+                ret = PSK_GET_SIZE((PreSharedKey*)extension->data, msgType,
+                                                                       &length);
+                break;
+
+            case TLSX_PSK_KEY_EXCHANGE_MODES:
+                ret = PKM_GET_SIZE(extension->val, msgType, &length);
+                break;
+    #endif
+
+    #ifdef WOLFSSL_EARLY_DATA
+            case TLSX_EARLY_DATA:
+                ret = EDI_GET_SIZE(msgType, &length);
+                break;
+    #endif
+
+    #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
+            case TLSX_POST_HANDSHAKE_AUTH:
+                ret = PHA_GET_SIZE(msgType, &length);
+                break;
+    #endif
+
+    #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22)
+            case TLSX_SIGNATURE_ALGORITHMS_CERT:
+                length += SAC_GET_SIZE(extension->data);
+                break;
+    #endif
+
+            case TLSX_KEY_SHARE:
+                length += KS_GET_SIZE((KeyShareEntry*)extension->data, msgType);
+                break;
+#endif
+        }
+
+        /* marks the extension as processed so ctx level */
+        /* extensions don't overlap with ssl level ones. */
+        TURN_ON(semaphore, TLSX_ToSemaphore(extension->type));
+    }
+
+    *pLength += length;
+
+    return ret;
+}
+
+/** Writes the extensions of a list in a buffer. */
+static int TLSX_Write(TLSX* list, byte* output, byte* semaphore,
+                         byte msgType, word16* pOffset)
+{
+    int    ret = 0;
+    TLSX*  extension;
+    word16 offset = 0;
+    word16 length_offset = 0;
+    byte   isRequest = (msgType == client_hello ||
+                        msgType == certificate_request);
+
+    while ((extension = list)) {
+        list = extension->next;
+
+        /* only extensions marked as response are written in a response. */
+        if (!isRequest && !extension->resp)
+            continue; /* skip! */
+
+        /* ssl level extensions are expected to override ctx level ones. */
+        if (!IS_OFF(semaphore, TLSX_ToSemaphore(extension->type)))
+            continue; /* skip! */
+
+        /* writes extension type. */
+        c16toa(extension->type, output + offset);
+        offset += HELLO_EXT_TYPE_SZ + OPAQUE16_LEN;
+        length_offset = offset;
+
+        /* extension data should be written internally. */
+        switch (extension->type) {
+            case TLSX_SERVER_NAME:
+                if (isRequest) {
+                    WOLFSSL_MSG("SNI extension to write");
+                    offset += SNI_WRITE((SNI*)extension->data, output + offset);
+                }
+                break;
+
+            case TLSX_TRUSTED_CA_KEYS:
+                WOLFSSL_MSG("Trusted CA Indication extension to write");
+                if (isRequest) {
+                    offset += TCA_WRITE((TCA*)extension->data, output + offset);
+                }
+                break;
+
+            case TLSX_MAX_FRAGMENT_LENGTH:
+                WOLFSSL_MSG("Max Fragment Length extension to write");
+                offset += MFL_WRITE((byte*)extension->data, output + offset);
+                break;
+
+            case TLSX_TRUNCATED_HMAC:
+                WOLFSSL_MSG("Truncated HMAC extension to write");
+                /* always empty. */
+                break;
+
+            case TLSX_SUPPORTED_GROUPS:
+                WOLFSSL_MSG("Supported Groups extension to write");
+                offset += EC_WRITE((SupportedCurve*)extension->data,
+                                    output + offset);
+                break;
+
+            case TLSX_EC_POINT_FORMATS:
+                WOLFSSL_MSG("Point Formats extension to write");
+                offset += PF_WRITE((PointFormat*)extension->data,
+                                    output + offset);
+                break;
+
+            case TLSX_STATUS_REQUEST:
+                WOLFSSL_MSG("Certificate Status Request extension to write");
+                offset += CSR_WRITE((CertificateStatusRequest*)extension->data,
+                        output + offset, isRequest);
+                break;
+
+            case TLSX_STATUS_REQUEST_V2:
+                WOLFSSL_MSG("Certificate Status Request v2 extension to write");
+                offset += CSR2_WRITE(
+                        (CertificateStatusRequestItemV2*)extension->data,
+                        output + offset, isRequest);
+                break;
+
+            case TLSX_RENEGOTIATION_INFO:
+                WOLFSSL_MSG("Secure Renegotiation extension to write");
+                offset += SCR_WRITE((SecureRenegotiation*)extension->data,
+                        output + offset, isRequest);
+                break;
+
+            case TLSX_SESSION_TICKET:
+                WOLFSSL_MSG("Session Ticket extension to write");
+                offset += WOLF_STK_WRITE((SessionTicket*)extension->data,
+                        output + offset, isRequest);
+                break;
+
+            case TLSX_QUANTUM_SAFE_HYBRID:
+                WOLFSSL_MSG("Quantum-Safe-Hybrid extension to write");
+                if (isRequest) {
+                    offset += QSH_WRITE((QSHScheme*)extension->data, output + offset);
+                }
+                offset += QSHPK_WRITE((QSHScheme*)extension->data, output + offset);
+                offset += QSH_SERREQ(output + offset, isRequest);
+                break;
+
+            case TLSX_APPLICATION_LAYER_PROTOCOL:
+                WOLFSSL_MSG("ALPN extension to write");
+                offset += ALPN_WRITE((ALPN*)extension->data, output + offset);
+                break;
+#if !defined(WOLFSSL_NO_SIGALG)
+            case TLSX_SIGNATURE_ALGORITHMS:
+                WOLFSSL_MSG("Signature Algorithms extension to write");
+                offset += SA_WRITE(extension->data, output + offset);
+                break;
+#endif
+#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+            case TLSX_ENCRYPT_THEN_MAC:
+                WOLFSSL_MSG("Encrypt-Then-Mac extension to write");
+                ret = ETM_WRITE(extension->data, output, msgType, &offset);
+                break;
+#endif /* HAVE_ENCRYPT_THEN_MAC */
+#ifdef WOLFSSL_TLS13
+            case TLSX_SUPPORTED_VERSIONS:
+                WOLFSSL_MSG("Supported Versions extension to write");
+                ret = SV_WRITE(extension->data, output + offset, msgType, &offset);
+                break;
+
+            case TLSX_COOKIE:
+                WOLFSSL_MSG("Cookie extension to write");
+                ret = CKE_WRITE((Cookie*)extension->data, output + offset,
+                                msgType, &offset);
+                break;
+
+    #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+            case TLSX_PRE_SHARED_KEY:
+                WOLFSSL_MSG("Pre-Shared Key extension to write");
+                ret = PSK_WRITE((PreSharedKey*)extension->data, output + offset,
+                                                              msgType, &offset);
+                break;
+
+            case TLSX_PSK_KEY_EXCHANGE_MODES:
+                WOLFSSL_MSG("PSK Key Exchange Modes extension to write");
+                ret = PKM_WRITE(extension->val, output + offset, msgType,
+                                                                       &offset);
+                break;
+    #endif
+
+    #ifdef WOLFSSL_EARLY_DATA
+            case TLSX_EARLY_DATA:
+                WOLFSSL_MSG("Early Data extension to write");
+                ret = EDI_WRITE(extension->val, output + offset, msgType,
+                                                                       &offset);
+                break;
+    #endif
+
+    #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
+            case TLSX_POST_HANDSHAKE_AUTH:
+                WOLFSSL_MSG("Post-Handshake Authentication extension to write");
+                ret = PHA_WRITE(output + offset, msgType, &offset);
+                break;
+    #endif
+
+    #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22)
+            case TLSX_SIGNATURE_ALGORITHMS_CERT:
+                WOLFSSL_MSG("Signature Algorithms extension to write");
+                offset += SAC_WRITE(extension->data, output + offset);
+                break;
+    #endif
+
+            case TLSX_KEY_SHARE:
+                WOLFSSL_MSG("Key Share extension to write");
+                offset += KS_WRITE((KeyShareEntry*)extension->data,
+                                                      output + offset, msgType);
+                break;
+#endif
+        }
+
+        /* writes extension data length. */
+        c16toa(offset - length_offset, output + length_offset - OPAQUE16_LEN);
+
+        /* marks the extension as processed so ctx level */
+        /* extensions don't overlap with ssl level ones. */
+        TURN_ON(semaphore, TLSX_ToSemaphore(extension->type));
+    }
+
+    *pOffset += offset;
+
+    return ret;
+}
+
+
+#if defined(HAVE_NTRU) && defined(HAVE_QSH)
+
+static word32 GetEntropy(unsigned char* out, word32 num_bytes)
+{
+    int ret = 0;
+
+    if (gRng == NULL) {
+        if ((gRng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL,
+                                                    DYNAMIC_TYPE_TLSX)) == NULL)
+            return DRBG_OUT_OF_MEMORY;
+        wc_InitRng(gRng);
+    }
+
+    if (gRngMutex == NULL) {
+        if ((gRngMutex = (wolfSSL_Mutex*)XMALLOC(sizeof(wolfSSL_Mutex), NULL,
+                                                    DYNAMIC_TYPE_TLSX)) == NULL)
+            return DRBG_OUT_OF_MEMORY;
+        wc_InitMutex(gRngMutex);
+    }
+
+    ret |= wc_LockMutex(gRngMutex);
+    ret |= wc_RNG_GenerateBlock(gRng, out, num_bytes);
+    ret |= wc_UnLockMutex(gRngMutex);
+
+    if (ret != 0)
+        return DRBG_ENTROPY_FAIL;
+
+    return DRBG_OK;
+}
+#endif
+
+
+#ifdef HAVE_QSH
+static int TLSX_CreateQSHKey(WOLFSSL* ssl, int type)
+{
+    int ret = -1;
+
+    (void)ssl;
+
+    switch (type) {
+#ifdef HAVE_NTRU
+        case WOLFSSL_NTRU_EESS439:
+        case WOLFSSL_NTRU_EESS593:
+        case WOLFSSL_NTRU_EESS743:
+            ret = TLSX_CreateNtruKey(ssl, type);
+            break;
+#endif
+        default:
+            WOLFSSL_MSG("Unknown type for creating NTRU key");
+            break;
+    }
+
+    return ret;
+}
+
+
+static int TLSX_AddQSHKey(QSHKey** list, QSHKey* key)
+{
+    QSHKey* current;
+
+    if (key == NULL)
+        return BAD_FUNC_ARG;
+
+    /* if no public key stored in key then do not add */
+    if (key->pub.length == 0 || key->pub.buffer == NULL)
+        return 0;
+
+    /* first element to be added to the list */
+    current = *list;
+    if (current == NULL) {
+        *list = key;
+        return 0;
+    }
+
+    while (current->next) {
+        /* can only have one of the key in the list */
+        if (current->name == key->name)
+            return -1;
+        current = (QSHKey*)current->next;
+    }
+
+    current->next = (struct QSHKey*)key;
+
+    return 0;
+}
+
+
+#if defined(HAVE_NTRU)
+int TLSX_CreateNtruKey(WOLFSSL* ssl, int type)
+{
+    int ret = -1;
+    int ntruType;
+
+    /* variable declarations for NTRU*/
+    QSHKey* temp = NULL;
+    byte   public_key[1027];
+    word16 public_key_len = sizeof(public_key);
+    byte   private_key[1120];
+    word16 private_key_len = sizeof(private_key);
+    DRBG_HANDLE drbg;
+
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    switch (type) {
+        case WOLFSSL_NTRU_EESS439:
+            ntruType = NTRU_EES439EP1;
+            break;
+        case WOLFSSL_NTRU_EESS593:
+            ntruType = NTRU_EES593EP1;
+            break;
+        case WOLFSSL_NTRU_EESS743:
+            ntruType = NTRU_EES743EP1;
+            break;
+        default:
+            WOLFSSL_MSG("Unknown type for creating NTRU key");
+            return -1;
+    }
+    ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg);
+    if (ret != DRBG_OK) {
+        WOLFSSL_MSG("NTRU drbg instantiate failed\n");
+        return ret;
+    }
+
+    if ((ret = ntru_crypto_ntru_encrypt_keygen(drbg, ntruType,
+                     &public_key_len, NULL, &private_key_len, NULL)) != NTRU_OK)
+        return ret;
+
+    if ((ret = ntru_crypto_ntru_encrypt_keygen(drbg, ntruType,
+        &public_key_len, public_key, &private_key_len, private_key)) != NTRU_OK)
+        return ret;
+
+    ret = ntru_crypto_drbg_uninstantiate(drbg);
+    if (ret != NTRU_OK) {
+        WOLFSSL_MSG("NTRU drbg uninstantiate failed\n");
+        return ret;
+    }
+
+    if ((temp = (QSHKey*)XMALLOC(sizeof(QSHKey), ssl->heap,
+                                                    DYNAMIC_TYPE_TLSX)) == NULL)
+        return MEMORY_E;
+    temp->name = type;
+    temp->pub.length = public_key_len;
+    temp->pub.buffer = (byte*)XMALLOC(public_key_len, ssl->heap,
+                                DYNAMIC_TYPE_PUBLIC_KEY);
+    XMEMCPY(temp->pub.buffer, public_key, public_key_len);
+    temp->pri.length = private_key_len;
+    temp->pri.buffer = (byte*)XMALLOC(private_key_len, ssl->heap,
+                                DYNAMIC_TYPE_ARRAYS);
+    XMEMCPY(temp->pri.buffer, private_key, private_key_len);
+    temp->next = NULL;
+
+    TLSX_AddQSHKey(&ssl->QSH_Key, temp);
+
+    (void)ssl;
+    (void)type;
+
+    return ret;
+}
+#endif
+
+
+/*
+    Used to find a public key from the list of keys
+    pubLen length of array
+    name   input the name of the scheme looking for ie WOLFSSL_NTRU_ESSXXX
+
+    returns a pointer to public key byte* or NULL if not found
+ */
+static byte* TLSX_QSHKeyFind_Pub(QSHKey* qsh, word16* pubLen, word16 name)
+{
+    QSHKey* current = qsh;
+
+    if (qsh == NULL || pubLen == NULL)
+        return NULL;
+
+    *pubLen = 0;
+
+    while(current) {
+        if (current->name == name) {
+            *pubLen = current->pub.length;
+            return current->pub.buffer;
+        }
+        current = (QSHKey*)current->next;
+    }
+
+    return NULL;
+}
+#endif /* HAVE_QSH */
+
+#if (!defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_TLS13) && \
+        !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)) || \
+    (defined(WOLFSSL_TLS13) && !defined(HAVE_ECC) && !defined(HAVE_CURVE25519) \
+        && !defined(HAVE_CURVE448) && defined(HAVE_SUPPORTED_CURVES)) || \
+    ((defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+        defined(HAVE_CURVE448)) && defined(HAVE_SUPPORTED_CURVES))
+
+/* Populates the default supported groups / curves */
+static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions)
+{
+    int ret = WOLFSSL_SUCCESS;
+#ifdef WOLFSSL_TLS13
+    int i;
+
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+    if (ssl->options.resuming && ssl->session.namedGroup != 0) {
+        return TLSX_UseSupportedCurve(extensions, ssl->session.namedGroup,
+                                                                     ssl->heap);
+    }
+#endif
+
+    if (ssl->numGroups != 0) {
+        for (i = 0; i < ssl->numGroups; i++) {
+            ret = TLSX_UseSupportedCurve(extensions, ssl->group[i], ssl->heap);
+            if (ret != WOLFSSL_SUCCESS)
+                return ret;
+        }
+        return WOLFSSL_SUCCESS;
+    }
+#endif /* WOLFSSL_TLS13 */
+
+#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES)
+        /* list in order by strength, since not all servers choose by strength */
+        #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
+            #ifndef NO_ECC_SECP
+                ret = TLSX_UseSupportedCurve(extensions,
+                                              WOLFSSL_ECC_SECP521R1, ssl->heap);
+                if (ret != WOLFSSL_SUCCESS) return ret;
+            #endif
+        #endif
+        #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)
+            #ifdef HAVE_ECC_BRAINPOOL
+                ret = TLSX_UseSupportedCurve(extensions,
+                                        WOLFSSL_ECC_BRAINPOOLP512R1, ssl->heap);
+                if (ret != WOLFSSL_SUCCESS) return ret;
+            #endif
+        #endif
+        #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
+            #ifndef NO_ECC_SECP
+                ret = TLSX_UseSupportedCurve(extensions,
+                                              WOLFSSL_ECC_SECP384R1, ssl->heap);
+                if (ret != WOLFSSL_SUCCESS) return ret;
+            #endif
+            #ifdef HAVE_ECC_BRAINPOOL
+                ret = TLSX_UseSupportedCurve(extensions,
+                                        WOLFSSL_ECC_BRAINPOOLP384R1, ssl->heap);
+                if (ret != WOLFSSL_SUCCESS) return ret;
+            #endif
+        #endif
+#endif /* HAVE_ECC && HAVE_SUPPORTED_CURVES */
+
+        #ifndef HAVE_FIPS
+            #if defined(HAVE_CURVE448)
+                ret = TLSX_UseSupportedCurve(extensions,
+                                                   WOLFSSL_ECC_X448, ssl->heap);
+                if (ret != WOLFSSL_SUCCESS) return ret;
+            #endif
+        #endif /* HAVE_FIPS */
+
+#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES)
+        #if !defined(NO_ECC256)  || defined(HAVE_ALL_CURVES)
+            #ifndef NO_ECC_SECP
+                ret = TLSX_UseSupportedCurve(extensions,
+                                              WOLFSSL_ECC_SECP256R1, ssl->heap);
+                if (ret != WOLFSSL_SUCCESS) return ret;
+            #endif
+            #ifdef HAVE_ECC_KOBLITZ
+                ret = TLSX_UseSupportedCurve(extensions,
+                                              WOLFSSL_ECC_SECP256K1, ssl->heap);
+                if (ret != WOLFSSL_SUCCESS) return ret;
+            #endif
+            #ifdef HAVE_ECC_BRAINPOOL
+                ret = TLSX_UseSupportedCurve(extensions,
+                                        WOLFSSL_ECC_BRAINPOOLP256R1, ssl->heap);
+                if (ret != WOLFSSL_SUCCESS) return ret;
+            #endif
+        #endif
+#endif /* HAVE_ECC && HAVE_SUPPORTED_CURVES */
+
+        #ifndef HAVE_FIPS
+            #if defined(HAVE_CURVE25519)
+                ret = TLSX_UseSupportedCurve(extensions,
+                                                 WOLFSSL_ECC_X25519, ssl->heap);
+                if (ret != WOLFSSL_SUCCESS) return ret;
+            #endif
+        #endif /* HAVE_FIPS */
+
+#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES)
+        #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)
+            #ifndef NO_ECC_SECP
+                ret = TLSX_UseSupportedCurve(extensions,
+                                              WOLFSSL_ECC_SECP224R1, ssl->heap);
+                if (ret != WOLFSSL_SUCCESS) return ret;
+            #endif
+            #ifdef HAVE_ECC_KOBLITZ
+                ret = TLSX_UseSupportedCurve(extensions,
+                                              WOLFSSL_ECC_SECP224K1, ssl->heap);
+                if (ret != WOLFSSL_SUCCESS) return ret;
+            #endif
+        #endif
+
+    #ifndef HAVE_FIPS
+        #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)
+            #ifndef NO_ECC_SECP
+                ret = TLSX_UseSupportedCurve(extensions,
+                                              WOLFSSL_ECC_SECP192R1, ssl->heap);
+                if (ret != WOLFSSL_SUCCESS) return ret;
+            #endif
+            #ifdef HAVE_ECC_KOBLITZ
+                ret = TLSX_UseSupportedCurve(extensions,
+                                              WOLFSSL_ECC_SECP192K1, ssl->heap);
+                if (ret != WOLFSSL_SUCCESS) return ret;
+            #endif
+        #endif
+        #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES)
+            #ifndef NO_ECC_SECP
+                ret = TLSX_UseSupportedCurve(extensions,
+                                              WOLFSSL_ECC_SECP160R1, ssl->heap);
+                if (ret != WOLFSSL_SUCCESS) return ret;
+            #endif
+            #ifdef HAVE_ECC_SECPR2
+                ret = TLSX_UseSupportedCurve(extensions,
+                                              WOLFSSL_ECC_SECP160R2, ssl->heap);
+                if (ret != WOLFSSL_SUCCESS) return ret;
+            #endif
+            #ifdef HAVE_ECC_KOBLITZ
+                ret = TLSX_UseSupportedCurve(extensions,
+                                              WOLFSSL_ECC_SECP160K1, ssl->heap);
+                if (ret != WOLFSSL_SUCCESS) return ret;
+            #endif
+        #endif
+    #endif /* HAVE_FIPS */
+#endif /* HAVE_ECC && HAVE_SUPPORTED_CURVES */
+
+                /* Add FFDHE supported groups. */
+        #ifdef HAVE_FFDHE_8192
+            if (8192/8 >= ssl->options.minDhKeySz &&
+                                            8192/8 <= ssl->options.maxDhKeySz) {
+                ret = TLSX_UseSupportedCurve(extensions,
+                                             WOLFSSL_FFDHE_8192, ssl->heap);
+                if (ret != WOLFSSL_SUCCESS)
+                    return ret;
+            }
+        #endif
+        #ifdef HAVE_FFDHE_6144
+            if (6144/8 >= ssl->options.minDhKeySz &&
+                                            6144/8 <= ssl->options.maxDhKeySz) {
+                ret = TLSX_UseSupportedCurve(extensions,
+                                             WOLFSSL_FFDHE_6144, ssl->heap);
+                if (ret != WOLFSSL_SUCCESS)
+                    return ret;
+            }
+        #endif
+        #ifdef HAVE_FFDHE_4096
+            if (4096/8 >= ssl->options.minDhKeySz &&
+                                            4096/8 <= ssl->options.maxDhKeySz) {
+                ret = TLSX_UseSupportedCurve(extensions,
+                                             WOLFSSL_FFDHE_4096, ssl->heap);
+                if (ret != WOLFSSL_SUCCESS)
+                    return ret;
+            }
+        #endif
+        #ifdef HAVE_FFDHE_3072
+            if (3072/8 >= ssl->options.minDhKeySz &&
+                                            3072/8 <= ssl->options.maxDhKeySz) {
+                ret = TLSX_UseSupportedCurve(extensions,
+                                             WOLFSSL_FFDHE_3072, ssl->heap);
+                if (ret != WOLFSSL_SUCCESS)
+                    return ret;
+            }
+        #endif
+        #ifdef HAVE_FFDHE_2048
+            if (2048/8 >= ssl->options.minDhKeySz &&
+                                            2048/8 <= ssl->options.maxDhKeySz) {
+                ret = TLSX_UseSupportedCurve(extensions,
+                                             WOLFSSL_FFDHE_2048, ssl->heap);
+                if (ret != WOLFSSL_SUCCESS)
+                    return ret;
+            }
+        #endif
+
+    (void)ssl;
+    (void)extensions;
+
+    return ret;
+}
+
+#endif
+
+int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
+{
+    int ret = 0;
+    byte* public_key      = NULL;
+    word16 public_key_len = 0;
+#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK))
+    int usingPSK = 0;
+#endif
+#ifdef HAVE_QSH
+    TLSX* extension;
+    QSHScheme* qsh;
+    QSHScheme* next;
+
+    /* add supported QSHSchemes */
+    WOLFSSL_MSG("Adding supported QSH Schemes");
+#endif
+
+    /* server will add extension depending on what is parsed from client */
+    if (!isServer) {
+#ifdef HAVE_QSH
+        /* test if user has set a specific scheme already */
+        if (!ssl->user_set_QSHSchemes) {
+            if (ssl->sendQSHKeys && ssl->QSH_Key == NULL) {
+                if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS743)) != 0) {
+                    WOLFSSL_MSG("Error creating ntru keys");
+                    return ret;
+                }
+                if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS593)) != 0) {
+                    WOLFSSL_MSG("Error creating ntru keys");
+                    return ret;
+                }
+                if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS439)) != 0) {
+                    WOLFSSL_MSG("Error creating ntru keys");
+                    return ret;
+                }
+
+            /* add NTRU 256 */
+            public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key,
+                    &public_key_len, WOLFSSL_NTRU_EESS743);
+            }
+            if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS743,
+                                  public_key, public_key_len, ssl->heap)
+                                  != WOLFSSL_SUCCESS)
+                ret = -1;
+
+            /* add NTRU 196 */
+            if (ssl->sendQSHKeys) {
+                public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key,
+                    &public_key_len, WOLFSSL_NTRU_EESS593);
+            }
+            if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS593,
+                                  public_key, public_key_len, ssl->heap)
+                                  != WOLFSSL_SUCCESS)
+                ret = -1;
+
+            /* add NTRU 128 */
+            if (ssl->sendQSHKeys) {
+                public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key,
+                    &public_key_len, WOLFSSL_NTRU_EESS439);
+            }
+            if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS439,
+                                  public_key, public_key_len, ssl->heap)
+                                  != WOLFSSL_SUCCESS)
+                ret = -1;
+        }
+        else if (ssl->sendQSHKeys && ssl->QSH_Key == NULL) {
+            /* for each scheme make a client key */
+            extension = TLSX_Find(ssl->extensions, TLSX_QUANTUM_SAFE_HYBRID);
+            if (extension) {
+                qsh = (QSHScheme*)extension->data;
+
+                while (qsh) {
+                    if ((ret = TLSX_CreateQSHKey(ssl, qsh->name)) != 0)
+                        return ret;
+
+                    /* get next now because qsh could be freed */
+                    next = qsh->next;
+
+                    /* find the public key created and add to extension*/
+                    public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key,
+                             &public_key_len, qsh->name);
+                    if (TLSX_UseQSHScheme(&ssl->extensions, qsh->name,
+                                          public_key, public_key_len,
+                                          ssl->heap) != WOLFSSL_SUCCESS)
+                        ret = -1;
+                    qsh = next;
+                }
+            }
+        }
+#endif
+
+#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+        if (!ssl->options.disallowEncThenMac) {
+            ret = TLSX_EncryptThenMac_Use(ssl);
+            if (ret != 0)
+                return ret;
+        }
+#endif
+
+#if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                       defined(HAVE_CURVE448)) && defined(HAVE_SUPPORTED_CURVES)
+        if (!ssl->options.userCurves && !ssl->ctx->userCurves) {
+            if (TLSX_Find(ssl->ctx->extensions,
+                                               TLSX_SUPPORTED_GROUPS) == NULL) {
+                ret = TLSX_PopulateSupportedGroups(ssl, &ssl->extensions);
+                if (ret != WOLFSSL_SUCCESS)
+                    return ret;
+            }
+        }
+        if ((!IsAtLeastTLSv1_3(ssl->version) || ssl->options.downgrade) &&
+               TLSX_Find(ssl->ctx->extensions, TLSX_EC_POINT_FORMATS) == NULL &&
+               TLSX_Find(ssl->extensions, TLSX_EC_POINT_FORMATS) == NULL) {
+             ret = TLSX_UsePointFormat(&ssl->extensions,
+                                         WOLFSSL_EC_PF_UNCOMPRESSED, ssl->heap);
+             if (ret != WOLFSSL_SUCCESS)
+                 return ret;
+        }
+#endif /* (HAVE_ECC || CURVE25519 || CURVE448) && HAVE_SUPPORTED_CURVES */
+    } /* is not server */
+
+#if !defined(WOLFSSL_NO_SIGALG)
+    WOLFSSL_MSG("Adding signature algorithms extension");
+    if ((ret = TLSX_SetSignatureAlgorithms(&ssl->extensions, ssl, ssl->heap))
+                                                                         != 0) {
+            return ret;
+    }
+#else
+    ret = 0;
+#endif
+    #ifdef WOLFSSL_TLS13
+        if (!isServer && IsAtLeastTLSv1_3(ssl->version)) {
+            /* Add mandatory TLS v1.3 extension: supported version */
+            WOLFSSL_MSG("Adding supported versions extension");
+            if ((ret = TLSX_SetSupportedVersions(&ssl->extensions, ssl,
+                                                             ssl->heap)) != 0) {
+                return ret;
+            }
+
+    #if !defined(HAVE_ECC) && !defined(HAVE_CURVE25519) && \
+                       !defined(HAVE_CURVE448) && defined(HAVE_SUPPORTED_CURVES)
+        if (TLSX_Find(ssl->ctx->extensions, TLSX_SUPPORTED_GROUPS) == NULL) {
+            /* Put in DH groups for TLS 1.3 only. */
+            ret = TLSX_PopulateSupportedGroups(ssl, &ssl->extensions);
+            if (ret != WOLFSSL_SUCCESS)
+                return ret;
+            ret = 0;
+        }
+    #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && HAVE_SUPPORTED_CURVES */
+
+        #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22)
+            if (ssl->certHashSigAlgoSz > 0) {
+                WOLFSSL_MSG("Adding signature algorithms cert extension");
+                if ((ret = TLSX_SetSignatureAlgorithmsCert(&ssl->extensions,
+                                                        ssl, ssl->heap)) != 0) {
+                    return ret;
+                }
+            }
+        #endif /* !WOLFSSL_TLS13_DRAFT_18 && !WOLFSSL_TLS13_DRAFT_22 */
+
+            if (TLSX_Find(ssl->extensions, TLSX_KEY_SHARE) == NULL) {
+                word16 namedGroup;
+
+        #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+                if (ssl->options.resuming && ssl->session.namedGroup != 0)
+                    namedGroup = ssl->session.namedGroup;
+                else
+        #endif
+                {
+        #if defined(HAVE_ECC) && (!defined(NO_ECC256) || \
+                              defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP)
+                    namedGroup = WOLFSSL_ECC_SECP256R1;
+        #elif defined(HAVE_CURVE25519)
+                    namedGroup = WOLFSSL_ECC_X25519;
+        #elif defined(HAVE_CURVE448)
+                    namedGroup = WOLFSSL_ECC_X448;
+        #elif defined(HAVE_ECC) && (!defined(NO_ECC384) || \
+                              defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP)
+                    namedGroup = WOLFSSL_ECC_SECP384R1;
+        #elif defined(HAVE_ECC) && (!defined(NO_ECC521) || \
+                              defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP)
+                    namedGroup = WOLFSSL_ECC_SECP521R1;
+        #elif defined(HAVE_FFDHE_2048)
+                    namedGroup = WOLFSSL_FFDHE_2048;
+        #elif defined(HAVE_FFDHE_3072)
+                    namedGroup = WOLFSSL_FFDHE_3072;
+        #elif defined(HAVE_FFDHE_4096)
+                    namedGroup = WOLFSSL_FFDHE_4096;
+        #elif defined(HAVE_FFDHE_6144)
+                    namedGroup = WOLFSSL_FFDHE_6144;
+        #elif defined(HAVE_FFDHE_8192)
+                    namedGroup = WOLFSSL_FFDHE_8192;
+        #else
+                    return KEY_SHARE_ERROR;
+        #endif
+                }
+                ret = TLSX_KeyShare_Use(ssl, namedGroup, 0, NULL, NULL);
+                if (ret != 0)
+                    return ret;
+            }
+
+        #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+            TLSX_Remove(&ssl->extensions, TLSX_PRE_SHARED_KEY, ssl->heap);
+        #endif
+        #if defined(HAVE_SESSION_TICKET)
+            if (ssl->options.resuming && ssl->session.ticketLen > 0) {
+                WOLFSSL_SESSION* sess = &ssl->session;
+                word32           milli;
+
+                if (sess->ticketLen > MAX_PSK_ID_LEN) {
+                    WOLFSSL_MSG("Session ticket length for PSK ext is too large");
+                    return BUFFER_ERROR;
+                }
+
+                /* Determine the MAC algorithm for the cipher suite used. */
+                ssl->options.cipherSuite0 = sess->cipherSuite0;
+                ssl->options.cipherSuite  = sess->cipherSuite;
+                ret = SetCipherSpecs(ssl);
+                if (ret != 0)
+                    return ret;
+                milli = TimeNowInMilliseconds() - sess->ticketSeen +
+                        sess->ticketAdd;
+                /* Pre-shared key is mandatory extension for resumption. */
+                ret = TLSX_PreSharedKey_Use(ssl, sess->ticket, sess->ticketLen,
+                                            milli, ssl->specs.mac_algorithm,
+                                            ssl->options.cipherSuite0,
+                                            ssl->options.cipherSuite, 1,
+                                            NULL);
+                if (ret != 0)
+                    return ret;
+
+                usingPSK = 1;
+            }
+        #endif
+        #ifndef NO_PSK
+            if (ssl->options.client_psk_cb != NULL ||
+                                     ssl->options.client_psk_tls13_cb != NULL) {
+                /* Default ciphersuite. */
+                byte cipherSuite0 = TLS13_BYTE;
+                byte cipherSuite = WOLFSSL_DEF_PSK_CIPHER;
+                const char* cipherName = NULL;
+
+                if (ssl->options.client_psk_tls13_cb != NULL) {
+                    ssl->arrays->psk_keySz = ssl->options.client_psk_tls13_cb(
+                        ssl, ssl->arrays->server_hint,
+                        ssl->arrays->client_identity, MAX_PSK_ID_LEN,
+                        ssl->arrays->psk_key, MAX_PSK_KEY_LEN, &cipherName);
+                    if (GetCipherSuiteFromName(cipherName, &cipherSuite0,
+                                                           &cipherSuite) != 0) {
+                        return PSK_KEY_ERROR;
+                    }
+                }
+                else {
+                    ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl,
+                        ssl->arrays->server_hint, ssl->arrays->client_identity,
+                        MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN);
+                }
+                if (ssl->arrays->psk_keySz == 0 ||
+                                     ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
+                    return PSK_KEY_ERROR;
+                }
+                ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0';
+                /* TODO: Callback should be able to change ciphersuite. */
+                ssl->options.cipherSuite0 = cipherSuite0;
+                ssl->options.cipherSuite  = cipherSuite;
+                ret = SetCipherSpecs(ssl);
+                if (ret != 0)
+                    return ret;
+
+                ret = TLSX_PreSharedKey_Use(ssl,
+                                  (byte*)ssl->arrays->client_identity,
+                                  (word16)XSTRLEN(ssl->arrays->client_identity),
+                                  0, ssl->specs.mac_algorithm,
+                                  cipherSuite0, cipherSuite, 0,
+                                  NULL);
+                if (ret != 0)
+                    return ret;
+
+                usingPSK = 1;
+            }
+        #endif
+        #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+            if (usingPSK) {
+                byte modes;
+
+                /* Pre-shared key modes: mandatory extension for resumption. */
+                modes = 1 << PSK_KE;
+            #if !defined(NO_DH) || defined(HAVE_ECC) || \
+                              defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
+                if (!ssl->options.noPskDheKe)
+                    modes |= 1 << PSK_DHE_KE;
+            #endif
+                ret = TLSX_PskKeModes_Use(ssl, modes);
+                if (ret != 0)
+                    return ret;
+            }
+        #endif
+        #if defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+            if (!isServer && ssl->options.postHandshakeAuth) {
+                ret = TLSX_PostHandAuth_Use(ssl);
+                if (ret != 0)
+                    return ret;
+            }
+        #endif
+        }
+
+    #endif
+
+    (void)isServer;
+    (void)public_key;
+    (void)public_key_len;
+    (void)ssl;
+
+    return ret;
+}
+
+
+#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_CLIENT)
+
+/** Tells the buffered size of extensions to be sent into the client hello. */
+int TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType, word16* pLength)
+{
+    int ret = 0;
+    word16 length = 0;
+    byte semaphore[SEMAPHORE_SIZE] = {0};
+
+    if (!TLSX_SupportExtensions(ssl))
+        return 0;
+    if (msgType == client_hello) {
+        EC_VALIDATE_REQUEST(ssl, semaphore);
+        PF_VALIDATE_REQUEST(ssl, semaphore);
+        QSH_VALIDATE_REQUEST(ssl, semaphore);
+        WOLF_STK_VALIDATE_REQUEST(ssl);
+#if !defined(WOLFSSL_NO_SIGALG)
+        if (ssl->suites->hashSigAlgoSz == 0)
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS));
+#endif
+#if defined(WOLFSSL_TLS13)
+        if (!IsAtLeastTLSv1_2(ssl))
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
+        if (!IsAtLeastTLSv1_3(ssl->version)) {
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
+    #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PSK_KEY_EXCHANGE_MODES));
+    #endif
+    #ifdef WOLFSSL_EARLY_DATA
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA));
+    #endif
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_COOKIE));
+    #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_POST_HANDSHAKE_AUTH));
+    #endif
+        }
+#endif
+    #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+     || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+        if (!ssl->ctx->cm->ocspStaplingEnabled) {
+            /* mark already sent, so it won't send it */
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST_V2));
+        }
+    #endif
+    }
+
+#ifdef WOLFSSL_TLS13
+    #ifndef NO_CERTS
+    else if (msgType == certificate_request) {
+        XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
+#if !defined(WOLFSSL_NO_SIGALG)
+        TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS));
+#endif
+        /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP,
+         *       TLSX_CERTIFICATE_AUTHORITIES, OID_FILTERS
+         *       TLSX_STATUS_REQUEST
+         */
+    }
+    #endif
+#endif
+    if (ssl->extensions) {
+        ret = TLSX_GetSize(ssl->extensions, semaphore, msgType, &length);
+        if (ret != 0)
+            return ret;
+    }
+    if (ssl->ctx && ssl->ctx->extensions) {
+        ret = TLSX_GetSize(ssl->ctx->extensions, semaphore, msgType, &length);
+        if (ret != 0)
+            return ret;
+    }
+
+#ifdef HAVE_EXTENDED_MASTER
+    if (msgType == client_hello && ssl->options.haveEMS &&
+                  (!IsAtLeastTLSv1_3(ssl->version) || ssl->options.downgrade)) {
+        length += HELLO_EXT_SZ;
+    }
+#endif
+
+    if (length)
+        length += OPAQUE16_LEN; /* for total length storage. */
+
+    *pLength += length;
+
+    return ret;
+}
+
+/** Writes the extensions to be sent into the client hello. */
+int TLSX_WriteRequest(WOLFSSL* ssl, byte* output, byte msgType, word16* pOffset)
+{
+    int ret = 0;
+    word16 offset = 0;
+    byte semaphore[SEMAPHORE_SIZE] = {0};
+
+    if (!TLSX_SupportExtensions(ssl) || output == NULL)
+        return 0;
+
+    offset += OPAQUE16_LEN; /* extensions length */
+
+    if (msgType == client_hello) {
+        EC_VALIDATE_REQUEST(ssl, semaphore);
+        PF_VALIDATE_REQUEST(ssl, semaphore);
+        WOLF_STK_VALIDATE_REQUEST(ssl);
+        QSH_VALIDATE_REQUEST(ssl, semaphore);
+#if !defined(WOLFSSL_NO_SIGALG)
+        if (ssl->suites->hashSigAlgoSz == 0)
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS));
+#endif
+#ifdef WOLFSSL_TLS13
+        if (!IsAtLeastTLSv1_2(ssl))
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
+        if (!IsAtLeastTLSv1_3(ssl->version)) {
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
+    #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PSK_KEY_EXCHANGE_MODES));
+    #endif
+    #ifdef WOLFSSL_EARLY_DATA
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA));
+    #endif
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_COOKIE));
+    #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_POST_HANDSHAKE_AUTH));
+    #endif
+        }
+    #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+        /* Must write Pre-shared Key extension at the end in TLS v1.3.
+         * Must not write out Pre-shared Key extension in earlier versions of
+         * protocol.
+         */
+        TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
+    #endif
+#endif
+    #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+     || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+         /* mark already sent, so it won't send it */
+        if (!ssl->ctx->cm->ocspStaplingEnabled) {
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST_V2));
+        }
+    #endif
+    }
+#ifdef WOLFSSL_TLS13
+    #ifndef NO_CERTS
+    else if (msgType == certificate_request) {
+        XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
+#if !defined(WOLFSSL_NO_SIGALG)
+        TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS));
+#endif
+        /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP,
+         *       TLSX_CERTIFICATE_AUTHORITIES, TLSX_OID_FILTERS
+         *       TLSX_STATUS_REQUEST
+         */
+    }
+    #endif
+#endif
+    if (ssl->extensions) {
+        ret = TLSX_Write(ssl->extensions, output + offset, semaphore,
+                         msgType, &offset);
+        if (ret != 0)
+            return ret;
+    }
+    if (ssl->ctx && ssl->ctx->extensions) {
+        ret = TLSX_Write(ssl->ctx->extensions, output + offset, semaphore,
+                         msgType, &offset);
+        if (ret != 0)
+            return ret;
+    }
+
+#ifdef HAVE_EXTENDED_MASTER
+    if (msgType == client_hello && ssl->options.haveEMS &&
+                  (!IsAtLeastTLSv1_3(ssl->version) || ssl->options.downgrade)) {
+        WOLFSSL_MSG("EMS extension to write");
+        c16toa(HELLO_EXT_EXTMS, output + offset);
+        offset += HELLO_EXT_TYPE_SZ;
+        c16toa(0, output + offset);
+        offset += HELLO_EXT_SZ_SZ;
+    }
+#endif
+
+#ifdef WOLFSSL_TLS13
+    #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+    if (msgType == client_hello && IsAtLeastTLSv1_3(ssl->version)) {
+        /* Write out what we can of Pre-shared key extension.  */
+        TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
+        ret = TLSX_Write(ssl->extensions, output + offset, semaphore,
+                         client_hello, &offset);
+        if (ret != 0)
+            return ret;
+    }
+    #endif
+#endif
+
+    if (offset > OPAQUE16_LEN || msgType != client_hello)
+        c16toa(offset - OPAQUE16_LEN, output); /* extensions length */
+
+     *pOffset += offset;
+
+    return ret;
+}
+
+#endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */
+
+#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_SERVER)
+
+/** Tells the buffered size of extensions to be sent into the server hello. */
+int TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType, word16* pLength)
+{
+    int ret = 0;
+    word16 length = 0;
+    byte semaphore[SEMAPHORE_SIZE] = {0};
+
+    switch (msgType) {
+#ifndef NO_WOLFSSL_SERVER
+        case server_hello:
+            PF_VALIDATE_RESPONSE(ssl, semaphore);
+    #ifdef WOLFSSL_TLS13
+                if (IsAtLeastTLSv1_3(ssl->version)) {
+                    XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
+        #ifndef WOLFSSL_TLS13_DRAFT_18
+                    TURN_OFF(semaphore,
+                                     TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
+        #endif
+                    if (!ssl->options.noPskDheKe)
+                        TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
+        #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+                    TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
+        #endif
+                }
+                else {
+                    TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
+        #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+                    TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
+        #endif
+                }
+    #endif
+            break;
+
+    #ifdef WOLFSSL_TLS13
+        case hello_retry_request:
+            XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
+        #ifndef WOLFSSL_TLS13_DRAFT_18
+                TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
+        #endif
+            if (!ssl->options.noPskDheKe)
+                TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
+            TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_COOKIE));
+            break;
+    #endif
+
+    #ifdef WOLFSSL_TLS13
+        case encrypted_extensions:
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS));
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SESSION_TICKET));
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
+        #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
+        #endif
+        #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
+        #endif
+        #if defined(HAVE_SECURE_RENEGOTIATION)
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_RENEGOTIATION_INFO));
+        #endif
+            break;
+
+        #ifdef WOLFSSL_EARLY_DATA
+        case session_ticket:
+            if (ssl->options.tls1_3) {
+                XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
+                TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA));
+            }
+            break;
+        #endif
+    #endif
+#endif
+
+#ifdef WOLFSSL_TLS13
+    #ifndef NO_CERTS
+        case certificate:
+            XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
+            TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
+            /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP,
+             *       TLSX_SERVER_CERTIFICATE_TYPE
+             */
+            break;
+    #endif
+#endif
+    }
+
+    #ifdef HAVE_QSH
+        /* change response if not using TLS_QSH */
+        if (!ssl->options.haveQSH) {
+            TLSX* ext = TLSX_Find(ssl->extensions, TLSX_QUANTUM_SAFE_HYBRID);
+            if (ext)
+                ext->resp = 0;
+        }
+    #endif
+
+#ifdef HAVE_EXTENDED_MASTER
+    if (ssl->options.haveEMS && msgType == server_hello &&
+                                              !IsAtLeastTLSv1_3(ssl->version)) {
+        length += HELLO_EXT_SZ;
+    }
+#endif
+
+    if (TLSX_SupportExtensions(ssl)) {
+        ret = TLSX_GetSize(ssl->extensions, semaphore, msgType, &length);
+        if (ret != 0)
+            return ret;
+    }
+
+    /* All the response data is set at the ssl object only, so no ctx here. */
+
+    if (length || msgType != server_hello)
+        length += OPAQUE16_LEN; /* for total length storage. */
+
+    *pLength += length;
+
+    return ret;
+}
+
+/** Writes the server hello extensions into a buffer. */
+int TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType, word16* pOffset)
+{
+    int ret = 0;
+    word16 offset = 0;
+
+    if (TLSX_SupportExtensions(ssl) && output) {
+        byte semaphore[SEMAPHORE_SIZE] = {0};
+
+        switch (msgType) {
+#ifndef NO_WOLFSSL_SERVER
+            case server_hello:
+                PF_VALIDATE_RESPONSE(ssl, semaphore);
+    #ifdef WOLFSSL_TLS13
+                if (IsAtLeastTLSv1_3(ssl->version)) {
+                    XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
+        #ifndef WOLFSSL_TLS13_DRAFT_18
+                    TURN_OFF(semaphore,
+                                     TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
+        #endif
+                    if (!ssl->options.noPskDheKe)
+                        TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
+        #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+                    TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
+        #endif
+                }
+                else {
+                    TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
+        #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+                    TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
+        #endif
+                }
+    #endif
+                break;
+
+    #ifdef WOLFSSL_TLS13
+            case hello_retry_request:
+                XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
+        #ifndef WOLFSSL_TLS13_DRAFT_18
+                TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
+        #endif
+                if (!ssl->options.noPskDheKe)
+                    TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
+                /* Cookie is written below as last extension. */
+                break;
+    #endif
+
+    #ifdef WOLFSSL_TLS13
+            case encrypted_extensions:
+                TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS));
+                TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
+                TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SESSION_TICKET));
+                TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
+        #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+                TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
+        #endif
+        #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+                TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
+        #endif
+        #if defined(HAVE_SECURE_RENEGOTIATION)
+            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_RENEGOTIATION_INFO));
+        #endif
+                break;
+
+        #ifdef WOLFSSL_EARLY_DATA
+            case session_ticket:
+                if (ssl->options.tls1_3) {
+                    XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
+                    TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA));
+                }
+                break;
+        #endif
+    #endif
+#endif
+
+    #ifdef WOLFSSL_TLS13
+        #ifndef NO_CERTS
+            case certificate:
+                XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
+                TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
+                /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP,
+                 *       TLSX_SERVER_CERTIFICATE_TYPE
+                 */
+                break;
+        #endif
+    #endif
+        }
+
+        offset += OPAQUE16_LEN; /* extensions length */
+
+        ret = TLSX_Write(ssl->extensions, output + offset, semaphore,
+                         msgType, &offset);
+        if (ret != 0)
+            return ret;
+
+#ifdef WOLFSSL_TLS13
+        if (msgType == hello_retry_request) {
+            XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
+            TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_COOKIE));
+            ret = TLSX_Write(ssl->extensions, output + offset, semaphore,
+                             msgType, &offset);
+            if (ret != 0)
+                return ret;
+        }
+#endif
+
+#ifdef HAVE_EXTENDED_MASTER
+        if (ssl->options.haveEMS && msgType == server_hello &&
+                                              !IsAtLeastTLSv1_3(ssl->version)) {
+            WOLFSSL_MSG("EMS extension to write");
+            c16toa(HELLO_EXT_EXTMS, output + offset);
+            offset += HELLO_EXT_TYPE_SZ;
+            c16toa(0, output + offset);
+            offset += HELLO_EXT_SZ_SZ;
+        }
+#endif
+
+        if (offset > OPAQUE16_LEN || msgType != server_hello)
+            c16toa(offset - OPAQUE16_LEN, output); /* extensions length */
+    }
+
+    if (pOffset)
+        *pOffset += offset;
+
+    return ret;
+}
+
+#endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_SERVER */
+
+#ifdef WOLFSSL_TLS13
+int TLSX_ParseVersion(WOLFSSL* ssl, byte* input, word16 length, byte msgType,
+                      int* found)
+{
+    int ret = 0;
+    int offset = 0;
+
+    *found = 0;
+    while (offset < (int)length) {
+        word16 type;
+        word16 size;
+
+        if (offset + (2 * OPAQUE16_LEN) > length) {
+            ret = BUFFER_ERROR;
+            break;
+        }
+
+        ato16(input + offset, &type);
+        offset += HELLO_EXT_TYPE_SZ;
+
+        ato16(input + offset, &size);
+        offset += OPAQUE16_LEN;
+
+        if (offset + size > length) {
+            ret = BUFFER_ERROR;
+            break;
+        }
+
+        if (type == TLSX_SUPPORTED_VERSIONS) {
+            *found = 1;
+
+            WOLFSSL_MSG("Supported Versions extension received");
+
+            ret = SV_PARSE(ssl, input + offset, size, msgType);
+            break;
+        }
+
+        offset += size;
+    }
+
+    return ret;
+}
+#endif
+
+/** Parses a buffer of TLS extensions. */
+int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType,
+                                                                 Suites *suites)
+{
+    int ret = 0;
+    word16 offset = 0;
+    byte isRequest = (msgType == client_hello ||
+                      msgType == certificate_request);
+
+#ifdef HAVE_EXTENDED_MASTER
+    byte pendingEMS = 0;
+#endif
+#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK))
+    int pskDone = 0;
+#endif
+
+    if (!ssl || !input || (isRequest && !suites))
+        return BAD_FUNC_ARG;
+
+    while (ret == 0 && offset < length) {
+        word16 type;
+        word16 size;
+
+#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK))
+        if (msgType == client_hello && pskDone)
+            return PSK_KEY_ERROR;
+#endif
+
+        if (length - offset < HELLO_EXT_TYPE_SZ + OPAQUE16_LEN)
+            return BUFFER_ERROR;
+
+        ato16(input + offset, &type);
+        offset += HELLO_EXT_TYPE_SZ;
+
+        ato16(input + offset, &size);
+        offset += OPAQUE16_LEN;
+
+        if (offset + size > length)
+            return BUFFER_ERROR;
+
+        switch (type) {
+            case TLSX_SERVER_NAME:
+                WOLFSSL_MSG("SNI extension received");
+            #ifdef WOLFSSL_DEBUG_TLS
+                WOLFSSL_BUFFER(input + offset, size);
+            #endif
+
+#ifdef WOLFSSL_TLS13
+                if (IsAtLeastTLSv1_3(ssl->version) &&
+                        msgType != client_hello &&
+                        msgType != server_hello &&
+                        msgType != encrypted_extensions) {
+                    return EXT_NOT_ALLOWED;
+                }
+                else if (!IsAtLeastTLSv1_3(ssl->version) &&
+                         msgType == encrypted_extensions) {
+                    return EXT_NOT_ALLOWED;
+                }
+#endif
+                ret = SNI_PARSE(ssl, input + offset, size, isRequest);
+                break;
+
+            case TLSX_TRUSTED_CA_KEYS:
+                WOLFSSL_MSG("Trusted CA extension received");
+            #ifdef WOLFSSL_DEBUG_TLS
+                WOLFSSL_BUFFER(input + offset, size);
+            #endif
+
+#ifdef WOLFSSL_TLS13
+                if (IsAtLeastTLSv1_3(ssl->version) &&
+                        msgType != client_hello &&
+                        msgType != encrypted_extensions) {
+                    return EXT_NOT_ALLOWED;
+                }
+#endif
+                ret = TCA_PARSE(ssl, input + offset, size, isRequest);
+                break;
+
+            case TLSX_MAX_FRAGMENT_LENGTH:
+                WOLFSSL_MSG("Max Fragment Length extension received");
+            #ifdef WOLFSSL_DEBUG_TLS
+                WOLFSSL_BUFFER(input + offset, size);
+            #endif
+
+#ifdef WOLFSSL_TLS13
+                if (IsAtLeastTLSv1_3(ssl->version) &&
+                        msgType != client_hello &&
+                        msgType != encrypted_extensions) {
+                    return EXT_NOT_ALLOWED;
+                }
+                else if (!IsAtLeastTLSv1_3(ssl->version) &&
+                         msgType == encrypted_extensions) {
+                    return EXT_NOT_ALLOWED;
+                }
+#endif
+                ret = MFL_PARSE(ssl, input + offset, size, isRequest);
+                break;
+
+            case TLSX_TRUNCATED_HMAC:
+                WOLFSSL_MSG("Truncated HMAC extension received");
+            #ifdef WOLFSSL_DEBUG_TLS
+                WOLFSSL_BUFFER(input + offset, size);
+            #endif
+
+#ifdef WOLFSSL_TLS13
+                if (IsAtLeastTLSv1_3(ssl->version))
+                    break;
+#endif
+                ret = THM_PARSE(ssl, input + offset, size, isRequest);
+                break;
+
+            case TLSX_SUPPORTED_GROUPS:
+                WOLFSSL_MSG("Supported Groups extension received");
+            #ifdef WOLFSSL_DEBUG_TLS
+                WOLFSSL_BUFFER(input + offset, size);
+            #endif
+
+#ifdef WOLFSSL_TLS13
+                if (IsAtLeastTLSv1_3(ssl->version) &&
+                        msgType != client_hello &&
+                        msgType != server_hello &&
+                        msgType != encrypted_extensions) {
+                    return EXT_NOT_ALLOWED;
+                }
+                else if (!IsAtLeastTLSv1_3(ssl->version) &&
+                         msgType == encrypted_extensions) {
+                    return EXT_NOT_ALLOWED;
+                }
+#endif
+                ret = EC_PARSE(ssl, input + offset, size, isRequest);
+                break;
+
+            case TLSX_EC_POINT_FORMATS:
+                WOLFSSL_MSG("Point Formats extension received");
+            #ifdef WOLFSSL_DEBUG_TLS
+                WOLFSSL_BUFFER(input + offset, size);
+            #endif
+
+#ifdef WOLFSSL_TLS13
+                if (IsAtLeastTLSv1_3(ssl->version))
+                    break;
+#endif
+                ret = PF_PARSE(ssl, input + offset, size, isRequest);
+                break;
+
+            case TLSX_STATUS_REQUEST:
+                WOLFSSL_MSG("Certificate Status Request extension received");
+            #ifdef WOLFSSL_DEBUG_TLS
+                WOLFSSL_BUFFER(input + offset, size);
+            #endif
+
+ #ifdef WOLFSSL_TLS13
+                if (IsAtLeastTLSv1_3(ssl->version) &&
+                        msgType != client_hello &&
+                        msgType != certificate_request &&
+                        msgType != certificate) {
+                     break;
+                }
+ #endif
+                ret = CSR_PARSE(ssl, input + offset, size, isRequest);
+                break;
+
+            case TLSX_STATUS_REQUEST_V2:
+                WOLFSSL_MSG("Certificate Status Request v2 extension received");
+            #ifdef WOLFSSL_DEBUG_TLS
+                WOLFSSL_BUFFER(input + offset, size);
+            #endif
+
+#ifdef WOLFSSL_TLS13
+                if (IsAtLeastTLSv1_3(ssl->version) &&
+                        msgType != client_hello &&
+                        msgType != certificate_request &&
+                        msgType != certificate) {
+                    return EXT_NOT_ALLOWED;
+                }
+#endif
+                ret = CSR2_PARSE(ssl, input + offset, size, isRequest);
+                break;
+
+#ifdef HAVE_EXTENDED_MASTER
+            case HELLO_EXT_EXTMS:
+                WOLFSSL_MSG("Extended Master Secret extension received");
+            #ifdef WOLFSSL_DEBUG_TLS
+                WOLFSSL_BUFFER(input + offset, size);
+            #endif
+
+#ifdef WOLFSSL_TLS13
+                if (IsAtLeastTLSv1_3(ssl->version))
+                    break;
+#endif
+                if (size != 0)
+                    return BUFFER_ERROR;
+
+#ifndef NO_WOLFSSL_SERVER
+                if (isRequest)
+                    ssl->options.haveEMS = 1;
+#endif
+                pendingEMS = 1;
+                break;
+#endif
+
+            case TLSX_RENEGOTIATION_INFO:
+                WOLFSSL_MSG("Secure Renegotiation extension received");
+            #ifdef WOLFSSL_DEBUG_TLS
+                WOLFSSL_BUFFER(input + offset, size);
+            #endif
+
+#ifdef WOLFSSL_TLS13
+                if (IsAtLeastTLSv1_3(ssl->version))
+                    break;
+#endif
+                ret = SCR_PARSE(ssl, input + offset, size, isRequest);
+                break;
+
+            case TLSX_SESSION_TICKET:
+                WOLFSSL_MSG("Session Ticket extension received");
+            #ifdef WOLFSSL_DEBUG_TLS
+                WOLFSSL_BUFFER(input + offset, size);
+            #endif
+
+#ifdef WOLFSSL_TLS13
+                if (IsAtLeastTLSv1_3(ssl->version) &&
+                        msgType != client_hello) {
+                    return EXT_NOT_ALLOWED;
+                }
+#endif
+                ret = WOLF_STK_PARSE(ssl, input + offset, size, isRequest);
+                break;
+
+            case TLSX_QUANTUM_SAFE_HYBRID:
+                WOLFSSL_MSG("Quantum-Safe-Hybrid extension received");
+            #ifdef WOLFSSL_DEBUG_TLS
+                WOLFSSL_BUFFER(input + offset, size);
+            #endif
+
+#ifdef WOLFSSL_TLS13
+                if (IsAtLeastTLSv1_3(ssl->version))
+                    break;
+#endif
+                ret = QSH_PARSE(ssl, input + offset, size, isRequest);
+                break;
+
+            case TLSX_APPLICATION_LAYER_PROTOCOL:
+                WOLFSSL_MSG("ALPN extension received");
+
+            #ifdef WOLFSSL_DEBUG_TLS
+                WOLFSSL_BUFFER(input + offset, size);
+            #endif
+
+#ifdef WOLFSSL_TLS13
+                if (IsAtLeastTLSv1_3(ssl->version) &&
+                        msgType != client_hello &&
+                        msgType != server_hello &&
+                        msgType != encrypted_extensions) {
+                    return EXT_NOT_ALLOWED;
+                }
+                else if (!IsAtLeastTLSv1_3(ssl->version) &&
+                         msgType == encrypted_extensions) {
+                    return EXT_NOT_ALLOWED;
+                }
+#endif
+                ret = ALPN_PARSE(ssl, input + offset, size, isRequest);
+                break;
+#if !defined(WOLFSSL_NO_SIGALG)
+            case TLSX_SIGNATURE_ALGORITHMS:
+                WOLFSSL_MSG("Signature Algorithms extension received");
+            #ifdef WOLFSSL_DEBUG_TLS
+                WOLFSSL_BUFFER(input + offset, size);
+            #endif
+
+                if (!IsAtLeastTLSv1_2(ssl))
+                    break;
+#ifdef WOLFSSL_TLS13
+                if (IsAtLeastTLSv1_3(ssl->version) &&
+                        msgType != client_hello &&
+                        msgType != certificate_request) {
+                    return EXT_NOT_ALLOWED;
+                }
+#endif
+                ret = SA_PARSE(ssl, input + offset, size, isRequest, suites);
+                break;
+#endif
+
+#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+            case TLSX_ENCRYPT_THEN_MAC:
+                WOLFSSL_MSG("Encrypt-Then-Mac extension received");
+
+                /* Ignore for TLS 1.3+ */
+                if (IsAtLeastTLSv1_3(ssl->version))
+                    break;
+
+                ret = ETM_PARSE(ssl, input + offset, size, msgType);
+                break;
+#endif /* HAVE_ENCRYPT_THEN_MAC */
+
+#ifdef WOLFSSL_TLS13
+            case TLSX_SUPPORTED_VERSIONS:
+                WOLFSSL_MSG("Skipping Supported Versions - already processed");
+            #ifdef WOLFSSL_DEBUG_TLS
+                WOLFSSL_BUFFER(input + offset, size);
+            #endif
+
+                break;
+
+            case TLSX_COOKIE:
+                WOLFSSL_MSG("Cookie extension received");
+            #ifdef WOLFSSL_DEBUG_TLS
+                WOLFSSL_BUFFER(input + offset, size);
+            #endif
+
+                if (!IsAtLeastTLSv1_3(ssl->version))
+                    break;
+
+                if (msgType != client_hello &&
+                        msgType != hello_retry_request) {
+                    return EXT_NOT_ALLOWED;
+                }
+
+                ret = CKE_PARSE(ssl, input + offset, size, msgType);
+                break;
+
+    #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+            case TLSX_PRE_SHARED_KEY:
+                WOLFSSL_MSG("Pre-Shared Key extension received");
+            #ifdef WOLFSSL_DEBUG_TLS
+                WOLFSSL_BUFFER(input + offset, size);
+            #endif
+
+                if (!IsAtLeastTLSv1_3(ssl->version))
+                    break;
+
+                if (msgType != client_hello && msgType != server_hello)
+                    return EXT_NOT_ALLOWED;
+
+                ret = PSK_PARSE(ssl, input + offset, size, msgType);
+                pskDone = 1;
+                break;
+
+            case TLSX_PSK_KEY_EXCHANGE_MODES:
+                WOLFSSL_MSG("PSK Key Exchange Modes extension received");
+            #ifdef WOLFSSL_DEBUG_TLS
+                WOLFSSL_BUFFER(input + offset, size);
+            #endif
+
+                if (!IsAtLeastTLSv1_3(ssl->version))
+                    break;
+
+                if (msgType != client_hello)
+                    return EXT_NOT_ALLOWED;
+
+                ret = PKM_PARSE(ssl, input + offset, size, msgType);
+                break;
+    #endif
+
+    #ifdef WOLFSSL_EARLY_DATA
+            case TLSX_EARLY_DATA:
+                WOLFSSL_MSG("Early Data extension received");
+            #ifdef WOLFSSL_DEBUG_TLS
+                WOLFSSL_BUFFER(input + offset, size);
+            #endif
+
+                if (!IsAtLeastTLSv1_3(ssl->version))
+                    break;
+
+                if (msgType != client_hello && msgType != session_ticket &&
+                        msgType != encrypted_extensions) {
+                    return EXT_NOT_ALLOWED;
+                }
+                if (!IsAtLeastTLSv1_3(ssl->version) &&
+                        (msgType == session_ticket ||
+                         msgType == encrypted_extensions)) {
+                    return EXT_NOT_ALLOWED;
+                }
+                ret = EDI_PARSE(ssl, input + offset, size, msgType);
+                break;
+    #endif
+
+    #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
+            case TLSX_POST_HANDSHAKE_AUTH:
+                WOLFSSL_MSG("Post Handshake Authentication extension received");
+            #ifdef WOLFSSL_DEBUG_TLS
+                WOLFSSL_BUFFER(input + offset, size);
+            #endif
+
+                if (!IsAtLeastTLSv1_3(ssl->version))
+                    break;
+
+                if (msgType != client_hello)
+                    return EXT_NOT_ALLOWED;
+
+                ret = PHA_PARSE(ssl, input + offset, size, msgType);
+                break;
+    #endif
+
+    #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22)
+            case TLSX_SIGNATURE_ALGORITHMS_CERT:
+                WOLFSSL_MSG("Signature Algorithms extension received");
+            #ifdef WOLFSSL_DEBUG_TLS
+                WOLFSSL_BUFFER(input + offset, size);
+            #endif
+
+                if (!IsAtLeastTLSv1_3(ssl->version))
+                    break;
+
+                if (msgType != client_hello &&
+                        msgType != certificate_request) {
+                    return EXT_NOT_ALLOWED;
+                }
+                if (!IsAtLeastTLSv1_3(ssl->version) &&
+                        msgType == certificate_request) {
+                    return EXT_NOT_ALLOWED;
+                }
+
+                ret = SAC_PARSE(ssl, input + offset, size, isRequest);
+                break;
+    #endif
+
+            case TLSX_KEY_SHARE:
+                WOLFSSL_MSG("Key Share extension received");
+            #ifdef WOLFSSL_DEBUG_TLS
+                WOLFSSL_BUFFER(input + offset, size);
+            #endif
+
+                if (!IsAtLeastTLSv1_3(ssl->version))
+                    break;
+
+                if (msgType != client_hello && msgType != server_hello &&
+                        msgType != hello_retry_request) {
+                    return EXT_NOT_ALLOWED;
+                }
+                ret = KS_PARSE(ssl, input + offset, size, msgType);
+                break;
+#endif
+            default:
+                WOLFSSL_MSG("Unknown TLS extension type");
+        }
+
+        /* offset should be updated here! */
+        offset += size;
+    }
+
+#ifdef HAVE_EXTENDED_MASTER
+    if (!isRequest && ssl->options.haveEMS && !pendingEMS)
+        ssl->options.haveEMS = 0;
+#endif
+
+    if (ret == 0)
+        ret = SNI_VERIFY_PARSE(ssl, isRequest);
+    if (ret == 0)
+        ret = TCA_VERIFY_PARSE(ssl, isRequest);
+
+    return ret;
+}
+
+/* undefining semaphore macros */
+#undef IS_OFF
+#undef TURN_ON
+#undef SEMAPHORE_SIZE
+
+#endif /* HAVE_TLS_EXTENSIONS */
+
+#ifndef NO_WOLFSSL_CLIENT
+
+    WOLFSSL_METHOD* wolfTLS_client_method(void)
+    {
+        return wolfTLS_client_method_ex(NULL);
+    }
+    WOLFSSL_METHOD* wolfTLS_client_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* method =
+                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+                                                     heap, DYNAMIC_TYPE_METHOD);
+        (void)heap;
+        WOLFSSL_ENTER("TLS_client_method_ex");
+        if (method) {
+        #if defined(WOLFSSL_TLS13)
+            InitSSL_Method(method, MakeTLSv1_3());
+        #elif !defined(WOLFSSL_NO_TLS12)
+            InitSSL_Method(method, MakeTLSv1_2());
+        #elif !defined(NO_OLD_TLS)
+            InitSSL_Method(method, MakeTLSv1_1());
+        #elif defined(WOLFSSL_ALLOW_TLSV10)
+            InitSSL_Method(method, MakeTLSv1());
+        #else
+            #error No TLS version enabled!
+        #endif
+
+            method->downgrade = 1;
+            method->side      = WOLFSSL_CLIENT_END;
+        }
+        return method;
+    }
+
+#ifndef NO_OLD_TLS
+    #ifdef WOLFSSL_ALLOW_TLSV10
+    WOLFSSL_METHOD* wolfTLSv1_client_method(void)
+    {
+        return wolfTLSv1_client_method_ex(NULL);
+    }
+    WOLFSSL_METHOD* wolfTLSv1_client_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* method =
+                             (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+                                                     heap, DYNAMIC_TYPE_METHOD);
+        (void)heap;
+        WOLFSSL_ENTER("TLSv1_client_method_ex");
+        if (method)
+            InitSSL_Method(method, MakeTLSv1());
+        return method;
+    }
+    #endif /* WOLFSSL_ALLOW_TLSV10 */
+
+    WOLFSSL_METHOD* wolfTLSv1_1_client_method(void)
+    {
+        return wolfTLSv1_1_client_method_ex(NULL);
+    }
+    WOLFSSL_METHOD* wolfTLSv1_1_client_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* method =
+                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+                                                     heap, DYNAMIC_TYPE_METHOD);
+        (void)heap;
+        WOLFSSL_ENTER("TLSv1_1_client_method_ex");
+        if (method)
+            InitSSL_Method(method, MakeTLSv1_1());
+        return method;
+    }
+#endif /* !NO_OLD_TLS */
+
+#ifndef WOLFSSL_NO_TLS12
+    WOLFSSL_ABI
+    WOLFSSL_METHOD* wolfTLSv1_2_client_method(void)
+    {
+        return wolfTLSv1_2_client_method_ex(NULL);
+    }
+    WOLFSSL_METHOD* wolfTLSv1_2_client_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* method =
+                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+                                                     heap, DYNAMIC_TYPE_METHOD);
+        (void)heap;
+        WOLFSSL_ENTER("TLSv1_2_client_method_ex");
+        if (method)
+            InitSSL_Method(method, MakeTLSv1_2());
+        return method;
+    }
+#endif /* WOLFSSL_NO_TLS12 */
+
+#ifdef WOLFSSL_TLS13
+    /* The TLS v1.3 client method data.
+     *
+     * returns the method data for a TLS v1.3 client.
+     */
+    WOLFSSL_ABI
+    WOLFSSL_METHOD* wolfTLSv1_3_client_method(void)
+    {
+        return wolfTLSv1_3_client_method_ex(NULL);
+    }
+
+    /* The TLS v1.3 client method data.
+     *
+     * heap  The heap used for allocation.
+     * returns the method data for a TLS v1.3 client.
+     */
+    WOLFSSL_METHOD* wolfTLSv1_3_client_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* method = (WOLFSSL_METHOD*)
+                                 XMALLOC(sizeof(WOLFSSL_METHOD), heap,
+                                         DYNAMIC_TYPE_METHOD);
+        (void)heap;
+        WOLFSSL_ENTER("TLSv1_3_client_method_ex");
+        if (method)
+            InitSSL_Method(method, MakeTLSv1_3());
+        return method;
+    }
+#endif /* WOLFSSL_TLS13 */
+
+#ifdef WOLFSSL_DTLS
+
+    WOLFSSL_METHOD* wolfDTLS_client_method(void)
+    {
+        return wolfDTLS_client_method_ex(NULL);
+    }
+    WOLFSSL_METHOD* wolfDTLS_client_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* method =
+                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+                                                     heap, DYNAMIC_TYPE_METHOD);
+        (void)heap;
+        WOLFSSL_ENTER("DTLS_client_method_ex");
+        if (method) {
+        #if !defined(WOLFSSL_NO_TLS12)
+            InitSSL_Method(method, MakeDTLSv1_2());
+        #elif !defined(NO_OLD_TLS)
+            InitSSL_Method(method, MakeDTLSv1());
+        #else
+            #error No DTLS version enabled!
+        #endif
+
+            method->downgrade = 1;
+            method->side      = WOLFSSL_CLIENT_END;
+        }
+        return method;
+    }
+
+    #ifndef NO_OLD_TLS
+    WOLFSSL_METHOD* wolfDTLSv1_client_method(void)
+    {
+        return wolfDTLSv1_client_method_ex(NULL);
+    }
+    WOLFSSL_METHOD* wolfDTLSv1_client_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* method =
+                          (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+                                                 heap, DYNAMIC_TYPE_METHOD);
+        (void)heap;
+        WOLFSSL_ENTER("DTLSv1_client_method_ex");
+        if (method)
+            InitSSL_Method(method, MakeDTLSv1());
+        return method;
+    }
+    #endif  /* NO_OLD_TLS */
+
+    #ifndef WOLFSSL_NO_TLS12
+    WOLFSSL_METHOD* wolfDTLSv1_2_client_method(void)
+    {
+        return wolfDTLSv1_2_client_method_ex(NULL);
+    }
+    WOLFSSL_METHOD* wolfDTLSv1_2_client_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* method =
+                          (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+                                                 heap, DYNAMIC_TYPE_METHOD);
+        (void)heap;
+        WOLFSSL_ENTER("DTLSv1_2_client_method_ex");
+        if (method)
+            InitSSL_Method(method, MakeDTLSv1_2());
+        (void)heap;
+        return method;
+    }
+    #endif /* !WOLFSSL_NO_TLS12 */
+#endif /* WOLFSSL_DTLS */
+
+#endif /* NO_WOLFSSL_CLIENT */
+
+
+/* EITHER SIDE METHODS */
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
+    #ifndef NO_OLD_TLS
+    #ifdef WOLFSSL_ALLOW_TLSV10
+    /* Gets a WOLFSL_METHOD type that is not set as client or server
+     *
+     * Returns a pointer to a WOLFSSL_METHOD struct
+     */
+    WOLFSSL_METHOD* wolfTLSv1_method(void)
+    {
+        return wolfTLSv1_method_ex(NULL);
+    }
+    WOLFSSL_METHOD* wolfTLSv1_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* m;
+        WOLFSSL_ENTER("TLSv1_method");
+    #ifndef NO_WOLFSSL_CLIENT
+        m = wolfTLSv1_client_method_ex(heap);
+    #else
+        m = wolfTLSv1_server_method_ex(heap);
+    #endif
+        if (m != NULL) {
+            m->side = WOLFSSL_NEITHER_END;
+        }
+
+        return m;
+    }
+    #endif /* WOLFSSL_ALLOW_TLSV10 */
+
+    /* Gets a WOLFSL_METHOD type that is not set as client or server
+     *
+     * Returns a pointer to a WOLFSSL_METHOD struct
+     */
+    WOLFSSL_METHOD* wolfTLSv1_1_method(void)
+    {
+        return wolfTLSv1_1_method_ex(NULL);
+    }
+    WOLFSSL_METHOD* wolfTLSv1_1_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* m;
+        WOLFSSL_ENTER("TLSv1_1_method");
+    #ifndef NO_WOLFSSL_CLIENT
+        m = wolfTLSv1_1_client_method_ex(heap);
+    #else
+        m = wolfTLSv1_1_server_method_ex(heap);
+    #endif
+        if (m != NULL) {
+            m->side = WOLFSSL_NEITHER_END;
+        }
+        return m;
+    }
+    #endif /* !NO_OLD_TLS */
+
+    #ifndef WOLFSSL_NO_TLS12
+    /* Gets a WOLFSL_METHOD type that is not set as client or server
+     *
+     * Returns a pointer to a WOLFSSL_METHOD struct
+     */
+    WOLFSSL_METHOD* wolfTLSv1_2_method(void)
+    {
+        return wolfTLSv1_2_method_ex(NULL);
+    }
+    WOLFSSL_METHOD* wolfTLSv1_2_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* m;
+        WOLFSSL_ENTER("TLSv1_2_method");
+    #ifndef NO_WOLFSSL_CLIENT
+        m = wolfTLSv1_2_client_method_ex(heap);
+    #else
+        m = wolfTLSv1_2_server_method_ex(heap);
+    #endif
+        if (m != NULL) {
+            m->side = WOLFSSL_NEITHER_END;
+        }
+        return m;
+    }
+    #endif /* !WOLFSSL_NO_TLS12 */
+
+    #ifdef WOLFSSL_TLS13
+    /* Gets a WOLFSL_METHOD type that is not set as client or server
+     *
+     * Returns a pointer to a WOLFSSL_METHOD struct
+     */
+    WOLFSSL_METHOD* wolfTLSv1_3_method(void)
+    {
+        return wolfTLSv1_3_method_ex(NULL);
+    }
+    WOLFSSL_METHOD* wolfTLSv1_3_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* m;
+        WOLFSSL_ENTER("TLSv1_3_method");
+    #ifndef NO_WOLFSSL_CLIENT
+        m = wolfTLSv1_3_client_method_ex(heap);
+    #else
+        m = wolfTLSv1_3_server_method_ex(heap);
+    #endif
+        if (m != NULL) {
+            m->side = WOLFSSL_NEITHER_END;
+        }
+        return m;
+    }
+    #endif /* WOLFSSL_TLS13 */
+
+#ifdef WOLFSSL_DTLS
+    WOLFSSL_METHOD* wolfDTLS_method(void)
+    {
+        return wolfDTLS_method_ex(NULL);
+    }
+    WOLFSSL_METHOD* wolfDTLS_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* m;
+        WOLFSSL_ENTER("DTLS_method_ex");
+    #ifndef NO_WOLFSSL_CLIENT
+        m = wolfDTLS_client_method_ex(heap);
+    #else
+        m = wolfDTLS_server_method_ex(heap);
+    #endif
+        if (m != NULL) {
+            m->side = WOLFSSL_NEITHER_END;
+        }
+        return m;
+    }
+
+    #ifndef NO_OLD_TLS
+    WOLFSSL_METHOD* wolfDTLSv1_method(void)
+    {
+        return wolfDTLSv1_method_ex(NULL);
+    }
+    WOLFSSL_METHOD* wolfDTLSv1_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* m;
+        WOLFSSL_ENTER("DTLSv1_method_ex");
+    #ifndef NO_WOLFSSL_CLIENT
+        m = wolfDTLSv1_client_method_ex(heap);
+    #else
+        m = wolfDTLSv1_server_method_ex(heap);
+    #endif
+        if (m != NULL) {
+            m->side = WOLFSSL_NEITHER_END;
+        }
+        return m;
+    }
+    #endif /* !NO_OLD_TLS */
+    #ifndef WOLFSSL_NO_TLS12
+    WOLFSSL_METHOD* wolfDTLSv1_2_method(void)
+    {
+        return wolfDTLSv1_2_method_ex(NULL);
+    }
+    WOLFSSL_METHOD* wolfDTLSv1_2_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* m;
+        WOLFSSL_ENTER("DTLSv1_2_method");
+    #ifndef NO_WOLFSSL_CLIENT
+        m = wolfDTLSv1_2_client_method_ex(heap);
+    #else
+        m = wolfDTLSv1_2_server_method_ex(heap);
+    #endif
+        if (m != NULL) {
+            m->side = WOLFSSL_NEITHER_END;
+        }
+        return m;
+    }
+    #endif /* !WOLFSSL_NO_TLS12 */
+#endif /* WOLFSSL_DTLS */
+#endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */
+
+
+#ifndef NO_WOLFSSL_SERVER
+
+    WOLFSSL_METHOD* wolfTLS_server_method(void)
+    {
+        return wolfTLS_server_method_ex(NULL);
+    }
+
+    WOLFSSL_METHOD* wolfTLS_server_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* method =
+                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+                                                     heap, DYNAMIC_TYPE_METHOD);
+        (void)heap;
+        WOLFSSL_ENTER("TLS_server_method_ex");
+        if (method) {
+        #if defined(WOLFSSL_TLS13)
+            InitSSL_Method(method, MakeTLSv1_3());
+        #elif !defined(WOLFSSL_NO_TLS12)
+            InitSSL_Method(method, MakeTLSv1_2());
+        #elif !defined(NO_OLD_TLS)
+            InitSSL_Method(method, MakeTLSv1_1());
+        #elif defined(WOLFSSL_ALLOW_TLSV10)
+            InitSSL_Method(method, MakeTLSv1());
+        #else
+            #error No TLS version enabled!
+        #endif
+
+            method->downgrade = 1;
+            method->side      = WOLFSSL_SERVER_END;
+        }
+        return method;
+    }
+
+#ifndef NO_OLD_TLS
+    #ifdef WOLFSSL_ALLOW_TLSV10
+    WOLFSSL_METHOD* wolfTLSv1_server_method(void)
+    {
+        return wolfTLSv1_server_method_ex(NULL);
+    }
+    WOLFSSL_METHOD* wolfTLSv1_server_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* method =
+                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+                                                     heap, DYNAMIC_TYPE_METHOD);
+        (void)heap;
+        WOLFSSL_ENTER("TLSv1_server_method_ex");
+        if (method) {
+            InitSSL_Method(method, MakeTLSv1());
+            method->side = WOLFSSL_SERVER_END;
+        }
+        return method;
+    }
+    #endif /* WOLFSSL_ALLOW_TLSV10 */
+
+    WOLFSSL_METHOD* wolfTLSv1_1_server_method(void)
+    {
+        return wolfTLSv1_1_server_method_ex(NULL);
+    }
+    WOLFSSL_METHOD* wolfTLSv1_1_server_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* method =
+                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+                                                     heap, DYNAMIC_TYPE_METHOD);
+        (void)heap;
+        WOLFSSL_ENTER("TLSv1_1_server_method_ex");
+        if (method) {
+            InitSSL_Method(method, MakeTLSv1_1());
+            method->side = WOLFSSL_SERVER_END;
+        }
+        return method;
+    }
+#endif /* !NO_OLD_TLS */
+
+
+#ifndef WOLFSSL_NO_TLS12
+    WOLFSSL_METHOD* wolfTLSv1_2_server_method(void)
+    {
+        return wolfTLSv1_2_server_method_ex(NULL);
+    }
+    WOLFSSL_METHOD* wolfTLSv1_2_server_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* method =
+                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+                                                     heap, DYNAMIC_TYPE_METHOD);
+        (void)heap;
+        WOLFSSL_ENTER("TLSv1_2_server_method_ex");
+        if (method) {
+            InitSSL_Method(method, MakeTLSv1_2());
+            method->side = WOLFSSL_SERVER_END;
+        }
+        return method;
+    }
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#ifdef WOLFSSL_TLS13
+    /* The TLS v1.3 server method data.
+     *
+     * returns the method data for a TLS v1.3 server.
+     */
+    WOLFSSL_METHOD* wolfTLSv1_3_server_method(void)
+    {
+        return wolfTLSv1_3_server_method_ex(NULL);
+    }
+
+    /* The TLS v1.3 server method data.
+     *
+     * heap  The heap used for allocation.
+     * returns the method data for a TLS v1.3 server.
+     */
+    WOLFSSL_METHOD* wolfTLSv1_3_server_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* method =
+                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+                                                     heap, DYNAMIC_TYPE_METHOD);
+        (void)heap;
+        WOLFSSL_ENTER("TLSv1_3_server_method_ex");
+        if (method) {
+            InitSSL_Method(method, MakeTLSv1_3());
+            method->side = WOLFSSL_SERVER_END;
+        }
+        return method;
+    }
+#endif /* WOLFSSL_TLS13 */
+
+#ifdef WOLFSSL_DTLS
+    WOLFSSL_METHOD* wolfDTLS_server_method(void)
+    {
+        return wolfDTLS_server_method_ex(NULL);
+    }
+    WOLFSSL_METHOD* wolfDTLS_server_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* method =
+                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+                                                     heap, DYNAMIC_TYPE_METHOD);
+        (void)heap;
+        WOLFSSL_ENTER("DTLS_server_method_ex");
+        if (method) {
+        #if !defined(WOLFSSL_NO_TLS12)
+            InitSSL_Method(method, MakeDTLSv1_2());
+        #elif !defined(NO_OLD_TLS)
+            InitSSL_Method(method, MakeDTLSv1());
+        #else
+            #error No DTLS version enabled!
+        #endif
+
+            method->downgrade = 1;
+            method->side      = WOLFSSL_SERVER_END;
+        }
+        return method;
+    }
+
+    #ifndef NO_OLD_TLS
+    WOLFSSL_METHOD* wolfDTLSv1_server_method(void)
+    {
+        return wolfDTLSv1_server_method_ex(NULL);
+    }
+    WOLFSSL_METHOD* wolfDTLSv1_server_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* method =
+                          (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+                                                 heap, DYNAMIC_TYPE_METHOD);
+        (void)heap;
+        WOLFSSL_ENTER("DTLSv1_server_method_ex");
+        if (method) {
+            InitSSL_Method(method, MakeDTLSv1());
+            method->side = WOLFSSL_SERVER_END;
+        }
+        return method;
+    }
+    #endif /* !NO_OLD_TLS */
+
+    #ifndef WOLFSSL_NO_TLS12
+    WOLFSSL_METHOD* wolfDTLSv1_2_server_method(void)
+    {
+        return wolfDTLSv1_2_server_method_ex(NULL);
+    }
+    WOLFSSL_METHOD* wolfDTLSv1_2_server_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* method =
+                          (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+                                                 heap, DYNAMIC_TYPE_METHOD);
+        WOLFSSL_ENTER("DTLSv1_2_server_method_ex");
+        (void)heap;
+        if (method) {
+            InitSSL_Method(method, MakeDTLSv1_2());
+            method->side = WOLFSSL_SERVER_END;
+        }
+        (void)heap;
+        return method;
+    }
+    #endif /* !WOLFSSL_NO_TLS12 */
+#endif /* WOLFSSL_DTLS */
+
+#endif /* NO_WOLFSSL_SERVER */
+
+#endif /* NO_TLS */
+#endif /* WOLFCRYPT_ONLY */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/tls13.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/tls13.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/tls13.c	(revision 453)
@@ -0,0 +1,9048 @@
+/* tls13.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+/*
+ * BUILD_GCM
+ *    Enables AES-GCM ciphersuites.
+ * HAVE_AESCCM
+ *    Enables AES-CCM ciphersuites.
+ * HAVE_SESSION_TICKET
+ *    Enables session tickets - required for TLS 1.3 resumption.
+ * NO_PSK
+ *    Do not enable Pre-Shared Keys.
+ * TLS13_SUPPORTS_EXPORTERS
+ *    Guard to compile out any code for exporter keys.
+ *    Feature not supported yet.
+ * WOLFSSL_ASYNC_CRYPT
+ *    Enables the use of asynchronous cryptographic operations.
+ *    This is available for ciphers and certificates.
+ * HAVE_CHACHA && HAVE_POLY1305
+ *    Enables use of CHACHA20-POLY1305 ciphersuites.
+ * WOLFSSL_DEBUG_TLS
+ *    Writes out details of TLS 1.3 protocol including handshake message buffers
+ *    and key generation input and output.
+ * WOLFSSL_EARLY_DATA
+ *    Allow 0-RTT Handshake using Early Data extensions and handshake message
+ * WOLFSSL_EARLY_DATA_GROUP
+ *    Group EarlyData message with ClientHello when sending
+ * WOLFSSL_NO_SERVER_GROUPS_EXT
+ *    Do not send the server's groups in an extension when the server's top
+ *    preference is not in client's list.
+ * WOLFSSL_POST_HANDSHAKE_AUTH
+ *    Allow TLS v1.3 code to perform post-handshake authentication of the
+ *    client.
+ * WOLFSSL_SEND_HRR_COOKIE
+ *    Send a cookie in hello_retry_request message to enable stateless tracking
+ *    of ClientHello replies.
+ * WOLFSSL_TLS13
+ *    Enable TLS 1.3 protocol implementation.
+ * WOLFSSL_TLS13_DRAFT_18
+ *    Conform with Draft 18 of the TLS v1.3 specification.
+ * WOLFSSL_TLS13_DRAFT_22
+ *    Conform with Draft 22 of the TLS v1.3 specification.
+ * WOLFSSL_TLS13_DRAFT_23
+ *    Conform with Draft 23 of the TLS v1.3 specification.
+ * WOLFSSL_TLS13_MIDDLEBOX_COMPAT
+ *    Enable middlebox compatibility in the TLS 1.3 handshake.
+ *    This includes sending ChangeCipherSpec before encrypted messages and
+ *    including a session id.
+ * WOLFSSL_TLS13_SHA512
+ *    Allow generation of SHA-512 digests in handshake - no ciphersuite
+ *    requires SHA-512 at this time.
+ * WOLFSSL_TLS13_TICKET_BEFORE_FINISHED
+ *    Allow a NewSessionTicket message to be sent by server before Client's
+ *    Finished message.
+ *    See TLS v1.3 specification, Section 4.6.1, Paragraph 4 (Note).
+ */
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifdef WOLFSSL_TLS13
+#ifdef HAVE_SESSION_TICKET
+    #include <wolfssl/wolfcrypt/wc_port.h>
+#endif
+
+#ifndef WOLFCRYPT_ONLY
+
+#ifdef HAVE_ERRNO_H
+    #include <errno.h>
+#endif
+
+#include <wolfssl/internal.h>
+#include <wolfssl/error-ssl.h>
+#include <wolfssl/wolfcrypt/asn.h>
+#include <wolfssl/wolfcrypt/dh.h>
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+#ifdef HAVE_NTRU
+    #include "libntruencrypt/ntru_crypto.h"
+#endif
+
+#ifdef __sun
+    #include <sys/filio.h>
+#endif
+
+#ifndef TRUE
+    #define TRUE  1
+#endif
+#ifndef FALSE
+    #define FALSE 0
+#endif
+
+#ifndef HAVE_HKDF
+    #error The build option HAVE_HKDF is required for TLS 1.3
+#endif
+
+#ifndef HAVE_TLS_EXTENSIONS
+    #ifndef _MSC_VER
+        #error "The build option HAVE_TLS_EXTENSIONS is required for TLS 1.3"
+    #else
+        #pragma message("error: The build option HAVE_TLS_EXTENSIONS is required for TLS 1.3")
+    #endif
+#endif
+
+
+/* Set ret to error value and jump to label.
+ *
+ * err     The error value to set.
+ * eLabel  The label to jump to.
+ */
+#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; }
+
+
+/* Extract data using HMAC, salt and input.
+ * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF)
+ *
+ * prk      The generated pseudorandom key.
+ * salt     The salt.
+ * saltLen  The length of the salt.
+ * ikm      The input keying material.
+ * ikmLen   The length of the input keying material.
+ * mac      The type of digest to use.
+ * returns 0 on success, otherwise failure.
+ */
+static int Tls13_HKDF_Extract(byte* prk, const byte* salt, int saltLen,
+                             byte* ikm, int ikmLen, int mac)
+{
+    int ret;
+    int hash = 0;
+    int len = 0;
+
+    switch (mac) {
+        #ifndef NO_SHA256
+        case sha256_mac:
+            hash = WC_SHA256;
+            len = WC_SHA256_DIGEST_SIZE;
+            break;
+        #endif
+
+        #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            hash = WC_SHA384;
+            len = WC_SHA384_DIGEST_SIZE;
+            break;
+        #endif
+
+        #ifdef WOLFSSL_TLS13_SHA512
+        case sha512_mac:
+            hash = WC_SHA512;
+            len = WC_SHA512_DIGEST_SIZE;
+            break;
+        #endif
+    }
+
+    /* When length is 0 then use zeroed data of digest length. */
+    if (ikmLen == 0) {
+        ikmLen = len;
+        XMEMSET(ikm, 0, len);
+    }
+
+#ifdef WOLFSSL_DEBUG_TLS
+    WOLFSSL_MSG("  Salt");
+    WOLFSSL_BUFFER(salt, saltLen);
+    WOLFSSL_MSG("  IKM");
+    WOLFSSL_BUFFER(ikm, ikmLen);
+#endif
+
+    ret = wc_HKDF_Extract(hash, salt, saltLen, ikm, ikmLen, prk);
+
+#ifdef WOLFSSL_DEBUG_TLS
+    WOLFSSL_MSG("  PRK");
+    WOLFSSL_BUFFER(prk, len);
+#endif
+
+    return ret;
+}
+
+/* Expand data using HMAC, salt and label and info.
+ * TLS v1.3 defines this function.
+ *
+ * okm          The generated pseudorandom key - output key material.
+ * okmLen       The length of generated pseudorandom key - output key material.
+ * prk          The salt - pseudo-random key.
+ * prkLen       The length of the salt - pseudo-random key.
+ * protocol     The TLS protocol label.
+ * protocolLen  The length of the TLS protocol label.
+ * info         The information to expand.
+ * infoLen      The length of the information.
+ * digest       The type of digest to use.
+ * returns 0 on success, otherwise failure.
+ */
+static int HKDF_Expand_Label(byte* okm, word32 okmLen,
+                             const byte* prk, word32 prkLen,
+                             const byte* protocol, word32 protocolLen,
+                             const byte* label, word32 labelLen,
+                             const byte* info, word32 infoLen,
+                             int digest)
+{
+    int    ret = 0;
+    int    idx = 0;
+    byte   data[MAX_HKDF_LABEL_SZ];
+
+    /* Output length. */
+    data[idx++] = (byte)(okmLen >> 8);
+    data[idx++] = (byte)okmLen;
+    /* Length of protocol | label. */
+    data[idx++] = (byte)(protocolLen + labelLen);
+    /* Protocol */
+    XMEMCPY(&data[idx], protocol, protocolLen);
+    idx += protocolLen;
+    /* Label */
+    XMEMCPY(&data[idx], label, labelLen);
+    idx += labelLen;
+    /* Length of hash of messages */
+    data[idx++] = (byte)infoLen;
+    /* Hash of messages */
+    XMEMCPY(&data[idx], info, infoLen);
+    idx += infoLen;
+
+#ifdef WOLFSSL_DEBUG_TLS
+    WOLFSSL_MSG("  PRK");
+    WOLFSSL_BUFFER(prk, prkLen);
+    WOLFSSL_MSG("  Info");
+    WOLFSSL_BUFFER(data, idx);
+#endif
+
+    ret = wc_HKDF_Expand(digest, prk, prkLen, data, idx, okm, okmLen);
+
+#ifdef WOLFSSL_DEBUG_TLS
+    WOLFSSL_MSG("  OKM");
+    WOLFSSL_BUFFER(okm, okmLen);
+#endif
+
+    ForceZero(data, idx);
+
+    return ret;
+}
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* Size of the TLS v1.3 label use when deriving keys. */
+#define TLS13_PROTOCOL_LABEL_SZ    9
+/* The protocol label for TLS v1.3. */
+static const byte tls13ProtocolLabel[TLS13_PROTOCOL_LABEL_SZ + 1] = "TLS 1.3, ";
+#else
+/* Size of the TLS v1.3 label use when deriving keys. */
+#define TLS13_PROTOCOL_LABEL_SZ    6
+/* The protocol label for TLS v1.3. */
+static const byte tls13ProtocolLabel[TLS13_PROTOCOL_LABEL_SZ + 1] = "tls13 ";
+#endif
+
+#if !defined(WOLFSSL_TLS13_DRAFT_18) || defined(HAVE_SESSION_TICKET) || \
+                                        !defined(NO_PSK)
+/* Derive a key from a message.
+ *
+ * ssl        The SSL/TLS object.
+ * output     The buffer to hold the derived key.
+ * outputLen  The length of the derived key.
+ * secret     The secret used to derive the key (HMAC secret).
+ * label      The label used to distinguish the context.
+ * labelLen   The length of the label.
+ * msg        The message data to derive key from.
+ * msgLen     The length of the message data to derive key from.
+ * hashAlgo   The hash algorithm to use in the HMAC.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveKeyMsg(WOLFSSL* ssl, byte* output, int outputLen,
+                        const byte* secret, const byte* label, word32 labelLen,
+                        byte* msg, int msgLen, int hashAlgo)
+{
+    byte        hash[WC_MAX_DIGEST_SIZE];
+    Digest      digest;
+    word32      hashSz = 0;
+    const byte* protocol;
+    word32      protocolLen;
+    int         digestAlg = -1;
+    int         ret = BAD_FUNC_ARG;
+
+    switch (hashAlgo) {
+#ifndef NO_WOLFSSL_SHA256
+        case sha256_mac:
+            ret = wc_InitSha256_ex(&digest.sha256, ssl->heap, INVALID_DEVID);
+            if (ret == 0) {
+                    ret = wc_Sha256Update(&digest.sha256, msg, msgLen);
+                if (ret == 0)
+                    ret = wc_Sha256Final(&digest.sha256, hash);
+                wc_Sha256Free(&digest.sha256);
+            }
+            hashSz = WC_SHA256_DIGEST_SIZE;
+            digestAlg = WC_SHA256;
+            break;
+#endif
+#ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            ret = wc_InitSha384_ex(&digest.sha384, ssl->heap, INVALID_DEVID);
+            if (ret == 0) {
+                ret = wc_Sha384Update(&digest.sha384, msg, msgLen);
+                if (ret == 0)
+                    ret = wc_Sha384Final(&digest.sha384, hash);
+                wc_Sha384Free(&digest.sha384);
+            }
+            hashSz = WC_SHA384_DIGEST_SIZE;
+            digestAlg = WC_SHA384;
+            break;
+#endif
+#ifdef WOLFSSL_TLS13_SHA512
+        case sha512_mac:
+            ret = wc_InitSha512_ex(&digest.sha512, ssl->heap, INVALID_DEVID);
+            if (ret == 0) {
+                ret = wc_Sha512Update(&digest.sha512, msg, msgLen);
+                if (ret == 0)
+                    ret = wc_Sha512Final(&digest.sha512, hash);
+                wc_Sha512Free(&digest.sha512);
+            }
+            hashSz = WC_SHA512_DIGEST_SIZE;
+            digestAlg = WC_SHA512;
+            break;
+#endif
+        default:
+            digestAlg = -1;
+            break;
+    }
+
+    if (digestAlg < 0)
+        return HASH_TYPE_E;
+
+    if (ret != 0)
+        return ret;
+
+    switch (ssl->version.minor) {
+        case TLSv1_3_MINOR:
+            protocol = tls13ProtocolLabel;
+            protocolLen = TLS13_PROTOCOL_LABEL_SZ;
+            break;
+
+        default:
+            return VERSION_ERROR;
+    }
+    if (outputLen == -1)
+        outputLen = hashSz;
+
+    return HKDF_Expand_Label(output, outputLen, secret, hashSz,
+                             protocol, protocolLen, label, labelLen,
+                             hash, hashSz, digestAlg);
+}
+#endif
+
+/* Derive a key.
+ *
+ * ssl          The SSL/TLS object.
+ * output       The buffer to hold the derived key.
+ * outputLen    The length of the derived key.
+ * secret       The secret used to derive the key (HMAC secret).
+ * label        The label used to distinguish the context.
+ * labelLen     The length of the label.
+ * hashAlgo     The hash algorithm to use in the HMAC.
+ * includeMsgs  Whether to include a hash of the handshake messages so far.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveKey(WOLFSSL* ssl, byte* output, int outputLen,
+                     const byte* secret, const byte* label, word32 labelLen,
+                     int hashAlgo, int includeMsgs)
+{
+    int         ret = 0;
+    byte        hash[WC_MAX_DIGEST_SIZE];
+    word32      hashSz = 0;
+    word32      hashOutSz = 0;
+    const byte* protocol;
+    word32      protocolLen;
+    int         digestAlg = 0;
+
+    switch (hashAlgo) {
+        #ifndef NO_SHA256
+            case sha256_mac:
+                hashSz    = WC_SHA256_DIGEST_SIZE;
+                digestAlg = WC_SHA256;
+                if (includeMsgs)
+                    ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash);
+            break;
+        #endif
+
+        #ifdef WOLFSSL_SHA384
+            case sha384_mac:
+                hashSz    = WC_SHA384_DIGEST_SIZE;
+                digestAlg = WC_SHA384;
+                if (includeMsgs)
+                    ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash);
+            break;
+        #endif
+
+        #ifdef WOLFSSL_TLS13_SHA512
+            case sha512_mac:
+                hashSz    = WC_SHA512_DIGEST_SIZE;
+                digestAlg = WC_SHA512;
+                if (includeMsgs)
+                    ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash);
+            break;
+        #endif
+    }
+    if (ret != 0)
+        return ret;
+
+    /* Only one protocol version defined at this time. */
+    protocol = tls13ProtocolLabel;
+    protocolLen = TLS13_PROTOCOL_LABEL_SZ;
+
+    if (outputLen == -1)
+        outputLen = hashSz;
+    if (includeMsgs)
+        hashOutSz = hashSz;
+
+    return HKDF_Expand_Label(output, outputLen, secret, hashSz,
+                             protocol, protocolLen, label, labelLen,
+                             hash, hashOutSz, digestAlg);
+}
+
+#ifndef NO_PSK
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* The length of the binder key label. */
+#define BINDER_KEY_LABEL_SZ         23
+/* The binder key label. */
+static const byte binderKeyLabel[BINDER_KEY_LABEL_SZ + 1] =
+    "external psk binder key";
+#else
+/* The length of the binder key label. */
+#define BINDER_KEY_LABEL_SZ         10
+/* The binder key label. */
+static const byte binderKeyLabel[BINDER_KEY_LABEL_SZ + 1] =
+    "ext binder";
+#endif
+/* Derive the binder key.
+ *
+ * ssl  The SSL/TLS object.
+ * key  The derived key.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveBinderKey(WOLFSSL* ssl, byte* key)
+{
+    WOLFSSL_MSG("Derive Binder Key");
+    return DeriveKeyMsg(ssl, key, -1, ssl->arrays->secret,
+                        binderKeyLabel, BINDER_KEY_LABEL_SZ,
+                        NULL, 0, ssl->specs.mac_algorithm);
+}
+#endif /* !NO_PSK */
+
+#ifdef HAVE_SESSION_TICKET
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* The length of the binder key resume label. */
+#define BINDER_KEY_RESUME_LABEL_SZ  25
+/* The binder key resume label. */
+static const byte binderKeyResumeLabel[BINDER_KEY_RESUME_LABEL_SZ + 1] =
+    "resumption psk binder key";
+#else
+/* The length of the binder key resume label. */
+#define BINDER_KEY_RESUME_LABEL_SZ  10
+/* The binder key resume label. */
+static const byte binderKeyResumeLabel[BINDER_KEY_RESUME_LABEL_SZ + 1] =
+    "res binder";
+#endif
+/* Derive the binder resumption key.
+ *
+ * ssl  The SSL/TLS object.
+ * key  The derived key.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveBinderKeyResume(WOLFSSL* ssl, byte* key)
+{
+    WOLFSSL_MSG("Derive Binder Key - Resumption");
+    return DeriveKeyMsg(ssl, key, -1, ssl->arrays->secret,
+                        binderKeyResumeLabel, BINDER_KEY_RESUME_LABEL_SZ,
+                        NULL, 0, ssl->specs.mac_algorithm);
+}
+#endif /* HAVE_SESSION_TICKET */
+
+#ifdef WOLFSSL_EARLY_DATA
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* The length of the early traffic label. */
+#define EARLY_TRAFFIC_LABEL_SZ      27
+/* The early traffic label. */
+static const byte earlyTrafficLabel[EARLY_TRAFFIC_LABEL_SZ + 1] =
+    "client early traffic secret";
+#else
+/* The length of the early traffic label. */
+#define EARLY_TRAFFIC_LABEL_SZ      11
+/* The early traffic label. */
+static const byte earlyTrafficLabel[EARLY_TRAFFIC_LABEL_SZ + 1] =
+    "c e traffic";
+#endif
+/* Derive the early traffic key.
+ *
+ * ssl  The SSL/TLS object.
+ * key  The derived key.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveEarlyTrafficSecret(WOLFSSL* ssl, byte* key)
+{
+    int ret;
+    WOLFSSL_MSG("Derive Early Traffic Secret");
+    ret = DeriveKey(ssl, key, -1, ssl->arrays->secret,
+                    earlyTrafficLabel, EARLY_TRAFFIC_LABEL_SZ,
+                    ssl->specs.mac_algorithm, 1);
+#ifdef HAVE_SECRET_CALLBACK
+    if (ret == 0 && ssl->tls13SecretCb != NULL) {
+        ret = ssl->tls13SecretCb(ssl, CLIENT_EARLY_TRAFFIC_SECRET, key,
+                                 ssl->specs.hash_size, ssl->tls13SecretCtx);
+        if (ret != 0) {
+            return TLS13_SECRET_CB_E;
+        }
+    }
+#endif /* HAVE_SECRET_CALLBACK */
+    return ret;
+}
+
+#ifdef TLS13_SUPPORTS_EXPORTERS
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* The length of the early exporter label. */
+#define EARLY_EXPORTER_LABEL_SZ     28
+/* The early exporter label. */
+static const byte earlyExporterLabel[EARLY_EXPORTER_LABEL_SZ + 1] =
+    "early exporter master secret";
+#else
+/* The length of the early exporter label. */
+#define EARLY_EXPORTER_LABEL_SZ     12
+/* The early exporter label. */
+static const byte earlyExporterLabel[EARLY_EXPORTER_LABEL_SZ + 1] =
+    "e exp master";
+#endif
+/* Derive the early exporter key.
+ *
+ * ssl  The SSL/TLS object.
+ * key  The derived key.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveEarlyExporterSecret(WOLFSSL* ssl, byte* key)
+{
+    int ret;
+    WOLFSSL_MSG("Derive Early Exporter Secret");
+    ret = DeriveKey(ssl, key, -1, ssl->arrays->secret,
+                    earlyExporterLabel, EARLY_EXPORTER_LABEL_SZ,
+                    ssl->specs.mac_algorithm, 1);
+#ifdef HAVE_SECRET_CALLBACK
+    if (ret == 0 && ssl->tls13SecretCb != NULL) {
+        ret = ssl->tls13SecretCb(ssl, EARLY_EXPORTER_SECRET, key
+                                 ssl->specs.hash_size, ssl->tls13SecretCtx);
+        if (ret != 0) {
+            return TLS13_SECRET_CB_E;
+        }
+    }
+#endif /* HAVE_SECRET_CALLBACK */
+    return ret;
+}
+#endif
+#endif
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* The length of the client handshake label. */
+#define CLIENT_HANDSHAKE_LABEL_SZ   31
+/* The client handshake label. */
+static const byte clientHandshakeLabel[CLIENT_HANDSHAKE_LABEL_SZ + 1] =
+    "client handshake traffic secret";
+#else
+/* The length of the client handshake label. */
+#define CLIENT_HANDSHAKE_LABEL_SZ   12
+/* The client handshake label. */
+static const byte clientHandshakeLabel[CLIENT_HANDSHAKE_LABEL_SZ + 1] =
+    "c hs traffic";
+#endif
+/* Derive the client handshake key.
+ *
+ * ssl  The SSL/TLS object.
+ * key  The derived key.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveClientHandshakeSecret(WOLFSSL* ssl, byte* key)
+{
+    int ret;
+    WOLFSSL_MSG("Derive Client Handshake Secret");
+    ret = DeriveKey(ssl, key, -1, ssl->arrays->preMasterSecret,
+                    clientHandshakeLabel, CLIENT_HANDSHAKE_LABEL_SZ,
+                    ssl->specs.mac_algorithm, 1);
+#ifdef HAVE_SECRET_CALLBACK
+    if (ret == 0 && ssl->tls13SecretCb != NULL) {
+        ret = ssl->tls13SecretCb(ssl, CLIENT_HANDSHAKE_TRAFFIC_SECRET, key,
+                                 ssl->specs.hash_size, ssl->tls13SecretCtx);
+        if (ret != 0) {
+            return TLS13_SECRET_CB_E;
+        }
+    }
+#endif /* HAVE_SECRET_CALLBACK */
+    return ret;
+}
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* The length of the server handshake label. */
+#define SERVER_HANDSHAKE_LABEL_SZ   31
+/* The server handshake label. */
+static const byte serverHandshakeLabel[SERVER_HANDSHAKE_LABEL_SZ + 1] =
+    "server handshake traffic secret";
+#else
+/* The length of the server handshake label. */
+#define SERVER_HANDSHAKE_LABEL_SZ   12
+/* The server handshake label. */
+static const byte serverHandshakeLabel[SERVER_HANDSHAKE_LABEL_SZ + 1] =
+    "s hs traffic";
+#endif
+/* Derive the server handshake key.
+ *
+ * ssl  The SSL/TLS object.
+ * key  The derived key.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveServerHandshakeSecret(WOLFSSL* ssl, byte* key)
+{
+    int ret;
+    WOLFSSL_MSG("Derive Server Handshake Secret");
+    ret = DeriveKey(ssl, key, -1, ssl->arrays->preMasterSecret,
+                    serverHandshakeLabel, SERVER_HANDSHAKE_LABEL_SZ,
+                    ssl->specs.mac_algorithm, 1);
+#ifdef HAVE_SECRET_CALLBACK
+    if (ret == 0 && ssl->tls13SecretCb != NULL) {
+        ret = ssl->tls13SecretCb(ssl, SERVER_HANDSHAKE_TRAFFIC_SECRET, key,
+                                 ssl->specs.hash_size, ssl->tls13SecretCtx);
+        if (ret != 0) {
+            return TLS13_SECRET_CB_E;
+        }
+    }
+#endif /* HAVE_SECRET_CALLBACK */
+    return ret;
+}
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* The length of the client application traffic label. */
+#define CLIENT_APP_LABEL_SZ         33
+/* The client application traffic label. */
+static const byte clientAppLabel[CLIENT_APP_LABEL_SZ + 1] =
+    "client application traffic secret";
+#else
+/* The length of the client application traffic label. */
+#define CLIENT_APP_LABEL_SZ         12
+/* The client application traffic label. */
+static const byte clientAppLabel[CLIENT_APP_LABEL_SZ + 1] =
+    "c ap traffic";
+#endif
+/* Derive the client application traffic key.
+ *
+ * ssl  The SSL/TLS object.
+ * key  The derived key.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveClientTrafficSecret(WOLFSSL* ssl, byte* key)
+{
+    int ret;
+    WOLFSSL_MSG("Derive Client Traffic Secret");
+    ret = DeriveKey(ssl, key, -1, ssl->arrays->masterSecret,
+                    clientAppLabel, CLIENT_APP_LABEL_SZ,
+                    ssl->specs.mac_algorithm, 1);
+#ifdef HAVE_SECRET_CALLBACK
+    if (ret == 0 && ssl->tls13SecretCb != NULL) {
+        ret = ssl->tls13SecretCb(ssl, CLIENT_TRAFFIC_SECRET, key,
+                                 ssl->specs.hash_size, ssl->tls13SecretCtx);
+        if (ret != 0) {
+            return TLS13_SECRET_CB_E;
+        }
+    }
+#endif /* HAVE_SECRET_CALLBACK */
+    return ret;
+}
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* The length of the server application traffic label. */
+#define SERVER_APP_LABEL_SZ         33
+/* The  server application traffic label. */
+static const byte serverAppLabel[SERVER_APP_LABEL_SZ + 1] =
+    "server application traffic secret";
+#else
+/* The length of the server application traffic label. */
+#define SERVER_APP_LABEL_SZ         12
+/* The  server application traffic label. */
+static const byte serverAppLabel[SERVER_APP_LABEL_SZ + 1] =
+    "s ap traffic";
+#endif
+/* Derive the server application traffic key.
+ *
+ * ssl  The SSL/TLS object.
+ * key  The derived key.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveServerTrafficSecret(WOLFSSL* ssl, byte* key)
+{
+    int ret;
+    WOLFSSL_MSG("Derive Server Traffic Secret");
+    ret = DeriveKey(ssl, key, -1, ssl->arrays->masterSecret,
+                    serverAppLabel, SERVER_APP_LABEL_SZ,
+                    ssl->specs.mac_algorithm, 1);
+#ifdef HAVE_SECRET_CALLBACK
+    if (ret == 0 && ssl->tls13SecretCb != NULL) {
+        ret = ssl->tls13SecretCb(ssl, SERVER_TRAFFIC_SECRET, key,
+                                 ssl->specs.hash_size, ssl->tls13SecretCtx);
+        if (ret != 0) {
+            return TLS13_SECRET_CB_E;
+        }
+    }
+#endif /* HAVE_SECRET_CALLBACK */
+    return ret;
+}
+
+#ifdef TLS13_SUPPORTS_EXPORTERS
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* The length of the exporter master secret label. */
+#define EXPORTER_MASTER_LABEL_SZ    22
+/* The exporter master secret label. */
+static const byte exporterMasterLabel[EXPORTER_MASTER_LABEL_SZ + 1] =
+    "exporter master secret";
+#else
+/* The length of the exporter master secret label. */
+#define EXPORTER_MASTER_LABEL_SZ    10
+/* The exporter master secret label. */
+static const byte exporterMasterLabel[EXPORTER_MASTER_LABEL_SZ + 1] =
+    "exp master";
+#endif
+/* Derive the exporter secret.
+ *
+ * ssl  The SSL/TLS object.
+ * key  The derived key.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveExporterSecret(WOLFSSL* ssl, byte* key)
+{
+    int ret;
+    WOLFSSL_MSG("Derive Exporter Secret");
+    ret = DeriveKey(ssl, key, -1, ssl->arrays->masterSecret,
+                    exporterMasterLabel, EXPORTER_MASTER_LABEL_SZ,
+                    ssl->specs.mac_algorithm, 1);
+#ifdef HAVE_SECRET_CALLBACK
+    if (ret == 0 && ssl->tls13SecretCb != NULL) {
+        ret = ssl->tls13SecretCb(ssl, EXPORTER_SECRET, key,
+                                 ssl->specs.hash_size, ssl->tls13SecretCtx);
+        if (ret != 0) {
+            return TLS13_SECRET_CB_E;
+        }
+    }
+#endif /* HAVE_SECRET_CALLBACK */
+    return ret;
+}
+#endif
+
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* The length of the resumption master secret label. */
+#define RESUME_MASTER_LABEL_SZ      24
+/* The resumption master secret label. */
+static const byte resumeMasterLabel[RESUME_MASTER_LABEL_SZ + 1] =
+    "resumption master secret";
+#else
+/* The length of the resumption master secret label. */
+#define RESUME_MASTER_LABEL_SZ      10
+/* The resumption master secret label. */
+static const byte resumeMasterLabel[RESUME_MASTER_LABEL_SZ + 1] =
+    "res master";
+#endif
+/* Derive the resumption secret.
+ *
+ * ssl  The SSL/TLS object.
+ * key  The derived key.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveResumptionSecret(WOLFSSL* ssl, byte* key)
+{
+    WOLFSSL_MSG("Derive Resumption Secret");
+    return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret,
+                     resumeMasterLabel, RESUME_MASTER_LABEL_SZ,
+                     ssl->specs.mac_algorithm, 1);
+}
+#endif
+
+/* Length of the finished label. */
+#define FINISHED_LABEL_SZ           8
+/* Finished label for generating finished key. */
+static const byte finishedLabel[FINISHED_LABEL_SZ+1] = "finished";
+/* Derive the finished secret.
+ *
+ * ssl     The SSL/TLS object.
+ * key     The key to use with the HMAC.
+ * secret  The derived secret.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveFinishedSecret(WOLFSSL* ssl, byte* key, byte* secret)
+{
+    WOLFSSL_MSG("Derive Finished Secret");
+    return DeriveKey(ssl, secret, -1, key, finishedLabel, FINISHED_LABEL_SZ,
+                     ssl->specs.mac_algorithm, 0);
+}
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* The length of the application traffic label. */
+#define APP_TRAFFIC_LABEL_SZ        26
+/* The application traffic label. */
+static const byte appTrafficLabel[APP_TRAFFIC_LABEL_SZ + 1] =
+    "application traffic secret";
+#else
+/* The length of the application traffic label. */
+#define APP_TRAFFIC_LABEL_SZ        11
+/* The application traffic label. */
+static const byte appTrafficLabel[APP_TRAFFIC_LABEL_SZ + 1] =
+    "traffic upd";
+#endif
+/* Update the traffic secret.
+ *
+ * ssl     The SSL/TLS object.
+ * secret  The previous secret and derived secret.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveTrafficSecret(WOLFSSL* ssl, byte* secret)
+{
+    WOLFSSL_MSG("Derive New Application Traffic Secret");
+    return DeriveKey(ssl, secret, -1, secret,
+                     appTrafficLabel, APP_TRAFFIC_LABEL_SZ,
+                     ssl->specs.mac_algorithm, 0);
+}
+
+/* Derive the early secret using HKDF Extract.
+ *
+ * ssl  The SSL/TLS object.
+ */
+static int DeriveEarlySecret(WOLFSSL* ssl)
+{
+    WOLFSSL_MSG("Derive Early Secret");
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+    return Tls13_HKDF_Extract(ssl->arrays->secret, NULL, 0,
+            ssl->arrays->psk_key, ssl->arrays->psk_keySz,
+            ssl->specs.mac_algorithm);
+#else
+    return Tls13_HKDF_Extract(ssl->arrays->secret, NULL, 0,
+            ssl->arrays->masterSecret, 0, ssl->specs.mac_algorithm);
+#endif
+}
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+/* The length of the derived label. */
+#define DERIVED_LABEL_SZ        7
+/* The derived label. */
+static const byte derivedLabel[DERIVED_LABEL_SZ + 1] =
+    "derived";
+#endif
+/* Derive the handshake secret using HKDF Extract.
+ *
+ * ssl  The SSL/TLS object.
+ */
+static int DeriveHandshakeSecret(WOLFSSL* ssl)
+{
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    WOLFSSL_MSG("Derive Handshake Secret");
+    return Tls13_HKDF_Extract(ssl->arrays->preMasterSecret,
+            ssl->arrays->secret, ssl->specs.hash_size,
+            ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz,
+            ssl->specs.mac_algorithm);
+#else
+    byte key[WC_MAX_DIGEST_SIZE];
+    int ret;
+
+    WOLFSSL_MSG("Derive Handshake Secret");
+
+    ret = DeriveKeyMsg(ssl, key, -1, ssl->arrays->secret,
+                        derivedLabel, DERIVED_LABEL_SZ,
+                        NULL, 0, ssl->specs.mac_algorithm);
+    if (ret != 0)
+        return ret;
+
+    return Tls13_HKDF_Extract(ssl->arrays->preMasterSecret,
+            key, ssl->specs.hash_size,
+            ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz,
+            ssl->specs.mac_algorithm);
+#endif
+}
+
+/* Derive the master secret using HKDF Extract.
+ *
+ * ssl  The SSL/TLS object.
+ */
+static int DeriveMasterSecret(WOLFSSL* ssl)
+{
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    WOLFSSL_MSG("Derive Master Secret");
+    return Tls13_HKDF_Extract(ssl->arrays->masterSecret,
+            ssl->arrays->preMasterSecret, ssl->specs.hash_size,
+            ssl->arrays->masterSecret, 0, ssl->specs.mac_algorithm);
+#else
+    byte key[WC_MAX_DIGEST_SIZE];
+    int ret;
+
+    WOLFSSL_MSG("Derive Master Secret");
+
+    ret = DeriveKeyMsg(ssl, key, -1, ssl->arrays->preMasterSecret,
+                        derivedLabel, DERIVED_LABEL_SZ,
+                        NULL, 0, ssl->specs.mac_algorithm);
+    if (ret != 0)
+        return ret;
+
+    return Tls13_HKDF_Extract(ssl->arrays->masterSecret,
+            key, ssl->specs.hash_size,
+            ssl->arrays->masterSecret, 0, ssl->specs.mac_algorithm);
+#endif
+}
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+#if defined(HAVE_SESSION_TICKET)
+/* Length of the resumption label. */
+#define RESUMPTION_LABEL_SZ         10
+/* Resumption label for generating PSK associated with the ticket. */
+static const byte resumptionLabel[RESUMPTION_LABEL_SZ+1] = "resumption";
+/* Derive the PSK associated with the ticket.
+ *
+ * ssl       The SSL/TLS object.
+ * nonce     The nonce to derive with.
+ * nonceLen  The length of the nonce to derive with.
+ * secret    The derived secret.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveResumptionPSK(WOLFSSL* ssl, byte* nonce, byte nonceLen,
+                               byte* secret)
+{
+    int         digestAlg;
+    /* Only one protocol version defined at this time. */
+    const byte* protocol    = tls13ProtocolLabel;
+    word32      protocolLen = TLS13_PROTOCOL_LABEL_SZ;
+
+    WOLFSSL_MSG("Derive Resumption PSK");
+
+    switch (ssl->specs.mac_algorithm) {
+        #ifndef NO_SHA256
+        case sha256_mac:
+            digestAlg = WC_SHA256;
+            break;
+        #endif
+
+        #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            digestAlg = WC_SHA384;
+            break;
+        #endif
+
+        #ifdef WOLFSSL_TLS13_SHA512
+        case sha512_mac:
+            digestAlg = WC_SHA512;
+            break;
+        #endif
+
+        default:
+            return BAD_FUNC_ARG;
+    }
+
+    return HKDF_Expand_Label(secret, ssl->specs.hash_size,
+                             ssl->session.masterSecret, ssl->specs.hash_size,
+                             protocol, protocolLen, resumptionLabel,
+                             RESUMPTION_LABEL_SZ, nonce, nonceLen, digestAlg);
+}
+#endif /* HAVE_SESSION_TICKET */
+#endif /* WOLFSSL_TLS13_DRAFT_18 */
+
+
+/* Calculate the HMAC of message data to this point.
+ *
+ * ssl   The SSL/TLS object.
+ * key   The HMAC key.
+ * hash  The hash result - verify data.
+ * returns length of verify data generated.
+ */
+static int BuildTls13HandshakeHmac(WOLFSSL* ssl, byte* key, byte* hash,
+    word32* pHashSz)
+{
+    Hmac verifyHmac;
+    int  hashType = WC_SHA256;
+    int  hashSz = WC_SHA256_DIGEST_SIZE;
+    int  ret = BAD_FUNC_ARG;
+
+    /* Get the hash of the previous handshake messages. */
+    switch (ssl->specs.mac_algorithm) {
+    #ifndef NO_SHA256
+        case sha256_mac:
+            hashType = WC_SHA256;
+            hashSz = WC_SHA256_DIGEST_SIZE;
+            ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash);
+            break;
+    #endif /* !NO_SHA256 */
+    #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            hashType = WC_SHA384;
+            hashSz = WC_SHA384_DIGEST_SIZE;
+            ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash);
+            break;
+    #endif /* WOLFSSL_SHA384 */
+    #ifdef WOLFSSL_TLS13_SHA512
+        case sha512_mac:
+            hashType = WC_SHA512;
+            hashSz = WC_SHA512_DIGEST_SIZE;
+            ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash);
+            break;
+    #endif /* WOLFSSL_TLS13_SHA512 */
+    }
+    if (ret != 0)
+        return ret;
+
+    /* Calculate the verify data. */
+    ret = wc_HmacInit(&verifyHmac, ssl->heap, ssl->devId);
+    if (ret == 0) {
+        ret = wc_HmacSetKey(&verifyHmac, hashType, key, ssl->specs.hash_size);
+        if (ret == 0)
+            ret = wc_HmacUpdate(&verifyHmac, hash, hashSz);
+        if (ret == 0)
+            ret = wc_HmacFinal(&verifyHmac, hash);
+        wc_HmacFree(&verifyHmac);
+    }
+
+    if (pHashSz)
+        *pHashSz = hashSz;
+
+    return ret;
+}
+
+/* The length of the label to use when deriving keys. */
+#define WRITE_KEY_LABEL_SZ     3
+/* The length of the label to use when deriving IVs. */
+#define WRITE_IV_LABEL_SZ      2
+/* The label to use when deriving keys. */
+static const byte writeKeyLabel[WRITE_KEY_LABEL_SZ+1] = "key";
+/* The label to use when deriving IVs. */
+static const byte writeIVLabel[WRITE_IV_LABEL_SZ+1]   = "iv";
+
+/* Derive the keys and IVs for TLS v1.3.
+ *
+ * ssl      The SSL/TLS object.
+ * sercret  early_data_key when deriving the key and IV for encrypting early
+ *          data application data and end_of_early_data messages.
+ *          handshake_key when deriving keys and IVs for encrypting handshake
+ *          messages.
+ *          traffic_key when deriving first keys and IVs for encrypting
+ *          traffic messages.
+ *          update_traffic_key when deriving next keys and IVs for encrypting
+ *          traffic messages.
+ * side     ENCRYPT_SIDE_ONLY when only encryption secret needs to be derived.
+ *          DECRYPT_SIDE_ONLY when only decryption secret needs to be derived.
+ *          ENCRYPT_AND_DECRYPT_SIDE when both secret needs to be derived.
+ * store    1 indicates to derive the keys and IVs from derived secret and
+ *          store ready for provisioning.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store)
+{
+    int   ret = BAD_FUNC_ARG; /* Assume failure */
+    int   i = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    byte* key_dig;
+#else
+    byte  key_dig[MAX_PRF_DIG];
+#endif
+    int   provision;
+
+#ifdef WOLFSSL_SMALL_STACK
+    key_dig = (byte*)XMALLOC(MAX_PRF_DIG, ssl->heap, DYNAMIC_TYPE_DIGEST);
+    if (key_dig == NULL)
+        return MEMORY_E;
+#endif
+
+    if (side == ENCRYPT_AND_DECRYPT_SIDE) {
+        provision = PROVISION_CLIENT_SERVER;
+    }
+    else {
+        provision = ((ssl->options.side != WOLFSSL_CLIENT_END) ^
+                     (side == ENCRYPT_SIDE_ONLY)) ? PROVISION_CLIENT :
+                                                    PROVISION_SERVER;
+    }
+
+    /* Derive the appropriate secret to use in the HKDF. */
+    switch (secret) {
+#ifdef WOLFSSL_EARLY_DATA
+        case early_data_key:
+            ret = DeriveEarlyTrafficSecret(ssl, ssl->clientSecret);
+            if (ret != 0)
+                goto end;
+            break;
+#endif
+
+        case handshake_key:
+            if (provision & PROVISION_CLIENT) {
+                ret = DeriveClientHandshakeSecret(ssl,
+                                                  ssl->clientSecret);
+                if (ret != 0)
+                    goto end;
+            }
+            if (provision & PROVISION_SERVER) {
+                ret = DeriveServerHandshakeSecret(ssl,
+                                                  ssl->serverSecret);
+                if (ret != 0)
+                    goto end;
+            }
+            break;
+
+        case traffic_key:
+            if (provision & PROVISION_CLIENT) {
+                ret = DeriveClientTrafficSecret(ssl, ssl->clientSecret);
+                if (ret != 0)
+                    goto end;
+            }
+            if (provision & PROVISION_SERVER) {
+                ret = DeriveServerTrafficSecret(ssl, ssl->serverSecret);
+                if (ret != 0)
+                    goto end;
+            }
+            break;
+
+        case update_traffic_key:
+            if (provision & PROVISION_CLIENT) {
+                ret = DeriveTrafficSecret(ssl, ssl->clientSecret);
+                if (ret != 0)
+                    goto end;
+            }
+            if (provision & PROVISION_SERVER) {
+                ret = DeriveTrafficSecret(ssl, ssl->serverSecret);
+                if (ret != 0)
+                    goto end;
+            }
+            break;
+    }
+
+    if (!store)
+        goto end;
+
+    /* Key data = client key | server key | client IV | server IV */
+
+    if (provision & PROVISION_CLIENT) {
+        /* Derive the client key.  */
+        WOLFSSL_MSG("Derive Client Key");
+        ret = DeriveKey(ssl, &key_dig[i], ssl->specs.key_size,
+                        ssl->clientSecret, writeKeyLabel,
+                        WRITE_KEY_LABEL_SZ, ssl->specs.mac_algorithm, 0);
+        if (ret != 0)
+            goto end;
+        i += ssl->specs.key_size;
+    }
+
+    if (provision & PROVISION_SERVER) {
+        /* Derive the server key.  */
+        WOLFSSL_MSG("Derive Server Key");
+        ret = DeriveKey(ssl, &key_dig[i], ssl->specs.key_size,
+                        ssl->serverSecret, writeKeyLabel,
+                        WRITE_KEY_LABEL_SZ, ssl->specs.mac_algorithm, 0);
+        if (ret != 0)
+            goto end;
+        i += ssl->specs.key_size;
+    }
+
+    if (provision & PROVISION_CLIENT) {
+        /* Derive the client IV.  */
+        WOLFSSL_MSG("Derive Client IV");
+        ret = DeriveKey(ssl, &key_dig[i], ssl->specs.iv_size,
+                        ssl->clientSecret, writeIVLabel,
+                        WRITE_IV_LABEL_SZ, ssl->specs.mac_algorithm, 0);
+        if (ret != 0)
+            goto end;
+        i += ssl->specs.iv_size;
+    }
+
+    if (provision & PROVISION_SERVER) {
+        /* Derive the server IV.  */
+        WOLFSSL_MSG("Derive Server IV");
+        ret = DeriveKey(ssl, &key_dig[i], ssl->specs.iv_size,
+                        ssl->serverSecret, writeIVLabel,
+                        WRITE_IV_LABEL_SZ, ssl->specs.mac_algorithm, 0);
+        if (ret != 0)
+            goto end;
+    }
+
+    /* Store keys and IVs but don't activate them. */
+    ret = StoreKeys(ssl, key_dig, provision);
+
+end:
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(key_dig, ssl->heap, DYNAMIC_TYPE_DIGEST);
+#endif
+
+    return ret;
+}
+
+#ifdef HAVE_SESSION_TICKET
+#if defined(USER_TICKS)
+#if 0
+    word32 TimeNowInMilliseconds(void)
+    {
+        /*
+        write your own clock tick function if don't want gettimeofday()
+        needs millisecond accuracy but doesn't have to correlated to EPOCH
+        */
+    }
+#endif
+
+#elif defined(TIME_OVERRIDES)
+    #ifndef HAVE_TIME_T_TYPE
+        typedef long time_t;
+    #endif
+    extern time_t XTIME(time_t * timer);
+
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        return (word32) XTIME(0) * 1000;
+    }
+
+#elif defined(XTIME_MS)
+    word32 TimeNowInMilliseconds(void)
+    {
+        return (word32)XTIME_MS(0);
+    }
+
+#elif defined(USE_WINDOWS_API)
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        static int           init = 0;
+        static LARGE_INTEGER freq;
+        LARGE_INTEGER        count;
+
+        if (!init) {
+            QueryPerformanceFrequency(&freq);
+            init = 1;
+        }
+
+        QueryPerformanceCounter(&count);
+
+        return (word32)(count.QuadPart / (freq.QuadPart / 1000));
+    }
+
+#elif defined(HAVE_RTP_SYS)
+    #include "rtptime.h"
+
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        return (word32)rtp_get_system_sec() * 1000;
+    }
+#elif defined(WOLFSSL_DEOS)
+    word32 TimeNowInMilliseconds(void)
+    {
+        const uint32_t systemTickTimeInHz = 1000000 / systemTickInMicroseconds();
+        uint32_t *systemTickPtr = systemTickPointer();
+
+        return (word32) (*systemTickPtr/systemTickTimeInHz) * 1000;
+    }
+#elif defined(MICRIUM)
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        OS_TICK ticks = 0;
+        OS_ERR  err;
+
+        ticks = OSTimeGet(&err);
+
+        return (word32) (ticks / OSCfg_TickRate_Hz) * 1000;
+    }
+#elif defined(MICROCHIP_TCPIP_V5)
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        return (word32) (TickGet() / (TICKS_PER_SECOND / 1000));
+    }
+#elif defined(MICROCHIP_TCPIP)
+    #if defined(MICROCHIP_MPLAB_HARMONY)
+        #include <system/tmr/sys_tmr.h>
+
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        return (word32)(SYS_TMR_TickCountGet() /
+                        (SYS_TMR_TickCounterFrequencyGet() / 1000));
+    }
+    #else
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        return (word32)(SYS_TICK_Get() / (SYS_TICK_TicksPerSecondGet() / 1000));
+    }
+
+    #endif
+
+#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        TIME_STRUCT mqxTime;
+
+        _time_get_elapsed(&mqxTime);
+
+        return (word32) mqxTime.SECONDS * 1000;
+    }
+#elif defined(FREESCALE_FREE_RTOS) || defined(FREESCALE_KSDK_FREERTOS)
+    #include "include/task.h"
+
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        return (unsigned int)(((float)xTaskGetTickCount()) /
+                              (configTICK_RATE_HZ / 1000));
+    }
+#elif defined(FREESCALE_KSDK_BM)
+    #include "lwip/sys.h" /* lwIP */
+
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        return sys_now();
+    }
+#elif defined(WOLFSSL_TIRTOS)
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        return (word32) Seconds_get() * 1000;
+    }
+#elif defined(WOLFSSL_UTASKER)
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        return (word32)(uTaskerSystemTick / (TICK_RESOLUTION / 1000));
+    }
+#else
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        struct timeval now;
+
+        if (gettimeofday(&now, 0) < 0)
+            return GETTIME_ERROR;
+        /* Convert to milliseconds number. */
+        return (word32)(now.tv_sec * 1000 + now.tv_usec / 1000);
+    }
+#endif
+#endif /* HAVE_SESSION_TICKET || !NO_PSK */
+
+
+#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_SESSION_TICKET) || \
+                                    !defined(NO_PSK))
+/* Add input to all handshake hashes.
+ *
+ * ssl    The SSL/TLS object.
+ * input  The data to hash.
+ * sz     The size of the data to hash.
+ * returns 0 on success, otherwise failure.
+ */
+static int HashInputRaw(WOLFSSL* ssl, const byte* input, int sz)
+{
+    int ret = BAD_FUNC_ARG;
+
+#ifndef NO_SHA256
+    ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, input, sz);
+    if (ret != 0)
+        return ret;
+#endif
+#ifdef WOLFSSL_SHA384
+    ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, input, sz);
+    if (ret != 0)
+        return ret;
+#endif
+#ifdef WOLFSSL_TLS13_SHA512
+    ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, input, sz);
+    if (ret != 0)
+        return ret;
+#endif
+
+    return ret;
+}
+#endif
+
+/* Extract the handshake header information.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The buffer holding the message data.
+ * inOutIdx  On entry, the index into the buffer of the handshake data.
+ *           On exit, the start of the handshake data.
+ * type      Type of handshake message.
+ * size      The length of the handshake message data.
+ * totalSz   The total size of data in the buffer.
+ * returns BUFFER_E if there is not enough input data and 0 on success.
+ */
+static int GetHandshakeHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                              byte* type, word32* size, word32 totalSz)
+{
+    const byte* ptr = input + *inOutIdx;
+    (void)ssl;
+
+    *inOutIdx += HANDSHAKE_HEADER_SZ;
+    if (*inOutIdx > totalSz)
+        return BUFFER_E;
+
+    *type = ptr[0];
+    c24to32(&ptr[1], size);
+
+    return 0;
+}
+
+/* Add record layer header to message.
+ *
+ * output  The buffer to write the record layer header into.
+ * length  The length of the record data.
+ * type    The type of record message.
+ * ssl     The SSL/TLS object.
+ */
+static void AddTls13RecordHeader(byte* output, word32 length, byte type,
+                                 WOLFSSL* ssl)
+{
+    RecordLayerHeader* rl;
+
+    rl = (RecordLayerHeader*)output;
+    rl->type    = type;
+    rl->pvMajor = ssl->version.major;
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    rl->pvMinor = TLSv1_MINOR;
+#else
+    /* NOTE: May be TLSv1_MINOR when sending first ClientHello. */
+    rl->pvMinor = TLSv1_2_MINOR;
+#endif
+    c16toa((word16)length, rl->length);
+}
+
+/* Add handshake header to message.
+ *
+ * output      The buffer to write the handshake header into.
+ * length      The length of the handshake data.
+ * fragOffset  The offset of the fragment data. (DTLS)
+ * fragLength  The length of the fragment data. (DTLS)
+ * type        The type of handshake message.
+ * ssl         The SSL/TLS object. (DTLS)
+ */
+static void AddTls13HandShakeHeader(byte* output, word32 length,
+                                    word32 fragOffset, word32 fragLength,
+                                    byte type, WOLFSSL* ssl)
+{
+    HandShakeHeader* hs;
+    (void)fragOffset;
+    (void)fragLength;
+    (void)ssl;
+
+    /* handshake header */
+    hs = (HandShakeHeader*)output;
+    hs->type = type;
+    c32to24(length, hs->length);
+}
+
+
+/* Add both record layer and handshake header to message.
+ *
+ * output      The buffer to write the headers into.
+ * length      The length of the handshake data.
+ * type        The type of record layer message.
+ * ssl         The SSL/TLS object. (DTLS)
+ */
+static void AddTls13Headers(byte* output, word32 length, byte type,
+                            WOLFSSL* ssl)
+{
+    word32 lengthAdj = HANDSHAKE_HEADER_SZ;
+    word32 outputAdj = RECORD_HEADER_SZ;
+
+    AddTls13RecordHeader(output, length + lengthAdj, handshake, ssl);
+    AddTls13HandShakeHeader(output + outputAdj, length, 0, length, type, ssl);
+}
+
+
+#ifndef NO_CERTS
+/* Add both record layer and fragment handshake header to message.
+ *
+ * output      The buffer to write the headers into.
+ * fragOffset  The offset of the fragment data. (DTLS)
+ * fragLength  The length of the fragment data. (DTLS)
+ * length      The length of the handshake data.
+ * type        The type of record layer message.
+ * ssl         The SSL/TLS object. (DTLS)
+ */
+static void AddTls13FragHeaders(byte* output, word32 fragSz, word32 fragOffset,
+                                word32 length, byte type, WOLFSSL* ssl)
+{
+    word32 lengthAdj = HANDSHAKE_HEADER_SZ;
+    word32 outputAdj = RECORD_HEADER_SZ;
+    (void)fragSz;
+
+    AddTls13RecordHeader(output, fragSz + lengthAdj, handshake, ssl);
+    AddTls13HandShakeHeader(output + outputAdj, length, fragOffset, fragSz,
+                            type, ssl);
+}
+#endif /* NO_CERTS */
+
+/* Write the sequence number into the buffer.
+ * No DTLS v1.3 support.
+ *
+ * ssl          The SSL/TLS object.
+ * verifyOrder  Which set of sequence numbers to use.
+ * out          The buffer to write into.
+ */
+static WC_INLINE void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out)
+{
+    word32 seq[2] = {0, 0};
+
+    if (verifyOrder) {
+        seq[0] = ssl->keys.peer_sequence_number_hi;
+        seq[1] = ssl->keys.peer_sequence_number_lo++;
+        /* handle rollover */
+        if (seq[1] > ssl->keys.peer_sequence_number_lo)
+            ssl->keys.peer_sequence_number_hi++;
+    }
+    else {
+        seq[0] = ssl->keys.sequence_number_hi;
+        seq[1] = ssl->keys.sequence_number_lo++;
+        /* handle rollover */
+        if (seq[1] > ssl->keys.sequence_number_lo)
+            ssl->keys.sequence_number_hi++;
+    }
+
+    c32toa(seq[0], out);
+    c32toa(seq[1], out + OPAQUE32_LEN);
+}
+
+/* Build the nonce for TLS v1.3 encryption and decryption.
+ *
+ * ssl    The SSL/TLS object.
+ * nonce  The nonce data to use when encrypting or decrypting.
+ * iv     The derived IV.
+ * order  The side on which the message is to be or was sent.
+ */
+static WC_INLINE void BuildTls13Nonce(WOLFSSL* ssl, byte* nonce, const byte* iv,
+                                   int order)
+{
+    int  i;
+
+    /* The nonce is the IV with the sequence XORed into the last bytes. */
+    WriteSEQ(ssl, order, nonce + AEAD_NONCE_SZ - SEQ_SZ);
+    for (i = 0; i < AEAD_NONCE_SZ - SEQ_SZ; i++)
+        nonce[i] = iv[i];
+    for (; i < AEAD_NONCE_SZ; i++)
+        nonce[i] ^= iv[i];
+}
+
+#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
+/* Encrypt with ChaCha20 and create authenication tag with Poly1305.
+ *
+ * ssl     The SSL/TLS object.
+ * output  The buffer to write encrypted data and authentication tag into.
+ *         May be the same pointer as input.
+ * input   The data to encrypt.
+ * sz      The number of bytes to encrypt.
+ * nonce   The nonce to use with ChaCha20.
+ * aad     The additional authentication data.
+ * aadSz   The size of the addition authentication data.
+ * tag     The authentication tag buffer.
+ * returns 0 on success, otherwise failure.
+ */
+static int ChaCha20Poly1305_Encrypt(WOLFSSL* ssl, byte* output,
+                                    const byte* input, word16 sz, byte* nonce,
+                                    const byte* aad, word16 aadSz, byte* tag)
+{
+    int    ret    = 0;
+    byte   poly[CHACHA20_256_KEY_SIZE];
+
+    /* Poly1305 key is 256 bits of zero encrypted with ChaCha20. */
+    XMEMSET(poly, 0, sizeof(poly));
+
+    /* Set the nonce for ChaCha and get Poly1305 key. */
+    ret = wc_Chacha_SetIV(ssl->encrypt.chacha, nonce, 0);
+    if (ret != 0)
+        return ret;
+    /* Create Poly1305 key using ChaCha20 keystream. */
+    ret = wc_Chacha_Process(ssl->encrypt.chacha, poly, poly, sizeof(poly));
+    if (ret != 0)
+        return ret;
+    ret = wc_Chacha_SetIV(ssl->encrypt.chacha, nonce, 1);
+    if (ret != 0)
+        return ret;
+    /* Encrypt the plain text. */
+    ret = wc_Chacha_Process(ssl->encrypt.chacha, output, input, sz);
+    if (ret != 0) {
+        ForceZero(poly, sizeof(poly));
+        return ret;
+    }
+
+    /* Set key for Poly1305. */
+    ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly, sizeof(poly));
+    ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */
+    if (ret != 0)
+        return ret;
+    /* Add authentication code of encrypted data to end. */
+    ret = wc_Poly1305_MAC(ssl->auth.poly1305, (byte*)aad, aadSz, output, sz,
+                          tag, POLY1305_AUTH_SZ);
+
+    return ret;
+}
+#endif
+
+#ifdef HAVE_NULL_CIPHER
+/* Create authenication tag and copy data over input.
+ *
+ * ssl     The SSL/TLS object.
+ * output  The buffer to copy data into.
+ *         May be the same pointer as input.
+ * input   The data.
+ * sz      The number of bytes of data.
+ * nonce   The nonce to use with authentication.
+ * aad     The additional authentication data.
+ * aadSz   The size of the addition authentication data.
+ * tag     The authentication tag buffer.
+ * returns 0 on success, otherwise failure.
+ */
+static int Tls13IntegrityOnly_Encrypt(WOLFSSL* ssl, byte* output,
+                                      const byte* input, word16 sz,
+                                      const byte* nonce,
+                                      const byte* aad, word16 aadSz, byte* tag)
+{
+    int ret;
+
+    /* HMAC: nonce | aad | input  */
+    ret = wc_HmacUpdate(ssl->encrypt.hmac, nonce, HMAC_NONCE_SZ);
+    if (ret == 0)
+        ret = wc_HmacUpdate(ssl->encrypt.hmac, aad, aadSz);
+    if (ret == 0)
+        ret = wc_HmacUpdate(ssl->encrypt.hmac, input, sz);
+    if (ret == 0)
+        ret = wc_HmacFinal(ssl->encrypt.hmac, tag);
+    /* Copy the input to output if not the same buffer */
+    if (ret == 0 && output != input)
+        XMEMCPY(output, input, sz);
+
+    return ret;
+}
+#endif
+
+/* Encrypt data for TLS v1.3.
+ *
+ * ssl     The SSL/TLS object.
+ * output  The buffer to write encrypted data and authentication tag into.
+ *         May be the same pointer as input.
+ * input   The record header and data to encrypt.
+ * sz      The number of bytes to encrypt.
+ * aad     The additional authentication data.
+ * aadSz   The size of the addition authentication data.
+ * asyncOkay If non-zero can return WC_PENDING_E, otherwise blocks on crypto
+ * returns 0 on success, otherwise failure.
+ */
+static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input,
+                        word16 sz, const byte* aad, word16 aadSz, int asyncOkay)
+{
+    int    ret    = 0;
+    word16 dataSz = sz - ssl->specs.aead_mac_size;
+    word16 macSz  = ssl->specs.aead_mac_size;
+    word32 nonceSz = 0;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    WC_ASYNC_DEV* asyncDev = NULL;
+    word32 event_flags = WC_ASYNC_FLAG_CALL_AGAIN;
+#endif
+
+    WOLFSSL_ENTER("EncryptTls13");
+
+    (void)output;
+    (void)input;
+    (void)sz;
+    (void)dataSz;
+    (void)macSz;
+    (void)asyncOkay;
+    (void)nonceSz;
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ssl->error == WC_PENDING_E) {
+        ssl->error = 0; /* clear async */
+    }
+#endif
+
+    switch (ssl->encrypt.state) {
+        case CIPHER_STATE_BEGIN:
+        {
+        #ifdef WOLFSSL_DEBUG_TLS
+            WOLFSSL_MSG("Data to encrypt");
+            WOLFSSL_BUFFER(input, dataSz);
+#if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) && \
+                                        !defined(WOLFSSL_TLS13_DRAFT_23)
+            WOLFSSL_MSG("Additional Authentication Data");
+            WOLFSSL_BUFFER(aad, aadSz);
+#endif
+        #endif
+
+        #ifdef CIPHER_NONCE
+            if (ssl->encrypt.nonce == NULL)
+                ssl->encrypt.nonce = (byte*)XMALLOC(AEAD_NONCE_SZ,
+                                            ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+            if (ssl->encrypt.nonce == NULL)
+                return MEMORY_E;
+
+            BuildTls13Nonce(ssl, ssl->encrypt.nonce, ssl->keys.aead_enc_imp_IV,
+                            CUR_ORDER);
+        #endif
+
+            /* Advance state and proceed */
+            ssl->encrypt.state = CIPHER_STATE_DO;
+        }
+        FALL_THROUGH;
+
+        case CIPHER_STATE_DO:
+        {
+            switch (ssl->specs.bulk_cipher_algorithm) {
+            #ifdef BUILD_AESGCM
+                case wolfssl_aes_gcm:
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    /* initialize event */
+                    asyncDev = &ssl->encrypt.aes->asyncDev;
+                    ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags);
+                    if (ret != 0)
+                        break;
+                #endif
+
+                    nonceSz = AESGCM_NONCE_SZ;
+                #if ((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \
+                    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)))
+                    ret = wc_AesGcmEncrypt(ssl->encrypt.aes, output, input,
+                        dataSz, ssl->encrypt.nonce, nonceSz,
+                        output + dataSz, macSz, aad, aadSz);
+                #else
+                    ret = wc_AesGcmSetExtIV(ssl->encrypt.aes,
+                            ssl->encrypt.nonce, nonceSz);
+                    if (ret == 0) {
+                        ret = wc_AesGcmEncrypt_ex(ssl->encrypt.aes, output,
+                                input, dataSz, ssl->encrypt.nonce, nonceSz,
+                                output + dataSz, macSz, aad, aadSz);
+                    }
+                #endif
+                    break;
+            #endif
+
+            #ifdef HAVE_AESCCM
+                case wolfssl_aes_ccm:
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    /* initialize event */
+                    asyncDev = &ssl->encrypt.aes->asyncDev;
+                    ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags);
+                    if (ret != 0)
+                        break;
+                #endif
+
+                    nonceSz = AESCCM_NONCE_SZ;
+                #if ((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \
+                    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)))
+                    ret = wc_AesCcmEncrypt(ssl->encrypt.aes, output, input,
+                        dataSz, ssl->encrypt.nonce, nonceSz,
+                        output + dataSz, macSz, aad, aadSz);
+                #else
+                    ret = wc_AesCcmSetNonce(ssl->encrypt.aes,
+                            ssl->encrypt.nonce, nonceSz);
+                    if (ret == 0) {
+                        ret = wc_AesCcmEncrypt_ex(ssl->encrypt.aes, output,
+                                input, dataSz, ssl->encrypt.nonce, nonceSz,
+                                output + dataSz, macSz, aad, aadSz);
+                    }
+                #endif
+                    break;
+            #endif
+
+            #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
+                case wolfssl_chacha:
+                    ret = ChaCha20Poly1305_Encrypt(ssl, output, input, dataSz,
+                        ssl->encrypt.nonce, aad, aadSz, output + dataSz);
+                    break;
+            #endif
+
+            #ifdef HAVE_NULL_CIPHER
+                case wolfssl_cipher_null:
+                    ret = Tls13IntegrityOnly_Encrypt(ssl, output, input, dataSz,
+                        ssl->encrypt.nonce, aad, aadSz, output + dataSz);
+                    break;
+            #endif
+
+                default:
+                    WOLFSSL_MSG("wolfSSL Encrypt programming error");
+                    return ENCRYPT_ERROR;
+            }
+
+            /* Advance state */
+            ssl->encrypt.state = CIPHER_STATE_END;
+
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (ret == WC_PENDING_E) {
+                /* if async is not okay, then block */
+                if (!asyncOkay) {
+                    ret = wc_AsyncWait(ret, asyncDev, event_flags);
+                }
+                else {
+                    /* If pending, then leave and return will resume below */
+                    return wolfSSL_AsyncPush(ssl, asyncDev);
+                }
+            }
+        #endif
+        }
+        FALL_THROUGH;
+
+        case CIPHER_STATE_END:
+        {
+        #ifdef WOLFSSL_DEBUG_TLS
+            #ifdef CIPHER_NONCE
+                WOLFSSL_MSG("Nonce");
+                WOLFSSL_BUFFER(ssl->encrypt.nonce, ssl->specs.iv_size);
+            #endif
+                WOLFSSL_MSG("Encrypted data");
+                WOLFSSL_BUFFER(output, dataSz);
+                WOLFSSL_MSG("Authentication Tag");
+                WOLFSSL_BUFFER(output + dataSz, macSz);
+        #endif
+
+        #ifdef CIPHER_NONCE
+            ForceZero(ssl->encrypt.nonce, AEAD_NONCE_SZ);
+        #endif
+
+            break;
+        }
+    }
+
+    /* Reset state */
+    ssl->encrypt.state = CIPHER_STATE_BEGIN;
+
+    return ret;
+}
+
+#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
+/* Decrypt with ChaCha20 and check authenication tag with Poly1305.
+ *
+ * ssl     The SSL/TLS object.
+ * output  The buffer to write decrypted data into.
+ *         May be the same pointer as input.
+ * input   The data to decrypt.
+ * sz      The number of bytes to decrypt.
+ * nonce   The nonce to use with ChaCha20.
+ * aad     The additional authentication data.
+ * aadSz   The size of the addition authentication data.
+ * tagIn   The authentication tag data from packet.
+ * returns 0 on success, otherwise failure.
+ */
+static int ChaCha20Poly1305_Decrypt(WOLFSSL* ssl, byte* output,
+                                    const byte* input, word16 sz, byte* nonce,
+                                    const byte* aad, word16 aadSz,
+                                    const byte* tagIn)
+{
+    int ret;
+    byte tag[POLY1305_AUTH_SZ];
+    byte poly[CHACHA20_256_KEY_SIZE]; /* generated key for mac */
+
+    /* Poly1305 key is 256 bits of zero encrypted with ChaCha20. */
+    XMEMSET(poly, 0, sizeof(poly));
+
+    /* Set nonce and get Poly1305 key. */
+    ret = wc_Chacha_SetIV(ssl->decrypt.chacha, nonce, 0);
+    if (ret != 0)
+        return ret;
+    /* Use ChaCha20 keystream to get Poly1305 key for tag. */
+    ret = wc_Chacha_Process(ssl->decrypt.chacha, poly, poly, sizeof(poly));
+    if (ret != 0)
+        return ret;
+    ret = wc_Chacha_SetIV(ssl->decrypt.chacha, nonce, 1);
+    if (ret != 0)
+        return ret;
+
+    /* Set key for Poly1305. */
+    ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly, sizeof(poly));
+    ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */
+    if (ret != 0)
+        return ret;
+    /* Generate authentication tag for encrypted data. */
+    if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, (byte*)aad, aadSz,
+                                    (byte*)input, sz, tag, sizeof(tag))) != 0) {
+        return ret;
+    }
+
+    /* Check tag sent along with packet. */
+    if (ConstantCompare(tagIn, tag, POLY1305_AUTH_SZ) != 0) {
+        WOLFSSL_MSG("MAC did not match");
+        return VERIFY_MAC_ERROR;
+    }
+
+    /* If the tag was good decrypt message. */
+    ret = wc_Chacha_Process(ssl->decrypt.chacha, output, input, sz);
+
+    return ret;
+}
+#endif
+
+#ifdef HAVE_NULL_CIPHER
+/* Check HMAC tag and copy over input.
+ *
+ * ssl     The SSL/TLS object.
+ * output  The buffer to copy data into.
+ *         May be the same pointer as input.
+ * input   The data.
+ * sz      The number of bytes of data.
+ * nonce   The nonce to use with authentication.
+ * aad     The additional authentication data.
+ * aadSz   The size of the addition authentication data.
+ * tagIn   The authentication tag data from packet.
+ * returns 0 on success, otherwise failure.
+ */
+static int Tls13IntegrityOnly_Decrypt(WOLFSSL* ssl, byte* output,
+                                      const byte* input, word16 sz,
+                                      const byte* nonce,
+                                      const byte* aad, word16 aadSz,
+                                      const byte* tagIn)
+{
+    int ret;
+    byte hmac[WC_MAX_DIGEST_SIZE];
+
+    /* HMAC: nonce | aad | input  */
+    ret = wc_HmacUpdate(ssl->decrypt.hmac, nonce, HMAC_NONCE_SZ);
+    if (ret == 0)
+        ret = wc_HmacUpdate(ssl->decrypt.hmac, aad, aadSz);
+    if (ret == 0)
+        ret = wc_HmacUpdate(ssl->decrypt.hmac, input, sz);
+    if (ret == 0)
+        ret = wc_HmacFinal(ssl->decrypt.hmac, hmac);
+    /* Check authentication tag matches */
+    if (ret == 0 && ConstantCompare(tagIn, hmac, ssl->specs.hash_size) != 0)
+        ret = DECRYPT_ERROR;
+    /* Copy the input to output if not the same buffer */
+    if (ret == 0 && output != input)
+        XMEMCPY(output, input, sz);
+
+    return ret;
+}
+#endif
+
+/* Decrypt data for TLS v1.3.
+ *
+ * ssl     The SSL/TLS object.
+ * output  The buffer to write decrypted data into.
+ *         May be the same pointer as input.
+ * input   The data to decrypt and authentication tag.
+ * sz      The length of the encrypted data plus authentication tag.
+ * aad     The additional authentication data.
+ * aadSz   The size of the addition authentication data.
+ * returns 0 on success, otherwise failure.
+ */
+int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz,
+                 const byte* aad, word16 aadSz)
+{
+    int    ret    = 0;
+    word16 dataSz = sz - ssl->specs.aead_mac_size;
+    word16 macSz  = ssl->specs.aead_mac_size;
+    word32 nonceSz = 0;
+
+    WOLFSSL_ENTER("DecryptTls13");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ret = wolfSSL_AsyncPop(ssl, &ssl->decrypt.state);
+    if (ret != WC_NOT_PENDING_E) {
+        /* check for still pending */
+        if (ret == WC_PENDING_E)
+            return ret;
+
+        ssl->error = 0; /* clear async */
+
+        /* let failures through so CIPHER_STATE_END logic is run */
+    }
+    else
+#endif
+    {
+        /* Reset state */
+        ret = 0;
+        ssl->decrypt.state = CIPHER_STATE_BEGIN;
+    }
+
+    (void)output;
+    (void)input;
+    (void)sz;
+    (void)dataSz;
+    (void)macSz;
+    (void)nonceSz;
+
+    switch (ssl->decrypt.state) {
+        case CIPHER_STATE_BEGIN:
+        {
+        #ifdef WOLFSSL_DEBUG_TLS
+            WOLFSSL_MSG("Data to decrypt");
+            WOLFSSL_BUFFER(input, dataSz);
+#if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) && \
+                                        !defined(WOLFSSL_TLS13_DRAFT_23)
+            WOLFSSL_MSG("Additional Authentication Data");
+            WOLFSSL_BUFFER(aad, aadSz);
+#endif
+            WOLFSSL_MSG("Authentication tag");
+            WOLFSSL_BUFFER(input + dataSz, macSz);
+        #endif
+
+        #ifdef CIPHER_NONCE
+            if (ssl->decrypt.nonce == NULL)
+                ssl->decrypt.nonce = (byte*)XMALLOC(AEAD_NONCE_SZ,
+                                            ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+            if (ssl->decrypt.nonce == NULL)
+                return MEMORY_E;
+
+            BuildTls13Nonce(ssl, ssl->decrypt.nonce, ssl->keys.aead_dec_imp_IV,
+                            PEER_ORDER);
+        #endif
+
+            /* Advance state and proceed */
+            ssl->decrypt.state = CIPHER_STATE_DO;
+        }
+        FALL_THROUGH;
+
+        case CIPHER_STATE_DO:
+        {
+            switch (ssl->specs.bulk_cipher_algorithm) {
+            #ifdef BUILD_AESGCM
+                case wolfssl_aes_gcm:
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    /* initialize event */
+                    ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev,
+                        WC_ASYNC_FLAG_CALL_AGAIN);
+                    if (ret != 0)
+                        break;
+                #endif
+
+                    nonceSz = AESGCM_NONCE_SZ;
+                    ret = wc_AesGcmDecrypt(ssl->decrypt.aes, output, input,
+                        dataSz, ssl->decrypt.nonce, nonceSz,
+                        input + dataSz, macSz, aad, aadSz);
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    if (ret == WC_PENDING_E) {
+                        ret = wolfSSL_AsyncPush(ssl,
+                                                   &ssl->decrypt.aes->asyncDev);
+                    }
+                #endif
+                    break;
+            #endif
+
+            #ifdef HAVE_AESCCM
+                case wolfssl_aes_ccm:
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    /* initialize event */
+                    ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev,
+                        WC_ASYNC_FLAG_CALL_AGAIN);
+                    if (ret != 0)
+                        break;
+                #endif
+
+                    nonceSz = AESCCM_NONCE_SZ;
+                    ret = wc_AesCcmDecrypt(ssl->decrypt.aes, output, input,
+                        dataSz, ssl->decrypt.nonce, nonceSz,
+                        input + dataSz, macSz, aad, aadSz);
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    if (ret == WC_PENDING_E) {
+                        ret = wolfSSL_AsyncPush(ssl,
+                                                   &ssl->decrypt.aes->asyncDev);
+                    }
+                #endif
+                    break;
+            #endif
+
+            #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
+                case wolfssl_chacha:
+                    ret = ChaCha20Poly1305_Decrypt(ssl, output, input, dataSz,
+                        ssl->decrypt.nonce, aad, aadSz, input + dataSz);
+                    break;
+            #endif
+
+            #ifdef HAVE_NULL_CIPHER
+                case wolfssl_cipher_null:
+                    ret = Tls13IntegrityOnly_Decrypt(ssl, output, input, dataSz,
+                        ssl->decrypt.nonce, aad, aadSz, input + dataSz);
+                    break;
+            #endif
+                default:
+                    WOLFSSL_MSG("wolfSSL Decrypt programming error");
+                    return DECRYPT_ERROR;
+            }
+
+            /* Advance state */
+            ssl->decrypt.state = CIPHER_STATE_END;
+
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            /* If pending, leave now */
+            if (ret == WC_PENDING_E) {
+                return ret;
+            }
+        #endif
+        }
+        FALL_THROUGH;
+
+        case CIPHER_STATE_END:
+        {
+        #ifdef WOLFSSL_DEBUG_TLS
+            #ifdef CIPHER_NONCE
+                WOLFSSL_MSG("Nonce");
+                WOLFSSL_BUFFER(ssl->decrypt.nonce, ssl->specs.iv_size);
+            #endif
+                WOLFSSL_MSG("Decrypted data");
+                WOLFSSL_BUFFER(output, dataSz);
+        #endif
+
+        #ifdef CIPHER_NONCE
+            ForceZero(ssl->decrypt.nonce, AEAD_NONCE_SZ);
+        #endif
+
+            break;
+        }
+    }
+
+#ifndef WOLFSSL_EARLY_DATA
+    if (ret < 0) {
+        SendAlert(ssl, alert_fatal, bad_record_mac);
+        ret = VERIFY_MAC_ERROR;
+    }
+#endif
+
+    return ret;
+}
+
+/* Persistable BuildTls13Message arguments */
+typedef struct BuildMsg13Args {
+    word32 sz;
+    word32 idx;
+    word32 headerSz;
+    word16 size;
+} BuildMsg13Args;
+
+static void FreeBuildMsg13Args(WOLFSSL* ssl, void* pArgs)
+{
+    BuildMsg13Args* args = (BuildMsg13Args*)pArgs;
+
+    (void)ssl;
+    (void)args;
+
+    /* no allocations in BuildTls13Message */
+}
+
+/* Build SSL Message, encrypted.
+ * TLS v1.3 encryption is AEAD only.
+ *
+ * ssl         The SSL/TLS object.
+ * output      The buffer to write record message to.
+ * outSz       Size of the buffer being written into.
+ * input       The record data to encrypt (excluding record header).
+ * inSz        The size of the record data.
+ * type        The recorder header content type.
+ * hashOutput  Whether to hash the unencrypted record data.
+ * sizeOnly    Only want the size of the record message.
+ * asyncOkay   If non-zero can return WC_PENDING_E, otherwise blocks on crypto
+ * returns the size of the encrypted record message or negative value on error.
+ */
+int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
+                int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay)
+{
+    int ret = 0;
+    BuildMsg13Args* args;
+    BuildMsg13Args  lcl_args;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    args = (BuildMsg13Args*)ssl->async.args;
+    typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+    (void)sizeof(args_test);
+#endif
+
+    WOLFSSL_ENTER("BuildTls13Message");
+
+    ret = WC_NOT_PENDING_E;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (asyncOkay) {
+        ret = wolfSSL_AsyncPop(ssl, &ssl->options.buildMsgState);
+        if (ret != WC_NOT_PENDING_E) {
+            /* Check for error */
+            if (ret < 0)
+                goto exit_buildmsg;
+        }
+    }
+    else
+#endif
+    {
+        args = &lcl_args;
+    }
+
+    /* Reset state */
+    if (ret == WC_NOT_PENDING_E) {
+        ret = 0;
+        ssl->options.buildMsgState = BUILD_MSG_BEGIN;
+        XMEMSET(args, 0, sizeof(BuildMsg13Args));
+
+        args->sz = RECORD_HEADER_SZ + inSz;
+        args->idx  = RECORD_HEADER_SZ;
+        args->headerSz = RECORD_HEADER_SZ;
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        ssl->async.freeArgs = FreeBuildMsg13Args;
+    #endif
+    }
+
+    switch (ssl->options.buildMsgState) {
+        case BUILD_MSG_BEGIN:
+        {
+           /* catch mistaken sizeOnly parameter */
+            if (sizeOnly) {
+                if (output || input) {
+                    WOLFSSL_MSG("BuildTls13Message with sizeOnly "
+                                "doesn't need input or output");
+                    return BAD_FUNC_ARG;
+                }
+            }
+            else if (output == NULL || input == NULL) {
+                return BAD_FUNC_ARG;
+            }
+
+            /* Record layer content type at the end of record data. */
+            args->sz++;
+            /* Authentication data at the end. */
+            args->sz += ssl->specs.aead_mac_size;
+
+            if (sizeOnly)
+                return args->sz;
+
+            if (args->sz > (word32)outSz) {
+                WOLFSSL_MSG("Oops, want to write past output buffer size");
+                return BUFFER_E;
+            }
+
+            /* Record data length. */
+            args->size = (word16)(args->sz - args->headerSz);
+            /* Write/update the record header with the new size.
+             * Always have the content type as application data for encrypted
+             * messages in TLS v1.3.
+             */
+            AddTls13RecordHeader(output, args->size, application_data, ssl);
+
+            /* TLS v1.3 can do in place encryption. */
+            if (input != output + args->idx)
+                XMEMCPY(output + args->idx, input, inSz);
+            args->idx += inSz;
+
+            ssl->options.buildMsgState = BUILD_MSG_HASH;
+        }
+        FALL_THROUGH;
+
+        case BUILD_MSG_HASH:
+        {
+            if (hashOutput) {
+                ret = HashOutput(ssl, output, args->headerSz + inSz, 0);
+                if (ret != 0)
+                    goto exit_buildmsg;
+            }
+
+            /* The real record content type goes at the end of the data. */
+            output[args->idx++] = (byte)type;
+
+            ssl->options.buildMsgState = BUILD_MSG_ENCRYPT;
+        }
+        FALL_THROUGH;
+
+        case BUILD_MSG_ENCRYPT:
+        {
+        #ifdef ATOMIC_USER
+            if (ssl->ctx->MacEncryptCb) {
+                /* User Record Layer Callback handling */
+                byte* mac = output + args->idx;
+                output += args->headerSz;
+
+                ret = ssl->ctx->MacEncryptCb(ssl, mac, output, inSz, type, 0,
+                        output, output, args->size, ssl->MacEncryptCtx);
+            }
+            else
+        #endif
+            {
+#if defined(WOLFSSL_TLS13_DRAFT_18) || defined(WOLFSSL_TLS13_DRAFT_22) || \
+                                       defined(WOLFSSL_TLS13_DRAFT_23)
+                output += args->headerSz;
+                ret = EncryptTls13(ssl, output, output, args->size, NULL, 0,
+                                                                     asyncOkay);
+#else
+                const byte* aad = output;
+                output += args->headerSz;
+                ret = EncryptTls13(ssl, output, output, args->size, aad,
+                                   RECORD_HEADER_SZ, asyncOkay);
+#endif
+            }
+            break;
+        }
+    }
+
+exit_buildmsg:
+
+    WOLFSSL_LEAVE("BuildTls13Message", ret);
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        return ret;
+    }
+#endif
+
+    /* make sure build message state is reset */
+    ssl->options.buildMsgState = BUILD_MSG_BEGIN;
+
+    /* return sz on success */
+    if (ret == 0)
+        ret = args->sz;
+
+    /* Final cleanup */
+    FreeBuildMsg13Args(ssl, args);
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ssl->async.freeArgs = NULL;
+#endif
+
+    return ret;
+}
+
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+/* Find the cipher suite in the suites set in the SSL.
+ *
+ * ssl    SSL/TLS object.
+ * suite  Cipher suite to look for.
+ * returns 1 when suite is found in SSL/TLS object's list and 0 otherwise.
+ */
+static int FindSuiteSSL(WOLFSSL* ssl, byte* suite)
+{
+    word16 i;
+
+    for (i = 0; i < ssl->suites->suiteSz; i += 2) {
+        if (ssl->suites->suites[i+0] == suite[0] &&
+            ssl->suites->suites[i+1] == suite[1]) {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+#endif
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+#if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER)
+/* Create Cookie extension using the hash of the first ClientHello.
+ *
+ * ssl     SSL/TLS object.
+ * hash    The hash data.
+ * hashSz  The size of the hash data in bytes.
+ * returns 0 on success, otherwise failure.
+ */
+static int CreateCookie(WOLFSSL* ssl, byte* hash, byte hashSz)
+{
+    int  ret;
+    byte mac[WC_MAX_DIGEST_SIZE] = {0};
+    Hmac cookieHmac;
+    byte cookieType = 0;
+    byte macSz = 0;
+
+#if !defined(NO_SHA) && defined(NO_SHA256)
+    cookieType = SHA;
+    macSz = WC_SHA_DIGEST_SIZE;
+#endif /* NO_SHA */
+#ifndef NO_SHA256
+    cookieType = WC_SHA256;
+    macSz = WC_SHA256_DIGEST_SIZE;
+#endif /* NO_SHA256 */
+    XMEMSET(&cookieHmac, 0, sizeof(Hmac));
+
+    ret = wc_HmacSetKey(&cookieHmac, cookieType,
+                        ssl->buffers.tls13CookieSecret.buffer,
+                        ssl->buffers.tls13CookieSecret.length);
+    if (ret != 0)
+        return ret;
+    if ((ret = wc_HmacUpdate(&cookieHmac, hash, hashSz)) != 0)
+        return ret;
+    if ((ret = wc_HmacFinal(&cookieHmac, mac)) != 0)
+        return ret;
+
+    /* The cookie data is the hash and the integrity check. */
+    return TLSX_Cookie_Use(ssl, hash, hashSz, mac, macSz, 1);
+}
+#endif
+
+/* Restart the handshake hash with a hash of the previous messages.
+ *
+ * ssl The SSL/TLS object.
+ * returns 0 on success, otherwise failure.
+ */
+static int RestartHandshakeHash(WOLFSSL* ssl)
+{
+    int    ret;
+    Hashes hashes;
+    byte   header[HANDSHAKE_HEADER_SZ] = {0};
+    byte*  hash = NULL;
+    byte   hashSz = 0;
+
+    ret = BuildCertHashes(ssl, &hashes);
+    if (ret != 0)
+        return ret;
+    switch (ssl->specs.mac_algorithm) {
+    #ifndef NO_SHA256
+        case sha256_mac:
+            hash = hashes.sha256;
+            break;
+    #endif
+    #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            hash = hashes.sha384;
+            break;
+    #endif
+    #ifdef WOLFSSL_TLS13_SHA512
+        case sha512_mac:
+            hash = hashes.sha512;
+            break;
+    #endif
+    }
+    hashSz = ssl->specs.hash_size;
+
+    /* check hash */
+    if (hash == NULL && hashSz > 0)
+        return BAD_FUNC_ARG;
+
+    AddTls13HandShakeHeader(header, hashSz, 0, 0, message_hash, ssl);
+
+    WOLFSSL_MSG("Restart Hash");
+    WOLFSSL_BUFFER(hash, hashSz);
+
+#if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER)
+    if (ssl->options.sendCookie) {
+        byte   cookie[OPAQUE8_LEN + WC_MAX_DIGEST_SIZE + OPAQUE16_LEN * 2];
+        TLSX*  ext;
+        word32 idx = 0;
+
+        /* Cookie Data = Hash Len | Hash | CS | KeyShare Group */
+        cookie[idx++] = hashSz;
+        if (hash)
+            XMEMCPY(cookie + idx, hash, hashSz);
+        idx += hashSz;
+        cookie[idx++] = ssl->options.cipherSuite0;
+        cookie[idx++] = ssl->options.cipherSuite;
+        if ((ext = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE)) != NULL) {
+            KeyShareEntry* kse = (KeyShareEntry*)ext->data;
+            c16toa(kse->group, cookie + idx);
+            idx += OPAQUE16_LEN;
+        }
+        return CreateCookie(ssl, cookie, idx);
+    }
+#endif
+
+    ret = InitHandshakeHashes(ssl);
+    if (ret != 0)
+        return ret;
+    ret = HashOutputRaw(ssl, header, sizeof(header));
+    if (ret != 0)
+        return ret;
+    return HashOutputRaw(ssl, hash, hashSz);
+}
+
+/* The value in the random field of a ServerHello to indicate
+ * HelloRetryRequest.
+ */
+static byte helloRetryRequestRandom[] = {
+    0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
+    0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91,
+    0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E,
+    0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C
+};
+#endif /* WOLFSSL_TLS13_DRAFT_18 */
+
+#ifndef NO_WOLFSSL_CLIENT
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+/* Setup pre-shared key based on the details in the extension data.
+ *
+ * ssl  SSL/TLS object.
+ * psk  Pre-shared key extension data.
+ * returns 0 on success, PSK_KEY_ERROR when the client PSK callback fails and
+ * other negative value on failure.
+ */
+static int SetupPskKey(WOLFSSL* ssl, PreSharedKey* psk)
+{
+    int ret;
+    byte suite[2];
+
+    if (psk == NULL)
+        return BAD_FUNC_ARG;
+
+    suite[0] = psk->cipherSuite0;
+    suite[1] = psk->cipherSuite;
+    if (!FindSuiteSSL(ssl, suite))
+        return PSK_KEY_ERROR;
+
+    ssl->options.cipherSuite0 = psk->cipherSuite0;
+    ssl->options.cipherSuite  = psk->cipherSuite;
+    if ((ret = SetCipherSpecs(ssl)) != 0)
+        return ret;
+
+#ifdef HAVE_SESSION_TICKET
+    if (psk->resumption) {
+    #ifdef WOLFSSL_EARLY_DATA
+        if (ssl->session.maxEarlyDataSz == 0)
+            ssl->earlyData = no_early_data;
+    #endif
+        /* Resumption PSK is master secret. */
+        ssl->arrays->psk_keySz = ssl->specs.hash_size;
+#ifdef WOLFSSL_TLS13_DRAFT_18
+        XMEMCPY(ssl->arrays->psk_key, ssl->session.masterSecret,
+                ssl->arrays->psk_keySz);
+#else
+        if ((ret = DeriveResumptionPSK(ssl, ssl->session.ticketNonce.data,
+                    ssl->session.ticketNonce.len, ssl->arrays->psk_key)) != 0) {
+            return ret;
+        }
+#endif
+    }
+#endif
+#ifndef NO_PSK
+    if (!psk->resumption) {
+    #ifndef WOLFSSL_PSK_ONE_ID
+        const char* cipherName = NULL;
+        byte cipherSuite0 = TLS13_BYTE, cipherSuite = WOLFSSL_DEF_PSK_CIPHER;
+
+        /* Get the pre-shared key. */
+        if (ssl->options.client_psk_tls13_cb != NULL) {
+            ssl->arrays->psk_keySz = ssl->options.client_psk_tls13_cb(ssl,
+                    (char *)psk->identity, ssl->arrays->client_identity,
+                    MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN,
+                    &cipherName);
+            if (GetCipherSuiteFromName(cipherName, &cipherSuite0,
+                                                           &cipherSuite) != 0) {
+                return PSK_KEY_ERROR;
+            }
+        }
+        else {
+            ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl,
+                    (char *)psk->identity, ssl->arrays->client_identity,
+                    MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN);
+        }
+        if (ssl->arrays->psk_keySz == 0 ||
+                                     ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
+            return PSK_KEY_ERROR;
+        }
+
+        if (psk->cipherSuite0 != cipherSuite0 ||
+                                              psk->cipherSuite != cipherSuite) {
+            return PSK_KEY_ERROR;
+        }
+    #else
+        /* PSK information loaded during setting of default TLS extensions. */
+    #endif
+    }
+#endif
+
+    if (ssl->options.noPskDheKe)
+        ssl->arrays->preMasterSz = 0;
+
+    /* Derive the early secret using the PSK. */
+    return DeriveEarlySecret(ssl);
+}
+
+/* Derive and write the binders into the ClientHello in space left when
+ * writing the Pre-Shared Key extension.
+ *
+ * ssl     The SSL/TLS object.
+ * output  The buffer containing the ClientHello.
+ * idx     The index at the end of the completed ClientHello.
+ * returns 0 on success and otherwise failure.
+ */
+static int WritePSKBinders(WOLFSSL* ssl, byte* output, word32 idx)
+{
+    int           ret;
+    TLSX*         ext;
+    PreSharedKey* current;
+    byte          binderKey[WC_MAX_DIGEST_SIZE];
+    word16        len;
+
+    WOLFSSL_ENTER("WritePSKBinders");
+
+    ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY);
+    if (ext == NULL)
+        return SANITY_MSG_E;
+
+    /* Get the size of the binders to determine where to write binders. */
+    ret = TLSX_PreSharedKey_GetSizeBinders((PreSharedKey*)ext->data,
+                                                            client_hello, &len);
+    if (ret < 0)
+        return ret;
+    idx -= len;
+
+    /* Hash truncated ClientHello - up to binders. */
+    ret = HashOutput(ssl, output, idx, 0);
+    if (ret != 0)
+        return ret;
+
+    current = (PreSharedKey*)ext->data;
+    /* Calculate the binder for each identity based on previous handshake data.
+     */
+    while (current != NULL) {
+        if ((ret = SetupPskKey(ssl, current)) != 0)
+            return ret;
+
+    #ifdef HAVE_SESSION_TICKET
+        if (current->resumption)
+            ret = DeriveBinderKeyResume(ssl, binderKey);
+    #endif
+    #ifndef NO_PSK
+        if (!current->resumption)
+            ret = DeriveBinderKey(ssl, binderKey);
+    #endif
+        if (ret != 0)
+            return ret;
+
+        /* Derive the Finished message secret. */
+        ret = DeriveFinishedSecret(ssl, binderKey,
+                                             ssl->keys.client_write_MAC_secret);
+        if (ret != 0)
+            return ret;
+
+        /* Build the HMAC of the handshake message data = binder. */
+        ret = BuildTls13HandshakeHmac(ssl, ssl->keys.client_write_MAC_secret,
+            current->binder, &current->binderLen);
+        if (ret != 0)
+            return ret;
+
+        current = current->next;
+    }
+
+    /* Data entered into extension, now write to message. */
+    ret = TLSX_PreSharedKey_WriteBinders((PreSharedKey*)ext->data, output + idx,
+                                                            client_hello, &len);
+    if (ret < 0)
+        return ret;
+
+    /* Hash binders to complete the hash of the ClientHello. */
+    ret = HashOutputRaw(ssl, output + idx, len);
+    if (ret < 0)
+        return ret;
+
+    #ifdef WOLFSSL_EARLY_DATA
+    if (ssl->earlyData != no_early_data) {
+        if ((ret = SetupPskKey(ssl, (PreSharedKey*)ext->data)) != 0)
+            return ret;
+
+        /* Derive early data encryption key. */
+        ret = DeriveTls13Keys(ssl, early_data_key, ENCRYPT_SIDE_ONLY, 1);
+        if (ret != 0)
+            return ret;
+        if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0)
+            return ret;
+    }
+    #endif
+
+    WOLFSSL_LEAVE("WritePSKBinders", ret);
+
+    return ret;
+}
+#endif
+
+/* handle generation of TLS 1.3 client_hello (1) */
+/* Send a ClientHello message to the server.
+ * Include the information required to start a handshake with servers using
+ * protocol versions less than TLS v1.3.
+ * Only a client will send this message.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 0 on success and otherwise failure.
+ */
+int SendTls13ClientHello(WOLFSSL* ssl)
+{
+    byte*  output;
+    word16 length;
+    word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+    int    sendSz;
+    int    ret;
+
+    WOLFSSL_START(WC_FUNC_CLIENT_HELLO_SEND);
+    WOLFSSL_ENTER("SendTls13ClientHello");
+
+#ifdef HAVE_SESSION_TICKET
+    if (ssl->options.resuming &&
+            (ssl->session.version.major != ssl->version.major ||
+             ssl->session.version.minor != ssl->version.minor)) {
+    #ifndef WOLFSSL_NO_TLS12
+        if (ssl->session.version.major == ssl->version.major &&
+            ssl->session.version.minor < ssl->version.minor) {
+            /* Cannot resume with a different protocol version. */
+            ssl->options.resuming = 0;
+            ssl->version.major = ssl->session.version.major;
+            ssl->version.minor = ssl->session.version.minor;
+            return SendClientHello(ssl);
+        }
+        else
+    #endif
+            return VERSION_ERROR;
+    }
+#endif
+
+    if (ssl->suites == NULL) {
+        WOLFSSL_MSG("Bad suites pointer in SendTls13ClientHello");
+        return SUITES_ERROR;
+    }
+
+    /* Version | Random | Session Id | Cipher Suites | Compression */
+    length = VERSION_SZ + RAN_LEN + ENUM_LEN + ssl->suites->suiteSz +
+             SUITE_LEN + COMP_LEN + ENUM_LEN;
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    #if defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
+    length += ID_LEN;
+    #else
+    if (ssl->session.sessionIDSz > 0)
+        length += ssl->session.sessionIDSz;
+    #endif
+#endif
+
+    /* Auto populate extensions supported unless user defined. */
+    if ((ret = TLSX_PopulateExtensions(ssl, 0)) != 0)
+        return ret;
+#ifdef WOLFSSL_EARLY_DATA
+    #ifndef NO_PSK
+        if (!ssl->options.resuming &&
+                                     ssl->options.client_psk_tls13_cb == NULL &&
+                                     ssl->options.client_psk_cb == NULL)
+    #else
+        if (!ssl->options.resuming)
+    #endif
+            ssl->earlyData = no_early_data;
+    if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE)
+        ssl->earlyData = no_early_data;
+    if (ssl->earlyData == no_early_data)
+        TLSX_Remove(&ssl->extensions, TLSX_EARLY_DATA, ssl->heap);
+    if (ssl->earlyData != no_early_data &&
+                                       (ret = TLSX_EarlyData_Use(ssl, 0)) < 0) {
+        return ret;
+    }
+#endif
+    /* Include length of TLS extensions. */
+    ret = TLSX_GetRequestSize(ssl, client_hello, &length);
+    if (ret != 0)
+        return ret;
+
+    /* Total message size. */
+    sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+
+    /* Check buffers are big enough and grow if needed. */
+    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+        return ret;
+
+    /* Get position in output buffer to write new message to. */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+
+    /* Put the record and handshake headers on. */
+    AddTls13Headers(output, length, client_hello, ssl);
+
+    /* Protocol version - negotiation now in extension: supported_versions. */
+    output[idx++] = SSLv3_MAJOR;
+    output[idx++] = TLSv1_2_MINOR;
+    /* Keep for downgrade. */
+    ssl->chVersion = ssl->version;
+
+    /* Client Random */
+    if (ssl->options.connectState == CONNECT_BEGIN) {
+        ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN);
+        if (ret != 0)
+            return ret;
+
+        /* Store random for possible second ClientHello. */
+        XMEMCPY(ssl->arrays->clientRandom, output + idx, RAN_LEN);
+    }
+    else
+        XMEMCPY(output + idx, ssl->arrays->clientRandom, RAN_LEN);
+    idx += RAN_LEN;
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    /* TLS v1.3 does not use session id - 0 length. */
+    output[idx++] = 0;
+#else
+    if (ssl->session.sessionIDSz > 0) {
+        /* Session resumption for old versions of protocol. */
+        output[idx++] = ID_LEN;
+        XMEMCPY(output + idx, ssl->session.sessionID, ssl->session.sessionIDSz);
+        idx += ID_LEN;
+    }
+    else {
+    #ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT
+        output[idx++] = ID_LEN;
+        XMEMCPY(output + idx, ssl->arrays->clientRandom, ID_LEN);
+        idx += ID_LEN;
+    #else
+        /* TLS v1.3 does not use session id - 0 length. */
+        output[idx++] = 0;
+    #endif /* WOLFSSL_TLS13_MIDDLEBOX_COMPAT */
+    }
+#endif /* WOLFSSL_TLS13_DRAFT_18 */
+
+    /* Cipher suites */
+    c16toa(ssl->suites->suiteSz, output + idx);
+    idx += OPAQUE16_LEN;
+    XMEMCPY(output + idx, &ssl->suites->suites, ssl->suites->suiteSz);
+    idx += ssl->suites->suiteSz;
+
+    /* Compression not supported in TLS v1.3. */
+    output[idx++] = COMP_LEN;
+    output[idx++] = NO_COMPRESSION;
+
+    /* Write out extensions for a request. */
+    length = 0;
+    ret = TLSX_WriteRequest(ssl, output + idx, client_hello, &length);
+    if (ret != 0)
+        return ret;
+    idx += length;
+
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+    /* Resumption has a specific set of extensions and binder is calculated
+     * for each identity.
+     */
+    if (TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY))
+        ret = WritePSKBinders(ssl, output, idx);
+    else
+#endif
+        ret = HashOutput(ssl, output, idx, 0);
+    if (ret != 0)
+        return ret;
+
+    ssl->options.clientState = CLIENT_HELLO_COMPLETE;
+
+#ifdef WOLFSSL_CALLBACKS
+    if (ssl->hsInfoOn) AddPacketName(ssl, "ClientHello");
+    if (ssl->toInfoOn) {
+        AddPacketInfo(ssl, "ClientHello", handshake, output, sendSz,
+                      WRITE_PROTO, ssl->heap);
+    }
+#endif
+
+    ssl->buffers.outputBuffer.length += sendSz;
+
+#ifdef WOLFSSL_EARLY_DATA_GROUP
+    if (ssl->earlyData == no_early_data)
+#endif
+        ret = SendBuffered(ssl);
+
+
+    WOLFSSL_LEAVE("SendTls13ClientHello", ret);
+    WOLFSSL_END(WC_FUNC_CLIENT_HELLO_SEND);
+
+    return ret;
+}
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* handle rocessing of TLS 1.3 hello_retry_request (6) */
+/* Parse and handle a HelloRetryRequest message.
+ * Only a client will receive this message.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The message buffer.
+ * inOutIdx  On entry, the index into the message buffer of
+ *           HelloRetryRequest.
+ *           On exit, the index of byte after the HelloRetryRequest message.
+ * totalSz   The length of the current handshake message.
+ * returns 0 on success and otherwise failure.
+ */
+static int DoTls13HelloRetryRequest(WOLFSSL* ssl, const byte* input,
+                                    word32* inOutIdx, word32 totalSz)
+{
+    int             ret;
+    word32          begin = *inOutIdx;
+    word32          i = begin;
+    word16          totalExtSz;
+    ProtocolVersion pv;
+
+    WOLFSSL_ENTER("DoTls13HelloRetryRequest");
+
+#ifdef WOLFSSL_CALLBACKS
+    if (ssl->hsInfoOn) AddPacketName(ssl, "HelloRetryRequest");
+    if (ssl->toInfoOn) AddLateName("HelloRetryRequest", &ssl->timeoutInfo);
+#endif
+
+    /* Version info and length field of extension data. */
+    if (totalSz < i - begin + OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN)
+        return BUFFER_ERROR;
+
+    /* Protocol version. */
+    XMEMCPY(&pv, input + i, OPAQUE16_LEN);
+    i += OPAQUE16_LEN;
+    ret = CheckVersion(ssl, pv);
+    if (ret != 0)
+        return ret;
+
+    /* Length of extension data. */
+    ato16(&input[i], &totalExtSz);
+    i += OPAQUE16_LEN;
+    if (totalExtSz == 0) {
+        WOLFSSL_MSG("HelloRetryRequest must contain extensions");
+        return MISSING_HANDSHAKE_DATA;
+    }
+
+    /* Extension data. */
+    if (i - begin + totalExtSz > totalSz)
+        return BUFFER_ERROR;
+    if ((ret = TLSX_Parse(ssl, (byte *)(input + i), totalExtSz,
+                          hello_retry_request, NULL)) != 0)
+        return ret;
+    /* The KeyShare extension parsing fails when not valid. */
+
+    /* Move index to byte after message. */
+    *inOutIdx = i + totalExtSz;
+
+    ssl->options.tls1_3 = 1;
+    ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE;
+
+    WOLFSSL_LEAVE("DoTls13HelloRetryRequest", ret);
+
+    return ret;
+}
+#endif
+
+
+/* handle processing of TLS 1.3 server_hello (2) and hello_retry_request (6) */
+/* Handle the ServerHello message from the server.
+ * Only a client will receive this message.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The message buffer.
+ * inOutIdx  On entry, the index into the message buffer of ServerHello.
+ *           On exit, the index of byte after the ServerHello message.
+ * helloSz   The length of the current handshake message.
+ * returns 0 on success and otherwise failure.
+ */
+int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                       word32 helloSz, byte* extMsgType)
+{
+    ProtocolVersion pv;
+    word32          i = *inOutIdx;
+    word32          begin = i;
+    int             ret;
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    byte            sessIdSz;
+    const byte*     sessId;
+    byte            b;
+    int             foundVersion;
+#endif
+    word16          totalExtSz;
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+    TLSX*           ext;
+    PreSharedKey*   psk = NULL;
+#endif
+
+    WOLFSSL_START(WC_FUNC_SERVER_HELLO_DO);
+    WOLFSSL_ENTER("DoTls13ServerHello");
+
+#ifdef WOLFSSL_CALLBACKS
+    if (ssl->hsInfoOn) AddPacketName(ssl, "ServerHello");
+    if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo);
+#endif
+
+    /* Protocol version length check. */
+    if (OPAQUE16_LEN > helloSz)
+        return BUFFER_ERROR;
+
+    /* Protocol version */
+    XMEMCPY(&pv, input + i, OPAQUE16_LEN);
+    i += OPAQUE16_LEN;
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    ret = CheckVersion(ssl, pv);
+    if (ret != 0)
+        return ret;
+    if (!IsAtLeastTLSv1_3(pv) && pv.major != TLS_DRAFT_MAJOR) {
+#ifndef WOLFSSL_NO_TLS12
+        if (ssl->options.downgrade) {
+            ssl->version = pv;
+            return DoServerHello(ssl, input, inOutIdx, helloSz);
+        }
+#endif
+
+        WOLFSSL_MSG("Client using higher version, fatal error");
+        return VERSION_ERROR;
+    }
+#else
+#ifndef WOLFSSL_NO_TLS12
+    if (pv.major == ssl->version.major  && pv.minor < TLSv1_2_MINOR &&
+                                                       ssl->options.downgrade) {
+        /* Force client hello version 1.2 to work for static RSA. */
+        ssl->chVersion.minor = TLSv1_2_MINOR;
+        ssl->version.minor = TLSv1_2_MINOR;
+        return DoServerHello(ssl, input, inOutIdx, helloSz);
+    }
+#endif
+    if (pv.major != ssl->version.major || pv.minor != TLSv1_2_MINOR)
+        return VERSION_ERROR;
+#endif
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    /* Random length check */
+    if ((i - begin) + RAN_LEN > helloSz)
+        return BUFFER_ERROR;
+#else
+    /* Random and session id length check */
+    if ((i - begin) + RAN_LEN + ENUM_LEN > helloSz)
+        return BUFFER_ERROR;
+
+    if (XMEMCMP(input + i, helloRetryRequestRandom, RAN_LEN) == 0)
+        *extMsgType = hello_retry_request;
+#endif
+
+    /* Server random - keep for debugging. */
+    XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN);
+    i += RAN_LEN;
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    /* Session id */
+    sessIdSz = input[i++];
+    if ((i - begin) + sessIdSz > helloSz)
+        return BUFFER_ERROR;
+    sessId = input + i;
+    i += sessIdSz;
+#endif /* WOLFSSL_TLS13_DRAFT_18 */
+    ssl->options.haveSessionId = 1;
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    /* Ciphersuite check */
+    if ((i - begin) + OPAQUE16_LEN + OPAQUE16_LEN > helloSz)
+        return BUFFER_ERROR;
+#else
+    /* Ciphersuite and compression check */
+    if ((i - begin) + OPAQUE16_LEN + OPAQUE8_LEN > helloSz)
+        return BUFFER_ERROR;
+#endif
+
+    /* Set the cipher suite from the message. */
+    ssl->options.cipherSuite0 = input[i++];
+    ssl->options.cipherSuite  = input[i++];
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    /* Compression */
+    b = input[i++];
+    if (b != 0) {
+        WOLFSSL_MSG("Must be no compression types in list");
+        return INVALID_PARAMETER;
+    }
+#endif
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    if ((i - begin) + OPAQUE16_LEN > helloSz) {
+        if (!ssl->options.downgrade)
+            return BUFFER_ERROR;
+#ifndef WOLFSSL_NO_TLS12
+        ssl->version.minor = TLSv1_2_MINOR;
+#endif
+        ssl->options.haveEMS = 0;
+    }
+    if ((i - begin) < helloSz)
+#endif
+    {
+        /* Get extension length and length check. */
+        if ((i - begin) + OPAQUE16_LEN > helloSz)
+            return BUFFER_ERROR;
+        ato16(&input[i], &totalExtSz);
+        i += OPAQUE16_LEN;
+        if ((i - begin) + totalExtSz > helloSz)
+            return BUFFER_ERROR;
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+        /* Need to negotiate version first. */
+        if ((ret = TLSX_ParseVersion(ssl, (byte*)input + i, totalExtSz,
+                                                 *extMsgType, &foundVersion))) {
+            return ret;
+        }
+        if (!foundVersion) {
+            if (!ssl->options.downgrade) {
+                WOLFSSL_MSG("Server trying to downgrade to version less than "
+                            "TLS v1.3");
+                return VERSION_ERROR;
+            }
+
+            if (pv.minor < ssl->options.minDowngrade)
+                return VERSION_ERROR;
+            ssl->version.minor = pv.minor;
+        }
+#endif
+
+        /* Parse and handle extensions. */
+        ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz, *extMsgType,
+                                                                          NULL);
+        if (ret != 0)
+            return ret;
+
+        i += totalExtSz;
+    }
+    *inOutIdx = i;
+
+    ssl->options.serverState = SERVER_HELLO_COMPLETE;
+
+#ifdef HAVE_SECRET_CALLBACK
+    if (ssl->sessionSecretCb != NULL) {
+        int secretSz = SECRET_LEN;
+        ret = ssl->sessionSecretCb(ssl, ssl->session.masterSecret,
+                                   &secretSz, ssl->sessionSecretCtx);
+        if (ret != 0 || secretSz != SECRET_LEN) {
+            return SESSION_SECRET_CB_E;
+        }
+    }
+#endif /* HAVE_SECRET_CALLBACK */
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    /* Version only negotiated in extensions for TLS v1.3.
+     * Only now do we know how to deal with session id.
+     */
+    if (!IsAtLeastTLSv1_3(ssl->version)) {
+#ifndef WOLFSSL_NO_TLS12
+        ssl->arrays->sessionIDSz = sessIdSz;
+
+        if (ssl->arrays->sessionIDSz > ID_LEN) {
+            WOLFSSL_MSG("Invalid session ID size");
+            ssl->arrays->sessionIDSz = 0;
+            return BUFFER_ERROR;
+        }
+        else if (ssl->arrays->sessionIDSz) {
+            XMEMCPY(ssl->arrays->sessionID, sessId, ssl->arrays->sessionIDSz);
+            ssl->options.haveSessionId = 1;
+        }
+
+        /* Force client hello version 1.2 to work for static RSA. */
+        ssl->chVersion.minor = TLSv1_2_MINOR;
+        /* Complete TLS v1.2 processing of ServerHello. */
+        ret = CompleteServerHello(ssl);
+#else
+        WOLFSSL_MSG("Client using higher version, fatal error");
+        ret = VERSION_ERROR;
+#endif
+
+        WOLFSSL_LEAVE("DoTls13ServerHello", ret);
+
+        return ret;
+    }
+
+    #ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT
+    if (sessIdSz == 0)
+        return INVALID_PARAMETER;
+    if (ssl->session.sessionIDSz != 0) {
+        if (ssl->session.sessionIDSz != sessIdSz ||
+                   XMEMCMP(ssl->session.sessionID, sessId, sessIdSz) != 0) {
+            return INVALID_PARAMETER;
+        }
+    }
+    else if (XMEMCMP(ssl->arrays->clientRandom, sessId, sessIdSz) != 0)
+        return INVALID_PARAMETER;
+    #else
+    if (sessIdSz != ssl->session.sessionIDSz || (sessIdSz > 0 &&
+                  XMEMCMP(ssl->session.sessionID, sessId, sessIdSz) != 0)) {
+        WOLFSSL_MSG("Server sent different session id");
+        return INVALID_PARAMETER;
+    }
+    #endif /* WOLFSSL_TLS13_MIDDLEBOX_COMPAT */
+#endif
+
+    ret = SetCipherSpecs(ssl);
+    if (ret != 0)
+        return ret;
+#ifdef HAVE_NULL_CIPHER
+    if (ssl->options.cipherSuite0 == ECC_BYTE &&
+                              (ssl->options.cipherSuite == TLS_SHA256_SHA256 ||
+                               ssl->options.cipherSuite == TLS_SHA384_SHA384)) {
+        ;
+    }
+    else
+#endif
+    /* Check that the negotiated ciphersuite matches protocol version. */
+    if (ssl->options.cipherSuite0 != TLS13_BYTE) {
+        WOLFSSL_MSG("Server sent non-TLS13 cipher suite in TLS 1.3 packet");
+        return INVALID_PARAMETER;
+    }
+
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    if (*extMsgType == server_hello)
+#endif
+    {
+        ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY);
+        if (ext != NULL)
+            psk = (PreSharedKey*)ext->data;
+        while (psk != NULL && !psk->chosen)
+            psk = psk->next;
+        if (psk == NULL) {
+            ssl->options.resuming = 0;
+            ssl->arrays->psk_keySz = 0;
+            XMEMSET(ssl->arrays->psk_key, 0, MAX_PSK_KEY_LEN);
+        }
+        else if ((ret = SetupPskKey(ssl, psk)) != 0)
+            return ret;
+    }
+#endif
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    ssl->keys.encryptionOn = 1;
+#else
+    if (*extMsgType == server_hello) {
+        ssl->keys.encryptionOn = 1;
+        ssl->options.serverState = SERVER_HELLO_COMPLETE;
+    }
+    else {
+        ssl->options.tls1_3 = 1;
+        ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE;
+
+        ret = RestartHandshakeHash(ssl);
+    }
+#endif
+
+    WOLFSSL_LEAVE("DoTls13ServerHello", ret);
+    WOLFSSL_END(WC_FUNC_SERVER_HELLO_DO);
+
+    return ret;
+}
+
+/* handle processing TLS 1.3 encrypted_extensions (8) */
+/* Parse and handle an EncryptedExtensions message.
+ * Only a client will receive this message.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The message buffer.
+ * inOutIdx  On entry, the index into the message buffer of
+ *           EncryptedExtensions.
+ *           On exit, the index of byte after the EncryptedExtensions
+ *           message.
+ * totalSz   The length of the current handshake message.
+ * returns 0 on success and otherwise failure.
+ */
+static int DoTls13EncryptedExtensions(WOLFSSL* ssl, const byte* input,
+                                      word32* inOutIdx, word32 totalSz)
+{
+    int    ret;
+    word32 begin = *inOutIdx;
+    word32 i = begin;
+    word16 totalExtSz;
+
+    WOLFSSL_START(WC_FUNC_ENCRYPTED_EXTENSIONS_DO);
+    WOLFSSL_ENTER("DoTls13EncryptedExtensions");
+
+#ifdef WOLFSSL_CALLBACKS
+    if (ssl->hsInfoOn) AddPacketName(ssl, "EncryptedExtensions");
+    if (ssl->toInfoOn) AddLateName("EncryptedExtensions", &ssl->timeoutInfo);
+#endif
+
+    /* Length field of extension data. */
+    if (totalSz < i - begin + OPAQUE16_LEN)
+        return BUFFER_ERROR;
+    ato16(&input[i], &totalExtSz);
+    i += OPAQUE16_LEN;
+
+    /* Extension data. */
+    if (i - begin + totalExtSz > totalSz)
+        return BUFFER_ERROR;
+    if ((ret = TLSX_Parse(ssl, (byte *)(input + i), totalExtSz,
+                          encrypted_extensions, NULL)))
+        return ret;
+
+    /* Move index to byte after message. */
+    *inOutIdx = i + totalExtSz;
+
+    /* Always encrypted. */
+    *inOutIdx += ssl->keys.padSz;
+
+#ifdef WOLFSSL_EARLY_DATA
+    if (ssl->earlyData != no_early_data) {
+        TLSX* ext = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA);
+        if (ext == NULL || !ext->val)
+            ssl->earlyData = no_early_data;
+    }
+#endif
+
+#ifdef WOLFSSL_EARLY_DATA
+    if (ssl->earlyData == no_early_data) {
+        ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY);
+        if (ret != 0)
+            return ret;
+    }
+#endif
+
+    ssl->options.serverState = SERVER_ENCRYPTED_EXTENSIONS_COMPLETE;
+
+    WOLFSSL_LEAVE("DoTls13EncryptedExtensions", ret);
+    WOLFSSL_END(WC_FUNC_ENCRYPTED_EXTENSIONS_DO);
+
+    return ret;
+}
+
+/* handle processing TLS v1.3 certificate_request (13) */
+/* Handle a TLS v1.3 CertificateRequest message.
+ * This message is always encrypted.
+ * Only a client will receive this message.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The message buffer.
+ * inOutIdx  On entry, the index into the message buffer of CertificateRequest.
+ *           On exit, the index of byte after the CertificateRequest message.
+ * size      The length of the current handshake message.
+ * returns 0 on success and otherwise failure.
+ */
+static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input,
+                                     word32* inOutIdx, word32 size)
+{
+    word16      len;
+    word32      begin = *inOutIdx;
+    int         ret = 0;
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    Suites      peerSuites;
+#endif
+#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
+    CertReqCtx* certReqCtx;
+#endif
+
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_REQUEST_DO);
+    WOLFSSL_ENTER("DoTls13CertificateRequest");
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    XMEMSET(&peerSuites, 0, sizeof(Suites));
+#endif
+#ifdef WOLFSSL_CALLBACKS
+    if (ssl->hsInfoOn) AddPacketName(ssl, "CertificateRequest");
+    if (ssl->toInfoOn) AddLateName("CertificateRequest", &ssl->timeoutInfo);
+#endif
+
+    if ((*inOutIdx - begin) + OPAQUE8_LEN > size)
+        return BUFFER_ERROR;
+
+    /* Length of the request context. */
+    len = input[(*inOutIdx)++];
+    if ((*inOutIdx - begin) + len > size)
+        return BUFFER_ERROR;
+    if (ssl->options.connectState < FINISHED_DONE && len > 0)
+        return BUFFER_ERROR;
+
+#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
+    /* CertReqCtx has one byte at end for context value.
+     * Increase size to handle other implementations sending more than one byte.
+     * That is, allocate extra space, over one byte, to hold the context value.
+     */
+    certReqCtx = (CertReqCtx*)XMALLOC(sizeof(CertReqCtx) + len - 1, ssl->heap,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+    if (certReqCtx == NULL)
+        return MEMORY_E;
+    certReqCtx->next = ssl->certReqCtx;
+    certReqCtx->len = len;
+    XMEMCPY(&certReqCtx->ctx, input + *inOutIdx, len);
+    ssl->certReqCtx = certReqCtx;
+#endif
+    *inOutIdx += len;
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    /* Signature and hash algorithms. */
+    if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
+        return BUFFER_ERROR;
+    ato16(input + *inOutIdx, &len);
+    *inOutIdx += OPAQUE16_LEN;
+    if ((*inOutIdx - begin) + len > size)
+        return BUFFER_ERROR;
+    if (PickHashSigAlgo(ssl, input + *inOutIdx, len) != 0 &&
+                 ssl->buffers.certificate && ssl->buffers.certificate->buffer &&
+                 ssl->buffers.key && ssl->buffers.key->buffer) {
+        return INVALID_PARAMETER;
+    }
+    *inOutIdx += len;
+
+    /* Length of certificate authority data. */
+    if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
+        return BUFFER_ERROR;
+    ato16(input + *inOutIdx, &len);
+    *inOutIdx += OPAQUE16_LEN;
+    if ((*inOutIdx - begin) + len > size)
+        return BUFFER_ERROR;
+
+    /* Certificate authorities. */
+    while (len) {
+        word16 dnSz;
+
+        if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
+            return BUFFER_ERROR;
+
+        ato16(input + *inOutIdx, &dnSz);
+        *inOutIdx += OPAQUE16_LEN;
+
+        if ((*inOutIdx - begin) + dnSz > size)
+            return BUFFER_ERROR;
+
+        *inOutIdx += dnSz;
+        len -= OPAQUE16_LEN + dnSz;
+    }
+
+    /* Certificate extensions */
+    if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
+        return BUFFER_ERROR;
+    ato16(input + *inOutIdx, &len);
+    *inOutIdx += OPAQUE16_LEN;
+    if ((*inOutIdx - begin) + len > size)
+        return BUFFER_ERROR;
+    *inOutIdx += len;
+#else
+    /* TODO: Add support for more extensions:
+     *   signed_certificate_timestamp, certificate_authorities, oid_filters.
+     */
+    /* Certificate extensions */
+    if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
+        return BUFFER_ERROR;
+    ato16(input + *inOutIdx, &len);
+    *inOutIdx += OPAQUE16_LEN;
+    if ((*inOutIdx - begin) + len > size)
+        return BUFFER_ERROR;
+    if (len == 0)
+        return INVALID_PARAMETER;
+    if ((ret = TLSX_Parse(ssl, (byte *)(input + *inOutIdx), len,
+                                           certificate_request, &peerSuites))) {
+        return ret;
+    }
+    *inOutIdx += len;
+#endif
+
+    if (ssl->buffers.certificate && ssl->buffers.certificate->buffer &&
+        ((ssl->buffers.key && ssl->buffers.key->buffer)
+        #ifdef HAVE_PK_CALLBACKS
+            || wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)
+        #endif
+    )) {
+#ifndef WOLFSSL_TLS13_DRAFT_18
+        if (PickHashSigAlgo(ssl, peerSuites.hashSigAlgo,
+                                               peerSuites.hashSigAlgoSz) != 0) {
+            return INVALID_PARAMETER;
+        }
+#endif
+        ssl->options.sendVerify = SEND_CERT;
+    }
+    else {
+        ssl->options.sendVerify = SEND_BLANK_CERT;
+    }
+
+    /* This message is always encrypted so add encryption padding. */
+    *inOutIdx += ssl->keys.padSz;
+
+    WOLFSSL_LEAVE("DoTls13CertificateRequest", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_DO);
+
+    return ret;
+}
+
+#endif /* !NO_WOLFSSL_CLIENT */
+
+#ifndef NO_WOLFSSL_SERVER
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+/* Refine list of supported cipher suites to those common to server and client.
+ *
+ * ssl         SSL/TLS object.
+ * peerSuites  The peer's advertised list of supported cipher suites.
+ */
+static void RefineSuites(WOLFSSL* ssl, Suites* peerSuites)
+{
+    byte suites[WOLFSSL_MAX_SUITE_SZ];
+    int suiteSz = 0;
+    word16 i, j;
+
+    XMEMSET(suites, 0, WOLFSSL_MAX_SUITE_SZ);
+
+    for (i = 0; i < ssl->suites->suiteSz; i += 2) {
+        for (j = 0; j < peerSuites->suiteSz; j += 2) {
+            if (ssl->suites->suites[i+0] == peerSuites->suites[j+0] &&
+                ssl->suites->suites[i+1] == peerSuites->suites[j+1]) {
+                suites[suiteSz++] = peerSuites->suites[j+0];
+                suites[suiteSz++] = peerSuites->suites[j+1];
+            }
+        }
+    }
+
+    ssl->suites->suiteSz = suiteSz;
+    XMEMCPY(ssl->suites->suites, &suites, sizeof(suites));
+}
+
+/* Handle any Pre-Shared Key (PSK) extension.
+ * Must do this in ClientHello as it requires a hash of the truncated message.
+ * Don't know size of binders until Pre-Shared Key extension has been parsed.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The ClientHello message.
+ * helloSz   The size of the ClientHello message (including binders if present).
+ * usingPSK  Indicates handshake is using Pre-Shared Keys.
+ * returns 0 on success and otherwise failure.
+ */
+static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz,
+                           int* usingPSK)
+{
+    int           ret;
+    TLSX*         ext;
+    word16        bindersLen;
+    PreSharedKey* current;
+    byte          binderKey[WC_MAX_DIGEST_SIZE];
+    byte          binder[WC_MAX_DIGEST_SIZE];
+    word32        binderLen;
+    word16        modes;
+    byte          suite[2];
+#ifdef WOLFSSL_EARLY_DATA
+    int           pskCnt = 0;
+    TLSX*         extEarlyData;
+#endif
+#ifndef NO_PSK
+    const char*   cipherName = NULL;
+    byte          cipherSuite0 = TLS13_BYTE;
+    byte          cipherSuite  = WOLFSSL_DEF_PSK_CIPHER;
+#endif
+
+    WOLFSSL_ENTER("DoPreSharedKeys");
+
+    ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY);
+    if (ext == NULL) {
+        /* Hash data up to binders for deriving binders in PSK extension. */
+        ret = HashInput(ssl, input,  helloSz);
+        return ret;
+    }
+
+    /* Extensions pushed on stack/list and PSK must be last. */
+    if (ssl->extensions != ext)
+        return PSK_KEY_ERROR;
+
+    /* Assume we are going to resume with a pre-shared key. */
+    ssl->options.resuming = 1;
+
+    /* Find the pre-shared key extension and calculate hash of truncated
+     * ClientHello for binders.
+     */
+    ret = TLSX_PreSharedKey_GetSizeBinders((PreSharedKey*)ext->data,
+                                                     client_hello, &bindersLen);
+    if (ret < 0)
+        return ret;
+
+    /* Hash data up to binders for deriving binders in PSK extension. */
+    ret = HashInput(ssl, input,  helloSz - bindersLen);
+    if (ret != 0)
+        return ret;
+
+    /* Look through all client's pre-shared keys for a match. */
+    current = (PreSharedKey*)ext->data;
+    while (current != NULL) {
+    #ifdef WOLFSSL_EARLY_DATA
+        pskCnt++;
+    #endif
+
+    #ifndef NO_PSK
+        if (current->identityLen > MAX_PSK_ID_LEN) {
+            return BUFFER_ERROR;
+        }
+        XMEMCPY(ssl->arrays->client_identity, current->identity,
+                current->identityLen);
+        ssl->arrays->client_identity[current->identityLen] = '\0';
+    #endif
+
+    #ifdef HAVE_SESSION_TICKET
+        /* Decode the identity. */
+        if ((ret = DoClientTicket(ssl, current->identity, current->identityLen))
+                                                     == WOLFSSL_TICKET_RET_OK) {
+            word32 now;
+            int    diff;
+
+            now = TimeNowInMilliseconds();
+            if (now == (word32)GETTIME_ERROR)
+                return now;
+            diff = now - ssl->session.ticketSeen;
+            diff -= current->ticketAge - ssl->session.ticketAdd;
+            /* Check session and ticket age timeout.
+             * Allow +/- 1000 milliseconds on ticket age.
+             */
+            if (diff > (int)ssl->timeout * 1000 || diff < -1000 ||
+                                     diff - MAX_TICKET_AGE_SECS * 1000 > 1000) {
+                /* Invalid difference, fallback to full handshake. */
+                ssl->options.resuming = 0;
+                break;
+            }
+
+            /* Check whether resumption is possible based on suites in SSL and
+             * ciphersuite in ticket.
+             */
+            suite[0] = ssl->session.cipherSuite0;
+            suite[1] = ssl->session.cipherSuite;
+            if (!FindSuiteSSL(ssl, suite)) {
+                current = current->next;
+                continue;
+            }
+
+        #ifdef WOLFSSL_EARLY_DATA
+            ssl->options.maxEarlyDataSz = ssl->session.maxEarlyDataSz;
+        #endif
+            /* Use the same cipher suite as before and set up for use. */
+            ssl->options.cipherSuite0   = ssl->session.cipherSuite0;
+            ssl->options.cipherSuite    = ssl->session.cipherSuite;
+            ret = SetCipherSpecs(ssl);
+            if (ret != 0)
+                return ret;
+
+            /* Resumption PSK is resumption master secret. */
+            ssl->arrays->psk_keySz = ssl->specs.hash_size;
+        #ifdef WOLFSSL_TLS13_DRAFT_18
+            XMEMCPY(ssl->arrays->psk_key, ssl->session.masterSecret,
+                    ssl->arrays->psk_keySz);
+        #else
+            if ((ret = DeriveResumptionPSK(ssl, ssl->session.ticketNonce.data,
+                    ssl->session.ticketNonce.len, ssl->arrays->psk_key)) != 0) {
+                return ret;
+            }
+        #endif
+
+            /* Derive the early secret using the PSK. */
+            ret = DeriveEarlySecret(ssl);
+            if (ret != 0)
+                return ret;
+            /* Derive the binder key to use to with HMAC. */
+            ret = DeriveBinderKeyResume(ssl, binderKey);
+            if (ret != 0)
+                return ret;
+        }
+        else
+    #endif
+    #ifndef NO_PSK
+        if ((ssl->options.server_psk_tls13_cb != NULL &&
+             (ssl->arrays->psk_keySz = ssl->options.server_psk_tls13_cb(ssl,
+                             ssl->arrays->client_identity, ssl->arrays->psk_key,
+                             MAX_PSK_KEY_LEN, &cipherName)) != 0 &&
+             GetCipherSuiteFromName(cipherName, &cipherSuite0,
+                                                          &cipherSuite) == 0) ||
+            (ssl->options.server_psk_cb != NULL &&
+             (ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl,
+                             ssl->arrays->client_identity, ssl->arrays->psk_key,
+                             MAX_PSK_KEY_LEN)) != 0)) {
+            if (ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN)
+                return PSK_KEY_ERROR;
+
+            /* Check whether PSK ciphersuite is in SSL. */
+            suite[0] = cipherSuite0;
+            suite[1] = cipherSuite;
+            if (!FindSuiteSSL(ssl, suite)) {
+                current = current->next;
+                continue;
+            }
+
+            /* Default to ciphersuite if cb doesn't specify. */
+            ssl->options.resuming = 0;
+
+            /* PSK age is always zero. */
+            if (current->ticketAge != ssl->session.ticketAdd)
+                return PSK_KEY_ERROR;
+
+            /* Set PSK ciphersuite into SSL. */
+            ssl->options.cipherSuite0 = cipherSuite0;
+            ssl->options.cipherSuite  = cipherSuite;
+            ret = SetCipherSpecs(ssl);
+            if (ret != 0)
+                return ret;
+
+            /* Derive the early secret using the PSK. */
+            ret = DeriveEarlySecret(ssl);
+            if (ret != 0)
+                return ret;
+            /* Derive the binder key to use to with HMAC. */
+            ret = DeriveBinderKey(ssl, binderKey);
+            if (ret != 0)
+                return ret;
+        }
+        else
+    #endif
+        {
+            current = current->next;
+            continue;
+        }
+
+        ssl->options.sendVerify = 0;
+
+        /* Derive the Finished message secret. */
+        ret = DeriveFinishedSecret(ssl, binderKey,
+                                             ssl->keys.client_write_MAC_secret);
+        if (ret != 0)
+            return ret;
+
+        /* Derive the binder and compare with the one in the extension. */
+        ret = BuildTls13HandshakeHmac(ssl,
+                         ssl->keys.client_write_MAC_secret, binder, &binderLen);
+        if (ret != 0)
+            return ret;
+        if (binderLen != current->binderLen ||
+                             XMEMCMP(binder, current->binder, binderLen) != 0) {
+            return BAD_BINDER;
+        }
+
+        /* This PSK works, no need to try any more. */
+        current->chosen = 1;
+        ext->resp = 1;
+        break;
+    }
+
+    /* Hash the rest of the ClientHello. */
+    ret = HashInputRaw(ssl, input + helloSz - bindersLen, bindersLen);
+    if (ret != 0)
+        return ret;
+
+    if (current == NULL) {
+#ifdef WOLFSSL_PSK_ID_PROTECTION
+    #ifndef NO_CERTS
+        if (ssl->buffers.certChainCnt != 0)
+            return 0;
+    #endif
+        return BAD_BINDER;
+#else
+        return 0;
+#endif
+    }
+
+#ifdef WOLFSSL_EARLY_DATA
+    extEarlyData = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA);
+    if (extEarlyData != NULL) {
+        if (ssl->earlyData != no_early_data && current == ext->data) {
+            extEarlyData->resp = 1;
+
+            /* Derive early data decryption key. */
+            ret = DeriveTls13Keys(ssl, early_data_key, DECRYPT_SIDE_ONLY, 1);
+            if (ret != 0)
+                return ret;
+            if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
+                return ret;
+
+            ssl->earlyData = process_early_data;
+        }
+        else
+            extEarlyData->resp = 0;
+    }
+#endif
+
+    /* Get the PSK key exchange modes the client wants to negotiate. */
+    ext = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES);
+    if (ext == NULL)
+        return MISSING_HANDSHAKE_DATA;
+    modes = ext->val;
+
+    ext = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
+    /* Use (EC)DHE for forward-security if possible. */
+    if ((modes & (1 << PSK_DHE_KE)) != 0 && !ssl->options.noPskDheKe &&
+                                                                  ext != NULL) {
+        /* Only use named group used in last session. */
+        ssl->namedGroup = ssl->session.namedGroup;
+
+        /* Pick key share and Generate a new key if not present. */
+        ret = TLSX_KeyShare_Establish(ssl);
+        if (ret == KEY_SHARE_ERROR) {
+            ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE;
+            ret = 0;
+        }
+        else if (ret < 0)
+            return ret;
+
+        /* Send new public key to client. */
+        ext->resp = 1;
+    }
+    else {
+        if ((modes & (1 << PSK_KE)) == 0)
+            return PSK_KEY_ERROR;
+        ssl->options.noPskDheKe = 1;
+        ssl->arrays->preMasterSz = 0;
+    }
+
+    *usingPSK = 1;
+
+    WOLFSSL_LEAVE("DoPreSharedKeys", ret);
+
+    return ret;
+}
+#endif
+
+#if !defined(WOLFSSL_TLS13_DRAFT_18) && defined(WOLFSSL_SEND_HRR_COOKIE)
+/* Check that the Cookie data's integrity.
+ *
+ * ssl       SSL/TLS object.
+ * cookie    The cookie data - hash and MAC.
+ * cookieSz  The length of the cookie data in bytes.
+ * returns Length of the hash on success, otherwise failure.
+ */
+static int CheckCookie(WOLFSSL* ssl, byte* cookie, byte cookieSz)
+{
+    int  ret;
+    byte mac[WC_MAX_DIGEST_SIZE] = {0};
+    Hmac cookieHmac;
+    byte cookieType = 0;
+    byte macSz = 0;
+
+#if !defined(NO_SHA) && defined(NO_SHA256)
+    cookieType = SHA;
+    macSz = WC_SHA_DIGEST_SIZE;
+#endif /* NO_SHA */
+#ifndef NO_SHA256
+    cookieType = WC_SHA256;
+    macSz = WC_SHA256_DIGEST_SIZE;
+#endif /* NO_SHA256 */
+
+    if (cookieSz < ssl->specs.hash_size + macSz)
+        return HRR_COOKIE_ERROR;
+    cookieSz -= macSz;
+    XMEMSET(&cookieHmac, 0, sizeof(Hmac));
+
+    ret = wc_HmacSetKey(&cookieHmac, cookieType,
+                        ssl->buffers.tls13CookieSecret.buffer,
+                        ssl->buffers.tls13CookieSecret.length);
+    if (ret != 0)
+        return ret;
+    if ((ret = wc_HmacUpdate(&cookieHmac, cookie, cookieSz)) != 0)
+        return ret;
+    if ((ret = wc_HmacFinal(&cookieHmac, mac)) != 0)
+        return ret;
+
+    if (ConstantCompare(cookie + cookieSz, mac, macSz) != 0)
+        return HRR_COOKIE_ERROR;
+    return cookieSz;
+}
+
+/* Length of the KeyShare Extension */
+#define HRR_KEY_SHARE_SZ   (OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN)
+/* Length of the Supported Vresions Extension */
+#define HRR_VERSIONS_SZ    (OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN)
+/* Length of the Cookie Extension excluding cookie data */
+#define HRR_COOKIE_HDR_SZ  (OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN)
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* PV | CipherSuite | Ext Len */
+#define HRR_BODY_SZ        (OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN)
+/* HH | PV | CipherSuite | Ext Len | Key Share | Cookie */
+#define MAX_HRR_SZ   (HANDSHAKE_HEADER_SZ   + \
+                        HRR_BODY_SZ         + \
+                          HRR_KEY_SHARE_SZ  + \
+                          HRR_COOKIE_HDR_SZ)
+#else
+/* PV | Random | Session Id | CipherSuite | Compression | Ext Len */
+#define HRR_BODY_SZ        (VERSION_SZ + RAN_LEN + ENUM_LEN + ID_LEN + \
+                            SUITE_LEN + COMP_LEN + OPAQUE16_LEN)
+/* HH | PV | CipherSuite | Ext Len | Key Share | Supported Version | Cookie */
+#define MAX_HRR_SZ   (HANDSHAKE_HEADER_SZ   + \
+                        HRR_BODY_SZ         + \
+                          HRR_KEY_SHARE_SZ  + \
+                          HRR_VERSIONS_SZ   + \
+                          HRR_COOKIE_HDR_SZ)
+#endif
+
+/* Restart the handshake hash from the cookie value.
+ *
+ * ssl     SSL/TLS object.
+ * cookie  Cookie data from client.
+ * returns 0 on success, otherwise failure.
+ */
+static int RestartHandshakeHashWithCookie(WOLFSSL* ssl, Cookie* cookie)
+{
+    byte   header[HANDSHAKE_HEADER_SZ] = {0};
+    byte   hrr[MAX_HRR_SZ] = {0};
+    int    hrrIdx;
+    word32 idx;
+    byte   hashSz;
+    byte*  cookieData;
+    byte   cookieDataSz;
+    word16 length;
+    int    keyShareExt = 0;
+    int    ret;
+
+    cookieDataSz = ret = CheckCookie(ssl, &cookie->data, cookie->len);
+    if (ret < 0)
+        return ret;
+    hashSz = cookie->data;
+    cookieData = &cookie->data;
+    idx = OPAQUE8_LEN;
+
+    /* Restart handshake hash with synthetic message hash. */
+    AddTls13HandShakeHeader(header, hashSz, 0, 0, message_hash, ssl);
+    if ((ret = InitHandshakeHashes(ssl)) != 0)
+        return ret;
+    if ((ret = HashOutputRaw(ssl, header, sizeof(header))) != 0)
+        return ret;
+    if ((ret = HashOutputRaw(ssl, cookieData + idx, hashSz)) != 0)
+        return ret;
+
+    /* Reconstruct the HelloRetryMessage for handshake hash. */
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    length = HRR_BODY_SZ + HRR_COOKIE_HDR_SZ + cookie->len;
+#else
+    length = HRR_BODY_SZ - ID_LEN + ssl->session.sessionIDSz +
+             HRR_COOKIE_HDR_SZ + cookie->len;
+    length += HRR_VERSIONS_SZ;
+#endif
+    if (cookieDataSz > hashSz + OPAQUE16_LEN) {
+        keyShareExt = 1;
+        length += HRR_KEY_SHARE_SZ;
+    }
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    AddTls13HandShakeHeader(hrr, length, 0, 0, hello_retry_request, ssl);
+
+    idx += hashSz;
+    hrrIdx = HANDSHAKE_HEADER_SZ;
+    /* The negotiated protocol version. */
+    hrr[hrrIdx++] = TLS_DRAFT_MAJOR;
+    hrr[hrrIdx++] = TLS_DRAFT_MINOR;
+    /* Cipher Suite */
+    hrr[hrrIdx++] = cookieData[idx++];
+    hrr[hrrIdx++] = cookieData[idx++];
+
+    /* Extensions' length */
+    length -= HRR_BODY_SZ;
+    c16toa(length, hrr + hrrIdx);
+    hrrIdx += 2;
+#else
+    AddTls13HandShakeHeader(hrr, length, 0, 0, server_hello, ssl);
+
+    idx += hashSz;
+    hrrIdx = HANDSHAKE_HEADER_SZ;
+
+    /* The negotiated protocol version. */
+    hrr[hrrIdx++] = ssl->version.major;
+    hrr[hrrIdx++] = TLSv1_2_MINOR;
+
+    /* HelloRetryRequest message has fixed value for random. */
+    XMEMCPY(hrr + hrrIdx, helloRetryRequestRandom, RAN_LEN);
+    hrrIdx += RAN_LEN;
+
+    hrr[hrrIdx++] = ssl->session.sessionIDSz;
+    if (ssl->session.sessionIDSz > 0) {
+        XMEMCPY(hrr + hrrIdx, ssl->session.sessionID, ssl->session.sessionIDSz);
+        hrrIdx += ssl->session.sessionIDSz;
+    }
+
+    /* Cipher Suite */
+    hrr[hrrIdx++] = cookieData[idx++];
+    hrr[hrrIdx++] = cookieData[idx++];
+
+    /* Compression not supported in TLS v1.3. */
+    hrr[hrrIdx++] = 0;
+
+    /* Extensions' length */
+    length -= HRR_BODY_SZ - ID_LEN + ssl->session.sessionIDSz;
+    c16toa(length, hrr + hrrIdx);
+    hrrIdx += 2;
+
+#endif
+    /* Optional KeyShare Extension */
+    if (keyShareExt) {
+        c16toa(TLSX_KEY_SHARE, hrr + hrrIdx);
+        hrrIdx += 2;
+        c16toa(OPAQUE16_LEN, hrr + hrrIdx);
+        hrrIdx += 2;
+        hrr[hrrIdx++] = cookieData[idx++];
+        hrr[hrrIdx++] = cookieData[idx++];
+    }
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    c16toa(TLSX_SUPPORTED_VERSIONS, hrr + hrrIdx);
+    hrrIdx += 2;
+    c16toa(OPAQUE16_LEN, hrr + hrrIdx);
+    hrrIdx += 2;
+    #ifdef WOLFSSL_TLS13_DRAFT
+        hrr[hrrIdx++] = TLS_DRAFT_MAJOR;
+        hrr[hrrIdx++] = TLS_DRAFT_MINOR;
+    #else
+        hrr[hrrIdx++] = ssl->version.major;
+        hrr[hrrIdx++] = ssl->version.minor;
+    #endif
+#endif
+    /* Mandatory Cookie Extension */
+    c16toa(TLSX_COOKIE, hrr + hrrIdx);
+    hrrIdx += 2;
+    c16toa(cookie->len + OPAQUE16_LEN, hrr + hrrIdx);
+    hrrIdx += 2;
+    c16toa(cookie->len, hrr + hrrIdx);
+    hrrIdx += 2;
+
+#ifdef WOLFSSL_DEBUG_TLS
+    WOLFSSL_MSG("Reconstucted HelloRetryRequest");
+    WOLFSSL_BUFFER(hrr, hrrIdx);
+    WOLFSSL_MSG("Cookie");
+    WOLFSSL_BUFFER(cookieData, cookie->len);
+#endif
+
+    if ((ret = HashOutputRaw(ssl, hrr, hrrIdx)) != 0)
+        return ret;
+    return HashOutputRaw(ssl, cookieData, cookie->len);
+}
+#endif
+
+/* Do SupportedVersion extension for TLS v1.3+ otherwise it is not.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The message buffer.
+ * i         The index into the message buffer of ClientHello.
+ * helloSz   The length of the current handshake message.
+ * returns 0 on success and otherwise failure.
+ */
+static int DoTls13SupportedVersions(WOLFSSL* ssl, const byte* input, word32 i,
+                                    word32 helloSz, int* wantDowngrade)
+{
+    int    ret;
+    byte   b;
+    word16 suiteSz;
+    word16 totalExtSz;
+    int    foundVersion = 0;
+
+    /* Client random */
+    i += RAN_LEN;
+    /* Session id - not used in TLS v1.3 */
+    b = input[i++];
+    if (i + b > helloSz) {
+        return BUFFER_ERROR;
+    }
+    i += b;
+    /* Cipher suites */
+    if (i + OPAQUE16_LEN > helloSz)
+        return BUFFER_ERROR;
+    ato16(input + i, &suiteSz);
+    i += OPAQUE16_LEN;
+    if (i + suiteSz + 1 > helloSz)
+        return BUFFER_ERROR;
+    i += suiteSz;
+    /* Compression */
+    b = input[i++];
+    if (i + b > helloSz)
+        return BUFFER_ERROR;
+    i += b;
+
+    /* TLS 1.3 must have extensions */
+    if (i < helloSz) {
+        if (i + OPAQUE16_LEN > helloSz)
+            return BUFFER_ERROR;
+        ato16(&input[i], &totalExtSz);
+        i += OPAQUE16_LEN;
+        if (totalExtSz != helloSz - i)
+            return BUFFER_ERROR;
+
+        /* Need to negotiate version first. */
+        if ((ret = TLSX_ParseVersion(ssl, (byte*)input + i, totalExtSz,
+                                                client_hello, &foundVersion))) {
+            return ret;
+        }
+    }
+    *wantDowngrade = !foundVersion || !IsAtLeastTLSv1_3(ssl->version);
+
+    return 0;
+}
+
+/* Handle a ClientHello handshake message.
+ * If the protocol version in the message is not TLS v1.3 or higher, use
+ * DoClientHello()
+ * Only a server will receive this message.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The message buffer.
+ * inOutIdx  On entry, the index into the message buffer of ClientHello.
+ *           On exit, the index of byte after the ClientHello message and
+ *           padding.
+ * helloSz   The length of the current handshake message.
+ * returns 0 on success and otherwise failure.
+ */
+int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                       word32 helloSz)
+{
+    int             ret = VERSION_ERROR;
+    byte            b = 0;
+    ProtocolVersion pv;
+    Suites          clSuites;
+    word32          i = *inOutIdx;
+    word32          begin = i;
+    word16          totalExtSz = 0;
+    int             usingPSK = 0;
+    byte            sessIdSz = 0;
+    int             wantDowngrade = 0;
+
+    WOLFSSL_START(WC_FUNC_CLIENT_HELLO_DO);
+    WOLFSSL_ENTER("DoTls13ClientHello");
+
+    XMEMSET(&pv, 0, sizeof(ProtocolVersion));
+    XMEMSET(&clSuites, 0, sizeof(Suites));
+
+#ifdef WOLFSSL_CALLBACKS
+    if (ssl->hsInfoOn) AddPacketName(ssl, "ClientHello");
+    if (ssl->toInfoOn) AddLateName("ClientHello", &ssl->timeoutInfo);
+#endif
+
+    /* protocol version, random and session id length check */
+    if ((i - begin) + OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz)
+        return BUFFER_ERROR;
+
+    /* Protocol version */
+    XMEMCPY(&pv, input + i, OPAQUE16_LEN);
+    ssl->chVersion = pv;   /* store */
+    i += OPAQUE16_LEN;
+    if (pv.major < SSLv3_MAJOR) {
+        WOLFSSL_MSG("Legacy version field contains unsupported value");
+ #ifdef WOLFSSL_MYSQL_COMPATIBLE
+        SendAlert(ssl, alert_fatal, wc_protocol_version);
+ #else
+        SendAlert(ssl, alert_fatal, protocol_version);
+ #endif
+        return INVALID_PARAMETER;
+    }
+    /* Legacy protocol version cannot negotiate TLS 1.3 or higher. */
+    if (pv.major > SSLv3_MAJOR || (pv.major == SSLv3_MAJOR &&
+                                                   pv.minor >= TLSv1_3_MINOR)) {
+        pv.major = SSLv3_MAJOR;
+        pv.minor = TLSv1_2_MINOR;
+        wantDowngrade = 1;
+        ssl->version.minor = pv.minor;
+    }
+    /* Legacy version must be [ SSLv3_MAJOR, TLSv1_2_MINOR ] for TLS v1.3 */
+    else if (pv.major == SSLv3_MAJOR && pv.minor < TLSv1_2_MINOR) {
+        wantDowngrade = 1;
+        ssl->version.minor = pv.minor;
+    }
+    else {
+        ret = DoTls13SupportedVersions(ssl, input + begin, i - begin, helloSz,
+                                                                &wantDowngrade);
+        if (ret < 0)
+            return ret;
+    }
+    if (wantDowngrade) {
+#ifndef WOLFSSL_NO_TLS12
+        if (!ssl->options.downgrade) {
+            WOLFSSL_MSG("Client trying to connect with lesser version than "
+                        "TLS v1.3");
+            return VERSION_ERROR;
+        }
+
+        if (pv.minor < ssl->options.minDowngrade)
+            return VERSION_ERROR;
+
+        if ((ret = HashInput(ssl, input + begin, helloSz)) != 0)
+            return ret;
+        return DoClientHello(ssl, input, inOutIdx, helloSz);
+#else
+        WOLFSSL_MSG("Client trying to connect with lesser version than "
+                    "TLS v1.3");
+        return VERSION_ERROR;
+#endif
+    }
+
+    /* Client random */
+    XMEMCPY(ssl->arrays->clientRandom, input + i, RAN_LEN);
+    i += RAN_LEN;
+
+#ifdef WOLFSSL_DEBUG_TLS
+    WOLFSSL_MSG("client random");
+    WOLFSSL_BUFFER(ssl->arrays->clientRandom, RAN_LEN);
+#endif
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    /* Session id - empty in TLS v1.3 */
+    sessIdSz = input[i++];
+    if (sessIdSz > 0 && !ssl->options.downgrade) {
+        WOLFSSL_MSG("Client sent session id - not supported");
+        return BUFFER_ERROR;
+    }
+#else
+    sessIdSz = input[i++];
+    if (sessIdSz != ID_LEN && sessIdSz != 0)
+        return INVALID_PARAMETER;
+#endif
+
+    if (sessIdSz + i > helloSz) {
+        return BUFFER_ERROR;
+    }
+
+    ssl->session.sessionIDSz = sessIdSz;
+    if (sessIdSz == ID_LEN) {
+        XMEMCPY(ssl->session.sessionID, input + i, sessIdSz);
+        i += ID_LEN;
+    }
+
+    /* Cipher suites */
+    if ((i - begin) + OPAQUE16_LEN > helloSz)
+        return BUFFER_ERROR;
+    ato16(&input[i], &clSuites.suiteSz);
+    i += OPAQUE16_LEN;
+    /* suites and compression length check */
+    if ((i - begin) + clSuites.suiteSz + OPAQUE8_LEN > helloSz)
+        return BUFFER_ERROR;
+    if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ)
+        return BUFFER_ERROR;
+    XMEMCPY(clSuites.suites, input + i, clSuites.suiteSz);
+    i += clSuites.suiteSz;
+    clSuites.hashSigAlgoSz = 0;
+
+#ifdef HAVE_SERVER_RENEGOTIATION_INFO
+    ret = FindSuite(&clSuites, 0, TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
+    if (ret == SUITES_ERROR)
+        return BUFFER_ERROR;
+    if (ret >= 0) {
+        TLSX* extension;
+
+        /* check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV suite */
+        ret = TLSX_AddEmptyRenegotiationInfo(&ssl->extensions, ssl->heap);
+        if (ret != WOLFSSL_SUCCESS)
+            return ret;
+
+        extension = TLSX_Find(ssl->extensions, TLSX_RENEGOTIATION_INFO);
+        if (extension) {
+            ssl->secure_renegotiation = (SecureRenegotiation*)extension->data;
+            ssl->secure_renegotiation->enabled = 1;
+        }
+    }
+#endif /* HAVE_SERVER_RENEGOTIATION_INFO */
+
+    /* Compression */
+    b = input[i++];
+    if ((i - begin) + b > helloSz)
+        return BUFFER_ERROR;
+    if (b != COMP_LEN) {
+        WOLFSSL_MSG("Must be one compression type in list");
+        return INVALID_PARAMETER;
+    }
+    b = input[i++];
+    if (b != NO_COMPRESSION) {
+        WOLFSSL_MSG("Must be no compression type in list");
+        return INVALID_PARAMETER;
+    }
+
+    /* Extensions */
+    if ((i - begin) == helloSz)
+        return BUFFER_ERROR;
+    if ((i - begin) + OPAQUE16_LEN > helloSz)
+        return BUFFER_ERROR;
+
+    ato16(&input[i], &totalExtSz);
+    i += OPAQUE16_LEN;
+    if ((i - begin) + totalExtSz > helloSz)
+        return BUFFER_ERROR;
+
+    /* Auto populate extensions supported unless user defined. */
+    if ((ret = TLSX_PopulateExtensions(ssl, 1)) != 0)
+        return ret;
+
+    /* Parse extensions */
+    if ((ret = TLSX_Parse(ssl, (byte*)input + i, totalExtSz, client_hello,
+                                                                  &clSuites))) {
+        return ret;
+    }
+
+#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \
+                                                        defined(WOLFSSL_HAPROXY)
+        if ((ret = SNI_Callback(ssl)) != 0)
+            return ret;
+        ssl->options.side = WOLFSSL_SERVER_END;
+#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
+
+    i += totalExtSz;
+    *inOutIdx = i;
+
+    ssl->options.sendVerify = SEND_CERT;
+
+    ssl->options.clientState = CLIENT_HELLO_COMPLETE;
+    ssl->options.haveSessionId = 1;
+
+#if !defined(WOLFSSL_TLS13_DRAFT_18) && defined(WOLFSSL_SEND_HRR_COOKIE)
+    if (ssl->options.sendCookie &&
+              ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
+        TLSX* ext;
+
+        if ((ext = TLSX_Find(ssl->extensions, TLSX_COOKIE)) == NULL)
+            return HRR_COOKIE_ERROR;
+        /* Ensure the cookie came from client and isn't the one in the
+         * response - HelloRetryRequest.
+         */
+        if (ext->resp == 1)
+            return HRR_COOKIE_ERROR;
+        ret = RestartHandshakeHashWithCookie(ssl, (Cookie*)ext->data);
+        if (ret != 0)
+            return ret;
+    }
+#endif
+
+#if (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) && \
+     defined(HAVE_TLS_EXTENSIONS)
+    if (TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY) != NULL) {
+        /* Refine list for PSK processing. */
+        RefineSuites(ssl, &clSuites);
+
+        /* Process the Pre-Shared Key extension if present. */
+        ret = DoPreSharedKeys(ssl, input + begin, helloSz, &usingPSK);
+        if (ret != 0)
+            return ret;
+    }
+    else
+#endif
+    {
+#ifdef WOLFSSL_EARLY_DATA
+        ssl->earlyData = no_early_data;
+#endif
+        if ((ret = HashInput(ssl, input + begin, helloSz)) != 0)
+            return ret;
+
+    }
+
+    if (!usingPSK) {
+        if (TLSX_Find(ssl->extensions, TLSX_KEY_SHARE) == NULL) {
+            WOLFSSL_MSG("Client did not send a KeyShare extension");
+            SendAlert(ssl, alert_fatal, missing_extension);
+            return INCOMPLETE_DATA;
+        }
+        if (TLSX_Find(ssl->extensions, TLSX_SIGNATURE_ALGORITHMS) == NULL) {
+            WOLFSSL_MSG("Client did not send a SignatureAlgorithms extension");
+            SendAlert(ssl, alert_fatal, missing_extension);
+            return INCOMPLETE_DATA;
+        }
+
+        if ((ret = MatchSuite(ssl, &clSuites)) < 0) {
+            WOLFSSL_MSG("Unsupported cipher suite, ClientHello");
+            SendAlert(ssl, alert_fatal, handshake_failure);
+            return ret;
+        }
+
+#ifdef HAVE_NULL_CIPHER
+        if (ssl->options.cipherSuite0 == ECC_BYTE &&
+                              (ssl->options.cipherSuite == TLS_SHA256_SHA256 ||
+                               ssl->options.cipherSuite == TLS_SHA384_SHA384)) {
+            ;
+        }
+        else
+#endif
+        /* Check that the negotiated ciphersuite matches protocol version. */
+        if (ssl->options.cipherSuite0 != TLS13_BYTE) {
+            WOLFSSL_MSG("Negotiated ciphersuite from lesser version than "
+                        "TLS v1.3");
+            SendAlert(ssl, alert_fatal, handshake_failure);
+            return VERSION_ERROR;
+        }
+
+#ifdef HAVE_SESSION_TICKET
+        if (ssl->options.resuming) {
+            ssl->options.resuming = 0;
+            XMEMSET(ssl->arrays->psk_key, 0, ssl->specs.hash_size);
+        }
+#endif
+
+        /* Derive early secret for handshake secret. */
+        if ((ret = DeriveEarlySecret(ssl)) != 0)
+            return ret;
+    }
+
+    WOLFSSL_LEAVE("DoTls13ClientHello", ret);
+    WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO);
+
+    return ret;
+}
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* handle generation of TLS 1.3 hello_retry_request (6) */
+/* Send the HelloRetryRequest message to indicate the negotiated protocol
+ * version and security parameters the server is willing to use.
+ * Only a server will send this message.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 0 on success, otherwise failure.
+ */
+int SendTls13HelloRetryRequest(WOLFSSL* ssl)
+{
+    int    ret;
+    byte*  output;
+    word32 length;
+    word16 len;
+    word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+    int    sendSz;
+
+    WOLFSSL_ENTER("SendTls13HelloRetryRequest");
+
+    /* Get the length of the extensions that will be written. */
+    len = 0;
+    ret = TLSX_GetResponseSize(ssl, hello_retry_request, &len);
+    /* There must be extensions sent to indicate what client needs to do. */
+    if (ret != 0)
+        return MISSING_HANDSHAKE_DATA;
+
+    /* Protocol version + Extensions */
+    length = OPAQUE16_LEN + len;
+    sendSz = idx + length;
+
+    /* Check buffers are big enough and grow if needed. */
+    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+        return ret;
+
+    /* Get position in output buffer to write new message to. */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+    /* Add record and handshake headers. */
+    AddTls13Headers(output, length, hello_retry_request, ssl);
+
+    /* The negotiated protocol version. */
+    output[idx++] = TLS_DRAFT_MAJOR;
+    output[idx++] = TLS_DRAFT_MINOR;
+
+    /* Add TLS extensions. */
+    ret = TLSX_WriteResponse(ssl, output + idx, hello_retry_request, NULL);
+    if (ret != 0)
+        return ret;
+    idx += len;
+
+#ifdef WOLFSSL_CALLBACKS
+    if (ssl->hsInfoOn)
+        AddPacketName(ssl, "HelloRetryRequest");
+    if (ssl->toInfoOn) {
+        AddPacketInfo(ssl, "HelloRetryRequest", handshake, output, sendSz,
+                      WRITE_PROTO, ssl->heap);
+    }
+#endif
+    if ((ret = HashOutput(ssl, output, idx, 0)) != 0)
+        return ret;
+
+    ssl->buffers.outputBuffer.length += sendSz;
+
+    if (!ssl->options.groupMessages)
+        ret = SendBuffered(ssl);
+
+    WOLFSSL_LEAVE("SendTls13HelloRetryRequest", ret);
+
+    return ret;
+}
+#endif /* WOLFSSL_TLS13_DRAFT_18 */
+
+/* Send TLS v1.3 ServerHello message to client.
+ * Only a server will send this message.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 0 on success, otherwise failure.
+ */
+#ifdef WOLFSSL_TLS13_DRAFT_18
+static
+#endif
+/* handle generation of TLS 1.3 server_hello (2) */
+int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType)
+{
+    int    ret;
+    byte*  output;
+    word16 length;
+    word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+    int    sendSz;
+
+    WOLFSSL_START(WC_FUNC_SERVER_HELLO_SEND);
+    WOLFSSL_ENTER("SendTls13ServerHello");
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    if (extMsgType == hello_retry_request) {
+        WOLFSSL_MSG("wolfSSL Doing HelloRetryRequest");
+        if ((ret = RestartHandshakeHash(ssl)) < 0)
+            return ret;
+    }
+#endif
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    /* Protocol version, server random, cipher suite and extensions. */
+    length = VERSION_SZ + RAN_LEN + SUITE_LEN;
+    ret = TLSX_GetResponseSize(ssl, server_hello, &length);
+    if (ret != 0)
+        return ret;
+#else
+    /* Protocol version, server random, session id, cipher suite, compression
+     * and extensions.
+     */
+    length = VERSION_SZ + RAN_LEN + ENUM_LEN + ssl->session.sessionIDSz +
+             SUITE_LEN + COMP_LEN;
+    ret = TLSX_GetResponseSize(ssl, extMsgType, &length);
+    if (ret != 0)
+        return ret;
+#endif
+    sendSz = idx + length;
+
+    /* Check buffers are big enough and grow if needed. */
+    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+        return ret;
+
+    /* Get position in output buffer to write new message to. */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+
+    /* Put the record and handshake headers on. */
+    AddTls13Headers(output, length, server_hello, ssl);
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    /* The negotiated protocol version. */
+    output[idx++] = TLS_DRAFT_MAJOR;
+    output[idx++] = TLS_DRAFT_MINOR;
+#else
+    /* The protocol version must be TLS v1.2 for middleboxes. */
+    output[idx++] = ssl->version.major;
+    output[idx++] = TLSv1_2_MINOR;
+#endif
+
+    if (extMsgType == server_hello) {
+        /* Generate server random. */
+        if ((ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN)) != 0)
+            return ret;
+    }
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    else {
+        /* HelloRetryRequest message has fixed value for random. */
+        XMEMCPY(output + idx, helloRetryRequestRandom, RAN_LEN);
+    }
+#endif
+    /* Store in SSL for debugging. */
+    XMEMCPY(ssl->arrays->serverRandom, output + idx, RAN_LEN);
+    idx += RAN_LEN;
+
+#ifdef WOLFSSL_DEBUG_TLS
+    WOLFSSL_MSG("Server random");
+    WOLFSSL_BUFFER(ssl->arrays->serverRandom, RAN_LEN);
+#endif
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    output[idx++] = ssl->session.sessionIDSz;
+    if (ssl->session.sessionIDSz > 0) {
+        XMEMCPY(output + idx, ssl->session.sessionID, ssl->session.sessionIDSz);
+        idx += ssl->session.sessionIDSz;
+    }
+#endif
+
+    /* Chosen cipher suite */
+    output[idx++] = ssl->options.cipherSuite0;
+    output[idx++] = ssl->options.cipherSuite;
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    /* Compression not supported in TLS v1.3. */
+    output[idx++] = 0;
+#endif
+
+    /* Extensions */
+    ret = TLSX_WriteResponse(ssl, output + idx, extMsgType, NULL);
+    if (ret != 0)
+        return ret;
+
+    ssl->buffers.outputBuffer.length += sendSz;
+
+    if ((ret = HashOutput(ssl, output, sendSz, 0)) != 0)
+        return ret;
+
+    #ifdef WOLFSSL_CALLBACKS
+    if (ssl->hsInfoOn)
+        AddPacketName(ssl, "ServerHello");
+    if (ssl->toInfoOn) {
+        AddPacketInfo(ssl, "ServerHello", handshake, output, sendSz,
+                      WRITE_PROTO, ssl->heap);
+    }
+    #endif
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    ssl->options.serverState = SERVER_HELLO_COMPLETE;
+#else
+    if (extMsgType == server_hello)
+        ssl->options.serverState = SERVER_HELLO_COMPLETE;
+#endif
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    if (!ssl->options.groupMessages)
+#else
+    if (!ssl->options.groupMessages || extMsgType != server_hello)
+#endif
+        ret = SendBuffered(ssl);
+
+    WOLFSSL_LEAVE("SendTls13ServerHello", ret);
+    WOLFSSL_END(WC_FUNC_SERVER_HELLO_SEND);
+
+    return ret;
+}
+
+/* handle generation of TLS 1.3 encrypted_extensions (8) */
+/* Send the rest of the extensions encrypted under the handshake key.
+ * This message is always encrypted in TLS v1.3.
+ * Only a server will send this message.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 0 on success, otherwise failure.
+ */
+static int SendTls13EncryptedExtensions(WOLFSSL* ssl)
+{
+    int    ret;
+    byte*  output;
+    word16 length = 0;
+    word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+    int    sendSz;
+
+    WOLFSSL_START(WC_FUNC_ENCRYPTED_EXTENSIONS_SEND);
+    WOLFSSL_ENTER("SendTls13EncryptedExtensions");
+
+    ssl->keys.encryptionOn = 1;
+
+#ifndef WOLFSSL_NO_SERVER_GROUPS_EXT
+    if ((ret = TLSX_SupportedCurve_CheckPriority(ssl)) != 0)
+        return ret;
+#endif
+
+    /* Derive the handshake secret now that we are at first message to be
+     * encrypted under the keys.
+     */
+    if ((ret = DeriveHandshakeSecret(ssl)) != 0)
+        return ret;
+    if ((ret = DeriveTls13Keys(ssl, handshake_key,
+                               ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0)
+        return ret;
+
+    /* Setup encrypt/decrypt keys for following messages. */
+#ifdef WOLFSSL_EARLY_DATA
+    if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0)
+        return ret;
+    if (ssl->earlyData != process_early_data) {
+        if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
+            return ret;
+    }
+#else
+    if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) != 0)
+        return ret;
+#endif
+
+    ret = TLSX_GetResponseSize(ssl, encrypted_extensions, &length);
+    if (ret != 0)
+        return ret;
+
+    sendSz = idx + length;
+    /* Encryption always on. */
+    sendSz += MAX_MSG_EXTRA;
+
+    /* Check buffers are big enough and grow if needed. */
+    ret = CheckAvailableSize(ssl, sendSz);
+    if (ret != 0)
+        return ret;
+
+    /* Get position in output buffer to write new message to. */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+
+    /* Put the record and handshake headers on. */
+    AddTls13Headers(output, length, encrypted_extensions, ssl);
+
+    ret = TLSX_WriteResponse(ssl, output + idx, encrypted_extensions, NULL);
+    if (ret != 0)
+        return ret;
+    idx += length;
+
+#ifdef WOLFSSL_CALLBACKS
+    if (ssl->hsInfoOn)
+        AddPacketName(ssl, "EncryptedExtensions");
+    if (ssl->toInfoOn) {
+        AddPacketInfo(ssl, "EncryptedExtensions", handshake, output,
+                      sendSz, WRITE_PROTO, ssl->heap);
+    }
+#endif
+
+    /* This handshake message is always encrypted. */
+    sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ,
+                               idx - RECORD_HEADER_SZ, handshake, 1, 0, 0);
+    if (sendSz < 0)
+        return sendSz;
+
+    ssl->buffers.outputBuffer.length += sendSz;
+
+    ssl->options.serverState = SERVER_ENCRYPTED_EXTENSIONS_COMPLETE;
+
+    if (!ssl->options.groupMessages)
+        ret = SendBuffered(ssl);
+
+    WOLFSSL_LEAVE("SendTls13EncryptedExtensions", ret);
+    WOLFSSL_END(WC_FUNC_ENCRYPTED_EXTENSIONS_SEND);
+
+    return ret;
+}
+
+#ifndef NO_CERTS
+/* handle generation TLS v1.3 certificate_request (13) */
+/* Send the TLS v1.3 CertificateRequest message.
+ * This message is always encrypted in TLS v1.3.
+ * Only a server will send this message.
+ *
+ * ssl        SSL/TLS object.
+ * reqCtx     Request context.
+ * reqCtxLen  Length of context. 0 when sending as part of handshake.
+ * returns 0 on success, otherwise failure.
+ */
+static int SendTls13CertificateRequest(WOLFSSL* ssl, byte* reqCtx,
+                                       int reqCtxLen)
+{
+    byte*   output;
+    int    ret;
+    int    sendSz;
+    word32 i;
+    word16 reqSz;
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    TLSX*  ext;
+#endif
+
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_REQUEST_SEND);
+    WOLFSSL_ENTER("SendTls13CertificateRequest");
+
+    if (ssl->options.side == WOLFSSL_SERVER_END)
+        InitSuitesHashSigAlgo(ssl->suites, 1, 1, 0, 1, ssl->buffers.keySz);
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+    reqSz = OPAQUE8_LEN + reqCtxLen + REQ_HEADER_SZ + REQ_HEADER_SZ;
+    reqSz += LENGTH_SZ + ssl->suites->hashSigAlgoSz;
+
+    sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + reqSz;
+    /* Always encrypted and make room for padding. */
+    sendSz += MAX_MSG_EXTRA;
+
+    /* Check buffers are big enough and grow if needed. */
+    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+        return ret;
+
+    /* Get position in output buffer to write new message to. */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+
+    /* Put the record and handshake headers on. */
+    AddTls13Headers(output, reqSz, certificate_request, ssl);
+
+    /* Certificate request context. */
+    output[i++] = reqCtxLen;
+    if (reqCtxLen != 0) {
+        XMEMCPY(output + i, reqCtx, reqCtxLen);
+        i += reqCtxLen;
+    }
+
+    /* supported hash/sig */
+    c16toa(ssl->suites->hashSigAlgoSz, &output[i]);
+    i += LENGTH_SZ;
+
+    XMEMCPY(&output[i], ssl->suites->hashSigAlgo, ssl->suites->hashSigAlgoSz);
+    i += ssl->suites->hashSigAlgoSz;
+
+    /* Certificate authorities not supported yet - empty buffer. */
+    c16toa(0, &output[i]);
+    i += REQ_HEADER_SZ;
+
+    /* Certificate extensions. */
+    c16toa(0, &output[i]);  /* auth's */
+    i += REQ_HEADER_SZ;
+#else
+    ext = TLSX_Find(ssl->extensions, TLSX_SIGNATURE_ALGORITHMS);
+    if (ext == NULL)
+        return EXT_MISSING;
+    ext->resp = 0;
+
+    i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+    reqSz = (word16)(OPAQUE8_LEN + reqCtxLen);
+    ret = TLSX_GetRequestSize(ssl, certificate_request, &reqSz);
+    if (ret != 0)
+        return ret;
+
+    sendSz = i + reqSz;
+    /* Always encrypted and make room for padding. */
+    sendSz += MAX_MSG_EXTRA;
+
+    /* Check buffers are big enough and grow if needed. */
+    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+        return ret;
+
+    /* Get position in output buffer to write new message to. */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+
+    /* Put the record and handshake headers on. */
+    AddTls13Headers(output, reqSz, certificate_request, ssl);
+
+    /* Certificate request context. */
+    output[i++] = (byte)reqCtxLen;
+    if (reqCtxLen != 0) {
+        XMEMCPY(output + i, reqCtx, reqCtxLen);
+        i += reqCtxLen;
+    }
+
+    /* Certificate extensions. */
+    reqSz = 0;
+    ret = TLSX_WriteRequest(ssl, output + i, certificate_request, &reqSz);
+    if (ret != 0)
+        return ret;
+    i += reqSz;
+#endif
+
+    /* Always encrypted. */
+    sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ,
+                               i - RECORD_HEADER_SZ, handshake, 1, 0, 0);
+    if (sendSz < 0)
+        return sendSz;
+
+    #ifdef WOLFSSL_CALLBACKS
+        if (ssl->hsInfoOn)
+            AddPacketName(ssl, "CertificateRequest");
+        if (ssl->toInfoOn) {
+            AddPacketInfo(ssl, "CertificateRequest", handshake, output,
+                          sendSz, WRITE_PROTO, ssl->heap);
+        }
+    #endif
+
+    ssl->buffers.outputBuffer.length += sendSz;
+    if (!ssl->options.groupMessages)
+        ret = SendBuffered(ssl);
+
+    WOLFSSL_LEAVE("SendTls13CertificateRequest", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_SEND);
+
+    return ret;
+}
+#endif /* NO_CERTS */
+#endif /* NO_WOLFSSL_SERVER */
+
+#ifndef NO_CERTS
+#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+                                                             defined(HAVE_ED448)
+/* Encode the signature algorithm into buffer.
+ *
+ * hashalgo  The hash algorithm.
+ * hsType   The signature type.
+ * output    The buffer to encode into.
+ */
+static WC_INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output)
+{
+    switch (hsType) {
+#ifdef HAVE_ECC
+        case ecc_dsa_sa_algo:
+            output[0] = hashAlgo;
+            output[1] = ecc_dsa_sa_algo;
+            break;
+#endif
+#ifdef HAVE_ED25519
+        /* ED25519: 0x0807 */
+        case ed25519_sa_algo:
+            output[0] = ED25519_SA_MAJOR;
+            output[1] = ED25519_SA_MINOR;
+            (void)hashAlgo;
+            break;
+#endif
+#ifdef HAVE_ED448
+        /* ED448: 0x0808 */
+        case ed448_sa_algo:
+            output[0] = ED448_SA_MAJOR;
+            output[1] = ED448_SA_MINOR;
+            (void)hashAlgo;
+            break;
+#endif
+#ifndef NO_RSA
+        /* PSS signatures: 0x080[4-6] */
+        case rsa_pss_sa_algo:
+            output[0] = rsa_pss_sa_algo;
+            output[1] = hashAlgo;
+            break;
+#endif
+    }
+}
+
+/* Decode the signature algorithm.
+ *
+ * input     The encoded signature algorithm.
+ * hashalgo  The hash algorithm.
+ * hsType    The signature type.
+ * returns INVALID_PARAMETER if not recognized and 0 otherwise.
+ */
+static WC_INLINE int DecodeTls13SigAlg(byte* input, byte* hashAlgo,
+                                       byte* hsType)
+{
+    int ret = 0;
+
+    switch (input[0]) {
+        case NEW_SA_MAJOR:
+            /* PSS signatures: 0x080[4-6] */
+            if (input[1] >= sha256_mac && input[1] <= sha512_mac) {
+                *hsType   = input[0];
+                *hashAlgo = input[1];
+            }
+    #ifdef HAVE_ED25519
+            /* ED25519: 0x0807 */
+            else if (input[1] == ED25519_SA_MINOR) {
+                *hsType = ed25519_sa_algo;
+                /* Hash performed as part of sign/verify operation. */
+                *hashAlgo = sha512_mac;
+            }
+    #endif
+    #ifdef HAVE_ED448
+            /* ED448: 0x0808 */
+            else if (input[1] == ED448_SA_MINOR) {
+                *hsType = ed448_sa_algo;
+                /* Hash performed as part of sign/verify operation. */
+                *hashAlgo = sha512_mac;
+            }
+    #endif
+            else
+                ret = INVALID_PARAMETER;
+            break;
+        default:
+            *hashAlgo = input[0];
+            *hsType   = input[1];
+            break;
+    }
+
+    return ret;
+}
+
+/* Get the hash of the messages so far.
+ *
+ * ssl   The SSL/TLS object.
+ * hash  The buffer to write the hash to.
+ * returns the length of the hash.
+ */
+static WC_INLINE int GetMsgHash(WOLFSSL* ssl, byte* hash)
+{
+    int ret = 0;
+    switch (ssl->specs.mac_algorithm) {
+    #ifndef NO_SHA256
+        case sha256_mac:
+            ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash);
+            if (ret == 0)
+                ret = WC_SHA256_DIGEST_SIZE;
+            break;
+    #endif /* !NO_SHA256 */
+    #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash);
+            if (ret == 0)
+                ret = WC_SHA384_DIGEST_SIZE;
+            break;
+    #endif /* WOLFSSL_SHA384 */
+    #ifdef WOLFSSL_TLS13_SHA512
+        case sha512_mac:
+            ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash);
+            if (ret == 0)
+                ret = WC_SHA512_DIGEST_SIZE;
+            break;
+    #endif /* WOLFSSL_TLS13_SHA512 */
+    }
+    return ret;
+}
+
+/* The length of the certificate verification label - client and server. */
+#define CERT_VFY_LABEL_SZ    34
+/* The server certificate verification label. */
+static const byte serverCertVfyLabel[CERT_VFY_LABEL_SZ] =
+    "TLS 1.3, server CertificateVerify";
+/* The client certificate verification label. */
+static const byte clientCertVfyLabel[CERT_VFY_LABEL_SZ] =
+    "TLS 1.3, client CertificateVerify";
+
+/* The number of prefix bytes for signature data. */
+#define SIGNING_DATA_PREFIX_SZ     64
+/* The prefix byte in the signature data. */
+#define SIGNING_DATA_PREFIX_BYTE   0x20
+/* Maximum length of the signature data. */
+#define MAX_SIG_DATA_SZ            (SIGNING_DATA_PREFIX_SZ + \
+                                    CERT_VFY_LABEL_SZ      + \
+                                    WC_MAX_DIGEST_SIZE)
+
+/* Create the signature data for TLS v1.3 certificate verification.
+ *
+ * ssl        The SSL/TLS object.
+ * sigData    The signature data.
+ * sigDataSz  The length of the signature data.
+ * check      Indicates this is a check not create.
+ */
+static int CreateSigData(WOLFSSL* ssl, byte* sigData, word16* sigDataSz,
+                          int check)
+{
+    word16 idx;
+    int side = ssl->options.side;
+    int ret;
+
+    /* Signature Data = Prefix | Label | Handshake Hash */
+    XMEMSET(sigData, SIGNING_DATA_PREFIX_BYTE, SIGNING_DATA_PREFIX_SZ);
+    idx = SIGNING_DATA_PREFIX_SZ;
+
+    if ((side == WOLFSSL_SERVER_END && check) ||
+        (side == WOLFSSL_CLIENT_END && !check)) {
+        XMEMCPY(&sigData[idx], clientCertVfyLabel, CERT_VFY_LABEL_SZ);
+    }
+    if ((side == WOLFSSL_CLIENT_END && check) ||
+        (side == WOLFSSL_SERVER_END && !check)) {
+        XMEMCPY(&sigData[idx], serverCertVfyLabel, CERT_VFY_LABEL_SZ);
+    }
+    idx += CERT_VFY_LABEL_SZ;
+
+    ret = GetMsgHash(ssl, &sigData[idx]);
+    if (ret < 0)
+        return ret;
+
+    *sigDataSz = (word16)(idx + ret);
+    ret = 0;
+
+    return ret;
+}
+
+#ifndef NO_RSA
+/* Encode the PKCS #1.5 RSA signature.
+ *
+ * sig        The buffer to place the encoded signature into.
+ * sigData    The data to be signed.
+ * sigDataSz  The size of the data to be signed.
+ * hashAlgo   The hash algorithm to use when signing.
+ * returns the length of the encoded signature or negative on error.
+ */
+static int CreateRSAEncodedSig(byte* sig, byte* sigData, int sigDataSz,
+                               int sigAlgo, int hashAlgo)
+{
+    Digest digest;
+    int    hashSz = 0;
+    int    ret = BAD_FUNC_ARG;
+    byte*  hash;
+
+    (void)sigAlgo;
+
+    hash = sig;
+
+    /* Digest the signature data. */
+    switch (hashAlgo) {
+#ifndef NO_WOLFSSL_SHA256
+        case sha256_mac:
+            ret = wc_InitSha256(&digest.sha256);
+            if (ret == 0) {
+                ret = wc_Sha256Update(&digest.sha256, sigData, sigDataSz);
+                if (ret == 0)
+                    ret = wc_Sha256Final(&digest.sha256, hash);
+                wc_Sha256Free(&digest.sha256);
+            }
+            hashSz = WC_SHA256_DIGEST_SIZE;
+            break;
+#endif
+#ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            ret = wc_InitSha384(&digest.sha384);
+            if (ret == 0) {
+                ret = wc_Sha384Update(&digest.sha384, sigData, sigDataSz);
+                if (ret == 0)
+                    ret = wc_Sha384Final(&digest.sha384, hash);
+                wc_Sha384Free(&digest.sha384);
+            }
+            hashSz = WC_SHA384_DIGEST_SIZE;
+            break;
+#endif
+#ifdef WOLFSSL_SHA512
+        case sha512_mac:
+            ret = wc_InitSha512(&digest.sha512);
+            if (ret == 0) {
+                ret = wc_Sha512Update(&digest.sha512, sigData, sigDataSz);
+                if (ret == 0)
+                    ret = wc_Sha512Final(&digest.sha512, hash);
+                wc_Sha512Free(&digest.sha512);
+            }
+            hashSz = WC_SHA512_DIGEST_SIZE;
+            break;
+#endif
+    }
+
+    if (ret != 0)
+        return ret;
+
+    return hashSz;
+}
+#endif /* !NO_RSA */
+
+#ifdef HAVE_ECC
+/* Encode the ECC signature.
+ *
+ * sigData    The data to be signed.
+ * sigDataSz  The size of the data to be signed.
+ * hashAlgo   The hash algorithm to use when signing.
+ * returns the length of the encoded signature or negative on error.
+ */
+static int CreateECCEncodedSig(byte* sigData, int sigDataSz, int hashAlgo)
+{
+    Digest digest;
+    int    hashSz = 0;
+    int    ret = BAD_FUNC_ARG;
+
+    /* Digest the signature data. */
+    switch (hashAlgo) {
+#ifndef NO_WOLFSSL_SHA256
+        case sha256_mac:
+            ret = wc_InitSha256(&digest.sha256);
+            if (ret == 0) {
+                ret = wc_Sha256Update(&digest.sha256, sigData, sigDataSz);
+                if (ret == 0)
+                    ret = wc_Sha256Final(&digest.sha256, sigData);
+                wc_Sha256Free(&digest.sha256);
+            }
+            hashSz = WC_SHA256_DIGEST_SIZE;
+            break;
+#endif
+#ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            ret = wc_InitSha384(&digest.sha384);
+            if (ret == 0) {
+                ret = wc_Sha384Update(&digest.sha384, sigData, sigDataSz);
+                if (ret == 0)
+                    ret = wc_Sha384Final(&digest.sha384, sigData);
+                wc_Sha384Free(&digest.sha384);
+            }
+            hashSz = WC_SHA384_DIGEST_SIZE;
+            break;
+#endif
+#ifdef WOLFSSL_SHA512
+        case sha512_mac:
+            ret = wc_InitSha512(&digest.sha512);
+            if (ret == 0) {
+                ret = wc_Sha512Update(&digest.sha512, sigData, sigDataSz);
+                if (ret == 0)
+                    ret = wc_Sha512Final(&digest.sha512, sigData);
+                wc_Sha512Free(&digest.sha512);
+            }
+            hashSz = WC_SHA512_DIGEST_SIZE;
+            break;
+#endif
+    }
+
+    if (ret != 0)
+        return ret;
+
+    return hashSz;
+}
+#endif /* HAVE_ECC */
+
+#ifndef NO_RSA
+/* Check that the decrypted signature matches the encoded signature
+ * based on the digest of the signature data.
+ *
+ * ssl       The SSL/TLS object.
+ * sigAlgo   The signature algorithm used to generate signature.
+ * hashAlgo  The hash algorithm used to generate signature.
+ * decSig    The decrypted signature.
+ * decSigSz  The size of the decrypted signature.
+ * returns 0 on success, otherwise failure.
+ */
+static int CheckRSASignature(WOLFSSL* ssl, int sigAlgo, int hashAlgo,
+                             byte* decSig, word32 decSigSz)
+{
+    int    ret = 0;
+    byte   sigData[MAX_SIG_DATA_SZ];
+    word16 sigDataSz;
+    word32 sigSz;
+
+    ret = CreateSigData(ssl, sigData, &sigDataSz, 1);
+    if (ret != 0)
+        return ret;
+
+    if (sigAlgo == rsa_pss_sa_algo) {
+        enum wc_HashType hashType = WC_HASH_TYPE_NONE;
+
+        ret = ConvertHashPss(hashAlgo, &hashType, NULL);
+        if (ret < 0)
+            return ret;
+
+        /* PSS signature can be done in-place */
+        ret = CreateRSAEncodedSig(sigData, sigData, sigDataSz,
+                                  sigAlgo, hashAlgo);
+        if (ret < 0)
+            return ret;
+        sigSz = ret;
+
+        ret = wc_RsaPSS_CheckPadding(sigData, sigSz, decSig, decSigSz,
+                                     hashType);
+    }
+
+    return ret;
+}
+#endif /* !NO_RSA */
+#endif /* !NO_RSA || HAVE_ECC */
+
+/* Get the next certificate from the list for writing into the TLS v1.3
+ * Certificate message.
+ *
+ * data    The certificate list.
+ * length  The length of the certificate data in the list.
+ * idx     The index of the next certificate.
+ * returns the length of the certificate data. 0 indicates no more certificates
+ * in the list.
+ */
+static word32 NextCert(byte* data, word32 length, word32* idx)
+{
+    word32 len;
+
+    /* Is index at end of list. */
+    if (*idx == length)
+        return 0;
+
+    /* Length of the current ASN.1 encoded certificate. */
+    c24to32(data + *idx, &len);
+    /* Include the length field. */
+    len += 3;
+
+    /* Move index to next certificate and return the current certificate's
+     * length.
+     */
+    *idx += len;
+    return len;
+}
+
+/* Add certificate data and empty extension to output up to the fragment size.
+ *
+ * ssl     SSL/TLS object.
+ * cert    The certificate data to write out.
+ * len     The length of the certificate data.
+ * extSz   Length of the extension data with the certificate.
+ * idx     The start of the certificate data to write out.
+ * fragSz  The maximum size of this fragment.
+ * output  The buffer to write to.
+ * returns the number of bytes written.
+ */
+static word32 AddCertExt(WOLFSSL* ssl, byte* cert, word32 len, word16 extSz,
+                         word32 idx, word32 fragSz, byte* output)
+{
+    word32 i = 0;
+    word32 copySz = min(len - idx, fragSz);
+
+    if (idx < len) {
+        XMEMCPY(output, cert + idx, copySz);
+        i = copySz;
+        if (copySz == fragSz)
+            return i;
+    }
+    copySz = len + extSz - idx - i;
+
+    if (extSz == OPAQUE16_LEN) {
+        if (copySz <= fragSz) {
+            /* Empty extension */
+            output[i++] = 0;
+            output[i++] = 0;
+        }
+    }
+    else {
+        byte* certExts = ssl->buffers.certExts->buffer + idx + i - len;
+        /* Put out as much of the extensions' data as will fit in fragment. */
+        if (copySz > fragSz - i)
+            copySz = fragSz - i;
+        XMEMCPY(output + i, certExts, copySz);
+        i += copySz;
+    }
+
+    return i;
+}
+
+/* handle generation TLS v1.3 certificate (11) */
+/* Send the certificate for this end and any CAs that help with validation.
+ * This message is always encrypted in TLS v1.3.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 0 on success, otherwise failure.
+ */
+static int SendTls13Certificate(WOLFSSL* ssl)
+{
+    int    ret = 0;
+    word32 certSz, certChainSz, headerSz, listSz, payloadSz;
+    word16 extSz = 0;
+    word32 length, maxFragment;
+    word32 len = 0;
+    word32 idx = 0;
+    word32 offset = OPAQUE16_LEN;
+    byte*  p = NULL;
+    byte   certReqCtxLen = 0;
+    byte*  certReqCtx = NULL;
+
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_SEND);
+    WOLFSSL_ENTER("SendTls13Certificate");
+
+#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
+    if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->certReqCtx != NULL) {
+        certReqCtxLen = ssl->certReqCtx->len;
+        certReqCtx = &ssl->certReqCtx->ctx;
+    }
+#endif
+
+    if (ssl->options.sendVerify == SEND_BLANK_CERT) {
+        certSz = 0;
+        certChainSz = 0;
+        headerSz = OPAQUE8_LEN + certReqCtxLen + CERT_HEADER_SZ;
+        length = headerSz;
+        listSz = 0;
+    }
+    else {
+        if (!ssl->buffers.certificate) {
+            WOLFSSL_MSG("Send Cert missing certificate buffer");
+            return BUFFER_ERROR;
+        }
+        /* Certificate Data */
+        certSz = ssl->buffers.certificate->length;
+        /* Cert Req Ctx Len | Cert Req Ctx | Cert List Len | Cert Data Len */
+        headerSz = OPAQUE8_LEN + certReqCtxLen + CERT_HEADER_SZ +
+                   CERT_HEADER_SZ;
+
+        ret = TLSX_GetResponseSize(ssl, certificate, &extSz);
+        if (ret < 0)
+            return ret;
+
+        /* Create extensions' data if none already present. */
+        if (extSz > OPAQUE16_LEN && ssl->buffers.certExts == NULL) {
+            ret = AllocDer(&ssl->buffers.certExts, extSz, CERT_TYPE, ssl->heap);
+            if (ret < 0)
+                return ret;
+
+            extSz = 0;
+            ret = TLSX_WriteResponse(ssl, ssl->buffers.certExts->buffer,
+                                                           certificate, &extSz);
+            if (ret < 0)
+                return ret;
+        }
+
+        /* Length of message data with one certificate and extensions. */
+        length = headerSz + certSz + extSz;
+        /* Length of list data with one certificate and extensions. */
+        listSz = CERT_HEADER_SZ + certSz + extSz;
+
+        /* Send rest of chain if sending cert (chain has leading size/s). */
+        if (certSz > 0 && ssl->buffers.certChainCnt > 0) {
+            p = ssl->buffers.certChain->buffer;
+            /* Chain length including extensions. */
+            certChainSz = ssl->buffers.certChain->length +
+                          OPAQUE16_LEN * ssl->buffers.certChainCnt;
+            length += certChainSz;
+            listSz += certChainSz;
+        }
+        else
+            certChainSz = 0;
+    }
+
+    payloadSz = length;
+
+    if (ssl->fragOffset != 0)
+        length -= (ssl->fragOffset + headerSz);
+
+    maxFragment = wolfSSL_GetMaxRecordSize(ssl, MAX_RECORD_SIZE);
+
+    while (length > 0 && ret == 0) {
+        byte*  output = NULL;
+        word32 fragSz = 0;
+        word32 i = RECORD_HEADER_SZ;
+        int    sendSz = RECORD_HEADER_SZ;
+
+        if (ssl->fragOffset == 0)  {
+            if (headerSz + certSz + extSz + certChainSz <=
+                                            maxFragment - HANDSHAKE_HEADER_SZ) {
+                fragSz = headerSz + certSz + extSz + certChainSz;
+            }
+            else
+                fragSz = maxFragment - HANDSHAKE_HEADER_SZ;
+
+            sendSz += fragSz + HANDSHAKE_HEADER_SZ;
+            i += HANDSHAKE_HEADER_SZ;
+        }
+        else {
+            fragSz = min(length, maxFragment);
+            sendSz += fragSz;
+        }
+
+        sendSz += MAX_MSG_EXTRA;
+
+        /* Check buffers are big enough and grow if needed. */
+        if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+            return ret;
+
+        /* Get position in output buffer to write new message to. */
+        output = ssl->buffers.outputBuffer.buffer +
+                 ssl->buffers.outputBuffer.length;
+
+        if (ssl->fragOffset == 0) {
+            AddTls13FragHeaders(output, fragSz, 0, payloadSz, certificate, ssl);
+
+            /* Request context. */
+            output[i++] = certReqCtxLen;
+            if (certReqCtxLen > 0) {
+                XMEMCPY(output + i, certReqCtx, certReqCtxLen);
+                i += certReqCtxLen;
+            }
+            length -= OPAQUE8_LEN + certReqCtxLen;
+            fragSz -= OPAQUE8_LEN + certReqCtxLen;
+            /* Certificate list length. */
+            c32to24(listSz, output + i);
+            i += CERT_HEADER_SZ;
+            length -= CERT_HEADER_SZ;
+            fragSz -= CERT_HEADER_SZ;
+            /* Leaf certificate data length. */
+            if (certSz > 0) {
+                c32to24(certSz, output + i);
+                i += CERT_HEADER_SZ;
+                length -= CERT_HEADER_SZ;
+                fragSz -= CERT_HEADER_SZ;
+            }
+        }
+        else
+            AddTls13RecordHeader(output, fragSz, handshake, ssl);
+
+        if (certSz > 0 && ssl->fragOffset < certSz + extSz) {
+            /* Put in the leaf certificate with extensions. */
+            word32 copySz = AddCertExt(ssl, ssl->buffers.certificate->buffer,
+                            certSz, extSz, ssl->fragOffset, fragSz, output + i);
+            i += copySz;
+            ssl->fragOffset += copySz;
+            length -= copySz;
+            fragSz -= copySz;
+            if (ssl->fragOffset == certSz + extSz)
+                FreeDer(&ssl->buffers.certExts);
+        }
+        if (certChainSz > 0 && fragSz > 0) {
+            /* Put in the CA certificates with empty extensions. */
+            while (fragSz > 0) {
+                word32 l;
+
+                if (offset == len + OPAQUE16_LEN) {
+                    /* Find next CA certificate to write out. */
+                    offset = 0;
+                    /* Point to the start of current cert in chain buffer. */
+                    p = ssl->buffers.certChain->buffer + idx;
+                    len = NextCert(ssl->buffers.certChain->buffer,
+                                   ssl->buffers.certChain->length, &idx);
+                    if (len == 0)
+                        break;
+                }
+
+                /* Write out certificate and empty extension. */
+                l = AddCertExt(ssl, p, len, OPAQUE16_LEN, offset, fragSz,
+                                                                    output + i);
+                i += l;
+                ssl->fragOffset += l;
+                length -= l;
+                fragSz -= l;
+                offset += l;
+            }
+        }
+
+        if ((int)i - RECORD_HEADER_SZ < 0) {
+            WOLFSSL_MSG("Send Cert bad inputSz");
+            return BUFFER_E;
+        }
+
+        /* This message is always encrypted. */
+        sendSz = BuildTls13Message(ssl, output, sendSz,
+                                   output + RECORD_HEADER_SZ,
+                                   i - RECORD_HEADER_SZ, handshake, 1, 0, 0);
+        if (sendSz < 0)
+            return sendSz;
+
+        #ifdef WOLFSSL_CALLBACKS
+            if (ssl->hsInfoOn)
+                AddPacketName(ssl, "Certificate");
+            if (ssl->toInfoOn) {
+                AddPacketInfo(ssl, "Certificate", handshake, output,
+                        sendSz, WRITE_PROTO, ssl->heap);
+            }
+        #endif
+
+        ssl->buffers.outputBuffer.length += sendSz;
+        if (!ssl->options.groupMessages)
+            ret = SendBuffered(ssl);
+    }
+
+    if (ret != WANT_WRITE) {
+        /* Clean up the fragment offset. */
+        ssl->fragOffset = 0;
+        if (ssl->options.side == WOLFSSL_SERVER_END)
+            ssl->options.serverState = SERVER_CERT_COMPLETE;
+    }
+
+#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
+    if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->certReqCtx != NULL) {
+        CertReqCtx* ctx = ssl->certReqCtx;
+        ssl->certReqCtx = ssl->certReqCtx->next;
+        XFREE(ctx, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+#endif
+
+    WOLFSSL_LEAVE("SendTls13Certificate", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_SEND);
+
+    return ret;
+}
+
+typedef struct Scv13Args {
+    byte*  output; /* not allocated */
+    byte*  verify; /* not allocated */
+    word32 idx;
+    word32 sigLen;
+    int    sendSz;
+    word16 length;
+
+    byte   sigAlgo;
+    byte*  sigData;
+    word16 sigDataSz;
+} Scv13Args;
+
+static void FreeScv13Args(WOLFSSL* ssl, void* pArgs)
+{
+    Scv13Args* args = (Scv13Args*)pArgs;
+
+    (void)ssl;
+
+    if (args->sigData) {
+        XFREE(args->sigData, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+        args->sigData = NULL;
+    }
+}
+
+/* handle generation TLS v1.3 certificate_verify (15) */
+/* Send the TLS v1.3 CertificateVerify message.
+ * A hash of all the message so far is used.
+ * The signed data is:
+ *     0x20 * 64 | context string | 0x00 | hash of messages
+ * This message is always encrypted in TLS v1.3.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 0 on success, otherwise failure.
+ */
+static int SendTls13CertificateVerify(WOLFSSL* ssl)
+{
+    int ret = 0;
+    buffer* sig = &ssl->buffers.sig;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    Scv13Args* args = (Scv13Args*)ssl->async.args;
+    typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+    (void)sizeof(args_test);
+#else
+    Scv13Args  args[1];
+#endif
+
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_VERIFY_SEND);
+    WOLFSSL_ENTER("SendTls13CertificateVerify");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
+    if (ret != WC_NOT_PENDING_E) {
+        /* Check for error */
+        if (ret < 0)
+            goto exit_scv;
+    }
+    else
+#endif
+    {
+        /* Reset state */
+        ret = 0;
+        ssl->options.asyncState = TLS_ASYNC_BEGIN;
+        XMEMSET(args, 0, sizeof(Scv13Args));
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        ssl->async.freeArgs = FreeScv13Args;
+    #endif
+    }
+
+    switch(ssl->options.asyncState)
+    {
+        case TLS_ASYNC_BEGIN:
+        {
+            if (ssl->options.sendVerify == SEND_BLANK_CERT) {
+                return 0;  /* sent blank cert, can't verify */
+            }
+
+            args->sendSz = MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA;
+            /* Always encrypted.  */
+            args->sendSz += MAX_MSG_EXTRA;
+
+            /* check for available size */
+            if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
+                goto exit_scv;
+            }
+
+            /* get output buffer */
+            args->output = ssl->buffers.outputBuffer.buffer +
+                           ssl->buffers.outputBuffer.length;
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_BUILD;
+        } /* case TLS_ASYNC_BEGIN */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_BUILD:
+        {
+            /* idx is used to track verify pointer offset to output */
+            args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+            args->verify =
+                          &args->output[RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ];
+
+            if (ssl->buffers.key == NULL) {
+            #ifdef HAVE_PK_CALLBACKS
+                if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx))
+                    args->length = GetPrivateKeySigSize(ssl);
+                else
+            #endif
+                    ERROR_OUT(NO_PRIVATE_KEY, exit_scv);
+            }
+            else {
+                ret = DecodePrivateKey(ssl, &args->length);
+                if (ret != 0)
+                    goto exit_scv;
+            }
+
+            if (args->length <= 0) {
+                ERROR_OUT(NO_PRIVATE_KEY, exit_scv);
+            }
+
+            /* Add signature algorithm. */
+            if (ssl->hsType == DYNAMIC_TYPE_RSA)
+                args->sigAlgo = rsa_pss_sa_algo;
+            else if (ssl->hsType == DYNAMIC_TYPE_ECC)
+                args->sigAlgo = ecc_dsa_sa_algo;
+        #ifdef HAVE_ED25519
+            else if (ssl->hsType == DYNAMIC_TYPE_ED25519)
+                args->sigAlgo = ed25519_sa_algo;
+        #endif
+        #ifdef HAVE_ED448
+            else if (ssl->hsType == DYNAMIC_TYPE_ED448)
+                args->sigAlgo = ed448_sa_algo;
+        #endif
+            EncodeSigAlg(ssl->suites->hashAlgo, args->sigAlgo, args->verify);
+
+            if (ssl->hsType == DYNAMIC_TYPE_RSA) {
+                int sigLen = MAX_SIG_DATA_SZ;
+                if (args->length > MAX_SIG_DATA_SZ)
+                    sigLen = args->length;
+                args->sigData = (byte*)XMALLOC(sigLen, ssl->heap,
+                                                        DYNAMIC_TYPE_SIGNATURE);
+            }
+            else {
+                args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap,
+                                                        DYNAMIC_TYPE_SIGNATURE);
+            }
+            if (args->sigData == NULL) {
+                ERROR_OUT(MEMORY_E, exit_scv);
+            }
+
+            /* Create the data to be signed. */
+            ret = CreateSigData(ssl, args->sigData, &args->sigDataSz, 0);
+            if (ret != 0)
+                goto exit_scv;
+
+        #ifndef NO_RSA
+            if (ssl->hsType == DYNAMIC_TYPE_RSA) {
+                /* build encoded signature buffer */
+                sig->length = WC_MAX_DIGEST_SIZE;
+                sig->buffer = (byte*)XMALLOC(sig->length, ssl->heap,
+                                                        DYNAMIC_TYPE_SIGNATURE);
+                if (sig->buffer == NULL) {
+                    ERROR_OUT(MEMORY_E, exit_scv);
+                }
+
+                ret = CreateRSAEncodedSig(sig->buffer, args->sigData,
+                    args->sigDataSz, args->sigAlgo, ssl->suites->hashAlgo);
+                if (ret < 0)
+                    goto exit_scv;
+                sig->length = ret;
+                ret = 0;
+
+                /* Maximum size of RSA Signature. */
+                args->sigLen = args->length;
+            }
+        #endif /* !NO_RSA */
+        #ifdef HAVE_ECC
+            if (ssl->hsType == DYNAMIC_TYPE_ECC) {
+                sig->length = args->sendSz - args->idx - HASH_SIG_SIZE -
+                              VERIFY_HEADER;
+                ret = CreateECCEncodedSig(args->sigData,
+                    args->sigDataSz, ssl->suites->hashAlgo);
+                if (ret < 0)
+                    goto exit_scv;
+                args->sigDataSz = (word16)ret;
+                ret = 0;
+            }
+        #endif /* HAVE_ECC */
+        #ifdef HAVE_ED25519
+            if (ssl->hsType == DYNAMIC_TYPE_ED25519) {
+                ret = Ed25519CheckPubKey(ssl);
+                if (ret < 0) {
+                    ERROR_OUT(ret, exit_scv);
+                }
+                sig->length = ED25519_SIG_SIZE;
+            }
+        #endif /* HAVE_ED25519 */
+        #ifdef HAVE_ED448
+            if (ssl->hsType == DYNAMIC_TYPE_ED448) {
+                ret = Ed448CheckPubKey(ssl);
+                if (ret < 0) {
+                    ERROR_OUT(ret, exit_scv);
+                }
+                sig->length = ED448_SIG_SIZE;
+            }
+        #endif /* HAVE_ED448 */
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_DO;
+        } /* case TLS_ASYNC_BUILD */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_DO:
+        {
+        #ifdef HAVE_ECC
+           if (ssl->hsType == DYNAMIC_TYPE_ECC) {
+
+                ret = EccSign(ssl, args->sigData, args->sigDataSz,
+                    args->verify + HASH_SIG_SIZE + VERIFY_HEADER,
+                    (word32*)&sig->length, (ecc_key*)ssl->hsKey,
+            #ifdef HAVE_PK_CALLBACKS
+                    ssl->buffers.key
+            #else
+                    NULL
+            #endif
+                );
+                args->length = (word16)sig->length;
+            }
+        #endif /* HAVE_ECC */
+        #ifdef HAVE_ED25519
+            if (ssl->hsType == DYNAMIC_TYPE_ED25519) {
+                ret = Ed25519Sign(ssl, args->sigData, args->sigDataSz,
+                    args->verify + HASH_SIG_SIZE + VERIFY_HEADER,
+                    (word32*)&sig->length, (ed25519_key*)ssl->hsKey,
+            #ifdef HAVE_PK_CALLBACKS
+                    ssl->buffers.key
+            #else
+                    NULL
+            #endif
+                );
+                args->length = (word16)sig->length;
+            }
+        #endif
+        #ifdef HAVE_ED448
+            if (ssl->hsType == DYNAMIC_TYPE_ED448) {
+                ret = Ed448Sign(ssl, args->sigData, args->sigDataSz,
+                    args->verify + HASH_SIG_SIZE + VERIFY_HEADER,
+                    (word32*)&sig->length, (ed448_key*)ssl->hsKey,
+            #ifdef HAVE_PK_CALLBACKS
+                    ssl->buffers.key
+            #else
+                    NULL
+            #endif
+                );
+                args->length = (word16)sig->length;
+            }
+        #endif
+        #ifndef NO_RSA
+            if (ssl->hsType == DYNAMIC_TYPE_RSA) {
+                ret = RsaSign(ssl, sig->buffer, (word32)sig->length,
+                    args->verify + HASH_SIG_SIZE + VERIFY_HEADER, &args->sigLen,
+                    args->sigAlgo, ssl->suites->hashAlgo,
+                    (RsaKey*)ssl->hsKey,
+                    ssl->buffers.key
+                );
+                if (ret == 0) {
+                    args->length = (word16)args->sigLen;
+
+                    XMEMCPY(args->sigData,
+                        args->verify + HASH_SIG_SIZE + VERIFY_HEADER,
+                        args->sigLen);
+                }
+            }
+        #endif /* !NO_RSA */
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_scv;
+            }
+
+            /* Add signature length. */
+            c16toa(args->length, args->verify + HASH_SIG_SIZE);
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_VERIFY;
+        } /* case TLS_ASYNC_DO */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_VERIFY:
+        {
+        #ifndef NO_RSA
+            if (ssl->hsType == DYNAMIC_TYPE_RSA) {
+                /* check for signature faults */
+                ret = VerifyRsaSign(ssl, args->sigData, args->sigLen,
+                    sig->buffer, (word32)sig->length, args->sigAlgo,
+                    ssl->suites->hashAlgo, (RsaKey*)ssl->hsKey,
+                    ssl->buffers.key
+                );
+            }
+        #endif /* !NO_RSA */
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_scv;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_FINALIZE;
+        } /* case TLS_ASYNC_VERIFY */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_FINALIZE:
+        {
+            /* Put the record and handshake headers on. */
+            AddTls13Headers(args->output, args->length + HASH_SIG_SIZE +
+                            VERIFY_HEADER, certificate_verify, ssl);
+
+            args->sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ +
+                                   args->length + HASH_SIG_SIZE + VERIFY_HEADER;
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_END;
+        } /* case TLS_ASYNC_FINALIZE */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_END:
+        {
+            /* This message is always encrypted. */
+            ret = BuildTls13Message(ssl, args->output,
+                                    MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA,
+                                    args->output + RECORD_HEADER_SZ,
+                                    args->sendSz - RECORD_HEADER_SZ, handshake,
+                                    1, 0, 0);
+
+            if (ret < 0) {
+                goto exit_scv;
+            }
+            else {
+                args->sendSz = ret;
+                ret = 0;
+            }
+
+        #ifdef WOLFSSL_CALLBACKS
+            if (ssl->hsInfoOn)
+                AddPacketName(ssl, "CertificateVerify");
+            if (ssl->toInfoOn) {
+                AddPacketInfo(ssl, "CertificateVerify", handshake,
+                            args->output, args->sendSz, WRITE_PROTO, ssl->heap);
+            }
+        #endif
+
+            ssl->buffers.outputBuffer.length += args->sendSz;
+
+            if (!ssl->options.groupMessages)
+                ret = SendBuffered(ssl);
+            break;
+        }
+        default:
+            ret = INPUT_CASE_ERROR;
+    } /* switch(ssl->options.asyncState) */
+
+exit_scv:
+
+    WOLFSSL_LEAVE("SendTls13CertificateVerify", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_SEND);
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* Handle async operation */
+    if (ret == WC_PENDING_E) {
+        return ret;
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    /* Final cleanup */
+    FreeScv13Args(ssl, args);
+    FreeKeyExchange(ssl);
+
+    return ret;
+}
+
+/* handle processing TLS v1.3 certificate (11) */
+/* Parse and handle a TLS v1.3 Certificate message.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The message buffer.
+ * inOutIdx  On entry, the index into the message buffer of Certificate.
+ *           On exit, the index of byte after the Certificate message.
+ * totalSz   The length of the current handshake message.
+ * returns 0 on success and otherwise failure.
+ */
+static int DoTls13Certificate(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+                              word32 totalSz)
+{
+    int ret;
+
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_DO);
+    WOLFSSL_ENTER("DoTls13Certificate");
+
+    ret = ProcessPeerCerts(ssl, input, inOutIdx, totalSz);
+    if (ret == 0) {
+#if !defined(NO_WOLFSSL_CLIENT)
+        if (ssl->options.side == WOLFSSL_CLIENT_END)
+            ssl->options.serverState = SERVER_CERT_COMPLETE;
+#endif
+#if !defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+        if (ssl->options.side == WOLFSSL_SERVER_END &&
+                                ssl->options.handShakeState == HANDSHAKE_DONE) {
+            /* reset handshake states */
+            ssl->options.serverState = SERVER_FINISHED_COMPLETE;
+            ssl->options.acceptState  = TICKET_SENT;
+            ssl->options.handShakeState = SERVER_FINISHED_COMPLETE;
+        }
+#endif
+    }
+
+    WOLFSSL_LEAVE("DoTls13Certificate", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_DO);
+
+    return ret;
+}
+
+#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+                                                             defined(HAVE_ED448)
+
+typedef struct Dcv13Args {
+    byte*  output; /* not allocated */
+    word32 sendSz;
+    word16 sz;
+    word32 sigSz;
+    word32 idx;
+    word32 begin;
+    byte   hashAlgo;
+    byte   sigAlgo;
+
+    byte*  sigData;
+    word16 sigDataSz;
+} Dcv13Args;
+
+static void FreeDcv13Args(WOLFSSL* ssl, void* pArgs)
+{
+    Dcv13Args* args = (Dcv13Args*)pArgs;
+
+    if (args->sigData != NULL) {
+        XFREE(args->sigData, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+        args->sigData = NULL;
+    }
+
+    (void)ssl;
+}
+
+/* handle processing TLS v1.3 certificate_verify (15) */
+/* Parse and handle a TLS v1.3 CertificateVerify message.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The message buffer.
+ * inOutIdx  On entry, the index into the message buffer of
+ *           CertificateVerify.
+ *           On exit, the index of byte after the CertificateVerify message.
+ * totalSz   The length of the current handshake message.
+ * returns 0 on success and otherwise failure.
+ */
+static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
+                                    word32* inOutIdx, word32 totalSz)
+{
+    int         ret = 0;
+    buffer*     sig = &ssl->buffers.sig;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    Dcv13Args* args = (Dcv13Args*)ssl->async.args;
+    typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+    (void)sizeof(args_test);
+#else
+    Dcv13Args  args[1];
+#endif
+
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_VERIFY_DO);
+    WOLFSSL_ENTER("DoTls13CertificateVerify");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
+    if (ret != WC_NOT_PENDING_E) {
+        /* Check for error */
+        if (ret < 0)
+            goto exit_dcv;
+    }
+    else
+#endif
+    {
+        /* Reset state */
+        ret = 0;
+        ssl->options.asyncState = TLS_ASYNC_BEGIN;
+        XMEMSET(args, 0, sizeof(Dcv13Args));
+        args->hashAlgo = sha_mac;
+        args->sigAlgo = anonymous_sa_algo;
+        args->idx = *inOutIdx;
+        args->begin = *inOutIdx;
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        ssl->async.freeArgs = FreeDcv13Args;
+    #endif
+    }
+
+    switch(ssl->options.asyncState)
+    {
+        case TLS_ASYNC_BEGIN:
+        {
+        #ifdef WOLFSSL_CALLBACKS
+            if (ssl->hsInfoOn) AddPacketName(ssl, "CertificateVerify");
+            if (ssl->toInfoOn) AddLateName("CertificateVerify",
+                                           &ssl->timeoutInfo);
+        #endif
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_BUILD;
+        } /* case TLS_ASYNC_BEGIN */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_BUILD:
+        {
+            /* Signature algorithm. */
+            if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN > totalSz) {
+                ERROR_OUT(BUFFER_ERROR, exit_dcv);
+            }
+            ret = DecodeTls13SigAlg(input + args->idx, &args->hashAlgo,
+                                                                &args->sigAlgo);
+            if (ret < 0)
+                goto exit_dcv;
+            args->idx += OPAQUE16_LEN;
+
+            /* Signature length. */
+            if ((args->idx - args->begin) + OPAQUE16_LEN > totalSz) {
+                ERROR_OUT(BUFFER_ERROR, exit_dcv);
+            }
+            ato16(input + args->idx, &args->sz);
+            args->idx += OPAQUE16_LEN;
+
+            /* Signature data. */
+            if ((args->idx - args->begin) + args->sz > totalSz ||
+                                                       args->sz > ENCRYPT_LEN) {
+                ERROR_OUT(BUFFER_ERROR, exit_dcv);
+            }
+
+            /* Check for public key of required type. */
+        #ifdef HAVE_ED25519
+            if (args->sigAlgo == ed25519_sa_algo &&
+                                                  !ssl->peerEd25519KeyPresent) {
+                WOLFSSL_MSG("Oops, peer sent ED25519 key but not in verify");
+            }
+        #endif
+        #ifdef HAVE_ED448
+            if (args->sigAlgo == ed448_sa_algo && !ssl->peerEd448KeyPresent) {
+                WOLFSSL_MSG("Oops, peer sent ED448 key but not in verify");
+            }
+        #endif
+        #ifdef HAVE_ECC
+            if (args->sigAlgo == ecc_dsa_sa_algo &&
+                                                   !ssl->peerEccDsaKeyPresent) {
+                WOLFSSL_MSG("Oops, peer sent ECC key but not in verify");
+            }
+        #endif
+        #ifndef NO_RSA
+            if (args->sigAlgo == rsa_sa_algo) {
+                WOLFSSL_MSG("Oops, peer sent PKCS#1.5 signature");
+                ERROR_OUT(INVALID_PARAMETER, exit_dcv);
+            }
+            if (args->sigAlgo == rsa_pss_sa_algo &&
+                         (ssl->peerRsaKey == NULL || !ssl->peerRsaKeyPresent)) {
+                WOLFSSL_MSG("Oops, peer sent RSA key but not in verify");
+            }
+        #endif
+
+            sig->buffer = (byte*)XMALLOC(args->sz, ssl->heap,
+                                         DYNAMIC_TYPE_SIGNATURE);
+            if (sig->buffer == NULL) {
+                ERROR_OUT(MEMORY_E, exit_dcv);
+            }
+            sig->length = args->sz;
+            XMEMCPY(sig->buffer, input + args->idx, args->sz);
+
+        #ifdef HAVE_ECC
+            if (ssl->peerEccDsaKeyPresent) {
+                WOLFSSL_MSG("Doing ECC peer cert verify");
+
+                args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap,
+                                                        DYNAMIC_TYPE_SIGNATURE);
+                if (args->sigData == NULL) {
+                    ERROR_OUT(MEMORY_E, exit_dcv);
+                }
+
+                ret = CreateSigData(ssl, args->sigData, &args->sigDataSz, 1);
+                if (ret != 0)
+                    goto exit_dcv;
+                ret = CreateECCEncodedSig(args->sigData,
+                    args->sigDataSz, args->hashAlgo);
+                if (ret < 0)
+                    goto exit_dcv;
+                args->sigDataSz = (word16)ret;
+                ret = 0;
+            }
+        #endif
+        #ifdef HAVE_ED25519
+            if (ssl->peerEd25519KeyPresent) {
+                WOLFSSL_MSG("Doing ED25519 peer cert verify");
+
+                args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap,
+                                                        DYNAMIC_TYPE_SIGNATURE);
+                if (args->sigData == NULL) {
+                    ERROR_OUT(MEMORY_E, exit_dcv);
+                }
+
+                CreateSigData(ssl, args->sigData, &args->sigDataSz, 1);
+                ret = 0;
+            }
+        #endif
+        #ifdef HAVE_ED448
+            if (ssl->peerEd448KeyPresent) {
+                WOLFSSL_MSG("Doing ED448 peer cert verify");
+
+                args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap,
+                                                        DYNAMIC_TYPE_SIGNATURE);
+                if (args->sigData == NULL) {
+                    ERROR_OUT(MEMORY_E, exit_dcv);
+                }
+
+                CreateSigData(ssl, args->sigData, &args->sigDataSz, 1);
+                ret = 0;
+            }
+       #endif
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_DO;
+        } /* case TLS_ASYNC_BUILD */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_DO:
+        {
+        #ifndef NO_RSA
+            if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) {
+                WOLFSSL_MSG("Doing RSA peer cert verify");
+
+                ret = RsaVerify(ssl, sig->buffer, (word32)sig->length, &args->output,
+                    args->sigAlgo, args->hashAlgo, ssl->peerRsaKey,
+                #ifdef HAVE_PK_CALLBACKS
+                    &ssl->buffers.peerRsaKey
+                #else
+                    NULL
+                #endif
+                );
+                if (ret >= 0) {
+                    args->sendSz = ret;
+                    ret = 0;
+                }
+            }
+        #endif /* !NO_RSA */
+        #ifdef HAVE_ECC
+            if (ssl->peerEccDsaKeyPresent) {
+                WOLFSSL_MSG("Doing ECC peer cert verify");
+
+                ret = EccVerify(ssl, input + args->idx, args->sz,
+                    args->sigData, args->sigDataSz,
+                    ssl->peerEccDsaKey,
+                #ifdef HAVE_PK_CALLBACKS
+                    &ssl->buffers.peerEccDsaKey
+                #else
+                    NULL
+                #endif
+                );
+
+                if (ret >= 0) {
+                    FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccDsaKey);
+                    ssl->peerEccDsaKeyPresent = 0;
+                }
+            }
+        #endif /* HAVE_ECC */
+        #ifdef HAVE_ED25519
+            if (ssl->peerEd25519KeyPresent) {
+                WOLFSSL_MSG("Doing ED25519 peer cert verify");
+
+                ret = Ed25519Verify(ssl, input + args->idx, args->sz,
+                    args->sigData, args->sigDataSz,
+                    ssl->peerEd25519Key,
+                #ifdef HAVE_PK_CALLBACKS
+                    &ssl->buffers.peerEd25519Key
+                #else
+                    NULL
+                #endif
+                );
+
+                if (ret >= 0) {
+                    FreeKey(ssl, DYNAMIC_TYPE_ED25519,
+                                                  (void**)&ssl->peerEd25519Key);
+                    ssl->peerEd25519KeyPresent = 0;
+                }
+            }
+        #endif
+        #ifdef HAVE_ED448
+            if (ssl->peerEd448KeyPresent) {
+                WOLFSSL_MSG("Doing ED448 peer cert verify");
+
+                ret = Ed448Verify(ssl, input + args->idx, args->sz,
+                    args->sigData, args->sigDataSz,
+                    ssl->peerEd448Key,
+                #ifdef HAVE_PK_CALLBACKS
+                    &ssl->buffers.peerEd448Key
+                #else
+                    NULL
+                #endif
+                );
+
+                if (ret >= 0) {
+                    FreeKey(ssl, DYNAMIC_TYPE_ED448,
+                                                    (void**)&ssl->peerEd448Key);
+                    ssl->peerEd448KeyPresent = 0;
+                }
+            }
+        #endif
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_dcv;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_VERIFY;
+        } /* case TLS_ASYNC_DO */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_VERIFY:
+        {
+        #ifndef NO_RSA
+            if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) {
+                ret = CheckRSASignature(ssl, args->sigAlgo, args->hashAlgo,
+                                        args->output, args->sendSz);
+                if (ret != 0)
+                    goto exit_dcv;
+
+                FreeKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey);
+                ssl->peerRsaKeyPresent = 0;
+            }
+        #endif /* !NO_RSA */
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_FINALIZE;
+        } /* case TLS_ASYNC_VERIFY */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_FINALIZE:
+        {
+            ssl->options.havePeerVerify = 1;
+
+            /* Set final index */
+            args->idx += args->sz;
+            *inOutIdx = args->idx;
+
+            /* Encryption is always on: add padding */
+            *inOutIdx += ssl->keys.padSz;
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_END;
+        } /* case TLS_ASYNC_FINALIZE */
+
+        case TLS_ASYNC_END:
+        {
+            break;
+        }
+        default:
+            ret = INPUT_CASE_ERROR;
+    } /* switch(ssl->options.asyncState) */
+
+exit_dcv:
+
+    WOLFSSL_LEAVE("DoTls13CertificateVerify", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_DO);
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* Handle async operation */
+    if (ret == WC_PENDING_E) {
+        /* Mark message as not received so it can process again */
+        ssl->msgsReceived.got_certificate_verify = 0;
+
+        return ret;
+    }
+    else
+#endif /* WOLFSSL_ASYNC_CRYPT */
+    if (ret != 0 && ret != INVALID_PARAMETER)
+        SendAlert(ssl, alert_fatal, decrypt_error);
+
+    /* Final cleanup */
+    FreeDcv13Args(ssl, args);
+    FreeKeyExchange(ssl);
+
+    return ret;
+}
+#endif /* !NO_RSA || HAVE_ECC */
+
+/* Parse and handle a TLS v1.3 Finished message.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The message buffer.
+ * inOutIdx  On entry, the index into the message buffer of Finished.
+ *           On exit, the index of byte after the Finished message and padding.
+ * size      Length of message data.
+ * totalSz   Length of remaining data in the message buffer.
+ * sniff     Indicates whether we are sniffing packets.
+ * returns 0 on success and otherwise failure.
+ */
+static int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                           word32 size, word32 totalSz, int sniff)
+{
+    int    ret;
+    word32 finishedSz = 0;
+    byte*  secret;
+    byte   mac[WC_MAX_DIGEST_SIZE];
+
+    WOLFSSL_START(WC_FUNC_FINISHED_DO);
+    WOLFSSL_ENTER("DoTls13Finished");
+
+    /* check against totalSz */
+    if (*inOutIdx + size + ssl->keys.padSz > totalSz)
+        return BUFFER_E;
+
+    if (ssl->options.handShakeDone) {
+        ret = DeriveFinishedSecret(ssl, ssl->clientSecret,
+                                   ssl->keys.client_write_MAC_secret);
+        if (ret != 0)
+            return ret;
+
+        secret = ssl->keys.client_write_MAC_secret;
+    }
+    else if (ssl->options.side == WOLFSSL_CLIENT_END) {
+        /* All the handshake messages have been received to calculate
+         * client and server finished keys.
+         */
+        ret = DeriveFinishedSecret(ssl, ssl->clientSecret,
+                                   ssl->keys.client_write_MAC_secret);
+        if (ret != 0)
+            return ret;
+
+        ret = DeriveFinishedSecret(ssl, ssl->serverSecret,
+                                   ssl->keys.server_write_MAC_secret);
+        if (ret != 0)
+            return ret;
+
+        secret = ssl->keys.server_write_MAC_secret;
+    }
+    else
+        secret = ssl->keys.client_write_MAC_secret;
+
+    ret = BuildTls13HandshakeHmac(ssl, secret, mac, &finishedSz);
+    if (ret != 0)
+        return ret;
+    if (size != finishedSz)
+        return BUFFER_ERROR;
+
+    #ifdef WOLFSSL_CALLBACKS
+        if (ssl->hsInfoOn) AddPacketName(ssl, "Finished");
+        if (ssl->toInfoOn) AddLateName("Finished", &ssl->timeoutInfo);
+    #endif
+
+    if (sniff == NO_SNIFF) {
+        /* Actually check verify data. */
+        if (XMEMCMP(input + *inOutIdx, mac, size) != 0){
+            WOLFSSL_MSG("Verify finished error on hashes");
+            SendAlert(ssl, alert_fatal, decrypt_error);
+            return VERIFY_FINISHED_ERROR;
+        }
+    }
+
+    /* Force input exhaustion at ProcessReply by consuming padSz. */
+    *inOutIdx += size + ssl->keys.padSz;
+
+    if (ssl->options.side == WOLFSSL_SERVER_END &&
+                                                  !ssl->options.handShakeDone) {
+#ifdef WOLFSSL_EARLY_DATA
+        if (ssl->earlyData != no_early_data) {
+            if ((ret = DeriveTls13Keys(ssl, no_key, DECRYPT_SIDE_ONLY, 1)) != 0)
+                return ret;
+        }
+#endif
+        /* Setup keys for application data messages from client. */
+        if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
+            return ret;
+    }
+
+#ifndef NO_WOLFSSL_CLIENT
+    if (ssl->options.side == WOLFSSL_CLIENT_END)
+        ssl->options.serverState = SERVER_FINISHED_COMPLETE;
+#endif
+#ifndef NO_WOLFSSL_SERVER
+    if (ssl->options.side == WOLFSSL_SERVER_END) {
+        ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
+        ssl->options.handShakeState = HANDSHAKE_DONE;
+        ssl->options.handShakeDone  = 1;
+    }
+#endif
+
+    WOLFSSL_LEAVE("DoTls13Finished", 0);
+    WOLFSSL_END(WC_FUNC_FINISHED_DO);
+
+    return 0;
+}
+#endif /* NO_CERTS */
+
+/* Send the TLS v1.3 Finished message.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 0 on success, otherwise failure.
+ */
+static int SendTls13Finished(WOLFSSL* ssl)
+{
+    int   sendSz;
+    int   finishedSz = ssl->specs.hash_size;
+    byte* input;
+    byte* output;
+    int   ret;
+    int   headerSz = HANDSHAKE_HEADER_SZ;
+    int   outputSz;
+    byte* secret;
+
+    WOLFSSL_START(WC_FUNC_FINISHED_SEND);
+    WOLFSSL_ENTER("SendTls13Finished");
+
+    outputSz = WC_MAX_DIGEST_SIZE + DTLS_HANDSHAKE_HEADER_SZ + MAX_MSG_EXTRA;
+    /* Check buffers are big enough and grow if needed. */
+    if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
+        return ret;
+
+    /* get output buffer */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+    input = output + RECORD_HEADER_SZ;
+
+    AddTls13HandShakeHeader(input, finishedSz, 0, finishedSz, finished, ssl);
+
+    /* make finished hashes */
+    if (ssl->options.handShakeDone) {
+        ret = DeriveFinishedSecret(ssl, ssl->clientSecret,
+                                   ssl->keys.client_write_MAC_secret);
+        if (ret != 0)
+            return ret;
+
+        secret = ssl->keys.client_write_MAC_secret;
+    }
+    else if (ssl->options.side == WOLFSSL_CLIENT_END)
+        secret = ssl->keys.client_write_MAC_secret;
+    else {
+        /* All the handshake messages have been done to calculate client and
+         * server finished keys.
+         */
+        ret = DeriveFinishedSecret(ssl, ssl->clientSecret,
+                                   ssl->keys.client_write_MAC_secret);
+        if (ret != 0)
+            return ret;
+
+        ret = DeriveFinishedSecret(ssl, ssl->serverSecret,
+                                   ssl->keys.server_write_MAC_secret);
+        if (ret != 0)
+            return ret;
+
+        secret = ssl->keys.server_write_MAC_secret;
+    }
+    ret = BuildTls13HandshakeHmac(ssl, secret, &input[headerSz], NULL);
+    if (ret != 0)
+        return ret;
+
+    /* This message is always encrypted. */
+    sendSz = BuildTls13Message(ssl, output, outputSz, input,
+                               headerSz + finishedSz, handshake, 1, 0, 0);
+    if (sendSz < 0)
+        return BUILD_MSG_ERROR;
+
+#ifndef NO_SESSION_CACHE
+    if (!ssl->options.resuming && (ssl->options.side == WOLFSSL_SERVER_END ||
+            (ssl->options.side == WOLFSSL_SERVER_END && ssl->arrays != NULL))) {
+        AddSession(ssl);    /* just try */
+    }
+#endif
+
+    #ifdef WOLFSSL_CALLBACKS
+        if (ssl->hsInfoOn) AddPacketName(ssl, "Finished");
+        if (ssl->toInfoOn) {
+            AddPacketInfo(ssl, "Finished", handshake, output, sendSz,
+                          WRITE_PROTO, ssl->heap);
+        }
+    #endif
+
+    ssl->buffers.outputBuffer.length += sendSz;
+
+    if (ssl->options.side == WOLFSSL_SERVER_END) {
+        /* Can send application data now. */
+        if ((ret = DeriveMasterSecret(ssl)) != 0)
+            return ret;
+#ifdef WOLFSSL_EARLY_DATA
+        if ((ret = DeriveTls13Keys(ssl, traffic_key, ENCRYPT_SIDE_ONLY, 1))
+                                                                         != 0) {
+            return ret;
+        }
+        if ((ret = DeriveTls13Keys(ssl, traffic_key, DECRYPT_SIDE_ONLY,
+                                       ssl->earlyData == no_early_data)) != 0) {
+            return ret;
+        }
+#else
+        if ((ret = DeriveTls13Keys(ssl, traffic_key, ENCRYPT_AND_DECRYPT_SIDE,
+                                                                     1)) != 0) {
+            return ret;
+        }
+#endif
+        if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0)
+            return ret;
+    }
+
+    if (ssl->options.side == WOLFSSL_CLIENT_END &&
+                                                  !ssl->options.handShakeDone) {
+#ifdef WOLFSSL_EARLY_DATA
+        if (ssl->earlyData != no_early_data) {
+            if ((ret = DeriveTls13Keys(ssl, no_key, ENCRYPT_AND_DECRYPT_SIDE,
+                                                                     1)) != 0) {
+                    return ret;
+            }
+        }
+#endif
+        /* Setup keys for application data messages. */
+        if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) != 0)
+            return ret;
+
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+        ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret);
+        if (ret != 0)
+            return ret;
+#endif
+    }
+
+#ifndef NO_WOLFSSL_CLIENT
+    if (ssl->options.side == WOLFSSL_CLIENT_END) {
+        ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
+        ssl->options.handShakeState = HANDSHAKE_DONE;
+        ssl->options.handShakeDone  = 1;
+    }
+#endif
+#ifndef NO_WOLFSSL_SERVER
+    if (ssl->options.side == WOLFSSL_SERVER_END) {
+        ssl->options.serverState = SERVER_FINISHED_COMPLETE;
+    }
+#endif
+
+    if ((ret = SendBuffered(ssl)) != 0)
+        return ret;
+
+    WOLFSSL_LEAVE("SendTls13Finished", ret);
+    WOLFSSL_END(WC_FUNC_FINISHED_SEND);
+
+    return ret;
+}
+
+/* handle generation TLS v1.3 key_update (24) */
+/* Send the TLS v1.3 KeyUpdate message.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 0 on success, otherwise failure.
+ */
+static int SendTls13KeyUpdate(WOLFSSL* ssl)
+{
+    int    sendSz;
+    byte*  input;
+    byte*  output;
+    int    ret;
+    int    headerSz = HANDSHAKE_HEADER_SZ;
+    int    outputSz;
+    word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+
+    WOLFSSL_START(WC_FUNC_KEY_UPDATE_SEND);
+    WOLFSSL_ENTER("SendTls13KeyUpdate");
+
+    outputSz = OPAQUE8_LEN + MAX_MSG_EXTRA;
+    /* Check buffers are big enough and grow if needed. */
+    if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
+        return ret;
+
+    /* get output buffer */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+    input = output + RECORD_HEADER_SZ;
+
+    AddTls13Headers(output, OPAQUE8_LEN, key_update, ssl);
+
+    /* If:
+     *   1. I haven't sent a KeyUpdate requesting a response and
+     *   2. This isn't responding to peer KeyUpdate requiring a response then,
+     * I want a response.
+     */
+    ssl->keys.updateResponseReq = output[i++] =
+         !ssl->keys.updateResponseReq && !ssl->keys.keyUpdateRespond;
+    /* Sent response, no longer need to respond. */
+    ssl->keys.keyUpdateRespond = 0;
+
+    /* This message is always encrypted. */
+    sendSz = BuildTls13Message(ssl, output, outputSz, input,
+                               headerSz + OPAQUE8_LEN, handshake, 0, 0, 0);
+    if (sendSz < 0)
+        return BUILD_MSG_ERROR;
+
+    #ifdef WOLFSSL_CALLBACKS
+        if (ssl->hsInfoOn) AddPacketName(ssl, "KeyUpdate");
+        if (ssl->toInfoOn) {
+            AddPacketInfo(ssl, "KeyUpdate", handshake, output, sendSz,
+                          WRITE_PROTO, ssl->heap);
+        }
+    #endif
+
+    ssl->buffers.outputBuffer.length += sendSz;
+
+    ret = SendBuffered(ssl);
+    if (ret != 0 && ret != WANT_WRITE)
+        return ret;
+
+    /* Future traffic uses new encryption keys. */
+    if ((ret = DeriveTls13Keys(ssl, update_traffic_key, ENCRYPT_SIDE_ONLY, 1))
+                                                                           != 0)
+        return ret;
+    if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0)
+        return ret;
+
+    WOLFSSL_LEAVE("SendTls13KeyUpdate", ret);
+    WOLFSSL_END(WC_FUNC_KEY_UPDATE_SEND);
+
+    return ret;
+}
+
+/* handle processing TLS v1.3 key_update (24) */
+/* Parse and handle a TLS v1.3 KeyUpdate message.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The message buffer.
+ * inOutIdx  On entry, the index into the message buffer of Finished.
+ *           On exit, the index of byte after the Finished message and padding.
+ * totalSz   The length of the current handshake message.
+ * returns 0 on success and otherwise failure.
+ */
+static int DoTls13KeyUpdate(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                            word32 totalSz)
+{
+    int    ret;
+    word32 i = *inOutIdx;
+
+    WOLFSSL_START(WC_FUNC_KEY_UPDATE_DO);
+    WOLFSSL_ENTER("DoTls13KeyUpdate");
+
+    /* check against totalSz */
+    if (OPAQUE8_LEN != totalSz)
+        return BUFFER_E;
+
+    switch (input[i]) {
+        case update_not_requested:
+            /* This message in response to any outstanding request. */
+            ssl->keys.keyUpdateRespond = 0;
+            ssl->keys.updateResponseReq = 0;
+            break;
+        case update_requested:
+            /* New key update requiring a response. */
+            ssl->keys.keyUpdateRespond = 1;
+            break;
+        default:
+            return INVALID_PARAMETER;
+    }
+
+    /* Move index to byte after message. */
+    *inOutIdx += totalSz;
+    /* Always encrypted. */
+    *inOutIdx += ssl->keys.padSz;
+
+    /* Future traffic uses new decryption keys. */
+    if ((ret = DeriveTls13Keys(ssl, update_traffic_key, DECRYPT_SIDE_ONLY, 1))
+                                                                         != 0) {
+        return ret;
+    }
+    if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
+        return ret;
+
+    if (ssl->keys.keyUpdateRespond)
+        return SendTls13KeyUpdate(ssl);
+
+    WOLFSSL_LEAVE("DoTls13KeyUpdate", ret);
+    WOLFSSL_END(WC_FUNC_KEY_UPDATE_DO);
+
+    return 0;
+}
+
+#ifdef WOLFSSL_EARLY_DATA
+#ifndef NO_WOLFSSL_CLIENT
+/* Send the TLS v1.3 EndOfEarlyData message to indicate that there will be no
+ * more early application data.
+ * The encryption key now changes to the pre-calculated handshake key.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 0 on success and otherwise failure.
+ */
+static int SendTls13EndOfEarlyData(WOLFSSL* ssl)
+{
+    byte*  output;
+    int    ret;
+    int    sendSz;
+    word32 length;
+    word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+
+    WOLFSSL_START(WC_FUNC_END_OF_EARLY_DATA_SEND);
+    WOLFSSL_ENTER("SendTls13EndOfEarlyData");
+
+    length = 0;
+    sendSz = idx + length + MAX_MSG_EXTRA;
+
+    /* Check buffers are big enough and grow if needed. */
+    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+        return ret;
+
+    /* Get position in output buffer to write new message to. */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+
+    /* Put the record and handshake headers on. */
+    AddTls13Headers(output, length, end_of_early_data, ssl);
+
+    /* This message is always encrypted. */
+    sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ,
+                               idx - RECORD_HEADER_SZ, handshake, 1, 0, 0);
+    if (sendSz < 0)
+        return sendSz;
+
+    ssl->buffers.outputBuffer.length += sendSz;
+
+    if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0)
+        return ret;
+
+    if (!ssl->options.groupMessages)
+        ret = SendBuffered(ssl);
+
+    WOLFSSL_LEAVE("SendTls13EndOfEarlyData", ret);
+    WOLFSSL_END(WC_FUNC_END_OF_EARLY_DATA_SEND);
+
+    return ret;
+}
+#endif /* !NO_WOLFSSL_CLIENT */
+
+#ifndef NO_WOLFSSL_SERVER
+/* handle processing of TLS 1.3 end_of_early_data (5) */
+/* Parse the TLS v1.3 EndOfEarlyData message that indicates that there will be
+ * no more early application data.
+ * The decryption key now changes to the pre-calculated handshake key.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 0 on success and otherwise failure.
+ */
+static int DoTls13EndOfEarlyData(WOLFSSL* ssl, const byte* input,
+                                 word32* inOutIdx, word32 size)
+{
+    int    ret;
+    word32 begin = *inOutIdx;
+
+    (void)input;
+
+    WOLFSSL_START(WC_FUNC_END_OF_EARLY_DATA_DO);
+    WOLFSSL_ENTER("DoTls13EndOfEarlyData");
+
+    if ((*inOutIdx - begin) != size)
+        return BUFFER_ERROR;
+
+    if (ssl->earlyData == no_early_data) {
+        WOLFSSL_MSG("EndOfEarlyData received unexpectedly");
+        SendAlert(ssl, alert_fatal, unexpected_message);
+        return OUT_OF_ORDER_E;
+    }
+
+    ssl->earlyData = done_early_data;
+
+    /* Always encrypted. */
+    *inOutIdx += ssl->keys.padSz;
+
+    ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY);
+
+    WOLFSSL_LEAVE("DoTls13EndOfEarlyData", ret);
+    WOLFSSL_END(WC_FUNC_END_OF_EARLY_DATA_DO);
+
+    return ret;
+}
+#endif /* !NO_WOLFSSL_SERVER */
+#endif /* WOLFSSL_EARLY_DATA */
+
+#ifndef NO_WOLFSSL_CLIENT
+/* Handle a New Session Ticket handshake message.
+ * Message contains the information required to perform resumption.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The message buffer.
+ * inOutIdx  On entry, the index into the message buffer of Finished.
+ *           On exit, the index of byte after the Finished message and padding.
+ * size      The length of the current handshake message.
+ * returns 0 on success, otherwise failure.
+ */
+static int DoTls13NewSessionTicket(WOLFSSL* ssl, const byte* input,
+                                   word32* inOutIdx, word32 size)
+{
+#ifdef HAVE_SESSION_TICKET
+    int    ret;
+    word32 begin = *inOutIdx;
+    word32 lifetime;
+    word32 ageAdd;
+    word16 length;
+    word32 now;
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    const byte*  nonce;
+    byte         nonceLength;
+#endif
+
+    WOLFSSL_START(WC_FUNC_NEW_SESSION_TICKET_DO);
+    WOLFSSL_ENTER("DoTls13NewSessionTicket");
+
+    /* Lifetime hint. */
+    if ((*inOutIdx - begin) + SESSION_HINT_SZ > size)
+        return BUFFER_ERROR;
+    ato32(input + *inOutIdx, &lifetime);
+    *inOutIdx += SESSION_HINT_SZ;
+    if (lifetime > MAX_LIFETIME)
+        return SERVER_HINT_ERROR;
+
+    /* Age add. */
+    if ((*inOutIdx - begin) + SESSION_ADD_SZ > size)
+        return BUFFER_ERROR;
+    ato32(input + *inOutIdx, &ageAdd);
+    *inOutIdx += SESSION_ADD_SZ;
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    /* Ticket nonce. */
+    if ((*inOutIdx - begin) + 1 > size)
+        return BUFFER_ERROR;
+    nonceLength = input[*inOutIdx];
+    if (nonceLength > MAX_TICKET_NONCE_SZ) {
+        WOLFSSL_MSG("Nonce length not supported");
+        return INVALID_PARAMETER;
+    }
+    *inOutIdx += 1;
+    if ((*inOutIdx - begin) + nonceLength > size)
+        return BUFFER_ERROR;
+    nonce = input + *inOutIdx;
+    *inOutIdx += nonceLength;
+#endif
+
+    /* Ticket length. */
+    if ((*inOutIdx - begin) + LENGTH_SZ > size)
+        return BUFFER_ERROR;
+    ato16(input + *inOutIdx, &length);
+    *inOutIdx += LENGTH_SZ;
+    if ((*inOutIdx - begin) + length > size)
+        return BUFFER_ERROR;
+
+    if ((ret = SetTicket(ssl, input + *inOutIdx, length)) != 0)
+        return ret;
+    *inOutIdx += length;
+
+    now = TimeNowInMilliseconds();
+    if (now == (word32)GETTIME_ERROR)
+        return now;
+    /* Copy in ticket data (server identity). */
+    ssl->timeout                = lifetime;
+    ssl->session.timeout        = lifetime;
+    ssl->session.cipherSuite0   = ssl->options.cipherSuite0;
+    ssl->session.cipherSuite    = ssl->options.cipherSuite;
+    ssl->session.ticketSeen     = now;
+    ssl->session.ticketAdd      = ageAdd;
+    #ifdef WOLFSSL_EARLY_DATA
+    ssl->session.maxEarlyDataSz = ssl->options.maxEarlyDataSz;
+    #endif
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    ssl->session.ticketNonce.len = nonceLength;
+    if (nonceLength > 0)
+        XMEMCPY(&ssl->session.ticketNonce.data, nonce, nonceLength);
+#endif
+    ssl->session.namedGroup     = ssl->namedGroup;
+
+    if ((*inOutIdx - begin) + EXTS_SZ > size)
+        return BUFFER_ERROR;
+    ato16(input + *inOutIdx, &length);
+    *inOutIdx += EXTS_SZ;
+    if ((*inOutIdx - begin) + length != size)
+        return BUFFER_ERROR;
+    #ifdef WOLFSSL_EARLY_DATA
+    ret = TLSX_Parse(ssl, (byte *)input + (*inOutIdx), length, session_ticket,
+                     NULL);
+    if (ret != 0)
+        return ret;
+    #endif
+    *inOutIdx += length;
+
+    #ifndef NO_SESSION_CACHE
+    AddSession(ssl);
+    #endif
+
+    /* Always encrypted. */
+    *inOutIdx += ssl->keys.padSz;
+
+    ssl->expect_session_ticket = 0;
+#else
+    (void)ssl;
+    (void)input;
+
+    WOLFSSL_ENTER("DoTls13NewSessionTicket");
+
+    *inOutIdx += size + ssl->keys.padSz;
+#endif /* HAVE_SESSION_TICKET */
+
+    WOLFSSL_LEAVE("DoTls13NewSessionTicket", 0);
+    WOLFSSL_END(WC_FUNC_NEW_SESSION_TICKET_DO);
+
+    return 0;
+}
+#endif /* NO_WOLFSSL_CLIENT */
+
+#ifndef NO_WOLFSSL_SERVER
+    #ifdef HAVE_SESSION_TICKET
+
+#ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED
+/* Offset of the MAC size in the finished message. */
+#define FINISHED_MSG_SIZE_OFFSET    3
+
+/* Calculate the resumption secret which includes the unseen client finished
+ * message.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 0 on success, otherwise failure.
+ */
+static int ExpectedResumptionSecret(WOLFSSL* ssl)
+{
+    int         ret;
+    word32      finishedSz = 0;
+    byte        mac[WC_MAX_DIGEST_SIZE];
+    Digest      digest;
+    static byte header[] = { 0x14, 0x00, 0x00, 0x00 };
+
+    /* Copy the running hash so we can restore it after. */
+    switch (ssl->specs.mac_algorithm) {
+    #ifndef NO_SHA256
+        case sha256_mac:
+            ret = wc_Sha256Copy(&ssl->hsHashes->hashSha256, &digest.sha256);
+            if (ret != 0)
+                return ret;
+            break;
+    #endif
+    #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            ret = wc_Sha384Copy(&ssl->hsHashes->hashSha384, &digest.sha384);
+            if (ret != 0)
+                return ret;
+            break;
+    #endif
+    #ifdef WOLFSSL_TLS13_SHA512
+        case sha512_mac:
+            ret = wc_Sha512Copy(&ssl->hsHashes->hashSha512, &digest.sha512);
+            if (ret != 0)
+                return ret;
+            break;
+    #endif
+    }
+
+    /* Generate the Client's Finished message and hash it. */
+    ret = BuildTls13HandshakeHmac(ssl, ssl->keys.client_write_MAC_secret, mac,
+                                  &finishedSz);
+    if (ret != 0)
+        return ret;
+    header[FINISHED_MSG_SIZE_OFFSET] = finishedSz;
+#ifdef WOLFSSL_EARLY_DATA
+    if (ssl->earlyData != no_early_data) {
+        static byte endOfEarlyData[] = { 0x05, 0x00, 0x00, 0x00 };
+        ret = HashInputRaw(ssl, endOfEarlyData, sizeof(endOfEarlyData));
+        if (ret != 0)
+            return ret;
+    }
+#endif
+    if ((ret = HashInputRaw(ssl, header, sizeof(header))) != 0)
+        return ret;
+    if ((ret = HashInputRaw(ssl, mac, finishedSz)) != 0)
+        return ret;
+
+    if ((ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret)) != 0)
+        return ret;
+
+    /* Restore the hash inline with currently seen messages. */
+    switch (ssl->specs.mac_algorithm) {
+    #ifndef NO_SHA256
+        case sha256_mac:
+            ret = wc_Sha256Copy(&digest.sha256, &ssl->hsHashes->hashSha256);
+            if (ret != 0)
+                return ret;
+            break;
+    #endif
+    #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            ret = wc_Sha384Copy(&digest.sha384, &ssl->hsHashes->hashSha384);
+            if (ret != 0)
+                return ret;
+            break;
+    #endif
+    #ifdef WOLFSSL_TLS13_SHA512
+        case sha512_mac:
+            ret = wc_Sha512Copy(&digest.sha512, &ssl->hsHashes->hashSha384);
+            if (ret != 0)
+                return ret;
+            break;
+    #endif
+    }
+
+    return ret;
+}
+#endif
+
+/* Send New Session Ticket handshake message.
+ * Message contains the information required to perform resumption.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 0 on success, otherwise failure.
+ */
+static int SendTls13NewSessionTicket(WOLFSSL* ssl)
+{
+    byte*  output;
+    int    ret;
+    int    sendSz;
+    word16 extSz;
+    word32 length;
+    word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+
+    WOLFSSL_START(WC_FUNC_NEW_SESSION_TICKET_SEND);
+    WOLFSSL_ENTER("SendTls13NewSessionTicket");
+
+#ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED
+    if (!ssl->msgsReceived.got_finished) {
+        if ((ret = ExpectedResumptionSecret(ssl)) != 0)
+            return ret;
+    }
+#endif
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    /* Start ticket nonce at 0 and go up to 255. */
+    if (ssl->session.ticketNonce.len == 0) {
+        ssl->session.ticketNonce.len = DEF_TICKET_NONCE_SZ;
+        ssl->session.ticketNonce.data[0] = 0;
+    }
+    else
+        ssl->session.ticketNonce.data[0]++;
+#endif
+
+    if (!ssl->options.noTicketTls13) {
+        if ((ret = CreateTicket(ssl)) != 0)
+            return ret;
+    }
+
+#ifdef WOLFSSL_EARLY_DATA
+    ssl->session.maxEarlyDataSz = ssl->options.maxEarlyDataSz;
+    if (ssl->session.maxEarlyDataSz > 0)
+        TLSX_EarlyData_Use(ssl, ssl->session.maxEarlyDataSz);
+    extSz = 0;
+    ret = TLSX_GetResponseSize(ssl, session_ticket, &extSz);
+    if (ret != 0)
+        return ret;
+#else
+    extSz = EXTS_SZ;
+#endif
+
+    /* Lifetime | Age Add | Ticket | Extensions */
+    length = SESSION_HINT_SZ + SESSION_ADD_SZ + LENGTH_SZ +
+             ssl->session.ticketLen + extSz;
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    /* Nonce */
+    length += TICKET_NONCE_LEN_SZ + DEF_TICKET_NONCE_SZ;
+#endif
+    sendSz = idx + length + MAX_MSG_EXTRA;
+
+    /* Check buffers are big enough and grow if needed. */
+    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+        return ret;
+
+    /* Get position in output buffer to write new message to. */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+
+    /* Put the record and handshake headers on. */
+    AddTls13Headers(output, length, session_ticket, ssl);
+
+    /* Lifetime hint */
+    c32toa(ssl->ctx->ticketHint, output + idx);
+    idx += SESSION_HINT_SZ;
+    /* Age add - obfuscator */
+    c32toa(ssl->session.ticketAdd, output + idx);
+    idx += SESSION_ADD_SZ;
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    output[idx++] = ssl->session.ticketNonce.len;
+    output[idx++] = ssl->session.ticketNonce.data[0];
+#endif
+
+    /* length */
+    c16toa(ssl->session.ticketLen, output + idx);
+    idx += LENGTH_SZ;
+    /* ticket */
+    XMEMCPY(output + idx, ssl->session.ticket, ssl->session.ticketLen);
+    idx += ssl->session.ticketLen;
+
+#ifdef WOLFSSL_EARLY_DATA
+    extSz = 0;
+    ret = TLSX_WriteResponse(ssl, output + idx, session_ticket, &extSz);
+    if (ret != 0)
+        return ret;
+    idx += extSz;
+#else
+    /* No extension support - empty extensions. */
+    c16toa(0, output + idx);
+    idx += EXTS_SZ;
+#endif
+
+    ssl->options.haveSessionId = 1;
+
+#ifndef NO_SESSION_CACHE
+    AddSession(ssl);
+#endif
+
+    /* This message is always encrypted. */
+    sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ,
+                               idx - RECORD_HEADER_SZ, handshake, 0, 0, 0);
+    if (sendSz < 0)
+        return sendSz;
+
+    ssl->buffers.outputBuffer.length += sendSz;
+
+    if (!ssl->options.groupMessages)
+        ret = SendBuffered(ssl);
+
+    WOLFSSL_LEAVE("SendTls13NewSessionTicket", 0);
+    WOLFSSL_END(WC_FUNC_NEW_SESSION_TICKET_SEND);
+
+    return ret;
+}
+    #endif /* HAVE_SESSION_TICKET */
+#endif /* NO_WOLFSSL_SERVER */
+
+/* Make sure no duplicates, no fast forward, or other problems
+ *
+ * ssl   The SSL/TLS object.
+ * type  Type of handshake message received.
+ * returns 0 on success, otherwise failure.
+ */
+static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type)
+{
+    /* verify not a duplicate, mark received, check state */
+    switch (type) {
+
+#ifndef NO_WOLFSSL_SERVER
+        case client_hello:
+        #ifndef NO_WOLFSSL_CLIENT
+            if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                WOLFSSL_MSG("ClientHello received by client");
+                return OUT_OF_ORDER_E;
+            }
+        #endif
+            if (ssl->options.clientState >= CLIENT_HELLO_COMPLETE) {
+                WOLFSSL_MSG("ClientHello received out of order");
+                return OUT_OF_ORDER_E;
+            }
+            if (ssl->msgsReceived.got_client_hello == 2) {
+                WOLFSSL_MSG("Too many ClientHello received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_client_hello++;
+
+            break;
+#endif
+
+#ifndef NO_WOLFSSL_CLIENT
+        case server_hello:
+        #ifndef NO_WOLFSSL_SERVER
+            if (ssl->options.side == WOLFSSL_SERVER_END) {
+                WOLFSSL_MSG("ServerHello received by server");
+                return OUT_OF_ORDER_E;
+            }
+        #endif
+        #ifdef WOLFSSL_TLS13_DRAFT_18
+            if (ssl->msgsReceived.got_server_hello) {
+                WOLFSSL_MSG("Duplicate ServerHello received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_server_hello = 1;
+        #else
+            if (ssl->msgsReceived.got_server_hello == 2) {
+                WOLFSSL_MSG("Duplicate ServerHello received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_server_hello++;
+        #endif
+
+            break;
+#endif
+
+#ifndef NO_WOLFSSL_CLIENT
+        case session_ticket:
+        #ifndef NO_WOLFSSL_SERVER
+            if (ssl->options.side == WOLFSSL_SERVER_END) {
+                WOLFSSL_MSG("NewSessionTicket received by server");
+                return OUT_OF_ORDER_E;
+            }
+        #endif
+            if (ssl->options.clientState < CLIENT_FINISHED_COMPLETE) {
+                WOLFSSL_MSG("NewSessionTicket received out of order");
+                return OUT_OF_ORDER_E;
+            }
+            ssl->msgsReceived.got_session_ticket = 1;
+
+            break;
+#endif
+
+#ifndef NO_WOLFSSL_SERVER
+    #ifdef WOLFSSL_EARLY_DATA
+        case end_of_early_data:
+        #ifndef NO_WOLFSSL_CLIENT
+            if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                WOLFSSL_MSG("EndOfEarlyData received by client");
+                return OUT_OF_ORDER_E;
+            }
+        #endif
+            if (ssl->options.serverState < SERVER_FINISHED_COMPLETE) {
+                WOLFSSL_MSG("EndOfEarlyData received out of order");
+                return OUT_OF_ORDER_E;
+            }
+            if (ssl->options.clientState >= CLIENT_FINISHED_COMPLETE) {
+                WOLFSSL_MSG("EndOfEarlyData received out of order");
+                return OUT_OF_ORDER_E;
+            }
+            if (ssl->msgsReceived.got_end_of_early_data == 1) {
+                WOLFSSL_MSG("Too many EndOfEarlyData received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_end_of_early_data++;
+
+            break;
+    #endif
+#endif
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    #ifndef NO_WOLFSSL_CLIENT
+        case hello_retry_request:
+        #ifndef NO_WOLFSSL_SERVER
+            if (ssl->options.side == WOLFSSL_SERVER_END) {
+                WOLFSSL_MSG("HelloRetryRequest received by server");
+                return OUT_OF_ORDER_E;
+            }
+        #endif
+            if (ssl->options.clientState > CLIENT_FINISHED_COMPLETE) {
+                WOLFSSL_MSG("HelloRetryRequest received out of order");
+                return OUT_OF_ORDER_E;
+            }
+            if (ssl->msgsReceived.got_hello_retry_request) {
+                WOLFSSL_MSG("Duplicate HelloRetryRequest received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_hello_retry_request = 1;
+
+            break;
+    #endif
+#endif
+
+#ifndef NO_WOLFSSL_CLIENT
+        case encrypted_extensions:
+        #ifndef NO_WOLFSSL_SERVER
+            if (ssl->options.side == WOLFSSL_SERVER_END) {
+                WOLFSSL_MSG("EncryptedExtensions received by server");
+                return OUT_OF_ORDER_E;
+            }
+        #endif
+            if (ssl->options.serverState != SERVER_HELLO_COMPLETE) {
+                WOLFSSL_MSG("EncryptedExtensions received out of order");
+                return OUT_OF_ORDER_E;
+            }
+            if (ssl->msgsReceived.got_encrypted_extensions) {
+                WOLFSSL_MSG("Duplicate EncryptedExtensions received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_encrypted_extensions = 1;
+
+            break;
+#endif
+
+        case certificate:
+    #ifndef NO_WOLFSSL_CLIENT
+            if (ssl->options.side == WOLFSSL_CLIENT_END &&
+                ssl->options.serverState !=
+                                         SERVER_ENCRYPTED_EXTENSIONS_COMPLETE) {
+                WOLFSSL_MSG("Certificate received out of order - Client");
+                return OUT_OF_ORDER_E;
+            }
+        #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+            /* Server's authenticating with PSK must not send this. */
+            if (ssl->options.side == WOLFSSL_CLIENT_END &&
+                             ssl->options.serverState == SERVER_CERT_COMPLETE &&
+                             ssl->arrays->psk_keySz != 0) {
+                WOLFSSL_MSG("Certificate received while using PSK");
+                return SANITY_MSG_E;
+            }
+        #endif
+    #endif
+    #ifndef NO_WOLFSSL_SERVER
+            if (ssl->options.side == WOLFSSL_SERVER_END &&
+                ssl->options.serverState < SERVER_FINISHED_COMPLETE) {
+                WOLFSSL_MSG("Certificate received out of order - Server");
+                return OUT_OF_ORDER_E;
+            }
+    #endif
+            if (ssl->msgsReceived.got_certificate) {
+                WOLFSSL_MSG("Duplicate Certificate received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_certificate = 1;
+
+            break;
+
+#ifndef NO_WOLFSSL_CLIENT
+        case certificate_request:
+        #ifndef NO_WOLFSSL_SERVER
+            if (ssl->options.side == WOLFSSL_SERVER_END) {
+                WOLFSSL_MSG("CertificateRequest received by server");
+                return OUT_OF_ORDER_E;
+            }
+        #endif
+        #ifndef WOLFSSL_POST_HANDSHAKE_AUTH
+            if (ssl->options.serverState !=
+                                         SERVER_ENCRYPTED_EXTENSIONS_COMPLETE) {
+                WOLFSSL_MSG("CertificateRequest received out of order");
+                return OUT_OF_ORDER_E;
+            }
+        #else
+            if (ssl->options.serverState !=
+                                         SERVER_ENCRYPTED_EXTENSIONS_COMPLETE &&
+                       (ssl->options.serverState != SERVER_FINISHED_COMPLETE ||
+                        ssl->options.clientState != CLIENT_FINISHED_COMPLETE)) {
+                WOLFSSL_MSG("CertificateRequest received out of order");
+                return OUT_OF_ORDER_E;
+            }
+        #endif
+        #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+            /* Server's authenticating with PSK must not send this. */
+            if (ssl->options.serverState ==
+                                         SERVER_ENCRYPTED_EXTENSIONS_COMPLETE &&
+                                                  ssl->arrays->psk_keySz != 0) {
+                WOLFSSL_MSG("CertificateRequset received while using PSK");
+                return SANITY_MSG_E;
+            }
+        #endif
+        #ifndef WOLFSSL_POST_HANDSHAKE_AUTH
+            if (ssl->msgsReceived.got_certificate_request) {
+                WOLFSSL_MSG("Duplicate CertificateRequest received");
+                return DUPLICATE_MSG_E;
+            }
+        #endif
+            ssl->msgsReceived.got_certificate_request = 1;
+
+            break;
+#endif
+
+        case certificate_verify:
+    #ifndef NO_WOLFSSL_CLIENT
+            if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                if (ssl->options.serverState != SERVER_CERT_COMPLETE) {
+                    WOLFSSL_MSG("No Cert before CertVerify");
+                    return OUT_OF_ORDER_E;
+                }
+            #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+                /* Server's authenticating with PSK must not send this. */
+                if (ssl->options.serverState == SERVER_CERT_COMPLETE &&
+                                                  ssl->arrays->psk_keySz != 0) {
+                    WOLFSSL_MSG("CertificateVerify received while using PSK");
+                    return SANITY_MSG_E;
+                }
+            #endif
+            }
+    #endif
+    #ifndef NO_WOLFSSL_SERVER
+            if (ssl->options.side == WOLFSSL_SERVER_END) {
+                if (ssl->options.serverState < SERVER_FINISHED_COMPLETE) {
+                    WOLFSSL_MSG("CertificateVerify received out of order");
+                    return OUT_OF_ORDER_E;
+                }
+                if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) {
+                    WOLFSSL_MSG("CertificateVerify before ClientHello done");
+                    return OUT_OF_ORDER_E;
+                }
+                if (!ssl->msgsReceived.got_certificate) {
+                    WOLFSSL_MSG("No Cert before CertificateVerify");
+                    return OUT_OF_ORDER_E;
+                }
+            }
+    #endif
+            if (ssl->msgsReceived.got_certificate_verify) {
+                WOLFSSL_MSG("Duplicate CertificateVerify received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_certificate_verify = 1;
+
+            break;
+
+        case finished:
+        #ifndef NO_WOLFSSL_CLIENT
+            if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) {
+                    WOLFSSL_MSG("Finished received out of order");
+                    return OUT_OF_ORDER_E;
+                }
+                if (ssl->options.serverState <
+                                         SERVER_ENCRYPTED_EXTENSIONS_COMPLETE) {
+                    WOLFSSL_MSG("Finished received out of order");
+                    return OUT_OF_ORDER_E;
+                }
+            }
+        #endif
+        #ifndef NO_WOLFSSL_SERVER
+            if (ssl->options.side == WOLFSSL_SERVER_END) {
+                if (ssl->options.serverState < SERVER_FINISHED_COMPLETE) {
+                    WOLFSSL_MSG("Finished received out of order");
+                    return OUT_OF_ORDER_E;
+                }
+                if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) {
+                    WOLFSSL_MSG("Finished received out of order");
+                    return OUT_OF_ORDER_E;
+                }
+            #ifdef WOLFSSL_EARLY_DATA
+                if (ssl->earlyData == process_early_data) {
+                    return OUT_OF_ORDER_E;
+                }
+            #endif
+            }
+        #endif
+            if (ssl->msgsReceived.got_finished) {
+                WOLFSSL_MSG("Duplicate Finished received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_finished = 1;
+
+            break;
+
+        case key_update:
+            if (!ssl->msgsReceived.got_finished) {
+                WOLFSSL_MSG("No KeyUpdate before Finished");
+                return OUT_OF_ORDER_E;
+            }
+            break;
+
+        default:
+            WOLFSSL_MSG("Unknown message type");
+            return SANITY_MSG_E;
+    }
+
+    return 0;
+}
+
+/* Handle a type of handshake message that has been received.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The message buffer.
+ * inOutIdx  On entry, the index into the buffer of the current message.
+ *           On exit, the index into the buffer of the next message.
+ * size      The length of the current handshake message.
+ * totalSz   Length of remaining data in the message buffer.
+ * returns 0 on success and otherwise failure.
+ */
+int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+                            byte type, word32 size, word32 totalSz)
+{
+    int ret = 0;
+    word32 inIdx = *inOutIdx;
+
+    (void)totalSz;
+
+    WOLFSSL_ENTER("DoTls13HandShakeMsgType");
+
+    /* make sure we can read the message */
+    if (*inOutIdx + size > totalSz)
+        return INCOMPLETE_DATA;
+
+    /* sanity check msg received */
+    if ((ret = SanityCheckTls13MsgReceived(ssl, type)) != 0) {
+        WOLFSSL_MSG("Sanity Check on handshake message type received failed");
+        SendAlert(ssl, alert_fatal, unexpected_message);
+        return ret;
+    }
+
+#ifdef WOLFSSL_CALLBACKS
+    /* add name later, add on record and handshake header part back on */
+    if (ssl->toInfoOn) {
+        int add = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+        AddPacketInfo(ssl, 0, handshake, input + *inOutIdx - add,
+                      size + add, READ_PROTO, ssl->heap);
+        AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo);
+    }
+#endif
+
+    if (ssl->options.handShakeState == HANDSHAKE_DONE &&
+            type != session_ticket && type != certificate_request &&
+            type != certificate && type != key_update) {
+        WOLFSSL_MSG("HandShake message after handshake complete");
+        SendAlert(ssl, alert_fatal, unexpected_message);
+        return OUT_OF_ORDER_E;
+    }
+
+    if (ssl->options.side == WOLFSSL_CLIENT_END &&
+               ssl->options.serverState == NULL_STATE &&
+               type != server_hello && type != hello_retry_request) {
+        WOLFSSL_MSG("First server message not server hello");
+        SendAlert(ssl, alert_fatal, unexpected_message);
+        return OUT_OF_ORDER_E;
+    }
+
+    if (ssl->options.side == WOLFSSL_SERVER_END &&
+               ssl->options.clientState == NULL_STATE && type != client_hello) {
+        WOLFSSL_MSG("First client message not client hello");
+        SendAlert(ssl, alert_fatal, unexpected_message);
+        return OUT_OF_ORDER_E;
+    }
+
+    /* above checks handshake state */
+    switch (type) {
+#ifndef NO_WOLFSSL_CLIENT
+    /* Messages only received by client. */
+    #ifdef WOLFSSL_TLS13_DRAFT_18
+    case hello_retry_request:
+        WOLFSSL_MSG("processing hello retry request");
+        ret = DoTls13HelloRetryRequest(ssl, input, inOutIdx, size);
+        break;
+    #endif
+
+    case server_hello:
+        WOLFSSL_MSG("processing server hello");
+        ret = DoTls13ServerHello(ssl, input, inOutIdx, size, &type);
+    #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
+               ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \
+                (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)))
+        if (ssl->options.resuming || !IsAtLeastTLSv1_2(ssl) ||
+                                               IsAtLeastTLSv1_3(ssl->version)) {
+            ssl->options.cacheMessages = 0;
+            if (ssl->hsHashes->messages != NULL) {
+                XFREE(ssl->hsHashes->messages, ssl->heap, DYNAMIC_TYPE_HASHES);
+                ssl->hsHashes->messages = NULL;
+            }
+        }
+    #endif
+        break;
+
+    case encrypted_extensions:
+        WOLFSSL_MSG("processing encrypted extensions");
+        ret = DoTls13EncryptedExtensions(ssl, input, inOutIdx, size);
+        break;
+
+    #ifndef NO_CERTS
+    case certificate_request:
+        WOLFSSL_MSG("processing certificate request");
+        ret = DoTls13CertificateRequest(ssl, input, inOutIdx, size);
+        break;
+    #endif
+
+    case session_ticket:
+        WOLFSSL_MSG("processing new session ticket");
+        ret = DoTls13NewSessionTicket(ssl, input, inOutIdx, size);
+        break;
+#endif /* !NO_WOLFSSL_CLIENT */
+
+#ifndef NO_WOLFSSL_SERVER
+    /* Messages only received by server. */
+    case client_hello:
+        WOLFSSL_MSG("processing client hello");
+        ret = DoTls13ClientHello(ssl, input, inOutIdx, size);
+        break;
+
+    #ifdef WOLFSSL_EARLY_DATA
+    case end_of_early_data:
+        WOLFSSL_MSG("processing end of early data");
+        ret = DoTls13EndOfEarlyData(ssl, input, inOutIdx, size);
+        break;
+    #endif
+#endif /* !NO_WOLFSSL_SERVER */
+
+    /* Messages received by both client and server. */
+#ifndef NO_CERTS
+    case certificate:
+        WOLFSSL_MSG("processing certificate");
+        ret = DoTls13Certificate(ssl, input, inOutIdx, size);
+        break;
+#endif
+
+#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+                                                             defined(HAVE_ED448)
+    case certificate_verify:
+        WOLFSSL_MSG("processing certificate verify");
+        ret = DoTls13CertificateVerify(ssl, input, inOutIdx, size);
+        break;
+#endif /* !NO_RSA || HAVE_ECC */
+
+    case finished:
+        WOLFSSL_MSG("processing finished");
+        ret = DoTls13Finished(ssl, input, inOutIdx, size, totalSz, NO_SNIFF);
+        break;
+
+    case key_update:
+        WOLFSSL_MSG("processing finished");
+        ret = DoTls13KeyUpdate(ssl, input, inOutIdx, size);
+        break;
+
+    default:
+        WOLFSSL_MSG("Unknown handshake message type");
+        ret = UNKNOWN_HANDSHAKE_TYPE;
+        break;
+    }
+
+    /* reset error */
+    if (ret == 0 && ssl->error == WC_PENDING_E)
+        ssl->error = 0;
+
+    if (ret == 0 && type != client_hello && type != session_ticket &&
+                                                           type != key_update) {
+        ret = HashInput(ssl, input + inIdx, size);
+    }
+    if (ret == 0 && ssl->buffers.inputBuffer.dynamicFlag) {
+        ShrinkInputBuffer(ssl, NO_FORCED_FREE);
+    }
+
+    if (ret == BUFFER_ERROR || ret == MISSING_HANDSHAKE_DATA)
+        SendAlert(ssl, alert_fatal, decode_error);
+    else if (ret == EXT_NOT_ALLOWED || ret == PEER_KEY_ERROR ||
+                        ret == ECC_PEERKEY_ERROR || ret == BAD_KEY_SHARE_DATA ||
+                        ret == PSK_KEY_ERROR || ret == INVALID_PARAMETER) {
+        SendAlert(ssl, alert_fatal, illegal_parameter);
+    }
+
+    if (ret == 0 && ssl->options.tls1_3) {
+        /* Need to hash input message before deriving secrets. */
+    #ifndef NO_WOLFSSL_CLIENT
+        if (ssl->options.side == WOLFSSL_CLIENT_END) {
+            if (type == server_hello) {
+                if ((ret = DeriveEarlySecret(ssl)) != 0)
+                    return ret;
+                if ((ret = DeriveHandshakeSecret(ssl)) != 0)
+                    return ret;
+
+                if ((ret = DeriveTls13Keys(ssl, handshake_key,
+                                           ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0) {
+                    return ret;
+                }
+        #ifdef WOLFSSL_EARLY_DATA
+                if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
+                    return ret;
+        #else
+                if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) != 0)
+                    return ret;
+        #endif
+            }
+
+            if (type == finished) {
+                if ((ret = DeriveMasterSecret(ssl)) != 0)
+                    return ret;
+        #ifdef WOLFSSL_EARLY_DATA
+                if ((ret = DeriveTls13Keys(ssl, traffic_key,
+                                       ENCRYPT_AND_DECRYPT_SIDE,
+                                       ssl->earlyData == no_early_data)) != 0) {
+                    return ret;
+                }
+        #else
+                if ((ret = DeriveTls13Keys(ssl, traffic_key,
+                                           ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0) {
+                    return ret;
+                }
+        #endif
+            }
+        #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
+            if (type == certificate_request &&
+                                ssl->options.handShakeState == HANDSHAKE_DONE) {
+                /* reset handshake states */
+                ssl->options.clientState = CLIENT_HELLO_COMPLETE;
+                ssl->options.connectState  = FIRST_REPLY_DONE;
+                ssl->options.handShakeState = CLIENT_HELLO_COMPLETE;
+
+                if (wolfSSL_connect_TLSv13(ssl) != SSL_SUCCESS)
+                    ret = POST_HAND_AUTH_ERROR;
+            }
+        #endif
+        }
+    #endif /* NO_WOLFSSL_CLIENT */
+
+#ifndef NO_WOLFSSL_SERVER
+    #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+        if (ssl->options.side == WOLFSSL_SERVER_END && type == finished) {
+            ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret);
+            if (ret != 0)
+                return ret;
+        }
+    #endif
+#endif /* NO_WOLFSSL_SERVER */
+    }
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* if async, offset index so this msg will be processed again */
+    if (ret == WC_PENDING_E && *inOutIdx > 0) {
+        *inOutIdx -= HANDSHAKE_HEADER_SZ;
+    }
+#endif
+
+    WOLFSSL_LEAVE("DoTls13HandShakeMsgType()", ret);
+    return ret;
+}
+
+
+/* Handle a handshake message that has been received.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The message buffer.
+ * inOutIdx  On entry, the index into the buffer of the current message.
+ *           On exit, the index into the buffer of the next message.
+ * totalSz   Length of remaining data in the message buffer.
+ * returns 0 on success and otherwise failure.
+ */
+int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+                        word32 totalSz)
+{
+    int    ret = 0;
+    word32 inputLength;
+
+    WOLFSSL_ENTER("DoTls13HandShakeMsg()");
+
+    if (ssl->arrays == NULL) {
+        byte   type;
+        word32 size;
+
+        if (GetHandshakeHeader(ssl, input, inOutIdx, &type, &size,
+                                                                totalSz) != 0) {
+            SendAlert(ssl, alert_fatal, unexpected_message);
+            return PARSE_ERROR;
+        }
+
+        return DoTls13HandShakeMsgType(ssl, input, inOutIdx, type, size,
+                                       totalSz);
+    }
+
+    inputLength = ssl->buffers.inputBuffer.length - *inOutIdx - ssl->keys.padSz;
+
+    /* If there is a pending fragmented handshake message,
+     * pending message size will be non-zero. */
+    if (ssl->arrays->pendingMsgSz == 0) {
+        byte   type;
+        word32 size;
+
+        if (GetHandshakeHeader(ssl,input, inOutIdx, &type, &size, totalSz) != 0)
+            return PARSE_ERROR;
+
+        /* Cap the maximum size of a handshake message to something reasonable.
+         * By default is the maximum size of a certificate message assuming
+         * nine 2048-bit RSA certificates in the chain. */
+        if (size > MAX_HANDSHAKE_SZ) {
+            WOLFSSL_MSG("Handshake message too large");
+            return HANDSHAKE_SIZE_ERROR;
+        }
+
+        /* size is the size of the certificate message payload */
+        if (inputLength - HANDSHAKE_HEADER_SZ < size) {
+            ssl->arrays->pendingMsgType = type;
+            ssl->arrays->pendingMsgSz = size + HANDSHAKE_HEADER_SZ;
+            ssl->arrays->pendingMsg = (byte*)XMALLOC(size + HANDSHAKE_HEADER_SZ,
+                                                     ssl->heap,
+                                                     DYNAMIC_TYPE_ARRAYS);
+            if (ssl->arrays->pendingMsg == NULL)
+                return MEMORY_E;
+            XMEMCPY(ssl->arrays->pendingMsg,
+                    input + *inOutIdx - HANDSHAKE_HEADER_SZ,
+                    inputLength);
+            ssl->arrays->pendingMsgOffset = inputLength;
+            *inOutIdx += inputLength + ssl->keys.padSz - HANDSHAKE_HEADER_SZ;
+            return 0;
+        }
+
+        ret = DoTls13HandShakeMsgType(ssl, input, inOutIdx, type, size,
+                                      totalSz);
+    }
+    else {
+        if (inputLength + ssl->arrays->pendingMsgOffset >
+                                                    ssl->arrays->pendingMsgSz) {
+            inputLength = ssl->arrays->pendingMsgSz -
+                                                  ssl->arrays->pendingMsgOffset;
+        }
+        XMEMCPY(ssl->arrays->pendingMsg + ssl->arrays->pendingMsgOffset,
+                input + *inOutIdx, inputLength);
+        ssl->arrays->pendingMsgOffset += inputLength;
+        *inOutIdx += inputLength + ssl->keys.padSz;
+
+        if (ssl->arrays->pendingMsgOffset == ssl->arrays->pendingMsgSz)
+        {
+            word32 idx = 0;
+            ret = DoTls13HandShakeMsgType(ssl,
+                                ssl->arrays->pendingMsg + HANDSHAKE_HEADER_SZ,
+                                &idx, ssl->arrays->pendingMsgType,
+                                ssl->arrays->pendingMsgSz - HANDSHAKE_HEADER_SZ,
+                                ssl->arrays->pendingMsgSz);
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (ret == WC_PENDING_E) {
+                /* setup to process fragment again */
+                ssl->arrays->pendingMsgOffset -= inputLength;
+                *inOutIdx -= inputLength + ssl->keys.padSz;
+            }
+            else
+        #endif
+            {
+                XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS);
+                ssl->arrays->pendingMsg = NULL;
+                ssl->arrays->pendingMsgSz = 0;
+            }
+        }
+    }
+
+    WOLFSSL_LEAVE("DoTls13HandShakeMsg()", ret);
+    return ret;
+}
+
+#ifndef NO_WOLFSSL_CLIENT
+
+/* The client connecting to the server.
+ * The protocol version is expecting to be TLS v1.3.
+ * If the server downgrades, and older versions of the protocol are compiled
+ * in, the client will fallback to wolfSSL_connect().
+ * Please see note at top of README if you get an error from connect.
+ *
+ * ssl  The SSL/TLS object.
+ * returns WOLFSSL_SUCCESS on successful handshake, WOLFSSL_FATAL_ERROR when
+ * unrecoverable error occurs and 0 otherwise.
+ * For more error information use wolfSSL_get_error().
+ */
+int wolfSSL_connect_TLSv13(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_connect_TLSv13()");
+
+    #ifdef HAVE_ERRNO_H
+    errno = 0;
+    #endif
+
+    if (ssl->options.side != WOLFSSL_CLIENT_END) {
+        WOLFSSL_ERROR(ssl->error = SIDE_ERROR);
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (ssl->buffers.outputBuffer.length > 0
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        /* do not send buffered or advance state if last error was an 
+            async pending operation */
+        && ssl->error != WC_PENDING_E
+    #endif
+    ) {
+        if ((ssl->error = SendBuffered(ssl)) == 0) {
+            /* fragOffset is non-zero when sending fragments. On the last
+             * fragment, fragOffset is zero again, and the state can be
+             * advanced. */
+            if (ssl->fragOffset == 0) {
+                ssl->options.connectState++;
+                WOLFSSL_MSG("connect state: "
+                            "Advanced from last buffered fragment send");
+            }
+            else {
+                WOLFSSL_MSG("connect state: "
+                            "Not advanced, more fragments to send");
+            }
+        }
+        else {
+            WOLFSSL_ERROR(ssl->error);
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+
+    switch (ssl->options.connectState) {
+
+        case CONNECT_BEGIN:
+            /* Always send client hello first. */
+            if ((ssl->error = SendTls13ClientHello(ssl)) != 0) {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+
+            ssl->options.connectState = CLIENT_HELLO_SENT;
+            WOLFSSL_MSG("connect state: CLIENT_HELLO_SENT");
+    #ifdef WOLFSSL_EARLY_DATA
+            if (ssl->earlyData != no_early_data) {
+        #if !defined(WOLFSSL_TLS13_DRAFT_18) && \
+                                         defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
+                if ((ssl->error = SendChangeCipher(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+                ssl->options.sentChangeCipher = 1;
+        #endif
+                ssl->options.handShakeState = CLIENT_HELLO_COMPLETE;
+                return WOLFSSL_SUCCESS;
+            }
+    #endif
+            FALL_THROUGH;
+
+        case CLIENT_HELLO_SENT:
+            /* Get the response/s from the server. */
+            while (ssl->options.serverState <
+                                          SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
+                if ((ssl->error = ProcessReply(ssl)) < 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+
+            ssl->options.connectState = HELLO_AGAIN;
+            WOLFSSL_MSG("connect state: HELLO_AGAIN");
+            FALL_THROUGH;
+
+        case HELLO_AGAIN:
+            if (ssl->options.certOnly)
+                return WOLFSSL_SUCCESS;
+
+            if (!ssl->options.tls1_3) {
+    #ifndef WOLFSSL_NO_TLS12
+                if (ssl->options.downgrade)
+                    return wolfSSL_connect(ssl);
+    #endif
+
+                WOLFSSL_MSG("Client using higher version, fatal error");
+                return VERSION_ERROR;
+            }
+
+            if (ssl->options.serverState ==
+                                          SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
+        #if !defined(WOLFSSL_TLS13_DRAFT_18) && \
+                                         defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
+                if (!ssl->options.sentChangeCipher) {
+                    if ((ssl->error = SendChangeCipher(ssl)) != 0) {
+                        WOLFSSL_ERROR(ssl->error);
+                        return WOLFSSL_FATAL_ERROR;
+                    }
+                    ssl->options.sentChangeCipher = 1;
+                }
+        #endif
+                /* Try again with different security parameters. */
+                if ((ssl->error = SendTls13ClientHello(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+
+            ssl->options.connectState = HELLO_AGAIN_REPLY;
+            WOLFSSL_MSG("connect state: HELLO_AGAIN_REPLY");
+            FALL_THROUGH;
+
+        case HELLO_AGAIN_REPLY:
+            /* Get the response/s from the server. */
+            while (ssl->options.serverState < SERVER_FINISHED_COMPLETE) {
+                if ((ssl->error = ProcessReply(ssl)) < 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+
+            ssl->options.connectState = FIRST_REPLY_DONE;
+            WOLFSSL_MSG("connect state: FIRST_REPLY_DONE");
+            FALL_THROUGH;
+
+        case FIRST_REPLY_DONE:
+        #ifdef WOLFSSL_EARLY_DATA
+            if (ssl->earlyData != no_early_data) {
+                if ((ssl->error = SendTls13EndOfEarlyData(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+                WOLFSSL_MSG("sent: end_of_early_data");
+            }
+        #endif
+
+            ssl->options.connectState = FIRST_REPLY_FIRST;
+            WOLFSSL_MSG("connect state: FIRST_REPLY_FIRST");
+            FALL_THROUGH;
+
+        case FIRST_REPLY_FIRST:
+        #if !defined(WOLFSSL_TLS13_DRAFT_18) && \
+                                         defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
+            if (!ssl->options.sentChangeCipher) {
+                if ((ssl->error = SendChangeCipher(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+                ssl->options.sentChangeCipher = 1;
+            }
+        #endif
+
+            ssl->options.connectState = FIRST_REPLY_SECOND;
+            WOLFSSL_MSG("connect state: FIRST_REPLY_SECOND");
+            FALL_THROUGH;
+
+        case FIRST_REPLY_SECOND:
+        #ifndef NO_CERTS
+            if (!ssl->options.resuming && ssl->options.sendVerify) {
+                ssl->error = SendTls13Certificate(ssl);
+                if (ssl->error != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+                WOLFSSL_MSG("sent: certificate");
+            }
+        #endif
+
+            ssl->options.connectState = FIRST_REPLY_THIRD;
+            WOLFSSL_MSG("connect state: FIRST_REPLY_THIRD");
+            FALL_THROUGH;
+
+        case FIRST_REPLY_THIRD:
+        #ifndef NO_CERTS
+            if (!ssl->options.resuming && ssl->options.sendVerify) {
+                ssl->error = SendTls13CertificateVerify(ssl);
+                if (ssl->error != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+                WOLFSSL_MSG("sent: certificate verify");
+            }
+        #endif
+
+            ssl->options.connectState = FIRST_REPLY_FOURTH;
+            WOLFSSL_MSG("connect state: FIRST_REPLY_FOURTH");
+            FALL_THROUGH;
+
+        case FIRST_REPLY_FOURTH:
+            if ((ssl->error = SendTls13Finished(ssl)) != 0) {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+            WOLFSSL_MSG("sent: finished");
+
+            ssl->options.connectState = FINISHED_DONE;
+            WOLFSSL_MSG("connect state: FINISHED_DONE");
+            FALL_THROUGH;
+
+        case FINISHED_DONE:
+        #ifndef NO_HANDSHAKE_DONE_CB
+            if (ssl->hsDoneCb != NULL) {
+                int cbret = ssl->hsDoneCb(ssl, ssl->hsDoneCtx);
+                if (cbret < 0) {
+                    ssl->error = cbret;
+                    WOLFSSL_MSG("HandShake Done Cb don't continue error");
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+        #endif /* NO_HANDSHAKE_DONE_CB */
+
+            if (!ssl->options.keepResources) {
+                FreeHandshakeResources(ssl);
+            }
+
+            WOLFSSL_LEAVE("wolfSSL_connect_TLSv13()", WOLFSSL_SUCCESS);
+            return WOLFSSL_SUCCESS;
+
+        default:
+            WOLFSSL_MSG("Unknown connect state ERROR");
+            return WOLFSSL_FATAL_ERROR; /* unknown connect state */
+    }
+}
+#endif
+
+#if defined(WOLFSSL_SEND_HRR_COOKIE)
+/* Send a cookie with the HelloRetryRequest to avoid storing state.
+ *
+ * ssl       SSL/TLS object.
+ * secret    Secret to use when generating integrity check for cookie.
+ *           A value of NULL indicates to generate a new random secret.
+ * secretSz  Size of secret data in bytes.
+ *           Use a value of 0 to indicate use of default size.
+ * returns BAD_FUNC_ARG when ssl is NULL or not using TLS v1.3, SIDE_ERROR when
+ * called on a client; WOLFSSL_SUCCESS on success and otherwise failure.
+ */
+int wolfSSL_send_hrr_cookie(WOLFSSL* ssl, const unsigned char* secret,
+                            unsigned int secretSz)
+{
+    int ret;
+
+    if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
+        return BAD_FUNC_ARG;
+ #ifndef NO_WOLFSSL_SERVER
+    if (ssl->options.side == WOLFSSL_CLIENT_END)
+        return SIDE_ERROR;
+
+    if (secretSz == 0) {
+    #if !defined(NO_SHA) && defined(NO_SHA256)
+        secretSz = WC_SHA_DIGEST_SIZE;
+    #endif /* NO_SHA */
+    #ifndef NO_SHA256
+        secretSz = WC_SHA256_DIGEST_SIZE;
+    #endif /* NO_SHA256 */
+    }
+
+    if (secretSz != ssl->buffers.tls13CookieSecret.length) {
+        byte* newSecret;
+
+        if (ssl->buffers.tls13CookieSecret.buffer != NULL) {
+            ForceZero(ssl->buffers.tls13CookieSecret.buffer,
+                      ssl->buffers.tls13CookieSecret.length);
+            XFREE(ssl->buffers.tls13CookieSecret.buffer,
+                  ssl->heap, DYNAMIC_TYPE_COOKIE_PWD);
+        }
+
+        newSecret = (byte*)XMALLOC(secretSz, ssl->heap,
+                                   DYNAMIC_TYPE_COOKIE_PWD);
+        if (newSecret == NULL) {
+            ssl->buffers.tls13CookieSecret.buffer = NULL;
+            ssl->buffers.tls13CookieSecret.length = 0;
+            WOLFSSL_MSG("couldn't allocate new cookie secret");
+            return MEMORY_ERROR;
+        }
+        ssl->buffers.tls13CookieSecret.buffer = newSecret;
+        ssl->buffers.tls13CookieSecret.length = secretSz;
+    }
+
+    /* If the supplied secret is NULL, randomly generate a new secret. */
+    if (secret == NULL) {
+        ret = wc_RNG_GenerateBlock(ssl->rng,
+                               ssl->buffers.tls13CookieSecret.buffer, secretSz);
+        if (ret < 0)
+            return ret;
+    }
+    else
+        XMEMCPY(ssl->buffers.tls13CookieSecret.buffer, secret, secretSz);
+
+    ssl->options.sendCookie = 1;
+
+    ret = WOLFSSL_SUCCESS;
+#else
+    (void)secret;
+    (void)secretSz;
+
+    ret = SIDE_ERROR;
+#endif
+
+    return ret;
+}
+#endif
+
+/* Create a key share entry from group.
+ * Generates a key pair.
+ *
+ * ssl    The SSL/TLS object.
+ * group  The named group.
+ * returns 0 on success, otherwise failure.
+ */
+int wolfSSL_UseKeyShare(WOLFSSL* ssl, word16 group)
+{
+    int ret;
+
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL);
+    if (ret != 0)
+        return ret;
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* Send no key share entries - use HelloRetryRequest to negotiate shared group.
+ *
+ * ssl    The SSL/TLS object.
+ * returns 0 on success, otherwise failure.
+ */
+int wolfSSL_NoKeyShares(WOLFSSL* ssl)
+{
+    int ret;
+
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+    if (ssl->options.side == WOLFSSL_SERVER_END)
+        return SIDE_ERROR;
+
+    ret = TLSX_KeyShare_Empty(ssl);
+    if (ret != 0)
+        return ret;
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* Do not send a ticket after TLS v1.3 handshake for resumption.
+ *
+ * ctx  The SSL/TLS CTX object.
+ * returns BAD_FUNC_ARG when ctx is NULL and 0 on success.
+ */
+int wolfSSL_CTX_no_ticket_TLSv13(WOLFSSL_CTX* ctx)
+{
+    if (ctx == NULL || !IsAtLeastTLSv1_3(ctx->method->version))
+        return BAD_FUNC_ARG;
+    if (ctx->method->side == WOLFSSL_CLIENT_END)
+        return SIDE_ERROR;
+
+#ifdef HAVE_SESSION_TICKET
+    ctx->noTicketTls13 = 1;
+#endif
+
+    return 0;
+}
+
+/* Do not send a ticket after TLS v1.3 handshake for resumption.
+ *
+ * ssl  The SSL/TLS object.
+ * returns BAD_FUNC_ARG when ssl is NULL, not using TLS v1.3, or called on
+ * a client and 0 on success.
+ */
+int wolfSSL_no_ticket_TLSv13(WOLFSSL* ssl)
+{
+    if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
+        return BAD_FUNC_ARG;
+    if (ssl->options.side == WOLFSSL_CLIENT_END)
+        return SIDE_ERROR;
+
+#ifdef HAVE_SESSION_TICKET
+    ssl->options.noTicketTls13 = 1;
+#endif
+
+    return 0;
+}
+
+/* Disallow (EC)DHE key exchange when using pre-shared keys.
+ *
+ * ctx  The SSL/TLS CTX object.
+ * returns BAD_FUNC_ARG when ctx is NULL and 0 on success.
+ */
+int wolfSSL_CTX_no_dhe_psk(WOLFSSL_CTX* ctx)
+{
+    if (ctx == NULL || !IsAtLeastTLSv1_3(ctx->method->version))
+        return BAD_FUNC_ARG;
+
+    ctx->noPskDheKe = 1;
+
+    return 0;
+}
+
+/* Disallow (EC)DHE key exchange when using pre-shared keys.
+ *
+ * ssl  The SSL/TLS object.
+ * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3 and 0 on
+ * success.
+ */
+int wolfSSL_no_dhe_psk(WOLFSSL* ssl)
+{
+    if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
+        return BAD_FUNC_ARG;
+
+    ssl->options.noPskDheKe = 1;
+
+    return 0;
+}
+
+/* Update the keys for encryption and decryption.
+ * If using non-blocking I/O and WOLFSSL_ERROR_WANT_WRITE is returned then
+ * calling wolfSSL_write() will have the message sent when ready.
+ *
+ * ssl  The SSL/TLS object.
+ * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3,
+ * WOLFSSL_ERROR_WANT_WRITE when non-blocking I/O is not ready to write,
+ * WOLFSSL_SUCCESS on success and otherwise failure.
+ */
+int wolfSSL_update_keys(WOLFSSL* ssl)
+{
+    int ret;
+
+    if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
+        return BAD_FUNC_ARG;
+
+    ret = SendTls13KeyUpdate(ssl);
+    if (ret == WANT_WRITE)
+        ret = WOLFSSL_ERROR_WANT_WRITE;
+    else if (ret == 0)
+        ret = WOLFSSL_SUCCESS;
+    return ret;
+}
+
+#if !defined(NO_CERTS) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+/* Allow post-handshake authentication in TLS v1.3 connections.
+ *
+ * ctx  The SSL/TLS CTX object.
+ * returns BAD_FUNC_ARG when ctx is NULL, SIDE_ERROR when not a client and
+ * 0 on success.
+ */
+int wolfSSL_CTX_allow_post_handshake_auth(WOLFSSL_CTX* ctx)
+{
+    if (ctx == NULL || !IsAtLeastTLSv1_3(ctx->method->version))
+        return BAD_FUNC_ARG;
+    if (ctx->method->side == WOLFSSL_SERVER_END)
+        return SIDE_ERROR;
+
+    ctx->postHandshakeAuth = 1;
+
+    return 0;
+}
+
+/* Allow post-handshake authentication in TLS v1.3 connection.
+ *
+ * ssl  The SSL/TLS object.
+ * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3,
+ * SIDE_ERROR when not a client and 0 on success.
+ */
+int wolfSSL_allow_post_handshake_auth(WOLFSSL* ssl)
+{
+    if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
+        return BAD_FUNC_ARG;
+    if (ssl->options.side == WOLFSSL_SERVER_END)
+        return SIDE_ERROR;
+
+    ssl->options.postHandshakeAuth = 1;
+
+    return 0;
+}
+
+/* Request a certificate of the client.
+ * Can be called any time after handshake completion.
+ * A maximum of 256 requests can be sent on a connection.
+ *
+ * ssl  SSL/TLS object.
+ */
+int wolfSSL_request_certificate(WOLFSSL* ssl)
+{
+    int         ret;
+#ifndef NO_WOLFSSL_SERVER
+    CertReqCtx* certReqCtx;
+#endif
+
+    if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
+        return BAD_FUNC_ARG;
+#ifndef NO_WOLFSSL_SERVER
+    if (ssl->options.side == WOLFSSL_CLIENT_END)
+        return SIDE_ERROR;
+    if (ssl->options.handShakeState != HANDSHAKE_DONE)
+        return NOT_READY_ERROR;
+    if (!ssl->options.postHandshakeAuth)
+        return POST_HAND_AUTH_ERROR;
+
+    certReqCtx = (CertReqCtx*)XMALLOC(sizeof(CertReqCtx), ssl->heap,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+    if (certReqCtx == NULL)
+        return MEMORY_E;
+    XMEMSET(certReqCtx, 0, sizeof(CertReqCtx));
+    certReqCtx->next = ssl->certReqCtx;
+    certReqCtx->len = 1;
+    if (certReqCtx->next != NULL)
+        certReqCtx->ctx = certReqCtx->next->ctx + 1;
+    ssl->certReqCtx = certReqCtx;
+
+    ssl->msgsReceived.got_certificate = 0;
+    ssl->msgsReceived.got_certificate_verify = 0;
+    ssl->msgsReceived.got_finished = 0;
+
+    ret = SendTls13CertificateRequest(ssl, &certReqCtx->ctx, certReqCtx->len);
+    if (ret == WANT_WRITE)
+        ret = WOLFSSL_ERROR_WANT_WRITE;
+    else if (ret == 0)
+        ret = WOLFSSL_SUCCESS;
+#else
+    ret = SIDE_ERROR;
+#endif
+
+    return ret;
+}
+#endif /* !NO_CERTS && WOLFSSL_POST_HANDSHAKE_AUTH */
+
+#if !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)
+/* Get the preferred key exchange group.
+ *
+ * ssl  The SSL/TLS object.
+ * returns BAD_FUNC_ARG when ssl is NULL or not using TLS v1.3,
+ * SIDE_ERROR when not a client, NOT_READY_ERROR when handshake not complete
+ * and group number on success.
+ */
+int wolfSSL_preferred_group(WOLFSSL* ssl)
+{
+    if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
+        return BAD_FUNC_ARG;
+#ifndef NO_WOLFSSL_CLIENT
+    if (ssl->options.side == WOLFSSL_SERVER_END)
+        return SIDE_ERROR;
+    if (ssl->options.handShakeState != HANDSHAKE_DONE)
+        return NOT_READY_ERROR;
+
+    /* Return supported groups only. */
+    return TLSX_SupportedCurve_Preferred(ssl, 1);
+#else
+    return SIDE_ERROR;
+#endif
+}
+#endif
+
+/* Sets the key exchange groups in rank order on a context.
+ *
+ * ctx     SSL/TLS context object.
+ * groups  Array of groups.
+ * count   Number of groups in array.
+ * returns BAD_FUNC_ARG when ctx or groups is NULL, not using TLS v1.3 or
+ * count is greater than WOLFSSL_MAX_GROUP_COUNT and WOLFSSL_SUCCESS on success.
+ */
+int wolfSSL_CTX_set_groups(WOLFSSL_CTX* ctx, int* groups, int count)
+{
+    int i;
+
+    if (ctx == NULL || groups == NULL || count > WOLFSSL_MAX_GROUP_COUNT)
+        return BAD_FUNC_ARG;
+    if (!IsAtLeastTLSv1_3(ctx->method->version))
+        return BAD_FUNC_ARG;
+
+    for (i = 0; i < count; i++)
+        ctx->group[i] = (word16)groups[i];
+    ctx->numGroups = (byte)count;
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* Sets the key exchange groups in rank order.
+ *
+ * ssl     SSL/TLS object.
+ * groups  Array of groups.
+ * count   Number of groups in array.
+ * returns BAD_FUNC_ARG when ssl or groups is NULL, not using TLS v1.3 or
+ * count is greater than WOLFSSL_MAX_GROUP_COUNT and WOLFSSL_SUCCESS on success.
+ */
+int wolfSSL_set_groups(WOLFSSL* ssl, int* groups, int count)
+{
+    int i;
+
+    if (ssl == NULL || groups == NULL || count > WOLFSSL_MAX_GROUP_COUNT)
+        return BAD_FUNC_ARG;
+    if (!IsAtLeastTLSv1_3(ssl->version))
+        return BAD_FUNC_ARG;
+
+    for (i = 0; i < count; i++)
+        ssl->group[i] = (word16)groups[i];
+    ssl->numGroups = (byte)count;
+
+    return WOLFSSL_SUCCESS;
+}
+
+#ifndef NO_PSK
+void wolfSSL_CTX_set_psk_client_tls13_callback(WOLFSSL_CTX* ctx,
+                                               wc_psk_client_tls13_callback cb)
+{
+    WOLFSSL_ENTER("SSL_CTX_set_psk_client_tls13_callback");
+
+    if (ctx == NULL)
+        return;
+
+    ctx->havePSK = 1;
+    ctx->client_psk_tls13_cb = cb;
+}
+
+
+void wolfSSL_set_psk_client_tls13_callback(WOLFSSL* ssl,
+                                           wc_psk_client_tls13_callback cb)
+{
+    byte haveRSA = 1;
+    int  keySz   = 0;
+
+    WOLFSSL_ENTER("SSL_set_psk_client_tls13_callback");
+
+    if (ssl == NULL)
+        return;
+
+    ssl->options.havePSK = 1;
+    ssl->options.client_psk_tls13_cb = cb;
+
+    #ifdef NO_RSA
+        haveRSA = 0;
+    #endif
+    #ifndef NO_CERTS
+        keySz = ssl->buffers.keySz;
+    #endif
+    InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE,
+               ssl->options.haveDH, ssl->options.haveNTRU,
+               ssl->options.haveECDSAsig, ssl->options.haveECC,
+               ssl->options.haveStaticECC, ssl->options.side);
+}
+
+
+void wolfSSL_CTX_set_psk_server_tls13_callback(WOLFSSL_CTX* ctx,
+                                               wc_psk_server_tls13_callback cb)
+{
+    WOLFSSL_ENTER("SSL_CTX_set_psk_server_tls13_callback");
+    if (ctx == NULL)
+        return;
+    ctx->havePSK = 1;
+    ctx->server_psk_tls13_cb = cb;
+}
+
+
+void wolfSSL_set_psk_server_tls13_callback(WOLFSSL* ssl,
+                                           wc_psk_server_tls13_callback cb)
+{
+    byte haveRSA = 1;
+    int  keySz   = 0;
+
+    WOLFSSL_ENTER("SSL_set_psk_server_tls13_callback");
+    if (ssl == NULL)
+        return;
+
+    ssl->options.havePSK = 1;
+    ssl->options.server_psk_tls13_cb = cb;
+
+    #ifdef NO_RSA
+        haveRSA = 0;
+    #endif
+    #ifndef NO_CERTS
+        keySz = ssl->buffers.keySz;
+    #endif
+    InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE,
+               ssl->options.haveDH, ssl->options.haveNTRU,
+               ssl->options.haveECDSAsig, ssl->options.haveECC,
+               ssl->options.haveStaticECC, ssl->options.side);
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_SERVER
+/* The server accepting a connection from a client.
+ * The protocol version is expecting to be TLS v1.3.
+ * If the client downgrades, and older versions of the protocol are compiled
+ * in, the server will fallback to wolfSSL_accept().
+ * Please see note at top of README if you get an error from accept.
+ *
+ * ssl  The SSL/TLS object.
+ * returns WOLFSSL_SUCCESS on successful handshake, WOLFSSL_FATAL_ERROR when
+ * unrecoverable error occurs and 0 otherwise.
+ * For more error information use wolfSSL_get_error().
+ */
+int wolfSSL_accept_TLSv13(WOLFSSL* ssl)
+{
+    word16 havePSK = 0;
+    WOLFSSL_ENTER("SSL_accept_TLSv13()");
+
+#ifdef HAVE_ERRNO_H
+    errno = 0;
+#endif
+
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+    havePSK = ssl->options.havePSK;
+#endif
+    (void)havePSK;
+
+    if (ssl->options.side != WOLFSSL_SERVER_END) {
+        WOLFSSL_ERROR(ssl->error = SIDE_ERROR);
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+#ifndef NO_CERTS
+    /* allow no private key if using PK callbacks and CB is set */
+    if (!havePSK) {
+        if (!ssl->buffers.certificate ||
+            !ssl->buffers.certificate->buffer) {
+
+            WOLFSSL_MSG("accept error: server cert required");
+            WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY);
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+    #ifdef HAVE_PK_CALLBACKS
+        if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) {
+            WOLFSSL_MSG("Using PK for server private key");
+        }
+        else
+    #endif
+        if (!ssl->buffers.key || !ssl->buffers.key->buffer) {
+            WOLFSSL_MSG("accept error: server key required");
+            WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY);
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+#endif
+
+    if (ssl->buffers.outputBuffer.length > 0
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        /* do not send buffered or advance state if last error was an 
+            async pending operation */
+        && ssl->error != WC_PENDING_E
+    #endif
+    ) {
+        if ((ssl->error = SendBuffered(ssl)) == 0) {
+            /* fragOffset is non-zero when sending fragments. On the last
+             * fragment, fragOffset is zero again, and the state can be
+             * advanced. */
+            if (ssl->fragOffset == 0) {
+                ssl->options.acceptState++;
+                WOLFSSL_MSG("accept state: "
+                            "Advanced from last buffered fragment send");
+            }
+            else {
+                WOLFSSL_MSG("accept state: "
+                            "Not advanced, more fragments to send");
+            }
+        }
+        else {
+            WOLFSSL_ERROR(ssl->error);
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+
+    switch (ssl->options.acceptState) {
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+        case TLS13_ACCEPT_BEGIN_RENEG:
+#endif
+        case TLS13_ACCEPT_BEGIN :
+            /* get client_hello */
+            while (ssl->options.clientState < CLIENT_HELLO_COMPLETE) {
+                if ((ssl->error = ProcessReply(ssl)) < 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+
+            ssl->options.acceptState = TLS13_ACCEPT_CLIENT_HELLO_DONE;
+            WOLFSSL_MSG("accept state ACCEPT_CLIENT_HELLO_DONE");
+            if (!IsAtLeastTLSv1_3(ssl->version))
+                return wolfSSL_accept(ssl);
+            FALL_THROUGH;
+
+        case TLS13_ACCEPT_CLIENT_HELLO_DONE :
+#ifdef WOLFSSL_TLS13_DRAFT_18
+            if (ssl->options.serverState ==
+                                          SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
+                if ((ssl->error = SendTls13HelloRetryRequest(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+
+            ssl->options.acceptState = TLS13_ACCEPT_FIRST_REPLY_DONE;
+            WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE");
+            FALL_THROUGH;
+
+        case TLS13_ACCEPT_HELLO_RETRY_REQUEST_DONE :
+#else
+            if (ssl->options.serverState ==
+                                          SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
+                if ((ssl->error = SendTls13ServerHello(ssl,
+                                                   hello_retry_request)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+
+            ssl->options.acceptState = TLS13_ACCEPT_HELLO_RETRY_REQUEST_DONE;
+            WOLFSSL_MSG("accept state ACCEPT_HELLO_RETRY_REQUEST_DONE");
+            FALL_THROUGH;
+
+        case TLS13_ACCEPT_HELLO_RETRY_REQUEST_DONE :
+    #ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT
+            if (ssl->options.serverState ==
+                                          SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
+                if ((ssl->error = SendChangeCipher(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+                ssl->options.sentChangeCipher = 1;
+                ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE;
+            }
+    #endif
+            ssl->options.acceptState = TLS13_ACCEPT_FIRST_REPLY_DONE;
+            WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE");
+            FALL_THROUGH;
+#endif
+
+        case TLS13_ACCEPT_FIRST_REPLY_DONE :
+            if (ssl->options.serverState ==
+                                          SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
+                ssl->options.clientState = CLIENT_HELLO_RETRY;
+                while (ssl->options.clientState < CLIENT_HELLO_COMPLETE) {
+                    if ((ssl->error = ProcessReply(ssl)) < 0) {
+                        WOLFSSL_ERROR(ssl->error);
+                        return WOLFSSL_FATAL_ERROR;
+                    }
+                }
+            }
+
+            ssl->options.acceptState = TLS13_ACCEPT_SECOND_REPLY_DONE;
+            WOLFSSL_MSG("accept state ACCEPT_SECOND_REPLY_DONE");
+            FALL_THROUGH;
+
+        case TLS13_ACCEPT_SECOND_REPLY_DONE :
+            if ((ssl->error = SendTls13ServerHello(ssl, server_hello)) != 0) {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+            ssl->options.acceptState = TLS13_SERVER_HELLO_SENT;
+            WOLFSSL_MSG("accept state SERVER_HELLO_SENT");
+            FALL_THROUGH;
+
+        case TLS13_SERVER_HELLO_SENT :
+    #if !defined(WOLFSSL_TLS13_DRAFT_18) && \
+                                         defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
+            if (!ssl->options.sentChangeCipher) {
+                if ((ssl->error = SendChangeCipher(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+                ssl->options.sentChangeCipher = 1;
+            }
+    #endif
+
+            ssl->options.acceptState = TLS13_ACCEPT_THIRD_REPLY_DONE;
+            WOLFSSL_MSG("accept state ACCEPT_THIRD_REPLY_DONE");
+            FALL_THROUGH;
+
+        case TLS13_ACCEPT_THIRD_REPLY_DONE :
+            if (!ssl->options.noPskDheKe) {
+                ssl->error = TLSX_KeyShare_DeriveSecret(ssl);
+                if (ssl->error != 0)
+                    return WOLFSSL_FATAL_ERROR;
+            }
+
+            if ((ssl->error = SendTls13EncryptedExtensions(ssl)) != 0) {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+            ssl->options.acceptState = TLS13_SERVER_EXTENSIONS_SENT;
+            WOLFSSL_MSG("accept state SERVER_EXTENSIONS_SENT");
+            FALL_THROUGH;
+
+        case TLS13_SERVER_EXTENSIONS_SENT :
+#ifndef NO_CERTS
+            if (!ssl->options.resuming) {
+                if (ssl->options.verifyPeer) {
+                    ssl->error = SendTls13CertificateRequest(ssl, NULL, 0);
+                    if (ssl->error != 0) {
+                        WOLFSSL_ERROR(ssl->error);
+                        return WOLFSSL_FATAL_ERROR;
+                    }
+                }
+            }
+#endif
+            ssl->options.acceptState = TLS13_CERT_REQ_SENT;
+            WOLFSSL_MSG("accept state CERT_REQ_SENT");
+            FALL_THROUGH;
+
+        case TLS13_CERT_REQ_SENT :
+#ifndef NO_CERTS
+            if (!ssl->options.resuming && ssl->options.sendVerify) {
+                if ((ssl->error = SendTls13Certificate(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+#endif
+            ssl->options.acceptState = TLS13_CERT_SENT;
+            WOLFSSL_MSG("accept state CERT_SENT");
+            FALL_THROUGH;
+
+        case TLS13_CERT_SENT :
+#ifndef NO_CERTS
+            if (!ssl->options.resuming && ssl->options.sendVerify) {
+                if ((ssl->error = SendTls13CertificateVerify(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+#endif
+            ssl->options.acceptState = TLS13_CERT_VERIFY_SENT;
+            WOLFSSL_MSG("accept state CERT_VERIFY_SENT");
+            FALL_THROUGH;
+
+        case TLS13_CERT_VERIFY_SENT :
+            if ((ssl->error = SendTls13Finished(ssl)) != 0) {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+
+            ssl->options.acceptState = TLS13_ACCEPT_FINISHED_SENT;
+            WOLFSSL_MSG("accept state ACCEPT_FINISHED_SENT");
+#ifdef WOLFSSL_EARLY_DATA
+            if (ssl->earlyData != no_early_data) {
+                ssl->options.handShakeState = SERVER_FINISHED_COMPLETE;
+                return WOLFSSL_SUCCESS;
+            }
+#endif
+            FALL_THROUGH;
+
+        case TLS13_ACCEPT_FINISHED_SENT :
+#ifdef HAVE_SESSION_TICKET
+    #ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED
+            if (!ssl->options.verifyPeer && !ssl->options.noTicketTls13 &&
+                                                ssl->ctx->ticketEncCb != NULL) {
+                if ((ssl->error = SendTls13NewSessionTicket(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+    #endif
+#endif /* HAVE_SESSION_TICKET */
+            ssl->options.acceptState = TLS13_PRE_TICKET_SENT;
+            WOLFSSL_MSG("accept state  TICKET_SENT");
+            FALL_THROUGH;
+
+        case TLS13_PRE_TICKET_SENT :
+            while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE)
+                if ( (ssl->error = ProcessReply(ssl)) < 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+
+            ssl->options.acceptState = TLS13_ACCEPT_FINISHED_DONE;
+            WOLFSSL_MSG("accept state ACCEPT_FINISHED_DONE");
+            FALL_THROUGH;
+
+        case TLS13_ACCEPT_FINISHED_DONE :
+#ifdef HAVE_SESSION_TICKET
+    #ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED
+            if (!ssl->options.verifyPeer) {
+            }
+            else
+    #endif
+            if (!ssl->options.noTicketTls13 && ssl->ctx->ticketEncCb != NULL) {
+                if ((ssl->error = SendTls13NewSessionTicket(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+#endif /* HAVE_SESSION_TICKET */
+            ssl->options.acceptState = TLS13_TICKET_SENT;
+            WOLFSSL_MSG("accept state TICKET_SENT");
+            FALL_THROUGH;
+
+        case TLS13_TICKET_SENT :
+#ifndef NO_HANDSHAKE_DONE_CB
+            if (ssl->hsDoneCb) {
+                int cbret = ssl->hsDoneCb(ssl, ssl->hsDoneCtx);
+                if (cbret < 0) {
+                    ssl->error = cbret;
+                    WOLFSSL_MSG("HandShake Done Cb don't continue error");
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+#endif /* NO_HANDSHAKE_DONE_CB */
+
+            if (!ssl->options.keepResources) {
+                FreeHandshakeResources(ssl);
+            }
+
+            WOLFSSL_LEAVE("SSL_accept()", WOLFSSL_SUCCESS);
+            return WOLFSSL_SUCCESS;
+
+        default :
+            WOLFSSL_MSG("Unknown accept state ERROR");
+            return WOLFSSL_FATAL_ERROR;
+    }
+}
+#endif
+
+#ifdef WOLFSSL_EARLY_DATA
+/* Sets the maximum amount of early data that can be seen by server when using
+ * session tickets for resumption.
+ * A value of zero indicates no early data is to be sent by client using session
+ * tickets.
+ *
+ * ctx  The SSL/TLS CTX object.
+ * sz   Maximum size of the early data.
+ * returns BAD_FUNC_ARG when ctx is NULL, SIDE_ERROR when not a server and
+ * 0 on success.
+ */
+int wolfSSL_CTX_set_max_early_data(WOLFSSL_CTX* ctx, unsigned int sz)
+{
+    if (ctx == NULL || !IsAtLeastTLSv1_3(ctx->method->version))
+        return BAD_FUNC_ARG;
+    if (ctx->method->side == WOLFSSL_CLIENT_END)
+        return SIDE_ERROR;
+
+    ctx->maxEarlyDataSz = sz;
+
+    return 0;
+}
+
+/* Sets the maximum amount of early data that can be seen by server when using
+ * session tickets for resumption.
+ * A value of zero indicates no early data is to be sent by client using session
+ * tickets.
+ *
+ * ssl  The SSL/TLS object.
+ * sz   Maximum size of the early data.
+ * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3,
+ * SIDE_ERROR when not a server and 0 on success.
+ */
+int wolfSSL_set_max_early_data(WOLFSSL* ssl, unsigned int sz)
+{
+    if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
+        return BAD_FUNC_ARG;
+    if (ssl->options.side == WOLFSSL_CLIENT_END)
+        return SIDE_ERROR;
+
+    ssl->options.maxEarlyDataSz = sz;
+
+    return 0;
+}
+
+/* Write early data to the server.
+ *
+ * ssl    The SSL/TLS object.
+ * data   Early data to write
+ * sz     The size of the eary data in bytes.
+ * outSz  The number of early data bytes written.
+ * returns BAD_FUNC_ARG when: ssl, data or outSz is NULL; sz is negative;
+ * or not using TLS v1.3. SIDE ERROR when not a server. Otherwise the number of
+ * early data bytes written.
+ */
+int wolfSSL_write_early_data(WOLFSSL* ssl, const void* data, int sz, int* outSz)
+{
+    int ret = 0;
+
+    WOLFSSL_ENTER("SSL_write_early_data()");
+
+    if (ssl == NULL || data == NULL || sz < 0 || outSz == NULL)
+        return BAD_FUNC_ARG;
+    if (!IsAtLeastTLSv1_3(ssl->version))
+        return BAD_FUNC_ARG;
+
+#ifndef NO_WOLFSSL_CLIENT
+    if (ssl->options.side == WOLFSSL_SERVER_END)
+        return SIDE_ERROR;
+
+    if (ssl->options.handShakeState == NULL_STATE) {
+        ssl->earlyData = expecting_early_data;
+        ret = wolfSSL_connect_TLSv13(ssl);
+        if (ret != WOLFSSL_SUCCESS)
+            return WOLFSSL_FATAL_ERROR;
+    }
+    if (ssl->options.handShakeState == CLIENT_HELLO_COMPLETE) {
+        ret = SendData(ssl, data, sz);
+        if (ret > 0)
+            *outSz = ret;
+    }
+#else
+    return SIDE_ERROR;
+#endif
+
+    WOLFSSL_LEAVE("SSL_write_early_data()", ret);
+
+    if (ret < 0)
+        ret = WOLFSSL_FATAL_ERROR;
+    return ret;
+}
+
+/* Read the any early data from the client.
+ *
+ * ssl    The SSL/TLS object.
+ * data   Buffer to put the early data into.
+ * sz     The size of the buffer in bytes.
+ * outSz  The number of early data bytes read.
+ * returns BAD_FUNC_ARG when: ssl, data or outSz is NULL; sz is negative;
+ * or not using TLS v1.3. SIDE ERROR when not a server. Otherwise the number of
+ * early data bytes read.
+ */
+int wolfSSL_read_early_data(WOLFSSL* ssl, void* data, int sz, int* outSz)
+{
+    int ret = 0;
+
+    WOLFSSL_ENTER("wolfSSL_read_early_data()");
+
+
+    if (ssl == NULL || data == NULL || sz < 0 || outSz == NULL)
+        return BAD_FUNC_ARG;
+    if (!IsAtLeastTLSv1_3(ssl->version))
+        return BAD_FUNC_ARG;
+
+#ifndef NO_WOLFSSL_SERVER
+    if (ssl->options.side == WOLFSSL_CLIENT_END)
+        return SIDE_ERROR;
+
+    if (ssl->options.handShakeState == NULL_STATE) {
+        ssl->earlyData = expecting_early_data;
+        ret = wolfSSL_accept_TLSv13(ssl);
+        if (ret <= 0)
+            return WOLFSSL_FATAL_ERROR;
+    }
+    if (ssl->options.handShakeState == SERVER_FINISHED_COMPLETE) {
+        ret = ReceiveData(ssl, (byte*)data, sz, FALSE);
+        if (ret > 0)
+            *outSz = ret;
+        if (ssl->error == ZERO_RETURN)
+            ssl->error = WOLFSSL_ERROR_NONE;
+    }
+    else
+        ret = 0;
+#else
+    return SIDE_ERROR;
+#endif
+
+    WOLFSSL_LEAVE("wolfSSL_read_early_data()", ret);
+
+    if (ret < 0)
+        ret = WOLFSSL_FATAL_ERROR;
+    return ret;
+}
+#endif
+
+#ifdef HAVE_SECRET_CALLBACK
+int wolfSSL_set_tls13_secret_cb(WOLFSSL* ssl, Tls13SecretCb cb, void* ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_set_tls13_secret_cb");
+    if (ssl == NULL)
+        return WOLFSSL_FATAL_ERROR;
+
+    ssl->tls13SecretCb = cb;
+    ssl->tls13SecretCtx = ctx;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif
+
+#undef ERROR_OUT
+
+#endif /* !WOLFCRYPT_ONLY */
+
+#endif /* WOLFSSL_TLS13 */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/wolfio.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/wolfio.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/wolfio.c	(revision 453)
@@ -0,0 +1,2375 @@
+/* wolfio.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifndef WOLFCRYPT_ONLY
+
+#ifdef _WIN32_WCE
+    /* On WinCE winsock2.h must be included before windows.h for socket stuff */
+    #include <winsock2.h>
+#endif
+
+#include <wolfssl/internal.h>
+#include <wolfssl/error-ssl.h>
+#include <wolfssl/wolfio.h>
+
+#if defined(HAVE_HTTP_CLIENT)
+    #include <stdlib.h>   /* strtol() */
+#endif
+
+/*
+Possible IO enable options:
+ * WOLFSSL_USER_IO:     Disables default Embed* callbacks and     default: off
+                        allows user to define their own using
+                        wolfSSL_CTX_SetIORecv and wolfSSL_CTX_SetIOSend
+ * USE_WOLFSSL_IO:      Enables the wolfSSL IO functions          default: off
+ * HAVE_HTTP_CLIENT:    Enables HTTP client API's                 default: off
+                                     (unless HAVE_OCSP or HAVE_CRL_IO defined)
+ * HAVE_IO_TIMEOUT:     Enables support for connect timeout       default: off
+ */
+
+
+/* if user writes own I/O callbacks they can define WOLFSSL_USER_IO to remove
+   automatic setting of default I/O functions EmbedSend() and EmbedReceive()
+   but they'll still need SetCallback xxx() at end of file
+*/
+
+#if defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT)
+
+/* Translates return codes returned from
+ * send() and recv() if need be.
+ */
+static WC_INLINE int TranslateReturnCode(int old, int sd)
+{
+    (void)sd;
+
+#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
+    if (old == 0) {
+        errno = SOCKET_EWOULDBLOCK;
+        return -1;  /* convert to BSD style wouldblock as error */
+    }
+
+    if (old < 0) {
+        errno = RTCS_geterror(sd);
+        if (errno == RTCSERR_TCP_CONN_CLOSING)
+            return 0;   /* convert to BSD style closing */
+        if (errno == RTCSERR_TCP_CONN_RLSD)
+            errno = SOCKET_ECONNRESET;
+        if (errno == RTCSERR_TCP_TIMED_OUT)
+            errno = SOCKET_EAGAIN;
+    }
+#endif
+
+    return old;
+}
+
+static WC_INLINE int wolfSSL_LastError(void)
+{
+#ifdef USE_WINDOWS_API
+    return WSAGetLastError();
+#elif defined(EBSNET)
+    return xn_getlasterror();
+#else
+    return errno;
+#endif
+}
+
+#endif /* USE_WOLFSSL_IO || HAVE_HTTP_CLIENT */
+
+
+#ifdef OPENSSL_EXTRA
+/* Use the WOLFSSL read BIO for receiving data. This is set by the function
+ * wolfSSL_set_bio and can also be set by wolfSSL_CTX_SetIORecv.
+ *
+ * ssl  WOLFSSL struct passed in that has this function set as the receive
+ *      callback.
+ * buf  buffer to fill with data read
+ * sz   size of buf buffer
+ * ctx  a user set context
+ *
+ * returns the amount of data read or want read. See WOLFSSL_CBIO_ERR_* values.
+ */
+int BioReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx)
+{
+    int recvd = WOLFSSL_CBIO_ERR_GENERAL;
+
+    WOLFSSL_ENTER("BioReceive");
+
+    if (ssl->biord == NULL) {
+        WOLFSSL_MSG("WOLFSSL biord not set");
+        return WOLFSSL_CBIO_ERR_GENERAL;
+    }
+
+    if (ssl->biord->method && ssl->biord->method->readCb) {
+        WOLFSSL_MSG("Calling custom biord");
+        recvd = ssl->biord->method->readCb(ssl->biord, buf, sz);
+        if (recvd < 0 && recvd != WOLFSSL_CBIO_ERR_WANT_READ)
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        return recvd;
+    }
+
+    switch (ssl->biord->type) {
+        case WOLFSSL_BIO_MEMORY:
+        case WOLFSSL_BIO_BIO:
+            if (wolfSSL_BIO_ctrl_pending(ssl->biord) == 0) {
+                WOLFSSL_MSG("BIO want read");
+               return WOLFSSL_CBIO_ERR_WANT_READ;
+            }
+            recvd = wolfSSL_BIO_read(ssl->biord, buf, sz);
+            if (recvd <= 0) {
+                WOLFSSL_MSG("BIO general error");
+                return WOLFSSL_CBIO_ERR_GENERAL;
+            }
+            break;
+
+       default:
+            WOLFSSL_MSG("This BIO type is unknown / unsupported");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+    }
+
+    (void)ctx;
+    return recvd;
+}
+
+
+/* Use the WOLFSSL write BIO for sending data. This is set by the function
+ * wolfSSL_set_bio and can also be set by wolfSSL_CTX_SetIOSend.
+ *
+ * ssl  WOLFSSL struct passed in that has this function set as the send callback.
+ * buf  buffer with data to write out
+ * sz   size of buf buffer
+ * ctx  a user set context
+ *
+ * returns the amount of data sent or want send. See WOLFSSL_CBIO_ERR_* values.
+ */
+int BioSend(WOLFSSL* ssl, char *buf, int sz, void *ctx)
+{
+    int sent = WOLFSSL_CBIO_ERR_GENERAL;
+
+    WOLFSSL_ENTER("BioSend");
+
+    if (ssl->biowr == NULL) {
+        WOLFSSL_MSG("WOLFSSL biowr not set");
+        return WOLFSSL_CBIO_ERR_GENERAL;
+    }
+
+    if (ssl->biowr->method && ssl->biowr->method->writeCb) {
+        WOLFSSL_MSG("Calling custom biowr");
+        sent = ssl->biowr->method->writeCb(ssl->biowr, buf, sz);
+        if (sent < 0) {
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+        return sent;
+    }
+
+    switch (ssl->biowr->type) {
+        case WOLFSSL_BIO_MEMORY:
+        case WOLFSSL_BIO_BIO:
+            sent = wolfSSL_BIO_write(ssl->biowr, buf, sz);
+            if (sent < 0) {
+                return WOLFSSL_CBIO_ERR_GENERAL;
+            }
+            break;
+
+        default:
+            WOLFSSL_MSG("This BIO type is unknown / unsupported");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+    }
+    (void)ctx;
+
+    return sent;
+}
+#endif
+
+
+#ifdef USE_WOLFSSL_IO
+
+/* The receive embedded callback
+ *  return : nb bytes read, or error
+ */
+int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
+{
+    int sd = *(int*)ctx;
+    int recvd;
+
+    recvd = wolfIO_Recv(sd, buf, sz, ssl->rflags);
+    if (recvd < 0) {
+        int err = wolfSSL_LastError();
+        WOLFSSL_MSG("Embed Receive error");
+
+        if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
+            WOLFSSL_MSG("\tWould block");
+            return WOLFSSL_CBIO_ERR_WANT_READ;
+        }
+        else if (err == SOCKET_ECONNRESET) {
+            WOLFSSL_MSG("\tConnection reset");
+            return WOLFSSL_CBIO_ERR_CONN_RST;
+        }
+        else if (err == SOCKET_EINTR) {
+            WOLFSSL_MSG("\tSocket interrupted");
+            return WOLFSSL_CBIO_ERR_ISR;
+        }
+        else if (err == SOCKET_ECONNABORTED) {
+            WOLFSSL_MSG("\tConnection aborted");
+            return WOLFSSL_CBIO_ERR_CONN_CLOSE;
+        }
+        else {
+            WOLFSSL_MSG("\tGeneral error");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+    }
+    else if (recvd == 0) {
+        WOLFSSL_MSG("Embed receive connection closed");
+        return WOLFSSL_CBIO_ERR_CONN_CLOSE;
+    }
+
+    return recvd;
+}
+
+/* The send embedded callback
+ *  return : nb bytes sent, or error
+ */
+int EmbedSend(WOLFSSL* ssl, char *buf, int sz, void *ctx)
+{
+    int sd = *(int*)ctx;
+    int sent;
+
+#ifdef WOLFSSL_MAX_SEND_SZ
+    if (sz > WOLFSSL_MAX_SEND_SZ)
+        sz = WOLFSSL_MAX_SEND_SZ;
+#endif
+
+    sent = wolfIO_Send(sd, buf, sz, ssl->wflags);
+    if (sent < 0) {
+        int err = wolfSSL_LastError();
+        WOLFSSL_MSG("Embed Send error");
+
+        if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
+            WOLFSSL_MSG("\tWould Block");
+            return WOLFSSL_CBIO_ERR_WANT_WRITE;
+        }
+        else if (err == SOCKET_ECONNRESET) {
+            WOLFSSL_MSG("\tConnection reset");
+            return WOLFSSL_CBIO_ERR_CONN_RST;
+        }
+        else if (err == SOCKET_EINTR) {
+            WOLFSSL_MSG("\tSocket interrupted");
+            return WOLFSSL_CBIO_ERR_ISR;
+        }
+        else if (err == SOCKET_EPIPE) {
+            WOLFSSL_MSG("\tSocket EPIPE");
+            return WOLFSSL_CBIO_ERR_CONN_CLOSE;
+        }
+        else {
+            WOLFSSL_MSG("\tGeneral error");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+    }
+
+    return sent;
+}
+
+
+#ifdef WOLFSSL_DTLS
+
+#include <wolfssl/wolfcrypt/sha.h>
+
+#define SENDTO_FUNCTION sendto
+#define RECVFROM_FUNCTION recvfrom
+
+
+/* The receive embedded callback
+ *  return : nb bytes read, or error
+ */
+int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
+{
+    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
+    int recvd;
+    int err;
+    int sd = dtlsCtx->rfd;
+    int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
+    SOCKADDR_S peer;
+    XSOCKLENT peerSz = sizeof(peer);
+
+    WOLFSSL_ENTER("EmbedReceiveFrom()");
+
+    if (ssl->options.handShakeDone)
+        dtls_timeout = 0;
+
+    if (!wolfSSL_get_using_nonblock(ssl)) {
+        #ifdef USE_WINDOWS_API
+            DWORD timeout = dtls_timeout * 1000;
+        #else
+            struct timeval timeout;
+            XMEMSET(&timeout, 0, sizeof(timeout));
+            timeout.tv_sec = dtls_timeout;
+        #endif
+        if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
+                       sizeof(timeout)) != 0) {
+                WOLFSSL_MSG("setsockopt rcvtimeo failed");
+        }
+    }
+
+    recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags,
+                                  (SOCKADDR*)&peer, &peerSz);
+
+    recvd = TranslateReturnCode(recvd, sd);
+
+    if (recvd < 0) {
+        err = wolfSSL_LastError();
+        WOLFSSL_MSG("Embed Receive From error");
+
+        if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
+            if (wolfSSL_dtls_get_using_nonblock(ssl)) {
+                WOLFSSL_MSG("\tWould block");
+                return WOLFSSL_CBIO_ERR_WANT_READ;
+            }
+            else {
+                WOLFSSL_MSG("\tSocket timeout");
+                return WOLFSSL_CBIO_ERR_TIMEOUT;
+            }
+        }
+        else if (err == SOCKET_ECONNRESET) {
+            WOLFSSL_MSG("\tConnection reset");
+            return WOLFSSL_CBIO_ERR_CONN_RST;
+        }
+        else if (err == SOCKET_EINTR) {
+            WOLFSSL_MSG("\tSocket interrupted");
+            return WOLFSSL_CBIO_ERR_ISR;
+        }
+        else if (err == SOCKET_ECONNREFUSED) {
+            WOLFSSL_MSG("\tConnection refused");
+            return WOLFSSL_CBIO_ERR_WANT_READ;
+        }
+        else {
+            WOLFSSL_MSG("\tGeneral error");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+    }
+    else {
+        if (dtlsCtx->peer.sz > 0
+                && peerSz != (XSOCKLENT)dtlsCtx->peer.sz
+                && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) {
+            WOLFSSL_MSG("    Ignored packet from invalid peer");
+            return WOLFSSL_CBIO_ERR_WANT_READ;
+        }
+    }
+
+    return recvd;
+}
+
+
+/* The send embedded callback
+ *  return : nb bytes sent, or error
+ */
+int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
+{
+    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
+    int sd = dtlsCtx->wfd;
+    int sent;
+    int err;
+
+    WOLFSSL_ENTER("EmbedSendTo()");
+
+    sent = (int)SENDTO_FUNCTION(sd, buf, sz, ssl->wflags,
+                                (const SOCKADDR*)dtlsCtx->peer.sa,
+                                dtlsCtx->peer.sz);
+
+    sent = TranslateReturnCode(sent, sd);
+
+    if (sent < 0) {
+        err = wolfSSL_LastError();
+        WOLFSSL_MSG("Embed Send To error");
+
+        if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
+            WOLFSSL_MSG("\tWould Block");
+            return WOLFSSL_CBIO_ERR_WANT_WRITE;
+        }
+        else if (err == SOCKET_ECONNRESET) {
+            WOLFSSL_MSG("\tConnection reset");
+            return WOLFSSL_CBIO_ERR_CONN_RST;
+        }
+        else if (err == SOCKET_EINTR) {
+            WOLFSSL_MSG("\tSocket interrupted");
+            return WOLFSSL_CBIO_ERR_ISR;
+        }
+        else if (err == SOCKET_EPIPE) {
+            WOLFSSL_MSG("\tSocket EPIPE");
+            return WOLFSSL_CBIO_ERR_CONN_CLOSE;
+        }
+        else {
+            WOLFSSL_MSG("\tGeneral error");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+    }
+
+    return sent;
+}
+
+
+#ifdef WOLFSSL_MULTICAST
+
+/* The alternate receive embedded callback for Multicast
+ *  return : nb bytes read, or error
+ */
+int EmbedReceiveFromMcast(WOLFSSL *ssl, char *buf, int sz, void *ctx)
+{
+    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
+    int recvd;
+    int err;
+    int sd = dtlsCtx->rfd;
+
+    WOLFSSL_ENTER("EmbedReceiveFromMcast()");
+
+    recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags, NULL, NULL);
+
+    recvd = TranslateReturnCode(recvd, sd);
+
+    if (recvd < 0) {
+        err = wolfSSL_LastError();
+        WOLFSSL_MSG("Embed Receive From error");
+
+        if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
+            if (wolfSSL_dtls_get_using_nonblock(ssl)) {
+                WOLFSSL_MSG("\tWould block");
+                return WOLFSSL_CBIO_ERR_WANT_READ;
+            }
+            else {
+                WOLFSSL_MSG("\tSocket timeout");
+                return WOLFSSL_CBIO_ERR_TIMEOUT;
+            }
+        }
+        else if (err == SOCKET_ECONNRESET) {
+            WOLFSSL_MSG("\tConnection reset");
+            return WOLFSSL_CBIO_ERR_CONN_RST;
+        }
+        else if (err == SOCKET_EINTR) {
+            WOLFSSL_MSG("\tSocket interrupted");
+            return WOLFSSL_CBIO_ERR_ISR;
+        }
+        else if (err == SOCKET_ECONNREFUSED) {
+            WOLFSSL_MSG("\tConnection refused");
+            return WOLFSSL_CBIO_ERR_WANT_READ;
+        }
+        else {
+            WOLFSSL_MSG("\tGeneral error");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+    }
+
+    return recvd;
+}
+#endif /* WOLFSSL_MULTICAST */
+
+
+/* The DTLS Generate Cookie callback
+ *  return : number of bytes copied into buf, or error
+ */
+int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx)
+{
+    int sd = ssl->wfd;
+    SOCKADDR_S peer;
+    XSOCKLENT peerSz = sizeof(peer);
+    byte digest[WC_SHA256_DIGEST_SIZE];
+    int  ret = 0;
+
+    (void)ctx;
+
+    XMEMSET(&peer, 0, sizeof(peer));
+    if (getpeername(sd, (SOCKADDR*)&peer, &peerSz) != 0) {
+        WOLFSSL_MSG("getpeername failed in EmbedGenerateCookie");
+        return GEN_COOKIE_E;
+    }
+
+    ret = wc_Sha256Hash((byte*)&peer, peerSz, digest);
+    if (ret != 0)
+        return ret;
+
+    if (sz > WC_SHA256_DIGEST_SIZE)
+        sz = WC_SHA256_DIGEST_SIZE;
+    XMEMCPY(buf, digest, sz);
+
+    return sz;
+}
+
+#ifdef WOLFSSL_SESSION_EXPORT
+
+    /* get the peer information in human readable form (ip, port, family)
+     * default function assumes BSD sockets
+     * can be overridden with wolfSSL_CTX_SetIOGetPeer
+     */
+    int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz,
+                                                 unsigned short* port, int* fam)
+    {
+        SOCKADDR_S peer;
+        word32     peerSz;
+        int        ret;
+
+        if (ssl == NULL || ip == NULL || ipSz == NULL ||
+                                                  port == NULL || fam == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        /* get peer information stored in ssl struct */
+        peerSz = sizeof(SOCKADDR_S);
+        if ((ret = wolfSSL_dtls_get_peer(ssl, (void*)&peer, &peerSz))
+                                                               != WOLFSSL_SUCCESS) {
+            return ret;
+        }
+
+        /* extract family, ip, and port */
+        *fam = ((SOCKADDR_S*)&peer)->ss_family;
+        switch (*fam) {
+            case WOLFSSL_IP4:
+                if (XINET_NTOP(*fam, &(((SOCKADDR_IN*)&peer)->sin_addr),
+                                                           ip, *ipSz) == NULL) {
+                    WOLFSSL_MSG("XINET_NTOP error");
+                    return SOCKET_ERROR_E;
+                }
+                *port = XNTOHS(((SOCKADDR_IN*)&peer)->sin_port);
+                break;
+
+            case WOLFSSL_IP6:
+            #ifdef WOLFSSL_IPV6
+                if (XINET_NTOP(*fam, &(((SOCKADDR_IN6*)&peer)->sin6_addr),
+                                                           ip, *ipSz) == NULL) {
+                    WOLFSSL_MSG("XINET_NTOP error");
+                    return SOCKET_ERROR_E;
+                }
+                *port = XNTOHS(((SOCKADDR_IN6*)&peer)->sin6_port);
+            #endif /* WOLFSSL_IPV6 */
+                break;
+
+            default:
+                WOLFSSL_MSG("Unknown family type");
+                return SOCKET_ERROR_E;
+        }
+        ip[*ipSz - 1] = '\0'; /* make sure has terminator */
+        *ipSz = (word16)XSTRLEN(ip);
+
+        return WOLFSSL_SUCCESS;
+    }
+
+    /* set the peer information in human readable form (ip, port, family)
+     * default function assumes BSD sockets
+     * can be overridden with wolfSSL_CTX_SetIOSetPeer
+     */
+    int EmbedSetPeer(WOLFSSL* ssl, char* ip, int ipSz,
+                                                   unsigned short port, int fam)
+    {
+        int    ret;
+        SOCKADDR_S addr;
+
+        /* sanity checks on arguments */
+        if (ssl == NULL || ip == NULL || ipSz < 0 || ipSz > DTLS_EXPORT_IP) {
+            return BAD_FUNC_ARG;
+        }
+
+        addr.ss_family = fam;
+        switch (addr.ss_family) {
+            case WOLFSSL_IP4:
+                if (XINET_PTON(addr.ss_family, ip,
+                                     &(((SOCKADDR_IN*)&addr)->sin_addr)) <= 0) {
+                    WOLFSSL_MSG("XINET_PTON error");
+                    return SOCKET_ERROR_E;
+                }
+                ((SOCKADDR_IN*)&addr)->sin_port = XHTONS(port);
+
+                /* peer sa is free'd in SSL_ResourceFree */
+                if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN*)&addr,
+                                          sizeof(SOCKADDR_IN)))!= WOLFSSL_SUCCESS) {
+                    WOLFSSL_MSG("Import DTLS peer info error");
+                    return ret;
+                }
+                break;
+
+            case WOLFSSL_IP6:
+            #ifdef WOLFSSL_IPV6
+                if (XINET_PTON(addr.ss_family, ip,
+                                   &(((SOCKADDR_IN6*)&addr)->sin6_addr)) <= 0) {
+                    WOLFSSL_MSG("XINET_PTON error");
+                    return SOCKET_ERROR_E;
+                }
+                ((SOCKADDR_IN6*)&addr)->sin6_port = XHTONS(port);
+
+                /* peer sa is free'd in SSL_ResourceFree */
+                if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN6*)&addr,
+                                         sizeof(SOCKADDR_IN6)))!= WOLFSSL_SUCCESS) {
+                    WOLFSSL_MSG("Import DTLS peer info error");
+                    return ret;
+                }
+            #endif /* WOLFSSL_IPV6 */
+                break;
+
+            default:
+                WOLFSSL_MSG("Unknown address family");
+                return BUFFER_E;
+        }
+
+        return WOLFSSL_SUCCESS;
+    }
+#endif /* WOLFSSL_SESSION_EXPORT */
+#endif /* WOLFSSL_DTLS */
+
+
+int wolfIO_Recv(SOCKET_T sd, char *buf, int sz, int rdFlags)
+{
+    int recvd;
+
+    recvd = (int)RECV_FUNCTION(sd, buf, sz, rdFlags);
+    recvd = TranslateReturnCode(recvd, sd);
+
+    return recvd;
+}
+
+int wolfIO_Send(SOCKET_T sd, char *buf, int sz, int wrFlags)
+{
+    int sent;
+
+    sent = (int)SEND_FUNCTION(sd, buf, sz, wrFlags);
+    sent = TranslateReturnCode(sent, sd);
+
+    return sent;
+}
+
+#endif /* USE_WOLFSSL_IO */
+
+
+#ifdef HAVE_HTTP_CLIENT
+
+#ifndef HAVE_IO_TIMEOUT
+    #define io_timeout_sec 0
+#else
+
+    #ifndef DEFAULT_TIMEOUT_SEC
+        #define DEFAULT_TIMEOUT_SEC 0 /* no timeout */
+    #endif
+
+    static int io_timeout_sec = DEFAULT_TIMEOUT_SEC;
+
+    void wolfIO_SetTimeout(int to_sec)
+    {
+        io_timeout_sec = to_sec;
+    }
+
+    int wolfIO_SetBlockingMode(SOCKET_T sockfd, int non_blocking)
+    {
+        int ret = 0;
+
+    #ifdef USE_WINDOWS_API
+        unsigned long blocking = non_blocking;
+        ret = ioctlsocket(sockfd, FIONBIO, &blocking);
+        if (ret == SOCKET_ERROR)
+            ret = -1;
+    #else
+        ret = fcntl(sockfd, F_GETFL, 0);
+        if (ret >= 0) {
+            if (non_blocking)
+                ret |= O_NONBLOCK;
+            else
+                ret &= ~O_NONBLOCK;
+            ret = fcntl(sockfd, F_SETFL, ret);
+        }
+    #endif
+        if (ret < 0) {
+            WOLFSSL_MSG("wolfIO_SetBlockingMode failed");
+        }
+
+        return ret;
+    }
+
+    int wolfIO_Select(SOCKET_T sockfd, int to_sec)
+    {
+        fd_set rfds, wfds;
+        int nfds = 0;
+        struct timeval timeout = { (to_sec > 0) ? to_sec : 0, 0};
+        int ret;
+
+    #ifndef USE_WINDOWS_API
+        nfds = (int)sockfd + 1;
+    #endif
+
+        FD_ZERO(&rfds);
+        FD_SET(sockfd, &rfds);
+        wfds = rfds;
+
+        ret = select(nfds, &rfds, &wfds, NULL, &timeout);
+        if (ret == 0) {
+        #ifdef DEBUG_HTTP
+            printf("Timeout: %d\n", ret);
+        #endif
+            return HTTP_TIMEOUT;
+        }
+        else if (ret > 0) {
+            if (FD_ISSET(sockfd, &wfds)) {
+                if (!FD_ISSET(sockfd, &rfds)) {
+                    return 0;
+                }
+            }
+        }
+        return SOCKET_ERROR_E;
+    }
+#endif /* HAVE_IO_TIMEOUT */
+
+static int wolfIO_Word16ToString(char* d, word16 number)
+{
+    int i = 0;
+    word16 order = 10000;
+    word16 digit;
+
+    if (d == NULL)
+        return i;
+
+    if (number == 0)
+        d[i++] = '0';
+    else {
+        while (order) {
+            digit = number / order;
+            if (i > 0 || digit != 0)
+                d[i++] = (char)digit + '0';
+            if (digit != 0)
+                number %= digit * order;
+
+            order = (order > 1) ? order / 10 : 0;
+        }
+    }
+    d[i] = 0; /* null terminate */
+
+    return i;
+}
+
+int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, word16 port, int to_sec)
+{
+#ifdef HAVE_SOCKADDR
+    int ret = 0;
+    SOCKADDR_S addr;
+    int sockaddr_len = sizeof(SOCKADDR_IN);
+    /* use gethostbyname for c99 */
+#if defined(HAVE_GETADDRINFO) && !defined(WOLF_C99)
+    ADDRINFO hints;
+    ADDRINFO* answer = NULL;
+    char strPort[6];
+#else
+    HOSTENT* entry;
+    SOCKADDR_IN *sin;
+#endif
+
+    XMEMSET(&addr, 0, sizeof(addr));
+
+#ifdef WOLFIO_DEBUG
+    printf("TCP Connect: %s:%d\n", ip, port);
+#endif
+
+    /* use gethostbyname for c99 */
+#if defined(HAVE_GETADDRINFO) && !defined(WOLF_C99)
+    XMEMSET(&hints, 0, sizeof(hints));
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_protocol = IPPROTO_TCP;
+
+    if (wolfIO_Word16ToString(strPort, port) == 0) {
+        WOLFSSL_MSG("invalid port number for responder");
+        return -1;
+    }
+
+    if (getaddrinfo(ip, strPort, &hints, &answer) < 0 || answer == NULL) {
+        WOLFSSL_MSG("no addr info for responder");
+        return -1;
+    }
+
+    sockaddr_len = answer->ai_addrlen;
+    XMEMCPY(&addr, answer->ai_addr, sockaddr_len);
+    freeaddrinfo(answer);
+#else
+    entry = gethostbyname(ip);
+    sin = (SOCKADDR_IN *)&addr;
+
+    if (entry) {
+        sin->sin_family = AF_INET;
+        sin->sin_port = XHTONS(port);
+        XMEMCPY(&sin->sin_addr.s_addr, entry->h_addr_list[0], entry->h_length);
+    }
+    else {
+        WOLFSSL_MSG("no addr info for responder");
+        return -1;
+    }
+#endif
+
+    *sockfd = (SOCKET_T)socket(addr.ss_family, SOCK_STREAM, 0);
+
+#ifdef USE_WINDOWS_API
+    if (*sockfd == INVALID_SOCKET) {
+        WOLFSSL_MSG("bad socket fd, out of fds?");
+        return -1;
+    }
+#else
+     if (*sockfd < 0) {
+         WOLFSSL_MSG("bad socket fd, out of fds?");
+         return -1;
+     }
+#endif
+
+#ifdef HAVE_IO_TIMEOUT
+    /* if timeout value provided then set socket non-blocking */
+    if (to_sec > 0) {
+        wolfIO_SetBlockingMode(*sockfd, 1);
+    }
+#else
+    (void)to_sec;
+#endif
+
+    ret = connect(*sockfd, (SOCKADDR *)&addr, sockaddr_len);
+#ifdef HAVE_IO_TIMEOUT
+    if (ret != 0) {
+        if ((errno == EINPROGRESS) && (to_sec > 0)) {
+            /* wait for connect to complete */
+            ret = wolfIO_Select(*sockfd, to_sec);
+
+            /* restore blocking mode */
+            wolfIO_SetBlockingMode(*sockfd, 0);
+        }
+    }
+#endif
+    if (ret != 0) {
+        WOLFSSL_MSG("Responder tcp connect failed");
+        return -1;
+    }
+    return ret;
+#else
+    (void)sockfd;
+    (void)ip;
+    (void)port;
+    (void)to_sec;
+    return -1;
+#endif /* HAVE_SOCKADDR */
+}
+
+#ifndef HTTP_SCRATCH_BUFFER_SIZE
+    #define HTTP_SCRATCH_BUFFER_SIZE 512
+#endif
+#ifndef MAX_URL_ITEM_SIZE
+    #define MAX_URL_ITEM_SIZE   80
+#endif
+
+int wolfIO_DecodeUrl(const char* url, int urlSz, char* outName, char* outPath,
+    word16* outPort)
+{
+    int result = -1;
+
+    if (url == NULL || urlSz == 0) {
+        if (outName)
+            *outName = 0;
+        if (outPath)
+            *outPath = 0;
+        if (outPort)
+            *outPort = 0;
+    }
+    else {
+        int i, cur;
+
+        /* need to break the url down into scheme, address, and port */
+        /*     "http://example.com:8080/" */
+        /*     "http://[::1]:443/"        */
+        if (XSTRNCMP(url, "http://", 7) == 0) {
+            cur = 7;
+        } else cur = 0;
+
+        i = 0;
+        if (url[cur] == '[') {
+            cur++;
+            /* copy until ']' */
+            while (i < MAX_URL_ITEM_SIZE-1 && cur < urlSz && url[cur] != 0 &&
+                    url[cur] != ']') {
+                if (outName)
+                    outName[i] = url[cur];
+                i++; cur++;
+            }
+            cur++; /* skip ']' */
+        }
+        else {
+            while (i < MAX_URL_ITEM_SIZE-1 && cur < urlSz && url[cur] != 0 &&
+                    url[cur] != ':' && url[cur] != '/') {
+                if (outName)
+                    outName[i] = url[cur];
+                i++; cur++;
+            }
+        }
+        if (outName)
+            outName[i] = 0;
+        /* Need to pick out the path after the domain name */
+
+        if (cur < urlSz && url[cur] == ':') {
+            char port[6];
+            int j;
+            word32 bigPort = 0;
+            i = 0;
+            cur++;
+            while (i < 6 && cur < urlSz && url[cur] != 0 && url[cur] != '/') {
+                port[i] = url[cur];
+                i++; cur++;
+            }
+
+            for (j = 0; j < i; j++) {
+                if (port[j] < '0' || port[j] > '9') return -1;
+                bigPort = (bigPort * 10) + (port[j] - '0');
+            }
+            if (outPort)
+                *outPort = (word16)bigPort;
+        }
+        else if (outPort)
+            *outPort = 80;
+
+
+        if (cur < urlSz && url[cur] == '/') {
+            i = 0;
+            while (i < MAX_URL_ITEM_SIZE-1 && cur < urlSz && url[cur] != 0) {
+                if (outPath)
+                    outPath[i] = url[cur];
+                i++; cur++;
+            }
+            if (outPath)
+                outPath[i] = 0;
+        }
+        else if (outPath) {
+            outPath[0] = '/';
+            outPath[1] = 0;
+        }
+
+        result = 0;
+    }
+
+    return result;
+}
+
+static int wolfIO_HttpProcessResponseBuf(int sfd, byte **recvBuf,
+    int* recvBufSz, int chunkSz, char* start, int len, int dynType, void* heap)
+{
+    byte* newRecvBuf = NULL;
+    int newRecvSz = *recvBufSz + chunkSz;
+    int pos = 0;
+
+    WOLFSSL_MSG("Processing HTTP response");
+#ifdef WOLFIO_DEBUG
+    printf("HTTP Chunk %d->%d\n", *recvBufSz, chunkSz);
+#endif
+
+    (void)heap;
+    (void)dynType;
+
+    if (chunkSz < 0 || len < 0) {
+        WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf invalid chunk or length size");
+        return MEMORY_E;
+    }
+
+    if (newRecvSz <= 0) {
+        WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf new receive size overflow");
+        return MEMORY_E;
+    }
+
+    newRecvBuf = (byte*)XMALLOC(newRecvSz, heap, dynType);
+    if (newRecvBuf == NULL) {
+        WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf malloc failed");
+        return MEMORY_E;
+    }
+
+    /* if buffer already exists, then we are growing it */
+    if (*recvBuf) {
+        XMEMCPY(&newRecvBuf[pos], *recvBuf, *recvBufSz);
+        XFREE(*recvBuf, heap, dynType);
+        pos += *recvBufSz;
+        *recvBuf = NULL;
+    }
+
+    /* copy the remainder of the httpBuf into the respBuf */
+    if (len != 0) {
+        if (pos + len <= newRecvSz) {
+            XMEMCPY(&newRecvBuf[pos], start, len);
+            pos += len;
+        }
+        else {
+            WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf bad size");
+            XFREE(newRecvBuf, heap, dynType);
+            return -1;
+        }
+    }
+
+    /* receive the remainder of chunk */
+    while (len < chunkSz) {
+        int rxSz = wolfIO_Recv(sfd, (char*)&newRecvBuf[pos], chunkSz-len, 0);
+        if (rxSz > 0) {
+            len += rxSz;
+            pos += rxSz;
+        }
+        else {
+            WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf recv failed");
+            XFREE(newRecvBuf, heap, dynType);
+            return -1;
+        }
+    }
+
+    *recvBuf = newRecvBuf;
+    *recvBufSz = newRecvSz;
+
+    return 0;
+}
+
+int wolfIO_HttpProcessResponse(int sfd, const char** appStrList,
+    byte** respBuf, byte* httpBuf, int httpBufSz, int dynType, void* heap)
+{
+    int result = 0;
+    int len = 0;
+    char *start, *end;
+    int respBufSz = 0;
+    int isChunked = 0, chunkSz = 0;
+    enum phr_state { phr_init, phr_http_start, phr_have_length, phr_have_type,
+                     phr_wait_end, phr_get_chunk_len, phr_get_chunk_data,
+                     phr_http_end
+    } state = phr_init;
+
+    *respBuf = NULL;
+    start = end = NULL;
+    do {
+        if (state == phr_get_chunk_data) {
+            /* get chunk of data */
+            result = wolfIO_HttpProcessResponseBuf(sfd, respBuf, &respBufSz,
+                chunkSz, start, len, dynType, heap);
+
+            state = (result != 0) ? phr_http_end : phr_get_chunk_len;
+            end = NULL;
+            len = 0;
+        }
+
+        /* read data if no \r\n or first time */
+        if (end == NULL) {
+            result = wolfIO_Recv(sfd, (char*)httpBuf+len, httpBufSz-len-1, 0);
+            if (result > 0) {
+                len += result;
+                start = (char*)httpBuf;
+                start[len] = 0;
+            }
+            else {
+                WOLFSSL_MSG("wolfIO_HttpProcessResponse recv http from peer failed");
+                return -1;
+            }
+        }
+        end = XSTRSTR(start, "\r\n"); /* locate end */
+
+        /* handle incomplete rx */
+        if (end == NULL) {
+            if (len != 0)
+                XMEMMOVE(httpBuf, start, len);
+            start = end = NULL;
+        }
+        /* when start is "\r\n" */
+        else if (end == start) {
+            /* if waiting for end or need chunk len */
+            if (state == phr_wait_end || state == phr_get_chunk_len) {
+                state = (isChunked) ? phr_get_chunk_len : phr_http_end;
+                len -= 2; start += 2; /* skip \r\n */
+             }
+             else {
+                WOLFSSL_MSG("wolfIO_HttpProcessResponse header ended early");
+                return -1;
+             }
+        }
+        else {
+            *end = 0; /* null terminate */
+            len -= (int)(end - start) + 2;
+                /* adjust len to remove the first line including the /r/n */
+
+        #ifdef WOLFIO_DEBUG
+            printf("HTTP Resp: %s\n", start);
+        #endif
+
+            switch (state) {
+                case phr_init:
+                    if (XSTRLEN(start) < 15) { /* 15 is the length of the two
+                                          constant strings we're about to
+                                          compare against. */
+                        WOLFSSL_MSG("wolfIO_HttpProcessResponse HTTP header too short.");
+                        return -1;
+                    }
+                    if (XSTRNCASECMP(start, "HTTP/1", 6) == 0) {
+                        start += 9;
+                        if (XSTRNCASECMP(start, "200 OK", 6) != 0) {
+                            WOLFSSL_MSG("wolfIO_HttpProcessResponse not OK");
+                            return -1;
+                        }
+                        state = phr_http_start;
+                    }
+                    break;
+                case phr_http_start:
+                case phr_have_length:
+                case phr_have_type:
+                    if (XSTRLEN(start) < 13) { /* 13 is the shortest of the following
+                                          next lines we're checking for. */
+                        WOLFSSL_MSG("wolfIO_HttpProcessResponse content type is too short.");
+                        return -1;
+                    }
+
+                    if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) {
+                        int i;
+
+                        start += 13;
+                        while (*start == ' ') start++;
+
+                        /* try and match against appStrList */
+                        i = 0;
+                        while (appStrList[i] != NULL) {
+                            if (XSTRNCASECMP(start, appStrList[i],
+                                                XSTRLEN(appStrList[i])) == 0) {
+                                break;
+                            }
+                            i++;
+                        }
+                        if (appStrList[i] == NULL) {
+                            WOLFSSL_MSG("wolfIO_HttpProcessResponse appstr mismatch");
+                            return -1;
+                        }
+                        state = (state == phr_http_start) ? phr_have_type : phr_wait_end;
+                    }
+                    else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) {
+                        start += 15;
+                        while (*start == ' ') start++;
+                        chunkSz = XATOI(start);
+                        state = (state == phr_http_start) ? phr_have_length : phr_wait_end;
+                    }
+                    else if (XSTRNCASECMP(start, "Transfer-Encoding:", 18) == 0) {
+                        start += 18;
+                        while (*start == ' ') start++;
+                        if (XSTRNCASECMP(start, "chunked", 7) == 0) {
+                            isChunked = 1;
+                            state = (state == phr_http_start) ? phr_have_length : phr_wait_end;
+                        }
+                    }
+                    break;
+                case phr_get_chunk_len:
+                    chunkSz = (int)strtol(start, NULL, 16); /* hex format */
+                    state = (chunkSz == 0) ? phr_http_end : phr_get_chunk_data;
+                    break;
+                case phr_get_chunk_data:
+                    /* processing for chunk data done above, since \r\n isn't required */
+                case phr_wait_end:
+                case phr_http_end:
+                    /* do nothing */
+                    break;
+            } /* switch (state) */
+
+            /* skip to end plus \r\n */
+            start = end + 2;
+        }
+    } while (state != phr_http_end);
+
+    if (!isChunked) {
+        result = wolfIO_HttpProcessResponseBuf(sfd, respBuf, &respBufSz, chunkSz,
+                                                    start, len, dynType, heap);
+    }
+
+    if (result >= 0) {
+        result = respBufSz;
+    }
+    else {
+        WOLFSSL_ERROR(result);
+    }
+
+    return result;
+}
+int wolfIO_HttpBuildRequest(const char *reqType, const char *domainName,
+                               const char *path, int pathLen, int reqSz, const char *contentType,
+                               byte *buf, int bufSize)
+{
+    return wolfIO_HttpBuildRequest_ex(reqType, domainName, path, pathLen, reqSz, contentType, "", buf, bufSize);
+}
+
+    int wolfIO_HttpBuildRequest_ex(const char *reqType, const char *domainName,
+                                const char *path, int pathLen, int reqSz, const char *contentType,
+                                const char *exHdrs, byte *buf, int bufSize)
+    {
+    word32 reqTypeLen, domainNameLen, reqSzStrLen, contentTypeLen, exHdrsLen, maxLen;
+    char reqSzStr[6];
+    char* req = (char*)buf;
+    const char* blankStr = " ";
+    const char* http11Str = " HTTP/1.1";
+    const char* hostStr = "\r\nHost: ";
+    const char* contentLenStr = "\r\nContent-Length: ";
+    const char* contentTypeStr = "\r\nContent-Type: ";
+    const char* singleCrLfStr = "\r\n";
+    const char* doubleCrLfStr = "\r\n\r\n";
+    word32 blankStrLen, http11StrLen, hostStrLen, contentLenStrLen,
+        contentTypeStrLen, singleCrLfStrLen, doubleCrLfStrLen;
+
+    reqTypeLen = (word32)XSTRLEN(reqType);
+    domainNameLen = (word32)XSTRLEN(domainName);
+    reqSzStrLen = wolfIO_Word16ToString(reqSzStr, (word16)reqSz);
+    contentTypeLen = (word32)XSTRLEN(contentType);
+
+    blankStrLen = (word32)XSTRLEN(blankStr);
+    http11StrLen = (word32)XSTRLEN(http11Str);
+    hostStrLen = (word32)XSTRLEN(hostStr);
+    contentLenStrLen = (word32)XSTRLEN(contentLenStr);
+    contentTypeStrLen = (word32)XSTRLEN(contentTypeStr);
+
+    if(exHdrs){
+        singleCrLfStrLen = (word32)XSTRLEN(singleCrLfStr);
+        exHdrsLen = (word32)XSTRLEN(exHdrs);
+    } else {
+        singleCrLfStrLen = 0;
+        exHdrsLen = 0;
+    }
+
+    doubleCrLfStrLen = (word32)XSTRLEN(doubleCrLfStr);
+
+    /* determine max length and check it */
+    maxLen =
+        reqTypeLen +
+        blankStrLen +
+        pathLen +
+        http11StrLen +
+        hostStrLen +
+        domainNameLen +
+        contentLenStrLen +
+        reqSzStrLen +
+        contentTypeStrLen +
+        contentTypeLen +
+        singleCrLfStrLen +
+        exHdrsLen +
+        doubleCrLfStrLen +
+        1 /* null term */;
+    if (maxLen > (word32)bufSize)
+        return 0;
+
+    XSTRNCPY((char*)buf, reqType, bufSize);
+    buf += reqTypeLen; bufSize -= reqTypeLen;
+    XSTRNCPY((char*)buf, blankStr, bufSize);
+    buf += blankStrLen; bufSize -= blankStrLen;
+    XSTRNCPY((char*)buf, path, bufSize);
+    buf += pathLen; bufSize -= pathLen;
+    XSTRNCPY((char*)buf, http11Str, bufSize);
+    buf += http11StrLen; bufSize -= http11StrLen;
+    if (domainNameLen > 0) {
+        XSTRNCPY((char*)buf, hostStr, bufSize);
+        buf += hostStrLen; bufSize -= hostStrLen;
+        XSTRNCPY((char*)buf, domainName, bufSize);
+        buf += domainNameLen; bufSize -= domainNameLen;
+    }
+    if (reqSz > 0 && reqSzStrLen > 0) {
+        XSTRNCPY((char*)buf, contentLenStr, bufSize);
+        buf += contentLenStrLen; bufSize -= contentLenStrLen;
+        XSTRNCPY((char*)buf, reqSzStr, bufSize);
+        buf += reqSzStrLen; bufSize -= reqSzStrLen;
+    }
+    if (contentTypeLen > 0) {
+        XSTRNCPY((char*)buf, contentTypeStr, bufSize);
+        buf += contentTypeStrLen; bufSize -= contentTypeStrLen;
+        XSTRNCPY((char*)buf, contentType, bufSize);
+        buf += contentTypeLen; bufSize -= contentTypeLen;
+    }
+    if (exHdrsLen > 0)
+    {
+        XSTRNCPY((char *)buf, singleCrLfStr, bufSize);
+        buf += singleCrLfStrLen;
+        bufSize -= singleCrLfStrLen;
+        XSTRNCPY((char *)buf, exHdrs, bufSize);
+        buf += exHdrsLen;
+        bufSize -= exHdrsLen;
+    }
+    XSTRNCPY((char*)buf, doubleCrLfStr, bufSize);
+    buf += doubleCrLfStrLen;
+
+#ifdef WOLFIO_DEBUG
+    printf("HTTP %s: %s", reqType, req);
+#endif
+
+    /* calculate actual length based on original and new pointer */
+    return (int)((char*)buf - req);
+}
+
+
+#ifdef HAVE_OCSP
+
+int wolfIO_HttpBuildRequestOcsp(const char* domainName, const char* path,
+                                    int ocspReqSz, byte* buf, int bufSize)
+{
+    const char *cacheCtl = "Cache-Control: no-cache";
+    return wolfIO_HttpBuildRequest_ex("POST", domainName, path, (int)XSTRLEN(path),
+        ocspReqSz, "application/ocsp-request", cacheCtl, buf, bufSize);
+}
+
+/* return: >0 OCSP Response Size
+ *         -1 error */
+int wolfIO_HttpProcessResponseOcsp(int sfd, byte** respBuf,
+                                       byte* httpBuf, int httpBufSz, void* heap)
+{
+    const char* appStrList[] = {
+        "application/ocsp-response",
+        NULL
+    };
+
+    return wolfIO_HttpProcessResponse(sfd, appStrList,
+        respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_OCSP, heap);
+}
+
+/* in default wolfSSL callback ctx is the heap pointer */
+int EmbedOcspLookup(void* ctx, const char* url, int urlSz,
+                        byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf)
+{
+    SOCKET_T sfd = 0;
+    word16   port;
+    int      ret = -1;
+#ifdef WOLFSSL_SMALL_STACK
+    char*    path;
+    char*    domainName;
+#else
+    char     path[MAX_URL_ITEM_SIZE];
+    char     domainName[MAX_URL_ITEM_SIZE];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+    path = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (path == NULL)
+        return MEMORY_E;
+
+    domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL,
+            DYNAMIC_TYPE_TMP_BUFFER);
+    if (domainName == NULL) {
+        XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return MEMORY_E;
+    }
+#endif
+
+    if (ocspReqBuf == NULL || ocspReqSz == 0) {
+        WOLFSSL_MSG("OCSP request is required for lookup");
+    }
+    else if (ocspRespBuf == NULL) {
+        WOLFSSL_MSG("Cannot save OCSP response");
+    }
+    else if (wolfIO_DecodeUrl(url, urlSz, domainName, path, &port) < 0) {
+        WOLFSSL_MSG("Unable to decode OCSP URL");
+    }
+    else {
+        /* Note, the library uses the EmbedOcspRespFree() callback to
+         * free this buffer. */
+        int   httpBufSz = HTTP_SCRATCH_BUFFER_SIZE;
+        byte* httpBuf   = (byte*)XMALLOC(httpBufSz, ctx, DYNAMIC_TYPE_OCSP);
+
+        if (httpBuf == NULL) {
+            WOLFSSL_MSG("Unable to create OCSP response buffer");
+        }
+        else {
+            httpBufSz = wolfIO_HttpBuildRequestOcsp(domainName, path, ocspReqSz,
+                                                            httpBuf, httpBufSz);
+
+            ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec);
+            if ((ret != 0) || ((int)sfd < 0)) {
+                WOLFSSL_MSG("OCSP Responder connection failed");
+            }
+            else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0) !=
+                                                                    httpBufSz) {
+                WOLFSSL_MSG("OCSP http request failed");
+            }
+            else if (wolfIO_Send(sfd, (char*)ocspReqBuf, ocspReqSz, 0) !=
+                                                                    ocspReqSz) {
+                WOLFSSL_MSG("OCSP ocsp request failed");
+            }
+            else {
+                ret = wolfIO_HttpProcessResponseOcsp(sfd, ocspRespBuf, httpBuf,
+                                                 HTTP_SCRATCH_BUFFER_SIZE, ctx);
+            }
+
+            CloseSocket(sfd);
+            XFREE(httpBuf, ctx, DYNAMIC_TYPE_OCSP);
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(path,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(domainName, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return ret;
+}
+
+/* in default callback ctx is heap hint */
+void EmbedOcspRespFree(void* ctx, byte *resp)
+{
+    if (resp)
+        XFREE(resp, ctx, DYNAMIC_TYPE_OCSP);
+
+    (void)ctx;
+}
+#endif /* HAVE_OCSP */
+
+
+#if defined(HAVE_CRL) && defined(HAVE_CRL_IO)
+
+int wolfIO_HttpBuildRequestCrl(const char* url, int urlSz,
+    const char* domainName, byte* buf, int bufSize)
+{
+    const char *cacheCtl = "Cache-Control: no-cache";
+    return wolfIO_HttpBuildRequest_ex("GET", domainName, url, urlSz, 0, "",
+                                   cacheCtl, buf, bufSize);
+}
+
+int wolfIO_HttpProcessResponseCrl(WOLFSSL_CRL* crl, int sfd, byte* httpBuf,
+    int httpBufSz)
+{
+    int result;
+    byte *respBuf = NULL;
+
+    const char* appStrList[] = {
+        "application/pkix-crl",
+        "application/x-pkcs7-crl",
+        NULL
+    };
+
+    result = wolfIO_HttpProcessResponse(sfd, appStrList,
+        &respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_CRL, crl->heap);
+    if (result >= 0) {
+        result = BufferLoadCRL(crl, respBuf, result, WOLFSSL_FILETYPE_ASN1, 0);
+    }
+    XFREE(respBuf, crl->heap, DYNAMIC_TYPE_CRL);
+
+    return result;
+}
+
+int EmbedCrlLookup(WOLFSSL_CRL* crl, const char* url, int urlSz)
+{
+    SOCKET_T sfd = 0;
+    word16   port;
+    int      ret = -1;
+#ifdef WOLFSSL_SMALL_STACK
+    char*    domainName;
+#else
+    char     domainName[MAX_URL_ITEM_SIZE];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+    domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, crl->heap,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+    if (domainName == NULL) {
+        return MEMORY_E;
+    }
+#endif
+
+    if (wolfIO_DecodeUrl(url, urlSz, domainName, NULL, &port) < 0) {
+        WOLFSSL_MSG("Unable to decode CRL URL");
+    }
+    else {
+        int   httpBufSz = HTTP_SCRATCH_BUFFER_SIZE;
+        byte* httpBuf   = (byte*)XMALLOC(httpBufSz, crl->heap,
+                                                              DYNAMIC_TYPE_CRL);
+        if (httpBuf == NULL) {
+            WOLFSSL_MSG("Unable to create CRL response buffer");
+        }
+        else {
+            httpBufSz = wolfIO_HttpBuildRequestCrl(url, urlSz, domainName,
+                httpBuf, httpBufSz);
+
+            ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec);
+            if ((ret != 0) || (sfd < 0)) {
+                WOLFSSL_MSG("CRL connection failed");
+            }
+            else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0)
+                                                                 != httpBufSz) {
+                WOLFSSL_MSG("CRL http get failed");
+            }
+            else {
+                ret = wolfIO_HttpProcessResponseCrl(crl, sfd, httpBuf,
+                                                      HTTP_SCRATCH_BUFFER_SIZE);
+            }
+
+            CloseSocket(sfd);
+            XFREE(httpBuf, crl->heap, DYNAMIC_TYPE_CRL);
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(domainName, crl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return ret;
+}
+#endif /* HAVE_CRL && HAVE_CRL_IO */
+
+#endif /* HAVE_HTTP_CLIENT */
+
+
+
+void wolfSSL_CTX_SetIORecv(WOLFSSL_CTX *ctx, CallbackIORecv CBIORecv)
+{
+    if (ctx) {
+        ctx->CBIORecv = CBIORecv;
+    #ifdef OPENSSL_EXTRA
+        ctx->cbioFlag |= WOLFSSL_CBIO_RECV;
+    #endif
+    }
+}
+
+
+void wolfSSL_CTX_SetIOSend(WOLFSSL_CTX *ctx, CallbackIOSend CBIOSend)
+{
+    if (ctx) {
+        ctx->CBIOSend = CBIOSend;
+    #ifdef OPENSSL_EXTRA
+        ctx->cbioFlag |= WOLFSSL_CBIO_SEND;
+    #endif
+    }
+}
+
+
+/* sets the IO callback to use for receives at WOLFSSL level */
+void wolfSSL_SSLSetIORecv(WOLFSSL *ssl, CallbackIORecv CBIORecv)
+{
+    if (ssl) {
+        ssl->CBIORecv = CBIORecv;
+    #ifdef OPENSSL_EXTRA
+        ssl->cbioFlag |= WOLFSSL_CBIO_RECV;
+    #endif
+    }
+}
+
+
+/* sets the IO callback to use for sends at WOLFSSL level */
+void wolfSSL_SSLSetIOSend(WOLFSSL *ssl, CallbackIOSend CBIOSend)
+{
+    if (ssl) {
+        ssl->CBIOSend = CBIOSend;
+    #ifdef OPENSSL_EXTRA
+        ssl->cbioFlag |= WOLFSSL_CBIO_SEND;
+    #endif
+    }
+}
+
+
+void wolfSSL_SetIOReadCtx(WOLFSSL* ssl, void *rctx)
+{
+    if (ssl)
+        ssl->IOCB_ReadCtx = rctx;
+}
+
+
+void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *wctx)
+{
+    if (ssl)
+        ssl->IOCB_WriteCtx = wctx;
+}
+
+
+void* wolfSSL_GetIOReadCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->IOCB_ReadCtx;
+
+    return NULL;
+}
+
+
+void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->IOCB_WriteCtx;
+
+    return NULL;
+}
+
+
+void wolfSSL_SetIOReadFlags(WOLFSSL* ssl, int flags)
+{
+    if (ssl)
+        ssl->rflags = flags;
+}
+
+
+void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags)
+{
+    if (ssl)
+        ssl->wflags = flags;
+}
+
+
+#ifdef WOLFSSL_DTLS
+
+void wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX* ctx, CallbackGenCookie cb)
+{
+    if (ctx)
+        ctx->CBIOCookie = cb;
+}
+
+
+void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->IOCB_CookieCtx = ctx;
+}
+
+
+void* wolfSSL_GetCookieCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->IOCB_CookieCtx;
+
+    return NULL;
+}
+
+#ifdef WOLFSSL_SESSION_EXPORT
+
+void wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX* ctx, CallbackGetPeer cb)
+{
+    if (ctx)
+        ctx->CBGetPeer = cb;
+}
+
+
+void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX* ctx, CallbackSetPeer cb)
+{
+    if (ctx)
+        ctx->CBSetPeer = cb;
+}
+
+#endif /* WOLFSSL_SESSION_EXPORT */
+#endif /* WOLFSSL_DTLS */
+
+
+#ifdef HAVE_NETX
+
+/* The NetX receive callback
+ *  return :  bytes read, or error
+ */
+int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
+{
+    NetX_Ctx* nxCtx = (NetX_Ctx*)ctx;
+    ULONG left;
+    ULONG total;
+    ULONG copied = 0;
+    UINT  status;
+
+    (void)ssl;
+
+    if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
+        WOLFSSL_MSG("NetX Recv NULL parameters");
+        return WOLFSSL_CBIO_ERR_GENERAL;
+    }
+
+    if (nxCtx->nxPacket == NULL) {
+        status = nx_tcp_socket_receive(nxCtx->nxSocket, &nxCtx->nxPacket,
+                                       nxCtx->nxWait);
+        if (status != NX_SUCCESS) {
+            WOLFSSL_MSG("NetX Recv receive error");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+    }
+
+    if (nxCtx->nxPacket) {
+        status = nx_packet_length_get(nxCtx->nxPacket, &total);
+        if (status != NX_SUCCESS) {
+            WOLFSSL_MSG("NetX Recv length get error");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+
+        left = total - nxCtx->nxOffset;
+        status = nx_packet_data_extract_offset(nxCtx->nxPacket, nxCtx->nxOffset,
+                                               buf, sz, &copied);
+        if (status != NX_SUCCESS) {
+            WOLFSSL_MSG("NetX Recv data extract offset error");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+
+        nxCtx->nxOffset += copied;
+
+        if (copied == left) {
+            WOLFSSL_MSG("NetX Recv Drained packet");
+            nx_packet_release(nxCtx->nxPacket);
+            nxCtx->nxPacket = NULL;
+            nxCtx->nxOffset = 0;
+        }
+    }
+
+    return copied;
+}
+
+
+/* The NetX send callback
+ *  return : bytes sent, or error
+ */
+int NetX_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx)
+{
+    NetX_Ctx*       nxCtx = (NetX_Ctx*)ctx;
+    NX_PACKET*      packet;
+    NX_PACKET_POOL* pool;   /* shorthand */
+    UINT            status;
+
+    (void)ssl;
+
+    if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
+        WOLFSSL_MSG("NetX Send NULL parameters");
+        return WOLFSSL_CBIO_ERR_GENERAL;
+    }
+
+    pool = nxCtx->nxSocket->nx_tcp_socket_ip_ptr->nx_ip_default_packet_pool;
+    status = nx_packet_allocate(pool, &packet, NX_TCP_PACKET,
+                                nxCtx->nxWait);
+    if (status != NX_SUCCESS) {
+        WOLFSSL_MSG("NetX Send packet alloc error");
+        return WOLFSSL_CBIO_ERR_GENERAL;
+    }
+
+    status = nx_packet_data_append(packet, buf, sz, pool, nxCtx->nxWait);
+    if (status != NX_SUCCESS) {
+        nx_packet_release(packet);
+        WOLFSSL_MSG("NetX Send data append error");
+        return WOLFSSL_CBIO_ERR_GENERAL;
+    }
+
+    status = nx_tcp_socket_send(nxCtx->nxSocket, packet, nxCtx->nxWait);
+    if (status != NX_SUCCESS) {
+        nx_packet_release(packet);
+        WOLFSSL_MSG("NetX Send socket send error");
+        return WOLFSSL_CBIO_ERR_GENERAL;
+    }
+
+    return sz;
+}
+
+
+/* like set_fd, but for default NetX context */
+void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxSocket, ULONG waitOption)
+{
+    if (ssl) {
+        ssl->nxCtx.nxSocket = nxSocket;
+        ssl->nxCtx.nxWait   = waitOption;
+    }
+}
+
+#endif /* HAVE_NETX */
+
+
+#ifdef MICRIUM
+
+/* Micrium uTCP/IP port, using the NetSock API
+ * TCP and UDP are currently supported with the callbacks below.
+ *
+ * WOLFSSL_SESSION_EXPORT is not yet supported, would need EmbedGetPeer()
+ * and EmbedSetPeer() callbacks implemented.
+ *
+ * HAVE_CRL is not yet supported, would need an EmbedCrlLookup()
+ * callback implemented.
+ *
+ * HAVE_OCSP is not yet supported, would need an EmbedOCSPLookup()
+ * callback implemented.
+ */
+
+/* The Micrium uTCP/IP send callback
+ * return : bytes sent, or error
+ */
+int MicriumSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
+{
+    NET_SOCK_ID sd = *(int*)ctx;
+    NET_SOCK_RTN_CODE ret;
+    NET_ERR err;
+
+    ret = NetSock_TxData(sd, buf, sz, ssl->wflags, &err);
+    if (ret < 0) {
+        WOLFSSL_MSG("Embed Send error");
+
+        if (err == NET_ERR_TX) {
+            WOLFSSL_MSG("\tWould block");
+            return WOLFSSL_CBIO_ERR_WANT_WRITE;
+
+        } else {
+            WOLFSSL_MSG("\tGeneral error");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+    }
+
+    return ret;
+}
+
+/* The Micrium uTCP/IP receive callback
+ *  return : nb bytes read, or error
+ */
+int MicriumReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
+{
+    NET_SOCK_ID sd = *(int*)ctx;
+    NET_SOCK_RTN_CODE ret;
+    NET_ERR err;
+
+#ifdef WOLFSSL_DTLS
+    {
+        int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
+        if (wolfSSL_dtls(ssl)
+                     && !wolfSSL_dtls_get_using_nonblock(ssl)
+                     && dtls_timeout != 0) {
+            /* needs timeout in milliseconds */
+            NetSock_CfgTimeoutRxQ_Set(sd, dtls_timeout * 1000, &err);
+            if (err != NET_SOCK_ERR_NONE) {
+                WOLFSSL_MSG("NetSock_CfgTimeoutRxQ_Set failed");
+            }
+        }
+    }
+#endif
+
+    ret = NetSock_RxData(sd, buf, sz, ssl->rflags, &err);
+    if (ret < 0) {
+        WOLFSSL_MSG("Embed Receive error");
+
+        if (err == NET_ERR_RX || err == NET_SOCK_ERR_RX_Q_EMPTY ||
+            err == NET_ERR_FAULT_LOCK_ACQUIRE) {
+            if (!wolfSSL_dtls(ssl) || wolfSSL_dtls_get_using_nonblock(ssl)) {
+                WOLFSSL_MSG("\tWould block");
+                return WOLFSSL_CBIO_ERR_WANT_READ;
+            }
+            else {
+                WOLFSSL_MSG("\tSocket timeout");
+                return WOLFSSL_CBIO_ERR_TIMEOUT;
+            }
+
+        } else if (err == NET_SOCK_ERR_CLOSED) {
+            WOLFSSL_MSG("Embed receive connection closed");
+            return WOLFSSL_CBIO_ERR_CONN_CLOSE;
+
+        } else {
+            WOLFSSL_MSG("\tGeneral error");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+    }
+
+    return ret;
+}
+
+/* The Micrium uTCP/IP receivefrom callback
+ *  return : nb bytes read, or error
+ */
+int MicriumReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
+{
+    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
+    NET_SOCK_ID       sd = dtlsCtx->rfd;
+    NET_SOCK_ADDR     peer;
+    NET_SOCK_ADDR_LEN peerSz = sizeof(peer);
+    NET_SOCK_RTN_CODE ret;
+    NET_ERR err;
+    int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
+
+    WOLFSSL_ENTER("MicriumReceiveFrom()");
+
+    if (ssl->options.handShakeDone)
+        dtls_timeout = 0;
+
+    if (!wolfSSL_dtls_get_using_nonblock(ssl)) {
+        /* needs timeout in milliseconds */
+        NetSock_CfgTimeoutRxQ_Set(sd, dtls_timeout * 1000, &err);
+        if (err != NET_SOCK_ERR_NONE) {
+            WOLFSSL_MSG("NetSock_CfgTimeoutRxQ_Set failed");
+        }
+    }
+
+    ret = NetSock_RxDataFrom(sd, buf, sz, ssl->rflags, &peer, &peerSz,
+                             0, 0, 0, &err);
+    if (ret < 0) {
+        WOLFSSL_MSG("Embed Receive From error");
+
+        if (err == NET_ERR_RX || err == NET_SOCK_ERR_RX_Q_EMPTY ||
+            err == NET_ERR_FAULT_LOCK_ACQUIRE) {
+            if (wolfSSL_dtls_get_using_nonblock(ssl)) {
+                WOLFSSL_MSG("\tWould block");
+                return WOLFSSL_CBIO_ERR_WANT_READ;
+            }
+            else {
+                WOLFSSL_MSG("\tSocket timeout");
+                return WOLFSSL_CBIO_ERR_TIMEOUT;
+            }
+        } else {
+            WOLFSSL_MSG("\tGeneral error");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+    }
+    else {
+        if (dtlsCtx->peer.sz > 0
+                && peerSz != (NET_SOCK_ADDR_LEN)dtlsCtx->peer.sz
+                && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) {
+            WOLFSSL_MSG("\tIgnored packet from invalid peer");
+            return WOLFSSL_CBIO_ERR_WANT_READ;
+        }
+    }
+
+    return ret;
+}
+
+/* The Micrium uTCP/IP sendto callback
+ *  return : nb bytes sent, or error
+ */
+int MicriumSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
+{
+    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
+    NET_SOCK_ID sd = dtlsCtx->wfd;
+    NET_SOCK_RTN_CODE ret;
+    NET_ERR err;
+
+    WOLFSSL_ENTER("MicriumSendTo()");
+
+    ret = NetSock_TxDataTo(sd, buf, sz, ssl->wflags,
+                           (NET_SOCK_ADDR*)dtlsCtx->peer.sa,
+                           (NET_SOCK_ADDR_LEN)dtlsCtx->peer.sz,
+                           &err);
+    if (err < 0) {
+        WOLFSSL_MSG("Embed Send To error");
+
+        if (err == NET_ERR_TX) {
+            WOLFSSL_MSG("\tWould block");
+            return WOLFSSL_CBIO_ERR_WANT_WRITE;
+
+        } else {
+            WOLFSSL_MSG("\tGeneral error");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+    }
+
+    return ret;
+}
+
+/* Micrium DTLS Generate Cookie callback
+ *  return : number of bytes copied into buf, or error
+ */
+int MicriumGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx)
+{
+    NET_SOCK_ADDR peer;
+    NET_SOCK_ADDR_LEN peerSz = sizeof(peer);
+    byte digest[WC_SHA_DIGEST_SIZE];
+    int  ret = 0;
+
+    (void)ctx;
+
+    XMEMSET(&peer, 0, sizeof(peer));
+    if (wolfSSL_dtls_get_peer(ssl, (void*)&peer,
+                              (unsigned int*)&peerSz) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("getpeername failed in MicriumGenerateCookie");
+        return GEN_COOKIE_E;
+    }
+
+    ret = wc_ShaHash((byte*)&peer, peerSz, digest);
+    if (ret != 0)
+        return ret;
+
+    if (sz > WC_SHA_DIGEST_SIZE)
+        sz = WC_SHA_DIGEST_SIZE;
+    XMEMCPY(buf, digest, sz);
+
+    return sz;
+}
+
+#endif /* MICRIUM */
+
+#if defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP)
+
+#include <os/os_error.h>
+#include <os/os_mbuf.h>
+#include <os/os_mempool.h>
+
+#define MB_NAME "wolfssl_mb"
+
+typedef struct Mynewt_Ctx {
+        struct mn_socket *mnSocket;          /* send/recv socket handler */
+        struct mn_sockaddr_in mnSockAddrIn;  /* socket address */
+        struct os_mbuf *mnPacket;            /* incoming packet handle
+                                                for short reads */
+        int reading;                         /* reading flag */
+
+        /* private */
+        void *mnMemBuffer;                   /* memory buffer for mempool */
+        struct os_mempool mnMempool;         /* mempool */
+        struct os_mbuf_pool mnMbufpool;      /* mbuf pool */
+} Mynewt_Ctx;
+
+void mynewt_ctx_clear(void *ctx) {
+    Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx*)ctx;
+    if(!mynewt_ctx) return;
+
+    if(mynewt_ctx->mnPacket) {
+        os_mbuf_free_chain(mynewt_ctx->mnPacket);
+        mynewt_ctx->mnPacket = NULL;
+    }
+    os_mempool_clear(&mynewt_ctx->mnMempool);
+    XFREE(mynewt_ctx->mnMemBuffer, 0, 0);
+    XFREE(mynewt_ctx, 0, 0);
+}
+
+/* return Mynewt_Ctx instance */
+void* mynewt_ctx_new() {
+    int rc = 0;
+    Mynewt_Ctx *mynewt_ctx;
+    int mem_buf_count = MYNEWT_VAL(WOLFSSL_MNSOCK_MEM_BUF_COUNT);
+    int mem_buf_size = MYNEWT_VAL(WOLFSSL_MNSOCK_MEM_BUF_SIZE);
+    int mempool_bytes = OS_MEMPOOL_BYTES(mem_buf_count, mem_buf_size);
+
+    mynewt_ctx = (Mynewt_Ctx *)XMALLOC(sizeof(struct Mynewt_Ctx),
+                                       NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if(!mynewt_ctx) return NULL;
+
+    XMEMSET(mynewt_ctx, 0, sizeof(Mynewt_Ctx));
+    mynewt_ctx->mnMemBuffer = XMALLOC(mempool_bytes, 0, 0);
+    if(!mynewt_ctx->mnMemBuffer) {
+        mynewt_ctx_clear((void*)mynewt_ctx);
+        return NULL;
+    }
+
+    rc = os_mempool_init(&mynewt_ctx->mnMempool,
+                         mem_buf_count, mem_buf_size,
+                         mynewt_ctx->mnMemBuffer, MB_NAME);
+    if(rc != 0) {
+        mynewt_ctx_clear((void*)mynewt_ctx);
+        return NULL;
+    }
+    rc = os_mbuf_pool_init(&mynewt_ctx->mnMbufpool, &mynewt_ctx->mnMempool,
+                           mem_buf_count, mem_buf_size);
+    if(rc != 0) {
+        mynewt_ctx_clear((void*)mynewt_ctx);
+        return NULL;
+    }
+
+    return mynewt_ctx;
+}
+
+static void mynewt_sock_writable(void *arg, int err);
+static void mynewt_sock_readable(void *arg, int err);
+static const union mn_socket_cb mynewt_sock_cbs = {
+    .socket.writable = mynewt_sock_writable,
+    .socket.readable = mynewt_sock_readable,
+};
+static void mynewt_sock_writable(void *arg, int err)
+{
+    /* do nothing */
+}
+static void mynewt_sock_readable(void *arg, int err)
+{
+    Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx *)arg;
+    if (err && mynewt_ctx->reading) {
+        mynewt_ctx->reading = 0;
+    }
+}
+
+/* The Mynewt receive callback
+ *  return :  bytes read, or error
+ */
+int Mynewt_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
+{
+    Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx*)ctx;
+    int rc = 0;
+    struct mn_sockaddr_in from;
+    struct os_mbuf *m;
+    int read_sz = 0;
+    uint16_t total;
+
+    if (mynewt_ctx == NULL || mynewt_ctx->mnSocket == NULL) {
+        WOLFSSL_MSG("Mynewt Recv NULL parameters");
+        return WOLFSSL_CBIO_ERR_GENERAL;
+    }
+
+    if(mynewt_ctx->mnPacket == NULL) {
+        mynewt_ctx->mnPacket = os_mbuf_get_pkthdr(&mynewt_ctx->mnMbufpool, 0);
+        if(mynewt_ctx->mnPacket == NULL) {
+            return MEMORY_E;
+        }
+
+        mynewt_ctx->reading = 1;
+        while(mynewt_ctx->reading && rc == 0) {
+            rc = mn_recvfrom(mynewt_ctx->mnSocket, &m, (struct mn_sockaddr *) &from);
+            if(rc == MN_ECONNABORTED) {
+                rc = 0;
+                mynewt_ctx->reading = 0;
+                break;
+            }
+            if (!(rc == 0 || rc == MN_EAGAIN)) {
+                WOLFSSL_MSG("Mynewt Recv receive error");
+                mynewt_ctx->reading = 0;
+                break;
+            }
+            if(rc == 0) {
+                int len = OS_MBUF_PKTLEN(m);
+                if(len == 0) {
+                    break;
+                }
+                rc = os_mbuf_appendfrom(mynewt_ctx->mnPacket, m, 0, len);
+                if(rc != 0) {
+                    WOLFSSL_MSG("Mynewt Recv os_mbuf_appendfrom error");
+                    break;
+                }
+                os_mbuf_free_chain(m);
+                m = NULL;
+            } else if(rc == MN_EAGAIN) {
+                /* continue to until reading all of packet data. */
+                rc = 0;
+                break;
+            }
+        }
+        if(rc != 0) {
+            mynewt_ctx->reading = 0;
+            os_mbuf_free_chain(mynewt_ctx->mnPacket);
+            mynewt_ctx->mnPacket = NULL;
+            return rc;
+        }
+    }
+
+    if(mynewt_ctx->mnPacket) {
+        total = OS_MBUF_PKTLEN(mynewt_ctx->mnPacket);
+        read_sz = (total >= sz)? sz : total;
+
+        os_mbuf_copydata(mynewt_ctx->mnPacket, 0, read_sz, (void*)buf);
+        os_mbuf_adj(mynewt_ctx->mnPacket, read_sz);
+
+        if (read_sz == total) {
+            WOLFSSL_MSG("Mynewt Recv Drained packet");
+            os_mbuf_free_chain(mynewt_ctx->mnPacket);
+            mynewt_ctx->mnPacket = NULL;
+        }
+    }
+
+    return read_sz;
+}
+
+/* The Mynewt send callback
+ *  return : bytes sent, or error
+ */
+int Mynewt_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx)
+{
+    Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx*)ctx;
+    int rc = 0;
+    struct os_mbuf *m;
+    int write_sz = 0;
+    m = os_msys_get_pkthdr(sz, 0);
+    if (!m) {
+        WOLFSSL_MSG("Mynewt Send os_msys_get_pkthdr error");
+        return WOLFSSL_CBIO_ERR_GENERAL;
+    }
+    rc = os_mbuf_copyinto(m, 0, buf, sz);
+    if (rc != 0) {
+        WOLFSSL_MSG("Mynewt Send os_mbuf_copyinto error");
+        os_mbuf_free_chain(m);
+        return rc;
+    }
+    rc = mn_sendto(mynewt_ctx->mnSocket, m, (struct mn_sockaddr *)&mynewt_ctx->mnSockAddrIn);
+    if(rc != 0) {
+        WOLFSSL_MSG("Mynewt Send mn_sendto error");
+        os_mbuf_free_chain(m);
+        return rc;
+    }
+    write_sz = sz;
+    return write_sz;
+}
+
+/* like set_fd, but for default NetX context */
+void wolfSSL_SetIO_Mynewt(WOLFSSL* ssl, struct mn_socket* mnSocket, struct mn_sockaddr_in* mnSockAddrIn)
+{
+    if (ssl && ssl->mnCtx) {
+        Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx *)ssl->mnCtx;
+        mynewt_ctx->mnSocket = mnSocket;
+        memcpy(&mynewt_ctx->mnSockAddrIn, mnSockAddrIn, sizeof(struct mn_sockaddr_in));
+        mn_socket_set_cbs(mynewt_ctx->mnSocket, mnSocket, &mynewt_sock_cbs);
+    }
+}
+
+#endif /* defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) */
+
+#ifdef WOLFSSL_UIP
+#include <uip.h>
+#include <stdio.h>
+
+/* uIP TCP/IP port, using the native tcp/udp socket api.
+ * TCP and UDP are currently supported with the callbacks below.
+ *
+ */
+/* The uIP tcp send callback
+ * return : bytes sent, or error
+ */
+int uIPSend(WOLFSSL* ssl, char* buf, int sz, void* _ctx)
+{
+    uip_wolfssl_ctx *ctx = (struct uip_wolfssl_ctx *)_ctx;
+    int ret;
+    unsigned int max_sendlen;
+    int total_written = 0;
+    (void)ssl;
+    do {
+        unsigned int bytes_left = sz - total_written;
+        max_sendlen = tcp_socket_max_sendlen(&ctx->conn.tcp);
+        if (bytes_left > max_sendlen) {
+            printf("Send limited by buffer\r\n");
+            bytes_left = max_sendlen;
+        }
+        if (bytes_left == 0) {
+            printf("Buffer full!\r\n");
+            break;
+        }
+        ret = tcp_socket_send(&ctx->conn.tcp, (unsigned char *)buf + total_written, bytes_left);
+        if (ret <= 0)
+            break;
+        total_written += ret;
+    } while(total_written < sz);
+    if (total_written == 0)
+        return WOLFSSL_CBIO_ERR_WANT_WRITE;
+    return total_written;
+}
+
+int uIPSendTo(WOLFSSL* ssl, char* buf, int sz, void* _ctx)
+{
+    uip_wolfssl_ctx *ctx = (struct uip_wolfssl_ctx *)_ctx;
+    int ret = 0;
+    (void)ssl;
+    ret = udp_socket_sendto(&ctx->conn.udp, (unsigned char *)buf, sz, &ctx->peer_addr, ctx->peer_port );
+    if (ret == 0)
+        return WOLFSSL_CBIO_ERR_WANT_WRITE;
+    return ret;
+}
+
+/* The uIP uTCP/IP receive callback
+ *  return : nb bytes read, or error
+ */
+int uIPReceive(WOLFSSL *ssl, char *buf, int sz, void *_ctx)
+{
+    uip_wolfssl_ctx *ctx = (uip_wolfssl_ctx *)_ctx;
+    if (!ctx || !ctx->ssl_rx_databuf)
+        return -1;
+    (void)ssl;
+    if (ctx->ssl_rb_len > 0) {
+        if (sz > ctx->ssl_rb_len - ctx->ssl_rb_off)
+            sz = ctx->ssl_rb_len - ctx->ssl_rb_off;
+        XMEMCPY(buf, ctx->ssl_rx_databuf + ctx->ssl_rb_off, sz);
+        ctx->ssl_rb_off += sz;
+        if (ctx->ssl_rb_off >= ctx->ssl_rb_len) {
+            ctx->ssl_rb_len = 0;
+            ctx->ssl_rb_off = 0;
+        }
+        return sz;
+    } else {
+        return WOLFSSL_CBIO_ERR_WANT_READ;
+    }
+}
+
+/* uIP DTLS Generate Cookie callback
+ *  return : number of bytes copied into buf, or error
+ */
+int uIPGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *_ctx)
+{
+    uip_wolfssl_ctx *ctx = (uip_wolfssl_ctx *)_ctx;
+    byte token[32];
+    byte digest[WC_SHA_DIGEST_SIZE];
+    int  ret = 0;
+    XMEMSET(token, 0, sizeof(token));
+    XMEMCPY(token, &ctx->peer_addr, sizeof(uip_ipaddr_t));
+    XMEMCPY(token + sizeof(uip_ipaddr_t), &ctx->peer_port, sizeof(word16));
+    ret = wc_ShaHash(token, sizeof(uip_ipaddr_t) + sizeof(word16), digest);
+    if (ret != 0)
+        return ret;
+    if (sz > WC_SHA_DIGEST_SIZE)
+        sz = WC_SHA_DIGEST_SIZE;
+    XMEMCPY(buf, digest, sz);
+    return sz;
+}
+
+#endif /* WOLFSSL_UIP */
+
+#ifdef WOLFSSL_GNRC
+
+#include <net/sock.h>
+#include <net/sock/tcp.h>
+#include <stdio.h>
+
+/* GNRC TCP/IP port, using the native tcp/udp socket api.
+ * TCP and UDP are currently supported with the callbacks below.
+ *
+ */
+/* The GNRC tcp send callback
+ * return : bytes sent, or error
+ */
+
+int GNRC_SendTo(WOLFSSL* ssl, char* buf, int sz, void* _ctx)
+{
+    sock_tls_t *ctx = (sock_tls_t *)_ctx;
+    int ret = 0;
+    (void)ssl;
+    if (!ctx)
+        return WOLFSSL_CBIO_ERR_GENERAL;
+    ret = sock_udp_send(&ctx->conn.udp, (unsigned char *)buf, sz, &ctx->peer_addr);
+    if (ret == 0)
+        return WOLFSSL_CBIO_ERR_WANT_WRITE;
+    return ret;
+}
+
+/* The GNRC TCP/IP receive callback
+ *  return : nb bytes read, or error
+ */
+int GNRC_ReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *_ctx)
+{
+    sock_udp_ep_t ep;
+    int ret;
+    uint32_t timeout = wolfSSL_dtls_get_current_timeout(ssl) * 1000000;
+    sock_tls_t *ctx = (sock_tls_t *)_ctx;
+    if (!ctx)
+        return WOLFSSL_CBIO_ERR_GENERAL;
+    (void)ssl;
+    if (wolfSSL_get_using_nonblock(ctx->ssl)) {
+        timeout = 0;
+    }
+    ret = sock_udp_recv(&ctx->conn.udp, buf, sz, timeout, &ep);
+    if (ret > 0) {
+        if (ctx->peer_addr.port == 0)
+            XMEMCPY(&ctx->peer_addr, &ep, sizeof(sock_udp_ep_t));
+    }
+    if (ret == -ETIMEDOUT) {
+        return WOLFSSL_CBIO_ERR_WANT_READ;
+    }
+    return ret;
+}
+
+/* GNRC DTLS Generate Cookie callback
+ *  return : number of bytes copied into buf, or error
+ */
+#define GNRC_MAX_TOKEN_SIZE (32)
+int GNRC_GenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *_ctx)
+{
+    sock_tls_t *ctx = (sock_tls_t *)_ctx;
+    if (!ctx)
+        return WOLFSSL_CBIO_ERR_GENERAL;
+    byte token[GNRC_MAX_TOKEN_SIZE];
+    byte digest[WC_SHA_DIGEST_SIZE];
+    int  ret = 0;
+    size_t token_size = sizeof(sock_udp_ep_t);
+    (void)ssl;
+    if (token_size > GNRC_MAX_TOKEN_SIZE)
+        token_size = GNRC_MAX_TOKEN_SIZE;
+    XMEMSET(token, 0, GNRC_MAX_TOKEN_SIZE);
+    XMEMCPY(token, &ctx->peer_addr, token_size);
+    ret = wc_ShaHash(token, token_size, digest);
+    if (ret != 0)
+        return ret;
+    if (sz > WC_SHA_DIGEST_SIZE)
+        sz = WC_SHA_DIGEST_SIZE;
+    XMEMCPY(buf, digest, sz);
+    return sz;
+}
+
+#endif /* WOLFSSL_GNRC */
+
+#endif /* WOLFCRYPT_ONLY */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/user_settings.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/user_settings.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/user_settings.h	(revision 453)
@@ -0,0 +1,53 @@
+//#define DEBUG_WOLFSSL
+
+#define WOLFSSL_NO_SOCK
+#define NO_WOLFSSL_DIR
+#define NO_WRITEV
+
+#ifndef HAVE_LIBZ
+#define HAVE_LIBZ
+#endif
+#define HAVE_ECC
+#define HAVE_AESGCM
+//#define HAVE_FIPS
+#define HAVE_TLS_EXTENSIONS
+#define HAVE_SNI
+#define HAVE_SUPPORTED_CURVES
+
+#define ECC_TIMING_RESISTANT
+#define TFM_TIMING_RESISTANT
+
+#define WOLFSSL_RIPEMD
+#define WOLFSSL_SHA512
+#define WOLFSSL_SHA384
+#define WOLFSSL_SMALL_STACK
+
+#define WOLFSSL_CERT_EXT
+
+#define WC_RSA_BLINDING
+
+#define SINGLE_THREADED
+
+#define CUSTOM_RAND_GENERATE_SEED custom_rand_generate_seed
+
+#define WOLFSSL_USER_FILESYSTEM
+#include <stdio.h>
+#include <fcntl.h>
+
+#define XFILE      FILE*
+#define XFOPEN     fopen
+#define XFSEEK     fseek
+#define XFTELL     ftell
+#define XREWIND    rewind
+#define XFREAD     fread
+#define XFWRITE    fwrite
+#define XFCLOSE    fclose
+#define XSEEK_END  SEEK_END
+#define XBADFILE   NULL
+#define XFGETS     fgets
+
+struct WOLFSSL;
+int EmbedReceive(struct WOLFSSL *ssl, char *buf, int sz, void *_ctx);
+int EmbedSend(struct WOLFSSL* ssl, char* buf, int sz, void* _ctx);
+
+/* WOLFSSL_USER_FILESYSTEM */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/aes.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/aes.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/aes.c	(revision 453)
@@ -0,0 +1,8704 @@
+/* aes.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+
+#if !defined(NO_AES)
+
+/* Tip: Locate the software cipher modes by searching for "Software AES" */
+
+#if defined(HAVE_FIPS) && \
+    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
+
+    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
+    #define FIPS_NO_WRAPPERS
+
+    #ifdef USE_WINDOWS_API
+        #pragma code_seg(".fipsA$g")
+        #pragma const_seg(".fipsB$g")
+    #endif
+#endif
+
+#include <wolfssl/wolfcrypt/aes.h>
+#include <wolfssl/wolfcrypt/cpuid.h>
+
+#ifdef WOLF_CRYPTO_CB
+    #include <wolfssl/wolfcrypt/cryptocb.h>
+#endif
+
+
+/* fips wrapper calls, user can call direct */
+#if defined(HAVE_FIPS) && \
+    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
+
+    int wc_AesSetKey(Aes* aes, const byte* key, word32 len, const byte* iv,
+                              int dir)
+    {
+        if (aes == NULL ||  !( (len == 16) || (len == 24) || (len == 32)) ) {
+            return BAD_FUNC_ARG;
+        }
+
+        return AesSetKey_fips(aes, key, len, iv, dir);
+    }
+    int wc_AesSetIV(Aes* aes, const byte* iv)
+    {
+        if (aes == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        return AesSetIV_fips(aes, iv);
+    }
+    #ifdef HAVE_AES_CBC
+        int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+        {
+            if (aes == NULL || out == NULL || in == NULL) {
+                return BAD_FUNC_ARG;
+            }
+
+            return AesCbcEncrypt_fips(aes, out, in, sz);
+        }
+        #ifdef HAVE_AES_DECRYPT
+            int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+            {
+                if (aes == NULL || out == NULL || in == NULL
+                                            || sz % AES_BLOCK_SIZE != 0) {
+                    return BAD_FUNC_ARG;
+                }
+
+                return AesCbcDecrypt_fips(aes, out, in, sz);
+            }
+        #endif /* HAVE_AES_DECRYPT */
+    #endif /* HAVE_AES_CBC */
+
+    /* AES-CTR */
+    #ifdef WOLFSSL_AES_COUNTER
+        int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+        {
+            if (aes == NULL || out == NULL || in == NULL) {
+                return BAD_FUNC_ARG;
+            }
+
+            return AesCtrEncrypt(aes, out, in, sz);
+        }
+    #endif
+
+    /* AES-DIRECT */
+    #if defined(WOLFSSL_AES_DIRECT)
+        void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in)
+        {
+            AesEncryptDirect(aes, out, in);
+        }
+
+        #ifdef HAVE_AES_DECRYPT
+            void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in)
+            {
+                AesDecryptDirect(aes, out, in);
+            }
+        #endif /* HAVE_AES_DECRYPT */
+
+        int wc_AesSetKeyDirect(Aes* aes, const byte* key, word32 len,
+                                        const byte* iv, int dir)
+        {
+            return AesSetKeyDirect(aes, key, len, iv, dir);
+        }
+    #endif /* WOLFSSL_AES_DIRECT */
+
+    /* AES-GCM */
+    #ifdef HAVE_AESGCM
+        int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
+        {
+            if (aes == NULL || !( (len == 16) || (len == 24) || (len == 32)) ) {
+                return BAD_FUNC_ARG;
+            }
+
+            return AesGcmSetKey_fips(aes, key, len);
+        }
+        int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
+                                      const byte* iv, word32 ivSz,
+                                      byte* authTag, word32 authTagSz,
+                                      const byte* authIn, word32 authInSz)
+        {
+            if (aes == NULL || authTagSz > AES_BLOCK_SIZE ||
+                        authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ ||
+                        ivSz == 0 || ivSz > AES_BLOCK_SIZE) {
+                return BAD_FUNC_ARG;
+            }
+
+            return AesGcmEncrypt_fips(aes, out, in, sz, iv, ivSz, authTag,
+                authTagSz, authIn, authInSz);
+        }
+
+        #ifdef HAVE_AES_DECRYPT
+            int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
+                                          const byte* iv, word32 ivSz,
+                                          const byte* authTag, word32 authTagSz,
+                                          const byte* authIn, word32 authInSz)
+            {
+                if (aes == NULL || out == NULL || in == NULL || iv == NULL
+                        || authTag == NULL || authTagSz > AES_BLOCK_SIZE ||
+                        ivSz == 0 || ivSz > AES_BLOCK_SIZE) {
+                    return BAD_FUNC_ARG;
+                }
+
+                return AesGcmDecrypt_fips(aes, out, in, sz, iv, ivSz, authTag,
+                    authTagSz, authIn, authInSz);
+            }
+        #endif /* HAVE_AES_DECRYPT */
+
+        int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len)
+        {
+            if (gmac == NULL || key == NULL || !((len == 16) ||
+                                (len == 24) || (len == 32)) ) {
+                return BAD_FUNC_ARG;
+            }
+
+            return GmacSetKey(gmac, key, len);
+        }
+        int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz,
+                                      const byte* authIn, word32 authInSz,
+                                      byte* authTag, word32 authTagSz)
+        {
+            if (gmac == NULL || authTagSz > AES_BLOCK_SIZE ||
+                               authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) {
+                return BAD_FUNC_ARG;
+            }
+
+            return GmacUpdate(gmac, iv, ivSz, authIn, authInSz,
+                              authTag, authTagSz);
+        }
+    #endif /* HAVE_AESGCM */
+
+    /* AES-CCM */
+    #if defined(HAVE_AESCCM) && \
+        defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
+        int wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz)
+        {
+            return AesCcmSetKey(aes, key, keySz);
+        }
+        int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
+                                      const byte* nonce, word32 nonceSz,
+                                      byte* authTag, word32 authTagSz,
+                                      const byte* authIn, word32 authInSz)
+        {
+            /* sanity check on arguments */
+            if (aes == NULL || out == NULL || in == NULL || nonce == NULL
+                    || authTag == NULL || nonceSz < 7 || nonceSz > 13)
+                return BAD_FUNC_ARG;
+
+            AesCcmEncrypt(aes, out, in, inSz, nonce, nonceSz, authTag,
+                authTagSz, authIn, authInSz);
+            return 0;
+        }
+
+        #ifdef HAVE_AES_DECRYPT
+            int  wc_AesCcmDecrypt(Aes* aes, byte* out,
+                const byte* in, word32 inSz,
+                const byte* nonce, word32 nonceSz,
+                const byte* authTag, word32 authTagSz,
+                const byte* authIn, word32 authInSz)
+            {
+
+                if (aes == NULL || out == NULL || in == NULL || nonce == NULL
+                    || authTag == NULL || nonceSz < 7 || nonceSz > 13) {
+                        return BAD_FUNC_ARG;
+                }
+
+                return AesCcmDecrypt(aes, out, in, inSz, nonce, nonceSz,
+                    authTag, authTagSz, authIn, authInSz);
+            }
+        #endif /* HAVE_AES_DECRYPT */
+    #endif /* HAVE_AESCCM && HAVE_FIPS_VERSION 2 */
+
+    int wc_AesInit(Aes* aes, void* h, int i)
+    {
+        if (aes == NULL)
+            return BAD_FUNC_ARG;
+
+        (void)h;
+        (void)i;
+
+        /* FIPS doesn't support:
+            return AesInit(aes, h, i); */
+        return 0;
+    }
+    void wc_AesFree(Aes* aes)
+    {
+        (void)aes;
+        /* FIPS doesn't support:
+            AesFree(aes); */
+    }
+
+#else /* else build without fips, or for FIPS v2 */
+
+
+#if defined(WOLFSSL_TI_CRYPT)
+    #include <wolfcrypt/src/port/ti/ti-aes.c>
+#else
+
+#include <wolfssl/wolfcrypt/logging.h>
+
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+#if !defined(WOLFSSL_ARMASM)
+
+#ifdef WOLFSSL_IMX6_CAAM_BLOB
+    /* case of possibly not using hardware acceleration for AES but using key
+       blobs */
+    #include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
+#endif
+
+#ifdef DEBUG_AESNI
+    #include <stdio.h>
+#endif
+
+#ifdef _MSC_VER
+    /* 4127 warning constant while(1)  */
+    #pragma warning(disable: 4127)
+#endif
+
+
+/* Define AES implementation includes and functions */
+#if defined(STM32_CRYPTO)
+     /* STM32F2/F4/F7/L4 hardware AES support for ECB, CBC, CTR and GCM modes */
+
+#if defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AESGCM) || defined(HAVE_AESCCM)
+
+    static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock)
+    {
+        int ret = 0;
+    #ifdef WOLFSSL_STM32_CUBEMX
+        CRYP_HandleTypeDef hcryp;
+    #else
+        CRYP_InitTypeDef cryptInit;
+        CRYP_KeyInitTypeDef keyInit;
+    #endif
+
+    #ifdef WOLFSSL_STM32_CUBEMX
+        ret = wc_Stm32_Aes_Init(aes, &hcryp);
+        if (ret != 0)
+            return ret;
+
+    #ifdef STM32_CRYPTO_AES_ONLY
+        hcryp.Init.OperatingMode = CRYP_ALGOMODE_ENCRYPT;
+        hcryp.Init.ChainingMode  = CRYP_CHAINMODE_AES_ECB;
+        hcryp.Init.KeyWriteFlag  = CRYP_KEY_WRITE_ENABLE;
+    #elif defined(STM32_HAL_V2)
+        hcryp.Init.Algorithm  = CRYP_AES_ECB;
+    #endif
+        HAL_CRYP_Init(&hcryp);
+
+    #ifdef STM32_CRYPTO_AES_ONLY
+        ret = HAL_CRYPEx_AES(&hcryp, (uint8_t*)inBlock, AES_BLOCK_SIZE,
+            outBlock, STM32_HAL_TIMEOUT);
+    #elif defined(STM32_HAL_V2)
+        ret = HAL_CRYP_Encrypt(&hcryp, (uint32_t*)inBlock, AES_BLOCK_SIZE,
+            (uint32_t*)outBlock, STM32_HAL_TIMEOUT);
+    #else
+        ret = HAL_CRYP_AESECB_Encrypt(&hcryp, (uint8_t*)inBlock, AES_BLOCK_SIZE,
+            outBlock, STM32_HAL_TIMEOUT);
+    #endif
+        if (ret != HAL_OK) {
+            ret = WC_TIMEOUT_E;
+        }
+        HAL_CRYP_DeInit(&hcryp);
+
+    #else /* STD_PERI_LIB */
+        ret = wc_Stm32_Aes_Init(aes, &cryptInit, &keyInit);
+        if (ret != 0)
+            return ret;
+
+        /* reset registers to their default values */
+        CRYP_DeInit();
+
+        /* setup key */
+        CRYP_KeyInit(&keyInit);
+
+        /* set direction and mode */
+        cryptInit.CRYP_AlgoDir  = CRYP_AlgoDir_Encrypt;
+        cryptInit.CRYP_AlgoMode = CRYP_AlgoMode_AES_ECB;
+        CRYP_Init(&cryptInit);
+
+        /* enable crypto processor */
+        CRYP_Cmd(ENABLE);
+
+        /* flush IN/OUT FIFOs */
+        CRYP_FIFOFlush();
+
+        CRYP_DataIn(*(uint32_t*)&inBlock[0]);
+        CRYP_DataIn(*(uint32_t*)&inBlock[4]);
+        CRYP_DataIn(*(uint32_t*)&inBlock[8]);
+        CRYP_DataIn(*(uint32_t*)&inBlock[12]);
+
+        /* wait until the complete message has been processed */
+        while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {}
+
+        *(uint32_t*)&outBlock[0]  = CRYP_DataOut();
+        *(uint32_t*)&outBlock[4]  = CRYP_DataOut();
+        *(uint32_t*)&outBlock[8]  = CRYP_DataOut();
+        *(uint32_t*)&outBlock[12] = CRYP_DataOut();
+
+        /* disable crypto processor */
+        CRYP_Cmd(DISABLE);
+    #endif /* WOLFSSL_STM32_CUBEMX */
+
+        return ret;
+    }
+#endif /* WOLFSSL_AES_DIRECT || HAVE_AESGCM || HAVE_AESCCM */
+
+#ifdef HAVE_AES_DECRYPT
+    #if defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AESCCM)
+    static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
+    {
+        int ret = 0;
+    #ifdef WOLFSSL_STM32_CUBEMX
+        CRYP_HandleTypeDef hcryp;
+    #else
+        CRYP_InitTypeDef cryptInit;
+        CRYP_KeyInitTypeDef keyInit;
+    #endif
+
+    #ifdef WOLFSSL_STM32_CUBEMX
+        ret = wc_Stm32_Aes_Init(aes, &hcryp);
+        if (ret != 0)
+            return ret;
+
+    #ifdef STM32_CRYPTO_AES_ONLY
+        hcryp.Init.OperatingMode = CRYP_ALGOMODE_DECRYPT;
+        hcryp.Init.ChainingMode  = CRYP_CHAINMODE_AES_ECB;
+        hcryp.Init.KeyWriteFlag  = CRYP_KEY_WRITE_ENABLE;
+    #elif defined(STM32_HAL_V2)
+        hcryp.Init.Algorithm  = CRYP_AES_ECB;
+    #endif
+        HAL_CRYP_Init(&hcryp);
+
+    #ifdef STM32_CRYPTO_AES_ONLY
+        ret = HAL_CRYPEx_AES(&hcryp, (uint8_t*)inBlock, AES_BLOCK_SIZE,
+            outBlock, STM32_HAL_TIMEOUT);
+    #elif defined(STM32_HAL_V2)
+        ret = HAL_CRYP_Decrypt(&hcryp, (uint32_t*)inBlock, AES_BLOCK_SIZE,
+            (uint32_t*)outBlock, STM32_HAL_TIMEOUT);
+    #else
+        ret = HAL_CRYP_AESECB_Decrypt(&hcryp, (uint8_t*)inBlock, AES_BLOCK_SIZE,
+            outBlock, STM32_HAL_TIMEOUT);
+    #endif
+        if (ret != HAL_OK) {
+            ret = WC_TIMEOUT_E;
+        }
+        HAL_CRYP_DeInit(&hcryp);
+
+    #else /* STD_PERI_LIB */
+        ret = wc_Stm32_Aes_Init(aes, &cryptInit, &keyInit);
+        if (ret != 0)
+            return ret;
+
+        /* reset registers to their default values */
+        CRYP_DeInit();
+
+        /* set direction and key */
+        CRYP_KeyInit(&keyInit);
+        cryptInit.CRYP_AlgoDir  = CRYP_AlgoDir_Decrypt;
+        cryptInit.CRYP_AlgoMode = CRYP_AlgoMode_AES_Key;
+        CRYP_Init(&cryptInit);
+
+        /* enable crypto processor */
+        CRYP_Cmd(ENABLE);
+
+        /* wait until decrypt key has been initialized */
+        while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {}
+
+        /* set direction and mode */
+        cryptInit.CRYP_AlgoDir  = CRYP_AlgoDir_Decrypt;
+        cryptInit.CRYP_AlgoMode = CRYP_AlgoMode_AES_ECB;
+        CRYP_Init(&cryptInit);
+
+        /* enable crypto processor */
+        CRYP_Cmd(ENABLE);
+
+        /* flush IN/OUT FIFOs */
+        CRYP_FIFOFlush();
+
+        CRYP_DataIn(*(uint32_t*)&inBlock[0]);
+        CRYP_DataIn(*(uint32_t*)&inBlock[4]);
+        CRYP_DataIn(*(uint32_t*)&inBlock[8]);
+        CRYP_DataIn(*(uint32_t*)&inBlock[12]);
+
+        /* wait until the complete message has been processed */
+        while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {}
+
+        *(uint32_t*)&outBlock[0]  = CRYP_DataOut();
+        *(uint32_t*)&outBlock[4]  = CRYP_DataOut();
+        *(uint32_t*)&outBlock[8]  = CRYP_DataOut();
+        *(uint32_t*)&outBlock[12] = CRYP_DataOut();
+
+        /* disable crypto processor */
+        CRYP_Cmd(DISABLE);
+    #endif /* WOLFSSL_STM32_CUBEMX */
+
+        return ret;
+    }
+    #endif /* WOLFSSL_AES_DIRECT || HAVE_AESCCM */
+#endif /* HAVE_AES_DECRYPT */
+
+#elif defined(HAVE_COLDFIRE_SEC)
+    /* Freescale Coldfire SEC support for CBC mode.
+     * NOTE: no support for AES-CTR/GCM/CCM/Direct */
+    #include <wolfssl/wolfcrypt/types.h>
+    #include "sec.h"
+    #include "mcf5475_sec.h"
+    #include "mcf5475_siu.h"
+#elif defined(FREESCALE_LTC)
+    #include "fsl_ltc.h"
+    #if defined(FREESCALE_LTC_AES_GCM)
+        #undef NEED_AES_TABLES
+        #undef GCM_TABLE
+    #else
+        /* if LTC doesn't have GCM, use software with LTC AES ECB mode */
+        static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock)
+        {
+            wc_AesEncryptDirect(aes, outBlock, inBlock);
+            return 0;
+        }
+        static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
+        {
+            wc_AesDecryptDirect(aes, outBlock, inBlock);
+            return 0;
+        }
+    #endif
+#elif defined(FREESCALE_MMCAU)
+    /* Freescale mmCAU hardware AES support for Direct, CBC, CCM, GCM modes
+     * through the CAU/mmCAU library. Documentation located in
+     * ColdFire/ColdFire+ CAU and Kinetis mmCAU Software Library User
+     * Guide (See note in README). */
+    #ifdef FREESCALE_MMCAU_CLASSIC
+        /* MMCAU 1.4 library used with non-KSDK / classic MQX builds */
+        #include "cau_api.h"
+    #else
+        #include "fsl_mmcau.h"
+    #endif
+
+    static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock)
+    {
+        int ret;
+
+    #ifdef FREESCALE_MMCAU_CLASSIC
+        if ((wolfssl_word)outBlock % WOLFSSL_MMCAU_ALIGNMENT) {
+            WOLFSSL_MSG("Bad cau_aes_encrypt alignment");
+            return BAD_ALIGN_E;
+        }
+    #endif
+
+        ret = wolfSSL_CryptHwMutexLock();
+        if(ret == 0) {
+        #ifdef FREESCALE_MMCAU_CLASSIC
+            cau_aes_encrypt(inBlock, (byte*)aes->key, aes->rounds, outBlock);
+        #else
+            MMCAU_AES_EncryptEcb(inBlock, (byte*)aes->key, aes->rounds,
+                                 outBlock);
+        #endif
+            wolfSSL_CryptHwMutexUnLock();
+        }
+        return ret;
+    }
+    #ifdef HAVE_AES_DECRYPT
+    static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
+    {
+        int ret;
+
+    #ifdef FREESCALE_MMCAU_CLASSIC
+        if ((wolfssl_word)outBlock % WOLFSSL_MMCAU_ALIGNMENT) {
+            WOLFSSL_MSG("Bad cau_aes_decrypt alignment");
+            return BAD_ALIGN_E;
+        }
+    #endif
+
+        ret = wolfSSL_CryptHwMutexLock();
+        if(ret == 0) {
+        #ifdef FREESCALE_MMCAU_CLASSIC
+            cau_aes_decrypt(inBlock, (byte*)aes->key, aes->rounds, outBlock);
+        #else
+            MMCAU_AES_DecryptEcb(inBlock, (byte*)aes->key, aes->rounds,
+                                 outBlock);
+        #endif
+            wolfSSL_CryptHwMutexUnLock();
+        }
+        return ret;
+    }
+    #endif /* HAVE_AES_DECRYPT */
+
+#elif defined(WOLFSSL_PIC32MZ_CRYPT)
+
+    #include <wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h>
+
+    #if defined(HAVE_AESGCM) || defined(WOLFSSL_AES_DIRECT)
+    static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock)
+    {
+        return wc_Pic32AesCrypt(aes->key, aes->keylen, NULL, 0,
+            outBlock, inBlock, AES_BLOCK_SIZE,
+            PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_RECB);
+    }
+    #endif
+
+    #if defined(HAVE_AES_DECRYPT) && defined(WOLFSSL_AES_DIRECT)
+    static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
+    {
+        return wc_Pic32AesCrypt(aes->key, aes->keylen, NULL, 0,
+            outBlock, inBlock, AES_BLOCK_SIZE,
+            PIC32_DECRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_RECB);
+    }
+    #endif
+
+#elif defined(WOLFSSL_NRF51_AES)
+    /* Use built-in AES hardware - AES 128 ECB Encrypt Only */
+    #include "wolfssl/wolfcrypt/port/nrf51.h"
+
+    static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock)
+    {
+        return nrf51_aes_encrypt(inBlock, (byte*)aes->key, aes->rounds, outBlock);
+    }
+
+    #ifdef HAVE_AES_DECRYPT
+        #error nRF51 AES Hardware does not support decrypt
+    #endif /* HAVE_AES_DECRYPT */
+
+#elif defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_AES)
+
+    #include "wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h"
+
+    #if defined(HAVE_AESGCM) || defined(WOLFSSL_AES_DIRECT)
+    static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock)
+    {
+        return wc_esp32AesEncrypt(aes, inBlock, outBlock);
+    }
+    #endif
+
+    #if defined(HAVE_AES_DECRYPT) && defined(WOLFSSL_AES_DIRECT)
+    static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
+    {
+       return wc_esp32AesDecrypt(aes, inBlock, outBlock);
+    }
+    #endif
+
+#elif defined(WOLFSSL_AESNI)
+
+    #define NEED_AES_TABLES
+
+    /* Each platform needs to query info type 1 from cpuid to see if aesni is
+     * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts
+     */
+
+    #ifndef AESNI_ALIGN
+        #define AESNI_ALIGN 16
+    #endif
+
+    #ifdef _MSC_VER
+        #define XASM_LINK(f)
+    #elif defined(__APPLE__)
+        #define XASM_LINK(f) asm("_" f)
+    #else
+        #define XASM_LINK(f) asm(f)
+    #endif /* _MSC_VER */
+
+    static int checkAESNI = 0;
+    static int haveAESNI  = 0;
+    static word32 intel_flags = 0;
+
+    static int Check_CPU_support_AES(void)
+    {
+        intel_flags = cpuid_get_flags();
+
+        return IS_INTEL_AESNI(intel_flags) != 0;
+    }
+
+
+    /* tell C compiler these are asm functions in case any mix up of ABI underscore
+       prefix between clang/gcc/llvm etc */
+    #ifdef HAVE_AES_CBC
+        void AES_CBC_encrypt(const unsigned char* in, unsigned char* out,
+                             unsigned char* ivec, unsigned long length,
+                             const unsigned char* KS, int nr)
+                             XASM_LINK("AES_CBC_encrypt");
+
+        #ifdef HAVE_AES_DECRYPT
+            #if defined(WOLFSSL_AESNI_BY4)
+                void AES_CBC_decrypt_by4(const unsigned char* in, unsigned char* out,
+                                         unsigned char* ivec, unsigned long length,
+                                         const unsigned char* KS, int nr)
+                                         XASM_LINK("AES_CBC_decrypt_by4");
+            #elif defined(WOLFSSL_AESNI_BY6)
+                void AES_CBC_decrypt_by6(const unsigned char* in, unsigned char* out,
+                                         unsigned char* ivec, unsigned long length,
+                                         const unsigned char* KS, int nr)
+                                         XASM_LINK("AES_CBC_decrypt_by6");
+            #else /* WOLFSSL_AESNI_BYx */
+                void AES_CBC_decrypt_by8(const unsigned char* in, unsigned char* out,
+                                         unsigned char* ivec, unsigned long length,
+                                         const unsigned char* KS, int nr)
+                                         XASM_LINK("AES_CBC_decrypt_by8");
+            #endif /* WOLFSSL_AESNI_BYx */
+        #endif /* HAVE_AES_DECRYPT */
+    #endif /* HAVE_AES_CBC */
+
+    void AES_ECB_encrypt(const unsigned char* in, unsigned char* out,
+                         unsigned long length, const unsigned char* KS, int nr)
+                         XASM_LINK("AES_ECB_encrypt");
+
+    #ifdef HAVE_AES_DECRYPT
+        void AES_ECB_decrypt(const unsigned char* in, unsigned char* out,
+                             unsigned long length, const unsigned char* KS, int nr)
+                             XASM_LINK("AES_ECB_decrypt");
+    #endif
+
+    void AES_128_Key_Expansion(const unsigned char* userkey,
+                               unsigned char* key_schedule)
+                               XASM_LINK("AES_128_Key_Expansion");
+
+    void AES_192_Key_Expansion(const unsigned char* userkey,
+                               unsigned char* key_schedule)
+                               XASM_LINK("AES_192_Key_Expansion");
+
+    void AES_256_Key_Expansion(const unsigned char* userkey,
+                               unsigned char* key_schedule)
+                               XASM_LINK("AES_256_Key_Expansion");
+
+
+    static int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
+                                   Aes* aes)
+    {
+        int ret;
+
+        if (!userKey || !aes)
+            return BAD_FUNC_ARG;
+
+        switch (bits) {
+            case 128:
+               AES_128_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 10;
+               return 0;
+            case 192:
+               AES_192_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 12;
+               return 0;
+            case 256:
+               AES_256_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 14;
+               return 0;
+            default:
+                ret = BAD_FUNC_ARG;
+        }
+
+        return ret;
+    }
+
+    #ifdef HAVE_AES_DECRYPT
+        static int AES_set_decrypt_key(const unsigned char* userKey,
+                                                    const int bits, Aes* aes)
+        {
+            int nr;
+            Aes temp_key;
+            __m128i *Key_Schedule = (__m128i*)aes->key;
+            __m128i *Temp_Key_Schedule = (__m128i*)temp_key.key;
+
+            if (!userKey || !aes)
+                return BAD_FUNC_ARG;
+
+            if (AES_set_encrypt_key(userKey,bits,&temp_key) == BAD_FUNC_ARG)
+                return BAD_FUNC_ARG;
+
+            nr = temp_key.rounds;
+            aes->rounds = nr;
+
+            Key_Schedule[nr] = Temp_Key_Schedule[0];
+            Key_Schedule[nr-1] = _mm_aesimc_si128(Temp_Key_Schedule[1]);
+            Key_Schedule[nr-2] = _mm_aesimc_si128(Temp_Key_Schedule[2]);
+            Key_Schedule[nr-3] = _mm_aesimc_si128(Temp_Key_Schedule[3]);
+            Key_Schedule[nr-4] = _mm_aesimc_si128(Temp_Key_Schedule[4]);
+            Key_Schedule[nr-5] = _mm_aesimc_si128(Temp_Key_Schedule[5]);
+            Key_Schedule[nr-6] = _mm_aesimc_si128(Temp_Key_Schedule[6]);
+            Key_Schedule[nr-7] = _mm_aesimc_si128(Temp_Key_Schedule[7]);
+            Key_Schedule[nr-8] = _mm_aesimc_si128(Temp_Key_Schedule[8]);
+            Key_Schedule[nr-9] = _mm_aesimc_si128(Temp_Key_Schedule[9]);
+
+            if (nr>10) {
+                Key_Schedule[nr-10] = _mm_aesimc_si128(Temp_Key_Schedule[10]);
+                Key_Schedule[nr-11] = _mm_aesimc_si128(Temp_Key_Schedule[11]);
+            }
+
+            if (nr>12) {
+                Key_Schedule[nr-12] = _mm_aesimc_si128(Temp_Key_Schedule[12]);
+                Key_Schedule[nr-13] = _mm_aesimc_si128(Temp_Key_Schedule[13]);
+            }
+
+            Key_Schedule[0] = Temp_Key_Schedule[nr];
+
+            return 0;
+        }
+    #endif /* HAVE_AES_DECRYPT */
+
+#elif (defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)) || \
+      ((defined(WOLFSSL_AFALG) || defined(WOLFSSL_DEVCRYPTO_AES)) && \
+        defined(HAVE_AESCCM))
+        static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock)
+        {
+            wc_AesEncryptDirect(aes, outBlock, inBlock);
+            return 0;
+        }
+
+#elif defined(WOLFSSL_AFALG)
+#elif defined(WOLFSSL_DEVCRYPTO_AES)
+
+#elif defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_AES)
+    #include "hal_data.h"
+
+    #ifndef WOLFSSL_SCE_AES256_HANDLE
+        #define WOLFSSL_SCE_AES256_HANDLE g_sce_aes_256
+    #endif
+
+    #ifndef WOLFSSL_SCE_AES192_HANDLE
+        #define WOLFSSL_SCE_AES192_HANDLE g_sce_aes_192
+    #endif
+
+    #ifndef WOLFSSL_SCE_AES128_HANDLE
+        #define WOLFSSL_SCE_AES128_HANDLE g_sce_aes_128
+    #endif
+
+    static int AES_ECB_encrypt(Aes* aes, const byte* inBlock, byte* outBlock,
+            int sz)
+    {
+        uint32_t ret;
+
+        if (WOLFSSL_SCE_GSCE_HANDLE.p_cfg->endian_flag ==
+                CRYPTO_WORD_ENDIAN_BIG) {
+            ByteReverseWords((word32*)inBlock, (word32*)inBlock, sz);
+        }
+
+        switch (aes->keylen) {
+        #ifdef WOLFSSL_AES_128
+            case AES_128_KEY_SIZE:
+                ret = WOLFSSL_SCE_AES128_HANDLE.p_api->encrypt(
+                        WOLFSSL_SCE_AES128_HANDLE.p_ctrl, aes->key,
+                        NULL, (sz / sizeof(word32)), (word32*)inBlock,
+                        (word32*)outBlock);
+                break;
+        #endif
+        #ifdef WOLFSSL_AES_192
+            case AES_192_KEY_SIZE:
+                ret = WOLFSSL_SCE_AES192_HANDLE.p_api->encrypt(
+                        WOLFSSL_SCE_AES192_HANDLE.p_ctrl, aes->key,
+                        NULL, (sz / sizeof(word32)), (word32*)inBlock,
+                        (word32*)outBlock);
+                break;
+        #endif
+        #ifdef WOLFSSL_AES_256
+            case AES_256_KEY_SIZE:
+                ret = WOLFSSL_SCE_AES256_HANDLE.p_api->encrypt(
+                        WOLFSSL_SCE_AES256_HANDLE.p_ctrl, aes->key,
+                        NULL, (sz / sizeof(word32)), (word32*)inBlock,
+                        (word32*)outBlock);
+                break;
+        #endif
+            default:
+                WOLFSSL_MSG("Unknown key size");
+                return BAD_FUNC_ARG;
+        }
+
+        if (ret != SSP_SUCCESS) {
+           /* revert input */
+            ByteReverseWords((word32*)inBlock, (word32*)inBlock, sz);
+            return WC_HW_E;
+        }
+
+        if (WOLFSSL_SCE_GSCE_HANDLE.p_cfg->endian_flag ==
+                CRYPTO_WORD_ENDIAN_BIG) {
+            ByteReverseWords((word32*)outBlock, (word32*)outBlock, sz);
+            if (inBlock != outBlock) {
+                /* revert input */
+                ByteReverseWords((word32*)inBlock, (word32*)inBlock, sz);
+            }
+        }
+        return 0;
+    }
+
+    #if defined(HAVE_AES_DECRYPT)
+    static int AES_ECB_decrypt(Aes* aes, const byte* inBlock, byte* outBlock,
+            int sz)
+    {
+        uint32_t ret;
+
+        if (WOLFSSL_SCE_GSCE_HANDLE.p_cfg->endian_flag ==
+                CRYPTO_WORD_ENDIAN_BIG) {
+            ByteReverseWords((word32*)inBlock, (word32*)inBlock, sz);
+        }
+
+        switch (aes->keylen) {
+        #ifdef WOLFSSL_AES_128
+            case AES_128_KEY_SIZE:
+                ret = WOLFSSL_SCE_AES128_HANDLE.p_api->decrypt(
+                        WOLFSSL_SCE_AES128_HANDLE.p_ctrl, aes->key, aes->reg,
+                        (sz / sizeof(word32)), (word32*)inBlock,
+                        (word32*)outBlock);
+                break;
+        #endif
+        #ifdef WOLFSSL_AES_192
+            case AES_192_KEY_SIZE:
+                ret = WOLFSSL_SCE_AES192_HANDLE.p_api->decrypt(
+                        WOLFSSL_SCE_AES192_HANDLE.p_ctrl, aes->key, aes->reg,
+                        (sz / sizeof(word32)), (word32*)inBlock,
+                        (word32*)outBlock);
+                break;
+        #endif
+        #ifdef WOLFSSL_AES_256
+            case AES_256_KEY_SIZE:
+                ret = WOLFSSL_SCE_AES256_HANDLE.p_api->decrypt(
+                        WOLFSSL_SCE_AES256_HANDLE.p_ctrl, aes->key, aes->reg,
+                        (sz / sizeof(word32)), (word32*)inBlock,
+                        (word32*)outBlock);
+                break;
+        #endif
+            default:
+                WOLFSSL_MSG("Unknown key size");
+                return BAD_FUNC_ARG;
+        }
+        if (ret != SSP_SUCCESS) {
+            return WC_HW_E;
+        }
+
+        if (WOLFSSL_SCE_GSCE_HANDLE.p_cfg->endian_flag ==
+                CRYPTO_WORD_ENDIAN_BIG) {
+            ByteReverseWords((word32*)outBlock, (word32*)outBlock, sz);
+            if (inBlock != outBlock) {
+                /* revert input */
+                ByteReverseWords((word32*)inBlock, (word32*)inBlock, sz);
+            }
+        }
+
+        return 0;
+    }
+
+    #endif
+
+    #if defined(HAVE_AESGCM) || defined(WOLFSSL_AES_DIRECT)
+    static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock)
+    {
+        return AES_ECB_encrypt(aes, inBlock, outBlock, AES_BLOCK_SIZE);
+    }
+    #endif
+
+    #if defined(HAVE_AES_DECRYPT) && defined(WOLFSSL_AES_DIRECT)
+    static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
+    {
+        return AES_ECB_decrypt(aes, inBlock, outBlock, AES_BLOCK_SIZE);
+    }
+    #endif
+#else
+
+    /* using wolfCrypt software implementation */
+    #define NEED_AES_TABLES
+#endif
+
+
+
+#ifdef NEED_AES_TABLES
+
+static const word32 rcon[] = {
+    0x01000000, 0x02000000, 0x04000000, 0x08000000,
+    0x10000000, 0x20000000, 0x40000000, 0x80000000,
+    0x1B000000, 0x36000000,
+    /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+
+#ifndef WOLFSSL_AES_SMALL_TABLES
+static const word32 Te[4][256] = {
+{
+    0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
+    0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
+    0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
+    0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
+    0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
+    0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
+    0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
+    0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
+    0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
+    0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
+    0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
+    0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
+    0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
+    0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
+    0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
+    0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
+    0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
+    0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
+    0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
+    0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
+    0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
+    0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
+    0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
+    0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
+    0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
+    0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
+    0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
+    0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
+    0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
+    0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
+    0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
+    0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
+    0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
+    0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
+    0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
+    0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
+    0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
+    0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
+    0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
+    0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
+    0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
+    0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
+    0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
+    0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
+    0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
+    0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
+    0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
+    0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
+    0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
+    0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
+    0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
+    0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
+    0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
+    0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
+    0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
+    0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
+    0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
+    0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
+    0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
+    0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
+    0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
+    0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
+    0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
+    0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
+},
+{
+    0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
+    0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
+    0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
+    0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
+    0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
+    0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
+    0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
+    0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
+    0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
+    0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
+    0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
+    0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
+    0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
+    0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
+    0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
+    0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
+    0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
+    0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
+    0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
+    0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
+    0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
+    0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
+    0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
+    0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
+    0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
+    0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
+    0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
+    0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
+    0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
+    0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
+    0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
+    0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
+    0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
+    0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
+    0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
+    0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
+    0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
+    0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
+    0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
+    0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
+    0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
+    0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
+    0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
+    0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
+    0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
+    0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
+    0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
+    0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
+    0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
+    0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
+    0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
+    0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
+    0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
+    0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
+    0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
+    0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
+    0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
+    0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
+    0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
+    0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
+    0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
+    0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
+    0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
+    0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
+},
+{
+    0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
+    0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
+    0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
+    0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
+    0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
+    0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
+    0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
+    0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
+    0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
+    0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
+    0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
+    0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
+    0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
+    0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
+    0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
+    0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
+    0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
+    0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
+    0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
+    0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
+    0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
+    0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
+    0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
+    0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
+    0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
+    0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
+    0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
+    0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
+    0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
+    0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
+    0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
+    0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
+    0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
+    0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
+    0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
+    0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
+    0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
+    0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
+    0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
+    0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
+    0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
+    0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
+    0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
+    0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
+    0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
+    0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
+    0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
+    0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
+    0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
+    0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
+    0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
+    0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
+    0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
+    0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
+    0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
+    0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
+    0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
+    0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
+    0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
+    0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
+    0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
+    0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
+    0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
+    0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
+},
+{
+    0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
+    0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
+    0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
+    0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
+    0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
+    0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
+    0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
+    0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
+    0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
+    0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
+    0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
+    0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
+    0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
+    0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
+    0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
+    0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
+    0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
+    0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
+    0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
+    0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
+    0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
+    0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
+    0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
+    0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
+    0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
+    0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
+    0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
+    0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
+    0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
+    0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
+    0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
+    0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
+    0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
+    0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
+    0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
+    0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
+    0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
+    0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
+    0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
+    0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
+    0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
+    0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
+    0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
+    0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
+    0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
+    0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
+    0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
+    0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
+    0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
+    0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
+    0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
+    0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
+    0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
+    0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
+    0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
+    0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
+    0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
+    0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
+    0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
+    0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
+    0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
+    0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
+    0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
+    0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
+}
+};
+
+#ifdef HAVE_AES_DECRYPT
+static const word32 Td[4][256] = {
+{
+    0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
+    0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
+    0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
+    0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
+    0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
+    0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
+    0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
+    0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
+    0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
+    0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
+    0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
+    0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
+    0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
+    0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
+    0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
+    0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
+    0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
+    0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
+    0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
+    0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
+    0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
+    0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
+    0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
+    0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
+    0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
+    0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
+    0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
+    0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
+    0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
+    0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
+    0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
+    0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
+    0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
+    0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
+    0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
+    0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
+    0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
+    0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
+    0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
+    0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
+    0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
+    0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
+    0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
+    0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
+    0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
+    0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
+    0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
+    0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
+    0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
+    0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
+    0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
+    0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
+    0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
+    0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
+    0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
+    0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
+    0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
+    0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
+    0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
+    0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
+    0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
+    0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
+    0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
+    0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
+},
+{
+    0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
+    0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
+    0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
+    0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
+    0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
+    0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
+    0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
+    0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
+    0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
+    0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
+    0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
+    0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
+    0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
+    0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
+    0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
+    0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
+    0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
+    0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
+    0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
+    0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
+    0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
+    0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
+    0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
+    0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
+    0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
+    0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
+    0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
+    0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
+    0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
+    0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
+    0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
+    0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
+    0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
+    0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
+    0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
+    0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
+    0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
+    0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
+    0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
+    0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
+    0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
+    0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
+    0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
+    0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
+    0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
+    0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
+    0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
+    0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
+    0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
+    0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
+    0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
+    0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
+    0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
+    0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
+    0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
+    0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
+    0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
+    0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
+    0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
+    0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
+    0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
+    0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
+    0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
+    0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
+},
+{
+    0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
+    0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
+    0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
+    0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
+    0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
+    0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
+    0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
+    0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
+    0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
+    0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
+    0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
+    0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
+    0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
+    0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
+    0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
+    0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
+    0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
+    0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
+    0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
+    0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
+
+    0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
+    0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
+    0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
+    0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
+    0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
+    0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
+    0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
+    0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
+    0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
+    0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
+    0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
+    0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
+    0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
+    0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
+    0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
+    0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
+    0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
+    0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
+    0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
+    0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
+    0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
+    0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
+    0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
+    0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
+    0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
+    0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
+    0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
+    0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
+    0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
+    0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
+    0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
+    0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
+    0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
+    0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
+    0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
+    0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
+    0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
+    0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
+    0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
+    0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
+    0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
+    0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
+    0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
+    0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
+},
+{
+    0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
+    0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
+    0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
+    0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
+    0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
+    0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
+    0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
+    0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
+    0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
+    0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
+    0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
+    0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
+    0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
+    0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
+    0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
+    0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
+    0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
+    0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
+    0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
+    0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
+    0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
+    0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
+    0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
+    0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
+    0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
+    0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
+    0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
+    0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
+    0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
+    0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
+    0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
+    0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
+    0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
+    0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
+    0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
+    0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
+    0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
+    0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
+    0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
+    0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
+    0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
+    0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
+    0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
+    0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
+    0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
+    0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
+    0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
+    0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
+    0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
+    0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
+    0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
+    0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
+    0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
+    0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
+    0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
+    0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
+    0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
+    0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
+    0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
+    0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
+    0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
+    0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
+    0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
+    0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
+}
+};
+#endif /* HAVE_AES_DECRYPT */
+#endif
+
+#ifdef HAVE_AES_DECRYPT
+#if (defined(HAVE_AES_CBC) && !defined(WOLFSSL_DEVCRYPTO_CBC)) \
+			|| defined(WOLFSSL_AES_DIRECT)
+static const byte Td4[256] =
+{
+    0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U,
+    0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU,
+    0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U,
+    0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU,
+    0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU,
+    0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU,
+    0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U,
+    0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U,
+    0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U,
+    0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U,
+    0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU,
+    0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U,
+    0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU,
+    0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U,
+    0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U,
+    0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU,
+    0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU,
+    0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U,
+    0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U,
+    0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU,
+    0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U,
+    0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU,
+    0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U,
+    0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U,
+    0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U,
+    0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU,
+    0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU,
+    0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU,
+    0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U,
+    0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U,
+    0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U,
+    0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU,
+};
+#endif /* HAVE_AES_CBC || WOLFSSL_AES_DIRECT */
+#endif /* HAVE_AES_DECRYPT */
+
+#define GETBYTE(x, y) (word32)((byte)((x) >> (8 * (y))))
+
+#ifdef WOLFSSL_AES_SMALL_TABLES
+static const byte Tsbox[256] = {
+    0x63U, 0x7cU, 0x77U, 0x7bU, 0xf2U, 0x6bU, 0x6fU, 0xc5U,
+    0x30U, 0x01U, 0x67U, 0x2bU, 0xfeU, 0xd7U, 0xabU, 0x76U,
+    0xcaU, 0x82U, 0xc9U, 0x7dU, 0xfaU, 0x59U, 0x47U, 0xf0U,
+    0xadU, 0xd4U, 0xa2U, 0xafU, 0x9cU, 0xa4U, 0x72U, 0xc0U,
+    0xb7U, 0xfdU, 0x93U, 0x26U, 0x36U, 0x3fU, 0xf7U, 0xccU,
+    0x34U, 0xa5U, 0xe5U, 0xf1U, 0x71U, 0xd8U, 0x31U, 0x15U,
+    0x04U, 0xc7U, 0x23U, 0xc3U, 0x18U, 0x96U, 0x05U, 0x9aU,
+    0x07U, 0x12U, 0x80U, 0xe2U, 0xebU, 0x27U, 0xb2U, 0x75U,
+    0x09U, 0x83U, 0x2cU, 0x1aU, 0x1bU, 0x6eU, 0x5aU, 0xa0U,
+    0x52U, 0x3bU, 0xd6U, 0xb3U, 0x29U, 0xe3U, 0x2fU, 0x84U,
+    0x53U, 0xd1U, 0x00U, 0xedU, 0x20U, 0xfcU, 0xb1U, 0x5bU,
+    0x6aU, 0xcbU, 0xbeU, 0x39U, 0x4aU, 0x4cU, 0x58U, 0xcfU,
+    0xd0U, 0xefU, 0xaaU, 0xfbU, 0x43U, 0x4dU, 0x33U, 0x85U,
+    0x45U, 0xf9U, 0x02U, 0x7fU, 0x50U, 0x3cU, 0x9fU, 0xa8U,
+    0x51U, 0xa3U, 0x40U, 0x8fU, 0x92U, 0x9dU, 0x38U, 0xf5U,
+    0xbcU, 0xb6U, 0xdaU, 0x21U, 0x10U, 0xffU, 0xf3U, 0xd2U,
+    0xcdU, 0x0cU, 0x13U, 0xecU, 0x5fU, 0x97U, 0x44U, 0x17U,
+    0xc4U, 0xa7U, 0x7eU, 0x3dU, 0x64U, 0x5dU, 0x19U, 0x73U,
+    0x60U, 0x81U, 0x4fU, 0xdcU, 0x22U, 0x2aU, 0x90U, 0x88U,
+    0x46U, 0xeeU, 0xb8U, 0x14U, 0xdeU, 0x5eU, 0x0bU, 0xdbU,
+    0xe0U, 0x32U, 0x3aU, 0x0aU, 0x49U, 0x06U, 0x24U, 0x5cU,
+    0xc2U, 0xd3U, 0xacU, 0x62U, 0x91U, 0x95U, 0xe4U, 0x79U,
+    0xe7U, 0xc8U, 0x37U, 0x6dU, 0x8dU, 0xd5U, 0x4eU, 0xa9U,
+    0x6cU, 0x56U, 0xf4U, 0xeaU, 0x65U, 0x7aU, 0xaeU, 0x08U,
+    0xbaU, 0x78U, 0x25U, 0x2eU, 0x1cU, 0xa6U, 0xb4U, 0xc6U,
+    0xe8U, 0xddU, 0x74U, 0x1fU, 0x4bU, 0xbdU, 0x8bU, 0x8aU,
+    0x70U, 0x3eU, 0xb5U, 0x66U, 0x48U, 0x03U, 0xf6U, 0x0eU,
+    0x61U, 0x35U, 0x57U, 0xb9U, 0x86U, 0xc1U, 0x1dU, 0x9eU,
+    0xe1U, 0xf8U, 0x98U, 0x11U, 0x69U, 0xd9U, 0x8eU, 0x94U,
+    0x9bU, 0x1eU, 0x87U, 0xe9U, 0xceU, 0x55U, 0x28U, 0xdfU,
+    0x8cU, 0xa1U, 0x89U, 0x0dU, 0xbfU, 0xe6U, 0x42U, 0x68U,
+    0x41U, 0x99U, 0x2dU, 0x0fU, 0xb0U, 0x54U, 0xbbU, 0x16U
+};
+
+#define AES_XTIME(x)    ((byte)((byte)((x) << 1) ^ ((0 - ((x) >> 7)) & 0x1b)))
+
+static word32 col_mul(word32 t, int i2, int i3, int ia, int ib)
+{
+    byte t3 = GETBYTE(t, i3);
+    byte tm = AES_XTIME(GETBYTE(t, i2) ^ t3);
+
+    return GETBYTE(t, ia) ^ GETBYTE(t, ib) ^ t3 ^ tm;
+}
+
+static word32 inv_col_mul(word32 t, int i9, int ib, int id, int ie)
+{
+    byte t9 = GETBYTE(t, i9);
+    byte tb = GETBYTE(t, ib);
+    byte td = GETBYTE(t, id);
+    byte te = GETBYTE(t, ie);
+    byte t0 = t9 ^ tb ^ td;
+    return t0 ^ AES_XTIME(AES_XTIME(AES_XTIME(t0 ^ te) ^ td ^ te) ^ tb ^ te);
+}
+#endif
+
+#if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AESGCM)
+
+#ifndef WC_CACHE_LINE_SZ
+    #if defined(__x86_64__) || defined(_M_X64) || \
+       (defined(__ILP32__) && (__ILP32__ >= 1))
+        #define WC_CACHE_LINE_SZ 64
+    #else
+        /* default cache line size */
+        #define WC_CACHE_LINE_SZ 32
+    #endif
+#endif
+
+
+#ifndef WOLFSSL_AES_SMALL_TABLES
+/* load 4 Te Tables into cache by cache line stride */
+static WC_INLINE word32 PreFetchTe(void)
+{
+    word32 x = 0;
+    int i,j;
+
+    for (i = 0; i < 4; i++) {
+        /* 256 elements, each one is 4 bytes */
+        for (j = 0; j < 256; j += WC_CACHE_LINE_SZ/4) {
+            x &= Te[i][j];
+        }
+    }
+    return x;
+}
+#else
+/* load sbox into cache by cache line stride */
+static WC_INLINE word32 PreFetchSBox(void)
+{
+    word32 x = 0;
+    int i;
+
+    for (i = 0; i < 256; i += WC_CACHE_LINE_SZ/4) {
+        x &= Tsbox[i];
+    }
+    return x;
+}
+#endif
+
+/* Software AES - ECB Encrypt */
+static void wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock)
+{
+    word32 s0, s1, s2, s3;
+    word32 t0, t1, t2, t3;
+    word32 r = aes->rounds >> 1;
+    const word32* rk = aes->key;
+
+    if (r > 7 || r == 0) {
+        WOLFSSL_MSG("AesEncrypt encountered improper key, set it up");
+        return;  /* stop instead of seg-faulting, set up your keys! */
+    }
+
+#ifdef WOLFSSL_AESNI
+    if (haveAESNI && aes->use_aesni) {
+        #ifdef DEBUG_AESNI
+            printf("about to aes encrypt\n");
+            printf("in  = %p\n", inBlock);
+            printf("out = %p\n", outBlock);
+            printf("aes->key = %p\n", aes->key);
+            printf("aes->rounds = %d\n", aes->rounds);
+            printf("sz = %d\n", AES_BLOCK_SIZE);
+        #endif
+
+        /* check alignment, decrypt doesn't need alignment */
+        if ((wolfssl_word)inBlock % AESNI_ALIGN) {
+        #ifndef NO_WOLFSSL_ALLOC_ALIGN
+            byte* tmp = (byte*)XMALLOC(AES_BLOCK_SIZE + AESNI_ALIGN, aes->heap,
+                                                      DYNAMIC_TYPE_TMP_BUFFER);
+            byte* tmp_align;
+            if (tmp == NULL) return;
+
+            tmp_align = tmp + (AESNI_ALIGN - ((size_t)tmp % AESNI_ALIGN));
+
+            XMEMCPY(tmp_align, inBlock, AES_BLOCK_SIZE);
+            AES_ECB_encrypt(tmp_align, tmp_align, AES_BLOCK_SIZE,
+                    (byte*)aes->key, aes->rounds);
+            XMEMCPY(outBlock, tmp_align, AES_BLOCK_SIZE);
+            XFREE(tmp, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            return;
+        #else
+            WOLFSSL_MSG("AES-ECB encrypt with bad alignment");
+            return;
+        #endif
+        }
+
+        AES_ECB_encrypt(inBlock, outBlock, AES_BLOCK_SIZE, (byte*)aes->key,
+                        aes->rounds);
+
+        return;
+    }
+    else {
+        #ifdef DEBUG_AESNI
+            printf("Skipping AES-NI\n");
+        #endif
+    }
+#endif
+#if defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_AES)
+    AES_ECB_encrypt(aes, inBlock, outBlock, AES_BLOCK_SIZE);
+    return;
+#endif
+
+    /*
+     * map byte array block to cipher state
+     * and add initial round key:
+     */
+    XMEMCPY(&s0, inBlock,                  sizeof(s0));
+    XMEMCPY(&s1, inBlock + sizeof(s0),     sizeof(s1));
+    XMEMCPY(&s2, inBlock + 2 * sizeof(s0), sizeof(s2));
+    XMEMCPY(&s3, inBlock + 3 * sizeof(s0), sizeof(s3));
+
+#ifdef LITTLE_ENDIAN_ORDER
+    s0 = ByteReverseWord32(s0);
+    s1 = ByteReverseWord32(s1);
+    s2 = ByteReverseWord32(s2);
+    s3 = ByteReverseWord32(s3);
+#endif
+
+    /* AddRoundKey */
+    s0 ^= rk[0];
+    s1 ^= rk[1];
+    s2 ^= rk[2];
+    s3 ^= rk[3];
+
+#ifndef WOLFSSL_AES_SMALL_TABLES
+    s0 |= PreFetchTe();
+
+    /*
+     * Nr - 1 full rounds:
+     */
+
+    for (;;) {
+        t0 =
+            Te[0][GETBYTE(s0, 3)] ^
+            Te[1][GETBYTE(s1, 2)] ^
+            Te[2][GETBYTE(s2, 1)] ^
+            Te[3][GETBYTE(s3, 0)] ^
+            rk[4];
+        t1 =
+            Te[0][GETBYTE(s1, 3)] ^
+            Te[1][GETBYTE(s2, 2)] ^
+            Te[2][GETBYTE(s3, 1)] ^
+            Te[3][GETBYTE(s0, 0)] ^
+            rk[5];
+        t2 =
+            Te[0][GETBYTE(s2, 3)] ^
+            Te[1][GETBYTE(s3, 2)] ^
+            Te[2][GETBYTE(s0, 1)] ^
+            Te[3][GETBYTE(s1, 0)] ^
+            rk[6];
+        t3 =
+            Te[0][GETBYTE(s3, 3)] ^
+            Te[1][GETBYTE(s0, 2)] ^
+            Te[2][GETBYTE(s1, 1)] ^
+            Te[3][GETBYTE(s2, 0)] ^
+            rk[7];
+
+        rk += 8;
+        if (--r == 0) {
+            break;
+        }
+
+        s0 =
+            Te[0][GETBYTE(t0, 3)] ^
+            Te[1][GETBYTE(t1, 2)] ^
+            Te[2][GETBYTE(t2, 1)] ^
+            Te[3][GETBYTE(t3, 0)] ^
+            rk[0];
+        s1 =
+            Te[0][GETBYTE(t1, 3)] ^
+            Te[1][GETBYTE(t2, 2)] ^
+            Te[2][GETBYTE(t3, 1)] ^
+            Te[3][GETBYTE(t0, 0)] ^
+            rk[1];
+        s2 =
+            Te[0][GETBYTE(t2, 3)] ^
+            Te[1][GETBYTE(t3, 2)] ^
+            Te[2][GETBYTE(t0, 1)] ^
+            Te[3][GETBYTE(t1, 0)] ^
+            rk[2];
+        s3 =
+            Te[0][GETBYTE(t3, 3)] ^
+            Te[1][GETBYTE(t0, 2)] ^
+            Te[2][GETBYTE(t1, 1)] ^
+            Te[3][GETBYTE(t2, 0)] ^
+            rk[3];
+    }
+
+    /*
+     * apply last round and
+     * map cipher state to byte array block:
+     */
+
+    s0 =
+        (Te[2][GETBYTE(t0, 3)] & 0xff000000) ^
+        (Te[3][GETBYTE(t1, 2)] & 0x00ff0000) ^
+        (Te[0][GETBYTE(t2, 1)] & 0x0000ff00) ^
+        (Te[1][GETBYTE(t3, 0)] & 0x000000ff) ^
+        rk[0];
+    s1 =
+        (Te[2][GETBYTE(t1, 3)] & 0xff000000) ^
+        (Te[3][GETBYTE(t2, 2)] & 0x00ff0000) ^
+        (Te[0][GETBYTE(t3, 1)] & 0x0000ff00) ^
+        (Te[1][GETBYTE(t0, 0)] & 0x000000ff) ^
+        rk[1];
+    s2 =
+        (Te[2][GETBYTE(t2, 3)] & 0xff000000) ^
+        (Te[3][GETBYTE(t3, 2)] & 0x00ff0000) ^
+        (Te[0][GETBYTE(t0, 1)] & 0x0000ff00) ^
+        (Te[1][GETBYTE(t1, 0)] & 0x000000ff) ^
+        rk[2];
+    s3 =
+        (Te[2][GETBYTE(t3, 3)] & 0xff000000) ^
+        (Te[3][GETBYTE(t0, 2)] & 0x00ff0000) ^
+        (Te[0][GETBYTE(t1, 1)] & 0x0000ff00) ^
+        (Te[1][GETBYTE(t2, 0)] & 0x000000ff) ^
+        rk[3];
+#else
+    s0 |= PreFetchSBox();
+
+    r *= 2;
+    /* Two rounds at a time */
+    for (rk += 4; r > 1; r--, rk += 4) {
+        t0 =
+            ((word32)Tsbox[GETBYTE(s0, 3)] << 24) ^
+            ((word32)Tsbox[GETBYTE(s1, 2)] << 16) ^
+            ((word32)Tsbox[GETBYTE(s2, 1)] <<  8) ^
+            ((word32)Tsbox[GETBYTE(s3, 0)]);
+        t1 =
+            ((word32)Tsbox[GETBYTE(s1, 3)] << 24) ^
+            ((word32)Tsbox[GETBYTE(s2, 2)] << 16) ^
+            ((word32)Tsbox[GETBYTE(s3, 1)] <<  8) ^
+            ((word32)Tsbox[GETBYTE(s0, 0)]);
+        t2 =
+            ((word32)Tsbox[GETBYTE(s2, 3)] << 24) ^
+            ((word32)Tsbox[GETBYTE(s3, 2)] << 16) ^
+            ((word32)Tsbox[GETBYTE(s0, 1)] <<  8) ^
+            ((word32)Tsbox[GETBYTE(s1, 0)]);
+        t3 =
+            ((word32)Tsbox[GETBYTE(s3, 3)] << 24) ^
+            ((word32)Tsbox[GETBYTE(s0, 2)] << 16) ^
+            ((word32)Tsbox[GETBYTE(s1, 1)] <<  8) ^
+            ((word32)Tsbox[GETBYTE(s2, 0)]);
+
+        s0 =
+            (col_mul(t0, 3, 2, 0, 1) << 24) ^
+            (col_mul(t0, 2, 1, 0, 3) << 16) ^
+            (col_mul(t0, 1, 0, 2, 3) <<  8) ^
+            (col_mul(t0, 0, 3, 2, 1)      ) ^
+            rk[0];
+        s1 =
+            (col_mul(t1, 3, 2, 0, 1) << 24) ^
+            (col_mul(t1, 2, 1, 0, 3) << 16) ^
+            (col_mul(t1, 1, 0, 2, 3) <<  8) ^
+            (col_mul(t1, 0, 3, 2, 1)      ) ^
+            rk[1];
+        s2 =
+            (col_mul(t2, 3, 2, 0, 1) << 24) ^
+            (col_mul(t2, 2, 1, 0, 3) << 16) ^
+            (col_mul(t2, 1, 0, 2, 3) <<  8) ^
+            (col_mul(t2, 0, 3, 2, 1)      ) ^
+            rk[2];
+        s3 =
+            (col_mul(t3, 3, 2, 0, 1) << 24) ^
+            (col_mul(t3, 2, 1, 0, 3) << 16) ^
+            (col_mul(t3, 1, 0, 2, 3) <<  8) ^
+            (col_mul(t3, 0, 3, 2, 1)      ) ^
+            rk[3];
+    }
+
+    t0 =
+        ((word32)Tsbox[GETBYTE(s0, 3)] << 24) ^
+        ((word32)Tsbox[GETBYTE(s1, 2)] << 16) ^
+        ((word32)Tsbox[GETBYTE(s2, 1)] <<  8) ^
+        ((word32)Tsbox[GETBYTE(s3, 0)]);
+    t1 =
+        ((word32)Tsbox[GETBYTE(s1, 3)] << 24) ^
+        ((word32)Tsbox[GETBYTE(s2, 2)] << 16) ^
+        ((word32)Tsbox[GETBYTE(s3, 1)] <<  8) ^
+        ((word32)Tsbox[GETBYTE(s0, 0)]);
+    t2 =
+        ((word32)Tsbox[GETBYTE(s2, 3)] << 24) ^
+        ((word32)Tsbox[GETBYTE(s3, 2)] << 16) ^
+        ((word32)Tsbox[GETBYTE(s0, 1)] <<  8) ^
+        ((word32)Tsbox[GETBYTE(s1, 0)]);
+    t3 =
+        ((word32)Tsbox[GETBYTE(s3, 3)] << 24) ^
+        ((word32)Tsbox[GETBYTE(s0, 2)] << 16) ^
+        ((word32)Tsbox[GETBYTE(s1, 1)] <<  8) ^
+        ((word32)Tsbox[GETBYTE(s2, 0)]);
+    s0 = t0 ^ rk[0];
+    s1 = t1 ^ rk[1];
+    s2 = t2 ^ rk[2];
+    s3 = t3 ^ rk[3];
+#endif
+
+    /* write out */
+#ifdef LITTLE_ENDIAN_ORDER
+    s0 = ByteReverseWord32(s0);
+    s1 = ByteReverseWord32(s1);
+    s2 = ByteReverseWord32(s2);
+    s3 = ByteReverseWord32(s3);
+#endif
+
+    XMEMCPY(outBlock,                  &s0, sizeof(s0));
+    XMEMCPY(outBlock + sizeof(s0),     &s1, sizeof(s1));
+    XMEMCPY(outBlock + 2 * sizeof(s0), &s2, sizeof(s2));
+    XMEMCPY(outBlock + 3 * sizeof(s0), &s3, sizeof(s3));
+
+}
+#endif /* HAVE_AES_CBC || WOLFSSL_AES_DIRECT || HAVE_AESGCM */
+
+#if defined(HAVE_AES_DECRYPT)
+#if (defined(HAVE_AES_CBC) && !defined(WOLFSSL_DEVCRYPTO_CBC)) || \
+     defined(WOLFSSL_AES_DIRECT)
+
+#ifndef WOLFSSL_AES_SMALL_TABLES
+/* load 4 Td Tables into cache by cache line stride */
+static WC_INLINE word32 PreFetchTd(void)
+{
+    word32 x = 0;
+    int i,j;
+
+    for (i = 0; i < 4; i++) {
+        /* 256 elements, each one is 4 bytes */
+        for (j = 0; j < 256; j += WC_CACHE_LINE_SZ/4) {
+            x &= Td[i][j];
+        }
+    }
+    return x;
+}
+#endif
+
+/* load Td Table4 into cache by cache line stride */
+static WC_INLINE word32 PreFetchTd4(void)
+{
+    word32 x = 0;
+    int i;
+
+    for (i = 0; i < 256; i += WC_CACHE_LINE_SZ) {
+        x &= (word32)Td4[i];
+    }
+    return x;
+}
+
+/* Software AES - ECB Decrypt */
+static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
+{
+    word32 s0, s1, s2, s3;
+    word32 t0, t1, t2, t3;
+    word32 r = aes->rounds >> 1;
+
+    const word32* rk = aes->key;
+    if (r > 7 || r == 0) {
+        WOLFSSL_MSG("AesDecrypt encountered improper key, set it up");
+        return;  /* stop instead of seg-faulting, set up your keys! */
+    }
+#ifdef WOLFSSL_AESNI
+    if (haveAESNI && aes->use_aesni) {
+        #ifdef DEBUG_AESNI
+            printf("about to aes decrypt\n");
+            printf("in  = %p\n", inBlock);
+            printf("out = %p\n", outBlock);
+            printf("aes->key = %p\n", aes->key);
+            printf("aes->rounds = %d\n", aes->rounds);
+            printf("sz = %d\n", AES_BLOCK_SIZE);
+        #endif
+
+        /* if input and output same will overwrite input iv */
+        if ((const byte*)aes->tmp != inBlock)
+            XMEMCPY(aes->tmp, inBlock, AES_BLOCK_SIZE);
+        AES_ECB_decrypt(inBlock, outBlock, AES_BLOCK_SIZE, (byte*)aes->key,
+                        aes->rounds);
+        return;
+    }
+    else {
+        #ifdef DEBUG_AESNI
+            printf("Skipping AES-NI\n");
+        #endif
+    }
+#endif /* WOLFSSL_AESNI */
+#if defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_AES)
+    return AES_ECB_decrypt(aes, inBlock, outBlock, AES_BLOCK_SIZE);
+#endif
+
+    /*
+     * map byte array block to cipher state
+     * and add initial round key:
+     */
+    XMEMCPY(&s0, inBlock,                  sizeof(s0));
+    XMEMCPY(&s1, inBlock + sizeof(s0),     sizeof(s1));
+    XMEMCPY(&s2, inBlock + 2 * sizeof(s0), sizeof(s2));
+    XMEMCPY(&s3, inBlock + 3 * sizeof(s0), sizeof(s3));
+
+#ifdef LITTLE_ENDIAN_ORDER
+    s0 = ByteReverseWord32(s0);
+    s1 = ByteReverseWord32(s1);
+    s2 = ByteReverseWord32(s2);
+    s3 = ByteReverseWord32(s3);
+#endif
+
+    s0 ^= rk[0];
+    s1 ^= rk[1];
+    s2 ^= rk[2];
+    s3 ^= rk[3];
+
+#ifndef WOLFSSL_AES_SMALL_TABLES
+    s0 |= PreFetchTd();
+
+    /*
+     * Nr - 1 full rounds:
+     */
+
+    for (;;) {
+        t0 =
+            Td[0][GETBYTE(s0, 3)] ^
+            Td[1][GETBYTE(s3, 2)] ^
+            Td[2][GETBYTE(s2, 1)] ^
+            Td[3][GETBYTE(s1, 0)] ^
+            rk[4];
+        t1 =
+            Td[0][GETBYTE(s1, 3)] ^
+            Td[1][GETBYTE(s0, 2)] ^
+            Td[2][GETBYTE(s3, 1)] ^
+            Td[3][GETBYTE(s2, 0)] ^
+            rk[5];
+        t2 =
+            Td[0][GETBYTE(s2, 3)] ^
+            Td[1][GETBYTE(s1, 2)] ^
+            Td[2][GETBYTE(s0, 1)] ^
+            Td[3][GETBYTE(s3, 0)] ^
+            rk[6];
+        t3 =
+            Td[0][GETBYTE(s3, 3)] ^
+            Td[1][GETBYTE(s2, 2)] ^
+            Td[2][GETBYTE(s1, 1)] ^
+            Td[3][GETBYTE(s0, 0)] ^
+            rk[7];
+
+        rk += 8;
+        if (--r == 0) {
+            break;
+        }
+
+        s0 =
+            Td[0][GETBYTE(t0, 3)] ^
+            Td[1][GETBYTE(t3, 2)] ^
+            Td[2][GETBYTE(t2, 1)] ^
+            Td[3][GETBYTE(t1, 0)] ^
+            rk[0];
+        s1 =
+            Td[0][GETBYTE(t1, 3)] ^
+            Td[1][GETBYTE(t0, 2)] ^
+            Td[2][GETBYTE(t3, 1)] ^
+            Td[3][GETBYTE(t2, 0)] ^
+            rk[1];
+        s2 =
+            Td[0][GETBYTE(t2, 3)] ^
+            Td[1][GETBYTE(t1, 2)] ^
+            Td[2][GETBYTE(t0, 1)] ^
+            Td[3][GETBYTE(t3, 0)] ^
+            rk[2];
+        s3 =
+            Td[0][GETBYTE(t3, 3)] ^
+            Td[1][GETBYTE(t2, 2)] ^
+            Td[2][GETBYTE(t1, 1)] ^
+            Td[3][GETBYTE(t0, 0)] ^
+            rk[3];
+    }
+    /*
+     * apply last round and
+     * map cipher state to byte array block:
+     */
+
+    t0 |= PreFetchTd4();
+
+    s0 =
+        ((word32)Td4[GETBYTE(t0, 3)] << 24) ^
+        ((word32)Td4[GETBYTE(t3, 2)] << 16) ^
+        ((word32)Td4[GETBYTE(t2, 1)] <<  8) ^
+        ((word32)Td4[GETBYTE(t1, 0)]) ^
+        rk[0];
+    s1 =
+        ((word32)Td4[GETBYTE(t1, 3)] << 24) ^
+        ((word32)Td4[GETBYTE(t0, 2)] << 16) ^
+        ((word32)Td4[GETBYTE(t3, 1)] <<  8) ^
+        ((word32)Td4[GETBYTE(t2, 0)]) ^
+        rk[1];
+    s2 =
+        ((word32)Td4[GETBYTE(t2, 3)] << 24) ^
+        ((word32)Td4[GETBYTE(t1, 2)] << 16) ^
+        ((word32)Td4[GETBYTE(t0, 1)] <<  8) ^
+        ((word32)Td4[GETBYTE(t3, 0)]) ^
+        rk[2];
+    s3 =
+        ((word32)Td4[GETBYTE(t3, 3)] << 24) ^
+        ((word32)Td4[GETBYTE(t2, 2)] << 16) ^
+        ((word32)Td4[GETBYTE(t1, 1)] <<  8) ^
+        ((word32)Td4[GETBYTE(t0, 0)]) ^
+        rk[3];
+#else
+    s0 |= PreFetchTd4();
+
+    r *= 2;
+    for (rk += 4; r > 1; r--, rk += 4) {
+        t0 =
+            ((word32)Td4[GETBYTE(s0, 3)] << 24) ^
+            ((word32)Td4[GETBYTE(s3, 2)] << 16) ^
+            ((word32)Td4[GETBYTE(s2, 1)] <<  8) ^
+            ((word32)Td4[GETBYTE(s1, 0)]) ^
+            rk[0];
+        t1 =
+            ((word32)Td4[GETBYTE(s1, 3)] << 24) ^
+            ((word32)Td4[GETBYTE(s0, 2)] << 16) ^
+            ((word32)Td4[GETBYTE(s3, 1)] <<  8) ^
+            ((word32)Td4[GETBYTE(s2, 0)]) ^
+            rk[1];
+        t2 =
+            ((word32)Td4[GETBYTE(s2, 3)] << 24) ^
+            ((word32)Td4[GETBYTE(s1, 2)] << 16) ^
+            ((word32)Td4[GETBYTE(s0, 1)] <<  8) ^
+            ((word32)Td4[GETBYTE(s3, 0)]) ^
+            rk[2];
+        t3 =
+            ((word32)Td4[GETBYTE(s3, 3)] << 24) ^
+            ((word32)Td4[GETBYTE(s2, 2)] << 16) ^
+            ((word32)Td4[GETBYTE(s1, 1)] <<  8) ^
+            ((word32)Td4[GETBYTE(s0, 0)]) ^
+            rk[3];
+
+        s0 =
+            (inv_col_mul(t0, 0, 2, 1, 3) << 24) ^
+            (inv_col_mul(t0, 3, 1, 0, 2) << 16) ^
+            (inv_col_mul(t0, 2, 0, 3, 1) <<  8) ^
+            (inv_col_mul(t0, 1, 3, 2, 0)      );
+        s1 =
+            (inv_col_mul(t1, 0, 2, 1, 3) << 24) ^
+            (inv_col_mul(t1, 3, 1, 0, 2) << 16) ^
+            (inv_col_mul(t1, 2, 0, 3, 1) <<  8) ^
+            (inv_col_mul(t1, 1, 3, 2, 0)      );
+        s2 =
+            (inv_col_mul(t2, 0, 2, 1, 3) << 24) ^
+            (inv_col_mul(t2, 3, 1, 0, 2) << 16) ^
+            (inv_col_mul(t2, 2, 0, 3, 1) <<  8) ^
+            (inv_col_mul(t2, 1, 3, 2, 0)      );
+        s3 =
+            (inv_col_mul(t3, 0, 2, 1, 3) << 24) ^
+            (inv_col_mul(t3, 3, 1, 0, 2) << 16) ^
+            (inv_col_mul(t3, 2, 0, 3, 1) <<  8) ^
+            (inv_col_mul(t3, 1, 3, 2, 0)      );
+    }
+
+    t0 =
+        ((word32)Td4[GETBYTE(s0, 3)] << 24) ^
+        ((word32)Td4[GETBYTE(s3, 2)] << 16) ^
+        ((word32)Td4[GETBYTE(s2, 1)] <<  8) ^
+        ((word32)Td4[GETBYTE(s1, 0)]);
+    t1 =
+        ((word32)Td4[GETBYTE(s1, 3)] << 24) ^
+        ((word32)Td4[GETBYTE(s0, 2)] << 16) ^
+        ((word32)Td4[GETBYTE(s3, 1)] <<  8) ^
+        ((word32)Td4[GETBYTE(s2, 0)]);
+    t2 =
+        ((word32)Td4[GETBYTE(s2, 3)] << 24) ^
+        ((word32)Td4[GETBYTE(s1, 2)] << 16) ^
+        ((word32)Td4[GETBYTE(s0, 1)] <<  8) ^
+        ((word32)Td4[GETBYTE(s3, 0)]);
+    t3 =
+        ((word32)Td4[GETBYTE(s3, 3)] << 24) ^
+        ((word32)Td4[GETBYTE(s2, 2)] << 16) ^
+        ((word32)Td4[GETBYTE(s1, 1)] <<  8) ^
+        ((word32)Td4[GETBYTE(s0, 0)]);
+    s0 = t0 ^ rk[0];
+    s1 = t1 ^ rk[1];
+    s2 = t2 ^ rk[2];
+    s3 = t3 ^ rk[3];
+#endif
+
+    /* write out */
+#ifdef LITTLE_ENDIAN_ORDER
+    s0 = ByteReverseWord32(s0);
+    s1 = ByteReverseWord32(s1);
+    s2 = ByteReverseWord32(s2);
+    s3 = ByteReverseWord32(s3);
+#endif
+
+    XMEMCPY(outBlock,                  &s0, sizeof(s0));
+    XMEMCPY(outBlock + sizeof(s0),     &s1, sizeof(s1));
+    XMEMCPY(outBlock + 2 * sizeof(s0), &s2, sizeof(s2));
+    XMEMCPY(outBlock + 3 * sizeof(s0), &s3, sizeof(s3));
+}
+#endif /* HAVE_AES_CBC || WOLFSSL_AES_DIRECT */
+#endif /* HAVE_AES_DECRYPT */
+
+#endif /* NEED_AES_TABLES */
+
+
+
+/* wc_AesSetKey */
+#if defined(STM32_CRYPTO)
+
+    int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen,
+            const byte* iv, int dir)
+    {
+        word32 *rk;
+
+        (void)dir;
+
+        if (aes == NULL || (keylen != 16 &&
+        #ifdef WOLFSSL_AES_192
+            keylen != 24 &&
+        #endif
+            keylen != 32)) {
+            return BAD_FUNC_ARG;
+        }
+
+        rk = aes->key;
+        aes->keylen = keylen;
+        aes->rounds = keylen/4 + 6;
+        XMEMCPY(rk, userKey, keylen);
+    #if !defined(WOLFSSL_STM32_CUBEMX) || defined(STM32_HAL_V2)
+        ByteReverseWords(rk, rk, keylen);
+    #endif
+    #if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_COUNTER) || \
+        defined(WOLFSSL_AES_OFB)
+        aes->left = 0;
+    #endif
+
+        return wc_AesSetIV(aes, iv);
+    }
+    #if defined(WOLFSSL_AES_DIRECT)
+        int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen,
+                            const byte* iv, int dir)
+        {
+            return wc_AesSetKey(aes, userKey, keylen, iv, dir);
+        }
+    #endif
+
+#elif defined(HAVE_COLDFIRE_SEC)
+    #if defined (HAVE_THREADX)
+        #include "memory_pools.h"
+        extern TX_BYTE_POOL mp_ncached;  /* Non Cached memory pool */
+    #endif
+
+    #define AES_BUFFER_SIZE (AES_BLOCK_SIZE * 64)
+    static unsigned char *AESBuffIn = NULL;
+    static unsigned char *AESBuffOut = NULL;
+    static byte *secReg;
+    static byte *secKey;
+    static volatile SECdescriptorType *secDesc;
+
+    static wolfSSL_Mutex Mutex_AesSEC;
+
+    #define SEC_DESC_AES_CBC_ENCRYPT 0x60300010
+    #define SEC_DESC_AES_CBC_DECRYPT 0x60200010
+
+    extern volatile unsigned char __MBAR[];
+
+    int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen,
+        const byte* iv, int dir)
+    {
+        if (AESBuffIn == NULL) {
+        #if defined (HAVE_THREADX)
+            int s1, s2, s3, s4, s5;
+            s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc,
+                                  sizeof(SECdescriptorType), TX_NO_WAIT);
+            s1 = tx_byte_allocate(&mp_ncached, (void *)&AESBuffIn,
+                                  AES_BUFFER_SIZE, TX_NO_WAIT);
+            s2 = tx_byte_allocate(&mp_ncached, (void *)&AESBuffOut,
+                                  AES_BUFFER_SIZE, TX_NO_WAIT);
+            s3 = tx_byte_allocate(&mp_ncached, (void *)&secKey,
+                                  AES_BLOCK_SIZE*2, TX_NO_WAIT);
+            s4 = tx_byte_allocate(&mp_ncached, (void *)&secReg,
+                                  AES_BLOCK_SIZE, TX_NO_WAIT);
+
+            if (s1 || s2 || s3 || s4 || s5)
+                return BAD_FUNC_ARG;
+        #else
+            #warning "Allocate non-Cache buffers"
+        #endif
+
+            wc_InitMutex(&Mutex_AesSEC);
+        }
+
+        if (!((keylen == 16) || (keylen == 24) || (keylen == 32)))
+            return BAD_FUNC_ARG;
+
+        if (aes == NULL)
+            return BAD_FUNC_ARG;
+
+        aes->keylen = keylen;
+        aes->rounds = keylen/4 + 6;
+        XMEMCPY(aes->key, userKey, keylen);
+
+        if (iv)
+            XMEMCPY(aes->reg, iv, AES_BLOCK_SIZE);
+
+    #if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_COUNTER) || \
+        defined(WOLFSSL_AES_OFB)
+        aes->left = 0;
+    #endif
+
+        return 0;
+    }
+#elif defined(FREESCALE_LTC)
+    int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv,
+                  int dir)
+    {
+        if (aes == NULL || !((keylen == 16) || (keylen == 24) || (keylen == 32)))
+            return BAD_FUNC_ARG;
+
+        aes->rounds = keylen/4 + 6;
+        XMEMCPY(aes->key, userKey, keylen);
+
+    #if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_COUNTER) || \
+        defined(WOLFSSL_AES_OFB)
+        aes->left = 0;
+    #endif
+
+        return wc_AesSetIV(aes, iv);
+    }
+
+    int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen,
+                        const byte* iv, int dir)
+    {
+        return wc_AesSetKey(aes, userKey, keylen, iv, dir);
+    }
+#elif defined(FREESCALE_MMCAU)
+    int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen,
+        const byte* iv, int dir)
+    {
+        int ret;
+        byte* rk;
+        byte* tmpKey = (byte*)userKey;
+        int tmpKeyDynamic = 0;
+        word32 alignOffset = 0;
+
+        (void)dir;
+
+        if (!((keylen == 16) || (keylen == 24) || (keylen == 32)))
+            return BAD_FUNC_ARG;
+        if (aes == NULL)
+            return BAD_FUNC_ARG;
+
+        rk = (byte*)aes->key;
+        if (rk == NULL)
+            return BAD_FUNC_ARG;
+
+    #if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_COUNTER) || \
+        defined(WOLFSSL_AES_OFB)
+        aes->left = 0;
+    #endif
+
+        aes->rounds = keylen/4 + 6;
+
+    #ifdef FREESCALE_MMCAU_CLASSIC
+        if ((wolfssl_word)userKey % WOLFSSL_MMCAU_ALIGNMENT) {
+        #ifndef NO_WOLFSSL_ALLOC_ALIGN
+            byte* tmp = (byte*)XMALLOC(keylen + WOLFSSL_MMCAU_ALIGNMENT,
+                                       aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            if (tmp == NULL) {
+                return MEMORY_E;
+            }
+            alignOffset = WOLFSSL_MMCAU_ALIGNMENT -
+                          ((wolfssl_word)tmp % WOLFSSL_MMCAU_ALIGNMENT);
+            tmpKey = tmp + alignOffset;
+            XMEMCPY(tmpKey, userKey, keylen);
+            tmpKeyDynamic = 1;
+        #else
+            WOLFSSL_MSG("Bad cau_aes_set_key alignment");
+            return BAD_ALIGN_E;
+        #endif
+        }
+    #endif
+
+        ret = wolfSSL_CryptHwMutexLock();
+        if(ret == 0) {
+        #ifdef FREESCALE_MMCAU_CLASSIC
+            cau_aes_set_key(tmpKey, keylen*8, rk);
+        #else
+            MMCAU_AES_SetKey(tmpKey, keylen, rk);
+        #endif
+            wolfSSL_CryptHwMutexUnLock();
+
+            ret = wc_AesSetIV(aes, iv);
+        }
+
+        if (tmpKeyDynamic == 1) {
+            XFREE(tmpKey - alignOffset, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        }
+
+        return ret;
+    }
+
+    int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen,
+                        const byte* iv, int dir)
+    {
+        return wc_AesSetKey(aes, userKey, keylen, iv, dir);
+    }
+
+#elif defined(WOLFSSL_NRF51_AES)
+    int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen,
+        const byte* iv, int dir)
+    {
+        int ret;
+
+        (void)dir;
+        (void)iv;
+
+        if (aes == NULL || keylen != 16)
+            return BAD_FUNC_ARG;
+
+        aes->keylen = keylen;
+        aes->rounds = keylen/4 + 6;
+        ret = nrf51_aes_set_key(userKey);
+
+    #if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_COUNTER) || \
+        defined(WOLFSSL_AES_OFB)
+        aes->left = 0;
+    #endif
+
+        return ret;
+    }
+
+    int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen,
+                        const byte* iv, int dir)
+    {
+        return wc_AesSetKey(aes, userKey, keylen, iv, dir);
+    }
+#elif defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_AES)
+
+    int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen,
+        const byte* iv, int dir)
+    {
+        (void)dir;
+        (void)iv;
+
+        if (aes == NULL || (keylen != 16 && keylen != 24 && keylen != 32)) {
+            return BAD_FUNC_ARG;
+        }
+
+        aes->keylen = keylen;
+        aes->rounds = keylen/4 + 6;
+
+        XMEMCPY(aes->key, userKey, keylen);
+        #if defined(WOLFSSL_AES_COUNTER)
+            aes->left = 0;
+        #endif
+        return wc_AesSetIV(aes, iv);
+    }
+
+    int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen,
+                        const byte* iv, int dir)
+    {
+        return wc_AesSetKey(aes, userKey, keylen, iv, dir);
+    }
+#elif defined(WOLFSSL_CRYPTOCELL) && defined(WOLFSSL_CRYPTOCELL_AES)
+
+    int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv,
+                    int dir)
+    {
+        SaSiError_t ret = SASI_OK;
+        SaSiAesIv_t iv_aes;
+
+        if (aes == NULL ||
+           (keylen != AES_128_KEY_SIZE &&
+            keylen != AES_192_KEY_SIZE &&
+            keylen != AES_256_KEY_SIZE)) {
+            return BAD_FUNC_ARG;
+        }
+    #if defined(AES_MAX_KEY_SIZE)
+        if (keylen > (AES_MAX_KEY_SIZE/8)) {
+            return BAD_FUNC_ARG;
+        }
+    #endif
+        if (dir != AES_ENCRYPTION &&
+            dir != AES_DECRYPTION) {
+            return BAD_FUNC_ARG;
+        }
+
+        if (dir == AES_ENCRYPTION) {
+            aes->ctx.mode = SASI_AES_ENCRYPT;
+            SaSi_AesInit(&aes->ctx.user_ctx,
+                         SASI_AES_ENCRYPT,
+                         SASI_AES_MODE_CBC,
+                         SASI_AES_PADDING_NONE);
+        }
+        else {
+            aes->ctx.mode = SASI_AES_DECRYPT;
+            SaSi_AesInit(&aes->ctx.user_ctx,
+                         SASI_AES_DECRYPT,
+                         SASI_AES_MODE_CBC,
+                         SASI_AES_PADDING_NONE);
+        }
+
+        aes->keylen = keylen;
+        aes->rounds = keylen/4 + 6;
+        XMEMCPY(aes->key, userKey, keylen);
+
+        aes->ctx.key.pKey = (uint8_t*)aes->key;
+        aes->ctx.key.keySize= keylen;
+
+        ret = SaSi_AesSetKey(&aes->ctx.user_ctx,
+                             SASI_AES_USER_KEY,
+                             &aes->ctx.key,
+                             sizeof(aes->ctx.key));
+        if (ret != SASI_OK) {
+            return BAD_FUNC_ARG;
+        }
+
+        ret = wc_AesSetIV(aes, iv);
+
+        if (iv)
+            XMEMCPY(iv_aes, iv, AES_BLOCK_SIZE);
+        else
+            XMEMSET(iv_aes,  0, AES_BLOCK_SIZE);
+
+
+        ret = SaSi_AesSetIv(&aes->ctx.user_ctx, iv_aes);
+        if (ret != SASI_OK) {
+            return ret;
+        }
+       return ret;
+    }
+    #if defined(WOLFSSL_AES_DIRECT)
+        int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen,
+                            const byte* iv, int dir)
+        {
+            return wc_AesSetKey(aes, userKey, keylen, iv, dir);
+        }
+    #endif
+
+#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
+      /* implemented in wolfcrypt/src/port/caam/caam_aes.c */
+
+#elif defined(WOLFSSL_AFALG)
+    /* implemented in wolfcrypt/src/port/af_alg/afalg_aes.c */
+
+#elif defined(WOLFSSL_DEVCRYPTO_AES)
+    /* implemented in wolfcrypt/src/port/devcrypto/devcrypto_aes.c */
+
+#else
+
+    /* Software AES - SetKey */
+    static int wc_AesSetKeyLocal(Aes* aes, const byte* userKey, word32 keylen,
+                const byte* iv, int dir)
+    {
+        word32 *rk = aes->key;
+    #ifdef NEED_AES_TABLES
+        word32 temp;
+        unsigned int i = 0;
+    #endif
+
+        #ifdef WOLFSSL_AESNI
+            aes->use_aesni = 0;
+        #endif /* WOLFSSL_AESNI */
+        #if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_COUNTER) || \
+            defined(WOLFSSL_AES_OFB)
+            aes->left = 0;
+        #endif
+
+        aes->keylen = keylen;
+        aes->rounds = (keylen/4) + 6;
+
+        XMEMCPY(rk, userKey, keylen);
+    #if defined(LITTLE_ENDIAN_ORDER) && !defined(WOLFSSL_PIC32MZ_CRYPT) && \
+        (!defined(WOLFSSL_ESP32WROOM32_CRYPT) || \
+          defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_AES))
+        ByteReverseWords(rk, rk, keylen);
+    #endif
+
+#ifdef NEED_AES_TABLES
+        switch (keylen) {
+    #if defined(AES_MAX_KEY_SIZE) && AES_MAX_KEY_SIZE >= 128 && \
+            defined(WOLFSSL_AES_128)
+        case 16:
+            while (1)
+            {
+                temp  = rk[3];
+                rk[4] = rk[0] ^
+            #ifndef WOLFSSL_AES_SMALL_TABLES
+                    (Te[2][GETBYTE(temp, 2)] & 0xff000000) ^
+                    (Te[3][GETBYTE(temp, 1)] & 0x00ff0000) ^
+                    (Te[0][GETBYTE(temp, 0)] & 0x0000ff00) ^
+                    (Te[1][GETBYTE(temp, 3)] & 0x000000ff) ^
+            #else
+                    ((word32)Tsbox[GETBYTE(temp, 2)] << 24) ^
+                    ((word32)Tsbox[GETBYTE(temp, 1)] << 16) ^
+                    ((word32)Tsbox[GETBYTE(temp, 0)] <<  8) ^
+                    ((word32)Tsbox[GETBYTE(temp, 3)]) ^
+            #endif
+                    rcon[i];
+                rk[5] = rk[1] ^ rk[4];
+                rk[6] = rk[2] ^ rk[5];
+                rk[7] = rk[3] ^ rk[6];
+                if (++i == 10)
+                    break;
+                rk += 4;
+            }
+            break;
+    #endif /* 128 */
+
+    #if defined(AES_MAX_KEY_SIZE) && AES_MAX_KEY_SIZE >= 192 && \
+            defined(WOLFSSL_AES_192)
+        case 24:
+            /* for (;;) here triggers a bug in VC60 SP4 w/ Pro Pack */
+            while (1)
+            {
+                temp = rk[ 5];
+                rk[ 6] = rk[ 0] ^
+            #ifndef WOLFSSL_AES_SMALL_TABLES
+                    (Te[2][GETBYTE(temp, 2)] & 0xff000000) ^
+                    (Te[3][GETBYTE(temp, 1)] & 0x00ff0000) ^
+                    (Te[0][GETBYTE(temp, 0)] & 0x0000ff00) ^
+                    (Te[1][GETBYTE(temp, 3)] & 0x000000ff) ^
+            #else
+                    ((word32)Tsbox[GETBYTE(temp, 2)] << 24) ^
+                    ((word32)Tsbox[GETBYTE(temp, 1)] << 16) ^
+                    ((word32)Tsbox[GETBYTE(temp, 0)] <<  8) ^
+                    ((word32)Tsbox[GETBYTE(temp, 3)]) ^
+            #endif
+                    rcon[i];
+                rk[ 7] = rk[ 1] ^ rk[ 6];
+                rk[ 8] = rk[ 2] ^ rk[ 7];
+                rk[ 9] = rk[ 3] ^ rk[ 8];
+                if (++i == 8)
+                    break;
+                rk[10] = rk[ 4] ^ rk[ 9];
+                rk[11] = rk[ 5] ^ rk[10];
+                rk += 6;
+            }
+            break;
+    #endif /* 192 */
+
+    #if defined(AES_MAX_KEY_SIZE) && AES_MAX_KEY_SIZE >= 256 && \
+            defined(WOLFSSL_AES_256)
+        case 32:
+            while (1)
+            {
+                temp = rk[ 7];
+                rk[ 8] = rk[ 0] ^
+            #ifndef WOLFSSL_AES_SMALL_TABLES
+                    (Te[2][GETBYTE(temp, 2)] & 0xff000000) ^
+                    (Te[3][GETBYTE(temp, 1)] & 0x00ff0000) ^
+                    (Te[0][GETBYTE(temp, 0)] & 0x0000ff00) ^
+                    (Te[1][GETBYTE(temp, 3)] & 0x000000ff) ^
+            #else
+                    ((word32)Tsbox[GETBYTE(temp, 2)] << 24) ^
+                    ((word32)Tsbox[GETBYTE(temp, 1)] << 16) ^
+                    ((word32)Tsbox[GETBYTE(temp, 0)] <<  8) ^
+                    ((word32)Tsbox[GETBYTE(temp, 3)]) ^
+            #endif
+                    rcon[i];
+                rk[ 9] = rk[ 1] ^ rk[ 8];
+                rk[10] = rk[ 2] ^ rk[ 9];
+                rk[11] = rk[ 3] ^ rk[10];
+                if (++i == 7)
+                    break;
+                temp = rk[11];
+                rk[12] = rk[ 4] ^
+            #ifndef WOLFSSL_AES_SMALL_TABLES
+                    (Te[2][GETBYTE(temp, 3)] & 0xff000000) ^
+                    (Te[3][GETBYTE(temp, 2)] & 0x00ff0000) ^
+                    (Te[0][GETBYTE(temp, 1)] & 0x0000ff00) ^
+                    (Te[1][GETBYTE(temp, 0)] & 0x000000ff);
+            #else
+                    ((word32)Tsbox[GETBYTE(temp, 3)] << 24) ^
+                    ((word32)Tsbox[GETBYTE(temp, 2)] << 16) ^
+                    ((word32)Tsbox[GETBYTE(temp, 1)] <<  8) ^
+                    ((word32)Tsbox[GETBYTE(temp, 0)]);
+            #endif
+                rk[13] = rk[ 5] ^ rk[12];
+                rk[14] = rk[ 6] ^ rk[13];
+                rk[15] = rk[ 7] ^ rk[14];
+
+                rk += 8;
+            }
+            break;
+    #endif /* 256 */
+
+        default:
+            return BAD_FUNC_ARG;
+        } /* switch */
+
+    #if defined(HAVE_AES_DECRYPT)
+        if (dir == AES_DECRYPTION) {
+            unsigned int j;
+            rk = aes->key;
+
+            /* invert the order of the round keys: */
+            for (i = 0, j = 4* aes->rounds; i < j; i += 4, j -= 4) {
+                temp = rk[i    ]; rk[i    ] = rk[j    ]; rk[j    ] = temp;
+                temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
+                temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
+                temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
+            }
+        #if !defined(WOLFSSL_AES_SMALL_TABLES)
+            /* apply the inverse MixColumn transform to all round keys but the
+               first and the last: */
+            for (i = 1; i < aes->rounds; i++) {
+                rk += 4;
+                rk[0] =
+                    Td[0][Te[1][GETBYTE(rk[0], 3)] & 0xff] ^
+                    Td[1][Te[1][GETBYTE(rk[0], 2)] & 0xff] ^
+                    Td[2][Te[1][GETBYTE(rk[0], 1)] & 0xff] ^
+                    Td[3][Te[1][GETBYTE(rk[0], 0)] & 0xff];
+                rk[1] =
+                    Td[0][Te[1][GETBYTE(rk[1], 3)] & 0xff] ^
+                    Td[1][Te[1][GETBYTE(rk[1], 2)] & 0xff] ^
+                    Td[2][Te[1][GETBYTE(rk[1], 1)] & 0xff] ^
+                    Td[3][Te[1][GETBYTE(rk[1], 0)] & 0xff];
+                rk[2] =
+                    Td[0][Te[1][GETBYTE(rk[2], 3)] & 0xff] ^
+                    Td[1][Te[1][GETBYTE(rk[2], 2)] & 0xff] ^
+                    Td[2][Te[1][GETBYTE(rk[2], 1)] & 0xff] ^
+                    Td[3][Te[1][GETBYTE(rk[2], 0)] & 0xff];
+                rk[3] =
+                    Td[0][Te[1][GETBYTE(rk[3], 3)] & 0xff] ^
+                    Td[1][Te[1][GETBYTE(rk[3], 2)] & 0xff] ^
+                    Td[2][Te[1][GETBYTE(rk[3], 1)] & 0xff] ^
+                    Td[3][Te[1][GETBYTE(rk[3], 0)] & 0xff];
+            }
+        #endif
+        }
+    #else
+        (void)dir;
+    #endif /* HAVE_AES_DECRYPT */
+        (void)temp;
+#endif /* NEED_AES_TABLES */
+
+#if defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_AES)
+        XMEMCPY((byte*)aes->key, userKey, keylen);
+        if (WOLFSSL_SCE_GSCE_HANDLE.p_cfg->endian_flag == CRYPTO_WORD_ENDIAN_BIG) {
+            ByteReverseWords(aes->key, aes->key, 32);
+        }
+#endif
+
+        return wc_AesSetIV(aes, iv);
+    }
+
+    int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen,
+        const byte* iv, int dir)
+    {
+        int ret;
+    #if defined(AES_MAX_KEY_SIZE)
+        const word32 max_key_len = (AES_MAX_KEY_SIZE / 8);
+    #endif
+
+    #ifdef WOLFSSL_IMX6_CAAM_BLOB
+        byte   local[32];
+        word32 localSz = 32;
+
+        if (keylen == (16 + WC_CAAM_BLOB_SZ) ||
+                keylen == (24 + WC_CAAM_BLOB_SZ) ||
+                keylen == (32 + WC_CAAM_BLOB_SZ)) {
+            if (wc_caamOpenBlob((byte*)userKey, keylen, local, &localSz) != 0) {
+                return BAD_FUNC_ARG;
+            }
+
+            /* set local values */
+            userKey = local;
+            keylen = localSz;
+        }
+    #endif
+        if (aes == NULL ||
+                !((keylen == 16) || (keylen == 24) || (keylen == 32))) {
+            return BAD_FUNC_ARG;
+        }
+
+    #if defined(AES_MAX_KEY_SIZE)
+        /* Check key length */
+        if (keylen > max_key_len) {
+            return BAD_FUNC_ARG;
+        }
+    #endif
+        aes->keylen = keylen;
+        aes->rounds = keylen/4 + 6;
+
+    #if defined(WOLF_CRYPTO_CB) || (defined(WOLFSSL_DEVCRYPTO) && \
+        (defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC))) || \
+        (defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES))
+        #ifdef WOLF_CRYPTO_CB
+        if (aes->devId != INVALID_DEVID)
+        #endif
+        {
+            XMEMCPY(aes->devKey, userKey, keylen);
+        }
+    #endif
+
+    #ifdef WOLFSSL_AESNI
+        if (checkAESNI == 0) {
+            haveAESNI  = Check_CPU_support_AES();
+            checkAESNI = 1;
+        }
+        if (haveAESNI) {
+            #if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) || \
+                defined(WOLFSSL_AES_OFB)
+                aes->left = 0;
+            #endif /* WOLFSSL_AES_COUNTER */
+            aes->use_aesni = 1;
+            if (iv)
+                XMEMCPY(aes->reg, iv, AES_BLOCK_SIZE);
+            else
+                XMEMSET(aes->reg, 0, AES_BLOCK_SIZE);
+            if (dir == AES_ENCRYPTION)
+                return AES_set_encrypt_key(userKey, keylen * 8, aes);
+        #ifdef HAVE_AES_DECRYPT
+            else
+                return AES_set_decrypt_key(userKey, keylen * 8, aes);
+        #endif
+        }
+    #endif /* WOLFSSL_AESNI */
+
+        ret = wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir);
+
+    #if defined(WOLFSSL_DEVCRYPTO) && \
+        (defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC))
+        aes->ctx.cfd = -1;
+    #endif
+    #ifdef WOLFSSL_IMX6_CAAM_BLOB
+        ForceZero(local, sizeof(local));
+    #endif
+        return ret;
+    }
+
+    #if defined(WOLFSSL_AES_DIRECT) || defined(WOLFSSL_AES_COUNTER)
+        /* AES-CTR and AES-DIRECT need to use this for key setup, no aesni yet */
+        int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen,
+                            const byte* iv, int dir)
+        {
+            int ret;
+
+        #ifdef WOLFSSL_IMX6_CAAM_BLOB
+            byte   local[32];
+            word32 localSz = 32;
+
+            if (keylen == (16 + WC_CAAM_BLOB_SZ) ||
+             keylen == (24 + WC_CAAM_BLOB_SZ) ||
+             keylen == (32 + WC_CAAM_BLOB_SZ)) {
+                if (wc_caamOpenBlob((byte*)userKey, keylen, local, &localSz)
+                        != 0) {
+                    return BAD_FUNC_ARG;
+                }
+
+                /* set local values */
+                userKey = local;
+                keylen = localSz;
+            }
+        #endif
+            ret = wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir);
+
+        #ifdef WOLFSSL_IMX6_CAAM_BLOB
+            ForceZero(local, sizeof(local));
+        #endif
+
+            return ret;
+        }
+    #endif /* WOLFSSL_AES_DIRECT || WOLFSSL_AES_COUNTER */
+#endif /* wc_AesSetKey block */
+
+
+/* wc_AesSetIV is shared between software and hardware */
+int wc_AesSetIV(Aes* aes, const byte* iv)
+{
+    if (aes == NULL)
+        return BAD_FUNC_ARG;
+
+    if (iv)
+        XMEMCPY(aes->reg, iv, AES_BLOCK_SIZE);
+    else
+        XMEMSET(aes->reg,  0, AES_BLOCK_SIZE);
+
+    return 0;
+}
+
+/* AES-DIRECT */
+#if defined(WOLFSSL_AES_DIRECT)
+    #if defined(HAVE_COLDFIRE_SEC)
+        #error "Coldfire SEC doesn't yet support AES direct"
+
+    #elif defined(FREESCALE_LTC)
+        /* Allow direct access to one block encrypt */
+        void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in)
+        {
+            byte *key;
+            uint32_t keySize;
+
+            key = (byte*)aes->key;
+            wc_AesGetKeySize(aes, &keySize);
+
+            LTC_AES_EncryptEcb(LTC_BASE, in, out, AES_BLOCK_SIZE,
+                key, keySize);
+        }
+
+        /* Allow direct access to one block decrypt */
+        void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in)
+        {
+            byte *key;
+            uint32_t keySize;
+
+            key = (byte*)aes->key;
+            wc_AesGetKeySize(aes, &keySize);
+
+            LTC_AES_DecryptEcb(LTC_BASE, in, out, AES_BLOCK_SIZE,
+                key, keySize, kLTC_EncryptKey);
+        }
+
+    #elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
+        /* implemented in wolfcrypt/src/port/caam/caam_aes.c */
+
+    #elif defined(WOLFSSL_AFALG)
+        /* implemented in wolfcrypt/src/port/af_alg/afalg_aes.c */
+
+    #elif defined(WOLFSSL_DEVCRYPTO_AES)
+        /* implemented in wolfcrypt/src/port/devcrypt/devcrypto_aes.c */
+
+    #elif defined(STM32_CRYPTO)
+        /* Allow direct access to one block encrypt */
+        void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in)
+        {
+            if (wolfSSL_CryptHwMutexLock() == 0) {
+                wc_AesEncrypt(aes, in, out);
+                wolfSSL_CryptHwMutexUnLock();
+            }
+        }
+        #ifdef HAVE_AES_DECRYPT
+        /* Allow direct access to one block decrypt */
+        void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in)
+        {
+            if (wolfSSL_CryptHwMutexLock() == 0) {
+                wc_AesDecrypt(aes, in, out);
+                wolfSSL_CryptHwMutexUnLock();
+            }
+        }
+        #endif /* HAVE_AES_DECRYPT */
+
+    #elif defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+        !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_AES)
+        
+        /* Allow direct access to one block encrypt */
+        void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in)
+        {
+            wc_AesEncrypt(aes, in, out);
+        }
+        #ifdef HAVE_AES_DECRYPT
+        /* Allow direct access to one block decrypt */
+        void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in)
+        {
+            wc_AesDecrypt(aes, in, out);
+        }
+        #endif /* HAVE_AES_DECRYPT */
+    #else
+        /* Allow direct access to one block encrypt */
+        void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in)
+        {
+            wc_AesEncrypt(aes, in, out);
+        }
+        #ifdef HAVE_AES_DECRYPT
+        /* Allow direct access to one block decrypt */
+        void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in)
+        {
+            wc_AesDecrypt(aes, in, out);
+        }
+        #endif /* HAVE_AES_DECRYPT */
+    #endif /* AES direct block */
+#endif /* WOLFSSL_AES_DIRECT */
+
+
+/* AES-CBC */
+#ifdef HAVE_AES_CBC
+#if defined(STM32_CRYPTO)
+
+#ifdef WOLFSSL_STM32_CUBEMX
+    int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+    {
+        int ret = 0;
+        word32 blocks = (sz / AES_BLOCK_SIZE);
+        CRYP_HandleTypeDef hcryp;
+
+        ret = wc_Stm32_Aes_Init(aes, &hcryp);
+        if (ret != 0)
+            return ret;
+
+        ret = wolfSSL_CryptHwMutexLock();
+        if (ret != 0) {
+            return ret;
+        }
+
+    #ifdef STM32_CRYPTO_AES_ONLY
+        hcryp.Init.OperatingMode = CRYP_ALGOMODE_ENCRYPT;
+        hcryp.Init.ChainingMode  = CRYP_CHAINMODE_AES_CBC;
+        hcryp.Init.KeyWriteFlag  = CRYP_KEY_WRITE_ENABLE;
+    #elif defined(STM32_HAL_V2)
+        hcryp.Init.Algorithm  = CRYP_AES_CBC;
+        ByteReverseWords(aes->reg, aes->reg, AES_BLOCK_SIZE);
+    #endif
+        hcryp.Init.pInitVect = (STM_CRYPT_TYPE*)aes->reg;
+        HAL_CRYP_Init(&hcryp);
+
+        while (blocks--) {
+        #ifdef STM32_CRYPTO_AES_ONLY
+            ret = HAL_CRYPEx_AES(&hcryp, (uint8_t*)in, AES_BLOCK_SIZE,
+                out, STM32_HAL_TIMEOUT);
+        #elif defined(STM32_HAL_V2)
+            ret = HAL_CRYP_Encrypt(&hcryp, (uint32_t*)in, AES_BLOCK_SIZE,
+                (uint32_t*)out, STM32_HAL_TIMEOUT);
+        #else
+            ret = HAL_CRYP_AESCBC_Encrypt(&hcryp, (uint8_t*)in, AES_BLOCK_SIZE,
+                out, STM32_HAL_TIMEOUT);
+        #endif
+            if (ret != HAL_OK) {
+                ret = WC_TIMEOUT_E;
+                break;
+            }
+
+            /* store iv for next call */
+            XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
+
+            sz  -= AES_BLOCK_SIZE;
+            in  += AES_BLOCK_SIZE;
+            out += AES_BLOCK_SIZE;
+        }
+
+        HAL_CRYP_DeInit(&hcryp);
+
+        wolfSSL_CryptHwMutexUnLock();
+
+        return ret;
+    }
+    #ifdef HAVE_AES_DECRYPT
+    int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+    {
+        int ret = 0;
+        word32 blocks = (sz / AES_BLOCK_SIZE);
+        CRYP_HandleTypeDef hcryp;
+
+        ret = wc_Stm32_Aes_Init(aes, &hcryp);
+        if (ret != 0)
+            return ret;
+
+        ret = wolfSSL_CryptHwMutexLock();
+        if (ret != 0) {
+            return ret;
+        }
+
+        /* if input and output same will overwrite input iv */
+        XMEMCPY(aes->tmp, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
+
+    #ifdef STM32_CRYPTO_AES_ONLY
+        hcryp.Init.OperatingMode = CRYP_ALGOMODE_KEYDERIVATION_DECRYPT;
+        hcryp.Init.ChainingMode  = CRYP_CHAINMODE_AES_CBC;
+        hcryp.Init.KeyWriteFlag  = CRYP_KEY_WRITE_ENABLE;
+    #elif defined(STM32_HAL_V2)
+        hcryp.Init.Algorithm  = CRYP_AES_CBC;
+        ByteReverseWords(aes->reg, aes->reg, AES_BLOCK_SIZE);
+    #endif
+
+        hcryp.Init.pInitVect = (STM_CRYPT_TYPE*)aes->reg;
+        HAL_CRYP_Init(&hcryp);
+
+        while (blocks--) {
+        #ifdef STM32_CRYPTO_AES_ONLY
+            ret = HAL_CRYPEx_AES(&hcryp, (uint8_t*)in, AES_BLOCK_SIZE,
+                out, STM32_HAL_TIMEOUT);
+        #elif defined(STM32_HAL_V2)
+            ret = HAL_CRYP_Decrypt(&hcryp, (uint32_t*)in, AES_BLOCK_SIZE,
+                (uint32_t*)out, STM32_HAL_TIMEOUT);
+        #else
+            ret = HAL_CRYP_AESCBC_Decrypt(&hcryp, (uint8_t*)in, AES_BLOCK_SIZE,
+                out, STM32_HAL_TIMEOUT);
+        #endif
+            if (ret != HAL_OK) {
+                ret = WC_TIMEOUT_E;
+                break;
+            }
+
+            /* store iv for next call */
+            XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE);
+
+            in  += AES_BLOCK_SIZE;
+            out += AES_BLOCK_SIZE;
+        }
+
+        HAL_CRYP_DeInit(&hcryp);
+        wolfSSL_CryptHwMutexUnLock();
+
+        return ret;
+    }
+    #endif /* HAVE_AES_DECRYPT */
+
+#else /* STD_PERI_LIB */
+    int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+    {
+        int ret;
+        word32 *iv;
+        word32 blocks = (sz / AES_BLOCK_SIZE);
+        CRYP_InitTypeDef cryptInit;
+        CRYP_KeyInitTypeDef keyInit;
+        CRYP_IVInitTypeDef ivInit;
+
+        ret = wc_Stm32_Aes_Init(aes, &cryptInit, &keyInit);
+        if (ret != 0)
+            return ret;
+
+        ret = wolfSSL_CryptHwMutexLock();
+        if (ret != 0) {
+            return ret;
+        }
+
+        /* reset registers to their default values */
+        CRYP_DeInit();
+
+        /* set key */
+        CRYP_KeyInit(&keyInit);
+
+        /* set iv */
+        iv = aes->reg;
+        CRYP_IVStructInit(&ivInit);
+        ByteReverseWords(iv, iv, AES_BLOCK_SIZE);
+        ivInit.CRYP_IV0Left  = iv[0];
+        ivInit.CRYP_IV0Right = iv[1];
+        ivInit.CRYP_IV1Left  = iv[2];
+        ivInit.CRYP_IV1Right = iv[3];
+        CRYP_IVInit(&ivInit);
+
+        /* set direction and mode */
+        cryptInit.CRYP_AlgoDir  = CRYP_AlgoDir_Encrypt;
+        cryptInit.CRYP_AlgoMode = CRYP_AlgoMode_AES_CBC;
+        CRYP_Init(&cryptInit);
+
+        /* enable crypto processor */
+        CRYP_Cmd(ENABLE);
+
+        while (blocks--) {
+            /* flush IN/OUT FIFOs */
+            CRYP_FIFOFlush();
+
+            CRYP_DataIn(*(uint32_t*)&in[0]);
+            CRYP_DataIn(*(uint32_t*)&in[4]);
+            CRYP_DataIn(*(uint32_t*)&in[8]);
+            CRYP_DataIn(*(uint32_t*)&in[12]);
+
+            /* wait until the complete message has been processed */
+            while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {}
+
+            *(uint32_t*)&out[0]  = CRYP_DataOut();
+            *(uint32_t*)&out[4]  = CRYP_DataOut();
+            *(uint32_t*)&out[8]  = CRYP_DataOut();
+            *(uint32_t*)&out[12] = CRYP_DataOut();
+
+            /* store iv for next call */
+            XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
+
+            sz  -= AES_BLOCK_SIZE;
+            in  += AES_BLOCK_SIZE;
+            out += AES_BLOCK_SIZE;
+        }
+
+        /* disable crypto processor */
+        CRYP_Cmd(DISABLE);
+        wolfSSL_CryptHwMutexUnLock();
+
+        return ret;
+    }
+
+    #ifdef HAVE_AES_DECRYPT
+    int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+    {
+        int ret;
+        word32 *iv;
+        word32 blocks = (sz / AES_BLOCK_SIZE);
+        CRYP_InitTypeDef cryptInit;
+        CRYP_KeyInitTypeDef keyInit;
+        CRYP_IVInitTypeDef ivInit;
+
+        ret = wc_Stm32_Aes_Init(aes, &cryptInit, &keyInit);
+        if (ret != 0)
+            return ret;
+
+        ret = wolfSSL_CryptHwMutexLock();
+        if (ret != 0) {
+            return ret;
+        }
+
+        /* if input and output same will overwrite input iv */
+        XMEMCPY(aes->tmp, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
+
+        /* reset registers to their default values */
+        CRYP_DeInit();
+
+        /* set direction and key */
+        CRYP_KeyInit(&keyInit);
+        cryptInit.CRYP_AlgoDir  = CRYP_AlgoDir_Decrypt;
+        cryptInit.CRYP_AlgoMode = CRYP_AlgoMode_AES_Key;
+        CRYP_Init(&cryptInit);
+
+        /* enable crypto processor */
+        CRYP_Cmd(ENABLE);
+
+        /* wait until key has been prepared */
+        while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {}
+
+        /* set direction and mode */
+        cryptInit.CRYP_AlgoDir  = CRYP_AlgoDir_Decrypt;
+        cryptInit.CRYP_AlgoMode = CRYP_AlgoMode_AES_CBC;
+        CRYP_Init(&cryptInit);
+
+        /* set iv */
+        iv = aes->reg;
+        CRYP_IVStructInit(&ivInit);
+        ByteReverseWords(iv, iv, AES_BLOCK_SIZE);
+        ivInit.CRYP_IV0Left  = iv[0];
+        ivInit.CRYP_IV0Right = iv[1];
+        ivInit.CRYP_IV1Left  = iv[2];
+        ivInit.CRYP_IV1Right = iv[3];
+        CRYP_IVInit(&ivInit);
+
+        /* enable crypto processor */
+        CRYP_Cmd(ENABLE);
+
+        while (blocks--) {
+            /* flush IN/OUT FIFOs */
+            CRYP_FIFOFlush();
+
+            CRYP_DataIn(*(uint32_t*)&in[0]);
+            CRYP_DataIn(*(uint32_t*)&in[4]);
+            CRYP_DataIn(*(uint32_t*)&in[8]);
+            CRYP_DataIn(*(uint32_t*)&in[12]);
+
+            /* wait until the complete message has been processed */
+            while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {}
+
+            *(uint32_t*)&out[0]  = CRYP_DataOut();
+            *(uint32_t*)&out[4]  = CRYP_DataOut();
+            *(uint32_t*)&out[8]  = CRYP_DataOut();
+            *(uint32_t*)&out[12] = CRYP_DataOut();
+
+            /* store iv for next call */
+            XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE);
+
+            in  += AES_BLOCK_SIZE;
+            out += AES_BLOCK_SIZE;
+        }
+
+        /* disable crypto processor */
+        CRYP_Cmd(DISABLE);
+        wolfSSL_CryptHwMutexUnLock();
+
+        return ret;
+    }
+    #endif /* HAVE_AES_DECRYPT */
+#endif /* WOLFSSL_STM32_CUBEMX */
+
+#elif defined(HAVE_COLDFIRE_SEC)
+    static int wc_AesCbcCrypt(Aes* aes, byte* po, const byte* pi, word32 sz,
+        word32 descHeader)
+    {
+        #ifdef DEBUG_WOLFSSL
+            int i; int stat1, stat2; int ret;
+        #endif
+
+        int size;
+        volatile int v;
+
+        if ((pi == NULL) || (po == NULL))
+            return BAD_FUNC_ARG;    /*wrong pointer*/
+
+        wc_LockMutex(&Mutex_AesSEC);
+
+        /* Set descriptor for SEC */
+        secDesc->length1 = 0x0;
+        secDesc->pointer1 = NULL;
+
+        secDesc->length2 = AES_BLOCK_SIZE;
+        secDesc->pointer2 = (byte *)secReg; /* Initial Vector */
+
+        switch(aes->rounds) {
+            case 10: secDesc->length3 = 16; break;
+            case 12: secDesc->length3 = 24; break;
+            case 14: secDesc->length3 = 32; break;
+        }
+        XMEMCPY(secKey, aes->key, secDesc->length3);
+
+        secDesc->pointer3 = (byte *)secKey;
+        secDesc->pointer4 = AESBuffIn;
+        secDesc->pointer5 = AESBuffOut;
+        secDesc->length6 = 0x0;
+        secDesc->pointer6 = NULL;
+        secDesc->length7 = 0x0;
+        secDesc->pointer7 = NULL;
+        secDesc->nextDescriptorPtr = NULL;
+
+        while (sz) {
+            secDesc->header = descHeader;
+            XMEMCPY(secReg, aes->reg, AES_BLOCK_SIZE);
+            if ((sz % AES_BUFFER_SIZE) == sz) {
+                size = sz;
+                sz = 0;
+            } else {
+                size = AES_BUFFER_SIZE;
+                sz -= AES_BUFFER_SIZE;
+            }
+            secDesc->length4 = size;
+            secDesc->length5 = size;
+
+            XMEMCPY(AESBuffIn, pi, size);
+            if(descHeader == SEC_DESC_AES_CBC_DECRYPT) {
+                XMEMCPY((void*)aes->tmp, (void*)&(pi[size-AES_BLOCK_SIZE]),
+                        AES_BLOCK_SIZE);
+            }
+
+            /* Point SEC to the location of the descriptor */
+            MCF_SEC_FR0 = (uint32)secDesc;
+            /* Initialize SEC and wait for encryption to complete */
+            MCF_SEC_CCCR0 = 0x0000001a;
+            /* poll SISR to determine when channel is complete */
+            v=0;
+
+            while ((secDesc->header>> 24) != 0xff) v++;
+
+            #ifdef DEBUG_WOLFSSL
+                ret = MCF_SEC_SISRH;
+                stat1 = MCF_SEC_AESSR;
+                stat2 = MCF_SEC_AESISR;
+                if (ret & 0xe0000000) {
+                    db_printf("Aes_Cbc(i=%d):ISRH=%08x, AESSR=%08x, "
+                              "AESISR=%08x\n", i, ret, stat1, stat2);
+                }
+            #endif
+
+            XMEMCPY(po, AESBuffOut, size);
+
+            if (descHeader == SEC_DESC_AES_CBC_ENCRYPT) {
+                XMEMCPY((void*)aes->reg, (void*)&(po[size-AES_BLOCK_SIZE]),
+                        AES_BLOCK_SIZE);
+            } else {
+                XMEMCPY((void*)aes->reg, (void*)aes->tmp, AES_BLOCK_SIZE);
+            }
+
+            pi += size;
+            po += size;
+        }
+
+        wc_UnLockMutex(&Mutex_AesSEC);
+        return 0;
+    }
+
+    int wc_AesCbcEncrypt(Aes* aes, byte* po, const byte* pi, word32 sz)
+    {
+        return (wc_AesCbcCrypt(aes, po, pi, sz, SEC_DESC_AES_CBC_ENCRYPT));
+    }
+
+    #ifdef HAVE_AES_DECRYPT
+    int wc_AesCbcDecrypt(Aes* aes, byte* po, const byte* pi, word32 sz)
+    {
+        return (wc_AesCbcCrypt(aes, po, pi, sz, SEC_DESC_AES_CBC_DECRYPT));
+    }
+    #endif /* HAVE_AES_DECRYPT */
+
+#elif defined(FREESCALE_LTC)
+    int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+    {
+        uint32_t keySize;
+        status_t status;
+        byte *iv, *enc_key;
+        word32 blocks = (sz / AES_BLOCK_SIZE);
+
+        iv      = (byte*)aes->reg;
+        enc_key = (byte*)aes->key;
+
+        status = wc_AesGetKeySize(aes, &keySize);
+        if (status != 0) {
+            return status;
+        }
+
+        status = LTC_AES_EncryptCbc(LTC_BASE, in, out, blocks * AES_BLOCK_SIZE,
+            iv, enc_key, keySize);
+
+        /* store iv for next call */
+        if (status == kStatus_Success) {
+            XMEMCPY(iv, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
+        }
+
+        return (status == kStatus_Success) ? 0 : -1;
+    }
+
+    #ifdef HAVE_AES_DECRYPT
+    int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+    {
+        uint32_t keySize;
+        status_t status;
+        byte* iv, *dec_key;
+        word32 blocks = (sz / AES_BLOCK_SIZE);
+        byte temp_block[AES_BLOCK_SIZE];
+
+        iv      = (byte*)aes->reg;
+        dec_key = (byte*)aes->key;
+
+        status = wc_AesGetKeySize(aes, &keySize);
+        if (status != 0) {
+            return status;
+        }
+
+        /* get IV for next call */
+        XMEMCPY(temp_block, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
+
+        status = LTC_AES_DecryptCbc(LTC_BASE, in, out, blocks * AES_BLOCK_SIZE,
+            iv, dec_key, keySize, kLTC_EncryptKey);
+
+        /* store IV for next call */
+        if (status == kStatus_Success) {
+            XMEMCPY(iv, temp_block, AES_BLOCK_SIZE);
+        }
+
+        return (status == kStatus_Success) ? 0 : -1;
+    }
+    #endif /* HAVE_AES_DECRYPT */
+
+#elif defined(FREESCALE_MMCAU)
+    int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+    {
+        int i;
+        int offset = 0;
+        word32 blocks = (sz / AES_BLOCK_SIZE);
+        byte *iv;
+        byte temp_block[AES_BLOCK_SIZE];
+
+        iv      = (byte*)aes->reg;
+
+        while (blocks--) {
+            XMEMCPY(temp_block, in + offset, AES_BLOCK_SIZE);
+
+            /* XOR block with IV for CBC */
+            for (i = 0; i < AES_BLOCK_SIZE; i++)
+                temp_block[i] ^= iv[i];
+
+            wc_AesEncrypt(aes, temp_block, out + offset);
+
+            offset += AES_BLOCK_SIZE;
+
+            /* store IV for next block */
+            XMEMCPY(iv, out + offset - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
+        }
+
+        return 0;
+    }
+    #ifdef HAVE_AES_DECRYPT
+    int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+    {
+        int i;
+        int offset = 0;
+        word32 blocks = (sz / AES_BLOCK_SIZE);
+        byte* iv;
+        byte temp_block[AES_BLOCK_SIZE];
+
+        iv      = (byte*)aes->reg;
+
+        while (blocks--) {
+            XMEMCPY(temp_block, in + offset, AES_BLOCK_SIZE);
+
+            wc_AesDecrypt(aes, in + offset, out + offset);
+
+            /* XOR block with IV for CBC */
+            for (i = 0; i < AES_BLOCK_SIZE; i++)
+                (out + offset)[i] ^= iv[i];
+
+            /* store IV for next block */
+            XMEMCPY(iv, temp_block, AES_BLOCK_SIZE);
+
+            offset += AES_BLOCK_SIZE;
+        }
+
+        return 0;
+    }
+    #endif /* HAVE_AES_DECRYPT */
+
+#elif defined(WOLFSSL_PIC32MZ_CRYPT)
+
+    int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+    {
+        int ret;
+
+        /* hardware fails on input that is not a multiple of AES block size */
+        if (sz % AES_BLOCK_SIZE != 0) {
+            return BAD_FUNC_ARG;
+        }
+
+        ret = wc_Pic32AesCrypt(
+            aes->key, aes->keylen, aes->reg, AES_BLOCK_SIZE,
+            out, in, sz, PIC32_ENCRYPTION,
+            PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCBC);
+
+        /* store iv for next call */
+        if (ret == 0) {
+            XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
+        }
+
+        return ret;
+    }
+    #ifdef HAVE_AES_DECRYPT
+    int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+    {
+        int ret;
+        byte scratch[AES_BLOCK_SIZE];
+
+        /* hardware fails on input that is not a multiple of AES block size */
+        if (sz % AES_BLOCK_SIZE != 0) {
+            return BAD_FUNC_ARG;
+        }
+        XMEMCPY(scratch, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
+
+        ret = wc_Pic32AesCrypt(
+            aes->key, aes->keylen, aes->reg, AES_BLOCK_SIZE,
+            out, in, sz, PIC32_DECRYPTION,
+            PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCBC);
+
+        /* store iv for next call */
+        if (ret == 0) {
+            XMEMCPY((byte*)aes->reg, scratch, AES_BLOCK_SIZE);
+        }
+
+        return ret;
+    }
+    #endif /* HAVE_AES_DECRYPT */
+#elif defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_AES)
+
+    int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+    {
+        return wc_esp32AesCbcEncrypt(aes, out, in, sz);
+    }
+    int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+    {
+        return wc_esp32AesCbcDecrypt(aes, out, in, sz);
+    }
+#elif defined(WOLFSSL_CRYPTOCELL) && defined(WOLFSSL_CRYPTOCELL_AES)
+    int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+    {
+        return SaSi_AesBlock(&aes->ctx.user_ctx, (uint8_t* )in, sz, out);
+    }
+    int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+    {
+        return SaSi_AesBlock(&aes->ctx.user_ctx, (uint8_t* )in, sz, out);
+    }
+#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
+      /* implemented in wolfcrypt/src/port/caam/caam_aes.c */
+
+#elif defined(WOLFSSL_AFALG)
+    /* implemented in wolfcrypt/src/port/af_alg/afalg_aes.c */
+
+#elif defined(WOLFSSL_DEVCRYPTO_CBC)
+    /* implemented in wolfcrypt/src/port/devcrypt/devcrypto_aes.c */
+
+#else
+
+    /* Software AES - CBC Encrypt */
+    int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+    {
+        word32 blocks = (sz / AES_BLOCK_SIZE);
+
+        if (aes == NULL || out == NULL || in == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+    #ifdef WOLF_CRYPTO_CB
+        if (aes->devId != INVALID_DEVID) {
+            int ret = wc_CryptoCb_AesCbcEncrypt(aes, out, in, sz);
+            if (ret != CRYPTOCB_UNAVAILABLE)
+                return ret;
+            /* fall-through when unavailable */
+        }
+    #endif
+    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES)
+        /* if async and byte count above threshold */
+        if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES &&
+                                                sz >= WC_ASYNC_THRESH_AES_CBC) {
+        #if defined(HAVE_CAVIUM)
+            return NitroxAesCbcEncrypt(aes, out, in, sz);
+        #elif defined(HAVE_INTEL_QA)
+            return IntelQaSymAesCbcEncrypt(&aes->asyncDev, out, in, sz,
+                (const byte*)aes->devKey, aes->keylen,
+                (byte*)aes->reg, AES_BLOCK_SIZE);
+        #else /* WOLFSSL_ASYNC_CRYPT_TEST */
+            if (wc_AsyncTestInit(&aes->asyncDev, ASYNC_TEST_AES_CBC_ENCRYPT)) {
+                WC_ASYNC_TEST* testDev = &aes->asyncDev.test;
+                testDev->aes.aes = aes;
+                testDev->aes.out = out;
+                testDev->aes.in = in;
+                testDev->aes.sz = sz;
+                return WC_PENDING_E;
+            }
+        #endif
+        }
+    #endif /* WOLFSSL_ASYNC_CRYPT */
+
+    #ifdef WOLFSSL_AESNI
+        if (haveAESNI) {
+            #ifdef DEBUG_AESNI
+                printf("about to aes cbc encrypt\n");
+                printf("in  = %p\n", in);
+                printf("out = %p\n", out);
+                printf("aes->key = %p\n", aes->key);
+                printf("aes->reg = %p\n", aes->reg);
+                printf("aes->rounds = %d\n", aes->rounds);
+                printf("sz = %d\n", sz);
+            #endif
+
+            /* check alignment, decrypt doesn't need alignment */
+            if ((wolfssl_word)in % AESNI_ALIGN) {
+            #ifndef NO_WOLFSSL_ALLOC_ALIGN
+                byte* tmp = (byte*)XMALLOC(sz + AES_BLOCK_SIZE + AESNI_ALIGN,
+                                            aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
+                byte* tmp_align;
+                if (tmp == NULL) return MEMORY_E;
+
+                tmp_align = tmp + (AESNI_ALIGN - ((size_t)tmp % AESNI_ALIGN));
+                XMEMCPY(tmp_align, in, sz);
+                AES_CBC_encrypt(tmp_align, tmp_align, (byte*)aes->reg, sz,
+                                                  (byte*)aes->key, aes->rounds);
+                /* store iv for next call */
+                XMEMCPY(aes->reg, tmp_align + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
+
+                XMEMCPY(out, tmp_align, sz);
+                XFREE(tmp, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
+                return 0;
+            #else
+                WOLFSSL_MSG("AES-CBC encrypt with bad alignment");
+                return BAD_ALIGN_E;
+            #endif
+            }
+
+            AES_CBC_encrypt(in, out, (byte*)aes->reg, sz, (byte*)aes->key,
+                            aes->rounds);
+            /* store iv for next call */
+            XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
+
+            return 0;
+        }
+    #endif
+
+        while (blocks--) {
+            xorbuf((byte*)aes->reg, in, AES_BLOCK_SIZE);
+            wc_AesEncrypt(aes, (byte*)aes->reg, (byte*)aes->reg);
+            XMEMCPY(out, aes->reg, AES_BLOCK_SIZE);
+
+            out += AES_BLOCK_SIZE;
+            in  += AES_BLOCK_SIZE;
+        }
+
+        return 0;
+    }
+
+    #ifdef HAVE_AES_DECRYPT
+    /* Software AES - CBC Decrypt */
+    int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+    {
+        word32 blocks;
+
+        if (aes == NULL || out == NULL || in == NULL
+                                       || sz % AES_BLOCK_SIZE != 0) {
+            return BAD_FUNC_ARG;
+        }
+
+    #ifdef WOLF_CRYPTO_CB
+        if (aes->devId != INVALID_DEVID) {
+            int ret = wc_CryptoCb_AesCbcDecrypt(aes, out, in, sz);
+            if (ret != CRYPTOCB_UNAVAILABLE)
+                return ret;
+            /* fall-through when unavailable */
+        }
+    #endif
+    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES)
+        /* if async and byte count above threshold */
+        if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES &&
+                                                sz >= WC_ASYNC_THRESH_AES_CBC) {
+        #if defined(HAVE_CAVIUM)
+            return NitroxAesCbcDecrypt(aes, out, in, sz);
+        #elif defined(HAVE_INTEL_QA)
+            return IntelQaSymAesCbcDecrypt(&aes->asyncDev, out, in, sz,
+                (const byte*)aes->devKey, aes->keylen,
+                (byte*)aes->reg, AES_BLOCK_SIZE);
+        #else /* WOLFSSL_ASYNC_CRYPT_TEST */
+            if (wc_AsyncTestInit(&aes->asyncDev, ASYNC_TEST_AES_CBC_DECRYPT)) {
+                WC_ASYNC_TEST* testDev = &aes->asyncDev.test;
+                testDev->aes.aes = aes;
+                testDev->aes.out = out;
+                testDev->aes.in = in;
+                testDev->aes.sz = sz;
+                return WC_PENDING_E;
+            }
+        #endif
+        }
+    #endif
+
+    #ifdef WOLFSSL_AESNI
+        if (haveAESNI) {
+            #ifdef DEBUG_AESNI
+                printf("about to aes cbc decrypt\n");
+                printf("in  = %p\n", in);
+                printf("out = %p\n", out);
+                printf("aes->key = %p\n", aes->key);
+                printf("aes->reg = %p\n", aes->reg);
+                printf("aes->rounds = %d\n", aes->rounds);
+                printf("sz = %d\n", sz);
+            #endif
+
+            /* if input and output same will overwrite input iv */
+            XMEMCPY(aes->tmp, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
+            #if defined(WOLFSSL_AESNI_BY4)
+            AES_CBC_decrypt_by4(in, out, (byte*)aes->reg, sz, (byte*)aes->key,
+                            aes->rounds);
+            #elif defined(WOLFSSL_AESNI_BY6)
+            AES_CBC_decrypt_by6(in, out, (byte*)aes->reg, sz, (byte*)aes->key,
+                            aes->rounds);
+            #else /* WOLFSSL_AESNI_BYx */
+            AES_CBC_decrypt_by8(in, out, (byte*)aes->reg, sz, (byte*)aes->key,
+                            aes->rounds);
+            #endif /* WOLFSSL_AESNI_BYx */
+            /* store iv for next call */
+            XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE);
+            return 0;
+        }
+    #endif
+
+        blocks = sz / AES_BLOCK_SIZE;
+        while (blocks--) {
+            XMEMCPY(aes->tmp, in, AES_BLOCK_SIZE);
+            wc_AesDecrypt(aes, (byte*)aes->tmp, out);
+            xorbuf(out, (byte*)aes->reg, AES_BLOCK_SIZE);
+            /* store iv for next call */
+            XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE);
+
+            out += AES_BLOCK_SIZE;
+            in  += AES_BLOCK_SIZE;
+        }
+
+        return 0;
+    }
+    #endif
+
+#endif /* AES-CBC block */
+#endif /* HAVE_AES_CBC */
+
+/* AES-CTR */
+#if defined(WOLFSSL_AES_COUNTER)
+
+    #ifdef STM32_CRYPTO
+        #define NEED_AES_CTR_SOFT
+        #define XTRANSFORM_AESCTRBLOCK wc_AesCtrEncryptBlock
+
+        int wc_AesCtrEncryptBlock(Aes* aes, byte* out, const byte* in)
+        {
+            int ret = 0;
+        #ifdef WOLFSSL_STM32_CUBEMX
+            CRYP_HandleTypeDef hcryp;
+            #ifdef STM32_HAL_V2
+            word32 iv[AES_BLOCK_SIZE/sizeof(word32)];
+            #endif
+        #else
+            word32 *iv;
+            CRYP_InitTypeDef cryptInit;
+            CRYP_KeyInitTypeDef keyInit;
+            CRYP_IVInitTypeDef ivInit;
+        #endif
+
+            ret = wolfSSL_CryptHwMutexLock();
+            if (ret != 0) {
+                return ret;
+            }
+
+        #ifdef WOLFSSL_STM32_CUBEMX
+            ret = wc_Stm32_Aes_Init(aes, &hcryp);
+            if (ret != 0) {
+                wolfSSL_CryptHwMutexUnLock();
+                return ret;
+            }
+
+        #ifdef STM32_CRYPTO_AES_ONLY
+            hcryp.Init.OperatingMode = CRYP_ALGOMODE_ENCRYPT;
+            hcryp.Init.ChainingMode  = CRYP_CHAINMODE_AES_CTR;
+            hcryp.Init.KeyWriteFlag  = CRYP_KEY_WRITE_ENABLE;
+            hcryp.Init.pInitVect = (STM_CRYPT_TYPE*)aes->reg;
+        #elif defined(STM32_HAL_V2)
+            hcryp.Init.Algorithm  = CRYP_AES_CTR;
+            ByteReverseWords(iv, aes->reg, AES_BLOCK_SIZE);
+            hcryp.Init.pInitVect = (STM_CRYPT_TYPE*)iv;
+        #else
+            hcryp.Init.pInitVect = (STM_CRYPT_TYPE*)aes->reg;
+        #endif
+            HAL_CRYP_Init(&hcryp);
+
+        #ifdef STM32_CRYPTO_AES_ONLY
+            ret = HAL_CRYPEx_AES(&hcryp, (byte*)in, AES_BLOCK_SIZE,
+                out, STM32_HAL_TIMEOUT);
+        #elif defined(STM32_HAL_V2)
+            ret = HAL_CRYP_Encrypt(&hcryp, (uint32_t*)in, AES_BLOCK_SIZE,
+                (uint32_t*)out, STM32_HAL_TIMEOUT);
+        #else
+            ret = HAL_CRYP_AESCTR_Encrypt(&hcryp, (byte*)in, AES_BLOCK_SIZE,
+                out, STM32_HAL_TIMEOUT);
+        #endif
+            if (ret != HAL_OK) {
+                ret = WC_TIMEOUT_E;
+            }
+            HAL_CRYP_DeInit(&hcryp);
+
+        #else /* STD_PERI_LIB */
+            ret = wc_Stm32_Aes_Init(aes, &cryptInit, &keyInit);
+            if (ret != 0) {
+                wolfSSL_CryptHwMutexUnLock();
+                return ret;
+            }
+
+            /* reset registers to their default values */
+            CRYP_DeInit();
+
+            /* set key */
+            CRYP_KeyInit(&keyInit);
+
+            /* set iv */
+            iv = aes->reg;
+            CRYP_IVStructInit(&ivInit);
+            ivInit.CRYP_IV0Left  = ByteReverseWord32(iv[0]);
+            ivInit.CRYP_IV0Right = ByteReverseWord32(iv[1]);
+            ivInit.CRYP_IV1Left  = ByteReverseWord32(iv[2]);
+            ivInit.CRYP_IV1Right = ByteReverseWord32(iv[3]);
+            CRYP_IVInit(&ivInit);
+
+            /* set direction and mode */
+            cryptInit.CRYP_AlgoDir  = CRYP_AlgoDir_Encrypt;
+            cryptInit.CRYP_AlgoMode = CRYP_AlgoMode_AES_CTR;
+            CRYP_Init(&cryptInit);
+
+            /* enable crypto processor */
+            CRYP_Cmd(ENABLE);
+
+            /* flush IN/OUT FIFOs */
+            CRYP_FIFOFlush();
+
+            CRYP_DataIn(*(uint32_t*)&in[0]);
+            CRYP_DataIn(*(uint32_t*)&in[4]);
+            CRYP_DataIn(*(uint32_t*)&in[8]);
+            CRYP_DataIn(*(uint32_t*)&in[12]);
+
+            /* wait until the complete message has been processed */
+            while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {}
+
+            *(uint32_t*)&out[0]  = CRYP_DataOut();
+            *(uint32_t*)&out[4]  = CRYP_DataOut();
+            *(uint32_t*)&out[8]  = CRYP_DataOut();
+            *(uint32_t*)&out[12] = CRYP_DataOut();
+
+            /* disable crypto processor */
+            CRYP_Cmd(DISABLE);
+
+        #endif /* WOLFSSL_STM32_CUBEMX */
+
+            wolfSSL_CryptHwMutexUnLock();
+            return ret;
+        }
+
+
+    #elif defined(WOLFSSL_PIC32MZ_CRYPT)
+
+        #define NEED_AES_CTR_SOFT
+        #define XTRANSFORM_AESCTRBLOCK wc_AesCtrEncryptBlock
+
+        int wc_AesCtrEncryptBlock(Aes* aes, byte* out, const byte* in)
+        {
+            word32 tmpIv[AES_BLOCK_SIZE / sizeof(word32)];
+            XMEMCPY(tmpIv, aes->reg, AES_BLOCK_SIZE);
+            return wc_Pic32AesCrypt(
+                aes->key, aes->keylen, tmpIv, AES_BLOCK_SIZE,
+                out, in, AES_BLOCK_SIZE,
+                PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCTR);
+        }
+
+    #elif defined(HAVE_COLDFIRE_SEC)
+        #error "Coldfire SEC doesn't currently support AES-CTR mode"
+
+    #elif defined(FREESCALE_LTC)
+        int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+        {
+            uint32_t keySize;
+            byte *iv, *enc_key;
+            byte* tmp;
+
+            if (aes == NULL || out == NULL || in == NULL) {
+                return BAD_FUNC_ARG;
+            }
+
+            /* consume any unused bytes left in aes->tmp */
+            tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left;
+            while (aes->left && sz) {
+                *(out++) = *(in++) ^ *(tmp++);
+                aes->left--;
+                sz--;
+            }
+
+            if (sz) {
+                iv      = (byte*)aes->reg;
+                enc_key = (byte*)aes->key;
+
+                wc_AesGetKeySize(aes, &keySize);
+
+                LTC_AES_CryptCtr(LTC_BASE, in, out, sz,
+                    iv, enc_key, keySize, (byte*)aes->tmp,
+                    (uint32_t*)&aes->left);
+            }
+
+            return 0;
+        }
+
+    #elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
+        /* implemented in wolfcrypt/src/port/caam/caam_aes.c */
+
+    #elif defined(WOLFSSL_AFALG)
+        /* implemented in wolfcrypt/src/port/af_alg/afalg_aes.c */
+
+    #elif defined(WOLFSSL_DEVCRYPTO_AES)
+        /* implemented in wolfcrypt/src/port/devcrypt/devcrypto_aes.c */
+   
+    #elif defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+        !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_AES)
+        /* esp32 doesn't support CRT mode by hw.     */
+        /* use aes ecnryption plus sw implementation */
+        #define NEED_AES_CTR_SOFT
+
+    #else
+
+        /* Use software based AES counter */
+        #define NEED_AES_CTR_SOFT
+    #endif
+
+    #ifdef NEED_AES_CTR_SOFT
+        /* Increment AES counter */
+        static WC_INLINE void IncrementAesCounter(byte* inOutCtr)
+        {
+            /* in network byte order so start at end and work back */
+            int i;
+            for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) {
+                if (++inOutCtr[i])  /* we're done unless we overflow */
+                    return;
+            }
+        }
+
+        /* Software AES - CTR Encrypt */
+        int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+        {
+            byte* tmp;
+            byte scratch[AES_BLOCK_SIZE];
+
+            if (aes == NULL || out == NULL || in == NULL) {
+                return BAD_FUNC_ARG;
+            }
+
+            /* consume any unused bytes left in aes->tmp */
+            tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left;
+            while (aes->left && sz) {
+               *(out++) = *(in++) ^ *(tmp++);
+               aes->left--;
+               sz--;
+            }
+
+            /* do as many block size ops as possible */
+            while (sz >= AES_BLOCK_SIZE) {
+            #ifdef XTRANSFORM_AESCTRBLOCK
+                XTRANSFORM_AESCTRBLOCK(aes, out, in);
+            #else
+                wc_AesEncrypt(aes, (byte*)aes->reg, scratch);
+                xorbuf(scratch, in, AES_BLOCK_SIZE);
+                XMEMCPY(out, scratch, AES_BLOCK_SIZE);
+            #endif
+                IncrementAesCounter((byte*)aes->reg);
+
+                out += AES_BLOCK_SIZE;
+                in  += AES_BLOCK_SIZE;
+                sz  -= AES_BLOCK_SIZE;
+                aes->left = 0;
+            }
+            ForceZero(scratch, AES_BLOCK_SIZE);
+
+            /* handle non block size remaining and store unused byte count in left */
+            if (sz) {
+                wc_AesEncrypt(aes, (byte*)aes->reg, (byte*)aes->tmp);
+                IncrementAesCounter((byte*)aes->reg);
+
+                aes->left = AES_BLOCK_SIZE;
+                tmp = (byte*)aes->tmp;
+
+                while (sz--) {
+                    *(out++) = *(in++) ^ *(tmp++);
+                    aes->left--;
+                }
+            }
+
+            return 0;
+        }
+
+    #endif /* NEED_AES_CTR_SOFT */
+
+#endif /* WOLFSSL_AES_COUNTER */
+#endif /* !WOLFSSL_ARMASM */
+
+
+/*
+ * The IV for AES GCM and CCM, stored in struct Aes's member reg, is comprised
+ * of two parts in order:
+ *   1. The fixed field which may be 0 or 4 bytes long. In TLS, this is set
+ *      to the implicit IV.
+ *   2. The explicit IV is generated by wolfCrypt. It needs to be managed
+ *      by wolfCrypt to ensure the IV is unique for each call to encrypt.
+ * The IV may be a 96-bit random value, or the 32-bit fixed value and a
+ * 64-bit set of 0 or random data. The final 32-bits of reg is used as a
+ * block counter during the encryption.
+ */
+
+#if (defined(HAVE_AESGCM) && !defined(WC_NO_RNG)) || defined(HAVE_AESCCM)
+static WC_INLINE void IncCtr(byte* ctr, word32 ctrSz)
+{
+    int i;
+    for (i = ctrSz-1; i >= 0; i--) {
+        if (++ctr[i])
+            break;
+    }
+}
+#endif /* HAVE_AESGCM || HAVE_AESCCM */
+
+
+#ifdef HAVE_AESGCM
+
+#if defined(HAVE_COLDFIRE_SEC)
+    #error "Coldfire SEC doesn't currently support AES-GCM mode"
+
+#elif defined(WOLFSSL_NRF51_AES)
+    #error "nRF51 doesn't currently support AES-GCM mode"
+
+#endif
+
+#ifdef WOLFSSL_ARMASM
+    /* implementation is located in wolfcrypt/src/port/arm/armv8-aes.c */
+
+#elif defined(WOLFSSL_AFALG)
+    /* implemented in wolfcrypt/src/port/afalg/afalg_aes.c */
+
+#elif defined(WOLFSSL_DEVCRYPTO_AES)
+    /* implemented in wolfcrypt/src/port/devcrypt/devcrypto_aes.c */
+
+#else /* software + AESNI implementation */
+
+#if !defined(FREESCALE_LTC_AES_GCM)
+static WC_INLINE void IncrementGcmCounter(byte* inOutCtr)
+{
+    int i;
+
+    /* in network byte order so start at end and work back */
+    for (i = AES_BLOCK_SIZE - 1; i >= AES_BLOCK_SIZE - CTR_SZ; i--) {
+        if (++inOutCtr[i])  /* we're done unless we overflow */
+            return;
+    }
+}
+#ifdef STM32_CRYPTO_AES_GCM
+static WC_INLINE void DecrementGcmCounter(byte* inOutCtr)
+{
+    int i;
+
+    /* in network byte order so start at end and work back */
+    for (i = AES_BLOCK_SIZE - 1; i >= AES_BLOCK_SIZE - CTR_SZ; i--) {
+        if (--inOutCtr[i] != 0xFF)  /* we're done unless we underflow */
+            return;
+    }
+}
+#endif /* STM32_CRYPTO_AES_GCM */
+#endif /* !FREESCALE_LTC_AES_GCM */
+
+#if defined(GCM_SMALL) || defined(GCM_TABLE)
+
+static WC_INLINE void FlattenSzInBits(byte* buf, word32 sz)
+{
+    /* Multiply the sz by 8 */
+    word32 szHi = (sz >> (8*sizeof(sz) - 3));
+    sz <<= 3;
+
+    /* copy over the words of the sz into the destination buffer */
+    buf[0] = (szHi >> 24) & 0xff;
+    buf[1] = (szHi >> 16) & 0xff;
+    buf[2] = (szHi >>  8) & 0xff;
+    buf[3] = szHi & 0xff;
+    buf[4] = (sz >> 24) & 0xff;
+    buf[5] = (sz >> 16) & 0xff;
+    buf[6] = (sz >>  8) & 0xff;
+    buf[7] = sz & 0xff;
+}
+
+
+static WC_INLINE void RIGHTSHIFTX(byte* x)
+{
+    int i;
+    int carryOut = 0;
+    int carryIn = 0;
+    int borrow = x[15] & 0x01;
+
+    for (i = 0; i < AES_BLOCK_SIZE; i++) {
+        carryOut = x[i] & 0x01;
+        x[i] = (x[i] >> 1) | (carryIn ? 0x80 : 0);
+        carryIn = carryOut;
+    }
+    if (borrow) x[0] ^= 0xE1;
+}
+
+#endif /* defined(GCM_SMALL) || defined(GCM_TABLE) */
+
+
+#ifdef GCM_TABLE
+
+static void GenerateM0(Aes* aes)
+{
+    int i, j;
+    byte (*m)[AES_BLOCK_SIZE] = aes->M0;
+
+    XMEMCPY(m[128], aes->H, AES_BLOCK_SIZE);
+
+    for (i = 64; i > 0; i /= 2) {
+        XMEMCPY(m[i], m[i*2], AES_BLOCK_SIZE);
+        RIGHTSHIFTX(m[i]);
+    }
+
+    for (i = 2; i < 256; i *= 2) {
+        for (j = 1; j < i; j++) {
+            XMEMCPY(m[i+j], m[i], AES_BLOCK_SIZE);
+            xorbuf(m[i+j], m[j], AES_BLOCK_SIZE);
+        }
+    }
+
+    XMEMSET(m[0], 0, AES_BLOCK_SIZE);
+}
+
+#endif /* GCM_TABLE */
+
+/* Software AES - GCM SetKey */
+int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
+{
+    int  ret;
+    byte iv[AES_BLOCK_SIZE];
+
+    #ifdef WOLFSSL_IMX6_CAAM_BLOB
+        byte   local[32];
+        word32 localSz = 32;
+
+        if (len == (16 + WC_CAAM_BLOB_SZ) ||
+          len == (24 + WC_CAAM_BLOB_SZ) ||
+          len == (32 + WC_CAAM_BLOB_SZ)) {
+            if (wc_caamOpenBlob((byte*)key, len, local, &localSz) != 0) {
+                 return BAD_FUNC_ARG;
+            }
+
+            /* set local values */
+            key = local;
+            len = localSz;
+        }
+    #endif
+
+    if (!((len == 16) || (len == 24) || (len == 32)))
+        return BAD_FUNC_ARG;
+
+#ifdef OPENSSL_EXTRA
+    if (aes != NULL) {
+        XMEMSET(aes->aadH, 0, sizeof(aes->aadH));
+        aes->aadLen = 0;
+    }
+#endif
+    XMEMSET(iv, 0, AES_BLOCK_SIZE);
+    ret = wc_AesSetKey(aes, key, len, iv, AES_ENCRYPTION);
+
+    #ifdef WOLFSSL_AESNI
+        /* AES-NI code generates its own H value. */
+        if (haveAESNI)
+            return ret;
+    #endif /* WOLFSSL_AESNI */
+
+#if !defined(FREESCALE_LTC_AES_GCM)
+    if (ret == 0) {
+        wc_AesEncrypt(aes, iv, aes->H);
+    #ifdef GCM_TABLE
+        GenerateM0(aes);
+    #endif /* GCM_TABLE */
+    }
+#endif /* FREESCALE_LTC_AES_GCM */
+
+#if defined(WOLFSSL_XILINX_CRYPT)
+    wc_AesGcmSetKey_ex(aes, key, len, XSECURE_CSU_AES_KEY_SRC_KUP);
+#elif defined(WOLFSSL_AFALG_XILINX_AES)
+    wc_AesGcmSetKey_ex(aes, key, len, 0);
+#endif
+
+#ifdef WOLF_CRYPTO_CB
+    if (aes->devId != INVALID_DEVID) {
+        XMEMCPY(aes->devKey, key, len);
+    }
+#endif
+
+#ifdef WOLFSSL_IMX6_CAAM_BLOB
+    ForceZero(local, sizeof(local));
+#endif
+
+    return ret;
+}
+
+
+#ifdef WOLFSSL_AESNI
+
+#if defined(USE_INTEL_SPEEDUP)
+    #define HAVE_INTEL_AVX1
+    #define HAVE_INTEL_AVX2
+#endif /* USE_INTEL_SPEEDUP */
+
+#ifndef _MSC_VER
+
+void AES_GCM_encrypt(const unsigned char *in, unsigned char *out,
+                     const unsigned char* addt, const unsigned char* ivec,
+                     unsigned char *tag, unsigned int nbytes,
+                     unsigned int abytes, unsigned int ibytes,
+                     unsigned int tbytes, const unsigned char* key, int nr)
+                     XASM_LINK("AES_GCM_encrypt");
+#ifdef HAVE_INTEL_AVX1
+void AES_GCM_encrypt_avx1(const unsigned char *in, unsigned char *out,
+                          const unsigned char* addt, const unsigned char* ivec,
+                          unsigned char *tag, unsigned int nbytes,
+                          unsigned int abytes, unsigned int ibytes,
+                          unsigned int tbytes, const unsigned char* key,
+                          int nr)
+                          XASM_LINK("AES_GCM_encrypt_avx1");
+#ifdef HAVE_INTEL_AVX2
+void AES_GCM_encrypt_avx2(const unsigned char *in, unsigned char *out,
+                          const unsigned char* addt, const unsigned char* ivec,
+                          unsigned char *tag, unsigned int nbytes,
+                          unsigned int abytes, unsigned int ibytes,
+                          unsigned int tbytes, const unsigned char* key,
+                          int nr)
+                          XASM_LINK("AES_GCM_encrypt_avx2");
+#endif /* HAVE_INTEL_AVX2 */
+#endif /* HAVE_INTEL_AVX1 */
+
+#ifdef HAVE_AES_DECRYPT
+void AES_GCM_decrypt(const unsigned char *in, unsigned char *out,
+                     const unsigned char* addt, const unsigned char* ivec,
+                     const unsigned char *tag, int nbytes, int abytes,
+                     int ibytes, int tbytes, const unsigned char* key, int nr,
+                     int* res)
+                     XASM_LINK("AES_GCM_decrypt");
+#ifdef HAVE_INTEL_AVX1
+void AES_GCM_decrypt_avx1(const unsigned char *in, unsigned char *out,
+                          const unsigned char* addt, const unsigned char* ivec,
+                          const unsigned char *tag, int nbytes, int abytes,
+                          int ibytes, int tbytes, const unsigned char* key,
+                          int nr, int* res)
+                          XASM_LINK("AES_GCM_decrypt_avx1");
+#ifdef HAVE_INTEL_AVX2
+void AES_GCM_decrypt_avx2(const unsigned char *in, unsigned char *out,
+                          const unsigned char* addt, const unsigned char* ivec,
+                          const unsigned char *tag, int nbytes, int abytes,
+                          int ibytes, int tbytes, const unsigned char* key,
+                          int nr, int* res)
+                          XASM_LINK("AES_GCM_decrypt_avx2");
+#endif /* HAVE_INTEL_AVX2 */
+#endif /* HAVE_INTEL_AVX1 */
+#endif /* HAVE_AES_DECRYPT */
+
+#else /* _MSC_VER */
+
+#define S(w,z) ((char)((unsigned long long)(w) >> (8*(7-(z))) & 0xFF))
+#define M128_INIT(x,y) { S((x),7), S((x),6), S((x),5), S((x),4), \
+                         S((x),3), S((x),2), S((x),1), S((x),0), \
+                         S((y),7), S((y),6), S((y),5), S((y),4), \
+                         S((y),3), S((y),2), S((y),1), S((y),0) }
+
+static const __m128i MOD2_128 =
+        M128_INIT(0x1, (long long int)0xc200000000000000UL);
+
+
+/* See Intel® Carry-Less Multiplication Instruction
+ * and its Usage for Computing the GCM Mode White Paper
+ * by Shay Gueron, Intel Mobility Group, Israel Development Center;
+ * and Michael E. Kounavis, Intel Labs, Circuits and Systems Research */
+
+
+/* Figure 9. AES-GCM – Encrypt With Single Block Ghash at a Time */
+
+static const __m128i ONE   = M128_INIT(0x0, 0x1);
+#ifndef AES_GCM_AESNI_NO_UNROLL
+static const __m128i TWO   = M128_INIT(0x0, 0x2);
+static const __m128i THREE = M128_INIT(0x0, 0x3);
+static const __m128i FOUR  = M128_INIT(0x0, 0x4);
+static const __m128i FIVE  = M128_INIT(0x0, 0x5);
+static const __m128i SIX   = M128_INIT(0x0, 0x6);
+static const __m128i SEVEN = M128_INIT(0x0, 0x7);
+static const __m128i EIGHT = M128_INIT(0x0, 0x8);
+#endif
+static const __m128i BSWAP_EPI64 =
+        M128_INIT(0x0001020304050607, 0x08090a0b0c0d0e0f);
+static const __m128i BSWAP_MASK =
+        M128_INIT(0x08090a0b0c0d0e0f, 0x0001020304050607);
+
+
+/* The following are for MSC based builds which do not allow
+ * inline assembly. Intrinsic functions are used instead. */
+
+#define aes_gcm_calc_iv_12(KEY, ivec, nr, H, Y, T)         \
+do                                                         \
+{                                                          \
+    word32 iv12[4];                                        \
+    iv12[0] = *(word32*)&ivec[0];                          \
+    iv12[1] = *(word32*)&ivec[4];                          \
+    iv12[2] = *(word32*)&ivec[8];                          \
+    iv12[3] = 0x01000000;                                  \
+    Y = _mm_loadu_si128((__m128i*)iv12);                   \
+                                                           \
+    /* (Compute E[ZERO, KS] and E[Y0, KS] together */      \
+    tmp1 = _mm_load_si128(&KEY[0]);                        \
+    tmp2 = _mm_xor_si128(Y, KEY[0]);                       \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[1]);                 \
+    tmp2 = _mm_aesenc_si128(tmp2, KEY[1]);                 \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[2]);                 \
+    tmp2 = _mm_aesenc_si128(tmp2, KEY[2]);                 \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[3]);                 \
+    tmp2 = _mm_aesenc_si128(tmp2, KEY[3]);                 \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[4]);                 \
+    tmp2 = _mm_aesenc_si128(tmp2, KEY[4]);                 \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[5]);                 \
+    tmp2 = _mm_aesenc_si128(tmp2, KEY[5]);                 \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[6]);                 \
+    tmp2 = _mm_aesenc_si128(tmp2, KEY[6]);                 \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[7]);                 \
+    tmp2 = _mm_aesenc_si128(tmp2, KEY[7]);                 \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[8]);                 \
+    tmp2 = _mm_aesenc_si128(tmp2, KEY[8]);                 \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[9]);                 \
+    tmp2 = _mm_aesenc_si128(tmp2, KEY[9]);                 \
+    lastKey = KEY[10];                                     \
+    if (nr > 10) {                                         \
+        tmp1 = _mm_aesenc_si128(tmp1, lastKey);            \
+        tmp2 = _mm_aesenc_si128(tmp2, lastKey);            \
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[11]);            \
+        tmp2 = _mm_aesenc_si128(tmp2, KEY[11]);            \
+        lastKey = KEY[12];                                 \
+        if (nr > 12) {                                     \
+            tmp1 = _mm_aesenc_si128(tmp1, lastKey);        \
+            tmp2 = _mm_aesenc_si128(tmp2, lastKey);        \
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[13]);        \
+            tmp2 = _mm_aesenc_si128(tmp2, KEY[13]);        \
+            lastKey = KEY[14];                             \
+        }                                                  \
+    }                                                      \
+    H = _mm_aesenclast_si128(tmp1, lastKey);               \
+    T = _mm_aesenclast_si128(tmp2, lastKey);               \
+    H = _mm_shuffle_epi8(H, BSWAP_MASK);                   \
+}                                                          \
+while (0)
+
+#define aes_gcm_calc_iv(KEY, ivec, ibytes, nr, H, Y, T)         \
+do                                                              \
+{                                                               \
+    if (ibytes % 16) {                                          \
+        i = ibytes / 16;                                        \
+        for (j=0; j < (int)(ibytes%16); j++)                    \
+            ((unsigned char*)&last_block)[j] = ivec[i*16+j];    \
+    }                                                           \
+    tmp1 = _mm_load_si128(&KEY[0]);                             \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[1]);                      \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[2]);                      \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[3]);                      \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[4]);                      \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[5]);                      \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[6]);                      \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[7]);                      \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[8]);                      \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[9]);                      \
+    lastKey = KEY[10];                                          \
+    if (nr > 10) {                                              \
+        tmp1 = _mm_aesenc_si128(tmp1, lastKey);                 \
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[11]);                 \
+        lastKey = KEY[12];                                      \
+        if (nr > 12) {                                          \
+            tmp1 = _mm_aesenc_si128(tmp1, lastKey);             \
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[13]);             \
+            lastKey = KEY[14];                                  \
+        }                                                       \
+    }                                                           \
+    H = _mm_aesenclast_si128(tmp1, lastKey);                    \
+    H = _mm_shuffle_epi8(H, BSWAP_MASK);                        \
+    Y = _mm_setzero_si128();                                    \
+    for (i=0; i < (int)(ibytes/16); i++) {                      \
+        tmp1 = _mm_loadu_si128(&((__m128i*)ivec)[i]);           \
+        tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK);              \
+        Y = _mm_xor_si128(Y, tmp1);                             \
+        Y = gfmul_sw(Y, H);                                     \
+    }                                                           \
+    if (ibytes % 16) {                                          \
+        tmp1 = last_block;                                      \
+        tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK);              \
+        Y = _mm_xor_si128(Y, tmp1);                             \
+        Y = gfmul_sw(Y, H);                                     \
+    }                                                           \
+    tmp1 = _mm_insert_epi64(tmp1, ibytes*8, 0);                 \
+    tmp1 = _mm_insert_epi64(tmp1, 0, 1);                        \
+    Y = _mm_xor_si128(Y, tmp1);                                 \
+    Y = gfmul_sw(Y, H);                                         \
+    Y = _mm_shuffle_epi8(Y, BSWAP_MASK); /* Compute E(K, Y0) */ \
+    tmp1 = _mm_xor_si128(Y, KEY[0]);                            \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[1]);                      \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[2]);                      \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[3]);                      \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[4]);                      \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[5]);                      \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[6]);                      \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[7]);                      \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[8]);                      \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[9]);                      \
+    lastKey = KEY[10];                                          \
+    if (nr > 10) {                                              \
+        tmp1 = _mm_aesenc_si128(tmp1, lastKey);                 \
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[11]);                 \
+        lastKey = KEY[12];                                      \
+        if (nr > 12) {                                          \
+            tmp1 = _mm_aesenc_si128(tmp1, lastKey);             \
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[13]);             \
+            lastKey = KEY[14];                                  \
+        }                                                       \
+    }                                                           \
+    T = _mm_aesenclast_si128(tmp1, lastKey);                    \
+}                                                               \
+while (0)
+
+#define AES_ENC_8(j)                       \
+    tmp1 = _mm_aesenc_si128(tmp1, KEY[j]); \
+    tmp2 = _mm_aesenc_si128(tmp2, KEY[j]); \
+    tmp3 = _mm_aesenc_si128(tmp3, KEY[j]); \
+    tmp4 = _mm_aesenc_si128(tmp4, KEY[j]); \
+    tmp5 = _mm_aesenc_si128(tmp5, KEY[j]); \
+    tmp6 = _mm_aesenc_si128(tmp6, KEY[j]); \
+    tmp7 = _mm_aesenc_si128(tmp7, KEY[j]); \
+    tmp8 = _mm_aesenc_si128(tmp8, KEY[j]);
+
+#define AES_ENC_LAST_8()                                                  \
+    tmp1 =_mm_aesenclast_si128(tmp1, lastKey);                            \
+    tmp2 =_mm_aesenclast_si128(tmp2, lastKey);                            \
+    tmp1 = _mm_xor_si128(tmp1, _mm_loadu_si128(&((__m128i*)in)[i*8+0]));  \
+    tmp2 = _mm_xor_si128(tmp2, _mm_loadu_si128(&((__m128i*)in)[i*8+1]));  \
+    _mm_storeu_si128(&((__m128i*)out)[i*8+0], tmp1);                      \
+    _mm_storeu_si128(&((__m128i*)out)[i*8+1], tmp2);                      \
+    tmp3 =_mm_aesenclast_si128(tmp3, lastKey);                            \
+    tmp4 =_mm_aesenclast_si128(tmp4, lastKey);                            \
+    tmp3 = _mm_xor_si128(tmp3, _mm_loadu_si128(&((__m128i*)in)[i*8+2]));  \
+    tmp4 = _mm_xor_si128(tmp4, _mm_loadu_si128(&((__m128i*)in)[i*8+3]));  \
+    _mm_storeu_si128(&((__m128i*)out)[i*8+2], tmp3);                      \
+    _mm_storeu_si128(&((__m128i*)out)[i*8+3], tmp4);                      \
+    tmp5 =_mm_aesenclast_si128(tmp5, lastKey);                            \
+    tmp6 =_mm_aesenclast_si128(tmp6, lastKey);                            \
+    tmp5 = _mm_xor_si128(tmp5, _mm_loadu_si128(&((__m128i*)in)[i*8+4]));  \
+    tmp6 = _mm_xor_si128(tmp6, _mm_loadu_si128(&((__m128i*)in)[i*8+5]));  \
+    _mm_storeu_si128(&((__m128i*)out)[i*8+4], tmp5);                      \
+    _mm_storeu_si128(&((__m128i*)out)[i*8+5], tmp6);                      \
+    tmp7 =_mm_aesenclast_si128(tmp7, lastKey);                            \
+    tmp8 =_mm_aesenclast_si128(tmp8, lastKey);                            \
+    tmp7 = _mm_xor_si128(tmp7, _mm_loadu_si128(&((__m128i*)in)[i*8+6]));  \
+    tmp8 = _mm_xor_si128(tmp8, _mm_loadu_si128(&((__m128i*)in)[i*8+7]));  \
+    _mm_storeu_si128(&((__m128i*)out)[i*8+6], tmp7);                      \
+    _mm_storeu_si128(&((__m128i*)out)[i*8+7], tmp8);
+
+
+static __m128i gfmul_sw(__m128i a, __m128i b)
+{
+    __m128i r, t1, t2, t3, t4, t5, t6, t7;
+    t2 = _mm_shuffle_epi32(b, 78);
+    t3 = _mm_shuffle_epi32(a, 78);
+    t2 = _mm_xor_si128(t2, b);
+    t3 = _mm_xor_si128(t3, a);
+    t4 = _mm_clmulepi64_si128(b, a, 0x11);
+    t1 = _mm_clmulepi64_si128(b, a, 0x00);
+    t2 = _mm_clmulepi64_si128(t2, t3, 0x00);
+    t2 = _mm_xor_si128(t2, t1);
+    t2 = _mm_xor_si128(t2, t4);
+    t3 = _mm_slli_si128(t2, 8);
+    t2 = _mm_srli_si128(t2, 8);
+    t1 = _mm_xor_si128(t1, t3);
+    t4 = _mm_xor_si128(t4, t2);
+
+    t5 = _mm_srli_epi32(t1, 31);
+    t6 = _mm_srli_epi32(t4, 31);
+    t1 = _mm_slli_epi32(t1, 1);
+    t4 = _mm_slli_epi32(t4, 1);
+    t7 = _mm_srli_si128(t5, 12);
+    t5 = _mm_slli_si128(t5, 4);
+    t6 = _mm_slli_si128(t6, 4);
+    t4 = _mm_or_si128(t4, t7);
+    t1 = _mm_or_si128(t1, t5);
+    t4 = _mm_or_si128(t4, t6);
+
+    t5 = _mm_slli_epi32(t1, 31);
+    t6 = _mm_slli_epi32(t1, 30);
+    t7 = _mm_slli_epi32(t1, 25);
+    t5 = _mm_xor_si128(t5, t6);
+    t5 = _mm_xor_si128(t5, t7);
+
+    t6 = _mm_srli_si128(t5, 4);
+    t5 = _mm_slli_si128(t5, 12);
+    t1 = _mm_xor_si128(t1, t5);
+    t7 = _mm_srli_epi32(t1, 1);
+    t3 = _mm_srli_epi32(t1, 2);
+    t2 = _mm_srli_epi32(t1, 7);
+
+    t7 = _mm_xor_si128(t7, t3);
+    t7 = _mm_xor_si128(t7, t2);
+    t7 = _mm_xor_si128(t7, t6);
+    t7 = _mm_xor_si128(t7, t1);
+    r = _mm_xor_si128(t4, t7);
+
+    return r;
+}
+
+static void gfmul_only(__m128i a, __m128i b, __m128i* r0, __m128i* r1)
+{
+    __m128i t1, t2, t3, t4;
+
+    /* 128 x 128 Carryless Multiply */
+    t2 = _mm_shuffle_epi32(b, 78);
+    t3 = _mm_shuffle_epi32(a, 78);
+    t2 = _mm_xor_si128(t2, b);
+    t3 = _mm_xor_si128(t3, a);
+    t4 = _mm_clmulepi64_si128(b, a, 0x11);
+    t1 = _mm_clmulepi64_si128(b, a, 0x00);
+    t2 = _mm_clmulepi64_si128(t2, t3, 0x00);
+    t2 = _mm_xor_si128(t2, t1);
+    t2 = _mm_xor_si128(t2, t4);
+    t3 = _mm_slli_si128(t2, 8);
+    t2 = _mm_srli_si128(t2, 8);
+    t1 = _mm_xor_si128(t1, t3);
+    t4 = _mm_xor_si128(t4, t2);
+    *r0 = _mm_xor_si128(t1, *r0);
+    *r1 = _mm_xor_si128(t4, *r1);
+}
+
+static __m128i gfmul_shl1(__m128i a)
+{
+    __m128i t1 = a, t2;
+    t2 = _mm_srli_epi64(t1, 63);
+    t1 = _mm_slli_epi64(t1, 1);
+    t2 = _mm_slli_si128(t2, 8);
+    t1 = _mm_or_si128(t1, t2);
+    /* if (a[1] >> 63) t1 = _mm_xor_si128(t1, MOD2_128); */
+    a = _mm_shuffle_epi32(a, 0xff);
+    a = _mm_srai_epi32(a, 31);
+    a = _mm_and_si128(a, MOD2_128);
+    t1 = _mm_xor_si128(t1, a);
+    return t1;
+}
+
+static __m128i ghash_red(__m128i r0, __m128i r1)
+{
+    __m128i t2, t3;
+    __m128i t5, t6, t7;
+
+    t5 = _mm_slli_epi32(r0, 31);
+    t6 = _mm_slli_epi32(r0, 30);
+    t7 = _mm_slli_epi32(r0, 25);
+    t5 = _mm_xor_si128(t5, t6);
+    t5 = _mm_xor_si128(t5, t7);
+
+    t6 = _mm_srli_si128(t5, 4);
+    t5 = _mm_slli_si128(t5, 12);
+    r0 = _mm_xor_si128(r0, t5);
+    t7 = _mm_srli_epi32(r0, 1);
+    t3 = _mm_srli_epi32(r0, 2);
+    t2 = _mm_srli_epi32(r0, 7);
+
+    t7 = _mm_xor_si128(t7, t3);
+    t7 = _mm_xor_si128(t7, t2);
+    t7 = _mm_xor_si128(t7, t6);
+    t7 = _mm_xor_si128(t7, r0);
+    return _mm_xor_si128(r1, t7);
+}
+
+static __m128i gfmul_shifted(__m128i a, __m128i b)
+{
+    __m128i t0 = _mm_setzero_si128(), t1 = _mm_setzero_si128();
+    gfmul_only(a, b, &t0, &t1);
+    return ghash_red(t0, t1);
+}
+
+#ifndef AES_GCM_AESNI_NO_UNROLL
+static __m128i gfmul8(__m128i a1, __m128i a2, __m128i a3, __m128i a4,
+                      __m128i a5, __m128i a6, __m128i a7, __m128i a8,
+                      __m128i b1, __m128i b2, __m128i b3, __m128i b4,
+                      __m128i b5, __m128i b6, __m128i b7, __m128i b8)
+{
+    __m128i t0 = _mm_setzero_si128(), t1 = _mm_setzero_si128();
+    gfmul_only(a1, b8, &t0, &t1);
+    gfmul_only(a2, b7, &t0, &t1);
+    gfmul_only(a3, b6, &t0, &t1);
+    gfmul_only(a4, b5, &t0, &t1);
+    gfmul_only(a5, b4, &t0, &t1);
+    gfmul_only(a6, b3, &t0, &t1);
+    gfmul_only(a7, b2, &t0, &t1);
+    gfmul_only(a8, b1, &t0, &t1);
+    return ghash_red(t0, t1);
+}
+#endif
+
+
+static void AES_GCM_encrypt(const unsigned char *in,
+                              unsigned char *out,
+                              const unsigned char* addt,
+                              const unsigned char* ivec,
+                              unsigned char *tag, unsigned int nbytes,
+                              unsigned int abytes, unsigned int ibytes,
+                              unsigned int tbytes,
+                              const unsigned char* key, int nr)
+{
+    int i, j ,k;
+    __m128i ctr1;
+    __m128i H, Y, T;
+    __m128i X = _mm_setzero_si128();
+    __m128i *KEY = (__m128i*)key, lastKey;
+    __m128i last_block = _mm_setzero_si128();
+    __m128i tmp1, tmp2;
+#ifndef AES_GCM_AESNI_NO_UNROLL
+    __m128i HT[8];
+    __m128i r0, r1;
+    __m128i XV;
+    __m128i tmp3, tmp4, tmp5, tmp6, tmp7, tmp8;
+#endif
+
+    if (ibytes == GCM_NONCE_MID_SZ)
+        aes_gcm_calc_iv_12(KEY, ivec, nr, H, Y, T);
+    else
+        aes_gcm_calc_iv(KEY, ivec, ibytes, nr, H, Y, T);
+
+    for (i=0; i < (int)(abytes/16); i++) {
+        tmp1 = _mm_loadu_si128(&((__m128i*)addt)[i]);
+        tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK);
+        X = _mm_xor_si128(X, tmp1);
+        X = gfmul_sw(X, H);
+    }
+    if (abytes%16) {
+        last_block = _mm_setzero_si128();
+        for (j=0; j < (int)(abytes%16); j++)
+            ((unsigned char*)&last_block)[j] = addt[i*16+j];
+        tmp1 = last_block;
+        tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK);
+        X = _mm_xor_si128(X, tmp1);
+        X = gfmul_sw(X, H);
+    }
+    tmp1 = _mm_shuffle_epi8(Y, BSWAP_EPI64);
+    ctr1 = _mm_add_epi32(tmp1, ONE);
+    H = gfmul_shl1(H);
+
+#ifndef AES_GCM_AESNI_NO_UNROLL
+    i = 0;
+    if (nbytes >= 16*8) {
+        HT[0] = H;
+        HT[1] = gfmul_shifted(H, H);
+        HT[2] = gfmul_shifted(H, HT[1]);
+        HT[3] = gfmul_shifted(HT[1], HT[1]);
+        HT[4] = gfmul_shifted(HT[1], HT[2]);
+        HT[5] = gfmul_shifted(HT[2], HT[2]);
+        HT[6] = gfmul_shifted(HT[2], HT[3]);
+        HT[7] = gfmul_shifted(HT[3], HT[3]);
+
+        tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64);
+        tmp2 = _mm_add_epi32(ctr1, ONE);
+        tmp2 = _mm_shuffle_epi8(tmp2, BSWAP_EPI64);
+        tmp3 = _mm_add_epi32(ctr1, TWO);
+        tmp3 = _mm_shuffle_epi8(tmp3, BSWAP_EPI64);
+        tmp4 = _mm_add_epi32(ctr1, THREE);
+        tmp4 = _mm_shuffle_epi8(tmp4, BSWAP_EPI64);
+        tmp5 = _mm_add_epi32(ctr1, FOUR);
+        tmp5 = _mm_shuffle_epi8(tmp5, BSWAP_EPI64);
+        tmp6 = _mm_add_epi32(ctr1, FIVE);
+        tmp6 = _mm_shuffle_epi8(tmp6, BSWAP_EPI64);
+        tmp7 = _mm_add_epi32(ctr1, SIX);
+        tmp7 = _mm_shuffle_epi8(tmp7, BSWAP_EPI64);
+        tmp8 = _mm_add_epi32(ctr1, SEVEN);
+        tmp8 = _mm_shuffle_epi8(tmp8, BSWAP_EPI64);
+        ctr1 = _mm_add_epi32(ctr1, EIGHT);
+        tmp1 =_mm_xor_si128(tmp1, KEY[0]);
+        tmp2 =_mm_xor_si128(tmp2, KEY[0]);
+        tmp3 =_mm_xor_si128(tmp3, KEY[0]);
+        tmp4 =_mm_xor_si128(tmp4, KEY[0]);
+        tmp5 =_mm_xor_si128(tmp5, KEY[0]);
+        tmp6 =_mm_xor_si128(tmp6, KEY[0]);
+        tmp7 =_mm_xor_si128(tmp7, KEY[0]);
+        tmp8 =_mm_xor_si128(tmp8, KEY[0]);
+        AES_ENC_8(1);
+        AES_ENC_8(2);
+        AES_ENC_8(3);
+        AES_ENC_8(4);
+        AES_ENC_8(5);
+        AES_ENC_8(6);
+        AES_ENC_8(7);
+        AES_ENC_8(8);
+        AES_ENC_8(9);
+        lastKey = KEY[10];
+        if (nr > 10) {
+            AES_ENC_8(10);
+            AES_ENC_8(11);
+            lastKey = KEY[12];
+            if (nr > 12) {
+                AES_ENC_8(12);
+                AES_ENC_8(13);
+                lastKey = KEY[14];
+            }
+        }
+        AES_ENC_LAST_8();
+
+        for (i=1; i < (int)(nbytes/16/8); i++) {
+                r0 = _mm_setzero_si128();
+                r1 = _mm_setzero_si128();
+            tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64);
+            tmp2 = _mm_add_epi32(ctr1, ONE);
+            tmp2 = _mm_shuffle_epi8(tmp2, BSWAP_EPI64);
+            tmp3 = _mm_add_epi32(ctr1, TWO);
+            tmp3 = _mm_shuffle_epi8(tmp3, BSWAP_EPI64);
+            tmp4 = _mm_add_epi32(ctr1, THREE);
+            tmp4 = _mm_shuffle_epi8(tmp4, BSWAP_EPI64);
+            tmp5 = _mm_add_epi32(ctr1, FOUR);
+            tmp5 = _mm_shuffle_epi8(tmp5, BSWAP_EPI64);
+            tmp6 = _mm_add_epi32(ctr1, FIVE);
+            tmp6 = _mm_shuffle_epi8(tmp6, BSWAP_EPI64);
+            tmp7 = _mm_add_epi32(ctr1, SIX);
+            tmp7 = _mm_shuffle_epi8(tmp7, BSWAP_EPI64);
+            tmp8 = _mm_add_epi32(ctr1, SEVEN);
+            tmp8 = _mm_shuffle_epi8(tmp8, BSWAP_EPI64);
+            ctr1 = _mm_add_epi32(ctr1, EIGHT);
+            tmp1 =_mm_xor_si128(tmp1, KEY[0]);
+            tmp2 =_mm_xor_si128(tmp2, KEY[0]);
+            tmp3 =_mm_xor_si128(tmp3, KEY[0]);
+            tmp4 =_mm_xor_si128(tmp4, KEY[0]);
+            tmp5 =_mm_xor_si128(tmp5, KEY[0]);
+            tmp6 =_mm_xor_si128(tmp6, KEY[0]);
+            tmp7 =_mm_xor_si128(tmp7, KEY[0]);
+            tmp8 =_mm_xor_si128(tmp8, KEY[0]);
+                /* 128 x 128 Carryless Multiply */
+                XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+0]);
+                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
+                XV = _mm_xor_si128(XV, X);
+                gfmul_only(XV, HT[7], &r0, &r1);
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[1]);
+            tmp2 = _mm_aesenc_si128(tmp2, KEY[1]);
+            tmp3 = _mm_aesenc_si128(tmp3, KEY[1]);
+            tmp4 = _mm_aesenc_si128(tmp4, KEY[1]);
+            tmp5 = _mm_aesenc_si128(tmp5, KEY[1]);
+            tmp6 = _mm_aesenc_si128(tmp6, KEY[1]);
+            tmp7 = _mm_aesenc_si128(tmp7, KEY[1]);
+            tmp8 = _mm_aesenc_si128(tmp8, KEY[1]);
+                /* 128 x 128 Carryless Multiply */
+                XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+1]);
+                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
+                gfmul_only(XV, HT[6], &r0, &r1);
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[2]);
+            tmp2 = _mm_aesenc_si128(tmp2, KEY[2]);
+            tmp3 = _mm_aesenc_si128(tmp3, KEY[2]);
+            tmp4 = _mm_aesenc_si128(tmp4, KEY[2]);
+            tmp5 = _mm_aesenc_si128(tmp5, KEY[2]);
+            tmp6 = _mm_aesenc_si128(tmp6, KEY[2]);
+            tmp7 = _mm_aesenc_si128(tmp7, KEY[2]);
+            tmp8 = _mm_aesenc_si128(tmp8, KEY[2]);
+                /* 128 x 128 Carryless Multiply */
+                XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+2]);
+                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
+                gfmul_only(XV, HT[5], &r0, &r1);
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[3]);
+            tmp2 = _mm_aesenc_si128(tmp2, KEY[3]);
+            tmp3 = _mm_aesenc_si128(tmp3, KEY[3]);
+            tmp4 = _mm_aesenc_si128(tmp4, KEY[3]);
+            tmp5 = _mm_aesenc_si128(tmp5, KEY[3]);
+            tmp6 = _mm_aesenc_si128(tmp6, KEY[3]);
+            tmp7 = _mm_aesenc_si128(tmp7, KEY[3]);
+            tmp8 = _mm_aesenc_si128(tmp8, KEY[3]);
+                /* 128 x 128 Carryless Multiply */
+                XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+3]);
+                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
+                gfmul_only(XV, HT[4], &r0, &r1);
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[4]);
+            tmp2 = _mm_aesenc_si128(tmp2, KEY[4]);
+            tmp3 = _mm_aesenc_si128(tmp3, KEY[4]);
+            tmp4 = _mm_aesenc_si128(tmp4, KEY[4]);
+            tmp5 = _mm_aesenc_si128(tmp5, KEY[4]);
+            tmp6 = _mm_aesenc_si128(tmp6, KEY[4]);
+            tmp7 = _mm_aesenc_si128(tmp7, KEY[4]);
+            tmp8 = _mm_aesenc_si128(tmp8, KEY[4]);
+                /* 128 x 128 Carryless Multiply */
+                XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+4]);
+                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
+                gfmul_only(XV, HT[3], &r0, &r1);
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[5]);
+            tmp2 = _mm_aesenc_si128(tmp2, KEY[5]);
+            tmp3 = _mm_aesenc_si128(tmp3, KEY[5]);
+            tmp4 = _mm_aesenc_si128(tmp4, KEY[5]);
+            tmp5 = _mm_aesenc_si128(tmp5, KEY[5]);
+            tmp6 = _mm_aesenc_si128(tmp6, KEY[5]);
+            tmp7 = _mm_aesenc_si128(tmp7, KEY[5]);
+            tmp8 = _mm_aesenc_si128(tmp8, KEY[5]);
+                /* 128 x 128 Carryless Multiply */
+                XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+5]);
+                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
+                gfmul_only(XV, HT[2], &r0, &r1);
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[6]);
+            tmp2 = _mm_aesenc_si128(tmp2, KEY[6]);
+            tmp3 = _mm_aesenc_si128(tmp3, KEY[6]);
+            tmp4 = _mm_aesenc_si128(tmp4, KEY[6]);
+            tmp5 = _mm_aesenc_si128(tmp5, KEY[6]);
+            tmp6 = _mm_aesenc_si128(tmp6, KEY[6]);
+            tmp7 = _mm_aesenc_si128(tmp7, KEY[6]);
+            tmp8 = _mm_aesenc_si128(tmp8, KEY[6]);
+                /* 128 x 128 Carryless Multiply */
+                XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+6]);
+                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
+                gfmul_only(XV, HT[1], &r0, &r1);
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[7]);
+            tmp2 = _mm_aesenc_si128(tmp2, KEY[7]);
+            tmp3 = _mm_aesenc_si128(tmp3, KEY[7]);
+            tmp4 = _mm_aesenc_si128(tmp4, KEY[7]);
+            tmp5 = _mm_aesenc_si128(tmp5, KEY[7]);
+            tmp6 = _mm_aesenc_si128(tmp6, KEY[7]);
+            tmp7 = _mm_aesenc_si128(tmp7, KEY[7]);
+            tmp8 = _mm_aesenc_si128(tmp8, KEY[7]);
+                /* 128 x 128 Carryless Multiply */
+                XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+7]);
+                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
+                gfmul_only(XV, HT[0], &r0, &r1);
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[8]);
+            tmp2 = _mm_aesenc_si128(tmp2, KEY[8]);
+            tmp3 = _mm_aesenc_si128(tmp3, KEY[8]);
+            tmp4 = _mm_aesenc_si128(tmp4, KEY[8]);
+            tmp5 = _mm_aesenc_si128(tmp5, KEY[8]);
+            tmp6 = _mm_aesenc_si128(tmp6, KEY[8]);
+            tmp7 = _mm_aesenc_si128(tmp7, KEY[8]);
+            tmp8 = _mm_aesenc_si128(tmp8, KEY[8]);
+                /* Reduction */
+                X = ghash_red(r0, r1);
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[9]);
+            tmp2 = _mm_aesenc_si128(tmp2, KEY[9]);
+            tmp3 = _mm_aesenc_si128(tmp3, KEY[9]);
+            tmp4 = _mm_aesenc_si128(tmp4, KEY[9]);
+            tmp5 = _mm_aesenc_si128(tmp5, KEY[9]);
+            tmp6 = _mm_aesenc_si128(tmp6, KEY[9]);
+            tmp7 = _mm_aesenc_si128(tmp7, KEY[9]);
+            tmp8 = _mm_aesenc_si128(tmp8, KEY[9]);
+            lastKey = KEY[10];
+            if (nr > 10) {
+                tmp1 = _mm_aesenc_si128(tmp1, KEY[10]);
+                tmp2 = _mm_aesenc_si128(tmp2, KEY[10]);
+                tmp3 = _mm_aesenc_si128(tmp3, KEY[10]);
+                tmp4 = _mm_aesenc_si128(tmp4, KEY[10]);
+                tmp5 = _mm_aesenc_si128(tmp5, KEY[10]);
+                tmp6 = _mm_aesenc_si128(tmp6, KEY[10]);
+                tmp7 = _mm_aesenc_si128(tmp7, KEY[10]);
+                tmp8 = _mm_aesenc_si128(tmp8, KEY[10]);
+                tmp1 = _mm_aesenc_si128(tmp1, KEY[11]);
+                tmp2 = _mm_aesenc_si128(tmp2, KEY[11]);
+                tmp3 = _mm_aesenc_si128(tmp3, KEY[11]);
+                tmp4 = _mm_aesenc_si128(tmp4, KEY[11]);
+                tmp5 = _mm_aesenc_si128(tmp5, KEY[11]);
+                tmp6 = _mm_aesenc_si128(tmp6, KEY[11]);
+                tmp7 = _mm_aesenc_si128(tmp7, KEY[11]);
+                tmp8 = _mm_aesenc_si128(tmp8, KEY[11]);
+                lastKey = KEY[12];
+                if (nr > 12) {
+                    tmp1 = _mm_aesenc_si128(tmp1, KEY[12]);
+                    tmp2 = _mm_aesenc_si128(tmp2, KEY[12]);
+                    tmp3 = _mm_aesenc_si128(tmp3, KEY[12]);
+                    tmp4 = _mm_aesenc_si128(tmp4, KEY[12]);
+                    tmp5 = _mm_aesenc_si128(tmp5, KEY[12]);
+                    tmp6 = _mm_aesenc_si128(tmp6, KEY[12]);
+                    tmp7 = _mm_aesenc_si128(tmp7, KEY[12]);
+                    tmp8 = _mm_aesenc_si128(tmp8, KEY[12]);
+                    tmp1 = _mm_aesenc_si128(tmp1, KEY[13]);
+                    tmp2 = _mm_aesenc_si128(tmp2, KEY[13]);
+                    tmp3 = _mm_aesenc_si128(tmp3, KEY[13]);
+                    tmp4 = _mm_aesenc_si128(tmp4, KEY[13]);
+                    tmp5 = _mm_aesenc_si128(tmp5, KEY[13]);
+                    tmp6 = _mm_aesenc_si128(tmp6, KEY[13]);
+                    tmp7 = _mm_aesenc_si128(tmp7, KEY[13]);
+                    tmp8 = _mm_aesenc_si128(tmp8, KEY[13]);
+                    lastKey = KEY[14];
+                }
+            }
+            AES_ENC_LAST_8();
+        }
+
+        tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK);
+        tmp2 = _mm_shuffle_epi8(tmp2, BSWAP_MASK);
+        tmp3 = _mm_shuffle_epi8(tmp3, BSWAP_MASK);
+        tmp4 = _mm_shuffle_epi8(tmp4, BSWAP_MASK);
+        tmp5 = _mm_shuffle_epi8(tmp5, BSWAP_MASK);
+        tmp6 = _mm_shuffle_epi8(tmp6, BSWAP_MASK);
+        tmp7 = _mm_shuffle_epi8(tmp7, BSWAP_MASK);
+        tmp8 = _mm_shuffle_epi8(tmp8, BSWAP_MASK);
+        tmp1 = _mm_xor_si128(X, tmp1);
+        X = gfmul8(tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8,
+                   HT[0], HT[1], HT[2], HT[3], HT[4], HT[5], HT[6], HT[7]);
+    }
+    for (k = i*8; k < (int)(nbytes/16); k++) {
+        tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64);
+        ctr1 = _mm_add_epi32(ctr1, ONE);
+        tmp1 = _mm_xor_si128(tmp1, KEY[0]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[1]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[2]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[3]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[4]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[5]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[6]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[7]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[8]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[9]);
+        lastKey = KEY[10];
+        if (nr > 10) {
+            tmp1 = _mm_aesenc_si128(tmp1, lastKey);
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[11]);
+            lastKey = KEY[12];
+            if (nr > 12) {
+                tmp1 = _mm_aesenc_si128(tmp1, lastKey);
+                tmp1 = _mm_aesenc_si128(tmp1, KEY[13]);
+                lastKey = KEY[14];
+            }
+        }
+        tmp1 = _mm_aesenclast_si128(tmp1, lastKey);
+        tmp1 = _mm_xor_si128(tmp1, _mm_loadu_si128(&((__m128i*)in)[k]));
+        _mm_storeu_si128(&((__m128i*)out)[k], tmp1);
+        tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK);
+        X =_mm_xor_si128(X, tmp1);
+        X = gfmul_shifted(X, H);
+    }
+#else /* AES_GCM_AESNI_NO_UNROLL */
+    for (k = 0; k < (int)(nbytes/16) && k < 1; k++) {
+        tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64);
+        ctr1 = _mm_add_epi32(ctr1, ONE);
+        tmp1 = _mm_xor_si128(tmp1, KEY[0]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[1]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[2]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[3]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[4]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[5]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[6]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[7]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[8]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[9]);
+        lastKey = KEY[10];
+        if (nr > 10) {
+            tmp1 = _mm_aesenc_si128(tmp1, lastKey);
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[11]);
+            lastKey = KEY[12];
+            if (nr > 12) {
+                tmp1 = _mm_aesenc_si128(tmp1, lastKey);
+                tmp1 = _mm_aesenc_si128(tmp1, KEY[13]);
+                lastKey = KEY[14];
+            }
+        }
+        tmp1 = _mm_aesenclast_si128(tmp1, lastKey);
+        tmp1 = _mm_xor_si128(tmp1, _mm_loadu_si128(&((__m128i*)in)[k]));
+        _mm_storeu_si128(&((__m128i*)out)[k], tmp1);
+        tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK);
+        X =_mm_xor_si128(X, tmp1);
+    }
+    for (; k < (int)(nbytes/16); k++) {
+        tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64);
+        ctr1 = _mm_add_epi32(ctr1, ONE);
+        tmp1 = _mm_xor_si128(tmp1, KEY[0]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[1]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[2]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[3]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[4]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[5]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[6]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[7]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[8]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[9]);
+        X = gfmul_shifted(X, H);
+        lastKey = KEY[10];
+        if (nr > 10) {
+            tmp1 = _mm_aesenc_si128(tmp1, lastKey);
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[11]);
+            lastKey = KEY[12];
+            if (nr > 12) {
+                tmp1 = _mm_aesenc_si128(tmp1, lastKey);
+                tmp1 = _mm_aesenc_si128(tmp1, KEY[13]);
+                lastKey = KEY[14];
+            }
+        }
+        tmp1 = _mm_aesenclast_si128(tmp1, lastKey);
+        tmp1 = _mm_xor_si128(tmp1, _mm_loadu_si128(&((__m128i*)in)[k]));
+        _mm_storeu_si128(&((__m128i*)out)[k], tmp1);
+        tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK);
+        X =_mm_xor_si128(X, tmp1);
+    }
+    if (k > 0) {
+        X = gfmul_shifted(X, H);
+    }
+#endif /* AES_GCM_AESNI_NO_UNROLL */
+
+    /* If one partial block remains */
+    if (nbytes % 16) {
+        tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64);
+        tmp1 = _mm_xor_si128(tmp1, KEY[0]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[1]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[2]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[3]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[4]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[5]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[6]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[7]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[8]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[9]);
+        lastKey = KEY[10];
+        if (nr > 10) {
+            tmp1 = _mm_aesenc_si128(tmp1, lastKey);
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[11]);
+            lastKey = KEY[12];
+            if (nr > 12) {
+                tmp1 = _mm_aesenc_si128(tmp1, lastKey);
+                tmp1 = _mm_aesenc_si128(tmp1, KEY[13]);
+                lastKey = KEY[14];
+            }
+        }
+        tmp1 = _mm_aesenclast_si128(tmp1, lastKey);
+        last_block = tmp1;
+        for (j=0; j < (int)(nbytes%16); j++)
+            ((unsigned char*)&last_block)[j] = in[k*16+j];
+        tmp1 = _mm_xor_si128(tmp1, last_block);
+        last_block = tmp1;
+        for (j=0; j < (int)(nbytes%16); j++)
+            out[k*16+j] = ((unsigned char*)&last_block)[j];
+        tmp1 = last_block;
+        tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK);
+        X =_mm_xor_si128(X, tmp1);
+        X = gfmul_shifted(X, H);
+    }
+    tmp1 = _mm_insert_epi64(tmp1, nbytes*8, 0);
+    tmp1 = _mm_insert_epi64(tmp1, abytes*8, 1);
+    X = _mm_xor_si128(X, tmp1);
+    X = gfmul_shifted(X, H);
+    X = _mm_shuffle_epi8(X, BSWAP_MASK);
+    T = _mm_xor_si128(X, T);
+    /*_mm_storeu_si128((__m128i*)tag, T);*/
+    XMEMCPY(tag, &T, tbytes);
+}
+
+#ifdef HAVE_AES_DECRYPT
+
+static void AES_GCM_decrypt(const unsigned char *in,
+                           unsigned char *out,
+                           const unsigned char* addt,
+                           const unsigned char* ivec,
+                           const unsigned char *tag, int nbytes, int abytes,
+                           int ibytes, word32 tbytes, const unsigned char* key,
+                           int nr, int* res)
+{
+    int i, j ,k;
+    __m128i H, Y, T;
+    __m128i *KEY = (__m128i*)key, lastKey;
+    __m128i ctr1;
+    __m128i last_block = _mm_setzero_si128();
+    __m128i X = _mm_setzero_si128();
+    __m128i tmp1, tmp2, XV;
+#ifndef AES_GCM_AESNI_NO_UNROLL
+    __m128i HT[8];
+    __m128i r0, r1;
+    __m128i tmp3, tmp4, tmp5, tmp6, tmp7, tmp8;
+#endif /* AES_GCM_AESNI_NO_UNROLL */
+
+    if (ibytes == GCM_NONCE_MID_SZ)
+        aes_gcm_calc_iv_12(KEY, ivec, nr, H, Y, T);
+    else
+        aes_gcm_calc_iv(KEY, ivec, ibytes, nr, H, Y, T);
+
+    for (i=0; i<abytes/16; i++) {
+        tmp1 = _mm_loadu_si128(&((__m128i*)addt)[i]);
+        tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK);
+        X = _mm_xor_si128(X, tmp1);
+        X = gfmul_sw(X, H);
+    }
+    if (abytes%16) {
+        last_block = _mm_setzero_si128();
+        for (j=0; j<abytes%16; j++)
+            ((unsigned char*)&last_block)[j] = addt[i*16+j];
+        tmp1 = last_block;
+        tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK);
+        X = _mm_xor_si128(X, tmp1);
+        X = gfmul_sw(X, H);
+    }
+
+    tmp1 = _mm_shuffle_epi8(Y, BSWAP_EPI64);
+    ctr1 = _mm_add_epi32(tmp1, ONE);
+    H = gfmul_shl1(H);
+    i = 0;
+
+#ifndef AES_GCM_AESNI_NO_UNROLL
+
+    if (0 < nbytes/16/8) {
+        HT[0] = H;
+        HT[1] = gfmul_shifted(H, H);
+        HT[2] = gfmul_shifted(H, HT[1]);
+        HT[3] = gfmul_shifted(HT[1], HT[1]);
+        HT[4] = gfmul_shifted(HT[1], HT[2]);
+        HT[5] = gfmul_shifted(HT[2], HT[2]);
+        HT[6] = gfmul_shifted(HT[2], HT[3]);
+        HT[7] = gfmul_shifted(HT[3], HT[3]);
+
+        for (; i < nbytes/16/8; i++) {
+                r0 = _mm_setzero_si128();
+                r1 = _mm_setzero_si128();
+
+            tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64);
+            tmp2 = _mm_add_epi32(ctr1, ONE);
+            tmp2 = _mm_shuffle_epi8(tmp2, BSWAP_EPI64);
+            tmp3 = _mm_add_epi32(ctr1, TWO);
+            tmp3 = _mm_shuffle_epi8(tmp3, BSWAP_EPI64);
+            tmp4 = _mm_add_epi32(ctr1, THREE);
+            tmp4 = _mm_shuffle_epi8(tmp4, BSWAP_EPI64);
+            tmp5 = _mm_add_epi32(ctr1, FOUR);
+            tmp5 = _mm_shuffle_epi8(tmp5, BSWAP_EPI64);
+            tmp6 = _mm_add_epi32(ctr1, FIVE);
+            tmp6 = _mm_shuffle_epi8(tmp6, BSWAP_EPI64);
+            tmp7 = _mm_add_epi32(ctr1, SIX);
+            tmp7 = _mm_shuffle_epi8(tmp7, BSWAP_EPI64);
+            tmp8 = _mm_add_epi32(ctr1, SEVEN);
+            tmp8 = _mm_shuffle_epi8(tmp8, BSWAP_EPI64);
+            ctr1 = _mm_add_epi32(ctr1, EIGHT);
+            tmp1 =_mm_xor_si128(tmp1, KEY[0]);
+            tmp2 =_mm_xor_si128(tmp2, KEY[0]);
+            tmp3 =_mm_xor_si128(tmp3, KEY[0]);
+            tmp4 =_mm_xor_si128(tmp4, KEY[0]);
+            tmp5 =_mm_xor_si128(tmp5, KEY[0]);
+            tmp6 =_mm_xor_si128(tmp6, KEY[0]);
+            tmp7 =_mm_xor_si128(tmp7, KEY[0]);
+            tmp8 =_mm_xor_si128(tmp8, KEY[0]);
+                /* 128 x 128 Carryless Multiply */
+                XV = _mm_loadu_si128(&((__m128i*)in)[i*8+0]);
+                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
+                XV = _mm_xor_si128(XV, X);
+                gfmul_only(XV, HT[7], &r0, &r1);
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[1]);
+            tmp2 = _mm_aesenc_si128(tmp2, KEY[1]);
+            tmp3 = _mm_aesenc_si128(tmp3, KEY[1]);
+            tmp4 = _mm_aesenc_si128(tmp4, KEY[1]);
+            tmp5 = _mm_aesenc_si128(tmp5, KEY[1]);
+            tmp6 = _mm_aesenc_si128(tmp6, KEY[1]);
+            tmp7 = _mm_aesenc_si128(tmp7, KEY[1]);
+            tmp8 = _mm_aesenc_si128(tmp8, KEY[1]);
+                /* 128 x 128 Carryless Multiply */
+                XV = _mm_loadu_si128(&((__m128i*)in)[i*8+1]);
+                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
+                gfmul_only(XV, HT[6], &r0, &r1);
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[2]);
+            tmp2 = _mm_aesenc_si128(tmp2, KEY[2]);
+            tmp3 = _mm_aesenc_si128(tmp3, KEY[2]);
+            tmp4 = _mm_aesenc_si128(tmp4, KEY[2]);
+            tmp5 = _mm_aesenc_si128(tmp5, KEY[2]);
+            tmp6 = _mm_aesenc_si128(tmp6, KEY[2]);
+            tmp7 = _mm_aesenc_si128(tmp7, KEY[2]);
+            tmp8 = _mm_aesenc_si128(tmp8, KEY[2]);
+                /* 128 x 128 Carryless Multiply */
+                XV = _mm_loadu_si128(&((__m128i*)in)[i*8+2]);
+                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
+                gfmul_only(XV, HT[5], &r0, &r1);
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[3]);
+            tmp2 = _mm_aesenc_si128(tmp2, KEY[3]);
+            tmp3 = _mm_aesenc_si128(tmp3, KEY[3]);
+            tmp4 = _mm_aesenc_si128(tmp4, KEY[3]);
+            tmp5 = _mm_aesenc_si128(tmp5, KEY[3]);
+            tmp6 = _mm_aesenc_si128(tmp6, KEY[3]);
+            tmp7 = _mm_aesenc_si128(tmp7, KEY[3]);
+            tmp8 = _mm_aesenc_si128(tmp8, KEY[3]);
+                /* 128 x 128 Carryless Multiply */
+                XV = _mm_loadu_si128(&((__m128i*)in)[i*8+3]);
+                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
+                gfmul_only(XV, HT[4], &r0, &r1);
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[4]);
+            tmp2 = _mm_aesenc_si128(tmp2, KEY[4]);
+            tmp3 = _mm_aesenc_si128(tmp3, KEY[4]);
+            tmp4 = _mm_aesenc_si128(tmp4, KEY[4]);
+            tmp5 = _mm_aesenc_si128(tmp5, KEY[4]);
+            tmp6 = _mm_aesenc_si128(tmp6, KEY[4]);
+            tmp7 = _mm_aesenc_si128(tmp7, KEY[4]);
+            tmp8 = _mm_aesenc_si128(tmp8, KEY[4]);
+                /* 128 x 128 Carryless Multiply */
+                XV = _mm_loadu_si128(&((__m128i*)in)[i*8+4]);
+                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
+                gfmul_only(XV, HT[3], &r0, &r1);
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[5]);
+            tmp2 = _mm_aesenc_si128(tmp2, KEY[5]);
+            tmp3 = _mm_aesenc_si128(tmp3, KEY[5]);
+            tmp4 = _mm_aesenc_si128(tmp4, KEY[5]);
+            tmp5 = _mm_aesenc_si128(tmp5, KEY[5]);
+            tmp6 = _mm_aesenc_si128(tmp6, KEY[5]);
+            tmp7 = _mm_aesenc_si128(tmp7, KEY[5]);
+            tmp8 = _mm_aesenc_si128(tmp8, KEY[5]);
+                /* 128 x 128 Carryless Multiply */
+                XV = _mm_loadu_si128(&((__m128i*)in)[i*8+5]);
+                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
+                gfmul_only(XV, HT[2], &r0, &r1);
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[6]);
+            tmp2 = _mm_aesenc_si128(tmp2, KEY[6]);
+            tmp3 = _mm_aesenc_si128(tmp3, KEY[6]);
+            tmp4 = _mm_aesenc_si128(tmp4, KEY[6]);
+            tmp5 = _mm_aesenc_si128(tmp5, KEY[6]);
+            tmp6 = _mm_aesenc_si128(tmp6, KEY[6]);
+            tmp7 = _mm_aesenc_si128(tmp7, KEY[6]);
+            tmp8 = _mm_aesenc_si128(tmp8, KEY[6]);
+                /* 128 x 128 Carryless Multiply */
+                XV = _mm_loadu_si128(&((__m128i*)in)[i*8+6]);
+                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
+                gfmul_only(XV, HT[1], &r0, &r1);
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[7]);
+            tmp2 = _mm_aesenc_si128(tmp2, KEY[7]);
+            tmp3 = _mm_aesenc_si128(tmp3, KEY[7]);
+            tmp4 = _mm_aesenc_si128(tmp4, KEY[7]);
+            tmp5 = _mm_aesenc_si128(tmp5, KEY[7]);
+            tmp6 = _mm_aesenc_si128(tmp6, KEY[7]);
+            tmp7 = _mm_aesenc_si128(tmp7, KEY[7]);
+            tmp8 = _mm_aesenc_si128(tmp8, KEY[7]);
+                /* 128 x 128 Carryless Multiply */
+                XV = _mm_loadu_si128(&((__m128i*)in)[i*8+7]);
+                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
+                gfmul_only(XV, HT[0], &r0, &r1);
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[8]);
+            tmp2 = _mm_aesenc_si128(tmp2, KEY[8]);
+            tmp3 = _mm_aesenc_si128(tmp3, KEY[8]);
+            tmp4 = _mm_aesenc_si128(tmp4, KEY[8]);
+            tmp5 = _mm_aesenc_si128(tmp5, KEY[8]);
+            tmp6 = _mm_aesenc_si128(tmp6, KEY[8]);
+            tmp7 = _mm_aesenc_si128(tmp7, KEY[8]);
+            tmp8 = _mm_aesenc_si128(tmp8, KEY[8]);
+                /* Reduction */
+                X = ghash_red(r0, r1);
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[9]);
+            tmp2 = _mm_aesenc_si128(tmp2, KEY[9]);
+            tmp3 = _mm_aesenc_si128(tmp3, KEY[9]);
+            tmp4 = _mm_aesenc_si128(tmp4, KEY[9]);
+            tmp5 = _mm_aesenc_si128(tmp5, KEY[9]);
+            tmp6 = _mm_aesenc_si128(tmp6, KEY[9]);
+            tmp7 = _mm_aesenc_si128(tmp7, KEY[9]);
+            tmp8 = _mm_aesenc_si128(tmp8, KEY[9]);
+            lastKey = KEY[10];
+            if (nr > 10) {
+                tmp1 = _mm_aesenc_si128(tmp1, KEY[10]);
+                tmp2 = _mm_aesenc_si128(tmp2, KEY[10]);
+                tmp3 = _mm_aesenc_si128(tmp3, KEY[10]);
+                tmp4 = _mm_aesenc_si128(tmp4, KEY[10]);
+                tmp5 = _mm_aesenc_si128(tmp5, KEY[10]);
+                tmp6 = _mm_aesenc_si128(tmp6, KEY[10]);
+                tmp7 = _mm_aesenc_si128(tmp7, KEY[10]);
+                tmp8 = _mm_aesenc_si128(tmp8, KEY[10]);
+                tmp1 = _mm_aesenc_si128(tmp1, KEY[11]);
+                tmp2 = _mm_aesenc_si128(tmp2, KEY[11]);
+                tmp3 = _mm_aesenc_si128(tmp3, KEY[11]);
+                tmp4 = _mm_aesenc_si128(tmp4, KEY[11]);
+                tmp5 = _mm_aesenc_si128(tmp5, KEY[11]);
+                tmp6 = _mm_aesenc_si128(tmp6, KEY[11]);
+                tmp7 = _mm_aesenc_si128(tmp7, KEY[11]);
+                tmp8 = _mm_aesenc_si128(tmp8, KEY[11]);
+                lastKey = KEY[12];
+                if (nr > 12) {
+                    tmp1 = _mm_aesenc_si128(tmp1, KEY[12]);
+                    tmp2 = _mm_aesenc_si128(tmp2, KEY[12]);
+                    tmp3 = _mm_aesenc_si128(tmp3, KEY[12]);
+                    tmp4 = _mm_aesenc_si128(tmp4, KEY[12]);
+                    tmp5 = _mm_aesenc_si128(tmp5, KEY[12]);
+                    tmp6 = _mm_aesenc_si128(tmp6, KEY[12]);
+                    tmp7 = _mm_aesenc_si128(tmp7, KEY[12]);
+                    tmp8 = _mm_aesenc_si128(tmp8, KEY[12]);
+                    tmp1 = _mm_aesenc_si128(tmp1, KEY[13]);
+                    tmp2 = _mm_aesenc_si128(tmp2, KEY[13]);
+                    tmp3 = _mm_aesenc_si128(tmp3, KEY[13]);
+                    tmp4 = _mm_aesenc_si128(tmp4, KEY[13]);
+                    tmp5 = _mm_aesenc_si128(tmp5, KEY[13]);
+                    tmp6 = _mm_aesenc_si128(tmp6, KEY[13]);
+                    tmp7 = _mm_aesenc_si128(tmp7, KEY[13]);
+                    tmp8 = _mm_aesenc_si128(tmp8, KEY[13]);
+                    lastKey = KEY[14];
+                }
+            }
+            AES_ENC_LAST_8();
+        }
+    }
+
+#endif /* AES_GCM_AESNI_NO_UNROLL */
+
+    for (k = i*8; k < nbytes/16; k++) {
+        tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64);
+        ctr1 = _mm_add_epi32(ctr1, ONE);
+        tmp1 = _mm_xor_si128(tmp1, KEY[0]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[1]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[2]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[3]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[4]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[5]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[6]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[7]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[8]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[9]);
+        /* 128 x 128 Carryless Multiply */
+        XV = _mm_loadu_si128(&((__m128i*)in)[k]);
+        XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
+        XV = _mm_xor_si128(XV, X);
+        X = gfmul_shifted(XV, H);
+        lastKey = KEY[10];
+        if (nr > 10) {
+            tmp1 = _mm_aesenc_si128(tmp1, lastKey);
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[11]);
+            lastKey = KEY[12];
+            if (nr > 12) {
+                tmp1 = _mm_aesenc_si128(tmp1, lastKey);
+                tmp1 = _mm_aesenc_si128(tmp1, KEY[13]);
+                lastKey = KEY[14];
+            }
+        }
+        tmp1 = _mm_aesenclast_si128(tmp1, lastKey);
+        tmp2 = _mm_loadu_si128(&((__m128i*)in)[k]);
+        tmp1 = _mm_xor_si128(tmp1, tmp2);
+        _mm_storeu_si128(&((__m128i*)out)[k], tmp1);
+    }
+
+    /* If one partial block remains */
+    if (nbytes % 16) {
+        tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64);
+        tmp1 = _mm_xor_si128(tmp1, KEY[0]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[1]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[2]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[3]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[4]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[5]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[6]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[7]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[8]);
+        tmp1 = _mm_aesenc_si128(tmp1, KEY[9]);
+        lastKey = KEY[10];
+        if (nr > 10) {
+            tmp1 = _mm_aesenc_si128(tmp1, lastKey);
+            tmp1 = _mm_aesenc_si128(tmp1, KEY[11]);
+            lastKey = KEY[12];
+            if (nr > 12) {
+                tmp1 = _mm_aesenc_si128(tmp1, lastKey);
+                tmp1 = _mm_aesenc_si128(tmp1, KEY[13]);
+                lastKey = KEY[14];
+            }
+        }
+        tmp1 = _mm_aesenclast_si128(tmp1, lastKey);
+        last_block = _mm_setzero_si128();
+        for (j=0; j < nbytes%16; j++)
+            ((unsigned char*)&last_block)[j] = in[k*16+j];
+        XV = last_block;
+        tmp1 = _mm_xor_si128(tmp1, last_block);
+        last_block = tmp1;
+        for (j=0; j < nbytes%16; j++)
+            out[k*16+j] = ((unsigned char*)&last_block)[j];
+        XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
+        XV = _mm_xor_si128(XV, X);
+        X = gfmul_shifted(XV, H);
+    }
+
+    tmp1 = _mm_insert_epi64(tmp1, nbytes*8, 0);
+    tmp1 = _mm_insert_epi64(tmp1, abytes*8, 1);
+    /* 128 x 128 Carryless Multiply */
+    X = _mm_xor_si128(X, tmp1);
+    X = gfmul_shifted(X, H);
+    X = _mm_shuffle_epi8(X, BSWAP_MASK);
+    T = _mm_xor_si128(X, T);
+
+/*    if (0xffff !=
+           _mm_movemask_epi8(_mm_cmpeq_epi8(T, _mm_loadu_si128((__m128i*)tag)))) */
+    if (XMEMCMP(tag, &T, tbytes) != 0)
+        *res = 0; /* in case the authentication failed */
+    else
+        *res = 1; /* when successful returns 1 */
+}
+
+#endif /* HAVE_AES_DECRYPT */
+#endif /* _MSC_VER */
+#endif /* WOLFSSL_AESNI */
+
+
+#if defined(GCM_SMALL)
+static void GMULT(byte* X, byte* Y)
+{
+    byte Z[AES_BLOCK_SIZE];
+    byte V[AES_BLOCK_SIZE];
+    int i, j;
+
+    XMEMSET(Z, 0, AES_BLOCK_SIZE);
+    XMEMCPY(V, X, AES_BLOCK_SIZE);
+    for (i = 0; i < AES_BLOCK_SIZE; i++)
+    {
+        byte y = Y[i];
+        for (j = 0; j < 8; j++)
+        {
+            if (y & 0x80) {
+                xorbuf(Z, V, AES_BLOCK_SIZE);
+            }
+
+            RIGHTSHIFTX(V);
+            y = y << 1;
+        }
+    }
+    XMEMCPY(X, Z, AES_BLOCK_SIZE);
+}
+
+
+void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
+    word32 cSz, byte* s, word32 sSz)
+{
+    byte x[AES_BLOCK_SIZE];
+    byte scratch[AES_BLOCK_SIZE];
+    word32 blocks, partial;
+    byte* h = aes->H;
+
+    XMEMSET(x, 0, AES_BLOCK_SIZE);
+
+    /* Hash in A, the Additional Authentication Data */
+    if (aSz != 0 && a != NULL) {
+        blocks = aSz / AES_BLOCK_SIZE;
+        partial = aSz % AES_BLOCK_SIZE;
+        while (blocks--) {
+            xorbuf(x, a, AES_BLOCK_SIZE);
+            GMULT(x, h);
+            a += AES_BLOCK_SIZE;
+        }
+        if (partial != 0) {
+            XMEMSET(scratch, 0, AES_BLOCK_SIZE);
+            XMEMCPY(scratch, a, partial);
+            xorbuf(x, scratch, AES_BLOCK_SIZE);
+            GMULT(x, h);
+        }
+    }
+
+    /* Hash in C, the Ciphertext */
+    if (cSz != 0 && c != NULL) {
+        blocks = cSz / AES_BLOCK_SIZE;
+        partial = cSz % AES_BLOCK_SIZE;
+        while (blocks--) {
+            xorbuf(x, c, AES_BLOCK_SIZE);
+            GMULT(x, h);
+            c += AES_BLOCK_SIZE;
+        }
+        if (partial != 0) {
+            XMEMSET(scratch, 0, AES_BLOCK_SIZE);
+            XMEMCPY(scratch, c, partial);
+            xorbuf(x, scratch, AES_BLOCK_SIZE);
+            GMULT(x, h);
+        }
+    }
+
+    /* Hash in the lengths of A and C in bits */
+    FlattenSzInBits(&scratch[0], aSz);
+    FlattenSzInBits(&scratch[8], cSz);
+    xorbuf(x, scratch, AES_BLOCK_SIZE);
+    GMULT(x, h);
+
+    /* Copy the result into s. */
+    XMEMCPY(s, x, sSz);
+}
+
+/* end GCM_SMALL */
+#elif defined(GCM_TABLE)
+
+static const byte R[256][2] = {
+    {0x00, 0x00}, {0x01, 0xc2}, {0x03, 0x84}, {0x02, 0x46},
+    {0x07, 0x08}, {0x06, 0xca}, {0x04, 0x8c}, {0x05, 0x4e},
+    {0x0e, 0x10}, {0x0f, 0xd2}, {0x0d, 0x94}, {0x0c, 0x56},
+    {0x09, 0x18}, {0x08, 0xda}, {0x0a, 0x9c}, {0x0b, 0x5e},
+    {0x1c, 0x20}, {0x1d, 0xe2}, {0x1f, 0xa4}, {0x1e, 0x66},
+    {0x1b, 0x28}, {0x1a, 0xea}, {0x18, 0xac}, {0x19, 0x6e},
+    {0x12, 0x30}, {0x13, 0xf2}, {0x11, 0xb4}, {0x10, 0x76},
+    {0x15, 0x38}, {0x14, 0xfa}, {0x16, 0xbc}, {0x17, 0x7e},
+    {0x38, 0x40}, {0x39, 0x82}, {0x3b, 0xc4}, {0x3a, 0x06},
+    {0x3f, 0x48}, {0x3e, 0x8a}, {0x3c, 0xcc}, {0x3d, 0x0e},
+    {0x36, 0x50}, {0x37, 0x92}, {0x35, 0xd4}, {0x34, 0x16},
+    {0x31, 0x58}, {0x30, 0x9a}, {0x32, 0xdc}, {0x33, 0x1e},
+    {0x24, 0x60}, {0x25, 0xa2}, {0x27, 0xe4}, {0x26, 0x26},
+    {0x23, 0x68}, {0x22, 0xaa}, {0x20, 0xec}, {0x21, 0x2e},
+    {0x2a, 0x70}, {0x2b, 0xb2}, {0x29, 0xf4}, {0x28, 0x36},
+    {0x2d, 0x78}, {0x2c, 0xba}, {0x2e, 0xfc}, {0x2f, 0x3e},
+    {0x70, 0x80}, {0x71, 0x42}, {0x73, 0x04}, {0x72, 0xc6},
+    {0x77, 0x88}, {0x76, 0x4a}, {0x74, 0x0c}, {0x75, 0xce},
+    {0x7e, 0x90}, {0x7f, 0x52}, {0x7d, 0x14}, {0x7c, 0xd6},
+    {0x79, 0x98}, {0x78, 0x5a}, {0x7a, 0x1c}, {0x7b, 0xde},
+    {0x6c, 0xa0}, {0x6d, 0x62}, {0x6f, 0x24}, {0x6e, 0xe6},
+    {0x6b, 0xa8}, {0x6a, 0x6a}, {0x68, 0x2c}, {0x69, 0xee},
+    {0x62, 0xb0}, {0x63, 0x72}, {0x61, 0x34}, {0x60, 0xf6},
+    {0x65, 0xb8}, {0x64, 0x7a}, {0x66, 0x3c}, {0x67, 0xfe},
+    {0x48, 0xc0}, {0x49, 0x02}, {0x4b, 0x44}, {0x4a, 0x86},
+    {0x4f, 0xc8}, {0x4e, 0x0a}, {0x4c, 0x4c}, {0x4d, 0x8e},
+    {0x46, 0xd0}, {0x47, 0x12}, {0x45, 0x54}, {0x44, 0x96},
+    {0x41, 0xd8}, {0x40, 0x1a}, {0x42, 0x5c}, {0x43, 0x9e},
+    {0x54, 0xe0}, {0x55, 0x22}, {0x57, 0x64}, {0x56, 0xa6},
+    {0x53, 0xe8}, {0x52, 0x2a}, {0x50, 0x6c}, {0x51, 0xae},
+    {0x5a, 0xf0}, {0x5b, 0x32}, {0x59, 0x74}, {0x58, 0xb6},
+    {0x5d, 0xf8}, {0x5c, 0x3a}, {0x5e, 0x7c}, {0x5f, 0xbe},
+    {0xe1, 0x00}, {0xe0, 0xc2}, {0xe2, 0x84}, {0xe3, 0x46},
+    {0xe6, 0x08}, {0xe7, 0xca}, {0xe5, 0x8c}, {0xe4, 0x4e},
+    {0xef, 0x10}, {0xee, 0xd2}, {0xec, 0x94}, {0xed, 0x56},
+    {0xe8, 0x18}, {0xe9, 0xda}, {0xeb, 0x9c}, {0xea, 0x5e},
+    {0xfd, 0x20}, {0xfc, 0xe2}, {0xfe, 0xa4}, {0xff, 0x66},
+    {0xfa, 0x28}, {0xfb, 0xea}, {0xf9, 0xac}, {0xf8, 0x6e},
+    {0xf3, 0x30}, {0xf2, 0xf2}, {0xf0, 0xb4}, {0xf1, 0x76},
+    {0xf4, 0x38}, {0xf5, 0xfa}, {0xf7, 0xbc}, {0xf6, 0x7e},
+    {0xd9, 0x40}, {0xd8, 0x82}, {0xda, 0xc4}, {0xdb, 0x06},
+    {0xde, 0x48}, {0xdf, 0x8a}, {0xdd, 0xcc}, {0xdc, 0x0e},
+    {0xd7, 0x50}, {0xd6, 0x92}, {0xd4, 0xd4}, {0xd5, 0x16},
+    {0xd0, 0x58}, {0xd1, 0x9a}, {0xd3, 0xdc}, {0xd2, 0x1e},
+    {0xc5, 0x60}, {0xc4, 0xa2}, {0xc6, 0xe4}, {0xc7, 0x26},
+    {0xc2, 0x68}, {0xc3, 0xaa}, {0xc1, 0xec}, {0xc0, 0x2e},
+    {0xcb, 0x70}, {0xca, 0xb2}, {0xc8, 0xf4}, {0xc9, 0x36},
+    {0xcc, 0x78}, {0xcd, 0xba}, {0xcf, 0xfc}, {0xce, 0x3e},
+    {0x91, 0x80}, {0x90, 0x42}, {0x92, 0x04}, {0x93, 0xc6},
+    {0x96, 0x88}, {0x97, 0x4a}, {0x95, 0x0c}, {0x94, 0xce},
+    {0x9f, 0x90}, {0x9e, 0x52}, {0x9c, 0x14}, {0x9d, 0xd6},
+    {0x98, 0x98}, {0x99, 0x5a}, {0x9b, 0x1c}, {0x9a, 0xde},
+    {0x8d, 0xa0}, {0x8c, 0x62}, {0x8e, 0x24}, {0x8f, 0xe6},
+    {0x8a, 0xa8}, {0x8b, 0x6a}, {0x89, 0x2c}, {0x88, 0xee},
+    {0x83, 0xb0}, {0x82, 0x72}, {0x80, 0x34}, {0x81, 0xf6},
+    {0x84, 0xb8}, {0x85, 0x7a}, {0x87, 0x3c}, {0x86, 0xfe},
+    {0xa9, 0xc0}, {0xa8, 0x02}, {0xaa, 0x44}, {0xab, 0x86},
+    {0xae, 0xc8}, {0xaf, 0x0a}, {0xad, 0x4c}, {0xac, 0x8e},
+    {0xa7, 0xd0}, {0xa6, 0x12}, {0xa4, 0x54}, {0xa5, 0x96},
+    {0xa0, 0xd8}, {0xa1, 0x1a}, {0xa3, 0x5c}, {0xa2, 0x9e},
+    {0xb5, 0xe0}, {0xb4, 0x22}, {0xb6, 0x64}, {0xb7, 0xa6},
+    {0xb2, 0xe8}, {0xb3, 0x2a}, {0xb1, 0x6c}, {0xb0, 0xae},
+    {0xbb, 0xf0}, {0xba, 0x32}, {0xb8, 0x74}, {0xb9, 0xb6},
+    {0xbc, 0xf8}, {0xbd, 0x3a}, {0xbf, 0x7c}, {0xbe, 0xbe} };
+
+
+static void GMULT(byte *x, byte m[256][AES_BLOCK_SIZE])
+{
+    int i, j;
+    byte Z[AES_BLOCK_SIZE];
+    byte a;
+
+    XMEMSET(Z, 0, sizeof(Z));
+
+    for (i = 15; i > 0; i--) {
+        xorbuf(Z, m[x[i]], AES_BLOCK_SIZE);
+        a = Z[15];
+
+        for (j = 15; j > 0; j--) {
+            Z[j] = Z[j-1];
+        }
+
+        Z[0] = R[a][0];
+        Z[1] ^= R[a][1];
+    }
+    xorbuf(Z, m[x[0]], AES_BLOCK_SIZE);
+
+    XMEMCPY(x, Z, AES_BLOCK_SIZE);
+}
+
+
+void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
+    word32 cSz, byte* s, word32 sSz)
+{
+    byte x[AES_BLOCK_SIZE];
+    byte scratch[AES_BLOCK_SIZE];
+    word32 blocks, partial;
+
+    XMEMSET(x, 0, AES_BLOCK_SIZE);
+
+    /* Hash in A, the Additional Authentication Data */
+    if (aSz != 0 && a != NULL) {
+        blocks = aSz / AES_BLOCK_SIZE;
+        partial = aSz % AES_BLOCK_SIZE;
+        while (blocks--) {
+            xorbuf(x, a, AES_BLOCK_SIZE);
+            GMULT(x, aes->M0);
+            a += AES_BLOCK_SIZE;
+        }
+        if (partial != 0) {
+            XMEMSET(scratch, 0, AES_BLOCK_SIZE);
+            XMEMCPY(scratch, a, partial);
+            xorbuf(x, scratch, AES_BLOCK_SIZE);
+            GMULT(x, aes->M0);
+        }
+    }
+
+    /* Hash in C, the Ciphertext */
+    if (cSz != 0 && c != NULL) {
+        blocks = cSz / AES_BLOCK_SIZE;
+        partial = cSz % AES_BLOCK_SIZE;
+        while (blocks--) {
+            xorbuf(x, c, AES_BLOCK_SIZE);
+            GMULT(x, aes->M0);
+            c += AES_BLOCK_SIZE;
+        }
+        if (partial != 0) {
+            XMEMSET(scratch, 0, AES_BLOCK_SIZE);
+            XMEMCPY(scratch, c, partial);
+            xorbuf(x, scratch, AES_BLOCK_SIZE);
+            GMULT(x, aes->M0);
+        }
+    }
+
+    /* Hash in the lengths of A and C in bits */
+    FlattenSzInBits(&scratch[0], aSz);
+    FlattenSzInBits(&scratch[8], cSz);
+    xorbuf(x, scratch, AES_BLOCK_SIZE);
+    GMULT(x, aes->M0);
+
+    /* Copy the result into s. */
+    XMEMCPY(s, x, sSz);
+}
+
+/* end GCM_TABLE */
+#elif defined(WORD64_AVAILABLE) && !defined(GCM_WORD32)
+
+#if !defined(FREESCALE_LTC_AES_GCM)
+static void GMULT(word64* X, word64* Y)
+{
+    word64 Z[2] = {0,0};
+    word64 V[2];
+    int i, j;
+    V[0] = X[0];  V[1] = X[1];
+
+    for (i = 0; i < 2; i++)
+    {
+        word64 y = Y[i];
+        for (j = 0; j < 64; j++)
+        {
+            if (y & 0x8000000000000000ULL) {
+                Z[0] ^= V[0];
+                Z[1] ^= V[1];
+            }
+
+            if (V[1] & 0x0000000000000001) {
+                V[1] >>= 1;
+                V[1] |= ((V[0] & 0x0000000000000001) ?
+                    0x8000000000000000ULL : 0);
+                V[0] >>= 1;
+                V[0] ^= 0xE100000000000000ULL;
+            }
+            else {
+                V[1] >>= 1;
+                V[1] |= ((V[0] & 0x0000000000000001) ?
+                    0x8000000000000000ULL : 0);
+                V[0] >>= 1;
+            }
+            y <<= 1;
+        }
+    }
+    X[0] = Z[0];
+    X[1] = Z[1];
+}
+
+
+void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
+    word32 cSz, byte* s, word32 sSz)
+{
+    word64 x[2] = {0,0};
+    word32 blocks, partial;
+    word64 bigH[2];
+
+    XMEMCPY(bigH, aes->H, AES_BLOCK_SIZE);
+    #ifdef LITTLE_ENDIAN_ORDER
+        ByteReverseWords64(bigH, bigH, AES_BLOCK_SIZE);
+    #endif
+
+    /* Hash in A, the Additional Authentication Data */
+    if (aSz != 0 && a != NULL) {
+        word64 bigA[2];
+        blocks = aSz / AES_BLOCK_SIZE;
+        partial = aSz % AES_BLOCK_SIZE;
+        while (blocks--) {
+            XMEMCPY(bigA, a, AES_BLOCK_SIZE);
+            #ifdef LITTLE_ENDIAN_ORDER
+                ByteReverseWords64(bigA, bigA, AES_BLOCK_SIZE);
+            #endif
+            x[0] ^= bigA[0];
+            x[1] ^= bigA[1];
+            GMULT(x, bigH);
+            a += AES_BLOCK_SIZE;
+        }
+        if (partial != 0) {
+            XMEMSET(bigA, 0, AES_BLOCK_SIZE);
+            XMEMCPY(bigA, a, partial);
+            #ifdef LITTLE_ENDIAN_ORDER
+                ByteReverseWords64(bigA, bigA, AES_BLOCK_SIZE);
+            #endif
+            x[0] ^= bigA[0];
+            x[1] ^= bigA[1];
+            GMULT(x, bigH);
+        }
+#ifdef OPENSSL_EXTRA
+        /* store AAD partial tag for next call */
+        aes->aadH[0] = (word32)((x[0] & 0xFFFFFFFF00000000) >> 32);
+        aes->aadH[1] = (word32)(x[0] & 0xFFFFFFFF);
+        aes->aadH[2] = (word32)((x[1] & 0xFFFFFFFF00000000) >> 32);
+        aes->aadH[3] = (word32)(x[1] & 0xFFFFFFFF);
+#endif
+    }
+
+    /* Hash in C, the Ciphertext */
+    if (cSz != 0 && c != NULL) {
+        word64 bigC[2];
+        blocks = cSz / AES_BLOCK_SIZE;
+        partial = cSz % AES_BLOCK_SIZE;
+#ifdef OPENSSL_EXTRA
+        /* Start from last AAD partial tag */
+        if(aes->aadLen) {
+            x[0] = ((word64)aes->aadH[0]) << 32 | aes->aadH[1];
+            x[1] = ((word64)aes->aadH[2]) << 32 | aes->aadH[3];
+         }
+#endif
+        while (blocks--) {
+            XMEMCPY(bigC, c, AES_BLOCK_SIZE);
+            #ifdef LITTLE_ENDIAN_ORDER
+                ByteReverseWords64(bigC, bigC, AES_BLOCK_SIZE);
+            #endif
+            x[0] ^= bigC[0];
+            x[1] ^= bigC[1];
+            GMULT(x, bigH);
+            c += AES_BLOCK_SIZE;
+        }
+        if (partial != 0) {
+            XMEMSET(bigC, 0, AES_BLOCK_SIZE);
+            XMEMCPY(bigC, c, partial);
+            #ifdef LITTLE_ENDIAN_ORDER
+                ByteReverseWords64(bigC, bigC, AES_BLOCK_SIZE);
+            #endif
+            x[0] ^= bigC[0];
+            x[1] ^= bigC[1];
+            GMULT(x, bigH);
+        }
+    }
+
+    /* Hash in the lengths in bits of A and C */
+    {
+        word64 len[2];
+        len[0] = aSz; len[1] = cSz;
+#ifdef OPENSSL_EXTRA
+        if (aes->aadLen)
+            len[0] = (word64)aes->aadLen;
+#endif
+        /* Lengths are in bytes. Convert to bits. */
+        len[0] *= 8;
+        len[1] *= 8;
+
+        x[0] ^= len[0];
+        x[1] ^= len[1];
+        GMULT(x, bigH);
+    }
+    #ifdef LITTLE_ENDIAN_ORDER
+        ByteReverseWords64(x, x, AES_BLOCK_SIZE);
+    #endif
+    XMEMCPY(s, x, sSz);
+}
+#endif /* !FREESCALE_LTC_AES_GCM */
+
+/* end defined(WORD64_AVAILABLE) && !defined(GCM_WORD32) */
+#else /* GCM_WORD32 */
+
+static void GMULT(word32* X, word32* Y)
+{
+    word32 Z[4] = {0,0,0,0};
+    word32 V[4];
+    int i, j;
+
+    V[0] = X[0];  V[1] = X[1]; V[2] =  X[2]; V[3] =  X[3];
+
+    for (i = 0; i < 4; i++)
+    {
+        word32 y = Y[i];
+        for (j = 0; j < 32; j++)
+        {
+            if (y & 0x80000000) {
+                Z[0] ^= V[0];
+                Z[1] ^= V[1];
+                Z[2] ^= V[2];
+                Z[3] ^= V[3];
+            }
+
+            if (V[3] & 0x00000001) {
+                V[3] >>= 1;
+                V[3] |= ((V[2] & 0x00000001) ? 0x80000000 : 0);
+                V[2] >>= 1;
+                V[2] |= ((V[1] & 0x00000001) ? 0x80000000 : 0);
+                V[1] >>= 1;
+                V[1] |= ((V[0] & 0x00000001) ? 0x80000000 : 0);
+                V[0] >>= 1;
+                V[0] ^= 0xE1000000;
+            } else {
+                V[3] >>= 1;
+                V[3] |= ((V[2] & 0x00000001) ? 0x80000000 : 0);
+                V[2] >>= 1;
+                V[2] |= ((V[1] & 0x00000001) ? 0x80000000 : 0);
+                V[1] >>= 1;
+                V[1] |= ((V[0] & 0x00000001) ? 0x80000000 : 0);
+                V[0] >>= 1;
+            }
+            y <<= 1;
+        }
+    }
+    X[0] = Z[0];
+    X[1] = Z[1];
+    X[2] = Z[2];
+    X[3] = Z[3];
+}
+
+
+void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
+    word32 cSz, byte* s, word32 sSz)
+{
+    word32 x[4] = {0,0,0,0};
+    word32 blocks, partial;
+    word32 bigH[4];
+
+    XMEMCPY(bigH, aes->H, AES_BLOCK_SIZE);
+    #ifdef LITTLE_ENDIAN_ORDER
+        ByteReverseWords(bigH, bigH, AES_BLOCK_SIZE);
+    #endif
+
+    /* Hash in A, the Additional Authentication Data */
+    if (aSz != 0 && a != NULL) {
+        word32 bigA[4];
+        blocks = aSz / AES_BLOCK_SIZE;
+        partial = aSz % AES_BLOCK_SIZE;
+        while (blocks--) {
+            XMEMCPY(bigA, a, AES_BLOCK_SIZE);
+            #ifdef LITTLE_ENDIAN_ORDER
+                ByteReverseWords(bigA, bigA, AES_BLOCK_SIZE);
+            #endif
+            x[0] ^= bigA[0];
+            x[1] ^= bigA[1];
+            x[2] ^= bigA[2];
+            x[3] ^= bigA[3];
+            GMULT(x, bigH);
+            a += AES_BLOCK_SIZE;
+        }
+        if (partial != 0) {
+            XMEMSET(bigA, 0, AES_BLOCK_SIZE);
+            XMEMCPY(bigA, a, partial);
+            #ifdef LITTLE_ENDIAN_ORDER
+                ByteReverseWords(bigA, bigA, AES_BLOCK_SIZE);
+            #endif
+            x[0] ^= bigA[0];
+            x[1] ^= bigA[1];
+            x[2] ^= bigA[2];
+            x[3] ^= bigA[3];
+            GMULT(x, bigH);
+        }
+    }
+
+    /* Hash in C, the Ciphertext */
+    if (cSz != 0 && c != NULL) {
+        word32 bigC[4];
+        blocks = cSz / AES_BLOCK_SIZE;
+        partial = cSz % AES_BLOCK_SIZE;
+        while (blocks--) {
+            XMEMCPY(bigC, c, AES_BLOCK_SIZE);
+            #ifdef LITTLE_ENDIAN_ORDER
+                ByteReverseWords(bigC, bigC, AES_BLOCK_SIZE);
+            #endif
+            x[0] ^= bigC[0];
+            x[1] ^= bigC[1];
+            x[2] ^= bigC[2];
+            x[3] ^= bigC[3];
+            GMULT(x, bigH);
+            c += AES_BLOCK_SIZE;
+        }
+        if (partial != 0) {
+            XMEMSET(bigC, 0, AES_BLOCK_SIZE);
+            XMEMCPY(bigC, c, partial);
+            #ifdef LITTLE_ENDIAN_ORDER
+                ByteReverseWords(bigC, bigC, AES_BLOCK_SIZE);
+            #endif
+            x[0] ^= bigC[0];
+            x[1] ^= bigC[1];
+            x[2] ^= bigC[2];
+            x[3] ^= bigC[3];
+            GMULT(x, bigH);
+        }
+    }
+
+    /* Hash in the lengths in bits of A and C */
+    {
+        word32 len[4];
+
+        /* Lengths are in bytes. Convert to bits. */
+        len[0] = (aSz >> (8*sizeof(aSz) - 3));
+        len[1] = aSz << 3;
+        len[2] = (cSz >> (8*sizeof(cSz) - 3));
+        len[3] = cSz << 3;
+
+        x[0] ^= len[0];
+        x[1] ^= len[1];
+        x[2] ^= len[2];
+        x[3] ^= len[3];
+        GMULT(x, bigH);
+    }
+    #ifdef LITTLE_ENDIAN_ORDER
+        ByteReverseWords(x, x, AES_BLOCK_SIZE);
+    #endif
+    XMEMCPY(s, x, sSz);
+}
+
+#endif /* end GCM_WORD32 */
+
+
+#if !defined(WOLFSSL_XILINX_CRYPT) && !defined(WOLFSSL_AFALG_XILINX_AES)
+#ifdef FREESCALE_LTC_AES_GCM
+int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
+                   const byte* iv, word32 ivSz,
+                   byte* authTag, word32 authTagSz,
+                   const byte* authIn, word32 authInSz)
+{
+    status_t status;
+    word32 keySize;
+
+    /* argument checks */
+    if (aes == NULL || authTagSz > AES_BLOCK_SIZE || ivSz == 0) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) {
+        WOLFSSL_MSG("GcmEncrypt authTagSz too small error");
+        return BAD_FUNC_ARG;
+    }
+
+    status = wc_AesGetKeySize(aes, &keySize);
+    if (status)
+        return status;
+
+    status = LTC_AES_EncryptTagGcm(LTC_BASE, in, out, sz, iv, ivSz,
+        authIn, authInSz, (byte*)aes->key, keySize, authTag, authTagSz);
+
+    return (status == kStatus_Success) ? 0 : AES_GCM_AUTH_E;
+}
+
+#else
+
+#ifdef STM32_CRYPTO_AES_GCM
+
+/* this function supports inline encrypt */
+static int wc_AesGcmEncrypt_STM32(Aes* aes, byte* out, const byte* in, word32 sz,
+                                  const byte* iv, word32 ivSz,
+                                  byte* authTag, word32 authTagSz,
+                                  const byte* authIn, word32 authInSz)
+{
+    int ret;
+#ifdef WOLFSSL_STM32_CUBEMX
+    CRYP_HandleTypeDef hcryp;
+#else
+    word32 keyCopy[AES_256_KEY_SIZE/sizeof(word32)];
+#endif
+    word32 keySize;
+    int status = HAL_OK;
+    word32 blocks = sz / AES_BLOCK_SIZE;
+    word32 partial = sz % AES_BLOCK_SIZE;
+    byte tag[AES_BLOCK_SIZE];
+    byte partialBlock[AES_BLOCK_SIZE];
+    byte ctr[AES_BLOCK_SIZE];
+    byte* authInPadded = NULL;
+    int authPadSz;
+
+    ret = wc_AesGetKeySize(aes, &keySize);
+    if (ret != 0)
+        return ret;
+
+#ifdef WOLFSSL_STM32_CUBEMX
+    ret = wc_Stm32_Aes_Init(aes, &hcryp);
+    if (ret != 0)
+        return ret;
+#endif
+
+    ret = wolfSSL_CryptHwMutexLock();
+    if (ret != 0) {
+        return ret;
+    }
+
+    XMEMSET(ctr, 0, AES_BLOCK_SIZE);
+    if (ivSz == GCM_NONCE_MID_SZ) {
+        XMEMCPY(ctr, iv, ivSz);
+        ctr[AES_BLOCK_SIZE - 1] = 1;
+    }
+    else {
+        GHASH(aes, NULL, 0, iv, ivSz, ctr, AES_BLOCK_SIZE);
+    }
+    /* Hardware requires counter + 1 */
+    IncrementGcmCounter(ctr);
+
+    if (authInSz == 0 || (authInSz % AES_BLOCK_SIZE) != 0) {
+        /* Need to pad the AAD to a full block with zeros. */
+        authPadSz = ((authInSz / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE;
+        authInPadded = (byte*)XMALLOC(authPadSz, aes->heap,
+            DYNAMIC_TYPE_TMP_BUFFER);
+        if (authInPadded == NULL) {
+            wolfSSL_CryptHwMutexUnLock();
+            return MEMORY_E;
+        }
+        XMEMSET(authInPadded, 0, authPadSz);
+        XMEMCPY(authInPadded, authIn, authInSz);
+    } else {
+        authPadSz = authInSz;
+        authInPadded = (byte*)authIn;
+    }
+
+#ifdef WOLFSSL_STM32_CUBEMX
+    hcryp.Init.pInitVect = (STM_CRYPT_TYPE*)ctr;
+    hcryp.Init.Header = (STM_CRYPT_TYPE*)authInPadded;
+    hcryp.Init.HeaderSize = authInSz;
+
+#ifdef STM32_CRYPTO_AES_ONLY
+    /* Set the CRYP parameters */
+    hcryp.Init.ChainingMode  = CRYP_CHAINMODE_AES_GCM_GMAC;
+    hcryp.Init.OperatingMode = CRYP_ALGOMODE_ENCRYPT;
+    hcryp.Init.GCMCMACPhase  = CRYP_INIT_PHASE;
+    HAL_CRYP_Init(&hcryp);
+
+    /* GCM init phase */
+    status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, 0, NULL, STM32_HAL_TIMEOUT);
+    if (status == HAL_OK) {
+        /* GCM header phase */
+        hcryp.Init.GCMCMACPhase  = CRYP_HEADER_PHASE;
+        status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, 0, NULL, STM32_HAL_TIMEOUT);
+    }
+    if (status == HAL_OK) {
+        /* GCM payload phase - blocks */
+        hcryp.Init.GCMCMACPhase  = CRYP_PAYLOAD_PHASE;
+        if (blocks) {
+            status = HAL_CRYPEx_AES_Auth(&hcryp, (byte*)in,
+                (blocks * AES_BLOCK_SIZE), out, STM32_HAL_TIMEOUT);
+        }
+    }
+    if (status == HAL_OK && (partial != 0 || blocks == 0)) {
+        /* GCM payload phase - partial remainder */
+        XMEMSET(partialBlock, 0, sizeof(partialBlock));
+        XMEMCPY(partialBlock, in + (blocks * AES_BLOCK_SIZE), partial);
+        status = HAL_CRYPEx_AES_Auth(&hcryp, partialBlock, partial,
+            partialBlock, STM32_HAL_TIMEOUT);
+        XMEMCPY(out + (blocks * AES_BLOCK_SIZE), partialBlock, partial);
+    }
+    if (status == HAL_OK) {
+        /* GCM final phase */
+        hcryp.Init.GCMCMACPhase  = CRYP_FINAL_PHASE;
+        status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, sz, tag, STM32_HAL_TIMEOUT);
+    }
+#elif defined(STM32_HAL_V2)
+    hcryp.Init.Algorithm  = CRYP_AES_GCM;
+    ByteReverseWords((word32*)partialBlock, (word32*)ctr, AES_BLOCK_SIZE);
+    hcryp.Init.pInitVect = (STM_CRYPT_TYPE*)partialBlock;
+    HAL_CRYP_Init(&hcryp);
+
+    /* GCM payload phase - can handle partial blocks */
+    status = HAL_CRYP_Encrypt(&hcryp, (uint32_t*)in,
+        (blocks * AES_BLOCK_SIZE) + partial, (uint32_t*)out, STM32_HAL_TIMEOUT);
+    if (status == HAL_OK) {
+        /* Compute the authTag */
+        status = HAL_CRYPEx_AESGCM_GenerateAuthTAG(&hcryp, (uint32_t*)tag,
+            STM32_HAL_TIMEOUT);
+    }
+#else
+    HAL_CRYP_Init(&hcryp);
+    if (blocks) {
+        /* GCM payload phase - blocks */
+        status = HAL_CRYPEx_AESGCM_Encrypt(&hcryp, (byte*)in,
+            (blocks * AES_BLOCK_SIZE), out, STM32_HAL_TIMEOUT);
+    }
+    if (status == HAL_OK && (partial != 0 || blocks == 0)) {
+        /* GCM payload phase - partial remainder */
+        XMEMSET(partialBlock, 0, sizeof(partialBlock));
+        XMEMCPY(partialBlock, in + (blocks * AES_BLOCK_SIZE), partial);
+        status = HAL_CRYPEx_AESGCM_Encrypt(&hcryp, partialBlock, partial,
+            partialBlock, STM32_HAL_TIMEOUT);
+        XMEMCPY(out + (blocks * AES_BLOCK_SIZE), partialBlock, partial);
+    }
+    if (status == HAL_OK) {
+        /* Compute the authTag */
+        status = HAL_CRYPEx_AESGCM_Finish(&hcryp, sz, tag, STM32_HAL_TIMEOUT);
+    }
+#endif
+
+    if (status != HAL_OK)
+        ret = AES_GCM_AUTH_E;
+    HAL_CRYP_DeInit(&hcryp);
+
+#else /* STD_PERI_LIB */
+    ByteReverseWords(keyCopy, (word32*)aes->key, keySize);
+    status = CRYP_AES_GCM(MODE_ENCRYPT, (uint8_t*)ctr,
+                         (uint8_t*)keyCopy,      keySize * 8,
+                         (uint8_t*)in,           sz,
+                         (uint8_t*)authInPadded, authInSz,
+                         (uint8_t*)out,          tag);
+    if (status != SUCCESS)
+        ret = AES_GCM_AUTH_E;
+#endif /* WOLFSSL_STM32_CUBEMX */
+
+    if (ret == 0) {
+        /* return authTag */
+        if (authTag) {
+            /* STM32 GCM won't compute Auth correctly for partial or
+                when IV != 12, so use software here */
+            if (sz == 0 || partial != 0 || ivSz != GCM_NONCE_MID_SZ) {
+                DecrementGcmCounter(ctr); /* hardware requires +1, so subtract it */
+                GHASH(aes, authIn, authInSz, out, sz, authTag, authTagSz);
+                wc_AesEncrypt(aes, ctr, tag);
+                xorbuf(authTag, tag, authTagSz);
+            }
+            else {
+                XMEMCPY(authTag, tag, authTagSz);
+            }
+        }
+    }
+
+    /* Free memory if not a multiple of AES_BLOCK_SZ */
+    if (authInPadded != authIn) {
+        XFREE(authInPadded, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+
+    wolfSSL_CryptHwMutexUnLock();
+
+    return ret;
+}
+
+#endif /* STM32_CRYPTO_AES_GCM */
+
+#ifdef WOLFSSL_AESNI
+int AES_GCM_encrypt_C(Aes* aes, byte* out, const byte* in, word32 sz,
+                      const byte* iv, word32 ivSz,
+                      byte* authTag, word32 authTagSz,
+                      const byte* authIn, word32 authInSz);
+#else
+static
+#endif
+int AES_GCM_encrypt_C(Aes* aes, byte* out, const byte* in, word32 sz,
+                      const byte* iv, word32 ivSz,
+                      byte* authTag, word32 authTagSz,
+                      const byte* authIn, word32 authInSz)
+{
+    int ret = 0;
+    word32 blocks = sz / AES_BLOCK_SIZE;
+    word32 partial = sz % AES_BLOCK_SIZE;
+    const byte* p = in;
+    byte* c = out;
+    byte counter[AES_BLOCK_SIZE];
+    byte initialCounter[AES_BLOCK_SIZE];
+    byte *ctr;
+    byte scratch[AES_BLOCK_SIZE];
+#ifdef OPENSSL_EXTRA
+    word32 aadTemp;
+#endif
+    ctr = counter;
+    XMEMSET(initialCounter, 0, AES_BLOCK_SIZE);
+    XMEMSET(scratch, 0, AES_BLOCK_SIZE);
+    if (ivSz == GCM_NONCE_MID_SZ) {
+        XMEMCPY(initialCounter, iv, ivSz);
+        initialCounter[AES_BLOCK_SIZE - 1] = 1;
+    }
+    else {
+#ifdef OPENSSL_EXTRA
+        aadTemp = aes->aadLen;
+        aes->aadLen = 0;
+#endif
+        GHASH(aes, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE);
+#ifdef OPENSSL_EXTRA
+        aes->aadLen = aadTemp;
+#endif
+    }
+    XMEMCPY(ctr, initialCounter, AES_BLOCK_SIZE);
+
+#ifdef WOLFSSL_PIC32MZ_CRYPT
+    if (blocks) {
+        /* use initial IV for HW, but don't use it below */
+        XMEMCPY(aes->reg, ctr, AES_BLOCK_SIZE);
+
+        ret = wc_Pic32AesCrypt(
+            aes->key, aes->keylen, aes->reg, AES_BLOCK_SIZE,
+            out, in, (blocks * AES_BLOCK_SIZE),
+            PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_AES_GCM);
+        if (ret != 0)
+            return ret;
+    }
+    /* process remainder using partial handling */
+#endif
+
+#if defined(HAVE_AES_ECB) && !defined(WOLFSSL_PIC32MZ_CRYPT)
+    /* some hardware acceleration can gain performance from doing AES encryption
+     * of the whole buffer at once */
+    if (c != p && blocks > 0) { /* can not handle inline encryption */
+        while (blocks--) {
+            IncrementGcmCounter(ctr);
+            XMEMCPY(c, ctr, AES_BLOCK_SIZE);
+            c += AES_BLOCK_SIZE;
+        }
+
+        /* reset number of blocks and then do encryption */
+        blocks = sz / AES_BLOCK_SIZE;
+        wc_AesEcbEncrypt(aes, out, out, AES_BLOCK_SIZE * blocks);
+        xorbuf(out, p, AES_BLOCK_SIZE * blocks);
+        p += AES_BLOCK_SIZE * blocks;
+    }
+    else
+#endif /* HAVE_AES_ECB && !WOLFSSL_PIC32MZ_CRYPT */
+
+    while (blocks--) {
+        IncrementGcmCounter(ctr);
+    #if !defined(WOLFSSL_PIC32MZ_CRYPT)
+        wc_AesEncrypt(aes, ctr, scratch);
+        xorbuf(scratch, p, AES_BLOCK_SIZE);
+        XMEMCPY(c, scratch, AES_BLOCK_SIZE);
+    #endif
+        p += AES_BLOCK_SIZE;
+        c += AES_BLOCK_SIZE;
+    }
+
+    if (partial != 0) {
+        IncrementGcmCounter(ctr);
+        wc_AesEncrypt(aes, ctr, scratch);
+        xorbuf(scratch, p, partial);
+        XMEMCPY(c, scratch, partial);
+    }
+    if (authTag) {
+        GHASH(aes, authIn, authInSz, out, sz, authTag, authTagSz);
+        wc_AesEncrypt(aes, initialCounter, scratch);
+        xorbuf(authTag, scratch, authTagSz);
+#ifdef OPENSSL_EXTRA
+        if (!in && !sz)
+            /* store AAD size for next call */
+            aes->aadLen = authInSz;
+#endif
+    }
+
+    return ret;
+}
+
+/* Software AES - GCM Encrypt */
+int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
+                   const byte* iv, word32 ivSz,
+                   byte* authTag, word32 authTagSz,
+                   const byte* authIn, word32 authInSz)
+{
+    /* argument checks */
+    if (aes == NULL || authTagSz > AES_BLOCK_SIZE || ivSz == 0) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) {
+        WOLFSSL_MSG("GcmEncrypt authTagSz too small error");
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef WOLF_CRYPTO_CB
+    if (aes->devId != INVALID_DEVID) {
+        int ret = wc_CryptoCb_AesGcmEncrypt(aes, out, in, sz, iv, ivSz,
+            authTag, authTagSz, authIn, authInSz);
+        if (ret != CRYPTOCB_UNAVAILABLE)
+            return ret;
+        /* fall-through when unavailable */
+    }
+#endif
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES)
+    /* if async and byte count above threshold */
+    /* only 12-byte IV is supported in HW */
+    if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES &&
+                    sz >= WC_ASYNC_THRESH_AES_GCM && ivSz == GCM_NONCE_MID_SZ) {
+    #if defined(HAVE_CAVIUM)
+        #ifdef HAVE_CAVIUM_V
+        if (authInSz == 20) { /* Nitrox V GCM is only working with 20 byte AAD */
+            return NitroxAesGcmEncrypt(aes, out, in, sz,
+                (const byte*)aes->devKey, aes->keylen, iv, ivSz,
+                authTag, authTagSz, authIn, authInSz);
+        }
+        #endif
+    #elif defined(HAVE_INTEL_QA)
+        return IntelQaSymAesGcmEncrypt(&aes->asyncDev, out, in, sz,
+            (const byte*)aes->devKey, aes->keylen, iv, ivSz,
+            authTag, authTagSz, authIn, authInSz);
+    #else /* WOLFSSL_ASYNC_CRYPT_TEST */
+        if (wc_AsyncTestInit(&aes->asyncDev, ASYNC_TEST_AES_GCM_ENCRYPT)) {
+            WC_ASYNC_TEST* testDev = &aes->asyncDev.test;
+            testDev->aes.aes = aes;
+            testDev->aes.out = out;
+            testDev->aes.in = in;
+            testDev->aes.sz = sz;
+            testDev->aes.iv = iv;
+            testDev->aes.ivSz = ivSz;
+            testDev->aes.authTag = authTag;
+            testDev->aes.authTagSz = authTagSz;
+            testDev->aes.authIn = authIn;
+            testDev->aes.authInSz = authInSz;
+            return WC_PENDING_E;
+        }
+    #endif
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+#ifdef STM32_CRYPTO_AES_GCM
+    /* The STM standard peripheral library API's doesn't support partial blocks */
+    #ifdef STD_PERI_LIB
+    if (partial == 0)
+    #endif
+    {
+        return wc_AesGcmEncrypt_STM32(
+            aes, out, in, sz, iv, ivSz,
+            authTag, authTagSz, authIn, authInSz);
+    }
+#endif /* STM32_CRYPTO_AES_GCM */
+
+#ifdef WOLFSSL_AESNI
+    #ifdef HAVE_INTEL_AVX2
+    if (IS_INTEL_AVX2(intel_flags)) {
+        AES_GCM_encrypt_avx2(in, out, authIn, iv, authTag, sz, authInSz, ivSz,
+                                 authTagSz, (const byte*)aes->key, aes->rounds);
+        return 0;
+    }
+    else
+    #endif
+    #ifdef HAVE_INTEL_AVX1
+    if (IS_INTEL_AVX1(intel_flags)) {
+        AES_GCM_encrypt_avx1(in, out, authIn, iv, authTag, sz, authInSz, ivSz,
+                                 authTagSz, (const byte*)aes->key, aes->rounds);
+        return 0;
+    }
+    else
+    #endif
+    if (haveAESNI) {
+        AES_GCM_encrypt(in, out, authIn, iv, authTag, sz, authInSz, ivSz,
+                                 authTagSz, (const byte*)aes->key, aes->rounds);
+        return 0;
+    }
+    else
+#endif
+    {
+        return AES_GCM_encrypt_C(aes, out, in, sz, iv, ivSz, authTag, authTagSz,
+                                                              authIn, authInSz);
+    }
+}
+#endif
+
+
+
+/* AES GCM Decrypt */
+#if defined(HAVE_AES_DECRYPT) || defined(HAVE_AESGCM_DECRYPT)
+#ifdef FREESCALE_LTC_AES_GCM
+int  wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
+                   const byte* iv, word32 ivSz,
+                   const byte* authTag, word32 authTagSz,
+                   const byte* authIn, word32 authInSz)
+{
+    int ret;
+    word32 keySize;
+    status_t status;
+
+    /* argument checks */
+    /* If the sz is non-zero, both in and out must be set. If sz is 0,
+     * in and out are don't cares, as this is is the GMAC case. */
+    if (aes == NULL || iv == NULL || (sz != 0 && (in == NULL || out == NULL)) ||
+        authTag == NULL || authTagSz > AES_BLOCK_SIZE || authTagSz == 0 ||
+        ivSz == 0) {
+
+        return BAD_FUNC_ARG;
+    }
+
+    ret = wc_AesGetKeySize(aes, &keySize);
+    if (ret != 0) {
+        return ret;
+    }
+
+    status = LTC_AES_DecryptTagGcm(LTC_BASE, in, out, sz, iv, ivSz,
+        authIn, authInSz, (byte*)aes->key, keySize, authTag, authTagSz);
+
+    return (status == kStatus_Success) ? 0 : AES_GCM_AUTH_E;
+}
+
+#else
+
+#ifdef STM32_CRYPTO_AES_GCM
+/* this function supports inline decrypt */
+static int wc_AesGcmDecrypt_STM32(Aes* aes, byte* out,
+                                  const byte* in, word32 sz,
+                                  const byte* iv, word32 ivSz,
+                                  const byte* authTag, word32 authTagSz,
+                                  const byte* authIn, word32 authInSz)
+{
+    int ret;
+#ifdef WOLFSSL_STM32_CUBEMX
+    CRYP_HandleTypeDef hcryp;
+#else
+    word32 keyCopy[AES_256_KEY_SIZE/sizeof(word32)];
+#endif
+    word32 keySize;
+    int status = HAL_OK;
+    word32 blocks = sz / AES_BLOCK_SIZE;
+    word32 partial = sz % AES_BLOCK_SIZE;
+    byte tag[AES_BLOCK_SIZE];
+    byte partialBlock[AES_BLOCK_SIZE];
+    byte ctr[AES_BLOCK_SIZE];
+    byte* authInPadded = NULL;
+    int authPadSz;
+
+    ret = wc_AesGetKeySize(aes, &keySize);
+    if (ret != 0)
+        return ret;
+
+#ifdef WOLFSSL_STM32_CUBEMX
+    ret = wc_Stm32_Aes_Init(aes, &hcryp);
+    if (ret != 0)
+        return ret;
+#endif
+
+    ret = wolfSSL_CryptHwMutexLock();
+    if (ret != 0) {
+        return ret;
+    }
+
+    XMEMSET(ctr, 0, AES_BLOCK_SIZE);
+    if (ivSz == GCM_NONCE_MID_SZ) {
+        XMEMCPY(ctr, iv, ivSz);
+        ctr[AES_BLOCK_SIZE - 1] = 1;
+    }
+    else {
+        GHASH(aes, NULL, 0, iv, ivSz, ctr, AES_BLOCK_SIZE);
+    }
+    /* Hardware requires counter + 1 */
+    IncrementGcmCounter(ctr);
+
+    if (authInSz == 0 || (authInSz % AES_BLOCK_SIZE) != 0) {
+        /* Need to pad the AAD to a full block with zeros. */
+        authPadSz = ((authInSz / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE;
+        authInPadded = (byte*)XMALLOC(authPadSz, aes->heap,
+            DYNAMIC_TYPE_TMP_BUFFER);
+        if (authInPadded == NULL) {
+            wolfSSL_CryptHwMutexUnLock();
+            return MEMORY_E;
+        }
+        XMEMSET(authInPadded, 0, authPadSz);
+        XMEMCPY(authInPadded, authIn, authInSz);
+    } else {
+        authPadSz = authInSz;
+        authInPadded = (byte*)authIn;
+    }
+
+#ifdef WOLFSSL_STM32_CUBEMX
+    hcryp.Init.pInitVect = (STM_CRYPT_TYPE*)ctr;
+    hcryp.Init.Header = (STM_CRYPT_TYPE*)authInPadded;
+    hcryp.Init.HeaderSize = authInSz;
+
+#ifdef STM32_CRYPTO_AES_ONLY
+    /* Set the CRYP parameters */
+    hcryp.Init.ChainingMode  = CRYP_CHAINMODE_AES_GCM_GMAC;
+    hcryp.Init.OperatingMode = CRYP_ALGOMODE_DECRYPT;
+    hcryp.Init.GCMCMACPhase  = CRYP_INIT_PHASE;
+    HAL_CRYP_Init(&hcryp);
+
+    /* GCM init phase */
+    status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, 0, NULL, STM32_HAL_TIMEOUT);
+    if (status == HAL_OK) {
+        /* GCM header phase */
+        hcryp.Init.GCMCMACPhase = CRYP_HEADER_PHASE;
+        status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, 0, NULL, STM32_HAL_TIMEOUT);
+    }
+    if (status == HAL_OK) {
+        /* GCM payload phase - blocks */
+        hcryp.Init.GCMCMACPhase  = CRYP_PAYLOAD_PHASE;
+        if (blocks) {
+            status = HAL_CRYPEx_AES_Auth(&hcryp, (byte*)in,
+                (blocks * AES_BLOCK_SIZE), out, STM32_HAL_TIMEOUT);
+        }
+    }
+    if (status == HAL_OK && (partial != 0 || blocks == 0)) {
+        /* GCM payload phase - partial remainder */
+        XMEMSET(partialBlock, 0, sizeof(partialBlock));
+        XMEMCPY(partialBlock, in + (blocks * AES_BLOCK_SIZE), partial);
+        status = HAL_CRYPEx_AES_Auth(&hcryp, partialBlock, partial,
+            partialBlock, STM32_HAL_TIMEOUT);
+        XMEMCPY(out + (blocks * AES_BLOCK_SIZE), partialBlock, partial);
+    }
+    if (status == HAL_OK) {
+        /* GCM final phase */
+        hcryp.Init.GCMCMACPhase = CRYP_FINAL_PHASE;
+        status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, sz, tag, STM32_HAL_TIMEOUT);
+    }
+#elif defined(STM32_HAL_V2)
+    hcryp.Init.Algorithm = CRYP_AES_GCM;
+    ByteReverseWords((word32*)partialBlock, (word32*)ctr, AES_BLOCK_SIZE);
+    hcryp.Init.pInitVect = (STM_CRYPT_TYPE*)partialBlock;
+    HAL_CRYP_Init(&hcryp);
+
+    /* GCM payload phase - can handle partial blocks */
+    status = HAL_CRYP_Decrypt(&hcryp, (uint32_t*)in,
+        (blocks * AES_BLOCK_SIZE) + partial, (uint32_t*)out, STM32_HAL_TIMEOUT);
+    if (status == HAL_OK) {
+        /* Compute the authTag */
+        status = HAL_CRYPEx_AESGCM_GenerateAuthTAG(&hcryp, (uint32_t*)tag,
+            STM32_HAL_TIMEOUT);
+    }
+#else
+    HAL_CRYP_Init(&hcryp);
+    if (blocks) {
+        /* GCM payload phase - blocks */
+        status = HAL_CRYPEx_AESGCM_Decrypt(&hcryp, (byte*)in,
+            (blocks * AES_BLOCK_SIZE), out, STM32_HAL_TIMEOUT);
+    }
+    if (status == HAL_OK && (partial != 0 || blocks == 0)) {
+        /* GCM payload phase - partial remainder */
+        XMEMSET(partialBlock, 0, sizeof(partialBlock));
+        XMEMCPY(partialBlock, in + (blocks * AES_BLOCK_SIZE), partial);
+        status = HAL_CRYPEx_AESGCM_Decrypt(&hcryp, partialBlock, partial,
+            partialBlock, STM32_HAL_TIMEOUT);
+        XMEMCPY(out + (blocks * AES_BLOCK_SIZE), partialBlock, partial);
+    }
+    if (status == HAL_OK) {
+        /* Compute the authTag */
+        status = HAL_CRYPEx_AESGCM_Finish(&hcryp, sz, tag, STM32_HAL_TIMEOUT);
+    }
+#endif
+
+    if (status != HAL_OK)
+        ret = AES_GCM_AUTH_E;
+
+    HAL_CRYP_DeInit(&hcryp);
+
+#else /* STD_PERI_LIB */
+    ByteReverseWords(keyCopy, (word32*)aes->key, aes->keylen);
+
+    /* Input size and auth size need to be the actual sizes, even though
+     * they are not block aligned, because this length (in bits) is used
+     * in the final GHASH. */
+    status = CRYP_AES_GCM(MODE_DECRYPT, (uint8_t*)ctr,
+                         (uint8_t*)keyCopy,      keySize * 8,
+                         (uint8_t*)in,           sz,
+                         (uint8_t*)authInPadded, authInSz,
+                         (uint8_t*)out,          tag);
+    if (status != SUCCESS)
+        ret = AES_GCM_AUTH_E;
+#endif /* WOLFSSL_STM32_CUBEMX */
+
+    /* STM32 GCM hardware only supports IV of 12 bytes, so use software for auth */
+    if (sz == 0 || ivSz != GCM_NONCE_MID_SZ) {
+        DecrementGcmCounter(ctr); /* hardware requires +1, so subtract it */
+        GHASH(aes, authIn, authInSz, in, sz, tag, sizeof(tag));
+        wc_AesEncrypt(aes, ctr, partialBlock);
+        xorbuf(tag, partialBlock, sizeof(tag));
+    }
+
+    if (ConstantCompare(authTag, tag, authTagSz) != 0) {
+        ret = AES_GCM_AUTH_E;
+    }
+
+    /* Free memory if not a multiple of AES_BLOCK_SZ */
+    if (authInPadded != authIn) {
+        XFREE(authInPadded, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+
+    wolfSSL_CryptHwMutexUnLock();
+
+    return ret;
+}
+
+#endif /* STM32_CRYPTO_AES_GCM */
+
+#ifdef WOLFSSL_AESNI
+int AES_GCM_decrypt_C(Aes* aes, byte* out, const byte* in, word32 sz,
+                      const byte* iv, word32 ivSz,
+                      const byte* authTag, word32 authTagSz,
+                      const byte* authIn, word32 authInSz);
+#else
+static
+#endif
+int AES_GCM_decrypt_C(Aes* aes, byte* out, const byte* in, word32 sz,
+                      const byte* iv, word32 ivSz,
+                      const byte* authTag, word32 authTagSz,
+                      const byte* authIn, word32 authInSz)
+{
+    int ret = 0;
+    word32 blocks = sz / AES_BLOCK_SIZE;
+    word32 partial = sz % AES_BLOCK_SIZE;
+    const byte* c = in;
+    byte* p = out;
+    byte counter[AES_BLOCK_SIZE];
+    byte initialCounter[AES_BLOCK_SIZE];
+    byte *ctr;
+    byte scratch[AES_BLOCK_SIZE];
+    byte Tprime[AES_BLOCK_SIZE];
+    byte EKY0[AES_BLOCK_SIZE];
+#ifdef OPENSSL_EXTRA
+    word32 aadTemp;
+#endif
+    ctr = counter;
+    XMEMSET(initialCounter, 0, AES_BLOCK_SIZE);
+    if (ivSz == GCM_NONCE_MID_SZ) {
+        XMEMCPY(initialCounter, iv, ivSz);
+        initialCounter[AES_BLOCK_SIZE - 1] = 1;
+    }
+    else {
+#ifdef OPENSSL_EXTRA
+        aadTemp = aes->aadLen;
+        aes->aadLen = 0;
+#endif
+        GHASH(aes, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE);
+#ifdef OPENSSL_EXTRA
+        aes->aadLen = aadTemp;
+#endif
+    }
+    XMEMCPY(ctr, initialCounter, AES_BLOCK_SIZE);
+
+    /* Calc the authTag again using the received auth data and the cipher text */
+    GHASH(aes, authIn, authInSz, in, sz, Tprime, sizeof(Tprime));
+    wc_AesEncrypt(aes, ctr, EKY0);
+    xorbuf(Tprime, EKY0, sizeof(Tprime));
+
+#ifdef OPENSSL_EXTRA
+    if (!out) {
+        /* authenticated, non-confidential data */
+        /* store AAD size for next call */
+        aes->aadLen = authInSz;
+    }
+#endif
+    if (ConstantCompare(authTag, Tprime, authTagSz) != 0) {
+        return AES_GCM_AUTH_E;
+    }
+
+#if defined(WOLFSSL_PIC32MZ_CRYPT)
+    if (blocks) {
+        /* use initial IV for HW, but don't use it below */
+        XMEMCPY(aes->reg, ctr, AES_BLOCK_SIZE);
+
+        ret = wc_Pic32AesCrypt(
+            aes->key, aes->keylen, aes->reg, AES_BLOCK_SIZE,
+            out, in, (blocks * AES_BLOCK_SIZE),
+            PIC32_DECRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_AES_GCM);
+        if (ret != 0)
+            return ret;
+    }
+    /* process remainder using partial handling */
+#endif
+
+#if defined(HAVE_AES_ECB) && !defined(WOLFSSL_PIC32MZ_CRYPT)
+    /* some hardware acceleration can gain performance from doing AES encryption
+     * of the whole buffer at once */
+    if (c != p && blocks > 0) { /* can not handle inline decryption */
+        while (blocks--) {
+            IncrementGcmCounter(ctr);
+            XMEMCPY(p, ctr, AES_BLOCK_SIZE);
+            p += AES_BLOCK_SIZE;
+        }
+
+        /* reset number of blocks and then do encryption */
+        blocks = sz / AES_BLOCK_SIZE;
+
+        wc_AesEcbEncrypt(aes, out, out, AES_BLOCK_SIZE * blocks);
+        xorbuf(out, c, AES_BLOCK_SIZE * blocks);
+        c += AES_BLOCK_SIZE * blocks;
+    }
+    else
+#endif /* HAVE_AES_ECB && !PIC32MZ */
+    while (blocks--) {
+        IncrementGcmCounter(ctr);
+    #if !defined(WOLFSSL_PIC32MZ_CRYPT)
+        wc_AesEncrypt(aes, ctr, scratch);
+        xorbuf(scratch, c, AES_BLOCK_SIZE);
+        XMEMCPY(p, scratch, AES_BLOCK_SIZE);
+    #endif
+        p += AES_BLOCK_SIZE;
+        c += AES_BLOCK_SIZE;
+    }
+
+    if (partial != 0) {
+        IncrementGcmCounter(ctr);
+        wc_AesEncrypt(aes, ctr, scratch);
+        xorbuf(scratch, c, partial);
+        XMEMCPY(p, scratch, partial);
+    }
+
+    return ret;
+}
+
+/* Software AES - GCM Decrypt */
+int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
+                     const byte* iv, word32 ivSz,
+                     const byte* authTag, word32 authTagSz,
+                     const byte* authIn, word32 authInSz)
+{
+#ifdef WOLFSSL_AESNI
+    int res = AES_GCM_AUTH_E;
+#endif
+
+    /* argument checks */
+    /* If the sz is non-zero, both in and out must be set. If sz is 0,
+     * in and out are don't cares, as this is is the GMAC case. */
+    if (aes == NULL || iv == NULL || (sz != 0 && (in == NULL || out == NULL)) ||
+        authTag == NULL || authTagSz > AES_BLOCK_SIZE || authTagSz == 0 ||
+        ivSz == 0) {
+
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef WOLF_CRYPTO_CB
+    if (aes->devId != INVALID_DEVID) {
+        int ret = wc_CryptoCb_AesGcmDecrypt(aes, out, in, sz, iv, ivSz,
+            authTag, authTagSz, authIn, authInSz);
+        if (ret != CRYPTOCB_UNAVAILABLE)
+            return ret;
+        /* fall-through when unavailable */
+    }
+#endif
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES)
+    /* if async and byte count above threshold */
+    /* only 12-byte IV is supported in HW */
+    if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES &&
+                    sz >= WC_ASYNC_THRESH_AES_GCM && ivSz == GCM_NONCE_MID_SZ) {
+    #if defined(HAVE_CAVIUM)
+        #ifdef HAVE_CAVIUM_V
+        if (authInSz == 20) { /* Nitrox V GCM is only working with 20 byte AAD */
+            return NitroxAesGcmDecrypt(aes, out, in, sz,
+                (const byte*)aes->devKey, aes->keylen, iv, ivSz,
+                authTag, authTagSz, authIn, authInSz);
+        }
+        #endif
+    #elif defined(HAVE_INTEL_QA)
+        return IntelQaSymAesGcmDecrypt(&aes->asyncDev, out, in, sz,
+            (const byte*)aes->devKey, aes->keylen, iv, ivSz,
+            authTag, authTagSz, authIn, authInSz);
+    #else /* WOLFSSL_ASYNC_CRYPT_TEST */
+        if (wc_AsyncTestInit(&aes->asyncDev, ASYNC_TEST_AES_GCM_DECRYPT)) {
+            WC_ASYNC_TEST* testDev = &aes->asyncDev.test;
+            testDev->aes.aes = aes;
+            testDev->aes.out = out;
+            testDev->aes.in = in;
+            testDev->aes.sz = sz;
+            testDev->aes.iv = iv;
+            testDev->aes.ivSz = ivSz;
+            testDev->aes.authTag = (byte*)authTag;
+            testDev->aes.authTagSz = authTagSz;
+            testDev->aes.authIn = authIn;
+            testDev->aes.authInSz = authInSz;
+            return WC_PENDING_E;
+        }
+    #endif
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+#ifdef STM32_CRYPTO_AES_GCM
+    /* The STM standard peripheral library API's doesn't support partial blocks */
+    #ifdef STD_PERI_LIB
+    if (partial == 0)
+    #endif
+    {
+        return wc_AesGcmDecrypt_STM32(
+            aes, out, in, sz, iv, ivSz,
+            authTag, authTagSz, authIn, authInSz);
+    }
+#endif /* STM32_CRYPTO_AES_GCM */
+
+#ifdef WOLFSSL_AESNI
+    #ifdef HAVE_INTEL_AVX2
+    if (IS_INTEL_AVX2(intel_flags)) {
+        AES_GCM_decrypt_avx2(in, out, authIn, iv, authTag, sz, authInSz, ivSz,
+                                 authTagSz, (byte*)aes->key, aes->rounds, &res);
+        if (res == 0)
+            return AES_GCM_AUTH_E;
+        return 0;
+    }
+    else
+    #endif
+    #ifdef HAVE_INTEL_AVX1
+    if (IS_INTEL_AVX1(intel_flags)) {
+        AES_GCM_decrypt_avx1(in, out, authIn, iv, authTag, sz, authInSz, ivSz,
+                                 authTagSz, (byte*)aes->key, aes->rounds, &res);
+        if (res == 0)
+            return AES_GCM_AUTH_E;
+        return 0;
+    }
+    else
+    #endif
+    if (haveAESNI) {
+        AES_GCM_decrypt(in, out, authIn, iv, authTag, sz, authInSz, ivSz,
+                                 authTagSz, (byte*)aes->key, aes->rounds, &res);
+        if (res == 0)
+            return AES_GCM_AUTH_E;
+        return 0;
+    }
+    else
+#endif
+    {
+        return AES_GCM_decrypt_C(aes, out, in, sz, iv, ivSz, authTag, authTagSz,
+                                                              authIn, authInSz);
+    }
+}
+#endif
+#endif /* HAVE_AES_DECRYPT || HAVE_AESGCM_DECRYPT */
+#endif /* WOLFSSL_XILINX_CRYPT */
+#endif /* end of block for AESGCM implementation selection */
+
+
+/* Common to all, abstract functions that build off of lower level AESGCM
+ * functions */
+#ifndef WC_NO_RNG
+
+int wc_AesGcmSetExtIV(Aes* aes, const byte* iv, word32 ivSz)
+{
+    int ret = 0;
+
+    if (aes == NULL || iv == NULL ||
+        (ivSz != GCM_NONCE_MIN_SZ && ivSz != GCM_NONCE_MID_SZ &&
+         ivSz != GCM_NONCE_MAX_SZ)) {
+
+        ret = BAD_FUNC_ARG;
+    }
+
+    if (ret == 0) {
+        XMEMCPY((byte*)aes->reg, iv, ivSz);
+
+        /* If the IV is 96, allow for a 2^64 invocation counter.
+         * For any other size for the nonce, limit the invocation
+         * counter to 32-bits. (SP 800-38D 8.3) */
+        aes->invokeCtr[0] = 0;
+        aes->invokeCtr[1] = (ivSz == GCM_NONCE_MID_SZ) ? 0 : 0xFFFFFFFF;
+        aes->nonceSz = ivSz;
+    }
+
+    return ret;
+}
+
+
+int wc_AesGcmSetIV(Aes* aes, word32 ivSz,
+                   const byte* ivFixed, word32 ivFixedSz,
+                   WC_RNG* rng)
+{
+    int ret = 0;
+
+    if (aes == NULL || rng == NULL ||
+        (ivSz != GCM_NONCE_MIN_SZ && ivSz != GCM_NONCE_MID_SZ &&
+         ivSz != GCM_NONCE_MAX_SZ) ||
+        (ivFixed == NULL && ivFixedSz != 0) ||
+        (ivFixed != NULL && ivFixedSz != AES_IV_FIXED_SZ)) {
+
+        ret = BAD_FUNC_ARG;
+    }
+
+    if (ret == 0) {
+        byte* iv = (byte*)aes->reg;
+
+        if (ivFixedSz)
+            XMEMCPY(iv, ivFixed, ivFixedSz);
+
+        ret = wc_RNG_GenerateBlock(rng, iv + ivFixedSz, ivSz - ivFixedSz);
+    }
+
+    if (ret == 0) {
+        /* If the IV is 96, allow for a 2^64 invocation counter.
+         * For any other size for the nonce, limit the invocation
+         * counter to 32-bits. (SP 800-38D 8.3) */
+        aes->invokeCtr[0] = 0;
+        aes->invokeCtr[1] = (ivSz == GCM_NONCE_MID_SZ) ? 0 : 0xFFFFFFFF;
+        aes->nonceSz = ivSz;
+    }
+
+    return ret;
+}
+
+
+int wc_AesGcmEncrypt_ex(Aes* aes, byte* out, const byte* in, word32 sz,
+                        byte* ivOut, word32 ivOutSz,
+                        byte* authTag, word32 authTagSz,
+                        const byte* authIn, word32 authInSz)
+{
+    int ret = 0;
+
+    if (aes == NULL || (sz != 0 && (in == NULL || out == NULL)) ||
+        ivOut == NULL || ivOutSz != aes->nonceSz ||
+        (authIn == NULL && authInSz != 0)) {
+
+        ret = BAD_FUNC_ARG;
+    }
+
+    if (ret == 0) {
+        aes->invokeCtr[0]++;
+        if (aes->invokeCtr[0] == 0) {
+            aes->invokeCtr[1]++;
+            if (aes->invokeCtr[1] == 0)
+                ret = AES_GCM_OVERFLOW_E;
+        }
+    }
+
+    if (ret == 0) {
+        XMEMCPY(ivOut, aes->reg, ivOutSz);
+        ret = wc_AesGcmEncrypt(aes, out, in, sz,
+                               (byte*)aes->reg, ivOutSz,
+                               authTag, authTagSz,
+                               authIn, authInSz);
+        if (ret == 0)
+            IncCtr((byte*)aes->reg, ivOutSz);
+    }
+
+    return ret;
+}
+
+int wc_Gmac(const byte* key, word32 keySz, byte* iv, word32 ivSz,
+            const byte* authIn, word32 authInSz,
+            byte* authTag, word32 authTagSz, WC_RNG* rng)
+{
+    Aes aes;
+    int ret;
+
+    if (key == NULL || iv == NULL || (authIn == NULL && authInSz != 0) ||
+        authTag == NULL || authTagSz == 0 || rng == NULL) {
+
+        return BAD_FUNC_ARG;
+    }
+
+    ret = wc_AesInit(&aes, NULL, INVALID_DEVID);
+    if (ret == 0) {
+        ret = wc_AesGcmSetKey(&aes, key, keySz);
+        if (ret == 0)
+            ret = wc_AesGcmSetIV(&aes, ivSz, NULL, 0, rng);
+        if (ret == 0)
+            ret = wc_AesGcmEncrypt_ex(&aes, NULL, NULL, 0, iv, ivSz,
+                                  authTag, authTagSz, authIn, authInSz);
+        wc_AesFree(&aes);
+    }
+    ForceZero(&aes, sizeof(aes));
+
+    return ret;
+}
+
+int wc_GmacVerify(const byte* key, word32 keySz,
+                  const byte* iv, word32 ivSz,
+                  const byte* authIn, word32 authInSz,
+                  const byte* authTag, word32 authTagSz)
+{
+    int ret;
+#ifndef NO_AES_DECRYPT
+    Aes aes;
+
+    if (key == NULL || iv == NULL || (authIn == NULL && authInSz != 0) ||
+        authTag == NULL || authTagSz == 0 || authTagSz > AES_BLOCK_SIZE) {
+
+        return BAD_FUNC_ARG;
+    }
+
+    ret = wc_AesInit(&aes, NULL, INVALID_DEVID);
+    if (ret == 0) {
+        ret = wc_AesGcmSetKey(&aes, key, keySz);
+        if (ret == 0)
+            ret = wc_AesGcmDecrypt(&aes, NULL, NULL, 0, iv, ivSz,
+                                  authTag, authTagSz, authIn, authInSz);
+        wc_AesFree(&aes);
+    }
+    ForceZero(&aes, sizeof(aes));
+#else
+    (void)key;
+    (void)keySz;
+    (void)iv;
+    (void)ivSz;
+    (void)authIn;
+    (void)authInSz;
+    (void)authTag;
+    (void)authTagSz;
+    ret = NOT_COMPILED_IN;
+#endif
+    return ret;
+}
+
+#endif /* WC_NO_RNG */
+
+
+WOLFSSL_API int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len)
+{
+    if (gmac == NULL || key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+    return wc_AesGcmSetKey(&gmac->aes, key, len);
+}
+
+
+WOLFSSL_API int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz,
+                              const byte* authIn, word32 authInSz,
+                              byte* authTag, word32 authTagSz)
+{
+    return wc_AesGcmEncrypt(&gmac->aes, NULL, NULL, 0, iv, ivSz,
+                                         authTag, authTagSz, authIn, authInSz);
+}
+
+#endif /* HAVE_AESGCM */
+
+
+#ifdef HAVE_AESCCM
+
+int wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz)
+{
+    if (!((keySz == 16) || (keySz == 24) || (keySz == 32)))
+        return BAD_FUNC_ARG;
+
+    return wc_AesSetKey(aes, key, keySz, NULL, AES_ENCRYPTION);
+}
+
+#ifdef WOLFSSL_ARMASM
+    /* implementation located in wolfcrypt/src/port/arm/armv8-aes.c */
+
+#elif defined(HAVE_COLDFIRE_SEC)
+    #error "Coldfire SEC doesn't currently support AES-CCM mode"
+
+#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
+    /* implemented in wolfcrypt/src/port/caam_aes.c */
+
+#elif defined(FREESCALE_LTC)
+
+/* return 0 on success */
+int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
+                   const byte* nonce, word32 nonceSz,
+                   byte* authTag, word32 authTagSz,
+                   const byte* authIn, word32 authInSz)
+{
+    byte *key;
+    uint32_t keySize;
+    status_t status;
+
+    /* sanity check on arguments */
+    if (aes == NULL || out == NULL || in == NULL || nonce == NULL
+            || authTag == NULL || nonceSz < 7 || nonceSz > 13)
+        return BAD_FUNC_ARG;
+
+    key = (byte*)aes->key;
+
+    status = wc_AesGetKeySize(aes, &keySize);
+    if (status != 0) {
+        return status;
+    }
+
+    status = LTC_AES_EncryptTagCcm(LTC_BASE, in, out, inSz,
+        nonce, nonceSz, authIn, authInSz, key, keySize, authTag, authTagSz);
+
+    return (kStatus_Success == status) ? 0 : BAD_FUNC_ARG;
+}
+
+#ifdef HAVE_AES_DECRYPT
+int  wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
+                   const byte* nonce, word32 nonceSz,
+                   const byte* authTag, word32 authTagSz,
+                   const byte* authIn, word32 authInSz)
+{
+    byte *key;
+    uint32_t keySize;
+    status_t status;
+
+    /* sanity check on arguments */
+    if (aes == NULL || out == NULL || in == NULL || nonce == NULL
+            || authTag == NULL || nonceSz < 7 || nonceSz > 13)
+        return BAD_FUNC_ARG;
+
+    key = (byte*)aes->key;
+
+    status = wc_AesGetKeySize(aes, &keySize);
+    if (status != 0) {
+        return status;
+    }
+
+    status = LTC_AES_DecryptTagCcm(LTC_BASE, in, out, inSz,
+        nonce, nonceSz, authIn, authInSz, key, keySize, authTag, authTagSz);
+
+    if (status == kStatus_Success) {
+        return 0;
+    }
+    else {
+        XMEMSET(out, 0, inSz);
+        return AES_CCM_AUTH_E;
+    }
+}
+#endif /* HAVE_AES_DECRYPT */
+
+#else
+
+/* Software CCM */
+static void roll_x(Aes* aes, const byte* in, word32 inSz, byte* out)
+{
+    /* process the bulk of the data */
+    while (inSz >= AES_BLOCK_SIZE) {
+        xorbuf(out, in, AES_BLOCK_SIZE);
+        in += AES_BLOCK_SIZE;
+        inSz -= AES_BLOCK_SIZE;
+
+        wc_AesEncrypt(aes, out, out);
+    }
+
+    /* process remainder of the data */
+    if (inSz > 0) {
+        xorbuf(out, in, inSz);
+        wc_AesEncrypt(aes, out, out);
+    }
+}
+
+static void roll_auth(Aes* aes, const byte* in, word32 inSz, byte* out)
+{
+    word32 authLenSz;
+    word32 remainder;
+
+    /* encode the length in */
+    if (inSz <= 0xFEFF) {
+        authLenSz = 2;
+        out[0] ^= ((inSz & 0xFF00) >> 8);
+        out[1] ^=  (inSz & 0x00FF);
+    }
+    else if (inSz <= 0xFFFFFFFF) {
+        authLenSz = 6;
+        out[0] ^= 0xFF; out[1] ^= 0xFE;
+        out[2] ^= ((inSz & 0xFF000000) >> 24);
+        out[3] ^= ((inSz & 0x00FF0000) >> 16);
+        out[4] ^= ((inSz & 0x0000FF00) >>  8);
+        out[5] ^=  (inSz & 0x000000FF);
+    }
+    /* Note, the protocol handles auth data up to 2^64, but we are
+     * using 32-bit sizes right now, so the bigger data isn't handled
+     * else if (inSz <= 0xFFFFFFFFFFFFFFFF) {} */
+    else
+        return;
+
+    /* start fill out the rest of the first block */
+    remainder = AES_BLOCK_SIZE - authLenSz;
+    if (inSz >= remainder) {
+        /* plenty of bulk data to fill the remainder of this block */
+        xorbuf(out + authLenSz, in, remainder);
+        inSz -= remainder;
+        in += remainder;
+    }
+    else {
+        /* not enough bulk data, copy what is available, and pad zero */
+        xorbuf(out + authLenSz, in, inSz);
+        inSz = 0;
+    }
+    wc_AesEncrypt(aes, out, out);
+
+    if (inSz > 0)
+        roll_x(aes, in, inSz, out);
+}
+
+
+static WC_INLINE void AesCcmCtrInc(byte* B, word32 lenSz)
+{
+    word32 i;
+
+    for (i = 0; i < lenSz; i++) {
+        if (++B[AES_BLOCK_SIZE - 1 - i] != 0) return;
+    }
+}
+
+#ifdef WOLFSSL_AESNI
+static WC_INLINE void AesCcmCtrIncSet4(byte* B, word32 lenSz)
+{
+    word32 i;
+
+    /* B+1 = B */
+    XMEMCPY(B + AES_BLOCK_SIZE * 1, B, AES_BLOCK_SIZE);
+    /* B+2,B+3 = B,B+1 */
+    XMEMCPY(B + AES_BLOCK_SIZE * 2, B, AES_BLOCK_SIZE * 2);
+
+    for (i = 0; i < lenSz; i++) {
+        if (++B[AES_BLOCK_SIZE * 1 - 1 - i] != 0) break;
+    }
+    B[AES_BLOCK_SIZE * 2 - 1] += 2;
+    if (B[AES_BLOCK_SIZE * 2 - 1] < 2) {
+        for (i = 1; i < lenSz; i++) {
+            if (++B[AES_BLOCK_SIZE * 2 - 1 - i] != 0) break;
+        }
+    }
+    B[AES_BLOCK_SIZE * 3 - 1] += 3;
+    if (B[AES_BLOCK_SIZE * 3 - 1] < 3) {
+        for (i = 1; i < lenSz; i++) {
+            if (++B[AES_BLOCK_SIZE * 3 - 1 - i] != 0) break;
+        }
+    }
+}
+
+static WC_INLINE void AesCcmCtrInc4(byte* B, word32 lenSz)
+{
+    word32 i;
+
+    B[AES_BLOCK_SIZE - 1] += 4;
+    if (B[AES_BLOCK_SIZE - 1] < 4) {
+        for (i = 1; i < lenSz; i++) {
+            if (++B[AES_BLOCK_SIZE - 1 - i] != 0) break;
+        }
+    }
+}
+#endif
+
+/* Software AES - CCM Encrypt */
+/* return 0 on success */
+int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
+                   const byte* nonce, word32 nonceSz,
+                   byte* authTag, word32 authTagSz,
+                   const byte* authIn, word32 authInSz)
+{
+#ifndef WOLFSSL_AESNI
+    byte A[AES_BLOCK_SIZE];
+    byte B[AES_BLOCK_SIZE];
+#else
+    ALIGN128 byte A[AES_BLOCK_SIZE * 4];
+    ALIGN128 byte B[AES_BLOCK_SIZE * 4];
+#endif
+    byte lenSz;
+    word32 i;
+    byte mask = 0xFF;
+    const word32 wordSz = (word32)sizeof(word32);
+
+    /* sanity check on arguments */
+    if (aes == NULL || out == NULL || in == NULL || nonce == NULL
+            || authTag == NULL || nonceSz < 7 || nonceSz > 13 ||
+            authTagSz > AES_BLOCK_SIZE)
+        return BAD_FUNC_ARG;
+
+    XMEMSET(A, 0, sizeof(A));
+    XMEMCPY(B+1, nonce, nonceSz);
+    lenSz = AES_BLOCK_SIZE - 1 - (byte)nonceSz;
+    B[0] = (authInSz > 0 ? 64 : 0)
+         + (8 * (((byte)authTagSz - 2) / 2))
+         + (lenSz - 1);
+    for (i = 0; i < lenSz; i++) {
+        if (mask && i >= wordSz)
+            mask = 0x00;
+        B[AES_BLOCK_SIZE - 1 - i] = (inSz >> ((8 * i) & mask)) & mask;
+    }
+
+    wc_AesEncrypt(aes, B, A);
+
+    if (authInSz > 0)
+        roll_auth(aes, authIn, authInSz, A);
+    if (inSz > 0)
+        roll_x(aes, in, inSz, A);
+    XMEMCPY(authTag, A, authTagSz);
+
+    B[0] = lenSz - 1;
+    for (i = 0; i < lenSz; i++)
+        B[AES_BLOCK_SIZE - 1 - i] = 0;
+    wc_AesEncrypt(aes, B, A);
+    xorbuf(authTag, A, authTagSz);
+
+    B[15] = 1;
+#ifdef WOLFSSL_AESNI
+    if (haveAESNI && aes->use_aesni) {
+        while (inSz >= AES_BLOCK_SIZE * 4) {
+            AesCcmCtrIncSet4(B, lenSz);
+
+            AES_ECB_encrypt(B, A, AES_BLOCK_SIZE * 4, (byte*)aes->key,
+                            aes->rounds);
+            xorbuf(A, in, AES_BLOCK_SIZE * 4);
+            XMEMCPY(out, A, AES_BLOCK_SIZE * 4);
+
+            inSz -= AES_BLOCK_SIZE * 4;
+            in += AES_BLOCK_SIZE * 4;
+            out += AES_BLOCK_SIZE * 4;
+
+            if (inSz < AES_BLOCK_SIZE * 4) {
+                AesCcmCtrInc4(B, lenSz);
+            }
+        }
+    }
+#endif
+    while (inSz >= AES_BLOCK_SIZE) {
+        wc_AesEncrypt(aes, B, A);
+        xorbuf(A, in, AES_BLOCK_SIZE);
+        XMEMCPY(out, A, AES_BLOCK_SIZE);
+
+        AesCcmCtrInc(B, lenSz);
+        inSz -= AES_BLOCK_SIZE;
+        in += AES_BLOCK_SIZE;
+        out += AES_BLOCK_SIZE;
+    }
+    if (inSz > 0) {
+        wc_AesEncrypt(aes, B, A);
+        xorbuf(A, in, inSz);
+        XMEMCPY(out, A, inSz);
+    }
+
+    ForceZero(A, AES_BLOCK_SIZE);
+    ForceZero(B, AES_BLOCK_SIZE);
+
+    return 0;
+}
+
+#ifdef HAVE_AES_DECRYPT
+/* Software AES - CCM Decrypt */
+int  wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
+                   const byte* nonce, word32 nonceSz,
+                   const byte* authTag, word32 authTagSz,
+                   const byte* authIn, word32 authInSz)
+{
+#ifndef WOLFSSL_AESNI
+    byte A[AES_BLOCK_SIZE];
+    byte B[AES_BLOCK_SIZE];
+#else
+    ALIGN128 byte B[AES_BLOCK_SIZE * 4];
+    ALIGN128 byte A[AES_BLOCK_SIZE * 4];
+#endif
+    byte* o;
+    byte lenSz;
+    word32 i, oSz;
+    int result = 0;
+    byte mask = 0xFF;
+    const word32 wordSz = (word32)sizeof(word32);
+
+    /* sanity check on arguments */
+    if (aes == NULL || out == NULL || in == NULL || nonce == NULL
+            || authTag == NULL || nonceSz < 7 || nonceSz > 13 ||
+            authTagSz > AES_BLOCK_SIZE)
+        return BAD_FUNC_ARG;
+
+    o = out;
+    oSz = inSz;
+    XMEMCPY(B+1, nonce, nonceSz);
+    lenSz = AES_BLOCK_SIZE - 1 - (byte)nonceSz;
+
+    B[0] = lenSz - 1;
+    for (i = 0; i < lenSz; i++)
+        B[AES_BLOCK_SIZE - 1 - i] = 0;
+    B[15] = 1;
+
+#ifdef WOLFSSL_AESNI
+    if (haveAESNI && aes->use_aesni) {
+        while (oSz >= AES_BLOCK_SIZE * 4) {
+            AesCcmCtrIncSet4(B, lenSz);
+
+            AES_ECB_encrypt(B, A, AES_BLOCK_SIZE * 4, (byte*)aes->key,
+                            aes->rounds);
+            xorbuf(A, in, AES_BLOCK_SIZE * 4);
+            XMEMCPY(o, A, AES_BLOCK_SIZE * 4);
+
+            oSz -= AES_BLOCK_SIZE * 4;
+            in += AES_BLOCK_SIZE * 4;
+            o += AES_BLOCK_SIZE * 4;
+
+            if (oSz < AES_BLOCK_SIZE * 4) {
+                AesCcmCtrInc4(B, lenSz);
+            }
+        }
+    }
+#endif
+    while (oSz >= AES_BLOCK_SIZE) {
+        wc_AesEncrypt(aes, B, A);
+        xorbuf(A, in, AES_BLOCK_SIZE);
+        XMEMCPY(o, A, AES_BLOCK_SIZE);
+
+        AesCcmCtrInc(B, lenSz);
+        oSz -= AES_BLOCK_SIZE;
+        in += AES_BLOCK_SIZE;
+        o += AES_BLOCK_SIZE;
+    }
+    if (inSz > 0) {
+        wc_AesEncrypt(aes, B, A);
+        xorbuf(A, in, oSz);
+        XMEMCPY(o, A, oSz);
+    }
+
+    for (i = 0; i < lenSz; i++)
+        B[AES_BLOCK_SIZE - 1 - i] = 0;
+    wc_AesEncrypt(aes, B, A);
+
+    o = out;
+    oSz = inSz;
+
+    B[0] = (authInSz > 0 ? 64 : 0)
+         + (8 * (((byte)authTagSz - 2) / 2))
+         + (lenSz - 1);
+    for (i = 0; i < lenSz; i++) {
+        if (mask && i >= wordSz)
+            mask = 0x00;
+        B[AES_BLOCK_SIZE - 1 - i] = (inSz >> ((8 * i) & mask)) & mask;
+    }
+
+    wc_AesEncrypt(aes, B, A);
+
+    if (authInSz > 0)
+        roll_auth(aes, authIn, authInSz, A);
+    if (inSz > 0)
+        roll_x(aes, o, oSz, A);
+
+    B[0] = lenSz - 1;
+    for (i = 0; i < lenSz; i++)
+        B[AES_BLOCK_SIZE - 1 - i] = 0;
+    wc_AesEncrypt(aes, B, B);
+    xorbuf(A, B, authTagSz);
+
+    if (ConstantCompare(A, authTag, authTagSz) != 0) {
+        /* If the authTag check fails, don't keep the decrypted data.
+         * Unfortunately, you need the decrypted data to calculate the
+         * check value. */
+        XMEMSET(out, 0, inSz);
+        result = AES_CCM_AUTH_E;
+    }
+
+    ForceZero(A, AES_BLOCK_SIZE);
+    ForceZero(B, AES_BLOCK_SIZE);
+    o = NULL;
+
+    return result;
+}
+
+#endif /* HAVE_AES_DECRYPT */
+#endif /* software CCM */
+
+/* abstract functions that call lower level AESCCM functions */
+#ifndef WC_NO_RNG
+
+int wc_AesCcmSetNonce(Aes* aes, const byte* nonce, word32 nonceSz)
+{
+    int ret = 0;
+
+    if (aes == NULL || nonce == NULL ||
+        nonceSz < CCM_NONCE_MIN_SZ || nonceSz > CCM_NONCE_MAX_SZ) {
+
+        ret = BAD_FUNC_ARG;
+    }
+
+    if (ret == 0) {
+        XMEMCPY(aes->reg, nonce, nonceSz);
+        aes->nonceSz = nonceSz;
+
+        /* Invocation counter should be 2^61 */
+        aes->invokeCtr[0] = 0;
+        aes->invokeCtr[1] = 0xE0000000;
+    }
+
+    return ret;
+}
+
+
+int wc_AesCcmEncrypt_ex(Aes* aes, byte* out, const byte* in, word32 sz,
+                        byte* ivOut, word32 ivOutSz,
+                        byte* authTag, word32 authTagSz,
+                        const byte* authIn, word32 authInSz)
+{
+    int ret = 0;
+
+    if (aes == NULL || out == NULL ||
+        (in == NULL && sz != 0) ||
+        ivOut == NULL ||
+        (authIn == NULL && authInSz != 0) ||
+        (ivOutSz != aes->nonceSz)) {
+
+        ret = BAD_FUNC_ARG;
+    }
+
+    if (ret == 0) {
+        aes->invokeCtr[0]++;
+        if (aes->invokeCtr[0] == 0) {
+            aes->invokeCtr[1]++;
+            if (aes->invokeCtr[1] == 0)
+                ret = AES_CCM_OVERFLOW_E;
+        }
+    }
+
+    if (ret == 0) {
+        ret = wc_AesCcmEncrypt(aes, out, in, sz,
+                               (byte*)aes->reg, aes->nonceSz,
+                               authTag, authTagSz,
+                               authIn, authInSz);
+        if (ret == 0) {
+            XMEMCPY(ivOut, aes->reg, aes->nonceSz);
+            IncCtr((byte*)aes->reg, aes->nonceSz);
+        }
+    }
+
+    return ret;
+}
+
+#endif /* WC_NO_RNG */
+
+#endif /* HAVE_AESCCM */
+
+
+/* Initialize Aes for use with async hardware */
+int wc_AesInit(Aes* aes, void* heap, int devId)
+{
+    int ret = 0;
+
+    if (aes == NULL)
+        return BAD_FUNC_ARG;
+
+    aes->heap = heap;
+
+#ifdef WOLF_CRYPTO_CB
+    aes->devId = devId;
+    aes->devCtx = NULL;
+#else
+    (void)devId;
+#endif
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES)
+    ret = wolfAsync_DevCtxInit(&aes->asyncDev, WOLFSSL_ASYNC_MARKER_AES,
+                                                        aes->heap, devId);
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+#ifdef WOLFSSL_AFALG
+    aes->alFd = -1;
+    aes->rdFd = -1;
+#endif
+#if defined(WOLFSSL_DEVCRYPTO) && \
+   (defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC))
+    aes->ctx.cfd = -1;
+#endif
+#if defined(WOLFSSL_CRYPTOCELL) && defined(WOLFSSL_CRYPTOCELL_AES)
+    XMEMSET(&aes->ctx, 0, sizeof(aes->ctx));
+#endif
+#ifdef HAVE_AESGCM
+#ifdef OPENSSL_EXTRA
+    XMEMSET(aes->aadH, 0, sizeof(aes->aadH));
+    aes->aadLen = 0;
+#endif
+#endif
+    return ret;
+}
+
+#ifdef HAVE_PKCS11
+int  wc_AesInit_Id(Aes* aes, unsigned char* id, int len, void* heap, int devId)
+{
+    int ret = 0;
+
+    if (aes == NULL)
+        ret = BAD_FUNC_ARG;
+    if (ret == 0 && (len < 0 || len > AES_MAX_ID_LEN))
+        ret = BUFFER_E;
+
+    if (ret == 0)
+        ret  = wc_AesInit(aes, heap, devId);
+    if (ret == 0) {
+        XMEMCPY(aes->id, id, len);
+        aes->idLen = len;
+    }
+
+    return ret;
+}
+#endif
+
+/* Free Aes from use with async hardware */
+void wc_AesFree(Aes* aes)
+{
+    if (aes == NULL)
+        return;
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES)
+    wolfAsync_DevCtxFree(&aes->asyncDev, WOLFSSL_ASYNC_MARKER_AES);
+#endif /* WOLFSSL_ASYNC_CRYPT */
+#if defined(WOLFSSL_AFALG) || defined(WOLFSSL_AFALG_XILINX_AES)
+    if (aes->rdFd > 0) { /* negative is error case */
+        close(aes->rdFd);
+    }
+    if (aes->alFd > 0) {
+        close(aes->alFd);
+    }
+#endif /* WOLFSSL_AFALG */
+#if defined(WOLFSSL_DEVCRYPTO) && \
+    (defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC))
+    wc_DevCryptoFree(&aes->ctx);
+#endif
+#if defined(WOLF_CRYPTO_CB) || (defined(WOLFSSL_DEVCRYPTO) && \
+    (defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC))) || \
+    (defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES))
+    ForceZero((byte*)aes->devKey, AES_MAX_KEY_SIZE/WOLFSSL_BIT_SIZE);
+#endif
+}
+
+
+int wc_AesGetKeySize(Aes* aes, word32* keySize)
+{
+    int ret = 0;
+
+    if (aes == NULL || keySize == NULL) {
+        return BAD_FUNC_ARG;
+    }
+#if defined(WOLFSSL_CRYPTOCELL) && defined(WOLFSSL_CRYPTOCELL_AES)
+    *keySize = aes->ctx.key.keySize;
+    return ret;
+#endif
+    switch (aes->rounds) {
+#ifdef WOLFSSL_AES_128
+    case 10:
+        *keySize = 16;
+        break;
+#endif
+#ifdef WOLFSSL_AES_192
+    case 12:
+        *keySize = 24;
+        break;
+#endif
+#ifdef WOLFSSL_AES_256
+    case 14:
+        *keySize = 32;
+        break;
+#endif
+    default:
+        *keySize = 0;
+        ret = BAD_FUNC_ARG;
+    }
+
+    return ret;
+}
+
+#endif /* !WOLFSSL_TI_CRYPT */
+
+#ifdef HAVE_AES_ECB
+#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
+    /* implemented in wolfcrypt/src/port/caam/caam_aes.c */
+
+#elif defined(WOLFSSL_AFALG)
+    /* implemented in wolfcrypt/src/port/af_alg/afalg_aes.c */
+
+#elif defined(WOLFSSL_DEVCRYPTO_AES)
+    /* implemented in wolfcrypt/src/port/devcrypt/devcrypto_aes.c */
+
+#elif defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_AES)
+
+/* Software AES - ECB */
+int wc_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+{
+    if ((in == NULL) || (out == NULL) || (aes == NULL))
+        return BAD_FUNC_ARG;
+
+        return AES_ECB_encrypt(aes, in, out, sz);
+}
+
+
+int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+{
+    if ((in == NULL) || (out == NULL) || (aes == NULL))
+        return BAD_FUNC_ARG;
+
+        return AES_ECB_decrypt(aes, in, out, sz);
+}
+
+#else
+
+/* Software AES - ECB */
+int wc_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+{
+    word32 blocks = sz / AES_BLOCK_SIZE;
+
+    if ((in == NULL) || (out == NULL) || (aes == NULL))
+      return BAD_FUNC_ARG;
+    while (blocks>0) {
+      wc_AesEncryptDirect(aes, out, in);
+      out += AES_BLOCK_SIZE;
+      in  += AES_BLOCK_SIZE;
+      sz  -= AES_BLOCK_SIZE;
+      blocks--;
+    }
+    return 0;
+}
+
+
+int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+{
+    word32 blocks = sz / AES_BLOCK_SIZE;
+
+    if ((in == NULL) || (out == NULL) || (aes == NULL))
+      return BAD_FUNC_ARG;
+    while (blocks>0) {
+      wc_AesDecryptDirect(aes, out, in);
+      out += AES_BLOCK_SIZE;
+      in  += AES_BLOCK_SIZE;
+      sz  -= AES_BLOCK_SIZE;
+      blocks--;
+    }
+    return 0;
+}
+#endif
+#endif /* HAVE_AES_ECB */
+
+#if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_OFB)
+/* Feedback AES mode
+ *
+ * aes structure holding key to use for encryption
+ * out buffer to hold result of encryption (must be at least as large as input
+ *     buffer)
+ * in  buffer to encrypt
+ * sz  size of input buffer
+ * mode flag to specify AES mode
+ *
+ * returns 0 on success and negative error values on failure
+ */
+/* Software AES - CFB Encrypt */
+static int wc_AesFeedbackEncrypt(Aes* aes, byte* out, const byte* in,
+        word32 sz, byte mode)
+{
+    byte*  tmp = NULL;
+#ifdef WOLFSSL_AES_CFB
+    byte*  reg = NULL;
+#endif
+
+    if (aes == NULL || out == NULL || in == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef WOLFSSL_AES_CFB
+    if (aes->left && sz) {
+        reg = (byte*)aes->reg + AES_BLOCK_SIZE - aes->left;
+    }
+#endif
+
+    /* consume any unused bytes left in aes->tmp */
+    tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left;
+    while (aes->left && sz) {
+        *(out) = *(in++) ^ *(tmp++);
+    #ifdef WOLFSSL_AES_CFB
+        if (mode == AES_CFB_MODE) {
+            *(reg++) = *out;
+        }
+    #endif
+        out++;
+        aes->left--;
+        sz--;
+    }
+
+    while (sz >= AES_BLOCK_SIZE) {
+        /* Using aes->tmp here for inline case i.e. in=out */
+        wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg);
+    #ifdef WOLFSSL_AES_OFB
+        if (mode == AES_OFB_MODE) {
+            XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE);
+        }
+    #endif
+        xorbuf((byte*)aes->tmp, in, AES_BLOCK_SIZE);
+    #ifdef WOLFSSL_AES_CFB
+        if (mode == AES_CFB_MODE) {
+            XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE);
+        }
+    #endif
+        XMEMCPY(out, aes->tmp, AES_BLOCK_SIZE);
+        out += AES_BLOCK_SIZE;
+        in  += AES_BLOCK_SIZE;
+        sz  -= AES_BLOCK_SIZE;
+        aes->left = 0;
+    }
+
+    /* encrypt left over data */
+    if (sz) {
+        wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg);
+        aes->left = AES_BLOCK_SIZE;
+        tmp = (byte*)aes->tmp;
+    #ifdef WOLFSSL_AES_OFB
+        if (mode == AES_OFB_MODE) {
+            XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE);
+        }
+    #endif
+    #ifdef WOLFSSL_AES_CFB
+        reg = (byte*)aes->reg;
+    #endif
+
+        while (sz--) {
+            *(out) = *(in++) ^ *(tmp++);
+        #ifdef WOLFSSL_AES_CFB
+            if (mode == AES_CFB_MODE) {
+                *(reg++) = *out;
+            }
+        #endif
+            out++;
+            aes->left--;
+        }
+    }
+
+    return 0;
+}
+
+
+#ifdef HAVE_AES_DECRYPT
+/* CFB 128
+ *
+ * aes structure holding key to use for decryption
+ * out buffer to hold result of decryption (must be at least as large as input
+ *     buffer)
+ * in  buffer to decrypt
+ * sz  size of input buffer
+ *
+ * returns 0 on success and negative error values on failure
+ */
+/* Software AES - CFB Decrypt */
+static int wc_AesFeedbackDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
+        byte mode)
+{
+    byte*  tmp;
+
+    if (aes == NULL || out == NULL || in == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    #ifdef WOLFSSL_AES_CFB
+    /* check if more input needs copied over to aes->reg */
+    if (aes->left && sz && mode == AES_CFB_MODE) {
+        int size = min(aes->left, sz);
+        XMEMCPY((byte*)aes->reg + AES_BLOCK_SIZE - aes->left, in, size);
+    }
+    #endif
+
+    /* consume any unused bytes left in aes->tmp */
+    tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left;
+    while (aes->left && sz) {
+        *(out++) = *(in++) ^ *(tmp++);
+        aes->left--;
+        sz--;
+    }
+
+    while (sz > AES_BLOCK_SIZE) {
+        /* Using aes->tmp here for inline case i.e. in=out */
+        wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg);
+    #ifdef WOLFSSL_AES_OFB
+        if (mode == AES_OFB_MODE) {
+            XMEMCPY((byte*)aes->reg, (byte*)aes->tmp, AES_BLOCK_SIZE);
+        }
+    #endif
+        xorbuf((byte*)aes->tmp, in, AES_BLOCK_SIZE);
+    #ifdef WOLFSSL_AES_CFB
+        if (mode == AES_CFB_MODE) {
+            XMEMCPY(aes->reg, in, AES_BLOCK_SIZE);
+        }
+    #endif
+        XMEMCPY(out, (byte*)aes->tmp, AES_BLOCK_SIZE);
+        out += AES_BLOCK_SIZE;
+        in  += AES_BLOCK_SIZE;
+        sz  -= AES_BLOCK_SIZE;
+        aes->left = 0;
+    }
+
+    /* decrypt left over data */
+    if (sz) {
+        wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg);
+    #ifdef WOLFSSL_AES_CFB
+        if (mode == AES_CFB_MODE) {
+            XMEMCPY(aes->reg, in, sz);
+        }
+    #endif
+    #ifdef WOLFSSL_AES_OFB
+        if (mode == AES_OFB_MODE) {
+            XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE);
+        }
+    #endif
+
+        aes->left = AES_BLOCK_SIZE;
+        tmp = (byte*)aes->tmp;
+
+        while (sz--) {
+            *(out++) = *(in++) ^ *(tmp++);
+            aes->left--;
+        }
+    }
+
+    return 0;
+}
+#endif /* HAVE_AES_DECRYPT */
+#endif /* WOLFSSL_AES_CFB */
+
+#ifdef WOLFSSL_AES_CFB
+/* CFB 128
+ *
+ * aes structure holding key to use for encryption
+ * out buffer to hold result of encryption (must be at least as large as input
+ *     buffer)
+ * in  buffer to encrypt
+ * sz  size of input buffer
+ *
+ * returns 0 on success and negative error values on failure
+ */
+/* Software AES - CFB Encrypt */
+int wc_AesCfbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+{
+    return wc_AesFeedbackEncrypt(aes, out, in, sz, AES_CFB_MODE);
+}
+
+
+#ifdef HAVE_AES_DECRYPT
+/* CFB 128
+ *
+ * aes structure holding key to use for decryption
+ * out buffer to hold result of decryption (must be at least as large as input
+ *     buffer)
+ * in  buffer to decrypt
+ * sz  size of input buffer
+ *
+ * returns 0 on success and negative error values on failure
+ */
+/* Software AES - CFB Decrypt */
+int wc_AesCfbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+{
+    return wc_AesFeedbackDecrypt(aes, out, in, sz, AES_CFB_MODE);
+}
+#endif /* HAVE_AES_DECRYPT */
+
+
+/* shift the whole AES_BLOCK_SIZE array left by 8 or 1 bits */
+static void shiftLeftArray(byte* ary, byte shift)
+{
+    int i;
+
+    if (shift == WOLFSSL_BIT_SIZE) {
+        /* shifting over by 8 bits */
+        for (i = 0; i < AES_BLOCK_SIZE - 1; i++) {
+            ary[i] = ary[i+1];
+        }
+        ary[i] = 0;
+    }
+    else {
+        byte carry = 0;
+
+        /* shifting over by 7 or less bits */
+        for (i = 0; i < AES_BLOCK_SIZE - 1; i++) {
+            carry = ary[i+1] & (0XFF << (WOLFSSL_BIT_SIZE - shift));
+            carry >>= (WOLFSSL_BIT_SIZE - shift);
+            ary[i] = (ary[i] << shift) + carry;
+        }
+        ary[i] = ary[i] << shift;
+    }
+}
+
+
+/* returns 0 on success and negative values on failure */
+static int wc_AesFeedbackCFB8(Aes* aes, byte* out, const byte* in,
+        word32 sz, byte dir)
+{
+    byte *pt;
+
+    if (aes == NULL || out == NULL || in == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (sz == 0) {
+        return 0;
+    }
+
+    while (sz > 0) {
+        wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg);
+        if (dir == AES_DECRYPTION) {
+            pt = (byte*)aes->reg;
+
+            /* LSB + CAT */
+            shiftLeftArray(pt, WOLFSSL_BIT_SIZE);
+            pt[AES_BLOCK_SIZE - 1] = in[0];
+        }
+
+        /* MSB + XOR */
+        out[0] = aes->tmp[0] ^ in[0];
+        if (dir == AES_ENCRYPTION) {
+            pt = (byte*)aes->reg;
+
+            /* LSB + CAT */
+            shiftLeftArray(pt, WOLFSSL_BIT_SIZE);
+            pt[AES_BLOCK_SIZE - 1] = out[0];
+        }
+
+        out += 1;
+        in  += 1;
+        sz  -= 1;
+    }
+
+    return 0;
+}
+
+
+/* returns 0 on success and negative values on failure */
+static int wc_AesFeedbackCFB1(Aes* aes, byte* out, const byte* in,
+        word32 sz, byte dir)
+{
+    byte tmp;
+    byte cur = 0; /* hold current work in order to handle inline in=out */
+    byte* pt;
+    int bit = 7;
+
+    if (aes == NULL || out == NULL || in == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (sz == 0) {
+        return 0;
+    }
+
+    while (sz > 0) {
+        wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg);
+        if (dir == AES_DECRYPTION) {
+            pt = (byte*)aes->reg;
+
+            /* LSB + CAT */
+            tmp = (0X01 << bit) & in[0];
+            tmp = tmp >> bit;
+            tmp &= 0x01;
+            shiftLeftArray((byte*)aes->reg, 1);
+            pt[AES_BLOCK_SIZE - 1] |= tmp;
+        }
+
+        /* MSB  + XOR */
+        tmp = (0X01 << bit) & in[0];
+        pt = (byte*)aes->tmp;
+        tmp = (pt[0] >> 7) ^ (tmp >> bit);
+        tmp &= 0x01;
+        cur |= (tmp << bit);
+
+
+        if (dir == AES_ENCRYPTION) {
+            pt = (byte*)aes->reg;
+
+            /* LSB + CAT */
+            shiftLeftArray((byte*)aes->reg, 1);
+            pt[AES_BLOCK_SIZE - 1] |= tmp;
+        }
+
+        bit--;
+        if (bit < 0) {
+            out[0] = cur;
+            out += 1;
+            in  += 1;
+            sz  -= 1;
+            bit = 7;
+            cur = 0;
+        }
+        else {
+            sz -= 1;
+        }
+    }
+
+    if (bit > 0 && bit < 7) {
+        out[0] = cur;
+    }
+
+    return 0;
+}
+
+
+/* CFB 1
+ *
+ * aes structure holding key to use for encryption
+ * out buffer to hold result of encryption (must be at least as large as input
+ *     buffer)
+ * in  buffer to encrypt (packed to left, i.e. 101 is 0x90)
+ * sz  size of input buffer in bits (0x1 would be size of 1 and 0xFF size of 8)
+ *
+ * returns 0 on success and negative values on failure
+ */
+int wc_AesCfb1Encrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+{
+    return wc_AesFeedbackCFB1(aes, out, in, sz, AES_ENCRYPTION);
+}
+
+
+/* CFB 8
+ *
+ * aes structure holding key to use for encryption
+ * out buffer to hold result of encryption (must be at least as large as input
+ *     buffer)
+ * in  buffer to encrypt
+ * sz  size of input buffer
+ *
+ * returns 0 on success and negative values on failure
+ */
+int wc_AesCfb8Encrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+{
+    return wc_AesFeedbackCFB8(aes, out, in, sz, AES_ENCRYPTION);
+}
+#ifdef HAVE_AES_DECRYPT
+
+/* CFB 1
+ *
+ * aes structure holding key to use for encryption
+ * out buffer to hold result of encryption (must be at least as large as input
+ *     buffer)
+ * in  buffer to encrypt
+ * sz  size of input buffer in bits (0x1 would be size of 1 and 0xFF size of 8)
+ *
+ * returns 0 on success and negative values on failure
+ */
+int wc_AesCfb1Decrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+{
+    return wc_AesFeedbackCFB1(aes, out, in, sz, AES_DECRYPTION);
+}
+
+
+/* CFB 8
+ *
+ * aes structure holding key to use for encryption
+ * out buffer to hold result of encryption (must be at least as large as input
+ *     buffer)
+ * in  buffer to encrypt
+ * sz  size of input buffer
+ *
+ * returns 0 on success and negative values on failure
+ */
+int wc_AesCfb8Decrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+{
+    return wc_AesFeedbackCFB8(aes, out, in, sz, AES_DECRYPTION);
+}
+#endif /* HAVE_AES_DECRYPT */
+#endif /* WOLFSSL_AES_CFB */
+
+#ifdef WOLFSSL_AES_OFB
+/* OFB
+ *
+ * aes structure holding key to use for encryption
+ * out buffer to hold result of encryption (must be at least as large as input
+ *     buffer)
+ * in  buffer to encrypt
+ * sz  size of input buffer
+ *
+ * returns 0 on success and negative error values on failure
+ */
+/* Software AES - CFB Encrypt */
+int wc_AesOfbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+{
+    return wc_AesFeedbackEncrypt(aes, out, in, sz, AES_OFB_MODE);
+}
+
+
+#ifdef HAVE_AES_DECRYPT
+/* OFB
+ *
+ * aes structure holding key to use for decryption
+ * out buffer to hold result of decryption (must be at least as large as input
+ *     buffer)
+ * in  buffer to decrypt
+ * sz  size of input buffer
+ *
+ * returns 0 on success and negative error values on failure
+ */
+/* Software AES - OFB Decrypt */
+int wc_AesOfbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+{
+    return wc_AesFeedbackDecrypt(aes, out, in, sz, AES_OFB_MODE);
+}
+#endif /* HAVE_AES_DECRYPT */
+#endif /* WOLFSSL_AES_OFB */
+
+
+#ifdef HAVE_AES_KEYWRAP
+
+/* Initialize key wrap counter with value */
+static WC_INLINE void InitKeyWrapCounter(byte* inOutCtr, word32 value)
+{
+    int i;
+    word32 bytes;
+
+    bytes = sizeof(word32);
+    for (i = 0; i < (int)sizeof(word32); i++) {
+        inOutCtr[i+sizeof(word32)] = (value >> ((bytes - 1) * 8)) & 0xFF;
+        bytes--;
+    }
+}
+
+/* Increment key wrap counter */
+static WC_INLINE void IncrementKeyWrapCounter(byte* inOutCtr)
+{
+    int i;
+
+    /* in network byte order so start at end and work back */
+    for (i = KEYWRAP_BLOCK_SIZE - 1; i >= 0; i--) {
+        if (++inOutCtr[i])  /* we're done unless we overflow */
+            return;
+    }
+}
+
+/* Decrement key wrap counter */
+static WC_INLINE void DecrementKeyWrapCounter(byte* inOutCtr)
+{
+    int i;
+
+    for (i = KEYWRAP_BLOCK_SIZE - 1; i >= 0; i--) {
+        if (--inOutCtr[i] != 0xFF)  /* we're done unless we underflow */
+            return;
+    }
+}
+
+/* perform AES key wrap (RFC3394), return out sz on success, negative on err */
+int wc_AesKeyWrap(const byte* key, word32 keySz, const byte* in, word32 inSz,
+                  byte* out, word32 outSz, const byte* iv)
+{
+    Aes aes;
+    byte* r;
+    word32 i;
+    int ret, j;
+
+    byte t[KEYWRAP_BLOCK_SIZE];
+    byte tmp[AES_BLOCK_SIZE];
+
+    /* n must be at least 2, output size is n + 8 bytes */
+    if (key == NULL || in  == NULL || inSz < 2 ||
+        out == NULL || outSz < (inSz + KEYWRAP_BLOCK_SIZE))
+        return BAD_FUNC_ARG;
+
+    /* input must be multiple of 64-bits */
+    if (inSz % KEYWRAP_BLOCK_SIZE != 0)
+        return BAD_FUNC_ARG;
+
+    /* user IV is optional */
+    if (iv == NULL) {
+        XMEMSET(tmp, 0xA6, KEYWRAP_BLOCK_SIZE);
+    } else {
+        XMEMCPY(tmp, iv, KEYWRAP_BLOCK_SIZE);
+    }
+
+    r = out + 8;
+    XMEMCPY(r, in, inSz);
+    XMEMSET(t, 0, sizeof(t));
+
+    ret = wc_AesInit(&aes, NULL, INVALID_DEVID);
+    if (ret != 0)
+        return ret;
+
+    ret = wc_AesSetKey(&aes, key, keySz, NULL, AES_ENCRYPTION);
+    if (ret != 0)
+        return ret;
+
+    for (j = 0; j <= 5; j++) {
+        for (i = 1; i <= inSz / KEYWRAP_BLOCK_SIZE; i++) {
+
+            /* load R[i] */
+            XMEMCPY(tmp + KEYWRAP_BLOCK_SIZE, r, KEYWRAP_BLOCK_SIZE);
+
+            wc_AesEncryptDirect(&aes, tmp, tmp);
+
+            /* calculate new A */
+            IncrementKeyWrapCounter(t);
+            xorbuf(tmp, t, KEYWRAP_BLOCK_SIZE);
+
+            /* save R[i] */
+            XMEMCPY(r, tmp + KEYWRAP_BLOCK_SIZE, KEYWRAP_BLOCK_SIZE);
+            r += KEYWRAP_BLOCK_SIZE;
+        }
+        r = out + KEYWRAP_BLOCK_SIZE;
+    }
+
+    /* C[0] = A */
+    XMEMCPY(out, tmp, KEYWRAP_BLOCK_SIZE);
+
+    wc_AesFree(&aes);
+
+    return inSz + KEYWRAP_BLOCK_SIZE;
+}
+
+int wc_AesKeyUnWrap(const byte* key, word32 keySz, const byte* in, word32 inSz,
+                    byte* out, word32 outSz, const byte* iv)
+{
+    Aes aes;
+    byte* r;
+    word32 i, n;
+    int ret, j;
+
+    byte t[KEYWRAP_BLOCK_SIZE];
+    byte tmp[AES_BLOCK_SIZE];
+
+    const byte* expIv;
+    const byte defaultIV[] = {
+        0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6
+    };
+
+    (void)iv;
+
+    if (key == NULL || in == NULL || inSz < 3 ||
+        out == NULL || outSz < (inSz - KEYWRAP_BLOCK_SIZE))
+        return BAD_FUNC_ARG;
+
+    /* input must be multiple of 64-bits */
+    if (inSz % KEYWRAP_BLOCK_SIZE != 0)
+        return BAD_FUNC_ARG;
+
+    /* user IV optional */
+    if (iv != NULL) {
+        expIv = iv;
+    } else {
+        expIv = defaultIV;
+    }
+
+    /* A = C[0], R[i] = C[i] */
+    XMEMCPY(tmp, in, KEYWRAP_BLOCK_SIZE);
+    XMEMCPY(out, in + KEYWRAP_BLOCK_SIZE, inSz - KEYWRAP_BLOCK_SIZE);
+    XMEMSET(t, 0, sizeof(t));
+
+    ret = wc_AesInit(&aes, NULL, INVALID_DEVID);
+    if (ret != 0)
+        return ret;
+
+    ret = wc_AesSetKey(&aes, key, keySz, NULL, AES_DECRYPTION);
+    if (ret != 0)
+        return ret;
+
+    /* initialize counter to 6n */
+    n = (inSz - 1) / KEYWRAP_BLOCK_SIZE;
+    InitKeyWrapCounter(t, 6 * n);
+
+    for (j = 5; j >= 0; j--) {
+        for (i = n; i >= 1; i--) {
+
+            /* calculate A */
+            xorbuf(tmp, t, KEYWRAP_BLOCK_SIZE);
+            DecrementKeyWrapCounter(t);
+
+            /* load R[i], starting at end of R */
+            r = out + ((i - 1) * KEYWRAP_BLOCK_SIZE);
+            XMEMCPY(tmp + KEYWRAP_BLOCK_SIZE, r, KEYWRAP_BLOCK_SIZE);
+            wc_AesDecryptDirect(&aes, tmp, tmp);
+
+            /* save R[i] */
+            XMEMCPY(r, tmp + KEYWRAP_BLOCK_SIZE, KEYWRAP_BLOCK_SIZE);
+        }
+    }
+
+    wc_AesFree(&aes);
+
+    /* verify IV */
+    if (XMEMCMP(tmp, expIv, KEYWRAP_BLOCK_SIZE) != 0)
+        return BAD_KEYWRAP_IV_E;
+
+    return inSz - KEYWRAP_BLOCK_SIZE;
+}
+
+#endif /* HAVE_AES_KEYWRAP */
+
+#ifdef WOLFSSL_AES_XTS
+
+/* Galios Field to use */
+#define GF_XTS 0x87
+
+/* This is to help with setting keys to correct encrypt or decrypt type.
+ *
+ * tweak AES key for tweak in XTS
+ * aes   AES key for encrypt/decrypt process
+ * key   buffer holding aes key | tweak key
+ * len   length of key buffer in bytes. Should be twice that of key size. i.e.
+ *       32 for a 16 byte key.
+ * dir   direction, either AES_ENCRYPTION or AES_DECRYPTION
+ * heap  heap hint to use for memory. Can be NULL
+ * devId id to use with async crypto. Can be 0
+ *
+ * Note: is up to user to call wc_AesFree on tweak and aes key when done.
+ *
+ * return 0 on success
+ */
+int wc_AesXtsSetKey(XtsAes* aes, const byte* key, word32 len, int dir,
+        void* heap, int devId)
+{
+    word32 keySz;
+    int    ret = 0;
+
+    if (aes == NULL || key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if ((ret = wc_AesInit(&aes->tweak, heap, devId)) != 0) {
+        return ret;
+    }
+    if ((ret = wc_AesInit(&aes->aes, heap, devId)) != 0) {
+        return ret;
+    }
+
+    keySz = len/2;
+    if (keySz != 16 && keySz != 32) {
+        WOLFSSL_MSG("Unsupported key size");
+        return WC_KEY_SIZE_E;
+    }
+
+    if ((ret = wc_AesSetKey(&aes->aes, key, keySz, NULL, dir)) == 0) {
+        ret = wc_AesSetKey(&aes->tweak, key + keySz, keySz, NULL,
+                AES_ENCRYPTION);
+        if (ret != 0) {
+            wc_AesFree(&aes->aes);
+        }
+    }
+
+    return ret;
+}
+
+
+/* This is used to free up resources used by Aes structs
+ *
+ * aes AES keys to free
+ *
+ * return 0 on success
+ */
+int wc_AesXtsFree(XtsAes* aes)
+{
+    if (aes != NULL) {
+        wc_AesFree(&aes->aes);
+        wc_AesFree(&aes->tweak);
+    }
+
+    return 0;
+}
+
+
+/* Same process as wc_AesXtsEncrypt but uses a word64 type as the tweak value
+ * instead of a byte array. This just converts the word64 to a byte array and
+ * calls wc_AesXtsEncrypt.
+ *
+ * aes    AES keys to use for block encrypt/decrypt
+ * out    output buffer to hold cipher text
+ * in     input plain text buffer to encrypt
+ * sz     size of both out and in buffers
+ * sector value to use for tweak
+ *
+ * returns 0 on success
+ */
+int wc_AesXtsEncryptSector(XtsAes* aes, byte* out, const byte* in,
+        word32 sz, word64 sector)
+{
+    byte* pt;
+    byte  i[AES_BLOCK_SIZE];
+
+    XMEMSET(i, 0, AES_BLOCK_SIZE);
+#ifdef BIG_ENDIAN_ORDER
+    sector = ByteReverseWord64(sector);
+#endif
+    pt = (byte*)&sector;
+    XMEMCPY(i, pt, sizeof(word64));
+
+    return wc_AesXtsEncrypt(aes, out, in, sz, (const byte*)i, AES_BLOCK_SIZE);
+}
+
+
+/* Same process as wc_AesXtsDecrypt but uses a word64 type as the tweak value
+ * instead of a byte array. This just converts the word64 to a byte array.
+ *
+ * aes    AES keys to use for block encrypt/decrypt
+ * out    output buffer to hold plain text
+ * in     input cipher text buffer to encrypt
+ * sz     size of both out and in buffers
+ * sector value to use for tweak
+ *
+ * returns 0 on success
+ */
+int wc_AesXtsDecryptSector(XtsAes* aes, byte* out, const byte* in, word32 sz,
+        word64 sector)
+{
+    byte* pt;
+    byte  i[AES_BLOCK_SIZE];
+
+    XMEMSET(i, 0, AES_BLOCK_SIZE);
+#ifdef BIG_ENDIAN_ORDER
+    sector = ByteReverseWord64(sector);
+#endif
+    pt = (byte*)&sector;
+    XMEMCPY(i, pt, sizeof(word64));
+
+    return wc_AesXtsDecrypt(aes, out, in, sz, (const byte*)i, AES_BLOCK_SIZE);
+}
+
+#ifdef HAVE_AES_ECB
+/* helper function for encrypting / decrypting full buffer at once */
+static int _AesXtsHelper(Aes* aes, byte* out, const byte* in, word32 sz, int dir)
+{
+    word32 outSz   = sz;
+    word32 totalSz = (sz / AES_BLOCK_SIZE) * AES_BLOCK_SIZE; /* total bytes */
+    byte*  pt      = out;
+
+    outSz -= AES_BLOCK_SIZE;
+
+    while (outSz > 0) {
+        word32 j;
+        byte carry = 0;
+
+        /* multiply by shift left and propagate carry */
+        for (j = 0; j < AES_BLOCK_SIZE && outSz > 0; j++, outSz--) {
+            byte tmpC;
+
+            tmpC   = (pt[j] >> 7) & 0x01;
+            pt[j+AES_BLOCK_SIZE] = ((pt[j] << 1) + carry) & 0xFF;
+            carry  = tmpC;
+        }
+        if (carry) {
+            pt[AES_BLOCK_SIZE] ^= GF_XTS;
+        }
+
+        pt += AES_BLOCK_SIZE;
+    }
+
+    xorbuf(out, in, totalSz);
+    if (dir == AES_ENCRYPTION) {
+        return wc_AesEcbEncrypt(aes, out, out, totalSz);
+    }
+    else {
+        return wc_AesEcbDecrypt(aes, out, out, totalSz);
+    }
+}
+#endif /* HAVE_AES_ECB */
+
+
+/* AES with XTS mode. (XTS) XEX encryption with Tweak and cipher text Stealing.
+ *
+ * xaes  AES keys to use for block encrypt/decrypt
+ * out   output buffer to hold cipher text
+ * in    input plain text buffer to encrypt
+ * sz    size of both out and in buffers
+ * i     value to use for tweak
+ * iSz   size of i buffer, should always be AES_BLOCK_SIZE but having this input
+ *       adds a sanity check on how the user calls the function.
+ *
+ * returns 0 on success
+ */
+/* Software AES - XTS Encrypt  */
+int wc_AesXtsEncrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz,
+        const byte* i, word32 iSz)
+{
+    int ret = 0;
+    word32 blocks = (sz / AES_BLOCK_SIZE);
+    Aes *aes, *tweak;
+
+    if (xaes == NULL || out == NULL || in == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    aes   = &xaes->aes;
+    tweak = &xaes->tweak;
+
+    if (iSz < AES_BLOCK_SIZE) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (blocks > 0) {
+        byte tmp[AES_BLOCK_SIZE];
+
+        XMEMSET(tmp, 0, AES_BLOCK_SIZE); /* set to 0's in case of improper AES
+                                          * key setup passed to encrypt direct*/
+
+        wc_AesEncryptDirect(tweak, tmp, i);
+
+    #ifdef HAVE_AES_ECB
+        /* encrypt all of buffer at once when possible */
+        if (in != out) { /* can not handle inline */
+            XMEMCPY(out, tmp, AES_BLOCK_SIZE);
+            if ((ret = _AesXtsHelper(aes, out, in, sz, AES_ENCRYPTION)) != 0) {
+                return ret;
+            }
+        }
+    #endif
+
+        while (blocks > 0) {
+            word32 j;
+            byte carry = 0;
+            byte buf[AES_BLOCK_SIZE];
+
+    #ifdef HAVE_AES_ECB
+            if (in == out) { /* check for if inline */
+    #endif
+            XMEMCPY(buf, in, AES_BLOCK_SIZE);
+            xorbuf(buf, tmp, AES_BLOCK_SIZE);
+            wc_AesEncryptDirect(aes, out, buf);
+    #ifdef HAVE_AES_ECB
+            }
+    #endif
+            xorbuf(out, tmp, AES_BLOCK_SIZE);
+
+            /* multiply by shift left and propagate carry */
+            for (j = 0; j < AES_BLOCK_SIZE; j++) {
+                byte tmpC;
+
+                tmpC   = (tmp[j] >> 7) & 0x01;
+                tmp[j] = ((tmp[j] << 1) + carry) & 0xFF;
+                carry  = tmpC;
+            }
+            if (carry) {
+                tmp[0] ^= GF_XTS;
+            }
+
+            in  += AES_BLOCK_SIZE;
+            out += AES_BLOCK_SIZE;
+            sz  -= AES_BLOCK_SIZE;
+            blocks--;
+        }
+
+        /* stealing operation of XTS to handle left overs */
+        if (sz > 0) {
+            byte buf[AES_BLOCK_SIZE];
+
+            XMEMCPY(buf, out - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
+            if (sz >= AES_BLOCK_SIZE) { /* extra sanity check before copy */
+                return BUFFER_E;
+            }
+            XMEMCPY(out, buf, sz);
+            XMEMCPY(buf, in, sz);
+
+            xorbuf(buf, tmp, AES_BLOCK_SIZE);
+            wc_AesEncryptDirect(aes, out - AES_BLOCK_SIZE, buf);
+            xorbuf(out - AES_BLOCK_SIZE, tmp, AES_BLOCK_SIZE);
+        }
+    }
+    else {
+        WOLFSSL_MSG("Plain text input too small for encryption");
+        return BAD_FUNC_ARG;
+    }
+
+    return ret;
+}
+
+
+/* Same process as encryption but Aes key is AES_DECRYPTION type.
+ *
+ * xaes  AES keys to use for block encrypt/decrypt
+ * out   output buffer to hold plain text
+ * in    input cipher text buffer to decrypt
+ * sz    size of both out and in buffers
+ * i     value to use for tweak
+ * iSz   size of i buffer, should always be AES_BLOCK_SIZE but having this input
+ *       adds a sanity check on how the user calls the function.
+ *
+ * returns 0 on success
+ */
+/* Software AES - XTS Decrypt */
+int wc_AesXtsDecrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz,
+        const byte* i, word32 iSz)
+{
+    int ret = 0;
+    word32 blocks = (sz / AES_BLOCK_SIZE);
+    Aes *aes, *tweak;
+
+    if (xaes == NULL || out == NULL || in == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    aes   = &xaes->aes;
+    tweak = &xaes->tweak;
+
+    if (iSz < AES_BLOCK_SIZE) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (blocks > 0) {
+        word32 j;
+        byte carry = 0;
+        byte tmp[AES_BLOCK_SIZE];
+        byte stl = (sz % AES_BLOCK_SIZE);
+
+        XMEMSET(tmp, 0, AES_BLOCK_SIZE); /* set to 0's in case of improper AES
+                                          * key setup passed to decrypt direct*/
+
+        wc_AesEncryptDirect(tweak, tmp, i);
+
+        /* if Stealing then break out of loop one block early to handle special
+         * case */
+        if (stl > 0) {
+            blocks--;
+        }
+
+    #ifdef HAVE_AES_ECB
+        /* decrypt all of buffer at once when possible */
+        if (in != out) { /* can not handle inline */
+            XMEMCPY(out, tmp, AES_BLOCK_SIZE);
+            if ((ret = _AesXtsHelper(aes, out, in, sz, AES_DECRYPTION)) != 0) {
+                return ret;
+            }
+        }
+    #endif
+
+        while (blocks > 0) {
+            byte buf[AES_BLOCK_SIZE];
+
+    #ifdef HAVE_AES_ECB
+            if (in == out) { /* check for if inline */
+    #endif
+            XMEMCPY(buf, in, AES_BLOCK_SIZE);
+            xorbuf(buf, tmp, AES_BLOCK_SIZE);
+            wc_AesDecryptDirect(aes, out, buf);
+    #ifdef HAVE_AES_ECB
+            }
+    #endif
+            xorbuf(out, tmp, AES_BLOCK_SIZE);
+
+            /* multiply by shift left and propagate carry */
+            for (j = 0; j < AES_BLOCK_SIZE; j++) {
+                byte tmpC;
+
+                tmpC   = (tmp[j] >> 7) & 0x01;
+                tmp[j] = ((tmp[j] << 1) + carry) & 0xFF;
+                carry  = tmpC;
+            }
+            if (carry) {
+                tmp[0] ^= GF_XTS;
+            }
+            carry = 0;
+
+            in  += AES_BLOCK_SIZE;
+            out += AES_BLOCK_SIZE;
+            sz  -= AES_BLOCK_SIZE;
+            blocks--;
+        }
+
+        /* stealing operation of XTS to handle left overs */
+        if (sz > 0) {
+            byte buf[AES_BLOCK_SIZE];
+            byte tmp2[AES_BLOCK_SIZE];
+
+            /* multiply by shift left and propagate carry */
+            for (j = 0; j < AES_BLOCK_SIZE; j++) {
+                byte tmpC;
+
+                tmpC   = (tmp[j] >> 7) & 0x01;
+                tmp2[j] = ((tmp[j] << 1) + carry) & 0xFF;
+                carry  = tmpC;
+            }
+            if (carry) {
+                tmp2[0] ^= GF_XTS;
+            }
+
+            XMEMCPY(buf, in, AES_BLOCK_SIZE);
+            xorbuf(buf, tmp2, AES_BLOCK_SIZE);
+            wc_AesDecryptDirect(aes, out, buf);
+            xorbuf(out, tmp2, AES_BLOCK_SIZE);
+
+            /* tmp2 holds partial | last */
+            XMEMCPY(tmp2, out, AES_BLOCK_SIZE);
+            in  += AES_BLOCK_SIZE;
+            out += AES_BLOCK_SIZE;
+            sz  -= AES_BLOCK_SIZE;
+
+            /* Make buffer with end of cipher text | last */
+            XMEMCPY(buf, tmp2, AES_BLOCK_SIZE);
+            if (sz >= AES_BLOCK_SIZE) { /* extra sanity check before copy */
+                return BUFFER_E;
+            }
+            XMEMCPY(buf, in,   sz);
+            XMEMCPY(out, tmp2, sz);
+
+            xorbuf(buf, tmp, AES_BLOCK_SIZE);
+            wc_AesDecryptDirect(aes, tmp2, buf);
+            xorbuf(tmp2, tmp, AES_BLOCK_SIZE);
+            XMEMCPY(out - AES_BLOCK_SIZE, tmp2, AES_BLOCK_SIZE);
+        }
+    }
+    else {
+        WOLFSSL_MSG("Plain text input too small for encryption");
+        return BAD_FUNC_ARG;
+    }
+
+    return ret;
+}
+
+#endif /* WOLFSSL_AES_XTS */
+
+#endif /* HAVE_FIPS */
+#endif /* !NO_AES */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/arc4.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/arc4.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/arc4.c	(revision 453)
@@ -0,0 +1,149 @@
+/* arc4.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifndef NO_RC4
+
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#include <wolfssl/wolfcrypt/arc4.h>
+
+
+int wc_Arc4SetKey(Arc4* arc4, const byte* key, word32 length)
+{
+    int ret = 0;
+    word32 i;
+    word32 keyIndex = 0, stateIndex = 0;
+
+    if (arc4 == NULL || key == NULL || length == 0) {
+        return BAD_FUNC_ARG;
+    }
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4) && \
+        defined(HAVE_CAVIUM) && !defined(HAVE_CAVIUM_V)
+    if (arc4->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ARC4) {
+        return NitroxArc4SetKey(arc4, key, length);
+    }
+#endif
+
+    arc4->x = 1;
+    arc4->y = 0;
+
+    for (i = 0; i < ARC4_STATE_SIZE; i++)
+        arc4->state[i] = (byte)i;
+
+    for (i = 0; i < ARC4_STATE_SIZE; i++) {
+        word32 a = arc4->state[i];
+        stateIndex += key[keyIndex] + a;
+        stateIndex &= 0xFF;
+        arc4->state[i] = arc4->state[stateIndex];
+        arc4->state[stateIndex] = (byte)a;
+
+        if (++keyIndex >= length)
+            keyIndex = 0;
+    }
+
+    return ret;
+}
+
+
+static WC_INLINE byte MakeByte(word32* x, word32* y, byte* s)
+{
+    word32 a = s[*x], b;
+    *y = (*y+a) & 0xff;
+
+    b = s[*y];
+    s[*x] = (byte)b;
+    s[*y] = (byte)a;
+    *x = (*x+1) & 0xff;
+
+    return s[(a+b) & 0xff];
+}
+
+
+int wc_Arc4Process(Arc4* arc4, byte* out, const byte* in, word32 length)
+{
+    int ret = 0;
+    word32 x;
+    word32 y;
+
+    if (arc4 == NULL || out == NULL || in == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4) && \
+        defined(HAVE_CAVIUM) && !defined(HAVE_CAVIUM_V)
+    if (arc4->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ARC4) {
+        return NitroxArc4Process(arc4, out, in, length);
+    }
+#endif
+
+    x = arc4->x;
+    y = arc4->y;
+
+    while(length--)
+        *out++ = *in++ ^ MakeByte(&x, &y, arc4->state);
+
+    arc4->x = (byte)x;
+    arc4->y = (byte)y;
+
+    return ret;
+}
+
+/* Initialize Arc4 for use with async device */
+int wc_Arc4Init(Arc4* arc4, void* heap, int devId)
+{
+    int ret = 0;
+
+    if (arc4 == NULL)
+        return BAD_FUNC_ARG;
+
+    arc4->heap = heap;
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4)
+    ret = wolfAsync_DevCtxInit(&arc4->asyncDev, WOLFSSL_ASYNC_MARKER_ARC4,
+        arc4->heap, devId);
+#else
+    (void)devId;
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    return ret;
+}
+
+
+/* Free Arc4 from use with async device */
+void wc_Arc4Free(Arc4* arc4)
+{
+    if (arc4 == NULL)
+        return;
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4)
+    wolfAsync_DevCtxFree(&arc4->asyncDev, WOLFSSL_ASYNC_MARKER_ARC4);
+#endif /* WOLFSSL_ASYNC_CRYPT */
+}
+
+#endif /* NO_RC4 */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/asn.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/asn.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/asn.c	(revision 453)
@@ -0,0 +1,17525 @@
+/* asn.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+/*
+ASN Options:
+ * NO_ASN_TIME: Disables time parts of the ASN code for systems without an RTC
+    or wishing to save space.
+ * IGNORE_NAME_CONSTRAINTS: Skip ASN name checks.
+ * ASN_DUMP_OID: Allows dump of OID information for debugging.
+ * RSA_DECODE_EXTRA: Decodes extra information in RSA public key.
+ * WOLFSSL_CERT_GEN: Cert generation. Saves extra certificate info in GetName.
+ * WOLFSSL_NO_ASN_STRICT: Disable strict RFC compliance checks to
+    restore 3.13.0 behavior.
+ * WOLFSSL_NO_OCSP_OPTIONAL_CERTS: Skip optional OCSP certs (responder issuer
+    must still be trusted)
+ * WOLFSSL_NO_TRUSTED_CERTS_VERIFY: Workaround for situation where entire cert
+    chain is not loaded. This only matches on subject and public key and
+    does not perform a PKI validation, so it is not a secure solution.
+    Only enabled for OCSP.
+ * WOLFSSL_NO_OCSP_ISSUER_CHECK: Can be defined for backwards compatibility to
+    disable checking of OCSP subject hash with issuer hash.
+ * WOLFSSL_SMALL_CERT_VERIFY: Verify the certificate signature without using
+    DecodedCert. Doubles up on some code but allows smaller dynamic memory
+    usage.
+ * WOLFSSL_NO_OCSP_DATE_CHECK: Disable date checks for OCSP responses. This
+    may be required when the system's real-time clock is not very accurate.
+    It is recommended to enforce the nonce check instead if possible.
+ * WOLFSSL_FORCE_OCSP_NONCE_CHECK: Require nonces to be available in OCSP
+    responses. The nonces are optional and may not be supported by all
+    responders. If it can be ensured that the used responder sends nonces this
+    option may improve security.
+*/
+
+#ifndef NO_ASN
+
+#include <wolfssl/wolfcrypt/asn.h>
+#include <wolfssl/wolfcrypt/coding.h>
+#include <wolfssl/wolfcrypt/md2.h>
+#include <wolfssl/wolfcrypt/hmac.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#include <wolfssl/wolfcrypt/pwdbased.h>
+#include <wolfssl/wolfcrypt/des3.h>
+#include <wolfssl/wolfcrypt/aes.h>
+#include <wolfssl/wolfcrypt/wc_encrypt.h>
+#include <wolfssl/wolfcrypt/logging.h>
+
+#include <wolfssl/wolfcrypt/random.h>
+#include <wolfssl/wolfcrypt/hash.h>
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+#ifndef NO_RC4
+    #include <wolfssl/wolfcrypt/arc4.h>
+#endif
+
+#ifdef HAVE_NTRU
+    #include "libntruencrypt/ntru_crypto.h"
+#endif
+
+#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
+    #include <wolfssl/wolfcrypt/sha512.h>
+#endif
+
+#ifndef NO_SHA256
+    #include <wolfssl/wolfcrypt/sha256.h>
+#endif
+
+#ifdef HAVE_ECC
+    #include <wolfssl/wolfcrypt/ecc.h>
+#endif
+
+#ifdef HAVE_ED25519
+    #include <wolfssl/wolfcrypt/ed25519.h>
+#endif
+
+#ifdef HAVE_ED448
+    #include <wolfssl/wolfcrypt/ed448.h>
+#endif
+
+#ifndef NO_RSA
+    #include <wolfssl/wolfcrypt/rsa.h>
+#if defined(WOLFSSL_XILINX_CRYPT) || defined(WOLFSSL_CRYPTOCELL)
+extern int wc_InitRsaHw(RsaKey* key);
+#endif
+#endif
+
+#ifdef WOLF_CRYPTO_CB
+    #include <wolfssl/wolfcrypt/cryptocb.h>
+#endif
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+    #include <wolfssl/openssl/objects.h>
+#endif
+
+#ifdef _MSC_VER
+    /* 4996 warning to use MS extensions e.g., strcpy_s instead of XSTRNCPY */
+    #pragma warning(disable: 4996)
+#endif
+
+#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; }
+
+#if defined(HAVE_SELFTEST) || ( !defined(NO_SKID) && \
+                                ( !defined(HAVE_FIPS) || \
+                                  !defined(HAVE_FIPS_VERSION) ))
+    #ifndef WOLFSSL_AES_KEY_SIZE_ENUM
+    #define WOLFSSL_AES_KEY_SIZE_ENUM
+    enum Asn_Misc {
+        AES_IV_SIZE         = 16,
+        AES_128_KEY_SIZE    = 16,
+        AES_192_KEY_SIZE    = 24,
+        AES_256_KEY_SIZE    = 32
+    };
+    #endif
+#endif
+#ifdef WOLFSSL_RENESAS_TSIP_TLS
+void tsip_inform_key_position(const word32 key_n_start,
+                const word32 key_n_len, const word32 key_e_start,
+                const word32 key_e_len);
+int tsip_tls_CertVerify(const byte *cert, word32 certSz,
+                        const byte *signature, word32 sigSz,
+                        word32 key_n_start, word32 key_n_len,
+                        word32 key_e_start, word32 key_e_len,
+                        byte *tsip_encRsaKeyIdx);
+#endif
+int GetLength(const byte* input, word32* inOutIdx, int* len,
+                           word32 maxIdx)
+{
+    return GetLength_ex(input, inOutIdx, len, maxIdx, 1);
+}
+
+
+/* give option to check length value found against index. 1 to check 0 to not */
+int GetLength_ex(const byte* input, word32* inOutIdx, int* len,
+                           word32 maxIdx, int check)
+{
+    int     length = 0;
+    word32  idx = *inOutIdx;
+    byte    b;
+
+    *len = 0;    /* default length */
+
+    if ((idx + 1) > maxIdx) {   /* for first read */
+        WOLFSSL_MSG("GetLength bad index on input");
+        return BUFFER_E;
+    }
+
+    b = input[idx++];
+    if (b >= ASN_LONG_LENGTH) {
+        word32 bytes = b & 0x7F;
+
+        if ((idx + bytes) > maxIdx) {   /* for reading bytes */
+            WOLFSSL_MSG("GetLength bad long length");
+            return BUFFER_E;
+        }
+
+        if (bytes > sizeof(length)) {
+            return ASN_PARSE_E;
+        }
+        while (bytes--) {
+            b = input[idx++];
+            length = (length << 8) | b;
+        }
+        if (length < 0) {
+            return ASN_PARSE_E;
+        }
+    }
+    else
+        length = b;
+
+    if (check && (idx + length) > maxIdx) {   /* for user of length */
+        WOLFSSL_MSG("GetLength value exceeds buffer length");
+        return BUFFER_E;
+    }
+
+    *inOutIdx = idx;
+    if (length > 0)
+        *len = length;
+
+    return length;
+}
+
+
+/* input : buffer to read from
+ * inOutIdx : index to start reading from, gets advanced by 1 if successful
+ * maxIdx : maximum index value
+ * tag : ASN tag value found
+ *
+ * returns 0 on success
+ */
+int GetASNTag(const byte* input, word32* inOutIdx, byte* tag, word32 maxIdx)
+{
+    word32 idx;
+
+    if (tag == NULL || inOutIdx == NULL || input == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    idx = *inOutIdx;
+    if (idx + ASN_TAG_SZ > maxIdx) {
+        WOLFSSL_MSG("Buffer too small for ASN tag");
+        return BUFFER_E;
+    }
+
+    *tag = input[idx];
+    *inOutIdx = idx + ASN_TAG_SZ;
+    return 0;
+}
+
+
+static int GetASNHeader_ex(const byte* input, byte tag, word32* inOutIdx, int* len,
+                        word32 maxIdx, int check)
+{
+    word32 idx = *inOutIdx;
+    byte   tagFound;
+    int    length;
+
+    if (GetASNTag(input, &idx, &tagFound, maxIdx) != 0)
+        return ASN_PARSE_E;
+
+    if (tagFound != tag)
+        return ASN_PARSE_E;
+
+    if (GetLength_ex(input, &idx, &length, maxIdx, check) < 0)
+        return ASN_PARSE_E;
+
+    *len      = length;
+    *inOutIdx = idx;
+    return length;
+}
+
+
+/* Get the DER/BER encoding of an ASN.1 header.
+ *
+ * input     Buffer holding DER/BER encoded data.
+ * tag       ASN.1 tag value expected in header.
+ * inOutIdx  Current index into buffer to parse.
+ * len       The number of bytes in the ASN.1 data.
+ * maxIdx    Length of data in buffer.
+ * returns BUFFER_E when there is not enough data to parse.
+ *         ASN_PARSE_E when the expected tag is not found or length is invalid.
+ *         Otherwise, the number of bytes in the ASN.1 data.
+ */
+static int GetASNHeader(const byte* input, byte tag, word32* inOutIdx, int* len,
+                        word32 maxIdx)
+{
+    return GetASNHeader_ex(input, tag, inOutIdx, len, maxIdx, 1);
+}
+
+static int GetHeader(const byte* input, byte* tag, word32* inOutIdx, int* len,
+                     word32 maxIdx, int check)
+{
+    word32 idx = *inOutIdx;
+    int    length;
+
+    if ((idx + 1) > maxIdx)
+        return BUFFER_E;
+
+    *tag = input[idx++];
+
+    if (GetLength_ex(input, &idx, &length, maxIdx, check) < 0)
+        return ASN_PARSE_E;
+
+    *len      = length;
+    *inOutIdx = idx;
+    return length;
+}
+
+int GetSequence(const byte* input, word32* inOutIdx, int* len,
+                           word32 maxIdx)
+{
+    return GetASNHeader(input, ASN_SEQUENCE | ASN_CONSTRUCTED, inOutIdx, len,
+                        maxIdx);
+}
+
+
+int GetSequence_ex(const byte* input, word32* inOutIdx, int* len,
+                           word32 maxIdx, int check)
+{
+    return GetASNHeader_ex(input, ASN_SEQUENCE | ASN_CONSTRUCTED, inOutIdx, len,
+                        maxIdx, check);
+}
+
+
+int GetSet(const byte* input, word32* inOutIdx, int* len,
+                        word32 maxIdx)
+{
+    return GetASNHeader(input, ASN_SET | ASN_CONSTRUCTED, inOutIdx, len,
+                        maxIdx);
+}
+
+
+int GetSet_ex(const byte* input, word32* inOutIdx, int* len,
+                        word32 maxIdx, int check)
+{
+    return GetASNHeader_ex(input, ASN_SET | ASN_CONSTRUCTED, inOutIdx, len,
+                        maxIdx, check);
+}
+
+/* Get the DER/BER encoded ASN.1 NULL element.
+ * Ensure that the all fields are as expected and move index past the element.
+ *
+ * input     Buffer holding DER/BER encoded data.
+ * inOutIdx  Current index into buffer to parse.
+ * maxIdx    Length of data in buffer.
+ * returns BUFFER_E when there is not enough data to parse.
+ *         ASN_TAG_NULL_E when the NULL tag is not found.
+ *         ASN_EXPECT_0_E when the length is not zero.
+ *         Otherwise, 0 to indicate success.
+ */
+static int GetASNNull(const byte* input, word32* inOutIdx, word32 maxIdx)
+{
+    word32 idx = *inOutIdx;
+    byte   b;
+
+    if ((idx + 2) > maxIdx)
+        return BUFFER_E;
+
+    b = input[idx++];
+    if (b != ASN_TAG_NULL)
+        return ASN_TAG_NULL_E;
+
+    if (input[idx++] != 0)
+        return ASN_EXPECT_0_E;
+
+    *inOutIdx = idx;
+    return 0;
+}
+
+/* Set the DER/BER encoding of the ASN.1 NULL element.
+ *
+ * output  Buffer to write into.
+ * returns the number of bytes added to the buffer.
+ */
+static int SetASNNull(byte* output)
+{
+    output[0] = ASN_TAG_NULL;
+    output[1] = 0;
+
+    return 2;
+}
+
+/* Get the DER/BER encoding of an ASN.1 BOOLEAN.
+ *
+ * input     Buffer holding DER/BER encoded data.
+ * inOutIdx  Current index into buffer to parse.
+ * maxIdx    Length of data in buffer.
+ * returns BUFFER_E when there is not enough data to parse.
+ *         ASN_PARSE_E when the BOOLEAN tag is not found or length is not 1.
+ *         Otherwise, 0 to indicate the value was false and 1 to indicate true.
+ */
+static int GetBoolean(const byte* input, word32* inOutIdx, word32 maxIdx)
+{
+    word32 idx = *inOutIdx;
+    byte   b;
+
+    if ((idx + 3) > maxIdx)
+        return BUFFER_E;
+
+    b = input[idx++];
+    if (b != ASN_BOOLEAN)
+        return ASN_PARSE_E;
+
+    if (input[idx++] != 1)
+        return ASN_PARSE_E;
+
+    b = input[idx++] != 0;
+
+    *inOutIdx = idx;
+    return b;
+}
+
+#ifdef ASN1_SET_BOOLEAN
+/* Set the DER/BER encoding of the ASN.1 NULL element.
+ * Note: Function not required as yet.
+ *
+ * val     Boolean value to encode.
+ * output  Buffer to write into.
+ * returns the number of bytes added to the buffer.
+ */
+static int SetBoolean(int val, byte* output)
+{
+    output[0] = ASN_BOOLEAN;
+    output[1] = 1;
+    output[2] = val ? -1 : 0;
+
+    return 3;
+}
+#endif
+
+/* Get the DER/BER encoding of an ASN.1 OCTET_STRING header.
+ *
+ * input     Buffer holding DER/BER encoded data.
+ * inOutIdx  Current index into buffer to parse.
+ * len       The number of bytes in the ASN.1 data.
+ * maxIdx    Length of data in buffer.
+ * returns BUFFER_E when there is not enough data to parse.
+ *         ASN_PARSE_E when the OCTET_STRING tag is not found or length is
+ *         invalid.
+ *         Otherwise, the number of bytes in the ASN.1 data.
+ */
+int GetOctetString(const byte* input, word32* inOutIdx, int* len,
+                          word32 maxIdx)
+{
+    return GetASNHeader(input, ASN_OCTET_STRING, inOutIdx, len, maxIdx);
+}
+
+/* Get the DER/BER encoding of an ASN.1 INTEGER header.
+ * Removes the leading zero byte when found.
+ *
+ * input     Buffer holding DER/BER encoded data.
+ * inOutIdx  Current index into buffer to parse.
+ * len       The number of bytes in the ASN.1 data (excluding any leading zero).
+ * maxIdx    Length of data in buffer.
+ * returns BUFFER_E when there is not enough data to parse.
+ *         ASN_PARSE_E when the INTEGER tag is not found, length is invalid,
+ *         or invalid use of or missing leading zero.
+ *         Otherwise, 0 to indicate success.
+ */
+static int GetASNInt(const byte* input, word32* inOutIdx, int* len,
+                     word32 maxIdx)
+{
+    int    ret;
+
+    ret = GetASNHeader(input, ASN_INTEGER, inOutIdx, len, maxIdx);
+    if (ret < 0)
+        return ret;
+
+    if (*len > 0) {
+        /* remove leading zero, unless there is only one 0x00 byte */
+        if ((input[*inOutIdx] == 0x00) && (*len > 1)) {
+            (*inOutIdx)++;
+            (*len)--;
+
+            if (*len > 0 && (input[*inOutIdx] & 0x80) == 0)
+                return ASN_PARSE_E;
+        }
+    }
+
+    return 0;
+}
+
+/* Get the DER/BER encoding of an ASN.1 INTEGER that has a value of no more than
+ * 7 bits.
+ *
+ * input     Buffer holding DER/BER encoded data.
+ * inOutIdx  Current index into buffer to parse.
+ * maxIdx    Length of data in buffer.
+ * returns BUFFER_E when there is not enough data to parse.
+ *         ASN_PARSE_E when the INTEGER tag is not found or length is invalid.
+ *         Otherwise, the 7-bit value.
+ */
+static int GetInteger7Bit(const byte* input, word32* inOutIdx, word32 maxIdx)
+{
+    word32 idx = *inOutIdx;
+    byte   b;
+
+    if ((idx + 3) > maxIdx)
+        return BUFFER_E;
+
+    if (GetASNTag(input, &idx, &b, maxIdx) != 0)
+        return ASN_PARSE_E;
+    if (b != ASN_INTEGER)
+        return ASN_PARSE_E;
+    if (input[idx++] != 1)
+        return ASN_PARSE_E;
+    b = input[idx++];
+
+    *inOutIdx = idx;
+    return b;
+}
+
+
+#if !defined(NO_DSA) && !defined(NO_SHA)
+static const char sigSha1wDsaName[] = "SHAwDSA";
+#endif /* NO_DSA */
+#ifndef NO_RSA
+#ifdef WOLFSSL_MD2
+    static const char  sigMd2wRsaName[] = "md2WithRSAEncryption";
+#endif
+#ifndef NO_MD5
+    static const char  sigMd5wRsaName[] = "md5WithRSAEncryption";
+#endif
+#ifndef NO_SHA
+    static const char  sigSha1wRsaName[] = "sha1WithRSAEncryption";
+#endif
+#ifdef WOLFSSL_SHA224
+    static const char sigSha224wRsaName[] = "sha224WithRSAEncryption";
+#endif
+#ifndef NO_SHA256
+    static const char sigSha256wRsaName[] = "sha256WithRSAEncryption";
+#endif
+#ifdef WOLFSSL_SHA384
+    static const char sigSha384wRsaName[] = "sha384WithRSAEncryption";
+#endif
+#ifdef WOLFSSL_SHA512
+    static const char sigSha512wRsaName[] = "sha512WithRSAEncryption";
+#endif
+#endif /* NO_RSA */
+#ifdef HAVE_ECC
+#ifndef NO_SHA
+    static const char sigSha1wEcdsaName[] = "SHAwECDSA";
+#endif
+#ifdef WOLFSSL_SHA224
+    static const char sigSha224wEcdsaName[] = "SHA224wECDSA";
+#endif
+#ifndef NO_SHA256
+    static const char sigSha256wEcdsaName[] = "SHA256wECDSA";
+#endif
+#ifdef WOLFSSL_SHA384
+    static const char sigSha384wEcdsaName[] = "SHA384wECDSA";
+#endif
+#ifdef WOLFSSL_SHA512
+    static const char sigSha512wEcdsaName[] = "SHA512wECDSA";
+#endif
+#endif /* HAVE_ECC */
+static const char sigUnknownName[] = "Unknown";
+
+
+/* Get the human readable string for a signature type
+ *
+ * oid  Oid value for signature
+ */
+const char* GetSigName(int oid) {
+    switch (oid) {
+    #if !defined(NO_DSA) && !defined(NO_SHA)
+        case CTC_SHAwDSA:
+            return sigSha1wDsaName;
+    #endif /* NO_DSA && NO_SHA */
+    #ifndef NO_RSA
+        #ifdef WOLFSSL_MD2
+        case CTC_MD2wRSA:
+            return sigMd2wRsaName;
+        #endif
+        #ifndef NO_MD5
+        case CTC_MD5wRSA:
+            return sigMd5wRsaName;
+        #endif
+        #ifndef NO_SHA
+        case CTC_SHAwRSA:
+            return sigSha1wRsaName;
+        #endif
+        #ifdef WOLFSSL_SHA224
+        case CTC_SHA224wRSA:
+            return sigSha224wRsaName;
+        #endif
+        #ifndef NO_SHA256
+        case CTC_SHA256wRSA:
+            return sigSha256wRsaName;
+        #endif
+        #ifdef WOLFSSL_SHA384
+        case CTC_SHA384wRSA:
+            return sigSha384wRsaName;
+        #endif
+        #ifdef WOLFSSL_SHA512
+        case CTC_SHA512wRSA:
+            return sigSha512wRsaName;
+        #endif
+    #endif /* NO_RSA */
+    #ifdef HAVE_ECC
+        #ifndef NO_SHA
+        case CTC_SHAwECDSA:
+            return sigSha1wEcdsaName;
+        #endif
+        #ifdef WOLFSSL_SHA224
+        case CTC_SHA224wECDSA:
+            return sigSha224wEcdsaName;
+        #endif
+        #ifndef NO_SHA256
+        case CTC_SHA256wECDSA:
+            return sigSha256wEcdsaName;
+        #endif
+        #ifdef WOLFSSL_SHA384
+        case CTC_SHA384wECDSA:
+            return sigSha384wEcdsaName;
+        #endif
+        #ifdef WOLFSSL_SHA512
+        case CTC_SHA512wECDSA:
+            return sigSha512wEcdsaName;
+        #endif
+    #endif /* HAVE_ECC */
+        default:
+            return sigUnknownName;
+    }
+}
+
+
+#if !defined(NO_DSA) || defined(HAVE_ECC) || !defined(NO_CERTS) || \
+   (!defined(NO_RSA) && \
+        (defined(WOLFSSL_CERT_GEN) || \
+        ((defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !defined(HAVE_USER_RSA))))
+/* Set the DER/BER encoding of the ASN.1 INTEGER header.
+ *
+ * len        Length of data to encode.
+ * firstByte  First byte of data, most significant byte of integer, to encode.
+ * output     Buffer to write into.
+ * returns the number of bytes added to the buffer.
+ */
+static int SetASNInt(int len, byte firstByte, byte* output)
+{
+    word32 idx = 0;
+
+    if (output)
+        output[idx] = ASN_INTEGER;
+    idx++;
+    if (firstByte & 0x80)
+        len++;
+    idx += SetLength(len, output ? output + idx : NULL);
+    if (firstByte & 0x80) {
+        if (output)
+            output[idx] = 0x00;
+        idx++;
+    }
+
+    return idx;
+}
+#endif
+
+#if !defined(NO_DSA) || defined(HAVE_ECC) || (defined(WOLFSSL_CERT_GEN) && \
+    !defined(NO_RSA)) || ((defined(WOLFSSL_KEY_GEN) || \
+    defined(OPENSSL_EXTRA)) && !defined(NO_RSA) && !defined(HAVE_USER_RSA))
+/* Set the DER/BER encoding of the ASN.1 INTEGER element with an mp_int.
+ * The number is assumed to be positive.
+ *
+ * n       Multi-precision integer to encode.
+ * maxSz   Maximum size of the encoded integer.
+ *         A negative value indicates no check of length requested.
+ * output  Buffer to write into.
+ * returns BUFFER_E when the data is too long for the buffer.
+ *         MP_TO_E when encoding the integer fails.
+ *         Otherwise, the number of bytes added to the buffer.
+ */
+static int SetASNIntMP(mp_int* n, int maxSz, byte* output)
+{
+    int idx = 0;
+    int leadingBit;
+    int length;
+    int err;
+
+    leadingBit = mp_leading_bit(n);
+    length = mp_unsigned_bin_size(n);
+    idx = SetASNInt(length, leadingBit ? 0x80 : 0x00, output);
+    if (maxSz >= 0 && (idx + length) > maxSz)
+        return BUFFER_E;
+
+    if (output) {
+        err = mp_to_unsigned_bin(n, output + idx);
+        if (err != MP_OKAY)
+            return MP_TO_E;
+    }
+    idx += length;
+
+    return idx;
+}
+#endif
+
+#if !defined(NO_RSA) && defined(HAVE_USER_RSA) && \
+    (defined(WOLFSSL_CERT_GEN) || defined(OPENSSL_EXTRA))
+/* Set the DER/BER encoding of the ASN.1 INTEGER element with an mp_int from
+ * an RSA key.
+ * The number is assumed to be positive.
+ *
+ * n       Multi-precision integer to encode.
+ * output  Buffer to write into.
+ * returns BUFFER_E when the data is too long for the buffer.
+ *         MP_TO_E when encoding the integer fails.
+ *         Otherwise, the number of bytes added to the buffer.
+ */
+static int SetASNIntRSA(void* n, byte* output)
+{
+    int idx = 0;
+    int leadingBit;
+    int length;
+    int err;
+
+    leadingBit = wc_Rsa_leading_bit(n);
+    length = wc_Rsa_unsigned_bin_size(n);
+    idx = SetASNInt(length, leadingBit ? 0x80 : 0x00, output);
+    if ((idx + length) > MAX_RSA_INT_SZ)
+        return BUFFER_E;
+
+    if (output) {
+        err = wc_Rsa_to_unsigned_bin(n, output + idx, length);
+        if (err != MP_OKAY)
+            return MP_TO_E;
+    }
+    idx += length;
+
+    return idx;
+}
+#endif /* !NO_RSA && HAVE_USER_RSA && WOLFSSL_CERT_GEN */
+
+/* Windows header clash for WinCE using GetVersion */
+int GetMyVersion(const byte* input, word32* inOutIdx,
+                               int* version, word32 maxIdx)
+{
+    word32 idx = *inOutIdx;
+    byte   tag;
+
+    if ((idx + MIN_VERSION_SZ) > maxIdx)
+        return ASN_PARSE_E;
+
+    if (GetASNTag(input, &idx, &tag, maxIdx) != 0)
+        return ASN_PARSE_E;
+
+    if (tag != ASN_INTEGER)
+        return ASN_PARSE_E;
+
+    if (input[idx++] != 0x01)
+        return ASN_VERSION_E;
+
+    *version  = input[idx++];
+    *inOutIdx = idx;
+
+    return *version;
+}
+
+
+#ifndef NO_PWDBASED
+/* Get small count integer, 32 bits or less */
+int GetShortInt(const byte* input, word32* inOutIdx, int* number, word32 maxIdx)
+{
+    word32 idx = *inOutIdx;
+    word32 len;
+    byte   tag;
+
+    *number = 0;
+
+    /* check for type and length bytes */
+    if ((idx + 2) > maxIdx)
+        return BUFFER_E;
+
+    if (GetASNTag(input, &idx, &tag, maxIdx) != 0)
+        return ASN_PARSE_E;
+
+    if (tag != ASN_INTEGER)
+        return ASN_PARSE_E;
+
+    len = input[idx++];
+    if (len > 4)
+        return ASN_PARSE_E;
+
+    if (len + idx > maxIdx)
+        return ASN_PARSE_E;
+
+    while (len--) {
+        *number  = *number << 8 | input[idx++];
+    }
+
+    *inOutIdx = idx;
+
+    return *number;
+}
+
+
+/* Set small integer, 32 bits or less. DER encoding with no leading 0s
+ * returns total amount written including ASN tag and length byte on success */
+int SetShortInt(byte* input, word32* inOutIdx, word32 number, word32 maxIdx)
+{
+    word32 idx = *inOutIdx;
+    word32 len = 0;
+    int    i;
+    byte ar[MAX_LENGTH_SZ];
+
+    /* check for room for type and length bytes */
+    if ((idx + 2) > maxIdx)
+        return BUFFER_E;
+
+    input[idx++] = ASN_INTEGER;
+    idx++; /* place holder for length byte */
+    if (MAX_LENGTH_SZ + idx > maxIdx)
+        return ASN_PARSE_E;
+
+    /* find first non zero byte */
+    XMEMSET(ar, 0, MAX_LENGTH_SZ);
+    c32toa(number, ar);
+    for (i = 0; i < MAX_LENGTH_SZ; i++) {
+        if (ar[i] != 0) {
+            break;
+        }
+    }
+
+    /* handle case of 0 */
+    if (i == MAX_LENGTH_SZ) {
+        input[idx++] = 0; len++;
+    }
+
+    for (; i < MAX_LENGTH_SZ && idx < maxIdx; i++) {
+        input[idx++] = ar[i]; len++;
+    }
+
+    /* jump back to beginning of input buffer using unaltered inOutIdx value
+     * and set number of bytes for integer, then update the index value */
+    input[*inOutIdx + 1] = (byte)len;
+    *inOutIdx = idx;
+
+    return len + 2; /* size of integer bytes plus ASN TAG and length byte */
+}
+#endif /* !NO_PWDBASED */
+
+/* May not have one, not an error */
+static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version,
+                              word32 maxIdx)
+{
+    word32 idx = *inOutIdx;
+    byte tag;
+
+    WOLFSSL_ENTER("GetExplicitVersion");
+
+    if (GetASNTag(input, &idx, &tag, maxIdx) != 0)
+        return ASN_PARSE_E;
+
+    if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) {
+        *inOutIdx = ++idx;  /* skip header */
+        return GetMyVersion(input, inOutIdx, version, maxIdx);
+    }
+
+    /* go back as is */
+    *version = 0;
+
+    return 0;
+}
+
+int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx, word32 maxIdx)
+{
+    word32 idx = *inOutIdx;
+    int    ret;
+    int    length;
+
+    ret = GetASNInt(input, &idx, &length, maxIdx);
+    if (ret != 0)
+        return ret;
+
+    if (mp_init(mpi) != MP_OKAY)
+        return MP_INIT_E;
+
+    if (mp_read_unsigned_bin(mpi, (byte*)input + idx, length) != 0) {
+        mp_clear(mpi);
+        return ASN_GETINT_E;
+    }
+
+#ifdef HAVE_WOLF_BIGINT
+    if (wc_bigint_from_unsigned_bin(&mpi->raw, input + idx, length) != 0) {
+        mp_clear(mpi);
+        return ASN_GETINT_E;
+    }
+#endif /* HAVE_WOLF_BIGINT */
+
+    *inOutIdx = idx + length;
+
+    return 0;
+}
+
+#if (!defined(WOLFSSL_KEY_GEN) && !defined(OPENSSL_EXTRA) && defined(RSA_LOW_MEM)) \
+    || defined(WOLFSSL_RSA_PUBLIC_ONLY) || (!defined(NO_DSA) && defined(WOLFSSL_QT))
+#if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+static int SkipInt(const byte* input, word32* inOutIdx, word32 maxIdx)
+{
+    word32 idx = *inOutIdx;
+    int    ret;
+    int    length;
+
+    ret = GetASNInt(input, &idx, &length, maxIdx);
+    if (ret != 0)
+        return ret;
+
+    *inOutIdx = idx + length;
+
+    return 0;
+}
+#endif
+#endif
+
+static int CheckBitString(const byte* input, word32* inOutIdx, int* len,
+                          word32 maxIdx, int zeroBits, byte* unusedBits)
+{
+    word32 idx = *inOutIdx;
+    int    length;
+    byte   b;
+
+    if (GetASNTag(input, &idx, &b, maxIdx) != 0) {
+        return ASN_BITSTR_E;
+    }
+
+    if (b != ASN_BIT_STRING) {
+        return ASN_BITSTR_E;
+    }
+
+    if (GetLength(input, &idx, &length, maxIdx) < 0)
+        return ASN_PARSE_E;
+
+    /* extra sanity check that length is greater than 0 */
+    if (length <= 0) {
+        WOLFSSL_MSG("Error length was 0 in CheckBitString");
+        return BUFFER_E;
+    }
+
+    if (idx + 1 > maxIdx) {
+        WOLFSSL_MSG("Attempted buffer read larger than input buffer");
+        return BUFFER_E;
+    }
+
+    b = input[idx];
+    if (zeroBits && b != 0x00)
+        return ASN_EXPECT_0_E;
+    if (b >= 0x08)
+        return ASN_PARSE_E;
+    if (b != 0) {
+        if ((byte)(input[idx + length - 1] << (8 - b)) != 0)
+            return ASN_PARSE_E;
+    }
+    idx++;
+    length--; /* length has been checked for greater than 0 */
+
+    *inOutIdx = idx;
+    if (len != NULL)
+        *len = length;
+    if (unusedBits != NULL)
+        *unusedBits = b;
+
+    return 0;
+}
+
+/* RSA (with CertGen or KeyGen) OR ECC OR ED25519 OR ED448 (with CertGen or
+ * KeyGen) */
+#if (!defined(NO_RSA) && !defined(HAVE_USER_RSA) && \
+        (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA))) || \
+    (defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)) || \
+    ((defined(HAVE_ED25519) || defined(HAVE_ED448)) && \
+        (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)))
+
+/* Set the DER/BER encoding of the ASN.1 BIT_STRING header.
+ *
+ * len         Length of data to encode.
+ * unusedBits  The number of unused bits in the last byte of data.
+ *             That is, the number of least significant zero bits before a one.
+ *             The last byte is the most-significant non-zero byte of a number.
+ * output      Buffer to write into.
+ * returns the number of bytes added to the buffer.
+ */
+word32 SetBitString(word32 len, byte unusedBits, byte* output)
+{
+    word32 idx = 0;
+
+    if (output)
+        output[idx] = ASN_BIT_STRING;
+    idx++;
+
+    idx += SetLength(len + 1, output ? output + idx : NULL);
+    if (output)
+        output[idx] = unusedBits;
+    idx++;
+
+    return idx;
+}
+#endif /* !NO_RSA || HAVE_ECC || HAVE_ED25519 || HAVE_ED448 */
+
+#ifdef ASN_BER_TO_DER
+/* Pull informtation from the ASN.1 BER encoded item header */
+static int GetBerHeader(const byte* data, word32* idx, word32 maxIdx,
+                        byte* pTag, word32* pLen, int* indef)
+{
+    int len = 0;
+    byte tag;
+    word32 i = *idx;
+
+    *indef = 0;
+
+    /* Check there is enough data for a minimal header */
+    if (i + 2 > maxIdx) {
+        return ASN_PARSE_E;
+    }
+
+    /* Retrieve tag */
+    tag = data[i++];
+
+    /* Indefinite length handled specially */
+    if (data[i] == 0x80) {
+        /* Check valid tag for indefinite */
+        if (((tag & 0xc0) == 0) && ((tag & ASN_CONSTRUCTED) == 0x00)) {
+            return ASN_PARSE_E;
+        }
+        i++;
+        *indef = 1;
+    }
+    else if (GetLength(data, &i, &len, maxIdx) < 0) {
+        return ASN_PARSE_E;
+    }
+
+    /* Return tag, length and index after BER item header */
+    *pTag = tag;
+    *pLen = len;
+    *idx = i;
+    return 0;
+}
+
+#ifndef INDEF_ITEMS_MAX
+#define INDEF_ITEMS_MAX       20
+#endif
+
+/* Indef length item data */
+typedef struct Indef {
+    word32 start;
+    int depth;
+    int headerLen;
+    word32 len;
+} Indef;
+
+/* Indef length items */
+typedef struct IndefItems
+{
+    Indef len[INDEF_ITEMS_MAX];
+    int cnt;
+    int idx;
+    int depth;
+} IndefItems;
+
+
+/* Get header length of current item */
+static int IndefItems_HeaderLen(IndefItems* items)
+{
+    return items->len[items->idx].headerLen;
+}
+
+/* Get data length of current item */
+static word32 IndefItems_Len(IndefItems* items)
+{
+    return items->len[items->idx].len;
+}
+
+/* Add a indefinite length item */
+static int IndefItems_AddItem(IndefItems* items, word32 start)
+{
+    int ret = 0;
+    int i;
+
+    if (items->cnt == INDEF_ITEMS_MAX) {
+        ret = MEMORY_E;
+    }
+    else {
+        i = items->cnt++;
+        items->len[i].start = start;
+        items->len[i].depth = items->depth++;
+        items->len[i].headerLen = 1;
+        items->len[i].len = 0;
+        items->idx = i;
+    }
+
+    return ret;
+}
+
+/* Increase data length of current item */
+static void IndefItems_AddData(IndefItems* items, word32 length)
+{
+    items->len[items->idx].len += length;
+}
+
+/* Update header length of current item to reflect data length */
+static void IndefItems_UpdateHeaderLen(IndefItems* items)
+{
+    items->len[items->idx].headerLen +=
+                                    SetLength(items->len[items->idx].len, NULL);
+}
+
+/* Go to indefinite parent of current item */
+static void IndefItems_Up(IndefItems* items)
+{
+    int i;
+    int depth = items->len[items->idx].depth - 1;
+
+    for (i = items->cnt - 1; i >= 0; i--) {
+        if (items->len[i].depth == depth) {
+            break;
+        }
+    }
+    items->idx = i;
+    items->depth = depth + 1;
+}
+
+/* Calculate final length by adding length of indefinite child items */
+static void IndefItems_CalcLength(IndefItems* items)
+{
+    int i;
+    int idx = items->idx;
+
+    for (i = idx + 1; i < items->cnt; i++) {
+        if (items->len[i].depth == items->depth) {
+            items->len[idx].len += items->len[i].headerLen;
+            items->len[idx].len += items->len[i].len;
+        }
+    }
+    items->len[idx].headerLen += SetLength(items->len[idx].len, NULL);
+}
+
+/* Add more data to indefinite length item */
+static void IndefItems_MoreData(IndefItems* items, word32 length)
+{
+    if (items->cnt > 0 && items->idx >= 0) {
+        items->len[items->idx].len += length;
+    }
+}
+
+/* Convert a BER encoding with indefinite length items to DER.
+ *
+ * ber    BER encoded data.
+ * berSz  Length of BER encoded data.
+ * der    Buffer to hold DER encoded version of data.
+ *        NULL indicates only the length is required.
+ * derSz  The size of the buffer to hold the DER encoded data.
+ *        Will be set if der is NULL, otherwise the value is checked as der is
+ *        filled.
+ * returns ASN_PARSE_E if the BER data is invalid and BAD_FUNC_ARG if ber or
+ * derSz are NULL.
+ */
+int wc_BerToDer(const byte* ber, word32 berSz, byte* der, word32* derSz)
+{
+    int ret = 0;
+    word32 i, j;
+#ifdef WOLFSSL_SMALL_STACK
+    IndefItems* indefItems = NULL;
+#else
+    IndefItems indefItems[1];
+#endif
+    byte tag, basic;
+    word32 length;
+    int indef;
+
+    if (ber == NULL || derSz == NULL)
+        return BAD_FUNC_ARG;
+
+#ifdef WOLFSSL_SMALL_STACK
+    indefItems = XMALLOC(sizeof(IndefItems), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (indefItems == NULL) {
+        ret = MEMORY_E;
+        goto end;
+    }
+#endif
+
+    XMEMSET(indefItems, 0, sizeof(*indefItems));
+
+    /* Calculate indefinite item lengths */
+    for (i = 0; i < berSz; ) {
+        word32 start = i;
+
+        /* Get next BER item */
+        ret = GetBerHeader(ber, &i, berSz, &tag, &length, &indef);
+        if (ret != 0) {
+            goto end;
+        }
+
+        if (indef) {
+            /* Indefinite item - add to list */
+            ret = IndefItems_AddItem(indefItems, i);
+            if (ret != 0) {
+                goto end;
+            }
+
+            if ((tag & 0xC0) == 0 &&
+                tag != (ASN_SEQUENCE | ASN_CONSTRUCTED) &&
+                tag != (ASN_SET      | ASN_CONSTRUCTED)) {
+                /* Constructed basic type - get repeating tag */
+                basic = tag & (~ASN_CONSTRUCTED);
+
+                /* Add up lengths of each item below */
+                for (; i < berSz; ) {
+                    /* Get next BER_item */
+                    ret = GetBerHeader(ber, &i, berSz, &tag, &length, &indef);
+                    if (ret != 0) {
+                        goto end;
+                    }
+
+                    /* End of content closes item */
+                    if (tag == ASN_EOC) {
+                        /* Must be zero length */
+                        if (length != 0) {
+                            ret = ASN_PARSE_E;
+                            goto end;
+                        }
+                        break;
+                    }
+
+                    /* Must not be indefinite and tag must match parent */
+                    if (indef || tag != basic) {
+                        ret = ASN_PARSE_E;
+                        goto end;
+                    }
+
+                    /* Add to length */
+                    IndefItems_AddData(indefItems, length);
+                    /* Skip data */
+                    i += length;
+                }
+
+                /* Ensure we got an EOC and not end of data */
+                if (tag != ASN_EOC) {
+                    ret = ASN_PARSE_E;
+                    goto end;
+                }
+
+                /* Set the header length to include the length field */
+                IndefItems_UpdateHeaderLen(indefItems);
+                /* Go to indefinte parent item */
+                IndefItems_Up(indefItems);
+            }
+        }
+        else if (tag == ASN_EOC) {
+            /* End-of-content must be 0 length */
+            if (length != 0) {
+                ret = ASN_PARSE_E;
+                goto end;
+            }
+            /* Check there is an item to close - missing EOC */
+            if (indefItems->depth == 0) {
+                ret = ASN_PARSE_E;
+                goto end;
+            }
+
+            /* Finish calculation of data length for indefinite item */
+            IndefItems_CalcLength(indefItems);
+            /* Go to indefinte parent item */
+            IndefItems_Up(indefItems);
+        }
+        else {
+            /* Known length item to add in - make sure enough data for it */
+            if (i + length > berSz) {
+                ret = ASN_PARSE_E;
+                goto end;
+            }
+
+            /* Include all data - can't have indefinite inside definite */
+            i += length;
+            /* Add entire item to current indefinite item */
+            IndefItems_MoreData(indefItems, i - start);
+        }
+    }
+    /* Check we had a EOC for each indefinite item */
+    if (indefItems->depth != 0) {
+        ret = ASN_PARSE_E;
+        goto end;
+    }
+
+    /* Write out DER */
+
+    j = 0;
+    /* Reset index */
+    indefItems->idx = 0;
+    for (i = 0; i < berSz; ) {
+        word32 start = i;
+
+        /* Get item - checked above */
+        (void)GetBerHeader(ber, &i, berSz, &tag, &length, &indef);
+        if (indef) {
+            if (der != NULL) {
+                /* Check enough space for header */
+                if (j + IndefItems_HeaderLen(indefItems) > *derSz) {
+                    ret = BUFFER_E;
+                    goto end;
+                }
+
+                if ((tag & 0xC0) == 0 &&
+                    tag != (ASN_SEQUENCE | ASN_CONSTRUCTED) &&
+                    tag != (ASN_SET      | ASN_CONSTRUCTED)) {
+                    /* Remove constructed tag for basic types */
+                    tag &= ~ASN_CONSTRUCTED;
+                }
+                /* Add tag and length */
+                der[j] = tag;
+                (void)SetLength(IndefItems_Len(indefItems), der + j + 1);
+            }
+            /* Add header length of indefinite item */
+            j += IndefItems_HeaderLen(indefItems);
+
+            if ((tag & 0xC0) == 0 &&
+                tag != (ASN_SEQUENCE | ASN_CONSTRUCTED) &&
+                tag != (ASN_SET      | ASN_CONSTRUCTED)) {
+                /* For basic type - get each child item and add data */
+                for (; i < berSz; ) {
+                    (void)GetBerHeader(ber, &i, berSz, &tag, &length, &indef);
+                    if (tag == ASN_EOC) {
+                        break;
+                    }
+                    if (der != NULL) {
+                        if (j + length > *derSz) {
+                            ret = BUFFER_E;
+                            goto end;
+                        }
+                        XMEMCPY(der + j, ber + i, length);
+                    }
+                    j += length;
+                    i += length;
+                }
+            }
+
+            /* Move to next indef item in list */
+            indefItems->idx++;
+        }
+        else if (tag == ASN_EOC) {
+            /* End-Of-Content is not written out in DER */
+        }
+        else {
+            /* Write out definite length item as is. */
+            i += length;
+            if (der != NULL) {
+                /* Ensure space for item */
+                if (j + i - start > *derSz) {
+                    ret = BUFFER_E;
+                    goto end;
+                }
+                /* Copy item as is */
+                XMEMCPY(der + j, ber + start, i - start);
+            }
+            j += i - start;
+        }
+    }
+
+    /* Return the length of the DER encoded ASN.1 */
+    *derSz = j;
+    if (der == NULL) {
+        ret = LENGTH_ONLY_E;
+    }
+end:
+#ifdef WOLFSSL_SMALL_STACK
+    if (indefItems != NULL) {
+        XFREE(indefItems, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+#endif
+    return ret;
+}
+#endif
+
+#if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN)
+
+#if (!defined(NO_RSA) && !defined(HAVE_USER_RSA)) || \
+    defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
+
+#ifdef WOLFSSL_CERT_EXT
+/* Set the DER/BER encoding of the ASN.1 BIT_STRING with a 16-bit value.
+ *
+ * val         16-bit value to encode.
+ * output      Buffer to write into.
+ * returns the number of bytes added to the buffer.
+ */
+static word32 SetBitString16Bit(word16 val, byte* output)
+{
+    word32 idx;
+    int    len;
+    byte   lastByte;
+    byte   unusedBits = 0;
+
+    if ((val >> 8) != 0) {
+        len = 2;
+        lastByte = (byte)(val >> 8);
+    }
+    else {
+        len = 1;
+        lastByte = (byte)val;
+    }
+
+    while (((lastByte >> unusedBits) & 0x01) == 0x00)
+        unusedBits++;
+
+    idx = SetBitString(len, unusedBits, output);
+    output[idx++] = (byte)val;
+    if (len > 1)
+        output[idx++] = (byte)(val >> 8);
+
+    return idx;
+}
+#endif /* WOLFSSL_CERT_EXT */
+#endif /* !NO_RSA || HAVE_ECC || HAVE_ED25519 || defined(HAVE_ED448) */
+#endif /* WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN */
+
+
+
+/* hashType */
+#ifdef WOLFSSL_MD2
+    static const byte hashMd2hOid[] = {42, 134, 72, 134, 247, 13, 2, 2};
+#endif
+#ifndef NO_MD5
+    static const byte hashMd5hOid[] = {42, 134, 72, 134, 247, 13, 2, 5};
+#endif
+#ifndef NO_SHA
+    static const byte hashSha1hOid[] = {43, 14, 3, 2, 26};
+#endif
+#ifdef WOLFSSL_SHA224
+    static const byte hashSha224hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 4};
+#endif
+#ifndef NO_SHA256
+    static const byte hashSha256hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 1};
+#endif
+#ifdef WOLFSSL_SHA384
+    static const byte hashSha384hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 2};
+#endif
+#ifdef WOLFSSL_SHA512
+    static const byte hashSha512hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 3};
+#endif
+
+/* hmacType */
+#ifndef NO_HMAC
+    #ifdef WOLFSSL_SHA224
+    static const byte hmacSha224Oid[] = {42, 134, 72, 134, 247, 13, 2, 8};
+    #endif
+    #ifndef NO_SHA256
+    static const byte hmacSha256Oid[] = {42, 134, 72, 134, 247, 13, 2, 9};
+    #endif
+    #ifdef WOLFSSL_SHA384
+    static const byte hmacSha384Oid[] = {42, 134, 72, 134, 247, 13, 2, 10};
+    #endif
+    #ifdef WOLFSSL_SHA512
+    static const byte hmacSha512Oid[] = {42, 134, 72, 134, 247, 13, 2, 11};
+    #endif
+#endif
+
+/* sigType */
+#if !defined(NO_DSA) && !defined(NO_SHA)
+    static const byte sigSha1wDsaOid[] = {42, 134, 72, 206, 56, 4, 3};
+#endif /* NO_DSA */
+#ifndef NO_RSA
+    #ifdef WOLFSSL_MD2
+    static const byte sigMd2wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 2};
+    #endif
+    #ifndef NO_MD5
+    static const byte sigMd5wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 4};
+    #endif
+    #ifndef NO_SHA
+    static const byte sigSha1wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 5};
+    #endif
+    #ifdef WOLFSSL_SHA224
+    static const byte sigSha224wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,14};
+    #endif
+    #ifndef NO_SHA256
+    static const byte sigSha256wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,11};
+    #endif
+    #ifdef WOLFSSL_SHA384
+    static const byte sigSha384wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,12};
+    #endif
+    #ifdef WOLFSSL_SHA512
+    static const byte sigSha512wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,13};
+    #endif
+#endif /* NO_RSA */
+#ifdef HAVE_ECC
+    #ifndef NO_SHA
+    static const byte sigSha1wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 1};
+    #endif
+    #ifdef WOLFSSL_SHA224
+    static const byte sigSha224wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 1};
+    #endif
+    #ifndef NO_SHA256
+    static const byte sigSha256wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 2};
+    #endif
+    #ifdef WOLFSSL_SHA384
+    static const byte sigSha384wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 3};
+    #endif
+    #ifdef WOLFSSL_SHA512
+    static const byte sigSha512wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 4};
+    #endif
+#endif /* HAVE_ECC */
+#ifdef HAVE_ED25519
+    static const byte sigEd25519Oid[] = {43, 101, 112};
+#endif /* HAVE_ED25519 */
+#ifdef HAVE_ED448
+    static const byte sigEd448Oid[] = {43, 101, 113};
+#endif /* HAVE_ED448 */
+
+/* keyType */
+#ifndef NO_DSA
+    static const byte keyDsaOid[] = {42, 134, 72, 206, 56, 4, 1};
+#endif /* NO_DSA */
+#ifndef NO_RSA
+    static const byte keyRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 1};
+#endif /* NO_RSA */
+#ifdef HAVE_NTRU
+    static const byte keyNtruOid[] = {43, 6, 1, 4, 1, 193, 22, 1, 1, 1, 1};
+#endif /* HAVE_NTRU */
+#ifdef HAVE_ECC
+    static const byte keyEcdsaOid[] = {42, 134, 72, 206, 61, 2, 1};
+#endif /* HAVE_ECC */
+#ifdef HAVE_ED25519
+    static const byte keyEd25519Oid[] = {43, 101, 112};
+#endif /* HAVE_ED25519 */
+#ifdef HAVE_ED448
+    static const byte keyEd448Oid[] = {43, 101, 113};
+#endif /* HAVE_ED448 */
+#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
+    static const byte keyDhOid[] = {42, 134, 72, 134, 247, 13, 1, 3, 1};
+#endif /* ! NO_DH ... */
+
+/* curveType */
+#ifdef HAVE_ECC
+    /* See "ecc_sets" table in ecc.c */
+#endif /* HAVE_ECC */
+
+#ifdef HAVE_AES_CBC
+/* blkType */
+    #ifdef WOLFSSL_AES_128
+    static const byte blkAes128CbcOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 2};
+    #endif
+    #ifdef WOLFSSL_AES_192
+    static const byte blkAes192CbcOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 22};
+    #endif
+    #ifdef WOLFSSL_AES_256
+    static const byte blkAes256CbcOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 42};
+    #endif
+#endif /* HAVE_AES_CBC */
+#ifdef HAVE_AESGCM
+    #ifdef WOLFSSL_AES_128
+    static const byte blkAes128GcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 6};
+    #endif
+    #ifdef WOLFSSL_AES_192
+    static const byte blkAes192GcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 26};
+    #endif
+    #ifdef WOLFSSL_AES_256
+    static const byte blkAes256GcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 46};
+    #endif
+#endif /* HAVE_AESGCM */
+#ifdef HAVE_AESCCM
+    #ifdef WOLFSSL_AES_128
+    static const byte blkAes128CcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 7};
+    #endif
+    #ifdef WOLFSSL_AES_192
+    static const byte blkAes192CcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 27};
+    #endif
+    #ifdef WOLFSSL_AES_256
+    static const byte blkAes256CcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 47};
+    #endif
+#endif /* HAVE_AESCCM */
+
+#ifndef NO_DES3
+    static const byte blkDesCbcOid[]  = {43, 14, 3, 2, 7};
+    static const byte blkDes3CbcOid[] = {42, 134, 72, 134, 247, 13, 3, 7};
+#endif
+
+/* keyWrapType */
+#ifdef WOLFSSL_AES_128
+    static const byte wrapAes128Oid[] = {96, 134, 72, 1, 101, 3, 4, 1, 5};
+#endif
+#ifdef WOLFSSL_AES_192
+    static const byte wrapAes192Oid[] = {96, 134, 72, 1, 101, 3, 4, 1, 25};
+#endif
+#ifdef WOLFSSL_AES_256
+    static const byte wrapAes256Oid[] = {96, 134, 72, 1, 101, 3, 4, 1, 45};
+#endif
+#ifdef HAVE_PKCS7
+/* From RFC 3211 */
+static const byte wrapPwriKekOid[] = {42, 134, 72, 134, 247, 13, 1, 9, 16, 3,9};
+#endif
+
+/* cmsKeyAgreeType */
+#ifndef NO_SHA
+    static const byte dhSinglePass_stdDH_sha1kdf_Oid[]   =
+                                          {43, 129, 5, 16, 134, 72, 63, 0, 2};
+#endif
+#ifdef WOLFSSL_SHA224
+    static const byte dhSinglePass_stdDH_sha224kdf_Oid[] = {43, 129, 4, 1, 11, 0};
+#endif
+#ifndef NO_SHA256
+    static const byte dhSinglePass_stdDH_sha256kdf_Oid[] = {43, 129, 4, 1, 11, 1};
+#endif
+#ifdef WOLFSSL_SHA384
+    static const byte dhSinglePass_stdDH_sha384kdf_Oid[] = {43, 129, 4, 1, 11, 2};
+#endif
+#ifdef WOLFSSL_SHA512
+    static const byte dhSinglePass_stdDH_sha512kdf_Oid[] = {43, 129, 4, 1, 11, 3};
+#endif
+
+/* ocspType */
+#ifdef HAVE_OCSP
+    static const byte ocspBasicOid[] = {43, 6, 1, 5, 5, 7, 48, 1, 1};
+    static const byte ocspNonceOid[] = {43, 6, 1, 5, 5, 7, 48, 1, 2};
+#endif /* HAVE_OCSP */
+
+/* certExtType */
+static const byte extBasicCaOid[] = {85, 29, 19};
+static const byte extAltNamesOid[] = {85, 29, 17};
+static const byte extCrlDistOid[] = {85, 29, 31};
+static const byte extAuthInfoOid[] = {43, 6, 1, 5, 5, 7, 1, 1};
+static const byte extAuthKeyOid[] = {85, 29, 35};
+static const byte extSubjKeyOid[] = {85, 29, 14};
+static const byte extCertPolicyOid[] = {85, 29, 32};
+static const byte extKeyUsageOid[] = {85, 29, 15};
+static const byte extInhibitAnyOid[] = {85, 29, 54};
+static const byte extExtKeyUsageOid[] = {85, 29, 37};
+#ifndef IGNORE_NAME_CONSTRAINTS
+    static const byte extNameConsOid[] = {85, 29, 30};
+#endif
+
+/* certAuthInfoType */
+#ifdef HAVE_OCSP
+    static const byte extAuthInfoOcspOid[] = {43, 6, 1, 5, 5, 7, 48, 1};
+#endif
+static const byte extAuthInfoCaIssuerOid[] = {43, 6, 1, 5, 5, 7, 48, 2};
+
+/* certPolicyType */
+static const byte extCertPolicyAnyOid[] = {85, 29, 32, 0};
+
+/* certKeyUseType */
+static const byte extAltNamesHwNameOid[] = {43, 6, 1, 5, 5, 7, 8, 4};
+
+/* certKeyUseType */
+static const byte extExtKeyUsageAnyOid[] = {85, 29, 37, 0};
+static const byte extExtKeyUsageServerAuthOid[]   = {43, 6, 1, 5, 5, 7, 3, 1};
+static const byte extExtKeyUsageClientAuthOid[]   = {43, 6, 1, 5, 5, 7, 3, 2};
+static const byte extExtKeyUsageCodeSigningOid[]  = {43, 6, 1, 5, 5, 7, 3, 3};
+static const byte extExtKeyUsageEmailProtectOid[] = {43, 6, 1, 5, 5, 7, 3, 4};
+static const byte extExtKeyUsageTimestampOid[]    = {43, 6, 1, 5, 5, 7, 3, 8};
+static const byte extExtKeyUsageOcspSignOid[]     = {43, 6, 1, 5, 5, 7, 3, 9};
+
+/* kdfType */
+static const byte pbkdf2Oid[] = {42, 134, 72, 134, 247, 13, 1, 5, 12};
+
+/* PKCS5 */
+#if !defined(NO_DES3) && !defined(NO_SHA)
+static const byte pbeSha1Des[] = {42, 134, 72, 134, 247, 13, 1, 5, 10};
+#endif
+static const byte pbes2[] = {42, 134, 72, 134, 247, 13, 1, 5, 13};
+
+/* PKCS12 */
+#if !defined(NO_RC4) && !defined(NO_SHA)
+static const byte pbeSha1RC4128[] = {42, 134, 72, 134, 247, 13, 1, 12, 1, 1};
+#endif
+#if !defined(NO_DES3) && !defined(NO_SHA)
+static const byte pbeSha1Des3[] = {42, 134, 72, 134, 247, 13, 1, 12, 1, 3};
+#endif
+
+#ifdef HAVE_LIBZ
+/* zlib compression */
+static const byte zlibCompress[] = {42, 134, 72, 134, 247, 13, 1, 9, 16, 3, 8};
+#endif
+#ifdef WOLFSSL_APACHE_HTTPD
+/* tlsExtType */
+static const byte tlsFeatureOid[] = {43, 6, 1, 5, 5, 7, 1, 24};
+/* certNameType */
+static const byte dnsSRVOid[] = {43, 6, 1, 5, 5, 7, 8, 7};
+#endif
+
+
+/* returns a pointer to the OID string on success and NULL on fail */
+const byte* OidFromId(word32 id, word32 type, word32* oidSz)
+{
+    const byte* oid = NULL;
+
+    *oidSz = 0;
+
+    switch (type) {
+
+        case oidHashType:
+            switch (id) {
+            #ifdef WOLFSSL_MD2
+                case MD2h:
+                    oid = hashMd2hOid;
+                    *oidSz = sizeof(hashMd2hOid);
+                    break;
+            #endif
+            #ifndef NO_MD5
+                case MD5h:
+                    oid = hashMd5hOid;
+                    *oidSz = sizeof(hashMd5hOid);
+                    break;
+            #endif
+            #ifndef NO_SHA
+                case SHAh:
+                    oid = hashSha1hOid;
+                    *oidSz = sizeof(hashSha1hOid);
+                    break;
+            #endif
+            #ifdef WOLFSSL_SHA224
+                case SHA224h:
+                    oid = hashSha224hOid;
+                    *oidSz = sizeof(hashSha224hOid);
+                    break;
+            #endif
+            #ifndef NO_SHA256
+                case SHA256h:
+                    oid = hashSha256hOid;
+                    *oidSz = sizeof(hashSha256hOid);
+                    break;
+            #endif
+            #ifdef WOLFSSL_SHA384
+                case SHA384h:
+                    oid = hashSha384hOid;
+                    *oidSz = sizeof(hashSha384hOid);
+                    break;
+            #endif
+            #ifdef WOLFSSL_SHA512
+                case SHA512h:
+                    oid = hashSha512hOid;
+                    *oidSz = sizeof(hashSha512hOid);
+                    break;
+            #endif
+            }
+            break;
+
+        case oidSigType:
+            switch (id) {
+                #if !defined(NO_DSA) && !defined(NO_SHA)
+                case CTC_SHAwDSA:
+                    oid = sigSha1wDsaOid;
+                    *oidSz = sizeof(sigSha1wDsaOid);
+                    break;
+                #endif /* NO_DSA */
+                #ifndef NO_RSA
+                #ifdef WOLFSSL_MD2
+                case CTC_MD2wRSA:
+                    oid = sigMd2wRsaOid;
+                    *oidSz = sizeof(sigMd2wRsaOid);
+                    break;
+                #endif
+                #ifndef NO_MD5
+                case CTC_MD5wRSA:
+                    oid = sigMd5wRsaOid;
+                    *oidSz = sizeof(sigMd5wRsaOid);
+                    break;
+                #endif
+                #ifndef NO_SHA
+                case CTC_SHAwRSA:
+                    oid = sigSha1wRsaOid;
+                    *oidSz = sizeof(sigSha1wRsaOid);
+                    break;
+                #endif
+                #ifdef WOLFSSL_SHA224
+                case CTC_SHA224wRSA:
+                    oid = sigSha224wRsaOid;
+                    *oidSz = sizeof(sigSha224wRsaOid);
+                    break;
+                #endif
+                #ifndef NO_SHA256
+                case CTC_SHA256wRSA:
+                    oid = sigSha256wRsaOid;
+                    *oidSz = sizeof(sigSha256wRsaOid);
+                    break;
+                #endif
+                #ifdef WOLFSSL_SHA384
+                case CTC_SHA384wRSA:
+                    oid = sigSha384wRsaOid;
+                    *oidSz = sizeof(sigSha384wRsaOid);
+                    break;
+                #endif
+                #ifdef WOLFSSL_SHA512
+                case CTC_SHA512wRSA:
+                    oid = sigSha512wRsaOid;
+                    *oidSz = sizeof(sigSha512wRsaOid);
+                    break;
+                #endif /* WOLFSSL_SHA512 */
+                #endif /* NO_RSA */
+                #ifdef HAVE_ECC
+                #ifndef NO_SHA
+                case CTC_SHAwECDSA:
+                    oid = sigSha1wEcdsaOid;
+                    *oidSz = sizeof(sigSha1wEcdsaOid);
+                    break;
+                #endif
+                #ifdef WOLFSSL_SHA224
+                case CTC_SHA224wECDSA:
+                    oid = sigSha224wEcdsaOid;
+                    *oidSz = sizeof(sigSha224wEcdsaOid);
+                    break;
+                #endif
+                #ifndef NO_SHA256
+                case CTC_SHA256wECDSA:
+                    oid = sigSha256wEcdsaOid;
+                    *oidSz = sizeof(sigSha256wEcdsaOid);
+                    break;
+                #endif
+                #ifdef WOLFSSL_SHA384
+                case CTC_SHA384wECDSA:
+                    oid = sigSha384wEcdsaOid;
+                    *oidSz = sizeof(sigSha384wEcdsaOid);
+                    break;
+                #endif
+                #ifdef WOLFSSL_SHA512
+                case CTC_SHA512wECDSA:
+                    oid = sigSha512wEcdsaOid;
+                    *oidSz = sizeof(sigSha512wEcdsaOid);
+                    break;
+                #endif
+                #endif /* HAVE_ECC */
+                #ifdef HAVE_ED25519
+                case CTC_ED25519:
+                    oid = sigEd25519Oid;
+                    *oidSz = sizeof(sigEd25519Oid);
+                    break;
+                #endif
+                #ifdef HAVE_ED448
+                case CTC_ED448:
+                    oid = sigEd448Oid;
+                    *oidSz = sizeof(sigEd448Oid);
+                    break;
+                #endif
+                default:
+                    break;
+            }
+            break;
+
+        case oidKeyType:
+            switch (id) {
+                #ifndef NO_DSA
+                case DSAk:
+                    oid = keyDsaOid;
+                    *oidSz = sizeof(keyDsaOid);
+                    break;
+                #endif /* NO_DSA */
+                #ifndef NO_RSA
+                case RSAk:
+                    oid = keyRsaOid;
+                    *oidSz = sizeof(keyRsaOid);
+                    break;
+                #endif /* NO_RSA */
+                #ifdef HAVE_NTRU
+                case NTRUk:
+                    oid = keyNtruOid;
+                    *oidSz = sizeof(keyNtruOid);
+                    break;
+                #endif /* HAVE_NTRU */
+                #ifdef HAVE_ECC
+                case ECDSAk:
+                    oid = keyEcdsaOid;
+                    *oidSz = sizeof(keyEcdsaOid);
+                    break;
+                #endif /* HAVE_ECC */
+                #ifdef HAVE_ED25519
+                case ED25519k:
+                    oid = keyEd25519Oid;
+                    *oidSz = sizeof(keyEd25519Oid);
+                    break;
+                #endif /* HAVE_ED25519 */
+                #ifdef HAVE_ED448
+                case ED448k:
+                    oid = keyEd448Oid;
+                    *oidSz = sizeof(keyEd448Oid);
+                    break;
+                #endif /* HAVE_ED448 */
+                #if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
+                case DHk:
+                    oid = keyDhOid;
+                    *oidSz = sizeof(keyDhOid);
+                    break;
+                #endif /* ! NO_DH && (WOLFSSL_QT || OPENSSL_ALL */
+                default:
+                    break;
+            }
+            break;
+
+        #ifdef HAVE_ECC
+        case oidCurveType:
+            if (wc_ecc_get_oid(id, &oid, oidSz) < 0) {
+                WOLFSSL_MSG("ECC OID not found");
+            }
+            break;
+        #endif /* HAVE_ECC */
+
+        case oidBlkType:
+            switch (id) {
+    #ifdef HAVE_AES_CBC
+        #ifdef WOLFSSL_AES_128
+                case AES128CBCb:
+                    oid = blkAes128CbcOid;
+                    *oidSz = sizeof(blkAes128CbcOid);
+                    break;
+        #endif
+        #ifdef WOLFSSL_AES_192
+                case AES192CBCb:
+                    oid = blkAes192CbcOid;
+                    *oidSz = sizeof(blkAes192CbcOid);
+                    break;
+        #endif
+        #ifdef WOLFSSL_AES_256
+                case AES256CBCb:
+                    oid = blkAes256CbcOid;
+                    *oidSz = sizeof(blkAes256CbcOid);
+                    break;
+        #endif
+    #endif /* HAVE_AES_CBC */
+    #ifdef HAVE_AESGCM
+        #ifdef WOLFSSL_AES_128
+                case AES128GCMb:
+                    oid = blkAes128GcmOid;
+                    *oidSz = sizeof(blkAes128GcmOid);
+                    break;
+        #endif
+        #ifdef WOLFSSL_AES_192
+                case AES192GCMb:
+                    oid = blkAes192GcmOid;
+                    *oidSz = sizeof(blkAes192GcmOid);
+                    break;
+        #endif
+        #ifdef WOLFSSL_AES_256
+                case AES256GCMb:
+                    oid = blkAes256GcmOid;
+                    *oidSz = sizeof(blkAes256GcmOid);
+                    break;
+        #endif
+    #endif /* HAVE_AESGCM */
+    #ifdef HAVE_AESCCM
+        #ifdef WOLFSSL_AES_128
+                case AES128CCMb:
+                    oid = blkAes128CcmOid;
+                    *oidSz = sizeof(blkAes128CcmOid);
+                    break;
+        #endif
+        #ifdef WOLFSSL_AES_192
+                case AES192CCMb:
+                    oid = blkAes192CcmOid;
+                    *oidSz = sizeof(blkAes192CcmOid);
+                    break;
+        #endif
+        #ifdef WOLFSSL_AES_256
+                case AES256CCMb:
+                    oid = blkAes256CcmOid;
+                    *oidSz = sizeof(blkAes256CcmOid);
+                    break;
+        #endif
+    #endif /* HAVE_AESCCM */
+    #ifndef NO_DES3
+                case DESb:
+                    oid = blkDesCbcOid;
+                    *oidSz = sizeof(blkDesCbcOid);
+                    break;
+                case DES3b:
+                    oid = blkDes3CbcOid;
+                    *oidSz = sizeof(blkDes3CbcOid);
+                    break;
+    #endif /* !NO_DES3 */
+            }
+            break;
+
+        #ifdef HAVE_OCSP
+        case oidOcspType:
+            switch (id) {
+                case OCSP_BASIC_OID:
+                    oid = ocspBasicOid;
+                    *oidSz = sizeof(ocspBasicOid);
+                    break;
+                case OCSP_NONCE_OID:
+                    oid = ocspNonceOid;
+                    *oidSz = sizeof(ocspNonceOid);
+                    break;
+            }
+            break;
+        #endif /* HAVE_OCSP */
+
+        case oidCertExtType:
+            switch (id) {
+                case BASIC_CA_OID:
+                    oid = extBasicCaOid;
+                    *oidSz = sizeof(extBasicCaOid);
+                    break;
+                case ALT_NAMES_OID:
+                    oid = extAltNamesOid;
+                    *oidSz = sizeof(extAltNamesOid);
+                    break;
+                case CRL_DIST_OID:
+                    oid = extCrlDistOid;
+                    *oidSz = sizeof(extCrlDistOid);
+                    break;
+                case AUTH_INFO_OID:
+                    oid = extAuthInfoOid;
+                    *oidSz = sizeof(extAuthInfoOid);
+                    break;
+                case AUTH_KEY_OID:
+                    oid = extAuthKeyOid;
+                    *oidSz = sizeof(extAuthKeyOid);
+                    break;
+                case SUBJ_KEY_OID:
+                    oid = extSubjKeyOid;
+                    *oidSz = sizeof(extSubjKeyOid);
+                    break;
+                case CERT_POLICY_OID:
+                    oid = extCertPolicyOid;
+                    *oidSz = sizeof(extCertPolicyOid);
+                    break;
+                case KEY_USAGE_OID:
+                    oid = extKeyUsageOid;
+                    *oidSz = sizeof(extKeyUsageOid);
+                    break;
+                case INHIBIT_ANY_OID:
+                    oid = extInhibitAnyOid;
+                    *oidSz = sizeof(extInhibitAnyOid);
+                    break;
+                case EXT_KEY_USAGE_OID:
+                    oid = extExtKeyUsageOid;
+                    *oidSz = sizeof(extExtKeyUsageOid);
+                    break;
+            #ifndef IGNORE_NAME_CONSTRAINTS
+                case NAME_CONS_OID:
+                    oid = extNameConsOid;
+                    *oidSz = sizeof(extNameConsOid);
+                    break;
+            #endif
+            }
+            break;
+
+        case oidCrlExtType:
+            #ifdef HAVE_CRL
+            switch (id) {
+                case AUTH_KEY_OID:
+                    oid = extAuthKeyOid;
+                    *oidSz = sizeof(extAuthKeyOid);
+                    break;
+            }
+            #endif
+            break;
+
+        case oidCertAuthInfoType:
+            switch (id) {
+            #ifdef HAVE_OCSP
+                case AIA_OCSP_OID:
+                    oid = extAuthInfoOcspOid;
+                    *oidSz = sizeof(extAuthInfoOcspOid);
+                    break;
+            #endif
+                case AIA_CA_ISSUER_OID:
+                    oid = extAuthInfoCaIssuerOid;
+                    *oidSz = sizeof(extAuthInfoCaIssuerOid);
+                    break;
+            }
+            break;
+
+        case oidCertPolicyType:
+            switch (id) {
+                case CP_ANY_OID:
+                    oid = extCertPolicyAnyOid;
+                    *oidSz = sizeof(extCertPolicyAnyOid);
+                    break;
+            }
+            break;
+
+        case oidCertAltNameType:
+            switch (id) {
+                case HW_NAME_OID:
+                    oid = extAltNamesHwNameOid;
+                    *oidSz = sizeof(extAltNamesHwNameOid);
+                    break;
+            }
+            break;
+
+        case oidCertKeyUseType:
+            switch (id) {
+                case EKU_ANY_OID:
+                    oid = extExtKeyUsageAnyOid;
+                    *oidSz = sizeof(extExtKeyUsageAnyOid);
+                    break;
+                case EKU_SERVER_AUTH_OID:
+                    oid = extExtKeyUsageServerAuthOid;
+                    *oidSz = sizeof(extExtKeyUsageServerAuthOid);
+                    break;
+                case EKU_CLIENT_AUTH_OID:
+                    oid = extExtKeyUsageClientAuthOid;
+                    *oidSz = sizeof(extExtKeyUsageClientAuthOid);
+                    break;
+                case EKU_CODESIGNING_OID:
+                    oid = extExtKeyUsageCodeSigningOid;
+                    *oidSz = sizeof(extExtKeyUsageCodeSigningOid);
+                    break;
+                case EKU_EMAILPROTECT_OID:
+                    oid = extExtKeyUsageEmailProtectOid;
+                    *oidSz = sizeof(extExtKeyUsageEmailProtectOid);
+                    break;
+                case EKU_TIMESTAMP_OID:
+                    oid = extExtKeyUsageTimestampOid;
+                    *oidSz = sizeof(extExtKeyUsageTimestampOid);
+                    break;
+                case EKU_OCSP_SIGN_OID:
+                    oid = extExtKeyUsageOcspSignOid;
+                    *oidSz = sizeof(extExtKeyUsageOcspSignOid);
+                    break;
+            }
+            break;
+
+        case oidKdfType:
+            switch (id) {
+                case PBKDF2_OID:
+                    oid = pbkdf2Oid;
+                    *oidSz = sizeof(pbkdf2Oid);
+                    break;
+            }
+            break;
+
+        case oidPBEType:
+            switch (id) {
+        #if !defined(NO_SHA) && !defined(NO_RC4)
+                case PBE_SHA1_RC4_128:
+                    oid = pbeSha1RC4128;
+                    *oidSz = sizeof(pbeSha1RC4128);
+                    break;
+        #endif
+        #if !defined(NO_SHA) && !defined(NO_DES3)
+                case PBE_SHA1_DES:
+                    oid = pbeSha1Des;
+                    *oidSz = sizeof(pbeSha1Des);
+                    break;
+
+        #endif
+        #if !defined(NO_SHA) && !defined(NO_DES3)
+                case PBE_SHA1_DES3:
+                    oid = pbeSha1Des3;
+                    *oidSz = sizeof(pbeSha1Des3);
+                    break;
+        #endif
+                case PBES2:
+                    oid = pbes2;
+                    *oidSz = sizeof(pbes2);
+                    break;
+            }
+            break;
+
+        case oidKeyWrapType:
+            switch (id) {
+            #ifdef WOLFSSL_AES_128
+                case AES128_WRAP:
+                    oid = wrapAes128Oid;
+                    *oidSz = sizeof(wrapAes128Oid);
+                    break;
+            #endif
+            #ifdef WOLFSSL_AES_192
+                case AES192_WRAP:
+                    oid = wrapAes192Oid;
+                    *oidSz = sizeof(wrapAes192Oid);
+                    break;
+            #endif
+            #ifdef WOLFSSL_AES_256
+                case AES256_WRAP:
+                    oid = wrapAes256Oid;
+                    *oidSz = sizeof(wrapAes256Oid);
+                    break;
+            #endif
+            #ifdef HAVE_PKCS7
+                case PWRI_KEK_WRAP:
+                    oid = wrapPwriKekOid;
+                    *oidSz = sizeof(wrapPwriKekOid);
+                    break;
+            #endif
+            }
+            break;
+
+        case oidCmsKeyAgreeType:
+            switch (id) {
+            #ifndef NO_SHA
+                case dhSinglePass_stdDH_sha1kdf_scheme:
+                    oid = dhSinglePass_stdDH_sha1kdf_Oid;
+                    *oidSz = sizeof(dhSinglePass_stdDH_sha1kdf_Oid);
+                    break;
+            #endif
+            #ifdef WOLFSSL_SHA224
+                case dhSinglePass_stdDH_sha224kdf_scheme:
+                    oid = dhSinglePass_stdDH_sha224kdf_Oid;
+                    *oidSz = sizeof(dhSinglePass_stdDH_sha224kdf_Oid);
+                    break;
+            #endif
+            #ifndef NO_SHA256
+                case dhSinglePass_stdDH_sha256kdf_scheme:
+                    oid = dhSinglePass_stdDH_sha256kdf_Oid;
+                    *oidSz = sizeof(dhSinglePass_stdDH_sha256kdf_Oid);
+                    break;
+            #endif
+            #ifdef WOLFSSL_SHA384
+                case dhSinglePass_stdDH_sha384kdf_scheme:
+                    oid = dhSinglePass_stdDH_sha384kdf_Oid;
+                    *oidSz = sizeof(dhSinglePass_stdDH_sha384kdf_Oid);
+                    break;
+            #endif
+            #ifdef WOLFSSL_SHA512
+                case dhSinglePass_stdDH_sha512kdf_scheme:
+                    oid = dhSinglePass_stdDH_sha512kdf_Oid;
+                    *oidSz = sizeof(dhSinglePass_stdDH_sha512kdf_Oid);
+                    break;
+            #endif
+            }
+            break;
+
+#ifndef NO_HMAC
+        case oidHmacType:
+            switch (id) {
+        #ifdef WOLFSSL_SHA224
+                case HMAC_SHA224_OID:
+                    oid = hmacSha224Oid;
+                    *oidSz = sizeof(hmacSha224Oid);
+                    break;
+        #endif
+        #ifndef NO_SHA256
+                case HMAC_SHA256_OID:
+                    oid = hmacSha256Oid;
+                    *oidSz = sizeof(hmacSha256Oid);
+                    break;
+        #endif
+        #ifdef WOLFSSL_SHA384
+                case HMAC_SHA384_OID:
+                    oid = hmacSha384Oid;
+                    *oidSz = sizeof(hmacSha384Oid);
+                    break;
+        #endif
+        #ifdef WOLFSSL_SHA512
+                case HMAC_SHA512_OID:
+                    oid = hmacSha512Oid;
+                    *oidSz = sizeof(hmacSha512Oid);
+                    break;
+        #endif
+            }
+            break;
+#endif /* !NO_HMAC */
+
+#ifdef HAVE_LIBZ
+        case oidCompressType:
+            switch (id) {
+                case ZLIBc:
+                    oid = zlibCompress;
+                    *oidSz = sizeof(zlibCompress);
+                    break;
+            }
+            break;
+#endif /* HAVE_LIBZ */
+#ifdef WOLFSSL_APACHE_HTTPD
+        case oidCertNameType:
+            switch (id) {
+                 case NID_id_on_dnsSRV:
+                    oid = dnsSRVOid;
+                    *oidSz = sizeof(dnsSRVOid);
+                    break;
+            }
+            break;
+        case oidTlsExtType:
+            switch (id) {
+                case TLS_FEATURE_OID:
+                    oid = tlsFeatureOid;
+                    *oidSz = sizeof(tlsFeatureOid);
+                    break;
+            }
+            break;
+#endif /* WOLFSSL_APACHE_HTTPD */
+        case oidIgnoreType:
+        default:
+            break;
+    }
+
+    return oid;
+}
+
+#ifdef HAVE_OID_ENCODING
+int EncodeObjectId(const word16* in, word32 inSz, byte* out, word32* outSz)
+{
+    int i, x, len;
+    word32 d, t;
+
+    /* check args */
+    if (in == NULL || outSz == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* compute length of encoded OID */
+    d = (in[0] * 40) + in[1];
+    len = 0;
+    for (i = 1; i < (int)inSz; i++) {
+        x = 0;
+        t = d;
+        while (t) {
+            x++;
+            t >>= 1;
+        }
+        len += (x / 7) + ((x % 7) ? 1 : 0) + (d == 0 ? 1 : 0);
+
+        if (i < (int)inSz - 1) {
+            d = in[i + 1];
+        }
+    }
+
+    if (out) {
+        /* verify length */
+        if ((int)*outSz < len) {
+            return BUFFER_E; /* buffer provided is not large enough */
+        }
+
+        /* calc first byte */
+        d = (in[0] * 40) + in[1];
+
+        /* encode bytes */
+        x = 0;
+        for (i = 1; i < (int)inSz; i++) {
+            if (d) {
+                int y = x, z;
+                byte mask = 0;
+                while (d) {
+                    out[x++] = (byte)((d & 0x7F) | mask);
+                    d     >>= 7;
+                    mask  |= 0x80;  /* upper bit is set on all but the last byte */
+                }
+                /* now swap bytes y...x-1 */
+                z = x - 1;
+                while (y < z) {
+                    mask = out[y];
+                    out[y] = out[z];
+                    out[z] = mask;
+                    ++y;
+                    --z;
+                }
+            }
+            else {
+              out[x++] = 0x00; /* zero value */
+            }
+
+            /* next word */
+            if (i < (int)inSz - 1) {
+                d = in[i + 1];
+            }
+        }
+    }
+
+    /* return length */
+    *outSz = len;
+
+    return 0;
+}
+#endif /* HAVE_OID_ENCODING */
+
+#ifdef HAVE_OID_DECODING
+int DecodeObjectId(const byte* in, word32 inSz, word16* out, word32* outSz)
+{
+    int x = 0, y = 0;
+    word32 t = 0;
+
+    /* check args */
+    if (in == NULL || outSz == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* decode bytes */
+    while (inSz--) {
+        t = (t << 7) | (in[x] & 0x7F);
+        if (!(in[x] & 0x80)) {
+            if (y >= (int)*outSz) {
+                return BUFFER_E;
+            }
+            if (y == 0) {
+                out[0] = (t / 40);
+                out[1] = (t % 40);
+                y = 2;
+            }
+            else {
+                out[y++] = t;
+            }
+            t = 0; /* reset tmp */
+        }
+        x++;
+    }
+
+    /* return length */
+    *outSz = y;
+
+    return 0;
+}
+#endif /* HAVE_OID_DECODING */
+
+/* Get the DER/BER encoding of an ASN.1 OBJECT_ID header.
+ *
+ * input     Buffer holding DER/BER encoded data.
+ * inOutIdx  Current index into buffer to parse.
+ * len       The number of bytes in the ASN.1 data.
+ * maxIdx    Length of data in buffer.
+ * returns BUFFER_E when there is not enough data to parse.
+ *         ASN_OBJECt_ID_E when the OBJECT_ID tag is not found.
+ *         ASN_PARSE_E when length is invalid.
+ *         Otherwise, 0 to indicate success.
+ */
+int GetASNObjectId(const byte* input, word32* inOutIdx, int* len,
+                          word32 maxIdx)
+{
+    word32 idx = *inOutIdx;
+    int    length;
+    byte   tag;
+
+    if ((idx + 1) > maxIdx)
+        return BUFFER_E;
+
+    if (GetASNTag(input, &idx, &tag, maxIdx) != 0)
+        return ASN_PARSE_E;
+
+    if (tag != ASN_OBJECT_ID)
+        return ASN_OBJECT_ID_E;
+
+    if (GetLength(input, &idx, &length, maxIdx) < 0)
+        return ASN_PARSE_E;
+
+    *len = length;
+    *inOutIdx = idx;
+    return 0;
+}
+
+/* Set the DER/BER encoding of the ASN.1 OBJECT_ID header.
+ *
+ * len         Length of the OBJECT_ID data.
+ * output      Buffer to write into.
+ * returns the number of bytes added to the buffer.
+ */
+int SetObjectId(int len, byte* output)
+{
+    int idx = 0;
+
+    output[idx++] = ASN_OBJECT_ID;
+    idx += SetLength(len, output + idx);
+
+    return idx;
+}
+
+int GetObjectId(const byte* input, word32* inOutIdx, word32* oid,
+                                  word32 oidType, word32 maxIdx)
+{
+    int    ret = 0, length;
+    word32 idx = *inOutIdx;
+#ifndef NO_VERIFY_OID
+    word32 actualOidSz = 0;
+    const byte* actualOid;
+#endif /* NO_VERIFY_OID */
+
+    (void)oidType;
+    WOLFSSL_ENTER("GetObjectId()");
+    *oid = 0;
+
+    ret = GetASNObjectId(input, &idx, &length, maxIdx);
+    if (ret != 0)
+        return ret;
+
+#ifndef NO_VERIFY_OID
+    actualOid = &input[idx];
+    if (length > 0)
+        actualOidSz = (word32)length;
+#endif /* NO_VERIFY_OID */
+
+    while (length--) {
+        /* odd HC08 compiler behavior here when input[idx++] */
+        *oid += (word32)input[idx];
+        idx++;
+    }
+    /* just sum it up for now */
+
+    *inOutIdx = idx;
+
+#ifndef NO_VERIFY_OID
+    {
+        const byte* checkOid = NULL;
+        word32 checkOidSz;
+    #ifdef ASN_DUMP_OID
+        word32 i;
+    #endif
+
+        if (oidType != oidIgnoreType) {
+            checkOid = OidFromId(*oid, oidType, &checkOidSz);
+
+        #ifdef ASN_DUMP_OID
+            /* support for dumping OID information */
+            printf("OID (Type %d, Sz %d, Sum %d): ", oidType, actualOidSz, *oid);
+            for (i=0; i<actualOidSz; i++) {
+                printf("%d, ", actualOid[i]);
+            }
+            printf("\n");
+            #ifdef HAVE_OID_DECODING
+            {
+                word16 decOid[16];
+                word32 decOidSz = sizeof(decOid);
+                ret = DecodeObjectId(actualOid, actualOidSz, decOid, &decOidSz);
+                if (ret == 0) {
+                    printf("  Decoded (Sz %d): ", decOidSz);
+                    for (i=0; i<decOidSz; i++) {
+                        printf("%d.", decOid[i]);
+                    }
+                    printf("\n");
+                }
+                else {
+                    printf("DecodeObjectId failed: %d\n", ret);
+                }
+            }
+            #endif /* HAVE_OID_DECODING */
+        #endif /* ASN_DUMP_OID */
+
+            if (checkOid != NULL &&
+                (checkOidSz != actualOidSz ||
+                    XMEMCMP(actualOid, checkOid, checkOidSz) != 0)) {
+                WOLFSSL_MSG("OID Check Failed");
+                return ASN_UNKNOWN_OID_E;
+            }
+        }
+    }
+#endif /* NO_VERIFY_OID */
+
+    return ret;
+}
+
+static int SkipObjectId(const byte* input, word32* inOutIdx, word32 maxIdx)
+{
+    word32 idx = *inOutIdx;
+    int    length;
+    int ret;
+
+    ret = GetASNObjectId(input, &idx, &length, maxIdx);
+    if (ret != 0)
+        return ret;
+
+    idx += length;
+    *inOutIdx = idx;
+
+    return 0;
+}
+
+int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid,
+                     word32 oidType, word32 maxIdx)
+{
+    int    length;
+    word32 idx = *inOutIdx;
+    int    ret;
+    *oid = 0;
+
+    WOLFSSL_ENTER("GetAlgoId");
+
+    if (GetSequence(input, &idx, &length, maxIdx) < 0)
+        return ASN_PARSE_E;
+
+    if (GetObjectId(input, &idx, oid, oidType, maxIdx) < 0)
+        return ASN_OBJECT_ID_E;
+
+    /* could have NULL tag and 0 terminator, but may not */
+    if (idx < maxIdx) {
+        word32 localIdx = idx; /*use localIdx to not advance when checking tag*/
+        byte   tag;
+
+        if (GetASNTag(input, &localIdx, &tag, maxIdx) == 0) {
+            if (tag == ASN_TAG_NULL) {
+                ret = GetASNNull(input, &idx, maxIdx);
+                if (ret != 0)
+                    return ret;
+            }
+        }
+    }
+
+    *inOutIdx = idx;
+
+    return 0;
+}
+
+#ifndef NO_RSA
+
+#ifndef HAVE_USER_RSA
+int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key,
+                        word32 inSz)
+{
+    int version, length;
+
+    if (inOutIdx == NULL) {
+        return BAD_FUNC_ARG;
+    }
+    if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+        return ASN_PARSE_E;
+
+    if (GetMyVersion(input, inOutIdx, &version, inSz) < 0)
+        return ASN_PARSE_E;
+
+    key->type = RSA_PRIVATE;
+
+    if (GetInt(&key->n,  input, inOutIdx, inSz) < 0 ||
+        GetInt(&key->e,  input, inOutIdx, inSz) < 0 ||
+#ifndef WOLFSSL_RSA_PUBLIC_ONLY
+        GetInt(&key->d,  input, inOutIdx, inSz) < 0 ||
+        GetInt(&key->p,  input, inOutIdx, inSz) < 0 ||
+        GetInt(&key->q,  input, inOutIdx, inSz) < 0)
+#else
+        SkipInt(input, inOutIdx, inSz) < 0 ||
+        SkipInt(input, inOutIdx, inSz) < 0 ||
+        SkipInt(input, inOutIdx, inSz) < 0 )
+
+#endif
+            return ASN_RSA_KEY_E;
+#if (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM)) \
+    && !defined(WOLFSSL_RSA_PUBLIC_ONLY)
+    if (GetInt(&key->dP, input, inOutIdx, inSz) < 0 ||
+        GetInt(&key->dQ, input, inOutIdx, inSz) < 0 ||
+        GetInt(&key->u,  input, inOutIdx, inSz) < 0 )  return ASN_RSA_KEY_E;
+#else
+    if (SkipInt(input, inOutIdx, inSz) < 0 ||
+        SkipInt(input, inOutIdx, inSz) < 0 ||
+        SkipInt(input, inOutIdx, inSz) < 0 )  return ASN_RSA_KEY_E;
+#endif
+
+#if defined(WOLFSSL_XILINX_CRYPT) || defined(WOLFSSL_CRYPTOCELL)
+    if (wc_InitRsaHw(key) != 0) {
+        return BAD_STATE_E;
+    }
+#endif
+
+    return 0;
+}
+#endif /* HAVE_USER_RSA */
+#endif /* NO_RSA */
+
+#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12)
+
+/* Remove PKCS8 header, place inOutIdx at beginning of traditional,
+ * return traditional length on success, negative on error */
+int ToTraditionalInline_ex(const byte* input, word32* inOutIdx, word32 sz,
+                           word32* algId)
+{
+    word32 idx;
+    int    version, length;
+    int    ret;
+    byte   tag;
+
+    if (input == NULL || inOutIdx == NULL)
+        return BAD_FUNC_ARG;
+
+    idx = *inOutIdx;
+
+    if (GetSequence(input, &idx, &length, sz) < 0)
+        return ASN_PARSE_E;
+
+    if (GetMyVersion(input, &idx, &version, sz) < 0)
+        return ASN_PARSE_E;
+
+    if (GetAlgoId(input, &idx, algId, oidKeyType, sz) < 0)
+        return ASN_PARSE_E;
+
+    if (GetASNTag(input, &idx, &tag, sz) < 0)
+        return ASN_PARSE_E;
+    idx = idx - 1; /* reset idx after finding tag */
+
+    if (tag == ASN_OBJECT_ID) {
+        if (SkipObjectId(input, &idx, sz) < 0)
+            return ASN_PARSE_E;
+    }
+
+    ret = GetOctetString(input, &idx, &length, sz);
+    if (ret < 0) {
+        if (ret == BUFFER_E)
+            return ASN_PARSE_E;
+        /* Some private keys don't expect an octet string */
+        WOLFSSL_MSG("Couldn't find Octet string");
+    }
+
+    *inOutIdx = idx;
+
+    return length;
+}
+
+int ToTraditionalInline(const byte* input, word32* inOutIdx, word32 sz)
+{
+    word32 oid;
+
+    return ToTraditionalInline_ex(input, inOutIdx, sz, &oid);
+}
+
+/* Remove PKCS8 header, move beginning of traditional to beginning of input */
+int ToTraditional_ex(byte* input, word32 sz, word32* algId)
+{
+    word32 inOutIdx = 0;
+    int    length;
+
+    if (input == NULL)
+        return BAD_FUNC_ARG;
+
+    length = ToTraditionalInline_ex(input, &inOutIdx, sz, algId);
+    if (length < 0)
+        return length;
+
+    XMEMMOVE(input, input + inOutIdx, length);
+
+    return length;
+}
+
+int ToTraditional(byte* input, word32 sz)
+{
+    word32 oid;
+
+    return ToTraditional_ex(input, sz, &oid);
+}
+
+#endif /* HAVE_PKCS8 || HAVE_PKCS12 */
+
+#ifdef HAVE_PKCS8
+
+/* find beginning of traditional key inside PKCS#8 unencrypted buffer
+ * return traditional length on success, with inOutIdx at beginning of
+ * traditional
+ * return negative on failure/error */
+int wc_GetPkcs8TraditionalOffset(byte* input, word32* inOutIdx, word32 sz)
+{
+    int length;
+    word32 algId;
+
+    if (input == NULL || inOutIdx == NULL || (*inOutIdx > sz))
+        return BAD_FUNC_ARG;
+
+    length = ToTraditionalInline_ex(input, inOutIdx, sz, &algId);
+
+    return length;
+}
+
+
+/* PKCS#8 from RFC 5208
+ * This function takes in a DER key and converts it to PKCS#8 format. Used
+ * in creating PKCS#12 shrouded key bags.
+ * Reverse of ToTraditional
+ *
+ * PrivateKeyInfo ::= SEQUENCE {
+ *  version Version,
+ *  privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
+ *  privateKey          PrivateKey,
+ *  attributes          optional
+ *  }
+ *  Version ::= INTEGER
+ *  PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
+ *  PrivateKey ::= OCTET STRING
+ *
+ * out      buffer to place result in
+ * outSz    size of out buffer
+ * key      buffer with DER key
+ * keySz    size of key buffer
+ * algoID   algorithm ID i.e. RSAk
+ * curveOID ECC curve oid if used. Should be NULL for RSA keys.
+ * oidSz    size of curve oid. Is set to 0 if curveOID is NULL.
+ *
+ * Returns the size of PKCS#8 placed into out. In error cases returns negative
+ * values.
+ */
+int wc_CreatePKCS8Key(byte* out, word32* outSz, byte* key, word32 keySz,
+        int algoID, const byte* curveOID, word32 oidSz)
+{
+        word32 keyIdx = 0;
+        word32 tmpSz  = 0;
+        word32 sz;
+
+
+        /* If out is NULL then return the max size needed
+         * + 2 for ASN_OBJECT_ID and ASN_OCTET_STRING tags */
+        if (out == NULL && outSz != NULL) {
+            *outSz = keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ
+                     + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 2;
+
+            if (curveOID != NULL)
+                *outSz += oidSz + MAX_LENGTH_SZ + 1;
+
+            WOLFSSL_MSG("Checking size of PKCS8");
+
+            return LENGTH_ONLY_E;
+        }
+
+        WOLFSSL_ENTER("wc_CreatePKCS8Key()");
+
+        if (key == NULL || out == NULL || outSz == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        /* check the buffer has enough room for largest possible size */
+        if (curveOID != NULL) {
+            if (*outSz < (keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ
+                   + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 3 + oidSz + MAX_LENGTH_SZ))
+                return BUFFER_E;
+        }
+        else {
+            oidSz = 0; /* with no curveOID oid size must be 0 */
+            if (*outSz < (keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ
+                      + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 2))
+                return BUFFER_E;
+        }
+
+        /* PrivateKeyInfo ::= SEQUENCE */
+        keyIdx += MAX_SEQ_SZ; /* save room for sequence */
+
+        /*  version Version
+         *  no header information just INTEGER */
+        sz = SetMyVersion(PKCS8v0, out + keyIdx, 0);
+        tmpSz += sz; keyIdx += sz;
+
+        /*  privateKeyAlgorithm PrivateKeyAlgorithmIdentifier */
+        sz = 0; /* set sz to 0 and get privateKey oid buffer size needed */
+        if (curveOID != NULL && oidSz > 0) {
+            byte buf[MAX_LENGTH_SZ];
+            sz = SetLength(oidSz, buf);
+            sz += 1; /* plus one for ASN object id */
+        }
+        sz = SetAlgoID(algoID, out + keyIdx, oidKeyType, oidSz + sz);
+        tmpSz += sz; keyIdx += sz;
+
+        /*  privateKey          PrivateKey *
+         * pkcs8 ecc uses slightly different format. Places curve oid in
+         * buffer */
+        if (curveOID != NULL && oidSz > 0) {
+            sz = SetObjectId(oidSz, out + keyIdx);
+            keyIdx += sz; tmpSz += sz;
+            XMEMCPY(out + keyIdx, curveOID, oidSz);
+            keyIdx += oidSz; tmpSz += oidSz;
+        }
+
+        sz = SetOctetString(keySz, out + keyIdx);
+        keyIdx += sz; tmpSz += sz;
+        XMEMCPY(out + keyIdx, key, keySz);
+        tmpSz += keySz;
+
+        /*  attributes          optional
+         * No attributes currently added */
+
+        /* rewind and add sequence */
+        sz = SetSequence(tmpSz, out);
+        XMEMMOVE(out + sz, out + MAX_SEQ_SZ, tmpSz);
+
+        return tmpSz + sz;
+}
+
+#endif /* HAVE_PKCS8 */
+
+#if defined(HAVE_PKCS12) || !defined(NO_CHECK_PRIVATE_KEY)
+/* check that the private key is a pair for the public key in certificate
+ * return 1 (true) on match
+ * return 0 or negative value on failure/error
+ *
+ * key   : buffer holding DER format key
+ * keySz : size of key buffer
+ * der   : a initialized and parsed DecodedCert holding a certificate */
+int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der)
+{
+    int ret;
+    (void)keySz;
+
+    if (key == NULL || der == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    #if !defined(NO_RSA) && !defined(NO_ASN_CRYPT)
+    /* test if RSA key */
+    if (der->keyOID == RSAk) {
+    #ifdef WOLFSSL_SMALL_STACK
+        RsaKey* a;
+        RsaKey* b = NULL;
+    #else
+        RsaKey a[1], b[1];
+    #endif
+        word32 keyIdx = 0;
+
+    #ifdef WOLFSSL_SMALL_STACK
+        a = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA);
+        if (a == NULL)
+            return MEMORY_E;
+        b = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA);
+        if (b == NULL) {
+            XFREE(a, NULL, DYNAMIC_TYPE_RSA);
+            return MEMORY_E;
+        }
+    #endif
+
+        if ((ret = wc_InitRsaKey(a, NULL)) < 0) {
+    #ifdef WOLFSSL_SMALL_STACK
+            XFREE(b, NULL, DYNAMIC_TYPE_RSA);
+            XFREE(a, NULL, DYNAMIC_TYPE_RSA);
+    #endif
+            return ret;
+        }
+        if ((ret = wc_InitRsaKey(b, NULL)) < 0) {
+            wc_FreeRsaKey(a);
+    #ifdef WOLFSSL_SMALL_STACK
+            XFREE(b, NULL, DYNAMIC_TYPE_RSA);
+            XFREE(a, NULL, DYNAMIC_TYPE_RSA);
+    #endif
+            return ret;
+        }
+        if ((ret = wc_RsaPrivateKeyDecode(key, &keyIdx, a, keySz)) == 0) {
+            WOLFSSL_MSG("Checking RSA key pair");
+            keyIdx = 0; /* reset to 0 for parsing public key */
+
+            if ((ret = wc_RsaPublicKeyDecode(der->publicKey, &keyIdx, b,
+                                                       der->pubKeySize)) == 0) {
+                /* limit for user RSA crypto because of RsaKey
+                 * dereference. */
+            #if defined(HAVE_USER_RSA)
+                WOLFSSL_MSG("Cannot verify RSA pair with user RSA");
+                ret = 1; /* return first RSA cert as match */
+            #else
+                /* both keys extracted successfully now check n and e
+                 * values are the same. This is dereferencing RsaKey */
+                if (mp_cmp(&(a->n), &(b->n)) != MP_EQ ||
+                    mp_cmp(&(a->e), &(b->e)) != MP_EQ) {
+                    ret = MP_CMP_E;
+                }
+                else
+                    ret = 1;
+            #endif
+            }
+        }
+        wc_FreeRsaKey(b);
+        wc_FreeRsaKey(a);
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(b, NULL, DYNAMIC_TYPE_RSA);
+        XFREE(a, NULL, DYNAMIC_TYPE_RSA);
+    #endif
+    }
+    else
+    #endif /* !NO_RSA && !NO_ASN_CRYPT */
+
+    #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) && !defined(NO_ASN_CRYPT)
+    if (der->keyOID == ECDSAk) {
+    #ifdef WOLFSSL_SMALL_STACK
+        ecc_key* key_pair;
+        byte*    privDer;
+    #else
+        ecc_key  key_pair[1];
+        byte     privDer[MAX_ECC_BYTES];
+    #endif
+        word32   privSz = MAX_ECC_BYTES;
+        word32   keyIdx = 0;
+
+    #ifdef WOLFSSL_SMALL_STACK
+        key_pair = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_ECC);
+        if (key_pair == NULL)
+            return MEMORY_E;
+        privDer = (byte*)XMALLOC(MAX_ECC_BYTES, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (privDer == NULL) {
+            XFREE(key_pair, NULL, DYNAMIC_TYPE_ECC);
+            return MEMORY_E;
+        }
+    #endif
+
+        if ((ret = wc_ecc_init(key_pair)) < 0) {
+    #ifdef WOLFSSL_SMALL_STACK
+            XFREE(privDer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            XFREE(key_pair, NULL, DYNAMIC_TYPE_ECC);
+    #endif
+            return ret;
+        }
+
+        if ((ret = wc_EccPrivateKeyDecode(key, &keyIdx, key_pair,
+                                                                 keySz)) == 0) {
+            WOLFSSL_MSG("Checking ECC key pair");
+
+            if ((ret = wc_ecc_export_private_only(key_pair, privDer, &privSz))
+                                                                         == 0) {
+                wc_ecc_free(key_pair);
+                ret = wc_ecc_init(key_pair);
+                if (ret == 0) {
+                    ret = wc_ecc_import_private_key((const byte*)privDer,
+                                            privSz, (const byte*)der->publicKey,
+                                            der->pubKeySize, key_pair);
+                }
+
+                /* public and private extracted successfully now check if is
+                 * a pair and also do sanity checks on key. wc_ecc_check_key
+                 * checks that private * base generator equals pubkey */
+                if (ret == 0) {
+                    if ((ret = wc_ecc_check_key(key_pair)) == 0) {
+                        ret = 1;
+                    }
+                }
+                ForceZero(privDer, privSz);
+            }
+        }
+        wc_ecc_free(key_pair);
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(privDer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(key_pair, NULL, DYNAMIC_TYPE_ECC);
+    #endif
+    }
+    else
+    #endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT && !NO_ASN_CRYPT */
+
+    #if defined(HAVE_ED25519) && !defined(NO_ASN_CRYPT)
+    if (der->keyOID == ED25519k) {
+    #ifdef WOLFSSL_SMALL_STACK
+        ed25519_key* key_pair;
+    #else
+        ed25519_key  key_pair[1];
+    #endif
+        word32       keyIdx = 0;
+
+    #ifdef WOLFSSL_SMALL_STACK
+        key_pair = (ed25519_key*)XMALLOC(sizeof(ed25519_key), NULL,
+                                                          DYNAMIC_TYPE_ED25519);
+        if (key_pair == NULL)
+            return MEMORY_E;
+    #endif
+
+        if ((ret = wc_ed25519_init(key_pair)) < 0) {
+    #ifdef WOLFSSL_SMALL_STACK
+            XFREE(key_pair, NULL, DYNAMIC_TYPE_ED25519);
+    #endif
+            return ret;
+        }
+        if ((ret = wc_Ed25519PrivateKeyDecode(key, &keyIdx, key_pair,
+                                                                 keySz)) == 0) {
+            WOLFSSL_MSG("Checking ED25519 key pair");
+            keyIdx = 0;
+            if ((ret = wc_ed25519_import_public(der->publicKey, der->pubKeySize,
+                                                              key_pair)) == 0) {
+                /* public and private extracted successfully no check if is
+                 * a pair and also do sanity checks on key. wc_ecc_check_key
+                 * checks that private * base generator equals pubkey */
+                if ((ret = wc_ed25519_check_key(key_pair)) == 0)
+                    ret = 1;
+            }
+        }
+        wc_ed25519_free(key_pair);
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(key_pair, NULL, DYNAMIC_TYPE_ED25519);
+    #endif
+    }
+    else
+    #endif /* HAVE_ED25519 && !NO_ASN_CRYPT */
+
+    #if defined(HAVE_ED448) && !defined(NO_ASN_CRYPT)
+    if (der->keyOID == ED448k) {
+    #ifdef WOLFSSL_SMALL_STACK
+        ed448_key* key_pair = NULL;
+    #else
+        ed448_key  key_pair[1];
+    #endif
+        word32     keyIdx = 0;
+
+    #ifdef WOLFSSL_SMALL_STACK
+        key_pair = (ed448_key*)XMALLOC(sizeof(ed448_key), NULL,
+                                                            DYNAMIC_TYPE_ED448);
+        if (key_pair == NULL)
+            return MEMORY_E;
+    #endif
+
+        if ((ret = wc_ed448_init(key_pair)) < 0) {
+    #ifdef WOLFSSL_SMALL_STACK
+            XFREE(key_pair, NULL, DYNAMIC_TYPE_ED448);
+    #endif
+            return ret;
+        }
+        if ((ret = wc_Ed448PrivateKeyDecode(key, &keyIdx, key_pair,
+                                                                 keySz)) == 0) {
+            WOLFSSL_MSG("Checking ED448 key pair");
+            keyIdx = 0;
+            if ((ret = wc_ed448_import_public(der->publicKey, der->pubKeySize,
+                                                              key_pair)) == 0) {
+                /* public and private extracted successfully no check if is
+                 * a pair and also do sanity checks on key. wc_ecc_check_key
+                 * checks that private * base generator equals pubkey */
+                if ((ret = wc_ed448_check_key(key_pair)) == 0)
+                    ret = 1;
+            }
+        }
+        wc_ed448_free(key_pair);
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(key_pair, NULL, DYNAMIC_TYPE_ED448);
+    #endif
+    }
+    else
+    #endif /* HAVE_ED448 && !NO_ASN_CRYPT */
+    {
+        ret = 0;
+    }
+
+    (void)keySz;
+
+    return ret;
+}
+
+#endif /* HAVE_PKCS12 || !NO_CHECK_PRIVATE_KEY */
+
+#ifndef NO_PWDBASED
+
+#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12)
+/* Check To see if PKCS version algo is supported, set id if it is return 0
+   < 0 on error */
+static int CheckAlgo(int first, int second, int* id, int* version, int* blockSz)
+{
+    *id      = ALGO_ID_E;
+    *version = PKCS5;   /* default */
+    if (blockSz) *blockSz = 8; /* default */
+
+    if (first == 1) {
+        switch (second) {
+#if !defined(NO_SHA)
+    #ifndef NO_RC4
+        case PBE_SHA1_RC4_128:
+            *id = PBE_SHA1_RC4_128;
+            *version = PKCS12v1;
+            return 0;
+    #endif
+    #ifndef NO_DES3
+        case PBE_SHA1_DES3:
+            *id = PBE_SHA1_DES3;
+            *version = PKCS12v1;
+            if (blockSz) *blockSz = DES_BLOCK_SIZE;
+            return 0;
+        case PBE_SHA1_DES:
+            *id = PBE_SHA1_DES;
+            *version = PKCS12v1;
+            if (blockSz) *blockSz = DES_BLOCK_SIZE;
+            return 0;
+    #endif
+#endif /* !NO_SHA */
+        default:
+            return ALGO_ID_E;
+        }
+    }
+
+    if (first != PKCS5)
+        return ASN_INPUT_E;  /* VERSION ERROR */
+
+    if (second == PBES2) {
+        *version = PKCS5v2;
+        return 0;
+    }
+
+    switch (second) {
+#ifndef NO_DES3
+    #ifndef NO_MD5
+    case 3:                   /* see RFC 2898 for ids */
+        *id = PBE_MD5_DES;
+        if (blockSz) *blockSz = DES_BLOCK_SIZE;
+        return 0;
+    #endif
+    #ifndef NO_SHA
+    case 10:
+        *id = PBE_SHA1_DES;
+        if (blockSz) *blockSz = DES_BLOCK_SIZE;
+        return 0;
+    #endif
+#endif /* !NO_DES3 */
+    default:
+        return ALGO_ID_E;
+
+    }
+}
+
+/* Check To see if PKCS v2 algo is supported, set id if it is return 0
+   < 0 on error */
+static int CheckAlgoV2(int oid, int* id, int* blockSz)
+{
+    if (blockSz) *blockSz = 8; /* default */
+    (void)id; /* not used if AES and DES3 disabled */
+    switch (oid) {
+#if !defined(NO_DES3) && !defined(NO_SHA)
+    case DESb:
+        *id = PBE_SHA1_DES;
+        if (blockSz) *blockSz = DES_BLOCK_SIZE;
+        return 0;
+    case DES3b:
+        *id = PBE_SHA1_DES3;
+        if (blockSz) *blockSz = DES_BLOCK_SIZE;
+        return 0;
+#endif
+#ifdef WOLFSSL_AES_256
+    case AES256CBCb:
+        *id = PBE_AES256_CBC;
+        if (blockSz) *blockSz = AES_BLOCK_SIZE;
+        return 0;
+#endif
+#ifdef WOLFSSL_AES_128
+    case AES128CBCb:
+        *id = PBE_AES128_CBC;
+        if (blockSz) *blockSz = AES_BLOCK_SIZE;
+        return 0;
+#endif
+    default:
+        WOLFSSL_MSG("No PKCS v2 algo found");
+        return ALGO_ID_E;
+
+    }
+}
+
+#endif /* HAVE_PKCS8 || HAVE_PKCS12 */
+
+#ifdef HAVE_PKCS8
+
+int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz,
+        int* algoID, void* heap)
+{
+    word32 tmpIdx = 0;
+
+    if (key == NULL || algoID == NULL)
+        return BAD_FUNC_ARG;
+
+    *algoID = 0;
+
+    #if !defined(NO_RSA) && !defined(NO_ASN_CRYPT)
+    {
+        RsaKey rsa;
+
+        wc_InitRsaKey(&rsa, heap);
+        if (wc_RsaPrivateKeyDecode(key, &tmpIdx, &rsa, keySz) == 0) {
+            *algoID = RSAk;
+        }
+        else {
+            WOLFSSL_MSG("Not RSA DER key");
+        }
+        wc_FreeRsaKey(&rsa);
+    }
+    #endif /* !NO_RSA && !NO_ASN_CRYPT */
+    #if defined(HAVE_ECC) && !defined(NO_ASN_CRYPT)
+    if (*algoID == 0) {
+        ecc_key ecc;
+
+        tmpIdx = 0;
+        wc_ecc_init_ex(&ecc, heap, INVALID_DEVID);
+        if (wc_EccPrivateKeyDecode(key, &tmpIdx, &ecc, keySz) == 0) {
+            *algoID = ECDSAk;
+
+            /* now find oid */
+            if (wc_ecc_get_oid(ecc.dp->oidSum, curveOID, oidSz) < 0) {
+                WOLFSSL_MSG("Error getting ECC curve OID");
+                wc_ecc_free(&ecc);
+                return BAD_FUNC_ARG;
+            }
+        }
+        else {
+            WOLFSSL_MSG("Not ECC DER key either");
+        }
+        wc_ecc_free(&ecc);
+    }
+#endif /* HAVE_ECC && !NO_ASN_CRYPT */
+#if defined(HAVE_ED25519) && !defined(NO_ASN_CRYPT)
+    if (*algoID != RSAk && *algoID != ECDSAk) {
+        ed25519_key ed25519;
+
+        tmpIdx = 0;
+        if (wc_ed25519_init(&ed25519) == 0) {
+            if (wc_Ed25519PrivateKeyDecode(key, &tmpIdx, &ed25519, keySz)
+                                                                         == 0) {
+                *algoID = ED25519k;
+            }
+            else {
+                WOLFSSL_MSG("Not ED25519 DER key");
+            }
+            wc_ed25519_free(&ed25519);
+        }
+        else {
+            WOLFSSL_MSG("GetKeyOID wc_ed25519_init failed");
+        }
+    }
+#endif /* HAVE_ED25519 && !NO_ASN_CRYPT */
+#if defined(HAVE_ED448) && !defined(NO_ASN_CRYPT)
+    if (*algoID != RSAk && *algoID != ECDSAk && *algoID != ED25519k) {
+        ed448_key ed448;
+
+        tmpIdx = 0;
+        if (wc_ed448_init(&ed448) == 0) {
+            if (wc_Ed448PrivateKeyDecode(key, &tmpIdx, &ed448, keySz) == 0) {
+                *algoID = ED448k;
+            }
+            else {
+                WOLFSSL_MSG("Not ED448 DER key");
+            }
+            wc_ed448_free(&ed448);
+        }
+        else {
+            WOLFSSL_MSG("GetKeyOID wc_ed448_init failed");
+        }
+    }
+#endif /* HAVE_ED448 && !NO_ASN_CRYPT */
+
+    /* if flag is not set then is neither RSA or ECC key that could be
+     * found */
+    if (*algoID == 0) {
+        WOLFSSL_MSG("Bad key DER or compile options");
+        return BAD_FUNC_ARG;
+    }
+
+    (void)tmpIdx;
+    (void)curveOID;
+    (void)oidSz;
+    (void)keySz;
+    (void)heap;
+
+    return 1;
+}
+
+#endif /* HAVE_PKCS8 */
+
+#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12)
+
+#define PKCS8_MIN_BLOCK_SIZE 8
+static int Pkcs8Pad(byte* buf, int sz, int blockSz)
+{
+    int i, padSz;
+
+    /* calculate pad size */
+    padSz = blockSz - (sz & (blockSz - 1));
+
+    /* pad with padSz value */
+    if (buf) {
+        for (i = 0; i < padSz; i++) {
+            buf[sz+i] = (byte)(padSz & 0xFF);
+        }
+    }
+
+    /* return adjusted length */
+    return sz + padSz;
+}
+
+#endif /* HAVE_PKCS8 || HAVE_PKCS12 */
+
+#ifdef HAVE_PKCS8
+
+/*
+ * Used when creating PKCS12 shrouded key bags
+ * vPKCS is the version of PKCS to use
+ * vAlgo is the algorithm version to use
+ *
+ * if salt is NULL a random number is generated
+ *
+ * returns the size of encrypted data on success
+ */
+int UnTraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz,
+        const char* password, int passwordSz, int vPKCS, int vAlgo,
+        byte* salt, word32 saltSz, int itt, WC_RNG* rng, void* heap)
+{
+    int algoID = 0;
+    byte*  tmp;
+    word32 tmpSz = 0;
+    word32 sz;
+    word32 seqSz;
+    word32 inOutIdx = 0;
+    word32 totalSz = 0;
+    int    version, id;
+    int    ret;
+    int    blockSz = 0;
+
+    const byte* curveOID = NULL;
+    word32 oidSz   = 0;
+
+#ifdef WOLFSSL_SMALL_STACK
+    byte*  saltTmp = NULL;
+    byte*  cbcIv   = NULL;
+#else
+    byte   saltTmp[MAX_IV_SIZE];
+    byte   cbcIv[MAX_IV_SIZE];
+#endif
+
+    WOLFSSL_ENTER("UnTraditionalEnc()");
+
+    if (saltSz > MAX_SALT_SIZE)
+        return ASN_PARSE_E;
+
+
+    inOutIdx += MAX_SEQ_SZ; /* leave room for size of finished shroud */
+    if (CheckAlgo(vPKCS, vAlgo, &id, &version, &blockSz) < 0) {
+        WOLFSSL_MSG("Bad/Unsupported algorithm ID");
+        return ASN_INPUT_E;  /* Algo ID error */
+    }
+
+    if (out != NULL) {
+        if (*outSz < inOutIdx + MAX_ALGO_SZ + MAX_SALT_SIZE + MAX_SEQ_SZ + 1 +
+                MAX_LENGTH_SZ + MAX_SHORT_SZ + 1)
+                return BUFFER_E;
+
+        if (version == PKCS5v2) {
+            WOLFSSL_MSG("PKCS5v2 Not supported yet\n");
+            return ASN_VERSION_E;
+        }
+
+        if (salt == NULL || saltSz == 0) {
+            saltSz = 8;
+        #ifdef WOLFSSL_SMALL_STACK
+            saltTmp = (byte*)XMALLOC(saltSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
+            if (saltTmp == NULL)
+                return MEMORY_E;
+        #endif
+            salt = saltTmp;
+
+            if ((ret = wc_RNG_GenerateBlock(rng, saltTmp, saltSz)) != 0) {
+                WOLFSSL_MSG("Error generating random salt");
+            #ifdef WOLFSSL_SMALL_STACK
+                if (saltTmp != NULL)
+                    XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+            #endif
+                return ret;
+            }
+        }
+
+
+        /* leave room for a sequence (contains salt and iterations int) */
+        inOutIdx += MAX_SEQ_SZ; sz = 0;
+        inOutIdx += MAX_ALGO_SZ;
+
+        /* place salt in buffer */
+        out[inOutIdx++] = ASN_OCTET_STRING; sz++;
+        tmpSz = SetLength(saltSz, out + inOutIdx);
+        inOutIdx += tmpSz; sz += tmpSz;
+        XMEMCPY(out + inOutIdx, salt, saltSz);
+        inOutIdx += saltSz; sz += saltSz;
+
+        /* place iteration count in buffer */
+        ret = SetShortInt(out, &inOutIdx, itt, *outSz);
+        if (ret < 0) {
+            return ret;
+        }
+        sz += (word32)ret;
+
+        /* wind back index and set sequence then clean up buffer */
+        inOutIdx -= (sz + MAX_SEQ_SZ);
+        tmpSz = SetSequence(sz, out + inOutIdx);
+        XMEMMOVE(out + inOutIdx + tmpSz, out + inOutIdx + MAX_SEQ_SZ, sz);
+        totalSz += tmpSz + sz; sz += tmpSz;
+
+        /* add in algo ID */
+        inOutIdx -= MAX_ALGO_SZ;
+        tmpSz =  SetAlgoID(id, out + inOutIdx, oidPBEType, sz);
+        XMEMMOVE(out + inOutIdx + tmpSz, out + inOutIdx + MAX_ALGO_SZ, sz);
+        totalSz += tmpSz; inOutIdx += tmpSz + sz;
+
+        /* octet string containing encrypted key */
+        out[inOutIdx++] = ASN_OCTET_STRING; totalSz++;
+    }
+
+    /* check key type and get OID if ECC */
+    if ((ret = wc_GetKeyOID(key, keySz, &curveOID, &oidSz, &algoID, heap))< 0) {
+        WOLFSSL_MSG("Error getting key OID");
+        return ret;
+    }
+
+    /* PKCS#8 wrapping around key */
+    if (wc_CreatePKCS8Key(NULL, &tmpSz, key, keySz, algoID, curveOID, oidSz)
+            != LENGTH_ONLY_E) {
+    #ifdef WOLFSSL_SMALL_STACK
+        if (saltTmp != NULL)
+            XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+        return MEMORY_E;
+    }
+
+    /* check if should return max size */
+    if (out == NULL) {
+        /* account for salt size */
+        if (salt == NULL || saltSz == 0) {
+            tmpSz += MAX_SALT_SIZE;
+        }
+        else {
+            tmpSz += saltSz;
+        }
+
+        /* plus 3 for tags */
+        *outSz = tmpSz + MAX_ALGO_SZ + MAX_LENGTH_SZ +MAX_LENGTH_SZ + MAX_SEQ_SZ
+            + MAX_LENGTH_SZ + MAX_SEQ_SZ + 3;
+        return LENGTH_ONLY_E;
+    }
+
+    /* reserve buffer for crypto and make sure it supports full blocks */
+    tmp = (byte*)XMALLOC(tmpSz + (blockSz-1), heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (tmp == NULL) {
+    #ifdef WOLFSSL_SMALL_STACK
+        if (saltTmp != NULL)
+            XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+        return MEMORY_E;
+    }
+
+    if ((ret = wc_CreatePKCS8Key(tmp, &tmpSz, key, keySz, algoID, curveOID,
+                    oidSz)) < 0) {
+        XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+        WOLFSSL_MSG("Error wrapping key with PKCS#8");
+    #ifdef WOLFSSL_SMALL_STACK
+        if (saltTmp != NULL)
+            XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+        return ret;
+    }
+    tmpSz = ret;
+
+    /* adjust size to pad */
+    tmpSz = Pkcs8Pad(tmp, tmpSz, blockSz);
+
+#ifdef WOLFSSL_SMALL_STACK
+    cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (cbcIv == NULL) {
+        if (saltTmp != NULL)
+            XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(salt, heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return MEMORY_E;
+    }
+#endif
+
+    /* encrypt PKCS#8 wrapped key */
+    if ((ret = wc_CryptKey(password, passwordSz, salt, saltSz, itt, id,
+               tmp, tmpSz, version, cbcIv, 1, 0)) < 0) {
+        XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+        WOLFSSL_MSG("Error encrypting key");
+    #ifdef WOLFSSL_SMALL_STACK
+        if (saltTmp != NULL)
+            XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+        if (cbcIv != NULL)
+            XFREE(cbcIv, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+        return ret;  /* encryption failure */
+    }
+    totalSz += tmpSz;
+
+#ifdef WOLFSSL_SMALL_STACK
+    if (saltTmp != NULL)
+        XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (cbcIv != NULL)
+        XFREE(cbcIv, heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    if (*outSz < inOutIdx + tmpSz + MAX_LENGTH_SZ) {
+        XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return BUFFER_E;
+    }
+
+    /* set length of key and copy over encrypted key */
+    seqSz = SetLength(tmpSz, out + inOutIdx);
+    inOutIdx += seqSz; totalSz += seqSz;
+    XMEMCPY(out + inOutIdx, tmp, tmpSz);
+    XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+    /* set total size at beginning */
+    sz = SetSequence(totalSz, out);
+    XMEMMOVE(out + sz, out + MAX_SEQ_SZ, totalSz);
+
+    (void)rng;
+
+    return totalSz + sz;
+}
+
+static int GetAlgoV2(int encAlgId, const byte** oid, int *len, int* id,
+                     int *blkSz)
+{
+    int ret = 0;
+
+    switch (encAlgId) {
+#if !defined(NO_DES3) && !defined(NO_SHA)
+    case DESb:
+        *len = sizeof(blkDesCbcOid);
+        *oid = blkDesCbcOid;
+        *id = PBE_SHA1_DES;
+        *blkSz = 8;
+        break;
+    case DES3b:
+        *len = sizeof(blkDes3CbcOid);
+        *oid = blkDes3CbcOid;
+        *id = PBE_SHA1_DES3;
+        *blkSz = 8;
+        break;
+#endif
+#if defined(WOLFSSL_AES_256) && defined(HAVE_AES_CBC)
+    case AES256CBCb:
+        *len = sizeof(blkAes256CbcOid);
+        *oid = blkAes256CbcOid;
+        *id = PBE_AES256_CBC;
+        *blkSz = 16;
+        break;
+#endif
+    default:
+        (void)len;
+        (void)oid;
+        (void)id;
+        (void)blkSz;
+        ret = ALGO_ID_E;
+    }
+
+    return ret;
+}
+
+/* Converts Encrypted PKCS#8 to 'traditional' (i.e. PKCS#8 removed from
+ * decrypted key.)
+ */
+int TraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz,
+        const char* password, int passwordSz, int vPKCS, int vAlgo,
+        int encAlgId, byte* salt, word32 saltSz, int itt, WC_RNG* rng,
+        void* heap)
+{
+    int ret = 0;
+    int version, blockSz, id;
+    word32 idx = 0, encIdx;
+#ifdef WOLFSSL_SMALL_STACK
+    byte* saltTmp = NULL;
+#else
+    byte saltTmp[MAX_SALT_SIZE];
+#endif
+    byte cbcIv[MAX_IV_SIZE];
+    byte *pkcs8Key = NULL;
+    word32 pkcs8KeySz = 0, padSz = 0;
+    int algId = 0;
+    const byte* curveOid = NULL;
+    word32 curveOidSz = 0;
+    const byte* pbeOid = NULL;
+    word32 pbeOidSz = 0;
+    const byte* encOid = NULL;
+    int encOidSz = 0;
+    word32 pbeLen = 0, kdfLen = 0, encLen = 0;
+    word32 innerLen = 0, outerLen;
+
+    ret = CheckAlgo(vPKCS, vAlgo, &id, &version, &blockSz);
+    /* create random salt if one not provided */
+    if (ret == 0 && (salt == NULL || saltSz == 0)) {
+        saltSz = 8;
+    #ifdef WOLFSSL_SMALL_STACK
+        saltTmp = (byte*)XMALLOC(saltSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
+        if (saltTmp == NULL)
+            return MEMORY_E;
+    #endif
+        salt = saltTmp;
+
+        if ((ret = wc_RNG_GenerateBlock(rng, saltTmp, saltSz)) != 0) {
+            WOLFSSL_MSG("Error generating random salt");
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+        #endif
+            return ret;
+        }
+    }
+
+    if (ret == 0) {
+        /* check key type and get OID if ECC */
+        ret = wc_GetKeyOID(key, keySz, &curveOid, &curveOidSz, &algId, heap);
+        if (ret == 1)
+            ret = 0;
+    }
+    if (ret == 0) {
+        ret = wc_CreatePKCS8Key(NULL, &pkcs8KeySz, key, keySz, algId, curveOid,
+                                                                    curveOidSz);
+        if (ret == LENGTH_ONLY_E)
+            ret = 0;
+    }
+    if (ret == 0) {
+        pkcs8Key = (byte*)XMALLOC(pkcs8KeySz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (pkcs8Key == NULL)
+            ret = MEMORY_E;
+    }
+    if (ret == 0) {
+        ret = wc_CreatePKCS8Key(pkcs8Key, &pkcs8KeySz, key, keySz, algId,
+                                                          curveOid, curveOidSz);
+        if (ret >= 0) {
+            pkcs8KeySz = ret;
+            ret = 0;
+        }
+    }
+
+    if (ret == 0 && version == PKCS5v2)
+        ret = GetAlgoV2(encAlgId, &encOid, &encOidSz, &id, &blockSz);
+
+    if (ret == 0) {
+        padSz = (blockSz - (pkcs8KeySz & (blockSz - 1))) & (blockSz - 1);
+        /* inner = OCT salt INT itt */
+        innerLen = 2 + saltSz + 2 + (itt < 256 ? 1 : 2);
+
+        if (version != PKCS5v2) {
+            pbeOid = OidFromId(id, oidPBEType, &pbeOidSz);
+            /* pbe = OBJ pbse1 SEQ [ inner ] */
+            pbeLen = 2 + pbeOidSz + 2 + innerLen;
+        }
+        else {
+            pbeOid = pbes2;
+            pbeOidSz = sizeof(pbes2);
+            /* kdf = OBJ pbkdf2 [ SEQ innerLen ] */
+            kdfLen = 2 + sizeof(pbkdf2Oid) + 2 + innerLen;
+            /* enc = OBJ enc_alg OCT iv */
+            encLen = 2 + encOidSz + 2 + blockSz;
+            /* pbe = OBJ pbse2 SEQ [ SEQ [ kdf ] SEQ [ enc ] ] */
+            pbeLen = 2 + sizeof(pbes2) + 2 + 2 + kdfLen + 2 + encLen;
+
+            ret = wc_RNG_GenerateBlock(rng, cbcIv, blockSz);
+        }
+    }
+    if (ret == 0) {
+        /* outer = SEQ [ pbe ] OCT encrypted_PKCS#8_key */
+        outerLen = 2 + pbeLen;
+        outerLen += SetOctetString(pkcs8KeySz + padSz, out);
+        outerLen += pkcs8KeySz + padSz;
+
+        idx += SetSequence(outerLen, out + idx);
+
+        encIdx = idx + outerLen - pkcs8KeySz - padSz;
+        /* Put Encrypted content in place. */
+        XMEMCPY(out + encIdx, pkcs8Key, pkcs8KeySz);
+        if (padSz > 0) {
+            XMEMSET(out + encIdx + pkcs8KeySz, padSz, padSz);
+            pkcs8KeySz += padSz;
+        }
+        ret = wc_CryptKey(password, passwordSz, salt, saltSz, itt, id,
+                                out + encIdx, pkcs8KeySz, version, cbcIv, 1, 0);
+    }
+    if (ret == 0) {
+        if (version != PKCS5v2) {
+            /* PBE algorithm */
+            idx += SetSequence(pbeLen, out + idx);
+            idx += SetObjectId(pbeOidSz, out + idx);
+            XMEMCPY(out + idx, pbeOid, pbeOidSz);
+            idx += pbeOidSz;
+        }
+        else {
+            /* PBES2 algorithm identifier */
+            idx += SetSequence(pbeLen, out + idx);
+            idx += SetObjectId(pbeOidSz, out + idx);
+            XMEMCPY(out + idx, pbeOid, pbeOidSz);
+            idx += pbeOidSz;
+            /* PBES2 Parameters: SEQ [ kdf ] SEQ [ enc ] */
+            idx += SetSequence(2 + kdfLen + 2 + encLen, out + idx);
+            /* KDF Algorithm Identifier */
+            idx += SetSequence(kdfLen, out + idx);
+            idx += SetObjectId(sizeof(pbkdf2Oid), out + idx);
+            XMEMCPY(out + idx, pbkdf2Oid, sizeof(pbkdf2Oid));
+            idx += sizeof(pbkdf2Oid);
+        }
+        idx += SetSequence(innerLen, out + idx);
+        idx += SetOctetString(saltSz, out + idx);
+        XMEMCPY(out + idx, salt, saltSz); idx += saltSz;
+        ret = SetShortInt(out, &idx, itt, *outSz);
+        if (ret > 0)
+            ret = 0;
+    }
+    if (ret == 0) {
+        if (version == PKCS5v2) {
+            /* Encryption Algorithm Identifier */
+            idx += SetSequence(encLen, out + idx);
+            idx += SetObjectId(encOidSz, out + idx);
+            XMEMCPY(out + idx, encOid, encOidSz);
+            idx += encOidSz;
+            /* Encryption Algorithm Parameter: CBC IV */
+            idx += SetOctetString(blockSz, out + idx);
+            XMEMCPY(out + idx, cbcIv, blockSz);
+            idx += blockSz;
+        }
+        idx += SetOctetString(pkcs8KeySz, out + idx);
+        /* Default PRF - no need to write out OID */
+        idx += pkcs8KeySz;
+
+        ret = idx;
+    }
+
+    if (pkcs8Key != NULL) {
+        ForceZero(pkcs8Key, pkcs8KeySz);
+        XFREE(pkcs8Key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+#ifdef WOLFSSL_SMALL_STACK
+    if (saltTmp != NULL) {
+        XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+#endif
+
+    (void)rng;
+
+    return ret;
+}
+
+#endif /* HAVE_PKCS8 */
+
+#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12)
+/* decrypt PKCS
+ *
+ * NOTE: input buffer is overwritten with decrypted data!
+ *
+ * input[in/out] data to decrypt and results are written to
+ * sz            size of input buffer
+ * password      password if used. Can be NULL for no password
+ * passwordSz    size of password buffer
+ *
+ * returns the total size of decrypted content on success.
+ */
+int DecryptContent(byte* input, word32 sz, const char* password, int passwordSz)
+{
+    word32 inOutIdx = 0, seqEnd, oid, shaOid = 0;
+    int    ret = 0, first, second, length = 0, version, saltSz, id;
+    int    iterations = 0, keySz = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    byte*  salt = NULL;
+    byte*  cbcIv = NULL;
+#else
+    byte   salt[MAX_SALT_SIZE];
+    byte   cbcIv[MAX_IV_SIZE];
+#endif
+    byte   tag;
+
+    if (passwordSz < 0) {
+        WOLFSSL_MSG("Bad password size");
+        return BAD_FUNC_ARG;
+    }
+
+    if (GetAlgoId(input, &inOutIdx, &oid, oidIgnoreType, sz) < 0) {
+        ERROR_OUT(ASN_PARSE_E, exit_dc);
+    }
+
+    first  = input[inOutIdx - 2];   /* PKCS version always 2nd to last byte */
+    second = input[inOutIdx - 1];   /* version.algo, algo id last byte */
+
+    if (CheckAlgo(first, second, &id, &version, NULL) < 0) {
+        ERROR_OUT(ASN_INPUT_E, exit_dc); /* Algo ID error */
+    }
+
+    if (version == PKCS5v2) {
+        if (GetSequence(input, &inOutIdx, &length, sz) < 0) {
+            ERROR_OUT(ASN_PARSE_E, exit_dc);
+        }
+
+        if (GetAlgoId(input, &inOutIdx, &oid, oidKdfType, sz) < 0) {
+            ERROR_OUT(ASN_PARSE_E, exit_dc);
+        }
+
+        if (oid != PBKDF2_OID) {
+            ERROR_OUT(ASN_PARSE_E, exit_dc);
+        }
+    }
+
+    if (GetSequence(input, &inOutIdx, &length, sz) <= 0) {
+        ERROR_OUT(ASN_PARSE_E, exit_dc);
+    }
+    /* Find the end of this SEQUENCE so we can check for the OPTIONAL and
+     * DEFAULT items. */
+    seqEnd = inOutIdx + length;
+
+    ret = GetOctetString(input, &inOutIdx, &saltSz, sz);
+    if (ret < 0)
+        goto exit_dc;
+
+    if (saltSz > MAX_SALT_SIZE) {
+        ERROR_OUT(ASN_PARSE_E, exit_dc);
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    salt = (byte*)XMALLOC(MAX_SALT_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (salt == NULL) {
+        ERROR_OUT(MEMORY_E, exit_dc);
+    }
+#endif
+
+    XMEMCPY(salt, &input[inOutIdx], saltSz);
+    inOutIdx += saltSz;
+
+    if (GetShortInt(input, &inOutIdx, &iterations, sz) < 0) {
+        ERROR_OUT(ASN_PARSE_E, exit_dc);
+    }
+
+    /* OPTIONAL key length */
+    if (seqEnd > inOutIdx) {
+        word32 localIdx = inOutIdx;
+
+        if (GetASNTag(input, &localIdx, &tag, sz) < 0) {
+            ERROR_OUT(ASN_PARSE_E, exit_dc);
+        }
+
+        if (tag == ASN_INTEGER &&
+                GetShortInt(input, &inOutIdx, &keySz, sz) < 0) {
+            ERROR_OUT(ASN_PARSE_E, exit_dc);
+        }
+    }
+
+    /* DEFAULT HMAC is SHA-1 */
+    if (seqEnd > inOutIdx) {
+        if (GetAlgoId(input, &inOutIdx, &oid, oidHmacType, sz) < 0) {
+            ERROR_OUT(ASN_PARSE_E, exit_dc);
+        }
+
+        shaOid = oid;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (cbcIv == NULL) {
+        ERROR_OUT(MEMORY_E, exit_dc);
+    }
+#endif
+
+    if (version == PKCS5v2) {
+        /* get encryption algo */
+        if (GetAlgoId(input, &inOutIdx, &oid, oidBlkType, sz) < 0) {
+            ERROR_OUT(ASN_PARSE_E, exit_dc);
+        }
+
+        if (CheckAlgoV2(oid, &id, NULL) < 0) {
+            ERROR_OUT(ASN_PARSE_E, exit_dc); /* PKCS v2 algo id error */
+        }
+
+        if (shaOid == 0)
+            shaOid = oid;
+
+        ret = GetOctetString(input, &inOutIdx, &length, sz);
+        if (ret < 0)
+            goto exit_dc;
+
+        if (length > MAX_IV_SIZE) {
+            ERROR_OUT(ASN_PARSE_E, exit_dc);
+        }
+
+        XMEMCPY(cbcIv, &input[inOutIdx], length);
+        inOutIdx += length;
+    }
+
+    if (GetASNTag(input, &inOutIdx, &tag, sz) < 0) {
+        ERROR_OUT(ASN_PARSE_E, exit_dc);
+    }
+
+    if (tag != (ASN_CONTEXT_SPECIFIC | 0) && tag != ASN_OCTET_STRING) {
+        ERROR_OUT(ASN_PARSE_E, exit_dc);
+    }
+
+    if (GetLength(input, &inOutIdx, &length, sz) < 0) {
+        ERROR_OUT(ASN_PARSE_E, exit_dc);
+    }
+
+    ret = wc_CryptKey(password, passwordSz, salt, saltSz, iterations, id,
+                   input + inOutIdx, length, version, cbcIv, 0, shaOid);
+
+exit_dc:
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(salt,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    if (ret == 0) {
+        XMEMMOVE(input, input + inOutIdx, length);
+        ret = length;
+    }
+
+    return ret;
+}
+
+
+/* Remove Encrypted PKCS8 header, move beginning of traditional to beginning
+   of input */
+int ToTraditionalEnc(byte* input, word32 sz,const char* password,
+                     int passwordSz, word32* algId)
+{
+    int ret, length;
+    word32 inOutIdx = 0;
+
+    if (GetSequence(input, &inOutIdx, &length, sz) < 0) {
+        ret = ASN_PARSE_E;
+    }
+    else {
+        ret = DecryptContent(input + inOutIdx, sz - inOutIdx, password,
+                passwordSz);
+        if (ret > 0) {
+            XMEMMOVE(input, input + inOutIdx, ret);
+            ret = ToTraditional_ex(input, ret, algId);
+        }
+    }
+
+    return ret;
+}
+
+#endif /* HAVE_PKCS8 || HAVE_PKCS12 */
+
+#ifdef HAVE_PKCS12
+
+/* encrypt PKCS 12 content
+ *
+ * NOTE: if out is NULL then outSz is set with the total buffer size needed and
+ *       the error value LENGTH_ONLY_E is returned.
+ *
+ * input      data to encrypt
+ * inputSz    size of input buffer
+ * out        buffer to hold the result
+ * outSz      size of out buffer
+ * password   password if used. Can be NULL for no password
+ * passwordSz size of password buffer
+ * vPKCS      version of PKCS i.e. PKCS5v2
+ * vAlgo      algorithm version
+ * salt       buffer holding salt if used. If NULL then a random salt is created
+ * saltSz     size of salt buffer if it is not NULL
+ * itt        number of iterations used
+ * rng        random number generator to use
+ * heap       possible heap hint for mallocs/frees
+ *
+ * returns the total size of encrypted content on success.
+ *
+ * data returned is :
+ * [ seq - obj [ seq -salt,itt]] , construct with encrypted data
+ */
+int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz,
+        const char* password, int passwordSz, int vPKCS, int vAlgo,
+        byte* salt, word32 saltSz, int itt, WC_RNG* rng, void* heap)
+{
+    word32 sz;
+    word32 inOutIdx = 0;
+    word32 tmpIdx   = 0;
+    word32 totalSz  = 0;
+    word32 seqSz;
+    word32 innerSz;
+    int    ret;
+    int    version, id, blockSz = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    byte*  saltTmp = NULL;
+    byte*  cbcIv   = NULL;
+#else
+    byte   saltTmp[MAX_SALT_SIZE];
+    byte   cbcIv[MAX_IV_SIZE];
+#endif
+    byte   seq[MAX_SEQ_SZ];
+    byte   shr[MAX_SHORT_SZ];
+    word32 maxShr = MAX_SHORT_SZ;
+    word32 algoSz;
+    const  byte* algoName;
+
+    (void)heap;
+
+    WOLFSSL_ENTER("EncryptContent()");
+
+    if (CheckAlgo(vPKCS, vAlgo, &id, &version, &blockSz) < 0)
+        return ASN_INPUT_E;  /* Algo ID error */
+
+    if (version == PKCS5v2) {
+        WOLFSSL_MSG("PKCS#5 version 2 not supported yet");
+        return BAD_FUNC_ARG;
+    }
+
+    if (saltSz > MAX_SALT_SIZE)
+        return ASN_PARSE_E;
+
+    if (outSz == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* calculate size */
+    /* size of constructed string at end */
+    sz = Pkcs8Pad(NULL, inputSz, blockSz);
+    totalSz  = ASN_TAG_SZ;
+    totalSz += SetLength(sz, seq);
+    totalSz += sz;
+
+    /* size of sequence holding object id and sub sequence of salt and itt */
+    algoName = OidFromId(id, oidPBEType, &algoSz);
+    if (algoName == NULL) {
+        WOLFSSL_MSG("Unknown Algorithm");
+        return 0;
+    }
+    innerSz = SetObjectId(algoSz, seq);
+    innerSz += algoSz;
+
+    /* get subsequence of salt and itt */
+    if (salt == NULL || saltSz == 0) {
+        sz = 8;
+    }
+    else {
+        sz = saltSz;
+    }
+    seqSz  = SetOctetString(sz, seq);
+    seqSz += sz;
+
+    tmpIdx = 0;
+    seqSz += SetShortInt(shr, &tmpIdx, itt, maxShr);
+    innerSz += seqSz + SetSequence(seqSz, seq);
+    totalSz += innerSz + SetSequence(innerSz, seq);
+
+    if (out == NULL) {
+        *outSz = totalSz;
+        return LENGTH_ONLY_E;
+    }
+
+    inOutIdx = 0;
+    if (totalSz > *outSz)
+        return BUFFER_E;
+
+    inOutIdx += SetSequence(innerSz, out + inOutIdx);
+    inOutIdx += SetObjectId(algoSz, out + inOutIdx);
+    XMEMCPY(out + inOutIdx, algoName, algoSz);
+    inOutIdx += algoSz;
+    inOutIdx += SetSequence(seqSz, out + inOutIdx);
+
+    /* create random salt if one not provided */
+    if (salt == NULL || saltSz == 0) {
+        saltSz = 8;
+    #ifdef WOLFSSL_SMALL_STACK
+        saltTmp = (byte*)XMALLOC(saltSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
+        if (saltTmp == NULL)
+            return MEMORY_E;
+    #endif
+        salt = saltTmp;
+
+        if ((ret = wc_RNG_GenerateBlock(rng, saltTmp, saltSz)) != 0) {
+            WOLFSSL_MSG("Error generating random salt");
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+        #endif
+            return ret;
+        }
+    }
+    inOutIdx += SetOctetString(saltSz, out + inOutIdx);
+    if (saltSz + inOutIdx > *outSz) {
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+        return BUFFER_E;
+    }
+    XMEMCPY(out + inOutIdx, salt, saltSz);
+    inOutIdx += saltSz;
+
+    /* place iteration setting in buffer */
+    ret = SetShortInt(out, &inOutIdx, itt, *outSz);
+    if (ret < 0) {
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+        return ret;
+    }
+
+    if (inOutIdx + 1 > *outSz) {
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+        return BUFFER_E;
+    }
+    out[inOutIdx++] = ASN_CONTEXT_SPECIFIC | 0;
+
+    /* get pad size and verify buffer room */
+    sz = Pkcs8Pad(NULL, inputSz, blockSz);
+    if (sz + inOutIdx > *outSz) {
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+        return BUFFER_E;
+    }
+    inOutIdx += SetLength(sz, out + inOutIdx);
+
+    /* copy input to output buffer and pad end */
+    XMEMCPY(out + inOutIdx, input, inputSz);
+    sz = Pkcs8Pad(out + inOutIdx, inputSz, blockSz);
+#ifdef WOLFSSL_SMALL_STACK
+    cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (cbcIv == NULL) {
+        XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return MEMORY_E;
+    }
+#endif
+
+    /* encrypt */
+    if ((ret = wc_CryptKey(password, passwordSz, salt, saltSz, itt, id,
+                   out + inOutIdx, sz, version, cbcIv, 1, 0)) < 0) {
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(cbcIv,   heap, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+        return ret;  /* encrypt failure */
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(cbcIv,   heap, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    (void)rng;
+
+    return inOutIdx + sz;
+}
+
+
+#endif /* HAVE_PKCS12 */
+#endif /* NO_PWDBASED */
+
+#ifndef NO_RSA
+
+#ifndef HAVE_USER_RSA
+#ifdef WOLFSSL_RENESAS_TSIP
+/* This function is to retrieve key position information in a cert.*
+ * The information will be used to call TSIP TLS-linked API for    *
+ * certificate verification.                                       */
+static int RsaPublicKeyDecodeRawIndex(const byte* input, word32* inOutIdx,
+                                      word32 inSz, word32* key_n,
+                                      word32* key_n_len, word32* key_e,
+                                      word32* key_e_len)
+{
+
+    int ret = 0;
+    int length = 0;
+#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA)
+    byte b;
+#endif
+
+    if (input == NULL || inOutIdx == NULL)
+        return BAD_FUNC_ARG;
+
+    if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+        return ASN_PARSE_E;
+
+#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA)
+    if ((*inOutIdx + 1) > inSz)
+        return BUFFER_E;
+
+    b = input[*inOutIdx];
+    if (b != ASN_INTEGER) {
+        /* not from decoded cert, will have algo id, skip past */
+        if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+            return ASN_PARSE_E;
+
+        if (SkipObjectId(input, inOutIdx, inSz) < 0)
+            return ASN_PARSE_E;
+
+        /* Option NULL ASN.1 tag */
+        if (*inOutIdx  >= inSz) {
+            return BUFFER_E;
+        }
+        if (input[*inOutIdx] == ASN_TAG_NULL) {
+            ret = GetASNNull(input, inOutIdx, inSz);
+            if (ret != 0)
+                return ret;
+        }
+
+        /* should have bit tag length and seq next */
+        ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL);
+        if (ret != 0)
+            return ret;
+
+        if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+            return ASN_PARSE_E;
+    }
+#endif /* OPENSSL_EXTRA */
+
+    /* Get modulus */
+    ret = GetASNInt(input, inOutIdx, &length, inSz);
+    *key_n += *inOutIdx;
+    if (ret < 0) {
+        return ASN_RSA_KEY_E;
+    }
+    if (key_n_len)
+        *key_n_len = length;
+    *inOutIdx += length;
+
+    /* Get exponent */
+    ret = GetASNInt(input, inOutIdx, &length, inSz);
+    *key_e += *inOutIdx;
+    if (ret < 0) {
+        return ASN_RSA_KEY_E;
+    }
+    if (key_e_len)
+        *key_e_len = length;
+
+    return ret;
+}
+#endif /* WOLFSSL_RENESAS_TSIP */
+
+int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx, word32 inSz,
+    const byte** n, word32* nSz, const byte** e, word32* eSz)
+{
+    int ret = 0;
+    int length = 0;
+#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA)
+    word32 localIdx;
+    byte   tag;
+#endif
+
+    if (input == NULL || inOutIdx == NULL)
+        return BAD_FUNC_ARG;
+
+    if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+        return ASN_PARSE_E;
+
+#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA)
+    localIdx = *inOutIdx;
+    if (GetASNTag(input, &localIdx, &tag, inSz) < 0)
+        return BUFFER_E;
+
+    if (tag != ASN_INTEGER) {
+        /* not from decoded cert, will have algo id, skip past */
+        if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+            return ASN_PARSE_E;
+
+        if (SkipObjectId(input, inOutIdx, inSz) < 0)
+            return ASN_PARSE_E;
+
+        /* Option NULL ASN.1 tag */
+        if (*inOutIdx  >= inSz) {
+            return BUFFER_E;
+        }
+
+        localIdx = *inOutIdx;
+        if (GetASNTag(input, &localIdx, &tag, inSz) < 0)
+            return ASN_PARSE_E;
+
+        if (tag == ASN_TAG_NULL) {
+            ret = GetASNNull(input, inOutIdx, inSz);
+            if (ret != 0)
+                return ret;
+        }
+
+        /* should have bit tag length and seq next */
+        ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL);
+        if (ret != 0)
+            return ret;
+
+        if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+            return ASN_PARSE_E;
+    }
+#endif /* OPENSSL_EXTRA */
+
+    /* Get modulus */
+    ret = GetASNInt(input, inOutIdx, &length, inSz);
+    if (ret < 0) {
+        return ASN_RSA_KEY_E;
+    }
+    if (nSz)
+        *nSz = length;
+    if (n)
+        *n = &input[*inOutIdx];
+    *inOutIdx += length;
+
+    /* Get exponent */
+    ret = GetASNInt(input, inOutIdx, &length, inSz);
+    if (ret < 0) {
+        return ASN_RSA_KEY_E;
+    }
+    if (eSz)
+        *eSz = length;
+    if (e)
+        *e = &input[*inOutIdx];
+    *inOutIdx += length;
+
+    return ret;
+}
+
+int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key,
+                       word32 inSz)
+{
+    int ret;
+    const byte *n = NULL, *e = NULL;
+    word32 nSz = 0, eSz = 0;
+
+    if (key == NULL)
+        return BAD_FUNC_ARG;
+
+    ret = wc_RsaPublicKeyDecode_ex(input, inOutIdx, inSz, &n, &nSz, &e, &eSz);
+    if (ret == 0) {
+        ret = wc_RsaPublicKeyDecodeRaw(n, nSz, e, eSz, key);
+    }
+
+    return ret;
+}
+
+/* import RSA public key elements (n, e) into RsaKey structure (key) */
+int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e,
+                             word32 eSz, RsaKey* key)
+{
+    if (n == NULL || e == NULL || key == NULL)
+        return BAD_FUNC_ARG;
+
+    key->type = RSA_PUBLIC;
+
+    if (mp_init(&key->n) != MP_OKAY)
+        return MP_INIT_E;
+
+    if (mp_read_unsigned_bin(&key->n, n, nSz) != 0) {
+        mp_clear(&key->n);
+        return ASN_GETINT_E;
+    }
+#ifdef HAVE_WOLF_BIGINT
+    if ((int)nSz > 0 && wc_bigint_from_unsigned_bin(&key->n.raw, n, nSz) != 0) {
+        mp_clear(&key->n);
+        return ASN_GETINT_E;
+    }
+#endif /* HAVE_WOLF_BIGINT */
+
+    if (mp_init(&key->e) != MP_OKAY) {
+        mp_clear(&key->n);
+        return MP_INIT_E;
+    }
+
+    if (mp_read_unsigned_bin(&key->e, e, eSz) != 0) {
+        mp_clear(&key->n);
+        mp_clear(&key->e);
+        return ASN_GETINT_E;
+    }
+#ifdef HAVE_WOLF_BIGINT
+    if ((int)eSz > 0 && wc_bigint_from_unsigned_bin(&key->e.raw, e, eSz) != 0) {
+        mp_clear(&key->n);
+        mp_clear(&key->e);
+        return ASN_GETINT_E;
+    }
+#endif /* HAVE_WOLF_BIGINT */
+
+#ifdef WOLFSSL_XILINX_CRYPT
+    if (wc_InitRsaHw(key) != 0) {
+        return BAD_STATE_E;
+    }
+#endif
+
+    return 0;
+}
+#endif /* HAVE_USER_RSA */
+#endif /* !NO_RSA */
+
+#ifndef NO_DH
+
+int wc_DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32 inSz)
+{
+    int ret = 0;
+    int length;
+    #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+    word32 oid = 0, temp = 0;
+    #endif
+
+    WOLFSSL_ENTER("wc_DhKeyDecode");
+
+    if (inOutIdx == NULL)
+        return BAD_FUNC_ARG;
+
+    if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+        return ASN_PARSE_E;
+
+    #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+    temp = *inOutIdx;
+    #endif
+
+    /* Assume input started after 1.2.840.113549.1.3.1 dhKeyAgreement */
+    if (GetInt(&key->p,  input, inOutIdx, inSz) < 0 ||
+        GetInt(&key->g,  input, inOutIdx, inSz) < 0) {
+        ret = ASN_DH_KEY_E;
+    }
+
+    #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+    /* If ASN_DH_KEY_E: Check if input started at beginning of key */
+    if (ret == ASN_DH_KEY_E) {
+        /* rewind back to after the first sequence */
+        *inOutIdx = temp;
+        if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+            return ASN_PARSE_E;
+
+        /* Check for dhKeyAgreement */
+        ret = GetObjectId(input, inOutIdx, &oid, oidKeyType, inSz);
+        if (oid != DHk || ret < 0)
+            return ASN_DH_KEY_E;
+
+        if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+            return ASN_PARSE_E;
+
+        if (GetInt(&key->p,  input, inOutIdx, inSz) < 0 ||
+            GetInt(&key->g,  input, inOutIdx, inSz) < 0) {
+            return ASN_DH_KEY_E;
+        }
+    }
+
+    temp = *inOutIdx;
+    ret = (CheckBitString(input, inOutIdx, &length, inSz, 0, NULL) == 0);
+    if (ret > 0) {
+        /* Found Bit String */
+        if (GetInt(&key->pub, input, inOutIdx, inSz) == 0) {
+            WOLFSSL_MSG("Found Public Key");
+            ret = 0;
+        }
+    } else {
+        *inOutIdx = temp;
+        ret = (GetOctetString(input, inOutIdx, &length, inSz) >= 0);
+        if (ret > 0) {
+            /* Found Octet String */
+            if (GetInt(&key->priv, input, inOutIdx, inSz) == 0) {
+                WOLFSSL_MSG("Found Private Key");
+                ret = 0;
+            }
+        } else {
+            /* Don't use length from failed CheckBitString/GetOctetString */
+            *inOutIdx = temp;
+            ret = 0;
+        }
+    }
+    #endif /* WOLFSSL_QT || OPENSSL_ALL */
+
+    WOLFSSL_MSG("wc_DhKeyDecode Success");
+
+    return ret;
+}
+
+
+int wc_DhParamsLoad(const byte* input, word32 inSz, byte* p, word32* pInOutSz,
+                 byte* g, word32* gInOutSz)
+{
+    word32 idx = 0;
+    int    ret;
+    int    length;
+
+    if (GetSequence(input, &idx, &length, inSz) <= 0)
+        return ASN_PARSE_E;
+
+    ret = GetASNInt(input, &idx, &length, inSz);
+    if (ret != 0)
+        return ret;
+
+    if (length <= (int)*pInOutSz) {
+        XMEMCPY(p, &input[idx], length);
+        *pInOutSz = length;
+    }
+    else {
+        return BUFFER_E;
+    }
+    idx += length;
+
+    ret = GetASNInt(input, &idx, &length, inSz);
+    if (ret != 0)
+        return ret;
+
+    if (length <= (int)*gInOutSz) {
+        XMEMCPY(g, &input[idx], length);
+        *gInOutSz = length;
+    }
+    else {
+        return BUFFER_E;
+    }
+
+    return 0;
+}
+#endif /* NO_DH */
+
+
+#ifndef NO_DSA
+
+int DsaPublicKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key,
+                        word32 inSz)
+{
+    int    length;
+    int    ret = 0;
+    word32 oid;
+
+    if (input == NULL || inOutIdx == NULL || key == NULL)
+        return BAD_FUNC_ARG;
+
+    if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+        return ASN_PARSE_E;
+
+    if (GetInt(&key->p,  input, inOutIdx, inSz) < 0 ||
+        GetInt(&key->q,  input, inOutIdx, inSz) < 0 ||
+        GetInt(&key->g,  input, inOutIdx, inSz) < 0 ||
+        GetInt(&key->y,  input, inOutIdx, inSz) < 0 )
+        ret = ASN_DH_KEY_E;
+
+    if (ret != 0) {
+        if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+            return ASN_PARSE_E;
+
+        ret = GetObjectId(input, inOutIdx, &oid, oidIgnoreType, inSz);
+        if (ret != 0)
+            return ret;
+
+        if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+            return ASN_PARSE_E;
+
+        if (GetInt(&key->p,  input, inOutIdx, inSz) < 0 ||
+            GetInt(&key->q,  input, inOutIdx, inSz) < 0 ||
+            GetInt(&key->g,  input, inOutIdx, inSz) < 0)
+            return ASN_DH_KEY_E;
+
+        if (CheckBitString(input, inOutIdx, &length, inSz, 0, NULL) < 0)
+            return ASN_PARSE_E;
+
+        if (GetInt(&key->y,  input, inOutIdx, inSz) < 0 )
+            return ASN_DH_KEY_E;
+
+        ret = 0;
+    }
+
+    key->type = DSA_PUBLIC;
+    return ret;
+}
+
+
+int DsaPrivateKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key,
+                        word32 inSz)
+{
+    int    length, version, ret = 0, temp = 0;
+
+    /* Sanity checks on input */
+    if (input == NULL || inOutIdx == NULL || key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+        return ASN_PARSE_E;
+
+    temp = (int)*inOutIdx;
+
+    /* Default case expects a certificate with OctetString but no version ID */
+    ret = GetInt(&key->p, input, inOutIdx, inSz);
+    if (ret < 0) {
+        mp_clear(&key->p);
+        ret = ASN_PARSE_E;
+    }
+    else {
+        ret = GetInt(&key->q, input, inOutIdx, inSz);
+        if (ret < 0) {
+            mp_clear(&key->p);
+            mp_clear(&key->q);
+            ret = ASN_PARSE_E;
+        }
+        else {
+            ret = GetInt(&key->g, input, inOutIdx, inSz);
+            if (ret < 0) {
+                mp_clear(&key->p);
+                mp_clear(&key->q);
+                mp_clear(&key->g);
+                ret = ASN_PARSE_E;
+            }
+            else {
+                ret = GetOctetString(input, inOutIdx, &length, inSz);
+                if (ret < 0) {
+                    mp_clear(&key->p);
+                    mp_clear(&key->q);
+                    mp_clear(&key->g);
+                    ret = ASN_PARSE_E;
+                }
+                else {
+                    ret = GetInt(&key->y, input, inOutIdx, inSz);
+                    if (ret < 0) {
+                        mp_clear(&key->p);
+                        mp_clear(&key->q);
+                        mp_clear(&key->g);
+                        mp_clear(&key->y);
+                        ret = ASN_PARSE_E;
+                    }
+                }
+            }
+        }
+    }
+    /* An alternate pass if default certificate fails parsing */
+    if (ret == ASN_PARSE_E) {
+        *inOutIdx = temp;
+        if (GetMyVersion(input, inOutIdx, &version, inSz) < 0)
+            return ASN_PARSE_E;
+
+        if (GetInt(&key->p,  input, inOutIdx, inSz) < 0 ||
+            GetInt(&key->q,  input, inOutIdx, inSz) < 0 ||
+            GetInt(&key->g,  input, inOutIdx, inSz) < 0 ||
+            GetInt(&key->y,  input, inOutIdx, inSz) < 0 ||
+            GetInt(&key->x,  input, inOutIdx, inSz) < 0 )
+            return ASN_DH_KEY_E;
+    }
+
+    key->type = DSA_PRIVATE;
+    return 0;
+}
+
+static mp_int* GetDsaInt(DsaKey* key, int idx)
+{
+    if (idx == 0)
+        return &key->p;
+    if (idx == 1)
+        return &key->q;
+    if (idx == 2)
+        return &key->g;
+    if (idx == 3)
+        return &key->y;
+    if (idx == 4)
+        return &key->x;
+
+    return NULL;
+}
+
+/* Release Tmp DSA resources */
+static WC_INLINE void FreeTmpDsas(byte** tmps, void* heap)
+{
+    int i;
+
+    for (i = 0; i < DSA_INTS; i++)
+        XFREE(tmps[i], heap, DYNAMIC_TYPE_DSA);
+
+    (void)heap;
+}
+
+#if !defined(HAVE_SELFTEST) && defined(WOLFSSL_KEY_GEN)
+/* Write a public DSA key to output */
+int wc_SetDsaPublicKey(byte* output, DsaKey* key,
+                           int outLen, int with_header)
+{
+    /* p, g, q = DSA params, y = public exponent */
+#ifdef WOLFSSL_SMALL_STACK
+    byte* p = NULL;
+    byte* g = NULL;
+    byte* q = NULL;
+    byte* y = NULL;
+#else
+    byte p[MAX_DSA_INT_SZ];
+    byte g[MAX_DSA_INT_SZ];
+    byte q[MAX_DSA_INT_SZ];
+    byte y[MAX_DSA_INT_SZ];
+#endif
+    byte innerSeq[MAX_SEQ_SZ];
+    byte outerSeq[MAX_SEQ_SZ];
+    byte bitString[1 + MAX_LENGTH_SZ + 1];
+    int  idx, pSz, gSz, qSz, ySz, innerSeqSz, outerSeqSz, bitStringSz = 0;
+
+    WOLFSSL_ENTER("wc_SetDsaPublicKey");
+
+    if (output == NULL || key == NULL || outLen < MAX_SEQ_SZ) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* p */
+#ifdef WOLFSSL_SMALL_STACK
+    p = (byte*)XMALLOC(MAX_DSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (p == NULL)
+        return MEMORY_E;
+#endif
+    if ((pSz = SetASNIntMP(&key->p, MAX_DSA_INT_SZ, p)) < 0) {
+        WOLFSSL_MSG("SetASNIntMP Error with p");
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+        return pSz;
+    }
+
+    /* q */
+#ifdef WOLFSSL_SMALL_STACK
+    q = (byte*)XMALLOC(MAX_DSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (q == NULL)
+        return MEMORY_E;
+#endif
+    if ((qSz = SetASNIntMP(&key->q, MAX_DSA_INT_SZ, q)) < 0) {
+        WOLFSSL_MSG("SetASNIntMP Error with q");
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(q, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+        return qSz;
+    }
+
+    /* g */
+#ifdef WOLFSSL_SMALL_STACK
+    g = (byte*)XMALLOC(MAX_DSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (g == NULL)
+        return MEMORY_E;
+#endif
+    if ((gSz = SetASNIntMP(&key->g, MAX_DSA_INT_SZ, g)) < 0) {
+        WOLFSSL_MSG("SetASNIntMP Error with g");
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(q, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(g, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+        return gSz;
+    }
+
+    /* y */
+#ifdef WOLFSSL_SMALL_STACK
+    y = (byte*)XMALLOC(MAX_DSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (y == NULL)
+        return MEMORY_E;
+#endif
+    if ((ySz = SetASNIntMP(&key->y, MAX_DSA_INT_SZ, y)) < 0) {
+        WOLFSSL_MSG("SetASNIntMP Error with y");
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(q, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(g, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(y, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+        return ySz;
+    }
+
+    innerSeqSz  = SetSequence(pSz + qSz + gSz, innerSeq);
+
+    /* check output size */
+    if ((innerSeqSz + pSz + qSz + gSz) > outLen) {
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(p,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(q,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(g,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(y,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+        WOLFSSL_MSG("Error, output size smaller than outlen");
+        return BUFFER_E;
+    }
+
+    if (with_header) {
+        int algoSz;
+#ifdef WOLFSSL_SMALL_STACK
+        byte* algo = NULL;
+
+        algo = (byte*)XMALLOC(MAX_ALGO_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        if (algo == NULL) {
+            XFREE(p,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            XFREE(q,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            XFREE(g,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            XFREE(y,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            return MEMORY_E;
+        }
+#else
+        byte algo[MAX_ALGO_SZ];
+#endif
+        algoSz = SetAlgoID(DSAk, algo, oidKeyType, 0);
+        bitStringSz  = SetBitString(ySz, 0, bitString);
+        outerSeqSz = SetSequence(algoSz + innerSeqSz + pSz + qSz + gSz,
+                                                                      outerSeq);
+
+        idx = SetSequence(algoSz + innerSeqSz + pSz + qSz + gSz + bitStringSz +
+                                                      ySz + outerSeqSz, output);
+
+        /* check output size */
+        if ((idx + algoSz + bitStringSz + innerSeqSz + pSz + qSz + gSz + ySz) >
+                                                                       outLen) {
+            #ifdef WOLFSSL_SMALL_STACK
+                XFREE(p,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+                XFREE(q,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+                XFREE(g,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+                XFREE(y,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+                XFREE(algo, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            #endif
+            WOLFSSL_MSG("Error, output size smaller than outlen");
+            return BUFFER_E;
+        }
+
+        /* outerSeq */
+        XMEMCPY(output + idx, outerSeq, outerSeqSz);
+        idx += outerSeqSz;
+        /* algo */
+        XMEMCPY(output + idx, algo, algoSz);
+        idx += algoSz;
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(algo, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+    } else {
+        idx = 0;
+    }
+
+    /* innerSeq */
+    XMEMCPY(output + idx, innerSeq, innerSeqSz);
+    idx += innerSeqSz;
+    /* p */
+    XMEMCPY(output + idx, p, pSz);
+    idx += pSz;
+    /* q */
+    XMEMCPY(output + idx, q, qSz);
+    idx += qSz;
+    /* g */
+    XMEMCPY(output + idx, g, gSz);
+    idx += gSz;
+    /* bit string */
+    XMEMCPY(output + idx, bitString, bitStringSz);
+    idx += bitStringSz;
+    /* y */
+    XMEMCPY(output + idx, y, ySz);
+    idx += ySz;
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(p,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(q,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(g,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(y,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+    return idx;
+}
+
+/* Convert DSA Public key to DER format, write to output (inLen), return bytes
+   written */
+int wc_DsaKeyToPublicDer(DsaKey* key, byte* output, word32 inLen)
+{
+    return wc_SetDsaPublicKey(output, key, inLen, 1);
+}
+#endif /* !HAVE_SELFTEST && WOLFSSL_KEY_GEN */
+
+/* Convert private DsaKey key to DER format, write to output (inLen),
+   return bytes written */
+int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen)
+{
+    word32 seqSz, verSz, rawLen, intTotalLen = 0;
+    word32 sizes[DSA_INTS];
+    int    i, j, outLen, ret = 0, mpSz;
+
+    byte  seq[MAX_SEQ_SZ];
+    byte  ver[MAX_VERSION_SZ];
+    byte* tmps[DSA_INTS];
+
+    if (!key || !output)
+        return BAD_FUNC_ARG;
+
+    if (key->type != DSA_PRIVATE)
+        return BAD_FUNC_ARG;
+
+    for (i = 0; i < DSA_INTS; i++)
+        tmps[i] = NULL;
+
+    /* write all big ints from key to DER tmps */
+    for (i = 0; i < DSA_INTS; i++) {
+        mp_int* keyInt = GetDsaInt(key, i);
+
+        rawLen = mp_unsigned_bin_size(keyInt) + 1;
+        tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap,
+                                                              DYNAMIC_TYPE_DSA);
+        if (tmps[i] == NULL) {
+            ret = MEMORY_E;
+            break;
+        }
+
+        mpSz = SetASNIntMP(keyInt, -1, tmps[i]);
+        if (mpSz < 0) {
+            ret = mpSz;
+            break;
+        }
+        intTotalLen += (sizes[i] = mpSz);
+    }
+
+    if (ret != 0) {
+        FreeTmpDsas(tmps, key->heap);
+        return ret;
+    }
+
+    /* make headers */
+    verSz = SetMyVersion(0, ver, FALSE);
+    seqSz = SetSequence(verSz + intTotalLen, seq);
+
+    outLen = seqSz + verSz + intTotalLen;
+    if (outLen > (int)inLen) {
+        FreeTmpDsas(tmps, key->heap);
+        return BAD_FUNC_ARG;
+    }
+
+    /* write to output */
+    XMEMCPY(output, seq, seqSz);
+    j = seqSz;
+    XMEMCPY(output + j, ver, verSz);
+    j += verSz;
+
+    for (i = 0; i < DSA_INTS; i++) {
+        XMEMCPY(output + j, tmps[i], sizes[i]);
+        j += sizes[i];
+    }
+    FreeTmpDsas(tmps, key->heap);
+
+    return outLen;
+}
+
+#endif /* NO_DSA */
+
+void InitDecodedCert(DecodedCert* cert,
+                     const byte* source, word32 inSz, void* heap)
+{
+    if (cert != NULL) {
+        XMEMSET(cert, 0, sizeof(DecodedCert));
+
+        cert->subjectCNEnc    = CTC_UTF8;
+        cert->issuer[0]       = '\0';
+        cert->subject[0]      = '\0';
+        cert->source          = source;  /* don't own */
+        cert->maxIdx          = inSz;    /* can't go over this index */
+        cert->heap            = heap;
+        cert->maxPathLen      = WOLFSSL_MAX_PATH_LEN;
+    #ifdef WOLFSSL_CERT_GEN
+        cert->subjectSNEnc    = CTC_UTF8;
+        cert->subjectCEnc     = CTC_PRINTABLE;
+        cert->subjectLEnc     = CTC_UTF8;
+        cert->subjectSTEnc    = CTC_UTF8;
+        cert->subjectOEnc     = CTC_UTF8;
+        cert->subjectOUEnc    = CTC_UTF8;
+    #endif /* WOLFSSL_CERT_GEN */
+
+    #ifndef NO_CERTS
+        InitSignatureCtx(&cert->sigCtx, heap, INVALID_DEVID);
+    #endif
+    }
+}
+
+
+void FreeAltNames(DNS_entry* altNames, void* heap)
+{
+    (void)heap;
+
+    while (altNames) {
+        DNS_entry* tmp = altNames->next;
+
+        XFREE(altNames->name, heap, DYNAMIC_TYPE_ALTNAME);
+        XFREE(altNames,       heap, DYNAMIC_TYPE_ALTNAME);
+        altNames = tmp;
+    }
+}
+
+#ifndef IGNORE_NAME_CONSTRAINTS
+
+void FreeNameSubtrees(Base_entry* names, void* heap)
+{
+    (void)heap;
+
+    while (names) {
+        Base_entry* tmp = names->next;
+
+        XFREE(names->name, heap, DYNAMIC_TYPE_ALTNAME);
+        XFREE(names,       heap, DYNAMIC_TYPE_ALTNAME);
+        names = tmp;
+    }
+}
+
+#endif /* IGNORE_NAME_CONSTRAINTS */
+
+void FreeDecodedCert(DecodedCert* cert)
+{
+    if (cert == NULL)
+        return;
+    if (cert->subjectCNStored == 1)
+        XFREE(cert->subjectCN, cert->heap, DYNAMIC_TYPE_SUBJECT_CN);
+    if (cert->pubKeyStored == 1)
+        XFREE((void*)cert->publicKey, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    if (cert->weOwnAltNames && cert->altNames)
+        FreeAltNames(cert->altNames, cert->heap);
+#ifndef IGNORE_NAME_CONSTRAINTS
+    if (cert->altEmailNames)
+        FreeAltNames(cert->altEmailNames, cert->heap);
+    if (cert->permittedNames)
+        FreeNameSubtrees(cert->permittedNames, cert->heap);
+    if (cert->excludedNames)
+        FreeNameSubtrees(cert->excludedNames, cert->heap);
+#endif /* IGNORE_NAME_CONSTRAINTS */
+#ifdef WOLFSSL_SEP
+    XFREE(cert->deviceType, cert->heap, DYNAMIC_TYPE_X509_EXT);
+    XFREE(cert->hwType, cert->heap, DYNAMIC_TYPE_X509_EXT);
+    XFREE(cert->hwSerialNum, cert->heap, DYNAMIC_TYPE_X509_EXT);
+#endif /* WOLFSSL_SEP */
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+    if (cert->issuerName.fullName != NULL)
+        XFREE(cert->issuerName.fullName, cert->heap, DYNAMIC_TYPE_X509);
+    if (cert->subjectName.fullName != NULL)
+        XFREE(cert->subjectName.fullName, cert->heap, DYNAMIC_TYPE_X509);
+#endif /* OPENSSL_EXTRA */
+#ifdef WOLFSSL_RENESAS_TSIP_TLS
+    if (cert->tsip_encRsaKeyIdx != NULL)
+        XFREE(cert->tsip_encRsaKeyIdx, cert->heap, DYNAMIC_TYPE_RSA);
+#endif
+#ifndef NO_CERTS
+    FreeSignatureCtx(&cert->sigCtx);
+#endif
+}
+
+static int GetCertHeader(DecodedCert* cert)
+{
+    int ret = 0, len;
+
+    if (GetSequence(cert->source, &cert->srcIdx, &len, cert->maxIdx) < 0)
+        return ASN_PARSE_E;
+
+    /* Reset the max index for the size indicated in the outer wrapper. */
+    cert->maxIdx = len + cert->srcIdx;
+    cert->certBegin = cert->srcIdx;
+
+    if (GetSequence(cert->source, &cert->srcIdx, &len, cert->maxIdx) < 0)
+        return ASN_PARSE_E;
+
+    cert->sigIndex = len + cert->srcIdx;
+    if (cert->sigIndex > cert->maxIdx)
+        return ASN_PARSE_E;
+
+    if (GetExplicitVersion(cert->source, &cert->srcIdx, &cert->version,
+                                                            cert->sigIndex) < 0)
+        return ASN_PARSE_E;
+
+    if (GetSerialNumber(cert->source, &cert->srcIdx, cert->serial,
+                                           &cert->serialSz, cert->sigIndex) < 0)
+        return ASN_PARSE_E;
+
+    return ret;
+}
+
+#if !defined(NO_RSA)
+/* Store Rsa Key, may save later, Dsa could use in future */
+static int StoreRsaKey(DecodedCert* cert, word32 bitStringEnd)
+{
+    int    length;
+    word32 recvd = cert->srcIdx;
+
+    if (GetSequence(cert->source, &cert->srcIdx, &length, bitStringEnd) < 0)
+        return ASN_PARSE_E;
+
+    recvd = cert->srcIdx - recvd;
+    length += recvd;
+
+    while (recvd--)
+       cert->srcIdx--;
+#if defined(WOLFSSL_RENESAS_TSIP)
+    cert->sigCtx.pubkey_n_start = cert->sigCtx.pubkey_e_start = cert->srcIdx;
+#endif
+    cert->pubKeySize = length;
+    cert->publicKey = cert->source + cert->srcIdx;
+    cert->srcIdx += length;
+
+    return 0;
+}
+#endif /* !NO_RSA */
+
+#ifdef HAVE_ECC
+
+    /* return 0 on success if the ECC curve oid sum is supported */
+    static int CheckCurve(word32 oid)
+    {
+        int ret = 0;
+        word32 oidSz = 0;
+
+        ret = wc_ecc_get_oid(oid, NULL, &oidSz);
+        if (ret < 0 || oidSz == 0) {
+            WOLFSSL_MSG("CheckCurve not found");
+            ret = ALGO_ID_E;
+        }
+
+        return ret;
+    }
+
+#endif /* HAVE_ECC */
+
+static int GetKey(DecodedCert* cert)
+{
+    int length;
+#if !defined(NO_DSA) && defined(WOLFSSL_QT)
+    int tmpLen;
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_NTRU)
+    int tmpIdx = cert->srcIdx;
+#endif
+
+    if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
+        return ASN_PARSE_E;
+
+#if !defined(NO_DSA) && defined(WOLFSSL_QT)
+    tmpLen = length + 4;
+#endif
+
+    if (GetAlgoId(cert->source, &cert->srcIdx,
+                  &cert->keyOID, oidKeyType, cert->maxIdx) < 0)
+        return ASN_PARSE_E;
+
+    switch (cert->keyOID) {
+   #ifndef NO_RSA
+        case RSAk:
+        {
+            int ret;
+
+            ret = CheckBitString(cert->source, &cert->srcIdx, &length,
+                                 cert->maxIdx, 1, NULL);
+            if (ret != 0)
+                return ret;
+
+            #ifdef HAVE_OCSP
+                ret = CalcHashId(cert->source + cert->srcIdx, length,
+                        cert->subjectKeyHash);
+                if (ret != 0)
+                    return ret;
+            #endif
+
+            return StoreRsaKey(cert, cert->srcIdx + length);
+        }
+
+    #endif /* NO_RSA */
+    #ifdef HAVE_NTRU
+        case NTRUk:
+        {
+            const byte* key = &cert->source[tmpIdx];
+            byte*       next = (byte*)key;
+            word16      keyLen;
+            word32      rc;
+            word32      remaining = cert->maxIdx - cert->srcIdx;
+            byte*       publicKey;
+#ifdef WOLFSSL_SMALL_STACK
+            byte*       keyBlob = NULL;
+#else
+            byte        keyBlob[MAX_NTRU_KEY_SZ];
+#endif
+            rc = ntru_crypto_ntru_encrypt_subjectPublicKeyInfo2PublicKey(key,
+                                &keyLen, NULL, &next, &remaining);
+            if (rc != NTRU_OK)
+                return ASN_NTRU_KEY_E;
+            if (keyLen > MAX_NTRU_KEY_SZ)
+                return ASN_NTRU_KEY_E;
+
+#ifdef WOLFSSL_SMALL_STACK
+            keyBlob = (byte*)XMALLOC(MAX_NTRU_KEY_SZ, cert->heap,
+                                     DYNAMIC_TYPE_TMP_BUFFER);
+            if (keyBlob == NULL)
+                return MEMORY_E;
+#endif
+
+            rc = ntru_crypto_ntru_encrypt_subjectPublicKeyInfo2PublicKey(key,
+                                &keyLen, keyBlob, &next, &remaining);
+            if (rc != NTRU_OK) {
+#ifdef WOLFSSL_SMALL_STACK
+                XFREE(keyBlob, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+                return ASN_NTRU_KEY_E;
+            }
+
+            if ( (next - key) < 0) {
+#ifdef WOLFSSL_SMALL_STACK
+                XFREE(keyBlob, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+                return ASN_NTRU_KEY_E;
+            }
+
+            cert->srcIdx = tmpIdx + (int)(next - key);
+
+            publicKey = (byte*)XMALLOC(keyLen, cert->heap,
+                                       DYNAMIC_TYPE_PUBLIC_KEY);
+            if (publicKey == NULL) {
+#ifdef WOLFSSL_SMALL_STACK
+                XFREE(keyBlob, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+                return MEMORY_E;
+            }
+            XMEMCPY(publicKey, keyBlob, keyLen);
+            cert->publicKey = publicKey;
+            cert->pubKeyStored = 1;
+            cert->pubKeySize   = keyLen;
+
+#ifdef WOLFSSL_SMALL_STACK
+            XFREE(keyBlob, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+            return 0;
+        }
+    #endif /* HAVE_NTRU */
+    #ifdef HAVE_ECC
+        case ECDSAk:
+        {
+            int ret;
+            byte seq[5];
+            int pubLen = length + 1 + SetLength(length, seq);
+            word32 localIdx;
+            byte* publicKey;
+            byte  tag;
+
+            localIdx = cert->srcIdx;
+            if (GetASNTag(cert->source, &localIdx, &tag, cert->maxIdx) < 0)
+                return ASN_PARSE_E;
+
+            if (tag != (ASN_SEQUENCE | ASN_CONSTRUCTED)) {
+                if (GetObjectId(cert->source, &cert->srcIdx,
+                            &cert->pkCurveOID, oidCurveType, cert->maxIdx) < 0)
+                    return ASN_PARSE_E;
+
+                if (CheckCurve(cert->pkCurveOID) < 0)
+                    return ECC_CURVE_OID_E;
+
+                /* key header */
+                ret = CheckBitString(cert->source, &cert->srcIdx, &length,
+                                                         cert->maxIdx, 1, NULL);
+                if (ret != 0)
+                    return ret;
+            #ifdef HAVE_OCSP
+                ret = CalcHashId(cert->source + cert->srcIdx, length,
+                        cert->subjectKeyHash);
+                if (ret != 0)
+                    return ret;
+            #endif
+            }
+
+            publicKey = (byte*)XMALLOC(pubLen, cert->heap,
+                                       DYNAMIC_TYPE_PUBLIC_KEY);
+            if (publicKey == NULL)
+                return MEMORY_E;
+            XMEMCPY(publicKey, &cert->source[tmpIdx], pubLen);
+            cert->publicKey = publicKey;
+            cert->pubKeyStored = 1;
+            cert->pubKeySize   = pubLen;
+
+            cert->srcIdx = tmpIdx + pubLen;
+
+            return 0;
+        }
+    #endif /* HAVE_ECC */
+    #ifdef HAVE_ED25519
+        case ED25519k:
+        {
+            byte* publicKey;
+            int ret;
+
+            cert->pkCurveOID = ED25519k;
+
+            ret = CheckBitString(cert->source, &cert->srcIdx, &length,
+                                 cert->maxIdx, 1, NULL);
+            if (ret != 0)
+                return ret;
+
+            #ifdef HAVE_OCSP
+                ret = CalcHashId(cert->source + cert->srcIdx, length,
+                        cert->subjectKeyHash);
+                if (ret != 0)
+                    return ret;
+            #endif
+
+            publicKey = (byte*) XMALLOC(length, cert->heap,
+                                        DYNAMIC_TYPE_PUBLIC_KEY);
+            if (publicKey == NULL)
+                return MEMORY_E;
+            XMEMCPY(publicKey, &cert->source[cert->srcIdx], length);
+            cert->publicKey = publicKey;
+            cert->pubKeyStored = 1;
+            cert->pubKeySize   = length;
+
+            cert->srcIdx += length;
+
+            return 0;
+        }
+    #endif /* HAVE_ED25519 */
+    #ifdef HAVE_ED448
+        case ED448k:
+        {
+            byte* publicKey;
+            int ret;
+
+            cert->pkCurveOID = ED448k;
+
+            ret = CheckBitString(cert->source, &cert->srcIdx, &length,
+                                 cert->maxIdx, 1, NULL);
+            if (ret != 0)
+                return ret;
+
+            #ifdef HAVE_OCSP
+                ret = CalcHashId(cert->source + cert->srcIdx, length,
+                                 cert->subjectKeyHash);
+                if (ret != 0)
+                    return ret;
+            #endif
+
+            publicKey = (byte*) XMALLOC(length, cert->heap,
+                                        DYNAMIC_TYPE_PUBLIC_KEY);
+            if (publicKey == NULL)
+                return MEMORY_E;
+            XMEMCPY(publicKey, &cert->source[cert->srcIdx], length);
+            cert->publicKey = publicKey;
+            cert->pubKeyStored = 1;
+            cert->pubKeySize   = length;
+
+            cert->srcIdx += length;
+
+            return 0;
+        }
+    #endif /* HAVE_ED448 */
+    #if !defined(NO_DSA) && defined(WOLFSSL_QT)
+        case DSAk:
+        {
+            int ret;
+            ret = GetSequence(cert->source, &cert->srcIdx, &length,
+                           cert->maxIdx);
+            if (ret < 0)
+                return ret;
+
+            ret = SkipInt(cert->source, &cert->srcIdx, cert->maxIdx);
+            if (ret != 0)
+                return ret;
+            ret = SkipInt(cert->source, &cert->srcIdx, cert->maxIdx);
+            if (ret != 0)
+                return ret;
+            ret = SkipInt(cert->source, &cert->srcIdx, cert->maxIdx);
+            if (ret != 0)
+                return ret;
+
+            ret = CheckBitString(cert->source, &cert->srcIdx, &length,
+                                                         cert->maxIdx, 1, NULL);
+            if (ret != 0)
+                return ret;
+
+            ret = GetASNInt(cert->source, &cert->srcIdx, &length, cert->maxIdx);
+            if (ret !=0)
+                return ASN_PARSE_E;
+
+            cert->publicKey = cert->source + tmpIdx;
+            cert->pubKeySize = tmpLen;
+            cert->srcIdx += length;
+            return 0;
+        }
+    #endif /* NO_DSA && QT */
+        default:
+            return ASN_UNKNOWN_OID_E;
+    }
+}
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+#if defined(HAVE_ECC)
+/* Converts ECC curve enum values in ecc_curve_id to the associated OpenSSL NID
+    value */
+WOLFSSL_API int EccEnumToNID(int n)
+{
+    WOLFSSL_ENTER("EccEnumToNID()");
+
+    switch(n) {
+        case ECC_SECP192R1:
+            return NID_X9_62_prime192v1;
+        case ECC_PRIME192V2:
+            return NID_X9_62_prime192v2;
+        case ECC_PRIME192V3:
+            return NID_X9_62_prime192v3;
+        case ECC_PRIME239V1:
+            return NID_X9_62_prime239v1;
+        case ECC_PRIME239V2:
+            return NID_X9_62_prime239v2;
+        case ECC_PRIME239V3:
+            return NID_X9_62_prime239v3;
+        case ECC_SECP256R1:
+            return NID_X9_62_prime256v1;
+        case ECC_SECP112R1:
+            return NID_secp112r1;
+        case ECC_SECP112R2:
+            return NID_secp112r2;
+        case ECC_SECP128R1:
+            return NID_secp128r1;
+        case ECC_SECP128R2:
+            return NID_secp128r2;
+        case ECC_SECP160R1:
+            return NID_secp160r1;
+        case ECC_SECP160R2:
+            return NID_secp160r2;
+        case ECC_SECP224R1:
+            return NID_secp224r1;
+        case ECC_SECP384R1:
+            return NID_secp384r1;
+        case ECC_SECP521R1:
+            return NID_secp521r1;
+        case ECC_SECP160K1:
+            return NID_secp160k1;
+        case ECC_SECP192K1:
+            return NID_secp192k1;
+        case ECC_SECP224K1:
+            return NID_secp224k1;
+        case ECC_SECP256K1:
+            return NID_secp256k1;
+        case ECC_BRAINPOOLP160R1:
+            return NID_brainpoolP160r1;
+        case ECC_BRAINPOOLP192R1:
+            return NID_brainpoolP192r1;
+        case ECC_BRAINPOOLP224R1:
+            return NID_brainpoolP224r1;
+        case ECC_BRAINPOOLP256R1:
+            return NID_brainpoolP256r1;
+        case ECC_BRAINPOOLP320R1:
+            return NID_brainpoolP320r1;
+        case ECC_BRAINPOOLP384R1:
+            return NID_brainpoolP384r1;
+        case ECC_BRAINPOOLP512R1:
+            return NID_brainpoolP512r1;
+        default:
+            WOLFSSL_MSG("NID not found");
+            return -1;
+    }
+}
+#endif /* HAVE_ECC */
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+int wc_OBJ_sn2nid(const char *sn)
+{
+    const struct {
+        const char *sn;
+        int  nid;
+    } sn2nid[] = {
+        {WOLFSSL_COMMON_NAME, NID_commonName},
+        {WOLFSSL_COUNTRY_NAME, NID_countryName},
+        {WOLFSSL_LOCALITY_NAME, NID_localityName},
+        {WOLFSSL_STATE_NAME, NID_stateOrProvinceName},
+        {WOLFSSL_ORG_NAME, NID_organizationName},
+        {WOLFSSL_ORGUNIT_NAME, NID_organizationalUnitName},
+        {WOLFSSL_EMAIL_ADDR, NID_emailAddress},
+        {NULL, -1}};
+
+    int i;
+    #ifdef HAVE_ECC
+    int eccEnum;
+    #endif
+    WOLFSSL_ENTER("OBJ_sn2nid");
+    for(i=0; sn2nid[i].sn != NULL; i++) {
+        if(XSTRNCMP(sn, sn2nid[i].sn, XSTRLEN(sn2nid[i].sn)) == 0) {
+            return sn2nid[i].nid;
+        }
+    }
+    #ifdef HAVE_ECC
+    /* Nginx uses this OpenSSL string. */
+    if (XSTRNCMP(sn, "prime256v1", 10) == 0)
+        sn = "SECP256R1";
+    if (XSTRNCMP(sn, "secp384r1", 10) == 0)
+        sn = "SECP384R1";
+    /* find based on name and return NID */
+    for (i = 0; ecc_sets[i].size != 0 && ecc_sets[i].name != NULL; i++) {
+        if (XSTRNCMP(sn, ecc_sets[i].name, ECC_MAXNAME) == 0) {
+            eccEnum = ecc_sets[i].id;
+            /* Convert enum value in ecc_curve_id to OpenSSL NID */
+            return EccEnumToNID(eccEnum);
+        }
+    }
+    #endif
+
+    return NID_undef;
+}
+#endif
+
+/* Routine for calculating hashId */
+int CalcHashId(const byte* data, word32 len, byte* hash)
+{
+    int ret;
+
+#ifdef WOLF_CRYPTO_CB
+    /* try to use a registered crypto callback */
+    ret = wc_CryptoCb_Sha256Hash(NULL, data, len, hash);
+    if (ret != CRYPTOCB_UNAVAILABLE)
+        return ret;
+    /* fall-through when unavailable */
+#endif
+
+#if defined(NO_SHA) && !defined(NO_SHA256)
+    ret = wc_Sha256Hash(data, len, hash);
+#elif !defined(NO_SHA)
+    ret = wc_ShaHash(data, len, hash);
+#else
+    ret = NOT_COMPILED_IN;
+#endif
+
+    return ret;
+}
+
+/* process NAME, either issuer or subject */
+static int GetName(DecodedCert* cert, int nameType, int maxIdx)
+{
+    int    length;  /* length of all distinguished names */
+    int    dummy;
+    int    ret;
+    char*  full;
+    byte*  hash;
+    word32 idx, localIdx = 0;
+    byte   tag;
+    #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+        DecodedName* dName =
+                  (nameType == ISSUER) ? &cert->issuerName : &cert->subjectName;
+        int dcnum = 0;
+        #ifdef OPENSSL_EXTRA
+        int count = 0;
+        #endif
+    #endif /* OPENSSL_EXTRA */
+
+    WOLFSSL_MSG("Getting Cert Name");
+
+    if (nameType == ISSUER) {
+        full = cert->issuer;
+        hash = cert->issuerHash;
+    }
+    else {
+        full = cert->subject;
+        hash = cert->subjectHash;
+    }
+
+    if (cert->srcIdx >= (word32)maxIdx) {
+        return BUFFER_E;
+    }
+
+    localIdx = cert->srcIdx;
+    if (GetASNTag(cert->source, &localIdx, &tag, maxIdx) < 0) {
+        return ASN_PARSE_E;
+    }
+
+    if (tag == ASN_OBJECT_ID) {
+        WOLFSSL_MSG("Trying optional prefix...");
+
+        if (SkipObjectId(cert->source, &cert->srcIdx, maxIdx) < 0)
+            return ASN_PARSE_E;
+        WOLFSSL_MSG("Got optional prefix");
+    }
+
+    /* For OCSP, RFC2560 section 4.1.1 states the issuer hash should be
+     * calculated over the entire DER encoding of the Name field, including
+     * the tag and length. */
+    idx = cert->srcIdx;
+    if (GetSequence(cert->source, &cert->srcIdx, &length, maxIdx) < 0)
+        return ASN_PARSE_E;
+
+    ret = CalcHashId(&cert->source[idx], length + cert->srcIdx - idx, hash);
+    if (ret != 0)
+        return ret;
+
+    length += cert->srcIdx;
+    idx = 0;
+
+#if defined(HAVE_PKCS7) || defined(WOLFSSL_CERT_EXT)
+    /* store pointer to raw issuer */
+    if (nameType == ISSUER) {
+        cert->issuerRaw = &cert->source[cert->srcIdx];
+        cert->issuerRawLen = length - cert->srcIdx;
+    }
+#endif
+#ifndef IGNORE_NAME_CONSTRAINTS
+    if (nameType == SUBJECT) {
+        cert->subjectRaw = &cert->source[cert->srcIdx];
+        cert->subjectRawLen = length - cert->srcIdx;
+    }
+#endif
+
+    while (cert->srcIdx < (word32)length) {
+        byte        b       = 0;
+        byte        joint[3];
+        byte        tooBig  = FALSE;
+        int         oidSz;
+        const char* copy    = NULL;
+        int         copyLen = 0;
+        int         strLen  = 0;
+        byte        id      = 0;
+
+        if (GetSet(cert->source, &cert->srcIdx, &dummy, maxIdx) < 0) {
+            WOLFSSL_MSG("Cert name lacks set header, trying sequence");
+        }
+
+        if (GetSequence(cert->source, &cert->srcIdx, &dummy, maxIdx) <= 0)
+            return ASN_PARSE_E;
+
+        ret = GetASNObjectId(cert->source, &cert->srcIdx, &oidSz, maxIdx);
+        if (ret != 0)
+            return ret;
+
+        /* make sure there is room for joint */
+        if ((cert->srcIdx + sizeof(joint)) > (word32)maxIdx)
+            return ASN_PARSE_E;
+
+        XMEMCPY(joint, &cert->source[cert->srcIdx], sizeof(joint));
+
+        /* v1 name types */
+        if (joint[0] == 0x55 && joint[1] == 0x04) {
+            cert->srcIdx += 3;
+            id = joint[2];
+            if (GetHeader(cert->source, &b, &cert->srcIdx, &strLen,
+                          maxIdx, 1) < 0) {
+                return ASN_PARSE_E;
+            }
+
+            if (id == ASN_COMMON_NAME) {
+                if (nameType == SUBJECT) {
+                    cert->subjectCN = (char *)&cert->source[cert->srcIdx];
+                    cert->subjectCNLen = strLen;
+                    cert->subjectCNEnc = b;
+                }
+
+                copy = WOLFSSL_COMMON_NAME;
+                copyLen = sizeof(WOLFSSL_COMMON_NAME) - 1;
+                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                    dName->cnIdx = cert->srcIdx;
+                    dName->cnLen = strLen;
+                #endif /* OPENSSL_EXTRA */
+            }
+            else if (id == ASN_SUR_NAME) {
+                copy = WOLFSSL_SUR_NAME;
+                copyLen = sizeof(WOLFSSL_SUR_NAME) - 1;
+                #ifdef WOLFSSL_CERT_GEN
+                    if (nameType == SUBJECT) {
+                        cert->subjectSN = (char*)&cert->source[cert->srcIdx];
+                        cert->subjectSNLen = strLen;
+                        cert->subjectSNEnc = b;
+                    }
+                #endif /* WOLFSSL_CERT_GEN */
+                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                    dName->snIdx = cert->srcIdx;
+                    dName->snLen = strLen;
+                #endif /* OPENSSL_EXTRA */
+            }
+            else if (id == ASN_COUNTRY_NAME) {
+                copy = WOLFSSL_COUNTRY_NAME;
+                copyLen = sizeof(WOLFSSL_COUNTRY_NAME) - 1;
+                #ifdef WOLFSSL_CERT_GEN
+                    if (nameType == SUBJECT) {
+                        cert->subjectC = (char*)&cert->source[cert->srcIdx];
+                        cert->subjectCLen = strLen;
+                        cert->subjectCEnc = b;
+                    }
+                #endif /* WOLFSSL_CERT_GEN */
+                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                    dName->cIdx = cert->srcIdx;
+                    dName->cLen = strLen;
+                #endif /* OPENSSL_EXTRA */
+            }
+            else if (id == ASN_LOCALITY_NAME) {
+                copy = WOLFSSL_LOCALITY_NAME;
+                copyLen = sizeof(WOLFSSL_LOCALITY_NAME) - 1;
+                #ifdef WOLFSSL_CERT_GEN
+                    if (nameType == SUBJECT) {
+                        cert->subjectL = (char*)&cert->source[cert->srcIdx];
+                        cert->subjectLLen = strLen;
+                        cert->subjectLEnc = b;
+                    }
+                #endif /* WOLFSSL_CERT_GEN */
+                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                    dName->lIdx = cert->srcIdx;
+                    dName->lLen = strLen;
+                #endif /* OPENSSL_EXTRA */
+            }
+            else if (id == ASN_STATE_NAME) {
+                copy = WOLFSSL_STATE_NAME;
+                copyLen = sizeof(WOLFSSL_STATE_NAME) - 1;
+                #ifdef WOLFSSL_CERT_GEN
+                    if (nameType == SUBJECT) {
+                        cert->subjectST = (char*)&cert->source[cert->srcIdx];
+                        cert->subjectSTLen = strLen;
+                        cert->subjectSTEnc = b;
+                    }
+                #endif /* WOLFSSL_CERT_GEN */
+                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                    dName->stIdx = cert->srcIdx;
+                    dName->stLen = strLen;
+                #endif /* OPENSSL_EXTRA */
+            }
+            else if (id == ASN_ORG_NAME) {
+                copy = WOLFSSL_ORG_NAME;
+                copyLen = sizeof(WOLFSSL_ORG_NAME) - 1;
+                #ifdef WOLFSSL_CERT_GEN
+                    if (nameType == SUBJECT) {
+                        cert->subjectO = (char*)&cert->source[cert->srcIdx];
+                        cert->subjectOLen = strLen;
+                        cert->subjectOEnc = b;
+                    }
+                #endif /* WOLFSSL_CERT_GEN */
+                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                    dName->oIdx = cert->srcIdx;
+                    dName->oLen = strLen;
+                #endif /* OPENSSL_EXTRA */
+            }
+            else if (id == ASN_ORGUNIT_NAME) {
+                copy = WOLFSSL_ORGUNIT_NAME;
+                copyLen = sizeof(WOLFSSL_ORGUNIT_NAME) - 1;
+                #ifdef WOLFSSL_CERT_GEN
+                    if (nameType == SUBJECT) {
+                        cert->subjectOU = (char*)&cert->source[cert->srcIdx];
+                        cert->subjectOULen = strLen;
+                        cert->subjectOUEnc = b;
+                    }
+                #endif /* WOLFSSL_CERT_GEN */
+                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                    dName->ouIdx = cert->srcIdx;
+                    dName->ouLen = strLen;
+                #endif /* OPENSSL_EXTRA */
+            }
+            else if (id == ASN_SERIAL_NUMBER) {
+                copy = WOLFSSL_SERIAL_NUMBER;
+                copyLen = sizeof(WOLFSSL_SERIAL_NUMBER) - 1;
+                #ifdef WOLFSSL_CERT_GEN
+                    if (nameType == SUBJECT) {
+                        cert->subjectSND = (char*)&cert->source[cert->srcIdx];
+                        cert->subjectSNDLen = strLen;
+                        cert->subjectSNDEnc = b;
+                    }
+                #endif /* WOLFSSL_CERT_GEN */
+                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                    dName->snIdx = cert->srcIdx;
+                    dName->snLen = strLen;
+                #endif /* OPENSSL_EXTRA */
+            }
+        #ifdef WOLFSSL_CERT_EXT
+            else if (id == ASN_BUS_CAT) {
+                copy = WOLFSSL_BUS_CAT;
+                copyLen = sizeof(WOLFSSL_BUS_CAT) - 1;
+            #ifdef WOLFSSL_CERT_GEN
+                if (nameType == SUBJECT) {
+                    cert->subjectBC = (char*)&cert->source[cert->srcIdx];
+                    cert->subjectBCLen = strLen;
+                    cert->subjectBCEnc = b;
+                }
+            #endif /* WOLFSSL_CERT_GEN */
+            #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                dName->bcIdx = cert->srcIdx;
+                dName->bcLen = strLen;
+            #endif /* OPENSSL_EXTRA */
+            }
+        #endif /* WOLFSSL_CERT_EXT */
+        }
+    #ifdef WOLFSSL_CERT_EXT
+        else if ((cert->srcIdx + ASN_JOI_PREFIX_SZ + 2 <= (word32)maxIdx) &&
+                 (0 == XMEMCMP(&cert->source[cert->srcIdx], ASN_JOI_PREFIX,
+                               ASN_JOI_PREFIX_SZ)) &&
+                 ((cert->source[cert->srcIdx+ASN_JOI_PREFIX_SZ] == ASN_JOI_C) ||
+                  (cert->source[cert->srcIdx+ASN_JOI_PREFIX_SZ] == ASN_JOI_ST)))
+        {
+            cert->srcIdx += ASN_JOI_PREFIX_SZ;
+            id = cert->source[cert->srcIdx++];
+            b = cert->source[cert->srcIdx++]; /* encoding */
+
+            if (GetLength(cert->source, &cert->srcIdx, &strLen,
+                          maxIdx) < 0)
+                return ASN_PARSE_E;
+
+            /* Check for jurisdiction of incorporation country name */
+            if (id == ASN_JOI_C) {
+                copy = WOLFSSL_JOI_C;
+                copyLen = sizeof(WOLFSSL_JOI_C) - 1;
+                #ifdef WOLFSSL_CERT_GEN
+                    if (nameType == SUBJECT) {
+                        cert->subjectJC = (char*)&cert->source[cert->srcIdx];
+                        cert->subjectJCLen = strLen;
+                        cert->subjectJCEnc = b;
+                    }
+                #endif /* WOLFSSL_CERT_GEN */
+                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                    dName->jcIdx = cert->srcIdx;
+                    dName->jcLen = strLen;
+                #endif /* OPENSSL_EXTRA */
+            }
+
+            /* Check for jurisdiction of incorporation state name */
+            else if (id == ASN_JOI_ST) {
+                copy = WOLFSSL_JOI_ST;
+                copyLen = sizeof(WOLFSSL_JOI_ST) - 1;
+                #ifdef WOLFSSL_CERT_GEN
+                    if (nameType == SUBJECT) {
+                        cert->subjectJS = (char*)&cert->source[cert->srcIdx];
+                        cert->subjectJSLen = strLen;
+                        cert->subjectJSEnc = b;
+                    }
+                #endif /* WOLFSSL_CERT_GEN */
+                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                    dName->jsIdx = cert->srcIdx;
+                    dName->jsLen = strLen;
+                #endif /* OPENSSL_EXTRA */
+            }
+
+            if ((strLen + copyLen) > (int)(ASN_NAME_MAX - idx)) {
+                WOLFSSL_MSG("ASN Name too big, skipping");
+                tooBig = TRUE;
+            }
+        }
+    #endif /* WOLFSSL_CERT_EXT */
+        else {
+            /* skip */
+            byte email = FALSE;
+            byte pilot = FALSE;
+
+            if (joint[0] == 0x2a && joint[1] == 0x86) {  /* email id hdr */
+                id = ASN_EMAIL_NAME;
+                email = TRUE;
+            }
+
+            if (joint[0] == 0x9  && joint[1] == 0x92) { /* uid id hdr */
+                /* last value of OID is the type of pilot attribute */
+                id    = cert->source[cert->srcIdx + oidSz - 1];
+                pilot = TRUE;
+            }
+
+            cert->srcIdx += oidSz + 1;
+
+            if (GetLength(cert->source, &cert->srcIdx, &strLen, maxIdx) < 0)
+                return ASN_PARSE_E;
+
+            if (strLen > (int)(ASN_NAME_MAX - idx)) {
+                WOLFSSL_MSG("ASN name too big, skipping");
+                tooBig = TRUE;
+            }
+
+            if (email) {
+                copyLen = sizeof(WOLFSSL_EMAIL_ADDR) - 1;
+                if ((copyLen + strLen) > (int)(ASN_NAME_MAX - idx)) {
+                    WOLFSSL_MSG("ASN name too big, skipping");
+                    tooBig = TRUE;
+                }
+                else {
+                    copy = WOLFSSL_EMAIL_ADDR;
+                }
+
+                #ifdef WOLFSSL_CERT_GEN
+                    if (nameType == SUBJECT) {
+                        cert->subjectEmail = (char*)&cert->source[cert->srcIdx];
+                        cert->subjectEmailLen = strLen;
+                    }
+                #endif /* WOLFSSL_CERT_GEN */
+                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                    dName->emailIdx = cert->srcIdx;
+                    dName->emailLen = strLen;
+                #endif /* OPENSSL_EXTRA */
+                #ifndef IGNORE_NAME_CONSTRAINTS
+                    {
+                        DNS_entry* emailName;
+
+                        emailName = (DNS_entry*)XMALLOC(sizeof(DNS_entry),
+                                              cert->heap, DYNAMIC_TYPE_ALTNAME);
+                        if (emailName == NULL) {
+                            WOLFSSL_MSG("\tOut of Memory");
+                            return MEMORY_E;
+                        }
+                        emailName->type = 0;
+                        emailName->name = (char*)XMALLOC(strLen + 1,
+                                              cert->heap, DYNAMIC_TYPE_ALTNAME);
+                        if (emailName->name == NULL) {
+                            WOLFSSL_MSG("\tOut of Memory");
+                            XFREE(emailName, cert->heap, DYNAMIC_TYPE_ALTNAME);
+                            return MEMORY_E;
+                        }
+                        emailName->len = strLen;
+                        XMEMCPY(emailName->name, &cert->source[cert->srcIdx],
+                                                                        strLen);
+                        emailName->name[strLen] = '\0';
+
+                        emailName->next = cert->altEmailNames;
+                        cert->altEmailNames = emailName;
+                    }
+                #endif /* IGNORE_NAME_CONSTRAINTS */
+            }
+
+            if (pilot) {
+                switch (id) {
+                    case ASN_USER_ID:
+                        copy = WOLFSSL_USER_ID;
+                        copyLen = sizeof(WOLFSSL_USER_ID) - 1;
+                    #if defined(OPENSSL_EXTRA) || \
+                        defined(OPENSSL_EXTRA_X509_SMALL)
+                        dName->uidIdx = cert->srcIdx;
+                        dName->uidLen = strLen;
+                    #endif /* OPENSSL_EXTRA */
+                        break;
+
+                    case ASN_DOMAIN_COMPONENT:
+                        copy = WOLFSSL_DOMAIN_COMPONENT;
+                        copyLen = sizeof(WOLFSSL_DOMAIN_COMPONENT) - 1;
+                    #if defined(OPENSSL_EXTRA) || \
+                        defined(OPENSSL_EXTRA_X509_SMALL)
+                        dName->dcIdx[dcnum] = cert->srcIdx;
+                        dName->dcLen[dcnum] = strLen;
+                        dName->dcNum = dcnum + 1;
+                        dcnum++;
+                    #endif /* OPENSSL_EXTRA */
+                        break;
+
+                    default:
+                        WOLFSSL_MSG("Unknown pilot attribute type");
+                        return ASN_PARSE_E;
+                }
+            }
+        }
+        if ((copyLen + strLen) > (int)(ASN_NAME_MAX - idx))
+        {
+            WOLFSSL_MSG("ASN Name too big, skipping");
+            tooBig = TRUE;
+        }
+        if ((copy != NULL) && !tooBig) {
+            XMEMCPY(&full[idx], copy, copyLen);
+            idx += copyLen;
+            XMEMCPY(&full[idx], &cert->source[cert->srcIdx], strLen);
+            idx += strLen;
+
+        #ifdef OPENSSL_EXTRA
+            if (count < DOMAIN_COMPONENT_MAX) {
+                /* store order that DN was parsed */
+                dName->loc[count++] = id;
+            }
+        #endif
+        }
+        cert->srcIdx += strLen;
+    }
+    full[idx++] = 0;
+#if defined(OPENSSL_EXTRA)
+    /* store order that DN was parsed */
+    dName->locSz = count;
+#endif
+
+    #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+    {
+        int totalLen = 0;
+        int i = 0;
+
+        if (dName->cnLen != 0)
+            totalLen += dName->cnLen + 4;
+        if (dName->snLen != 0)
+            totalLen += dName->snLen + 4;
+        if (dName->cLen != 0)
+            totalLen += dName->cLen + 3;
+        if (dName->lLen != 0)
+            totalLen += dName->lLen + 3;
+        if (dName->stLen != 0)
+            totalLen += dName->stLen + 4;
+        if (dName->oLen != 0)
+            totalLen += dName->oLen + 3;
+        if (dName->ouLen != 0)
+            totalLen += dName->ouLen + 4;
+        if (dName->emailLen != 0)
+            totalLen += dName->emailLen + 14;
+        if (dName->uidLen != 0)
+            totalLen += dName->uidLen + 5;
+        if (dName->serialLen != 0)
+            totalLen += dName->serialLen + 14;
+        if (dName->dcNum != 0){
+            for (i = 0;i < dName->dcNum;i++)
+                totalLen += dName->dcLen[i] + 4;
+        }
+
+        dName->fullName = (char*)XMALLOC(totalLen + 1, cert->heap,
+                                                             DYNAMIC_TYPE_X509);
+        if (dName->fullName != NULL) {
+            idx = 0;
+
+            if (dName->cnLen != 0) {
+                dName->entryCount++;
+                XMEMCPY(&dName->fullName[idx], WOLFSSL_COMMON_NAME, 4);
+                dName->cnNid = wc_OBJ_sn2nid((const char *)WOLFSSL_COMMON_NAME);
+                idx += 4;
+                XMEMCPY(&dName->fullName[idx],
+                                     &cert->source[dName->cnIdx], dName->cnLen);
+                dName->cnIdx = idx;
+                idx += dName->cnLen;
+            }
+            if (dName->snLen != 0) {
+                dName->entryCount++;
+                XMEMCPY(&dName->fullName[idx], WOLFSSL_SUR_NAME, 4);
+                dName->snNid = wc_OBJ_sn2nid((const char *)WOLFSSL_SUR_NAME);
+                idx += 4;
+                XMEMCPY(&dName->fullName[idx],
+                                     &cert->source[dName->snIdx], dName->snLen);
+                dName->snIdx = idx;
+                idx += dName->snLen;
+            }
+            if (dName->cLen != 0) {
+                dName->entryCount++;
+                XMEMCPY(&dName->fullName[idx], WOLFSSL_COUNTRY_NAME, 3);
+                dName->cNid = wc_OBJ_sn2nid((const char *)WOLFSSL_COUNTRY_NAME);
+                idx += 3;
+                XMEMCPY(&dName->fullName[idx],
+                                       &cert->source[dName->cIdx], dName->cLen);
+                dName->cIdx = idx;
+                idx += dName->cLen;
+            }
+            if (dName->lLen != 0) {
+                dName->entryCount++;
+                XMEMCPY(&dName->fullName[idx], WOLFSSL_LOCALITY_NAME, 3);
+                dName->lNid = wc_OBJ_sn2nid((const char *)WOLFSSL_LOCALITY_NAME);
+                idx += 3;
+                XMEMCPY(&dName->fullName[idx],
+                                       &cert->source[dName->lIdx], dName->lLen);
+                dName->lIdx = idx;
+                idx += dName->lLen;
+            }
+            if (dName->stLen != 0) {
+                dName->entryCount++;
+                XMEMCPY(&dName->fullName[idx], WOLFSSL_STATE_NAME, 4);
+                dName->stNid = wc_OBJ_sn2nid((const char *)WOLFSSL_STATE_NAME);
+                idx += 4;
+                XMEMCPY(&dName->fullName[idx],
+                                     &cert->source[dName->stIdx], dName->stLen);
+                dName->stIdx = idx;
+                idx += dName->stLen;
+            }
+            if (dName->oLen != 0) {
+                dName->entryCount++;
+                XMEMCPY(&dName->fullName[idx], WOLFSSL_ORG_NAME, 3);
+                dName->oNid = wc_OBJ_sn2nid((const char *)WOLFSSL_ORG_NAME);
+                idx += 3;
+                XMEMCPY(&dName->fullName[idx],
+                                       &cert->source[dName->oIdx], dName->oLen);
+                dName->oIdx = idx;
+                idx += dName->oLen;
+            }
+            if (dName->ouLen != 0) {
+                dName->entryCount++;
+                XMEMCPY(&dName->fullName[idx], WOLFSSL_ORGUNIT_NAME, 4);
+                dName->ouNid = wc_OBJ_sn2nid((const char *)WOLFSSL_ORGUNIT_NAME);
+                idx += 4;
+                XMEMCPY(&dName->fullName[idx],
+                                     &cert->source[dName->ouIdx], dName->ouLen);
+                dName->ouIdx = idx;
+                idx += dName->ouLen;
+            }
+            if (dName->emailLen != 0) {
+                dName->entryCount++;
+                XMEMCPY(&dName->fullName[idx], "/emailAddress=", 14);
+                dName->emailNid = wc_OBJ_sn2nid((const char *)"/emailAddress=");
+                idx += 14;
+                XMEMCPY(&dName->fullName[idx],
+                               &cert->source[dName->emailIdx], dName->emailLen);
+                dName->emailIdx = idx;
+                idx += dName->emailLen;
+            }
+            for (i = 0;i < dName->dcNum;i++){
+                if (dName->dcLen[i] != 0) {
+                    dName->entryCount++;
+                    XMEMCPY(&dName->fullName[idx], WOLFSSL_DOMAIN_COMPONENT, 4);
+                    idx += 4;
+                    XMEMCPY(&dName->fullName[idx],
+                                    &cert->source[dName->dcIdx[i]], dName->dcLen[i]);
+                    dName->dcIdx[i] = idx;
+                    idx += dName->dcLen[i];
+                }
+            }
+            if (dName->uidLen != 0) {
+                dName->entryCount++;
+                XMEMCPY(&dName->fullName[idx], "/UID=", 5);
+                dName->uidNid = wc_OBJ_sn2nid((const char *)"/UID=");
+                idx += 5;
+                XMEMCPY(&dName->fullName[idx],
+                                   &cert->source[dName->uidIdx], dName->uidLen);
+                dName->uidIdx = idx;
+                idx += dName->uidLen;
+            }
+            if (dName->serialLen != 0) {
+                dName->entryCount++;
+                XMEMCPY(&dName->fullName[idx], WOLFSSL_SERIAL_NUMBER, 14);
+                dName->serialNid = wc_OBJ_sn2nid((const char *)WOLFSSL_SERIAL_NUMBER);
+                idx += 14;
+                XMEMCPY(&dName->fullName[idx],
+                             &cert->source[dName->serialIdx], dName->serialLen);
+                dName->serialIdx = idx;
+                idx += dName->serialLen;
+            }
+            dName->fullName[idx] = '\0';
+            dName->fullNameLen = totalLen;
+        }
+    }
+    #endif /* OPENSSL_EXTRA */
+
+    return 0;
+}
+
+
+#ifndef NO_ASN_TIME
+
+/* two byte date/time, add to value */
+static WC_INLINE int GetTime(int* value, const byte* date, int* idx)
+{
+    int i = *idx;
+
+    if (date[i] < 0x30 || date[i] > 0x39 || date[i+1] < 0x30 ||
+                                                             date[i+1] > 0x39) {
+        return ASN_PARSE_E;
+    }
+
+    *value += btoi(date[i++]) * 10;
+    *value += btoi(date[i++]);
+
+    *idx = i;
+
+    return 0;
+}
+
+int ExtractDate(const unsigned char* date, unsigned char format,
+                                                  struct tm* certTime, int* idx)
+{
+    XMEMSET(certTime, 0, sizeof(struct tm));
+
+    if (format == ASN_UTC_TIME) {
+        if (btoi(date[*idx]) >= 5)
+            certTime->tm_year = 1900;
+        else
+            certTime->tm_year = 2000;
+    }
+    else  { /* format == GENERALIZED_TIME */
+        if (GetTime(&certTime->tm_year, date, idx) != 0) return 0;
+        certTime->tm_year *= 100;
+    }
+
+    /* adjust tm_year, tm_mon */
+    if (GetTime(&certTime->tm_year, date, idx) != 0) return 0;
+    certTime->tm_year -= 1900;
+    if (GetTime(&certTime->tm_mon , date, idx) != 0) return 0;
+    certTime->tm_mon  -= 1;
+    if (GetTime(&certTime->tm_mday, date, idx) != 0) return 0;
+    if (GetTime(&certTime->tm_hour, date, idx) != 0) return 0;
+    if (GetTime(&certTime->tm_min , date, idx) != 0) return 0;
+    if (GetTime(&certTime->tm_sec , date, idx) != 0) return 0;
+
+    return 1;
+}
+
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \
+    defined(OPENSSL_EXTRA) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+int GetTimeString(byte* date, int format, char* buf, int len)
+{
+    struct tm t;
+    int idx = 0;
+
+    if (!ExtractDate(date, (unsigned char)format, &t, &idx)) {
+        return 0;
+    }
+
+    if (date[idx] != 'Z') {
+        WOLFSSL_MSG("UTCtime, not Zulu") ;
+        return 0;
+    }
+
+    /* place month in buffer */
+    buf[0] = '\0';
+    switch(t.tm_mon) {
+        case 0:  XSTRNCAT(buf, "Jan ", 5); break;
+        case 1:  XSTRNCAT(buf, "Feb ", 5); break;
+        case 2:  XSTRNCAT(buf, "Mar ", 5); break;
+        case 3:  XSTRNCAT(buf, "Apr ", 5); break;
+        case 4:  XSTRNCAT(buf, "May ", 5); break;
+        case 5:  XSTRNCAT(buf, "Jun ", 5); break;
+        case 6:  XSTRNCAT(buf, "Jul ", 5); break;
+        case 7:  XSTRNCAT(buf, "Aug ", 5); break;
+        case 8:  XSTRNCAT(buf, "Sep ", 5); break;
+        case 9:  XSTRNCAT(buf, "Oct ", 5); break;
+        case 10: XSTRNCAT(buf, "Nov ", 5); break;
+        case 11: XSTRNCAT(buf, "Dec ", 5); break;
+        default:
+            return 0;
+
+    }
+    idx = 4; /* use idx now for char buffer */
+
+    XSNPRINTF(buf + idx, len - idx, "%2d %02d:%02d:%02d %d GMT",
+              t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, t.tm_year + 1900);
+
+    return 1;
+}
+#endif /* OPENSSL_ALL || WOLFSSL_MYSQL_COMPATIBLE || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
+
+
+#if !defined(NO_ASN_TIME) && defined(HAVE_PKCS7)
+
+/* Set current time string, either UTC or GeneralizedTime.
+ * (void*) tm should be a pointer to time_t, output is placed in buf.
+ *
+ * Return time string length placed in buf on success, negative on error */
+int GetAsnTimeString(void* currTime, byte* buf, word32 len)
+{
+    struct tm* ts      = NULL;
+    struct tm* tmpTime = NULL;
+#if defined(NEED_TMP_TIME)
+    struct tm tmpTimeStorage;
+    tmpTime = &tmpTimeStorage;
+#else
+    (void)tmpTime;
+#endif
+    byte* data_ptr  = buf;
+    word32 data_len = 0;
+    int year, mon, day, hour, mini, sec;
+
+    WOLFSSL_ENTER("SetAsnTimeString");
+
+    if (buf == NULL || len == 0)
+        return BAD_FUNC_ARG;
+
+    ts = (struct tm *)XGMTIME((time_t*)currTime, tmpTime);
+    if (ts == NULL){
+        WOLFSSL_MSG("failed to get time data.");
+        return ASN_TIME_E;
+    }
+
+    /* Note ASN_UTC_TIME_SIZE and ASN_GENERALIZED_TIME_SIZE include space for
+     * the null terminator. ASN encoded values leave off the terminator. */
+
+    if (ts->tm_year >= 50 && ts->tm_year < 150) {
+        /* UTC Time */
+        char utc_str[ASN_UTC_TIME_SIZE];
+        data_len = ASN_UTC_TIME_SIZE - 1 + 2;
+
+        if (len < data_len)
+            return BUFFER_E;
+
+        if (ts->tm_year >= 50 && ts->tm_year < 100) {
+            year = ts->tm_year;
+        } else if (ts->tm_year >= 100 && ts->tm_year < 150) {
+            year = ts->tm_year - 100;
+        }
+        else {
+            WOLFSSL_MSG("unsupported year range");
+            return BAD_FUNC_ARG;
+        }
+        mon  = ts->tm_mon + 1;
+        day  = ts->tm_mday;
+        hour = ts->tm_hour;
+        mini = ts->tm_min;
+        sec  = ts->tm_sec;
+        XSNPRINTF((char *)utc_str, ASN_UTC_TIME_SIZE,
+                  "%02d%02d%02d%02d%02d%02dZ", year, mon, day, hour, mini, sec);
+        *data_ptr = (byte) ASN_UTC_TIME; data_ptr++;
+        /* -1 below excludes null terminator */
+        *data_ptr = (byte) ASN_UTC_TIME_SIZE - 1; data_ptr++;
+        XMEMCPY(data_ptr,(byte *)utc_str, ASN_UTC_TIME_SIZE - 1);
+
+    } else {
+        /* GeneralizedTime */
+        char gt_str[ASN_GENERALIZED_TIME_SIZE];
+        data_len = ASN_GENERALIZED_TIME_SIZE - 1 + 2;
+
+        if (len < data_len)
+            return BUFFER_E;
+
+        year = ts->tm_year + 1900;
+        mon  = ts->tm_mon + 1;
+        day  = ts->tm_mday;
+        hour = ts->tm_hour;
+        mini = ts->tm_min;
+        sec  = ts->tm_sec;
+        XSNPRINTF((char *)gt_str, ASN_GENERALIZED_TIME_SIZE,
+                  "%4d%02d%02d%02d%02d%02dZ", year, mon, day, hour, mini, sec);
+        *data_ptr = (byte) ASN_GENERALIZED_TIME; data_ptr++;
+        /* -1 below excludes null terminator */
+        *data_ptr = (byte) ASN_GENERALIZED_TIME_SIZE - 1; data_ptr++;
+        XMEMCPY(data_ptr,(byte *)gt_str, ASN_GENERALIZED_TIME_SIZE - 1);
+    }
+
+    return data_len;
+}
+
+#endif /* !NO_ASN_TIME && HAVE_PKCS7 */
+
+
+#if defined(USE_WOLF_VALIDDATE)
+
+/* to the second */
+int DateGreaterThan(const struct tm* a, const struct tm* b)
+{
+    if (a->tm_year > b->tm_year)
+        return 1;
+
+    if (a->tm_year == b->tm_year && a->tm_mon > b->tm_mon)
+        return 1;
+
+    if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon &&
+           a->tm_mday > b->tm_mday)
+        return 1;
+
+    if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon &&
+        a->tm_mday == b->tm_mday && a->tm_hour > b->tm_hour)
+        return 1;
+
+    if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon &&
+        a->tm_mday == b->tm_mday && a->tm_hour == b->tm_hour &&
+        a->tm_min > b->tm_min)
+        return 1;
+
+    if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon &&
+        a->tm_mday == b->tm_mday && a->tm_hour == b->tm_hour &&
+        a->tm_min  == b->tm_min  && a->tm_sec > b->tm_sec)
+        return 1;
+
+    return 0; /* false */
+}
+
+
+static WC_INLINE int DateLessThan(const struct tm* a, const struct tm* b)
+{
+    return DateGreaterThan(b,a);
+}
+
+/* like atoi but only use first byte */
+/* Make sure before and after dates are valid */
+int ValidateDate(const byte* date, byte format, int dateType)
+{
+    time_t ltime;
+    struct tm  certTime;
+    struct tm* localTime;
+    struct tm* tmpTime;
+    int    i = 0;
+    int    timeDiff = 0 ;
+    int    diffHH = 0 ; int diffMM = 0 ;
+    int    diffSign = 0 ;
+
+#if defined(NEED_TMP_TIME)
+    struct tm tmpTimeStorage;
+    tmpTime = &tmpTimeStorage;
+#else
+    tmpTime = NULL;
+#endif
+    (void)tmpTime;
+
+    ltime = XTIME(0);
+
+#ifdef WOLFSSL_BEFORE_DATE_CLOCK_SKEW
+    if (dateType == BEFORE) {
+        WOLFSSL_MSG("Skewing local time for before date check");
+        ltime += WOLFSSL_BEFORE_DATE_CLOCK_SKEW;
+    }
+#endif
+
+#ifdef WOLFSSL_AFTER_DATE_CLOCK_SKEW
+    if (dateType == AFTER) {
+        WOLFSSL_MSG("Skewing local time for after date check");
+        ltime -= WOLFSSL_AFTER_DATE_CLOCK_SKEW;
+    }
+#endif
+
+    if (!ExtractDate(date, format, &certTime, &i)) {
+        WOLFSSL_MSG("Error extracting the date");
+        return 0;
+    }
+
+    if ((date[i] == '+') || (date[i] == '-')) {
+        WOLFSSL_MSG("Using time differential, not Zulu") ;
+        diffSign = date[i++] == '+' ? 1 : -1 ;
+        if (GetTime(&diffHH, date, &i) != 0)
+            return 0;
+        if (GetTime(&diffMM, date, &i) != 0)
+            return 0;
+        timeDiff = diffSign * (diffHH*60 + diffMM) * 60 ;
+    } else if (date[i] != 'Z') {
+        WOLFSSL_MSG("UTCtime, neither Zulu or time differential") ;
+        return 0;
+    }
+
+    ltime -= (time_t)timeDiff ;
+    localTime = XGMTIME(&ltime, tmpTime);
+
+    if (localTime == NULL) {
+        WOLFSSL_MSG("XGMTIME failed");
+        return 0;
+    }
+
+    if (dateType == BEFORE) {
+        if (DateLessThan(localTime, &certTime)) {
+            WOLFSSL_MSG("Date BEFORE check failed");
+            return 0;
+        }
+    }
+    else {  /* dateType == AFTER */
+        if (DateGreaterThan(localTime, &certTime)) {
+            WOLFSSL_MSG("Date AFTER check failed");
+            return 0;
+        }
+    }
+
+    return 1;
+}
+#endif /* USE_WOLF_VALIDDATE */
+
+int wc_GetTime(void* timePtr, word32 timeSize)
+{
+    time_t* ltime = (time_t*)timePtr;
+
+    if (timePtr == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if ((word32)sizeof(time_t) > timeSize) {
+        return BUFFER_E;
+    }
+
+    *ltime = XTIME(0);
+
+    return 0;
+}
+
+#endif /* !NO_ASN_TIME */
+
+
+/* Get date buffer, format and length. Returns 0=success or error */
+static int GetDateInfo(const byte* source, word32* idx, const byte** pDate,
+                        byte* pFormat, int* pLength, word32 maxIdx)
+{
+    int length;
+    byte format;
+
+    if (source == NULL || idx == NULL)
+        return BAD_FUNC_ARG;
+
+    /* get ASN format header */
+    if (*idx+1 > maxIdx)
+        return BUFFER_E;
+    format = source[*idx];
+    *idx += 1;
+    if (format != ASN_UTC_TIME && format != ASN_GENERALIZED_TIME)
+        return ASN_TIME_E;
+
+    /* get length */
+    if (GetLength(source, idx, &length, maxIdx) < 0)
+        return ASN_PARSE_E;
+    if (length > MAX_DATE_SIZE || length < MIN_DATE_SIZE)
+        return ASN_DATE_SZ_E;
+
+    /* return format, date and length */
+    if (pFormat)
+        *pFormat = format;
+    if (pDate)
+        *pDate = &source[*idx];
+    if (pLength)
+        *pLength = length;
+
+    *idx += length;
+
+    return 0;
+}
+
+static int GetDate(DecodedCert* cert, int dateType, int verify, int maxIdx)
+{
+    int    ret, length;
+    const byte *datePtr = NULL;
+    byte   date[MAX_DATE_SIZE];
+    byte   format;
+    word32 startIdx = 0;
+
+    if (dateType == BEFORE)
+        cert->beforeDate = &cert->source[cert->srcIdx];
+    else
+        cert->afterDate = &cert->source[cert->srcIdx];
+    startIdx = cert->srcIdx;
+
+    ret = GetDateInfo(cert->source, &cert->srcIdx, &datePtr, &format,
+                      &length, maxIdx);
+    if (ret < 0)
+        return ret;
+
+    XMEMSET(date, 0, MAX_DATE_SIZE);
+    XMEMCPY(date, datePtr, length);
+
+    if (dateType == BEFORE)
+        cert->beforeDateLen = cert->srcIdx - startIdx;
+    else
+        cert->afterDateLen  = cert->srcIdx - startIdx;
+
+#ifndef NO_ASN_TIME
+    if (verify != NO_VERIFY && verify != VERIFY_SKIP_DATE &&
+            !XVALIDATE_DATE(date, format, dateType)) {
+        if (dateType == BEFORE)
+            return ASN_BEFORE_DATE_E;
+        else
+            return ASN_AFTER_DATE_E;
+    }
+#else
+    (void)verify;
+#endif
+
+    return 0;
+}
+
+static int GetValidity(DecodedCert* cert, int verify, int maxIdx)
+{
+    int length;
+    int badDate = 0;
+
+    if (GetSequence(cert->source, &cert->srcIdx, &length, maxIdx) < 0)
+        return ASN_PARSE_E;
+
+    maxIdx = cert->srcIdx + length;
+
+    if (GetDate(cert, BEFORE, verify, maxIdx) < 0)
+        badDate = ASN_BEFORE_DATE_E; /* continue parsing */
+
+    if (GetDate(cert, AFTER, verify, maxIdx) < 0)
+        return ASN_AFTER_DATE_E;
+
+    if (badDate != 0)
+        return badDate;
+
+    return 0;
+}
+
+
+int wc_GetDateInfo(const byte* certDate, int certDateSz, const byte** date,
+    byte* format, int* length)
+{
+    int ret;
+    word32 idx = 0;
+
+    ret = GetDateInfo(certDate, &idx, date, format, length, certDateSz);
+    if (ret < 0)
+        return ret;
+
+    return 0;
+}
+
+#ifndef NO_ASN_TIME
+int wc_GetDateAsCalendarTime(const byte* date, int length, byte format,
+    struct tm* timearg)
+{
+    int idx = 0;
+    (void)length;
+    if (!ExtractDate(date, format, timearg, &idx))
+        return ASN_TIME_E;
+    return 0;
+}
+
+#if defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_ALT_NAMES)
+int wc_GetCertDates(Cert* cert, struct tm* before, struct tm* after)
+{
+    int ret = 0;
+    const byte* date;
+    byte format;
+    int length;
+
+    if (cert == NULL)
+        return BAD_FUNC_ARG;
+
+    if (before && cert->beforeDateSz > 0) {
+        ret = wc_GetDateInfo(cert->beforeDate, cert->beforeDateSz, &date,
+                             &format, &length);
+        if (ret == 0)
+            ret = wc_GetDateAsCalendarTime(date, length, format, before);
+    }
+    if (after && cert->afterDateSz > 0) {
+        ret = wc_GetDateInfo(cert->afterDate, cert->afterDateSz, &date,
+                             &format, &length);
+        if (ret == 0)
+            ret = wc_GetDateAsCalendarTime(date, length, format, after);
+    }
+
+    return ret;
+}
+#endif /* WOLFSSL_CERT_GEN && WOLFSSL_ALT_NAMES */
+#endif /* !NO_ASN_TIME */
+
+/* parses certificate up to point of X.509 public key
+ *
+ * if cert date is invalid then badDate gets set to error value, otherwise is 0
+ *
+ * returns a negative value on fail case
+ */
+int wc_GetPubX509(DecodedCert* cert, int verify, int* badDate)
+{
+    int ret;
+
+    if (cert == NULL || badDate == NULL)
+        return BAD_FUNC_ARG;
+
+    *badDate = 0;
+    if ( (ret = GetCertHeader(cert)) < 0)
+        return ret;
+
+    WOLFSSL_MSG("Got Cert Header");
+
+    /* Using the sigIndex as the upper bound because that's where the
+     * actual certificate data ends. */
+    if ( (ret = GetAlgoId(cert->source, &cert->srcIdx, &cert->signatureOID,
+                          oidSigType, cert->sigIndex)) < 0)
+        return ret;
+
+    WOLFSSL_MSG("Got Algo ID");
+
+    if ( (ret = GetName(cert, ISSUER, cert->sigIndex)) < 0)
+        return ret;
+
+    if ( (ret = GetValidity(cert, verify, cert->sigIndex)) < 0)
+        *badDate = ret;
+
+    if ( (ret = GetName(cert, SUBJECT, cert->sigIndex)) < 0)
+        return ret;
+
+    WOLFSSL_MSG("Got Subject Name");
+    return ret;
+}
+
+int DecodeToKey(DecodedCert* cert, int verify)
+{
+    int badDate = 0;
+    int ret;
+
+    if ( (ret = wc_GetPubX509(cert, verify, &badDate)) < 0)
+        return ret;
+
+    /* Determine if self signed */
+    cert->selfSigned = XMEMCMP(cert->issuerHash,
+                               cert->subjectHash,
+                               KEYID_SIZE) == 0 ? 1 : 0;
+
+    if ( (ret = GetKey(cert)) < 0)
+        return ret;
+
+    WOLFSSL_MSG("Got Key");
+
+    if (badDate != 0)
+        return badDate;
+
+    return ret;
+}
+
+static int GetSignature(DecodedCert* cert)
+{
+    int length;
+    int ret;
+    ret = CheckBitString(cert->source, &cert->srcIdx, &length, cert->maxIdx, 1,
+                         NULL);
+    if (ret != 0)
+        return ret;
+
+    cert->sigLength = length;
+    cert->signature = &cert->source[cert->srcIdx];
+    cert->srcIdx += cert->sigLength;
+
+    return 0;
+}
+
+static word32 SetOctetString8Bit(word32 len, byte* output)
+{
+    output[0] = ASN_OCTET_STRING;
+    output[1] = (byte)len;
+    return 2;
+}
+
+static word32 SetDigest(const byte* digest, word32 digSz, byte* output)
+{
+    word32 idx = SetOctetString8Bit(digSz, output);
+    XMEMCPY(&output[idx], digest, digSz);
+
+    return idx + digSz;
+}
+
+
+static word32 BytePrecision(word32 value)
+{
+    word32 i;
+    for (i = sizeof(value); i; --i)
+        if (value >> ((i - 1) * WOLFSSL_BIT_SIZE))
+            break;
+
+    return i;
+}
+
+
+word32 SetLength(word32 length, byte* output)
+{
+    word32 i = 0, j;
+
+    if (length < ASN_LONG_LENGTH) {
+        if (output)
+            output[i] = (byte)length;
+        i++;
+    }
+    else {
+        if (output)
+            output[i] = (byte)(BytePrecision(length) | ASN_LONG_LENGTH);
+        i++;
+
+        for (j = BytePrecision(length); j; --j) {
+            if (output)
+                output[i] = (byte)(length >> ((j - 1) * WOLFSSL_BIT_SIZE));
+            i++;
+        }
+    }
+
+    return i;
+}
+
+word32 SetSequence(word32 len, byte* output)
+{
+    if (output)
+        output[0] = ASN_SEQUENCE | ASN_CONSTRUCTED;
+    return SetLength(len, output ? output + 1 : NULL) + 1;
+}
+
+word32 SetOctetString(word32 len, byte* output)
+{
+    output[0] = ASN_OCTET_STRING;
+    return SetLength(len, output + 1) + 1;
+}
+
+/* Write a set header to output */
+word32 SetSet(word32 len, byte* output)
+{
+    output[0] = ASN_SET | ASN_CONSTRUCTED;
+    return SetLength(len, output + 1) + 1;
+}
+
+word32 SetImplicit(byte tag, byte number, word32 len, byte* output)
+{
+
+    output[0] = ((tag == ASN_SEQUENCE || tag == ASN_SET) ? ASN_CONSTRUCTED : 0)
+                    | ASN_CONTEXT_SPECIFIC | number;
+    return SetLength(len, output + 1) + 1;
+}
+
+word32 SetExplicit(byte number, word32 len, byte* output)
+{
+    output[0] = ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | number;
+    return SetLength(len, output + 1) + 1;
+}
+
+
+#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)
+
+static int SetCurve(ecc_key* key, byte* output)
+{
+#ifdef HAVE_OID_ENCODING
+    int ret;
+#endif
+    int idx = 0;
+    word32 oidSz = 0;
+
+    /* validate key */
+    if (key == NULL || key->dp == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef HAVE_OID_ENCODING
+    ret = EncodeObjectId(key->dp->oid, key->dp->oidSz, NULL, &oidSz);
+    if (ret != 0) {
+        return ret;
+    }
+#else
+    oidSz = key->dp->oidSz;
+#endif
+
+    idx += SetObjectId(oidSz, output);
+
+#ifdef HAVE_OID_ENCODING
+    ret = EncodeObjectId(key->dp->oid, key->dp->oidSz, output+idx, &oidSz);
+    if (ret != 0) {
+        return ret;
+    }
+#else
+    XMEMCPY(output+idx, key->dp->oid, oidSz);
+#endif
+    idx += oidSz;
+
+    return idx;
+}
+
+#endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT */
+
+
+#ifdef HAVE_ECC
+static WC_INLINE int IsSigAlgoECDSA(int algoOID)
+{
+    /* ECDSA sigAlgo must not have ASN1 NULL parameters */
+    if (algoOID == CTC_SHAwECDSA || algoOID == CTC_SHA256wECDSA ||
+        algoOID == CTC_SHA384wECDSA || algoOID == CTC_SHA512wECDSA) {
+        return 1;
+    }
+
+    return 0;
+}
+#endif
+
+word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz)
+{
+    word32 tagSz, idSz, seqSz, algoSz = 0;
+    const  byte* algoName = 0;
+    byte   ID_Length[1 + MAX_LENGTH_SZ];
+    byte   seqArray[MAX_SEQ_SZ + 1];  /* add object_id to end */
+    int    length = 0;
+
+    tagSz = (type == oidHashType ||
+             (type == oidSigType
+        #ifdef HAVE_ECC
+              && !IsSigAlgoECDSA(algoOID)
+        #endif
+        #ifdef HAVE_ED25519
+              && algoOID != ED25519k
+        #endif
+        #ifdef HAVE_ED448
+              && algoOID != ED448k
+        #endif
+              ) ||
+             (type == oidKeyType && algoOID == RSAk)) ? 2 : 0;
+
+    algoName = OidFromId(algoOID, type, &algoSz);
+
+    if (algoName == NULL) {
+        WOLFSSL_MSG("Unknown Algorithm");
+        return 0;
+    }
+
+    idSz  = SetObjectId(algoSz, ID_Length);
+    seqSz = SetSequence(idSz + algoSz + tagSz + curveSz, seqArray);
+
+    /* Copy only algo to output for DSA keys */
+    if (algoOID == DSAk && output) {
+        XMEMCPY(output, ID_Length, idSz);
+        XMEMCPY(output + idSz, algoName, algoSz);
+        if (tagSz == 2)
+            SetASNNull(&output[seqSz + idSz + algoSz]);
+    }
+    else if (output) {
+        XMEMCPY(output, seqArray, seqSz);
+        XMEMCPY(output + seqSz, ID_Length, idSz);
+        XMEMCPY(output + seqSz + idSz, algoName, algoSz);
+        if (tagSz == 2)
+            SetASNNull(&output[seqSz + idSz + algoSz]);
+    }
+
+    if (algoOID == DSAk)
+        length = idSz + algoSz + tagSz;
+    else
+        length = seqSz + idSz + algoSz + tagSz;
+
+    return length;
+}
+
+
+word32 wc_EncodeSignature(byte* out, const byte* digest, word32 digSz,
+                          int hashOID)
+{
+    byte digArray[MAX_ENCODED_DIG_SZ];
+    byte algoArray[MAX_ALGO_SZ];
+    byte seqArray[MAX_SEQ_SZ];
+    word32 encDigSz, algoSz, seqSz;
+
+    encDigSz = SetDigest(digest, digSz, digArray);
+    algoSz   = SetAlgoID(hashOID, algoArray, oidHashType, 0);
+    seqSz    = SetSequence(encDigSz + algoSz, seqArray);
+
+    XMEMCPY(out, seqArray, seqSz);
+    XMEMCPY(out + seqSz, algoArray, algoSz);
+    XMEMCPY(out + seqSz + algoSz, digArray, encDigSz);
+
+    return encDigSz + algoSz + seqSz;
+}
+
+
+#ifndef NO_CERTS
+
+int wc_GetCTC_HashOID(int type)
+{
+    int ret;
+    enum wc_HashType hType;
+
+    hType = wc_HashTypeConvert(type);
+    ret = wc_HashGetOID(hType);
+    if (ret < 0)
+        ret = 0; /* backwards compatibility */
+
+    return ret;
+}
+
+void InitSignatureCtx(SignatureCtx* sigCtx, void* heap, int devId)
+{
+    if (sigCtx) {
+        XMEMSET(sigCtx, 0, sizeof(SignatureCtx));
+        sigCtx->devId = devId;
+        sigCtx->heap = heap;
+    }
+}
+
+void FreeSignatureCtx(SignatureCtx* sigCtx)
+{
+    if (sigCtx == NULL)
+        return;
+
+    if (sigCtx->digest) {
+        XFREE(sigCtx->digest, sigCtx->heap, DYNAMIC_TYPE_DIGEST);
+        sigCtx->digest = NULL;
+    }
+#ifndef NO_RSA
+    if (sigCtx->plain) {
+        XFREE(sigCtx->plain, sigCtx->heap, DYNAMIC_TYPE_SIGNATURE);
+        sigCtx->plain = NULL;
+    }
+#endif
+#ifndef NO_ASN_CRYPT
+    if (sigCtx->key.ptr) {
+        switch (sigCtx->keyOID) {
+        #ifndef NO_RSA
+            case RSAk:
+                wc_FreeRsaKey(sigCtx->key.rsa);
+                XFREE(sigCtx->key.ptr, sigCtx->heap, DYNAMIC_TYPE_RSA);
+                break;
+        #endif /* !NO_RSA */
+        #ifdef HAVE_ECC
+            case ECDSAk:
+                wc_ecc_free(sigCtx->key.ecc);
+                XFREE(sigCtx->key.ecc, sigCtx->heap, DYNAMIC_TYPE_ECC);
+                break;
+        #endif /* HAVE_ECC */
+        #ifdef HAVE_ED25519
+            case ED25519k:
+                wc_ed25519_free(sigCtx->key.ed25519);
+                XFREE(sigCtx->key.ed25519, sigCtx->heap, DYNAMIC_TYPE_ED25519);
+                break;
+        #endif /* HAVE_ED25519 */
+        #ifdef HAVE_ED448
+            case ED448k:
+                wc_ed448_free(sigCtx->key.ed448);
+                XFREE(sigCtx->key.ed448, sigCtx->heap, DYNAMIC_TYPE_ED448);
+                break;
+        #endif /* HAVE_ED448 */
+            default:
+                break;
+        } /* switch (keyOID) */
+        sigCtx->key.ptr = NULL;
+    }
+#endif
+
+    /* reset state, we are done */
+    sigCtx->state = SIG_STATE_BEGIN;
+}
+
+#ifndef NO_ASN_CRYPT
+static int HashForSignature(const byte* buf, word32 bufSz, word32 sigOID,
+                            byte* digest, int* typeH, int* digestSz, int verify)
+{
+    int ret = 0;
+
+    (void)verify;
+
+    switch (sigOID) {
+    #if defined(WOLFSSL_MD2)
+        case CTC_MD2wRSA:
+            if (!verify) {
+                ret = HASH_TYPE_E;
+                WOLFSSL_MSG("MD2 not supported for signing");
+            }
+            else if ((ret = wc_Md2Hash(buf, bufSz, digest)) == 0) {
+                *typeH    = MD2h;
+                *digestSz = MD2_DIGEST_SIZE;
+            }
+        break;
+    #endif
+    #ifndef NO_MD5
+        case CTC_MD5wRSA:
+            if ((ret = wc_Md5Hash(buf, bufSz, digest)) == 0) {
+                *typeH    = MD5h;
+                *digestSz = WC_MD5_DIGEST_SIZE;
+            }
+            break;
+    #endif
+    #ifndef NO_SHA
+        case CTC_SHAwRSA:
+        case CTC_SHAwDSA:
+        case CTC_SHAwECDSA:
+            if ((ret = wc_ShaHash(buf, bufSz, digest)) == 0) {
+                *typeH    = SHAh;
+                *digestSz = WC_SHA_DIGEST_SIZE;
+            }
+            break;
+    #endif
+    #ifdef WOLFSSL_SHA224
+        case CTC_SHA224wRSA:
+        case CTC_SHA224wECDSA:
+            if ((ret = wc_Sha224Hash(buf, bufSz, digest)) == 0) {
+                *typeH    = SHA224h;
+                *digestSz = WC_SHA224_DIGEST_SIZE;
+            }
+            break;
+    #endif
+    #ifndef NO_SHA256
+        case CTC_SHA256wRSA:
+        case CTC_SHA256wECDSA:
+            if ((ret = wc_Sha256Hash(buf, bufSz, digest)) == 0) {
+                *typeH    = SHA256h;
+                *digestSz = WC_SHA256_DIGEST_SIZE;
+            }
+            break;
+    #endif
+    #ifdef WOLFSSL_SHA384
+        case CTC_SHA384wRSA:
+        case CTC_SHA384wECDSA:
+            if ((ret = wc_Sha384Hash(buf, bufSz, digest)) == 0) {
+                *typeH    = SHA384h;
+                *digestSz = WC_SHA384_DIGEST_SIZE;
+            }
+            break;
+    #endif
+    #ifdef WOLFSSL_SHA512
+        case CTC_SHA512wRSA:
+        case CTC_SHA512wECDSA:
+            if ((ret = wc_Sha512Hash(buf, bufSz, digest)) == 0) {
+                *typeH    = SHA512h;
+                *digestSz = WC_SHA512_DIGEST_SIZE;
+            }
+            break;
+    #endif
+    #ifdef HAVE_ED25519
+        case CTC_ED25519:
+            /* Hashes done in signing operation.
+             * Two dependent hashes with prefixes performed.
+             */
+            break;
+    #endif
+    #ifdef HAVE_ED448
+        case CTC_ED448:
+            /* Hashes done in signing operation.
+             * Two dependent hashes with prefixes performed.
+             */
+            break;
+    #endif
+        default:
+            ret = HASH_TYPE_E;
+            WOLFSSL_MSG("Hash for Signature has unsupported type");
+    }
+
+    return ret;
+}
+#endif /* !NO_ASN_CRYPT */
+
+/* Return codes: 0=Success, Negative (see error-crypt.h), ASN_SIG_CONFIRM_E */
+static int ConfirmSignature(SignatureCtx* sigCtx,
+    const byte* buf, word32 bufSz,
+    const byte* key, word32 keySz, word32 keyOID,
+    const byte* sig, word32 sigSz, word32 sigOID, byte* rsaKeyIdx)
+{
+    int ret = 0;
+#ifndef WOLFSSL_RENESAS_TSIP_TLS
+    (void)rsaKeyIdx;
+#endif
+    if (sigCtx == NULL || buf == NULL || bufSz == 0 || key == NULL ||
+        keySz == 0 || sig == NULL || sigSz == 0) {
+        return BAD_FUNC_ARG;
+    }
+
+    (void)key;
+    (void)keySz;
+    (void)sig;
+    (void)sigSz;
+
+    WOLFSSL_ENTER("ConfirmSignature");
+
+#ifndef NO_ASN_CRYPT
+    switch (sigCtx->state) {
+        case SIG_STATE_BEGIN:
+        {
+            sigCtx->keyOID = keyOID; /* must set early for cleanup */
+
+            sigCtx->digest = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, sigCtx->heap,
+                                                    DYNAMIC_TYPE_DIGEST);
+            if (sigCtx->digest == NULL) {
+                ERROR_OUT(MEMORY_E, exit_cs);
+            }
+
+            sigCtx->state = SIG_STATE_HASH;
+        } /* SIG_STATE_BEGIN */
+        FALL_THROUGH;
+
+        case SIG_STATE_HASH:
+        {
+            ret = HashForSignature(buf, bufSz, sigOID, sigCtx->digest,
+                                   &sigCtx->typeH, &sigCtx->digestSz, 1);
+            if (ret != 0) {
+                goto exit_cs;
+            }
+
+            sigCtx->state = SIG_STATE_KEY;
+        } /* SIG_STATE_HASH */
+        FALL_THROUGH;
+
+        case SIG_STATE_KEY:
+        {
+            switch (keyOID) {
+            #ifndef NO_RSA
+                case RSAk:
+                {
+                    word32 idx = 0;
+
+                    sigCtx->key.rsa = (RsaKey*)XMALLOC(sizeof(RsaKey),
+                                                sigCtx->heap, DYNAMIC_TYPE_RSA);
+                    sigCtx->plain = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ,
+                                         sigCtx->heap, DYNAMIC_TYPE_SIGNATURE);
+                    if (sigCtx->key.rsa == NULL || sigCtx->plain == NULL) {
+                        ERROR_OUT(MEMORY_E, exit_cs);
+                    }
+                    if ((ret = wc_InitRsaKey_ex(sigCtx->key.rsa, sigCtx->heap,
+                                                        sigCtx->devId)) != 0) {
+                        goto exit_cs;
+                    }
+                    if (sigSz > MAX_ENCODED_SIG_SZ) {
+                        WOLFSSL_MSG("Verify Signature is too big");
+                        ERROR_OUT(BUFFER_E, exit_cs);
+                    }
+                    if ((ret = wc_RsaPublicKeyDecode(key, &idx, sigCtx->key.rsa,
+                                                                 keySz)) != 0) {
+                        WOLFSSL_MSG("ASN Key decode error RSA");
+                        goto exit_cs;
+                    }
+                    XMEMCPY(sigCtx->plain, sig, sigSz);
+                    sigCtx->out = NULL;
+
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    sigCtx->asyncDev = &sigCtx->key.rsa->asyncDev;
+                #endif
+                    break;
+                }
+            #endif /* !NO_RSA */
+            #ifdef HAVE_ECC
+                case ECDSAk:
+                {
+                    word32 idx = 0;
+
+                    sigCtx->verify = 0;
+                    sigCtx->key.ecc = (ecc_key*)XMALLOC(sizeof(ecc_key),
+                                                sigCtx->heap, DYNAMIC_TYPE_ECC);
+                    if (sigCtx->key.ecc == NULL) {
+                        ERROR_OUT(MEMORY_E, exit_cs);
+                    }
+                    if ((ret = wc_ecc_init_ex(sigCtx->key.ecc, sigCtx->heap,
+                                                          sigCtx->devId)) < 0) {
+                        goto exit_cs;
+                    }
+                    ret = wc_EccPublicKeyDecode(key, &idx, sigCtx->key.ecc,
+                                                                         keySz);
+                    if (ret < 0) {
+                        WOLFSSL_MSG("ASN Key import error ECC");
+                        goto exit_cs;
+                    }
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    sigCtx->asyncDev = &sigCtx->key.ecc->asyncDev;
+                #endif
+                    break;
+                }
+            #endif /* HAVE_ECC */
+            #ifdef HAVE_ED25519
+                case ED25519k:
+                {
+                    sigCtx->verify = 0;
+                    sigCtx->key.ed25519 = (ed25519_key*)XMALLOC(
+                                              sizeof(ed25519_key), sigCtx->heap,
+                                              DYNAMIC_TYPE_ED25519);
+                    if (sigCtx->key.ed25519 == NULL) {
+                        ERROR_OUT(MEMORY_E, exit_cs);
+                    }
+                    if ((ret = wc_ed25519_init(sigCtx->key.ed25519)) < 0) {
+                        goto exit_cs;
+                    }
+                    if ((ret = wc_ed25519_import_public(key, keySz,
+                                                    sigCtx->key.ed25519)) < 0) {
+                        WOLFSSL_MSG("ASN Key import error ED25519");
+                        goto exit_cs;
+                    }
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    sigCtx->asyncDev = &sigCtx->key.ed25519->asyncDev;
+                #endif
+                    break;
+                }
+            #endif
+            #ifdef HAVE_ED448
+                case ED448k:
+                {
+                    sigCtx->verify = 0;
+                    sigCtx->key.ed448 = (ed448_key*)XMALLOC(
+                                                sizeof(ed448_key), sigCtx->heap,
+                                                DYNAMIC_TYPE_ED448);
+                    if (sigCtx->key.ed448 == NULL) {
+                        ERROR_OUT(MEMORY_E, exit_cs);
+                    }
+                    if ((ret = wc_ed448_init(sigCtx->key.ed448)) < 0) {
+                        goto exit_cs;
+                    }
+                    if ((ret = wc_ed448_import_public(key, keySz,
+                                                      sigCtx->key.ed448)) < 0) {
+                        WOLFSSL_MSG("ASN Key import error ED448");
+                        goto exit_cs;
+                    }
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    sigCtx->asyncDev = &sigCtx->key.ed448->asyncDev;
+                #endif
+                    break;
+                }
+            #endif
+                default:
+                    WOLFSSL_MSG("Verify Key type unknown");
+                    ret = ASN_UNKNOWN_OID_E;
+                    break;
+            } /* switch (keyOID) */
+
+            if (ret != 0) {
+                goto exit_cs;
+            }
+
+            sigCtx->state = SIG_STATE_DO;
+
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (sigCtx->devId != INVALID_DEVID && sigCtx->asyncDev && sigCtx->asyncCtx) {
+                /* make sure event is initialized */
+                WOLF_EVENT* event = &sigCtx->asyncDev->event;
+                ret = wolfAsync_EventInit(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL,
+                    sigCtx->asyncCtx, WC_ASYNC_FLAG_CALL_AGAIN);
+            }
+        #endif
+        } /* SIG_STATE_KEY */
+        FALL_THROUGH;
+
+        case SIG_STATE_DO:
+        {
+            switch (keyOID) {
+            #ifndef NO_RSA
+                case RSAk:
+                {
+                #ifdef HAVE_PK_CALLBACKS
+                    if (sigCtx->pkCbRsa) {
+                        ret = sigCtx->pkCbRsa(
+                                sigCtx->plain, sigSz, &sigCtx->out,
+                                key, keySz,
+                                sigCtx->pkCtxRsa);
+                    }
+                    else
+                #endif /* HAVE_PK_CALLBACKS */
+                    {
+                     #ifdef WOLFSSL_RENESAS_TSIP_TLS
+                        if (rsaKeyIdx != NULL)
+                        {
+                            ret = tsip_tls_CertVerify(buf, bufSz, sigCtx->plain,
+                                sigSz,
+                                sigCtx->pubkey_n_start - sigCtx->certBegin,
+                                sigCtx->pubkey_n_len - 1,
+                                sigCtx->pubkey_e_start - sigCtx->certBegin,
+                                sigCtx->pubkey_e_len - 1,
+                                rsaKeyIdx);
+
+                            if (ret == 0){
+                                sigCtx->verifyByTSIP = 1;
+                                ret = 0;
+                            } else {
+                                WOLFSSL_MSG("RSA Verify by tsip didn't match");
+                                ret = ASN_SIG_CONFIRM_E;
+                            }
+                        } else
+                    #endif
+                        ret = wc_RsaSSL_VerifyInline(sigCtx->plain, sigSz,
+                                                 &sigCtx->out, sigCtx->key.rsa);
+                    }
+                    break;
+                }
+            #endif /* !NO_RSA */
+            #if defined(HAVE_ECC)
+                case ECDSAk:
+                {
+                #ifdef HAVE_PK_CALLBACKS
+                    if (sigCtx->pkCbEcc) {
+                        ret = sigCtx->pkCbEcc(
+                                sig, sigSz,
+                                sigCtx->digest, sigCtx->digestSz,
+                                key, keySz, &sigCtx->verify,
+                                sigCtx->pkCtxEcc);
+                    }
+                    else
+                #endif /* HAVE_PK_CALLBACKS */
+                    {
+                        ret = wc_ecc_verify_hash(sig, sigSz, sigCtx->digest,
+                                            sigCtx->digestSz, &sigCtx->verify,
+                                            sigCtx->key.ecc);
+                    }
+                    break;
+                }
+            #endif /* HAVE_ECC */
+            #ifdef HAVE_ED25519
+                case ED25519k:
+                {
+                    ret = wc_ed25519_verify_msg(sig, sigSz, buf, bufSz,
+                                          &sigCtx->verify, sigCtx->key.ed25519);
+                    break;
+                }
+            #endif
+            #ifdef HAVE_ED448
+                case ED448k:
+                {
+                    ret = wc_ed448_verify_msg(sig, sigSz, buf, bufSz,
+                                             &sigCtx->verify, sigCtx->key.ed448,
+                                             NULL, 0);
+                    break;
+                }
+            #endif
+                default:
+                    break;
+            }  /* switch (keyOID) */
+
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (ret == WC_PENDING_E) {
+                goto exit_cs;
+            }
+        #endif
+
+            if (ret < 0) {
+                /* treat all RSA errors as ASN_SIG_CONFIRM_E */
+                ret = ASN_SIG_CONFIRM_E;
+                goto exit_cs;
+            }
+
+            sigCtx->state = SIG_STATE_CHECK;
+        } /* SIG_STATE_DO */
+        FALL_THROUGH;
+
+        case SIG_STATE_CHECK:
+        {
+            switch (keyOID) {
+            #ifndef NO_RSA
+                case RSAk:
+                {
+                    int encodedSigSz, verifySz;
+                #ifdef WOLFSSL_RENESAS_TSIP
+                    if (sigCtx->verifyByTSIP == 1) break;
+                #endif
+                #ifdef WOLFSSL_SMALL_STACK
+                    byte* encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ,
+                                        sigCtx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+                    if (encodedSig == NULL) {
+                        ERROR_OUT(MEMORY_E, exit_cs);
+                    }
+                #else
+                    byte encodedSig[MAX_ENCODED_SIG_SZ];
+                #endif
+
+                    verifySz = ret;
+
+                    /* make sure we're right justified */
+                    encodedSigSz = wc_EncodeSignature(encodedSig,
+                            sigCtx->digest, sigCtx->digestSz, sigCtx->typeH);
+                    if (encodedSigSz == verifySz && sigCtx->out != NULL &&
+                        XMEMCMP(sigCtx->out, encodedSig, encodedSigSz) == 0) {
+                        ret = 0;
+                    }
+                    else {
+                        WOLFSSL_MSG("RSA SSL verify match encode error");
+                        ret = ASN_SIG_CONFIRM_E;
+                    }
+
+                #ifdef WOLFSSL_SMALL_STACK
+                    XFREE(encodedSig, sigCtx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+                #endif
+                    break;
+                }
+            #endif /* NO_RSA */
+            #ifdef HAVE_ECC
+                case ECDSAk:
+                {
+                    if (sigCtx->verify == 1) {
+                        ret = 0;
+                    }
+                    else {
+                        WOLFSSL_MSG("ECC Verify didn't match");
+                        ret = ASN_SIG_CONFIRM_E;
+                    }
+                    break;
+                }
+            #endif /* HAVE_ECC */
+            #ifdef HAVE_ED25519
+                case ED25519k:
+                {
+                    if (sigCtx->verify == 1) {
+                        ret = 0;
+                    }
+                    else {
+                        WOLFSSL_MSG("ED25519 Verify didn't match");
+                        ret = ASN_SIG_CONFIRM_E;
+                    }
+                    break;
+                }
+            #endif /* HAVE_ED25519 */
+            #ifdef HAVE_ED448
+                case ED448k:
+                {
+                    if (sigCtx->verify == 1) {
+                        ret = 0;
+                    }
+                    else {
+                        WOLFSSL_MSG("ED448 Verify didn't match");
+                        ret = ASN_SIG_CONFIRM_E;
+                    }
+                    break;
+                }
+            #endif /* HAVE_ED448 */
+                default:
+                    break;
+            }  /* switch (keyOID) */
+
+            break;
+        } /* SIG_STATE_CHECK */
+    } /* switch (sigCtx->state) */
+
+exit_cs:
+
+#endif /* !NO_ASN_CRYPT */
+
+    (void)keyOID;
+    (void)sigOID;
+
+    WOLFSSL_LEAVE("ConfirmSignature", ret);
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E)
+        return ret;
+#endif
+
+    FreeSignatureCtx(sigCtx);
+
+    return ret;
+}
+
+
+#ifndef IGNORE_NAME_CONSTRAINTS
+
+static int MatchBaseName(int type, const char* name, int nameSz,
+                         const char* base, int baseSz)
+{
+    if (base == NULL || baseSz <= 0 || name == NULL || nameSz <= 0 ||
+            name[0] == '.' || nameSz < baseSz ||
+            (type != ASN_RFC822_TYPE && type != ASN_DNS_TYPE))
+        return 0;
+
+    /* If an email type, handle special cases where the base is only
+     * a domain, or is an email address itself. */
+    if (type == ASN_RFC822_TYPE) {
+        const char* p = NULL;
+        int count = 0;
+
+        if (base[0] != '.') {
+            p = base;
+            count = 0;
+
+            /* find the '@' in the base */
+            while (*p != '@' && count < baseSz) {
+                count++;
+                p++;
+            }
+
+            /* No '@' in base, reset p to NULL */
+            if (count >= baseSz)
+                p = NULL;
+        }
+
+        if (p == NULL) {
+            /* Base isn't an email address, it is a domain name,
+             * wind the name forward one character past its '@'. */
+            p = name;
+            count = 0;
+            while (*p != '@' && count < baseSz) {
+                count++;
+                p++;
+            }
+
+            if (count < baseSz && *p == '@') {
+                name = p + 1;
+                nameSz -= count + 1;
+            }
+        }
+    }
+
+    if ((type == ASN_DNS_TYPE || type == ASN_RFC822_TYPE) && base[0] == '.') {
+        int szAdjust = nameSz - baseSz;
+        name += szAdjust;
+        nameSz -= szAdjust;
+    }
+
+    while (nameSz > 0) {
+        if (XTOLOWER((unsigned char)*name++) !=
+                                               XTOLOWER((unsigned char)*base++))
+            return 0;
+        nameSz--;
+    }
+
+    return 1;
+}
+
+
+static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert)
+{
+    if (signer == NULL || cert == NULL)
+        return 0;
+
+    /* Check against the excluded list */
+    if (signer->excludedNames) {
+        Base_entry* base = signer->excludedNames;
+
+        while (base != NULL) {
+            switch (base->type) {
+                case ASN_DNS_TYPE:
+                {
+                    DNS_entry* name = cert->altNames;
+                    while (name != NULL) {
+                        if (MatchBaseName(ASN_DNS_TYPE,
+                                          name->name, name->len,
+                                          base->name, base->nameSz)) {
+                            return 0;
+                        }
+                        name = name->next;
+                    }
+                    break;
+                }
+                case ASN_RFC822_TYPE:
+                {
+                    DNS_entry* name = cert->altEmailNames;
+                    while (name != NULL) {
+                        if (MatchBaseName(ASN_RFC822_TYPE,
+                                          name->name, name->len,
+                                          base->name, base->nameSz)) {
+                            return 0;
+                        }
+                        name = name->next;
+                    }
+                    break;
+                }
+                case ASN_DIR_TYPE:
+                {
+                    /* allow permitted dirName smaller than actual subject */
+                    if (cert->subjectRawLen >= base->nameSz &&
+                        XMEMCMP(cert->subjectRaw, base->name,
+                                                        base->nameSz) == 0) {
+                        return 0;
+                    }
+                    break;
+                }
+            }; /* switch */
+            base = base->next;
+        }
+    }
+
+    /* Check against the permitted list */
+    if (signer->permittedNames != NULL) {
+        int needDns = 0;
+        int matchDns = 0;
+        int needEmail = 0;
+        int matchEmail = 0;
+        int needDir = 0;
+        int matchDir = 0;
+        Base_entry* base = signer->permittedNames;
+
+        while (base != NULL) {
+            switch (base->type) {
+                case ASN_DNS_TYPE:
+                {
+                    DNS_entry* name = cert->altNames;
+
+                    if (name != NULL)
+                        needDns = 1;
+
+                    while (name != NULL) {
+                        matchDns = MatchBaseName(ASN_DNS_TYPE,
+                                          name->name, name->len,
+                                          base->name, base->nameSz);
+                        name = name->next;
+                    }
+                    break;
+                }
+                case ASN_RFC822_TYPE:
+                {
+                    DNS_entry* name = cert->altEmailNames;
+
+                    if (name != NULL)
+                        needEmail = 1;
+
+                    while (name != NULL) {
+                        matchEmail = MatchBaseName(ASN_DNS_TYPE,
+                                          name->name, name->len,
+                                          base->name, base->nameSz);
+                        name = name->next;
+                    }
+                    break;
+                }
+                case ASN_DIR_TYPE:
+                {
+                    /* allow permitted dirName smaller than actual subject */
+                    needDir = 1;
+                    if (cert->subjectRaw != NULL &&
+                        cert->subjectRawLen >= base->nameSz &&
+                        XMEMCMP(cert->subjectRaw, base->name,
+                                                        base->nameSz) == 0) {
+                        matchDir = 1;
+                    }
+                    break;
+                }
+            } /* switch */
+            base = base->next;
+        }
+
+        if ((needDns   && !matchDns) ||
+            (needEmail && !matchEmail) ||
+            (needDir   && !matchDir)) {
+            return 0;
+        }
+    }
+
+    return 1;
+}
+
+#endif /* IGNORE_NAME_CONSTRAINTS */
+
+static int DecodeAltNames(const byte* input, int sz, DecodedCert* cert)
+{
+    word32 idx = 0;
+    int length = 0;
+
+    WOLFSSL_ENTER("DecodeAltNames");
+
+    if (GetSequence(input, &idx, &length, sz) < 0) {
+        WOLFSSL_MSG("\tBad Sequence");
+        return ASN_PARSE_E;
+    }
+
+    if (length == 0) {
+        /* RFC 5280 4.2.1.6.  Subject Alternative Name
+           If the subjectAltName extension is present, the sequence MUST
+           contain at least one entry. */
+        return ASN_PARSE_E;
+    }
+
+    cert->weOwnAltNames = 1;
+
+    while (length > 0) {
+        byte b = input[idx++];
+
+        length--;
+
+        /* Save DNS Type names in the altNames list. */
+        /* Save Other Type names in the cert's OidMap */
+        if (b == (ASN_CONTEXT_SPECIFIC | ASN_DNS_TYPE)) {
+            DNS_entry* dnsEntry;
+            int strLen;
+            word32 lenStartIdx = idx;
+
+            if (GetLength(input, &idx, &strLen, sz) < 0) {
+                WOLFSSL_MSG("\tfail: str length");
+                return ASN_PARSE_E;
+            }
+            length -= (idx - lenStartIdx);
+
+            dnsEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap,
+                                        DYNAMIC_TYPE_ALTNAME);
+            if (dnsEntry == NULL) {
+                WOLFSSL_MSG("\tOut of Memory");
+                return MEMORY_E;
+            }
+
+            dnsEntry->type = ASN_DNS_TYPE;
+            dnsEntry->name = (char*)XMALLOC(strLen + 1, cert->heap,
+                                         DYNAMIC_TYPE_ALTNAME);
+            if (dnsEntry->name == NULL) {
+                WOLFSSL_MSG("\tOut of Memory");
+                XFREE(dnsEntry, cert->heap, DYNAMIC_TYPE_ALTNAME);
+                return MEMORY_E;
+            }
+            dnsEntry->len = strLen;
+            XMEMCPY(dnsEntry->name, &input[idx], strLen);
+            dnsEntry->name[strLen] = '\0';
+
+            dnsEntry->next = cert->altNames;
+            cert->altNames = dnsEntry;
+
+            length -= strLen;
+            idx    += strLen;
+        }
+    #ifndef IGNORE_NAME_CONSTRAINTS
+        else if (b == (ASN_CONTEXT_SPECIFIC | ASN_RFC822_TYPE)) {
+            DNS_entry* emailEntry;
+            int strLen;
+            word32 lenStartIdx = idx;
+
+            if (GetLength(input, &idx, &strLen, sz) < 0) {
+                WOLFSSL_MSG("\tfail: str length");
+                return ASN_PARSE_E;
+            }
+            length -= (idx - lenStartIdx);
+
+            emailEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap,
+                                        DYNAMIC_TYPE_ALTNAME);
+            if (emailEntry == NULL) {
+                WOLFSSL_MSG("\tOut of Memory");
+                return MEMORY_E;
+            }
+
+            emailEntry->type = ASN_RFC822_TYPE;
+            emailEntry->name = (char*)XMALLOC(strLen + 1, cert->heap,
+                                         DYNAMIC_TYPE_ALTNAME);
+            if (emailEntry->name == NULL) {
+                WOLFSSL_MSG("\tOut of Memory");
+                XFREE(emailEntry, cert->heap, DYNAMIC_TYPE_ALTNAME);
+                return MEMORY_E;
+            }
+            emailEntry->len = strLen;
+            XMEMCPY(emailEntry->name, &input[idx], strLen);
+            emailEntry->name[strLen] = '\0';
+
+            emailEntry->next = cert->altEmailNames;
+            cert->altEmailNames = emailEntry;
+
+            length -= strLen;
+            idx    += strLen;
+        }
+        else if (b == (ASN_CONTEXT_SPECIFIC | ASN_URI_TYPE)) {
+            DNS_entry* uriEntry;
+            int strLen;
+            word32 lenStartIdx = idx;
+
+            WOLFSSL_MSG("\tPutting URI into list but not using");
+            if (GetLength(input, &idx, &strLen, sz) < 0) {
+                WOLFSSL_MSG("\tfail: str length");
+                return ASN_PARSE_E;
+            }
+            length -= (idx - lenStartIdx);
+
+            /* check that strLen at index is not past input buffer */
+            if (strLen + (int)idx > sz) {
+                return BUFFER_E;
+            }
+
+        #ifndef WOLFSSL_NO_ASN_STRICT
+            /* Verify RFC 5280 Sec 4.2.1.6 rule:
+                "The name MUST NOT be a relative URI" */
+
+            {
+                int i;
+
+                /* skip past scheme (i.e http,ftp,...) finding first ':' char */
+                for (i = 0; i < strLen; i++) {
+                    if (input[idx + i] == ':') {
+                        break;
+                    }
+                    if (input[idx + i] == '/') {
+                        i = strLen; /* error, found relative path since '/' was
+                                     * encountered before ':'. Returning error
+                                     * value in next if statement. */
+                    }
+                }
+
+                /* test if no ':' char was found and test that the next two
+                 * chars are // to match the pattern "://" */
+                if (i >= strLen - 2 || (input[idx + i + 1] != '/' ||
+                                        input[idx + i + 2] != '/')) {
+                    WOLFSSL_MSG("\tAlt Name must be absolute URI");
+                    return ASN_ALT_NAME_E;
+                }
+            }
+        #endif
+
+            uriEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap,
+                                        DYNAMIC_TYPE_ALTNAME);
+            if (uriEntry == NULL) {
+                WOLFSSL_MSG("\tOut of Memory");
+                return MEMORY_E;
+            }
+
+            uriEntry->type = ASN_URI_TYPE;
+            uriEntry->name = (char*)XMALLOC(strLen + 1, cert->heap,
+                                         DYNAMIC_TYPE_ALTNAME);
+            if (uriEntry->name == NULL) {
+                WOLFSSL_MSG("\tOut of Memory");
+                XFREE(uriEntry, cert->heap, DYNAMIC_TYPE_ALTNAME);
+                return MEMORY_E;
+            }
+            uriEntry->len = strLen;
+            XMEMCPY(uriEntry->name, &input[idx], strLen);
+            uriEntry->name[strLen] = '\0';
+
+            uriEntry->next = cert->altNames;
+            cert->altNames = uriEntry;
+
+            length -= strLen;
+            idx    += strLen;
+        }
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+        else if (b == (ASN_CONTEXT_SPECIFIC | ASN_IP_TYPE)) {
+            DNS_entry* ipAddr;
+            int strLen;
+            word32 lenStartIdx = idx;
+            WOLFSSL_MSG("Decoding Subject Alt. Name: IP Address");
+
+            if (GetLength(input, &idx, &strLen, sz) < 0) {
+                WOLFSSL_MSG("\tfail: str length");
+                return ASN_PARSE_E;
+            }
+            length -= (idx - lenStartIdx);
+            /* check that strLen at index is not past input buffer */
+            if (strLen + (int)idx > sz) {
+                return BUFFER_E;
+            }
+
+            ipAddr = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap,
+                                        DYNAMIC_TYPE_ALTNAME);
+            if (ipAddr == NULL) {
+                WOLFSSL_MSG("\tOut of Memory");
+                return MEMORY_E;
+            }
+
+            ipAddr->type = ASN_IP_TYPE;
+            ipAddr->name = (char*)XMALLOC(strLen + 1, cert->heap,
+                                         DYNAMIC_TYPE_ALTNAME);
+            if (ipAddr->name == NULL) {
+                WOLFSSL_MSG("\tOut of Memory");
+                XFREE(ipAddr, cert->heap, DYNAMIC_TYPE_ALTNAME);
+                return MEMORY_E;
+            }
+            ipAddr->len = strLen;
+            XMEMCPY(ipAddr->name, &input[idx], strLen);
+            ipAddr->name[strLen] = '\0';
+
+            ipAddr->next   = cert->altNames;
+            cert->altNames = ipAddr;
+
+            length -= strLen;
+            idx    += strLen;
+        }
+#endif /* WOLFSSL_QT || OPENSSL_ALL */
+#endif /* IGNORE_NAME_CONSTRAINTS */
+#ifdef WOLFSSL_SEP
+        else if (b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | ASN_OTHER_TYPE))
+        {
+            int strLen;
+            word32 lenStartIdx = idx;
+            word32 oid = 0;
+            int    ret;
+            byte   tag;
+
+            if (GetLength(input, &idx, &strLen, sz) < 0) {
+                WOLFSSL_MSG("\tfail: other name length");
+                return ASN_PARSE_E;
+            }
+            /* Consume the rest of this sequence. */
+            length -= (strLen + idx - lenStartIdx);
+
+            if (GetObjectId(input, &idx, &oid, oidCertAltNameType, sz) < 0) {
+                WOLFSSL_MSG("\tbad OID");
+                return ASN_PARSE_E;
+            }
+
+            if (oid != HW_NAME_OID) {
+                WOLFSSL_MSG("\tincorrect OID");
+                return ASN_PARSE_E;
+            }
+
+            if (GetASNTag(input, &idx, &tag, sz) < 0) {
+                return ASN_PARSE_E;
+            }
+
+            if (tag != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) {
+                WOLFSSL_MSG("\twrong type");
+                return ASN_PARSE_E;
+            }
+
+            if (GetLength(input, &idx, &strLen, sz) < 0) {
+                WOLFSSL_MSG("\tfail: str len");
+                return ASN_PARSE_E;
+            }
+
+            if (GetSequence(input, &idx, &strLen, sz) < 0) {
+                WOLFSSL_MSG("\tBad Sequence");
+                return ASN_PARSE_E;
+            }
+
+            ret = GetASNObjectId(input, &idx, &strLen, sz);
+            if (ret != 0) {
+                WOLFSSL_MSG("\tbad OID");
+                return ret;
+            }
+
+            cert->hwType = (byte*)XMALLOC(strLen, cert->heap,
+                                          DYNAMIC_TYPE_X509_EXT);
+            if (cert->hwType == NULL) {
+                WOLFSSL_MSG("\tOut of Memory");
+                return MEMORY_E;
+            }
+
+            XMEMCPY(cert->hwType, &input[idx], strLen);
+            cert->hwTypeSz = strLen;
+            idx += strLen;
+
+            ret = GetOctetString(input, &idx, &strLen, sz);
+            if (ret < 0)
+                return ret;
+
+            cert->hwSerialNum = (byte*)XMALLOC(strLen + 1, cert->heap,
+                                               DYNAMIC_TYPE_X509_EXT);
+            if (cert->hwSerialNum == NULL) {
+                WOLFSSL_MSG("\tOut of Memory");
+                return MEMORY_E;
+            }
+
+            XMEMCPY(cert->hwSerialNum, &input[idx], strLen);
+            cert->hwSerialNum[strLen] = '\0';
+            cert->hwSerialNumSz = strLen;
+            idx += strLen;
+        }
+    #endif /* WOLFSSL_SEP */
+        else {
+            int strLen;
+            word32 lenStartIdx = idx;
+
+            WOLFSSL_MSG("\tUnsupported name type, skipping");
+
+            if (GetLength(input, &idx, &strLen, sz) < 0) {
+                WOLFSSL_MSG("\tfail: unsupported name length");
+                return ASN_PARSE_E;
+            }
+            length -= (strLen + idx - lenStartIdx);
+            idx += strLen;
+        }
+    }
+    return 0;
+}
+
+static int DecodeBasicCaConstraint(const byte* input, int sz, DecodedCert* cert)
+{
+    word32 idx = 0;
+    int length = 0;
+    int ret;
+
+    WOLFSSL_ENTER("DecodeBasicCaConstraint");
+
+    if (GetSequence(input, &idx, &length, sz) < 0) {
+        WOLFSSL_MSG("\tfail: bad SEQUENCE");
+        return ASN_PARSE_E;
+    }
+
+    if (length == 0)
+        return 0;
+
+    /* If the basic ca constraint is false, this extension may be named, but
+     * left empty. So, if the length is 0, just return. */
+
+    ret = GetBoolean(input, &idx, sz);
+
+#ifndef WOLFSSL_X509_BASICCONS_INT
+    if (ret < 0) {
+        WOLFSSL_MSG("\tfail: constraint not valid BOOLEAN");
+        return ret;
+    }
+
+    cert->isCA = (byte)ret;
+#else
+    if (ret < 0) {
+        if(input[idx] == ASN_INTEGER) {
+            /* For OpenSSL compatibility, if ASN_INTEGER it is valid format */
+            cert->isCA = FALSE;
+        } else return ret;
+    } else
+        cert->isCA = (byte)ret;
+#endif
+
+    /* If there isn't any more data, return. */
+    if (idx >= (word32)sz) {
+        return 0;
+    }
+
+    ret = GetInteger7Bit(input, &idx, sz);
+    if (ret < 0)
+        return ret;
+    cert->pathLength = (byte)ret;
+    cert->pathLengthSet = 1;
+
+    return 0;
+}
+
+
+#define CRLDP_FULL_NAME 0
+    /* From RFC3280 SS4.2.1.14, Distribution Point Name*/
+#define GENERALNAME_URI 6
+    /* From RFC3280 SS4.2.1.7, GeneralName */
+
+static int DecodeCrlDist(const byte* input, int sz, DecodedCert* cert)
+{
+    word32 idx = 0, localIdx;
+    int length = 0;
+    byte tag   = 0;
+
+    WOLFSSL_ENTER("DecodeCrlDist");
+
+    /* Unwrap the list of Distribution Points*/
+    if (GetSequence(input, &idx, &length, sz) < 0)
+        return ASN_PARSE_E;
+
+    /* Unwrap a single Distribution Point */
+    if (GetSequence(input, &idx, &length, sz) < 0)
+        return ASN_PARSE_E;
+
+    /* The Distribution Point has three explicit optional members
+     *  First check for a DistributionPointName
+     */
+    localIdx = idx;
+    if (GetASNTag(input, &localIdx, &tag, sz) == 0 &&
+            tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
+    {
+        idx++;
+        if (GetLength(input, &idx, &length, sz) < 0)
+            return ASN_PARSE_E;
+
+        localIdx = idx;
+        if (GetASNTag(input, &localIdx, &tag, sz) == 0 &&
+                tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED |
+                    CRLDP_FULL_NAME))
+        {
+            idx++;
+            if (GetLength(input, &idx, &length, sz) < 0)
+                return ASN_PARSE_E;
+
+            localIdx = idx;
+            if (GetASNTag(input, &localIdx, &tag, sz) == 0 &&
+                    tag == (ASN_CONTEXT_SPECIFIC | GENERALNAME_URI))
+            {
+                idx++;
+                if (GetLength(input, &idx, &length, sz) < 0)
+                    return ASN_PARSE_E;
+
+                cert->extCrlInfoSz = length;
+                cert->extCrlInfo = input + idx;
+                idx += length;
+            }
+            else
+                /* This isn't a URI, skip it. */
+                idx += length;
+        }
+        else {
+            /* This isn't a FULLNAME, skip it. */
+            idx += length;
+        }
+    }
+
+    /* Check for reasonFlags */
+    localIdx = idx;
+    if (idx < (word32)sz &&
+        GetASNTag(input, &localIdx, &tag, sz) == 0 &&
+        tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
+    {
+        idx++;
+        if (GetLength(input, &idx, &length, sz) < 0)
+            return ASN_PARSE_E;
+        idx += length;
+    }
+
+    /* Check for cRLIssuer */
+    localIdx = idx;
+    if (idx < (word32)sz &&
+        GetASNTag(input, &localIdx, &tag, sz) == 0 &&
+        tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 2))
+    {
+        idx++;
+        if (GetLength(input, &idx, &length, sz) < 0)
+            return ASN_PARSE_E;
+        idx += length;
+    }
+
+    if (idx < (word32)sz)
+    {
+        WOLFSSL_MSG("\tThere are more CRL Distribution Point records, "
+                   "but we only use the first one.");
+    }
+
+    return 0;
+}
+
+
+static int DecodeAuthInfo(const byte* input, int sz, DecodedCert* cert)
+/*
+ *  Read Authority Information Access records. If there are
+ *  any issues, return without saving the record.
+ */
+{
+    word32 idx = 0;
+    int length = 0;
+    int count  = 0;
+    byte b = 0;
+    word32 oid;
+
+    WOLFSSL_ENTER("DecodeAuthInfo");
+
+    /* Unwrap the list of AIAs */
+    if (GetSequence(input, &idx, &length, sz) < 0)
+        return ASN_PARSE_E;
+
+    while ((idx < (word32)sz) && (count < MAX_AIA_SZ)) {
+        /* Unwrap a single AIA */
+        if (GetSequence(input, &idx, &length, sz) < 0)
+            return ASN_PARSE_E;
+
+        oid = 0;
+        if (GetObjectId(input, &idx, &oid, oidCertAuthInfoType, sz) < 0)
+            return ASN_PARSE_E;
+
+        /* Only supporting URIs right now. */
+        if (GetASNTag(input, &idx, &b, sz) < 0)
+            return ASN_PARSE_E;
+
+        if (GetLength(input, &idx, &length, sz) < 0)
+            return ASN_PARSE_E;
+
+        /* Set ocsp entry */
+        if (b == (ASN_CONTEXT_SPECIFIC | GENERALNAME_URI) &&
+            oid == AIA_OCSP_OID)
+        {
+            cert->extAuthInfoSz = length;
+            cert->extAuthInfo = input + idx;
+            count++;
+        #if !defined(OPENSSL_ALL) || !defined(WOLFSSL_QT)
+            break;
+        #endif
+        }
+        #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+        /* Set CaIssuers entry */
+        else if ((b == (ASN_CONTEXT_SPECIFIC | GENERALNAME_URI)) &&
+            oid == AIA_CA_ISSUER_OID)
+        {
+            cert->extAuthInfoCaIssuerSz = length;
+            cert->extAuthInfoCaIssuer = input + idx;
+            count++;
+        }
+        #endif
+        idx += length;
+    }
+
+    return 0;
+}
+
+
+static int DecodeAuthKeyId(const byte* input, int sz, DecodedCert* cert)
+{
+    word32 idx = 0;
+    int length = 0, ret = 0;
+    byte tag;
+
+    WOLFSSL_ENTER("DecodeAuthKeyId");
+
+    if (GetSequence(input, &idx, &length, sz) < 0) {
+        WOLFSSL_MSG("\tfail: should be a SEQUENCE\n");
+        return ASN_PARSE_E;
+    }
+
+    if (GetASNTag(input, &idx, &tag, sz) < 0) {
+        return ASN_PARSE_E;
+    }
+
+    if (tag != (ASN_CONTEXT_SPECIFIC | 0)) {
+        WOLFSSL_MSG("\tinfo: OPTIONAL item 0, not available\n");
+        cert->extAuthKeyIdSet = 0;
+        return 0;
+    }
+
+    if (GetLength(input, &idx, &length, sz) <= 0) {
+        WOLFSSL_MSG("\tfail: extension data length");
+        return ASN_PARSE_E;
+    }
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+    cert->extAuthKeyIdSrc = &input[idx];
+    cert->extAuthKeyIdSz = length;
+#endif /* OPENSSL_EXTRA */
+
+    if (length == KEYID_SIZE) {
+        XMEMCPY(cert->extAuthKeyId, input + idx, length);
+    }
+    else
+        ret = CalcHashId(input + idx, length, cert->extAuthKeyId);
+
+    return ret;
+}
+
+
+static int DecodeSubjKeyId(const byte* input, int sz, DecodedCert* cert)
+{
+    word32 idx = 0;
+    int length = 0, ret = 0;
+
+    WOLFSSL_ENTER("DecodeSubjKeyId");
+
+    if (sz <= 0)
+        return ASN_PARSE_E;
+
+    ret = GetOctetString(input, &idx, &length, sz);
+    if (ret < 0)
+        return ret;
+
+    #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+        cert->extSubjKeyIdSrc = &input[idx];
+        cert->extSubjKeyIdSz = length;
+    #endif /* OPENSSL_EXTRA */
+
+    if (length == KEYID_SIZE) {
+        XMEMCPY(cert->extSubjKeyId, input + idx, length);
+    }
+    else
+        ret = CalcHashId(input + idx, length, cert->extSubjKeyId);
+
+    return ret;
+}
+
+
+static int DecodeKeyUsage(const byte* input, int sz, DecodedCert* cert)
+{
+    word32 idx = 0;
+    int length;
+    int ret;
+    WOLFSSL_ENTER("DecodeKeyUsage");
+
+    ret = CheckBitString(input, &idx, &length, sz, 0, NULL);
+    if (ret != 0)
+        return ret;
+
+    cert->extKeyUsage = (word16)(input[idx]);
+    if (length == 2)
+        cert->extKeyUsage |= (word16)(input[idx+1] << 8);
+
+    return 0;
+}
+
+
+static int DecodeExtKeyUsage(const byte* input, int sz, DecodedCert* cert)
+{
+    word32 idx = 0, oid;
+    int length, ret;
+
+    WOLFSSL_MSG("DecodeExtKeyUsage");
+
+    if (GetSequence(input, &idx, &length, sz) < 0) {
+        WOLFSSL_MSG("\tfail: should be a SEQUENCE");
+        return ASN_PARSE_E;
+    }
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+    cert->extExtKeyUsageSrc = input + idx;
+    cert->extExtKeyUsageSz = length;
+#endif
+
+    while (idx < (word32)sz) {
+        ret = GetObjectId(input, &idx, &oid, oidCertKeyUseType, sz);
+        if (ret == ASN_UNKNOWN_OID_E)
+            continue;
+        else if (ret < 0)
+            return ret;
+
+        switch (oid) {
+            case EKU_ANY_OID:
+                cert->extExtKeyUsage |= EXTKEYUSE_ANY;
+                break;
+            case EKU_SERVER_AUTH_OID:
+                cert->extExtKeyUsage |= EXTKEYUSE_SERVER_AUTH;
+                break;
+            case EKU_CLIENT_AUTH_OID:
+                cert->extExtKeyUsage |= EXTKEYUSE_CLIENT_AUTH;
+                break;
+            case EKU_CODESIGNING_OID:
+                cert->extExtKeyUsage |= EXTKEYUSE_CODESIGN;
+                break;
+            case EKU_EMAILPROTECT_OID:
+                cert->extExtKeyUsage |= EXTKEYUSE_EMAILPROT;
+                break;
+            case EKU_TIMESTAMP_OID:
+                cert->extExtKeyUsage |= EXTKEYUSE_TIMESTAMP;
+                break;
+            case EKU_OCSP_SIGN_OID:
+                cert->extExtKeyUsage |= EXTKEYUSE_OCSP_SIGN;
+                break;
+        }
+
+    #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+        cert->extExtKeyUsageCount++;
+    #endif
+    }
+
+    return 0;
+}
+
+
+#ifndef IGNORE_NAME_CONSTRAINTS
+#define ASN_TYPE_MASK 0xF
+static int DecodeSubtree(const byte* input, int sz,
+                         Base_entry** head, void* heap)
+{
+    word32 idx = 0;
+
+    (void)heap;
+
+    while (idx < (word32)sz) {
+        int seqLength, strLength;
+        word32 nameIdx;
+        byte b, bType;
+
+        if (GetSequence(input, &idx, &seqLength, sz) < 0) {
+            WOLFSSL_MSG("\tfail: should be a SEQUENCE");
+            return ASN_PARSE_E;
+        }
+        nameIdx = idx;
+        b = input[nameIdx++];
+
+        if (GetLength(input, &nameIdx, &strLength, sz) <= 0) {
+            WOLFSSL_MSG("\tinvalid length");
+            return ASN_PARSE_E;
+        }
+
+        /* Get type, LSB 4-bits */
+        bType = (b & ASN_TYPE_MASK);
+
+        if (bType == ASN_DNS_TYPE || bType == ASN_RFC822_TYPE ||
+                                                        bType == ASN_DIR_TYPE) {
+            Base_entry* entry;
+
+            /* if constructed has leading sequence */
+            if (b & ASN_CONSTRUCTED) {
+                if (GetSequence(input, &nameIdx, &strLength, sz) < 0) {
+                    WOLFSSL_MSG("\tfail: constructed be a SEQUENCE");
+                    return ASN_PARSE_E;
+                }
+            }
+
+            entry = (Base_entry*)XMALLOC(sizeof(Base_entry), heap,
+                                                          DYNAMIC_TYPE_ALTNAME);
+            if (entry == NULL) {
+                WOLFSSL_MSG("allocate error");
+                return MEMORY_E;
+            }
+
+            entry->name = (char*)XMALLOC(strLength, heap, DYNAMIC_TYPE_ALTNAME);
+            if (entry->name == NULL) {
+                WOLFSSL_MSG("allocate error");
+                XFREE(entry, heap, DYNAMIC_TYPE_ALTNAME);
+                return MEMORY_E;
+            }
+
+            XMEMCPY(entry->name, &input[nameIdx], strLength);
+            entry->nameSz = strLength;
+            entry->type = bType;
+
+            entry->next = *head;
+            *head = entry;
+        }
+
+        idx += seqLength;
+    }
+
+    return 0;
+}
+
+
+static int DecodeNameConstraints(const byte* input, int sz, DecodedCert* cert)
+{
+    word32 idx = 0;
+    int length = 0;
+
+    WOLFSSL_ENTER("DecodeNameConstraints");
+
+    if (GetSequence(input, &idx, &length, sz) < 0) {
+        WOLFSSL_MSG("\tfail: should be a SEQUENCE");
+        return ASN_PARSE_E;
+    }
+
+    while (idx < (word32)sz) {
+        byte b = input[idx++];
+        Base_entry** subtree = NULL;
+
+        if (GetLength(input, &idx, &length, sz) <= 0) {
+            WOLFSSL_MSG("\tinvalid length");
+            return ASN_PARSE_E;
+        }
+
+        if (b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0))
+            subtree = &cert->permittedNames;
+        else if (b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1))
+            subtree = &cert->excludedNames;
+        else {
+            WOLFSSL_MSG("\tinvalid subtree");
+            return ASN_PARSE_E;
+        }
+
+        DecodeSubtree(input + idx, length, subtree, cert->heap);
+
+        idx += length;
+    }
+
+    return 0;
+}
+#endif /* IGNORE_NAME_CONSTRAINTS */
+
+#if (defined(WOLFSSL_CERT_EXT) && !defined(WOLFSSL_SEP)) || defined(OPENSSL_EXTRA)
+
+/* Decode ITU-T X.690 OID format to a string representation
+ * return string length */
+int DecodePolicyOID(char *out, word32 outSz, const byte *in, word32 inSz)
+{
+    word32 val, inIdx = 0, outIdx = 0;
+    int w = 0;
+
+    if (out == NULL || in == NULL || outSz < 4 || inSz < 2)
+        return BAD_FUNC_ARG;
+
+    /* The first byte expands into b/40 dot b%40. */
+    val = in[inIdx++];
+
+    w = XSNPRINTF(out, outSz, "%u.%u", val / 40, val % 40);
+    if (w < 0)
+        goto exit;
+    outIdx += w;
+    val = 0;
+
+    while (inIdx < inSz && outIdx < outSz) {
+        /* extract the next OID digit from in to val */
+        /* first bit is used to set if value is coded on 1 or multiple bytes */
+        if (in[inIdx] & 0x80) {
+            val += in[inIdx] & 0x7F;
+            val *= 128;
+        }
+        else {
+            /* write val as text into out */
+            val += in[inIdx];
+            w = XSNPRINTF(out + outIdx, outSz - outIdx, ".%u", val);
+            if (w < 0)
+                goto exit;
+            outIdx += w;
+            val = 0;
+        }
+        inIdx++;
+    }
+    if (outIdx == outSz)
+        outIdx--;
+    out[outIdx] = 0;
+
+    w = (int)outIdx;
+
+exit:
+    return w;
+}
+#endif /* WOLFSSL_CERT_EXT && !WOLFSSL_SEP */
+
+#if defined(WOLFSSL_SEP) || defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_QT)
+    /* Reference: https://tools.ietf.org/html/rfc5280#section-4.2.1.4 */
+    static int DecodeCertPolicy(const byte* input, int sz, DecodedCert* cert)
+    {
+        word32 idx = 0;
+        word32 oldIdx;
+        int ret;
+        int total_length = 0, policy_length = 0, length = 0;
+    #if !defined(WOLFSSL_SEP) && defined(WOLFSSL_CERT_EXT) && \
+        !defined(WOLFSSL_DUP_CERTPOL)
+        int i;
+    #endif
+
+        WOLFSSL_ENTER("DecodeCertPolicy");
+        #if defined(WOLFSSL_SEP) || defined(WOLFSSL_CERT_EXT)
+        /* Check if cert is null before dereferencing below */
+        if (cert == NULL)
+            return BAD_FUNC_ARG;
+        #endif
+
+    #if defined(WOLFSSL_CERT_EXT)
+         cert->extCertPoliciesNb = 0;
+    #endif
+
+        if (GetSequence(input, &idx, &total_length, sz) < 0) {
+            WOLFSSL_MSG("\tGet CertPolicy total seq failed");
+            return ASN_PARSE_E;
+        }
+
+        /* Validate total length */
+        if (total_length > (sz - (int)idx)) {
+            WOLFSSL_MSG("\tCertPolicy length mismatch");
+            return ASN_PARSE_E;
+        }
+
+        /* Unwrap certificatePolicies */
+        do {
+            if (GetSequence(input, &idx, &policy_length, sz) < 0) {
+                WOLFSSL_MSG("\tGet CertPolicy seq failed");
+                return ASN_PARSE_E;
+            }
+
+            oldIdx = idx;
+            ret = GetASNObjectId(input, &idx, &length, sz);
+            if (ret != 0)
+                return ret;
+            policy_length -= idx - oldIdx;
+
+            if (length > 0) {
+                /* Verify length won't overrun buffer */
+                if (length > (sz - (int)idx)) {
+                    WOLFSSL_MSG("\tCertPolicy length exceeds input buffer");
+                    return ASN_PARSE_E;
+                }
+
+        #if defined(WOLFSSL_SEP)
+                cert->deviceType = (byte*)XMALLOC(length, cert->heap,
+                                                         DYNAMIC_TYPE_X509_EXT);
+                if (cert->deviceType == NULL) {
+                    WOLFSSL_MSG("\tCouldn't alloc memory for deviceType");
+                    return MEMORY_E;
+                }
+                cert->deviceTypeSz = length;
+                XMEMCPY(cert->deviceType, input + idx, length);
+                break;
+        #elif defined(WOLFSSL_CERT_EXT)
+                /* decode cert policy */
+                if (DecodePolicyOID(cert->extCertPolicies[
+                                       cert->extCertPoliciesNb], MAX_CERTPOL_SZ,
+                                       input + idx, length) <= 0) {
+                    WOLFSSL_MSG("\tCouldn't decode CertPolicy");
+                    return ASN_PARSE_E;
+                }
+            #ifndef WOLFSSL_DUP_CERTPOL
+                /* From RFC 5280 section 4.2.1.3 "A certificate policy OID MUST
+                 * NOT appear more than once in a certificate policies
+                 * extension". This is a sanity check for duplicates.
+                 * extCertPolicies should only have OID values, additional
+                 * qualifiers need to be stored in a separate array. */
+                for (i = 0; i < cert->extCertPoliciesNb; i++) {
+                    if (XMEMCMP(cert->extCertPolicies[i],
+                            cert->extCertPolicies[cert->extCertPoliciesNb],
+                            MAX_CERTPOL_SZ) == 0) {
+                            WOLFSSL_MSG("Duplicate policy OIDs not allowed");
+                            WOLFSSL_MSG("Use WOLFSSL_DUP_CERTPOL if wanted");
+                            return CERTPOLICIES_E;
+                    }
+                }
+            #endif /* !WOLFSSL_DUP_CERTPOL */
+                cert->extCertPoliciesNb++;
+        #else
+                WOLFSSL_LEAVE("DecodeCertPolicy : unsupported mode", 0);
+                return 0;
+        #endif
+            }
+            idx += policy_length;
+        } while((int)idx < total_length
+    #if defined(WOLFSSL_CERT_EXT)
+            && cert->extCertPoliciesNb < MAX_CERTPOL_NB
+    #endif
+        );
+
+        WOLFSSL_LEAVE("DecodeCertPolicy", 0);
+        return 0;
+    }
+#endif /* WOLFSSL_SEP */
+
+/* Macro to check if bit is set, if not sets and return success.
+    Otherwise returns failure */
+/* Macro required here because bit-field operation */
+#ifndef WOLFSSL_NO_ASN_STRICT
+    #define VERIFY_AND_SET_OID(bit) \
+        if (bit == 0) \
+            bit = 1; \
+        else \
+            return ASN_OBJECT_ID_E;
+#else
+    /* With no strict defined, the verify is skipped */
+#define VERIFY_AND_SET_OID(bit) bit = 1;
+#endif
+
+static int DecodeCertExtensions(DecodedCert* cert)
+/*
+ *  Processing the Certificate Extensions. This does not modify the current
+ *  index. It is works starting with the recorded extensions pointer.
+ */
+{
+    int ret = 0;
+    word32 idx = 0;
+    int sz = cert->extensionsSz;
+    const byte* input = cert->extensions;
+    int length;
+    word32 oid;
+    byte critical = 0;
+    byte criticalFail = 0;
+    byte tag = 0;
+
+    WOLFSSL_ENTER("DecodeCertExtensions");
+
+    if (input == NULL || sz == 0)
+        return BAD_FUNC_ARG;
+
+    if (GetASNTag(input, &idx, &tag, sz) < 0) {
+        return ASN_PARSE_E;
+    }
+
+    if (tag != ASN_EXTENSIONS) {
+        WOLFSSL_MSG("\tfail: should be an EXTENSIONS");
+        return ASN_PARSE_E;
+    }
+
+    if (GetLength(input, &idx, &length, sz) < 0) {
+        WOLFSSL_MSG("\tfail: invalid length");
+        return ASN_PARSE_E;
+    }
+
+    if (GetSequence(input, &idx, &length, sz) < 0) {
+        WOLFSSL_MSG("\tfail: should be a SEQUENCE (1)");
+        return ASN_PARSE_E;
+    }
+
+    while (idx < (word32)sz) {
+        word32 localIdx;
+
+        if (GetSequence(input, &idx, &length, sz) < 0) {
+            WOLFSSL_MSG("\tfail: should be a SEQUENCE");
+            return ASN_PARSE_E;
+        }
+
+        oid = 0;
+        if ((ret = GetObjectId(input, &idx, &oid, oidCertExtType, sz)) < 0) {
+            WOLFSSL_MSG("\tfail: OBJECT ID");
+            return ret;
+        }
+
+        /* check for critical flag */
+        critical = 0;
+        if ((idx + 1) > (word32)sz) {
+            WOLFSSL_MSG("\tfail: malformed buffer");
+            return BUFFER_E;
+        }
+
+        localIdx = idx;
+        if (GetASNTag(input, &localIdx, &tag, sz) == 0) {
+            if (tag == ASN_BOOLEAN) {
+                ret = GetBoolean(input, &idx, sz);
+                if (ret < 0) {
+                    WOLFSSL_MSG("\tfail: critical boolean");
+                    return ret;
+                }
+
+                critical = (byte)ret;
+            }
+        }
+
+        /* process the extension based on the OID */
+        ret = GetOctetString(input, &idx, &length, sz);
+        if (ret < 0) {
+            WOLFSSL_MSG("\tfail: bad OCTET STRING");
+            return ret;
+        }
+
+        switch (oid) {
+            case BASIC_CA_OID:
+                VERIFY_AND_SET_OID(cert->extBasicConstSet);
+                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                    cert->extBasicConstCrit = critical;
+                #endif
+                if (DecodeBasicCaConstraint(&input[idx], length, cert) < 0)
+                    return ASN_PARSE_E;
+                break;
+
+            case CRL_DIST_OID:
+                VERIFY_AND_SET_OID(cert->extCRLdistSet);
+                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                    cert->extCRLdistCrit = critical;
+                #endif
+                if (DecodeCrlDist(&input[idx], length, cert) < 0)
+                    return ASN_PARSE_E;
+                break;
+
+            case AUTH_INFO_OID:
+                VERIFY_AND_SET_OID(cert->extAuthInfoSet);
+                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                    cert->extAuthInfoCrit = critical;
+                #endif
+                if (DecodeAuthInfo(&input[idx], length, cert) < 0)
+                    return ASN_PARSE_E;
+                break;
+
+            case ALT_NAMES_OID:
+                VERIFY_AND_SET_OID(cert->extSubjAltNameSet);
+                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                    cert->extSubjAltNameCrit = critical;
+                #endif
+                ret = DecodeAltNames(&input[idx], length, cert);
+                if (ret < 0)
+                    return ret;
+                break;
+
+            case AUTH_KEY_OID:
+                VERIFY_AND_SET_OID(cert->extAuthKeyIdSet);
+                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                    cert->extAuthKeyIdCrit = critical;
+                #endif
+                #ifndef WOLFSSL_ALLOW_CRIT_SKID
+                    /* This check is added due to RFC 5280 section 4.2.1.1
+                     * stating that conforming CA's must mark this extension
+                     * as non-critical. When parsing extensions check that
+                     * certificate was made in compliance with this. */
+                    if (critical) {
+                        WOLFSSL_MSG("Critical Auth Key ID is not allowed");
+                        WOLFSSL_MSG("Use macro WOLFSSL_ALLOW_CRIT_SKID if wanted");
+                        return ASN_CRIT_EXT_E;
+                    }
+                #endif
+                if (DecodeAuthKeyId(&input[idx], length, cert) < 0)
+                    return ASN_PARSE_E;
+                break;
+
+            case SUBJ_KEY_OID:
+                VERIFY_AND_SET_OID(cert->extSubjKeyIdSet);
+                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                    cert->extSubjKeyIdCrit = critical;
+                #endif
+                #ifndef WOLFSSL_ALLOW_CRIT_SKID
+                    /* This check is added due to RFC 5280 section 4.2.1.2
+                     * stating that conforming CA's must mark this extension
+                     * as non-critical. When parsing extensions check that
+                     * certificate was made in compliance with this. */
+                    if (critical) {
+                        WOLFSSL_MSG("Critical Subject Key ID is not allowed");
+                        WOLFSSL_MSG("Use macro WOLFSSL_ALLOW_CRIT_SKID if wanted");
+                        return ASN_CRIT_EXT_E;
+                    }
+                #endif
+
+                if (DecodeSubjKeyId(&input[idx], length, cert) < 0)
+                    return ASN_PARSE_E;
+                break;
+
+            case CERT_POLICY_OID:
+                #if defined(WOLFSSL_SEP) || defined(WOLFSSL_QT)
+                    VERIFY_AND_SET_OID(cert->extCertPolicySet);
+                    #if defined(OPENSSL_EXTRA) || \
+                        defined(OPENSSL_EXTRA_X509_SMALL)
+                        cert->extCertPolicyCrit = critical;
+                    #endif
+                #endif
+                #if defined(WOLFSSL_SEP) || defined(WOLFSSL_CERT_EXT) || \
+                    defined(WOLFSSL_QT)
+                    if (DecodeCertPolicy(&input[idx], length, cert) < 0) {
+                        return ASN_PARSE_E;
+                    }
+                #else
+                    WOLFSSL_MSG("Certificate Policy extension not supported yet.");
+                #endif
+                break;
+
+            case KEY_USAGE_OID:
+                VERIFY_AND_SET_OID(cert->extKeyUsageSet);
+                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                    cert->extKeyUsageCrit = critical;
+                #endif
+                if (DecodeKeyUsage(&input[idx], length, cert) < 0)
+                    return ASN_PARSE_E;
+                break;
+
+            case EXT_KEY_USAGE_OID:
+                VERIFY_AND_SET_OID(cert->extExtKeyUsageSet);
+                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                    cert->extExtKeyUsageCrit = critical;
+                #endif
+                if (DecodeExtKeyUsage(&input[idx], length, cert) < 0)
+                    return ASN_PARSE_E;
+                break;
+
+            #ifndef IGNORE_NAME_CONSTRAINTS
+            case NAME_CONS_OID:
+            #ifndef WOLFSSL_NO_ASN_STRICT
+                /* Verify RFC 5280 Sec 4.2.1.10 rule:
+                    "The name constraints extension,
+                    which MUST be used only in a CA certificate" */
+                if (!cert->isCA) {
+                    WOLFSSL_MSG("Name constraints allowed only for CA certs");
+                    return ASN_NAME_INVALID_E;
+                }
+            #endif
+                VERIFY_AND_SET_OID(cert->extNameConstraintSet);
+                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+                    cert->extNameConstraintCrit = critical;
+                #endif
+                if (DecodeNameConstraints(&input[idx], length, cert) < 0)
+                    return ASN_PARSE_E;
+                break;
+            #endif /* IGNORE_NAME_CONSTRAINTS */
+
+            case INHIBIT_ANY_OID:
+                VERIFY_AND_SET_OID(cert->inhibitAnyOidSet);
+                WOLFSSL_MSG("Inhibit anyPolicy extension not supported yet.");
+                break;
+
+       #ifndef IGNORE_NETSCAPE_CERT_TYPE
+            case NETSCAPE_CT_OID:
+                WOLFSSL_MSG("Netscape certificate type extension not supported "
+                            "yet.");
+                if (CheckBitString(input, &idx, &length, idx + length, 0,
+                                                                    NULL) < 0) {
+                    return ASN_PARSE_E;
+                }
+                break;
+        #endif
+
+            default:
+            #ifndef WOLFSSL_NO_ASN_STRICT
+                /* While it is a failure to not support critical extensions,
+                 * still parse the certificate ignoring the unsupported
+                 * extension to allow caller to accept it with the verify
+                 * callback. */
+                if (critical)
+                    criticalFail = 1;
+            #endif
+            break;
+        }
+        idx += length;
+    }
+
+    return criticalFail ? ASN_CRIT_EXT_E : 0;
+}
+
+int ParseCert(DecodedCert* cert, int type, int verify, void* cm)
+{
+    int   ret;
+    char* ptr;
+
+    ret = ParseCertRelative(cert, type, verify, cm);
+    if (ret < 0)
+        return ret;
+
+    if (cert->subjectCNLen > 0) {
+        ptr = (char*) XMALLOC(cert->subjectCNLen + 1, cert->heap,
+                              DYNAMIC_TYPE_SUBJECT_CN);
+        if (ptr == NULL)
+            return MEMORY_E;
+        XMEMCPY(ptr, cert->subjectCN, cert->subjectCNLen);
+        ptr[cert->subjectCNLen] = '\0';
+        cert->subjectCN = ptr;
+        cert->subjectCNStored = 1;
+    }
+
+    if (cert->keyOID == RSAk &&
+                          cert->publicKey != NULL  && cert->pubKeySize > 0) {
+        ptr = (char*) XMALLOC(cert->pubKeySize, cert->heap,
+                              DYNAMIC_TYPE_PUBLIC_KEY);
+        if (ptr == NULL)
+            return MEMORY_E;
+        XMEMCPY(ptr, cert->publicKey, cert->pubKeySize);
+        cert->publicKey = (byte *)ptr;
+        cert->pubKeyStored = 1;
+    }
+
+    return ret;
+}
+
+/* from SSL proper, for locking can't do find here anymore */
+#ifdef __cplusplus
+    extern "C" {
+#endif
+    Signer* GetCA(void* signers, byte* hash);
+    #ifndef NO_SKID
+        Signer* GetCAByName(void* signers, byte* hash);
+    #endif
+#ifdef __cplusplus
+    }
+#endif
+
+#if defined(WOLFCRYPT_ONLY) || defined(NO_CERTS)
+
+/* dummy functions, not using wolfSSL so don't need actual ones */
+Signer* GetCA(void* signers, byte* hash)
+{
+    (void)hash;
+
+    return (Signer*)signers;
+}
+
+#ifndef NO_SKID
+Signer* GetCAByName(void* signers, byte* hash)
+{
+    (void)hash;
+
+    return (Signer*)signers;
+}
+#endif /* NO_SKID */
+
+#endif /* WOLFCRYPT_ONLY || NO_CERTS */
+
+#if defined(WOLFSSL_NO_TRUSTED_CERTS_VERIFY) && !defined(NO_SKID)
+static Signer* GetCABySubjectAndPubKey(DecodedCert* cert, void* cm)
+{
+    Signer* ca = NULL;
+    if (cert->extSubjKeyIdSet)
+        ca = GetCA(cm, cert->extSubjKeyId);
+    if (ca == NULL)
+        ca = GetCAByName(cm, cert->subjectHash);
+    if (ca) {
+        if ((ca->pubKeySize == cert->pubKeySize) &&
+               (XMEMCMP(ca->publicKey, cert->publicKey, ca->pubKeySize) == 0)) {
+            return ca;
+        }
+    }
+    return NULL;
+}
+#endif
+
+#if defined(WOLFSSL_SMALL_CERT_VERIFY) || defined(OPENSSL_EXTRA)
+/* Only quick step through the certificate to find fields that are then used
+ * in certificate signature verification.
+ * Must use the signature OID from the signed part of the certificate.
+ *
+ * This is only for minimizing dynamic memory usage during TLS certificate
+ * chain processing.
+ * Doesn't support:
+ *   OCSP Only: alt lookup using subject and pub key w/o sig check
+ */
+static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap,
+        void* cm, const byte* pubKey, word32 pubKeySz, int pubKeyOID)
+{
+#ifndef WOLFSSL_SMALL_STACK
+    SignatureCtx  sigCtx[1];
+#else
+    SignatureCtx* sigCtx;
+#endif
+    byte          hash[KEYID_SIZE];
+    Signer*       ca = NULL;
+    word32        idx = 0;
+    int           len;
+    word32        tbsCertIdx = 0;
+    word32        sigIndex   = 0;
+    word32        signatureOID = 0;
+    word32        oid = 0;
+    word32        issuerIdx = 0;
+    word32        issuerSz  = 0;
+#ifndef NO_SKID
+    int           extLen = 0;
+    word32        extIdx = 0;
+    word32        extEndIdx = 0;
+    int           extAuthKeyIdSet = 0;
+#endif
+    int           ret = 0;
+    word32        localIdx;
+    byte          tag;
+
+
+    if (cert == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    sigCtx = (SignatureCtx*)XMALLOC(sizeof(*sigCtx), heap, DYNAMIC_TYPE_SIGNATURE);
+    if (sigCtx == NULL)
+        return MEMORY_E;
+#endif
+    InitSignatureCtx(sigCtx, heap, INVALID_DEVID);
+
+    /* Certificate SEQUENCE */
+    if (GetSequence(cert, &idx, &len, certSz) < 0)
+        ret = ASN_PARSE_E;
+    if (ret == 0) {
+        tbsCertIdx = idx;
+
+        /* TBSCertificate SEQUENCE */
+        if (GetSequence(cert, &idx, &len, certSz) < 0)
+            ret = ASN_PARSE_E;
+    }
+    if (ret == 0) {
+        sigIndex = len + idx;
+
+        if ((idx + 1) > certSz)
+            ret = BUFFER_E;
+    }
+    if (ret == 0) {
+        /* version - optional */
+        localIdx = idx;
+        if (GetASNTag(cert, &localIdx, &tag, certSz) == 0) {
+            if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) {
+                idx++;
+                if (GetLength(cert, &idx, &len, certSz) < 0)
+                    ret = ASN_PARSE_E;
+                idx += len;
+            }
+        }
+    }
+
+    if (ret == 0) {
+        /* serialNumber */
+        if (GetASNHeader(cert, ASN_INTEGER, &idx, &len, certSz) < 0)
+            ret = ASN_PARSE_E;
+    }
+    if (ret == 0) {
+        idx += len;
+
+        /* signature */
+        if (GetAlgoId(cert, &idx, &signatureOID, oidSigType, certSz) < 0)
+            ret = ASN_PARSE_E;
+    }
+
+    if (ret == 0) {
+        issuerIdx = idx;
+        /* issuer */
+        if (GetSequence(cert, &idx, &len, certSz) < 0)
+            ret = ASN_PARSE_E;
+    }
+    if (ret == 0) {
+        issuerSz = len + idx - issuerIdx;
+    }
+#ifndef NO_SKID
+    if (ret == 0) {
+        idx += len;
+
+        /* validity */
+        if (GetSequence(cert, &idx, &len, certSz) < 0)
+            ret = ASN_PARSE_E;
+    }
+    if (ret == 0) {
+        idx += len;
+
+        /* subject */
+        if (GetSequence(cert, &idx, &len, certSz) < 0)
+            ret = ASN_PARSE_E;
+    }
+    if (ret == 0) {
+        idx += len;
+
+        /* subjectPublicKeyInfo */
+        if (GetSequence(cert, &idx, &len, certSz) < 0)
+            ret = ASN_PARSE_E;
+    }
+    if (ret == 0) {
+        idx += len;
+
+        if ((idx + 1) > certSz)
+            ret = BUFFER_E;
+    }
+    if (ret == 0) {
+        /* issuerUniqueID - optional */
+        localIdx = idx;
+        if (GetASNTag(cert, &localIdx, &tag, certSz) == 0) {
+            if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) {
+                idx++;
+                if (GetLength(cert, &idx, &len, certSz) < 0)
+                    ret = ASN_PARSE_E;
+                idx += len;
+            }
+        }
+    }
+    if (ret == 0) {
+        if ((idx + 1) > certSz)
+            ret = BUFFER_E;
+    }
+    if (ret == 0) {
+        /* subjectUniqueID - optional */
+        localIdx = idx;
+        if (GetASNTag(cert, &localIdx, &tag, certSz) == 0) {
+            if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2)) {
+                idx++;
+                if (GetLength(cert, &idx, &len, certSz) < 0)
+                    ret = ASN_PARSE_E;
+                idx += len;
+            }
+        }
+    }
+
+    if (ret == 0) {
+        if ((idx + 1) > certSz)
+            ret = BUFFER_E;
+    }
+    /* extensions - optional */
+    localIdx = idx;
+    if (ret == 0 && GetASNTag(cert, &localIdx, &tag, certSz) == 0 &&
+            tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 3)) {
+        idx++;
+        if (GetLength(cert, &idx, &extLen, certSz) < 0)
+            ret = ASN_PARSE_E;
+        if (ret == 0) {
+            if (GetSequence(cert, &idx, &extLen, certSz) < 0)
+                ret = ASN_PARSE_E;
+        }
+        if (ret == 0) {
+            extEndIdx = idx + extLen;
+
+            /* Check each extension for the ones we want. */
+            while (ret == 0 && idx < extEndIdx) {
+                if (GetSequence(cert, &idx, &len, certSz) < 0)
+                    ret = ASN_PARSE_E;
+                if (ret == 0) {
+                    extIdx = idx;
+                    if (GetObjectId(cert, &extIdx, &oid, oidCertExtType,
+                                                                  certSz) < 0) {
+                        ret = ASN_PARSE_E;
+                    }
+
+                    if (ret == 0) {
+                        if ((extIdx + 1) > certSz)
+                            ret = BUFFER_E;
+                    }
+                }
+
+                if (ret == 0) {
+                    localIdx = extIdx;
+                    if (GetASNTag(cert, &localIdx, &tag, certSz) == 0 &&
+                            tag == ASN_BOOLEAN) {
+                        if (GetBoolean(cert, &extIdx, certSz) < 0)
+                            ret = ASN_PARSE_E;
+                    }
+                }
+                if (ret == 0) {
+                    if (GetOctetString(cert, &extIdx, &extLen, certSz) < 0)
+                        ret = ASN_PARSE_E;
+                }
+
+                if (ret == 0) {
+                    switch (oid) {
+                    case AUTH_KEY_OID:
+                        if (GetSequence(cert, &extIdx, &extLen, certSz) < 0)
+                            ret = ASN_PARSE_E;
+
+                        if (ret == 0 && (extIdx + 1) >= certSz)
+                            ret = BUFFER_E;
+
+                        if (ret == 0 &&
+                                GetASNTag(cert, &extIdx, &tag, certSz) == 0 &&
+                                tag == (ASN_CONTEXT_SPECIFIC | 0)) {
+                            if (GetLength(cert, &extIdx, &extLen, certSz) <= 0)
+                                ret = ASN_PARSE_E;
+                            if (ret == 0) {
+                                extAuthKeyIdSet = 1;
+                                if (extLen == KEYID_SIZE)
+                                    XMEMCPY(hash, cert + extIdx, extLen);
+                                else {
+                                    ret = CalcHashId(cert + extIdx, extLen,
+                                                                          hash);
+                                }
+                            }
+                        }
+                        break;
+
+                    default:
+                        break;
+                    }
+                }
+                idx += len;
+            }
+        }
+    }
+
+    if (ret == 0 && pubKey == NULL) {
+        if (extAuthKeyIdSet)
+            ca = GetCA(cm, hash);
+        if (ca == NULL) {
+            ret = CalcHashId(cert + issuerIdx, issuerSz, hash);
+            if (ret == 0)
+                ca = GetCAByName(cm, hash);
+        }
+    }
+#else
+    if (ret == 0 && pubKey == NULL) {
+        ret = CalcHashId(cert + issuerIdx, issuerSz, hash);
+        if (ret == 0)
+            ca = GetCA(cm, hash);
+    }
+#endif /* !NO_SKID */
+    if (ca == NULL && pubKey == NULL)
+        ret = ASN_NO_SIGNER_E;
+
+    if (ret == 0) {
+        idx = sigIndex;
+        /* signatureAlgorithm */
+        if (GetAlgoId(cert, &idx, &oid, oidSigType, certSz) < 0)
+            ret = ASN_PARSE_E;
+    }
+    if (ret == 0) {
+        if (oid != signatureOID)
+            ret = ASN_SIG_OID_E;
+    }
+    if (ret == 0) {
+        /* signatureValue */
+        if (CheckBitString(cert, &idx, &len, certSz, 1, NULL) < 0)
+            ret = ASN_PARSE_E;
+    }
+
+    if (ret == 0) {
+        if (pubKey != NULL) {
+            ret = ConfirmSignature(sigCtx, cert + tbsCertIdx,
+                               sigIndex - tbsCertIdx,
+                               pubKey, pubKeySz, pubKeyOID,
+                               cert + idx, len, signatureOID, NULL);
+        }
+        else {
+            ret = ConfirmSignature(sigCtx, cert + tbsCertIdx,
+                               sigIndex - tbsCertIdx,
+                               ca->publicKey, ca->pubKeySize, ca->keyOID,
+                               cert + idx, len, signatureOID, NULL);
+        }
+        if (ret != 0) {
+            WOLFSSL_MSG("Confirm signature failed");
+        }
+    }
+
+    FreeSignatureCtx(sigCtx);
+#ifdef WOLFSSL_SMALL_STACK
+    if (sigCtx != NULL)
+        XFREE(sigCtx, heap, DYNAMIC_TYPE_SIGNATURE);
+#endif
+    return ret;
+}
+
+#ifdef OPENSSL_EXTRA
+/* Call CheckCertSignature_ex using a public key buffer for verification
+ */
+int CheckCertSignaturePubKey(const byte* cert, word32 certSz, void* heap,
+        const byte* pubKey, word32 pubKeySz, int pubKeyOID)
+{
+    return CheckCertSignature_ex(cert, certSz, heap, NULL,
+            pubKey, pubKeySz, pubKeyOID);
+}
+#endif /* OPENSSL_EXTRA */
+#ifdef WOLFSSL_SMALL_CERT_VERIFY
+/* Call CheckCertSignature_ex using a certificate manager (cm)
+ */
+int CheckCertSignature(const byte* cert, word32 certSz, void* heap, void* cm)
+{
+    return CheckCertSignature_ex(cert, certSz, heap, cm, NULL, 0, 0);
+}
+#endif /* WOLFSSL_SMALL_CERT_VERIFY */
+#endif /* WOLFSSL_SMALL_CERT_VERIFY || OPENSSL_EXTRA */
+
+int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm)
+{
+    int    ret = 0;
+    int    checkPathLen = 0;
+    int    decrementMaxPathLen = 0;
+    word32 confirmOID;
+#if defined(WOLFSSL_RENESAS_TSIP)
+    int    idx = 0;
+#endif
+    byte*  tsip_encRsaKeyIdx;
+
+    if (cert == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (cert->sigCtx.state == SIG_STATE_BEGIN) {
+        cert->badDate = 0;
+        cert->criticalExt = 0;
+        if ((ret = DecodeToKey(cert, verify)) < 0) {
+            if (ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E)
+                cert->badDate = ret;
+            else
+                return ret;
+        }
+
+        WOLFSSL_MSG("Parsed Past Key");
+
+        if (cert->srcIdx < cert->sigIndex) {
+        #ifndef ALLOW_V1_EXTENSIONS
+            if (cert->version < 2) {
+                WOLFSSL_MSG("\tv1 and v2 certs not allowed extensions");
+                return ASN_VERSION_E;
+            }
+        #endif
+
+            /* save extensions */
+            cert->extensions    = &cert->source[cert->srcIdx];
+            cert->extensionsSz  = cert->sigIndex - cert->srcIdx;
+            cert->extensionsIdx = cert->srcIdx;   /* for potential later use */
+
+            if ((ret = DecodeCertExtensions(cert)) < 0) {
+                if (ret == ASN_CRIT_EXT_E)
+                    cert->criticalExt = ret;
+                else
+                    return ret;
+            }
+
+            /* advance past extensions */
+            cert->srcIdx = cert->sigIndex;
+        }
+
+        if ((ret = GetAlgoId(cert->source, &cert->srcIdx, &confirmOID,
+                             oidSigType, cert->maxIdx)) < 0)
+            return ret;
+
+        if ((ret = GetSignature(cert)) < 0)
+            return ret;
+
+        if (confirmOID != cert->signatureOID)
+            return ASN_SIG_OID_E;
+
+    #ifndef NO_SKID
+        if (cert->extSubjKeyIdSet == 0 && cert->publicKey != NULL &&
+                                                         cert->pubKeySize > 0) {
+            ret = CalcHashId(cert->publicKey, cert->pubKeySize,
+                                                            cert->extSubjKeyId);
+            if (ret != 0)
+                return ret;
+        }
+    #endif /* !NO_SKID */
+
+        if (!cert->selfSigned || (verify != NO_VERIFY && type != CA_TYPE &&
+                                                   type != TRUSTED_PEER_TYPE)) {
+            cert->ca = NULL;
+    #ifndef NO_SKID
+            if (cert->extAuthKeyIdSet) {
+                cert->ca = GetCA(cm, cert->extAuthKeyId);
+            }
+            if (cert->ca == NULL && cert->extSubjKeyIdSet
+                                 && verify != VERIFY_OCSP) {
+                cert->ca = GetCA(cm, cert->extSubjKeyId);
+            }
+            if (cert->ca != NULL && XMEMCMP(cert->issuerHash,
+                                  cert->ca->subjectNameHash, KEYID_SIZE) != 0) {
+                cert->ca = NULL;
+            }
+            if (cert->ca == NULL) {
+                cert->ca = GetCAByName(cm, cert->issuerHash);
+                /* If AKID is available then this CA doesn't have the public
+                 * key required */
+                if (cert->ca && cert->extAuthKeyIdSet) {
+                    WOLFSSL_MSG("CA SKID doesn't match AKID");
+                    cert->ca = NULL;
+                }
+            }
+
+            /* OCSP Only: alt lookup using subject and pub key w/o sig check */
+        #ifdef WOLFSSL_NO_TRUSTED_CERTS_VERIFY
+            if (cert->ca == NULL && verify == VERIFY_OCSP) {
+                cert->ca = GetCABySubjectAndPubKey(cert, cm);
+                if (cert->ca) {
+                    ret = 0; /* success */
+                    goto exit_pcr;
+                }
+            }
+        #endif /* WOLFSSL_NO_TRUSTED_CERTS_VERIFY */
+    #else
+            cert->ca = GetCA(cm, cert->issuerHash);
+    #endif /* !NO_SKID */
+        }
+
+        if (cert->selfSigned) {
+            cert->maxPathLen = WOLFSSL_MAX_PATH_LEN;
+        } else {
+            /* RFC 5280 Section 4.2.1.9:
+             *
+             * load/receive check
+             *
+             * 1) Is CA boolean set?
+             *      No  - SKIP CHECK
+             *      Yes - Check key usage
+             * 2) Is Key usage extension present?
+             *      No  - goto 3
+             *      Yes - check keyCertSign assertion
+             *     2.a) Is keyCertSign asserted?
+             *          No  - goto 4
+             *          Yes - goto 3
+             * 3) Is pathLen set?
+             *      No  - goto 4
+             *      Yes - check pathLen against maxPathLen.
+             *      3.a) Is pathLen less than maxPathLen?
+             *           No - goto 4
+             *           Yes - set maxPathLen to pathLen and EXIT
+             * 4) Is maxPathLen > 0?
+             *      Yes - Reduce by 1
+             *      No  - ERROR
+             */
+
+            if (cert->ca && cert->pathLengthSet) {
+                cert->maxPathLen = cert->pathLength;
+                if (cert->isCA) {
+                    WOLFSSL_MSG("\tCA boolean set");
+                    if (cert->extKeyUsageSet) {
+                         WOLFSSL_MSG("\tExtension Key Usage Set");
+                         if ((cert->extKeyUsage & KEYUSE_KEY_CERT_SIGN) != 0) {
+                            checkPathLen = 1;
+                         } else {
+                            decrementMaxPathLen = 1;
+                         }
+                    } else {
+                        checkPathLen = 1;
+                    } /* !cert->ca check */
+                } /* cert is not a CA (assuming entity cert) */
+
+                if (checkPathLen && cert->pathLengthSet) {
+                    if (cert->pathLength < cert->ca->maxPathLen) {
+                        WOLFSSL_MSG("\tmaxPathLen status: set to pathLength");
+                        cert->maxPathLen = cert->pathLength;
+                    } else {
+                        decrementMaxPathLen = 1;
+                    }
+                }
+
+                if (decrementMaxPathLen && cert->ca->maxPathLen > 0) {
+                    WOLFSSL_MSG("\tmaxPathLen status: reduce by 1");
+                    cert->maxPathLen = cert->ca->maxPathLen - 1;
+                    if (verify != NO_VERIFY && type != CA_TYPE &&
+                                                    type != TRUSTED_PEER_TYPE) {
+                        WOLFSSL_MSG("\tmaxPathLen status: OK");
+                    }
+                } else if (decrementMaxPathLen && cert->ca->maxPathLen == 0) {
+                    cert->maxPathLen = 0;
+                    if (verify != NO_VERIFY && type != CA_TYPE &&
+                                                    type != TRUSTED_PEER_TYPE) {
+                        WOLFSSL_MSG("\tNon-entity cert, maxPathLen is 0");
+                        WOLFSSL_MSG("\tmaxPathLen status: ERROR");
+                        return ASN_PATHLEN_INV_E;
+                    }
+                }
+            } else if (cert->ca && cert->isCA) {
+                /* case where cert->pathLength extension is not set */
+                if (cert->ca->maxPathLen > 0) {
+                    cert->maxPathLen = cert->ca->maxPathLen - 1;
+                } else {
+                    cert->maxPathLen = 0;
+                    if (verify != NO_VERIFY && type != CA_TYPE &&
+                                                    type != TRUSTED_PEER_TYPE) {
+                        WOLFSSL_MSG("\tNon-entity cert, maxPathLen is 0");
+                        WOLFSSL_MSG("\tmaxPathLen status: ERROR");
+                        return ASN_PATHLEN_INV_E;
+                    }
+                }
+            }
+            #ifdef HAVE_OCSP
+            if (verify != NO_VERIFY && type != CA_TYPE &&
+                                                    type != TRUSTED_PEER_TYPE) {
+                if (cert->ca) {
+                    /* Need the CA's public key hash for OCSP */
+                    XMEMCPY(cert->issuerKeyHash, cert->ca->subjectKeyHash,
+                                                                    KEYID_SIZE);
+                }
+
+            }
+            #endif /* HAVE_OCSP */
+        }
+    }
+#if defined(WOLFSSL_RENESAS_TSIP)
+    /* prepare for TSIP TLS cert verification API use */
+    if (cert->keyOID == RSAk) {
+        /* to call TSIP API, it needs keys position info in bytes */
+        if ((ret = RsaPublicKeyDecodeRawIndex(cert->publicKey, (word32*)&idx,
+                                   cert->pubKeySize,
+                                   &cert->sigCtx.pubkey_n_start,
+                                   &cert->sigCtx.pubkey_n_len,
+                                   &cert->sigCtx.pubkey_e_start,
+                                   &cert->sigCtx.pubkey_e_len)) != 0) {
+            WOLFSSL_MSG("Decoding index from cert failed.");
+            return ret;
+        }
+        cert->sigCtx.certBegin = cert->certBegin;
+    }
+    /* check if we can use TSIP for cert verification */
+    /* if the ca is verified as tsip root ca.         */
+    /* TSIP can only handle 2048 bits(256 byte) key.  */
+    if (cert->ca && tsip_checkCA(cert->ca->cm_idx) != 0 &&
+        cert->sigCtx.pubkey_n_len == 256) {
+
+        /* assign memory to encrypted tsip Rsa key index */
+        if (!cert->tsip_encRsaKeyIdx)
+            cert->tsip_encRsaKeyIdx =
+                            (byte*)XMALLOC(TSIP_TLS_ENCPUBKEY_SZ_BY_CERTVRFY,
+                             cert->heap, DYNAMIC_TYPE_RSA);
+        if (cert->tsip_encRsaKeyIdx == NULL)
+                return MEMORY_E;
+    } else {
+        if (cert->ca) {
+            /* TSIP isn't usable */
+            if (tsip_checkCA(cert->ca->cm_idx) == 0)
+                WOLFSSL_MSG("TSIP isn't usable because the ca isn't verified "
+                            "by TSIP.");
+            else if (cert->sigCtx.pubkey_n_len != 256)
+                WOLFSSL_MSG("TSIP isn't usable because the ca isn't signed by "
+                            "RSA 2048.");
+            else
+                WOLFSSL_MSG("TSIP isn't usable");
+        }
+        cert->tsip_encRsaKeyIdx = NULL;
+    }
+
+    tsip_encRsaKeyIdx = cert->tsip_encRsaKeyIdx;
+#else
+    tsip_encRsaKeyIdx = NULL;
+#endif
+
+    if (verify != NO_VERIFY && type != CA_TYPE && type != TRUSTED_PEER_TYPE) {
+        if (cert->ca) {
+            if (verify == VERIFY || verify == VERIFY_OCSP ||
+                                                 verify == VERIFY_SKIP_DATE) {
+                /* try to confirm/verify signature */
+                if ((ret = ConfirmSignature(&cert->sigCtx,
+                        cert->source + cert->certBegin,
+                        cert->sigIndex - cert->certBegin,
+                        cert->ca->publicKey, cert->ca->pubKeySize,
+                        cert->ca->keyOID, cert->signature,
+                        cert->sigLength, cert->signatureOID,
+                        tsip_encRsaKeyIdx)) != 0) {
+                    if (ret != 0 && ret != WC_PENDING_E) {
+                        WOLFSSL_MSG("Confirm signature failed");
+                    }
+                    return ret;
+                }
+            }
+        #ifndef IGNORE_NAME_CONSTRAINTS
+            if (verify == VERIFY || verify == VERIFY_OCSP ||
+                        verify == VERIFY_NAME || verify == VERIFY_SKIP_DATE) {
+                /* check that this cert's name is permitted by the signer's
+                 * name constraints */
+                if (!ConfirmNameConstraints(cert->ca, cert)) {
+                    WOLFSSL_MSG("Confirm name constraint failed");
+                    return ASN_NAME_INVALID_E;
+                }
+            }
+        #endif /* IGNORE_NAME_CONSTRAINTS */
+        }
+        else {
+            /* no signer */
+            WOLFSSL_MSG("No CA signer to verify with");
+            return ASN_NO_SIGNER_E;
+        }
+    }
+
+#if defined(WOLFSSL_NO_TRUSTED_CERTS_VERIFY) && !defined(NO_SKID)
+exit_pcr:
+#endif
+
+    if (cert->badDate != 0) {
+        if (verify != VERIFY_SKIP_DATE) {
+            return cert->badDate;
+        }
+        WOLFSSL_MSG("Date error: Verify option is skipping");
+    }
+
+    if (cert->criticalExt != 0)
+        return cert->criticalExt;
+
+    return ret;
+}
+
+/* Create and init an new signer */
+Signer* MakeSigner(void* heap)
+{
+    Signer* signer = (Signer*) XMALLOC(sizeof(Signer), heap,
+                                       DYNAMIC_TYPE_SIGNER);
+    if (signer) {
+        XMEMSET(signer, 0, sizeof(Signer));
+    }
+    (void)heap;
+
+    return signer;
+}
+
+
+/* Free an individual signer */
+void FreeSigner(Signer* signer, void* heap)
+{
+    XFREE(signer->name, heap, DYNAMIC_TYPE_SUBJECT_CN);
+    XFREE((void*)signer->publicKey, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+#ifndef IGNORE_NAME_CONSTRAINTS
+    if (signer->permittedNames)
+        FreeNameSubtrees(signer->permittedNames, heap);
+    if (signer->excludedNames)
+        FreeNameSubtrees(signer->excludedNames, heap);
+#endif
+#ifdef WOLFSSL_SIGNER_DER_CERT
+    FreeDer(&signer->derCert);
+#endif
+    XFREE(signer, heap, DYNAMIC_TYPE_SIGNER);
+
+    (void)heap;
+}
+
+
+/* Free the whole singer table with number of rows */
+void FreeSignerTable(Signer** table, int rows, void* heap)
+{
+    int i;
+
+    for (i = 0; i < rows; i++) {
+        Signer* signer = table[i];
+        while (signer) {
+            Signer* next = signer->next;
+            FreeSigner(signer, heap);
+            signer = next;
+        }
+        table[i] = NULL;
+    }
+}
+
+#ifdef WOLFSSL_TRUST_PEER_CERT
+/* Free an individual trusted peer cert */
+void FreeTrustedPeer(TrustedPeerCert* tp, void* heap)
+{
+    if (tp == NULL) {
+        return;
+    }
+
+    if (tp->name) {
+        XFREE(tp->name, heap, DYNAMIC_TYPE_SUBJECT_CN);
+    }
+
+    if (tp->sig) {
+        XFREE(tp->sig, heap, DYNAMIC_TYPE_SIGNATURE);
+    }
+#ifndef IGNORE_NAME_CONSTRAINTS
+    if (tp->permittedNames)
+        FreeNameSubtrees(tp->permittedNames, heap);
+    if (tp->excludedNames)
+        FreeNameSubtrees(tp->excludedNames, heap);
+#endif
+    XFREE(tp, heap, DYNAMIC_TYPE_CERT);
+
+    (void)heap;
+}
+
+/* Free the whole Trusted Peer linked list */
+void FreeTrustedPeerTable(TrustedPeerCert** table, int rows, void* heap)
+{
+    int i;
+
+    for (i = 0; i < rows; i++) {
+        TrustedPeerCert* tp = table[i];
+        while (tp) {
+            TrustedPeerCert* next = tp->next;
+            FreeTrustedPeer(tp, heap);
+            tp = next;
+        }
+        table[i] = NULL;
+    }
+}
+#endif /* WOLFSSL_TRUST_PEER_CERT */
+
+int SetMyVersion(word32 version, byte* output, int header)
+{
+    int i = 0;
+
+    if (output == NULL)
+        return BAD_FUNC_ARG;
+
+    if (header) {
+        output[i++] = ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED;
+        output[i++] = 3;
+    }
+    output[i++] = ASN_INTEGER;
+    output[i++] = 0x01;
+    output[i++] = (byte)version;
+
+    return i;
+}
+
+int SetSerialNumber(const byte* sn, word32 snSz, byte* output,
+    word32 outputSz, int maxSnSz)
+{
+    int i;
+    int snSzInt = (int)snSz;
+
+    if (sn == NULL || output == NULL || snSzInt < 0)
+        return BAD_FUNC_ARG;
+
+    /* remove leading zeros */
+    while (snSzInt > 0 && sn[0] == 0) {
+        snSzInt--;
+        sn++;
+    }
+    /* RFC 5280 - 4.1.2.2:
+     *   Serial numbers must be a positive value (and not zero) */
+    if (snSzInt == 0)
+        return BAD_FUNC_ARG;
+
+    if (sn[0] & 0x80)
+        maxSnSz--;
+    /* truncate if input is too long */
+    if (snSzInt > maxSnSz)
+        snSzInt = maxSnSz;
+
+    i = SetASNInt(snSzInt, sn[0], NULL);
+    /* truncate if input is too long */
+    if (snSzInt > (int)outputSz - i)
+        snSzInt = (int)outputSz - i;
+    /* sanity check number of bytes to copy */
+    if (snSzInt <= 0) {
+        return BUFFER_E;
+    }
+
+    /* write out ASN.1 Integer */
+    (void)SetASNInt(snSzInt, sn[0], output);
+    XMEMCPY(output + i, sn, snSzInt);
+
+    /* compute final length */
+    i += snSzInt;
+
+    return i;
+}
+
+#endif /* !NO_CERTS */
+
+int GetSerialNumber(const byte* input, word32* inOutIdx,
+    byte* serial, int* serialSz, word32 maxIdx)
+{
+    int result = 0;
+    int ret;
+
+    WOLFSSL_ENTER("GetSerialNumber");
+
+    if (serial == NULL || input == NULL || serialSz == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* First byte is ASN type */
+    if ((*inOutIdx+1) > maxIdx) {
+        WOLFSSL_MSG("Bad idx first");
+        return BUFFER_E;
+    }
+
+    ret = GetASNInt(input, inOutIdx, serialSz, maxIdx);
+    if (ret != 0)
+        return ret;
+
+    if (*serialSz > EXTERNAL_SERIAL_SIZE) {
+        WOLFSSL_MSG("Serial size bad");
+        return ASN_PARSE_E;
+    }
+
+    /* return serial */
+    XMEMCPY(serial, &input[*inOutIdx], *serialSz);
+    *inOutIdx += *serialSz;
+
+    return result;
+}
+
+#ifndef NO_CERTS
+
+int AllocDer(DerBuffer** pDer, word32 length, int type, void* heap)
+{
+    int ret = BAD_FUNC_ARG;
+    if (pDer) {
+        int dynType = 0;
+        DerBuffer* der;
+
+        /* Determine dynamic type */
+        switch (type) {
+            case CA_TYPE:   dynType = DYNAMIC_TYPE_CA;   break;
+            case CERT_TYPE: dynType = DYNAMIC_TYPE_CERT; break;
+            case CRL_TYPE:  dynType = DYNAMIC_TYPE_CRL;  break;
+            case DSA_TYPE:  dynType = DYNAMIC_TYPE_DSA;  break;
+            case ECC_TYPE:  dynType = DYNAMIC_TYPE_ECC;  break;
+            case RSA_TYPE:  dynType = DYNAMIC_TYPE_RSA;  break;
+            default:        dynType = DYNAMIC_TYPE_KEY;  break;
+        }
+
+        /* Setup new buffer */
+        *pDer = (DerBuffer*)XMALLOC(sizeof(DerBuffer) + length, heap, dynType);
+        if (*pDer == NULL) {
+            return MEMORY_E;
+        }
+        XMEMSET(*pDer, 0, sizeof(DerBuffer) + length);
+
+        der = *pDer;
+        der->type = type;
+        der->dynType = dynType; /* Cache this for FreeDer */
+        der->heap = heap;
+        der->buffer = (byte*)der + sizeof(DerBuffer);
+        der->length = length;
+        ret = 0; /* Success */
+    }
+    return ret;
+}
+
+void FreeDer(DerBuffer** pDer)
+{
+    if (pDer && *pDer)
+    {
+        DerBuffer* der = (DerBuffer*)*pDer;
+
+        /* ForceZero private keys */
+        if (der->type == PRIVATEKEY_TYPE) {
+            ForceZero(der->buffer, der->length);
+        }
+        der->buffer = NULL;
+        der->length = 0;
+        XFREE(der, der->heap, der->dynType);
+
+        *pDer = NULL;
+    }
+}
+
+int wc_AllocDer(DerBuffer** pDer, word32 length, int type, void* heap)
+{
+    return AllocDer(pDer, length, type, heap);
+}
+void wc_FreeDer(DerBuffer** pDer)
+{
+    FreeDer(pDer);
+}
+
+
+#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
+
+/* Max X509 header length indicates the max length + 2 ('\n', '\0') */
+#define MAX_X509_HEADER_SZ  (37 + 2)
+
+wcchar BEGIN_CERT           = "-----BEGIN CERTIFICATE-----";
+wcchar END_CERT             = "-----END CERTIFICATE-----";
+#ifdef WOLFSSL_CERT_REQ
+    wcchar BEGIN_CERT_REQ   = "-----BEGIN CERTIFICATE REQUEST-----";
+    wcchar END_CERT_REQ     = "-----END CERTIFICATE REQUEST-----";
+#endif
+#ifndef NO_DH
+    wcchar BEGIN_DH_PARAM   = "-----BEGIN DH PARAMETERS-----";
+    wcchar END_DH_PARAM     = "-----END DH PARAMETERS-----";
+#endif
+#ifndef NO_DSA
+    wcchar BEGIN_DSA_PARAM  = "-----BEGIN DSA PARAMETERS-----";
+    wcchar END_DSA_PARAM    = "-----END DSA PARAMETERS-----";
+#endif
+wcchar BEGIN_X509_CRL       = "-----BEGIN X509 CRL-----";
+wcchar END_X509_CRL         = "-----END X509 CRL-----";
+wcchar BEGIN_RSA_PRIV       = "-----BEGIN RSA PRIVATE KEY-----";
+wcchar END_RSA_PRIV         = "-----END RSA PRIVATE KEY-----";
+wcchar BEGIN_PRIV_KEY       = "-----BEGIN PRIVATE KEY-----";
+wcchar END_PRIV_KEY         = "-----END PRIVATE KEY-----";
+wcchar BEGIN_ENC_PRIV_KEY   = "-----BEGIN ENCRYPTED PRIVATE KEY-----";
+wcchar END_ENC_PRIV_KEY     = "-----END ENCRYPTED PRIVATE KEY-----";
+#ifdef HAVE_ECC
+    wcchar BEGIN_EC_PRIV    = "-----BEGIN EC PRIVATE KEY-----";
+    wcchar END_EC_PRIV      = "-----END EC PRIVATE KEY-----";
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \
+                                                                !defined(NO_DSA)
+    wcchar BEGIN_DSA_PRIV   = "-----BEGIN DSA PRIVATE KEY-----";
+    wcchar END_DSA_PRIV     = "-----END DSA PRIVATE KEY-----";
+#endif
+#ifdef OPENSSL_EXTRA
+    const char BEGIN_PRIV_KEY_PREFIX[] = "-----BEGIN";
+    const char PRIV_KEY_SUFFIX[] = "PRIVATE KEY-----";
+    const char END_PRIV_KEY_PREFIX[]   = "-----END";
+#endif
+wcchar BEGIN_PUB_KEY        = "-----BEGIN PUBLIC KEY-----";
+wcchar END_PUB_KEY          = "-----END PUBLIC KEY-----";
+#if defined(HAVE_ED25519) || defined(HAVE_ED448)
+    wcchar BEGIN_EDDSA_PRIV = "-----BEGIN EDDSA PRIVATE KEY-----";
+    wcchar END_EDDSA_PRIV   = "-----END EDDSA PRIVATE KEY-----";
+#endif
+#ifdef HAVE_CRL
+    const char *const BEGIN_CRL = "-----BEGIN X509 CRL-----";
+    wcchar END_CRL   = "-----END X509 CRL-----";
+#endif
+
+
+static WC_INLINE char* SkipEndOfLineChars(char* line, const char* endOfLine)
+{
+    /* eat end of line characters */
+    while (line < endOfLine &&
+              (line[0] == '\r' || line[0] == '\n')) {
+        line++;
+    }
+    return line;
+}
+
+int wc_PemGetHeaderFooter(int type, const char** header, const char** footer)
+{
+    int ret = BAD_FUNC_ARG;
+
+    switch (type) {
+        case CA_TYPE:       /* same as below */
+        case TRUSTED_PEER_TYPE:
+        case CERT_TYPE:
+            if (header) *header = BEGIN_CERT;
+            if (footer) *footer = END_CERT;
+            ret = 0;
+            break;
+
+        case CRL_TYPE:
+            if (header) *header = BEGIN_X509_CRL;
+            if (footer) *footer = END_X509_CRL;
+            ret = 0;
+            break;
+    #ifndef NO_DH
+        case DH_PARAM_TYPE:
+            if (header) *header = BEGIN_DH_PARAM;
+            if (footer) *footer = END_DH_PARAM;
+            ret = 0;
+            break;
+    #endif
+    #ifndef NO_DSA
+        case DSA_PARAM_TYPE:
+            if (header) *header = BEGIN_DSA_PARAM;
+            if (footer) *footer = END_DSA_PARAM;
+            ret = 0;
+            break;
+    #endif
+    #ifdef WOLFSSL_CERT_REQ
+        case CERTREQ_TYPE:
+            if (header) *header = BEGIN_CERT_REQ;
+            if (footer) *footer = END_CERT_REQ;
+            ret = 0;
+            break;
+    #endif
+    #ifndef NO_DSA
+        case DSA_TYPE:
+        case DSA_PRIVATEKEY_TYPE:
+            if (header) *header = BEGIN_DSA_PRIV;
+            if (footer) *footer = END_DSA_PRIV;
+            ret = 0;
+            break;
+    #endif
+    #ifdef HAVE_ECC
+        case ECC_TYPE:
+        case ECC_PRIVATEKEY_TYPE:
+            if (header) *header = BEGIN_EC_PRIV;
+            if (footer) *footer = END_EC_PRIV;
+            ret = 0;
+            break;
+    #endif
+        case RSA_TYPE:
+        case PRIVATEKEY_TYPE:
+            if (header) *header = BEGIN_RSA_PRIV;
+            if (footer) *footer = END_RSA_PRIV;
+            ret = 0;
+            break;
+    #ifdef HAVE_ED25519
+        case ED25519_TYPE:
+    #endif
+    #ifdef HAVE_ED448
+        case ED448_TYPE:
+    #endif
+    #if defined(HAVE_ED25519) || defined(HAVE_ED448)
+        case EDDSA_PRIVATEKEY_TYPE:
+            if (header) *header = BEGIN_EDDSA_PRIV;
+            if (footer) *footer = END_EDDSA_PRIV;
+            ret = 0;
+            break;
+    #endif
+        case PUBLICKEY_TYPE:
+        case ECC_PUBLICKEY_TYPE:
+            if (header) *header = BEGIN_PUB_KEY;
+            if (footer) *footer = END_PUB_KEY;
+            ret = 0;
+            break;
+    #if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
+        case DH_PRIVATEKEY_TYPE:
+    #endif
+        case PKCS8_PRIVATEKEY_TYPE:
+            if (header) *header = BEGIN_PRIV_KEY;
+            if (footer) *footer = END_PRIV_KEY;
+            ret = 0;
+            break;
+        case PKCS8_ENC_PRIVATEKEY_TYPE:
+            if (header) *header = BEGIN_ENC_PRIV_KEY;
+            if (footer) *footer = END_ENC_PRIV_KEY;
+            ret = 0;
+            break;
+        default:
+            break;
+    }
+    return ret;
+}
+
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+
+static wcchar kProcTypeHeader = "Proc-Type";
+static wcchar kDecInfoHeader = "DEK-Info";
+
+#ifdef WOLFSSL_PEM_TO_DER
+#ifndef NO_DES3
+    static wcchar kEncTypeDes = "DES-CBC";
+    static wcchar kEncTypeDes3 = "DES-EDE3-CBC";
+#endif
+#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_128)
+    static wcchar kEncTypeAesCbc128 = "AES-128-CBC";
+#endif
+#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_192)
+    static wcchar kEncTypeAesCbc192 = "AES-192-CBC";
+#endif
+#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_256)
+    static wcchar kEncTypeAesCbc256 = "AES-256-CBC";
+#endif
+
+int wc_EncryptedInfoGet(EncryptedInfo* info, const char* cipherInfo)
+{
+    int ret = 0;
+
+    if (info == NULL || cipherInfo == NULL)
+        return BAD_FUNC_ARG;
+
+    /* determine cipher information */
+#ifndef NO_DES3
+    if (XSTRNCMP(cipherInfo, kEncTypeDes, XSTRLEN(kEncTypeDes)) == 0) {
+        info->cipherType = WC_CIPHER_DES;
+        info->keySz = DES_KEY_SIZE;
+        if (info->ivSz == 0) info->ivSz  = DES_IV_SIZE;
+    }
+    else if (XSTRNCMP(cipherInfo, kEncTypeDes3, XSTRLEN(kEncTypeDes3)) == 0) {
+        info->cipherType = WC_CIPHER_DES3;
+        info->keySz = DES3_KEY_SIZE;
+        if (info->ivSz == 0) info->ivSz  = DES_IV_SIZE;
+    }
+    else
+#endif /* !NO_DES3 */
+#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_128)
+    if (XSTRNCMP(cipherInfo, kEncTypeAesCbc128, XSTRLEN(kEncTypeAesCbc128)) == 0) {
+        info->cipherType = WC_CIPHER_AES_CBC;
+        info->keySz = AES_128_KEY_SIZE;
+        if (info->ivSz == 0) info->ivSz  = AES_IV_SIZE;
+    }
+    else
+#endif
+#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_192)
+    if (XSTRNCMP(cipherInfo, kEncTypeAesCbc192, XSTRLEN(kEncTypeAesCbc192)) == 0) {
+        info->cipherType = WC_CIPHER_AES_CBC;
+        info->keySz = AES_192_KEY_SIZE;
+        if (info->ivSz == 0) info->ivSz  = AES_IV_SIZE;
+    }
+    else
+#endif
+#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_256)
+    if (XSTRNCMP(cipherInfo, kEncTypeAesCbc256, XSTRLEN(kEncTypeAesCbc256)) == 0) {
+        info->cipherType = WC_CIPHER_AES_CBC;
+        info->keySz = AES_256_KEY_SIZE;
+        if (info->ivSz == 0) info->ivSz  = AES_IV_SIZE;
+    }
+    else
+#endif
+    {
+        ret = NOT_COMPILED_IN;
+    }
+    return ret;
+}
+
+int wc_EncryptedInfoParse(EncryptedInfo* info, char** pBuffer, size_t bufSz)
+{
+    int err = 0;
+    char*  bufferStart;
+    char*  bufferEnd;
+    char*  line;
+    word32 lineSz;
+    char*  finish;
+    word32 finishSz;
+    char*  start = NULL;
+    word32 startSz;
+    char*  newline = NULL;
+
+    if (info == NULL || pBuffer == NULL || bufSz == 0)
+        return BAD_FUNC_ARG;
+
+    bufferStart = *pBuffer;
+    bufferEnd = bufferStart + bufSz;
+
+    /* find encrypted info marker */
+    line = XSTRNSTR(bufferStart, kProcTypeHeader,
+                    min((word32)bufSz, PEM_LINE_LEN));
+    if (line != NULL) {
+        if (line >= bufferEnd) {
+            return BUFFER_E;
+        }
+
+        lineSz = (word32)(bufferEnd - line);
+
+        /* find DEC-Info marker */
+        start = XSTRNSTR(line, kDecInfoHeader, min(lineSz, PEM_LINE_LEN));
+
+        if (start == NULL)
+            return BUFFER_E;
+
+        /* skip dec-info and ": " */
+        start += XSTRLEN(kDecInfoHeader);
+        if (start >= bufferEnd)
+            return BUFFER_E;
+
+        if (start[0] == ':') {
+            start++;
+            if (start >= bufferEnd)
+                return BUFFER_E;
+        }
+        if (start[0] == ' ')
+            start++;
+
+        startSz = (word32)(bufferEnd - start);
+        finish = XSTRNSTR(start, ",", min(startSz, PEM_LINE_LEN));
+
+        if ((start != NULL) && (finish != NULL) && (start < finish)) {
+            if (finish >= bufferEnd) {
+                return BUFFER_E;
+            }
+
+            finishSz = (word32)(bufferEnd - finish);
+            newline = XSTRNSTR(finish, "\r", min(finishSz, PEM_LINE_LEN));
+
+            /* get cipher name */
+            if (NAME_SZ < (finish - start)) /* buffer size of info->name */
+                return BUFFER_E;
+            if (XMEMCPY(info->name, start, finish - start) == NULL)
+                return BUFFER_E;
+            info->name[finish - start] = '\0'; /* null term */
+
+            /* populate info */
+            err = wc_EncryptedInfoGet(info, info->name);
+            if (err != 0)
+                return err;
+
+            /* get IV */
+            if (finishSz < info->ivSz + 1)
+                return BUFFER_E;
+
+            if (newline == NULL) {
+                newline = XSTRNSTR(finish, "\n", min(finishSz,
+                                                     PEM_LINE_LEN));
+            }
+            if ((newline != NULL) && (newline > finish)) {
+                finish++;
+                info->ivSz = (word32)(newline - finish);
+                if (info->ivSz > IV_SZ)
+                    return BUFFER_E;
+                if (XMEMCPY(info->iv, finish, info->ivSz) == NULL)
+                    return BUFFER_E;
+                info->set = 1;
+            }
+            else
+                return BUFFER_E;
+        }
+        else
+            return BUFFER_E;
+
+        /* eat end of line characters */
+        newline = SkipEndOfLineChars(newline, bufferEnd);
+
+        /* return new headerEnd */
+
+        *pBuffer = newline;
+    }
+
+    return err;
+}
+#endif /* WOLFSSL_PEM_TO_DER */
+
+#ifdef WOLFSSL_DER_TO_PEM
+static int wc_EncryptedInfoAppend(char* dest, int destSz, char* cipherInfo)
+{
+    if (cipherInfo != NULL) {
+        int cipherInfoStrLen = (int)XSTRLEN((char*)cipherInfo);
+
+        if (cipherInfoStrLen > HEADER_ENCRYPTED_KEY_SIZE - (9+14+10+3))
+            cipherInfoStrLen = HEADER_ENCRYPTED_KEY_SIZE - (9+14+10+3);
+
+        if (destSz - (int)XSTRLEN(dest) >= cipherInfoStrLen + (9+14+8+2+2+1)) {
+            /* strncat's src length needs to include the NULL */
+            XSTRNCAT(dest, kProcTypeHeader, 10);
+            XSTRNCAT(dest, ": 4,ENCRYPTED\n", 15);
+            XSTRNCAT(dest, kDecInfoHeader, 9);
+            XSTRNCAT(dest, ": ", 3);
+            XSTRNCAT(dest, cipherInfo, destSz - (int)XSTRLEN(dest) - 1);
+            XSTRNCAT(dest, "\n\n", 4);
+        }
+    }
+    return 0;
+}
+#endif /* WOLFSSL_DER_TO_PEM */
+#endif /* WOLFSSL_ENCRYPTED_KEYS */
+
+#ifdef WOLFSSL_DER_TO_PEM
+
+/* Used for compatibility API */
+int wc_DerToPem(const byte* der, word32 derSz,
+                byte* output, word32 outSz, int type)
+{
+    return wc_DerToPemEx(der, derSz, output, outSz, NULL, type);
+}
+
+/* convert der buffer to pem into output, can't do inplace, der and output
+   need to be different */
+int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, word32 outSz,
+             byte *cipher_info, int type)
+{
+    const char* headerStr = NULL;
+    const char* footerStr = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    char* header = NULL;
+    char* footer = NULL;
+#else
+    char header[MAX_X509_HEADER_SZ + HEADER_ENCRYPTED_KEY_SIZE];
+    char footer[MAX_X509_HEADER_SZ];
+#endif
+    int headerLen = MAX_X509_HEADER_SZ + HEADER_ENCRYPTED_KEY_SIZE;
+    int footerLen = MAX_X509_HEADER_SZ;
+    int i;
+    int err;
+    int outLen;   /* return length or error */
+
+    (void)cipher_info;
+
+    if (der == output)      /* no in place conversion */
+        return BAD_FUNC_ARG;
+
+    err = wc_PemGetHeaderFooter(type, &headerStr, &footerStr);
+    if (err != 0)
+        return err;
+
+#ifdef WOLFSSL_SMALL_STACK
+    header = (char*)XMALLOC(headerLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (header == NULL)
+        return MEMORY_E;
+
+    footer = (char*)XMALLOC(footerLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (footer == NULL) {
+        XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return MEMORY_E;
+    }
+#endif
+
+    /* build header and footer based on type */
+    XSTRNCPY(header, headerStr, headerLen - 1);
+    header[headerLen - 2] = 0;
+    XSTRNCPY(footer, footerStr, footerLen - 1);
+    footer[footerLen - 2] = 0;
+
+    /* add new line to end */
+    XSTRNCAT(header, "\n", 2);
+    XSTRNCAT(footer, "\n", 2);
+
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+    err = wc_EncryptedInfoAppend(header, headerLen, (char*)cipher_info);
+    if (err != 0) {
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+        return err;
+    }
+#endif
+
+    headerLen = (int)XSTRLEN(header);
+    footerLen = (int)XSTRLEN(footer);
+
+    /* if null output and 0 size passed in then return size needed */
+    if (!output && outSz == 0) {
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+        outLen = 0;
+        if ((err = Base64_Encode(der, derSz, NULL, (word32*)&outLen))
+                != LENGTH_ONLY_E) {
+            return err;
+        }
+        return headerLen + footerLen + outLen;
+    }
+
+    if (!der || !output) {
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+        return BAD_FUNC_ARG;
+    }
+
+    /* don't even try if outSz too short */
+    if (outSz < headerLen + footerLen + derSz) {
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+        return BAD_FUNC_ARG;
+    }
+
+    /* header */
+    XMEMCPY(output, header, headerLen);
+    i = headerLen;
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    /* body */
+    outLen = outSz - (headerLen + footerLen);  /* input to Base64_Encode */
+    if ( (err = Base64_Encode(der, derSz, output + i, (word32*)&outLen)) < 0) {
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+        return err;
+    }
+    i += outLen;
+
+    /* footer */
+    if ( (i + footerLen) > (int)outSz) {
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+        return BAD_FUNC_ARG;
+    }
+    XMEMCPY(output + i, footer, footerLen);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return outLen + headerLen + footerLen;
+}
+
+#endif /* WOLFSSL_DER_TO_PEM */
+
+#ifdef WOLFSSL_PEM_TO_DER
+
+/* Remove PEM header/footer, convert to ASN1, store any encrypted data
+   info->consumed tracks of PEM bytes consumed in case multiple parts */
+int PemToDer(const unsigned char* buff, long longSz, int type,
+              DerBuffer** pDer, void* heap, EncryptedInfo* info, int* keyFormat)
+{
+    const char* header      = NULL;
+    const char* footer      = NULL;
+    char*       headerEnd;
+    char*       footerEnd;
+    char*       consumedEnd;
+    char*       bufferEnd   = (char*)(buff + longSz);
+    long        neededSz;
+    int         ret         = 0;
+    int         sz          = (int)longSz;
+    int         encrypted_key = 0;
+    DerBuffer*  der;
+#if defined(HAVE_PKCS8) || defined(WOLFSSL_ENCRYPTED_KEYS)
+    word32      algId = 0;
+    #if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_DES3) && !defined(NO_WOLFSSL_SKIP_TRAILING_PAD)
+        int     padVal = 0;
+    #endif
+#endif
+#ifdef OPENSSL_EXTRA
+    char        beginBuf[PEM_LINE_LEN + 1]; /* add 1 for null terminator */
+    char        endBuf[PEM_LINE_LEN + 1];   /* add 1 for null terminator */
+#endif
+
+    WOLFSSL_ENTER("PemToDer");
+
+    /* get PEM header and footer based on type */
+    ret = wc_PemGetHeaderFooter(type, &header, &footer);
+    if (ret != 0)
+        return ret;
+
+    /* map header if not found for type */
+    for (;;) {
+        headerEnd = XSTRNSTR((char*)buff, header, sz);
+
+        if (headerEnd) {
+            break;
+        } else
+        if (type == PRIVATEKEY_TYPE) {
+            if (header == BEGIN_RSA_PRIV) {
+                header =  BEGIN_PRIV_KEY;       footer = END_PRIV_KEY;
+            } else
+            if (header == BEGIN_PRIV_KEY) {
+                header =  BEGIN_ENC_PRIV_KEY;   footer = END_ENC_PRIV_KEY;
+            } else
+    #ifdef HAVE_ECC
+            if (header == BEGIN_ENC_PRIV_KEY) {
+                header =  BEGIN_EC_PRIV;        footer = END_EC_PRIV;
+            } else
+            if (header == BEGIN_EC_PRIV) {
+                header =  BEGIN_DSA_PRIV;       footer = END_DSA_PRIV;
+            } else
+    #endif
+    #if defined(HAVE_ED25519) || defined(HAVE_ED448)
+        #ifdef HAVE_ECC
+            if (header == BEGIN_DSA_PRIV)
+        #else
+            if (header == BEGIN_ENC_PRIV_KEY)
+        #endif
+            {
+                header =  BEGIN_EDDSA_PRIV;     footer = END_EDDSA_PRIV;
+            } else
+    #endif
+            {
+                break;
+            }
+        } else
+#ifdef HAVE_CRL
+        if ((type == CRL_TYPE) && (header != BEGIN_CRL)) {
+            header =  BEGIN_CRL;                footer = END_CRL;
+        } else
+#endif
+        {
+            break;
+        }
+    }
+
+    if (!headerEnd) {
+#ifdef OPENSSL_EXTRA
+        char* beginEnd;
+        int endLen;
+        /* see if there is a -----BEGIN * PRIVATE KEY----- header */
+        headerEnd = XSTRNSTR((char*)buff, PRIV_KEY_SUFFIX, sz);
+        if (headerEnd) {
+            beginEnd = headerEnd + XSTR_SIZEOF(PRIV_KEY_SUFFIX);
+            /* back up to BEGIN_PRIV_KEY_PREFIX */
+            headerEnd -= XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX);
+            while (headerEnd > (char*)buff &&
+                    XSTRNCMP(headerEnd, BEGIN_PRIV_KEY_PREFIX,
+                            XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX)) != 0) {
+                headerEnd--;
+            }
+            if (headerEnd <= (char*)buff ||
+                    XSTRNCMP(headerEnd, BEGIN_PRIV_KEY_PREFIX,
+                    XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX)) != 0 ||
+                    beginEnd - headerEnd > PEM_LINE_LEN) {
+                WOLFSSL_MSG("Couldn't find PEM header");
+                return ASN_NO_PEM_HEADER;
+            }
+            /* headerEnd now points to beginning of header */
+            XMEMCPY(beginBuf, headerEnd, beginEnd - headerEnd);
+            beginBuf[beginEnd - headerEnd] = '\0';
+            /* look for matching footer */
+            footer = XSTRNSTR(beginEnd,
+                            beginBuf + XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX),
+                            (unsigned int)((char*)buff + sz - beginEnd));
+            if (!footer) {
+                WOLFSSL_MSG("Couldn't find PEM footer");
+                return ASN_NO_PEM_HEADER;
+            }
+            footer -= XSTR_SIZEOF(END_PRIV_KEY_PREFIX);
+            endLen = (unsigned int)(beginEnd - headerEnd -
+                        (XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX) -
+                                XSTR_SIZEOF(END_PRIV_KEY_PREFIX)));
+            XMEMCPY(endBuf, footer, endLen);
+            endBuf[endLen] = '\0';
+
+            header = beginBuf;
+            footer = endBuf;
+            headerEnd = beginEnd;
+        } else {
+            WOLFSSL_MSG("Couldn't find PEM header");
+            return ASN_NO_PEM_HEADER;
+        }
+#else
+        WOLFSSL_MSG("Couldn't find PEM header");
+        return ASN_NO_PEM_HEADER;
+#endif
+    } else {
+        headerEnd += XSTRLEN(header);
+    }
+
+    /* eat end of line characters */
+    headerEnd = SkipEndOfLineChars(headerEnd, bufferEnd);
+
+    if (type == PRIVATEKEY_TYPE) {
+        /* keyFormat is Key_Sum enum */
+        if (keyFormat) {
+        #ifdef HAVE_ECC
+            if (header == BEGIN_EC_PRIV)
+                *keyFormat = ECDSAk;
+        #endif
+        #if !defined(NO_DSA)
+            if (header == BEGIN_DSA_PRIV)
+                *keyFormat = DSAk;
+        #endif
+        }
+    }
+
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+    if (info) {
+        ret = wc_EncryptedInfoParse(info, &headerEnd, bufferEnd - headerEnd);
+        if (ret < 0)
+            return ret;
+        if (info->set)
+            encrypted_key = 1;
+    }
+#endif /* WOLFSSL_ENCRYPTED_KEYS */
+
+    /* find footer */
+    footerEnd = XSTRNSTR(headerEnd, footer, (unsigned int)((char*)buff + sz - headerEnd));
+    if (!footerEnd) {
+        if (info)
+            info->consumed = longSz; /* No more certs if no footer */
+        return BUFFER_E;
+    }
+
+    consumedEnd = footerEnd + XSTRLEN(footer);
+
+    if (consumedEnd < bufferEnd) { /* handle no end of line on last line */
+        /* eat end of line characters */
+        consumedEnd = SkipEndOfLineChars(consumedEnd, bufferEnd);
+        /* skip possible null term */
+        if (consumedEnd < bufferEnd && consumedEnd[0] == '\0')
+            consumedEnd++;
+    }
+
+    if (info)
+        info->consumed = (long)(consumedEnd - (char*)buff);
+
+    /* set up der buffer */
+    neededSz = (long)(footerEnd - headerEnd);
+    if (neededSz > sz || neededSz <= 0)
+        return BUFFER_E;
+
+    ret = AllocDer(pDer, (word32)neededSz, type, heap);
+    if (ret < 0) {
+        return ret;
+    }
+    der = *pDer;
+
+    if (Base64_Decode((byte*)headerEnd, (word32)neededSz,
+                      der->buffer, &der->length) < 0)
+        return BUFFER_E;
+
+    if ((header == BEGIN_PRIV_KEY
+#ifdef OPENSSL_EXTRA
+         || header == beginBuf
+#endif
+#ifdef HAVE_ECC
+         || header == BEGIN_EC_PRIV
+#endif
+        ) && !encrypted_key)
+    {
+    #ifdef HAVE_PKCS8
+        /* pkcs8 key, convert and adjust length */
+        if ((ret = ToTraditional_ex(der->buffer, der->length, &algId)) > 0) {
+            der->length = ret;
+            if (keyFormat) {
+                *keyFormat = algId;
+            }
+        }
+        else {
+            /* ignore failure here and assume key is not pkcs8 wrapped */
+        }
+    #endif
+
+        return 0;
+    }
+
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+    if (encrypted_key || header == BEGIN_ENC_PRIV_KEY) {
+        int   passwordSz = NAME_SZ;
+    #ifdef WOLFSSL_SMALL_STACK
+        char* password = NULL;
+    #else
+        char  password[NAME_SZ];
+    #endif
+
+        if (!info || !info->passwd_cb) {
+            WOLFSSL_MSG("No password callback set");
+            return NO_PASSWORD;
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        password = (char*)XMALLOC(passwordSz, heap, DYNAMIC_TYPE_STRING);
+        if (password == NULL)
+            return MEMORY_E;
+    #endif
+
+        /* get password */
+        ret = info->passwd_cb(password, passwordSz, PEM_PASS_READ,
+            info->passwd_userdata);
+        if (ret >= 0) {
+            passwordSz = ret;
+
+            /* convert and adjust length */
+            if (header == BEGIN_ENC_PRIV_KEY) {
+            #ifndef NO_PWDBASED
+                ret = ToTraditionalEnc(der->buffer, der->length,
+                                       password, passwordSz, &algId);
+
+                if (ret >= 0) {
+                    der->length = ret;
+                    if (keyFormat) {
+                        *keyFormat = algId;
+                    }
+                    ret = 0;
+                }
+            #else
+                ret = NOT_COMPILED_IN;
+            #endif
+            }
+            /* decrypt the key */
+            else {
+                if (passwordSz == 0) {
+                    /* The key is encrypted but does not have a password */
+                    WOLFSSL_MSG("No password for encrypted key");
+                    ret = NO_PASSWORD;
+                }
+                else {
+                    ret = wc_BufferKeyDecrypt(info, der->buffer, der->length,
+                        (byte*)password, passwordSz, WC_MD5);
+
+#ifndef NO_WOLFSSL_SKIP_TRAILING_PAD
+                #ifndef NO_DES3
+                    if (info->cipherType == WC_CIPHER_DES3) {
+                        padVal = der->buffer[der->length-1];
+                        if (padVal <= DES_BLOCK_SIZE) {
+                            der->length -= padVal;
+                        }
+                    }
+                #endif /* !NO_DES3 */
+#endif /* !NO_WOLFSSL_SKIP_TRAILING_PAD */
+                }
+            }
+#ifdef OPENSSL_EXTRA
+            if (ret) {
+                PEMerr(0, PEM_R_BAD_DECRYPT);
+            }
+#endif
+            ForceZero(password, passwordSz);
+        }
+#ifdef OPENSSL_EXTRA
+        else {
+            PEMerr(0, PEM_R_BAD_PASSWORD_READ);
+        }
+#endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(password, heap, DYNAMIC_TYPE_STRING);
+    #endif
+    }
+#endif /* WOLFSSL_ENCRYPTED_KEYS */
+
+    return ret;
+}
+
+int wc_PemToDer(const unsigned char* buff, long longSz, int type,
+              DerBuffer** pDer, void* heap, EncryptedInfo* info, int* eccKey)
+{
+    return PemToDer(buff, longSz, type, pDer, heap, info, eccKey);
+}
+
+
+/* our KeyPemToDer password callback, password in userData */
+static WC_INLINE int OurPasswordCb(char* passwd, int sz, int rw, void* userdata)
+{
+    (void)rw;
+
+    if (userdata == NULL)
+        return 0;
+
+    XSTRNCPY(passwd, (char*)userdata, sz);
+    return min((word32)sz, (word32)XSTRLEN((char*)userdata));
+}
+
+/* Return bytes written to buff or < 0 for error */
+int wc_KeyPemToDer(const unsigned char* pem, int pemSz,
+                        unsigned char* buff, int buffSz, const char* pass)
+{
+    int            eccKey = 0;
+    int            ret;
+    DerBuffer*     der = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    EncryptedInfo* info = NULL;
+#else
+    EncryptedInfo  info[1];
+#endif
+
+    WOLFSSL_ENTER("wc_KeyPemToDer");
+
+    if (pem == NULL || buff == NULL || buffSz <= 0) {
+        WOLFSSL_MSG("Bad pem der args");
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
+                                   DYNAMIC_TYPE_ENCRYPTEDINFO);
+    if (info == NULL)
+        return MEMORY_E;
+#endif
+
+    XMEMSET(info, 0, sizeof(EncryptedInfo));
+    info->passwd_cb = OurPasswordCb;
+    info->passwd_userdata = (void*)pass;
+
+    ret = PemToDer(pem, pemSz, PRIVATEKEY_TYPE, &der, NULL, info, &eccKey);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
+#endif
+
+    if (ret < 0 || der == NULL) {
+        WOLFSSL_MSG("Bad Pem To Der");
+    }
+    else {
+        if (der->length <= (word32)buffSz) {
+            XMEMCPY(buff, der->buffer, der->length);
+            ret = der->length;
+        }
+        else {
+            WOLFSSL_MSG("Bad der length");
+            ret = BAD_FUNC_ARG;
+        }
+    }
+
+    FreeDer(&der);
+    return ret;
+}
+
+
+/* Return bytes written to buff or < 0 for error */
+int wc_CertPemToDer(const unsigned char* pem, int pemSz,
+                        unsigned char* buff, int buffSz, int type)
+{
+    int            eccKey = 0;
+    int            ret;
+    DerBuffer*     der = NULL;
+
+    WOLFSSL_ENTER("wc_CertPemToDer");
+
+    if (pem == NULL || buff == NULL || buffSz <= 0) {
+        WOLFSSL_MSG("Bad pem der args");
+        return BAD_FUNC_ARG;
+    }
+
+    if (type != CERT_TYPE && type != CA_TYPE && type != CERTREQ_TYPE) {
+        WOLFSSL_MSG("Bad cert type");
+        return BAD_FUNC_ARG;
+    }
+
+
+    ret = PemToDer(pem, pemSz, type, &der, NULL, NULL, &eccKey);
+    if (ret < 0 || der == NULL) {
+        WOLFSSL_MSG("Bad Pem To Der");
+    }
+    else {
+        if (der->length <= (word32)buffSz) {
+            XMEMCPY(buff, der->buffer, der->length);
+            ret = der->length;
+        }
+        else {
+            WOLFSSL_MSG("Bad der length");
+            ret = BAD_FUNC_ARG;
+        }
+    }
+
+    FreeDer(&der);
+    return ret;
+}
+
+#endif /* WOLFSSL_PEM_TO_DER */
+#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
+
+
+#ifdef WOLFSSL_PEM_TO_DER
+#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER)
+/* Return bytes written to buff or < 0 for error */
+int wc_PubKeyPemToDer(const unsigned char* pem, int pemSz,
+                           unsigned char* buff, int buffSz)
+{
+    int ret;
+    DerBuffer* der = NULL;
+
+    WOLFSSL_ENTER("wc_PubKeyPemToDer");
+
+    if (pem == NULL || buff == NULL || buffSz <= 0) {
+        WOLFSSL_MSG("Bad pem der args");
+        return BAD_FUNC_ARG;
+    }
+
+    ret = PemToDer(pem, pemSz, PUBLICKEY_TYPE, &der, NULL, NULL, NULL);
+    if (ret < 0 || der == NULL) {
+        WOLFSSL_MSG("Bad Pem To Der");
+    }
+    else {
+        if (der->length <= (word32)buffSz) {
+            XMEMCPY(buff, der->buffer, der->length);
+            ret = der->length;
+        }
+        else {
+            WOLFSSL_MSG("Bad der length");
+            ret = BAD_FUNC_ARG;
+        }
+    }
+
+    FreeDer(&der);
+    return ret;
+}
+#endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER */
+#endif /* WOLFSSL_PEM_TO_DER */
+
+#ifndef NO_FILESYSTEM
+
+#ifdef WOLFSSL_CERT_GEN
+/* load pem cert from file into der buffer, return der size or error */
+int wc_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz)
+{
+#ifdef WOLFSSL_SMALL_STACK
+    byte   staticBuffer[1]; /* force XMALLOC */
+#else
+    byte   staticBuffer[FILE_BUFFER_SIZE];
+#endif
+    byte*  fileBuf = staticBuffer;
+    int    dynamic = 0;
+    int    ret     = 0;
+    long   sz      = 0;
+    XFILE  file;
+    DerBuffer* converted = NULL;
+
+    WOLFSSL_ENTER("wc_PemCertToDer");
+
+    if (fileName == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+    else {
+        file = XFOPEN(fileName, "rb");
+        if (file == XBADFILE) {
+            ret = BUFFER_E;
+        }
+    }
+
+    if (ret == 0) {
+        if(XFSEEK(file, 0, XSEEK_END) != 0)
+            ret = BUFFER_E;
+        sz = XFTELL(file);
+        XREWIND(file);
+
+        if (sz <= 0) {
+            ret = BUFFER_E;
+        }
+        else if (sz > (long)sizeof(staticBuffer)) {
+        #ifdef WOLFSSL_STATIC_MEMORY
+            WOLFSSL_MSG("File was larger then static buffer");
+            return MEMORY_E;
+        #endif
+            fileBuf = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE);
+            if (fileBuf == NULL)
+                ret = MEMORY_E;
+            else
+                dynamic = 1;
+        }
+
+        if (ret == 0) {
+            if ( (ret = (int)XFREAD(fileBuf, 1, sz, file)) != sz) {
+                ret = BUFFER_E;
+            }
+        #ifdef WOLFSSL_PEM_TO_DER
+            else {
+                ret = PemToDer(fileBuf, sz, CA_TYPE, &converted,  0, NULL,NULL);
+            }
+        #endif
+
+            if (ret == 0) {
+                if (converted->length < (word32)derSz) {
+                    XMEMCPY(derBuf, converted->buffer, converted->length);
+                    ret = converted->length;
+                }
+                else
+                    ret = BUFFER_E;
+            }
+
+            FreeDer(&converted);
+        }
+
+        XFCLOSE(file);
+        if (dynamic)
+            XFREE(fileBuf, NULL, DYNAMIC_TYPE_FILE);
+    }
+
+    return ret;
+}
+#endif /* WOLFSSL_CERT_GEN */
+
+#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER)
+/* load pem public key from file into der buffer, return der size or error */
+int wc_PemPubKeyToDer(const char* fileName,
+                           unsigned char* derBuf, int derSz)
+{
+#ifdef WOLFSSL_SMALL_STACK
+    byte   staticBuffer[1]; /* force XMALLOC */
+#else
+    byte   staticBuffer[FILE_BUFFER_SIZE];
+#endif
+    byte*  fileBuf = staticBuffer;
+    int    dynamic = 0;
+    int    ret     = 0;
+    long   sz      = 0;
+    XFILE  file;
+    DerBuffer* converted = NULL;
+
+    WOLFSSL_ENTER("wc_PemPubKeyToDer");
+
+    if (fileName == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+    else {
+        file = XFOPEN(fileName, "rb");
+        if (file == XBADFILE) {
+            ret = BUFFER_E;
+        }
+    }
+
+    if (ret == 0) {
+        if(XFSEEK(file, 0, XSEEK_END) != 0)
+            ret = BUFFER_E;
+        sz = XFTELL(file);
+        XREWIND(file);
+
+        if (sz <= 0) {
+            ret = BUFFER_E;
+        }
+        else if (sz > (long)sizeof(staticBuffer)) {
+        #ifdef WOLFSSL_STATIC_MEMORY
+            WOLFSSL_MSG("File was larger then static buffer");
+            return MEMORY_E;
+        #endif
+            fileBuf = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE);
+            if (fileBuf == NULL)
+                ret = MEMORY_E;
+            else
+                dynamic = 1;
+        }
+        if (ret == 0) {
+            if ( (ret = (int)XFREAD(fileBuf, 1, sz, file)) != sz) {
+                ret = BUFFER_E;
+            }
+        #ifdef WOLFSSL_PEM_TO_DER
+            else {
+                ret = PemToDer(fileBuf, sz, PUBLICKEY_TYPE, &converted,
+                               0, NULL, NULL);
+            }
+        #endif
+
+            if (ret == 0) {
+                if (converted->length < (word32)derSz) {
+                    XMEMCPY(derBuf, converted->buffer, converted->length);
+                    ret = converted->length;
+                }
+                else
+                    ret = BUFFER_E;
+            }
+
+            FreeDer(&converted);
+        }
+
+        XFCLOSE(file);
+        if (dynamic)
+            XFREE(fileBuf, NULL, DYNAMIC_TYPE_FILE);
+    }
+
+    return ret;
+}
+#endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER */
+
+#endif /* !NO_FILESYSTEM */
+
+
+#if !defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || \
+    ((defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !defined(HAVE_USER_RSA)))
+/* USER RSA ifdef portions used instead of refactor in consideration for
+   possible fips build */
+/* Write a public RSA key to output */
+static int SetRsaPublicKey(byte* output, RsaKey* key,
+                           int outLen, int with_header)
+{
+#ifdef WOLFSSL_SMALL_STACK
+    byte* n = NULL;
+    byte* e = NULL;
+#else
+    byte n[MAX_RSA_INT_SZ];
+    byte e[MAX_RSA_E_SZ];
+#endif
+    byte seq[MAX_SEQ_SZ];
+    byte bitString[1 + MAX_LENGTH_SZ + 1];
+    int  nSz;
+    int  eSz;
+    int  seqSz;
+    int  bitStringSz;
+    int  idx;
+
+    if (output == NULL || key == NULL || outLen < MAX_SEQ_SZ)
+        return BAD_FUNC_ARG;
+
+    /* n */
+#ifdef WOLFSSL_SMALL_STACK
+    n = (byte*)XMALLOC(MAX_RSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (n == NULL)
+        return MEMORY_E;
+#endif
+
+#ifdef HAVE_USER_RSA
+    nSz = SetASNIntRSA(key->n, n);
+#else
+    nSz = SetASNIntMP(&key->n, MAX_RSA_INT_SZ, n);
+#endif
+    if (nSz < 0) {
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+        return nSz;
+    }
+
+    /* e */
+#ifdef WOLFSSL_SMALL_STACK
+    e = (byte*)XMALLOC(MAX_RSA_E_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (e == NULL) {
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+        return MEMORY_E;
+    }
+#endif
+
+#ifdef HAVE_USER_RSA
+    eSz = SetASNIntRSA(key->e, e);
+#else
+    eSz = SetASNIntMP(&key->e, MAX_RSA_INT_SZ, e);
+#endif
+    if (eSz < 0) {
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+        return eSz;
+    }
+
+    seqSz  = SetSequence(nSz + eSz, seq);
+
+    /* check output size */
+    if ( (seqSz + nSz + eSz) > outLen) {
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(n,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(e,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+        return BUFFER_E;
+    }
+
+    /* headers */
+    if (with_header) {
+        int  algoSz;
+#ifdef WOLFSSL_SMALL_STACK
+        byte* algo;
+
+        algo = (byte*)XMALLOC(MAX_ALGO_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        if (algo == NULL) {
+            XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            return MEMORY_E;
+        }
+#else
+        byte algo[MAX_ALGO_SZ];
+#endif
+        algoSz = SetAlgoID(RSAk, algo, oidKeyType, 0);
+        bitStringSz  = SetBitString(seqSz + nSz + eSz, 0, bitString);
+
+        idx = SetSequence(nSz + eSz + seqSz + bitStringSz + algoSz, output);
+
+        /* check output size */
+        if ( (idx + algoSz + bitStringSz + seqSz + nSz + eSz) > outLen) {
+            #ifdef WOLFSSL_SMALL_STACK
+                XFREE(n,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+                XFREE(e,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+                XFREE(algo, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            #endif
+
+            return BUFFER_E;
+        }
+
+        /* algo */
+        XMEMCPY(output + idx, algo, algoSz);
+        idx += algoSz;
+        /* bit string */
+        XMEMCPY(output + idx, bitString, bitStringSz);
+        idx += bitStringSz;
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(algo, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+    }
+    else
+        idx = 0;
+
+    /* seq */
+    XMEMCPY(output + idx, seq, seqSz);
+    idx += seqSz;
+    /* n */
+    XMEMCPY(output + idx, n, nSz);
+    idx += nSz;
+    /* e */
+    XMEMCPY(output + idx, e, eSz);
+    idx += eSz;
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(n,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(e,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return idx;
+}
+
+#endif /* !NO_RSA && (WOLFSSL_CERT_GEN || (WOLFSSL_KEY_GEN &&
+                                           !HAVE_USER_RSA))) */
+
+#if !defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || defined(OPENSSL_EXTRA))
+int wc_RsaPublicKeyDerSize(RsaKey* key, int with_header)
+{
+    int  idx = 0;
+    int  nSz, eSz, seqSz, bitStringSz, algoSz;
+
+    if (key == NULL)
+        return BAD_FUNC_ARG;
+
+    /* n */
+#ifdef HAVE_USER_RSA
+    nSz = SetASNIntRSA(key->n, NULL);
+#else
+    nSz = SetASNIntMP(&key->n, MAX_RSA_INT_SZ, NULL);
+#endif
+    if (nSz < 0) {
+        return nSz;
+    }
+
+    /* e */
+#ifdef HAVE_USER_RSA
+    eSz = SetASNIntRSA(key->e, NULL);
+#else
+    eSz = SetASNIntMP(&key->e, MAX_RSA_INT_SZ, NULL);
+#endif
+    if (eSz < 0) {
+        return eSz;
+    }
+
+    seqSz  = SetSequence(nSz + eSz, NULL);
+
+    /* headers */
+    if (with_header) {
+        algoSz = SetAlgoID(RSAk, NULL, oidKeyType, 0);
+        bitStringSz = SetBitString(seqSz + nSz + eSz, 0, NULL);
+
+        idx += SetSequence(nSz + eSz + seqSz + bitStringSz + algoSz, NULL);
+
+        /* algo */
+        idx += algoSz;
+        /* bit string */
+        idx += bitStringSz;
+    }
+
+    /* seq */
+    idx += seqSz;
+    /* n */
+    idx += nSz;
+    /* e */
+    idx += eSz;
+
+    return idx;
+}
+
+#endif /* !NO_RSA && WOLFSSL_CERT_GEN */
+
+
+#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+
+static mp_int* GetRsaInt(RsaKey* key, int idx)
+{
+    if (idx == 0)
+        return &key->n;
+    if (idx == 1)
+        return &key->e;
+    if (idx == 2)
+        return &key->d;
+    if (idx == 3)
+        return &key->p;
+    if (idx == 4)
+        return &key->q;
+    if (idx == 5)
+        return &key->dP;
+    if (idx == 6)
+        return &key->dQ;
+    if (idx == 7)
+        return &key->u;
+
+    return NULL;
+}
+
+
+/* Release Tmp RSA resources */
+static WC_INLINE void FreeTmpRsas(byte** tmps, void* heap)
+{
+    int i;
+
+    (void)heap;
+
+    for (i = 0; i < RSA_INTS; i++)
+        XFREE(tmps[i], heap, DYNAMIC_TYPE_RSA);
+}
+
+
+/* Convert RsaKey key to DER format, write to output (inLen), return bytes
+   written */
+int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen)
+{
+    word32 seqSz, verSz, rawLen, intTotalLen = 0;
+    word32 sizes[RSA_INTS];
+    int    i, j, outLen, ret = 0, mpSz;
+
+    byte  seq[MAX_SEQ_SZ];
+    byte  ver[MAX_VERSION_SZ];
+    byte* tmps[RSA_INTS];
+
+    if (!key)
+        return BAD_FUNC_ARG;
+
+    if (key->type != RSA_PRIVATE)
+        return BAD_FUNC_ARG;
+
+    for (i = 0; i < RSA_INTS; i++)
+        tmps[i] = NULL;
+
+    /* write all big ints from key to DER tmps */
+    for (i = 0; i < RSA_INTS; i++) {
+        mp_int* keyInt = GetRsaInt(key, i);
+
+        rawLen = mp_unsigned_bin_size(keyInt) + 1;
+        tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap,
+                                 DYNAMIC_TYPE_RSA);
+        if (tmps[i] == NULL) {
+            ret = MEMORY_E;
+            break;
+        }
+
+        mpSz = SetASNIntMP(keyInt, MAX_RSA_INT_SZ, tmps[i]);
+        if (mpSz < 0) {
+            ret = mpSz;
+            break;
+        }
+        intTotalLen += (sizes[i] = mpSz);
+    }
+
+    if (ret != 0) {
+        FreeTmpRsas(tmps, key->heap);
+        return ret;
+    }
+
+    /* make headers */
+    verSz = SetMyVersion(0, ver, FALSE);
+    seqSz = SetSequence(verSz + intTotalLen, seq);
+
+    outLen = seqSz + verSz + intTotalLen;
+    if (output) {
+        if (outLen > (int)inLen) {
+            FreeTmpRsas(tmps, key->heap);
+            return BAD_FUNC_ARG;
+        }
+
+        /* write to output */
+        XMEMCPY(output, seq, seqSz);
+        j = seqSz;
+        XMEMCPY(output + j, ver, verSz);
+        j += verSz;
+
+        for (i = 0; i < RSA_INTS; i++) {
+            XMEMCPY(output + j, tmps[i], sizes[i]);
+            j += sizes[i];
+        }
+    }
+    FreeTmpRsas(tmps, key->heap);
+
+    return outLen;
+}
+#endif
+
+#if (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+/* Convert Rsa Public key to DER format, write to output (inLen), return bytes
+   written */
+int wc_RsaKeyToPublicDer(RsaKey* key, byte* output, word32 inLen)
+{
+    return SetRsaPublicKey(output, key, inLen, 1);
+}
+
+#endif /* (WOLFSSL_KEY_GEN || OPENSSL_EXTRA) && !NO_RSA && !HAVE_USER_RSA */
+
+
+#ifdef WOLFSSL_CERT_GEN
+
+/* Initialize and Set Certificate defaults:
+   version    = 3 (0x2)
+   serial     = 0
+   sigType    = SHA_WITH_RSA
+   issuer     = blank
+   daysValid  = 500
+   selfSigned = 1 (true) use subject as issuer
+   subject    = blank
+*/
+int wc_InitCert(Cert* cert)
+{
+#ifdef WOLFSSL_MULTI_ATTRIB
+    int i = 0;
+#endif
+    if (cert == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    XMEMSET(cert, 0, sizeof(Cert));
+
+    cert->version    = 2;   /* version 3 is hex 2 */
+#ifndef NO_SHA
+    cert->sigType    = CTC_SHAwRSA;
+#elif !defined(NO_SHA256)
+    cert->sigType    = CTC_SHA256wRSA;
+#else
+    cert->sigType    = 0;
+#endif
+    cert->daysValid  = 500;
+    cert->selfSigned = 1;
+    cert->keyType    = RSA_KEY;
+
+    cert->issuer.countryEnc = CTC_PRINTABLE;
+    cert->issuer.stateEnc = CTC_UTF8;
+    cert->issuer.localityEnc = CTC_UTF8;
+    cert->issuer.surEnc = CTC_UTF8;
+    cert->issuer.orgEnc = CTC_UTF8;
+    cert->issuer.unitEnc = CTC_UTF8;
+    cert->issuer.commonNameEnc = CTC_UTF8;
+
+    cert->subject.countryEnc = CTC_PRINTABLE;
+    cert->subject.stateEnc = CTC_UTF8;
+    cert->subject.localityEnc = CTC_UTF8;
+    cert->subject.surEnc = CTC_UTF8;
+    cert->subject.orgEnc = CTC_UTF8;
+    cert->subject.unitEnc = CTC_UTF8;
+    cert->subject.commonNameEnc = CTC_UTF8;
+
+#ifdef WOLFSSL_MULTI_ATTRIB
+    for (i = 0; i < CTC_MAX_ATTRIB; i++) {
+        cert->issuer.name[i].type   = CTC_UTF8;
+        cert->subject.name[i].type  = CTC_UTF8;
+    }
+#endif /* WOLFSSL_MULTI_ATTRIB */
+
+#ifdef WOLFSSL_HEAP_TEST
+    cert->heap = (void*)WOLFSSL_HEAP_TEST;
+#endif
+
+    return 0;
+}
+
+
+/* DER encoded x509 Certificate */
+typedef struct DerCert {
+    byte size[MAX_LENGTH_SZ];          /* length encoded */
+    byte version[MAX_VERSION_SZ];      /* version encoded */
+    byte serial[(int)CTC_SERIAL_SIZE + (int)MAX_LENGTH_SZ]; /* serial number encoded */
+    byte sigAlgo[MAX_ALGO_SZ];         /* signature algo encoded */
+    byte issuer[ASN_NAME_MAX];         /* issuer  encoded */
+    byte subject[ASN_NAME_MAX];        /* subject encoded */
+    byte validity[MAX_DATE_SIZE*2 + MAX_SEQ_SZ*2];  /* before and after dates */
+    byte publicKey[MAX_PUBLIC_KEY_SZ]; /* rsa / ntru public key encoded */
+    byte ca[MAX_CA_SZ];                /* basic constraint CA true size */
+    byte extensions[MAX_EXTENSIONS_SZ]; /* all extensions */
+#ifdef WOLFSSL_CERT_EXT
+    byte skid[MAX_KID_SZ];             /* Subject Key Identifier extension */
+    byte akid[MAX_KID_SZ];             /* Authority Key Identifier extension */
+    byte keyUsage[MAX_KEYUSAGE_SZ];    /* Key Usage extension */
+    byte extKeyUsage[MAX_EXTKEYUSAGE_SZ]; /* Extended Key Usage extension */
+    byte certPolicies[MAX_CERTPOL_NB*MAX_CERTPOL_SZ]; /* Certificate Policies */
+#endif
+#ifdef WOLFSSL_CERT_REQ
+    byte attrib[MAX_ATTRIB_SZ];        /* Cert req attributes encoded */
+#endif
+#ifdef WOLFSSL_ALT_NAMES
+    byte altNames[CTC_MAX_ALT_SIZE];   /* Alternative Names encoded */
+#endif
+    int  sizeSz;                       /* encoded size length */
+    int  versionSz;                    /* encoded version length */
+    int  serialSz;                     /* encoded serial length */
+    int  sigAlgoSz;                    /* encoded sig algo length */
+    int  issuerSz;                     /* encoded issuer length */
+    int  subjectSz;                    /* encoded subject length */
+    int  validitySz;                   /* encoded validity length */
+    int  publicKeySz;                  /* encoded public key length */
+    int  caSz;                         /* encoded CA extension length */
+#ifdef WOLFSSL_CERT_EXT
+    int  skidSz;                       /* encoded SKID extension length */
+    int  akidSz;                       /* encoded SKID extension length */
+    int  keyUsageSz;                   /* encoded KeyUsage extension length */
+    int  extKeyUsageSz;                /* encoded ExtendedKeyUsage extension length */
+    int  certPoliciesSz;               /* encoded CertPolicies extension length*/
+#endif
+#ifdef WOLFSSL_ALT_NAMES
+    int  altNamesSz;                   /* encoded AltNames extension length */
+#endif
+    int  extensionsSz;                 /* encoded extensions total length */
+    int  total;                        /* total encoded lengths */
+#ifdef WOLFSSL_CERT_REQ
+    int  attribSz;
+#endif
+} DerCert;
+
+
+#ifdef WOLFSSL_CERT_REQ
+
+/* Write a set header to output */
+static word32 SetPrintableString(word32 len, byte* output)
+{
+    output[0] = ASN_PRINTABLE_STRING;
+    return SetLength(len, output + 1) + 1;
+}
+
+static word32 SetUTF8String(word32 len, byte* output)
+{
+    output[0] = ASN_UTF8STRING;
+    return SetLength(len, output + 1) + 1;
+}
+
+#endif /* WOLFSSL_CERT_REQ */
+
+
+#ifndef WOLFSSL_CERT_GEN_CACHE
+/* wc_SetCert_Free is only public when WOLFSSL_CERT_GEN_CACHE is not defined */
+static
+#endif
+void wc_SetCert_Free(Cert* cert)
+{
+    if (cert != NULL) {
+        cert->der = NULL;
+        if (cert->decodedCert) {
+            FreeDecodedCert((DecodedCert*)cert->decodedCert);
+
+            XFREE(cert->decodedCert, cert->heap, DYNAMIC_TYPE_DCERT);
+            cert->decodedCert = NULL;
+        }
+    }
+}
+
+static int wc_SetCert_LoadDer(Cert* cert, const byte* der, word32 derSz)
+{
+    int ret;
+
+    if (cert == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+    else {
+        /* Allocate DecodedCert struct and Zero */
+        cert->decodedCert = (void*)XMALLOC(sizeof(DecodedCert), cert->heap,
+            DYNAMIC_TYPE_DCERT);
+
+        if (cert->decodedCert == NULL) {
+            ret = MEMORY_E;
+        }
+        else {
+            XMEMSET(cert->decodedCert, 0, sizeof(DecodedCert));
+
+            InitDecodedCert((DecodedCert*)cert->decodedCert, der, derSz,
+                    cert->heap);
+            ret = ParseCertRelative((DecodedCert*)cert->decodedCert,
+                    CERT_TYPE, 0, NULL);
+            if (ret >= 0) {
+                cert->der = (byte*)der;
+            }
+            else {
+                wc_SetCert_Free(cert);
+            }
+        }
+    }
+
+    return ret;
+}
+
+#endif /* WOLFSSL_CERT_GEN */
+
+
+#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)
+
+/* Write a public ECC key to output */
+static int SetEccPublicKey(byte* output, ecc_key* key, int with_header)
+{
+    byte bitString[1 + MAX_LENGTH_SZ + 1];
+    int  algoSz;
+    int  curveSz;
+    int  bitStringSz;
+    int  idx;
+    word32 pubSz = ECC_BUFSIZE;
+#ifdef WOLFSSL_SMALL_STACK
+    byte* algo = NULL;
+    byte* curve = NULL;
+    byte* pub;
+#else
+    byte algo[MAX_ALGO_SZ];
+    byte curve[MAX_ALGO_SZ];
+    byte pub[ECC_BUFSIZE];
+#endif
+    int ret;
+
+#ifdef WOLFSSL_SMALL_STACK
+    pub = (byte*)XMALLOC(ECC_BUFSIZE, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (pub == NULL)
+        return MEMORY_E;
+#endif
+
+#ifdef HAVE_SELFTEST
+    /* older version of ecc.c can not handle dp being NULL */
+    if (key != NULL && key->dp == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+    else {
+        ret = wc_ecc_export_x963(key, pub, &pubSz);
+    }
+#else
+    ret = wc_ecc_export_x963(key, pub, &pubSz);
+#endif
+    if (ret != 0) {
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+        return ret;
+    }
+
+    /* headers */
+    if (with_header) {
+#ifdef WOLFSSL_SMALL_STACK
+        curve = (byte*)XMALLOC(MAX_ALGO_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        if (curve == NULL) {
+            XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            return MEMORY_E;
+        }
+#endif
+        curveSz = SetCurve(key, curve);
+        if (curveSz <= 0) {
+#ifdef WOLFSSL_SMALL_STACK
+            XFREE(curve, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            XFREE(pub,   key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+            return curveSz;
+        }
+
+#ifdef WOLFSSL_SMALL_STACK
+        algo = (byte*)XMALLOC(MAX_ALGO_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        if (algo == NULL) {
+            XFREE(curve, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            XFREE(pub,   key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            return MEMORY_E;
+        }
+#endif
+        algoSz  = SetAlgoID(ECDSAk, algo, oidKeyType, curveSz);
+
+        bitStringSz = SetBitString(pubSz, 0, bitString);
+
+        idx = SetSequence(pubSz + curveSz + bitStringSz + algoSz, output);
+        /* algo */
+        if (output)
+            XMEMCPY(output + idx, algo, algoSz);
+        idx += algoSz;
+        /* curve */
+        if (output)
+            XMEMCPY(output + idx, curve, curveSz);
+        idx += curveSz;
+        /* bit string */
+        if (output)
+            XMEMCPY(output + idx, bitString, bitStringSz);
+        idx += bitStringSz;
+    }
+    else
+        idx = 0;
+
+    /* pub */
+    if (output)
+        XMEMCPY(output + idx, pub, pubSz);
+    idx += pubSz;
+
+#ifdef WOLFSSL_SMALL_STACK
+    if (with_header) {
+        XFREE(algo,  key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(curve, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+    XFREE(pub,   key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return idx;
+}
+
+
+/* returns the size of buffer used, the public ECC key in DER format is stored
+   in output buffer
+   with_AlgCurve is a flag for when to include a header that has the Algorithm
+   and Curve information */
+int wc_EccPublicKeyToDer(ecc_key* key, byte* output, word32 inLen,
+                                                              int with_AlgCurve)
+{
+    word32 infoSz = 0;
+    word32 keySz  = 0;
+    int ret;
+
+    if (key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (with_AlgCurve) {
+        /* buffer space for algorithm/curve */
+        infoSz += MAX_SEQ_SZ;
+        infoSz += 2 * MAX_ALGO_SZ;
+
+        /* buffer space for public key sequence */
+        infoSz += MAX_SEQ_SZ;
+        infoSz += TRAILING_ZERO;
+    }
+
+#ifdef HAVE_SELFTEST
+    /* older version of ecc.c can not handle dp being NULL */
+    if (key != NULL && key->dp == NULL) {
+        keySz = 1 + 2 * MAX_ECC_BYTES;
+        ret = LENGTH_ONLY_E;
+    }
+    else {
+        ret = wc_ecc_export_x963(key, NULL, &keySz);
+    }
+#else
+    ret = wc_ecc_export_x963(key, NULL, &keySz);
+#endif
+    if (ret != LENGTH_ONLY_E) {
+        WOLFSSL_MSG("Error in getting ECC public key size");
+        return ret;
+    }
+
+    /* if output null then just return size */
+    if (output == NULL) {
+        return keySz + infoSz;
+    }
+
+    if (inLen < keySz + infoSz) {
+        return BUFFER_E;
+    }
+
+    return SetEccPublicKey(output, key, with_AlgCurve);
+}
+
+int wc_EccPublicKeyDerSize(ecc_key* key, int with_AlgCurve)
+{
+    return wc_EccPublicKeyToDer(key, NULL, 0, with_AlgCurve);
+}
+
+#endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT */
+
+#if defined(HAVE_ED25519) && (defined(WOLFSSL_CERT_GEN) || \
+                              defined(WOLFSSL_KEY_GEN))
+
+/* Write a public ECC key to output */
+static int SetEd25519PublicKey(byte* output, ed25519_key* key, int with_header)
+{
+    byte bitString[1 + MAX_LENGTH_SZ + 1];
+    int  algoSz;
+    int  bitStringSz;
+    int  idx;
+    word32 pubSz = ED25519_PUB_KEY_SIZE;
+#ifdef WOLFSSL_SMALL_STACK
+    byte* algo = NULL;
+    byte* pub;
+#else
+    byte algo[MAX_ALGO_SZ];
+    byte pub[ED25519_PUB_KEY_SIZE];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+    pub = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (pub == NULL)
+        return MEMORY_E;
+#endif
+
+    idx = wc_ed25519_export_public(key, pub, &pubSz);
+    if (idx != 0) {
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+        return idx;
+    }
+
+    /* headers */
+    if (with_header) {
+#ifdef WOLFSSL_SMALL_STACK
+        algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (algo == NULL) {
+            XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            return MEMORY_E;
+        }
+#endif
+        algoSz  = SetAlgoID(ED25519k, algo, oidKeyType, 0);
+
+        bitStringSz = SetBitString(pubSz, 0, bitString);
+
+        idx = SetSequence(pubSz + bitStringSz + algoSz, output);
+        /* algo */
+        XMEMCPY(output + idx, algo, algoSz);
+        idx += algoSz;
+        /* bit string */
+        XMEMCPY(output + idx, bitString, bitStringSz);
+        idx += bitStringSz;
+    }
+    else
+        idx = 0;
+
+    /* pub */
+    XMEMCPY(output + idx, pub, pubSz);
+    idx += pubSz;
+
+#ifdef WOLFSSL_SMALL_STACK
+    if (with_header) {
+        XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+    XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return idx;
+}
+
+int wc_Ed25519PublicKeyToDer(ed25519_key* key, byte* output, word32 inLen,
+                                                                    int withAlg)
+{
+    word32 infoSz = 0;
+    word32 keySz  = 0;
+    int ret;
+
+    if (output == NULL || key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (withAlg) {
+        /* buffer space for algorithm */
+        infoSz += MAX_SEQ_SZ;
+        infoSz += MAX_ALGO_SZ;
+
+        /* buffer space for public key sequence */
+        infoSz += MAX_SEQ_SZ;
+        infoSz += TRAILING_ZERO;
+    }
+
+    if ((ret = wc_ed25519_export_public(key, output, &keySz)) != BUFFER_E) {
+        WOLFSSL_MSG("Error in getting ECC public key size");
+        return ret;
+    }
+
+    if (inLen < keySz + infoSz) {
+        return BUFFER_E;
+    }
+
+    return SetEd25519PublicKey(output, key, withAlg);
+}
+#endif /* HAVE_ED25519 && (WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN) */
+#if defined(HAVE_ED448) && (defined(WOLFSSL_CERT_GEN) || \
+                                                       defined(WOLFSSL_KEY_GEN))
+
+/* Write a public ECC key to output */
+static int SetEd448PublicKey(byte* output, ed448_key* key, int with_header)
+{
+    byte bitString[1 + MAX_LENGTH_SZ + 1];
+    int  algoSz;
+    int  bitStringSz;
+    int  idx;
+    word32 pubSz = ED448_PUB_KEY_SIZE;
+#ifdef WOLFSSL_SMALL_STACK
+    byte* algo = NULL;
+    byte* pub = NULL;
+#else
+    byte algo[MAX_ALGO_SZ];
+    byte pub[ED448_PUB_KEY_SIZE];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+    pub = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (pub == NULL)
+        return MEMORY_E;
+#endif
+
+    idx = wc_ed448_export_public(key, pub, &pubSz);
+    if (idx != 0) {
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+        return idx;
+    }
+
+    /* headers */
+    if (with_header) {
+#ifdef WOLFSSL_SMALL_STACK
+        algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (algo == NULL) {
+            XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            return MEMORY_E;
+        }
+#endif
+        algoSz  = SetAlgoID(ED448k, algo, oidKeyType, 0);
+
+        bitStringSz = SetBitString(pubSz, 0, bitString);
+
+        idx = SetSequence(pubSz + bitStringSz + algoSz, output);
+        /* algo */
+        XMEMCPY(output + idx, algo, algoSz);
+        idx += algoSz;
+        /* bit string */
+        XMEMCPY(output + idx, bitString, bitStringSz);
+        idx += bitStringSz;
+    }
+    else
+        idx = 0;
+
+    /* pub */
+    XMEMCPY(output + idx, pub, pubSz);
+    idx += pubSz;
+
+#ifdef WOLFSSL_SMALL_STACK
+    if (with_header) {
+        XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+    XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return idx;
+}
+
+int wc_Ed448PublicKeyToDer(ed448_key* key, byte* output, word32 inLen,
+                                                                    int withAlg)
+{
+    word32 infoSz = 0;
+    word32 keySz  = 0;
+    int ret;
+
+    if (output == NULL || key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (withAlg) {
+        /* buffer space for algorithm */
+        infoSz += MAX_SEQ_SZ;
+        infoSz += MAX_ALGO_SZ;
+
+        /* buffer space for public key sequence */
+        infoSz += MAX_SEQ_SZ;
+        infoSz += TRAILING_ZERO;
+    }
+
+    if ((ret = wc_ed448_export_public(key, output, &keySz)) != BUFFER_E) {
+        WOLFSSL_MSG("Error in getting ECC public key size");
+        return ret;
+    }
+
+    if (inLen < keySz + infoSz) {
+        return BUFFER_E;
+    }
+
+    return SetEd448PublicKey(output, key, withAlg);
+}
+#endif /* HAVE_ED448 && (WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN) */
+
+
+#ifdef WOLFSSL_CERT_GEN
+
+static WC_INLINE byte itob(int number)
+{
+    return (byte)number + 0x30;
+}
+
+
+/* write time to output, format */
+static void SetTime(struct tm* date, byte* output)
+{
+    int i = 0;
+
+    output[i++] = itob((date->tm_year % 10000) / 1000);
+    output[i++] = itob((date->tm_year % 1000)  /  100);
+    output[i++] = itob((date->tm_year % 100)   /   10);
+    output[i++] = itob( date->tm_year % 10);
+
+    output[i++] = itob(date->tm_mon / 10);
+    output[i++] = itob(date->tm_mon % 10);
+
+    output[i++] = itob(date->tm_mday / 10);
+    output[i++] = itob(date->tm_mday % 10);
+
+    output[i++] = itob(date->tm_hour / 10);
+    output[i++] = itob(date->tm_hour % 10);
+
+    output[i++] = itob(date->tm_min / 10);
+    output[i++] = itob(date->tm_min % 10);
+
+    output[i++] = itob(date->tm_sec / 10);
+    output[i++] = itob(date->tm_sec % 10);
+
+    output[i] = 'Z';  /* Zulu profile */
+}
+
+
+#ifdef WOLFSSL_ALT_NAMES
+
+/* Copy Dates from cert, return bytes written */
+static int CopyValidity(byte* output, Cert* cert)
+{
+    int seqSz;
+
+    WOLFSSL_ENTER("CopyValidity");
+
+    /* headers and output */
+    seqSz = SetSequence(cert->beforeDateSz + cert->afterDateSz, output);
+    if (output) {
+        XMEMCPY(output + seqSz, cert->beforeDate, cert->beforeDateSz);
+        XMEMCPY(output + seqSz + cert->beforeDateSz, cert->afterDate,
+                                                     cert->afterDateSz);
+    }
+    return seqSz + cert->beforeDateSz + cert->afterDateSz;
+}
+
+#endif
+
+
+/* Set Date validity from now until now + daysValid
+ * return size in bytes written to output, 0 on error */
+static int SetValidity(byte* output, int daysValid)
+{
+    byte before[MAX_DATE_SIZE];
+    byte  after[MAX_DATE_SIZE];
+
+    int beforeSz;
+    int afterSz;
+    int seqSz;
+
+    time_t now;
+    time_t then;
+    struct tm* tmpTime;
+    struct tm* expandedTime;
+    struct tm localTime;
+
+#if defined(NEED_TMP_TIME)
+    /* for use with gmtime_r */
+    struct tm tmpTimeStorage;
+    tmpTime = &tmpTimeStorage;
+#else
+    tmpTime = NULL;
+#endif
+    (void)tmpTime;
+
+    now = XTIME(0);
+
+    /* before now */
+    before[0] = ASN_GENERALIZED_TIME;
+    beforeSz = SetLength(ASN_GEN_TIME_SZ, before + 1) + 1;  /* gen tag */
+
+    /* subtract 1 day of seconds for more compliance */
+    then = now - 86400;
+    expandedTime = XGMTIME(&then, tmpTime);
+    if (expandedTime == NULL) {
+        WOLFSSL_MSG("XGMTIME failed");
+        return 0;   /* error */
+    }
+    localTime = *expandedTime;
+
+    /* adjust */
+    localTime.tm_year += 1900;
+    localTime.tm_mon +=    1;
+
+    SetTime(&localTime, before + beforeSz);
+    beforeSz += ASN_GEN_TIME_SZ;
+
+    after[0] = ASN_GENERALIZED_TIME;
+    afterSz  = SetLength(ASN_GEN_TIME_SZ, after + 1) + 1;  /* gen tag */
+
+    /* add daysValid of seconds */
+    then = now + (daysValid * (time_t)86400);
+    expandedTime = XGMTIME(&then, tmpTime);
+    if (expandedTime == NULL) {
+        WOLFSSL_MSG("XGMTIME failed");
+        return 0;   /* error */
+    }
+    localTime = *expandedTime;
+
+    /* adjust */
+    localTime.tm_year += 1900;
+    localTime.tm_mon  +=    1;
+
+    SetTime(&localTime, after + afterSz);
+    afterSz += ASN_GEN_TIME_SZ;
+
+    /* headers and output */
+    seqSz = SetSequence(beforeSz + afterSz, output);
+    XMEMCPY(output + seqSz, before, beforeSz);
+    XMEMCPY(output + seqSz + beforeSz, after, afterSz);
+
+    return seqSz + beforeSz + afterSz;
+}
+
+
+/* ASN Encoded Name field */
+typedef struct EncodedName {
+    int  nameLen;                /* actual string value length */
+    int  totalLen;               /* total encoded length */
+    int  type;                   /* type of name */
+    int  used;                   /* are we actually using this one */
+    byte encoded[CTC_NAME_SIZE * 2]; /* encoding */
+} EncodedName;
+
+
+/* Get Which Name from index */
+static const char* GetOneName(CertName* name, int idx)
+{
+    switch (idx) {
+    case 0:
+       return name->country;
+
+    case 1:
+       return name->state;
+
+    case 2:
+       return name->locality;
+
+    case 3:
+       return name->sur;
+
+    case 4:
+       return name->org;
+
+    case 5:
+       return name->unit;
+
+    case 6:
+       return name->commonName;
+
+    case 7:
+       return name->serialDev;
+
+#ifdef WOLFSSL_CERT_EXT
+    case 8:
+       return name->busCat;
+
+    case 9:
+#else
+    case 8:
+#endif
+       return name->email;
+
+    default:
+       return 0;
+    }
+}
+
+
+/* Get Which Name Encoding from index */
+static char GetNameType(CertName* name, int idx)
+{
+    switch (idx) {
+    case 0:
+       return name->countryEnc;
+
+    case 1:
+       return name->stateEnc;
+
+    case 2:
+       return name->localityEnc;
+
+    case 3:
+       return name->surEnc;
+
+    case 4:
+       return name->orgEnc;
+
+    case 5:
+       return name->unitEnc;
+
+    case 6:
+       return name->commonNameEnc;
+
+    case 7:
+       return name->serialDevEnc;
+
+#ifdef WOLFSSL_CERT_EXT
+    case 8:
+       return name->busCatEnc;
+
+    case 9:
+#else
+    case 8:
+#endif
+        /* FALL THROUGH */
+        /* The last index, email name, does not have encoding type.
+           The empty case here is to keep track of it for future reference. */
+    default:
+       return 0;
+    }
+}
+
+
+/* Get ASN Name from index */
+static byte GetNameId(int idx)
+{
+    switch (idx) {
+    case 0:
+       return ASN_COUNTRY_NAME;
+
+    case 1:
+       return ASN_STATE_NAME;
+
+    case 2:
+       return ASN_LOCALITY_NAME;
+
+    case 3:
+       return ASN_SUR_NAME;
+
+    case 4:
+       return ASN_ORG_NAME;
+
+    case 5:
+       return ASN_ORGUNIT_NAME;
+
+    case 6:
+       return ASN_COMMON_NAME;
+
+    case 7:
+       return ASN_SERIAL_NUMBER;
+
+#ifdef WOLFSSL_CERT_EXT
+    case 8:
+        return ASN_BUS_CAT;
+
+    case 9:
+#else
+    case 8:
+#endif
+        return ASN_EMAIL_NAME;
+
+    default:
+       return 0;
+    }
+}
+
+/*
+ Extensions ::= SEQUENCE OF Extension
+
+ Extension ::= SEQUENCE {
+ extnId     OBJECT IDENTIFIER,
+ critical   BOOLEAN DEFAULT FALSE,
+ extnValue  OCTET STRING }
+ */
+
+/* encode all extensions, return total bytes written */
+static int SetExtensions(byte* out, word32 outSz, int *IdxInOut,
+                         const byte* ext, int extSz)
+{
+    if (out == NULL || IdxInOut == NULL || ext == NULL)
+        return BAD_FUNC_ARG;
+
+    if (outSz < (word32)(*IdxInOut+extSz))
+        return BUFFER_E;
+
+    XMEMCPY(&out[*IdxInOut], ext, extSz);  /* extensions */
+    *IdxInOut += extSz;
+
+    return *IdxInOut;
+}
+
+/* encode extensions header, return total bytes written */
+static int SetExtensionsHeader(byte* out, word32 outSz, int extSz)
+{
+    byte sequence[MAX_SEQ_SZ];
+    byte len[MAX_LENGTH_SZ];
+    int seqSz, lenSz, idx = 0;
+
+    if (out == NULL)
+        return BAD_FUNC_ARG;
+
+    if (outSz < 3)
+        return BUFFER_E;
+
+    seqSz = SetSequence(extSz, sequence);
+
+    /* encode extensions length provided */
+    lenSz = SetLength(extSz+seqSz, len);
+
+    if (outSz < (word32)(lenSz+seqSz+1))
+        return BUFFER_E;
+
+    out[idx++] = ASN_EXTENSIONS; /* extensions id */
+    XMEMCPY(&out[idx], len, lenSz);  /* length */
+    idx += lenSz;
+
+    XMEMCPY(&out[idx], sequence, seqSz);  /* sequence */
+    idx += seqSz;
+
+    return idx;
+}
+
+
+/* encode CA basic constraint true, return total bytes written */
+static int SetCa(byte* out, word32 outSz)
+{
+    const byte ca[] = { 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04,
+                               0x05, 0x30, 0x03, 0x01, 0x01, 0xff };
+
+    if (out == NULL)
+        return BAD_FUNC_ARG;
+
+    if (outSz < sizeof(ca))
+        return BUFFER_E;
+
+    XMEMCPY(out, ca, sizeof(ca));
+
+    return (int)sizeof(ca);
+}
+
+
+#ifdef WOLFSSL_CERT_EXT
+/* encode OID and associated value, return total bytes written */
+static int SetOidValue(byte* out, word32 outSz, const byte *oid, word32 oidSz,
+                       byte *in, word32 inSz)
+{
+    int idx = 0;
+
+    if (out == NULL || oid == NULL || in == NULL)
+        return BAD_FUNC_ARG;
+
+    if (outSz < 3)
+        return BUFFER_E;
+
+    /* sequence,  + 1 => byte to put value size */
+    idx = SetSequence(inSz + oidSz + 1, out);
+
+    if ((idx + inSz + oidSz + 1) > outSz)
+        return BUFFER_E;
+
+    XMEMCPY(out+idx, oid, oidSz);
+    idx += oidSz;
+    out[idx++] = (byte)inSz;
+    XMEMCPY(out+idx, in, inSz);
+
+    return (idx+inSz);
+}
+
+/* encode Subject Key Identifier, return total bytes written
+ * RFC5280 : non-critical */
+static int SetSKID(byte* output, word32 outSz, const byte *input, word32 length)
+{
+    byte skid_len[1 + MAX_LENGTH_SZ];
+    byte skid_enc_len[MAX_LENGTH_SZ];
+    int idx = 0, skid_lenSz, skid_enc_lenSz;
+    const byte skid_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04 };
+
+    if (output == NULL || input == NULL)
+        return BAD_FUNC_ARG;
+
+    /* Octet String header */
+    skid_lenSz = SetOctetString(length, skid_len);
+
+    /* length of encoded value */
+    skid_enc_lenSz = SetLength(length + skid_lenSz, skid_enc_len);
+
+    if (outSz < 3)
+        return BUFFER_E;
+
+    idx = SetSequence(length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz,
+                      output);
+
+    if ((length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz) > outSz)
+        return BUFFER_E;
+
+    /* put oid */
+    XMEMCPY(output+idx, skid_oid, sizeof(skid_oid));
+    idx += sizeof(skid_oid);
+
+    /* put encoded len */
+    XMEMCPY(output+idx, skid_enc_len, skid_enc_lenSz);
+    idx += skid_enc_lenSz;
+
+    /* put octet header */
+    XMEMCPY(output+idx, skid_len, skid_lenSz);
+    idx += skid_lenSz;
+
+    /* put value */
+    XMEMCPY(output+idx, input, length);
+    idx += length;
+
+    return idx;
+}
+
+/* encode Authority Key Identifier, return total bytes written
+ * RFC5280 : non-critical */
+static int SetAKID(byte* output, word32 outSz,
+                                         byte *input, word32 length, void* heap)
+{
+    byte    *enc_val;
+    int     ret, enc_valSz;
+    const byte akid_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04 };
+    const byte akid_cs[] = { 0x80 };
+
+    (void)heap;
+
+    if (output == NULL || input == NULL)
+        return BAD_FUNC_ARG;
+
+    enc_valSz = length + 3 + sizeof(akid_cs);
+    enc_val = (byte *)XMALLOC(enc_valSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (enc_val == NULL)
+        return MEMORY_E;
+
+    /* sequence for ContentSpec & value */
+    ret = SetOidValue(enc_val, enc_valSz, akid_cs, sizeof(akid_cs),
+                      input, length);
+    if (ret > 0) {
+        enc_valSz = ret;
+
+        ret = SetOidValue(output, outSz, akid_oid, sizeof(akid_oid),
+                          enc_val, enc_valSz);
+    }
+
+    XFREE(enc_val, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    return ret;
+}
+
+/* encode Key Usage, return total bytes written
+ * RFC5280 : critical */
+static int SetKeyUsage(byte* output, word32 outSz, word16 input)
+{
+    byte ku[5];
+    int  idx;
+    const byte keyusage_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x0f,
+                                         0x01, 0x01, 0xff, 0x04};
+    if (output == NULL)
+        return BAD_FUNC_ARG;
+
+    idx = SetBitString16Bit(input, ku);
+    return SetOidValue(output, outSz, keyusage_oid, sizeof(keyusage_oid),
+                       ku, idx);
+}
+
+static int SetOjectIdValue(byte* output, word32 outSz, int* idx,
+    const byte* oid, word32 oidSz)
+{
+    /* verify room */
+    if (*idx + 2 + oidSz >= outSz)
+        return ASN_PARSE_E;
+
+    *idx += SetObjectId(oidSz, &output[*idx]);
+    XMEMCPY(&output[*idx], oid, oidSz);
+    *idx += oidSz;
+
+    return 0;
+}
+
+/* encode Extended Key Usage (RFC 5280 4.2.1.12), return total bytes written */
+static int SetExtKeyUsage(Cert* cert, byte* output, word32 outSz, byte input)
+{
+    int idx = 0, oidListSz = 0, totalSz, ret = 0;
+    const byte extkeyusage_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x25 };
+
+    if (output == NULL)
+        return BAD_FUNC_ARG;
+
+    /* Skip to OID List */
+    totalSz = 2 + sizeof(extkeyusage_oid) + 4;
+    idx = totalSz;
+
+    /* Build OID List */
+    /* If any set, then just use it */
+    if (input & EXTKEYUSE_ANY) {
+        ret |= SetOjectIdValue(output, outSz, &idx,
+            extExtKeyUsageAnyOid, sizeof(extExtKeyUsageAnyOid));
+    }
+    else {
+        if (input & EXTKEYUSE_SERVER_AUTH)
+            ret |= SetOjectIdValue(output, outSz, &idx,
+                extExtKeyUsageServerAuthOid, sizeof(extExtKeyUsageServerAuthOid));
+        if (input & EXTKEYUSE_CLIENT_AUTH)
+            ret |= SetOjectIdValue(output, outSz, &idx,
+                extExtKeyUsageClientAuthOid, sizeof(extExtKeyUsageClientAuthOid));
+        if (input & EXTKEYUSE_CODESIGN)
+            ret |= SetOjectIdValue(output, outSz, &idx,
+                extExtKeyUsageCodeSigningOid, sizeof(extExtKeyUsageCodeSigningOid));
+        if (input & EXTKEYUSE_EMAILPROT)
+            ret |= SetOjectIdValue(output, outSz, &idx,
+                extExtKeyUsageEmailProtectOid, sizeof(extExtKeyUsageEmailProtectOid));
+        if (input & EXTKEYUSE_TIMESTAMP)
+            ret |= SetOjectIdValue(output, outSz, &idx,
+                extExtKeyUsageTimestampOid, sizeof(extExtKeyUsageTimestampOid));
+        if (input & EXTKEYUSE_OCSP_SIGN)
+            ret |= SetOjectIdValue(output, outSz, &idx,
+                extExtKeyUsageOcspSignOid, sizeof(extExtKeyUsageOcspSignOid));
+    #ifdef WOLFSSL_EKU_OID
+        /* iterate through OID values */
+        if (input & EXTKEYUSE_USER) {
+            int i, sz;
+            for (i = 0; i < CTC_MAX_EKU_NB; i++) {
+                sz = cert->extKeyUsageOIDSz[i];
+                if (sz > 0) {
+                    ret |= SetOjectIdValue(output, outSz, &idx,
+                        cert->extKeyUsageOID[i], sz);
+                }
+            }
+        }
+    #endif /* WOLFSSL_EKU_OID */
+    }
+    if (ret != 0)
+        return ASN_PARSE_E;
+
+    /* Calculate Sizes */
+    oidListSz = idx - totalSz;
+    totalSz = idx - 2; /* exclude first seq/len (2) */
+
+    /* 1. Seq + Total Len (2) */
+    idx = SetSequence(totalSz, output);
+
+    /* 2. Object ID (2) */
+    XMEMCPY(&output[idx], extkeyusage_oid, sizeof(extkeyusage_oid));
+    idx += sizeof(extkeyusage_oid);
+
+    /* 3. Octet String (2) */
+    idx += SetOctetString(totalSz - idx, &output[idx]);
+
+    /* 4. Seq + OidListLen (2) */
+    idx += SetSequence(oidListSz, &output[idx]);
+
+    /* 5. Oid List (already set in-place above) */
+    idx += oidListSz;
+
+    (void)cert;
+    return idx;
+}
+
+/* encode Certificate Policies, return total bytes written
+ * each input value must be ITU-T X.690 formatted : a.b.c...
+ * input must be an array of values with a NULL terminated for the latest
+ * RFC5280 : non-critical */
+static int SetCertificatePolicies(byte *output,
+                                  word32 outputSz,
+                                  char input[MAX_CERTPOL_NB][MAX_CERTPOL_SZ],
+                                  word16 nb_certpol,
+                                  void* heap)
+{
+    byte    oid[MAX_OID_SZ],
+            der_oid[MAX_CERTPOL_NB][MAX_OID_SZ],
+            out[MAX_CERTPOL_SZ];
+    word32  oidSz;
+    word32  outSz, i = 0, der_oidSz[MAX_CERTPOL_NB];
+    int     ret;
+
+    const byte certpol_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04 };
+    const byte oid_oid[] = { 0x06 };
+
+    if (output == NULL || input == NULL || nb_certpol > MAX_CERTPOL_NB)
+        return BAD_FUNC_ARG;
+
+    for (i = 0; i < nb_certpol; i++) {
+        oidSz = sizeof(oid);
+        XMEMSET(oid, 0, oidSz);
+
+        ret = EncodePolicyOID(oid, &oidSz, input[i], heap);
+        if (ret != 0)
+            return ret;
+
+        /* compute sequence value for the oid */
+        ret = SetOidValue(der_oid[i], MAX_OID_SZ, oid_oid,
+                          sizeof(oid_oid), oid, oidSz);
+        if (ret <= 0)
+            return ret;
+        else
+            der_oidSz[i] = (word32)ret;
+    }
+
+    /* concatenate oid, keep two byte for sequence/size of the created value */
+    for (i = 0, outSz = 2; i < nb_certpol; i++) {
+        XMEMCPY(out+outSz, der_oid[i], der_oidSz[i]);
+        outSz += der_oidSz[i];
+    }
+
+    /* add sequence */
+    ret = SetSequence(outSz-2, out);
+    if (ret <= 0)
+        return ret;
+
+    /* add Policy OID to compute final value */
+    return SetOidValue(output, outputSz, certpol_oid, sizeof(certpol_oid),
+                      out, outSz);
+}
+#endif /* WOLFSSL_CERT_EXT */
+
+
+#ifdef WOLFSSL_ALT_NAMES
+
+/* encode Alternative Names, return total bytes written */
+static int SetAltNames(byte *output, word32 outSz,
+        const byte *input, word32 length)
+{
+    byte san_len[1 + MAX_LENGTH_SZ];
+    int idx = 0, san_lenSz;
+    const byte san_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x11 };
+
+    if (output == NULL || input == NULL)
+        return BAD_FUNC_ARG;
+
+    if (outSz < length)
+        return BUFFER_E;
+
+    /* Octet String header */
+    san_lenSz = SetOctetString(length, san_len);
+
+    if (outSz < MAX_SEQ_SZ)
+        return BUFFER_E;
+
+    idx = SetSequence(length + sizeof(san_oid) + san_lenSz, output);
+
+    if ((length + sizeof(san_oid) + san_lenSz) > outSz)
+        return BUFFER_E;
+
+    /* put oid */
+    XMEMCPY(output+idx, san_oid, sizeof(san_oid));
+    idx += sizeof(san_oid);
+
+    /* put octet header */
+    XMEMCPY(output+idx, san_len, san_lenSz);
+    idx += san_lenSz;
+
+    /* put value */
+    XMEMCPY(output+idx, input, length);
+    idx += length;
+
+    return idx;
+}
+
+
+#ifdef WOLFSSL_CERT_GEN
+
+int FlattenAltNames(byte* output, word32 outputSz, const DNS_entry* names)
+{
+    word32 idx;
+    const DNS_entry* curName;
+    word32 namesSz = 0;
+
+    if (output == NULL)
+        return BAD_FUNC_ARG;
+
+    if (names == NULL)
+        return 0;
+
+    curName = names;
+    do {
+        namesSz += curName->len + 2 +
+            ((curName->len < ASN_LONG_LENGTH) ? 0
+             : BytePrecision(curName->len));
+        curName = curName->next;
+    } while (curName != NULL);
+
+    if (outputSz < MAX_SEQ_SZ + namesSz)
+        return BUFFER_E;
+
+    idx = SetSequence(namesSz, output);
+
+    curName = names;
+    do {
+        output[idx++] = ASN_CONTEXT_SPECIFIC | curName->type;
+        idx += SetLength(curName->len, output + idx);
+        XMEMCPY(output + idx, curName->name, curName->len);
+        idx += curName->len;
+        curName = curName->next;
+    } while (curName != NULL);
+
+    return idx;
+}
+
+#endif /* WOLFSSL_CERT_GEN */
+
+#endif /* WOLFSSL_ALT_NAMES */
+
+/* Encodes one attribute of the name (issuer/subject)
+ *
+ * name     structure to hold result of encoding
+ * nameStr  value to be encoded
+ * nameType type of encoding i.e CTC_UTF8
+ * type     id of attribute i.e ASN_COMMON_NAME
+ *
+ * returns length on success
+ */
+static int wc_EncodeName(EncodedName* name, const char* nameStr, char nameType,
+        byte type)
+{
+    word32 idx = 0;
+
+    if (nameStr) {
+        /* bottom up */
+        byte firstLen[1 + MAX_LENGTH_SZ];
+        byte secondLen[MAX_LENGTH_SZ];
+        byte sequence[MAX_SEQ_SZ];
+        byte set[MAX_SET_SZ];
+
+        int strLen  = (int)XSTRLEN(nameStr);
+        int thisLen = strLen;
+        int firstSz, secondSz, seqSz, setSz;
+
+        if (strLen == 0) { /* no user data for this item */
+            name->used = 0;
+            return 0;
+        }
+
+        /* Restrict country code size */
+        if (ASN_COUNTRY_NAME == type && strLen != CTC_COUNTRY_SIZE) {
+            return ASN_COUNTRY_SIZE_E;
+        }
+
+        secondSz = SetLength(strLen, secondLen);
+        thisLen += secondSz;
+        switch (type) {
+            case ASN_EMAIL_NAME: /* email */
+                thisLen += EMAIL_JOINT_LEN;
+                firstSz  = EMAIL_JOINT_LEN;
+                break;
+
+            case ASN_DOMAIN_COMPONENT:
+                thisLen += PILOT_JOINT_LEN;
+                firstSz  = PILOT_JOINT_LEN;
+                break;
+
+            default:
+                thisLen++;                                 /* str type */
+                thisLen += JOINT_LEN;
+                firstSz  = JOINT_LEN + 1;
+        }
+        thisLen++; /* id  type */
+        firstSz  = SetObjectId(firstSz, firstLen);
+        thisLen += firstSz;
+
+        seqSz = SetSequence(thisLen, sequence);
+        thisLen += seqSz;
+        setSz = SetSet(thisLen, set);
+        thisLen += setSz;
+
+        if (thisLen > (int)sizeof(name->encoded)) {
+            return BUFFER_E;
+        }
+
+        /* store it */
+        idx = 0;
+        /* set */
+        XMEMCPY(name->encoded, set, setSz);
+        idx += setSz;
+        /* seq */
+        XMEMCPY(name->encoded + idx, sequence, seqSz);
+        idx += seqSz;
+        /* asn object id */
+        XMEMCPY(name->encoded + idx, firstLen, firstSz);
+        idx += firstSz;
+        switch (type) {
+            case ASN_EMAIL_NAME:
+                {
+                    const byte EMAIL_OID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+                                       0x01, 0x09, 0x01, 0x16 };
+                    /* email joint id */
+                    XMEMCPY(name->encoded + idx, EMAIL_OID, sizeof(EMAIL_OID));
+                    idx += (int)sizeof(EMAIL_OID);
+                }
+                break;
+
+            case ASN_DOMAIN_COMPONENT:
+                {
+                    const byte PILOT_OID[] = { 0x09, 0x92, 0x26, 0x89,
+                                    0x93, 0xF2, 0x2C, 0x64, 0x01
+                    };
+
+                    XMEMCPY(name->encoded + idx, PILOT_OID,
+                                                     sizeof(PILOT_OID));
+                    idx += (int)sizeof(PILOT_OID);
+                    /* id type */
+                    name->encoded[idx++] = type;
+                    /* str type */
+                    name->encoded[idx++] = nameType;
+                }
+                break;
+
+            default:
+                name->encoded[idx++] = 0x55;
+                name->encoded[idx++] = 0x04;
+                /* id type */
+                name->encoded[idx++] = type;
+                /* str type */
+                name->encoded[idx++] = nameType;
+        }
+        /* second length */
+        XMEMCPY(name->encoded + idx, secondLen, secondSz);
+        idx += secondSz;
+        /* str value */
+        XMEMCPY(name->encoded + idx, nameStr, strLen);
+        idx += strLen;
+
+        name->type = type;
+        name->totalLen = idx;
+        name->used = 1;
+    }
+    else
+        name->used = 0;
+
+    return idx;
+}
+
+/* encode CertName into output, return total bytes written */
+int SetName(byte* output, word32 outputSz, CertName* name)
+{
+    int          totalBytes = 0, i, idx;
+#ifdef WOLFSSL_SMALL_STACK
+    EncodedName* names = NULL;
+#else
+    EncodedName  names[NAME_ENTRIES];
+#endif
+#ifdef WOLFSSL_MULTI_ATTRIB
+    EncodedName addNames[CTC_MAX_ATTRIB];
+    int j, type;
+#endif
+
+    if (output == NULL || name == NULL)
+        return BAD_FUNC_ARG;
+
+    if (outputSz < 3)
+        return BUFFER_E;
+
+#ifdef WOLFSSL_SMALL_STACK
+    names = (EncodedName*)XMALLOC(sizeof(EncodedName) * NAME_ENTRIES, NULL,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+    if (names == NULL)
+        return MEMORY_E;
+#endif
+
+    for (i = 0; i < NAME_ENTRIES; i++) {
+        int ret;
+        const char* nameStr = GetOneName(name, i);
+
+        ret = wc_EncodeName(&names[i], nameStr, GetNameType(name, i),
+                          GetNameId(i));
+        if (ret < 0) {
+        #ifdef WOLFSSL_SMALL_STACK
+                XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        #endif
+                return BUFFER_E;
+        }
+        totalBytes += ret;
+    }
+#ifdef WOLFSSL_MULTI_ATTRIB
+    for (i = 0; i < CTC_MAX_ATTRIB; i++) {
+        if (name->name[i].sz > 0) {
+            int ret;
+            ret = wc_EncodeName(&addNames[i], name->name[i].value,
+                        name->name[i].type, name->name[i].id);
+            if (ret < 0) {
+            #ifdef WOLFSSL_SMALL_STACK
+                XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            #endif
+                return BUFFER_E;
+            }
+            totalBytes += ret;
+        }
+        else {
+            addNames[i].used = 0;
+        }
+    }
+#endif /* WOLFSSL_MULTI_ATTRIB */
+
+    /* header */
+    idx = SetSequence(totalBytes, output);
+    totalBytes += idx;
+    if (totalBytes > ASN_NAME_MAX) {
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+        return BUFFER_E;
+    }
+
+    for (i = 0; i < NAME_ENTRIES; i++) {
+    #ifdef WOLFSSL_MULTI_ATTRIB
+        type = GetNameId(i);
+
+        /* list all DC values before OUs */
+        if (type == ASN_ORGUNIT_NAME) {
+            type = ASN_DOMAIN_COMPONENT;
+            for (j = 0; j < CTC_MAX_ATTRIB; j++) {
+                if (name->name[j].sz > 0 && type == name->name[j].id) {
+                    if (outputSz < (word32)(idx+addNames[j].totalLen)) {
+                    #ifdef WOLFSSL_SMALL_STACK
+                        XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                    #endif
+                        return BUFFER_E;
+                    }
+
+                    XMEMCPY(output + idx, addNames[j].encoded,
+                            addNames[j].totalLen);
+                    idx += addNames[j].totalLen;
+                }
+            }
+            type = ASN_ORGUNIT_NAME;
+        }
+
+        /* write all similar types to the buffer */
+        for (j = 0; j < CTC_MAX_ATTRIB; j++) {
+            if (name->name[j].sz > 0 && type == name->name[j].id) {
+                if (outputSz < (word32)(idx+addNames[j].totalLen)) {
+                #ifdef WOLFSSL_SMALL_STACK
+                    XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                #endif
+                    return BUFFER_E;
+                }
+
+                XMEMCPY(output + idx, addNames[j].encoded,
+                        addNames[j].totalLen);
+                idx += addNames[j].totalLen;
+            }
+        }
+    #endif /* WOLFSSL_MULTI_ATTRIB */
+
+        if (names[i].used) {
+            if (outputSz < (word32)(idx+names[i].totalLen)) {
+#ifdef WOLFSSL_SMALL_STACK
+                XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+                return BUFFER_E;
+            }
+
+            XMEMCPY(output + idx, names[i].encoded, names[i].totalLen);
+            idx += names[i].totalLen;
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return totalBytes;
+}
+
+/* encode info from cert into DER encoded format */
+static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey,
+                      WC_RNG* rng, const byte* ntruKey, word16 ntruSz,
+                      ed25519_key* ed25519Key, ed448_key* ed448Key)
+{
+    int ret;
+
+    if (cert == NULL || der == NULL || rng == NULL)
+        return BAD_FUNC_ARG;
+
+    /* make sure at least one key type is provided */
+    if (rsaKey == NULL && eccKey == NULL && ed25519Key == NULL &&
+                                          ed448Key == NULL && ntruKey == NULL) {
+        return PUBLIC_KEY_E;
+    }
+
+    /* init */
+    XMEMSET(der, 0, sizeof(DerCert));
+
+    /* version */
+    der->versionSz = SetMyVersion(cert->version, der->version, TRUE);
+
+    /* serial number (must be positive) */
+    if (cert->serialSz == 0) {
+        /* generate random serial */
+        cert->serialSz = CTC_GEN_SERIAL_SZ;
+        ret = wc_RNG_GenerateBlock(rng, cert->serial, cert->serialSz);
+        if (ret != 0)
+            return ret;
+        /* Clear the top bit to avoid a negative value */
+        cert->serial[0] &= 0x7f;
+    }
+    der->serialSz = SetSerialNumber(cert->serial, cert->serialSz, der->serial,
+        sizeof(der->serial), CTC_SERIAL_SIZE);
+    if (der->serialSz < 0)
+        return der->serialSz;
+
+    /* signature algo */
+    der->sigAlgoSz = SetAlgoID(cert->sigType, der->sigAlgo, oidSigType, 0);
+    if (der->sigAlgoSz <= 0)
+        return ALGO_ID_E;
+
+    /* public key */
+#ifndef NO_RSA
+    if (cert->keyType == RSA_KEY) {
+        if (rsaKey == NULL)
+            return PUBLIC_KEY_E;
+        der->publicKeySz = SetRsaPublicKey(der->publicKey, rsaKey,
+                                           sizeof(der->publicKey), 1);
+    }
+#endif
+
+#ifdef HAVE_ECC
+    if (cert->keyType == ECC_KEY) {
+        if (eccKey == NULL)
+            return PUBLIC_KEY_E;
+        der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey, 1);
+    }
+#endif
+
+#ifdef HAVE_ED25519
+    if (cert->keyType == ED25519_KEY) {
+        if (ed25519Key == NULL)
+            return PUBLIC_KEY_E;
+        der->publicKeySz = SetEd25519PublicKey(der->publicKey, ed25519Key, 1);
+    }
+#endif
+
+#ifdef HAVE_ED448
+    if (cert->keyType == ED448_KEY) {
+        if (ed448Key == NULL)
+            return PUBLIC_KEY_E;
+        der->publicKeySz = SetEd448PublicKey(der->publicKey, ed448Key, 1);
+    }
+#endif
+
+#ifdef HAVE_NTRU
+    if (cert->keyType == NTRU_KEY) {
+        word32 rc;
+        word16 encodedSz;
+
+        if (ntruKey == NULL)
+            return PUBLIC_KEY_E;
+
+        rc  = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo(ntruSz,
+                                                   ntruKey, &encodedSz, NULL);
+        if (rc != NTRU_OK)
+            return PUBLIC_KEY_E;
+        if (encodedSz > MAX_PUBLIC_KEY_SZ)
+            return PUBLIC_KEY_E;
+
+        rc  = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo(ntruSz,
+                                         ntruKey, &encodedSz, der->publicKey);
+        if (rc != NTRU_OK)
+            return PUBLIC_KEY_E;
+
+        der->publicKeySz = encodedSz;
+    }
+#else
+    (void)ntruSz;
+#endif /* HAVE_NTRU */
+
+    if (der->publicKeySz <= 0)
+        return PUBLIC_KEY_E;
+
+    der->validitySz = 0;
+#ifdef WOLFSSL_ALT_NAMES
+    /* date validity copy ? */
+    if (cert->beforeDateSz && cert->afterDateSz) {
+        der->validitySz = CopyValidity(der->validity, cert);
+        if (der->validitySz <= 0)
+            return DATE_E;
+    }
+#endif
+
+    /* date validity */
+    if (der->validitySz == 0) {
+        der->validitySz = SetValidity(der->validity, cert->daysValid);
+        if (der->validitySz <= 0)
+            return DATE_E;
+    }
+
+    /* subject name */
+#ifdef WOLFSSL_CERT_EXT
+    if (XSTRLEN((const char*)cert->sbjRaw) > 0) {
+        /* Use the raw subject */
+        int idx;
+
+        der->subjectSz = min(sizeof(der->subject),
+                (word32)XSTRLEN((const char*)cert->sbjRaw));
+        /* header */
+        idx = SetSequence(der->subjectSz, der->subject);
+        if (der->subjectSz + idx > (int)sizeof(der->subject)) {
+            return SUBJECT_E;
+        }
+
+        XMEMCPY((char*)der->subject + idx, (const char*)cert->sbjRaw,
+                der->subjectSz);
+        der->subjectSz += idx;
+    }
+    else
+#endif
+    {
+        /* Use the name structure */
+        der->subjectSz = SetName(der->subject, sizeof(der->subject),
+                &cert->subject);
+    }
+    if (der->subjectSz <= 0)
+        return SUBJECT_E;
+
+    /* issuer name */
+#ifdef WOLFSSL_CERT_EXT
+    if (XSTRLEN((const char*)cert->issRaw) > 0) {
+        /* Use the raw issuer */
+        int idx;
+
+        der->issuerSz = min(sizeof(der->issuer),
+                (word32)XSTRLEN((const char*)cert->issRaw));
+        /* header */
+        idx = SetSequence(der->issuerSz, der->issuer);
+        if (der->issuerSz + idx > (int)sizeof(der->issuer)) {
+            return ISSUER_E;
+        }
+
+        XMEMCPY((char*)der->issuer + idx, (const char*)cert->issRaw,
+                der->issuerSz);
+        der->issuerSz += idx;
+    }
+    else
+#endif
+    {
+        /* Use the name structure */
+        der->issuerSz = SetName(der->issuer, sizeof(der->issuer),
+                cert->selfSigned ? &cert->subject : &cert->issuer);
+    }
+    if (der->issuerSz <= 0)
+        return ISSUER_E;
+
+    /* set the extensions */
+    der->extensionsSz = 0;
+
+    /* CA */
+    if (cert->isCA) {
+        der->caSz = SetCa(der->ca, sizeof(der->ca));
+        if (der->caSz <= 0)
+            return CA_TRUE_E;
+
+        der->extensionsSz += der->caSz;
+    }
+    else
+        der->caSz = 0;
+
+#ifdef WOLFSSL_ALT_NAMES
+    /* Alternative Name */
+    if (cert->altNamesSz) {
+        der->altNamesSz = SetAltNames(der->altNames, sizeof(der->altNames),
+                                      cert->altNames, cert->altNamesSz);
+        if (der->altNamesSz <= 0)
+            return ALT_NAME_E;
+
+        der->extensionsSz += der->altNamesSz;
+    }
+    else
+        der->altNamesSz = 0;
+#endif
+
+#ifdef WOLFSSL_CERT_EXT
+    /* SKID */
+    if (cert->skidSz) {
+        /* check the provided SKID size */
+        if (cert->skidSz > (int)min(CTC_MAX_SKID_SIZE, sizeof(der->skid)))
+            return SKID_E;
+
+        /* Note: different skid buffers sizes for der (MAX_KID_SZ) and
+            cert (CTC_MAX_SKID_SIZE). */
+        der->skidSz = SetSKID(der->skid, sizeof(der->skid),
+                              cert->skid, cert->skidSz);
+        if (der->skidSz <= 0)
+            return SKID_E;
+
+        der->extensionsSz += der->skidSz;
+    }
+    else
+        der->skidSz = 0;
+
+    /* AKID */
+    if (cert->akidSz) {
+        /* check the provided AKID size */
+        if (cert->akidSz > (int)min(CTC_MAX_AKID_SIZE, sizeof(der->akid)))
+            return AKID_E;
+
+        der->akidSz = SetAKID(der->akid, sizeof(der->akid),
+                              cert->akid, cert->akidSz, cert->heap);
+        if (der->akidSz <= 0)
+            return AKID_E;
+
+        der->extensionsSz += der->akidSz;
+    }
+    else
+        der->akidSz = 0;
+
+    /* Key Usage */
+    if (cert->keyUsage != 0){
+        der->keyUsageSz = SetKeyUsage(der->keyUsage, sizeof(der->keyUsage),
+                                      cert->keyUsage);
+        if (der->keyUsageSz <= 0)
+            return KEYUSAGE_E;
+
+        der->extensionsSz += der->keyUsageSz;
+    }
+    else
+        der->keyUsageSz = 0;
+
+    /* Extended Key Usage */
+    if (cert->extKeyUsage != 0){
+        der->extKeyUsageSz = SetExtKeyUsage(cert, der->extKeyUsage,
+                                sizeof(der->extKeyUsage), cert->extKeyUsage);
+        if (der->extKeyUsageSz <= 0)
+            return EXTKEYUSAGE_E;
+
+        der->extensionsSz += der->extKeyUsageSz;
+    }
+    else
+        der->extKeyUsageSz = 0;
+
+    /* Certificate Policies */
+    if (cert->certPoliciesNb != 0) {
+        der->certPoliciesSz = SetCertificatePolicies(der->certPolicies,
+                                                     sizeof(der->certPolicies),
+                                                     cert->certPolicies,
+                                                     cert->certPoliciesNb,
+                                                     cert->heap);
+        if (der->certPoliciesSz <= 0)
+            return CERTPOLICIES_E;
+
+        der->extensionsSz += der->certPoliciesSz;
+    }
+    else
+        der->certPoliciesSz = 0;
+#endif /* WOLFSSL_CERT_EXT */
+
+    /* put extensions */
+    if (der->extensionsSz > 0) {
+
+        /* put the start of extensions sequence (ID, Size) */
+        der->extensionsSz = SetExtensionsHeader(der->extensions,
+                                                sizeof(der->extensions),
+                                                der->extensionsSz);
+        if (der->extensionsSz <= 0)
+            return EXTENSIONS_E;
+
+        /* put CA */
+        if (der->caSz) {
+            ret = SetExtensions(der->extensions, sizeof(der->extensions),
+                                &der->extensionsSz,
+                                der->ca, der->caSz);
+            if (ret == 0)
+                return EXTENSIONS_E;
+        }
+
+#ifdef WOLFSSL_ALT_NAMES
+        /* put Alternative Names */
+        if (der->altNamesSz) {
+            ret = SetExtensions(der->extensions, sizeof(der->extensions),
+                                &der->extensionsSz,
+                                der->altNames, der->altNamesSz);
+            if (ret <= 0)
+                return EXTENSIONS_E;
+        }
+#endif
+
+#ifdef WOLFSSL_CERT_EXT
+        /* put SKID */
+        if (der->skidSz) {
+            ret = SetExtensions(der->extensions, sizeof(der->extensions),
+                                &der->extensionsSz,
+                                der->skid, der->skidSz);
+            if (ret <= 0)
+                return EXTENSIONS_E;
+        }
+
+        /* put AKID */
+        if (der->akidSz) {
+            ret = SetExtensions(der->extensions, sizeof(der->extensions),
+                                &der->extensionsSz,
+                                der->akid, der->akidSz);
+            if (ret <= 0)
+                return EXTENSIONS_E;
+        }
+
+        /* put KeyUsage */
+        if (der->keyUsageSz) {
+            ret = SetExtensions(der->extensions, sizeof(der->extensions),
+                                &der->extensionsSz,
+                                der->keyUsage, der->keyUsageSz);
+            if (ret <= 0)
+                return EXTENSIONS_E;
+        }
+
+        /* put ExtendedKeyUsage */
+        if (der->extKeyUsageSz) {
+            ret = SetExtensions(der->extensions, sizeof(der->extensions),
+                                &der->extensionsSz,
+                                der->extKeyUsage, der->extKeyUsageSz);
+            if (ret <= 0)
+                return EXTENSIONS_E;
+        }
+
+        /* put Certificate Policies */
+        if (der->certPoliciesSz) {
+            ret = SetExtensions(der->extensions, sizeof(der->extensions),
+                                &der->extensionsSz,
+                                der->certPolicies, der->certPoliciesSz);
+            if (ret <= 0)
+                return EXTENSIONS_E;
+        }
+#endif /* WOLFSSL_CERT_EXT */
+    }
+
+    der->total = der->versionSz + der->serialSz + der->sigAlgoSz +
+        der->publicKeySz + der->validitySz + der->subjectSz + der->issuerSz +
+        der->extensionsSz;
+
+    return 0;
+}
+
+
+/* write DER encoded cert to buffer, size already checked */
+static int WriteCertBody(DerCert* der, byte* buf)
+{
+    int idx;
+
+    /* signed part header */
+    idx = SetSequence(der->total, buf);
+    /* version */
+    XMEMCPY(buf + idx, der->version, der->versionSz);
+    idx += der->versionSz;
+    /* serial */
+    XMEMCPY(buf + idx, der->serial, der->serialSz);
+    idx += der->serialSz;
+    /* sig algo */
+    XMEMCPY(buf + idx, der->sigAlgo, der->sigAlgoSz);
+    idx += der->sigAlgoSz;
+    /* issuer */
+    XMEMCPY(buf + idx, der->issuer, der->issuerSz);
+    idx += der->issuerSz;
+    /* validity */
+    XMEMCPY(buf + idx, der->validity, der->validitySz);
+    idx += der->validitySz;
+    /* subject */
+    XMEMCPY(buf + idx, der->subject, der->subjectSz);
+    idx += der->subjectSz;
+    /* public key */
+    XMEMCPY(buf + idx, der->publicKey, der->publicKeySz);
+    idx += der->publicKeySz;
+    if (der->extensionsSz) {
+        /* extensions */
+        XMEMCPY(buf + idx, der->extensions, min(der->extensionsSz,
+                                                   (int)sizeof(der->extensions)));
+        idx += der->extensionsSz;
+    }
+
+    return idx;
+}
+
+
+/* Make RSA signature from buffer (sz), write to sig (sigSz) */
+static int MakeSignature(CertSignCtx* certSignCtx, const byte* buf, int sz,
+    byte* sig, int sigSz, RsaKey* rsaKey, ecc_key* eccKey,
+    ed25519_key* ed25519Key, ed448_key* ed448Key, WC_RNG* rng, int sigAlgoType,
+    void* heap)
+{
+    int digestSz = 0, typeH = 0, ret = 0;
+
+    (void)digestSz;
+    (void)typeH;
+    (void)buf;
+    (void)sz;
+    (void)sig;
+    (void)sigSz;
+    (void)rsaKey;
+    (void)eccKey;
+    (void)ed25519Key;
+    (void)ed448Key;
+    (void)rng;
+    (void)heap;
+
+    switch (certSignCtx->state) {
+    case CERTSIGN_STATE_BEGIN:
+    case CERTSIGN_STATE_DIGEST:
+
+        certSignCtx->state = CERTSIGN_STATE_DIGEST;
+        certSignCtx->digest = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, heap,
+            DYNAMIC_TYPE_TMP_BUFFER);
+        if (certSignCtx->digest == NULL) {
+            ret = MEMORY_E; goto exit_ms;
+        }
+
+        ret = HashForSignature(buf, sz, sigAlgoType, certSignCtx->digest,
+                               &typeH, &digestSz, 0);
+        /* set next state, since WC_PENDING_E rentry for these are not "call again" */
+        certSignCtx->state = CERTSIGN_STATE_ENCODE;
+        if (ret != 0) {
+            goto exit_ms;
+        }
+        FALL_THROUGH;
+
+    case CERTSIGN_STATE_ENCODE:
+    #ifndef NO_RSA
+        if (rsaKey) {
+            certSignCtx->encSig = (byte*)XMALLOC(MAX_DER_DIGEST_SZ, heap,
+                DYNAMIC_TYPE_TMP_BUFFER);
+            if (certSignCtx->encSig == NULL) {
+                ret = MEMORY_E; goto exit_ms;
+            }
+
+            /* signature */
+            certSignCtx->encSigSz = wc_EncodeSignature(certSignCtx->encSig,
+                                          certSignCtx->digest, digestSz, typeH);
+        }
+    #endif /* !NO_RSA */
+        FALL_THROUGH;
+
+    case CERTSIGN_STATE_DO:
+        certSignCtx->state = CERTSIGN_STATE_DO;
+        ret = ALGO_ID_E; /* default to error */
+
+    #ifndef NO_RSA
+        if (rsaKey) {
+            /* signature */
+            ret = wc_RsaSSL_Sign(certSignCtx->encSig, certSignCtx->encSigSz,
+                                 sig, sigSz, rsaKey, rng);
+        }
+    #endif /* !NO_RSA */
+
+    #ifdef HAVE_ECC
+        if (!rsaKey && eccKey) {
+            word32 outSz = sigSz;
+
+            ret = wc_ecc_sign_hash(certSignCtx->digest, digestSz,
+                                   sig, &outSz, rng, eccKey);
+            if (ret == 0)
+                ret = outSz;
+        }
+    #endif /* HAVE_ECC */
+
+    #ifdef HAVE_ED25519
+        if (!rsaKey && !eccKey && ed25519Key) {
+            word32 outSz = sigSz;
+
+            ret = wc_ed25519_sign_msg(buf, sz, sig, &outSz, ed25519Key);
+            if (ret == 0)
+                ret = outSz;
+        }
+    #endif /* HAVE_ECC */
+
+    #ifdef HAVE_ED448
+        if (!rsaKey && !eccKey && !ed25519Key && ed448Key) {
+            word32 outSz = sigSz;
+
+            ret = wc_ed448_sign_msg(buf, sz, sig, &outSz, ed448Key, NULL, 0);
+            if (ret == 0)
+                ret = outSz;
+        }
+    #endif /* HAVE_ECC */
+        break;
+    }
+
+exit_ms:
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        return ret;
+    }
+#endif
+
+#ifndef NO_RSA
+    if (rsaKey) {
+        XFREE(certSignCtx->encSig, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+#endif /* !NO_RSA */
+
+    XFREE(certSignCtx->digest, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    certSignCtx->digest = NULL;
+
+    /* reset state */
+    certSignCtx->state = CERTSIGN_STATE_BEGIN;
+
+    return ret;
+}
+
+
+/* add signature to end of buffer, size of buffer assumed checked, return
+   new length */
+static int AddSignature(byte* buf, int bodySz, const byte* sig, int sigSz,
+                        int sigAlgoType)
+{
+    byte seq[MAX_SEQ_SZ];
+    int  idx = bodySz, seqSz;
+
+    /* algo */
+    idx += SetAlgoID(sigAlgoType, buf ? buf + idx : NULL, oidSigType, 0);
+    /* bit string */
+    idx += SetBitString(sigSz, 0, buf ? buf + idx : NULL);
+    /* signature */
+    if (buf)
+        XMEMCPY(buf + idx, sig, sigSz);
+    idx += sigSz;
+
+    /* make room for overall header */
+    seqSz = SetSequence(idx, seq);
+    if (buf) {
+        XMEMMOVE(buf + seqSz, buf, idx);
+        XMEMCPY(buf, seq, seqSz);
+    }
+
+    return idx + seqSz;
+}
+
+
+/* Make an x509 Certificate v3 any key type from cert input, write to buffer */
+static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz,
+                       RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng,
+                       const byte* ntruKey, word16 ntruSz,
+                       ed25519_key* ed25519Key, ed448_key* ed448Key)
+{
+    int ret;
+#ifdef WOLFSSL_SMALL_STACK
+    DerCert* der;
+#else
+    DerCert der[1];
+#endif
+
+    if (derBuffer == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    cert->keyType = eccKey ? ECC_KEY : (rsaKey ? RSA_KEY :
+            (ed25519Key ? ED25519_KEY : (ed448Key ? ED448_KEY : NTRU_KEY)));
+
+#ifdef WOLFSSL_SMALL_STACK
+    der = (DerCert*)XMALLOC(sizeof(DerCert), cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (der == NULL)
+        return MEMORY_E;
+#endif
+
+    ret = EncodeCert(cert, der, rsaKey, eccKey, rng, ntruKey, ntruSz,
+                     ed25519Key, ed448Key);
+    if (ret == 0) {
+        if (der->total + MAX_SEQ_SZ * 2 > (int)derSz)
+            ret = BUFFER_E;
+        else
+            ret = cert->bodySz = WriteCertBody(der, derBuffer);
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(der, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return ret;
+}
+
+
+/* Make an x509 Certificate v3 RSA or ECC from cert input, write to buffer */
+int wc_MakeCert_ex(Cert* cert, byte* derBuffer, word32 derSz, int keyType,
+                   void* key, WC_RNG* rng)
+{
+    RsaKey*      rsaKey = NULL;
+    ecc_key*     eccKey = NULL;
+    ed25519_key* ed25519Key = NULL;
+    ed448_key*   ed448Key = NULL;
+
+    if (keyType == RSA_TYPE)
+        rsaKey = (RsaKey*)key;
+    else if (keyType == ECC_TYPE)
+        eccKey = (ecc_key*)key;
+    else if (keyType == ED25519_TYPE)
+        ed25519Key = (ed25519_key*)key;
+    else if (keyType == ED448_TYPE)
+        ed448Key = (ed448_key*)key;
+
+    return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0,
+                       ed25519Key, ed448Key);
+}
+/* Make an x509 Certificate v3 RSA or ECC from cert input, write to buffer */
+int wc_MakeCert(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey,
+             ecc_key* eccKey, WC_RNG* rng)
+{
+    return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0,
+                       NULL, NULL);
+}
+
+
+#ifdef HAVE_NTRU
+
+int wc_MakeNtruCert(Cert* cert, byte* derBuffer, word32 derSz,
+                  const byte* ntruKey, word16 keySz, WC_RNG* rng)
+{
+    return MakeAnyCert(cert, derBuffer, derSz, NULL, NULL, rng, ntruKey, keySz, NULL);
+}
+
+#endif /* HAVE_NTRU */
+
+
+#ifdef WOLFSSL_CERT_REQ
+
+static int SetReqAttrib(byte* output, char* pw, int pwPrintableString,
+                        int extSz)
+{
+    const byte cpOid[] =
+        { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+                         0x09, 0x07 };
+    const byte erOid[] =
+        { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+                         0x09, 0x0e };
+
+    int sz      = 0; /* overall size */
+    int cpSz    = 0; /* Challenge Password section size */
+    int cpSeqSz = 0;
+    int cpSetSz = 0;
+    int cpStrSz = 0;
+    int pwSz    = 0;
+    int erSz    = 0; /* Extension Request section size */
+    int erSeqSz = 0;
+    int erSetSz = 0;
+    byte cpSeq[MAX_SEQ_SZ];
+    byte cpSet[MAX_SET_SZ];
+    byte cpStr[MAX_PRSTR_SZ];
+    byte erSeq[MAX_SEQ_SZ];
+    byte erSet[MAX_SET_SZ];
+
+    output[0] = 0xa0;
+    sz++;
+
+    if (pw && pw[0]) {
+        pwSz = (int)XSTRLEN(pw);
+        if (pwPrintableString) {
+            cpStrSz = SetPrintableString(pwSz, cpStr);
+        } else {
+            cpStrSz = SetUTF8String(pwSz, cpStr);
+        }
+        cpSetSz = SetSet(cpStrSz + pwSz, cpSet);
+        cpSeqSz = SetSequence(sizeof(cpOid) + cpSetSz + cpStrSz + pwSz, cpSeq);
+        cpSz = cpSeqSz + sizeof(cpOid) + cpSetSz + cpStrSz + pwSz;
+    }
+
+    if (extSz) {
+        erSetSz = SetSet(extSz, erSet);
+        erSeqSz = SetSequence(erSetSz + sizeof(erOid) + extSz, erSeq);
+        erSz = extSz + erSetSz + erSeqSz + sizeof(erOid);
+    }
+
+    /* Put the pieces together. */
+    sz += SetLength(cpSz + erSz, &output[sz]);
+
+    if (cpSz) {
+        XMEMCPY(&output[sz], cpSeq, cpSeqSz);
+        sz += cpSeqSz;
+        XMEMCPY(&output[sz], cpOid, sizeof(cpOid));
+        sz += sizeof(cpOid);
+        XMEMCPY(&output[sz], cpSet, cpSetSz);
+        sz += cpSetSz;
+        XMEMCPY(&output[sz], cpStr, cpStrSz);
+        sz += cpStrSz;
+        XMEMCPY(&output[sz], pw, pwSz);
+        sz += pwSz;
+    }
+
+    if (erSz) {
+        XMEMCPY(&output[sz], erSeq, erSeqSz);
+        sz += erSeqSz;
+        XMEMCPY(&output[sz], erOid, sizeof(erOid));
+        sz += sizeof(erOid);
+        XMEMCPY(&output[sz], erSet, erSetSz);
+        sz += erSetSz;
+        /* The actual extension data will be tacked onto the output later. */
+    }
+
+    return sz;
+}
+
+
+/* encode info from cert into DER encoded format */
+static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey,
+                         ecc_key* eccKey, ed25519_key* ed25519Key,
+                         ed448_key* ed448Key)
+{
+    (void)eccKey;
+    (void)ed25519Key;
+    (void)ed448Key;
+
+    if (cert == NULL || der == NULL)
+        return BAD_FUNC_ARG;
+
+    if (rsaKey == NULL && eccKey == NULL && ed25519Key == NULL &&
+                                                             ed448Key == NULL) {
+            return PUBLIC_KEY_E;
+    }
+
+    /* init */
+    XMEMSET(der, 0, sizeof(DerCert));
+
+    /* version */
+    der->versionSz = SetMyVersion(cert->version, der->version, FALSE);
+
+    /* subject name */
+    der->subjectSz = SetName(der->subject, sizeof(der->subject), &cert->subject);
+    if (der->subjectSz <= 0)
+        return SUBJECT_E;
+
+    /* public key */
+#ifndef NO_RSA
+    if (cert->keyType == RSA_KEY) {
+        if (rsaKey == NULL)
+            return PUBLIC_KEY_E;
+        der->publicKeySz = SetRsaPublicKey(der->publicKey, rsaKey,
+                                           sizeof(der->publicKey), 1);
+    }
+#endif
+
+#ifdef HAVE_ECC
+    if (cert->keyType == ECC_KEY) {
+        der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey, 1);
+    }
+#endif
+
+#ifdef HAVE_ED25519
+    if (cert->keyType == ED25519_KEY) {
+        if (ed25519Key == NULL)
+            return PUBLIC_KEY_E;
+        der->publicKeySz = SetEd25519PublicKey(der->publicKey, ed25519Key, 1);
+    }
+#endif
+
+#ifdef HAVE_ED448
+    if (cert->keyType == ED448_KEY) {
+        if (ed448Key == NULL)
+            return PUBLIC_KEY_E;
+        der->publicKeySz = SetEd448PublicKey(der->publicKey, ed448Key, 1);
+    }
+#endif
+    if (der->publicKeySz <= 0)
+        return PUBLIC_KEY_E;
+
+    /* set the extensions */
+    der->extensionsSz = 0;
+
+    /* CA */
+    if (cert->isCA) {
+        der->caSz = SetCa(der->ca, sizeof(der->ca));
+        if (der->caSz <= 0)
+            return CA_TRUE_E;
+
+        der->extensionsSz += der->caSz;
+    }
+    else
+        der->caSz = 0;
+
+#ifdef WOLFSSL_CERT_EXT
+    /* SKID */
+    if (cert->skidSz) {
+        /* check the provided SKID size */
+        if (cert->skidSz > (int)min(CTC_MAX_SKID_SIZE, sizeof(der->skid)))
+            return SKID_E;
+
+        der->skidSz = SetSKID(der->skid, sizeof(der->skid),
+                              cert->skid, cert->skidSz);
+        if (der->skidSz <= 0)
+            return SKID_E;
+
+        der->extensionsSz += der->skidSz;
+    }
+    else
+        der->skidSz = 0;
+
+    /* Key Usage */
+    if (cert->keyUsage != 0){
+        der->keyUsageSz = SetKeyUsage(der->keyUsage, sizeof(der->keyUsage),
+                                      cert->keyUsage);
+        if (der->keyUsageSz <= 0)
+            return KEYUSAGE_E;
+
+        der->extensionsSz += der->keyUsageSz;
+    }
+    else
+        der->keyUsageSz = 0;
+
+    /* Extended Key Usage */
+    if (cert->extKeyUsage != 0){
+        der->extKeyUsageSz = SetExtKeyUsage(cert, der->extKeyUsage,
+                                sizeof(der->extKeyUsage), cert->extKeyUsage);
+        if (der->extKeyUsageSz <= 0)
+            return EXTKEYUSAGE_E;
+
+        der->extensionsSz += der->extKeyUsageSz;
+    }
+    else
+        der->extKeyUsageSz = 0;
+
+#endif /* WOLFSSL_CERT_EXT */
+
+    /* put extensions */
+    if (der->extensionsSz > 0) {
+        int ret;
+
+        /* put the start of sequence (ID, Size) */
+        der->extensionsSz = SetSequence(der->extensionsSz, der->extensions);
+        if (der->extensionsSz <= 0)
+            return EXTENSIONS_E;
+
+        /* put CA */
+        if (der->caSz) {
+            ret = SetExtensions(der->extensions, sizeof(der->extensions),
+                                &der->extensionsSz,
+                                der->ca, der->caSz);
+            if (ret <= 0)
+                return EXTENSIONS_E;
+        }
+
+#ifdef WOLFSSL_CERT_EXT
+        /* put SKID */
+        if (der->skidSz) {
+            ret = SetExtensions(der->extensions, sizeof(der->extensions),
+                                &der->extensionsSz,
+                                der->skid, der->skidSz);
+            if (ret <= 0)
+                return EXTENSIONS_E;
+        }
+
+        /* put AKID */
+        if (der->akidSz) {
+            ret = SetExtensions(der->extensions, sizeof(der->extensions),
+                                &der->extensionsSz,
+                                der->akid, der->akidSz);
+            if (ret <= 0)
+                return EXTENSIONS_E;
+        }
+
+        /* put KeyUsage */
+        if (der->keyUsageSz) {
+            ret = SetExtensions(der->extensions, sizeof(der->extensions),
+                                &der->extensionsSz,
+                                der->keyUsage, der->keyUsageSz);
+            if (ret <= 0)
+                return EXTENSIONS_E;
+        }
+
+        /* put ExtendedKeyUsage */
+        if (der->extKeyUsageSz) {
+            ret = SetExtensions(der->extensions, sizeof(der->extensions),
+                                &der->extensionsSz,
+                                der->extKeyUsage, der->extKeyUsageSz);
+            if (ret <= 0)
+                return EXTENSIONS_E;
+        }
+
+#endif /* WOLFSSL_CERT_EXT */
+    }
+
+    der->attribSz = SetReqAttrib(der->attrib, cert->challengePw,
+                                 cert->challengePwPrintableString,
+                                 der->extensionsSz);
+    if (der->attribSz <= 0)
+        return REQ_ATTRIBUTE_E;
+
+    der->total = der->versionSz + der->subjectSz + der->publicKeySz +
+        der->extensionsSz + der->attribSz;
+
+    return 0;
+}
+
+
+/* write DER encoded cert req to buffer, size already checked */
+static int WriteCertReqBody(DerCert* der, byte* buf)
+{
+    int idx;
+
+    /* signed part header */
+    idx = SetSequence(der->total, buf);
+    /* version */
+    if (buf)
+        XMEMCPY(buf + idx, der->version, der->versionSz);
+    idx += der->versionSz;
+    /* subject */
+    if (buf)
+        XMEMCPY(buf + idx, der->subject, der->subjectSz);
+    idx += der->subjectSz;
+    /* public key */
+    if (buf)
+        XMEMCPY(buf + idx, der->publicKey, der->publicKeySz);
+    idx += der->publicKeySz;
+    /* attributes */
+    if (buf)
+        XMEMCPY(buf + idx, der->attrib, der->attribSz);
+    idx += der->attribSz;
+    /* extensions */
+    if (der->extensionsSz) {
+        if (buf)
+            XMEMCPY(buf + idx, der->extensions, min(der->extensionsSz,
+                                               (int)sizeof(der->extensions)));
+        idx += der->extensionsSz;
+    }
+
+    return idx;
+}
+
+
+static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz,
+                   RsaKey* rsaKey, ecc_key* eccKey, ed25519_key* ed25519Key,
+                   ed448_key* ed448Key)
+{
+    int ret;
+#ifdef WOLFSSL_SMALL_STACK
+    DerCert* der;
+#else
+    DerCert der[1];
+#endif
+
+    cert->keyType = eccKey ? ECC_KEY : (ed25519Key ? ED25519_KEY :
+                                       (ed448Key ? ED448_KEY: RSA_KEY));
+
+#ifdef WOLFSSL_SMALL_STACK
+    der = (DerCert*)XMALLOC(sizeof(DerCert), cert->heap,
+                                                    DYNAMIC_TYPE_TMP_BUFFER);
+    if (der == NULL)
+        return MEMORY_E;
+#endif
+
+    ret = EncodeCertReq(cert, der, rsaKey, eccKey, ed25519Key, ed448Key);
+
+    if (ret == 0) {
+        if (der->total + MAX_SEQ_SZ * 2 > (int)derSz)
+            ret = BUFFER_E;
+        else
+            ret = cert->bodySz = WriteCertReqBody(der, derBuffer);
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(der, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return ret;
+}
+
+int wc_MakeCertReq_ex(Cert* cert, byte* derBuffer, word32 derSz, int keyType,
+                      void* key)
+{
+    RsaKey*      rsaKey = NULL;
+    ecc_key*     eccKey = NULL;
+    ed25519_key* ed25519Key = NULL;
+    ed448_key*   ed448Key = NULL;
+
+    if (keyType == RSA_TYPE)
+        rsaKey = (RsaKey*)key;
+    else if (keyType == ECC_TYPE)
+        eccKey = (ecc_key*)key;
+    else if (keyType == ED25519_TYPE)
+        ed25519Key = (ed25519_key*)key;
+    else if (keyType == ED448_TYPE)
+        ed448Key = (ed448_key*)key;
+
+    return MakeCertReq(cert, derBuffer, derSz, rsaKey, eccKey, ed25519Key,
+                       ed448Key);
+}
+
+int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz,
+                   RsaKey* rsaKey, ecc_key* eccKey)
+{
+    return MakeCertReq(cert, derBuffer, derSz, rsaKey, eccKey, NULL, NULL);
+}
+#endif /* WOLFSSL_CERT_REQ */
+
+
+static int SignCert(int requestSz, int sType, byte* buf, word32 buffSz,
+                    RsaKey* rsaKey, ecc_key* eccKey, ed25519_key* ed25519Key,
+                    ed448_key* ed448Key, WC_RNG* rng)
+{
+    int sigSz = 0;
+    void* heap = NULL;
+    CertSignCtx* certSignCtx;
+#ifndef WOLFSSL_ASYNC_CRYPT
+    CertSignCtx  certSignCtx_lcl;
+
+    certSignCtx = &certSignCtx_lcl;
+    XMEMSET(certSignCtx, 0, sizeof(CertSignCtx));
+#else
+    certSignCtx = NULL;
+#endif
+
+    if (requestSz < 0)
+        return requestSz;
+
+    /* locate ctx */
+    if (rsaKey) {
+    #ifndef NO_RSA
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        certSignCtx = &rsaKey->certSignCtx;
+    #endif
+        heap = rsaKey->heap;
+    #else
+        return NOT_COMPILED_IN;
+    #endif /* NO_RSA */
+    }
+    else if (eccKey) {
+    #ifdef HAVE_ECC
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        certSignCtx = &eccKey->certSignCtx;
+    #endif
+        heap = eccKey->heap;
+    #else
+        return NOT_COMPILED_IN;
+    #endif /* HAVE_ECC */
+    }
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (certSignCtx == NULL) {
+        return BAD_FUNC_ARG;
+    }
+#endif
+
+    if (certSignCtx->sig == NULL) {
+        certSignCtx->sig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, heap,
+            DYNAMIC_TYPE_TMP_BUFFER);
+        if (certSignCtx->sig == NULL)
+            return MEMORY_E;
+    }
+
+    sigSz = MakeSignature(certSignCtx, buf, requestSz, certSignCtx->sig,
+        MAX_ENCODED_SIG_SZ, rsaKey, eccKey, ed25519Key, ed448Key, rng, sType,
+        heap);
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (sigSz == WC_PENDING_E) {
+        /* Not free'ing certSignCtx->sig here because it could still be in use
+         * with async operations. */
+        return sigSz;
+    }
+#endif
+
+    if (sigSz >= 0) {
+        if (requestSz + MAX_SEQ_SZ * 2 + sigSz > (int)buffSz)
+            sigSz = BUFFER_E;
+        else
+            sigSz = AddSignature(buf, requestSz, certSignCtx->sig, sigSz,
+                                 sType);
+    }
+
+    XFREE(certSignCtx->sig, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    certSignCtx->sig = NULL;
+
+    return sigSz;
+}
+
+int wc_SignCert_ex(int requestSz, int sType, byte* buf, word32 buffSz,
+                   int keyType, void* key, WC_RNG* rng)
+{
+    RsaKey*      rsaKey = NULL;
+    ecc_key*     eccKey = NULL;
+    ed25519_key* ed25519Key = NULL;
+    ed448_key*   ed448Key = NULL;
+
+    if (keyType == RSA_TYPE)
+        rsaKey = (RsaKey*)key;
+    else if (keyType == ECC_TYPE)
+        eccKey = (ecc_key*)key;
+    else if (keyType == ED25519_TYPE)
+        ed25519Key = (ed25519_key*)key;
+    else if (keyType == ED448_TYPE)
+        ed448Key = (ed448_key*)key;
+
+    return SignCert(requestSz, sType, buf, buffSz, rsaKey, eccKey, ed25519Key,
+                    ed448Key, rng);
+}
+
+int wc_SignCert(int requestSz, int sType, byte* buf, word32 buffSz,
+                RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng)
+{
+    return SignCert(requestSz, sType, buf, buffSz, rsaKey, eccKey, NULL, NULL,
+                    rng);
+}
+
+int wc_MakeSelfCert(Cert* cert, byte* buf, word32 buffSz,
+                    RsaKey* key, WC_RNG* rng)
+{
+    int ret;
+
+    ret = wc_MakeCert(cert, buf, buffSz, key, NULL, rng);
+    if (ret < 0)
+        return ret;
+
+    return wc_SignCert(cert->bodySz, cert->sigType,
+                       buf, buffSz, key, NULL, rng);
+}
+
+
+#ifdef WOLFSSL_CERT_EXT
+
+/* Get raw subject from cert, which may contain OIDs not parsed by Decode.
+   The raw subject pointer will only be valid while "cert" is valid. */
+int wc_GetSubjectRaw(byte **subjectRaw, Cert *cert)
+{
+    int rc = BAD_FUNC_ARG;
+    if ((subjectRaw != NULL) && (cert != NULL)) {
+        *subjectRaw = cert->sbjRaw;
+        rc = 0;
+    }
+    return rc;
+}
+
+/* Set KID from public key */
+static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey,
+                                 byte *ntruKey, word16 ntruKeySz,
+                                 ed25519_key* ed25519Key, ed448_key* ed448Key,
+                                 int kid_type)
+{
+    byte *buf;
+    int   bufferSz, ret;
+
+    if (cert == NULL ||
+        (rsakey == NULL && eckey == NULL && ntruKey == NULL &&
+                                      ed25519Key == NULL && ed448Key == NULL) ||
+        (kid_type != SKID_TYPE && kid_type != AKID_TYPE))
+        return BAD_FUNC_ARG;
+
+    buf = (byte *)XMALLOC(MAX_PUBLIC_KEY_SZ, cert->heap,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+    if (buf == NULL)
+        return MEMORY_E;
+
+    /* Public Key */
+    bufferSz = -1;
+#ifndef NO_RSA
+    /* RSA public key */
+    if (rsakey != NULL)
+        bufferSz = SetRsaPublicKey(buf, rsakey, MAX_PUBLIC_KEY_SZ, 0);
+#endif
+#ifdef HAVE_ECC
+    /* ECC public key */
+    if (eckey != NULL)
+        bufferSz = SetEccPublicKey(buf, eckey, 0);
+#endif
+#ifdef HAVE_NTRU
+    /* NTRU public key */
+    if (ntruKey != NULL) {
+        bufferSz = MAX_PUBLIC_KEY_SZ;
+        ret = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo(
+                        ntruKeySz, ntruKey, (word16 *)(&bufferSz), buf);
+        if (ret != NTRU_OK)
+            bufferSz = -1;
+    }
+#else
+    (void)ntruKeySz;
+#endif
+#ifdef HAVE_ED25519
+    /* ED25519 public key */
+    if (ed25519Key != NULL)
+        bufferSz = SetEd25519PublicKey(buf, ed25519Key, 0);
+#endif
+#ifdef HAVE_ED448
+    /* ED448 public key */
+    if (ed448Key != NULL)
+        bufferSz = SetEd448PublicKey(buffer, ed448Key, 0);
+#endif
+
+    if (bufferSz <= 0) {
+        XFREE(buf, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return PUBLIC_KEY_E;
+    }
+
+    /* Compute SKID by hashing public key */
+    if (kid_type == SKID_TYPE) {
+        ret = CalcHashId(buf, bufferSz, cert->skid);
+        cert->skidSz = KEYID_SIZE;
+    }
+    else if (kid_type == AKID_TYPE) {
+        ret = CalcHashId(buf, bufferSz, cert->akid);
+        cert->akidSz = KEYID_SIZE;
+    }
+    else
+        ret = BAD_FUNC_ARG;
+
+    XFREE(buf, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    return ret;
+}
+
+int wc_SetSubjectKeyIdFromPublicKey_ex(Cert *cert, int keyType, void* key)
+{
+    RsaKey*      rsaKey = NULL;
+    ecc_key*     eccKey = NULL;
+    ed25519_key* ed25519Key = NULL;
+    ed448_key*   ed448Key = NULL;
+
+    if (keyType == RSA_TYPE)
+        rsaKey = (RsaKey*)key;
+    else if (keyType == ECC_TYPE)
+        eccKey = (ecc_key*)key;
+    else if (keyType == ED25519_TYPE)
+        ed25519Key = (ed25519_key*)key;
+    else if (keyType == ED448_TYPE)
+        ed448Key = (ed448_key*)key;
+
+    return SetKeyIdFromPublicKey(cert, rsaKey, eccKey, NULL, 0, ed25519Key,
+                                 ed448Key, SKID_TYPE);
+}
+
+/* Set SKID from RSA or ECC public key */
+int wc_SetSubjectKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey)
+{
+    return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, 0, NULL, NULL,
+                                 SKID_TYPE);
+}
+
+#ifdef HAVE_NTRU
+/* Set SKID from NTRU public key */
+int wc_SetSubjectKeyIdFromNtruPublicKey(Cert *cert,
+                                        byte *ntruKey, word16 ntruKeySz)
+{
+    return SetKeyIdFromPublicKey(cert, NULL,NULL,ntruKey, ntruKeySz, NULL, NULL,
+                                 SKID_TYPE);
+}
+#endif
+
+int wc_SetAuthKeyIdFromPublicKey_ex(Cert *cert, int keyType, void* key)
+{
+    RsaKey*      rsaKey = NULL;
+    ecc_key*     eccKey = NULL;
+    ed25519_key* ed25519Key = NULL;
+    ed448_key*   ed448Key = NULL;
+
+    if (keyType == RSA_TYPE)
+        rsaKey = (RsaKey*)key;
+    else if (keyType == ECC_TYPE)
+        eccKey = (ecc_key*)key;
+    else if (keyType == ED25519_TYPE)
+        ed25519Key = (ed25519_key*)key;
+    else if (keyType == ED448_TYPE)
+        ed448Key = (ed448_key*)key;
+
+    return SetKeyIdFromPublicKey(cert, rsaKey, eccKey, NULL, 0, ed25519Key,
+                                 ed448Key, AKID_TYPE);
+}
+
+/* Set SKID from RSA or ECC public key */
+int wc_SetAuthKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey)
+{
+    return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, 0, NULL, NULL,
+                                 AKID_TYPE);
+}
+
+
+#if !defined(NO_FILESYSTEM) && !defined(NO_ASN_CRYPT)
+
+/* Set SKID from public key file in PEM */
+int wc_SetSubjectKeyId(Cert *cert, const char* file)
+{
+    int     ret, derSz;
+    byte*   der;
+    word32  idx;
+    RsaKey  *rsakey = NULL;
+    ecc_key *eckey = NULL;
+
+    if (cert == NULL || file == NULL)
+        return BAD_FUNC_ARG;
+
+    der = (byte*)XMALLOC(MAX_PUBLIC_KEY_SZ, cert->heap, DYNAMIC_TYPE_CERT);
+    if (der == NULL) {
+        WOLFSSL_MSG("wc_SetSubjectKeyId memory Problem");
+        return MEMORY_E;
+    }
+    derSz = MAX_PUBLIC_KEY_SZ;
+
+    XMEMSET(der, 0, derSz);
+    derSz = wc_PemPubKeyToDer(file, der, derSz);
+    if (derSz <= 0) {
+        XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+        return derSz;
+    }
+
+    /* Load PubKey in internal structure */
+#ifndef NO_RSA
+    rsakey = (RsaKey*) XMALLOC(sizeof(RsaKey), cert->heap, DYNAMIC_TYPE_RSA);
+    if (rsakey == NULL) {
+        XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+        return MEMORY_E;
+    }
+
+    if (wc_InitRsaKey(rsakey, cert->heap) != 0) {
+        WOLFSSL_MSG("wc_InitRsaKey failure");
+        XFREE(rsakey, cert->heap, DYNAMIC_TYPE_RSA);
+        XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+        return MEMORY_E;
+    }
+
+    idx = 0;
+    ret = wc_RsaPublicKeyDecode(der, &idx, rsakey, derSz);
+    if (ret != 0)
+#endif
+    {
+#ifndef NO_RSA
+        WOLFSSL_MSG("wc_RsaPublicKeyDecode failed");
+        wc_FreeRsaKey(rsakey);
+        XFREE(rsakey, cert->heap, DYNAMIC_TYPE_RSA);
+        rsakey = NULL;
+#endif
+#ifdef HAVE_ECC
+        /* Check to load ecc public key */
+        eckey = (ecc_key*) XMALLOC(sizeof(ecc_key), cert->heap,
+                                                              DYNAMIC_TYPE_ECC);
+        if (eckey == NULL) {
+            XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+            return MEMORY_E;
+        }
+
+        if (wc_ecc_init(eckey) != 0) {
+            WOLFSSL_MSG("wc_ecc_init failure");
+            wc_ecc_free(eckey);
+            XFREE(eckey, cert->heap, DYNAMIC_TYPE_ECC);
+            XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+            return MEMORY_E;
+        }
+
+        idx = 0;
+        ret = wc_EccPublicKeyDecode(der, &idx, eckey, derSz);
+        if (ret != 0) {
+            WOLFSSL_MSG("wc_EccPublicKeyDecode failed");
+            XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+            wc_ecc_free(eckey);
+            XFREE(eckey, cert->heap, DYNAMIC_TYPE_ECC);
+            return PUBLIC_KEY_E;
+        }
+#else
+        XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+        return PUBLIC_KEY_E;
+#endif /* HAVE_ECC */
+    }
+
+    XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+
+    ret = wc_SetSubjectKeyIdFromPublicKey(cert, rsakey, eckey);
+
+#ifndef NO_RSA
+    wc_FreeRsaKey(rsakey);
+    XFREE(rsakey, cert->heap, DYNAMIC_TYPE_RSA);
+#endif
+#ifdef HAVE_ECC
+    wc_ecc_free(eckey);
+    XFREE(eckey, cert->heap, DYNAMIC_TYPE_ECC);
+#endif
+    return ret;
+}
+
+#endif /* !NO_FILESYSTEM && !NO_ASN_CRYPT */
+
+static int SetAuthKeyIdFromDcert(Cert* cert, DecodedCert* decoded)
+{
+    int ret = 0;
+
+    /* Subject Key Id not found !! */
+    if (decoded->extSubjKeyIdSet == 0) {
+        ret = ASN_NO_SKID;
+    }
+
+    /* SKID invalid size */
+    else if (sizeof(cert->akid) < sizeof(decoded->extSubjKeyId)) {
+        ret = MEMORY_E;
+    }
+
+    else {
+        /* Put the SKID of CA to AKID of certificate */
+        XMEMCPY(cert->akid, decoded->extSubjKeyId, KEYID_SIZE);
+        cert->akidSz = KEYID_SIZE;
+    }
+
+    return ret;
+}
+
+/* Set AKID from certificate contains in buffer (DER encoded) */
+int wc_SetAuthKeyIdFromCert(Cert *cert, const byte *der, int derSz)
+{
+    int ret = 0;
+
+    if (cert == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+    else {
+        /* Check if decodedCert is cached */
+        if (cert->der != der) {
+            /* Allocate cache for the decoded cert */
+            ret = wc_SetCert_LoadDer(cert, der, derSz);
+        }
+
+        if (ret >= 0) {
+            ret = SetAuthKeyIdFromDcert(cert, (DecodedCert*)cert->decodedCert);
+#ifndef WOLFSSL_CERT_GEN_CACHE
+            wc_SetCert_Free(cert);
+#endif
+        }
+    }
+
+    return ret;
+}
+
+
+#ifndef NO_FILESYSTEM
+
+/* Set AKID from certificate file in PEM */
+int wc_SetAuthKeyId(Cert *cert, const char* file)
+{
+    int         ret;
+    int         derSz;
+    byte*       der;
+
+    if (cert == NULL || file == NULL)
+        return BAD_FUNC_ARG;
+
+    der = (byte*)XMALLOC(EIGHTK_BUF, cert->heap, DYNAMIC_TYPE_CERT);
+    if (der == NULL) {
+        WOLFSSL_MSG("wc_SetAuthKeyId OOF Problem");
+        return MEMORY_E;
+    }
+
+    derSz = wc_PemCertToDer(file, der, EIGHTK_BUF);
+    if (derSz <= 0)
+    {
+        XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+        return derSz;
+    }
+
+    ret = wc_SetAuthKeyIdFromCert(cert, der, derSz);
+    XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+
+    return ret;
+}
+
+#endif /* !NO_FILESYSTEM */
+
+/* Set KeyUsage from human readable string */
+int wc_SetKeyUsage(Cert *cert, const char *value)
+{
+    int ret = 0;
+    char *token, *str, *ptr;
+    word32 len;
+
+    if (cert == NULL || value == NULL)
+        return BAD_FUNC_ARG;
+
+    cert->keyUsage = 0;
+
+    /* duplicate string (including terminator) */
+    len = (word32)XSTRLEN(value);
+    str = (char*)XMALLOC(len+1, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (str == NULL)
+        return MEMORY_E;
+    XMEMCPY(str, value, len+1);
+
+    /* parse value, and set corresponding Key Usage value */
+    if ((token = XSTRTOK(str, ",", &ptr)) == NULL) {
+        XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return KEYUSAGE_E;
+    }
+    while (token != NULL)
+    {
+        len = (word32)XSTRLEN(token);
+
+        if (!XSTRNCASECMP(token, "digitalSignature", len))
+            cert->keyUsage |= KEYUSE_DIGITAL_SIG;
+        else if (!XSTRNCASECMP(token, "nonRepudiation", len) ||
+                 !XSTRNCASECMP(token, "contentCommitment", len))
+            cert->keyUsage |= KEYUSE_CONTENT_COMMIT;
+        else if (!XSTRNCASECMP(token, "keyEncipherment", len))
+            cert->keyUsage |= KEYUSE_KEY_ENCIPHER;
+        else if (!XSTRNCASECMP(token, "dataEncipherment", len))
+            cert->keyUsage |= KEYUSE_DATA_ENCIPHER;
+        else if (!XSTRNCASECMP(token, "keyAgreement", len))
+            cert->keyUsage |= KEYUSE_KEY_AGREE;
+        else if (!XSTRNCASECMP(token, "keyCertSign", len))
+            cert->keyUsage |= KEYUSE_KEY_CERT_SIGN;
+        else if (!XSTRNCASECMP(token, "cRLSign", len))
+            cert->keyUsage |= KEYUSE_CRL_SIGN;
+        else if (!XSTRNCASECMP(token, "encipherOnly", len))
+            cert->keyUsage |= KEYUSE_ENCIPHER_ONLY;
+        else if (!XSTRNCASECMP(token, "decipherOnly", len))
+            cert->keyUsage |= KEYUSE_DECIPHER_ONLY;
+        else {
+            ret = KEYUSAGE_E;
+            break;
+        }
+
+        token = XSTRTOK(NULL, ",", &ptr);
+    }
+
+    XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    return ret;
+}
+
+/* Set ExtendedKeyUsage from human readable string */
+int wc_SetExtKeyUsage(Cert *cert, const char *value)
+{
+    int ret = 0;
+    char *token, *str, *ptr;
+    word32 len;
+
+    if (cert == NULL || value == NULL)
+        return BAD_FUNC_ARG;
+
+    cert->extKeyUsage = 0;
+
+    /* duplicate string (including terminator) */
+    len = (word32)XSTRLEN(value);
+    str = (char*)XMALLOC(len+1, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (str == NULL)
+        return MEMORY_E;
+    XMEMCPY(str, value, len+1);
+
+    /* parse value, and set corresponding Key Usage value */
+    if ((token = XSTRTOK(str, ",", &ptr)) == NULL) {
+        XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return EXTKEYUSAGE_E;
+    }
+
+    while (token != NULL)
+    {
+        len = (word32)XSTRLEN(token);
+
+        if (!XSTRNCASECMP(token, "any", len))
+            cert->extKeyUsage |= EXTKEYUSE_ANY;
+        else if (!XSTRNCASECMP(token, "serverAuth", len))
+            cert->extKeyUsage |= EXTKEYUSE_SERVER_AUTH;
+        else if (!XSTRNCASECMP(token, "clientAuth", len))
+            cert->extKeyUsage |= EXTKEYUSE_CLIENT_AUTH;
+        else if (!XSTRNCASECMP(token, "codeSigning", len))
+            cert->extKeyUsage |= EXTKEYUSE_CODESIGN;
+        else if (!XSTRNCASECMP(token, "emailProtection", len))
+            cert->extKeyUsage |= EXTKEYUSE_EMAILPROT;
+        else if (!XSTRNCASECMP(token, "timeStamping", len))
+            cert->extKeyUsage |= EXTKEYUSE_TIMESTAMP;
+        else if (!XSTRNCASECMP(token, "OCSPSigning", len))
+            cert->extKeyUsage |= EXTKEYUSE_OCSP_SIGN;
+        else {
+            ret = EXTKEYUSAGE_E;
+            break;
+        }
+
+        token = XSTRTOK(NULL, ",", &ptr);
+    }
+
+    XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    return ret;
+}
+
+#ifdef WOLFSSL_EKU_OID
+/*
+ * cert structure to set EKU oid in
+ * oid  the oid in byte representation
+ * sz   size of oid buffer
+ * idx  index of array to place oid
+ *
+ * returns 0 on success
+ */
+int wc_SetExtKeyUsageOID(Cert *cert, const char *in, word32 sz, byte idx,
+        void* heap)
+{
+    byte oid[MAX_OID_SZ];
+    word32 oidSz = MAX_OID_SZ;
+
+    if (idx >= CTC_MAX_EKU_NB || sz >= CTC_MAX_EKU_OID_SZ) {
+        WOLFSSL_MSG("Either idx or sz was too large");
+        return BAD_FUNC_ARG;
+    }
+
+    if (EncodePolicyOID(oid, &oidSz, in, heap) != 0) {
+        return BUFFER_E;
+    }
+
+    XMEMCPY(cert->extKeyUsageOID[idx], oid, oidSz);
+    cert->extKeyUsageOIDSz[idx] = oidSz;
+    cert->extKeyUsage |= EXTKEYUSE_USER;
+
+    return 0;
+}
+#endif /* WOLFSSL_EKU_OID */
+#endif /* WOLFSSL_CERT_EXT */
+
+
+#ifdef WOLFSSL_ALT_NAMES
+
+static int SetAltNamesFromDcert(Cert* cert, DecodedCert* decoded)
+{
+    int ret = 0;
+    byte tag;
+
+    if (decoded->extensions) {
+        int    length;
+        word32 maxExtensionsIdx;
+
+        decoded->srcIdx = decoded->extensionsIdx;
+        if (GetASNTag(decoded->source, &decoded->srcIdx, &tag, decoded->maxIdx)
+                != 0) {
+            return ASN_PARSE_E;
+        }
+
+        if (tag != ASN_EXTENSIONS) {
+            ret = ASN_PARSE_E;
+        }
+        else if (GetLength(decoded->source, &decoded->srcIdx, &length,
+                                                         decoded->maxIdx) < 0) {
+            ret = ASN_PARSE_E;
+        }
+        else if (GetSequence(decoded->source, &decoded->srcIdx, &length,
+                                                         decoded->maxIdx) < 0) {
+            ret = ASN_PARSE_E;
+        }
+        else {
+            maxExtensionsIdx = decoded->srcIdx + length;
+
+            while (decoded->srcIdx < maxExtensionsIdx) {
+                word32 oid;
+                word32 startIdx = decoded->srcIdx;
+                word32 tmpIdx;
+
+                if (GetSequence(decoded->source, &decoded->srcIdx, &length,
+                            decoded->maxIdx) < 0) {
+                    ret = ASN_PARSE_E;
+                    break;
+                }
+
+                tmpIdx = decoded->srcIdx;
+                decoded->srcIdx = startIdx;
+
+                if (GetAlgoId(decoded->source, &decoded->srcIdx, &oid,
+                              oidCertExtType, decoded->maxIdx) < 0) {
+                    ret = ASN_PARSE_E;
+                    break;
+                }
+
+                if (oid == ALT_NAMES_OID) {
+                    cert->altNamesSz = length + (tmpIdx - startIdx);
+
+                    if (cert->altNamesSz < (int)sizeof(cert->altNames))
+                        XMEMCPY(cert->altNames, &decoded->source[startIdx],
+                                cert->altNamesSz);
+                    else {
+                        cert->altNamesSz = 0;
+                        WOLFSSL_MSG("AltNames extensions too big");
+                        ret = ALT_NAME_E;
+                        break;
+                    }
+                }
+                decoded->srcIdx = tmpIdx + length;
+            }
+        }
+    }
+
+    return ret;
+}
+
+#ifndef NO_FILESYSTEM
+
+/* Set Alt Names from der cert, return 0 on success */
+static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz)
+{
+    int ret;
+#ifdef WOLFSSL_SMALL_STACK
+    DecodedCert* decoded;
+#else
+    DecodedCert decoded[1];
+#endif
+
+    if (derSz < 0)
+        return derSz;
+
+#ifdef WOLFSSL_SMALL_STACK
+    decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cert->heap,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+    if (decoded == NULL)
+        return MEMORY_E;
+#endif
+
+    InitDecodedCert(decoded, der, derSz, NULL);
+    ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0);
+
+    if (ret < 0) {
+        WOLFSSL_MSG("ParseCertRelative error");
+    }
+    else {
+        ret = SetAltNamesFromDcert(cert, decoded);
+    }
+
+    FreeDecodedCert(decoded);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(decoded, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return ret < 0 ? ret : 0;
+}
+
+#endif
+
+static int SetDatesFromDcert(Cert* cert, DecodedCert* decoded)
+{
+    int ret = 0;
+
+    if (decoded->beforeDate == NULL || decoded->afterDate == NULL) {
+        WOLFSSL_MSG("Couldn't extract dates");
+        ret = -1;
+    }
+    else if (decoded->beforeDateLen > MAX_DATE_SIZE ||
+                                        decoded->afterDateLen > MAX_DATE_SIZE) {
+        WOLFSSL_MSG("Bad date size");
+        ret = -1;
+    }
+    else {
+        XMEMCPY(cert->beforeDate, decoded->beforeDate, decoded->beforeDateLen);
+        XMEMCPY(cert->afterDate,  decoded->afterDate,  decoded->afterDateLen);
+
+        cert->beforeDateSz = decoded->beforeDateLen;
+        cert->afterDateSz  = decoded->afterDateLen;
+    }
+
+    return ret;
+}
+
+#endif /* WOLFSSL_ALT_NAMES */
+
+static void SetNameFromDcert(CertName* cn, DecodedCert* decoded)
+{
+    int sz;
+
+    if (decoded->subjectCN) {
+        sz = (decoded->subjectCNLen < CTC_NAME_SIZE) ? decoded->subjectCNLen
+                                                     : CTC_NAME_SIZE - 1;
+        XSTRNCPY(cn->commonName, decoded->subjectCN, sz);
+        cn->commonName[sz] = '\0';
+        cn->commonNameEnc = decoded->subjectCNEnc;
+    }
+    if (decoded->subjectC) {
+        sz = (decoded->subjectCLen < CTC_NAME_SIZE) ? decoded->subjectCLen
+                                                    : CTC_NAME_SIZE - 1;
+        XSTRNCPY(cn->country, decoded->subjectC, sz);
+        cn->country[sz] = '\0';
+        cn->countryEnc = decoded->subjectCEnc;
+    }
+    if (decoded->subjectST) {
+        sz = (decoded->subjectSTLen < CTC_NAME_SIZE) ? decoded->subjectSTLen
+                                                     : CTC_NAME_SIZE - 1;
+        XSTRNCPY(cn->state, decoded->subjectST, sz);
+        cn->state[sz] = '\0';
+        cn->stateEnc = decoded->subjectSTEnc;
+    }
+    if (decoded->subjectL) {
+        sz = (decoded->subjectLLen < CTC_NAME_SIZE) ? decoded->subjectLLen
+                                                    : CTC_NAME_SIZE - 1;
+        XSTRNCPY(cn->locality, decoded->subjectL, sz);
+        cn->locality[sz] = '\0';
+        cn->localityEnc = decoded->subjectLEnc;
+    }
+    if (decoded->subjectO) {
+        sz = (decoded->subjectOLen < CTC_NAME_SIZE) ? decoded->subjectOLen
+                                                    : CTC_NAME_SIZE - 1;
+        XSTRNCPY(cn->org, decoded->subjectO, sz);
+        cn->org[sz] = '\0';
+        cn->orgEnc = decoded->subjectOEnc;
+    }
+    if (decoded->subjectOU) {
+        sz = (decoded->subjectOULen < CTC_NAME_SIZE) ? decoded->subjectOULen
+                                                     : CTC_NAME_SIZE - 1;
+        XSTRNCPY(cn->unit, decoded->subjectOU, sz);
+        cn->unit[sz] = '\0';
+        cn->unitEnc = decoded->subjectOUEnc;
+    }
+    if (decoded->subjectSN) {
+        sz = (decoded->subjectSNLen < CTC_NAME_SIZE) ? decoded->subjectSNLen
+                                                     : CTC_NAME_SIZE - 1;
+        XSTRNCPY(cn->sur, decoded->subjectSN, sz);
+        cn->sur[sz] = '\0';
+        cn->surEnc = decoded->subjectSNEnc;
+    }
+    if (decoded->subjectSND) {
+        sz = (decoded->subjectSNDLen < CTC_NAME_SIZE) ? decoded->subjectSNDLen
+                                                     : CTC_NAME_SIZE - 1;
+        XSTRNCPY(cn->serialDev, decoded->subjectSND, sz);
+        cn->serialDev[sz] = '\0';
+        cn->serialDevEnc = decoded->subjectSNDEnc;
+    }
+#ifdef WOLFSSL_CERT_EXT
+    if (decoded->subjectBC) {
+        sz = (decoded->subjectBCLen < CTC_NAME_SIZE) ? decoded->subjectBCLen
+                                                     : CTC_NAME_SIZE - 1;
+        XSTRNCPY(cn->busCat, decoded->subjectBC, sz);
+        cn->busCat[sz] = '\0';
+        cn->busCatEnc = decoded->subjectBCEnc;
+    }
+    if (decoded->subjectJC) {
+        sz = (decoded->subjectJCLen < CTC_NAME_SIZE) ? decoded->subjectJCLen
+                                                     : CTC_NAME_SIZE - 1;
+        XSTRNCPY(cn->joiC, decoded->subjectJC, sz);
+        cn->joiC[sz] = '\0';
+        cn->joiCEnc = decoded->subjectJCEnc;
+    }
+    if (decoded->subjectJS) {
+        sz = (decoded->subjectJSLen < CTC_NAME_SIZE) ? decoded->subjectJSLen
+                                                     : CTC_NAME_SIZE - 1;
+        XSTRNCPY(cn->joiSt, decoded->subjectJS, sz);
+        cn->joiSt[sz] = '\0';
+        cn->joiStEnc = decoded->subjectJSEnc;
+    }
+#endif
+    if (decoded->subjectEmail) {
+        sz = (decoded->subjectEmailLen < CTC_NAME_SIZE)
+           ?  decoded->subjectEmailLen : CTC_NAME_SIZE - 1;
+        XSTRNCPY(cn->email, decoded->subjectEmail, sz);
+        cn->email[sz] = '\0';
+    }
+}
+
+#ifndef NO_FILESYSTEM
+
+/* Set cn name from der buffer, return 0 on success */
+static int SetNameFromCert(CertName* cn, const byte* der, int derSz)
+{
+    int ret;
+#ifdef WOLFSSL_SMALL_STACK
+    DecodedCert* decoded;
+#else
+    DecodedCert decoded[1];
+#endif
+
+    if (derSz < 0)
+        return derSz;
+
+#ifdef WOLFSSL_SMALL_STACK
+    decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+    if (decoded == NULL)
+        return MEMORY_E;
+#endif
+
+    InitDecodedCert(decoded, der, derSz, NULL);
+    ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0);
+
+    if (ret < 0) {
+        WOLFSSL_MSG("ParseCertRelative error");
+    }
+    else {
+        SetNameFromDcert(cn, decoded);
+    }
+
+    FreeDecodedCert(decoded);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return ret < 0 ? ret : 0;
+}
+
+/* Set cert issuer from issuerFile in PEM */
+int wc_SetIssuer(Cert* cert, const char* issuerFile)
+{
+    int         ret;
+    int         derSz;
+    byte*       der;
+
+    if (cert == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    der = (byte*)XMALLOC(EIGHTK_BUF, cert->heap, DYNAMIC_TYPE_CERT);
+    if (der == NULL) {
+        WOLFSSL_MSG("wc_SetIssuer OOF Problem");
+        return MEMORY_E;
+    }
+    derSz = wc_PemCertToDer(issuerFile, der, EIGHTK_BUF);
+    cert->selfSigned = 0;
+    ret = SetNameFromCert(&cert->issuer, der, derSz);
+    XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+
+    return ret;
+}
+
+
+/* Set cert subject from subjectFile in PEM */
+int wc_SetSubject(Cert* cert, const char* subjectFile)
+{
+    int         ret;
+    int         derSz;
+    byte*       der;
+
+    if (cert == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    der = (byte*)XMALLOC(EIGHTK_BUF, cert->heap, DYNAMIC_TYPE_CERT);
+    if (der == NULL) {
+        WOLFSSL_MSG("wc_SetSubject OOF Problem");
+        return MEMORY_E;
+    }
+
+    derSz = wc_PemCertToDer(subjectFile, der, EIGHTK_BUF);
+    ret = SetNameFromCert(&cert->subject, der, derSz);
+    XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+
+    return ret;
+}
+
+#ifdef WOLFSSL_ALT_NAMES
+
+/* Set alt names from file in PEM */
+int wc_SetAltNames(Cert* cert, const char* file)
+{
+    int         ret;
+    int         derSz;
+    byte*       der;
+
+    if (cert == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    der = (byte*)XMALLOC(EIGHTK_BUF, cert->heap, DYNAMIC_TYPE_CERT);
+    if (der == NULL) {
+        WOLFSSL_MSG("wc_SetAltNames OOF Problem");
+        return MEMORY_E;
+    }
+    derSz = wc_PemCertToDer(file, der, EIGHTK_BUF);
+    ret = SetAltNamesFromCert(cert, der, derSz);
+    XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+
+    return ret;
+}
+
+#endif /* WOLFSSL_ALT_NAMES */
+
+#endif /* !NO_FILESYSTEM */
+
+/* Set cert issuer from DER buffer */
+int wc_SetIssuerBuffer(Cert* cert, const byte* der, int derSz)
+{
+    int ret = 0;
+
+    if (cert == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+    else {
+        cert->selfSigned = 0;
+
+        /* Check if decodedCert is cached */
+        if (cert->der != der) {
+            /* Allocate cache for the decoded cert */
+            ret = wc_SetCert_LoadDer(cert, der, derSz);
+        }
+
+        if (ret >= 0) {
+            SetNameFromDcert(&cert->issuer, (DecodedCert*)cert->decodedCert);
+#ifndef WOLFSSL_CERT_GEN_CACHE
+            wc_SetCert_Free(cert);
+#endif
+        }
+    }
+
+    return ret;
+}
+
+/* Set cert subject from DER buffer */
+int wc_SetSubjectBuffer(Cert* cert, const byte* der, int derSz)
+{
+    int ret = 0;
+
+    if (cert == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+    else {
+        /* Check if decodedCert is cached */
+        if (cert->der != der) {
+            /* Allocate cache for the decoded cert */
+            ret = wc_SetCert_LoadDer(cert, der, derSz);
+        }
+
+        if (ret >= 0) {
+            SetNameFromDcert(&cert->subject, (DecodedCert*)cert->decodedCert);
+#ifndef WOLFSSL_CERT_GEN_CACHE
+            wc_SetCert_Free(cert);
+#endif
+        }
+    }
+
+    return ret;
+}
+#ifdef WOLFSSL_CERT_EXT
+/* Set cert raw subject from DER buffer */
+int wc_SetSubjectRaw(Cert* cert, const byte* der, int derSz)
+{
+    int ret = 0;
+
+    if (cert == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+    else {
+        /* Check if decodedCert is cached */
+        if (cert->der != der) {
+            /* Allocate cache for the decoded cert */
+            ret = wc_SetCert_LoadDer(cert, der, derSz);
+        }
+
+        if (ret >= 0) {
+            if ((((DecodedCert*)cert->decodedCert)->subjectRaw) &&
+                (((DecodedCert*)cert->decodedCert)->subjectRawLen <=
+                        (int)sizeof(CertName))) {
+                XMEMCPY(cert->sbjRaw,
+                        ((DecodedCert*)cert->decodedCert)->subjectRaw,
+                        ((DecodedCert*)cert->decodedCert)->subjectRawLen);
+            }
+#ifndef WOLFSSL_CERT_GEN_CACHE
+            wc_SetCert_Free(cert);
+#endif
+        }
+    }
+
+    return ret;
+}
+
+/* Set cert raw issuer from DER buffer */
+int wc_SetIssuerRaw(Cert* cert, const byte* der, int derSz)
+{
+    int ret = 0;
+
+    if (cert == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+    else {
+        /* Check if decodedCert is cached */
+        if (cert->der != der) {
+            /* Allocate cache for the decoded cert */
+            ret = wc_SetCert_LoadDer(cert, der, derSz);
+        }
+
+        if (ret >= 0) {
+            if ((((DecodedCert*)cert->decodedCert)->issuerRaw) &&
+                (((DecodedCert*)cert->decodedCert)->issuerRawLen <=
+                        (int)sizeof(CertName))) {
+                XMEMCPY(cert->issRaw,
+                        ((DecodedCert*)cert->decodedCert)->issuerRaw,
+                        ((DecodedCert*)cert->decodedCert)->issuerRawLen);
+            }
+#ifndef WOLFSSL_CERT_GEN_CACHE
+            wc_SetCert_Free(cert);
+#endif
+        }
+    }
+    return ret;
+}
+#endif
+
+#ifdef WOLFSSL_ALT_NAMES
+
+/* Set cert alt names from DER buffer */
+int wc_SetAltNamesBuffer(Cert* cert, const byte* der, int derSz)
+{
+    int ret = 0;
+
+    if (cert == NULL) {
+     ret = BAD_FUNC_ARG;
+    }
+    else {
+        /* Check if decodedCert is cached */
+        if (cert->der != der) {
+            /* Allocate cache for the decoded cert */
+            ret = wc_SetCert_LoadDer(cert, der, derSz);
+        }
+
+        if (ret >= 0) {
+            ret = SetAltNamesFromDcert(cert, (DecodedCert*)cert->decodedCert);
+#ifndef WOLFSSL_CERT_GEN_CACHE
+            wc_SetCert_Free(cert);
+#endif
+       }
+    }
+
+    return(ret);
+}
+
+/* Set cert dates from DER buffer */
+int wc_SetDatesBuffer(Cert* cert, const byte* der, int derSz)
+{
+    int ret = 0;
+
+    if (cert == NULL) {
+     ret = BAD_FUNC_ARG;
+    }
+    else {
+        /* Check if decodedCert is cached */
+        if (cert->der != der) {
+            /* Allocate cache for the decoded cert */
+            ret = wc_SetCert_LoadDer(cert, der, derSz);
+        }
+
+        if (ret >= 0) {
+            ret = SetDatesFromDcert(cert, (DecodedCert*)cert->decodedCert);
+#ifndef WOLFSSL_CERT_GEN_CACHE
+            wc_SetCert_Free(cert);
+#endif
+        }
+    }
+
+    return(ret);
+}
+
+#endif /* WOLFSSL_ALT_NAMES */
+
+#endif /* WOLFSSL_CERT_GEN */
+
+#if (defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT)) \
+        || defined(OPENSSL_EXTRA)
+/* Encode OID string representation to ITU-T X.690 format */
+int EncodePolicyOID(byte *out, word32 *outSz, const char *in, void* heap)
+{
+    word32 val, idx = 0, nb_val;
+    char *token, *str, *ptr;
+    word32 len;
+
+    (void)heap;
+
+    if (out == NULL || outSz == NULL || *outSz < 2 || in == NULL)
+        return BAD_FUNC_ARG;
+
+    /* duplicate string (including terminator) */
+    len = (word32)XSTRLEN(in);
+    str = (char *)XMALLOC(len+1, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (str == NULL)
+        return MEMORY_E;
+    XMEMCPY(str, in, len+1);
+
+    nb_val = 0;
+
+    /* parse value, and set corresponding Policy OID value */
+    token = XSTRTOK(str, ".", &ptr);
+    while (token != NULL)
+    {
+        val = (word32)XATOI(token);
+
+        if (nb_val == 0) {
+            if (val > 2) {
+                XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
+                return ASN_OBJECT_ID_E;
+            }
+
+            out[idx] = (byte)(40 * val);
+        }
+        else if (nb_val == 1) {
+            if (val > 127) {
+                XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
+                return ASN_OBJECT_ID_E;
+            }
+
+            if (idx > *outSz) {
+                XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
+                return BUFFER_E;
+            }
+
+            out[idx++] += (byte)val;
+        }
+        else {
+            word32  tb = 0, x;
+            int     i = 0;
+            byte    oid[MAX_OID_SZ];
+
+            while (val >= 128) {
+                x = val % 128;
+                val /= 128;
+                oid[i++] = (byte) (((tb++) ? 0x80 : 0) | x);
+            }
+
+            if ((idx+(word32)i) > *outSz) {
+                XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
+                return BUFFER_E;
+            }
+
+            oid[i] = (byte) (((tb++) ? 0x80 : 0) | val);
+
+            /* push value in the right order */
+            while (i >= 0)
+                out[idx++] = oid[i--];
+        }
+
+        token = XSTRTOK(NULL, ".", &ptr);
+        nb_val++;
+    }
+
+    *outSz = idx;
+
+    XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    return 0;
+}
+#endif /* WOLFSSL_CERT_EXT || OPENSSL_EXTRA */
+
+#endif /* !NO_CERTS */
+
+#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
+/* Helper function for wolfSSL_i2d_DHparams */
+int StoreDHparams(byte* out, word32* outLen, mp_int* p, mp_int* g)
+{
+    word32 idx = 0;
+    int pSz;
+    int gSz;
+    unsigned int tmp;
+    word32 headerSz = 4; /* 2*ASN_TAG + 2*LEN(ENUM) */
+
+    /* If the leading bit on the INTEGER is a 1, add a leading zero */
+    int pLeadingZero = mp_leading_bit(p);
+    int gLeadingZero = mp_leading_bit(g);
+    int pLen = mp_unsigned_bin_size(p);
+    int gLen = mp_unsigned_bin_size(g);
+
+    WOLFSSL_ENTER("StoreDHparams");
+    if (out == NULL) {
+        WOLFSSL_MSG("Null buffer error");
+        return BUFFER_E;
+    }
+
+    tmp = pLeadingZero + gLeadingZero + pLen + gLen;
+    if (*outLen < (tmp + headerSz)) {
+        return BUFFER_E;
+    }
+
+    /* Set sequence */
+    idx = SetSequence(tmp + headerSz + 2, out);
+
+    /* Encode p */
+    pSz = SetASNIntMP(p, -1, &out[idx]);
+    if (pSz < 0) {
+        WOLFSSL_MSG("SetASNIntMP failed");
+        return pSz;
+    }
+    idx += pSz;
+
+    /* Encode g */
+    gSz = SetASNIntMP(g, -1, &out[idx]);
+    if (gSz < 0) {
+        WOLFSSL_MSG("SetASNIntMP failed");
+        return gSz;
+    }
+    idx += gSz;
+
+    *outLen = idx;
+
+    return 0;
+}
+#endif /* !NO_DH && WOLFSSL_QT || OPENSSL_ALL */
+
+#ifdef HAVE_ECC
+
+/* Der Encode r & s ints into out, outLen is (in/out) size */
+int StoreECC_DSA_Sig(byte* out, word32* outLen, mp_int* r, mp_int* s)
+{
+    word32 idx = 0;
+    int    rSz;                           /* encoding size */
+    int    sSz;
+    word32 headerSz = 4;   /* 2*ASN_TAG + 2*LEN(ENUM) */
+
+    /* If the leading bit on the INTEGER is a 1, add a leading zero */
+    int rLeadingZero = mp_leading_bit(r);
+    int sLeadingZero = mp_leading_bit(s);
+    int rLen = mp_unsigned_bin_size(r);   /* big int size */
+    int sLen = mp_unsigned_bin_size(s);
+
+    if (*outLen < (rLen + rLeadingZero + sLen + sLeadingZero +
+                   headerSz + 2))  /* SEQ_TAG + LEN(ENUM) */
+        return BUFFER_E;
+
+    idx = SetSequence(rLen + rLeadingZero + sLen+sLeadingZero + headerSz, out);
+
+    /* store r */
+    rSz = SetASNIntMP(r, -1, &out[idx]);
+    if (rSz < 0)
+        return rSz;
+    idx += rSz;
+
+    /* store s */
+    sSz = SetASNIntMP(s, -1, &out[idx]);
+    if (sSz < 0)
+        return sSz;
+    idx += sSz;
+
+    *outLen = idx;
+
+    return 0;
+}
+
+
+/* Der Decode ECC-DSA Signature, r & s stored as big ints */
+int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen, mp_int* r, mp_int* s)
+{
+    word32 idx = 0;
+    int    len = 0;
+
+    if (GetSequence(sig, &idx, &len, sigLen) < 0) {
+        return ASN_ECC_KEY_E;
+    }
+
+#ifndef NO_STRICT_ECDSA_LEN
+    /* enable strict length checking for signature */
+    if (sigLen != idx + (word32)len) {
+        return ASN_ECC_KEY_E;
+    }
+#else
+    /* allow extra signature bytes at end */
+    if ((word32)len > (sigLen - idx)) {
+        return ASN_ECC_KEY_E;
+    }
+#endif
+
+    if (GetInt(r, sig, &idx, sigLen) < 0) {
+        return ASN_ECC_KEY_E;
+    }
+
+    if (GetInt(s, sig, &idx, sigLen) < 0) {
+        return ASN_ECC_KEY_E;
+    }
+
+    return 0;
+}
+
+
+int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key,
+                        word32 inSz)
+{
+    word32 oidSum;
+    int    version, length;
+    int    privSz, pubSz = 0;
+    byte   b;
+    int    ret = 0;
+    int    curve_id = ECC_CURVE_DEF;
+#ifdef WOLFSSL_SMALL_STACK
+    byte* priv;
+    byte* pub;
+#else
+    byte priv[ECC_MAXSIZE+1];
+    byte pub[2*(ECC_MAXSIZE+1)]; /* public key has two parts plus header */
+#endif
+    byte* pubData = NULL;
+
+    if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0)
+        return BAD_FUNC_ARG;
+
+    if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+        return ASN_PARSE_E;
+
+    if (GetMyVersion(input, inOutIdx, &version, inSz) < 0)
+        return ASN_PARSE_E;
+
+    if (*inOutIdx >= inSz)
+        return ASN_PARSE_E;
+
+    b = input[*inOutIdx];
+    *inOutIdx += 1;
+
+    /* priv type */
+    if (b != 4 && b != 6 && b != 7)
+        return ASN_PARSE_E;
+
+    if (GetLength(input, inOutIdx, &length, inSz) < 0)
+        return ASN_PARSE_E;
+
+    if (length > ECC_MAXSIZE)
+        return BUFFER_E;
+
+#ifdef WOLFSSL_SMALL_STACK
+    priv = (byte*)XMALLOC(ECC_MAXSIZE+1, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (priv == NULL)
+        return MEMORY_E;
+
+    pub = (byte*)XMALLOC(2*(ECC_MAXSIZE+1), key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (pub == NULL) {
+        XFREE(priv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return MEMORY_E;
+    }
+#endif
+
+    /* priv key */
+    privSz = length;
+    XMEMCPY(priv, &input[*inOutIdx], privSz);
+    *inOutIdx += length;
+
+    if ((*inOutIdx + 1) < inSz) {
+        /* prefix 0, may have */
+        b = input[*inOutIdx];
+        if (b == ECC_PREFIX_0) {
+            *inOutIdx += 1;
+
+            if (GetLength(input, inOutIdx, &length, inSz) <= 0)
+                ret = ASN_PARSE_E;
+            else {
+                ret = GetObjectId(input, inOutIdx, &oidSum, oidIgnoreType,
+                                  inSz);
+                if (ret == 0) {
+                    if ((ret = CheckCurve(oidSum)) < 0)
+                        ret = ECC_CURVE_OID_E;
+                    else {
+                        curve_id = ret;
+                        ret = 0;
+                    }
+                }
+            }
+        }
+    }
+
+    if (ret == 0 && (*inOutIdx + 1) < inSz) {
+        /* prefix 1 */
+        b = input[*inOutIdx];
+        *inOutIdx += 1;
+
+        if (b != ECC_PREFIX_1) {
+            ret = ASN_ECC_KEY_E;
+        }
+        else if (GetLength(input, inOutIdx, &length, inSz) <= 0) {
+            ret = ASN_PARSE_E;
+        }
+        else {
+            /* key header */
+            ret = CheckBitString(input, inOutIdx, &length, inSz, 0, NULL);
+            if (ret == 0) {
+                /* pub key */
+                pubSz = length;
+                if (pubSz < 2*(ECC_MAXSIZE+1)) {
+                    XMEMCPY(pub, &input[*inOutIdx], pubSz);
+                    *inOutIdx += length;
+                    pubData = pub;
+                }
+                else
+                    ret = BUFFER_E;
+            }
+        }
+    }
+
+    if (ret == 0) {
+        ret = wc_ecc_import_private_key_ex(priv, privSz, pubData, pubSz, key,
+                                                                      curve_id);
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(priv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(pub,  key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return ret;
+}
+
+
+#ifdef WOLFSSL_CUSTOM_CURVES
+static void ByteToHex(byte n, char* str)
+{
+    const char hexChar[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+                                    '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+
+    str[0] = hexChar[n >> 4];
+    str[1] = hexChar[n & 0xf];
+}
+
+/* returns 0 on success */
+static int ASNToHexString(const byte* input, word32* inOutIdx, char** out,
+                          word32 inSz, void* heap, int heapType)
+{
+    int len;
+    int i;
+    char* str;
+    word32 localIdx;
+    byte   tag;
+
+    if (*inOutIdx >= inSz) {
+        return BUFFER_E;
+    }
+
+    localIdx = *inOutIdx;
+    if (GetASNTag(input, &localIdx, &tag, inSz) == 0 && tag == ASN_INTEGER) {
+        if (GetASNInt(input, inOutIdx, &len, inSz) < 0)
+            return ASN_PARSE_E;
+    }
+    else {
+        if (GetOctetString(input, inOutIdx, &len, inSz) < 0)
+            return ASN_PARSE_E;
+    }
+
+    str = (char*)XMALLOC(len * 2 + 1, heap, heapType);
+    for (i=0; i<len; i++)
+        ByteToHex(input[*inOutIdx + i], str + i*2);
+    str[len*2] = '\0';
+
+    *inOutIdx += len;
+    *out = str;
+
+    (void)heap;
+    (void)heapType;
+
+    return 0;
+}
+#endif /* WOLFSSL_CUSTOM_CURVES */
+
+#ifdef WOLFSSL_CUSTOM_CURVES
+static int EccKeyParamCopy(char** dst, char* src)
+{
+    int ret = 0;
+#ifdef WOLFSSL_ECC_CURVE_STATIC
+    word32 length;
+#endif
+
+    if (dst == NULL || src == NULL)
+        return BAD_FUNC_ARG;
+
+#ifndef WOLFSSL_ECC_CURVE_STATIC
+    *dst = src;
+#else
+    length = (int)XSTRLEN(src) + 1;
+    if (length > MAX_ECC_STRING) {
+        WOLFSSL_MSG("ECC Param too large for buffer");
+        ret = BUFFER_E;
+    }
+    else {
+        XSTRNCPY(*dst, src, length);
+    }
+    XFREE(src, key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+#endif
+
+    return ret;
+}
+#endif /* WOLFSSL_CUSTOM_CURVES */
+
+int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx,
+                          ecc_key* key, word32 inSz)
+{
+    int    length;
+    int    ret;
+    int    curve_id = ECC_CURVE_DEF;
+    word32 oidSum, localIdx;
+    byte   tag;
+
+    if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0)
+        return BAD_FUNC_ARG;
+
+    if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+        return ASN_PARSE_E;
+
+    if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+        return ASN_PARSE_E;
+
+    ret = SkipObjectId(input, inOutIdx, inSz);
+    if (ret != 0)
+        return ret;
+
+    if (*inOutIdx >= inSz) {
+        return BUFFER_E;
+    }
+
+    localIdx = *inOutIdx;
+    if (GetASNTag(input, &localIdx, &tag, inSz) == 0 &&
+            tag == (ASN_SEQUENCE | ASN_CONSTRUCTED)) {
+#ifdef WOLFSSL_CUSTOM_CURVES
+        ecc_set_type* curve;
+        int len;
+        char* point = NULL;
+
+        ret = 0;
+
+        curve = (ecc_set_type*)XMALLOC(sizeof(*curve), key->heap,
+                                                       DYNAMIC_TYPE_ECC_BUFFER);
+        if (curve == NULL)
+            ret = MEMORY_E;
+
+        if (ret == 0) {
+            static const char customName[] = "Custom";
+            XMEMSET(curve, 0, sizeof(*curve));
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            curve->name = customName;
+        #else
+            XMEMCPY((void*)curve->name, customName, sizeof(customName));
+        #endif
+            curve->id = ECC_CURVE_CUSTOM;
+
+            if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+                ret = ASN_PARSE_E;
+        }
+
+        if (ret == 0) {
+            GetInteger7Bit(input, inOutIdx, inSz);
+            if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+                ret = ASN_PARSE_E;
+        }
+        if (ret == 0) {
+            char* p = NULL;
+            SkipObjectId(input, inOutIdx, inSz);
+            ret = ASNToHexString(input, inOutIdx, &p, inSz,
+                                            key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+            if (ret == 0)
+                ret = EccKeyParamCopy((char**)&curve->prime, p);
+        }
+        if (ret == 0) {
+            curve->size = (int)XSTRLEN(curve->prime) / 2;
+
+            if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+                ret = ASN_PARSE_E;
+        }
+        if (ret == 0) {
+            char* af = NULL;
+            ret = ASNToHexString(input, inOutIdx, &af, inSz,
+                                            key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+            if (ret == 0)
+                ret = EccKeyParamCopy((char**)&curve->Af, af);
+        }
+        if (ret == 0) {
+            char* bf = NULL;
+            ret = ASNToHexString(input, inOutIdx, &bf, inSz,
+                                            key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+            if (ret == 0)
+                ret = EccKeyParamCopy((char**)&curve->Bf, bf);
+        }
+        if (ret == 0) {
+            localIdx = *inOutIdx;
+            if (*inOutIdx < inSz && GetASNTag(input, &localIdx, &tag, inSz)
+                    == 0 && tag == ASN_BIT_STRING) {
+                len = 0;
+                ret = GetASNHeader(input, ASN_BIT_STRING, inOutIdx, &len, inSz);
+                *inOutIdx += len;
+            }
+        }
+        if (ret == 0) {
+            ret = ASNToHexString(input, inOutIdx, (char**)&point, inSz,
+                                            key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+
+            /* sanity check that point buffer is not smaller than the expected
+             * size to hold ( 0 4 || Gx || Gy )
+             * where Gx and Gy are each the size of curve->size * 2 */
+            if (ret == 0 && (int)XSTRLEN(point) < (curve->size * 4) + 2) {
+                XFREE(point, key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+                ret = BUFFER_E;
+            }
+        }
+        if (ret == 0) {
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            curve->Gx = (const char*)XMALLOC(curve->size * 2 + 2, key->heap,
+                                                       DYNAMIC_TYPE_ECC_BUFFER);
+            curve->Gy = (const char*)XMALLOC(curve->size * 2 + 2, key->heap,
+                                                       DYNAMIC_TYPE_ECC_BUFFER);
+            if (curve->Gx == NULL || curve->Gy == NULL) {
+                XFREE(point, key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+                ret = MEMORY_E;
+            }
+        #else
+            if (curve->size * 2 + 2 > MAX_ECC_STRING) {
+                WOLFSSL_MSG("curve size is too large to fit in buffer");
+                ret = BUFFER_E;
+            }
+        #endif
+        }
+        if (ret == 0) {
+            char* o = NULL;
+
+            XMEMCPY((char*)curve->Gx, point + 2, curve->size * 2);
+            XMEMCPY((char*)curve->Gy, point + curve->size * 2 + 2,
+                                                               curve->size * 2);
+            ((char*)curve->Gx)[curve->size * 2] = '\0';
+            ((char*)curve->Gy)[curve->size * 2] = '\0';
+            XFREE(point, key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+            ret = ASNToHexString(input, inOutIdx, &o, inSz,
+                                            key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+            if (ret == 0)
+                ret = EccKeyParamCopy((char**)&curve->order, o);
+        }
+        if (ret == 0) {
+            curve->cofactor = GetInteger7Bit(input, inOutIdx, inSz);
+
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            curve->oid = NULL;
+        #else
+            XMEMSET((void*)curve->oid, 0, sizeof(curve->oid));
+        #endif
+            curve->oidSz = 0;
+            curve->oidSum = 0;
+
+            if (wc_ecc_set_custom_curve(key, curve) < 0) {
+                ret = ASN_PARSE_E;
+            }
+        #ifdef WOLFSSL_CUSTOM_CURVES
+            key->deallocSet = 1;
+        #endif
+            curve = NULL;
+        }
+        if (curve != NULL)
+            wc_ecc_free_curve(curve, key->heap);
+
+        if (ret < 0)
+            return ret;
+#else
+        return ASN_PARSE_E;
+#endif /* WOLFSSL_CUSTOM_CURVES */
+    }
+    else {
+        /* ecc params information */
+        ret = GetObjectId(input, inOutIdx, &oidSum, oidIgnoreType, inSz);
+        if (ret != 0)
+            return ret;
+
+        /* get curve id */
+        curve_id = wc_ecc_get_oid(oidSum, NULL, 0);
+        if (curve_id < 0)
+            return ECC_CURVE_OID_E;
+    }
+
+    /* key header */
+    ret = CheckBitString(input, inOutIdx, &length, inSz, 1, NULL);
+    if (ret != 0)
+        return ret;
+
+    /* This is the raw point data compressed or uncompressed. */
+    if (wc_ecc_import_x963_ex(input + *inOutIdx, length, key,
+                                                            curve_id) != 0) {
+        return ASN_ECC_KEY_E;
+    }
+
+    *inOutIdx += length;
+
+    return 0;
+}
+
+#if defined(HAVE_ECC_KEY_EXPORT) && !defined(NO_ASN_CRYPT)
+/* build DER formatted ECC key, include optional public key if requested,
+ * return length on success, negative on error */
+static int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 inLen,
+                             int pubIn)
+{
+    byte   curve[MAX_ALGO_SZ+2];
+    byte   ver[MAX_VERSION_SZ];
+    byte   seq[MAX_SEQ_SZ];
+    byte   *prv = NULL, *pub = NULL;
+    int    ret, totalSz, curveSz, verSz;
+    int    privHdrSz  = ASN_ECC_HEADER_SZ;
+    int    pubHdrSz   = ASN_ECC_CONTEXT_SZ + ASN_ECC_HEADER_SZ;
+
+    word32 idx = 0, prvidx = 0, pubidx = 0, curveidx = 0;
+    word32 seqSz, privSz, pubSz = ECC_BUFSIZE;
+
+    if (key == NULL || output == NULL || inLen == 0)
+        return BAD_FUNC_ARG;
+
+    /* curve */
+    curve[curveidx++] = ECC_PREFIX_0;
+    curveidx++ /* to put the size after computation */;
+    curveSz = SetCurve(key, curve+curveidx);
+    if (curveSz < 0)
+        return curveSz;
+    /* set computed size */
+    curve[1] = (byte)curveSz;
+    curveidx += curveSz;
+
+    /* private */
+    privSz = key->dp->size;
+    prv = (byte*)XMALLOC(privSz + privHdrSz + MAX_SEQ_SZ,
+                         key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (prv == NULL) {
+        return MEMORY_E;
+    }
+    prvidx += SetOctetString8Bit(key->dp->size, &prv[prvidx]);
+    ret = wc_ecc_export_private_only(key, prv + prvidx, &privSz);
+    if (ret < 0) {
+        XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return ret;
+    }
+    prvidx += privSz;
+
+    /* pubIn */
+    if (pubIn) {
+        ret = wc_ecc_export_x963(key, NULL, &pubSz);
+        if (ret != LENGTH_ONLY_E) {
+            XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            return ret;
+        }
+
+        pub = (byte*)XMALLOC(pubSz + pubHdrSz + MAX_SEQ_SZ,
+                             key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        if (pub == NULL) {
+            XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            return MEMORY_E;
+        }
+
+        pub[pubidx++] = ECC_PREFIX_1;
+        if (pubSz > 128) /* leading zero + extra size byte */
+            pubidx += SetLength(pubSz + ASN_ECC_CONTEXT_SZ + 2, pub+pubidx);
+        else /* leading zero */
+            pubidx += SetLength(pubSz + ASN_ECC_CONTEXT_SZ + 1, pub+pubidx);
+
+        /* SetBitString adds leading zero */
+        pubidx += SetBitString(pubSz, 0, pub + pubidx);
+        ret = wc_ecc_export_x963(key, pub + pubidx, &pubSz);
+        if (ret != 0) {
+            XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            return ret;
+        }
+        pubidx += pubSz;
+    }
+
+    /* make headers */
+    verSz = SetMyVersion(1, ver, FALSE);
+    seqSz = SetSequence(verSz + prvidx + pubidx + curveidx, seq);
+
+    totalSz = prvidx + pubidx + curveidx + verSz + seqSz;
+    if (totalSz > (int)inLen) {
+        XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        if (pubIn) {
+            XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        }
+        return BAD_FUNC_ARG;
+    }
+
+    /* write out */
+    /* seq */
+    XMEMCPY(output + idx, seq, seqSz);
+    idx = seqSz;
+
+    /* ver */
+    XMEMCPY(output + idx, ver, verSz);
+    idx += verSz;
+
+    /* private */
+    XMEMCPY(output + idx, prv, prvidx);
+    idx += prvidx;
+    XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+    /* curve */
+    XMEMCPY(output + idx, curve, curveidx);
+    idx += curveidx;
+
+    /* pubIn */
+    if (pubIn) {
+        XMEMCPY(output + idx, pub, pubidx);
+        /* idx += pubidx;  not used after write, if more data remove comment */
+        XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+
+    return totalSz;
+}
+
+/* Write a Private ecc key, including public to DER format,
+ * length on success else < 0 */
+int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen)
+{
+    return wc_BuildEccKeyDer(key, output, inLen, 1);
+}
+
+
+/* Write only private ecc key to DER format,
+ * length on success else < 0 */
+int wc_EccPrivateKeyToDer(ecc_key* key, byte* output, word32 inLen)
+{
+    return wc_BuildEccKeyDer(key, output, inLen, 0);
+}
+
+#ifdef HAVE_PKCS8
+/* Write only private ecc key to unencrypted PKCS#8 format.
+ *
+ * If output is NULL, places required PKCS#8 buffer size in outLen and
+ * returns LENGTH_ONLY_E.
+ *
+ * return length on success else < 0 */
+int wc_EccPrivateKeyToPKCS8(ecc_key* key, byte* output, word32* outLen)
+{
+    int ret, tmpDerSz;
+    int algoID = 0;
+    word32 oidSz = 0;
+    word32 pkcs8Sz = 0;
+    const byte* curveOID = NULL;
+    byte* tmpDer = NULL;
+
+    if (key == NULL || outLen == NULL)
+        return BAD_FUNC_ARG;
+
+    /* set algoID, get curve OID */
+    algoID = ECDSAk;
+    ret = wc_ecc_get_oid(key->dp->oidSum, &curveOID, &oidSz);
+    if (ret < 0)
+        return ret;
+
+    /* temp buffer for plain DER key */
+    tmpDer = (byte*)XMALLOC(ECC_BUFSIZE, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (tmpDer == NULL)
+        return MEMORY_E;
+
+    XMEMSET(tmpDer, 0, ECC_BUFSIZE);
+
+    tmpDerSz = wc_BuildEccKeyDer(key, tmpDer, ECC_BUFSIZE, 0);
+    if (tmpDerSz < 0) {
+        XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return tmpDerSz;
+    }
+
+    /* get pkcs8 expected output size */
+    ret = wc_CreatePKCS8Key(NULL, &pkcs8Sz, tmpDer, tmpDerSz, algoID,
+                            curveOID, oidSz);
+    if (ret != LENGTH_ONLY_E) {
+        XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return ret;
+    }
+
+    if (output == NULL) {
+        XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        *outLen = pkcs8Sz;
+        return LENGTH_ONLY_E;
+
+    } else if (*outLen < pkcs8Sz) {
+        XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        WOLFSSL_MSG("Input buffer too small for ECC PKCS#8 key");
+        return BUFFER_E;
+    }
+
+    ret = wc_CreatePKCS8Key(output, &pkcs8Sz, tmpDer, tmpDerSz,
+                            algoID, curveOID, oidSz);
+    if (ret < 0) {
+        XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return ret;
+    }
+
+    XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+    *outLen = ret;
+    return ret;
+}
+#endif /* HAVE_PKCS8 */
+#endif /* HAVE_ECC_KEY_EXPORT && !NO_ASN_CRYPT */
+#endif /* HAVE_ECC */
+
+
+#ifdef HAVE_ED25519
+
+int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx,
+                               ed25519_key* key, word32 inSz)
+{
+    word32      oid;
+    int         ret, version, length, endKeyIdx, privSz, pubSz;
+    const byte* priv;
+    const byte* pub;
+
+    if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0)
+        return BAD_FUNC_ARG;
+
+    if (GetSequence(input, inOutIdx, &length, inSz) >= 0) {
+        endKeyIdx = *inOutIdx + length;
+
+        if (GetMyVersion(input, inOutIdx, &version, inSz) < 0)
+            return ASN_PARSE_E;
+        if (version != 0) {
+            WOLFSSL_MSG("Unrecognized version of ED25519 private key");
+            return ASN_PARSE_E;
+        }
+
+        if (GetAlgoId(input, inOutIdx, &oid, oidKeyType, inSz) < 0)
+            return ASN_PARSE_E;
+        if (oid != ED25519k)
+            return ASN_PARSE_E;
+
+        if (GetOctetString(input, inOutIdx, &length, inSz) < 0)
+            return ASN_PARSE_E;
+
+        if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0)
+            return ASN_PARSE_E;
+
+        priv = input + *inOutIdx;
+        *inOutIdx += privSz;
+    }
+    else {
+        if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0)
+            return ASN_PARSE_E;
+
+        if (privSz != 32)
+            return ASN_PARSE_E;
+
+        priv = input + *inOutIdx;
+        *inOutIdx += privSz;
+        endKeyIdx = *inOutIdx;
+    }
+
+    if (endKeyIdx == (int)*inOutIdx) {
+        ret = wc_ed25519_import_private_only(priv, privSz, key);
+    }
+    else {
+        if (GetASNHeader(input, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1,
+                         inOutIdx, &length, inSz) < 0) {
+            return ASN_PARSE_E;
+        }
+        if (GetOctetString(input, inOutIdx, &pubSz, inSz) < 0)
+            return ASN_PARSE_E;
+        pub = input + *inOutIdx;
+        *inOutIdx += pubSz;
+
+        ret = wc_ed25519_import_private_key(priv, privSz, pub, pubSz, key);
+    }
+    if (ret == 0 && endKeyIdx != (int)*inOutIdx)
+        return ASN_PARSE_E;
+
+    return ret;
+}
+
+
+int wc_Ed25519PublicKeyDecode(const byte* input, word32* inOutIdx,
+                              ed25519_key* key, word32 inSz)
+{
+    int    length;
+    int    ret;
+
+    if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0)
+        return BAD_FUNC_ARG;
+
+    if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+        return ASN_PARSE_E;
+
+    if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+        return ASN_PARSE_E;
+
+    ret = SkipObjectId(input, inOutIdx, inSz);
+    if (ret != 0)
+        return ret;
+
+    /* key header */
+    ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL);
+    if (ret != 0)
+        return ret;
+
+    /* This is the raw point data compressed or uncompressed. */
+    if (wc_ed25519_import_public(input + *inOutIdx, inSz - *inOutIdx, key) != 0)
+        return ASN_ECC_KEY_E;
+
+    return 0;
+}
+
+
+#ifdef WOLFSSL_KEY_GEN
+
+/* build DER formatted ED25519 key,
+ * return length on success, negative on error */
+static int wc_BuildEd25519KeyDer(ed25519_key* key, byte* output, word32 inLen,
+                                 int pubOut)
+{
+    byte   algoArray[MAX_ALGO_SZ];
+    byte   ver[MAX_VERSION_SZ];
+    byte   seq[MAX_SEQ_SZ];
+    int    ret;
+    word32 idx = 0, seqSz, verSz, algoSz, privSz, pubSz = 0;
+
+    if (key == NULL || output == NULL || inLen == 0)
+        return BAD_FUNC_ARG;
+
+    if (pubOut)
+        pubSz = 2 + 2 + ED25519_PUB_KEY_SIZE;
+    privSz = 2 + 2 + ED25519_KEY_SIZE;
+    algoSz = SetAlgoID(ED25519k, algoArray, oidKeyType, 0);
+    verSz  = SetMyVersion(0, ver, FALSE);
+    seqSz  = SetSequence(verSz + algoSz + privSz + pubSz, seq);
+
+    if (seqSz + verSz + algoSz + privSz + pubSz > inLen)
+        return BAD_FUNC_ARG;
+
+    /* write out */
+    /* seq */
+    XMEMCPY(output + idx, seq, seqSz);
+    idx = seqSz;
+    /* ver */
+    XMEMCPY(output + idx, ver, verSz);
+    idx += verSz;
+    /* algo */
+    XMEMCPY(output + idx, algoArray, algoSz);
+    idx += algoSz;
+    /* privKey */
+    idx += SetOctetString(2 + ED25519_KEY_SIZE, output + idx);
+    idx += SetOctetString(ED25519_KEY_SIZE, output + idx);
+    ret = wc_ed25519_export_private_only(key, output + idx, &privSz);
+    if (ret != 0)
+        return ret;
+    idx += privSz;
+    /* pubKey */
+    if (pubOut) {
+        idx += SetExplicit(1, 2 + ED25519_PUB_KEY_SIZE, output + idx);
+        idx += SetOctetString(ED25519_KEY_SIZE, output + idx);
+        ret = wc_ed25519_export_public(key, output + idx, &pubSz);
+        if (ret != 0)
+            return ret;
+        idx += pubSz;
+    }
+
+    return idx;
+}
+
+/* Write a Private ecc key, including public to DER format,
+ * length on success else < 0 */
+int wc_Ed25519KeyToDer(ed25519_key* key, byte* output, word32 inLen)
+{
+    return wc_BuildEd25519KeyDer(key, output, inLen, 1);
+}
+
+
+
+/* Write only private ecc key to DER format,
+ * length on success else < 0 */
+int wc_Ed25519PrivateKeyToDer(ed25519_key* key, byte* output, word32 inLen)
+{
+    return wc_BuildEd25519KeyDer(key, output, inLen, 0);
+}
+
+#endif /* WOLFSSL_KEY_GEN */
+
+#endif /* HAVE_ED25519 */
+
+#ifdef HAVE_ED448
+
+int wc_Ed448PrivateKeyDecode(const byte* input, word32* inOutIdx,
+                             ed448_key* key, word32 inSz)
+{
+    word32      oid;
+    int         ret, version, length, endKeyIdx, privSz, pubSz;
+    const byte* priv;
+    const byte* pub;
+
+    if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0)
+        return BAD_FUNC_ARG;
+
+    if (GetSequence(input, inOutIdx, &length, inSz) >= 0) {
+        endKeyIdx = *inOutIdx + length;
+
+        if (GetMyVersion(input, inOutIdx, &version, inSz) < 0)
+            return ASN_PARSE_E;
+        if (version != 0) {
+            WOLFSSL_MSG("Unrecognized version of ED448 private key");
+            return ASN_PARSE_E;
+        }
+
+        if (GetAlgoId(input, inOutIdx, &oid, oidKeyType, inSz) < 0)
+            return ASN_PARSE_E;
+        if (oid != ED448k)
+            return ASN_PARSE_E;
+
+        if (GetOctetString(input, inOutIdx, &length, inSz) < 0)
+            return ASN_PARSE_E;
+
+        if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0)
+            return ASN_PARSE_E;
+
+        priv = input + *inOutIdx;
+        *inOutIdx += privSz;
+    }
+    else {
+        if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0)
+            return ASN_PARSE_E;
+
+        if (privSz != 57)
+            return ASN_PARSE_E;
+
+        priv = input + *inOutIdx;
+        *inOutIdx += privSz;
+        endKeyIdx = *inOutIdx;
+    }
+
+    if (endKeyIdx == (int)*inOutIdx) {
+        ret = wc_ed448_import_private_only(priv, privSz, key);
+    }
+    else {
+        if (GetASNHeader(input, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1,
+                         inOutIdx, &length, inSz) < 0) {
+            return ASN_PARSE_E;
+        }
+        if (GetOctetString(input, inOutIdx, &pubSz, inSz) < 0)
+            return ASN_PARSE_E;
+        pub = input + *inOutIdx;
+        *inOutIdx += pubSz;
+
+        ret = wc_ed448_import_private_key(priv, privSz, pub, pubSz, key);
+    }
+    if (ret == 0 && endKeyIdx != (int)*inOutIdx)
+        return ASN_PARSE_E;
+
+    return ret;
+}
+
+
+int wc_Ed448PublicKeyDecode(const byte* input, word32* inOutIdx,
+                            ed448_key* key, word32 inSz)
+{
+    int    length;
+    int    ret;
+
+    if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0)
+        return BAD_FUNC_ARG;
+
+    if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+        return ASN_PARSE_E;
+
+    if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+        return ASN_PARSE_E;
+
+    ret = SkipObjectId(input, inOutIdx, inSz);
+    if (ret != 0)
+        return ret;
+
+    /* key header */
+    ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL);
+    if (ret != 0)
+        return ret;
+
+    /* This is the raw point data compressed or uncompressed. */
+    if (wc_ed448_import_public(input + *inOutIdx, inSz - *inOutIdx, key) != 0)
+        return ASN_ECC_KEY_E;
+
+    return 0;
+}
+
+
+#ifdef WOLFSSL_KEY_GEN
+
+/* build DER formatted ED448 key,
+ * return length on success, negative on error */
+static int wc_BuildEd448KeyDer(ed448_key* key, byte* output, word32 inLen,
+                               int pubOut)
+{
+    byte   algoArray[MAX_ALGO_SZ];
+    byte   ver[MAX_VERSION_SZ];
+    byte   seq[MAX_SEQ_SZ];
+    int    ret;
+    word32 idx = 0, seqSz, verSz, algoSz, privSz, pubSz = 0;
+
+    if (key == NULL || output == NULL || inLen == 0)
+        return BAD_FUNC_ARG;
+
+    if (pubOut) {
+        pubSz = 2 + 2 + ED448_PUB_KEY_SIZE;
+    }
+    privSz = 2 + 2 + ED448_KEY_SIZE;
+    algoSz = SetAlgoID(ED448k, algoArray, oidKeyType, 0);
+    verSz  = SetMyVersion(0, ver, FALSE);
+    seqSz  = SetSequence(verSz + algoSz + privSz + pubSz, seq);
+
+    if (seqSz + verSz + algoSz + privSz + pubSz > inLen)
+        return BAD_FUNC_ARG;
+
+    /* write out */
+    /* seq */
+    XMEMCPY(output + idx, seq, seqSz);
+    idx = seqSz;
+    /* ver */
+    XMEMCPY(output + idx, ver, verSz);
+    idx += verSz;
+    /* algo */
+    XMEMCPY(output + idx, algoArray, algoSz);
+    idx += algoSz;
+    /* privKey */
+    idx += SetOctetString(2 + ED448_KEY_SIZE, output + idx);
+    idx += SetOctetString(ED448_KEY_SIZE, output + idx);
+    ret = wc_ed448_export_private_only(key, output + idx, &privSz);
+    if (ret != 0)
+        return ret;
+    idx += privSz;
+    /* pubKey */
+    if (pubOut) {
+        idx += SetExplicit(1, 2 + ED448_PUB_KEY_SIZE, output + idx);
+        idx += SetOctetString(ED448_KEY_SIZE, output + idx);
+        ret = wc_ed448_export_public(key, output + idx, &pubSz);
+        if (ret != 0)
+            return ret;
+        idx += pubSz;
+    }
+
+    return idx;
+}
+
+/* Write a Private ecc key, including public to DER format,
+ * length on success else < 0 */
+int wc_Ed448KeyToDer(ed448_key* key, byte* output, word32 inLen)
+{
+    return wc_BuildEd448KeyDer(key, output, inLen, 1);
+}
+
+
+
+/* Write only private ecc key to DER format,
+ * length on success else < 0 */
+int wc_Ed448PrivateKeyToDer(ed448_key* key, byte* output, word32 inLen)
+{
+    return wc_BuildEd448KeyDer(key, output, inLen, 0);
+}
+
+#endif /* WOLFSSL_KEY_GEN */
+
+#endif /* HAVE_ED448 */
+
+#if defined(HAVE_OCSP) || defined(HAVE_CRL)
+
+/* Get raw Date only, no processing, 0 on success */
+static int GetBasicDate(const byte* source, word32* idx, byte* date,
+                        byte* format, int maxIdx)
+{
+    int    ret, length;
+    const byte *datePtr = NULL;
+
+    WOLFSSL_ENTER("GetBasicDate");
+
+    ret = GetDateInfo(source, idx, &datePtr, format, &length, maxIdx);
+    if (ret < 0)
+        return ret;
+
+    XMEMCPY(date, datePtr, length);
+
+    return 0;
+}
+
+#endif /* HAVE_OCSP || HAVE_CRL */
+
+
+#ifdef HAVE_OCSP
+
+static int GetEnumerated(const byte* input, word32* inOutIdx, int *value,
+        int sz)
+{
+    word32 idx = *inOutIdx;
+    word32 len;
+    byte   tag;
+
+    WOLFSSL_ENTER("GetEnumerated");
+
+    *value = 0;
+
+    if (GetASNTag(input, &idx, &tag, sz) < 0)
+        return ASN_PARSE_E;
+
+    if (tag != ASN_ENUMERATED)
+        return ASN_PARSE_E;
+
+    if ((int)idx >= sz)
+        return BUFFER_E;
+
+    len = input[idx++];
+    if (len > 4 || (int)(len + idx) > sz)
+        return ASN_PARSE_E;
+
+    while (len--) {
+        *value  = *value << 8 | input[idx++];
+    }
+
+    *inOutIdx = idx;
+
+    return *value;
+}
+
+
+static int DecodeSingleResponse(byte* source,
+                            word32* ioIndex, OcspResponse* resp, word32 size)
+{
+    word32 idx = *ioIndex, prevIndex, oid, localIdx;
+    int length, wrapperSz;
+    CertStatus* cs = resp->status;
+    int ret;
+    byte tag;
+
+    WOLFSSL_ENTER("DecodeSingleResponse");
+
+    /* Outer wrapper of the SEQUENCE OF Single Responses. */
+    if (GetSequence(source, &idx, &wrapperSz, size) < 0)
+        return ASN_PARSE_E;
+
+    prevIndex = idx;
+
+    /* When making a request, we only request one status on one certificate
+     * at a time. There should only be one SingleResponse */
+
+    /* Wrapper around the Single Response */
+    if (GetSequence(source, &idx, &length, size) < 0)
+        return ASN_PARSE_E;
+
+    /* Wrapper around the CertID */
+    if (GetSequence(source, &idx, &length, size) < 0)
+        return ASN_PARSE_E;
+    /* Skip the hash algorithm */
+    if (GetAlgoId(source, &idx, &oid, oidIgnoreType, size) < 0)
+        return ASN_PARSE_E;
+    /* Save reference to the hash of CN */
+    ret = GetOctetString(source, &idx, &length, size);
+    if (ret < 0)
+        return ret;
+    resp->issuerHash = source + idx;
+    idx += length;
+    /* Save reference to the hash of the issuer public key */
+    ret = GetOctetString(source, &idx, &length, size);
+    if (ret < 0)
+        return ret;
+    resp->issuerKeyHash = source + idx;
+    idx += length;
+
+    /* Get serial number */
+    if (GetSerialNumber(source, &idx, cs->serial, &cs->serialSz, size) < 0)
+        return ASN_PARSE_E;
+
+    if ( idx >= size )
+        return BUFFER_E;
+
+    /* CertStatus */
+    switch (source[idx++])
+    {
+        case (ASN_CONTEXT_SPECIFIC | CERT_GOOD):
+            cs->status = CERT_GOOD;
+            idx++;
+            break;
+        case (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | CERT_REVOKED):
+            cs->status = CERT_REVOKED;
+            if (GetLength(source, &idx, &length, size) < 0)
+                return ASN_PARSE_E;
+            idx += length;
+            break;
+        case (ASN_CONTEXT_SPECIFIC | CERT_UNKNOWN):
+            cs->status = CERT_UNKNOWN;
+            idx++;
+            break;
+        default:
+            return ASN_PARSE_E;
+    }
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+    cs->thisDateAsn = source + idx;
+    localIdx = 0;
+    if (GetDateInfo(cs->thisDateAsn, &localIdx, NULL,
+                    (byte*)&cs->thisDateParsed.type,
+                    &cs->thisDateParsed.length, size) < 0)
+        return ASN_PARSE_E;
+    XMEMCPY(cs->thisDateParsed.data,
+            cs->thisDateAsn + localIdx - cs->thisDateParsed.length,
+            cs->thisDateParsed.length);
+#endif
+    if (GetBasicDate(source, &idx, cs->thisDate,
+                                                &cs->thisDateFormat, size) < 0)
+        return ASN_PARSE_E;
+
+#ifndef NO_ASN_TIME
+#ifndef WOLFSSL_NO_OCSP_DATE_CHECK
+    if (!XVALIDATE_DATE(cs->thisDate, cs->thisDateFormat, BEFORE))
+        return ASN_BEFORE_DATE_E;
+#endif
+#endif
+
+    /* The following items are optional. Only check for them if there is more
+     * unprocessed data in the singleResponse wrapper. */
+
+    localIdx = idx;
+    if (((int)(idx - prevIndex) < wrapperSz) &&
+        GetASNTag(source, &localIdx, &tag, size) == 0 &&
+        tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
+    {
+        idx++;
+        if (GetLength(source, &idx, &length, size) < 0)
+            return ASN_PARSE_E;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+        cs->nextDateAsn = source + idx;
+        localIdx = 0;
+        if (GetDateInfo(cs->nextDateAsn, &localIdx, NULL,
+                        (byte*)&cs->nextDateParsed.type,
+                        &cs->nextDateParsed.length, size) < 0)
+            return ASN_PARSE_E;
+        XMEMCPY(cs->nextDateParsed.data,
+                cs->nextDateAsn + localIdx - cs->nextDateParsed.length,
+                cs->nextDateParsed.length);
+#endif
+        if (GetBasicDate(source, &idx, cs->nextDate,
+                                                &cs->nextDateFormat, size) < 0)
+            return ASN_PARSE_E;
+
+#ifndef NO_ASN_TIME
+#ifndef WOLFSSL_NO_OCSP_DATE_CHECK
+        if (!XVALIDATE_DATE(cs->nextDate, cs->nextDateFormat, AFTER))
+            return ASN_AFTER_DATE_E;
+#endif
+#endif
+    }
+
+    localIdx = idx;
+    if (((int)(idx - prevIndex) < wrapperSz) &&
+        GetASNTag(source, &localIdx, &tag, size) == 0 &&
+        tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
+    {
+        idx++;
+        if (GetLength(source, &idx, &length, size) < 0)
+            return ASN_PARSE_E;
+        idx += length;
+    }
+
+    *ioIndex = idx;
+
+    return 0;
+}
+
+static int DecodeOcspRespExtensions(byte* source,
+                            word32* ioIndex, OcspResponse* resp, word32 sz)
+{
+    word32 idx = *ioIndex;
+    int length;
+    int ext_bound; /* boundary index for the sequence of extensions */
+    word32 oid;
+    int ret;
+    byte tag;
+
+    WOLFSSL_ENTER("DecodeOcspRespExtensions");
+
+    if ((idx + 1) > sz)
+        return BUFFER_E;
+
+    if (GetASNTag(source, &idx, &tag, sz) < 0)
+        return ASN_PARSE_E;
+
+    if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
+        return ASN_PARSE_E;
+
+    if (GetLength(source, &idx, &length, sz) < 0)
+        return ASN_PARSE_E;
+
+    if (GetSequence(source, &idx, &length, sz) < 0)
+        return ASN_PARSE_E;
+
+    ext_bound = idx + length;
+
+    while (idx < (word32)ext_bound) {
+        word32 localIdx;
+
+        if (GetSequence(source, &idx, &length, sz) < 0) {
+            WOLFSSL_MSG("\tfail: should be a SEQUENCE");
+            return ASN_PARSE_E;
+        }
+
+        oid = 0;
+        if (GetObjectId(source, &idx, &oid, oidOcspType, sz) < 0) {
+            WOLFSSL_MSG("\tfail: OBJECT ID");
+            return ASN_PARSE_E;
+        }
+
+        /* check for critical flag */
+        if ((idx + 1) > (word32)sz) {
+            WOLFSSL_MSG("\tfail: malformed buffer");
+            return BUFFER_E;
+        }
+
+        localIdx = idx;
+        if (GetASNTag(source, &localIdx, &tag, sz) == 0 && tag == ASN_BOOLEAN) {
+            WOLFSSL_MSG("\tfound optional critical flag, moving past");
+            ret = GetBoolean(source, &idx, sz);
+            if (ret < 0)
+                return ret;
+        }
+
+        ret = GetOctetString(source, &idx, &length, sz);
+        if (ret < 0)
+            return ret;
+
+        if (oid == OCSP_NONCE_OID) {
+            /* get data inside extra OCTET_STRING */
+            ret = GetOctetString(source, &idx, &length, sz);
+            if (ret < 0)
+                return ret;
+
+            resp->nonce = source + idx;
+            resp->nonceSz = length;
+        }
+
+        idx += length;
+    }
+
+    *ioIndex = idx;
+    return 0;
+}
+
+
+static int DecodeResponseData(byte* source,
+                            word32* ioIndex, OcspResponse* resp, word32 size)
+{
+    word32 idx = *ioIndex, prev_idx, localIdx;
+    int length;
+    int version;
+    int ret;
+    byte tag;
+
+    WOLFSSL_ENTER("DecodeResponseData");
+
+    resp->response = source + idx;
+    prev_idx = idx;
+    if (GetSequence(source, &idx, &length, size) < 0)
+        return ASN_PARSE_E;
+    resp->responseSz = length + idx - prev_idx;
+
+    /* Get version. It is an EXPLICIT[0] DEFAULT(0) value. If this
+     * item isn't an EXPLICIT[0], then set version to zero and move
+     * onto the next item.
+     */
+    localIdx = idx;
+    if (GetASNTag(source, &localIdx, &tag, size) == 0 &&
+            tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED))
+    {
+        idx += 2; /* Eat the value and length */
+        if (GetMyVersion(source, &idx, &version, size) < 0)
+            return ASN_PARSE_E;
+    } else
+        version = 0;
+
+    localIdx = idx;
+    if (GetASNTag(source, &localIdx, &tag, size) == 0 &&
+        ( tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1) ||
+          tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2) ))
+    {
+        idx++; /* advance past ASN tag */
+        if (GetLength(source, &idx, &length, size) < 0)
+            return ASN_PARSE_E;
+        idx += length;
+    }
+    else
+        return ASN_PARSE_E;
+
+    /* save pointer to the producedAt time */
+    if (GetBasicDate(source, &idx, resp->producedDate,
+                                        &resp->producedDateFormat, size) < 0)
+        return ASN_PARSE_E;
+
+    if ((ret = DecodeSingleResponse(source, &idx, resp, size)) < 0)
+        return ret; /* ASN_PARSE_E, ASN_BEFORE_DATE_E, ASN_AFTER_DATE_E */
+
+    /*
+     * Check the length of the ResponseData against the current index to
+     * see if there are extensions, they are optional.
+     */
+    if (idx - prev_idx < resp->responseSz)
+        if (DecodeOcspRespExtensions(source, &idx, resp, size) < 0)
+            return ASN_PARSE_E;
+
+    *ioIndex = idx;
+    return 0;
+}
+
+
+#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS
+
+static int DecodeCerts(byte* source,
+                            word32* ioIndex, OcspResponse* resp, word32 size)
+{
+    word32 idx = *ioIndex;
+    byte tag;
+
+    WOLFSSL_ENTER("DecodeCerts");
+
+    if (GetASNTag(source, &idx, &tag, size) < 0)
+        return ASN_PARSE_E;
+
+    if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC))
+    {
+        int length;
+
+        if (GetLength(source, &idx, &length, size) < 0)
+            return ASN_PARSE_E;
+
+        if (GetSequence(source, &idx, &length, size) < 0)
+            return ASN_PARSE_E;
+
+        resp->cert = source + idx;
+        resp->certSz = length;
+
+        idx += length;
+    }
+    *ioIndex = idx;
+    return 0;
+}
+
+#endif /* WOLFSSL_NO_OCSP_OPTIONAL_CERTS */
+
+
+static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
+            OcspResponse* resp, word32 size, void* cm, void* heap, int noVerify)
+{
+    int    length;
+    word32 idx = *ioIndex;
+    word32 end_index;
+    int    ret;
+    int    sigLength;
+
+    WOLFSSL_ENTER("DecodeBasicOcspResponse");
+    (void)heap;
+
+    if (GetSequence(source, &idx, &length, size) < 0)
+        return ASN_PARSE_E;
+
+    if (idx + length > size)
+        return ASN_INPUT_E;
+    end_index = idx + length;
+
+    if ((ret = DecodeResponseData(source, &idx, resp, size)) < 0)
+        return ret; /* ASN_PARSE_E, ASN_BEFORE_DATE_E, ASN_AFTER_DATE_E */
+
+    /* Get the signature algorithm */
+    if (GetAlgoId(source, &idx, &resp->sigOID, oidSigType, size) < 0)
+        return ASN_PARSE_E;
+
+    ret = CheckBitString(source, &idx, &sigLength, size, 1, NULL);
+    if (ret != 0)
+        return ret;
+
+    resp->sigSz = sigLength;
+    resp->sig = source + idx;
+    idx += sigLength;
+
+    /*
+     * Check the length of the BasicOcspResponse against the current index to
+     * see if there are certificates, they are optional.
+     */
+#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS
+    if (idx < end_index)
+    {
+        DecodedCert cert;
+
+        if (DecodeCerts(source, &idx, resp, size) < 0)
+            return ASN_PARSE_E;
+
+        InitDecodedCert(&cert, resp->cert, resp->certSz, heap);
+
+        /* Don't verify if we don't have access to Cert Manager. */
+        ret = ParseCertRelative(&cert, CERT_TYPE,
+                                noVerify ? NO_VERIFY : VERIFY_OCSP, cm);
+        if (ret < 0) {
+            WOLFSSL_MSG("\tOCSP Responder certificate parsing failed");
+            FreeDecodedCert(&cert);
+            return ret;
+        }
+
+#ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK
+        if ((cert.extExtKeyUsage & EXTKEYUSE_OCSP_SIGN) == 0) {
+            if (XMEMCMP(cert.subjectHash,
+                        resp->issuerHash, KEYID_SIZE) == 0) {
+                WOLFSSL_MSG("\tOCSP Response signed by issuer");
+            }
+            else {
+                WOLFSSL_MSG("\tOCSP Responder key usage check failed");
+    #ifdef OPENSSL_EXTRA
+                resp->verifyError = OCSP_BAD_ISSUER;
+    #else
+                FreeDecodedCert(&cert);
+                return BAD_OCSP_RESPONDER;
+    #endif
+            }
+        }
+#endif
+
+        /* ConfirmSignature is blocking here */
+        ret = ConfirmSignature(&cert.sigCtx,
+            resp->response, resp->responseSz,
+            cert.publicKey, cert.pubKeySize, cert.keyOID,
+            resp->sig, resp->sigSz, resp->sigOID, NULL);
+
+        FreeDecodedCert(&cert);
+
+        if (ret != 0) {
+            WOLFSSL_MSG("\tOCSP Confirm signature failed");
+            return ASN_OCSP_CONFIRM_E;
+        }
+    }
+    else
+#endif /* WOLFSSL_NO_OCSP_OPTIONAL_CERTS */
+    {
+        Signer* ca;
+        int sigValid = -1;
+
+        #ifndef NO_SKID
+            ca = GetCA(cm, resp->issuerKeyHash);
+        #else
+            ca = GetCA(cm, resp->issuerHash);
+        #endif
+
+        if (ca) {
+            SignatureCtx sigCtx;
+            InitSignatureCtx(&sigCtx, heap, INVALID_DEVID);
+
+            /* ConfirmSignature is blocking here */
+            sigValid = ConfirmSignature(&sigCtx, resp->response,
+                resp->responseSz, ca->publicKey, ca->pubKeySize, ca->keyOID,
+                                resp->sig, resp->sigSz, resp->sigOID, NULL);
+        }
+        if (ca == NULL || sigValid != 0) {
+            WOLFSSL_MSG("\tOCSP Confirm signature failed");
+            return ASN_OCSP_CONFIRM_E;
+        }
+
+        (void)noVerify;
+    }
+
+    *ioIndex = idx;
+    return 0;
+}
+
+
+void InitOcspResponse(OcspResponse* resp, CertStatus* status,
+                                                    byte* source, word32 inSz)
+{
+    WOLFSSL_ENTER("InitOcspResponse");
+
+    XMEMSET(status, 0, sizeof(CertStatus));
+    XMEMSET(resp,   0, sizeof(OcspResponse));
+
+    resp->responseStatus = -1;
+    resp->status         = status;
+    resp->source         = source;
+    resp->maxIdx         = inSz;
+}
+
+
+int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap, int noVerify)
+{
+    int ret;
+    int length = 0;
+    word32 idx = 0;
+    byte* source = resp->source;
+    word32 size = resp->maxIdx;
+    word32 oid;
+    byte   tag;
+
+    WOLFSSL_ENTER("OcspResponseDecode");
+
+    /* peel the outer SEQUENCE wrapper */
+    if (GetSequence(source, &idx, &length, size) < 0)
+        return ASN_PARSE_E;
+
+    /* First get the responseStatus, an ENUMERATED */
+    if (GetEnumerated(source, &idx, &resp->responseStatus, size) < 0)
+        return ASN_PARSE_E;
+
+    if (resp->responseStatus != OCSP_SUCCESSFUL)
+        return 0;
+
+    /* Next is an EXPLICIT record called ResponseBytes, OPTIONAL */
+    if (idx >= size)
+        return ASN_INPUT_E;
+    if (GetASNTag(source, &idx, &tag, size) < 0)
+        return ASN_PARSE_E;
+    if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC))
+        return ASN_PARSE_E;
+    if (GetLength(source, &idx, &length, size) < 0)
+        return ASN_PARSE_E;
+
+    /* Get the responseBytes SEQUENCE */
+    if (GetSequence(source, &idx, &length, size) < 0)
+        return ASN_PARSE_E;
+
+    /* Check ObjectID for the resposeBytes */
+    if (GetObjectId(source, &idx, &oid, oidOcspType, size) < 0)
+        return ASN_PARSE_E;
+    if (oid != OCSP_BASIC_OID)
+        return ASN_PARSE_E;
+    ret = GetOctetString(source, &idx, &length, size);
+    if (ret < 0)
+        return ret;
+
+    ret = DecodeBasicOcspResponse(source, &idx, resp, size, cm, heap, noVerify);
+    if (ret < 0)
+        return ret;
+
+    return 0;
+}
+
+
+word32 EncodeOcspRequestExtensions(OcspRequest* req, byte* output, word32 size)
+{
+    const byte NonceObjId[] = { 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
+                                       0x30, 0x01, 0x02 };
+    byte seqArray[5][MAX_SEQ_SZ];
+    word32 seqSz[5], totalSz = (word32)sizeof(NonceObjId);
+
+    WOLFSSL_ENTER("SetOcspReqExtensions");
+
+    if (!req || !output || !req->nonceSz)
+        return 0;
+
+    totalSz += req->nonceSz;
+    totalSz += seqSz[0] = SetOctetString(req->nonceSz, seqArray[0]);
+    totalSz += seqSz[1] = SetOctetString(req->nonceSz + seqSz[0], seqArray[1]);
+    totalSz += seqSz[2] = SetObjectId(sizeof(NonceObjId), seqArray[2]);
+    totalSz += seqSz[3] = SetSequence(totalSz, seqArray[3]);
+    totalSz += seqSz[4] = SetSequence(totalSz, seqArray[4]);
+
+    if (totalSz > size)
+        return 0;
+
+    totalSz = 0;
+
+    XMEMCPY(output + totalSz, seqArray[4], seqSz[4]);
+    totalSz += seqSz[4];
+
+    XMEMCPY(output + totalSz, seqArray[3], seqSz[3]);
+    totalSz += seqSz[3];
+
+    XMEMCPY(output + totalSz, seqArray[2], seqSz[2]);
+    totalSz += seqSz[2];
+
+    XMEMCPY(output + totalSz, NonceObjId, sizeof(NonceObjId));
+    totalSz += (word32)sizeof(NonceObjId);
+
+    XMEMCPY(output + totalSz, seqArray[1], seqSz[1]);
+    totalSz += seqSz[1];
+
+    XMEMCPY(output + totalSz, seqArray[0], seqSz[0]);
+    totalSz += seqSz[0];
+
+    XMEMCPY(output + totalSz, req->nonce, req->nonceSz);
+    totalSz += req->nonceSz;
+
+    return totalSz;
+}
+
+
+int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size)
+{
+    byte seqArray[5][MAX_SEQ_SZ];
+    /* The ASN.1 of the OCSP Request is an onion of sequences */
+    byte algoArray[MAX_ALGO_SZ];
+    byte issuerArray[MAX_ENCODED_DIG_SZ];
+    byte issuerKeyArray[MAX_ENCODED_DIG_SZ];
+    byte snArray[MAX_SN_SZ];
+    byte extArray[MAX_OCSP_EXT_SZ];
+    word32 seqSz[5], algoSz, issuerSz, issuerKeySz, extSz, totalSz;
+    int i, snSz;
+
+    WOLFSSL_ENTER("EncodeOcspRequest");
+
+#ifdef NO_SHA
+    algoSz = SetAlgoID(SHA256h, algoArray, oidHashType, 0);
+#else
+    algoSz = SetAlgoID(SHAh, algoArray, oidHashType, 0);
+#endif
+
+    issuerSz    = SetDigest(req->issuerHash,    KEYID_SIZE,    issuerArray);
+    issuerKeySz = SetDigest(req->issuerKeyHash, KEYID_SIZE,    issuerKeyArray);
+    snSz        = SetSerialNumber(req->serial,  req->serialSz, snArray,
+                                                          MAX_SN_SZ, MAX_SN_SZ);
+    extSz       = 0;
+
+    if (snSz < 0)
+        return snSz;
+
+    if (req->nonceSz) {
+        /* TLS Extensions use this function too - put extensions after
+         * ASN.1: Context Specific [2].
+         */
+        extSz = EncodeOcspRequestExtensions(req, extArray + 2,
+                                            OCSP_NONCE_EXT_SZ);
+        extSz += SetExplicit(2, extSz, extArray);
+    }
+
+    totalSz = algoSz + issuerSz + issuerKeySz + snSz;
+    for (i = 4; i >= 0; i--) {
+        seqSz[i] = SetSequence(totalSz, seqArray[i]);
+        totalSz += seqSz[i];
+        if (i == 2) totalSz += extSz;
+    }
+
+    if (output == NULL)
+        return totalSz;
+    if (totalSz > size)
+        return BUFFER_E;
+
+    totalSz = 0;
+    for (i = 0; i < 5; i++) {
+        XMEMCPY(output + totalSz, seqArray[i], seqSz[i]);
+        totalSz += seqSz[i];
+    }
+
+    XMEMCPY(output + totalSz, algoArray, algoSz);
+    totalSz += algoSz;
+
+    XMEMCPY(output + totalSz, issuerArray, issuerSz);
+    totalSz += issuerSz;
+
+    XMEMCPY(output + totalSz, issuerKeyArray, issuerKeySz);
+    totalSz += issuerKeySz;
+
+    XMEMCPY(output + totalSz, snArray, snSz);
+    totalSz += snSz;
+
+    if (extSz != 0) {
+        XMEMCPY(output + totalSz, extArray, extSz);
+        totalSz += extSz;
+    }
+
+    return totalSz;
+}
+
+
+int InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce,
+                                                                     void* heap)
+{
+    int ret;
+
+    WOLFSSL_ENTER("InitOcspRequest");
+
+    if (req == NULL)
+        return BAD_FUNC_ARG;
+
+    ForceZero(req, sizeof(OcspRequest));
+    req->heap = heap;
+
+    if (cert) {
+        XMEMCPY(req->issuerHash,    cert->issuerHash,    KEYID_SIZE);
+        XMEMCPY(req->issuerKeyHash, cert->issuerKeyHash, KEYID_SIZE);
+
+        req->serial = (byte*)XMALLOC(cert->serialSz, req->heap,
+                                                     DYNAMIC_TYPE_OCSP_REQUEST);
+        if (req->serial == NULL)
+            return MEMORY_E;
+
+        XMEMCPY(req->serial, cert->serial, cert->serialSz);
+        req->serialSz = cert->serialSz;
+
+        if (cert->extAuthInfoSz != 0 && cert->extAuthInfo != NULL) {
+            req->url = (byte*)XMALLOC(cert->extAuthInfoSz + 1, req->heap,
+                                                     DYNAMIC_TYPE_OCSP_REQUEST);
+            if (req->url == NULL) {
+                XFREE(req->serial, req->heap, DYNAMIC_TYPE_OCSP);
+                return MEMORY_E;
+            }
+
+            XMEMCPY(req->url, cert->extAuthInfo, cert->extAuthInfoSz);
+            req->urlSz = cert->extAuthInfoSz;
+            req->url[req->urlSz] = 0;
+        }
+    }
+
+    if (useNonce) {
+        WC_RNG rng;
+
+    #ifndef HAVE_FIPS
+        ret = wc_InitRng_ex(&rng, req->heap, INVALID_DEVID);
+    #else
+        ret = wc_InitRng(&rng);
+    #endif
+        if (ret != 0) {
+            WOLFSSL_MSG("\tCannot initialize RNG. Skipping the OSCP Nonce.");
+        } else {
+            if (wc_RNG_GenerateBlock(&rng, req->nonce, MAX_OCSP_NONCE_SZ) != 0)
+                WOLFSSL_MSG("\tCannot run RNG. Skipping the OSCP Nonce.");
+            else
+                req->nonceSz = MAX_OCSP_NONCE_SZ;
+
+            wc_FreeRng(&rng);
+        }
+    }
+
+    return 0;
+}
+
+void FreeOcspRequest(OcspRequest* req)
+{
+    WOLFSSL_ENTER("FreeOcspRequest");
+
+    if (req) {
+        if (req->serial)
+            XFREE(req->serial, req->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+        req->serial = NULL;
+
+#ifdef OPENSSL_EXTRA
+        if (req->serialInt) {
+            if (req->serialInt->isDynamic) {
+                XFREE(req->serialInt->data, NULL, DYNAMIC_TYPE_OPENSSL);
+            }
+            XFREE(req->serialInt, NULL, DYNAMIC_TYPE_OPENSSL);
+        }
+        req->serialInt = NULL;
+#endif
+
+        if (req->url)
+            XFREE(req->url, req->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+        req->url = NULL;
+    }
+}
+
+
+int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp)
+{
+    int cmp;
+
+    WOLFSSL_ENTER("CompareOcspReqResp");
+
+    if (req == NULL)
+    {
+        WOLFSSL_MSG("\tReq missing");
+        return -1;
+    }
+
+    if (resp == NULL)
+    {
+        WOLFSSL_MSG("\tResp missing");
+        return 1;
+    }
+
+    /* Nonces are not critical. The responder may not necessarily add
+     * the nonce to the response. */
+    if (req->nonceSz
+#ifndef WOLFSSL_FORCE_OCSP_NONCE_CHECK
+            && resp->nonceSz != 0
+#endif
+    ) {
+        cmp = req->nonceSz - resp->nonceSz;
+        if (cmp != 0)
+        {
+            WOLFSSL_MSG("\tnonceSz mismatch");
+            return cmp;
+        }
+
+        cmp = XMEMCMP(req->nonce, resp->nonce, req->nonceSz);
+        if (cmp != 0)
+        {
+            WOLFSSL_MSG("\tnonce mismatch");
+            return cmp;
+        }
+    }
+
+    cmp = XMEMCMP(req->issuerHash, resp->issuerHash, KEYID_SIZE);
+    if (cmp != 0)
+    {
+        WOLFSSL_MSG("\tissuerHash mismatch");
+        return cmp;
+    }
+
+    cmp = XMEMCMP(req->issuerKeyHash, resp->issuerKeyHash, KEYID_SIZE);
+    if (cmp != 0)
+    {
+        WOLFSSL_MSG("\tissuerKeyHash mismatch");
+        return cmp;
+    }
+
+    cmp = req->serialSz - resp->status->serialSz;
+    if (cmp != 0)
+    {
+        WOLFSSL_MSG("\tserialSz mismatch");
+        return cmp;
+    }
+
+    cmp = XMEMCMP(req->serial, resp->status->serial, req->serialSz);
+    if (cmp != 0)
+    {
+        WOLFSSL_MSG("\tserial mismatch");
+        return cmp;
+    }
+
+    return 0;
+}
+
+#endif /* HAVE_OCSP */
+
+
+/* store WC_SHA hash of NAME */
+int GetNameHash(const byte* source, word32* idx, byte* hash,
+                             int maxIdx)
+{
+    int    length;  /* length of all distinguished names */
+    int    ret;
+    word32 dummy;
+    byte   tag;
+
+    WOLFSSL_ENTER("GetNameHash");
+
+    dummy = *idx;
+    if (GetASNTag(source, &dummy, &tag, maxIdx) == 0 && tag == ASN_OBJECT_ID) {
+        WOLFSSL_MSG("Trying optional prefix...");
+
+        if (GetLength(source, idx, &length, maxIdx) < 0)
+            return ASN_PARSE_E;
+
+        *idx += length;
+        WOLFSSL_MSG("Got optional prefix");
+    }
+
+    /* For OCSP, RFC2560 section 4.1.1 states the issuer hash should be
+     * calculated over the entire DER encoding of the Name field, including
+     * the tag and length. */
+    dummy = *idx;
+    if (GetSequence(source, idx, &length, maxIdx) < 0)
+        return ASN_PARSE_E;
+
+    ret = CalcHashId(source + dummy, length + *idx - dummy, hash);
+
+    *idx += length;
+
+    return ret;
+}
+
+
+#ifdef HAVE_CRL
+
+/* initialize decoded CRL */
+void InitDecodedCRL(DecodedCRL* dcrl, void* heap)
+{
+    WOLFSSL_MSG("InitDecodedCRL");
+
+    XMEMSET(dcrl, 0, sizeof(DecodedCRL));
+    dcrl->heap = heap;
+    #ifdef WOLFSSL_HEAP_TEST
+        dcrl->heap = (void*)WOLFSSL_HEAP_TEST;
+    #endif
+}
+
+
+/* free decoded CRL resources */
+void FreeDecodedCRL(DecodedCRL* dcrl)
+{
+    RevokedCert* tmp = dcrl->certs;
+
+    WOLFSSL_MSG("FreeDecodedCRL");
+
+    while(tmp) {
+        RevokedCert* next = tmp->next;
+        XFREE(tmp, dcrl->heap, DYNAMIC_TYPE_REVOKED);
+        tmp = next;
+    }
+}
+
+
+/* Get Revoked Cert list, 0 on success */
+static int GetRevoked(const byte* buff, word32* idx, DecodedCRL* dcrl,
+                      int maxIdx)
+{
+    int    ret, len;
+    word32 end;
+    byte   b;
+    RevokedCert* rc;
+
+    WOLFSSL_ENTER("GetRevoked");
+
+    if (GetSequence(buff, idx, &len, maxIdx) < 0)
+        return ASN_PARSE_E;
+
+    end = *idx + len;
+
+    rc = (RevokedCert*)XMALLOC(sizeof(RevokedCert), dcrl->heap,
+                                                          DYNAMIC_TYPE_REVOKED);
+    if (rc == NULL) {
+        WOLFSSL_MSG("Alloc Revoked Cert failed");
+        return MEMORY_E;
+    }
+
+    if (GetSerialNumber(buff, idx, rc->serialNumber, &rc->serialSz,
+                                                                maxIdx) < 0) {
+        XFREE(rc, dcrl->heap, DYNAMIC_TYPE_REVOKED);
+        return ASN_PARSE_E;
+    }
+
+    /* add to list */
+    rc->next = dcrl->certs;
+    dcrl->certs = rc;
+    dcrl->totalCerts++;
+
+    /* get date */
+    ret = GetDateInfo(buff, idx, NULL, &b, NULL, maxIdx);
+    if (ret < 0) {
+        WOLFSSL_MSG("Expecting Date");
+        return ret;
+    }
+
+    /* skip extensions */
+    *idx = end;
+
+    return 0;
+}
+
+
+/* Get CRL Signature, 0 on success */
+static int GetCRL_Signature(const byte* source, word32* idx, DecodedCRL* dcrl,
+                            int maxIdx)
+{
+    int    length;
+    int    ret;
+
+    WOLFSSL_ENTER("GetCRL_Signature");
+
+    ret = CheckBitString(source, idx, &length, maxIdx, 1, NULL);
+    if (ret != 0)
+        return ret;
+    dcrl->sigLength = length;
+
+    dcrl->signature = (byte*)&source[*idx];
+    *idx += dcrl->sigLength;
+
+    return 0;
+}
+
+int VerifyCRL_Signature(SignatureCtx* sigCtx, const byte* toBeSigned,
+                        word32 tbsSz, const byte* signature, word32 sigSz,
+                        word32 signatureOID, Signer *ca, void* heap)
+{
+    /* try to confirm/verify signature */
+#ifndef IGNORE_KEY_EXTENSIONS
+    if ((ca->keyUsage & KEYUSE_CRL_SIGN) == 0) {
+        WOLFSSL_MSG("CA cannot sign CRLs");
+        return ASN_CRL_NO_SIGNER_E;
+    }
+#endif /* IGNORE_KEY_EXTENSIONS */
+
+    InitSignatureCtx(sigCtx, heap, INVALID_DEVID);
+    if (ConfirmSignature(sigCtx, toBeSigned, tbsSz, ca->publicKey,
+                         ca->pubKeySize, ca->keyOID, signature, sigSz,
+                         signatureOID, NULL) != 0) {
+        WOLFSSL_MSG("CRL Confirm signature failed");
+        return ASN_CRL_CONFIRM_E;
+    }
+
+    return 0;
+}
+
+
+static int ParseCRL_CertList(DecodedCRL* dcrl, const byte* buf,
+        word32* inOutIdx, int sz)
+{
+    word32 oid, dateIdx, idx, checkIdx;
+    int version, doNextDate = 1;
+    byte tag;
+
+    if (dcrl == NULL || inOutIdx == NULL || buf == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* may have version */
+    idx = *inOutIdx;
+
+    checkIdx = idx;
+    if (GetASNTag(buf, &checkIdx, &tag, sz) == 0 && tag == ASN_INTEGER) {
+        if (GetMyVersion(buf, &idx, &version, sz) < 0)
+            return ASN_PARSE_E;
+    }
+
+    if (GetAlgoId(buf, &idx, &oid, oidIgnoreType, sz) < 0)
+        return ASN_PARSE_E;
+
+    if (GetNameHash(buf, &idx, dcrl->issuerHash, sz) < 0)
+        return ASN_PARSE_E;
+
+    if (GetBasicDate(buf, &idx, dcrl->lastDate, &dcrl->lastDateFormat, sz) < 0)
+        return ASN_PARSE_E;
+
+    dateIdx = idx;
+
+    if (GetBasicDate(buf, &idx, dcrl->nextDate, &dcrl->nextDateFormat, sz) < 0)
+    {
+#ifndef WOLFSSL_NO_CRL_NEXT_DATE
+        (void)dateIdx;
+        return ASN_PARSE_E;
+#else
+        dcrl->nextDateFormat = ASN_OTHER_TYPE;  /* skip flag */
+        doNextDate = 0;
+        idx = dateIdx;
+#endif
+    }
+
+    if (doNextDate) {
+#ifndef NO_ASN_TIME
+        if (!XVALIDATE_DATE(dcrl->nextDate, dcrl->nextDateFormat, AFTER)) {
+            WOLFSSL_MSG("CRL after date is no longer valid");
+            return ASN_AFTER_DATE_E;
+        }
+#endif
+    }
+
+    checkIdx = idx;
+    if (idx != dcrl->sigIndex &&
+           GetASNTag(buf, &checkIdx, &tag, sz) == 0 && tag != CRL_EXTENSIONS) {
+
+        int len;
+
+        if (GetSequence(buf, &idx, &len, sz) < 0)
+            return ASN_PARSE_E;
+        len += idx;
+
+        while (idx < (word32)len) {
+            if (GetRevoked(buf, &idx, dcrl, len) < 0)
+                return ASN_PARSE_E;
+        }
+    }
+
+    *inOutIdx = idx;
+
+    return 0;
+}
+
+
+#ifndef NO_SKID
+static int ParseCRL_AuthKeyIdExt(const byte* input, int sz, DecodedCRL* dcrl)
+{
+    word32 idx = 0;
+    int length = 0, ret = 0;
+    byte tag;
+
+    WOLFSSL_ENTER("ParseCRL_AuthKeyIdExt");
+
+    if (GetSequence(input, &idx, &length, sz) < 0) {
+        WOLFSSL_MSG("\tfail: should be a SEQUENCE\n");
+        return ASN_PARSE_E;
+    }
+
+    if (GetASNTag(input, &idx, &tag, sz) < 0) {
+        return ASN_PARSE_E;
+    }
+
+    if (tag != (ASN_CONTEXT_SPECIFIC | 0)) {
+        WOLFSSL_MSG("\tinfo: OPTIONAL item 0, not available\n");
+        return 0;
+    }
+
+    if (GetLength(input, &idx, &length, sz) <= 0) {
+        WOLFSSL_MSG("\tfail: extension data length");
+        return ASN_PARSE_E;
+    }
+
+    dcrl->extAuthKeyIdSet = 1;
+    if (length == KEYID_SIZE) {
+        XMEMCPY(dcrl->extAuthKeyId, input + idx, length);
+    }
+    else {
+        ret = CalcHashId(input + idx, length, dcrl->extAuthKeyId);
+    }
+
+    return ret;
+}
+#endif
+
+
+static int ParseCRL_Extensions(DecodedCRL* dcrl, const byte* buf,
+        word32* inOutIdx, word32 sz)
+{
+    int length;
+    word32 idx;
+    word32 ext_bound; /* boundary index for the sequence of extensions */
+    word32 oid;
+    byte tag;
+
+    WOLFSSL_ENTER("ParseCRL_Extensions");
+    (void)dcrl;
+
+    if (inOutIdx == NULL)
+        return BAD_FUNC_ARG;
+
+    idx = *inOutIdx;
+
+    /* CRL Extensions are optional */
+    if ((idx + 1) > sz)
+        return 0;
+
+    /* CRL Extensions are optional */
+    if (GetASNTag(buf, &idx, &tag, sz) < 0)
+        return 0;
+
+    /* CRL Extensions are optional */
+    if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
+        return 0;
+
+    if (GetLength(buf, &idx, &length, sz) < 0)
+        return ASN_PARSE_E;
+
+    if (GetSequence(buf, &idx, &length, sz) < 0)
+        return ASN_PARSE_E;
+
+    ext_bound = idx + length;
+
+    while (idx < (word32)ext_bound) {
+        word32 localIdx;
+        int ret;
+
+        if (GetSequence(buf, &idx, &length, sz) < 0) {
+            WOLFSSL_MSG("\tfail: should be a SEQUENCE");
+            return ASN_PARSE_E;
+        }
+
+        oid = 0;
+        if (GetObjectId(buf, &idx, &oid, oidCrlExtType, sz) < 0) {
+            WOLFSSL_MSG("\tfail: OBJECT ID");
+            return ASN_PARSE_E;
+        }
+
+        /* check for critical flag */
+        if ((idx + 1) > (word32)sz) {
+            WOLFSSL_MSG("\tfail: malformed buffer");
+            return BUFFER_E;
+        }
+
+        localIdx = idx;
+        if (GetASNTag(buf, &localIdx, &tag, sz) == 0 && tag == ASN_BOOLEAN) {
+            WOLFSSL_MSG("\tfound optional critical flag, moving past");
+            ret = GetBoolean(buf, &idx, sz);
+            if (ret < 0)
+                return ret;
+        }
+
+        ret = GetOctetString(buf, &idx, &length, sz);
+        if (ret < 0)
+            return ret;
+
+        if (oid == AUTH_KEY_OID) {
+        #ifndef NO_SKID
+            ret = ParseCRL_AuthKeyIdExt(buf + idx, length, dcrl);
+            if (ret < 0) {
+                WOLFSSL_MSG("\tcouldn't parse AuthKeyId extension");
+                return ret;
+            }
+        #endif
+        }
+
+        idx += length;
+    }
+
+    *inOutIdx = idx;
+
+    return 0;
+}
+
+
+/* prase crl buffer into decoded state, 0 on success */
+int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm)
+{
+    int          len;
+    word32       idx = 0;
+    Signer*      ca = NULL;
+    SignatureCtx sigCtx;
+
+    WOLFSSL_MSG("ParseCRL");
+
+    /* raw crl hash */
+    /* hash here if needed for optimized comparisons
+     * wc_Sha sha;
+     * wc_InitSha(&sha);
+     * wc_ShaUpdate(&sha, buff, sz);
+     * wc_ShaFinal(&sha, dcrl->crlHash); */
+
+    if (GetSequence(buff, &idx, &len, sz) < 0)
+        return ASN_PARSE_E;
+
+    dcrl->certBegin = idx;
+    /* Normalize sz for the length inside the outer sequence. */
+    sz = len + idx;
+
+    if (GetSequence(buff, &idx, &len, sz) < 0)
+        return ASN_PARSE_E;
+    dcrl->sigIndex = len + idx;
+
+    if (ParseCRL_CertList(dcrl, buff, &idx, idx + len) < 0)
+        return ASN_PARSE_E;
+
+    if (ParseCRL_Extensions(dcrl, buff, &idx, idx + len) < 0)
+        return ASN_PARSE_E;
+
+    idx = dcrl->sigIndex;
+
+    if (GetAlgoId(buff, &idx, &dcrl->signatureOID, oidSigType, sz) < 0)
+        return ASN_PARSE_E;
+
+    if (GetCRL_Signature(buff, &idx, dcrl, sz) < 0)
+        return ASN_PARSE_E;
+
+    /* openssl doesn't add skid by default for CRLs cause firefox chokes
+       if experiencing issues uncomment NO_SKID define in CRL section of
+       wolfssl/wolfcrypt/settings.h */
+#ifndef NO_SKID
+    if (dcrl->extAuthKeyIdSet) {
+        ca = GetCA(cm, dcrl->extAuthKeyId); /* more unique than issuerHash */
+    }
+    if (ca != NULL && XMEMCMP(dcrl->issuerHash, ca->subjectNameHash,
+                KEYID_SIZE) != 0) {
+        ca = NULL;
+    }
+    if (ca == NULL) {
+        ca = GetCAByName(cm, dcrl->issuerHash); /* last resort */
+        /* If AKID is available then this CA doesn't have the public
+         * key required */
+        if (ca && dcrl->extAuthKeyIdSet) {
+            WOLFSSL_MSG("CA SKID doesn't match AKID");
+            ca = NULL;
+        }
+    }
+#else
+    ca = GetCA(cm, dcrl->issuerHash);
+#endif /* !NO_SKID */
+    WOLFSSL_MSG("About to verify CRL signature");
+
+    if (ca == NULL) {
+        WOLFSSL_MSG("Did NOT find CRL issuer CA");
+        return ASN_CRL_NO_SIGNER_E;
+    }
+
+    WOLFSSL_MSG("Found CRL issuer CA");
+    return VerifyCRL_Signature(&sigCtx, buff + dcrl->certBegin,
+           dcrl->sigIndex - dcrl->certBegin, dcrl->signature, dcrl->sigLength,
+           dcrl->signatureOID, ca, dcrl->heap);
+}
+
+#endif /* HAVE_CRL */
+
+
+
+#ifdef WOLFSSL_CERT_PIV
+
+int wc_ParseCertPIV(wc_CertPIV* piv, const byte* buf, word32 totalSz)
+{
+    int length = 0;
+    word32 idx = 0;
+
+    WOLFSSL_ENTER("wc_ParseCertPIV");
+
+    if (piv == NULL || buf == NULL || totalSz == 0)
+        return BAD_FUNC_ARG;
+
+    XMEMSET(piv, 0, sizeof(wc_CertPIV));
+
+    /* Detect Identiv PIV (with 0x0A, 0x0B and 0x0C sections) */
+    /* Certificate (0A 82 05FA) */
+    if (GetASNHeader(buf, ASN_PIV_CERT, &idx, &length, totalSz) >= 0) {
+        /* Identiv Type PIV card */
+        piv->isIdentiv = 1;
+
+        piv->cert =   &buf[idx];
+        piv->certSz = length;
+        idx += length;
+
+        /* Nonce (0B 14) */
+        if (GetASNHeader(buf, ASN_PIV_NONCE, &idx, &length, totalSz) >= 0) {
+            piv->nonce =   &buf[idx];
+            piv->nonceSz = length;
+            idx += length;
+        }
+
+        /* Signed Nonce (0C 82 0100) */
+        if (GetASNHeader(buf, ASN_PIV_SIGNED_NONCE, &idx, &length, totalSz) >= 0) {
+            piv->signedNonce =   &buf[idx];
+            piv->signedNonceSz = length;
+        }
+
+        idx = 0;
+        buf = piv->cert;
+        totalSz = piv->certSz;
+    }
+
+    /* Certificate Buffer Total Size (53 82 05F6) */
+    if (GetASNHeader(buf, ASN_APPLICATION | ASN_PRINTABLE_STRING, &idx,
+                                                   &length, totalSz) < 0) {
+        return ASN_PARSE_E;
+    }
+    /* PIV Certificate (70 82 05ED) */
+    if (GetASNHeader(buf, ASN_PIV_TAG_CERT, &idx, &length,
+                                                         totalSz) < 0) {
+        return ASN_PARSE_E;
+    }
+
+    /* Capture certificate buffer pointer and length */
+    piv->cert =   &buf[idx];
+    piv->certSz = length;
+    idx += length;
+
+    /* PIV Certificate Info (71 01 00) */
+    if (GetASNHeader(buf, ASN_PIV_TAG_CERT_INFO, &idx, &length,
+                                                        totalSz) >= 0) {
+        if (length >= 1) {
+            piv->compression = (buf[idx] & ASN_PIV_CERT_INFO_COMPRESSED);
+            piv->isX509 =      (buf[idx] & ASN_PIV_CERT_INFO_ISX509);
+        }
+        idx += length;
+    }
+
+    /* PIV Error Detection (FE 00) */
+    if (GetASNHeader(buf, ASN_PIV_TAG_ERR_DET, &idx, &length,
+                                                        totalSz) >= 0) {
+        piv->certErrDet =   &buf[idx];
+        piv->certErrDetSz = length;
+        idx += length;
+    }
+
+    return 0;
+}
+
+#endif /* WOLFSSL_CERT_PIV */
+
+
+#undef ERROR_OUT
+
+#endif /* !NO_ASN */
+
+#ifdef WOLFSSL_SEP
+
+
+#endif /* WOLFSSL_SEP */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/blake2b.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/blake2b.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/blake2b.c	(revision 453)
@@ -0,0 +1,452 @@
+/*
+   BLAKE2 reference source code package - reference C implementations
+
+   Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
+
+   To the extent possible under law, the author(s) have dedicated all copyright
+   and related and neighboring rights to this software to the public domain
+   worldwide. This software is distributed without any warranty.
+
+   You should have received a copy of the CC0 Public Domain Dedication along with
+   this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
+*/
+/* blake2b.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifdef HAVE_BLAKE2
+
+#include <wolfssl/wolfcrypt/blake2.h>
+#include <wolfssl/wolfcrypt/blake2-impl.h>
+
+
+static const word64 blake2b_IV[8] =
+{
+  0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
+  0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
+  0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
+  0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
+};
+
+static const byte blake2b_sigma[12][16] =
+{
+  {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15 } ,
+  { 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3 } ,
+  { 11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9,  4 } ,
+  {  7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15,  8 } ,
+  {  9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3, 13 } ,
+  {  2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1,  9 } ,
+  { 12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8, 11 } ,
+  { 13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2, 10 } ,
+  {  6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10,  5 } ,
+  { 10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13 , 0 } ,
+  {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15 } ,
+  { 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3 }
+};
+
+
+static WC_INLINE int blake2b_set_lastnode( blake2b_state *S )
+{
+  S->f[1] = ~0ULL;
+  return 0;
+}
+
+/* Some helper functions, not necessarily useful */
+static WC_INLINE int blake2b_set_lastblock( blake2b_state *S )
+{
+  if( S->last_node ) blake2b_set_lastnode( S );
+
+  S->f[0] = ~0ULL;
+  return 0;
+}
+
+static WC_INLINE int blake2b_increment_counter( blake2b_state *S, const word64
+                                             inc )
+{
+  S->t[0] += inc;
+  S->t[1] += ( S->t[0] < inc );
+  return 0;
+}
+
+static WC_INLINE int blake2b_init0( blake2b_state *S )
+{
+  int i;
+  XMEMSET( S, 0, sizeof( blake2b_state ) );
+
+  for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i];
+
+  return 0;
+}
+
+/* init xors IV with input parameter block */
+int blake2b_init_param( blake2b_state *S, const blake2b_param *P )
+{
+  word32 i;
+  byte *p ;
+  blake2b_init0( S );
+  p =  ( byte * )( P );
+
+  /* IV XOR ParamBlock */
+  for( i = 0; i < 8; ++i )
+    S->h[i] ^= load64( p + sizeof( S->h[i] ) * i );
+
+  return 0;
+}
+
+
+
+int blake2b_init( blake2b_state *S, const byte outlen )
+{
+  blake2b_param P[1];
+
+  if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
+
+#ifdef WOLFSSL_BLAKE2B_INIT_EACH_FIELD
+  P->digest_length = outlen;
+  P->key_length    = 0;
+  P->fanout        = 1;
+  P->depth         = 1;
+  store32( &P->leaf_length, 0 );
+  store64( &P->node_offset, 0 );
+  P->node_depth    = 0;
+  P->inner_length  = 0;
+  XMEMSET( P->reserved, 0, sizeof( P->reserved ) );
+  XMEMSET( P->salt,     0, sizeof( P->salt ) );
+  XMEMSET( P->personal, 0, sizeof( P->personal ) );
+#else
+  XMEMSET( P, 0, sizeof( *P ) );
+  P->digest_length = outlen;
+  P->fanout        = 1;
+  P->depth         = 1;
+#endif
+  return blake2b_init_param( S, P );
+}
+
+
+int blake2b_init_key( blake2b_state *S, const byte outlen, const void *key,
+                      const byte keylen )
+{
+  blake2b_param P[1];
+
+  if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
+
+  if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1;
+
+#ifdef WOLFSSL_BLAKE2B_INIT_EACH_FIELD
+  P->digest_length = outlen;
+  P->key_length    = keylen;
+  P->fanout        = 1;
+  P->depth         = 1;
+  store32( &P->leaf_length, 0 );
+  store64( &P->node_offset, 0 );
+  P->node_depth    = 0;
+  P->inner_length  = 0;
+  XMEMSET( P->reserved, 0, sizeof( P->reserved ) );
+  XMEMSET( P->salt,     0, sizeof( P->salt ) );
+  XMEMSET( P->personal, 0, sizeof( P->personal ) );
+#else
+  XMEMSET( P, 0, sizeof( *P ) );
+  P->digest_length = outlen;
+  P->key_length    = keylen;
+  P->fanout        = 1;
+  P->depth         = 1;
+#endif
+
+  if( blake2b_init_param( S, P ) < 0 ) return -1;
+
+  {
+#ifdef WOLFSSL_SMALL_STACK
+    byte* block;
+
+    block = (byte*)XMALLOC(BLAKE2B_BLOCKBYTES, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+    if ( block == NULL ) return -1;
+#else
+    byte block[BLAKE2B_BLOCKBYTES];
+#endif
+
+    XMEMSET( block, 0, BLAKE2B_BLOCKBYTES );
+    XMEMCPY( block, key, keylen );
+    blake2b_update( S, block, BLAKE2B_BLOCKBYTES );
+    secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from */
+                                                     /* memory */
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(block, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+  }
+  return 0;
+}
+
+static int blake2b_compress( blake2b_state *S,
+                             const byte block[BLAKE2B_BLOCKBYTES] )
+{
+  int i;
+
+#ifdef WOLFSSL_SMALL_STACK
+  word64* m;
+  word64* v;
+
+  m = (word64*)XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+  if ( m == NULL ) return -1;
+
+  v = (word64*)XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+  if ( v == NULL )
+  {
+    XFREE(m, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    return -1;
+  }
+#else
+  word64 m[16];
+  word64 v[16];
+#endif
+
+  for( i = 0; i < 16; ++i )
+    m[i] = load64( block + i * sizeof( m[i] ) );
+
+  for( i = 0; i < 8; ++i )
+    v[i] = S->h[i];
+
+  v[ 8] = blake2b_IV[0];
+  v[ 9] = blake2b_IV[1];
+  v[10] = blake2b_IV[2];
+  v[11] = blake2b_IV[3];
+  v[12] = S->t[0] ^ blake2b_IV[4];
+  v[13] = S->t[1] ^ blake2b_IV[5];
+  v[14] = S->f[0] ^ blake2b_IV[6];
+  v[15] = S->f[1] ^ blake2b_IV[7];
+#define G(r,i,a,b,c,d) \
+  do { \
+    a = a + b + m[blake2b_sigma[r][2*i+0]]; \
+    d = rotr64(d ^ a, 32); \
+    c = c + d; \
+    b = rotr64(b ^ c, 24); \
+    a = a + b + m[blake2b_sigma[r][2*i+1]]; \
+    d = rotr64(d ^ a, 16); \
+    c = c + d; \
+    b = rotr64(b ^ c, 63); \
+  } while(0)
+#define ROUND(r)  \
+  do { \
+    G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
+    G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
+    G(r,2,v[ 2],v[ 6],v[10],v[14]); \
+    G(r,3,v[ 3],v[ 7],v[11],v[15]); \
+    G(r,4,v[ 0],v[ 5],v[10],v[15]); \
+    G(r,5,v[ 1],v[ 6],v[11],v[12]); \
+    G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
+    G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
+  } while(0)
+  ROUND( 0 );
+  ROUND( 1 );
+  ROUND( 2 );
+  ROUND( 3 );
+  ROUND( 4 );
+  ROUND( 5 );
+  ROUND( 6 );
+  ROUND( 7 );
+  ROUND( 8 );
+  ROUND( 9 );
+  ROUND( 10 );
+  ROUND( 11 );
+
+  for( i = 0; i < 8; ++i )
+    S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
+
+#undef G
+#undef ROUND
+
+#ifdef WOLFSSL_SMALL_STACK
+  XFREE(m, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+  XFREE(v, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+  return 0;
+}
+
+/* inlen now in bytes */
+int blake2b_update( blake2b_state *S, const byte *in, word64 inlen )
+{
+  while( inlen > 0 )
+  {
+    word64 left = S->buflen;
+    word64 fill = 2 * BLAKE2B_BLOCKBYTES - left;
+
+    if( inlen > fill )
+    {
+      XMEMCPY( S->buf + left, in, (wolfssl_word)fill ); /* Fill buffer */
+      S->buflen += fill;
+      blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
+
+      if ( blake2b_compress( S, S->buf ) < 0 ) return -1; /* Compress */
+
+      XMEMCPY( S->buf, S->buf + BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES );
+              /* Shift buffer left */
+      S->buflen -= BLAKE2B_BLOCKBYTES;
+      in += fill;
+      inlen -= fill;
+    }
+    else /* inlen <= fill */
+    {
+      XMEMCPY( S->buf + left, in, (wolfssl_word)inlen );
+      S->buflen += inlen; /* Be lazy, do not compress */
+      inlen = 0;
+    }
+  }
+
+  return 0;
+}
+
+/* Is this correct? */
+int blake2b_final( blake2b_state *S, byte *out, byte outlen )
+{
+  byte buffer[BLAKE2B_OUTBYTES];
+  int     i;
+
+  if( S->buflen > BLAKE2B_BLOCKBYTES )
+  {
+    blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
+
+    if ( blake2b_compress( S, S->buf ) < 0 ) return -1;
+
+    S->buflen -= BLAKE2B_BLOCKBYTES;
+    XMEMCPY( S->buf, S->buf + BLAKE2B_BLOCKBYTES, (wolfssl_word)S->buflen );
+  }
+
+  blake2b_increment_counter( S, S->buflen );
+  blake2b_set_lastblock( S );
+  XMEMSET( S->buf + S->buflen, 0, (wolfssl_word)(2 * BLAKE2B_BLOCKBYTES - S->buflen) );
+         /* Padding */
+  if ( blake2b_compress( S, S->buf ) < 0 ) return -1;
+
+  for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
+    store64( buffer + sizeof( S->h[i] ) * i, S->h[i] );
+
+  XMEMCPY( out, buffer, outlen );
+  return 0;
+}
+
+/* inlen, at least, should be word64. Others can be size_t. */
+int blake2b( byte *out, const void *in, const void *key, const byte outlen,
+             const word64 inlen, byte keylen )
+{
+  blake2b_state S[1];
+
+  /* Verify parameters */
+  if ( NULL == in ) return -1;
+
+  if ( NULL == out ) return -1;
+
+  if( NULL == key ) keylen = 0;
+
+  if( keylen > 0 )
+  {
+    if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1;
+  }
+  else
+  {
+    if( blake2b_init( S, outlen ) < 0 ) return -1;
+  }
+
+  if ( blake2b_update( S, ( byte * )in, inlen ) < 0) return -1;
+
+  return blake2b_final( S, out, outlen );
+}
+
+#if defined(BLAKE2B_SELFTEST)
+#include <string.h>
+#include "blake2-kat.h"
+int main( int argc, char **argv )
+{
+  byte key[BLAKE2B_KEYBYTES];
+  byte buf[KAT_LENGTH];
+
+  for( word32 i = 0; i < BLAKE2B_KEYBYTES; ++i )
+    key[i] = ( byte )i;
+
+  for( word32 i = 0; i < KAT_LENGTH; ++i )
+    buf[i] = ( byte )i;
+
+  for( word32 i = 0; i < KAT_LENGTH; ++i )
+  {
+    byte hash[BLAKE2B_OUTBYTES];
+    if ( blake2b( hash, buf, key, BLAKE2B_OUTBYTES, i, BLAKE2B_KEYBYTES ) < 0 )
+    {
+      puts( "error" );
+      return -1;
+    }
+
+    if( 0 != XMEMCMP( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) )
+    {
+      puts( "error" );
+      return -1;
+    }
+  }
+
+  puts( "ok" );
+  return 0;
+}
+#endif
+
+
+/* wolfCrypt API */
+
+/* Init Blake2b digest, track size in case final doesn't want to "remember" */
+int wc_InitBlake2b(Blake2b* b2b, word32 digestSz)
+{
+    if (b2b == NULL){
+        return -1;
+    }
+    b2b->digestSz = digestSz;
+
+    return blake2b_init(b2b->S, (byte)digestSz);
+}
+
+
+/* Blake2b Update */
+int wc_Blake2bUpdate(Blake2b* b2b, const byte* data, word32 sz)
+{
+    return blake2b_update(b2b->S, data, sz);
+}
+
+
+/* Blake2b Final, if pass in zero size we use init digestSz */
+int wc_Blake2bFinal(Blake2b* b2b, byte* final, word32 requestSz)
+{
+    word32 sz = requestSz ? requestSz : b2b->digestSz;
+
+    return blake2b_final(b2b->S, final, (byte)sz);
+}
+
+
+/* end CTaoCrypt API */
+
+#endif  /* HAVE_BLAKE2 */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/camellia.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/camellia.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/camellia.c	(revision 453)
@@ -0,0 +1,1644 @@
+/* camellia.c ver 1.2.0
+ *
+ * Copyright (c) 2006,2007
+ * NTT (Nippon Telegraph and Telephone Corporation) . All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer as
+ *   the first lines of this file unmodified.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NTT ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL NTT BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* camellia.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+/*
+ * Algorithm Specification
+ *  http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifdef HAVE_CAMELLIA
+
+#include <wolfssl/wolfcrypt/camellia.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#include <wolfssl/wolfcrypt/logging.h>
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+/* u32 must be 32bit word */
+typedef unsigned int u32;
+typedef unsigned char u8;
+
+/* key constants */
+
+#define CAMELLIA_SIGMA1L ((u32)0xA09E667FL)
+#define CAMELLIA_SIGMA1R ((u32)0x3BCC908BL)
+#define CAMELLIA_SIGMA2L ((u32)0xB67AE858L)
+#define CAMELLIA_SIGMA2R ((u32)0x4CAA73B2L)
+#define CAMELLIA_SIGMA3L ((u32)0xC6EF372FL)
+#define CAMELLIA_SIGMA3R ((u32)0xE94F82BEL)
+#define CAMELLIA_SIGMA4L ((u32)0x54FF53A5L)
+#define CAMELLIA_SIGMA4R ((u32)0xF1D36F1CL)
+#define CAMELLIA_SIGMA5L ((u32)0x10E527FAL)
+#define CAMELLIA_SIGMA5R ((u32)0xDE682D1DL)
+#define CAMELLIA_SIGMA6L ((u32)0xB05688C2L)
+#define CAMELLIA_SIGMA6R ((u32)0xB3E6C1FDL)
+
+/*
+ *  macros
+ */
+
+
+#if defined(_MSC_VER)
+
+# define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
+# define GETU32(p) SWAP(*((u32 *)(p)))
+# define PUTU32(ct, st) {*((u32 *)(ct)) = SWAP((st));}
+
+#else /* not MS-VC */
+
+# define GETU32(pt)				\
+    (((u32)(pt)[0] << 24)			\
+     ^ ((u32)(pt)[1] << 16)			\
+     ^ ((u32)(pt)[2] <<  8)			\
+     ^ ((u32)(pt)[3]))
+
+# define PUTU32(ct, st)  {			\
+	(ct)[0] = (u8)((st) >> 24);		\
+	(ct)[1] = (u8)((st) >> 16);		\
+	(ct)[2] = (u8)((st) >>  8);		\
+	(ct)[3] = (u8)(st); }
+
+#endif
+
+#define CamelliaSubkeyL(INDEX) (subkey[(INDEX)*2])
+#define CamelliaSubkeyR(INDEX) (subkey[(INDEX)*2 + 1])
+
+/* rotation right shift 1byte */
+#define CAMELLIA_RR8(x) (((x) >> 8) + ((x) << 24))
+/* rotation left shift 1bit */
+#define CAMELLIA_RL1(x) (((x) << 1) + ((x) >> 31))
+/* rotation left shift 1byte */
+#define CAMELLIA_RL8(x) (((x) << 8) + ((x) >> 24))
+
+#define CAMELLIA_ROLDQ(ll, lr, rl, rr, w0, w1, bits)	\
+    do {						\
+	w0 = ll;					\
+	ll = (ll << bits) + (lr >> (32 - bits));	\
+	lr = (lr << bits) + (rl >> (32 - bits));	\
+	rl = (rl << bits) + (rr >> (32 - bits));	\
+	rr = (rr << bits) + (w0 >> (32 - bits));	\
+    } while(0)
+
+#define CAMELLIA_ROLDQo32(ll, lr, rl, rr, w0, w1, bits)	\
+    do {						\
+	w0 = ll;					\
+	w1 = lr;					\
+	ll = (lr << (bits - 32)) + (rl >> (64 - bits));	\
+	lr = (rl << (bits - 32)) + (rr >> (64 - bits));	\
+	rl = (rr << (bits - 32)) + (w0 >> (64 - bits));	\
+	rr = (w0 << (bits - 32)) + (w1 >> (64 - bits));	\
+    } while(0)
+
+#define CAMELLIA_SP1110(INDEX) (camellia_sp1110[(INDEX)])
+#define CAMELLIA_SP0222(INDEX) (camellia_sp0222[(INDEX)])
+#define CAMELLIA_SP3033(INDEX) (camellia_sp3033[(INDEX)])
+#define CAMELLIA_SP4404(INDEX) (camellia_sp4404[(INDEX)])
+
+#define CAMELLIA_F(xl, xr, kl, kr, yl, yr, il, ir, t0, t1)	\
+    do {							\
+	il = xl ^ kl;						\
+	ir = xr ^ kr;						\
+	t0 = il >> 16;						\
+	t1 = ir >> 16;						\
+	yl = CAMELLIA_SP1110(ir & 0xff)				\
+	    ^ CAMELLIA_SP0222((t1 >> 8) & 0xff)			\
+	    ^ CAMELLIA_SP3033(t1 & 0xff)			\
+	    ^ CAMELLIA_SP4404((ir >> 8) & 0xff);		\
+	yr = CAMELLIA_SP1110((t0 >> 8) & 0xff)			\
+	    ^ CAMELLIA_SP0222(t0 & 0xff)			\
+	    ^ CAMELLIA_SP3033((il >> 8) & 0xff)			\
+	    ^ CAMELLIA_SP4404(il & 0xff);			\
+	yl ^= yr;						\
+	yr = CAMELLIA_RR8(yr);					\
+	yr ^= yl;						\
+    } while(0)
+
+
+/*
+ * for speed up
+ *
+ */
+#define CAMELLIA_FLS(ll, lr, rl, rr, kll, klr, krl, krr, t0, t1, t2, t3) \
+    do {								\
+	t0 = kll;							\
+	t0 &= ll;							\
+	lr ^= CAMELLIA_RL1(t0);						\
+	t1 = klr;							\
+	t1 |= lr;							\
+	ll ^= t1;							\
+									\
+	t2 = krr;							\
+	t2 |= rr;							\
+	rl ^= t2;							\
+	t3 = krl;							\
+	t3 &= rl;							\
+	rr ^= CAMELLIA_RL1(t3);						\
+    } while(0)
+
+#define CAMELLIA_ROUNDSM(xl, xr, kl, kr, yl, yr, il, ir, t0, t1)	\
+    do {								\
+	ir = CAMELLIA_SP1110(xr & 0xff)					\
+	    ^ CAMELLIA_SP0222((xr >> 24) & 0xff)			\
+	    ^ CAMELLIA_SP3033((xr >> 16) & 0xff)			\
+	    ^ CAMELLIA_SP4404((xr >> 8) & 0xff);			\
+	il = CAMELLIA_SP1110((xl >> 24) & 0xff)				\
+	    ^ CAMELLIA_SP0222((xl >> 16) & 0xff)			\
+	    ^ CAMELLIA_SP3033((xl >> 8) & 0xff)				\
+	    ^ CAMELLIA_SP4404(xl & 0xff);				\
+	il ^= kl;							\
+	ir ^= kr;							\
+	ir ^= il;							\
+	il = CAMELLIA_RR8(il);						\
+	il ^= ir;							\
+	yl ^= ir;							\
+	yr ^= il;							\
+    } while(0)
+
+
+static const u32 camellia_sp1110[256] = {
+    0x70707000,0x82828200,0x2c2c2c00,0xececec00,
+    0xb3b3b300,0x27272700,0xc0c0c000,0xe5e5e500,
+    0xe4e4e400,0x85858500,0x57575700,0x35353500,
+    0xeaeaea00,0x0c0c0c00,0xaeaeae00,0x41414100,
+    0x23232300,0xefefef00,0x6b6b6b00,0x93939300,
+    0x45454500,0x19191900,0xa5a5a500,0x21212100,
+    0xededed00,0x0e0e0e00,0x4f4f4f00,0x4e4e4e00,
+    0x1d1d1d00,0x65656500,0x92929200,0xbdbdbd00,
+    0x86868600,0xb8b8b800,0xafafaf00,0x8f8f8f00,
+    0x7c7c7c00,0xebebeb00,0x1f1f1f00,0xcecece00,
+    0x3e3e3e00,0x30303000,0xdcdcdc00,0x5f5f5f00,
+    0x5e5e5e00,0xc5c5c500,0x0b0b0b00,0x1a1a1a00,
+    0xa6a6a600,0xe1e1e100,0x39393900,0xcacaca00,
+    0xd5d5d500,0x47474700,0x5d5d5d00,0x3d3d3d00,
+    0xd9d9d900,0x01010100,0x5a5a5a00,0xd6d6d600,
+    0x51515100,0x56565600,0x6c6c6c00,0x4d4d4d00,
+    0x8b8b8b00,0x0d0d0d00,0x9a9a9a00,0x66666600,
+    0xfbfbfb00,0xcccccc00,0xb0b0b000,0x2d2d2d00,
+    0x74747400,0x12121200,0x2b2b2b00,0x20202000,
+    0xf0f0f000,0xb1b1b100,0x84848400,0x99999900,
+    0xdfdfdf00,0x4c4c4c00,0xcbcbcb00,0xc2c2c200,
+    0x34343400,0x7e7e7e00,0x76767600,0x05050500,
+    0x6d6d6d00,0xb7b7b700,0xa9a9a900,0x31313100,
+    0xd1d1d100,0x17171700,0x04040400,0xd7d7d700,
+    0x14141400,0x58585800,0x3a3a3a00,0x61616100,
+    0xdedede00,0x1b1b1b00,0x11111100,0x1c1c1c00,
+    0x32323200,0x0f0f0f00,0x9c9c9c00,0x16161600,
+    0x53535300,0x18181800,0xf2f2f200,0x22222200,
+    0xfefefe00,0x44444400,0xcfcfcf00,0xb2b2b200,
+    0xc3c3c300,0xb5b5b500,0x7a7a7a00,0x91919100,
+    0x24242400,0x08080800,0xe8e8e800,0xa8a8a800,
+    0x60606000,0xfcfcfc00,0x69696900,0x50505000,
+    0xaaaaaa00,0xd0d0d000,0xa0a0a000,0x7d7d7d00,
+    0xa1a1a100,0x89898900,0x62626200,0x97979700,
+    0x54545400,0x5b5b5b00,0x1e1e1e00,0x95959500,
+    0xe0e0e000,0xffffff00,0x64646400,0xd2d2d200,
+    0x10101000,0xc4c4c400,0x00000000,0x48484800,
+    0xa3a3a300,0xf7f7f700,0x75757500,0xdbdbdb00,
+    0x8a8a8a00,0x03030300,0xe6e6e600,0xdadada00,
+    0x09090900,0x3f3f3f00,0xdddddd00,0x94949400,
+    0x87878700,0x5c5c5c00,0x83838300,0x02020200,
+    0xcdcdcd00,0x4a4a4a00,0x90909000,0x33333300,
+    0x73737300,0x67676700,0xf6f6f600,0xf3f3f300,
+    0x9d9d9d00,0x7f7f7f00,0xbfbfbf00,0xe2e2e200,
+    0x52525200,0x9b9b9b00,0xd8d8d800,0x26262600,
+    0xc8c8c800,0x37373700,0xc6c6c600,0x3b3b3b00,
+    0x81818100,0x96969600,0x6f6f6f00,0x4b4b4b00,
+    0x13131300,0xbebebe00,0x63636300,0x2e2e2e00,
+    0xe9e9e900,0x79797900,0xa7a7a700,0x8c8c8c00,
+    0x9f9f9f00,0x6e6e6e00,0xbcbcbc00,0x8e8e8e00,
+    0x29292900,0xf5f5f500,0xf9f9f900,0xb6b6b600,
+    0x2f2f2f00,0xfdfdfd00,0xb4b4b400,0x59595900,
+    0x78787800,0x98989800,0x06060600,0x6a6a6a00,
+    0xe7e7e700,0x46464600,0x71717100,0xbababa00,
+    0xd4d4d400,0x25252500,0xababab00,0x42424200,
+    0x88888800,0xa2a2a200,0x8d8d8d00,0xfafafa00,
+    0x72727200,0x07070700,0xb9b9b900,0x55555500,
+    0xf8f8f800,0xeeeeee00,0xacacac00,0x0a0a0a00,
+    0x36363600,0x49494900,0x2a2a2a00,0x68686800,
+    0x3c3c3c00,0x38383800,0xf1f1f100,0xa4a4a400,
+    0x40404000,0x28282800,0xd3d3d300,0x7b7b7b00,
+    0xbbbbbb00,0xc9c9c900,0x43434300,0xc1c1c100,
+    0x15151500,0xe3e3e300,0xadadad00,0xf4f4f400,
+    0x77777700,0xc7c7c700,0x80808000,0x9e9e9e00,
+};
+
+static const u32 camellia_sp0222[256] = {
+    0x00e0e0e0,0x00050505,0x00585858,0x00d9d9d9,
+    0x00676767,0x004e4e4e,0x00818181,0x00cbcbcb,
+    0x00c9c9c9,0x000b0b0b,0x00aeaeae,0x006a6a6a,
+    0x00d5d5d5,0x00181818,0x005d5d5d,0x00828282,
+    0x00464646,0x00dfdfdf,0x00d6d6d6,0x00272727,
+    0x008a8a8a,0x00323232,0x004b4b4b,0x00424242,
+    0x00dbdbdb,0x001c1c1c,0x009e9e9e,0x009c9c9c,
+    0x003a3a3a,0x00cacaca,0x00252525,0x007b7b7b,
+    0x000d0d0d,0x00717171,0x005f5f5f,0x001f1f1f,
+    0x00f8f8f8,0x00d7d7d7,0x003e3e3e,0x009d9d9d,
+    0x007c7c7c,0x00606060,0x00b9b9b9,0x00bebebe,
+    0x00bcbcbc,0x008b8b8b,0x00161616,0x00343434,
+    0x004d4d4d,0x00c3c3c3,0x00727272,0x00959595,
+    0x00ababab,0x008e8e8e,0x00bababa,0x007a7a7a,
+    0x00b3b3b3,0x00020202,0x00b4b4b4,0x00adadad,
+    0x00a2a2a2,0x00acacac,0x00d8d8d8,0x009a9a9a,
+    0x00171717,0x001a1a1a,0x00353535,0x00cccccc,
+    0x00f7f7f7,0x00999999,0x00616161,0x005a5a5a,
+    0x00e8e8e8,0x00242424,0x00565656,0x00404040,
+    0x00e1e1e1,0x00636363,0x00090909,0x00333333,
+    0x00bfbfbf,0x00989898,0x00979797,0x00858585,
+    0x00686868,0x00fcfcfc,0x00ececec,0x000a0a0a,
+    0x00dadada,0x006f6f6f,0x00535353,0x00626262,
+    0x00a3a3a3,0x002e2e2e,0x00080808,0x00afafaf,
+    0x00282828,0x00b0b0b0,0x00747474,0x00c2c2c2,
+    0x00bdbdbd,0x00363636,0x00222222,0x00383838,
+    0x00646464,0x001e1e1e,0x00393939,0x002c2c2c,
+    0x00a6a6a6,0x00303030,0x00e5e5e5,0x00444444,
+    0x00fdfdfd,0x00888888,0x009f9f9f,0x00656565,
+    0x00878787,0x006b6b6b,0x00f4f4f4,0x00232323,
+    0x00484848,0x00101010,0x00d1d1d1,0x00515151,
+    0x00c0c0c0,0x00f9f9f9,0x00d2d2d2,0x00a0a0a0,
+    0x00555555,0x00a1a1a1,0x00414141,0x00fafafa,
+    0x00434343,0x00131313,0x00c4c4c4,0x002f2f2f,
+    0x00a8a8a8,0x00b6b6b6,0x003c3c3c,0x002b2b2b,
+    0x00c1c1c1,0x00ffffff,0x00c8c8c8,0x00a5a5a5,
+    0x00202020,0x00898989,0x00000000,0x00909090,
+    0x00474747,0x00efefef,0x00eaeaea,0x00b7b7b7,
+    0x00151515,0x00060606,0x00cdcdcd,0x00b5b5b5,
+    0x00121212,0x007e7e7e,0x00bbbbbb,0x00292929,
+    0x000f0f0f,0x00b8b8b8,0x00070707,0x00040404,
+    0x009b9b9b,0x00949494,0x00212121,0x00666666,
+    0x00e6e6e6,0x00cecece,0x00ededed,0x00e7e7e7,
+    0x003b3b3b,0x00fefefe,0x007f7f7f,0x00c5c5c5,
+    0x00a4a4a4,0x00373737,0x00b1b1b1,0x004c4c4c,
+    0x00919191,0x006e6e6e,0x008d8d8d,0x00767676,
+    0x00030303,0x002d2d2d,0x00dedede,0x00969696,
+    0x00262626,0x007d7d7d,0x00c6c6c6,0x005c5c5c,
+    0x00d3d3d3,0x00f2f2f2,0x004f4f4f,0x00191919,
+    0x003f3f3f,0x00dcdcdc,0x00797979,0x001d1d1d,
+    0x00525252,0x00ebebeb,0x00f3f3f3,0x006d6d6d,
+    0x005e5e5e,0x00fbfbfb,0x00696969,0x00b2b2b2,
+    0x00f0f0f0,0x00313131,0x000c0c0c,0x00d4d4d4,
+    0x00cfcfcf,0x008c8c8c,0x00e2e2e2,0x00757575,
+    0x00a9a9a9,0x004a4a4a,0x00575757,0x00848484,
+    0x00111111,0x00454545,0x001b1b1b,0x00f5f5f5,
+    0x00e4e4e4,0x000e0e0e,0x00737373,0x00aaaaaa,
+    0x00f1f1f1,0x00dddddd,0x00595959,0x00141414,
+    0x006c6c6c,0x00929292,0x00545454,0x00d0d0d0,
+    0x00787878,0x00707070,0x00e3e3e3,0x00494949,
+    0x00808080,0x00505050,0x00a7a7a7,0x00f6f6f6,
+    0x00777777,0x00939393,0x00868686,0x00838383,
+    0x002a2a2a,0x00c7c7c7,0x005b5b5b,0x00e9e9e9,
+    0x00eeeeee,0x008f8f8f,0x00010101,0x003d3d3d,
+};
+
+static const u32 camellia_sp3033[256] = {
+    0x38003838,0x41004141,0x16001616,0x76007676,
+    0xd900d9d9,0x93009393,0x60006060,0xf200f2f2,
+    0x72007272,0xc200c2c2,0xab00abab,0x9a009a9a,
+    0x75007575,0x06000606,0x57005757,0xa000a0a0,
+    0x91009191,0xf700f7f7,0xb500b5b5,0xc900c9c9,
+    0xa200a2a2,0x8c008c8c,0xd200d2d2,0x90009090,
+    0xf600f6f6,0x07000707,0xa700a7a7,0x27002727,
+    0x8e008e8e,0xb200b2b2,0x49004949,0xde00dede,
+    0x43004343,0x5c005c5c,0xd700d7d7,0xc700c7c7,
+    0x3e003e3e,0xf500f5f5,0x8f008f8f,0x67006767,
+    0x1f001f1f,0x18001818,0x6e006e6e,0xaf00afaf,
+    0x2f002f2f,0xe200e2e2,0x85008585,0x0d000d0d,
+    0x53005353,0xf000f0f0,0x9c009c9c,0x65006565,
+    0xea00eaea,0xa300a3a3,0xae00aeae,0x9e009e9e,
+    0xec00ecec,0x80008080,0x2d002d2d,0x6b006b6b,
+    0xa800a8a8,0x2b002b2b,0x36003636,0xa600a6a6,
+    0xc500c5c5,0x86008686,0x4d004d4d,0x33003333,
+    0xfd00fdfd,0x66006666,0x58005858,0x96009696,
+    0x3a003a3a,0x09000909,0x95009595,0x10001010,
+    0x78007878,0xd800d8d8,0x42004242,0xcc00cccc,
+    0xef00efef,0x26002626,0xe500e5e5,0x61006161,
+    0x1a001a1a,0x3f003f3f,0x3b003b3b,0x82008282,
+    0xb600b6b6,0xdb00dbdb,0xd400d4d4,0x98009898,
+    0xe800e8e8,0x8b008b8b,0x02000202,0xeb00ebeb,
+    0x0a000a0a,0x2c002c2c,0x1d001d1d,0xb000b0b0,
+    0x6f006f6f,0x8d008d8d,0x88008888,0x0e000e0e,
+    0x19001919,0x87008787,0x4e004e4e,0x0b000b0b,
+    0xa900a9a9,0x0c000c0c,0x79007979,0x11001111,
+    0x7f007f7f,0x22002222,0xe700e7e7,0x59005959,
+    0xe100e1e1,0xda00dada,0x3d003d3d,0xc800c8c8,
+    0x12001212,0x04000404,0x74007474,0x54005454,
+    0x30003030,0x7e007e7e,0xb400b4b4,0x28002828,
+    0x55005555,0x68006868,0x50005050,0xbe00bebe,
+    0xd000d0d0,0xc400c4c4,0x31003131,0xcb00cbcb,
+    0x2a002a2a,0xad00adad,0x0f000f0f,0xca00caca,
+    0x70007070,0xff00ffff,0x32003232,0x69006969,
+    0x08000808,0x62006262,0x00000000,0x24002424,
+    0xd100d1d1,0xfb00fbfb,0xba00baba,0xed00eded,
+    0x45004545,0x81008181,0x73007373,0x6d006d6d,
+    0x84008484,0x9f009f9f,0xee00eeee,0x4a004a4a,
+    0xc300c3c3,0x2e002e2e,0xc100c1c1,0x01000101,
+    0xe600e6e6,0x25002525,0x48004848,0x99009999,
+    0xb900b9b9,0xb300b3b3,0x7b007b7b,0xf900f9f9,
+    0xce00cece,0xbf00bfbf,0xdf00dfdf,0x71007171,
+    0x29002929,0xcd00cdcd,0x6c006c6c,0x13001313,
+    0x64006464,0x9b009b9b,0x63006363,0x9d009d9d,
+    0xc000c0c0,0x4b004b4b,0xb700b7b7,0xa500a5a5,
+    0x89008989,0x5f005f5f,0xb100b1b1,0x17001717,
+    0xf400f4f4,0xbc00bcbc,0xd300d3d3,0x46004646,
+    0xcf00cfcf,0x37003737,0x5e005e5e,0x47004747,
+    0x94009494,0xfa00fafa,0xfc00fcfc,0x5b005b5b,
+    0x97009797,0xfe00fefe,0x5a005a5a,0xac00acac,
+    0x3c003c3c,0x4c004c4c,0x03000303,0x35003535,
+    0xf300f3f3,0x23002323,0xb800b8b8,0x5d005d5d,
+    0x6a006a6a,0x92009292,0xd500d5d5,0x21002121,
+    0x44004444,0x51005151,0xc600c6c6,0x7d007d7d,
+    0x39003939,0x83008383,0xdc00dcdc,0xaa00aaaa,
+    0x7c007c7c,0x77007777,0x56005656,0x05000505,
+    0x1b001b1b,0xa400a4a4,0x15001515,0x34003434,
+    0x1e001e1e,0x1c001c1c,0xf800f8f8,0x52005252,
+    0x20002020,0x14001414,0xe900e9e9,0xbd00bdbd,
+    0xdd00dddd,0xe400e4e4,0xa100a1a1,0xe000e0e0,
+    0x8a008a8a,0xf100f1f1,0xd600d6d6,0x7a007a7a,
+    0xbb00bbbb,0xe300e3e3,0x40004040,0x4f004f4f,
+};
+
+static const u32 camellia_sp4404[256] = {
+    0x70700070,0x2c2c002c,0xb3b300b3,0xc0c000c0,
+    0xe4e400e4,0x57570057,0xeaea00ea,0xaeae00ae,
+    0x23230023,0x6b6b006b,0x45450045,0xa5a500a5,
+    0xeded00ed,0x4f4f004f,0x1d1d001d,0x92920092,
+    0x86860086,0xafaf00af,0x7c7c007c,0x1f1f001f,
+    0x3e3e003e,0xdcdc00dc,0x5e5e005e,0x0b0b000b,
+    0xa6a600a6,0x39390039,0xd5d500d5,0x5d5d005d,
+    0xd9d900d9,0x5a5a005a,0x51510051,0x6c6c006c,
+    0x8b8b008b,0x9a9a009a,0xfbfb00fb,0xb0b000b0,
+    0x74740074,0x2b2b002b,0xf0f000f0,0x84840084,
+    0xdfdf00df,0xcbcb00cb,0x34340034,0x76760076,
+    0x6d6d006d,0xa9a900a9,0xd1d100d1,0x04040004,
+    0x14140014,0x3a3a003a,0xdede00de,0x11110011,
+    0x32320032,0x9c9c009c,0x53530053,0xf2f200f2,
+    0xfefe00fe,0xcfcf00cf,0xc3c300c3,0x7a7a007a,
+    0x24240024,0xe8e800e8,0x60600060,0x69690069,
+    0xaaaa00aa,0xa0a000a0,0xa1a100a1,0x62620062,
+    0x54540054,0x1e1e001e,0xe0e000e0,0x64640064,
+    0x10100010,0x00000000,0xa3a300a3,0x75750075,
+    0x8a8a008a,0xe6e600e6,0x09090009,0xdddd00dd,
+    0x87870087,0x83830083,0xcdcd00cd,0x90900090,
+    0x73730073,0xf6f600f6,0x9d9d009d,0xbfbf00bf,
+    0x52520052,0xd8d800d8,0xc8c800c8,0xc6c600c6,
+    0x81810081,0x6f6f006f,0x13130013,0x63630063,
+    0xe9e900e9,0xa7a700a7,0x9f9f009f,0xbcbc00bc,
+    0x29290029,0xf9f900f9,0x2f2f002f,0xb4b400b4,
+    0x78780078,0x06060006,0xe7e700e7,0x71710071,
+    0xd4d400d4,0xabab00ab,0x88880088,0x8d8d008d,
+    0x72720072,0xb9b900b9,0xf8f800f8,0xacac00ac,
+    0x36360036,0x2a2a002a,0x3c3c003c,0xf1f100f1,
+    0x40400040,0xd3d300d3,0xbbbb00bb,0x43430043,
+    0x15150015,0xadad00ad,0x77770077,0x80800080,
+    0x82820082,0xecec00ec,0x27270027,0xe5e500e5,
+    0x85850085,0x35350035,0x0c0c000c,0x41410041,
+    0xefef00ef,0x93930093,0x19190019,0x21210021,
+    0x0e0e000e,0x4e4e004e,0x65650065,0xbdbd00bd,
+    0xb8b800b8,0x8f8f008f,0xebeb00eb,0xcece00ce,
+    0x30300030,0x5f5f005f,0xc5c500c5,0x1a1a001a,
+    0xe1e100e1,0xcaca00ca,0x47470047,0x3d3d003d,
+    0x01010001,0xd6d600d6,0x56560056,0x4d4d004d,
+    0x0d0d000d,0x66660066,0xcccc00cc,0x2d2d002d,
+    0x12120012,0x20200020,0xb1b100b1,0x99990099,
+    0x4c4c004c,0xc2c200c2,0x7e7e007e,0x05050005,
+    0xb7b700b7,0x31310031,0x17170017,0xd7d700d7,
+    0x58580058,0x61610061,0x1b1b001b,0x1c1c001c,
+    0x0f0f000f,0x16160016,0x18180018,0x22220022,
+    0x44440044,0xb2b200b2,0xb5b500b5,0x91910091,
+    0x08080008,0xa8a800a8,0xfcfc00fc,0x50500050,
+    0xd0d000d0,0x7d7d007d,0x89890089,0x97970097,
+    0x5b5b005b,0x95950095,0xffff00ff,0xd2d200d2,
+    0xc4c400c4,0x48480048,0xf7f700f7,0xdbdb00db,
+    0x03030003,0xdada00da,0x3f3f003f,0x94940094,
+    0x5c5c005c,0x02020002,0x4a4a004a,0x33330033,
+    0x67670067,0xf3f300f3,0x7f7f007f,0xe2e200e2,
+    0x9b9b009b,0x26260026,0x37370037,0x3b3b003b,
+    0x96960096,0x4b4b004b,0xbebe00be,0x2e2e002e,
+    0x79790079,0x8c8c008c,0x6e6e006e,0x8e8e008e,
+    0xf5f500f5,0xb6b600b6,0xfdfd00fd,0x59590059,
+    0x98980098,0x6a6a006a,0x46460046,0xbaba00ba,
+    0x25250025,0x42420042,0xa2a200a2,0xfafa00fa,
+    0x07070007,0x55550055,0xeeee00ee,0x0a0a000a,
+    0x49490049,0x68680068,0x38380038,0xa4a400a4,
+    0x28280028,0x7b7b007b,0xc9c900c9,0xc1c100c1,
+    0xe3e300e3,0xf4f400f4,0xc7c700c7,0x9e9e009e,
+};
+
+
+/**
+ * Stuff related to the Camellia key schedule
+ */
+#define subl(x) subL[(x)]
+#define subr(x) subR[(x)]
+
+static int camellia_setup128(const unsigned char *key, u32 *subkey)
+{
+    u32 kll, klr, krl, krr;
+    u32 il, ir, t0, t1, w0, w1;
+    u32 kw4l, kw4r, dw, tl, tr;
+
+#ifdef WOLFSSL_SMALL_STACK
+    u32* subL;
+    u32* subR;
+
+    subL = (u32*) XMALLOC(sizeof(u32) * 26, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (subL == NULL)
+        return MEMORY_E;
+
+    subR = (u32*) XMALLOC(sizeof(u32) * 26, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (subR == NULL) {
+        XFREE(subL, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return MEMORY_E;
+    }
+#else
+    u32 subL[26];
+    u32 subR[26];
+#endif
+
+    /**
+     *  k == kll || klr || krl || krr (|| is concatenation)
+     */
+    kll = GETU32(key     );
+    klr = GETU32(key +  4);
+    krl = GETU32(key +  8);
+    krr = GETU32(key + 12);
+    /**
+     * generate KL dependent subkeys
+     */
+    subl(0) = kll; subr(0) = klr;
+    subl(1) = krl; subr(1) = krr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+    subl(4) = kll; subr(4) = klr;
+    subl(5) = krl; subr(5) = krr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30);
+    subl(10) = kll; subr(10) = klr;
+    subl(11) = krl; subr(11) = krr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+    subl(13) = krl; subr(13) = krr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+    subl(16) = kll; subr(16) = klr;
+    subl(17) = krl; subr(17) = krr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+    subl(18) = kll; subr(18) = klr;
+    subl(19) = krl; subr(19) = krr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+    subl(22) = kll; subr(22) = klr;
+    subl(23) = krl; subr(23) = krr;
+
+    /* generate KA */
+    kll = subl(0); klr = subr(0);
+    krl = subl(1); krr = subr(1);
+    CAMELLIA_F(kll, klr,
+	       CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R,
+	       w0, w1, il, ir, t0, t1);
+    krl ^= w0; krr ^= w1;
+    CAMELLIA_F(krl, krr,
+	       CAMELLIA_SIGMA2L, CAMELLIA_SIGMA2R,
+	       kll, klr, il, ir, t0, t1);
+    CAMELLIA_F(kll, klr,
+	       CAMELLIA_SIGMA3L, CAMELLIA_SIGMA3R,
+	       krl, krr, il, ir, t0, t1);
+    krl ^= w0; krr ^= w1;
+    CAMELLIA_F(krl, krr,
+	       CAMELLIA_SIGMA4L, CAMELLIA_SIGMA4R,
+	       w0, w1, il, ir, t0, t1);
+    kll ^= w0; klr ^= w1;
+
+    /* generate KA dependent subkeys */
+    subl(2) = kll; subr(2) = klr;
+    subl(3) = krl; subr(3) = krr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+    subl(6) = kll; subr(6) = klr;
+    subl(7) = krl; subr(7) = krr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+    subl(8) = kll; subr(8) = klr;
+    subl(9) = krl; subr(9) = krr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+    subl(12) = kll; subr(12) = klr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+    subl(14) = kll; subr(14) = klr;
+    subl(15) = krl; subr(15) = krr;
+    CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34);
+    subl(20) = kll; subr(20) = klr;
+    subl(21) = krl; subr(21) = krr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+    subl(24) = kll; subr(24) = klr;
+    subl(25) = krl; subr(25) = krr;
+
+
+    /* absorb kw2 to other subkeys */
+    subl(3) ^= subl(1); subr(3) ^= subr(1);
+    subl(5) ^= subl(1); subr(5) ^= subr(1);
+    subl(7) ^= subl(1); subr(7) ^= subr(1);
+    subl(1) ^= subr(1) & ~subr(9);
+    dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw);
+    subl(11) ^= subl(1); subr(11) ^= subr(1);
+    subl(13) ^= subl(1); subr(13) ^= subr(1);
+    subl(15) ^= subl(1); subr(15) ^= subr(1);
+    subl(1) ^= subr(1) & ~subr(17);
+    dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw);
+    subl(19) ^= subl(1); subr(19) ^= subr(1);
+    subl(21) ^= subl(1); subr(21) ^= subr(1);
+    subl(23) ^= subl(1); subr(23) ^= subr(1);
+    subl(24) ^= subl(1); subr(24) ^= subr(1);
+
+    /* absorb kw4 to other subkeys */
+    kw4l = subl(25); kw4r = subr(25);
+    subl(22) ^= kw4l; subr(22) ^= kw4r;
+    subl(20) ^= kw4l; subr(20) ^= kw4r;
+    subl(18) ^= kw4l; subr(18) ^= kw4r;
+    kw4l ^= kw4r & ~subr(16);
+    dw = kw4l & subl(16), kw4r ^= CAMELLIA_RL1(dw);
+    subl(14) ^= kw4l; subr(14) ^= kw4r;
+    subl(12) ^= kw4l; subr(12) ^= kw4r;
+    subl(10) ^= kw4l; subr(10) ^= kw4r;
+    kw4l ^= kw4r & ~subr(8);
+    dw = kw4l & subl(8), kw4r ^= CAMELLIA_RL1(dw);
+    subl(6) ^= kw4l; subr(6) ^= kw4r;
+    subl(4) ^= kw4l; subr(4) ^= kw4r;
+    subl(2) ^= kw4l; subr(2) ^= kw4r;
+    subl(0) ^= kw4l; subr(0) ^= kw4r;
+
+    /* key XOR is end of F-function */
+    CamelliaSubkeyL(0) = subl(0) ^ subl(2);
+    CamelliaSubkeyR(0) = subr(0) ^ subr(2);
+    CamelliaSubkeyL(2) = subl(3);
+    CamelliaSubkeyR(2) = subr(3);
+    CamelliaSubkeyL(3) = subl(2) ^ subl(4);
+    CamelliaSubkeyR(3) = subr(2) ^ subr(4);
+    CamelliaSubkeyL(4) = subl(3) ^ subl(5);
+    CamelliaSubkeyR(4) = subr(3) ^ subr(5);
+    CamelliaSubkeyL(5) = subl(4) ^ subl(6);
+    CamelliaSubkeyR(5) = subr(4) ^ subr(6);
+    CamelliaSubkeyL(6) = subl(5) ^ subl(7);
+    CamelliaSubkeyR(6) = subr(5) ^ subr(7);
+    tl = subl(10) ^ (subr(10) & ~subr(8));
+    dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw);
+    CamelliaSubkeyL(7) = subl(6) ^ tl;
+    CamelliaSubkeyR(7) = subr(6) ^ tr;
+    CamelliaSubkeyL(8) = subl(8);
+    CamelliaSubkeyR(8) = subr(8);
+    CamelliaSubkeyL(9) = subl(9);
+    CamelliaSubkeyR(9) = subr(9);
+    tl = subl(7) ^ (subr(7) & ~subr(9));
+    dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw);
+    CamelliaSubkeyL(10) = tl ^ subl(11);
+    CamelliaSubkeyR(10) = tr ^ subr(11);
+    CamelliaSubkeyL(11) = subl(10) ^ subl(12);
+    CamelliaSubkeyR(11) = subr(10) ^ subr(12);
+    CamelliaSubkeyL(12) = subl(11) ^ subl(13);
+    CamelliaSubkeyR(12) = subr(11) ^ subr(13);
+    CamelliaSubkeyL(13) = subl(12) ^ subl(14);
+    CamelliaSubkeyR(13) = subr(12) ^ subr(14);
+    CamelliaSubkeyL(14) = subl(13) ^ subl(15);
+    CamelliaSubkeyR(14) = subr(13) ^ subr(15);
+    tl = subl(18) ^ (subr(18) & ~subr(16));
+    dw = tl & subl(16),	tr = subr(18) ^ CAMELLIA_RL1(dw);
+    CamelliaSubkeyL(15) = subl(14) ^ tl;
+    CamelliaSubkeyR(15) = subr(14) ^ tr;
+    CamelliaSubkeyL(16) = subl(16);
+    CamelliaSubkeyR(16) = subr(16);
+    CamelliaSubkeyL(17) = subl(17);
+    CamelliaSubkeyR(17) = subr(17);
+    tl = subl(15) ^ (subr(15) & ~subr(17));
+    dw = tl & subl(17),	tr = subr(15) ^ CAMELLIA_RL1(dw);
+    CamelliaSubkeyL(18) = tl ^ subl(19);
+    CamelliaSubkeyR(18) = tr ^ subr(19);
+    CamelliaSubkeyL(19) = subl(18) ^ subl(20);
+    CamelliaSubkeyR(19) = subr(18) ^ subr(20);
+    CamelliaSubkeyL(20) = subl(19) ^ subl(21);
+    CamelliaSubkeyR(20) = subr(19) ^ subr(21);
+    CamelliaSubkeyL(21) = subl(20) ^ subl(22);
+    CamelliaSubkeyR(21) = subr(20) ^ subr(22);
+    CamelliaSubkeyL(22) = subl(21) ^ subl(23);
+    CamelliaSubkeyR(22) = subr(21) ^ subr(23);
+    CamelliaSubkeyL(23) = subl(22);
+    CamelliaSubkeyR(23) = subr(22);
+    CamelliaSubkeyL(24) = subl(24) ^ subl(23);
+    CamelliaSubkeyR(24) = subr(24) ^ subr(23);
+
+    /* apply the inverse of the last half of P-function */
+    dw = CamelliaSubkeyL(2) ^ CamelliaSubkeyR(2), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(2) = CamelliaSubkeyL(2) ^ dw, CamelliaSubkeyL(2) = dw;
+    dw = CamelliaSubkeyL(3) ^ CamelliaSubkeyR(3), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(3) = CamelliaSubkeyL(3) ^ dw, CamelliaSubkeyL(3) = dw;
+    dw = CamelliaSubkeyL(4) ^ CamelliaSubkeyR(4), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(4) = CamelliaSubkeyL(4) ^ dw, CamelliaSubkeyL(4) = dw;
+    dw = CamelliaSubkeyL(5) ^ CamelliaSubkeyR(5), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(5) = CamelliaSubkeyL(5) ^ dw, CamelliaSubkeyL(5) = dw;
+    dw = CamelliaSubkeyL(6) ^ CamelliaSubkeyR(6), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(6) = CamelliaSubkeyL(6) ^ dw, CamelliaSubkeyL(6) = dw;
+    dw = CamelliaSubkeyL(7) ^ CamelliaSubkeyR(7), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(7) = CamelliaSubkeyL(7) ^ dw, CamelliaSubkeyL(7) = dw;
+    dw = CamelliaSubkeyL(10) ^ CamelliaSubkeyR(10), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(10) = CamelliaSubkeyL(10) ^ dw, CamelliaSubkeyL(10) = dw;
+    dw = CamelliaSubkeyL(11) ^ CamelliaSubkeyR(11), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(11) = CamelliaSubkeyL(11) ^ dw, CamelliaSubkeyL(11) = dw;
+    dw = CamelliaSubkeyL(12) ^ CamelliaSubkeyR(12), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(12) = CamelliaSubkeyL(12) ^ dw, CamelliaSubkeyL(12) = dw;
+    dw = CamelliaSubkeyL(13) ^ CamelliaSubkeyR(13), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(13) = CamelliaSubkeyL(13) ^ dw, CamelliaSubkeyL(13) = dw;
+    dw = CamelliaSubkeyL(14) ^ CamelliaSubkeyR(14), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(14) = CamelliaSubkeyL(14) ^ dw, CamelliaSubkeyL(14) = dw;
+    dw = CamelliaSubkeyL(15) ^ CamelliaSubkeyR(15), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(15) = CamelliaSubkeyL(15) ^ dw, CamelliaSubkeyL(15) = dw;
+    dw = CamelliaSubkeyL(18) ^ CamelliaSubkeyR(18), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(18) = CamelliaSubkeyL(18) ^ dw, CamelliaSubkeyL(18) = dw;
+    dw = CamelliaSubkeyL(19) ^ CamelliaSubkeyR(19), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(19) = CamelliaSubkeyL(19) ^ dw, CamelliaSubkeyL(19) = dw;
+    dw = CamelliaSubkeyL(20) ^ CamelliaSubkeyR(20), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(20) = CamelliaSubkeyL(20) ^ dw, CamelliaSubkeyL(20) = dw;
+    dw = CamelliaSubkeyL(21) ^ CamelliaSubkeyR(21), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(21) = CamelliaSubkeyL(21) ^ dw, CamelliaSubkeyL(21) = dw;
+    dw = CamelliaSubkeyL(22) ^ CamelliaSubkeyR(22), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(22) = CamelliaSubkeyL(22) ^ dw, CamelliaSubkeyL(22) = dw;
+    dw = CamelliaSubkeyL(23) ^ CamelliaSubkeyR(23), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(23) = CamelliaSubkeyL(23) ^ dw, CamelliaSubkeyL(23) = dw;
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(subL, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(subR, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return 0;
+}
+
+static int camellia_setup256(const unsigned char *key, u32 *subkey)
+{
+    u32 kll,klr,krl,krr;           /* left half of key */
+    u32 krll,krlr,krrl,krrr;       /* right half of key */
+    u32 il, ir, t0, t1, w0, w1;    /* temporary variables */
+    u32 kw4l, kw4r, dw, tl, tr;
+
+#ifdef WOLFSSL_SMALL_STACK
+    u32* subL;
+    u32* subR;
+
+    subL = (u32*) XMALLOC(sizeof(u32) * 34, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (subL == NULL)
+        return MEMORY_E;
+
+    subR = (u32*) XMALLOC(sizeof(u32) * 34, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (subR == NULL) {
+        XFREE(subL, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return MEMORY_E;
+    }
+#else
+    u32 subL[34];
+    u32 subR[34];
+#endif
+
+    /**
+     *  key = (kll || klr || krl || krr || krll || krlr || krrl || krrr)
+     *  (|| is concatenation)
+     */
+
+    kll  = GETU32(key     );
+    klr  = GETU32(key +  4);
+    krl  = GETU32(key +  8);
+    krr  = GETU32(key + 12);
+    krll = GETU32(key + 16);
+    krlr = GETU32(key + 20);
+    krrl = GETU32(key + 24);
+    krrr = GETU32(key + 28);
+
+    /* generate KL dependent subkeys */
+    subl(0) = kll; subr(0) = klr;
+    subl(1) = krl; subr(1) = krr;
+    CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 45);
+    subl(12) = kll; subr(12) = klr;
+    subl(13) = krl; subr(13) = krr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+    subl(16) = kll; subr(16) = klr;
+    subl(17) = krl; subr(17) = krr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+    subl(22) = kll; subr(22) = klr;
+    subl(23) = krl; subr(23) = krr;
+    CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34);
+    subl(30) = kll; subr(30) = klr;
+    subl(31) = krl; subr(31) = krr;
+
+    /* generate KR dependent subkeys */
+    CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15);
+    subl(4) = krll; subr(4) = krlr;
+    subl(5) = krrl; subr(5) = krrr;
+    CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15);
+    subl(8) = krll; subr(8) = krlr;
+    subl(9) = krrl; subr(9) = krrr;
+    CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
+    subl(18) = krll; subr(18) = krlr;
+    subl(19) = krrl; subr(19) = krrr;
+    CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34);
+    subl(26) = krll; subr(26) = krlr;
+    subl(27) = krrl; subr(27) = krrr;
+    CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34);
+
+    /* generate KA */
+    kll = subl(0) ^ krll; klr = subr(0) ^ krlr;
+    krl = subl(1) ^ krrl; krr = subr(1) ^ krrr;
+    CAMELLIA_F(kll, klr,
+	       CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R,
+	       w0, w1, il, ir, t0, t1);
+    krl ^= w0; krr ^= w1;
+    CAMELLIA_F(krl, krr,
+	       CAMELLIA_SIGMA2L, CAMELLIA_SIGMA2R,
+	       kll, klr, il, ir, t0, t1);
+    kll ^= krll; klr ^= krlr;
+    CAMELLIA_F(kll, klr,
+	       CAMELLIA_SIGMA3L, CAMELLIA_SIGMA3R,
+	       krl, krr, il, ir, t0, t1);
+    krl ^= w0 ^ krrl; krr ^= w1 ^ krrr;
+    CAMELLIA_F(krl, krr,
+	       CAMELLIA_SIGMA4L, CAMELLIA_SIGMA4R,
+	       w0, w1, il, ir, t0, t1);
+    kll ^= w0; klr ^= w1;
+
+    /* generate KB */
+    krll ^= kll; krlr ^= klr;
+    krrl ^= krl; krrr ^= krr;
+    CAMELLIA_F(krll, krlr,
+	       CAMELLIA_SIGMA5L, CAMELLIA_SIGMA5R,
+	       w0, w1, il, ir, t0, t1);
+    krrl ^= w0; krrr ^= w1;
+    CAMELLIA_F(krrl, krrr,
+	       CAMELLIA_SIGMA6L, CAMELLIA_SIGMA6R,
+	       w0, w1, il, ir, t0, t1);
+    krll ^= w0; krlr ^= w1;
+
+    /* generate KA dependent subkeys */
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+    subl(6) = kll; subr(6) = klr;
+    subl(7) = krl; subr(7) = krr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30);
+    subl(14) = kll; subr(14) = klr;
+    subl(15) = krl; subr(15) = krr;
+    subl(24) = klr; subr(24) = krl;
+    subl(25) = krr; subr(25) = kll;
+    CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 49);
+    subl(28) = kll; subr(28) = klr;
+    subl(29) = krl; subr(29) = krr;
+
+    /* generate KB dependent subkeys */
+    subl(2) = krll; subr(2) = krlr;
+    subl(3) = krrl; subr(3) = krrr;
+    CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
+    subl(10) = krll; subr(10) = krlr;
+    subl(11) = krrl; subr(11) = krrr;
+    CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
+    subl(20) = krll; subr(20) = krlr;
+    subl(21) = krrl; subr(21) = krrr;
+    CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 51);
+    subl(32) = krll; subr(32) = krlr;
+    subl(33) = krrl; subr(33) = krrr;
+
+    /* absorb kw2 to other subkeys */
+    subl(3) ^= subl(1); subr(3) ^= subr(1);
+    subl(5) ^= subl(1); subr(5) ^= subr(1);
+    subl(7) ^= subl(1); subr(7) ^= subr(1);
+    subl(1) ^= subr(1) & ~subr(9);
+    dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw);
+    subl(11) ^= subl(1); subr(11) ^= subr(1);
+    subl(13) ^= subl(1); subr(13) ^= subr(1);
+    subl(15) ^= subl(1); subr(15) ^= subr(1);
+    subl(1) ^= subr(1) & ~subr(17);
+    dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw);
+    subl(19) ^= subl(1); subr(19) ^= subr(1);
+    subl(21) ^= subl(1); subr(21) ^= subr(1);
+    subl(23) ^= subl(1); subr(23) ^= subr(1);
+    subl(1) ^= subr(1) & ~subr(25);
+    dw = subl(1) & subl(25), subr(1) ^= CAMELLIA_RL1(dw);
+    subl(27) ^= subl(1); subr(27) ^= subr(1);
+    subl(29) ^= subl(1); subr(29) ^= subr(1);
+    subl(31) ^= subl(1); subr(31) ^= subr(1);
+    subl(32) ^= subl(1); subr(32) ^= subr(1);
+
+    /* absorb kw4 to other subkeys */
+    kw4l = subl(33); kw4r = subr(33);
+    subl(30) ^= kw4l; subr(30) ^= kw4r;
+    subl(28) ^= kw4l; subr(28) ^= kw4r;
+    subl(26) ^= kw4l; subr(26) ^= kw4r;
+    kw4l ^= kw4r & ~subr(24);
+    dw = kw4l & subl(24), kw4r ^= CAMELLIA_RL1(dw);
+    subl(22) ^= kw4l; subr(22) ^= kw4r;
+    subl(20) ^= kw4l; subr(20) ^= kw4r;
+    subl(18) ^= kw4l; subr(18) ^= kw4r;
+    kw4l ^= kw4r & ~subr(16);
+    dw = kw4l & subl(16), kw4r ^= CAMELLIA_RL1(dw);
+    subl(14) ^= kw4l; subr(14) ^= kw4r;
+    subl(12) ^= kw4l; subr(12) ^= kw4r;
+    subl(10) ^= kw4l; subr(10) ^= kw4r;
+    kw4l ^= kw4r & ~subr(8);
+    dw = kw4l & subl(8), kw4r ^= CAMELLIA_RL1(dw);
+    subl(6) ^= kw4l; subr(6) ^= kw4r;
+    subl(4) ^= kw4l; subr(4) ^= kw4r;
+    subl(2) ^= kw4l; subr(2) ^= kw4r;
+    subl(0) ^= kw4l; subr(0) ^= kw4r;
+
+    /* key XOR is end of F-function */
+    CamelliaSubkeyL(0) = subl(0) ^ subl(2);
+    CamelliaSubkeyR(0) = subr(0) ^ subr(2);
+    CamelliaSubkeyL(2) = subl(3);
+    CamelliaSubkeyR(2) = subr(3);
+    CamelliaSubkeyL(3) = subl(2) ^ subl(4);
+    CamelliaSubkeyR(3) = subr(2) ^ subr(4);
+    CamelliaSubkeyL(4) = subl(3) ^ subl(5);
+    CamelliaSubkeyR(4) = subr(3) ^ subr(5);
+    CamelliaSubkeyL(5) = subl(4) ^ subl(6);
+    CamelliaSubkeyR(5) = subr(4) ^ subr(6);
+    CamelliaSubkeyL(6) = subl(5) ^ subl(7);
+    CamelliaSubkeyR(6) = subr(5) ^ subr(7);
+    tl = subl(10) ^ (subr(10) & ~subr(8));
+    dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw);
+    CamelliaSubkeyL(7) = subl(6) ^ tl;
+    CamelliaSubkeyR(7) = subr(6) ^ tr;
+    CamelliaSubkeyL(8) = subl(8);
+    CamelliaSubkeyR(8) = subr(8);
+    CamelliaSubkeyL(9) = subl(9);
+    CamelliaSubkeyR(9) = subr(9);
+    tl = subl(7) ^ (subr(7) & ~subr(9));
+    dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw);
+    CamelliaSubkeyL(10) = tl ^ subl(11);
+    CamelliaSubkeyR(10) = tr ^ subr(11);
+    CamelliaSubkeyL(11) = subl(10) ^ subl(12);
+    CamelliaSubkeyR(11) = subr(10) ^ subr(12);
+    CamelliaSubkeyL(12) = subl(11) ^ subl(13);
+    CamelliaSubkeyR(12) = subr(11) ^ subr(13);
+    CamelliaSubkeyL(13) = subl(12) ^ subl(14);
+    CamelliaSubkeyR(13) = subr(12) ^ subr(14);
+    CamelliaSubkeyL(14) = subl(13) ^ subl(15);
+    CamelliaSubkeyR(14) = subr(13) ^ subr(15);
+    tl = subl(18) ^ (subr(18) & ~subr(16));
+    dw = tl & subl(16), tr = subr(18) ^ CAMELLIA_RL1(dw);
+    CamelliaSubkeyL(15) = subl(14) ^ tl;
+    CamelliaSubkeyR(15) = subr(14) ^ tr;
+    CamelliaSubkeyL(16) = subl(16);
+    CamelliaSubkeyR(16) = subr(16);
+    CamelliaSubkeyL(17) = subl(17);
+    CamelliaSubkeyR(17) = subr(17);
+    tl = subl(15) ^ (subr(15) & ~subr(17));
+    dw = tl & subl(17), tr = subr(15) ^ CAMELLIA_RL1(dw);
+    CamelliaSubkeyL(18) = tl ^ subl(19);
+    CamelliaSubkeyR(18) = tr ^ subr(19);
+    CamelliaSubkeyL(19) = subl(18) ^ subl(20);
+    CamelliaSubkeyR(19) = subr(18) ^ subr(20);
+    CamelliaSubkeyL(20) = subl(19) ^ subl(21);
+    CamelliaSubkeyR(20) = subr(19) ^ subr(21);
+    CamelliaSubkeyL(21) = subl(20) ^ subl(22);
+    CamelliaSubkeyR(21) = subr(20) ^ subr(22);
+    CamelliaSubkeyL(22) = subl(21) ^ subl(23);
+    CamelliaSubkeyR(22) = subr(21) ^ subr(23);
+    tl = subl(26) ^ (subr(26) & ~subr(24));
+    dw = tl & subl(24), tr = subr(26) ^ CAMELLIA_RL1(dw);
+    CamelliaSubkeyL(23) = subl(22) ^ tl;
+    CamelliaSubkeyR(23) = subr(22) ^ tr;
+    CamelliaSubkeyL(24) = subl(24);
+    CamelliaSubkeyR(24) = subr(24);
+    CamelliaSubkeyL(25) = subl(25);
+    CamelliaSubkeyR(25) = subr(25);
+    tl = subl(23) ^ (subr(23) &  ~subr(25));
+    dw = tl & subl(25), tr = subr(23) ^ CAMELLIA_RL1(dw);
+    CamelliaSubkeyL(26) = tl ^ subl(27);
+    CamelliaSubkeyR(26) = tr ^ subr(27);
+    CamelliaSubkeyL(27) = subl(26) ^ subl(28);
+    CamelliaSubkeyR(27) = subr(26) ^ subr(28);
+    CamelliaSubkeyL(28) = subl(27) ^ subl(29);
+    CamelliaSubkeyR(28) = subr(27) ^ subr(29);
+    CamelliaSubkeyL(29) = subl(28) ^ subl(30);
+    CamelliaSubkeyR(29) = subr(28) ^ subr(30);
+    CamelliaSubkeyL(30) = subl(29) ^ subl(31);
+    CamelliaSubkeyR(30) = subr(29) ^ subr(31);
+    CamelliaSubkeyL(31) = subl(30);
+    CamelliaSubkeyR(31) = subr(30);
+    CamelliaSubkeyL(32) = subl(32) ^ subl(31);
+    CamelliaSubkeyR(32) = subr(32) ^ subr(31);
+
+    /* apply the inverse of the last half of P-function */
+    dw = CamelliaSubkeyL(2) ^ CamelliaSubkeyR(2), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(2) = CamelliaSubkeyL(2) ^ dw, CamelliaSubkeyL(2) = dw;
+    dw = CamelliaSubkeyL(3) ^ CamelliaSubkeyR(3), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(3) = CamelliaSubkeyL(3) ^ dw, CamelliaSubkeyL(3) = dw;
+    dw = CamelliaSubkeyL(4) ^ CamelliaSubkeyR(4), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(4) = CamelliaSubkeyL(4) ^ dw, CamelliaSubkeyL(4) = dw;
+    dw = CamelliaSubkeyL(5) ^ CamelliaSubkeyR(5), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(5) = CamelliaSubkeyL(5) ^ dw, CamelliaSubkeyL(5) = dw;
+    dw = CamelliaSubkeyL(6) ^ CamelliaSubkeyR(6), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(6) = CamelliaSubkeyL(6) ^ dw, CamelliaSubkeyL(6) = dw;
+    dw = CamelliaSubkeyL(7) ^ CamelliaSubkeyR(7), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(7) = CamelliaSubkeyL(7) ^ dw, CamelliaSubkeyL(7) = dw;
+    dw = CamelliaSubkeyL(10) ^ CamelliaSubkeyR(10), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(10) = CamelliaSubkeyL(10) ^ dw, CamelliaSubkeyL(10) = dw;
+    dw = CamelliaSubkeyL(11) ^ CamelliaSubkeyR(11), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(11) = CamelliaSubkeyL(11) ^ dw, CamelliaSubkeyL(11) = dw;
+    dw = CamelliaSubkeyL(12) ^ CamelliaSubkeyR(12), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(12) = CamelliaSubkeyL(12) ^ dw, CamelliaSubkeyL(12) = dw;
+    dw = CamelliaSubkeyL(13) ^ CamelliaSubkeyR(13), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(13) = CamelliaSubkeyL(13) ^ dw, CamelliaSubkeyL(13) = dw;
+    dw = CamelliaSubkeyL(14) ^ CamelliaSubkeyR(14), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(14) = CamelliaSubkeyL(14) ^ dw, CamelliaSubkeyL(14) = dw;
+    dw = CamelliaSubkeyL(15) ^ CamelliaSubkeyR(15), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(15) = CamelliaSubkeyL(15) ^ dw, CamelliaSubkeyL(15) = dw;
+    dw = CamelliaSubkeyL(18) ^ CamelliaSubkeyR(18), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(18) = CamelliaSubkeyL(18) ^ dw, CamelliaSubkeyL(18) = dw;
+    dw = CamelliaSubkeyL(19) ^ CamelliaSubkeyR(19), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(19) = CamelliaSubkeyL(19) ^ dw, CamelliaSubkeyL(19) = dw;
+    dw = CamelliaSubkeyL(20) ^ CamelliaSubkeyR(20), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(20) = CamelliaSubkeyL(20) ^ dw, CamelliaSubkeyL(20) = dw;
+    dw = CamelliaSubkeyL(21) ^ CamelliaSubkeyR(21), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(21) = CamelliaSubkeyL(21) ^ dw, CamelliaSubkeyL(21) = dw;
+    dw = CamelliaSubkeyL(22) ^ CamelliaSubkeyR(22), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(22) = CamelliaSubkeyL(22) ^ dw, CamelliaSubkeyL(22) = dw;
+    dw = CamelliaSubkeyL(23) ^ CamelliaSubkeyR(23), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(23) = CamelliaSubkeyL(23) ^ dw, CamelliaSubkeyL(23) = dw;
+    dw = CamelliaSubkeyL(26) ^ CamelliaSubkeyR(26), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(26) = CamelliaSubkeyL(26) ^ dw, CamelliaSubkeyL(26) = dw;
+    dw = CamelliaSubkeyL(27) ^ CamelliaSubkeyR(27), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(27) = CamelliaSubkeyL(27) ^ dw, CamelliaSubkeyL(27) = dw;
+    dw = CamelliaSubkeyL(28) ^ CamelliaSubkeyR(28), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(28) = CamelliaSubkeyL(28) ^ dw, CamelliaSubkeyL(28) = dw;
+    dw = CamelliaSubkeyL(29) ^ CamelliaSubkeyR(29), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(29) = CamelliaSubkeyL(29) ^ dw, CamelliaSubkeyL(29) = dw;
+    dw = CamelliaSubkeyL(30) ^ CamelliaSubkeyR(30), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(30) = CamelliaSubkeyL(30) ^ dw, CamelliaSubkeyL(30) = dw;
+    dw = CamelliaSubkeyL(31) ^ CamelliaSubkeyR(31), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(31) = CamelliaSubkeyL(31) ^ dw,CamelliaSubkeyL(31) = dw;
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(subL, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(subR, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return 0;
+}
+
+static int camellia_setup192(const unsigned char *key, u32 *subkey)
+{
+    unsigned char kk[32];
+    u32 krll, krlr, krrl,krrr;
+
+    XMEMCPY(kk, key, 24);
+    XMEMCPY((unsigned char *)&krll, key+16,4);
+    XMEMCPY((unsigned char *)&krlr, key+20,4);
+    krrl = ~krll;
+    krrr = ~krlr;
+    XMEMCPY(kk+24, (unsigned char *)&krrl, 4);
+    XMEMCPY(kk+28, (unsigned char *)&krrr, 4);
+
+    return camellia_setup256(kk, subkey);
+}
+
+
+/**
+ * Stuff related to camellia encryption/decryption
+ *
+ * "io" must be 4byte aligned and big-endian data.
+ */
+static void camellia_encrypt128(const u32 *subkey, u32 *io)
+{
+    u32 il, ir, t0, t1;
+
+    /* pre whitening but absorb kw2*/
+    io[0] ^= CamelliaSubkeyL(0);
+    io[1] ^= CamelliaSubkeyR(0);
+    /* main iteration */
+
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(2),CamelliaSubkeyR(2),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(3),CamelliaSubkeyR(3),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(4),CamelliaSubkeyR(4),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(5),CamelliaSubkeyR(5),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(6),CamelliaSubkeyR(6),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(7),CamelliaSubkeyR(7),
+		     io[0],io[1],il,ir,t0,t1);
+
+    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		 CamelliaSubkeyL(8),CamelliaSubkeyR(8),
+		 CamelliaSubkeyL(9),CamelliaSubkeyR(9),
+		 t0,t1,il,ir);
+
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(10),CamelliaSubkeyR(10),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(11),CamelliaSubkeyR(11),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(12),CamelliaSubkeyR(12),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(13),CamelliaSubkeyR(13),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(14),CamelliaSubkeyR(14),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(15),CamelliaSubkeyR(15),
+		     io[0],io[1],il,ir,t0,t1);
+
+    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		 CamelliaSubkeyL(16),CamelliaSubkeyR(16),
+		 CamelliaSubkeyL(17),CamelliaSubkeyR(17),
+		 t0,t1,il,ir);
+
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(18),CamelliaSubkeyR(18),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(19),CamelliaSubkeyR(19),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(20),CamelliaSubkeyR(20),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(21),CamelliaSubkeyR(21),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(22),CamelliaSubkeyR(22),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(23),CamelliaSubkeyR(23),
+		     io[0],io[1],il,ir,t0,t1);
+
+    /* post whitening but kw4 */
+    io[2] ^= CamelliaSubkeyL(24);
+    io[3] ^= CamelliaSubkeyR(24);
+
+    t0 = io[0];
+    t1 = io[1];
+    io[0] = io[2];
+    io[1] = io[3];
+    io[2] = t0;
+    io[3] = t1;
+
+    return;
+}
+
+static void camellia_decrypt128(const u32 *subkey, u32 *io)
+{
+    u32 il,ir,t0,t1;               /* temporary variables */
+
+    /* pre whitening but absorb kw2*/
+    io[0] ^= CamelliaSubkeyL(24);
+    io[1] ^= CamelliaSubkeyR(24);
+
+    /* main iteration */
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(23),CamelliaSubkeyR(23),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(22),CamelliaSubkeyR(22),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(21),CamelliaSubkeyR(21),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(20),CamelliaSubkeyR(20),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(19),CamelliaSubkeyR(19),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(18),CamelliaSubkeyR(18),
+		     io[0],io[1],il,ir,t0,t1);
+
+    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		 CamelliaSubkeyL(17),CamelliaSubkeyR(17),
+		 CamelliaSubkeyL(16),CamelliaSubkeyR(16),
+		 t0,t1,il,ir);
+
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(15),CamelliaSubkeyR(15),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(14),CamelliaSubkeyR(14),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(13),CamelliaSubkeyR(13),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(12),CamelliaSubkeyR(12),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(11),CamelliaSubkeyR(11),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(10),CamelliaSubkeyR(10),
+		     io[0],io[1],il,ir,t0,t1);
+
+    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		 CamelliaSubkeyL(9),CamelliaSubkeyR(9),
+		 CamelliaSubkeyL(8),CamelliaSubkeyR(8),
+		 t0,t1,il,ir);
+
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(7),CamelliaSubkeyR(7),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(6),CamelliaSubkeyR(6),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(5),CamelliaSubkeyR(5),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(4),CamelliaSubkeyR(4),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(3),CamelliaSubkeyR(3),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(2),CamelliaSubkeyR(2),
+		     io[0],io[1],il,ir,t0,t1);
+
+    /* post whitening but kw4 */
+    io[2] ^= CamelliaSubkeyL(0);
+    io[3] ^= CamelliaSubkeyR(0);
+
+    t0 = io[0];
+    t1 = io[1];
+    io[0] = io[2];
+    io[1] = io[3];
+    io[2] = t0;
+    io[3] = t1;
+
+    return;
+}
+
+/**
+ * stuff for 192 and 256bit encryption/decryption
+ */
+static void camellia_encrypt256(const u32 *subkey, u32 *io)
+{
+    u32 il,ir,t0,t1;           /* temporary variables */
+
+    /* pre whitening but absorb kw2*/
+    io[0] ^= CamelliaSubkeyL(0);
+    io[1] ^= CamelliaSubkeyR(0);
+
+    /* main iteration */
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(2),CamelliaSubkeyR(2),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(3),CamelliaSubkeyR(3),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(4),CamelliaSubkeyR(4),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(5),CamelliaSubkeyR(5),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(6),CamelliaSubkeyR(6),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(7),CamelliaSubkeyR(7),
+		     io[0],io[1],il,ir,t0,t1);
+
+    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		 CamelliaSubkeyL(8),CamelliaSubkeyR(8),
+		 CamelliaSubkeyL(9),CamelliaSubkeyR(9),
+		 t0,t1,il,ir);
+
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(10),CamelliaSubkeyR(10),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(11),CamelliaSubkeyR(11),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(12),CamelliaSubkeyR(12),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(13),CamelliaSubkeyR(13),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(14),CamelliaSubkeyR(14),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(15),CamelliaSubkeyR(15),
+		     io[0],io[1],il,ir,t0,t1);
+
+    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		 CamelliaSubkeyL(16),CamelliaSubkeyR(16),
+		 CamelliaSubkeyL(17),CamelliaSubkeyR(17),
+		 t0,t1,il,ir);
+
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(18),CamelliaSubkeyR(18),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(19),CamelliaSubkeyR(19),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(20),CamelliaSubkeyR(20),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(21),CamelliaSubkeyR(21),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(22),CamelliaSubkeyR(22),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(23),CamelliaSubkeyR(23),
+		     io[0],io[1],il,ir,t0,t1);
+
+    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		 CamelliaSubkeyL(24),CamelliaSubkeyR(24),
+		 CamelliaSubkeyL(25),CamelliaSubkeyR(25),
+		 t0,t1,il,ir);
+
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(26),CamelliaSubkeyR(26),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(27),CamelliaSubkeyR(27),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(28),CamelliaSubkeyR(28),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(29),CamelliaSubkeyR(29),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(30),CamelliaSubkeyR(30),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(31),CamelliaSubkeyR(31),
+		     io[0],io[1],il,ir,t0,t1);
+
+    /* post whitening but kw4 */
+    io[2] ^= CamelliaSubkeyL(32);
+    io[3] ^= CamelliaSubkeyR(32);
+
+    t0 = io[0];
+    t1 = io[1];
+    io[0] = io[2];
+    io[1] = io[3];
+    io[2] = t0;
+    io[3] = t1;
+
+    return;
+}
+
+static void camellia_decrypt256(const u32 *subkey, u32 *io)
+{
+    u32 il,ir,t0,t1;           /* temporary variables */
+
+    /* pre whitening but absorb kw2*/
+    io[0] ^= CamelliaSubkeyL(32);
+    io[1] ^= CamelliaSubkeyR(32);
+
+    /* main iteration */
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(31),CamelliaSubkeyR(31),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(30),CamelliaSubkeyR(30),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(29),CamelliaSubkeyR(29),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(28),CamelliaSubkeyR(28),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(27),CamelliaSubkeyR(27),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(26),CamelliaSubkeyR(26),
+		     io[0],io[1],il,ir,t0,t1);
+
+    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		 CamelliaSubkeyL(25),CamelliaSubkeyR(25),
+		 CamelliaSubkeyL(24),CamelliaSubkeyR(24),
+		 t0,t1,il,ir);
+
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(23),CamelliaSubkeyR(23),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(22),CamelliaSubkeyR(22),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(21),CamelliaSubkeyR(21),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(20),CamelliaSubkeyR(20),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(19),CamelliaSubkeyR(19),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(18),CamelliaSubkeyR(18),
+		     io[0],io[1],il,ir,t0,t1);
+
+    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		 CamelliaSubkeyL(17),CamelliaSubkeyR(17),
+		 CamelliaSubkeyL(16),CamelliaSubkeyR(16),
+		 t0,t1,il,ir);
+
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(15),CamelliaSubkeyR(15),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(14),CamelliaSubkeyR(14),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(13),CamelliaSubkeyR(13),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(12),CamelliaSubkeyR(12),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(11),CamelliaSubkeyR(11),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(10),CamelliaSubkeyR(10),
+		     io[0],io[1],il,ir,t0,t1);
+
+    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		 CamelliaSubkeyL(9),CamelliaSubkeyR(9),
+		 CamelliaSubkeyL(8),CamelliaSubkeyR(8),
+		 t0,t1,il,ir);
+
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(7),CamelliaSubkeyR(7),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(6),CamelliaSubkeyR(6),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(5),CamelliaSubkeyR(5),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(4),CamelliaSubkeyR(4),
+		     io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+		     CamelliaSubkeyL(3),CamelliaSubkeyR(3),
+		     io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+		     CamelliaSubkeyL(2),CamelliaSubkeyR(2),
+		     io[0],io[1],il,ir,t0,t1);
+
+    /* post whitening but kw4 */
+    io[2] ^= CamelliaSubkeyL(0);
+    io[3] ^= CamelliaSubkeyR(0);
+
+    t0 = io[0];
+    t1 = io[1];
+    io[0] = io[2];
+    io[1] = io[3];
+    io[2] = t0;
+    io[3] = t1;
+
+    return;
+}
+
+/***
+ *
+ * API for compatibility
+ */
+
+static void Camellia_EncryptBlock(const int keyBitLength,
+			   const unsigned char *plaintext,
+			   const KEY_TABLE_TYPE keyTable,
+			   unsigned char *ciphertext)
+{
+    u32 tmp[4];
+
+    tmp[0] = GETU32(plaintext);
+    tmp[1] = GETU32(plaintext + 4);
+    tmp[2] = GETU32(plaintext + 8);
+    tmp[3] = GETU32(plaintext + 12);
+
+    switch (keyBitLength) {
+    case 128:
+	camellia_encrypt128(keyTable, tmp);
+	break;
+    case 192:
+	/* fall through */
+    case 256:
+	camellia_encrypt256(keyTable, tmp);
+	break;
+    default:
+	break;
+    }
+
+    PUTU32(ciphertext, tmp[0]);
+    PUTU32(ciphertext + 4, tmp[1]);
+    PUTU32(ciphertext + 8, tmp[2]);
+    PUTU32(ciphertext + 12, tmp[3]);
+}
+
+static void Camellia_DecryptBlock(const int keyBitLength,
+			   const unsigned char *ciphertext,
+			   const KEY_TABLE_TYPE keyTable,
+			   unsigned char *plaintext)
+{
+    u32 tmp[4];
+
+    tmp[0] = GETU32(ciphertext);
+    tmp[1] = GETU32(ciphertext + 4);
+    tmp[2] = GETU32(ciphertext + 8);
+    tmp[3] = GETU32(ciphertext + 12);
+
+    switch (keyBitLength) {
+    case 128:
+	camellia_decrypt128(keyTable, tmp);
+	break;
+    case 192:
+	/* fall through */
+    case 256:
+	camellia_decrypt256(keyTable, tmp);
+	break;
+    default:
+	break;
+    }
+    PUTU32(plaintext, tmp[0]);
+    PUTU32(plaintext + 4, tmp[1]);
+    PUTU32(plaintext + 8, tmp[2]);
+    PUTU32(plaintext + 12, tmp[3]);
+}
+
+
+
+/* wolfCrypt wrappers to the Camellia code */
+
+int wc_CamelliaSetKey(Camellia* cam, const byte* key, word32 len, const byte* iv)
+{
+    int ret = 0;
+
+    if (cam == NULL) return BAD_FUNC_ARG;
+
+    XMEMSET(cam->key, 0, sizeof(KEY_TABLE_TYPE));
+
+    switch (len) {
+        case 16:
+        	ret = camellia_setup128(key, cam->key);
+            break;
+        case 24:
+        	ret = camellia_setup192(key, cam->key);
+            break;
+        case 32:
+            ret = camellia_setup256(key, cam->key);
+            break;
+        default:
+            return BAD_FUNC_ARG;
+    }
+
+    if (ret != 0)
+        return ret;
+
+    cam->keySz = len * 8;
+
+    return wc_CamelliaSetIV(cam, iv);
+}
+
+
+int wc_CamelliaSetIV(Camellia* cam, const byte* iv)
+{
+    if (cam == NULL)
+        return BAD_FUNC_ARG;
+
+    if (iv)
+        XMEMCPY(cam->reg, iv, CAMELLIA_BLOCK_SIZE);
+    else
+        XMEMSET(cam->reg,  0, CAMELLIA_BLOCK_SIZE);
+
+    return 0;
+}
+
+
+int wc_CamelliaEncryptDirect(Camellia* cam, byte* out, const byte* in)
+{
+    if (cam == NULL || out == NULL || in == NULL) {
+        return BAD_FUNC_ARG;
+    }
+    Camellia_EncryptBlock(cam->keySz, in, cam->key, out);
+
+    return 0;
+}
+
+
+int wc_CamelliaDecryptDirect(Camellia* cam, byte* out, const byte* in)
+{
+    if (cam == NULL || out == NULL || in == NULL) {
+        return BAD_FUNC_ARG;
+    }
+    Camellia_DecryptBlock(cam->keySz, in, cam->key, out);
+
+    return 0;
+}
+
+
+int wc_CamelliaCbcEncrypt(Camellia* cam, byte* out, const byte* in, word32 sz)
+{
+    word32 blocks;
+    if (cam == NULL || out == NULL || in == NULL) {
+        return BAD_FUNC_ARG;
+    }
+    blocks = sz / CAMELLIA_BLOCK_SIZE;
+
+    while (blocks--) {
+        xorbuf((byte*)cam->reg, in, CAMELLIA_BLOCK_SIZE);
+        Camellia_EncryptBlock(cam->keySz, (byte*)cam->reg,
+                                                     cam->key, (byte*)cam->reg);
+        XMEMCPY(out, cam->reg, CAMELLIA_BLOCK_SIZE);
+
+        out += CAMELLIA_BLOCK_SIZE;
+        in  += CAMELLIA_BLOCK_SIZE;
+    }
+
+    return 0;
+}
+
+
+int wc_CamelliaCbcDecrypt(Camellia* cam, byte* out, const byte* in, word32 sz)
+{
+    word32 blocks;
+    if (cam == NULL || out == NULL || in == NULL) {
+        return BAD_FUNC_ARG;
+    }
+    blocks = sz / CAMELLIA_BLOCK_SIZE;
+
+    while (blocks--) {
+        XMEMCPY(cam->tmp, in, CAMELLIA_BLOCK_SIZE);
+        Camellia_DecryptBlock(cam->keySz, (byte*)cam->tmp, cam->key, out);
+        xorbuf(out, (byte*)cam->reg, CAMELLIA_BLOCK_SIZE);
+        XMEMCPY(cam->reg, cam->tmp, CAMELLIA_BLOCK_SIZE);
+
+        out += CAMELLIA_BLOCK_SIZE;
+        in  += CAMELLIA_BLOCK_SIZE;
+    }
+
+    return 0;
+}
+
+
+#endif /* HAVE_CAMELLIA */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/coding.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/coding.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/coding.c	(revision 453)
@@ -0,0 +1,511 @@
+/* coding.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifndef NO_CODING
+
+#include <wolfssl/wolfcrypt/coding.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#include <wolfssl/wolfcrypt/logging.h>
+
+
+enum {
+    BAD         = 0xFF,  /* invalid encoding */
+    PAD         = '=',
+    PEM_LINE_SZ = 64,
+    BASE64_MIN  = 0x2B,
+    BASE16_MIN  = 0x30,
+};
+
+
+#ifdef WOLFSSL_BASE64_DECODE
+
+static
+const byte base64Decode[] = { 62, BAD, BAD, BAD, 63,   /* + starts at 0x2B */
+                              52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+                              BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+                              0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+                              10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+                              20, 21, 22, 23, 24, 25,
+                              BAD, BAD, BAD, BAD, BAD, BAD,
+                              26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+                              36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+                              46, 47, 48, 49, 50, 51
+                            };
+
+static WC_INLINE int Base64_SkipNewline(const byte* in, word32 *inLen, word32 *outJ)
+{
+    word32 len = *inLen;
+    word32 j = *outJ;
+    if (len && (in[j] == ' ' || in[j] == '\r' || in[j] == '\n')) {
+        byte endLine = in[j++];
+        len--;
+        while (len && endLine == ' ') {   /* allow trailing whitespace */
+            endLine = in[j++];
+            len--;
+        }
+        if (endLine == '\r') {
+            if (len) {
+                endLine = in[j++];
+                len--;
+            }
+        }
+        if (endLine != '\n') {
+            WOLFSSL_MSG("Bad end of line in Base64 Decode");
+            return ASN_INPUT_E;
+        }
+    }
+    if (!len) {
+        return BUFFER_E;
+    }
+    *inLen = len;
+    *outJ = j;
+    return 0;
+}
+
+int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
+{
+    word32 i = 0;
+    word32 j = 0;
+    word32 plainSz = inLen - ((inLen + (PEM_LINE_SZ - 1)) / PEM_LINE_SZ );
+    int ret;
+    const byte maxIdx = (byte)sizeof(base64Decode) + BASE64_MIN - 1;
+
+    plainSz = (plainSz * 3 + 3) / 4;
+    if (plainSz > *outLen) return BAD_FUNC_ARG;
+
+    while (inLen > 3) {
+        int pad3 = 0;
+        int pad4 = 0;
+
+        byte b1, b2, b3;
+        byte e1, e2, e3, e4;
+        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
+            if (ret == BUFFER_E) {
+                /* Running out of buffer here is not an error */
+                break;
+            }
+            return ret;
+        }
+        e1 = in[j++];
+        if (e1 == '\0') {
+            break;
+        }
+        inLen--;
+        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
+            return ret;
+        }
+        e2 = in[j++];
+        inLen--;
+        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
+            return ret;
+        }
+        e3 = in[j++];
+        inLen--;
+        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
+            return ret;
+        }
+        e4 = in[j++];
+        inLen--;
+
+        if (e1 == 0)            /* end file 0's */
+            break;
+        if (e3 == PAD)
+            pad3 = 1;
+        if (e4 == PAD)
+            pad4 = 1;
+
+        if (e1 < BASE64_MIN || e2 < BASE64_MIN || e3 < BASE64_MIN || e4 < BASE64_MIN) {
+            WOLFSSL_MSG("Bad Base64 Decode data, too small");
+            return ASN_INPUT_E;
+        }
+
+        if (e1 > maxIdx || e2 > maxIdx || e3 > maxIdx || e4 > maxIdx) {
+            WOLFSSL_MSG("Bad Base64 Decode data, too big");
+            return ASN_INPUT_E;
+        }
+
+        if (i + 1 + !pad3 + !pad4 > *outLen) {
+            WOLFSSL_MSG("Bad Base64 Decode out buffer, too small");
+            return BAD_FUNC_ARG;
+        }
+
+        e1 = base64Decode[e1 - BASE64_MIN];
+        e2 = base64Decode[e2 - BASE64_MIN];
+        e3 = (e3 == PAD) ? 0 : base64Decode[e3 - BASE64_MIN];
+        e4 = (e4 == PAD) ? 0 : base64Decode[e4 - BASE64_MIN];
+
+        b1 = (byte)((e1 << 2) | (e2 >> 4));
+        b2 = (byte)(((e2 & 0xF) << 4) | (e3 >> 2));
+        b3 = (byte)(((e3 & 0x3) << 6) | e4);
+
+        out[i++] = b1;
+        if (!pad3)
+            out[i++] = b2;
+        if (!pad4)
+            out[i++] = b3;
+        else
+            break;
+    }
+/* If the output buffer has a room for an extra byte, add a null terminator */
+    if (out && *outLen > i)
+        out[i]= '\0';
+
+    *outLen = i;
+
+    return 0;
+}
+
+#endif /* WOLFSSL_BASE64_DECODE */
+
+#if defined(WOLFSSL_BASE64_ENCODE)
+
+static
+const byte base64Encode[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+                              'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+                              'U', 'V', 'W', 'X', 'Y', 'Z',
+                              'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
+                              'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
+                              'u', 'v', 'w', 'x', 'y', 'z',
+                              '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+                              '+', '/'
+                            };
+
+
+/* make sure *i (idx) won't exceed max, store and possibly escape to out,
+ * raw means use e w/o decode,  0 on success */
+static int CEscape(int escaped, byte e, byte* out, word32* i, word32 max,
+                  int raw, int getSzOnly)
+{
+    int    doEscape = 0;
+    word32 needed = 1;
+    word32 idx = *i;
+
+    byte basic;
+    byte plus    = 0;
+    byte equals  = 0;
+    byte newline = 0;
+
+    if (raw)
+        basic = e;
+    else
+        basic = base64Encode[e];
+
+    /* check whether to escape. Only escape for EncodeEsc */
+    if (escaped == WC_ESC_NL_ENC) {
+        switch ((char)basic) {
+            case '+' :
+                plus     = 1;
+                doEscape = 1;
+                needed  += 2;
+                break;
+            case '=' :
+                equals   = 1;
+                doEscape = 1;
+                needed  += 2;
+                break;
+            case '\n' :
+                newline  = 1;
+                doEscape = 1;
+                needed  += 2;
+                break;
+            default:
+                /* do nothing */
+                break;
+        }
+    }
+
+    /* check size */
+    if ( (idx+needed) > max && !getSzOnly) {
+        WOLFSSL_MSG("Escape buffer max too small");
+        return BUFFER_E;
+    }
+
+    /* store it */
+    if (doEscape == 0) {
+        if(getSzOnly)
+            idx++;
+        else
+            out[idx++] = basic;
+    }
+    else {
+        if(getSzOnly)
+            idx+=3;
+        else {
+            out[idx++] = '%';  /* start escape */
+
+            if (plus) {
+                out[idx++] = '2';
+                out[idx++] = 'B';
+            }
+            else if (equals) {
+                out[idx++] = '3';
+                out[idx++] = 'D';
+            }
+            else if (newline) {
+                out[idx++] = '0';
+                out[idx++] = 'A';
+            }
+        }
+    }
+    *i = idx;
+
+    return 0;
+}
+
+
+/* internal worker, handles both escaped and normal line endings.
+   If out buffer is NULL, will return sz needed in outLen */
+static int DoBase64_Encode(const byte* in, word32 inLen, byte* out,
+                           word32* outLen, int escaped)
+{
+    int    ret = 0;
+    word32 i = 0,
+           j = 0,
+           n = 0;   /* new line counter */
+
+    int    getSzOnly = (out == NULL);
+
+    word32 outSz = (inLen + 3 - 1) / 3 * 4;
+    word32 addSz = (outSz + PEM_LINE_SZ - 1) / PEM_LINE_SZ;  /* new lines */
+
+    if (escaped == WC_ESC_NL_ENC)
+        addSz *= 3;   /* instead of just \n, we're doing %0A triplet */
+    else if (escaped == WC_NO_NL_ENC)
+        addSz = 0;    /* encode without \n */
+
+    outSz += addSz;
+
+    /* if escaped we can't predetermine size for one pass encoding, but
+     * make sure we have enough if no escapes are in input
+     * Also need to ensure outLen valid before dereference */
+    if (!outLen || (outSz > *outLen && !getSzOnly)) return BAD_FUNC_ARG;
+
+    while (inLen > 2) {
+        byte b1 = in[j++];
+        byte b2 = in[j++];
+        byte b3 = in[j++];
+
+        /* encoded idx */
+        byte e1 = b1 >> 2;
+        byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
+        byte e3 = (byte)(((b2 & 0xF) << 2) | (b3 >> 6));
+        byte e4 = b3 & 0x3F;
+
+        /* store */
+        ret = CEscape(escaped, e1, out, &i, *outLen, 0, getSzOnly);
+        if (ret != 0) break;
+        ret = CEscape(escaped, e2, out, &i, *outLen, 0, getSzOnly);
+        if (ret != 0) break;
+        ret = CEscape(escaped, e3, out, &i, *outLen, 0, getSzOnly);
+        if (ret != 0) break;
+        ret = CEscape(escaped, e4, out, &i, *outLen, 0, getSzOnly);
+        if (ret != 0) break;
+
+        inLen -= 3;
+
+        /* Insert newline after PEM_LINE_SZ, unless no \n requested */
+        if (escaped != WC_NO_NL_ENC && (++n % (PEM_LINE_SZ/4)) == 0 && inLen) {
+            ret = CEscape(escaped, '\n', out, &i, *outLen, 1, getSzOnly);
+            if (ret != 0) break;
+        }
+    }
+
+    /* last integral */
+    if (inLen && ret == 0) {
+        int twoBytes = (inLen == 2);
+
+        byte b1 = in[j++];
+        byte b2 = (twoBytes) ? in[j++] : 0;
+
+        byte e1 = b1 >> 2;
+        byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
+        byte e3 = (byte)((b2 & 0xF) << 2);
+
+        ret = CEscape(escaped, e1, out, &i, *outLen, 0, getSzOnly);
+        if (ret == 0)
+            ret = CEscape(escaped, e2, out, &i, *outLen, 0, getSzOnly);
+        if (ret == 0) {
+            /* third */
+            if (twoBytes)
+                ret = CEscape(escaped, e3, out, &i, *outLen, 0, getSzOnly);
+            else
+                ret = CEscape(escaped, '=', out, &i, *outLen, 1, getSzOnly);
+        }
+        /* fourth always pad */
+        if (ret == 0)
+            ret = CEscape(escaped, '=', out, &i, *outLen, 1, getSzOnly);
+    }
+
+    if (ret == 0 && escaped != WC_NO_NL_ENC)
+        ret = CEscape(escaped, '\n', out, &i, *outLen, 1, getSzOnly);
+
+    if (i != outSz && escaped != 1 && ret == 0)
+        return ASN_INPUT_E;
+/* If the output buffer has a room for an extra byte, add a null terminator */
+    if (out && *outLen > i)
+        out[i]= '\0';
+
+    *outLen = i;
+
+    if (ret == 0)
+        return getSzOnly ? LENGTH_ONLY_E : 0;
+
+    return ret;
+}
+
+
+/* Base64 Encode, PEM style, with \n line endings */
+int Base64_Encode(const byte* in, word32 inLen, byte* out, word32* outLen)
+{
+    return DoBase64_Encode(in, inLen, out, outLen, WC_STD_ENC);
+}
+
+
+/* Base64 Encode, with %0A escaped line endings instead of \n */
+int Base64_EncodeEsc(const byte* in, word32 inLen, byte* out, word32* outLen)
+{
+    return DoBase64_Encode(in, inLen, out, outLen, WC_ESC_NL_ENC);
+}
+
+int Base64_Encode_NoNl(const byte* in, word32 inLen, byte* out, word32* outLen)
+{
+    return DoBase64_Encode(in, inLen, out, outLen, WC_NO_NL_ENC);
+}
+
+#endif /* WOLFSSL_BASE64_ENCODE */
+
+
+#ifdef WOLFSSL_BASE16
+
+static
+const byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+                           BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+                           10, 11, 12, 13, 14, 15,  /* upper case A-F */
+                           BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+                           BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+                           BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+                           BAD, BAD,  /* G - ` */
+                           10, 11, 12, 13, 14, 15   /* lower case a-f */
+                         };  /* A starts at 0x41 not 0x3A */
+
+int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
+{
+    word32 inIdx  = 0;
+    word32 outIdx = 0;
+
+    if (in == NULL || out == NULL || outLen == NULL)
+        return BAD_FUNC_ARG;
+
+    if (inLen == 1 && *outLen && in) {
+        byte b = in[inIdx++] - BASE16_MIN;  /* 0 starts at 0x30 */
+
+        /* sanity check */
+        if (b >=  sizeof(hexDecode)/sizeof(hexDecode[0]))
+            return ASN_INPUT_E;
+
+        b  = hexDecode[b];
+
+        if (b == BAD)
+            return ASN_INPUT_E;
+
+        out[outIdx++] = b;
+
+        *outLen = outIdx;
+        return 0;
+    }
+
+    if (inLen % 2)
+        return BAD_FUNC_ARG;
+
+    if (*outLen < (inLen / 2))
+        return BAD_FUNC_ARG;
+
+    while (inLen) {
+        byte b  = in[inIdx++] - BASE16_MIN;  /* 0 starts at 0x30 */
+        byte b2 = in[inIdx++] - BASE16_MIN;
+
+        /* sanity checks */
+        if (b >=  sizeof(hexDecode)/sizeof(hexDecode[0]))
+            return ASN_INPUT_E;
+        if (b2 >= sizeof(hexDecode)/sizeof(hexDecode[0]))
+            return ASN_INPUT_E;
+
+        b  = hexDecode[b];
+        b2 = hexDecode[b2];
+
+        if (b == BAD || b2 == BAD)
+            return ASN_INPUT_E;
+
+        out[outIdx++] = (byte)((b << 4) | b2);
+        inLen -= 2;
+    }
+
+    *outLen = outIdx;
+    return 0;
+}
+
+int Base16_Encode(const byte* in, word32 inLen, byte* out, word32* outLen)
+{
+    word32 outIdx = 0;
+    word32 i;
+    byte   hb, lb;
+
+    if (in == NULL || out == NULL || outLen == NULL)
+        return BAD_FUNC_ARG;
+
+    if (*outLen < (2 * inLen + 1))
+        return BAD_FUNC_ARG;
+
+    for (i = 0; i < inLen; i++) {
+        hb = in[i] >> 4;
+        lb = in[i] & 0x0f;
+
+        /* ASCII value */
+        hb += '0';
+        if (hb > '9')
+            hb += 7;
+
+        /* ASCII value */
+        lb += '0';
+        if (lb>'9')
+            lb += 7;
+
+        out[outIdx++] = hb;
+        out[outIdx++] = lb;
+    }
+
+    /* force 0 at this end */
+    out[outIdx++] = 0;
+
+    *outLen = outIdx;
+    return 0;
+}
+
+#endif /* WOLFSSL_BASE16 */
+
+#endif /* !NO_CODING */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/des3.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/des3.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/des3.c	(revision 453)
@@ -0,0 +1,1825 @@
+/* des3.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#include <wolfssl/wolfcrypt/logging.h>
+
+
+#ifndef NO_DES3
+
+#if defined(HAVE_FIPS) && \
+	defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
+
+    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
+    #define FIPS_NO_WRAPPERS
+
+    #ifdef USE_WINDOWS_API
+        #pragma code_seg(".fipsA$i")
+        #pragma const_seg(".fipsB$i")
+    #endif
+#endif
+
+#include <wolfssl/wolfcrypt/des3.h>
+
+#ifdef WOLF_CRYPTO_CB
+    #include <wolfssl/wolfcrypt/cryptocb.h>
+#endif
+
+/* fips wrapper calls, user can call direct */
+#if defined(HAVE_FIPS) && \
+    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
+
+    int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir)
+    {
+        return Des_SetKey(des, key, iv, dir);
+    }
+    int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir)
+    {
+        if (des == NULL || key == NULL || dir < 0) {
+            return BAD_FUNC_ARG;
+        }
+
+        return Des3_SetKey_fips(des, key, iv, dir);
+    }
+    int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz)
+    {
+        return Des_CbcEncrypt(des, out, in, sz);
+    }
+    int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz)
+    {
+        return Des_CbcDecrypt(des, out, in, sz);
+    }
+    int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz)
+    {
+        if (des == NULL || out == NULL || in == NULL) {
+            return BAD_FUNC_ARG;
+        }
+        return Des3_CbcEncrypt_fips(des, out, in, sz);
+    }
+    int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz)
+    {
+        if (des == NULL || out == NULL || in == NULL) {
+            return BAD_FUNC_ARG;
+        }
+        return Des3_CbcDecrypt_fips(des, out, in, sz);
+    }
+
+    #ifdef WOLFSSL_DES_ECB
+        /* One block, compatibility only */
+        int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz)
+        {
+            return Des_EcbEncrypt(des, out, in, sz);
+        }
+        int wc_Des3_EcbEncrypt(Des3* des, byte* out, const byte* in, word32 sz)
+        {
+            return Des3_EcbEncrypt(des, out, in, sz);
+        }
+    #endif /* WOLFSSL_DES_ECB */
+
+    void wc_Des_SetIV(Des* des, const byte* iv)
+    {
+        Des_SetIV(des, iv);
+    }
+    int wc_Des3_SetIV(Des3* des, const byte* iv)
+    {
+        return Des3_SetIV_fips(des, iv);
+    }
+
+    int wc_Des3Init(Des3* des3, void* heap, int devId)
+    {
+        (void)des3;
+        (void)heap;
+        (void)devId;
+        /* FIPS doesn't support:
+            return Des3Init(des3, heap, devId); */
+        return 0;
+    }
+    void wc_Des3Free(Des3* des3)
+    {
+        (void)des3;
+        /* FIPS doesn't support:
+            Des3Free(des3); */
+    }
+
+#else /* else build without fips, or for FIPS v2 */
+
+
+#if defined(WOLFSSL_TI_CRYPT)
+    #include <wolfcrypt/src/port/ti/ti-des3.c>
+#else
+
+
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+
+/* Hardware Acceleration */
+#if defined(STM32_CRYPTO)
+
+    /*
+     * STM32F2/F4 hardware DES/3DES support through the standard
+     * peripheral library. (See note in README).
+     */
+
+    int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir)
+    {
+        word32 *dkey = des->key;
+
+        (void)dir;
+
+        XMEMCPY(dkey, key, 8);
+    #ifndef WOLFSSL_STM32_CUBEMX
+        ByteReverseWords(dkey, dkey, 8);
+    #endif
+
+        wc_Des_SetIV(des, iv);
+
+        return 0;
+    }
+
+    int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir)
+    {
+        if (des == NULL || key == NULL)
+            return BAD_FUNC_ARG;
+
+        (void)dir;
+
+    #ifndef WOLFSSL_STM32_CUBEMX
+        {
+            word32 *dkey1 = des->key[0];
+            word32 *dkey2 = des->key[1];
+            word32 *dkey3 = des->key[2];
+
+            XMEMCPY(dkey1, key, 8);         /* set key 1 */
+            XMEMCPY(dkey2, key + 8, 8);     /* set key 2 */
+            XMEMCPY(dkey3, key + 16, 8);    /* set key 3 */
+
+            ByteReverseWords(dkey1, dkey1, 8);
+            ByteReverseWords(dkey2, dkey2, 8);
+            ByteReverseWords(dkey3, dkey3, 8);
+        }
+    #else
+        XMEMCPY(des->key[0], key, DES3_KEYLEN); /* CUBEMX wants keys in sequential memory */
+    #endif
+
+        return wc_Des3_SetIV(des, iv);
+    }
+
+    static void DesCrypt(Des* des, byte* out, const byte* in, word32 sz,
+                  int dir, int mode)
+    {
+        int ret;
+    #ifdef WOLFSSL_STM32_CUBEMX
+        CRYP_HandleTypeDef hcryp;
+    #else
+        word32 *dkey, *iv;
+        CRYP_InitTypeDef DES_CRYP_InitStructure;
+        CRYP_KeyInitTypeDef DES_CRYP_KeyInitStructure;
+        CRYP_IVInitTypeDef DES_CRYP_IVInitStructure;
+    #endif
+
+        ret = wolfSSL_CryptHwMutexLock();
+        if (ret != 0) {
+            return;
+        }
+
+    #ifdef WOLFSSL_STM32_CUBEMX
+        XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef));
+        hcryp.Instance = CRYP;
+        hcryp.Init.KeySize  = CRYP_KEYSIZE_128B;
+        hcryp.Init.DataType = CRYP_DATATYPE_8B;
+        hcryp.Init.pKey = (uint8_t*)des->key;
+        hcryp.Init.pInitVect = (uint8_t*)des->reg;
+
+        HAL_CRYP_Init(&hcryp);
+
+        while (sz > 0) {
+            /* if input and output same will overwrite input iv */
+            XMEMCPY(des->tmp, in + sz - DES_BLOCK_SIZE, DES_BLOCK_SIZE);
+
+            if (mode == DES_CBC) {
+                if (dir == DES_ENCRYPTION) {
+                    HAL_CRYP_DESCBC_Encrypt(&hcryp, (uint8_t*)in,
+                                    DES_BLOCK_SIZE, out, STM32_HAL_TIMEOUT);
+                }
+                else {
+                    HAL_CRYP_DESCBC_Decrypt(&hcryp, (uint8_t*)in,
+                                    DES_BLOCK_SIZE, out, STM32_HAL_TIMEOUT);
+                }
+            }
+            else {
+                if (dir == DES_ENCRYPTION) {
+                    HAL_CRYP_DESECB_Encrypt(&hcryp, (uint8_t*)in,
+                                    DES_BLOCK_SIZE, out, STM32_HAL_TIMEOUT);
+                }
+                else {
+                    HAL_CRYP_DESECB_Decrypt(&hcryp, (uint8_t*)in,
+                                    DES_BLOCK_SIZE, out, STM32_HAL_TIMEOUT);
+                }
+            }
+
+            /* store iv for next call */
+            XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE);
+
+            sz  -= DES_BLOCK_SIZE;
+            in  += DES_BLOCK_SIZE;
+            out += DES_BLOCK_SIZE;
+        }
+
+        HAL_CRYP_DeInit(&hcryp);
+    #else
+        dkey = des->key;
+        iv = des->reg;
+
+        /* crypto structure initialization */
+        CRYP_KeyStructInit(&DES_CRYP_KeyInitStructure);
+        CRYP_StructInit(&DES_CRYP_InitStructure);
+        CRYP_IVStructInit(&DES_CRYP_IVInitStructure);
+
+        /* reset registers to their default values */
+        CRYP_DeInit();
+
+        /* set direction, mode, and datatype */
+        if (dir == DES_ENCRYPTION) {
+            DES_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Encrypt;
+        } else { /* DES_DECRYPTION */
+            DES_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Decrypt;
+        }
+
+        if (mode == DES_CBC) {
+            DES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_DES_CBC;
+        } else { /* DES_ECB */
+            DES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_DES_ECB;
+        }
+
+        DES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b;
+        CRYP_Init(&DES_CRYP_InitStructure);
+
+        /* load key into correct registers */
+        DES_CRYP_KeyInitStructure.CRYP_Key1Left  = dkey[0];
+        DES_CRYP_KeyInitStructure.CRYP_Key1Right = dkey[1];
+        CRYP_KeyInit(&DES_CRYP_KeyInitStructure);
+
+        /* set iv */
+        ByteReverseWords(iv, iv, DES_BLOCK_SIZE);
+        DES_CRYP_IVInitStructure.CRYP_IV0Left  = iv[0];
+        DES_CRYP_IVInitStructure.CRYP_IV0Right = iv[1];
+        CRYP_IVInit(&DES_CRYP_IVInitStructure);
+
+        /* enable crypto processor */
+        CRYP_Cmd(ENABLE);
+
+        while (sz > 0) {
+            /* flush IN/OUT FIFOs */
+            CRYP_FIFOFlush();
+
+            /* if input and output same will overwrite input iv */
+            XMEMCPY(des->tmp, in + sz - DES_BLOCK_SIZE, DES_BLOCK_SIZE);
+
+            CRYP_DataIn(*(uint32_t*)&in[0]);
+            CRYP_DataIn(*(uint32_t*)&in[4]);
+
+            /* wait until the complete message has been processed */
+            while(CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {}
+
+            *(uint32_t*)&out[0]  = CRYP_DataOut();
+            *(uint32_t*)&out[4]  = CRYP_DataOut();
+
+            /* store iv for next call */
+            XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE);
+
+            sz  -= DES_BLOCK_SIZE;
+            in  += DES_BLOCK_SIZE;
+            out += DES_BLOCK_SIZE;
+        }
+
+        /* disable crypto processor */
+        CRYP_Cmd(DISABLE);
+    #endif /* WOLFSSL_STM32_CUBEMX */
+        wolfSSL_CryptHwMutexUnLock();
+    }
+
+    int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz)
+    {
+        DesCrypt(des, out, in, sz, DES_ENCRYPTION, DES_CBC);
+        return 0;
+    }
+
+    int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz)
+    {
+        DesCrypt(des, out, in, sz, DES_DECRYPTION, DES_CBC);
+        return 0;
+    }
+
+    int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz)
+    {
+        DesCrypt(des, out, in, sz, DES_ENCRYPTION, DES_ECB);
+        return 0;
+    }
+
+    static void Des3Crypt(Des3* des, byte* out, const byte* in, word32 sz,
+                   int dir)
+    {
+        if (des == NULL || out == NULL || in == NULL)
+            return BAD_FUNC_ARG;
+
+    #ifdef WOLFSSL_STM32_CUBEMX
+        {
+            CRYP_HandleTypeDef hcryp;
+
+            XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef));
+            hcryp.Instance = CRYP;
+            hcryp.Init.KeySize  = CRYP_KEYSIZE_128B;
+            hcryp.Init.DataType = CRYP_DATATYPE_8B;
+            hcryp.Init.pKey = (uint8_t*)des->key;
+            hcryp.Init.pInitVect = (uint8_t*)des->reg;
+
+            HAL_CRYP_Init(&hcryp);
+
+            while (sz > 0)
+            {
+                if (dir == DES_ENCRYPTION) {
+                    HAL_CRYP_TDESCBC_Encrypt(&hcryp, (byte*)in,
+                                       DES_BLOCK_SIZE, out, STM32_HAL_TIMEOUT);
+                }
+                else {
+                    HAL_CRYP_TDESCBC_Decrypt(&hcryp, (byte*)in,
+                                       DES_BLOCK_SIZE, out, STM32_HAL_TIMEOUT);
+                }
+
+                /* store iv for next call */
+                XMEMCPY(des->reg, out + sz - DES_BLOCK_SIZE, DES_BLOCK_SIZE);
+
+                sz  -= DES_BLOCK_SIZE;
+                in  += DES_BLOCK_SIZE;
+                out += DES_BLOCK_SIZE;
+            }
+
+            HAL_CRYP_DeInit(&hcryp);
+        }
+    #else
+        {
+            word32 *dkey1, *dkey2, *dkey3, *iv;
+            CRYP_InitTypeDef DES3_CRYP_InitStructure;
+            CRYP_KeyInitTypeDef DES3_CRYP_KeyInitStructure;
+            CRYP_IVInitTypeDef DES3_CRYP_IVInitStructure;
+
+            dkey1 = des->key[0];
+            dkey2 = des->key[1];
+            dkey3 = des->key[2];
+            iv = des->reg;
+
+            /* crypto structure initialization */
+            CRYP_KeyStructInit(&DES3_CRYP_KeyInitStructure);
+            CRYP_StructInit(&DES3_CRYP_InitStructure);
+            CRYP_IVStructInit(&DES3_CRYP_IVInitStructure);
+
+            /* reset registers to their default values */
+            CRYP_DeInit();
+
+            /* set direction, mode, and datatype */
+            if (dir == DES_ENCRYPTION) {
+                DES3_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Encrypt;
+            } else {
+                DES3_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Decrypt;
+            }
+
+            DES3_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_TDES_CBC;
+            DES3_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b;
+            CRYP_Init(&DES3_CRYP_InitStructure);
+
+            /* load key into correct registers */
+            DES3_CRYP_KeyInitStructure.CRYP_Key1Left  = dkey1[0];
+            DES3_CRYP_KeyInitStructure.CRYP_Key1Right = dkey1[1];
+            DES3_CRYP_KeyInitStructure.CRYP_Key2Left  = dkey2[0];
+            DES3_CRYP_KeyInitStructure.CRYP_Key2Right = dkey2[1];
+            DES3_CRYP_KeyInitStructure.CRYP_Key3Left  = dkey3[0];
+            DES3_CRYP_KeyInitStructure.CRYP_Key3Right = dkey3[1];
+            CRYP_KeyInit(&DES3_CRYP_KeyInitStructure);
+
+            /* set iv */
+            ByteReverseWords(iv, iv, DES_BLOCK_SIZE);
+            DES3_CRYP_IVInitStructure.CRYP_IV0Left  = iv[0];
+            DES3_CRYP_IVInitStructure.CRYP_IV0Right = iv[1];
+            CRYP_IVInit(&DES3_CRYP_IVInitStructure);
+
+            /* enable crypto processor */
+            CRYP_Cmd(ENABLE);
+
+            while (sz > 0)
+            {
+                /* flush IN/OUT FIFOs */
+                CRYP_FIFOFlush();
+
+                CRYP_DataIn(*(uint32_t*)&in[0]);
+                CRYP_DataIn(*(uint32_t*)&in[4]);
+
+                /* wait until the complete message has been processed */
+                while(CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {}
+
+                *(uint32_t*)&out[0]  = CRYP_DataOut();
+                *(uint32_t*)&out[4]  = CRYP_DataOut();
+
+                /* store iv for next call */
+                XMEMCPY(des->reg, out + sz - DES_BLOCK_SIZE, DES_BLOCK_SIZE);
+
+                sz  -= DES_BLOCK_SIZE;
+                in  += DES_BLOCK_SIZE;
+                out += DES_BLOCK_SIZE;
+            }
+
+            /* disable crypto processor */
+            CRYP_Cmd(DISABLE);
+        }
+    #endif /* WOLFSSL_STM32_CUBEMX */
+    }
+
+    int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz)
+    {
+        Des3Crypt(des, out, in, sz, DES_ENCRYPTION);
+        return 0;
+    }
+
+    int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz)
+    {
+        Des3Crypt(des, out, in, sz, DES_DECRYPTION);
+        return 0;
+    }
+
+#elif defined(HAVE_COLDFIRE_SEC)
+
+    #include <wolfssl/ctaocrypt/types.h>
+
+    #include "sec.h"
+    #include "mcf5475_sec.h"
+    #include "mcf5475_siu.h"
+
+    #if defined (HAVE_THREADX)
+    #include "memory_pools.h"
+    extern TX_BYTE_POOL mp_ncached;  /* Non Cached memory pool */
+    #endif
+
+    #define DES_BUFFER_SIZE (DES_BLOCK_SIZE * 64)
+    static unsigned char *desBuffIn = NULL;
+    static unsigned char *desBuffOut = NULL;
+    static byte *secIV;
+    static byte *secKey;
+    static volatile SECdescriptorType *secDesc;
+
+    static wolfSSL_Mutex Mutex_DesSEC;
+
+    #define SEC_DESC_DES_CBC_ENCRYPT  0x20500010
+    #define SEC_DESC_DES_CBC_DECRYPT  0x20400010
+    #define SEC_DESC_DES3_CBC_ENCRYPT 0x20700010
+    #define SEC_DESC_DES3_CBC_DECRYPT 0x20600010
+
+    #define DES_IVLEN 8
+    #define DES_KEYLEN 8
+    #define DES3_IVLEN 8
+    #define DES3_KEYLEN 24
+
+    extern volatile unsigned char __MBAR[];
+
+    static void wc_Des_Cbc(byte* out, const byte* in, word32 sz,
+                        byte *key, byte *iv, word32 desc)
+    {
+        #ifdef DEBUG_WOLFSSL
+        int ret;  int stat1,stat2;
+    	  #endif
+        int size;
+        volatile int v;
+
+        wc_LockMutex(&Mutex_DesSEC) ;
+
+        secDesc->length1 = 0x0;
+        secDesc->pointer1 = NULL;
+        if((desc==SEC_DESC_DES_CBC_ENCRYPT)||(desc==SEC_DESC_DES_CBC_DECRYPT)){
+            secDesc->length2 = DES_IVLEN;
+            secDesc->length3 = DES_KEYLEN;
+        } else {
+            secDesc->length2 = DES3_IVLEN;
+            secDesc->length3 = DES3_KEYLEN;
+        }
+        secDesc->pointer2 = secIV;
+        secDesc->pointer3 = secKey;
+        secDesc->pointer4 = desBuffIn;
+        secDesc->pointer5 = desBuffOut;
+        secDesc->length6 = 0;
+        secDesc->pointer6 = NULL;
+        secDesc->length7 = 0x0;
+        secDesc->pointer7 = NULL;
+        secDesc->nextDescriptorPtr = NULL;
+
+        while(sz) {
+            XMEMCPY(secIV, iv, secDesc->length2);
+            if((sz%DES_BUFFER_SIZE) == sz) {
+                size = sz;
+                sz = 0;
+            } else {
+                size = DES_BUFFER_SIZE;
+                sz -= DES_BUFFER_SIZE;
+            }
+
+            XMEMCPY(desBuffIn, in, size);
+            XMEMCPY(secKey, key, secDesc->length3);
+
+            secDesc->header = desc;
+            secDesc->length4 = size;
+            secDesc->length5 = size;
+            /* Point SEC to the location of the descriptor */
+            MCF_SEC_FR0 = (uint32)secDesc;
+            /* Initialize SEC and wait for encryption to complete */
+            MCF_SEC_CCCR0 = 0x0000001a;
+            /* poll SISR to determine when channel is complete */
+            v=0;
+            while((secDesc->header>> 24) != 0xff) {
+                if(v++ > 1000)break;
+            }
+
+        #ifdef DEBUG_WOLFSSL
+            ret = MCF_SEC_SISRH;
+            stat1 = MCF_SEC_DSR;
+            stat2 = MCF_SEC_DISR;
+            if(ret & 0xe0000000) {
+                /* db_printf("Des_Cbc(%x):ISRH=%08x, DSR=%08x, DISR=%08x\n", desc, ret, stat1, stat2); */
+            }
+        #endif
+
+            XMEMCPY(out, desBuffOut, size);
+
+            if ((desc==SEC_DESC_DES3_CBC_ENCRYPT)||(desc==SEC_DESC_DES_CBC_ENCRYPT)) {
+                XMEMCPY((void*)iv, (void*)&(out[size-secDesc->length2]), secDesc->length2);
+            } else {
+                XMEMCPY((void*)iv, (void*)&(in[size-secDesc->length2]), secDesc->length2);
+            }
+
+            in  += size;
+            out += size;
+
+        }
+        wc_UnLockMutex(&Mutex_DesSEC) ;
+
+    }
+
+
+    int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz)
+    {
+        wc_Des_Cbc(out, in, sz,  (byte *)des->key,  (byte *)des->reg, SEC_DESC_DES_CBC_ENCRYPT);
+        return 0;
+    }
+
+    int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz)
+    {
+        wc_Des_Cbc(out, in, sz,   (byte *)des->key,  (byte *)des->reg, SEC_DESC_DES_CBC_DECRYPT);
+        return 0;
+    }
+
+    int wc_Des3_CbcEncrypt(Des3* des3, byte* out, const byte* in, word32 sz)
+    {
+        wc_Des_Cbc(out, in, sz,  (byte *)des3->key,  (byte *)des3->reg, SEC_DESC_DES3_CBC_ENCRYPT);
+    	  return 0;
+    }
+
+
+    int wc_Des3_CbcDecrypt(Des3* des3, byte* out, const byte* in, word32 sz)
+    {
+        wc_Des_Cbc(out, in, sz,   (byte *)des3->key,  (byte *)des3->reg, SEC_DESC_DES3_CBC_DECRYPT);
+    	  return 0;
+    }
+
+    static void setParity(byte *buf, int len)
+    {
+        int i, j;
+        byte v;
+        int bits;
+
+        for (i=0; i<len; i++) {
+            v = buf[i] >> 1;
+            buf[i] = v << 1;
+            bits = 0;
+            for (j=0; j<7; j++) {
+                bits += (v&0x1);
+                v = v >> 1;
+            }
+            buf[i] |= (1 - (bits&0x1));
+        }
+
+    }
+
+    int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir)
+    {
+        if(desBuffIn == NULL) {
+        #if defined (HAVE_THREADX)
+    			  int s1, s2, s3, s4, s5;
+            s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc,
+                                                         sizeof(SECdescriptorType), TX_NO_WAIT);
+            s1 = tx_byte_allocate(&mp_ncached,(void *)&desBuffIn,  DES_BUFFER_SIZE, TX_NO_WAIT);
+            s2 = tx_byte_allocate(&mp_ncached,(void *)&desBuffOut, DES_BUFFER_SIZE, TX_NO_WAIT);
+            /* Don't know des or des3 to be used. Allocate larger buffers */
+            s3 = tx_byte_allocate(&mp_ncached,(void *)&secKey,     DES3_KEYLEN,TX_NO_WAIT);
+            s4 = tx_byte_allocate(&mp_ncached,(void *)&secIV,      DES3_IVLEN,  TX_NO_WAIT);
+        #else
+            #warning "Allocate non-Cache buffers"
+        #endif
+
+            InitMutex(&Mutex_DesSEC);
+        }
+
+        XMEMCPY(des->key, key, DES_KEYLEN);
+        setParity((byte *)des->key, DES_KEYLEN);
+
+        if (iv) {
+            XMEMCPY(des->reg, iv, DES_IVLEN);
+        }   else {
+            XMEMSET(des->reg, 0x0, DES_IVLEN);
+        }
+    		return 0;
+    }
+
+    int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir)
+    {
+        if (des3 == NULL || key == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        if (desBuffIn == NULL) {
+        #if defined (HAVE_THREADX)
+            int s1, s2, s3, s4, s5;
+            s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc,
+                                                         sizeof(SECdescriptorType), TX_NO_WAIT);
+            s1 = tx_byte_allocate(&mp_ncached,(void *)&desBuffIn,  DES_BUFFER_SIZE, TX_NO_WAIT);
+            s2 = tx_byte_allocate(&mp_ncached,(void *)&desBuffOut, DES_BUFFER_SIZE, TX_NO_WAIT);
+            s3 = tx_byte_allocate(&mp_ncached,(void *)&secKey,     DES3_KEYLEN,TX_NO_WAIT);
+            s4 = tx_byte_allocate(&mp_ncached,(void *)&secIV,      DES3_IVLEN,  TX_NO_WAIT);
+        #else
+            #warning "Allocate non-Cache buffers"
+        #endif
+
+            InitMutex(&Mutex_DesSEC);
+        }
+
+        XMEMCPY(des3->key[0], key, DES3_KEYLEN);
+        setParity((byte *)des3->key[0], DES3_KEYLEN);
+
+        if (iv) {
+            XMEMCPY(des3->reg, iv, DES3_IVLEN);
+        }   else {
+            XMEMSET(des3->reg, 0x0, DES3_IVLEN);
+        }
+        return 0;
+
+    }
+#elif defined(FREESCALE_LTC_DES)
+
+    #include "fsl_ltc.h"
+    int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir)
+    {
+        byte* dkey;
+
+        if (des == NULL || key == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        dkey = (byte*)des->key;
+
+        XMEMCPY(dkey, key, 8);
+
+        wc_Des_SetIV(des, iv);
+
+        return 0;
+    }
+
+    int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir)
+    {
+        int ret = 0;
+        byte* dkey1 = (byte*)des->key[0];
+        byte* dkey2 = (byte*)des->key[1];
+        byte* dkey3 = (byte*)des->key[2];
+
+        XMEMCPY(dkey1, key, 8);         /* set key 1 */
+        XMEMCPY(dkey2, key + 8, 8);     /* set key 2 */
+        XMEMCPY(dkey3, key + 16, 8);    /* set key 3 */
+
+        ret = wc_Des3_SetIV(des, iv);
+        if (ret != 0)
+            return ret;
+
+        return ret;
+    }
+
+    int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz)
+    {
+        status_t status;
+        status = LTC_DES_EncryptCbc(LTC_BASE, in, out, sz, (byte*)des->reg, (byte*)des->key);
+        if (status == kStatus_Success)
+            return 0;
+        else
+            return -1;
+    }
+
+    int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz)
+    {
+        status_t status;
+        status = LTC_DES_DecryptCbc(LTC_BASE, in, out, sz, (byte*)des->reg, (byte*)des->key);
+        if (status == kStatus_Success)
+            return 0;
+        else
+            return -1;
+    }
+
+    int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz)
+    {
+        status_t status;
+        status = LTC_DES3_EncryptCbc(LTC_BASE,
+                                 in,
+                                 out,
+                                 sz,
+                                 (byte*)des->reg,
+                                 (byte*)des->key[0],
+                                 (byte*)des->key[1],
+                                 (byte*)des->key[2]);
+        if (status == kStatus_Success)
+            return 0;
+        else
+            return -1;
+    }
+
+    int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz)
+    {
+        status_t status;
+        status = LTC_DES3_DecryptCbc(LTC_BASE,
+                                 in,
+                                 out,
+                                 sz,
+                                 (byte*)des->reg,
+                                 (byte*)des->key[0],
+                                 (byte*)des->key[1],
+                                 (byte*)des->key[2]);
+        if (status == kStatus_Success)
+            return 0;
+        else
+            return -1;
+
+    }
+
+#elif defined(FREESCALE_MMCAU)
+    /*
+     * Freescale mmCAU hardware DES/3DES support through the CAU/mmCAU library.
+     * Documentation located in ColdFire/ColdFire+ CAU and Kinetis mmCAU
+     * Software Library User Guide (See note in README).
+     */
+    #ifdef FREESCALE_MMCAU_CLASSIC
+        #include "cau_api.h"
+    #else
+        #include "fsl_mmcau.h"
+    #endif
+
+    const unsigned char parityLookup[128] = {
+        1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
+        0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
+        0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
+        1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0
+     };
+
+    int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir)
+    {
+        int i = 0;
+        byte* dkey;
+
+
+        if (des == NULL || key == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        dkey = (byte*)des->key;
+
+        XMEMCPY(dkey, key, 8);
+
+        wc_Des_SetIV(des, iv);
+
+        /* fix key parity, if needed */
+        for (i = 0; i < 8; i++) {
+            dkey[i] = ((dkey[i] & 0xFE) | parityLookup[dkey[i] >> 1]);
+        }
+
+        return 0;
+    }
+
+    int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir)
+    {
+        int i = 0, ret = 0;
+        byte* dkey1 = (byte*)des->key[0];
+        byte* dkey2 = (byte*)des->key[1];
+        byte* dkey3 = (byte*)des->key[2];
+
+        XMEMCPY(dkey1, key, 8);         /* set key 1 */
+        XMEMCPY(dkey2, key + 8, 8);     /* set key 2 */
+        XMEMCPY(dkey3, key + 16, 8);    /* set key 3 */
+
+        ret = wc_Des3_SetIV(des, iv);
+        if (ret != 0)
+            return ret;
+
+        /* fix key parity if needed */
+        for (i = 0; i < 8; i++)
+           dkey1[i] = ((dkey1[i] & 0xFE) | parityLookup[dkey1[i] >> 1]);
+
+        for (i = 0; i < 8; i++)
+           dkey2[i] = ((dkey2[i] & 0xFE) | parityLookup[dkey2[i] >> 1]);
+
+        for (i = 0; i < 8; i++)
+           dkey3[i] = ((dkey3[i] & 0xFE) | parityLookup[dkey3[i] >> 1]);
+
+        return ret;
+    }
+
+    int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz)
+    {
+        int i;
+        int offset = 0;
+        int len = sz;
+        int ret = 0;
+        byte *iv;
+        byte temp_block[DES_BLOCK_SIZE];
+
+        iv = (byte*)des->reg;
+
+    #ifdef FREESCALE_MMCAU_CLASSIC
+        if ((wolfssl_word)out % WOLFSSL_MMCAU_ALIGNMENT) {
+            WOLFSSL_MSG("Bad cau_des_encrypt alignment");
+            return BAD_ALIGN_E;
+        }
+    #endif
+
+        while (len > 0)
+        {
+            XMEMCPY(temp_block, in + offset, DES_BLOCK_SIZE);
+
+            /* XOR block with IV for CBC */
+            for (i = 0; i < DES_BLOCK_SIZE; i++)
+                temp_block[i] ^= iv[i];
+
+            ret = wolfSSL_CryptHwMutexLock();
+            if(ret != 0) {
+                return ret;
+            }
+        #ifdef FREESCALE_MMCAU_CLASSIC
+            cau_des_encrypt(temp_block, (byte*)des->key, out + offset);
+        #else
+            MMCAU_DES_EncryptEcb(temp_block, (byte*)des->key, out + offset);
+        #endif
+            wolfSSL_CryptHwMutexUnLock();
+
+            len    -= DES_BLOCK_SIZE;
+            offset += DES_BLOCK_SIZE;
+
+            /* store IV for next block */
+            XMEMCPY(iv, out + offset - DES_BLOCK_SIZE, DES_BLOCK_SIZE);
+        }
+
+        return ret;
+    }
+
+    int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz)
+    {
+        int i;
+        int offset = 0;
+        int len = sz;
+        int ret = 0;
+        byte* iv;
+        byte temp_block[DES_BLOCK_SIZE];
+
+        iv = (byte*)des->reg;
+
+    #ifdef FREESCALE_MMCAU_CLASSIC
+        if ((wolfssl_word)out % WOLFSSL_MMCAU_ALIGNMENT) {
+            WOLFSSL_MSG("Bad cau_des_decrypt alignment");
+            return BAD_ALIGN_E;
+        }
+    #endif
+
+        while (len > 0)
+        {
+            XMEMCPY(temp_block, in + offset, DES_BLOCK_SIZE);
+
+            ret = wolfSSL_CryptHwMutexLock();
+            if(ret != 0) {
+                return ret;
+            }
+
+        #ifdef FREESCALE_MMCAU_CLASSIC
+            cau_des_decrypt(in + offset, (byte*)des->key, out + offset);
+        #else
+            MMCAU_DES_DecryptEcb(in + offset, (byte*)des->key, out + offset);
+        #endif
+            wolfSSL_CryptHwMutexUnLock();
+
+            /* XOR block with IV for CBC */
+            for (i = 0; i < DES_BLOCK_SIZE; i++)
+                (out + offset)[i] ^= iv[i];
+
+            /* store IV for next block */
+            XMEMCPY(iv, temp_block, DES_BLOCK_SIZE);
+
+            len     -= DES_BLOCK_SIZE;
+            offset += DES_BLOCK_SIZE;
+        }
+
+        return ret;
+    }
+
+    int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz)
+    {
+        int i;
+        int offset = 0;
+        int len = sz;
+        int ret = 0;
+
+        byte *iv;
+        byte temp_block[DES_BLOCK_SIZE];
+
+        iv = (byte*)des->reg;
+
+    #ifdef FREESCALE_MMCAU_CLASSIC
+        if ((wolfssl_word)out % WOLFSSL_MMCAU_ALIGNMENT) {
+            WOLFSSL_MSG("Bad 3ede cau_des_encrypt alignment");
+            return BAD_ALIGN_E;
+        }
+    #endif
+
+        while (len > 0)
+        {
+            XMEMCPY(temp_block, in + offset, DES_BLOCK_SIZE);
+
+            /* XOR block with IV for CBC */
+            for (i = 0; i < DES_BLOCK_SIZE; i++)
+                temp_block[i] ^= iv[i];
+
+            ret = wolfSSL_CryptHwMutexLock();
+            if(ret != 0) {
+                return ret;
+            }
+    #ifdef FREESCALE_MMCAU_CLASSIC
+            cau_des_encrypt(temp_block,   (byte*)des->key[0], out + offset);
+            cau_des_decrypt(out + offset, (byte*)des->key[1], out + offset);
+            cau_des_encrypt(out + offset, (byte*)des->key[2], out + offset);
+    #else
+            MMCAU_DES_EncryptEcb(temp_block  , (byte*)des->key[0], out + offset);
+            MMCAU_DES_DecryptEcb(out + offset, (byte*)des->key[1], out + offset);
+            MMCAU_DES_EncryptEcb(out + offset, (byte*)des->key[2], out + offset);
+    #endif
+            wolfSSL_CryptHwMutexUnLock();
+
+            len    -= DES_BLOCK_SIZE;
+            offset += DES_BLOCK_SIZE;
+
+            /* store IV for next block */
+            XMEMCPY(iv, out + offset - DES_BLOCK_SIZE, DES_BLOCK_SIZE);
+        }
+
+        return ret;
+    }
+
+    int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz)
+    {
+        int i;
+        int offset = 0;
+        int len = sz;
+        int ret = 0;
+
+        byte* iv;
+        byte temp_block[DES_BLOCK_SIZE];
+
+        iv = (byte*)des->reg;
+
+    #ifdef FREESCALE_MMCAU_CLASSIC
+        if ((wolfssl_word)out % WOLFSSL_MMCAU_ALIGNMENT) {
+            WOLFSSL_MSG("Bad 3ede cau_des_decrypt alignment");
+            return BAD_ALIGN_E;
+        }
+    #endif
+
+        while (len > 0)
+        {
+            XMEMCPY(temp_block, in + offset, DES_BLOCK_SIZE);
+
+            ret = wolfSSL_CryptHwMutexLock();
+            if(ret != 0) {
+                return ret;
+            }
+        #ifdef FREESCALE_MMCAU_CLASSIC
+            cau_des_decrypt(in + offset,  (byte*)des->key[2], out + offset);
+            cau_des_encrypt(out + offset, (byte*)des->key[1], out + offset);
+            cau_des_decrypt(out + offset, (byte*)des->key[0], out + offset);
+        #else
+            MMCAU_DES_DecryptEcb(in + offset , (byte*)des->key[2], out + offset);
+            MMCAU_DES_EncryptEcb(out + offset, (byte*)des->key[1], out + offset);
+            MMCAU_DES_DecryptEcb(out + offset, (byte*)des->key[0], out + offset);
+        #endif
+            wolfSSL_CryptHwMutexUnLock();
+
+            /* XOR block with IV for CBC */
+            for (i = 0; i < DES_BLOCK_SIZE; i++)
+                (out + offset)[i] ^= iv[i];
+
+            /* store IV for next block */
+            XMEMCPY(iv, temp_block, DES_BLOCK_SIZE);
+
+            len    -= DES_BLOCK_SIZE;
+            offset += DES_BLOCK_SIZE;
+        }
+
+        return ret;
+    }
+
+
+#elif defined(WOLFSSL_PIC32MZ_CRYPT)
+
+    /* PIC32MZ DES hardware requires size multiple of block size */
+    #include <wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h>
+
+    int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir)
+    {
+        if (des == NULL || key == NULL || iv == NULL)
+            return BAD_FUNC_ARG;
+
+        XMEMCPY(des->key, key, DES_KEYLEN);
+        XMEMCPY(des->reg, iv, DES_IVLEN);
+
+        return 0;
+    }
+
+    int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir)
+    {
+        if (des == NULL || key == NULL || iv == NULL)
+            return BAD_FUNC_ARG;
+
+        XMEMCPY(des->key[0], key, DES3_KEYLEN);
+        XMEMCPY(des->reg, iv, DES3_IVLEN);
+
+        return 0;
+    }
+
+    int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz)
+    {
+        word32 blocks = sz / DES_BLOCK_SIZE;
+
+        if (des == NULL || out == NULL || in == NULL)
+            return BAD_FUNC_ARG;
+
+        return wc_Pic32DesCrypt(des->key, DES_KEYLEN, des->reg, DES_IVLEN,
+            out, in, (blocks * DES_BLOCK_SIZE),
+            PIC32_ENCRYPTION, PIC32_ALGO_DES, PIC32_CRYPTOALGO_CBC);
+    }
+
+    int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz)
+    {
+        word32 blocks = sz / DES_BLOCK_SIZE;
+
+        if (des == NULL || out == NULL || in == NULL)
+            return BAD_FUNC_ARG;
+
+        return wc_Pic32DesCrypt(des->key, DES_KEYLEN, des->reg, DES_IVLEN,
+            out, in, (blocks * DES_BLOCK_SIZE),
+            PIC32_DECRYPTION, PIC32_ALGO_DES, PIC32_CRYPTOALGO_CBC);
+    }
+
+    int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz)
+    {
+        word32 blocks = sz / DES_BLOCK_SIZE;
+
+        if (des == NULL || out == NULL || in == NULL)
+            return BAD_FUNC_ARG;
+
+        return wc_Pic32DesCrypt(des->key[0], DES3_KEYLEN, des->reg, DES3_IVLEN,
+            out, in, (blocks * DES_BLOCK_SIZE),
+            PIC32_ENCRYPTION, PIC32_ALGO_TDES, PIC32_CRYPTOALGO_TCBC);
+    }
+
+    int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz)
+    {
+        word32 blocks = sz / DES_BLOCK_SIZE;
+
+        if (des == NULL || out == NULL || in == NULL)
+            return BAD_FUNC_ARG;
+
+        return wc_Pic32DesCrypt(des->key[0], DES3_KEYLEN, des->reg, DES3_IVLEN,
+            out, in, (blocks * DES_BLOCK_SIZE),
+            PIC32_DECRYPTION, PIC32_ALGO_TDES, PIC32_CRYPTOALGO_TCBC);
+    }
+
+    #ifdef WOLFSSL_DES_ECB
+        int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz)
+        {
+            word32 blocks = sz / DES_BLOCK_SIZE;
+
+            if (des == NULL || out == NULL || in == NULL)
+                return BAD_FUNC_ARG;
+
+            return wc_Pic32DesCrypt(des->key, DES_KEYLEN, des->reg, DES_IVLEN,
+                out, in, (blocks * DES_BLOCK_SIZE),
+                    PIC32_ENCRYPTION, PIC32_ALGO_DES, PIC32_CRYPTOALGO_ECB);
+        }
+
+        int wc_Des3_EcbEncrypt(Des3* des, byte* out, const byte* in, word32 sz)
+        {
+            word32 blocks = sz / DES_BLOCK_SIZE;
+
+            if (des == NULL || out == NULL || in == NULL)
+                return BAD_FUNC_ARG;
+
+            return wc_Pic32DesCrypt(des->key[0], DES3_KEYLEN, des->reg, DES3_IVLEN,
+                out, in, (blocks * DES_BLOCK_SIZE),
+                PIC32_ENCRYPTION, PIC32_ALGO_TDES, PIC32_CRYPTOALGO_TECB);
+        }
+    #endif /* WOLFSSL_DES_ECB */
+
+#else
+    #define NEED_SOFT_DES
+
+#endif
+
+
+#ifdef NEED_SOFT_DES
+
+    /* permuted choice table (key) */
+    static const byte pc1[] = {
+           57, 49, 41, 33, 25, 17,  9,
+            1, 58, 50, 42, 34, 26, 18,
+           10,  2, 59, 51, 43, 35, 27,
+           19, 11,  3, 60, 52, 44, 36,
+
+           63, 55, 47, 39, 31, 23, 15,
+            7, 62, 54, 46, 38, 30, 22,
+           14,  6, 61, 53, 45, 37, 29,
+           21, 13,  5, 28, 20, 12,  4
+    };
+
+    /* number left rotations of pc1 */
+    static const byte totrot[] = {
+           1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28
+    };
+
+    /* permuted choice key (table) */
+    static const byte pc2[] = {
+           14, 17, 11, 24,  1,  5,
+            3, 28, 15,  6, 21, 10,
+           23, 19, 12,  4, 26,  8,
+           16,  7, 27, 20, 13,  2,
+           41, 52, 31, 37, 47, 55,
+           30, 40, 51, 45, 33, 48,
+           44, 49, 39, 56, 34, 53,
+           46, 42, 50, 36, 29, 32
+    };
+
+    /* End of DES-defined tables */
+
+    /* bit 0 is left-most in byte */
+    static const int bytebit[] = {
+        0200,0100,040,020,010,04,02,01
+    };
+
+    static const word32 Spbox[8][64] = {
+    {   0x01010400,0x00000000,0x00010000,0x01010404,
+        0x01010004,0x00010404,0x00000004,0x00010000,
+        0x00000400,0x01010400,0x01010404,0x00000400,
+        0x01000404,0x01010004,0x01000000,0x00000004,
+        0x00000404,0x01000400,0x01000400,0x00010400,
+        0x00010400,0x01010000,0x01010000,0x01000404,
+        0x00010004,0x01000004,0x01000004,0x00010004,
+        0x00000000,0x00000404,0x00010404,0x01000000,
+        0x00010000,0x01010404,0x00000004,0x01010000,
+        0x01010400,0x01000000,0x01000000,0x00000400,
+        0x01010004,0x00010000,0x00010400,0x01000004,
+        0x00000400,0x00000004,0x01000404,0x00010404,
+        0x01010404,0x00010004,0x01010000,0x01000404,
+        0x01000004,0x00000404,0x00010404,0x01010400,
+        0x00000404,0x01000400,0x01000400,0x00000000,
+        0x00010004,0x00010400,0x00000000,0x01010004},
+    {   0x80108020,0x80008000,0x00008000,0x00108020,
+        0x00100000,0x00000020,0x80100020,0x80008020,
+        0x80000020,0x80108020,0x80108000,0x80000000,
+        0x80008000,0x00100000,0x00000020,0x80100020,
+        0x00108000,0x00100020,0x80008020,0x00000000,
+        0x80000000,0x00008000,0x00108020,0x80100000,
+        0x00100020,0x80000020,0x00000000,0x00108000,
+        0x00008020,0x80108000,0x80100000,0x00008020,
+        0x00000000,0x00108020,0x80100020,0x00100000,
+        0x80008020,0x80100000,0x80108000,0x00008000,
+        0x80100000,0x80008000,0x00000020,0x80108020,
+        0x00108020,0x00000020,0x00008000,0x80000000,
+        0x00008020,0x80108000,0x00100000,0x80000020,
+        0x00100020,0x80008020,0x80000020,0x00100020,
+        0x00108000,0x00000000,0x80008000,0x00008020,
+        0x80000000,0x80100020,0x80108020,0x00108000},
+    {   0x00000208,0x08020200,0x00000000,0x08020008,
+        0x08000200,0x00000000,0x00020208,0x08000200,
+        0x00020008,0x08000008,0x08000008,0x00020000,
+        0x08020208,0x00020008,0x08020000,0x00000208,
+        0x08000000,0x00000008,0x08020200,0x00000200,
+        0x00020200,0x08020000,0x08020008,0x00020208,
+        0x08000208,0x00020200,0x00020000,0x08000208,
+        0x00000008,0x08020208,0x00000200,0x08000000,
+        0x08020200,0x08000000,0x00020008,0x00000208,
+        0x00020000,0x08020200,0x08000200,0x00000000,
+        0x00000200,0x00020008,0x08020208,0x08000200,
+        0x08000008,0x00000200,0x00000000,0x08020008,
+        0x08000208,0x00020000,0x08000000,0x08020208,
+        0x00000008,0x00020208,0x00020200,0x08000008,
+        0x08020000,0x08000208,0x00000208,0x08020000,
+        0x00020208,0x00000008,0x08020008,0x00020200},
+    {   0x00802001,0x00002081,0x00002081,0x00000080,
+        0x00802080,0x00800081,0x00800001,0x00002001,
+        0x00000000,0x00802000,0x00802000,0x00802081,
+        0x00000081,0x00000000,0x00800080,0x00800001,
+        0x00000001,0x00002000,0x00800000,0x00802001,
+        0x00000080,0x00800000,0x00002001,0x00002080,
+        0x00800081,0x00000001,0x00002080,0x00800080,
+        0x00002000,0x00802080,0x00802081,0x00000081,
+        0x00800080,0x00800001,0x00802000,0x00802081,
+        0x00000081,0x00000000,0x00000000,0x00802000,
+        0x00002080,0x00800080,0x00800081,0x00000001,
+        0x00802001,0x00002081,0x00002081,0x00000080,
+        0x00802081,0x00000081,0x00000001,0x00002000,
+        0x00800001,0x00002001,0x00802080,0x00800081,
+        0x00002001,0x00002080,0x00800000,0x00802001,
+        0x00000080,0x00800000,0x00002000,0x00802080},
+    {   0x00000100,0x02080100,0x02080000,0x42000100,
+        0x00080000,0x00000100,0x40000000,0x02080000,
+        0x40080100,0x00080000,0x02000100,0x40080100,
+        0x42000100,0x42080000,0x00080100,0x40000000,
+        0x02000000,0x40080000,0x40080000,0x00000000,
+        0x40000100,0x42080100,0x42080100,0x02000100,
+        0x42080000,0x40000100,0x00000000,0x42000000,
+        0x02080100,0x02000000,0x42000000,0x00080100,
+        0x00080000,0x42000100,0x00000100,0x02000000,
+        0x40000000,0x02080000,0x42000100,0x40080100,
+        0x02000100,0x40000000,0x42080000,0x02080100,
+        0x40080100,0x00000100,0x02000000,0x42080000,
+        0x42080100,0x00080100,0x42000000,0x42080100,
+        0x02080000,0x00000000,0x40080000,0x42000000,
+        0x00080100,0x02000100,0x40000100,0x00080000,
+        0x00000000,0x40080000,0x02080100,0x40000100},
+    {   0x20000010,0x20400000,0x00004000,0x20404010,
+        0x20400000,0x00000010,0x20404010,0x00400000,
+        0x20004000,0x00404010,0x00400000,0x20000010,
+        0x00400010,0x20004000,0x20000000,0x00004010,
+        0x00000000,0x00400010,0x20004010,0x00004000,
+        0x00404000,0x20004010,0x00000010,0x20400010,
+        0x20400010,0x00000000,0x00404010,0x20404000,
+        0x00004010,0x00404000,0x20404000,0x20000000,
+        0x20004000,0x00000010,0x20400010,0x00404000,
+        0x20404010,0x00400000,0x00004010,0x20000010,
+        0x00400000,0x20004000,0x20000000,0x00004010,
+        0x20000010,0x20404010,0x00404000,0x20400000,
+        0x00404010,0x20404000,0x00000000,0x20400010,
+        0x00000010,0x00004000,0x20400000,0x00404010,
+        0x00004000,0x00400010,0x20004010,0x00000000,
+        0x20404000,0x20000000,0x00400010,0x20004010},
+    {   0x00200000,0x04200002,0x04000802,0x00000000,
+        0x00000800,0x04000802,0x00200802,0x04200800,
+        0x04200802,0x00200000,0x00000000,0x04000002,
+        0x00000002,0x04000000,0x04200002,0x00000802,
+        0x04000800,0x00200802,0x00200002,0x04000800,
+        0x04000002,0x04200000,0x04200800,0x00200002,
+        0x04200000,0x00000800,0x00000802,0x04200802,
+        0x00200800,0x00000002,0x04000000,0x00200800,
+        0x04000000,0x00200800,0x00200000,0x04000802,
+        0x04000802,0x04200002,0x04200002,0x00000002,
+        0x00200002,0x04000000,0x04000800,0x00200000,
+        0x04200800,0x00000802,0x00200802,0x04200800,
+        0x00000802,0x04000002,0x04200802,0x04200000,
+        0x00200800,0x00000000,0x00000002,0x04200802,
+        0x00000000,0x00200802,0x04200000,0x00000800,
+        0x04000002,0x04000800,0x00000800,0x00200002},
+    {   0x10001040,0x00001000,0x00040000,0x10041040,
+        0x10000000,0x10001040,0x00000040,0x10000000,
+        0x00040040,0x10040000,0x10041040,0x00041000,
+        0x10041000,0x00041040,0x00001000,0x00000040,
+        0x10040000,0x10000040,0x10001000,0x00001040,
+        0x00041000,0x00040040,0x10040040,0x10041000,
+        0x00001040,0x00000000,0x00000000,0x10040040,
+        0x10000040,0x10001000,0x00041040,0x00040000,
+        0x00041040,0x00040000,0x10041000,0x00001000,
+        0x00000040,0x10040040,0x00001000,0x00041040,
+        0x10001000,0x00000040,0x10000040,0x10040000,
+        0x10040040,0x10000000,0x00040000,0x10001040,
+        0x00000000,0x10041040,0x00040040,0x10000040,
+        0x10040000,0x10001000,0x10001040,0x00000000,
+        0x10041040,0x00041000,0x00041000,0x00001040,
+        0x00001040,0x00040040,0x10000000,0x10041000}
+    };
+
+    static WC_INLINE void IPERM(word32* left, word32* right)
+    {
+        word32 work;
+
+        *right = rotlFixed(*right, 4U);
+        work = (*left ^ *right) & 0xf0f0f0f0;
+        *left ^= work;
+
+        *right = rotrFixed(*right^work, 20U);
+        work = (*left ^ *right) & 0xffff0000;
+        *left ^= work;
+
+        *right = rotrFixed(*right^work, 18U);
+        work = (*left ^ *right) & 0x33333333;
+        *left ^= work;
+
+        *right = rotrFixed(*right^work, 6U);
+        work = (*left ^ *right) & 0x00ff00ff;
+        *left ^= work;
+
+        *right = rotlFixed(*right^work, 9U);
+        work = (*left ^ *right) & 0xaaaaaaaa;
+        *left = rotlFixed(*left^work, 1U);
+        *right ^= work;
+    }
+
+    static WC_INLINE void FPERM(word32* left, word32* right)
+    {
+        word32 work;
+
+        *right = rotrFixed(*right, 1U);
+        work = (*left ^ *right) & 0xaaaaaaaa;
+        *right ^= work;
+
+        *left = rotrFixed(*left^work, 9U);
+        work = (*left ^ *right) & 0x00ff00ff;
+        *right ^= work;
+
+        *left = rotlFixed(*left^work, 6U);
+        work = (*left ^ *right) & 0x33333333;
+        *right ^= work;
+
+        *left = rotlFixed(*left^work, 18U);
+        work = (*left ^ *right) & 0xffff0000;
+        *right ^= work;
+
+        *left = rotlFixed(*left^work, 20U);
+        work = (*left ^ *right) & 0xf0f0f0f0;
+        *right ^= work;
+
+        *left = rotrFixed(*left^work, 4U);
+    }
+
+    static int DesSetKey(const byte* key, int dir, word32* out)
+    {
+        #define DES_KEY_BUFFER_SIZE (56+56+8)
+    #ifdef WOLFSSL_SMALL_STACK
+        byte* buffer = (byte*)XMALLOC(DES_KEY_BUFFER_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+        if (buffer == NULL)
+            return MEMORY_E;
+    #else
+        byte buffer[DES_KEY_BUFFER_SIZE];
+    #endif
+
+        {
+            byte* const  pc1m = buffer;            /* place to modify pc1 into */
+            byte* const  pcr  = pc1m + 56;         /* place to rotate pc1 into */
+            byte* const  ks   = pcr  + 56;
+            register int i, j, l;
+            int          m;
+
+            for (j = 0; j < 56; j++) {             /* convert pc1 to bits of key  */
+                l = pc1[j] - 1;                    /* integer bit location        */
+                m = l & 07;                        /* find bit                    */
+                pc1m[j] = (key[l >> 3] &           /* find which key byte l is in */
+                    bytebit[m])                    /* and which bit of that byte  */
+                    ? 1 : 0;                       /* and store 1-bit result      */
+            }
+
+            for (i = 0; i < 16; i++) {            /* key chunk for each iteration */
+                XMEMSET(ks, 0, 8);                /* Clear key schedule */
+
+                for (j = 0; j < 56; j++)          /* rotate pc1 the right amount  */
+                    pcr[j] =
+                          pc1m[(l = j + totrot[i]) < (j < 28 ? 28 : 56) ? l : l-28];
+
+                /* rotate left and right halves independently */
+                for (j = 0; j < 48; j++) {        /* select bits individually     */
+                    if (pcr[pc2[j] - 1]) {        /* check bit that goes to ks[j] */
+                        l= j % 6;                 /* mask it in if it's there     */
+                        ks[j/6] |= bytebit[l] >> 2;
+                    }
+                }
+
+                /* Now convert to odd/even interleaved form for use in F */
+                out[2*i] = ((word32) ks[0] << 24)
+                         | ((word32) ks[2] << 16)
+                         | ((word32) ks[4] << 8)
+                         | ((word32) ks[6]);
+
+                out[2*i + 1] = ((word32) ks[1] << 24)
+                             | ((word32) ks[3] << 16)
+                             | ((word32) ks[5] << 8)
+                             | ((word32) ks[7]);
+            }
+
+            /* reverse key schedule order */
+            if (dir == DES_DECRYPTION) {
+                for (i = 0; i < 16; i += 2) {
+                    word32 swap = out[i];
+                    out[i] = out[DES_KS_SIZE - 2 - i];
+                    out[DES_KS_SIZE - 2 - i] = swap;
+
+                    swap = out[i + 1];
+                    out[i + 1] = out[DES_KS_SIZE - 1 - i];
+                    out[DES_KS_SIZE - 1 - i] = swap;
+                }
+            }
+
+    #ifdef WOLFSSL_SMALL_STACK
+            XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+        }
+
+        return 0;
+    }
+
+    int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir)
+    {
+        wc_Des_SetIV(des, iv);
+
+        return DesSetKey(key, dir, des->key);
+    }
+
+    int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir)
+    {
+        int ret;
+
+        if (des == NULL || key == NULL || dir < 0) {
+            return BAD_FUNC_ARG;
+        }
+
+    #if defined(WOLF_CRYPTO_CB) || \
+        (defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES))
+        #ifdef WOLF_CRYPTO_CB
+        if (des->devId != INVALID_DEVID)
+        #endif
+        {
+            XMEMCPY(des->devKey, key, DES3_KEYLEN);
+        }
+    #endif
+
+        ret = DesSetKey(key + (dir == DES_ENCRYPTION ? 0:16), dir, des->key[0]);
+        if (ret != 0)
+            return ret;
+
+        ret = DesSetKey(key + 8, !dir, des->key[1]);
+        if (ret != 0)
+            return ret;
+
+        ret = DesSetKey(key + (dir == DES_DECRYPTION ? 0:16), dir, des->key[2]);
+        if (ret != 0)
+            return ret;
+
+        return wc_Des3_SetIV(des, iv);
+    }
+
+    static void DesRawProcessBlock(word32* lIn, word32* rIn, const word32* kptr)
+    {
+        word32 l = *lIn, r = *rIn, i;
+
+        for (i=0; i<8; i++)
+        {
+            word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0];
+            l ^= Spbox[6][(work) & 0x3f]
+              ^  Spbox[4][(work >> 8) & 0x3f]
+              ^  Spbox[2][(work >> 16) & 0x3f]
+              ^  Spbox[0][(work >> 24) & 0x3f];
+            work = r ^ kptr[4*i+1];
+            l ^= Spbox[7][(work) & 0x3f]
+              ^  Spbox[5][(work >> 8) & 0x3f]
+              ^  Spbox[3][(work >> 16) & 0x3f]
+              ^  Spbox[1][(work >> 24) & 0x3f];
+
+            work = rotrFixed(l, 4U) ^ kptr[4*i+2];
+            r ^= Spbox[6][(work) & 0x3f]
+              ^  Spbox[4][(work >> 8) & 0x3f]
+              ^  Spbox[2][(work >> 16) & 0x3f]
+              ^  Spbox[0][(work >> 24) & 0x3f];
+            work = l ^ kptr[4*i+3];
+            r ^= Spbox[7][(work) & 0x3f]
+              ^  Spbox[5][(work >> 8) & 0x3f]
+              ^  Spbox[3][(work >> 16) & 0x3f]
+              ^  Spbox[1][(work >> 24) & 0x3f];
+        }
+
+        *lIn = l; *rIn = r;
+    }
+
+    static void DesProcessBlock(Des* des, const byte* in, byte* out)
+    {
+        word32 l, r;
+
+        XMEMCPY(&l, in, sizeof(l));
+        XMEMCPY(&r, in + sizeof(l), sizeof(r));
+        #ifdef LITTLE_ENDIAN_ORDER
+            l = ByteReverseWord32(l);
+            r = ByteReverseWord32(r);
+        #endif
+        IPERM(&l,&r);
+
+        DesRawProcessBlock(&l, &r, des->key);
+
+        FPERM(&l,&r);
+        #ifdef LITTLE_ENDIAN_ORDER
+            l = ByteReverseWord32(l);
+            r = ByteReverseWord32(r);
+        #endif
+        XMEMCPY(out, &r, sizeof(r));
+        XMEMCPY(out + sizeof(r), &l, sizeof(l));
+    }
+
+    static void Des3ProcessBlock(Des3* des, const byte* in, byte* out)
+    {
+        word32 l, r;
+
+        XMEMCPY(&l, in, sizeof(l));
+        XMEMCPY(&r, in + sizeof(l), sizeof(r));
+        #ifdef LITTLE_ENDIAN_ORDER
+            l = ByteReverseWord32(l);
+            r = ByteReverseWord32(r);
+        #endif
+        IPERM(&l,&r);
+
+        DesRawProcessBlock(&l, &r, des->key[0]);
+        DesRawProcessBlock(&r, &l, des->key[1]);
+        DesRawProcessBlock(&l, &r, des->key[2]);
+
+        FPERM(&l,&r);
+        #ifdef LITTLE_ENDIAN_ORDER
+            l = ByteReverseWord32(l);
+            r = ByteReverseWord32(r);
+        #endif
+        XMEMCPY(out, &r, sizeof(r));
+        XMEMCPY(out + sizeof(r), &l, sizeof(l));
+    }
+
+    int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz)
+    {
+        word32 blocks = sz / DES_BLOCK_SIZE;
+
+        while (blocks--) {
+            xorbuf((byte*)des->reg, in, DES_BLOCK_SIZE);
+            DesProcessBlock(des, (byte*)des->reg, (byte*)des->reg);
+            XMEMCPY(out, des->reg, DES_BLOCK_SIZE);
+
+            out += DES_BLOCK_SIZE;
+            in  += DES_BLOCK_SIZE;
+        }
+        return 0;
+    }
+
+    int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz)
+    {
+        word32 blocks = sz / DES_BLOCK_SIZE;
+
+        while (blocks--) {
+            XMEMCPY(des->tmp, in, DES_BLOCK_SIZE);
+            DesProcessBlock(des, (byte*)des->tmp, out);
+            xorbuf(out, (byte*)des->reg, DES_BLOCK_SIZE);
+            XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE);
+
+            out += DES_BLOCK_SIZE;
+            in  += DES_BLOCK_SIZE;
+        }
+        return 0;
+    }
+
+    int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz)
+    {
+        word32 blocks;
+
+        if (des == NULL || out == NULL || in == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+    #ifdef WOLF_CRYPTO_CB
+        if (des->devId != INVALID_DEVID) {
+            int ret = wc_CryptoCb_Des3Encrypt(des, out, in, sz);
+            if (ret != CRYPTOCB_UNAVAILABLE)
+                return ret;
+            /* fall-through when unavailable */
+        }
+    #endif
+
+    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES)
+        if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES &&
+                                            sz >= WC_ASYNC_THRESH_DES3_CBC) {
+        #if defined(HAVE_CAVIUM)
+            return NitroxDes3CbcEncrypt(des, out, in, sz);
+        #elif defined(HAVE_INTEL_QA)
+            return IntelQaSymDes3CbcEncrypt(&des->asyncDev, out, in, sz,
+                (const byte*)des->devKey, DES3_KEYLEN, (byte*)des->reg, DES3_IVLEN);
+        #else /* WOLFSSL_ASYNC_CRYPT_TEST */
+            if (wc_AsyncTestInit(&des->asyncDev, ASYNC_TEST_DES3_CBC_ENCRYPT)) {
+                WC_ASYNC_TEST* testDev = &des->asyncDev.test;
+                testDev->des.des = des;
+                testDev->des.out = out;
+                testDev->des.in = in;
+                testDev->des.sz = sz;
+                return WC_PENDING_E;
+            }
+        #endif
+        }
+    #endif /* WOLFSSL_ASYNC_CRYPT */
+
+        blocks = sz / DES_BLOCK_SIZE;
+        while (blocks--) {
+            xorbuf((byte*)des->reg, in, DES_BLOCK_SIZE);
+            Des3ProcessBlock(des, (byte*)des->reg, (byte*)des->reg);
+            XMEMCPY(out, des->reg, DES_BLOCK_SIZE);
+
+            out += DES_BLOCK_SIZE;
+            in  += DES_BLOCK_SIZE;
+        }
+        return 0;
+    }
+
+
+    int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz)
+    {
+        word32 blocks;
+
+        if (des == NULL || out == NULL || in == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+    #ifdef WOLF_CRYPTO_CB
+        if (des->devId != INVALID_DEVID) {
+            int ret = wc_CryptoCb_Des3Decrypt(des, out, in, sz);
+            if (ret != CRYPTOCB_UNAVAILABLE)
+                return ret;
+            /* fall-through when unavailable */
+        }
+    #endif
+
+    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES)
+        if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES &&
+                                            sz >= WC_ASYNC_THRESH_DES3_CBC) {
+        #if defined(HAVE_CAVIUM)
+            return NitroxDes3CbcDecrypt(des, out, in, sz);
+        #elif defined(HAVE_INTEL_QA)
+            return IntelQaSymDes3CbcDecrypt(&des->asyncDev, out, in, sz,
+                (const byte*)des->devKey, DES3_KEYLEN, (byte*)des->reg, DES3_IVLEN);
+        #else /* WOLFSSL_ASYNC_CRYPT_TEST */
+            if (wc_AsyncTestInit(&des->asyncDev, ASYNC_TEST_DES3_CBC_DECRYPT)) {
+                WC_ASYNC_TEST* testDev = &des->asyncDev.test;
+                testDev->des.des = des;
+                testDev->des.out = out;
+                testDev->des.in = in;
+                testDev->des.sz = sz;
+                return WC_PENDING_E;
+            }
+        #endif
+        }
+    #endif /* WOLFSSL_ASYNC_CRYPT */
+
+        blocks = sz / DES_BLOCK_SIZE;
+        while (blocks--) {
+            XMEMCPY(des->tmp, in, DES_BLOCK_SIZE);
+            Des3ProcessBlock(des, (byte*)des->tmp, out);
+            xorbuf(out, (byte*)des->reg, DES_BLOCK_SIZE);
+            XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE);
+
+            out += DES_BLOCK_SIZE;
+            in  += DES_BLOCK_SIZE;
+        }
+        return 0;
+    }
+
+    #ifdef WOLFSSL_DES_ECB
+        /* One block, compatibility only */
+        int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz)
+        {
+            word32 blocks = sz / DES_BLOCK_SIZE;
+
+            if (des == NULL || out == NULL || in == NULL) {
+                return BAD_FUNC_ARG;
+            }
+
+            while (blocks--) {
+                DesProcessBlock(des, in, out);
+
+                out += DES_BLOCK_SIZE;
+                in  += DES_BLOCK_SIZE;
+            }
+            return 0;
+        }
+
+        int wc_Des3_EcbEncrypt(Des3* des, byte* out, const byte* in, word32 sz)
+        {
+            word32 blocks = sz / DES_BLOCK_SIZE;
+
+            if (des == NULL || out == NULL || in == NULL) {
+                return BAD_FUNC_ARG;
+            }
+
+            while (blocks--) {
+                Des3ProcessBlock(des, in, out);
+
+                out += DES_BLOCK_SIZE;
+                in  += DES_BLOCK_SIZE;
+            }
+            return 0;
+        }
+    #endif /* WOLFSSL_DES_ECB */
+
+#endif /* NEED_SOFT_DES */
+
+
+void wc_Des_SetIV(Des* des, const byte* iv)
+{
+    if (des && iv)
+        XMEMCPY(des->reg, iv, DES_BLOCK_SIZE);
+    else if (des)
+        XMEMSET(des->reg,  0, DES_BLOCK_SIZE);
+}
+
+int wc_Des3_SetIV(Des3* des, const byte* iv)
+{
+    if (des == NULL) {
+        return BAD_FUNC_ARG;
+    }
+    if (des && iv)
+        XMEMCPY(des->reg, iv, DES_BLOCK_SIZE);
+    else if (des)
+        XMEMSET(des->reg,  0, DES_BLOCK_SIZE);
+
+    return 0;
+}
+
+
+/* Initialize Des3 for use with async device */
+int wc_Des3Init(Des3* des3, void* heap, int devId)
+{
+    int ret = 0;
+    if (des3 == NULL)
+        return BAD_FUNC_ARG;
+
+    des3->heap = heap;
+
+#ifdef WOLF_CRYPTO_CB
+    des3->devId = devId;
+    des3->devCtx = NULL;
+#else
+    (void)devId;
+#endif
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES)
+    ret = wolfAsync_DevCtxInit(&des3->asyncDev, WOLFSSL_ASYNC_MARKER_3DES,
+                                                        des3->heap, devId);
+#endif
+
+    return ret;
+}
+
+/* Free Des3 from use with async device */
+void wc_Des3Free(Des3* des3)
+{
+    if (des3 == NULL)
+        return;
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES)
+    wolfAsync_DevCtxFree(&des3->asyncDev, WOLFSSL_ASYNC_MARKER_3DES);
+#endif /* WOLFSSL_ASYNC_CRYPT */
+#if defined(WOLF_CRYPTO_CB) || \
+        (defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES))
+    ForceZero(des3->devKey, sizeof(des3->devKey));
+#endif
+}
+
+#endif /* WOLFSSL_TI_CRYPT */
+#endif /* HAVE_FIPS */
+#endif /* NO_DES3 */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/dh.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/dh.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/dh.c	(revision 453)
@@ -0,0 +1,2491 @@
+/* dh.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifndef NO_DH
+
+#if defined(HAVE_FIPS) && \
+    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
+
+    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
+    #define FIPS_NO_WRAPPERS
+
+    #ifdef USE_WINDOWS_API
+        #pragma code_seg(".fipsA$m")
+        #pragma const_seg(".fipsB$m")
+    #endif
+#endif
+
+#include <wolfssl/wolfcrypt/dh.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#include <wolfssl/wolfcrypt/logging.h>
+
+#ifdef WOLFSSL_HAVE_SP_DH
+#include <wolfssl/wolfcrypt/sp.h>
+#endif
+
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+
+/*
+Possible DH enable options:
+ * NO_RSA:              Overall control of DH                 default: on (not defined)
+ * WOLFSSL_OLD_PRIME_CHECK: Disables the new prime number check. It does not
+                        directly effect this file, but it does speed up DH
+                        removing the testing. It is not recommended to
+                        disable the prime checking.           default: off
+
+*/
+
+
+#if !defined(USER_MATH_LIB) && !defined(WOLFSSL_DH_CONST)
+    #include <math.h>
+    #define XPOW(x,y) pow((x),(y))
+    #define XLOG(x)   log((x))
+#else
+    /* user's own math lib */
+#endif
+
+#ifdef HAVE_FFDHE_2048
+static const byte dh_ffdhe2048_p[] = {
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A,
+    0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1,
+    0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95,
+    0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB,
+    0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9,
+    0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8,
+    0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A,
+    0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61,
+    0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0,
+    0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3,
+    0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35,
+    0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77,
+    0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72,
+    0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35,
+    0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A,
+    0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61,
+    0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB,
+    0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68,
+    0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4,
+    0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19,
+    0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70,
+    0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC,
+    0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61,
+    0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF,
+    0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83,
+    0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73,
+    0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05,
+    0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2,
+    0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA,
+    0x88, 0x6B, 0x42, 0x38, 0x61, 0x28, 0x5C, 0x97,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+static const byte dh_ffdhe2048_g[] = { 0x02 };
+#ifdef HAVE_FFDHE_Q
+static const byte dh_ffdhe2048_q[] = {
+    0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xD6, 0xFC, 0x2A, 0x2C, 0x51, 0x5D, 0xA5, 0x4D,
+    0x57, 0xEE, 0x2B, 0x10, 0x13, 0x9E, 0x9E, 0x78,
+    0xEC, 0x5C, 0xE2, 0xC1, 0xE7, 0x16, 0x9B, 0x4A,
+    0xD4, 0xF0, 0x9B, 0x20, 0x8A, 0x32, 0x19, 0xFD,
+    0xE6, 0x49, 0xCE, 0xE7, 0x12, 0x4D, 0x9F, 0x7C,
+    0xBE, 0x97, 0xF1, 0xB1, 0xB1, 0x86, 0x3A, 0xEC,
+    0x7B, 0x40, 0xD9, 0x01, 0x57, 0x62, 0x30, 0xBD,
+    0x69, 0xEF, 0x8F, 0x6A, 0xEA, 0xFE, 0xB2, 0xB0,
+    0x92, 0x19, 0xFA, 0x8F, 0xAF, 0x83, 0x37, 0x68,
+    0x42, 0xB1, 0xB2, 0xAA, 0x9E, 0xF6, 0x8D, 0x79,
+    0xDA, 0xAB, 0x89, 0xAF, 0x3F, 0xAB, 0xE4, 0x9A,
+    0xCC, 0x27, 0x86, 0x38, 0x70, 0x73, 0x45, 0xBB,
+    0xF1, 0x53, 0x44, 0xED, 0x79, 0xF7, 0xF4, 0x39,
+    0x0E, 0xF8, 0xAC, 0x50, 0x9B, 0x56, 0xF3, 0x9A,
+    0x98, 0x56, 0x65, 0x27, 0xA4, 0x1D, 0x3C, 0xBD,
+    0x5E, 0x05, 0x58, 0xC1, 0x59, 0x92, 0x7D, 0xB0,
+    0xE8, 0x84, 0x54, 0xA5, 0xD9, 0x64, 0x71, 0xFD,
+    0xDC, 0xB5, 0x6D, 0x5B, 0xB0, 0x6B, 0xFA, 0x34,
+    0x0E, 0xA7, 0xA1, 0x51, 0xEF, 0x1C, 0xA6, 0xFA,
+    0x57, 0x2B, 0x76, 0xF3, 0xB1, 0xB9, 0x5D, 0x8C,
+    0x85, 0x83, 0xD3, 0xE4, 0x77, 0x05, 0x36, 0xB8,
+    0x4F, 0x01, 0x7E, 0x70, 0xE6, 0xFB, 0xF1, 0x76,
+    0x60, 0x1A, 0x02, 0x66, 0x94, 0x1A, 0x17, 0xB0,
+    0xC8, 0xB9, 0x7F, 0x4E, 0x74, 0xC2, 0xC1, 0xFF,
+    0xC7, 0x27, 0x89, 0x19, 0x77, 0x79, 0x40, 0xC1,
+    0xE1, 0xFF, 0x1D, 0x8D, 0xA6, 0x37, 0xD6, 0xB9,
+    0x9D, 0xDA, 0xFE, 0x5E, 0x17, 0x61, 0x10, 0x02,
+    0xE2, 0xC7, 0x78, 0xC1, 0xBE, 0x8B, 0x41, 0xD9,
+    0x63, 0x79, 0xA5, 0x13, 0x60, 0xD9, 0x77, 0xFD,
+    0x44, 0x35, 0xA1, 0x1C, 0x30, 0x94, 0x2E, 0x4B,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+#endif /* HAVE_FFDHE_Q */
+
+const DhParams* wc_Dh_ffdhe2048_Get(void)
+{
+    static const DhParams ffdhe2048 = {
+        #ifdef HAVE_FFDHE_Q
+            dh_ffdhe2048_q, sizeof(dh_ffdhe2048_q),
+        #endif /* HAVE_FFDHE_Q */
+        dh_ffdhe2048_p, sizeof(dh_ffdhe2048_p),
+        dh_ffdhe2048_g, sizeof(dh_ffdhe2048_g)
+    };
+    return &ffdhe2048;
+}
+#endif
+
+#ifdef HAVE_FFDHE_3072
+static const byte dh_ffdhe3072_p[] = {
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A,
+    0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1,
+    0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95,
+    0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB,
+    0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9,
+    0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8,
+    0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A,
+    0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61,
+    0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0,
+    0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3,
+    0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35,
+    0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77,
+    0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72,
+    0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35,
+    0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A,
+    0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61,
+    0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB,
+    0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68,
+    0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4,
+    0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19,
+    0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70,
+    0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC,
+    0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61,
+    0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF,
+    0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83,
+    0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73,
+    0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05,
+    0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2,
+    0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA,
+    0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC,
+    0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B,
+    0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38,
+    0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07,
+    0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE,
+    0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C,
+    0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70,
+    0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44,
+    0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3,
+    0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF,
+    0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E,
+    0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D,
+    0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA,
+    0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E,
+    0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF,
+    0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C,
+    0x25, 0xE4, 0x1D, 0x2B, 0x66, 0xC6, 0x2E, 0x37,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+static const byte dh_ffdhe3072_g[] = { 0x02 };
+#ifdef HAVE_FFDHE_Q
+static const byte dh_ffdhe3072_q[] = {
+    0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xD6, 0xFC, 0x2A, 0x2C, 0x51, 0x5D, 0xA5, 0x4D,
+    0x57, 0xEE, 0x2B, 0x10, 0x13, 0x9E, 0x9E, 0x78,
+    0xEC, 0x5C, 0xE2, 0xC1, 0xE7, 0x16, 0x9B, 0x4A,
+    0xD4, 0xF0, 0x9B, 0x20, 0x8A, 0x32, 0x19, 0xFD,
+    0xE6, 0x49, 0xCE, 0xE7, 0x12, 0x4D, 0x9F, 0x7C,
+    0xBE, 0x97, 0xF1, 0xB1, 0xB1, 0x86, 0x3A, 0xEC,
+    0x7B, 0x40, 0xD9, 0x01, 0x57, 0x62, 0x30, 0xBD,
+    0x69, 0xEF, 0x8F, 0x6A, 0xEA, 0xFE, 0xB2, 0xB0,
+    0x92, 0x19, 0xFA, 0x8F, 0xAF, 0x83, 0x37, 0x68,
+    0x42, 0xB1, 0xB2, 0xAA, 0x9E, 0xF6, 0x8D, 0x79,
+    0xDA, 0xAB, 0x89, 0xAF, 0x3F, 0xAB, 0xE4, 0x9A,
+    0xCC, 0x27, 0x86, 0x38, 0x70, 0x73, 0x45, 0xBB,
+    0xF1, 0x53, 0x44, 0xED, 0x79, 0xF7, 0xF4, 0x39,
+    0x0E, 0xF8, 0xAC, 0x50, 0x9B, 0x56, 0xF3, 0x9A,
+    0x98, 0x56, 0x65, 0x27, 0xA4, 0x1D, 0x3C, 0xBD,
+    0x5E, 0x05, 0x58, 0xC1, 0x59, 0x92, 0x7D, 0xB0,
+    0xE8, 0x84, 0x54, 0xA5, 0xD9, 0x64, 0x71, 0xFD,
+    0xDC, 0xB5, 0x6D, 0x5B, 0xB0, 0x6B, 0xFA, 0x34,
+    0x0E, 0xA7, 0xA1, 0x51, 0xEF, 0x1C, 0xA6, 0xFA,
+    0x57, 0x2B, 0x76, 0xF3, 0xB1, 0xB9, 0x5D, 0x8C,
+    0x85, 0x83, 0xD3, 0xE4, 0x77, 0x05, 0x36, 0xB8,
+    0x4F, 0x01, 0x7E, 0x70, 0xE6, 0xFB, 0xF1, 0x76,
+    0x60, 0x1A, 0x02, 0x66, 0x94, 0x1A, 0x17, 0xB0,
+    0xC8, 0xB9, 0x7F, 0x4E, 0x74, 0xC2, 0xC1, 0xFF,
+    0xC7, 0x27, 0x89, 0x19, 0x77, 0x79, 0x40, 0xC1,
+    0xE1, 0xFF, 0x1D, 0x8D, 0xA6, 0x37, 0xD6, 0xB9,
+    0x9D, 0xDA, 0xFE, 0x5E, 0x17, 0x61, 0x10, 0x02,
+    0xE2, 0xC7, 0x78, 0xC1, 0xBE, 0x8B, 0x41, 0xD9,
+    0x63, 0x79, 0xA5, 0x13, 0x60, 0xD9, 0x77, 0xFD,
+    0x44, 0x35, 0xA1, 0x1C, 0x30, 0x8F, 0xE7, 0xEE,
+    0x6F, 0x1A, 0xAD, 0x9D, 0xB2, 0x8C, 0x81, 0xAD,
+    0xDE, 0x1A, 0x7A, 0x6F, 0x7C, 0xCE, 0x01, 0x1C,
+    0x30, 0xDA, 0x37, 0xE4, 0xEB, 0x73, 0x64, 0x83,
+    0xBD, 0x6C, 0x8E, 0x93, 0x48, 0xFB, 0xFB, 0xF7,
+    0x2C, 0xC6, 0x58, 0x7D, 0x60, 0xC3, 0x6C, 0x8E,
+    0x57, 0x7F, 0x09, 0x84, 0xC2, 0x89, 0xC9, 0x38,
+    0x5A, 0x09, 0x86, 0x49, 0xDE, 0x21, 0xBC, 0xA2,
+    0x7A, 0x7E, 0xA2, 0x29, 0x71, 0x6B, 0xA6, 0xE9,
+    0xB2, 0x79, 0x71, 0x0F, 0x38, 0xFA, 0xA5, 0xFF,
+    0xAE, 0x57, 0x41, 0x55, 0xCE, 0x4E, 0xFB, 0x4F,
+    0x74, 0x36, 0x95, 0xE2, 0x91, 0x1B, 0x1D, 0x06,
+    0xD5, 0xE2, 0x90, 0xCB, 0xCD, 0x86, 0xF5, 0x6D,
+    0x0E, 0xDF, 0xCD, 0x21, 0x6A, 0xE2, 0x24, 0x27,
+    0x05, 0x5E, 0x68, 0x35, 0xFD, 0x29, 0xEE, 0xF7,
+    0x9E, 0x0D, 0x90, 0x77, 0x1F, 0xEA, 0xCE, 0xBE,
+    0x12, 0xF2, 0x0E, 0x95, 0xB3, 0x63, 0x17, 0x1B,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+#endif /* HAVE_FFDHE_Q */
+
+const DhParams* wc_Dh_ffdhe3072_Get(void)
+{
+    static const DhParams ffdhe3072 = {
+        #ifdef HAVE_FFDHE_Q
+            dh_ffdhe3072_q, sizeof(dh_ffdhe3072_q),
+        #endif /* HAVE_FFDHE_Q */
+        dh_ffdhe3072_p, sizeof(dh_ffdhe3072_p),
+        dh_ffdhe3072_g, sizeof(dh_ffdhe3072_g)
+    };
+    return &ffdhe3072;
+}
+#endif
+
+#ifdef HAVE_FFDHE_4096
+static const byte dh_ffdhe4096_p[] = {
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A,
+    0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1,
+    0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95,
+    0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB,
+    0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9,
+    0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8,
+    0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A,
+    0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61,
+    0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0,
+    0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3,
+    0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35,
+    0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77,
+    0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72,
+    0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35,
+    0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A,
+    0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61,
+    0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB,
+    0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68,
+    0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4,
+    0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19,
+    0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70,
+    0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC,
+    0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61,
+    0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF,
+    0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83,
+    0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73,
+    0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05,
+    0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2,
+    0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA,
+    0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC,
+    0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B,
+    0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38,
+    0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07,
+    0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE,
+    0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C,
+    0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70,
+    0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44,
+    0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3,
+    0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF,
+    0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E,
+    0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D,
+    0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA,
+    0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E,
+    0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF,
+    0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C,
+    0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1,
+    0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB,
+    0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6,
+    0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18,
+    0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04,
+    0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A,
+    0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A,
+    0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32,
+    0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4,
+    0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38,
+    0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A,
+    0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C,
+    0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC,
+    0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF,
+    0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B,
+    0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1,
+    0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x65, 0x5F, 0x6A,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+static const byte dh_ffdhe4096_g[] = { 0x02 };
+#ifdef HAVE_FFDHE_Q
+static const byte dh_ffdhe4096_q[] = {
+    0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xD6, 0xFC, 0x2A, 0x2C, 0x51, 0x5D, 0xA5, 0x4D,
+    0x57, 0xEE, 0x2B, 0x10, 0x13, 0x9E, 0x9E, 0x78,
+    0xEC, 0x5C, 0xE2, 0xC1, 0xE7, 0x16, 0x9B, 0x4A,
+    0xD4, 0xF0, 0x9B, 0x20, 0x8A, 0x32, 0x19, 0xFD,
+    0xE6, 0x49, 0xCE, 0xE7, 0x12, 0x4D, 0x9F, 0x7C,
+    0xBE, 0x97, 0xF1, 0xB1, 0xB1, 0x86, 0x3A, 0xEC,
+    0x7B, 0x40, 0xD9, 0x01, 0x57, 0x62, 0x30, 0xBD,
+    0x69, 0xEF, 0x8F, 0x6A, 0xEA, 0xFE, 0xB2, 0xB0,
+    0x92, 0x19, 0xFA, 0x8F, 0xAF, 0x83, 0x37, 0x68,
+    0x42, 0xB1, 0xB2, 0xAA, 0x9E, 0xF6, 0x8D, 0x79,
+    0xDA, 0xAB, 0x89, 0xAF, 0x3F, 0xAB, 0xE4, 0x9A,
+    0xCC, 0x27, 0x86, 0x38, 0x70, 0x73, 0x45, 0xBB,
+    0xF1, 0x53, 0x44, 0xED, 0x79, 0xF7, 0xF4, 0x39,
+    0x0E, 0xF8, 0xAC, 0x50, 0x9B, 0x56, 0xF3, 0x9A,
+    0x98, 0x56, 0x65, 0x27, 0xA4, 0x1D, 0x3C, 0xBD,
+    0x5E, 0x05, 0x58, 0xC1, 0x59, 0x92, 0x7D, 0xB0,
+    0xE8, 0x84, 0x54, 0xA5, 0xD9, 0x64, 0x71, 0xFD,
+    0xDC, 0xB5, 0x6D, 0x5B, 0xB0, 0x6B, 0xFA, 0x34,
+    0x0E, 0xA7, 0xA1, 0x51, 0xEF, 0x1C, 0xA6, 0xFA,
+    0x57, 0x2B, 0x76, 0xF3, 0xB1, 0xB9, 0x5D, 0x8C,
+    0x85, 0x83, 0xD3, 0xE4, 0x77, 0x05, 0x36, 0xB8,
+    0x4F, 0x01, 0x7E, 0x70, 0xE6, 0xFB, 0xF1, 0x76,
+    0x60, 0x1A, 0x02, 0x66, 0x94, 0x1A, 0x17, 0xB0,
+    0xC8, 0xB9, 0x7F, 0x4E, 0x74, 0xC2, 0xC1, 0xFF,
+    0xC7, 0x27, 0x89, 0x19, 0x77, 0x79, 0x40, 0xC1,
+    0xE1, 0xFF, 0x1D, 0x8D, 0xA6, 0x37, 0xD6, 0xB9,
+    0x9D, 0xDA, 0xFE, 0x5E, 0x17, 0x61, 0x10, 0x02,
+    0xE2, 0xC7, 0x78, 0xC1, 0xBE, 0x8B, 0x41, 0xD9,
+    0x63, 0x79, 0xA5, 0x13, 0x60, 0xD9, 0x77, 0xFD,
+    0x44, 0x35, 0xA1, 0x1C, 0x30, 0x8F, 0xE7, 0xEE,
+    0x6F, 0x1A, 0xAD, 0x9D, 0xB2, 0x8C, 0x81, 0xAD,
+    0xDE, 0x1A, 0x7A, 0x6F, 0x7C, 0xCE, 0x01, 0x1C,
+    0x30, 0xDA, 0x37, 0xE4, 0xEB, 0x73, 0x64, 0x83,
+    0xBD, 0x6C, 0x8E, 0x93, 0x48, 0xFB, 0xFB, 0xF7,
+    0x2C, 0xC6, 0x58, 0x7D, 0x60, 0xC3, 0x6C, 0x8E,
+    0x57, 0x7F, 0x09, 0x84, 0xC2, 0x89, 0xC9, 0x38,
+    0x5A, 0x09, 0x86, 0x49, 0xDE, 0x21, 0xBC, 0xA2,
+    0x7A, 0x7E, 0xA2, 0x29, 0x71, 0x6B, 0xA6, 0xE9,
+    0xB2, 0x79, 0x71, 0x0F, 0x38, 0xFA, 0xA5, 0xFF,
+    0xAE, 0x57, 0x41, 0x55, 0xCE, 0x4E, 0xFB, 0x4F,
+    0x74, 0x36, 0x95, 0xE2, 0x91, 0x1B, 0x1D, 0x06,
+    0xD5, 0xE2, 0x90, 0xCB, 0xCD, 0x86, 0xF5, 0x6D,
+    0x0E, 0xDF, 0xCD, 0x21, 0x6A, 0xE2, 0x24, 0x27,
+    0x05, 0x5E, 0x68, 0x35, 0xFD, 0x29, 0xEE, 0xF7,
+    0x9E, 0x0D, 0x90, 0x77, 0x1F, 0xEA, 0xCE, 0xBE,
+    0x12, 0xF2, 0x0E, 0x95, 0xB3, 0x4F, 0x0F, 0x78,
+    0xB7, 0x37, 0xA9, 0x61, 0x8B, 0x26, 0xFA, 0x7D,
+    0xBC, 0x98, 0x74, 0xF2, 0x72, 0xC4, 0x2B, 0xDB,
+    0x56, 0x3E, 0xAF, 0xA1, 0x6B, 0x4F, 0xB6, 0x8C,
+    0x3B, 0xB1, 0xE7, 0x8E, 0xAA, 0x81, 0xA0, 0x02,
+    0x43, 0xFA, 0xAD, 0xD2, 0xBF, 0x18, 0xE6, 0x3D,
+    0x38, 0x9A, 0xE4, 0x43, 0x77, 0xDA, 0x18, 0xC5,
+    0x76, 0xB5, 0x0F, 0x00, 0x96, 0xCF, 0x34, 0x19,
+    0x54, 0x83, 0xB0, 0x05, 0x48, 0xC0, 0x98, 0x62,
+    0x36, 0xE3, 0xBC, 0x7C, 0xB8, 0xD6, 0x80, 0x1C,
+    0x04, 0x94, 0xCC, 0xD1, 0x99, 0xE5, 0xC5, 0xBD,
+    0x0D, 0x0E, 0xDC, 0x9E, 0xB8, 0xA0, 0x00, 0x1E,
+    0x15, 0x27, 0x67, 0x54, 0xFC, 0xC6, 0x85, 0x66,
+    0x05, 0x41, 0x48, 0xE6, 0xE7, 0x64, 0xBE, 0xE7,
+    0xC7, 0x64, 0xDA, 0xAD, 0x3F, 0xC4, 0x52, 0x35,
+    0xA6, 0xDA, 0xD4, 0x28, 0xFA, 0x20, 0xC1, 0x70,
+    0xE3, 0x45, 0x00, 0x3F, 0x2F, 0x32, 0xAF, 0xB5,
+    0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+#endif /* HAVE_FFDHE_Q */
+
+const DhParams* wc_Dh_ffdhe4096_Get(void)
+{
+    static const DhParams ffdhe4096 = {
+        #ifdef HAVE_FFDHE_Q
+            dh_ffdhe4096_q, sizeof(dh_ffdhe4096_q),
+        #endif /* HAVE_FFDHE_Q */
+        dh_ffdhe4096_p, sizeof(dh_ffdhe4096_p),
+        dh_ffdhe4096_g, sizeof(dh_ffdhe4096_g)
+    };
+    return &ffdhe4096;
+}
+#endif
+
+#ifdef HAVE_FFDHE_6144
+static const byte dh_ffdhe6144_p[] = {
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A,
+    0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1,
+    0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95,
+    0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB,
+    0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9,
+    0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8,
+    0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A,
+    0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61,
+    0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0,
+    0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3,
+    0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35,
+    0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77,
+    0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72,
+    0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35,
+    0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A,
+    0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61,
+    0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB,
+    0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68,
+    0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4,
+    0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19,
+    0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70,
+    0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC,
+    0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61,
+    0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF,
+    0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83,
+    0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73,
+    0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05,
+    0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2,
+    0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA,
+    0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC,
+    0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B,
+    0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38,
+    0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07,
+    0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE,
+    0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C,
+    0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70,
+    0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44,
+    0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3,
+    0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF,
+    0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E,
+    0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D,
+    0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA,
+    0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E,
+    0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF,
+    0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C,
+    0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1,
+    0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB,
+    0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6,
+    0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18,
+    0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04,
+    0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A,
+    0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A,
+    0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32,
+    0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4,
+    0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38,
+    0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A,
+    0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C,
+    0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC,
+    0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF,
+    0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B,
+    0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1,
+    0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02,
+    0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A,
+    0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A,
+    0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6,
+    0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8,
+    0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C,
+    0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A,
+    0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71,
+    0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F,
+    0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77,
+    0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10,
+    0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8,
+    0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3,
+    0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E,
+    0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3,
+    0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4,
+    0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1,
+    0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92,
+    0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6,
+    0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82,
+    0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE,
+    0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C,
+    0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E,
+    0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46,
+    0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A,
+    0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17,
+    0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03,
+    0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04,
+    0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6,
+    0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69,
+    0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1,
+    0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4,
+    0xA4, 0x0E, 0x32, 0x9C, 0xD0, 0xE4, 0x0E, 0x65,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+static const byte dh_ffdhe6144_g[] = { 0x02 };
+#ifdef HAVE_FFDHE_Q
+static const byte dh_ffdhe6144_q[] = {
+    0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xD6, 0xFC, 0x2A, 0x2C, 0x51, 0x5D, 0xA5, 0x4D,
+    0x57, 0xEE, 0x2B, 0x10, 0x13, 0x9E, 0x9E, 0x78,
+    0xEC, 0x5C, 0xE2, 0xC1, 0xE7, 0x16, 0x9B, 0x4A,
+    0xD4, 0xF0, 0x9B, 0x20, 0x8A, 0x32, 0x19, 0xFD,
+    0xE6, 0x49, 0xCE, 0xE7, 0x12, 0x4D, 0x9F, 0x7C,
+    0xBE, 0x97, 0xF1, 0xB1, 0xB1, 0x86, 0x3A, 0xEC,
+    0x7B, 0x40, 0xD9, 0x01, 0x57, 0x62, 0x30, 0xBD,
+    0x69, 0xEF, 0x8F, 0x6A, 0xEA, 0xFE, 0xB2, 0xB0,
+    0x92, 0x19, 0xFA, 0x8F, 0xAF, 0x83, 0x37, 0x68,
+    0x42, 0xB1, 0xB2, 0xAA, 0x9E, 0xF6, 0x8D, 0x79,
+    0xDA, 0xAB, 0x89, 0xAF, 0x3F, 0xAB, 0xE4, 0x9A,
+    0xCC, 0x27, 0x86, 0x38, 0x70, 0x73, 0x45, 0xBB,
+    0xF1, 0x53, 0x44, 0xED, 0x79, 0xF7, 0xF4, 0x39,
+    0x0E, 0xF8, 0xAC, 0x50, 0x9B, 0x56, 0xF3, 0x9A,
+    0x98, 0x56, 0x65, 0x27, 0xA4, 0x1D, 0x3C, 0xBD,
+    0x5E, 0x05, 0x58, 0xC1, 0x59, 0x92, 0x7D, 0xB0,
+    0xE8, 0x84, 0x54, 0xA5, 0xD9, 0x64, 0x71, 0xFD,
+    0xDC, 0xB5, 0x6D, 0x5B, 0xB0, 0x6B, 0xFA, 0x34,
+    0x0E, 0xA7, 0xA1, 0x51, 0xEF, 0x1C, 0xA6, 0xFA,
+    0x57, 0x2B, 0x76, 0xF3, 0xB1, 0xB9, 0x5D, 0x8C,
+    0x85, 0x83, 0xD3, 0xE4, 0x77, 0x05, 0x36, 0xB8,
+    0x4F, 0x01, 0x7E, 0x70, 0xE6, 0xFB, 0xF1, 0x76,
+    0x60, 0x1A, 0x02, 0x66, 0x94, 0x1A, 0x17, 0xB0,
+    0xC8, 0xB9, 0x7F, 0x4E, 0x74, 0xC2, 0xC1, 0xFF,
+    0xC7, 0x27, 0x89, 0x19, 0x77, 0x79, 0x40, 0xC1,
+    0xE1, 0xFF, 0x1D, 0x8D, 0xA6, 0x37, 0xD6, 0xB9,
+    0x9D, 0xDA, 0xFE, 0x5E, 0x17, 0x61, 0x10, 0x02,
+    0xE2, 0xC7, 0x78, 0xC1, 0xBE, 0x8B, 0x41, 0xD9,
+    0x63, 0x79, 0xA5, 0x13, 0x60, 0xD9, 0x77, 0xFD,
+    0x44, 0x35, 0xA1, 0x1C, 0x30, 0x8F, 0xE7, 0xEE,
+    0x6F, 0x1A, 0xAD, 0x9D, 0xB2, 0x8C, 0x81, 0xAD,
+    0xDE, 0x1A, 0x7A, 0x6F, 0x7C, 0xCE, 0x01, 0x1C,
+    0x30, 0xDA, 0x37, 0xE4, 0xEB, 0x73, 0x64, 0x83,
+    0xBD, 0x6C, 0x8E, 0x93, 0x48, 0xFB, 0xFB, 0xF7,
+    0x2C, 0xC6, 0x58, 0x7D, 0x60, 0xC3, 0x6C, 0x8E,
+    0x57, 0x7F, 0x09, 0x84, 0xC2, 0x89, 0xC9, 0x38,
+    0x5A, 0x09, 0x86, 0x49, 0xDE, 0x21, 0xBC, 0xA2,
+    0x7A, 0x7E, 0xA2, 0x29, 0x71, 0x6B, 0xA6, 0xE9,
+    0xB2, 0x79, 0x71, 0x0F, 0x38, 0xFA, 0xA5, 0xFF,
+    0xAE, 0x57, 0x41, 0x55, 0xCE, 0x4E, 0xFB, 0x4F,
+    0x74, 0x36, 0x95, 0xE2, 0x91, 0x1B, 0x1D, 0x06,
+    0xD5, 0xE2, 0x90, 0xCB, 0xCD, 0x86, 0xF5, 0x6D,
+    0x0E, 0xDF, 0xCD, 0x21, 0x6A, 0xE2, 0x24, 0x27,
+    0x05, 0x5E, 0x68, 0x35, 0xFD, 0x29, 0xEE, 0xF7,
+    0x9E, 0x0D, 0x90, 0x77, 0x1F, 0xEA, 0xCE, 0xBE,
+    0x12, 0xF2, 0x0E, 0x95, 0xB3, 0x4F, 0x0F, 0x78,
+    0xB7, 0x37, 0xA9, 0x61, 0x8B, 0x26, 0xFA, 0x7D,
+    0xBC, 0x98, 0x74, 0xF2, 0x72, 0xC4, 0x2B, 0xDB,
+    0x56, 0x3E, 0xAF, 0xA1, 0x6B, 0x4F, 0xB6, 0x8C,
+    0x3B, 0xB1, 0xE7, 0x8E, 0xAA, 0x81, 0xA0, 0x02,
+    0x43, 0xFA, 0xAD, 0xD2, 0xBF, 0x18, 0xE6, 0x3D,
+    0x38, 0x9A, 0xE4, 0x43, 0x77, 0xDA, 0x18, 0xC5,
+    0x76, 0xB5, 0x0F, 0x00, 0x96, 0xCF, 0x34, 0x19,
+    0x54, 0x83, 0xB0, 0x05, 0x48, 0xC0, 0x98, 0x62,
+    0x36, 0xE3, 0xBC, 0x7C, 0xB8, 0xD6, 0x80, 0x1C,
+    0x04, 0x94, 0xCC, 0xD1, 0x99, 0xE5, 0xC5, 0xBD,
+    0x0D, 0x0E, 0xDC, 0x9E, 0xB8, 0xA0, 0x00, 0x1E,
+    0x15, 0x27, 0x67, 0x54, 0xFC, 0xC6, 0x85, 0x66,
+    0x05, 0x41, 0x48, 0xE6, 0xE7, 0x64, 0xBE, 0xE7,
+    0xC7, 0x64, 0xDA, 0xAD, 0x3F, 0xC4, 0x52, 0x35,
+    0xA6, 0xDA, 0xD4, 0x28, 0xFA, 0x20, 0xC1, 0x70,
+    0xE3, 0x45, 0x00, 0x3F, 0x2F, 0x06, 0xEC, 0x81,
+    0x05, 0xFE, 0xB2, 0x5B, 0x22, 0x81, 0xB6, 0x3D,
+    0x27, 0x33, 0xBE, 0x96, 0x1C, 0x29, 0x95, 0x1D,
+    0x11, 0xDD, 0x22, 0x21, 0x65, 0x7A, 0x9F, 0x53,
+    0x1D, 0xDA, 0x2A, 0x19, 0x4D, 0xBB, 0x12, 0x64,
+    0x48, 0xBD, 0xEE, 0xB2, 0x58, 0xE0, 0x7E, 0xA6,
+    0x59, 0xC7, 0x46, 0x19, 0xA6, 0x38, 0x0E, 0x1D,
+    0x66, 0xD6, 0x83, 0x2B, 0xFE, 0x67, 0xF6, 0x38,
+    0xCD, 0x8F, 0xAE, 0x1F, 0x27, 0x23, 0x02, 0x0F,
+    0x9C, 0x40, 0xA3, 0xFD, 0xA6, 0x7E, 0xDA, 0x3B,
+    0xD2, 0x92, 0x38, 0xFB, 0xD4, 0xD4, 0xB4, 0x88,
+    0x5C, 0x2A, 0x99, 0x17, 0x6D, 0xB1, 0xA0, 0x6C,
+    0x50, 0x07, 0x78, 0x49, 0x1A, 0x82, 0x88, 0xF1,
+    0x85, 0x5F, 0x60, 0xFF, 0xFC, 0xF1, 0xD1, 0x37,
+    0x3F, 0xD9, 0x4F, 0xC6, 0x0C, 0x18, 0x11, 0xE1,
+    0xAC, 0x3F, 0x1C, 0x6D, 0x00, 0x3B, 0xEC, 0xDA,
+    0x3B, 0x1F, 0x27, 0x25, 0xCA, 0x59, 0x5D, 0xE0,
+    0xCA, 0x63, 0x32, 0x8F, 0x3B, 0xE5, 0x7C, 0xC9,
+    0x77, 0x55, 0x60, 0x11, 0x95, 0x14, 0x0D, 0xFB,
+    0x59, 0xD3, 0x9C, 0xE0, 0x91, 0x30, 0x8B, 0x41,
+    0x05, 0x74, 0x6D, 0xAC, 0x23, 0xD3, 0x3E, 0x5F,
+    0x7C, 0xE4, 0x84, 0x8D, 0xA3, 0x16, 0xA9, 0xC6,
+    0x6B, 0x95, 0x81, 0xBA, 0x35, 0x73, 0xBF, 0xAF,
+    0x31, 0x14, 0x96, 0x18, 0x8A, 0xB1, 0x54, 0x23,
+    0x28, 0x2E, 0xE4, 0x16, 0xDC, 0x2A, 0x19, 0xC5,
+    0x72, 0x4F, 0xA9, 0x1A, 0xE4, 0xAD, 0xC8, 0x8B,
+    0xC6, 0x67, 0x96, 0xEA, 0xE5, 0x67, 0x7A, 0x01,
+    0xF6, 0x4E, 0x8C, 0x08, 0x63, 0x13, 0x95, 0x82,
+    0x2D, 0x9D, 0xB8, 0xFC, 0xEE, 0x35, 0xC0, 0x6B,
+    0x1F, 0xEE, 0xA5, 0x47, 0x4D, 0x6D, 0x8F, 0x34,
+    0xB1, 0x53, 0x4A, 0x93, 0x6A, 0x18, 0xB0, 0xE0,
+    0xD2, 0x0E, 0xAB, 0x86, 0xBC, 0x9C, 0x6D, 0x6A,
+    0x52, 0x07, 0x19, 0x4E, 0x68, 0x72, 0x07, 0x32,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+#endif /* HAVE_FFDHE_Q */
+
+const DhParams* wc_Dh_ffdhe6144_Get(void)
+{
+    static const DhParams ffdhe6144 = {
+        #ifdef HAVE_FFDHE_Q
+            dh_ffdhe6144_q, sizeof(dh_ffdhe6144_q),
+        #endif /* HAVE_FFDHE_Q */
+        dh_ffdhe6144_p, sizeof(dh_ffdhe6144_p),
+        dh_ffdhe6144_g, sizeof(dh_ffdhe6144_g)
+    };
+    return &ffdhe6144;
+}
+#endif
+
+#ifdef HAVE_FFDHE_8192
+static const byte dh_ffdhe8192_p[] = {
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A,
+    0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1,
+    0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95,
+    0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB,
+    0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9,
+    0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8,
+    0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A,
+    0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61,
+    0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0,
+    0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3,
+    0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35,
+    0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77,
+    0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72,
+    0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35,
+    0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A,
+    0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61,
+    0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB,
+    0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68,
+    0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4,
+    0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19,
+    0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70,
+    0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC,
+    0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61,
+    0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF,
+    0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83,
+    0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73,
+    0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05,
+    0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2,
+    0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA,
+    0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC,
+    0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B,
+    0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38,
+    0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07,
+    0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE,
+    0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C,
+    0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70,
+    0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44,
+    0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3,
+    0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF,
+    0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E,
+    0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D,
+    0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA,
+    0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E,
+    0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF,
+    0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C,
+    0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1,
+    0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB,
+    0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6,
+    0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18,
+    0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04,
+    0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A,
+    0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A,
+    0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32,
+    0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4,
+    0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38,
+    0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A,
+    0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C,
+    0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC,
+    0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF,
+    0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B,
+    0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1,
+    0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02,
+    0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A,
+    0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A,
+    0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6,
+    0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8,
+    0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C,
+    0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A,
+    0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71,
+    0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F,
+    0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77,
+    0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10,
+    0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8,
+    0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3,
+    0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E,
+    0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3,
+    0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4,
+    0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1,
+    0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92,
+    0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6,
+    0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82,
+    0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE,
+    0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C,
+    0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E,
+    0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46,
+    0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A,
+    0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17,
+    0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03,
+    0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04,
+    0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6,
+    0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69,
+    0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1,
+    0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4,
+    0xA4, 0x0E, 0x32, 0x9C, 0xCF, 0xF4, 0x6A, 0xAA,
+    0x36, 0xAD, 0x00, 0x4C, 0xF6, 0x00, 0xC8, 0x38,
+    0x1E, 0x42, 0x5A, 0x31, 0xD9, 0x51, 0xAE, 0x64,
+    0xFD, 0xB2, 0x3F, 0xCE, 0xC9, 0x50, 0x9D, 0x43,
+    0x68, 0x7F, 0xEB, 0x69, 0xED, 0xD1, 0xCC, 0x5E,
+    0x0B, 0x8C, 0xC3, 0xBD, 0xF6, 0x4B, 0x10, 0xEF,
+    0x86, 0xB6, 0x31, 0x42, 0xA3, 0xAB, 0x88, 0x29,
+    0x55, 0x5B, 0x2F, 0x74, 0x7C, 0x93, 0x26, 0x65,
+    0xCB, 0x2C, 0x0F, 0x1C, 0xC0, 0x1B, 0xD7, 0x02,
+    0x29, 0x38, 0x88, 0x39, 0xD2, 0xAF, 0x05, 0xE4,
+    0x54, 0x50, 0x4A, 0xC7, 0x8B, 0x75, 0x82, 0x82,
+    0x28, 0x46, 0xC0, 0xBA, 0x35, 0xC3, 0x5F, 0x5C,
+    0x59, 0x16, 0x0C, 0xC0, 0x46, 0xFD, 0x82, 0x51,
+    0x54, 0x1F, 0xC6, 0x8C, 0x9C, 0x86, 0xB0, 0x22,
+    0xBB, 0x70, 0x99, 0x87, 0x6A, 0x46, 0x0E, 0x74,
+    0x51, 0xA8, 0xA9, 0x31, 0x09, 0x70, 0x3F, 0xEE,
+    0x1C, 0x21, 0x7E, 0x6C, 0x38, 0x26, 0xE5, 0x2C,
+    0x51, 0xAA, 0x69, 0x1E, 0x0E, 0x42, 0x3C, 0xFC,
+    0x99, 0xE9, 0xE3, 0x16, 0x50, 0xC1, 0x21, 0x7B,
+    0x62, 0x48, 0x16, 0xCD, 0xAD, 0x9A, 0x95, 0xF9,
+    0xD5, 0xB8, 0x01, 0x94, 0x88, 0xD9, 0xC0, 0xA0,
+    0xA1, 0xFE, 0x30, 0x75, 0xA5, 0x77, 0xE2, 0x31,
+    0x83, 0xF8, 0x1D, 0x4A, 0x3F, 0x2F, 0xA4, 0x57,
+    0x1E, 0xFC, 0x8C, 0xE0, 0xBA, 0x8A, 0x4F, 0xE8,
+    0xB6, 0x85, 0x5D, 0xFE, 0x72, 0xB0, 0xA6, 0x6E,
+    0xDE, 0xD2, 0xFB, 0xAB, 0xFB, 0xE5, 0x8A, 0x30,
+    0xFA, 0xFA, 0xBE, 0x1C, 0x5D, 0x71, 0xA8, 0x7E,
+    0x2F, 0x74, 0x1E, 0xF8, 0xC1, 0xFE, 0x86, 0xFE,
+    0xA6, 0xBB, 0xFD, 0xE5, 0x30, 0x67, 0x7F, 0x0D,
+    0x97, 0xD1, 0x1D, 0x49, 0xF7, 0xA8, 0x44, 0x3D,
+    0x08, 0x22, 0xE5, 0x06, 0xA9, 0xF4, 0x61, 0x4E,
+    0x01, 0x1E, 0x2A, 0x94, 0x83, 0x8F, 0xF8, 0x8C,
+    0xD6, 0x8C, 0x8B, 0xB7, 0xC5, 0xC6, 0x42, 0x4C,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+static const byte dh_ffdhe8192_g[] = { 0x02 };
+#ifdef HAVE_FFDHE_Q
+static const byte dh_ffdhe8192_q[] = {
+    0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xD6, 0xFC, 0x2A, 0x2C, 0x51, 0x5D, 0xA5, 0x4D,
+    0x57, 0xEE, 0x2B, 0x10, 0x13, 0x9E, 0x9E, 0x78,
+    0xEC, 0x5C, 0xE2, 0xC1, 0xE7, 0x16, 0x9B, 0x4A,
+    0xD4, 0xF0, 0x9B, 0x20, 0x8A, 0x32, 0x19, 0xFD,
+    0xE6, 0x49, 0xCE, 0xE7, 0x12, 0x4D, 0x9F, 0x7C,
+    0xBE, 0x97, 0xF1, 0xB1, 0xB1, 0x86, 0x3A, 0xEC,
+    0x7B, 0x40, 0xD9, 0x01, 0x57, 0x62, 0x30, 0xBD,
+    0x69, 0xEF, 0x8F, 0x6A, 0xEA, 0xFE, 0xB2, 0xB0,
+    0x92, 0x19, 0xFA, 0x8F, 0xAF, 0x83, 0x37, 0x68,
+    0x42, 0xB1, 0xB2, 0xAA, 0x9E, 0xF6, 0x8D, 0x79,
+    0xDA, 0xAB, 0x89, 0xAF, 0x3F, 0xAB, 0xE4, 0x9A,
+    0xCC, 0x27, 0x86, 0x38, 0x70, 0x73, 0x45, 0xBB,
+    0xF1, 0x53, 0x44, 0xED, 0x79, 0xF7, 0xF4, 0x39,
+    0x0E, 0xF8, 0xAC, 0x50, 0x9B, 0x56, 0xF3, 0x9A,
+    0x98, 0x56, 0x65, 0x27, 0xA4, 0x1D, 0x3C, 0xBD,
+    0x5E, 0x05, 0x58, 0xC1, 0x59, 0x92, 0x7D, 0xB0,
+    0xE8, 0x84, 0x54, 0xA5, 0xD9, 0x64, 0x71, 0xFD,
+    0xDC, 0xB5, 0x6D, 0x5B, 0xB0, 0x6B, 0xFA, 0x34,
+    0x0E, 0xA7, 0xA1, 0x51, 0xEF, 0x1C, 0xA6, 0xFA,
+    0x57, 0x2B, 0x76, 0xF3, 0xB1, 0xB9, 0x5D, 0x8C,
+    0x85, 0x83, 0xD3, 0xE4, 0x77, 0x05, 0x36, 0xB8,
+    0x4F, 0x01, 0x7E, 0x70, 0xE6, 0xFB, 0xF1, 0x76,
+    0x60, 0x1A, 0x02, 0x66, 0x94, 0x1A, 0x17, 0xB0,
+    0xC8, 0xB9, 0x7F, 0x4E, 0x74, 0xC2, 0xC1, 0xFF,
+    0xC7, 0x27, 0x89, 0x19, 0x77, 0x79, 0x40, 0xC1,
+    0xE1, 0xFF, 0x1D, 0x8D, 0xA6, 0x37, 0xD6, 0xB9,
+    0x9D, 0xDA, 0xFE, 0x5E, 0x17, 0x61, 0x10, 0x02,
+    0xE2, 0xC7, 0x78, 0xC1, 0xBE, 0x8B, 0x41, 0xD9,
+    0x63, 0x79, 0xA5, 0x13, 0x60, 0xD9, 0x77, 0xFD,
+    0x44, 0x35, 0xA1, 0x1C, 0x30, 0x8F, 0xE7, 0xEE,
+    0x6F, 0x1A, 0xAD, 0x9D, 0xB2, 0x8C, 0x81, 0xAD,
+    0xDE, 0x1A, 0x7A, 0x6F, 0x7C, 0xCE, 0x01, 0x1C,
+    0x30, 0xDA, 0x37, 0xE4, 0xEB, 0x73, 0x64, 0x83,
+    0xBD, 0x6C, 0x8E, 0x93, 0x48, 0xFB, 0xFB, 0xF7,
+    0x2C, 0xC6, 0x58, 0x7D, 0x60, 0xC3, 0x6C, 0x8E,
+    0x57, 0x7F, 0x09, 0x84, 0xC2, 0x89, 0xC9, 0x38,
+    0x5A, 0x09, 0x86, 0x49, 0xDE, 0x21, 0xBC, 0xA2,
+    0x7A, 0x7E, 0xA2, 0x29, 0x71, 0x6B, 0xA6, 0xE9,
+    0xB2, 0x79, 0x71, 0x0F, 0x38, 0xFA, 0xA5, 0xFF,
+    0xAE, 0x57, 0x41, 0x55, 0xCE, 0x4E, 0xFB, 0x4F,
+    0x74, 0x36, 0x95, 0xE2, 0x91, 0x1B, 0x1D, 0x06,
+    0xD5, 0xE2, 0x90, 0xCB, 0xCD, 0x86, 0xF5, 0x6D,
+    0x0E, 0xDF, 0xCD, 0x21, 0x6A, 0xE2, 0x24, 0x27,
+    0x05, 0x5E, 0x68, 0x35, 0xFD, 0x29, 0xEE, 0xF7,
+    0x9E, 0x0D, 0x90, 0x77, 0x1F, 0xEA, 0xCE, 0xBE,
+    0x12, 0xF2, 0x0E, 0x95, 0xB3, 0x4F, 0x0F, 0x78,
+    0xB7, 0x37, 0xA9, 0x61, 0x8B, 0x26, 0xFA, 0x7D,
+    0xBC, 0x98, 0x74, 0xF2, 0x72, 0xC4, 0x2B, 0xDB,
+    0x56, 0x3E, 0xAF, 0xA1, 0x6B, 0x4F, 0xB6, 0x8C,
+    0x3B, 0xB1, 0xE7, 0x8E, 0xAA, 0x81, 0xA0, 0x02,
+    0x43, 0xFA, 0xAD, 0xD2, 0xBF, 0x18, 0xE6, 0x3D,
+    0x38, 0x9A, 0xE4, 0x43, 0x77, 0xDA, 0x18, 0xC5,
+    0x76, 0xB5, 0x0F, 0x00, 0x96, 0xCF, 0x34, 0x19,
+    0x54, 0x83, 0xB0, 0x05, 0x48, 0xC0, 0x98, 0x62,
+    0x36, 0xE3, 0xBC, 0x7C, 0xB8, 0xD6, 0x80, 0x1C,
+    0x04, 0x94, 0xCC, 0xD1, 0x99, 0xE5, 0xC5, 0xBD,
+    0x0D, 0x0E, 0xDC, 0x9E, 0xB8, 0xA0, 0x00, 0x1E,
+    0x15, 0x27, 0x67, 0x54, 0xFC, 0xC6, 0x85, 0x66,
+    0x05, 0x41, 0x48, 0xE6, 0xE7, 0x64, 0xBE, 0xE7,
+    0xC7, 0x64, 0xDA, 0xAD, 0x3F, 0xC4, 0x52, 0x35,
+    0xA6, 0xDA, 0xD4, 0x28, 0xFA, 0x20, 0xC1, 0x70,
+    0xE3, 0x45, 0x00, 0x3F, 0x2F, 0x06, 0xEC, 0x81,
+    0x05, 0xFE, 0xB2, 0x5B, 0x22, 0x81, 0xB6, 0x3D,
+    0x27, 0x33, 0xBE, 0x96, 0x1C, 0x29, 0x95, 0x1D,
+    0x11, 0xDD, 0x22, 0x21, 0x65, 0x7A, 0x9F, 0x53,
+    0x1D, 0xDA, 0x2A, 0x19, 0x4D, 0xBB, 0x12, 0x64,
+    0x48, 0xBD, 0xEE, 0xB2, 0x58, 0xE0, 0x7E, 0xA6,
+    0x59, 0xC7, 0x46, 0x19, 0xA6, 0x38, 0x0E, 0x1D,
+    0x66, 0xD6, 0x83, 0x2B, 0xFE, 0x67, 0xF6, 0x38,
+    0xCD, 0x8F, 0xAE, 0x1F, 0x27, 0x23, 0x02, 0x0F,
+    0x9C, 0x40, 0xA3, 0xFD, 0xA6, 0x7E, 0xDA, 0x3B,
+    0xD2, 0x92, 0x38, 0xFB, 0xD4, 0xD4, 0xB4, 0x88,
+    0x5C, 0x2A, 0x99, 0x17, 0x6D, 0xB1, 0xA0, 0x6C,
+    0x50, 0x07, 0x78, 0x49, 0x1A, 0x82, 0x88, 0xF1,
+    0x85, 0x5F, 0x60, 0xFF, 0xFC, 0xF1, 0xD1, 0x37,
+    0x3F, 0xD9, 0x4F, 0xC6, 0x0C, 0x18, 0x11, 0xE1,
+    0xAC, 0x3F, 0x1C, 0x6D, 0x00, 0x3B, 0xEC, 0xDA,
+    0x3B, 0x1F, 0x27, 0x25, 0xCA, 0x59, 0x5D, 0xE0,
+    0xCA, 0x63, 0x32, 0x8F, 0x3B, 0xE5, 0x7C, 0xC9,
+    0x77, 0x55, 0x60, 0x11, 0x95, 0x14, 0x0D, 0xFB,
+    0x59, 0xD3, 0x9C, 0xE0, 0x91, 0x30, 0x8B, 0x41,
+    0x05, 0x74, 0x6D, 0xAC, 0x23, 0xD3, 0x3E, 0x5F,
+    0x7C, 0xE4, 0x84, 0x8D, 0xA3, 0x16, 0xA9, 0xC6,
+    0x6B, 0x95, 0x81, 0xBA, 0x35, 0x73, 0xBF, 0xAF,
+    0x31, 0x14, 0x96, 0x18, 0x8A, 0xB1, 0x54, 0x23,
+    0x28, 0x2E, 0xE4, 0x16, 0xDC, 0x2A, 0x19, 0xC5,
+    0x72, 0x4F, 0xA9, 0x1A, 0xE4, 0xAD, 0xC8, 0x8B,
+    0xC6, 0x67, 0x96, 0xEA, 0xE5, 0x67, 0x7A, 0x01,
+    0xF6, 0x4E, 0x8C, 0x08, 0x63, 0x13, 0x95, 0x82,
+    0x2D, 0x9D, 0xB8, 0xFC, 0xEE, 0x35, 0xC0, 0x6B,
+    0x1F, 0xEE, 0xA5, 0x47, 0x4D, 0x6D, 0x8F, 0x34,
+    0xB1, 0x53, 0x4A, 0x93, 0x6A, 0x18, 0xB0, 0xE0,
+    0xD2, 0x0E, 0xAB, 0x86, 0xBC, 0x9C, 0x6D, 0x6A,
+    0x52, 0x07, 0x19, 0x4E, 0x67, 0xFA, 0x35, 0x55,
+    0x1B, 0x56, 0x80, 0x26, 0x7B, 0x00, 0x64, 0x1C,
+    0x0F, 0x21, 0x2D, 0x18, 0xEC, 0xA8, 0xD7, 0x32,
+    0x7E, 0xD9, 0x1F, 0xE7, 0x64, 0xA8, 0x4E, 0xA1,
+    0xB4, 0x3F, 0xF5, 0xB4, 0xF6, 0xE8, 0xE6, 0x2F,
+    0x05, 0xC6, 0x61, 0xDE, 0xFB, 0x25, 0x88, 0x77,
+    0xC3, 0x5B, 0x18, 0xA1, 0x51, 0xD5, 0xC4, 0x14,
+    0xAA, 0xAD, 0x97, 0xBA, 0x3E, 0x49, 0x93, 0x32,
+    0xE5, 0x96, 0x07, 0x8E, 0x60, 0x0D, 0xEB, 0x81,
+    0x14, 0x9C, 0x44, 0x1C, 0xE9, 0x57, 0x82, 0xF2,
+    0x2A, 0x28, 0x25, 0x63, 0xC5, 0xBA, 0xC1, 0x41,
+    0x14, 0x23, 0x60, 0x5D, 0x1A, 0xE1, 0xAF, 0xAE,
+    0x2C, 0x8B, 0x06, 0x60, 0x23, 0x7E, 0xC1, 0x28,
+    0xAA, 0x0F, 0xE3, 0x46, 0x4E, 0x43, 0x58, 0x11,
+    0x5D, 0xB8, 0x4C, 0xC3, 0xB5, 0x23, 0x07, 0x3A,
+    0x28, 0xD4, 0x54, 0x98, 0x84, 0xB8, 0x1F, 0xF7,
+    0x0E, 0x10, 0xBF, 0x36, 0x1C, 0x13, 0x72, 0x96,
+    0x28, 0xD5, 0x34, 0x8F, 0x07, 0x21, 0x1E, 0x7E,
+    0x4C, 0xF4, 0xF1, 0x8B, 0x28, 0x60, 0x90, 0xBD,
+    0xB1, 0x24, 0x0B, 0x66, 0xD6, 0xCD, 0x4A, 0xFC,
+    0xEA, 0xDC, 0x00, 0xCA, 0x44, 0x6C, 0xE0, 0x50,
+    0x50, 0xFF, 0x18, 0x3A, 0xD2, 0xBB, 0xF1, 0x18,
+    0xC1, 0xFC, 0x0E, 0xA5, 0x1F, 0x97, 0xD2, 0x2B,
+    0x8F, 0x7E, 0x46, 0x70, 0x5D, 0x45, 0x27, 0xF4,
+    0x5B, 0x42, 0xAE, 0xFF, 0x39, 0x58, 0x53, 0x37,
+    0x6F, 0x69, 0x7D, 0xD5, 0xFD, 0xF2, 0xC5, 0x18,
+    0x7D, 0x7D, 0x5F, 0x0E, 0x2E, 0xB8, 0xD4, 0x3F,
+    0x17, 0xBA, 0x0F, 0x7C, 0x60, 0xFF, 0x43, 0x7F,
+    0x53, 0x5D, 0xFE, 0xF2, 0x98, 0x33, 0xBF, 0x86,
+    0xCB, 0xE8, 0x8E, 0xA4, 0xFB, 0xD4, 0x22, 0x1E,
+    0x84, 0x11, 0x72, 0x83, 0x54, 0xFA, 0x30, 0xA7,
+    0x00, 0x8F, 0x15, 0x4A, 0x41, 0xC7, 0xFC, 0x46,
+    0x6B, 0x46, 0x45, 0xDB, 0xE2, 0xE3, 0x21, 0x26,
+    0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+#endif /* HAVE_FFDHE_Q */
+
+const DhParams* wc_Dh_ffdhe8192_Get(void)
+{
+    static const DhParams ffdhe8192 = {
+        #ifdef HAVE_FFDHE_Q
+            dh_ffdhe8192_q, sizeof(dh_ffdhe8192_q),
+        #endif /* HAVE_FFDHE_Q */
+        dh_ffdhe8192_p, sizeof(dh_ffdhe8192_p),
+        dh_ffdhe8192_g, sizeof(dh_ffdhe8192_g)
+    };
+    return &ffdhe8192;
+}
+#endif
+
+int wc_InitDhKey_ex(DhKey* key, void* heap, int devId)
+{
+    int ret = 0;
+
+    if (key == NULL)
+        return BAD_FUNC_ARG;
+
+    key->heap = heap; /* for XMALLOC/XFREE in future */
+
+#if !defined(WOLFSSL_QT) && !defined(OPENSSL_ALL)
+    if (mp_init_multi(&key->p, &key->g, &key->q, NULL, NULL, NULL) != MP_OKAY)
+#else
+    if (mp_init_multi(&key->p,&key->g,&key->q,&key->pub,&key->priv,NULL) != MP_OKAY)
+#endif
+        return MEMORY_E;
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH)
+    /* handle as async */
+    ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_DH,
+        key->heap, devId);
+#else
+    (void)devId;
+#endif
+
+    return ret;
+}
+
+int wc_InitDhKey(DhKey* key)
+{
+    return wc_InitDhKey_ex(key, NULL, INVALID_DEVID);
+}
+
+
+int wc_FreeDhKey(DhKey* key)
+{
+    if (key) {
+        mp_clear(&key->p);
+        mp_clear(&key->g);
+        mp_clear(&key->q);
+
+    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH)
+        wolfAsync_DevCtxFree(&key->asyncDev, WOLFSSL_ASYNC_MARKER_DH);
+    #endif
+    }
+    return 0;
+}
+
+
+#ifndef WC_NO_RNG
+/* if defined to not use floating point values do not compile in */
+#ifndef WOLFSSL_DH_CONST
+    static word32 DiscreteLogWorkFactor(word32 n)
+    {
+        /* assuming discrete log takes about the same time as factoring */
+        if (n < 5)
+            return 0;
+        else
+            return (word32)(2.4 * XPOW((double)n, 1.0/3.0) *
+                    XPOW(XLOG((double)n), 2.0/3.0) - 5);
+    }
+#endif /* WOLFSSL_DH_CONST*/
+
+
+/* if not using fixed points use DiscreteLogWorkFactor function for unusual size
+   otherwise round up on size needed */
+#ifndef WOLFSSL_DH_CONST
+    #define WOLFSSL_DH_ROUND(x)
+#else
+    #define WOLFSSL_DH_ROUND(x) \
+        do {                    \
+            if (x % 128) {      \
+                x &= 0xffffff80;\
+                x += 128;       \
+            }                   \
+        }                       \
+        while (0)
+#endif
+
+
+#ifndef WOLFSSL_NO_DH186
+/* validate that (L,N) match allowed sizes from SP 800-56A, Section 5.5.1.1.
+ * modLen - represents L, the size of p in bits
+ * divLen - represents N, the size of q in bits
+ * return 0 on success, -1 on error */
+static int CheckDhLN(int modLen, int divLen)
+{
+    int ret = -1;
+
+    switch (modLen) {
+        /* FA */
+        case 1024:
+            if (divLen == 160)
+                ret = 0;
+            break;
+        /* FB, FC */
+        case 2048:
+            if (divLen == 224 || divLen == 256)
+                ret = 0;
+            break;
+        default:
+            break;
+    }
+
+    return ret;
+}
+
+
+/* Create DH private key
+ *
+ * Based on NIST FIPS 186-4,
+ * "B.1.1 Key Pair Generation Using Extra Random Bits"
+ *
+ * dh     - pointer to initialized DhKey structure, needs to have dh->q
+ * rng    - pointer to initialized WC_RNG structure
+ * priv   - output location for generated private key
+ * privSz - IN/OUT, size of priv buffer, size of generated private key
+ *
+ * return 0 on success, negative on error */
+static int GeneratePrivateDh186(DhKey* key, WC_RNG* rng, byte* priv,
+                                word32* privSz)
+{
+    byte* cBuf;
+    int qSz, pSz, cSz, err;
+#ifdef WOLFSSL_SMALL_STACK
+    mp_int* tmpQ = NULL;
+    mp_int* tmpX = NULL;
+#else
+    mp_int tmpQ[1], tmpX[1];
+#endif
+
+    /* Parameters validated in calling functions. */
+
+    if (mp_iszero(&key->q) == MP_YES) {
+        WOLFSSL_MSG("DH q parameter needed for FIPS 186-4 key generation");
+        return BAD_FUNC_ARG;
+    }
+
+    qSz = mp_unsigned_bin_size(&key->q);
+    pSz = mp_unsigned_bin_size(&key->p);
+
+    /* verify (L,N) pair bit lengths */
+    if (CheckDhLN(pSz * WOLFSSL_BIT_SIZE, qSz * WOLFSSL_BIT_SIZE) != 0) {
+        WOLFSSL_MSG("DH param sizes do not match SP 800-56A requirements");
+        return BAD_FUNC_ARG;
+    }
+
+    /* generate extra 64 bits so that bias from mod function is negligible */
+    cSz = qSz + (64 / WOLFSSL_BIT_SIZE);
+    cBuf = (byte*)XMALLOC(cSz, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (cBuf == NULL) {
+        return MEMORY_E;
+    }
+#ifdef WOLFSSL_SMALL_STACK
+    tmpQ = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
+    if (tmpQ == NULL) {
+        XFREE(cBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return MEMORY_E;
+    }
+    tmpX = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
+    if (tmpX == NULL) {
+        XFREE(cBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(tmpQ, key->heap, DYNAMIC_TYPE_DH);
+        return MEMORY_E;
+    }
+#endif
+
+
+    if ((err = mp_init_multi(tmpX, tmpQ, NULL, NULL, NULL, NULL))
+                   != MP_OKAY) {
+        XFREE(cBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(tmpQ, key->heap, DYNAMIC_TYPE_DH);
+        XFREE(tmpX, key->heap, DYNAMIC_TYPE_DH);
+#endif
+        return err;
+    }
+
+    do {
+        /* generate N+64 bits (c) from RBG into tmpX, making sure positive.
+         * Hash_DRBG uses SHA-256 which matches maximum
+         * requested_security_strength of (L,N) */
+        err = wc_RNG_GenerateBlock(rng, cBuf, cSz);
+        if (err == MP_OKAY)
+            err = mp_read_unsigned_bin(tmpX, cBuf, cSz);
+        if (err != MP_OKAY) {
+            mp_clear(tmpX);
+            mp_clear(tmpQ);
+            XFREE(cBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#ifdef WOLFSSL_SMALL_STACK
+            XFREE(tmpQ, key->heap, DYNAMIC_TYPE_DH);
+            XFREE(tmpX, key->heap, DYNAMIC_TYPE_DH);
+#endif
+            return err;
+        }
+    } while (mp_cmp_d(tmpX, 1) != MP_GT);
+
+    ForceZero(cBuf, cSz);
+    XFREE(cBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+    /* tmpQ = q - 1 */
+    if (err == MP_OKAY)
+        err = mp_copy(&key->q, tmpQ);
+
+    if (err == MP_OKAY)
+        err = mp_sub_d(tmpQ, 1, tmpQ);
+
+    /* x = c mod (q-1), tmpX holds c */
+    if (err == MP_OKAY)
+        err = mp_mod(tmpX, tmpQ, tmpX);
+
+    /* x = c mod (q-1) + 1 */
+    if (err == MP_OKAY)
+        err = mp_add_d(tmpX, 1, tmpX);
+
+    /* copy tmpX into priv */
+    if (err == MP_OKAY) {
+        pSz = mp_unsigned_bin_size(tmpX);
+        if (pSz > (int)*privSz) {
+            WOLFSSL_MSG("DH private key output buffer too small");
+            err = BAD_FUNC_ARG;
+        } else {
+            *privSz = pSz;
+            err = mp_to_unsigned_bin(tmpX, priv);
+        }
+    }
+
+    mp_forcezero(tmpX);
+    mp_clear(tmpX);
+    mp_clear(tmpQ);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(tmpQ, key->heap, DYNAMIC_TYPE_DH);
+    XFREE(tmpX, key->heap, DYNAMIC_TYPE_DH);
+#endif
+
+    return err;
+}
+#endif /* WOLFSSL_NO_DH186 */
+#endif /* !WC_NO_RNG */
+
+static int GeneratePrivateDh(DhKey* key, WC_RNG* rng, byte* priv,
+                             word32* privSz)
+{
+#ifndef WC_NO_RNG
+    int ret = 0;
+    word32 sz = 0;
+
+#ifndef WOLFSSL_NO_DH186
+    if (mp_iszero(&key->q) == MP_NO) {
+
+        /* q param available, use NIST FIPS 186-4, "B.1.1 Key Pair
+         * Generation Using Extra Random Bits" */
+        ret = GeneratePrivateDh186(key, rng, priv, privSz);
+
+    } else
+#endif
+    {
+
+        sz = mp_unsigned_bin_size(&key->p);
+
+        /* Table of predetermined values from the operation
+           2 * DiscreteLogWorkFactor(sz * WOLFSSL_BIT_SIZE) /
+           WOLFSSL_BIT_SIZE + 1
+           Sizes in table checked against RFC 3526
+         */
+        WOLFSSL_DH_ROUND(sz); /* if using fixed points only, then round up */
+        switch (sz) {
+            case 128:  sz = 21; break;
+            case 256:  sz = 29; break;
+            case 384:  sz = 34; break;
+            case 512:  sz = 39; break;
+            case 640:  sz = 42; break;
+            case 768:  sz = 46; break;
+            case 896:  sz = 49; break;
+            case 1024: sz = 52; break;
+            default:
+            #ifndef WOLFSSL_DH_CONST
+                /* if using floating points and size of p is not in table */
+                sz = min(sz, 2 * DiscreteLogWorkFactor(sz * WOLFSSL_BIT_SIZE) /
+                                           WOLFSSL_BIT_SIZE + 1);
+                break;
+            #else
+                return BAD_FUNC_ARG;
+            #endif
+        }
+
+        ret = wc_RNG_GenerateBlock(rng, priv, sz);
+
+        if (ret == 0) {
+            priv[0] |= 0x0C;
+            *privSz = sz;
+        }
+    }
+
+    return ret;
+#else
+    (void)key;
+    (void)rng;
+    (void)priv;
+    (void)privSz;
+    return NOT_COMPILED_IN;
+#endif /* WC_NO_RNG */
+}
+
+
+static int GeneratePublicDh(DhKey* key, byte* priv, word32 privSz,
+    byte* pub, word32* pubSz)
+{
+    int ret = 0;
+#ifndef WOLFSSL_SP_MATH
+#ifdef WOLFSSL_SMALL_STACK
+    mp_int* x;
+    mp_int* y;
+#else
+    mp_int x[1];
+    mp_int y[1];
+#endif
+#endif
+
+#ifdef WOLFSSL_HAVE_SP_DH
+#ifndef WOLFSSL_SP_NO_2048
+    if (mp_count_bits(&key->p) == 2048)
+        return sp_DhExp_2048(&key->g, priv, privSz, &key->p, pub, pubSz);
+#endif
+#ifndef WOLFSSL_SP_NO_3072
+    if (mp_count_bits(&key->p) == 3072)
+        return sp_DhExp_3072(&key->g, priv, privSz, &key->p, pub, pubSz);
+#endif
+#ifdef WOLFSSL_SP_4096
+    if (mp_count_bits(&key->p) == 4096)
+        return sp_DhExp_4096(&key->g, priv, privSz, &key->p, pub, pubSz);
+#endif
+#endif
+
+#ifndef WOLFSSL_SP_MATH
+#ifdef WOLFSSL_SMALL_STACK
+    x = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
+    if (x == NULL)
+        return MEMORY_E;
+    y = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
+    if (y == NULL) {
+        XFREE(x, key->heap, DYNAMIC_TYPE_DH);
+        return MEMORY_E;
+    }
+#endif
+    if (mp_init_multi(x, y, 0, 0, 0, 0) != MP_OKAY) {
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(y, key->heap, DYNAMIC_TYPE_DH);
+        XFREE(x, key->heap, DYNAMIC_TYPE_DH);
+    #endif
+        return MP_INIT_E;
+    }
+
+    if (mp_read_unsigned_bin(x, priv, privSz) != MP_OKAY)
+        ret = MP_READ_E;
+
+    if (ret == 0 && mp_exptmod(&key->g, x, &key->p, y) != MP_OKAY)
+        ret = MP_EXPTMOD_E;
+
+    if (ret == 0 && mp_to_unsigned_bin(y, pub) != MP_OKAY)
+        ret = MP_TO_E;
+
+    if (ret == 0)
+        *pubSz = mp_unsigned_bin_size(y);
+
+    mp_clear(y);
+    mp_clear(x);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(y, key->heap, DYNAMIC_TYPE_DH);
+    XFREE(x, key->heap, DYNAMIC_TYPE_DH);
+#endif
+#else
+    ret = WC_KEY_SIZE_E;
+#endif
+
+    return ret;
+}
+
+static int wc_DhGenerateKeyPair_Sync(DhKey* key, WC_RNG* rng,
+    byte* priv, word32* privSz, byte* pub, word32* pubSz)
+{
+    int ret;
+
+    if (key == NULL || rng == NULL || priv == NULL || privSz == NULL ||
+        pub == NULL || pubSz == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    ret = GeneratePrivateDh(key, rng, priv, privSz);
+
+    return (ret != 0) ? ret : GeneratePublicDh(key, priv, *privSz, pub, pubSz);
+}
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH)
+static int wc_DhGenerateKeyPair_Async(DhKey* key, WC_RNG* rng,
+    byte* priv, word32* privSz, byte* pub, word32* pubSz)
+{
+    int ret;
+
+#if defined(HAVE_INTEL_QA)
+    word32 pBits;
+
+    /* QAT DH sizes: 768, 1024, 1536, 2048, 3072 and 4096 bits */
+    pBits = mp_unsigned_bin_size(&key->p) * 8;
+    if (pBits == 768 ||  pBits == 1024 || pBits == 1536 ||
+        pBits == 2048 || pBits == 3072 || pBits == 4096) {
+        mp_int x;
+
+        ret = mp_init(&x);
+        if (ret != MP_OKAY)
+            return ret;
+
+        ret = GeneratePrivateDh(key, rng, priv, privSz);
+        if (ret == 0)
+            ret = mp_read_unsigned_bin(&x, priv, *privSz);
+        if (ret == MP_OKAY)
+            ret = wc_mp_to_bigint(&x, &x.raw);
+        if (ret == MP_OKAY)
+            ret = wc_mp_to_bigint(&key->p, &key->p.raw);
+        if (ret == MP_OKAY)
+            ret = wc_mp_to_bigint(&key->g, &key->g.raw);
+        if (ret == MP_OKAY)
+            ret = IntelQaDhKeyGen(&key->asyncDev, &key->p.raw, &key->g.raw,
+                &x.raw, pub, pubSz);
+        mp_clear(&x);
+
+        return ret;
+    }
+
+#elif defined(HAVE_CAVIUM)
+    /* TODO: Not implemented - use software for now */
+
+#else /* WOLFSSL_ASYNC_CRYPT_TEST */
+    if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_DH_GEN)) {
+        WC_ASYNC_TEST* testDev = &key->asyncDev.test;
+        testDev->dhGen.key = key;
+        testDev->dhGen.rng = rng;
+        testDev->dhGen.priv = priv;
+        testDev->dhGen.privSz = privSz;
+        testDev->dhGen.pub = pub;
+        testDev->dhGen.pubSz = pubSz;
+        return WC_PENDING_E;
+    }
+#endif
+
+    /* otherwise use software DH */
+    ret = wc_DhGenerateKeyPair_Sync(key, rng, priv, privSz, pub, pubSz);
+
+    return ret;
+}
+#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_DH */
+
+
+/* Check DH Public Key for invalid numbers, optionally allowing
+ * the public key to be checked against the large prime (q).
+ * Check per process in SP 800-56Ar3, section 5.6.2.3.1.
+ *
+ * key     DH key group parameters.
+ * pub     Public Key.
+ * pubSz   Public Key size.
+ * prime   Large prime (q), optionally NULL to skip check
+ * primeSz Size of large prime
+ *
+ *  returns 0 on success or error code
+ */
+int wc_DhCheckPubKey_ex(DhKey* key, const byte* pub, word32 pubSz,
+                        const byte* prime, word32 primeSz)
+{
+    int ret = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    mp_int* y = NULL;
+    mp_int* p = NULL;
+    mp_int* q = NULL;
+#else
+    mp_int y[1];
+    mp_int p[1];
+    mp_int q[1];
+#endif
+
+    if (key == NULL || pub == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    y = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
+    if (y == NULL)
+        return MEMORY_E;
+    p = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
+    if (p == NULL) {
+        XFREE(y, key->heap, DYNAMIC_TYPE_DH);
+        return MEMORY_E;
+    }
+    q = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
+    if (q == NULL) {
+        XFREE(p, key->heap, DYNAMIC_TYPE_DH);
+        XFREE(y, key->heap, DYNAMIC_TYPE_DH);
+        return MEMORY_E;
+    }
+#endif
+
+    if (mp_init_multi(y, p, q, NULL, NULL, NULL) != MP_OKAY) {
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(q, key->heap, DYNAMIC_TYPE_DH);
+        XFREE(p, key->heap, DYNAMIC_TYPE_DH);
+        XFREE(y, key->heap, DYNAMIC_TYPE_DH);
+    #endif
+        return MP_INIT_E;
+    }
+
+    if (mp_read_unsigned_bin(y, pub, pubSz) != MP_OKAY) {
+        ret = MP_READ_E;
+    }
+
+    if (ret == 0 && prime != NULL) {
+        if (mp_read_unsigned_bin(q, prime, primeSz) != MP_OKAY)
+            ret = MP_READ_E;
+
+    } else if (mp_iszero(&key->q) == MP_NO) {
+        /* use q available in DhKey */
+        if (mp_copy(&key->q, q) != MP_OKAY)
+            ret = MP_INIT_E;
+    }
+
+    /* SP 800-56Ar3, section 5.6.2.3.1, process step 1 */
+    /* pub (y) should not be 0 or 1 */
+    if (ret == 0 && mp_cmp_d(y, 2) == MP_LT) {
+        ret = MP_CMP_E;
+    }
+
+    /* pub (y) shouldn't be greater than or equal to p - 1 */
+    if (ret == 0 && mp_copy(&key->p, p) != MP_OKAY) {
+        ret = MP_INIT_E;
+    }
+    if (ret == 0 && mp_sub_d(p, 2, p) != MP_OKAY) {
+        ret = MP_SUB_E;
+    }
+    if (ret == 0 && mp_cmp(y, p) == MP_GT) {
+        ret = MP_CMP_E;
+    }
+
+    if (ret == 0 && (prime != NULL || (mp_iszero(&key->q) == MP_NO) )) {
+
+        /* restore key->p into p */
+        if (mp_copy(&key->p, p) != MP_OKAY)
+            ret = MP_INIT_E;
+    }
+
+    if (ret == 0 && prime != NULL) {
+#ifdef WOLFSSL_HAVE_SP_DH
+#ifndef WOLFSSL_SP_NO_2048
+        if (mp_count_bits(&key->p) == 2048) {
+            ret = sp_ModExp_2048(y, q, p, y);
+            if (ret != 0)
+                ret = MP_EXPTMOD_E;
+        }
+        else
+#endif
+#ifndef WOLFSSL_SP_NO_3072
+        if (mp_count_bits(&key->p) == 3072) {
+            ret = sp_ModExp_3072(y, q, p, y);
+            if (ret != 0)
+                ret = MP_EXPTMOD_E;
+        }
+        else
+#endif
+#ifdef WOLFSSL_SP_NO_4096
+        if (mp_count_bits(&key->p) == 4096) {
+            ret = sp_ModExp_4096(y, q, p, y);
+            if (ret != 0)
+                ret = MP_EXPTMOD_E;
+        }
+        else
+#endif
+#endif
+
+        {
+    /* SP 800-56Ar3, section 5.6.2.3.1, process step 2 */
+#ifndef WOLFSSL_SP_MATH
+            /* calculate (y^q) mod(p), store back into y */
+            if (mp_exptmod(y, q, p, y) != MP_OKAY)
+                ret = MP_EXPTMOD_E;
+#else
+            ret = WC_KEY_SIZE_E;
+#endif
+        }
+
+        /* verify above == 1 */
+        if (ret == 0 && mp_cmp_d(y, 1) != MP_EQ)
+            ret = MP_CMP_E;
+    }
+
+    mp_clear(y);
+    mp_clear(p);
+    mp_clear(q);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(q, key->heap, DYNAMIC_TYPE_DH);
+    XFREE(p, key->heap, DYNAMIC_TYPE_DH);
+    XFREE(y, key->heap, DYNAMIC_TYPE_DH);
+#endif
+
+    return ret;
+}
+
+
+/* Check DH Public Key for invalid numbers
+ *
+ * key   DH key group parameters.
+ * pub   Public Key.
+ * pubSz Public Key size.
+ *
+ *  returns 0 on success or error code
+ */
+int wc_DhCheckPubKey(DhKey* key, const byte* pub, word32 pubSz)
+{
+    return wc_DhCheckPubKey_ex(key, pub, pubSz, NULL, 0);
+}
+
+
+/**
+ * Quick validity check of public key value against prime.
+ * Checks are:
+ *   - Public key not 0 or 1
+ *   - Public key not equal to prime or prime - 1
+ *   - Public key not bigger than prime.
+ *
+ * prime    Big-endian encoding of prime in bytes.
+ * primeSz  Size of prime in bytes.
+ * pub      Big-endian encoding of public key in bytes.
+ * pubSz    Size of public key in bytes.
+ */
+int wc_DhCheckPubValue(const byte* prime, word32 primeSz, const byte* pub,
+                       word32 pubSz)
+{
+    int ret = 0;
+    word32 i;
+
+    for (i = 0; i < pubSz && pub[i] == 0; i++) {
+    }
+    pubSz -= i;
+    pub += i;
+
+    if (pubSz == 0 || (pubSz == 1 && pub[0] == 1))
+        ret = MP_VAL;
+    else if (pubSz == primeSz) {
+        for (i = 0; i < pubSz-1 && pub[i] == prime[i]; i++) {
+        }
+        if (i == pubSz-1 && (pub[i] == prime[i] || pub[i] == prime[i] - 1))
+            ret = MP_VAL;
+        else if (pub[i] > prime[i])
+            ret = MP_VAL;
+    }
+    else if (pubSz > primeSz)
+        ret = MP_VAL;
+
+    return ret;
+}
+
+
+/* Check DH Private Key for invalid numbers, optionally allowing
+ * the private key to be checked against the large prime (q).
+ * Check per process in SP 800-56Ar3, section 5.6.2.1.2.
+ *
+ * key     DH key group parameters.
+ * priv    Private Key.
+ * privSz  Private Key size.
+ * prime   Large prime (q), optionally NULL to skip check
+ * primeSz Size of large prime
+ *
+ *  returns 0 on success or error code
+ */
+int wc_DhCheckPrivKey_ex(DhKey* key, const byte* priv, word32 privSz,
+                         const byte* prime, word32 primeSz)
+{
+    int ret = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    mp_int* x = NULL;
+    mp_int* q = NULL;
+#else
+    mp_int x[1];
+    mp_int q[1];
+#endif
+
+    if (key == NULL || priv == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    x = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
+    if (x == NULL)
+        return MEMORY_E;
+    q = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
+    if (q == NULL) {
+        XFREE(x, key->heap, DYNAMIC_TYPE_DH);
+        return MEMORY_E;
+    }
+#endif
+
+    if (mp_init_multi(x, q, NULL, NULL, NULL, NULL) != MP_OKAY) {
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(q, key->heap, DYNAMIC_TYPE_DH);
+        XFREE(x, key->heap, DYNAMIC_TYPE_DH);
+    #endif
+        return MP_INIT_E;
+    }
+
+    if (mp_read_unsigned_bin(x, priv, privSz) != MP_OKAY) {
+        ret = MP_READ_E;
+    }
+
+    if (ret == 0) {
+        if (prime != NULL) {
+            if (mp_read_unsigned_bin(q, prime, primeSz) != MP_OKAY)
+                ret = MP_READ_E;
+        }
+        else if (mp_iszero(&key->q) == MP_NO) {
+            /* use q available in DhKey */
+            if (mp_copy(&key->q, q) != MP_OKAY)
+                ret = MP_INIT_E;
+        }
+    }
+
+    /* priv (x) should not be 0 */
+    if (ret == 0) {
+        if (mp_cmp_d(x, 0) == MP_EQ)
+            ret = MP_CMP_E;
+    }
+
+    if (ret == 0) {
+        if (mp_iszero(q) == MP_NO) {
+            /* priv (x) shouldn't be greater than q - 1 */
+            if (ret == 0) {
+                if (mp_copy(&key->q, q) != MP_OKAY)
+                    ret = MP_INIT_E;
+            }
+            if (ret == 0) {
+                if (mp_sub_d(q, 1, q) != MP_OKAY)
+                    ret = MP_SUB_E;
+            }
+            if (ret == 0) {
+                if (mp_cmp(x, q) == MP_GT)
+                    ret = DH_CHECK_PRIV_E;
+            }
+        }
+    }
+
+    mp_clear(x);
+    mp_clear(q);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(q, key->heap, DYNAMIC_TYPE_DH);
+    XFREE(x, key->heap, DYNAMIC_TYPE_DH);
+#endif
+
+    return ret;
+}
+
+
+/* Check DH Private Key for invalid numbers
+ *
+ * key    DH key group parameters.
+ * priv   Private Key.
+ * privSz Private Key size.
+ *
+ *  returns 0 on success or error code
+ */
+int wc_DhCheckPrivKey(DhKey* key, const byte* priv, word32 privSz)
+{
+    return wc_DhCheckPrivKey_ex(key, priv, privSz, NULL, 0);
+}
+
+
+/* Check DH Keys for pair-wise consistency per process in
+ * SP 800-56Ar3, section 5.6.2.1.4, method (b) for FFC.
+ *
+ * key    DH key group parameters.
+ * pub    Public Key.
+ * pubSz  Public Key size.
+ * priv   Private Key.
+ * privSz Private Key size.
+ *
+ *  returns 0 on success or error code
+ */
+int wc_DhCheckKeyPair(DhKey* key, const byte* pub, word32 pubSz,
+                      const byte* priv, word32 privSz)
+{
+#ifdef WOLFSSL_SMALL_STACK
+    mp_int* publicKey = NULL;
+    mp_int* privateKey = NULL;
+    mp_int* checkKey = NULL;
+#else
+    mp_int publicKey[1];
+    mp_int privateKey[1];
+    mp_int checkKey[1];
+#endif
+    int ret = 0;
+
+    if (key == NULL || pub == NULL || priv == NULL)
+        return BAD_FUNC_ARG;
+
+#ifdef WOLFSSL_SMALL_STACK
+    publicKey = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
+    if (publicKey == NULL)
+        return MEMORY_E;
+    privateKey = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
+    if (privateKey == NULL) {
+        XFREE(publicKey, key->heap, DYNAMIC_TYPE_DH);
+        return MEMORY_E;
+    }
+    checkKey = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
+    if (checkKey == NULL) {
+        XFREE(privateKey, key->heap, DYNAMIC_TYPE_DH);
+        XFREE(publicKey, key->heap, DYNAMIC_TYPE_DH);
+        return MEMORY_E;
+    }
+#endif
+
+    if (mp_init_multi(publicKey, privateKey, checkKey,
+                      NULL, NULL, NULL) != MP_OKAY) {
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(privateKey, key->heap, DYNAMIC_TYPE_DH);
+        XFREE(publicKey, key->heap, DYNAMIC_TYPE_DH);
+        XFREE(checkKey, key->heap, DYNAMIC_TYPE_DH);
+    #endif
+        return MP_INIT_E;
+    }
+
+    /* Load the private and public keys into big integers. */
+    if (mp_read_unsigned_bin(publicKey, pub, pubSz) != MP_OKAY ||
+        mp_read_unsigned_bin(privateKey, priv, privSz) != MP_OKAY) {
+
+        ret = MP_READ_E;
+    }
+
+    /* Calculate checkKey = g^privateKey mod p */
+    if (ret == 0) {
+#ifdef WOLFSSL_HAVE_SP_DH
+#ifndef WOLFSSL_SP_NO_2048
+        if (mp_count_bits(&key->p) == 2048) {
+            ret = sp_ModExp_2048(&key->g, privateKey, &key->p, checkKey);
+            if (ret != 0)
+                ret = MP_EXPTMOD_E;
+        }
+        else
+#endif
+#ifndef WOLFSSL_SP_NO_3072
+        if (mp_count_bits(&key->p) == 3072) {
+            ret = sp_ModExp_3072(&key->g, privateKey, &key->p, checkKey);
+            if (ret != 0)
+                ret = MP_EXPTMOD_E;
+        }
+        else
+#endif
+#ifdef WOLFSSL_SP_4096
+        if (mp_count_bits(&key->p) == 4096) {
+            ret = sp_ModExp_4096(&key->g, privateKey, &key->p, checkKey);
+            if (ret != 0)
+                ret = MP_EXPTMOD_E;
+        }
+        else
+#endif
+#endif
+        {
+#ifndef WOLFSSL_SP_MATH
+            if (mp_exptmod(&key->g, privateKey, &key->p, checkKey) != MP_OKAY)
+                ret = MP_EXPTMOD_E;
+#else
+            ret = WC_KEY_SIZE_E;
+#endif
+        }
+    }
+
+    /* Compare the calculated public key to the supplied check value. */
+    if (ret == 0) {
+        if (mp_cmp(checkKey, publicKey) != MP_EQ)
+            ret = MP_CMP_E;
+    }
+
+    mp_forcezero(privateKey);
+    mp_clear(privateKey);
+    mp_clear(publicKey);
+    mp_clear(checkKey);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(checkKey, key->heap, DYNAMIC_TYPE_DH);
+    XFREE(privateKey, key->heap, DYNAMIC_TYPE_DH);
+    XFREE(publicKey, key->heap, DYNAMIC_TYPE_DH);
+#endif
+
+    return ret;
+}
+
+
+int wc_DhGenerateKeyPair(DhKey* key, WC_RNG* rng,
+    byte* priv, word32* privSz, byte* pub, word32* pubSz)
+{
+    int ret;
+
+    if (key == NULL || rng == NULL || priv == NULL || privSz == NULL ||
+                                                pub == NULL || pubSz == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH)
+    if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_DH) {
+        ret = wc_DhGenerateKeyPair_Async(key, rng, priv, privSz, pub, pubSz);
+    }
+    else
+#endif
+    {
+        ret = wc_DhGenerateKeyPair_Sync(key, rng, priv, privSz, pub, pubSz);
+    }
+
+    return ret;
+}
+
+
+static int wc_DhAgree_Sync(DhKey* key, byte* agree, word32* agreeSz,
+    const byte* priv, word32 privSz, const byte* otherPub, word32 pubSz)
+{
+    int ret = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    mp_int* y;
+#ifndef WOLFSSL_SP_MATH
+    mp_int* x;
+    mp_int* z;
+#endif
+#else
+    mp_int y[1];
+#ifndef WOLFSSL_SP_MATH
+    mp_int x[1];
+    mp_int z[1];
+#endif
+#endif
+
+#ifdef WOLFSSL_VALIDATE_FFC_IMPORT
+    if (wc_DhCheckPrivKey(key, priv, privSz) != 0) {
+        WOLFSSL_MSG("wc_DhAgree wc_DhCheckPrivKey failed");
+        return DH_CHECK_PRIV_E;
+    }
+
+    if (wc_DhCheckPubKey(key, otherPub, pubSz) != 0) {
+        WOLFSSL_MSG("wc_DhAgree wc_DhCheckPubKey failed");
+        return DH_CHECK_PUB_E;
+    }
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+    y = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
+    if (y == NULL)
+        return MEMORY_E;
+#ifndef WOLFSSL_SP_MATH
+    x = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
+    if (x == NULL) {
+        XFREE(y, key->heap, DYNAMIC_TYPE_DH);
+        return MEMORY_E;
+    }
+    z = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
+    if (z == NULL) {
+        XFREE(x, key->heap, DYNAMIC_TYPE_DH);
+        XFREE(y, key->heap, DYNAMIC_TYPE_DH);
+        return MEMORY_E;
+    }
+#endif
+#endif
+
+#ifdef WOLFSSL_HAVE_SP_DH
+#ifndef WOLFSSL_SP_NO_2048
+    if (mp_count_bits(&key->p) == 2048) {
+        if (mp_init(y) != MP_OKAY)
+            return MP_INIT_E;
+
+        if (ret == 0 && mp_read_unsigned_bin(y, otherPub, pubSz) != MP_OKAY)
+            ret = MP_READ_E;
+
+        if (ret == 0)
+            ret = sp_DhExp_2048(y, priv, privSz, &key->p, agree, agreeSz);
+
+        mp_clear(y);
+    #ifdef WOLFSSL_SMALL_STACK
+    #ifndef WOLFSSL_SP_MATH
+        XFREE(z, key->heap, DYNAMIC_TYPE_DH);
+        XFREE(x, key->heap, DYNAMIC_TYPE_DH);
+    #endif
+        XFREE(y, key->heap, DYNAMIC_TYPE_DH);
+    #endif
+        return ret;
+    }
+#endif
+#ifndef WOLFSSL_SP_NO_3072
+    if (mp_count_bits(&key->p) == 3072) {
+        if (mp_init(y) != MP_OKAY)
+            return MP_INIT_E;
+
+        if (ret == 0 && mp_read_unsigned_bin(y, otherPub, pubSz) != MP_OKAY)
+            ret = MP_READ_E;
+
+        if (ret == 0)
+            ret = sp_DhExp_3072(y, priv, privSz, &key->p, agree, agreeSz);
+
+        mp_clear(y);
+    #ifdef WOLFSSL_SMALL_STACK
+    #ifndef WOLFSSL_SP_MATH
+        XFREE(z, key->heap, DYNAMIC_TYPE_DH);
+        XFREE(x, key->heap, DYNAMIC_TYPE_DH);
+    #endif
+        XFREE(y, key->heap, DYNAMIC_TYPE_DH);
+    #endif
+        return ret;
+    }
+#endif
+#ifdef WOLFSSL_SP_4096
+    if (mp_count_bits(&key->p) == 4096) {
+        if (mp_init(y) != MP_OKAY)
+            return MP_INIT_E;
+
+        if (ret == 0 && mp_read_unsigned_bin(y, otherPub, pubSz) != MP_OKAY)
+            ret = MP_READ_E;
+
+        if (ret == 0)
+            ret = sp_DhExp_4096(y, priv, privSz, &key->p, agree, agreeSz);
+
+        mp_clear(y);
+    #ifdef WOLFSSL_SMALL_STACK
+    #ifndef WOLFSSL_SP_MATH
+        XFREE(z, key->heap, DYNAMIC_TYPE_DH);
+        XFREE(x, key->heap, DYNAMIC_TYPE_DH);
+    #endif
+        XFREE(y, key->heap, DYNAMIC_TYPE_DH);
+    #endif
+        return ret;
+    }
+#endif
+#endif
+
+#ifndef WOLFSSL_SP_MATH
+    if (mp_init_multi(x, y, z, 0, 0, 0) != MP_OKAY) {
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(z, key->heap, DYNAMIC_TYPE_DH);
+        XFREE(x, key->heap, DYNAMIC_TYPE_DH);
+        XFREE(y, key->heap, DYNAMIC_TYPE_DH);
+    #endif
+        return MP_INIT_E;
+    }
+
+    if (mp_read_unsigned_bin(x, priv, privSz) != MP_OKAY)
+        ret = MP_READ_E;
+
+    if (ret == 0 && mp_read_unsigned_bin(y, otherPub, pubSz) != MP_OKAY)
+        ret = MP_READ_E;
+
+    if (ret == 0 && mp_exptmod(y, x, &key->p, z) != MP_OKAY)
+        ret = MP_EXPTMOD_E;
+
+    /* make sure z is not one (SP800-56A, 5.7.1.1) */
+    if (ret == 0 && (mp_cmp_d(z, 1) == MP_EQ))
+        ret = MP_VAL;
+
+    if (ret == 0 && mp_to_unsigned_bin(z, agree) != MP_OKAY)
+        ret = MP_TO_E;
+
+    if (ret == 0)
+        *agreeSz = mp_unsigned_bin_size(z);
+
+    mp_clear(z);
+    mp_clear(y);
+    mp_forcezero(x);
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+#ifndef WOLFSSL_SP_MATH
+    XFREE(z, key->heap, DYNAMIC_TYPE_DH);
+    XFREE(x, key->heap, DYNAMIC_TYPE_DH);
+#endif
+    XFREE(y, key->heap, DYNAMIC_TYPE_DH);
+#endif
+
+    return ret;
+}
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH)
+static int wc_DhAgree_Async(DhKey* key, byte* agree, word32* agreeSz,
+    const byte* priv, word32 privSz, const byte* otherPub, word32 pubSz)
+{
+    int ret;
+
+#if defined(HAVE_INTEL_QA)
+    word32 pBits;
+
+    /* QAT DH sizes: 768, 1024, 1536, 2048, 3072 and 4096 bits */
+    pBits = mp_unsigned_bin_size(&key->p) * 8;
+    if (pBits == 768 ||  pBits == 1024 || pBits == 1536 ||
+        pBits == 2048 || pBits == 3072 || pBits == 4096) {
+        ret = wc_mp_to_bigint(&key->p, &key->p.raw);
+        if (ret == MP_OKAY)
+            ret = IntelQaDhAgree(&key->asyncDev, &key->p.raw,
+                agree, agreeSz, priv, privSz, otherPub, pubSz);
+        return ret;
+    }
+
+#elif defined(HAVE_CAVIUM)
+    /* TODO: Not implemented - use software for now */
+
+#else /* WOLFSSL_ASYNC_CRYPT_TEST */
+    if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_DH_AGREE)) {
+        WC_ASYNC_TEST* testDev = &key->asyncDev.test;
+        testDev->dhAgree.key = key;
+        testDev->dhAgree.agree = agree;
+        testDev->dhAgree.agreeSz = agreeSz;
+        testDev->dhAgree.priv = priv;
+        testDev->dhAgree.privSz = privSz;
+        testDev->dhAgree.otherPub = otherPub;
+        testDev->dhAgree.pubSz = pubSz;
+        return WC_PENDING_E;
+    }
+#endif
+
+    /* otherwise use software DH */
+    ret = wc_DhAgree_Sync(key, agree, agreeSz, priv, privSz, otherPub, pubSz);
+
+    return ret;
+}
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv,
+            word32 privSz, const byte* otherPub, word32 pubSz)
+{
+    int ret = 0;
+
+    if (key == NULL || agree == NULL || agreeSz == NULL || priv == NULL ||
+                                                            otherPub == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH)
+    if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_DH) {
+        ret = wc_DhAgree_Async(key, agree, agreeSz, priv, privSz, otherPub, pubSz);
+    }
+    else
+#endif
+    {
+        ret = wc_DhAgree_Sync(key, agree, agreeSz, priv, privSz, otherPub, pubSz);
+    }
+
+    return ret;
+}
+
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+/* Sets private and public key in DhKey if both are available, otherwise sets
+    either private or public key, depending on which is available.
+    Returns WOLFSSL_SUCCESS if at least one of the keys was set. */
+WOLFSSL_LOCAL int wc_DhSetFullKeys(DhKey* key,const byte* priv_key,word32 privSz,
+                                   const byte* pub_key, word32 pubSz)
+{
+    byte havePriv = 0;
+    byte havePub = 0;
+    mp_int* keyPriv = NULL;
+    mp_int* keyPub  = NULL;
+
+    if (key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    havePriv = ( (priv_key != NULL) && (privSz > 0) );
+    havePub  = ( (pub_key  != NULL) && (pubSz  > 0) );
+
+    if (!havePub && !havePriv) {
+        WOLFSSL_MSG("No Public or Private Key to Set");
+        return BAD_FUNC_ARG;
+    }
+    /* Set Private Key */
+    if (havePriv == TRUE) {
+        /* may have leading 0 */
+        if (priv_key[0] == 0) {
+            privSz--; priv_key++;
+        }
+        if (mp_init(&key->priv) != MP_OKAY)
+            havePriv = FALSE;
+    }
+
+    if (havePriv == TRUE) {
+        if (mp_read_unsigned_bin(&key->priv, priv_key, privSz) != MP_OKAY) {
+            havePriv = FALSE;
+        } else {
+            keyPriv = &key->priv;
+            WOLFSSL_MSG("DH Private Key Set.");
+        }
+    }
+
+    /* Set Public Key */
+    if (havePub == TRUE) {
+        /* may have leading 0 */
+        if (pub_key[0] == 0) {
+            pubSz--; pub_key++;
+        }
+        if (mp_init(&key->pub) != MP_OKAY)
+            havePub = FALSE;
+    }
+
+    if (havePub == TRUE) {
+        if (mp_read_unsigned_bin(&key->pub, pub_key, pubSz) != MP_OKAY) {
+            havePub = FALSE;
+        } else {
+            keyPub = &key->pub;
+            WOLFSSL_MSG("DH Public Key Set.");
+        }
+    }
+    /* Free Memory if error occured */
+    if (havePriv == FALSE && keyPriv != NULL)
+        mp_clear(keyPriv);
+    if (havePub == FALSE && keyPub != NULL)
+        mp_clear(keyPub);
+
+    /* WOLFSSL_SUCCESS if private or public was set else WOLFSSL_FAILURE */
+    return havePriv || havePub;
+}
+#endif
+
+static int _DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g,
+                   word32 gSz, const byte* q, word32 qSz, int trusted,
+                   WC_RNG* rng)
+{
+    int ret = 0;
+    mp_int* keyP = NULL;
+    mp_int* keyG = NULL;
+
+    if (key == NULL || p == NULL || g == NULL || pSz == 0 || gSz == 0) {
+        ret = BAD_FUNC_ARG;
+    }
+
+    if (ret == 0) {
+        /* may have leading 0 */
+        if (p[0] == 0) {
+            pSz--; p++;
+        }
+
+        if (g[0] == 0) {
+            gSz--; g++;
+        }
+
+        if (q != NULL) {
+            if (q[0] == 0) {
+                qSz--; q++;
+            }
+        }
+
+        if (mp_init(&key->p) != MP_OKAY)
+            ret = MP_INIT_E;
+    }
+
+    if (ret == 0) {
+        if (mp_read_unsigned_bin(&key->p, p, pSz) != MP_OKAY)
+            ret = ASN_DH_KEY_E;
+        else
+            keyP = &key->p;
+    }
+
+    if (ret == 0 && !trusted) {
+        int isPrime = 0;
+        if (rng != NULL)
+            ret = mp_prime_is_prime_ex(keyP, 8, &isPrime, rng);
+        else
+            ret = mp_prime_is_prime(keyP, 8, &isPrime);
+
+        if (ret == 0 && isPrime == 0)
+            ret = DH_CHECK_PUB_E;
+    }
+
+    if (ret == 0 && mp_init(&key->g) != MP_OKAY)
+        ret = MP_INIT_E;
+    if (ret == 0) {
+        if (mp_read_unsigned_bin(&key->g, g, gSz) != MP_OKAY)
+            ret = ASN_DH_KEY_E;
+        else
+            keyG = &key->g;
+    }
+
+    if (ret == 0 && q != NULL) {
+        if (mp_init(&key->q) != MP_OKAY)
+            ret = MP_INIT_E;
+    }
+    if (ret == 0 && q != NULL) {
+        if (mp_read_unsigned_bin(&key->q, q, qSz) != MP_OKAY)
+            ret = MP_INIT_E;
+    }
+
+    if (ret != 0 && key != NULL) {
+        if (keyG)
+            mp_clear(keyG);
+        if (keyP)
+            mp_clear(keyP);
+    }
+
+    return ret;
+}
+
+
+int wc_DhSetCheckKey(DhKey* key, const byte* p, word32 pSz, const byte* g,
+                   word32 gSz, const byte* q, word32 qSz, int trusted,
+                   WC_RNG* rng)
+{
+    return _DhSetKey(key, p, pSz, g, gSz, q, qSz, trusted, rng);
+}
+
+
+int wc_DhSetKey_ex(DhKey* key, const byte* p, word32 pSz, const byte* g,
+                   word32 gSz, const byte* q, word32 qSz)
+{
+    return _DhSetKey(key, p, pSz, g, gSz, q, qSz, 1, NULL);
+}
+
+
+/* not in asn anymore since no actual asn types used */
+int wc_DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g,
+                word32 gSz)
+{
+    return _DhSetKey(key, p, pSz, g, gSz, NULL, 0, 1, NULL);
+}
+
+
+#ifdef WOLFSSL_KEY_GEN
+
+/* modulus_size in bits */
+int wc_DhGenerateParams(WC_RNG *rng, int modSz, DhKey *dh)
+{
+    mp_int  tmp, tmp2;
+    int     groupSz = 0, bufSz = 0,
+            primeCheckCount = 0,
+            primeCheck = MP_NO,
+            ret = 0;
+    unsigned char *buf = NULL;
+
+    if (rng == NULL || dh == NULL)
+        ret = BAD_FUNC_ARG;
+
+    /* set group size in bytes from modulus size
+     * FIPS 186-4 defines valid values (1024, 160) (2048, 256) (3072, 256)
+     */
+    if (ret == 0) {
+        switch (modSz) {
+            case 1024:
+                groupSz = 20;
+                break;
+            case 2048:
+            case 3072:
+                groupSz = 32;
+                break;
+            default:
+                ret = BAD_FUNC_ARG;
+                break;
+        }
+    }
+
+    if (ret == 0) {
+        /* modulus size in bytes */
+        modSz /= WOLFSSL_BIT_SIZE;
+        bufSz = modSz - groupSz;
+
+        /* allocate ram */
+        buf = (unsigned char *)XMALLOC(bufSz,
+                                       dh->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        if (buf == NULL)
+            ret = MEMORY_E;
+    }
+
+    /* make a random string that will be multiplied against q */
+    if (ret == 0)
+        ret = wc_RNG_GenerateBlock(rng, buf, bufSz);
+
+    if (ret == 0) {
+        /* force magnitude */
+        buf[0] |= 0xC0;
+        /* force even */
+        buf[bufSz - 1] &= ~1;
+
+        if (mp_init_multi(&tmp, &tmp2, &dh->p, &dh->q, &dh->g, 0)
+                != MP_OKAY) {
+            ret = MP_INIT_E;
+        }
+    }
+
+    if (ret == 0) {
+        if (mp_read_unsigned_bin(&tmp2, buf, bufSz) != MP_OKAY)
+            ret = MP_READ_E;
+    }
+
+    /* make our prime q */
+    if (ret == 0) {
+        if (mp_rand_prime(&dh->q, groupSz, rng, NULL) != MP_OKAY)
+            ret = PRIME_GEN_E;
+    }
+
+    /* p = random * q */
+    if (ret == 0) {
+        if (mp_mul(&dh->q, &tmp2, &dh->p) != MP_OKAY)
+            ret = MP_MUL_E;
+    }
+
+    /* p = random * q + 1, so q is a prime divisor of p-1 */
+    if (ret == 0) {
+        if (mp_add_d(&dh->p, 1, &dh->p) != MP_OKAY)
+            ret = MP_ADD_E;
+    }
+
+    /* tmp = 2q  */
+    if (ret == 0) {
+        if (mp_add(&dh->q, &dh->q, &tmp) != MP_OKAY)
+            ret = MP_ADD_E;
+    }
+
+    /* loop until p is prime */
+    if (ret == 0) {
+        do {
+            if (mp_prime_is_prime_ex(&dh->p, 8, &primeCheck, rng) != MP_OKAY)
+                ret = PRIME_GEN_E;
+
+            if (primeCheck != MP_YES) {
+                /* p += 2q */
+                if (mp_add(&tmp, &dh->p, &dh->p) != MP_OKAY)
+                    ret = MP_ADD_E;
+                else
+                    primeCheckCount++;
+            }
+        } while (ret == 0 && primeCheck == MP_NO);
+    }
+
+    /* tmp2 += (2*loop_check_prime)
+     * to have p = (q * tmp2) + 1 prime
+     */
+    if ((ret == 0) && (primeCheckCount)) {
+        if (mp_add_d(&tmp2, 2 * primeCheckCount, &tmp2) != MP_OKAY)
+            ret = MP_ADD_E;
+    }
+
+    /* find a value g for which g^tmp2 != 1 */
+    if ((ret == 0) && (mp_set(&dh->g, 1) != MP_OKAY))
+        ret = MP_ZERO_E;
+
+    if (ret == 0) {
+        do {
+            if (mp_add_d(&dh->g, 1, &dh->g) != MP_OKAY)
+                ret = MP_ADD_E;
+            else if (mp_exptmod(&dh->g, &tmp2, &dh->p, &tmp) != MP_OKAY)
+                ret = MP_EXPTMOD_E;
+        } while (ret == 0 && mp_cmp_d(&tmp, 1) == MP_EQ);
+    }
+
+    if (ret == 0) {
+        /* at this point tmp generates a group of order q mod p */
+        mp_exch(&tmp, &dh->g);
+    }
+
+    /* clear the parameters if there was an error */
+    if ((ret != 0) && (dh != NULL)) {
+        mp_clear(&dh->q);
+        mp_clear(&dh->p);
+        mp_clear(&dh->g);
+    }
+
+    if (buf != NULL) {
+        ForceZero(buf, bufSz);
+        if (dh != NULL) {
+            XFREE(buf, dh->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        }
+    }
+    mp_clear(&tmp);
+    mp_clear(&tmp2);
+
+    return ret;
+}
+
+
+/* Export raw DH parameters from DhKey structure
+ *
+ * dh   - pointer to initialized DhKey structure
+ * p    - output location for DH (p) parameter
+ * pSz  - [IN/OUT] size of output buffer for p, size of p
+ * q    - output location for DH (q) parameter
+ * qSz  - [IN/OUT] size of output buffer for q, size of q
+ * g    - output location for DH (g) parameter
+ * gSz  - [IN/OUT] size of output buffer for g, size of g
+ *
+ * If p, q, and g pointers are all passed in as NULL, the function
+ * will set pSz, qSz, and gSz to the required output buffer sizes for p,
+ * q, and g. In this case, the function will return LENGTH_ONLY_E.
+ *
+ * returns 0 on success, negative upon failure
+ */
+int wc_DhExportParamsRaw(DhKey* dh, byte* p, word32* pSz,
+                         byte* q, word32* qSz, byte* g, word32* gSz)
+{
+    int ret = 0;
+    word32 pLen = 0, qLen = 0, gLen = 0;
+
+    if (dh == NULL || pSz == NULL || qSz == NULL || gSz == NULL)
+        ret = BAD_FUNC_ARG;
+
+    /* get required output buffer sizes */
+    if (ret == 0) {
+        pLen = mp_unsigned_bin_size(&dh->p);
+        qLen = mp_unsigned_bin_size(&dh->q);
+        gLen = mp_unsigned_bin_size(&dh->g);
+
+        /* return buffer sizes and LENGTH_ONLY_E if buffers are NULL */
+        if (p == NULL && q == NULL && g == NULL) {
+            *pSz = pLen;
+            *qSz = qLen;
+            *gSz = gLen;
+            ret = LENGTH_ONLY_E;
+        }
+    }
+
+    if (ret == 0) {
+        if (p == NULL || q == NULL || g == NULL)
+            ret = BAD_FUNC_ARG;
+    }
+
+    /* export p */
+    if (ret == 0) {
+        if (*pSz < pLen) {
+            WOLFSSL_MSG("Output buffer for DH p parameter too small, "
+                        "required size placed into pSz");
+            *pSz = pLen;
+            ret = BUFFER_E;
+        }
+    }
+
+    if (ret == 0) {
+        *pSz = pLen;
+        if (mp_to_unsigned_bin(&dh->p, p) != MP_OKAY)
+            ret = MP_TO_E;
+    }
+
+    /* export q */
+    if (ret == 0) {
+        if (*qSz < qLen) {
+            WOLFSSL_MSG("Output buffer for DH q parameter too small, "
+                        "required size placed into qSz");
+            *qSz = qLen;
+            ret = BUFFER_E;
+        }
+    }
+
+    if (ret == 0) {
+        *qSz = qLen;
+        if (mp_to_unsigned_bin(&dh->q, q) != MP_OKAY)
+            ret = MP_TO_E;
+    }
+
+    /* export g */
+    if (ret == 0) {
+        if (*gSz < gLen) {
+            WOLFSSL_MSG("Output buffer for DH g parameter too small, "
+                        "required size placed into gSz");
+            *gSz = gLen;
+            ret = BUFFER_E;
+        }
+    }
+
+    if (ret == 0) {
+        *gSz = gLen;
+        if (mp_to_unsigned_bin(&dh->g, g) != MP_OKAY)
+            ret = MP_TO_E;
+    }
+
+    return ret;
+}
+
+#endif /* WOLFSSL_KEY_GEN */
+
+#endif /* NO_DH */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/dsa.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/dsa.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/dsa.c	(revision 453)
@@ -0,0 +1,920 @@
+/* dsa.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifndef NO_DSA
+
+#include <wolfssl/wolfcrypt/random.h>
+#include <wolfssl/wolfcrypt/integer.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#include <wolfssl/wolfcrypt/logging.h>
+#include <wolfssl/wolfcrypt/sha.h>
+#include <wolfssl/wolfcrypt/dsa.h>
+
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+int wc_InitDsaKey(DsaKey* key)
+{
+    if (key == NULL)
+        return BAD_FUNC_ARG;
+
+    key->type = -1;  /* haven't decided yet */
+    key->heap = NULL;
+
+    return mp_init_multi(
+        /* public  alloc parts */
+        &key->p,
+        &key->q,
+        &key->g,
+        &key->y,
+
+        /* private alloc parts */
+        &key->x,
+        NULL
+    );
+}
+
+
+int wc_InitDsaKey_h(DsaKey* key, void* h)
+{
+    int ret = wc_InitDsaKey(key);
+    if (ret == 0)
+        key->heap = h;
+
+    return ret;
+}
+
+
+void wc_FreeDsaKey(DsaKey* key)
+{
+    if (key == NULL)
+        return;
+
+    if (key->type == DSA_PRIVATE)
+        mp_forcezero(&key->x);
+
+    mp_clear(&key->x);
+    mp_clear(&key->y);
+    mp_clear(&key->g);
+    mp_clear(&key->q);
+    mp_clear(&key->p);
+}
+
+
+/* validate that (L,N) match allowed sizes from FIPS 186-4, Section 4.2.
+ * modLen - represents L, the size of p (prime modulus) in bits
+ * divLen - represents N, the size of q (prime divisor) in bits
+ * return 0 on success, -1 on error */
+static int CheckDsaLN(int modLen, int divLen)
+{
+    int ret = -1;
+
+    switch (modLen) {
+        case 1024:
+            if (divLen == 160)
+                ret = 0;
+            break;
+        case 2048:
+            if (divLen == 224 || divLen == 256)
+                ret = 0;
+            break;
+        case 3072:
+            if (divLen == 256)
+                ret = 0;
+            break;
+        default:
+            break;
+    }
+
+    return ret;
+}
+
+
+#ifdef WOLFSSL_KEY_GEN
+
+/* Create DSA key pair (&dsa->x, &dsa->y)
+ *
+ * Based on NIST FIPS 186-4,
+ * "B.1.1 Key Pair Generation Using Extra Random Bits"
+ *
+ * rng - pointer to initialized WC_RNG structure
+ * dsa - pointer to initialized DsaKey structure, will hold generated key
+ *
+ * return 0 on success, negative on error */
+int wc_MakeDsaKey(WC_RNG *rng, DsaKey *dsa)
+{
+    byte* cBuf;
+    int qSz, pSz, cSz, err;
+    mp_int tmpQ;
+
+    if (rng == NULL || dsa == NULL)
+        return BAD_FUNC_ARG;
+
+    qSz = mp_unsigned_bin_size(&dsa->q);
+    pSz = mp_unsigned_bin_size(&dsa->p);
+
+    /* verify (L,N) pair bit lengths */
+    if (CheckDsaLN(pSz * WOLFSSL_BIT_SIZE, qSz * WOLFSSL_BIT_SIZE) != 0)
+        return BAD_FUNC_ARG;
+
+    /* generate extra 64 bits so that bias from mod function is negligible */
+    cSz = qSz + (64 / WOLFSSL_BIT_SIZE);
+    cBuf = (byte*)XMALLOC(cSz, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (cBuf == NULL) {
+        return MEMORY_E;
+    }
+
+    if ((err = mp_init_multi(&dsa->x, &dsa->y, &tmpQ, NULL, NULL, NULL))
+                   != MP_OKAY) {
+        XFREE(cBuf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return err;
+    }
+
+    do {
+        /* generate N+64 bits (c) from RBG into &dsa->x, making sure positive.
+         * Hash_DRBG uses SHA-256 which matches maximum
+         * requested_security_strength of (L,N) */
+        err = wc_RNG_GenerateBlock(rng, cBuf, cSz);
+        if (err != MP_OKAY) {
+            mp_clear(&dsa->x);
+            mp_clear(&dsa->y);
+            mp_clear(&tmpQ);
+            XFREE(cBuf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            return err;
+        }
+
+        err = mp_read_unsigned_bin(&dsa->x, cBuf, cSz);
+        if (err != MP_OKAY) {
+            mp_clear(&dsa->x);
+            mp_clear(&dsa->y);
+            mp_clear(&tmpQ);
+            XFREE(cBuf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            return err;
+        }
+    } while (mp_cmp_d(&dsa->x, 1) != MP_GT);
+
+    XFREE(cBuf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+    /* tmpQ = q - 1 */
+    if (err == MP_OKAY)
+        err = mp_copy(&dsa->q, &tmpQ);
+
+    if (err == MP_OKAY)
+        err = mp_sub_d(&tmpQ, 1, &tmpQ);
+
+    /* x = c mod (q-1), &dsa->x holds c */
+    if (err == MP_OKAY)
+        err = mp_mod(&dsa->x, &tmpQ, &dsa->x);
+
+    /* x = c mod (q-1) + 1 */
+    if (err == MP_OKAY)
+        err = mp_add_d(&dsa->x, 1, &dsa->x);
+
+    /* public key : y = g^x mod p */
+    if (err == MP_OKAY)
+        err = mp_exptmod_ex(&dsa->g, &dsa->x, dsa->q.used, &dsa->p, &dsa->y);
+
+    if (err == MP_OKAY)
+        dsa->type = DSA_PRIVATE;
+
+    if (err != MP_OKAY) {
+        mp_clear(&dsa->x);
+        mp_clear(&dsa->y);
+    }
+    mp_clear(&tmpQ);
+
+    return err;
+}
+
+
+/* modulus_size in bits */
+int wc_MakeDsaParameters(WC_RNG *rng, int modulus_size, DsaKey *dsa)
+{
+    mp_int  tmp, tmp2;
+    int     err, msize, qsize,
+            loop_check_prime = 0,
+            check_prime = MP_NO;
+    unsigned char   *buf;
+
+    if (rng == NULL || dsa == NULL)
+        return BAD_FUNC_ARG;
+
+    /* set group size in bytes from modulus size
+     * FIPS 186-4 defines valid values (1024, 160) (2048, 256) (3072, 256)
+     */
+    switch (modulus_size) {
+        case 1024:
+            qsize = 20;
+            break;
+        case 2048:
+        case 3072:
+            qsize = 32;
+            break;
+        default:
+            return BAD_FUNC_ARG;
+    }
+
+    /* modulus size in bytes */
+    msize = modulus_size / WOLFSSL_BIT_SIZE;
+
+    /* allocate ram */
+    buf = (unsigned char *)XMALLOC(msize - qsize,
+                                   dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (buf == NULL) {
+        return MEMORY_E;
+    }
+
+    /* make a random string that will be multiplied against q */
+    err = wc_RNG_GenerateBlock(rng, buf, msize - qsize);
+    if (err != MP_OKAY) {
+        XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return err;
+    }
+
+    /* force magnitude */
+    buf[0] |= 0xC0;
+
+    /* force even */
+    buf[msize - qsize - 1] &= ~1;
+
+    if (mp_init_multi(&tmp2, &dsa->p, &dsa->q, 0, 0, 0) != MP_OKAY) {
+        mp_clear(&dsa->q);
+        XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return MP_INIT_E;
+    }
+
+    err = mp_read_unsigned_bin(&tmp2, buf, msize - qsize);
+    if (err != MP_OKAY) {
+        mp_clear(&dsa->q);
+        mp_clear(&dsa->p);
+        mp_clear(&tmp2);
+        XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return err;
+    }
+    XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+    /* make our prime q */
+    err = mp_rand_prime(&dsa->q, qsize, rng, NULL);
+    if (err != MP_OKAY) {
+        mp_clear(&dsa->q);
+        mp_clear(&dsa->p);
+        mp_clear(&tmp2);
+        return err;
+    }
+
+    /* p = random * q */
+    err = mp_mul(&dsa->q, &tmp2, &dsa->p);
+    if (err != MP_OKAY) {
+        mp_clear(&dsa->q);
+        mp_clear(&dsa->p);
+        mp_clear(&tmp2);
+        return err;
+    }
+
+    /* p = random * q + 1, so q is a prime divisor of p-1 */
+    err = mp_add_d(&dsa->p, 1, &dsa->p);
+    if (err != MP_OKAY) {
+        mp_clear(&dsa->q);
+        mp_clear(&dsa->p);
+        mp_clear(&tmp2);
+        return err;
+    }
+
+    if (mp_init(&tmp) != MP_OKAY) {
+        mp_clear(&dsa->q);
+        mp_clear(&dsa->p);
+        mp_clear(&tmp2);
+        return MP_INIT_E;
+    }
+
+    /* tmp = 2q  */
+    err = mp_add(&dsa->q, &dsa->q, &tmp);
+    if (err != MP_OKAY) {
+        mp_clear(&dsa->q);
+        mp_clear(&dsa->p);
+        mp_clear(&tmp);
+        mp_clear(&tmp2);
+        return err;
+    }
+
+    /* loop until p is prime */
+    while (check_prime == MP_NO) {
+        err = mp_prime_is_prime_ex(&dsa->p, 8, &check_prime, rng);
+        if (err != MP_OKAY) {
+            mp_clear(&dsa->q);
+            mp_clear(&dsa->p);
+            mp_clear(&tmp);
+            mp_clear(&tmp2);
+            return err;
+        }
+
+        if (check_prime != MP_YES) {
+            /* p += 2q */
+            err = mp_add(&tmp, &dsa->p, &dsa->p);
+            if (err != MP_OKAY) {
+                mp_clear(&dsa->q);
+                mp_clear(&dsa->p);
+                mp_clear(&tmp);
+                mp_clear(&tmp2);
+                return err;
+            }
+
+            loop_check_prime++;
+        }
+    }
+
+    /* tmp2 += (2*loop_check_prime)
+     * to have p = (q * tmp2) + 1 prime
+     */
+    if (loop_check_prime) {
+        err = mp_add_d(&tmp2, 2*loop_check_prime, &tmp2);
+        if (err != MP_OKAY) {
+            mp_clear(&dsa->q);
+            mp_clear(&dsa->p);
+            mp_clear(&tmp);
+            mp_clear(&tmp2);
+            return err;
+        }
+    }
+
+    if (mp_init(&dsa->g) != MP_OKAY) {
+        mp_clear(&dsa->q);
+        mp_clear(&dsa->p);
+        mp_clear(&tmp);
+        mp_clear(&tmp2);
+        return MP_INIT_E;
+    }
+
+    /* find a value g for which g^tmp2 != 1 */
+    if (mp_set(&dsa->g, 1) != MP_OKAY) {
+        mp_clear(&dsa->q);
+        mp_clear(&dsa->p);
+        mp_clear(&tmp);
+        mp_clear(&tmp2);
+        return MP_INIT_E;
+    }
+
+    do {
+        err = mp_add_d(&dsa->g, 1, &dsa->g);
+        if (err != MP_OKAY) {
+            mp_clear(&dsa->q);
+            mp_clear(&dsa->p);
+            mp_clear(&dsa->g);
+            mp_clear(&tmp);
+            mp_clear(&tmp2);
+            return err;
+        }
+
+        err = mp_exptmod(&dsa->g, &tmp2, &dsa->p, &tmp);
+        if (err != MP_OKAY) {
+            mp_clear(&dsa->q);
+            mp_clear(&dsa->p);
+            mp_clear(&dsa->g);
+            mp_clear(&tmp);
+            mp_clear(&tmp2);
+            return err;
+        }
+
+    } while (mp_cmp_d(&tmp, 1) == MP_EQ);
+
+    /* at this point tmp generates a group of order q mod p */
+    mp_exch(&tmp, &dsa->g);
+
+    mp_clear(&tmp);
+    mp_clear(&tmp2);
+
+    return MP_OKAY;
+}
+#endif /* WOLFSSL_KEY_GEN */
+
+
+static int _DsaImportParamsRaw(DsaKey* dsa, const char* p, const char* q,
+                          const char* g, int trusted, WC_RNG* rng)
+{
+    int err;
+    word32 pSz, qSz;
+
+    if (dsa == NULL || p == NULL || q == NULL || g == NULL)
+        return BAD_FUNC_ARG;
+
+    /* read p */
+    err = mp_read_radix(&dsa->p, p, MP_RADIX_HEX);
+    if (err == MP_OKAY && !trusted) {
+        int isPrime = 1;
+        if (rng == NULL)
+            err = mp_prime_is_prime(&dsa->p, 8, &isPrime);
+        else
+            err = mp_prime_is_prime_ex(&dsa->p, 8, &isPrime, rng);
+
+        if (err == MP_OKAY) {
+            if (!isPrime)
+                err = DH_CHECK_PUB_E;
+        }
+    }
+
+    /* read q */
+    if (err == MP_OKAY)
+        err = mp_read_radix(&dsa->q, q, MP_RADIX_HEX);
+
+    /* read g */
+    if (err == MP_OKAY)
+        err = mp_read_radix(&dsa->g, g, MP_RADIX_HEX);
+
+    /* verify (L,N) pair bit lengths */
+    pSz = mp_unsigned_bin_size(&dsa->p);
+    qSz = mp_unsigned_bin_size(&dsa->q);
+
+    if (CheckDsaLN(pSz * WOLFSSL_BIT_SIZE, qSz * WOLFSSL_BIT_SIZE) != 0) {
+        WOLFSSL_MSG("Invalid DSA p or q parameter size");
+        err = BAD_FUNC_ARG;
+    }
+
+    if (err != MP_OKAY) {
+        mp_clear(&dsa->p);
+        mp_clear(&dsa->q);
+        mp_clear(&dsa->g);
+    }
+
+    return err;
+}
+
+
+/* Import raw DSA parameters into DsaKey structure for use with wc_MakeDsaKey(),
+ * input parameters (p,q,g) should be represented as ASCII hex values.
+ *
+ * dsa  - pointer to initialized DsaKey structure
+ * p    - DSA (p) parameter, ASCII hex string
+ * pSz  - length of p
+ * q    - DSA (q) parameter, ASCII hex string
+ * qSz  - length of q
+ * g    - DSA (g) parameter, ASCII hex string
+ * gSz  - length of g
+ *
+ * returns 0 on success, negative upon failure
+ */
+int wc_DsaImportParamsRaw(DsaKey* dsa, const char* p, const char* q,
+                          const char* g)
+{
+    return _DsaImportParamsRaw(dsa, p, q, g, 1, NULL);
+}
+
+
+/* Import raw DSA parameters into DsaKey structure for use with wc_MakeDsaKey(),
+ * input parameters (p,q,g) should be represented as ASCII hex values. Check
+ * that the p value is probably prime.
+ *
+ * dsa  - pointer to initialized DsaKey structure
+ * p    - DSA (p) parameter, ASCII hex string
+ * pSz  - length of p
+ * q    - DSA (q) parameter, ASCII hex string
+ * qSz  - length of q
+ * g    - DSA (g) parameter, ASCII hex string
+ * gSz  - length of g
+ * trusted - trust that p is OK
+ * rng  - random number generator for the prime test
+ *
+ * returns 0 on success, negative upon failure
+ */
+int wc_DsaImportParamsRawCheck(DsaKey* dsa, const char* p, const char* q,
+                          const char* g, int trusted, WC_RNG* rng)
+{
+    return _DsaImportParamsRaw(dsa, p, q, g, trusted, rng);
+}
+
+
+/* Export raw DSA parameters from DsaKey structure
+ *
+ * dsa  - pointer to initialized DsaKey structure
+ * p    - output location for DSA (p) parameter
+ * pSz  - [IN/OUT] size of output buffer for p, size of p
+ * q    - output location for DSA (q) parameter
+ * qSz  - [IN/OUT] size of output buffer for q, size of q
+ * g    - output location for DSA (g) parameter
+ * gSz  - [IN/OUT] size of output buffer for g, size of g
+ *
+ * If p, q, and g pointers are all passed in as NULL, the function
+ * will set pSz, qSz, and gSz to the required output buffer sizes for p,
+ * q, and g. In this case, the function will return LENGTH_ONLY_E.
+ *
+ * returns 0 on success, negative upon failure
+ */
+int wc_DsaExportParamsRaw(DsaKey* dsa, byte* p, word32* pSz,
+                          byte* q, word32* qSz, byte* g, word32* gSz)
+{
+    int err;
+    word32 pLen, qLen, gLen;
+
+    if (dsa == NULL || pSz == NULL || qSz == NULL || gSz == NULL)
+        return BAD_FUNC_ARG;
+
+    /* get required output buffer sizes */
+    pLen = mp_unsigned_bin_size(&dsa->p);
+    qLen = mp_unsigned_bin_size(&dsa->q);
+    gLen = mp_unsigned_bin_size(&dsa->g);
+
+    /* return buffer sizes and LENGTH_ONLY_E if buffers are NULL */
+    if (p == NULL && q == NULL && g == NULL) {
+        *pSz = pLen;
+        *qSz = qLen;
+        *gSz = gLen;
+        return LENGTH_ONLY_E;
+    }
+
+    if (p == NULL || q == NULL || g == NULL)
+        return BAD_FUNC_ARG;
+
+    /* export p */
+    if (*pSz < pLen) {
+        WOLFSSL_MSG("Output buffer for DSA p parameter too small, "
+                    "required size placed into pSz");
+        *pSz = pLen;
+        return BUFFER_E;
+    }
+    *pSz = pLen;
+    err = mp_to_unsigned_bin(&dsa->p, p);
+
+    /* export q */
+    if (err == MP_OKAY) {
+        if (*qSz < qLen) {
+            WOLFSSL_MSG("Output buffer for DSA q parameter too small, "
+                        "required size placed into qSz");
+            *qSz = qLen;
+            return BUFFER_E;
+        }
+        *qSz = qLen;
+        err = mp_to_unsigned_bin(&dsa->q, q);
+    }
+
+    /* export g */
+    if (err == MP_OKAY) {
+        if (*gSz < gLen) {
+            WOLFSSL_MSG("Output buffer for DSA g parameter too small, "
+                        "required size placed into gSz");
+            *gSz = gLen;
+            return BUFFER_E;
+        }
+        *gSz = gLen;
+        err = mp_to_unsigned_bin(&dsa->g, g);
+    }
+
+    return err;
+}
+
+
+/* Export raw DSA key (x, y) from DsaKey structure
+ *
+ * dsa  - pointer to initialized DsaKey structure
+ * x    - output location for private key
+ * xSz  - [IN/OUT] size of output buffer for x, size of x
+ * y    - output location for public key
+ * ySz  - [IN/OUT] size of output buffer for y, size of y
+ *
+ * If x and y pointers are all passed in as NULL, the function
+ * will set xSz and ySz to the required output buffer sizes for x
+ * and y. In this case, the function will return LENGTH_ONLY_E.
+ *
+ * returns 0 on success, negative upon failure
+ */
+int wc_DsaExportKeyRaw(DsaKey* dsa, byte* x, word32* xSz, byte* y, word32* ySz)
+{
+    int err;
+    word32 xLen, yLen;
+
+    if (dsa == NULL || xSz == NULL || ySz == NULL)
+        return BAD_FUNC_ARG;
+
+    /* get required output buffer sizes */
+    xLen = mp_unsigned_bin_size(&dsa->x);
+    yLen = mp_unsigned_bin_size(&dsa->y);
+
+    /* return buffer sizes and LENGTH_ONLY_E if buffers are NULL */
+    if (x == NULL && y == NULL) {
+        *xSz = xLen;
+        *ySz = yLen;
+        return LENGTH_ONLY_E;
+    }
+
+    if (x == NULL || y == NULL)
+        return BAD_FUNC_ARG;
+
+    /* export x */
+    if (*xSz < xLen) {
+        WOLFSSL_MSG("Output buffer for DSA private key (x) too small, "
+                    "required size placed into xSz");
+        *xSz = xLen;
+        return BUFFER_E;
+    }
+    *xSz = xLen;
+    err = mp_to_unsigned_bin(&dsa->x, x);
+
+    /* export y */
+    if (err == MP_OKAY) {
+        if (*ySz < yLen) {
+            WOLFSSL_MSG("Output buffer to DSA public key (y) too small, "
+                        "required size placed into ySz");
+            *ySz = yLen;
+            return BUFFER_E;
+        }
+        *ySz = yLen;
+        err = mp_to_unsigned_bin(&dsa->y, y);
+    }
+
+    return err;
+}
+
+
+int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng)
+{
+    mp_int  k, kInv, r, s, H;
+#ifndef WOLFSSL_MP_INVMOD_CONSTANT_TIME
+    mp_int  b;
+#endif
+    mp_int* qMinus1;
+    int     ret = 0, sz;
+    byte    buffer[DSA_HALF_SIZE];
+    byte*   tmp;  /* initial output pointer */
+
+    if (digest == NULL || out == NULL || key == NULL || rng == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    tmp = out;
+
+    sz = min((int)sizeof(buffer), mp_unsigned_bin_size(&key->q));
+
+#ifdef WOLFSSL_MP_INVMOD_CONSTANT_TIME
+    if (mp_init_multi(&k, &kInv, &r, &s, &H, 0) != MP_OKAY)
+#else
+    if (mp_init_multi(&k, &kInv, &r, &s, &H, &b) != MP_OKAY)
+#endif
+    {
+        return MP_INIT_E;
+    }
+    qMinus1 = &kInv;
+
+    /* NIST FIPS 186-4: B.2.2
+     * Per-Message Secret Number Generation by Testing Candidates
+     * Generate k in range [1, q-1].
+     *   Check that k is less than q-1: range [0, q-2].
+     *   Add 1 to k: range [1, q-1].
+     */
+    if (mp_sub_d(&key->q, 1, qMinus1))
+        ret = MP_SUB_E;
+
+    if (ret == 0) {
+        do {
+            /* Step 4: generate k */
+            ret = wc_RNG_GenerateBlock(rng, buffer, sz);
+
+            /* Step 5 */
+            if (ret == 0 && mp_read_unsigned_bin(&k, buffer, sz) != MP_OKAY)
+                ret = MP_READ_E;
+
+            /* k is a random numnber and it should be less than q-1
+             * if k greater than repeat
+             */
+        /* Step 6 */
+        } while (ret == 0 && mp_cmp(&k, qMinus1) != MP_LT);
+    }
+    /* Step 7 */
+    if (ret == 0 && mp_add_d(&k, 1, &k) != MP_OKAY)
+        ret = MP_MOD_E;
+
+#ifdef WOLFSSL_MP_INVMOD_CONSTANT_TIME
+    /* inverse k mod q */
+    if (ret == 0 && mp_invmod(&k, &key->q, &kInv) != MP_OKAY)
+        ret = MP_INVMOD_E;
+
+    /* generate r, r = (g exp k mod p) mod q */
+    if (ret == 0 && mp_exptmod_ex(&key->g, &k, key->q.used, &key->p,
+                                                               &r) != MP_OKAY) {
+        ret = MP_EXPTMOD_E;
+    }
+
+    if (ret == 0 && mp_mod(&r, &key->q, &r) != MP_OKAY)
+        ret = MP_MOD_E;
+
+    /* generate H from sha digest */
+    if (ret == 0 && mp_read_unsigned_bin(&H, digest,WC_SHA_DIGEST_SIZE) != MP_OKAY)
+        ret = MP_READ_E;
+
+    /* generate s, s = (kInv * (H + x*r)) % q */
+    if (ret == 0 && mp_mul(&key->x, &r, &s) != MP_OKAY)
+        ret = MP_MUL_E;
+
+    if (ret == 0 && mp_add(&s, &H, &s) != MP_OKAY)
+        ret = MP_ADD_E;
+
+    if (ret == 0 && mp_mulmod(&s, &kInv, &key->q, &s) != MP_OKAY)
+        ret = MP_MULMOD_E;
+#else
+    /* Blinding value
+     * Generate b in range [1, q-1].
+     */
+    if (ret == 0) {
+        do {
+            ret = wc_RNG_GenerateBlock(rng, buffer, sz);
+            if (ret == 0 && mp_read_unsigned_bin(&b, buffer, sz) != MP_OKAY)
+                ret = MP_READ_E;
+        } while (ret == 0 && mp_cmp(&b, qMinus1) != MP_LT);
+    }
+    if (ret == 0 && mp_add_d(&b, 1, &b) != MP_OKAY)
+        ret = MP_MOD_E;
+
+    /* set H from sha digest */
+    if (ret == 0 && mp_read_unsigned_bin(&H, digest,
+                                               WC_SHA_DIGEST_SIZE) != MP_OKAY) {
+        ret = MP_READ_E;
+    }
+
+    /* generate r, r = (g exp k mod p) mod q */
+    if (ret == 0 && mp_exptmod_ex(&key->g, &k, key->q.used, &key->p,
+                                                               &r) != MP_OKAY) {
+        ret = MP_EXPTMOD_E;
+    }
+
+    /* calculate s = (H + xr)/k
+                   = b.(H/k.b + x.r/k.b) */
+
+    /* k = k.b */
+    if (ret == 0 && mp_mulmod(&k, &b, &key->q, &k) != MP_OKAY)
+        ret = MP_MULMOD_E;
+
+    /* kInv = 1/k.b mod q */
+    if (ret == 0 && mp_invmod(&k, &key->q, &kInv) != MP_OKAY)
+        ret = MP_INVMOD_E;
+
+    if (ret == 0 && mp_mod(&r, &key->q, &r) != MP_OKAY)
+        ret = MP_MOD_E;
+
+    /* s = x.r */
+    if (ret == 0 && mp_mul(&key->x, &r, &s) != MP_OKAY)
+        ret = MP_MUL_E;
+
+    /* s = x.r/k.b */
+    if (ret == 0 && mp_mulmod(&s, &kInv, &key->q, &s) != MP_OKAY)
+        ret = MP_MULMOD_E;
+
+    /* H = H/k.b */
+    if (ret == 0 && mp_mulmod(&H, &kInv, &key->q, &H) != MP_OKAY)
+        ret = MP_MULMOD_E;
+
+    /* s = H/k.b + x.r/k.b
+         = (H + x.r)/k.b */
+    if (ret == 0 && mp_add(&s, &H, &s) != MP_OKAY)
+        ret = MP_ADD_E;
+
+    /* s = b.(e + x.r)/k.b
+         = (e + x.r)/k */
+    if (ret == 0 && mp_mulmod(&s, &b, &key->q, &s) != MP_OKAY)
+        ret = MP_MULMOD_E;
+
+    /* s = (e + x.r)/k */
+    if (ret == 0 && mp_mod(&s, &key->q, &s) != MP_OKAY)
+        ret = MP_MOD_E;
+#endif
+
+    /* detect zero r or s */
+    if (ret == 0 && (mp_iszero(&r) == MP_YES || mp_iszero(&s) == MP_YES))
+        ret = MP_ZERO_E;
+
+    /* write out */
+    if (ret == 0)  {
+        int rSz = mp_unsigned_bin_size(&r);
+        int sSz = mp_unsigned_bin_size(&s);
+
+        while (rSz++ < DSA_HALF_SIZE) {
+            *out++ = 0x00;  /* pad front with zeros */
+        }
+
+        if (mp_to_unsigned_bin(&r, out) != MP_OKAY)
+            ret = MP_TO_E;
+        else {
+            out = tmp + DSA_HALF_SIZE;  /* advance to s in output */
+            while (sSz++ < DSA_HALF_SIZE) {
+                *out++ = 0x00;  /* pad front with zeros */
+            }
+            ret = mp_to_unsigned_bin(&s, out);
+        }
+    }
+
+    ForceZero(buffer, sz);
+    mp_forcezero(&kInv);
+    mp_forcezero(&k);
+#ifndef WOLFSSL_MP_INVMOD_CONSTANT_TIME
+    mp_forcezero(&b);
+
+    mp_clear(&b);
+#endif
+    mp_clear(&H);
+    mp_clear(&s);
+    mp_clear(&r);
+    mp_clear(&kInv);
+    mp_clear(&k);
+
+    return ret;
+}
+
+
+int wc_DsaVerify(const byte* digest, const byte* sig, DsaKey* key, int* answer)
+{
+    mp_int w, u1, u2, v, r, s;
+    int    ret = 0;
+
+    if (digest == NULL || sig == NULL || key == NULL || answer == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (mp_init_multi(&w, &u1, &u2, &v, &r, &s) != MP_OKAY)
+        return MP_INIT_E;
+
+    /* set r and s from signature */
+    if (mp_read_unsigned_bin(&r, sig, DSA_HALF_SIZE) != MP_OKAY ||
+        mp_read_unsigned_bin(&s, sig + DSA_HALF_SIZE, DSA_HALF_SIZE) != MP_OKAY)
+        ret = MP_READ_E;
+
+    /* sanity checks */
+    if (ret == 0) {
+        if (mp_iszero(&r) == MP_YES || mp_iszero(&s) == MP_YES ||
+                mp_cmp(&r, &key->q) != MP_LT || mp_cmp(&s, &key->q) != MP_LT) {
+            ret = MP_ZERO_E;
+        }
+    }
+
+    /* put H into u1 from sha digest */
+    if (ret == 0 && mp_read_unsigned_bin(&u1,digest,WC_SHA_DIGEST_SIZE) != MP_OKAY)
+        ret = MP_READ_E;
+
+    /* w = s invmod q */
+    if (ret == 0 && mp_invmod(&s, &key->q, &w) != MP_OKAY)
+        ret = MP_INVMOD_E;
+
+    /* u1 = (H * w) % q */
+    if (ret == 0 && mp_mulmod(&u1, &w, &key->q, &u1) != MP_OKAY)
+        ret = MP_MULMOD_E;
+
+    /* u2 = (r * w) % q */
+    if (ret == 0 && mp_mulmod(&r, &w, &key->q, &u2) != MP_OKAY)
+        ret = MP_MULMOD_E;
+
+    /* verify v = ((g^u1 * y^u2) mod p) mod q */
+    if (ret == 0 && mp_exptmod(&key->g, &u1, &key->p, &u1) != MP_OKAY)
+        ret = MP_EXPTMOD_E;
+
+    if (ret == 0 && mp_exptmod(&key->y, &u2, &key->p, &u2) != MP_OKAY)
+        ret = MP_EXPTMOD_E;
+
+    if (ret == 0 && mp_mulmod(&u1, &u2, &key->p, &v) != MP_OKAY)
+        ret = MP_MULMOD_E;
+
+    if (ret == 0 && mp_mod(&v, &key->q, &v) != MP_OKAY)
+        ret = MP_MULMOD_E;
+
+    /* do they match */
+    if (ret == 0 && mp_cmp(&r, &v) == MP_EQ)
+        *answer = 1;
+    else
+        *answer = 0;
+
+    mp_clear(&s);
+    mp_clear(&r);
+    mp_clear(&u1);
+    mp_clear(&u2);
+    mp_clear(&w);
+    mp_clear(&v);
+
+    return ret;
+}
+
+
+#endif /* NO_DSA */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/ecc.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/ecc.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/ecc.c	(revision 453)
@@ -0,0 +1,10761 @@
+/* ecc.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+/* in case user set HAVE_ECC there */
+#include <wolfssl/wolfcrypt/settings.h>
+
+/* public ASN interface */
+#include <wolfssl/wolfcrypt/asn_public.h>
+
+/*
+Possible ECC enable options:
+ * HAVE_ECC:            Overall control of ECC                  default: on
+ * HAVE_ECC_ENCRYPT:    ECC encrypt/decrypt w/AES and HKDF      default: off
+ * HAVE_ECC_SIGN:       ECC sign                                default: on
+ * HAVE_ECC_VERIFY:     ECC verify                              default: on
+ * HAVE_ECC_DHE:        ECC build shared secret                 default: on
+ * HAVE_ECC_CDH:        ECC cofactor DH shared secret           default: off
+ * HAVE_ECC_KEY_IMPORT: ECC Key import                          default: on
+ * HAVE_ECC_KEY_EXPORT: ECC Key export                          default: on
+ * ECC_SHAMIR:          Enables Shamir calc method              default: on
+ * HAVE_COMP_KEY:       Enables compressed key                  default: off
+ * WOLFSSL_VALIDATE_ECC_IMPORT: Validate ECC key on import      default: off
+ * WOLFSSL_VALIDATE_ECC_KEYGEN: Validate ECC key gen            default: off
+ * WOLFSSL_CUSTOM_CURVES: Allow non-standard curves.            default: off
+ *                        Includes the curve "a" variable in calculation
+ * ECC_DUMP_OID:        Enables dump of OID encoding and sum    default: off
+ * ECC_CACHE_CURVE:     Enables cache of curve info to improve perofrmance
+                                                                default: off
+ * FP_ECC:              ECC Fixed Point Cache                   default: off
+ * USE_ECC_B_PARAM:     Enable ECC curve B param                default: off
+                         (on for HAVE_COMP_KEY)
+ * WOLFSSL_ECC_CURVE_STATIC:                                    default off (on for windows)
+                        For the ECC curve paramaters `ecc_set_type` use fixed
+                        array for hex string
+ */
+
+/*
+ECC Curve Types:
+ * NO_ECC_SECP          Disables SECP curves                    default: off (not defined)
+ * HAVE_ECC_SECPR2      Enables SECP R2 curves                  default: off
+ * HAVE_ECC_SECPR3      Enables SECP R3 curves                  default: off
+ * HAVE_ECC_BRAINPOOL   Enables Brainpool curves                default: off
+ * HAVE_ECC_KOBLITZ     Enables Koblitz curves                  default: off
+ */
+
+/*
+ECC Curve Sizes:
+ * ECC_USER_CURVES: Allows custom combination of key sizes below
+ * HAVE_ALL_CURVES: Enable all key sizes (on unless ECC_USER_CURVES is defined)
+ * HAVE_ECC112: 112 bit key
+ * HAVE_ECC128: 128 bit key
+ * HAVE_ECC160: 160 bit key
+ * HAVE_ECC192: 192 bit key
+ * HAVE_ECC224: 224 bit key
+ * HAVE_ECC239: 239 bit key
+ * NO_ECC256: Disables 256 bit key (on by default)
+ * HAVE_ECC320: 320 bit key
+ * HAVE_ECC384: 384 bit key
+ * HAVE_ECC512: 512 bit key
+ * HAVE_ECC521: 521 bit key
+ */
+
+
+#ifdef HAVE_ECC
+
+/* Make sure custom curves is enabled for Brainpool or Koblitz curve types */
+#if (defined(HAVE_ECC_BRAINPOOL) || defined(HAVE_ECC_KOBLITZ)) &&\
+    !defined(WOLFSSL_CUSTOM_CURVES)
+    #error Brainpool and Koblitz curves requires WOLFSSL_CUSTOM_CURVES
+#endif
+
+#if defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
+    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
+    #define FIPS_NO_WRAPPERS
+
+	#ifdef USE_WINDOWS_API
+		#pragma code_seg(".fipsA$f")
+		#pragma const_seg(".fipsB$f")
+	#endif
+#endif
+
+#include <wolfssl/wolfcrypt/ecc.h>
+#include <wolfssl/wolfcrypt/asn.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#include <wolfssl/wolfcrypt/logging.h>
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifdef WOLFSSL_HAVE_SP_ECC
+#include <wolfssl/wolfcrypt/sp.h>
+#endif
+
+#ifdef HAVE_ECC_ENCRYPT
+    #include <wolfssl/wolfcrypt/hmac.h>
+    #include <wolfssl/wolfcrypt/aes.h>
+#endif
+
+#ifdef HAVE_X963_KDF
+    #include <wolfssl/wolfcrypt/hash.h>
+#endif
+
+#ifdef WOLF_CRYPTO_CB
+    #include <wolfssl/wolfcrypt/cryptocb.h>
+#endif
+
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+#if defined(FREESCALE_LTC_ECC)
+    #include <wolfssl/wolfcrypt/port/nxp/ksdk_port.h>
+#endif
+
+#if defined(WOLFSSL_STM32_PKA)
+    #include <wolfssl/wolfcrypt/port/st/stm32.h>
+#endif
+
+#ifdef WOLFSSL_SP_MATH
+    #define GEN_MEM_ERR MP_MEM
+#elif defined(USE_FAST_MATH)
+    #define GEN_MEM_ERR FP_MEM
+#else
+    #define GEN_MEM_ERR MP_MEM
+#endif
+
+
+/* internal ECC states */
+enum {
+    ECC_STATE_NONE = 0,
+
+    ECC_STATE_SHARED_SEC_GEN,
+    ECC_STATE_SHARED_SEC_RES,
+
+    ECC_STATE_SIGN_DO,
+    ECC_STATE_SIGN_ENCODE,
+
+    ECC_STATE_VERIFY_DECODE,
+    ECC_STATE_VERIFY_DO,
+    ECC_STATE_VERIFY_RES,
+};
+
+
+/* map
+   ptmul -> mulmod
+*/
+
+/* 256-bit curve on by default whether user curves or not */
+#if defined(HAVE_ECC112) || defined(HAVE_ALL_CURVES)
+    #define ECC112
+#endif
+#if defined(HAVE_ECC128) || defined(HAVE_ALL_CURVES)
+    #define ECC128
+#endif
+#if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES)
+    #define ECC160
+#endif
+#if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)
+    #define ECC192
+#endif
+#if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)
+    #define ECC224
+#endif
+#if defined(HAVE_ECC239) || defined(HAVE_ALL_CURVES)
+    #define ECC239
+#endif
+#if !defined(NO_ECC256)  || defined(HAVE_ALL_CURVES)
+    #define ECC256
+#endif
+#if defined(HAVE_ECC320) || defined(HAVE_ALL_CURVES)
+    #define ECC320
+#endif
+#if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
+    #define ECC384
+#endif
+#if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)
+    #define ECC512
+#endif
+#if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
+    #define ECC521
+#endif
+
+/* The encoded OID's for ECC curves */
+#ifdef ECC112
+    #ifndef NO_ECC_SECP
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_SECP112R1    {1,3,132,0,6}
+            #define CODED_SECP112R1_SZ 5
+        #else
+            #define CODED_SECP112R1    {0x2B,0x81,0x04,0x00,0x06}
+            #define CODED_SECP112R1_SZ 5
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_secp112r1[] = CODED_SECP112R1;
+        #else
+            #define ecc_oid_secp112r1 CODED_SECP112R1
+        #endif
+        #define ecc_oid_secp112r1_sz CODED_SECP112R1_SZ
+    #endif /* !NO_ECC_SECP */
+    #ifdef HAVE_ECC_SECPR2
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_SECP112R2    {1,3,132,0,7}
+            #define CODED_SECP112R2_SZ 5
+        #else
+            #define CODED_SECP112R2    {0x2B,0x81,0x04,0x00,0x07}
+            #define CODED_SECP112R2_SZ 5
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_secp112r2[] = CODED_SECP112R2;
+        #else
+            #define ecc_oid_secp112r2 CODED_SECP112R2
+        #endif
+        #define ecc_oid_secp112r2_sz CODED_SECP112R2_SZ
+    #endif /* HAVE_ECC_SECPR2 */
+#endif /* ECC112 */
+#ifdef ECC128
+    #ifndef NO_ECC_SECP
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_SECP128R1    {1,3,132,0,28}
+            #define CODED_SECP128R1_SZ 5
+        #else
+            #define CODED_SECP128R1    {0x2B,0x81,0x04,0x00,0x1C}
+            #define CODED_SECP128R1_SZ 5
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_secp128r1[] = CODED_SECP128R1;
+        #else
+            #define ecc_oid_secp128r1 CODED_SECP128R1
+        #endif
+        #define ecc_oid_secp128r1_sz CODED_SECP128R1_SZ
+    #endif /* !NO_ECC_SECP */
+    #ifdef HAVE_ECC_SECPR2
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_SECP128R2    {1,3,132,0,29}
+            #define CODED_SECP128R2_SZ 5
+        #else
+            #define CODED_SECP128R2    {0x2B,0x81,0x04,0x00,0x1D}
+            #define CODED_SECP128R2_SZ 5
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_secp128r2[] = CODED_SECP128R2;
+        #else
+            #define ecc_oid_secp128r2 CODED_SECP128R2
+        #endif
+        #define ecc_oid_secp128r2_sz CODED_SECP128R2_SZ
+    #endif /* HAVE_ECC_SECPR2 */
+#endif /* ECC128 */
+#ifdef ECC160
+    #ifndef NO_ECC_SECP
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_SECP160R1    {1,3,132,0,8}
+            #define CODED_SECP160R1_SZ 5
+        #else
+            #define CODED_SECP160R1    {0x2B,0x81,0x04,0x00,0x08}
+            #define CODED_SECP160R1_SZ 5
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_secp160r1[] = CODED_SECP160R1;
+        #else
+            #define ecc_oid_secp160r1 CODED_SECP160R1
+        #endif
+        #define ecc_oid_secp160r1_sz CODED_SECP160R1_SZ
+    #endif /* !NO_ECC_SECP */
+    #ifdef HAVE_ECC_SECPR2
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_SECP160R2    {1,3,132,0,30}
+            #define CODED_SECP160R2_SZ 5
+        #else
+            #define CODED_SECP160R2    {0x2B,0x81,0x04,0x00,0x1E}
+            #define CODED_SECP160R2_SZ 5
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_secp160r2[] = CODED_SECP160R2;
+        #else
+            #define ecc_oid_secp160r2 CODED_SECP160R2
+        #endif
+        #define ecc_oid_secp160r2_sz CODED_SECP160R2_SZ
+    #endif /* HAVE_ECC_SECPR2 */
+    #ifdef HAVE_ECC_KOBLITZ
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_SECP160K1    {1,3,132,0,9}
+            #define CODED_SECP160K1_SZ 5
+        #else
+            #define CODED_SECP160K1    {0x2B,0x81,0x04,0x00,0x09}
+            #define CODED_SECP160K1_SZ 5
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_secp160k1[] = CODED_SECP160K1;
+        #else
+            #define ecc_oid_secp160k1 CODED_SECP160K1
+        #endif
+        #define ecc_oid_secp160k1_sz CODED_SECP160K1_SZ
+    #endif /* HAVE_ECC_KOBLITZ */
+    #ifdef HAVE_ECC_BRAINPOOL
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_BRAINPOOLP160R1    {1,3,36,3,3,2,8,1,1,1}
+            #define CODED_BRAINPOOLP160R1_SZ 10
+        #else
+            #define CODED_BRAINPOOLP160R1    {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x01}
+            #define CODED_BRAINPOOLP160R1_SZ 9
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_brainpoolp160r1[] = CODED_BRAINPOOLP160R1;
+        #else
+            #define ecc_oid_brainpoolp160r1 CODED_BRAINPOOLP160R1
+        #endif
+        #define ecc_oid_brainpoolp160r1_sz CODED_BRAINPOOLP160R1_SZ
+    #endif /* HAVE_ECC_BRAINPOOL */
+#endif /* ECC160 */
+#ifdef ECC192
+    #ifndef NO_ECC_SECP
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_SECP192R1    {1,2,840,10045,3,1,1}
+            #define CODED_SECP192R1_SZ 7
+        #else
+            #define CODED_SECP192R1    {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x01}
+            #define CODED_SECP192R1_SZ 8
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_secp192r1[] = CODED_SECP192R1;
+        #else
+            #define ecc_oid_secp192r1 CODED_SECP192R1
+        #endif
+        #define ecc_oid_secp192r1_sz CODED_SECP192R1_SZ
+    #endif /* !NO_ECC_SECP */
+    #ifdef HAVE_ECC_SECPR2
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_PRIME192V2    {1,2,840,10045,3,1,2}
+            #define CODED_PRIME192V2_SZ 7
+        #else
+            #define CODED_PRIME192V2    {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x02}
+            #define CODED_PRIME192V2_SZ 8
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_prime192v2[] = CODED_PRIME192V2;
+        #else
+            #define ecc_oid_prime192v2 CODED_PRIME192V2
+        #endif
+        #define ecc_oid_prime192v2_sz CODED_PRIME192V2_SZ
+    #endif /* HAVE_ECC_SECPR2 */
+    #ifdef HAVE_ECC_SECPR3
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_PRIME192V3    {1,2,840,10045,3,1,3}
+            #define CODED_PRIME192V3_SZ 7
+        #else
+            #define CODED_PRIME192V3    {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x03}
+            #define CODED_PRIME192V3_SZ 8
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_prime192v3[] = CODED_PRIME192V3;
+        #else
+            #define ecc_oid_prime192v3 CODED_PRIME192V3
+        #endif
+        #define ecc_oid_prime192v3_sz CODED_PRIME192V3_SZ
+    #endif /* HAVE_ECC_SECPR3 */
+    #ifdef HAVE_ECC_KOBLITZ
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_SECP192K1    {1,3,132,0,31}
+            #define CODED_SECP192K1_SZ 5
+        #else
+            #define CODED_SECP192K1    {0x2B,0x81,0x04,0x00,0x1F}
+            #define CODED_SECP192K1_SZ 5
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_secp192k1[] = CODED_SECP192K1;
+        #else
+            #define ecc_oid_secp192k1 CODED_SECP192K1
+        #endif
+        #define ecc_oid_secp192k1_sz CODED_SECP192K1_SZ
+    #endif /* HAVE_ECC_KOBLITZ */
+    #ifdef HAVE_ECC_BRAINPOOL
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_BRAINPOOLP192R1    {1,3,36,3,3,2,8,1,1,3}
+            #define CODED_BRAINPOOLP192R1_SZ 10
+        #else
+            #define CODED_BRAINPOOLP192R1    {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x03}
+            #define CODED_BRAINPOOLP192R1_SZ 9
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_brainpoolp192r1[] = CODED_BRAINPOOLP192R1;
+        #else
+            #define ecc_oid_brainpoolp192r1 CODED_BRAINPOOLP192R1
+        #endif
+        #define ecc_oid_brainpoolp192r1_sz CODED_BRAINPOOLP192R1_SZ
+    #endif /* HAVE_ECC_BRAINPOOL */
+#endif /* ECC192 */
+#ifdef ECC224
+    #ifndef NO_ECC_SECP
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_SECP224R1    {1,3,132,0,33}
+            #define CODED_SECP224R1_SZ 5
+        #else
+            #define CODED_SECP224R1    {0x2B,0x81,0x04,0x00,0x21}
+            #define CODED_SECP224R1_SZ 5
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_secp224r1[] = CODED_SECP224R1;
+        #else
+            #define ecc_oid_secp224r1 CODED_SECP224R1
+        #endif
+        #define ecc_oid_secp224r1_sz CODED_SECP224R1_SZ
+    #endif /* !NO_ECC_SECP */
+    #ifdef HAVE_ECC_KOBLITZ
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_SECP224K1    {1,3,132,0,32}
+            #define CODED_SECP224K1_SZ 5
+        #else
+            #define CODED_SECP224K1    {0x2B,0x81,0x04,0x00,0x20}
+            #define CODED_SECP224K1_SZ 5
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_secp224k1[] = CODED_SECP224K1;
+        #else
+            #define ecc_oid_secp224k1 CODED_SECP224K1
+        #endif
+        #define ecc_oid_secp224k1_sz CODED_SECP224K1_SZ
+    #endif /* HAVE_ECC_KOBLITZ */
+    #ifdef HAVE_ECC_BRAINPOOL
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_BRAINPOOLP224R1    {1,3,36,3,3,2,8,1,1,5}
+            #define CODED_BRAINPOOLP224R1_SZ 10
+        #else
+            #define CODED_BRAINPOOLP224R1    {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x05}
+            #define CODED_BRAINPOOLP224R1_SZ 9
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_brainpoolp224r1[] = CODED_BRAINPOOLP224R1;
+        #else
+            #define ecc_oid_brainpoolp224r1 CODED_BRAINPOOLP224R1
+        #endif
+        #define ecc_oid_brainpoolp224r1_sz CODED_BRAINPOOLP224R1_SZ
+    #endif /* HAVE_ECC_BRAINPOOL */
+#endif /* ECC224 */
+#ifdef ECC239
+    #ifndef NO_ECC_SECP
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_PRIME239V1    {1,2,840,10045,3,1,4}
+            #define CODED_PRIME239V1_SZ 7
+        #else
+            #define CODED_PRIME239V1    {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x04}
+            #define CODED_PRIME239V1_SZ 8
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_prime239v1[] = CODED_PRIME239V1;
+        #else
+            #define ecc_oid_prime239v1 CODED_PRIME239V1
+        #endif
+        #define ecc_oid_prime239v1_sz CODED_PRIME239V1_SZ
+    #endif /* !NO_ECC_SECP */
+    #ifdef HAVE_ECC_SECPR2
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_PRIME239V2    {1,2,840,10045,3,1,5}
+            #define CODED_PRIME239V2_SZ 7
+        #else
+            #define CODED_PRIME239V2    {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x05}
+            #define CODED_PRIME239V2_SZ 8
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_prime239v2[] = CODED_PRIME239V2;
+        #else
+            #define ecc_oid_prime239v2 CODED_PRIME239V2
+        #endif
+        #define ecc_oid_prime239v2_sz CODED_PRIME239V2_SZ
+    #endif /* HAVE_ECC_SECPR2 */
+    #ifdef HAVE_ECC_SECPR3
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_PRIME239V3    {1,2,840,10045,3,1,6}
+            #define CODED_PRIME239V3_SZ 7
+        #else
+            #define CODED_PRIME239V3    {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x06}
+            #define CODED_PRIME239V3_SZ 8
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_prime239v3[] = CODED_PRIME239V3;
+        #else
+            #define ecc_oid_prime239v3 CODED_PRIME239V3
+        #endif
+        #define ecc_oid_prime239v3_sz CODED_PRIME239V3_SZ
+    #endif /* HAVE_ECC_SECPR3 */
+#endif /* ECC239 */
+#ifdef ECC256
+    #ifndef NO_ECC_SECP
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_SECP256R1    {1,2,840,10045,3,1,7}
+            #define CODED_SECP256R1_SZ 7
+        #else
+            #define CODED_SECP256R1    {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07}
+            #define CODED_SECP256R1_SZ 8
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_secp256r1[] = CODED_SECP256R1;
+        #else
+            #define ecc_oid_secp256r1 CODED_SECP256R1
+        #endif
+        #define ecc_oid_secp256r1_sz CODED_SECP256R1_SZ
+    #endif /* !NO_ECC_SECP */
+    #ifdef HAVE_ECC_KOBLITZ
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_SECP256K1    {1,3,132,0,10}
+            #define CODED_SECP256K1_SZ 5
+        #else
+            #define CODED_SECP256K1    {0x2B,0x81,0x04,0x00,0x0A}
+            #define CODED_SECP256K1_SZ 5
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_secp256k1[] = CODED_SECP256K1;
+        #else
+            #define ecc_oid_secp256k1 CODED_SECP256K1
+        #endif
+        #define ecc_oid_secp256k1_sz CODED_SECP256K1_SZ
+    #endif /* HAVE_ECC_KOBLITZ */
+    #ifdef HAVE_ECC_BRAINPOOL
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_BRAINPOOLP256R1    {1,3,36,3,3,2,8,1,1,7}
+            #define CODED_BRAINPOOLP256R1_SZ 10
+        #else
+            #define CODED_BRAINPOOLP256R1    {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x07}
+            #define CODED_BRAINPOOLP256R1_SZ 9
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_brainpoolp256r1[] = CODED_BRAINPOOLP256R1;
+        #else
+            #define ecc_oid_brainpoolp256r1 CODED_BRAINPOOLP256R1
+        #endif
+        #define ecc_oid_brainpoolp256r1_sz CODED_BRAINPOOLP256R1_SZ
+    #endif /* HAVE_ECC_BRAINPOOL */
+#endif /* ECC256 */
+#ifdef ECC320
+    #ifdef HAVE_ECC_BRAINPOOL
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_BRAINPOOLP320R1    {1,3,36,3,3,2,8,1,1,9}
+            #define CODED_BRAINPOOLP320R1_SZ 10
+        #else
+            #define CODED_BRAINPOOLP320R1    {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x09}
+            #define CODED_BRAINPOOLP320R1_SZ 9
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_brainpoolp320r1[] = CODED_BRAINPOOLP320R1;
+        #else
+            #define ecc_oid_brainpoolp320r1 CODED_BRAINPOOLP320R1
+        #endif
+        #define ecc_oid_brainpoolp320r1_sz CODED_BRAINPOOLP320R1_SZ
+    #endif /* HAVE_ECC_BRAINPOOL */
+#endif /* ECC320 */
+#ifdef ECC384
+    #ifndef NO_ECC_SECP
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_SECP384R1    {1,3,132,0,34}
+            #define CODED_SECP384R1_SZ 5
+        #else
+            #define CODED_SECP384R1    {0x2B,0x81,0x04,0x00,0x22}
+            #define CODED_SECP384R1_SZ 5
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_secp384r1[] = CODED_SECP384R1;
+            #define CODED_SECP384R1_OID ecc_oid_secp384r1
+        #else
+			#define ecc_oid_secp384r1 CODED_SECP384R1
+        #endif
+        #define ecc_oid_secp384r1_sz CODED_SECP384R1_SZ
+    #endif /* !NO_ECC_SECP */
+    #ifdef HAVE_ECC_BRAINPOOL
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_BRAINPOOLP384R1    {1,3,36,3,3,2,8,1,1,11}
+            #define CODED_BRAINPOOLP384R1_SZ 10
+        #else
+            #define CODED_BRAINPOOLP384R1    {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0B}
+            #define CODED_BRAINPOOLP384R1_SZ 9
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_brainpoolp384r1[] = CODED_BRAINPOOLP384R1;
+        #else
+            #define ecc_oid_brainpoolp384r1 CODED_BRAINPOOLP384R1
+        #endif
+        #define ecc_oid_brainpoolp384r1_sz CODED_BRAINPOOLP384R1_SZ
+    #endif /* HAVE_ECC_BRAINPOOL */
+#endif /* ECC384 */
+#ifdef ECC512
+    #ifdef HAVE_ECC_BRAINPOOL
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_BRAINPOOLP512R1    {1,3,36,3,3,2,8,1,1,13}
+            #define CODED_BRAINPOOLP512R1_SZ 10
+        #else
+            #define CODED_BRAINPOOLP512R1    {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0D}
+            #define CODED_BRAINPOOLP512R1_SZ 9
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_brainpoolp512r1[] = CODED_BRAINPOOLP512R1;
+        #else
+            #define ecc_oid_brainpoolp512r1 CODED_BRAINPOOLP512R1
+        #endif
+        #define ecc_oid_brainpoolp512r1_sz CODED_BRAINPOOLP512R1_SZ
+    #endif /* HAVE_ECC_BRAINPOOL */
+#endif /* ECC512 */
+#ifdef ECC521
+    #ifndef NO_ECC_SECP
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_SECP521R1     {1,3,132,0,35}
+            #define CODED_SECP521R1_SZ 5
+        #else
+            #define CODED_SECP521R1     {0x2B,0x81,0x04,0x00,0x23}
+            #define CODED_SECP521R1_SZ 5
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_secp521r1[] = CODED_SECP521R1;
+        #else
+            #define ecc_oid_secp521r1 CODED_SECP521R1
+        #endif
+        #define ecc_oid_secp521r1_sz CODED_SECP521R1_SZ
+    #endif /* !NO_ECC_SECP */
+#endif /* ECC521 */
+
+
+/* This holds the key settings.
+   ***MUST*** be organized by size from smallest to largest. */
+
+const ecc_set_type ecc_sets[] = {
+#ifdef ECC112
+    #ifndef NO_ECC_SECP
+    {
+        14,                             /* size/bytes */
+        ECC_SECP112R1,                  /* ID         */
+        "SECP112R1",                    /* curve name */
+        "DB7C2ABF62E35E668076BEAD208B", /* prime      */
+        "DB7C2ABF62E35E668076BEAD2088", /* A          */
+        "659EF8BA043916EEDE8911702B22", /* B          */
+        "DB7C2ABF62E35E7628DFAC6561C5", /* order      */
+        "9487239995A5EE76B55F9C2F098",  /* Gx         */
+        "A89CE5AF8724C0A23E0E0FF77500", /* Gy         */
+        ecc_oid_secp112r1,              /* oid/oidSz  */
+        ecc_oid_secp112r1_sz,
+        ECC_SECP112R1_OID,              /* oid sum    */
+        1,                              /* cofactor   */
+    },
+    #endif /* !NO_ECC_SECP */
+    #ifdef HAVE_ECC_SECPR2
+    {
+        14,                             /* size/bytes */
+        ECC_SECP112R2,                  /* ID         */
+        "SECP112R2",                    /* curve name */
+        "DB7C2ABF62E35E668076BEAD208B", /* prime      */
+        "6127C24C05F38A0AAAF65C0EF02C", /* A          */
+        "51DEF1815DB5ED74FCC34C85D709", /* B          */
+        "36DF0AAFD8B8D7597CA10520D04B", /* order      */
+        "4BA30AB5E892B4E1649DD0928643", /* Gx         */
+        "ADCD46F5882E3747DEF36E956E97", /* Gy         */
+        ecc_oid_secp112r2,              /* oid/oidSz  */
+        ecc_oid_secp112r2_sz,
+        ECC_SECP112R2_OID,              /* oid sum    */
+        4,                              /* cofactor   */
+    },
+    #endif /* HAVE_ECC_SECPR2 */
+#endif /* ECC112 */
+#ifdef ECC128
+    #ifndef NO_ECC_SECP
+    {
+        16,                                 /* size/bytes */
+        ECC_SECP128R1,                      /* ID         */
+        "SECP128R1",                        /* curve name */
+        "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", /* prime      */
+        "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC", /* A          */
+        "E87579C11079F43DD824993C2CEE5ED3", /* B          */
+        "FFFFFFFE0000000075A30D1B9038A115", /* order      */
+        "161FF7528B899B2D0C28607CA52C5B86", /* Gx         */
+        "CF5AC8395BAFEB13C02DA292DDED7A83", /* Gy         */
+        ecc_oid_secp128r1,                  /* oid/oidSz  */
+        ecc_oid_secp128r1_sz,
+        ECC_SECP128R1_OID,                  /* oid sum    */
+        1,                                  /* cofactor   */
+    },
+    #endif /* !NO_ECC_SECP */
+    #ifdef HAVE_ECC_SECPR2
+    {
+        16,                                 /* size/bytes */
+        ECC_SECP128R2,                      /* ID         */
+        "SECP128R2",                        /* curve name */
+        "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", /* prime      */
+        "D6031998D1B3BBFEBF59CC9BBFF9AEE1", /* A          */
+        "5EEEFCA380D02919DC2C6558BB6D8A5D", /* B          */
+        "3FFFFFFF7FFFFFFFBE0024720613B5A3", /* order      */
+        "7B6AA5D85E572983E6FB32A7CDEBC140", /* Gx         */
+        "27B6916A894D3AEE7106FE805FC34B44", /* Gy         */
+        ecc_oid_secp128r2,                  /* oid/oidSz  */
+        ecc_oid_secp128r2_sz,
+        ECC_SECP128R2_OID,                  /* oid sum    */
+        4,                                  /* cofactor   */
+    },
+    #endif /* HAVE_ECC_SECPR2 */
+#endif /* ECC128 */
+#ifdef ECC160
+    #ifndef NO_ECC_SECP
+    {
+        20,                                         /* size/bytes */
+        ECC_SECP160R1,                              /* ID         */
+        "SECP160R1",                                /* curve name */
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", /* prime      */
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC", /* A          */
+        "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", /* B          */
+        "100000000000000000001F4C8F927AED3CA752257",/* order      */
+        "4A96B5688EF573284664698968C38BB913CBFC82", /* Gx         */
+        "23A628553168947D59DCC912042351377AC5FB32", /* Gy         */
+        ecc_oid_secp160r1,                          /* oid/oidSz  */
+        ecc_oid_secp160r1_sz,
+        ECC_SECP160R1_OID,                          /* oid sum    */
+        1,                                          /* cofactor   */
+    },
+    #endif /* !NO_ECC_SECP */
+    #ifdef HAVE_ECC_SECPR2
+    {
+        20,                                         /* size/bytes */
+        ECC_SECP160R2,                              /* ID         */
+        "SECP160R2",                                /* curve name */
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", /* prime      */
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70", /* A          */
+        "B4E134D3FB59EB8BAB57274904664D5AF50388BA", /* B          */
+        "100000000000000000000351EE786A818F3A1A16B",/* order      */
+        "52DCB034293A117E1F4FF11B30F7199D3144CE6D", /* Gx         */
+        "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E", /* Gy         */
+        ecc_oid_secp160r2,                          /* oid/oidSz  */
+        ecc_oid_secp160r2_sz,
+        ECC_SECP160R2_OID,                          /* oid sum    */
+        1,                                          /* cofactor   */
+    },
+    #endif /* HAVE_ECC_SECPR2 */
+    #ifdef HAVE_ECC_KOBLITZ
+    {
+        20,                                         /* size/bytes */
+        ECC_SECP160K1,                              /* ID         */
+        "SECP160K1",                                /* curve name */
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", /* prime      */
+        "0000000000000000000000000000000000000000", /* A          */
+        "0000000000000000000000000000000000000007", /* B          */
+        "100000000000000000001B8FA16DFAB9ACA16B6B3",/* order      */
+        "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB", /* Gx         */
+        "938CF935318FDCED6BC28286531733C3F03C4FEE", /* Gy         */
+        ecc_oid_secp160k1,                          /* oid/oidSz  */
+        ecc_oid_secp160k1_sz,
+        ECC_SECP160K1_OID,                          /* oid sum    */
+        1,                                          /* cofactor   */
+    },
+    #endif /* HAVE_ECC_KOBLITZ */
+    #ifdef HAVE_ECC_BRAINPOOL
+    {
+        20,                                         /* size/bytes */
+        ECC_BRAINPOOLP160R1,                        /* ID         */
+        "BRAINPOOLP160R1",                          /* curve name */
+        "E95E4A5F737059DC60DFC7AD95B3D8139515620F", /* prime      */
+        "340E7BE2A280EB74E2BE61BADA745D97E8F7C300", /* A          */
+        "1E589A8595423412134FAA2DBDEC95C8D8675E58", /* B          */
+        "E95E4A5F737059DC60DF5991D45029409E60FC09", /* order      */
+        "BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3", /* Gx         */
+        "1667CB477A1A8EC338F94741669C976316DA6321", /* Gy         */
+        ecc_oid_brainpoolp160r1,                    /* oid/oidSz  */
+        ecc_oid_brainpoolp160r1_sz,
+        ECC_BRAINPOOLP160R1_OID,                    /* oid sum    */
+        1,                                          /* cofactor   */
+    },
+    #endif /* HAVE_ECC_BRAINPOOL */
+#endif /* ECC160 */
+#ifdef ECC192
+    #ifndef NO_ECC_SECP
+    {
+        24,                                                 /* size/bytes */
+        ECC_SECP192R1,                                      /* ID         */
+        "SECP192R1",                                        /* curve name */
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", /* prime      */
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", /* A          */
+        "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", /* B          */
+        "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", /* order      */
+        "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", /* Gx         */
+        "7192B95FFC8DA78631011ED6B24CDD573F977A11E794811",  /* Gy         */
+        ecc_oid_secp192r1,                                  /* oid/oidSz  */
+        ecc_oid_secp192r1_sz,
+        ECC_SECP192R1_OID,                                  /* oid sum    */
+        1,                                                  /* cofactor   */
+    },
+    #endif /* !NO_ECC_SECP */
+    #ifdef HAVE_ECC_SECPR2
+    {
+        24,                                                 /* size/bytes */
+        ECC_PRIME192V2,                                     /* ID         */
+        "PRIME192V2",                                       /* curve name */
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", /* prime      */
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", /* A          */
+        "CC22D6DFB95C6B25E49C0D6364A4E5980C393AA21668D953", /* B          */
+        "FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31", /* order      */
+        "EEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A", /* Gx         */
+        "6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15", /* Gy         */
+        ecc_oid_prime192v2,                                 /* oid/oidSz  */
+        ecc_oid_prime192v2_sz,
+        ECC_PRIME192V2_OID,                                 /* oid sum    */
+        1,                                                  /* cofactor   */
+    },
+    #endif /* HAVE_ECC_SECPR2 */
+    #ifdef HAVE_ECC_SECPR3
+    {
+        24,                                                 /* size/bytes */
+        ECC_PRIME192V3,                                     /* ID         */
+        "PRIME192V3",                                       /* curve name */
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", /* prime      */
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", /* A          */
+        "22123DC2395A05CAA7423DAECCC94760A7D462256BD56916", /* B          */
+        "FFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13", /* order      */
+        "7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896", /* Gx         */
+        "38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0", /* Gy         */
+        ecc_oid_prime192v3,                                 /* oid/oidSz  */
+        ecc_oid_prime192v3_sz,
+        ECC_PRIME192V3_OID,                                 /* oid sum    */
+        1,                                                  /* cofactor   */
+    },
+    #endif /* HAVE_ECC_SECPR3 */
+    #ifdef HAVE_ECC_KOBLITZ
+    {
+        24,                                                 /* size/bytes */
+        ECC_SECP192K1,                                      /* ID         */
+        "SECP192K1",                                        /* curve name */
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", /* prime      */
+        "000000000000000000000000000000000000000000000000", /* A          */
+        "000000000000000000000000000000000000000000000003", /* B          */
+        "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", /* order      */
+        "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D", /* Gx         */
+        "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", /* Gy         */
+        ecc_oid_secp192k1,                                  /* oid/oidSz  */
+        ecc_oid_secp192k1_sz,
+        ECC_SECP192K1_OID,                                  /* oid sum    */
+        1,                                                  /* cofactor   */
+    },
+    #endif /* HAVE_ECC_KOBLITZ */
+    #ifdef HAVE_ECC_BRAINPOOL
+    {
+        24,                                                 /* size/bytes */
+        ECC_BRAINPOOLP192R1,                                /* ID         */
+        "BRAINPOOLP192R1",                                  /* curve name */
+        "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", /* prime      */
+        "6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF", /* A          */
+        "469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", /* B          */
+        "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", /* order      */
+        "C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6", /* Gx         */
+        "14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F", /* Gy         */
+        ecc_oid_brainpoolp192r1,                            /* oid/oidSz  */
+        ecc_oid_brainpoolp192r1_sz,
+        ECC_BRAINPOOLP192R1_OID,                            /* oid sum    */
+        1,                                                  /* cofactor   */
+    },
+    #endif /* HAVE_ECC_BRAINPOOL */
+#endif /* ECC192 */
+#ifdef ECC224
+    #ifndef NO_ECC_SECP
+    {
+        28,                                                         /* size/bytes */
+        ECC_SECP224R1,                                              /* ID         */
+        "SECP224R1",                                                /* curve name */
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", /* prime      */
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", /* A          */
+        "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", /* B          */
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", /* order      */
+        "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", /* Gx         */
+        "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", /* Gy         */
+        ecc_oid_secp224r1,                                          /* oid/oidSz  */
+        ecc_oid_secp224r1_sz,
+        ECC_SECP224R1_OID,                                          /* oid sum    */
+        1,                                                          /* cofactor   */
+    },
+    #endif /* !NO_ECC_SECP */
+    #ifdef HAVE_ECC_KOBLITZ
+    {
+        28,                                                         /* size/bytes */
+        ECC_SECP224K1,                                              /* ID         */
+        "SECP224K1",                                                /* curve name */
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D", /* prime      */
+        "00000000000000000000000000000000000000000000000000000000", /* A          */
+        "00000000000000000000000000000000000000000000000000000005", /* B          */
+        "10000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7",/* order      */
+        "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C", /* Gx         */
+        "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5", /* Gy         */
+        ecc_oid_secp224k1,                                          /* oid/oidSz  */
+        ecc_oid_secp224k1_sz,
+        ECC_SECP224K1_OID,                                          /* oid sum    */
+        1,                                                          /* cofactor   */
+    },
+    #endif /* HAVE_ECC_KOBLITZ */
+    #ifdef HAVE_ECC_BRAINPOOL
+    {
+        28,                                                         /* size/bytes */
+        ECC_BRAINPOOLP224R1,                                        /* ID         */
+        "BRAINPOOLP224R1",                                          /* curve name */
+        "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", /* prime      */
+        "68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43", /* A          */
+        "2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", /* B          */
+        "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", /* order      */
+        "0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D", /* Gx         */
+        "58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD", /* Gy         */
+        ecc_oid_brainpoolp224r1,                                    /* oid/oidSz  */
+        ecc_oid_brainpoolp224r1_sz,
+        ECC_BRAINPOOLP224R1_OID,                                    /* oid sum    */
+        1,                                                          /* cofactor   */
+    },
+    #endif /* HAVE_ECC_BRAINPOOL */
+#endif /* ECC224 */
+#ifdef ECC239
+    #ifndef NO_ECC_SECP
+    {
+        30,                                                             /* size/bytes */
+        ECC_PRIME239V1,                                                 /* ID         */
+        "PRIME239V1",                                                   /* curve name */
+        "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", /* prime      */
+        "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", /* A          */
+        "6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A", /* B          */
+        "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF9E5E9A9F5D9071FBD1522688909D0B", /* order      */
+        "0FFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF", /* Gx         */
+        "7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE", /* Gy         */
+        ecc_oid_prime239v1,                                             /* oid/oidSz  */
+        ecc_oid_prime239v1_sz,
+        ECC_PRIME239V1_OID,                                             /* oid sum    */
+        1,                                                              /* cofactor   */
+    },
+    #endif /* !NO_ECC_SECP */
+    #ifdef HAVE_ECC_SECPR2
+    {
+        30,                                                             /* size/bytes */
+        ECC_PRIME239V2,                                                 /* ID         */
+        "PRIME239V2",                                                   /* curve name */
+        "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", /* prime      */
+        "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", /* A          */
+        "617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C", /* B          */
+        "7FFFFFFFFFFFFFFFFFFFFFFF800000CFA7E8594377D414C03821BC582063", /* order      */
+        "38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7", /* Gx         */
+        "5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA", /* Gy         */
+        ecc_oid_prime239v2,                                             /* oid/oidSz  */
+        ecc_oid_prime239v2_sz,
+        ECC_PRIME239V2_OID,                                             /* oid sum    */
+        1,                                                              /* cofactor   */
+    },
+    #endif /* HAVE_ECC_SECPR2 */
+    #ifdef HAVE_ECC_SECPR3
+    {
+        30,                                                             /* size/bytes */
+        ECC_PRIME239V3,                                                 /* ID         */
+        "PRIME239V3",                                                   /* curve name */
+        "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", /* prime      */
+        "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", /* A          */
+        "255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E", /* B          */
+        "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF975DEB41B3A6057C3C432146526551", /* order      */
+        "6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A", /* Gx         */
+        "1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3", /* Gy         */
+        ecc_oid_prime239v3,                                             /* oid/oidSz  */
+        ecc_oid_prime239v3_sz,
+        ECC_PRIME239V3_OID,                                             /* oid sum    */
+        1,                                                              /* cofactor   */
+    },
+    #endif /* HAVE_ECC_SECPR3 */
+#endif /* ECC239 */
+#ifdef ECC256
+    #ifndef NO_ECC_SECP
+    {
+        32,                                                                 /* size/bytes */
+        ECC_SECP256R1,                                                      /* ID         */
+        "SECP256R1",                                                        /* curve name */
+        "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", /* prime      */
+        "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", /* A          */
+        "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", /* B          */
+        "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", /* order      */
+        "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", /* Gx         */
+        "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", /* Gy         */
+		ecc_oid_secp256r1,                                                  /* oid/oidSz  */
+        ecc_oid_secp256r1_sz,
+        ECC_SECP256R1_OID,                                                  /* oid sum    */
+        1,                                                                  /* cofactor   */
+    },
+    #endif /* !NO_ECC_SECP */
+    #ifdef HAVE_ECC_KOBLITZ
+    {
+        32,                                                                 /* size/bytes */
+        ECC_SECP256K1,                                                      /* ID         */
+        "SECP256K1",                                                        /* curve name */
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", /* prime      */
+        "0000000000000000000000000000000000000000000000000000000000000000", /* A          */
+        "0000000000000000000000000000000000000000000000000000000000000007", /* B          */
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", /* order      */
+        "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", /* Gx         */
+        "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", /* Gy         */
+        ecc_oid_secp256k1,                                                  /* oid/oidSz  */
+        ecc_oid_secp256k1_sz,
+        ECC_SECP256K1_OID,                                                  /* oid sum    */
+        1,                                                                  /* cofactor   */
+    },
+    #endif /* HAVE_ECC_KOBLITZ */
+    #ifdef HAVE_ECC_BRAINPOOL
+    {
+        32,                                                                 /* size/bytes */
+        ECC_BRAINPOOLP256R1,                                                /* ID         */
+        "BRAINPOOLP256R1",                                                  /* curve name */
+        "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", /* prime      */
+        "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", /* A          */
+        "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", /* B          */
+        "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", /* order      */
+        "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262", /* Gx         */
+        "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", /* Gy         */
+        ecc_oid_brainpoolp256r1,                                            /* oid/oidSz  */
+        ecc_oid_brainpoolp256r1_sz,
+        ECC_BRAINPOOLP256R1_OID,                                            /* oid sum    */
+        1,                                                                  /* cofactor   */
+    },
+    #endif /* HAVE_ECC_BRAINPOOL */
+#endif /* ECC256 */
+#ifdef ECC320
+    #ifdef HAVE_ECC_BRAINPOOL
+    {
+        40,                                                                                 /* size/bytes */
+        ECC_BRAINPOOLP320R1,                                                                /* ID         */
+        "BRAINPOOLP320R1",                                                                  /* curve name */
+        "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", /* prime      */
+        "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4", /* A          */
+        "520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", /* B          */
+        "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", /* order      */
+        "43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611", /* Gx         */
+        "14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1", /* Gy         */
+        ecc_oid_brainpoolp320r1, ecc_oid_brainpoolp320r1_sz,                                /* oid/oidSz  */
+        ECC_BRAINPOOLP320R1_OID,                                                            /* oid sum    */
+        1,                                                                                  /* cofactor   */
+    },
+    #endif /* HAVE_ECC_BRAINPOOL */
+#endif /* ECC320 */
+#ifdef ECC384
+    #ifndef NO_ECC_SECP
+    {
+        48,                                                                                                 /* size/bytes */
+        ECC_SECP384R1,                                                                                      /* ID         */
+        "SECP384R1",                                                                                        /* curve name */
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", /* prime      */
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", /* A          */
+        "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", /* B          */
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", /* order      */
+        "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", /* Gx         */
+        "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", /* Gy         */
+        ecc_oid_secp384r1, ecc_oid_secp384r1_sz,                                                            /* oid/oidSz  */
+        ECC_SECP384R1_OID,                                                                                  /* oid sum    */
+        1,                                                                                                  /* cofactor   */
+    },
+    #endif /* !NO_ECC_SECP */
+    #ifdef HAVE_ECC_BRAINPOOL
+    {
+        48,                                                                                                 /* size/bytes */
+        ECC_BRAINPOOLP384R1,                                                                                /* ID         */
+        "BRAINPOOLP384R1",                                                                                  /* curve name */
+        "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", /* prime      */
+        "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", /* A          */
+        "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", /* B          */
+        "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", /* order      */
+        "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E", /* Gx         */
+        "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", /* Gy         */
+        ecc_oid_brainpoolp384r1, ecc_oid_brainpoolp384r1_sz,                                                /* oid/oidSz  */
+        ECC_BRAINPOOLP384R1_OID,                                                                            /* oid sum    */
+        1,                                                                                                  /* cofactor   */
+    },
+    #endif /* HAVE_ECC_BRAINPOOL */
+#endif /* ECC384 */
+#ifdef ECC512
+    #ifdef HAVE_ECC_BRAINPOOL
+    {
+        64,                                                                                                                                 /* size/bytes */
+        ECC_BRAINPOOLP512R1,                                                                                                                /* ID         */
+        "BRAINPOOLP512R1",                                                                                                                  /* curve name */
+        "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", /* prime      */
+        "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", /* A          */
+        "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", /* B          */
+        "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", /* order      */
+        "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822", /* Gx         */
+        "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", /* Gy         */
+        ecc_oid_brainpoolp512r1, ecc_oid_brainpoolp512r1_sz,                                                                                /* oid/oidSz  */
+        ECC_BRAINPOOLP512R1_OID,                                                                                                            /* oid sum    */
+        1,                                                                                                                                  /* cofactor   */
+    },
+    #endif /* HAVE_ECC_BRAINPOOL */
+#endif /* ECC512 */
+#ifdef ECC521
+    #ifndef NO_ECC_SECP
+    {
+        66,                                                                                                                                    /* size/bytes */
+        ECC_SECP521R1,                                                                                                                         /* ID         */
+        "SECP521R1",                                                                                                                           /* curve name */
+        "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* prime      */
+        "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", /* A          */
+        "51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",  /* B          */
+        "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", /* order      */
+        "C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",  /* Gx         */
+        "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", /* Gy         */
+        ecc_oid_secp521r1, ecc_oid_secp521r1_sz,                                                                                               /* oid/oidSz  */
+        ECC_SECP521R1_OID,                                                                                                                     /* oid sum    */
+        1,                                                                                                                                     /* cofactor   */
+    },
+    #endif /* !NO_ECC_SECP */
+#endif /* ECC521 */
+#if defined(WOLFSSL_CUSTOM_CURVES) && defined(ECC_CACHE_CURVE)
+    /* place holder for custom curve index for cache */
+    {
+        1, /* non-zero */
+        ECC_CURVE_CUSTOM,
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+        #else
+            {0},{0},{0},{0},{0},{0},{0},{0},
+        #endif
+        0, 0, 0
+    },
+#endif
+    {
+        0,
+        ECC_CURVE_INVALID,
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+        #else
+            {0},{0},{0},{0},{0},{0},{0},{0},
+        #endif
+        0, 0, 0
+    }
+};
+#define ECC_SET_COUNT   (sizeof(ecc_sets)/sizeof(ecc_set_type))
+const size_t ecc_sets_count = ECC_SET_COUNT - 1;
+
+
+#ifdef HAVE_OID_ENCODING
+    /* encoded OID cache */
+    typedef struct {
+        word32 oidSz;
+        byte oid[ECC_MAX_OID_LEN];
+    } oid_cache_t;
+    static oid_cache_t ecc_oid_cache[ECC_SET_COUNT];
+#endif
+
+
+#ifdef HAVE_COMP_KEY
+static int wc_ecc_export_x963_compressed(ecc_key*, byte* out, word32* outLen);
+#endif
+
+
+#if (defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || !defined(WOLFSSL_SP_MATH)) && \
+    !defined(WOLFSSL_ATECC508A)
+static int ecc_check_pubkey_order(ecc_key* key, ecc_point* pubkey, mp_int* a,
+        mp_int* prime, mp_int* order);
+#endif
+
+int mp_jacobi(mp_int* a, mp_int* n, int* c);
+int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret);
+
+
+/* Curve Specs */
+typedef struct ecc_curve_spec {
+    const ecc_set_type* dp;
+
+    mp_int* prime;
+    mp_int* Af;
+    #ifdef USE_ECC_B_PARAM
+        mp_int* Bf;
+    #endif
+    mp_int* order;
+    mp_int* Gx;
+    mp_int* Gy;
+
+#ifdef ECC_CACHE_CURVE
+    mp_int prime_lcl;
+    mp_int Af_lcl;
+    #ifdef USE_ECC_B_PARAM
+        mp_int Bf_lcl;
+    #endif
+    mp_int order_lcl;
+    mp_int Gx_lcl;
+    mp_int Gy_lcl;
+#else
+    mp_int* spec_ints;
+    word32 spec_count;
+    word32 spec_use;
+#endif
+
+    byte load_mask;
+} ecc_curve_spec;
+
+enum ecc_curve_load_mask {
+    ECC_CURVE_FIELD_NONE    = 0x00,
+    ECC_CURVE_FIELD_PRIME   = 0x01,
+    ECC_CURVE_FIELD_AF      = 0x02,
+#ifdef USE_ECC_B_PARAM
+    ECC_CURVE_FIELD_BF      = 0x04,
+#endif
+    ECC_CURVE_FIELD_ORDER   = 0x08,
+    ECC_CURVE_FIELD_GX      = 0x10,
+    ECC_CURVE_FIELD_GY      = 0x20,
+#ifdef USE_ECC_B_PARAM
+    ECC_CURVE_FIELD_ALL     = 0x3F,
+    ECC_CURVE_FIELD_COUNT   = 6,
+#else
+    ECC_CURVE_FIELD_ALL     = 0x3B,
+    ECC_CURVE_FIELD_COUNT   = 5,
+#endif
+};
+
+#ifdef ECC_CACHE_CURVE
+    /* cache (mp_int) of the curve parameters */
+    static ecc_curve_spec* ecc_curve_spec_cache[ECC_SET_COUNT];
+    #ifndef SINGLE_THREADED
+        static wolfSSL_Mutex ecc_curve_cache_mutex;
+    #endif
+
+    #define DECLARE_CURVE_SPECS(curve, intcount) ecc_curve_spec* curve = NULL
+    #define ALLOC_CURVE_SPECS(intcount)
+    #define FREE_CURVE_SPECS()
+#elif defined(WOLFSSL_SMALL_STACK)
+    #define DECLARE_CURVE_SPECS(curve, intcount)                        \
+        mp_int* spec_ints = NULL;                                       \
+        ecc_curve_spec curve_lcl;                                       \
+        ecc_curve_spec* curve = &curve_lcl;                             \
+        XMEMSET(curve, 0, sizeof(ecc_curve_spec));                      \
+        curve->spec_count = intcount
+
+    #define ALLOC_CURVE_SPECS(intcount)                                 \
+        spec_ints = (mp_int*)XMALLOC(sizeof(mp_int) * (intcount), NULL, \
+                            DYNAMIC_TYPE_ECC);                          \
+        if (spec_ints == NULL)                                          \
+            return MEMORY_E;                                            \
+        curve->spec_ints = spec_ints
+    #define FREE_CURVE_SPECS()                                          \
+        XFREE(spec_ints, NULL, DYNAMIC_TYPE_ECC)
+#else
+    #define DECLARE_CURVE_SPECS(curve, intcount) \
+        mp_int spec_ints[(intcount)]; \
+        ecc_curve_spec curve_lcl; \
+        ecc_curve_spec* curve = &curve_lcl; \
+        XMEMSET(curve, 0, sizeof(ecc_curve_spec)); \
+        curve->spec_ints = spec_ints; \
+        curve->spec_count = intcount
+    #define ALLOC_CURVE_SPECS(intcount)
+    #define FREE_CURVE_SPECS()
+#endif /* ECC_CACHE_CURVE */
+
+static void _wc_ecc_curve_free(ecc_curve_spec* curve)
+{
+    if (curve == NULL) {
+        return;
+    }
+
+    if (curve->load_mask & ECC_CURVE_FIELD_PRIME)
+        mp_clear(curve->prime);
+    if (curve->load_mask & ECC_CURVE_FIELD_AF)
+        mp_clear(curve->Af);
+#ifdef USE_ECC_B_PARAM
+    if (curve->load_mask & ECC_CURVE_FIELD_BF)
+        mp_clear(curve->Bf);
+#endif
+    if (curve->load_mask & ECC_CURVE_FIELD_ORDER)
+        mp_clear(curve->order);
+    if (curve->load_mask & ECC_CURVE_FIELD_GX)
+        mp_clear(curve->Gx);
+    if (curve->load_mask & ECC_CURVE_FIELD_GY)
+        mp_clear(curve->Gy);
+
+    curve->load_mask = 0;
+}
+
+static void wc_ecc_curve_free(ecc_curve_spec* curve)
+{
+    /* don't free cached curves */
+#ifndef ECC_CACHE_CURVE
+    _wc_ecc_curve_free(curve);
+#endif
+    (void)curve;
+}
+
+static int wc_ecc_curve_load_item(const char* src, mp_int** dst,
+    ecc_curve_spec* curve, byte mask)
+{
+    int err;
+
+#ifndef ECC_CACHE_CURVE
+    /* get mp_int from temp */
+    if (curve->spec_use >= curve->spec_count) {
+        WOLFSSL_MSG("Invalid DECLARE_CURVE_SPECS count");
+        return ECC_BAD_ARG_E;
+    }
+    *dst = &curve->spec_ints[curve->spec_use++];
+#endif
+
+    err = mp_init(*dst);
+    if (err == MP_OKAY) {
+        curve->load_mask |= mask;
+
+        err = mp_read_radix(*dst, src, MP_RADIX_HEX);
+
+    #ifdef HAVE_WOLF_BIGINT
+        if (err == MP_OKAY)
+            err = wc_mp_to_bigint(*dst, &(*dst)->raw);
+    #endif
+    }
+    return err;
+}
+
+static int wc_ecc_curve_load(const ecc_set_type* dp, ecc_curve_spec** pCurve,
+    byte load_mask)
+{
+    int ret = 0, x;
+    ecc_curve_spec* curve;
+    byte load_items = 0; /* mask of items to load */
+
+    if (dp == NULL || pCurve == NULL)
+        return BAD_FUNC_ARG;
+
+#ifdef ECC_CACHE_CURVE
+    x = wc_ecc_get_curve_idx(dp->id);
+    if (x == ECC_CURVE_INVALID)
+        return ECC_BAD_ARG_E;
+
+#if !defined(SINGLE_THREADED)
+    ret = wc_LockMutex(&ecc_curve_cache_mutex);
+    if (ret != 0) {
+        return ret;
+    }
+#endif
+
+    /* make sure cache has been allocated */
+    if (ecc_curve_spec_cache[x] == NULL) {
+        ecc_curve_spec_cache[x] = (ecc_curve_spec*)XMALLOC(
+            sizeof(ecc_curve_spec), NULL, DYNAMIC_TYPE_ECC);
+        if (ecc_curve_spec_cache[x] == NULL) {
+        #if defined(ECC_CACHE_CURVE) && !defined(SINGLE_THREADED)
+            wc_UnLockMutex(&ecc_curve_cache_mutex);
+        #endif
+            return MEMORY_E;
+        }
+        XMEMSET(ecc_curve_spec_cache[x], 0, sizeof(ecc_curve_spec));
+    }
+
+    /* set curve pointer to cache */
+    *pCurve = ecc_curve_spec_cache[x];
+
+#endif /* ECC_CACHE_CURVE */
+    curve = *pCurve;
+
+    /* make sure the curve is initialized */
+    if (curve->dp != dp) {
+        curve->load_mask = 0;
+
+    #ifdef ECC_CACHE_CURVE
+        curve->prime = &curve->prime_lcl;
+        curve->Af = &curve->Af_lcl;
+        #ifdef USE_ECC_B_PARAM
+            curve->Bf = &curve->Bf_lcl;
+        #endif
+        curve->order = &curve->order_lcl;
+        curve->Gx = &curve->Gx_lcl;
+        curve->Gy = &curve->Gy_lcl;
+    #endif
+    }
+    curve->dp = dp; /* set dp info */
+
+    /* determine items to load */
+    load_items = (((byte)~(word32)curve->load_mask) & load_mask);
+    curve->load_mask |= load_items;
+
+    /* load items */
+    x = 0;
+    if (load_items & ECC_CURVE_FIELD_PRIME)
+        x += wc_ecc_curve_load_item(dp->prime, &curve->prime, curve,
+            ECC_CURVE_FIELD_PRIME);
+    if (load_items & ECC_CURVE_FIELD_AF)
+        x += wc_ecc_curve_load_item(dp->Af, &curve->Af, curve,
+            ECC_CURVE_FIELD_AF);
+#ifdef USE_ECC_B_PARAM
+    if (load_items & ECC_CURVE_FIELD_BF)
+        x += wc_ecc_curve_load_item(dp->Bf, &curve->Bf, curve,
+            ECC_CURVE_FIELD_BF);
+#endif
+    if (load_items & ECC_CURVE_FIELD_ORDER)
+        x += wc_ecc_curve_load_item(dp->order, &curve->order, curve,
+            ECC_CURVE_FIELD_ORDER);
+    if (load_items & ECC_CURVE_FIELD_GX)
+        x += wc_ecc_curve_load_item(dp->Gx, &curve->Gx, curve,
+            ECC_CURVE_FIELD_GX);
+    if (load_items & ECC_CURVE_FIELD_GY)
+        x += wc_ecc_curve_load_item(dp->Gy, &curve->Gy, curve,
+            ECC_CURVE_FIELD_GY);
+
+    /* check for error */
+    if (x != 0) {
+        wc_ecc_curve_free(curve);
+        ret = MP_READ_E;
+    }
+
+#if defined(ECC_CACHE_CURVE) && !defined(SINGLE_THREADED)
+    wc_UnLockMutex(&ecc_curve_cache_mutex);
+#endif
+
+    return ret;
+}
+
+#ifdef ECC_CACHE_CURVE
+int wc_ecc_curve_cache_init(void)
+{
+    int ret = 0;
+#if defined(ECC_CACHE_CURVE) && !defined(SINGLE_THREADED)
+    ret = wc_InitMutex(&ecc_curve_cache_mutex);
+#endif
+    return ret;
+}
+
+void wc_ecc_curve_cache_free(void)
+{
+    int x;
+
+    /* free all ECC curve caches */
+    for (x = 0; x < (int)ECC_SET_COUNT; x++) {
+        if (ecc_curve_spec_cache[x]) {
+            _wc_ecc_curve_free(ecc_curve_spec_cache[x]);
+            XFREE(ecc_curve_spec_cache[x], NULL, DYNAMIC_TYPE_ECC);
+            ecc_curve_spec_cache[x] = NULL;
+        }
+    }
+
+#if defined(ECC_CACHE_CURVE) && !defined(SINGLE_THREADED)
+    wc_FreeMutex(&ecc_curve_cache_mutex);
+#endif
+}
+#endif /* ECC_CACHE_CURVE */
+
+
+/* Retrieve the curve name for the ECC curve id.
+ *
+ * curve_id  The id of the curve.
+ * returns the name stored from the curve if available, otherwise NULL.
+ */
+const char* wc_ecc_get_name(int curve_id)
+{
+    int curve_idx = wc_ecc_get_curve_idx(curve_id);
+    if (curve_idx == ECC_CURVE_INVALID)
+        return NULL;
+    return ecc_sets[curve_idx].name;
+}
+
+int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id)
+{
+    if (keysize <= 0 && curve_id < 0) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (keysize > ECC_MAXSIZE) {
+        return ECC_BAD_ARG_E;
+    }
+
+    /* handle custom case */
+    if (key->idx != ECC_CUSTOM_IDX) {
+        int x;
+
+        /* default values */
+        key->idx = 0;
+        key->dp = NULL;
+
+        /* find ecc_set based on curve_id or key size */
+        for (x = 0; ecc_sets[x].size != 0; x++) {
+            if (curve_id > ECC_CURVE_DEF) {
+                if (curve_id == ecc_sets[x].id)
+                  break;
+            }
+            else if (keysize <= ecc_sets[x].size) {
+                break;
+            }
+        }
+        if (ecc_sets[x].size == 0) {
+            WOLFSSL_MSG("ECC Curve not found");
+            return ECC_CURVE_OID_E;
+        }
+
+        key->idx = x;
+        key->dp  = &ecc_sets[x];
+    }
+
+    return 0;
+}
+
+
+#ifdef ALT_ECC_SIZE
+static void alt_fp_init(mp_int* a)
+{
+    a->size = FP_SIZE_ECC;
+    mp_zero(a);
+}
+#endif /* ALT_ECC_SIZE */
+
+
+#ifndef WOLFSSL_ATECC508A
+
+#if !defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_PUBLIC_ECC_ADD_DBL)
+
+/**
+   Add two ECC points
+   P        The point to add
+   Q        The point to add
+   R        [out] The destination of the double
+   a        ECC curve parameter a
+   modulus  The modulus of the field the ECC curve is in
+   mp       The "b" value from montgomery_setup()
+   return   MP_OKAY on success
+*/
+int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R,
+                             mp_int* a, mp_int* modulus, mp_digit mp)
+{
+#ifndef WOLFSSL_SP_MATH
+#ifdef WOLFSSL_SMALL_STACK
+   mp_int* t1 = NULL;
+   mp_int* t2 = NULL;
+#ifdef ALT_ECC_SIZE
+   mp_int* rx = NULL;
+   mp_int* ry = NULL;
+   mp_int* rz = NULL;
+#endif
+#else
+   mp_int  t1[1], t2[1];
+#ifdef ALT_ECC_SIZE
+   mp_int  rx[1], ry[1], rz[1];
+#endif
+#endif
+   mp_int  *x, *y, *z;
+   int     err;
+
+   if (P == NULL || Q == NULL || R == NULL || modulus == NULL) {
+       return ECC_BAD_ARG_E;
+   }
+
+   /* if Q == R then swap P and Q, so we don't require a local x,y,z */
+   if (Q == R) {
+      ecc_point* tPt  = P;
+      P = Q;
+      Q = tPt;
+   }
+
+#ifdef WOLFSSL_SMALL_STACK
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+   if (R->key != NULL) {
+       t1 = R->key->t1;
+       t2 = R->key->t2;
+#ifdef ALT_ECC_SIZE
+       rx = R->key->x;
+       ry = R->key->y;
+       rz = R->key->z;
+#endif
+   }
+   else
+#endif /* WOLFSSL_SMALL_STACK_CACHE */
+   {
+       t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       if (t1 == NULL || t2 == NULL) {
+           XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+           return MEMORY_E;
+       }
+#ifdef ALT_ECC_SIZE
+       rx = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       ry = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       rz = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       if (rx == NULL || ry == NULL || rz == NULL) {
+           XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+           return MEMORY_E;
+       }
+#endif
+   }
+#endif /* WOLFSSL_SMALL_STACK */
+
+   if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
+#ifdef WOLFSSL_SMALL_STACK
+   #ifdef WOLFSSL_SMALL_STACK_CACHE
+       if (R->key == NULL)
+   #endif
+       {
+       #ifdef ALT_ECC_SIZE
+          XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
+          XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
+          XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
+       #endif
+          XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+          XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+       }
+#endif
+      return err;
+   }
+
+   /* should we dbl instead? */
+   if (err == MP_OKAY)
+       err = mp_sub(modulus, Q->y, t1);
+   if (err == MP_OKAY) {
+       if ( (mp_cmp(P->x, Q->x) == MP_EQ) &&
+            (get_digit_count(Q->z) && mp_cmp(P->z, Q->z) == MP_EQ) &&
+            (mp_cmp(P->y, Q->y) == MP_EQ || mp_cmp(P->y, t1) == MP_EQ)) {
+           mp_clear(t1);
+           mp_clear(t2);
+    #ifdef WOLFSSL_SMALL_STACK
+       #ifdef WOLFSSL_SMALL_STACK_CACHE
+           if (R->key == NULL)
+       #endif
+           {
+            #ifdef ALT_ECC_SIZE
+               XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
+               XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
+               XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
+            #endif
+               XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+               XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+           }
+        #endif
+          return ecc_projective_dbl_point(P, R, a, modulus, mp);
+       }
+   }
+
+   if (err != MP_OKAY) {
+      goto done;
+   }
+
+/* If use ALT_ECC_SIZE we need to use local stack variable since
+   ecc_point x,y,z is reduced size */
+#ifdef ALT_ECC_SIZE
+   /* Use local stack variable */
+   x = rx;
+   y = ry;
+   z = rz;
+
+   if ((err = mp_init_multi(x, y, z, NULL, NULL, NULL)) != MP_OKAY) {
+      goto done;
+   }
+#else
+   /* Use destination directly */
+   x = R->x;
+   y = R->y;
+   z = R->z;
+#endif
+
+   if (err == MP_OKAY)
+       err = mp_copy(P->x, x);
+   if (err == MP_OKAY)
+       err = mp_copy(P->y, y);
+   if (err == MP_OKAY)
+       err = mp_copy(P->z, z);
+
+   /* if Z is one then these are no-operations */
+   if (err == MP_OKAY) {
+       if (!mp_iszero(Q->z)) {
+           /* T1 = Z' * Z' */
+           err = mp_sqr(Q->z, t1);
+           if (err == MP_OKAY)
+               err = mp_montgomery_reduce(t1, modulus, mp);
+
+           /* X = X * T1 */
+           if (err == MP_OKAY)
+               err = mp_mul(t1, x, x);
+           if (err == MP_OKAY)
+               err = mp_montgomery_reduce(x, modulus, mp);
+
+           /* T1 = Z' * T1 */
+           if (err == MP_OKAY)
+               err = mp_mul(Q->z, t1, t1);
+           if (err == MP_OKAY)
+               err = mp_montgomery_reduce(t1, modulus, mp);
+
+           /* Y = Y * T1 */
+           if (err == MP_OKAY)
+               err = mp_mul(t1, y, y);
+           if (err == MP_OKAY)
+               err = mp_montgomery_reduce(y, modulus, mp);
+       }
+   }
+
+   /* T1 = Z*Z */
+   if (err == MP_OKAY)
+       err = mp_sqr(z, t1);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(t1, modulus, mp);
+
+   /* T2 = X' * T1 */
+   if (err == MP_OKAY)
+       err = mp_mul(Q->x, t1, t2);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(t2, modulus, mp);
+
+   /* T1 = Z * T1 */
+   if (err == MP_OKAY)
+       err = mp_mul(z, t1, t1);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(t1, modulus, mp);
+
+   /* T1 = Y' * T1 */
+   if (err == MP_OKAY)
+       err = mp_mul(Q->y, t1, t1);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(t1, modulus, mp);
+
+   /* Y = Y - T1 */
+   if (err == MP_OKAY)
+       err = mp_sub(y, t1, y);
+   if (err == MP_OKAY) {
+       if (mp_isneg(y))
+           err = mp_add(y, modulus, y);
+   }
+   /* T1 = 2T1 */
+   if (err == MP_OKAY)
+       err = mp_add(t1, t1, t1);
+   if (err == MP_OKAY) {
+       if (mp_cmp(t1, modulus) != MP_LT)
+           err = mp_sub(t1, modulus, t1);
+   }
+   /* T1 = Y + T1 */
+   if (err == MP_OKAY)
+       err = mp_add(t1, y, t1);
+   if (err == MP_OKAY) {
+       if (mp_cmp(t1, modulus) != MP_LT)
+           err = mp_sub(t1, modulus, t1);
+   }
+   /* X = X - T2 */
+   if (err == MP_OKAY)
+       err = mp_sub(x, t2, x);
+   if (err == MP_OKAY) {
+       if (mp_isneg(x))
+           err = mp_add(x, modulus, x);
+   }
+   /* T2 = 2T2 */
+   if (err == MP_OKAY)
+       err = mp_add(t2, t2, t2);
+   if (err == MP_OKAY) {
+       if (mp_cmp(t2, modulus) != MP_LT)
+           err = mp_sub(t2, modulus, t2);
+   }
+   /* T2 = X + T2 */
+   if (err == MP_OKAY)
+       err = mp_add(t2, x, t2);
+   if (err == MP_OKAY) {
+       if (mp_cmp(t2, modulus) != MP_LT)
+           err = mp_sub(t2, modulus, t2);
+   }
+
+   if (err == MP_OKAY) {
+       if (!mp_iszero(Q->z)) {
+           /* Z = Z * Z' */
+           err = mp_mul(z, Q->z, z);
+           if (err == MP_OKAY)
+               err = mp_montgomery_reduce(z, modulus, mp);
+       }
+   }
+
+   /* Z = Z * X */
+   if (err == MP_OKAY)
+       err = mp_mul(z, x, z);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(z, modulus, mp);
+
+   /* T1 = T1 * X  */
+   if (err == MP_OKAY)
+       err = mp_mul(t1, x, t1);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(t1, modulus, mp);
+
+   /* X = X * X */
+   if (err == MP_OKAY)
+       err = mp_sqr(x, x);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(x, modulus, mp);
+
+   /* T2 = T2 * x */
+   if (err == MP_OKAY)
+       err = mp_mul(t2, x, t2);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(t2, modulus, mp);
+
+   /* T1 = T1 * X  */
+   if (err == MP_OKAY)
+       err = mp_mul(t1, x, t1);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(t1, modulus, mp);
+
+   /* X = Y*Y */
+   if (err == MP_OKAY)
+       err = mp_sqr(y, x);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(x, modulus, mp);
+
+   /* X = X - T2 */
+   if (err == MP_OKAY)
+       err = mp_sub(x, t2, x);
+   if (err == MP_OKAY) {
+       if (mp_isneg(x))
+           err = mp_add(x, modulus, x);
+   }
+   /* T2 = T2 - X */
+   if (err == MP_OKAY)
+       err = mp_sub(t2, x, t2);
+   if (err == MP_OKAY) {
+       if (mp_isneg(t2))
+           err = mp_add(t2, modulus, t2);
+   }
+   /* T2 = T2 - X */
+   if (err == MP_OKAY)
+       err = mp_sub(t2, x, t2);
+   if (err == MP_OKAY) {
+       if (mp_isneg(t2))
+           err = mp_add(t2, modulus, t2);
+   }
+   /* T2 = T2 * Y */
+   if (err == MP_OKAY)
+       err = mp_mul(t2, y, t2);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(t2, modulus, mp);
+
+   /* Y = T2 - T1 */
+   if (err == MP_OKAY)
+       err = mp_sub(t2, t1, y);
+   if (err == MP_OKAY) {
+       if (mp_isneg(y))
+           err = mp_add(y, modulus, y);
+   }
+   /* Y = Y/2 */
+   if (err == MP_OKAY) {
+       if (mp_isodd(y) == MP_YES)
+           err = mp_add(y, modulus, y);
+   }
+   if (err == MP_OKAY)
+       err = mp_div_2(y, y);
+
+#ifdef ALT_ECC_SIZE
+   if (err == MP_OKAY)
+       err = mp_copy(x, R->x);
+   if (err == MP_OKAY)
+       err = mp_copy(y, R->y);
+   if (err == MP_OKAY)
+       err = mp_copy(z, R->z);
+#endif
+
+done:
+
+   /* clean up */
+   mp_clear(t1);
+   mp_clear(t2);
+#ifdef WOLFSSL_SMALL_STACK
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+   if (R->key == NULL)
+#endif
+   {
+   #ifdef ALT_ECC_SIZE
+      XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
+      XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
+      XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
+   #endif
+      XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+      XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+   }
+#endif
+
+   return err;
+#else
+    if (P == NULL || Q == NULL || R == NULL || modulus == NULL) {
+        return ECC_BAD_ARG_E;
+    }
+
+    (void)a;
+    (void)mp;
+
+#ifndef WOLFSSL_SP_NO_256
+    if (mp_count_bits(modulus) == 256) {
+        return sp_ecc_proj_add_point_256(P->x, P->y, P->z, Q->x, Q->y, Q->z,
+                                         R->x, R->y, R->z);
+    }
+#endif
+#ifdef WOLFSSL_SP_384
+    if (mp_count_bits(modulus) == 384) {
+        return sp_ecc_proj_add_point_384(P->x, P->y, P->z, Q->x, Q->y, Q->z,
+                                         R->x, R->y, R->z);
+    }
+#endif
+    return ECC_BAD_ARG_E;
+#endif
+}
+
+/* ### Point doubling in Jacobian coordinate system ###
+ *
+ * let us have a curve:                 y^2 = x^3 + a*x + b
+ * in Jacobian coordinates it becomes:  y^2 = x^3 + a*x*z^4 + b*z^6
+ *
+ * The doubling of P = (Xp, Yp, Zp) is given by R = (Xr, Yr, Zr) where:
+ * Xr = M^2 - 2*S
+ * Yr = M * (S - Xr) - 8*T
+ * Zr = 2 * Yp * Zp
+ *
+ * M = 3 * Xp^2 + a*Zp^4
+ * T = Yp^4
+ * S = 4 * Xp * Yp^2
+ *
+ * SPECIAL CASE: when a == 3 we can compute M as
+ * M = 3 * (Xp^2 - Zp^4) = 3 * (Xp + Zp^2) * (Xp - Zp^2)
+ */
+
+/**
+   Double an ECC point
+   P   The point to double
+   R   [out] The destination of the double
+   a   ECC curve parameter a
+   modulus  The modulus of the field the ECC curve is in
+   mp       The "b" value from montgomery_setup()
+   return   MP_OKAY on success
+*/
+int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a,
+                                       mp_int* modulus, mp_digit mp)
+{
+#ifndef WOLFSSL_SP_MATH
+#ifdef WOLFSSL_SMALL_STACK
+   mp_int* t1 = NULL;
+   mp_int* t2 = NULL;
+#ifdef ALT_ECC_SIZE
+   mp_int* rx = NULL;
+   mp_int* ry = NULL;
+   mp_int* rz = NULL;
+#endif
+#else
+   mp_int  t1[1], t2[1];
+#ifdef ALT_ECC_SIZE
+   mp_int  rx[1], ry[1], rz[1];
+#endif
+#endif
+   mp_int *x, *y, *z;
+   int    err;
+
+   if (P == NULL || R == NULL || modulus == NULL)
+       return ECC_BAD_ARG_E;
+
+#ifdef WOLFSSL_SMALL_STACK
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+   if (R->key != NULL) {
+       t1 = R->key->t1;
+       t2 = R->key->t2;
+   #ifdef ALT_ECC_SIZE
+       rx = R->key->x;
+       ry = R->key->y;
+       rz = R->key->z;
+   #endif
+   }
+   else
+#endif /* WOLFSSL_SMALL_STACK_CACHE */
+   {
+       t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       if (t1 == NULL || t2 == NULL) {
+           XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+           return MEMORY_E;
+       }
+    #ifdef ALT_ECC_SIZE
+       rx = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       ry = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       rz = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       if (rx == NULL || ry == NULL || rz == NULL) {
+           XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+           return MEMORY_E;
+       }
+    #endif
+    }
+#endif
+
+   if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
+#ifdef WOLFSSL_SMALL_STACK
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+    if (R->key == NULL)
+#endif
+    {
+    #ifdef ALT_ECC_SIZE
+       XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
+       XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
+       XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
+    #endif
+       XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+       XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+     }
+#endif
+      return err;
+   }
+
+/* If use ALT_ECC_SIZE we need to use local stack variable since
+   ecc_point x,y,z is reduced size */
+#ifdef ALT_ECC_SIZE
+   /* Use local stack variable */
+   x = rx;
+   y = ry;
+   z = rz;
+
+   if ((err = mp_init_multi(x, y, z, NULL, NULL, NULL)) != MP_OKAY) {
+       mp_clear(t1);
+       mp_clear(t2);
+    #ifdef WOLFSSL_SMALL_STACK
+    #ifdef WOLFSSL_SMALL_STACK_CACHE
+       if (R->key == NULL)
+    #endif
+       {
+       #ifdef ALT_ECC_SIZE
+          XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
+          XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
+          XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
+       #endif
+          XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+          XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+       }
+    #endif
+       return err;
+   }
+#else
+   /* Use destination directly */
+   x = R->x;
+   y = R->y;
+   z = R->z;
+#endif
+
+   if (err == MP_OKAY)
+       err = mp_copy(P->x, x);
+   if (err == MP_OKAY)
+       err = mp_copy(P->y, y);
+   if (err == MP_OKAY)
+       err = mp_copy(P->z, z);
+
+   /* T1 = Z * Z */
+   if (err == MP_OKAY)
+       err = mp_sqr(z, t1);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(t1, modulus, mp);
+
+   /* Z = Y * Z */
+   if (err == MP_OKAY)
+       err = mp_mul(z, y, z);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(z, modulus, mp);
+
+   /* Z = 2Z */
+   if (err == MP_OKAY)
+       err = mp_add(z, z, z);
+   if (err == MP_OKAY) {
+       if (mp_cmp(z, modulus) != MP_LT)
+           err = mp_sub(z, modulus, z);
+   }
+
+   /* Determine if curve "a" should be used in calc */
+#ifdef WOLFSSL_CUSTOM_CURVES
+   if (err == MP_OKAY) {
+      /* Use a and prime to determine if a == 3 */
+      err = mp_submod(modulus, a, modulus, t2);
+   }
+   if (err == MP_OKAY && mp_cmp_d(t2, 3) != MP_EQ) {
+      /* use "a" in calc */
+
+      /* T2 = T1 * T1 */
+      if (err == MP_OKAY)
+          err = mp_sqr(t1, t2);
+      if (err == MP_OKAY)
+          err = mp_montgomery_reduce(t2, modulus, mp);
+      /* T1 = T2 * a */
+      if (err == MP_OKAY)
+          err = mp_mulmod(t2, a, modulus, t1);
+      /* T2 = X * X */
+      if (err == MP_OKAY)
+          err = mp_sqr(x, t2);
+      if (err == MP_OKAY)
+          err = mp_montgomery_reduce(t2, modulus, mp);
+      /* T1 = T2 + T1 */
+      if (err == MP_OKAY)
+          err = mp_add(t1, t2, t1);
+      if (err == MP_OKAY) {
+         if (mp_cmp(t1, modulus) != MP_LT)
+            err = mp_sub(t1, modulus, t1);
+      }
+      /* T1 = T2 + T1 */
+      if (err == MP_OKAY)
+          err = mp_add(t1, t2, t1);
+      if (err == MP_OKAY) {
+          if (mp_cmp(t1, modulus) != MP_LT)
+              err = mp_sub(t1, modulus, t1);
+      }
+      /* T1 = T2 + T1 */
+      if (err == MP_OKAY)
+          err = mp_add(t1, t2, t1);
+      if (err == MP_OKAY) {
+         if (mp_cmp(t1, modulus) != MP_LT)
+            err = mp_sub(t1, modulus, t1);
+      }
+   }
+   else
+#endif /* WOLFSSL_CUSTOM_CURVES */
+   {
+      /* assumes "a" == 3 */
+      (void)a;
+
+      /* T2 = X - T1 */
+      if (err == MP_OKAY)
+          err = mp_sub(x, t1, t2);
+      if (err == MP_OKAY) {
+          if (mp_isneg(t2))
+              err = mp_add(t2, modulus, t2);
+      }
+      /* T1 = X + T1 */
+      if (err == MP_OKAY)
+          err = mp_add(t1, x, t1);
+      if (err == MP_OKAY) {
+          if (mp_cmp(t1, modulus) != MP_LT)
+              err = mp_sub(t1, modulus, t1);
+      }
+      /* T2 = T1 * T2 */
+      if (err == MP_OKAY)
+          err = mp_mul(t1, t2, t2);
+      if (err == MP_OKAY)
+          err = mp_montgomery_reduce(t2, modulus, mp);
+
+      /* T1 = 2T2 */
+      if (err == MP_OKAY)
+          err = mp_add(t2, t2, t1);
+      if (err == MP_OKAY) {
+          if (mp_cmp(t1, modulus) != MP_LT)
+              err = mp_sub(t1, modulus, t1);
+      }
+      /* T1 = T1 + T2 */
+      if (err == MP_OKAY)
+          err = mp_add(t1, t2, t1);
+      if (err == MP_OKAY) {
+          if (mp_cmp(t1, modulus) != MP_LT)
+              err = mp_sub(t1, modulus, t1);
+      }
+   }
+
+   /* Y = 2Y */
+   if (err == MP_OKAY)
+       err = mp_add(y, y, y);
+   if (err == MP_OKAY) {
+       if (mp_cmp(y, modulus) != MP_LT)
+           err = mp_sub(y, modulus, y);
+   }
+   /* Y = Y * Y */
+   if (err == MP_OKAY)
+       err = mp_sqr(y, y);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(y, modulus, mp);
+
+   /* T2 = Y * Y */
+   if (err == MP_OKAY)
+       err = mp_sqr(y, t2);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(t2, modulus, mp);
+
+   /* T2 = T2/2 */
+   if (err == MP_OKAY) {
+       if (mp_isodd(t2) == MP_YES)
+           err = mp_add(t2, modulus, t2);
+   }
+   if (err == MP_OKAY)
+       err = mp_div_2(t2, t2);
+
+   /* Y = Y * X */
+   if (err == MP_OKAY)
+       err = mp_mul(y, x, y);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(y, modulus, mp);
+
+   /* X = T1 * T1 */
+   if (err == MP_OKAY)
+       err = mp_sqr(t1, x);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(x, modulus, mp);
+
+   /* X = X - Y */
+   if (err == MP_OKAY)
+       err = mp_sub(x, y, x);
+   if (err == MP_OKAY) {
+       if (mp_isneg(x))
+           err = mp_add(x, modulus, x);
+   }
+   /* X = X - Y */
+   if (err == MP_OKAY)
+       err = mp_sub(x, y, x);
+   if (err == MP_OKAY) {
+       if (mp_isneg(x))
+           err = mp_add(x, modulus, x);
+   }
+
+   /* Y = Y - X */
+   if (err == MP_OKAY)
+       err = mp_sub(y, x, y);
+   if (err == MP_OKAY) {
+       if (mp_isneg(y))
+           err = mp_add(y, modulus, y);
+   }
+   /* Y = Y * T1 */
+   if (err == MP_OKAY)
+       err = mp_mul(y, t1, y);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(y, modulus, mp);
+
+   /* Y = Y - T2 */
+   if (err == MP_OKAY)
+       err = mp_sub(y, t2, y);
+   if (err == MP_OKAY) {
+       if (mp_isneg(y))
+           err = mp_add(y, modulus, y);
+   }
+
+#ifdef ALT_ECC_SIZE
+   if (err == MP_OKAY)
+       err = mp_copy(x, R->x);
+   if (err == MP_OKAY)
+       err = mp_copy(y, R->y);
+   if (err == MP_OKAY)
+       err = mp_copy(z, R->z);
+#endif
+
+   /* clean up */
+   mp_clear(t1);
+   mp_clear(t2);
+
+#ifdef WOLFSSL_SMALL_STACK
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+   if (R->key == NULL)
+#endif
+   {
+    #ifdef ALT_ECC_SIZE
+       XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
+       XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
+       XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
+    #endif
+       XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+       XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+    }
+#endif
+
+   return err;
+#else
+    if (P == NULL || R == NULL || modulus == NULL)
+        return ECC_BAD_ARG_E;
+
+    (void)a;
+    (void)mp;
+
+#ifndef WOLFSSL_SP_NO_256
+    if (mp_count_bits(modulus) == 256) {
+        return sp_ecc_proj_dbl_point_256(P->x, P->y, P->z, R->x, R->y, R->z);
+    }
+#endif
+#ifdef WOLFSSL_SP_384
+    if (mp_count_bits(modulus) == 384) {
+        return sp_ecc_proj_dbl_point_384(P->x, P->y, P->z, R->x, R->y, R->z);
+    }
+#endif
+    return ECC_BAD_ARG_E;
+#endif
+}
+
+
+/**
+  Map a projective Jacobian point back to affine space
+  P        [in/out] The point to map
+  modulus  The modulus of the field the ECC curve is in
+  mp       The "b" value from montgomery_setup()
+  ct       Operation should be constant time.
+  return   MP_OKAY on success
+*/
+int ecc_map_ex(ecc_point* P, mp_int* modulus, mp_digit mp, int ct)
+{
+#ifndef WOLFSSL_SP_MATH
+#ifdef WOLFSSL_SMALL_STACK
+   mp_int* t1 = NULL;
+   mp_int* t2 = NULL;
+#ifdef ALT_ECC_SIZE
+   mp_int* rx = NULL;
+   mp_int* ry = NULL;
+   mp_int* rz = NULL;
+#endif
+#else
+   mp_int  t1[1], t2[1];
+#ifdef ALT_ECC_SIZE
+   mp_int  rx[1], ry[1], rz[1];
+#endif
+#endif /* WOLFSSL_SMALL_STACK */
+   mp_int *x, *y, *z;
+   int    err;
+
+   (void)ct;
+
+   if (P == NULL || modulus == NULL)
+       return ECC_BAD_ARG_E;
+
+   /* special case for point at infinity */
+   if (mp_cmp_d(P->z, 0) == MP_EQ) {
+       err = mp_set(P->x, 0);
+       if (err == MP_OKAY)
+           err = mp_set(P->y, 0);
+       if (err == MP_OKAY)
+           err = mp_set(P->z, 1);
+       return err;
+   }
+
+#ifdef WOLFSSL_SMALL_STACK
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+   if (P->key != NULL) {
+       t1 = P->key->t1;
+       t2 = P->key->t2;
+   #ifdef ALT_ECC_SIZE
+       rx = P->key->x;
+       ry = P->key->y;
+       rz = P->key->z;
+   #endif
+   }
+   else
+#endif /* WOLFSSL_SMALL_STACK_CACHE */
+   {
+       t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       if (t1 == NULL || t2 == NULL) {
+           XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+           return MEMORY_E;
+       }
+#ifdef ALT_ECC_SIZE
+       rx = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       ry = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       rz = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+       if (rx == NULL || ry == NULL || rz == NULL) {
+           XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+           XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+           return MEMORY_E;
+       }
+#endif
+   }
+#endif /* WOLFSSL_SMALL_STACK */
+
+   if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
+#ifdef WOLFSSL_SMALL_STACK
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+      if (P->key == NULL)
+#endif
+      {
+      #ifdef ALT_ECC_SIZE
+         XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
+         XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
+         XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
+      #endif
+         XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+         XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+      }
+#endif
+      return MEMORY_E;
+   }
+
+#ifdef ALT_ECC_SIZE
+   /* Use local stack variable */
+   x = rx;
+   y = ry;
+   z = rz;
+
+   if ((err = mp_init_multi(x, y, z, NULL, NULL, NULL)) != MP_OKAY) {
+       goto done;
+   }
+
+   if (err == MP_OKAY)
+       err = mp_copy(P->x, x);
+   if (err == MP_OKAY)
+       err = mp_copy(P->y, y);
+   if (err == MP_OKAY)
+       err = mp_copy(P->z, z);
+
+   if (err != MP_OKAY) {
+      goto done;
+   }
+#else
+   /* Use destination directly */
+   x = P->x;
+   y = P->y;
+   z = P->z;
+#endif
+
+   /* get 1/z */
+   if (err == MP_OKAY) {
+#if defined(ECC_TIMING_RESISTANT) && defined(USE_FAST_MATH)
+       if (ct) {
+           err = mp_invmod_mont_ct(z, modulus, t1, mp);
+           if (err == MP_OKAY)
+               err = mp_montgomery_reduce(t1, modulus, mp);
+       }
+       else
+#endif
+       {
+           /* first map z back to normal */
+           err = mp_montgomery_reduce(z, modulus, mp);
+           if (err == MP_OKAY)
+               err = mp_invmod(z, modulus, t1);
+       }
+   }
+
+   /* get 1/z^2 and 1/z^3 */
+   if (err == MP_OKAY)
+       err = mp_sqr(t1, t2);
+   if (err == MP_OKAY)
+       err = mp_mod(t2, modulus, t2);
+   if (err == MP_OKAY)
+       err = mp_mul(t1, t2, t1);
+   if (err == MP_OKAY)
+       err = mp_mod(t1, modulus, t1);
+
+   /* multiply against x/y */
+   if (err == MP_OKAY)
+       err = mp_mul(x, t2, x);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(x, modulus, mp);
+   if (err == MP_OKAY)
+       err = mp_mul(y, t1, y);
+   if (err == MP_OKAY)
+       err = mp_montgomery_reduce(y, modulus, mp);
+
+   if (err == MP_OKAY)
+       err = mp_set(z, 1);
+
+#ifdef ALT_ECC_SIZE
+   /* return result */
+   if (err == MP_OKAY)
+      err = mp_copy(x, P->x);
+   if (err == MP_OKAY)
+      err = mp_copy(y, P->y);
+   if (err == MP_OKAY)
+      err = mp_copy(z, P->z);
+
+done:
+#endif
+
+   /* clean up */
+   mp_clear(t1);
+   mp_clear(t2);
+
+#ifdef WOLFSSL_SMALL_STACK
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+   if (P->key == NULL)
+#endif
+   {
+   #ifdef ALT_ECC_SIZE
+      XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
+      XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
+      XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
+   #endif
+      XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+      XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+   }
+#endif
+
+   return err;
+#else
+    if (P == NULL || modulus == NULL)
+        return ECC_BAD_ARG_E;
+
+    (void)mp;
+
+#ifndef WOLFSSL_SP_NO_256
+    if (mp_count_bits(modulus) == 256) {
+        return sp_ecc_map_256(P->x, P->y, P->z);
+    }
+#endif
+#ifdef WOLFSSL_SP_384
+    if (mp_count_bits(modulus) == 384) {
+        return sp_ecc_map_384(P->x, P->y, P->z);
+    }
+#endif
+    return ECC_BAD_ARG_E;
+#endif
+}
+
+int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp)
+{
+    return ecc_map_ex(P, modulus, mp, 0);
+}
+#endif /* !WOLFSSL_SP_MATH || WOLFSSL_PUBLIC_ECC_ADD_DBL */
+
+#if !defined(FREESCALE_LTC_ECC) && !defined(WOLFSSL_STM32_PKA)
+
+#if !defined(FP_ECC) || !defined(WOLFSSL_SP_MATH)
+/**
+   Perform a point multiplication
+   k    The scalar to multiply by
+   G    The base point
+   R    [out] Destination for kG
+   a    ECC curve parameter a
+   modulus  The modulus of the field the ECC curve is in
+   map      Boolean whether to map back to affine or not
+                (1==map, 0 == leave in projective)
+   return MP_OKAY on success
+*/
+#ifdef FP_ECC
+static int normal_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R,
+                  mp_int* a, mp_int* modulus, int map,
+                  void* heap)
+#else
+int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R,
+                  mp_int* a, mp_int* modulus, int map,
+                  void* heap)
+#endif
+{
+#ifndef WOLFSSL_SP_MATH
+#ifndef ECC_TIMING_RESISTANT
+   /* size of sliding window, don't change this! */
+   #define WINSIZE  4
+   #define M_POINTS 8
+   int           first = 1, bitbuf = 0, bitcpy = 0, j;
+#elif defined(WC_NO_CACHE_RESISTANT)
+   #define M_POINTS 4
+#else
+   #define M_POINTS 5
+#endif
+
+   ecc_point     *tG, *M[M_POINTS];
+   int           i, err;
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+   ecc_key       key;
+#endif
+#ifdef WOLFSSL_SMALL_STACK
+   mp_int*       mu = NULL;
+#else
+   mp_int        mu[1];
+#endif
+   mp_digit      mp;
+   mp_digit      buf;
+   int           bitcnt = 0, mode = 0, digidx = 0;
+
+   if (k == NULL || G == NULL || R == NULL || modulus == NULL) {
+       return ECC_BAD_ARG_E;
+   }
+
+   /* init variables */
+   tG = NULL;
+   XMEMSET(M, 0, sizeof(M));
+#ifdef WOLFSSL_SMALL_STACK
+   mu = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
+   if (mu == NULL)
+       return MEMORY_E;
+#endif
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+   key.t1 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
+   key.t2 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
+#ifdef ALT_ECC_SIZE
+   key.x = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
+   key.y = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
+   key.z = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
+#endif
+   if (key.t1 == NULL || key.t2 == NULL
+#ifdef ALT_ECC_SIZE
+      || key.x == NULL || key.y == NULL || key.z == NULL
+#endif
+   ) {
+#ifdef ALT_ECC_SIZE
+       XFREE(key.z, heap, DYNAMIC_TYPE_ECC);
+       XFREE(key.y, heap, DYNAMIC_TYPE_ECC);
+       XFREE(key.x, heap, DYNAMIC_TYPE_ECC);
+#endif
+       XFREE(key.t2, heap, DYNAMIC_TYPE_ECC);
+       XFREE(key.t1, heap, DYNAMIC_TYPE_ECC);
+       XFREE(mu, heap, DYNAMIC_TYPE_ECC);
+       return MEMORY_E;
+   }
+#endif /* WOLFSSL_SMALL_STACK_CACHE */
+
+   /* init montgomery reduction */
+   if ((err = mp_montgomery_setup(modulus, &mp)) != MP_OKAY) {
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+#ifdef ALT_ECC_SIZE
+       XFREE(key.z, heap, DYNAMIC_TYPE_ECC);
+       XFREE(key.y, heap, DYNAMIC_TYPE_ECC);
+       XFREE(key.x, heap, DYNAMIC_TYPE_ECC);
+#endif
+       XFREE(key.t2, heap, DYNAMIC_TYPE_ECC);
+       XFREE(key.t1, heap, DYNAMIC_TYPE_ECC);
+#endif /* WOLFSSL_SMALL_STACK_CACHE */
+#ifdef WOLFSSL_SMALL_STACK
+       XFREE(mu, heap, DYNAMIC_TYPE_ECC);
+#endif
+       return err;
+   }
+
+   if ((err = mp_init(mu)) != MP_OKAY) {
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+#ifdef ALT_ECC_SIZE
+       XFREE(key.z, heap, DYNAMIC_TYPE_ECC);
+       XFREE(key.y, heap, DYNAMIC_TYPE_ECC);
+       XFREE(key.x, heap, DYNAMIC_TYPE_ECC);
+#endif
+       XFREE(key.t2, heap, DYNAMIC_TYPE_ECC);
+       XFREE(key.t1, heap, DYNAMIC_TYPE_ECC);
+#endif /* WOLFSSL_SMALL_STACK_CACHE */
+#ifdef WOLFSSL_SMALL_STACK
+       XFREE(mu, heap, DYNAMIC_TYPE_ECC);
+#endif
+       return err;
+   }
+   if ((err = mp_montgomery_calc_normalization(mu, modulus)) != MP_OKAY) {
+       mp_clear(mu);
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+#ifdef ALT_ECC_SIZE
+       XFREE(key.z, heap, DYNAMIC_TYPE_ECC);
+       XFREE(key.y, heap, DYNAMIC_TYPE_ECC);
+       XFREE(key.x, heap, DYNAMIC_TYPE_ECC);
+#endif
+       XFREE(key.t2, heap, DYNAMIC_TYPE_ECC);
+       XFREE(key.t1, heap, DYNAMIC_TYPE_ECC);
+#endif /* WOLFSSL_SMALL_STACK_CACHE */
+#ifdef WOLFSSL_SMALL_STACK
+       XFREE(mu, heap, DYNAMIC_TYPE_ECC);
+#endif
+       return err;
+   }
+
+  /* alloc ram for window temps */
+  for (i = 0; i < M_POINTS; i++) {
+      M[i] = wc_ecc_new_point_h(heap);
+      if (M[i] == NULL) {
+         mp_clear(mu);
+         err = MEMORY_E; goto exit;
+      }
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+      M[i]->key = &key;
+#endif
+  }
+
+   /* make a copy of G in case R==G */
+   tG = wc_ecc_new_point_h(heap);
+   if (tG == NULL)
+       err = MEMORY_E;
+
+   /* tG = G  and convert to montgomery */
+   if (err == MP_OKAY) {
+       if (mp_cmp_d(mu, 1) == MP_EQ) {
+           err = mp_copy(G->x, tG->x);
+           if (err == MP_OKAY)
+               err = mp_copy(G->y, tG->y);
+           if (err == MP_OKAY)
+               err = mp_copy(G->z, tG->z);
+       } else {
+           err = mp_mulmod(G->x, mu, modulus, tG->x);
+           if (err == MP_OKAY)
+               err = mp_mulmod(G->y, mu, modulus, tG->y);
+           if (err == MP_OKAY)
+               err = mp_mulmod(G->z, mu, modulus, tG->z);
+       }
+   }
+
+   /* done with mu */
+   mp_clear(mu);
+
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+   R->key = &key;
+#endif
+#ifndef ECC_TIMING_RESISTANT
+
+   /* calc the M tab, which holds kG for k==8..15 */
+   /* M[0] == 8G */
+   if (err == MP_OKAY)
+       err = ecc_projective_dbl_point(tG, M[0], a, modulus, mp);
+   if (err == MP_OKAY)
+       err = ecc_projective_dbl_point(M[0], M[0], a, modulus, mp);
+   if (err == MP_OKAY)
+       err = ecc_projective_dbl_point(M[0], M[0], a, modulus, mp);
+
+   /* now find (8+k)G for k=1..7 */
+   if (err == MP_OKAY)
+       for (j = 9; j < 16; j++) {
+           err = ecc_projective_add_point(M[j-9], tG, M[j-M_POINTS], a, modulus,
+                                                                            mp);
+           if (err != MP_OKAY) break;
+       }
+
+   /* setup sliding window */
+   if (err == MP_OKAY) {
+       mode   = 0;
+       bitcnt = 1;
+       buf    = 0;
+       digidx = get_digit_count(k) - 1;
+       bitcpy = bitbuf = 0;
+       first  = 1;
+
+       /* perform ops */
+       for (;;) {
+           /* grab next digit as required */
+           if (--bitcnt == 0) {
+               if (digidx == -1) {
+                   break;
+               }
+               buf    = get_digit(k, digidx);
+               bitcnt = (int) DIGIT_BIT;
+               --digidx;
+           }
+
+           /* grab the next msb from the ltiplicand */
+           i = (int)(buf >> (DIGIT_BIT - 1)) & 1;
+           buf <<= 1;
+
+           /* skip leading zero bits */
+           if (mode == 0 && i == 0)
+               continue;
+
+           /* if the bit is zero and mode == 1 then we double */
+           if (mode == 1 && i == 0) {
+               err = ecc_projective_dbl_point(R, R, a, modulus, mp);
+               if (err != MP_OKAY) break;
+               continue;
+           }
+
+           /* else we add it to the window */
+           bitbuf |= (i << (WINSIZE - ++bitcpy));
+           mode = 2;
+
+           if (bitcpy == WINSIZE) {
+               /* if this is the first window we do a simple copy */
+               if (first == 1) {
+                   /* R = kG [k = first window] */
+                   err = mp_copy(M[bitbuf-M_POINTS]->x, R->x);
+                   if (err != MP_OKAY) break;
+
+                   err = mp_copy(M[bitbuf-M_POINTS]->y, R->y);
+                   if (err != MP_OKAY) break;
+
+                   err = mp_copy(M[bitbuf-M_POINTS]->z, R->z);
+                   first = 0;
+               } else {
+                   /* normal window */
+                   /* ok window is filled so double as required and add  */
+                   /* double first */
+                   for (j = 0; j < WINSIZE; j++) {
+                       err = ecc_projective_dbl_point(R, R, a, modulus, mp);
+                       if (err != MP_OKAY) break;
+                   }
+                   if (err != MP_OKAY) break;  /* out of first for(;;) */
+
+                   /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */
+                   err = ecc_projective_add_point(R, M[bitbuf-M_POINTS], R, a,
+                                                                   modulus, mp);
+               }
+               if (err != MP_OKAY) break;
+               /* empty window and reset */
+               bitcpy = bitbuf = 0;
+               mode = 1;
+           }
+       }
+   }
+
+   /* if bits remain then double/add */
+   if (err == MP_OKAY) {
+       if (mode == 2 && bitcpy > 0) {
+           /* double then add */
+           for (j = 0; j < bitcpy; j++) {
+               /* only double if we have had at least one add first */
+               if (first == 0) {
+                   err = ecc_projective_dbl_point(R, R, a, modulus, mp);
+                   if (err != MP_OKAY) break;
+               }
+
+               bitbuf <<= 1;
+               if ((bitbuf & (1 << WINSIZE)) != 0) {
+                   if (first == 1) {
+                       /* first add, so copy */
+                       err = mp_copy(tG->x, R->x);
+                       if (err != MP_OKAY) break;
+
+                       err = mp_copy(tG->y, R->y);
+                       if (err != MP_OKAY) break;
+
+                       err = mp_copy(tG->z, R->z);
+                       if (err != MP_OKAY) break;
+                       first = 0;
+                   } else {
+                       /* then add */
+                       err = ecc_projective_add_point(R, tG, R, a, modulus, mp);
+                       if (err != MP_OKAY) break;
+                   }
+               }
+           }
+       }
+   }
+
+   #undef WINSIZE
+
+#else /* ECC_TIMING_RESISTANT */
+
+   /* calc the M tab */
+   /* M[0] == G */
+   if (err == MP_OKAY)
+       err = mp_copy(tG->x, M[0]->x);
+   if (err == MP_OKAY)
+       err = mp_copy(tG->y, M[0]->y);
+   if (err == MP_OKAY)
+       err = mp_copy(tG->z, M[0]->z);
+
+   /* M[1] == 2G */
+   if (err == MP_OKAY)
+       err = ecc_projective_dbl_point(tG, M[1], a, modulus, mp);
+#ifdef WC_NO_CACHE_RESISTANT
+   if (err == MP_OKAY)
+       err = wc_ecc_copy_point(M[0], M[2]);
+#else
+   if (err == MP_OKAY)
+       err = wc_ecc_copy_point(M[0], M[3]);
+   if (err == MP_OKAY)
+       err = wc_ecc_copy_point(M[1], M[4]);
+#endif
+
+   /* setup sliding window */
+   mode   = 0;
+   bitcnt = 1;
+   buf    = 0;
+   digidx = get_digit_count(modulus) - 1;
+   /* The order MAY be 1 bit longer than the modulus. */
+   digidx += (modulus->dp[digidx] >> (DIGIT_BIT-1));
+
+   /* perform ops */
+   if (err == MP_OKAY) {
+       for (;;) {
+           /* grab next digit as required */
+           if (--bitcnt == 0) {
+               if (digidx == -1) {
+                   break;
+               }
+               buf = get_digit(k, digidx);
+               bitcnt = (int)DIGIT_BIT;
+               --digidx;
+           }
+
+           /* grab the next msb from the multiplicand */
+           i = (buf >> (DIGIT_BIT - 1)) & 1;
+           buf <<= 1;
+
+#ifdef WC_NO_CACHE_RESISTANT
+           if (mode == 0) {
+               /* timing resistant - dummy operations */
+               if (err == MP_OKAY)
+                   err = ecc_projective_add_point(M[1], M[2], M[2], a, modulus,
+                                                  mp);
+               if (err == MP_OKAY)
+                   err = ecc_projective_dbl_point(M[2], M[3], a, modulus, mp);
+           }
+           else {
+               if (err == MP_OKAY)
+                   err = ecc_projective_add_point(M[0], M[1], M[i^1], a,
+                                                  modulus, mp);
+               if (err == MP_OKAY)
+                   err = ecc_projective_dbl_point(M[i], M[i], a, modulus, mp);
+           }
+#else
+           if (err == MP_OKAY)
+               err = ecc_projective_add_point(M[0], M[1], M[2], a, modulus, mp);
+           if (err == MP_OKAY)
+               err = mp_cond_copy(M[2]->x, i, M[0]->x);
+           if (err == MP_OKAY)
+               err = mp_cond_copy(M[2]->y, i, M[0]->y);
+           if (err == MP_OKAY)
+               err = mp_cond_copy(M[2]->z, i, M[0]->z);
+           if (err == MP_OKAY)
+               err = mp_cond_copy(M[2]->x, i ^ 1, M[1]->x);
+           if (err == MP_OKAY)
+               err = mp_cond_copy(M[2]->y, i ^ 1, M[1]->y);
+           if (err == MP_OKAY)
+               err = mp_cond_copy(M[2]->z, i ^ 1, M[1]->z);
+
+           if (err == MP_OKAY)
+               err = mp_cond_copy(M[0]->x, i ^ 1, M[2]->x);
+           if (err == MP_OKAY)
+               err = mp_cond_copy(M[0]->y, i ^ 1, M[2]->y);
+           if (err == MP_OKAY)
+               err = mp_cond_copy(M[0]->z, i ^ 1, M[2]->z);
+           if (err == MP_OKAY)
+               err = mp_cond_copy(M[1]->x, i, M[2]->x);
+           if (err == MP_OKAY)
+               err = mp_cond_copy(M[1]->y, i, M[2]->y);
+           if (err == MP_OKAY)
+               err = mp_cond_copy(M[1]->z, i, M[2]->z);
+
+           if (err == MP_OKAY)
+               err = ecc_projective_dbl_point(M[2], M[2], a, modulus, mp);
+           if (err == MP_OKAY)
+               err = mp_cond_copy(M[2]->x, i ^ 1, M[0]->x);
+           if (err == MP_OKAY)
+               err = mp_cond_copy(M[2]->y, i ^ 1, M[0]->y);
+           if (err == MP_OKAY)
+               err = mp_cond_copy(M[2]->z, i ^ 1, M[0]->z);
+           if (err == MP_OKAY)
+               err = mp_cond_copy(M[2]->x, i, M[1]->x);
+           if (err == MP_OKAY)
+               err = mp_cond_copy(M[2]->y, i, M[1]->y);
+           if (err == MP_OKAY)
+               err = mp_cond_copy(M[2]->z, i, M[1]->z);
+
+           if (err == MP_OKAY)
+               err = mp_cond_copy(M[3]->x, (mode ^ 1) & i, M[0]->x);
+           if (err == MP_OKAY)
+               err = mp_cond_copy(M[3]->y, (mode ^ 1) & i, M[0]->y);
+           if (err == MP_OKAY)
+               err = mp_cond_copy(M[3]->z, (mode ^ 1) & i, M[0]->z);
+           if (err == MP_OKAY)
+               err = mp_cond_copy(M[4]->x, (mode ^ 1) & i, M[1]->x);
+           if (err == MP_OKAY)
+               err = mp_cond_copy(M[4]->y, (mode ^ 1) & i, M[1]->y);
+           if (err == MP_OKAY)
+               err = mp_cond_copy(M[4]->z, (mode ^ 1) & i, M[1]->z);
+#endif /* WC_NO_CACHE_RESISTANT */
+
+           if (err != MP_OKAY)
+               break;
+
+           mode |= i;
+       } /* end for */
+   }
+
+   /* copy result out */
+   if (err == MP_OKAY)
+       err = mp_copy(M[0]->x, R->x);
+   if (err == MP_OKAY)
+       err = mp_copy(M[0]->y, R->y);
+   if (err == MP_OKAY)
+       err = mp_copy(M[0]->z, R->z);
+
+#endif /* ECC_TIMING_RESISTANT */
+
+   /* map R back from projective space */
+   if (err == MP_OKAY && map)
+       err = ecc_map(R, modulus, mp);
+
+exit:
+
+   /* done */
+   wc_ecc_del_point_h(tG, heap);
+   for (i = 0; i < M_POINTS; i++) {
+       wc_ecc_del_point_h(M[i], heap);
+   }
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+   R->key = NULL;
+#ifdef ALT_ECC_SIZE
+   XFREE(key.z, heap, DYNAMIC_TYPE_ECC);
+   XFREE(key.y, heap, DYNAMIC_TYPE_ECC);
+   XFREE(key.x, heap, DYNAMIC_TYPE_ECC);
+#endif
+   XFREE(key.t2, heap, DYNAMIC_TYPE_ECC);
+   XFREE(key.t1, heap, DYNAMIC_TYPE_ECC);
+#endif /* WOLFSSL_SMALL_STACK_CACHE */
+#ifdef WOLFSSL_SMALL_STACK
+   XFREE(mu, heap, DYNAMIC_TYPE_ECC);
+#endif
+
+   return err;
+#else
+   if (k == NULL || G == NULL || R == NULL || modulus == NULL) {
+       return ECC_BAD_ARG_E;
+   }
+
+   (void)a;
+
+#ifndef WOLFSSL_SP_NO_256
+   if (mp_count_bits(modulus) == 256) {
+       return sp_ecc_mulmod_256(k, G, R, map, heap);
+   }
+#endif
+#ifdef WOLFSSL_SP_384
+   if (mp_count_bits(modulus) == 384) {
+       return sp_ecc_mulmod_384(k, G, R, map, heap);
+   }
+#endif
+   return ECC_BAD_ARG_E;
+#endif
+}
+
+#endif /* !FP_ECC || !WOLFSSL_SP_MATH */
+
+#endif /* !FREESCALE_LTC_ECC && !WOLFSSL_STM32_PKA */
+
+/** ECC Fixed Point mulmod global
+    k        The multiplicand
+    G        Base point to multiply
+    R        [out] Destination of product
+    a        ECC curve parameter a
+    modulus  The modulus for the curve
+    map      [boolean] If non-zero maps the point back to affine coordinates,
+             otherwise it's left in jacobian-montgomery form
+    return MP_OKAY if successful
+*/
+int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a,
+                  mp_int* modulus, int map)
+{
+    return wc_ecc_mulmod_ex(k, G, R, a, modulus, map, NULL);
+}
+
+#endif /* !WOLFSSL_ATECC508A */
+
+/**
+ * use a heap hint when creating new ecc_point
+ * return an allocated point on success or NULL on failure
+ */
+ecc_point* wc_ecc_new_point_h(void* heap)
+{
+   ecc_point* p;
+
+   (void)heap;
+
+   p = (ecc_point*)XMALLOC(sizeof(ecc_point), heap, DYNAMIC_TYPE_ECC);
+   if (p == NULL) {
+      return NULL;
+   }
+   XMEMSET(p, 0, sizeof(ecc_point));
+
+#ifndef ALT_ECC_SIZE
+   if (mp_init_multi(p->x, p->y, p->z, NULL, NULL, NULL) != MP_OKAY) {
+      XFREE(p, heap, DYNAMIC_TYPE_ECC);
+      return NULL;
+   }
+#else
+   p->x = (mp_int*)&p->xyz[0];
+   p->y = (mp_int*)&p->xyz[1];
+   p->z = (mp_int*)&p->xyz[2];
+   alt_fp_init(p->x);
+   alt_fp_init(p->y);
+   alt_fp_init(p->z);
+#endif
+
+   return p;
+}
+
+
+/**
+   Allocate a new ECC point
+   return A newly allocated point or NULL on error
+*/
+ecc_point* wc_ecc_new_point(void)
+{
+  return wc_ecc_new_point_h(NULL);
+}
+
+
+void wc_ecc_del_point_h(ecc_point* p, void* heap)
+{
+   /* prevents free'ing null arguments */
+   if (p != NULL) {
+      mp_clear(p->x);
+      mp_clear(p->y);
+      mp_clear(p->z);
+      XFREE(p, heap, DYNAMIC_TYPE_ECC);
+   }
+   (void)heap;
+}
+
+
+/** Free an ECC point from memory
+  p   The point to free
+*/
+void wc_ecc_del_point(ecc_point* p)
+{
+    wc_ecc_del_point_h(p, NULL);
+}
+
+
+/** Copy the value of a point to an other one
+  p    The point to copy
+  r    The created point
+*/
+int wc_ecc_copy_point(ecc_point* p, ecc_point *r)
+{
+    int ret;
+
+    /* prevents null arguments */
+    if (p == NULL || r == NULL)
+        return ECC_BAD_ARG_E;
+
+    ret = mp_copy(p->x, r->x);
+    if (ret != MP_OKAY)
+        return ret;
+    ret = mp_copy(p->y, r->y);
+    if (ret != MP_OKAY)
+        return ret;
+    ret = mp_copy(p->z, r->z);
+    if (ret != MP_OKAY)
+        return ret;
+
+    return MP_OKAY;
+}
+
+/** Compare the value of a point with an other one
+ a    The point to compare
+ b    The other point to compare
+
+ return MP_EQ if equal, MP_LT/MP_GT if not, < 0 in case of error
+ */
+int wc_ecc_cmp_point(ecc_point* a, ecc_point *b)
+{
+    int ret;
+
+    /* prevents null arguments */
+    if (a == NULL || b == NULL)
+        return BAD_FUNC_ARG;
+
+    ret = mp_cmp(a->x, b->x);
+    if (ret != MP_EQ)
+        return ret;
+    ret = mp_cmp(a->y, b->y);
+    if (ret != MP_EQ)
+        return ret;
+    ret = mp_cmp(a->z, b->z);
+    if (ret != MP_EQ)
+        return ret;
+
+    return MP_EQ;
+}
+
+
+/** Returns whether an ECC idx is valid or not
+  n      The idx number to check
+  return 1 if valid, 0 if not
+*/
+int wc_ecc_is_valid_idx(int n)
+{
+   int x;
+
+   for (x = 0; ecc_sets[x].size != 0; x++)
+       ;
+   /* -1 is a valid index --- indicating that the domain params
+      were supplied by the user */
+   if ((n >= ECC_CUSTOM_IDX) && (n < x)) {
+      return 1;
+   }
+
+   return 0;
+}
+
+int wc_ecc_get_curve_idx(int curve_id)
+{
+    int curve_idx;
+    for (curve_idx = 0; ecc_sets[curve_idx].size != 0; curve_idx++) {
+        if (curve_id == ecc_sets[curve_idx].id)
+            break;
+    }
+    if (ecc_sets[curve_idx].size == 0) {
+        return ECC_CURVE_INVALID;
+    }
+    return curve_idx;
+}
+
+int wc_ecc_get_curve_id(int curve_idx)
+{
+    if (wc_ecc_is_valid_idx(curve_idx)) {
+        return ecc_sets[curve_idx].id;
+    }
+    return ECC_CURVE_INVALID;
+}
+
+/* Returns the curve size that corresponds to a given ecc_curve_id identifier
+ *
+ * id      curve id, from ecc_curve_id enum in ecc.h
+ * return  curve size, from ecc_sets[] on success, negative on error
+ */
+int wc_ecc_get_curve_size_from_id(int curve_id)
+{
+    int curve_idx = wc_ecc_get_curve_idx(curve_id);
+    if (curve_idx == ECC_CURVE_INVALID)
+        return ECC_BAD_ARG_E;
+    return ecc_sets[curve_idx].size;
+}
+
+/* Returns the curve index that corresponds to a given curve name in
+ * ecc_sets[] of ecc.c
+ *
+ * name    curve name, from ecc_sets[].name in ecc.c
+ * return  curve index in ecc_sets[] on success, negative on error
+ */
+int wc_ecc_get_curve_idx_from_name(const char* curveName)
+{
+    int curve_idx;
+    word32 len;
+
+    if (curveName == NULL)
+        return BAD_FUNC_ARG;
+
+    len = (word32)XSTRLEN(curveName);
+
+    for (curve_idx = 0; ecc_sets[curve_idx].size != 0; curve_idx++) {
+        if (
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            ecc_sets[curve_idx].name &&
+        #endif
+                XSTRNCASECMP(ecc_sets[curve_idx].name, curveName, len) == 0) {
+            break;
+        }
+    }
+    if (ecc_sets[curve_idx].size == 0) {
+        WOLFSSL_MSG("ecc_set curve name not found");
+        return ECC_CURVE_INVALID;
+    }
+    return curve_idx;
+}
+
+/* Returns the curve size that corresponds to a given curve name,
+ * as listed in ecc_sets[] of ecc.c.
+ *
+ * name    curve name, from ecc_sets[].name in ecc.c
+ * return  curve size, from ecc_sets[] on success, negative on error
+ */
+int wc_ecc_get_curve_size_from_name(const char* curveName)
+{
+    int curve_idx;
+
+    if (curveName == NULL)
+        return BAD_FUNC_ARG;
+
+    curve_idx = wc_ecc_get_curve_idx_from_name(curveName);
+    if (curve_idx < 0)
+        return curve_idx;
+
+    return ecc_sets[curve_idx].size;
+}
+
+/* Returns the curve id that corresponds to a given curve name,
+ * as listed in ecc_sets[] of ecc.c.
+ *
+ * name   curve name, from ecc_sets[].name in ecc.c
+ * return curve id, from ecc_sets[] on success, negative on error
+ */
+int wc_ecc_get_curve_id_from_name(const char* curveName)
+{
+    int curve_idx;
+
+    if (curveName == NULL)
+        return BAD_FUNC_ARG;
+
+    curve_idx = wc_ecc_get_curve_idx_from_name(curveName);
+    if (curve_idx < 0)
+        return curve_idx;
+
+    return ecc_sets[curve_idx].id;
+}
+
+/* Compares a curve parameter (hex, from ecc_sets[]) to given input
+ * parameter for equality.
+ * encType is WC_TYPE_UNSIGNED_BIN or WC_TYPE_HEX_STR
+ * Returns MP_EQ on success, negative on error */
+static int wc_ecc_cmp_param(const char* curveParam,
+                            const byte* param, word32 paramSz, int encType)
+{
+    int err = MP_OKAY;
+#ifdef WOLFSSL_SMALL_STACK
+    mp_int* a = NULL;
+    mp_int* b = NULL;
+#else
+    mp_int  a[1], b[1];
+#endif
+
+    if (param == NULL || curveParam == NULL)
+        return BAD_FUNC_ARG;
+
+    if (encType == WC_TYPE_HEX_STR)
+        return XSTRNCMP(curveParam, (char*) param, paramSz);
+
+#ifdef WOLFSSL_SMALL_STACK
+    a = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+    if (a == NULL)
+        return MEMORY_E;
+    b = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+    if (b == NULL) {
+        XFREE(a, NULL, DYNAMIC_TYPE_ECC);
+        return MEMORY_E;
+    }
+#endif
+
+    if ((err = mp_init_multi(a, b, NULL, NULL, NULL, NULL)) != MP_OKAY) {
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(a, NULL, DYNAMIC_TYPE_ECC);
+        XFREE(b, NULL, DYNAMIC_TYPE_ECC);
+    #endif
+        return err;
+    }
+
+    if (err == MP_OKAY) {
+        err = mp_read_unsigned_bin(a, param, paramSz);
+    }
+    if (err == MP_OKAY)
+        err = mp_read_radix(b, curveParam, MP_RADIX_HEX);
+
+    if (err == MP_OKAY) {
+        if (mp_cmp(a, b) != MP_EQ) {
+            err = -1;
+        } else {
+            err = MP_EQ;
+        }
+    }
+
+    mp_clear(a);
+    mp_clear(b);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(b, NULL, DYNAMIC_TYPE_ECC);
+    XFREE(a, NULL, DYNAMIC_TYPE_ECC);
+#endif
+
+    return err;
+}
+
+/* Returns the curve id in ecc_sets[] that corresponds to a given set of
+ * curve parameters.
+ *
+ * fieldSize  the field size in bits
+ * prime      prime of the finite field
+ * primeSz    size of prime in octets
+ * Af         first coefficient a of the curve
+ * AfSz       size of Af in octets
+ * Bf         second coefficient b of the curve
+ * BfSz       size of Bf in octets
+ * order      curve order
+ * orderSz    size of curve in octets
+ * Gx         affine x coordinate of base point
+ * GxSz       size of Gx in octets
+ * Gy         affine y coordinate of base point
+ * GySz       size of Gy in octets
+ * cofactor   curve cofactor
+ *
+ * return curve id, from ecc_sets[] on success, negative on error
+ */
+int wc_ecc_get_curve_id_from_params(int fieldSize,
+        const byte* prime, word32 primeSz, const byte* Af, word32 AfSz,
+        const byte* Bf, word32 BfSz, const byte* order, word32 orderSz,
+        const byte* Gx, word32 GxSz, const byte* Gy, word32 GySz, int cofactor)
+{
+    int idx;
+    int curveSz;
+
+    if (prime == NULL || Af == NULL || Bf == NULL || order == NULL ||
+        Gx == NULL || Gy == NULL)
+        return BAD_FUNC_ARG;
+
+    curveSz = (fieldSize + 1) / 8;    /* round up */
+
+    for (idx = 0; ecc_sets[idx].size != 0; idx++) {
+        if (curveSz == ecc_sets[idx].size) {
+            if ((wc_ecc_cmp_param(ecc_sets[idx].prime, prime,
+                            primeSz, WC_TYPE_UNSIGNED_BIN) == MP_EQ) &&
+                (wc_ecc_cmp_param(ecc_sets[idx].Af, Af, AfSz,
+                                  WC_TYPE_UNSIGNED_BIN) == MP_EQ) &&
+                (wc_ecc_cmp_param(ecc_sets[idx].Bf, Bf, BfSz,
+                                  WC_TYPE_UNSIGNED_BIN) == MP_EQ) &&
+                (wc_ecc_cmp_param(ecc_sets[idx].order, order,
+                                  orderSz, WC_TYPE_UNSIGNED_BIN) == MP_EQ) &&
+                (wc_ecc_cmp_param(ecc_sets[idx].Gx, Gx, GxSz,
+                                  WC_TYPE_UNSIGNED_BIN) == MP_EQ) &&
+                (wc_ecc_cmp_param(ecc_sets[idx].Gy, Gy, GySz,
+                                  WC_TYPE_UNSIGNED_BIN) == MP_EQ) &&
+                (cofactor == ecc_sets[idx].cofactor)) {
+                    break;
+            }
+        }
+    }
+
+    if (ecc_sets[idx].size == 0)
+        return ECC_CURVE_INVALID;
+
+    return ecc_sets[idx].id;
+}
+
+/* Returns the curve id in ecc_sets[] that corresponds
+ * to a given domain parameters pointer.
+ *
+ * dp   domain parameters pointer
+ *
+ * return curve id, from ecc_sets[] on success, negative on error
+ */
+int wc_ecc_get_curve_id_from_dp_params(const ecc_set_type* dp)
+{
+    int idx;
+
+    if (dp == NULL
+    #ifndef WOLFSSL_ECC_CURVE_STATIC
+         || dp->prime == NULL ||  dp->Af == NULL ||
+        dp->Bf == NULL || dp->order == NULL || dp->Gx == NULL || dp->Gy == NULL
+    #endif
+    ) {
+        return BAD_FUNC_ARG;
+    }
+
+    for (idx = 0; ecc_sets[idx].size != 0; idx++) {
+        if (dp->size == ecc_sets[idx].size) {
+            if ((wc_ecc_cmp_param(ecc_sets[idx].prime, (const byte*)dp->prime,
+                    (word32)XSTRLEN(dp->prime), WC_TYPE_HEX_STR) == MP_EQ) &&
+                (wc_ecc_cmp_param(ecc_sets[idx].Af, (const byte*)dp->Af,
+                    (word32)XSTRLEN(dp->Af),WC_TYPE_HEX_STR) == MP_EQ) &&
+                (wc_ecc_cmp_param(ecc_sets[idx].Bf, (const byte*)dp->Bf,
+                    (word32)XSTRLEN(dp->Bf),WC_TYPE_HEX_STR) == MP_EQ) &&
+                (wc_ecc_cmp_param(ecc_sets[idx].order, (const byte*)dp->order,
+                    (word32)XSTRLEN(dp->order),WC_TYPE_HEX_STR) == MP_EQ) &&
+                (wc_ecc_cmp_param(ecc_sets[idx].Gx, (const byte*)dp->Gx,
+                    (word32)XSTRLEN(dp->Gx),WC_TYPE_HEX_STR) == MP_EQ) &&
+                (wc_ecc_cmp_param(ecc_sets[idx].Gy, (const byte*)dp->Gy,
+                    (word32)XSTRLEN(dp->Gy),WC_TYPE_HEX_STR) == MP_EQ) &&
+                (dp->cofactor == ecc_sets[idx].cofactor)) {
+                    break;
+            }
+        }
+    }
+
+    if (ecc_sets[idx].size == 0)
+        return ECC_CURVE_INVALID;
+
+    return ecc_sets[idx].id;
+}
+
+/* Returns the curve id that corresponds to a given OID,
+ * as listed in ecc_sets[] of ecc.c.
+ *
+ * oid   OID, from ecc_sets[].name in ecc.c
+ * len   OID len, from ecc_sets[].name in ecc.c
+ * return curve id, from ecc_sets[] on success, negative on error
+ */
+int wc_ecc_get_curve_id_from_oid(const byte* oid, word32 len)
+{
+    int curve_idx;
+
+    if (oid == NULL)
+        return BAD_FUNC_ARG;
+
+    for (curve_idx = 0; ecc_sets[curve_idx].size != 0; curve_idx++) {
+        if (
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            ecc_sets[curve_idx].oid &&
+        #endif
+            ecc_sets[curve_idx].oidSz == len &&
+                              XMEMCMP(ecc_sets[curve_idx].oid, oid, len) == 0) {
+            break;
+        }
+    }
+    if (ecc_sets[curve_idx].size == 0) {
+        WOLFSSL_MSG("ecc_set curve name not found");
+        return ECC_CURVE_INVALID;
+    }
+
+    return ecc_sets[curve_idx].id;
+}
+
+/* Get curve parameters using curve index */
+const ecc_set_type* wc_ecc_get_curve_params(int curve_idx)
+{
+    const ecc_set_type* ecc_set = NULL;
+
+    if (curve_idx >= 0 && curve_idx < (int)ECC_SET_COUNT) {
+        ecc_set = &ecc_sets[curve_idx];
+    }
+    return ecc_set;
+}
+
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
+static WC_INLINE int wc_ecc_alloc_mpint(ecc_key* key, mp_int** mp)
+{
+   if (key == NULL || mp == NULL)
+      return BAD_FUNC_ARG;
+   if (*mp == NULL) {
+      *mp = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_BIGINT);
+      if (*mp == NULL) {
+         return MEMORY_E;
+      }
+      XMEMSET(*mp, 0, sizeof(mp_int));
+   }
+   return 0;
+}
+static WC_INLINE void wc_ecc_free_mpint(ecc_key* key, mp_int** mp)
+{
+   if (key && mp && *mp) {
+      mp_clear(*mp);
+      XFREE(*mp, key->heap, DYNAMIC_TYPE_BIGINT);
+      *mp = NULL;
+   }
+}
+
+static int wc_ecc_alloc_async(ecc_key* key)
+{
+    int err = wc_ecc_alloc_mpint(key, &key->r);
+    if (err == 0)
+        err = wc_ecc_alloc_mpint(key, &key->s);
+    return err;
+}
+
+static void wc_ecc_free_async(ecc_key* key)
+{
+    wc_ecc_free_mpint(key, &key->r);
+    wc_ecc_free_mpint(key, &key->s);
+#ifdef HAVE_CAVIUM_V
+    wc_ecc_free_mpint(key, &key->e);
+    wc_ecc_free_mpint(key, &key->signK);
+#endif /* HAVE_CAVIUM_V */
+}
+#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_ECC */
+
+
+#ifdef HAVE_ECC_DHE
+/**
+  Create an ECC shared secret between two keys
+  private_key      The private ECC key (heap hint based off of private key)
+  public_key       The public key
+  out              [out] Destination of the shared secret
+                         Conforms to EC-DH from ANSI X9.63
+  outlen           [in/out] The max size and resulting size of the shared secret
+  return           MP_OKAY if successful
+*/
+int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out,
+                      word32* outlen)
+{
+   int err;
+#if defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_ATECC508A)
+   CRYS_ECDH_TempData_t tempBuff;
+#endif
+   if (private_key == NULL || public_key == NULL || out == NULL ||
+                                                            outlen == NULL) {
+       return BAD_FUNC_ARG;
+   }
+
+#ifdef WOLF_CRYPTO_CB
+    if (private_key->devId != INVALID_DEVID) {
+        err = wc_CryptoCb_Ecdh(private_key, public_key, out, outlen);
+        if (err != CRYPTOCB_UNAVAILABLE)
+            return err;
+        /* fall-through when unavailable */
+    }
+#endif
+
+   /* type valid? */
+   if (private_key->type != ECC_PRIVATEKEY &&
+           private_key->type != ECC_PRIVATEKEY_ONLY) {
+      return ECC_BAD_ARG_E;
+   }
+
+   /* Verify domain params supplied */
+   if (wc_ecc_is_valid_idx(private_key->idx) == 0 ||
+       wc_ecc_is_valid_idx(public_key->idx)  == 0) {
+      return ECC_BAD_ARG_E;
+   }
+
+   /* Verify curve id matches */
+   if (private_key->dp->id != public_key->dp->id) {
+      return ECC_BAD_ARG_E;
+   }
+
+#ifdef WOLFSSL_ATECC508A
+   /* For SECP256R1 use hardware */
+   if (private_key->dp->id == ECC_SECP256R1) {
+       err = atmel_ecc_create_pms(private_key->slot, public_key->pubkey_raw, out);
+       *outlen = private_key->dp->size;
+   }
+   else {
+      err = NOT_COMPILED_IN;
+   }
+#elif defined(WOLFSSL_CRYPTOCELL)
+
+    /* generate a secret*/
+    err = CRYS_ECDH_SVDP_DH(&public_key->ctx.pubKey,
+                            &private_key->ctx.privKey,
+                            out,
+                            outlen,
+                            &tempBuff);
+
+    if (err != SA_SILIB_RET_OK){
+        WOLFSSL_MSG("CRYS_ECDH_SVDP_DH for secret failed");
+        return err;
+    }
+
+#else
+   err = wc_ecc_shared_secret_ex(private_key, &public_key->pubkey, out, outlen);
+#endif /* WOLFSSL_ATECC508A */
+
+   return err;
+}
+
+
+#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL)
+
+static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point,
+                               byte* out, word32* outlen, ecc_curve_spec* curve)
+{
+    int err;
+#ifndef WOLFSSL_SP_MATH
+    ecc_point* result = NULL;
+    word32 x = 0;
+#endif
+    mp_int* k = &private_key->k;
+#ifdef HAVE_ECC_CDH
+    mp_int k_lcl;
+
+    /* if cofactor flag has been set */
+    if (private_key->flags & WC_ECC_FLAG_COFACTOR) {
+        mp_digit cofactor = (mp_digit)private_key->dp->cofactor;
+        /* only perform cofactor calc if not equal to 1 */
+        if (cofactor != 1) {
+            k = &k_lcl;
+            if (mp_init(k) != MP_OKAY)
+                return MEMORY_E;
+            /* multiply cofactor times private key "k" */
+            err = mp_mul_d(&private_key->k, cofactor, k);
+            if (err != MP_OKAY) {
+                mp_clear(k);
+                return err;
+            }
+        }
+    }
+#endif
+
+#ifdef WOLFSSL_HAVE_SP_ECC
+#ifndef WOLFSSL_SP_NO_256
+    if (private_key->idx != ECC_CUSTOM_IDX &&
+                               ecc_sets[private_key->idx].id == ECC_SECP256R1) {
+        err = sp_ecc_secret_gen_256(k, point, out, outlen, private_key->heap);
+    }
+    else
+#endif
+#ifdef WOLFSSL_SP_384
+    if (private_key->idx != ECC_CUSTOM_IDX &&
+                               ecc_sets[private_key->idx].id == ECC_SECP384R1) {
+        err = sp_ecc_secret_gen_384(k, point, out, outlen, private_key->heap);
+    }
+    else
+#endif
+#endif
+#ifdef WOLFSSL_SP_MATH
+    {
+        err = WC_KEY_SIZE_E;
+
+        (void)curve;
+    }
+#else
+    {
+        mp_digit mp = 0;
+
+        /* make new point */
+        result = wc_ecc_new_point_h(private_key->heap);
+        if (result == NULL) {
+#ifdef HAVE_ECC_CDH
+            if (k == &k_lcl)
+                mp_clear(k);
+#endif
+            return MEMORY_E;
+        }
+
+        /* Map in a separate call as this should be constant time */
+        err = wc_ecc_mulmod_ex(k, point, result, curve->Af, curve->prime, 0,
+                                                             private_key->heap);
+        if (err == MP_OKAY) {
+            err = mp_montgomery_setup(curve->prime, &mp);
+        }
+        if (err == MP_OKAY) {
+            /* Use constant time map if compiled in */
+            err = ecc_map_ex(result, curve->prime, mp, 1);
+        }
+        if (err == MP_OKAY) {
+            x = mp_unsigned_bin_size(curve->prime);
+            if (*outlen < x || (int)x < mp_unsigned_bin_size(result->x)) {
+                err = BUFFER_E;
+            }
+        }
+
+        if (err == MP_OKAY) {
+            XMEMSET(out, 0, x);
+            err = mp_to_unsigned_bin(result->x,out +
+                                     (x - mp_unsigned_bin_size(result->x)));
+        }
+        *outlen = x;
+
+        wc_ecc_del_point_h(result, private_key->heap);
+    }
+#endif
+#ifdef HAVE_ECC_CDH
+    if (k == &k_lcl)
+        mp_clear(k);
+#endif
+
+    return err;
+}
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
+static int wc_ecc_shared_secret_gen_async(ecc_key* private_key,
+            ecc_point* point, byte* out, word32 *outlen,
+            ecc_curve_spec* curve)
+{
+    int err;
+
+#if defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA)
+#ifdef HAVE_CAVIUM_V
+    /* verify the curve is supported by hardware */
+    if (NitroxEccIsCurveSupported(private_key))
+#endif
+    {
+        word32 keySz = private_key->dp->size;
+
+        /* sync public key x/y */
+        err = wc_mp_to_bigint_sz(&private_key->k, &private_key->k.raw, keySz);
+        if (err == MP_OKAY)
+            err = wc_mp_to_bigint_sz(point->x, &point->x->raw, keySz);
+        if (err == MP_OKAY)
+            err = wc_mp_to_bigint_sz(point->y, &point->y->raw, keySz);
+    #ifdef HAVE_CAVIUM_V
+        /* allocate buffer for output */
+        if (err == MP_OKAY)
+            err = wc_ecc_alloc_mpint(private_key, &private_key->e);
+        if (err == MP_OKAY)
+            err = wc_bigint_alloc(&private_key->e->raw,
+                NitroxEccGetSize(private_key)*2);
+        if (err == MP_OKAY)
+            err = NitroxEcdh(private_key,
+                &private_key->k.raw, &point->x->raw, &point->y->raw,
+                private_key->e->raw.buf, &private_key->e->raw.len,
+                &curve->prime->raw);
+    #else
+        if (err == MP_OKAY)
+            err = wc_ecc_curve_load(private_key->dp, &curve, ECC_CURVE_FIELD_BF);
+        if (err == MP_OKAY)
+            err = IntelQaEcdh(&private_key->asyncDev,
+                &private_key->k.raw, &point->x->raw, &point->y->raw,
+                out, outlen,
+                &curve->Af->raw, &curve->Bf->raw, &curve->prime->raw,
+                private_key->dp->cofactor);
+    #endif
+        return err;
+    }
+#elif defined(WOLFSSL_ASYNC_CRYPT_TEST)
+    if (wc_AsyncTestInit(&private_key->asyncDev, ASYNC_TEST_ECC_SHARED_SEC)) {
+        WC_ASYNC_TEST* testDev = &private_key->asyncDev.test;
+        testDev->eccSharedSec.private_key = private_key;
+        testDev->eccSharedSec.public_point = point;
+        testDev->eccSharedSec.out = out;
+        testDev->eccSharedSec.outLen = outlen;
+        return WC_PENDING_E;
+    }
+#endif
+
+    /* use sync in other cases */
+    err = wc_ecc_shared_secret_gen_sync(private_key, point, out, outlen, curve);
+
+    return err;
+}
+#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_ECC */
+
+int wc_ecc_shared_secret_gen(ecc_key* private_key, ecc_point* point,
+                                                    byte* out, word32 *outlen)
+{
+    int err;
+    DECLARE_CURVE_SPECS(curve, 2);
+
+    if (private_key == NULL || point == NULL || out == NULL ||
+                                                            outlen == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* load curve info */
+    ALLOC_CURVE_SPECS(2);
+    err = wc_ecc_curve_load(private_key->dp, &curve,
+        (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF));
+    if (err != MP_OKAY) {
+        FREE_CURVE_SPECS();
+        return err;
+    }
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
+    if (private_key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) {
+        err = wc_ecc_shared_secret_gen_async(private_key, point,
+            out, outlen, curve);
+    }
+    else
+#endif
+    {
+        err = wc_ecc_shared_secret_gen_sync(private_key, point,
+            out, outlen, curve);
+    }
+
+    wc_ecc_curve_free(curve);
+    FREE_CURVE_SPECS();
+
+    return err;
+}
+
+/**
+ Create an ECC shared secret between private key and public point
+ private_key      The private ECC key (heap hint based on private key)
+ point            The point to use (public key)
+ out              [out] Destination of the shared secret
+                        Conforms to EC-DH from ANSI X9.63
+ outlen           [in/out] The max size and resulting size of the shared secret
+ return           MP_OKAY if successful
+*/
+int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point,
+                            byte* out, word32 *outlen)
+{
+    int err;
+
+    if (private_key == NULL || point == NULL || out == NULL ||
+                                                            outlen == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* type valid? */
+    if (private_key->type != ECC_PRIVATEKEY &&
+            private_key->type != ECC_PRIVATEKEY_ONLY) {
+        return ECC_BAD_ARG_E;
+    }
+
+    /* Verify domain params supplied */
+    if (wc_ecc_is_valid_idx(private_key->idx) == 0)
+        return ECC_BAD_ARG_E;
+
+    switch(private_key->state) {
+        case ECC_STATE_NONE:
+        case ECC_STATE_SHARED_SEC_GEN:
+            private_key->state = ECC_STATE_SHARED_SEC_GEN;
+
+            err = wc_ecc_shared_secret_gen(private_key, point, out, outlen);
+            if (err < 0) {
+                break;
+            }
+            FALL_THROUGH;
+
+        case ECC_STATE_SHARED_SEC_RES:
+            private_key->state = ECC_STATE_SHARED_SEC_RES;
+        #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
+            if (private_key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) {
+            #ifdef HAVE_CAVIUM_V
+                /* verify the curve is supported by hardware */
+                if (NitroxEccIsCurveSupported(private_key)) {
+                    /* copy output */
+                    *outlen = private_key->dp->size;
+                    XMEMCPY(out, private_key->e->raw.buf, *outlen);
+                }
+            #endif /* HAVE_CAVIUM_V */
+            }
+        #endif /* WOLFSSL_ASYNC_CRYPT */
+            err = 0;
+            break;
+
+        default:
+            err = BAD_STATE_E;
+    } /* switch */
+
+    /* if async pending then return and skip done cleanup below */
+    if (err == WC_PENDING_E) {
+        private_key->state++;
+        return err;
+    }
+
+    /* cleanup */
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
+    wc_ecc_free_async(private_key);
+#endif
+    private_key->state = ECC_STATE_NONE;
+
+    return err;
+}
+#endif /* !WOLFSSL_ATECC508A && !WOLFSSL_CRYPTOCELL */
+#endif /* HAVE_ECC_DHE */
+
+
+#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL)
+/* return 1 if point is at infinity, 0 if not, < 0 on error */
+int wc_ecc_point_is_at_infinity(ecc_point* p)
+{
+    if (p == NULL)
+        return BAD_FUNC_ARG;
+
+    if (get_digit_count(p->x) == 0 && get_digit_count(p->y) == 0)
+        return 1;
+
+    return 0;
+}
+
+/* generate random and ensure its greater than 0 and less than order */
+int wc_ecc_gen_k(WC_RNG* rng, int size, mp_int* k, mp_int* order)
+{
+#ifndef WC_NO_RNG
+    int err;
+    byte buf[ECC_MAXSIZE_GEN];
+
+    /*generate 8 extra bytes to mitigate bias from the modulo operation below*/
+    /*see section A.1.2 in 'Suite B Implementor's Guide to FIPS 186-3 (ECDSA)'*/
+    size += 8;
+
+    /* make up random string */
+    err = wc_RNG_GenerateBlock(rng, buf, size);
+
+    /* load random buffer data into k */
+    if (err == 0)
+        err = mp_read_unsigned_bin(k, (byte*)buf, size);
+
+    /* the key should be smaller than the order of base point */
+    if (err == MP_OKAY) {
+        if (mp_cmp(k, order) != MP_LT) {
+            err = mp_mod(k, order, k);
+        }
+    }
+
+    /* quick sanity check to make sure we're not dealing with a 0 key */
+    if (err == MP_OKAY) {
+        if (mp_iszero(k) == MP_YES)
+          err = MP_ZERO_E;
+    }
+
+    ForceZero(buf, ECC_MAXSIZE);
+
+    return err;
+#else
+    (void)rng;
+    (void)size;
+    (void)k;
+    (void)order;
+    return NOT_COMPILED_IN;
+#endif /* !WC_NO_RNG */
+}
+#endif /* !WOLFSSL_ATECC508A && !WOLFSSL_CRYPTOCELL */
+
+static WC_INLINE void wc_ecc_reset(ecc_key* key)
+{
+    /* make sure required key variables are reset */
+    key->state = ECC_STATE_NONE;
+}
+
+
+/* create the public ECC key from a private key
+ *
+ * key     an initialized private key to generate public part from
+ * curveIn [in]curve for key, can be NULL
+ * pubOut  [out]ecc_point holding the public key, if NULL then public key part
+ *         is cached in key instead.
+ *
+ * Note this function is local to the file because of the argument type
+ *      ecc_curve_spec. Having this argument allows for not having to load the
+ *      curve type multiple times when generating a key with wc_ecc_make_key().
+ *
+ * returns MP_OKAY on success
+ */
+static int wc_ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn,
+        ecc_point* pubOut)
+{
+    int err = MP_OKAY;
+#ifndef WOLFSSL_ATECC508A
+#ifndef WOLFSSL_SP_MATH
+    ecc_point* base = NULL;
+#endif
+    ecc_point* pub;
+    DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT);
+#endif /* !WOLFSSL_ATECC508A */
+
+    if (key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifndef WOLFSSL_ATECC508A
+
+    /* if ecc_point passed in then use it as output for public key point */
+    if (pubOut != NULL) {
+        pub = pubOut;
+    }
+    else {
+        /* caching public key making it a ECC_PRIVATEKEY instead of
+           ECC_PRIVATEKEY_ONLY */
+        pub = &key->pubkey;
+        key->type = ECC_PRIVATEKEY_ONLY;
+    }
+
+    /* avoid loading the curve unless it is not passed in */
+    if (curveIn != NULL) {
+        curve = curveIn;
+    }
+    else {
+        /* load curve info */
+        if (err == MP_OKAY) {
+            ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT);
+            err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL);
+        }
+    }
+
+    if (err == MP_OKAY) {
+    #ifndef ALT_ECC_SIZE
+        err = mp_init_multi(pub->x, pub->y, pub->z, NULL, NULL, NULL);
+    #else
+        pub->x = (mp_int*)&pub->xyz[0];
+        pub->y = (mp_int*)&pub->xyz[1];
+        pub->z = (mp_int*)&pub->xyz[2];
+        alt_fp_init(pub->x);
+        alt_fp_init(pub->y);
+        alt_fp_init(pub->z);
+    #endif
+    }
+
+
+    if (err != MP_OKAY) {
+    }
+    else
+#ifdef WOLFSSL_HAVE_SP_ECC
+#ifndef WOLFSSL_SP_NO_256
+    if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) {
+        err = sp_ecc_mulmod_base_256(&key->k, pub, 1, key->heap);
+    }
+    else
+#endif
+#ifdef WOLFSSL_SP_384
+    if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) {
+        err = sp_ecc_mulmod_base_384(&key->k, pub, 1, key->heap);
+    }
+    else
+#endif
+#endif
+#ifdef WOLFSSL_SP_MATH
+        err = WC_KEY_SIZE_E;
+#else
+    {
+        mp_digit mp;
+
+        base = wc_ecc_new_point_h(key->heap);
+        if (base == NULL)
+            err = MEMORY_E;
+        /* read in the x/y for this key */
+        if (err == MP_OKAY)
+            err = mp_copy(curve->Gx, base->x);
+        if (err == MP_OKAY)
+            err = mp_copy(curve->Gy, base->y);
+        if (err == MP_OKAY)
+            err = mp_set(base->z, 1);
+
+        /* make the public key */
+        if (err == MP_OKAY) {
+            /* Map in a separate call as this should be constant time */
+            err = wc_ecc_mulmod_ex(&key->k, base, pub, curve->Af, curve->prime,
+                                                                  0, key->heap);
+            if (err == MP_MEM) {
+               err = MEMORY_E;
+            }
+        }
+        if (err == MP_OKAY) {
+            err = mp_montgomery_setup(curve->prime, &mp);
+        }
+        if (err == MP_OKAY) {
+            /* Use constant time map if compiled in */
+            err = ecc_map_ex(pub, curve->prime, mp, 1);
+        }
+
+        wc_ecc_del_point_h(base, key->heap);
+    }
+#endif
+
+#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
+    /* validate the public key, order * pubkey = point at infinity */
+    if (err == MP_OKAY)
+        err = ecc_check_pubkey_order(key, pub, curve->Af, curve->prime,
+                curve->order);
+#endif /* WOLFSSL_VALIDATE_KEYGEN */
+
+    if (err != MP_OKAY) {
+        /* clean up if failed */
+    #ifndef ALT_ECC_SIZE
+        mp_clear(pub->x);
+        mp_clear(pub->y);
+        mp_clear(pub->z);
+    #endif
+    }
+
+    /* free up local curve */
+    if (curveIn == NULL) {
+        wc_ecc_curve_free(curve);
+        FREE_CURVE_SPECS();
+    }
+
+#else
+    (void)curveIn;
+    err = NOT_COMPILED_IN;
+#endif /* WOLFSSL_ATECC508A */
+
+    /* change key state if public part is cached */
+    if (key->type == ECC_PRIVATEKEY_ONLY && pubOut == NULL) {
+        key->type = ECC_PRIVATEKEY;
+    }
+
+    return err;
+}
+
+
+/* create the public ECC key from a private key
+ *
+ * key     an initialized private key to generate public part from
+ * pubOut  [out]ecc_point holding the public key, if NULL then public key part
+ *         is cached in key instead.
+ *
+ *
+ * returns MP_OKAY on success
+ */
+int wc_ecc_make_pub(ecc_key* key, ecc_point* pubOut)
+{
+    WOLFSSL_ENTER("wc_ecc_make_pub");
+
+    return wc_ecc_make_pub_ex(key, NULL, pubOut);
+}
+
+
+WOLFSSL_ABI
+int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id)
+{
+    int err;
+#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL)
+#ifndef WOLFSSL_SP_MATH
+    DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT);
+#endif
+#endif /* !WOLFSSL_ATECC508A */
+#if defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_ATECC508A)
+    const CRYS_ECPKI_Domain_t*  pDomain;
+    CRYS_ECPKI_KG_TempData_t    tempBuff;
+    CRYS_ECPKI_KG_FipsContext_t fipsCtx;
+    byte ucompressed_key[ECC_MAX_CRYPTO_HW_SIZE*2 + 1];
+    word32 raw_size = 0;
+#endif
+    if (key == NULL || rng == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* make sure required variables are reset */
+    wc_ecc_reset(key);
+
+    err = wc_ecc_set_curve(key, keysize, curve_id);
+    if (err != 0) {
+        return err;
+    }
+
+#ifdef WOLF_CRYPTO_CB
+    if (key->devId != INVALID_DEVID) {
+        err = wc_CryptoCb_MakeEccKey(rng, keysize, key, curve_id);
+        if (err != CRYPTOCB_UNAVAILABLE)
+            return err;
+        /* fall-through when unavailable */
+    }
+#endif
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
+    if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) {
+    #ifdef HAVE_CAVIUM
+        /* TODO: Not implemented */
+    #elif defined(HAVE_INTEL_QA)
+        /* TODO: Not implemented */
+    #else
+        if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_ECC_MAKE)) {
+            WC_ASYNC_TEST* testDev = &key->asyncDev.test;
+            testDev->eccMake.rng = rng;
+            testDev->eccMake.key = key;
+            testDev->eccMake.size = keysize;
+            testDev->eccMake.curve_id = curve_id;
+            return WC_PENDING_E;
+        }
+    #endif
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_ECC */
+
+#ifdef WOLFSSL_ATECC508A
+   if (key->dp->id == ECC_SECP256R1) {
+       key->type = ECC_PRIVATEKEY;
+       key->slot = atmel_ecc_alloc(ATMEL_SLOT_ECDHE);
+       err = atmel_ecc_create_key(key->slot, key->pubkey_raw);
+
+       /* populate key->pubkey */
+       if (err == 0
+       #ifdef ALT_ECC_SIZE
+          && key->pubkey.x
+       #endif
+       ) {
+           err = mp_read_unsigned_bin(key->pubkey.x, key->pubkey_raw,
+                                      ECC_MAX_CRYPTO_HW_SIZE);
+       }
+       if (err == 0
+       #ifdef ALT_ECC_SIZE
+          && key->pubkey.y
+       #endif
+       ) {
+           err = mp_read_unsigned_bin(key->pubkey.y,
+                                      key->pubkey_raw + ECC_MAX_CRYPTO_HW_SIZE,
+                                      ECC_MAX_CRYPTO_HW_SIZE);
+       }
+   }
+   else {
+      err = NOT_COMPILED_IN;
+   }
+#elif defined(WOLFSSL_CRYPTOCELL)
+
+    pDomain = CRYS_ECPKI_GetEcDomain(cc310_mapCurve(curve_id));
+    raw_size = (word32)(key->dp->size)*2 + 1;
+
+    /* generate first key pair */
+    err = CRYS_ECPKI_GenKeyPair(&wc_rndState,
+                                wc_rndGenVectFunc,
+                                pDomain,
+                                &key->ctx.privKey,
+                                &key->ctx.pubKey,
+                                &tempBuff,
+                                &fipsCtx);
+
+    if (err != SA_SILIB_RET_OK){
+        WOLFSSL_MSG("CRYS_ECPKI_GenKeyPair for key pair failed");
+        return err;
+    }
+    key->type = ECC_PRIVATEKEY;
+
+    err = CRYS_ECPKI_ExportPublKey(&key->ctx.pubKey,
+                                   CRYS_EC_PointUncompressed,
+                                   &ucompressed_key[0],
+                                   &raw_size);
+
+    if (err == SA_SILIB_RET_OK && key->pubkey.x && key->pubkey.y) {
+        err = mp_read_unsigned_bin(key->pubkey.x,
+                                   &ucompressed_key[1], key->dp->size);
+        if (err == MP_OKAY) {
+            err = mp_read_unsigned_bin(key->pubkey.y,
+                            &ucompressed_key[1+key->dp->size],key->dp->size);
+        }
+    }
+    raw_size = key->dp->size;
+    if (err == MP_OKAY) {
+        err = CRYS_ECPKI_ExportPrivKey(&key->ctx.privKey,
+                                       ucompressed_key,
+                                       &raw_size);
+    }
+
+    if (err == SA_SILIB_RET_OK) {
+        err = mp_read_unsigned_bin(&key->k, ucompressed_key, raw_size);
+    }
+
+#else
+
+#ifdef WOLFSSL_HAVE_SP_ECC
+#ifndef WOLFSSL_SP_NO_256
+    if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) {
+        err = sp_ecc_make_key_256(rng, &key->k, &key->pubkey, key->heap);
+        if (err == MP_OKAY) {
+            key->type = ECC_PRIVATEKEY;
+        }
+    }
+    else
+#endif
+#ifdef WOLFSSL_SP_384
+    if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) {
+        err = sp_ecc_make_key_384(rng, &key->k, &key->pubkey, key->heap);
+        if (err == MP_OKAY) {
+            key->type = ECC_PRIVATEKEY;
+        }
+    }
+    else
+#endif
+#endif /* WOLFSSL_HAVE_SP_ECC */
+
+   { /* software key gen */
+#ifdef WOLFSSL_SP_MATH
+        err = WC_KEY_SIZE_E;
+#else
+
+        /* setup the key variables */
+        err = mp_init(&key->k);
+
+        /* load curve info */
+        if (err == MP_OKAY) {
+            ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT);
+            err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL);
+        }
+
+        /* generate k */
+        if (err == MP_OKAY)
+            err = wc_ecc_gen_k(rng, key->dp->size, &key->k, curve->order);
+
+        /* generate public key from k */
+        if (err == MP_OKAY)
+            err = wc_ecc_make_pub_ex(key, curve, NULL);
+
+        if (err == MP_OKAY)
+            key->type = ECC_PRIVATEKEY;
+
+        /* cleanup these on failure case only */
+        if (err != MP_OKAY) {
+            /* clean up */
+            mp_forcezero(&key->k);
+        }
+
+        /* cleanup allocations */
+        wc_ecc_curve_free(curve);
+        FREE_CURVE_SPECS();
+#endif /* WOLFSSL_SP_MATH */
+    }
+
+#ifdef HAVE_WOLF_BIGINT
+    if (err == MP_OKAY)
+         err = wc_mp_to_bigint(&key->k, &key->k.raw);
+    if (err == MP_OKAY)
+         err = wc_mp_to_bigint(key->pubkey.x, &key->pubkey.x->raw);
+    if (err == MP_OKAY)
+         err = wc_mp_to_bigint(key->pubkey.y, &key->pubkey.y->raw);
+    if (err == MP_OKAY)
+         err = wc_mp_to_bigint(key->pubkey.z, &key->pubkey.z->raw);
+#endif
+
+#endif /* WOLFSSL_ATECC508A */
+
+    return err;
+}
+
+#ifdef ECC_DUMP_OID
+/* Optional dump of encoded OID for adding new curves */
+static int mOidDumpDone;
+static void wc_ecc_dump_oids(void)
+{
+    int x;
+
+    if (mOidDumpDone) {
+        return;
+    }
+
+    /* find matching OID sum (based on encoded value) */
+    for (x = 0; ecc_sets[x].size != 0; x++) {
+        int i;
+        byte* oid;
+        word32 oidSz, sum = 0;
+
+        printf("ECC %s (%d):\n", ecc_sets[x].name, x);
+
+    #ifdef HAVE_OID_ENCODING
+        byte oidEnc[ECC_MAX_OID_LEN];
+
+        oid = oidEnc;
+        oidSz = ECC_MAX_OID_LEN;
+
+        printf("OID: ");
+        for (i = 0; i < (int)ecc_sets[x].oidSz; i++) {
+            printf("%d.", ecc_sets[x].oid[i]);
+        }
+        printf("\n");
+
+        EncodeObjectId(ecc_sets[x].oid, ecc_sets[x].oidSz, oidEnc, &oidSz);
+    #else
+        oid = (byte*)ecc_sets[x].oid;
+        oidSz = ecc_sets[x].oidSz;
+    #endif
+
+        printf("OID Encoded: ");
+        for (i = 0; i < (int)oidSz; i++) {
+            printf("0x%02X,", oid[i]);
+        }
+        printf("\n");
+
+        for (i = 0; i < (int)oidSz; i++) {
+            sum += oid[i];
+        }
+        printf("Sum: %d\n", sum);
+
+        /* validate sum */
+        if (ecc_sets[x].oidSum != sum) {
+            printf("  Sum %d Not Valid!\n", ecc_sets[x].oidSum);
+        }
+    }
+    mOidDumpDone = 1;
+}
+#endif /* ECC_DUMP_OID */
+
+
+WOLFSSL_ABI
+ecc_key* wc_ecc_key_new(void* heap)
+{
+    ecc_key* key;
+
+    key = (ecc_key*)XMALLOC(sizeof(ecc_key), heap, DYNAMIC_TYPE_ECC);
+    if (key) {
+        if (wc_ecc_init_ex(key, heap, INVALID_DEVID) != 0) {
+            XFREE(key, heap, DYNAMIC_TYPE_ECC);
+            key = NULL;
+        }
+    }
+
+    return key;
+}
+
+
+WOLFSSL_ABI
+void wc_ecc_key_free(ecc_key* key)
+{
+    if (key) {
+        void* heap = key->heap;
+
+        wc_ecc_free(key);
+        ForceZero(key, sizeof(ecc_key));
+        XFREE(key, heap, DYNAMIC_TYPE_ECC);
+        (void)heap;
+    }
+}
+
+
+/**
+ Make a new ECC key
+ rng          An active RNG state
+ keysize      The keysize for the new key (in octets from 20 to 65 bytes)
+ key          [out] Destination of the newly created key
+ return       MP_OKAY if successful,
+ upon error all allocated memory will be freed
+ */
+int wc_ecc_make_key(WC_RNG* rng, int keysize, ecc_key* key)
+{
+    return wc_ecc_make_key_ex(rng, keysize, key, ECC_CURVE_DEF);
+}
+
+/* Setup dynamic pointers if using normal math for proper freeing */
+WOLFSSL_ABI
+int wc_ecc_init_ex(ecc_key* key, void* heap, int devId)
+{
+    int ret = 0;
+
+    if (key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef ECC_DUMP_OID
+    wc_ecc_dump_oids();
+#endif
+
+    XMEMSET(key, 0, sizeof(ecc_key));
+    key->state = ECC_STATE_NONE;
+
+#if defined(PLUTON_CRYPTO_ECC) || defined(WOLF_CRYPTO_CB)
+    key->devId = devId;
+#else
+    (void)devId;
+#endif
+
+#ifdef WOLFSSL_ATECC508A
+    key->slot = ATECC_INVALID_SLOT;
+#else
+#ifdef ALT_ECC_SIZE
+    key->pubkey.x = (mp_int*)&key->pubkey.xyz[0];
+    key->pubkey.y = (mp_int*)&key->pubkey.xyz[1];
+    key->pubkey.z = (mp_int*)&key->pubkey.xyz[2];
+    alt_fp_init(key->pubkey.x);
+    alt_fp_init(key->pubkey.y);
+    alt_fp_init(key->pubkey.z);
+    ret = mp_init(&key->k);
+    if (ret != MP_OKAY) {
+        return MEMORY_E;
+    }
+#else
+    ret = mp_init_multi(&key->k, key->pubkey.x, key->pubkey.y, key->pubkey.z,
+                                                                    NULL, NULL);
+    if (ret != MP_OKAY) {
+        return MEMORY_E;
+    }
+#endif /* ALT_ECC_SIZE */
+#endif /* WOLFSSL_ATECC508A */
+
+#ifdef WOLFSSL_HEAP_TEST
+    key->heap = (void*)WOLFSSL_HEAP_TEST;
+#else
+    key->heap = heap;
+#endif
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
+    /* handle as async */
+    ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_ECC,
+                                                            key->heap, devId);
+#endif
+
+#if defined(WOLFSSL_DSP)
+    key->handle = -1;
+#endif
+    return ret;
+}
+
+int wc_ecc_init(ecc_key* key)
+{
+    return wc_ecc_init_ex(key, NULL, INVALID_DEVID);
+}
+
+#ifdef HAVE_PKCS11
+int wc_ecc_init_id(ecc_key* key, unsigned char* id, int len, void* heap,
+                   int devId)
+{
+    int ret = 0;
+
+    if (key == NULL)
+        ret = BAD_FUNC_ARG;
+    if (ret == 0 && (len < 0 || len > ECC_MAX_ID_LEN))
+        ret = BUFFER_E;
+
+    if (ret == 0)
+        ret = wc_ecc_init_ex(key, heap, devId);
+
+    if (ret == 0 && id != NULL && len != 0) {
+        XMEMCPY(key->id, id, len);
+        key->idLen = len;
+    }
+
+    return ret;
+}
+#endif
+
+int wc_ecc_set_flags(ecc_key* key, word32 flags)
+{
+    if (key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+    key->flags |= flags;
+    return 0;
+}
+
+
+static int wc_ecc_get_curve_order_bit_count(const ecc_set_type* dp)
+{
+    int err;
+    word32 orderBits;
+    DECLARE_CURVE_SPECS(curve, 1);
+
+    ALLOC_CURVE_SPECS(1);
+    err = wc_ecc_curve_load(dp, &curve, ECC_CURVE_FIELD_ORDER);
+    if (err != 0) {
+       FREE_CURVE_SPECS();
+       return err;
+    }
+    orderBits = mp_count_bits(curve->order);
+
+    wc_ecc_curve_free(curve);
+    FREE_CURVE_SPECS();
+    return (int)orderBits;
+}
+
+#ifdef HAVE_ECC_SIGN
+
+#ifndef NO_ASN
+
+#if defined(WOLFSSL_ATECC508A) || defined(PLUTON_CRYPTO_ECC) || \
+    defined(WOLFSSL_CRYPTOCELL)
+static int wc_ecc_sign_hash_hw(const byte* in, word32 inlen,
+    mp_int* r, mp_int* s, byte* out, word32 *outlen, WC_RNG* rng,
+    ecc_key* key)
+{
+    int err;
+#ifdef PLUTON_CRYPTO_ECC
+    if (key->devId != INVALID_DEVID) /* use hardware */
+#endif
+    {
+    #if defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_ATECC508A)
+        CRYS_ECDSA_SignUserContext_t sigCtxTemp;
+        word32 raw_sig_size = *outlen;
+        word32 msgLenInBytes = inlen;
+        CRYS_ECPKI_HASH_OpMode_t hash_mode;
+    #endif
+        word32 keysize = (word32)key->dp->size;
+        word32 orderBits = wc_ecc_get_curve_order_bit_count(key->dp);
+
+        /* Check args */
+        if (keysize > ECC_MAX_CRYPTO_HW_SIZE || *outlen < keysize*2) {
+            return ECC_BAD_ARG_E;
+        }
+
+    #if defined(WOLFSSL_ATECC508A)
+        key->slot = atmel_ecc_alloc(ATMEL_SLOT_DEVICE);
+        if (key->slot == ATECC_INVALID_SLOT) {
+            return ECC_BAD_ARG_E;
+        }
+
+        /* Sign: Result is 32-bytes of R then 32-bytes of S */
+        err = atmel_ecc_sign(key->slot, in, out);
+        if (err != 0) {
+           return err;
+        }
+    #elif defined(PLUTON_CRYPTO_ECC)
+        {
+            /* if the input is larger than curve order, we must truncate */
+            if ((inlen * WOLFSSL_BIT_SIZE) > orderBits) {
+               inlen = (orderBits + WOLFSSL_BIT_SIZE - 1) / WOLFSSL_BIT_SIZE;
+            }
+
+            /* perform ECC sign */
+            word32 raw_sig_size = *outlen;
+            err = Crypto_EccSign(in, inlen, out, &raw_sig_size);
+            if (err != CRYPTO_RES_SUCCESS || raw_sig_size != keysize*2){
+               return BAD_COND_E;
+            }
+        }
+    #elif defined(WOLFSSL_CRYPTOCELL)
+
+        hash_mode = cc310_hashModeECC(msgLenInBytes);
+        if (hash_mode == CRYS_ECPKI_HASH_OpModeLast) {
+            hash_mode = cc310_hashModeECC(keysize);
+            hash_mode = CRYS_ECPKI_HASH_SHA256_mode;
+        }
+
+        /* truncate if hash is longer than key size */
+        if (msgLenInBytes > keysize) {
+            msgLenInBytes = keysize;
+        }
+
+        /* create signature from an input buffer using a private key*/
+        err = CRYS_ECDSA_Sign(&wc_rndState,
+                               wc_rndGenVectFunc,
+                               &sigCtxTemp,
+                               &key->ctx.privKey,
+                               hash_mode,
+                               (byte*)in,
+                               msgLenInBytes,
+                               out,
+                               &raw_sig_size);
+
+        if (err != SA_SILIB_RET_OK){
+            WOLFSSL_MSG("CRYS_ECDSA_Sign failed");
+            return err;
+        }
+    #endif
+
+        /* Load R and S */
+        err = mp_read_unsigned_bin(r, &out[0], keysize);
+        if (err != MP_OKAY) {
+            return err;
+        }
+        err = mp_read_unsigned_bin(s, &out[keysize], keysize);
+        if (err != MP_OKAY) {
+            return err;
+        }
+
+        /* Check for zeros */
+        if (mp_iszero(r) || mp_iszero(s)) {
+            return MP_ZERO_E;
+        }
+    }
+#ifdef PLUTON_CRYPTO_ECC
+    else {
+        err = wc_ecc_sign_hash_ex(in, inlen, rng, key, r, s);
+    }
+#endif
+    (void)rng;
+
+    return err;
+}
+#endif /* WOLFSSL_ATECC508A || PLUTON_CRYPTO_ECC || WOLFSSL_CRYPTOCELL */
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
+static int wc_ecc_sign_hash_async(const byte* in, word32 inlen, byte* out,
+    word32 *outlen, WC_RNG* rng, ecc_key* key)
+{
+    int err;
+    mp_int *r = NULL, *s = NULL;
+
+    if (in == NULL || out == NULL || outlen == NULL || key == NULL ||
+                                                                rng == NULL) {
+        return ECC_BAD_ARG_E;
+    }
+
+    err = wc_ecc_alloc_async(key);
+    if (err != 0) {
+        return err;
+    }
+    r = key->r;
+    s = key->s;
+
+    switch(key->state) {
+        case ECC_STATE_NONE:
+        case ECC_STATE_SIGN_DO:
+            key->state = ECC_STATE_SIGN_DO;
+
+            if ((err = mp_init_multi(r, s, NULL, NULL, NULL, NULL)) != MP_OKAY){
+                break;
+            }
+
+            err = wc_ecc_sign_hash_ex(in, inlen, rng, key, r, s);
+            if (err < 0) {
+                break;
+            }
+
+            FALL_THROUGH;
+
+        case ECC_STATE_SIGN_ENCODE:
+            key->state = ECC_STATE_SIGN_ENCODE;
+
+            if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) {
+                #ifdef HAVE_CAVIUM_V
+                    /* Nitrox requires r and s in sep buffer, so split it */
+                    NitroxEccRsSplit(key, &r->raw, &s->raw);
+                #endif
+                #ifndef WOLFSSL_ASYNC_CRYPT_TEST
+                    /* only do this if not simulator, since it overwrites result */
+                    wc_bigint_to_mp(&r->raw, r);
+                    wc_bigint_to_mp(&s->raw, s);
+                #endif
+            }
+
+            /* encoded with DSA header */
+            err = StoreECC_DSA_Sig(out, outlen, r, s);
+
+            /* done with R/S */
+            mp_clear(r);
+            mp_clear(s);
+            break;
+
+        default:
+            err = BAD_STATE_E;
+            break;
+    }
+
+    /* if async pending then return and skip done cleanup below */
+    if (err == WC_PENDING_E) {
+        key->state++;
+        return err;
+    }
+
+    /* cleanup */
+    wc_ecc_free_async(key);
+    key->state = ECC_STATE_NONE;
+
+    return err;
+}
+#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_ECC */
+
+/**
+ Sign a message digest
+ in        The message digest to sign
+ inlen     The length of the digest
+ out       [out] The destination for the signature
+ outlen    [in/out] The max size and resulting size of the signature
+ key       A private ECC key
+ return    MP_OKAY if successful
+ */
+WOLFSSL_ABI
+int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen,
+                     WC_RNG* rng, ecc_key* key)
+{
+    int err;
+#if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(WC_ASYNC_ENABLE_ECC)
+#ifdef WOLFSSL_SMALL_STACK
+    mp_int *r = NULL, *s = NULL;
+#else
+    mp_int r[1], s[1];
+#endif
+#endif
+
+    if (in == NULL || out == NULL || outlen == NULL || key == NULL ||
+                                                                rng == NULL) {
+        return ECC_BAD_ARG_E;
+    }
+
+#ifdef WOLF_CRYPTO_CB
+    if (key->devId != INVALID_DEVID) {
+        err = wc_CryptoCb_EccSign(in, inlen, out, outlen, rng, key);
+        if (err != CRYPTOCB_UNAVAILABLE)
+            return err;
+        /* fall-through when unavailable */
+    }
+#endif
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
+    /* handle async cases */
+    err = wc_ecc_sign_hash_async(in, inlen, out, outlen, rng, key);
+#else
+
+#ifdef WOLFSSL_SMALL_STACK
+    r = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
+    if (r == NULL)
+        return MEMORY_E;
+    s = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
+    if (s == NULL) {
+        XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
+        return MEMORY_E;
+    }
+#endif
+    XMEMSET(r, 0, sizeof(mp_int));
+    XMEMSET(s, 0, sizeof(mp_int));
+
+    if ((err = mp_init_multi(r, s, NULL, NULL, NULL, NULL)) != MP_OKAY){
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(s, key->heap, DYNAMIC_TYPE_ECC);
+        XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
+    #endif
+        return err;
+    }
+
+/* hardware crypto */
+#if defined(WOLFSSL_ATECC508A) || defined(PLUTON_CRYPTO_ECC) || defined(WOLFSSL_CRYPTOCELL)
+    err = wc_ecc_sign_hash_hw(in, inlen, r, s, out, outlen, rng, key);
+#else
+    err = wc_ecc_sign_hash_ex(in, inlen, rng, key, r, s);
+#endif
+    if (err < 0) {
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(s, key->heap, DYNAMIC_TYPE_ECC);
+        XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
+    #endif
+        return err;
+    }
+
+    /* encoded with DSA header */
+    err = StoreECC_DSA_Sig(out, outlen, r, s);
+
+    /* cleanup */
+    mp_clear(r);
+    mp_clear(s);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(s, key->heap, DYNAMIC_TYPE_ECC);
+    XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
+#endif
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    return err;
+}
+#endif /* !NO_ASN */
+
+#if defined(WOLFSSL_STM32_PKA)
+int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng,
+                     ecc_key* key, mp_int *r, mp_int *s)
+{
+    return stm32_ecc_sign_hash_ex(in, inlen, rng, key, r, s);
+}
+#elif !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL)
+/**
+  Sign a message digest
+  in        The message digest to sign
+  inlen     The length of the digest
+  key       A private ECC key
+  r         [out] The destination for r component of the signature
+  s         [out] The destination for s component of the signature
+  return    MP_OKAY if successful
+*/
+int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng,
+                     ecc_key* key, mp_int *r, mp_int *s)
+{
+   int    err = 0;
+#ifndef WOLFSSL_SP_MATH
+   mp_int* e;
+#if (!defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V)) && \
+                                                   !defined(WOLFSSL_SMALL_STACK)
+   mp_int  e_lcl;
+#endif
+
+#if defined(WOLFSSL_ECDSA_SET_K) || \
+    (defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \
+    (defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA)))
+   DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT);
+#else
+   DECLARE_CURVE_SPECS(curve, 1);
+#endif
+#endif /* !WOLFSSL_SP_MATH */
+
+   if (in == NULL || r == NULL || s == NULL || key == NULL || rng == NULL) {
+       return ECC_BAD_ARG_E;
+   }
+
+   /* is this a private key? */
+   if (key->type != ECC_PRIVATEKEY && key->type != ECC_PRIVATEKEY_ONLY) {
+      return ECC_BAD_ARG_E;
+   }
+
+   /* is the IDX valid ?  */
+   if (wc_ecc_is_valid_idx(key->idx) != 1) {
+      return ECC_BAD_ARG_E;
+   }
+
+#ifdef WOLFSSL_SP_MATH
+#ifndef WOLFSSL_SP_NO_256
+    if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) {
+    #ifndef WOLFSSL_ECDSA_SET_K
+        return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, NULL, key->heap);
+    #else
+        return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, key->sign_k,
+                                                                     key->heap);
+    #endif
+    }
+#endif
+#ifdef WOLFSSL_SP_384
+    if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) {
+    #ifndef WOLFSSL_ECDSA_SET_K
+        return sp_ecc_sign_384(in, inlen, rng, &key->k, r, s, NULL, key->heap);
+    #else
+        return sp_ecc_sign_384(in, inlen, rng, &key->k, r, s, key->sign_k,
+                                                                     key->heap);
+    #endif
+    }
+#endif
+    return WC_KEY_SIZE_E;
+#else
+#ifdef WOLFSSL_HAVE_SP_ECC
+    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
+    if (key->asyncDev.marker != WOLFSSL_ASYNC_MARKER_ECC)
+    #endif
+    {
+#ifndef WOLFSSL_SP_NO_256
+        if (key->idx != ECC_CUSTOM_IDX &&
+                                       ecc_sets[key->idx].id == ECC_SECP256R1) {
+        #ifndef WOLFSSL_ECDSA_SET_K
+            return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, NULL,
+                                                                     key->heap);
+        #else
+            return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, key->sign_k,
+                                                                     key->heap);
+        #endif
+        }
+#endif
+#ifdef WOLFSSL_SP_384
+        if (key->idx != ECC_CUSTOM_IDX &&
+                                       ecc_sets[key->idx].id == ECC_SECP384R1) {
+        #ifndef WOLFSSL_ECDSA_SET_K
+            return sp_ecc_sign_384(in, inlen, rng, &key->k, r, s, NULL,
+                                                                     key->heap);
+        #else
+            return sp_ecc_sign_384(in, inlen, rng, &key->k, r, s, key->sign_k,
+                                                                     key->heap);
+        #endif
+        }
+#endif
+    }
+#endif /* WOLFSSL_HAVE_SP_ECC */
+
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \
+       defined(WOLFSSL_ASYNC_CRYPT_TEST)
+    if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) {
+        if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_ECC_SIGN)) {
+            WC_ASYNC_TEST* testDev = &key->asyncDev.test;
+            testDev->eccSign.in = in;
+            testDev->eccSign.inSz = inlen;
+            testDev->eccSign.rng = rng;
+            testDev->eccSign.key = key;
+            testDev->eccSign.r = r;
+            testDev->eccSign.s = s;
+            return WC_PENDING_E;
+        }
+    }
+#endif
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM_V)
+   err = wc_ecc_alloc_mpint(key, &key->e);
+   if (err != 0) {
+      return err;
+   }
+   e = key->e;
+#elif !defined(WOLFSSL_SMALL_STACK)
+   e = &e_lcl;
+#else
+   e = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
+   if (e == NULL) {
+      return MEMORY_E;
+   }
+#endif
+
+   /* get the hash and load it as a bignum into 'e' */
+   /* init the bignums */
+   if ((err = mp_init(e)) != MP_OKAY) {
+   #ifdef WOLFSSL_SMALL_STACK
+      XFREE(e, key->heap, DYNAMIC_TYPE_ECC);
+   #endif
+      return err;
+   }
+
+   /* load curve info */
+#if defined(WOLFSSL_ECDSA_SET_K)
+   ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT);
+   err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL);
+#else
+   #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \
+      (defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA))
+   if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) {
+      ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT);
+      err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL);
+   }
+   else
+   #endif
+   {
+      ALLOC_CURVE_SPECS(1);
+      err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ORDER);
+   }
+#endif
+
+   /* load digest into e */
+   if (err == MP_OKAY) {
+       /* we may need to truncate if hash is longer than key size */
+       word32 orderBits = mp_count_bits(curve->order);
+
+       /* truncate down to byte size, may be all that's needed */
+       if ((WOLFSSL_BIT_SIZE * inlen) > orderBits)
+           inlen = (orderBits + WOLFSSL_BIT_SIZE - 1) / WOLFSSL_BIT_SIZE;
+       err = mp_read_unsigned_bin(e, (byte*)in, inlen);
+
+       /* may still need bit truncation too */
+       if (err == MP_OKAY && (WOLFSSL_BIT_SIZE * inlen) > orderBits)
+           mp_rshb(e, WOLFSSL_BIT_SIZE - (orderBits & 0x7));
+   }
+
+   /* make up a key and export the public copy */
+   if (err == MP_OKAY) {
+       int      loop_check = 0;
+   #ifdef WOLFSSL_SMALL_STACK
+       ecc_key* pubkey;
+   #else
+       ecc_key  pubkey[1];
+   #endif
+
+   #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
+        if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) {
+        #if defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA)
+        #ifdef HAVE_CAVIUM_V
+            if (NitroxEccIsCurveSupported(key))
+        #endif
+            {
+               word32 keySz = key->dp->size;
+               mp_int* k;
+            #ifdef HAVE_CAVIUM_V
+               err = wc_ecc_alloc_mpint(key, &key->signK);
+               if (err != 0)
+                  return err;
+               k = key->signK;
+            #else
+               mp_int k_lcl;
+               k = &k_lcl;
+            #endif
+
+               err = mp_init(k);
+
+                /* make sure r and s are allocated */
+           #ifdef HAVE_CAVIUM_V
+               /* Nitrox V needs single buffer for R and S */
+               if (err == MP_OKAY)
+                   err = wc_bigint_alloc(&key->r->raw, NitroxEccGetSize(key)*2);
+               /* Nitrox V only needs Prime and Order */
+               if (err == MP_OKAY)
+                   err = wc_ecc_curve_load(key->dp, &curve,
+                        (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_ORDER));
+           #else
+               if (err == MP_OKAY)
+                   err = wc_bigint_alloc(&key->r->raw, key->dp->size);
+               if (err == MP_OKAY)
+                   err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL);
+           #endif
+               if (err == MP_OKAY)
+                   err = wc_bigint_alloc(&key->s->raw, key->dp->size);
+
+               /* load e and k */
+               if (err == MP_OKAY)
+                   err = wc_mp_to_bigint_sz(e, &e->raw, keySz);
+               if (err == MP_OKAY)
+                   err = wc_mp_to_bigint_sz(&key->k, &key->k.raw, keySz);
+               if (err == MP_OKAY)
+                   err = wc_ecc_gen_k(rng, key->dp->size, k, curve->order);
+               if (err == MP_OKAY)
+                   err = wc_mp_to_bigint_sz(k, &k->raw, keySz);
+
+           #ifdef HAVE_CAVIUM_V
+               if (err == MP_OKAY)
+                   err = NitroxEcdsaSign(key, &e->raw, &key->k.raw, &k->raw,
+                    &r->raw, &s->raw, &curve->prime->raw, &curve->order->raw);
+           #else
+               if (err == MP_OKAY)
+                   err = IntelQaEcdsaSign(&key->asyncDev, &e->raw, &key->k.raw,
+                      &k->raw, &r->raw, &s->raw, &curve->Af->raw, &curve->Bf->raw,
+                      &curve->prime->raw, &curve->order->raw, &curve->Gx->raw,
+                      &curve->Gy->raw);
+           #endif
+
+           #ifndef HAVE_CAVIUM_V
+               mp_clear(e);
+               mp_clear(k);
+           #endif
+               wc_ecc_curve_free(curve);
+               FREE_CURVE_SPECS();
+
+               return err;
+           }
+       #endif /* HAVE_CAVIUM_V || HAVE_INTEL_QA */
+       }
+   #endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_ECC */
+
+   #ifdef WOLFSSL_SMALL_STACK
+       pubkey = (ecc_key*)XMALLOC(sizeof(ecc_key), key->heap, DYNAMIC_TYPE_ECC);
+       if (pubkey == NULL)
+           err = MEMORY_E;
+   #endif
+
+       /* don't use async for key, since we don't support async return here */
+       if (err == MP_OKAY && (err = wc_ecc_init_ex(pubkey, key->heap,
+                                                   INVALID_DEVID)) == MP_OKAY) {
+       #ifdef WOLFSSL_SMALL_STACK
+           mp_int* b = NULL;
+       #else
+           mp_int  b[1];
+       #endif
+
+       #ifdef WOLFSSL_SMALL_STACK
+           if (err == MP_OKAY) {
+               b = (mp_int*)XMALLOC(sizeof(mp_int), key->heap,
+                                                              DYNAMIC_TYPE_ECC);
+               if (b == NULL)
+                   err = MEMORY_E;
+           }
+       #endif
+
+           if (err == MP_OKAY) {
+               err = mp_init(b);
+           }
+
+       #ifdef WOLFSSL_CUSTOM_CURVES
+           /* if custom curve, apply params to pubkey */
+           if (err == MP_OKAY && key->idx == ECC_CUSTOM_IDX) {
+               err = wc_ecc_set_custom_curve(pubkey, key->dp);
+           }
+       #endif
+
+           if (err == MP_OKAY) {
+               /* Generate blinding value - non-zero value. */
+               do {
+                   if (++loop_check > 64) {
+                        err = RNG_FAILURE_E;
+                        break;
+                   }
+
+                   err = wc_ecc_gen_k(rng, key->dp->size, b, curve->order);
+               }
+               while (err == MP_ZERO_E);
+               loop_check = 0;
+           }
+
+           for (; err == MP_OKAY;) {
+               if (++loop_check > 64) {
+                    err = RNG_FAILURE_E;
+                    break;
+               }
+       #ifdef WOLFSSL_ECDSA_SET_K
+               if (key->sign_k != NULL) {
+                   if (loop_check > 1) {
+                      err = RNG_FAILURE_E;
+                      break;
+                   }
+
+                   err = mp_copy(key->sign_k, &pubkey->k);
+                   if (err != MP_OKAY) break;
+
+                   mp_forcezero(key->sign_k);
+                   mp_free(key->sign_k);
+                   XFREE(key->sign_k, key->heap, DYNAMIC_TYPE_ECC);
+                   key->sign_k = NULL;
+                   err = wc_ecc_make_pub_ex(pubkey, curve, NULL);
+               }
+               else
+       #endif
+               {
+                   err = wc_ecc_make_key_ex(rng, key->dp->size, pubkey,
+                                                                   key->dp->id);
+               }
+               if (err != MP_OKAY) break;
+
+               /* find r = x1 mod n */
+               err = mp_mod(pubkey->pubkey.x, curve->order, r);
+               if (err != MP_OKAY) break;
+
+               if (mp_iszero(r) == MP_YES) {
+                #ifndef ALT_ECC_SIZE
+                   mp_clear(pubkey->pubkey.x);
+                   mp_clear(pubkey->pubkey.y);
+                   mp_clear(pubkey->pubkey.z);
+                #endif
+                   mp_forcezero(&pubkey->k);
+               }
+               else {
+                   /* find s = (e + xr)/k
+                             = b.(e/k.b + x.r/k.b) */
+
+                   /* k = k.b */
+                   err = mp_mulmod(&pubkey->k, b, curve->order, &pubkey->k);
+                   if (err != MP_OKAY) break;
+
+                   /* k = 1/k.b */
+                   err = mp_invmod(&pubkey->k, curve->order, &pubkey->k);
+                   if (err != MP_OKAY) break;
+
+                   /* s = x.r */
+                   err = mp_mulmod(&key->k, r, curve->order, s);
+                   if (err != MP_OKAY) break;
+
+                   /* s = x.r/k.b */
+                   err = mp_mulmod(&pubkey->k, s, curve->order, s);
+                   if (err != MP_OKAY) break;
+
+                   /* e = e/k.b */
+                   err = mp_mulmod(&pubkey->k, e, curve->order, e);
+                   if (err != MP_OKAY) break;
+
+                   /* s = e/k.b + x.r/k.b
+                        = (e + x.r)/k.b */
+                   err = mp_add(e, s, s);
+                   if (err != MP_OKAY) break;
+
+                   /* s = b.(e + x.r)/k.b
+                        = (e + x.r)/k */
+                   err = mp_mulmod(s, b, curve->order, s);
+                   if (err != MP_OKAY) break;
+
+                   /* s = (e + xr)/k */
+                   err = mp_mod(s, curve->order, s);
+                   if (err != MP_OKAY) break;
+
+                   if (mp_iszero(s) == MP_NO)
+                       break;
+                }
+           }
+           mp_clear(b);
+           mp_free(b);
+       #ifdef WOLFSSL_SMALL_STACK
+           XFREE(b, key->heap, DYNAMIC_TYPE_ECC);
+       #endif
+           wc_ecc_free(pubkey);
+       #ifdef WOLFSSL_SMALL_STACK
+           XFREE(pubkey, key->heap, DYNAMIC_TYPE_ECC);
+       #endif
+       }
+   }
+
+   mp_clear(e);
+   wc_ecc_curve_free(curve);
+#ifdef WOLFSSL_SMALL_STACK
+   XFREE(e, key->heap, DYNAMIC_TYPE_ECC);
+#endif
+   FREE_CURVE_SPECS();
+#endif /* WOLFSSL_SP_MATH */
+
+   return err;
+}
+
+#ifdef WOLFSSL_ECDSA_SET_K
+int wc_ecc_sign_set_k(const byte* k, word32 klen, ecc_key* key)
+{
+    int ret = 0;
+
+    if (k == NULL || klen == 0 || key == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+
+    if (ret == 0) {
+        if (key->sign_k == NULL) {
+            key->sign_k = (mp_int*)XMALLOC(sizeof(mp_int), key->heap,
+                                                              DYNAMIC_TYPE_ECC);
+            if (key->sign_k == NULL) {
+                ret = MEMORY_E;
+            }
+        }
+    }
+
+    if (ret == 0) {
+        ret = mp_init(key->sign_k);
+    }
+    if (ret == 0) {
+        ret = mp_read_unsigned_bin(key->sign_k, k, klen);
+    }
+
+    return ret;
+}
+#endif /* WOLFSSL_ECDSA_SET_K */
+#endif /* WOLFSSL_ATECC508A && WOLFSSL_CRYPTOCELL*/
+
+#endif /* HAVE_ECC_SIGN */
+
+#ifdef WOLFSSL_CUSTOM_CURVES
+void wc_ecc_free_curve(const ecc_set_type* curve, void* heap)
+{
+#ifndef WOLFSSL_ECC_CURVE_STATIC
+    if (curve->prime != NULL)
+        XFREE((void*)curve->prime, heap, DYNAMIC_TYPE_ECC_BUFFER);
+    if (curve->Af != NULL)
+        XFREE((void*)curve->Af, heap, DYNAMIC_TYPE_ECC_BUFFER);
+    if (curve->Bf != NULL)
+        XFREE((void*)curve->Bf, heap, DYNAMIC_TYPE_ECC_BUFFER);
+    if (curve->order != NULL)
+        XFREE((void*)curve->order, heap, DYNAMIC_TYPE_ECC_BUFFER);
+    if (curve->Gx != NULL)
+        XFREE((void*)curve->Gx, heap, DYNAMIC_TYPE_ECC_BUFFER);
+    if (curve->Gy != NULL)
+        XFREE((void*)curve->Gy, heap, DYNAMIC_TYPE_ECC_BUFFER);
+#endif
+
+    XFREE((void*)curve, heap, DYNAMIC_TYPE_ECC_BUFFER);
+
+    (void)heap;
+}
+#endif /* WOLFSSL_CUSTOM_CURVES */
+
+/**
+  Free an ECC key from memory
+  key   The key you wish to free
+*/
+WOLFSSL_ABI
+int wc_ecc_free(ecc_key* key)
+{
+    if (key == NULL) {
+        return 0;
+    }
+
+#ifdef WOLFSSL_ECDSA_SET_K
+    if (key->sign_k != NULL) {
+        mp_forcezero(key->sign_k);
+        mp_free(key->sign_k);
+        XFREE(key->sign_k, key->heap, DYNAMIC_TYPE_ECC);
+    }
+#endif
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
+    #ifdef WC_ASYNC_ENABLE_ECC
+    wolfAsync_DevCtxFree(&key->asyncDev, WOLFSSL_ASYNC_MARKER_ECC);
+    #endif
+    wc_ecc_free_async(key);
+#endif
+
+#ifdef WOLFSSL_ATECC508A
+    atmel_ecc_free(key->slot);
+    key->slot = ATECC_INVALID_SLOT;
+#endif /* WOLFSSL_ATECC508A */
+
+    mp_clear(key->pubkey.x);
+    mp_clear(key->pubkey.y);
+    mp_clear(key->pubkey.z);
+
+    mp_forcezero(&key->k);
+
+#ifdef WOLFSSL_CUSTOM_CURVES
+    if (key->deallocSet && key->dp != NULL)
+        wc_ecc_free_curve(key->dp, key->heap);
+#endif
+
+    return 0;
+}
+
+#if !defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL)
+#ifdef ECC_SHAMIR
+
+/** Computes kA*A + kB*B = C using Shamir's Trick
+  A        First point to multiply
+  kA       What to multiple A by
+  B        Second point to multiply
+  kB       What to multiple B by
+  C        [out] Destination point (can overlap with A or B)
+  a        ECC curve parameter a
+  modulus  Modulus for curve
+  return MP_OKAY on success
+*/
+#ifdef FP_ECC
+static int normal_ecc_mul2add(ecc_point* A, mp_int* kA,
+                             ecc_point* B, mp_int* kB,
+                             ecc_point* C, mp_int* a, mp_int* modulus,
+                             void* heap)
+#else
+int ecc_mul2add(ecc_point* A, mp_int* kA,
+                    ecc_point* B, mp_int* kB,
+                    ecc_point* C, mp_int* a, mp_int* modulus,
+                    void* heap)
+#endif
+{
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+  ecc_key        key;
+#endif
+#ifdef WOLFSSL_SMALL_STACK
+  ecc_point**    precomp = NULL;
+#else
+  ecc_point*     precomp[SHAMIR_PRECOMP_SZ];
+#endif
+  unsigned       bitbufA, bitbufB, lenA, lenB, len, nA, nB, nibble;
+  unsigned char* tA;
+  unsigned char* tB;
+  int            err = MP_OKAY, first, x, y;
+  mp_digit       mp = 0;
+
+  /* argchks */
+  if (A == NULL || kA == NULL || B == NULL || kB == NULL || C == NULL ||
+                                                         modulus == NULL) {
+     return ECC_BAD_ARG_E;
+  }
+
+  /* allocate memory */
+  tA = (unsigned char*)XMALLOC(ECC_BUFSIZE, heap, DYNAMIC_TYPE_ECC_BUFFER);
+  if (tA == NULL) {
+     return GEN_MEM_ERR;
+  }
+  tB = (unsigned char*)XMALLOC(ECC_BUFSIZE, heap, DYNAMIC_TYPE_ECC_BUFFER);
+  if (tB == NULL) {
+     XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER);
+     return GEN_MEM_ERR;
+  }
+#ifdef WOLFSSL_SMALL_STACK
+  precomp = (ecc_point**)XMALLOC(sizeof(ecc_point*) * SHAMIR_PRECOMP_SZ, heap,
+                                                       DYNAMIC_TYPE_ECC_BUFFER);
+  if (precomp == NULL) {
+     XFREE(tB, heap, DYNAMIC_TYPE_ECC_BUFFER);
+     XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER);
+     return GEN_MEM_ERR;
+  }
+#endif
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+  key.t1 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
+  key.t2 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
+#ifdef ALT_ECC_SIZE
+  key.x = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
+  key.y = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
+  key.z = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
+#endif
+  if (key.t1 == NULL || key.t2 == NULL
+#ifdef ALT_ECC_SIZE
+     || key.x == NULL || key.y == NULL || key.z == NULL
+#endif
+  ) {
+#ifdef ALT_ECC_SIZE
+      XFREE(key.z, heap, DYNAMIC_TYPE_ECC);
+      XFREE(key.y, heap, DYNAMIC_TYPE_ECC);
+      XFREE(key.x, heap, DYNAMIC_TYPE_ECC);
+#endif
+      XFREE(key.t2, heap, DYNAMIC_TYPE_ECC);
+      XFREE(key.t1, heap, DYNAMIC_TYPE_ECC);
+      XFREE(precomp, heap, DYNAMIC_TYPE_ECC_BUFFER);
+      XFREE(tB, heap, DYNAMIC_TYPE_ECC_BUFFER);
+      XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER);
+      return MEMORY_E;
+  }
+  C->key = &key;
+#endif /* WOLFSSL_SMALL_STACK_CACHE */
+
+  /* init variables */
+  XMEMSET(tA, 0, ECC_BUFSIZE);
+  XMEMSET(tB, 0, ECC_BUFSIZE);
+#ifndef WOLFSSL_SMALL_STACK
+  XMEMSET(precomp, 0, sizeof(precomp));
+#else
+  XMEMSET(precomp, 0, sizeof(ecc_point*) * SHAMIR_PRECOMP_SZ);
+#endif
+
+  /* get sizes */
+  lenA = mp_unsigned_bin_size(kA);
+  lenB = mp_unsigned_bin_size(kB);
+  len  = MAX(lenA, lenB);
+
+  /* sanity check */
+  if ((lenA > ECC_BUFSIZE) || (lenB > ECC_BUFSIZE)) {
+    err = BAD_FUNC_ARG;
+  }
+
+  if (err == MP_OKAY) {
+    /* extract and justify kA */
+    err = mp_to_unsigned_bin(kA, (len - lenA) + tA);
+
+    /* extract and justify kB */
+    if (err == MP_OKAY)
+        err = mp_to_unsigned_bin(kB, (len - lenB) + tB);
+
+    /* allocate the table */
+    if (err == MP_OKAY) {
+        for (x = 0; x < SHAMIR_PRECOMP_SZ; x++) {
+            precomp[x] = wc_ecc_new_point_h(heap);
+            if (precomp[x] == NULL) {
+                err = GEN_MEM_ERR;
+                break;
+            }
+        #ifdef WOLFSSL_SMALL_STACK_CACHE
+            precomp[x]->key = &key;
+        #endif
+        }
+    }
+  }
+
+  if (err == MP_OKAY)
+    /* init montgomery reduction */
+    err = mp_montgomery_setup(modulus, &mp);
+
+  if (err == MP_OKAY) {
+  #ifdef WOLFSSL_SMALL_STACK
+    mp_int* mu;
+  #else
+    mp_int  mu[1];
+  #endif
+  #ifdef WOLFSSL_SMALL_STACK
+    mu = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
+    if (mu == NULL)
+        err = MEMORY_E;
+  #endif
+    if (err == MP_OKAY) {
+        err = mp_init(mu);
+    }
+    if (err == MP_OKAY) {
+      err = mp_montgomery_calc_normalization(mu, modulus);
+
+      if (err == MP_OKAY)
+        /* copy ones ... */
+        err = mp_mulmod(A->x, mu, modulus, precomp[1]->x);
+
+      if (err == MP_OKAY)
+        err = mp_mulmod(A->y, mu, modulus, precomp[1]->y);
+      if (err == MP_OKAY)
+        err = mp_mulmod(A->z, mu, modulus, precomp[1]->z);
+
+      if (err == MP_OKAY)
+        err = mp_mulmod(B->x, mu, modulus, precomp[1<<2]->x);
+      if (err == MP_OKAY)
+        err = mp_mulmod(B->y, mu, modulus, precomp[1<<2]->y);
+      if (err == MP_OKAY)
+        err = mp_mulmod(B->z, mu, modulus, precomp[1<<2]->z);
+
+      /* done with mu */
+      mp_clear(mu);
+    }
+  #ifdef WOLFSSL_SMALL_STACK
+    if (mu != NULL) {
+      XFREE(mu, heap, DYNAMIC_TYPE_ECC);
+    }
+  #endif
+  }
+
+  if (err == MP_OKAY)
+    /* precomp [i,0](A + B) table */
+    err = ecc_projective_dbl_point(precomp[1], precomp[2], a, modulus, mp);
+
+  if (err == MP_OKAY)
+    err = ecc_projective_add_point(precomp[1], precomp[2], precomp[3],
+                                   a, modulus, mp);
+  if (err == MP_OKAY)
+    /* precomp [0,i](A + B) table */
+    err = ecc_projective_dbl_point(precomp[1<<2], precomp[2<<2], a, modulus, mp);
+
+  if (err == MP_OKAY)
+    err = ecc_projective_add_point(precomp[1<<2], precomp[2<<2], precomp[3<<2],
+                                   a, modulus, mp);
+
+  if (err == MP_OKAY) {
+    /* precomp [i,j](A + B) table (i != 0, j != 0) */
+    for (x = 1; x < 4; x++) {
+      for (y = 1; y < 4; y++) {
+        if (err == MP_OKAY) {
+          err = ecc_projective_add_point(precomp[x], precomp[(y<<2)],
+                                             precomp[x+(y<<2)], a, modulus, mp);
+        }
+      }
+    }
+  }
+
+  if (err == MP_OKAY) {
+    nibble  = 3;
+    first   = 1;
+    bitbufA = tA[0];
+    bitbufB = tB[0];
+
+    /* for every byte of the multiplicands */
+    for (x = 0;; ) {
+        /* grab a nibble */
+        if (++nibble == 4) {
+            if (x == (int)len) break;
+            bitbufA = tA[x];
+            bitbufB = tB[x];
+            nibble  = 0;
+            x++;
+        }
+
+        /* extract two bits from both, shift/update */
+        nA = (bitbufA >> 6) & 0x03;
+        nB = (bitbufB >> 6) & 0x03;
+        bitbufA = (bitbufA << 2) & 0xFF;
+        bitbufB = (bitbufB << 2) & 0xFF;
+
+        /* if both zero, if first, continue */
+        if ((nA == 0) && (nB == 0) && (first == 1)) {
+            continue;
+        }
+
+        /* double twice, only if this isn't the first */
+        if (first == 0) {
+            /* double twice */
+            if (err == MP_OKAY)
+                err = ecc_projective_dbl_point(C, C, a, modulus, mp);
+            if (err == MP_OKAY)
+                err = ecc_projective_dbl_point(C, C, a, modulus, mp);
+            else
+                break;
+        }
+
+        /* if not both zero */
+        if ((nA != 0) || (nB != 0)) {
+            if (first == 1) {
+                /* if first, copy from table */
+                first = 0;
+                if (err == MP_OKAY)
+                    err = mp_copy(precomp[nA + (nB<<2)]->x, C->x);
+
+                if (err == MP_OKAY)
+                    err = mp_copy(precomp[nA + (nB<<2)]->y, C->y);
+
+                if (err == MP_OKAY)
+                    err = mp_copy(precomp[nA + (nB<<2)]->z, C->z);
+                else
+                    break;
+            } else {
+                /* if not first, add from table */
+                if (err == MP_OKAY)
+                    err = ecc_projective_add_point(C, precomp[nA + (nB<<2)], C,
+                                                   a, modulus, mp);
+                if (err != MP_OKAY)
+                    break;
+                if (mp_iszero(C->z)) {
+                    /* When all zero then should have done an add */
+                    if (mp_iszero(C->x) && mp_iszero(C->y)) {
+                        err = ecc_projective_dbl_point(precomp[nA + (nB<<2)], C,
+                                                       a, modulus, mp);
+                        if (err != MP_OKAY)
+                            break;
+                    }
+                    /* When only Z zero then result is infinity */
+                    else {
+                        err = mp_set(C->x, 0);
+                        if (err != MP_OKAY)
+                            break;
+                        err = mp_set(C->y, 0);
+                        if (err != MP_OKAY)
+                            break;
+                        err = mp_set(C->z, 1);
+                        if (err != MP_OKAY)
+                            break;
+                        first = 1;
+                    }
+                }
+            }
+        }
+    }
+  }
+
+  /* reduce to affine */
+  if (err == MP_OKAY)
+    err = ecc_map(C, modulus, mp);
+
+  /* clean up */
+  for (x = 0; x < SHAMIR_PRECOMP_SZ; x++) {
+     wc_ecc_del_point_h(precomp[x], heap);
+  }
+
+  ForceZero(tA, ECC_BUFSIZE);
+  ForceZero(tB, ECC_BUFSIZE);
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+#ifdef ALT_ECC_SIZE
+  XFREE(key.z, heap, DYNAMIC_TYPE_ECC);
+  XFREE(key.y, heap, DYNAMIC_TYPE_ECC);
+  XFREE(key.x, heap, DYNAMIC_TYPE_ECC);
+#endif
+  XFREE(key.t2, heap, DYNAMIC_TYPE_ECC);
+  XFREE(key.t1, heap, DYNAMIC_TYPE_ECC);
+  C->key = NULL;
+#endif
+#ifdef WOLFSSL_SMALL_STACK
+  XFREE(precomp, heap, DYNAMIC_TYPE_ECC_BUFFER);
+#endif
+  XFREE(tB, heap, DYNAMIC_TYPE_ECC_BUFFER);
+  XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER);
+
+  return err;
+}
+
+#endif /* ECC_SHAMIR */
+#endif /* !WOLFSSL_SP_MATH && !WOLFSSL_ATECC508A && !WOLFSSL_CRYPTOCEL*/
+
+
+#ifdef HAVE_ECC_VERIFY
+#ifndef NO_ASN
+/* verify
+ *
+ * w  = s^-1 mod n
+ * u1 = xw
+ * u2 = rw
+ * X = u1*G + u2*Q
+ * v = X_x1 mod n
+ * accept if v == r
+ */
+
+/**
+ Verify an ECC signature
+ sig         The signature to verify
+ siglen      The length of the signature (octets)
+ hash        The hash (message digest) that was signed
+ hashlen     The length of the hash (octets)
+ res         Result of signature, 1==valid, 0==invalid
+ key         The corresponding public ECC key
+ return      MP_OKAY if successful (even if the signature is not valid)
+ */
+int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash,
+                       word32 hashlen, int* res, ecc_key* key)
+{
+    int err;
+    mp_int *r = NULL, *s = NULL;
+#if (!defined(WOLFSSL_ASYNC_CRYPT) || !defined(WC_ASYNC_ENABLE_ECC)) && \
+    !defined(WOLFSSL_SMALL_STACK)
+    mp_int r_lcl, s_lcl;
+#endif
+
+    if (sig == NULL || hash == NULL || res == NULL || key == NULL) {
+        return ECC_BAD_ARG_E;
+    }
+
+#ifdef WOLF_CRYPTO_CB
+    if (key->devId != INVALID_DEVID) {
+        err = wc_CryptoCb_EccVerify(sig, siglen, hash, hashlen, res, key);
+        if (err != CRYPTOCB_UNAVAILABLE)
+            return err;
+        /* fall-through when unavailable */
+    }
+#endif
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
+    err = wc_ecc_alloc_async(key);
+    if (err != 0)
+        return err;
+    r = key->r;
+    s = key->s;
+#else
+    #ifndef WOLFSSL_SMALL_STACK
+    r = &r_lcl;
+    s = &s_lcl;
+    #else
+    r = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
+    if (r == NULL)
+        return MEMORY_E;
+    s = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
+    if (s == NULL) {
+        XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
+        return MEMORY_E;
+    }
+    #endif
+    XMEMSET(r, 0, sizeof(mp_int));
+    XMEMSET(s, 0, sizeof(mp_int));
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    switch (key->state) {
+        case ECC_STATE_NONE:
+        case ECC_STATE_VERIFY_DECODE:
+            key->state = ECC_STATE_VERIFY_DECODE;
+
+            /* default to invalid signature */
+            *res = 0;
+
+            /* Note, DecodeECC_DSA_Sig() calls mp_init() on r and s.
+             * If either of those don't allocate correctly, none of
+             * the rest of this function will execute, and everything
+             * gets cleaned up at the end. */
+            /* decode DSA header */
+            err = DecodeECC_DSA_Sig(sig, siglen, r, s);
+            if (err < 0) {
+                break;
+            }
+            FALL_THROUGH;
+
+        case ECC_STATE_VERIFY_DO:
+            key->state = ECC_STATE_VERIFY_DO;
+
+            err = wc_ecc_verify_hash_ex(r, s, hash, hashlen, res, key);
+
+        #ifndef WOLFSSL_ASYNC_CRYPT
+            /* done with R/S */
+            mp_clear(r);
+            mp_clear(s);
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(s, key->heap, DYNAMIC_TYPE_ECC);
+            XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
+            r = NULL;
+            s = NULL;
+        #endif
+        #endif
+
+            if (err < 0) {
+                break;
+            }
+            FALL_THROUGH;
+
+        case ECC_STATE_VERIFY_RES:
+            key->state = ECC_STATE_VERIFY_RES;
+            err = 0;
+            break;
+
+        default:
+            err = BAD_STATE_E;
+    }
+
+    /* if async pending then return and skip done cleanup below */
+    if (err == WC_PENDING_E) {
+        key->state++;
+        return err;
+    }
+
+    /* cleanup */
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
+    wc_ecc_free_async(key);
+#elif defined(WOLFSSL_SMALL_STACK)
+    XFREE(s, key->heap, DYNAMIC_TYPE_ECC);
+    XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
+    r = NULL;
+    s = NULL;
+#endif
+
+    key->state = ECC_STATE_NONE;
+
+    return err;
+}
+#endif /* !NO_ASN */
+
+
+/**
+   Verify an ECC signature
+   r           The signature R component to verify
+   s           The signature S component to verify
+   hash        The hash (message digest) that was signed
+   hashlen     The length of the hash (octets)
+   res         Result of signature, 1==valid, 0==invalid
+   key         The corresponding public ECC key
+   return      MP_OKAY if successful (even if the signature is not valid)
+*/
+
+int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash,
+                    word32 hashlen, int* res, ecc_key* key)
+#if defined(WOLFSSL_STM32_PKA)
+{
+    return stm32_ecc_verify_hash_ex(r, s, hash, hashlen, res, key);
+}
+#else
+{
+   int           err;
+   word32        keySz;
+#ifdef WOLFSSL_ATECC508A
+   byte sigRS[ATECC_KEY_SIZE*2];
+#elif defined(WOLFSSL_CRYPTOCELL)
+   byte sigRS[ECC_MAX_CRYPTO_HW_SIZE*2];
+   CRYS_ECDSA_VerifyUserContext_t sigCtxTemp;
+   word32 msgLenInBytes = hashlen;
+   CRYS_ECPKI_HASH_OpMode_t hash_mode;
+#elif !defined(WOLFSSL_SP_MATH) || defined(FREESCALE_LTC_ECC)
+   int          did_init = 0;
+   ecc_point    *mG = NULL, *mQ = NULL;
+   #ifdef WOLFSSL_SMALL_STACK
+   mp_int*       v = NULL;
+   mp_int*       w = NULL;
+   mp_int*       u1 = NULL;
+   mp_int*       u2 = NULL;
+      #if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V)
+   mp_int*       e_lcl = NULL;
+      #endif
+   #else /* WOLFSSL_SMALL_STACK */
+   mp_int        v[1];
+   mp_int        w[1];
+   mp_int        u1[1];
+   mp_int        u2[1];
+      #if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V)
+   mp_int        e_lcl[1];
+      #endif
+   #endif /* WOLFSSL_SMALL_STACK */
+   mp_int*       e;
+   DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT);
+#endif
+
+   if (r == NULL || s == NULL || hash == NULL || res == NULL || key == NULL)
+       return ECC_BAD_ARG_E;
+
+   /* default to invalid signature */
+   *res = 0;
+
+   /* is the IDX valid ?  */
+   if (wc_ecc_is_valid_idx(key->idx) != 1) {
+      return ECC_BAD_ARG_E;
+   }
+
+   keySz = key->dp->size;
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \
+       defined(WOLFSSL_ASYNC_CRYPT_TEST)
+    if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) {
+        if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_ECC_VERIFY)) {
+            WC_ASYNC_TEST* testDev = &key->asyncDev.test;
+            testDev->eccVerify.r = r;
+            testDev->eccVerify.s = s;
+            testDev->eccVerify.hash = hash;
+            testDev->eccVerify.hashlen = hashlen;
+            testDev->eccVerify.stat = res;
+            testDev->eccVerify.key = key;
+            return WC_PENDING_E;
+        }
+    }
+#endif
+
+#ifdef WOLFSSL_ATECC508A
+    /* Extract R and S */
+    err = mp_to_unsigned_bin(r, &sigRS[0]);
+    if (err != MP_OKAY) {
+        return err;
+    }
+    err = mp_to_unsigned_bin(s, &sigRS[keySz]);
+    if (err != MP_OKAY) {
+        return err;
+    }
+
+    err = atmel_ecc_verify(hash, sigRS, key->pubkey_raw, res);
+    if (err != 0) {
+       return err;
+    }
+    (void)hashlen;
+#elif defined(WOLFSSL_CRYPTOCELL)
+
+   /* Extract R and S */
+
+   err = mp_to_unsigned_bin(r, &sigRS[0]);
+   if (err != MP_OKAY) {
+       return err;
+   }
+   err = mp_to_unsigned_bin(s, &sigRS[keySz]);
+   if (err != MP_OKAY) {
+       return err;
+   }
+
+   hash_mode = cc310_hashModeECC(msgLenInBytes);
+   if (hash_mode == CRYS_ECPKI_HASH_OpModeLast) {
+       /* hash_mode = */ cc310_hashModeECC(keySz);
+       hash_mode = CRYS_ECPKI_HASH_SHA256_mode;
+   }
+   /* truncate if hash is longer than key size */
+   if (msgLenInBytes > keySz) {
+       msgLenInBytes = keySz;
+   }
+
+   /* verify the signature using the public key */
+   err = CRYS_ECDSA_Verify(&sigCtxTemp,
+                           &key->ctx.pubKey,
+                           hash_mode,
+                           &sigRS[0],
+                           keySz*2,
+                           (byte*)hash,
+                           msgLenInBytes);
+
+   if (err != SA_SILIB_RET_OK) {
+       WOLFSSL_MSG("CRYS_ECDSA_Verify failed");
+       return err;
+   }
+   /* valid signature if we get to this point */
+   *res = 1;
+#else
+  /* checking if private key with no public part */
+  if (key->type == ECC_PRIVATEKEY_ONLY) {
+      WOLFSSL_MSG("Verify called with private key, generating public part");
+      err = wc_ecc_make_pub_ex(key, NULL, NULL);
+      if (err != MP_OKAY) {
+           WOLFSSL_MSG("Unable to extract public key");
+           return err;
+      }
+  }
+
+#if defined(WOLFSSL_DSP) && !defined(FREESCALE_LTC_ECC)
+  if (key->handle != -1) {
+      return sp_dsp_ecc_verify_256(key->handle, hash, hashlen, key->pubkey.x, key->pubkey.y,
+                                           key->pubkey.z, r, s, res, key->heap);
+  }
+  if (wolfSSL_GetHandleCbSet() == 1) {
+      return sp_dsp_ecc_verify_256(0, hash, hashlen, key->pubkey.x, key->pubkey.y,
+                                           key->pubkey.z, r, s, res, key->heap);
+  }
+#endif
+#if defined(WOLFSSL_SP_MATH) && !defined(FREESCALE_LTC_ECC)
+#ifndef WOLFSSL_SP_NO_256
+  if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) {
+      return sp_ecc_verify_256(hash, hashlen, key->pubkey.x, key->pubkey.y,
+                                           key->pubkey.z, r, s, res, key->heap);
+  }
+#endif
+#ifdef WOLFSSL_SP_384
+  if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) {
+      return sp_ecc_verify_384(hash, hashlen, key->pubkey.x, key->pubkey.y,
+                                           key->pubkey.z, r, s, res, key->heap);
+  }
+#endif
+  return WC_KEY_SIZE_E;
+#else
+#if defined WOLFSSL_HAVE_SP_ECC && !defined(FREESCALE_LTC_ECC)
+    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
+    if (key->asyncDev.marker != WOLFSSL_ASYNC_MARKER_ECC)
+    #endif
+    {
+#ifndef WOLFSSL_SP_NO_256
+        if (key->idx != ECC_CUSTOM_IDX &&
+                                       ecc_sets[key->idx].id == ECC_SECP256R1) {
+            return sp_ecc_verify_256(hash, hashlen, key->pubkey.x,
+                                         key->pubkey.y, key->pubkey.z,r, s, res,
+                                         key->heap);
+        }
+#endif /* WOLFSSL_SP_NO_256 */
+#ifdef WOLFSSL_SP_384
+        if (key->idx != ECC_CUSTOM_IDX &&
+                                       ecc_sets[key->idx].id == ECC_SECP384R1) {
+            return sp_ecc_verify_384(hash, hashlen, key->pubkey.x,
+                                         key->pubkey.y, key->pubkey.z,r, s, res,
+                                         key->heap);
+        }
+#endif /* WOLFSSL_SP_384 */
+    }
+#endif /* WOLFSSL_HAVE_SP_ECC */
+
+   ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT);
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM_V)
+   err = wc_ecc_alloc_mpint(key, &key->e);
+   if (err != 0) {
+      FREE_CURVE_SPECS();
+      return err;
+   }
+   e = key->e;
+#else
+#ifdef WOLFSSL_SMALL_STACK
+   e_lcl = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
+   if (e_lcl == NULL) {
+       FREE_CURVE_SPECS();
+       return MEMORY_E;
+   }
+#endif
+   e = e_lcl;
+#endif /* WOLFSSL_ASYNC_CRYPT && HAVE_CAVIUM_V */
+
+   err = mp_init(e);
+   if (err != MP_OKAY)
+      return MEMORY_E;
+
+   /* read in the specs for this curve */
+   err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL);
+
+   /* check for zero */
+   if (err == MP_OKAY) {
+       if (mp_iszero(r) == MP_YES || mp_iszero(s) == MP_YES ||
+           mp_cmp(r, curve->order) != MP_LT ||
+           mp_cmp(s, curve->order) != MP_LT) {
+           err = MP_ZERO_E;
+       }
+   }
+
+   /* read hash */
+   if (err == MP_OKAY) {
+       /* we may need to truncate if hash is longer than key size */
+       unsigned int orderBits = mp_count_bits(curve->order);
+
+       /* truncate down to byte size, may be all that's needed */
+       if ( (WOLFSSL_BIT_SIZE * hashlen) > orderBits)
+           hashlen = (orderBits + WOLFSSL_BIT_SIZE - 1) / WOLFSSL_BIT_SIZE;
+       err = mp_read_unsigned_bin(e, hash, hashlen);
+
+       /* may still need bit truncation too */
+       if (err == MP_OKAY && (WOLFSSL_BIT_SIZE * hashlen) > orderBits)
+           mp_rshb(e, WOLFSSL_BIT_SIZE - (orderBits & 0x7));
+   }
+
+   /* check for async hardware acceleration */
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
+   if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) {
+   #if defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA)
+   #ifdef HAVE_CAVIUM_V
+      if (NitroxEccIsCurveSupported(key))
+   #endif
+      {
+          err = wc_mp_to_bigint_sz(e, &e->raw, keySz);
+          if (err == MP_OKAY)
+              err = wc_mp_to_bigint_sz(key->pubkey.x, &key->pubkey.x->raw, keySz);
+          if (err == MP_OKAY)
+              err = wc_mp_to_bigint_sz(key->pubkey.y, &key->pubkey.y->raw, keySz);
+          if (err == MP_OKAY)
+          #ifdef HAVE_CAVIUM_V
+              err = NitroxEcdsaVerify(key, &e->raw, &key->pubkey.x->raw,
+                    &key->pubkey.y->raw, &r->raw, &s->raw,
+                    &curve->prime->raw, &curve->order->raw, res);
+          #else
+              err = IntelQaEcdsaVerify(&key->asyncDev, &e->raw, &key->pubkey.x->raw,
+                    &key->pubkey.y->raw, &r->raw, &s->raw, &curve->Af->raw,
+                    &curve->Bf->raw, &curve->prime->raw, &curve->order->raw,
+                    &curve->Gx->raw, &curve->Gy->raw, res);
+          #endif
+
+      #ifndef HAVE_CAVIUM_V
+          mp_clear(e);
+      #endif
+          wc_ecc_curve_free(curve);
+          FREE_CURVE_SPECS();
+
+          return err;
+      }
+   #endif /* HAVE_CAVIUM_V || HAVE_INTEL_QA */
+   }
+#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_ECC */
+
+#ifdef WOLFSSL_SMALL_STACK
+   if (err == MP_OKAY) {
+       v = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
+       if (v == NULL)
+           err = MEMORY_E;
+   }
+   if (err == MP_OKAY) {
+       w = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
+       if (w == NULL)
+           err = MEMORY_E;
+   }
+   if (err == MP_OKAY) {
+       u1 = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
+       if (u1 == NULL)
+           err = MEMORY_E;
+   }
+   if (err == MP_OKAY) {
+       u2 = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
+       if (u2 == NULL)
+           err = MEMORY_E;
+   }
+#endif
+
+   /* allocate ints */
+   if (err == MP_OKAY) {
+       if ((err = mp_init_multi(v, w, u1, u2, NULL, NULL)) != MP_OKAY) {
+          err = MEMORY_E;
+       }
+       did_init = 1;
+   }
+
+   /* allocate points */
+   if (err == MP_OKAY) {
+       mG = wc_ecc_new_point_h(key->heap);
+       mQ = wc_ecc_new_point_h(key->heap);
+       if (mQ  == NULL || mG == NULL)
+          err = MEMORY_E;
+   }
+
+   /*  w  = s^-1 mod n */
+   if (err == MP_OKAY)
+       err = mp_invmod(s, curve->order, w);
+
+   /* u1 = ew */
+   if (err == MP_OKAY)
+       err = mp_mulmod(e, w, curve->order, u1);
+
+   /* u2 = rw */
+   if (err == MP_OKAY)
+       err = mp_mulmod(r, w, curve->order, u2);
+
+   /* find mG and mQ */
+   if (err == MP_OKAY)
+       err = mp_copy(curve->Gx, mG->x);
+   if (err == MP_OKAY)
+       err = mp_copy(curve->Gy, mG->y);
+   if (err == MP_OKAY)
+       err = mp_set(mG->z, 1);
+
+   if (err == MP_OKAY)
+       err = mp_copy(key->pubkey.x, mQ->x);
+   if (err == MP_OKAY)
+       err = mp_copy(key->pubkey.y, mQ->y);
+   if (err == MP_OKAY)
+       err = mp_copy(key->pubkey.z, mQ->z);
+
+#if defined(FREESCALE_LTC_ECC)
+   /* use PKHA to compute u1*mG + u2*mQ */
+   if (err == MP_OKAY)
+       err = wc_ecc_mulmod_ex(u1, mG, mG, curve->Af, curve->prime, 0, key->heap);
+   if (err == MP_OKAY)
+       err = wc_ecc_mulmod_ex(u2, mQ, mQ, curve->Af, curve->prime, 0, key->heap);
+   if (err == MP_OKAY)
+       err = wc_ecc_point_add(mG, mQ, mG, curve->prime);
+#else
+#ifndef ECC_SHAMIR
+    if (err == MP_OKAY)
+    {
+        mp_digit mp = 0;
+
+        if (!mp_iszero(u1)) {
+            /* compute u1*mG + u2*mQ = mG */
+            err = wc_ecc_mulmod_ex(u1, mG, mG, curve->Af, curve->prime, 0,
+                                                                     key->heap);
+            if (err == MP_OKAY) {
+                err = wc_ecc_mulmod_ex(u2, mQ, mQ, curve->Af, curve->prime, 0,
+                                                                     key->heap);
+            }
+
+            /* find the montgomery mp */
+            if (err == MP_OKAY)
+                err = mp_montgomery_setup(curve->prime, &mp);
+
+            /* add them */
+            if (err == MP_OKAY)
+                err = ecc_projective_add_point(mQ, mG, mG, curve->Af,
+                                                              curve->prime, mp);
+            if (err == MP_OKAY && mp_iszero(mG->z)) {
+                /* When all zero then should have done an add */
+                if (mp_iszero(mG->x) && mp_iszero(mG->y)) {
+                    err = ecc_projective_dbl_point(mQ, mG, curve->Af,
+                                                              curve->prime, mp);
+                }
+                /* When only Z zero then result is infinity */
+                else {
+                    err = mp_set(mG->x, 0);
+                    if (err == MP_OKAY)
+                        err = mp_set(mG->y, 0);
+                    if (err == MP_OKAY)
+                        err = mp_set(mG->z, 1);
+                }
+            }
+        }
+        else {
+            /* compute 0*mG + u2*mQ = mG */
+            err = wc_ecc_mulmod_ex(u2, mQ, mG, curve->Af, curve->prime, 0,
+                                                                     key->heap);
+            /* find the montgomery mp */
+            if (err == MP_OKAY)
+                err = mp_montgomery_setup(curve->prime, &mp);
+        }
+
+        /* reduce */
+        if (err == MP_OKAY)
+            err = ecc_map(mG, curve->prime, mp);
+    }
+#else
+    /* use Shamir's trick to compute u1*mG + u2*mQ using half the doubles */
+    if (err == MP_OKAY) {
+        err = ecc_mul2add(mG, u1, mQ, u2, mG, curve->Af, curve->prime,
+                                                                     key->heap);
+    }
+#endif /* ECC_SHAMIR */
+#endif /* FREESCALE_LTC_ECC */
+   /* v = X_x1 mod n */
+   if (err == MP_OKAY)
+       err = mp_mod(mG->x, curve->order, v);
+
+   /* does v == r */
+   if (err == MP_OKAY) {
+       if (mp_cmp(v, r) == MP_EQ)
+           *res = 1;
+   }
+
+   /* cleanup */
+   wc_ecc_del_point_h(mG, key->heap);
+   wc_ecc_del_point_h(mQ, key->heap);
+
+   mp_clear(e);
+   if (did_init) {
+       mp_clear(v);
+       mp_clear(w);
+       mp_clear(u1);
+       mp_clear(u2);
+   }
+#ifdef WOLFSSL_SMALL_STACK
+   XFREE(u2, key->heap, DYNAMIC_TYPE_ECC);
+   XFREE(u1, key->heap, DYNAMIC_TYPE_ECC);
+   XFREE(w, key->heap, DYNAMIC_TYPE_ECC);
+   XFREE(v, key->heap, DYNAMIC_TYPE_ECC);
+#if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V)
+   XFREE(e_lcl, key->heap, DYNAMIC_TYPE_ECC);
+#endif
+#endif
+
+   wc_ecc_curve_free(curve);
+   FREE_CURVE_SPECS();
+
+#endif /* WOLFSSL_SP_MATH */
+#endif /* WOLFSSL_ATECC508A */
+
+   (void)keySz;
+   (void)hashlen;
+
+   return err;
+}
+#endif /* WOLFSSL_STM32_PKA */
+#endif /* HAVE_ECC_VERIFY */
+
+#ifdef HAVE_ECC_KEY_IMPORT
+/* import point from der
+ * if shortKeySize != 0 then keysize is always (inLen-1)>>1 */
+int wc_ecc_import_point_der_ex(byte* in, word32 inLen, const int curve_idx,
+                               ecc_point* point, int shortKeySize)
+{
+    int err = 0;
+#ifdef HAVE_COMP_KEY
+    int compressed = 0;
+#endif
+    int keysize;
+    byte pointType;
+
+#ifndef HAVE_COMP_KEY
+    (void)shortKeySize;
+#endif
+
+    if (in == NULL || point == NULL || (curve_idx < 0) ||
+        (wc_ecc_is_valid_idx(curve_idx) == 0))
+        return ECC_BAD_ARG_E;
+
+    /* must be odd */
+    if ((inLen & 1) == 0) {
+        return ECC_BAD_ARG_E;
+    }
+
+    /* init point */
+#ifdef ALT_ECC_SIZE
+    point->x = (mp_int*)&point->xyz[0];
+    point->y = (mp_int*)&point->xyz[1];
+    point->z = (mp_int*)&point->xyz[2];
+    alt_fp_init(point->x);
+    alt_fp_init(point->y);
+    alt_fp_init(point->z);
+#else
+    err = mp_init_multi(point->x, point->y, point->z, NULL, NULL, NULL);
+#endif
+    if (err != MP_OKAY)
+        return MEMORY_E;
+
+    /* check for point type (4, 2, or 3) */
+    pointType = in[0];
+    if (pointType != ECC_POINT_UNCOMP && pointType != ECC_POINT_COMP_EVEN &&
+                                         pointType != ECC_POINT_COMP_ODD) {
+        err = ASN_PARSE_E;
+    }
+
+    if (pointType == ECC_POINT_COMP_EVEN || pointType == ECC_POINT_COMP_ODD) {
+#ifdef HAVE_COMP_KEY
+        compressed = 1;
+#else
+        err = NOT_COMPILED_IN;
+#endif
+    }
+
+    /* adjust to skip first byte */
+    inLen -= 1;
+    in += 1;
+
+    /* calculate key size based on inLen / 2 if uncompressed or shortKeySize
+     * is true */
+#ifdef HAVE_COMP_KEY
+    keysize = compressed && !shortKeySize ? inLen : inLen>>1;
+#else
+    keysize = inLen>>1;
+#endif
+
+    /* read data */
+    if (err == MP_OKAY)
+        err = mp_read_unsigned_bin(point->x, (byte*)in, keysize);
+
+#ifdef HAVE_COMP_KEY
+    if (err == MP_OKAY && compressed == 1) {   /* build y */
+#ifndef WOLFSSL_SP_MATH
+        int did_init = 0;
+        mp_int t1, t2;
+        DECLARE_CURVE_SPECS(curve, 3);
+
+        ALLOC_CURVE_SPECS(3);
+
+        if (mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL) != MP_OKAY)
+            err = MEMORY_E;
+        else
+            did_init = 1;
+
+        /* load curve info */
+        if (err == MP_OKAY)
+            err = wc_ecc_curve_load(&ecc_sets[curve_idx], &curve,
+                (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF |
+                    ECC_CURVE_FIELD_BF));
+
+        /* compute x^3 */
+        if (err == MP_OKAY)
+            err = mp_sqr(point->x, &t1);
+        if (err == MP_OKAY)
+            err = mp_mulmod(&t1, point->x, curve->prime, &t1);
+
+        /* compute x^3 + a*x */
+        if (err == MP_OKAY)
+            err = mp_mulmod(curve->Af, point->x, curve->prime, &t2);
+        if (err == MP_OKAY)
+            err = mp_add(&t1, &t2, &t1);
+
+        /* compute x^3 + a*x + b */
+        if (err == MP_OKAY)
+            err = mp_add(&t1, curve->Bf, &t1);
+
+        /* compute sqrt(x^3 + a*x + b) */
+        if (err == MP_OKAY)
+            err = mp_sqrtmod_prime(&t1, curve->prime, &t2);
+
+        /* adjust y */
+        if (err == MP_OKAY) {
+            if ((mp_isodd(&t2) == MP_YES && pointType == ECC_POINT_COMP_ODD) ||
+                (mp_isodd(&t2) == MP_NO &&  pointType == ECC_POINT_COMP_EVEN)) {
+                err = mp_mod(&t2, curve->prime, point->y);
+            }
+            else {
+                err = mp_submod(curve->prime, &t2, curve->prime, point->y);
+            }
+        }
+
+        if (did_init) {
+            mp_clear(&t2);
+            mp_clear(&t1);
+        }
+
+        wc_ecc_curve_free(curve);
+        FREE_CURVE_SPECS();
+#else
+    #ifndef WOLFSSL_SP_NO_256
+        if (curve_idx != ECC_CUSTOM_IDX &&
+                                      ecc_sets[curve_idx].id == ECC_SECP256R1) {
+            sp_ecc_uncompress_256(point->x, pointType, point->y);
+        }
+        else
+    #endif
+    #ifdef WOLFSSL_SP_384
+        if (curve_idx != ECC_CUSTOM_IDX &&
+                                      ecc_sets[curve_idx].id == ECC_SECP384R1) {
+            sp_ecc_uncompress_384(point->x, pointType, point->y);
+        }
+        else
+    #endif
+        {
+            err = WC_KEY_SIZE_E;
+        }
+#endif
+    }
+#endif
+
+    if (err == MP_OKAY) {
+#ifdef HAVE_COMP_KEY
+        if (compressed == 0)
+#endif
+            err = mp_read_unsigned_bin(point->y, (byte*)in + keysize, keysize);
+     }
+    if (err == MP_OKAY)
+        err = mp_set(point->z, 1);
+
+    if (err != MP_OKAY) {
+        mp_clear(point->x);
+        mp_clear(point->y);
+        mp_clear(point->z);
+    }
+
+    return err;
+}
+
+/* function for backwards compatiblity with previous implementations */
+int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx,
+                            ecc_point* point)
+{
+    return wc_ecc_import_point_der_ex(in, inLen, curve_idx, point, 1);
+}
+#endif /* HAVE_ECC_KEY_IMPORT */
+
+#ifdef HAVE_ECC_KEY_EXPORT
+/* export point to der */
+
+int wc_ecc_export_point_der_ex(const int curve_idx, ecc_point* point, byte* out,
+                               word32* outLen, int compressed)
+{
+    if (compressed == 0)
+        return wc_ecc_export_point_der(curve_idx, point, out, outLen);
+#ifdef HAVE_COMP_KEY
+    else
+        return wc_ecc_export_point_der_compressed(curve_idx, point, out, outLen);
+#else
+    return NOT_COMPILED_IN;
+#endif
+}
+
+int wc_ecc_export_point_der(const int curve_idx, ecc_point* point, byte* out,
+                            word32* outLen)
+{
+    int    ret = MP_OKAY;
+    word32 numlen;
+#ifdef WOLFSSL_SMALL_STACK
+    byte*  buf;
+#else
+    byte   buf[ECC_BUFSIZE];
+#endif
+
+    if ((curve_idx < 0) || (wc_ecc_is_valid_idx(curve_idx) == 0))
+        return ECC_BAD_ARG_E;
+
+    numlen = ecc_sets[curve_idx].size;
+
+    /* return length needed only */
+    if (point != NULL && out == NULL && outLen != NULL) {
+        *outLen = 1 + 2*numlen;
+        return LENGTH_ONLY_E;
+    }
+
+    if (point == NULL || out == NULL || outLen == NULL)
+        return ECC_BAD_ARG_E;
+
+    if (*outLen < (1 + 2*numlen)) {
+        *outLen = 1 + 2*numlen;
+        return BUFFER_E;
+    }
+
+    /* store byte point type */
+    out[0] = ECC_POINT_UNCOMP;
+
+#ifdef WOLFSSL_SMALL_STACK
+    buf = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER);
+    if (buf == NULL)
+        return MEMORY_E;
+#endif
+
+    /* pad and store x */
+    XMEMSET(buf, 0, ECC_BUFSIZE);
+    ret = mp_to_unsigned_bin(point->x, buf +
+                                 (numlen - mp_unsigned_bin_size(point->x)));
+    if (ret != MP_OKAY)
+        goto done;
+    XMEMCPY(out+1, buf, numlen);
+
+    /* pad and store y */
+    XMEMSET(buf, 0, ECC_BUFSIZE);
+    ret = mp_to_unsigned_bin(point->y, buf +
+                                 (numlen - mp_unsigned_bin_size(point->y)));
+    if (ret != MP_OKAY)
+        goto done;
+    XMEMCPY(out+1+numlen, buf, numlen);
+
+    *outLen = 1 + 2*numlen;
+
+done:
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(buf, NULL, DYNAMIC_TYPE_ECC_BUFFER);
+#endif
+
+    return ret;
+}
+
+
+/* export point to der */
+#ifdef HAVE_COMP_KEY
+int wc_ecc_export_point_der_compressed(const int curve_idx, ecc_point* point,
+                                       byte* out, word32* outLen)
+{
+    int    ret = MP_OKAY;
+    word32 numlen;
+    word32 output_len;
+#ifdef WOLFSSL_SMALL_STACK
+    byte*  buf;
+#else
+    byte   buf[ECC_BUFSIZE];
+#endif
+
+    if ((curve_idx < 0) || (wc_ecc_is_valid_idx(curve_idx) == 0))
+        return ECC_BAD_ARG_E;
+
+    numlen = ecc_sets[curve_idx].size;
+    output_len = 1 + numlen; /* y point type + x */
+
+    /* return length needed only */
+    if (point != NULL && out == NULL && outLen != NULL) {
+        *outLen = output_len;
+        return LENGTH_ONLY_E;
+    }
+
+    if (point == NULL || out == NULL || outLen == NULL)
+        return ECC_BAD_ARG_E;
+
+
+    if (*outLen < output_len) {
+        *outLen = output_len;
+        return BUFFER_E;
+    }
+
+    /* store byte point type */
+    out[0] = mp_isodd(point->y) == MP_YES ? ECC_POINT_COMP_ODD :
+                                            ECC_POINT_COMP_EVEN;
+
+#ifdef WOLFSSL_SMALL_STACK
+    buf = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER);
+    if (buf == NULL)
+        return MEMORY_E;
+#endif
+
+    /* pad and store x */
+    XMEMSET(buf, 0, ECC_BUFSIZE);
+    ret = mp_to_unsigned_bin(point->x, buf +
+                                 (numlen - mp_unsigned_bin_size(point->x)));
+    if (ret != MP_OKAY)
+        goto done;
+    XMEMCPY(out+1, buf, numlen);
+
+    *outLen = output_len;
+
+done:
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(buf, NULL, DYNAMIC_TYPE_ECC_BUFFER);
+#endif
+
+    return ret;
+}
+#endif /* HAVE_COMP_KEY */
+
+/* export public ECC key in ANSI X9.63 format */
+int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen)
+{
+   int    ret = MP_OKAY;
+   word32 numlen;
+#ifdef WOLFSSL_SMALL_STACK
+   byte*  buf;
+#else
+   byte   buf[ECC_BUFSIZE];
+#endif
+   word32 pubxlen, pubylen;
+
+   /* return length needed only */
+   if (key != NULL && out == NULL && outLen != NULL) {
+      /* if key hasn't been setup assume max bytes for size estimation */
+      numlen = key->dp ? key->dp->size : MAX_ECC_BYTES;
+      *outLen = 1 + 2*numlen;
+      return LENGTH_ONLY_E;
+   }
+
+   if (key == NULL || out == NULL || outLen == NULL)
+      return ECC_BAD_ARG_E;
+
+   if (key->type == ECC_PRIVATEKEY_ONLY)
+       return ECC_PRIVATEONLY_E;
+
+   if (wc_ecc_is_valid_idx(key->idx) == 0 || key->dp == NULL) {
+      return ECC_BAD_ARG_E;
+   }
+   numlen = key->dp->size;
+
+    /* verify room in out buffer */
+   if (*outLen < (1 + 2*numlen)) {
+      *outLen = 1 + 2*numlen;
+      return BUFFER_E;
+   }
+
+   /* verify public key length is less than key size */
+   pubxlen = mp_unsigned_bin_size(key->pubkey.x);
+   pubylen = mp_unsigned_bin_size(key->pubkey.y);
+   if ((pubxlen > numlen) || (pubylen > numlen)) {
+      WOLFSSL_MSG("Public key x/y invalid!");
+      return BUFFER_E;
+   }
+
+   /* store byte point type */
+   out[0] = ECC_POINT_UNCOMP;
+
+#ifdef WOLFSSL_SMALL_STACK
+   buf = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER);
+   if (buf == NULL)
+      return MEMORY_E;
+#endif
+
+   /* pad and store x */
+   XMEMSET(buf, 0, ECC_BUFSIZE);
+   ret = mp_to_unsigned_bin(key->pubkey.x, buf + (numlen - pubxlen));
+   if (ret != MP_OKAY)
+      goto done;
+   XMEMCPY(out+1, buf, numlen);
+
+   /* pad and store y */
+   XMEMSET(buf, 0, ECC_BUFSIZE);
+   ret = mp_to_unsigned_bin(key->pubkey.y, buf + (numlen - pubylen));
+   if (ret != MP_OKAY)
+      goto done;
+   XMEMCPY(out+1+numlen, buf, numlen);
+
+   *outLen = 1 + 2*numlen;
+
+done:
+#ifdef WOLFSSL_SMALL_STACK
+   XFREE(buf, NULL, DYNAMIC_TYPE_ECC_BUFFER);
+#endif
+
+   return ret;
+}
+
+
+/* export public ECC key in ANSI X9.63 format, extended with
+ * compression option */
+int wc_ecc_export_x963_ex(ecc_key* key, byte* out, word32* outLen,
+                          int compressed)
+{
+    if (compressed == 0)
+        return wc_ecc_export_x963(key, out, outLen);
+#ifdef HAVE_COMP_KEY
+    else
+        return wc_ecc_export_x963_compressed(key, out, outLen);
+#else
+    return NOT_COMPILED_IN;
+#endif
+}
+#endif /* HAVE_ECC_KEY_EXPORT */
+
+
+#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL)
+
+/* is ecc point on curve described by dp ? */
+int wc_ecc_is_point(ecc_point* ecp, mp_int* a, mp_int* b, mp_int* prime)
+{
+#ifndef WOLFSSL_SP_MATH
+   int err;
+#ifdef WOLFSSL_SMALL_STACK
+   mp_int* t1;
+   mp_int* t2;
+#else
+   mp_int  t1[1], t2[1];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+   t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+   if (t1 == NULL)
+       return MEMORY_E;
+   t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+   if (t2 == NULL) {
+       XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+       return MEMORY_E;
+   }
+#endif
+
+   if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
+   #ifdef WOLFSSL_SMALL_STACK
+      XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+      XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+   #endif
+      return err;
+   }
+
+   /* compute y^2 */
+   if (err == MP_OKAY)
+       err = mp_sqr(ecp->y, t1);
+
+   /* compute x^3 */
+   if (err == MP_OKAY)
+       err = mp_sqr(ecp->x, t2);
+   if (err == MP_OKAY)
+       err = mp_mod(t2, prime, t2);
+   if (err == MP_OKAY)
+       err = mp_mul(ecp->x, t2, t2);
+
+   /* compute y^2 - x^3 */
+   if (err == MP_OKAY)
+       err = mp_sub(t1, t2, t1);
+
+   /* Determine if curve "a" should be used in calc */
+#ifdef WOLFSSL_CUSTOM_CURVES
+   if (err == MP_OKAY) {
+      /* Use a and prime to determine if a == 3 */
+      err = mp_set(t2, 0);
+      if (err == MP_OKAY)
+          err = mp_submod(prime, a, prime, t2);
+   }
+   if (err == MP_OKAY && mp_cmp_d(t2, 3) != MP_EQ) {
+      /* compute y^2 - x^3 + a*x */
+      if (err == MP_OKAY)
+          err = mp_mulmod(t2, ecp->x, prime, t2);
+      if (err == MP_OKAY)
+          err = mp_addmod(t1, t2, prime, t1);
+   }
+   else
+#endif /* WOLFSSL_CUSTOM_CURVES */
+   {
+      /* assumes "a" == 3 */
+      (void)a;
+
+      /* compute y^2 - x^3 + 3x */
+      if (err == MP_OKAY)
+          err = mp_add(t1, ecp->x, t1);
+      if (err == MP_OKAY)
+          err = mp_add(t1, ecp->x, t1);
+      if (err == MP_OKAY)
+          err = mp_add(t1, ecp->x, t1);
+      if (err == MP_OKAY)
+          err = mp_mod(t1, prime, t1);
+  }
+
+   /* adjust range (0, prime) */
+   while (err == MP_OKAY && mp_isneg(t1)) {
+      err = mp_add(t1, prime, t1);
+   }
+   while (err == MP_OKAY && mp_cmp(t1, prime) != MP_LT) {
+      err = mp_sub(t1, prime, t1);
+   }
+
+   /* compare to b */
+   if (err == MP_OKAY) {
+       if (mp_cmp(t1, b) != MP_EQ) {
+          err = MP_VAL;
+       } else {
+          err = MP_OKAY;
+       }
+   }
+
+   mp_clear(t1);
+   mp_clear(t2);
+#ifdef WOLFSSL_SMALL_STACK
+   XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
+   XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
+#endif
+
+   return err;
+#else
+   (void)a;
+   (void)b;
+
+#ifndef WOLFSSL_SP_NO_256
+   if (mp_count_bits(prime) == 256) {
+       return sp_ecc_is_point_256(ecp->x, ecp->y);
+   }
+#endif
+#ifdef WOLFSSL_SP_384
+   if (mp_count_bits(prime) == 384) {
+       return sp_ecc_is_point_384(ecp->x, ecp->y);
+   }
+#endif
+   return WC_KEY_SIZE_E;
+#endif
+}
+
+#ifndef WOLFSSL_SP_MATH
+/* validate privkey * generator == pubkey, 0 on success */
+static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime)
+{
+    int        err = MP_OKAY;
+    ecc_point* base = NULL;
+    ecc_point* res  = NULL;
+    DECLARE_CURVE_SPECS(curve, 2);
+
+    if (key == NULL)
+        return BAD_FUNC_ARG;
+
+    ALLOC_CURVE_SPECS(2);
+
+    res = wc_ecc_new_point_h(key->heap);
+    if (res == NULL)
+        err = MEMORY_E;
+
+#ifdef WOLFSSL_HAVE_SP_ECC
+#ifndef WOLFSSL_SP_NO_256
+    if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) {
+        if (err == MP_OKAY) {
+            err = sp_ecc_mulmod_base_256(&key->k, res, 1, key->heap);
+        }
+    }
+    else
+#endif
+#ifdef WOLFSSL_SP_384
+    if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) {
+        if (err == MP_OKAY) {
+            err = sp_ecc_mulmod_base_384(&key->k, res, 1, key->heap);
+        }
+    }
+    else
+#endif
+#endif
+    {
+        base = wc_ecc_new_point_h(key->heap);
+        if (base == NULL)
+            err = MEMORY_E;
+
+        if (err == MP_OKAY) {
+            /* load curve info */
+            err = wc_ecc_curve_load(key->dp, &curve,
+                                      (ECC_CURVE_FIELD_GX | ECC_CURVE_FIELD_GY));
+        }
+
+        /* set up base generator */
+        if (err == MP_OKAY)
+            err = mp_copy(curve->Gx, base->x);
+        if (err == MP_OKAY)
+            err = mp_copy(curve->Gy, base->y);
+        if (err == MP_OKAY)
+            err = mp_set(base->z, 1);
+
+        if (err == MP_OKAY)
+            err = wc_ecc_mulmod_ex(&key->k, base, res, a, prime, 1, key->heap);
+    }
+
+    if (err == MP_OKAY) {
+        /* compare result to public key */
+        if (mp_cmp(res->x, key->pubkey.x) != MP_EQ ||
+            mp_cmp(res->y, key->pubkey.y) != MP_EQ ||
+            mp_cmp(res->z, key->pubkey.z) != MP_EQ) {
+            /* didn't match */
+            err = ECC_PRIV_KEY_E;
+        }
+    }
+
+    wc_ecc_curve_free(curve);
+    wc_ecc_del_point_h(res, key->heap);
+    wc_ecc_del_point_h(base, key->heap);
+    FREE_CURVE_SPECS();
+
+    return err;
+}
+#endif
+
+#ifdef WOLFSSL_VALIDATE_ECC_IMPORT
+
+/* check privkey generator helper, creates prime needed */
+static int ecc_check_privkey_gen_helper(ecc_key* key)
+{
+    int    err;
+#ifndef WOLFSSL_ATECC508A
+    DECLARE_CURVE_SPECS(curve, 2);
+#endif
+
+    if (key == NULL)
+        return BAD_FUNC_ARG;
+
+#ifdef WOLFSSL_ATECC508A
+    /* Hardware based private key, so this operation is not supported */
+    err = MP_OKAY; /* just report success */
+
+#else
+    ALLOC_CURVE_SPECS(2);
+
+    /* load curve info */
+    err = wc_ecc_curve_load(key->dp, &curve,
+        (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF));
+
+    if (err == MP_OKAY)
+        err = ecc_check_privkey_gen(key, curve->Af, curve->prime);
+
+    wc_ecc_curve_free(curve);
+    FREE_CURVE_SPECS();
+
+#endif /* WOLFSSL_ATECC508A */
+
+    return err;
+}
+
+#endif /* WOLFSSL_VALIDATE_ECC_IMPORT */
+
+#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || !defined(WOLFSSL_SP_MATH)
+/* validate order * pubkey = point at infinity, 0 on success */
+static int ecc_check_pubkey_order(ecc_key* key, ecc_point* pubkey, mp_int* a,
+        mp_int* prime, mp_int* order)
+{
+    ecc_point* inf = NULL;
+    int        err;
+
+    if (key == NULL)
+        return BAD_FUNC_ARG;
+
+    inf = wc_ecc_new_point_h(key->heap);
+    if (inf == NULL)
+        err = MEMORY_E;
+    else {
+#ifdef WOLFSSL_HAVE_SP_ECC
+#ifndef WOLFSSL_SP_NO_256
+        if (key->idx != ECC_CUSTOM_IDX &&
+                                       ecc_sets[key->idx].id == ECC_SECP256R1) {
+            err = sp_ecc_mulmod_256(order, pubkey, inf, 1, key->heap);
+        }
+        else
+#endif
+#ifdef WOLFSSL_SP_384
+        if (key->idx != ECC_CUSTOM_IDX &&
+                                       ecc_sets[key->idx].id == ECC_SECP384R1) {
+            err = sp_ecc_mulmod_384(order, pubkey, inf, 1, key->heap);
+        }
+        else
+#endif
+#endif
+#ifndef WOLFSSL_SP_MATH
+            err = wc_ecc_mulmod_ex(order, pubkey, inf, a, prime, 1, key->heap);
+        if (err == MP_OKAY && !wc_ecc_point_is_at_infinity(inf))
+            err = ECC_INF_E;
+#else
+            (void)a;
+            (void)prime;
+
+            err = WC_KEY_SIZE_E;
+#endif
+    }
+
+    wc_ecc_del_point_h(inf, key->heap);
+
+    return err;
+}
+#endif
+#endif /* !WOLFSSL_ATECC508A && !WOLFSSL_CRYPTOCELL*/
+
+#ifdef OPENSSL_EXTRA
+int wc_ecc_get_generator(ecc_point* ecp, int curve_idx)
+{
+    int err = MP_OKAY;
+    DECLARE_CURVE_SPECS(curve, 2);
+
+    if (!ecp || curve_idx < 0 || curve_idx > (int)(ECC_SET_COUNT-1))
+        return BAD_FUNC_ARG;
+
+    ALLOC_CURVE_SPECS(2);
+
+    err = wc_ecc_curve_load(&ecc_sets[curve_idx], &curve,
+                            (ECC_CURVE_FIELD_GX | ECC_CURVE_FIELD_GY));
+    if (err == MP_OKAY)
+        err = mp_copy(curve->Gx, ecp->x);
+    if (err == MP_OKAY)
+        err = mp_copy(curve->Gy, ecp->y);
+    if (err == MP_OKAY)
+        err = mp_set(ecp->z, 1);
+
+    wc_ecc_curve_free(curve);
+    FREE_CURVE_SPECS();
+
+    return err;
+}
+#endif /* OPENSSLALL */
+
+/* perform sanity checks on ecc key validity, 0 on success */
+int wc_ecc_check_key(ecc_key* key)
+{
+    int    err;
+#ifndef WOLFSSL_SP_MATH
+#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL)
+    mp_int* b = NULL;
+#ifdef USE_ECC_B_PARAM
+    DECLARE_CURVE_SPECS(curve, 4);
+#else
+#ifndef WOLFSSL_SMALL_STACK
+    mp_int b_lcl;
+#endif
+    DECLARE_CURVE_SPECS(curve, 3);
+#endif /* USE_ECC_B_PARAM */
+#endif /* WOLFSSL_ATECC508A */
+
+    if (key == NULL)
+        return BAD_FUNC_ARG;
+
+#if defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_CRYPTOCELL)
+
+    err = 0; /* consider key check success on ATECC508A */
+
+#else
+    #ifdef USE_ECC_B_PARAM
+        ALLOC_CURVE_SPECS(4);
+    #else
+        ALLOC_CURVE_SPECS(3);
+        #ifndef WOLFSSL_SMALL_STACK
+            b = &b_lcl;
+        #else
+            b = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
+            if (b == NULL) {
+                FREE_CURVE_SPECS();
+                return MEMORY_E;
+            }
+        #endif
+        XMEMSET(b, 0, sizeof(mp_int));
+    #endif
+
+    /* SP 800-56Ar3, section 5.6.2.3.3, process step 1 */
+    /* pubkey point cannot be at infinity */
+    if (wc_ecc_point_is_at_infinity(&key->pubkey)) {
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(b, key->heap, DYNAMIC_TYPE_ECC);
+    #endif
+        FREE_CURVE_SPECS();
+        return ECC_INF_E;
+    }
+
+    /* load curve info */
+    err = wc_ecc_curve_load(key->dp, &curve, (ECC_CURVE_FIELD_PRIME |
+            ECC_CURVE_FIELD_AF | ECC_CURVE_FIELD_ORDER
+#ifdef USE_ECC_B_PARAM
+            | ECC_CURVE_FIELD_BF
+#endif
+    ));
+
+#ifndef USE_ECC_B_PARAM
+    /* load curve b parameter */
+    if (err == MP_OKAY)
+        err = mp_init(b);
+    if (err == MP_OKAY)
+        err = mp_read_radix(b, key->dp->Bf, MP_RADIX_HEX);
+#else
+    if (err == MP_OKAY)
+        b = curve->Bf;
+#endif
+
+    /* SP 800-56Ar3, section 5.6.2.3.3, process step 2 */
+    /* Qx must be in the range [0, p-1] */
+    if (err == MP_OKAY) {
+        if (mp_cmp(key->pubkey.x, curve->prime) != MP_LT)
+            err = ECC_OUT_OF_RANGE_E;
+    }
+
+    /* Qy must be in the range [0, p-1] */
+    if (err == MP_OKAY) {
+        if (mp_cmp(key->pubkey.y, curve->prime) != MP_LT)
+            err = ECC_OUT_OF_RANGE_E;
+    }
+
+    /* SP 800-56Ar3, section 5.6.2.3.3, process steps 3 */
+    /* make sure point is actually on curve */
+    if (err == MP_OKAY)
+        err = wc_ecc_is_point(&key->pubkey, curve->Af, b, curve->prime);
+
+    /* SP 800-56Ar3, section 5.6.2.3.3, process steps 4 */
+    /* pubkey * order must be at infinity */
+    if (err == MP_OKAY)
+        err = ecc_check_pubkey_order(key, &key->pubkey, curve->Af, curve->prime,
+                curve->order);
+
+    /* SP 800-56Ar3, section 5.6.2.1.4, method (b) for ECC */
+    /* private * base generator must equal pubkey */
+    if (err == MP_OKAY && key->type == ECC_PRIVATEKEY)
+        err = ecc_check_privkey_gen(key, curve->Af, curve->prime);
+
+    wc_ecc_curve_free(curve);
+
+#ifndef USE_ECC_B_PARAM
+    mp_clear(b);
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(b, key->heap, DYNAMIC_TYPE_ECC);
+    #endif
+#endif
+
+    FREE_CURVE_SPECS();
+
+#endif /* WOLFSSL_ATECC508A */
+#else
+    if (key == NULL)
+        return BAD_FUNC_ARG;
+
+    /* pubkey point cannot be at infinity */
+#ifndef WOLFSSL_SP_NO_256
+    if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) {
+        err = sp_ecc_check_key_256(key->pubkey.x, key->pubkey.y, &key->k,
+                                                                     key->heap);
+    }
+    else
+#endif
+#ifdef WOLFSSL_SP_384
+    if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) {
+        err = sp_ecc_check_key_384(key->pubkey.x, key->pubkey.y, &key->k,
+                                                                     key->heap);
+    }
+    else
+#endif
+    {
+        err = WC_KEY_SIZE_E;
+    }
+#endif
+
+    return err;
+}
+
+#ifdef HAVE_ECC_KEY_IMPORT
+/* import public ECC key in ANSI X9.63 format */
+int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key,
+                          int curve_id)
+{
+    int err = MP_OKAY;
+#ifdef HAVE_COMP_KEY
+    int compressed = 0;
+#endif
+    int keysize = 0;
+    byte pointType;
+
+    if (in == NULL || key == NULL)
+        return BAD_FUNC_ARG;
+
+    /* must be odd */
+    if ((inLen & 1) == 0) {
+        return ECC_BAD_ARG_E;
+    }
+
+    /* make sure required variables are reset */
+    wc_ecc_reset(key);
+
+    /* init key */
+    #ifdef ALT_ECC_SIZE
+        key->pubkey.x = (mp_int*)&key->pubkey.xyz[0];
+        key->pubkey.y = (mp_int*)&key->pubkey.xyz[1];
+        key->pubkey.z = (mp_int*)&key->pubkey.xyz[2];
+        alt_fp_init(key->pubkey.x);
+        alt_fp_init(key->pubkey.y);
+        alt_fp_init(key->pubkey.z);
+        err = mp_init(&key->k);
+    #else
+        err = mp_init_multi(&key->k,
+                    key->pubkey.x, key->pubkey.y, key->pubkey.z, NULL, NULL);
+    #endif
+    if (err != MP_OKAY)
+        return MEMORY_E;
+
+    /* check for point type (4, 2, or 3) */
+    pointType = in[0];
+    if (pointType != ECC_POINT_UNCOMP && pointType != ECC_POINT_COMP_EVEN &&
+                                         pointType != ECC_POINT_COMP_ODD) {
+        err = ASN_PARSE_E;
+    }
+
+    if (pointType == ECC_POINT_COMP_EVEN || pointType == ECC_POINT_COMP_ODD) {
+    #ifdef HAVE_COMP_KEY
+        compressed = 1;
+    #else
+        err = NOT_COMPILED_IN;
+    #endif
+    }
+
+    /* adjust to skip first byte */
+    inLen -= 1;
+    in += 1;
+
+#ifdef WOLFSSL_ATECC508A
+    /* For SECP256R1 only save raw public key for hardware */
+    if (curve_id == ECC_SECP256R1 && inLen <= sizeof(key->pubkey_raw)) {
+    #ifdef HAVE_COMP_KEY
+        if (!compressed)
+    #endif
+            XMEMCPY(key->pubkey_raw, (byte*)in, inLen);
+    }
+#endif
+
+    if (err == MP_OKAY) {
+    #ifdef HAVE_COMP_KEY
+        /* adjust inLen if compressed */
+        if (compressed)
+            inLen = inLen*2 + 1;  /* used uncompressed len */
+    #endif
+
+        /* determine key size */
+        keysize = (inLen>>1);
+        err = wc_ecc_set_curve(key, keysize, curve_id);
+        key->type = ECC_PUBLICKEY;
+    }
+
+    /* read data */
+    if (err == MP_OKAY)
+        err = mp_read_unsigned_bin(key->pubkey.x, (byte*)in, keysize);
+
+#ifdef HAVE_COMP_KEY
+    if (err == MP_OKAY && compressed == 1) {   /* build y */
+#ifndef WOLFSSL_SP_MATH
+        mp_int t1, t2;
+        int did_init = 0;
+
+        DECLARE_CURVE_SPECS(curve, 3);
+        ALLOC_CURVE_SPECS(3);
+
+        if (mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL) != MP_OKAY)
+            err = MEMORY_E;
+        else
+            did_init = 1;
+
+        /* load curve info */
+        if (err == MP_OKAY)
+            err = wc_ecc_curve_load(key->dp, &curve,
+                (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF |
+                 ECC_CURVE_FIELD_BF));
+
+        /* compute x^3 */
+        if (err == MP_OKAY)
+            err = mp_sqr(key->pubkey.x, &t1);
+        if (err == MP_OKAY)
+            err = mp_mulmod(&t1, key->pubkey.x, curve->prime, &t1);
+
+        /* compute x^3 + a*x */
+        if (err == MP_OKAY)
+            err = mp_mulmod(curve->Af, key->pubkey.x, curve->prime, &t2);
+        if (err == MP_OKAY)
+            err = mp_add(&t1, &t2, &t1);
+
+        /* compute x^3 + a*x + b */
+        if (err == MP_OKAY)
+            err = mp_add(&t1, curve->Bf, &t1);
+
+        /* compute sqrt(x^3 + a*x + b) */
+        if (err == MP_OKAY)
+            err = mp_sqrtmod_prime(&t1, curve->prime, &t2);
+
+        /* adjust y */
+        if (err == MP_OKAY) {
+            if ((mp_isodd(&t2) == MP_YES && pointType == ECC_POINT_COMP_ODD) ||
+                (mp_isodd(&t2) == MP_NO &&  pointType == ECC_POINT_COMP_EVEN)) {
+                err = mp_mod(&t2, curve->prime, &t2);
+            }
+            else {
+                err = mp_submod(curve->prime, &t2, curve->prime, &t2);
+            }
+            if (err == MP_OKAY)
+                err = mp_copy(&t2, key->pubkey.y);
+        }
+
+        if (did_init) {
+            mp_clear(&t2);
+            mp_clear(&t1);
+        }
+
+        wc_ecc_curve_free(curve);
+        FREE_CURVE_SPECS();
+#else
+    #ifndef WOLFSSL_SP_NO_256
+        if (key->dp->id == ECC_SECP256R1) {
+            sp_ecc_uncompress_256(key->pubkey.x, pointType, key->pubkey.y);
+        }
+        else
+    #endif
+    #ifdef WOLFSSL_SP_384
+        if (key->dp->id == ECC_SECP384R1) {
+            sp_ecc_uncompress_384(key->pubkey.x, pointType, key->pubkey.y);
+        }
+        else
+    #endif
+        {
+            err = WC_KEY_SIZE_E;
+        }
+#endif
+    }
+#endif /* HAVE_COMP_KEY */
+
+    if (err == MP_OKAY) {
+    #ifdef HAVE_COMP_KEY
+        if (compressed == 0)
+    #endif
+        {
+            err = mp_read_unsigned_bin(key->pubkey.y, (byte*)in + keysize,
+                                                                      keysize);
+        }
+    }
+    if (err == MP_OKAY)
+        err = mp_set(key->pubkey.z, 1);
+
+#ifdef WOLFSSL_VALIDATE_ECC_IMPORT
+    if (err == MP_OKAY)
+        err = wc_ecc_check_key(key);
+#endif
+
+    if (err != MP_OKAY) {
+        mp_clear(key->pubkey.x);
+        mp_clear(key->pubkey.y);
+        mp_clear(key->pubkey.z);
+        mp_clear(&key->k);
+    }
+
+    return err;
+}
+
+WOLFSSL_ABI
+int wc_ecc_import_x963(const byte* in, word32 inLen, ecc_key* key)
+{
+    return wc_ecc_import_x963_ex(in, inLen, key, ECC_CURVE_DEF);
+}
+#endif /* HAVE_ECC_KEY_IMPORT */
+
+#ifdef HAVE_ECC_KEY_EXPORT
+
+/* export ecc key to component form, d is optional if only exporting public
+ * encType is WC_TYPE_UNSIGNED_BIN or WC_TYPE_HEX_STR
+ * return MP_OKAY on success */
+int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen,
+                 byte* qy, word32* qyLen, byte* d, word32* dLen, int encType)
+{
+    int err = 0;
+    word32 keySz;
+
+    if (key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (wc_ecc_is_valid_idx(key->idx) == 0) {
+        return ECC_BAD_ARG_E;
+    }
+    keySz = key->dp->size;
+
+    /* private key, d */
+    if (d != NULL) {
+        if (dLen == NULL ||
+            (key->type != ECC_PRIVATEKEY && key->type != ECC_PRIVATEKEY_ONLY))
+            return BAD_FUNC_ARG;
+
+    #ifdef WOLFSSL_ATECC508A
+        /* Hardware cannot export private portion */
+        return NOT_COMPILED_IN;
+    #else
+        err = wc_export_int(&key->k, d, dLen, keySz, encType);
+        if (err != MP_OKAY)
+            return err;
+    #endif
+    }
+
+    /* public x component */
+    if (qx != NULL) {
+        if (qxLen == NULL || key->type == ECC_PRIVATEKEY_ONLY)
+            return BAD_FUNC_ARG;
+
+        err = wc_export_int(key->pubkey.x, qx, qxLen, keySz, encType);
+        if (err != MP_OKAY)
+            return err;
+    }
+
+    /* public y component */
+    if (qy != NULL) {
+        if (qyLen == NULL || key->type == ECC_PRIVATEKEY_ONLY)
+            return BAD_FUNC_ARG;
+
+        err = wc_export_int(key->pubkey.y, qy, qyLen, keySz, encType);
+        if (err != MP_OKAY)
+            return err;
+    }
+
+    return err;
+}
+
+
+/* export ecc private key only raw, outLen is in/out size as unsigned bin
+   return MP_OKAY on success */
+int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen)
+{
+    if (out == NULL || outLen == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    return wc_ecc_export_ex(key, NULL, NULL, NULL, NULL, out, outLen,
+        WC_TYPE_UNSIGNED_BIN);
+}
+
+/* export public key to raw elements including public (Qx,Qy) as unsigned bin
+ * return MP_OKAY on success, negative on error */
+int wc_ecc_export_public_raw(ecc_key* key, byte* qx, word32* qxLen,
+                             byte* qy, word32* qyLen)
+{
+    if (qx == NULL || qxLen == NULL || qy == NULL || qyLen == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    return wc_ecc_export_ex(key, qx, qxLen, qy, qyLen, NULL, NULL,
+        WC_TYPE_UNSIGNED_BIN);
+}
+
+/* export ecc key to raw elements including public (Qx,Qy) and
+ *   private (d) as unsigned bin
+ * return MP_OKAY on success, negative on error */
+int wc_ecc_export_private_raw(ecc_key* key, byte* qx, word32* qxLen,
+                              byte* qy, word32* qyLen, byte* d, word32* dLen)
+{
+    return wc_ecc_export_ex(key, qx, qxLen, qy, qyLen, d, dLen,
+        WC_TYPE_UNSIGNED_BIN);
+}
+
+#endif /* HAVE_ECC_KEY_EXPORT */
+
+#ifdef HAVE_ECC_KEY_IMPORT
+/* import private key, public part optional if (pub) passed as NULL */
+int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz,
+                                 const byte* pub, word32 pubSz, ecc_key* key,
+                                 int curve_id)
+{
+    int ret;
+#if defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_ATECC508A)
+    const CRYS_ECPKI_Domain_t* pDomain;
+    CRYS_ECPKI_BUILD_TempData_t tempBuff;
+#endif
+    if (key == NULL || priv == NULL)
+        return BAD_FUNC_ARG;
+
+    /* public optional, NULL if only importing private */
+    if (pub != NULL) {
+    #ifndef NO_ASN
+        word32 idx = 0;
+        ret = wc_ecc_import_x963_ex(pub, pubSz, key, curve_id);
+        if (ret < 0)
+            ret = wc_EccPublicKeyDecode(pub, &idx, key, pubSz);
+        key->type = ECC_PRIVATEKEY;
+    #else
+        ret = NOT_COMPILED_IN;
+    #endif
+    }
+    else {
+        /* make sure required variables are reset */
+        wc_ecc_reset(key);
+
+        /* set key size */
+        ret = wc_ecc_set_curve(key, privSz, curve_id);
+        key->type = ECC_PRIVATEKEY_ONLY;
+    }
+
+    if (ret != 0)
+        return ret;
+
+#ifdef WOLFSSL_ATECC508A
+    /* Hardware does not support loading private keys */
+    return NOT_COMPILED_IN;
+#elif defined(WOLFSSL_CRYPTOCELL)
+    pDomain = CRYS_ECPKI_GetEcDomain(cc310_mapCurve(curve_id));
+
+    if (pub != NULL && pub[0] != '\0') {
+        /* create public key from external key buffer */
+        ret = CRYS_ECPKI_BuildPublKeyFullCheck(pDomain,
+                                               (byte*)pub,
+                                               pubSz,
+                                               &key->ctx.pubKey,
+                                               &tempBuff);
+
+        if (ret != SA_SILIB_RET_OK){
+            WOLFSSL_MSG("CRYS_ECPKI_BuildPublKeyFullCheck failed");
+            return ret;
+        }
+    }
+    /* import private key */
+    if (priv != NULL && priv[0] != '\0') {
+
+        /* Create private key from external key buffer*/
+        ret = CRYS_ECPKI_BuildPrivKey(pDomain,
+                                      priv,
+                                      privSz,
+                                      &key->ctx.privKey);
+
+        if (ret != SA_SILIB_RET_OK) {
+            WOLFSSL_MSG("CRYS_ECPKI_BuildPrivKey failed");
+            return ret;
+        }
+
+        ret = mp_read_unsigned_bin(&key->k, priv, privSz);
+    }
+
+#else
+
+    ret = mp_read_unsigned_bin(&key->k, priv, privSz);
+#ifdef HAVE_WOLF_BIGINT
+    if (ret == 0 &&
+                  wc_bigint_from_unsigned_bin(&key->k.raw, priv, privSz) != 0) {
+        mp_clear(&key->k);
+        ret = ASN_GETINT_E;
+    }
+#endif /* HAVE_WOLF_BIGINT */
+
+
+#endif /* WOLFSSL_ATECC508A */
+
+#ifdef WOLFSSL_VALIDATE_ECC_IMPORT
+    if ((pub != NULL) && (ret == MP_OKAY))
+        /* public key needed to perform key validation */
+        ret = ecc_check_privkey_gen_helper(key);
+#endif
+
+    return ret;
+}
+
+/* ecc private key import, public key in ANSI X9.63 format, private raw */
+int wc_ecc_import_private_key(const byte* priv, word32 privSz, const byte* pub,
+                           word32 pubSz, ecc_key* key)
+{
+    return wc_ecc_import_private_key_ex(priv, privSz, pub, pubSz, key,
+                                                                ECC_CURVE_DEF);
+}
+#endif /* HAVE_ECC_KEY_IMPORT */
+
+#ifndef NO_ASN
+/**
+   Convert ECC R,S to signature
+   r       R component of signature
+   s       S component of signature
+   out     DER-encoded ECDSA signature
+   outlen  [in/out] output buffer size, output signature size
+   return  MP_OKAY on success
+*/
+int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen)
+{
+    int err;
+#ifdef WOLFSSL_SMALL_STACK
+    mp_int* rtmp = NULL;
+    mp_int* stmp = NULL;
+#else
+    mp_int  rtmp[1];
+    mp_int  stmp[1];
+#endif
+
+    if (r == NULL || s == NULL || out == NULL || outlen == NULL)
+        return ECC_BAD_ARG_E;
+
+#ifdef WOLFSSL_SMALL_STACK
+    rtmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+    if (rtmp == NULL)
+        return MEMORY_E;
+    stmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+    if (stmp == NULL) {
+        XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
+        return MEMORY_E;
+    }
+#endif
+
+    err = mp_init_multi(rtmp, stmp, NULL, NULL, NULL, NULL);
+    if (err != MP_OKAY) {
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(stmp, NULL, DYNAMIC_TYPE_ECC);
+        XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
+    #endif
+        return err;
+    }
+
+    err = mp_read_radix(rtmp, r, MP_RADIX_HEX);
+    if (err == MP_OKAY)
+        err = mp_read_radix(stmp, s, MP_RADIX_HEX);
+
+    /* convert mp_ints to ECDSA sig, initializes rtmp and stmp internally */
+    if (err == MP_OKAY)
+        err = StoreECC_DSA_Sig(out, outlen, rtmp, stmp);
+
+    if (err == MP_OKAY) {
+        if (mp_iszero(rtmp) == MP_YES || mp_iszero(stmp) == MP_YES)
+            err = MP_ZERO_E;
+    }
+
+    mp_clear(rtmp);
+    mp_clear(stmp);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(stmp, NULL, DYNAMIC_TYPE_ECC);
+    XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
+#endif
+
+    return err;
+}
+
+/**
+   Convert ECC R,S raw unsigned bin to signature
+   r       R component of signature
+   rSz     R size
+   s       S component of signature
+   sSz     S size
+   out     DER-encoded ECDSA signature
+   outlen  [in/out] output buffer size, output signature size
+   return  MP_OKAY on success
+*/
+int wc_ecc_rs_raw_to_sig(const byte* r, word32 rSz, const byte* s, word32 sSz,
+    byte* out, word32* outlen)
+{
+    int err;
+#ifdef WOLFSSL_SMALL_STACK
+    mp_int* rtmp = NULL;
+    mp_int* stmp = NULL;
+#else
+    mp_int  rtmp[1];
+    mp_int  stmp[1];
+#endif
+
+    if (r == NULL || s == NULL || out == NULL || outlen == NULL)
+        return ECC_BAD_ARG_E;
+
+#ifdef WOLFSSL_SMALL_STACK
+    rtmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+    if (rtmp == NULL)
+        return MEMORY_E;
+    stmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+    if (stmp == NULL) {
+        XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
+        return MEMORY_E;
+    }
+#endif
+
+    err = mp_init_multi(rtmp, stmp, NULL, NULL, NULL, NULL);
+    if (err != MP_OKAY) {
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(stmp, NULL, DYNAMIC_TYPE_ECC);
+        XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
+    #endif
+        return err;
+    }
+
+    err = mp_read_unsigned_bin(rtmp, r, rSz);
+    if (err == MP_OKAY)
+        err = mp_read_unsigned_bin(stmp, s, sSz);
+
+    /* convert mp_ints to ECDSA sig, initializes rtmp and stmp internally */
+    if (err == MP_OKAY)
+        err = StoreECC_DSA_Sig(out, outlen, rtmp, stmp);
+
+    if (err == MP_OKAY) {
+        if (mp_iszero(rtmp) == MP_YES || mp_iszero(stmp) == MP_YES)
+            err = MP_ZERO_E;
+    }
+
+    mp_clear(rtmp);
+    mp_clear(stmp);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(stmp, NULL, DYNAMIC_TYPE_ECC);
+    XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
+#endif
+
+    return err;
+}
+
+/**
+   Convert ECC signature to R,S
+   sig     DER-encoded ECDSA signature
+   sigLen  length of signature in octets
+   r       R component of signature
+   rLen    [in/out] output "r" buffer size, output "r" size
+   s       S component of signature
+   sLen    [in/out] output "s" buffer size, output "s" size
+   return  MP_OKAY on success, negative on error
+*/
+int wc_ecc_sig_to_rs(const byte* sig, word32 sigLen, byte* r, word32* rLen,
+                     byte* s, word32* sLen)
+{
+    int err;
+    int tmp_valid = 0;
+    word32 x = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    mp_int* rtmp = NULL;
+    mp_int* stmp = NULL;
+#else
+    mp_int  rtmp[1];
+    mp_int  stmp[1];
+#endif
+
+    if (sig == NULL || r == NULL || rLen == NULL || s == NULL || sLen == NULL)
+        return ECC_BAD_ARG_E;
+
+#ifdef WOLFSSL_SMALL_STACK
+    rtmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+    if (rtmp == NULL)
+        return MEMORY_E;
+    stmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+    if (stmp == NULL) {
+        XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
+        return MEMORY_E;
+    }
+#endif
+
+    err = DecodeECC_DSA_Sig(sig, sigLen, rtmp, stmp);
+
+    /* rtmp and stmp are initialized */
+    if (err == MP_OKAY) {
+        tmp_valid = 1;
+
+        /* extract r */
+        x = mp_unsigned_bin_size(rtmp);
+        if (*rLen < x)
+            err = BUFFER_E;
+    }
+    if (err == MP_OKAY) {
+        *rLen = x;
+        err = mp_to_unsigned_bin(rtmp, r);
+    }
+
+    /* extract s */
+    if (err == MP_OKAY) {
+        x = mp_unsigned_bin_size(stmp);
+        if (*sLen < x)
+            err = BUFFER_E;
+
+        if (err == MP_OKAY) {
+            *sLen = x;
+            err = mp_to_unsigned_bin(stmp, s);
+        }
+    }
+
+    if (tmp_valid) {
+        mp_clear(rtmp);
+        mp_clear(stmp);
+    }
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(stmp, NULL, DYNAMIC_TYPE_ECC);
+    XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
+#endif
+
+    return err;
+}
+#endif /* !NO_ASN */
+
+#ifdef HAVE_ECC_KEY_IMPORT
+static int wc_ecc_import_raw_private(ecc_key* key, const char* qx,
+          const char* qy, const char* d, int curve_id, int encType)
+{
+    int err = MP_OKAY;
+#if defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_ATECC508A)
+    const CRYS_ECPKI_Domain_t* pDomain;
+    CRYS_ECPKI_BUILD_TempData_t tempBuff;
+    byte key_raw[ECC_MAX_CRYPTO_HW_SIZE*2 + 1];
+    word32 keySz = 0;
+#endif
+    /* if d is NULL, only import as public key using Qx,Qy */
+    if (key == NULL || qx == NULL || qy == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* make sure required variables are reset */
+    wc_ecc_reset(key);
+
+    /* set curve type and index */
+    err = wc_ecc_set_curve(key, 0, curve_id);
+    if (err != 0) {
+        return err;
+    }
+
+    /* init key */
+#ifdef ALT_ECC_SIZE
+    key->pubkey.x = (mp_int*)&key->pubkey.xyz[0];
+    key->pubkey.y = (mp_int*)&key->pubkey.xyz[1];
+    key->pubkey.z = (mp_int*)&key->pubkey.xyz[2];
+    alt_fp_init(key->pubkey.x);
+    alt_fp_init(key->pubkey.y);
+    alt_fp_init(key->pubkey.z);
+    err = mp_init(&key->k);
+#else
+    err = mp_init_multi(&key->k, key->pubkey.x, key->pubkey.y, key->pubkey.z,
+                                                                  NULL, NULL);
+#endif
+    if (err != MP_OKAY)
+        return MEMORY_E;
+
+    /* read Qx */
+    if (err == MP_OKAY) {
+        if (encType == WC_TYPE_HEX_STR)
+            err = mp_read_radix(key->pubkey.x, qx, MP_RADIX_HEX);
+        else
+            err = mp_read_unsigned_bin(key->pubkey.x, (const byte*)qx,
+                key->dp->size);
+    }
+
+    /* read Qy */
+    if (err == MP_OKAY) {
+        if (encType == WC_TYPE_HEX_STR)
+            err = mp_read_radix(key->pubkey.y, qy, MP_RADIX_HEX);
+        else
+            err = mp_read_unsigned_bin(key->pubkey.y, (const byte*)qy,
+                key->dp->size);
+
+    }
+
+    if (err == MP_OKAY)
+        err = mp_set(key->pubkey.z, 1);
+
+#ifdef WOLFSSL_ATECC508A
+    /* For SECP256R1 only save raw public key for hardware */
+    if (err == MP_OKAY && curve_id == ECC_SECP256R1) {
+        word32 keySz = key->dp->size;
+        err = wc_export_int(key->pubkey.x, key->pubkey_raw,
+            &keySz, keySz, WC_TYPE_UNSIGNED_BIN);
+        if (err == MP_OKAY)
+            err = wc_export_int(key->pubkey.y, &key->pubkey_raw[keySz],
+                &keySz, keySz, WC_TYPE_UNSIGNED_BIN);
+    }
+#elif defined(WOLFSSL_CRYPTOCELL)
+    if (err == MP_OKAY) {
+        key_raw[0] = ECC_POINT_UNCOMP;
+        keySz = (word32)key->dp->size;
+        err = wc_export_int(key->pubkey.x, &key_raw[1], &keySz, keySz,
+            WC_TYPE_UNSIGNED_BIN);
+        if (err == MP_OKAY) {
+            err = wc_export_int(key->pubkey.y, &key_raw[1+keySz],
+                &keySz, keySz, WC_TYPE_UNSIGNED_BIN);
+        }
+
+        if (err == MP_OKAY) {
+            pDomain = CRYS_ECPKI_GetEcDomain(cc310_mapCurve(curve_id));
+
+            /* create public key from external key buffer */
+            err = CRYS_ECPKI_BuildPublKeyFullCheck(pDomain,
+                                                   key_raw,
+                                                   keySz*2 + 1,
+                                                   &key->ctx.pubKey,
+                                                   &tempBuff);
+        }
+
+        if (err != SA_SILIB_RET_OK){
+            WOLFSSL_MSG("CRYS_ECPKI_BuildPublKeyFullCheck failed");
+            return err;
+        }
+    }
+
+#endif
+
+    /* import private key */
+    if (err == MP_OKAY) {
+        if (d != NULL && d[0] != '\0') {
+        #ifdef WOLFSSL_ATECC508A
+            /* Hardware doesn't support loading private key */
+            err = NOT_COMPILED_IN;
+
+        #elif defined(WOLFSSL_CRYPTOCELL)
+
+            key->type = ECC_PRIVATEKEY;
+
+            if (encType == WC_TYPE_HEX_STR)
+                err = mp_read_radix(&key->k, d, MP_RADIX_HEX);
+            else
+                err = mp_read_unsigned_bin(&key->k, (const byte*)d,
+                    key->dp->size);
+            if (err == MP_OKAY) {
+                err = wc_export_int(&key->k, &key_raw[0], &keySz, keySz,
+                    WC_TYPE_UNSIGNED_BIN);
+            }
+
+            if (err == MP_OKAY) {
+                /* Create private key from external key buffer*/
+                err = CRYS_ECPKI_BuildPrivKey(pDomain,
+                                              key_raw,
+                                              keySz,
+                                              &key->ctx.privKey);
+
+                if (err != SA_SILIB_RET_OK){
+                    WOLFSSL_MSG("CRYS_ECPKI_BuildPrivKey failed");
+                    return err;
+                }
+            }
+
+        #else
+            key->type = ECC_PRIVATEKEY;
+
+            if (encType == WC_TYPE_HEX_STR)
+                err = mp_read_radix(&key->k, d, MP_RADIX_HEX);
+            else
+                err = mp_read_unsigned_bin(&key->k, (const byte*)d,
+                    key->dp->size);
+        #endif /* WOLFSSL_ATECC508A */
+        } else {
+            key->type = ECC_PUBLICKEY;
+        }
+    }
+
+#ifdef WOLFSSL_VALIDATE_ECC_IMPORT
+    if (err == MP_OKAY)
+        err = wc_ecc_check_key(key);
+#endif
+
+    if (err != MP_OKAY) {
+        mp_clear(key->pubkey.x);
+        mp_clear(key->pubkey.y);
+        mp_clear(key->pubkey.z);
+        mp_clear(&key->k);
+    }
+
+    return err;
+}
+
+/**
+   Import raw ECC key
+   key       The destination ecc_key structure
+   qx        x component of the public key, as ASCII hex string
+   qy        y component of the public key, as ASCII hex string
+   d         private key, as ASCII hex string, optional if importing public
+             key only
+   dp        Custom ecc_set_type
+   return    MP_OKAY on success
+*/
+int wc_ecc_import_raw_ex(ecc_key* key, const char* qx, const char* qy,
+                   const char* d, int curve_id)
+{
+    return wc_ecc_import_raw_private(key, qx, qy, d, curve_id,
+        WC_TYPE_HEX_STR);
+
+}
+
+/* Import x, y and optional private (d) as unsigned binary */
+int wc_ecc_import_unsigned(ecc_key* key, byte* qx, byte* qy,
+                   byte* d, int curve_id)
+{
+    return wc_ecc_import_raw_private(key, (const char*)qx, (const char*)qy,
+        (const char*)d, curve_id, WC_TYPE_UNSIGNED_BIN);
+}
+
+/**
+   Import raw ECC key
+   key       The destination ecc_key structure
+   qx        x component of the public key, as ASCII hex string
+   qy        y component of the public key, as ASCII hex string
+   d         private key, as ASCII hex string, optional if importing public
+             key only
+   curveName ECC curve name, from ecc_sets[]
+   return    MP_OKAY on success
+*/
+int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy,
+                   const char* d, const char* curveName)
+{
+    int err, x;
+
+    /* if d is NULL, only import as public key using Qx,Qy */
+    if (key == NULL || qx == NULL || qy == NULL || curveName == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* set curve type and index */
+    for (x = 0; ecc_sets[x].size != 0; x++) {
+        if (XSTRNCMP(ecc_sets[x].name, curveName,
+                     XSTRLEN(curveName)) == 0) {
+            break;
+        }
+    }
+
+    if (ecc_sets[x].size == 0) {
+        WOLFSSL_MSG("ecc_set curve name not found");
+        err = ASN_PARSE_E;
+    } else {
+        return wc_ecc_import_raw_private(key, qx, qy, d, ecc_sets[x].id,
+            WC_TYPE_HEX_STR);
+    }
+
+    return err;
+}
+#endif /* HAVE_ECC_KEY_IMPORT */
+
+/* key size in octets */
+int wc_ecc_size(ecc_key* key)
+{
+    if (key == NULL)
+        return 0;
+
+    return key->dp->size;
+}
+
+/* maximum signature size based on key size */
+int wc_ecc_sig_size_calc(int sz)
+{
+    int maxSigSz = 0;
+
+    /* calculate based on key bits */
+    /* maximum possible signature header size is 7 bytes plus 2 bytes padding */
+    maxSigSz = (sz * 2) + SIG_HEADER_SZ + ECC_MAX_PAD_SZ;
+
+    /* if total length is less than 128 + SEQ(1)+LEN(1) then subtract 1 */
+    if (maxSigSz < (128 + 2)) {
+        maxSigSz -= 1;
+    }
+
+    return maxSigSz;
+}
+
+/* maximum signature size based on actual key curve */
+int wc_ecc_sig_size(ecc_key* key)
+{
+    int maxSigSz;
+    int orderBits, keySz;
+
+    if (key == NULL || key->dp == NULL)
+        return 0;
+
+    /* the signature r and s will always be less than order */
+    /* if the order MSB (top bit of byte) is set then ASN encoding needs
+        extra byte for r and s, so add 2 */
+    keySz = key->dp->size;
+    orderBits = wc_ecc_get_curve_order_bit_count(key->dp);
+    if (orderBits > keySz * 8) {
+        keySz = (orderBits + 7) / 8;
+    }
+    /* maximum possible signature header size is 7 bytes */
+    maxSigSz = (keySz * 2) + SIG_HEADER_SZ;
+    if ((orderBits % 8) == 0) {
+        /* MSB can be set, so add 2 */
+        maxSigSz += ECC_MAX_PAD_SZ;
+    }
+    /* if total length is less than 128 + SEQ(1)+LEN(1) then subtract 1 */
+    if (maxSigSz < (128 + 2)) {
+        maxSigSz -= 1;
+    }
+
+    return maxSigSz;
+}
+
+
+#ifdef FP_ECC
+
+/* fixed point ECC cache */
+/* number of entries in the cache */
+#ifndef FP_ENTRIES
+    #define FP_ENTRIES 15
+#endif
+
+/* number of bits in LUT */
+#ifndef FP_LUT
+    #define FP_LUT     8U
+#endif
+
+#ifdef ECC_SHAMIR
+    /* Sharmir requires a bigger LUT, TAO */
+    #if (FP_LUT > 12) || (FP_LUT < 4)
+        #error FP_LUT must be between 4 and 12 inclusively
+    #endif
+#else
+    #if (FP_LUT > 12) || (FP_LUT < 2)
+        #error FP_LUT must be between 2 and 12 inclusively
+    #endif
+#endif
+
+
+#ifndef WOLFSSL_SP_MATH
+
+/** Our FP cache */
+typedef struct {
+   ecc_point* g;               /* cached COPY of base point */
+   ecc_point* LUT[1U<<FP_LUT]; /* fixed point lookup */
+   mp_int     mu;              /* copy of the montgomery constant */
+   int        lru_count;       /* amount of times this entry has been used */
+   int        lock;            /* flag to indicate cache eviction */
+                               /* permitted (0) or not (1) */
+} fp_cache_t;
+
+/* if HAVE_THREAD_LS this cache is per thread, no locking needed */
+static THREAD_LS_T fp_cache_t fp_cache[FP_ENTRIES];
+
+#ifndef HAVE_THREAD_LS
+    static volatile int initMutex = 0;  /* prevent multiple mutex inits */
+    static wolfSSL_Mutex ecc_fp_lock;
+#endif /* HAVE_THREAD_LS */
+
+/* simple table to help direct the generation of the LUT */
+static const struct {
+   int ham, terma, termb;
+} lut_orders[] = {
+   { 0, 0, 0 }, { 1, 0, 0 }, { 1, 0, 0 }, { 2, 1, 2 }, { 1, 0, 0 }, { 2, 1, 4 }, { 2, 2, 4 }, { 3, 3, 4 },
+   { 1, 0, 0 }, { 2, 1, 8 }, { 2, 2, 8 }, { 3, 3, 8 }, { 2, 4, 8 }, { 3, 5, 8 }, { 3, 6, 8 }, { 4, 7, 8 },
+   { 1, 0, 0 }, { 2, 1, 16 }, { 2, 2, 16 }, { 3, 3, 16 }, { 2, 4, 16 }, { 3, 5, 16 }, { 3, 6, 16 }, { 4, 7, 16 },
+   { 2, 8, 16 }, { 3, 9, 16 }, { 3, 10, 16 }, { 4, 11, 16 }, { 3, 12, 16 }, { 4, 13, 16 }, { 4, 14, 16 }, { 5, 15, 16 },
+   { 1, 0, 0 }, { 2, 1, 32 }, { 2, 2, 32 }, { 3, 3, 32 }, { 2, 4, 32 }, { 3, 5, 32 }, { 3, 6, 32 }, { 4, 7, 32 },
+   { 2, 8, 32 }, { 3, 9, 32 }, { 3, 10, 32 }, { 4, 11, 32 }, { 3, 12, 32 }, { 4, 13, 32 }, { 4, 14, 32 }, { 5, 15, 32 },
+   { 2, 16, 32 }, { 3, 17, 32 }, { 3, 18, 32 }, { 4, 19, 32 }, { 3, 20, 32 }, { 4, 21, 32 }, { 4, 22, 32 }, { 5, 23, 32 },
+   { 3, 24, 32 }, { 4, 25, 32 }, { 4, 26, 32 }, { 5, 27, 32 }, { 4, 28, 32 }, { 5, 29, 32 }, { 5, 30, 32 }, { 6, 31, 32 },
+#if FP_LUT > 6
+   { 1, 0, 0 }, { 2, 1, 64 }, { 2, 2, 64 }, { 3, 3, 64 }, { 2, 4, 64 }, { 3, 5, 64 }, { 3, 6, 64 }, { 4, 7, 64 },
+   { 2, 8, 64 }, { 3, 9, 64 }, { 3, 10, 64 }, { 4, 11, 64 }, { 3, 12, 64 }, { 4, 13, 64 }, { 4, 14, 64 }, { 5, 15, 64 },
+   { 2, 16, 64 }, { 3, 17, 64 }, { 3, 18, 64 }, { 4, 19, 64 }, { 3, 20, 64 }, { 4, 21, 64 }, { 4, 22, 64 }, { 5, 23, 64 },
+   { 3, 24, 64 }, { 4, 25, 64 }, { 4, 26, 64 }, { 5, 27, 64 }, { 4, 28, 64 }, { 5, 29, 64 }, { 5, 30, 64 }, { 6, 31, 64 },
+   { 2, 32, 64 }, { 3, 33, 64 }, { 3, 34, 64 }, { 4, 35, 64 }, { 3, 36, 64 }, { 4, 37, 64 }, { 4, 38, 64 }, { 5, 39, 64 },
+   { 3, 40, 64 }, { 4, 41, 64 }, { 4, 42, 64 }, { 5, 43, 64 }, { 4, 44, 64 }, { 5, 45, 64 }, { 5, 46, 64 }, { 6, 47, 64 },
+   { 3, 48, 64 }, { 4, 49, 64 }, { 4, 50, 64 }, { 5, 51, 64 }, { 4, 52, 64 }, { 5, 53, 64 }, { 5, 54, 64 }, { 6, 55, 64 },
+   { 4, 56, 64 }, { 5, 57, 64 }, { 5, 58, 64 }, { 6, 59, 64 }, { 5, 60, 64 }, { 6, 61, 64 }, { 6, 62, 64 }, { 7, 63, 64 },
+#if FP_LUT > 7
+   { 1, 0, 0 }, { 2, 1, 128 }, { 2, 2, 128 }, { 3, 3, 128 }, { 2, 4, 128 }, { 3, 5, 128 }, { 3, 6, 128 }, { 4, 7, 128 },
+   { 2, 8, 128 }, { 3, 9, 128 }, { 3, 10, 128 }, { 4, 11, 128 }, { 3, 12, 128 }, { 4, 13, 128 }, { 4, 14, 128 }, { 5, 15, 128 },
+   { 2, 16, 128 }, { 3, 17, 128 }, { 3, 18, 128 }, { 4, 19, 128 }, { 3, 20, 128 }, { 4, 21, 128 }, { 4, 22, 128 }, { 5, 23, 128 },
+   { 3, 24, 128 }, { 4, 25, 128 }, { 4, 26, 128 }, { 5, 27, 128 }, { 4, 28, 128 }, { 5, 29, 128 }, { 5, 30, 128 }, { 6, 31, 128 },
+   { 2, 32, 128 }, { 3, 33, 128 }, { 3, 34, 128 }, { 4, 35, 128 }, { 3, 36, 128 }, { 4, 37, 128 }, { 4, 38, 128 }, { 5, 39, 128 },
+   { 3, 40, 128 }, { 4, 41, 128 }, { 4, 42, 128 }, { 5, 43, 128 }, { 4, 44, 128 }, { 5, 45, 128 }, { 5, 46, 128 }, { 6, 47, 128 },
+   { 3, 48, 128 }, { 4, 49, 128 }, { 4, 50, 128 }, { 5, 51, 128 }, { 4, 52, 128 }, { 5, 53, 128 }, { 5, 54, 128 }, { 6, 55, 128 },
+   { 4, 56, 128 }, { 5, 57, 128 }, { 5, 58, 128 }, { 6, 59, 128 }, { 5, 60, 128 }, { 6, 61, 128 }, { 6, 62, 128 }, { 7, 63, 128 },
+   { 2, 64, 128 }, { 3, 65, 128 }, { 3, 66, 128 }, { 4, 67, 128 }, { 3, 68, 128 }, { 4, 69, 128 }, { 4, 70, 128 }, { 5, 71, 128 },
+   { 3, 72, 128 }, { 4, 73, 128 }, { 4, 74, 128 }, { 5, 75, 128 }, { 4, 76, 128 }, { 5, 77, 128 }, { 5, 78, 128 }, { 6, 79, 128 },
+   { 3, 80, 128 }, { 4, 81, 128 }, { 4, 82, 128 }, { 5, 83, 128 }, { 4, 84, 128 }, { 5, 85, 128 }, { 5, 86, 128 }, { 6, 87, 128 },
+   { 4, 88, 128 }, { 5, 89, 128 }, { 5, 90, 128 }, { 6, 91, 128 }, { 5, 92, 128 }, { 6, 93, 128 }, { 6, 94, 128 }, { 7, 95, 128 },
+   { 3, 96, 128 }, { 4, 97, 128 }, { 4, 98, 128 }, { 5, 99, 128 }, { 4, 100, 128 }, { 5, 101, 128 }, { 5, 102, 128 }, { 6, 103, 128 },
+   { 4, 104, 128 }, { 5, 105, 128 }, { 5, 106, 128 }, { 6, 107, 128 }, { 5, 108, 128 }, { 6, 109, 128 }, { 6, 110, 128 }, { 7, 111, 128 },
+   { 4, 112, 128 }, { 5, 113, 128 }, { 5, 114, 128 }, { 6, 115, 128 }, { 5, 116, 128 }, { 6, 117, 128 }, { 6, 118, 128 }, { 7, 119, 128 },
+   { 5, 120, 128 }, { 6, 121, 128 }, { 6, 122, 128 }, { 7, 123, 128 }, { 6, 124, 128 }, { 7, 125, 128 }, { 7, 126, 128 }, { 8, 127, 128 },
+#if FP_LUT > 8
+   { 1, 0, 0 }, { 2, 1, 256 }, { 2, 2, 256 }, { 3, 3, 256 }, { 2, 4, 256 }, { 3, 5, 256 }, { 3, 6, 256 }, { 4, 7, 256 },
+   { 2, 8, 256 }, { 3, 9, 256 }, { 3, 10, 256 }, { 4, 11, 256 }, { 3, 12, 256 }, { 4, 13, 256 }, { 4, 14, 256 }, { 5, 15, 256 },
+   { 2, 16, 256 }, { 3, 17, 256 }, { 3, 18, 256 }, { 4, 19, 256 }, { 3, 20, 256 }, { 4, 21, 256 }, { 4, 22, 256 }, { 5, 23, 256 },
+   { 3, 24, 256 }, { 4, 25, 256 }, { 4, 26, 256 }, { 5, 27, 256 }, { 4, 28, 256 }, { 5, 29, 256 }, { 5, 30, 256 }, { 6, 31, 256 },
+   { 2, 32, 256 }, { 3, 33, 256 }, { 3, 34, 256 }, { 4, 35, 256 }, { 3, 36, 256 }, { 4, 37, 256 }, { 4, 38, 256 }, { 5, 39, 256 },
+   { 3, 40, 256 }, { 4, 41, 256 }, { 4, 42, 256 }, { 5, 43, 256 }, { 4, 44, 256 }, { 5, 45, 256 }, { 5, 46, 256 }, { 6, 47, 256 },
+   { 3, 48, 256 }, { 4, 49, 256 }, { 4, 50, 256 }, { 5, 51, 256 }, { 4, 52, 256 }, { 5, 53, 256 }, { 5, 54, 256 }, { 6, 55, 256 },
+   { 4, 56, 256 }, { 5, 57, 256 }, { 5, 58, 256 }, { 6, 59, 256 }, { 5, 60, 256 }, { 6, 61, 256 }, { 6, 62, 256 }, { 7, 63, 256 },
+   { 2, 64, 256 }, { 3, 65, 256 }, { 3, 66, 256 }, { 4, 67, 256 }, { 3, 68, 256 }, { 4, 69, 256 }, { 4, 70, 256 }, { 5, 71, 256 },
+   { 3, 72, 256 }, { 4, 73, 256 }, { 4, 74, 256 }, { 5, 75, 256 }, { 4, 76, 256 }, { 5, 77, 256 }, { 5, 78, 256 }, { 6, 79, 256 },
+   { 3, 80, 256 }, { 4, 81, 256 }, { 4, 82, 256 }, { 5, 83, 256 }, { 4, 84, 256 }, { 5, 85, 256 }, { 5, 86, 256 }, { 6, 87, 256 },
+   { 4, 88, 256 }, { 5, 89, 256 }, { 5, 90, 256 }, { 6, 91, 256 }, { 5, 92, 256 }, { 6, 93, 256 }, { 6, 94, 256 }, { 7, 95, 256 },
+   { 3, 96, 256 }, { 4, 97, 256 }, { 4, 98, 256 }, { 5, 99, 256 }, { 4, 100, 256 }, { 5, 101, 256 }, { 5, 102, 256 }, { 6, 103, 256 },
+   { 4, 104, 256 }, { 5, 105, 256 }, { 5, 106, 256 }, { 6, 107, 256 }, { 5, 108, 256 }, { 6, 109, 256 }, { 6, 110, 256 }, { 7, 111, 256 },
+   { 4, 112, 256 }, { 5, 113, 256 }, { 5, 114, 256 }, { 6, 115, 256 }, { 5, 116, 256 }, { 6, 117, 256 }, { 6, 118, 256 }, { 7, 119, 256 },
+   { 5, 120, 256 }, { 6, 121, 256 }, { 6, 122, 256 }, { 7, 123, 256 }, { 6, 124, 256 }, { 7, 125, 256 }, { 7, 126, 256 }, { 8, 127, 256 },
+   { 2, 128, 256 }, { 3, 129, 256 }, { 3, 130, 256 }, { 4, 131, 256 }, { 3, 132, 256 }, { 4, 133, 256 }, { 4, 134, 256 }, { 5, 135, 256 },
+   { 3, 136, 256 }, { 4, 137, 256 }, { 4, 138, 256 }, { 5, 139, 256 }, { 4, 140, 256 }, { 5, 141, 256 }, { 5, 142, 256 }, { 6, 143, 256 },
+   { 3, 144, 256 }, { 4, 145, 256 }, { 4, 146, 256 }, { 5, 147, 256 }, { 4, 148, 256 }, { 5, 149, 256 }, { 5, 150, 256 }, { 6, 151, 256 },
+   { 4, 152, 256 }, { 5, 153, 256 }, { 5, 154, 256 }, { 6, 155, 256 }, { 5, 156, 256 }, { 6, 157, 256 }, { 6, 158, 256 }, { 7, 159, 256 },
+   { 3, 160, 256 }, { 4, 161, 256 }, { 4, 162, 256 }, { 5, 163, 256 }, { 4, 164, 256 }, { 5, 165, 256 }, { 5, 166, 256 }, { 6, 167, 256 },
+   { 4, 168, 256 }, { 5, 169, 256 }, { 5, 170, 256 }, { 6, 171, 256 }, { 5, 172, 256 }, { 6, 173, 256 }, { 6, 174, 256 }, { 7, 175, 256 },
+   { 4, 176, 256 }, { 5, 177, 256 }, { 5, 178, 256 }, { 6, 179, 256 }, { 5, 180, 256 }, { 6, 181, 256 }, { 6, 182, 256 }, { 7, 183, 256 },
+   { 5, 184, 256 }, { 6, 185, 256 }, { 6, 186, 256 }, { 7, 187, 256 }, { 6, 188, 256 }, { 7, 189, 256 }, { 7, 190, 256 }, { 8, 191, 256 },
+   { 3, 192, 256 }, { 4, 193, 256 }, { 4, 194, 256 }, { 5, 195, 256 }, { 4, 196, 256 }, { 5, 197, 256 }, { 5, 198, 256 }, { 6, 199, 256 },
+   { 4, 200, 256 }, { 5, 201, 256 }, { 5, 202, 256 }, { 6, 203, 256 }, { 5, 204, 256 }, { 6, 205, 256 }, { 6, 206, 256 }, { 7, 207, 256 },
+   { 4, 208, 256 }, { 5, 209, 256 }, { 5, 210, 256 }, { 6, 211, 256 }, { 5, 212, 256 }, { 6, 213, 256 }, { 6, 214, 256 }, { 7, 215, 256 },
+   { 5, 216, 256 }, { 6, 217, 256 }, { 6, 218, 256 }, { 7, 219, 256 }, { 6, 220, 256 }, { 7, 221, 256 }, { 7, 222, 256 }, { 8, 223, 256 },
+   { 4, 224, 256 }, { 5, 225, 256 }, { 5, 226, 256 }, { 6, 227, 256 }, { 5, 228, 256 }, { 6, 229, 256 }, { 6, 230, 256 }, { 7, 231, 256 },
+   { 5, 232, 256 }, { 6, 233, 256 }, { 6, 234, 256 }, { 7, 235, 256 }, { 6, 236, 256 }, { 7, 237, 256 }, { 7, 238, 256 }, { 8, 239, 256 },
+   { 5, 240, 256 }, { 6, 241, 256 }, { 6, 242, 256 }, { 7, 243, 256 }, { 6, 244, 256 }, { 7, 245, 256 }, { 7, 246, 256 }, { 8, 247, 256 },
+   { 6, 248, 256 }, { 7, 249, 256 }, { 7, 250, 256 }, { 8, 251, 256 }, { 7, 252, 256 }, { 8, 253, 256 }, { 8, 254, 256 }, { 9, 255, 256 },
+#if FP_LUT > 9
+   { 1, 0, 0 }, { 2, 1, 512 }, { 2, 2, 512 }, { 3, 3, 512 }, { 2, 4, 512 }, { 3, 5, 512 }, { 3, 6, 512 }, { 4, 7, 512 },
+   { 2, 8, 512 }, { 3, 9, 512 }, { 3, 10, 512 }, { 4, 11, 512 }, { 3, 12, 512 }, { 4, 13, 512 }, { 4, 14, 512 }, { 5, 15, 512 },
+   { 2, 16, 512 }, { 3, 17, 512 }, { 3, 18, 512 }, { 4, 19, 512 }, { 3, 20, 512 }, { 4, 21, 512 }, { 4, 22, 512 }, { 5, 23, 512 },
+   { 3, 24, 512 }, { 4, 25, 512 }, { 4, 26, 512 }, { 5, 27, 512 }, { 4, 28, 512 }, { 5, 29, 512 }, { 5, 30, 512 }, { 6, 31, 512 },
+   { 2, 32, 512 }, { 3, 33, 512 }, { 3, 34, 512 }, { 4, 35, 512 }, { 3, 36, 512 }, { 4, 37, 512 }, { 4, 38, 512 }, { 5, 39, 512 },
+   { 3, 40, 512 }, { 4, 41, 512 }, { 4, 42, 512 }, { 5, 43, 512 }, { 4, 44, 512 }, { 5, 45, 512 }, { 5, 46, 512 }, { 6, 47, 512 },
+   { 3, 48, 512 }, { 4, 49, 512 }, { 4, 50, 512 }, { 5, 51, 512 }, { 4, 52, 512 }, { 5, 53, 512 }, { 5, 54, 512 }, { 6, 55, 512 },
+   { 4, 56, 512 }, { 5, 57, 512 }, { 5, 58, 512 }, { 6, 59, 512 }, { 5, 60, 512 }, { 6, 61, 512 }, { 6, 62, 512 }, { 7, 63, 512 },
+   { 2, 64, 512 }, { 3, 65, 512 }, { 3, 66, 512 }, { 4, 67, 512 }, { 3, 68, 512 }, { 4, 69, 512 }, { 4, 70, 512 }, { 5, 71, 512 },
+   { 3, 72, 512 }, { 4, 73, 512 }, { 4, 74, 512 }, { 5, 75, 512 }, { 4, 76, 512 }, { 5, 77, 512 }, { 5, 78, 512 }, { 6, 79, 512 },
+   { 3, 80, 512 }, { 4, 81, 512 }, { 4, 82, 512 }, { 5, 83, 512 }, { 4, 84, 512 }, { 5, 85, 512 }, { 5, 86, 512 }, { 6, 87, 512 },
+   { 4, 88, 512 }, { 5, 89, 512 }, { 5, 90, 512 }, { 6, 91, 512 }, { 5, 92, 512 }, { 6, 93, 512 }, { 6, 94, 512 }, { 7, 95, 512 },
+   { 3, 96, 512 }, { 4, 97, 512 }, { 4, 98, 512 }, { 5, 99, 512 }, { 4, 100, 512 }, { 5, 101, 512 }, { 5, 102, 512 }, { 6, 103, 512 },
+   { 4, 104, 512 }, { 5, 105, 512 }, { 5, 106, 512 }, { 6, 107, 512 }, { 5, 108, 512 }, { 6, 109, 512 }, { 6, 110, 512 }, { 7, 111, 512 },
+   { 4, 112, 512 }, { 5, 113, 512 }, { 5, 114, 512 }, { 6, 115, 512 }, { 5, 116, 512 }, { 6, 117, 512 }, { 6, 118, 512 }, { 7, 119, 512 },
+   { 5, 120, 512 }, { 6, 121, 512 }, { 6, 122, 512 }, { 7, 123, 512 }, { 6, 124, 512 }, { 7, 125, 512 }, { 7, 126, 512 }, { 8, 127, 512 },
+   { 2, 128, 512 }, { 3, 129, 512 }, { 3, 130, 512 }, { 4, 131, 512 }, { 3, 132, 512 }, { 4, 133, 512 }, { 4, 134, 512 }, { 5, 135, 512 },
+   { 3, 136, 512 }, { 4, 137, 512 }, { 4, 138, 512 }, { 5, 139, 512 }, { 4, 140, 512 }, { 5, 141, 512 }, { 5, 142, 512 }, { 6, 143, 512 },
+   { 3, 144, 512 }, { 4, 145, 512 }, { 4, 146, 512 }, { 5, 147, 512 }, { 4, 148, 512 }, { 5, 149, 512 }, { 5, 150, 512 }, { 6, 151, 512 },
+   { 4, 152, 512 }, { 5, 153, 512 }, { 5, 154, 512 }, { 6, 155, 512 }, { 5, 156, 512 }, { 6, 157, 512 }, { 6, 158, 512 }, { 7, 159, 512 },
+   { 3, 160, 512 }, { 4, 161, 512 }, { 4, 162, 512 }, { 5, 163, 512 }, { 4, 164, 512 }, { 5, 165, 512 }, { 5, 166, 512 }, { 6, 167, 512 },
+   { 4, 168, 512 }, { 5, 169, 512 }, { 5, 170, 512 }, { 6, 171, 512 }, { 5, 172, 512 }, { 6, 173, 512 }, { 6, 174, 512 }, { 7, 175, 512 },
+   { 4, 176, 512 }, { 5, 177, 512 }, { 5, 178, 512 }, { 6, 179, 512 }, { 5, 180, 512 }, { 6, 181, 512 }, { 6, 182, 512 }, { 7, 183, 512 },
+   { 5, 184, 512 }, { 6, 185, 512 }, { 6, 186, 512 }, { 7, 187, 512 }, { 6, 188, 512 }, { 7, 189, 512 }, { 7, 190, 512 }, { 8, 191, 512 },
+   { 3, 192, 512 }, { 4, 193, 512 }, { 4, 194, 512 }, { 5, 195, 512 }, { 4, 196, 512 }, { 5, 197, 512 }, { 5, 198, 512 }, { 6, 199, 512 },
+   { 4, 200, 512 }, { 5, 201, 512 }, { 5, 202, 512 }, { 6, 203, 512 }, { 5, 204, 512 }, { 6, 205, 512 }, { 6, 206, 512 }, { 7, 207, 512 },
+   { 4, 208, 512 }, { 5, 209, 512 }, { 5, 210, 512 }, { 6, 211, 512 }, { 5, 212, 512 }, { 6, 213, 512 }, { 6, 214, 512 }, { 7, 215, 512 },
+   { 5, 216, 512 }, { 6, 217, 512 }, { 6, 218, 512 }, { 7, 219, 512 }, { 6, 220, 512 }, { 7, 221, 512 }, { 7, 222, 512 }, { 8, 223, 512 },
+   { 4, 224, 512 }, { 5, 225, 512 }, { 5, 226, 512 }, { 6, 227, 512 }, { 5, 228, 512 }, { 6, 229, 512 }, { 6, 230, 512 }, { 7, 231, 512 },
+   { 5, 232, 512 }, { 6, 233, 512 }, { 6, 234, 512 }, { 7, 235, 512 }, { 6, 236, 512 }, { 7, 237, 512 }, { 7, 238, 512 }, { 8, 239, 512 },
+   { 5, 240, 512 }, { 6, 241, 512 }, { 6, 242, 512 }, { 7, 243, 512 }, { 6, 244, 512 }, { 7, 245, 512 }, { 7, 246, 512 }, { 8, 247, 512 },
+   { 6, 248, 512 }, { 7, 249, 512 }, { 7, 250, 512 }, { 8, 251, 512 }, { 7, 252, 512 }, { 8, 253, 512 }, { 8, 254, 512 }, { 9, 255, 512 },
+   { 2, 256, 512 }, { 3, 257, 512 }, { 3, 258, 512 }, { 4, 259, 512 }, { 3, 260, 512 }, { 4, 261, 512 }, { 4, 262, 512 }, { 5, 263, 512 },
+   { 3, 264, 512 }, { 4, 265, 512 }, { 4, 266, 512 }, { 5, 267, 512 }, { 4, 268, 512 }, { 5, 269, 512 }, { 5, 270, 512 }, { 6, 271, 512 },
+   { 3, 272, 512 }, { 4, 273, 512 }, { 4, 274, 512 }, { 5, 275, 512 }, { 4, 276, 512 }, { 5, 277, 512 }, { 5, 278, 512 }, { 6, 279, 512 },
+   { 4, 280, 512 }, { 5, 281, 512 }, { 5, 282, 512 }, { 6, 283, 512 }, { 5, 284, 512 }, { 6, 285, 512 }, { 6, 286, 512 }, { 7, 287, 512 },
+   { 3, 288, 512 }, { 4, 289, 512 }, { 4, 290, 512 }, { 5, 291, 512 }, { 4, 292, 512 }, { 5, 293, 512 }, { 5, 294, 512 }, { 6, 295, 512 },
+   { 4, 296, 512 }, { 5, 297, 512 }, { 5, 298, 512 }, { 6, 299, 512 }, { 5, 300, 512 }, { 6, 301, 512 }, { 6, 302, 512 }, { 7, 303, 512 },
+   { 4, 304, 512 }, { 5, 305, 512 }, { 5, 306, 512 }, { 6, 307, 512 }, { 5, 308, 512 }, { 6, 309, 512 }, { 6, 310, 512 }, { 7, 311, 512 },
+   { 5, 312, 512 }, { 6, 313, 512 }, { 6, 314, 512 }, { 7, 315, 512 }, { 6, 316, 512 }, { 7, 317, 512 }, { 7, 318, 512 }, { 8, 319, 512 },
+   { 3, 320, 512 }, { 4, 321, 512 }, { 4, 322, 512 }, { 5, 323, 512 }, { 4, 324, 512 }, { 5, 325, 512 }, { 5, 326, 512 }, { 6, 327, 512 },
+   { 4, 328, 512 }, { 5, 329, 512 }, { 5, 330, 512 }, { 6, 331, 512 }, { 5, 332, 512 }, { 6, 333, 512 }, { 6, 334, 512 }, { 7, 335, 512 },
+   { 4, 336, 512 }, { 5, 337, 512 }, { 5, 338, 512 }, { 6, 339, 512 }, { 5, 340, 512 }, { 6, 341, 512 }, { 6, 342, 512 }, { 7, 343, 512 },
+   { 5, 344, 512 }, { 6, 345, 512 }, { 6, 346, 512 }, { 7, 347, 512 }, { 6, 348, 512 }, { 7, 349, 512 }, { 7, 350, 512 }, { 8, 351, 512 },
+   { 4, 352, 512 }, { 5, 353, 512 }, { 5, 354, 512 }, { 6, 355, 512 }, { 5, 356, 512 }, { 6, 357, 512 }, { 6, 358, 512 }, { 7, 359, 512 },
+   { 5, 360, 512 }, { 6, 361, 512 }, { 6, 362, 512 }, { 7, 363, 512 }, { 6, 364, 512 }, { 7, 365, 512 }, { 7, 366, 512 }, { 8, 367, 512 },
+   { 5, 368, 512 }, { 6, 369, 512 }, { 6, 370, 512 }, { 7, 371, 512 }, { 6, 372, 512 }, { 7, 373, 512 }, { 7, 374, 512 }, { 8, 375, 512 },
+   { 6, 376, 512 }, { 7, 377, 512 }, { 7, 378, 512 }, { 8, 379, 512 }, { 7, 380, 512 }, { 8, 381, 512 }, { 8, 382, 512 }, { 9, 383, 512 },
+   { 3, 384, 512 }, { 4, 385, 512 }, { 4, 386, 512 }, { 5, 387, 512 }, { 4, 388, 512 }, { 5, 389, 512 }, { 5, 390, 512 }, { 6, 391, 512 },
+   { 4, 392, 512 }, { 5, 393, 512 }, { 5, 394, 512 }, { 6, 395, 512 }, { 5, 396, 512 }, { 6, 397, 512 }, { 6, 398, 512 }, { 7, 399, 512 },
+   { 4, 400, 512 }, { 5, 401, 512 }, { 5, 402, 512 }, { 6, 403, 512 }, { 5, 404, 512 }, { 6, 405, 512 }, { 6, 406, 512 }, { 7, 407, 512 },
+   { 5, 408, 512 }, { 6, 409, 512 }, { 6, 410, 512 }, { 7, 411, 512 }, { 6, 412, 512 }, { 7, 413, 512 }, { 7, 414, 512 }, { 8, 415, 512 },
+   { 4, 416, 512 }, { 5, 417, 512 }, { 5, 418, 512 }, { 6, 419, 512 }, { 5, 420, 512 }, { 6, 421, 512 }, { 6, 422, 512 }, { 7, 423, 512 },
+   { 5, 424, 512 }, { 6, 425, 512 }, { 6, 426, 512 }, { 7, 427, 512 }, { 6, 428, 512 }, { 7, 429, 512 }, { 7, 430, 512 }, { 8, 431, 512 },
+   { 5, 432, 512 }, { 6, 433, 512 }, { 6, 434, 512 }, { 7, 435, 512 }, { 6, 436, 512 }, { 7, 437, 512 }, { 7, 438, 512 }, { 8, 439, 512 },
+   { 6, 440, 512 }, { 7, 441, 512 }, { 7, 442, 512 }, { 8, 443, 512 }, { 7, 444, 512 }, { 8, 445, 512 }, { 8, 446, 512 }, { 9, 447, 512 },
+   { 4, 448, 512 }, { 5, 449, 512 }, { 5, 450, 512 }, { 6, 451, 512 }, { 5, 452, 512 }, { 6, 453, 512 }, { 6, 454, 512 }, { 7, 455, 512 },
+   { 5, 456, 512 }, { 6, 457, 512 }, { 6, 458, 512 }, { 7, 459, 512 }, { 6, 460, 512 }, { 7, 461, 512 }, { 7, 462, 512 }, { 8, 463, 512 },
+   { 5, 464, 512 }, { 6, 465, 512 }, { 6, 466, 512 }, { 7, 467, 512 }, { 6, 468, 512 }, { 7, 469, 512 }, { 7, 470, 512 }, { 8, 471, 512 },
+   { 6, 472, 512 }, { 7, 473, 512 }, { 7, 474, 512 }, { 8, 475, 512 }, { 7, 476, 512 }, { 8, 477, 512 }, { 8, 478, 512 }, { 9, 479, 512 },
+   { 5, 480, 512 }, { 6, 481, 512 }, { 6, 482, 512 }, { 7, 483, 512 }, { 6, 484, 512 }, { 7, 485, 512 }, { 7, 486, 512 }, { 8, 487, 512 },
+   { 6, 488, 512 }, { 7, 489, 512 }, { 7, 490, 512 }, { 8, 491, 512 }, { 7, 492, 512 }, { 8, 493, 512 }, { 8, 494, 512 }, { 9, 495, 512 },
+   { 6, 496, 512 }, { 7, 497, 512 }, { 7, 498, 512 }, { 8, 499, 512 }, { 7, 500, 512 }, { 8, 501, 512 }, { 8, 502, 512 }, { 9, 503, 512 },
+   { 7, 504, 512 }, { 8, 505, 512 }, { 8, 506, 512 }, { 9, 507, 512 }, { 8, 508, 512 }, { 9, 509, 512 }, { 9, 510, 512 }, { 10, 511, 512 },
+#if FP_LUT > 10
+   { 1, 0, 0 }, { 2, 1, 1024 }, { 2, 2, 1024 }, { 3, 3, 1024 }, { 2, 4, 1024 }, { 3, 5, 1024 }, { 3, 6, 1024 }, { 4, 7, 1024 },
+   { 2, 8, 1024 }, { 3, 9, 1024 }, { 3, 10, 1024 }, { 4, 11, 1024 }, { 3, 12, 1024 }, { 4, 13, 1024 }, { 4, 14, 1024 }, { 5, 15, 1024 },
+   { 2, 16, 1024 }, { 3, 17, 1024 }, { 3, 18, 1024 }, { 4, 19, 1024 }, { 3, 20, 1024 }, { 4, 21, 1024 }, { 4, 22, 1024 }, { 5, 23, 1024 },
+   { 3, 24, 1024 }, { 4, 25, 1024 }, { 4, 26, 1024 }, { 5, 27, 1024 }, { 4, 28, 1024 }, { 5, 29, 1024 }, { 5, 30, 1024 }, { 6, 31, 1024 },
+   { 2, 32, 1024 }, { 3, 33, 1024 }, { 3, 34, 1024 }, { 4, 35, 1024 }, { 3, 36, 1024 }, { 4, 37, 1024 }, { 4, 38, 1024 }, { 5, 39, 1024 },
+   { 3, 40, 1024 }, { 4, 41, 1024 }, { 4, 42, 1024 }, { 5, 43, 1024 }, { 4, 44, 1024 }, { 5, 45, 1024 }, { 5, 46, 1024 }, { 6, 47, 1024 },
+   { 3, 48, 1024 }, { 4, 49, 1024 }, { 4, 50, 1024 }, { 5, 51, 1024 }, { 4, 52, 1024 }, { 5, 53, 1024 }, { 5, 54, 1024 }, { 6, 55, 1024 },
+   { 4, 56, 1024 }, { 5, 57, 1024 }, { 5, 58, 1024 }, { 6, 59, 1024 }, { 5, 60, 1024 }, { 6, 61, 1024 }, { 6, 62, 1024 }, { 7, 63, 1024 },
+   { 2, 64, 1024 }, { 3, 65, 1024 }, { 3, 66, 1024 }, { 4, 67, 1024 }, { 3, 68, 1024 }, { 4, 69, 1024 }, { 4, 70, 1024 }, { 5, 71, 1024 },
+   { 3, 72, 1024 }, { 4, 73, 1024 }, { 4, 74, 1024 }, { 5, 75, 1024 }, { 4, 76, 1024 }, { 5, 77, 1024 }, { 5, 78, 1024 }, { 6, 79, 1024 },
+   { 3, 80, 1024 }, { 4, 81, 1024 }, { 4, 82, 1024 }, { 5, 83, 1024 }, { 4, 84, 1024 }, { 5, 85, 1024 }, { 5, 86, 1024 }, { 6, 87, 1024 },
+   { 4, 88, 1024 }, { 5, 89, 1024 }, { 5, 90, 1024 }, { 6, 91, 1024 }, { 5, 92, 1024 }, { 6, 93, 1024 }, { 6, 94, 1024 }, { 7, 95, 1024 },
+   { 3, 96, 1024 }, { 4, 97, 1024 }, { 4, 98, 1024 }, { 5, 99, 1024 }, { 4, 100, 1024 }, { 5, 101, 1024 }, { 5, 102, 1024 }, { 6, 103, 1024 },
+   { 4, 104, 1024 }, { 5, 105, 1024 }, { 5, 106, 1024 }, { 6, 107, 1024 }, { 5, 108, 1024 }, { 6, 109, 1024 }, { 6, 110, 1024 }, { 7, 111, 1024 },
+   { 4, 112, 1024 }, { 5, 113, 1024 }, { 5, 114, 1024 }, { 6, 115, 1024 }, { 5, 116, 1024 }, { 6, 117, 1024 }, { 6, 118, 1024 }, { 7, 119, 1024 },
+   { 5, 120, 1024 }, { 6, 121, 1024 }, { 6, 122, 1024 }, { 7, 123, 1024 }, { 6, 124, 1024 }, { 7, 125, 1024 }, { 7, 126, 1024 }, { 8, 127, 1024 },
+   { 2, 128, 1024 }, { 3, 129, 1024 }, { 3, 130, 1024 }, { 4, 131, 1024 }, { 3, 132, 1024 }, { 4, 133, 1024 }, { 4, 134, 1024 }, { 5, 135, 1024 },
+   { 3, 136, 1024 }, { 4, 137, 1024 }, { 4, 138, 1024 }, { 5, 139, 1024 }, { 4, 140, 1024 }, { 5, 141, 1024 }, { 5, 142, 1024 }, { 6, 143, 1024 },
+   { 3, 144, 1024 }, { 4, 145, 1024 }, { 4, 146, 1024 }, { 5, 147, 1024 }, { 4, 148, 1024 }, { 5, 149, 1024 }, { 5, 150, 1024 }, { 6, 151, 1024 },
+   { 4, 152, 1024 }, { 5, 153, 1024 }, { 5, 154, 1024 }, { 6, 155, 1024 }, { 5, 156, 1024 }, { 6, 157, 1024 }, { 6, 158, 1024 }, { 7, 159, 1024 },
+   { 3, 160, 1024 }, { 4, 161, 1024 }, { 4, 162, 1024 }, { 5, 163, 1024 }, { 4, 164, 1024 }, { 5, 165, 1024 }, { 5, 166, 1024 }, { 6, 167, 1024 },
+   { 4, 168, 1024 }, { 5, 169, 1024 }, { 5, 170, 1024 }, { 6, 171, 1024 }, { 5, 172, 1024 }, { 6, 173, 1024 }, { 6, 174, 1024 }, { 7, 175, 1024 },
+   { 4, 176, 1024 }, { 5, 177, 1024 }, { 5, 178, 1024 }, { 6, 179, 1024 }, { 5, 180, 1024 }, { 6, 181, 1024 }, { 6, 182, 1024 }, { 7, 183, 1024 },
+   { 5, 184, 1024 }, { 6, 185, 1024 }, { 6, 186, 1024 }, { 7, 187, 1024 }, { 6, 188, 1024 }, { 7, 189, 1024 }, { 7, 190, 1024 }, { 8, 191, 1024 },
+   { 3, 192, 1024 }, { 4, 193, 1024 }, { 4, 194, 1024 }, { 5, 195, 1024 }, { 4, 196, 1024 }, { 5, 197, 1024 }, { 5, 198, 1024 }, { 6, 199, 1024 },
+   { 4, 200, 1024 }, { 5, 201, 1024 }, { 5, 202, 1024 }, { 6, 203, 1024 }, { 5, 204, 1024 }, { 6, 205, 1024 }, { 6, 206, 1024 }, { 7, 207, 1024 },
+   { 4, 208, 1024 }, { 5, 209, 1024 }, { 5, 210, 1024 }, { 6, 211, 1024 }, { 5, 212, 1024 }, { 6, 213, 1024 }, { 6, 214, 1024 }, { 7, 215, 1024 },
+   { 5, 216, 1024 }, { 6, 217, 1024 }, { 6, 218, 1024 }, { 7, 219, 1024 }, { 6, 220, 1024 }, { 7, 221, 1024 }, { 7, 222, 1024 }, { 8, 223, 1024 },
+   { 4, 224, 1024 }, { 5, 225, 1024 }, { 5, 226, 1024 }, { 6, 227, 1024 }, { 5, 228, 1024 }, { 6, 229, 1024 }, { 6, 230, 1024 }, { 7, 231, 1024 },
+   { 5, 232, 1024 }, { 6, 233, 1024 }, { 6, 234, 1024 }, { 7, 235, 1024 }, { 6, 236, 1024 }, { 7, 237, 1024 }, { 7, 238, 1024 }, { 8, 239, 1024 },
+   { 5, 240, 1024 }, { 6, 241, 1024 }, { 6, 242, 1024 }, { 7, 243, 1024 }, { 6, 244, 1024 }, { 7, 245, 1024 }, { 7, 246, 1024 }, { 8, 247, 1024 },
+   { 6, 248, 1024 }, { 7, 249, 1024 }, { 7, 250, 1024 }, { 8, 251, 1024 }, { 7, 252, 1024 }, { 8, 253, 1024 }, { 8, 254, 1024 }, { 9, 255, 1024 },
+   { 2, 256, 1024 }, { 3, 257, 1024 }, { 3, 258, 1024 }, { 4, 259, 1024 }, { 3, 260, 1024 }, { 4, 261, 1024 }, { 4, 262, 1024 }, { 5, 263, 1024 },
+   { 3, 264, 1024 }, { 4, 265, 1024 }, { 4, 266, 1024 }, { 5, 267, 1024 }, { 4, 268, 1024 }, { 5, 269, 1024 }, { 5, 270, 1024 }, { 6, 271, 1024 },
+   { 3, 272, 1024 }, { 4, 273, 1024 }, { 4, 274, 1024 }, { 5, 275, 1024 }, { 4, 276, 1024 }, { 5, 277, 1024 }, { 5, 278, 1024 }, { 6, 279, 1024 },
+   { 4, 280, 1024 }, { 5, 281, 1024 }, { 5, 282, 1024 }, { 6, 283, 1024 }, { 5, 284, 1024 }, { 6, 285, 1024 }, { 6, 286, 1024 }, { 7, 287, 1024 },
+   { 3, 288, 1024 }, { 4, 289, 1024 }, { 4, 290, 1024 }, { 5, 291, 1024 }, { 4, 292, 1024 }, { 5, 293, 1024 }, { 5, 294, 1024 }, { 6, 295, 1024 },
+   { 4, 296, 1024 }, { 5, 297, 1024 }, { 5, 298, 1024 }, { 6, 299, 1024 }, { 5, 300, 1024 }, { 6, 301, 1024 }, { 6, 302, 1024 }, { 7, 303, 1024 },
+   { 4, 304, 1024 }, { 5, 305, 1024 }, { 5, 306, 1024 }, { 6, 307, 1024 }, { 5, 308, 1024 }, { 6, 309, 1024 }, { 6, 310, 1024 }, { 7, 311, 1024 },
+   { 5, 312, 1024 }, { 6, 313, 1024 }, { 6, 314, 1024 }, { 7, 315, 1024 }, { 6, 316, 1024 }, { 7, 317, 1024 }, { 7, 318, 1024 }, { 8, 319, 1024 },
+   { 3, 320, 1024 }, { 4, 321, 1024 }, { 4, 322, 1024 }, { 5, 323, 1024 }, { 4, 324, 1024 }, { 5, 325, 1024 }, { 5, 326, 1024 }, { 6, 327, 1024 },
+   { 4, 328, 1024 }, { 5, 329, 1024 }, { 5, 330, 1024 }, { 6, 331, 1024 }, { 5, 332, 1024 }, { 6, 333, 1024 }, { 6, 334, 1024 }, { 7, 335, 1024 },
+   { 4, 336, 1024 }, { 5, 337, 1024 }, { 5, 338, 1024 }, { 6, 339, 1024 }, { 5, 340, 1024 }, { 6, 341, 1024 }, { 6, 342, 1024 }, { 7, 343, 1024 },
+   { 5, 344, 1024 }, { 6, 345, 1024 }, { 6, 346, 1024 }, { 7, 347, 1024 }, { 6, 348, 1024 }, { 7, 349, 1024 }, { 7, 350, 1024 }, { 8, 351, 1024 },
+   { 4, 352, 1024 }, { 5, 353, 1024 }, { 5, 354, 1024 }, { 6, 355, 1024 }, { 5, 356, 1024 }, { 6, 357, 1024 }, { 6, 358, 1024 }, { 7, 359, 1024 },
+   { 5, 360, 1024 }, { 6, 361, 1024 }, { 6, 362, 1024 }, { 7, 363, 1024 }, { 6, 364, 1024 }, { 7, 365, 1024 }, { 7, 366, 1024 }, { 8, 367, 1024 },
+   { 5, 368, 1024 }, { 6, 369, 1024 }, { 6, 370, 1024 }, { 7, 371, 1024 }, { 6, 372, 1024 }, { 7, 373, 1024 }, { 7, 374, 1024 }, { 8, 375, 1024 },
+   { 6, 376, 1024 }, { 7, 377, 1024 }, { 7, 378, 1024 }, { 8, 379, 1024 }, { 7, 380, 1024 }, { 8, 381, 1024 }, { 8, 382, 1024 }, { 9, 383, 1024 },
+   { 3, 384, 1024 }, { 4, 385, 1024 }, { 4, 386, 1024 }, { 5, 387, 1024 }, { 4, 388, 1024 }, { 5, 389, 1024 }, { 5, 390, 1024 }, { 6, 391, 1024 },
+   { 4, 392, 1024 }, { 5, 393, 1024 }, { 5, 394, 1024 }, { 6, 395, 1024 }, { 5, 396, 1024 }, { 6, 397, 1024 }, { 6, 398, 1024 }, { 7, 399, 1024 },
+   { 4, 400, 1024 }, { 5, 401, 1024 }, { 5, 402, 1024 }, { 6, 403, 1024 }, { 5, 404, 1024 }, { 6, 405, 1024 }, { 6, 406, 1024 }, { 7, 407, 1024 },
+   { 5, 408, 1024 }, { 6, 409, 1024 }, { 6, 410, 1024 }, { 7, 411, 1024 }, { 6, 412, 1024 }, { 7, 413, 1024 }, { 7, 414, 1024 }, { 8, 415, 1024 },
+   { 4, 416, 1024 }, { 5, 417, 1024 }, { 5, 418, 1024 }, { 6, 419, 1024 }, { 5, 420, 1024 }, { 6, 421, 1024 }, { 6, 422, 1024 }, { 7, 423, 1024 },
+   { 5, 424, 1024 }, { 6, 425, 1024 }, { 6, 426, 1024 }, { 7, 427, 1024 }, { 6, 428, 1024 }, { 7, 429, 1024 }, { 7, 430, 1024 }, { 8, 431, 1024 },
+   { 5, 432, 1024 }, { 6, 433, 1024 }, { 6, 434, 1024 }, { 7, 435, 1024 }, { 6, 436, 1024 }, { 7, 437, 1024 }, { 7, 438, 1024 }, { 8, 439, 1024 },
+   { 6, 440, 1024 }, { 7, 441, 1024 }, { 7, 442, 1024 }, { 8, 443, 1024 }, { 7, 444, 1024 }, { 8, 445, 1024 }, { 8, 446, 1024 }, { 9, 447, 1024 },
+   { 4, 448, 1024 }, { 5, 449, 1024 }, { 5, 450, 1024 }, { 6, 451, 1024 }, { 5, 452, 1024 }, { 6, 453, 1024 }, { 6, 454, 1024 }, { 7, 455, 1024 },
+   { 5, 456, 1024 }, { 6, 457, 1024 }, { 6, 458, 1024 }, { 7, 459, 1024 }, { 6, 460, 1024 }, { 7, 461, 1024 }, { 7, 462, 1024 }, { 8, 463, 1024 },
+   { 5, 464, 1024 }, { 6, 465, 1024 }, { 6, 466, 1024 }, { 7, 467, 1024 }, { 6, 468, 1024 }, { 7, 469, 1024 }, { 7, 470, 1024 }, { 8, 471, 1024 },
+   { 6, 472, 1024 }, { 7, 473, 1024 }, { 7, 474, 1024 }, { 8, 475, 1024 }, { 7, 476, 1024 }, { 8, 477, 1024 }, { 8, 478, 1024 }, { 9, 479, 1024 },
+   { 5, 480, 1024 }, { 6, 481, 1024 }, { 6, 482, 1024 }, { 7, 483, 1024 }, { 6, 484, 1024 }, { 7, 485, 1024 }, { 7, 486, 1024 }, { 8, 487, 1024 },
+   { 6, 488, 1024 }, { 7, 489, 1024 }, { 7, 490, 1024 }, { 8, 491, 1024 }, { 7, 492, 1024 }, { 8, 493, 1024 }, { 8, 494, 1024 }, { 9, 495, 1024 },
+   { 6, 496, 1024 }, { 7, 497, 1024 }, { 7, 498, 1024 }, { 8, 499, 1024 }, { 7, 500, 1024 }, { 8, 501, 1024 }, { 8, 502, 1024 }, { 9, 503, 1024 },
+   { 7, 504, 1024 }, { 8, 505, 1024 }, { 8, 506, 1024 }, { 9, 507, 1024 }, { 8, 508, 1024 }, { 9, 509, 1024 }, { 9, 510, 1024 }, { 10, 511, 1024 },
+   { 2, 512, 1024 }, { 3, 513, 1024 }, { 3, 514, 1024 }, { 4, 515, 1024 }, { 3, 516, 1024 }, { 4, 517, 1024 }, { 4, 518, 1024 }, { 5, 519, 1024 },
+   { 3, 520, 1024 }, { 4, 521, 1024 }, { 4, 522, 1024 }, { 5, 523, 1024 }, { 4, 524, 1024 }, { 5, 525, 1024 }, { 5, 526, 1024 }, { 6, 527, 1024 },
+   { 3, 528, 1024 }, { 4, 529, 1024 }, { 4, 530, 1024 }, { 5, 531, 1024 }, { 4, 532, 1024 }, { 5, 533, 1024 }, { 5, 534, 1024 }, { 6, 535, 1024 },
+   { 4, 536, 1024 }, { 5, 537, 1024 }, { 5, 538, 1024 }, { 6, 539, 1024 }, { 5, 540, 1024 }, { 6, 541, 1024 }, { 6, 542, 1024 }, { 7, 543, 1024 },
+   { 3, 544, 1024 }, { 4, 545, 1024 }, { 4, 546, 1024 }, { 5, 547, 1024 }, { 4, 548, 1024 }, { 5, 549, 1024 }, { 5, 550, 1024 }, { 6, 551, 1024 },
+   { 4, 552, 1024 }, { 5, 553, 1024 }, { 5, 554, 1024 }, { 6, 555, 1024 }, { 5, 556, 1024 }, { 6, 557, 1024 }, { 6, 558, 1024 }, { 7, 559, 1024 },
+   { 4, 560, 1024 }, { 5, 561, 1024 }, { 5, 562, 1024 }, { 6, 563, 1024 }, { 5, 564, 1024 }, { 6, 565, 1024 }, { 6, 566, 1024 }, { 7, 567, 1024 },
+   { 5, 568, 1024 }, { 6, 569, 1024 }, { 6, 570, 1024 }, { 7, 571, 1024 }, { 6, 572, 1024 }, { 7, 573, 1024 }, { 7, 574, 1024 }, { 8, 575, 1024 },
+   { 3, 576, 1024 }, { 4, 577, 1024 }, { 4, 578, 1024 }, { 5, 579, 1024 }, { 4, 580, 1024 }, { 5, 581, 1024 }, { 5, 582, 1024 }, { 6, 583, 1024 },
+   { 4, 584, 1024 }, { 5, 585, 1024 }, { 5, 586, 1024 }, { 6, 587, 1024 }, { 5, 588, 1024 }, { 6, 589, 1024 }, { 6, 590, 1024 }, { 7, 591, 1024 },
+   { 4, 592, 1024 }, { 5, 593, 1024 }, { 5, 594, 1024 }, { 6, 595, 1024 }, { 5, 596, 1024 }, { 6, 597, 1024 }, { 6, 598, 1024 }, { 7, 599, 1024 },
+   { 5, 600, 1024 }, { 6, 601, 1024 }, { 6, 602, 1024 }, { 7, 603, 1024 }, { 6, 604, 1024 }, { 7, 605, 1024 }, { 7, 606, 1024 }, { 8, 607, 1024 },
+   { 4, 608, 1024 }, { 5, 609, 1024 }, { 5, 610, 1024 }, { 6, 611, 1024 }, { 5, 612, 1024 }, { 6, 613, 1024 }, { 6, 614, 1024 }, { 7, 615, 1024 },
+   { 5, 616, 1024 }, { 6, 617, 1024 }, { 6, 618, 1024 }, { 7, 619, 1024 }, { 6, 620, 1024 }, { 7, 621, 1024 }, { 7, 622, 1024 }, { 8, 623, 1024 },
+   { 5, 624, 1024 }, { 6, 625, 1024 }, { 6, 626, 1024 }, { 7, 627, 1024 }, { 6, 628, 1024 }, { 7, 629, 1024 }, { 7, 630, 1024 }, { 8, 631, 1024 },
+   { 6, 632, 1024 }, { 7, 633, 1024 }, { 7, 634, 1024 }, { 8, 635, 1024 }, { 7, 636, 1024 }, { 8, 637, 1024 }, { 8, 638, 1024 }, { 9, 639, 1024 },
+   { 3, 640, 1024 }, { 4, 641, 1024 }, { 4, 642, 1024 }, { 5, 643, 1024 }, { 4, 644, 1024 }, { 5, 645, 1024 }, { 5, 646, 1024 }, { 6, 647, 1024 },
+   { 4, 648, 1024 }, { 5, 649, 1024 }, { 5, 650, 1024 }, { 6, 651, 1024 }, { 5, 652, 1024 }, { 6, 653, 1024 }, { 6, 654, 1024 }, { 7, 655, 1024 },
+   { 4, 656, 1024 }, { 5, 657, 1024 }, { 5, 658, 1024 }, { 6, 659, 1024 }, { 5, 660, 1024 }, { 6, 661, 1024 }, { 6, 662, 1024 }, { 7, 663, 1024 },
+   { 5, 664, 1024 }, { 6, 665, 1024 }, { 6, 666, 1024 }, { 7, 667, 1024 }, { 6, 668, 1024 }, { 7, 669, 1024 }, { 7, 670, 1024 }, { 8, 671, 1024 },
+   { 4, 672, 1024 }, { 5, 673, 1024 }, { 5, 674, 1024 }, { 6, 675, 1024 }, { 5, 676, 1024 }, { 6, 677, 1024 }, { 6, 678, 1024 }, { 7, 679, 1024 },
+   { 5, 680, 1024 }, { 6, 681, 1024 }, { 6, 682, 1024 }, { 7, 683, 1024 }, { 6, 684, 1024 }, { 7, 685, 1024 }, { 7, 686, 1024 }, { 8, 687, 1024 },
+   { 5, 688, 1024 }, { 6, 689, 1024 }, { 6, 690, 1024 }, { 7, 691, 1024 }, { 6, 692, 1024 }, { 7, 693, 1024 }, { 7, 694, 1024 }, { 8, 695, 1024 },
+   { 6, 696, 1024 }, { 7, 697, 1024 }, { 7, 698, 1024 }, { 8, 699, 1024 }, { 7, 700, 1024 }, { 8, 701, 1024 }, { 8, 702, 1024 }, { 9, 703, 1024 },
+   { 4, 704, 1024 }, { 5, 705, 1024 }, { 5, 706, 1024 }, { 6, 707, 1024 }, { 5, 708, 1024 }, { 6, 709, 1024 }, { 6, 710, 1024 }, { 7, 711, 1024 },
+   { 5, 712, 1024 }, { 6, 713, 1024 }, { 6, 714, 1024 }, { 7, 715, 1024 }, { 6, 716, 1024 }, { 7, 717, 1024 }, { 7, 718, 1024 }, { 8, 719, 1024 },
+   { 5, 720, 1024 }, { 6, 721, 1024 }, { 6, 722, 1024 }, { 7, 723, 1024 }, { 6, 724, 1024 }, { 7, 725, 1024 }, { 7, 726, 1024 }, { 8, 727, 1024 },
+   { 6, 728, 1024 }, { 7, 729, 1024 }, { 7, 730, 1024 }, { 8, 731, 1024 }, { 7, 732, 1024 }, { 8, 733, 1024 }, { 8, 734, 1024 }, { 9, 735, 1024 },
+   { 5, 736, 1024 }, { 6, 737, 1024 }, { 6, 738, 1024 }, { 7, 739, 1024 }, { 6, 740, 1024 }, { 7, 741, 1024 }, { 7, 742, 1024 }, { 8, 743, 1024 },
+   { 6, 744, 1024 }, { 7, 745, 1024 }, { 7, 746, 1024 }, { 8, 747, 1024 }, { 7, 748, 1024 }, { 8, 749, 1024 }, { 8, 750, 1024 }, { 9, 751, 1024 },
+   { 6, 752, 1024 }, { 7, 753, 1024 }, { 7, 754, 1024 }, { 8, 755, 1024 }, { 7, 756, 1024 }, { 8, 757, 1024 }, { 8, 758, 1024 }, { 9, 759, 1024 },
+   { 7, 760, 1024 }, { 8, 761, 1024 }, { 8, 762, 1024 }, { 9, 763, 1024 }, { 8, 764, 1024 }, { 9, 765, 1024 }, { 9, 766, 1024 }, { 10, 767, 1024 },
+   { 3, 768, 1024 }, { 4, 769, 1024 }, { 4, 770, 1024 }, { 5, 771, 1024 }, { 4, 772, 1024 }, { 5, 773, 1024 }, { 5, 774, 1024 }, { 6, 775, 1024 },
+   { 4, 776, 1024 }, { 5, 777, 1024 }, { 5, 778, 1024 }, { 6, 779, 1024 }, { 5, 780, 1024 }, { 6, 781, 1024 }, { 6, 782, 1024 }, { 7, 783, 1024 },
+   { 4, 784, 1024 }, { 5, 785, 1024 }, { 5, 786, 1024 }, { 6, 787, 1024 }, { 5, 788, 1024 }, { 6, 789, 1024 }, { 6, 790, 1024 }, { 7, 791, 1024 },
+   { 5, 792, 1024 }, { 6, 793, 1024 }, { 6, 794, 1024 }, { 7, 795, 1024 }, { 6, 796, 1024 }, { 7, 797, 1024 }, { 7, 798, 1024 }, { 8, 799, 1024 },
+   { 4, 800, 1024 }, { 5, 801, 1024 }, { 5, 802, 1024 }, { 6, 803, 1024 }, { 5, 804, 1024 }, { 6, 805, 1024 }, { 6, 806, 1024 }, { 7, 807, 1024 },
+   { 5, 808, 1024 }, { 6, 809, 1024 }, { 6, 810, 1024 }, { 7, 811, 1024 }, { 6, 812, 1024 }, { 7, 813, 1024 }, { 7, 814, 1024 }, { 8, 815, 1024 },
+   { 5, 816, 1024 }, { 6, 817, 1024 }, { 6, 818, 1024 }, { 7, 819, 1024 }, { 6, 820, 1024 }, { 7, 821, 1024 }, { 7, 822, 1024 }, { 8, 823, 1024 },
+   { 6, 824, 1024 }, { 7, 825, 1024 }, { 7, 826, 1024 }, { 8, 827, 1024 }, { 7, 828, 1024 }, { 8, 829, 1024 }, { 8, 830, 1024 }, { 9, 831, 1024 },
+   { 4, 832, 1024 }, { 5, 833, 1024 }, { 5, 834, 1024 }, { 6, 835, 1024 }, { 5, 836, 1024 }, { 6, 837, 1024 }, { 6, 838, 1024 }, { 7, 839, 1024 },
+   { 5, 840, 1024 }, { 6, 841, 1024 }, { 6, 842, 1024 }, { 7, 843, 1024 }, { 6, 844, 1024 }, { 7, 845, 1024 }, { 7, 846, 1024 }, { 8, 847, 1024 },
+   { 5, 848, 1024 }, { 6, 849, 1024 }, { 6, 850, 1024 }, { 7, 851, 1024 }, { 6, 852, 1024 }, { 7, 853, 1024 }, { 7, 854, 1024 }, { 8, 855, 1024 },
+   { 6, 856, 1024 }, { 7, 857, 1024 }, { 7, 858, 1024 }, { 8, 859, 1024 }, { 7, 860, 1024 }, { 8, 861, 1024 }, { 8, 862, 1024 }, { 9, 863, 1024 },
+   { 5, 864, 1024 }, { 6, 865, 1024 }, { 6, 866, 1024 }, { 7, 867, 1024 }, { 6, 868, 1024 }, { 7, 869, 1024 }, { 7, 870, 1024 }, { 8, 871, 1024 },
+   { 6, 872, 1024 }, { 7, 873, 1024 }, { 7, 874, 1024 }, { 8, 875, 1024 }, { 7, 876, 1024 }, { 8, 877, 1024 }, { 8, 878, 1024 }, { 9, 879, 1024 },
+   { 6, 880, 1024 }, { 7, 881, 1024 }, { 7, 882, 1024 }, { 8, 883, 1024 }, { 7, 884, 1024 }, { 8, 885, 1024 }, { 8, 886, 1024 }, { 9, 887, 1024 },
+   { 7, 888, 1024 }, { 8, 889, 1024 }, { 8, 890, 1024 }, { 9, 891, 1024 }, { 8, 892, 1024 }, { 9, 893, 1024 }, { 9, 894, 1024 }, { 10, 895, 1024 },
+   { 4, 896, 1024 }, { 5, 897, 1024 }, { 5, 898, 1024 }, { 6, 899, 1024 }, { 5, 900, 1024 }, { 6, 901, 1024 }, { 6, 902, 1024 }, { 7, 903, 1024 },
+   { 5, 904, 1024 }, { 6, 905, 1024 }, { 6, 906, 1024 }, { 7, 907, 1024 }, { 6, 908, 1024 }, { 7, 909, 1024 }, { 7, 910, 1024 }, { 8, 911, 1024 },
+   { 5, 912, 1024 }, { 6, 913, 1024 }, { 6, 914, 1024 }, { 7, 915, 1024 }, { 6, 916, 1024 }, { 7, 917, 1024 }, { 7, 918, 1024 }, { 8, 919, 1024 },
+   { 6, 920, 1024 }, { 7, 921, 1024 }, { 7, 922, 1024 }, { 8, 923, 1024 }, { 7, 924, 1024 }, { 8, 925, 1024 }, { 8, 926, 1024 }, { 9, 927, 1024 },
+   { 5, 928, 1024 }, { 6, 929, 1024 }, { 6, 930, 1024 }, { 7, 931, 1024 }, { 6, 932, 1024 }, { 7, 933, 1024 }, { 7, 934, 1024 }, { 8, 935, 1024 },
+   { 6, 936, 1024 }, { 7, 937, 1024 }, { 7, 938, 1024 }, { 8, 939, 1024 }, { 7, 940, 1024 }, { 8, 941, 1024 }, { 8, 942, 1024 }, { 9, 943, 1024 },
+   { 6, 944, 1024 }, { 7, 945, 1024 }, { 7, 946, 1024 }, { 8, 947, 1024 }, { 7, 948, 1024 }, { 8, 949, 1024 }, { 8, 950, 1024 }, { 9, 951, 1024 },
+   { 7, 952, 1024 }, { 8, 953, 1024 }, { 8, 954, 1024 }, { 9, 955, 1024 }, { 8, 956, 1024 }, { 9, 957, 1024 }, { 9, 958, 1024 }, { 10, 959, 1024 },
+   { 5, 960, 1024 }, { 6, 961, 1024 }, { 6, 962, 1024 }, { 7, 963, 1024 }, { 6, 964, 1024 }, { 7, 965, 1024 }, { 7, 966, 1024 }, { 8, 967, 1024 },
+   { 6, 968, 1024 }, { 7, 969, 1024 }, { 7, 970, 1024 }, { 8, 971, 1024 }, { 7, 972, 1024 }, { 8, 973, 1024 }, { 8, 974, 1024 }, { 9, 975, 1024 },
+   { 6, 976, 1024 }, { 7, 977, 1024 }, { 7, 978, 1024 }, { 8, 979, 1024 }, { 7, 980, 1024 }, { 8, 981, 1024 }, { 8, 982, 1024 }, { 9, 983, 1024 },
+   { 7, 984, 1024 }, { 8, 985, 1024 }, { 8, 986, 1024 }, { 9, 987, 1024 }, { 8, 988, 1024 }, { 9, 989, 1024 }, { 9, 990, 1024 }, { 10, 991, 1024 },
+   { 6, 992, 1024 }, { 7, 993, 1024 }, { 7, 994, 1024 }, { 8, 995, 1024 }, { 7, 996, 1024 }, { 8, 997, 1024 }, { 8, 998, 1024 }, { 9, 999, 1024 },
+   { 7, 1000, 1024 }, { 8, 1001, 1024 }, { 8, 1002, 1024 }, { 9, 1003, 1024 }, { 8, 1004, 1024 }, { 9, 1005, 1024 }, { 9, 1006, 1024 }, { 10, 1007, 1024 },
+   { 7, 1008, 1024 }, { 8, 1009, 1024 }, { 8, 1010, 1024 }, { 9, 1011, 1024 }, { 8, 1012, 1024 }, { 9, 1013, 1024 }, { 9, 1014, 1024 }, { 10, 1015, 1024 },
+   { 8, 1016, 1024 }, { 9, 1017, 1024 }, { 9, 1018, 1024 }, { 10, 1019, 1024 }, { 9, 1020, 1024 }, { 10, 1021, 1024 }, { 10, 1022, 1024 }, { 11, 1023, 1024 },
+#if FP_LUT > 11
+   { 1, 0, 0 }, { 2, 1, 2048 }, { 2, 2, 2048 }, { 3, 3, 2048 }, { 2, 4, 2048 }, { 3, 5, 2048 }, { 3, 6, 2048 }, { 4, 7, 2048 },
+   { 2, 8, 2048 }, { 3, 9, 2048 }, { 3, 10, 2048 }, { 4, 11, 2048 }, { 3, 12, 2048 }, { 4, 13, 2048 }, { 4, 14, 2048 }, { 5, 15, 2048 },
+   { 2, 16, 2048 }, { 3, 17, 2048 }, { 3, 18, 2048 }, { 4, 19, 2048 }, { 3, 20, 2048 }, { 4, 21, 2048 }, { 4, 22, 2048 }, { 5, 23, 2048 },
+   { 3, 24, 2048 }, { 4, 25, 2048 }, { 4, 26, 2048 }, { 5, 27, 2048 }, { 4, 28, 2048 }, { 5, 29, 2048 }, { 5, 30, 2048 }, { 6, 31, 2048 },
+   { 2, 32, 2048 }, { 3, 33, 2048 }, { 3, 34, 2048 }, { 4, 35, 2048 }, { 3, 36, 2048 }, { 4, 37, 2048 }, { 4, 38, 2048 }, { 5, 39, 2048 },
+   { 3, 40, 2048 }, { 4, 41, 2048 }, { 4, 42, 2048 }, { 5, 43, 2048 }, { 4, 44, 2048 }, { 5, 45, 2048 }, { 5, 46, 2048 }, { 6, 47, 2048 },
+   { 3, 48, 2048 }, { 4, 49, 2048 }, { 4, 50, 2048 }, { 5, 51, 2048 }, { 4, 52, 2048 }, { 5, 53, 2048 }, { 5, 54, 2048 }, { 6, 55, 2048 },
+   { 4, 56, 2048 }, { 5, 57, 2048 }, { 5, 58, 2048 }, { 6, 59, 2048 }, { 5, 60, 2048 }, { 6, 61, 2048 }, { 6, 62, 2048 }, { 7, 63, 2048 },
+   { 2, 64, 2048 }, { 3, 65, 2048 }, { 3, 66, 2048 }, { 4, 67, 2048 }, { 3, 68, 2048 }, { 4, 69, 2048 }, { 4, 70, 2048 }, { 5, 71, 2048 },
+   { 3, 72, 2048 }, { 4, 73, 2048 }, { 4, 74, 2048 }, { 5, 75, 2048 }, { 4, 76, 2048 }, { 5, 77, 2048 }, { 5, 78, 2048 }, { 6, 79, 2048 },
+   { 3, 80, 2048 }, { 4, 81, 2048 }, { 4, 82, 2048 }, { 5, 83, 2048 }, { 4, 84, 2048 }, { 5, 85, 2048 }, { 5, 86, 2048 }, { 6, 87, 2048 },
+   { 4, 88, 2048 }, { 5, 89, 2048 }, { 5, 90, 2048 }, { 6, 91, 2048 }, { 5, 92, 2048 }, { 6, 93, 2048 }, { 6, 94, 2048 }, { 7, 95, 2048 },
+   { 3, 96, 2048 }, { 4, 97, 2048 }, { 4, 98, 2048 }, { 5, 99, 2048 }, { 4, 100, 2048 }, { 5, 101, 2048 }, { 5, 102, 2048 }, { 6, 103, 2048 },
+   { 4, 104, 2048 }, { 5, 105, 2048 }, { 5, 106, 2048 }, { 6, 107, 2048 }, { 5, 108, 2048 }, { 6, 109, 2048 }, { 6, 110, 2048 }, { 7, 111, 2048 },
+   { 4, 112, 2048 }, { 5, 113, 2048 }, { 5, 114, 2048 }, { 6, 115, 2048 }, { 5, 116, 2048 }, { 6, 117, 2048 }, { 6, 118, 2048 }, { 7, 119, 2048 },
+   { 5, 120, 2048 }, { 6, 121, 2048 }, { 6, 122, 2048 }, { 7, 123, 2048 }, { 6, 124, 2048 }, { 7, 125, 2048 }, { 7, 126, 2048 }, { 8, 127, 2048 },
+   { 2, 128, 2048 }, { 3, 129, 2048 }, { 3, 130, 2048 }, { 4, 131, 2048 }, { 3, 132, 2048 }, { 4, 133, 2048 }, { 4, 134, 2048 }, { 5, 135, 2048 },
+   { 3, 136, 2048 }, { 4, 137, 2048 }, { 4, 138, 2048 }, { 5, 139, 2048 }, { 4, 140, 2048 }, { 5, 141, 2048 }, { 5, 142, 2048 }, { 6, 143, 2048 },
+   { 3, 144, 2048 }, { 4, 145, 2048 }, { 4, 146, 2048 }, { 5, 147, 2048 }, { 4, 148, 2048 }, { 5, 149, 2048 }, { 5, 150, 2048 }, { 6, 151, 2048 },
+   { 4, 152, 2048 }, { 5, 153, 2048 }, { 5, 154, 2048 }, { 6, 155, 2048 }, { 5, 156, 2048 }, { 6, 157, 2048 }, { 6, 158, 2048 }, { 7, 159, 2048 },
+   { 3, 160, 2048 }, { 4, 161, 2048 }, { 4, 162, 2048 }, { 5, 163, 2048 }, { 4, 164, 2048 }, { 5, 165, 2048 }, { 5, 166, 2048 }, { 6, 167, 2048 },
+   { 4, 168, 2048 }, { 5, 169, 2048 }, { 5, 170, 2048 }, { 6, 171, 2048 }, { 5, 172, 2048 }, { 6, 173, 2048 }, { 6, 174, 2048 }, { 7, 175, 2048 },
+   { 4, 176, 2048 }, { 5, 177, 2048 }, { 5, 178, 2048 }, { 6, 179, 2048 }, { 5, 180, 2048 }, { 6, 181, 2048 }, { 6, 182, 2048 }, { 7, 183, 2048 },
+   { 5, 184, 2048 }, { 6, 185, 2048 }, { 6, 186, 2048 }, { 7, 187, 2048 }, { 6, 188, 2048 }, { 7, 189, 2048 }, { 7, 190, 2048 }, { 8, 191, 2048 },
+   { 3, 192, 2048 }, { 4, 193, 2048 }, { 4, 194, 2048 }, { 5, 195, 2048 }, { 4, 196, 2048 }, { 5, 197, 2048 }, { 5, 198, 2048 }, { 6, 199, 2048 },
+   { 4, 200, 2048 }, { 5, 201, 2048 }, { 5, 202, 2048 }, { 6, 203, 2048 }, { 5, 204, 2048 }, { 6, 205, 2048 }, { 6, 206, 2048 }, { 7, 207, 2048 },
+   { 4, 208, 2048 }, { 5, 209, 2048 }, { 5, 210, 2048 }, { 6, 211, 2048 }, { 5, 212, 2048 }, { 6, 213, 2048 }, { 6, 214, 2048 }, { 7, 215, 2048 },
+   { 5, 216, 2048 }, { 6, 217, 2048 }, { 6, 218, 2048 }, { 7, 219, 2048 }, { 6, 220, 2048 }, { 7, 221, 2048 }, { 7, 222, 2048 }, { 8, 223, 2048 },
+   { 4, 224, 2048 }, { 5, 225, 2048 }, { 5, 226, 2048 }, { 6, 227, 2048 }, { 5, 228, 2048 }, { 6, 229, 2048 }, { 6, 230, 2048 }, { 7, 231, 2048 },
+   { 5, 232, 2048 }, { 6, 233, 2048 }, { 6, 234, 2048 }, { 7, 235, 2048 }, { 6, 236, 2048 }, { 7, 237, 2048 }, { 7, 238, 2048 }, { 8, 239, 2048 },
+   { 5, 240, 2048 }, { 6, 241, 2048 }, { 6, 242, 2048 }, { 7, 243, 2048 }, { 6, 244, 2048 }, { 7, 245, 2048 }, { 7, 246, 2048 }, { 8, 247, 2048 },
+   { 6, 248, 2048 }, { 7, 249, 2048 }, { 7, 250, 2048 }, { 8, 251, 2048 }, { 7, 252, 2048 }, { 8, 253, 2048 }, { 8, 254, 2048 }, { 9, 255, 2048 },
+   { 2, 256, 2048 }, { 3, 257, 2048 }, { 3, 258, 2048 }, { 4, 259, 2048 }, { 3, 260, 2048 }, { 4, 261, 2048 }, { 4, 262, 2048 }, { 5, 263, 2048 },
+   { 3, 264, 2048 }, { 4, 265, 2048 }, { 4, 266, 2048 }, { 5, 267, 2048 }, { 4, 268, 2048 }, { 5, 269, 2048 }, { 5, 270, 2048 }, { 6, 271, 2048 },
+   { 3, 272, 2048 }, { 4, 273, 2048 }, { 4, 274, 2048 }, { 5, 275, 2048 }, { 4, 276, 2048 }, { 5, 277, 2048 }, { 5, 278, 2048 }, { 6, 279, 2048 },
+   { 4, 280, 2048 }, { 5, 281, 2048 }, { 5, 282, 2048 }, { 6, 283, 2048 }, { 5, 284, 2048 }, { 6, 285, 2048 }, { 6, 286, 2048 }, { 7, 287, 2048 },
+   { 3, 288, 2048 }, { 4, 289, 2048 }, { 4, 290, 2048 }, { 5, 291, 2048 }, { 4, 292, 2048 }, { 5, 293, 2048 }, { 5, 294, 2048 }, { 6, 295, 2048 },
+   { 4, 296, 2048 }, { 5, 297, 2048 }, { 5, 298, 2048 }, { 6, 299, 2048 }, { 5, 300, 2048 }, { 6, 301, 2048 }, { 6, 302, 2048 }, { 7, 303, 2048 },
+   { 4, 304, 2048 }, { 5, 305, 2048 }, { 5, 306, 2048 }, { 6, 307, 2048 }, { 5, 308, 2048 }, { 6, 309, 2048 }, { 6, 310, 2048 }, { 7, 311, 2048 },
+   { 5, 312, 2048 }, { 6, 313, 2048 }, { 6, 314, 2048 }, { 7, 315, 2048 }, { 6, 316, 2048 }, { 7, 317, 2048 }, { 7, 318, 2048 }, { 8, 319, 2048 },
+   { 3, 320, 2048 }, { 4, 321, 2048 }, { 4, 322, 2048 }, { 5, 323, 2048 }, { 4, 324, 2048 }, { 5, 325, 2048 }, { 5, 326, 2048 }, { 6, 327, 2048 },
+   { 4, 328, 2048 }, { 5, 329, 2048 }, { 5, 330, 2048 }, { 6, 331, 2048 }, { 5, 332, 2048 }, { 6, 333, 2048 }, { 6, 334, 2048 }, { 7, 335, 2048 },
+   { 4, 336, 2048 }, { 5, 337, 2048 }, { 5, 338, 2048 }, { 6, 339, 2048 }, { 5, 340, 2048 }, { 6, 341, 2048 }, { 6, 342, 2048 }, { 7, 343, 2048 },
+   { 5, 344, 2048 }, { 6, 345, 2048 }, { 6, 346, 2048 }, { 7, 347, 2048 }, { 6, 348, 2048 }, { 7, 349, 2048 }, { 7, 350, 2048 }, { 8, 351, 2048 },
+   { 4, 352, 2048 }, { 5, 353, 2048 }, { 5, 354, 2048 }, { 6, 355, 2048 }, { 5, 356, 2048 }, { 6, 357, 2048 }, { 6, 358, 2048 }, { 7, 359, 2048 },
+   { 5, 360, 2048 }, { 6, 361, 2048 }, { 6, 362, 2048 }, { 7, 363, 2048 }, { 6, 364, 2048 }, { 7, 365, 2048 }, { 7, 366, 2048 }, { 8, 367, 2048 },
+   { 5, 368, 2048 }, { 6, 369, 2048 }, { 6, 370, 2048 }, { 7, 371, 2048 }, { 6, 372, 2048 }, { 7, 373, 2048 }, { 7, 374, 2048 }, { 8, 375, 2048 },
+   { 6, 376, 2048 }, { 7, 377, 2048 }, { 7, 378, 2048 }, { 8, 379, 2048 }, { 7, 380, 2048 }, { 8, 381, 2048 }, { 8, 382, 2048 }, { 9, 383, 2048 },
+   { 3, 384, 2048 }, { 4, 385, 2048 }, { 4, 386, 2048 }, { 5, 387, 2048 }, { 4, 388, 2048 }, { 5, 389, 2048 }, { 5, 390, 2048 }, { 6, 391, 2048 },
+   { 4, 392, 2048 }, { 5, 393, 2048 }, { 5, 394, 2048 }, { 6, 395, 2048 }, { 5, 396, 2048 }, { 6, 397, 2048 }, { 6, 398, 2048 }, { 7, 399, 2048 },
+   { 4, 400, 2048 }, { 5, 401, 2048 }, { 5, 402, 2048 }, { 6, 403, 2048 }, { 5, 404, 2048 }, { 6, 405, 2048 }, { 6, 406, 2048 }, { 7, 407, 2048 },
+   { 5, 408, 2048 }, { 6, 409, 2048 }, { 6, 410, 2048 }, { 7, 411, 2048 }, { 6, 412, 2048 }, { 7, 413, 2048 }, { 7, 414, 2048 }, { 8, 415, 2048 },
+   { 4, 416, 2048 }, { 5, 417, 2048 }, { 5, 418, 2048 }, { 6, 419, 2048 }, { 5, 420, 2048 }, { 6, 421, 2048 }, { 6, 422, 2048 }, { 7, 423, 2048 },
+   { 5, 424, 2048 }, { 6, 425, 2048 }, { 6, 426, 2048 }, { 7, 427, 2048 }, { 6, 428, 2048 }, { 7, 429, 2048 }, { 7, 430, 2048 }, { 8, 431, 2048 },
+   { 5, 432, 2048 }, { 6, 433, 2048 }, { 6, 434, 2048 }, { 7, 435, 2048 }, { 6, 436, 2048 }, { 7, 437, 2048 }, { 7, 438, 2048 }, { 8, 439, 2048 },
+   { 6, 440, 2048 }, { 7, 441, 2048 }, { 7, 442, 2048 }, { 8, 443, 2048 }, { 7, 444, 2048 }, { 8, 445, 2048 }, { 8, 446, 2048 }, { 9, 447, 2048 },
+   { 4, 448, 2048 }, { 5, 449, 2048 }, { 5, 450, 2048 }, { 6, 451, 2048 }, { 5, 452, 2048 }, { 6, 453, 2048 }, { 6, 454, 2048 }, { 7, 455, 2048 },
+   { 5, 456, 2048 }, { 6, 457, 2048 }, { 6, 458, 2048 }, { 7, 459, 2048 }, { 6, 460, 2048 }, { 7, 461, 2048 }, { 7, 462, 2048 }, { 8, 463, 2048 },
+   { 5, 464, 2048 }, { 6, 465, 2048 }, { 6, 466, 2048 }, { 7, 467, 2048 }, { 6, 468, 2048 }, { 7, 469, 2048 }, { 7, 470, 2048 }, { 8, 471, 2048 },
+   { 6, 472, 2048 }, { 7, 473, 2048 }, { 7, 474, 2048 }, { 8, 475, 2048 }, { 7, 476, 2048 }, { 8, 477, 2048 }, { 8, 478, 2048 }, { 9, 479, 2048 },
+   { 5, 480, 2048 }, { 6, 481, 2048 }, { 6, 482, 2048 }, { 7, 483, 2048 }, { 6, 484, 2048 }, { 7, 485, 2048 }, { 7, 486, 2048 }, { 8, 487, 2048 },
+   { 6, 488, 2048 }, { 7, 489, 2048 }, { 7, 490, 2048 }, { 8, 491, 2048 }, { 7, 492, 2048 }, { 8, 493, 2048 }, { 8, 494, 2048 }, { 9, 495, 2048 },
+   { 6, 496, 2048 }, { 7, 497, 2048 }, { 7, 498, 2048 }, { 8, 499, 2048 }, { 7, 500, 2048 }, { 8, 501, 2048 }, { 8, 502, 2048 }, { 9, 503, 2048 },
+   { 7, 504, 2048 }, { 8, 505, 2048 }, { 8, 506, 2048 }, { 9, 507, 2048 }, { 8, 508, 2048 }, { 9, 509, 2048 }, { 9, 510, 2048 }, { 10, 511, 2048 },
+   { 2, 512, 2048 }, { 3, 513, 2048 }, { 3, 514, 2048 }, { 4, 515, 2048 }, { 3, 516, 2048 }, { 4, 517, 2048 }, { 4, 518, 2048 }, { 5, 519, 2048 },
+   { 3, 520, 2048 }, { 4, 521, 2048 }, { 4, 522, 2048 }, { 5, 523, 2048 }, { 4, 524, 2048 }, { 5, 525, 2048 }, { 5, 526, 2048 }, { 6, 527, 2048 },
+   { 3, 528, 2048 }, { 4, 529, 2048 }, { 4, 530, 2048 }, { 5, 531, 2048 }, { 4, 532, 2048 }, { 5, 533, 2048 }, { 5, 534, 2048 }, { 6, 535, 2048 },
+   { 4, 536, 2048 }, { 5, 537, 2048 }, { 5, 538, 2048 }, { 6, 539, 2048 }, { 5, 540, 2048 }, { 6, 541, 2048 }, { 6, 542, 2048 }, { 7, 543, 2048 },
+   { 3, 544, 2048 }, { 4, 545, 2048 }, { 4, 546, 2048 }, { 5, 547, 2048 }, { 4, 548, 2048 }, { 5, 549, 2048 }, { 5, 550, 2048 }, { 6, 551, 2048 },
+   { 4, 552, 2048 }, { 5, 553, 2048 }, { 5, 554, 2048 }, { 6, 555, 2048 }, { 5, 556, 2048 }, { 6, 557, 2048 }, { 6, 558, 2048 }, { 7, 559, 2048 },
+   { 4, 560, 2048 }, { 5, 561, 2048 }, { 5, 562, 2048 }, { 6, 563, 2048 }, { 5, 564, 2048 }, { 6, 565, 2048 }, { 6, 566, 2048 }, { 7, 567, 2048 },
+   { 5, 568, 2048 }, { 6, 569, 2048 }, { 6, 570, 2048 }, { 7, 571, 2048 }, { 6, 572, 2048 }, { 7, 573, 2048 }, { 7, 574, 2048 }, { 8, 575, 2048 },
+   { 3, 576, 2048 }, { 4, 577, 2048 }, { 4, 578, 2048 }, { 5, 579, 2048 }, { 4, 580, 2048 }, { 5, 581, 2048 }, { 5, 582, 2048 }, { 6, 583, 2048 },
+   { 4, 584, 2048 }, { 5, 585, 2048 }, { 5, 586, 2048 }, { 6, 587, 2048 }, { 5, 588, 2048 }, { 6, 589, 2048 }, { 6, 590, 2048 }, { 7, 591, 2048 },
+   { 4, 592, 2048 }, { 5, 593, 2048 }, { 5, 594, 2048 }, { 6, 595, 2048 }, { 5, 596, 2048 }, { 6, 597, 2048 }, { 6, 598, 2048 }, { 7, 599, 2048 },
+   { 5, 600, 2048 }, { 6, 601, 2048 }, { 6, 602, 2048 }, { 7, 603, 2048 }, { 6, 604, 2048 }, { 7, 605, 2048 }, { 7, 606, 2048 }, { 8, 607, 2048 },
+   { 4, 608, 2048 }, { 5, 609, 2048 }, { 5, 610, 2048 }, { 6, 611, 2048 }, { 5, 612, 2048 }, { 6, 613, 2048 }, { 6, 614, 2048 }, { 7, 615, 2048 },
+   { 5, 616, 2048 }, { 6, 617, 2048 }, { 6, 618, 2048 }, { 7, 619, 2048 }, { 6, 620, 2048 }, { 7, 621, 2048 }, { 7, 622, 2048 }, { 8, 623, 2048 },
+   { 5, 624, 2048 }, { 6, 625, 2048 }, { 6, 626, 2048 }, { 7, 627, 2048 }, { 6, 628, 2048 }, { 7, 629, 2048 }, { 7, 630, 2048 }, { 8, 631, 2048 },
+   { 6, 632, 2048 }, { 7, 633, 2048 }, { 7, 634, 2048 }, { 8, 635, 2048 }, { 7, 636, 2048 }, { 8, 637, 2048 }, { 8, 638, 2048 }, { 9, 639, 2048 },
+   { 3, 640, 2048 }, { 4, 641, 2048 }, { 4, 642, 2048 }, { 5, 643, 2048 }, { 4, 644, 2048 }, { 5, 645, 2048 }, { 5, 646, 2048 }, { 6, 647, 2048 },
+   { 4, 648, 2048 }, { 5, 649, 2048 }, { 5, 650, 2048 }, { 6, 651, 2048 }, { 5, 652, 2048 }, { 6, 653, 2048 }, { 6, 654, 2048 }, { 7, 655, 2048 },
+   { 4, 656, 2048 }, { 5, 657, 2048 }, { 5, 658, 2048 }, { 6, 659, 2048 }, { 5, 660, 2048 }, { 6, 661, 2048 }, { 6, 662, 2048 }, { 7, 663, 2048 },
+   { 5, 664, 2048 }, { 6, 665, 2048 }, { 6, 666, 2048 }, { 7, 667, 2048 }, { 6, 668, 2048 }, { 7, 669, 2048 }, { 7, 670, 2048 }, { 8, 671, 2048 },
+   { 4, 672, 2048 }, { 5, 673, 2048 }, { 5, 674, 2048 }, { 6, 675, 2048 }, { 5, 676, 2048 }, { 6, 677, 2048 }, { 6, 678, 2048 }, { 7, 679, 2048 },
+   { 5, 680, 2048 }, { 6, 681, 2048 }, { 6, 682, 2048 }, { 7, 683, 2048 }, { 6, 684, 2048 }, { 7, 685, 2048 }, { 7, 686, 2048 }, { 8, 687, 2048 },
+   { 5, 688, 2048 }, { 6, 689, 2048 }, { 6, 690, 2048 }, { 7, 691, 2048 }, { 6, 692, 2048 }, { 7, 693, 2048 }, { 7, 694, 2048 }, { 8, 695, 2048 },
+   { 6, 696, 2048 }, { 7, 697, 2048 }, { 7, 698, 2048 }, { 8, 699, 2048 }, { 7, 700, 2048 }, { 8, 701, 2048 }, { 8, 702, 2048 }, { 9, 703, 2048 },
+   { 4, 704, 2048 }, { 5, 705, 2048 }, { 5, 706, 2048 }, { 6, 707, 2048 }, { 5, 708, 2048 }, { 6, 709, 2048 }, { 6, 710, 2048 }, { 7, 711, 2048 },
+   { 5, 712, 2048 }, { 6, 713, 2048 }, { 6, 714, 2048 }, { 7, 715, 2048 }, { 6, 716, 2048 }, { 7, 717, 2048 }, { 7, 718, 2048 }, { 8, 719, 2048 },
+   { 5, 720, 2048 }, { 6, 721, 2048 }, { 6, 722, 2048 }, { 7, 723, 2048 }, { 6, 724, 2048 }, { 7, 725, 2048 }, { 7, 726, 2048 }, { 8, 727, 2048 },
+   { 6, 728, 2048 }, { 7, 729, 2048 }, { 7, 730, 2048 }, { 8, 731, 2048 }, { 7, 732, 2048 }, { 8, 733, 2048 }, { 8, 734, 2048 }, { 9, 735, 2048 },
+   { 5, 736, 2048 }, { 6, 737, 2048 }, { 6, 738, 2048 }, { 7, 739, 2048 }, { 6, 740, 2048 }, { 7, 741, 2048 }, { 7, 742, 2048 }, { 8, 743, 2048 },
+   { 6, 744, 2048 }, { 7, 745, 2048 }, { 7, 746, 2048 }, { 8, 747, 2048 }, { 7, 748, 2048 }, { 8, 749, 2048 }, { 8, 750, 2048 }, { 9, 751, 2048 },
+   { 6, 752, 2048 }, { 7, 753, 2048 }, { 7, 754, 2048 }, { 8, 755, 2048 }, { 7, 756, 2048 }, { 8, 757, 2048 }, { 8, 758, 2048 }, { 9, 759, 2048 },
+   { 7, 760, 2048 }, { 8, 761, 2048 }, { 8, 762, 2048 }, { 9, 763, 2048 }, { 8, 764, 2048 }, { 9, 765, 2048 }, { 9, 766, 2048 }, { 10, 767, 2048 },
+   { 3, 768, 2048 }, { 4, 769, 2048 }, { 4, 770, 2048 }, { 5, 771, 2048 }, { 4, 772, 2048 }, { 5, 773, 2048 }, { 5, 774, 2048 }, { 6, 775, 2048 },
+   { 4, 776, 2048 }, { 5, 777, 2048 }, { 5, 778, 2048 }, { 6, 779, 2048 }, { 5, 780, 2048 }, { 6, 781, 2048 }, { 6, 782, 2048 }, { 7, 783, 2048 },
+   { 4, 784, 2048 }, { 5, 785, 2048 }, { 5, 786, 2048 }, { 6, 787, 2048 }, { 5, 788, 2048 }, { 6, 789, 2048 }, { 6, 790, 2048 }, { 7, 791, 2048 },
+   { 5, 792, 2048 }, { 6, 793, 2048 }, { 6, 794, 2048 }, { 7, 795, 2048 }, { 6, 796, 2048 }, { 7, 797, 2048 }, { 7, 798, 2048 }, { 8, 799, 2048 },
+   { 4, 800, 2048 }, { 5, 801, 2048 }, { 5, 802, 2048 }, { 6, 803, 2048 }, { 5, 804, 2048 }, { 6, 805, 2048 }, { 6, 806, 2048 }, { 7, 807, 2048 },
+   { 5, 808, 2048 }, { 6, 809, 2048 }, { 6, 810, 2048 }, { 7, 811, 2048 }, { 6, 812, 2048 }, { 7, 813, 2048 }, { 7, 814, 2048 }, { 8, 815, 2048 },
+   { 5, 816, 2048 }, { 6, 817, 2048 }, { 6, 818, 2048 }, { 7, 819, 2048 }, { 6, 820, 2048 }, { 7, 821, 2048 }, { 7, 822, 2048 }, { 8, 823, 2048 },
+   { 6, 824, 2048 }, { 7, 825, 2048 }, { 7, 826, 2048 }, { 8, 827, 2048 }, { 7, 828, 2048 }, { 8, 829, 2048 }, { 8, 830, 2048 }, { 9, 831, 2048 },
+   { 4, 832, 2048 }, { 5, 833, 2048 }, { 5, 834, 2048 }, { 6, 835, 2048 }, { 5, 836, 2048 }, { 6, 837, 2048 }, { 6, 838, 2048 }, { 7, 839, 2048 },
+   { 5, 840, 2048 }, { 6, 841, 2048 }, { 6, 842, 2048 }, { 7, 843, 2048 }, { 6, 844, 2048 }, { 7, 845, 2048 }, { 7, 846, 2048 }, { 8, 847, 2048 },
+   { 5, 848, 2048 }, { 6, 849, 2048 }, { 6, 850, 2048 }, { 7, 851, 2048 }, { 6, 852, 2048 }, { 7, 853, 2048 }, { 7, 854, 2048 }, { 8, 855, 2048 },
+   { 6, 856, 2048 }, { 7, 857, 2048 }, { 7, 858, 2048 }, { 8, 859, 2048 }, { 7, 860, 2048 }, { 8, 861, 2048 }, { 8, 862, 2048 }, { 9, 863, 2048 },
+   { 5, 864, 2048 }, { 6, 865, 2048 }, { 6, 866, 2048 }, { 7, 867, 2048 }, { 6, 868, 2048 }, { 7, 869, 2048 }, { 7, 870, 2048 }, { 8, 871, 2048 },
+   { 6, 872, 2048 }, { 7, 873, 2048 }, { 7, 874, 2048 }, { 8, 875, 2048 }, { 7, 876, 2048 }, { 8, 877, 2048 }, { 8, 878, 2048 }, { 9, 879, 2048 },
+   { 6, 880, 2048 }, { 7, 881, 2048 }, { 7, 882, 2048 }, { 8, 883, 2048 }, { 7, 884, 2048 }, { 8, 885, 2048 }, { 8, 886, 2048 }, { 9, 887, 2048 },
+   { 7, 888, 2048 }, { 8, 889, 2048 }, { 8, 890, 2048 }, { 9, 891, 2048 }, { 8, 892, 2048 }, { 9, 893, 2048 }, { 9, 894, 2048 }, { 10, 895, 2048 },
+   { 4, 896, 2048 }, { 5, 897, 2048 }, { 5, 898, 2048 }, { 6, 899, 2048 }, { 5, 900, 2048 }, { 6, 901, 2048 }, { 6, 902, 2048 }, { 7, 903, 2048 },
+   { 5, 904, 2048 }, { 6, 905, 2048 }, { 6, 906, 2048 }, { 7, 907, 2048 }, { 6, 908, 2048 }, { 7, 909, 2048 }, { 7, 910, 2048 }, { 8, 911, 2048 },
+   { 5, 912, 2048 }, { 6, 913, 2048 }, { 6, 914, 2048 }, { 7, 915, 2048 }, { 6, 916, 2048 }, { 7, 917, 2048 }, { 7, 918, 2048 }, { 8, 919, 2048 },
+   { 6, 920, 2048 }, { 7, 921, 2048 }, { 7, 922, 2048 }, { 8, 923, 2048 }, { 7, 924, 2048 }, { 8, 925, 2048 }, { 8, 926, 2048 }, { 9, 927, 2048 },
+   { 5, 928, 2048 }, { 6, 929, 2048 }, { 6, 930, 2048 }, { 7, 931, 2048 }, { 6, 932, 2048 }, { 7, 933, 2048 }, { 7, 934, 2048 }, { 8, 935, 2048 },
+   { 6, 936, 2048 }, { 7, 937, 2048 }, { 7, 938, 2048 }, { 8, 939, 2048 }, { 7, 940, 2048 }, { 8, 941, 2048 }, { 8, 942, 2048 }, { 9, 943, 2048 },
+   { 6, 944, 2048 }, { 7, 945, 2048 }, { 7, 946, 2048 }, { 8, 947, 2048 }, { 7, 948, 2048 }, { 8, 949, 2048 }, { 8, 950, 2048 }, { 9, 951, 2048 },
+   { 7, 952, 2048 }, { 8, 953, 2048 }, { 8, 954, 2048 }, { 9, 955, 2048 }, { 8, 956, 2048 }, { 9, 957, 2048 }, { 9, 958, 2048 }, { 10, 959, 2048 },
+   { 5, 960, 2048 }, { 6, 961, 2048 }, { 6, 962, 2048 }, { 7, 963, 2048 }, { 6, 964, 2048 }, { 7, 965, 2048 }, { 7, 966, 2048 }, { 8, 967, 2048 },
+   { 6, 968, 2048 }, { 7, 969, 2048 }, { 7, 970, 2048 }, { 8, 971, 2048 }, { 7, 972, 2048 }, { 8, 973, 2048 }, { 8, 974, 2048 }, { 9, 975, 2048 },
+   { 6, 976, 2048 }, { 7, 977, 2048 }, { 7, 978, 2048 }, { 8, 979, 2048 }, { 7, 980, 2048 }, { 8, 981, 2048 }, { 8, 982, 2048 }, { 9, 983, 2048 },
+   { 7, 984, 2048 }, { 8, 985, 2048 }, { 8, 986, 2048 }, { 9, 987, 2048 }, { 8, 988, 2048 }, { 9, 989, 2048 }, { 9, 990, 2048 }, { 10, 991, 2048 },
+   { 6, 992, 2048 }, { 7, 993, 2048 }, { 7, 994, 2048 }, { 8, 995, 2048 }, { 7, 996, 2048 }, { 8, 997, 2048 }, { 8, 998, 2048 }, { 9, 999, 2048 },
+   { 7, 1000, 2048 }, { 8, 1001, 2048 }, { 8, 1002, 2048 }, { 9, 1003, 2048 }, { 8, 1004, 2048 }, { 9, 1005, 2048 }, { 9, 1006, 2048 }, { 10, 1007, 2048 },
+   { 7, 1008, 2048 }, { 8, 1009, 2048 }, { 8, 1010, 2048 }, { 9, 1011, 2048 }, { 8, 1012, 2048 }, { 9, 1013, 2048 }, { 9, 1014, 2048 }, { 10, 1015, 2048 },
+   { 8, 1016, 2048 }, { 9, 1017, 2048 }, { 9, 1018, 2048 }, { 10, 1019, 2048 }, { 9, 1020, 2048 }, { 10, 1021, 2048 }, { 10, 1022, 2048 }, { 11, 1023, 2048 },
+   { 2, 1024, 2048 }, { 3, 1025, 2048 }, { 3, 1026, 2048 }, { 4, 1027, 2048 }, { 3, 1028, 2048 }, { 4, 1029, 2048 }, { 4, 1030, 2048 }, { 5, 1031, 2048 },
+   { 3, 1032, 2048 }, { 4, 1033, 2048 }, { 4, 1034, 2048 }, { 5, 1035, 2048 }, { 4, 1036, 2048 }, { 5, 1037, 2048 }, { 5, 1038, 2048 }, { 6, 1039, 2048 },
+   { 3, 1040, 2048 }, { 4, 1041, 2048 }, { 4, 1042, 2048 }, { 5, 1043, 2048 }, { 4, 1044, 2048 }, { 5, 1045, 2048 }, { 5, 1046, 2048 }, { 6, 1047, 2048 },
+   { 4, 1048, 2048 }, { 5, 1049, 2048 }, { 5, 1050, 2048 }, { 6, 1051, 2048 }, { 5, 1052, 2048 }, { 6, 1053, 2048 }, { 6, 1054, 2048 }, { 7, 1055, 2048 },
+   { 3, 1056, 2048 }, { 4, 1057, 2048 }, { 4, 1058, 2048 }, { 5, 1059, 2048 }, { 4, 1060, 2048 }, { 5, 1061, 2048 }, { 5, 1062, 2048 }, { 6, 1063, 2048 },
+   { 4, 1064, 2048 }, { 5, 1065, 2048 }, { 5, 1066, 2048 }, { 6, 1067, 2048 }, { 5, 1068, 2048 }, { 6, 1069, 2048 }, { 6, 1070, 2048 }, { 7, 1071, 2048 },
+   { 4, 1072, 2048 }, { 5, 1073, 2048 }, { 5, 1074, 2048 }, { 6, 1075, 2048 }, { 5, 1076, 2048 }, { 6, 1077, 2048 }, { 6, 1078, 2048 }, { 7, 1079, 2048 },
+   { 5, 1080, 2048 }, { 6, 1081, 2048 }, { 6, 1082, 2048 }, { 7, 1083, 2048 }, { 6, 1084, 2048 }, { 7, 1085, 2048 }, { 7, 1086, 2048 }, { 8, 1087, 2048 },
+   { 3, 1088, 2048 }, { 4, 1089, 2048 }, { 4, 1090, 2048 }, { 5, 1091, 2048 }, { 4, 1092, 2048 }, { 5, 1093, 2048 }, { 5, 1094, 2048 }, { 6, 1095, 2048 },
+   { 4, 1096, 2048 }, { 5, 1097, 2048 }, { 5, 1098, 2048 }, { 6, 1099, 2048 }, { 5, 1100, 2048 }, { 6, 1101, 2048 }, { 6, 1102, 2048 }, { 7, 1103, 2048 },
+   { 4, 1104, 2048 }, { 5, 1105, 2048 }, { 5, 1106, 2048 }, { 6, 1107, 2048 }, { 5, 1108, 2048 }, { 6, 1109, 2048 }, { 6, 1110, 2048 }, { 7, 1111, 2048 },
+   { 5, 1112, 2048 }, { 6, 1113, 2048 }, { 6, 1114, 2048 }, { 7, 1115, 2048 }, { 6, 1116, 2048 }, { 7, 1117, 2048 }, { 7, 1118, 2048 }, { 8, 1119, 2048 },
+   { 4, 1120, 2048 }, { 5, 1121, 2048 }, { 5, 1122, 2048 }, { 6, 1123, 2048 }, { 5, 1124, 2048 }, { 6, 1125, 2048 }, { 6, 1126, 2048 }, { 7, 1127, 2048 },
+   { 5, 1128, 2048 }, { 6, 1129, 2048 }, { 6, 1130, 2048 }, { 7, 1131, 2048 }, { 6, 1132, 2048 }, { 7, 1133, 2048 }, { 7, 1134, 2048 }, { 8, 1135, 2048 },
+   { 5, 1136, 2048 }, { 6, 1137, 2048 }, { 6, 1138, 2048 }, { 7, 1139, 2048 }, { 6, 1140, 2048 }, { 7, 1141, 2048 }, { 7, 1142, 2048 }, { 8, 1143, 2048 },
+   { 6, 1144, 2048 }, { 7, 1145, 2048 }, { 7, 1146, 2048 }, { 8, 1147, 2048 }, { 7, 1148, 2048 }, { 8, 1149, 2048 }, { 8, 1150, 2048 }, { 9, 1151, 2048 },
+   { 3, 1152, 2048 }, { 4, 1153, 2048 }, { 4, 1154, 2048 }, { 5, 1155, 2048 }, { 4, 1156, 2048 }, { 5, 1157, 2048 }, { 5, 1158, 2048 }, { 6, 1159, 2048 },
+   { 4, 1160, 2048 }, { 5, 1161, 2048 }, { 5, 1162, 2048 }, { 6, 1163, 2048 }, { 5, 1164, 2048 }, { 6, 1165, 2048 }, { 6, 1166, 2048 }, { 7, 1167, 2048 },
+   { 4, 1168, 2048 }, { 5, 1169, 2048 }, { 5, 1170, 2048 }, { 6, 1171, 2048 }, { 5, 1172, 2048 }, { 6, 1173, 2048 }, { 6, 1174, 2048 }, { 7, 1175, 2048 },
+   { 5, 1176, 2048 }, { 6, 1177, 2048 }, { 6, 1178, 2048 }, { 7, 1179, 2048 }, { 6, 1180, 2048 }, { 7, 1181, 2048 }, { 7, 1182, 2048 }, { 8, 1183, 2048 },
+   { 4, 1184, 2048 }, { 5, 1185, 2048 }, { 5, 1186, 2048 }, { 6, 1187, 2048 }, { 5, 1188, 2048 }, { 6, 1189, 2048 }, { 6, 1190, 2048 }, { 7, 1191, 2048 },
+   { 5, 1192, 2048 }, { 6, 1193, 2048 }, { 6, 1194, 2048 }, { 7, 1195, 2048 }, { 6, 1196, 2048 }, { 7, 1197, 2048 }, { 7, 1198, 2048 }, { 8, 1199, 2048 },
+   { 5, 1200, 2048 }, { 6, 1201, 2048 }, { 6, 1202, 2048 }, { 7, 1203, 2048 }, { 6, 1204, 2048 }, { 7, 1205, 2048 }, { 7, 1206, 2048 }, { 8, 1207, 2048 },
+   { 6, 1208, 2048 }, { 7, 1209, 2048 }, { 7, 1210, 2048 }, { 8, 1211, 2048 }, { 7, 1212, 2048 }, { 8, 1213, 2048 }, { 8, 1214, 2048 }, { 9, 1215, 2048 },
+   { 4, 1216, 2048 }, { 5, 1217, 2048 }, { 5, 1218, 2048 }, { 6, 1219, 2048 }, { 5, 1220, 2048 }, { 6, 1221, 2048 }, { 6, 1222, 2048 }, { 7, 1223, 2048 },
+   { 5, 1224, 2048 }, { 6, 1225, 2048 }, { 6, 1226, 2048 }, { 7, 1227, 2048 }, { 6, 1228, 2048 }, { 7, 1229, 2048 }, { 7, 1230, 2048 }, { 8, 1231, 2048 },
+   { 5, 1232, 2048 }, { 6, 1233, 2048 }, { 6, 1234, 2048 }, { 7, 1235, 2048 }, { 6, 1236, 2048 }, { 7, 1237, 2048 }, { 7, 1238, 2048 }, { 8, 1239, 2048 },
+   { 6, 1240, 2048 }, { 7, 1241, 2048 }, { 7, 1242, 2048 }, { 8, 1243, 2048 }, { 7, 1244, 2048 }, { 8, 1245, 2048 }, { 8, 1246, 2048 }, { 9, 1247, 2048 },
+   { 5, 1248, 2048 }, { 6, 1249, 2048 }, { 6, 1250, 2048 }, { 7, 1251, 2048 }, { 6, 1252, 2048 }, { 7, 1253, 2048 }, { 7, 1254, 2048 }, { 8, 1255, 2048 },
+   { 6, 1256, 2048 }, { 7, 1257, 2048 }, { 7, 1258, 2048 }, { 8, 1259, 2048 }, { 7, 1260, 2048 }, { 8, 1261, 2048 }, { 8, 1262, 2048 }, { 9, 1263, 2048 },
+   { 6, 1264, 2048 }, { 7, 1265, 2048 }, { 7, 1266, 2048 }, { 8, 1267, 2048 }, { 7, 1268, 2048 }, { 8, 1269, 2048 }, { 8, 1270, 2048 }, { 9, 1271, 2048 },
+   { 7, 1272, 2048 }, { 8, 1273, 2048 }, { 8, 1274, 2048 }, { 9, 1275, 2048 }, { 8, 1276, 2048 }, { 9, 1277, 2048 }, { 9, 1278, 2048 }, { 10, 1279, 2048 },
+   { 3, 1280, 2048 }, { 4, 1281, 2048 }, { 4, 1282, 2048 }, { 5, 1283, 2048 }, { 4, 1284, 2048 }, { 5, 1285, 2048 }, { 5, 1286, 2048 }, { 6, 1287, 2048 },
+   { 4, 1288, 2048 }, { 5, 1289, 2048 }, { 5, 1290, 2048 }, { 6, 1291, 2048 }, { 5, 1292, 2048 }, { 6, 1293, 2048 }, { 6, 1294, 2048 }, { 7, 1295, 2048 },
+   { 4, 1296, 2048 }, { 5, 1297, 2048 }, { 5, 1298, 2048 }, { 6, 1299, 2048 }, { 5, 1300, 2048 }, { 6, 1301, 2048 }, { 6, 1302, 2048 }, { 7, 1303, 2048 },
+   { 5, 1304, 2048 }, { 6, 1305, 2048 }, { 6, 1306, 2048 }, { 7, 1307, 2048 }, { 6, 1308, 2048 }, { 7, 1309, 2048 }, { 7, 1310, 2048 }, { 8, 1311, 2048 },
+   { 4, 1312, 2048 }, { 5, 1313, 2048 }, { 5, 1314, 2048 }, { 6, 1315, 2048 }, { 5, 1316, 2048 }, { 6, 1317, 2048 }, { 6, 1318, 2048 }, { 7, 1319, 2048 },
+   { 5, 1320, 2048 }, { 6, 1321, 2048 }, { 6, 1322, 2048 }, { 7, 1323, 2048 }, { 6, 1324, 2048 }, { 7, 1325, 2048 }, { 7, 1326, 2048 }, { 8, 1327, 2048 },
+   { 5, 1328, 2048 }, { 6, 1329, 2048 }, { 6, 1330, 2048 }, { 7, 1331, 2048 }, { 6, 1332, 2048 }, { 7, 1333, 2048 }, { 7, 1334, 2048 }, { 8, 1335, 2048 },
+   { 6, 1336, 2048 }, { 7, 1337, 2048 }, { 7, 1338, 2048 }, { 8, 1339, 2048 }, { 7, 1340, 2048 }, { 8, 1341, 2048 }, { 8, 1342, 2048 }, { 9, 1343, 2048 },
+   { 4, 1344, 2048 }, { 5, 1345, 2048 }, { 5, 1346, 2048 }, { 6, 1347, 2048 }, { 5, 1348, 2048 }, { 6, 1349, 2048 }, { 6, 1350, 2048 }, { 7, 1351, 2048 },
+   { 5, 1352, 2048 }, { 6, 1353, 2048 }, { 6, 1354, 2048 }, { 7, 1355, 2048 }, { 6, 1356, 2048 }, { 7, 1357, 2048 }, { 7, 1358, 2048 }, { 8, 1359, 2048 },
+   { 5, 1360, 2048 }, { 6, 1361, 2048 }, { 6, 1362, 2048 }, { 7, 1363, 2048 }, { 6, 1364, 2048 }, { 7, 1365, 2048 }, { 7, 1366, 2048 }, { 8, 1367, 2048 },
+   { 6, 1368, 2048 }, { 7, 1369, 2048 }, { 7, 1370, 2048 }, { 8, 1371, 2048 }, { 7, 1372, 2048 }, { 8, 1373, 2048 }, { 8, 1374, 2048 }, { 9, 1375, 2048 },
+   { 5, 1376, 2048 }, { 6, 1377, 2048 }, { 6, 1378, 2048 }, { 7, 1379, 2048 }, { 6, 1380, 2048 }, { 7, 1381, 2048 }, { 7, 1382, 2048 }, { 8, 1383, 2048 },
+   { 6, 1384, 2048 }, { 7, 1385, 2048 }, { 7, 1386, 2048 }, { 8, 1387, 2048 }, { 7, 1388, 2048 }, { 8, 1389, 2048 }, { 8, 1390, 2048 }, { 9, 1391, 2048 },
+   { 6, 1392, 2048 }, { 7, 1393, 2048 }, { 7, 1394, 2048 }, { 8, 1395, 2048 }, { 7, 1396, 2048 }, { 8, 1397, 2048 }, { 8, 1398, 2048 }, { 9, 1399, 2048 },
+   { 7, 1400, 2048 }, { 8, 1401, 2048 }, { 8, 1402, 2048 }, { 9, 1403, 2048 }, { 8, 1404, 2048 }, { 9, 1405, 2048 }, { 9, 1406, 2048 }, { 10, 1407, 2048 },
+   { 4, 1408, 2048 }, { 5, 1409, 2048 }, { 5, 1410, 2048 }, { 6, 1411, 2048 }, { 5, 1412, 2048 }, { 6, 1413, 2048 }, { 6, 1414, 2048 }, { 7, 1415, 2048 },
+   { 5, 1416, 2048 }, { 6, 1417, 2048 }, { 6, 1418, 2048 }, { 7, 1419, 2048 }, { 6, 1420, 2048 }, { 7, 1421, 2048 }, { 7, 1422, 2048 }, { 8, 1423, 2048 },
+   { 5, 1424, 2048 }, { 6, 1425, 2048 }, { 6, 1426, 2048 }, { 7, 1427, 2048 }, { 6, 1428, 2048 }, { 7, 1429, 2048 }, { 7, 1430, 2048 }, { 8, 1431, 2048 },
+   { 6, 1432, 2048 }, { 7, 1433, 2048 }, { 7, 1434, 2048 }, { 8, 1435, 2048 }, { 7, 1436, 2048 }, { 8, 1437, 2048 }, { 8, 1438, 2048 }, { 9, 1439, 2048 },
+   { 5, 1440, 2048 }, { 6, 1441, 2048 }, { 6, 1442, 2048 }, { 7, 1443, 2048 }, { 6, 1444, 2048 }, { 7, 1445, 2048 }, { 7, 1446, 2048 }, { 8, 1447, 2048 },
+   { 6, 1448, 2048 }, { 7, 1449, 2048 }, { 7, 1450, 2048 }, { 8, 1451, 2048 }, { 7, 1452, 2048 }, { 8, 1453, 2048 }, { 8, 1454, 2048 }, { 9, 1455, 2048 },
+   { 6, 1456, 2048 }, { 7, 1457, 2048 }, { 7, 1458, 2048 }, { 8, 1459, 2048 }, { 7, 1460, 2048 }, { 8, 1461, 2048 }, { 8, 1462, 2048 }, { 9, 1463, 2048 },
+   { 7, 1464, 2048 }, { 8, 1465, 2048 }, { 8, 1466, 2048 }, { 9, 1467, 2048 }, { 8, 1468, 2048 }, { 9, 1469, 2048 }, { 9, 1470, 2048 }, { 10, 1471, 2048 },
+   { 5, 1472, 2048 }, { 6, 1473, 2048 }, { 6, 1474, 2048 }, { 7, 1475, 2048 }, { 6, 1476, 2048 }, { 7, 1477, 2048 }, { 7, 1478, 2048 }, { 8, 1479, 2048 },
+   { 6, 1480, 2048 }, { 7, 1481, 2048 }, { 7, 1482, 2048 }, { 8, 1483, 2048 }, { 7, 1484, 2048 }, { 8, 1485, 2048 }, { 8, 1486, 2048 }, { 9, 1487, 2048 },
+   { 6, 1488, 2048 }, { 7, 1489, 2048 }, { 7, 1490, 2048 }, { 8, 1491, 2048 }, { 7, 1492, 2048 }, { 8, 1493, 2048 }, { 8, 1494, 2048 }, { 9, 1495, 2048 },
+   { 7, 1496, 2048 }, { 8, 1497, 2048 }, { 8, 1498, 2048 }, { 9, 1499, 2048 }, { 8, 1500, 2048 }, { 9, 1501, 2048 }, { 9, 1502, 2048 }, { 10, 1503, 2048 },
+   { 6, 1504, 2048 }, { 7, 1505, 2048 }, { 7, 1506, 2048 }, { 8, 1507, 2048 }, { 7, 1508, 2048 }, { 8, 1509, 2048 }, { 8, 1510, 2048 }, { 9, 1511, 2048 },
+   { 7, 1512, 2048 }, { 8, 1513, 2048 }, { 8, 1514, 2048 }, { 9, 1515, 2048 }, { 8, 1516, 2048 }, { 9, 1517, 2048 }, { 9, 1518, 2048 }, { 10, 1519, 2048 },
+   { 7, 1520, 2048 }, { 8, 1521, 2048 }, { 8, 1522, 2048 }, { 9, 1523, 2048 }, { 8, 1524, 2048 }, { 9, 1525, 2048 }, { 9, 1526, 2048 }, { 10, 1527, 2048 },
+   { 8, 1528, 2048 }, { 9, 1529, 2048 }, { 9, 1530, 2048 }, { 10, 1531, 2048 }, { 9, 1532, 2048 }, { 10, 1533, 2048 }, { 10, 1534, 2048 }, { 11, 1535, 2048 },
+   { 3, 1536, 2048 }, { 4, 1537, 2048 }, { 4, 1538, 2048 }, { 5, 1539, 2048 }, { 4, 1540, 2048 }, { 5, 1541, 2048 }, { 5, 1542, 2048 }, { 6, 1543, 2048 },
+   { 4, 1544, 2048 }, { 5, 1545, 2048 }, { 5, 1546, 2048 }, { 6, 1547, 2048 }, { 5, 1548, 2048 }, { 6, 1549, 2048 }, { 6, 1550, 2048 }, { 7, 1551, 2048 },
+   { 4, 1552, 2048 }, { 5, 1553, 2048 }, { 5, 1554, 2048 }, { 6, 1555, 2048 }, { 5, 1556, 2048 }, { 6, 1557, 2048 }, { 6, 1558, 2048 }, { 7, 1559, 2048 },
+   { 5, 1560, 2048 }, { 6, 1561, 2048 }, { 6, 1562, 2048 }, { 7, 1563, 2048 }, { 6, 1564, 2048 }, { 7, 1565, 2048 }, { 7, 1566, 2048 }, { 8, 1567, 2048 },
+   { 4, 1568, 2048 }, { 5, 1569, 2048 }, { 5, 1570, 2048 }, { 6, 1571, 2048 }, { 5, 1572, 2048 }, { 6, 1573, 2048 }, { 6, 1574, 2048 }, { 7, 1575, 2048 },
+   { 5, 1576, 2048 }, { 6, 1577, 2048 }, { 6, 1578, 2048 }, { 7, 1579, 2048 }, { 6, 1580, 2048 }, { 7, 1581, 2048 }, { 7, 1582, 2048 }, { 8, 1583, 2048 },
+   { 5, 1584, 2048 }, { 6, 1585, 2048 }, { 6, 1586, 2048 }, { 7, 1587, 2048 }, { 6, 1588, 2048 }, { 7, 1589, 2048 }, { 7, 1590, 2048 }, { 8, 1591, 2048 },
+   { 6, 1592, 2048 }, { 7, 1593, 2048 }, { 7, 1594, 2048 }, { 8, 1595, 2048 }, { 7, 1596, 2048 }, { 8, 1597, 2048 }, { 8, 1598, 2048 }, { 9, 1599, 2048 },
+   { 4, 1600, 2048 }, { 5, 1601, 2048 }, { 5, 1602, 2048 }, { 6, 1603, 2048 }, { 5, 1604, 2048 }, { 6, 1605, 2048 }, { 6, 1606, 2048 }, { 7, 1607, 2048 },
+   { 5, 1608, 2048 }, { 6, 1609, 2048 }, { 6, 1610, 2048 }, { 7, 1611, 2048 }, { 6, 1612, 2048 }, { 7, 1613, 2048 }, { 7, 1614, 2048 }, { 8, 1615, 2048 },
+   { 5, 1616, 2048 }, { 6, 1617, 2048 }, { 6, 1618, 2048 }, { 7, 1619, 2048 }, { 6, 1620, 2048 }, { 7, 1621, 2048 }, { 7, 1622, 2048 }, { 8, 1623, 2048 },
+   { 6, 1624, 2048 }, { 7, 1625, 2048 }, { 7, 1626, 2048 }, { 8, 1627, 2048 }, { 7, 1628, 2048 }, { 8, 1629, 2048 }, { 8, 1630, 2048 }, { 9, 1631, 2048 },
+   { 5, 1632, 2048 }, { 6, 1633, 2048 }, { 6, 1634, 2048 }, { 7, 1635, 2048 }, { 6, 1636, 2048 }, { 7, 1637, 2048 }, { 7, 1638, 2048 }, { 8, 1639, 2048 },
+   { 6, 1640, 2048 }, { 7, 1641, 2048 }, { 7, 1642, 2048 }, { 8, 1643, 2048 }, { 7, 1644, 2048 }, { 8, 1645, 2048 }, { 8, 1646, 2048 }, { 9, 1647, 2048 },
+   { 6, 1648, 2048 }, { 7, 1649, 2048 }, { 7, 1650, 2048 }, { 8, 1651, 2048 }, { 7, 1652, 2048 }, { 8, 1653, 2048 }, { 8, 1654, 2048 }, { 9, 1655, 2048 },
+   { 7, 1656, 2048 }, { 8, 1657, 2048 }, { 8, 1658, 2048 }, { 9, 1659, 2048 }, { 8, 1660, 2048 }, { 9, 1661, 2048 }, { 9, 1662, 2048 }, { 10, 1663, 2048 },
+   { 4, 1664, 2048 }, { 5, 1665, 2048 }, { 5, 1666, 2048 }, { 6, 1667, 2048 }, { 5, 1668, 2048 }, { 6, 1669, 2048 }, { 6, 1670, 2048 }, { 7, 1671, 2048 },
+   { 5, 1672, 2048 }, { 6, 1673, 2048 }, { 6, 1674, 2048 }, { 7, 1675, 2048 }, { 6, 1676, 2048 }, { 7, 1677, 2048 }, { 7, 1678, 2048 }, { 8, 1679, 2048 },
+   { 5, 1680, 2048 }, { 6, 1681, 2048 }, { 6, 1682, 2048 }, { 7, 1683, 2048 }, { 6, 1684, 2048 }, { 7, 1685, 2048 }, { 7, 1686, 2048 }, { 8, 1687, 2048 },
+   { 6, 1688, 2048 }, { 7, 1689, 2048 }, { 7, 1690, 2048 }, { 8, 1691, 2048 }, { 7, 1692, 2048 }, { 8, 1693, 2048 }, { 8, 1694, 2048 }, { 9, 1695, 2048 },
+   { 5, 1696, 2048 }, { 6, 1697, 2048 }, { 6, 1698, 2048 }, { 7, 1699, 2048 }, { 6, 1700, 2048 }, { 7, 1701, 2048 }, { 7, 1702, 2048 }, { 8, 1703, 2048 },
+   { 6, 1704, 2048 }, { 7, 1705, 2048 }, { 7, 1706, 2048 }, { 8, 1707, 2048 }, { 7, 1708, 2048 }, { 8, 1709, 2048 }, { 8, 1710, 2048 }, { 9, 1711, 2048 },
+   { 6, 1712, 2048 }, { 7, 1713, 2048 }, { 7, 1714, 2048 }, { 8, 1715, 2048 }, { 7, 1716, 2048 }, { 8, 1717, 2048 }, { 8, 1718, 2048 }, { 9, 1719, 2048 },
+   { 7, 1720, 2048 }, { 8, 1721, 2048 }, { 8, 1722, 2048 }, { 9, 1723, 2048 }, { 8, 1724, 2048 }, { 9, 1725, 2048 }, { 9, 1726, 2048 }, { 10, 1727, 2048 },
+   { 5, 1728, 2048 }, { 6, 1729, 2048 }, { 6, 1730, 2048 }, { 7, 1731, 2048 }, { 6, 1732, 2048 }, { 7, 1733, 2048 }, { 7, 1734, 2048 }, { 8, 1735, 2048 },
+   { 6, 1736, 2048 }, { 7, 1737, 2048 }, { 7, 1738, 2048 }, { 8, 1739, 2048 }, { 7, 1740, 2048 }, { 8, 1741, 2048 }, { 8, 1742, 2048 }, { 9, 1743, 2048 },
+   { 6, 1744, 2048 }, { 7, 1745, 2048 }, { 7, 1746, 2048 }, { 8, 1747, 2048 }, { 7, 1748, 2048 }, { 8, 1749, 2048 }, { 8, 1750, 2048 }, { 9, 1751, 2048 },
+   { 7, 1752, 2048 }, { 8, 1753, 2048 }, { 8, 1754, 2048 }, { 9, 1755, 2048 }, { 8, 1756, 2048 }, { 9, 1757, 2048 }, { 9, 1758, 2048 }, { 10, 1759, 2048 },
+   { 6, 1760, 2048 }, { 7, 1761, 2048 }, { 7, 1762, 2048 }, { 8, 1763, 2048 }, { 7, 1764, 2048 }, { 8, 1765, 2048 }, { 8, 1766, 2048 }, { 9, 1767, 2048 },
+   { 7, 1768, 2048 }, { 8, 1769, 2048 }, { 8, 1770, 2048 }, { 9, 1771, 2048 }, { 8, 1772, 2048 }, { 9, 1773, 2048 }, { 9, 1774, 2048 }, { 10, 1775, 2048 },
+   { 7, 1776, 2048 }, { 8, 1777, 2048 }, { 8, 1778, 2048 }, { 9, 1779, 2048 }, { 8, 1780, 2048 }, { 9, 1781, 2048 }, { 9, 1782, 2048 }, { 10, 1783, 2048 },
+   { 8, 1784, 2048 }, { 9, 1785, 2048 }, { 9, 1786, 2048 }, { 10, 1787, 2048 }, { 9, 1788, 2048 }, { 10, 1789, 2048 }, { 10, 1790, 2048 }, { 11, 1791, 2048 },
+   { 4, 1792, 2048 }, { 5, 1793, 2048 }, { 5, 1794, 2048 }, { 6, 1795, 2048 }, { 5, 1796, 2048 }, { 6, 1797, 2048 }, { 6, 1798, 2048 }, { 7, 1799, 2048 },
+   { 5, 1800, 2048 }, { 6, 1801, 2048 }, { 6, 1802, 2048 }, { 7, 1803, 2048 }, { 6, 1804, 2048 }, { 7, 1805, 2048 }, { 7, 1806, 2048 }, { 8, 1807, 2048 },
+   { 5, 1808, 2048 }, { 6, 1809, 2048 }, { 6, 1810, 2048 }, { 7, 1811, 2048 }, { 6, 1812, 2048 }, { 7, 1813, 2048 }, { 7, 1814, 2048 }, { 8, 1815, 2048 },
+   { 6, 1816, 2048 }, { 7, 1817, 2048 }, { 7, 1818, 2048 }, { 8, 1819, 2048 }, { 7, 1820, 2048 }, { 8, 1821, 2048 }, { 8, 1822, 2048 }, { 9, 1823, 2048 },
+   { 5, 1824, 2048 }, { 6, 1825, 2048 }, { 6, 1826, 2048 }, { 7, 1827, 2048 }, { 6, 1828, 2048 }, { 7, 1829, 2048 }, { 7, 1830, 2048 }, { 8, 1831, 2048 },
+   { 6, 1832, 2048 }, { 7, 1833, 2048 }, { 7, 1834, 2048 }, { 8, 1835, 2048 }, { 7, 1836, 2048 }, { 8, 1837, 2048 }, { 8, 1838, 2048 }, { 9, 1839, 2048 },
+   { 6, 1840, 2048 }, { 7, 1841, 2048 }, { 7, 1842, 2048 }, { 8, 1843, 2048 }, { 7, 1844, 2048 }, { 8, 1845, 2048 }, { 8, 1846, 2048 }, { 9, 1847, 2048 },
+   { 7, 1848, 2048 }, { 8, 1849, 2048 }, { 8, 1850, 2048 }, { 9, 1851, 2048 }, { 8, 1852, 2048 }, { 9, 1853, 2048 }, { 9, 1854, 2048 }, { 10, 1855, 2048 },
+   { 5, 1856, 2048 }, { 6, 1857, 2048 }, { 6, 1858, 2048 }, { 7, 1859, 2048 }, { 6, 1860, 2048 }, { 7, 1861, 2048 }, { 7, 1862, 2048 }, { 8, 1863, 2048 },
+   { 6, 1864, 2048 }, { 7, 1865, 2048 }, { 7, 1866, 2048 }, { 8, 1867, 2048 }, { 7, 1868, 2048 }, { 8, 1869, 2048 }, { 8, 1870, 2048 }, { 9, 1871, 2048 },
+   { 6, 1872, 2048 }, { 7, 1873, 2048 }, { 7, 1874, 2048 }, { 8, 1875, 2048 }, { 7, 1876, 2048 }, { 8, 1877, 2048 }, { 8, 1878, 2048 }, { 9, 1879, 2048 },
+   { 7, 1880, 2048 }, { 8, 1881, 2048 }, { 8, 1882, 2048 }, { 9, 1883, 2048 }, { 8, 1884, 2048 }, { 9, 1885, 2048 }, { 9, 1886, 2048 }, { 10, 1887, 2048 },
+   { 6, 1888, 2048 }, { 7, 1889, 2048 }, { 7, 1890, 2048 }, { 8, 1891, 2048 }, { 7, 1892, 2048 }, { 8, 1893, 2048 }, { 8, 1894, 2048 }, { 9, 1895, 2048 },
+   { 7, 1896, 2048 }, { 8, 1897, 2048 }, { 8, 1898, 2048 }, { 9, 1899, 2048 }, { 8, 1900, 2048 }, { 9, 1901, 2048 }, { 9, 1902, 2048 }, { 10, 1903, 2048 },
+   { 7, 1904, 2048 }, { 8, 1905, 2048 }, { 8, 1906, 2048 }, { 9, 1907, 2048 }, { 8, 1908, 2048 }, { 9, 1909, 2048 }, { 9, 1910, 2048 }, { 10, 1911, 2048 },
+   { 8, 1912, 2048 }, { 9, 1913, 2048 }, { 9, 1914, 2048 }, { 10, 1915, 2048 }, { 9, 1916, 2048 }, { 10, 1917, 2048 }, { 10, 1918, 2048 }, { 11, 1919, 2048 },
+   { 5, 1920, 2048 }, { 6, 1921, 2048 }, { 6, 1922, 2048 }, { 7, 1923, 2048 }, { 6, 1924, 2048 }, { 7, 1925, 2048 }, { 7, 1926, 2048 }, { 8, 1927, 2048 },
+   { 6, 1928, 2048 }, { 7, 1929, 2048 }, { 7, 1930, 2048 }, { 8, 1931, 2048 }, { 7, 1932, 2048 }, { 8, 1933, 2048 }, { 8, 1934, 2048 }, { 9, 1935, 2048 },
+   { 6, 1936, 2048 }, { 7, 1937, 2048 }, { 7, 1938, 2048 }, { 8, 1939, 2048 }, { 7, 1940, 2048 }, { 8, 1941, 2048 }, { 8, 1942, 2048 }, { 9, 1943, 2048 },
+   { 7, 1944, 2048 }, { 8, 1945, 2048 }, { 8, 1946, 2048 }, { 9, 1947, 2048 }, { 8, 1948, 2048 }, { 9, 1949, 2048 }, { 9, 1950, 2048 }, { 10, 1951, 2048 },
+   { 6, 1952, 2048 }, { 7, 1953, 2048 }, { 7, 1954, 2048 }, { 8, 1955, 2048 }, { 7, 1956, 2048 }, { 8, 1957, 2048 }, { 8, 1958, 2048 }, { 9, 1959, 2048 },
+   { 7, 1960, 2048 }, { 8, 1961, 2048 }, { 8, 1962, 2048 }, { 9, 1963, 2048 }, { 8, 1964, 2048 }, { 9, 1965, 2048 }, { 9, 1966, 2048 }, { 10, 1967, 2048 },
+   { 7, 1968, 2048 }, { 8, 1969, 2048 }, { 8, 1970, 2048 }, { 9, 1971, 2048 }, { 8, 1972, 2048 }, { 9, 1973, 2048 }, { 9, 1974, 2048 }, { 10, 1975, 2048 },
+   { 8, 1976, 2048 }, { 9, 1977, 2048 }, { 9, 1978, 2048 }, { 10, 1979, 2048 }, { 9, 1980, 2048 }, { 10, 1981, 2048 }, { 10, 1982, 2048 }, { 11, 1983, 2048 },
+   { 6, 1984, 2048 }, { 7, 1985, 2048 }, { 7, 1986, 2048 }, { 8, 1987, 2048 }, { 7, 1988, 2048 }, { 8, 1989, 2048 }, { 8, 1990, 2048 }, { 9, 1991, 2048 },
+   { 7, 1992, 2048 }, { 8, 1993, 2048 }, { 8, 1994, 2048 }, { 9, 1995, 2048 }, { 8, 1996, 2048 }, { 9, 1997, 2048 }, { 9, 1998, 2048 }, { 10, 1999, 2048 },
+   { 7, 2000, 2048 }, { 8, 2001, 2048 }, { 8, 2002, 2048 }, { 9, 2003, 2048 }, { 8, 2004, 2048 }, { 9, 2005, 2048 }, { 9, 2006, 2048 }, { 10, 2007, 2048 },
+   { 8, 2008, 2048 }, { 9, 2009, 2048 }, { 9, 2010, 2048 }, { 10, 2011, 2048 }, { 9, 2012, 2048 }, { 10, 2013, 2048 }, { 10, 2014, 2048 }, { 11, 2015, 2048 },
+   { 7, 2016, 2048 }, { 8, 2017, 2048 }, { 8, 2018, 2048 }, { 9, 2019, 2048 }, { 8, 2020, 2048 }, { 9, 2021, 2048 }, { 9, 2022, 2048 }, { 10, 2023, 2048 },
+   { 8, 2024, 2048 }, { 9, 2025, 2048 }, { 9, 2026, 2048 }, { 10, 2027, 2048 }, { 9, 2028, 2048 }, { 10, 2029, 2048 }, { 10, 2030, 2048 }, { 11, 2031, 2048 },
+   { 8, 2032, 2048 }, { 9, 2033, 2048 }, { 9, 2034, 2048 }, { 10, 2035, 2048 }, { 9, 2036, 2048 }, { 10, 2037, 2048 }, { 10, 2038, 2048 }, { 11, 2039, 2048 },
+   { 9, 2040, 2048 }, { 10, 2041, 2048 }, { 10, 2042, 2048 }, { 11, 2043, 2048 }, { 10, 2044, 2048 }, { 11, 2045, 2048 }, { 11, 2046, 2048 }, { 12, 2047, 2048 },
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+};
+
+
+/* find a hole and free as required, return -1 if no hole found */
+static int find_hole(void)
+{
+   unsigned x;
+   int      y, z;
+   for (z = -1, y = INT_MAX, x = 0; x < FP_ENTRIES; x++) {
+       if (fp_cache[x].lru_count < y && fp_cache[x].lock == 0) {
+          z = x;
+          y = fp_cache[x].lru_count;
+       }
+   }
+
+   /* decrease all */
+   for (x = 0; x < FP_ENTRIES; x++) {
+      if (fp_cache[x].lru_count > 3) {
+         --(fp_cache[x].lru_count);
+      }
+   }
+
+   /* free entry z */
+   if (z >= 0 && fp_cache[z].g) {
+      mp_clear(&fp_cache[z].mu);
+      wc_ecc_del_point(fp_cache[z].g);
+      fp_cache[z].g  = NULL;
+      for (x = 0; x < (1U<<FP_LUT); x++) {
+         wc_ecc_del_point(fp_cache[z].LUT[x]);
+         fp_cache[z].LUT[x] = NULL;
+      }
+      fp_cache[z].lru_count = 0;
+   }
+   return z;
+}
+
+/* determine if a base is already in the cache and if so, where */
+static int find_base(ecc_point* g)
+{
+   int x;
+   for (x = 0; x < FP_ENTRIES; x++) {
+      if (fp_cache[x].g != NULL &&
+          mp_cmp(fp_cache[x].g->x, g->x) == MP_EQ &&
+          mp_cmp(fp_cache[x].g->y, g->y) == MP_EQ &&
+          mp_cmp(fp_cache[x].g->z, g->z) == MP_EQ) {
+         break;
+      }
+   }
+   if (x == FP_ENTRIES) {
+      x = -1;
+   }
+   return x;
+}
+
+/* add a new base to the cache */
+static int add_entry(int idx, ecc_point *g)
+{
+   unsigned x, y;
+
+   /* allocate base and LUT */
+   fp_cache[idx].g = wc_ecc_new_point();
+   if (fp_cache[idx].g == NULL) {
+      return GEN_MEM_ERR;
+   }
+
+   /* copy x and y */
+   if ((mp_copy(g->x, fp_cache[idx].g->x) != MP_OKAY) ||
+       (mp_copy(g->y, fp_cache[idx].g->y) != MP_OKAY) ||
+       (mp_copy(g->z, fp_cache[idx].g->z) != MP_OKAY)) {
+      wc_ecc_del_point(fp_cache[idx].g);
+      fp_cache[idx].g = NULL;
+      return GEN_MEM_ERR;
+   }
+
+   for (x = 0; x < (1U<<FP_LUT); x++) {
+      fp_cache[idx].LUT[x] = wc_ecc_new_point();
+      if (fp_cache[idx].LUT[x] == NULL) {
+         for (y = 0; y < x; y++) {
+            wc_ecc_del_point(fp_cache[idx].LUT[y]);
+            fp_cache[idx].LUT[y] = NULL;
+         }
+         wc_ecc_del_point(fp_cache[idx].g);
+         fp_cache[idx].g         = NULL;
+         fp_cache[idx].lru_count = 0;
+         return GEN_MEM_ERR;
+      }
+   }
+
+   fp_cache[idx].lru_count = 0;
+
+   return MP_OKAY;
+}
+#endif
+
+#ifndef WOLFSSL_SP_MATH
+/* build the LUT by spacing the bits of the input by #modulus/FP_LUT bits apart
+ *
+ * The algorithm builds patterns in increasing bit order by first making all
+ * single bit input patterns, then all two bit input patterns and so on
+ */
+static int build_lut(int idx, mp_int* a, mp_int* modulus, mp_digit mp,
+    mp_int* mu)
+{
+   int err;
+   unsigned x, y, bitlen, lut_gap;
+   mp_int tmp;
+
+   if (mp_init(&tmp) != MP_OKAY)
+       return GEN_MEM_ERR;
+
+   /* sanity check to make sure lut_order table is of correct size,
+      should compile out to a NOP if true */
+   if ((sizeof(lut_orders) / sizeof(lut_orders[0])) < (1U<<FP_LUT)) {
+       err = BAD_FUNC_ARG;
+   }
+   else {
+    /* get bitlen and round up to next multiple of FP_LUT */
+    bitlen  = mp_unsigned_bin_size(modulus) << 3;
+    x       = bitlen % FP_LUT;
+    if (x) {
+      bitlen += FP_LUT - x;
+    }
+    lut_gap = bitlen / FP_LUT;
+
+    /* init the mu */
+    err = mp_init_copy(&fp_cache[idx].mu, mu);
+   }
+
+   /* copy base */
+   if (err == MP_OKAY) {
+     if ((mp_mulmod(fp_cache[idx].g->x, mu, modulus,
+                  fp_cache[idx].LUT[1]->x) != MP_OKAY) ||
+         (mp_mulmod(fp_cache[idx].g->y, mu, modulus,
+                  fp_cache[idx].LUT[1]->y) != MP_OKAY) ||
+         (mp_mulmod(fp_cache[idx].g->z, mu, modulus,
+                  fp_cache[idx].LUT[1]->z) != MP_OKAY)) {
+       err = MP_MULMOD_E;
+     }
+   }
+
+   /* make all single bit entries */
+   for (x = 1; x < FP_LUT; x++) {
+      if (err != MP_OKAY)
+          break;
+      if ((mp_copy(fp_cache[idx].LUT[1<<(x-1)]->x,
+                   fp_cache[idx].LUT[1<<x]->x) != MP_OKAY) ||
+          (mp_copy(fp_cache[idx].LUT[1<<(x-1)]->y,
+                   fp_cache[idx].LUT[1<<x]->y) != MP_OKAY) ||
+          (mp_copy(fp_cache[idx].LUT[1<<(x-1)]->z,
+                   fp_cache[idx].LUT[1<<x]->z) != MP_OKAY)){
+          err = MP_INIT_E;
+          break;
+      } else {
+
+         /* now double it bitlen/FP_LUT times */
+         for (y = 0; y < lut_gap; y++) {
+             if ((err = ecc_projective_dbl_point(fp_cache[idx].LUT[1<<x],
+                            fp_cache[idx].LUT[1<<x], a, modulus, mp)) != MP_OKAY) {
+                 break;
+             }
+         }
+     }
+  }
+
+   /* now make all entries in increase order of hamming weight */
+   for (x = 2; x <= FP_LUT; x++) {
+       if (err != MP_OKAY)
+           break;
+       for (y = 0; y < (1UL<<FP_LUT); y++) {
+           if (lut_orders[y].ham != (int)x) continue;
+
+           /* perform the add */
+           if ((err = ecc_projective_add_point(
+                           fp_cache[idx].LUT[lut_orders[y].terma],
+                           fp_cache[idx].LUT[lut_orders[y].termb],
+                           fp_cache[idx].LUT[y], a, modulus, mp)) != MP_OKAY) {
+              break;
+           }
+       }
+   }
+
+   /* now map all entries back to affine space to make point addition faster */
+   for (x = 1; x < (1UL<<FP_LUT); x++) {
+       if (err != MP_OKAY)
+           break;
+
+       /* convert z to normal from montgomery */
+       err = mp_montgomery_reduce(fp_cache[idx].LUT[x]->z, modulus, mp);
+
+       /* invert it */
+       if (err == MP_OKAY)
+         err = mp_invmod(fp_cache[idx].LUT[x]->z, modulus,
+                         fp_cache[idx].LUT[x]->z);
+
+       if (err == MP_OKAY)
+         /* now square it */
+         err = mp_sqrmod(fp_cache[idx].LUT[x]->z, modulus, &tmp);
+
+       if (err == MP_OKAY)
+         /* fix x */
+         err = mp_mulmod(fp_cache[idx].LUT[x]->x, &tmp, modulus,
+                         fp_cache[idx].LUT[x]->x);
+
+       if (err == MP_OKAY)
+         /* get 1/z^3 */
+         err = mp_mulmod(&tmp, fp_cache[idx].LUT[x]->z, modulus, &tmp);
+
+       if (err == MP_OKAY)
+         /* fix y */
+         err = mp_mulmod(fp_cache[idx].LUT[x]->y, &tmp, modulus,
+                         fp_cache[idx].LUT[x]->y);
+
+       if (err == MP_OKAY)
+         /* free z */
+         mp_clear(fp_cache[idx].LUT[x]->z);
+   }
+
+   mp_clear(&tmp);
+
+   if (err == MP_OKAY)
+     return MP_OKAY;
+
+   /* err cleanup */
+   for (y = 0; y < (1U<<FP_LUT); y++) {
+      wc_ecc_del_point(fp_cache[idx].LUT[y]);
+      fp_cache[idx].LUT[y] = NULL;
+   }
+   wc_ecc_del_point(fp_cache[idx].g);
+   fp_cache[idx].g         = NULL;
+   fp_cache[idx].lru_count = 0;
+   mp_clear(&fp_cache[idx].mu);
+
+   return err;
+}
+
+/* perform a fixed point ECC mulmod */
+static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* a,
+                        mp_int* modulus, mp_digit mp, int map)
+{
+#define KB_SIZE 128
+
+#ifdef WOLFSSL_SMALL_STACK
+   unsigned char* kb = NULL;
+#else
+   unsigned char kb[KB_SIZE];
+#endif
+   int      x, err;
+   unsigned y, z = 0, bitlen, bitpos, lut_gap, first;
+   mp_int   tk, order;
+
+   if (mp_init_multi(&tk, &order, NULL, NULL, NULL, NULL) != MP_OKAY)
+       return MP_INIT_E;
+
+   /* if it's smaller than modulus we fine */
+   if (mp_unsigned_bin_size(k) > mp_unsigned_bin_size(modulus)) {
+      /* find order */
+      y = mp_unsigned_bin_size(modulus);
+      for (x = 0; ecc_sets[x].size; x++) {
+         if (y <= (unsigned)ecc_sets[x].size) break;
+      }
+
+      /* back off if we are on the 521 bit curve */
+      if (y == 66) --x;
+
+      if ((err = mp_read_radix(&order, ecc_sets[x].order,
+                                                MP_RADIX_HEX)) != MP_OKAY) {
+         goto done;
+      }
+
+      /* k must be less than modulus */
+      if (mp_cmp(k, &order) != MP_LT) {
+         if ((err = mp_mod(k, &order, &tk)) != MP_OKAY) {
+            goto done;
+         }
+      } else {
+         if ((err = mp_copy(k, &tk)) != MP_OKAY) {
+            goto done;
+         }
+      }
+   } else {
+      if ((err = mp_copy(k, &tk)) != MP_OKAY) {
+         goto done;
+      }
+   }
+
+   /* get bitlen and round up to next multiple of FP_LUT */
+   bitlen  = mp_unsigned_bin_size(modulus) << 3;
+   x       = bitlen % FP_LUT;
+   if (x) {
+      bitlen += FP_LUT - x;
+   }
+   lut_gap = bitlen / FP_LUT;
+
+   /* get the k value */
+   if (mp_unsigned_bin_size(&tk) > (int)(KB_SIZE - 2)) {
+      err = BUFFER_E; goto done;
+   }
+
+   /* store k */
+#ifdef WOLFSSL_SMALL_STACK
+   kb = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER);
+   if (kb == NULL) {
+      err = MEMORY_E; goto done;
+   }
+#endif
+
+   XMEMSET(kb, 0, KB_SIZE);
+   if ((err = mp_to_unsigned_bin(&tk, kb)) == MP_OKAY) {
+      /* let's reverse kb so it's little endian */
+      x = 0;
+      y = mp_unsigned_bin_size(&tk);
+      if (y > 0) {
+          y -= 1;
+      }
+
+      while ((unsigned)x < y) {
+         z = kb[x]; kb[x] = kb[y]; kb[y] = (byte)z;
+         ++x; --y;
+      }
+
+      /* at this point we can start, yipee */
+      first = 1;
+      for (x = lut_gap-1; x >= 0; x--) {
+          /* extract FP_LUT bits from kb spread out by lut_gap bits and offset
+             by x bits from the start */
+          bitpos = x;
+          for (y = z = 0; y < FP_LUT; y++) {
+             z |= ((kb[bitpos>>3] >> (bitpos&7)) & 1) << y;
+             bitpos += lut_gap;  /* it's y*lut_gap + x, but here we can avoid
+                                    the mult in each loop */
+          }
+
+          /* double if not first */
+          if (!first) {
+             if ((err = ecc_projective_dbl_point(R, R, a, modulus,
+                                                              mp)) != MP_OKAY) {
+                break;
+             }
+          }
+
+          /* add if not first, otherwise copy */
+          if (!first && z) {
+             if ((err = ecc_projective_add_point(R, fp_cache[idx].LUT[z], R, a,
+                                                     modulus, mp)) != MP_OKAY) {
+                break;
+             }
+             if (mp_iszero(R->z)) {
+                 /* When all zero then should have done an add */
+                 if (mp_iszero(R->x) && mp_iszero(R->y)) {
+                     if ((err = ecc_projective_dbl_point(fp_cache[idx].LUT[z],
+                                               R, a, modulus, mp)) != MP_OKAY) {
+                         break;
+                     }
+                 }
+                 /* When only Z zero then result is infinity */
+                 else {
+                    err = mp_set(R->x, 0);
+                    if (err != MP_OKAY) {
+                       break;
+                    }
+                    err = mp_set(R->y, 0);
+                    if (err != MP_OKAY) {
+                       break;
+                    }
+                    err = mp_copy(&fp_cache[idx].mu, R->z);
+                    if (err != MP_OKAY) {
+                       break;
+                    }
+                    first = 1;
+                 }
+             }
+          } else if (z) {
+             if ((mp_copy(fp_cache[idx].LUT[z]->x, R->x) != MP_OKAY) ||
+                 (mp_copy(fp_cache[idx].LUT[z]->y, R->y) != MP_OKAY) ||
+                 (mp_copy(&fp_cache[idx].mu,       R->z) != MP_OKAY)) {
+                 err = GEN_MEM_ERR;
+                 break;
+             }
+             first = 0;
+          }
+      }
+   }
+
+   if (err == MP_OKAY) {
+      (void) z; /* Acknowledge the unused assignment */
+      ForceZero(kb, KB_SIZE);
+
+      /* map R back from projective space */
+      if (map) {
+         err = ecc_map(R, modulus, mp);
+      } else {
+         err = MP_OKAY;
+      }
+   }
+
+done:
+   /* cleanup */
+   mp_clear(&order);
+   mp_clear(&tk);
+
+#ifdef WOLFSSL_SMALL_STACK
+   XFREE(kb, NULL, DYNAMIC_TYPE_ECC_BUFFER);
+#endif
+
+#undef KB_SIZE
+
+   return err;
+}
+#endif
+
+#ifdef ECC_SHAMIR
+#ifndef WOLFSSL_SP_MATH
+/* perform a fixed point ECC mulmod */
+static int accel_fp_mul2add(int idx1, int idx2,
+                            mp_int* kA, mp_int* kB,
+                            ecc_point *R, mp_int* a,
+                            mp_int* modulus, mp_digit mp)
+{
+#define KB_SIZE 128
+
+#ifdef WOLFSSL_SMALL_STACK
+   unsigned char* kb[2] = {NULL, NULL};
+#else
+   unsigned char kb[2][KB_SIZE];
+#endif
+   int      x, err;
+   unsigned y, z, bitlen, bitpos, lut_gap, first, zA, zB;
+   mp_int tka, tkb, order;
+
+   if (mp_init_multi(&tka, &tkb, &order, NULL, NULL, NULL) != MP_OKAY)
+       return MP_INIT_E;
+
+   /* if it's smaller than modulus we fine */
+   if (mp_unsigned_bin_size(kA) > mp_unsigned_bin_size(modulus)) {
+      /* find order */
+      y = mp_unsigned_bin_size(modulus);
+      for (x = 0; ecc_sets[x].size; x++) {
+         if (y <= (unsigned)ecc_sets[x].size) break;
+      }
+
+      /* back off if we are on the 521 bit curve */
+      if (y == 66) --x;
+
+      if ((err = mp_read_radix(&order, ecc_sets[x].order,
+                                                MP_RADIX_HEX)) != MP_OKAY) {
+         goto done;
+      }
+
+      /* kA must be less than modulus */
+      if (mp_cmp(kA, &order) != MP_LT) {
+         if ((err = mp_mod(kA, &order, &tka)) != MP_OKAY) {
+            goto done;
+         }
+      } else {
+         if ((err = mp_copy(kA, &tka)) != MP_OKAY) {
+            goto done;
+         }
+      }
+   } else {
+      if ((err = mp_copy(kA, &tka)) != MP_OKAY) {
+         goto done;
+      }
+   }
+
+   /* if it's smaller than modulus we fine */
+   if (mp_unsigned_bin_size(kB) > mp_unsigned_bin_size(modulus)) {
+      /* find order */
+      y = mp_unsigned_bin_size(modulus);
+      for (x = 0; ecc_sets[x].size; x++) {
+         if (y <= (unsigned)ecc_sets[x].size) break;
+      }
+
+      /* back off if we are on the 521 bit curve */
+      if (y == 66) --x;
+
+      if ((err = mp_read_radix(&order, ecc_sets[x].order,
+                                                MP_RADIX_HEX)) != MP_OKAY) {
+         goto done;
+      }
+
+      /* kB must be less than modulus */
+      if (mp_cmp(kB, &order) != MP_LT) {
+         if ((err = mp_mod(kB, &order, &tkb)) != MP_OKAY) {
+            goto done;
+         }
+      } else {
+         if ((err = mp_copy(kB, &tkb)) != MP_OKAY) {
+            goto done;
+         }
+      }
+   } else {
+      if ((err = mp_copy(kB, &tkb)) != MP_OKAY) {
+         goto done;
+      }
+   }
+
+   /* get bitlen and round up to next multiple of FP_LUT */
+   bitlen  = mp_unsigned_bin_size(modulus) << 3;
+   x       = bitlen % FP_LUT;
+   if (x) {
+      bitlen += FP_LUT - x;
+   }
+   lut_gap = bitlen / FP_LUT;
+
+   /* get the k value */
+   if ((mp_unsigned_bin_size(&tka) > (int)(KB_SIZE - 2)) ||
+       (mp_unsigned_bin_size(&tkb) > (int)(KB_SIZE - 2))  ) {
+      err = BUFFER_E; goto done;
+   }
+
+   /* store k */
+#ifdef WOLFSSL_SMALL_STACK
+   kb[0] = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER);
+   if (kb[0] == NULL) {
+      err = MEMORY_E; goto done;
+   }
+#endif
+
+   XMEMSET(kb[0], 0, KB_SIZE);
+   if ((err = mp_to_unsigned_bin(&tka, kb[0])) != MP_OKAY) {
+      goto done;
+   }
+
+   /* let's reverse kb so it's little endian */
+   x = 0;
+   y = mp_unsigned_bin_size(&tka);
+   if (y > 0) {
+       y -= 1;
+   }
+   mp_clear(&tka);
+   while ((unsigned)x < y) {
+      z = kb[0][x]; kb[0][x] = kb[0][y]; kb[0][y] = (byte)z;
+      ++x; --y;
+   }
+
+   /* store b */
+#ifdef WOLFSSL_SMALL_STACK
+   kb[1] = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER);
+   if (kb[1] == NULL) {
+      err = MEMORY_E; goto done;
+   }
+#endif
+
+   XMEMSET(kb[1], 0, KB_SIZE);
+   if ((err = mp_to_unsigned_bin(&tkb, kb[1])) == MP_OKAY) {
+      x = 0;
+      y = mp_unsigned_bin_size(&tkb);
+      if (y > 0) {
+          y -= 1;
+      }
+
+      while ((unsigned)x < y) {
+         z = kb[1][x]; kb[1][x] = kb[1][y]; kb[1][y] = (byte)z;
+         ++x; --y;
+      }
+
+      /* at this point we can start, yipee */
+      first = 1;
+      for (x = lut_gap-1; x >= 0; x--) {
+          /* extract FP_LUT bits from kb spread out by lut_gap bits and
+             offset by x bits from the start */
+          bitpos = x;
+          for (y = zA = zB = 0; y < FP_LUT; y++) {
+             zA |= ((kb[0][bitpos>>3] >> (bitpos&7)) & 1) << y;
+             zB |= ((kb[1][bitpos>>3] >> (bitpos&7)) & 1) << y;
+             bitpos += lut_gap;    /* it's y*lut_gap + x, but here we can avoid
+                                      the mult in each loop */
+          }
+
+          /* double if not first */
+          if (!first) {
+             if ((err = ecc_projective_dbl_point(R, R, a, modulus,
+                                                              mp)) != MP_OKAY) {
+                break;
+             }
+
+             /* add if not first, otherwise copy */
+             if (zA) {
+                if ((err = ecc_projective_add_point(R, fp_cache[idx1].LUT[zA],
+                                               R, a, modulus, mp)) != MP_OKAY) {
+                   break;
+                }
+                if (mp_iszero(R->z)) {
+                    /* When all zero then should have done an add */
+                    if (mp_iszero(R->x) && mp_iszero(R->y)) {
+                        if ((err = ecc_projective_dbl_point(
+                                                  fp_cache[idx1].LUT[zA], R,
+                                                  a, modulus, mp)) != MP_OKAY) {
+                            break;
+                        }
+                    }
+                    /* When only Z zero then result is infinity */
+                    else {
+                       err = mp_set(R->x, 0);
+                       if (err != MP_OKAY) {
+                          break;
+                       }
+                       err = mp_set(R->y, 0);
+                       if (err != MP_OKAY) {
+                          break;
+                       }
+                       err = mp_copy(&fp_cache[idx1].mu, R->z);
+                       if (err != MP_OKAY) {
+                          break;
+                       }
+                       first = 1;
+                    }
+                }
+             }
+
+             if (zB) {
+                if ((err = ecc_projective_add_point(R, fp_cache[idx2].LUT[zB],
+                                               R, a, modulus, mp)) != MP_OKAY) {
+                   break;
+                }
+                if (mp_iszero(R->z)) {
+                    /* When all zero then should have done an add */
+                    if (mp_iszero(R->x) && mp_iszero(R->y)) {
+                        if ((err = ecc_projective_dbl_point(
+                                                  fp_cache[idx2].LUT[zB], R,
+                                                  a, modulus, mp)) != MP_OKAY) {
+                            break;
+                        }
+                    }
+                    /* When only Z zero then result is infinity */
+                    else {
+                       err = mp_set(R->x, 0);
+                       if (err != MP_OKAY) {
+                          break;
+                       }
+                       err = mp_set(R->y, 0);
+                       if (err != MP_OKAY) {
+                          break;
+                       }
+                       err = mp_copy(&fp_cache[idx2].mu, R->z);
+                       if (err != MP_OKAY) {
+                          break;
+                       }
+                       first = 1;
+                    }
+                }
+             }
+          } else {
+             if (zA) {
+                 if ((mp_copy(fp_cache[idx1].LUT[zA]->x, R->x) != MP_OKAY) ||
+                     (mp_copy(fp_cache[idx1].LUT[zA]->y, R->y) != MP_OKAY) ||
+                     (mp_copy(&fp_cache[idx1].mu,        R->z) != MP_OKAY)) {
+                     err = GEN_MEM_ERR;
+                     break;
+                 }
+                    first = 0;
+             }
+             if (zB && first == 0) {
+                if (zB) {
+                   if ((err = ecc_projective_add_point(R,
+                        fp_cache[idx2].LUT[zB], R, a, modulus, mp)) != MP_OKAY){
+                      break;
+                   }
+                   if (mp_iszero(R->z)) {
+                       /* When all zero then should have done an add */
+                       if (mp_iszero(R->x) && mp_iszero(R->y)) {
+                           if ((err = ecc_projective_dbl_point(
+                                                  fp_cache[idx2].LUT[zB], R,
+                                                  a, modulus, mp)) != MP_OKAY) {
+                               break;
+                           }
+                       }
+                       /* When only Z zero then result is infinity */
+                       else {
+                          err = mp_set(R->x, 0);
+                          if (err != MP_OKAY) {
+                             break;
+                          }
+                          err = mp_set(R->y, 0);
+                          if (err != MP_OKAY) {
+                             break;
+                          }
+                          err = mp_copy(&fp_cache[idx2].mu, R->z);
+                          if (err != MP_OKAY) {
+                             break;
+                          }
+                          first = 1;
+                       }
+                   }
+                }
+             } else if (zB && first == 1) {
+                 if ((mp_copy(fp_cache[idx2].LUT[zB]->x, R->x) != MP_OKAY) ||
+                     (mp_copy(fp_cache[idx2].LUT[zB]->y, R->y) != MP_OKAY) ||
+                     (mp_copy(&fp_cache[idx2].mu,        R->z) != MP_OKAY)) {
+                     err = GEN_MEM_ERR;
+                     break;
+                 }
+                    first = 0;
+             }
+          }
+      }
+   }
+
+done:
+   /* cleanup */
+   mp_clear(&tkb);
+   mp_clear(&tka);
+   mp_clear(&order);
+
+#ifdef WOLFSSL_SMALL_STACK
+   if (kb[0])
+#endif
+      ForceZero(kb[0], KB_SIZE);
+#ifdef WOLFSSL_SMALL_STACK
+   if (kb[1])
+#endif
+      ForceZero(kb[1], KB_SIZE);
+
+#ifdef WOLFSSL_SMALL_STACK
+   XFREE(kb[0], NULL, DYNAMIC_TYPE_ECC_BUFFER);
+   XFREE(kb[1], NULL, DYNAMIC_TYPE_ECC_BUFFER);
+#endif
+
+#undef KB_SIZE
+
+    if (err != MP_OKAY)
+        return err;
+
+   return ecc_map(R, modulus, mp);
+}
+
+
+/** ECC Fixed Point mulmod global with heap hint used
+  Computes kA*A + kB*B = C using Shamir's Trick
+  A        First point to multiply
+  kA       What to multiple A by
+  B        Second point to multiply
+  kB       What to multiple B by
+  C        [out] Destination point (can overlap with A or B)
+  a        ECC curve parameter a
+  modulus  Modulus for curve
+  return MP_OKAY on success
+*/
+int ecc_mul2add(ecc_point* A, mp_int* kA,
+                ecc_point* B, mp_int* kB,
+                ecc_point* C, mp_int* a, mp_int* modulus, void* heap)
+{
+   int  idx1 = -1, idx2 = -1, err, mpInit = 0;
+   mp_digit mp;
+   mp_int   mu;
+
+   err = mp_init(&mu);
+   if (err != MP_OKAY)
+       return err;
+
+#ifndef HAVE_THREAD_LS
+   if (initMutex == 0) {
+        wc_InitMutex(&ecc_fp_lock);
+        initMutex = 1;
+   }
+   if (wc_LockMutex(&ecc_fp_lock) != 0)
+      return BAD_MUTEX_E;
+#endif /* HAVE_THREAD_LS */
+
+      /* find point */
+      idx1 = find_base(A);
+
+      /* no entry? */
+      if (idx1 == -1) {
+         /* find hole and add it */
+         if ((idx1 = find_hole()) >= 0) {
+            err = add_entry(idx1, A);
+         }
+      }
+      if (err == MP_OKAY && idx1 != -1) {
+         /* increment LRU */
+         ++(fp_cache[idx1].lru_count);
+      }
+
+      if (err == MP_OKAY) {
+        /* find point */
+        idx2 = find_base(B);
+
+        /* no entry? */
+        if (idx2 == -1) {
+           /* find hole and add it */
+           if ((idx2 = find_hole()) >= 0)
+              err = add_entry(idx2, B);
+         }
+      }
+
+      if (err == MP_OKAY && idx2 != -1) {
+         /* increment LRU */
+         ++(fp_cache[idx2].lru_count);
+      }
+
+      if (err == MP_OKAY) {
+        /* if it's 2 build the LUT, if it's higher just use the LUT */
+        if (idx1 >= 0 && fp_cache[idx1].lru_count == 2) {
+           /* compute mp */
+           err = mp_montgomery_setup(modulus, &mp);
+
+           if (err == MP_OKAY) {
+             mpInit = 1;
+             err = mp_montgomery_calc_normalization(&mu, modulus);
+           }
+
+           if (err == MP_OKAY)
+             /* build the LUT */
+               err = build_lut(idx1, a, modulus, mp, &mu);
+        }
+      }
+
+      if (err == MP_OKAY) {
+        /* if it's 2 build the LUT, if it's higher just use the LUT */
+        if (idx2 >= 0 && fp_cache[idx2].lru_count == 2) {
+           if (mpInit == 0) {
+                /* compute mp */
+                err = mp_montgomery_setup(modulus, &mp);
+                if (err == MP_OKAY) {
+                    mpInit = 1;
+                    err = mp_montgomery_calc_normalization(&mu, modulus);
+                }
+            }
+
+            if (err == MP_OKAY)
+            /* build the LUT */
+              err = build_lut(idx2, a, modulus, mp, &mu);
+        }
+      }
+
+
+      if (err == MP_OKAY) {
+        if (idx1 >=0 && idx2 >= 0 && fp_cache[idx1].lru_count >= 2 &&
+                                     fp_cache[idx2].lru_count >= 2) {
+           if (mpInit == 0) {
+              /* compute mp */
+              err = mp_montgomery_setup(modulus, &mp);
+           }
+           if (err == MP_OKAY)
+             err = accel_fp_mul2add(idx1, idx2, kA, kB, C, a, modulus, mp);
+        } else {
+           err = normal_ecc_mul2add(A, kA, B, kB, C, a, modulus, heap);
+        }
+    }
+
+#ifndef HAVE_THREAD_LS
+    wc_UnLockMutex(&ecc_fp_lock);
+#endif /* HAVE_THREAD_LS */
+    mp_clear(&mu);
+
+    return err;
+}
+#endif
+#endif /* ECC_SHAMIR */
+
+/** ECC Fixed Point mulmod global
+    k        The multiplicand
+    G        Base point to multiply
+    R        [out] Destination of product
+    a        ECC curve parameter a
+    modulus  The modulus for the curve
+    map      [boolean] If non-zero maps the point back to affine coordinates,
+             otherwise it's left in jacobian-montgomery form
+    return MP_OKAY if successful
+*/
+int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a,
+    mp_int* modulus, int map, void* heap)
+{
+#ifndef WOLFSSL_SP_MATH
+   int   idx, err = MP_OKAY;
+   mp_digit mp;
+   mp_int   mu;
+   int      mpSetup = 0;
+
+   if (k == NULL || G == NULL || R == NULL || a == NULL || modulus == NULL) {
+       return ECC_BAD_ARG_E;
+   }
+
+   if (mp_init(&mu) != MP_OKAY)
+       return MP_INIT_E;
+
+#ifndef HAVE_THREAD_LS
+   if (initMutex == 0) {
+        wc_InitMutex(&ecc_fp_lock);
+        initMutex = 1;
+   }
+
+   if (wc_LockMutex(&ecc_fp_lock) != 0)
+      return BAD_MUTEX_E;
+#endif /* HAVE_THREAD_LS */
+
+      /* find point */
+      idx = find_base(G);
+
+      /* no entry? */
+      if (idx == -1) {
+         /* find hole and add it */
+         idx = find_hole();
+
+         if (idx >= 0)
+            err = add_entry(idx, G);
+      }
+      if (err == MP_OKAY && idx >= 0) {
+         /* increment LRU */
+         ++(fp_cache[idx].lru_count);
+      }
+
+
+      if (err == MP_OKAY) {
+        /* if it's 2 build the LUT, if it's higher just use the LUT */
+        if (idx >= 0 && fp_cache[idx].lru_count == 2) {
+           /* compute mp */
+           err = mp_montgomery_setup(modulus, &mp);
+
+           if (err == MP_OKAY) {
+             /* compute mu */
+             mpSetup = 1;
+             err = mp_montgomery_calc_normalization(&mu, modulus);
+           }
+
+           if (err == MP_OKAY)
+             /* build the LUT */
+             err = build_lut(idx, a, modulus, mp, &mu);
+        }
+      }
+
+      if (err == MP_OKAY) {
+        if (idx >= 0 && fp_cache[idx].lru_count >= 2) {
+           if (mpSetup == 0) {
+              /* compute mp */
+              err = mp_montgomery_setup(modulus, &mp);
+           }
+           if (err == MP_OKAY)
+             err = accel_fp_mul(idx, k, R, a, modulus, mp, map);
+        } else {
+           err = normal_ecc_mulmod(k, G, R, a, modulus, map, heap);
+        }
+     }
+
+#ifndef HAVE_THREAD_LS
+    wc_UnLockMutex(&ecc_fp_lock);
+#endif /* HAVE_THREAD_LS */
+    mp_clear(&mu);
+
+    return err;
+#else
+    if (k == NULL || G == NULL || R == NULL || a == NULL || modulus == NULL) {
+        return ECC_BAD_ARG_E;
+    }
+
+#ifndef WOLFSSL_SP_NO_256
+    if (mp_count_bits(modulus) == 256) {
+        return sp_ecc_mulmod_256(k, G, R, map, heap);
+    }
+#endif
+#ifdef WOLFSSL_SP_384
+    if (mp_count_bits(modulus) == 384) {
+        return sp_ecc_mulmod_384(k, G, R, map, heap);
+    }
+#endif
+    return WC_KEY_SIZE_E;
+#endif
+}
+
+#ifndef WOLFSSL_SP_MATH
+/* helper function for freeing the cache ...
+   must be called with the cache mutex locked */
+static void wc_ecc_fp_free_cache(void)
+{
+   unsigned x, y;
+   for (x = 0; x < FP_ENTRIES; x++) {
+      if (fp_cache[x].g != NULL) {
+         for (y = 0; y < (1U<<FP_LUT); y++) {
+            wc_ecc_del_point(fp_cache[x].LUT[y]);
+            fp_cache[x].LUT[y] = NULL;
+         }
+         wc_ecc_del_point(fp_cache[x].g);
+         fp_cache[x].g         = NULL;
+         mp_clear(&fp_cache[x].mu);
+         fp_cache[x].lru_count = 0;
+         fp_cache[x].lock = 0;
+      }
+   }
+}
+#endif
+
+/** Free the Fixed Point cache */
+void wc_ecc_fp_free(void)
+{
+#ifndef WOLFSSL_SP_MATH
+#ifndef HAVE_THREAD_LS
+   if (initMutex == 0) {
+        wc_InitMutex(&ecc_fp_lock);
+        initMutex = 1;
+   }
+
+   if (wc_LockMutex(&ecc_fp_lock) == 0) {
+#endif /* HAVE_THREAD_LS */
+
+       wc_ecc_fp_free_cache();
+
+#ifndef HAVE_THREAD_LS
+       wc_UnLockMutex(&ecc_fp_lock);
+       wc_FreeMutex(&ecc_fp_lock);
+       initMutex = 0;
+   }
+#endif /* HAVE_THREAD_LS */
+#endif
+}
+
+
+#endif /* FP_ECC */
+
+#ifdef HAVE_ECC_ENCRYPT
+
+
+enum ecCliState {
+    ecCLI_INIT      = 1,
+    ecCLI_SALT_GET  = 2,
+    ecCLI_SALT_SET  = 3,
+    ecCLI_SENT_REQ  = 4,
+    ecCLI_RECV_RESP = 5,
+    ecCLI_BAD_STATE = 99
+};
+
+enum ecSrvState {
+    ecSRV_INIT      = 1,
+    ecSRV_SALT_GET  = 2,
+    ecSRV_SALT_SET  = 3,
+    ecSRV_RECV_REQ  = 4,
+    ecSRV_SENT_RESP = 5,
+    ecSRV_BAD_STATE = 99
+};
+
+
+struct ecEncCtx {
+    const byte* kdfSalt;   /* optional salt for kdf */
+    const byte* kdfInfo;   /* optional info for kdf */
+    const byte* macSalt;   /* optional salt for mac */
+    word32    kdfSaltSz;   /* size of kdfSalt */
+    word32    kdfInfoSz;   /* size of kdfInfo */
+    word32    macSaltSz;   /* size of macSalt */
+    void*     heap;        /* heap hint for memory used */
+    byte      clientSalt[EXCHANGE_SALT_SZ];  /* for msg exchange */
+    byte      serverSalt[EXCHANGE_SALT_SZ];  /* for msg exchange */
+    byte      encAlgo;     /* which encryption type */
+    byte      kdfAlgo;     /* which key derivation function type */
+    byte      macAlgo;     /* which mac function type */
+    byte      protocol;    /* are we REQ_RESP client or server ? */
+    byte      cliSt;       /* protocol state, for sanity checks */
+    byte      srvSt;       /* protocol state, for sanity checks */
+};
+
+
+const byte* wc_ecc_ctx_get_own_salt(ecEncCtx* ctx)
+{
+    if (ctx == NULL || ctx->protocol == 0)
+        return NULL;
+
+    if (ctx->protocol == REQ_RESP_CLIENT) {
+        if (ctx->cliSt == ecCLI_INIT) {
+            ctx->cliSt =  ecCLI_SALT_GET;
+            return ctx->clientSalt;
+        }
+        else {
+            ctx->cliSt = ecCLI_BAD_STATE;
+            return NULL;
+        }
+    }
+    else if (ctx->protocol == REQ_RESP_SERVER) {
+        if (ctx->srvSt == ecSRV_INIT) {
+            ctx->srvSt =  ecSRV_SALT_GET;
+            return ctx->serverSalt;
+        }
+        else {
+            ctx->srvSt = ecSRV_BAD_STATE;
+            return NULL;
+        }
+    }
+
+    return NULL;
+}
+
+
+/* optional set info, can be called before or after set_peer_salt */
+int wc_ecc_ctx_set_info(ecEncCtx* ctx, const byte* info, int sz)
+{
+    if (ctx == NULL || info == 0 || sz < 0)
+        return BAD_FUNC_ARG;
+
+    ctx->kdfInfo   = info;
+    ctx->kdfInfoSz = sz;
+
+    return 0;
+}
+
+
+static const char* exchange_info = "Secure Message Exchange";
+
+int wc_ecc_ctx_set_peer_salt(ecEncCtx* ctx, const byte* salt)
+{
+    byte tmp[EXCHANGE_SALT_SZ/2];
+    int  halfSz = EXCHANGE_SALT_SZ/2;
+
+    if (ctx == NULL || ctx->protocol == 0 || salt == NULL)
+        return BAD_FUNC_ARG;
+
+    if (ctx->protocol == REQ_RESP_CLIENT) {
+        XMEMCPY(ctx->serverSalt, salt, EXCHANGE_SALT_SZ);
+        if (ctx->cliSt == ecCLI_SALT_GET)
+            ctx->cliSt =  ecCLI_SALT_SET;
+        else {
+            ctx->cliSt =  ecCLI_BAD_STATE;
+            return BAD_STATE_E;
+        }
+    }
+    else {
+        XMEMCPY(ctx->clientSalt, salt, EXCHANGE_SALT_SZ);
+        if (ctx->srvSt == ecSRV_SALT_GET)
+            ctx->srvSt =  ecSRV_SALT_SET;
+        else {
+            ctx->srvSt =  ecSRV_BAD_STATE;
+            return BAD_STATE_E;
+        }
+    }
+
+    /* mix half and half */
+    /* tmp stores 2nd half of client before overwrite */
+    XMEMCPY(tmp, ctx->clientSalt + halfSz, halfSz);
+    XMEMCPY(ctx->clientSalt + halfSz, ctx->serverSalt, halfSz);
+    XMEMCPY(ctx->serverSalt, tmp, halfSz);
+
+    ctx->kdfSalt   = ctx->clientSalt;
+    ctx->kdfSaltSz = EXCHANGE_SALT_SZ;
+
+    ctx->macSalt   = ctx->serverSalt;
+    ctx->macSaltSz = EXCHANGE_SALT_SZ;
+
+    if (ctx->kdfInfo == NULL) {
+        /* default info */
+        ctx->kdfInfo   = (const byte*)exchange_info;
+        ctx->kdfInfoSz = EXCHANGE_INFO_SZ;
+    }
+
+    return 0;
+}
+
+
+static int ecc_ctx_set_salt(ecEncCtx* ctx, int flags, WC_RNG* rng)
+{
+    byte* saltBuffer = NULL;
+
+    if (ctx == NULL || rng == NULL || flags == 0)
+        return BAD_FUNC_ARG;
+
+    saltBuffer = (flags == REQ_RESP_CLIENT) ? ctx->clientSalt : ctx->serverSalt;
+
+    return wc_RNG_GenerateBlock(rng, saltBuffer, EXCHANGE_SALT_SZ);
+}
+
+
+static void ecc_ctx_init(ecEncCtx* ctx, int flags)
+{
+    if (ctx) {
+        XMEMSET(ctx, 0, sizeof(ecEncCtx));
+
+        ctx->encAlgo  = ecAES_128_CBC;
+        ctx->kdfAlgo  = ecHKDF_SHA256;
+        ctx->macAlgo  = ecHMAC_SHA256;
+        ctx->protocol = (byte)flags;
+
+        if (flags == REQ_RESP_CLIENT)
+            ctx->cliSt = ecCLI_INIT;
+        if (flags == REQ_RESP_SERVER)
+            ctx->srvSt = ecSRV_INIT;
+    }
+}
+
+
+/* allow ecc context reset so user doesn't have to init/free for reuse */
+int wc_ecc_ctx_reset(ecEncCtx* ctx, WC_RNG* rng)
+{
+    if (ctx == NULL || rng == NULL)
+        return BAD_FUNC_ARG;
+
+    ecc_ctx_init(ctx, ctx->protocol);
+    return ecc_ctx_set_salt(ctx, ctx->protocol, rng);
+}
+
+
+ecEncCtx* wc_ecc_ctx_new_ex(int flags, WC_RNG* rng, void* heap)
+{
+    int       ret = 0;
+    ecEncCtx* ctx = (ecEncCtx*)XMALLOC(sizeof(ecEncCtx), heap,
+                                                              DYNAMIC_TYPE_ECC);
+
+    if (ctx) {
+        ctx->protocol = (byte)flags;
+        ctx->heap     = heap;
+    }
+
+    ret = wc_ecc_ctx_reset(ctx, rng);
+    if (ret != 0) {
+        wc_ecc_ctx_free(ctx);
+        ctx = NULL;
+    }
+
+    return ctx;
+}
+
+
+/* alloc/init and set defaults, return new Context  */
+ecEncCtx* wc_ecc_ctx_new(int flags, WC_RNG* rng)
+{
+    return wc_ecc_ctx_new_ex(flags, rng, NULL);
+}
+
+
+/* free any resources, clear any keys */
+void wc_ecc_ctx_free(ecEncCtx* ctx)
+{
+    if (ctx) {
+        ForceZero(ctx, sizeof(ecEncCtx));
+        XFREE(ctx, ctx->heap, DYNAMIC_TYPE_ECC);
+    }
+}
+
+
+static int ecc_get_key_sizes(ecEncCtx* ctx, int* encKeySz, int* ivSz,
+                             int* keysLen, word32* digestSz, word32* blockSz)
+{
+    if (ctx) {
+        switch (ctx->encAlgo) {
+            case ecAES_128_CBC:
+                *encKeySz = KEY_SIZE_128;
+                *ivSz     = IV_SIZE_128;
+                *blockSz  = AES_BLOCK_SIZE;
+                break;
+            default:
+                return BAD_FUNC_ARG;
+        }
+
+        switch (ctx->macAlgo) {
+            case ecHMAC_SHA256:
+                *digestSz = WC_SHA256_DIGEST_SIZE;
+                break;
+            default:
+                return BAD_FUNC_ARG;
+        }
+    } else
+        return BAD_FUNC_ARG;
+
+    *keysLen  = *encKeySz + *ivSz + *digestSz;
+
+    return 0;
+}
+
+
+/* ecc encrypt with shared secret run through kdf
+   ctx holds non default algos and inputs
+   msgSz should be the right size for encAlgo, i.e., already padded
+   return 0 on success */
+int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
+                word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx)
+{
+    int          ret = 0;
+    word32       blockSz;
+    word32       digestSz;
+    ecEncCtx     localCtx;
+#ifdef WOLFSSL_SMALL_STACK
+    byte*        sharedSecret;
+    byte*        keys;
+#else
+    byte         sharedSecret[ECC_MAXSIZE];  /* 521 max size */
+    byte         keys[ECC_BUFSIZE];         /* max size */
+#endif
+    word32       sharedSz = ECC_MAXSIZE;
+    int          keysLen;
+    int          encKeySz;
+    int          ivSz;
+    int          offset = 0;         /* keys offset if doing msg exchange */
+    byte*        encKey;
+    byte*        encIv;
+    byte*        macKey;
+
+    if (privKey == NULL || pubKey == NULL || msg == NULL || out == NULL ||
+                           outSz  == NULL)
+        return BAD_FUNC_ARG;
+
+    if (ctx == NULL) {  /* use defaults */
+        ecc_ctx_init(&localCtx, 0);
+        ctx = &localCtx;
+    }
+
+    ret = ecc_get_key_sizes(ctx, &encKeySz, &ivSz, &keysLen, &digestSz,
+                            &blockSz);
+    if (ret != 0)
+        return ret;
+
+    if (ctx->protocol == REQ_RESP_SERVER) {
+        offset = keysLen;
+        keysLen *= 2;
+
+        if (ctx->srvSt != ecSRV_RECV_REQ)
+            return BAD_STATE_E;
+
+        ctx->srvSt = ecSRV_BAD_STATE; /* we're done no more ops allowed */
+    }
+    else if (ctx->protocol == REQ_RESP_CLIENT) {
+        if (ctx->cliSt != ecCLI_SALT_SET)
+            return BAD_STATE_E;
+
+        ctx->cliSt = ecCLI_SENT_REQ; /* only do this once */
+    }
+
+    if (keysLen > ECC_BUFSIZE) /* keys size */
+        return BUFFER_E;
+
+    if ( (msgSz%blockSz) != 0)
+        return BAD_PADDING_E;
+
+    if (*outSz < (msgSz + digestSz))
+        return BUFFER_E;
+
+#ifdef WOLFSSL_SMALL_STACK
+    sharedSecret = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER);
+    if (sharedSecret == NULL)
+        return MEMORY_E;
+
+    keys = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER);
+    if (keys == NULL) {
+        XFREE(sharedSecret, NULL, DYNAMIC_TYPE_ECC_BUFFER);
+        return MEMORY_E;
+    }
+#endif
+
+    do {
+    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
+        ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+        if (ret != 0)
+            break;
+    #endif
+        ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz);
+    } while (ret == WC_PENDING_E);
+    if (ret == 0) {
+       switch (ctx->kdfAlgo) {
+           case ecHKDF_SHA256 :
+               ret = wc_HKDF(WC_SHA256, sharedSecret, sharedSz, ctx->kdfSalt,
+                          ctx->kdfSaltSz, ctx->kdfInfo, ctx->kdfInfoSz,
+                          keys, keysLen);
+               break;
+
+           default:
+               ret = BAD_FUNC_ARG;
+               break;
+       }
+    }
+
+    if (ret == 0) {
+       encKey = keys + offset;
+       encIv  = encKey + encKeySz;
+       macKey = encKey + encKeySz + ivSz;
+
+       switch (ctx->encAlgo) {
+           case ecAES_128_CBC:
+               {
+                   Aes aes;
+                   ret = wc_AesInit(&aes, NULL, INVALID_DEVID);
+                   if (ret == 0) {
+                       ret = wc_AesSetKey(&aes, encKey, KEY_SIZE_128, encIv,
+                                                                AES_ENCRYPTION);
+                       if (ret == 0) {
+                           ret = wc_AesCbcEncrypt(&aes, out, msg, msgSz);
+                       #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES)
+                           ret = wc_AsyncWait(ret, &aes.asyncDev,
+                                              WC_ASYNC_FLAG_NONE);
+                       #endif
+                       }
+                       wc_AesFree(&aes);
+                   }
+                   if (ret != 0)
+                      break;
+               }
+               break;
+
+           default:
+               ret = BAD_FUNC_ARG;
+               break;
+       }
+    }
+
+    if (ret == 0) {
+       switch (ctx->macAlgo) {
+           case ecHMAC_SHA256:
+               {
+                   Hmac hmac;
+                   ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID);
+                   if (ret == 0) {
+                       ret = wc_HmacSetKey(&hmac, WC_SHA256, macKey, WC_SHA256_DIGEST_SIZE);
+                       if (ret == 0)
+                           ret = wc_HmacUpdate(&hmac, out, msgSz);
+                       if (ret == 0)
+                           ret = wc_HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz);
+                       if (ret == 0)
+                           ret = wc_HmacFinal(&hmac, out+msgSz);
+                       wc_HmacFree(&hmac);
+                   }
+               }
+               break;
+
+           default:
+               ret = BAD_FUNC_ARG;
+               break;
+       }
+    }
+
+    if (ret == 0)
+       *outSz = msgSz + digestSz;
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(sharedSecret, NULL, DYNAMIC_TYPE_ECC_BUFFER);
+    XFREE(keys, NULL, DYNAMIC_TYPE_ECC_BUFFER);
+#endif
+
+    return ret;
+}
+
+
+/* ecc decrypt with shared secret run through kdf
+   ctx holds non default algos and inputs
+   return 0 on success */
+int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
+                word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx)
+{
+    int          ret = 0;
+    word32       blockSz;
+    word32       digestSz;
+    ecEncCtx     localCtx;
+#ifdef WOLFSSL_SMALL_STACK
+    byte*        sharedSecret;
+    byte*        keys;
+#else
+    byte         sharedSecret[ECC_MAXSIZE];  /* 521 max size */
+    byte         keys[ECC_BUFSIZE];         /* max size */
+#endif
+    word32       sharedSz = ECC_MAXSIZE;
+    int          keysLen;
+    int          encKeySz;
+    int          ivSz;
+    int          offset = 0;       /* in case using msg exchange */
+    byte*        encKey;
+    byte*        encIv;
+    byte*        macKey;
+
+    if (privKey == NULL || pubKey == NULL || msg == NULL || out == NULL ||
+                           outSz  == NULL)
+        return BAD_FUNC_ARG;
+
+    if (ctx == NULL) {  /* use defaults */
+        ecc_ctx_init(&localCtx, 0);
+        ctx = &localCtx;
+    }
+
+    ret = ecc_get_key_sizes(ctx, &encKeySz, &ivSz, &keysLen, &digestSz,
+                            &blockSz);
+    if (ret != 0)
+        return ret;
+
+    if (ctx->protocol == REQ_RESP_CLIENT) {
+        offset = keysLen;
+        keysLen *= 2;
+
+        if (ctx->cliSt != ecCLI_SENT_REQ)
+            return BAD_STATE_E;
+
+        ctx->cliSt = ecSRV_BAD_STATE; /* we're done no more ops allowed */
+    }
+    else if (ctx->protocol == REQ_RESP_SERVER) {
+        if (ctx->srvSt != ecSRV_SALT_SET)
+            return BAD_STATE_E;
+
+        ctx->srvSt = ecSRV_RECV_REQ; /* only do this once */
+    }
+
+    if (keysLen > ECC_BUFSIZE) /* keys size */
+        return BUFFER_E;
+
+    if ( ((msgSz-digestSz) % blockSz) != 0)
+        return BAD_PADDING_E;
+
+    if (*outSz < (msgSz - digestSz))
+        return BUFFER_E;
+
+#ifdef WOLFSSL_SMALL_STACK
+    sharedSecret = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER);
+    if (sharedSecret == NULL)
+        return MEMORY_E;
+
+    keys = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER);
+    if (keys == NULL) {
+        XFREE(sharedSecret, NULL, DYNAMIC_TYPE_ECC_BUFFER);
+        return MEMORY_E;
+    }
+#endif
+
+    do {
+    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
+        ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+        if (ret != 0)
+            break;
+    #endif
+        ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz);
+    } while (ret == WC_PENDING_E);
+    if (ret == 0) {
+       switch (ctx->kdfAlgo) {
+           case ecHKDF_SHA256 :
+               ret = wc_HKDF(WC_SHA256, sharedSecret, sharedSz, ctx->kdfSalt,
+                          ctx->kdfSaltSz, ctx->kdfInfo, ctx->kdfInfoSz,
+                          keys, keysLen);
+               break;
+
+           default:
+               ret = BAD_FUNC_ARG;
+               break;
+       }
+    }
+
+    if (ret == 0) {
+       encKey = keys + offset;
+       encIv  = encKey + encKeySz;
+       macKey = encKey + encKeySz + ivSz;
+
+       switch (ctx->macAlgo) {
+           case ecHMAC_SHA256:
+           {
+               byte verify[WC_SHA256_DIGEST_SIZE];
+               Hmac hmac;
+
+               ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID);
+               if (ret == 0) {
+                   ret = wc_HmacSetKey(&hmac, WC_SHA256, macKey, WC_SHA256_DIGEST_SIZE);
+                   if (ret == 0)
+                       ret = wc_HmacUpdate(&hmac, msg, msgSz-digestSz);
+                   if (ret == 0)
+                       ret = wc_HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz);
+                   if (ret == 0)
+                       ret = wc_HmacFinal(&hmac, verify);
+                   if (ret == 0) {
+                      if (XMEMCMP(verify, msg + msgSz - digestSz, digestSz) != 0)
+                          ret = -1;
+                   }
+
+                   wc_HmacFree(&hmac);
+               }
+               break;
+           }
+
+           default:
+               ret = BAD_FUNC_ARG;
+               break;
+       }
+    }
+
+    if (ret == 0) {
+       switch (ctx->encAlgo) {
+    #ifdef HAVE_AES_CBC
+           case ecAES_128_CBC:
+               {
+                   Aes aes;
+                   ret = wc_AesSetKey(&aes, encKey, KEY_SIZE_128, encIv,
+                                                                AES_DECRYPTION);
+                   if (ret != 0)
+                       break;
+                   ret = wc_AesCbcDecrypt(&aes, out, msg, msgSz-digestSz);
+                #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES)
+                   ret = wc_AsyncWait(ret, &aes.asyncDev, WC_ASYNC_FLAG_NONE);
+                #endif
+               }
+               break;
+    #endif
+           default:
+               ret = BAD_FUNC_ARG;
+               break;
+       }
+    }
+
+    if (ret == 0)
+       *outSz = msgSz - digestSz;
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(sharedSecret, NULL, DYNAMIC_TYPE_ECC_BUFFER);
+    XFREE(keys, NULL, DYNAMIC_TYPE_ECC_BUFFER);
+#endif
+
+    return ret;
+}
+
+
+#endif /* HAVE_ECC_ENCRYPT */
+
+
+#ifdef HAVE_COMP_KEY
+#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL)
+
+#ifndef WOLFSSL_SP_MATH
+int do_mp_jacobi(mp_int* a, mp_int* n, int* c);
+
+int do_mp_jacobi(mp_int* a, mp_int* n, int* c)
+{
+  int      k, s, res;
+  int      r = 0; /* initialize to help static analysis out */
+  mp_digit residue;
+
+  /* if a < 0 return MP_VAL */
+  if (mp_isneg(a) == MP_YES) {
+     return MP_VAL;
+  }
+
+  /* if n <= 0 return MP_VAL */
+  if (mp_cmp_d(n, 0) != MP_GT) {
+     return MP_VAL;
+  }
+
+  /* step 1. handle case of a == 0 */
+  if (mp_iszero (a) == MP_YES) {
+     /* special case of a == 0 and n == 1 */
+     if (mp_cmp_d (n, 1) == MP_EQ) {
+       *c = 1;
+     } else {
+       *c = 0;
+     }
+     return MP_OKAY;
+  }
+
+  /* step 2.  if a == 1, return 1 */
+  if (mp_cmp_d (a, 1) == MP_EQ) {
+    *c = 1;
+    return MP_OKAY;
+  }
+
+  /* default */
+  s = 0;
+
+  /* divide out larger power of two */
+  k = mp_cnt_lsb(a);
+  res = mp_div_2d(a, k, a, NULL);
+
+  if (res == MP_OKAY) {
+    /* step 4.  if e is even set s=1 */
+    if ((k & 1) == 0) {
+      s = 1;
+    } else {
+      /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */
+      residue = n->dp[0] & 7;
+
+      if (residue == 1 || residue == 7) {
+        s = 1;
+      } else if (residue == 3 || residue == 5) {
+        s = -1;
+      }
+    }
+
+    /* step 5.  if p == 3 (mod 4) *and* a == 3 (mod 4) then s = -s */
+    if ( ((n->dp[0] & 3) == 3) && ((a->dp[0] & 3) == 3)) {
+      s = -s;
+    }
+  }
+
+  if (res == MP_OKAY) {
+    /* if a == 1 we're done */
+    if (mp_cmp_d(a, 1) == MP_EQ) {
+      *c = s;
+    } else {
+      /* n1 = n mod a */
+      res = mp_mod (n, a, n);
+      if (res == MP_OKAY)
+        res = do_mp_jacobi(n, a, &r);
+
+      if (res == MP_OKAY)
+        *c = s * r;
+    }
+  }
+
+  return res;
+}
+
+
+/* computes the jacobi c = (a | n) (or Legendre if n is prime)
+ * HAC pp. 73 Algorithm 2.149
+ * HAC is wrong here, as the special case of (0 | 1) is not
+ * handled correctly.
+ */
+int mp_jacobi(mp_int* a, mp_int* n, int* c)
+{
+    mp_int   a1, n1;
+    int      res;
+
+    /* step 3.  write a = a1 * 2**k  */
+    if ((res = mp_init_multi(&a1, &n1, NULL, NULL, NULL, NULL)) != MP_OKAY) {
+        return res;
+    }
+
+    if ((res = mp_copy(a, &a1)) != MP_OKAY) {
+        goto done;
+    }
+
+    if ((res = mp_copy(n, &n1)) != MP_OKAY) {
+        goto done;
+    }
+
+    res = do_mp_jacobi(&a1, &n1, c);
+
+done:
+  /* cleanup */
+  mp_clear(&n1);
+  mp_clear(&a1);
+
+  return res;
+}
+
+
+/* Solves the modular equation x^2 = n (mod p)
+ * where prime number is greater than 2 (odd prime).
+ * The result is returned in the third argument x
+ * the function returns MP_OKAY on success, MP_VAL or another error on failure
+ */
+int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret)
+{
+#ifdef SQRTMOD_USE_MOD_EXP
+  int res;
+
+  mp_int e;
+
+  res = mp_init(&e);
+  if (res == MP_OKAY)
+      res = mp_add_d(prime, 1, &e);
+  if (res == MP_OKAY)
+      res = mp_div_2d(&e, 2, &e, NULL);
+  if (res == MP_OKAY)
+      res = mp_exptmod(n, &e, prime, ret);
+
+  mp_clear(&e);
+
+  return res;
+#else
+  int res, legendre, done = 0;
+  mp_int t1, C, Q, S, Z, M, T, R, two;
+  mp_digit i;
+
+  /* first handle the simple cases n = 0 or n = 1 */
+  if (mp_cmp_d(n, 0) == MP_EQ) {
+    mp_zero(ret);
+    return MP_OKAY;
+  }
+  if (mp_cmp_d(n, 1) == MP_EQ) {
+    return mp_set(ret, 1);
+  }
+
+  /* prime must be odd */
+  if (mp_cmp_d(prime, 2) == MP_EQ) {
+    return MP_VAL;
+  }
+
+  /* is quadratic non-residue mod prime */
+  if ((res = mp_jacobi(n, prime, &legendre)) != MP_OKAY) {
+    return res;
+  }
+  if (legendre == -1) {
+    return MP_VAL;
+  }
+
+  if ((res = mp_init_multi(&t1, &C, &Q, &S, &Z, &M)) != MP_OKAY)
+    return res;
+
+  if ((res = mp_init_multi(&T, &R, &two, NULL, NULL, NULL))
+                          != MP_OKAY) {
+    mp_clear(&t1); mp_clear(&C); mp_clear(&Q); mp_clear(&S); mp_clear(&Z);
+    mp_clear(&M);
+    return res;
+  }
+
+  /* SPECIAL CASE: if prime mod 4 == 3
+   * compute directly: res = n^(prime+1)/4 mod prime
+   * Handbook of Applied Cryptography algorithm 3.36
+   */
+  res = mp_mod_d(prime, 4, &i);
+  if (res == MP_OKAY && i == 3) {
+    res = mp_add_d(prime, 1, &t1);
+
+    if (res == MP_OKAY)
+      res = mp_div_2(&t1, &t1);
+    if (res == MP_OKAY)
+      res = mp_div_2(&t1, &t1);
+    if (res == MP_OKAY)
+      res = mp_exptmod(n, &t1, prime, ret);
+
+    done = 1;
+  }
+
+  /* NOW: TonelliShanks algorithm */
+  if (res == MP_OKAY && done == 0) {
+
+    /* factor out powers of 2 from prime-1, defining Q and S
+    *                                      as: prime-1 = Q*2^S */
+    /* Q = prime - 1 */
+    res = mp_copy(prime, &Q);
+    if (res == MP_OKAY)
+      res = mp_sub_d(&Q, 1, &Q);
+
+    /* S = 0 */
+    if (res == MP_OKAY)
+      mp_zero(&S);
+
+    while (res == MP_OKAY && mp_iseven(&Q) == MP_YES) {
+      /* Q = Q / 2 */
+      res = mp_div_2(&Q, &Q);
+
+      /* S = S + 1 */
+      if (res == MP_OKAY)
+        res = mp_add_d(&S, 1, &S);
+    }
+
+    /* find a Z such that the Legendre symbol (Z|prime) == -1 */
+    /* Z = 2 */
+    if (res == MP_OKAY)
+      res = mp_set_int(&Z, 2);
+
+    while (res == MP_OKAY) {
+      res = mp_jacobi(&Z, prime, &legendre);
+      if (res == MP_OKAY && legendre == -1)
+        break;
+
+      /* Z = Z + 1 */
+      if (res == MP_OKAY)
+        res = mp_add_d(&Z, 1, &Z);
+    }
+
+    /* C = Z ^ Q mod prime */
+    if (res == MP_OKAY)
+      res = mp_exptmod(&Z, &Q, prime, &C);
+
+    /* t1 = (Q + 1) / 2 */
+    if (res == MP_OKAY)
+      res = mp_add_d(&Q, 1, &t1);
+    if (res == MP_OKAY)
+      res = mp_div_2(&t1, &t1);
+
+    /* R = n ^ ((Q + 1) / 2) mod prime */
+    if (res == MP_OKAY)
+      res = mp_exptmod(n, &t1, prime, &R);
+
+    /* T = n ^ Q mod prime */
+    if (res == MP_OKAY)
+      res = mp_exptmod(n, &Q, prime, &T);
+
+    /* M = S */
+    if (res == MP_OKAY)
+      res = mp_copy(&S, &M);
+
+    if (res == MP_OKAY)
+      res = mp_set_int(&two, 2);
+
+    while (res == MP_OKAY && done == 0) {
+      res = mp_copy(&T, &t1);
+
+      /* reduce to 1 and count */
+      i = 0;
+      while (res == MP_OKAY) {
+        if (mp_cmp_d(&t1, 1) == MP_EQ)
+            break;
+        res = mp_exptmod(&t1, &two, prime, &t1);
+        if (res == MP_OKAY)
+          i++;
+      }
+      if (res == MP_OKAY && i == 0) {
+        res = mp_copy(&R, ret);
+        done = 1;
+      }
+
+      if (done == 0) {
+        /* t1 = 2 ^ (M - i - 1) */
+        if (res == MP_OKAY)
+          res = mp_sub_d(&M, i, &t1);
+        if (res == MP_OKAY)
+          res = mp_sub_d(&t1, 1, &t1);
+        if (res == MP_OKAY)
+          res = mp_exptmod(&two, &t1, prime, &t1);
+
+        /* t1 = C ^ (2 ^ (M - i - 1)) mod prime */
+        if (res == MP_OKAY)
+          res = mp_exptmod(&C, &t1, prime, &t1);
+
+        /* C = (t1 * t1) mod prime */
+        if (res == MP_OKAY)
+          res = mp_sqrmod(&t1, prime, &C);
+
+        /* R = (R * t1) mod prime */
+        if (res == MP_OKAY)
+          res = mp_mulmod(&R, &t1, prime, &R);
+
+        /* T = (T * C) mod prime */
+        if (res == MP_OKAY)
+          res = mp_mulmod(&T, &C, prime, &T);
+
+        /* M = i */
+        if (res == MP_OKAY)
+          res = mp_set(&M, i);
+      }
+    }
+  }
+
+  /* done */
+  mp_clear(&t1);
+  mp_clear(&C);
+  mp_clear(&Q);
+  mp_clear(&S);
+  mp_clear(&Z);
+  mp_clear(&M);
+  mp_clear(&T);
+  mp_clear(&R);
+  mp_clear(&two);
+
+  return res;
+#endif
+}
+#endif
+#endif /* !WOLFSSL_ATECC508A && !WOLFSSL_CRYPTOCELL */
+
+
+/* export public ECC key in ANSI X9.63 format compressed */
+static int wc_ecc_export_x963_compressed(ecc_key* key, byte* out, word32* outLen)
+{
+   word32 numlen;
+   int    ret = MP_OKAY;
+
+   if (key == NULL || out == NULL || outLen == NULL)
+       return BAD_FUNC_ARG;
+
+   if (wc_ecc_is_valid_idx(key->idx) == 0) {
+      return ECC_BAD_ARG_E;
+   }
+   numlen = key->dp->size;
+
+   if (*outLen < (1 + numlen)) {
+      *outLen = 1 + numlen;
+      return BUFFER_E;
+   }
+
+   /* store first byte */
+   out[0] = mp_isodd(key->pubkey.y) == MP_YES ? ECC_POINT_COMP_ODD : ECC_POINT_COMP_EVEN;
+
+   /* pad and store x */
+   XMEMSET(out+1, 0, numlen);
+   ret = mp_to_unsigned_bin(key->pubkey.x,
+                       out+1 + (numlen - mp_unsigned_bin_size(key->pubkey.x)));
+   *outLen = 1 + numlen;
+
+   return ret;
+}
+
+#endif /* HAVE_COMP_KEY */
+
+
+int wc_ecc_get_oid(word32 oidSum, const byte** oid, word32* oidSz)
+{
+    int x;
+
+    if (oidSum == 0) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* find matching OID sum (based on encoded value) */
+    for (x = 0; ecc_sets[x].size != 0; x++) {
+        if (ecc_sets[x].oidSum == oidSum) {
+            int ret;
+        #ifdef HAVE_OID_ENCODING
+            ret = 0;
+            /* check cache */
+            oid_cache_t* o = &ecc_oid_cache[x];
+            if (o->oidSz == 0) {
+                o->oidSz = sizeof(o->oid);
+                ret = EncodeObjectId(ecc_sets[x].oid, ecc_sets[x].oidSz,
+                                                            o->oid, &o->oidSz);
+            }
+            if (oidSz) {
+                *oidSz = o->oidSz;
+            }
+            if (oid) {
+                *oid = o->oid;
+            }
+            /* on success return curve id */
+            if (ret == 0) {
+                ret = ecc_sets[x].id;
+            }
+        #else
+            if (oidSz) {
+                *oidSz = ecc_sets[x].oidSz;
+            }
+            if (oid) {
+                *oid = ecc_sets[x].oid;
+            }
+            ret = ecc_sets[x].id;
+        #endif
+            return ret;
+        }
+    }
+
+    return NOT_COMPILED_IN;
+}
+
+#ifdef WOLFSSL_CUSTOM_CURVES
+int wc_ecc_set_custom_curve(ecc_key* key, const ecc_set_type* dp)
+{
+    if (key == NULL || dp == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    key->idx = ECC_CUSTOM_IDX;
+    key->dp = dp;
+
+    return 0;
+}
+#endif /* WOLFSSL_CUSTOM_CURVES */
+
+#ifdef HAVE_X963_KDF
+
+static WC_INLINE void IncrementX963KdfCounter(byte* inOutCtr)
+{
+    int i;
+
+    /* in network byte order so start at end and work back */
+    for (i = 3; i >= 0; i--) {
+        if (++inOutCtr[i])  /* we're done unless we overflow */
+            return;
+    }
+}
+
+/* ASN X9.63 Key Derivation Function (SEC1) */
+int wc_X963_KDF(enum wc_HashType type, const byte* secret, word32 secretSz,
+                const byte* sinfo, word32 sinfoSz, byte* out, word32 outSz)
+{
+    int ret, i;
+    int digestSz, copySz;
+    int remaining = outSz;
+    byte* outIdx;
+    byte  counter[4];
+    byte  tmp[WC_MAX_DIGEST_SIZE];
+
+#ifdef WOLFSSL_SMALL_STACK
+    wc_HashAlg* hash;
+#else
+    wc_HashAlg hash[1];
+#endif
+
+    if (secret == NULL || secretSz == 0 || out == NULL)
+        return BAD_FUNC_ARG;
+
+    /* X9.63 allowed algos only */
+    if (type != WC_HASH_TYPE_SHA    && type != WC_HASH_TYPE_SHA224 &&
+        type != WC_HASH_TYPE_SHA256 && type != WC_HASH_TYPE_SHA384 &&
+        type != WC_HASH_TYPE_SHA512)
+        return BAD_FUNC_ARG;
+
+    digestSz = wc_HashGetDigestSize(type);
+    if (digestSz < 0)
+        return digestSz;
+
+#ifdef WOLFSSL_SMALL_STACK
+    hash = (wc_HashAlg*)XMALLOC(sizeof(wc_HashAlg), NULL,
+                                DYNAMIC_TYPE_HASHES);
+    if (hash == NULL)
+        return MEMORY_E;
+#endif
+
+    ret = wc_HashInit(hash, type);
+    if (ret != 0) {
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(hash, NULL, DYNAMIC_TYPE_HASHES);
+#endif
+        return ret;
+    }
+
+    outIdx = out;
+    XMEMSET(counter, 0, sizeof(counter));
+
+    for (i = 1; remaining > 0; i++) {
+
+        IncrementX963KdfCounter(counter);
+
+        ret = wc_HashUpdate(hash, type, secret, secretSz);
+        if (ret != 0) {
+            break;
+        }
+
+        ret = wc_HashUpdate(hash, type, counter, sizeof(counter));
+        if (ret != 0) {
+            break;
+        }
+
+        if (sinfo) {
+            ret = wc_HashUpdate(hash, type, sinfo, sinfoSz);
+            if (ret != 0) {
+                break;
+            }
+        }
+
+        ret = wc_HashFinal(hash, type, tmp);
+        if (ret != 0) {
+            break;
+        }
+
+        copySz = min(remaining, digestSz);
+        XMEMCPY(outIdx, tmp, copySz);
+
+        remaining -= copySz;
+        outIdx += copySz;
+    }
+
+    wc_HashFree(hash, type);
+
+#ifdef WOLFSSL_SMALL_STACK
+     XFREE(hash, NULL, DYNAMIC_TYPE_HASHES);
+#endif
+
+    return ret;
+}
+#endif /* HAVE_X963_KDF */
+
+#endif /* HAVE_ECC */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/error.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/error.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/error.c	(revision 453)
@@ -0,0 +1,530 @@
+/* error.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#include <wolfssl/wolfcrypt/error-crypt.h>
+
+#ifdef _MSC_VER
+    /* 4996 warning to use MS extensions e.g., strcpy_s instead of XSTRNCPY */
+    #pragma warning(disable: 4996)
+#endif
+
+#ifndef NO_ERROR_STRINGS
+const char* wc_GetErrorString(int error)
+{
+    switch (error) {
+
+    case OPEN_RAN_E :
+        return "opening random device error";
+
+    case READ_RAN_E :
+        return "reading random device error";
+
+    case WINCRYPT_E :
+        return "windows crypt init error";
+
+    case CRYPTGEN_E :
+        return "windows crypt generation error";
+
+    case RAN_BLOCK_E :
+        return "random device read would block error";
+
+    case BAD_MUTEX_E :
+        return "Bad mutex, operation failed";
+
+    case WC_TIMEOUT_E:
+        return "Timeout error";
+
+    case WC_PENDING_E:
+        return "wolfCrypt Operation Pending (would block / eagain) error";
+
+    case WC_NOT_PENDING_E:
+        return "wolfCrypt operation not pending error";
+
+    case MP_INIT_E :
+        return "mp_init error state";
+
+    case MP_READ_E :
+        return "mp_read error state";
+
+    case MP_EXPTMOD_E :
+        return "mp_exptmod error state";
+
+    case MP_TO_E :
+        return "mp_to_xxx error state, can't convert";
+
+    case MP_SUB_E :
+        return "mp_sub error state, can't subtract";
+
+    case MP_ADD_E :
+        return "mp_add error state, can't add";
+
+    case MP_MUL_E :
+        return "mp_mul error state, can't multiply";
+
+    case MP_MULMOD_E :
+        return "mp_mulmod error state, can't multiply mod";
+
+    case MP_MOD_E :
+        return "mp_mod error state, can't mod";
+
+    case MP_INVMOD_E :
+        return "mp_invmod error state, can't inv mod";
+
+    case MP_CMP_E :
+        return "mp_cmp error state";
+
+    case MP_ZERO_E :
+        return "mp zero result, not expected";
+
+    case MEMORY_E :
+        return "out of memory error";
+
+    case VAR_STATE_CHANGE_E :
+        return "Variable state modified by different thread";
+
+    case RSA_WRONG_TYPE_E :
+        return "RSA wrong block type for RSA function";
+
+    case RSA_BUFFER_E :
+        return "RSA buffer error, output too small or input too big";
+
+    case BUFFER_E :
+        return "Buffer error, output too small or input too big";
+
+    case ALGO_ID_E :
+        return "Setting Cert AlgoID error";
+
+    case PUBLIC_KEY_E :
+        return "Setting Cert Public Key error";
+
+    case DATE_E :
+        return "Setting Cert Date validity error";
+
+    case SUBJECT_E :
+        return "Setting Cert Subject name error";
+
+    case ISSUER_E :
+        return "Setting Cert Issuer name error";
+
+    case CA_TRUE_E :
+        return "Setting basic constraint CA true error";
+
+    case EXTENSIONS_E :
+        return "Setting extensions error";
+
+    case ASN_PARSE_E :
+        return "ASN parsing error, invalid input";
+
+    case ASN_VERSION_E :
+        return "ASN version error, invalid number";
+
+    case ASN_GETINT_E :
+        return "ASN get big int error, invalid data";
+
+    case ASN_RSA_KEY_E :
+        return "ASN key init error, invalid input";
+
+    case ASN_OBJECT_ID_E :
+        return "ASN object id error, invalid id";
+
+    case ASN_TAG_NULL_E :
+        return "ASN tag error, not null";
+
+    case ASN_EXPECT_0_E :
+        return "ASN expect error, not zero";
+
+    case ASN_BITSTR_E :
+        return "ASN bit string error, wrong id";
+
+    case ASN_UNKNOWN_OID_E :
+        return "ASN oid error, unknown sum id";
+
+    case ASN_DATE_SZ_E :
+        return "ASN date error, bad size";
+
+    case ASN_BEFORE_DATE_E :
+        return "ASN date error, current date before";
+
+    case ASN_AFTER_DATE_E :
+        return "ASN date error, current date after";
+
+    case ASN_SIG_OID_E :
+        return "ASN signature error, mismatched oid";
+
+    case ASN_TIME_E :
+        return "ASN time error, unknown time type";
+
+    case ASN_INPUT_E :
+        return "ASN input error, not enough data";
+
+    case ASN_SIG_CONFIRM_E :
+        return "ASN sig error, confirm failure";
+
+    case ASN_SIG_HASH_E :
+        return "ASN sig error, unsupported hash type";
+
+    case ASN_SIG_KEY_E :
+        return "ASN sig error, unsupported key type";
+
+    case ASN_DH_KEY_E :
+        return "ASN key init error, invalid input";
+
+    case ASN_NTRU_KEY_E :
+        return "ASN NTRU key decode error, invalid input";
+
+    case ASN_CRIT_EXT_E:
+        return "X.509 Critical extension ignored or invalid";
+
+    case ASN_ALT_NAME_E:
+        return "ASN alternate name error";
+
+    case ECC_BAD_ARG_E :
+        return "ECC input argument wrong type, invalid input";
+
+    case ASN_ECC_KEY_E :
+        return "ECC ASN1 bad key data, invalid input";
+
+    case ECC_CURVE_OID_E :
+        return "ECC curve sum OID unsupported, invalid input";
+
+    case BAD_FUNC_ARG :
+        return "Bad function argument";
+
+    case NOT_COMPILED_IN :
+        return "Feature not compiled in";
+
+    case UNICODE_SIZE_E :
+        return "Unicode password too big";
+
+    case NO_PASSWORD :
+        return "No password provided by user";
+
+    case ALT_NAME_E :
+        return "Alt Name problem, too big";
+
+    case AES_GCM_AUTH_E:
+        return "AES-GCM Authentication check fail";
+
+    case AES_CCM_AUTH_E:
+        return "AES-CCM Authentication check fail";
+
+    case ASYNC_INIT_E:
+        return "Async Init error";
+
+    case COMPRESS_INIT_E:
+        return "Compress Init error";
+
+    case COMPRESS_E:
+        return "Compress error";
+
+    case DECOMPRESS_INIT_E:
+        return "DeCompress Init error";
+
+    case DECOMPRESS_E:
+        return "DeCompress error";
+
+    case BAD_ALIGN_E:
+        return "Bad alignment error, no alloc help";
+
+    case ASN_NO_SIGNER_E :
+        return "ASN no signer error to confirm failure";
+
+    case ASN_CRL_CONFIRM_E :
+        return "ASN CRL sig error, confirm failure";
+
+    case ASN_CRL_NO_SIGNER_E :
+        return "ASN CRL no signer error to confirm failure";
+
+    case ASN_OCSP_CONFIRM_E :
+        return "ASN OCSP sig error, confirm failure";
+
+    case ASN_NO_PEM_HEADER:
+        return "ASN no PEM Header Error";
+
+    case BAD_STATE_E:
+        return "Bad state operation";
+
+    case BAD_PADDING_E:
+        return "Bad padding, message wrong length";
+
+    case REQ_ATTRIBUTE_E:
+        return "Setting cert request attributes error";
+
+    case PKCS7_OID_E:
+        return "PKCS#7 error: mismatched OID value";
+
+    case PKCS7_RECIP_E:
+        return "PKCS#7 error: no matching recipient found";
+
+    case WC_PKCS7_WANT_READ_E:
+        return "PKCS#7 operations wants more input, call again";
+
+    case FIPS_NOT_ALLOWED_E:
+        return "FIPS mode not allowed error";
+
+    case ASN_NAME_INVALID_E:
+        return "Name Constraint error";
+
+    case RNG_FAILURE_E:
+        return "Random Number Generator failed";
+
+    case HMAC_MIN_KEYLEN_E:
+        return "FIPS Mode HMAC Minimum Key Length error";
+
+    case RSA_PAD_E:
+        return "Rsa Padding error";
+
+    case LENGTH_ONLY_E:
+        return "Output length only set, not for other use error";
+
+    case IN_CORE_FIPS_E:
+        return "In Core Integrity check FIPS error";
+
+    case AES_KAT_FIPS_E:
+        return "AES Known Answer Test check FIPS error";
+
+    case DES3_KAT_FIPS_E:
+        return "DES3 Known Answer Test check FIPS error";
+
+    case HMAC_KAT_FIPS_E:
+        return "HMAC Known Answer Test check FIPS error";
+
+    case RSA_KAT_FIPS_E:
+        return "RSA Known Answer Test check FIPS error";
+
+    case DRBG_KAT_FIPS_E:
+        return "DRBG Known Answer Test check FIPS error";
+
+    case DRBG_CONT_FIPS_E:
+        return "DRBG Continuous Test FIPS error";
+
+    case AESGCM_KAT_FIPS_E:
+        return "AESGCM Known Answer Test check FIPS error";
+
+    case THREAD_STORE_KEY_E:
+        return "Thread Storage Key Create error";
+
+    case THREAD_STORE_SET_E:
+        return "Thread Storage Set error";
+
+    case MAC_CMP_FAILED_E:
+        return "MAC comparison failed";
+
+    case IS_POINT_E:
+        return "ECC is point on curve failed";
+
+    case ECC_INF_E:
+        return " ECC point at infinity error";
+
+    case ECC_OUT_OF_RANGE_E:
+        return " ECC Qx or Qy out of range error";
+
+    case ECC_PRIV_KEY_E:
+        return " ECC private key is not valid error";
+
+    case SRP_CALL_ORDER_E:
+        return "SRP function called in the wrong order error";
+
+    case SRP_VERIFY_E:
+        return "SRP proof verification error";
+
+    case SRP_BAD_KEY_E:
+        return "SRP bad key values error";
+
+    case ASN_NO_SKID:
+        return "ASN no Subject Key Identifier found error";
+
+    case ASN_NO_AKID:
+        return "ASN no Authority Key Identifier found error";
+
+    case ASN_NO_KEYUSAGE:
+        return "ASN no Key Usage found error";
+
+    case SKID_E:
+        return "Setting Subject Key Identifier error";
+
+    case AKID_E:
+        return "Setting Authority Key Identifier error";
+
+    case KEYUSAGE_E:
+        return "Key Usage value error";
+
+    case EXTKEYUSAGE_E:
+        return "Extended Key Usage value error";
+
+    case CERTPOLICIES_E:
+        return "Setting Certificate Policies error";
+
+    case WC_INIT_E:
+        return "wolfCrypt Initialize Failure error";
+
+    case SIG_VERIFY_E:
+        return "Signature verify error";
+
+    case BAD_COND_E:
+        return "Bad condition variable operation error";
+
+    case SIG_TYPE_E:
+        return "Signature type not enabled/available";
+
+    case HASH_TYPE_E:
+        return "Hash type not enabled/available";
+
+    case WC_KEY_SIZE_E:
+        return "Key size error, either too small or large";
+
+    case ASN_COUNTRY_SIZE_E:
+        return "Country code size error, either too small or large";
+
+    case MISSING_RNG_E:
+        return "RNG required but not provided";
+
+    case ASN_PATHLEN_SIZE_E:
+        return "ASN CA path length value too large error";
+
+    case ASN_PATHLEN_INV_E:
+        return "ASN CA path length larger than signer error";
+
+    case BAD_KEYWRAP_ALG_E:
+        return "Unsupported key wrap algorithm error";
+
+    case BAD_KEYWRAP_IV_E:
+        return "Decrypted AES key wrap IV does not match expected";
+
+    case WC_CLEANUP_E:
+        return "wolfcrypt cleanup failed";
+
+    case ECC_CDH_KAT_FIPS_E:
+        return "wolfcrypt FIPS ECC CDH Known Answer Test Failure";
+
+    case DH_CHECK_PUB_E:
+        return "DH Check Public Key failure";
+
+    case BAD_PATH_ERROR:
+        return "Bad path for opendir error";
+
+    case ASYNC_OP_E:
+        return "Async operation error";
+
+    case BAD_OCSP_RESPONDER:
+        return "Invalid OCSP Responder, missing specific key usage extensions";
+
+    case ECC_PRIVATEONLY_E:
+        return "Invalid use of private only ECC key";
+
+    case WC_HW_E:
+        return "Error with hardware crypto use";
+
+    case WC_HW_WAIT_E:
+        return "Hardware waiting on resource";
+
+    case PSS_SALTLEN_E:
+        return "PSS - Length of salt is too big for hash algorithm";
+
+    case PRIME_GEN_E:
+        return "Unable to find a prime for RSA key";
+
+    case BER_INDEF_E:
+        return "Unable to decode an indefinite length encoded message";
+
+    case RSA_OUT_OF_RANGE_E:
+        return "Ciphertext to decrypt is out of range";
+
+    case RSAPSS_PAT_FIPS_E:
+        return "wolfcrypt FIPS RSA-PSS Pairwise Agreement Test Failure";
+
+    case ECDSA_PAT_FIPS_E:
+        return "wolfcrypt FIPS ECDSA Pairwise Agreement Test Failure";
+
+    case DH_KAT_FIPS_E:
+        return "wolfcrypt FIPS DH Known Answer Test Failure";
+
+    case AESCCM_KAT_FIPS_E:
+        return "AESCCM Known Answer Test check FIPS error";
+
+    case SHA3_KAT_FIPS_E:
+        return "SHA-3 Known Answer Test check FIPS error";
+
+    case ECDHE_KAT_FIPS_E:
+        return "wolfcrypt FIPS ECDHE Known Answer Test Failure";
+
+    case AES_GCM_OVERFLOW_E:
+        return "AES-GCM invocation counter overflow";
+
+    case AES_CCM_OVERFLOW_E:
+        return "AES-CCM invocation counter overflow";
+
+    case RSA_KEY_PAIR_E:
+        return "RSA Key Pair-Wise Consistency check fail";
+
+    case DH_CHECK_PRIV_E:
+        return "DH Check Private Key failure";
+
+    case WC_AFALG_SOCK_E:
+        return "AF_ALG socket error";
+
+    case WC_DEVCRYPTO_E:
+        return "Error with /dev/crypto";
+
+    case ZLIB_INIT_ERROR:
+        return "zlib init error";
+
+    case ZLIB_COMPRESS_ERROR:
+        return "zlib compress error";
+
+    case ZLIB_DECOMPRESS_ERROR:
+        return "zlib decompress error";
+
+    case PKCS7_NO_SIGNER_E:
+        return "No signer in PKCS#7 signed data";
+
+    case CRYPTOCB_UNAVAILABLE:
+        return "Crypto callback unavailable";
+
+    case PKCS7_SIGNEEDS_CHECK:
+        return "Signature found but no certificate to verify";
+
+    case PSS_SALTLEN_RECOVER_E:
+        return "PSS - Salt length unable to be recovered";
+
+    case ASN_SELF_SIGNED_E:
+        return "ASN self-signed certificate error";
+
+    default:
+        return "unknown error number";
+
+    }
+}
+
+void wc_ErrorString(int error, char* buffer)
+{
+    XSTRNCPY(buffer, wc_GetErrorString(error), WOLFSSL_MAX_ERROR_SZ);
+    buffer[WOLFSSL_MAX_ERROR_SZ-1] = 0;
+}
+#endif /* !NO_ERROR_STRINGS */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/evp.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/evp.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/evp.c	(revision 453)
@@ -0,0 +1,6595 @@
+/* evp.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#if !defined(WOLFSSL_EVP_INCLUDED)
+    #ifndef WOLFSSL_IGNORE_FILE_WARN
+        #warning evp.c does not need to be compiled separately from ssl.c
+    #endif
+#elif defined(WOLFCRYPT_ONLY)
+#else
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#include <wolfssl/openssl/ecdsa.h>
+#include <wolfssl/openssl/evp.h>
+
+#if defined(OPENSSL_EXTRA)
+
+#ifndef NO_AES
+    #ifdef HAVE_AES_CBC
+    #ifdef WOLFSSL_AES_128
+        static char *EVP_AES_128_CBC = NULL;
+    #endif
+    #ifdef WOLFSSL_AES_192
+        static char *EVP_AES_192_CBC = NULL;
+    #endif
+    #ifdef WOLFSSL_AES_256
+        static char *EVP_AES_256_CBC = NULL;
+    #endif
+    #endif /* HAVE_AES_CBC */
+
+    #ifdef WOLFSSL_AES_OFB
+    #ifdef WOLFSSL_AES_128
+        static char *EVP_AES_128_OFB = NULL;
+    #endif
+    #ifdef WOLFSSL_AES_192
+        static char *EVP_AES_192_OFB = NULL;
+    #endif
+    #ifdef WOLFSSL_AES_256
+        static char *EVP_AES_256_OFB = NULL;
+    #endif
+    #endif /* WOLFSSL_AES_OFB */
+
+    #ifdef WOLFSSL_AES_XTS
+    #ifdef WOLFSSL_AES_128
+        static char *EVP_AES_128_XTS = NULL;
+    #endif
+    #ifdef WOLFSSL_AES_256
+        static char *EVP_AES_256_XTS = NULL;
+    #endif
+    #endif /* WOLFSSL_AES_XTS */
+
+    #ifdef WOLFSSL_AES_CFB
+    #ifdef WOLFSSL_AES_128
+        static char *EVP_AES_128_CFB1 = NULL;
+    #endif
+    #ifdef WOLFSSL_AES_192
+        static char *EVP_AES_192_CFB1 = NULL;
+    #endif
+    #ifdef WOLFSSL_AES_256
+        static char *EVP_AES_256_CFB1 = NULL;
+    #endif
+
+    #ifdef WOLFSSL_AES_128
+        static char *EVP_AES_128_CFB8 = NULL;
+    #endif
+    #ifdef WOLFSSL_AES_192
+        static char *EVP_AES_192_CFB8 = NULL;
+    #endif
+    #ifdef WOLFSSL_AES_256
+        static char *EVP_AES_256_CFB8 = NULL;
+    #endif
+
+    #ifdef WOLFSSL_AES_128
+        static char *EVP_AES_128_CFB128 = NULL;
+    #endif
+    #ifdef WOLFSSL_AES_192
+        static char *EVP_AES_192_CFB128 = NULL;
+    #endif
+    #ifdef WOLFSSL_AES_256
+        static char *EVP_AES_256_CFB128 = NULL;
+    #endif
+    #endif /* WOLFSSL_AES_CFB */
+
+    #ifdef HAVE_AESGCM
+        #ifdef WOLFSSL_AES_128
+            static char *EVP_AES_128_GCM = NULL;
+        #endif
+        #ifdef WOLFSSL_AES_192
+            static char *EVP_AES_192_GCM = NULL;
+        #endif
+        #ifdef WOLFSSL_AES_256
+            static char *EVP_AES_256_GCM = NULL;
+        #endif
+    #endif /* HAVE_AESGCM */
+    #ifdef WOLFSSL_AES_128
+        static char *EVP_AES_128_CTR = NULL;
+    #endif
+    #ifdef WOLFSSL_AES_192
+        static char *EVP_AES_192_CTR = NULL;
+    #endif
+    #ifdef WOLFSSL_AES_256
+        static char *EVP_AES_256_CTR = NULL;
+    #endif
+
+    #ifdef WOLFSSL_AES_128
+        static char *EVP_AES_128_ECB = NULL;
+    #endif
+    #ifdef WOLFSSL_AES_192
+        static char *EVP_AES_192_ECB = NULL;
+    #endif
+    #ifdef WOLFSSL_AES_256
+        static char *EVP_AES_256_ECB = NULL;
+    #endif
+        #define      EVP_AES_SIZE 11
+    #ifdef WOLFSSL_AES_CFB
+        #define      EVP_AESCFB_SIZE 14
+    #endif
+#endif
+
+#ifndef NO_DES3
+    static char *EVP_DES_CBC = NULL;
+    static char *EVP_DES_ECB = NULL;
+
+    static char *EVP_DES_EDE3_CBC = NULL;
+    static char *EVP_DES_EDE3_ECB = NULL;
+
+    #define EVP_DES_SIZE 7
+    #define EVP_DES_EDE3_SIZE 12
+#endif
+
+#ifdef HAVE_IDEA
+    static char *EVP_IDEA_CBC;
+    #define EVP_IDEA_SIZE 8
+#endif
+
+static unsigned int cipherType(const WOLFSSL_EVP_CIPHER *cipher);
+
+
+/* Getter function for cipher key length
+ *
+ * c  WOLFSSL_EVP_CIPHER structure to get key length from
+ *
+ * NOTE: OpenSSL_add_all_ciphers() should be called first before using this
+ *       function
+ *
+ * Returns size of key in bytes
+ */
+int wolfSSL_EVP_Cipher_key_length(const WOLFSSL_EVP_CIPHER* c)
+{
+    WOLFSSL_ENTER("wolfSSL_EVP_Cipher_key_length");
+
+    if (c == NULL) {
+        return 0;
+    }
+
+    switch (cipherType(c)) {
+#if !defined(NO_AES)
+  #if defined(HAVE_AES_CBC)
+      case AES_128_CBC_TYPE: return 16;
+      case AES_192_CBC_TYPE: return 24;
+      case AES_256_CBC_TYPE: return 32;
+  #endif
+  #if defined(WOLFSSL_AES_CFB)
+      case AES_128_CFB1_TYPE: return 16;
+      case AES_192_CFB1_TYPE: return 24;
+      case AES_256_CFB1_TYPE: return 32;
+      case AES_128_CFB8_TYPE: return 16;
+      case AES_192_CFB8_TYPE: return 24;
+      case AES_256_CFB8_TYPE: return 32;
+      case AES_128_CFB128_TYPE: return 16;
+      case AES_192_CFB128_TYPE: return 24;
+      case AES_256_CFB128_TYPE: return 32;
+  #endif
+  #if defined(WOLFSSL_AES_OFB)
+      case AES_128_OFB_TYPE: return 16;
+      case AES_192_OFB_TYPE: return 24;
+      case AES_256_OFB_TYPE: return 32;
+  #endif
+  #if defined(WOLFSSL_AES_XTS)
+      case AES_128_XTS_TYPE: return 16;
+      case AES_256_XTS_TYPE: return 32;
+  #endif
+  #if defined(HAVE_AESGCM)
+      case AES_128_GCM_TYPE: return 16;
+      case AES_192_GCM_TYPE: return 24;
+      case AES_256_GCM_TYPE: return 32;
+  #endif
+  #if defined(WOLFSSL_AES_COUNTER)
+      case AES_128_CTR_TYPE: return 16;
+      case AES_192_CTR_TYPE: return 24;
+      case AES_256_CTR_TYPE: return 32;
+  #endif
+  #if defined(HAVE_AES_ECB)
+      case AES_128_ECB_TYPE: return 16;
+      case AES_192_ECB_TYPE: return 24;
+      case AES_256_ECB_TYPE: return 32;
+  #endif
+#endif /* !NO_AES */
+  #ifndef NO_DES3
+      case DES_CBC_TYPE:      return 8;
+      case DES_EDE3_CBC_TYPE: return 24;
+      case DES_ECB_TYPE:      return 8;
+      case DES_EDE3_ECB_TYPE: return 24;
+  #endif
+      default:
+          return 0;
+      }
+}
+
+
+int  wolfSSL_EVP_EncryptInit(WOLFSSL_EVP_CIPHER_CTX* ctx,
+                                        const WOLFSSL_EVP_CIPHER* type,
+                                        const unsigned char* key,
+                                        const unsigned char* iv)
+{
+    return wolfSSL_EVP_CipherInit(ctx, type, (byte*)key, (byte*)iv, 1);
+}
+
+int  wolfSSL_EVP_EncryptInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx,
+                                        const WOLFSSL_EVP_CIPHER* type,
+                                        WOLFSSL_ENGINE *impl,
+                                        const unsigned char* key,
+                                        const unsigned char* iv)
+{
+    (void) impl;
+    return wolfSSL_EVP_CipherInit(ctx, type, (byte*)key, (byte*)iv, 1);
+}
+
+int  wolfSSL_EVP_DecryptInit(WOLFSSL_EVP_CIPHER_CTX* ctx,
+                                        const WOLFSSL_EVP_CIPHER* type,
+                                        const unsigned char* key,
+                                        const unsigned char* iv)
+{
+    WOLFSSL_ENTER("wolfSSL_EVP_CipherInit");
+    return wolfSSL_EVP_CipherInit(ctx, type, (byte*)key, (byte*)iv, 0);
+}
+
+int  wolfSSL_EVP_DecryptInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx,
+                                        const WOLFSSL_EVP_CIPHER* type,
+                                        WOLFSSL_ENGINE *impl,
+                                        const unsigned char* key,
+                                        const unsigned char* iv)
+{
+    (void) impl;
+    WOLFSSL_ENTER("wolfSSL_EVP_DecryptInit");
+    return wolfSSL_EVP_CipherInit(ctx, type, (byte*)key, (byte*)iv, 0);
+}
+
+
+WOLFSSL_EVP_CIPHER_CTX *wolfSSL_EVP_CIPHER_CTX_new(void)
+{
+    WOLFSSL_EVP_CIPHER_CTX *ctx = (WOLFSSL_EVP_CIPHER_CTX*)XMALLOC(sizeof *ctx,
+                                                 NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (ctx) {
+        WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_new");
+        wolfSSL_EVP_CIPHER_CTX_init(ctx);
+    }
+    return ctx;
+}
+
+void wolfSSL_EVP_CIPHER_CTX_free(WOLFSSL_EVP_CIPHER_CTX *ctx)
+{
+    if (ctx) {
+        WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_free");
+        wolfSSL_EVP_CIPHER_CTX_cleanup(ctx);
+        XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+}
+
+int wolfSSL_EVP_CIPHER_CTX_reset(WOLFSSL_EVP_CIPHER_CTX *ctx)
+{
+    int ret = WOLFSSL_FAILURE;
+
+    if (ctx != NULL) {
+        WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_reset");
+        wolfSSL_EVP_CIPHER_CTX_cleanup(ctx);
+        ret = WOLFSSL_SUCCESS;
+    }
+
+    return ret;
+}
+
+unsigned long wolfSSL_EVP_CIPHER_CTX_mode(const WOLFSSL_EVP_CIPHER_CTX *ctx)
+{
+  if (ctx == NULL) return 0;
+  return ctx->flags & WOLFSSL_EVP_CIPH_MODE;
+}
+
+int  wolfSSL_EVP_EncryptFinal(WOLFSSL_EVP_CIPHER_CTX *ctx,
+                                   unsigned char *out, int *outl)
+{
+    if (ctx && ctx->enc) {
+        WOLFSSL_ENTER("wolfSSL_EVP_EncryptFinal");
+        return wolfSSL_EVP_CipherFinal(ctx, out, outl);
+    }
+    else
+        return WOLFSSL_FAILURE;
+}
+
+
+int  wolfSSL_EVP_CipherInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx,
+                                    const WOLFSSL_EVP_CIPHER* type,
+                                    WOLFSSL_ENGINE *impl,
+                                    const unsigned char* key,
+                                    const unsigned char* iv,
+                                    int enc)
+{
+    (void)impl;
+    return wolfSSL_EVP_CipherInit(ctx, type, key, iv, enc);
+}
+
+int  wolfSSL_EVP_EncryptFinal_ex(WOLFSSL_EVP_CIPHER_CTX *ctx,
+                                   unsigned char *out, int *outl)
+{
+    if (ctx && ctx->enc) {
+        WOLFSSL_ENTER("wolfSSL_EVP_EncryptFinal_ex");
+        return wolfSSL_EVP_CipherFinal(ctx, out, outl);
+    }
+    else
+        return WOLFSSL_FAILURE;
+}
+
+int  wolfSSL_EVP_DecryptFinal(WOLFSSL_EVP_CIPHER_CTX *ctx,
+                                   unsigned char *out, int *outl)
+{
+    if (ctx && !ctx->enc) {
+        WOLFSSL_ENTER("wolfSSL_EVP_DecryptFinal");
+        return wolfSSL_EVP_CipherFinal(ctx, out, outl);
+    }
+    else {
+        return WOLFSSL_FAILURE;
+    }
+}
+
+int  wolfSSL_EVP_DecryptFinal_ex(WOLFSSL_EVP_CIPHER_CTX *ctx,
+                                   unsigned char *out, int *outl)
+{
+    if (ctx && !ctx->enc) {
+        WOLFSSL_ENTER("wolfSSL_EVP_DecryptFinal_ex");
+        return wolfSSL_EVP_CipherFinal(ctx, out, outl);
+    }
+    else {
+        return WOLFSSL_FAILURE;
+    }
+}
+
+
+int wolfSSL_EVP_DigestInit_ex(WOLFSSL_EVP_MD_CTX* ctx,
+                                     const WOLFSSL_EVP_MD* type,
+                                     WOLFSSL_ENGINE *impl)
+{
+    (void) impl;
+    WOLFSSL_ENTER("wolfSSL_EVP_DigestInit_ex");
+    return wolfSSL_EVP_DigestInit(ctx, type);
+}
+
+#ifdef DEBUG_WOLFSSL_EVP
+#define PRINT_BUF(b, sz) { int _i; for(_i=0; _i<(sz); _i++) { \
+  printf("%02x(%c),", (b)[_i], (b)[_i]); if ((_i+1)%8==0)printf("\n");}}
+#else
+#define PRINT_BUF(b, sz)
+#endif
+
+static int fillBuff(WOLFSSL_EVP_CIPHER_CTX *ctx, const unsigned char *in, int sz)
+{
+    int fill;
+
+    if (sz > 0) {
+        if ((sz+ctx->bufUsed) > ctx->block_size) {
+            fill = ctx->block_size - ctx->bufUsed;
+        } else {
+            fill = sz;
+        }
+        XMEMCPY(&(ctx->buf[ctx->bufUsed]), in, fill);
+        ctx->bufUsed += fill;
+        return fill;
+    } else return 0;
+}
+
+static int evpCipherBlock(WOLFSSL_EVP_CIPHER_CTX *ctx,
+                                   unsigned char *out,
+                                   const unsigned char *in, int inl)
+{
+    int ret = 0;
+
+    switch (ctx->cipherType) {
+#if !defined(NO_AES)
+    #if defined(HAVE_AES_CBC)
+        case AES_128_CBC_TYPE:
+        case AES_192_CBC_TYPE:
+        case AES_256_CBC_TYPE:
+            if (ctx->enc)
+                ret = wc_AesCbcEncrypt(&ctx->cipher.aes, out, in, inl);
+            else
+                ret = wc_AesCbcDecrypt(&ctx->cipher.aes, out, in, inl);
+            break;
+    #endif
+    #if defined(HAVE_AESGCM)
+        case AES_128_GCM_TYPE:
+        case AES_192_GCM_TYPE:
+        case AES_256_GCM_TYPE:
+            if (ctx->enc) {
+                if (out){
+                    /* encrypt confidential data*/
+                    ret = wc_AesGcmEncrypt(&ctx->cipher.aes, out, in, inl,
+                              ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz,
+                              NULL, 0);
+                }
+                else {
+                    /* authenticated, non-confidential data */
+                    ret = wc_AesGcmEncrypt(&ctx->cipher.aes, NULL, NULL, 0,
+                              ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz,
+                              in, inl);
+                    /* Reset partial authTag error for AAD*/
+                    if (ret == AES_GCM_AUTH_E)
+                        ret = 0;
+                }
+            }
+            else {
+                if (out){
+                    /* decrypt confidential data*/
+                    ret = wc_AesGcmDecrypt(&ctx->cipher.aes, out, in, inl,
+                              ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz,
+                              NULL, 0);
+                }
+                else {
+                    /* authenticated, non-confidential data*/
+                    ret = wc_AesGcmDecrypt(&ctx->cipher.aes, NULL, NULL, 0,
+                              ctx->iv, ctx->ivSz,
+                              ctx->authTag, ctx->authTagSz,
+                              in, inl);
+                    /* Reset partial authTag error for AAD*/
+                    if (ret == AES_GCM_AUTH_E)
+                        ret = 0;
+                }
+            }
+            break;
+    #endif
+    #if defined(WOLFSSL_AES_COUNTER)
+        case AES_128_CTR_TYPE:
+        case AES_192_CTR_TYPE:
+        case AES_256_CTR_TYPE:
+            ret = wc_AesCtrEncrypt(&ctx->cipher.aes, out, in, inl);
+            break;
+    #endif
+    #if defined(HAVE_AES_ECB)
+        case AES_128_ECB_TYPE:
+        case AES_192_ECB_TYPE:
+        case AES_256_ECB_TYPE:
+            if (ctx->enc)
+                ret = wc_AesEcbEncrypt(&ctx->cipher.aes, out, in, inl);
+            else
+                ret = wc_AesEcbDecrypt(&ctx->cipher.aes, out, in, inl);
+            break;
+    #endif
+    #if defined(WOLFSSL_AES_OFB)
+        case AES_128_OFB_TYPE:
+        case AES_192_OFB_TYPE:
+        case AES_256_OFB_TYPE:
+            if (ctx->enc)
+                ret = wc_AesOfbEncrypt(&ctx->cipher.aes, out, in, inl);
+            else
+                ret = wc_AesOfbDecrypt(&ctx->cipher.aes, out, in, inl);
+            break;
+    #endif
+    #if defined(WOLFSSL_AES_CFB)
+    #if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS)
+        case AES_128_CFB1_TYPE:
+        case AES_192_CFB1_TYPE:
+        case AES_256_CFB1_TYPE:
+            if (ctx->enc)
+                ret = wc_AesCfb1Encrypt(&ctx->cipher.aes, out, in,
+                        inl * WOLFSSL_BIT_SIZE);
+            else
+                ret = wc_AesCfb1Decrypt(&ctx->cipher.aes, out, in,
+                        inl * WOLFSSL_BIT_SIZE);
+            break;
+
+        case AES_128_CFB8_TYPE:
+        case AES_192_CFB8_TYPE:
+        case AES_256_CFB8_TYPE:
+            if (ctx->enc)
+                ret = wc_AesCfb8Encrypt(&ctx->cipher.aes, out, in, inl);
+            else
+                ret = wc_AesCfb8Decrypt(&ctx->cipher.aes, out, in, inl);
+            break;
+    #endif /* !HAVE_SELFTEST && !HAVE_FIPS */
+
+        case AES_128_CFB128_TYPE:
+        case AES_192_CFB128_TYPE:
+        case AES_256_CFB128_TYPE:
+            if (ctx->enc)
+                ret = wc_AesCfbEncrypt(&ctx->cipher.aes, out, in, inl);
+            else
+                ret = wc_AesCfbDecrypt(&ctx->cipher.aes, out, in, inl);
+            break;
+    #endif
+#if defined(WOLFSSL_AES_XTS)
+    case AES_128_XTS_TYPE:
+    case AES_256_XTS_TYPE:
+        if (ctx->enc)
+            ret = wc_AesXtsEncrypt(&ctx->cipher.xts, out, in, inl,
+                    ctx->iv, ctx->ivSz);
+        else
+            ret = wc_AesXtsDecrypt(&ctx->cipher.xts, out, in, inl,
+                    ctx->iv, ctx->ivSz);
+        break;
+#endif
+#endif /* !NO_AES */
+    #ifndef NO_DES3
+        case DES_CBC_TYPE:
+            if (ctx->enc)
+                ret = wc_Des_CbcEncrypt(&ctx->cipher.des, out, in, inl);
+            else
+                ret = wc_Des_CbcDecrypt(&ctx->cipher.des, out, in, inl);
+            break;
+        case DES_EDE3_CBC_TYPE:
+            if (ctx->enc)
+                ret = wc_Des3_CbcEncrypt(&ctx->cipher.des3, out, in, inl);
+            else
+                ret = wc_Des3_CbcDecrypt(&ctx->cipher.des3, out, in, inl);
+            break;
+        #if defined(WOLFSSL_DES_ECB)
+        case DES_ECB_TYPE:
+            ret = wc_Des_EcbEncrypt(&ctx->cipher.des, out, in, inl);
+            break;
+        case DES_EDE3_ECB_TYPE:
+            ret = wc_Des3_EcbEncrypt(&ctx->cipher.des3, out, in, inl);
+            break;
+        #endif
+    #endif
+    #ifndef NO_RC4
+        case ARC4_TYPE:
+            wc_Arc4Process(&ctx->cipher.arc4, out, in, inl);
+        break;
+    #endif
+        default:
+            return WOLFSSL_FAILURE;
+    }
+
+    if (ret != 0)
+        return WOLFSSL_FAILURE; /* failure */
+
+    (void)in;
+    (void)inl;
+    (void)out;
+
+    return WOLFSSL_SUCCESS; /* success */
+}
+
+#if defined(HAVE_AESGCM)
+static int wolfSSL_EVP_CipherUpdate_GCM(WOLFSSL_EVP_CIPHER_CTX *ctx,
+                                   unsigned char *out, int *outl,
+                                   const unsigned char *in, int inl)
+{
+    /* process blocks */
+    if (evpCipherBlock(ctx, out, in, inl) == 0)
+        return WOLFSSL_FAILURE;
+    *outl = inl;
+    return WOLFSSL_SUCCESS;
+}
+#endif
+
+/* returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure */
+WOLFSSL_API int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx,
+                                   unsigned char *out, int *outl,
+                                   const unsigned char *in, int inl)
+{
+    int blocks;
+    int fill;
+
+    WOLFSSL_ENTER("wolfSSL_EVP_CipherUpdate");
+    if ((ctx == NULL) || (inl < 0) || (outl == NULL)|| (in == NULL)) {
+        WOLFSSL_MSG("Bad argument");
+        return WOLFSSL_FAILURE;
+    }
+
+    *outl = 0;
+    if (inl == 0) {
+        return WOLFSSL_SUCCESS;
+    }
+
+#if !defined(NO_AES) && defined(HAVE_AESGCM)
+        switch (ctx->cipherType) {
+            case AES_128_GCM_TYPE:
+            case AES_192_GCM_TYPE:
+            case AES_256_GCM_TYPE:
+/* if out == NULL, in/inl contains the additional authenticated data for GCM */
+                return wolfSSL_EVP_CipherUpdate_GCM(ctx, out, outl, in, inl);
+            default:
+                /* fall-through */
+                break;
+        }
+#endif /* !defined(NO_AES) && defined(HAVE_AESGCM) */
+
+    if (out == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+
+    if (ctx->bufUsed > 0) { /* concatenate them if there is anything */
+        fill = fillBuff(ctx, in, inl);
+        inl -= fill;
+        in  += fill;
+    }
+
+    /* check if the buff is full, and if so flash it out */
+    if (ctx->bufUsed == ctx->block_size) {
+        byte* output = out;
+
+        /* During decryption we save the last block to check padding on Final.
+         * Update the last block stored if one has already been stored */
+        if (ctx->enc == 0) {
+            if (ctx->lastUsed == 1) {
+                XMEMCPY(out, ctx->lastBlock, ctx->block_size);
+                *outl+= ctx->block_size;
+                out  += ctx->block_size;
+            }
+            output = ctx->lastBlock; /* redirect output to last block buffer */
+            ctx->lastUsed = 1;
+        }
+
+        PRINT_BUF(ctx->buf, ctx->block_size);
+        if (evpCipherBlock(ctx, output, ctx->buf, ctx->block_size) == 0) {
+            return WOLFSSL_FAILURE;
+        }
+        PRINT_BUF(out, ctx->block_size);
+        ctx->bufUsed = 0;
+
+        /* if doing encryption update the new output block, decryption will
+         * always have the last block saved for when Final is called */
+        if ((ctx->enc != 0)) {
+            *outl+= ctx->block_size;
+            out  += ctx->block_size;
+        }
+    }
+
+    blocks = inl / ctx->block_size;
+    if (blocks > 0) {
+        /* During decryption we save the last block to check padding on Final.
+         * Update the last block stored if one has already been stored */
+        if ((ctx->enc == 0) && (ctx->lastUsed == 1)) {
+            PRINT_BUF(ctx->lastBlock, ctx->block_size);
+            XMEMCPY(out, ctx->lastBlock, ctx->block_size);
+            *outl += ctx->block_size;
+            out += ctx->block_size;
+            ctx->lastUsed = 0;
+        }
+
+        /* process blocks */
+        if (evpCipherBlock(ctx, out, in, blocks * ctx->block_size) == 0) {
+            return WOLFSSL_FAILURE;
+        }
+        PRINT_BUF(in, ctx->block_size*blocks);
+        PRINT_BUF(out,ctx->block_size*blocks);
+        inl  -= ctx->block_size * blocks;
+        in   += ctx->block_size * blocks;
+        if (ctx->enc == 0) {
+            if ((ctx->flags & WOLFSSL_EVP_CIPH_NO_PADDING) ||
+                    (ctx->block_size == 1)) {
+                ctx->lastUsed = 0;
+                *outl += ctx->block_size * blocks;
+            } else {
+                /* in the case of decryption and padding, store the last block
+                 * here in order to verify the padding when Final is called */
+                if (inl == 0) { /* if not 0 then we know leftovers are checked*/
+                    ctx->lastUsed = 1;
+                    blocks = blocks - 1; /* save last block to check padding in
+                                          * EVP_CipherFinal call */
+                    XMEMCPY(ctx->lastBlock, &out[ctx->block_size * blocks],
+                            ctx->block_size);
+                }
+                *outl += ctx->block_size * blocks;
+            }
+        } else {
+            *outl += ctx->block_size * blocks;
+        }
+    }
+
+
+    if (inl > 0) {
+        /* put fraction into buff */
+        fillBuff(ctx, in, inl);
+        /* no increase of outl */
+    }
+    (void)out; /* silence warning in case not read */
+
+    return WOLFSSL_SUCCESS;
+}
+
+static void padBlock(WOLFSSL_EVP_CIPHER_CTX *ctx)
+{
+    int i;
+    for (i = ctx->bufUsed; i < ctx->block_size; i++)
+        ctx->buf[i] = (byte)(ctx->block_size - ctx->bufUsed);
+}
+
+static int checkPad(WOLFSSL_EVP_CIPHER_CTX *ctx, unsigned char *buff)
+{
+    int i;
+    int n;
+    n = buff[ctx->block_size-1];
+    if (n > ctx->block_size) return -1;
+    for (i = 0; i < n; i++) {
+        if (buff[ctx->block_size-i-1] != n)
+            return -1;
+    }
+    return ctx->block_size - n;
+}
+
+int  wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx,
+                                   unsigned char *out, int *outl)
+{
+    int fl;
+    int ret = WOLFSSL_SUCCESS;
+    if (!ctx || !outl)
+        return WOLFSSL_FAILURE;
+
+    WOLFSSL_ENTER("wolfSSL_EVP_CipherFinal");
+
+#if !defined(NO_AES) && defined(HAVE_AESGCM)
+        switch (ctx->cipherType) {
+            case AES_128_GCM_TYPE:
+            case AES_192_GCM_TYPE:
+            case AES_256_GCM_TYPE:
+                *outl = 0;
+                /* Clear IV, since IV reuse is not recommended for AES GCM. */
+                XMEMSET(ctx->iv, 0, AES_BLOCK_SIZE);
+                return WOLFSSL_SUCCESS;
+            default:
+                /* fall-through */
+                break;
+        }
+#endif /* !NO_AES && HAVE_AESGCM */
+
+    if (!out)
+        return WOLFSSL_FAILURE;
+
+    if (ctx->flags & WOLFSSL_EVP_CIPH_NO_PADDING) {
+        if (ctx->bufUsed != 0) return WOLFSSL_FAILURE;
+        *outl = 0;
+    }
+    else if (ctx->enc) {
+        if (ctx->block_size == 1) {
+            *outl = 0;
+        }
+        else if ((ctx->bufUsed >= 0) && (ctx->block_size != 1)) {
+            padBlock(ctx);
+            PRINT_BUF(ctx->buf, ctx->block_size);
+            if (evpCipherBlock(ctx, out, ctx->buf, ctx->block_size) == 0) {
+                WOLFSSL_MSG("Final Cipher Block failed");
+                ret = WOLFSSL_FAILURE;
+            }
+            else {
+                PRINT_BUF(out, ctx->block_size);
+                *outl = ctx->block_size;
+            }
+        }
+    }
+    else {
+        if (ctx->block_size == 1) {
+            *outl = 0;
+        }
+        else if ((ctx->bufUsed % ctx->block_size) != 0) {
+            *outl = 0;
+            /* not enough padding for decrypt */
+            WOLFSSL_MSG("Final Cipher Block not enough padding");
+            ret = WOLFSSL_FAILURE;
+        }
+        else if (ctx->lastUsed) {
+            PRINT_BUF(ctx->lastBlock, ctx->block_size);
+            if ((fl = checkPad(ctx, ctx->lastBlock)) >= 0) {
+                XMEMCPY(out, ctx->lastBlock, fl);
+                *outl = fl;
+                if (ctx->lastUsed == 0 && ctx->bufUsed == 0) {
+                    /* return error in cases where the block length is incorrect */
+                    WOLFSSL_MSG("Final Cipher Block bad length");
+                    ret = WOLFSSL_FAILURE;
+                }
+            }
+            else {
+                ret = WOLFSSL_FAILURE;
+            }
+        }
+        else if (ctx->lastUsed == 0 && ctx->bufUsed == 0) {
+            /* return error in cases where the block length is incorrect */
+            ret = WOLFSSL_FAILURE;
+        }
+    }
+    if (ret == WOLFSSL_SUCCESS) {
+        /* reset cipher state after final */
+        wolfSSL_EVP_CipherInit(ctx, NULL, NULL, NULL, -1);
+    }
+    return ret;
+}
+
+
+#ifdef WOLFSSL_EVP_DECRYPT_LEGACY
+/* This is a version of DecryptFinal to work with data encrypted with
+ * wolfSSL_EVP_EncryptFinal() with the broken padding. (pre-v3.12.0)
+ * Only call this after wolfSSL_EVP_CipherFinal() fails on a decrypt.
+ * Note, you don't know if the padding is good or bad with the old
+ * encrypt, but it is likely to be or bad. It will update the output
+ * length with the block_size so the last block is still captured. */
+WOLFSSL_API int  wolfSSL_EVP_DecryptFinal_legacy(WOLFSSL_EVP_CIPHER_CTX *ctx,
+        unsigned char *out, int *outl)
+{
+    int fl;
+    if (ctx == NULL || out == NULL || outl == NULL)
+        return BAD_FUNC_ARG;
+
+    WOLFSSL_ENTER("wolfSSL_EVP_DecryptFinal_legacy");
+    if (ctx->block_size == 1) {
+        *outl = 0;
+        return WOLFSSL_SUCCESS;
+    }
+    if ((ctx->bufUsed % ctx->block_size) != 0) {
+        *outl = 0;
+        /* not enough padding for decrypt */
+        return WOLFSSL_FAILURE;
+    }
+    /* The original behavior of CipherFinal() was like it is now,
+     * but checkPad would return 0 in case of a bad pad. It would
+     * treat the pad as 0, and leave the data in the output buffer,
+     * and not try to copy anything. This converts checkPad's -1 error
+     * code to block_size.
+     */
+    if (ctx->lastUsed) {
+        PRINT_BUF(ctx->lastBlock, ctx->block_size);
+        if ((fl = checkPad(ctx, ctx->lastBlock)) < 0) {
+            fl = ctx->block_size;
+        }
+        else {
+            XMEMCPY(out, ctx->lastBlock, fl);
+        }
+        *outl = fl;
+    }
+    /* return error in cases where the block length is incorrect */
+    if (ctx->lastUsed == 0 && ctx->bufUsed == 0) {
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+#endif
+
+
+int wolfSSL_EVP_CIPHER_CTX_block_size(const WOLFSSL_EVP_CIPHER_CTX *ctx)
+{
+    if (ctx == NULL) return BAD_FUNC_ARG;
+    switch (ctx->cipherType) {
+#if !defined(NO_AES) || !defined(NO_DES3)
+#if !defined(NO_AES)
+#if defined(HAVE_AES_CBC)
+    case AES_128_CBC_TYPE:
+    case AES_192_CBC_TYPE:
+    case AES_256_CBC_TYPE:
+#endif
+#if defined(HAVE_AESGCM)
+    case AES_128_GCM_TYPE:
+    case AES_192_GCM_TYPE:
+    case AES_256_GCM_TYPE:
+#endif
+#if defined(WOLFSSL_AES_COUNTER)
+    case AES_128_CTR_TYPE:
+    case AES_192_CTR_TYPE:
+    case AES_256_CTR_TYPE:
+#endif
+#if defined(WOLFSSL_AES_CFB)
+    case AES_128_CFB1_TYPE:
+    case AES_192_CFB1_TYPE:
+    case AES_256_CFB1_TYPE:
+    case AES_128_CFB8_TYPE:
+    case AES_192_CFB8_TYPE:
+    case AES_256_CFB8_TYPE:
+    case AES_128_CFB128_TYPE:
+    case AES_192_CFB128_TYPE:
+    case AES_256_CFB128_TYPE:
+#endif
+#if defined(WOLFSSL_AES_OFB)
+    case AES_128_OFB_TYPE:
+    case AES_192_OFB_TYPE:
+    case AES_256_OFB_TYPE:
+#endif
+#if defined(WOLFSSL_AES_XTS)
+    case AES_128_XTS_TYPE:
+    case AES_256_XTS_TYPE:
+#endif
+
+    case AES_128_ECB_TYPE:
+    case AES_192_ECB_TYPE:
+    case AES_256_ECB_TYPE:
+#endif /* !NO_AES */
+#ifndef NO_DES3
+    case DES_CBC_TYPE:
+    case DES_ECB_TYPE:
+    case DES_EDE3_CBC_TYPE:
+    case DES_EDE3_ECB_TYPE:
+#endif
+        return ctx->block_size;
+#endif /* !NO_AES || !NO_DES3 */
+    default:
+        return 0;
+    }
+}
+
+static unsigned int cipherType(const WOLFSSL_EVP_CIPHER *cipher)
+{
+    if (cipher == NULL) return 0; /* dummy for #ifdef */
+#ifndef NO_DES3
+    else if (EVP_DES_CBC && XSTRNCMP(cipher, EVP_DES_CBC, EVP_DES_SIZE) == 0)
+        return DES_CBC_TYPE;
+    else if (EVP_DES_EDE3_CBC && XSTRNCMP(cipher, EVP_DES_EDE3_CBC, EVP_DES_EDE3_SIZE) == 0)
+        return DES_EDE3_CBC_TYPE;
+#if !defined(NO_DES3)
+    else if (EVP_DES_ECB && XSTRNCMP(cipher, EVP_DES_ECB, EVP_DES_SIZE) == 0)
+        return DES_ECB_TYPE;
+    else if (EVP_DES_EDE3_ECB && XSTRNCMP(cipher, EVP_DES_EDE3_ECB, EVP_DES_EDE3_SIZE) == 0)
+        return DES_EDE3_ECB_TYPE;
+#endif /* NO_DES3 && HAVE_AES_ECB */
+#endif
+#if !defined(NO_AES)
+#if defined(HAVE_AES_CBC)
+    #ifdef WOLFSSL_AES_128
+    else if (EVP_AES_128_CBC && XSTRNCMP(cipher, EVP_AES_128_CBC, EVP_AES_SIZE) == 0)
+        return AES_128_CBC_TYPE;
+    #endif
+    #ifdef WOLFSSL_AES_192
+    else if (EVP_AES_192_CBC && XSTRNCMP(cipher, EVP_AES_192_CBC, EVP_AES_SIZE) == 0)
+        return AES_192_CBC_TYPE;
+    #endif
+    #ifdef WOLFSSL_AES_256
+    else if (EVP_AES_256_CBC && XSTRNCMP(cipher, EVP_AES_256_CBC, EVP_AES_SIZE) == 0)
+        return AES_256_CBC_TYPE;
+    #endif
+#endif /* HAVE_AES_CBC */
+#if defined(HAVE_AESGCM)
+    #ifdef WOLFSSL_AES_128
+    else if (EVP_AES_128_GCM && XSTRNCMP(cipher, EVP_AES_128_GCM, EVP_AES_SIZE) == 0)
+        return AES_128_GCM_TYPE;
+    #endif
+    #ifdef WOLFSSL_AES_192
+    else if (EVP_AES_192_GCM && XSTRNCMP(cipher, EVP_AES_192_GCM, EVP_AES_SIZE) == 0)
+        return AES_192_GCM_TYPE;
+    #endif
+    #ifdef WOLFSSL_AES_256
+    else if (EVP_AES_256_GCM && XSTRNCMP(cipher, EVP_AES_256_GCM, EVP_AES_SIZE) == 0)
+        return AES_256_GCM_TYPE;
+    #endif
+#endif /* HAVE_AESGCM */
+#if defined(WOLFSSL_AES_COUNTER)
+    #ifdef WOLFSSL_AES_128
+    else if (EVP_AES_128_CTR && XSTRNCMP(cipher, EVP_AES_128_CTR, EVP_AES_SIZE) == 0)
+        return AES_128_CTR_TYPE;
+    #endif
+    #ifdef WOLFSSL_AES_192
+    else if (EVP_AES_192_CTR && XSTRNCMP(cipher, EVP_AES_192_CTR, EVP_AES_SIZE) == 0)
+        return AES_192_CTR_TYPE;
+    #endif
+    #ifdef WOLFSSL_AES_256
+    else if (EVP_AES_256_CTR && XSTRNCMP(cipher, EVP_AES_256_CTR, EVP_AES_SIZE) == 0)
+        return AES_256_CTR_TYPE;
+    #endif
+#endif /* HAVE_AES_CBC */
+#if defined(HAVE_AES_ECB)
+    #ifdef WOLFSSL_AES_128
+    else if (EVP_AES_128_ECB && XSTRNCMP(cipher, EVP_AES_128_ECB, EVP_AES_SIZE) == 0)
+        return AES_128_ECB_TYPE;
+    #endif
+    #ifdef WOLFSSL_AES_192
+    else if (EVP_AES_192_ECB && XSTRNCMP(cipher, EVP_AES_192_ECB, EVP_AES_SIZE) == 0)
+        return AES_192_ECB_TYPE;
+    #endif
+    #ifdef WOLFSSL_AES_256
+    else if (EVP_AES_256_ECB && XSTRNCMP(cipher, EVP_AES_256_ECB, EVP_AES_SIZE) == 0)
+        return AES_256_ECB_TYPE;
+    #endif
+#endif /*HAVE_AES_CBC */
+#if defined(WOLFSSL_AES_XTS)
+    #ifdef WOLFSSL_AES_128
+    else if (EVP_AES_128_XTS && XSTRNCMP(cipher, EVP_AES_128_XTS, EVP_AES_SIZE) == 0)
+        return AES_128_XTS_TYPE;
+    #endif
+    #ifdef WOLFSSL_AES_256
+    else if (EVP_AES_256_XTS && XSTRNCMP(cipher, EVP_AES_256_XTS, EVP_AES_SIZE) == 0)
+        return AES_256_XTS_TYPE;
+    #endif
+#endif /* WOLFSSL_AES_XTS */
+#if defined(WOLFSSL_AES_CFB)
+    #ifdef WOLFSSL_AES_128
+    else if (EVP_AES_128_CFB1 && XSTRNCMP(cipher, EVP_AES_128_CFB1, EVP_AESCFB_SIZE) == 0)
+        return AES_128_CFB1_TYPE;
+    #endif
+    #ifdef WOLFSSL_AES_192
+    else if (EVP_AES_192_CFB1 && XSTRNCMP(cipher, EVP_AES_192_CFB1, EVP_AESCFB_SIZE) == 0)
+        return AES_192_CFB1_TYPE;
+    #endif
+    #ifdef WOLFSSL_AES_256
+    else if (EVP_AES_256_CFB1 && XSTRNCMP(cipher, EVP_AES_256_CFB1, EVP_AESCFB_SIZE) == 0)
+        return AES_256_CFB1_TYPE;
+    #endif
+    #ifdef WOLFSSL_AES_128
+    else if (EVP_AES_128_CFB8 && XSTRNCMP(cipher, EVP_AES_128_CFB8, EVP_AESCFB_SIZE) == 0)
+        return AES_128_CFB8_TYPE;
+    #endif
+    #ifdef WOLFSSL_AES_192
+    else if (EVP_AES_192_CFB8 && XSTRNCMP(cipher, EVP_AES_192_CFB8, EVP_AESCFB_SIZE) == 0)
+        return AES_192_CFB8_TYPE;
+    #endif
+    #ifdef WOLFSSL_AES_256
+    else if (EVP_AES_256_CFB8 && XSTRNCMP(cipher, EVP_AES_256_CFB8, EVP_AESCFB_SIZE) == 0)
+        return AES_256_CFB8_TYPE;
+    #endif
+    #ifdef WOLFSSL_AES_128
+    else if (EVP_AES_128_CFB128 && XSTRNCMP(cipher, EVP_AES_128_CFB128, EVP_AESCFB_SIZE) == 0)
+        return AES_128_CFB128_TYPE;
+    #endif
+    #ifdef WOLFSSL_AES_192
+    else if (EVP_AES_192_CFB128 && XSTRNCMP(cipher, EVP_AES_192_CFB128, EVP_AESCFB_SIZE) == 0)
+        return AES_192_CFB128_TYPE;
+    #endif
+    #ifdef WOLFSSL_AES_256
+    else if (EVP_AES_256_CFB128 && XSTRNCMP(cipher, EVP_AES_256_CFB128, EVP_AESCFB_SIZE) == 0)
+        return AES_256_CFB128_TYPE;
+    #endif
+#endif /*HAVE_AES_CBC */
+#endif /* !NO_AES */
+      else return 0;
+}
+
+int wolfSSL_EVP_CIPHER_block_size(const WOLFSSL_EVP_CIPHER *cipher)
+{
+  if (cipher == NULL) return BAD_FUNC_ARG;
+  switch (cipherType(cipher)) {
+#if !defined(NO_AES)
+  #if defined(HAVE_AES_CBC)
+      case AES_128_CBC_TYPE:
+      case AES_192_CBC_TYPE:
+      case AES_256_CBC_TYPE:
+          return AES_BLOCK_SIZE;
+  #endif
+  #if defined(HAVE_AESGCM)
+      case AES_128_GCM_TYPE:
+      case AES_192_GCM_TYPE:
+      case AES_256_GCM_TYPE:
+          return AES_BLOCK_SIZE;
+  #endif
+  #if defined(WOLFSSL_AES_COUNTER)
+      case AES_128_CTR_TYPE:
+      case AES_192_CTR_TYPE:
+      case AES_256_CTR_TYPE:
+          return AES_BLOCK_SIZE;
+  #endif
+  #if defined(HAVE_AES_ECB)
+      case AES_128_ECB_TYPE:
+      case AES_192_ECB_TYPE:
+      case AES_256_ECB_TYPE:
+          return AES_BLOCK_SIZE;
+  #endif
+#endif /* NO_AES */
+  #ifndef NO_DES3
+      case DES_CBC_TYPE: return 8;
+      case DES_EDE3_CBC_TYPE: return 8;
+      case DES_ECB_TYPE: return 8;
+      case DES_EDE3_ECB_TYPE: return 8;
+  #endif
+      default:
+          return 0;
+      }
+}
+
+unsigned long WOLFSSL_CIPHER_mode(const WOLFSSL_EVP_CIPHER *cipher)
+{
+    switch (cipherType(cipher)) {
+#if !defined(NO_AES)
+    #if defined(HAVE_AES_CBC)
+        case AES_128_CBC_TYPE:
+        case AES_192_CBC_TYPE:
+        case AES_256_CBC_TYPE:
+            return WOLFSSL_EVP_CIPH_CBC_MODE;
+    #endif
+    #if defined(HAVE_AESGCM)
+        case AES_128_GCM_TYPE:
+        case AES_192_GCM_TYPE:
+        case AES_256_GCM_TYPE:
+            return WOLFSSL_EVP_CIPH_GCM_MODE;
+    #endif
+    #if defined(WOLFSSL_AES_COUNTER)
+        case AES_128_CTR_TYPE:
+        case AES_192_CTR_TYPE:
+        case AES_256_CTR_TYPE:
+            return WOLFSSL_EVP_CIPH_CTR_MODE;
+    #endif
+        case AES_128_ECB_TYPE:
+        case AES_192_ECB_TYPE:
+        case AES_256_ECB_TYPE:
+            return WOLFSSL_EVP_CIPH_ECB_MODE;
+#endif /* NO_ASE */
+    #ifndef NO_DES3
+        case DES_CBC_TYPE:
+        case DES_EDE3_CBC_TYPE:
+            return WOLFSSL_EVP_CIPH_CBC_MODE;
+        case DES_ECB_TYPE:
+        case DES_EDE3_ECB_TYPE:
+            return WOLFSSL_EVP_CIPH_ECB_MODE;
+    #endif
+    #ifndef NO_RC4
+        case ARC4_TYPE:
+            return EVP_CIPH_STREAM_CIPHER;
+    #endif
+        default:
+            return 0;
+        }
+}
+
+unsigned long WOLFSSL_EVP_CIPHER_mode(const WOLFSSL_EVP_CIPHER *cipher)
+{
+  if (cipher == NULL) return 0;
+  return WOLFSSL_CIPHER_mode(cipher);
+}
+
+void wolfSSL_EVP_CIPHER_CTX_set_flags(WOLFSSL_EVP_CIPHER_CTX *ctx, int flags)
+{
+    if (ctx != NULL) {
+        ctx->flags |= flags;
+    }
+}
+
+void wolfSSL_EVP_CIPHER_CTX_clear_flags(WOLFSSL_EVP_CIPHER_CTX *ctx, int flags)
+{
+    if (ctx != NULL) {
+        ctx->flags &= ~flags;
+    }
+}
+
+unsigned long wolfSSL_EVP_CIPHER_flags(const WOLFSSL_EVP_CIPHER *cipher)
+{
+  if (cipher == NULL) return 0;
+  return WOLFSSL_CIPHER_mode(cipher);
+}
+
+int  wolfSSL_EVP_CIPHER_CTX_set_padding(WOLFSSL_EVP_CIPHER_CTX *ctx, int padding)
+{
+  if (ctx == NULL) return BAD_FUNC_ARG;
+  if (padding) {
+      ctx->flags &= ~WOLFSSL_EVP_CIPH_NO_PADDING;
+  }
+  else {
+      ctx->flags |=  WOLFSSL_EVP_CIPH_NO_PADDING;
+  }
+  return 1;
+}
+
+int wolfSSL_EVP_add_digest(const WOLFSSL_EVP_MD *digest)
+{
+    (void)digest;
+    /* nothing to do */
+    return 0;
+}
+
+
+/* Frees the WOLFSSL_EVP_PKEY_CTX passed in.
+ *
+ * return WOLFSSL_SUCCESS on success
+ */
+int wolfSSL_EVP_PKEY_CTX_free(WOLFSSL_EVP_PKEY_CTX *ctx)
+{
+    if (ctx == NULL) return 0;
+    WOLFSSL_ENTER("EVP_PKEY_CTX_free");
+    if (ctx->pkey != NULL)
+        wolfSSL_EVP_PKEY_free(ctx->pkey);
+    if (ctx->peerKey != NULL)
+        wolfSSL_EVP_PKEY_free(ctx->peerKey);
+    XFREE(ctx, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* Creates a new WOLFSSL_EVP_PKEY_CTX structure.
+ *
+ * pkey  key structure to use with new WOLFSSL_EVP_PEKY_CTX
+ * e     engine to use. It should be NULL at this time.
+ *
+ * return the new structure on success and NULL if failed.
+ */
+WOLFSSL_EVP_PKEY_CTX *wolfSSL_EVP_PKEY_CTX_new(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_ENGINE *e)
+{
+    WOLFSSL_EVP_PKEY_CTX* ctx;
+    int type = NID_undef;
+
+    if (pkey == NULL) return 0;
+    if (e != NULL) return 0;
+    WOLFSSL_ENTER("EVP_PKEY_CTX_new");
+
+    ctx = (WOLFSSL_EVP_PKEY_CTX*)XMALLOC(sizeof(WOLFSSL_EVP_PKEY_CTX), NULL,
+            DYNAMIC_TYPE_PUBLIC_KEY);
+    if (ctx == NULL) return NULL;
+    XMEMSET(ctx, 0, sizeof(WOLFSSL_EVP_PKEY_CTX));
+    ctx->pkey = pkey;
+#if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+    ctx->padding = RSA_PKCS1_PADDING;
+#endif
+    type = wolfSSL_EVP_PKEY_type(pkey->type);
+
+    if (type != NID_undef) {
+        if (wc_LockMutex(&pkey->refMutex) != 0) {
+            WOLFSSL_MSG("Couldn't lock pkey mutex");
+        }
+        pkey->references++;
+
+        wc_UnLockMutex(&pkey->refMutex);
+    }
+    return ctx;
+}
+
+
+/* Sets the type of RSA padding to use.
+ *
+ * ctx     structure to set padding in.
+ * padding RSA padding type
+ *
+ * returns WOLFSSL_SUCCESS on success.
+ */
+int wolfSSL_EVP_PKEY_CTX_set_rsa_padding(WOLFSSL_EVP_PKEY_CTX *ctx, int padding)
+{
+    if (ctx == NULL) return 0;
+    WOLFSSL_ENTER("EVP_PKEY_CTX_set_rsa_padding");
+    ctx->padding = padding;
+    return WOLFSSL_SUCCESS;
+}
+
+/* create a PKEY contxt and return it */
+WOLFSSL_EVP_PKEY_CTX *wolfSSL_EVP_PKEY_CTX_new_id(int id, WOLFSSL_ENGINE *e)
+{
+    WOLFSSL_EVP_PKEY* pkey;
+    WOLFSSL_EVP_PKEY_CTX* ctx = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_EVP_PKEY_CTX_new_id");
+
+    pkey = wolfSSL_EVP_PKEY_new_ex(NULL);
+    if (pkey) {
+        pkey->type = id;
+        ctx = wolfSSL_EVP_PKEY_CTX_new(pkey, e);
+        if (ctx == NULL) {
+            wolfSSL_EVP_PKEY_free(pkey);
+        }
+    }
+    return ctx;
+}
+
+/* Returns WOLFSSL_SUCCESS or error */
+int wolfSSL_EVP_PKEY_CTX_set_rsa_keygen_bits(WOLFSSL_EVP_PKEY_CTX *ctx, int bits)
+{
+    if (ctx) {
+        ctx->nbits = bits;
+    }
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_EVP_PKEY_derive_init(WOLFSSL_EVP_PKEY_CTX *ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_EVP_PKEY_derive_init");
+
+    if (!ctx) {
+        return WOLFSSL_FAILURE;
+    }
+    wolfSSL_EVP_PKEY_free(ctx->peerKey);
+    ctx->op = EVP_PKEY_OP_DERIVE;
+    ctx->padding = 0;
+    ctx->nbits = 0;
+    return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_EVP_PKEY_derive_set_peer(WOLFSSL_EVP_PKEY_CTX *ctx, WOLFSSL_EVP_PKEY *peer)
+{
+    WOLFSSL_ENTER("wolfSSL_EVP_PKEY_derive_set_peer");
+
+    if (!ctx || ctx->op != EVP_PKEY_OP_DERIVE) {
+        return WOLFSSL_FAILURE;
+    }
+    wolfSSL_EVP_PKEY_free(ctx->peerKey);
+    ctx->peerKey = peer;
+    if (!wolfSSL_EVP_PKEY_up_ref(peer)) {
+        ctx->peerKey = NULL;
+        return WOLFSSL_FAILURE;
+    }
+    return WOLFSSL_SUCCESS;
+}
+
+#if !defined(NO_DH) && defined(HAVE_ECC)
+int wolfSSL_EVP_PKEY_derive(WOLFSSL_EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
+{
+    int len;
+
+    WOLFSSL_ENTER("wolfSSL_EVP_PKEY_derive");
+
+    if (!ctx || ctx->op != EVP_PKEY_OP_DERIVE || !ctx->pkey || !ctx->peerKey || !keylen
+            || ctx->pkey->type != ctx->peerKey->type) {
+        return WOLFSSL_FAILURE;
+    }
+    switch (ctx->pkey->type) {
+#ifndef NO_DH
+    case EVP_PKEY_DH:
+        /* Use DH */
+        if (!ctx->pkey->dh || !ctx->peerKey->dh || !ctx->peerKey->dh->pub_key) {
+            return WOLFSSL_FAILURE;
+        }
+        if ((len = wolfSSL_DH_size(ctx->pkey->dh)) <= 0) {
+            return WOLFSSL_FAILURE;
+        }
+        if (key) {
+            if (*keylen < (size_t)len) {
+                return WOLFSSL_FAILURE;
+            }
+            if (wolfSSL_DH_compute_key(key, ctx->peerKey->dh->pub_key,
+                                       ctx->pkey->dh) != len) {
+                return WOLFSSL_FAILURE;
+            }
+        }
+        *keylen = (size_t)len;
+        break;
+#endif
+#ifdef HAVE_ECC
+    case EVP_PKEY_EC:
+        /* Use ECDH */
+        if (!ctx->pkey->ecc || !ctx->peerKey->ecc) {
+            return WOLFSSL_FAILURE;
+        }
+        /* set internal key if not done */
+        if (!ctx->pkey->ecc->inSet) {
+            if (SetECKeyInternal(ctx->pkey->ecc) != WOLFSSL_SUCCESS) {
+                WOLFSSL_MSG("SetECKeyInternal failed");
+                return WOLFSSL_FAILURE;
+            }
+        }
+        if (!ctx->peerKey->ecc->exSet || !ctx->peerKey->ecc->pub_key->internal) {
+            if (SetECKeyExternal(ctx->peerKey->ecc) != WOLFSSL_SUCCESS) {
+                WOLFSSL_MSG("SetECKeyExternal failed");
+                return WOLFSSL_FAILURE;
+            }
+        }
+        if (!(len = wc_ecc_size((ecc_key*)ctx->pkey->ecc->internal))) {
+            return WOLFSSL_FAILURE;
+        }
+        if (key) {
+            word32 len32 = (word32)len;
+            if (*keylen < len32) {
+                WOLFSSL_MSG("buffer too short");
+                return WOLFSSL_FAILURE;
+            }
+            if (wc_ecc_shared_secret_ssh((ecc_key*)ctx->pkey->ecc->internal,
+                                         (ecc_point*)ctx->peerKey->ecc->pub_key->internal,
+                                         key, &len32) != MP_OKAY) {
+                WOLFSSL_MSG("wc_ecc_shared_secret failed");
+                return WOLFSSL_FAILURE;
+            }
+            len = (int)len32;
+        }
+        *keylen = (size_t)len;
+        break;
+#endif
+    default:
+        WOLFSSL_MSG("Unknown key type");
+        return WOLFSSL_FAILURE;
+    }
+    return WOLFSSL_SUCCESS;
+}
+#endif
+
+/* Uses the WOLFSSL_EVP_PKEY_CTX to decrypt a buffer.
+ *
+ * ctx    structure to decrypt with
+ * out    buffer to hold the results
+ * outlen initially holds size of out buffer and gets set to decrypt result size
+ * in     buffer decrypt
+ * inlen  length of in buffer
+ *
+ * returns WOLFSSL_SUCCESS on success.
+ */
+int wolfSSL_EVP_PKEY_decrypt(WOLFSSL_EVP_PKEY_CTX *ctx,
+                     unsigned char *out, size_t *outlen,
+                     const unsigned char *in, size_t inlen)
+{
+    int len = 0;
+
+    if (ctx == NULL) return 0;
+    WOLFSSL_ENTER("EVP_PKEY_decrypt");
+
+    (void)out;
+    (void)outlen;
+    (void)in;
+    (void)inlen;
+    (void)len;
+
+    switch (ctx->pkey->type) {
+#if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+    case EVP_PKEY_RSA:
+        len = wolfSSL_RSA_private_decrypt((int)inlen, (unsigned char*)in, out,
+              ctx->pkey->rsa, ctx->padding);
+        if (len < 0) break;
+        else {
+            *outlen = len;
+            return WOLFSSL_SUCCESS;
+        }
+#endif /* NO_RSA */
+
+    case EVP_PKEY_EC:
+        WOLFSSL_MSG("not implemented");
+        FALL_THROUGH;
+    default:
+        break;
+    }
+    return WOLFSSL_FAILURE;
+}
+
+
+/* Initialize a WOLFSSL_EVP_PKEY_CTX structure for decryption
+ *
+ * ctx    WOLFSSL_EVP_PKEY_CTX structure to use with decryption
+ *
+ * Returns WOLFSSL_FAILURE on failure and WOLFSSL_SUCCESS on success
+ */
+int wolfSSL_EVP_PKEY_decrypt_init(WOLFSSL_EVP_PKEY_CTX *ctx)
+{
+    if (ctx == NULL) return WOLFSSL_FAILURE;
+    WOLFSSL_ENTER("EVP_PKEY_decrypt_init");
+    switch (ctx->pkey->type) {
+    case EVP_PKEY_RSA:
+        ctx->op = EVP_PKEY_OP_DECRYPT;
+        return WOLFSSL_SUCCESS;
+    case EVP_PKEY_EC:
+        WOLFSSL_MSG("not implemented");
+        FALL_THROUGH;
+    default:
+        break;
+    }
+    return WOLFSSL_FAILURE;
+}
+
+
+/* Use a WOLFSSL_EVP_PKEY_CTX structure to encrypt data
+ *
+ * ctx    WOLFSSL_EVP_PKEY_CTX structure to use with encryption
+ * out    buffer to hold encrypted data
+ * outlen length of out buffer
+ * in     data to be encrypted
+ * inlen  length of in buffer
+ *
+ * Returns WOLFSSL_FAILURE on failure and WOLFSSL_SUCCESS on success
+ */
+int wolfSSL_EVP_PKEY_encrypt(WOLFSSL_EVP_PKEY_CTX *ctx,
+                     unsigned char *out, size_t *outlen,
+                     const unsigned char *in, size_t inlen)
+{
+    int len = 0;
+    if (ctx == NULL) return WOLFSSL_FAILURE;
+    WOLFSSL_ENTER("EVP_PKEY_encrypt");
+    if (ctx->op != EVP_PKEY_OP_ENCRYPT) return WOLFSSL_FAILURE;
+
+    (void)out;
+    (void)outlen;
+    (void)in;
+    (void)inlen;
+    (void)len;
+    switch (ctx->pkey->type) {
+#if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+    case EVP_PKEY_RSA:
+        len = wolfSSL_RSA_public_encrypt((int)inlen, (unsigned char *)in, out,
+                  ctx->pkey->rsa, ctx->padding);
+        if (len < 0)
+            break;
+        else {
+            *outlen = len;
+            return WOLFSSL_SUCCESS;
+        }
+#endif /* NO_RSA */
+
+    case EVP_PKEY_EC:
+        WOLFSSL_MSG("not implemented");
+        FALL_THROUGH;
+    default:
+        break;
+    }
+    return WOLFSSL_FAILURE;
+}
+
+
+/* Initialize a WOLFSSL_EVP_PKEY_CTX structure to encrypt data
+ *
+ * ctx    WOLFSSL_EVP_PKEY_CTX structure to use with encryption
+ *
+ * Returns WOLFSSL_FAILURE on failure and WOLFSSL_SUCCESS on success
+ */
+int wolfSSL_EVP_PKEY_encrypt_init(WOLFSSL_EVP_PKEY_CTX *ctx)
+{
+    if (ctx == NULL) return WOLFSSL_FAILURE;
+    WOLFSSL_ENTER("EVP_PKEY_encrypt_init");
+
+    switch (ctx->pkey->type) {
+    case EVP_PKEY_RSA:
+        ctx->op = EVP_PKEY_OP_ENCRYPT;
+        return WOLFSSL_SUCCESS;
+    case EVP_PKEY_EC:
+        WOLFSSL_MSG("not implemented");
+        FALL_THROUGH;
+    default:
+        break;
+    }
+    return WOLFSSL_FAILURE;
+}
+/******************************************************************************
+* wolfSSL_EVP_PKEY_sign_init -  initializes a public key algorithm context for
+* a signing operation.
+*
+* RETURNS:
+* returns WOLFSSL_SUCCESS on success, otherwise returns -2
+*/
+WOLFSSL_API int wolfSSL_EVP_PKEY_sign_init(WOLFSSL_EVP_PKEY_CTX *ctx)
+{
+    int ret = -2;
+
+    WOLFSSL_MSG("wolfSSL_EVP_PKEY_sign_init");
+    if (!ctx  || !ctx->pkey)
+        return ret;
+
+    switch (ctx->pkey->type) {
+        case EVP_PKEY_RSA:
+            ctx->op = EVP_PKEY_OP_SIGN;
+            ret = WOLFSSL_SUCCESS;
+            break;
+        case EVP_PKEY_EC:
+            WOLFSSL_MSG("not implemented");
+            FALL_THROUGH;
+        default:
+            ret = -2;
+    }
+    return ret;
+}
+/******************************************************************************
+* wolfSSL_EVP_PKEY_sign - performs a public key signing operation using ctx
+* The data to be signed should be hashed since the function does not hash the data.
+*
+* RETURNS:
+* returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE
+*/
+
+WOLFSSL_API int wolfSSL_EVP_PKEY_sign(WOLFSSL_EVP_PKEY_CTX *ctx, unsigned char *sig,
+                        size_t *siglen, const unsigned char *tbs, size_t tbslen)
+{
+    int len = 0;
+
+    WOLFSSL_MSG("wolfSSL_EVP_PKEY_sign");
+
+    if (!ctx || ctx->op != EVP_PKEY_OP_SIGN || !ctx->pkey)
+        return WOLFSSL_FAILURE;
+
+    (void)sig;
+    (void)siglen;
+    (void)tbs;
+    (void)tbslen;
+    (void)len;
+
+    switch (ctx->pkey->type) {
+#if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+    case EVP_PKEY_RSA:
+        len = wolfSSL_RSA_private_encrypt((int)tbslen, (unsigned char*)tbs, sig,
+              ctx->pkey->rsa, ctx->padding);
+        if (len < 0)
+            break;
+        else {
+            *siglen = len;
+            return WOLFSSL_SUCCESS;
+        }
+#endif /* NO_RSA */
+
+    case EVP_PKEY_EC:
+        WOLFSSL_MSG("not implemented");
+        FALL_THROUGH;
+    default:
+        break;
+    }
+    return WOLFSSL_FAILURE;
+}
+
+/* Get the size in bits for WOLFSSL_EVP_PKEY key
+ *
+ * pkey WOLFSSL_EVP_PKEY structure to get key size of
+ *
+ * returns the size in bits of key on success
+ */
+int wolfSSL_EVP_PKEY_bits(const WOLFSSL_EVP_PKEY *pkey)
+{
+    int bytes;
+
+    if (pkey == NULL) return 0;
+    WOLFSSL_ENTER("EVP_PKEY_bits");
+    if ((bytes = wolfSSL_EVP_PKEY_size((WOLFSSL_EVP_PKEY*)pkey)) ==0) return 0;
+    return bytes*8;
+}
+
+
+int wolfSSL_EVP_PKEY_keygen_init(WOLFSSL_EVP_PKEY_CTX *ctx)
+{
+    (void)ctx;
+    return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_EVP_PKEY_keygen(WOLFSSL_EVP_PKEY_CTX *ctx,
+  WOLFSSL_EVP_PKEY **ppkey)
+{
+    int ret = WOLFSSL_FAILURE;
+    int ownPkey = 0;
+    WOLFSSL_EVP_PKEY* pkey;
+
+    if (ctx == NULL || ppkey == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    pkey = *ppkey;
+    if (pkey == NULL) {
+        ownPkey = 1;
+        pkey = wolfSSL_EVP_PKEY_new();
+
+        if (pkey == NULL)
+            return ret;
+    }
+
+    switch (pkey->type) {
+#if !defined(HAVE_FAST_RSA) && defined(WOLFSSL_KEY_GEN) && \
+    !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+        case EVP_PKEY_RSA:
+            pkey->rsa = wolfSSL_RSA_generate_key(ctx->nbits, WC_RSA_EXPONENT,
+                NULL, NULL);
+            if (pkey->rsa) {
+                pkey->ownRsa = 1;
+                pkey->pkey_sz = wolfSSL_i2d_RSAPrivateKey(pkey->rsa,
+                        (unsigned char**)&pkey->pkey.ptr);
+                ret = WOLFSSL_SUCCESS;
+            }
+            break;
+#endif
+#ifdef HAVE_ECC
+        case EVP_PKEY_EC:
+            pkey->ecc = wolfSSL_EC_KEY_new();
+            if (pkey->ecc) {
+                ret = wolfSSL_EC_KEY_generate_key(pkey->ecc);
+                if (ret == WOLFSSL_SUCCESS) {
+                    pkey->ownEcc = 1;
+                }
+            }
+#endif
+        default:
+            break;
+    }
+
+    if (ret != WOLFSSL_SUCCESS && ownPkey) {
+        wolfSSL_EVP_PKEY_free(pkey);
+        pkey = NULL;
+    }
+
+    *ppkey = pkey;
+
+    return ret;
+}
+
+/* Get the size in bytes for WOLFSSL_EVP_PKEY key
+ *
+ * pkey WOLFSSL_EVP_PKEY structure to get key size of
+ *
+ * returns the size of a key on success which is the maximum size of a
+ *         signature
+ */
+int wolfSSL_EVP_PKEY_size(WOLFSSL_EVP_PKEY *pkey)
+{
+    if (pkey == NULL) return 0;
+    WOLFSSL_ENTER("EVP_PKEY_size");
+
+    switch (pkey->type) {
+#ifndef NO_RSA
+    case EVP_PKEY_RSA:
+        return (int)wolfSSL_RSA_size((const WOLFSSL_RSA*)(pkey->rsa));
+#endif /* !NO_RSA */
+
+#ifdef HAVE_ECC
+    case EVP_PKEY_EC:
+        if (pkey->ecc == NULL || pkey->ecc->internal == NULL) {
+            WOLFSSL_MSG("No ECC key has been set");
+            break;
+        }
+        return wc_ecc_size((ecc_key*)(pkey->ecc->internal));
+#endif /* HAVE_ECC */
+
+    default:
+        break;
+    }
+    return 0;
+}
+
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_API int wolfSSL_EVP_PKEY_missing_parameters(WOLFSSL_EVP_PKEY *pkey)
+{
+    (void)pkey;
+    /* not using missing params callback and returning zero to indicate success */
+    return 0;
+}
+#endif
+
+WOLFSSL_API int wolfSSL_EVP_PKEY_cmp(const WOLFSSL_EVP_PKEY *a, const WOLFSSL_EVP_PKEY *b)
+{
+    int ret = -1; /* failure */
+    int a_sz = 0, b_sz = 0;
+
+    if (a == NULL || b == NULL)
+        return ret;
+
+    /* check its the same type of key */
+    if (a->type != b->type)
+        return ret;
+
+    /* get size based on key type */
+    switch (a->type) {
+#ifndef NO_RSA
+    case EVP_PKEY_RSA:
+        a_sz = (int)wolfSSL_RSA_size((const WOLFSSL_RSA*)(a->rsa));
+        b_sz = (int)wolfSSL_RSA_size((const WOLFSSL_RSA*)(b->rsa));
+        break;
+#endif /* !NO_RSA */
+#ifdef HAVE_ECC
+    case EVP_PKEY_EC:
+        if (a->ecc == NULL || a->ecc->internal == NULL ||
+            b->ecc == NULL || b->ecc->internal == NULL) {
+            return ret;
+        }
+        a_sz = wc_ecc_size((ecc_key*)(a->ecc->internal));
+        b_sz = wc_ecc_size((ecc_key*)(b->ecc->internal));
+        break;
+#endif /* HAVE_ECC */
+    default:
+        break;
+    } /* switch (a->type) */
+
+    /* check size */
+    if (a_sz <= 0 || b_sz <= 0 || a_sz != b_sz) {
+        return ret;
+    }
+
+    /* check public key size */
+    if (a->pkey_sz > 0 && b->pkey_sz > 0 && a->pkey_sz != b->pkey_sz) {
+        return ret;
+    }
+
+    /* check public key */
+    if (a->pkey.ptr && b->pkey.ptr) {
+        if (XMEMCMP(a->pkey.ptr, b->pkey.ptr, a->pkey_sz) != 0) {
+            return ret;
+        }
+    }
+    ret = 0; /* success */
+
+    return ret;
+}
+
+/* Initialize structure for signing
+ *
+ * ctx  WOLFSSL_EVP_MD_CTX structure to initialize
+ * type is the type of message digest to use
+ *
+ * returns WOLFSSL_SUCCESS on success
+ */
+int wolfSSL_EVP_SignInit(WOLFSSL_EVP_MD_CTX *ctx, const WOLFSSL_EVP_MD *type)
+{
+    if (ctx == NULL) return WOLFSSL_FAILURE;
+    WOLFSSL_ENTER("EVP_SignInit");
+    return wolfSSL_EVP_DigestInit(ctx,type);
+}
+
+WOLFSSL_API int wolfSSL_EVP_SignInit_ex(WOLFSSL_EVP_MD_CTX* ctx,
+                                     const WOLFSSL_EVP_MD* type,
+                                     WOLFSSL_ENGINE *impl)
+{
+    if (ctx == NULL) return WOLFSSL_FAILURE;
+    WOLFSSL_ENTER("EVP_SignInit");
+    return wolfSSL_EVP_DigestInit_ex(ctx,type,impl);
+}
+
+
+/* Update structure with data for signing
+ *
+ * ctx  WOLFSSL_EVP_MD_CTX structure to update
+ * data buffer holding data to update with for sign
+ * len  length of data buffer
+ *
+ * returns WOLFSSL_SUCCESS on success
+ */
+int wolfSSL_EVP_SignUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *data, size_t len)
+{
+    if (ctx == NULL) return 0;
+    WOLFSSL_ENTER("EVP_SignUpdate(");
+    return wolfSSL_EVP_DigestUpdate(ctx, data, len);
+}
+
+static const struct s_ent {
+    const int macType;
+    const int nid;
+    const char *name;
+} md_tbl[] = {
+#ifndef NO_MD4
+    {WC_HASH_TYPE_MD4, NID_md4, "MD4"},
+#endif /* NO_MD4 */
+
+#ifndef NO_MD5
+    {WC_HASH_TYPE_MD5, NID_md5, "MD5"},
+#endif /* NO_MD5 */
+
+#ifndef NO_SHA
+    {WC_HASH_TYPE_SHA, NID_sha1, "SHA"},
+#endif /* NO_SHA */
+
+#ifdef WOLFSSL_SHA224
+    {WC_HASH_TYPE_SHA224, NID_sha224, "SHA224"},
+#endif /* WOLFSSL_SHA224 */
+#ifndef NO_SHA256
+    {WC_HASH_TYPE_SHA256, NID_sha256, "SHA256"},
+#endif
+
+#ifdef WOLFSSL_SHA384
+    {WC_HASH_TYPE_SHA384, NID_sha384, "SHA384"},
+#endif /* WOLFSSL_SHA384 */
+#ifdef WOLFSSL_SHA512
+    {WC_HASH_TYPE_SHA512, NID_sha512, "SHA512"},
+#endif /* WOLFSSL_SHA512 */
+#ifndef WOLFSSL_NOSHA3_224
+    {WC_HASH_TYPE_SHA3_224, NID_sha3_224, "SHA3_224"},
+#endif
+#ifndef WOLFSSL_NOSHA3_256
+    {WC_HASH_TYPE_SHA3_256, NID_sha3_256, "SHA3_256"},
+#endif
+    {WC_HASH_TYPE_SHA3_384, NID_sha3_384, "SHA3_384"},
+#ifndef WOLFSSL_NOSHA3_512
+    {WC_HASH_TYPE_SHA3_512, NID_sha3_512, "SHA3_512"},
+#endif
+    {0, 0, NULL}
+};
+
+static int wolfSSL_EVP_md2macType(const WOLFSSL_EVP_MD *md)
+{
+    const struct s_ent *ent ;
+
+    if (md != NULL) {
+        for( ent = md_tbl; ent->name != NULL; ent++) {
+            if(XSTRNCMP((const char *)md, ent->name, XSTRLEN(ent->name)+1) == 0) {
+                return ent->macType;
+            }
+        }
+    }
+    return WC_HASH_TYPE_NONE;
+}
+
+/* Finalize structure for signing
+ *
+ * ctx    WOLFSSL_EVP_MD_CTX structure to finalize
+ * sigret buffer to hold resulting signature
+ * siglen length of sigret buffer
+ * pkey   key to sign with
+ *
+ * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure
+ */
+int wolfSSL_EVP_SignFinal(WOLFSSL_EVP_MD_CTX *ctx, unsigned char *sigret,
+                  unsigned int *siglen, WOLFSSL_EVP_PKEY *pkey)
+{
+    unsigned int mdsize;
+    unsigned char md[WC_MAX_DIGEST_SIZE];
+    int ret;
+    if (ctx == NULL) return WOLFSSL_FAILURE;
+    WOLFSSL_ENTER("EVP_SignFinal");
+
+    ret = wolfSSL_EVP_DigestFinal(ctx, md, &mdsize);
+    if (ret <= 0) return ret;
+
+    (void)sigret;
+    (void)siglen;
+
+    switch (pkey->type) {
+#if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+    case EVP_PKEY_RSA: {
+        int nid = wolfSSL_EVP_MD_type(wolfSSL_EVP_MD_CTX_md(ctx));
+        if (nid < 0) break;
+        return wolfSSL_RSA_sign(nid, md, mdsize, sigret,
+                                siglen, pkey->rsa);
+    }
+#endif /* NO_RSA */
+
+    case EVP_PKEY_DSA:
+    case EVP_PKEY_EC:
+        WOLFSSL_MSG("not implemented");
+        FALL_THROUGH;
+    default:
+        break;
+    }
+    return WOLFSSL_FAILURE;
+}
+
+
+/* Initialize structure for verifying signature
+ *
+ * ctx  WOLFSSL_EVP_MD_CTX structure to initialize
+ * type is the type of message digest to use
+ *
+ * returns WOLFSSL_SUCCESS on success
+ */
+int wolfSSL_EVP_VerifyInit(WOLFSSL_EVP_MD_CTX *ctx, const WOLFSSL_EVP_MD *type)
+{
+    if (ctx == NULL) return WOLFSSL_FAILURE;
+    WOLFSSL_ENTER("EVP_VerifyInit");
+    return wolfSSL_EVP_DigestInit(ctx,type);
+}
+
+
+/* Update structure for verifying signature
+ *
+ * ctx  WOLFSSL_EVP_MD_CTX structure to update
+ * data buffer holding data to update with for verify
+ * len  length of data buffer
+ *
+ * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure
+ */
+int wolfSSL_EVP_VerifyUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *data, size_t len)
+{
+    if (ctx == NULL) return WOLFSSL_FAILURE;
+    WOLFSSL_ENTER("EVP_VerifyUpdate");
+    return wolfSSL_EVP_DigestUpdate(ctx, data, len);
+}
+
+
+/* Finalize structure for verifying signature
+ *
+ * ctx    WOLFSSL_EVP_MD_CTX structure to finalize
+ * sig    buffer holding signature
+ * siglen length of sig buffer
+ * pkey   key to verify with
+ *
+ * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure
+ */
+int wolfSSL_EVP_VerifyFinal(WOLFSSL_EVP_MD_CTX *ctx,
+        unsigned char*sig, unsigned int siglen, WOLFSSL_EVP_PKEY *pkey)
+{
+    int ret;
+    unsigned char md[WC_MAX_DIGEST_SIZE];
+    unsigned int mdsize;
+
+    if (ctx == NULL) return WOLFSSL_FAILURE;
+    WOLFSSL_ENTER("EVP_VerifyFinal");
+    ret = wolfSSL_EVP_DigestFinal(ctx, md, &mdsize);
+    if (ret <= 0) return ret;
+
+    (void)sig;
+    (void)siglen;
+
+    switch (pkey->type) {
+#if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+    case EVP_PKEY_RSA: {
+        int nid = wolfSSL_EVP_MD_type(wolfSSL_EVP_MD_CTX_md(ctx));
+        if (nid < 0) break;
+        return wolfSSL_RSA_verify(nid, md, mdsize, sig,
+                (unsigned int)siglen, pkey->rsa);
+    }
+#endif /* NO_RSA */
+
+    case EVP_PKEY_DSA:
+    case EVP_PKEY_EC:
+        WOLFSSL_MSG("not implemented");
+        FALL_THROUGH;
+    default:
+        break;
+    }
+    return WOLFSSL_FAILURE;
+}
+
+int wolfSSL_EVP_add_cipher(const WOLFSSL_EVP_CIPHER *cipher)
+{
+    (void)cipher;
+    /* nothing to do */
+    return 0;
+}
+
+
+WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_mac_key(int type, ENGINE* e,
+                                          const unsigned char* key, int keylen)
+{
+    WOLFSSL_EVP_PKEY* pkey;
+
+    (void)e;
+
+    if (type != EVP_PKEY_HMAC || (key == NULL && keylen != 0))
+        return NULL;
+
+    pkey = wolfSSL_EVP_PKEY_new();
+    if (pkey != NULL) {
+        pkey->pkey.ptr = (char*)XMALLOC(keylen, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+        if (pkey->pkey.ptr == NULL && keylen > 0) {
+            wolfSSL_EVP_PKEY_free(pkey);
+            pkey = NULL;
+        }
+        else {
+            XMEMCPY(pkey->pkey.ptr, key, keylen);
+            pkey->pkey_sz = keylen;
+            pkey->type = pkey->save_type = type;
+        }
+    }
+
+    return pkey;
+}
+
+
+const unsigned char* wolfSSL_EVP_PKEY_get0_hmac(const WOLFSSL_EVP_PKEY* pkey,
+                                                size_t* len)
+{
+    if (pkey == NULL || len == NULL)
+        return NULL;
+
+    *len = (size_t)pkey->pkey_sz;
+
+    return (const unsigned char*)pkey->pkey.ptr;
+}
+
+
+/* Initialize an EVP_DigestSign/Verify operation.
+ * Initialize a digest for RSA and ECC keys, or HMAC for HMAC key.
+ */
+static int wolfSSL_evp_digest_pk_init(WOLFSSL_EVP_MD_CTX *ctx,
+                                      WOLFSSL_EVP_PKEY_CTX **pctx,
+                                      const WOLFSSL_EVP_MD *type,
+                                      WOLFSSL_ENGINE *e,
+                                      WOLFSSL_EVP_PKEY *pkey)
+{
+    if (pkey->type == EVP_PKEY_HMAC) {
+        int                  hashType;
+        const unsigned char* key;
+        size_t               keySz;
+
+        if (XSTRNCMP(type, "SHA256", 6) == 0) {
+            hashType = WC_SHA256;
+        }
+    #ifdef WOLFSSL_SHA224
+        else if (XSTRNCMP(type, "SHA224", 6) == 0) {
+            hashType = WC_SHA224;
+        }
+    #endif
+    #ifdef WOLFSSL_SHA384
+        else if (XSTRNCMP(type, "SHA384", 6) == 0) {
+            hashType = WC_SHA384;
+        }
+    #endif
+    #ifdef WOLFSSL_SHA512
+        else if (XSTRNCMP(type, "SHA512", 6) == 0) {
+            hashType = WC_SHA512;
+        }
+    #endif
+    #ifndef NO_MD5
+        else if (XSTRNCMP(type, "MD5", 3) == 0) {
+            hashType = WC_MD5;
+        }
+    #endif
+    #ifndef NO_SHA
+        /* has to be last since would pick or 224, 256, 384, or 512 too */
+        else if (XSTRNCMP(type, "SHA", 3) == 0) {
+             hashType = WC_SHA;
+        }
+    #endif /* NO_SHA */
+        else
+             return BAD_FUNC_ARG;
+
+        key = wolfSSL_EVP_PKEY_get0_hmac(pkey, &keySz);
+
+        if (wc_HmacInit(&ctx->hash.hmac, NULL, INVALID_DEVID) != 0)
+            return WOLFSSL_FAILURE;
+
+        if (wc_HmacSetKey(&ctx->hash.hmac, hashType, key, (word32)keySz) != 0)
+            return WOLFSSL_FAILURE;
+
+        ctx->macType = NID_hmac;
+    }
+    else {
+        int ret;
+
+        if (ctx->pctx == NULL) {
+            ctx->pctx = wolfSSL_EVP_PKEY_CTX_new(pkey, e);
+            if (ctx->pctx == NULL)
+                return WOLFSSL_FAILURE;
+        }
+
+        ret = wolfSSL_EVP_DigestInit(ctx, type);
+        if (ret == WOLFSSL_SUCCESS && pctx != NULL)
+            *pctx = ctx->pctx;
+        return ret;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* Update an EVP_DigestSign/Verify operation.
+ * Update a digest for RSA and ECC keys, or HMAC for HMAC key.
+ */
+static int wolfssl_evp_digest_pk_update(WOLFSSL_EVP_MD_CTX *ctx,
+                                        const void *d, unsigned int cnt)
+{
+    if (ctx->pctx == NULL) {
+        if (ctx->macType != NID_hmac)
+            return WOLFSSL_FAILURE;
+
+        if (wc_HmacUpdate(&ctx->hash.hmac, (const byte *)d, cnt) != 0)
+            return WOLFSSL_FAILURE;
+
+        return WOLFSSL_SUCCESS;
+    }
+    else
+        return wolfSSL_EVP_DigestUpdate(ctx, d, cnt);
+}
+
+/* Finalize an EVP_DigestSign/Verify operation - common part only.
+ * Finalize a digest for RSA and ECC keys, or HMAC for HMAC key.
+ * Copies the digest so that you can keep updating.
+ */
+static int wolfssl_evp_digest_pk_final(WOLFSSL_EVP_MD_CTX *ctx,
+                                       unsigned char *md, unsigned int* mdlen)
+{
+    int  ret;
+
+    if (ctx->pctx == NULL) {
+        Hmac hmacCopy;
+
+        if (ctx->macType != NID_hmac)
+            return WOLFSSL_FAILURE;
+
+        if (wolfSSL_HmacCopy(&hmacCopy, &ctx->hash.hmac) != WOLFSSL_SUCCESS)
+            return WOLFSSL_FAILURE;
+        ret = wc_HmacFinal(&hmacCopy, md) == 0;
+        wc_HmacFree(&hmacCopy);
+        return ret;
+    }
+    else {
+        WOLFSSL_EVP_MD_CTX ctxCopy;
+
+        if (wolfSSL_EVP_MD_CTX_copy_ex(&ctxCopy, ctx) != WOLFSSL_SUCCESS)
+            return WOLFSSL_FAILURE;
+
+        ret = wolfSSL_EVP_DigestFinal(&ctxCopy, md, mdlen);
+        wolfSSL_EVP_MD_CTX_cleanup(&ctxCopy);
+        return ret;
+    }
+}
+
+/* Get the length of the mac based on the digest algorithm. */
+static int wolfssl_mac_len(unsigned char macType)
+{
+    int hashLen;
+
+    switch (macType) {
+    #ifndef NO_MD5
+        case WC_MD5:
+            hashLen = WC_MD5_DIGEST_SIZE;
+            break;
+    #endif /* !NO_MD5 */
+
+    #ifndef NO_SHA
+        case WC_SHA:
+            hashLen = WC_SHA_DIGEST_SIZE;
+            break;
+    #endif /* !NO_SHA */
+
+    #ifdef WOLFSSL_SHA224
+        case WC_SHA224:
+            hashLen = WC_SHA224_DIGEST_SIZE;
+            break;
+    #endif /* WOLFSSL_SHA224 */
+
+    #ifndef NO_SHA256
+        case WC_SHA256:
+            hashLen = WC_SHA256_DIGEST_SIZE;
+            break;
+    #endif /* !NO_SHA256 */
+
+    #ifdef WOLFSSL_SHA384
+        case WC_SHA384:
+            hashLen = WC_SHA384_DIGEST_SIZE;
+            break;
+    #endif /* WOLFSSL_SHA384 */
+    #ifdef WOLFSSL_SHA512
+        case WC_SHA512:
+            hashLen = WC_SHA512_DIGEST_SIZE;
+            break;
+    #endif /* WOLFSSL_SHA512 */
+
+    #ifdef HAVE_BLAKE2
+        case BLAKE2B_ID:
+            hashLen = BLAKE2B_OUTBYTES;
+            break;
+    #endif /* HAVE_BLAKE2 */
+
+        default:
+            hashLen = 0;
+    }
+
+    return hashLen;
+}
+
+int wolfSSL_EVP_DigestSignInit(WOLFSSL_EVP_MD_CTX *ctx,
+                               WOLFSSL_EVP_PKEY_CTX **pctx,
+                               const WOLFSSL_EVP_MD *type,
+                               WOLFSSL_ENGINE *e,
+                               WOLFSSL_EVP_PKEY *pkey)
+{
+    WOLFSSL_ENTER("EVP_DigestSignInit");
+
+    if (ctx == NULL || type == NULL || pkey == NULL)
+        return BAD_FUNC_ARG;
+
+    return wolfSSL_evp_digest_pk_init(ctx, pctx, type, e, pkey);
+}
+
+
+int wolfSSL_EVP_DigestSignUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *d,
+                                 unsigned int cnt)
+{
+    WOLFSSL_ENTER("EVP_DigestSignUpdate");
+
+    if (ctx == NULL || d == NULL)
+        return BAD_FUNC_ARG;
+
+    return wolfssl_evp_digest_pk_update(ctx, d, cnt);
+}
+
+int wolfSSL_EVP_DigestSignFinal(WOLFSSL_EVP_MD_CTX *ctx, unsigned char *sig,
+                                size_t *siglen)
+{
+    unsigned char digest[WC_MAX_DIGEST_SIZE];
+    unsigned int  hashLen;
+    int           ret = WOLFSSL_FAILURE;
+
+    WOLFSSL_ENTER("EVP_DigestSignFinal");
+
+    if (ctx == NULL || siglen == NULL)
+        return WOLFSSL_FAILURE;
+
+    /* Return the maximum size of the signaure when sig is NULL. */
+    if (ctx->pctx == NULL) {
+        if (ctx->macType != NID_hmac)
+            return WOLFSSL_FAILURE;
+
+        hashLen = wolfssl_mac_len(ctx->hash.hmac.macType);
+
+        if (sig == NULL) {
+            *siglen = hashLen;
+            return WOLFSSL_SUCCESS;
+        }
+    }
+#ifndef NO_RSA
+    else if (ctx->pctx->pkey->type == EVP_PKEY_RSA) {
+        if (sig == NULL) {
+            *siglen = wolfSSL_RSA_size(ctx->pctx->pkey->rsa);
+            return WOLFSSL_SUCCESS;
+        }
+    }
+#endif /* !NO_RSA */
+#ifdef HAVE_ECC
+    else if (ctx->pctx->pkey->type == EVP_PKEY_EC) {
+        if (sig == NULL) {
+            /* SEQ + INT + INT */
+            *siglen = ecc_sets[ctx->pctx->pkey->ecc->group->curve_idx].size * 2
+                    + 8;
+            return WOLFSSL_SUCCESS;
+        }
+    }
+#endif
+
+    if (wolfssl_evp_digest_pk_final(ctx, digest, &hashLen) <= 0)
+        return WOLFSSL_FAILURE;
+
+    if (ctx->pctx == NULL) {
+        /* Copy the HMAC result as signature. */
+        if ((unsigned int)(*siglen) > hashLen)
+            *siglen = hashLen;
+        /* May be a truncated signature. */
+
+        XMEMCPY(sig, digest, *siglen);
+        ret = WOLFSSL_SUCCESS;
+    }
+    else {
+        /* Sign the digest. */
+        switch (ctx->pctx->pkey->type) {
+    #if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+        case EVP_PKEY_RSA: {
+            unsigned int sigSz;
+            int nid = wolfSSL_EVP_MD_type(wolfSSL_EVP_MD_CTX_md(ctx));
+            if (nid < 0)
+                break;
+            ret = wolfSSL_RSA_sign(nid, digest, hashLen, sig, &sigSz,
+                                   ctx->pctx->pkey->rsa);
+            if (ret >= 0)
+                *siglen = sigSz;
+            break;
+        }
+    #endif /* NO_RSA */
+
+    #ifdef HAVE_ECC
+        case EVP_PKEY_EC: {
+            WOLFSSL_ECDSA_SIG *ecdsaSig;
+            ecdsaSig = wolfSSL_ECDSA_do_sign(digest, hashLen,
+                                             ctx->pctx->pkey->ecc);
+            if (ecdsaSig == NULL)
+                break;
+            *siglen = wolfSSL_i2d_ECDSA_SIG(ecdsaSig, &sig);
+            wolfSSL_ECDSA_SIG_free(ecdsaSig);
+            ret = WOLFSSL_SUCCESS;
+            break;
+        }
+    #endif
+        default:
+            break;
+        }
+    }
+
+    ForceZero(digest, sizeof(digest));
+    return ret;
+}
+int wolfSSL_EVP_DigestVerifyInit(WOLFSSL_EVP_MD_CTX *ctx,
+                                 WOLFSSL_EVP_PKEY_CTX **pctx,
+                                 const WOLFSSL_EVP_MD *type,
+                                 WOLFSSL_ENGINE *e,
+                                 WOLFSSL_EVP_PKEY *pkey)
+{
+    WOLFSSL_ENTER("EVP_DigestVerifyInit");
+
+    if (ctx == NULL || type == NULL || pkey == NULL)
+        return BAD_FUNC_ARG;
+
+    return wolfSSL_evp_digest_pk_init(ctx, pctx, type, e, pkey);
+}
+
+
+int wolfSSL_EVP_DigestVerifyUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *d,
+                                   size_t cnt)
+{
+    WOLFSSL_ENTER("EVP_DigestVerifyUpdate");
+
+    if (ctx == NULL || d == NULL)
+        return BAD_FUNC_ARG;
+
+    return wolfssl_evp_digest_pk_update(ctx, d, (unsigned int)cnt);
+}
+
+
+int wolfSSL_EVP_DigestVerifyFinal(WOLFSSL_EVP_MD_CTX *ctx,
+                                  const unsigned char *sig, size_t siglen)
+{
+    unsigned char digest[WC_MAX_DIGEST_SIZE];
+    unsigned int  hashLen;
+
+    WOLFSSL_ENTER("EVP_DigestVerifyFinal");
+
+    if (ctx == NULL || sig == NULL)
+        return WOLFSSL_FAILURE;
+
+    if (ctx->pctx == NULL) {
+        if (ctx->macType != NID_hmac)
+            return WOLFSSL_FAILURE;
+
+        hashLen = wolfssl_mac_len(ctx->hash.hmac.macType);
+
+        if (siglen > hashLen)
+            return WOLFSSL_FAILURE;
+        /* May be a truncated signature. */
+    }
+
+    if (wolfssl_evp_digest_pk_final(ctx, digest, &hashLen) <= 0)
+        return WOLFSSL_FAILURE;
+
+    if (ctx->pctx == NULL) {
+        /* Check HMAC result matches the signature. */
+        if (XMEMCMP(sig, digest, siglen) == 0)
+            return WOLFSSL_SUCCESS;
+        return WOLFSSL_FAILURE;
+    }
+    else {
+        /* Verify the signature with the digest. */
+        switch (ctx->pctx->pkey->type) {
+    #if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+        case EVP_PKEY_RSA: {
+            int nid = wolfSSL_EVP_MD_type(wolfSSL_EVP_MD_CTX_md(ctx));
+            if (nid < 0)
+                return WOLFSSL_FAILURE;
+            return wolfSSL_RSA_verify(nid, digest, hashLen, sig,
+                                      (unsigned int)siglen,
+                                      ctx->pctx->pkey->rsa);
+        }
+    #endif /* NO_RSA */
+
+    #ifdef HAVE_ECC
+        case EVP_PKEY_EC: {
+            int ret;
+            WOLFSSL_ECDSA_SIG *ecdsaSig;
+            ecdsaSig = wolfSSL_d2i_ECDSA_SIG(NULL, &sig, (long)siglen);
+            if (ecdsaSig == NULL)
+                return WOLFSSL_FAILURE;
+            ret = wolfSSL_ECDSA_do_verify(digest, hashLen, ecdsaSig,
+                                          ctx->pctx->pkey->ecc);
+            wolfSSL_ECDSA_SIG_free(ecdsaSig);
+            return ret;
+        }
+    #endif
+        default:
+            break;
+        }
+    }
+
+    return WOLFSSL_FAILURE;
+}
+
+
+#ifdef WOLFSSL_APACHE_HTTPD
+#if !defined(USE_WINDOWS_API) && !defined(MICROCHIP_PIC32)
+    #include <termios.h>
+#endif
+
+#ifndef XGETPASSWD
+    static int XGETPASSWD(char* buf, int bufSz) {
+        int ret = WOLFSSL_SUCCESS;
+
+        /* turn off echo for passwords */
+    #ifdef USE_WINDOWS_API
+        DWORD originalTerm;
+        DWORD newTerm;
+        CONSOLE_SCREEN_BUFFER_INFO screenOrig;
+        HANDLE stdinHandle = GetStdHandle(STD_INPUT_HANDLE);
+        if (GetConsoleMode(stdinHandle, &originalTerm) == 0) {
+            WOLFSSL_MSG("Couldn't get the original terminal settings");
+            return WOLFSSL_FAILURE;
+        }
+        newTerm = originalTerm;
+        newTerm &= ~ENABLE_ECHO_INPUT;
+        if (SetConsoleMode(stdinHandle, newTerm) == 0) {
+            WOLFSSL_MSG("Couldn't turn off echo");
+            return WOLFSSL_FAILURE;
+        }
+    #else
+        struct termios originalTerm;
+        struct termios newTerm;
+        if (tcgetattr(STDIN_FILENO, &originalTerm) != 0) {
+            WOLFSSL_MSG("Couldn't get the original terminal settings");
+            return WOLFSSL_FAILURE;
+        }
+        XMEMCPY(&newTerm, &originalTerm, sizeof(struct termios));
+
+        newTerm.c_lflag &= ~ECHO;
+        newTerm.c_lflag |= (ICANON | ECHONL);
+        if (tcsetattr(STDIN_FILENO, TCSANOW, &newTerm) != 0) {
+            WOLFSSL_MSG("Couldn't turn off echo");
+            return WOLFSSL_FAILURE;
+        }
+    #endif
+
+        if (XFGETS(buf, bufSz, stdin) == NULL) {
+            ret = WOLFSSL_FAILURE;
+        }
+
+        /* restore default echo */
+    #ifdef USE_WINDOWS_API
+        if (SetConsoleMode(stdinHandle, originalTerm) == 0) {
+            WOLFSSL_MSG("Couldn't restore the terminal settings");
+            return WOLFSSL_FAILURE;
+        }
+    #else
+        if (tcsetattr(STDIN_FILENO, TCSANOW, &originalTerm) != 0) {
+            WOLFSSL_MSG("Couldn't restore the terminal settings");
+            return WOLFSSL_FAILURE;
+        }
+    #endif
+        return ret;
+    }
+#endif
+
+/* returns 0 on success and -2 or -1 on failure */
+int wolfSSL_EVP_read_pw_string(char* buf, int bufSz, const char* banner, int v)
+{
+    printf("%s", banner);
+    if (XGETPASSWD(buf, bufSz) == WOLFSSL_FAILURE) {
+        return -1;
+    }
+    (void)v; /* fgets always sanity checks size of input vs buffer */
+    return 0;
+}
+#endif /* WOLFSSL_APACHE_HTTPD */
+
+#if !defined(NO_PWDBASED) && !defined(NO_SHA)
+int wolfSSL_PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
+                                               const unsigned char *salt,
+                                               int saltlen, int iter,
+                                               int keylen, unsigned char *out)
+{
+    const char *nostring = "";
+    int ret = 0;
+
+    if (pass == NULL) {
+        passlen = 0;
+        pass = nostring;
+    }
+    else if (passlen == -1) {
+        passlen = (int)XSTRLEN(pass);
+    }
+
+    ret = wc_PBKDF2((byte*)out, (byte*)pass, passlen, (byte*)salt, saltlen,
+                    iter, keylen, WC_SHA);
+    if (ret == 0)
+        return WOLFSSL_SUCCESS;
+    else
+        return WOLFSSL_FAILURE;
+}
+#endif /* !NO_PWDBASED !NO_SHA*/
+
+#if !defined(NO_PWDBASED)
+WOLFSSL_API int wolfSSL_PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
+                                           const unsigned char *salt,
+                                           int saltlen, int iter,
+                                           const WOLFSSL_EVP_MD *digest,
+                                           int keylen, unsigned char *out)
+{
+    const char *nostring = "";
+    int ret = 0;
+
+    if (pass == NULL) {
+        passlen = 0;
+        pass = nostring;
+    } else if (passlen == -1) {
+        passlen = (int)XSTRLEN(pass);
+    }
+
+    ret = wc_PBKDF2((byte*)out, (byte*)pass, passlen, (byte*)salt, saltlen,
+                    iter, keylen, wolfSSL_EVP_md2macType(digest));
+    if (ret == 0)
+        return WOLFSSL_SUCCESS;
+    else
+        return WOLFSSL_FAILURE;
+}
+#endif /* !NO_PWDBASED */
+
+static const struct cipher{
+        unsigned char type;
+        const char *name;
+        int nid;
+} cipher_tbl[] = {
+
+#ifndef NO_AES
+    #ifdef WOLFSSL_AES_128
+    {AES_128_CBC_TYPE, "AES-128-CBC", NID_aes_128_cbc},
+    #endif
+    #ifdef WOLFSSL_AES_192
+    {AES_192_CBC_TYPE, "AES-192-CBC", NID_aes_192_cbc},
+    #endif
+    #ifdef WOLFSSL_AES_256
+    {AES_256_CBC_TYPE, "AES-256-CBC", NID_aes_256_cbc},
+    #endif
+
+    #ifdef WOLFSSL_AES_128
+    {AES_128_CFB1_TYPE, "AES-128-CFB1", NID_aes_128_cfb1},
+    #endif
+    #ifdef WOLFSSL_AES_192
+    {AES_192_CFB1_TYPE, "AES-192-CFB1", NID_aes_192_cfb1},
+    #endif
+    #ifdef WOLFSSL_AES_256
+    {AES_256_CFB1_TYPE, "AES-256-CFB1", NID_aes_256_cfb1},
+    #endif
+
+    #ifdef WOLFSSL_AES_128
+    {AES_128_CFB8_TYPE, "AES-128-CFB8", NID_aes_128_cfb8},
+    #endif
+    #ifdef WOLFSSL_AES_192
+    {AES_192_CFB8_TYPE, "AES-192-CFB8", NID_aes_192_cfb8},
+    #endif
+    #ifdef WOLFSSL_AES_256
+    {AES_256_CFB8_TYPE, "AES-256-CFB8", NID_aes_256_cfb8},
+    #endif
+
+    #ifdef WOLFSSL_AES_128
+    {AES_128_CFB128_TYPE, "AES-128-CFB128", NID_aes_128_cfb128},
+    #endif
+    #ifdef WOLFSSL_AES_192
+    {AES_192_CFB128_TYPE, "AES-192-CFB128", NID_aes_192_cfb128},
+    #endif
+    #ifdef WOLFSSL_AES_256
+    {AES_256_CFB128_TYPE, "AES-256-CFB128", NID_aes_256_cfb128},
+    #endif
+
+    #ifdef WOLFSSL_AES_128
+    {AES_128_OFB_TYPE, "AES-128-OFB", NID_aes_128_ofb},
+    #endif
+    #ifdef WOLFSSL_AES_192
+    {AES_192_OFB_TYPE, "AES-192-OFB", NID_aes_192_ofb},
+    #endif
+    #ifdef WOLFSSL_AES_256
+    {AES_256_OFB_TYPE, "AES-256-OFB", NID_aes_256_ofb},
+    #endif
+
+    #ifdef WOLFSSL_AES_128
+    {AES_128_XTS_TYPE, "AES-128-XTS", NID_aes_128_xts},
+    #endif
+    #ifdef WOLFSSL_AES_256
+    {AES_256_XTS_TYPE, "AES-256-XTS", NID_aes_256_xts},
+    #endif
+
+    #ifdef WOLFSSL_AES_128
+    {AES_128_GCM_TYPE, "AES-128-GCM", NID_aes_128_gcm},
+    #endif
+    #ifdef WOLFSSL_AES_192
+    {AES_192_GCM_TYPE, "AES-192-GCM", NID_aes_192_gcm},
+    #endif
+    #ifdef WOLFSSL_AES_256
+    {AES_256_GCM_TYPE, "AES-256-GCM", NID_aes_256_gcm},
+    #endif
+    #ifdef WOLFSSL_AES_128
+        {AES_128_CTR_TYPE, "AES-128-CTR", NID_aes_128_ctr},
+    #endif
+    #ifdef WOLFSSL_AES_192
+        {AES_192_CTR_TYPE, "AES-192-CTR", NID_aes_192_ctr},
+    #endif
+    #ifdef WOLFSSL_AES_256
+        {AES_256_CTR_TYPE, "AES-256-CTR", NID_aes_256_ctr},
+    #endif
+
+    #ifdef WOLFSSL_AES_128
+        {AES_128_ECB_TYPE, "AES-128-ECB", NID_aes_128_ecb},
+    #endif
+    #ifdef WOLFSSL_AES_192
+        {AES_192_ECB_TYPE, "AES-192-ECB", NID_aes_192_ecb},
+    #endif
+    #ifdef WOLFSSL_AES_256
+        {AES_256_ECB_TYPE, "AES-256-ECB", NID_aes_256_ecb},
+    #endif
+
+#endif
+
+#ifndef NO_DES3
+    {DES_CBC_TYPE, "DES-CBC", NID_des_cbc},
+    {DES_ECB_TYPE, "DES-ECB", NID_des_ecb},
+
+    {DES_EDE3_CBC_TYPE, "DES-EDE3-CBC", NID_des_ede3_cbc},
+    {DES_EDE3_ECB_TYPE, "DES-EDE3-ECB", NID_des_ede3_ecb},
+#endif
+
+#ifndef NO_RC4
+    {ARC4_TYPE, "ARC4", NID_undef},
+#endif
+
+#ifdef HAVE_IDEA
+    {IDEA_CBC_TYPE, "IDEA-CBC", NID_idea_cbc},
+#endif
+    { 0, NULL, 0}
+};
+
+/* returns cipher using provided ctx type */
+const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_CIPHER_CTX_cipher(
+    const WOLFSSL_EVP_CIPHER_CTX *ctx)
+{
+    const struct cipher* c;
+
+    if (!ctx || !ctx->cipherType) {
+        return NULL;
+    }
+
+    for (c = cipher_tbl; c->type != 0; c++) {
+        if (ctx->cipherType == c->type) {
+            return wolfSSL_EVP_get_cipherbyname(c->name);
+        }
+    }
+
+    return NULL;
+}
+
+int wolfSSL_EVP_CIPHER_nid(const WOLFSSL_EVP_CIPHER *cipher)
+{
+    const struct cipher* c;
+
+    if (!cipher) {
+        return 0;
+    }
+
+    for (c = cipher_tbl; c->type != 0; c++) {
+        if (XSTRNCMP(cipher, c->name, XSTRLEN(c->name)+1) == 0) {
+            return c->nid;
+        }
+    }
+
+    return 0;
+}
+
+const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_get_cipherbyname(const char *name)
+{
+
+    static const struct alias {
+        const char *name;
+        const char *alias;
+    } alias_tbl[] =
+    {
+#ifndef NO_DES3
+        {"DES-CBC", "DES"},
+        {"DES-CBC", "des"},
+        {"DES-ECB", "DES-ECB"},
+        {"DES-ECB", "des-ecb"},
+        {"DES-EDE3-CBC", "DES3"},
+        {"DES-EDE3-CBC", "des3"},
+        {"DES-EDE3-ECB", "DES-EDE3"},
+        {"DES-EDE3-ECB", "des-ede3"},
+        {"DES-EDE3-ECB", "des-ede3-ecb"},
+#endif
+#ifdef HAVE_IDEA
+        {"IDEA-CBC", "IDEA"},
+        {"IDEA-CBC", "idea"},
+#endif
+#ifndef NO_AES
+    #ifdef HAVE_AES_CBC
+        #ifdef WOLFSSL_AES_128
+        {"AES-128-CBC", "AES128-CBC"},
+        {"AES-128-CBC", "aes128-cbc"},
+        #endif
+        #ifdef WOLFSSL_AES_192
+        {"AES-192-CBC", "AES192-CBC"},
+        {"AES-192-CBC", "aes192-cbc"},
+        #endif
+        #ifdef WOLFSSL_AES_256
+        {"AES-256-CBC", "AES256-CBC"},
+        {"AES-256-CBC", "aes256-cbc"},
+        #endif
+    #endif
+    #ifdef WOLFSSL_AES_128
+        {"AES-128-ECB", "AES128-ECB"},
+        {"AES-128-ECB", "aes128-ecb"},
+    #endif
+    #ifdef WOLFSSL_AES_192
+        {"AES-192-ECB", "AES192-ECB"},
+        {"AES-192-ECB", "aes192-ecb"},
+    #endif
+    #ifdef WOLFSSL_AES_256
+        {"AES-256-ECB", "AES256-ECB"},
+    #endif
+    #ifdef HAVE_AESGCM
+        #ifdef WOLFSSL_AES_128
+        {"AES-128-GCM", "aes-128-gcm"},
+        {"AES-128-GCM", "id-aes128-GCM"},
+        #endif
+        #ifdef WOLFSSL_AES_192
+        {"AES-192-GCM", "aes-192-gcm"},
+        {"AES-192-GCM", "id-aes192-GCM"},
+        #endif
+        #ifdef WOLFSSL_AES_256
+        {"AES-256-GCM", "aes-256-gcm"},
+        {"AES-256-GCM", "id-aes256-GCM"},
+        #endif
+    #endif
+#endif
+#ifndef NO_RC4
+        {"ARC4", "RC4"},
+#endif
+        { NULL, NULL}
+    };
+
+    const struct cipher *ent;
+    const struct alias  *al;
+
+    WOLFSSL_ENTER("EVP_get_cipherbyname");
+
+    for( al = alias_tbl; al->name != NULL; al++)
+        if(XSTRNCMP(name, al->alias, XSTRLEN(al->alias)+1) == 0) {
+            name = al->name;
+            break;
+        }
+
+    for( ent = cipher_tbl; ent->name != NULL; ent++)
+        if(XSTRNCMP(name, ent->name, XSTRLEN(ent->name)+1) == 0) {
+            return (WOLFSSL_EVP_CIPHER *)ent->name;
+        }
+
+    return NULL;
+}
+
+/*
+ * return an EVP_CIPHER structure when cipher NID is passed.
+ *
+ * id  cipher NID
+ *
+ * return WOLFSSL_EVP_CIPHER
+*/
+const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_get_cipherbynid(int id)
+{
+    WOLFSSL_ENTER("EVP_get_cipherbynid");
+
+    switch(id) {
+
+#ifndef NO_AES
+    #ifdef HAVE_AES_CBC
+        #ifdef WOLFSSL_AES_128
+        case NID_aes_128_cbc:
+            return wolfSSL_EVP_aes_128_cbc();
+        #endif
+        #ifdef WOLFSSL_AES_192
+        case NID_aes_192_cbc:
+            return wolfSSL_EVP_aes_192_cbc();
+        #endif
+        #ifdef WOLFSSL_AES_256
+        case NID_aes_256_cbc:
+            return wolfSSL_EVP_aes_256_cbc();
+        #endif
+    #endif
+    #ifdef WOLFSSL_AES_COUNTER
+        #ifdef WOLFSSL_AES_128
+        case NID_aes_128_ctr:
+            return wolfSSL_EVP_aes_128_ctr();
+        #endif
+        #ifdef WOLFSSL_AES_192
+        case NID_aes_192_ctr:
+            return wolfSSL_EVP_aes_192_ctr();
+        #endif
+        #ifdef WOLFSSL_AES_256
+        case NID_aes_256_ctr:
+            return wolfSSL_EVP_aes_256_ctr();
+        #endif
+    #endif /* WOLFSSL_AES_COUNTER */
+    #ifdef HAVE_AES_ECB
+        #ifdef WOLFSSL_AES_128
+        case NID_aes_128_ecb:
+            return wolfSSL_EVP_aes_128_ecb();
+        #endif
+        #ifdef WOLFSSL_AES_192
+        case NID_aes_192_ecb:
+            return wolfSSL_EVP_aes_192_ecb();
+        #endif
+        #ifdef WOLFSSL_AES_256
+        case NID_aes_256_ecb:
+            return wolfSSL_EVP_aes_256_ecb();
+        #endif
+    #endif /* HAVE_AES_ECB */
+    #ifdef HAVE_AESGCM
+        #ifdef WOLFSSL_AES_128
+        case NID_aes_128_gcm:
+            return wolfSSL_EVP_aes_128_gcm();
+        #endif
+        #ifdef WOLFSSL_AES_192
+        case NID_aes_192_gcm:
+            return wolfSSL_EVP_aes_192_gcm();
+        #endif
+        #ifdef WOLFSSL_AES_256
+        case NID_aes_256_gcm:
+            return wolfSSL_EVP_aes_256_gcm();
+        #endif
+    #endif
+#endif
+
+#ifndef NO_DES3
+        case NID_des_cbc:
+            return wolfSSL_EVP_des_cbc();
+#ifdef WOLFSSL_DES_ECB
+        case NID_des_ecb:
+            return wolfSSL_EVP_des_ecb();
+#endif
+        case NID_des_ede3_cbc:
+            return wolfSSL_EVP_des_ede3_cbc();
+#ifdef WOLFSSL_DES_ECB
+        case NID_des_ede3_ecb:
+            return wolfSSL_EVP_des_ede3_ecb();
+#endif
+#endif /*NO_DES3*/
+
+#ifdef HAVE_IDEA
+        case NID_idea_cbc:
+            return wolfSSL_EVP_idea_cbc();
+#endif
+
+        default:
+            WOLFSSL_MSG("Bad cipher id value");
+    }
+
+    return NULL;
+}
+
+void wolfSSL_EVP_init(void)
+{
+#ifndef NO_AES
+    #ifdef HAVE_AES_CBC
+        #ifdef WOLFSSL_AES_128
+        EVP_AES_128_CBC = (char *)EVP_get_cipherbyname("AES-128-CBC");
+        #endif
+        #ifdef WOLFSSL_AES_192
+        EVP_AES_192_CBC = (char *)EVP_get_cipherbyname("AES-192-CBC");
+        #endif
+        #ifdef WOLFSSL_AES_256
+        EVP_AES_256_CBC = (char *)EVP_get_cipherbyname("AES-256-CBC");
+        #endif
+    #endif /* HAVE_AES_CBC */
+
+    #ifdef WOLFSSL_AES_CFB
+        #ifdef WOLFSSL_AES_128
+        EVP_AES_128_CFB1 = (char *)EVP_get_cipherbyname("AES-128-CFB1");
+        #endif
+
+        #ifdef WOLFSSL_AES_192
+        EVP_AES_192_CFB1 = (char *)EVP_get_cipherbyname("AES-192-CFB1");
+        #endif
+
+        #ifdef WOLFSSL_AES_256
+        EVP_AES_256_CFB1 = (char *)EVP_get_cipherbyname("AES-256-CFB1");
+        #endif
+
+        #ifdef WOLFSSL_AES_128
+        EVP_AES_128_CFB8 = (char *)EVP_get_cipherbyname("AES-128-CFB8");
+        #endif
+
+        #ifdef WOLFSSL_AES_192
+        EVP_AES_192_CFB8 = (char *)EVP_get_cipherbyname("AES-192-CFB8");
+        #endif
+
+        #ifdef WOLFSSL_AES_256
+        EVP_AES_256_CFB8 = (char *)EVP_get_cipherbyname("AES-256-CFB8");
+        #endif
+
+        #ifdef WOLFSSL_AES_128
+        EVP_AES_128_CFB128 = (char *)EVP_get_cipherbyname("AES-128-CFB128");
+        #endif
+
+        #ifdef WOLFSSL_AES_192
+        EVP_AES_192_CFB128 = (char *)EVP_get_cipherbyname("AES-192-CFB128");
+        #endif
+
+        #ifdef WOLFSSL_AES_256
+        EVP_AES_256_CFB128 = (char *)EVP_get_cipherbyname("AES-256-CFB128");
+        #endif
+    #endif /* WOLFSSL_AES_CFB */
+
+    #ifdef WOLFSSL_AES_OFB
+        #ifdef WOLFSSL_AES_128
+        EVP_AES_128_OFB = (char *)EVP_get_cipherbyname("AES-128-OFB");
+        #endif
+
+        #ifdef WOLFSSL_AES_192
+        EVP_AES_192_OFB = (char *)EVP_get_cipherbyname("AES-192-OFB");
+        #endif
+
+        #ifdef WOLFSSL_AES_256
+        EVP_AES_256_OFB = (char *)EVP_get_cipherbyname("AES-256-OFB");
+        #endif
+    #endif /* WOLFSSL_AES_OFB */
+
+    #ifdef WOLFSSL_AES_XTS
+        #ifdef WOLFSSL_AES_128
+        EVP_AES_128_XTS = (char *)EVP_get_cipherbyname("AES-128-XTS");
+        #endif
+
+        #ifdef WOLFSSL_AES_256
+        EVP_AES_256_XTS = (char *)EVP_get_cipherbyname("AES-256-XTS");
+        #endif
+    #endif /* WOLFSSL_AES_XTS */
+
+    #ifdef HAVE_AESGCM
+        #ifdef WOLFSSL_AES_128
+        EVP_AES_128_GCM = (char *)EVP_get_cipherbyname("AES-128-GCM");
+        #endif
+        #ifdef WOLFSSL_AES_192
+        EVP_AES_192_GCM = (char *)EVP_get_cipherbyname("AES-192-GCM");
+        #endif
+        #ifdef WOLFSSL_AES_256
+        EVP_AES_256_GCM = (char *)EVP_get_cipherbyname("AES-256-GCM");
+        #endif
+    #endif /* HAVE_AESGCM*/
+        #ifdef WOLFSSL_AES_128
+        EVP_AES_128_CTR = (char *)EVP_get_cipherbyname("AES-128-CTR");
+        #endif
+        #ifdef WOLFSSL_AES_192
+        EVP_AES_192_CTR = (char *)EVP_get_cipherbyname("AES-192-CTR");
+        #endif
+        #ifdef WOLFSSL_AES_256
+        EVP_AES_256_CTR = (char *)EVP_get_cipherbyname("AES-256-CTR");
+        #endif
+
+        #ifdef WOLFSSL_AES_128
+        EVP_AES_128_ECB = (char *)EVP_get_cipherbyname("AES-128-ECB");
+        #endif
+        #ifdef WOLFSSL_AES_192
+        EVP_AES_192_ECB = (char *)EVP_get_cipherbyname("AES-192-ECB");
+        #endif
+        #ifdef WOLFSSL_AES_256
+        EVP_AES_256_ECB = (char *)EVP_get_cipherbyname("AES-256-ECB");
+        #endif
+#endif /* ifndef NO_AES*/
+
+#ifndef NO_DES3
+    EVP_DES_CBC = (char *)EVP_get_cipherbyname("DES-CBC");
+    EVP_DES_ECB = (char *)EVP_get_cipherbyname("DES-ECB");
+
+    EVP_DES_EDE3_CBC = (char *)EVP_get_cipherbyname("DES-EDE3-CBC");
+    EVP_DES_EDE3_ECB = (char *)EVP_get_cipherbyname("DES-EDE3-ECB");
+#endif
+
+#ifdef HAVE_IDEA
+    EVP_IDEA_CBC = (char *)EVP_get_cipherbyname("IDEA-CBC");
+#endif
+}
+
+#if !defined(NO_PWDBASED)
+int wolfSSL_EVP_get_hashinfo(const WOLFSSL_EVP_MD* evp,
+    int* pHash, int* pHashSz)
+{
+    enum wc_HashType hash = WC_HASH_TYPE_NONE;
+    int hashSz;
+
+    if (XSTRLEN(evp) < 3) {
+        /* do not try comparing strings if size is too small */
+        return WOLFSSL_FAILURE;
+    }
+
+    if (XSTRNCMP("SHA", evp, 3) == 0) {
+        if (XSTRLEN(evp) > 3) {
+        #ifndef NO_SHA256
+            if (XSTRNCMP("SHA256", evp, 6) == 0) {
+                hash = WC_HASH_TYPE_SHA256;
+            }
+            else
+        #endif
+        #ifdef WOLFSSL_SHA384
+            if (XSTRNCMP("SHA384", evp, 6) == 0) {
+                hash = WC_HASH_TYPE_SHA384;
+            }
+            else
+        #endif
+        #ifdef WOLFSSL_SHA512
+            if (XSTRNCMP("SHA512", evp, 6) == 0) {
+                hash = WC_HASH_TYPE_SHA512;
+            }
+            else
+        #endif
+            {
+                WOLFSSL_MSG("Unknown SHA hash");
+            }
+        }
+        else {
+            hash = WC_HASH_TYPE_SHA;
+        }
+    }
+#ifdef WOLFSSL_MD2
+    else if (XSTRNCMP("MD2", evp, 3) == 0) {
+        hash = WC_HASH_TYPE_MD2;
+    }
+#endif
+#ifndef NO_MD4
+    else if (XSTRNCMP("MD4", evp, 3) == 0) {
+        hash = WC_HASH_TYPE_MD4;
+    }
+#endif
+#ifndef NO_MD5
+    else if (XSTRNCMP("MD5", evp, 3) == 0) {
+        hash = WC_HASH_TYPE_MD5;
+    }
+#endif
+
+    if (pHash)
+        *pHash = hash;
+
+    hashSz = wc_HashGetDigestSize(hash);
+    if (pHashSz)
+        *pHashSz = hashSz;
+
+    if (hashSz < 0) {
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* this function makes the assumption that out buffer is big enough for digest*/
+int wolfSSL_EVP_Digest(const unsigned char* in, int inSz, unsigned char* out,
+                              unsigned int* outSz, const WOLFSSL_EVP_MD* evp,
+                              WOLFSSL_ENGINE* eng)
+{
+    int err;
+    int hashType = WC_HASH_TYPE_NONE;
+    int hashSz;
+
+    WOLFSSL_ENTER("wolfSSL_EVP_Digest");
+    if (in == NULL || out == NULL || evp == NULL) {
+        WOLFSSL_MSG("Null argument passed in");
+        return WOLFSSL_FAILURE;
+    }
+
+    err = wolfSSL_EVP_get_hashinfo(evp, &hashType, &hashSz);
+    if (err != WOLFSSL_SUCCESS)
+        return err;
+
+    if (wc_Hash((enum wc_HashType)hashType, in, inSz, out, hashSz) != 0) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if (outSz != NULL)
+        *outSz = hashSz;
+
+    (void)eng;
+    return WOLFSSL_SUCCESS;
+}
+#endif
+
+const WOLFSSL_EVP_MD *wolfSSL_EVP_get_digestbyname(const char *name)
+{
+    static const struct alias {
+        const char *name;
+        const char *alias;
+    } alias_tbl[] =
+    {
+        {"MD4", "ssl3-md4"},
+        {"MD5", "ssl3-md5"},
+        {"SHA", "ssl3-sha1"},
+        {"SHA", "SHA1"},
+        { NULL, NULL}
+    };
+
+    const struct alias  *al;
+    const struct s_ent *ent;
+
+
+    for (al = alias_tbl; al->name != NULL; al++)
+        if(XSTRNCMP(name, al->alias, XSTRLEN(al->alias)+1) == 0) {
+            name = al->name;
+            break;
+        }
+
+    for (ent = md_tbl; ent->name != NULL; ent++)
+        if(XSTRNCMP(name, ent->name, XSTRLEN(ent->name)+1) == 0) {
+            return (EVP_MD *)ent->name;
+        }
+    return NULL;
+}
+
+int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md)
+{
+    const struct s_ent *ent ;
+    WOLFSSL_ENTER("EVP_MD_type");
+    for( ent = md_tbl; ent->name != NULL; ent++){
+        if(XSTRNCMP((const char *)md, ent->name, XSTRLEN(ent->name)+1) == 0) {
+            return ent->nid;
+        }
+    }
+    return 0;
+}
+
+#ifndef NO_MD4
+
+    /* return a pointer to MD4 EVP type */
+    const WOLFSSL_EVP_MD* wolfSSL_EVP_md4(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_md4");
+        return EVP_get_digestbyname("MD4");
+    }
+
+#endif /* !NO_MD4 */
+
+
+#ifndef NO_MD5
+
+    const WOLFSSL_EVP_MD* wolfSSL_EVP_md5(void)
+    {
+        WOLFSSL_ENTER("EVP_md5");
+        return EVP_get_digestbyname("MD5");
+    }
+
+#endif /* !NO_MD5 */
+
+
+#ifndef NO_WOLFSSL_STUB
+    const WOLFSSL_EVP_MD* wolfSSL_EVP_mdc2(void)
+    {
+        WOLFSSL_STUB("EVP_mdc2");
+        return NULL;
+    }
+#endif
+
+#ifndef NO_SHA
+    const WOLFSSL_EVP_MD* wolfSSL_EVP_sha1(void)
+    {
+        WOLFSSL_ENTER("EVP_sha1");
+        return EVP_get_digestbyname("SHA");
+    }
+#endif /* NO_SHA */
+
+#ifdef WOLFSSL_SHA224
+
+    const WOLFSSL_EVP_MD* wolfSSL_EVP_sha224(void)
+    {
+        WOLFSSL_ENTER("EVP_sha224");
+        return EVP_get_digestbyname("SHA224");
+    }
+
+#endif /* WOLFSSL_SHA224 */
+
+
+    const WOLFSSL_EVP_MD* wolfSSL_EVP_sha256(void)
+    {
+        WOLFSSL_ENTER("EVP_sha256");
+        return EVP_get_digestbyname("SHA256");
+    }
+
+#ifdef WOLFSSL_SHA384
+
+    const WOLFSSL_EVP_MD* wolfSSL_EVP_sha384(void)
+    {
+        WOLFSSL_ENTER("EVP_sha384");
+        return EVP_get_digestbyname("SHA384");
+    }
+
+#endif /* WOLFSSL_SHA384 */
+
+#ifdef WOLFSSL_SHA512
+
+    const WOLFSSL_EVP_MD* wolfSSL_EVP_sha512(void)
+    {
+        WOLFSSL_ENTER("EVP_sha512");
+        return EVP_get_digestbyname("SHA512");
+    }
+
+#endif /* WOLFSSL_SHA512 */
+
+#ifdef WOLFSSL_SHA3
+#ifndef WOLFSSL_NOSHA3_224
+    const WOLFSSL_EVP_MD* wolfSSL_EVP_sha3_224(void)
+    {
+        WOLFSSL_ENTER("EVP_sha3_224");
+        return EVP_get_digestbyname("SHA3_224");
+    }
+#endif /* WOLFSSL_NOSHA3_224 */
+
+
+#ifndef WOLFSSL_NOSHA3_256
+    const WOLFSSL_EVP_MD* wolfSSL_EVP_sha3_256(void)
+    {
+        WOLFSSL_ENTER("EVP_sha3_256");
+        return EVP_get_digestbyname("SHA3_256");
+    }
+#endif /* WOLFSSL_NOSHA3_256 */
+
+    const WOLFSSL_EVP_MD* wolfSSL_EVP_sha3_384(void)
+    {
+        WOLFSSL_ENTER("EVP_sha3_384");
+        return EVP_get_digestbyname("SHA3_384");
+    }
+
+#ifndef WOLFSSL_NOSHA3_512
+    const WOLFSSL_EVP_MD* wolfSSL_EVP_sha3_512(void)
+    {
+        WOLFSSL_ENTER("EVP_sha3_512");
+        return EVP_get_digestbyname("SHA3_512");
+    }
+#endif /* WOLFSSL_NOSHA3_512 */
+#endif /* WOLFSSL_SHA3 */
+
+    WOLFSSL_EVP_MD_CTX *wolfSSL_EVP_MD_CTX_new(void)
+    {
+        WOLFSSL_EVP_MD_CTX* ctx;
+        WOLFSSL_ENTER("EVP_MD_CTX_new");
+        ctx = (WOLFSSL_EVP_MD_CTX*)XMALLOC(sizeof *ctx, NULL,
+                                                       DYNAMIC_TYPE_OPENSSL);
+        if (ctx){
+            wolfSSL_EVP_MD_CTX_init(ctx);
+        }
+        return ctx;
+    }
+
+    WOLFSSL_API void wolfSSL_EVP_MD_CTX_free(WOLFSSL_EVP_MD_CTX *ctx)
+    {
+        if (ctx) {
+            WOLFSSL_ENTER("EVP_MD_CTX_free");
+                wolfSSL_EVP_MD_CTX_cleanup(ctx);
+                XFREE(ctx, NULL, DYNAMIC_TYPE_OPENSSL);
+            }
+    }
+
+    /* returns the NID of message digest used by the ctx */
+    int wolfSSL_EVP_MD_CTX_type(const WOLFSSL_EVP_MD_CTX *ctx) {
+        const struct s_ent *ent;
+
+        WOLFSSL_ENTER("EVP_MD_CTX_type");
+
+        if (ctx) {
+            for(ent = md_tbl; ent->name != NULL; ent++) {
+                if (ctx->macType == ent->macType) {
+                    return ent->nid;
+                }
+            }
+            /* Return whatever we got */
+            return ctx->macType;
+        }
+        return 0;
+    }
+
+
+    /* returns WOLFSSL_SUCCESS on success */
+    int wolfSSL_EVP_MD_CTX_copy(WOLFSSL_EVP_MD_CTX *out, const WOLFSSL_EVP_MD_CTX *in)
+    {
+        return wolfSSL_EVP_MD_CTX_copy_ex(out, in);
+    }
+
+    /* returns digest size */
+    int wolfSSL_EVP_MD_CTX_size(const WOLFSSL_EVP_MD_CTX *ctx) {
+        return(wolfSSL_EVP_MD_size(wolfSSL_EVP_MD_CTX_md(ctx)));
+    }
+    /* returns block size */
+    int wolfSSL_EVP_MD_CTX_block_size(const WOLFSSL_EVP_MD_CTX *ctx) {
+        return(wolfSSL_EVP_MD_block_size(wolfSSL_EVP_MD_CTX_md(ctx)));
+    }
+
+    /* Deep copy of EVP_MD hasher
+     * return WOLFSSL_SUCCESS on success */
+    static int wolfSSL_EVP_MD_Copy_Hasher(WOLFSSL_EVP_MD_CTX* des,
+            const WOLFSSL_EVP_MD_CTX* src)
+    {
+        if (src->macType == NID_hmac) {
+            wolfSSL_HmacCopy(&des->hash.hmac, (Hmac*)&src->hash.hmac);
+        }
+        else {
+            switch (src->macType) {
+            #ifndef NO_MD5
+                case WC_HASH_TYPE_MD5:
+                    wc_Md5Copy((wc_Md5*)&src->hash.digest,
+                            (wc_Md5*)&des->hash.digest);
+                    break;
+            #endif /* !NO_MD5 */
+
+            #ifndef NO_SHA
+                case WC_HASH_TYPE_SHA:
+                    wc_ShaCopy((wc_Sha*)&src->hash.digest,
+                            (wc_Sha*)&des->hash.digest);
+                    break;
+            #endif /* !NO_SHA */
+
+            #ifdef WOLFSSL_SHA224
+                case WC_HASH_TYPE_SHA224:
+                    wc_Sha224Copy((wc_Sha224*)&src->hash.digest,
+                            (wc_Sha224*)&des->hash.digest);
+                    break;
+            #endif /* WOLFSSL_SHA224 */
+
+            #ifndef NO_SHA256
+                case WC_HASH_TYPE_SHA256:
+                    wc_Sha256Copy((wc_Sha256*)&src->hash.digest,
+                            (wc_Sha256*)&des->hash.digest);
+                    break;
+            #endif /* !NO_SHA256 */
+
+            #ifdef WOLFSSL_SHA384
+                case WC_HASH_TYPE_SHA384:
+                    wc_Sha384Copy((wc_Sha384*)&src->hash.digest,
+                            (wc_Sha384*)&des->hash.digest);
+                    break;
+            #endif /* WOLFSSL_SHA384 */
+            #ifdef WOLFSSL_SHA512
+                case WC_HASH_TYPE_SHA512:
+                    wc_Sha512Copy((wc_Sha512*)&src->hash.digest,
+                        (wc_Sha512*)&des->hash.digest);
+                    break;
+            #endif /* WOLFSSL_SHA512 */
+        #ifdef WOLFSSL_SHA3
+            #ifndef WOLFSSL_NOSHA3_224
+                case WC_HASH_TYPE_SHA3_224:
+                    wc_Sha3_224_Copy((wc_Sha3*)&src->hash.digest,
+                            (wc_Sha3*)&des->hash.digest);
+                    break;
+            #endif
+
+            #ifndef WOLFSSL_NOSHA3_256
+                case WC_HASH_TYPE_SHA3_256:
+                    wc_Sha3_256_Copy((wc_Sha3*)&src->hash.digest,
+                            (wc_Sha3*)&des->hash.digest);
+                    break;
+            #endif
+
+                case WC_HASH_TYPE_SHA3_384:
+                    wc_Sha3_384_Copy((wc_Sha3*)&src->hash.digest,
+                            (wc_Sha3*)&des->hash.digest);
+                    break;
+
+            #ifndef WOLFSSL_NOSHA3_512
+                case WC_HASH_TYPE_SHA3_512:
+                    wc_Sha3_512_Copy((wc_Sha3*)&src->hash.digest,
+                        (wc_Sha3*)&des->hash.digest);
+                    break;
+            #endif
+        #endif
+                default:
+                    return WOLFSSL_FAILURE;
+            }
+        }
+        return WOLFSSL_SUCCESS;
+    }
+
+    /* copies structure in to the structure out
+     *
+     * returns WOLFSSL_SUCCESS on success */
+    int wolfSSL_EVP_MD_CTX_copy_ex(WOLFSSL_EVP_MD_CTX *out, const WOLFSSL_EVP_MD_CTX *in)
+    {
+        if ((out == NULL) || (in == NULL)) return WOLFSSL_FAILURE;
+        WOLFSSL_ENTER("EVP_CIPHER_MD_CTX_copy_ex");
+        XMEMCPY(out, in, sizeof(WOLFSSL_EVP_MD_CTX));
+        if (in->pctx != NULL) {
+            out->pctx = wolfSSL_EVP_PKEY_CTX_new(in->pctx->pkey, NULL);
+            if (out->pctx == NULL)
+                return WOLFSSL_FAILURE;
+        }
+        return wolfSSL_EVP_MD_Copy_Hasher(out, (WOLFSSL_EVP_MD_CTX*)in);
+    }
+
+    void wolfSSL_EVP_MD_CTX_init(WOLFSSL_EVP_MD_CTX* ctx)
+    {
+        WOLFSSL_ENTER("EVP_CIPHER_MD_CTX_init");
+        XMEMSET(ctx, 0, sizeof(WOLFSSL_EVP_MD_CTX));
+    }
+
+    const WOLFSSL_EVP_MD *wolfSSL_EVP_MD_CTX_md(const WOLFSSL_EVP_MD_CTX *ctx)
+    {
+        const struct s_ent *ent;
+        if (ctx == NULL)
+            return NULL;
+        WOLFSSL_ENTER("EVP_MD_CTX_md");
+        for(ent = md_tbl; ent->name != NULL; ent++) {
+            if(ctx->macType == ent->macType) {
+                return (const WOLFSSL_EVP_MD *)ent->name;
+            }
+        }
+        return (WOLFSSL_EVP_MD *)NULL;
+    }
+
+    #ifndef NO_AES
+
+    #ifdef HAVE_AES_CBC
+    #ifdef WOLFSSL_AES_128
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cbc(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_128_cbc");
+        if (EVP_AES_128_CBC == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_128_CBC;
+    }
+    #endif /* WOLFSSL_AES_128 */
+
+
+    #ifdef WOLFSSL_AES_192
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cbc(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_192_cbc");
+        if (EVP_AES_192_CBC == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_192_CBC;
+    }
+    #endif /* WOLFSSL_AES_192 */
+
+
+    #ifdef WOLFSSL_AES_256
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cbc(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_256_cbc");
+        if (EVP_AES_256_CBC == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_256_CBC;
+    }
+    #endif /* WOLFSSL_AES_256 */
+    #endif /* HAVE_AES_CBC */
+
+    #ifdef WOLFSSL_AES_CFB
+#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS)
+    #ifdef WOLFSSL_AES_128
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cfb1(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_128_cfb1");
+        if (EVP_AES_128_CFB1 == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_128_CFB1;
+    }
+    #endif /* WOLFSSL_AES_128 */
+
+    #ifdef WOLFSSL_AES_192
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cfb1(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_192_cfb1");
+        if (EVP_AES_192_CFB1 == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_192_CFB1;
+    }
+    #endif /* WOLFSSL_AES_192 */
+
+    #ifdef WOLFSSL_AES_256
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cfb1(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_256_cfb1");
+        if (EVP_AES_256_CFB1 == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_256_CFB1;
+    }
+    #endif /* WOLFSSL_AES_256 */
+
+    #ifdef WOLFSSL_AES_128
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cfb8(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_128_cfb8");
+        if (EVP_AES_128_CFB8 == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_128_CFB8;
+    }
+    #endif /* WOLFSSL_AES_128 */
+
+    #ifdef WOLFSSL_AES_192
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cfb8(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_192_cfb8");
+        if (EVP_AES_192_CFB8 == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_192_CFB8;
+    }
+    #endif /* WOLFSSL_AES_192 */
+
+    #ifdef WOLFSSL_AES_256
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cfb8(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_256_cfb8");
+        if (EVP_AES_256_CFB8 == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_256_CFB8;
+    }
+    #endif /* WOLFSSL_AES_256 */
+#endif /* !HAVE_SELFTEST && !HAVE_FIPS */
+
+    #ifdef WOLFSSL_AES_128
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cfb128(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_128_cfb128");
+        if (EVP_AES_128_CFB128 == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_128_CFB128;
+    }
+    #endif /* WOLFSSL_AES_128 */
+
+    #ifdef WOLFSSL_AES_192
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cfb128(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_192_cfb128");
+        if (EVP_AES_192_CFB128 == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_192_CFB128;
+    }
+    #endif /* WOLFSSL_AES_192 */
+
+    #ifdef WOLFSSL_AES_256
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cfb128(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_256_cfb128");
+        if (EVP_AES_256_CFB128 == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_256_CFB128;
+    }
+    #endif /* WOLFSSL_AES_256 */
+    #endif /* WOLFSSL_AES_CFB */
+
+    #ifdef WOLFSSL_AES_OFB
+    #ifdef WOLFSSL_AES_128
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ofb(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_128_ofb");
+        if (EVP_AES_128_OFB == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_128_OFB;
+    }
+    #endif /* WOLFSSL_AES_128 */
+
+    #ifdef WOLFSSL_AES_192
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ofb(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_192_ofb");
+        if (EVP_AES_192_OFB == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_192_OFB;
+    }
+    #endif /* WOLFSSL_AES_192 */
+
+    #ifdef WOLFSSL_AES_256
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ofb(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_256_ofb");
+        if (EVP_AES_256_OFB == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_256_OFB;
+    }
+    #endif /* WOLFSSL_AES_256 */
+    #endif /* WOLFSSL_AES_OFB */
+
+    #ifdef WOLFSSL_AES_XTS
+    #ifdef WOLFSSL_AES_128
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_xts(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_128_xts");
+        if (EVP_AES_128_XTS == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_128_XTS;
+    }
+    #endif /* WOLFSSL_AES_128 */
+
+    #ifdef WOLFSSL_AES_256
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_xts(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_256_xts");
+        if (EVP_AES_256_XTS == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_256_XTS;
+    }
+    #endif /* WOLFSSL_AES_256 */
+    #endif /* WOLFSSL_AES_XTS */
+
+    #ifdef HAVE_AESGCM
+    #ifdef WOLFSSL_AES_128
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_gcm(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_128_gcm");
+        if (EVP_AES_128_GCM == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_128_GCM;
+    }
+    #endif /* WOLFSSL_GCM_128 */
+
+    #ifdef WOLFSSL_AES_192
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_gcm(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_192_gcm");
+        if (EVP_AES_192_GCM == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_192_GCM;
+    }
+    #endif /* WOLFSSL_AES_192 */
+
+    #ifdef WOLFSSL_AES_256
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_gcm(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_256_gcm");
+        if (EVP_AES_256_GCM == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_256_GCM;
+    }
+    #endif /* WOLFSSL_AES_256 */
+    #endif /* HAVE_AESGCM */
+
+    #ifdef WOLFSSL_AES_128
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ctr(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_128_ctr");
+        if (EVP_AES_128_CTR == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_128_CTR;
+    }
+    #endif /* WOLFSSL_AES_2128 */
+
+
+    #ifdef WOLFSSL_AES_192
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ctr(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_192_ctr");
+        if (EVP_AES_192_CTR == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_192_CTR;
+    }
+    #endif /* WOLFSSL_AES_192 */
+
+
+    #ifdef WOLFSSL_AES_256
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ctr(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_256_ctr");
+        if (EVP_AES_256_CTR == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_256_CTR;
+    }
+    #endif /* WOLFSSL_AES_256 */
+
+    #ifdef WOLFSSL_AES_128
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ecb(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_128_ecb");
+        if (EVP_AES_128_ECB == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_128_ECB;
+    }
+    #endif /* WOLFSSL_AES_128 */
+
+
+    #ifdef WOLFSSL_AES_192
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ecb(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_192_ecb");
+        if (EVP_AES_192_ECB == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_192_ECB;
+    }
+    #endif /* WOLFSSL_AES_192*/
+
+
+    #ifdef WOLFSSL_AES_256
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ecb(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_256_ecb");
+        if (EVP_AES_256_ECB == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_256_ECB;
+    }
+    #endif /* WOLFSSL_AES_256 */
+    #endif /* NO_AES */
+
+#ifndef NO_DES3
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_cbc(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_des_cbc");
+        if (EVP_DES_CBC == NULL)
+            wolfSSL_EVP_init();
+        return EVP_DES_CBC;
+    }
+#ifdef WOLFSSL_DES_ECB
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ecb(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_des_ecb");
+        if (EVP_DES_ECB == NULL)
+            wolfSSL_EVP_init();
+        return EVP_DES_ECB;
+    }
+#endif
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ede3_cbc(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_des_ede3_cbc");
+        if (EVP_DES_EDE3_CBC == NULL)
+            wolfSSL_EVP_init();
+        return EVP_DES_EDE3_CBC;
+    }
+#ifdef WOLFSSL_DES_ECB
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ede3_ecb(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_des_ede3_ecb");
+        if (EVP_DES_EDE3_ECB == NULL)
+            wolfSSL_EVP_init();
+        return EVP_DES_EDE3_ECB;
+    }
+#endif
+#endif /* NO_DES3 */
+
+#ifndef NO_RC4
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_rc4(void)
+    {
+        static const char* type = "ARC4";
+        WOLFSSL_ENTER("wolfSSL_EVP_rc4");
+        return type;
+    }
+#endif
+
+#ifdef HAVE_IDEA
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_idea_cbc(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_idea_cbc");
+        if (EVP_IDEA_CBC == NULL)
+            wolfSSL_EVP_init();
+        return EVP_IDEA_CBC;
+    }
+#endif
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_enc_null(void)
+    {
+        static const char* type = "NULL";
+        WOLFSSL_ENTER("wolfSSL_EVP_enc_null");
+        return type;
+    }
+
+    int wolfSSL_EVP_MD_CTX_cleanup(WOLFSSL_EVP_MD_CTX* ctx)
+    {
+        WOLFSSL_ENTER("EVP_MD_CTX_cleanup");
+        if (ctx->pctx != NULL)
+            wolfSSL_EVP_PKEY_CTX_free(ctx->pctx);
+
+        if (ctx->macType == NID_hmac) {
+            wc_HmacFree(&ctx->hash.hmac);
+        }
+        else {
+            switch (ctx->macType) {
+            #ifndef NO_MD5
+                case WC_HASH_TYPE_MD5:
+                    wc_Md5Free((wc_Md5*)&ctx->hash.digest);
+                    break;
+            #endif /* !NO_MD5 */
+
+            #ifndef NO_SHA
+                case WC_HASH_TYPE_SHA:
+                    wc_ShaFree((wc_Sha*)&ctx->hash.digest);
+                    break;
+            #endif /* !NO_SHA */
+
+            #ifdef WOLFSSL_SHA224
+                case WC_HASH_TYPE_SHA224:
+                    wc_Sha224Free((wc_Sha224*)&ctx->hash.digest);
+                    break;
+            #endif /* WOLFSSL_SHA224 */
+
+            #ifndef NO_SHA256
+                case WC_HASH_TYPE_SHA256:
+                    wc_Sha256Free((wc_Sha256*)&ctx->hash.digest);
+                    break;
+            #endif /* !NO_SHA256 */
+
+            #ifdef WOLFSSL_SHA384
+                case WC_HASH_TYPE_SHA384:
+                    wc_Sha384Free((wc_Sha384*)&ctx->hash.digest);
+                    break;
+            #endif /* WOLFSSL_SHA384 */
+            #ifdef WOLFSSL_SHA512
+                case WC_HASH_TYPE_SHA512:
+                    wc_Sha512Free((wc_Sha512*)&ctx->hash.digest);
+                    break;
+            #endif /* WOLFSSL_SHA512 */
+        #ifdef WOLFSSL_SHA3
+            #ifndef WOLFSSL_NOSHA3_224
+                case WC_HASH_TYPE_SHA3_224:
+                    wc_Sha3_224_Free((wc_Sha3*)&ctx->hash.digest);
+                    break;
+            #endif
+
+            #ifndef WOLFSSL_NOSHA3_256
+                case WC_HASH_TYPE_SHA3_256:
+                    wc_Sha3_256_Free((wc_Sha3*)&ctx->hash.digest);
+                    break;
+            #endif
+
+                case WC_HASH_TYPE_SHA3_384:
+                    wc_Sha3_384_Free((wc_Sha3*)&ctx->hash.digest);
+                    break;
+
+            #ifndef WOLFSSL_NOSHA3_512
+                case WC_HASH_TYPE_SHA3_512:
+                    wc_Sha3_512_Free((wc_Sha3*)&ctx->hash.digest);
+                    break;
+            #endif
+        #endif
+                default:
+                    return WOLFSSL_FAILURE;
+            }
+        }
+        ForceZero(ctx, sizeof(*ctx));
+        ctx->macType = WC_HASH_TYPE_NONE;
+        return 1;
+    }
+
+    void wolfSSL_EVP_CIPHER_CTX_init(WOLFSSL_EVP_CIPHER_CTX* ctx)
+    {
+        WOLFSSL_ENTER("EVP_CIPHER_CTX_init");
+        if (ctx) {
+            XMEMSET(ctx, 0, sizeof(WOLFSSL_EVP_CIPHER_CTX));
+            ctx->cipherType = WOLFSSL_EVP_CIPH_TYPE_INIT;   /* not yet initialized */
+            ctx->keyLen     = 0;
+            ctx->enc        = 1;      /* start in encrypt mode */
+        }
+    }
+
+#if defined(HAVE_AESGCM) && !defined(HAVE_SELFTEST)
+    static WC_INLINE void IncCtr(byte* ctr, word32 ctrSz)
+    {
+        int i;
+        for (i = ctrSz-1; i >= 0; i--) {
+            if (++ctr[i])
+                break;
+        }
+    }
+#endif
+
+    /* This function allows cipher specific parameters to be
+    determined and set. */
+    int wolfSSL_EVP_CIPHER_CTX_ctrl(WOLFSSL_EVP_CIPHER_CTX *ctx, int type, \
+                                    int arg, void *ptr)
+    {
+        int ret = WOLFSSL_FAILURE;
+#if defined(HAVE_AESGCM) && !defined(HAVE_SELFTEST) && !defined(WC_NO_RNG)
+        WC_RNG rng;
+#endif
+        if (ctx == NULL)
+            return WOLFSSL_FAILURE;
+
+        (void)arg;
+        (void)ptr;
+
+        WOLFSSL_ENTER("EVP_CIPHER_CTX_ctrl");
+
+        switch(type) {
+            case EVP_CTRL_INIT:
+                wolfSSL_EVP_CIPHER_CTX_init(ctx);
+                if(ctx)
+                    ret = WOLFSSL_SUCCESS;
+                break;
+            case EVP_CTRL_SET_KEY_LENGTH:
+                ret = wolfSSL_EVP_CIPHER_CTX_set_key_length(ctx, arg);
+                break;
+#if defined(HAVE_AESGCM) && !defined(HAVE_SELFTEST) && !defined(WC_NO_RNG)
+            case EVP_CTRL_GCM_SET_IVLEN:
+                if(arg <= 0 || arg > 16)
+                    return WOLFSSL_FAILURE;
+                ret = wolfSSL_EVP_CIPHER_CTX_set_iv_length(ctx, arg);
+                break;
+            case EVP_CTRL_AEAD_SET_IV_FIXED:
+                if (arg == -1) {
+                    /* arg == -1 copies ctx->ivSz from ptr */
+                    ret = wolfSSL_EVP_CIPHER_CTX_set_iv(ctx, (byte*)ptr, ctx->ivSz);
+                }
+                else {
+                    /*
+                     * Fixed field must be at least 4 bytes and invocation
+                     * field at least 8.
+                     */
+                    if ((arg < 4) || (ctx->ivSz - arg) < 8) {
+                        WOLFSSL_MSG("Fixed field or invocation field too short");
+                        ret = WOLFSSL_FAILURE;
+                        break;
+                    }
+                    if (wc_InitRng(&rng) != 0) {
+                        WOLFSSL_MSG("wc_InitRng failed");
+                        ret = WOLFSSL_FAILURE;
+                        break;
+                    }
+                    if (arg) {
+                        XMEMCPY(ctx->iv, ptr, arg);
+                    }
+                    if (wc_RNG_GenerateBlock(&rng, ctx->iv   + arg,
+                                                   ctx->ivSz - arg) != 0) {
+                        /* rng is freed immediately after if block so no need
+                         * to do it here
+                         */
+                        WOLFSSL_MSG("wc_RNG_GenerateBlock failed");
+                        ret = WOLFSSL_FAILURE;
+                    }
+
+                    if (wc_FreeRng(&rng) != 0) {
+                        WOLFSSL_MSG("wc_FreeRng failed");
+                        ret = WOLFSSL_FAILURE;
+                        break;
+                    }
+                }
+                break;
+#if !defined(_WIN32) && !defined(HAVE_FIPS)
+            case EVP_CTRL_GCM_IV_GEN:
+                if (ctx->cipher.aes.keylen == 0 || ctx->ivSz == 0) {
+                    ret = WOLFSSL_FAILURE;
+                    WOLFSSL_MSG("Key or IV not set");
+                    break;
+                }
+                if ((ret = wc_AesGcmSetExtIV(&ctx->cipher.aes, ctx->iv, ctx->ivSz)) != 0) {
+                    WOLFSSL_MSG("wc_AesGcmSetIV failed");
+                    ret = WOLFSSL_FAILURE;
+                }
+                /* OpenSSL increments the IV. Not sure why */
+                IncCtr(ctx->iv, ctx->ivSz);
+                break;
+#endif
+            case EVP_CTRL_AEAD_SET_TAG:
+                if(arg <= 0 || arg > 16 || (ptr == NULL))
+                    return WOLFSSL_FAILURE;
+
+                XMEMCPY(ctx->authTag, ptr, arg);
+                ctx->authTagSz = arg;
+                ret = WOLFSSL_SUCCESS;
+
+                break;
+            case EVP_CTRL_AEAD_GET_TAG:
+                if(arg <= 0 || arg > 16)
+                    return WOLFSSL_FAILURE;
+
+                XMEMCPY(ptr, ctx->authTag, arg);
+                ret = WOLFSSL_SUCCESS;
+                break;
+#endif /* HAVE_AESGCM && !HAVE_SELFTEST && !WC_NO_RNG */
+            default:
+                WOLFSSL_MSG("EVP_CIPHER_CTX_ctrl operation not yet handled");
+                ret = WOLFSSL_FAILURE;
+        }
+        return ret;
+    }
+
+    /* WOLFSSL_SUCCESS on ok */
+    int wolfSSL_EVP_CIPHER_CTX_cleanup(WOLFSSL_EVP_CIPHER_CTX* ctx)
+    {
+        WOLFSSL_ENTER("EVP_CIPHER_CTX_cleanup");
+        if (ctx) {
+            ctx->cipherType = WOLFSSL_EVP_CIPH_TYPE_INIT;  /* not yet initialized  */
+            ctx->keyLen     = 0;
+        }
+
+        return WOLFSSL_SUCCESS;
+    }
+
+    /* Permanent stub for Qt compilation. */
+    #if defined(WOLFSSL_QT) && !defined(NO_WOLFSSL_STUB)
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_rc2_cbc(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_rc2_cbc");
+        WOLFSSL_STUB("EVP_rc2_cbc");
+        return NULL;
+    }
+    #endif
+
+#if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED)
+
+    int wolfSSL_EVP_BytesToKey(const WOLFSSL_EVP_CIPHER* type,
+                       const WOLFSSL_EVP_MD* md, const byte* salt,
+                       const byte* data, int sz, int count, byte* key, byte* iv)
+    {
+        int ret;
+        int hashType = WC_HASH_TYPE_NONE;
+    #ifdef WOLFSSL_SMALL_STACK
+        EncryptedInfo* info;
+    #else
+        EncryptedInfo  info[1];
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
+                                       DYNAMIC_TYPE_ENCRYPTEDINFO);
+        if (info == NULL) {
+            WOLFSSL_MSG("malloc failed");
+            return WOLFSSL_FAILURE;
+        }
+    #endif
+
+        XMEMSET(info, 0, sizeof(EncryptedInfo));
+
+        ret = wc_EncryptedInfoGet(info, type);
+        if (ret < 0)
+            goto end;
+
+        if (data == NULL) {
+            ret = info->keySz;
+            goto end;
+        }
+
+        ret = wolfSSL_EVP_get_hashinfo(md, &hashType, NULL);
+        if (ret == WOLFSSL_FAILURE)
+            goto end;
+
+        ret = wc_PBKDF1_ex(key, info->keySz, iv, info->ivSz, data, sz, salt,
+                           EVP_SALT_SIZE, count, hashType, NULL);
+        if (ret == 0)
+            ret = info->keySz;
+
+    end:
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
+    #endif
+        if (ret < 0)
+            return 0; /* failure - for compatibility */
+
+        return ret;
+    }
+
+#endif /* WOLFSSL_ENCRYPTED_KEYS && !NO_PWDBASED */
+
+#ifndef NO_AES
+    static int   AesSetKey_ex(Aes* aes, const byte* key, word32 len,
+                              const byte* iv, int dir, int direct)
+    {
+        int ret;
+        /* wc_AesSetKey clear aes.reg if iv == NULL.
+           Keep IV for openSSL compatibility */
+        if (iv == NULL)
+            XMEMCPY((byte *)aes->tmp, (byte *)aes->reg, AES_BLOCK_SIZE);
+        if (direct) {
+        #if defined(WOLFSSL_AES_DIRECT)
+            ret = wc_AesSetKeyDirect(aes, key, len, iv, dir);
+        #else
+            ret = NOT_COMPILED_IN;
+        #endif
+        }
+        else {
+            ret = wc_AesSetKey(aes, key, len, iv, dir);
+        }
+        if (iv == NULL)
+            XMEMCPY((byte *)aes->reg, (byte *)aes->tmp, AES_BLOCK_SIZE);
+        return ret;
+    }
+#endif
+
+    /* return WOLFSSL_SUCCESS on ok, 0 on failure to match API compatibility */
+    int  wolfSSL_EVP_CipherInit(WOLFSSL_EVP_CIPHER_CTX* ctx,
+                               const WOLFSSL_EVP_CIPHER* type, const byte* key,
+                               const byte* iv, int enc)
+    {
+        int ret = 0;
+        (void)key;
+        (void)iv;
+        (void)enc;
+
+        WOLFSSL_ENTER("wolfSSL_EVP_CipherInit");
+        if (ctx == NULL) {
+            WOLFSSL_MSG("no ctx");
+            return WOLFSSL_FAILURE;
+        }
+
+        if (type == NULL && ctx->cipherType == WOLFSSL_EVP_CIPH_TYPE_INIT) {
+            WOLFSSL_MSG("no type set");
+            return WOLFSSL_FAILURE;
+        }
+        if (ctx->cipherType == WOLFSSL_EVP_CIPH_TYPE_INIT){
+            /* only first EVP_CipherInit invoke. ctx->cipherType is set below */
+            XMEMSET(&ctx->cipher, 0, sizeof(ctx->cipher));
+            ctx->flags   = 0;
+        }
+        /* always clear buffer state */
+        ctx->bufUsed = 0;
+        ctx->lastUsed = 0;
+
+#ifdef HAVE_WOLFSSL_EVP_CIPHER_CTX_IV
+        if (!iv && ctx->ivSz) {
+            iv = ctx->iv;
+        }
+#endif
+
+#ifndef NO_AES
+    #ifdef HAVE_AES_CBC
+        #ifdef WOLFSSL_AES_128
+        if (ctx->cipherType == AES_128_CBC_TYPE ||
+            (type && XSTRNCMP(type, EVP_AES_128_CBC, EVP_AES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_128_CBC");
+            ctx->cipherType = AES_128_CBC_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CBC_MODE;
+            ctx->keyLen     = 16;
+            ctx->block_size = AES_BLOCK_SIZE;
+            ctx->ivSz       = AES_BLOCK_SIZE;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv,
+                                ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION, 0);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+            if (iv && key == NULL) {
+                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+        }
+        #endif /* WOLFSSL_AES_128 */
+        #ifdef WOLFSSL_AES_192
+        if (ctx->cipherType == AES_192_CBC_TYPE ||
+                 (type && XSTRNCMP(type, EVP_AES_192_CBC, EVP_AES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_192_CBC");
+            ctx->cipherType = AES_192_CBC_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CBC_MODE;
+            ctx->keyLen     = 24;
+            ctx->block_size = AES_BLOCK_SIZE;
+            ctx->ivSz       = AES_BLOCK_SIZE;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv,
+                                ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION, 0);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+            if (iv && key == NULL) {
+                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+        }
+        #endif /* WOLFSSL_AES_192 */
+        #ifdef WOLFSSL_AES_256
+        if (ctx->cipherType == AES_256_CBC_TYPE ||
+                 (type && XSTRNCMP(type, EVP_AES_256_CBC, EVP_AES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_256_CBC");
+            ctx->cipherType = AES_256_CBC_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CBC_MODE;
+            ctx->keyLen     = 32;
+            ctx->block_size = AES_BLOCK_SIZE;
+            ctx->ivSz       = AES_BLOCK_SIZE;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv,
+                                ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION, 0);
+                if (ret != 0){
+                    WOLFSSL_MSG("AesSetKey() failed");
+                    return WOLFSSL_FAILURE;
+                }
+            }
+            if (iv && key == NULL) {
+                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
+                if (ret != 0){
+                    WOLFSSL_MSG("wc_AesSetIV() failed");
+                    return WOLFSSL_FAILURE;
+                }
+            }
+        }
+        #endif /* WOLFSSL_AES_256 */
+    #endif /* HAVE_AES_CBC */
+#if !defined(_WIN32) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
+    #ifdef HAVE_AESGCM
+        #ifdef WOLFSSL_AES_128
+        if (ctx->cipherType == AES_128_GCM_TYPE ||
+            (type && XSTRNCMP(type, EVP_AES_128_GCM, EVP_AES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_128_GCM");
+            ctx->cipherType = AES_128_GCM_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_GCM_MODE;
+            ctx->keyLen     = 16;
+            ctx->block_size = AES_BLOCK_SIZE;
+            ctx->authTagSz  = AES_BLOCK_SIZE;
+            ctx->ivSz       = GCM_NONCE_MID_SZ;
+
+            XMEMSET(ctx->authTag, 0, ctx->authTagSz);
+            if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) {
+                WOLFSSL_MSG("wc_AesGcmSetKey() failed");
+                return WOLFSSL_FAILURE;
+            }
+            if (iv && wc_AesGcmSetExtIV(&ctx->cipher.aes, iv, GCM_NONCE_MID_SZ)) {
+                WOLFSSL_MSG("wc_AesGcmSetExtIV() failed");
+                return WOLFSSL_FAILURE;
+            }
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+        }
+        #endif /* WOLFSSL_AES_128 */
+        #ifdef WOLFSSL_AES_192
+        if (ctx->cipherType == AES_192_GCM_TYPE ||
+                 (type && XSTRNCMP(type, EVP_AES_192_GCM, EVP_AES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_192_GCM");
+            ctx->cipherType = AES_192_GCM_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_GCM_MODE;
+            ctx->keyLen     = 24;
+            ctx->block_size = AES_BLOCK_SIZE;
+            ctx->authTagSz  = AES_BLOCK_SIZE;
+            ctx->ivSz       = GCM_NONCE_MID_SZ;
+
+            XMEMSET(ctx->authTag, 0, ctx->authTagSz);
+            if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) {
+                WOLFSSL_MSG("wc_AesGcmSetKey() failed");
+                return WOLFSSL_FAILURE;
+            }
+            if (iv && wc_AesGcmSetExtIV(&ctx->cipher.aes, iv, GCM_NONCE_MID_SZ)) {
+                WOLFSSL_MSG("wc_AesGcmSetExtIV() failed");
+                return WOLFSSL_FAILURE;
+            }
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+        }
+        #endif /* WOLFSSL_AES_192 */
+        #ifdef WOLFSSL_AES_256
+        if (ctx->cipherType == AES_256_GCM_TYPE ||
+                 (type && XSTRNCMP(type, EVP_AES_256_GCM, EVP_AES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_256_GCM");
+            ctx->cipherType = AES_256_GCM_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_GCM_MODE;
+            ctx->keyLen     = 32;
+            ctx->block_size = AES_BLOCK_SIZE;
+            ctx->authTagSz  = AES_BLOCK_SIZE;
+            ctx->ivSz       = GCM_NONCE_MID_SZ;
+
+            XMEMSET(ctx->authTag, 0, ctx->authTagSz);
+            if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) {
+                WOLFSSL_MSG("wc_AesGcmSetKey() failed");
+                return WOLFSSL_FAILURE;
+            }
+            if (iv && wc_AesGcmSetExtIV(&ctx->cipher.aes, iv, GCM_NONCE_MID_SZ)) {
+                WOLFSSL_MSG("wc_AesGcmSetExtIV() failed");
+                return WOLFSSL_FAILURE;
+            }
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+        }
+        #endif /* WOLFSSL_AES_256 */
+    #endif /* HAVE_AESGCM */
+#endif /* !defined(_WIN32) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) */
+#ifdef WOLFSSL_AES_COUNTER
+        #ifdef WOLFSSL_AES_128
+        if (ctx->cipherType == AES_128_CTR_TYPE ||
+                 (type && XSTRNCMP(type, EVP_AES_128_CTR, EVP_AES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_128_CTR");
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->cipherType = AES_128_CTR_TYPE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CTR_MODE;
+            ctx->keyLen     = 16;
+            ctx->block_size = NO_PADDING_BLOCK_SIZE;
+            ctx->ivSz       = AES_BLOCK_SIZE;
+#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB)
+            ctx->cipher.aes.left = 0;
+#endif
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret =  AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv,
+                    AES_ENCRYPTION, 1);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+            if (iv && key == NULL) {
+                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+        }
+        #endif /* WOLFSSL_AES_128 */
+        #ifdef WOLFSSL_AES_192
+        if (ctx->cipherType == AES_192_CTR_TYPE ||
+                 (type && XSTRNCMP(type, EVP_AES_192_CTR, EVP_AES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_192_CTR");
+            ctx->cipherType = AES_192_CTR_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CTR_MODE;
+            ctx->keyLen     = 24;
+            ctx->block_size = NO_PADDING_BLOCK_SIZE;
+            ctx->ivSz       = AES_BLOCK_SIZE;
+#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB)
+            ctx->cipher.aes.left = 0;
+#endif
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret =  AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv,
+                      AES_ENCRYPTION, 1);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+            if (iv && key == NULL) {
+                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+        }
+        #endif /* WOLFSSL_AES_192 */
+        #ifdef WOLFSSL_AES_256
+        if (ctx->cipherType == AES_256_CTR_TYPE ||
+                 (type && XSTRNCMP(type, EVP_AES_256_CTR, EVP_AES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_256_CTR");
+            ctx->cipherType = AES_256_CTR_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CTR_MODE;
+            ctx->keyLen     = 32;
+            ctx->block_size = NO_PADDING_BLOCK_SIZE;
+            ctx->ivSz       = AES_BLOCK_SIZE;
+#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB)
+            ctx->cipher.aes.left = 0;
+#endif
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret =  AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv,
+                      AES_ENCRYPTION, 1);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+            if (iv && key == NULL) {
+                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+        }
+        #endif /* WOLFSSL_AES_256 */
+#endif /* WOLFSSL_AES_COUNTER */
+        #ifdef WOLFSSL_AES_128
+        if (ctx->cipherType == AES_128_ECB_TYPE ||
+            (type && XSTRNCMP(type, EVP_AES_128_ECB, EVP_AES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_128_ECB");
+            ctx->cipherType = AES_128_ECB_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_ECB_MODE;
+            ctx->keyLen     = 16;
+            ctx->block_size = AES_BLOCK_SIZE;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret =  AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, NULL,
+                      ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION, 1);
+            }
+            if (ret != 0)
+                return WOLFSSL_FAILURE;
+        }
+        #endif /* WOLFSSL_AES_128 */
+        #ifdef WOLFSSL_AES_192
+        if (ctx->cipherType == AES_192_ECB_TYPE ||
+                 (type && XSTRNCMP(type, EVP_AES_192_ECB, EVP_AES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_192_ECB");
+            ctx->cipherType = AES_192_ECB_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_ECB_MODE;
+            ctx->keyLen     = 24;
+            ctx->block_size = AES_BLOCK_SIZE;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret =  AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, NULL,
+                      ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION, 1);
+            }
+            if (ret != 0)
+                return WOLFSSL_FAILURE;
+        }
+        #endif /* WOLFSSL_AES_192 */
+        #ifdef WOLFSSL_AES_256
+        if (ctx->cipherType == AES_256_ECB_TYPE ||
+                 (type && XSTRNCMP(type, EVP_AES_256_ECB, EVP_AES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_256_ECB");
+            ctx->cipherType = AES_256_ECB_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_ECB_MODE;
+            ctx->keyLen     = 32;
+            ctx->block_size = AES_BLOCK_SIZE;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret =  AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, NULL,
+                    ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION, 1);
+            }
+            if (ret != 0)
+                return WOLFSSL_FAILURE;
+        }
+        #endif /* WOLFSSL_AES_256 */
+    #ifdef WOLFSSL_AES_CFB
+        #ifdef WOLFSSL_AES_128
+        if (ctx->cipherType == AES_128_CFB1_TYPE ||
+            (type && XSTRNCMP(type, EVP_AES_128_CFB1, EVP_AESCFB_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_128_CFB1");
+            ctx->cipherType = AES_128_CFB1_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CFB_MODE;
+            ctx->keyLen     = 16;
+            ctx->block_size = 1;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv,
+                        AES_ENCRYPTION, 0);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+            if (iv && key == NULL) {
+                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+        }
+        #endif /* WOLFSSL_AES_128 */
+        #ifdef WOLFSSL_AES_192
+        if (ctx->cipherType == AES_192_CFB1_TYPE ||
+                 (type && XSTRNCMP(type, EVP_AES_192_CFB1, EVP_AESCFB_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_192_CFB1");
+            ctx->cipherType = AES_192_CFB1_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CFB_MODE;
+            ctx->keyLen     = 24;
+            ctx->block_size = 1;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv,
+                            AES_ENCRYPTION, 0);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+            if (iv && key == NULL) {
+                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+        }
+        #endif /* WOLFSSL_AES_192 */
+        #ifdef WOLFSSL_AES_256
+        if (ctx->cipherType == AES_256_CFB1_TYPE ||
+                 (type && XSTRNCMP(type, EVP_AES_256_CFB1, EVP_AESCFB_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_256_CFB1");
+            ctx->cipherType = AES_256_CFB1_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CFB_MODE;
+            ctx->keyLen     = 32;
+            ctx->block_size = 1;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv,
+                            AES_ENCRYPTION, 0);
+                if (ret != 0){
+                    WOLFSSL_MSG("AesSetKey() failed");
+                    return WOLFSSL_FAILURE;
+                }
+            }
+            if (iv && key == NULL) {
+                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
+                if (ret != 0){
+                    WOLFSSL_MSG("wc_AesSetIV() failed");
+                    return WOLFSSL_FAILURE;
+                }
+            }
+        }
+        #endif /* WOLFSSL_AES_256 */
+        #ifdef WOLFSSL_AES_128
+        if (ctx->cipherType == AES_128_CFB8_TYPE ||
+            (type && XSTRNCMP(type, EVP_AES_128_CFB8, EVP_AESCFB_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_128_CFB8");
+            ctx->cipherType = AES_128_CFB8_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CFB_MODE;
+            ctx->keyLen     = 16;
+            ctx->block_size = 1;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv,
+                        AES_ENCRYPTION, 0);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+            if (iv && key == NULL) {
+                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+        }
+        #endif /* WOLFSSL_AES_128 */
+        #ifdef WOLFSSL_AES_192
+        if (ctx->cipherType == AES_192_CFB8_TYPE ||
+                 (type && XSTRNCMP(type, EVP_AES_192_CFB8, EVP_AESCFB_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_192_CFB8");
+            ctx->cipherType = AES_192_CFB8_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CFB_MODE;
+            ctx->keyLen     = 24;
+            ctx->block_size = 1;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv,
+                            AES_ENCRYPTION, 0);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+            if (iv && key == NULL) {
+                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+        }
+        #endif /* WOLFSSL_AES_192 */
+        #ifdef WOLFSSL_AES_256
+        if (ctx->cipherType == AES_256_CFB8_TYPE ||
+                 (type && XSTRNCMP(type, EVP_AES_256_CFB8, EVP_AESCFB_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_256_CFB8");
+            ctx->cipherType = AES_256_CFB8_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CFB_MODE;
+            ctx->keyLen     = 32;
+            ctx->block_size = 1;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv,
+                            AES_ENCRYPTION, 0);
+                if (ret != 0){
+                    WOLFSSL_MSG("AesSetKey() failed");
+                    return WOLFSSL_FAILURE;
+                }
+            }
+            if (iv && key == NULL) {
+                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
+                if (ret != 0){
+                    WOLFSSL_MSG("wc_AesSetIV() failed");
+                    return WOLFSSL_FAILURE;
+                }
+            }
+        }
+        #endif /* WOLFSSL_AES_256 */
+        #ifdef WOLFSSL_AES_128
+        if (ctx->cipherType == AES_128_CFB128_TYPE ||
+            (type && XSTRNCMP(type, EVP_AES_128_CFB128, EVP_AESCFB_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_128_CFB128");
+            ctx->cipherType = AES_128_CFB128_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CFB_MODE;
+            ctx->keyLen     = 16;
+            ctx->block_size = 1;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv,
+                        AES_ENCRYPTION, 0);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+            if (iv && key == NULL) {
+                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+        }
+        #endif /* WOLFSSL_AES_128 */
+        #ifdef WOLFSSL_AES_192
+        if (ctx->cipherType == AES_192_CFB128_TYPE ||
+                 (type && XSTRNCMP(type, EVP_AES_192_CFB128, EVP_AESCFB_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_192_CFB128");
+            ctx->cipherType = AES_192_CFB128_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CFB_MODE;
+            ctx->keyLen     = 24;
+            ctx->block_size = 1;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv,
+                            AES_ENCRYPTION, 0);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+            if (iv && key == NULL) {
+                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+        }
+        #endif /* WOLFSSL_AES_192 */
+        #ifdef WOLFSSL_AES_256
+        if (ctx->cipherType == AES_256_CFB128_TYPE ||
+                 (type && XSTRNCMP(type, EVP_AES_256_CFB128, EVP_AESCFB_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_256_CFB128");
+            ctx->cipherType = AES_256_CFB128_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CFB_MODE;
+            ctx->keyLen     = 32;
+            ctx->block_size = 1;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv,
+                            AES_ENCRYPTION, 0);
+                if (ret != 0){
+                    WOLFSSL_MSG("AesSetKey() failed");
+                    return WOLFSSL_FAILURE;
+                }
+            }
+            if (iv && key == NULL) {
+                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
+                if (ret != 0){
+                    WOLFSSL_MSG("wc_AesSetIV() failed");
+                    return WOLFSSL_FAILURE;
+                }
+            }
+        }
+        #endif /* WOLFSSL_AES_256 */
+    #endif /* HAVE_AES_CFB */
+    #ifdef WOLFSSL_AES_OFB
+        #ifdef WOLFSSL_AES_128
+        if (ctx->cipherType == AES_128_OFB_TYPE ||
+            (type && XSTRNCMP(type, EVP_AES_128_OFB, EVP_AES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_128_OFB");
+            ctx->cipherType = AES_128_OFB_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_OFB_MODE;
+            ctx->keyLen     = 16;
+            ctx->block_size = 1;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv,
+                        AES_ENCRYPTION, 0);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+            if (iv && key == NULL) {
+                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+        }
+        #endif /* WOLFSSL_AES_128 */
+        #ifdef WOLFSSL_AES_192
+        if (ctx->cipherType == AES_192_OFB_TYPE ||
+                 (type && XSTRNCMP(type, EVP_AES_192_OFB, EVP_AES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_192_OFB");
+            ctx->cipherType = AES_192_OFB_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_OFB_MODE;
+            ctx->keyLen     = 24;
+            ctx->block_size = 1;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv,
+                            AES_ENCRYPTION, 0);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+            if (iv && key == NULL) {
+                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+        }
+        #endif /* WOLFSSL_AES_192 */
+        #ifdef WOLFSSL_AES_256
+        if (ctx->cipherType == AES_256_OFB_TYPE ||
+                 (type && XSTRNCMP(type, EVP_AES_256_OFB, EVP_AES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_256_OFB");
+            ctx->cipherType = AES_256_OFB_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_OFB_MODE;
+            ctx->keyLen     = 32;
+            ctx->block_size = 1;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv,
+                            AES_ENCRYPTION, 0);
+                if (ret != 0){
+                    WOLFSSL_MSG("AesSetKey() failed");
+                    return WOLFSSL_FAILURE;
+                }
+            }
+            if (iv && key == NULL) {
+                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
+                if (ret != 0){
+                    WOLFSSL_MSG("wc_AesSetIV() failed");
+                    return WOLFSSL_FAILURE;
+                }
+            }
+        }
+        #endif /* WOLFSSL_AES_256 */
+    #endif /* HAVE_AES_OFB */
+    #ifdef WOLFSSL_AES_XTS
+        #ifdef WOLFSSL_AES_128
+        if (ctx->cipherType == AES_128_XTS_TYPE ||
+            (type && XSTRNCMP(type, EVP_AES_128_XTS, EVP_AES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_128_XTS");
+            ctx->cipherType = AES_128_XTS_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_XTS_MODE;
+            ctx->keyLen     = 32;
+            ctx->block_size = 1;
+            ctx->ivSz       = AES_BLOCK_SIZE;
+
+            if (iv != NULL) {
+                if (iv != ctx->iv) /* Valgrind error when src == dst */
+                    XMEMCPY(ctx->iv, iv, ctx->ivSz);
+            }
+            else
+                XMEMSET(ctx->iv, 0, AES_BLOCK_SIZE);
+
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = wc_AesXtsSetKey(&ctx->cipher.xts, key, ctx->keyLen,
+                    ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION, NULL, 0);
+                if (ret != 0) {
+                    WOLFSSL_MSG("wc_AesXtsSetKey() failed");
+                    return WOLFSSL_FAILURE;
+                }
+            }
+        }
+        #endif /* WOLFSSL_AES_128 */
+        #ifdef WOLFSSL_AES_256
+        if (ctx->cipherType == AES_256_XTS_TYPE ||
+                 (type && XSTRNCMP(type, EVP_AES_256_XTS, EVP_AES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_256_XTS");
+            ctx->cipherType = AES_256_XTS_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_XTS_MODE;
+            ctx->keyLen     = 64;
+            ctx->block_size = 1;
+            ctx->ivSz       = AES_BLOCK_SIZE;
+
+            if (iv != NULL) {
+                if (iv != ctx->iv) /* Valgrind error when src == dst */
+                    XMEMCPY(ctx->iv, iv, ctx->ivSz);
+            }
+            else
+                XMEMSET(ctx->iv, 0, AES_BLOCK_SIZE);
+
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = wc_AesXtsSetKey(&ctx->cipher.xts, key, ctx->keyLen,
+                        ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION, NULL, 0);
+                if (ret != 0) {
+                    WOLFSSL_MSG("wc_AesXtsSetKey() failed");
+                    return WOLFSSL_FAILURE;
+                }
+            }
+        }
+        #endif /* WOLFSSL_AES_256 */
+    #endif /* HAVE_AES_XTS */
+#endif /* NO_AES */
+
+#ifndef NO_DES3
+        if (ctx->cipherType == DES_CBC_TYPE ||
+                 (type && XSTRNCMP(type, EVP_DES_CBC, EVP_DES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_DES_CBC");
+            ctx->cipherType = DES_CBC_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CBC_MODE;
+            ctx->keyLen     = 8;
+            ctx->block_size = DES_BLOCK_SIZE;
+            ctx->ivSz       = DES_BLOCK_SIZE;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = wc_Des_SetKey(&ctx->cipher.des, key, iv,
+                          ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+
+            if (iv && key == NULL)
+                wc_Des_SetIV(&ctx->cipher.des, iv);
+        }
+#ifdef WOLFSSL_DES_ECB
+        else if (ctx->cipherType == DES_ECB_TYPE ||
+                 (type && XSTRNCMP(type, EVP_DES_ECB, EVP_DES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_DES_ECB");
+            ctx->cipherType = DES_ECB_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_ECB_MODE;
+            ctx->keyLen     = 8;
+            ctx->block_size = DES_BLOCK_SIZE;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                WOLFSSL_MSG("Des_SetKey");
+                ret = wc_Des_SetKey(&ctx->cipher.des, key, NULL,
+                          ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+        }
+#endif
+        else if (ctx->cipherType == DES_EDE3_CBC_TYPE ||
+                 (type &&
+                  XSTRNCMP(type, EVP_DES_EDE3_CBC, EVP_DES_EDE3_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_DES_EDE3_CBC");
+            ctx->cipherType = DES_EDE3_CBC_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CBC_MODE;
+            ctx->keyLen     = 24;
+            ctx->block_size = DES_BLOCK_SIZE;
+            ctx->ivSz       = DES_BLOCK_SIZE;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = wc_Des3_SetKey(&ctx->cipher.des3, key, iv,
+                          ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+
+            if (iv && key == NULL) {
+                ret = wc_Des3_SetIV(&ctx->cipher.des3, iv);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+        }
+        else if (ctx->cipherType == DES_EDE3_ECB_TYPE ||
+                 (type &&
+                  XSTRNCMP(type, EVP_DES_EDE3_ECB, EVP_DES_EDE3_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_DES_EDE3_ECB");
+            ctx->cipherType = DES_EDE3_ECB_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_ECB_MODE;
+            ctx->keyLen     = 24;
+            ctx->block_size = DES_BLOCK_SIZE;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = wc_Des3_SetKey(&ctx->cipher.des3, key, NULL,
+                          ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+        }
+#endif /* NO_DES3 */
+#ifndef NO_RC4
+        if (ctx->cipherType == ARC4_TYPE || (type &&
+                                     XSTRNCMP(type, "ARC4", 4) == 0)) {
+            WOLFSSL_MSG("ARC4");
+            ctx->cipherType = ARC4_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_STREAM_CIPHER;
+            ctx->block_size = 1;
+            if (ctx->keyLen == 0)  /* user may have already set */
+                ctx->keyLen = 16;  /* default to 128 */
+            if (key)
+                wc_Arc4SetKey(&ctx->cipher.arc4, key, ctx->keyLen);
+        }
+#endif /* NO_RC4 */
+#ifdef HAVE_IDEA
+        if (ctx->cipherType == IDEA_CBC_TYPE ||
+                 (type && XSTRNCMP(type, EVP_IDEA_CBC, EVP_IDEA_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_IDEA_CBC");
+            ctx->cipherType = IDEA_CBC_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CBC_MODE;
+            ctx->keyLen     = IDEA_KEY_SIZE;
+            ctx->block_size = 8;
+            ctx->ivSz       = IDEA_BLOCK_SIZE;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = wc_IdeaSetKey(&ctx->cipher.idea, key, (word16)ctx->keyLen,
+                                    iv, ctx->enc ? IDEA_ENCRYPTION :
+                                                   IDEA_DECRYPTION);
+                if (ret != 0)
+                    return WOLFSSL_FAILURE;
+            }
+
+            if (iv && key == NULL)
+                wc_IdeaSetIV(&ctx->cipher.idea, iv);
+        }
+#endif /* HAVE_IDEA */
+        if (ctx->cipherType == NULL_CIPHER_TYPE || (type &&
+                                     XSTRNCMP(type, "NULL", 4) == 0)) {
+            WOLFSSL_MSG("NULL cipher");
+            ctx->cipherType = NULL_CIPHER_TYPE;
+            ctx->keyLen = 0;
+            ctx->block_size = 16;
+        }
+#ifdef HAVE_WOLFSSL_EVP_CIPHER_CTX_IV
+        if (iv && iv != ctx->iv) {
+            if (wolfSSL_StoreExternalIV(ctx) != WOLFSSL_SUCCESS) {
+                return WOLFSSL_FAILURE;
+            }
+        }
+#endif
+        (void)ret; /* remove warning. If execution reaches this point, ret=0 */
+        return WOLFSSL_SUCCESS;
+    }
+
+    /* WOLFSSL_SUCCESS on ok */
+    int wolfSSL_EVP_CIPHER_CTX_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_key_length");
+        if (ctx)
+            return ctx->keyLen;
+
+        return 0;   /* failure */
+    }
+
+    /* WOLFSSL_SUCCESS on ok */
+    int wolfSSL_EVP_CIPHER_CTX_set_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx,
+                                             int keylen)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_set_key_length");
+        if (ctx)
+            ctx->keyLen = keylen;
+        else
+            return 0;  /* failure */
+
+        return WOLFSSL_SUCCESS;
+    }
+#if defined(HAVE_AESGCM)
+    /* returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE */
+    int wolfSSL_EVP_CIPHER_CTX_set_iv_length(WOLFSSL_EVP_CIPHER_CTX* ctx,
+                                             int ivLen)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_set_iv_length");
+        if (ctx)
+            ctx->ivSz= ivLen;
+        else
+            return WOLFSSL_FAILURE;
+
+        return WOLFSSL_SUCCESS;
+    }
+
+    /* returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE */
+    int wolfSSL_EVP_CIPHER_CTX_set_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, byte* iv,
+                                             int ivLen)
+    {
+        int expectedIvLen;
+
+        WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_set_iv_length");
+        if (!ctx || !iv || !ivLen) {
+            return WOLFSSL_FAILURE;
+        }
+
+        expectedIvLen = wolfSSL_EVP_CIPHER_CTX_iv_length(ctx);
+
+        if (expectedIvLen == 0 || expectedIvLen != ivLen) {
+            WOLFSSL_MSG("Wrong ivLen value");
+            return WOLFSSL_FAILURE;
+        }
+
+        return wolfSSL_EVP_CipherInit(ctx, NULL, NULL, iv, -1);
+    }
+#endif
+
+    /* WOLFSSL_SUCCESS on ok */
+    int wolfSSL_EVP_Cipher(WOLFSSL_EVP_CIPHER_CTX* ctx, byte* dst, byte* src,
+                          word32 len)
+    {
+        int ret = 0;
+        WOLFSSL_ENTER("wolfSSL_EVP_Cipher");
+
+        if (ctx == NULL || src == NULL ||
+            (dst == NULL &&
+             ctx->cipherType != AES_128_GCM_TYPE &&
+             ctx->cipherType != AES_192_GCM_TYPE &&
+             ctx->cipherType != AES_256_GCM_TYPE)) {
+            WOLFSSL_MSG("Bad function argument");
+            return 0;  /* failure */
+        }
+
+        if (ctx->cipherType == 0xff) {
+            WOLFSSL_MSG("no init");
+            return 0;  /* failure */
+        }
+
+        switch (ctx->cipherType) {
+
+#ifndef NO_AES
+#ifdef HAVE_AES_CBC
+            case AES_128_CBC_TYPE :
+            case AES_192_CBC_TYPE :
+            case AES_256_CBC_TYPE :
+                WOLFSSL_MSG("AES CBC");
+                if (ctx->enc)
+                    ret = wc_AesCbcEncrypt(&ctx->cipher.aes, dst, src, len);
+                else
+                    ret = wc_AesCbcDecrypt(&ctx->cipher.aes, dst, src, len);
+                break;
+#endif /* HAVE_AES_CBC */
+
+#ifdef WOLFSSL_AES_CFB
+#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS)
+            case AES_128_CFB1_TYPE:
+            case AES_192_CFB1_TYPE:
+            case AES_256_CFB1_TYPE:
+                WOLFSSL_MSG("AES CFB1");
+                if (ctx->enc)
+                    ret = wc_AesCfb1Encrypt(&ctx->cipher.aes, dst, src, len);
+                else
+                    ret = wc_AesCfb1Decrypt(&ctx->cipher.aes, dst, src, len);
+                break;
+            case AES_128_CFB8_TYPE:
+            case AES_192_CFB8_TYPE:
+            case AES_256_CFB8_TYPE:
+                WOLFSSL_MSG("AES CFB8");
+                if (ctx->enc)
+                    ret = wc_AesCfb8Encrypt(&ctx->cipher.aes, dst, src, len);
+                else
+                    ret = wc_AesCfb8Decrypt(&ctx->cipher.aes, dst, src, len);
+                break;
+#endif /* !HAVE_SELFTEST && !HAVE_FIPS */
+            case AES_128_CFB128_TYPE:
+            case AES_192_CFB128_TYPE:
+            case AES_256_CFB128_TYPE:
+                WOLFSSL_MSG("AES CFB128");
+                if (ctx->enc)
+                    ret = wc_AesCfbEncrypt(&ctx->cipher.aes, dst, src, len);
+                else
+                    ret = wc_AesCfbDecrypt(&ctx->cipher.aes, dst, src, len);
+                break;
+#endif /* WOLFSSL_AES_CFB */
+#if defined(WOLFSSL_AES_OFB)
+            case AES_128_OFB_TYPE:
+            case AES_192_OFB_TYPE:
+            case AES_256_OFB_TYPE:
+                WOLFSSL_MSG("AES OFB");
+                if (ctx->enc)
+                    ret = wc_AesOfbEncrypt(&ctx->cipher.aes, dst, src, len);
+                else
+                    ret = wc_AesOfbDecrypt(&ctx->cipher.aes, dst, src, len);
+                break;
+#endif /* WOLFSSL_AES_OFB */
+#if defined(WOLFSSL_AES_XTS)
+            case AES_128_XTS_TYPE:
+            case AES_256_XTS_TYPE:
+                WOLFSSL_MSG("AES XTS");
+                if (ctx->enc)
+                    ret = wc_AesXtsEncrypt(&ctx->cipher.xts, dst, src, len,
+                            ctx->iv, ctx->ivSz);
+                else
+                    ret = wc_AesXtsDecrypt(&ctx->cipher.xts, dst, src, len,
+                            ctx->iv, ctx->ivSz);
+                break;
+#endif /* WOLFSSL_AES_XTS */
+
+#ifdef HAVE_AESGCM
+            case AES_128_GCM_TYPE :
+            case AES_192_GCM_TYPE :
+            case AES_256_GCM_TYPE :
+                WOLFSSL_MSG("AES GCM");
+                if (ctx->enc) {
+                    if (dst){
+                        /* encrypt confidential data*/
+                        ret = wc_AesGcmEncrypt(&ctx->cipher.aes, dst, src, len,
+                                  ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz,
+                                  NULL, 0);
+                    }
+                    else {
+                        /* authenticated, non-confidential data */
+                        ret = wc_AesGcmEncrypt(&ctx->cipher.aes, NULL, NULL, 0,
+                                  ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz,
+                                  src, len);
+                        /* Reset partial authTag error for AAD*/
+                        if (ret == AES_GCM_AUTH_E)
+                            ret = 0;
+                    }
+                }
+                else {
+                    if (dst){
+                        /* decrypt confidential data*/
+                        ret = wc_AesGcmDecrypt(&ctx->cipher.aes, dst, src, len,
+                                  ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz,
+                                  NULL, 0);
+                    }
+                    else {
+                        /* authenticated, non-confidential data*/
+                        ret = wc_AesGcmDecrypt(&ctx->cipher.aes, NULL, NULL, 0,
+                                  ctx->iv, ctx->ivSz,
+                                  ctx->authTag, ctx->authTagSz,
+                                  src, len);
+                        /* Reset partial authTag error for AAD*/
+                        if (ret == AES_GCM_AUTH_E)
+                            ret = 0;
+                    }
+                }
+                break;
+#endif /* HAVE_AESGCM */
+#ifdef HAVE_AES_ECB
+            case AES_128_ECB_TYPE :
+            case AES_192_ECB_TYPE :
+            case AES_256_ECB_TYPE :
+                WOLFSSL_MSG("AES ECB");
+                if (ctx->enc)
+                    ret = wc_AesEcbEncrypt(&ctx->cipher.aes, dst, src, len);
+                else
+                    ret = wc_AesEcbDecrypt(&ctx->cipher.aes, dst, src, len);
+                break;
+#endif
+#ifdef WOLFSSL_AES_COUNTER
+            case AES_128_CTR_TYPE :
+            case AES_192_CTR_TYPE :
+            case AES_256_CTR_TYPE :
+                    WOLFSSL_MSG("AES CTR");
+                    ret = wc_AesCtrEncrypt(&ctx->cipher.aes, dst, src, len);
+                break;
+#endif /* WOLFSSL_AES_COUNTER */
+#endif /* NO_AES */
+
+#ifndef NO_DES3
+            case DES_CBC_TYPE :
+                WOLFSSL_MSG("DES CBC");
+                if (ctx->enc)
+                    wc_Des_CbcEncrypt(&ctx->cipher.des, dst, src, len);
+                else
+                    wc_Des_CbcDecrypt(&ctx->cipher.des, dst, src, len);
+                break;
+            case DES_EDE3_CBC_TYPE :
+                WOLFSSL_MSG("DES3 CBC");
+                if (ctx->enc)
+                    ret = wc_Des3_CbcEncrypt(&ctx->cipher.des3, dst, src, len);
+                else
+                    ret = wc_Des3_CbcDecrypt(&ctx->cipher.des3, dst, src, len);
+                break;
+#ifdef WOLFSSL_DES_ECB
+            case DES_ECB_TYPE :
+                WOLFSSL_MSG("DES ECB");
+                ret = wc_Des_EcbEncrypt(&ctx->cipher.des, dst, src, len);
+                break;
+            case DES_EDE3_ECB_TYPE :
+                WOLFSSL_MSG("DES3 ECB");
+                ret = wc_Des3_EcbEncrypt(&ctx->cipher.des3, dst, src, len);
+                break;
+#endif
+#endif /* !NO_DES3 */
+
+#ifndef NO_RC4
+            case ARC4_TYPE :
+                WOLFSSL_MSG("ARC4");
+                wc_Arc4Process(&ctx->cipher.arc4, dst, src, len);
+                break;
+#endif
+
+#ifdef HAVE_IDEA
+            case IDEA_CBC_TYPE :
+                WOLFSSL_MSG("IDEA CBC");
+                if (ctx->enc)
+                    wc_IdeaCbcEncrypt(&ctx->cipher.idea, dst, src, len);
+                else
+                    wc_IdeaCbcDecrypt(&ctx->cipher.idea, dst, src, len);
+                break;
+#endif
+            case NULL_CIPHER_TYPE :
+                WOLFSSL_MSG("NULL CIPHER");
+                XMEMCPY(dst, src, len);
+                break;
+
+            default: {
+                WOLFSSL_MSG("bad type");
+                return 0;  /* failure */
+            }
+        }
+
+        if (ret != 0) {
+            WOLFSSL_MSG("wolfSSL_EVP_Cipher failure");
+            return 0;  /* failure */
+        }
+
+        if (wolfSSL_StoreExternalIV(ctx) != WOLFSSL_SUCCESS) {
+            return WOLFSSL_FAILURE;
+        }
+
+        WOLFSSL_MSG("wolfSSL_EVP_Cipher success");
+        return WOLFSSL_SUCCESS;  /* success */
+    }
+
+    /* WOLFSSL_SUCCESS on ok */
+    int wolfSSL_EVP_DigestInit(WOLFSSL_EVP_MD_CTX* ctx,
+                               const WOLFSSL_EVP_MD* md)
+    {
+        int ret = WOLFSSL_SUCCESS;
+
+        WOLFSSL_ENTER("EVP_DigestInit");
+
+        if (ctx == NULL || md == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        /* compile-time validation of ASYNC_CTX_SIZE */
+        typedef char async_test[WC_ASYNC_DEV_SIZE >= sizeof(WC_ASYNC_DEV) ?
+                                                                        1 : -1];
+        (void)sizeof(async_test);
+    #endif
+
+        /* Set to 0 if no match */
+        ctx->macType = wolfSSL_EVP_md2macType(md);
+        if (XSTRNCMP(md, "SHA256", 6) == 0) {
+             ret = wolfSSL_SHA256_Init(&(ctx->hash.digest.sha256));
+        }
+    #ifdef WOLFSSL_SHA224
+        else if (XSTRNCMP(md, "SHA224", 6) == 0) {
+             ret = wolfSSL_SHA224_Init(&(ctx->hash.digest.sha224));
+        }
+    #endif
+    #ifdef WOLFSSL_SHA384
+        else if (XSTRNCMP(md, "SHA384", 6) == 0) {
+             ret = wolfSSL_SHA384_Init(&(ctx->hash.digest.sha384));
+        }
+    #endif
+    #ifdef WOLFSSL_SHA512
+        else if (XSTRNCMP(md, "SHA512", 6) == 0) {
+             ret = wolfSSL_SHA512_Init(&(ctx->hash.digest.sha512));
+        }
+    #endif
+    #ifndef NO_MD4
+        else if (XSTRNCMP(md, "MD4", 3) == 0) {
+            wolfSSL_MD4_Init(&(ctx->hash.digest.md4));
+        }
+    #endif
+    #ifndef NO_MD5
+        else if (XSTRNCMP(md, "MD5", 3) == 0) {
+            ret = wolfSSL_MD5_Init(&(ctx->hash.digest.md5));
+        }
+    #endif
+#ifdef WOLFSSL_SHA3
+    #ifndef WOLFSSL_NOSHA3_224
+        else if (XSTRNCMP(md, "SHA3_224", 8) == 0) {
+             ret = wolfSSL_SHA3_224_Init(&(ctx->hash.digest.sha3_224));
+        }
+    #endif
+    #ifndef WOLFSSL_NOSHA3_256
+        else if (XSTRNCMP(md, "SHA3_256", 8) == 0) {
+             ret = wolfSSL_SHA3_256_Init(&(ctx->hash.digest.sha3_256));
+        }
+    #endif
+        else if (XSTRNCMP(md, "SHA3_384", 8) == 0) {
+             ret = wolfSSL_SHA3_384_Init(&(ctx->hash.digest.sha3_384));
+        }
+    #ifndef WOLFSSL_NOSHA3_512
+        else if (XSTRNCMP(md, "SHA3_512", 8) == 0) {
+             ret = wolfSSL_SHA3_512_Init(&(ctx->hash.digest.sha3_512));
+        }
+    #endif
+#endif
+    #ifndef NO_SHA
+        /* has to be last since would pick or 224, 256, 384, or 512 too */
+        else if (XSTRNCMP(md, "SHA", 3) == 0) {
+             ret = wolfSSL_SHA_Init(&(ctx->hash.digest.sha));
+        }
+    #endif /* NO_SHA */
+        else {
+             ctx->macType = WC_HASH_TYPE_NONE;
+             return BAD_FUNC_ARG;
+        }
+
+        return ret;
+    }
+
+    /* WOLFSSL_SUCCESS on ok, WOLFSSL_FAILURE on failure */
+    int wolfSSL_EVP_DigestUpdate(WOLFSSL_EVP_MD_CTX* ctx, const void* data,
+                                size_t sz)
+    {
+        int macType;
+
+        WOLFSSL_ENTER("EVP_DigestUpdate");
+
+        macType = wolfSSL_EVP_md2macType(EVP_MD_CTX_md(ctx));
+        switch (macType) {
+#ifndef NO_MD4
+            case WC_HASH_TYPE_MD4:
+                wolfSSL_MD4_Update((MD4_CTX*)&ctx->hash, data,
+                                  (unsigned long)sz);
+                break;
+#endif
+#ifndef NO_MD5
+            case WC_HASH_TYPE_MD5:
+                wolfSSL_MD5_Update((MD5_CTX*)&ctx->hash, data,
+                                  (unsigned long)sz);
+                break;
+#endif
+#ifndef NO_SHA
+            case WC_HASH_TYPE_SHA:
+                wolfSSL_SHA_Update((SHA_CTX*)&ctx->hash, data,
+                                  (unsigned long)sz);
+                break;
+#endif
+#ifdef WOLFSSL_SHA224
+            case WC_HASH_TYPE_SHA224:
+                wolfSSL_SHA224_Update((SHA224_CTX*)&ctx->hash, data,
+                                     (unsigned long)sz);
+                break;
+#endif
+#ifndef NO_SHA256
+            case WC_HASH_TYPE_SHA256:
+                wolfSSL_SHA256_Update((SHA256_CTX*)&ctx->hash, data,
+                                     (unsigned long)sz);
+                break;
+#endif /* !NO_SHA256 */
+#ifdef WOLFSSL_SHA384
+            case WC_HASH_TYPE_SHA384:
+                wolfSSL_SHA384_Update((SHA384_CTX*)&ctx->hash, data,
+                                     (unsigned long)sz);
+                break;
+#endif
+#ifdef WOLFSSL_SHA512
+            case WC_HASH_TYPE_SHA512:
+                wolfSSL_SHA512_Update((SHA512_CTX*)&ctx->hash, data,
+                                     (unsigned long)sz);
+                break;
+#endif /* WOLFSSL_SHA512 */
+    #ifdef WOLFSSL_SHA3
+        #ifndef WOLFSSL_NOSHA3_224
+            case WC_HASH_TYPE_SHA3_224:
+                wolfSSL_SHA3_224_Update((SHA3_224_CTX*)&ctx->hash, data,
+                                     (unsigned long)sz);
+                break;
+        #endif
+        #ifndef WOLFSSL_NOSHA3_256
+            case WC_HASH_TYPE_SHA3_256:
+                wolfSSL_SHA3_256_Update((SHA3_256_CTX*)&ctx->hash, data,
+                                     (unsigned long)sz);
+                break;
+        #endif
+            case WC_HASH_TYPE_SHA3_384:
+                wolfSSL_SHA3_384_Update((SHA3_384_CTX*)&ctx->hash, data,
+                                     (unsigned long)sz);
+                break;
+        #ifndef WOLFSSL_NOSHA3_512
+            case WC_HASH_TYPE_SHA3_512:
+                wolfSSL_SHA3_512_Update((SHA3_512_CTX*)&ctx->hash, data,
+                                     (unsigned long)sz);
+                break;
+        #endif
+    #endif
+            default:
+                return WOLFSSL_FAILURE;
+        }
+
+        return WOLFSSL_SUCCESS;
+    }
+
+    /* WOLFSSL_SUCCESS on ok */
+    int wolfSSL_EVP_DigestFinal(WOLFSSL_EVP_MD_CTX* ctx, unsigned char* md,
+                               unsigned int* s)
+    {
+        int macType;
+
+        WOLFSSL_ENTER("EVP_DigestFinal");
+        macType = wolfSSL_EVP_md2macType(EVP_MD_CTX_md(ctx));
+        switch (macType) {
+#ifndef NO_MD4
+            case WC_HASH_TYPE_MD4:
+                wolfSSL_MD4_Final(md, (MD4_CTX*)&ctx->hash);
+                if (s) *s = MD4_DIGEST_SIZE;
+                break;
+#endif
+#ifndef NO_MD5
+            case WC_HASH_TYPE_MD5:
+                wolfSSL_MD5_Final(md, (MD5_CTX*)&ctx->hash);
+                if (s) *s = WC_MD5_DIGEST_SIZE;
+                break;
+#endif
+#ifndef NO_SHA
+            case WC_HASH_TYPE_SHA:
+                wolfSSL_SHA_Final(md, (SHA_CTX*)&ctx->hash);
+                if (s) *s = WC_SHA_DIGEST_SIZE;
+                break;
+#endif
+#ifdef WOLFSSL_SHA224
+            case WC_HASH_TYPE_SHA224:
+                wolfSSL_SHA224_Final(md, (SHA224_CTX*)&ctx->hash);
+                if (s) *s = WC_SHA224_DIGEST_SIZE;
+                break;
+#endif
+#ifndef NO_SHA256
+            case WC_HASH_TYPE_SHA256:
+                wolfSSL_SHA256_Final(md, (SHA256_CTX*)&ctx->hash);
+                if (s) *s = WC_SHA256_DIGEST_SIZE;
+                break;
+#endif /* !NO_SHA256 */
+#ifdef WOLFSSL_SHA384
+            case WC_HASH_TYPE_SHA384:
+                wolfSSL_SHA384_Final(md, (SHA384_CTX*)&ctx->hash);
+                if (s) *s = WC_SHA384_DIGEST_SIZE;
+                break;
+#endif
+#ifdef WOLFSSL_SHA512
+            case WC_HASH_TYPE_SHA512:
+                wolfSSL_SHA512_Final(md, (SHA512_CTX*)&ctx->hash);
+                if (s) *s = WC_SHA512_DIGEST_SIZE;
+                break;
+#endif /* WOLFSSL_SHA512 */
+    #ifdef WOLFSSL_SHA3
+        #ifndef WOLFSSL_NOSHA3_224
+            case WC_HASH_TYPE_SHA3_224:
+                wolfSSL_SHA3_224_Final(md, (SHA3_224_CTX*)&ctx->hash);
+                if (s) *s = WC_SHA3_224_DIGEST_SIZE;
+                break;
+        #endif
+        #ifndef WOLFSSL_NOSHA3_256
+            case WC_HASH_TYPE_SHA3_256:
+                wolfSSL_SHA3_256_Final(md, (SHA3_256_CTX*)&ctx->hash);
+                if (s) *s = WC_SHA3_256_DIGEST_SIZE;
+                break;
+        #endif
+            case WC_HASH_TYPE_SHA3_384:
+                wolfSSL_SHA3_384_Final(md, (SHA3_384_CTX*)&ctx->hash);
+                if (s) *s = WC_SHA3_384_DIGEST_SIZE;
+                break;
+        #ifndef WOLFSSL_NOSHA3_512
+            case WC_HASH_TYPE_SHA3_512:
+                wolfSSL_SHA3_512_Final(md, (SHA3_512_CTX*)&ctx->hash);
+                if (s) *s = WC_SHA3_512_DIGEST_SIZE;
+                break;
+        #endif
+    #endif
+            default:
+                return WOLFSSL_FAILURE;
+        }
+
+        return WOLFSSL_SUCCESS;
+    }
+
+    /* WOLFSSL_SUCCESS on ok */
+    int wolfSSL_EVP_DigestFinal_ex(WOLFSSL_EVP_MD_CTX* ctx, unsigned char* md,
+                                   unsigned int* s)
+    {
+        WOLFSSL_ENTER("EVP_DigestFinal_ex");
+        return EVP_DigestFinal(ctx, md, s);
+    }
+
+    void wolfSSL_EVP_cleanup(void)
+    {
+        /* nothing to do here */
+    }
+
+const WOLFSSL_EVP_MD* wolfSSL_EVP_get_digestbynid(int id)
+{
+    WOLFSSL_MSG("wolfSSL_get_digestbynid");
+
+    switch(id) {
+#ifndef NO_MD5
+        case NID_md5:
+            return wolfSSL_EVP_md5();
+#endif
+#ifndef NO_SHA
+        case NID_sha1:
+            return wolfSSL_EVP_sha1();
+#endif
+        default:
+            WOLFSSL_MSG("Bad digest id value");
+    }
+
+    return NULL;
+}
+
+#ifndef NO_RSA
+WOLFSSL_RSA* wolfSSL_EVP_PKEY_get0_RSA(WOLFSSL_EVP_PKEY *pkey)
+{
+    if (!pkey) {
+        return NULL;
+    }
+    return pkey->rsa;
+}
+
+WOLFSSL_RSA* wolfSSL_EVP_PKEY_get1_RSA(WOLFSSL_EVP_PKEY* key)
+{
+    WOLFSSL_RSA* local;
+
+    WOLFSSL_MSG("wolfSSL_EVP_PKEY_get1_RSA");
+
+    if (key == NULL) {
+        return NULL;
+    }
+
+    local = wolfSSL_RSA_new();
+    if (local == NULL) {
+        WOLFSSL_MSG("Error creating a new WOLFSSL_RSA structure");
+        return NULL;
+    }
+
+    if (key->type == EVP_PKEY_RSA) {
+        if (wolfSSL_RSA_LoadDer(local, (const unsigned char*)key->pkey.ptr,
+                    key->pkey_sz) != SSL_SUCCESS) {
+            /* now try public key */
+            if (wolfSSL_RSA_LoadDer_ex(local,
+                        (const unsigned char*)key->pkey.ptr, key->pkey_sz,
+                        WOLFSSL_RSA_LOAD_PUBLIC) != SSL_SUCCESS) {
+                wolfSSL_RSA_free(local);
+                local = NULL;
+            }
+        }
+    }
+    else {
+        WOLFSSL_MSG("WOLFSSL_EVP_PKEY does not hold an RSA key");
+        wolfSSL_RSA_free(local);
+        local = NULL;
+    }
+    return local;
+}
+
+/* with set1 functions the pkey struct does not own the RSA structure
+ *
+ * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure
+ */
+int wolfSSL_EVP_PKEY_set1_RSA(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_RSA *key)
+{
+#if defined(WOLFSSL_KEY_GEN) && !defined(HAVE_USER_RSA)
+    int derMax = 0;
+    int derSz  = 0;
+    byte* derBuf = NULL;
+    RsaKey* rsa  = NULL;
+#endif
+    WOLFSSL_ENTER("wolfSSL_EVP_PKEY_set1_RSA");
+    if ((pkey == NULL) || (key == NULL))
+        return WOLFSSL_FAILURE;
+
+    if (pkey->rsa != NULL && pkey->ownRsa == 1) {
+        wolfSSL_RSA_free(pkey->rsa);
+    }
+    pkey->rsa    = key;
+    pkey->ownRsa = 0; /* pkey does not own RSA */
+    pkey->type   = EVP_PKEY_RSA;
+    if (key->inSet == 0) {
+        if (SetRsaInternal(key) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetRsaInternal failed");
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+#if defined(WOLFSSL_KEY_GEN) && !defined(HAVE_USER_RSA)
+    rsa = (RsaKey*)key->internal;
+    /* 5 > size of n, d, p, q, d%(p-1), d(q-1), 1/q%p, e + ASN.1 additional
+     * information */
+    derMax = 5 * wolfSSL_RSA_size(key) + (2 * AES_BLOCK_SIZE);
+
+    derBuf = (byte*)XMALLOC(derMax, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (derBuf == NULL) {
+        WOLFSSL_MSG("malloc failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (rsa->type == RSA_PRIVATE) {
+        /* Private key to DER */
+        derSz = wc_RsaKeyToDer(rsa, derBuf, derMax);
+    }
+    else {
+        /* Public key to DER */
+        derSz = wc_RsaKeyToPublicDer(rsa, derBuf, derMax);
+    }
+
+    if (derSz < 0) {
+        if (rsa->type == RSA_PRIVATE) {
+            WOLFSSL_MSG("wc_RsaKeyToDer failed");
+        }
+        else {
+            WOLFSSL_MSG("wc_RsaKeyToPublicDer failed");
+        }
+        XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_FAILURE;
+    }
+
+    pkey->pkey.ptr = (char*)XMALLOC(derSz, pkey->heap, DYNAMIC_TYPE_DER);
+    if (pkey->pkey.ptr == NULL) {
+        WOLFSSL_MSG("key malloc failed");
+        XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_FAILURE;
+    }
+    pkey->pkey_sz = derSz;
+    XMEMCPY(pkey->pkey.ptr, derBuf, derSz);
+    XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif /* WOLFSSL_KEY_GEN && !HAVE_USER_RSA */
+
+#ifdef WC_RSA_BLINDING
+    if (key->ownRng == 0) {
+        if (wc_RsaSetRNG((RsaKey*)(pkey->rsa->internal), &(pkey->rng)) != 0) {
+            WOLFSSL_MSG("Error setting RSA rng");
+            return WOLFSSL_FAILURE;
+        }
+    }
+#endif
+    return WOLFSSL_SUCCESS;
+}
+#endif /* !NO_RSA */
+
+#if !defined (NO_DSA) && !defined(HAVE_SELFTEST) && defined(WOLFSSL_KEY_GEN)
+/* with set1 functions the pkey struct does not own the DSA structure
+ *
+ * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure
+ */
+int wolfSSL_EVP_PKEY_set1_DSA(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_DSA *key)
+{
+    int derMax = 0;
+    int derSz  = 0;
+    DsaKey* dsa  = NULL;
+    byte* derBuf = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_EVP_PKEY_set1_DSA");
+
+    if((pkey == NULL) || (key == NULL))return WOLFSSL_FAILURE;
+    if (pkey->dsa != NULL && pkey->ownDsa == 1) {
+        wolfSSL_DSA_free(pkey->dsa);
+    }
+    pkey->dsa    = key;
+    pkey->ownDsa = 0; /* pkey does not own DSA */
+    pkey->type   = EVP_PKEY_DSA;
+    if (key->inSet == 0) {
+        if (SetDsaInternal(key) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetDsaInternal failed");
+            return WOLFSSL_FAILURE;
+        }
+    }
+    dsa = (DsaKey*)key->internal;
+
+    /* 4 > size of pub, priv, p, q, g + ASN.1 additional information */
+    derMax = 4 * wolfSSL_BN_num_bytes(key->g) + AES_BLOCK_SIZE;
+
+    derBuf = (byte*)XMALLOC(derMax, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (derBuf == NULL) {
+        WOLFSSL_MSG("malloc failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (dsa->type == DSA_PRIVATE) {
+        /* Private key to DER */
+        derSz = wc_DsaKeyToDer(dsa, derBuf, derMax);
+    }
+    else {
+        /* Public key to DER */
+        derSz = wc_DsaKeyToPublicDer(dsa, derBuf, derMax);
+    }
+
+    if (derSz < 0) {
+        if (dsa->type == DSA_PRIVATE) {
+            WOLFSSL_MSG("wc_DsaKeyToDer failed");
+        }
+        else {
+            WOLFSSL_MSG("wc_DsaKeyToPublicDer failed");
+        }
+        XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_FAILURE;
+    }
+
+    pkey->pkey.ptr = (char*)XMALLOC(derSz, pkey->heap, DYNAMIC_TYPE_DER);
+    if (pkey->pkey.ptr == NULL) {
+        WOLFSSL_MSG("key malloc failed");
+        XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_FAILURE;
+    }
+    pkey->pkey_sz = derSz;
+    XMEMCPY(pkey->pkey.ptr, derBuf, derSz);
+    XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+    return WOLFSSL_SUCCESS;
+}
+
+WOLFSSL_DSA* wolfSSL_EVP_PKEY_get1_DSA(WOLFSSL_EVP_PKEY* key)
+{
+    WOLFSSL_DSA* local;
+
+    WOLFSSL_ENTER("wolfSSL_EVP_PKEY_get1_DSA");
+
+    if (key == NULL) {
+        WOLFSSL_MSG("Bad function argument");
+        return NULL;
+    }
+
+    local = wolfSSL_DSA_new();
+    if (local == NULL) {
+        WOLFSSL_MSG("Error creating a new WOLFSSL_DSA structure");
+        return NULL;
+    }
+
+    if (key->type == EVP_PKEY_DSA) {
+        if (wolfSSL_DSA_LoadDer(local, (const unsigned char*)key->pkey.ptr,
+                    key->pkey_sz) != SSL_SUCCESS) {
+            /* now try public key */
+            if (wolfSSL_DSA_LoadDer_ex(local,
+                        (const unsigned char*)key->pkey.ptr, key->pkey_sz,
+                        WOLFSSL_DSA_LOAD_PUBLIC) != SSL_SUCCESS) {
+                wolfSSL_DSA_free(local);
+                local = NULL;
+            }
+        }
+    }
+    else {
+        WOLFSSL_MSG("WOLFSSL_EVP_PKEY does not hold a DSA key");
+        wolfSSL_DSA_free(local);
+        local = NULL;
+    }
+    return local;
+}
+#endif /* !NO_DSA && !HAVE_SELFTEST && WOLFSSL_KEY_GEN */
+
+#ifdef HAVE_ECC
+WOLFSSL_EC_KEY *wolfSSL_EVP_PKEY_get0_EC_KEY(WOLFSSL_EVP_PKEY *pkey)
+{
+    WOLFSSL_EC_KEY *eckey = NULL;
+    if (pkey) {
+#ifdef HAVE_ECC
+        eckey = pkey->ecc;
+#endif
+    }
+    return eckey;
+}
+
+WOLFSSL_EC_KEY* wolfSSL_EVP_PKEY_get1_EC_KEY(WOLFSSL_EVP_PKEY* key)
+{
+    WOLFSSL_EC_KEY* local;
+    WOLFSSL_ENTER("wolfSSL_EVP_PKEY_get1_EC_KEY");
+
+    if (key == NULL) {
+        return NULL;
+    }
+
+    local = wolfSSL_EC_KEY_new();
+    if (local == NULL) {
+        WOLFSSL_MSG("Error creating a new WOLFSSL_EC_KEY structure");
+        return NULL;
+    }
+
+    if (key->type == EVP_PKEY_EC) {
+        if (wolfSSL_EC_KEY_LoadDer(local, (const unsigned char*)key->pkey.ptr,
+                    key->pkey_sz) != SSL_SUCCESS) {
+            /* now try public key */
+            if (wolfSSL_EC_KEY_LoadDer_ex(local,
+                    (const unsigned char*)key->pkey.ptr,
+                    key->pkey_sz, WOLFSSL_EC_KEY_LOAD_PUBLIC) != SSL_SUCCESS) {
+
+                wolfSSL_EC_KEY_free(local);
+                local = NULL;
+            }
+        }
+    }
+    else {
+        WOLFSSL_MSG("WOLFSSL_EVP_PKEY does not hold an EC key");
+        wolfSSL_EC_KEY_free(local);
+        local = NULL;
+    }
+#ifdef OPENSSL_ALL
+    if (!local && key->ecc) {
+        local = wolfSSL_EC_KEY_dup(key->ecc);
+    }
+#endif
+    return local;
+}
+#endif /* HAVE_ECC */
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+#if !defined(NO_DH) && !defined(NO_FILESYSTEM)
+/* with set1 functions the pkey struct does not own the DH structure
+ * Build the following DH Key format from the passed in WOLFSSL_DH
+ * then store in WOLFSSL_EVP_PKEY in DER format.
+ *
+ * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure
+ */
+int wolfSSL_EVP_PKEY_set1_DH(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_DH *key)
+{
+    byte havePublic = 0, havePrivate = 0;
+    int ret;
+    word32 derSz = 0;
+    byte* derBuf = NULL;
+    DhKey* dhkey = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_EVP_PKEY_set1_DH");
+
+    if (pkey == NULL || key == NULL)
+        return WOLFSSL_FAILURE;
+
+    if (pkey->dh != NULL && pkey->ownDh == 1)
+        wolfSSL_DH_free(pkey->dh);
+
+    pkey->dh    = key;
+    pkey->ownDh = 0; /* pkey does not own DH */
+    pkey->type  = EVP_PKEY_DH;
+    if (key->inSet == 0) {
+        if (SetDhInternal(key) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetDhInternal failed");
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+    dhkey = (DhKey*)key->internal;
+
+    havePublic  = mp_unsigned_bin_size(&dhkey->pub)  > 0;
+    havePrivate = mp_unsigned_bin_size(&dhkey->priv) > 0;
+
+    /* Get size of DER buffer only */
+    if (havePublic && !havePrivate) {
+        ret = wc_DhPubKeyToDer(dhkey, NULL, &derSz);
+    } else if (havePrivate && !havePublic) {
+        ret = wc_DhPrivKeyToDer(dhkey, NULL, &derSz);
+    } else {
+        ret = wc_DhParamsToDer(dhkey,NULL,&derSz);
+    }
+
+    if (derSz <= 0 || ret != LENGTH_ONLY_E) {
+       WOLFSSL_MSG("Failed to get size of DH Key");
+       return WOLFSSL_FAILURE;
+    }
+
+    derBuf = (byte*)XMALLOC(derSz, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (derBuf == NULL) {
+        WOLFSSL_MSG("malloc failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* Fill DER buffer */
+    if (havePublic && !havePrivate) {
+        ret = wc_DhPubKeyToDer(dhkey, derBuf, &derSz);
+    } else if (havePrivate && !havePublic) {
+        ret = wc_DhPrivKeyToDer(dhkey, derBuf, &derSz);
+    } else {
+        ret = wc_DhParamsToDer(dhkey,derBuf,&derSz);
+    }
+
+    if (ret <= 0) {
+        WOLFSSL_MSG("Failed to export DH Key");
+        XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* Store DH key into pkey (DER format) */
+    pkey->pkey.ptr = (char*)derBuf;
+    pkey->pkey_sz = derSz;
+
+    return WOLFSSL_SUCCESS;
+}
+
+WOLFSSL_DH* wolfSSL_EVP_PKEY_get0_DH(WOLFSSL_EVP_PKEY* key)
+{
+    if (!key) {
+        return NULL;
+    }
+    return key->dh;
+}
+
+WOLFSSL_DH* wolfSSL_EVP_PKEY_get1_DH(WOLFSSL_EVP_PKEY* key)
+{
+    WOLFSSL_DH* local = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_EVP_PKEY_get1_DH");
+
+    if (key == NULL || key->dh == NULL) {
+        WOLFSSL_MSG("Bad function argument");
+        return NULL;
+    }
+
+    if (key->type == EVP_PKEY_DH) {
+        local = wolfSSL_DH_new();
+        if (local == NULL) {
+            WOLFSSL_MSG("Error creating a new WOLFSSL_DH structure");
+            return NULL;
+        }
+
+        if (wolfSSL_DH_LoadDer(local, (const unsigned char*)key->pkey.ptr,
+                    key->pkey_sz) != SSL_SUCCESS) {
+            wolfSSL_DH_free(local);
+            WOLFSSL_MSG("Error wolfSSL_DH_LoadDer");
+            local = NULL;
+        }
+    }
+    else {
+        WOLFSSL_MSG("WOLFSSL_EVP_PKEY does not hold a DH key");
+        wolfSSL_DH_free(local);
+        return NULL;
+    }
+
+    return local;
+}
+#endif /* NO_DH && NO_FILESYSTEM */
+
+int wolfSSL_EVP_PKEY_assign(WOLFSSL_EVP_PKEY *pkey, int type, void *key)
+{
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_EVP_PKEY_assign");
+
+    /* pkey and key checked if NULL in subsequent assign functions */
+    switch(type) {
+    #ifndef NO_RSA
+        case EVP_PKEY_RSA:
+            ret = wolfSSL_EVP_PKEY_assign_RSA(pkey, (WOLFSSL_RSA*)key);
+            break;
+    #endif
+    #ifndef NO_DSA
+        case EVP_PKEY_DSA:
+            ret = wolfSSL_EVP_PKEY_assign_DSA(pkey, (WOLFSSL_DSA*)key);
+            break;
+    #endif
+    #ifdef HAVE_ECC
+        case EVP_PKEY_EC:
+            ret = wolfSSL_EVP_PKEY_assign_EC_KEY(pkey, (WOLFSSL_EC_KEY*)key);
+            break;
+    #endif
+    #ifdef NO_DH
+         case EVP_PKEY_DH:
+            ret = wolfSSL_EVP_PKEY_assign_DH(pkey, (WOLFSSL_DH*)key);
+            break;
+    #endif
+        default:
+            WOLFSSL_MSG("Unknown EVP_PKEY type in wolfSSL_EVP_PKEY_assign.");
+            ret = WOLFSSL_FAILURE;
+    }
+
+    return ret;
+}
+#endif /* WOLFSSL_QT || OPENSSL_ALL */
+
+#if defined(HAVE_ECC)
+/* try and populate public pkey_sz and pkey.ptr */
+static void ECC_populate_EVP_PKEY(EVP_PKEY* pkey, ecc_key* ecc)
+{
+    int ret;
+    if (!pkey || !ecc)
+        return;
+    if ((ret = wc_EccPublicKeyDerSize(ecc, 1)) > 0) {
+        int derSz = ret;
+        char* derBuf = (char*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (derBuf) {
+            ret = wc_EccPublicKeyToDer(ecc, (byte*)derBuf, derSz, 1);
+            if (ret >= 0) {
+                if (pkey->pkey.ptr) {
+                    XFREE(pkey->pkey.ptr, NULL, DYNAMIC_TYPE_OPENSSL);
+                }
+                pkey->pkey_sz = ret;
+                pkey->pkey.ptr = derBuf;
+            }
+            else { /* failure - okay to ignore */
+                XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                derBuf = NULL;
+            }
+        }
+    }
+}
+
+WOLFSSL_API int wolfSSL_EVP_PKEY_set1_EC_KEY(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_EC_KEY *key)
+{
+#ifdef HAVE_ECC
+    if((pkey == NULL) || (key ==NULL))return WOLFSSL_FAILURE;
+    WOLFSSL_ENTER("wolfSSL_EVP_PKEY_set1_EC_KEY");
+#ifndef NO_RSA
+    if (pkey->rsa != NULL && pkey->ownRsa == 1) {
+        wolfSSL_RSA_free(pkey->rsa);
+    }
+    pkey->ownRsa = 0;
+#endif
+#ifndef NO_DSA
+    if (pkey->dsa != NULL && pkey->ownDsa == 1) {
+        wolfSSL_DSA_free(pkey->dsa);
+    }
+    pkey->ownDsa = 0;
+#endif
+#ifndef NO_DH
+    if (pkey->dh != NULL && pkey->ownDh == 1) {
+        wolfSSL_DH_free(pkey->dh);
+    }
+    pkey->ownDh = 0;
+#endif
+    if (pkey->ecc != NULL && pkey->ownEcc == 1) {
+        wolfSSL_EC_KEY_free(pkey->ecc);
+    }
+    pkey->ecc    = key;
+    pkey->ownEcc = 0; /* pkey does not own EC key */
+    pkey->type   = EVP_PKEY_EC;
+    ECC_populate_EVP_PKEY(pkey, (ecc_key*)key->internal);
+    return WOLFSSL_SUCCESS;
+#else
+    (void)pkey;
+    (void)key;
+    return WOLFSSL_FAILURE;
+#endif
+}
+
+void* wolfSSL_EVP_X_STATE(const WOLFSSL_EVP_CIPHER_CTX* ctx)
+{
+    WOLFSSL_MSG("wolfSSL_EVP_X_STATE");
+
+    if (ctx) {
+        switch (ctx->cipherType) {
+            case ARC4_TYPE:
+                WOLFSSL_MSG("returning arc4 state");
+                return (void*)&ctx->cipher.arc4.x;
+
+            default:
+                WOLFSSL_MSG("bad x state type");
+                return 0;
+        }
+    }
+
+    return NULL;
+}
+int wolfSSL_EVP_PKEY_assign_EC_KEY(EVP_PKEY* pkey, WOLFSSL_EC_KEY* key)
+{
+    if (pkey == NULL || key == NULL)
+        return WOLFSSL_FAILURE;
+
+    pkey->type = EVP_PKEY_EC;
+    pkey->ecc = key;
+    pkey->ownEcc = 1;
+
+    /* try and populate public pkey_sz and pkey.ptr */
+    ECC_populate_EVP_PKEY(pkey, (ecc_key*)key->internal);
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* HAVE_ECC */
+
+#ifndef NO_WOLFSSL_STUB
+const WOLFSSL_EVP_MD* wolfSSL_EVP_ripemd160(void)
+{
+    WOLFSSL_MSG("wolfSSL_ripemd160");
+    WOLFSSL_STUB("EVP_ripemd160");
+    return NULL;
+}
+#endif
+
+
+int wolfSSL_EVP_MD_block_size(const WOLFSSL_EVP_MD* type)
+{
+    WOLFSSL_MSG("wolfSSL_EVP_MD_block_size");
+
+    if (type == NULL) {
+        WOLFSSL_MSG("No md type arg");
+        return BAD_FUNC_ARG;
+    }
+
+    if (XSTRNCMP(type, "SHA256", 6) == 0) {
+        return WC_SHA256_BLOCK_SIZE;
+    }
+#ifndef NO_MD5
+    else if (XSTRNCMP(type, "MD5", 3) == 0) {
+        return WC_MD5_BLOCK_SIZE;
+    }
+#endif
+#ifdef WOLFSSL_SHA224
+    else if (XSTRNCMP(type, "SHA224", 6) == 0) {
+        return WC_SHA224_BLOCK_SIZE;
+    }
+#endif
+#ifdef WOLFSSL_SHA384
+    else if (XSTRNCMP(type, "SHA384", 6) == 0) {
+        return WC_SHA384_BLOCK_SIZE;
+    }
+#endif
+#ifdef WOLFSSL_SHA512
+    else if (XSTRNCMP(type, "SHA512", 6) == 0) {
+        return WC_SHA512_BLOCK_SIZE;
+    }
+#endif
+#ifndef NO_SHA
+    /* has to be last since would pick or 256, 384, or 512 too */
+    else if (XSTRNCMP(type, "SHA", 3) == 0) {
+        return WC_SHA_BLOCK_SIZE;
+    }
+#endif
+
+    return BAD_FUNC_ARG;
+}
+
+int wolfSSL_EVP_MD_size(const WOLFSSL_EVP_MD* type)
+{
+    WOLFSSL_MSG("wolfSSL_EVP_MD_size");
+
+    if (type == NULL) {
+        WOLFSSL_MSG("No md type arg");
+        return BAD_FUNC_ARG;
+    }
+
+    if (XSTRNCMP(type, "SHA256", 6) == 0) {
+        return WC_SHA256_DIGEST_SIZE;
+    }
+#ifndef NO_MD5
+    else if (XSTRNCMP(type, "MD5", 3) == 0) {
+        return WC_MD5_DIGEST_SIZE;
+    }
+#endif
+#ifdef WOLFSSL_SHA224
+    else if (XSTRNCMP(type, "SHA224", 6) == 0) {
+        return WC_SHA224_DIGEST_SIZE;
+    }
+#endif
+#ifdef WOLFSSL_SHA384
+    else if (XSTRNCMP(type, "SHA384", 6) == 0) {
+        return WC_SHA384_DIGEST_SIZE;
+    }
+#endif
+#ifdef WOLFSSL_SHA512
+    else if (XSTRNCMP(type, "SHA512", 6) == 0) {
+        return WC_SHA512_DIGEST_SIZE;
+    }
+#endif
+#ifndef NO_SHA
+    /* has to be last since would pick or 256, 384, or 512 too */
+    else if (XSTRNCMP(type, "SHA", 3) == 0) {
+        return WC_SHA_DIGEST_SIZE;
+    }
+#endif
+
+    return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_EVP_CIPHER_CTX_iv_length(const WOLFSSL_EVP_CIPHER_CTX* ctx)
+{
+    WOLFSSL_MSG("wolfSSL_EVP_CIPHER_CTX_iv_length");
+
+    switch (ctx->cipherType) {
+
+#ifdef HAVE_AES_CBC
+        case AES_128_CBC_TYPE :
+        case AES_192_CBC_TYPE :
+        case AES_256_CBC_TYPE :
+            WOLFSSL_MSG("AES CBC");
+            return AES_BLOCK_SIZE;
+#endif
+#ifdef HAVE_AESGCM
+        case AES_128_GCM_TYPE :
+        case AES_192_GCM_TYPE :
+        case AES_256_GCM_TYPE :
+            WOLFSSL_MSG("AES GCM");
+            return GCM_NONCE_MID_SZ;
+#endif
+#ifdef WOLFSSL_AES_COUNTER
+        case AES_128_CTR_TYPE :
+        case AES_192_CTR_TYPE :
+        case AES_256_CTR_TYPE :
+            WOLFSSL_MSG("AES CTR");
+            return AES_BLOCK_SIZE;
+#endif
+#ifndef NO_DES3
+        case DES_CBC_TYPE :
+            WOLFSSL_MSG("DES CBC");
+            return DES_BLOCK_SIZE;
+
+        case DES_EDE3_CBC_TYPE :
+            WOLFSSL_MSG("DES EDE3 CBC");
+            return DES_BLOCK_SIZE;
+#endif
+#ifdef HAVE_IDEA
+        case IDEA_CBC_TYPE :
+            WOLFSSL_MSG("IDEA CBC");
+            return IDEA_BLOCK_SIZE;
+#endif
+#ifndef NO_RC4
+        case ARC4_TYPE :
+            WOLFSSL_MSG("ARC4");
+            return 0;
+#endif
+#ifdef WOLFSSL_AES_CFB
+#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS)
+        case AES_128_CFB1_TYPE:
+        case AES_192_CFB1_TYPE:
+        case AES_256_CFB1_TYPE:
+            WOLFSSL_MSG("AES CFB1");
+            return AES_BLOCK_SIZE;
+        case AES_128_CFB8_TYPE:
+        case AES_192_CFB8_TYPE:
+        case AES_256_CFB8_TYPE:
+            WOLFSSL_MSG("AES CFB8");
+            return AES_BLOCK_SIZE;
+#endif /* !HAVE_SELFTEST && !HAVE_FIPS */
+        case AES_128_CFB128_TYPE:
+        case AES_192_CFB128_TYPE:
+        case AES_256_CFB128_TYPE:
+            WOLFSSL_MSG("AES CFB128");
+            return AES_BLOCK_SIZE;
+#endif /* WOLFSSL_AES_CFB */
+#if defined(WOLFSSL_AES_OFB)
+        case AES_128_OFB_TYPE:
+        case AES_192_OFB_TYPE:
+        case AES_256_OFB_TYPE:
+            WOLFSSL_MSG("AES OFB");
+            return AES_BLOCK_SIZE;
+#endif /* WOLFSSL_AES_OFB */
+#ifdef WOLFSSL_AES_XTS
+        case AES_128_XTS_TYPE:
+        case AES_256_XTS_TYPE:
+            WOLFSSL_MSG("AES XTS");
+            return AES_BLOCK_SIZE;
+#endif /* WOLFSSL_AES_XTS */
+
+        case NULL_CIPHER_TYPE :
+            WOLFSSL_MSG("NULL");
+            return 0;
+
+        default: {
+            WOLFSSL_MSG("bad type");
+        }
+    }
+    return 0;
+}
+
+int wolfSSL_EVP_CIPHER_iv_length(const WOLFSSL_EVP_CIPHER* cipher)
+{
+    const char *name = (const char *)cipher;
+    WOLFSSL_MSG("wolfSSL_EVP_CIPHER_iv_length");
+
+#ifndef NO_AES
+#ifdef HAVE_AES_CBC
+    #ifdef WOLFSSL_AES_128
+    if (EVP_AES_128_CBC && XSTRNCMP(name, EVP_AES_128_CBC, XSTRLEN(EVP_AES_128_CBC)) == 0)
+        return AES_BLOCK_SIZE;
+    #endif
+    #ifdef WOLFSSL_AES_192
+    if (EVP_AES_192_CBC && XSTRNCMP(name, EVP_AES_192_CBC, XSTRLEN(EVP_AES_192_CBC)) == 0)
+        return AES_BLOCK_SIZE;
+    #endif
+    #ifdef WOLFSSL_AES_256
+    if (EVP_AES_256_CBC && XSTRNCMP(name, EVP_AES_256_CBC, XSTRLEN(EVP_AES_256_CBC)) == 0)
+        return AES_BLOCK_SIZE;
+    #endif
+#endif /* HAVE_AES_CBC */
+#ifdef HAVE_AESGCM
+    #ifdef WOLFSSL_AES_128
+    if (EVP_AES_128_GCM && XSTRNCMP(name, EVP_AES_128_GCM, XSTRLEN(EVP_AES_128_GCM)) == 0)
+        return GCM_NONCE_MID_SZ;
+    #endif
+    #ifdef WOLFSSL_AES_192
+    if (EVP_AES_192_GCM && XSTRNCMP(name, EVP_AES_192_GCM, XSTRLEN(EVP_AES_192_GCM)) == 0)
+        return GCM_NONCE_MID_SZ;
+    #endif
+    #ifdef WOLFSSL_AES_256
+    if (EVP_AES_256_GCM && XSTRNCMP(name, EVP_AES_256_GCM, XSTRLEN(EVP_AES_256_GCM)) == 0)
+        return GCM_NONCE_MID_SZ;
+    #endif
+#endif /* HAVE_AESGCM */
+#ifdef WOLFSSL_AES_COUNTER
+    #ifdef WOLFSSL_AES_128
+    if (EVP_AES_128_CTR && XSTRNCMP(name, EVP_AES_128_CTR, XSTRLEN(EVP_AES_128_CTR)) == 0)
+        return AES_BLOCK_SIZE;
+    #endif
+    #ifdef WOLFSSL_AES_192
+    if (EVP_AES_192_CTR && XSTRNCMP(name, EVP_AES_192_CTR, XSTRLEN(EVP_AES_192_CTR)) == 0)
+        return AES_BLOCK_SIZE;
+    #endif
+    #ifdef WOLFSSL_AES_256
+    if (EVP_AES_256_CTR && XSTRNCMP(name, EVP_AES_256_CTR, XSTRLEN(EVP_AES_256_CTR)) == 0)
+        return AES_BLOCK_SIZE;
+    #endif
+#endif
+#ifdef WOLFSSL_AES_XTS
+    #ifdef WOLFSSL_AES_128
+    if (EVP_AES_128_XTS && XSTRNCMP(name, EVP_AES_128_XTS, XSTRLEN(EVP_AES_128_XTS)) == 0)
+        return AES_BLOCK_SIZE;
+    #endif /* WOLFSSL_AES_128 */
+
+    #ifdef WOLFSSL_AES_256
+    if (EVP_AES_256_XTS && XSTRNCMP(name, EVP_AES_256_XTS, XSTRLEN(EVP_AES_256_XTS)) == 0)
+        return AES_BLOCK_SIZE;
+    #endif /* WOLFSSL_AES_256 */
+#endif /* WOLFSSL_AES_XTS */
+
+#endif
+
+#ifndef NO_DES3
+    if ((EVP_DES_CBC && XSTRNCMP(name, EVP_DES_CBC, XSTRLEN(EVP_DES_CBC)) == 0) ||
+           (EVP_DES_EDE3_CBC && XSTRNCMP(name, EVP_DES_EDE3_CBC, XSTRLEN(EVP_DES_EDE3_CBC)) == 0)) {
+        return DES_BLOCK_SIZE;
+    }
+#endif
+
+#ifdef HAVE_IDEA
+    if (EVP_IDEA_CBC && XSTRNCMP(name, EVP_IDEA_CBC, XSTRLEN(EVP_IDEA_CBC)) == 0)
+        return IDEA_BLOCK_SIZE;
+#endif
+
+    (void)name;
+
+    return 0;
+}
+
+
+int wolfSSL_EVP_X_STATE_LEN(const WOLFSSL_EVP_CIPHER_CTX* ctx)
+{
+    WOLFSSL_MSG("wolfSSL_EVP_X_STATE_LEN");
+
+    if (ctx) {
+        switch (ctx->cipherType) {
+            case ARC4_TYPE:
+                WOLFSSL_MSG("returning arc4 state size");
+                return sizeof(Arc4);
+
+            default:
+                WOLFSSL_MSG("bad x state type");
+                return 0;
+        }
+    }
+
+    return 0;
+}
+
+
+/* return of pkey->type which will be EVP_PKEY_RSA for example.
+ *
+ * type  type of EVP_PKEY
+ *
+ * returns type or if type is not found then NID_undef
+ */
+int wolfSSL_EVP_PKEY_type(int type)
+{
+    WOLFSSL_MSG("wolfSSL_EVP_PKEY_type");
+
+    switch (type) {
+        case EVP_PKEY_RSA:
+            return EVP_PKEY_RSA;
+        case EVP_PKEY_DSA:
+            return EVP_PKEY_DSA;
+        case EVP_PKEY_EC:
+            return EVP_PKEY_EC;
+        case EVP_PKEY_DH:
+            return EVP_PKEY_DH;
+        default:
+            return NID_undef;
+    }
+}
+
+
+int wolfSSL_EVP_PKEY_id(const EVP_PKEY *pkey)
+{
+    if (pkey != NULL)
+        return pkey->type;
+    return 0;
+}
+
+
+int wolfSSL_EVP_PKEY_base_id(const EVP_PKEY *pkey)
+{
+    if (pkey == NULL)
+        return NID_undef;
+    return wolfSSL_EVP_PKEY_type(pkey->type);
+}
+
+
+/* increments ref count of WOLFSSL_EVP_PKEY. Return 1 on success, 0 on error */
+int wolfSSL_EVP_PKEY_up_ref(WOLFSSL_EVP_PKEY* pkey)
+{
+    if (pkey) {
+        if (wc_LockMutex(&pkey->refMutex) != 0) {
+            WOLFSSL_MSG("Failed to lock pkey mutex");
+        }
+        pkey->references++;
+        wc_UnLockMutex(&pkey->refMutex);
+
+        return 1;
+    }
+
+    return 0;
+}
+
+#ifndef NO_RSA
+int wolfSSL_EVP_PKEY_assign_RSA(EVP_PKEY* pkey, WOLFSSL_RSA* key)
+{
+    if (pkey == NULL || key == NULL)
+        return WOLFSSL_FAILURE;
+
+    pkey->type = EVP_PKEY_RSA;
+    pkey->rsa = key;
+    pkey->ownRsa = 1;
+
+    /* try and populate public pkey_sz and pkey.ptr */
+    if (key->internal) {
+        RsaKey* rsa = (RsaKey*)key->internal;
+        int ret = wc_RsaPublicKeyDerSize(rsa, 1);
+        if (ret > 0) {
+            int derSz = ret;
+            char* derBuf = (char*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            if (derBuf) {
+                ret = wc_RsaKeyToPublicDer(rsa, (byte*)derBuf, derSz);
+                if (ret >= 0) {
+                    pkey->pkey_sz = ret;
+                    pkey->pkey.ptr = derBuf;
+                }
+                else { /* failure - okay to ignore */
+                    XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                    derBuf = NULL;
+                }
+            }
+        }
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* !NO_RSA */
+
+#ifndef NO_DSA
+int wolfSSL_EVP_PKEY_assign_DSA(EVP_PKEY* pkey, WOLFSSL_DSA* key)
+{
+    if (pkey == NULL || key == NULL)
+        return WOLFSSL_FAILURE;
+
+    pkey->type = EVP_PKEY_DSA;
+    pkey->dsa = key;
+    pkey->ownDsa = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* !NO_DSA */
+
+#ifndef NO_DH
+int wolfSSL_EVP_PKEY_assign_DH(EVP_PKEY* pkey, WOLFSSL_DH* key)
+{
+    if (pkey == NULL || key == NULL)
+        return WOLFSSL_FAILURE;
+
+    pkey->type = EVP_PKEY_DH;
+    pkey->dh = key;
+    pkey->ownDh = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* !NO_DH */
+
+#endif /* OPENSSL_EXTRA */
+
+#if defined(OPENSSL_EXTRA_X509_SMALL)
+/* Subset of OPENSSL_EXTRA for PKEY operations PKEY free is needed by the
+ * subset of X509 API */
+
+WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new(void){
+    return wolfSSL_EVP_PKEY_new_ex(NULL);
+}
+
+WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_ex(void* heap)
+{
+    WOLFSSL_EVP_PKEY* pkey;
+    int ret;
+    WOLFSSL_ENTER("wolfSSL_EVP_PKEY_new_ex");
+    pkey = (WOLFSSL_EVP_PKEY*)XMALLOC(sizeof(WOLFSSL_EVP_PKEY), heap,
+            DYNAMIC_TYPE_PUBLIC_KEY);
+    if (pkey != NULL) {
+        XMEMSET(pkey, 0, sizeof(WOLFSSL_EVP_PKEY));
+        pkey->heap = heap;
+        pkey->type = WOLFSSL_EVP_PKEY_DEFAULT;
+#ifndef HAVE_FIPS
+        ret = wc_InitRng_ex(&pkey->rng, heap, INVALID_DEVID);
+#else
+        ret = wc_InitRng(&pkey->rng);
+#endif
+        if (ret != 0){
+            wolfSSL_EVP_PKEY_free(pkey);
+            WOLFSSL_MSG("memory failure");
+            return NULL;
+        }
+        pkey->references = 1;
+        wc_InitMutex(&pkey->refMutex);
+    }
+    else {
+        WOLFSSL_MSG("memory failure");
+    }
+
+    return pkey;
+}
+
+void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY* key)
+{
+    int doFree = 0;
+    WOLFSSL_ENTER("wolfSSL_EVP_PKEY_free");
+    if (key != NULL) {
+        if (wc_LockMutex(&key->refMutex) != 0) {
+            WOLFSSL_MSG("Couldn't lock pkey mutex");
+        }
+
+        /* only free if all references to it are done */
+        key->references--;
+        if (key->references == 0) {
+            doFree = 1;
+        }
+        wc_UnLockMutex(&key->refMutex);
+
+        if (doFree) {
+            wc_FreeRng(&key->rng);
+
+            if (key->pkey.ptr != NULL) {
+                XFREE(key->pkey.ptr, key->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+                key->pkey.ptr = NULL;
+            }
+            switch(key->type)
+            {
+                #ifndef NO_RSA
+                case EVP_PKEY_RSA:
+                    if (key->rsa != NULL && key->ownRsa == 1) {
+                        wolfSSL_RSA_free(key->rsa);
+                        key->rsa = NULL;
+                    }
+                    break;
+                #endif /* NO_RSA */
+
+                #if defined(HAVE_ECC) && defined(OPENSSL_EXTRA)
+                case EVP_PKEY_EC:
+                    if (key->ecc != NULL && key->ownEcc == 1) {
+                        wolfSSL_EC_KEY_free(key->ecc);
+                        key->ecc = NULL;
+                    }
+                    break;
+                #endif /* HAVE_ECC && OPENSSL_EXTRA */
+
+                #ifndef NO_DSA
+                case EVP_PKEY_DSA:
+                    if (key->dsa != NULL && key->ownDsa == 1) {
+                        wolfSSL_DSA_free(key->dsa);
+                        key->dsa = NULL;
+                    }
+                    break;
+                #endif /* NO_DSA */
+
+                #if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
+                case EVP_PKEY_DH:
+                    if (key->dh != NULL && key->ownDh == 1) {
+                        wolfSSL_DH_free(key->dh);
+                        key->dh = NULL;
+                    }
+                    break;
+                #endif /* ! NO_DH ... */
+
+                default:
+                break;
+            }
+
+            if (wc_FreeMutex(&key->refMutex) != 0) {
+                WOLFSSL_MSG("Couldn't free pkey mutex");
+            }
+            XFREE(key, key->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        }
+    }
+}
+
+#endif /* OPENSSL_EXTRA_X509_SMALL */
+
+#endif /* WOLFSSL_EVP_INCLUDED */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/hash.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/hash.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/hash.c	(revision 453)
@@ -0,0 +1,1677 @@
+/* hash.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+#include <wolfssl/wolfcrypt/logging.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#ifndef NO_ASN
+#include <wolfssl/wolfcrypt/asn.h>
+#endif
+
+#include <wolfssl/wolfcrypt/hash.h>
+#include <wolfssl/wolfcrypt/hmac.h>
+
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+
+#ifdef NO_ASN
+enum Hash_Sum  {
+    MD2h      = 646,
+    MD5h      = 649,
+    SHAh      =  88,
+    SHA224h   = 417,
+    SHA256h   = 414,
+    SHA384h   = 415,
+    SHA512h   = 416,
+    SHA3_224h = 420,
+    SHA3_256h = 421,
+    SHA3_384h = 422,
+    SHA3_512h = 423
+};
+#endif /* !NO_ASN */
+
+#if !defined(NO_PWDBASED) || !defined(NO_ASN)
+/* function converts int hash type to enum */
+enum wc_HashType wc_HashTypeConvert(int hashType)
+{
+    /* Default to hash type none as error */
+    enum wc_HashType eHashType = WC_HASH_TYPE_NONE;
+#if defined(HAVE_FIPS) || defined(HAVE_SELFTEST)
+    /* original FIPSv1  and CAVP selftest require a mapping for unique hash
+       type to wc_HashType */
+    switch (hashType) {
+    #ifndef NO_MD5
+        case WC_MD5:
+            eHashType = WC_HASH_TYPE_MD5;
+            break;
+    #endif /* !NO_MD5 */
+    #ifndef NO_SHA
+        case WC_SHA:
+            eHashType = WC_HASH_TYPE_SHA;
+            break;
+    #endif /* !NO_SHA */
+
+    #ifdef WOLFSSL_SHA224
+        case WC_SHA224:
+            eHashType = WC_HASH_TYPE_SHA224;
+            break;
+    #endif /* WOLFSSL_SHA224 */
+
+    #ifndef NO_SHA256
+        case WC_SHA256:
+            eHashType = WC_HASH_TYPE_SHA256;
+            break;
+    #endif /* !NO_SHA256 */
+
+    #ifdef WOLFSSL_SHA384
+        case WC_SHA384:
+            eHashType = WC_HASH_TYPE_SHA384;
+            break;
+    #endif /* WOLFSSL_SHA384 */
+    #ifdef WOLFSSL_SHA512
+        case WC_SHA512:
+            eHashType = WC_HASH_TYPE_SHA512;
+            break;
+    #endif /* WOLFSSL_SHA512 */
+    #ifdef WOLFSSL_SHA3
+        case WC_SHA3_224:
+            eHashType = WC_HASH_TYPE_SHA3_224;
+            break;
+        case WC_SHA3_256:
+            eHashType = WC_HASH_TYPE_SHA3_256;
+            break;
+        case WC_SHA3_384:
+            eHashType = WC_HASH_TYPE_SHA3_384;
+            break;
+        case WC_SHA3_512:
+            eHashType = WC_HASH_TYPE_SHA3_512;
+            break;
+    #endif /* WOLFSSL_SHA3 */
+        default:
+            eHashType = WC_HASH_TYPE_NONE;
+            break;
+    }
+#else
+    /* current master uses same unique types as wc_HashType */
+    if (hashType > 0 && hashType <= WC_HASH_TYPE_MAX) {
+        eHashType = (enum wc_HashType)hashType;
+    }
+#endif
+    return eHashType;
+}
+#endif /* !NO_PWDBASED || !NO_ASN */
+
+#if !defined(NO_ASN) || !defined(NO_DH) || defined(HAVE_ECC)
+
+int wc_HashGetOID(enum wc_HashType hash_type)
+{
+    int oid = HASH_TYPE_E; /* Default to hash type error */
+    switch(hash_type)
+    {
+        case WC_HASH_TYPE_MD2:
+        #ifdef WOLFSSL_MD2
+            oid = MD2h;
+        #endif
+            break;
+        case WC_HASH_TYPE_MD5_SHA:
+        case WC_HASH_TYPE_MD5:
+        #ifndef NO_MD5
+            oid = MD5h;
+        #endif
+            break;
+        case WC_HASH_TYPE_SHA:
+        #ifndef NO_SHA
+            oid = SHAh;
+        #endif
+            break;
+        case WC_HASH_TYPE_SHA224:
+        #ifdef WOLFSSL_SHA224
+            oid = SHA224h;
+        #endif
+            break;
+        case WC_HASH_TYPE_SHA256:
+        #ifndef NO_SHA256
+            oid = SHA256h;
+        #endif
+            break;
+        case WC_HASH_TYPE_SHA384:
+        #ifdef WOLFSSL_SHA384
+            oid = SHA384h;
+        #endif
+            break;
+        case WC_HASH_TYPE_SHA512:
+        #ifdef WOLFSSL_SHA512
+            oid = SHA512h;
+        #endif
+            break;
+        case WC_HASH_TYPE_SHA3_224:
+        #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224)
+            oid = SHA3_224h;
+        #endif
+            break;
+        case WC_HASH_TYPE_SHA3_256:
+        #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256)
+            oid = SHA3_256h;
+        #endif
+            break;
+        case WC_HASH_TYPE_SHA3_384:
+        #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384)
+            oid = SHA3_384h;
+        #endif
+            break;
+        case WC_HASH_TYPE_SHA3_512:
+        #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512)
+            oid = SHA3_512h;
+        #endif
+            break;
+
+        /* Not Supported */
+        case WC_HASH_TYPE_MD4:
+        case WC_HASH_TYPE_BLAKE2B:
+        case WC_HASH_TYPE_BLAKE2S:
+        case WC_HASH_TYPE_NONE:
+        default:
+            oid = BAD_FUNC_ARG;
+            break;
+    }
+    return oid;
+}
+
+enum wc_HashType wc_OidGetHash(int oid)
+{
+    enum wc_HashType hash_type = WC_HASH_TYPE_NONE;
+    switch (oid)
+    {
+    #ifdef WOLFSSL_MD2
+        case MD2h:
+            hash_type = WC_HASH_TYPE_MD2;
+            break;
+    #endif
+        case MD5h:
+        #ifndef NO_MD5
+            hash_type = WC_HASH_TYPE_MD5;
+        #endif
+            break;
+        case SHAh:
+        #ifndef NO_SHA
+            hash_type = WC_HASH_TYPE_SHA;
+        #endif
+            break;
+        case SHA224h:
+        #ifdef WOLFSSL_SHA224
+            hash_type = WC_HASH_TYPE_SHA224;
+        #endif
+            break;
+        case SHA256h:
+        #ifndef NO_SHA256
+            hash_type = WC_HASH_TYPE_SHA256;
+        #endif
+            break;
+        case SHA384h:
+        #ifdef WOLFSSL_SHA384
+            hash_type = WC_HASH_TYPE_SHA384;
+        #endif
+            break;
+        case SHA512h:
+        #ifdef WOLFSSL_SHA512
+            hash_type = WC_HASH_TYPE_SHA512;
+        #endif
+            break;
+    #ifdef WOLFSSL_SHA3
+        case SHA3_224h:
+            hash_type = WC_HASH_TYPE_SHA3_224;
+            break;
+        case SHA3_256h:
+            hash_type = WC_HASH_TYPE_SHA3_256;
+            break;
+        case SHA3_384h:
+            hash_type = WC_HASH_TYPE_SHA3_384;
+            break;
+        case SHA3_512h:
+            hash_type = WC_HASH_TYPE_SHA3_512;
+            break;
+    #endif /* WOLFSSL_SHA3 */
+        default:
+            break;
+    }
+    return hash_type;
+}
+#endif /* !NO_ASN || !NO_DH || HAVE_ECC */
+
+#ifndef NO_HASH_WRAPPER
+
+/* Get Hash digest size */
+int wc_HashGetDigestSize(enum wc_HashType hash_type)
+{
+    int dig_size = HASH_TYPE_E; /* Default to hash type error */
+    switch(hash_type)
+    {
+        case WC_HASH_TYPE_MD2:
+        #ifdef WOLFSSL_MD2
+            dig_size = MD2_DIGEST_SIZE;
+        #endif
+            break;
+        case WC_HASH_TYPE_MD4:
+        #ifndef NO_MD4
+            dig_size = MD4_DIGEST_SIZE;
+        #endif
+            break;
+        case WC_HASH_TYPE_MD5:
+        #ifndef NO_MD5
+            dig_size = WC_MD5_DIGEST_SIZE;
+        #endif
+            break;
+        case WC_HASH_TYPE_SHA:
+        #ifndef NO_SHA
+            dig_size = WC_SHA_DIGEST_SIZE;
+        #endif
+            break;
+        case WC_HASH_TYPE_SHA224:
+        #ifdef WOLFSSL_SHA224
+            dig_size = WC_SHA224_DIGEST_SIZE;
+        #endif
+            break;
+        case WC_HASH_TYPE_SHA256:
+        #ifndef NO_SHA256
+            dig_size = WC_SHA256_DIGEST_SIZE;
+        #endif
+            break;
+        case WC_HASH_TYPE_SHA384:
+        #ifdef WOLFSSL_SHA384
+            dig_size = WC_SHA384_DIGEST_SIZE;
+        #endif
+            break;
+        case WC_HASH_TYPE_SHA512:
+        #ifdef WOLFSSL_SHA512
+            dig_size = WC_SHA512_DIGEST_SIZE;
+        #endif
+            break;
+        case WC_HASH_TYPE_MD5_SHA: /* Old TLS Specific */
+        #if !defined(NO_MD5) && !defined(NO_SHA)
+            dig_size = (int)WC_MD5_DIGEST_SIZE + (int)WC_SHA_DIGEST_SIZE;
+        #endif
+            break;
+
+        case WC_HASH_TYPE_SHA3_224:
+        #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224)
+            dig_size = WC_SHA3_224_DIGEST_SIZE;
+        #endif
+            break;
+        case WC_HASH_TYPE_SHA3_256:
+        #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256)
+            dig_size = WC_SHA3_256_DIGEST_SIZE;
+        #endif
+            break;
+        case WC_HASH_TYPE_SHA3_384:
+        #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384)
+            dig_size = WC_SHA3_384_DIGEST_SIZE;
+        #endif
+            break;
+        case WC_HASH_TYPE_SHA3_512:
+        #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512)
+            dig_size = WC_SHA3_512_DIGEST_SIZE;
+        #endif
+            break;
+        case WC_HASH_TYPE_BLAKE2B:
+        case WC_HASH_TYPE_BLAKE2S:
+        #if defined(HAVE_BLAKE2) || defined(HAVE_BLAKE2S)
+            dig_size = BLAKE2S_OUTBYTES;
+        #endif
+            break;
+
+        /* Not Supported */
+        case WC_HASH_TYPE_NONE:
+        default:
+            dig_size = BAD_FUNC_ARG;
+            break;
+    }
+    return dig_size;
+}
+
+
+/* Get Hash block size */
+int wc_HashGetBlockSize(enum wc_HashType hash_type)
+{
+    int block_size = HASH_TYPE_E; /* Default to hash type error */
+    switch (hash_type)
+    {
+        case WC_HASH_TYPE_MD2:
+        #ifdef WOLFSSL_MD2
+            block_size = MD2_BLOCK_SIZE;
+        #endif
+            break;
+        case WC_HASH_TYPE_MD4:
+        #ifndef NO_MD4
+            block_size = MD4_BLOCK_SIZE;
+        #endif
+            break;
+        case WC_HASH_TYPE_MD5:
+        #ifndef NO_MD5
+            block_size = WC_MD5_BLOCK_SIZE;
+        #endif
+            break;
+        case WC_HASH_TYPE_SHA:
+        #ifndef NO_SHA
+            block_size = WC_SHA_BLOCK_SIZE;
+        #endif
+            break;
+        case WC_HASH_TYPE_SHA224:
+        #ifdef WOLFSSL_SHA224
+            block_size = WC_SHA224_BLOCK_SIZE;
+        #endif
+            break;
+        case WC_HASH_TYPE_SHA256:
+        #ifndef NO_SHA256
+            block_size = WC_SHA256_BLOCK_SIZE;
+        #endif
+            break;
+        case WC_HASH_TYPE_SHA384:
+        #ifdef WOLFSSL_SHA384
+            block_size = WC_SHA384_BLOCK_SIZE;
+        #endif
+            break;
+        case WC_HASH_TYPE_SHA512:
+        #ifdef WOLFSSL_SHA512
+            block_size = WC_SHA512_BLOCK_SIZE;
+        #endif
+            break;
+        case WC_HASH_TYPE_MD5_SHA: /* Old TLS Specific */
+        #if !defined(NO_MD5) && !defined(NO_SHA)
+            block_size = (int)WC_MD5_BLOCK_SIZE + (int)WC_SHA_BLOCK_SIZE;
+        #endif
+            break;
+
+        case WC_HASH_TYPE_SHA3_224:
+        #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224)
+            block_size = WC_SHA3_224_BLOCK_SIZE;
+        #endif
+            break;
+        case WC_HASH_TYPE_SHA3_256:
+        #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256)
+            block_size = WC_SHA3_256_BLOCK_SIZE;
+        #endif
+            break;
+        case WC_HASH_TYPE_SHA3_384:
+        #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384)
+            block_size = WC_SHA3_384_BLOCK_SIZE;
+        #endif
+            break;
+        case WC_HASH_TYPE_SHA3_512:
+        #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512)
+            block_size = WC_SHA3_512_BLOCK_SIZE;
+        #endif
+            break;
+        case WC_HASH_TYPE_BLAKE2B:
+        case WC_HASH_TYPE_BLAKE2S:
+        #if defined(HAVE_BLAKE2) || defined(HAVE_BLAKE2S)
+            block_size = BLAKE2S_BLOCKBYTES;
+        #endif
+            break;
+
+        /* Not Supported */
+        case WC_HASH_TYPE_NONE:
+        default:
+            block_size = BAD_FUNC_ARG;
+            break;
+    }
+    return block_size;
+}
+
+/* Generic Hashing Wrapper */
+int wc_Hash(enum wc_HashType hash_type, const byte* data,
+    word32 data_len, byte* hash, word32 hash_len)
+{
+    int ret = HASH_TYPE_E; /* Default to hash type error */
+    word32 dig_size;
+
+    /* Validate hash buffer size */
+    dig_size = wc_HashGetDigestSize(hash_type);
+    if (hash_len < dig_size) {
+        return BUFFER_E;
+    }
+
+    /* Suppress possible unused arg if all hashing is disabled */
+    (void)data;
+    (void)data_len;
+    (void)hash;
+    (void)hash_len;
+
+    switch(hash_type)
+    {
+        case WC_HASH_TYPE_MD5:
+#ifndef NO_MD5
+            ret = wc_Md5Hash(data, data_len, hash);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA:
+#ifndef NO_SHA
+            ret = wc_ShaHash(data, data_len, hash);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA224:
+#ifdef WOLFSSL_SHA224
+            ret = wc_Sha224Hash(data, data_len, hash);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA256:
+#ifndef NO_SHA256
+            ret = wc_Sha256Hash(data, data_len, hash);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA384:
+#ifdef WOLFSSL_SHA384
+            ret = wc_Sha384Hash(data, data_len, hash);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA512:
+#ifdef WOLFSSL_SHA512
+            ret = wc_Sha512Hash(data, data_len, hash);
+#endif
+            break;
+        case WC_HASH_TYPE_MD5_SHA:
+#if !defined(NO_MD5) && !defined(NO_SHA)
+            ret = wc_Md5Hash(data, data_len, hash);
+            if (ret == 0) {
+                ret = wc_ShaHash(data, data_len, &hash[WC_MD5_DIGEST_SIZE]);
+            }
+#endif
+            break;
+
+        case WC_HASH_TYPE_SHA3_224:
+#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224)
+            ret = wc_Sha3_224Hash(data, data_len, hash);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA3_256:
+#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256)
+            ret = wc_Sha3_256Hash(data, data_len, hash);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA3_384:
+#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384)
+            ret = wc_Sha3_384Hash(data, data_len, hash);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA3_512:
+#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512)
+            ret = wc_Sha3_512Hash(data, data_len, hash);
+#endif
+            break;
+
+        /* Not Supported */
+        case WC_HASH_TYPE_MD2:
+        case WC_HASH_TYPE_MD4:
+        case WC_HASH_TYPE_BLAKE2B:
+        case WC_HASH_TYPE_BLAKE2S:
+        case WC_HASH_TYPE_NONE:
+        default:
+            ret = BAD_FUNC_ARG;
+            break;
+    }
+    return ret;
+}
+
+int wc_HashInit_ex(wc_HashAlg* hash, enum wc_HashType type, void* heap,
+    int devId)
+{
+    int ret = HASH_TYPE_E; /* Default to hash type error */
+
+    if (hash == NULL)
+        return BAD_FUNC_ARG;
+
+    switch (type) {
+        case WC_HASH_TYPE_MD5:
+#ifndef NO_MD5
+            ret = wc_InitMd5_ex(&hash->md5, heap, devId);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA:
+#ifndef NO_SHA
+            ret = wc_InitSha_ex(&hash->sha, heap, devId);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA224:
+#ifdef WOLFSSL_SHA224
+            ret = wc_InitSha224_ex(&hash->sha224, heap, devId);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA256:
+#ifndef NO_SHA256
+            ret = wc_InitSha256_ex(&hash->sha256, heap, devId);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA384:
+#ifdef WOLFSSL_SHA384
+            ret = wc_InitSha384_ex(&hash->sha384, heap, devId);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA512:
+#ifdef WOLFSSL_SHA512
+            ret = wc_InitSha512_ex(&hash->sha512, heap, devId);
+#endif
+            break;
+
+        case WC_HASH_TYPE_SHA3_224:
+#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224)
+            ret = wc_InitSha3_224(&hash->sha3, heap, devId);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA3_256:
+#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256)
+            ret = wc_InitSha3_256(&hash->sha3, heap, devId);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA3_384:
+#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384)
+            ret = wc_InitSha3_384(&hash->sha3, heap, devId);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA3_512:
+#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512)
+            ret = wc_InitSha3_512(&hash->sha3, heap, devId);
+#endif
+            break;
+
+        /* not supported */
+        case WC_HASH_TYPE_MD5_SHA:
+        case WC_HASH_TYPE_MD2:
+        case WC_HASH_TYPE_MD4:
+        case WC_HASH_TYPE_BLAKE2B:
+        case WC_HASH_TYPE_BLAKE2S:
+        case WC_HASH_TYPE_NONE:
+        default:
+            ret = BAD_FUNC_ARG;
+    };
+
+    return ret;
+}
+
+int wc_HashInit(wc_HashAlg* hash, enum wc_HashType type)
+{
+    return wc_HashInit_ex(hash, type, NULL, INVALID_DEVID);
+}
+
+int wc_HashUpdate(wc_HashAlg* hash, enum wc_HashType type, const byte* data,
+                  word32 dataSz)
+{
+    int ret = HASH_TYPE_E; /* Default to hash type error */
+
+    if (hash == NULL || data == NULL)
+        return BAD_FUNC_ARG;
+
+    switch (type) {
+        case WC_HASH_TYPE_MD5:
+#ifndef NO_MD5
+            ret = wc_Md5Update(&hash->md5, data, dataSz);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA:
+#ifndef NO_SHA
+            ret = wc_ShaUpdate(&hash->sha, data, dataSz);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA224:
+#ifdef WOLFSSL_SHA224
+            ret = wc_Sha224Update(&hash->sha224, data, dataSz);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA256:
+#ifndef NO_SHA256
+            ret = wc_Sha256Update(&hash->sha256, data, dataSz);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA384:
+#ifdef WOLFSSL_SHA384
+            ret = wc_Sha384Update(&hash->sha384, data, dataSz);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA512:
+#ifdef WOLFSSL_SHA512
+            ret = wc_Sha512Update(&hash->sha512, data, dataSz);
+#endif
+            break;
+
+        case WC_HASH_TYPE_SHA3_224:
+#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224)
+            ret = wc_Sha3_224_Update(&hash->sha3, data, dataSz);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA3_256:
+#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256)
+            ret = wc_Sha3_256_Update(&hash->sha3, data, dataSz);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA3_384:
+#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384)
+            ret = wc_Sha3_384_Update(&hash->sha3, data, dataSz);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA3_512:
+#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512)
+            ret = wc_Sha3_512_Update(&hash->sha3, data, dataSz);
+#endif
+            break;
+
+        /* not supported */
+        case WC_HASH_TYPE_MD5_SHA:
+        case WC_HASH_TYPE_MD2:
+        case WC_HASH_TYPE_MD4:
+        case WC_HASH_TYPE_BLAKE2B:
+        case WC_HASH_TYPE_BLAKE2S:
+        case WC_HASH_TYPE_NONE:
+        default:
+            ret = BAD_FUNC_ARG;
+    };
+
+    return ret;
+}
+
+int wc_HashFinal(wc_HashAlg* hash, enum wc_HashType type, byte* out)
+{
+    int ret = HASH_TYPE_E; /* Default to hash type error */
+
+    if (hash == NULL || out == NULL)
+        return BAD_FUNC_ARG;
+
+    switch (type) {
+        case WC_HASH_TYPE_MD5:
+#ifndef NO_MD5
+            ret = wc_Md5Final(&hash->md5, out);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA:
+#ifndef NO_SHA
+            ret = wc_ShaFinal(&hash->sha, out);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA224:
+#ifdef WOLFSSL_SHA224
+            ret = wc_Sha224Final(&hash->sha224, out);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA256:
+#ifndef NO_SHA256
+            ret = wc_Sha256Final(&hash->sha256, out);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA384:
+#ifdef WOLFSSL_SHA384
+            ret = wc_Sha384Final(&hash->sha384, out);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA512:
+#ifdef WOLFSSL_SHA512
+            ret = wc_Sha512Final(&hash->sha512, out);
+#endif
+            break;
+
+        case WC_HASH_TYPE_SHA3_224:
+#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224)
+            ret = wc_Sha3_224_Final(&hash->sha3, out);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA3_256:
+#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256)
+            ret = wc_Sha3_256_Final(&hash->sha3, out);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA3_384:
+#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384)
+            ret = wc_Sha3_384_Final(&hash->sha3, out);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA3_512:
+#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512)
+            ret = wc_Sha3_512_Final(&hash->sha3, out);
+#endif
+            break;
+
+        /* not supported */
+        case WC_HASH_TYPE_MD5_SHA:
+        case WC_HASH_TYPE_MD2:
+        case WC_HASH_TYPE_MD4:
+        case WC_HASH_TYPE_BLAKE2B:
+        case WC_HASH_TYPE_BLAKE2S:
+        case WC_HASH_TYPE_NONE:
+        default:
+            ret = BAD_FUNC_ARG;
+    };
+
+    return ret;
+}
+
+int wc_HashFree(wc_HashAlg* hash, enum wc_HashType type)
+{
+    int ret = HASH_TYPE_E; /* Default to hash type error */
+
+    if (hash == NULL)
+        return BAD_FUNC_ARG;
+
+    switch (type) {
+        case WC_HASH_TYPE_MD5:
+#ifndef NO_MD5
+            wc_Md5Free(&hash->md5);
+            ret = 0;
+#endif
+            break;
+        case WC_HASH_TYPE_SHA:
+#ifndef NO_SHA
+            wc_ShaFree(&hash->sha);
+            ret = 0;
+#endif
+            break;
+        case WC_HASH_TYPE_SHA224:
+#ifdef WOLFSSL_SHA224
+            wc_Sha224Free(&hash->sha224);
+            ret = 0;
+#endif
+            break;
+        case WC_HASH_TYPE_SHA256:
+#ifndef NO_SHA256
+            wc_Sha256Free(&hash->sha256);
+            ret = 0;
+#endif
+            break;
+        case WC_HASH_TYPE_SHA384:
+#ifdef WOLFSSL_SHA384
+            wc_Sha384Free(&hash->sha384);
+            ret = 0;
+#endif
+            break;
+        case WC_HASH_TYPE_SHA512:
+#ifdef WOLFSSL_SHA512
+            wc_Sha512Free(&hash->sha512);
+            ret = 0;
+#endif
+            break;
+
+        case WC_HASH_TYPE_SHA3_224:
+#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224)
+            wc_Sha3_224_Free(&hash->sha3);
+            ret = 0;
+#endif
+            break;
+        case WC_HASH_TYPE_SHA3_256:
+#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256)
+            wc_Sha3_256_Free(&hash->sha3);
+            ret = 0;
+#endif
+            break;
+        case WC_HASH_TYPE_SHA3_384:
+#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384)
+            wc_Sha3_384_Free(&hash->sha3);
+            ret = 0;
+#endif
+            break;
+        case WC_HASH_TYPE_SHA3_512:
+#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512)
+            wc_Sha3_512_Free(&hash->sha3);
+            ret = 0;
+#endif
+            break;
+
+        /* not supported */
+        case WC_HASH_TYPE_MD5_SHA:
+        case WC_HASH_TYPE_MD2:
+        case WC_HASH_TYPE_MD4:
+        case WC_HASH_TYPE_BLAKE2B:
+        case WC_HASH_TYPE_BLAKE2S:
+        case WC_HASH_TYPE_NONE:
+        default:
+            ret = BAD_FUNC_ARG;
+    };
+
+    return ret;
+}
+
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+int wc_HashSetFlags(wc_HashAlg* hash, enum wc_HashType type, word32 flags)
+{
+    int ret = HASH_TYPE_E; /* Default to hash type error */
+
+    if (hash == NULL)
+        return BAD_FUNC_ARG;
+
+    switch (type) {
+        case WC_HASH_TYPE_MD5:
+#ifndef NO_MD5
+            ret = wc_Md5SetFlags(&hash->md5, flags);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA:
+#ifndef NO_SHA
+            ret = wc_ShaSetFlags(&hash->sha, flags);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA224:
+#ifdef WOLFSSL_SHA224
+            ret = wc_Sha224SetFlags(&hash->sha224, flags);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA256:
+#ifndef NO_SHA256
+            ret = wc_Sha256SetFlags(&hash->sha256, flags);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA384:
+#ifdef WOLFSSL_SHA384
+            ret = wc_Sha384SetFlags(&hash->sha384, flags);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA512:
+#ifdef WOLFSSL_SHA512
+            ret = wc_Sha512SetFlags(&hash->sha512, flags);
+#endif
+            break;
+
+        case WC_HASH_TYPE_SHA3_224:
+        case WC_HASH_TYPE_SHA3_256:
+        case WC_HASH_TYPE_SHA3_384:
+        case WC_HASH_TYPE_SHA3_512:
+#ifdef WOLFSSL_SHA3
+            ret = wc_Sha3_SetFlags(&hash->sha3, flags);
+#endif
+            break;
+
+        /* not supported */
+        case WC_HASH_TYPE_MD5_SHA:
+        case WC_HASH_TYPE_MD2:
+        case WC_HASH_TYPE_MD4:
+        case WC_HASH_TYPE_BLAKE2B:
+        case WC_HASH_TYPE_BLAKE2S:
+        case WC_HASH_TYPE_NONE:
+        default:
+            ret = BAD_FUNC_ARG;
+    };
+
+    return ret;
+}
+int wc_HashGetFlags(wc_HashAlg* hash, enum wc_HashType type, word32* flags)
+{
+    int ret = HASH_TYPE_E; /* Default to hash type error */
+
+    if (hash == NULL)
+        return BAD_FUNC_ARG;
+
+    switch (type) {
+        case WC_HASH_TYPE_MD5:
+#ifndef NO_MD5
+            ret = wc_Md5GetFlags(&hash->md5, flags);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA:
+#ifndef NO_SHA
+            ret = wc_ShaGetFlags(&hash->sha, flags);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA224:
+#ifdef WOLFSSL_SHA224
+            ret = wc_Sha224GetFlags(&hash->sha224, flags);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA256:
+#ifndef NO_SHA256
+            ret = wc_Sha256GetFlags(&hash->sha256, flags);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA384:
+#ifdef WOLFSSL_SHA384
+            ret = wc_Sha384GetFlags(&hash->sha384, flags);
+#endif
+            break;
+        case WC_HASH_TYPE_SHA512:
+#ifdef WOLFSSL_SHA512
+            ret = wc_Sha512GetFlags(&hash->sha512, flags);
+#endif
+            break;
+
+        case WC_HASH_TYPE_SHA3_224:
+        case WC_HASH_TYPE_SHA3_256:
+        case WC_HASH_TYPE_SHA3_384:
+        case WC_HASH_TYPE_SHA3_512:
+#ifdef WOLFSSL_SHA3
+            ret = wc_Sha3_GetFlags(&hash->sha3, flags);
+#endif
+            break;
+
+        /* not supported */
+        case WC_HASH_TYPE_MD5_SHA:
+        case WC_HASH_TYPE_MD2:
+        case WC_HASH_TYPE_MD4:
+        case WC_HASH_TYPE_BLAKE2B:
+        case WC_HASH_TYPE_BLAKE2S:
+        case WC_HASH_TYPE_NONE:
+        default:
+            ret = BAD_FUNC_ARG;
+    };
+
+    return ret;
+}
+#endif
+
+
+#if !defined(WOLFSSL_TI_HASH)
+
+#if !defined(NO_MD5)
+    int wc_Md5Hash(const byte* data, word32 len, byte* hash)
+    {
+        int ret;
+    #ifdef WOLFSSL_SMALL_STACK
+        wc_Md5* md5;
+    #else
+        wc_Md5  md5[1];
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        md5 = (wc_Md5*)XMALLOC(sizeof(wc_Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (md5 == NULL)
+            return MEMORY_E;
+    #endif
+
+        if ((ret = wc_InitMd5(md5)) != 0) {
+            WOLFSSL_MSG("InitMd5 failed");
+        }
+        else {
+            if ((ret = wc_Md5Update(md5, data, len)) != 0) {
+                WOLFSSL_MSG("Md5Update failed");
+            }
+            else if ((ret = wc_Md5Final(md5, hash)) != 0) {
+                WOLFSSL_MSG("Md5Final failed");
+            }
+            wc_Md5Free(md5);
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+
+        return ret;
+    }
+#endif /* !NO_MD5 */
+
+#if !defined(NO_SHA)
+    int wc_ShaHash(const byte* data, word32 len, byte* hash)
+    {
+        int ret = 0;
+    #ifdef WOLFSSL_SMALL_STACK
+        wc_Sha* sha;
+    #else
+        wc_Sha sha[1];
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        sha = (wc_Sha*)XMALLOC(sizeof(wc_Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (sha == NULL)
+            return MEMORY_E;
+    #endif
+
+        if ((ret = wc_InitSha(sha)) != 0) {
+            WOLFSSL_MSG("InitSha failed");
+        }
+        else {
+            if ((ret = wc_ShaUpdate(sha, data, len)) != 0) {
+                WOLFSSL_MSG("ShaUpdate failed");
+            }
+            else if ((ret = wc_ShaFinal(sha, hash)) != 0) {
+                WOLFSSL_MSG("ShaFinal failed");
+            }
+            wc_ShaFree(sha);
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+
+        return ret;
+    }
+#endif /* !NO_SHA */
+
+#if defined(WOLFSSL_SHA224)
+    int wc_Sha224Hash(const byte* data, word32 len, byte* hash)
+    {
+        int ret = 0;
+    #ifdef WOLFSSL_SMALL_STACK
+        wc_Sha224* sha224;
+    #else
+        wc_Sha224 sha224[1];
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        sha224 = (wc_Sha224*)XMALLOC(sizeof(wc_Sha224), NULL,
+            DYNAMIC_TYPE_TMP_BUFFER);
+        if (sha224 == NULL)
+            return MEMORY_E;
+    #endif
+
+        if ((ret = wc_InitSha224(sha224)) != 0) {
+            WOLFSSL_MSG("InitSha224 failed");
+        }
+        else {
+            if ((ret = wc_Sha224Update(sha224, data, len)) != 0) {
+                WOLFSSL_MSG("Sha224Update failed");
+            }
+            else if ((ret = wc_Sha224Final(sha224, hash)) != 0) {
+                WOLFSSL_MSG("Sha224Final failed");
+            }
+            wc_Sha224Free(sha224);
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(sha224, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+
+    return ret;
+}
+#endif /* WOLFSSL_SHA224 */
+
+#if !defined(NO_SHA256)
+    int wc_Sha256Hash(const byte* data, word32 len, byte* hash)
+    {
+        int ret = 0;
+    #ifdef WOLFSSL_SMALL_STACK
+        wc_Sha256* sha256;
+    #else
+        wc_Sha256 sha256[1];
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        sha256 = (wc_Sha256*)XMALLOC(sizeof(wc_Sha256), NULL,
+            DYNAMIC_TYPE_TMP_BUFFER);
+        if (sha256 == NULL)
+            return MEMORY_E;
+    #endif
+
+        if ((ret = wc_InitSha256(sha256)) != 0) {
+            WOLFSSL_MSG("InitSha256 failed");
+        }
+        else {
+            if ((ret = wc_Sha256Update(sha256, data, len)) != 0) {
+                WOLFSSL_MSG("Sha256Update failed");
+            }
+            else if ((ret = wc_Sha256Final(sha256, hash)) != 0) {
+                WOLFSSL_MSG("Sha256Final failed");
+            }
+            wc_Sha256Free(sha256);
+        }
+
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+
+        return ret;
+    }
+#endif /* !NO_SHA256 */
+
+#endif /* !defined(WOLFSSL_TI_HASH) */
+
+
+#if defined(WOLFSSL_SHA512)
+    int wc_Sha512Hash(const byte* data, word32 len, byte* hash)
+    {
+        int ret = 0;
+    #ifdef WOLFSSL_SMALL_STACK
+        wc_Sha512* sha512;
+    #else
+        wc_Sha512 sha512[1];
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        sha512 = (wc_Sha512*)XMALLOC(sizeof(wc_Sha512), NULL,
+            DYNAMIC_TYPE_TMP_BUFFER);
+        if (sha512 == NULL)
+            return MEMORY_E;
+    #endif
+
+        if ((ret = wc_InitSha512(sha512)) != 0) {
+            WOLFSSL_MSG("InitSha512 failed");
+        }
+        else {
+            if ((ret = wc_Sha512Update(sha512, data, len)) != 0) {
+                WOLFSSL_MSG("Sha512Update failed");
+            }
+            else if ((ret = wc_Sha512Final(sha512, hash)) != 0) {
+                WOLFSSL_MSG("Sha512Final failed");
+            }
+            wc_Sha512Free(sha512);
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+
+        return ret;
+    }
+#endif /* WOLFSSL_SHA512 */
+
+#if defined(WOLFSSL_SHA384)
+    int wc_Sha384Hash(const byte* data, word32 len, byte* hash)
+    {
+        int ret = 0;
+    #ifdef WOLFSSL_SMALL_STACK
+        wc_Sha384* sha384;
+    #else
+        wc_Sha384 sha384[1];
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        sha384 = (wc_Sha384*)XMALLOC(sizeof(wc_Sha384), NULL,
+            DYNAMIC_TYPE_TMP_BUFFER);
+        if (sha384 == NULL)
+            return MEMORY_E;
+    #endif
+
+        if ((ret = wc_InitSha384(sha384)) != 0) {
+            WOLFSSL_MSG("InitSha384 failed");
+        }
+        else {
+            if ((ret = wc_Sha384Update(sha384, data, len)) != 0) {
+                WOLFSSL_MSG("Sha384Update failed");
+            }
+            else if ((ret = wc_Sha384Final(sha384, hash)) != 0) {
+                WOLFSSL_MSG("Sha384Final failed");
+            }
+            wc_Sha384Free(sha384);
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+
+        return ret;
+    }
+#endif /* WOLFSSL_SHA384 */
+
+#if defined(WOLFSSL_SHA3)
+#if !defined(WOLFSSL_NOSHA3_224)
+    int wc_Sha3_224Hash(const byte* data, word32 len, byte* hash)
+    {
+        int ret = 0;
+    #ifdef WOLFSSL_SMALL_STACK
+        wc_Sha3* sha3;
+    #else
+        wc_Sha3 sha3[1];
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        sha3 = (wc_Sha3*)XMALLOC(sizeof(wc_Sha3), NULL,
+            DYNAMIC_TYPE_TMP_BUFFER);
+        if (sha3 == NULL)
+            return MEMORY_E;
+    #endif
+
+        if ((ret = wc_InitSha3_224(sha3, NULL, INVALID_DEVID)) != 0) {
+            WOLFSSL_MSG("InitSha3_224 failed");
+        }
+        else {
+            if ((ret = wc_Sha3_224_Update(sha3, data, len)) != 0) {
+                WOLFSSL_MSG("Sha3_224_Update failed");
+            }
+            else if ((ret = wc_Sha3_224_Final(sha3, hash)) != 0) {
+                WOLFSSL_MSG("Sha3_224_Final failed");
+            }
+            wc_Sha3_224_Free(sha3);
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(sha3, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+
+        return ret;
+    }
+#endif /* !WOLFSSL_NOSHA3_224 */
+
+#if !defined(WOLFSSL_NOSHA3_256)
+    int wc_Sha3_256Hash(const byte* data, word32 len, byte* hash)
+    {
+        int ret = 0;
+    #ifdef WOLFSSL_SMALL_STACK
+        wc_Sha3* sha3;
+    #else
+        wc_Sha3 sha3[1];
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        sha3 = (wc_Sha3*)XMALLOC(sizeof(wc_Sha3), NULL,
+            DYNAMIC_TYPE_TMP_BUFFER);
+        if (sha3 == NULL)
+            return MEMORY_E;
+    #endif
+
+        if ((ret = wc_InitSha3_256(sha3, NULL, INVALID_DEVID)) != 0) {
+            WOLFSSL_MSG("InitSha3_256 failed");
+        }
+        else {
+            if ((ret = wc_Sha3_256_Update(sha3, data, len)) != 0) {
+                WOLFSSL_MSG("Sha3_256_Update failed");
+            }
+            else if ((ret = wc_Sha3_256_Final(sha3, hash)) != 0) {
+                WOLFSSL_MSG("Sha3_256_Final failed");
+            }
+            wc_Sha3_256_Free(sha3);
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(sha3, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+
+        return ret;
+    }
+#endif /* !WOLFSSL_NOSHA3_256 */
+
+#if !defined(WOLFSSL_NOSHA3_384)
+    int wc_Sha3_384Hash(const byte* data, word32 len, byte* hash)
+    {
+        int ret = 0;
+    #ifdef WOLFSSL_SMALL_STACK
+        wc_Sha3* sha3;
+    #else
+        wc_Sha3 sha3[1];
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        sha3 = (wc_Sha3*)XMALLOC(sizeof(wc_Sha3), NULL,
+            DYNAMIC_TYPE_TMP_BUFFER);
+        if (sha3 == NULL)
+            return MEMORY_E;
+    #endif
+
+        if ((ret = wc_InitSha3_384(sha3, NULL, INVALID_DEVID)) != 0) {
+            WOLFSSL_MSG("InitSha3_384 failed");
+        }
+        else {
+            if ((ret = wc_Sha3_384_Update(sha3, data, len)) != 0) {
+                WOLFSSL_MSG("Sha3_384_Update failed");
+            }
+            else if ((ret = wc_Sha3_384_Final(sha3, hash)) != 0) {
+                WOLFSSL_MSG("Sha3_384_Final failed");
+            }
+            wc_Sha3_384_Free(sha3);
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(sha3, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+
+        return ret;
+    }
+#endif /* !WOLFSSL_NOSHA3_384 */
+
+#if !defined(WOLFSSL_NOSHA3_512)
+    int wc_Sha3_512Hash(const byte* data, word32 len, byte* hash)
+    {
+        int ret = 0;
+    #ifdef WOLFSSL_SMALL_STACK
+        wc_Sha3* sha3;
+    #else
+        wc_Sha3 sha3[1];
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        sha3 = (wc_Sha3*)XMALLOC(sizeof(wc_Sha3), NULL,
+            DYNAMIC_TYPE_TMP_BUFFER);
+        if (sha3 == NULL)
+            return MEMORY_E;
+    #endif
+
+        if ((ret = wc_InitSha3_512(sha3, NULL, INVALID_DEVID)) != 0) {
+            WOLFSSL_MSG("InitSha3_512 failed");
+        }
+        else {
+            if ((ret = wc_Sha3_512_Update(sha3, data, len)) != 0) {
+                WOLFSSL_MSG("Sha3_512_Update failed");
+            }
+            else if ((ret = wc_Sha3_512_Final(sha3, hash)) != 0) {
+                WOLFSSL_MSG("Sha3_512_Final failed");
+            }
+            wc_Sha3_512_Free(sha3);
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(sha3, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+
+        return ret;
+    }
+#endif /* !WOLFSSL_NOSHA3_512 */
+
+#if defined(WOLFSSL_SHAKE256) && !defined(WOLFSSL_NO_SHAKE256)
+    int wc_Shake256Hash(const byte* data, word32 len, byte* hash,
+                        word32 hashLen)
+    {
+        int ret = 0;
+    #ifdef WOLFSSL_SMALL_STACK
+        wc_Shake* shake;
+    #else
+        wc_Shake shake[1];
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        shake = (wc_Shake*)XMALLOC(sizeof(wc_Shake), NULL,
+            DYNAMIC_TYPE_TMP_BUFFER);
+        if (shake == NULL)
+            return MEMORY_E;
+    #endif
+
+        if ((ret = wc_InitShake256(shake, NULL, INVALID_DEVID)) != 0) {
+            WOLFSSL_MSG("InitShake256 failed");
+        }
+        else {
+            if ((ret = wc_Shake256_Update(shake, data, len)) != 0) {
+                WOLFSSL_MSG("Shake256_Update failed");
+            }
+            else if ((ret = wc_Shake256_Final(shake, hash, hashLen)) != 0) {
+                WOLFSSL_MSG("Shake256_Final failed");
+            }
+            wc_Shake256_Free(shake);
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(shake, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+
+        return ret;
+    }
+#endif /* WOLFSSL_SHAKE_256 && !WOLFSSL_NO_SHAKE256 */
+#endif /* WOLFSSL_SHA3 */
+
+#endif /* !NO_HASH_WRAPPER */
+
+#ifdef WOLFSSL_HAVE_PRF
+
+#ifdef WOLFSSL_SHA384
+    #define P_HASH_MAX_SIZE WC_SHA384_DIGEST_SIZE
+#else
+    #define P_HASH_MAX_SIZE WC_SHA256_DIGEST_SIZE
+#endif
+
+/* Pseudo Random Function for MD5, SHA-1, SHA-256, or SHA-384 */
+int wc_PRF(byte* result, word32 resLen, const byte* secret,
+                  word32 secLen, const byte* seed, word32 seedLen, int hash,
+                  void* heap, int devId)
+{
+    word32 len = P_HASH_MAX_SIZE;
+    word32 times;
+    word32 lastLen;
+    word32 lastTime;
+    word32 i;
+    word32 idx = 0;
+    int    ret = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    byte*  previous;
+    byte*  current;
+    Hmac*  hmac;
+#else
+    byte   previous[P_HASH_MAX_SIZE];  /* max size */
+    byte   current[P_HASH_MAX_SIZE];   /* max size */
+    Hmac   hmac[1];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+    previous = (byte*)XMALLOC(P_HASH_MAX_SIZE, heap, DYNAMIC_TYPE_DIGEST);
+    current  = (byte*)XMALLOC(P_HASH_MAX_SIZE, heap, DYNAMIC_TYPE_DIGEST);
+    hmac     = (Hmac*)XMALLOC(sizeof(Hmac),    heap, DYNAMIC_TYPE_HMAC);
+
+    if (previous == NULL || current == NULL || hmac == NULL) {
+        if (previous) XFREE(previous, heap, DYNAMIC_TYPE_DIGEST);
+        if (current)  XFREE(current,  heap, DYNAMIC_TYPE_DIGEST);
+        if (hmac)     XFREE(hmac,     heap, DYNAMIC_TYPE_HMAC);
+
+        return MEMORY_E;
+    }
+#endif
+
+    switch (hash) {
+    #ifndef NO_MD5
+        case md5_mac:
+            hash = WC_MD5;
+            len  = WC_MD5_DIGEST_SIZE;
+        break;
+    #endif
+
+    #ifndef NO_SHA256
+        case sha256_mac:
+            hash = WC_SHA256;
+            len  = WC_SHA256_DIGEST_SIZE;
+        break;
+    #endif
+
+    #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            hash = WC_SHA384;
+            len  = WC_SHA384_DIGEST_SIZE;
+        break;
+    #endif
+
+    #ifndef NO_SHA
+        case sha_mac:
+        default:
+            hash = WC_SHA;
+            len  = WC_SHA_DIGEST_SIZE;
+        break;
+    #endif
+    }
+
+    times   = resLen / len;
+    lastLen = resLen % len;
+
+    if (lastLen)
+        times += 1;
+
+    lastTime = times - 1;
+
+    ret = wc_HmacInit(hmac, heap, devId);
+    if (ret == 0) {
+        ret = wc_HmacSetKey(hmac, hash, secret, secLen);
+        if (ret == 0)
+            ret = wc_HmacUpdate(hmac, seed, seedLen); /* A0 = seed */
+        if (ret == 0)
+            ret = wc_HmacFinal(hmac, previous);       /* A1 */
+        if (ret == 0) {
+            for (i = 0; i < times; i++) {
+                ret = wc_HmacUpdate(hmac, previous, len);
+                if (ret != 0)
+                    break;
+                ret = wc_HmacUpdate(hmac, seed, seedLen);
+                if (ret != 0)
+                    break;
+                ret = wc_HmacFinal(hmac, current);
+                if (ret != 0)
+                    break;
+
+                if ((i == lastTime) && lastLen)
+                    XMEMCPY(&result[idx], current,
+                                             min(lastLen, P_HASH_MAX_SIZE));
+                else {
+                    XMEMCPY(&result[idx], current, len);
+                    idx += len;
+                    ret = wc_HmacUpdate(hmac, previous, len);
+                    if (ret != 0)
+                        break;
+                    ret = wc_HmacFinal(hmac, previous);
+                    if (ret != 0)
+                        break;
+                }
+            }
+        }
+        wc_HmacFree(hmac);
+    }
+
+    ForceZero(previous,  P_HASH_MAX_SIZE);
+    ForceZero(current,   P_HASH_MAX_SIZE);
+    ForceZero(hmac,      sizeof(Hmac));
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(previous, heap, DYNAMIC_TYPE_DIGEST);
+    XFREE(current,  heap, DYNAMIC_TYPE_DIGEST);
+    XFREE(hmac,     heap, DYNAMIC_TYPE_HMAC);
+#endif
+
+    return ret;
+}
+#undef P_HASH_MAX_SIZE
+
+/* compute PRF (pseudo random function) using SHA1 and MD5 for TLSv1 */
+int wc_PRF_TLSv1(byte* digest, word32 digLen, const byte* secret,
+           word32 secLen, const byte* label, word32 labLen,
+           const byte* seed, word32 seedLen, void* heap, int devId)
+{
+    int    ret  = 0;
+    word32 half = (secLen + 1) / 2;
+
+#ifdef WOLFSSL_SMALL_STACK
+    byte* md5_half;
+    byte* sha_half;
+    byte* md5_result;
+    byte* sha_result;
+#else
+    byte  md5_half[MAX_PRF_HALF];     /* half is real size */
+    byte  sha_half[MAX_PRF_HALF];     /* half is real size */
+    byte  md5_result[MAX_PRF_DIG];    /* digLen is real size */
+    byte  sha_result[MAX_PRF_DIG];    /* digLen is real size */
+#endif
+#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
+    DECLARE_VAR(labelSeed, byte, MAX_PRF_LABSEED, heap);
+    if (labelSeed == NULL)
+        return MEMORY_E;
+#else
+    byte labelSeed[MAX_PRF_LABSEED];
+#endif
+
+    if (half > MAX_PRF_HALF ||
+        labLen + seedLen > MAX_PRF_LABSEED ||
+        digLen > MAX_PRF_DIG)
+    {
+    #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
+        FREE_VAR(labelSeed, heap);
+    #endif
+        return BUFFER_E;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    md5_half   = (byte*)XMALLOC(MAX_PRF_HALF,    heap, DYNAMIC_TYPE_DIGEST);
+    sha_half   = (byte*)XMALLOC(MAX_PRF_HALF,    heap, DYNAMIC_TYPE_DIGEST);
+    md5_result = (byte*)XMALLOC(MAX_PRF_DIG,     heap, DYNAMIC_TYPE_DIGEST);
+    sha_result = (byte*)XMALLOC(MAX_PRF_DIG,     heap, DYNAMIC_TYPE_DIGEST);
+
+    if (md5_half == NULL || sha_half == NULL || md5_result == NULL ||
+                                                           sha_result == NULL) {
+        if (md5_half)   XFREE(md5_half,   heap, DYNAMIC_TYPE_DIGEST);
+        if (sha_half)   XFREE(sha_half,   heap, DYNAMIC_TYPE_DIGEST);
+        if (md5_result) XFREE(md5_result, heap, DYNAMIC_TYPE_DIGEST);
+        if (sha_result) XFREE(sha_result, heap, DYNAMIC_TYPE_DIGEST);
+    #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
+        FREE_VAR(labelSeed, heap);
+    #endif
+
+        return MEMORY_E;
+    }
+#endif
+
+    XMEMSET(md5_result, 0, digLen);
+    XMEMSET(sha_result, 0, digLen);
+
+    XMEMCPY(md5_half, secret, half);
+    XMEMCPY(sha_half, secret + half - secLen % 2, half);
+
+    XMEMCPY(labelSeed, label, labLen);
+    XMEMCPY(labelSeed + labLen, seed, seedLen);
+
+    if ((ret = wc_PRF(md5_result, digLen, md5_half, half, labelSeed,
+                                labLen + seedLen, md5_mac, heap, devId)) == 0) {
+        if ((ret = wc_PRF(sha_result, digLen, sha_half, half, labelSeed,
+                                labLen + seedLen, sha_mac, heap, devId)) == 0) {
+            /* calculate XOR for TLSv1 PRF */
+            XMEMCPY(digest, md5_result, digLen);
+            xorbuf(digest, sha_result, digLen);
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(md5_half,   heap, DYNAMIC_TYPE_DIGEST);
+    XFREE(sha_half,   heap, DYNAMIC_TYPE_DIGEST);
+    XFREE(md5_result, heap, DYNAMIC_TYPE_DIGEST);
+    XFREE(sha_result, heap, DYNAMIC_TYPE_DIGEST);
+#endif
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
+    FREE_VAR(labelSeed, heap);
+#endif
+
+    return ret;
+}
+
+/* Wrapper for TLS 1.2 and TLSv1 cases to calculate PRF */
+/* In TLS 1.2 case call straight thru to wc_PRF */
+int wc_PRF_TLS(byte* digest, word32 digLen, const byte* secret, word32 secLen,
+            const byte* label, word32 labLen, const byte* seed, word32 seedLen,
+            int useAtLeastSha256, int hash_type, void* heap, int devId)
+{
+    int ret = 0;
+
+    if (useAtLeastSha256) {
+    #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
+        DECLARE_VAR(labelSeed, byte, MAX_PRF_LABSEED, heap);
+        if (labelSeed == NULL)
+            return MEMORY_E;
+    #else
+        byte labelSeed[MAX_PRF_LABSEED];
+    #endif
+
+        if (labLen + seedLen > MAX_PRF_LABSEED)
+            return BUFFER_E;
+
+        XMEMCPY(labelSeed, label, labLen);
+        XMEMCPY(labelSeed + labLen, seed, seedLen);
+
+        /* If a cipher suite wants an algorithm better than sha256, it
+         * should use better. */
+        if (hash_type < sha256_mac || hash_type == blake2b_mac)
+            hash_type = sha256_mac;
+        /* compute PRF for MD5, SHA-1, SHA-256, or SHA-384 for TLSv1.2 PRF */
+        ret = wc_PRF(digest, digLen, secret, secLen, labelSeed,
+                     labLen + seedLen, hash_type, heap, devId);
+
+    #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
+        FREE_VAR(labelSeed, heap);
+    #endif
+    }
+#ifndef NO_OLD_TLS
+    else {
+        /* compute TLSv1 PRF (pseudo random function using HMAC) */
+        ret = wc_PRF_TLSv1(digest, digLen, secret, secLen, label, labLen, seed,
+                          seedLen, heap, devId);
+    }
+#endif
+
+    return ret;
+}
+#endif /* WOLFSSL_HAVE_PRF */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/hc128.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/hc128.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/hc128.c	(revision 453)
@@ -0,0 +1,430 @@
+/* hc128.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifdef HAVE_HC128
+
+#include <wolfssl/wolfcrypt/hc128.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#include <wolfssl/wolfcrypt/logging.h>
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/hc128.h>
+		#include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+
+#ifdef BIG_ENDIAN_ORDER
+    #define LITTLE32(x) ByteReverseWord32(x)
+#else
+    #define LITTLE32(x) (x)
+#endif
+
+
+/*h1 function*/
+#define h1(ctx, x, y) {                         \
+     byte a,c;                                  \
+     a = (byte) (x);                            \
+     c = (byte) ((x) >> 16);                    \
+     y = (ctx->T[512+a])+(ctx->T[512+256+c]);   \
+}
+
+/*h2 function*/
+#define h2(ctx, x, y) {                         \
+     byte a,c;                                  \
+     a = (byte) (x);                            \
+     c = (byte) ((x) >> 16);                    \
+     y = (ctx->T[a])+(ctx->T[256+c]);           \
+}
+
+/*one step of HC-128, update P and generate 32 bits keystream*/
+#define step_P(ctx,u,v,a,b,c,d,n){              \
+     word32 tem0,tem1,tem2,tem3;                \
+     h1((ctx),(ctx->X[(d)]),tem3);              \
+     tem0 = rotrFixed((ctx->T[(v)]),23);        \
+     tem1 = rotrFixed((ctx->X[(c)]),10);        \
+     tem2 = rotrFixed((ctx->X[(b)]),8);         \
+     (ctx->T[(u)]) += tem2+(tem0 ^ tem1);       \
+     (ctx->X[(a)]) = (ctx->T[(u)]);             \
+     (n) = tem3 ^ (ctx->T[(u)]) ;               \
+}
+
+/*one step of HC-128, update Q and generate 32 bits keystream*/
+#define step_Q(ctx,u,v,a,b,c,d,n){              \
+     word32 tem0,tem1,tem2,tem3;                \
+     h2((ctx),(ctx->Y[(d)]),tem3);              \
+     tem0 = rotrFixed((ctx->T[(v)]),(32-23));   \
+     tem1 = rotrFixed((ctx->Y[(c)]),(32-10));   \
+     tem2 = rotrFixed((ctx->Y[(b)]),(32-8));    \
+     (ctx->T[(u)]) += tem2 + (tem0 ^ tem1);     \
+     (ctx->Y[(a)]) = (ctx->T[(u)]);             \
+     (n) = tem3 ^ (ctx->T[(u)]) ;               \
+}
+
+/*16 steps of HC-128, generate 512 bits keystream*/
+static void generate_keystream(HC128* ctx, word32* keystream)
+{
+   word32 cc,dd;
+   cc = ctx->counter1024 & 0x1ff;
+   dd = (cc+16)&0x1ff;
+
+   if (ctx->counter1024 < 512)
+   {
+      ctx->counter1024 = (ctx->counter1024 + 16) & 0x3ff;
+      step_P(ctx, cc+0, cc+1, 0, 6, 13,4, keystream[0]);
+      step_P(ctx, cc+1, cc+2, 1, 7, 14,5, keystream[1]);
+      step_P(ctx, cc+2, cc+3, 2, 8, 15,6, keystream[2]);
+      step_P(ctx, cc+3, cc+4, 3, 9, 0, 7, keystream[3]);
+      step_P(ctx, cc+4, cc+5, 4, 10,1, 8, keystream[4]);
+      step_P(ctx, cc+5, cc+6, 5, 11,2, 9, keystream[5]);
+      step_P(ctx, cc+6, cc+7, 6, 12,3, 10,keystream[6]);
+      step_P(ctx, cc+7, cc+8, 7, 13,4, 11,keystream[7]);
+      step_P(ctx, cc+8, cc+9, 8, 14,5, 12,keystream[8]);
+      step_P(ctx, cc+9, cc+10,9, 15,6, 13,keystream[9]);
+      step_P(ctx, cc+10,cc+11,10,0, 7, 14,keystream[10]);
+      step_P(ctx, cc+11,cc+12,11,1, 8, 15,keystream[11]);
+      step_P(ctx, cc+12,cc+13,12,2, 9, 0, keystream[12]);
+      step_P(ctx, cc+13,cc+14,13,3, 10,1, keystream[13]);
+      step_P(ctx, cc+14,cc+15,14,4, 11,2, keystream[14]);
+      step_P(ctx, cc+15,dd+0, 15,5, 12,3, keystream[15]);
+   }
+   else
+   {
+	  ctx->counter1024 = (ctx->counter1024 + 16) & 0x3ff;
+      step_Q(ctx, 512+cc+0, 512+cc+1, 0, 6, 13,4, keystream[0]);
+      step_Q(ctx, 512+cc+1, 512+cc+2, 1, 7, 14,5, keystream[1]);
+      step_Q(ctx, 512+cc+2, 512+cc+3, 2, 8, 15,6, keystream[2]);
+      step_Q(ctx, 512+cc+3, 512+cc+4, 3, 9, 0, 7, keystream[3]);
+      step_Q(ctx, 512+cc+4, 512+cc+5, 4, 10,1, 8, keystream[4]);
+      step_Q(ctx, 512+cc+5, 512+cc+6, 5, 11,2, 9, keystream[5]);
+      step_Q(ctx, 512+cc+6, 512+cc+7, 6, 12,3, 10,keystream[6]);
+      step_Q(ctx, 512+cc+7, 512+cc+8, 7, 13,4, 11,keystream[7]);
+      step_Q(ctx, 512+cc+8, 512+cc+9, 8, 14,5, 12,keystream[8]);
+      step_Q(ctx, 512+cc+9, 512+cc+10,9, 15,6, 13,keystream[9]);
+      step_Q(ctx, 512+cc+10,512+cc+11,10,0, 7, 14,keystream[10]);
+      step_Q(ctx, 512+cc+11,512+cc+12,11,1, 8, 15,keystream[11]);
+      step_Q(ctx, 512+cc+12,512+cc+13,12,2, 9, 0, keystream[12]);
+      step_Q(ctx, 512+cc+13,512+cc+14,13,3, 10,1, keystream[13]);
+      step_Q(ctx, 512+cc+14,512+cc+15,14,4, 11,2, keystream[14]);
+      step_Q(ctx, 512+cc+15,512+dd+0, 15,5, 12,3, keystream[15]);
+   }
+}
+
+
+/* The following defines the initialization functions */
+#define f1(x)  (rotrFixed((x),7)  ^ rotrFixed((x),18) ^ ((x) >> 3))
+#define f2(x)  (rotrFixed((x),17) ^ rotrFixed((x),19) ^ ((x) >> 10))
+
+/*update table P*/
+#define update_P(ctx,u,v,a,b,c,d){                  \
+     word32 tem0,tem1,tem2,tem3;                    \
+     tem0 = rotrFixed((ctx->T[(v)]),23);            \
+     tem1 = rotrFixed((ctx->X[(c)]),10);            \
+     tem2 = rotrFixed((ctx->X[(b)]),8);             \
+     h1((ctx),(ctx->X[(d)]),tem3);                  \
+     (ctx->T[(u)]) = ((ctx->T[(u)]) + tem2+(tem0^tem1)) ^ tem3;     \
+     (ctx->X[(a)]) = (ctx->T[(u)]);                 \
+}
+
+/*update table Q*/
+#define update_Q(ctx,u,v,a,b,c,d){                  \
+     word32 tem0,tem1,tem2,tem3;                    \
+     tem0 = rotrFixed((ctx->T[(v)]),(32-23));       \
+     tem1 = rotrFixed((ctx->Y[(c)]),(32-10));       \
+     tem2 = rotrFixed((ctx->Y[(b)]),(32-8));        \
+     h2((ctx),(ctx->Y[(d)]),tem3);                  \
+     (ctx->T[(u)]) = ((ctx->T[(u)]) + tem2+(tem0^tem1)) ^ tem3;     \
+     (ctx->Y[(a)]) = (ctx->T[(u)]);                 \
+}
+
+/*16 steps of HC-128, without generating keystream, */
+/*but use the outputs to update P and Q*/
+static void setup_update(HC128* ctx)  /*each time 16 steps*/
+{
+   word32 cc,dd;
+   cc = ctx->counter1024 & 0x1ff;
+   dd = (cc+16)&0x1ff;
+
+   if (ctx->counter1024 < 512)
+   {
+      ctx->counter1024 = (ctx->counter1024 + 16) & 0x3ff;
+      update_P(ctx, cc+0, cc+1, 0, 6, 13, 4);
+      update_P(ctx, cc+1, cc+2, 1, 7, 14, 5);
+      update_P(ctx, cc+2, cc+3, 2, 8, 15, 6);
+      update_P(ctx, cc+3, cc+4, 3, 9, 0,  7);
+      update_P(ctx, cc+4, cc+5, 4, 10,1,  8);
+      update_P(ctx, cc+5, cc+6, 5, 11,2,  9);
+      update_P(ctx, cc+6, cc+7, 6, 12,3,  10);
+      update_P(ctx, cc+7, cc+8, 7, 13,4,  11);
+      update_P(ctx, cc+8, cc+9, 8, 14,5,  12);
+      update_P(ctx, cc+9, cc+10,9, 15,6,  13);
+      update_P(ctx, cc+10,cc+11,10,0, 7,  14);
+      update_P(ctx, cc+11,cc+12,11,1, 8,  15);
+      update_P(ctx, cc+12,cc+13,12,2, 9,  0);
+      update_P(ctx, cc+13,cc+14,13,3, 10, 1);
+      update_P(ctx, cc+14,cc+15,14,4, 11, 2);
+      update_P(ctx, cc+15,dd+0, 15,5, 12, 3);
+   }
+   else
+   {
+      ctx->counter1024 = (ctx->counter1024 + 16) & 0x3ff;
+      update_Q(ctx, 512+cc+0, 512+cc+1, 0, 6, 13, 4);
+      update_Q(ctx, 512+cc+1, 512+cc+2, 1, 7, 14, 5);
+      update_Q(ctx, 512+cc+2, 512+cc+3, 2, 8, 15, 6);
+      update_Q(ctx, 512+cc+3, 512+cc+4, 3, 9, 0,  7);
+      update_Q(ctx, 512+cc+4, 512+cc+5, 4, 10,1,  8);
+      update_Q(ctx, 512+cc+5, 512+cc+6, 5, 11,2,  9);
+      update_Q(ctx, 512+cc+6, 512+cc+7, 6, 12,3,  10);
+      update_Q(ctx, 512+cc+7, 512+cc+8, 7, 13,4,  11);
+      update_Q(ctx, 512+cc+8, 512+cc+9, 8, 14,5,  12);
+      update_Q(ctx, 512+cc+9, 512+cc+10,9, 15,6,  13);
+      update_Q(ctx, 512+cc+10,512+cc+11,10,0, 7,  14);
+      update_Q(ctx, 512+cc+11,512+cc+12,11,1, 8,  15);
+      update_Q(ctx, 512+cc+12,512+cc+13,12,2, 9,  0);
+      update_Q(ctx, 512+cc+13,512+cc+14,13,3, 10, 1);
+      update_Q(ctx, 512+cc+14,512+cc+15,14,4, 11, 2);
+      update_Q(ctx, 512+cc+15,512+dd+0, 15,5, 12, 3);
+   }
+}
+
+
+/* for the 128-bit key:  key[0]...key[15]
+*  key[0] is the least significant byte of ctx->key[0] (K_0);
+*  key[3] is the most significant byte of ctx->key[0]  (K_0);
+*  ...
+*  key[12] is the least significant byte of ctx->key[3] (K_3)
+*  key[15] is the most significant byte of ctx->key[3]  (K_3)
+*
+*  for the 128-bit iv:  iv[0]...iv[15]
+*  iv[0] is the least significant byte of ctx->iv[0] (IV_0);
+*  iv[3] is the most significant byte of ctx->iv[0]  (IV_0);
+*  ...
+*  iv[12] is the least significant byte of ctx->iv[3] (IV_3)
+*  iv[15] is the most significant byte of ctx->iv[3]  (IV_3)
+*/
+
+
+
+static void Hc128_SetIV(HC128* ctx, const byte* inIv)
+{
+    word32 i;
+    word32 iv[4];
+
+    if (inIv)
+        XMEMCPY(iv, inIv, sizeof(iv));
+    else
+        XMEMSET(iv,    0, sizeof(iv));
+
+	for (i = 0; i < (128 >> 5); i++)
+        ctx->iv[i] = LITTLE32(iv[i]);
+
+    for (; i < 8; i++) ctx->iv[i] = ctx->iv[i-4];
+
+    /* expand the key and IV into the table T */
+    /* (expand the key and IV into the table P and Q) */
+
+	for (i = 0; i < 8;  i++)   ctx->T[i] = ctx->key[i];
+	for (i = 8; i < 16; i++)   ctx->T[i] = ctx->iv[i-8];
+
+    for (i = 16; i < (256+16); i++)
+		ctx->T[i] = f2(ctx->T[i-2]) + ctx->T[i-7] + f1(ctx->T[i-15]) +
+                                                       ctx->T[i-16]+i;
+
+	for (i = 0; i < 16;  i++)  ctx->T[i] = ctx->T[256+i];
+
+	for (i = 16; i < 1024; i++)
+		ctx->T[i] = f2(ctx->T[i-2]) + ctx->T[i-7] + f1(ctx->T[i-15]) +
+                                                       ctx->T[i-16]+256+i;
+
+    /* initialize counter1024, X and Y */
+	ctx->counter1024 = 0;
+	for (i = 0; i < 16; i++) ctx->X[i] = ctx->T[512-16+i];
+    for (i = 0; i < 16; i++) ctx->Y[i] = ctx->T[512+512-16+i];
+
+    /* run the cipher 1024 steps before generating the output */
+	for (i = 0; i < 64; i++)  setup_update(ctx);
+}
+
+
+static WC_INLINE int DoKey(HC128* ctx, const byte* key, const byte* iv)
+{
+  word32 i;
+
+  /* Key size in bits 128 */
+  for (i = 0; i < (128 >> 5); i++)
+      ctx->key[i] = LITTLE32(((word32*)key)[i]);
+
+  for ( ; i < 8 ; i++) ctx->key[i] = ctx->key[i-4];
+
+  Hc128_SetIV(ctx, iv);
+
+  return 0;
+}
+
+
+int wc_Hc128_SetHeap(HC128* ctx, void* heap)
+{
+    if (ctx == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef XSTREAM_ALIGN
+    ctx->heap = heap;
+#endif
+
+    (void)heap;
+    return 0;
+}
+
+/* Key setup */
+int wc_Hc128_SetKey(HC128* ctx, const byte* key, const byte* iv)
+{
+    if (ctx == NULL || key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef XSTREAM_ALIGN
+    /* default heap to NULL or heap test value */
+    #ifdef WOLFSSL_HEAP_TEST
+        ctx->heap = (void*)WOLFSSL_HEAP_TEST;
+    #else
+        ctx->heap = NULL;
+    #endif /* WOLFSSL_HEAP_TEST */
+
+    if ((wolfssl_word)key % 4) {
+        int alignKey[4];
+
+        /* iv gets aligned in SetIV */
+        WOLFSSL_MSG("Hc128SetKey unaligned key");
+
+        XMEMCPY(alignKey, key, sizeof(alignKey));
+
+        return DoKey(ctx, (const byte*)alignKey, iv);
+    }
+#endif /* XSTREAM_ALIGN */
+
+    return DoKey(ctx, key, iv);
+}
+
+
+
+/* The following defines the encryption of data stream */
+static WC_INLINE int DoProcess(HC128* ctx, byte* output, const byte* input,
+                            word32 msglen)
+{
+  word32 i, keystream[16];
+
+  for ( ; msglen >= 64; msglen -= 64, input += 64, output += 64)
+  {
+	  generate_keystream(ctx, keystream);
+
+      /* unroll loop */
+	  ((word32*)output)[0]  = ((word32*)input)[0]  ^ LITTLE32(keystream[0]);
+	  ((word32*)output)[1]  = ((word32*)input)[1]  ^ LITTLE32(keystream[1]);
+	  ((word32*)output)[2]  = ((word32*)input)[2]  ^ LITTLE32(keystream[2]);
+	  ((word32*)output)[3]  = ((word32*)input)[3]  ^ LITTLE32(keystream[3]);
+	  ((word32*)output)[4]  = ((word32*)input)[4]  ^ LITTLE32(keystream[4]);
+	  ((word32*)output)[5]  = ((word32*)input)[5]  ^ LITTLE32(keystream[5]);
+	  ((word32*)output)[6]  = ((word32*)input)[6]  ^ LITTLE32(keystream[6]);
+	  ((word32*)output)[7]  = ((word32*)input)[7]  ^ LITTLE32(keystream[7]);
+	  ((word32*)output)[8]  = ((word32*)input)[8]  ^ LITTLE32(keystream[8]);
+	  ((word32*)output)[9]  = ((word32*)input)[9]  ^ LITTLE32(keystream[9]);
+	  ((word32*)output)[10] = ((word32*)input)[10] ^ LITTLE32(keystream[10]);
+	  ((word32*)output)[11] = ((word32*)input)[11] ^ LITTLE32(keystream[11]);
+	  ((word32*)output)[12] = ((word32*)input)[12] ^ LITTLE32(keystream[12]);
+	  ((word32*)output)[13] = ((word32*)input)[13] ^ LITTLE32(keystream[13]);
+	  ((word32*)output)[14] = ((word32*)input)[14] ^ LITTLE32(keystream[14]);
+	  ((word32*)output)[15] = ((word32*)input)[15] ^ LITTLE32(keystream[15]);
+  }
+
+  if (msglen > 0)
+  {
+      XMEMSET(keystream, 0, sizeof(keystream)); /* hush the static analysis */
+      generate_keystream(ctx, keystream);
+
+#ifdef BIG_ENDIAN_ORDER
+      {
+          word32 wordsLeft = msglen / sizeof(word32);
+          if (msglen % sizeof(word32)) wordsLeft++;
+
+          ByteReverseWords(keystream, keystream, wordsLeft * sizeof(word32));
+      }
+#endif
+
+      for (i = 0; i < msglen; i++)
+	      output[i] = input[i] ^ ((byte*)keystream)[i];
+  }
+
+  return 0;
+}
+
+
+/* Encrypt/decrypt a message of any size */
+int wc_Hc128_Process(HC128* ctx, byte* output, const byte* input, word32 msglen)
+{
+    if (ctx == NULL || output == NULL || input == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef XSTREAM_ALIGN
+    if ((wolfssl_word)input % 4 || (wolfssl_word)output % 4) {
+        #ifndef NO_WOLFSSL_ALLOC_ALIGN
+            byte* tmp;
+            WOLFSSL_MSG("Hc128Process unaligned");
+
+            tmp = (byte*)XMALLOC(msglen, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            if (tmp == NULL) return MEMORY_E;
+
+            XMEMCPY(tmp, input, msglen);
+            DoProcess(ctx, tmp, tmp, msglen);
+            XMEMCPY(output, tmp, msglen);
+
+            XFREE(tmp, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+            return 0;
+        #else
+            return BAD_ALIGN_E;
+        #endif
+    }
+#endif /* XSTREAM_ALIGN */
+
+    return DoProcess(ctx, output, input, msglen);
+}
+
+
+#else  /* HAVE_HC128 */
+
+
+#ifdef _MSC_VER
+    /* 4206 warning for blank file */
+    #pragma warning(disable: 4206)
+#endif
+
+
+#endif /* HAVE_HC128 */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/hmac.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/hmac.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/hmac.c	(revision 453)
@@ -0,0 +1,1290 @@
+/* hmac.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+
+#ifndef NO_HMAC
+
+#if defined(HAVE_FIPS) && \
+    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
+
+    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
+    #define FIPS_NO_WRAPPERS
+
+    #ifdef USE_WINDOWS_API
+        #pragma code_seg(".fipsA$b")
+        #pragma const_seg(".fipsB$b")
+    #endif
+#endif
+
+#include <wolfssl/wolfcrypt/hmac.h>
+
+#ifdef WOLF_CRYPTO_CB
+    #include <wolfssl/wolfcrypt/cryptocb.h>
+#endif
+
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+
+/* fips wrapper calls, user can call direct */
+/* If building for old FIPS. */
+#if defined(HAVE_FIPS) && \
+    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
+
+    /* does init */
+    int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 keySz)
+    {
+        if (hmac == NULL || (key == NULL && keySz != 0) ||
+           !(type == WC_MD5 || type == WC_SHA || type == WC_SHA256 ||
+                type == WC_SHA384 || type == WC_SHA512)) {
+            return BAD_FUNC_ARG;
+        }
+
+        return HmacSetKey_fips(hmac, type, key, keySz);
+    }
+    int wc_HmacUpdate(Hmac* hmac, const byte* in, word32 sz)
+    {
+        if (hmac == NULL || (in == NULL && sz > 0)) {
+            return BAD_FUNC_ARG;
+        }
+
+        return HmacUpdate_fips(hmac, in, sz);
+    }
+    int wc_HmacFinal(Hmac* hmac, byte* out)
+    {
+        if (hmac == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        return HmacFinal_fips(hmac, out);
+    }
+    int wolfSSL_GetHmacMaxSize(void)
+    {
+        return CyaSSL_GetHmacMaxSize();
+    }
+
+    int wc_HmacInit(Hmac* hmac, void* heap, int devId)
+    {
+        (void)hmac;
+        (void)heap;
+        (void)devId;
+        /* FIPS doesn't support:
+            return HmacInit(hmac, heap, devId); */
+        return 0;
+    }
+    void wc_HmacFree(Hmac* hmac)
+    {
+        (void)hmac;
+        /* FIPS doesn't support:
+            HmacFree(hmac); */
+    }
+
+    #ifdef HAVE_HKDF
+        int wc_HKDF(int type, const byte* inKey, word32 inKeySz,
+                    const byte* salt, word32 saltSz,
+                    const byte* info, word32 infoSz,
+                    byte* out, word32 outSz)
+        {
+            return HKDF(type, inKey, inKeySz, salt, saltSz,
+                info, infoSz, out, outSz);
+        }
+    #endif /* HAVE_HKDF */
+
+#else /* else build without fips, or for new fips */
+
+
+int wc_HmacSizeByType(int type)
+{
+    int ret;
+
+    if (!(type == WC_MD5 || type == WC_SHA ||
+            type == WC_SHA224 || type == WC_SHA256 ||
+            type == WC_SHA384 || type == WC_SHA512 ||
+            type == WC_SHA3_224 || type == WC_SHA3_256 ||
+            type == WC_SHA3_384 || type == WC_SHA3_512)) {
+        return BAD_FUNC_ARG;
+    }
+
+    switch (type) {
+    #ifndef NO_MD5
+        case WC_MD5:
+            ret = WC_MD5_DIGEST_SIZE;
+            break;
+    #endif /* !NO_MD5 */
+
+    #ifndef NO_SHA
+        case WC_SHA:
+            ret = WC_SHA_DIGEST_SIZE;
+            break;
+    #endif /* !NO_SHA */
+
+    #ifdef WOLFSSL_SHA224
+        case WC_SHA224:
+            ret = WC_SHA224_DIGEST_SIZE;
+            break;
+    #endif /* WOLFSSL_SHA224 */
+
+    #ifndef NO_SHA256
+        case WC_SHA256:
+            ret = WC_SHA256_DIGEST_SIZE;
+            break;
+    #endif /* !NO_SHA256 */
+
+    #ifdef WOLFSSL_SHA384
+        case WC_SHA384:
+            ret = WC_SHA384_DIGEST_SIZE;
+            break;
+    #endif /* WOLFSSL_SHA384 */
+    #ifdef WOLFSSL_SHA512
+        case WC_SHA512:
+            ret = WC_SHA512_DIGEST_SIZE;
+            break;
+    #endif /* WOLFSSL_SHA512 */
+
+    #ifdef WOLFSSL_SHA3
+        case WC_SHA3_224:
+            ret = WC_SHA3_224_DIGEST_SIZE;
+            break;
+
+        case WC_SHA3_256:
+            ret = WC_SHA3_256_DIGEST_SIZE;
+            break;
+
+        case WC_SHA3_384:
+            ret = WC_SHA3_384_DIGEST_SIZE;
+            break;
+
+        case WC_SHA3_512:
+            ret = WC_SHA3_512_DIGEST_SIZE;
+            break;
+
+    #endif
+
+        default:
+            ret = BAD_FUNC_ARG;
+            break;
+    }
+
+    return ret;
+}
+
+int _InitHmac(Hmac* hmac, int type, void* heap)
+{
+    int ret = 0;
+
+    switch (type) {
+    #ifndef NO_MD5
+        case WC_MD5:
+            ret = wc_InitMd5(&hmac->hash.md5);
+            break;
+    #endif /* !NO_MD5 */
+
+    #ifndef NO_SHA
+        case WC_SHA:
+            ret = wc_InitSha(&hmac->hash.sha);
+            break;
+    #endif /* !NO_SHA */
+
+    #ifdef WOLFSSL_SHA224
+        case WC_SHA224:
+            ret = wc_InitSha224(&hmac->hash.sha224);
+            break;
+    #endif /* WOLFSSL_SHA224 */
+
+    #ifndef NO_SHA256
+        case WC_SHA256:
+            ret = wc_InitSha256(&hmac->hash.sha256);
+            break;
+    #endif /* !NO_SHA256 */
+
+    #ifdef WOLFSSL_SHA384
+        case WC_SHA384:
+            ret = wc_InitSha384(&hmac->hash.sha384);
+            break;
+    #endif /* WOLFSSL_SHA384 */
+    #ifdef WOLFSSL_SHA512
+        case WC_SHA512:
+            ret = wc_InitSha512(&hmac->hash.sha512);
+            break;
+    #endif /* WOLFSSL_SHA512 */
+
+    #ifdef WOLFSSL_SHA3
+    #ifndef WOLFSSL_NOSHA3_224
+        case WC_SHA3_224:
+            ret = wc_InitSha3_224(&hmac->hash.sha3, heap, INVALID_DEVID);
+            break;
+    #endif
+    #ifndef WOLFSSL_NOSHA3_256
+        case WC_SHA3_256:
+            ret = wc_InitSha3_256(&hmac->hash.sha3, heap, INVALID_DEVID);
+            break;
+    #endif
+    #ifndef WOLFSSL_NOSHA3_384
+        case WC_SHA3_384:
+            ret = wc_InitSha3_384(&hmac->hash.sha3, heap, INVALID_DEVID);
+            break;
+    #endif
+    #ifndef WOLFSSL_NOSHA3_512
+        case WC_SHA3_512:
+            ret = wc_InitSha3_512(&hmac->hash.sha3, heap, INVALID_DEVID);
+            break;
+    #endif
+    #endif
+
+        default:
+            ret = BAD_FUNC_ARG;
+            break;
+    }
+
+    /* default to NULL heap hint or test value */
+#ifdef WOLFSSL_HEAP_TEST
+    hmac->heap = (void)WOLFSSL_HEAP_TEST;
+#else
+    hmac->heap = heap;
+#endif /* WOLFSSL_HEAP_TEST */
+
+    return ret;
+}
+
+
+int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length)
+{
+    byte*  ip;
+    byte*  op;
+    word32 i, hmac_block_size = 0;
+    int    ret = 0;
+    void*  heap = NULL;
+
+    if (hmac == NULL || (key == NULL && length != 0) ||
+       !(type == WC_MD5 || type == WC_SHA ||
+            type == WC_SHA224 || type == WC_SHA256 ||
+            type == WC_SHA384 || type == WC_SHA512 ||
+            type == WC_SHA3_224 || type == WC_SHA3_256 ||
+            type == WC_SHA3_384 || type == WC_SHA3_512)) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifndef HAVE_FIPS
+    /* if set key has already been run then make sure and free existing */
+    /* This is for async and PIC32MZ situations, and just normally OK,
+       provided the user calls wc_HmacInit() first. That function is not
+       available in FIPS builds. In current FIPS builds, the hashes are
+       not allocating resources. */
+    if (hmac->macType != WC_HASH_TYPE_NONE) {
+        wc_HmacFree(hmac);
+    }
+#endif
+
+    hmac->innerHashKeyed = 0;
+    hmac->macType = (byte)type;
+
+    ret = _InitHmac(hmac, type, heap);
+    if (ret != 0)
+        return ret;
+
+#ifdef HAVE_FIPS
+    if (length < HMAC_FIPS_MIN_KEY)
+        return HMAC_MIN_KEYLEN_E;
+#endif
+
+#ifdef WOLF_CRYPTO_CB
+    hmac->keyRaw = key; /* use buffer directly */
+    hmac->keyLen = length;
+#endif
+
+    ip = (byte*)hmac->ipad;
+    op = (byte*)hmac->opad;
+
+    switch (hmac->macType) {
+    #ifndef NO_MD5
+        case WC_MD5:
+            hmac_block_size = WC_MD5_BLOCK_SIZE;
+            if (length <= WC_MD5_BLOCK_SIZE) {
+                if (key != NULL) {
+                    XMEMCPY(ip, key, length);
+                }
+            }
+            else {
+                ret = wc_Md5Update(&hmac->hash.md5, key, length);
+                if (ret != 0)
+                    break;
+                ret = wc_Md5Final(&hmac->hash.md5, ip);
+                if (ret != 0)
+                    break;
+                length = WC_MD5_DIGEST_SIZE;
+            }
+            break;
+    #endif /* !NO_MD5 */
+
+    #ifndef NO_SHA
+        case WC_SHA:
+            hmac_block_size = WC_SHA_BLOCK_SIZE;
+            if (length <= WC_SHA_BLOCK_SIZE) {
+                if (key != NULL) {
+                    XMEMCPY(ip, key, length);
+                }
+            }
+            else {
+                ret = wc_ShaUpdate(&hmac->hash.sha, key, length);
+                if (ret != 0)
+                    break;
+                ret = wc_ShaFinal(&hmac->hash.sha, ip);
+                if (ret != 0)
+                    break;
+
+                length = WC_SHA_DIGEST_SIZE;
+            }
+            break;
+    #endif /* !NO_SHA */
+
+    #ifdef WOLFSSL_SHA224
+        case WC_SHA224:
+            hmac_block_size = WC_SHA224_BLOCK_SIZE;
+            if (length <= WC_SHA224_BLOCK_SIZE) {
+                if (key != NULL) {
+                    XMEMCPY(ip, key, length);
+                }
+            }
+            else {
+                ret = wc_Sha224Update(&hmac->hash.sha224, key, length);
+                if (ret != 0)
+                    break;
+                ret = wc_Sha224Final(&hmac->hash.sha224, ip);
+                if (ret != 0)
+                    break;
+
+                length = WC_SHA224_DIGEST_SIZE;
+            }
+            break;
+    #endif /* WOLFSSL_SHA224 */
+    #ifndef NO_SHA256
+        case WC_SHA256:
+            hmac_block_size = WC_SHA256_BLOCK_SIZE;
+            if (length <= WC_SHA256_BLOCK_SIZE) {
+                if (key != NULL) {
+                    XMEMCPY(ip, key, length);
+                }
+            }
+            else {
+                ret = wc_Sha256Update(&hmac->hash.sha256, key, length);
+                if (ret != 0)
+                    break;
+                ret = wc_Sha256Final(&hmac->hash.sha256, ip);
+                if (ret != 0)
+                    break;
+
+                length = WC_SHA256_DIGEST_SIZE;
+            }
+            break;
+    #endif /* !NO_SHA256 */
+
+    #ifdef WOLFSSL_SHA384
+        case WC_SHA384:
+            hmac_block_size = WC_SHA384_BLOCK_SIZE;
+            if (length <= WC_SHA384_BLOCK_SIZE) {
+                if (key != NULL) {
+                    XMEMCPY(ip, key, length);
+                }
+            }
+            else {
+                ret = wc_Sha384Update(&hmac->hash.sha384, key, length);
+                if (ret != 0)
+                    break;
+                ret = wc_Sha384Final(&hmac->hash.sha384, ip);
+                if (ret != 0)
+                    break;
+
+                length = WC_SHA384_DIGEST_SIZE;
+            }
+            break;
+    #endif /* WOLFSSL_SHA384 */
+    #ifdef WOLFSSL_SHA512
+        case WC_SHA512:
+            hmac_block_size = WC_SHA512_BLOCK_SIZE;
+            if (length <= WC_SHA512_BLOCK_SIZE) {
+                if (key != NULL) {
+                    XMEMCPY(ip, key, length);
+                }
+            }
+            else {
+                ret = wc_Sha512Update(&hmac->hash.sha512, key, length);
+                if (ret != 0)
+                    break;
+                ret = wc_Sha512Final(&hmac->hash.sha512, ip);
+                if (ret != 0)
+                    break;
+
+                length = WC_SHA512_DIGEST_SIZE;
+            }
+            break;
+    #endif /* WOLFSSL_SHA512 */
+
+    #ifdef WOLFSSL_SHA3
+    #ifndef WOLFSSL_NOSHA3_224
+        case WC_SHA3_224:
+            hmac_block_size = WC_SHA3_224_BLOCK_SIZE;
+            if (length <= WC_SHA3_224_BLOCK_SIZE) {
+                if (key != NULL) {
+                    XMEMCPY(ip, key, length);
+                }
+            }
+            else {
+                ret = wc_Sha3_224_Update(&hmac->hash.sha3, key, length);
+                if (ret != 0)
+                    break;
+                ret = wc_Sha3_224_Final(&hmac->hash.sha3, ip);
+                if (ret != 0)
+                    break;
+
+                length = WC_SHA3_224_DIGEST_SIZE;
+            }
+            break;
+    #endif
+    #ifndef WOLFSSL_NOSHA3_256
+        case WC_SHA3_256:
+            hmac_block_size = WC_SHA3_256_BLOCK_SIZE;
+            if (length <= WC_SHA3_256_BLOCK_SIZE) {
+                if (key != NULL) {
+                    XMEMCPY(ip, key, length);
+                }
+            }
+            else {
+                ret = wc_Sha3_256_Update(&hmac->hash.sha3, key, length);
+                if (ret != 0)
+                    break;
+                ret = wc_Sha3_256_Final(&hmac->hash.sha3, ip);
+                if (ret != 0)
+                    break;
+
+                length = WC_SHA3_256_DIGEST_SIZE;
+            }
+            break;
+    #endif
+    #ifndef WOLFSSL_NOSHA3_384
+        case WC_SHA3_384:
+            hmac_block_size = WC_SHA3_384_BLOCK_SIZE;
+            if (length <= WC_SHA3_384_BLOCK_SIZE) {
+                if (key != NULL) {
+                    XMEMCPY(ip, key, length);
+                }
+            }
+            else {
+                ret = wc_Sha3_384_Update(&hmac->hash.sha3, key, length);
+                if (ret != 0)
+                    break;
+                ret = wc_Sha3_384_Final(&hmac->hash.sha3, ip);
+                if (ret != 0)
+                    break;
+
+                length = WC_SHA3_384_DIGEST_SIZE;
+            }
+            break;
+    #endif
+    #ifndef WOLFSSL_NOSHA3_512
+        case WC_SHA3_512:
+            hmac_block_size = WC_SHA3_512_BLOCK_SIZE;
+            if (length <= WC_SHA3_512_BLOCK_SIZE) {
+                if (key != NULL) {
+                    XMEMCPY(ip, key, length);
+                }
+            }
+            else {
+                ret = wc_Sha3_512_Update(&hmac->hash.sha3, key, length);
+                if (ret != 0)
+                    break;
+                ret = wc_Sha3_512_Final(&hmac->hash.sha3, ip);
+                if (ret != 0)
+                    break;
+
+                length = WC_SHA3_512_DIGEST_SIZE;
+            }
+            break;
+    #endif
+    #endif /* WOLFSSL_SHA3 */
+
+        default:
+            return BAD_FUNC_ARG;
+    }
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC)
+    if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) {
+    #if defined(HAVE_INTEL_QA) || defined(HAVE_CAVIUM)
+        #ifdef HAVE_INTEL_QA
+        if (IntelQaHmacGetType(hmac->macType, NULL) == 0)
+        #endif
+        {
+            if (length > hmac_block_size)
+                length = hmac_block_size;
+            /* update key length */
+            hmac->keyLen = (word16)length;
+
+            return ret;
+        }
+        /* no need to pad below */
+    #endif
+    }
+#endif
+
+    if (ret == 0) {
+        if (length < hmac_block_size)
+            XMEMSET(ip + length, 0, hmac_block_size - length);
+
+        for(i = 0; i < hmac_block_size; i++) {
+            op[i] = ip[i] ^ OPAD;
+            ip[i] ^= IPAD;
+        }
+    }
+
+    return ret;
+}
+
+
+static int HmacKeyInnerHash(Hmac* hmac)
+{
+    int ret = 0;
+
+    switch (hmac->macType) {
+    #ifndef NO_MD5
+        case WC_MD5:
+            ret = wc_Md5Update(&hmac->hash.md5, (byte*)hmac->ipad,
+                                                             WC_MD5_BLOCK_SIZE);
+            break;
+    #endif /* !NO_MD5 */
+
+    #ifndef NO_SHA
+        case WC_SHA:
+            ret = wc_ShaUpdate(&hmac->hash.sha, (byte*)hmac->ipad,
+                                                             WC_SHA_BLOCK_SIZE);
+            break;
+    #endif /* !NO_SHA */
+
+    #ifdef WOLFSSL_SHA224
+        case WC_SHA224:
+            ret = wc_Sha224Update(&hmac->hash.sha224, (byte*)hmac->ipad,
+                                                          WC_SHA224_BLOCK_SIZE);
+            break;
+    #endif /* WOLFSSL_SHA224 */
+    #ifndef NO_SHA256
+        case WC_SHA256:
+            ret = wc_Sha256Update(&hmac->hash.sha256, (byte*)hmac->ipad,
+                                                          WC_SHA256_BLOCK_SIZE);
+            break;
+    #endif /* !NO_SHA256 */
+
+    #ifdef WOLFSSL_SHA384
+        case WC_SHA384:
+            ret = wc_Sha384Update(&hmac->hash.sha384, (byte*)hmac->ipad,
+                                                          WC_SHA384_BLOCK_SIZE);
+            break;
+    #endif /* WOLFSSL_SHA384 */
+    #ifdef WOLFSSL_SHA512
+        case WC_SHA512:
+            ret = wc_Sha512Update(&hmac->hash.sha512, (byte*)hmac->ipad,
+                                                          WC_SHA512_BLOCK_SIZE);
+            break;
+    #endif /* WOLFSSL_SHA512 */
+
+    #ifdef WOLFSSL_SHA3
+    #ifndef WOLFSSL_NOSHA3_224
+        case WC_SHA3_224:
+            ret = wc_Sha3_224_Update(&hmac->hash.sha3, (byte*)hmac->ipad,
+                                                        WC_SHA3_224_BLOCK_SIZE);
+            break;
+    #endif
+    #ifndef WOLFSSL_NOSHA3_256
+        case WC_SHA3_256:
+            ret = wc_Sha3_256_Update(&hmac->hash.sha3, (byte*)hmac->ipad,
+                                                        WC_SHA3_256_BLOCK_SIZE);
+            break;
+    #endif
+    #ifndef WOLFSSL_NOSHA3_384
+        case WC_SHA3_384:
+            ret = wc_Sha3_384_Update(&hmac->hash.sha3, (byte*)hmac->ipad,
+                                                        WC_SHA3_384_BLOCK_SIZE);
+            break;
+    #endif
+    #ifndef WOLFSSL_NOSHA3_512
+        case WC_SHA3_512:
+            ret = wc_Sha3_512_Update(&hmac->hash.sha3, (byte*)hmac->ipad,
+                                                        WC_SHA3_512_BLOCK_SIZE);
+            break;
+    #endif
+    #endif /* WOLFSSL_SHA3 */
+
+        default:
+            break;
+    }
+
+    if (ret == 0)
+        hmac->innerHashKeyed = WC_HMAC_INNER_HASH_KEYED_SW;
+
+    return ret;
+}
+
+
+int wc_HmacUpdate(Hmac* hmac, const byte* msg, word32 length)
+{
+    int ret = 0;
+
+    if (hmac == NULL || (msg == NULL && length > 0)) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef WOLF_CRYPTO_CB
+    if (hmac->devId != INVALID_DEVID) {
+        ret = wc_CryptoCb_Hmac(hmac, hmac->macType, msg, length, NULL);
+        if (ret != CRYPTOCB_UNAVAILABLE)
+            return ret;
+        /* fall-through when unavailable */
+        ret = 0; /* reset error code */
+    }
+#endif
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC)
+    if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) {
+    #if defined(HAVE_CAVIUM)
+        return NitroxHmacUpdate(hmac, msg, length);
+    #elif defined(HAVE_INTEL_QA)
+        if (IntelQaHmacGetType(hmac->macType, NULL) == 0) {
+            return IntelQaHmac(&hmac->asyncDev, hmac->macType,
+                (byte*)hmac->ipad, hmac->keyLen, NULL, msg, length);
+        }
+    #endif
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    if (!hmac->innerHashKeyed) {
+        ret = HmacKeyInnerHash(hmac);
+        if (ret != 0)
+            return ret;
+    }
+
+    switch (hmac->macType) {
+    #ifndef NO_MD5
+        case WC_MD5:
+            ret = wc_Md5Update(&hmac->hash.md5, msg, length);
+            break;
+    #endif /* !NO_MD5 */
+
+    #ifndef NO_SHA
+        case WC_SHA:
+            ret = wc_ShaUpdate(&hmac->hash.sha, msg, length);
+            break;
+    #endif /* !NO_SHA */
+
+    #ifdef WOLFSSL_SHA224
+        case WC_SHA224:
+            ret = wc_Sha224Update(&hmac->hash.sha224, msg, length);
+            break;
+    #endif /* WOLFSSL_SHA224 */
+
+    #ifndef NO_SHA256
+        case WC_SHA256:
+            ret = wc_Sha256Update(&hmac->hash.sha256, msg, length);
+            break;
+    #endif /* !NO_SHA256 */
+
+    #ifdef WOLFSSL_SHA384
+        case WC_SHA384:
+            ret = wc_Sha384Update(&hmac->hash.sha384, msg, length);
+            break;
+    #endif /* WOLFSSL_SHA384 */
+    #ifdef WOLFSSL_SHA512
+        case WC_SHA512:
+            ret = wc_Sha512Update(&hmac->hash.sha512, msg, length);
+            break;
+    #endif /* WOLFSSL_SHA512 */
+
+    #ifdef WOLFSSL_SHA3
+    #ifndef WOLFSSL_NOSHA3_224
+        case WC_SHA3_224:
+            ret = wc_Sha3_224_Update(&hmac->hash.sha3, msg, length);
+            break;
+    #endif
+    #ifndef WOLFSSL_NOSHA3_256
+        case WC_SHA3_256:
+            ret = wc_Sha3_256_Update(&hmac->hash.sha3, msg, length);
+            break;
+    #endif
+    #ifndef WOLFSSL_NOSHA3_384
+        case WC_SHA3_384:
+            ret = wc_Sha3_384_Update(&hmac->hash.sha3, msg, length);
+            break;
+    #endif
+    #ifndef WOLFSSL_NOSHA3_512
+        case WC_SHA3_512:
+            ret = wc_Sha3_512_Update(&hmac->hash.sha3, msg, length);
+            break;
+    #endif
+    #endif /* WOLFSSL_SHA3 */
+
+        default:
+            break;
+    }
+
+    return ret;
+}
+
+
+int wc_HmacFinal(Hmac* hmac, byte* hash)
+{
+    int ret;
+
+    if (hmac == NULL || hash == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef WOLF_CRYPTO_CB
+    if (hmac->devId != INVALID_DEVID) {
+        ret = wc_CryptoCb_Hmac(hmac, hmac->macType, NULL, 0, hash);
+        if (ret != CRYPTOCB_UNAVAILABLE)
+            return ret;
+        /* fall-through when unavailable */
+    }
+#endif
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC)
+    if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) {
+        int hashLen = wc_HmacSizeByType(hmac->macType);
+        if (hashLen <= 0)
+            return hashLen;
+
+    #if defined(HAVE_CAVIUM)
+        return NitroxHmacFinal(hmac, hash, hashLen);
+    #elif defined(HAVE_INTEL_QA)
+        if (IntelQaHmacGetType(hmac->macType, NULL) == 0) {
+            return IntelQaHmac(&hmac->asyncDev, hmac->macType,
+                (byte*)hmac->ipad, hmac->keyLen, hash, NULL, hashLen);
+        }
+    #endif
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    if (!hmac->innerHashKeyed) {
+        ret = HmacKeyInnerHash(hmac);
+        if (ret != 0)
+            return ret;
+    }
+
+    switch (hmac->macType) {
+    #ifndef NO_MD5
+        case WC_MD5:
+            ret = wc_Md5Final(&hmac->hash.md5, (byte*)hmac->innerHash);
+            if (ret != 0)
+                break;
+            ret = wc_Md5Update(&hmac->hash.md5, (byte*)hmac->opad,
+                                                             WC_MD5_BLOCK_SIZE);
+            if (ret != 0)
+                break;
+            ret = wc_Md5Update(&hmac->hash.md5, (byte*)hmac->innerHash,
+                                                            WC_MD5_DIGEST_SIZE);
+            if (ret != 0)
+                break;
+            ret = wc_Md5Final(&hmac->hash.md5, hash);
+            break;
+    #endif /* !NO_MD5 */
+
+    #ifndef NO_SHA
+        case WC_SHA:
+            ret = wc_ShaFinal(&hmac->hash.sha, (byte*)hmac->innerHash);
+            if (ret != 0)
+                break;
+            ret = wc_ShaUpdate(&hmac->hash.sha, (byte*)hmac->opad,
+                                                             WC_SHA_BLOCK_SIZE);
+            if (ret != 0)
+                break;
+            ret = wc_ShaUpdate(&hmac->hash.sha, (byte*)hmac->innerHash,
+                                                            WC_SHA_DIGEST_SIZE);
+            if (ret != 0)
+                break;
+            ret = wc_ShaFinal(&hmac->hash.sha, hash);
+            break;
+    #endif /* !NO_SHA */
+
+    #ifdef WOLFSSL_SHA224
+        case WC_SHA224:
+            ret = wc_Sha224Final(&hmac->hash.sha224, (byte*)hmac->innerHash);
+            if (ret != 0)
+                break;
+            ret = wc_Sha224Update(&hmac->hash.sha224, (byte*)hmac->opad,
+                                                          WC_SHA224_BLOCK_SIZE);
+            if (ret != 0)
+                break;
+            ret = wc_Sha224Update(&hmac->hash.sha224, (byte*)hmac->innerHash,
+                                                         WC_SHA224_DIGEST_SIZE);
+            if (ret != 0)
+                break;
+            ret = wc_Sha224Final(&hmac->hash.sha224, hash);
+            if (ret != 0)
+                break;
+            break;
+    #endif /* WOLFSSL_SHA224 */
+    #ifndef NO_SHA256
+        case WC_SHA256:
+            ret = wc_Sha256Final(&hmac->hash.sha256, (byte*)hmac->innerHash);
+            if (ret != 0)
+                break;
+            ret = wc_Sha256Update(&hmac->hash.sha256, (byte*)hmac->opad,
+                                                          WC_SHA256_BLOCK_SIZE);
+            if (ret != 0)
+                break;
+            ret = wc_Sha256Update(&hmac->hash.sha256, (byte*)hmac->innerHash,
+                                                         WC_SHA256_DIGEST_SIZE);
+            if (ret != 0)
+                break;
+            ret = wc_Sha256Final(&hmac->hash.sha256, hash);
+            break;
+    #endif /* !NO_SHA256 */
+
+    #ifdef WOLFSSL_SHA384
+        case WC_SHA384:
+            ret = wc_Sha384Final(&hmac->hash.sha384, (byte*)hmac->innerHash);
+            if (ret != 0)
+                break;
+            ret = wc_Sha384Update(&hmac->hash.sha384, (byte*)hmac->opad,
+                                                          WC_SHA384_BLOCK_SIZE);
+            if (ret != 0)
+                break;
+            ret = wc_Sha384Update(&hmac->hash.sha384, (byte*)hmac->innerHash,
+                                                         WC_SHA384_DIGEST_SIZE);
+            if (ret != 0)
+                break;
+            ret = wc_Sha384Final(&hmac->hash.sha384, hash);
+            break;
+    #endif /* WOLFSSL_SHA384 */
+    #ifdef WOLFSSL_SHA512
+        case WC_SHA512:
+            ret = wc_Sha512Final(&hmac->hash.sha512, (byte*)hmac->innerHash);
+            if (ret != 0)
+                break;
+            ret = wc_Sha512Update(&hmac->hash.sha512, (byte*)hmac->opad,
+                                                          WC_SHA512_BLOCK_SIZE);
+            if (ret != 0)
+                break;
+            ret = wc_Sha512Update(&hmac->hash.sha512, (byte*)hmac->innerHash,
+                                                         WC_SHA512_DIGEST_SIZE);
+            if (ret != 0)
+                break;
+            ret = wc_Sha512Final(&hmac->hash.sha512, hash);
+            break;
+    #endif /* WOLFSSL_SHA512 */
+
+    #ifdef WOLFSSL_SHA3
+    #ifndef WOLFSSL_NOSHA3_224
+        case WC_SHA3_224:
+            ret = wc_Sha3_224_Final(&hmac->hash.sha3, (byte*)hmac->innerHash);
+            if (ret != 0)
+                break;
+            ret = wc_Sha3_224_Update(&hmac->hash.sha3, (byte*)hmac->opad,
+                                                        WC_SHA3_224_BLOCK_SIZE);
+            if (ret != 0)
+                break;
+            ret = wc_Sha3_224_Update(&hmac->hash.sha3, (byte*)hmac->innerHash,
+                                                       WC_SHA3_224_DIGEST_SIZE);
+            if (ret != 0)
+                break;
+            ret = wc_Sha3_224_Final(&hmac->hash.sha3, hash);
+            break;
+    #endif
+    #ifndef WOLFSSL_NOSHA3_256
+        case WC_SHA3_256:
+            ret = wc_Sha3_256_Final(&hmac->hash.sha3, (byte*)hmac->innerHash);
+            if (ret != 0)
+                break;
+            ret = wc_Sha3_256_Update(&hmac->hash.sha3, (byte*)hmac->opad,
+                                                        WC_SHA3_256_BLOCK_SIZE);
+            if (ret != 0)
+                break;
+            ret = wc_Sha3_256_Update(&hmac->hash.sha3, (byte*)hmac->innerHash,
+                                                       WC_SHA3_256_DIGEST_SIZE);
+            if (ret != 0)
+                break;
+            ret = wc_Sha3_256_Final(&hmac->hash.sha3, hash);
+            break;
+    #endif
+    #ifndef WOLFSSL_NOSHA3_384
+        case WC_SHA3_384:
+            ret = wc_Sha3_384_Final(&hmac->hash.sha3, (byte*)hmac->innerHash);
+            if (ret != 0)
+                break;
+            ret = wc_Sha3_384_Update(&hmac->hash.sha3, (byte*)hmac->opad,
+                                                        WC_SHA3_384_BLOCK_SIZE);
+            if (ret != 0)
+                break;
+            ret = wc_Sha3_384_Update(&hmac->hash.sha3, (byte*)hmac->innerHash,
+                                                       WC_SHA3_384_DIGEST_SIZE);
+            if (ret != 0)
+                break;
+            ret = wc_Sha3_384_Final(&hmac->hash.sha3, hash);
+            break;
+    #endif
+    #ifndef WOLFSSL_NOSHA3_512
+        case WC_SHA3_512:
+            ret = wc_Sha3_512_Final(&hmac->hash.sha3, (byte*)hmac->innerHash);
+            if (ret != 0)
+                break;
+            ret = wc_Sha3_512_Update(&hmac->hash.sha3, (byte*)hmac->opad,
+                                                        WC_SHA3_512_BLOCK_SIZE);
+            if (ret != 0)
+                break;
+            ret = wc_Sha3_512_Update(&hmac->hash.sha3, (byte*)hmac->innerHash,
+                                                       WC_SHA3_512_DIGEST_SIZE);
+            if (ret != 0)
+                break;
+            ret = wc_Sha3_512_Final(&hmac->hash.sha3, hash);
+            break;
+    #endif
+    #endif /* WOLFSSL_SHA3 */
+
+        default:
+            ret = BAD_FUNC_ARG;
+            break;
+    }
+
+    if (ret == 0) {
+        hmac->innerHashKeyed = 0;
+    }
+
+    return ret;
+}
+
+
+/* Initialize Hmac for use with async device */
+int wc_HmacInit(Hmac* hmac, void* heap, int devId)
+{
+    int ret = 0;
+
+    if (hmac == NULL)
+        return BAD_FUNC_ARG;
+
+    XMEMSET(hmac, 0, sizeof(Hmac));
+    hmac->macType = WC_HASH_TYPE_NONE;
+    hmac->heap = heap;
+#ifdef WOLF_CRYPTO_CB
+    hmac->devId = devId;
+    hmac->devCtx = NULL;
+#endif
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC)
+    ret = wolfAsync_DevCtxInit(&hmac->asyncDev, WOLFSSL_ASYNC_MARKER_HMAC,
+                                                         hmac->heap, devId);
+#else
+    (void)devId;
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    return ret;
+}
+
+#ifdef HAVE_PKCS11
+int  wc_HmacInit_Id(Hmac* hmac, unsigned char* id, int len, void* heap,
+                    int devId)
+{
+    int ret = 0;
+
+    if (hmac == NULL)
+        ret = BAD_FUNC_ARG;
+    if (ret == 0 && (len < 0 || len > HMAC_MAX_ID_LEN))
+        ret = BUFFER_E;
+
+    if (ret == 0)
+        ret  = wc_HmacInit(hmac, heap, devId);
+    if (ret == 0) {
+        XMEMCPY(hmac->id, id, len);
+        hmac->idLen = len;
+    }
+
+    return ret;
+}
+#endif
+
+/* Free Hmac from use with async device */
+void wc_HmacFree(Hmac* hmac)
+{
+    if (hmac == NULL)
+        return;
+
+#ifdef WOLF_CRYPTO_CB
+    /* handle cleanup case where final is not called */
+    if (hmac->devId != INVALID_DEVID && hmac->devCtx != NULL) {
+        int  ret;
+        byte finalHash[WC_HMAC_BLOCK_SIZE];
+        ret = wc_CryptoCb_Hmac(hmac, hmac->macType, NULL, 0, finalHash);
+        (void)ret; /* must ignore return code here */
+        (void)finalHash;
+    }
+#endif
+
+    switch (hmac->macType) {
+    #ifndef NO_MD5
+        case WC_MD5:
+            wc_Md5Free(&hmac->hash.md5);
+            break;
+    #endif /* !NO_MD5 */
+
+    #ifndef NO_SHA
+        case WC_SHA:
+            wc_ShaFree(&hmac->hash.sha);
+            break;
+    #endif /* !NO_SHA */
+
+    #ifdef WOLFSSL_SHA224
+        case WC_SHA224:
+            wc_Sha224Free(&hmac->hash.sha224);
+            break;
+    #endif /* WOLFSSL_SHA224 */
+    #ifndef NO_SHA256
+        case WC_SHA256:
+            wc_Sha256Free(&hmac->hash.sha256);
+            break;
+    #endif /* !NO_SHA256 */
+
+    #ifdef WOLFSSL_SHA384
+        case WC_SHA384:
+            wc_Sha384Free(&hmac->hash.sha384);
+            break;
+    #endif /* WOLFSSL_SHA384 */
+    #ifdef WOLFSSL_SHA512
+        case WC_SHA512:
+            wc_Sha512Free(&hmac->hash.sha512);
+            break;
+    #endif /* WOLFSSL_SHA512 */
+
+    #ifdef WOLFSSL_SHA3
+    #ifndef WOLFSSL_NOSHA3_224
+        case WC_SHA3_224:
+            wc_Sha3_224_Free(&hmac->hash.sha3);
+            break;
+    #endif
+    #ifndef WOLFSSL_NOSHA3_256
+        case WC_SHA3_256:
+            wc_Sha3_256_Free(&hmac->hash.sha3);
+            break;
+    #endif
+    #ifndef WOLFSSL_NOSHA3_384
+        case WC_SHA3_384:
+            wc_Sha3_384_Free(&hmac->hash.sha3);
+            break;
+    #endif
+    #ifndef WOLFSSL_NOSHA3_512
+        case WC_SHA3_512:
+            wc_Sha3_512_Free(&hmac->hash.sha3);
+            break;
+    #endif
+    #endif /* WOLFSSL_SHA3 */
+
+        default:
+            break;
+    }
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC)
+    wolfAsync_DevCtxFree(&hmac->asyncDev, WOLFSSL_ASYNC_MARKER_HMAC);
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    switch (hmac->macType) {
+    #ifndef NO_MD5
+        case WC_MD5:
+            wc_Md5Free(&hmac->hash.md5);
+            break;
+    #endif /* !NO_MD5 */
+
+    #ifndef NO_SHA
+        case WC_SHA:
+            wc_ShaFree(&hmac->hash.sha);
+            break;
+    #endif /* !NO_SHA */
+
+    #ifdef WOLFSSL_SHA224
+        case WC_SHA224:
+            wc_Sha224Free(&hmac->hash.sha224);
+            break;
+    #endif /* WOLFSSL_SHA224 */
+    #ifndef NO_SHA256
+        case WC_SHA256:
+            wc_Sha256Free(&hmac->hash.sha256);
+            break;
+    #endif /* !NO_SHA256 */
+
+    #ifdef WOLFSSL_SHA512
+    #ifdef WOLFSSL_SHA384
+        case WC_SHA384:
+            wc_Sha384Free(&hmac->hash.sha384);
+            break;
+    #endif /* WOLFSSL_SHA384 */
+        case WC_SHA512:
+            wc_Sha512Free(&hmac->hash.sha512);
+            break;
+    #endif /* WOLFSSL_SHA512 */
+    }
+}
+
+int wolfSSL_GetHmacMaxSize(void)
+{
+    return WC_MAX_DIGEST_SIZE;
+}
+
+#ifdef HAVE_HKDF
+    /* HMAC-KDF-Extract.
+     * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF).
+     *
+     * type     The hash algorithm type.
+     * salt     The optional salt value.
+     * saltSz   The size of the salt.
+     * inKey    The input keying material.
+     * inKeySz  The size of the input keying material.
+     * out      The pseudorandom key with the length that of the hash.
+     * returns 0 on success, otherwise failure.
+     */
+    int wc_HKDF_Extract(int type, const byte* salt, word32 saltSz,
+                        const byte* inKey, word32 inKeySz, byte* out)
+    {
+        byte   tmp[WC_MAX_DIGEST_SIZE]; /* localSalt helper */
+        Hmac   myHmac;
+        int    ret;
+        const  byte* localSalt;  /* either points to user input or tmp */
+        int    hashSz;
+
+        ret = wc_HmacSizeByType(type);
+        if (ret < 0)
+            return ret;
+
+        hashSz = ret;
+        localSalt = salt;
+        if (localSalt == NULL) {
+            XMEMSET(tmp, 0, hashSz);
+            localSalt = tmp;
+            saltSz    = hashSz;
+        }
+
+        ret = wc_HmacInit(&myHmac, NULL, INVALID_DEVID);
+        if (ret == 0) {
+            ret = wc_HmacSetKey(&myHmac, type, localSalt, saltSz);
+            if (ret == 0)
+                ret = wc_HmacUpdate(&myHmac, inKey, inKeySz);
+            if (ret == 0)
+                ret = wc_HmacFinal(&myHmac,  out);
+            wc_HmacFree(&myHmac);
+        }
+
+        return ret;
+    }
+
+    /* HMAC-KDF-Expand.
+     * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF).
+     *
+     * type     The hash algorithm type.
+     * inKey    The input key.
+     * inKeySz  The size of the input key.
+     * info     The application specific information.
+     * infoSz   The size of the application specific information.
+     * out      The output keying material.
+     * returns 0 on success, otherwise failure.
+     */
+    int wc_HKDF_Expand(int type, const byte* inKey, word32 inKeySz,
+                       const byte* info, word32 infoSz, byte* out, word32 outSz)
+    {
+        byte   tmp[WC_MAX_DIGEST_SIZE];
+        Hmac   myHmac;
+        int    ret = 0;
+        word32 outIdx = 0;
+        word32 hashSz = wc_HmacSizeByType(type);
+        byte   n = 0x1;
+
+        ret = wc_HmacInit(&myHmac, NULL, INVALID_DEVID);
+        if (ret != 0)
+            return ret;
+
+        while (outIdx < outSz) {
+            int    tmpSz = (n == 1) ? 0 : hashSz;
+            word32 left = outSz - outIdx;
+
+            ret = wc_HmacSetKey(&myHmac, type, inKey, inKeySz);
+            if (ret != 0)
+                break;
+            ret = wc_HmacUpdate(&myHmac, tmp, tmpSz);
+            if (ret != 0)
+                break;
+            ret = wc_HmacUpdate(&myHmac, info, infoSz);
+            if (ret != 0)
+                break;
+            ret = wc_HmacUpdate(&myHmac, &n, 1);
+            if (ret != 0)
+                break;
+            ret = wc_HmacFinal(&myHmac, tmp);
+            if (ret != 0)
+                break;
+
+            left = min(left, hashSz);
+            XMEMCPY(out+outIdx, tmp, left);
+
+            outIdx += hashSz;
+            n++;
+        }
+
+        wc_HmacFree(&myHmac);
+
+        return ret;
+    }
+
+    /* HMAC-KDF.
+     * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF).
+     *
+     * type     The hash algorithm type.
+     * inKey    The input keying material.
+     * inKeySz  The size of the input keying material.
+     * salt     The optional salt value.
+     * saltSz   The size of the salt.
+     * info     The application specific information.
+     * infoSz   The size of the application specific information.
+     * out      The output keying material.
+     * returns 0 on success, otherwise failure.
+     */
+    int wc_HKDF(int type, const byte* inKey, word32 inKeySz,
+                       const byte* salt,  word32 saltSz,
+                       const byte* info,  word32 infoSz,
+                       byte* out,         word32 outSz)
+    {
+        byte   prk[WC_MAX_DIGEST_SIZE];
+        int    hashSz = wc_HmacSizeByType(type);
+        int    ret;
+
+        if (hashSz < 0)
+            return BAD_FUNC_ARG;
+
+        ret = wc_HKDF_Extract(type, salt, saltSz, inKey, inKeySz, prk);
+        if (ret != 0)
+            return ret;
+
+        return wc_HKDF_Expand(type, prk, hashSz, info, infoSz, out, outSz);
+    }
+
+#endif /* HAVE_HKDF */
+
+#endif /* HAVE_FIPS */
+#endif /* NO_HMAC */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/integer.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/integer.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/integer.c	(revision 453)
@@ -0,0 +1,5320 @@
+/* integer.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+/*
+ * Based on public domain LibTomMath 0.38 by Tom St Denis, tomstdenis@iahu.ca,
+ * http://math.libtomcrypt.com
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+/* in case user set USE_FAST_MATH there */
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+#ifndef NO_BIG_INT
+
+#ifndef USE_FAST_MATH
+
+#ifndef WOLFSSL_SP_MATH
+
+#include <wolfssl/wolfcrypt/integer.h>
+
+#if defined(FREESCALE_LTC_TFM)
+    #include <wolfssl/wolfcrypt/port/nxp/ksdk_port.h>
+#endif
+#ifdef WOLFSSL_DEBUG_MATH
+    #include <stdio.h>
+#endif
+
+#ifdef SHOW_GEN
+    #ifndef NO_STDIO_FILESYSTEM
+        #include <stdio.h>
+    #endif
+#endif
+
+#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)
+#ifdef __cplusplus
+    extern "C" {
+#endif
+WOLFSSL_LOCAL int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod,
+    mp_int* res);
+WOLFSSL_LOCAL int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod,
+    mp_int* res);
+WOLFSSL_LOCAL int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod,
+    mp_int* res);
+WOLFSSL_LOCAL int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod,
+    mp_int* res);
+WOLFSSL_LOCAL int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod,
+    mp_int* res);
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+#endif
+
+/* reverse an array, used for radix code */
+static void
+bn_reverse (unsigned char *s, int len)
+{
+    int     ix, iy;
+    unsigned char t;
+
+    ix = 0;
+    iy = len - 1;
+    while (ix < iy) {
+        t     = s[ix];
+        s[ix] = s[iy];
+        s[iy] = t;
+        ++ix;
+        --iy;
+    }
+}
+
+/* math settings check */
+word32 CheckRunTimeSettings(void)
+{
+    return CTC_SETTINGS;
+}
+
+
+/* handle up to 6 inits */
+int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e,
+                  mp_int* f)
+{
+    int res = MP_OKAY;
+
+    if (a) XMEMSET(a, 0, sizeof(mp_int));
+    if (b) XMEMSET(b, 0, sizeof(mp_int));
+    if (c) XMEMSET(c, 0, sizeof(mp_int));
+    if (d) XMEMSET(d, 0, sizeof(mp_int));
+    if (e) XMEMSET(e, 0, sizeof(mp_int));
+    if (f) XMEMSET(f, 0, sizeof(mp_int));
+
+    if (a && ((res = mp_init(a)) != MP_OKAY))
+        return res;
+
+    if (b && ((res = mp_init(b)) != MP_OKAY)) {
+        mp_clear(a);
+        return res;
+    }
+
+    if (c && ((res = mp_init(c)) != MP_OKAY)) {
+        mp_clear(a); mp_clear(b);
+        return res;
+    }
+
+    if (d && ((res = mp_init(d)) != MP_OKAY)) {
+        mp_clear(a); mp_clear(b); mp_clear(c);
+        return res;
+    }
+
+    if (e && ((res = mp_init(e)) != MP_OKAY)) {
+        mp_clear(a); mp_clear(b); mp_clear(c); mp_clear(d);
+        return res;
+    }
+
+    if (f && ((res = mp_init(f)) != MP_OKAY)) {
+        mp_clear(a); mp_clear(b); mp_clear(c); mp_clear(d); mp_clear(e);
+        return res;
+    }
+
+    return res;
+}
+
+
+/* init a new mp_int */
+int mp_init (mp_int * a)
+{
+  /* Safeguard against passing in a null pointer */
+  if (a == NULL)
+    return MP_VAL;
+
+  /* defer allocation until mp_grow */
+  a->dp = NULL;
+
+  /* set the used to zero, allocated digits to the default precision
+   * and sign to positive */
+  a->used  = 0;
+  a->alloc = 0;
+  a->sign  = MP_ZPOS;
+#ifdef HAVE_WOLF_BIGINT
+  wc_bigint_init(&a->raw);
+#endif
+
+  return MP_OKAY;
+}
+
+
+/* clear one (frees)  */
+void mp_clear (mp_int * a)
+{
+  int i;
+
+  if (a == NULL)
+      return;
+
+  /* only do anything if a hasn't been freed previously */
+  if (a->dp != NULL) {
+    /* first zero the digits */
+    for (i = 0; i < a->used; i++) {
+        a->dp[i] = 0;
+    }
+
+    /* free ram */
+    mp_free(a);
+
+    /* reset members to make debugging easier */
+    a->alloc = a->used = 0;
+    a->sign  = MP_ZPOS;
+  }
+}
+
+void mp_free (mp_int * a)
+{
+  /* only do anything if a hasn't been freed previously */
+  if (a->dp != NULL) {
+    /* free ram */
+    XFREE(a->dp, 0, DYNAMIC_TYPE_BIGINT);
+    a->dp    = NULL;
+  }
+
+#ifdef HAVE_WOLF_BIGINT
+  wc_bigint_free(&a->raw);
+#endif
+}
+
+void mp_forcezero(mp_int * a)
+{
+    if (a == NULL)
+        return;
+
+    /* only do anything if a hasn't been freed previously */
+    if (a->dp != NULL) {
+      /* force zero the used digits */
+      ForceZero(a->dp, a->used * sizeof(mp_digit));
+#ifdef HAVE_WOLF_BIGINT
+      wc_bigint_zero(&a->raw);
+#endif
+      /* free ram */
+      mp_free(a);
+
+      /* reset members to make debugging easier */
+      a->alloc = a->used = 0;
+      a->sign  = MP_ZPOS;
+    }
+
+    a->sign = MP_ZPOS;
+    a->used = 0;
+}
+
+
+/* get the size for an unsigned equivalent */
+int mp_unsigned_bin_size (mp_int * a)
+{
+  int     size = mp_count_bits (a);
+  return (size / 8 + ((size & 7) != 0 ? 1 : 0));
+}
+
+
+/* returns the number of bits in an int */
+int mp_count_bits (mp_int * a)
+{
+  int     r;
+  mp_digit q;
+
+  /* shortcut */
+  if (a->used == 0) {
+    return 0;
+  }
+
+  /* get number of digits and add that */
+  r = (a->used - 1) * DIGIT_BIT;
+
+  /* take the last digit and count the bits in it */
+  q = a->dp[a->used - 1];
+  while (q > ((mp_digit) 0)) {
+    ++r;
+    q >>= ((mp_digit) 1);
+  }
+  return r;
+}
+
+
+int mp_leading_bit (mp_int * a)
+{
+    int bit = 0;
+    mp_int t;
+
+    if (mp_init_copy(&t, a) != MP_OKAY)
+        return 0;
+
+    while (mp_iszero(&t) == MP_NO) {
+#ifndef MP_8BIT
+        bit = (t.dp[0] & 0x80) != 0;
+#else
+        bit = ((t.dp[0] | ((t.dp[1] & 0x01) << 7)) & 0x80) != 0;
+#endif
+        if (mp_div_2d (&t, 8, &t, NULL) != MP_OKAY)
+            break;
+    }
+    mp_clear(&t);
+    return bit;
+}
+
+int mp_to_unsigned_bin_at_pos(int x, mp_int *t, unsigned char *b)
+{
+  int res = 0;
+  while (mp_iszero(t) == MP_NO) {
+#ifndef MP_8BIT
+      b[x++] = (unsigned char) (t->dp[0] & 255);
+#else
+      b[x++] = (unsigned char) (t->dp[0] | ((t->dp[1] & 0x01) << 7));
+#endif
+    if ((res = mp_div_2d (t, 8, t, NULL)) != MP_OKAY) {
+      return res;
+    }
+    res = x;
+  }
+  return res;
+}
+
+/* store in unsigned [big endian] format */
+int mp_to_unsigned_bin (mp_int * a, unsigned char *b)
+{
+  int     x, res;
+  mp_int  t;
+
+  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+    return res;
+  }
+
+  x = mp_to_unsigned_bin_at_pos(0, &t, b);
+  if (x < 0) {
+    mp_clear(&t);
+    return x;
+  }
+
+  bn_reverse (b, x);
+  mp_clear (&t);
+  return res;
+}
+
+int mp_to_unsigned_bin_len(mp_int * a, unsigned char *b, int c)
+{
+    int i, len;
+
+    len = mp_unsigned_bin_size(a);
+
+    /* pad front w/ zeros to match length */
+    for (i = 0; i < c - len; i++)
+        b[i] = 0x00;
+    return mp_to_unsigned_bin(a, b + i);
+}
+
+/* creates "a" then copies b into it */
+int mp_init_copy (mp_int * a, mp_int * b)
+{
+  int     res;
+
+  if ((res = mp_init_size (a, b->used)) != MP_OKAY) {
+    return res;
+  }
+
+  if((res = mp_copy (b, a)) != MP_OKAY) {
+    mp_clear(a);
+  }
+
+  return res;
+}
+
+
+/* copy, b = a */
+int mp_copy (mp_int * a, mp_int * b)
+{
+  int     res, n;
+
+  /* Safeguard against passing in a null pointer */
+  if (a == NULL || b == NULL)
+    return MP_VAL;
+
+  /* if dst == src do nothing */
+  if (a == b) {
+    return MP_OKAY;
+  }
+
+  /* grow dest */
+  if (b->alloc < a->used || b->alloc == 0) {
+     if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  /* zero b and copy the parameters over */
+  {
+    mp_digit *tmpa, *tmpb;
+
+    /* pointer aliases */
+
+    /* source */
+    tmpa = a->dp;
+
+    /* destination */
+    tmpb = b->dp;
+
+    /* copy all the digits */
+    for (n = 0; n < a->used; n++) {
+      *tmpb++ = *tmpa++;
+    }
+
+    /* clear high digits */
+    for (; n < b->used && b->dp; n++) {
+      *tmpb++ = 0;
+    }
+  }
+
+  /* copy used count and sign */
+  b->used = a->used;
+  b->sign = a->sign;
+  return MP_OKAY;
+}
+
+
+/* grow as required */
+int mp_grow (mp_int * a, int size)
+{
+  int     i;
+  mp_digit *tmp;
+
+  /* if the alloc size is smaller alloc more ram */
+  if (a->alloc < size || size == 0) {
+    /* ensure there are always at least MP_PREC digits extra on top */
+    size += (MP_PREC * 2) - (size % MP_PREC);
+
+    /* reallocate the array a->dp
+     *
+     * We store the return in a temporary variable
+     * in case the operation failed we don't want
+     * to overwrite the dp member of a.
+     */
+    tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size, NULL,
+                                                           DYNAMIC_TYPE_BIGINT);
+    if (tmp == NULL) {
+      /* reallocation failed but "a" is still valid [can be freed] */
+      return MP_MEM;
+    }
+
+    /* reallocation succeeded so set a->dp */
+    a->dp = tmp;
+
+    /* zero excess digits */
+    i        = a->alloc;
+    a->alloc = size;
+    for (; i < a->alloc; i++) {
+      a->dp[i] = 0;
+    }
+  }
+  return MP_OKAY;
+}
+
+
+/* shift right by a certain bit count (store quotient in c, optional
+   remainder in d) */
+int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d)
+{
+  int     D, res;
+  mp_int  t;
+
+
+  /* if the shift count is <= 0 then we do no work */
+  if (b <= 0) {
+    res = mp_copy (a, c);
+    if (d != NULL) {
+      mp_zero (d);
+    }
+    return res;
+  }
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  /* get the remainder */
+  if (d != NULL) {
+    if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) {
+      mp_clear (&t);
+      return res;
+    }
+  }
+
+  /* copy */
+  if ((res = mp_copy (a, c)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+
+  /* shift by as many digits in the bit count */
+  if (b >= (int)DIGIT_BIT) {
+    mp_rshd (c, b / DIGIT_BIT);
+  }
+
+  /* shift any bit count < DIGIT_BIT */
+  D = (b % DIGIT_BIT);
+  if (D != 0) {
+    mp_rshb(c, D);
+  }
+  mp_clamp (c);
+  if (d != NULL) {
+    mp_exch (&t, d);
+  }
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+
+/* set to zero */
+void mp_zero (mp_int * a)
+{
+  int       n;
+  mp_digit *tmp;
+
+  if (a == NULL)
+      return;
+
+  a->sign = MP_ZPOS;
+  a->used = 0;
+
+  tmp = a->dp;
+  for (n = 0; n < a->alloc; n++) {
+     *tmp++ = 0;
+  }
+}
+
+
+/* trim unused digits
+ *
+ * This is used to ensure that leading zero digits are
+ * trimmed and the leading "used" digit will be non-zero
+ * Typically very fast.  Also fixes the sign if there
+ * are no more leading digits
+ */
+void mp_clamp (mp_int * a)
+{
+  /* decrease used while the most significant digit is
+   * zero.
+   */
+  while (a->used > 0 && a->dp[a->used - 1] == 0) {
+    --(a->used);
+  }
+
+  /* reset the sign flag if used == 0 */
+  if (a->used == 0) {
+    a->sign = MP_ZPOS;
+  }
+}
+
+
+/* swap the elements of two integers, for cases where you can't simply swap the
+ * mp_int pointers around
+ */
+void mp_exch (mp_int * a, mp_int * b)
+{
+  mp_int  t;
+
+  t  = *a;
+  *a = *b;
+  *b = t;
+}
+
+
+/* shift right a certain number of bits */
+void mp_rshb (mp_int *c, int x)
+{
+    mp_digit *tmpc, mask, shift;
+    mp_digit r, rr;
+    mp_digit D = x;
+
+    if (mp_iszero(c)) return;
+
+    /* mask */
+    mask = (((mp_digit)1) << D) - 1;
+
+    /* shift for lsb */
+    shift = DIGIT_BIT - D;
+
+    /* alias */
+    tmpc = c->dp + (c->used - 1);
+
+    /* carry */
+    r = 0;
+    for (x = c->used - 1; x >= 0; x--) {
+      /* get the lower  bits of this word in a temp */
+      rr = *tmpc & mask;
+
+      /* shift the current word and mix in the carry bits from previous word */
+      *tmpc = (*tmpc >> D) | (r << shift);
+      --tmpc;
+
+      /* set the carry to the carry bits of the current word found above */
+      r = rr;
+    }
+    mp_clamp(c);
+}
+
+
+/* shift right a certain amount of digits */
+void mp_rshd (mp_int * a, int b)
+{
+  int     x;
+
+  /* if b <= 0 then ignore it */
+  if (b <= 0) {
+    return;
+  }
+
+  /* if b > used then simply zero it and return */
+  if (a->used <= b) {
+    mp_zero (a);
+    return;
+  }
+
+  {
+    mp_digit *bottom, *top;
+
+    /* shift the digits down */
+
+    /* bottom */
+    bottom = a->dp;
+
+    /* top [offset into digits] */
+    top = a->dp + b;
+
+    /* this is implemented as a sliding window where
+     * the window is b-digits long and digits from
+     * the top of the window are copied to the bottom
+     *
+     * e.g.
+
+     b-2 | b-1 | b0 | b1 | b2 | ... | bb |   ---->
+                 /\                   |      ---->
+                  \-------------------/      ---->
+     */
+    for (x = 0; x < (a->used - b); x++) {
+      *bottom++ = *top++;
+    }
+
+    /* zero the top digits */
+    for (; x < a->used; x++) {
+      *bottom++ = 0;
+    }
+  }
+
+  /* remove excess digits */
+  a->used -= b;
+}
+
+
+/* calc a value mod 2**b */
+int mp_mod_2d (mp_int * a, int b, mp_int * c)
+{
+  int     x, res;
+
+  /* if b is <= 0 then zero the int */
+  if (b <= 0) {
+    mp_zero (c);
+    return MP_OKAY;
+  }
+
+  /* if the modulus is larger than the value than return */
+  if (b >= (int) (a->used * DIGIT_BIT)) {
+    res = mp_copy (a, c);
+    return res;
+  }
+
+  /* copy */
+  if ((res = mp_copy (a, c)) != MP_OKAY) {
+    return res;
+  }
+
+  /* zero digits above the last digit of the modulus */
+  for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) {
+    c->dp[x] = 0;
+  }
+  /* clear the digit that is not completely outside/inside the modulus */
+  c->dp[b / DIGIT_BIT] &= (mp_digit) ((((mp_digit) 1) <<
+              (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1));
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+
+/* reads a unsigned char array, assumes the msb is stored first [big endian] */
+int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c)
+{
+  int     res;
+
+  /* make sure there are at least two digits */
+  if (a->alloc < 2) {
+     if ((res = mp_grow(a, 2)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  /* zero the int */
+  mp_zero (a);
+
+  /* read the bytes in */
+  while (c-- > 0) {
+    if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) {
+      return res;
+    }
+
+#ifndef MP_8BIT
+      a->dp[0] |= *b++;
+      a->used += 1;
+#else
+      a->dp[0] = (*b & MP_MASK);
+      a->dp[1] |= ((*b++ >> 7U) & 1);
+      a->used += 2;
+#endif
+  }
+  mp_clamp (a);
+  return MP_OKAY;
+}
+
+
+/* shift left by a certain bit count */
+int mp_mul_2d (mp_int * a, int b, mp_int * c)
+{
+  mp_digit d;
+  int      res;
+
+  /* copy */
+  if (a != c) {
+     if ((res = mp_copy (a, c)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) {
+     if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  /* shift by as many digits in the bit count */
+  if (b >= (int)DIGIT_BIT) {
+    if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* shift any bit count < DIGIT_BIT */
+  d = (mp_digit) (b % DIGIT_BIT);
+  if (d != 0) {
+    mp_digit *tmpc, shift, mask, r, rr;
+    int x;
+
+    /* bitmask for carries */
+    mask = (((mp_digit)1) << d) - 1;
+
+    /* shift for msbs */
+    shift = DIGIT_BIT - d;
+
+    /* alias */
+    tmpc = c->dp;
+
+    /* carry */
+    r    = 0;
+    for (x = 0; x < c->used; x++) {
+      /* get the higher bits of the current word */
+      rr = (*tmpc >> shift) & mask;
+
+      /* shift the current word and OR in the carry */
+      *tmpc = (mp_digit)(((*tmpc << d) | r) & MP_MASK);
+      ++tmpc;
+
+      /* set the carry to the carry bits of the current word */
+      r = rr;
+    }
+
+    /* set final carry */
+    if (r != 0) {
+       c->dp[(c->used)++] = r;
+    }
+  }
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+
+/* shift left a certain amount of digits */
+int mp_lshd (mp_int * a, int b)
+{
+  int     x, res;
+
+  /* if its less than zero return */
+  if (b <= 0) {
+    return MP_OKAY;
+  }
+
+  /* grow to fit the new digits */
+  if (a->alloc < a->used + b) {
+     if ((res = mp_grow (a, a->used + b)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  {
+    mp_digit *top, *bottom;
+
+    /* increment the used by the shift amount then copy upwards */
+    a->used += b;
+
+    /* top */
+    top = a->dp + a->used - 1;
+
+    /* base */
+    bottom = a->dp + a->used - 1 - b;
+
+    /* much like mp_rshd this is implemented using a sliding window
+     * except the window goes the other way around.  Copying from
+     * the bottom to the top.  see bn_mp_rshd.c for more info.
+     */
+    for (x = a->used - 1; x >= b; x--) {
+      *top-- = *bottom--;
+    }
+
+    /* zero the lower digits */
+    top = a->dp;
+    for (x = 0; x < b; x++) {
+      *top++ = 0;
+    }
+  }
+  return MP_OKAY;
+}
+
+
+/* this is a shell function that calls either the normal or Montgomery
+ * exptmod functions.  Originally the call to the montgomery code was
+ * embedded in the normal function but that wasted a lot of stack space
+ * for nothing (since 99% of the time the Montgomery code would be called)
+ */
+#if defined(FREESCALE_LTC_TFM)
+int wolfcrypt_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
+#else
+int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
+#endif
+{
+  int dr;
+
+  /* modulus P must be positive */
+  if (mp_iszero(P) || P->sign == MP_NEG) {
+     return MP_VAL;
+  }
+  if (mp_isone(P)) {
+     mp_set(Y, 0);
+     return MP_OKAY;
+  }
+  if (mp_iszero(X)) {
+     mp_set(Y, 1);
+     return MP_OKAY;
+  }
+  if (mp_iszero(G)) {
+     mp_set(Y, 0);
+     return MP_OKAY;
+  }
+
+  /* if exponent X is negative we have to recurse */
+  if (X->sign == MP_NEG) {
+#ifdef BN_MP_INVMOD_C
+     mp_int tmpG, tmpX;
+     int err;
+
+     /* first compute 1/G mod P */
+     if ((err = mp_init(&tmpG)) != MP_OKAY) {
+        return err;
+     }
+     if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) {
+        mp_clear(&tmpG);
+        return err;
+     }
+
+     /* now get |X| */
+     if ((err = mp_init(&tmpX)) != MP_OKAY) {
+        mp_clear(&tmpG);
+        return err;
+     }
+     if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
+        mp_clear(&tmpG);
+        mp_clear(&tmpX);
+        return err;
+     }
+
+     /* and now compute (1/G)**|X| instead of G**X [X < 0] */
+     err = mp_exptmod(&tmpG, &tmpX, P, Y);
+     mp_clear(&tmpG);
+     mp_clear(&tmpX);
+     return err;
+#else
+     /* no invmod */
+     return MP_VAL;
+#endif
+  }
+
+#ifdef BN_MP_EXPTMOD_BASE_2
+  if (G->used == 1 && G->dp[0] == 2) {
+    return mp_exptmod_base_2(X, P, Y);
+  }
+#endif
+
+/* modified diminished radix reduction */
+#if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && \
+  defined(BN_S_MP_EXPTMOD_C)
+  if (mp_reduce_is_2k_l(P) == MP_YES) {
+     return s_mp_exptmod(G, X, P, Y, 1);
+  }
+#endif
+
+#ifdef BN_MP_DR_IS_MODULUS_C
+  /* is it a DR modulus? */
+  dr = mp_dr_is_modulus(P);
+#else
+  /* default to no */
+  dr = 0;
+#endif
+
+  (void)dr;
+
+#ifdef BN_MP_REDUCE_IS_2K_C
+  /* if not, is it a unrestricted DR modulus? */
+  if (dr == 0) {
+     dr = mp_reduce_is_2k(P) << 1;
+  }
+#endif
+
+  /* if the modulus is odd or dr != 0 use the montgomery method */
+#ifdef BN_MP_EXPTMOD_FAST_C
+  if (mp_isodd (P) == MP_YES || dr !=  0) {
+    return mp_exptmod_fast (G, X, P, Y, dr);
+  } else {
+#endif
+#ifdef BN_S_MP_EXPTMOD_C
+    /* otherwise use the generic Barrett reduction technique */
+    return s_mp_exptmod (G, X, P, Y, 0);
+#else
+    /* no exptmod for evens */
+    return MP_VAL;
+#endif
+#ifdef BN_MP_EXPTMOD_FAST_C
+  }
+#endif
+}
+
+int mp_exptmod_ex (mp_int * G, mp_int * X, int digits, mp_int * P, mp_int * Y)
+{
+    (void)digits;
+    return mp_exptmod(G, X, P, Y);
+}
+
+/* b = |a|
+ *
+ * Simple function copies the input and fixes the sign to positive
+ */
+int mp_abs (mp_int * a, mp_int * b)
+{
+  int     res;
+
+  /* copy a to b */
+  if (a != b) {
+     if ((res = mp_copy (a, b)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  /* force the sign of b to positive */
+  b->sign = MP_ZPOS;
+
+  return MP_OKAY;
+}
+
+
+/* hac 14.61, pp608 */
+#if defined(FREESCALE_LTC_TFM)
+int wolfcrypt_mp_invmod(mp_int * a, mp_int * b, mp_int * c)
+#else
+int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
+#endif
+{
+  /* b cannot be negative or zero, and can not divide by 0 (1/a mod b) */
+  if (b->sign == MP_NEG || mp_iszero(b) == MP_YES || mp_iszero(a) == MP_YES) {
+    return MP_VAL;
+  }
+
+#ifdef BN_FAST_MP_INVMOD_C
+  /* if the modulus is odd we can use a faster routine instead */
+  if ((mp_isodd(b) == MP_YES) && (mp_cmp_d(b, 1) != MP_EQ)) {
+    return fast_mp_invmod (a, b, c);
+  }
+#endif
+
+#ifdef BN_MP_INVMOD_SLOW_C
+  return mp_invmod_slow(a, b, c);
+#else
+  return MP_VAL;
+#endif
+}
+
+
+/* computes the modular inverse via binary extended euclidean algorithm,
+ * that is c = 1/a mod b
+ *
+ * Based on slow invmod except this is optimized for the case where b is
+ * odd as per HAC Note 14.64 on pp. 610
+ */
+int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int  x, y, u, v, B, D;
+  int     res, neg, loop_check = 0;
+
+  /* 2. [modified] b must be odd   */
+  if (mp_iseven (b) == MP_YES) {
+    return MP_VAL;
+  }
+
+  /* init all our temps */
+  if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D)) != MP_OKAY) {
+     return res;
+  }
+
+  /* x == modulus, y == value to invert */
+  if ((res = mp_copy (b, &x)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+
+  /* we need y = |a| */
+  if ((res = mp_mod (a, b, &y)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+
+  /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
+  if ((res = mp_copy (&x, &u)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+  if ((res = mp_copy (&y, &v)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+  if ((res = mp_set (&D, 1)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+
+top:
+  /* 4.  while u is even do */
+  while (mp_iseven (&u) == MP_YES) {
+    /* 4.1 u = u/2 */
+    if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    /* 4.2 if B is odd then */
+    if (mp_isodd (&B) == MP_YES) {
+      if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
+        goto LBL_ERR;
+      }
+    }
+    /* B = B/2 */
+    if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* 5.  while v is even do */
+  while (mp_iseven (&v) == MP_YES) {
+    /* 5.1 v = v/2 */
+    if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    /* 5.2 if D is odd then */
+    if (mp_isodd (&D) == MP_YES) {
+      /* D = (D-x)/2 */
+      if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
+        goto LBL_ERR;
+      }
+    }
+    /* D = D/2 */
+    if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* 6.  if u >= v then */
+  if (mp_cmp (&u, &v) != MP_LT) {
+    /* u = u - v, B = B - D */
+    if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  } else {
+    /* v - v - u, D = D - B */
+    if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* if not zero goto step 4 */
+  if (mp_iszero (&u) == MP_NO) {
+    if (++loop_check > MAX_INVMOD_SZ) {
+        res = MP_VAL;
+        goto LBL_ERR;
+    }
+    goto top;
+  }
+
+  /* now a = C, b = D, gcd == g*v */
+
+  /* if v != 1 then there is no inverse */
+  if (mp_cmp_d (&v, 1) != MP_EQ) {
+    res = MP_VAL;
+    goto LBL_ERR;
+  }
+
+  /* b is now the inverse */
+  neg = a->sign;
+  while (D.sign == MP_NEG) {
+    if ((res = mp_add (&D, b, &D)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+  /* too big */
+  while (mp_cmp_mag(&D, b) != MP_LT) {
+      if ((res = mp_sub(&D, b, &D)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+  }
+  mp_exch (&D, c);
+  c->sign = neg;
+  res = MP_OKAY;
+
+LBL_ERR:mp_clear(&x);
+        mp_clear(&y);
+        mp_clear(&u);
+        mp_clear(&v);
+        mp_clear(&B);
+        mp_clear(&D);
+  return res;
+}
+
+
+/* hac 14.61, pp608 */
+int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int  x, y, u, v, A, B, C, D;
+  int     res;
+
+  /* b cannot be negative */
+  if (b->sign == MP_NEG || mp_iszero(b) == MP_YES) {
+    return MP_VAL;
+  }
+
+  /* init temps */
+  if ((res = mp_init_multi(&x, &y, &u, &v,
+                           &A, &B)) != MP_OKAY) {
+    return res;
+  }
+
+  /* init rest of tmps temps */
+  if ((res = mp_init_multi(&C, &D, 0, 0, 0, 0)) != MP_OKAY) {
+    mp_clear(&x);
+    mp_clear(&y);
+    mp_clear(&u);
+    mp_clear(&v);
+    mp_clear(&A);
+    mp_clear(&B);
+    return res;
+  }
+
+  /* x = a, y = b */
+  if ((res = mp_mod(a, b, &x)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+  if (mp_isone(&x)) {
+    mp_set(c, 1);
+    res = MP_OKAY;
+    goto LBL_ERR;
+  }
+  if ((res = mp_copy (b, &y)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+
+  /* 2. [modified] if x,y are both even then return an error! */
+  if (mp_iseven (&x) == MP_YES && mp_iseven (&y) == MP_YES) {
+    res = MP_VAL;
+    goto LBL_ERR;
+  }
+
+  /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
+  if ((res = mp_copy (&x, &u)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+  if ((res = mp_copy (&y, &v)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+  if ((res = mp_set (&A, 1)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+  if ((res = mp_set (&D, 1)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+
+top:
+  /* 4.  while u is even do */
+  while (mp_iseven (&u) == MP_YES) {
+    /* 4.1 u = u/2 */
+    if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    /* 4.2 if A or B is odd then */
+    if (mp_isodd (&A) == MP_YES || mp_isodd (&B) == MP_YES) {
+      /* A = (A+y)/2, B = (B-x)/2 */
+      if ((res = mp_add (&A, &y, &A)) != MP_OKAY) {
+        goto LBL_ERR;
+      }
+      if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
+        goto LBL_ERR;
+      }
+    }
+    /* A = A/2, B = B/2 */
+    if ((res = mp_div_2 (&A, &A)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* 5.  while v is even do */
+  while (mp_iseven (&v) == MP_YES) {
+    /* 5.1 v = v/2 */
+    if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    /* 5.2 if C or D is odd then */
+    if (mp_isodd (&C) == MP_YES || mp_isodd (&D) == MP_YES) {
+      /* C = (C+y)/2, D = (D-x)/2 */
+      if ((res = mp_add (&C, &y, &C)) != MP_OKAY) {
+        goto LBL_ERR;
+      }
+      if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
+        goto LBL_ERR;
+      }
+    }
+    /* C = C/2, D = D/2 */
+    if ((res = mp_div_2 (&C, &C)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* 6.  if u >= v then */
+  if (mp_cmp (&u, &v) != MP_LT) {
+    /* u = u - v, A = A - C, B = B - D */
+    if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  } else {
+    /* v - v - u, C = C - A, D = D - B */
+    if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* if not zero goto step 4 */
+  if (mp_iszero (&u) == MP_NO)
+    goto top;
+
+  /* now a = C, b = D, gcd == g*v */
+
+  /* if v != 1 then there is no inverse */
+  if (mp_cmp_d (&v, 1) != MP_EQ) {
+    res = MP_VAL;
+    goto LBL_ERR;
+  }
+
+  /* if its too low */
+  while (mp_cmp_d(&C, 0) == MP_LT) {
+      if ((res = mp_add(&C, b, &C)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+  }
+
+  /* too big */
+  while (mp_cmp_mag(&C, b) != MP_LT) {
+      if ((res = mp_sub(&C, b, &C)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+  }
+
+  /* C is now the inverse */
+  mp_exch (&C, c);
+  res = MP_OKAY;
+LBL_ERR:mp_clear(&x);
+        mp_clear(&y);
+        mp_clear(&u);
+        mp_clear(&v);
+        mp_clear(&A);
+        mp_clear(&B);
+        mp_clear(&C);
+        mp_clear(&D);
+  return res;
+}
+
+
+/* compare magnitude of two ints (unsigned) */
+int mp_cmp_mag (mp_int * a, mp_int * b)
+{
+  int     n;
+  mp_digit *tmpa, *tmpb;
+
+  /* compare based on # of non-zero digits */
+  if (a->used > b->used) {
+    return MP_GT;
+  }
+
+  if (a->used < b->used) {
+    return MP_LT;
+  }
+
+  /* alias for a */
+  tmpa = a->dp + (a->used - 1);
+
+  /* alias for b */
+  tmpb = b->dp + (a->used - 1);
+
+  /* compare based on digits  */
+  for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
+    if (*tmpa > *tmpb) {
+      return MP_GT;
+    }
+
+    if (*tmpa < *tmpb) {
+      return MP_LT;
+    }
+  }
+  return MP_EQ;
+}
+
+
+/* compare two ints (signed)*/
+int mp_cmp (mp_int * a, mp_int * b)
+{
+  /* compare based on sign */
+  if (a->sign != b->sign) {
+     if (a->sign == MP_NEG) {
+        return MP_LT;
+     } else {
+        return MP_GT;
+     }
+  }
+
+  /* compare digits */
+  if (a->sign == MP_NEG) {
+     /* if negative compare opposite direction */
+     return mp_cmp_mag(b, a);
+  } else {
+     return mp_cmp_mag(a, b);
+  }
+}
+
+
+/* compare a digit */
+int mp_cmp_d(mp_int * a, mp_digit b)
+{
+  /* special case for zero*/
+  if (a->used == 0 && b == 0)
+    return MP_EQ;
+
+  /* compare based on sign */
+  if ((b && a->used == 0) || a->sign == MP_NEG) {
+    return MP_LT;
+  }
+
+  /* compare based on magnitude */
+  if (a->used > 1) {
+    return MP_GT;
+  }
+
+  /* compare the only digit of a to b */
+  if (a->dp[0] > b) {
+    return MP_GT;
+  } else if (a->dp[0] < b) {
+    return MP_LT;
+  } else {
+    return MP_EQ;
+  }
+}
+
+
+/* set to a digit */
+int mp_set (mp_int * a, mp_digit b)
+{
+  int res;
+  mp_zero (a);
+  res = mp_grow (a, 1);
+  if (res == MP_OKAY) {
+    a->dp[0] = (mp_digit)(b & MP_MASK);
+    a->used  = (a->dp[0] != 0) ? 1 : 0;
+  }
+  return res;
+}
+
+/* check if a bit is set */
+int mp_is_bit_set (mp_int *a, mp_digit b)
+{
+    if ((mp_digit)a->used < b/DIGIT_BIT)
+        return 0;
+
+    return (int)((a->dp[b/DIGIT_BIT] >> b%DIGIT_BIT) & (mp_digit)1);
+}
+
+/* c = a mod b, 0 <= c < b */
+#if defined(FREESCALE_LTC_TFM)
+int wolfcrypt_mp_mod(mp_int * a, mp_int * b, mp_int * c)
+#else
+int mp_mod (mp_int * a, mp_int * b, mp_int * c)
+#endif
+{
+  mp_int  t;
+  int     res;
+
+  if ((res = mp_init_size (&t, b->used)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+
+  if ((mp_iszero(&t) != MP_NO) || (t.sign == b->sign)) {
+    res = MP_OKAY;
+    mp_exch (&t, c);
+  } else {
+    res = mp_add (b, &t, c);
+  }
+
+  mp_clear (&t);
+  return res;
+}
+
+
+/* slower bit-bang division... also smaller */
+int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+   mp_int ta, tb, tq, q;
+   int    res, n, n2;
+
+  /* is divisor zero ? */
+  if (mp_iszero (b) == MP_YES) {
+    return MP_VAL;
+  }
+
+  /* if a < b then q=0, r = a */
+  if (mp_cmp_mag (a, b) == MP_LT) {
+    if (d != NULL) {
+      res = mp_copy (a, d);
+    } else {
+      res = MP_OKAY;
+    }
+    if (c != NULL) {
+      mp_zero (c);
+    }
+    return res;
+  }
+
+  /* init our temps */
+  if ((res = mp_init_multi(&ta, &tb, &tq, &q, 0, 0)) != MP_OKAY) {
+     return res;
+  }
+
+  if ((res = mp_set(&tq, 1)) != MP_OKAY) {
+     return res;
+  }
+  n = mp_count_bits(a) - mp_count_bits(b);
+  if (((res = mp_abs(a, &ta)) != MP_OKAY) ||
+      ((res = mp_abs(b, &tb)) != MP_OKAY) ||
+      ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) ||
+      ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) {
+      goto LBL_ERR;
+  }
+
+  while (n-- >= 0) {
+     if (mp_cmp(&tb, &ta) != MP_GT) {
+        if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) ||
+            ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) {
+           goto LBL_ERR;
+        }
+     }
+     if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) ||
+         ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) {
+           goto LBL_ERR;
+     }
+  }
+
+  /* now q == quotient and ta == remainder */
+  n  = a->sign;
+  n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG);
+  if (c != NULL) {
+     mp_exch(c, &q);
+     c->sign  = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2;
+  }
+  if (d != NULL) {
+     mp_exch(d, &ta);
+     d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n;
+  }
+LBL_ERR:
+   mp_clear(&ta);
+   mp_clear(&tb);
+   mp_clear(&tq);
+   mp_clear(&q);
+   return res;
+}
+
+
+/* b = a/2 */
+int mp_div_2(mp_int * a, mp_int * b)
+{
+  int     x, res, oldused;
+
+  /* copy */
+  if (b->alloc < a->used) {
+    if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  oldused = b->used;
+  b->used = a->used;
+  {
+    mp_digit r, rr, *tmpa, *tmpb;
+
+    /* source alias */
+    tmpa = a->dp + b->used - 1;
+
+    /* dest alias */
+    tmpb = b->dp + b->used - 1;
+
+    /* carry */
+    r = 0;
+    for (x = b->used - 1; x >= 0; x--) {
+      /* get the carry for the next iteration */
+      rr = *tmpa & 1;
+
+      /* shift the current digit, add in carry and store */
+      *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
+
+      /* forward carry to next iteration */
+      r = rr;
+    }
+
+    /* zero excess digits */
+    tmpb = b->dp + b->used;
+    for (x = b->used; x < oldused; x++) {
+      *tmpb++ = 0;
+    }
+  }
+  b->sign = a->sign;
+  mp_clamp (b);
+  return MP_OKAY;
+}
+
+
+/* high level addition (handles signs) */
+int mp_add (mp_int * a, mp_int * b, mp_int * c)
+{
+  int sa, sb, res;
+
+  /* get sign of both inputs */
+  sa = a->sign;
+  sb = b->sign;
+
+  /* handle two cases, not four */
+  if (sa == sb) {
+    /* both positive or both negative */
+    /* add their magnitudes, copy the sign */
+    c->sign = sa;
+    res = s_mp_add (a, b, c);
+  } else {
+    /* one positive, the other negative */
+    /* subtract the one with the greater magnitude from */
+    /* the one of the lesser magnitude.  The result gets */
+    /* the sign of the one with the greater magnitude. */
+    if (mp_cmp_mag (a, b) == MP_LT) {
+      c->sign = sb;
+      res = s_mp_sub (b, a, c);
+    } else {
+      c->sign = sa;
+      res = s_mp_sub (a, b, c);
+    }
+  }
+  return res;
+}
+
+
+/* low level addition, based on HAC pp.594, Algorithm 14.7 */
+int s_mp_add (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int *x;
+  int     olduse, res, min_ab, max_ab;
+
+  /* find sizes, we let |a| <= |b| which means we have to sort
+   * them.  "x" will point to the input with the most digits
+   */
+  if (a->used > b->used) {
+    min_ab = b->used;
+    max_ab = a->used;
+    x = a;
+  } else {
+    min_ab = a->used;
+    max_ab = b->used;
+    x = b;
+  }
+
+  /* init result */
+  if (c->alloc < max_ab + 1) {
+    if ((res = mp_grow (c, max_ab + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* get old used digit count and set new one */
+  olduse = c->used;
+  c->used = max_ab + 1;
+
+  {
+    mp_digit u, *tmpa, *tmpb, *tmpc;
+    int i;
+
+    /* alias for digit pointers */
+
+    /* first input */
+    tmpa = a->dp;
+
+    /* second input */
+    tmpb = b->dp;
+
+    /* destination */
+    tmpc = c->dp;
+
+    /* zero the carry */
+    u = 0;
+    for (i = 0; i < min_ab; i++) {
+      /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */
+      *tmpc = *tmpa++ + *tmpb++ + u;
+
+      /* U = carry bit of T[i] */
+      u = *tmpc >> ((mp_digit)DIGIT_BIT);
+
+      /* take away carry bit from T[i] */
+      *tmpc++ &= MP_MASK;
+    }
+
+    /* now copy higher words if any, that is in A+B
+     * if A or B has more digits add those in
+     */
+    if (min_ab != max_ab) {
+      for (; i < max_ab; i++) {
+        /* T[i] = X[i] + U */
+        *tmpc = x->dp[i] + u;
+
+        /* U = carry bit of T[i] */
+        u = *tmpc >> ((mp_digit)DIGIT_BIT);
+
+        /* take away carry bit from T[i] */
+        *tmpc++ &= MP_MASK;
+      }
+    }
+
+    /* add carry */
+    *tmpc++ = u;
+
+    /* clear digits above olduse */
+    for (i = c->used; i < olduse; i++) {
+      *tmpc++ = 0;
+    }
+  }
+
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+
+/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
+int s_mp_sub (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     olduse, res, min_b, max_a;
+
+  /* find sizes */
+  min_b = b->used;
+  max_a = a->used;
+
+  /* init result */
+  if (c->alloc < max_a) {
+    if ((res = mp_grow (c, max_a)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* sanity check on destination */
+  if (c->dp == NULL)
+     return MP_VAL;
+
+  olduse = c->used;
+  c->used = max_a;
+
+  {
+    mp_digit u, *tmpa, *tmpb, *tmpc;
+    int i;
+
+    /* alias for digit pointers */
+    tmpa = a->dp;
+    tmpb = b->dp;
+    tmpc = c->dp;
+
+    /* set carry to zero */
+    u = 0;
+    for (i = 0; i < min_b; i++) {
+      /* T[i] = A[i] - B[i] - U */
+      *tmpc = *tmpa++ - *tmpb++ - u;
+
+      /* U = carry bit of T[i]
+       * Note this saves performing an AND operation since
+       * if a carry does occur it will propagate all the way to the
+       * MSB.  As a result a single shift is enough to get the carry
+       */
+      u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
+
+      /* Clear carry from T[i] */
+      *tmpc++ &= MP_MASK;
+    }
+
+    /* now copy higher words if any, e.g. if A has more digits than B  */
+    for (; i < max_a; i++) {
+      /* T[i] = A[i] - U */
+      *tmpc = *tmpa++ - u;
+
+      /* U = carry bit of T[i] */
+      u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
+
+      /* Clear carry from T[i] */
+      *tmpc++ &= MP_MASK;
+    }
+
+    /* clear digits above used (since we may not have grown result above) */
+    for (i = c->used; i < olduse; i++) {
+      *tmpc++ = 0;
+    }
+  }
+
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+
+/* high level subtraction (handles signs) */
+int mp_sub (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     sa, sb, res;
+
+  sa = a->sign;
+  sb = b->sign;
+
+  if (sa != sb) {
+    /* subtract a negative from a positive, OR */
+    /* subtract a positive from a negative. */
+    /* In either case, ADD their magnitudes, */
+    /* and use the sign of the first number. */
+    c->sign = sa;
+    res = s_mp_add (a, b, c);
+  } else {
+    /* subtract a positive from a positive, OR */
+    /* subtract a negative from a negative. */
+    /* First, take the difference between their */
+    /* magnitudes, then... */
+    if (mp_cmp_mag (a, b) != MP_LT) {
+      /* Copy the sign from the first */
+      c->sign = sa;
+      /* The first has a larger or equal magnitude */
+      res = s_mp_sub (a, b, c);
+    } else {
+      /* The result has the *opposite* sign from */
+      /* the first number. */
+      c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS;
+      /* The second has a larger magnitude */
+      res = s_mp_sub (b, a, c);
+    }
+  }
+  return res;
+}
+
+
+/* determines if reduce_2k_l can be used */
+int mp_reduce_is_2k_l(mp_int *a)
+{
+   int ix, iy;
+
+   if (a->used == 0) {
+      return MP_NO;
+   } else if (a->used == 1) {
+      return MP_YES;
+   } else if (a->used > 1) {
+      /* if more than half of the digits are -1 we're sold */
+      for (iy = ix = 0; ix < a->used; ix++) {
+          if (a->dp[ix] == MP_MASK) {
+              ++iy;
+          }
+      }
+      return (iy >= (a->used/2)) ? MP_YES : MP_NO;
+
+   }
+   return MP_NO;
+}
+
+
+/* determines if mp_reduce_2k can be used */
+int mp_reduce_is_2k(mp_int *a)
+{
+   int ix, iy, iw;
+   mp_digit iz;
+
+   if (a->used == 0) {
+      return MP_NO;
+   } else if (a->used == 1) {
+      return MP_YES;
+   } else if (a->used > 1) {
+      iy = mp_count_bits(a);
+      iz = 1;
+      iw = 1;
+
+      /* Test every bit from the second digit up, must be 1 */
+      for (ix = DIGIT_BIT; ix < iy; ix++) {
+          if ((a->dp[iw] & iz) == 0) {
+             return MP_NO;
+          }
+          iz <<= 1;
+          if (iz > (mp_digit)MP_MASK) {
+             ++iw;
+             iz = 1;
+          }
+      }
+   }
+   return MP_YES;
+}
+
+
+/* determines if a number is a valid DR modulus */
+int mp_dr_is_modulus(mp_int *a)
+{
+   int ix;
+
+   /* must be at least two digits */
+   if (a->used < 2) {
+      return 0;
+   }
+
+   /* must be of the form b**k - a [a <= b] so all
+    * but the first digit must be equal to -1 (mod b).
+    */
+   for (ix = 1; ix < a->used; ix++) {
+       if (a->dp[ix] != MP_MASK) {
+          return 0;
+       }
+   }
+   return 1;
+}
+
+
+/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85
+ *
+ * Uses a left-to-right k-ary sliding window to compute the modular
+ * exponentiation.
+ * The value of k changes based on the size of the exponent.
+ *
+ * Uses Montgomery or Diminished Radix reduction [whichever appropriate]
+ */
+
+#ifdef MP_LOW_MEM
+   #define TAB_SIZE 32
+#else
+   #define TAB_SIZE 256
+#endif
+
+int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y,
+                     int redmode)
+{
+  mp_int res;
+  mp_digit buf, mp;
+  int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+#ifdef WOLFSSL_SMALL_STACK
+  mp_int* M;
+#else
+  mp_int M[TAB_SIZE];
+#endif
+  /* use a pointer to the reduction algorithm.  This allows us to use
+   * one of many reduction algorithms without modding the guts of
+   * the code with if statements everywhere.
+   */
+  int     (*redux)(mp_int*,mp_int*,mp_digit) = NULL;
+
+#ifdef WOLFSSL_SMALL_STACK
+  M = (mp_int*) XMALLOC(sizeof(mp_int) * TAB_SIZE, NULL,
+                                                       DYNAMIC_TYPE_BIGINT);
+  if (M == NULL)
+    return MP_MEM;
+#endif
+
+  /* find window size */
+  x = mp_count_bits (X);
+  if (x <= 7) {
+    winsize = 2;
+  } else if (x <= 36) {
+    winsize = 3;
+  } else if (x <= 140) {
+    winsize = 4;
+  } else if (x <= 450) {
+    winsize = 5;
+  } else if (x <= 1303) {
+    winsize = 6;
+  } else if (x <= 3529) {
+    winsize = 7;
+  } else {
+    winsize = 8;
+  }
+
+#ifdef MP_LOW_MEM
+  if (winsize > 5) {
+     winsize = 5;
+  }
+#endif
+
+  /* init M array */
+  /* init first cell */
+  if ((err = mp_init_size(&M[1], P->alloc)) != MP_OKAY) {
+#ifdef WOLFSSL_SMALL_STACK
+     XFREE(M, NULL, DYNAMIC_TYPE_BIGINT);
+#endif
+
+     return err;
+  }
+
+  /* now init the second half of the array */
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    if ((err = mp_init_size(&M[x], P->alloc)) != MP_OKAY) {
+      for (y = 1<<(winsize-1); y < x; y++) {
+        mp_clear (&M[y]);
+      }
+      mp_clear(&M[1]);
+
+#ifdef WOLFSSL_SMALL_STACK
+      XFREE(M, NULL, DYNAMIC_TYPE_BIGINT);
+#endif
+
+      return err;
+    }
+  }
+
+  /* determine and setup reduction code */
+  if (redmode == 0) {
+#ifdef BN_MP_MONTGOMERY_SETUP_C
+     /* now setup montgomery  */
+     if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) {
+        goto LBL_M;
+     }
+#else
+     err = MP_VAL;
+     goto LBL_M;
+#endif
+
+     /* automatically pick the comba one if available (saves quite a few
+        calls/ifs) */
+#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
+     if (((P->used * 2 + 1) < (int)MP_WARRAY) &&
+          P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+        redux = fast_mp_montgomery_reduce;
+     } else
+#endif
+     {
+#ifdef BN_MP_MONTGOMERY_REDUCE_C
+        /* use slower baseline Montgomery method */
+        redux = mp_montgomery_reduce;
+#endif
+     }
+  } else if (redmode == 1) {
+#if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C)
+     /* setup DR reduction for moduli of the form B**k - b */
+     mp_dr_setup(P, &mp);
+     redux = mp_dr_reduce;
+#endif
+  } else {
+#if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C)
+     /* setup DR reduction for moduli of the form 2**k - b */
+     if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) {
+        goto LBL_M;
+     }
+     redux = mp_reduce_2k;
+#endif
+  }
+
+  if (redux == NULL) {
+     err = MP_VAL;
+     goto LBL_M;
+  }
+
+  /* setup result */
+  if ((err = mp_init_size (&res, P->alloc)) != MP_OKAY) {
+    goto LBL_M;
+  }
+
+  /* create M table
+   *
+
+   *
+   * The first half of the table is not computed though accept for M[0] and M[1]
+   */
+
+  if (redmode == 0) {
+#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+     /* now we need R mod m */
+     if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) {
+       goto LBL_RES;
+     }
+
+     /* now set M[1] to G * R mod m */
+     if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) {
+       goto LBL_RES;
+     }
+#else
+     err = MP_VAL;
+     goto LBL_RES;
+#endif
+  } else {
+     if ((err = mp_set(&res, 1)) != MP_OKAY) {
+        goto LBL_RES;
+     }
+     if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) {
+        goto LBL_RES;
+     }
+  }
+
+  /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times*/
+  if ((err = mp_copy (&M[1], &M[(mp_digit)(1 << (winsize - 1))])) != MP_OKAY) {
+    goto LBL_RES;
+  }
+
+  for (x = 0; x < (winsize - 1); x++) {
+    if ((err = mp_sqr (&M[(mp_digit)(1 << (winsize - 1))],
+                       &M[(mp_digit)(1 << (winsize - 1))])) != MP_OKAY) {
+      goto LBL_RES;
+    }
+    if ((err = redux (&M[(mp_digit)(1 << (winsize - 1))], P, mp)) != MP_OKAY) {
+      goto LBL_RES;
+    }
+  }
+
+  /* create upper table */
+  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+    if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
+      goto LBL_RES;
+    }
+    if ((err = redux (&M[x], P, mp)) != MP_OKAY) {
+      goto LBL_RES;
+    }
+  }
+
+  /* set initial mode and bit cnt */
+  mode   = 0;
+  bitcnt = 1;
+  buf    = 0;
+  digidx = X->used - 1;
+  bitcpy = 0;
+  bitbuf = 0;
+
+  for (;;) {
+    /* grab next digit as required */
+    if (--bitcnt == 0) {
+      /* if digidx == -1 we are out of digits so break */
+      if (digidx == -1) {
+        break;
+      }
+      /* read next digit and reset bitcnt */
+      buf    = X->dp[digidx--];
+      bitcnt = (int)DIGIT_BIT;
+    }
+
+    /* grab the next msb from the exponent */
+    y     = (int)(buf >> (DIGIT_BIT - 1)) & 1;
+    buf <<= (mp_digit)1;
+
+    /* if the bit is zero and mode == 0 then we ignore it
+     * These represent the leading zero bits before the first 1 bit
+     * in the exponent.  Technically this opt is not required but it
+     * does lower the # of trivial squaring/reductions used
+     */
+    if (mode == 0 && y == 0) {
+      continue;
+    }
+
+    /* if the bit is zero and mode == 1 then we square */
+    if (mode == 1 && y == 0) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, mp)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      continue;
+    }
+
+    /* else we add it to the window */
+    bitbuf |= (y << (winsize - ++bitcpy));
+    mode    = 2;
+
+    if (bitcpy == winsize) {
+      /* ok window is filled so square as required and multiply  */
+      /* square first */
+      for (x = 0; x < winsize; x++) {
+        if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, mp)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+
+      /* then multiply */
+      if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, mp)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      /* empty window and reset */
+      bitcpy = 0;
+      bitbuf = 0;
+      mode   = 1;
+    }
+  }
+
+  /* if bits remain then square/multiply */
+  if (mode == 2 && bitcpy > 0) {
+    /* square then multiply if the bit is set */
+    for (x = 0; x < bitcpy; x++) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, mp)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      /* get next bit of the window */
+      bitbuf <<= 1;
+      if ((bitbuf & (1 << winsize)) != 0) {
+        /* then multiply */
+        if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, mp)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+    }
+  }
+
+  if (redmode == 0) {
+     /* fixup result if Montgomery reduction is used
+      * recall that any value in a Montgomery system is
+      * actually multiplied by R mod n.  So we have
+      * to reduce one more time to cancel out the factor
+      * of R.
+      */
+     if ((err = redux(&res, P, mp)) != MP_OKAY) {
+       goto LBL_RES;
+     }
+  }
+
+  /* swap res with Y */
+  mp_exch (&res, Y);
+  err = MP_OKAY;
+LBL_RES:mp_clear (&res);
+LBL_M:
+  mp_clear(&M[1]);
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    mp_clear (&M[x]);
+  }
+
+#ifdef WOLFSSL_SMALL_STACK
+  XFREE(M, NULL, DYNAMIC_TYPE_BIGINT);
+#endif
+
+  return err;
+}
+
+#ifdef BN_MP_EXPTMOD_BASE_2
+#if DIGIT_BIT < 16
+    #define WINSIZE    3
+#elif DIGIT_BIT < 32
+    #define WINSIZE    4
+#elif DIGIT_BIT < 64
+    #define WINSIZE    5
+#elif DIGIT_BIT < 128
+    #define WINSIZE    6
+#endif
+int mp_exptmod_base_2(mp_int * X, mp_int * P, mp_int * Y)
+{
+  mp_digit buf, mp;
+  int      err = MP_OKAY, bitbuf, bitcpy, bitcnt, digidx, x, y;
+#ifdef WOLFSSL_SMALL_STACK
+  mp_int  *res = NULL;
+#else
+  mp_int   res[1];
+#endif
+  int     (*redux)(mp_int*,mp_int*,mp_digit) = NULL;
+
+  /* automatically pick the comba one if available (saves quite a few
+     calls/ifs) */
+#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
+  if (((P->used * 2 + 1) < (int)MP_WARRAY) &&
+       P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+     redux = fast_mp_montgomery_reduce;
+  } else
+#endif
+  {
+#ifdef BN_MP_MONTGOMERY_REDUCE_C
+     /* use slower baseline Montgomery method */
+     redux = mp_montgomery_reduce;
+#else
+     return MP_VAL;
+#endif
+  }
+
+#ifdef WOLFSSL_SMALL_STACK
+  res = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+  if (res == NULL) {
+     return MP_MEM;
+  }
+#endif
+
+  /* now setup montgomery  */
+  if ((err = mp_montgomery_setup(P, &mp)) != MP_OKAY) {
+     goto LBL_M;
+  }
+
+  /* setup result */
+  if ((err = mp_init(res)) != MP_OKAY) {
+     goto LBL_M;
+  }
+
+  /* now we need R mod m */
+  if ((err = mp_montgomery_calc_normalization(res, P)) != MP_OKAY) {
+     goto LBL_RES;
+  }
+
+  /* Get the top bits left over after taking WINSIZE bits starting at the
+   * least-significant.
+   */
+  digidx = X->used - 1;
+  bitcpy = (X->used * DIGIT_BIT) % WINSIZE;
+  if (bitcpy > 0) {
+     bitcnt = (int)DIGIT_BIT - bitcpy;
+     buf    = X->dp[digidx--];
+     bitbuf = (int)(buf >> bitcnt);
+     /* Multiply montgomery representation of 1 by 2 ^ top */
+     err = mp_mul_2d(res, bitbuf, res);
+     if (err != MP_OKAY) {
+        goto LBL_RES;
+     }
+     err = mp_mod(res, P, res);
+     if (err != MP_OKAY) {
+        goto LBL_RES;
+     }
+     /* Move out bits used */
+     buf  <<= bitcpy;
+     bitcnt++;
+  }
+  else {
+     bitcnt = 1;
+     buf    = 0;
+  }
+
+  /* empty window and reset  */
+  bitbuf = 0;
+  bitcpy = 0;
+
+  for (;;) {
+    /* grab next digit as required */
+    if (--bitcnt == 0) {
+      /* if digidx == -1 we are out of digits so break */
+      if (digidx == -1) {
+        break;
+      }
+      /* read next digit and reset bitcnt */
+      buf    = X->dp[digidx--];
+      bitcnt = (int)DIGIT_BIT;
+    }
+
+    /* grab the next msb from the exponent */
+    y       = (int)(buf >> (DIGIT_BIT - 1)) & 1;
+    buf   <<= (mp_digit)1;
+    /* add bit to the window */
+    bitbuf |= (y << (WINSIZE - ++bitcpy));
+
+    if (bitcpy == WINSIZE) {
+      /* ok window is filled so square as required and multiply  */
+      /* square first */
+      for (x = 0; x < WINSIZE; x++) {
+        err = mp_sqr(res, res);
+        if (err != MP_OKAY) {
+          goto LBL_RES;
+        }
+        err = (*redux)(res, P, mp);
+        if (err != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+
+      /* then multiply by 2^bitbuf */
+      err = mp_mul_2d(res, bitbuf, res);
+      if (err != MP_OKAY) {
+         goto LBL_RES;
+      }
+      err = mp_mod(res, P, res);
+      if (err != MP_OKAY) {
+         goto LBL_RES;
+      }
+
+      /* empty window and reset */
+      bitcpy = 0;
+      bitbuf = 0;
+    }
+  }
+
+  /* fixup result if Montgomery reduction is used
+   * recall that any value in a Montgomery system is
+   * actually multiplied by R mod n.  So we have
+   * to reduce one more time to cancel out the factor
+   * of R.
+   */
+  err = (*redux)(res, P, mp);
+  if (err != MP_OKAY) {
+     goto LBL_RES;
+  }
+
+  /* swap res with Y */
+  mp_copy(res, Y);
+
+LBL_RES:mp_clear (res);
+LBL_M:
+#ifdef WOLFSSL_SMALL_STACK
+  XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+  return err;
+}
+
+#undef WINSIZE
+#endif /* BN_MP_EXPTMOD_BASE_2 */
+
+
+/* setups the montgomery reduction stuff */
+int mp_montgomery_setup (mp_int * n, mp_digit * rho)
+{
+  mp_digit x, b;
+
+/* fast inversion mod 2**k
+ *
+ * Based on the fact that
+ *
+ * XA = 1 (mod 2**n)  =>  (X(2-XA)) A = 1 (mod 2**2n)
+ *                    =>  2*X*A - X*X*A*A = 1
+ *                    =>  2*(1) - (1)     = 1
+ */
+  b = n->dp[0];
+
+  if ((b & 1) == 0) {
+    return MP_VAL;
+  }
+
+  x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
+  x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
+#if !defined(MP_8BIT)
+  x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
+#endif
+#if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT))
+  x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
+#endif
+#ifdef MP_64BIT
+  x *= 2 - b * x;               /* here x*a==1 mod 2**64 */
+#endif
+
+  /* rho = -1/m mod b */
+  /* TAO, switched mp_word casts to mp_digit to shut up compiler */
+  *rho = (mp_digit)((((mp_digit)1 << ((mp_digit) DIGIT_BIT)) - x) & MP_MASK);
+
+  return MP_OKAY;
+}
+
+
+/* computes xR**-1 == x (mod N) via Montgomery Reduction
+ *
+ * This is an optimized implementation of montgomery_reduce
+ * which uses the comba method to quickly calculate the columns of the
+ * reduction.
+ *
+ * Based on Algorithm 14.32 on pp.601 of HAC.
+*/
+int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
+{
+  int     ix, res, olduse;
+#ifdef WOLFSSL_SMALL_STACK
+  mp_word* W;    /* uses dynamic memory and slower */
+#else
+  mp_word W[MP_WARRAY];
+#endif
+
+  /* get old used count */
+  olduse = x->used;
+
+  /* grow a as required */
+  if (x->alloc < n->used + 1) {
+    if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+#ifdef WOLFSSL_SMALL_STACK
+  W = (mp_word*)XMALLOC(sizeof(mp_word) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT);
+  if (W == NULL)
+    return MP_MEM;
+#endif
+
+  /* first we have to get the digits of the input into
+   * an array of double precision words W[...]
+   */
+  {
+    mp_word *_W;
+    mp_digit *tmpx;
+
+    /* alias for the W[] array */
+    _W   = W;
+
+    /* alias for the digits of  x*/
+    tmpx = x->dp;
+
+    /* copy the digits of a into W[0..a->used-1] */
+    for (ix = 0; ix < x->used; ix++) {
+      *_W++ = *tmpx++;
+    }
+
+    /* zero the high words of W[a->used..m->used*2] */
+    for (; ix < n->used * 2 + 1; ix++) {
+      *_W++ = 0;
+    }
+  }
+
+  /* now we proceed to zero successive digits
+   * from the least significant upwards
+   */
+  for (ix = 0; ix < n->used; ix++) {
+    /* mu = ai * m' mod b
+     *
+     * We avoid a double precision multiplication (which isn't required)
+     * by casting the value down to a mp_digit.  Note this requires
+     * that W[ix-1] have  the carry cleared (see after the inner loop)
+     */
+    mp_digit mu;
+    mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK);
+
+    /* a = a + mu * m * b**i
+     *
+     * This is computed in place and on the fly.  The multiplication
+     * by b**i is handled by offsetting which columns the results
+     * are added to.
+     *
+     * Note the comba method normally doesn't handle carries in the
+     * inner loop In this case we fix the carry from the previous
+     * column since the Montgomery reduction requires digits of the
+     * result (so far) [see above] to work.  This is
+     * handled by fixing up one carry after the inner loop.  The
+     * carry fixups are done in order so after these loops the
+     * first m->used words of W[] have the carries fixed
+     */
+    {
+      int iy;
+      mp_digit *tmpn;
+      mp_word *_W;
+
+      /* alias for the digits of the modulus */
+      tmpn = n->dp;
+
+      /* Alias for the columns set by an offset of ix */
+      _W = W + ix;
+
+      /* inner loop */
+      for (iy = 0; iy < n->used; iy++) {
+          *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++);
+      }
+    }
+
+    /* now fix carry for next digit, W[ix+1] */
+    W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT);
+  }
+
+  /* now we have to propagate the carries and
+   * shift the words downward [all those least
+   * significant digits we zeroed].
+   */
+  {
+    mp_digit *tmpx;
+    mp_word *_W, *_W1;
+
+    /* nox fix rest of carries */
+
+    /* alias for current word */
+    _W1 = W + ix;
+
+    /* alias for next word, where the carry goes */
+    _W = W + ++ix;
+
+    for (; ix <= n->used * 2 + 1; ix++) {
+      *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT);
+    }
+
+    /* copy out, A = A/b**n
+     *
+     * The result is A/b**n but instead of converting from an
+     * array of mp_word to mp_digit than calling mp_rshd
+     * we just copy them in the right order
+     */
+
+    /* alias for destination word */
+    tmpx = x->dp;
+
+    /* alias for shifted double precision result */
+    _W = W + n->used;
+
+    for (ix = 0; ix < n->used + 1; ix++) {
+      *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK));
+    }
+
+    /* zero olduse digits, if the input a was larger than
+     * m->used+1 we'll have to clear the digits
+     */
+    for (; ix < olduse; ix++) {
+      *tmpx++ = 0;
+    }
+  }
+
+  /* set the max used and clamp */
+  x->used = n->used + 1;
+  mp_clamp (x);
+
+#ifdef WOLFSSL_SMALL_STACK
+  XFREE(W, NULL, DYNAMIC_TYPE_BIGINT);
+#endif
+
+  /* if A >= m then A = A - m */
+  if (mp_cmp_mag (x, n) != MP_LT) {
+    return s_mp_sub (x, n, x);
+  }
+  return MP_OKAY;
+}
+
+
+/* computes xR**-1 == x (mod N) via Montgomery Reduction */
+int mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
+{
+  int     ix, res, digs;
+  mp_digit mu;
+
+  /* can the fast reduction [comba] method be used?
+   *
+   * Note that unlike in mul you're safely allowed *less*
+   * than the available columns [255 per default] since carries
+   * are fixed up in the inner loop.
+   */
+  digs = n->used * 2 + 1;
+  if ((digs < (int)MP_WARRAY) &&
+      n->used <
+      (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+    return fast_mp_montgomery_reduce (x, n, rho);
+  }
+
+  /* grow the input as required */
+  if (x->alloc < digs) {
+    if ((res = mp_grow (x, digs)) != MP_OKAY) {
+      return res;
+    }
+  }
+  x->used = digs;
+
+  for (ix = 0; ix < n->used; ix++) {
+    /* mu = ai * rho mod b
+     *
+     * The value of rho must be precalculated via
+     * montgomery_setup() such that
+     * it equals -1/n0 mod b this allows the
+     * following inner loop to reduce the
+     * input one digit at a time
+     */
+    mu = (mp_digit) (((mp_word)x->dp[ix]) * ((mp_word)rho) & MP_MASK);
+
+    /* a = a + mu * m * b**i */
+    {
+      int iy;
+      mp_digit *tmpn, *tmpx, u;
+      mp_word r;
+
+      /* alias for digits of the modulus */
+      tmpn = n->dp;
+
+      /* alias for the digits of x [the input] */
+      tmpx = x->dp + ix;
+
+      /* set the carry to zero */
+      u = 0;
+
+      /* Multiply and add in place */
+      for (iy = 0; iy < n->used; iy++) {
+        /* compute product and sum */
+        r       = ((mp_word)mu) * ((mp_word)*tmpn++) +
+                  ((mp_word) u) + ((mp_word) * tmpx);
+
+        /* get carry */
+        u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+
+        /* fix digit */
+        *tmpx++ = (mp_digit)(r & ((mp_word) MP_MASK));
+      }
+      /* At this point the ix'th digit of x should be zero */
+
+
+      /* propagate carries upwards as required*/
+      while (u) {
+        *tmpx   += u;
+        u        = *tmpx >> DIGIT_BIT;
+        *tmpx++ &= MP_MASK;
+      }
+    }
+  }
+
+  /* at this point the n.used'th least
+   * significant digits of x are all zero
+   * which means we can shift x to the
+   * right by n.used digits and the
+   * residue is unchanged.
+   */
+
+  /* x = x/b**n.used */
+  mp_clamp(x);
+  mp_rshd (x, n->used);
+
+  /* if x >= n then x = x - n */
+  if (mp_cmp_mag (x, n) != MP_LT) {
+    return s_mp_sub (x, n, x);
+  }
+
+  return MP_OKAY;
+}
+
+
+/* determines the setup value */
+void mp_dr_setup(mp_int *a, mp_digit *d)
+{
+   /* the casts are required if DIGIT_BIT is one less than
+    * the number of bits in a mp_digit [e.g. DIGIT_BIT==31]
+    */
+   *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) -
+        ((mp_word)a->dp[0]));
+}
+
+
+/* reduce "x" in place modulo "n" using the Diminished Radix algorithm.
+ *
+ * Based on algorithm from the paper
+ *
+ * "Generating Efficient Primes for Discrete Log Cryptosystems"
+ *                 Chae Hoon Lim, Pil Joong Lee,
+ *          POSTECH Information Research Laboratories
+ *
+ * The modulus must be of a special format [see manual]
+ *
+ * Has been modified to use algorithm 7.10 from the LTM book instead
+ *
+ * Input x must be in the range 0 <= x <= (n-1)**2
+ */
+int mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k)
+{
+  int      err, i, m;
+  mp_word  r;
+  mp_digit mu, *tmpx1, *tmpx2;
+
+  /* m = digits in modulus */
+  m = n->used;
+
+  /* ensure that "x" has at least 2m digits */
+  if (x->alloc < m + m) {
+    if ((err = mp_grow (x, m + m)) != MP_OKAY) {
+      return err;
+    }
+  }
+
+/* top of loop, this is where the code resumes if
+ * another reduction pass is required.
+ */
+top:
+  /* aliases for digits */
+  /* alias for lower half of x */
+  tmpx1 = x->dp;
+
+  /* alias for upper half of x, or x/B**m */
+  tmpx2 = x->dp + m;
+
+  /* set carry to zero */
+  mu = 0;
+
+  /* compute (x mod B**m) + k * [x/B**m] inline and inplace */
+  for (i = 0; i < m; i++) {
+      r         = ((mp_word)*tmpx2++) * ((mp_word)k) + *tmpx1 + mu;
+      *tmpx1++  = (mp_digit)(r & MP_MASK);
+      mu        = (mp_digit)(r >> ((mp_word)DIGIT_BIT));
+  }
+
+  /* set final carry */
+  *tmpx1++ = mu;
+
+  /* zero words above m */
+  for (i = m + 1; i < x->used; i++) {
+      *tmpx1++ = 0;
+  }
+
+  /* clamp, sub and return */
+  mp_clamp (x);
+
+  /* if x >= n then subtract and reduce again
+   * Each successive "recursion" makes the input smaller and smaller.
+   */
+  if (mp_cmp_mag (x, n) != MP_LT) {
+    if ((err = s_mp_sub(x, n, x)) != MP_OKAY) {
+        return err;
+    }
+    goto top;
+  }
+  return MP_OKAY;
+}
+
+
+/* reduces a modulo n where n is of the form 2**p - d */
+int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d)
+{
+   mp_int q;
+   int    p, res;
+
+   if ((res = mp_init(&q)) != MP_OKAY) {
+      return res;
+   }
+
+   p = mp_count_bits(n);
+top:
+   /* q = a/2**p, a = a mod 2**p */
+   if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
+      goto ERR;
+   }
+
+   if (d != 1) {
+      /* q = q * d */
+      if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) {
+         goto ERR;
+      }
+   }
+
+   /* a = a + q */
+   if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
+      goto ERR;
+   }
+
+   if (mp_cmp_mag(a, n) != MP_LT) {
+      if ((res = s_mp_sub(a, n, a)) != MP_OKAY) {
+         goto ERR;
+      }
+      goto top;
+   }
+
+ERR:
+   mp_clear(&q);
+   return res;
+}
+
+
+/* determines the setup value */
+int mp_reduce_2k_setup(mp_int *a, mp_digit *d)
+{
+   int res, p;
+   mp_int tmp;
+
+   if ((res = mp_init(&tmp)) != MP_OKAY) {
+      return res;
+   }
+
+   p = mp_count_bits(a);
+   if ((res = mp_2expt(&tmp, p)) != MP_OKAY) {
+      mp_clear(&tmp);
+      return res;
+   }
+
+   if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) {
+      mp_clear(&tmp);
+      return res;
+   }
+
+   *d = tmp.dp[0];
+   mp_clear(&tmp);
+   return MP_OKAY;
+}
+
+
+/* set the b bit of a */
+int mp_set_bit (mp_int * a, int b)
+{
+    int i = b / DIGIT_BIT, res;
+
+    /*
+     * Require:
+     *  bit index b >= 0
+     *  a->alloc == a->used == 0 if a->dp == NULL
+     */
+    if (b < 0 || (a->dp == NULL && (a->alloc != 0 || a->used != 0)))
+        return MP_VAL;
+
+    if (a->dp == NULL || a->used < (int)(i + 1)) {
+        /* grow a to accommodate the single bit */
+        if ((res = mp_grow (a, i + 1)) != MP_OKAY) {
+            return res;
+        }
+
+        /* set the used count of where the bit will go */
+        a->used = (int)(i + 1);
+    }
+
+    /* put the single bit in its place */
+    a->dp[i] |= ((mp_digit)1) << (b % DIGIT_BIT);
+
+    return MP_OKAY;
+}
+
+/* computes a = 2**b
+ *
+ * Simple algorithm which zeros the int, set the required bit
+ */
+int mp_2expt (mp_int * a, int b)
+{
+    /* zero a as per default */
+    mp_zero (a);
+
+    return mp_set_bit(a, b);
+}
+
+/* multiply by a digit */
+int mp_mul_d (mp_int * a, mp_digit b, mp_int * c)
+{
+  mp_digit u, *tmpa, *tmpc;
+  mp_word  r;
+  int      ix, res, olduse;
+
+  /* make sure c is big enough to hold a*b */
+  if (c->alloc < a->used + 1) {
+    if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* get the original destinations used count */
+  olduse = c->used;
+
+  /* set the sign */
+  c->sign = a->sign;
+
+  /* alias for a->dp [source] */
+  tmpa = a->dp;
+
+  /* alias for c->dp [dest] */
+  tmpc = c->dp;
+
+  /* zero carry */
+  u = 0;
+
+  /* compute columns */
+  for (ix = 0; ix < a->used; ix++) {
+    /* compute product and carry sum for this term */
+    r       = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b);
+
+    /* mask off higher bits to get a single digit */
+    *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+    /* send carry into next iteration */
+    u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+  }
+
+  /* store final carry [if any] and increment ix offset  */
+  *tmpc++ = u;
+  ++ix;
+
+  /* now zero digits above the top */
+  while (ix++ < olduse) {
+     *tmpc++ = 0;
+  }
+
+  /* set used count */
+  c->used = a->used + 1;
+  mp_clamp(c);
+
+  return MP_OKAY;
+}
+
+
+/* d = a * b (mod c) */
+#if defined(FREESCALE_LTC_TFM)
+int wolfcrypt_mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d)
+#else
+int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+#endif
+{
+  int     res;
+  mp_int  t;
+
+  if ((res = mp_init_size (&t, c->used)) != MP_OKAY) {
+    return res;
+  }
+
+  res = mp_mul (a, b, &t);
+  if (res == MP_OKAY) {
+      res = mp_mod (&t, c, d);
+  }
+
+  mp_clear (&t);
+  return res;
+}
+
+
+/* d = a - b (mod c) */
+int mp_submod(mp_int* a, mp_int* b, mp_int* c, mp_int* d)
+{
+  int     res;
+  mp_int  t;
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  res = mp_sub (a, b, &t);
+  if (res == MP_OKAY) {
+      res = mp_mod (&t, c, d);
+  }
+
+  mp_clear (&t);
+
+  return res;
+}
+
+/* d = a + b (mod c) */
+int mp_addmod(mp_int* a, mp_int* b, mp_int* c, mp_int* d)
+{
+   int     res;
+   mp_int  t;
+
+   if ((res = mp_init (&t)) != MP_OKAY) {
+     return res;
+   }
+
+   res = mp_add (a, b, &t);
+   if (res == MP_OKAY) {
+       res = mp_mod (&t, c, d);
+   }
+
+   mp_clear (&t);
+
+   return res;
+}
+
+/* computes b = a*a */
+int mp_sqr (mp_int * a, mp_int * b)
+{
+  int     res;
+
+  {
+#ifdef BN_FAST_S_MP_SQR_C
+    /* can we use the fast comba multiplier? */
+    if ((a->used * 2 + 1) < (int)MP_WARRAY &&
+         a->used <
+         (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) {
+      res = fast_s_mp_sqr (a, b);
+    } else
+#endif
+#ifdef BN_S_MP_SQR_C
+      res = s_mp_sqr (a, b);
+#else
+      res = MP_VAL;
+#endif
+  }
+  b->sign = MP_ZPOS;
+  return res;
+}
+
+
+/* high level multiplication (handles sign) */
+#if defined(FREESCALE_LTC_TFM)
+int wolfcrypt_mp_mul(mp_int *a, mp_int *b, mp_int *c)
+#else
+int mp_mul (mp_int * a, mp_int * b, mp_int * c)
+#endif
+{
+  int     res, neg;
+  neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
+
+  {
+#ifdef BN_FAST_S_MP_MUL_DIGS_C
+    /* can we use the fast multiplier?
+     *
+     * The fast multiplier can be used if the output will
+     * have less than MP_WARRAY digits and the number of
+     * digits won't affect carry propagation
+     */
+    int     digs = a->used + b->used + 1;
+
+    if ((digs < (int)MP_WARRAY) &&
+        MIN(a->used, b->used) <=
+        (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+      res = fast_s_mp_mul_digs (a, b, c, digs);
+    } else
+#endif
+#ifdef BN_S_MP_MUL_DIGS_C
+      res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */
+#else
+      res = MP_VAL;
+#endif
+
+  }
+  c->sign = (c->used > 0) ? neg : MP_ZPOS;
+  return res;
+}
+
+
+/* b = a*2 */
+int mp_mul_2(mp_int * a, mp_int * b)
+{
+  int     x, res, oldused;
+
+  /* grow to accommodate result */
+  if (b->alloc < a->used + 1) {
+    if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  oldused = b->used;
+  b->used = a->used;
+
+  {
+    mp_digit r, rr, *tmpa, *tmpb;
+
+    /* alias for source */
+    tmpa = a->dp;
+
+    /* alias for dest */
+    tmpb = b->dp;
+
+    /* carry */
+    r = 0;
+    for (x = 0; x < a->used; x++) {
+
+      /* get what will be the *next* carry bit from the
+       * MSB of the current digit
+       */
+      rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1));
+
+      /* now shift up this digit, add in the carry [from the previous] */
+      *tmpb++ = (mp_digit)(((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK);
+
+      /* copy the carry that would be from the source
+       * digit into the next iteration
+       */
+      r = rr;
+    }
+
+    /* new leading digit? */
+    if (r != 0) {
+      /* add a MSB which is always 1 at this point */
+      *tmpb = 1;
+      ++(b->used);
+    }
+
+    /* now zero any excess digits on the destination
+     * that we didn't write to
+     */
+    tmpb = b->dp + b->used;
+    for (x = b->used; x < oldused; x++) {
+      *tmpb++ = 0;
+    }
+  }
+  b->sign = a->sign;
+  return MP_OKAY;
+}
+
+
+/* divide by three (based on routine from MPI and the GMP manual) */
+int mp_div_3 (mp_int * a, mp_int *c, mp_digit * d)
+{
+  mp_int   q;
+  mp_word  w, t;
+  mp_digit b;
+  int      res, ix;
+
+  /* b = 2**DIGIT_BIT / 3 */
+  b = (mp_digit) ( (((mp_word)1) << ((mp_word)DIGIT_BIT)) / ((mp_word)3) );
+
+  if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
+     return res;
+  }
+
+  q.used = a->used;
+  q.sign = a->sign;
+  w = 0;
+  for (ix = a->used - 1; ix >= 0; ix--) {
+     w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
+
+     if (w >= 3) {
+        /* multiply w by [1/3] */
+        t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT);
+
+        /* now subtract 3 * [w/3] from w, to get the remainder */
+        w -= t+t+t;
+
+        /* fixup the remainder as required since
+         * the optimization is not exact.
+         */
+        while (w >= 3) {
+           t += 1;
+           w -= 3;
+        }
+      } else {
+        t = 0;
+      }
+      q.dp[ix] = (mp_digit)t;
+  }
+
+  /* [optional] store the remainder */
+  if (d != NULL) {
+     *d = (mp_digit)w;
+  }
+
+  /* [optional] store the quotient */
+  if (c != NULL) {
+     mp_clamp(&q);
+     mp_exch(&q, c);
+  }
+  mp_clear(&q);
+
+  return res;
+}
+
+
+/* init an mp_init for a given size */
+int mp_init_size (mp_int * a, int size)
+{
+  int x;
+
+  /* pad size so there are always extra digits */
+  size += (MP_PREC * 2) - (size % MP_PREC);
+
+  /* alloc mem */
+  a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size, NULL,
+                                      DYNAMIC_TYPE_BIGINT);
+  if (a->dp == NULL) {
+    return MP_MEM;
+  }
+
+  /* set the members */
+  a->used  = 0;
+  a->alloc = size;
+  a->sign  = MP_ZPOS;
+#ifdef HAVE_WOLF_BIGINT
+  wc_bigint_init(&a->raw);
+#endif
+
+  /* zero the digits */
+  for (x = 0; x < size; x++) {
+      a->dp[x] = 0;
+  }
+
+  return MP_OKAY;
+}
+
+
+/* the jist of squaring...
+ * you do like mult except the offset of the tmpx [one that
+ * starts closer to zero] can't equal the offset of tmpy.
+ * So basically you set up iy like before then you min it with
+ * (ty-tx) so that it never happens.  You double all those
+ * you add in the inner loop
+
+After that loop you do the squares and add them in.
+*/
+
+int fast_s_mp_sqr (mp_int * a, mp_int * b)
+{
+  int       olduse, res, pa, ix, iz;
+#ifdef WOLFSSL_SMALL_STACK
+  mp_digit* W;    /* uses dynamic memory and slower */
+#else
+  mp_digit W[MP_WARRAY];
+#endif
+  mp_digit  *tmpx;
+  mp_word   W1;
+
+  /* grow the destination as required */
+  pa = a->used + a->used;
+  if (b->alloc < pa) {
+    if ((res = mp_grow (b, pa)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  if (pa > (int)MP_WARRAY)
+    return MP_RANGE;  /* TAO range check */
+
+#ifdef WOLFSSL_SMALL_STACK
+  W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT);
+  if (W == NULL)
+    return MP_MEM;
+#endif
+
+  /* number of output digits to produce */
+  W1 = 0;
+  for (ix = 0; ix < pa; ix++) {
+      int      tx, ty, iy;
+      mp_word  _W;
+      mp_digit *tmpy;
+
+      /* clear counter */
+      _W = 0;
+
+      /* get offsets into the two bignums */
+      ty = MIN(a->used-1, ix);
+      tx = ix - ty;
+
+      /* setup temp aliases */
+      tmpx = a->dp + tx;
+      tmpy = a->dp + ty;
+
+      /* this is the number of times the loop will iterate, essentially
+         while (tx++ < a->used && ty-- >= 0) { ... }
+       */
+      iy = MIN(a->used-tx, ty+1);
+
+      /* now for squaring tx can never equal ty
+       * we halve the distance since they approach at a rate of 2x
+       * and we have to round because odd cases need to be executed
+       */
+      iy = MIN(iy, (ty-tx+1)>>1);
+
+      /* execute loop */
+      for (iz = 0; iz < iy; iz++) {
+         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+      }
+
+      /* double the inner product and add carry */
+      _W = _W + _W + W1;
+
+      /* even columns have the square term in them */
+      if ((ix&1) == 0) {
+         _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]);
+      }
+
+      /* store it */
+      W[ix] = (mp_digit)(_W & MP_MASK);
+
+      /* make next carry */
+      W1 = _W >> ((mp_word)DIGIT_BIT);
+  }
+
+  /* setup dest */
+  olduse  = b->used;
+  b->used = a->used+a->used;
+
+  {
+    mp_digit *tmpb;
+    tmpb = b->dp;
+    for (ix = 0; ix < pa; ix++) {
+      *tmpb++ = (mp_digit)(W[ix] & MP_MASK);
+    }
+
+    /* clear unused digits [that existed in the old copy of c] */
+    for (; ix < olduse; ix++) {
+      *tmpb++ = 0;
+    }
+  }
+  mp_clamp (b);
+
+#ifdef WOLFSSL_SMALL_STACK
+  XFREE(W, NULL, DYNAMIC_TYPE_BIGINT);
+#endif
+
+  return MP_OKAY;
+}
+
+
+/* Fast (comba) multiplier
+ *
+ * This is the fast column-array [comba] multiplier.  It is
+ * designed to compute the columns of the product first
+ * then handle the carries afterwards.  This has the effect
+ * of making the nested loops that compute the columns very
+ * simple and schedulable on super-scalar processors.
+ *
+ * This has been modified to produce a variable number of
+ * digits of output so if say only a half-product is required
+ * you don't have to compute the upper half (a feature
+ * required for fast Barrett reduction).
+ *
+ * Based on Algorithm 14.12 on pp.595 of HAC.
+ *
+ */
+int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  int     olduse, res, pa, ix, iz;
+#ifdef WOLFSSL_SMALL_STACK
+  mp_digit* W;    /* uses dynamic memory and slower */
+#else
+  mp_digit W[MP_WARRAY];
+#endif
+  mp_word  _W;
+
+  /* grow the destination as required */
+  if (c->alloc < digs) {
+    if ((res = mp_grow (c, digs)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* number of output digits to produce */
+  pa = MIN(digs, a->used + b->used);
+  if (pa > (int)MP_WARRAY)
+    return MP_RANGE;  /* TAO range check */
+
+#ifdef WOLFSSL_SMALL_STACK
+  W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT);
+  if (W == NULL)
+    return MP_MEM;
+#endif
+
+  /* clear the carry */
+  _W = 0;
+  for (ix = 0; ix < pa; ix++) {
+      int      tx, ty;
+      int      iy;
+      mp_digit *tmpx, *tmpy;
+
+      /* get offsets into the two bignums */
+      ty = MIN(b->used-1, ix);
+      tx = ix - ty;
+
+      /* setup temp aliases */
+      tmpx = a->dp + tx;
+      tmpy = b->dp + ty;
+
+      /* this is the number of times the loop will iterate, essentially
+         while (tx++ < a->used && ty-- >= 0) { ... }
+       */
+      iy = MIN(a->used-tx, ty+1);
+
+      /* execute loop */
+      for (iz = 0; iz < iy; ++iz) {
+         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+
+      }
+
+      /* store term */
+      W[ix] = (mp_digit)(((mp_digit)_W) & MP_MASK);
+
+      /* make next carry */
+      _W = _W >> ((mp_word)DIGIT_BIT);
+ }
+
+  /* setup dest */
+  olduse  = c->used;
+  c->used = pa;
+
+  {
+    mp_digit *tmpc;
+    tmpc = c->dp;
+    for (ix = 0; ix < pa; ix++) { /* JRB, +1 could read uninitialized data */
+      /* now extract the previous digit [below the carry] */
+      *tmpc++ = W[ix];
+    }
+
+    /* clear unused digits [that existed in the old copy of c] */
+    for (; ix < olduse; ix++) {
+      *tmpc++ = 0;
+    }
+  }
+  mp_clamp (c);
+
+#ifdef WOLFSSL_SMALL_STACK
+  XFREE(W, NULL, DYNAMIC_TYPE_BIGINT);
+#endif
+
+  return MP_OKAY;
+}
+
+
+/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */
+int s_mp_sqr (mp_int * a, mp_int * b)
+{
+  mp_int  t;
+  int     res, ix, iy, pa;
+  mp_word r;
+  mp_digit u, tmpx, *tmpt;
+
+  pa = a->used;
+  if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) {
+    return res;
+  }
+
+  /* default used is maximum possible size */
+  t.used = 2*pa + 1;
+
+  for (ix = 0; ix < pa; ix++) {
+    /* first calculate the digit at 2*ix */
+    /* calculate double precision result */
+    r = ((mp_word) t.dp[2*ix]) +
+        ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]);
+
+    /* store lower part in result */
+    t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK));
+
+    /* get the carry */
+    u           = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+
+    /* left hand side of A[ix] * A[iy] */
+    tmpx        = a->dp[ix];
+
+    /* alias for where to store the results */
+    tmpt        = t.dp + (2*ix + 1);
+
+    for (iy = ix + 1; iy < pa; iy++) {
+      /* first calculate the product */
+      r       = ((mp_word)tmpx) * ((mp_word)a->dp[iy]);
+
+      /* now calculate the double precision result, note we use
+       * addition instead of *2 since it's easier to optimize
+       */
+      r       = ((mp_word) *tmpt) + r + r + ((mp_word) u);
+
+      /* store lower part */
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+      /* get carry */
+      u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+    }
+    /* propagate upwards */
+    while (u != ((mp_digit) 0)) {
+      r       = ((mp_word) *tmpt) + ((mp_word) u);
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+      u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+    }
+  }
+
+  mp_clamp (&t);
+  mp_exch (&t, b);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+
+/* multiplies |a| * |b| and only computes up to digs digits of result
+ * HAC pp. 595, Algorithm 14.12  Modified so you can control how
+ * many digits of output are created.
+ */
+int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  mp_int  t;
+  int     res, pa, pb, ix, iy;
+  mp_digit u;
+  mp_word r;
+  mp_digit tmpx, *tmpt, *tmpy;
+
+  /* can we use the fast multiplier? */
+  if ((digs < (int)MP_WARRAY) &&
+      MIN (a->used, b->used) <
+          (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+    return fast_s_mp_mul_digs (a, b, c, digs);
+  }
+
+  if ((res = mp_init_size (&t, digs)) != MP_OKAY) {
+    return res;
+  }
+  t.used = digs;
+
+  /* compute the digits of the product directly */
+  pa = a->used;
+  for (ix = 0; ix < pa; ix++) {
+    /* set the carry to zero */
+    u = 0;
+
+    /* limit ourselves to making digs digits of output */
+    pb = MIN (b->used, digs - ix);
+
+    /* setup some aliases */
+    /* copy of the digit from a used within the nested loop */
+    tmpx = a->dp[ix];
+
+    /* an alias for the destination shifted ix places */
+    tmpt = t.dp + ix;
+
+    /* an alias for the digits of b */
+    tmpy = b->dp;
+
+    /* compute the columns of the output and propagate the carry */
+    for (iy = 0; iy < pb; iy++) {
+      /* compute the column as a mp_word */
+      r       = ((mp_word)*tmpt) +
+                ((mp_word)tmpx) * ((mp_word)*tmpy++) +
+                ((mp_word) u);
+
+      /* the new column is the lower part of the result */
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+      /* get the carry word from the result */
+      u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+    }
+    /* set carry if it is placed below digs */
+    if (ix + iy < digs) {
+      *tmpt = u;
+    }
+  }
+
+  mp_clamp (&t);
+  mp_exch (&t, c);
+
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+
+/*
+ * shifts with subtractions when the result is greater than b.
+ *
+ * The method is slightly modified to shift B unconditionally up to just under
+ * the leading bit of b.  This saves a lot of multiple precision shifting.
+ */
+int mp_montgomery_calc_normalization (mp_int * a, mp_int * b)
+{
+  int     x, bits, res;
+
+  /* how many bits of last digit does b use */
+  bits = mp_count_bits (b) % DIGIT_BIT;
+
+  if (b->used > 1) {
+     if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1))
+         != MP_OKAY) {
+        return res;
+     }
+  } else {
+     if ((res = mp_set(a, 1)) != MP_OKAY) {
+        return res;
+     }
+     bits = 1;
+  }
+
+  /* now compute C = A * B mod b */
+  for (x = bits - 1; x < (int)DIGIT_BIT; x++) {
+    if ((res = mp_mul_2 (a, a)) != MP_OKAY) {
+      return res;
+    }
+    if (mp_cmp_mag (a, b) != MP_LT) {
+      if ((res = s_mp_sub (a, b, a)) != MP_OKAY) {
+        return res;
+      }
+    }
+  }
+
+  return MP_OKAY;
+}
+
+
+#ifdef MP_LOW_MEM
+   #define TAB_SIZE 32
+#else
+   #define TAB_SIZE 256
+#endif
+
+int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
+{
+  mp_int  M[TAB_SIZE], res, mu;
+  mp_digit buf;
+  int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+  int (*redux)(mp_int*,mp_int*,mp_int*);
+
+  /* find window size */
+  x = mp_count_bits (X);
+  if (x <= 7) {
+    winsize = 2;
+  } else if (x <= 36) {
+    winsize = 3;
+  } else if (x <= 140) {
+    winsize = 4;
+  } else if (x <= 450) {
+    winsize = 5;
+  } else if (x <= 1303) {
+    winsize = 6;
+  } else if (x <= 3529) {
+    winsize = 7;
+  } else {
+    winsize = 8;
+  }
+
+#ifdef MP_LOW_MEM
+    if (winsize > 5) {
+       winsize = 5;
+    }
+#endif
+
+  /* init M array */
+  /* init first cell */
+  if ((err = mp_init(&M[1])) != MP_OKAY) {
+     return err;
+  }
+
+  /* now init the second half of the array */
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    if ((err = mp_init(&M[x])) != MP_OKAY) {
+      for (y = 1<<(winsize-1); y < x; y++) {
+        mp_clear (&M[y]);
+      }
+      mp_clear(&M[1]);
+      return err;
+    }
+  }
+
+  /* create mu, used for Barrett reduction */
+  if ((err = mp_init (&mu)) != MP_OKAY) {
+    goto LBL_M;
+  }
+
+  if (redmode == 0) {
+     if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) {
+        goto LBL_MU;
+     }
+     redux = mp_reduce;
+  } else {
+     if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) {
+        goto LBL_MU;
+     }
+     redux = mp_reduce_2k_l;
+  }
+
+  /* create M table
+   *
+   * The M table contains powers of the base,
+   * e.g. M[x] = G**x mod P
+   *
+   * The first half of the table is not
+   * computed though accept for M[0] and M[1]
+   */
+  if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) {
+    goto LBL_MU;
+  }
+
+  /* compute the value at M[1<<(winsize-1)] by squaring
+   * M[1] (winsize-1) times
+   */
+  if ((err = mp_copy (&M[1], &M[(mp_digit)(1 << (winsize - 1))])) != MP_OKAY) {
+    goto LBL_MU;
+  }
+
+  for (x = 0; x < (winsize - 1); x++) {
+    /* square it */
+    if ((err = mp_sqr (&M[(mp_digit)(1 << (winsize - 1))],
+                       &M[(mp_digit)(1 << (winsize - 1))])) != MP_OKAY) {
+      goto LBL_MU;
+    }
+
+    /* reduce modulo P */
+    if ((err = redux (&M[(mp_digit)(1 << (winsize - 1))], P, &mu)) != MP_OKAY) {
+      goto LBL_MU;
+    }
+  }
+
+  /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
+   * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
+   */
+  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+    if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
+      goto LBL_MU;
+    }
+    if ((err = redux (&M[x], P, &mu)) != MP_OKAY) {
+      goto LBL_MU;
+    }
+  }
+
+  /* setup result */
+  if ((err = mp_init (&res)) != MP_OKAY) {
+    goto LBL_MU;
+  }
+  if ((err = mp_set (&res, 1)) != MP_OKAY) {
+    goto LBL_MU;
+  }
+
+  /* set initial mode and bit cnt */
+  mode   = 0;
+  bitcnt = 1;
+  buf    = 0;
+  digidx = X->used - 1;
+  bitcpy = 0;
+  bitbuf = 0;
+
+  for (;;) {
+    /* grab next digit as required */
+    if (--bitcnt == 0) {
+      /* if digidx == -1 we are out of digits */
+      if (digidx == -1) {
+        break;
+      }
+      /* read next digit and reset the bitcnt */
+      buf    = X->dp[digidx--];
+      bitcnt = (int) DIGIT_BIT;
+    }
+
+    /* grab the next msb from the exponent */
+    y     = (int)(buf >> (mp_digit)(DIGIT_BIT - 1)) & 1;
+    buf <<= (mp_digit)1;
+
+    /* if the bit is zero and mode == 0 then we ignore it
+     * These represent the leading zero bits before the first 1 bit
+     * in the exponent.  Technically this opt is not required but it
+     * does lower the # of trivial squaring/reductions used
+     */
+    if (mode == 0 && y == 0) {
+      continue;
+    }
+
+    /* if the bit is zero and mode == 1 then we square */
+    if (mode == 1 && y == 0) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      continue;
+    }
+
+    /* else we add it to the window */
+    bitbuf |= (y << (winsize - ++bitcpy));
+    mode    = 2;
+
+    if (bitcpy == winsize) {
+      /* ok window is filled so square as required and multiply  */
+      /* square first */
+      for (x = 0; x < winsize; x++) {
+        if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+
+      /* then multiply */
+      if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      /* empty window and reset */
+      bitcpy = 0;
+      bitbuf = 0;
+      mode   = 1;
+    }
+  }
+
+  /* if bits remain then square/multiply */
+  if (mode == 2 && bitcpy > 0) {
+    /* square then multiply if the bit is set */
+    for (x = 0; x < bitcpy; x++) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      bitbuf <<= 1;
+      if ((bitbuf & (1 << winsize)) != 0) {
+        /* then multiply */
+        if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+    }
+  }
+
+  mp_exch (&res, Y);
+  err = MP_OKAY;
+LBL_RES:mp_clear (&res);
+LBL_MU:mp_clear (&mu);
+LBL_M:
+  mp_clear(&M[1]);
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    mp_clear (&M[x]);
+  }
+  return err;
+}
+
+
+/* pre-calculate the value required for Barrett reduction
+ * For a given modulus "b" it calculates the value required in "a"
+ */
+int mp_reduce_setup (mp_int * a, mp_int * b)
+{
+  int     res;
+
+  if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) {
+    return res;
+  }
+  return mp_div (a, b, a, NULL);
+}
+
+
+/* reduces x mod m, assumes 0 < x < m**2, mu is
+ * precomputed via mp_reduce_setup.
+ * From HAC pp.604 Algorithm 14.42
+ */
+int mp_reduce (mp_int * x, mp_int * m, mp_int * mu)
+{
+  mp_int  q;
+  int     res, um = m->used;
+
+  /* q = x */
+  if ((res = mp_init_copy (&q, x)) != MP_OKAY) {
+    return res;
+  }
+
+  /* q1 = x / b**(k-1)  */
+  mp_rshd (&q, um - 1);
+
+  /* according to HAC this optimization is ok */
+  if (((mp_word) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) {
+    if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+  } else {
+#ifdef BN_S_MP_MUL_HIGH_DIGS_C
+    if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+#elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
+    if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+#else
+    {
+      res = MP_VAL;
+      goto CLEANUP;
+    }
+#endif
+  }
+
+  /* q3 = q2 / b**(k+1) */
+  mp_rshd (&q, um + 1);
+
+  /* x = x mod b**(k+1), quick (no division) */
+  if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) {
+    goto CLEANUP;
+  }
+
+  /* q = q * m mod b**(k+1), quick (no division) */
+  if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) {
+    goto CLEANUP;
+  }
+
+  /* x = x - q */
+  if ((res = mp_sub (x, &q, x)) != MP_OKAY) {
+    goto CLEANUP;
+  }
+
+  /* If x < 0, add b**(k+1) to it */
+  if (mp_cmp_d (x, 0) == MP_LT) {
+    if ((res = mp_set (&q, 1)) != MP_OKAY)
+        goto CLEANUP;
+    if ((res = mp_lshd (&q, um + 1)) != MP_OKAY)
+      goto CLEANUP;
+    if ((res = mp_add (x, &q, x)) != MP_OKAY)
+      goto CLEANUP;
+  }
+
+  /* Back off if it's too big */
+  while (mp_cmp (x, m) != MP_LT) {
+    if ((res = s_mp_sub (x, m, x)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+  }
+
+CLEANUP:
+  mp_clear (&q);
+
+  return res;
+}
+
+
+/* reduces a modulo n where n is of the form 2**p - d
+   This differs from reduce_2k since "d" can be larger
+   than a single digit.
+*/
+int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d)
+{
+   mp_int q;
+   int    p, res;
+
+   if ((res = mp_init(&q)) != MP_OKAY) {
+      return res;
+   }
+
+   p = mp_count_bits(n);
+top:
+   /* q = a/2**p, a = a mod 2**p */
+   if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
+      goto ERR;
+   }
+
+   /* q = q * d */
+   if ((res = mp_mul(&q, d, &q)) != MP_OKAY) {
+      goto ERR;
+   }
+
+   /* a = a + q */
+   if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
+      goto ERR;
+   }
+
+   if (mp_cmp_mag(a, n) != MP_LT) {
+      if ((res = s_mp_sub(a, n, a)) != MP_OKAY) {
+         goto ERR;
+      }
+      goto top;
+   }
+
+ERR:
+   mp_clear(&q);
+   return res;
+}
+
+
+/* determines the setup value */
+int mp_reduce_2k_setup_l(mp_int *a, mp_int *d)
+{
+   int    res;
+   mp_int tmp;
+
+   if ((res = mp_init(&tmp)) != MP_OKAY) {
+      return res;
+   }
+
+   if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) {
+      goto ERR;
+   }
+
+   if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) {
+      goto ERR;
+   }
+
+ERR:
+   mp_clear(&tmp);
+   return res;
+}
+
+
+/* multiplies |a| * |b| and does not compute the lower digs digits
+ * [meant to get the higher part of the product]
+ */
+int s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  mp_int  t;
+  int     res, pa, pb, ix, iy;
+  mp_digit u;
+  mp_word r;
+  mp_digit tmpx, *tmpt, *tmpy;
+
+  /* can we use the fast multiplier? */
+#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
+  if (((a->used + b->used + 1) < (int)MP_WARRAY)
+      && MIN (a->used, b->used) <
+      (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+    return fast_s_mp_mul_high_digs (a, b, c, digs);
+  }
+#endif
+
+  if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) {
+    return res;
+  }
+  t.used = a->used + b->used + 1;
+
+  pa = a->used;
+  pb = b->used;
+  for (ix = 0; ix < pa && a->dp; ix++) {
+    /* clear the carry */
+    u = 0;
+
+    /* left hand side of A[ix] * B[iy] */
+    tmpx = a->dp[ix];
+
+    /* alias to the address of where the digits will be stored */
+    tmpt = &(t.dp[digs]);
+
+    /* alias for where to read the right hand side from */
+    tmpy = b->dp + (digs - ix);
+
+    for (iy = digs - ix; iy < pb; iy++) {
+      /* calculate the double precision result */
+      r       = ((mp_word)*tmpt) +
+                ((mp_word)tmpx) * ((mp_word)*tmpy++) +
+                ((mp_word) u);
+
+      /* get the lower part */
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+      /* carry the carry */
+      u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+    }
+    *tmpt = u;
+  }
+  mp_clamp (&t);
+  mp_exch (&t, c);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+
+/* this is a modified version of fast_s_mul_digs that only produces
+ * output digits *above* digs.  See the comments for fast_s_mul_digs
+ * to see how it works.
+ *
+ * This is used in the Barrett reduction since for one of the multiplications
+ * only the higher digits were needed.  This essentially halves the work.
+ *
+ * Based on Algorithm 14.12 on pp.595 of HAC.
+ */
+int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  int     olduse, res, pa, ix, iz;
+#ifdef WOLFSSL_SMALL_STACK
+  mp_digit* W;    /* uses dynamic memory and slower */
+#else
+  mp_digit W[MP_WARRAY];
+#endif
+  mp_word  _W;
+
+  if (a->dp == NULL) { /* JRB, avoid reading uninitialized values */
+      return MP_VAL;
+  }
+
+  /* grow the destination as required */
+  pa = a->used + b->used;
+  if (c->alloc < pa) {
+    if ((res = mp_grow (c, pa)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  if (pa > (int)MP_WARRAY)
+    return MP_RANGE;  /* TAO range check */
+
+#ifdef WOLFSSL_SMALL_STACK
+  W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT);
+  if (W == NULL)
+    return MP_MEM;
+#endif
+
+  /* number of output digits to produce */
+  pa = a->used + b->used;
+  _W = 0;
+  for (ix = digs; ix < pa; ix++) { /* JRB, have a->dp check at top of function*/
+      int      tx, ty, iy;
+      mp_digit *tmpx, *tmpy;
+
+      /* get offsets into the two bignums */
+      ty = MIN(b->used-1, ix);
+      tx = ix - ty;
+
+      /* setup temp aliases */
+      tmpx = a->dp + tx;
+      tmpy = b->dp + ty;
+
+      /* this is the number of times the loop will iterate, essentially its
+         while (tx++ < a->used && ty-- >= 0) { ... }
+       */
+      iy = MIN(a->used-tx, ty+1);
+
+      /* execute loop */
+      for (iz = 0; iz < iy; iz++) {
+         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+      }
+
+      /* store term */
+      W[ix] = (mp_digit)(((mp_digit)_W) & MP_MASK);
+
+      /* make next carry */
+      _W = _W >> ((mp_word)DIGIT_BIT);
+  }
+
+  /* setup dest */
+  olduse  = c->used;
+  c->used = pa;
+
+  {
+    mp_digit *tmpc;
+
+    tmpc = c->dp + digs;
+    for (ix = digs; ix < pa; ix++) {   /* TAO, <= could potentially overwrite */
+      /* now extract the previous digit [below the carry] */
+      *tmpc++ = W[ix];
+    }
+
+    /* clear unused digits [that existed in the old copy of c] */
+    for (; ix < olduse; ix++) {
+      *tmpc++ = 0;
+    }
+  }
+  mp_clamp (c);
+
+#ifdef WOLFSSL_SMALL_STACK
+  XFREE(W, NULL, DYNAMIC_TYPE_BIGINT);
+#endif
+
+  return MP_OKAY;
+}
+
+
+#ifndef MP_SET_CHUNK_BITS
+    #define MP_SET_CHUNK_BITS 4
+#endif
+int mp_set_int (mp_int * a, unsigned long b)
+{
+  int x, res;
+
+  /* use direct mp_set if b is less than mp_digit max */
+  if (b < MP_DIGIT_MAX) {
+    return mp_set (a, (mp_digit)b);
+  }
+
+  mp_zero (a);
+
+  /* set chunk bits at a time */
+  for (x = 0; x < (int)(sizeof(b) * 8) / MP_SET_CHUNK_BITS; x++) {
+    /* shift the number up chunk bits */
+    if ((res = mp_mul_2d (a, MP_SET_CHUNK_BITS, a)) != MP_OKAY) {
+      return res;
+    }
+
+    /* OR in the top bits of the source */
+    a->dp[0] |= (b >> ((sizeof(b) * 8) - MP_SET_CHUNK_BITS)) &
+                                  ((1 << MP_SET_CHUNK_BITS) - 1);
+
+    /* shift the source up to the next chunk bits */
+    b <<= MP_SET_CHUNK_BITS;
+
+    /* ensure that digits are not clamped off */
+    a->used += 1;
+  }
+  mp_clamp (a);
+  return MP_OKAY;
+}
+
+
+#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_ECC) || !defined(NO_RSA) || \
+    !defined(NO_DSA) | !defined(NO_DH)
+
+/* c = a * a (mod b) */
+int mp_sqrmod (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res;
+  mp_int  t;
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_sqr (a, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+  res = mp_mod (&t, b, c);
+  mp_clear (&t);
+  return res;
+}
+
+#endif
+
+
+#if defined(HAVE_ECC) || !defined(NO_PWDBASED) || defined(WOLFSSL_SNIFFER) || \
+    defined(WOLFSSL_HAVE_WOLFSCEP) || defined(WOLFSSL_KEY_GEN) || \
+    defined(OPENSSL_EXTRA) || defined(WC_RSA_BLINDING) || \
+    (!defined(NO_RSA) && !defined(NO_RSA_BOUNDS_CHECK))
+
+/* single digit addition */
+int mp_add_d (mp_int* a, mp_digit b, mp_int* c)
+{
+  int     res, ix, oldused;
+  mp_digit *tmpa, *tmpc, mu;
+
+  /* grow c as required */
+  if (c->alloc < a->used + 1) {
+     if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  /* if a is negative and |a| >= b, call c = |a| - b */
+  if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) {
+     /* temporarily fix sign of a */
+     a->sign = MP_ZPOS;
+
+     /* c = |a| - b */
+     res = mp_sub_d(a, b, c);
+
+     /* fix sign  */
+     a->sign = c->sign = MP_NEG;
+
+     /* clamp */
+     mp_clamp(c);
+
+     return res;
+  }
+
+  /* old number of used digits in c */
+  oldused = c->used;
+
+  /* sign always positive */
+  c->sign = MP_ZPOS;
+
+  /* source alias */
+  tmpa    = a->dp;
+
+  /* destination alias */
+  tmpc    = c->dp;
+
+  /* if a is positive */
+  if (a->sign == MP_ZPOS) {
+     /* add digit, after this we're propagating
+      * the carry.
+      */
+     *tmpc   = *tmpa++ + b;
+     mu      = *tmpc >> DIGIT_BIT;
+     *tmpc++ &= MP_MASK;
+
+     /* now handle rest of the digits */
+     for (ix = 1; ix < a->used; ix++) {
+        *tmpc   = *tmpa++ + mu;
+        mu      = *tmpc >> DIGIT_BIT;
+        *tmpc++ &= MP_MASK;
+     }
+     /* set final carry */
+     if (ix < c->alloc) {
+        ix++;
+        *tmpc++  = mu;
+     }
+
+     /* setup size */
+     c->used = a->used + 1;
+  } else {
+     /* a was negative and |a| < b */
+     c->used  = 1;
+
+     /* the result is a single digit */
+     if (a->used == 1) {
+        *tmpc++  =  b - a->dp[0];
+     } else {
+        *tmpc++  =  b;
+     }
+
+     /* setup count so the clearing of oldused
+      * can fall through correctly
+      */
+     ix       = 1;
+  }
+
+  /* now zero to oldused */
+  while (ix++ < oldused) {
+     *tmpc++ = 0;
+  }
+  mp_clamp(c);
+
+  return MP_OKAY;
+}
+
+
+/* single digit subtraction */
+int mp_sub_d (mp_int * a, mp_digit b, mp_int * c)
+{
+  mp_digit *tmpa, *tmpc, mu;
+  int       res, ix, oldused;
+
+  /* grow c as required */
+  if (c->alloc < a->used + 1) {
+     if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  /* if a is negative just do an unsigned
+   * addition [with fudged signs]
+   */
+  if (a->sign == MP_NEG) {
+     a->sign = MP_ZPOS;
+     res     = mp_add_d(a, b, c);
+     a->sign = c->sign = MP_NEG;
+
+     /* clamp */
+     mp_clamp(c);
+
+     return res;
+  }
+
+  /* setup regs */
+  oldused = c->used;
+  tmpa    = a->dp;
+  tmpc    = c->dp;
+
+  /* if a <= b simply fix the single digit */
+  if ((a->used == 1 && a->dp[0] <= b) || a->used == 0) {
+     if (a->used == 1) {
+        *tmpc++ = b - *tmpa;
+     } else {
+        *tmpc++ = b;
+     }
+     ix      = 1;
+
+     /* negative/1digit */
+     c->sign = MP_NEG;
+     c->used = 1;
+  } else {
+     /* positive/size */
+     c->sign = MP_ZPOS;
+     c->used = a->used;
+
+     /* subtract first digit */
+     *tmpc    = *tmpa++ - b;
+     mu       = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
+     *tmpc++ &= MP_MASK;
+
+     /* handle rest of the digits */
+     for (ix = 1; ix < a->used; ix++) {
+        *tmpc    = *tmpa++ - mu;
+        mu       = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
+        *tmpc++ &= MP_MASK;
+     }
+  }
+
+  /* zero excess digits */
+  while (ix++ < oldused) {
+     *tmpc++ = 0;
+  }
+  mp_clamp(c);
+  return MP_OKAY;
+}
+
+#endif /* defined(HAVE_ECC) || !defined(NO_PWDBASED) */
+
+
+#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || defined(HAVE_ECC) || \
+    defined(DEBUG_WOLFSSL) || !defined(NO_RSA) || !defined(NO_DSA) || \
+    !defined(NO_DH)
+
+static const int lnz[16] = {
+   4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+};
+
+/* Counts the number of lsbs which are zero before the first zero bit */
+int mp_cnt_lsb(mp_int *a)
+{
+    int x;
+    mp_digit q = 0, qq;
+
+    /* easy out */
+    if (mp_iszero(a) == MP_YES) {
+        return 0;
+    }
+
+    /* scan lower digits until non-zero */
+    for (x = 0; x < a->used && a->dp[x] == 0; x++) {}
+    if (a->dp)
+        q = a->dp[x];
+    x *= DIGIT_BIT;
+
+    /* now scan this digit until a 1 is found */
+    if ((q & 1) == 0) {
+        do {
+            qq  = q & 15;
+            x  += lnz[qq];
+            q >>= 4;
+        } while (qq == 0);
+    }
+    return x;
+}
+
+
+
+
+static int s_is_power_of_two(mp_digit b, int *p)
+{
+   int x;
+
+   /* fast return if no power of two */
+   if ((b==0) || (b & (b-1))) {
+      return 0;
+   }
+
+   for (x = 0; x < DIGIT_BIT; x++) {
+      if (b == (((mp_digit)1)<<x)) {
+         *p = x;
+         return 1;
+      }
+   }
+   return 0;
+}
+
+/* single digit division (based on routine from MPI) */
+static int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
+{
+  mp_int  q;
+  mp_word w;
+  mp_digit t;
+  int     res = MP_OKAY, ix;
+
+  /* cannot divide by zero */
+  if (b == 0) {
+     return MP_VAL;
+  }
+
+  /* quick outs */
+  if (b == 1 || mp_iszero(a) == MP_YES) {
+     if (d != NULL) {
+        *d = 0;
+     }
+     if (c != NULL) {
+        return mp_copy(a, c);
+     }
+     return MP_OKAY;
+  }
+
+  /* power of two ? */
+  if (s_is_power_of_two(b, &ix) == 1) {
+     if (d != NULL) {
+        *d = a->dp[0] & ((((mp_digit)1)<<ix) - 1);
+     }
+     if (c != NULL) {
+        return mp_div_2d(a, ix, c, NULL);
+     }
+     return MP_OKAY;
+  }
+
+#ifdef BN_MP_DIV_3_C
+  /* three? */
+  if (b == 3) {
+     return mp_div_3(a, c, d);
+  }
+#endif
+
+  /* no easy answer [c'est la vie].  Just division */
+  if (c != NULL) {
+      if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
+         return res;
+      }
+
+      q.used = a->used;
+      q.sign = a->sign;
+  }
+  else {
+      if ((res = mp_init(&q)) != MP_OKAY) {
+         return res;
+      }
+  }
+
+
+  w = 0;
+  for (ix = a->used - 1; ix >= 0; ix--) {
+     w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
+
+     if (w >= b) {
+        t = (mp_digit)(w / b);
+        w -= ((mp_word)t) * ((mp_word)b);
+      } else {
+        t = 0;
+      }
+      if (c != NULL)
+        q.dp[ix] = (mp_digit)t;
+  }
+
+  if (d != NULL) {
+     *d = (mp_digit)w;
+  }
+
+  if (c != NULL) {
+     mp_clamp(&q);
+     mp_exch(&q, c);
+  }
+  mp_clear(&q);
+
+  return res;
+}
+
+
+int mp_mod_d (mp_int * a, mp_digit b, mp_digit * c)
+{
+  return mp_div_d(a, b, NULL, c);
+}
+
+#endif /* WOLFSSL_KEY_GEN || HAVE_COMP_KEY || HAVE_ECC || DEBUG_WOLFSSL */
+
+#if defined(WOLFSSL_KEY_GEN) || !defined(NO_DH) || !defined(NO_DSA) || !defined(NO_RSA)
+
+const mp_digit ltm_prime_tab[PRIME_SIZE] = {
+  0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
+  0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
+  0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
+  0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F,
+#ifndef MP_8BIT
+  0x0083,
+  0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
+  0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
+  0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
+  0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
+
+  0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
+  0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
+  0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
+  0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
+  0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
+  0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
+  0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
+  0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,
+
+  0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
+  0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
+  0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
+  0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
+  0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
+  0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
+  0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
+  0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,
+
+  0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
+  0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
+  0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
+  0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
+  0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
+  0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
+  0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
+  0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653
+#endif
+};
+
+
+/* Miller-Rabin test of "a" to the base of "b" as described in
+ * HAC pp. 139 Algorithm 4.24
+ *
+ * Sets result to 0 if definitely composite or 1 if probably prime.
+ * Randomly the chance of error is no more than 1/4 and often
+ * very much lower.
+ */
+static int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
+{
+  mp_int  n1, y, r;
+  int     s, j, err;
+
+  /* default */
+  *result = MP_NO;
+
+  /* ensure b > 1 */
+  if (mp_cmp_d(b, 1) != MP_GT) {
+     return MP_VAL;
+  }
+
+  /* get n1 = a - 1 */
+  if ((err = mp_init_copy (&n1, a)) != MP_OKAY) {
+    return err;
+  }
+  if ((err = mp_sub_d (&n1, 1, &n1)) != MP_OKAY) {
+    goto LBL_N1;
+  }
+
+  /* set 2**s * r = n1 */
+  if ((err = mp_init_copy (&r, &n1)) != MP_OKAY) {
+    goto LBL_N1;
+  }
+
+  /* count the number of least significant bits
+   * which are zero
+   */
+  s = mp_cnt_lsb(&r);
+
+  /* now divide n - 1 by 2**s */
+  if ((err = mp_div_2d (&r, s, &r, NULL)) != MP_OKAY) {
+    goto LBL_R;
+  }
+
+  /* compute y = b**r mod a */
+  if ((err = mp_init (&y)) != MP_OKAY) {
+    goto LBL_R;
+  }
+#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)
+#ifndef WOLFSSL_SP_NO_2048
+  if (mp_count_bits(a) == 1024)
+      err = sp_ModExp_1024(b, &r, a, &y);
+  else if (mp_count_bits(a) == 2048)
+      err = sp_ModExp_2048(b, &r, a, &y);
+  else
+#endif
+#ifndef WOLFSSL_SP_NO_3072
+  if (mp_count_bits(a) == 1536)
+      err = sp_ModExp_1536(b, &r, a, &y);
+  else if (mp_count_bits(a) == 3072)
+      err = sp_ModExp_3072(b, &r, a, &y);
+  else
+#endif
+#ifdef WOLFSSL_SP_4096
+  if (mp_count_bits(a) == 4096)
+      err = sp_ModExp_4096(b, &r, a, &y);
+  else
+#endif
+#endif
+      err = mp_exptmod (b, &r, a, &y);
+  if (err != MP_OKAY)
+      goto LBL_Y;
+
+  /* if y != 1 and y != n1 do */
+  if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) {
+    j = 1;
+    /* while j <= s-1 and y != n1 */
+    while ((j <= (s - 1)) && mp_cmp (&y, &n1) != MP_EQ) {
+      if ((err = mp_sqrmod (&y, a, &y)) != MP_OKAY) {
+         goto LBL_Y;
+      }
+
+      /* if y == 1 then composite */
+      if (mp_cmp_d (&y, 1) == MP_EQ) {
+         goto LBL_Y;
+      }
+
+      ++j;
+    }
+
+    /* if y != n1 then composite */
+    if (mp_cmp (&y, &n1) != MP_EQ) {
+      goto LBL_Y;
+    }
+  }
+
+  /* probably prime now */
+  *result = MP_YES;
+LBL_Y:mp_clear (&y);
+LBL_R:mp_clear (&r);
+LBL_N1:mp_clear (&n1);
+  return err;
+}
+
+
+/* determines if an integers is divisible by one
+ * of the first PRIME_SIZE primes or not
+ *
+ * sets result to 0 if not, 1 if yes
+ */
+static int mp_prime_is_divisible (mp_int * a, int *result)
+{
+  int     err, ix;
+  mp_digit res;
+
+  /* default to not */
+  *result = MP_NO;
+
+  for (ix = 0; ix < PRIME_SIZE; ix++) {
+    /* what is a mod LBL_prime_tab[ix] */
+    if ((err = mp_mod_d (a, ltm_prime_tab[ix], &res)) != MP_OKAY) {
+      return err;
+    }
+
+    /* is the residue zero? */
+    if (res == 0) {
+      *result = MP_YES;
+      return MP_OKAY;
+    }
+  }
+
+  return MP_OKAY;
+}
+
+/*
+ * Sets result to 1 if probably prime, 0 otherwise
+ */
+int mp_prime_is_prime (mp_int * a, int t, int *result)
+{
+  mp_int  b;
+  int     ix, err, res;
+
+  /* default to no */
+  *result = MP_NO;
+
+  /* valid value of t? */
+  if (t <= 0 || t > PRIME_SIZE) {
+    return MP_VAL;
+  }
+
+  if (mp_isone(a)) {
+      *result = MP_NO;
+      return MP_OKAY;
+  }
+
+  /* is the input equal to one of the primes in the table? */
+  for (ix = 0; ix < PRIME_SIZE; ix++) {
+      if (mp_cmp_d(a, ltm_prime_tab[ix]) == MP_EQ) {
+         *result = MP_YES;
+         return MP_OKAY;
+      }
+  }
+
+  /* first perform trial division */
+  if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) {
+    return err;
+  }
+
+  /* return if it was trivially divisible */
+  if (res == MP_YES) {
+    return MP_OKAY;
+  }
+
+  /* now perform the miller-rabin rounds */
+  if ((err = mp_init (&b)) != MP_OKAY) {
+    return err;
+  }
+
+  for (ix = 0; ix < t; ix++) {
+    /* set the prime */
+    if ((err = mp_set (&b, ltm_prime_tab[ix])) != MP_OKAY) {
+        goto LBL_B;
+    }
+
+    if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) {
+      goto LBL_B;
+    }
+
+    if (res == MP_NO) {
+      goto LBL_B;
+    }
+  }
+
+  /* passed the test */
+  *result = MP_YES;
+LBL_B:mp_clear (&b);
+  return err;
+}
+
+
+/*
+ * Sets result to 1 if probably prime, 0 otherwise
+ */
+int mp_prime_is_prime_ex (mp_int * a, int t, int *result, WC_RNG *rng)
+{
+  mp_int  b, c;
+  int     ix, err, res;
+  byte*   base = NULL;
+  word32  baseSz = 0;
+
+  /* default to no */
+  *result = MP_NO;
+
+  /* valid value of t? */
+  if (t <= 0 || t > PRIME_SIZE) {
+    return MP_VAL;
+  }
+
+  if (mp_isone(a)) {
+    *result = MP_NO;
+    return MP_OKAY;
+  }
+
+  /* is the input equal to one of the primes in the table? */
+  for (ix = 0; ix < PRIME_SIZE; ix++) {
+      if (mp_cmp_d(a, ltm_prime_tab[ix]) == MP_EQ) {
+         *result = MP_YES;
+         return MP_OKAY;
+      }
+  }
+
+  /* first perform trial division */
+  if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) {
+    return err;
+  }
+
+  /* return if it was trivially divisible */
+  if (res == MP_YES) {
+    return MP_OKAY;
+  }
+
+  /* now perform the miller-rabin rounds */
+  if ((err = mp_init (&b)) != MP_OKAY) {
+    return err;
+  }
+  if ((err = mp_init (&c)) != MP_OKAY) {
+      mp_clear(&b);
+    return err;
+  }
+
+  baseSz = mp_count_bits(a);
+  baseSz = (baseSz / 8) + ((baseSz % 8) ? 1 : 0);
+
+  base = (byte*)XMALLOC(baseSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+  if (base == NULL) {
+      err = MP_MEM;
+      goto LBL_B;
+  }
+
+  if ((err = mp_sub_d(a, 2, &c)) != MP_OKAY) {
+      goto LBL_B;
+  }
+
+ /* now do a miller rabin with up to t random numbers, this should
+  * give a (1/4)^t chance of a false prime. */
+  for (ix = 0; ix < t; ix++) {
+    /* Set a test candidate. */
+    if ((err = wc_RNG_GenerateBlock(rng, base, baseSz)) != 0) {
+        goto LBL_B;
+    }
+
+    if ((err = mp_read_unsigned_bin(&b, base, baseSz)) != MP_OKAY) {
+        goto LBL_B;
+    }
+
+    if (mp_cmp_d(&b, 2) != MP_GT || mp_cmp(&b, &c) != MP_LT) {
+        ix--;
+        continue;
+    }
+
+    if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) {
+      goto LBL_B;
+    }
+
+    if (res == MP_NO) {
+      goto LBL_B;
+    }
+  }
+
+  /* passed the test */
+  *result = MP_YES;
+LBL_B:mp_clear (&b);
+      mp_clear (&c);
+      XFREE(base, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+  return err;
+}
+
+#endif /* WOLFSSL_KEY_GEN NO_DH NO_DSA NO_RSA */
+
+#ifdef WOLFSSL_KEY_GEN
+
+static const int USE_BBS = 1;
+
+int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap)
+{
+    int   err, res, type;
+    byte* buf;
+
+    if (N == NULL || rng == NULL)
+        return MP_VAL;
+
+    /* get type */
+    if (len < 0) {
+        type = USE_BBS;
+        len = -len;
+    } else {
+        type = 0;
+    }
+
+    /* allow sizes between 2 and 512 bytes for a prime size */
+    if (len < 2 || len > 512) {
+        return MP_VAL;
+    }
+
+    /* allocate buffer to work with */
+    buf = (byte*)XMALLOC(len, heap, DYNAMIC_TYPE_RSA);
+    if (buf == NULL) {
+        return MP_MEM;
+    }
+    XMEMSET(buf, 0, len);
+
+    do {
+#ifdef SHOW_GEN
+        printf(".");
+        fflush(stdout);
+#endif
+        /* generate value */
+        err = wc_RNG_GenerateBlock(rng, buf, len);
+        if (err != 0) {
+            XFREE(buf, heap, DYNAMIC_TYPE_RSA);
+            return err;
+        }
+
+        /* munge bits */
+        buf[0]     |= 0x80 | 0x40;
+        buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00);
+
+        /* load value */
+        if ((err = mp_read_unsigned_bin(N, buf, len)) != MP_OKAY) {
+            XFREE(buf, heap, DYNAMIC_TYPE_RSA);
+            return err;
+        }
+
+        /* test */
+        /* Running Miller-Rabin up to 3 times gives us a 2^{-80} chance
+         * of a 1024-bit candidate being a false positive, when it is our
+         * prime candidate. (Note 4.49 of Handbook of Applied Cryptography.)
+         * Using 8 because we've always used 8. */
+        if ((err = mp_prime_is_prime_ex(N, 8, &res, rng)) != MP_OKAY) {
+            XFREE(buf, heap, DYNAMIC_TYPE_RSA);
+            return err;
+        }
+    } while (res == MP_NO);
+
+    XMEMSET(buf, 0, len);
+    XFREE(buf, heap, DYNAMIC_TYPE_RSA);
+
+    return MP_OKAY;
+}
+
+
+/* computes least common multiple as |a*b|/(a, b) */
+int mp_lcm (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res;
+  mp_int  t1, t2;
+
+
+  if ((res = mp_init_multi (&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
+    return res;
+  }
+
+  /* t1 = get the GCD of the two inputs */
+  if ((res = mp_gcd (a, b, &t1)) != MP_OKAY) {
+    goto LBL_T;
+  }
+
+  /* divide the smallest by the GCD */
+  if (mp_cmp_mag(a, b) == MP_LT) {
+     /* store quotient in t2 such that t2 * b is the LCM */
+     if ((res = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) {
+        goto LBL_T;
+     }
+     res = mp_mul(b, &t2, c);
+  } else {
+     /* store quotient in t2 such that t2 * a is the LCM */
+     if ((res = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) {
+        goto LBL_T;
+     }
+     res = mp_mul(a, &t2, c);
+  }
+
+  /* fix the sign to positive */
+  c->sign = MP_ZPOS;
+
+LBL_T:
+  mp_clear(&t1);
+  mp_clear(&t2);
+  return res;
+}
+
+
+
+/* Greatest Common Divisor using the binary method */
+int mp_gcd (mp_int * a, mp_int * b, mp_int * c)
+{
+    mp_int  u, v;
+    int     k, u_lsb, v_lsb, res;
+
+    /* either zero than gcd is the largest */
+    if (mp_iszero (a) == MP_YES) {
+        return mp_abs (b, c);
+    }
+    if (mp_iszero (b) == MP_YES) {
+        return mp_abs (a, c);
+    }
+
+    /* get copies of a and b we can modify */
+    if ((res = mp_init_copy (&u, a)) != MP_OKAY) {
+        return res;
+    }
+
+    if ((res = mp_init_copy (&v, b)) != MP_OKAY) {
+        goto LBL_U;
+    }
+
+    /* must be positive for the remainder of the algorithm */
+    u.sign = v.sign = MP_ZPOS;
+
+    /* B1.  Find the common power of two for u and v */
+    u_lsb = mp_cnt_lsb(&u);
+    v_lsb = mp_cnt_lsb(&v);
+    k     = MIN(u_lsb, v_lsb);
+
+    if (k > 0) {
+        /* divide the power of two out */
+        if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) {
+            goto LBL_V;
+        }
+
+        if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) {
+            goto LBL_V;
+        }
+    }
+
+    /* divide any remaining factors of two out */
+    if (u_lsb != k) {
+        if ((res = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) {
+            goto LBL_V;
+        }
+    }
+
+    if (v_lsb != k) {
+        if ((res = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) {
+            goto LBL_V;
+        }
+    }
+
+    while (mp_iszero(&v) == MP_NO) {
+        /* make sure v is the largest */
+        if (mp_cmp_mag(&u, &v) == MP_GT) {
+            /* swap u and v to make sure v is >= u */
+            mp_exch(&u, &v);
+        }
+
+        /* subtract smallest from largest */
+        if ((res = s_mp_sub(&v, &u, &v)) != MP_OKAY) {
+            goto LBL_V;
+        }
+
+        /* Divide out all factors of two */
+        if ((res = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) {
+            goto LBL_V;
+        }
+    }
+
+    /* multiply by 2**k which we divided out at the beginning */
+    if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) {
+        goto LBL_V;
+    }
+    c->sign = MP_ZPOS;
+    res = MP_OKAY;
+LBL_V:mp_clear (&v);
+LBL_U:mp_clear (&u);
+    return res;
+}
+
+#endif /* WOLFSSL_KEY_GEN */
+
+
+#if !defined(NO_DSA) || defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) || \
+    defined(HAVE_COMP_KEY) || defined(WOLFSSL_DEBUG_MATH) || \
+    defined(DEBUG_WOLFSSL) || defined(OPENSSL_EXTRA)
+
+/* chars used in radix conversions */
+const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\
+                         abcdefghijklmnopqrstuvwxyz+/";
+#endif
+
+#if !defined(NO_DSA) || defined(HAVE_ECC)
+/* read a string [ASCII] in a given radix */
+int mp_read_radix (mp_int * a, const char *str, int radix)
+{
+  int     y, res, neg;
+  char    ch;
+
+  /* zero the digit bignum */
+  mp_zero(a);
+
+  /* make sure the radix is ok */
+  if (radix < MP_RADIX_BIN || radix > MP_RADIX_MAX) {
+    return MP_VAL;
+  }
+
+  /* if the leading digit is a
+   * minus set the sign to negative.
+   */
+  if (*str == '-') {
+    ++str;
+    neg = MP_NEG;
+  } else {
+    neg = MP_ZPOS;
+  }
+
+  /* set the integer to the default of zero */
+  mp_zero (a);
+
+  /* process each digit of the string */
+  while (*str != '\0') {
+    /* if the radix <= 36 the conversion is case insensitive
+     * this allows numbers like 1AB and 1ab to represent the same  value
+     * [e.g. in hex]
+     */
+    ch = (radix <= 36) ? (char)XTOUPPER((unsigned char)*str) : *str;
+    for (y = 0; y < 64; y++) {
+      if (ch == mp_s_rmap[y]) {
+         break;
+      }
+    }
+
+    /* if the char was found in the map
+     * and is less than the given radix add it
+     * to the number, otherwise exit the loop.
+     */
+    if (y < radix) {
+      if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) {
+         return res;
+      }
+      if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) {
+         return res;
+      }
+    } else {
+      break;
+    }
+    ++str;
+  }
+
+  /* if digit in isn't null term, then invalid character was found */
+  if (*str != '\0') {
+     mp_zero (a);
+     return MP_VAL;
+  }
+
+  /* set the sign only if a != 0 */
+  if (mp_iszero(a) != MP_YES) {
+     a->sign = neg;
+  }
+  return MP_OKAY;
+}
+#endif /* !defined(NO_DSA) || defined(HAVE_ECC) */
+
+#ifdef WC_MP_TO_RADIX
+
+/* returns size of ASCII representation */
+int mp_radix_size (mp_int *a, int radix, int *size)
+{
+    int     res, digs;
+    mp_int  t;
+    mp_digit d;
+
+    *size = 0;
+
+    /* special case for binary */
+    if (radix == MP_RADIX_BIN) {
+        *size = mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1;
+        return MP_OKAY;
+    }
+
+    /* make sure the radix is in range */
+    if (radix < MP_RADIX_BIN || radix > MP_RADIX_MAX) {
+        return MP_VAL;
+    }
+
+    if (mp_iszero(a) == MP_YES) {
+        *size = 2;
+        return MP_OKAY;
+    }
+
+    /* digs is the digit count */
+    digs = 0;
+
+    /* if it's negative add one for the sign */
+    if (a->sign == MP_NEG) {
+        ++digs;
+    }
+
+    /* init a copy of the input */
+    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+        return res;
+    }
+
+    /* force temp to positive */
+    t.sign = MP_ZPOS;
+
+    /* fetch out all of the digits */
+    while (mp_iszero (&t) == MP_NO) {
+        if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
+            mp_clear (&t);
+            return res;
+        }
+        ++digs;
+    }
+    mp_clear (&t);
+
+    /* return digs + 1, the 1 is for the NULL byte that would be required. */
+    *size = digs + 1;
+    return MP_OKAY;
+}
+
+/* stores a bignum as a ASCII string in a given radix (2..64) */
+int mp_toradix (mp_int *a, char *str, int radix)
+{
+    int     res, digs;
+    mp_int  t;
+    mp_digit d;
+    char   *_s = str;
+
+    /* check range of the radix */
+    if (radix < MP_RADIX_BIN || radix > MP_RADIX_MAX) {
+        return MP_VAL;
+    }
+
+    /* quick out if its zero */
+    if (mp_iszero(a) == MP_YES) {
+        *str++ = '0';
+        *str = '\0';
+        return MP_OKAY;
+    }
+
+    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+        return res;
+    }
+
+    /* if it is negative output a - */
+    if (t.sign == MP_NEG) {
+        ++_s;
+        *str++ = '-';
+        t.sign = MP_ZPOS;
+    }
+
+    digs = 0;
+    while (mp_iszero (&t) == MP_NO) {
+        if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
+            mp_clear (&t);
+            return res;
+        }
+        *str++ = mp_s_rmap[d];
+        ++digs;
+    }
+#ifndef WC_DISABLE_RADIX_ZERO_PAD
+    /* For hexadecimal output, add zero padding when number of digits is odd */
+    if ((digs & 1) && (radix == 16)) {
+        *str++ = mp_s_rmap[0];
+        ++digs;
+    }
+#endif
+    /* reverse the digits of the string.  In this case _s points
+     * to the first digit [excluding the sign] of the number]
+     */
+    bn_reverse ((unsigned char *)_s, digs);
+
+    /* append a NULL so the string is properly terminated */
+    *str = '\0';
+
+    mp_clear (&t);
+    return MP_OKAY;
+}
+
+#ifdef WOLFSSL_DEBUG_MATH
+void mp_dump(const char* desc, mp_int* a, byte verbose)
+{
+  char *buffer;
+  int size = a->alloc;
+
+  buffer = (char*)XMALLOC(size * sizeof(mp_digit) * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+  if (buffer == NULL) {
+    return;
+  }
+
+  printf("%s: ptr=%p, used=%d, sign=%d, size=%d, mpd=%d\n",
+    desc, a, a->used, a->sign, size, (int)sizeof(mp_digit));
+
+  mp_tohex(a, buffer);
+  printf("  %s\n  ", buffer);
+
+  if (verbose) {
+    int i;
+    for(i=0; i<a->alloc * (int)sizeof(mp_digit); i++) {
+      printf("%02x ", *(((byte*)a->dp) + i));
+    }
+    printf("\n");
+  }
+
+  XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+}
+#endif /* WOLFSSL_DEBUG_MATH */
+
+#endif /* WC_MP_TO_RADIX */
+
+#endif /* WOLFSSL_SP_MATH */
+
+#endif /* USE_FAST_MATH */
+
+#endif /* NO_BIG_INT */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/logging.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/logging.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/logging.c	(revision 453)
@@ -0,0 +1,843 @@
+/* logging.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#include <wolfssl/wolfcrypt/logging.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY)
+/* avoid adding WANT_READ and WANT_WRITE to error queue */
+#include <wolfssl/error-ssl.h>
+#endif
+
+#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
+static wolfSSL_Mutex debug_mutex; /* mutex for access to debug structure */
+
+/* accessing any node from the queue should be wrapped in a lock of
+ * debug_mutex */
+static void* wc_error_heap;
+struct wc_error_queue {
+    void*  heap; /* the heap hint used with nodes creation */
+    struct wc_error_queue* next;
+    struct wc_error_queue* prev;
+    char   error[WOLFSSL_MAX_ERROR_SZ];
+    char   file[WOLFSSL_MAX_ERROR_SZ];
+    int    value;
+    int    line;
+};
+volatile struct wc_error_queue* wc_errors;
+static struct wc_error_queue* wc_current_node;
+static struct wc_error_queue* wc_last_node;
+/* pointer to last node in queue to make insertion O(1) */
+#endif
+
+#ifdef WOLFSSL_FUNC_TIME
+/* WARNING: This code is only to be used for debugging performance.
+ *          The code is not thread-safe.
+ *          Do not use WOLFSSL_FUNC_TIME in production code.
+ */
+static double wc_func_start[WC_FUNC_COUNT];
+static double wc_func_time[WC_FUNC_COUNT] = { 0, };
+static const char* wc_func_name[WC_FUNC_COUNT] = {
+    "SendHelloRequest",
+    "DoHelloRequest",
+    "SendClientHello",
+    "DoClientHello",
+    "SendServerHello",
+    "DoServerHello",
+    "SendEncryptedExtensions",
+    "DoEncryptedExtensions",
+    "SendCertificateRequest",
+    "DoCertificateRequest",
+    "SendCertificate",
+    "DoCertificate",
+    "SendCertificateVerify",
+    "DoCertificateVerify",
+    "SendFinished",
+    "DoFinished",
+    "SendKeyUpdate",
+    "DoKeyUpdate",
+    "SendEarlyData",
+    "DoEarlyData",
+    "SendNewSessionTicket",
+    "DoNewSessionTicket",
+    "SendServerHelloDone",
+    "DoServerHelloDone",
+    "SendTicket",
+    "DoTicket",
+    "SendClientKeyExchange",
+    "DoClientKeyExchange",
+    "SendCertificateStatus",
+    "DoCertificateStatus",
+    "SendServerKeyExchange",
+    "DoServerKeyExchange",
+    "SendEarlyData",
+    "DoEarlyData",
+};
+
+#include <sys/time.h>
+
+/* WARNING: This function is not portable. */
+static WC_INLINE double current_time(int reset)
+{
+    struct timeval tv;
+    gettimeofday(&tv, 0);
+    (void)reset;
+
+    return (double)tv.tv_sec + (double)tv.tv_usec / 1000000;
+}
+#endif /* WOLFSSL_FUNC_TIME */
+
+#ifdef DEBUG_WOLFSSL
+
+/* Set these to default values initially. */
+static wolfSSL_Logging_cb log_function = NULL;
+static int loggingEnabled = 0;
+
+#if defined(WOLFSSL_APACHE_MYNEWT)
+#include "log/log.h"
+static struct log mynewt_log;
+#endif /* WOLFSSL_APACHE_MYNEWT */
+
+#endif /* DEBUG_WOLFSSL */
+
+
+/* allow this to be set to NULL, so logs can be redirected to default output */
+int wolfSSL_SetLoggingCb(wolfSSL_Logging_cb f)
+{
+#ifdef DEBUG_WOLFSSL
+    log_function = f;
+    return 0;
+#else
+    (void)f;
+    return NOT_COMPILED_IN;
+#endif
+}
+
+/* allow this to be set to NULL, so logs can be redirected to default output */
+wolfSSL_Logging_cb wolfSSL_GetLoggingCb(void)
+{
+#ifdef DEBUG_WOLFSSL
+    return log_function;
+#else
+    return NULL;
+#endif
+}
+
+
+int wolfSSL_Debugging_ON(void)
+{
+#ifdef DEBUG_WOLFSSL
+    loggingEnabled = 1;
+#if defined(WOLFSSL_APACHE_MYNEWT)
+    log_register("wolfcrypt", &mynewt_log, &log_console_handler, NULL, LOG_SYSLEVEL);
+#endif /* WOLFSSL_APACHE_MYNEWT */
+    return 0;
+#else
+    return NOT_COMPILED_IN;
+#endif
+}
+
+
+void wolfSSL_Debugging_OFF(void)
+{
+#ifdef DEBUG_WOLFSSL
+    loggingEnabled = 0;
+#endif
+}
+
+#ifdef WOLFSSL_FUNC_TIME
+/* WARNING: This code is only to be used for debugging performance.
+ *          The code is not thread-safe.
+ *          Do not use WOLFSSL_FUNC_TIME in production code.
+ */
+void WOLFSSL_START(int funcNum)
+{
+    double now = current_time(0) * 1000.0;
+#ifdef WOLFSSL_FUNC_TIME_LOG
+    fprintf(stderr, "%17.3f: START - %s\n", now, wc_func_name[funcNum]);
+#endif
+    wc_func_start[funcNum] = now;
+}
+
+void WOLFSSL_END(int funcNum)
+{
+    double now = current_time(0) * 1000.0;
+    wc_func_time[funcNum] += now - wc_func_start[funcNum];
+#ifdef WOLFSSL_FUNC_TIME_LOG
+    fprintf(stderr, "%17.3f: END   - %s\n", now, wc_func_name[funcNum]);
+#endif
+}
+
+void WOLFSSL_TIME(int count)
+{
+    int i;
+    double avg, total = 0;
+
+    for (i = 0; i < WC_FUNC_COUNT; i++) {
+        if (wc_func_time[i] > 0) {
+            avg = wc_func_time[i] / count;
+            fprintf(stderr, "%8.3f ms: %s\n", avg, wc_func_name[i]);
+            total += avg;
+        }
+    }
+    fprintf(stderr, "%8.3f ms\n", total);
+}
+#endif
+
+#ifdef DEBUG_WOLFSSL
+
+#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
+    /* see wc_port.h for fio.h and nio.h includes */
+#elif defined(WOLFSSL_SGX)
+    /* Declare sprintf for ocall */
+    int sprintf(char* buf, const char *fmt, ...);
+#elif defined(WOLFSSL_DEOS)
+#elif defined(MICRIUM)
+    #if (BSP_SER_COMM_EN  == DEF_ENABLED)
+        #include <bsp_ser.h>
+    #endif
+#elif defined(WOLFSSL_USER_LOG)
+    /* user includes their own headers */
+#elif defined(WOLFSSL_ESPIDF)
+    #include "esp_types.h"
+    #include "esp_log.h"
+#elif defined(WOLFSSL_TELIT_M2MB)
+    #include <stdio.h>
+    #include "m2m_log.h"
+#elif defined(WOLFSSL_ANDROID_DEBUG)
+    #include <android/log.h>
+#else
+    #include <stdio.h>   /* for default printf stuff */
+#endif
+
+#if defined(THREADX) && !defined(THREADX_NO_DC_PRINTF)
+    int dc_log_printf(char*, ...);
+#endif
+
+static void wolfssl_log(const int logLevel, const char *const logMessage)
+{
+    if (log_function)
+        log_function(logLevel, logMessage);
+    else {
+#if defined(WOLFSSL_USER_LOG)
+        WOLFSSL_USER_LOG(logMessage);
+#elif defined(WOLFSSL_LOG_PRINTF)
+        printf("%s\n", logMessage);
+
+#elif defined(THREADX) && !defined(THREADX_NO_DC_PRINTF)
+        dc_log_printf("%s\n", logMessage);
+#elif defined(WOLFSSL_DEOS)
+        printf("%s\r\n", logMessage);
+#elif defined(MICRIUM)
+        BSP_Ser_Printf("%s\r\n", logMessage);
+#elif defined(WOLFSSL_MDK_ARM)
+        fflush(stdout) ;
+        printf("%s\n", logMessage);
+        fflush(stdout) ;
+#elif defined(WOLFSSL_UTASKER)
+        fnDebugMsg((char*)logMessage);
+        fnDebugMsg("\r\n");
+#elif defined(MQX_USE_IO_OLD)
+        fprintf(_mqxio_stderr, "%s\n", logMessage);
+
+#elif defined(WOLFSSL_APACHE_MYNEWT)
+        LOG_DEBUG(&mynewt_log, LOG_MODULE_DEFAULT, "%s\n", logMessage);
+#elif defined(WOLFSSL_ESPIDF)
+        ESP_LOGI("wolfssl", "%s", logMessage);
+#elif defined(WOLFSSL_ZEPHYR)
+        printk("%s\n", logMessage);
+#elif defined(WOLFSSL_TELIT_M2MB)
+        M2M_LOG_INFO("%s\n", logMessage);
+#elif defined(WOLFSSL_ANDROID_DEBUG)
+        __android_log_print(ANDROID_LOG_VERBOSE, "[wolfSSL]", "%s", logMessage);
+#else
+        fprintf(stderr, "%s\n", logMessage);
+#endif
+    }
+}
+
+#ifndef WOLFSSL_DEBUG_ERRORS_ONLY
+void WOLFSSL_MSG(const char* msg)
+{
+    if (loggingEnabled)
+        wolfssl_log(INFO_LOG , msg);
+}
+
+#ifndef LINE_LEN
+#define LINE_LEN 16
+#endif
+void WOLFSSL_BUFFER(const byte* buffer, word32 length)
+{
+    int i, buflen = (int)length, bufidx;
+    char line[(LINE_LEN * 4) + 3]; /* \t00..0F | chars...chars\0 */
+
+    if (!loggingEnabled) {
+        return;
+    }
+
+    if (!buffer) {
+        wolfssl_log(INFO_LOG, "\tNULL");
+        return;
+    }
+
+    while (buflen > 0) {
+        bufidx = 0;
+        XSNPRINTF(&line[bufidx], sizeof(line)-bufidx, "\t");
+        bufidx++;
+
+        for (i = 0; i < LINE_LEN; i++) {
+            if (i < buflen) {
+                XSNPRINTF(&line[bufidx], sizeof(line)-bufidx, "%02x ", buffer[i]);
+            }
+            else {
+                XSNPRINTF(&line[bufidx], sizeof(line)-bufidx, "   ");
+            }
+            bufidx += 3;
+        }
+
+        XSNPRINTF(&line[bufidx], sizeof(line)-bufidx, "| ");
+        bufidx++;
+
+        for (i = 0; i < LINE_LEN; i++) {
+            if (i < buflen) {
+                XSNPRINTF(&line[bufidx], sizeof(line)-bufidx,
+                     "%c", 31 < buffer[i] && buffer[i] < 127 ? buffer[i] : '.');
+                bufidx++;
+            }
+        }
+
+        wolfssl_log(INFO_LOG, line);
+        buffer += LINE_LEN;
+        buflen -= LINE_LEN;
+    }
+}
+
+
+void WOLFSSL_ENTER(const char* msg)
+{
+    if (loggingEnabled) {
+        char buffer[WOLFSSL_MAX_ERROR_SZ];
+        XSNPRINTF(buffer, sizeof(buffer), "wolfSSL Entering %s", msg);
+        wolfssl_log(ENTER_LOG , buffer);
+    }
+}
+
+
+void WOLFSSL_LEAVE(const char* msg, int ret)
+{
+    if (loggingEnabled) {
+        char buffer[WOLFSSL_MAX_ERROR_SZ];
+        XSNPRINTF(buffer, sizeof(buffer), "wolfSSL Leaving %s, return %d",
+                msg, ret);
+        wolfssl_log(LEAVE_LOG , buffer);
+    }
+}
+
+WOLFSSL_API int WOLFSSL_IS_DEBUG_ON(void)
+{
+    return loggingEnabled;
+}
+#endif /* !WOLFSSL_DEBUG_ERRORS_ONLY */
+#endif /* DEBUG_WOLFSSL */
+
+/*
+ * When using OPENSSL_EXTRA or DEBUG_WOLFSSL_VERBOSE macro then WOLFSSL_ERROR is
+ * mapped to new function WOLFSSL_ERROR_LINE which gets the line # and function
+ * name where WOLFSSL_ERROR is called at.
+ */
+#if defined(DEBUG_WOLFSSL) || defined(OPENSSL_ALL) || \
+    defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
+    defined(OPENSSL_EXTRA)
+
+#if (defined(OPENSSL_EXTRA) && !defined(_WIN32) && !defined(NO_ERROR_QUEUE)) \
+    || defined(DEBUG_WOLFSSL_VERBOSE)
+void WOLFSSL_ERROR_LINE(int error, const char* func, unsigned int line,
+        const char* file, void* usrCtx)
+#else
+void WOLFSSL_ERROR(int error)
+#endif
+{
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (error != WC_PENDING_E)
+#endif
+    {
+        char buffer[WOLFSSL_MAX_ERROR_SZ];
+
+    #if (defined(OPENSSL_EXTRA) && !defined(_WIN32) && \
+            !defined(NO_ERROR_QUEUE)) || defined(DEBUG_WOLFSSL_VERBOSE)
+        (void)usrCtx; /* a user ctx for future flexibility */
+        (void)func;
+
+        if (wc_LockMutex(&debug_mutex) != 0) {
+            WOLFSSL_MSG("Lock debug mutex failed");
+            XSNPRINTF(buffer, sizeof(buffer),
+                    "wolfSSL error occurred, error = %d", error);
+        }
+        else {
+            #if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY)
+            /* If running in compatibility mode do not add want read and
+               want right to error queue */
+            if (error != WANT_READ && error != WANT_WRITE) {
+            #endif
+            if (error < 0)
+                error = error - (2 * error); /* get absolute value */
+            XSNPRINTF(buffer, sizeof(buffer),
+                    "wolfSSL error occurred, error = %d line:%d file:%s",
+                    error, line, file);
+            if (wc_AddErrorNode(error, line, buffer, (char*)file) != 0) {
+                WOLFSSL_MSG("Error creating logging node");
+                /* with void function there is no return here, continue on
+                 * to unlock mutex and log what buffer was created. */
+            }
+            #if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY)
+            }
+            else {
+                XSNPRINTF(buffer, sizeof(buffer),
+                    "wolfSSL error occurred, error = %d", error);
+
+            }
+            #endif
+
+            wc_UnLockMutex(&debug_mutex);
+        }
+    #else
+        XSNPRINTF(buffer, sizeof(buffer),
+                "wolfSSL error occurred, error = %d", error);
+    #endif
+
+    #ifdef DEBUG_WOLFSSL
+        if (loggingEnabled)
+            wolfssl_log(ERROR_LOG , buffer);
+    #endif
+    }
+}
+
+void WOLFSSL_ERROR_MSG(const char* msg)
+{
+#ifdef DEBUG_WOLFSSL
+    if (loggingEnabled)
+        wolfssl_log(ERROR_LOG , msg);
+#else
+    (void)msg;
+#endif
+}
+
+#endif  /* DEBUG_WOLFSSL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
+
+#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
+/* Internal function that is called by wolfCrypt_Init() */
+int wc_LoggingInit(void)
+{
+    if (wc_InitMutex(&debug_mutex) != 0) {
+        WOLFSSL_MSG("Bad Init Mutex");
+        return BAD_MUTEX_E;
+    }
+    wc_errors          = NULL;
+    wc_current_node    = NULL;
+    wc_last_node       = NULL;
+
+    return 0;
+}
+
+
+/* internal function that is called by wolfCrypt_Cleanup */
+int wc_LoggingCleanup(void)
+{
+    /* clear logging entries */
+    wc_ClearErrorNodes();
+
+    /* free mutex */
+    if (wc_FreeMutex(&debug_mutex) != 0) {
+        WOLFSSL_MSG("Bad Mutex free");
+        return BAD_MUTEX_E;
+    }
+    return 0;
+}
+
+
+/* peek at an error node
+ *
+ * idx : if -1 then the most recent node is looked at, otherwise search
+ *         through queue for node at the given index
+ * file  : pointer to internal file string
+ * reason : pointer to internal error reason
+ * line  : line number that error happened at
+ *
+ * Returns a negative value in error case, on success returns the nodes error
+ * value which is positive (absolute value)
+ */
+int wc_PeekErrorNode(int idx, const char **file, const char **reason,
+        int *line)
+{
+    struct wc_error_queue* err;
+
+    if (wc_LockMutex(&debug_mutex) != 0) {
+        WOLFSSL_MSG("Lock debug mutex failed");
+        return BAD_MUTEX_E;
+    }
+
+    if (idx < 0) {
+        err = wc_last_node;
+    }
+    else {
+        int i;
+
+        err = (struct wc_error_queue*)wc_errors;
+        for (i = 0; i < idx; i++) {
+            if (err == NULL) {
+                WOLFSSL_MSG("Error node not found. Bad index?");
+                wc_UnLockMutex(&debug_mutex);
+                return BAD_FUNC_ARG;
+            }
+            err = err->next;
+        }
+    }
+
+    if (err == NULL) {
+        WOLFSSL_MSG("No Errors in queue");
+        wc_UnLockMutex(&debug_mutex);
+        return BAD_STATE_E;
+    }
+
+    if (file != NULL) {
+        *file = err->file;
+    }
+
+    if (reason != NULL) {
+        *reason = err->error;
+    }
+
+    if (line != NULL) {
+        *line = err->line;
+    }
+
+    wc_UnLockMutex(&debug_mutex);
+
+    return err->value;
+}
+
+
+/* Pulls the current node from error queue and increments current state.
+ * Note: this does not delete nodes because input arguments are pointing to
+ *       node buffers.
+ *
+ * file   pointer to file that error was in. Can be NULL to return no file.
+ * reason error string giving reason for error. Can be NULL to return no reason.
+ * line   return line number of where error happened.
+ *
+ * returns the error value on success and BAD_MUTEX_E or BAD_STATE_E on failure
+ */
+int wc_PullErrorNode(const char **file, const char **reason, int *line)
+{
+    struct wc_error_queue* err;
+    int value;
+
+    if (wc_LockMutex(&debug_mutex) != 0) {
+        WOLFSSL_MSG("Lock debug mutex failed");
+        return BAD_MUTEX_E;
+    }
+
+    err = wc_current_node;
+    if (err == NULL) {
+        WOLFSSL_MSG("No Errors in queue");
+        wc_UnLockMutex(&debug_mutex);
+        return BAD_STATE_E;
+    }
+
+    if (file != NULL) {
+        *file = err->file;
+    }
+
+    if (reason != NULL) {
+        *reason = err->error;
+    }
+
+    if (line != NULL) {
+        *line = err->line;
+    }
+
+    value = err->value;
+    wc_current_node = err->next;
+    wc_UnLockMutex(&debug_mutex);
+
+    return value;
+}
+
+
+/* create new error node and add it to the queue
+ * buffers are assumed to be of size WOLFSSL_MAX_ERROR_SZ for this internal
+ * function. debug_mutex should be locked before a call to this function. */
+int wc_AddErrorNode(int error, int line, char* buf, char* file)
+{
+#if defined(NO_ERROR_QUEUE)
+    (void)error;
+    (void)line;
+    (void)buf;
+    (void)file;
+    WOLFSSL_MSG("Error queue turned off, can not add nodes");
+#else
+    struct wc_error_queue* err;
+    err = (struct wc_error_queue*)XMALLOC(
+            sizeof(struct wc_error_queue), wc_error_heap, DYNAMIC_TYPE_LOG);
+    if (err == NULL) {
+        WOLFSSL_MSG("Unable to create error node for log");
+        return MEMORY_E;
+    }
+    else {
+        int sz;
+
+        XMEMSET(err, 0, sizeof(struct wc_error_queue));
+        err->heap = wc_error_heap;
+        sz = (int)XSTRLEN(buf);
+        if (sz > WOLFSSL_MAX_ERROR_SZ - 1) {
+            sz = WOLFSSL_MAX_ERROR_SZ - 1;
+        }
+        if (sz > 0) {
+            XMEMCPY(err->error, buf, sz);
+        }
+
+        sz = (int)XSTRLEN(file);
+        if (sz > WOLFSSL_MAX_ERROR_SZ - 1) {
+            sz = WOLFSSL_MAX_ERROR_SZ - 1;
+        }
+        if (sz > 0) {
+            XMEMCPY(err->file, file, sz);
+        }
+
+        err->value = error;
+        err->line  = line;
+
+        /* make sure is terminated */
+        err->error[WOLFSSL_MAX_ERROR_SZ - 1] = '\0';
+        err->file[WOLFSSL_MAX_ERROR_SZ - 1]  = '\0';
+
+
+        /* since is queue place new node at last of the list */
+        if (wc_last_node == NULL) {
+            /* case of first node added to queue */
+            if (wc_errors != NULL) {
+                /* check for unexpected case before over writing wc_errors */
+                WOLFSSL_MSG("ERROR in adding new node to logging queue!!\n");
+                /* In the event both wc_last_node and wc_errors are NULL, err
+                 * goes unassigned to external wc_errors, wc_last_node. Free
+                 * err in this instance since wc_ClearErrorNodes will not
+                 */
+                XFREE(err, wc_error_heap, DYNAMIC_TYPE_LOG);
+            }
+            else {
+                wc_errors    = err;
+                wc_last_node = err;
+                wc_current_node = err;
+            }
+        }
+        else {
+            wc_last_node->next = err;
+            err->prev = wc_last_node;
+            wc_last_node = err;
+
+            /* check the case where have read to the end of the queue and the
+             * current node to read needs updated */
+            if (wc_current_node == NULL) {
+                wc_current_node = err;
+            }
+        }
+    }
+#endif
+    return 0;
+}
+
+/* Removes the error node at the specified index.
+ * idx : if -1 then the most recent node is looked at, otherwise search
+ *         through queue for node at the given index
+ */
+void wc_RemoveErrorNode(int idx)
+{
+    struct wc_error_queue* current;
+
+    if (wc_LockMutex(&debug_mutex) != 0) {
+        WOLFSSL_MSG("Lock debug mutex failed");
+        return;
+    }
+
+    if (idx == -1)
+        current = wc_last_node;
+    else {
+        current = (struct wc_error_queue*)wc_errors;
+        for (; current != NULL && idx > 0; idx--)
+             current = current->next;
+    }
+    if (current != NULL) {
+        if (current->prev != NULL)
+            current->prev->next = current->next;
+        if (current->next != NULL)
+            current->next->prev = current->prev;
+        if (wc_last_node == current)
+            wc_last_node = current->prev;
+        if (wc_errors == current)
+            wc_errors = current->next;
+        if (wc_current_node == current)
+            wc_current_node = current->next;
+        XFREE(current, current->heap, DYNAMIC_TYPE_LOG);
+    }
+
+    wc_UnLockMutex(&debug_mutex);
+}
+
+
+/* Clears out the list of error nodes.
+ */
+void wc_ClearErrorNodes(void)
+{
+#if defined(DEBUG_WOLFSSL) || defined(WOLFSSL_NGINX) || \
+    defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
+
+    if (wc_LockMutex(&debug_mutex) != 0) {
+        WOLFSSL_MSG("Lock debug mutex failed");
+        return;
+    }
+
+    /* free all nodes from error queue */
+    {
+        struct wc_error_queue* current;
+        struct wc_error_queue* next;
+
+        current = (struct wc_error_queue*)wc_errors;
+        while (current != NULL) {
+            next = current->next;
+            XFREE(current, current->heap, DYNAMIC_TYPE_LOG);
+            current = next;
+        }
+    }
+
+    wc_errors       = NULL;
+    wc_last_node    = NULL;
+    wc_current_node = NULL;
+    wc_UnLockMutex(&debug_mutex);
+#endif /* DEBUG_WOLFSSL || WOLFSSL_NGINX */
+}
+
+int wc_SetLoggingHeap(void* h)
+{
+    if (wc_LockMutex(&debug_mutex) != 0) {
+        WOLFSSL_MSG("Lock debug mutex failed");
+        return BAD_MUTEX_E;
+    }
+    wc_error_heap = h;
+    wc_UnLockMutex(&debug_mutex);
+    return 0;
+}
+
+
+/* frees all nodes in the queue
+ *
+ * id  this is the thread id
+ */
+int wc_ERR_remove_state(void)
+{
+    struct wc_error_queue* current;
+    struct wc_error_queue* next;
+
+    if (wc_LockMutex(&debug_mutex) != 0) {
+        WOLFSSL_MSG("Lock debug mutex failed");
+        return BAD_MUTEX_E;
+    }
+
+    /* free all nodes from error queue */
+    current = (struct wc_error_queue*)wc_errors;
+    while (current != NULL) {
+        next = current->next;
+        XFREE(current, current->heap, DYNAMIC_TYPE_LOG);
+        current = next;
+    }
+
+    wc_errors          = NULL;
+    wc_last_node       = NULL;
+
+    wc_UnLockMutex(&debug_mutex);
+
+    return 0;
+}
+
+#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)
+/* empties out the error queue into the file */
+static int wc_ERR_dump_to_file (const char *str, size_t len, void *u)
+{
+    XFILE fp = (XFILE ) u;
+    fprintf(fp, "%-*.*s\n", (int)len, (int)len, str);
+    return 0;
+}
+
+/* This callback allows the application to provide a custom error printing
+ * function. */
+void wc_ERR_print_errors_cb(int (*cb)(const char *str, size_t len, void *u),
+                            void *u)
+{
+    WOLFSSL_ENTER("wc_ERR_print_errors_cb");
+
+    if (cb == NULL) {
+        /* Invalid param */
+        return;
+    }
+
+    if (wc_LockMutex(&debug_mutex) != 0)
+    {
+        WOLFSSL_MSG("Lock debug mutex failed");
+    }
+    else
+    {
+        /* free all nodes from error queue and print them to file */
+        struct wc_error_queue *current;
+        struct wc_error_queue *next;
+
+        current = (struct wc_error_queue *)wc_errors;
+        while (current != NULL)
+        {
+            next = current->next;
+            cb(current->error, strlen(current->error), u);
+            XFREE(current, current->heap, DYNAMIC_TYPE_LOG);
+            current = next;
+        }
+
+        /* set global pointers to match having been freed */
+        wc_errors = NULL;
+        wc_last_node = NULL;
+
+        wc_UnLockMutex(&debug_mutex);
+    }
+}
+
+void wc_ERR_print_errors_fp(XFILE fp)
+{
+    WOLFSSL_ENTER("wc_ERR_print_errors_fp");
+
+    /* Send all errors to the wc_ERR_dump_to_file function */
+    wc_ERR_print_errors_cb(wc_ERR_dump_to_file, fp);
+}
+
+#endif /* !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) */
+
+#endif /* defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/md4.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/md4.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/md4.c	(revision 453)
@@ -0,0 +1,211 @@
+/* md4.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifndef NO_MD4
+
+#include <wolfssl/wolfcrypt/md4.h>
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+
+void wc_InitMd4(Md4* md4)
+{
+    md4->digest[0] = 0x67452301L;
+    md4->digest[1] = 0xefcdab89L;
+    md4->digest[2] = 0x98badcfeL;
+    md4->digest[3] = 0x10325476L;
+
+    md4->buffLen = 0;
+    md4->loLen   = 0;
+    md4->hiLen   = 0;
+}
+
+
+static void Transform(Md4* md4)
+{
+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+
+    /* Copy context->state[] to working vars  */
+    word32 A = md4->digest[0];
+    word32 B = md4->digest[1];
+    word32 C = md4->digest[2];
+    word32 D = md4->digest[3];
+
+#define function(a,b,c,d,k,s) a=rotlFixed(a+F(b,c,d)+md4->buffer[k],s);
+    function(A,B,C,D, 0, 3);
+    function(D,A,B,C, 1, 7);
+    function(C,D,A,B, 2,11);
+    function(B,C,D,A, 3,19);
+    function(A,B,C,D, 4, 3);
+    function(D,A,B,C, 5, 7);
+    function(C,D,A,B, 6,11);
+    function(B,C,D,A, 7,19);
+    function(A,B,C,D, 8, 3);
+    function(D,A,B,C, 9, 7);
+    function(C,D,A,B,10,11);
+    function(B,C,D,A,11,19);
+    function(A,B,C,D,12, 3);
+    function(D,A,B,C,13, 7);
+    function(C,D,A,B,14,11);
+    function(B,C,D,A,15,19);
+
+#undef function
+#define function(a,b,c,d,k,s) \
+    a=rotlFixed(a+G(b,c,d)+md4->buffer[k]+0x5a827999,s);
+
+    function(A,B,C,D, 0, 3);
+    function(D,A,B,C, 4, 5);
+    function(C,D,A,B, 8, 9);
+    function(B,C,D,A,12,13);
+    function(A,B,C,D, 1, 3);
+    function(D,A,B,C, 5, 5);
+    function(C,D,A,B, 9, 9);
+    function(B,C,D,A,13,13);
+    function(A,B,C,D, 2, 3);
+    function(D,A,B,C, 6, 5);
+    function(C,D,A,B,10, 9);
+    function(B,C,D,A,14,13);
+    function(A,B,C,D, 3, 3);
+    function(D,A,B,C, 7, 5);
+    function(C,D,A,B,11, 9);
+    function(B,C,D,A,15,13);
+
+#undef function
+#define function(a,b,c,d,k,s) \
+    a=rotlFixed(a+H(b,c,d)+md4->buffer[k]+0x6ed9eba1,s);
+
+    function(A,B,C,D, 0, 3);
+    function(D,A,B,C, 8, 9);
+    function(C,D,A,B, 4,11);
+    function(B,C,D,A,12,15);
+    function(A,B,C,D, 2, 3);
+    function(D,A,B,C,10, 9);
+    function(C,D,A,B, 6,11);
+    function(B,C,D,A,14,15);
+    function(A,B,C,D, 1, 3);
+    function(D,A,B,C, 9, 9);
+    function(C,D,A,B, 5,11);
+    function(B,C,D,A,13,15);
+    function(A,B,C,D, 3, 3);
+    function(D,A,B,C,11, 9);
+    function(C,D,A,B, 7,11);
+    function(B,C,D,A,15,15);
+
+    /* Add the working vars back into digest state[]  */
+    md4->digest[0] += A;
+    md4->digest[1] += B;
+    md4->digest[2] += C;
+    md4->digest[3] += D;
+}
+
+
+static WC_INLINE void AddLength(Md4* md4, word32 len)
+{
+    word32 tmp = md4->loLen;
+    if ( (md4->loLen += len) < tmp)
+        md4->hiLen++;                       /* carry low to high */
+}
+
+
+void wc_Md4Update(Md4* md4, const byte* data, word32 len)
+{
+    /* do block size increments */
+    byte* local = (byte*)md4->buffer;
+
+    while (len) {
+        word32 add = min(len, MD4_BLOCK_SIZE - md4->buffLen);
+        XMEMCPY(&local[md4->buffLen], data, add);
+
+        md4->buffLen += add;
+        data         += add;
+        len          -= add;
+
+        if (md4->buffLen == MD4_BLOCK_SIZE) {
+            #ifdef BIG_ENDIAN_ORDER
+                ByteReverseWords(md4->buffer, md4->buffer, MD4_BLOCK_SIZE);
+            #endif
+            Transform(md4);
+            AddLength(md4, MD4_BLOCK_SIZE);
+            md4->buffLen = 0;
+        }
+    }
+}
+
+
+void wc_Md4Final(Md4* md4, byte* hash)
+{
+    byte* local = (byte*)md4->buffer;
+
+    AddLength(md4, md4->buffLen);               /* before adding pads */
+
+    local[md4->buffLen++] = 0x80;  /* add 1 */
+
+    /* pad with zeros */
+    if (md4->buffLen > MD4_PAD_SIZE) {
+        XMEMSET(&local[md4->buffLen], 0, MD4_BLOCK_SIZE - md4->buffLen);
+        md4->buffLen += MD4_BLOCK_SIZE - md4->buffLen;
+
+        #ifdef BIG_ENDIAN_ORDER
+            ByteReverseWords(md4->buffer, md4->buffer, MD4_BLOCK_SIZE);
+        #endif
+        Transform(md4);
+        md4->buffLen = 0;
+    }
+    XMEMSET(&local[md4->buffLen], 0, MD4_PAD_SIZE - md4->buffLen);
+
+    /* put lengths in bits */
+    md4->hiLen = (md4->loLen >> (8*sizeof(md4->loLen) - 3)) +
+                 (md4->hiLen << 3);
+    md4->loLen = md4->loLen << 3;
+
+    /* store lengths */
+    #ifdef BIG_ENDIAN_ORDER
+        ByteReverseWords(md4->buffer, md4->buffer, MD4_BLOCK_SIZE);
+    #endif
+    /* ! length ordering dependent on digest endian type ! */
+    XMEMCPY(&local[MD4_PAD_SIZE], &md4->loLen, sizeof(word32));
+    XMEMCPY(&local[MD4_PAD_SIZE + sizeof(word32)], &md4->hiLen, sizeof(word32));
+
+    Transform(md4);
+    #ifdef BIG_ENDIAN_ORDER
+        ByteReverseWords(md4->digest, md4->digest, MD4_DIGEST_SIZE);
+    #endif
+    XMEMCPY(hash, md4->digest, MD4_DIGEST_SIZE);
+
+    wc_InitMd4(md4);  /* reset state */
+}
+
+
+#endif /* NO_MD4 */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/md5.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/md5.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/md5.c	(revision 453)
@@ -0,0 +1,572 @@
+/* md5.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#if !defined(NO_MD5)
+
+#if defined(WOLFSSL_TI_HASH)
+/* #include <wolfcrypt/src/port/ti/ti-hash.c> included by wc_port.c */
+
+#else
+
+#include <wolfssl/wolfcrypt/md5.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#include <wolfssl/wolfcrypt/logging.h>
+#include <wolfssl/wolfcrypt/hash.h>
+
+#ifdef NO_INLINE
+#include <wolfssl/wolfcrypt/misc.h>
+#else
+#define WOLFSSL_MISC_INCLUDED
+#include <wolfcrypt/src/misc.c>
+#endif
+
+
+/* Hardware Acceleration */
+#if defined(STM32_HASH)
+
+/* Supports CubeMX HAL or Standard Peripheral Library */
+#define HAVE_MD5_CUST_API
+
+int wc_InitMd5_ex(wc_Md5* md5, void* heap, int devId)
+{
+    if (md5 == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    (void)devId;
+    (void)heap;
+
+    wc_Stm32_Hash_Init(&md5->stmCtx);
+
+    return 0;
+}
+
+int wc_Md5Update(wc_Md5* md5, const byte* data, word32 len)
+{
+    int ret;
+
+    if (md5 == NULL || (data == NULL && len > 0)) {
+        return BAD_FUNC_ARG;
+    }
+
+    ret = wolfSSL_CryptHwMutexLock();
+    if (ret == 0) {
+        ret = wc_Stm32_Hash_Update(&md5->stmCtx, HASH_AlgoSelection_MD5,
+                                   data, len);
+        wolfSSL_CryptHwMutexUnLock();
+    }
+    return ret;
+}
+
+int wc_Md5Final(wc_Md5* md5, byte* hash)
+{
+    int ret;
+
+    if (md5 == NULL || hash == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    ret = wolfSSL_CryptHwMutexLock();
+    if (ret == 0) {
+        ret = wc_Stm32_Hash_Final(&md5->stmCtx, HASH_AlgoSelection_MD5,
+                                  hash, WC_MD5_DIGEST_SIZE);
+        wolfSSL_CryptHwMutexUnLock();
+    }
+
+    (void)wc_InitMd5(md5);  /* reset state */
+
+    return ret;
+}
+
+#elif defined(FREESCALE_MMCAU_SHA)
+
+#ifdef FREESCALE_MMCAU_CLASSIC_SHA
+    #include "cau_api.h"
+#else
+    #include "fsl_mmcau.h"
+#endif
+
+#define XTRANSFORM(S,B)       Transform((S), (B))
+#define XTRANSFORM_LEN(S,B,L) Transform_Len((S), (B), (L))
+
+#ifndef WC_HASH_DATA_ALIGNMENT
+    /* these hardware API's require 4 byte (word32) alignment */
+    #define WC_HASH_DATA_ALIGNMENT 4
+#endif
+
+static int Transform(wc_Md5* md5, const byte* data)
+{
+    int ret = wolfSSL_CryptHwMutexLock();
+    if (ret == 0) {
+#ifdef FREESCALE_MMCAU_CLASSIC_SHA
+        cau_md5_hash_n((byte*)data, 1, (unsigned char*)md5->digest);
+#else
+        MMCAU_MD5_HashN((byte*)data, 1, (uint32_t*)md5->digest);
+#endif
+        wolfSSL_CryptHwMutexUnLock();
+    }
+    return ret;
+}
+
+static int Transform_Len(wc_Md5* md5, const byte* data, word32 len)
+{
+    int ret = wolfSSL_CryptHwMutexLock();
+    if (ret == 0) {
+    #if defined(WC_HASH_DATA_ALIGNMENT) && WC_HASH_DATA_ALIGNMENT > 0
+        if ((size_t)data % WC_HASH_DATA_ALIGNMENT) {
+            /* data pointer is NOT aligned,
+             * so copy and perform one block at a time */
+            byte* local = (byte*)md5->buffer;
+            while (len >= WC_MD5_BLOCK_SIZE) {
+                XMEMCPY(local, data, WC_MD5_BLOCK_SIZE);
+            #ifdef FREESCALE_MMCAU_CLASSIC_SHA
+                cau_md5_hash_n(local, 1, (unsigned char*)md5->digest);
+            #else
+                MMCAU_MD5_HashN(local, 1, (uint32_t*)md5->digest);
+            #endif
+                data += WC_MD5_BLOCK_SIZE;
+                len  -= WC_MD5_BLOCK_SIZE;
+            }
+        }
+        else
+    #endif
+        {
+#ifdef FREESCALE_MMCAU_CLASSIC_SHA
+        cau_md5_hash_n((byte*)data, len / WC_MD5_BLOCK_SIZE,
+            (unsigned char*)md5->digest);
+#else
+        MMCAU_MD5_HashN((byte*)data, len / WC_MD5_BLOCK_SIZE,
+            (uint32_t*)md5->digest);
+#endif
+        }
+        wolfSSL_CryptHwMutexUnLock();
+    }
+    return ret;
+}
+
+#elif defined(WOLFSSL_PIC32MZ_HASH)
+#include <wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h>
+#define HAVE_MD5_CUST_API
+
+#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
+/* functions implemented in wolfcrypt/src/port/caam/caam_sha.c */
+#define HAVE_MD5_CUST_API
+#else
+#define NEED_SOFT_MD5
+#endif /* End Hardware Acceleration */
+
+#ifdef NEED_SOFT_MD5
+
+#define XTRANSFORM(S,B)  Transform((S),(B))
+
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+#define MD5STEP(f, w, x, y, z, data, s) \
+        w = rotlFixed(w + f(x, y, z) + data, s) + x
+
+static int Transform(wc_Md5* md5, const byte* data)
+{
+    word32* buffer = (word32*)data;
+    /* Copy context->state[] to working vars  */
+    word32 a = md5->digest[0];
+    word32 b = md5->digest[1];
+    word32 c = md5->digest[2];
+    word32 d = md5->digest[3];
+
+    MD5STEP(F1, a, b, c, d, buffer[0]  + 0xd76aa478,  7);
+    MD5STEP(F1, d, a, b, c, buffer[1]  + 0xe8c7b756, 12);
+    MD5STEP(F1, c, d, a, b, buffer[2]  + 0x242070db, 17);
+    MD5STEP(F1, b, c, d, a, buffer[3]  + 0xc1bdceee, 22);
+    MD5STEP(F1, a, b, c, d, buffer[4]  + 0xf57c0faf,  7);
+    MD5STEP(F1, d, a, b, c, buffer[5]  + 0x4787c62a, 12);
+    MD5STEP(F1, c, d, a, b, buffer[6]  + 0xa8304613, 17);
+    MD5STEP(F1, b, c, d, a, buffer[7]  + 0xfd469501, 22);
+    MD5STEP(F1, a, b, c, d, buffer[8]  + 0x698098d8,  7);
+    MD5STEP(F1, d, a, b, c, buffer[9]  + 0x8b44f7af, 12);
+    MD5STEP(F1, c, d, a, b, buffer[10] + 0xffff5bb1, 17);
+    MD5STEP(F1, b, c, d, a, buffer[11] + 0x895cd7be, 22);
+    MD5STEP(F1, a, b, c, d, buffer[12] + 0x6b901122,  7);
+    MD5STEP(F1, d, a, b, c, buffer[13] + 0xfd987193, 12);
+    MD5STEP(F1, c, d, a, b, buffer[14] + 0xa679438e, 17);
+    MD5STEP(F1, b, c, d, a, buffer[15] + 0x49b40821, 22);
+
+    MD5STEP(F2, a, b, c, d, buffer[1]  + 0xf61e2562,  5);
+    MD5STEP(F2, d, a, b, c, buffer[6]  + 0xc040b340,  9);
+    MD5STEP(F2, c, d, a, b, buffer[11] + 0x265e5a51, 14);
+    MD5STEP(F2, b, c, d, a, buffer[0]  + 0xe9b6c7aa, 20);
+    MD5STEP(F2, a, b, c, d, buffer[5]  + 0xd62f105d,  5);
+    MD5STEP(F2, d, a, b, c, buffer[10] + 0x02441453,  9);
+    MD5STEP(F2, c, d, a, b, buffer[15] + 0xd8a1e681, 14);
+    MD5STEP(F2, b, c, d, a, buffer[4]  + 0xe7d3fbc8, 20);
+    MD5STEP(F2, a, b, c, d, buffer[9]  + 0x21e1cde6,  5);
+    MD5STEP(F2, d, a, b, c, buffer[14] + 0xc33707d6,  9);
+    MD5STEP(F2, c, d, a, b, buffer[3]  + 0xf4d50d87, 14);
+    MD5STEP(F2, b, c, d, a, buffer[8]  + 0x455a14ed, 20);
+    MD5STEP(F2, a, b, c, d, buffer[13] + 0xa9e3e905,  5);
+    MD5STEP(F2, d, a, b, c, buffer[2]  + 0xfcefa3f8,  9);
+    MD5STEP(F2, c, d, a, b, buffer[7]  + 0x676f02d9, 14);
+    MD5STEP(F2, b, c, d, a, buffer[12] + 0x8d2a4c8a, 20);
+
+    MD5STEP(F3, a, b, c, d, buffer[5]  + 0xfffa3942,  4);
+    MD5STEP(F3, d, a, b, c, buffer[8]  + 0x8771f681, 11);
+    MD5STEP(F3, c, d, a, b, buffer[11] + 0x6d9d6122, 16);
+    MD5STEP(F3, b, c, d, a, buffer[14] + 0xfde5380c, 23);
+    MD5STEP(F3, a, b, c, d, buffer[1]  + 0xa4beea44,  4);
+    MD5STEP(F3, d, a, b, c, buffer[4]  + 0x4bdecfa9, 11);
+    MD5STEP(F3, c, d, a, b, buffer[7]  + 0xf6bb4b60, 16);
+    MD5STEP(F3, b, c, d, a, buffer[10] + 0xbebfbc70, 23);
+    MD5STEP(F3, a, b, c, d, buffer[13] + 0x289b7ec6,  4);
+    MD5STEP(F3, d, a, b, c, buffer[0]  + 0xeaa127fa, 11);
+    MD5STEP(F3, c, d, a, b, buffer[3]  + 0xd4ef3085, 16);
+    MD5STEP(F3, b, c, d, a, buffer[6]  + 0x04881d05, 23);
+    MD5STEP(F3, a, b, c, d, buffer[9]  + 0xd9d4d039,  4);
+    MD5STEP(F3, d, a, b, c, buffer[12] + 0xe6db99e5, 11);
+    MD5STEP(F3, c, d, a, b, buffer[15] + 0x1fa27cf8, 16);
+    MD5STEP(F3, b, c, d, a, buffer[2]  + 0xc4ac5665, 23);
+
+    MD5STEP(F4, a, b, c, d, buffer[0]  + 0xf4292244,  6);
+    MD5STEP(F4, d, a, b, c, buffer[7]  + 0x432aff97, 10);
+    MD5STEP(F4, c, d, a, b, buffer[14] + 0xab9423a7, 15);
+    MD5STEP(F4, b, c, d, a, buffer[5]  + 0xfc93a039, 21);
+    MD5STEP(F4, a, b, c, d, buffer[12] + 0x655b59c3,  6);
+    MD5STEP(F4, d, a, b, c, buffer[3]  + 0x8f0ccc92, 10);
+    MD5STEP(F4, c, d, a, b, buffer[10] + 0xffeff47d, 15);
+    MD5STEP(F4, b, c, d, a, buffer[1]  + 0x85845dd1, 21);
+    MD5STEP(F4, a, b, c, d, buffer[8]  + 0x6fa87e4f,  6);
+    MD5STEP(F4, d, a, b, c, buffer[15] + 0xfe2ce6e0, 10);
+    MD5STEP(F4, c, d, a, b, buffer[6]  + 0xa3014314, 15);
+    MD5STEP(F4, b, c, d, a, buffer[13] + 0x4e0811a1, 21);
+    MD5STEP(F4, a, b, c, d, buffer[4]  + 0xf7537e82,  6);
+    MD5STEP(F4, d, a, b, c, buffer[11] + 0xbd3af235, 10);
+    MD5STEP(F4, c, d, a, b, buffer[2]  + 0x2ad7d2bb, 15);
+    MD5STEP(F4, b, c, d, a, buffer[9]  + 0xeb86d391, 21);
+
+    /* Add the working vars back into digest state[]  */
+    md5->digest[0] += a;
+    md5->digest[1] += b;
+    md5->digest[2] += c;
+    md5->digest[3] += d;
+
+    return 0;
+}
+#endif /* NEED_SOFT_MD5 */
+
+#ifndef HAVE_MD5_CUST_API
+
+static WC_INLINE void AddLength(wc_Md5* md5, word32 len)
+{
+    word32 tmp = md5->loLen;
+    if ((md5->loLen += len) < tmp) {
+        md5->hiLen++;                       /* carry low to high */
+    }
+}
+
+static int _InitMd5(wc_Md5* md5)
+{
+    int ret = 0;
+
+    md5->digest[0] = 0x67452301L;
+    md5->digest[1] = 0xefcdab89L;
+    md5->digest[2] = 0x98badcfeL;
+    md5->digest[3] = 0x10325476L;
+
+    md5->buffLen = 0;
+    md5->loLen   = 0;
+    md5->hiLen   = 0;
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+    md5->flags = 0;
+#endif
+
+    return ret;
+}
+
+int wc_InitMd5_ex(wc_Md5* md5, void* heap, int devId)
+{
+    int ret = 0;
+
+    if (md5 == NULL)
+        return BAD_FUNC_ARG;
+
+    md5->heap = heap;
+
+    ret = _InitMd5(md5);
+    if (ret != 0)
+        return ret;
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5)
+    ret = wolfAsync_DevCtxInit(&md5->asyncDev, WOLFSSL_ASYNC_MARKER_MD5,
+                               md5->heap, devId);
+#else
+    (void)devId;
+#endif
+    return ret;
+}
+
+/* do block size increments/updates */
+int wc_Md5Update(wc_Md5* md5, const byte* data, word32 len)
+{
+    int ret = 0;
+    word32 blocksLen;
+    byte* local;
+
+    if (md5 == NULL || (data == NULL && len > 0)) {
+        return BAD_FUNC_ARG;
+    }
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5)
+    if (md5->asyncDev.marker == WOLFSSL_ASYNC_MARKER_MD5) {
+#if defined(HAVE_INTEL_QA)
+        return IntelQaSymMd5(&md5->asyncDev, NULL, data, len);
+#endif
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    /* check that internal buffLen is valid */
+    if (md5->buffLen >= WC_MD5_BLOCK_SIZE)
+        return BUFFER_E;
+
+    if (data == NULL && len == 0) {
+        /* valid, but do nothing */
+        return 0;
+    }
+
+    /* add length for final */
+    AddLength(md5, len);
+
+    local = (byte*)md5->buffer;
+
+    /* process any remainder from previous operation */
+    if (md5->buffLen > 0) {
+        blocksLen = min(len, WC_MD5_BLOCK_SIZE - md5->buffLen);
+        XMEMCPY(&local[md5->buffLen], data, blocksLen);
+
+        md5->buffLen += blocksLen;
+        data         += blocksLen;
+        len          -= blocksLen;
+
+        if (md5->buffLen == WC_MD5_BLOCK_SIZE) {
+        #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
+            ByteReverseWords(md5->buffer, md5->buffer, WC_MD5_BLOCK_SIZE);
+        #endif
+
+            ret = XTRANSFORM(md5, (const byte*)local);
+            if (ret != 0)
+                return ret;
+
+            md5->buffLen = 0;
+        }
+    }
+
+    /* process blocks */
+#ifdef XTRANSFORM_LEN
+    /* get number of blocks */
+    /* 64-1 = 0x3F (~ Inverted = 0xFFFFFFC0) */
+    /* len (masked by 0xFFFFFFC0) returns block aligned length */
+    blocksLen = len & ~(WC_MD5_BLOCK_SIZE-1);
+    if (blocksLen > 0) {
+        /* Byte reversal performed in function if required. */
+        XTRANSFORM_LEN(md5, data, blocksLen);
+        data += blocksLen;
+        len  -= blocksLen;
+    }
+#else
+    while (len >= WC_MD5_BLOCK_SIZE) {
+        word32* local32 = md5->buffer;
+        /* optimization to avoid memcpy if data pointer is properly aligned */
+        /* Big Endian requires byte swap, so can't use data directly */
+    #if defined(WC_HASH_DATA_ALIGNMENT) && !defined(BIG_ENDIAN_ORDER)
+        if (((size_t)data % WC_HASH_DATA_ALIGNMENT) == 0) {
+            local32 = (word32*)data;
+        }
+        else
+    #endif
+        {
+            XMEMCPY(local32, data, WC_MD5_BLOCK_SIZE);
+        }
+
+        data += WC_MD5_BLOCK_SIZE;
+        len  -= WC_MD5_BLOCK_SIZE;
+
+    #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
+        ByteReverseWords(local32, local32, WC_MD5_BLOCK_SIZE);
+    #endif
+
+        ret = XTRANSFORM(md5, (const byte*)local32);
+    }
+#endif /* XTRANSFORM_LEN */
+
+    /* save remainder */
+    if (len > 0) {
+        XMEMCPY(local, data, len);
+        md5->buffLen = len;
+    }
+
+    return ret;
+}
+
+int wc_Md5Final(wc_Md5* md5, byte* hash)
+{
+    byte* local;
+
+    if (md5 == NULL || hash == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5)
+    if (md5->asyncDev.marker == WOLFSSL_ASYNC_MARKER_MD5) {
+#if defined(HAVE_INTEL_QA)
+        return IntelQaSymMd5(&md5->asyncDev, hash, NULL, WC_MD5_DIGEST_SIZE);
+#endif
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    local = (byte*)md5->buffer;
+
+    local[md5->buffLen++] = 0x80;  /* add 1 */
+
+    /* pad with zeros */
+    if (md5->buffLen > WC_MD5_PAD_SIZE) {
+        XMEMSET(&local[md5->buffLen], 0, WC_MD5_BLOCK_SIZE - md5->buffLen);
+        md5->buffLen += WC_MD5_BLOCK_SIZE - md5->buffLen;
+
+#if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
+        ByteReverseWords(md5->buffer, md5->buffer, WC_MD5_BLOCK_SIZE);
+#endif
+        XTRANSFORM(md5, local);
+        md5->buffLen = 0;
+    }
+    XMEMSET(&local[md5->buffLen], 0, WC_MD5_PAD_SIZE - md5->buffLen);
+
+#if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
+    ByteReverseWords(md5->buffer, md5->buffer, WC_MD5_BLOCK_SIZE);
+#endif
+
+    /* put lengths in bits */
+    md5->hiLen = (md5->loLen >> (8 * sizeof(md5->loLen) - 3)) +
+                 (md5->hiLen << 3);
+    md5->loLen = md5->loLen << 3;
+
+    /* store lengths */
+    /* ! length ordering dependent on digest endian type ! */
+    XMEMCPY(&local[WC_MD5_PAD_SIZE], &md5->loLen, sizeof(word32));
+    XMEMCPY(&local[WC_MD5_PAD_SIZE + sizeof(word32)], &md5->hiLen, sizeof(word32));
+
+    /* final transform and result to hash */
+    XTRANSFORM(md5, local);
+#ifdef BIG_ENDIAN_ORDER
+    ByteReverseWords(md5->digest, md5->digest, WC_MD5_DIGEST_SIZE);
+#endif
+    XMEMCPY(hash, md5->digest, WC_MD5_DIGEST_SIZE);
+
+    return _InitMd5(md5); /* reset state */
+}
+#endif /* !HAVE_MD5_CUST_API */
+
+
+int wc_InitMd5(wc_Md5* md5)
+{
+    if (md5 == NULL) {
+        return BAD_FUNC_ARG;
+    }
+    return wc_InitMd5_ex(md5, NULL, INVALID_DEVID);
+}
+
+void wc_Md5Free(wc_Md5* md5)
+{
+    if (md5 == NULL)
+        return;
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5)
+    wolfAsync_DevCtxFree(&md5->asyncDev, WOLFSSL_ASYNC_MARKER_MD5);
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+#ifdef WOLFSSL_PIC32MZ_HASH
+    wc_Md5Pic32Free(md5);
+#endif
+}
+
+int wc_Md5GetHash(wc_Md5* md5, byte* hash)
+{
+    int ret;
+    wc_Md5 tmpMd5;
+
+    if (md5 == NULL || hash == NULL)
+        return BAD_FUNC_ARG;
+
+    ret = wc_Md5Copy(md5, &tmpMd5);
+    if (ret == 0) {
+        ret = wc_Md5Final(&tmpMd5, hash);
+    }
+
+    return ret;
+}
+
+int wc_Md5Copy(wc_Md5* src, wc_Md5* dst)
+{
+    int ret = 0;
+
+    if (src == NULL || dst == NULL)
+        return BAD_FUNC_ARG;
+
+    XMEMCPY(dst, src, sizeof(wc_Md5));
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev);
+#endif
+#ifdef WOLFSSL_PIC32MZ_HASH
+    ret = wc_Pic32HashCopy(&src->cache, &dst->cache);
+#endif
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+    dst->flags |= WC_HASH_FLAG_ISCOPY;
+#endif
+
+    return ret;
+}
+
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+int wc_Md5SetFlags(wc_Md5* md5, word32 flags)
+{
+    if (md5) {
+        md5->flags = flags;
+    }
+    return 0;
+}
+int wc_Md5GetFlags(wc_Md5* md5, word32* flags)
+{
+    if (md5 && flags) {
+        *flags = md5->flags;
+    }
+    return 0;
+}
+#endif
+
+#endif /* WOLFSSL_TI_HASH */
+#endif /* NO_MD5 */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/memory.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/memory.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/memory.c	(revision 453)
@@ -0,0 +1,1126 @@
+/* memory.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+/* check old macros @wc_fips */
+#if defined(USE_CYASSL_MEMORY) && !defined(USE_WOLFSSL_MEMORY)
+    #define USE_WOLFSSL_MEMORY
+#endif
+#if defined(CYASSL_MALLOC_CHECK) && !defined(WOLFSSL_MALLOC_CHECK)
+    #define WOLFSSL_MALLOC_CHECK
+#endif
+
+
+/*
+Possible memory options:
+ * NO_WOLFSSL_MEMORY:               Disables wolf memory callback support. When not defined settings.h defines USE_WOLFSSL_MEMORY.
+ * WOLFSSL_STATIC_MEMORY:           Turns on the use of static memory buffers and functions.
+                                        This allows for using static memory instead of dynamic.
+ * WOLFSSL_STATIC_ALIGN:            Define defaults to 16 to indicate static memory alignment.
+ * HAVE_IO_POOL:                    Enables use of static thread safe memory pool for input/output buffers.
+ * XMALLOC_OVERRIDE:                Allows override of the XMALLOC, XFREE and XREALLOC macros.
+ * XMALLOC_USER:                    Allows custom XMALLOC, XFREE and XREALLOC functions to be defined.
+ * WOLFSSL_NO_MALLOC:               Disables the fall-back case to use STDIO malloc/free when no callbacks are set.
+ * WOLFSSL_TRACK_MEMORY:            Enables memory tracking for total stats and list of allocated memory.
+ * WOLFSSL_DEBUG_MEMORY:            Enables extra function and line number args for memory callbacks.
+ * WOLFSSL_DEBUG_MEMORY_PRINT:      Enables printing of each malloc/free.
+ * WOLFSSL_MALLOC_CHECK:            Reports malloc or alignment failure using WOLFSSL_STATIC_ALIGN
+ * WOLFSSL_FORCE_MALLOC_FAIL_TEST:  Used for internal testing to induce random malloc failures.
+ * WOLFSSL_HEAP_TEST:               Used for internal testing of heap hint
+ */
+
+#ifdef WOLFSSL_ZEPHYR
+#undef realloc
+void *z_realloc(void *ptr, size_t size)
+{
+    if (ptr == NULL)
+        ptr = malloc(size);
+    else
+        ptr = realloc(ptr, size);
+
+    return ptr;
+}
+#define realloc z_realloc
+#endif
+
+#ifdef USE_WOLFSSL_MEMORY
+
+#include <wolfssl/wolfcrypt/memory.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#include <wolfssl/wolfcrypt/logging.h>
+
+#if defined(WOLFSSL_DEBUG_MEMORY) && defined(WOLFSSL_DEBUG_MEMORY_PRINT)
+#include <stdio.h>
+#endif
+
+#ifdef WOLFSSL_FORCE_MALLOC_FAIL_TEST
+    static int gMemFailCountSeed;
+    static int gMemFailCount;
+    void wolfSSL_SetMemFailCount(int memFailCount)
+    {
+        if (gMemFailCountSeed == 0) {
+            gMemFailCountSeed = memFailCount;
+            gMemFailCount = memFailCount;
+        }
+    }
+#endif
+#if defined(WOLFSSL_MALLOC_CHECK) || defined(WOLFSSL_TRACK_MEMORY_FULL) || \
+                                                     defined(WOLFSSL_MEMORY_LOG)
+    #include <stdio.h>
+#endif
+
+
+/* Set these to default values initially. */
+static wolfSSL_Malloc_cb  malloc_function = NULL;
+static wolfSSL_Free_cb    free_function = NULL;
+static wolfSSL_Realloc_cb realloc_function = NULL;
+
+int wolfSSL_SetAllocators(wolfSSL_Malloc_cb  mf,
+                          wolfSSL_Free_cb    ff,
+                          wolfSSL_Realloc_cb rf)
+{
+    malloc_function = mf;
+    free_function = ff;
+    realloc_function = rf;
+    return 0;
+}
+
+int wolfSSL_GetAllocators(wolfSSL_Malloc_cb*  mf,
+                          wolfSSL_Free_cb*    ff,
+                          wolfSSL_Realloc_cb* rf)
+{
+    if (mf) *mf = malloc_function;
+    if (ff) *ff = free_function;
+    if (rf) *rf = realloc_function;
+    return 0;
+}
+
+#ifndef WOLFSSL_STATIC_MEMORY
+#ifdef WOLFSSL_DEBUG_MEMORY
+void* wolfSSL_Malloc(size_t size, const char* func, unsigned int line)
+#else
+void* wolfSSL_Malloc(size_t size)
+#endif
+{
+    void* res = 0;
+
+    if (malloc_function) {
+    #ifdef WOLFSSL_DEBUG_MEMORY
+        res = malloc_function(size, func, line);
+    #else
+        res = malloc_function(size);
+    #endif
+    }
+    else {
+    #ifndef WOLFSSL_NO_MALLOC
+        res = malloc(size);
+    #else
+        WOLFSSL_MSG("No malloc available");
+    #endif
+    }
+
+#ifdef WOLFSSL_DEBUG_MEMORY
+#if defined(WOLFSSL_DEBUG_MEMORY_PRINT) && !defined(WOLFSSL_TRACK_MEMORY)
+    printf("Alloc: %p -> %u at %s:%d\n", res, (word32)size, func, line);
+#else
+    (void)func;
+    (void)line;
+#endif
+#endif
+
+#ifdef WOLFSSL_MALLOC_CHECK
+    if (res == NULL)
+        WOLFSSL_MSG("wolfSSL_malloc failed");
+#endif
+
+#ifdef WOLFSSL_FORCE_MALLOC_FAIL_TEST
+    if (res && --gMemFailCount == 0) {
+        printf("\n---FORCED MEM FAIL TEST---\n");
+        if (free_function) {
+        #ifdef WOLFSSL_DEBUG_MEMORY
+            free_function(res, func, line);
+        #else
+            free_function(res);
+        #endif
+        }
+        else {
+            free(res); /* clear */
+        }
+        gMemFailCount = gMemFailCountSeed; /* reset */
+        return NULL;
+    }
+#endif
+
+    return res;
+}
+
+#ifdef WOLFSSL_DEBUG_MEMORY
+void wolfSSL_Free(void *ptr, const char* func, unsigned int line)
+#else
+void wolfSSL_Free(void *ptr)
+#endif
+{
+#ifdef WOLFSSL_DEBUG_MEMORY
+#if defined(WOLFSSL_DEBUG_MEMORY_PRINT) && !defined(WOLFSSL_TRACK_MEMORY)
+    printf("Free: %p at %s:%d\n", ptr, func, line);
+#else
+    (void)func;
+    (void)line;
+#endif
+#endif
+
+    if (free_function) {
+    #ifdef WOLFSSL_DEBUG_MEMORY
+        free_function(ptr, func, line);
+    #else
+        free_function(ptr);
+    #endif
+    }
+    else {
+    #ifndef WOLFSSL_NO_MALLOC
+        free(ptr);
+    #else
+        WOLFSSL_MSG("No free available");
+    #endif
+    }
+}
+
+#ifdef WOLFSSL_DEBUG_MEMORY
+void* wolfSSL_Realloc(void *ptr, size_t size, const char* func, unsigned int line)
+#else
+void* wolfSSL_Realloc(void *ptr, size_t size)
+#endif
+{
+    void* res = 0;
+
+    if (realloc_function) {
+    #ifdef WOLFSSL_DEBUG_MEMORY
+        res = realloc_function(ptr, size, func, line);
+    #else
+        res = realloc_function(ptr, size);
+    #endif
+    }
+    else {
+    #ifndef WOLFSSL_NO_MALLOC
+        res = realloc(ptr, size);
+    #else
+        WOLFSSL_MSG("No realloc available");
+    #endif
+    }
+
+    return res;
+}
+#endif /* WOLFSSL_STATIC_MEMORY */
+
+#ifdef WOLFSSL_STATIC_MEMORY
+
+struct wc_Memory {
+    byte*  buffer;
+    struct wc_Memory* next;
+    word32 sz;
+};
+
+
+/* returns amount of memory used on success. On error returns negative value
+   wc_Memory** list is the list that new buckets are prepended to
+ */
+static int create_memory_buckets(byte* buffer, word32 bufSz,
+                              word32 buckSz, word32 buckNum, wc_Memory** list) {
+    word32 i;
+    byte*  pt  = buffer;
+    int    ret = 0;
+    word32 memSz = (word32)sizeof(wc_Memory);
+    word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
+
+    /* if not enough space available for bucket size then do not try */
+    if (buckSz + memSz + padSz > bufSz) {
+        return ret;
+    }
+
+    for (i = 0; i < buckNum; i++) {
+        if ((buckSz + memSz + padSz) <= (bufSz - ret)) {
+            /* create a new struct and set its values */
+            wc_Memory* mem = (struct wc_Memory*)(pt);
+            mem->sz = buckSz;
+            mem->buffer = (byte*)pt + padSz + memSz;
+            mem->next = NULL;
+
+            /* add the newly created struct to front of list */
+            if (*list == NULL) {
+                *list = mem;
+            } else {
+                mem->next = *list;
+                *list = mem;
+            }
+
+            /* advance pointer and keep track of memory used */
+            ret += buckSz + padSz + memSz;
+            pt  += buckSz + padSz + memSz;
+        }
+        else {
+            break; /* not enough space left for more buckets of this size */
+        }
+    }
+
+    return ret;
+}
+
+int wolfSSL_init_memory_heap(WOLFSSL_HEAP* heap)
+{
+    word32 wc_MemSz[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_BUCKETS };
+    word32 wc_Dist[WOLFMEM_DEF_BUCKETS]  = { WOLFMEM_DIST };
+
+    if (heap == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    XMEMSET(heap, 0, sizeof(WOLFSSL_HEAP));
+
+    XMEMCPY(heap->sizeList, wc_MemSz, sizeof(wc_MemSz));
+    XMEMCPY(heap->distList, wc_Dist,  sizeof(wc_Dist));
+
+    if (wc_InitMutex(&(heap->memory_mutex)) != 0) {
+        WOLFSSL_MSG("Error creating heap memory mutex");
+        return BAD_MUTEX_E;
+    }
+
+    return 0;
+}
+
+int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint,
+    unsigned char* buf, unsigned int sz, int flag, int max)
+{
+    int ret;
+    WOLFSSL_HEAP*      heap;
+    WOLFSSL_HEAP_HINT* hint;
+    word32 idx = 0;
+
+    if (pHint == NULL || buf == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if ((sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT)) > sz - idx) {
+        return BUFFER_E; /* not enough memory for structures */
+    }
+
+    /* check if hint has already been assigned */
+    if (*pHint == NULL) {
+        heap = (WOLFSSL_HEAP*)buf;
+        idx += sizeof(WOLFSSL_HEAP);
+        hint = (WOLFSSL_HEAP_HINT*)(buf + idx);
+        idx += sizeof(WOLFSSL_HEAP_HINT);
+
+        ret = wolfSSL_init_memory_heap(heap);
+        if (ret != 0) {
+            return ret;
+        }
+
+        XMEMSET(hint, 0, sizeof(WOLFSSL_HEAP_HINT));
+        hint->memory = heap;
+    }
+    else {
+    #ifdef WOLFSSL_HEAP_TEST
+        /* do not load in memory if test has been set */
+        if (heap == (void*)WOLFSSL_HEAP_TEST) {
+            return 0;
+        }
+    #endif
+
+        hint = (WOLFSSL_HEAP_HINT*)(*pHint);
+        heap = hint->memory;
+    }
+
+    ret = wolfSSL_load_static_memory(buf + idx, sz - idx, flag, heap);
+    if (ret != 1) {
+        WOLFSSL_MSG("Error partitioning memory");
+        return -1;
+    }
+
+    /* determine what max applies too */
+    if ((flag & WOLFMEM_IO_POOL) || (flag & WOLFMEM_IO_POOL_FIXED)) {
+        heap->maxIO = max;
+    }
+    else { /* general memory used in handshakes */
+        heap->maxHa = max;
+    }
+
+    heap->flag |= flag;
+    *pHint = hint;
+
+    (void)max;
+
+    return 0;
+}
+
+int wolfSSL_load_static_memory(byte* buffer, word32 sz, int flag,
+                                                             WOLFSSL_HEAP* heap)
+{
+    word32 ava = sz;
+    byte*  pt  = buffer;
+    int    ret = 0;
+    word32 memSz = (word32)sizeof(wc_Memory);
+    word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
+
+    WOLFSSL_ENTER("wolfSSL_load_static_memory");
+
+    if (buffer == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* align pt */
+    while ((wolfssl_word)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) {
+        *pt = 0x00;
+        pt++;
+        ava--;
+    }
+
+#ifdef WOLFSSL_DEBUG_MEMORY
+    printf("Allocated %d bytes for static memory @ %p\n", ava, pt);
+#endif
+
+    /* divide into chunks of memory and add them to available list */
+    while (ava >= (heap->sizeList[0] + padSz + memSz)) {
+        int i;
+        /* creating only IO buffers from memory passed in, max TLS is 16k */
+        if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) {
+            if ((ret = create_memory_buckets(pt, ava,
+                                          WOLFMEM_IO_SZ, 1, &(heap->io))) < 0) {
+                WOLFSSL_LEAVE("wolfSSL_load_static_memory", ret);
+                return ret;
+            }
+
+            /* check if no more room left for creating IO buffers */
+            if (ret == 0) {
+                break;
+            }
+
+            /* advance pointer in buffer for next buckets and keep track
+               of how much memory is left available */
+            pt  += ret;
+            ava -= ret;
+        }
+        else {
+            /* start at largest and move to smaller buckets */
+            for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) {
+                if ((heap->sizeList[i] + padSz + memSz) <= ava) {
+                    if ((ret = create_memory_buckets(pt, ava, heap->sizeList[i],
+                                     heap->distList[i], &(heap->ava[i]))) < 0) {
+                        WOLFSSL_LEAVE("wolfSSL_load_static_memory", ret);
+                        return ret;
+                    }
+
+                    /* advance pointer in buffer for next buckets and keep track
+                       of how much memory is left available */
+                    pt  += ret;
+                    ava -= ret;
+                }
+            }
+        }
+    }
+
+    return 1;
+}
+
+
+/* returns the size of management memory needed for each bucket.
+ * This is memory that is used to keep track of and align memory buckets. */
+int wolfSSL_MemoryPaddingSz(void)
+{
+    word32 memSz = (word32)sizeof(wc_Memory);
+    word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
+    return memSz + padSz;
+}
+
+
+/* Used to calculate memory size for optimum use with buckets.
+   returns the suggested size rounded down to the nearest bucket. */
+int wolfSSL_StaticBufferSz(byte* buffer, word32 sz, int flag)
+{
+    word32 bucketSz[WOLFMEM_MAX_BUCKETS] = {WOLFMEM_BUCKETS};
+    word32 distList[WOLFMEM_MAX_BUCKETS] = {WOLFMEM_DIST};
+
+    word32 ava = sz;
+    byte*  pt  = buffer;
+    word32 memSz = (word32)sizeof(wc_Memory);
+    word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
+
+    WOLFSSL_ENTER("wolfSSL_static_size");
+
+    if (buffer == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* align pt */
+    while ((wolfssl_word)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) {
+        pt++;
+        ava--;
+    }
+
+    /* creating only IO buffers from memory passed in, max TLS is 16k */
+    if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) {
+        if (ava < (memSz + padSz + WOLFMEM_IO_SZ)) {
+            return 0; /* not enough room for even one bucket */
+        }
+
+        ava = ava % (memSz + padSz + WOLFMEM_IO_SZ);
+    }
+    else {
+        int i, k;
+
+        if (ava < (bucketSz[0] + padSz + memSz)) {
+            return 0; /* not enough room for even one bucket */
+        }
+
+        while ((ava >= (bucketSz[0] + padSz + memSz)) && (ava > 0)) {
+            /* start at largest and move to smaller buckets */
+            for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) {
+                for (k = distList[i]; k > 0; k--) {
+                    if ((bucketSz[i] + padSz + memSz) <= ava) {
+                        ava -= bucketSz[i] + padSz + memSz;
+                    }
+                }
+            }
+        }
+    }
+
+    return sz - ava; /* round down */
+}
+
+
+int FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io)
+{
+    WOLFSSL_MSG("Freeing fixed IO buffer");
+
+    /* check if fixed buffer was set */
+    if (*io == NULL) {
+        return 1;
+    }
+
+    if (heap == NULL) {
+        WOLFSSL_MSG("No heap to return fixed IO too");
+    }
+    else {
+        /* put IO buffer back into IO pool */
+        (*io)->next = heap->io;
+        heap->io    = *io;
+        *io         = NULL;
+    }
+
+    return 1;
+}
+
+
+int SetFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io)
+{
+    WOLFSSL_MSG("Setting fixed IO for SSL");
+    if (heap == NULL) {
+        return MEMORY_E;
+    }
+
+    *io = heap->io;
+
+    if (*io != NULL) {
+        heap->io = (*io)->next;
+        (*io)->next = NULL;
+    }
+    else { /* failed to grab an IO buffer */
+        return 0;
+    }
+
+    return 1;
+}
+
+
+int wolfSSL_GetMemStats(WOLFSSL_HEAP* heap, WOLFSSL_MEM_STATS* stats)
+{
+        word32     i;
+        wc_Memory* pt;
+
+        XMEMSET(stats, 0, sizeof(WOLFSSL_MEM_STATS));
+
+        stats->totalAlloc = heap->alloc;
+        stats->totalFr    = heap->frAlc;
+        stats->curAlloc   = stats->totalAlloc - stats->totalFr;
+        stats->maxHa      = heap->maxHa;
+        stats->maxIO      = heap->maxIO;
+        for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
+            stats->blockSz[i] = heap->sizeList[i];
+            for (pt = heap->ava[i]; pt != NULL; pt = pt->next) {
+                stats->avaBlock[i] += 1;
+            }
+        }
+
+        for (pt = heap->io; pt != NULL; pt = pt->next) {
+            stats->avaIO++;
+        }
+
+        stats->flag       = heap->flag; /* flag used */
+
+    return 1;
+}
+
+
+#ifdef WOLFSSL_DEBUG_MEMORY
+void* wolfSSL_Malloc(size_t size, void* heap, int type, const char* func, unsigned int line)
+#else
+void* wolfSSL_Malloc(size_t size, void* heap, int type)
+#endif
+{
+    void* res = 0;
+    wc_Memory* pt = NULL;
+    int   i;
+
+    /* check for testing heap hint was set */
+#ifdef WOLFSSL_HEAP_TEST
+    if (heap == (void*)WOLFSSL_HEAP_TEST) {
+        return malloc(size);
+    }
+#endif
+
+    /* if no heap hint then use dynamic memory*/
+    if (heap == NULL) {
+        #ifdef WOLFSSL_HEAP_TEST
+            /* allow using malloc for creating ctx and method */
+            if (type == DYNAMIC_TYPE_CTX || type == DYNAMIC_TYPE_METHOD ||
+                                            type == DYNAMIC_TYPE_CERT_MANAGER) {
+                WOLFSSL_MSG("ERROR allowing null heap hint for ctx/method\n");
+                res = malloc(size);
+            }
+            else {
+                WOLFSSL_MSG("ERROR null heap hint passed into XMALLOC\n");
+                res = NULL;
+            }
+        #else
+        #ifndef WOLFSSL_NO_MALLOC
+            #ifdef FREERTOS
+                res = pvPortMalloc(size);
+            #else
+                res = malloc(size);
+            #endif
+        #else
+            WOLFSSL_MSG("No heap hint found to use and no malloc");
+            #ifdef WOLFSSL_DEBUG_MEMORY
+            printf("ERROR: at %s:%d\n", func, line);
+            #endif
+        #endif /* WOLFSSL_NO_MALLOC */
+        #endif /* WOLFSSL_HEAP_TEST */
+    }
+    else {
+        WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap;
+        WOLFSSL_HEAP*      mem  = hint->memory;
+
+        if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
+            WOLFSSL_MSG("Bad memory_mutex lock");
+            return NULL;
+        }
+
+        /* case of using fixed IO buffers */
+        if (mem->flag & WOLFMEM_IO_POOL_FIXED &&
+                                             (type == DYNAMIC_TYPE_OUT_BUFFER ||
+                                              type == DYNAMIC_TYPE_IN_BUFFER)) {
+            if (type == DYNAMIC_TYPE_OUT_BUFFER) {
+                pt = hint->outBuf;
+            }
+            if (type == DYNAMIC_TYPE_IN_BUFFER) {
+                pt = hint->inBuf;
+            }
+        }
+        else {
+            /* check if using IO pool flag */
+            if (mem->flag & WOLFMEM_IO_POOL &&
+                                             (type == DYNAMIC_TYPE_OUT_BUFFER ||
+                                              type == DYNAMIC_TYPE_IN_BUFFER)) {
+                if (mem->io != NULL) {
+                    pt      = mem->io;
+                    mem->io = pt->next;
+                }
+            }
+
+            /* general static memory */
+            if (pt == NULL) {
+                for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
+                    if ((word32)size < mem->sizeList[i]) {
+                        if (mem->ava[i] != NULL) {
+                            pt = mem->ava[i];
+                            mem->ava[i] = pt->next;
+                            break;
+                        }
+                    #ifdef WOLFSSL_DEBUG_STATIC_MEMORY
+                        else {
+                            printf("Size: %ld, Empty: %d\n", size,
+                                                              mem->sizeList[i]);
+                        }
+                    #endif
+                    }
+                }
+            }
+        }
+
+        if (pt != NULL) {
+            mem->inUse += pt->sz;
+            mem->alloc += 1;
+            res = pt->buffer;
+
+        #ifdef WOLFSSL_DEBUG_MEMORY
+            printf("Alloc: %p -> %u at %s:%d\n", pt->buffer, pt->sz, func, line);
+        #endif
+
+            /* keep track of connection statistics if flag is set */
+            if (mem->flag & WOLFMEM_TRACK_STATS) {
+                WOLFSSL_MEM_CONN_STATS* stats = hint->stats;
+                if (stats != NULL) {
+                    stats->curMem += pt->sz;
+                    if (stats->peakMem < stats->curMem) {
+                        stats->peakMem = stats->curMem;
+                    }
+                    stats->curAlloc++;
+                    if (stats->peakAlloc < stats->curAlloc) {
+                        stats->peakAlloc = stats->curAlloc;
+                    }
+                    stats->totalAlloc++;
+                }
+            }
+        }
+        else {
+            WOLFSSL_MSG("ERROR ran out of static memory");
+            #ifdef WOLFSSL_DEBUG_MEMORY
+            printf("Looking for %lu bytes at %s:%d\n", size, func, line);
+            #endif
+        }
+
+        wc_UnLockMutex(&(mem->memory_mutex));
+    }
+
+    #ifdef WOLFSSL_MALLOC_CHECK
+        if ((wolfssl_word)res % WOLFSSL_STATIC_ALIGN) {
+            WOLFSSL_MSG("ERROR memory is not aligned");
+            res = NULL;
+        }
+    #endif
+
+
+    (void)i;
+    (void)pt;
+    (void)type;
+
+    return res;
+}
+
+
+#ifdef WOLFSSL_DEBUG_MEMORY
+void wolfSSL_Free(void *ptr, void* heap, int type, const char* func, unsigned int line)
+#else
+void wolfSSL_Free(void *ptr, void* heap, int type)
+#endif
+{
+    int i;
+    wc_Memory* pt;
+
+    if (ptr) {
+        /* check for testing heap hint was set */
+    #ifdef WOLFSSL_HEAP_TEST
+        if (heap == (void*)WOLFSSL_HEAP_TEST) {
+            return free(ptr);
+        }
+    #endif
+
+        if (heap == NULL) {
+        #ifdef WOLFSSL_HEAP_TEST
+            /* allow using malloc for creating ctx and method */
+            if (type == DYNAMIC_TYPE_CTX || type == DYNAMIC_TYPE_METHOD ||
+                                            type == DYNAMIC_TYPE_CERT_MANAGER) {
+                WOLFSSL_MSG("ERROR allowing null heap hint for ctx/method\n");
+            }
+            else {
+                WOLFSSL_MSG("ERROR null heap hint passed into XFREE\n");
+            }
+        #endif
+        #ifndef WOLFSSL_NO_MALLOC
+            #ifdef FREERTOS
+                vPortFree(ptr);
+            #else
+                free(ptr);
+            #endif
+        #else
+            WOLFSSL_MSG("Error trying to call free when turned off");
+        #endif /* WOLFSSL_NO_MALLOC */
+        }
+        else {
+            WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap;
+            WOLFSSL_HEAP*      mem  = hint->memory;
+            word32 padSz = -(int)sizeof(wc_Memory) & (WOLFSSL_STATIC_ALIGN - 1);
+
+            /* get memory struct and add it to available list */
+            pt = (wc_Memory*)((byte*)ptr - sizeof(wc_Memory) - padSz);
+            if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
+                WOLFSSL_MSG("Bad memory_mutex lock");
+                return;
+            }
+
+            /* case of using fixed IO buffers */
+            if (mem->flag & WOLFMEM_IO_POOL_FIXED &&
+                                             (type == DYNAMIC_TYPE_OUT_BUFFER ||
+                                              type == DYNAMIC_TYPE_IN_BUFFER)) {
+                /* fixed IO pools are free'd at the end of SSL lifetime
+                   using FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io) */
+            }
+            else if (mem->flag & WOLFMEM_IO_POOL && pt->sz == WOLFMEM_IO_SZ &&
+                                             (type == DYNAMIC_TYPE_OUT_BUFFER ||
+                                              type == DYNAMIC_TYPE_IN_BUFFER)) {
+                pt->next = mem->io;
+                mem->io  = pt;
+            }
+            else { /* general memory free */
+                for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
+                    if (pt->sz == mem->sizeList[i]) {
+                        pt->next = mem->ava[i];
+                        mem->ava[i] = pt;
+                        break;
+                    }
+                }
+            }
+            mem->inUse -= pt->sz;
+            mem->frAlc += 1;
+
+        #ifdef WOLFSSL_DEBUG_MEMORY
+            printf("Free: %p -> %u at %s:%d\n", pt->buffer, pt->sz, func, line);
+        #endif
+
+            /* keep track of connection statistics if flag is set */
+            if (mem->flag & WOLFMEM_TRACK_STATS) {
+                WOLFSSL_MEM_CONN_STATS* stats = hint->stats;
+                if (stats != NULL) {
+                    /* avoid under flow */
+                    if (stats->curMem > pt->sz) {
+                        stats->curMem -= pt->sz;
+                    }
+                    else {
+                        stats->curMem = 0;
+                    }
+
+                    if (stats->curAlloc > 0) {
+                        stats->curAlloc--;
+                    }
+                    stats->totalFr++;
+                }
+            }
+            wc_UnLockMutex(&(mem->memory_mutex));
+        }
+    }
+
+    (void)i;
+    (void)pt;
+    (void)type;
+}
+
+#ifdef WOLFSSL_DEBUG_MEMORY
+void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type, const char* func, unsigned int line)
+#else
+void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type)
+#endif
+{
+    void* res = 0;
+    wc_Memory* pt = NULL;
+    word32 prvSz;
+    int    i;
+
+    /* check for testing heap hint was set */
+#ifdef WOLFSSL_HEAP_TEST
+    if (heap == (void*)WOLFSSL_HEAP_TEST) {
+        return realloc(ptr, size);
+    }
+#endif
+
+    if (heap == NULL) {
+        #ifdef WOLFSSL_HEAP_TEST
+            WOLFSSL_MSG("ERROR null heap hint passed in to XREALLOC\n");
+        #endif
+        #ifndef WOLFSSL_NO_MALLOC
+            res = realloc(ptr, size);
+        #else
+            WOLFSSL_MSG("NO heap found to use for realloc");
+        #endif /* WOLFSSL_NO_MALLOC */
+    }
+    else {
+        WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap;
+        WOLFSSL_HEAP*      mem  = hint->memory;
+        word32 padSz = -(int)sizeof(wc_Memory) & (WOLFSSL_STATIC_ALIGN - 1);
+
+        if (ptr == NULL) {
+        #ifdef WOLFSSL_DEBUG_MEMORY
+            return wolfSSL_Malloc(size, heap, type, func, line);
+        #else
+            return wolfSSL_Malloc(size, heap, type);
+        #endif
+        }
+
+        if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
+            WOLFSSL_MSG("Bad memory_mutex lock");
+            return NULL;
+        }
+
+        /* case of using fixed IO buffers or IO pool */
+        if (((mem->flag & WOLFMEM_IO_POOL)||(mem->flag & WOLFMEM_IO_POOL_FIXED))
+                                          && (type == DYNAMIC_TYPE_OUT_BUFFER ||
+                                              type == DYNAMIC_TYPE_IN_BUFFER)) {
+            /* no realloc, is fixed size */
+            pt = (wc_Memory*)((byte*)ptr - padSz - sizeof(wc_Memory));
+            if (pt->sz < size) {
+                WOLFSSL_MSG("Error IO memory was not large enough");
+                res = NULL; /* return NULL in error case */
+            }
+            res = pt->buffer;
+        }
+        else {
+        /* general memory */
+            for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
+                if ((word32)size < mem->sizeList[i]) {
+                    if (mem->ava[i] != NULL) {
+                        pt = mem->ava[i];
+                        mem->ava[i] = pt->next;
+                        break;
+                    }
+                }
+            }
+
+            if (pt != NULL && res == NULL) {
+                res = pt->buffer;
+
+                /* copy over original information and free ptr */
+                prvSz = ((wc_Memory*)((byte*)ptr - padSz -
+                                               sizeof(wc_Memory)))->sz;
+                prvSz = (prvSz > pt->sz)? pt->sz: prvSz;
+                XMEMCPY(pt->buffer, ptr, prvSz);
+                mem->inUse += pt->sz;
+                mem->alloc += 1;
+
+                /* free memory that was previously being used */
+                wc_UnLockMutex(&(mem->memory_mutex));
+                wolfSSL_Free(ptr, heap, type
+            #ifdef WOLFSSL_DEBUG_MEMORY
+                    , func, line
+            #endif
+                );
+                if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
+                    WOLFSSL_MSG("Bad memory_mutex lock");
+                    return NULL;
+                }
+            }
+        }
+        wc_UnLockMutex(&(mem->memory_mutex));
+    }
+
+    #ifdef WOLFSSL_MALLOC_CHECK
+        if ((wolfssl_word)res % WOLFSSL_STATIC_ALIGN) {
+            WOLFSSL_MSG("ERROR memory is not aligned");
+            res = NULL;
+        }
+    #endif
+
+    (void)i;
+    (void)pt;
+    (void)type;
+
+    return res;
+}
+#endif /* WOLFSSL_STATIC_MEMORY */
+
+#endif /* USE_WOLFSSL_MEMORY */
+
+
+#ifdef HAVE_IO_POOL
+
+/* Example for user io pool, shared build may need definitions in lib proper */
+
+#include <wolfssl/wolfcrypt/types.h>
+#include <stdlib.h>
+
+#ifndef HAVE_THREAD_LS
+    #error "Oops, simple I/O pool example needs thread local storage"
+#endif
+
+
+/* allow simple per thread in and out pools */
+/* use 17k size since max record size is 16k plus overhead */
+static THREAD_LS_T byte pool_in[17*1024];
+static THREAD_LS_T byte pool_out[17*1024];
+
+
+void* XMALLOC(size_t n, void* heap, int type)
+{
+    (void)heap;
+
+    if (type == DYNAMIC_TYPE_IN_BUFFER) {
+        if (n < sizeof(pool_in))
+            return pool_in;
+        else
+            return NULL;
+    }
+
+    if (type == DYNAMIC_TYPE_OUT_BUFFER) {
+        if (n < sizeof(pool_out))
+            return pool_out;
+        else
+            return NULL;
+    }
+
+    return malloc(n);
+}
+
+void* XREALLOC(void *p, size_t n, void* heap, int type)
+{
+    (void)heap;
+
+    if (type == DYNAMIC_TYPE_IN_BUFFER) {
+        if (n < sizeof(pool_in))
+            return pool_in;
+        else
+            return NULL;
+    }
+
+    if (type == DYNAMIC_TYPE_OUT_BUFFER) {
+        if (n < sizeof(pool_out))
+            return pool_out;
+        else
+            return NULL;
+    }
+
+    return realloc(p, n);
+}
+
+void XFREE(void *p, void* heap, int type)
+{
+    (void)heap;
+
+    if (type == DYNAMIC_TYPE_IN_BUFFER)
+        return;  /* do nothing, static pool */
+
+    if (type == DYNAMIC_TYPE_OUT_BUFFER)
+        return;  /* do nothing, static pool */
+
+    free(p);
+}
+
+#endif /* HAVE_IO_POOL */
+
+#ifdef WOLFSSL_MEMORY_LOG
+void *xmalloc(size_t n, void* heap, int type, const char* func,
+              const char* file, unsigned int line)
+{
+    void*   p;
+    word32* p32;
+
+    if (malloc_function)
+        p32 = malloc_function(n + sizeof(word32) * 4);
+    else
+        p32 = malloc(n + sizeof(word32) * 4);
+
+    p32[0] = (word32)n;
+    p = (void*)(p32 + 4);
+
+    fprintf(stderr, "Alloc: %p -> %u (%d) at %s:%s:%u\n", p, (word32)n, type,
+                                                              func, file, line);
+
+    (void)heap;
+
+    return p;
+}
+void *xrealloc(void *p, size_t n, void* heap, int type, const char* func,
+               const char* file, unsigned int line)
+{
+    void*   newp = NULL;
+    word32* p32;
+    word32* oldp32 = NULL;
+    word32  oldLen;
+
+    if (p != NULL) {
+        oldp32 = (word32*)p;
+        oldp32 -= 4;
+        oldLen = oldp32[0];
+    }
+
+    if (realloc_function)
+        p32 = realloc_function(oldp32, n + sizeof(word32) * 4);
+    else
+        p32 = realloc(oldp32, n + sizeof(word32) * 4);
+
+    if (p32 != NULL) {
+        p32[0] = (word32)n;
+        newp = (void*)(p32 + 4);
+
+        fprintf(stderr, "Alloc: %p -> %u (%d) at %s:%s:%u\n", newp, (word32)n,
+                                                        type, func, file, line);
+        if (p != NULL) {
+            fprintf(stderr, "Free: %p -> %u (%d) at %s:%s:%u\n", p, oldLen,
+                                                        type, func, file, line);
+        }
+    }
+
+    (void)heap;
+
+    return newp;
+}
+void xfree(void *p, void* heap, int type, const char* func, const char* file,
+           unsigned int line)
+{
+    word32* p32 = (word32*)p;
+
+    if (p != NULL) {
+        p32 -= 4;
+
+        fprintf(stderr, "Free: %p -> %u (%d) at %s:%s:%u\n", p, p32[0], type,
+                                                              func, file, line);
+
+        if (free_function)
+            free_function(p32);
+        else
+            free(p32);
+    }
+
+    (void)heap;
+}
+#endif /* WOLFSSL_MEMORY_LOG */
+
+#ifdef WOLFSSL_STACK_LOG
+/* Note: this code only works with GCC using -finstrument-functions. */
+void __attribute__((no_instrument_function))
+     __cyg_profile_func_enter(void *func,  void *caller)
+{
+    register void* sp asm("sp");
+    fprintf(stderr, "ENTER: %016lx %p\n", (unsigned long)(size_t)func, sp);
+    (void)caller;
+}
+
+void __attribute__((no_instrument_function))
+     __cyg_profile_func_exit(void *func, void *caller)
+{
+    register void* sp asm("sp");
+    fprintf(stderr, "EXIT: %016lx %p\n", (unsigned long)(size_t)func, sp);
+    (void)caller;
+}
+#endif
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/misc.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/misc.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/misc.c	(revision 453)
@@ -0,0 +1,405 @@
+/* misc.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifndef WOLF_CRYPT_MISC_C
+#define WOLF_CRYPT_MISC_C
+
+#include <wolfssl/wolfcrypt/misc.h>
+
+/* inlining these functions is a huge speed increase and a small size decrease,
+   because the functions are smaller than function call setup/cleanup, e.g.,
+   md5 benchmark is twice as fast with inline.  If you don't want it, then
+   define NO_INLINE and compile this file into wolfssl, otherwise it's used as
+   a source header
+ */
+
+#ifdef NO_INLINE
+    #define WC_STATIC
+#else
+    #define WC_STATIC static
+#endif
+
+/* Check for if compiling misc.c when not needed. */
+#if !defined(WOLFSSL_MISC_INCLUDED) && !defined(NO_INLINE)
+    #ifndef WOLFSSL_IGNORE_FILE_WARN
+        #warning misc.c does not need to be compiled when using inline (NO_INLINE not defined)
+    #endif
+
+#else
+
+
+#if defined(__ICCARM__)
+    #include <intrinsics.h>
+#endif
+
+
+#ifdef INTEL_INTRINSICS
+
+    #include <stdlib.h>      /* get intrinsic definitions */
+
+    /* for non visual studio probably need no long version, 32 bit only
+     * i.e., _rotl and _rotr */
+    #pragma intrinsic(_lrotl, _lrotr)
+
+    WC_STATIC WC_INLINE word32 rotlFixed(word32 x, word32 y)
+    {
+        return y ? _lrotl(x, y) : x;
+    }
+
+    WC_STATIC WC_INLINE word32 rotrFixed(word32 x, word32 y)
+    {
+        return y ? _lrotr(x, y) : x;
+    }
+
+#else /* generic */
+
+    WC_STATIC WC_INLINE word32 rotlFixed(word32 x, word32 y)
+    {
+        return (x << y) | (x >> (sizeof(y) * 8 - y));
+    }
+
+
+    WC_STATIC WC_INLINE word32 rotrFixed(word32 x, word32 y)
+    {
+        return (x >> y) | (x << (sizeof(y) * 8 - y));
+    }
+
+#endif
+
+
+WC_STATIC WC_INLINE word32 ByteReverseWord32(word32 value)
+{
+#ifdef PPC_INTRINSICS
+    /* PPC: load reverse indexed instruction */
+    return (word32)__lwbrx(&value,0);
+#elif defined(__ICCARM__)
+    return (word32)__REV(value);
+#elif defined(KEIL_INTRINSICS)
+    return (word32)__rev(value);
+#elif defined(WOLF_ALLOW_BUILTIN) && \
+        defined(__GNUC_PREREQ) && __GNUC_PREREQ(4, 3)
+    return (word32)__builtin_bswap32(value);
+#elif defined(FAST_ROTATE)
+    /* 5 instructions with rotate instruction, 9 without */
+    return (rotrFixed(value, 8U) & 0xff00ff00) |
+           (rotlFixed(value, 8U) & 0x00ff00ff);
+#else
+    /* 6 instructions with rotate instruction, 8 without */
+    value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8);
+    return rotlFixed(value, 16U);
+#endif
+}
+
+
+WC_STATIC WC_INLINE void ByteReverseWords(word32* out, const word32* in,
+                                    word32 byteCount)
+{
+    word32 count = byteCount/(word32)sizeof(word32), i;
+
+    for (i = 0; i < count; i++)
+        out[i] = ByteReverseWord32(in[i]);
+
+}
+
+
+#if defined(WORD64_AVAILABLE) && !defined(WOLFSSL_NO_WORD64_OPS)
+
+
+WC_STATIC WC_INLINE word64 rotlFixed64(word64 x, word64 y)
+{
+    return (x << y) | (x >> (sizeof(y) * 8 - y));
+}
+
+
+WC_STATIC WC_INLINE word64 rotrFixed64(word64 x, word64 y)
+{
+    return (x >> y) | (x << (sizeof(y) * 8 - y));
+}
+
+
+WC_STATIC WC_INLINE word64 ByteReverseWord64(word64 value)
+{
+#if defined(WOLF_ALLOW_BUILTIN) && defined(__GNUC_PREREQ) && __GNUC_PREREQ(4, 3)
+    return (word64)__builtin_bswap64(value);
+#elif defined(WOLFCRYPT_SLOW_WORD64)
+	return (word64)((word64)ByteReverseWord32((word32) value)) << 32 |
+                    (word64)ByteReverseWord32((word32)(value   >> 32));
+#else
+	value = ((value & W64LIT(0xFF00FF00FF00FF00)) >> 8) |
+            ((value & W64LIT(0x00FF00FF00FF00FF)) << 8);
+	value = ((value & W64LIT(0xFFFF0000FFFF0000)) >> 16) |
+            ((value & W64LIT(0x0000FFFF0000FFFF)) << 16);
+	return rotlFixed64(value, 32U);
+#endif
+}
+
+
+WC_STATIC WC_INLINE void ByteReverseWords64(word64* out, const word64* in,
+                                      word32 byteCount)
+{
+    word32 count = byteCount/(word32)sizeof(word64), i;
+
+    for (i = 0; i < count; i++)
+        out[i] = ByteReverseWord64(in[i]);
+
+}
+
+#endif /* WORD64_AVAILABLE && !WOLFSSL_NO_WORD64_OPS */
+
+#ifndef WOLFSSL_NO_XOR_OPS
+WC_STATIC WC_INLINE void XorWords(wolfssl_word* r, const wolfssl_word* a, word32 n)
+{
+    word32 i;
+
+    for (i = 0; i < n; i++) r[i] ^= a[i];
+}
+
+
+WC_STATIC WC_INLINE void xorbuf(void* buf, const void* mask, word32 count)
+{
+    if (((wolfssl_word)buf | (wolfssl_word)mask | count) % WOLFSSL_WORD_SIZE == 0)
+        XorWords( (wolfssl_word*)buf,
+                  (const wolfssl_word*)mask, count / WOLFSSL_WORD_SIZE);
+    else {
+        word32 i;
+        byte*       b = (byte*)buf;
+        const byte* m = (const byte*)mask;
+
+        for (i = 0; i < count; i++) b[i] ^= m[i];
+    }
+}
+#endif
+
+#ifndef WOLFSSL_NO_FORCE_ZERO
+/* Make sure compiler doesn't skip */
+WC_STATIC WC_INLINE void ForceZero(const void* mem, word32 len)
+{
+    volatile byte* z = (volatile byte*)mem;
+
+#if defined(WOLFSSL_X86_64_BUILD) && defined(WORD64_AVAILABLE)
+    volatile word64* w;
+    #ifndef WOLFSSL_UNALIGNED_64BIT_ACCESS
+        word32 l = (sizeof(word64) - ((size_t)z & (sizeof(word64)-1))) &
+                                                             (sizeof(word64)-1);
+
+        if (len < l) l = len;
+        len -= l;
+        while (l--) *z++ = 0;
+    #endif
+    for (w = (volatile word64*)z; len >= sizeof(*w); len -= sizeof(*w))
+        *w++ = 0;
+    z = (volatile byte*)w;
+#endif
+
+    while (len--) *z++ = 0;
+}
+#endif
+
+
+#ifndef WOLFSSL_NO_CONST_CMP
+/* check all length bytes for equality, return 0 on success */
+WC_STATIC WC_INLINE int ConstantCompare(const byte* a, const byte* b, int length)
+{
+    int i;
+    int compareSum = 0;
+
+    for (i = 0; i < length; i++) {
+        compareSum |= a[i] ^ b[i];
+    }
+
+    return compareSum;
+}
+#endif
+
+
+#ifndef WOLFSSL_HAVE_MIN
+    #define WOLFSSL_HAVE_MIN
+    #if defined(HAVE_FIPS) && !defined(min) /* so ifdef check passes */
+        #define min min
+    #endif
+    WC_STATIC WC_INLINE word32 min(word32 a, word32 b)
+    {
+        return a > b ? b : a;
+    }
+#endif /* !WOLFSSL_HAVE_MIN */
+
+#ifndef WOLFSSL_HAVE_MAX
+    #define WOLFSSL_HAVE_MAX
+    #if defined(HAVE_FIPS) && !defined(max) /* so ifdef check passes */
+        #define max max
+    #endif
+    WC_STATIC WC_INLINE word32 max(word32 a, word32 b)
+    {
+        return a > b ? a : b;
+    }
+#endif /* !WOLFSSL_HAVE_MAX */
+
+#ifndef WOLFSSL_NO_INT_ENCODE
+/* converts a 32 bit integer to 24 bit */
+WC_STATIC WC_INLINE void c32to24(word32 in, word24 out)
+{
+    out[0] = (in >> 16) & 0xff;
+    out[1] = (in >>  8) & 0xff;
+    out[2] =  in & 0xff;
+}
+
+/* convert 16 bit integer to opaque */
+WC_STATIC WC_INLINE void c16toa(word16 wc_u16, byte* c)
+{
+    c[0] = (wc_u16 >> 8) & 0xff;
+    c[1] =  wc_u16 & 0xff;
+}
+
+/* convert 32 bit integer to opaque */
+WC_STATIC WC_INLINE void c32toa(word32 wc_u32, byte* c)
+{
+    c[0] = (wc_u32 >> 24) & 0xff;
+    c[1] = (wc_u32 >> 16) & 0xff;
+    c[2] = (wc_u32 >>  8) & 0xff;
+    c[3] =  wc_u32 & 0xff;
+}
+#endif
+
+#ifndef WOLFSSL_NO_INT_DECODE
+/* convert a 24 bit integer into a 32 bit one */
+WC_STATIC WC_INLINE void c24to32(const word24 wc_u24, word32* wc_u32)
+{
+    *wc_u32 = ((word32)wc_u24[0] << 16) | (wc_u24[1] << 8) | wc_u24[2];
+}
+
+
+/* convert opaque to 24 bit integer */
+WC_STATIC WC_INLINE void ato24(const byte* c, word32* wc_u24)
+{
+    *wc_u24 = ((word32)c[0] << 16) | (c[1] << 8) | c[2];
+}
+
+/* convert opaque to 16 bit integer */
+WC_STATIC WC_INLINE void ato16(const byte* c, word16* wc_u16)
+{
+    *wc_u16 = (word16) ((c[0] << 8) | (c[1]));
+}
+
+/* convert opaque to 32 bit integer */
+WC_STATIC WC_INLINE void ato32(const byte* c, word32* wc_u32)
+{
+    *wc_u32 = ((word32)c[0] << 24) | ((word32)c[1] << 16) | (c[2] << 8) | c[3];
+}
+
+
+WC_STATIC WC_INLINE word32 btoi(byte b)
+{
+    return (word32)(b - 0x30);
+}
+#endif
+
+
+#ifndef WOLFSSL_NO_CT_OPS
+/* Constant time - mask set when a > b. */
+WC_STATIC WC_INLINE byte ctMaskGT(int a, int b)
+{
+    return (((word32)a - b - 1) >> 31) - 1;
+}
+
+/* Constant time - mask set when a >= b. */
+WC_STATIC WC_INLINE byte ctMaskGTE(int a, int b)
+{
+    return (((word32)a - b    ) >> 31) - 1;
+}
+
+/* Constant time - mask set when a >= b. */
+WC_STATIC WC_INLINE int ctMaskIntGTE(int a, int b)
+{
+    return (((word32)a - b    ) >> 31) - 1;
+}
+
+/* Constant time - mask set when a < b. */
+WC_STATIC WC_INLINE byte ctMaskLT(int a, int b)
+{
+    return (((word32)b - a - 1) >> 31) - 1;
+}
+
+/* Constant time - mask set when a <= b. */
+WC_STATIC WC_INLINE byte ctMaskLTE(int a, int b)
+{
+    return (((word32)b - a    ) >> 31) - 1;
+}
+
+/* Constant time - mask set when a == b. */
+WC_STATIC WC_INLINE byte ctMaskEq(int a, int b)
+{
+    return (~ctMaskGT(a, b)) & (~ctMaskLT(a, b));
+}
+
+WC_STATIC WC_INLINE word16 ctMask16GT(int a, int b)
+{
+    return (((word32)a - b - 1) >> 31) - 1;
+}
+
+WC_STATIC WC_INLINE word16 ctMask16LT(int a, int b)
+{
+    return (((word32)a - b - 1) >> 31) - 1;
+}
+
+WC_STATIC WC_INLINE word16 ctMask16Eq(int a, int b)
+{
+    return (~ctMask16GT(a, b)) & (~ctMask16LT(a, b));
+}
+
+/* Constant time - mask set when a != b. */
+WC_STATIC WC_INLINE byte ctMaskNotEq(int a, int b)
+{
+    return ctMaskGT(a, b) | ctMaskLT(a, b);
+}
+
+/* Constant time - select a when mask is set and b otherwise. */
+WC_STATIC WC_INLINE byte ctMaskSel(byte m, byte a, byte b)
+{
+    return (b & ((byte)~(word32)m)) | (a & m);
+}
+
+/* Constant time - select integer a when mask is set and integer b otherwise. */
+WC_STATIC WC_INLINE int ctMaskSelInt(byte m, int a, int b)
+{
+    return (b & (~(signed int)(signed char)m)) |
+           (a & ( (signed int)(signed char)m));
+}
+
+/* Constant time - bit set when a <= b. */
+WC_STATIC WC_INLINE byte ctSetLTE(int a, int b)
+{
+    return ((word32)a - b - 1) >> 31;
+}
+#endif
+
+
+#undef WC_STATIC
+
+#endif /* !WOLFSSL_MISC_INCLUDED && !NO_INLINE */
+
+#endif /* WOLF_CRYPT_MISC_C */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/pwdbased.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/pwdbased.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/pwdbased.c	(revision 453)
@@ -0,0 +1,795 @@
+/* pwdbased.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifndef NO_PWDBASED
+
+#include <wolfssl/wolfcrypt/pwdbased.h>
+#include <wolfssl/wolfcrypt/hmac.h>
+#include <wolfssl/wolfcrypt/hash.h>
+#include <wolfssl/wolfcrypt/integer.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+
+#ifdef HAVE_PBKDF1
+
+/* PKCS#5 v1.5 with non standard extension to optionally derive the extra data (IV) */
+int wc_PBKDF1_ex(byte* key, int keyLen, byte* iv, int ivLen,
+    const byte* passwd, int passwdLen, const byte* salt, int saltLen,
+    int iterations, int hashType, void* heap)
+{
+    int  err;
+    int  keyLeft, ivLeft, i;
+    int  digestLeft, store;
+    int  keyOutput = 0;
+    int  diestLen;
+    byte digest[WC_MAX_DIGEST_SIZE];
+#ifdef WOLFSSL_SMALL_STACK
+    wc_HashAlg* hash = NULL;
+#else
+    wc_HashAlg  hash[1];
+#endif
+    enum wc_HashType hashT;
+
+    (void)heap;
+
+    if (key == NULL || keyLen < 0 || passwdLen < 0 || saltLen < 0 || ivLen < 0){
+        return BAD_FUNC_ARG;
+    }
+
+    if (iterations <= 0)
+        iterations = 1;
+
+    hashT = wc_HashTypeConvert(hashType);
+    err = wc_HashGetDigestSize(hashT);
+    if (err < 0)
+        return err;
+    diestLen = err;
+
+    /* initialize hash */
+#ifdef WOLFSSL_SMALL_STACK
+    hash = (wc_HashAlg*)XMALLOC(sizeof(wc_HashAlg), heap,
+                                DYNAMIC_TYPE_HASHCTX);
+    if (hash == NULL)
+        return MEMORY_E;
+#endif
+
+    err = wc_HashInit_ex(hash, hashT, heap, INVALID_DEVID);
+    if (err != 0) {
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(hash, heap, DYNAMIC_TYPE_HASHCTX);
+    #endif
+        return err;
+    }
+
+    keyLeft = keyLen;
+    ivLeft  = ivLen;
+    while (keyOutput < (keyLen + ivLen)) {
+        digestLeft = diestLen;
+        /* D_(i - 1) */
+        if (keyOutput) { /* first time D_0 is empty */
+            err = wc_HashUpdate(hash, hashT, digest, diestLen);
+            if (err != 0) break;
+        }
+
+        /* data */
+        err = wc_HashUpdate(hash, hashT, passwd, passwdLen);
+        if (err != 0) break;
+
+        /* salt */
+        if (salt) {
+            err = wc_HashUpdate(hash, hashT, salt, saltLen);
+            if (err != 0) break;
+        }
+
+        err = wc_HashFinal(hash, hashT, digest);
+        if (err != 0) break;
+
+        /* count */
+        for (i = 1; i < iterations; i++) {
+            err = wc_HashUpdate(hash, hashT, digest, diestLen);
+            if (err != 0) break;
+
+            err = wc_HashFinal(hash, hashT, digest);
+            if (err != 0) break;
+        }
+
+        if (keyLeft) {
+            store = min(keyLeft, diestLen);
+            XMEMCPY(&key[keyLen - keyLeft], digest, store);
+
+            keyOutput  += store;
+            keyLeft    -= store;
+            digestLeft -= store;
+        }
+
+        if (ivLeft && digestLeft) {
+            store = min(ivLeft, digestLeft);
+            if (iv != NULL)
+                XMEMCPY(&iv[ivLen - ivLeft],
+                        &digest[diestLen - digestLeft], store);
+            keyOutput += store;
+            ivLeft    -= store;
+        }
+    }
+
+    wc_HashFree(hash, hashT);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(hash, heap, DYNAMIC_TYPE_HASHCTX);
+#endif
+
+    if (err != 0)
+        return err;
+
+    if (keyOutput != (keyLen + ivLen))
+        return BUFFER_E;
+
+    return err;
+}
+
+/* PKCS#5 v1.5 */
+int wc_PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt,
+           int sLen, int iterations, int kLen, int hashType)
+{
+    return wc_PBKDF1_ex(output, kLen, NULL, 0,
+        passwd, pLen, salt, sLen, iterations, hashType, NULL);
+}
+
+#endif /* HAVE_PKCS5 */
+
+#ifdef HAVE_PBKDF2
+
+int wc_PBKDF2_ex(byte* output, const byte* passwd, int pLen, const byte* salt,
+           int sLen, int iterations, int kLen, int hashType, void* heap, int devId)
+{
+    word32 i = 1;
+    int    hLen;
+    int    j, ret;
+#ifdef WOLFSSL_SMALL_STACK
+    byte*  buffer;
+    Hmac*  hmac;
+#else
+    byte   buffer[WC_MAX_DIGEST_SIZE];
+    Hmac   hmac[1];
+#endif
+    enum wc_HashType hashT;
+
+    if (output == NULL || pLen < 0 || sLen < 0 || kLen < 0) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (iterations <= 0)
+        iterations = 1;
+
+    hashT = wc_HashTypeConvert(hashType);
+    hLen = wc_HashGetDigestSize(hashT);
+    if (hLen < 0)
+        return BAD_FUNC_ARG;
+
+#ifdef WOLFSSL_SMALL_STACK
+    buffer = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (buffer == NULL)
+        return MEMORY_E;
+    hmac = (Hmac*)XMALLOC(sizeof(Hmac), heap, DYNAMIC_TYPE_HMAC);
+    if (hmac == NULL) {
+        XFREE(buffer, heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return MEMORY_E;
+    }
+#endif
+
+    ret = wc_HmacInit(hmac, heap, devId);
+    if (ret == 0) {
+        /* use int hashType here, since HMAC FIPS uses the old unique value */
+        ret = wc_HmacSetKey(hmac, hashType, passwd, pLen);
+
+        while (ret == 0 && kLen) {
+            int currentLen;
+
+            ret = wc_HmacUpdate(hmac, salt, sLen);
+            if (ret != 0)
+                break;
+
+            /* encode i */
+            for (j = 0; j < 4; j++) {
+                byte b = (byte)(i >> ((3-j) * 8));
+
+                ret = wc_HmacUpdate(hmac, &b, 1);
+                if (ret != 0)
+                    break;
+            }
+
+            /* check ret from inside for loop */
+            if (ret != 0)
+                break;
+
+            ret = wc_HmacFinal(hmac, buffer);
+            if (ret != 0)
+                break;
+
+            currentLen = min(kLen, hLen);
+            XMEMCPY(output, buffer, currentLen);
+
+            for (j = 1; j < iterations; j++) {
+                ret = wc_HmacUpdate(hmac, buffer, hLen);
+                if (ret != 0)
+                    break;
+                ret = wc_HmacFinal(hmac, buffer);
+                if (ret != 0)
+                    break;
+                xorbuf(output, buffer, currentLen);
+            }
+
+            /* check ret from inside for loop */
+            if (ret != 0)
+                break;
+
+            output += currentLen;
+            kLen   -= currentLen;
+            i++;
+        }
+        wc_HmacFree(hmac);
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(buffer, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(hmac, heap, DYNAMIC_TYPE_HMAC);
+#endif
+
+    return ret;
+}
+
+int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt,
+           int sLen, int iterations, int kLen, int hashType)
+{
+    return wc_PBKDF2_ex(output, passwd, pLen, salt, sLen, iterations, kLen,
+        hashType, NULL, INVALID_DEVID);
+}
+
+#endif /* HAVE_PBKDF2 */
+
+#ifdef HAVE_PKCS12
+
+/* helper for PKCS12_PBKDF(), does hash operation */
+static int DoPKCS12Hash(int hashType, byte* buffer, word32 totalLen,
+                 byte* Ai, word32 u, int iterations)
+{
+    int i;
+    int ret = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    wc_HashAlg* hash = NULL;
+#else
+    wc_HashAlg  hash[1];
+#endif
+    enum wc_HashType hashT;
+
+    if (buffer == NULL || Ai == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    hashT = wc_HashTypeConvert(hashType);
+
+    /* initialize hash */
+#ifdef WOLFSSL_SMALL_STACK
+    hash = (wc_HashAlg*)XMALLOC(sizeof(wc_HashAlg), NULL,
+                                DYNAMIC_TYPE_HASHCTX);
+    if (hash == NULL)
+        return MEMORY_E;
+#endif
+
+    ret = wc_HashInit(hash, hashT);
+    if (ret != 0) {
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(hash, NULL, DYNAMIC_TYPE_HASHCTX);
+    #endif
+        return ret;
+    }
+
+    ret = wc_HashUpdate(hash, hashT, buffer, totalLen);
+
+    if (ret == 0)
+        ret = wc_HashFinal(hash, hashT, Ai);
+
+    for (i = 1; i < iterations; i++) {
+        if (ret == 0)
+            ret = wc_HashUpdate(hash, hashT, Ai, u);
+        if (ret == 0)
+            ret = wc_HashFinal(hash, hashT, Ai);
+    }
+
+    wc_HashFree(hash, hashT);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(hash, NULL, DYNAMIC_TYPE_HASHCTX);
+#endif
+
+    return ret;
+}
+
+
+int wc_PKCS12_PBKDF(byte* output, const byte* passwd, int passLen,
+    const byte* salt, int saltLen, int iterations, int kLen, int hashType,
+    int id)
+{
+    return wc_PKCS12_PBKDF_ex(output, passwd, passLen, salt, saltLen,
+                              iterations, kLen, hashType, id, NULL);
+}
+
+
+/* extended API that allows a heap hint to be used */
+int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd, int passLen,
+                       const byte* salt, int saltLen, int iterations, int kLen,
+                       int hashType, int id, void* heap)
+{
+    /* all in bytes instead of bits */
+    word32 u, v, dLen, pLen, iLen, sLen, totalLen;
+    int    dynamic = 0;
+    int    ret = 0;
+    int    i;
+    byte   *D, *S, *P, *I;
+#ifdef WOLFSSL_SMALL_STACK
+    byte   staticBuffer[1]; /* force dynamic usage */
+#else
+    byte   staticBuffer[1024];
+#endif
+    byte*  buffer = staticBuffer;
+
+#ifdef WOLFSSL_SMALL_STACK
+    byte*  Ai;
+    byte*  B;
+#else
+    byte   Ai[WC_MAX_DIGEST_SIZE];
+    byte   B[WC_MAX_BLOCK_SIZE];
+#endif
+    enum wc_HashType hashT;
+
+    (void)heap;
+
+    if (output == NULL || passLen < 0 || saltLen < 0 || kLen < 0) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (iterations <= 0)
+        iterations = 1;
+
+    hashT = wc_HashTypeConvert(hashType);
+    ret = wc_HashGetDigestSize(hashT);
+    if (ret < 0)
+        return ret;
+    u = ret;
+
+    ret = wc_HashGetBlockSize(hashT);
+    if (ret < 0)
+        return ret;
+    v = ret;
+
+#ifdef WOLFSSL_SMALL_STACK
+    Ai = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (Ai == NULL)
+        return MEMORY_E;
+
+    B = (byte*)XMALLOC(WC_MAX_BLOCK_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (B == NULL) {
+        XFREE(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return MEMORY_E;
+    }
+#endif
+
+    XMEMSET(Ai, 0, WC_MAX_DIGEST_SIZE);
+    XMEMSET(B,  0, WC_MAX_BLOCK_SIZE);
+
+    dLen = v;
+    sLen = v * ((saltLen + v - 1) / v);
+    if (passLen)
+        pLen = v * ((passLen + v - 1) / v);
+    else
+        pLen = 0;
+    iLen = sLen + pLen;
+
+    totalLen = dLen + sLen + pLen;
+
+    if (totalLen > sizeof(staticBuffer)) {
+        buffer = (byte*)XMALLOC(totalLen, heap, DYNAMIC_TYPE_KEY);
+        if (buffer == NULL) {
+#ifdef WOLFSSL_SMALL_STACK
+            XFREE(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER);
+            XFREE(B,  heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+            return MEMORY_E;
+        }
+        dynamic = 1;
+    }
+
+    D = buffer;
+    S = D + dLen;
+    P = S + sLen;
+    I = S;
+
+    XMEMSET(D, id, dLen);
+
+    for (i = 0; i < (int)sLen; i++)
+        S[i] = salt[i % saltLen];
+    for (i = 0; i < (int)pLen; i++)
+        P[i] = passwd[i % passLen];
+
+    while (kLen > 0) {
+        word32 currentLen;
+        mp_int B1;
+
+        ret = DoPKCS12Hash(hashType, buffer, totalLen, Ai, u, iterations);
+        if (ret < 0)
+            break;
+
+        for (i = 0; i < (int)v; i++)
+            B[i] = Ai[i % u];
+
+        if (mp_init(&B1) != MP_OKAY)
+            ret = MP_INIT_E;
+        else if (mp_read_unsigned_bin(&B1, B, v) != MP_OKAY)
+            ret = MP_READ_E;
+        else if (mp_add_d(&B1, (mp_digit)1, &B1) != MP_OKAY)
+            ret = MP_ADD_E;
+
+        if (ret != 0) {
+            mp_clear(&B1);
+            break;
+        }
+
+        for (i = 0; i < (int)iLen; i += v) {
+            int    outSz;
+            mp_int i1;
+            mp_int res;
+
+            if (mp_init_multi(&i1, &res, NULL, NULL, NULL, NULL) != MP_OKAY) {
+                ret = MP_INIT_E;
+                break;
+            }
+            if (mp_read_unsigned_bin(&i1, I + i, v) != MP_OKAY)
+                ret = MP_READ_E;
+            else if (mp_add(&i1, &B1, &res) != MP_OKAY)
+                ret = MP_ADD_E;
+            else if ( (outSz = mp_unsigned_bin_size(&res)) < 0)
+                ret = MP_TO_E;
+            else {
+                if (outSz > (int)v) {
+                    /* take off MSB */
+                    byte  tmp[WC_MAX_BLOCK_SIZE + 1];
+                    ret = mp_to_unsigned_bin(&res, tmp);
+                    XMEMCPY(I + i, tmp + 1, v);
+                }
+                else if (outSz < (int)v) {
+                    XMEMSET(I + i, 0, v - outSz);
+                    ret = mp_to_unsigned_bin(&res, I + i + v - outSz);
+                }
+                else
+                    ret = mp_to_unsigned_bin(&res, I + i);
+            }
+
+            mp_clear(&i1);
+            mp_clear(&res);
+            if (ret < 0) break;
+        }
+
+        currentLen = min(kLen, (int)u);
+        XMEMCPY(output, Ai, currentLen);
+        output += currentLen;
+        kLen   -= currentLen;
+        mp_clear(&B1);
+    }
+
+    if (dynamic) XFREE(buffer, heap, DYNAMIC_TYPE_KEY);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(B,  heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return ret;
+}
+
+#endif /* HAVE_PKCS12 */
+
+#ifdef HAVE_SCRYPT
+/* Rotate the 32-bit value a by b bits to the left.
+ *
+ * a  32-bit value.
+ * b  Number of bits to rotate.
+ * returns rotated value.
+ */
+#define R(a, b) rotlFixed(a, b)
+
+/* One round of Salsa20/8.
+ * Code taken from RFC 7914: scrypt PBKDF.
+ *
+ * out  Output buffer.
+ * in   Input data to hash.
+ */
+static void scryptSalsa(word32* out, word32* in)
+{
+    int    i;
+    word32 x[16];
+
+#ifdef LITTLE_ENDIAN_ORDER
+    for (i = 0; i < 16; ++i)
+        x[i] = in[i];
+#else
+    for (i = 0; i < 16; i++)
+        x[i] = ByteReverseWord32(in[i]);
+#endif
+    for (i = 8; i > 0; i -= 2) {
+        x[ 4] ^= R(x[ 0] + x[12],  7);  x[ 8] ^= R(x[ 4] + x[ 0],  9);
+        x[12] ^= R(x[ 8] + x[ 4], 13);  x[ 0] ^= R(x[12] + x[ 8], 18);
+        x[ 9] ^= R(x[ 5] + x[ 1],  7);  x[13] ^= R(x[ 9] + x[ 5],  9);
+        x[ 1] ^= R(x[13] + x[ 9], 13);  x[ 5] ^= R(x[ 1] + x[13], 18);
+        x[14] ^= R(x[10] + x[ 6],  7);  x[ 2] ^= R(x[14] + x[10],  9);
+        x[ 6] ^= R(x[ 2] + x[14], 13);  x[10] ^= R(x[ 6] + x[ 2], 18);
+        x[ 3] ^= R(x[15] + x[11],  7);  x[ 7] ^= R(x[ 3] + x[15],  9);
+        x[11] ^= R(x[ 7] + x[ 3], 13);  x[15] ^= R(x[11] + x[ 7], 18);
+        x[ 1] ^= R(x[ 0] + x[ 3],  7);  x[ 2] ^= R(x[ 1] + x[ 0],  9);
+        x[ 3] ^= R(x[ 2] + x[ 1], 13);  x[ 0] ^= R(x[ 3] + x[ 2], 18);
+        x[ 6] ^= R(x[ 5] + x[ 4],  7);  x[ 7] ^= R(x[ 6] + x[ 5],  9);
+        x[ 4] ^= R(x[ 7] + x[ 6], 13);  x[ 5] ^= R(x[ 4] + x[ 7], 18);
+        x[11] ^= R(x[10] + x[ 9],  7);  x[ 8] ^= R(x[11] + x[10],  9);
+        x[ 9] ^= R(x[ 8] + x[11], 13);  x[10] ^= R(x[ 9] + x[ 8], 18);
+        x[12] ^= R(x[15] + x[14],  7);  x[13] ^= R(x[12] + x[15],  9);
+        x[14] ^= R(x[13] + x[12], 13);  x[15] ^= R(x[14] + x[13], 18);
+    }
+#ifdef LITTLE_ENDIAN_ORDER
+    for (i = 0; i < 16; ++i)
+        out[i] = in[i] + x[i];
+#else
+    for (i = 0; i < 16; i++)
+        out[i] = ByteReverseWord32(ByteReverseWord32(in[i]) + x[i]);
+#endif
+}
+
+/* Mix a block using Salsa20/8.
+ * Based on RFC 7914: scrypt PBKDF.
+ *
+ * b  Blocks to mix.
+ * y  Temporary storage.
+ * r  Size of the block.
+ */
+static void scryptBlockMix(byte* b, byte* y, int r)
+{
+    byte x[64];
+#ifdef WORD64_AVAILABLE
+    word64* b64 = (word64*)b;
+    word64* y64 = (word64*)y;
+    word64* x64 = (word64*)x;
+#else
+    word32* b32 = (word32*)b;
+    word32* y32 = (word32*)y;
+    word32* x32 = (word32*)x;
+#endif
+    int  i;
+    int  j;
+
+    /* Step 1. */
+    XMEMCPY(x, b + (2 * r - 1) * 64, sizeof(x));
+    /* Step 2. */
+    for (i = 0; i < 2 * r; i++)
+    {
+#ifdef WORD64_AVAILABLE
+        for (j = 0; j < 8; j++)
+            x64[j] ^= b64[i * 8 + j];
+#else
+        for (j = 0; j < 16; j++)
+            x32[j] ^= b32[i * 16 + j];
+#endif
+        scryptSalsa((word32*)x, (word32*)x);
+        XMEMCPY(y + i * 64, x, sizeof(x));
+    }
+    /* Step 3. */
+    for (i = 0; i < r; i++) {
+#ifdef WORD64_AVAILABLE
+        for (j = 0; j < 8; j++) {
+            b64[i * 8 + j] = y64[2 * i * 8 + j];
+            b64[(r + i) * 8 + j] = y64[(2 * i + 1) * 8 + j];
+        }
+#else
+        for (j = 0; j < 16; j++) {
+            b32[i * 16 + j] = y32[2 * i * 16 + j];
+            b32[(r + i) * 16 + j] = y32[(2 * i + 1) * 16 + j];
+        }
+#endif
+    }
+}
+
+/* Random oracles mix.
+ * Based on RFC 7914: scrypt PBKDF.
+ *
+ * x  Data to mix.
+ * v  Temporary buffer.
+ * y  Temporary buffer for the block mix.
+ * r  Block size parameter.
+ * n  CPU/Memory cost parameter.
+ */
+static void scryptROMix(byte* x, byte* v, byte* y, int r, word32 n)
+{
+    word32 i;
+    word32 j;
+    word32 k;
+    word32 bSz = 128 * r;
+#ifdef WORD64_AVAILABLE
+    word64* x64 = (word64*)x;
+    word64* v64 = (word64*)v;
+#else
+    word32* x32 = (word32*)x;
+    word32* v32 = (word32*)v;
+#endif
+
+    /* Step 1. X = B (B not needed therefore not implemented) */
+    /* Step 2. */
+    for (i = 0; i < n; i++)
+    {
+        XMEMCPY(v + i * bSz, x, bSz);
+        scryptBlockMix(x, y, r);
+    }
+
+    /* Step 3. */
+    for (i = 0; i < n; i++)
+    {
+#ifdef LITTLE_ENDIAN_ORDER
+#ifdef WORD64_AVAILABLE
+        j = *(word64*)(x + (2*r - 1) * 64) & (n-1);
+#else
+        j = *(word32*)(x + (2*r - 1) * 64) & (n-1);
+#endif
+#else
+        byte* t = x + (2*r - 1) * 64;
+        j = (t[0] | (t[1] << 8) | (t[2] << 16) | ((word32)t[3] << 24)) & (n-1);
+#endif
+#ifdef WORD64_AVAILABLE
+        for (k = 0; k < bSz / 8; k++)
+            x64[k] ^= v64[j * bSz / 8 + k];
+#else
+        for (k = 0; k < bSz / 4; k++)
+            x32[k] ^= v32[j * bSz / 4 + k];
+#endif
+        scryptBlockMix(x, y, r);
+    }
+    /* Step 4. B' = X (B = X = B' so not needed, therefore not implemented) */
+}
+
+/* Generates an key derived from a password and salt using a memory hard
+ * algorithm.
+ * Implements RFC 7914: scrypt PBKDF.
+ *
+ * output     The derived key.
+ * passwd     The password to derive key from.
+ * passLen    The length of the password.
+ * salt       The key specific data.
+ * saltLen    The length of the salt data.
+ * cost       The CPU/memory cost parameter. Range: 1..(128*r/8-1)
+ *            (Iterations = 2^cost)
+ * blockSize  The number of 128 byte octets in a working block.
+ * parallel   The number of parallel mix operations to perform.
+ *            (Note: this implementation does not use threads.)
+ * dkLen      The length of the derived key in bytes.
+ * returns BAD_FUNC_ARG when: blockSize is too large for cost.
+ */
+int wc_scrypt(byte* output, const byte* passwd, int passLen,
+              const byte* salt, int saltLen, int cost, int blockSize,
+              int parallel, int dkLen)
+{
+    int    ret = 0;
+    int    i;
+    byte*  v = NULL;
+    byte*  y = NULL;
+    byte*  blocks = NULL;
+    word32 blocksSz;
+    word32 bSz;
+
+    if (blockSize > 8)
+        return BAD_FUNC_ARG;
+
+    if (cost < 1 || cost >= 128 * blockSize / 8 || parallel < 1 || dkLen < 1)
+        return BAD_FUNC_ARG;
+
+    bSz = 128 * blockSize;
+    blocksSz = bSz * parallel;
+    blocks = (byte*)XMALLOC(blocksSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (blocks == NULL)
+        goto end;
+    /* Temporary for scryptROMix. */
+    v = (byte*)XMALLOC((1 << cost) * bSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (v == NULL)
+        goto end;
+    /* Temporary for scryptBlockMix. */
+    y = (byte*)XMALLOC(blockSize * 128, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (y == NULL)
+        goto end;
+
+    /* Step 1. */
+    ret = wc_PBKDF2(blocks, passwd, passLen, salt, saltLen, 1, blocksSz,
+                    WC_SHA256);
+    if (ret != 0)
+        goto end;
+
+    /* Step 2. */
+    for (i = 0; i < parallel; i++)
+        scryptROMix(blocks + i * bSz, v, y, blockSize, 1 << cost);
+
+    /* Step 3. */
+    ret = wc_PBKDF2(output, passwd, passLen, blocks, blocksSz, 1, dkLen,
+                    WC_SHA256);
+end:
+    if (blocks != NULL)
+        XFREE(blocks, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (v != NULL)
+        XFREE(v, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (y != NULL)
+        XFREE(y, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+    return ret;
+}
+
+/* Generates an key derived from a password and salt using a memory hard
+ * algorithm.
+ * Implements RFC 7914: scrypt PBKDF.
+ *
+ * output      Derived key.
+ * passwd      Password to derive key from.
+ * passLen     Length of the password.
+ * salt        Key specific data.
+ * saltLen     Length of the salt data.
+ * iterations  Number of iterations to perform. Range: 1 << (1..(128*r/8-1))
+ * blockSize   Number of 128 byte octets in a working block.
+ * parallel    Number of parallel mix operations to perform.
+ *             (Note: this implementation does not use threads.)
+ * dkLen       Length of the derived key in bytes.
+ * returns BAD_FUNC_ARG when: iterations is not a power of 2 or blockSize is too
+ *                            large for iterations.
+ */
+int wc_scrypt_ex(byte* output, const byte* passwd, int passLen,
+                 const byte* salt, int saltLen, word32 iterations,
+                 int blockSize, int parallel, int dkLen)
+{
+    int cost;
+
+    /* Iterations must be a power of 2. */
+    if ((iterations & (iterations - 1)) != 0)
+        return BAD_FUNC_ARG;
+
+    for (cost = -1; iterations != 0; cost++) {
+        iterations >>= 1;
+    }
+
+    return wc_scrypt(output, passwd, passLen, salt, saltLen, cost, blockSize,
+                     parallel, dkLen);
+}
+#endif /* HAVE_SCRYPT */
+
+#endif /* NO_PWDBASED */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/rabbit.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/rabbit.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/rabbit.c	(revision 453)
@@ -0,0 +1,342 @@
+/* rabbit.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifndef NO_RABBIT
+
+#include <wolfssl/wolfcrypt/rabbit.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#include <wolfssl/wolfcrypt/logging.h>
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+
+#ifdef BIG_ENDIAN_ORDER
+    #define LITTLE32(x) ByteReverseWord32(x)
+#else
+    #define LITTLE32(x) (x)
+#endif
+
+#define U32V(x) ((word32)(x) & 0xFFFFFFFFU)
+
+
+/* Square a 32-bit unsigned integer to obtain the 64-bit result and return */
+/* the upper 32 bits XOR the lower 32 bits */
+static word32 RABBIT_g_func(word32 x)
+{
+    /* Temporary variables */
+    word32 a, b, h, l;
+
+    /* Construct high and low argument for squaring */
+    a = x&0xFFFF;
+    b = x>>16;
+
+    /* Calculate high and low result of squaring */
+    h = (((U32V(a*a)>>17) + U32V(a*b))>>15) + b*b;
+    l = x*x;
+
+    /* Return high XOR low */
+    return U32V(h^l);
+}
+
+
+/* Calculate the next internal state */
+static void RABBIT_next_state(RabbitCtx* ctx)
+{
+    /* Temporary variables */
+    word32 g[8], c_old[8], i;
+
+    /* Save old counter values */
+    for (i=0; i<8; i++)
+        c_old[i] = ctx->c[i];
+
+    /* Calculate new counter values */
+    ctx->c[0] = U32V(ctx->c[0] + 0x4D34D34D + ctx->carry);
+    ctx->c[1] = U32V(ctx->c[1] + 0xD34D34D3 + (ctx->c[0] < c_old[0]));
+    ctx->c[2] = U32V(ctx->c[2] + 0x34D34D34 + (ctx->c[1] < c_old[1]));
+    ctx->c[3] = U32V(ctx->c[3] + 0x4D34D34D + (ctx->c[2] < c_old[2]));
+    ctx->c[4] = U32V(ctx->c[4] + 0xD34D34D3 + (ctx->c[3] < c_old[3]));
+    ctx->c[5] = U32V(ctx->c[5] + 0x34D34D34 + (ctx->c[4] < c_old[4]));
+    ctx->c[6] = U32V(ctx->c[6] + 0x4D34D34D + (ctx->c[5] < c_old[5]));
+    ctx->c[7] = U32V(ctx->c[7] + 0xD34D34D3 + (ctx->c[6] < c_old[6]));
+    ctx->carry = (ctx->c[7] < c_old[7]);
+
+    /* Calculate the g-values */
+    for (i=0;i<8;i++)
+        g[i] = RABBIT_g_func(U32V(ctx->x[i] + ctx->c[i]));
+
+    /* Calculate new state values */
+    ctx->x[0] = U32V(g[0] + rotlFixed(g[7],16) + rotlFixed(g[6], 16));
+    ctx->x[1] = U32V(g[1] + rotlFixed(g[0], 8) + g[7]);
+    ctx->x[2] = U32V(g[2] + rotlFixed(g[1],16) + rotlFixed(g[0], 16));
+    ctx->x[3] = U32V(g[3] + rotlFixed(g[2], 8) + g[1]);
+    ctx->x[4] = U32V(g[4] + rotlFixed(g[3],16) + rotlFixed(g[2], 16));
+    ctx->x[5] = U32V(g[5] + rotlFixed(g[4], 8) + g[3]);
+    ctx->x[6] = U32V(g[6] + rotlFixed(g[5],16) + rotlFixed(g[4], 16));
+    ctx->x[7] = U32V(g[7] + rotlFixed(g[6], 8) + g[5]);
+}
+
+
+/* IV setup */
+static void wc_RabbitSetIV(Rabbit* ctx, const byte* inIv)
+{
+    /* Temporary variables */
+    word32 i0, i1, i2, i3, i;
+    word32 iv[2];
+
+    if (inIv)
+        XMEMCPY(iv, inIv, sizeof(iv));
+    else
+        XMEMSET(iv,    0, sizeof(iv));
+
+    /* Generate four subvectors */
+    i0 = LITTLE32(iv[0]);
+    i2 = LITTLE32(iv[1]);
+    i1 = (i0>>16) | (i2&0xFFFF0000);
+    i3 = (i2<<16) | (i0&0x0000FFFF);
+
+    /* Modify counter values */
+    ctx->workCtx.c[0] = ctx->masterCtx.c[0] ^ i0;
+    ctx->workCtx.c[1] = ctx->masterCtx.c[1] ^ i1;
+    ctx->workCtx.c[2] = ctx->masterCtx.c[2] ^ i2;
+    ctx->workCtx.c[3] = ctx->masterCtx.c[3] ^ i3;
+    ctx->workCtx.c[4] = ctx->masterCtx.c[4] ^ i0;
+    ctx->workCtx.c[5] = ctx->masterCtx.c[5] ^ i1;
+    ctx->workCtx.c[6] = ctx->masterCtx.c[6] ^ i2;
+    ctx->workCtx.c[7] = ctx->masterCtx.c[7] ^ i3;
+
+    /* Copy state variables */
+    for (i=0; i<8; i++)
+        ctx->workCtx.x[i] = ctx->masterCtx.x[i];
+    ctx->workCtx.carry = ctx->masterCtx.carry;
+
+    /* Iterate the system four times */
+    for (i=0; i<4; i++)
+        RABBIT_next_state(&(ctx->workCtx));
+}
+
+
+/* Key setup */
+static WC_INLINE int DoKey(Rabbit* ctx, const byte* key, const byte* iv)
+{
+    /* Temporary variables */
+    word32 k0, k1, k2, k3, i;
+
+    /* Generate four subkeys */
+    k0 = LITTLE32(*(word32*)(key+ 0));
+    k1 = LITTLE32(*(word32*)(key+ 4));
+    k2 = LITTLE32(*(word32*)(key+ 8));
+    k3 = LITTLE32(*(word32*)(key+12));
+
+    /* Generate initial state variables */
+    ctx->masterCtx.x[0] = k0;
+    ctx->masterCtx.x[2] = k1;
+    ctx->masterCtx.x[4] = k2;
+    ctx->masterCtx.x[6] = k3;
+    ctx->masterCtx.x[1] = U32V(k3<<16) | (k2>>16);
+    ctx->masterCtx.x[3] = U32V(k0<<16) | (k3>>16);
+    ctx->masterCtx.x[5] = U32V(k1<<16) | (k0>>16);
+    ctx->masterCtx.x[7] = U32V(k2<<16) | (k1>>16);
+
+    /* Generate initial counter values */
+    ctx->masterCtx.c[0] = rotlFixed(k2, 16);
+    ctx->masterCtx.c[2] = rotlFixed(k3, 16);
+    ctx->masterCtx.c[4] = rotlFixed(k0, 16);
+    ctx->masterCtx.c[6] = rotlFixed(k1, 16);
+    ctx->masterCtx.c[1] = (k0&0xFFFF0000) | (k1&0xFFFF);
+    ctx->masterCtx.c[3] = (k1&0xFFFF0000) | (k2&0xFFFF);
+    ctx->masterCtx.c[5] = (k2&0xFFFF0000) | (k3&0xFFFF);
+    ctx->masterCtx.c[7] = (k3&0xFFFF0000) | (k0&0xFFFF);
+
+    /* Clear carry bit */
+    ctx->masterCtx.carry = 0;
+
+    /* Iterate the system four times */
+    for (i=0; i<4; i++)
+        RABBIT_next_state(&(ctx->masterCtx));
+
+    /* Modify the counters */
+    for (i=0; i<8; i++)
+        ctx->masterCtx.c[i] ^= ctx->masterCtx.x[(i+4)&0x7];
+
+    /* Copy master instance to work instance */
+    for (i=0; i<8; i++) {
+        ctx->workCtx.x[i] = ctx->masterCtx.x[i];
+        ctx->workCtx.c[i] = ctx->masterCtx.c[i];
+    }
+    ctx->workCtx.carry = ctx->masterCtx.carry;
+
+    wc_RabbitSetIV(ctx, iv);
+
+    return 0;
+}
+
+
+int wc_Rabbit_SetHeap(Rabbit* ctx, void* heap)
+{
+    if (ctx == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef XSTREAM_ALIGN
+    ctx->heap = heap;
+#endif
+
+    (void)heap;
+    return 0;
+}
+
+
+/* Key setup */
+int wc_RabbitSetKey(Rabbit* ctx, const byte* key, const byte* iv)
+{
+    if (ctx == NULL || key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef XSTREAM_ALIGN
+    /* default heap to NULL or heap test value */
+    #ifdef WOLFSSL_HEAP_TEST
+        ctx->heap = (void*)WOLFSSL_HEAP_TEST;
+    #else
+        ctx->heap = NULL;
+    #endif /* WOLFSSL_HEAP_TEST */
+
+    if ((wolfssl_word)key % 4) {
+        int alignKey[4];
+
+        /* iv aligned in SetIV */
+        WOLFSSL_MSG("wc_RabbitSetKey unaligned key");
+
+        XMEMCPY(alignKey, key, sizeof(alignKey));
+
+        return DoKey(ctx, (const byte*)alignKey, iv);
+    }
+#endif /* XSTREAM_ALIGN */
+
+    return DoKey(ctx, key, iv);
+}
+
+
+/* Encrypt/decrypt a message of any size */
+static WC_INLINE int DoProcess(Rabbit* ctx, byte* output, const byte* input,
+                            word32 msglen)
+{
+    /* Encrypt/decrypt all full blocks */
+    while (msglen >= 16) {
+        /* Iterate the system */
+        RABBIT_next_state(&(ctx->workCtx));
+
+        /* Encrypt/decrypt 16 bytes of data */
+        *(word32*)(output+ 0) = *(word32*)(input+ 0) ^
+                   LITTLE32(ctx->workCtx.x[0] ^ (ctx->workCtx.x[5]>>16) ^
+                   U32V(ctx->workCtx.x[3]<<16));
+        *(word32*)(output+ 4) = *(word32*)(input+ 4) ^
+                   LITTLE32(ctx->workCtx.x[2] ^ (ctx->workCtx.x[7]>>16) ^
+                   U32V(ctx->workCtx.x[5]<<16));
+        *(word32*)(output+ 8) = *(word32*)(input+ 8) ^
+                   LITTLE32(ctx->workCtx.x[4] ^ (ctx->workCtx.x[1]>>16) ^
+                   U32V(ctx->workCtx.x[7]<<16));
+        *(word32*)(output+12) = *(word32*)(input+12) ^
+                   LITTLE32(ctx->workCtx.x[6] ^ (ctx->workCtx.x[3]>>16) ^
+                   U32V(ctx->workCtx.x[1]<<16));
+
+        /* Increment pointers and decrement length */
+        input  += 16;
+        output += 16;
+        msglen -= 16;
+    }
+
+    /* Encrypt/decrypt remaining data */
+    if (msglen) {
+
+        word32 i;
+        word32 tmp[4];
+        byte*  buffer = (byte*)tmp;
+
+        XMEMSET(tmp, 0, sizeof(tmp));   /* help static analysis */
+
+        /* Iterate the system */
+        RABBIT_next_state(&(ctx->workCtx));
+
+        /* Generate 16 bytes of pseudo-random data */
+        tmp[0] = LITTLE32(ctx->workCtx.x[0] ^
+                  (ctx->workCtx.x[5]>>16) ^ U32V(ctx->workCtx.x[3]<<16));
+        tmp[1] = LITTLE32(ctx->workCtx.x[2] ^
+                  (ctx->workCtx.x[7]>>16) ^ U32V(ctx->workCtx.x[5]<<16));
+        tmp[2] = LITTLE32(ctx->workCtx.x[4] ^
+                  (ctx->workCtx.x[1]>>16) ^ U32V(ctx->workCtx.x[7]<<16));
+        tmp[3] = LITTLE32(ctx->workCtx.x[6] ^
+                  (ctx->workCtx.x[3]>>16) ^ U32V(ctx->workCtx.x[1]<<16));
+
+        /* Encrypt/decrypt the data */
+        for (i=0; i<msglen; i++)
+            output[i] = input[i] ^ buffer[i];
+    }
+
+    return 0;
+}
+
+
+/* Encrypt/decrypt a message of any size */
+int wc_RabbitProcess(Rabbit* ctx, byte* output, const byte* input, word32 msglen)
+{
+    if (ctx == NULL || output == NULL || input == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef XSTREAM_ALIGN
+    if ((wolfssl_word)input % 4 || (wolfssl_word)output % 4) {
+        #ifndef NO_WOLFSSL_ALLOC_ALIGN
+            byte* tmp;
+            WOLFSSL_MSG("wc_RabbitProcess unaligned");
+
+            tmp = (byte*)XMALLOC(msglen, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            if (tmp == NULL) return MEMORY_E;
+
+            XMEMCPY(tmp, input, msglen);
+            DoProcess(ctx, tmp, tmp, msglen);
+            XMEMCPY(output, tmp, msglen);
+
+            XFREE(tmp, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+            return 0;
+        #else
+            return BAD_ALIGN_E;
+        #endif
+    }
+#endif /* XSTREAM_ALIGN */
+
+    return DoProcess(ctx, output, input, msglen);
+}
+
+
+#endif /* NO_RABBIT */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/random.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/random.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/random.c	(revision 453)
@@ -0,0 +1,2552 @@
+/* random.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+
+/* on HPUX 11 you may need to install /dev/random see
+   http://h20293.www2.hp.com/portal/swdepot/displayProductInfo.do?productNumber=KRNG11I
+
+*/
+
+#if defined(HAVE_FIPS) && \
+    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
+
+    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
+    #define FIPS_NO_WRAPPERS
+
+    #ifdef USE_WINDOWS_API
+        #pragma code_seg(".fipsA$c")
+        #pragma const_seg(".fipsB$c")
+    #endif
+#endif
+
+
+#include <wolfssl/wolfcrypt/random.h>
+#include <wolfssl/wolfcrypt/cpuid.h>
+
+
+/* If building for old FIPS. */
+#if defined(HAVE_FIPS) && \
+    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
+
+int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz)
+{
+    return GenerateSeed(os, seed, sz);
+}
+
+int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId)
+{
+    (void)heap;
+    (void)devId;
+    return InitRng_fips(rng);
+}
+
+int wc_InitRng(WC_RNG* rng)
+{
+    return InitRng_fips(rng);
+}
+
+
+int wc_RNG_GenerateBlock(WC_RNG* rng, byte* b, word32 sz)
+{
+    return RNG_GenerateBlock_fips(rng, b, sz);
+}
+
+
+int wc_RNG_GenerateByte(WC_RNG* rng, byte* b)
+{
+    return RNG_GenerateByte(rng, b);
+}
+
+#ifdef HAVE_HASHDRBG
+
+    int wc_FreeRng(WC_RNG* rng)
+    {
+        return FreeRng_fips(rng);
+    }
+
+    int wc_RNG_HealthTest(int reseed, const byte* seedA, word32 seedASz,
+                                      const byte* seedB, word32 seedBSz,
+                                      byte* output, word32 outputSz)
+    {
+        return RNG_HealthTest_fips(reseed, seedA, seedASz,
+                              seedB, seedBSz, output, outputSz);
+   }
+#endif /* HAVE_HASHDRBG */
+
+#else /* else build without fips, or for new fips */
+
+#ifndef WC_NO_RNG /* if not FIPS and RNG is disabled then do not compile */
+
+#include <wolfssl/wolfcrypt/sha256.h>
+
+#ifdef WOLF_CRYPTO_CB
+    #include <wolfssl/wolfcrypt/cryptocb.h>
+#endif
+
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+#if defined(WOLFSSL_SGX)
+    #include <sgx_trts.h>
+#elif defined(USE_WINDOWS_API)
+    #ifndef _WIN32_WINNT
+        #define _WIN32_WINNT 0x0400
+    #endif
+    #include <windows.h>
+    #include <wincrypt.h>
+#elif defined(HAVE_WNR)
+    #include <wnr.h>
+    #include <wolfssl/wolfcrypt/logging.h>
+    wolfSSL_Mutex wnr_mutex;    /* global netRandom mutex */
+    int wnr_timeout     = 0;    /* entropy timeout, mililseconds */
+    int wnr_mutex_init  = 0;    /* flag for mutex init */
+    wnr_context*  wnr_ctx;      /* global netRandom context */
+#elif defined(FREESCALE_KSDK_2_0_TRNG)
+    #include "fsl_trng.h"
+#elif defined(FREESCALE_KSDK_2_0_RNGA)
+    #include "fsl_rnga.h"
+#elif defined(WOLFSSL_WICED)
+    #include "wiced_crypto.h"
+#elif defined(WOLFSSL_NETBURNER)
+    #include <predef.h>
+    #include <basictypes.h>
+    #include <random.h>
+#elif defined(NO_DEV_RANDOM)
+#elif defined(CUSTOM_RAND_GENERATE)
+#elif defined(CUSTOM_RAND_GENERATE_BLOCK)
+#elif defined(CUSTOM_RAND_GENERATE_SEED)
+#elif defined(WOLFSSL_GENSEED_FORTEST)
+#elif defined(WOLFSSL_MDK_ARM)
+#elif defined(WOLFSSL_IAR_ARM)
+#elif defined(WOLFSSL_ROWLEY_ARM)
+#elif defined(WOLFSSL_EMBOS)
+#elif defined(WOLFSSL_DEOS)
+#elif defined(MICRIUM)
+#elif defined(WOLFSSL_NUCLEUS)
+#elif defined(WOLFSSL_PB)
+#elif defined(WOLFSSL_ZEPHYR)
+#elif defined(WOLFSSL_TELIT_M2MB)
+#elif defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_TRNG)
+#else
+    /* include headers that may be needed to get good seed */
+    #include <fcntl.h>
+    #ifndef EBSNET
+        #include <unistd.h>
+    #endif
+#endif
+
+
+#if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED)
+    static word32 intel_flags = 0;
+    static void wc_InitRng_IntelRD(void)
+    {
+        intel_flags = cpuid_get_flags();
+    }
+    #ifdef HAVE_INTEL_RDSEED
+    static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz);
+    #endif
+    #ifdef HAVE_INTEL_RDRAND
+    static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz);
+    #endif
+
+#ifdef USE_WINDOWS_API
+    #include <immintrin.h>
+#endif /* USE_WINDOWS_API */
+#endif
+
+/* Start NIST DRBG code */
+#ifdef HAVE_HASHDRBG
+
+#define OUTPUT_BLOCK_LEN  (WC_SHA256_DIGEST_SIZE)
+#define MAX_REQUEST_LEN   (0x10000)
+#define RESEED_INTERVAL   WC_RESEED_INTERVAL
+
+
+/* For FIPS builds, the user should not be adjusting the values. */
+#if defined(HAVE_FIPS) && \
+    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
+    #if defined(RNG_SECURITY_STRENGTH) \
+            || defined(ENTROPY_SCALE_FACTOR) \
+            || defined(SEED_BLOCK_SZ)
+
+        #error "Do not change the RNG parameters for FIPS builds."
+    #endif
+#endif
+
+
+/* The security strength for the RNG is the target number of bits of
+ * entropy you are looking for in a seed. */
+#ifndef RNG_SECURITY_STRENGTH
+    #if defined(HAVE_FIPS) && \
+        defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
+        /* SHA-256 requires a minimum of 256-bits of entropy. The goal
+         * of 1024 will provide 4 times that. */
+        #define RNG_SECURITY_STRENGTH (1024)
+    #else
+        /* If not using FIPS or using old FIPS, set the number down a bit.
+         * More is better, but more is also slower. */
+        #define RNG_SECURITY_STRENGTH (256)
+    #endif
+#endif
+
+#ifndef ENTROPY_SCALE_FACTOR
+    /* The entropy scale factor should be the whole number inverse of the
+     * minimum bits of entropy per bit of NDRNG output. */
+    #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND)
+        /* The value of 2 applies to Intel's RDSEED which provides about
+         * 0.5 bits minimum of entropy per bit. */
+        #define ENTROPY_SCALE_FACTOR 2
+    #else
+        /* Setting the default to 1. */
+        #define ENTROPY_SCALE_FACTOR 1
+    #endif
+#endif
+
+#ifndef SEED_BLOCK_SZ
+    /* The seed block size, is the size of the output of the underlying NDRNG.
+     * This value is used for testing the output of the NDRNG. */
+    #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND)
+        /* RDSEED outputs in blocks of 64-bits. */
+        #define SEED_BLOCK_SZ sizeof(word64)
+    #else
+        /* Setting the default to 4. */
+        #define SEED_BLOCK_SZ 4
+    #endif
+#endif
+
+#define SEED_SZ        (RNG_SECURITY_STRENGTH*ENTROPY_SCALE_FACTOR/8)
+
+/* The maximum seed size will be the seed size plus a seed block for the
+ * test, and an additional half of the seed size. This additional half
+ * is in case the user does not supply a nonce. A nonce will be obtained
+ * from the NDRNG. */
+#define MAX_SEED_SZ    (SEED_SZ + SEED_SZ/2 + SEED_BLOCK_SZ)
+
+
+/* Internal return codes */
+#define DRBG_SUCCESS      0
+#define DRBG_FAILURE      1
+#define DRBG_NEED_RESEED  2
+#define DRBG_CONT_FAILURE 3
+
+/* RNG health states */
+#define DRBG_NOT_INIT     0
+#define DRBG_OK           1
+#define DRBG_FAILED       2
+#define DRBG_CONT_FAILED  3
+
+#define RNG_HEALTH_TEST_CHECK_SIZE (WC_SHA256_DIGEST_SIZE * 4)
+
+/* Verify max gen block len */
+#if RNG_MAX_BLOCK_LEN > MAX_REQUEST_LEN
+    #error RNG_MAX_BLOCK_LEN is larger than NIST DBRG max request length
+#endif
+
+enum {
+    drbgInitC     = 0,
+    drbgReseed    = 1,
+    drbgGenerateW = 2,
+    drbgGenerateH = 3,
+    drbgInitV
+};
+
+/* NOTE: if DRBG struct is changed please update random.h drbg_data size */
+typedef struct DRBG {
+    word32 reseedCtr;
+    word32 lastBlock;
+    byte V[DRBG_SEED_LEN];
+    byte C[DRBG_SEED_LEN];
+#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
+    void* heap;
+    int devId;
+#endif
+    byte   matchCount;
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+    wc_Sha256 sha256;
+#endif
+} DRBG;
+
+
+static int wc_RNG_HealthTestLocal(int reseed);
+
+/* Hash Derivation Function */
+/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
+static int Hash_df(DRBG* drbg, byte* out, word32 outSz, byte type,
+                                                  const byte* inA, word32 inASz,
+                                                  const byte* inB, word32 inBSz)
+{
+    int ret = DRBG_FAILURE;
+    byte ctr;
+    int i;
+    int len;
+    word32 bits = (outSz * 8); /* reverse byte order */
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+    wc_Sha256* sha = &drbg->sha256;
+#else
+    wc_Sha256 sha[1];
+#endif
+#ifdef WC_ASYNC_ENABLE_SHA256
+    DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap);
+    if (digest == NULL)
+        return MEMORY_E;
+#else
+    byte digest[WC_SHA256_DIGEST_SIZE];
+#endif
+
+    (void)drbg;
+#ifdef WC_ASYNC_ENABLE_SHA256
+    if (digest == NULL)
+        return DRBG_FAILURE;
+#endif
+
+#ifdef LITTLE_ENDIAN_ORDER
+    bits = ByteReverseWord32(bits);
+#endif
+    len = (outSz / OUTPUT_BLOCK_LEN)
+        + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0);
+
+    for (i = 0, ctr = 1; i < len; i++, ctr++) {
+#ifndef WOLFSSL_SMALL_STACK_CACHE
+    #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
+        ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId);
+    #else
+        ret = wc_InitSha256(sha);
+    #endif
+        if (ret != 0)
+            break;
+
+        if (ret == 0)
+#endif
+            ret = wc_Sha256Update(sha, &ctr, sizeof(ctr));
+        if (ret == 0)
+            ret = wc_Sha256Update(sha, (byte*)&bits, sizeof(bits));
+
+        if (ret == 0) {
+            /* churning V is the only string that doesn't have the type added */
+            if (type != drbgInitV)
+                ret = wc_Sha256Update(sha, &type, sizeof(type));
+        }
+        if (ret == 0)
+            ret = wc_Sha256Update(sha, inA, inASz);
+        if (ret == 0) {
+            if (inB != NULL && inBSz > 0)
+                ret = wc_Sha256Update(sha, inB, inBSz);
+        }
+        if (ret == 0)
+            ret = wc_Sha256Final(sha, digest);
+
+#ifndef WOLFSSL_SMALL_STACK_CACHE
+        wc_Sha256Free(sha);
+#endif
+        if (ret == 0) {
+            if (outSz > OUTPUT_BLOCK_LEN) {
+                XMEMCPY(out, digest, OUTPUT_BLOCK_LEN);
+                outSz -= OUTPUT_BLOCK_LEN;
+                out += OUTPUT_BLOCK_LEN;
+            }
+            else {
+                XMEMCPY(out, digest, outSz);
+            }
+        }
+    }
+
+    ForceZero(digest, WC_SHA256_DIGEST_SIZE);
+
+#ifdef WC_ASYNC_ENABLE_SHA256
+    FREE_VAR(digest, drbg->heap);
+#endif
+
+    return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
+}
+
+/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
+static int Hash_DRBG_Reseed(DRBG* drbg, const byte* seed, word32 seedSz)
+{
+    byte newV[DRBG_SEED_LEN];
+
+    XMEMSET(newV, 0, DRBG_SEED_LEN);
+
+    if (Hash_df(drbg, newV, sizeof(newV), drbgReseed,
+                drbg->V, sizeof(drbg->V), seed, seedSz) != DRBG_SUCCESS) {
+        return DRBG_FAILURE;
+    }
+
+    XMEMCPY(drbg->V, newV, sizeof(drbg->V));
+    ForceZero(newV, sizeof(newV));
+
+    if (Hash_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V,
+                                    sizeof(drbg->V), NULL, 0) != DRBG_SUCCESS) {
+        return DRBG_FAILURE;
+    }
+
+    drbg->reseedCtr = 1;
+    drbg->lastBlock = 0;
+    drbg->matchCount = 0;
+    return DRBG_SUCCESS;
+}
+
+/* Returns: DRBG_SUCCESS and DRBG_FAILURE or BAD_FUNC_ARG on fail */
+int wc_RNG_DRBG_Reseed(WC_RNG* rng, const byte* seed, word32 seedSz)
+{
+    if (rng == NULL || seed == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    return Hash_DRBG_Reseed(rng->drbg, seed, seedSz);
+}
+
+static WC_INLINE void array_add_one(byte* data, word32 dataSz)
+{
+    int i;
+
+    for (i = dataSz - 1; i >= 0; i--)
+    {
+        data[i]++;
+        if (data[i] != 0) break;
+    }
+}
+
+/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
+static int Hash_gen(DRBG* drbg, byte* out, word32 outSz, const byte* V)
+{
+    int ret = DRBG_FAILURE;
+    byte data[DRBG_SEED_LEN];
+    int i;
+    int len;
+    word32 checkBlock;
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+    wc_Sha256* sha = &drbg->sha256;
+#else
+    wc_Sha256 sha[1];
+#endif
+#ifdef WC_ASYNC_ENABLE_SHA256
+    DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap);
+    if (digest == NULL)
+        return MEMORY_E;
+#else
+    byte digest[WC_SHA256_DIGEST_SIZE];
+#endif
+
+    /* Special case: outSz is 0 and out is NULL. wc_Generate a block to save for
+     * the continuous test. */
+
+    if (outSz == 0) outSz = 1;
+
+    len = (outSz / OUTPUT_BLOCK_LEN) + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0);
+
+    XMEMCPY(data, V, sizeof(data));
+    for (i = 0; i < len; i++) {
+#ifndef WOLFSSL_SMALL_STACK_CACHE
+    #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
+        ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId);
+    #else
+        ret = wc_InitSha256(sha);
+    #endif
+        if (ret == 0)
+#endif
+            ret = wc_Sha256Update(sha, data, sizeof(data));
+        if (ret == 0)
+            ret = wc_Sha256Final(sha, digest);
+#ifndef WOLFSSL_SMALL_STACK_CACHE
+        wc_Sha256Free(sha);
+#endif
+
+        if (ret == 0) {
+            XMEMCPY(&checkBlock, digest, sizeof(word32));
+            if (drbg->reseedCtr > 1 && checkBlock == drbg->lastBlock) {
+                if (drbg->matchCount == 1) {
+                    return DRBG_CONT_FAILURE;
+                }
+                else {
+                    if (i == len) {
+                        len++;
+                    }
+                    drbg->matchCount = 1;
+                }
+            }
+            else {
+                drbg->matchCount = 0;
+                drbg->lastBlock = checkBlock;
+            }
+
+            if (out != NULL && outSz != 0) {
+                if (outSz >= OUTPUT_BLOCK_LEN) {
+                    XMEMCPY(out, digest, OUTPUT_BLOCK_LEN);
+                    outSz -= OUTPUT_BLOCK_LEN;
+                    out += OUTPUT_BLOCK_LEN;
+                    array_add_one(data, DRBG_SEED_LEN);
+                }
+                else {
+                    XMEMCPY(out, digest, outSz);
+                    outSz = 0;
+                }
+            }
+        }
+    }
+    ForceZero(data, sizeof(data));
+
+#ifdef WC_ASYNC_ENABLE_SHA256
+    FREE_VAR(digest, drbg->heap);
+#endif
+
+    return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
+}
+
+static WC_INLINE void array_add(byte* d, word32 dLen, const byte* s, word32 sLen)
+{
+    word16 carry = 0;
+
+    if (dLen > 0 && sLen > 0 && dLen >= sLen) {
+        int sIdx, dIdx;
+
+        for (sIdx = sLen - 1, dIdx = dLen - 1; sIdx >= 0; dIdx--, sIdx--)
+        {
+            carry += d[dIdx] + s[sIdx];
+            d[dIdx] = (byte)carry;
+            carry >>= 8;
+        }
+
+        for (; carry != 0 && dIdx >= 0; dIdx--) {
+            carry += d[dIdx];
+            d[dIdx] = (byte)carry;
+            carry >>= 8;
+        }
+    }
+}
+
+/* Returns: DRBG_SUCCESS, DRBG_NEED_RESEED, or DRBG_FAILURE */
+static int Hash_DRBG_Generate(DRBG* drbg, byte* out, word32 outSz)
+{
+    int ret;
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+    wc_Sha256* sha = &drbg->sha256;
+#else
+    wc_Sha256 sha[1];
+#endif
+    byte type;
+    word32 reseedCtr;
+
+    if (drbg->reseedCtr == RESEED_INTERVAL) {
+        return DRBG_NEED_RESEED;
+    } else {
+    #ifdef WC_ASYNC_ENABLE_SHA256
+        DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap);
+        if (digest == NULL)
+            return MEMORY_E;
+    #else
+        byte digest[WC_SHA256_DIGEST_SIZE];
+    #endif
+        type = drbgGenerateH;
+        reseedCtr = drbg->reseedCtr;
+
+        ret = Hash_gen(drbg, out, outSz, drbg->V);
+        if (ret == DRBG_SUCCESS) {
+#ifndef WOLFSSL_SMALL_STACK_CACHE
+        #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
+            ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId);
+        #else
+            ret = wc_InitSha256(sha);
+        #endif
+            if (ret == 0)
+#endif
+                ret = wc_Sha256Update(sha, &type, sizeof(type));
+            if (ret == 0)
+                ret = wc_Sha256Update(sha, drbg->V, sizeof(drbg->V));
+            if (ret == 0)
+                ret = wc_Sha256Final(sha, digest);
+
+#ifndef WOLFSSL_SMALL_STACK_CACHE
+            wc_Sha256Free(sha);
+#endif
+
+            if (ret == 0) {
+                array_add(drbg->V, sizeof(drbg->V), digest, WC_SHA256_DIGEST_SIZE);
+                array_add(drbg->V, sizeof(drbg->V), drbg->C, sizeof(drbg->C));
+            #ifdef LITTLE_ENDIAN_ORDER
+                reseedCtr = ByteReverseWord32(reseedCtr);
+            #endif
+                array_add(drbg->V, sizeof(drbg->V),
+                                          (byte*)&reseedCtr, sizeof(reseedCtr));
+                ret = DRBG_SUCCESS;
+            }
+            drbg->reseedCtr++;
+        }
+        ForceZero(digest, WC_SHA256_DIGEST_SIZE);
+    #ifdef WC_ASYNC_ENABLE_SHA256
+        FREE_VAR(digest, drbg->heap);
+    #endif
+    }
+
+    return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
+}
+
+/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
+static int Hash_DRBG_Instantiate(DRBG* drbg, const byte* seed, word32 seedSz,
+                                             const byte* nonce, word32 nonceSz,
+                                             void* heap, int devId)
+{
+    int ret;
+
+    XMEMSET(drbg, 0, sizeof(DRBG));
+#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
+    drbg->heap = heap;
+    drbg->devId = devId;
+#else
+    (void)heap;
+    (void)devId;
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+    #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
+        ret = wc_InitSha256_ex(&drbg->sha256, drbg->heap, drbg->devId);
+    #else
+        ret = wc_InitSha256(&drbg->sha256);
+    #endif
+    if (ret != 0)
+        return ret;
+#endif
+
+    if (Hash_df(drbg, drbg->V, sizeof(drbg->V), drbgInitV, seed, seedSz,
+                                              nonce, nonceSz) == DRBG_SUCCESS &&
+        Hash_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V,
+                                    sizeof(drbg->V), NULL, 0) == DRBG_SUCCESS) {
+
+        drbg->reseedCtr = 1;
+        drbg->lastBlock = 0;
+        drbg->matchCount = 0;
+        ret = DRBG_SUCCESS;
+    }
+    else {
+        ret = DRBG_FAILURE;
+    }
+
+    return ret;
+}
+
+/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
+static int Hash_DRBG_Uninstantiate(DRBG* drbg)
+{
+    word32 i;
+    int    compareSum = 0;
+    byte*  compareDrbg = (byte*)drbg;
+
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+    wc_Sha256Free(&drbg->sha256);
+#endif
+
+    ForceZero(drbg, sizeof(DRBG));
+
+    for (i = 0; i < sizeof(DRBG); i++)
+        compareSum |= compareDrbg[i] ^ 0;
+
+    return (compareSum == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
+}
+
+
+int wc_RNG_TestSeed(const byte* seed, word32 seedSz)
+{
+    int ret = DRBG_SUCCESS;
+
+    /* Check the seed for duplicate words. */
+    word32 seedIdx = 0;
+    word32 scratchSz = min(SEED_BLOCK_SZ, seedSz - SEED_BLOCK_SZ);
+
+    while (seedIdx < seedSz - SEED_BLOCK_SZ) {
+        if (ConstantCompare(seed + seedIdx,
+                            seed + seedIdx + scratchSz,
+                            scratchSz) == 0) {
+
+            ret = DRBG_CONT_FAILURE;
+        }
+        seedIdx += SEED_BLOCK_SZ;
+        scratchSz = min(SEED_BLOCK_SZ, (seedSz - seedIdx));
+    }
+
+    return ret;
+}
+#endif /* HAVE_HASHDRBG */
+/* End NIST DRBG Code */
+
+
+static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz,
+                    void* heap, int devId)
+{
+    int ret = RNG_FAILURE_E;
+#ifdef HAVE_HASHDRBG
+    word32 seedSz = SEED_SZ + SEED_BLOCK_SZ;
+#endif
+
+    (void)nonce;
+    (void)nonceSz;
+
+    if (rng == NULL)
+        return BAD_FUNC_ARG;
+    if (nonce == NULL && nonceSz != 0)
+        return BAD_FUNC_ARG;
+
+#ifdef WOLFSSL_HEAP_TEST
+    rng->heap = (void*)WOLFSSL_HEAP_TEST;
+    (void)heap;
+#else
+    rng->heap = heap;
+#endif
+#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
+    rng->devId = devId;
+    #if defined(WOLF_CRYPTO_CB)
+        rng->seed.devId = devId;
+    #endif
+#else
+    (void)devId;
+#endif
+
+#ifdef HAVE_HASHDRBG
+    /* init the DBRG to known values */
+    rng->drbg = NULL;
+    rng->status = DRBG_NOT_INIT;
+#endif
+
+#if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND)
+    /* init the intel RD seed and/or rand */
+    wc_InitRng_IntelRD();
+#endif
+
+    /* configure async RNG source if available */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ret = wolfAsync_DevCtxInit(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG,
+                                                        rng->heap, rng->devId);
+    if (ret != 0)
+        return ret;
+#endif
+
+#ifdef HAVE_INTEL_RDRAND
+    /* if CPU supports RDRAND, use it directly and by-pass DRBG init */
+    if (IS_INTEL_RDRAND(intel_flags))
+        return 0;
+#endif
+
+#ifdef CUSTOM_RAND_GENERATE_BLOCK
+    ret = 0; /* success */
+#else
+#ifdef HAVE_HASHDRBG
+    if (nonceSz == 0)
+        seedSz = MAX_SEED_SZ;
+
+    if (wc_RNG_HealthTestLocal(0) == 0) {
+    #ifdef WC_ASYNC_ENABLE_SHA256
+        DECLARE_VAR(seed, byte, MAX_SEED_SZ, rng->heap);
+        if (seed == NULL)
+            return MEMORY_E;
+    #else
+        byte seed[MAX_SEED_SZ];
+    #endif
+
+#if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
+        rng->drbg =
+                (struct DRBG*)XMALLOC(sizeof(DRBG), rng->heap,
+                                                          DYNAMIC_TYPE_RNG);
+#else
+        /* compile-time validation of drbg_data size */
+        typedef char drbg_data_test[sizeof(rng->drbg_data) >=
+                sizeof(struct DRBG) ? 1 : -1];
+        (void)sizeof(drbg_data_test);
+        rng->drbg = (struct DRBG*)rng->drbg_data;
+#endif
+
+        if (rng->drbg == NULL) {
+            ret = MEMORY_E;
+        }
+        else {
+            ret = wc_GenerateSeed(&rng->seed, seed, seedSz);
+            if (ret != 0)
+                ret = DRBG_FAILURE;
+            else
+                ret = wc_RNG_TestSeed(seed, seedSz);
+
+            if (ret == DRBG_SUCCESS)
+                 ret = Hash_DRBG_Instantiate(rng->drbg,
+                            seed + SEED_BLOCK_SZ, seedSz - SEED_BLOCK_SZ,
+                            nonce, nonceSz, rng->heap, devId);
+
+            if (ret != DRBG_SUCCESS) {
+            #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
+                XFREE(rng->drbg, rng->heap, DYNAMIC_TYPE_RNG);
+            #endif
+                rng->drbg = NULL;
+            }
+        }
+
+        ForceZero(seed, seedSz);
+    #ifdef WC_ASYNC_ENABLE_SHA256
+        FREE_VAR(seed, rng->heap);
+    #endif
+    }
+    else
+        ret = DRBG_CONT_FAILURE;
+
+    if (ret == DRBG_SUCCESS) {
+        rng->status = DRBG_OK;
+        ret = 0;
+    }
+    else if (ret == DRBG_CONT_FAILURE) {
+        rng->status = DRBG_CONT_FAILED;
+        ret = DRBG_CONT_FIPS_E;
+    }
+    else if (ret == DRBG_FAILURE) {
+        rng->status = DRBG_FAILED;
+        ret = RNG_FAILURE_E;
+    }
+    else {
+        rng->status = DRBG_FAILED;
+    }
+#endif /* HAVE_HASHDRBG */
+#endif /* CUSTOM_RAND_GENERATE_BLOCK */
+
+    return ret;
+}
+
+
+WOLFSSL_ABI
+WC_RNG* wc_rng_new(byte* nonce, word32 nonceSz, void* heap)
+{
+    WC_RNG* rng;
+
+    rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), heap, DYNAMIC_TYPE_RNG);
+    if (rng) {
+        int error = _InitRng(rng, nonce, nonceSz, heap, INVALID_DEVID) != 0;
+        if (error) {
+            XFREE(rng, heap, DYNAMIC_TYPE_RNG);
+            rng = NULL;
+        }
+    }
+
+    return rng;
+}
+
+
+WOLFSSL_ABI
+void wc_rng_free(WC_RNG* rng)
+{
+    if (rng) {
+        void* heap = rng->heap;
+
+        wc_FreeRng(rng);
+        ForceZero(rng, sizeof(WC_RNG));
+        XFREE(rng, heap, DYNAMIC_TYPE_RNG);
+        (void)heap;
+    }
+}
+
+
+int wc_InitRng(WC_RNG* rng)
+{
+    return _InitRng(rng, NULL, 0, NULL, INVALID_DEVID);
+}
+
+
+int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId)
+{
+    return _InitRng(rng, NULL, 0, heap, devId);
+}
+
+
+int wc_InitRngNonce(WC_RNG* rng, byte* nonce, word32 nonceSz)
+{
+    return _InitRng(rng, nonce, nonceSz, NULL, INVALID_DEVID);
+}
+
+
+int wc_InitRngNonce_ex(WC_RNG* rng, byte* nonce, word32 nonceSz,
+                       void* heap, int devId)
+{
+    return _InitRng(rng, nonce, nonceSz, heap, devId);
+}
+
+
+/* place a generated block in output */
+WOLFSSL_ABI
+int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz)
+{
+    int ret;
+
+    if (rng == NULL || output == NULL)
+        return BAD_FUNC_ARG;
+
+#ifdef WOLF_CRYPTO_CB
+    if (rng->devId != INVALID_DEVID) {
+        ret = wc_CryptoCb_RandomBlock(rng, output, sz);
+        if (ret != CRYPTOCB_UNAVAILABLE)
+            return ret;
+        /* fall-through when unavailable */
+    }
+#endif
+
+#ifdef HAVE_INTEL_RDRAND
+    if (IS_INTEL_RDRAND(intel_flags))
+        return wc_GenerateRand_IntelRD(NULL, output, sz);
+#endif
+
+#if defined(WOLFSSL_ASYNC_CRYPT)
+    if (rng->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RNG) {
+        /* these are blocking */
+    #ifdef HAVE_CAVIUM
+        return NitroxRngGenerateBlock(rng, output, sz);
+    #elif defined(HAVE_INTEL_QA) && defined(QAT_ENABLE_RNG)
+        return IntelQaDrbg(&rng->asyncDev, output, sz);
+    #else
+        /* simulator not supported */
+    #endif
+    }
+#endif
+
+#ifdef CUSTOM_RAND_GENERATE_BLOCK
+    XMEMSET(output, 0, sz);
+    ret = CUSTOM_RAND_GENERATE_BLOCK(output, sz);
+#else
+
+#ifdef HAVE_HASHDRBG
+    if (sz > RNG_MAX_BLOCK_LEN)
+        return BAD_FUNC_ARG;
+
+    if (rng->status != DRBG_OK)
+        return RNG_FAILURE_E;
+
+    ret = Hash_DRBG_Generate(rng->drbg, output, sz);
+    if (ret == DRBG_NEED_RESEED) {
+        if (wc_RNG_HealthTestLocal(1) == 0) {
+            byte newSeed[SEED_SZ + SEED_BLOCK_SZ];
+
+            ret = wc_GenerateSeed(&rng->seed, newSeed,
+                                  SEED_SZ + SEED_BLOCK_SZ);
+            if (ret != 0)
+                ret = DRBG_FAILURE;
+            else
+                ret = wc_RNG_TestSeed(newSeed, SEED_SZ + SEED_BLOCK_SZ);
+
+            if (ret == DRBG_SUCCESS)
+                ret = Hash_DRBG_Reseed(rng->drbg, newSeed + SEED_BLOCK_SZ,
+                                       SEED_SZ);
+            if (ret == DRBG_SUCCESS)
+                ret = Hash_DRBG_Generate(rng->drbg, output, sz);
+
+            ForceZero(newSeed, sizeof(newSeed));
+        }
+        else
+            ret = DRBG_CONT_FAILURE;
+    }
+
+    if (ret == DRBG_SUCCESS) {
+        ret = 0;
+    }
+    else if (ret == DRBG_CONT_FAILURE) {
+        ret = DRBG_CONT_FIPS_E;
+        rng->status = DRBG_CONT_FAILED;
+    }
+    else {
+        ret = RNG_FAILURE_E;
+        rng->status = DRBG_FAILED;
+    }
+#else
+
+    /* if we get here then there is an RNG configuration error */
+    ret = RNG_FAILURE_E;
+
+#endif /* HAVE_HASHDRBG */
+#endif /* CUSTOM_RAND_GENERATE_BLOCK */
+
+    return ret;
+}
+
+
+int wc_RNG_GenerateByte(WC_RNG* rng, byte* b)
+{
+    return wc_RNG_GenerateBlock(rng, b, 1);
+}
+
+
+int wc_FreeRng(WC_RNG* rng)
+{
+    int ret = 0;
+
+    if (rng == NULL)
+        return BAD_FUNC_ARG;
+
+#if defined(WOLFSSL_ASYNC_CRYPT)
+    wolfAsync_DevCtxFree(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG);
+#endif
+
+#ifdef HAVE_HASHDRBG
+    if (rng->drbg != NULL) {
+        if (Hash_DRBG_Uninstantiate(rng->drbg) != DRBG_SUCCESS)
+            ret = RNG_FAILURE_E;
+
+    #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
+        XFREE(rng->drbg, rng->heap, DYNAMIC_TYPE_RNG);
+    #endif
+        rng->drbg = NULL;
+    }
+
+    rng->status = DRBG_NOT_INIT;
+#endif /* HAVE_HASHDRBG */
+
+    return ret;
+}
+
+#ifdef HAVE_HASHDRBG
+int wc_RNG_HealthTest(int reseed, const byte* seedA, word32 seedASz,
+                                  const byte* seedB, word32 seedBSz,
+                                  byte* output, word32 outputSz)
+{
+    return wc_RNG_HealthTest_ex(reseed, NULL, 0,
+                                seedA, seedASz, seedB, seedBSz,
+                                output, outputSz,
+                                NULL, INVALID_DEVID);
+}
+
+
+int wc_RNG_HealthTest_ex(int reseed, const byte* nonce, word32 nonceSz,
+                                  const byte* seedA, word32 seedASz,
+                                  const byte* seedB, word32 seedBSz,
+                                  byte* output, word32 outputSz,
+                                  void* heap, int devId)
+{
+    int ret = -1;
+    DRBG* drbg;
+#ifndef WOLFSSL_SMALL_STACK
+    DRBG  drbg_var;
+#endif
+
+    if (seedA == NULL || output == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (reseed != 0 && seedB == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (outputSz != RNG_HEALTH_TEST_CHECK_SIZE) {
+        return ret;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    drbg = (DRBG*)XMALLOC(sizeof(DRBG), NULL, DYNAMIC_TYPE_RNG);
+    if (drbg == NULL) {
+        return MEMORY_E;
+    }
+#else
+    drbg = &drbg_var;
+#endif
+
+    if (Hash_DRBG_Instantiate(drbg, seedA, seedASz, nonce, nonceSz,
+                              heap, devId) != 0) {
+        goto exit_rng_ht;
+    }
+
+    if (reseed) {
+        if (Hash_DRBG_Reseed(drbg, seedB, seedBSz) != 0) {
+            goto exit_rng_ht;
+        }
+    }
+
+    /* This call to generate is prescribed by the NIST DRBGVS
+     * procedure. The results are thrown away. The known
+     * answer test checks the second block of DRBG out of
+     * the generator to ensure the internal state is updated
+     * as expected. */
+    if (Hash_DRBG_Generate(drbg, output, outputSz) != 0) {
+        goto exit_rng_ht;
+    }
+
+    if (Hash_DRBG_Generate(drbg, output, outputSz) != 0) {
+        goto exit_rng_ht;
+    }
+
+    /* Mark success */
+    ret = 0;
+
+exit_rng_ht:
+
+    /* This is safe to call even if Hash_DRBG_Instantiate fails */
+    if (Hash_DRBG_Uninstantiate(drbg) != 0) {
+        ret = -1;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(drbg, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+    return ret;
+}
+
+
+const byte seedA[] = {
+    0x63, 0x36, 0x33, 0x77, 0xe4, 0x1e, 0x86, 0x46, 0x8d, 0xeb, 0x0a, 0xb4,
+    0xa8, 0xed, 0x68, 0x3f, 0x6a, 0x13, 0x4e, 0x47, 0xe0, 0x14, 0xc7, 0x00,
+    0x45, 0x4e, 0x81, 0xe9, 0x53, 0x58, 0xa5, 0x69, 0x80, 0x8a, 0xa3, 0x8f,
+    0x2a, 0x72, 0xa6, 0x23, 0x59, 0x91, 0x5a, 0x9f, 0x8a, 0x04, 0xca, 0x68
+};
+
+const byte reseedSeedA[] = {
+    0xe6, 0x2b, 0x8a, 0x8e, 0xe8, 0xf1, 0x41, 0xb6, 0x98, 0x05, 0x66, 0xe3,
+    0xbf, 0xe3, 0xc0, 0x49, 0x03, 0xda, 0xd4, 0xac, 0x2c, 0xdf, 0x9f, 0x22,
+    0x80, 0x01, 0x0a, 0x67, 0x39, 0xbc, 0x83, 0xd3
+};
+
+const byte outputA[] = {
+    0x04, 0xee, 0xc6, 0x3b, 0xb2, 0x31, 0xdf, 0x2c, 0x63, 0x0a, 0x1a, 0xfb,
+    0xe7, 0x24, 0x94, 0x9d, 0x00, 0x5a, 0x58, 0x78, 0x51, 0xe1, 0xaa, 0x79,
+    0x5e, 0x47, 0x73, 0x47, 0xc8, 0xb0, 0x56, 0x62, 0x1c, 0x18, 0xbd, 0xdc,
+    0xdd, 0x8d, 0x99, 0xfc, 0x5f, 0xc2, 0xb9, 0x20, 0x53, 0xd8, 0xcf, 0xac,
+    0xfb, 0x0b, 0xb8, 0x83, 0x12, 0x05, 0xfa, 0xd1, 0xdd, 0xd6, 0xc0, 0x71,
+    0x31, 0x8a, 0x60, 0x18, 0xf0, 0x3b, 0x73, 0xf5, 0xed, 0xe4, 0xd4, 0xd0,
+    0x71, 0xf9, 0xde, 0x03, 0xfd, 0x7a, 0xea, 0x10, 0x5d, 0x92, 0x99, 0xb8,
+    0xaf, 0x99, 0xaa, 0x07, 0x5b, 0xdb, 0x4d, 0xb9, 0xaa, 0x28, 0xc1, 0x8d,
+    0x17, 0x4b, 0x56, 0xee, 0x2a, 0x01, 0x4d, 0x09, 0x88, 0x96, 0xff, 0x22,
+    0x82, 0xc9, 0x55, 0xa8, 0x19, 0x69, 0xe0, 0x69, 0xfa, 0x8c, 0xe0, 0x07,
+    0xa1, 0x80, 0x18, 0x3a, 0x07, 0xdf, 0xae, 0x17
+};
+
+const byte seedB[] = {
+    0xa6, 0x5a, 0xd0, 0xf3, 0x45, 0xdb, 0x4e, 0x0e, 0xff, 0xe8, 0x75, 0xc3,
+    0xa2, 0xe7, 0x1f, 0x42, 0xc7, 0x12, 0x9d, 0x62, 0x0f, 0xf5, 0xc1, 0x19,
+    0xa9, 0xef, 0x55, 0xf0, 0x51, 0x85, 0xe0, 0xfb, /* nonce next */
+    0x85, 0x81, 0xf9, 0x31, 0x75, 0x17, 0x27, 0x6e, 0x06, 0xe9, 0x60, 0x7d,
+    0xdb, 0xcb, 0xcc, 0x2e
+};
+
+const byte outputB[] = {
+    0xd3, 0xe1, 0x60, 0xc3, 0x5b, 0x99, 0xf3, 0x40, 0xb2, 0x62, 0x82, 0x64,
+    0xd1, 0x75, 0x10, 0x60, 0xe0, 0x04, 0x5d, 0xa3, 0x83, 0xff, 0x57, 0xa5,
+    0x7d, 0x73, 0xa6, 0x73, 0xd2, 0xb8, 0xd8, 0x0d, 0xaa, 0xf6, 0xa6, 0xc3,
+    0x5a, 0x91, 0xbb, 0x45, 0x79, 0xd7, 0x3f, 0xd0, 0xc8, 0xfe, 0xd1, 0x11,
+    0xb0, 0x39, 0x13, 0x06, 0x82, 0x8a, 0xdf, 0xed, 0x52, 0x8f, 0x01, 0x81,
+    0x21, 0xb3, 0xfe, 0xbd, 0xc3, 0x43, 0xe7, 0x97, 0xb8, 0x7d, 0xbb, 0x63,
+    0xdb, 0x13, 0x33, 0xde, 0xd9, 0xd1, 0xec, 0xe1, 0x77, 0xcf, 0xa6, 0xb7,
+    0x1f, 0xe8, 0xab, 0x1d, 0xa4, 0x66, 0x24, 0xed, 0x64, 0x15, 0xe5, 0x1c,
+    0xcd, 0xe2, 0xc7, 0xca, 0x86, 0xe2, 0x83, 0x99, 0x0e, 0xea, 0xeb, 0x91,
+    0x12, 0x04, 0x15, 0x52, 0x8b, 0x22, 0x95, 0x91, 0x02, 0x81, 0xb0, 0x2d,
+    0xd4, 0x31, 0xf4, 0xc9, 0xf7, 0x04, 0x27, 0xdf
+};
+
+
+static int wc_RNG_HealthTestLocal(int reseed)
+{
+    int ret = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    byte* check;
+#else
+    byte  check[RNG_HEALTH_TEST_CHECK_SIZE];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+    check = (byte*)XMALLOC(RNG_HEALTH_TEST_CHECK_SIZE, NULL,
+                           DYNAMIC_TYPE_TMP_BUFFER);
+    if (check == NULL) {
+        return MEMORY_E;
+    }
+#endif
+
+    if (reseed) {
+        ret = wc_RNG_HealthTest(1, seedA, sizeof(seedA),
+                                reseedSeedA, sizeof(reseedSeedA),
+                                check, RNG_HEALTH_TEST_CHECK_SIZE);
+        if (ret == 0) {
+            if (ConstantCompare(check, outputA,
+                                RNG_HEALTH_TEST_CHECK_SIZE) != 0)
+                ret = -1;
+        }
+    }
+    else {
+        ret = wc_RNG_HealthTest(0, seedB, sizeof(seedB),
+                                NULL, 0,
+                                check, RNG_HEALTH_TEST_CHECK_SIZE);
+        if (ret == 0) {
+            if (ConstantCompare(check, outputB,
+                                RNG_HEALTH_TEST_CHECK_SIZE) != 0)
+                ret = -1;
+        }
+
+        /* The previous test cases use a large seed instead of a seed and nonce.
+         * seedB is actually from a test case with a seed and nonce, and
+         * just concatenates them. The pivot point between seed and nonce is
+         * byte 32, feed them into the health test separately. */
+        if (ret == 0) {
+            ret = wc_RNG_HealthTest_ex(0,
+                                    seedB + 32, sizeof(seedB) - 32,
+                                    seedB, 32,
+                                    NULL, 0,
+                                    check, RNG_HEALTH_TEST_CHECK_SIZE,
+                                    NULL, INVALID_DEVID);
+            if (ret == 0) {
+                if (ConstantCompare(check, outputB, sizeof(outputB)) != 0)
+                    ret = -1;
+            }
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(check, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return ret;
+}
+
+#endif /* HAVE_HASHDRBG */
+
+
+#ifdef HAVE_WNR
+
+/*
+ * Init global Whitewood netRandom context
+ * Returns 0 on success, negative on error
+ */
+int wc_InitNetRandom(const char* configFile, wnr_hmac_key hmac_cb, int timeout)
+{
+    if (configFile == NULL || timeout < 0)
+        return BAD_FUNC_ARG;
+
+    if (wnr_mutex_init > 0) {
+        WOLFSSL_MSG("netRandom context already created, skipping");
+        return 0;
+    }
+
+    if (wc_InitMutex(&wnr_mutex) != 0) {
+        WOLFSSL_MSG("Bad Init Mutex wnr_mutex");
+        return BAD_MUTEX_E;
+    }
+    wnr_mutex_init = 1;
+
+    if (wc_LockMutex(&wnr_mutex) != 0) {
+        WOLFSSL_MSG("Bad Lock Mutex wnr_mutex");
+        return BAD_MUTEX_E;
+    }
+
+    /* store entropy timeout */
+    wnr_timeout = timeout;
+
+    /* create global wnr_context struct */
+    if (wnr_create(&wnr_ctx) != WNR_ERROR_NONE) {
+        WOLFSSL_MSG("Error creating global netRandom context");
+        return RNG_FAILURE_E;
+    }
+
+    /* load config file */
+    if (wnr_config_loadf(wnr_ctx, (char*)configFile) != WNR_ERROR_NONE) {
+        WOLFSSL_MSG("Error loading config file into netRandom context");
+        wnr_destroy(wnr_ctx);
+        wnr_ctx = NULL;
+        return RNG_FAILURE_E;
+    }
+
+    /* create/init polling mechanism */
+    if (wnr_poll_create() != WNR_ERROR_NONE) {
+        printf("ERROR: wnr_poll_create() failed\n");
+        WOLFSSL_MSG("Error initializing netRandom polling mechanism");
+        wnr_destroy(wnr_ctx);
+        wnr_ctx = NULL;
+        return RNG_FAILURE_E;
+    }
+
+    /* validate config, set HMAC callback (optional) */
+    if (wnr_setup(wnr_ctx, hmac_cb) != WNR_ERROR_NONE) {
+        WOLFSSL_MSG("Error setting up netRandom context");
+        wnr_destroy(wnr_ctx);
+        wnr_ctx = NULL;
+        wnr_poll_destroy();
+        return RNG_FAILURE_E;
+    }
+
+    wc_UnLockMutex(&wnr_mutex);
+
+    return 0;
+}
+
+/*
+ * Free global Whitewood netRandom context
+ * Returns 0 on success, negative on error
+ */
+int wc_FreeNetRandom(void)
+{
+    if (wnr_mutex_init > 0) {
+
+        if (wc_LockMutex(&wnr_mutex) != 0) {
+            WOLFSSL_MSG("Bad Lock Mutex wnr_mutex");
+            return BAD_MUTEX_E;
+        }
+
+        if (wnr_ctx != NULL) {
+            wnr_destroy(wnr_ctx);
+            wnr_ctx = NULL;
+        }
+        wnr_poll_destroy();
+
+        wc_UnLockMutex(&wnr_mutex);
+
+        wc_FreeMutex(&wnr_mutex);
+        wnr_mutex_init = 0;
+    }
+
+    return 0;
+}
+
+#endif /* HAVE_WNR */
+
+
+#if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED)
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* need more retries if multiple cores */
+    #define INTELRD_RETRY (32 * 8)
+#else
+    #define INTELRD_RETRY 32
+#endif
+
+#ifdef HAVE_INTEL_RDSEED
+
+#ifndef USE_WINDOWS_API
+
+    /* return 0 on success */
+    static WC_INLINE int IntelRDseed64(word64* seed)
+    {
+        unsigned char ok;
+
+        __asm__ volatile("rdseed %0; setc %1":"=r"(*seed), "=qm"(ok));
+        return (ok) ? 0 : -1;
+    }
+
+#else /* USE_WINDOWS_API */
+    /* The compiler Visual Studio uses does not allow inline assembly.
+     * It does allow for Intel intrinsic functions. */
+
+    /* return 0 on success */
+    static WC_INLINE int IntelRDseed64(word64* seed)
+    {
+        int ok;
+
+        ok = _rdseed64_step(seed);
+        return (ok) ? 0 : -1;
+    }
+
+#endif /* USE_WINDOWS_API */
+
+/* return 0 on success */
+static WC_INLINE int IntelRDseed64_r(word64* rnd)
+{
+    int i;
+    for (i = 0; i < INTELRD_RETRY; i++) {
+        if (IntelRDseed64(rnd) == 0)
+            return 0;
+    }
+    return -1;
+}
+
+/* return 0 on success */
+static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz)
+{
+    int ret;
+    word64 rndTmp;
+
+    (void)os;
+
+    if (!IS_INTEL_RDSEED(intel_flags))
+        return -1;
+
+    for (; (sz / sizeof(word64)) > 0; sz -= sizeof(word64),
+                                                    output += sizeof(word64)) {
+        ret = IntelRDseed64_r((word64*)output);
+        if (ret != 0)
+            return ret;
+    }
+    if (sz == 0)
+        return 0;
+
+    /* handle unaligned remainder */
+    ret = IntelRDseed64_r(&rndTmp);
+    if (ret != 0)
+        return ret;
+
+    XMEMCPY(output, &rndTmp, sz);
+    ForceZero(&rndTmp, sizeof(rndTmp));
+
+    return 0;
+}
+
+#endif /* HAVE_INTEL_RDSEED */
+
+#ifdef HAVE_INTEL_RDRAND
+
+#ifndef USE_WINDOWS_API
+
+/* return 0 on success */
+static WC_INLINE int IntelRDrand64(word64 *rnd)
+{
+    unsigned char ok;
+
+    __asm__ volatile("rdrand %0; setc %1":"=r"(*rnd), "=qm"(ok));
+
+    return (ok) ? 0 : -1;
+}
+
+#else /* USE_WINDOWS_API */
+    /* The compiler Visual Studio uses does not allow inline assembly.
+     * It does allow for Intel intrinsic functions. */
+
+/* return 0 on success */
+static WC_INLINE int IntelRDrand64(word64 *rnd)
+{
+    int ok;
+
+    ok = _rdrand64_step(rnd);
+
+    return (ok) ? 0 : -1;
+}
+
+#endif /* USE_WINDOWS_API */
+
+/* return 0 on success */
+static WC_INLINE int IntelRDrand64_r(word64 *rnd)
+{
+    int i;
+    for (i = 0; i < INTELRD_RETRY; i++) {
+        if (IntelRDrand64(rnd) == 0)
+            return 0;
+    }
+    return -1;
+}
+
+/* return 0 on success */
+static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz)
+{
+    int ret;
+    word64 rndTmp;
+
+    (void)os;
+
+    if (!IS_INTEL_RDRAND(intel_flags))
+        return -1;
+
+    for (; (sz / sizeof(word64)) > 0; sz -= sizeof(word64),
+                                                    output += sizeof(word64)) {
+        ret = IntelRDrand64_r((word64 *)output);
+        if (ret != 0)
+            return ret;
+    }
+    if (sz == 0)
+        return 0;
+
+    /* handle unaligned remainder */
+    ret = IntelRDrand64_r(&rndTmp);
+    if (ret != 0)
+        return ret;
+
+    XMEMCPY(output, &rndTmp, sz);
+
+    return 0;
+}
+
+#endif /* HAVE_INTEL_RDRAND */
+#endif /* HAVE_INTEL_RDRAND || HAVE_INTEL_RDSEED */
+
+
+/* Begin wc_GenerateSeed Implementations */
+#if defined(CUSTOM_RAND_GENERATE_SEED)
+
+    /* Implement your own random generation function
+     * Return 0 to indicate success
+     * int rand_gen_seed(byte* output, word32 sz);
+     * #define CUSTOM_RAND_GENERATE_SEED  rand_gen_seed */
+
+    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+    {
+        (void)os; /* Suppress unused arg warning */
+        return CUSTOM_RAND_GENERATE_SEED(output, sz);
+    }
+
+#elif defined(CUSTOM_RAND_GENERATE_SEED_OS)
+
+    /* Implement your own random generation function,
+     *  which includes OS_Seed.
+     * Return 0 to indicate success
+     * int rand_gen_seed(OS_Seed* os, byte* output, word32 sz);
+     * #define CUSTOM_RAND_GENERATE_SEED_OS  rand_gen_seed */
+
+    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+    {
+        return CUSTOM_RAND_GENERATE_SEED_OS(os, output, sz);
+    }
+
+#elif defined(CUSTOM_RAND_GENERATE)
+
+   /* Implement your own random generation function
+    * word32 rand_gen(void);
+    * #define CUSTOM_RAND_GENERATE  rand_gen  */
+
+    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+    {
+        word32 i = 0;
+
+        (void)os;
+
+        while (i < sz)
+        {
+            /* If not aligned or there is odd/remainder */
+            if( (i + sizeof(CUSTOM_RAND_TYPE)) > sz ||
+                ((wolfssl_word)&output[i] % sizeof(CUSTOM_RAND_TYPE)) != 0
+            ) {
+                /* Single byte at a time */
+                output[i++] = (byte)CUSTOM_RAND_GENERATE();
+            }
+            else {
+                /* Use native 8, 16, 32 or 64 copy instruction */
+                *((CUSTOM_RAND_TYPE*)&output[i]) = CUSTOM_RAND_GENERATE();
+                i += sizeof(CUSTOM_RAND_TYPE);
+            }
+        }
+
+        return 0;
+    }
+
+#elif defined(WOLFSSL_SGX)
+
+int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+{
+    int ret = !SGX_SUCCESS;
+	int i, read_max = 10;
+
+	for (i = 0; i < read_max && ret != SGX_SUCCESS; i++) {
+		ret = sgx_read_rand(output, sz);
+	}
+
+	(void)os;
+	return (ret == SGX_SUCCESS) ? 0 : 1;
+}
+
+#elif defined(USE_WINDOWS_API)
+
+int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+{
+#ifdef WOLF_CRYPTO_CB
+    int ret;
+
+    if (os != NULL && os->devId != INVALID_DEVID) {
+        ret = wc_CryptoCb_RandomSeed(os, output, sz);
+        if (ret != CRYPTOCB_UNAVAILABLE)
+            return ret;
+        /* fall-through when unavailable */
+    }
+#endif
+
+    #ifdef HAVE_INTEL_RDSEED
+        if (IS_INTEL_RDSEED(intel_flags)) {
+             if (!wc_GenerateSeed_IntelRD(NULL, output, sz)) {
+                 /* success, we're done */
+                 return 0;
+             }
+        #ifdef FORCE_FAILURE_RDSEED
+             /* don't fall back to CryptoAPI */
+             return READ_RAN_E;
+        #endif
+        }
+    #endif /* HAVE_INTEL_RDSEED */
+
+    if(!CryptAcquireContext(&os->handle, 0, 0, PROV_RSA_FULL,
+                            CRYPT_VERIFYCONTEXT))
+        return WINCRYPT_E;
+
+    if (!CryptGenRandom(os->handle, sz, output))
+        return CRYPTGEN_E;
+
+    CryptReleaseContext(os->handle, 0);
+
+    return 0;
+}
+
+
+#elif defined(HAVE_RTP_SYS) || defined(EBSNET)
+
+#include "rtprand.h"   /* rtp_rand () */
+#include "rtptime.h"   /* rtp_get_system_msec() */
+
+int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+{
+    word32 i;
+
+    rtp_srand(rtp_get_system_msec());
+    for (i = 0; i < sz; i++ ) {
+        output[i] = rtp_rand() % 256;
+    }
+
+    return 0;
+}
+
+
+#elif defined(MICROCHIP_PIC32)
+
+    #ifdef MICROCHIP_MPLAB_HARMONY
+        #ifdef MICROCHIP_MPLAB_HARMONY_3
+            #include "system/time/sys_time.h"
+            #define PIC32_SEED_COUNT SYS_TIME_CounterGet
+        #else
+            #define PIC32_SEED_COUNT _CP0_GET_COUNT
+        #endif
+    #else
+        #if !defined(WOLFSSL_MICROCHIP_PIC32MZ)
+            #include <peripheral/timer.h>
+        #endif
+        extern word32 ReadCoreTimer(void);
+        #define PIC32_SEED_COUNT ReadCoreTimer
+    #endif
+
+    #ifdef WOLFSSL_PIC32MZ_RNG
+        #include "xc.h"
+        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+        {
+            int i;
+            byte rnd[8];
+            word32 *rnd32 = (word32 *)rnd;
+            word32 size = sz;
+            byte* op = output;
+
+#if ((__PIC32_FEATURE_SET0 == 'E') && (__PIC32_FEATURE_SET1 == 'C'))
+            RNGNUMGEN1 = _CP0_GET_COUNT();
+            RNGPOLY1 = _CP0_GET_COUNT();
+            RNGPOLY2 = _CP0_GET_COUNT();
+            RNGNUMGEN2 = _CP0_GET_COUNT();
+#else
+            // All others can be seeded from the TRNG
+            RNGCONbits.TRNGMODE = 1;
+            RNGCONbits.TRNGEN = 1;
+            while (RNGCNT < 64);
+            RNGCONbits.LOAD = 1;
+            while (RNGCONbits.LOAD == 1);
+            while (RNGCNT < 64);
+            RNGPOLY2 = RNGSEED2;
+            RNGPOLY1 = RNGSEED1;
+#endif
+
+            RNGCONbits.PLEN = 0x40;
+            RNGCONbits.PRNGEN = 1;
+            for (i=0; i<5; i++) { /* wait for RNGNUMGEN ready */
+                volatile int x, y;
+                x = RNGNUMGEN1;
+                y = RNGNUMGEN2;
+                (void)x;
+                (void)y;
+            }
+            do {
+                rnd32[0] = RNGNUMGEN1;
+                rnd32[1] = RNGNUMGEN2;
+
+                for(i=0; i<8; i++, op++) {
+                    *op = rnd[i];
+                    size --;
+                    if(size==0)break;
+                }
+            } while(size);
+            return 0;
+        }
+    #else  /* WOLFSSL_PIC32MZ_RNG */
+        /* uses the core timer, in nanoseconds to seed srand */
+        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+        {
+            int i;
+            srand(PIC32_SEED_COUNT() * 25);
+
+            for (i = 0; i < sz; i++ ) {
+                output[i] = rand() % 256;
+                if ( (i % 8) == 7)
+                    srand(PIC32_SEED_COUNT() * 25);
+            }
+            return 0;
+        }
+    #endif /* WOLFSSL_PIC32MZ_RNG */
+
+#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) || \
+      defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS)
+
+    #if defined(FREESCALE_K70_RNGA) || defined(FREESCALE_RNGA)
+        /*
+         * wc_Generates a RNG seed using the Random Number Generator Accelerator
+         * on the Kinetis K70. Documentation located in Chapter 37 of
+         * K70 Sub-Family Reference Manual (see Note 3 in the README for link).
+         */
+        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+        {
+            word32 i;
+
+            /* turn on RNGA module */
+            #if defined(SIM_SCGC3_RNGA_MASK)
+                SIM_SCGC3 |= SIM_SCGC3_RNGA_MASK;
+            #endif
+            #if defined(SIM_SCGC6_RNGA_MASK)
+                /* additionally needed for at least K64F */
+                SIM_SCGC6 |= SIM_SCGC6_RNGA_MASK;
+            #endif
+
+            /* set SLP bit to 0 - "RNGA is not in sleep mode" */
+            RNG_CR &= ~RNG_CR_SLP_MASK;
+
+            /* set HA bit to 1 - "security violations masked" */
+            RNG_CR |= RNG_CR_HA_MASK;
+
+            /* set GO bit to 1 - "output register loaded with data" */
+            RNG_CR |= RNG_CR_GO_MASK;
+
+            for (i = 0; i < sz; i++) {
+
+                /* wait for RNG FIFO to be full */
+                while((RNG_SR & RNG_SR_OREG_LVL(0xF)) == 0) {}
+
+                /* get value */
+                output[i] = RNG_OR;
+            }
+
+            return 0;
+        }
+
+    #elif defined(FREESCALE_K53_RNGB) || defined(FREESCALE_RNGB)
+        /*
+         * wc_Generates a RNG seed using the Random Number Generator (RNGB)
+         * on the Kinetis K53. Documentation located in Chapter 33 of
+         * K53 Sub-Family Reference Manual (see note in the README for link).
+         */
+        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+        {
+            int i;
+
+            /* turn on RNGB module */
+            SIM_SCGC3 |= SIM_SCGC3_RNGB_MASK;
+
+            /* reset RNGB */
+            RNG_CMD |= RNG_CMD_SR_MASK;
+
+            /* FIFO generate interrupt, return all zeros on underflow,
+             * set auto reseed */
+            RNG_CR |= (RNG_CR_FUFMOD_MASK | RNG_CR_AR_MASK);
+
+            /* gen seed, clear interrupts, clear errors */
+            RNG_CMD |= (RNG_CMD_GS_MASK | RNG_CMD_CI_MASK | RNG_CMD_CE_MASK);
+
+            /* wait for seeding to complete */
+            while ((RNG_SR & RNG_SR_SDN_MASK) == 0) {}
+
+            for (i = 0; i < sz; i++) {
+
+                /* wait for a word to be available from FIFO */
+                while((RNG_SR & RNG_SR_FIFO_LVL_MASK) == 0) {}
+
+                /* get value */
+                output[i] = RNG_OUT;
+            }
+
+            return 0;
+        }
+
+    #elif defined(FREESCALE_KSDK_2_0_TRNG)
+
+        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+        {
+            status_t status;
+            status = TRNG_GetRandomData(TRNG0, output, sz);
+            if (status == kStatus_Success)
+            {
+                return(0);
+            }
+            else
+            {
+                return RAN_BLOCK_E;
+            }
+        }
+
+    #elif defined(FREESCALE_KSDK_2_0_RNGA)
+
+        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+        {
+            status_t status;
+            status = RNGA_GetRandomData(RNG, output, sz);
+            if (status == kStatus_Success)
+            {
+                return(0);
+            }
+            else
+            {
+                return RAN_BLOCK_E;
+            }
+        }
+
+
+    #elif defined(FREESCALE_RNGA)
+
+        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+        {
+            RNGA_DRV_GetRandomData(RNGA_INSTANCE, output, sz);
+            return 0;
+        }
+
+    #else
+        #define USE_TEST_GENSEED
+    #endif /* FREESCALE_K70_RNGA */
+
+#elif defined(STM32_RNG)
+     /* Generate a RNG seed using the hardware random number generator
+      * on the STM32F2/F4/F7/L4. */
+
+    #ifdef WOLFSSL_STM32_CUBEMX
+    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+    {
+        int ret;
+        RNG_HandleTypeDef hrng;
+        word32 i = 0;
+        (void)os;
+
+        ret = wolfSSL_CryptHwMutexLock();
+        if (ret != 0) {
+            return ret;
+        }
+
+        /* enable RNG clock source */
+        __HAL_RCC_RNG_CLK_ENABLE();
+
+        /* enable RNG peripheral */
+        XMEMSET(&hrng, 0, sizeof(hrng));
+        hrng.Instance = RNG;
+        HAL_RNG_Init(&hrng);
+
+        while (i < sz) {
+            /* If not aligned or there is odd/remainder */
+            if( (i + sizeof(word32)) > sz ||
+                ((wolfssl_word)&output[i] % sizeof(word32)) != 0
+            ) {
+                /* Single byte at a time */
+                uint32_t tmpRng = 0;
+                if (HAL_RNG_GenerateRandomNumber(&hrng, &tmpRng) != HAL_OK) {
+                    wolfSSL_CryptHwMutexUnLock();
+                    return RAN_BLOCK_E;
+                }
+                output[i++] = (byte)tmpRng;
+            }
+            else {
+                /* Use native 32 instruction */
+                if (HAL_RNG_GenerateRandomNumber(&hrng, (uint32_t*)&output[i]) != HAL_OK) {
+                    wolfSSL_CryptHwMutexUnLock();
+                    return RAN_BLOCK_E;
+                }
+                i += sizeof(word32);
+            }
+        }
+
+        wolfSSL_CryptHwMutexUnLock();
+
+        return 0;
+    }
+    #elif defined(WOLFSSL_STM32F427_RNG) || defined(WOLFSSL_STM32_RNG_NOLIB)
+
+    /* Generate a RNG seed using the hardware RNG on the STM32F427
+     * directly, following steps outlined in STM32F4 Reference
+     * Manual (Chapter 24) for STM32F4xx family. */
+    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+    {
+        int ret;
+        word32 i;
+        (void)os;
+
+        ret = wolfSSL_CryptHwMutexLock();
+        if (ret != 0) {
+            return ret;
+        }
+
+        /* enable RNG peripheral clock */
+        RCC->AHB2ENR |= RCC_AHB2ENR_RNGEN;
+
+        /* enable RNG interrupt, set IE bit in RNG->CR register */
+        RNG->CR |= RNG_CR_IE;
+
+        /* enable RNG, set RNGEN bit in RNG->CR. Activates RNG,
+         * RNG_LFSR, and error detector */
+        RNG->CR |= RNG_CR_RNGEN;
+
+        /* verify no errors, make sure SEIS and CEIS bits are 0
+         * in RNG->SR register */
+        if (RNG->SR & (RNG_SR_SECS | RNG_SR_CECS)) {
+            wolfSSL_CryptHwMutexUnLock();
+            return RNG_FAILURE_E;
+        }
+
+        for (i = 0; i < sz; i++) {
+            /* wait until RNG number is ready */
+            while ((RNG->SR & RNG_SR_DRDY) == 0) { }
+
+            /* get value */
+            output[i] = RNG->DR;
+        }
+
+        wolfSSL_CryptHwMutexUnLock();
+
+        return 0;
+    }
+
+    #else
+
+    /* Generate a RNG seed using the STM32 Standard Peripheral Library */
+    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+    {
+        int ret;
+        word32 i;
+        (void)os;
+
+        ret = wolfSSL_CryptHwMutexLock();
+        if (ret != 0) {
+            return ret;
+        }
+
+        /* enable RNG clock source */
+        RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE);
+
+        /* reset RNG */
+        RNG_DeInit();
+
+        /* enable RNG peripheral */
+        RNG_Cmd(ENABLE);
+
+        /* verify no errors with RNG_CLK or Seed */
+        if (RNG_GetFlagStatus(RNG_FLAG_SECS | RNG_FLAG_CECS) != RESET) {
+            wolfSSL_CryptHwMutexUnLock();
+            return RNG_FAILURE_E;
+        }
+
+        for (i = 0; i < sz; i++) {
+            /* wait until RNG number is ready */
+            while (RNG_GetFlagStatus(RNG_FLAG_DRDY) == RESET) { }
+
+            /* get value */
+            output[i] = RNG_GetRandomNumber();
+        }
+
+        wolfSSL_CryptHwMutexUnLock();
+
+        return 0;
+    }
+    #endif /* WOLFSSL_STM32_CUBEMX */
+
+#elif defined(WOLFSSL_TIRTOS)
+
+    #include <xdc/runtime/Timestamp.h>
+    #include <stdlib.h>
+    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+    {
+        int i;
+        srand(xdc_runtime_Timestamp_get32());
+
+        for (i = 0; i < sz; i++ ) {
+            output[i] = rand() % 256;
+            if ((i % 8) == 7) {
+                srand(xdc_runtime_Timestamp_get32());
+            }
+        }
+
+        return 0;
+    }
+
+#elif defined(WOLFSSL_PB)
+
+    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+    {
+        word32 i;
+        for (i = 0; i < sz; i++)
+            output[i] = UTL_Rand();
+
+        (void)os;
+
+        return 0;
+    }
+
+#elif defined(WOLFSSL_NUCLEUS)
+#include "nucleus.h"
+#include "kernel/plus_common.h"
+
+#warning "potential for not enough entropy, currently being used for testing"
+int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+{
+    int i;
+    srand(NU_Get_Time_Stamp());
+
+    for (i = 0; i < sz; i++ ) {
+        output[i] = rand() % 256;
+        if ((i % 8) == 7) {
+            srand(NU_Get_Time_Stamp());
+        }
+    }
+
+    return 0;
+}
+#elif defined(WOLFSSL_DEOS) && !defined(CUSTOM_RAND_GENERATE)
+    #include "stdlib.h"
+
+    #warning "potential for not enough entropy, currently being used for testing Deos"
+    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+    {
+        int i;
+        int seed = XTIME(0);
+        (void)os;
+
+        for (i = 0; i < sz; i++ ) {
+            output[i] = rand_r(&seed) % 256;
+            if ((i % 8) == 7) {
+                seed = XTIME(0);
+                rand_r(&seed);
+            }
+        }
+
+        return 0;
+    }
+#elif defined(WOLFSSL_VXWORKS)
+
+    #include <randomNumGen.h>
+
+    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) {
+        STATUS        status;
+
+        #ifdef VXWORKS_SIM
+            /* cannot generate true entropy with VxWorks simulator */
+            #warning "not enough entropy, simulator for testing only"
+            int i = 0;
+
+            for (i = 0; i < 1000; i++) {
+                randomAddTimeStamp();
+            }
+        #endif
+
+        status = randBytes (output, sz);
+        if (status == ERROR) {
+            return RNG_FAILURE_E;
+        }
+
+        return 0;
+    }
+
+#elif defined(WOLFSSL_NRF51)
+    #include "app_error.h"
+    #include "nrf_drv_rng.h"
+    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+    {
+        int remaining = sz, length, pos = 0;
+        uint8_t available;
+        uint32_t err_code;
+
+        (void)os;
+
+        /* Make sure RNG is running */
+        err_code = nrf_drv_rng_init(NULL);
+        if (err_code != NRF_SUCCESS && err_code != NRF_ERROR_INVALID_STATE) {
+            return -1;
+        }
+
+        while (remaining > 0) {
+            err_code = nrf_drv_rng_bytes_available(&available);
+            if (err_code == NRF_SUCCESS) {
+                length = (remaining < available) ? remaining : available;
+                if (length > 0) {
+                    err_code = nrf_drv_rng_rand(&output[pos], length);
+                    remaining -= length;
+                    pos += length;
+                }
+            }
+
+            if (err_code != NRF_SUCCESS) {
+                break;
+            }
+        }
+
+        return (err_code == NRF_SUCCESS) ? 0 : -1;
+    }
+
+#elif defined(HAVE_WNR)
+
+    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+    {
+        if (os == NULL || output == NULL || wnr_ctx == NULL ||
+                wnr_timeout < 0) {
+            return BAD_FUNC_ARG;
+        }
+
+        if (wnr_mutex_init == 0) {
+            WOLFSSL_MSG("netRandom context must be created before use");
+            return RNG_FAILURE_E;
+        }
+
+        if (wc_LockMutex(&wnr_mutex) != 0) {
+            WOLFSSL_MSG("Bad Lock Mutex wnr_mutex\n");
+            return BAD_MUTEX_E;
+        }
+
+        if (wnr_get_entropy(wnr_ctx, wnr_timeout, output, sz, sz) !=
+                WNR_ERROR_NONE)
+            return RNG_FAILURE_E;
+
+        wc_UnLockMutex(&wnr_mutex);
+
+        return 0;
+    }
+
+#elif defined(WOLFSSL_ATMEL)
+    #include <wolfssl/wolfcrypt/port/atmel/atmel.h>
+
+    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+    {
+        int ret = 0;
+
+        (void)os;
+        if (output == NULL) {
+            return BUFFER_E;
+        }
+
+        ret = atmel_get_random_number(sz, output);
+
+        return ret;
+    }
+
+#elif defined(INTIME_RTOS)
+    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+    {
+        int ret = 0;
+
+        (void)os;
+
+        if (output == NULL) {
+            return BUFFER_E;
+        }
+
+        /* Note: Investigate better solution */
+        /* no return to check */
+        arc4random_buf(output, sz);
+
+        return ret;
+    }
+
+#elif defined(WOLFSSL_WICED)
+    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+    {
+        int ret;
+        (void)os;
+
+        if (output == NULL || UINT16_MAX < sz) {
+            return BUFFER_E;
+        }
+
+        if ((ret = wiced_crypto_get_random((void*) output, sz) )
+                         != WICED_SUCCESS) {
+            return ret;
+        }
+
+        return ret;
+    }
+
+#elif defined(WOLFSSL_NETBURNER)
+    #warning using NetBurner pseudo random GetRandomByte for seed
+    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+    {
+        word32 i;
+        (void)os;
+
+        if (output == NULL) {
+            return BUFFER_E;
+        }
+
+        for (i = 0; i < sz; i++) {
+            output[i] = GetRandomByte();
+
+            /* check if was a valid random number */
+            if (!RandomValid())
+                return RNG_FAILURE_E;
+        }
+
+        return 0;
+    }
+#elif defined(IDIRECT_DEV_RANDOM)
+
+    extern int getRandom( int sz, unsigned char *output );
+
+    int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+    {
+        int num_bytes_returned = 0;
+
+        num_bytes_returned = getRandom( (int) sz, (unsigned char *) output );
+
+        return 0;
+    }
+
+#elif (defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG))
+
+    #include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
+    #include <wolfssl/wolfcrypt/port/caam/caam_driver.h>
+
+    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+    {
+        Buffer buf[1];
+        int ret  = 0;
+        int times = 1000, i;
+
+        (void)os;
+
+        if (output == NULL) {
+            return BUFFER_E;
+        }
+
+        buf[0].BufferType = DataBuffer | LastBuffer;
+        buf[0].TheAddress = (Address)output;
+        buf[0].Length     = sz;
+
+        /* Check Waiting to make sure entropy is ready */
+        for (i = 0; i < times; i++) {
+            ret = wc_caamAddAndWait(buf, NULL, CAAM_ENTROPY);
+            if (ret == Success) {
+                break;
+            }
+
+            /* driver could be waiting for entropy */
+            if (ret != RAN_BLOCK_E) {
+                return ret;
+            }
+            usleep(100);
+        }
+
+        if (i == times && ret != Success) {
+             return RNG_FAILURE_E;
+        }
+        else { /* Success case */
+            ret = 0;
+        }
+
+        return ret;
+    }
+
+#elif defined(WOLFSSL_APACHE_MYNEWT)
+
+    #include <stdlib.h>
+    #include "os/os_time.h"
+    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+    {
+        int i;
+        srand(os_time_get());
+
+        for (i = 0; i < sz; i++ ) {
+            output[i] = rand() % 256;
+            if ((i % 8) == 7) {
+                srand(os_time_get());
+            }
+        }
+
+        return 0;
+    }
+
+#elif defined(WOLFSSL_ESPIDF)
+    #if defined(WOLFSSL_ESPWROOM32) || defined(WOLFSSL_ESPWROOM32SE)
+        #include <esp_system.h>
+
+        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+        {
+            word32 rand;
+            while (sz > 0) {
+                word32 len = sizeof(rand);
+                if (sz < len)
+                    len = sz;
+                /* Get one random 32-bit word from hw RNG */
+                rand = esp_random( );
+                XMEMCPY(output, &rand, len);
+                output += len;
+                sz -= len;
+            }
+
+            return 0;
+        }
+    #endif /* end WOLFSSL_ESPWROOM32 */
+
+#elif defined(WOLFSSL_RENESAS_TSIP)
+#if defined(WOLFSSL_RENESA_TSIP_IAREWRX)
+    #include "r_bsp/mcu/all/r_rx_compiler.h"
+#endif
+    #include "r_bsp/platform.h"
+    #include "r_tsip_rx_if.h"
+    
+    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+    {
+        int ret;
+        uint32_t buffer[4];
+
+        while (sz > 0) {
+            uint32_t len = sizeof(buffer);
+            
+            if (sz < len) {
+                len = sz;
+            }
+            /* return 4 words random number*/
+            ret = R_TSIP_GenerateRandomNumber(buffer);
+            if(ret == TSIP_SUCCESS) {
+                XMEMCPY(output, &buffer, len);
+                output += len;
+                sz -= len;
+            } else
+                return ret;
+        }
+        return ret;
+    }
+
+#elif defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_TRNG)
+    #include "hal_data.h"
+
+    #ifndef WOLFSSL_SCE_TRNG_HANDLE
+        #define WOLFSSL_SCE_TRNG_HANDLE g_sce_trng
+    #endif
+
+    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+    {
+        uint32_t ret;
+        uint32_t blocks;
+        word32   len = sz;
+
+        ret = WOLFSSL_SCE_TRNG_HANDLE.p_api->open(WOLFSSL_SCE_TRNG_HANDLE.p_ctrl,
+                                                  WOLFSSL_SCE_TRNG_HANDLE.p_cfg);
+        if (ret != SSP_SUCCESS && ret != SSP_ERR_CRYPTO_ALREADY_OPEN) {
+            /* error opening TRNG driver */
+            return -1;
+        }
+
+        blocks = sz / sizeof(uint32_t);
+        if (blocks > 0) {
+            ret = WOLFSSL_SCE_TRNG_HANDLE.p_api->read(WOLFSSL_SCE_TRNG_HANDLE.p_ctrl,
+                                                      (uint32_t*)output, blocks);
+            if (ret != SSP_SUCCESS) {
+                return -1;
+            }
+        }
+
+        len = len - (blocks * sizeof(uint32_t));
+        if (len > 0) {
+            uint32_t tmp;
+
+            if (len > sizeof(uint32_t)) {
+                return -1;
+            }
+            ret = WOLFSSL_SCE_TRNG_HANDLE.p_api->read(WOLFSSL_SCE_TRNG_HANDLE.p_ctrl,
+                                                      (uint32_t*)tmp, 1);
+            if (ret != SSP_SUCCESS) {
+                return -1;
+            }
+            XMEMCPY(output + (blocks * sizeof(uint32_t)), (byte*)&tmp, len);
+        }
+
+        ret = WOLFSSL_SCE_TRNG_HANDLE.p_api->close(WOLFSSL_SCE_TRNG_HANDLE.p_ctrl);
+        if (ret != SSP_SUCCESS) {
+            /* error opening TRNG driver */
+            return -1;
+        }
+        return 0;
+    }
+#elif defined(CUSTOM_RAND_GENERATE_BLOCK)
+    /* #define CUSTOM_RAND_GENERATE_BLOCK myRngFunc
+     * extern int myRngFunc(byte* output, word32 sz);
+     */
+
+#elif defined(WOLFSSL_SAFERTOS) || defined(WOLFSSL_LEANPSK) || \
+      defined(WOLFSSL_IAR_ARM)  || defined(WOLFSSL_MDK_ARM) || \
+      defined(WOLFSSL_uITRON4)  || defined(WOLFSSL_uTKERNEL2) || \
+      defined(WOLFSSL_LPC43xx)  || defined(WOLFSSL_STM32F2xx) || \
+      defined(MBED)             || defined(WOLFSSL_EMBOS) || \
+      defined(WOLFSSL_GENSEED_FORTEST) || defined(WOLFSSL_CHIBIOS) || \
+      defined(WOLFSSL_CONTIKI)  || defined(WOLFSSL_AZSPHERE)
+
+    /* these platforms do not have a default random seed and
+       you'll need to implement your own wc_GenerateSeed or define via
+       CUSTOM_RAND_GENERATE_BLOCK */
+
+    #define USE_TEST_GENSEED
+
+#elif defined(WOLFSSL_ZEPHYR)
+
+        #include <entropy.h>
+    #ifndef _POSIX_C_SOURCE
+        #include <posix/time.h>
+    #else
+        #include <sys/time.h>
+    #endif
+
+        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+        {
+            int ret = 0;
+            word32 rand;
+            while (sz > 0) {
+                word32 len = sizeof(rand);
+                if (sz < len)
+                    len = sz;
+                rand = sys_rand32_get();
+                XMEMCPY(output, &rand, len);
+                output += len;
+                sz -= len;
+            }
+
+            return ret;
+        }
+
+#elif defined(WOLFSSL_TELIT_M2MB)
+
+        #include "stdlib.h"
+        static long get_timestamp(void) {
+            long myTime = 0;
+            INT32 fd = m2mb_rtc_open("/dev/rtc0", 0);
+            if (fd >= 0) {
+                M2MB_RTC_TIMEVAL_T timeval;
+                m2mb_rtc_ioctl(fd, M2MB_RTC_IOCTL_GET_TIMEVAL, &timeval);
+                myTime = timeval.msec;
+                m2mb_rtc_close(fd);
+            }
+            return myTime;
+        }
+        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+        {
+            int i;
+            srand(get_timestamp());
+            for (i = 0; i < sz; i++ ) {
+                output[i] = rand() % 256;
+                if ((i % 8) == 7) {
+                    srand(get_timestamp());
+                }
+            }
+            return 0;
+        }
+
+#elif defined(NO_DEV_RANDOM)
+
+    #error "you need to write an os specific wc_GenerateSeed() here"
+
+    /*
+    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+    {
+        return 0;
+    }
+    */
+
+#else
+
+    /* may block */
+    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+    {
+        int ret = 0;
+
+        if (os == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+    #ifdef WOLF_CRYPTO_CB
+        if (os->devId != INVALID_DEVID) {
+            ret = wc_CryptoCb_RandomSeed(os, output, sz);
+            if (ret != CRYPTOCB_UNAVAILABLE)
+                return ret;
+            /* fall-through when unavailable */
+            ret = 0; /* reset error code */
+        }
+    #endif
+
+    #ifdef HAVE_INTEL_RDSEED
+        if (IS_INTEL_RDSEED(intel_flags)) {
+             ret = wc_GenerateSeed_IntelRD(NULL, output, sz);
+             if (ret == 0) {
+                 /* success, we're done */
+                 return ret;
+             }
+        #ifdef FORCE_FAILURE_RDSEED
+             /* don't fallback to /dev/urandom */
+             return ret;
+        #else
+             /* reset error and fallback to using /dev/urandom */
+             ret = 0;
+        #endif
+        }
+    #endif /* HAVE_INTEL_RDSEED */
+
+    #ifndef NO_DEV_URANDOM /* way to disable use of /dev/urandom */
+        os->fd = open("/dev/urandom", O_RDONLY);
+        if (os->fd == -1)
+    #endif
+        {
+            /* may still have /dev/random */
+            os->fd = open("/dev/random", O_RDONLY);
+            if (os->fd == -1)
+                return OPEN_RAN_E;
+        }
+
+        while (sz) {
+            int len = (int)read(os->fd, output, sz);
+            if (len == -1) {
+                ret = READ_RAN_E;
+                break;
+            }
+
+            sz     -= len;
+            output += len;
+
+            if (sz) {
+    #if defined(BLOCKING) || defined(WC_RNG_BLOCKING)
+                sleep(0);             /* context switch */
+    #else
+                ret = RAN_BLOCK_E;
+                break;
+    #endif
+            }
+        }
+        close(os->fd);
+
+        return ret;
+    }
+
+#endif
+
+#ifdef USE_TEST_GENSEED
+    #ifndef _MSC_VER
+        #warning "write a real random seed!!!!, just for testing now"
+    #else
+        #pragma message("Warning: write a real random seed!!!!, just for testing now")
+    #endif
+    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+    {
+        word32 i;
+        for (i = 0; i < sz; i++ )
+            output[i] = i;
+
+        (void)os;
+
+        return 0;
+    }
+#endif
+
+
+/* End wc_GenerateSeed */
+#endif /* WC_NO_RNG */
+#endif /* HAVE_FIPS */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/ripemd.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/ripemd.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/ripemd.c	(revision 453)
@@ -0,0 +1,366 @@
+/* ripemd.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifdef WOLFSSL_RIPEMD
+
+#include <wolfssl/wolfcrypt/ripemd.h>
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+#include <wolfssl/wolfcrypt/error-crypt.h>
+
+int wc_InitRipeMd(RipeMd* ripemd)
+{
+    if (ripemd == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    ripemd->digest[0] = 0x67452301L;
+    ripemd->digest[1] = 0xEFCDAB89L;
+    ripemd->digest[2] = 0x98BADCFEL;
+    ripemd->digest[3] = 0x10325476L;
+    ripemd->digest[4] = 0xC3D2E1F0L;
+
+    ripemd->buffLen = 0;
+    ripemd->loLen   = 0;
+    ripemd->hiLen   = 0;
+
+    return 0;
+}
+
+
+/* for all */
+#define F(x, y, z)    (x ^ y ^ z)
+#define G(x, y, z)    (z ^ (x & (y^z)))
+#define H(x, y, z)    (z ^ (x | ~y))
+#define I(x, y, z)    (y ^ (z & (x^y)))
+#define J(x, y, z)    (x ^ (y | ~z))
+
+#define k0 0
+#define k1 0x5a827999
+#define k2 0x6ed9eba1
+#define k3 0x8f1bbcdc
+#define k4 0xa953fd4e
+#define k5 0x50a28be6
+#define k6 0x5c4dd124
+#define k7 0x6d703ef3
+#define k8 0x7a6d76e9
+#define k9 0
+
+/* for 160 and 320 */
+#define Subround(f, a, b, c, d, e, x, s, k) \
+    a += f(b, c, d) + x + k;\
+    a = rotlFixed((word32)a, s) + e;\
+    c = rotlFixed((word32)c, 10U)
+
+static void Transform(RipeMd* ripemd)
+{
+    word32 a1, b1, c1, d1, e1, a2, b2, c2, d2, e2;
+    a1 = a2 = ripemd->digest[0];
+    b1 = b2 = ripemd->digest[1];
+    c1 = c2 = ripemd->digest[2];
+    d1 = d2 = ripemd->digest[3];
+    e1 = e2 = ripemd->digest[4];
+
+    Subround(F, a1, b1, c1, d1, e1, ripemd->buffer[ 0], 11, k0);
+    Subround(F, e1, a1, b1, c1, d1, ripemd->buffer[ 1], 14, k0);
+    Subround(F, d1, e1, a1, b1, c1, ripemd->buffer[ 2], 15, k0);
+    Subround(F, c1, d1, e1, a1, b1, ripemd->buffer[ 3], 12, k0);
+    Subround(F, b1, c1, d1, e1, a1, ripemd->buffer[ 4],  5, k0);
+    Subround(F, a1, b1, c1, d1, e1, ripemd->buffer[ 5],  8, k0);
+    Subround(F, e1, a1, b1, c1, d1, ripemd->buffer[ 6],  7, k0);
+    Subround(F, d1, e1, a1, b1, c1, ripemd->buffer[ 7],  9, k0);
+    Subround(F, c1, d1, e1, a1, b1, ripemd->buffer[ 8], 11, k0);
+    Subround(F, b1, c1, d1, e1, a1, ripemd->buffer[ 9], 13, k0);
+    Subround(F, a1, b1, c1, d1, e1, ripemd->buffer[10], 14, k0);
+    Subround(F, e1, a1, b1, c1, d1, ripemd->buffer[11], 15, k0);
+    Subround(F, d1, e1, a1, b1, c1, ripemd->buffer[12],  6, k0);
+    Subround(F, c1, d1, e1, a1, b1, ripemd->buffer[13],  7, k0);
+    Subround(F, b1, c1, d1, e1, a1, ripemd->buffer[14],  9, k0);
+    Subround(F, a1, b1, c1, d1, e1, ripemd->buffer[15],  8, k0);
+
+    Subround(G, e1, a1, b1, c1, d1, ripemd->buffer[ 7],  7, k1);
+    Subround(G, d1, e1, a1, b1, c1, ripemd->buffer[ 4],  6, k1);
+    Subround(G, c1, d1, e1, a1, b1, ripemd->buffer[13],  8, k1);
+    Subround(G, b1, c1, d1, e1, a1, ripemd->buffer[ 1], 13, k1);
+    Subround(G, a1, b1, c1, d1, e1, ripemd->buffer[10], 11, k1);
+    Subround(G, e1, a1, b1, c1, d1, ripemd->buffer[ 6],  9, k1);
+    Subround(G, d1, e1, a1, b1, c1, ripemd->buffer[15],  7, k1);
+    Subround(G, c1, d1, e1, a1, b1, ripemd->buffer[ 3], 15, k1);
+    Subround(G, b1, c1, d1, e1, a1, ripemd->buffer[12],  7, k1);
+    Subround(G, a1, b1, c1, d1, e1, ripemd->buffer[ 0], 12, k1);
+    Subround(G, e1, a1, b1, c1, d1, ripemd->buffer[ 9], 15, k1);
+    Subround(G, d1, e1, a1, b1, c1, ripemd->buffer[ 5],  9, k1);
+    Subround(G, c1, d1, e1, a1, b1, ripemd->buffer[ 2], 11, k1);
+    Subround(G, b1, c1, d1, e1, a1, ripemd->buffer[14],  7, k1);
+    Subround(G, a1, b1, c1, d1, e1, ripemd->buffer[11], 13, k1);
+    Subround(G, e1, a1, b1, c1, d1, ripemd->buffer[ 8], 12, k1);
+
+    Subround(H, d1, e1, a1, b1, c1, ripemd->buffer[ 3], 11, k2);
+    Subround(H, c1, d1, e1, a1, b1, ripemd->buffer[10], 13, k2);
+    Subround(H, b1, c1, d1, e1, a1, ripemd->buffer[14],  6, k2);
+    Subround(H, a1, b1, c1, d1, e1, ripemd->buffer[ 4],  7, k2);
+    Subround(H, e1, a1, b1, c1, d1, ripemd->buffer[ 9], 14, k2);
+    Subround(H, d1, e1, a1, b1, c1, ripemd->buffer[15],  9, k2);
+    Subround(H, c1, d1, e1, a1, b1, ripemd->buffer[ 8], 13, k2);
+    Subround(H, b1, c1, d1, e1, a1, ripemd->buffer[ 1], 15, k2);
+    Subround(H, a1, b1, c1, d1, e1, ripemd->buffer[ 2], 14, k2);
+    Subround(H, e1, a1, b1, c1, d1, ripemd->buffer[ 7],  8, k2);
+    Subround(H, d1, e1, a1, b1, c1, ripemd->buffer[ 0], 13, k2);
+    Subround(H, c1, d1, e1, a1, b1, ripemd->buffer[ 6],  6, k2);
+    Subround(H, b1, c1, d1, e1, a1, ripemd->buffer[13],  5, k2);
+    Subround(H, a1, b1, c1, d1, e1, ripemd->buffer[11], 12, k2);
+    Subround(H, e1, a1, b1, c1, d1, ripemd->buffer[ 5],  7, k2);
+    Subround(H, d1, e1, a1, b1, c1, ripemd->buffer[12],  5, k2);
+
+    Subround(I, c1, d1, e1, a1, b1, ripemd->buffer[ 1], 11, k3);
+    Subround(I, b1, c1, d1, e1, a1, ripemd->buffer[ 9], 12, k3);
+    Subround(I, a1, b1, c1, d1, e1, ripemd->buffer[11], 14, k3);
+    Subround(I, e1, a1, b1, c1, d1, ripemd->buffer[10], 15, k3);
+    Subround(I, d1, e1, a1, b1, c1, ripemd->buffer[ 0], 14, k3);
+    Subround(I, c1, d1, e1, a1, b1, ripemd->buffer[ 8], 15, k3);
+    Subround(I, b1, c1, d1, e1, a1, ripemd->buffer[12],  9, k3);
+    Subround(I, a1, b1, c1, d1, e1, ripemd->buffer[ 4],  8, k3);
+    Subround(I, e1, a1, b1, c1, d1, ripemd->buffer[13],  9, k3);
+    Subround(I, d1, e1, a1, b1, c1, ripemd->buffer[ 3], 14, k3);
+    Subround(I, c1, d1, e1, a1, b1, ripemd->buffer[ 7],  5, k3);
+    Subround(I, b1, c1, d1, e1, a1, ripemd->buffer[15],  6, k3);
+    Subround(I, a1, b1, c1, d1, e1, ripemd->buffer[14],  8, k3);
+    Subround(I, e1, a1, b1, c1, d1, ripemd->buffer[ 5],  6, k3);
+    Subround(I, d1, e1, a1, b1, c1, ripemd->buffer[ 6],  5, k3);
+    Subround(I, c1, d1, e1, a1, b1, ripemd->buffer[ 2], 12, k3);
+
+    Subround(J, b1, c1, d1, e1, a1, ripemd->buffer[ 4],  9, k4);
+    Subround(J, a1, b1, c1, d1, e1, ripemd->buffer[ 0], 15, k4);
+    Subround(J, e1, a1, b1, c1, d1, ripemd->buffer[ 5],  5, k4);
+    Subround(J, d1, e1, a1, b1, c1, ripemd->buffer[ 9], 11, k4);
+    Subround(J, c1, d1, e1, a1, b1, ripemd->buffer[ 7],  6, k4);
+    Subround(J, b1, c1, d1, e1, a1, ripemd->buffer[12],  8, k4);
+    Subround(J, a1, b1, c1, d1, e1, ripemd->buffer[ 2], 13, k4);
+    Subround(J, e1, a1, b1, c1, d1, ripemd->buffer[10], 12, k4);
+    Subround(J, d1, e1, a1, b1, c1, ripemd->buffer[14],  5, k4);
+    Subround(J, c1, d1, e1, a1, b1, ripemd->buffer[ 1], 12, k4);
+    Subround(J, b1, c1, d1, e1, a1, ripemd->buffer[ 3], 13, k4);
+    Subround(J, a1, b1, c1, d1, e1, ripemd->buffer[ 8], 14, k4);
+    Subround(J, e1, a1, b1, c1, d1, ripemd->buffer[11], 11, k4);
+    Subround(J, d1, e1, a1, b1, c1, ripemd->buffer[ 6],  8, k4);
+    Subround(J, c1, d1, e1, a1, b1, ripemd->buffer[15],  5, k4);
+    Subround(J, b1, c1, d1, e1, a1, ripemd->buffer[13],  6, k4);
+
+    Subround(J, a2, b2, c2, d2, e2, ripemd->buffer[ 5],  8, k5);
+    Subround(J, e2, a2, b2, c2, d2, ripemd->buffer[14],  9, k5);
+    Subround(J, d2, e2, a2, b2, c2, ripemd->buffer[ 7],  9, k5);
+    Subround(J, c2, d2, e2, a2, b2, ripemd->buffer[ 0], 11, k5);
+    Subround(J, b2, c2, d2, e2, a2, ripemd->buffer[ 9], 13, k5);
+    Subround(J, a2, b2, c2, d2, e2, ripemd->buffer[ 2], 15, k5);
+    Subround(J, e2, a2, b2, c2, d2, ripemd->buffer[11], 15, k5);
+    Subround(J, d2, e2, a2, b2, c2, ripemd->buffer[ 4],  5, k5);
+    Subround(J, c2, d2, e2, a2, b2, ripemd->buffer[13],  7, k5);
+    Subround(J, b2, c2, d2, e2, a2, ripemd->buffer[ 6],  7, k5);
+    Subround(J, a2, b2, c2, d2, e2, ripemd->buffer[15],  8, k5);
+    Subround(J, e2, a2, b2, c2, d2, ripemd->buffer[ 8], 11, k5);
+    Subround(J, d2, e2, a2, b2, c2, ripemd->buffer[ 1], 14, k5);
+    Subround(J, c2, d2, e2, a2, b2, ripemd->buffer[10], 14, k5);
+    Subround(J, b2, c2, d2, e2, a2, ripemd->buffer[ 3], 12, k5);
+    Subround(J, a2, b2, c2, d2, e2, ripemd->buffer[12],  6, k5);
+
+    Subround(I, e2, a2, b2, c2, d2, ripemd->buffer[ 6],  9, k6);
+    Subround(I, d2, e2, a2, b2, c2, ripemd->buffer[11], 13, k6);
+    Subround(I, c2, d2, e2, a2, b2, ripemd->buffer[ 3], 15, k6);
+    Subround(I, b2, c2, d2, e2, a2, ripemd->buffer[ 7],  7, k6);
+    Subround(I, a2, b2, c2, d2, e2, ripemd->buffer[ 0], 12, k6);
+    Subround(I, e2, a2, b2, c2, d2, ripemd->buffer[13],  8, k6);
+    Subround(I, d2, e2, a2, b2, c2, ripemd->buffer[ 5],  9, k6);
+    Subround(I, c2, d2, e2, a2, b2, ripemd->buffer[10], 11, k6);
+    Subround(I, b2, c2, d2, e2, a2, ripemd->buffer[14],  7, k6);
+    Subround(I, a2, b2, c2, d2, e2, ripemd->buffer[15],  7, k6);
+    Subround(I, e2, a2, b2, c2, d2, ripemd->buffer[ 8], 12, k6);
+    Subround(I, d2, e2, a2, b2, c2, ripemd->buffer[12],  7, k6);
+    Subround(I, c2, d2, e2, a2, b2, ripemd->buffer[ 4],  6, k6);
+    Subround(I, b2, c2, d2, e2, a2, ripemd->buffer[ 9], 15, k6);
+    Subround(I, a2, b2, c2, d2, e2, ripemd->buffer[ 1], 13, k6);
+    Subround(I, e2, a2, b2, c2, d2, ripemd->buffer[ 2], 11, k6);
+
+    Subround(H, d2, e2, a2, b2, c2, ripemd->buffer[15],  9, k7);
+    Subround(H, c2, d2, e2, a2, b2, ripemd->buffer[ 5],  7, k7);
+    Subround(H, b2, c2, d2, e2, a2, ripemd->buffer[ 1], 15, k7);
+    Subround(H, a2, b2, c2, d2, e2, ripemd->buffer[ 3], 11, k7);
+    Subround(H, e2, a2, b2, c2, d2, ripemd->buffer[ 7],  8, k7);
+    Subround(H, d2, e2, a2, b2, c2, ripemd->buffer[14],  6, k7);
+    Subround(H, c2, d2, e2, a2, b2, ripemd->buffer[ 6],  6, k7);
+    Subround(H, b2, c2, d2, e2, a2, ripemd->buffer[ 9], 14, k7);
+    Subround(H, a2, b2, c2, d2, e2, ripemd->buffer[11], 12, k7);
+    Subround(H, e2, a2, b2, c2, d2, ripemd->buffer[ 8], 13, k7);
+    Subround(H, d2, e2, a2, b2, c2, ripemd->buffer[12],  5, k7);
+    Subround(H, c2, d2, e2, a2, b2, ripemd->buffer[ 2], 14, k7);
+    Subround(H, b2, c2, d2, e2, a2, ripemd->buffer[10], 13, k7);
+    Subround(H, a2, b2, c2, d2, e2, ripemd->buffer[ 0], 13, k7);
+    Subround(H, e2, a2, b2, c2, d2, ripemd->buffer[ 4],  7, k7);
+    Subround(H, d2, e2, a2, b2, c2, ripemd->buffer[13],  5, k7);
+
+    Subround(G, c2, d2, e2, a2, b2, ripemd->buffer[ 8], 15, k8);
+    Subround(G, b2, c2, d2, e2, a2, ripemd->buffer[ 6],  5, k8);
+    Subround(G, a2, b2, c2, d2, e2, ripemd->buffer[ 4],  8, k8);
+    Subround(G, e2, a2, b2, c2, d2, ripemd->buffer[ 1], 11, k8);
+    Subround(G, d2, e2, a2, b2, c2, ripemd->buffer[ 3], 14, k8);
+    Subround(G, c2, d2, e2, a2, b2, ripemd->buffer[11], 14, k8);
+    Subround(G, b2, c2, d2, e2, a2, ripemd->buffer[15],  6, k8);
+    Subround(G, a2, b2, c2, d2, e2, ripemd->buffer[ 0], 14, k8);
+    Subround(G, e2, a2, b2, c2, d2, ripemd->buffer[ 5],  6, k8);
+    Subround(G, d2, e2, a2, b2, c2, ripemd->buffer[12],  9, k8);
+    Subround(G, c2, d2, e2, a2, b2, ripemd->buffer[ 2], 12, k8);
+    Subround(G, b2, c2, d2, e2, a2, ripemd->buffer[13],  9, k8);
+    Subround(G, a2, b2, c2, d2, e2, ripemd->buffer[ 9], 12, k8);
+    Subround(G, e2, a2, b2, c2, d2, ripemd->buffer[ 7],  5, k8);
+    Subround(G, d2, e2, a2, b2, c2, ripemd->buffer[10], 15, k8);
+    Subround(G, c2, d2, e2, a2, b2, ripemd->buffer[14],  8, k8);
+
+    Subround(F, b2, c2, d2, e2, a2, ripemd->buffer[12],  8, k9);
+    Subround(F, a2, b2, c2, d2, e2, ripemd->buffer[15],  5, k9);
+    Subround(F, e2, a2, b2, c2, d2, ripemd->buffer[10], 12, k9);
+    Subround(F, d2, e2, a2, b2, c2, ripemd->buffer[ 4],  9, k9);
+    Subround(F, c2, d2, e2, a2, b2, ripemd->buffer[ 1], 12, k9);
+    Subround(F, b2, c2, d2, e2, a2, ripemd->buffer[ 5],  5, k9);
+    Subround(F, a2, b2, c2, d2, e2, ripemd->buffer[ 8], 14, k9);
+    Subround(F, e2, a2, b2, c2, d2, ripemd->buffer[ 7],  6, k9);
+    Subround(F, d2, e2, a2, b2, c2, ripemd->buffer[ 6],  8, k9);
+    Subround(F, c2, d2, e2, a2, b2, ripemd->buffer[ 2], 13, k9);
+    Subround(F, b2, c2, d2, e2, a2, ripemd->buffer[13],  6, k9);
+    Subround(F, a2, b2, c2, d2, e2, ripemd->buffer[14],  5, k9);
+    Subround(F, e2, a2, b2, c2, d2, ripemd->buffer[ 0], 15, k9);
+    Subround(F, d2, e2, a2, b2, c2, ripemd->buffer[ 3], 13, k9);
+    Subround(F, c2, d2, e2, a2, b2, ripemd->buffer[ 9], 11, k9);
+    Subround(F, b2, c2, d2, e2, a2, ripemd->buffer[11], 11, k9);
+
+    c1                = ripemd->digest[1] + c1 + d2;
+    ripemd->digest[1] = ripemd->digest[2] + d1 + e2;
+    ripemd->digest[2] = ripemd->digest[3] + e1 + a2;
+    ripemd->digest[3] = ripemd->digest[4] + a1 + b2;
+    ripemd->digest[4] = ripemd->digest[0] + b1 + c2;
+    ripemd->digest[0] = c1;
+}
+
+
+static WC_INLINE void AddLength(RipeMd* ripemd, word32 len)
+{
+    word32 tmp = ripemd->loLen;
+    if ( (ripemd->loLen += len) < tmp)
+        ripemd->hiLen++;                       /* carry low to high */
+}
+
+
+int wc_RipeMdUpdate(RipeMd* ripemd, const byte* data, word32 len)
+{
+    /* do block size increments */
+    byte* local;
+
+    if (ripemd == NULL || (data == NULL && len > 0)) {
+        return BAD_FUNC_ARG;
+    }
+
+    local = (byte*)ripemd->buffer;
+
+    while (len) {
+        word32 add = min(len, RIPEMD_BLOCK_SIZE - ripemd->buffLen);
+        XMEMCPY(&local[ripemd->buffLen], data, add);
+
+        ripemd->buffLen += add;
+        data         += add;
+        len          -= add;
+
+        if (ripemd->buffLen == RIPEMD_BLOCK_SIZE) {
+            #ifdef BIG_ENDIAN_ORDER
+                ByteReverseWords(ripemd->buffer, ripemd->buffer,
+                                 RIPEMD_BLOCK_SIZE);
+            #endif
+            Transform(ripemd);
+            AddLength(ripemd, RIPEMD_BLOCK_SIZE);
+            ripemd->buffLen = 0;
+        }
+    }
+    return 0;
+}
+
+
+int wc_RipeMdFinal(RipeMd* ripemd, byte* hash)
+{
+    byte* local;
+
+    if (ripemd == NULL || hash == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    local = (byte*)ripemd->buffer;
+
+    AddLength(ripemd, ripemd->buffLen);               /* before adding pads */
+
+    local[ripemd->buffLen++] = 0x80;  /* add 1 */
+
+    /* pad with zeros */
+    if (ripemd->buffLen > RIPEMD_PAD_SIZE) {
+        XMEMSET(&local[ripemd->buffLen], 0, RIPEMD_BLOCK_SIZE - ripemd->buffLen);
+        ripemd->buffLen += RIPEMD_BLOCK_SIZE - ripemd->buffLen;
+
+        #ifdef BIG_ENDIAN_ORDER
+            ByteReverseWords(ripemd->buffer, ripemd->buffer, RIPEMD_BLOCK_SIZE);
+        #endif
+        Transform(ripemd);
+        ripemd->buffLen = 0;
+    }
+    XMEMSET(&local[ripemd->buffLen], 0, RIPEMD_PAD_SIZE - ripemd->buffLen);
+
+    /* put lengths in bits */
+    ripemd->loLen = ripemd->loLen << 3;
+    ripemd->hiLen = (ripemd->loLen >> (8*sizeof(ripemd->loLen) - 3)) +
+                 (ripemd->hiLen << 3);
+
+    /* store lengths */
+    #ifdef BIG_ENDIAN_ORDER
+        ByteReverseWords(ripemd->buffer, ripemd->buffer, RIPEMD_BLOCK_SIZE);
+    #endif
+    /* ! length ordering dependent on digest endian type ! */
+    XMEMCPY(&local[RIPEMD_PAD_SIZE], &ripemd->loLen, sizeof(word32));
+    XMEMCPY(&local[RIPEMD_PAD_SIZE + sizeof(word32)], &ripemd->hiLen,
+           sizeof(word32));
+
+    Transform(ripemd);
+    #ifdef BIG_ENDIAN_ORDER
+        ByteReverseWords(ripemd->digest, ripemd->digest, RIPEMD_DIGEST_SIZE);
+    #endif
+    XMEMCPY(hash, ripemd->digest, RIPEMD_DIGEST_SIZE);
+
+    return wc_InitRipeMd(ripemd);  /* reset state */
+}
+
+
+#endif /* WOLFSSL_RIPEMD */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/rsa.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/rsa.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/rsa.c	(revision 453)
@@ -0,0 +1,4201 @@
+/* rsa.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+
+#ifndef NO_RSA
+
+#if defined(HAVE_FIPS) && \
+    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
+
+    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
+    #define FIPS_NO_WRAPPERS
+
+       #ifdef USE_WINDOWS_API
+               #pragma code_seg(".fipsA$e")
+               #pragma const_seg(".fipsB$e")
+       #endif
+#endif
+
+#include <wolfssl/wolfcrypt/rsa.h>
+
+#ifdef WOLFSSL_AFALG_XILINX_RSA
+#include <wolfssl/wolfcrypt/port/af_alg/wc_afalg.h>
+#endif
+
+#ifdef WOLFSSL_HAVE_SP_RSA
+#include <wolfssl/wolfcrypt/sp.h>
+#endif
+
+/*
+Possible RSA enable options:
+ * NO_RSA:              Overall control of RSA                      default: on (not defined)
+ * WC_RSA_BLINDING:     Uses Blinding w/ Private Ops                default: off
+                        Note: slower by ~20%
+ * WOLFSSL_KEY_GEN:     Allows Private Key Generation               default: off
+ * RSA_LOW_MEM:         NON CRT Private Operations, less memory     default: off
+ * WC_NO_RSA_OAEP:      Disables RSA OAEP padding                   default: on (not defined)
+ * WC_RSA_NONBLOCK:     Enables support for RSA non-blocking        default: off
+ * WC_RSA_NONBLOCK_TIME:Enables support for time based blocking     default: off
+ *                      time calculation.
+*/
+
+/*
+RSA Key Size Configuration:
+ * FP_MAX_BITS:         With USE_FAST_MATH only                     default: 4096
+    If USE_FAST_MATH then use this to override default.
+    Value is key size * 2. Example: RSA 3072 = 6144
+*/
+
+
+/* If building for old FIPS. */
+#if defined(HAVE_FIPS) && \
+    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
+
+int  wc_InitRsaKey(RsaKey* key, void* ptr)
+{
+    if (key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    return InitRsaKey_fips(key, ptr);
+}
+
+
+int  wc_InitRsaKey_ex(RsaKey* key, void* ptr, int devId)
+{
+    (void)devId;
+    if (key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+    return InitRsaKey_fips(key, ptr);
+}
+
+
+int  wc_FreeRsaKey(RsaKey* key)
+{
+    return FreeRsaKey_fips(key);
+}
+
+
+#ifndef WOLFSSL_RSA_VERIFY_ONLY
+int  wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out,
+                                 word32 outLen, RsaKey* key, WC_RNG* rng)
+{
+    if (in == NULL || out == NULL || key == NULL || rng == NULL) {
+        return BAD_FUNC_ARG;
+    }
+    return RsaPublicEncrypt_fips(in, inLen, out, outLen, key, rng);
+}
+#endif
+
+
+#ifndef WOLFSSL_RSA_PUBLIC_ONLY
+int  wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out,
+                                        RsaKey* key)
+{
+    if (in == NULL || out == NULL || key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+    return RsaPrivateDecryptInline_fips(in, inLen, out, key);
+}
+
+
+int  wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out,
+                                  word32 outLen, RsaKey* key)
+{
+    if (in == NULL || out == NULL || key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+    return RsaPrivateDecrypt_fips(in, inLen, out, outLen, key);
+}
+
+
+int  wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out,
+                            word32 outLen, RsaKey* key, WC_RNG* rng)
+{
+    if (in == NULL || out == NULL || key == NULL || inLen == 0) {
+        return BAD_FUNC_ARG;
+    }
+    return RsaSSL_Sign_fips(in, inLen, out, outLen, key, rng);
+}
+#endif
+
+
+int  wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key)
+{
+    if (in == NULL || out == NULL || key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+    return RsaSSL_VerifyInline_fips(in, inLen, out, key);
+}
+
+
+int  wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out,
+                              word32 outLen, RsaKey* key)
+{
+    if (in == NULL || out == NULL || key == NULL || inLen == 0) {
+        return BAD_FUNC_ARG;
+    }
+    return RsaSSL_Verify_fips(in, inLen, out, outLen, key);
+}
+
+
+int  wc_RsaEncryptSize(RsaKey* key)
+{
+    if (key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+    return RsaEncryptSize_fips(key);
+}
+
+
+#ifndef WOLFSSL_RSA_VERIFY_ONLY
+int wc_RsaFlattenPublicKey(RsaKey* key, byte* a, word32* aSz, byte* b,
+                           word32* bSz)
+{
+
+    /* not specified as fips so not needing _fips */
+    return RsaFlattenPublicKey(key, a, aSz, b, bSz);
+}
+#endif
+
+
+#ifdef WOLFSSL_KEY_GEN
+    int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng)
+    {
+        return MakeRsaKey(key, size, e, rng);
+    }
+#endif
+
+
+/* these are functions in asn and are routed to wolfssl/wolfcrypt/asn.c
+* wc_RsaPrivateKeyDecode
+* wc_RsaPublicKeyDecode
+*/
+
+#else /* else build without fips, or for new fips */
+
+#include <wolfssl/wolfcrypt/random.h>
+#include <wolfssl/wolfcrypt/logging.h>
+#ifdef WOLF_CRYPTO_CB
+    #include <wolfssl/wolfcrypt/cryptocb.h>
+#endif
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+
+enum {
+    RSA_STATE_NONE = 0,
+
+    RSA_STATE_ENCRYPT_PAD,
+    RSA_STATE_ENCRYPT_EXPTMOD,
+    RSA_STATE_ENCRYPT_RES,
+
+    RSA_STATE_DECRYPT_EXPTMOD,
+    RSA_STATE_DECRYPT_UNPAD,
+    RSA_STATE_DECRYPT_RES,
+};
+
+
+static void wc_RsaCleanup(RsaKey* key)
+{
+#ifndef WOLFSSL_RSA_VERIFY_INLINE
+    if (key && key->data) {
+        /* make sure any allocated memory is free'd */
+        if (key->dataIsAlloc) {
+        #ifndef WOLFSSL_RSA_PUBLIC_ONLY
+            if (key->type == RSA_PRIVATE_DECRYPT ||
+                key->type == RSA_PRIVATE_ENCRYPT) {
+                ForceZero(key->data, key->dataLen);
+            }
+        #endif
+            XFREE(key->data, key->heap, DYNAMIC_TYPE_WOLF_BIGINT);
+            key->dataIsAlloc = 0;
+        }
+        key->data = NULL;
+        key->dataLen = 0;
+    }
+#else
+    (void)key;
+#endif
+}
+
+int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId)
+{
+    int ret = 0;
+
+    if (key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    XMEMSET(key, 0, sizeof(RsaKey));
+
+    key->type = RSA_TYPE_UNKNOWN;
+    key->state = RSA_STATE_NONE;
+    key->heap = heap;
+#ifndef WOLFSSL_RSA_VERIFY_INLINE
+    key->dataIsAlloc = 0;
+    key->data = NULL;
+#endif
+    key->dataLen = 0;
+#ifdef WC_RSA_BLINDING
+    key->rng = NULL;
+#endif
+
+#ifdef WOLF_CRYPTO_CB
+    key->devId = devId;
+#else
+    (void)devId;
+#endif
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    #ifdef WOLFSSL_CERT_GEN
+        XMEMSET(&key->certSignCtx, 0, sizeof(CertSignCtx));
+    #endif
+
+    #ifdef WC_ASYNC_ENABLE_RSA
+        /* handle as async */
+        ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_RSA,
+                                                            key->heap, devId);
+        if (ret != 0)
+            return ret;
+    #endif /* WC_ASYNC_ENABLE_RSA */
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+#ifndef WOLFSSL_RSA_PUBLIC_ONLY
+    ret = mp_init_multi(&key->n, &key->e, NULL, NULL, NULL, NULL);
+    if (ret != MP_OKAY)
+        return ret;
+
+#if !defined(WOLFSSL_KEY_GEN) && !defined(OPENSSL_EXTRA) && defined(RSA_LOW_MEM)
+    ret = mp_init_multi(&key->d, &key->p, &key->q, NULL, NULL, NULL);
+#else
+    ret = mp_init_multi(&key->d, &key->p, &key->q, &key->dP, &key->dQ, &key->u);
+#endif
+    if (ret != MP_OKAY) {
+        mp_clear(&key->n);
+        mp_clear(&key->e);
+        return ret;
+    }
+#else
+    ret = mp_init(&key->n);
+    if (ret != MP_OKAY)
+        return ret;
+    ret = mp_init(&key->e);
+    if (ret != MP_OKAY) {
+        mp_clear(&key->n);
+        return ret;
+    }
+#endif
+
+#ifdef WOLFSSL_XILINX_CRYPT
+    key->pubExp = 0;
+    key->mod    = NULL;
+#endif
+
+#ifdef WOLFSSL_AFALG_XILINX_RSA
+    key->alFd = WC_SOCK_NOTSET;
+    key->rdFd = WC_SOCK_NOTSET;
+#endif
+
+    return ret;
+}
+
+int wc_InitRsaKey(RsaKey* key, void* heap)
+{
+    return wc_InitRsaKey_ex(key, heap, INVALID_DEVID);
+}
+
+#ifdef HAVE_PKCS11
+int wc_InitRsaKey_Id(RsaKey* key, unsigned char* id, int len, void* heap,
+                     int devId)
+{
+    int ret = 0;
+
+    if (key == NULL)
+        ret = BAD_FUNC_ARG;
+    if (ret == 0 && (len < 0 || len > RSA_MAX_ID_LEN))
+        ret = BUFFER_E;
+
+    if (ret == 0)
+        ret = wc_InitRsaKey_ex(key, heap, devId);
+
+    if (ret == 0 && id != NULL && len != 0) {
+        XMEMCPY(key->id, id, len);
+        key->idLen = len;
+    }
+
+    return ret;
+}
+#endif
+
+
+#ifdef WOLFSSL_XILINX_CRYPT
+#define MAX_E_SIZE 4
+/* Used to setup hardware state
+ *
+ * key  the RSA key to setup
+ *
+ * returns 0 on success
+ */
+int wc_InitRsaHw(RsaKey* key)
+{
+    unsigned char* m; /* RSA modulous */
+    word32 e = 0;     /* RSA public exponent */
+    int mSz;
+    int eSz;
+
+    if (key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    mSz = mp_unsigned_bin_size(&(key->n));
+    m = (unsigned char*)XMALLOC(mSz, key->heap, DYNAMIC_TYPE_KEY);
+    if (m == 0) {
+        return MEMORY_E;
+    }
+
+    if (mp_to_unsigned_bin(&(key->n), m) != MP_OKAY) {
+        WOLFSSL_MSG("Unable to get RSA key modulus");
+        XFREE(m, key->heap, DYNAMIC_TYPE_KEY);
+        return MP_READ_E;
+    }
+
+    eSz = mp_unsigned_bin_size(&(key->e));
+    if (eSz > MAX_E_SIZE) {
+        WOLFSSL_MSG("Exponent of size 4 bytes expected");
+        XFREE(m, key->heap, DYNAMIC_TYPE_KEY);
+        return BAD_FUNC_ARG;
+    }
+
+    if (mp_to_unsigned_bin(&(key->e), (byte*)&e + (MAX_E_SIZE - eSz))
+                != MP_OKAY) {
+        XFREE(m, key->heap, DYNAMIC_TYPE_KEY);
+        WOLFSSL_MSG("Unable to get RSA key exponent");
+        return MP_READ_E;
+    }
+
+    /* check for existing mod buffer to avoid memory leak */
+    if (key->mod != NULL) {
+        XFREE(key->mod, key->heap, DYNAMIC_TYPE_KEY);
+    }
+
+    key->pubExp = e;
+    key->mod    = m;
+
+    if (XSecure_RsaInitialize(&(key->xRsa), key->mod, NULL,
+                (byte*)&(key->pubExp)) != XST_SUCCESS) {
+        WOLFSSL_MSG("Unable to initialize RSA on hardware");
+        XFREE(m, key->heap, DYNAMIC_TYPE_KEY);
+        return BAD_STATE_E;
+    }
+
+#ifdef WOLFSSL_XILINX_PATCH
+   /* currently a patch of xsecure_rsa.c for 2048 bit keys */
+   if (wc_RsaEncryptSize(key) == 256) {
+       if (XSecure_RsaSetSize(&(key->xRsa), 2048) != XST_SUCCESS) {
+           WOLFSSL_MSG("Unable to set RSA key size on hardware");
+           XFREE(m, key->heap, DYNAMIC_TYPE_KEY);
+           return BAD_STATE_E;
+       }
+   }
+#endif
+    return 0;
+} /* WOLFSSL_XILINX_CRYPT*/
+
+#elif defined(WOLFSSL_CRYPTOCELL)
+
+int wc_InitRsaHw(RsaKey* key)
+{
+    CRYSError_t ret = 0;
+    byte e[3];
+    word32 eSz = sizeof(e);
+    byte n[256];
+    word32 nSz = sizeof(n);
+    byte d[256];
+    word32 dSz = sizeof(d);
+    byte p[128];
+    word32 pSz = sizeof(p);
+    byte q[128];
+    word32 qSz = sizeof(q);
+
+    if (key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    ret = wc_RsaExportKey(key, e, &eSz, n, &nSz, d, &dSz, p, &pSz, q, &qSz);
+    if (ret != 0)
+        return MP_READ_E;
+
+    ret = CRYS_RSA_Build_PubKey(&key->ctx.pubKey, e, eSz, n, nSz);
+    if (ret != SA_SILIB_RET_OK){
+        WOLFSSL_MSG("CRYS_RSA_Build_PubKey failed");
+        return ret;
+    }
+
+    ret =  CRYS_RSA_Build_PrivKey(&key->ctx.privKey, d, dSz, e, eSz, n, nSz);
+
+    if (ret != SA_SILIB_RET_OK){
+        WOLFSSL_MSG("CRYS_RSA_Build_PrivKey failed");
+        return ret;
+    }
+    key->type = RSA_PRIVATE;
+    return 0;
+}
+static int cc310_RSA_GenerateKeyPair(RsaKey* key, int size, long e)
+{
+    CRYSError_t             ret = 0;
+    CRYS_RSAKGData_t        KeyGenData;
+    CRYS_RSAKGFipsContext_t FipsCtx;
+    byte ex[3];
+    uint16_t eSz = sizeof(ex);
+    byte n[256];
+    uint16_t nSz = sizeof(n);
+
+    ret = CRYS_RSA_KG_GenerateKeyPair(&wc_rndState,
+                        wc_rndGenVectFunc,
+                        (byte*)&e,
+                        3*sizeof(uint8_t),
+                        size,
+                        &key->ctx.privKey,
+                        &key->ctx.pubKey,
+                        &KeyGenData,
+                        &FipsCtx);
+
+    if (ret != SA_SILIB_RET_OK){
+        WOLFSSL_MSG("CRYS_RSA_KG_GenerateKeyPair failed");
+        return ret;
+    }
+
+    ret = CRYS_RSA_Get_PubKey(&key->ctx.pubKey, ex, &eSz, n, &nSz);
+    if (ret != SA_SILIB_RET_OK){
+        WOLFSSL_MSG("CRYS_RSA_Get_PubKey failed");
+        return ret;
+    }
+    ret = wc_RsaPublicKeyDecodeRaw(n, nSz, ex, eSz, key);
+
+    key->type = RSA_PRIVATE;
+
+    return ret;
+}
+#endif /* WOLFSSL_CRYPTOCELL */
+
+int wc_FreeRsaKey(RsaKey* key)
+{
+    int ret = 0;
+
+    if (key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    wc_RsaCleanup(key);
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA)
+    wolfAsync_DevCtxFree(&key->asyncDev, WOLFSSL_ASYNC_MARKER_RSA);
+#endif
+
+#ifndef WOLFSSL_RSA_PUBLIC_ONLY
+    if (key->type == RSA_PRIVATE) {
+#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM)
+        mp_forcezero(&key->u);
+        mp_forcezero(&key->dQ);
+        mp_forcezero(&key->dP);
+#endif
+        mp_forcezero(&key->q);
+        mp_forcezero(&key->p);
+        mp_forcezero(&key->d);
+    }
+    /* private part */
+#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM)
+    mp_clear(&key->u);
+    mp_clear(&key->dQ);
+    mp_clear(&key->dP);
+#endif
+    mp_clear(&key->q);
+    mp_clear(&key->p);
+    mp_clear(&key->d);
+#endif /* WOLFSSL_RSA_PUBLIC_ONLY */
+
+    /* public part */
+    mp_clear(&key->e);
+    mp_clear(&key->n);
+
+#ifdef WOLFSSL_XILINX_CRYPT
+    XFREE(key->mod, key->heap, DYNAMIC_TYPE_KEY);
+    key->mod = NULL;
+#endif
+
+#ifdef WOLFSSL_AFALG_XILINX_RSA
+    /* make sure that sockets are closed on cleanup */
+    if (key->alFd > 0) {
+        close(key->alFd);
+        key->alFd = WC_SOCK_NOTSET;
+    }
+    if (key->rdFd > 0) {
+        close(key->rdFd);
+        key->rdFd = WC_SOCK_NOTSET;
+    }
+#endif
+
+    return ret;
+}
+
+#ifndef WOLFSSL_RSA_PUBLIC_ONLY
+#if defined(WOLFSSL_KEY_GEN) && !defined(WOLFSSL_NO_RSA_KEY_CHECK)
+/* Check the pair-wise consistency of the RSA key.
+ * From NIST SP 800-56B, section 6.4.1.1.
+ * Verify that k = (k^e)^d, for some k: 1 < k < n-1. */
+int wc_CheckRsaKey(RsaKey* key)
+{
+#if defined(WOLFSSL_CRYPTOCELL)
+    return 0;
+#endif
+#ifdef WOLFSSL_SMALL_STACK
+    mp_int *k = NULL, *tmp = NULL;
+#else
+    mp_int k[1], tmp[1];
+#endif
+    int ret = 0;
+
+#ifdef WOLFSSL_SMALL_STACK
+    k = (mp_int*)XMALLOC(sizeof(mp_int) * 2, NULL, DYNAMIC_TYPE_RSA);
+    if (k == NULL)
+        return MEMORY_E;
+    tmp = k + 1;
+#endif
+
+    if (mp_init_multi(k, tmp, NULL, NULL, NULL, NULL) != MP_OKAY)
+        ret = MP_INIT_E;
+
+    if (ret == 0) {
+        if (key == NULL)
+            ret = BAD_FUNC_ARG;
+    }
+
+    if (ret == 0) {
+        if (mp_set_int(k, 0x2342) != MP_OKAY)
+            ret = MP_READ_E;
+    }
+
+#ifdef WOLFSSL_HAVE_SP_RSA
+#ifndef WOLFSSL_SP_NO_2048
+    if (mp_count_bits(&key->n) == 2048) {
+        ret = sp_ModExp_2048(k, &key->e, &key->n, tmp);
+        if (ret != 0)
+            ret = MP_EXPTMOD_E;
+        ret = sp_ModExp_2048(tmp, &key->d, &key->n, tmp);
+        if (ret != 0)
+            ret = MP_EXPTMOD_E;
+    }
+    else
+#endif
+#ifndef WOLFSSL_SP_NO_3072
+    if (mp_count_bits(&key->n) == 3072) {
+        ret = sp_ModExp_3072(k, &key->e, &key->n, tmp);
+        if (ret != 0)
+            ret = MP_EXPTMOD_E;
+        ret = sp_ModExp_3072(tmp, &key->d, &key->n, tmp);
+        if (ret != 0)
+            ret = MP_EXPTMOD_E;
+    }
+    else
+#endif
+#ifdef WOLFSSL_SP_4096
+    if (mp_count_bits(&key->n) == 4096) {
+        ret = sp_ModExp_4096(k, &key->e, &key->n, tmp);
+        if (ret != 0)
+            ret = MP_EXPTMOD_E;
+        ret = sp_ModExp_4096(tmp, &key->d, &key->n, tmp);
+        if (ret != 0)
+            ret = MP_EXPTMOD_E;
+    }
+    else
+#endif
+#endif
+#ifdef WOLFSSL_SP_MATH
+    {
+        ret = WC_KEY_SIZE_E;
+    }
+#else
+    {
+        if (ret == 0) {
+            if (mp_exptmod(k, &key->e, &key->n, tmp) != MP_OKAY)
+                ret = MP_EXPTMOD_E;
+        }
+
+        if (ret == 0) {
+            if (mp_exptmod(tmp, &key->d, &key->n, tmp) != MP_OKAY)
+                ret = MP_EXPTMOD_E;
+        }
+    }
+#endif
+
+    if (ret == 0) {
+        if (mp_cmp(k, tmp) != MP_EQ)
+            ret = RSA_KEY_PAIR_E;
+    }
+
+    /* Check d is less than n. */
+    if (ret == 0 ) {
+        if (mp_cmp(&key->d, &key->n) != MP_LT) {
+            ret = MP_EXPTMOD_E;
+        }
+    }
+    /* Check p*q = n. */
+    if (ret == 0 ) {
+        if (mp_mul(&key->p, &key->q, tmp) != MP_OKAY) {
+            ret = MP_EXPTMOD_E;
+        }
+    }
+    if (ret == 0 ) {
+        if (mp_cmp(&key->n, tmp) != MP_EQ) {
+            ret = MP_EXPTMOD_E;
+        }
+    }
+
+    /* Check dP, dQ and u if they exist */
+    if (ret == 0 && !mp_iszero(&key->dP)) {
+        if (mp_sub_d(&key->p, 1, tmp) != MP_OKAY) {
+            ret = MP_EXPTMOD_E;
+        }
+        /* Check dP <= p-1. */
+        if (ret == 0) {
+            if (mp_cmp(&key->dP, tmp) != MP_LT) {
+                ret = MP_EXPTMOD_E;
+            }
+        }
+        /* Check e*dP mod p-1 = 1. (dP = 1/e mod p-1) */
+        if (ret == 0) {
+            if (mp_mulmod(&key->dP, &key->e, tmp, tmp) != MP_OKAY) {
+                ret = MP_EXPTMOD_E;
+            }
+        }
+        if (ret == 0 ) {
+            if (!mp_isone(tmp)) {
+                ret = MP_EXPTMOD_E;
+            }
+        }
+
+        if (ret == 0) {
+            if (mp_sub_d(&key->q, 1, tmp) != MP_OKAY) {
+                ret = MP_EXPTMOD_E;
+            }
+        }
+        /* Check dQ <= q-1. */
+        if (ret == 0) {
+            if (mp_cmp(&key->dQ, tmp) != MP_LT) {
+                ret = MP_EXPTMOD_E;
+            }
+        }
+        /* Check e*dP mod p-1 = 1. (dQ = 1/e mod q-1) */
+        if (ret == 0) {
+            if (mp_mulmod(&key->dQ, &key->e, tmp, tmp) != MP_OKAY) {
+                ret = MP_EXPTMOD_E;
+            }
+        }
+        if (ret == 0 ) {
+            if (!mp_isone(tmp)) {
+                ret = MP_EXPTMOD_E;
+            }
+        }
+
+        /* Check u <= p. */
+        if (ret == 0) {
+            if (mp_cmp(&key->u, &key->p) != MP_LT) {
+                ret = MP_EXPTMOD_E;
+            }
+        }
+        /* Check u*q mod p = 1. (u = 1/q mod p) */
+        if (ret == 0) {
+            if (mp_mulmod(&key->u, &key->q, &key->p, tmp) != MP_OKAY) {
+                ret = MP_EXPTMOD_E;
+            }
+        }
+        if (ret == 0 ) {
+            if (!mp_isone(tmp)) {
+                ret = MP_EXPTMOD_E;
+            }
+        }
+    }
+
+    mp_forcezero(tmp);
+    mp_clear(tmp);
+    mp_clear(k);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(k, NULL, DYNAMIC_TYPE_RSA);
+#endif
+
+    return ret;
+}
+#endif
+#endif
+
+
+#if !defined(WC_NO_RSA_OAEP) || defined(WC_RSA_PSS)
+/* Uses MGF1 standard as a mask generation function
+   hType: hash type used
+   seed:  seed to use for generating mask
+   seedSz: size of seed buffer
+   out:   mask output after generation
+   outSz: size of output buffer
+ */
+#if !defined(NO_SHA) || !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512)
+static int RsaMGF1(enum wc_HashType hType, byte* seed, word32 seedSz,
+                                        byte* out, word32 outSz, void* heap)
+{
+    byte* tmp;
+    /* needs to be large enough for seed size plus counter(4) */
+    byte  tmpA[WC_MAX_DIGEST_SIZE + 4];
+    byte   tmpF;     /* 1 if dynamic memory needs freed */
+    word32 tmpSz;
+    int hLen;
+    int ret;
+    word32 counter;
+    word32 idx;
+    hLen    = wc_HashGetDigestSize(hType);
+    counter = 0;
+    idx     = 0;
+
+    (void)heap;
+
+    /* check error return of wc_HashGetDigestSize */
+    if (hLen < 0) {
+        return hLen;
+    }
+
+    /* if tmp is not large enough than use some dynamic memory */
+    if ((seedSz + 4) > sizeof(tmpA) || (word32)hLen > sizeof(tmpA)) {
+        /* find largest amount of memory needed which will be the max of
+         * hLen and (seedSz + 4) since tmp is used to store the hash digest */
+        tmpSz = ((seedSz + 4) > (word32)hLen)? seedSz + 4: (word32)hLen;
+        tmp = (byte*)XMALLOC(tmpSz, heap, DYNAMIC_TYPE_RSA_BUFFER);
+        if (tmp == NULL) {
+            return MEMORY_E;
+        }
+        tmpF = 1; /* make sure to free memory when done */
+    }
+    else {
+        /* use array on the stack */
+        tmpSz = sizeof(tmpA);
+        tmp  = tmpA;
+        tmpF = 0; /* no need to free memory at end */
+    }
+
+    do {
+        int i = 0;
+        XMEMCPY(tmp, seed, seedSz);
+
+        /* counter to byte array appended to tmp */
+        tmp[seedSz]     = (counter >> 24) & 0xFF;
+        tmp[seedSz + 1] = (counter >> 16) & 0xFF;
+        tmp[seedSz + 2] = (counter >>  8) & 0xFF;
+        tmp[seedSz + 3] = (counter)       & 0xFF;
+
+        /* hash and append to existing output */
+        if ((ret = wc_Hash(hType, tmp, (seedSz + 4), tmp, tmpSz)) != 0) {
+            /* check for if dynamic memory was needed, then free */
+            if (tmpF) {
+                XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER);
+            }
+            return ret;
+        }
+
+        for (i = 0; i < hLen && idx < outSz; i++) {
+            out[idx++] = tmp[i];
+        }
+        counter++;
+    } while (idx < outSz);
+
+    /* check for if dynamic memory was needed, then free */
+    if (tmpF) {
+        XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER);
+    }
+
+    return 0;
+}
+#endif /* SHA2 Hashes */
+
+/* helper function to direct which mask generation function is used
+   switched on type input
+ */
+static int RsaMGF(int type, byte* seed, word32 seedSz, byte* out,
+                                                    word32 outSz, void* heap)
+{
+    int ret;
+
+    switch(type) {
+    #ifndef NO_SHA
+        case WC_MGF1SHA1:
+            ret = RsaMGF1(WC_HASH_TYPE_SHA, seed, seedSz, out, outSz, heap);
+            break;
+    #endif
+    #ifndef NO_SHA256
+    #ifdef WOLFSSL_SHA224
+        case WC_MGF1SHA224:
+            ret = RsaMGF1(WC_HASH_TYPE_SHA224, seed, seedSz, out, outSz, heap);
+            break;
+    #endif
+        case WC_MGF1SHA256:
+            ret = RsaMGF1(WC_HASH_TYPE_SHA256, seed, seedSz, out, outSz, heap);
+            break;
+    #endif
+    #ifdef WOLFSSL_SHA384
+        case WC_MGF1SHA384:
+            ret = RsaMGF1(WC_HASH_TYPE_SHA384, seed, seedSz, out, outSz, heap);
+            break;
+    #endif
+    #ifdef WOLFSSL_SHA512
+        case WC_MGF1SHA512:
+            ret = RsaMGF1(WC_HASH_TYPE_SHA512, seed, seedSz, out, outSz, heap);
+            break;
+    #endif
+        default:
+            WOLFSSL_MSG("Unknown MGF type: check build options");
+            ret = BAD_FUNC_ARG;
+    }
+
+    /* in case of default avoid unused warning */
+    (void)seed;
+    (void)seedSz;
+    (void)out;
+    (void)outSz;
+    (void)heap;
+
+    return ret;
+}
+#endif /* !WC_NO_RSA_OAEP || WC_RSA_PSS */
+
+
+/* Padding */
+#ifndef WOLFSSL_RSA_VERIFY_ONLY
+#ifndef WC_NO_RNG
+#ifndef WC_NO_RSA_OAEP
+static int RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock,
+        word32 pkcsBlockLen, byte padValue, WC_RNG* rng,
+        enum wc_HashType hType, int mgf, byte* optLabel, word32 labelLen,
+        void* heap)
+{
+    int ret;
+    int hLen;
+    int psLen;
+    int i;
+    word32 idx;
+
+    byte* dbMask;
+
+    #ifdef WOLFSSL_SMALL_STACK
+        byte* lHash = NULL;
+        byte* seed  = NULL;
+    #else
+        /* must be large enough to contain largest hash */
+        byte lHash[WC_MAX_DIGEST_SIZE];
+        byte seed[ WC_MAX_DIGEST_SIZE];
+    #endif
+
+    /* no label is allowed, but catch if no label provided and length > 0 */
+    if (optLabel == NULL && labelLen > 0) {
+        return BUFFER_E;
+    }
+
+    /* limit of label is the same as limit of hash function which is massive */
+    hLen = wc_HashGetDigestSize(hType);
+    if (hLen < 0) {
+        return hLen;
+    }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        lHash = (byte*)XMALLOC(hLen, heap, DYNAMIC_TYPE_RSA_BUFFER);
+        if (lHash == NULL) {
+            return MEMORY_E;
+        }
+        seed = (byte*)XMALLOC(hLen, heap, DYNAMIC_TYPE_RSA_BUFFER);
+        if (seed == NULL) {
+            XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER);
+            return MEMORY_E;
+        }
+    #else
+        /* hLen should never be larger than lHash since size is max digest size,
+           but check before blindly calling wc_Hash */
+        if ((word32)hLen > sizeof(lHash)) {
+            WOLFSSL_MSG("OAEP lHash to small for digest!!");
+            return MEMORY_E;
+        }
+    #endif
+
+    if ((ret = wc_Hash(hType, optLabel, labelLen, lHash, hLen)) != 0) {
+        WOLFSSL_MSG("OAEP hash type possibly not supported or lHash to small");
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER);
+            XFREE(seed,  heap, DYNAMIC_TYPE_RSA_BUFFER);
+        #endif
+        return ret;
+    }
+
+    /* handles check of location for idx as well as psLen, cast to int to check
+       for pkcsBlockLen(k) - 2 * hLen - 2 being negative
+       This check is similar to decryption where k > 2 * hLen + 2 as msg
+       size approaches 0. In decryption if k is less than or equal -- then there
+       is no possible room for msg.
+       k = RSA key size
+       hLen = hash digest size -- will always be >= 0 at this point
+     */
+    if ((word32)(2 * hLen + 2) > pkcsBlockLen) {
+        WOLFSSL_MSG("OAEP pad error hash to big for RSA key size");
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER);
+            XFREE(seed,  heap, DYNAMIC_TYPE_RSA_BUFFER);
+        #endif
+        return BAD_FUNC_ARG;
+    }
+
+    if (inputLen > (pkcsBlockLen - 2 * hLen - 2)) {
+        WOLFSSL_MSG("OAEP pad error message too long");
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER);
+            XFREE(seed,  heap, DYNAMIC_TYPE_RSA_BUFFER);
+        #endif
+        return BAD_FUNC_ARG;
+    }
+
+    /* concatenate lHash || PS || 0x01 || msg */
+    idx = pkcsBlockLen - 1 - inputLen;
+    psLen = pkcsBlockLen - inputLen - 2 * hLen - 2;
+    if (pkcsBlockLen < inputLen) { /*make sure not writing over end of buffer */
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER);
+            XFREE(seed,  heap, DYNAMIC_TYPE_RSA_BUFFER);
+        #endif
+        return BUFFER_E;
+    }
+    XMEMCPY(pkcsBlock + (pkcsBlockLen - inputLen), input, inputLen);
+    pkcsBlock[idx--] = 0x01; /* PS and M separator */
+    while (psLen > 0 && idx > 0) {
+        pkcsBlock[idx--] = 0x00;
+        psLen--;
+    }
+
+    idx = idx - hLen + 1;
+    XMEMCPY(pkcsBlock + idx, lHash, hLen);
+
+    /* generate random seed */
+    if ((ret = wc_RNG_GenerateBlock(rng, seed, hLen)) != 0) {
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER);
+            XFREE(seed,  heap, DYNAMIC_TYPE_RSA_BUFFER);
+        #endif
+        return ret;
+    }
+
+    /* create maskedDB from dbMask */
+    dbMask = (byte*)XMALLOC(pkcsBlockLen - hLen - 1, heap, DYNAMIC_TYPE_RSA);
+    if (dbMask == NULL) {
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER);
+            XFREE(seed,  heap, DYNAMIC_TYPE_RSA_BUFFER);
+        #endif
+        return MEMORY_E;
+    }
+    XMEMSET(dbMask, 0, pkcsBlockLen - hLen - 1); /* help static analyzer */
+
+    ret = RsaMGF(mgf, seed, hLen, dbMask, pkcsBlockLen - hLen - 1, heap);
+    if (ret != 0) {
+        XFREE(dbMask, heap, DYNAMIC_TYPE_RSA);
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER);
+            XFREE(seed,  heap, DYNAMIC_TYPE_RSA_BUFFER);
+        #endif
+        return ret;
+    }
+
+    i = 0;
+    idx = hLen + 1;
+    while (idx < pkcsBlockLen && (word32)i < (pkcsBlockLen - hLen -1)) {
+        pkcsBlock[idx] = dbMask[i++] ^ pkcsBlock[idx];
+        idx++;
+    }
+    XFREE(dbMask, heap, DYNAMIC_TYPE_RSA);
+
+
+    /* create maskedSeed from seedMask */
+    idx = 0;
+    pkcsBlock[idx++] = 0x00;
+    /* create seedMask inline */
+    if ((ret = RsaMGF(mgf, pkcsBlock + hLen + 1, pkcsBlockLen - hLen - 1,
+                                           pkcsBlock + 1, hLen, heap)) != 0) {
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER);
+            XFREE(seed,  heap, DYNAMIC_TYPE_RSA_BUFFER);
+        #endif
+        return ret;
+    }
+
+    /* xor created seedMask with seed to make maskedSeed */
+    i = 0;
+    while (idx < (word32)(hLen + 1) && i < hLen) {
+        pkcsBlock[idx] = pkcsBlock[idx] ^ seed[i++];
+        idx++;
+    }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER);
+        XFREE(seed,  heap, DYNAMIC_TYPE_RSA_BUFFER);
+    #endif
+    (void)padValue;
+
+    return 0;
+}
+#endif /* !WC_NO_RSA_OAEP */
+
+#ifdef WC_RSA_PSS
+
+/* 0x00 .. 0x00 0x01 | Salt | Gen Hash | 0xbc
+ * XOR MGF over all bytes down to end of Salt
+ * Gen Hash = HASH(8 * 0x00 | Message Hash | Salt)
+ *
+ * input         Digest of the message.
+ * inputLen      Length of digest.
+ * pkcsBlock     Buffer to write to.
+ * pkcsBlockLen  Length of buffer to write to.
+ * rng           Random number generator (for salt).
+ * htype         Hash function to use.
+ * mgf           Mask generation function.
+ * saltLen       Length of salt to put in padding.
+ * bits          Length of key in bits.
+ * heap          Used for dynamic memory allocation.
+ * returns 0 on success, PSS_SALTLEN_E when the salt length is invalid
+ * and other negative values on error.
+ */
+static int RsaPad_PSS(const byte* input, word32 inputLen, byte* pkcsBlock,
+        word32 pkcsBlockLen, WC_RNG* rng, enum wc_HashType hType, int mgf,
+        int saltLen, int bits, void* heap)
+{
+    int   ret = 0;
+    int   hLen, i, o, maskLen, hiBits;
+    byte* m;
+    byte* s;
+#if defined(WOLFSSL_PSS_LONG_SALT) || defined(WOLFSSL_PSS_SALT_LEN_DISCOVER)
+    #if defined(WOLFSSL_NO_MALLOC) && !defined(WOLFSSL_STATIC_MEMORY)
+        byte salt[RSA_MAX_SIZE/8 + RSA_PSS_PAD_SZ];
+    #else
+        byte* salt = NULL;
+    #endif
+#else
+    byte salt[WC_MAX_DIGEST_SIZE];
+#endif
+
+#if defined(WOLFSSL_PSS_LONG_SALT) || defined(WOLFSSL_PSS_SALT_LEN_DISCOVER)
+    if (pkcsBlockLen > RSA_MAX_SIZE/8) {
+        return MEMORY_E;
+    }
+#endif
+
+    hLen = wc_HashGetDigestSize(hType);
+    if (hLen < 0)
+        return hLen;
+
+    hiBits = (bits - 1) & 0x7;
+    if (hiBits == 0) {
+        *(pkcsBlock++) = 0;
+        pkcsBlockLen--;
+    }
+
+    if (saltLen == RSA_PSS_SALT_LEN_DEFAULT) {
+        saltLen = hLen;
+        #ifdef WOLFSSL_SHA512
+            /* See FIPS 186-4 section 5.5 item (e). */
+            if (bits == 1024 && hLen == WC_SHA512_DIGEST_SIZE) {
+                saltLen = RSA_PSS_SALT_MAX_SZ;
+            }
+        #endif
+    }
+#ifndef WOLFSSL_PSS_LONG_SALT
+    else if (saltLen > hLen) {
+        return PSS_SALTLEN_E;
+    }
+#endif
+#ifndef WOLFSSL_PSS_SALT_LEN_DISCOVER
+    else if (saltLen < RSA_PSS_SALT_LEN_DEFAULT) {
+        return PSS_SALTLEN_E;
+    }
+#else
+    else if (saltLen == RSA_PSS_SALT_LEN_DISCOVER) {
+        saltLen = (int)pkcsBlockLen - hLen - 2;
+        if (saltLen < 0) {
+            return PSS_SALTLEN_E;
+        }
+    }
+    else if (saltLen < RSA_PSS_SALT_LEN_DISCOVER) {
+        return PSS_SALTLEN_E;
+    }
+#endif
+    if ((int)pkcsBlockLen - hLen < saltLen + 2) {
+        return PSS_SALTLEN_E;
+    }
+
+    maskLen = pkcsBlockLen - 1 - hLen;
+
+#if defined(WOLFSSL_PSS_LONG_SALT) || defined(WOLFSSL_PSS_SALT_LEN_DISCOVER)
+    #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
+        salt = (byte*)XMALLOC(RSA_PSS_PAD_SZ + inputLen + saltLen, heap,
+                                                       DYNAMIC_TYPE_RSA_BUFFER);
+        if (salt == NULL) {
+            return MEMORY_E;
+        }
+    #endif
+    s = m = salt;
+    XMEMSET(m, 0, RSA_PSS_PAD_SZ);
+    m += RSA_PSS_PAD_SZ;
+    XMEMCPY(m, input, inputLen);
+    m += inputLen;
+    o = (int)(m - s);
+    if (saltLen > 0) {
+        ret = wc_RNG_GenerateBlock(rng, m, saltLen);
+        if (ret == 0) {
+            m += saltLen;
+        }
+    }
+#else
+    s = m = pkcsBlock;
+    XMEMSET(m, 0, RSA_PSS_PAD_SZ);
+    m += RSA_PSS_PAD_SZ;
+    XMEMCPY(m, input, inputLen);
+    m += inputLen;
+    o = 0;
+    if (saltLen > 0) {
+        ret = wc_RNG_GenerateBlock(rng, salt, saltLen);
+        if (ret == 0) {
+            XMEMCPY(m, salt, saltLen);
+            m += saltLen;
+        }
+    }
+#endif
+    if (ret == 0) {
+        /* Put Hash at end of pkcsBlock - 1 */
+        ret = wc_Hash(hType, s, (word32)(m - s), pkcsBlock + maskLen, hLen);
+    }
+    if (ret == 0) {
+        pkcsBlock[pkcsBlockLen - 1] = RSA_PSS_PAD_TERM;
+
+        ret = RsaMGF(mgf, pkcsBlock + maskLen, hLen, pkcsBlock, maskLen, heap);
+    }
+    if (ret == 0) {
+        pkcsBlock[0] &= (1 << hiBits) - 1;
+
+        m = pkcsBlock + maskLen - saltLen - 1;
+        *(m++) ^= 0x01;
+        for (i = 0; i < saltLen; i++) {
+            m[i] ^= salt[o + i];
+        }
+    }
+
+#if defined(WOLFSSL_PSS_LONG_SALT) || defined(WOLFSSL_PSS_SALT_LEN_DISCOVER)
+    #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
+        if (salt != NULL) {
+            XFREE(salt, heap, DYNAMIC_TYPE_RSA_BUFFER);
+        }
+    #endif
+#endif
+    return ret;
+}
+#endif /* WC_RSA_PSS */
+#endif /* !WC_NO_RNG */
+
+static int RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock,
+                           word32 pkcsBlockLen, byte padValue, WC_RNG* rng)
+{
+    if (input == NULL || inputLen == 0 || pkcsBlock == NULL ||
+                                                        pkcsBlockLen == 0) {
+        return BAD_FUNC_ARG;
+    }
+
+    pkcsBlock[0] = 0x0;       /* set first byte to zero and advance */
+    pkcsBlock++; pkcsBlockLen--;
+    pkcsBlock[0] = padValue;  /* insert padValue */
+
+    if (padValue == RSA_BLOCK_TYPE_1) {
+        if (pkcsBlockLen < inputLen + 2) {
+            WOLFSSL_MSG("RsaPad error, invalid length");
+            return RSA_PAD_E;
+        }
+
+        /* pad with 0xff bytes */
+        XMEMSET(&pkcsBlock[1], 0xFF, pkcsBlockLen - inputLen - 2);
+    }
+    else {
+#if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WC_NO_RNG)
+        /* pad with non-zero random bytes */
+        word32 padLen, i;
+        int    ret;
+
+        if (pkcsBlockLen < inputLen + 1) {
+            WOLFSSL_MSG("RsaPad error, invalid length");
+            return RSA_PAD_E;
+        }
+
+        padLen = pkcsBlockLen - inputLen - 1;
+        ret    = wc_RNG_GenerateBlock(rng, &pkcsBlock[1], padLen);
+        if (ret != 0) {
+            return ret;
+        }
+
+        /* remove zeros */
+        for (i = 1; i < padLen; i++) {
+            if (pkcsBlock[i] == 0) pkcsBlock[i] = 0x01;
+        }
+#else
+        (void)rng;
+        return RSA_WRONG_TYPE_E;
+#endif
+    }
+
+    pkcsBlock[pkcsBlockLen-inputLen-1] = 0;     /* separator */
+    XMEMCPY(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen);
+
+    return 0;
+}
+
+/* helper function to direct which padding is used */
+int wc_RsaPad_ex(const byte* input, word32 inputLen, byte* pkcsBlock,
+    word32 pkcsBlockLen, byte padValue, WC_RNG* rng, int padType,
+    enum wc_HashType hType, int mgf, byte* optLabel, word32 labelLen,
+    int saltLen, int bits, void* heap)
+{
+    int ret;
+
+    switch (padType)
+    {
+        case WC_RSA_PKCSV15_PAD:
+            /*WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 padding");*/
+            ret = RsaPad(input, inputLen, pkcsBlock, pkcsBlockLen,
+                                                                 padValue, rng);
+            break;
+
+#ifndef WC_NO_RNG
+    #ifndef WC_NO_RSA_OAEP
+        case WC_RSA_OAEP_PAD:
+            WOLFSSL_MSG("wolfSSL Using RSA OAEP padding");
+            ret = RsaPad_OAEP(input, inputLen, pkcsBlock, pkcsBlockLen,
+                           padValue, rng, hType, mgf, optLabel, labelLen, heap);
+            break;
+    #endif
+
+    #ifdef WC_RSA_PSS
+        case WC_RSA_PSS_PAD:
+            WOLFSSL_MSG("wolfSSL Using RSA PSS padding");
+            ret = RsaPad_PSS(input, inputLen, pkcsBlock, pkcsBlockLen, rng,
+                                               hType, mgf, saltLen, bits, heap);
+            break;
+    #endif
+#endif /* !WC_NO_RNG */
+
+    #ifdef WC_RSA_NO_PADDING
+        case WC_RSA_NO_PAD:
+            WOLFSSL_MSG("wolfSSL Using NO padding");
+
+            /* In the case of no padding being used check that input is exactly
+             * the RSA key length */
+            if (bits <= 0 || inputLen != ((word32)bits/WOLFSSL_BIT_SIZE)) {
+                WOLFSSL_MSG("Bad input size");
+                ret = RSA_PAD_E;
+            }
+            else {
+                XMEMCPY(pkcsBlock, input, inputLen);
+                ret = 0;
+            }
+            break;
+    #endif
+
+        default:
+            WOLFSSL_MSG("Unknown RSA Pad Type");
+            ret = RSA_PAD_E;
+    }
+
+    /* silence warning if not used with padding scheme */
+    (void)input;
+    (void)inputLen;
+    (void)pkcsBlock;
+    (void)pkcsBlockLen;
+    (void)padValue;
+    (void)rng;
+    (void)padType;
+    (void)hType;
+    (void)mgf;
+    (void)optLabel;
+    (void)labelLen;
+    (void)saltLen;
+    (void)bits;
+    (void)heap;
+
+    return ret;
+}
+#endif /* WOLFSSL_RSA_VERIFY_ONLY */
+
+
+/* UnPadding */
+#ifndef WC_NO_RSA_OAEP
+/* UnPad plaintext, set start to *output, return length of plaintext,
+ * < 0 on error */
+static int RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen,
+                            byte **output, enum wc_HashType hType, int mgf,
+                            byte* optLabel, word32 labelLen, void* heap)
+{
+    int hLen;
+    int ret;
+    byte h[WC_MAX_DIGEST_SIZE]; /* max digest size */
+    byte* tmp;
+    word32 idx;
+
+    /* no label is allowed, but catch if no label provided and length > 0 */
+    if (optLabel == NULL && labelLen > 0) {
+        return BUFFER_E;
+    }
+
+    hLen = wc_HashGetDigestSize(hType);
+    if ((hLen < 0) || (pkcsBlockLen < (2 * (word32)hLen + 2))) {
+        return BAD_FUNC_ARG;
+    }
+
+    tmp = (byte*)XMALLOC(pkcsBlockLen, heap, DYNAMIC_TYPE_RSA_BUFFER);
+    if (tmp == NULL) {
+        return MEMORY_E;
+    }
+    XMEMSET(tmp, 0, pkcsBlockLen);
+
+    /* find seedMask value */
+    if ((ret = RsaMGF(mgf, (byte*)(pkcsBlock + (hLen + 1)),
+                            pkcsBlockLen - hLen - 1, tmp, hLen, heap)) != 0) {
+        XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER);
+        return ret;
+    }
+
+    /* xor seedMask value with maskedSeed to get seed value */
+    for (idx = 0; idx < (word32)hLen; idx++) {
+        tmp[idx] = tmp[idx] ^ pkcsBlock[1 + idx];
+    }
+
+    /* get dbMask value */
+    if ((ret = RsaMGF(mgf, tmp, hLen, tmp + hLen,
+                                       pkcsBlockLen - hLen - 1, heap)) != 0) {
+        XFREE(tmp, NULL, DYNAMIC_TYPE_RSA_BUFFER);
+        return ret;
+    }
+
+    /* get DB value by doing maskedDB xor dbMask */
+    for (idx = 0; idx < (pkcsBlockLen - hLen - 1); idx++) {
+        pkcsBlock[hLen + 1 + idx] = pkcsBlock[hLen + 1 + idx] ^ tmp[idx + hLen];
+    }
+
+    /* done with use of tmp buffer */
+    XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER);
+
+    /* advance idx to index of PS and msg separator, account for PS size of 0*/
+    idx = hLen + 1 + hLen;
+    while (idx < pkcsBlockLen && pkcsBlock[idx] == 0) {idx++;}
+
+    /* create hash of label for comparison with hash sent */
+    if ((ret = wc_Hash(hType, optLabel, labelLen, h, hLen)) != 0) {
+        return ret;
+    }
+
+    /* say no to chosen ciphertext attack.
+       Comparison of lHash, Y, and separator value needs to all happen in
+       constant time.
+       Attackers should not be able to get error condition from the timing of
+       these checks.
+     */
+    ret = 0;
+    ret |= ConstantCompare(pkcsBlock + hLen + 1, h, hLen);
+    ret += pkcsBlock[idx++] ^ 0x01; /* separator value is 0x01 */
+    ret += pkcsBlock[0]     ^ 0x00; /* Y, the first value, should be 0 */
+
+    /* Return 0 data length on error. */
+    idx = ctMaskSelInt(ctMaskEq(ret, 0), idx, pkcsBlockLen);
+
+    /* adjust pointer to correct location in array and return size of M */
+    *output = (byte*)(pkcsBlock + idx);
+    return pkcsBlockLen - idx;
+}
+#endif /* WC_NO_RSA_OAEP */
+
+#ifdef WC_RSA_PSS
+/* 0x00 .. 0x00 0x01 | Salt | Gen Hash | 0xbc
+ * MGF over all bytes down to end of Salt
+ *
+ * pkcsBlock     Buffer holding decrypted data.
+ * pkcsBlockLen  Length of buffer.
+ * htype         Hash function to use.
+ * mgf           Mask generation function.
+ * saltLen       Length of salt to put in padding.
+ * bits          Length of key in bits.
+ * heap          Used for dynamic memory allocation.
+ * returns 0 on success, PSS_SALTLEN_E when the salt length is invalid,
+ * BAD_PADDING_E when the padding is not valid, MEMORY_E when allocation fails
+ * and other negative values on error.
+ */
+static int RsaUnPad_PSS(byte *pkcsBlock, unsigned int pkcsBlockLen,
+                        byte **output, enum wc_HashType hType, int mgf,
+                        int saltLen, int bits, void* heap)
+{
+    int   ret;
+    byte* tmp;
+    int   hLen, i, maskLen;
+#ifdef WOLFSSL_SHA512
+    int orig_bits = bits;
+#endif
+#if defined(WOLFSSL_NO_MALLOC) && !defined(WOLFSSL_STATIC_MEMORY)
+    byte tmp_buf[RSA_MAX_SIZE/8];
+    tmp = tmp_buf;
+
+    if (pkcsBlockLen > RSA_MAX_SIZE/8) {
+        return MEMORY_E;
+    }
+#endif
+
+    hLen = wc_HashGetDigestSize(hType);
+    if (hLen < 0)
+        return hLen;
+    bits = (bits - 1) & 0x7;
+    if ((pkcsBlock[0] & (0xff << bits)) != 0) {
+        return BAD_PADDING_E;
+    }
+    if (bits == 0) {
+        pkcsBlock++;
+        pkcsBlockLen--;
+    }
+    maskLen = (int)pkcsBlockLen - 1 - hLen;
+    if (maskLen < 0) {
+        WOLFSSL_MSG("RsaUnPad_PSS: Hash too large");
+        return WC_KEY_SIZE_E;
+    }
+
+    if (saltLen == RSA_PSS_SALT_LEN_DEFAULT) {
+        saltLen = hLen;
+        #ifdef WOLFSSL_SHA512
+            /* See FIPS 186-4 section 5.5 item (e). */
+            if (orig_bits == 1024 && hLen == WC_SHA512_DIGEST_SIZE)
+                saltLen = RSA_PSS_SALT_MAX_SZ;
+        #endif
+    }
+#ifndef WOLFSSL_PSS_LONG_SALT
+    else if (saltLen > hLen)
+        return PSS_SALTLEN_E;
+#endif
+#ifndef WOLFSSL_PSS_SALT_LEN_DISCOVER
+    else if (saltLen < RSA_PSS_SALT_LEN_DEFAULT)
+        return PSS_SALTLEN_E;
+    if (maskLen < saltLen + 1) {
+        return PSS_SALTLEN_E;
+    }
+#else
+    else if (saltLen < RSA_PSS_SALT_LEN_DISCOVER)
+        return PSS_SALTLEN_E;
+    if (saltLen != RSA_PSS_SALT_LEN_DISCOVER && maskLen < saltLen + 1) {
+        return WC_KEY_SIZE_E;
+    }
+#endif
+
+    if (pkcsBlock[pkcsBlockLen - 1] != RSA_PSS_PAD_TERM) {
+        WOLFSSL_MSG("RsaUnPad_PSS: Padding Term Error");
+        return BAD_PADDING_E;
+    }
+
+#if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
+    tmp = (byte*)XMALLOC(maskLen, heap, DYNAMIC_TYPE_RSA_BUFFER);
+    if (tmp == NULL) {
+        return MEMORY_E;
+    }
+#endif
+
+    if ((ret = RsaMGF(mgf, pkcsBlock + maskLen, hLen, tmp, maskLen,
+                                                                  heap)) != 0) {
+        XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER);
+        return ret;
+    }
+
+    tmp[0] &= (1 << bits) - 1;
+    pkcsBlock[0] &= (1 << bits) - 1;
+#ifdef WOLFSSL_PSS_SALT_LEN_DISCOVER
+    if (saltLen == RSA_PSS_SALT_LEN_DISCOVER) {
+        for (i = 0; i < maskLen - 1; i++) {
+            if (tmp[i] != pkcsBlock[i]) {
+                break;
+            }
+        }
+        if (tmp[i] != (pkcsBlock[i] ^ 0x01)) {
+            XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER);
+            WOLFSSL_MSG("RsaUnPad_PSS: Padding Error Match");
+            return PSS_SALTLEN_RECOVER_E;
+        }
+        saltLen = maskLen - (i + 1);
+    }
+    else
+#endif
+    {
+        for (i = 0; i < maskLen - 1 - saltLen; i++) {
+            if (tmp[i] != pkcsBlock[i]) {
+                XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER);
+                WOLFSSL_MSG("RsaUnPad_PSS: Padding Error Match");
+                return PSS_SALTLEN_E;
+            }
+        }
+        if (tmp[i] != (pkcsBlock[i] ^ 0x01)) {
+            XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER);
+            WOLFSSL_MSG("RsaUnPad_PSS: Padding Error End");
+            return PSS_SALTLEN_E;
+        }
+    }
+    for (i++; i < maskLen; i++)
+        pkcsBlock[i] ^= tmp[i];
+
+#if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
+    XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER);
+#endif
+
+    *output = pkcsBlock + maskLen - saltLen;
+    return saltLen + hLen;
+}
+#endif
+
+/* UnPad plaintext, set start to *output, return length of plaintext,
+ * < 0 on error */
+static int RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen,
+                    byte **output, byte padValue)
+{
+    int    ret = BAD_FUNC_ARG;
+    word16 i;
+#ifndef WOLFSSL_RSA_VERIFY_ONLY
+    byte   invalid = 0;
+#endif
+
+    if (output == NULL || pkcsBlockLen == 0 || pkcsBlockLen > 0xFFFF) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (padValue == RSA_BLOCK_TYPE_1) {
+        /* First byte must be 0x00 and Second byte, block type, 0x01 */
+        if (pkcsBlock[0] != 0 || pkcsBlock[1] != RSA_BLOCK_TYPE_1) {
+            WOLFSSL_MSG("RsaUnPad error, invalid formatting");
+            return RSA_PAD_E;
+        }
+
+        /* check the padding until we find the separator */
+        for (i = 2; i < pkcsBlockLen && pkcsBlock[i++] == 0xFF; ) { }
+
+        /* Minimum of 11 bytes of pre-message data and must have separator. */
+        if (i < RSA_MIN_PAD_SZ || pkcsBlock[i-1] != 0) {
+            WOLFSSL_MSG("RsaUnPad error, bad formatting");
+            return RSA_PAD_E;
+        }
+
+        *output = (byte *)(pkcsBlock + i);
+        ret = pkcsBlockLen - i;
+    }
+#ifndef WOLFSSL_RSA_VERIFY_ONLY
+    else {
+        word16 j;
+        word16 pastSep = 0;
+
+        /* Decrypted with private key - unpad must be constant time. */
+        for (i = 0, j = 2; j < pkcsBlockLen; j++) {
+           /* Update i if not passed the separator and at separator. */
+            i |= (~pastSep) & ctMask16Eq(pkcsBlock[j], 0x00) & (j + 1);
+            pastSep |= ctMask16Eq(pkcsBlock[j], 0x00);
+        }
+
+        /* Minimum of 11 bytes of pre-message data - including leading 0x00. */
+        invalid |= ctMaskLT(i, RSA_MIN_PAD_SZ);
+        /* Must have seen separator. */
+        invalid |= ~pastSep;
+        /* First byte must be 0x00. */
+        invalid |= ctMaskNotEq(pkcsBlock[0], 0x00);
+        /* Check against expected block type: padValue */
+        invalid |= ctMaskNotEq(pkcsBlock[1], padValue);
+
+        *output = (byte *)(pkcsBlock + i);
+        ret = ((int)~invalid) & (pkcsBlockLen - i);
+    }
+#endif
+
+    return ret;
+}
+
+/* helper function to direct unpadding
+ *
+ * bits is the key modulus size in bits
+ */
+int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** out,
+                   byte padValue, int padType, enum wc_HashType hType,
+                   int mgf, byte* optLabel, word32 labelLen, int saltLen,
+                   int bits, void* heap)
+{
+    int ret;
+
+    switch (padType) {
+        case WC_RSA_PKCSV15_PAD:
+            /*WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 un-padding");*/
+            ret = RsaUnPad(pkcsBlock, pkcsBlockLen, out, padValue);
+            break;
+
+    #ifndef WC_NO_RSA_OAEP
+        case WC_RSA_OAEP_PAD:
+            WOLFSSL_MSG("wolfSSL Using RSA OAEP un-padding");
+            ret = RsaUnPad_OAEP((byte*)pkcsBlock, pkcsBlockLen, out,
+                                        hType, mgf, optLabel, labelLen, heap);
+            break;
+    #endif
+
+    #ifdef WC_RSA_PSS
+        case WC_RSA_PSS_PAD:
+            WOLFSSL_MSG("wolfSSL Using RSA PSS un-padding");
+            ret = RsaUnPad_PSS((byte*)pkcsBlock, pkcsBlockLen, out, hType, mgf,
+                                                           saltLen, bits, heap);
+            break;
+    #endif
+
+    #ifdef WC_RSA_NO_PADDING
+        case WC_RSA_NO_PAD:
+            WOLFSSL_MSG("wolfSSL Using NO un-padding");
+
+            /* In the case of no padding being used check that input is exactly
+             * the RSA key length */
+            if (bits <= 0 || pkcsBlockLen !=
+                         ((word32)(bits+WOLFSSL_BIT_SIZE-1)/WOLFSSL_BIT_SIZE)) {
+                WOLFSSL_MSG("Bad input size");
+                ret = RSA_PAD_E;
+            }
+            else {
+                if (out != NULL) {
+                    *out = pkcsBlock;
+                }
+                ret = pkcsBlockLen;
+            }
+            break;
+    #endif /* WC_RSA_NO_PADDING */
+
+        default:
+            WOLFSSL_MSG("Unknown RSA UnPad Type");
+            ret = RSA_PAD_E;
+    }
+
+    /* silence warning if not used with padding scheme */
+    (void)hType;
+    (void)mgf;
+    (void)optLabel;
+    (void)labelLen;
+    (void)saltLen;
+    (void)bits;
+    (void)heap;
+
+    return ret;
+}
+
+#if defined(WOLFSSL_XILINX_CRYPT)
+/*
+ * Xilinx hardened crypto acceleration.
+ *
+ * Returns 0 on success and negative values on error.
+ */
+static int wc_RsaFunctionXil(const byte* in, word32 inLen, byte* out,
+                          word32* outLen, int type, RsaKey* key, WC_RNG* rng)
+{
+    int    ret = 0;
+    word32 keyLen;
+    (void)rng;
+
+    keyLen = wc_RsaEncryptSize(key);
+    if (keyLen > *outLen) {
+        WOLFSSL_MSG("Output buffer is not big enough");
+        return BAD_FUNC_ARG;
+    }
+
+    if (inLen != keyLen) {
+        WOLFSSL_MSG("Expected that inLen equals RSA key length");
+        return BAD_FUNC_ARG;
+    }
+
+    switch(type) {
+    case RSA_PRIVATE_DECRYPT:
+    case RSA_PRIVATE_ENCRYPT:
+        /* Currently public exponent is loaded by default.
+         * In SDK 2017.1 RSA exponent values are expected to be of 4 bytes
+         * leading to private key operations with Xsecure_RsaDecrypt not being
+         * supported */
+        ret = RSA_WRONG_TYPE_E;
+        break;
+    case RSA_PUBLIC_ENCRYPT:
+    case RSA_PUBLIC_DECRYPT:
+        if (XSecure_RsaDecrypt(&(key->xRsa), in, out) != XST_SUCCESS) {
+            ret = BAD_STATE_E;
+        }
+        break;
+    default:
+        ret = RSA_WRONG_TYPE_E;
+    }
+
+    *outLen = keyLen;
+
+    return ret;
+}
+#endif /* WOLFSSL_XILINX_CRYPT */
+
+#ifdef WC_RSA_NONBLOCK
+static int wc_RsaFunctionNonBlock(const byte* in, word32 inLen, byte* out,
+                          word32* outLen, int type, RsaKey* key)
+{
+    int    ret = 0;
+    word32 keyLen, len;
+
+    if (key == NULL || key->nb == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (key->nb->exptmod.state == TFM_EXPTMOD_NB_INIT) {
+        if (mp_init(&key->nb->tmp) != MP_OKAY) {
+            ret = MP_INIT_E;
+        }
+
+        if (ret == 0) {
+            if (mp_read_unsigned_bin(&key->nb->tmp, (byte*)in, inLen) != MP_OKAY) {
+                ret = MP_READ_E;
+            }
+        }
+    }
+
+    if (ret == 0) {
+        switch(type) {
+        case RSA_PRIVATE_DECRYPT:
+        case RSA_PRIVATE_ENCRYPT:
+            ret = fp_exptmod_nb(&key->nb->exptmod, &key->nb->tmp, &key->d,
+                &key->n, &key->nb->tmp);
+            if (ret == FP_WOULDBLOCK)
+                return ret;
+            if (ret != MP_OKAY)
+                ret = MP_EXPTMOD_E;
+            break;
+
+        case RSA_PUBLIC_ENCRYPT:
+        case RSA_PUBLIC_DECRYPT:
+            ret = fp_exptmod_nb(&key->nb->exptmod, &key->nb->tmp, &key->e,
+                &key->n, &key->nb->tmp);
+            if (ret == FP_WOULDBLOCK)
+                return ret;
+            if (ret != MP_OKAY)
+                ret = MP_EXPTMOD_E;
+            break;
+        default:
+            ret = RSA_WRONG_TYPE_E;
+            break;
+        }
+    }
+
+    if (ret == 0) {
+        keyLen = wc_RsaEncryptSize(key);
+        if (keyLen > *outLen)
+            ret = RSA_BUFFER_E;
+    }
+    if (ret == 0) {
+        len = mp_unsigned_bin_size(&key->nb->tmp);
+
+        /* pad front w/ zeros to match key length */
+        while (len < keyLen) {
+            *out++ = 0x00;
+            len++;
+        }
+
+        *outLen = keyLen;
+
+        /* convert */
+        if (mp_to_unsigned_bin(&key->nb->tmp, out) != MP_OKAY) {
+             ret = MP_TO_E;
+        }
+    }
+
+    mp_clear(&key->nb->tmp);
+
+    return ret;
+}
+#endif /* WC_RSA_NONBLOCK */
+
+#ifdef WOLFSSL_AFALG_XILINX_RSA
+#ifndef ERROR_OUT
+#define ERROR_OUT(x) ret = (x); goto done
+#endif
+
+static const char WC_TYPE_ASYMKEY[] = "skcipher";
+static const char WC_NAME_RSA[] = "xilinx-zynqmp-rsa";
+#ifndef MAX_XILINX_RSA_KEY
+    /* max key size of 4096 bits / 512 bytes */
+    #define MAX_XILINX_RSA_KEY 512
+#endif
+static const byte XILINX_RSA_FLAG[] = {0x1};
+
+
+/* AF_ALG implementation of RSA */
+static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out,
+                          word32* outLen, int type, RsaKey* key, WC_RNG* rng)
+{
+    struct msghdr   msg;
+    struct cmsghdr* cmsg;
+    struct iovec      iov;
+    byte*  keyBuf   = NULL;
+    word32 keyBufSz = 0;
+    char cbuf[CMSG_SPACE(4) + CMSG_SPACE(sizeof(struct af_alg_iv) + 1)] = {0};
+    int    ret = 0;
+    int    op  = 0;    /* decryption vs encryption flag */
+    word32 keyLen;
+
+    /* input and output buffer need to be aligned */
+    ALIGN64 byte outBuf[MAX_XILINX_RSA_KEY];
+    ALIGN64 byte inBuf[MAX_XILINX_RSA_KEY];
+
+    XMEMSET(&msg, 0, sizeof(struct msghdr));
+    (void)rng;
+
+    keyLen = wc_RsaEncryptSize(key);
+    if (keyLen > *outLen) {
+        ERROR_OUT(RSA_BUFFER_E);
+    }
+
+    if (keyLen > MAX_XILINX_RSA_KEY) {
+        WOLFSSL_MSG("RSA key size larger than supported");
+        ERROR_OUT(BAD_FUNC_ARG);
+    }
+
+    if ((keyBuf = (byte*)XMALLOC(keyLen * 2, key->heap, DYNAMIC_TYPE_KEY))
+            == NULL) {
+        ERROR_OUT(MEMORY_E);
+    }
+
+    if ((ret = mp_to_unsigned_bin(&(key->n), keyBuf)) != MP_OKAY) {
+        ERROR_OUT(MP_TO_E);
+    }
+
+    switch(type) {
+        case RSA_PRIVATE_DECRYPT:
+        case RSA_PRIVATE_ENCRYPT:
+            op = 1; /* set as decrypt */
+            {
+                keyBufSz = mp_unsigned_bin_size(&(key->d));
+                if ((mp_to_unsigned_bin(&(key->d), keyBuf + keyLen))
+                        != MP_OKAY) {
+                    ERROR_OUT(MP_TO_E);
+                }
+            }
+            break;
+
+        case RSA_PUBLIC_DECRYPT:
+        case RSA_PUBLIC_ENCRYPT: {
+            word32 exp = 0;
+            word32 eSz = mp_unsigned_bin_size(&(key->e));
+            if ((mp_to_unsigned_bin(&(key->e), (byte*)&exp +
+                            (sizeof(word32) - eSz))) != MP_OKAY) {
+                ERROR_OUT(MP_TO_E);
+            }
+            keyBufSz = sizeof(word32);
+            XMEMCPY(keyBuf + keyLen, (byte*)&exp, keyBufSz);
+            break;
+        }
+
+        default:
+            ERROR_OUT(RSA_WRONG_TYPE_E);
+    }
+    keyBufSz += keyLen; /* add size of modulus */
+
+    /* check for existing sockets before creating new ones */
+    if (key->alFd > 0) {
+        close(key->alFd);
+        key->alFd = WC_SOCK_NOTSET;
+    }
+    if (key->rdFd > 0) {
+        close(key->rdFd);
+        key->rdFd = WC_SOCK_NOTSET;
+    }
+
+    /* create new sockets and set the key to use */
+    if ((key->alFd = wc_Afalg_Socket()) < 0) {
+        WOLFSSL_MSG("Unable to create socket");
+        ERROR_OUT(key->alFd);
+    }
+    if ((key->rdFd = wc_Afalg_CreateRead(key->alFd, WC_TYPE_ASYMKEY,
+                    WC_NAME_RSA)) < 0) {
+        WOLFSSL_MSG("Unable to bind and create read/send socket");
+        ERROR_OUT(key->rdFd);
+    }
+    if ((ret = setsockopt(key->alFd, SOL_ALG, ALG_SET_KEY, keyBuf,
+                    keyBufSz)) < 0) {
+        WOLFSSL_MSG("Error setting RSA key");
+        ERROR_OUT(ret);
+    }
+
+    msg.msg_control    = cbuf;
+    msg.msg_controllen = sizeof(cbuf);
+    cmsg = CMSG_FIRSTHDR(&msg);
+    if ((ret = wc_Afalg_SetOp(cmsg, op)) < 0) {
+        ERROR_OUT(ret);
+    }
+
+    /* set flag in IV spot, needed for Xilinx hardware acceleration use */
+    cmsg = CMSG_NXTHDR(&msg, cmsg);
+    if ((ret = wc_Afalg_SetIv(cmsg, (byte*)XILINX_RSA_FLAG,
+                    sizeof(XILINX_RSA_FLAG))) != 0) {
+        ERROR_OUT(ret);
+    }
+
+    /* compose and send msg */
+    XMEMCPY(inBuf, (byte*)in, inLen); /* for alignment */
+    iov.iov_base = inBuf;
+    iov.iov_len  = inLen;
+    msg.msg_iov  = &iov;
+    msg.msg_iovlen = 1;
+    if ((ret = sendmsg(key->rdFd, &msg, 0)) <= 0) {
+        ERROR_OUT(WC_AFALG_SOCK_E);
+    }
+
+    if ((ret = read(key->rdFd, outBuf, inLen)) <= 0) {
+        ERROR_OUT(WC_AFALG_SOCK_E);
+    }
+    XMEMCPY(out, outBuf, ret);
+    *outLen = keyLen;
+
+done:
+    /* clear key data and free buffer */
+    if (keyBuf != NULL) {
+        ForceZero(keyBuf, keyBufSz);
+    }
+    XFREE(keyBuf, key->heap, DYNAMIC_TYPE_KEY);
+
+    if (key->alFd > 0) {
+        close(key->alFd);
+        key->alFd = WC_SOCK_NOTSET;
+    }
+    if (key->rdFd > 0) {
+        close(key->rdFd);
+        key->rdFd = WC_SOCK_NOTSET;
+    }
+
+    return ret;
+}
+
+#else
+static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out,
+                          word32* outLen, int type, RsaKey* key, WC_RNG* rng)
+{
+#ifndef WOLFSSL_SP_MATH
+#ifdef WOLFSSL_SMALL_STACK
+    mp_int* tmp;
+#ifdef WC_RSA_BLINDING
+    mp_int* rnd;
+    mp_int* rndi;
+#endif
+#else
+    mp_int tmp[1];
+#ifdef WC_RSA_BLINDING
+    mp_int rnd[1], rndi[1];
+#endif
+#endif
+    int    ret = 0;
+    word32 keyLen = 0;
+#endif
+
+#ifdef WOLFSSL_HAVE_SP_RSA
+#ifndef WOLFSSL_SP_NO_2048
+    if (mp_count_bits(&key->n) == 2048) {
+        switch(type) {
+#ifndef WOLFSSL_RSA_PUBLIC_ONLY
+        case RSA_PRIVATE_DECRYPT:
+        case RSA_PRIVATE_ENCRYPT:
+    #ifdef WC_RSA_BLINDING
+            if (rng == NULL)
+                return MISSING_RNG_E;
+    #endif
+    #ifndef RSA_LOW_MEM
+            return sp_RsaPrivate_2048(in, inLen, &key->d, &key->p, &key->q,
+                                      &key->dP, &key->dQ, &key->u, &key->n,
+                                      out, outLen);
+    #else
+            return sp_RsaPrivate_2048(in, inLen, &key->d, &key->p, &key->q,
+                                      NULL, NULL, NULL, &key->n, out, outLen);
+    #endif
+#endif
+        case RSA_PUBLIC_ENCRYPT:
+        case RSA_PUBLIC_DECRYPT:
+            return sp_RsaPublic_2048(in, inLen, &key->e, &key->n, out, outLen);
+        }
+    }
+#endif
+#ifndef WOLFSSL_SP_NO_3072
+    if (mp_count_bits(&key->n) == 3072) {
+        switch(type) {
+#ifndef WOLFSSL_RSA_PUBLIC_ONLY
+        case RSA_PRIVATE_DECRYPT:
+        case RSA_PRIVATE_ENCRYPT:
+    #ifdef WC_RSA_BLINDING
+            if (rng == NULL)
+                return MISSING_RNG_E;
+    #endif
+    #ifndef RSA_LOW_MEM
+            return sp_RsaPrivate_3072(in, inLen, &key->d, &key->p, &key->q,
+                                      &key->dP, &key->dQ, &key->u, &key->n,
+                                      out, outLen);
+    #else
+            return sp_RsaPrivate_3072(in, inLen, &key->d, &key->p, &key->q,
+                                      NULL, NULL, NULL, &key->n, out, outLen);
+    #endif
+#endif
+        case RSA_PUBLIC_ENCRYPT:
+        case RSA_PUBLIC_DECRYPT:
+            return sp_RsaPublic_3072(in, inLen, &key->e, &key->n, out, outLen);
+        }
+    }
+#endif
+#ifdef WOLFSSL_SP_4096
+    if (mp_count_bits(&key->n) == 4096) {
+        switch(type) {
+#ifndef WOLFSSL_RSA_PUBLIC_ONLY
+        case RSA_PRIVATE_DECRYPT:
+        case RSA_PRIVATE_ENCRYPT:
+    #ifdef WC_RSA_BLINDING
+            if (rng == NULL)
+                return MISSING_RNG_E;
+    #endif
+    #ifndef RSA_LOW_MEM
+            return sp_RsaPrivate_4096(in, inLen, &key->d, &key->p, &key->q,
+                                      &key->dP, &key->dQ, &key->u, &key->n,
+                                      out, outLen);
+    #else
+            return sp_RsaPrivate_4096(in, inLen, &key->d, &key->p, &key->q,
+                                      NULL, NULL, NULL, &key->n, out, outLen);
+    #endif
+#endif
+        case RSA_PUBLIC_ENCRYPT:
+        case RSA_PUBLIC_DECRYPT:
+            return sp_RsaPublic_4096(in, inLen, &key->e, &key->n, out, outLen);
+        }
+    }
+#endif
+#endif /* WOLFSSL_HAVE_SP_RSA */
+
+#ifdef WOLFSSL_SP_MATH
+    (void)rng;
+    WOLFSSL_MSG("SP Key Size Error");
+    return WC_KEY_SIZE_E;
+#else
+    (void)rng;
+
+#ifdef WOLFSSL_SMALL_STACK
+    tmp = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_RSA);
+    if (tmp == NULL)
+        return MEMORY_E;
+#ifdef WC_RSA_BLINDING
+    rnd = (mp_int*)XMALLOC(sizeof(mp_int) * 2, key->heap, DYNAMIC_TYPE_RSA);
+    if (rnd == NULL) {
+        XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
+        return MEMORY_E;
+    }
+    rndi = rnd + 1;
+#endif /* WC_RSA_BLINDING */
+#endif /* WOLFSSL_SMALL_STACK */
+
+    if (mp_init(tmp) != MP_OKAY)
+        ret = MP_INIT_E;
+
+#ifdef WC_RSA_BLINDING
+    if (ret == 0) {
+        if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) {
+            if (mp_init_multi(rnd, rndi, NULL, NULL, NULL, NULL) != MP_OKAY) {
+                mp_clear(tmp);
+                ret = MP_INIT_E;
+            }
+        }
+    }
+#endif
+
+#ifndef TEST_UNPAD_CONSTANT_TIME
+    if (ret == 0 && mp_read_unsigned_bin(tmp, (byte*)in, inLen) != MP_OKAY)
+        ret = MP_READ_E;
+
+    if (ret == 0) {
+        switch(type) {
+    #ifndef WOLFSSL_RSA_PUBLIC_ONLY
+        case RSA_PRIVATE_DECRYPT:
+        case RSA_PRIVATE_ENCRYPT:
+        {
+        #if defined(WC_RSA_BLINDING) && !defined(WC_NO_RNG)
+            /* blind */
+            ret = mp_rand(rnd, get_digit_count(&key->n), rng);
+
+            /* rndi = 1/rnd mod n */
+            if (ret == 0 && mp_invmod(rnd, &key->n, rndi) != MP_OKAY)
+                ret = MP_INVMOD_E;
+
+            /* rnd = rnd^e */
+            if (ret == 0 && mp_exptmod(rnd, &key->e, &key->n, rnd) != MP_OKAY)
+                ret = MP_EXPTMOD_E;
+
+            /* tmp = tmp*rnd mod n */
+            if (ret == 0 && mp_mulmod(tmp, rnd, &key->n, tmp) != MP_OKAY)
+                ret = MP_MULMOD_E;
+        #endif /* WC_RSA_BLINDING && !WC_NO_RNG */
+
+        #ifdef RSA_LOW_MEM      /* half as much memory but twice as slow */
+            if (ret == 0 && mp_exptmod(tmp, &key->d, &key->n, tmp) != MP_OKAY)
+                ret = MP_EXPTMOD_E;
+        #else
+            if (ret == 0) {
+            #ifdef WOLFSSL_SMALL_STACK
+                mp_int* tmpa;
+                mp_int* tmpb = NULL;
+            #else
+                mp_int tmpa[1], tmpb[1];
+            #endif
+                int cleara = 0, clearb = 0;
+
+            #ifdef WOLFSSL_SMALL_STACK
+                tmpa = (mp_int*)XMALLOC(sizeof(mp_int) * 2,
+                        key->heap, DYNAMIC_TYPE_RSA);
+                if (tmpa != NULL)
+                    tmpb = tmpa + 1;
+                else
+                    ret = MEMORY_E;
+            #endif
+
+                if (ret == 0) {
+                    if (mp_init(tmpa) != MP_OKAY)
+                        ret = MP_INIT_E;
+                    else
+                        cleara = 1;
+                }
+
+                if (ret == 0) {
+                    if (mp_init(tmpb) != MP_OKAY)
+                        ret = MP_INIT_E;
+                    else
+                        clearb = 1;
+                }
+
+                /* tmpa = tmp^dP mod p */
+                if (ret == 0 && mp_exptmod(tmp, &key->dP, &key->p,
+                                                               tmpa) != MP_OKAY)
+                    ret = MP_EXPTMOD_E;
+
+                /* tmpb = tmp^dQ mod q */
+                if (ret == 0 && mp_exptmod(tmp, &key->dQ, &key->q,
+                                                               tmpb) != MP_OKAY)
+                    ret = MP_EXPTMOD_E;
+
+                /* tmp = (tmpa - tmpb) * qInv (mod p) */
+                if (ret == 0 && mp_sub(tmpa, tmpb, tmp) != MP_OKAY)
+                    ret = MP_SUB_E;
+
+                if (ret == 0 && mp_mulmod(tmp, &key->u, &key->p,
+                                                                tmp) != MP_OKAY)
+                    ret = MP_MULMOD_E;
+
+                /* tmp = tmpb + q * tmp */
+                if (ret == 0 && mp_mul(tmp, &key->q, tmp) != MP_OKAY)
+                    ret = MP_MUL_E;
+
+                if (ret == 0 && mp_add(tmp, tmpb, tmp) != MP_OKAY)
+                    ret = MP_ADD_E;
+
+            #ifdef WOLFSSL_SMALL_STACK
+                if (tmpa != NULL)
+            #endif
+                {
+                    if (cleara)
+                        mp_clear(tmpa);
+                    if (clearb)
+                        mp_clear(tmpb);
+            #ifdef WOLFSSL_SMALL_STACK
+                    XFREE(tmpa, key->heap, DYNAMIC_TYPE_RSA);
+            #endif
+                }
+            } /* tmpa/b scope */
+        #endif   /* RSA_LOW_MEM */
+
+        #ifdef WC_RSA_BLINDING
+            /* unblind */
+            if (ret == 0 && mp_mulmod(tmp, rndi, &key->n, tmp) != MP_OKAY)
+                ret = MP_MULMOD_E;
+        #endif   /* WC_RSA_BLINDING */
+
+            break;
+        }
+    #endif
+        case RSA_PUBLIC_ENCRYPT:
+        case RSA_PUBLIC_DECRYPT:
+        #ifdef WOLFSSL_XILINX_CRYPT
+            ret = wc_RsaFunctionXil(in, inLen, out, outLen, type, key, rng);
+        #else
+            if (mp_exptmod_nct(tmp, &key->e, &key->n, tmp) != MP_OKAY)
+                ret = MP_EXPTMOD_E;
+        #endif
+            break;
+        default:
+            ret = RSA_WRONG_TYPE_E;
+            break;
+        }
+    }
+
+    if (ret == 0) {
+        keyLen = wc_RsaEncryptSize(key);
+        if (keyLen > *outLen)
+            ret = RSA_BUFFER_E;
+    }
+    if (ret == 0) {
+        *outLen = keyLen;
+        if (mp_to_unsigned_bin_len(tmp, out, keyLen) != MP_OKAY)
+             ret = MP_TO_E;
+    }
+#else
+    (void)type;
+    (void)key;
+    (void)keyLen;
+    XMEMCPY(out, in, inLen);
+    *outLen = inLen;
+#endif
+
+    mp_clear(tmp);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
+#endif
+#ifdef WC_RSA_BLINDING
+    if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) {
+        mp_clear(rndi);
+        mp_clear(rnd);
+    }
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(rnd, key->heap, DYNAMIC_TYPE_RSA);
+#endif
+#endif /* WC_RSA_BLINDING */
+    return ret;
+#endif /* WOLFSSL_SP_MATH */
+}
+#endif
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA)
+static int wc_RsaFunctionAsync(const byte* in, word32 inLen, byte* out,
+                          word32* outLen, int type, RsaKey* key, WC_RNG* rng)
+{
+    int ret = 0;
+
+    (void)rng;
+
+#ifdef WOLFSSL_ASYNC_CRYPT_TEST
+    if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_RSA_FUNC)) {
+        WC_ASYNC_TEST* testDev = &key->asyncDev.test;
+        testDev->rsaFunc.in = in;
+        testDev->rsaFunc.inSz = inLen;
+        testDev->rsaFunc.out = out;
+        testDev->rsaFunc.outSz = outLen;
+        testDev->rsaFunc.type = type;
+        testDev->rsaFunc.key = key;
+        testDev->rsaFunc.rng = rng;
+        return WC_PENDING_E;
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT_TEST */
+
+    switch(type) {
+#ifndef WOLFSSL_RSA_PUBLIC_ONLY
+    case RSA_PRIVATE_DECRYPT:
+    case RSA_PRIVATE_ENCRYPT:
+    #ifdef HAVE_CAVIUM
+        key->dataLen = key->n.raw.len;
+        ret = NitroxRsaExptMod(in, inLen,
+                               key->d.raw.buf, key->d.raw.len,
+                               key->n.raw.buf, key->n.raw.len,
+                               out, outLen, key);
+    #elif defined(HAVE_INTEL_QA)
+        #ifdef RSA_LOW_MEM
+            ret = IntelQaRsaPrivate(&key->asyncDev, in, inLen,
+                                    &key->d.raw, &key->n.raw,
+                                    out, outLen);
+        #else
+            ret = IntelQaRsaCrtPrivate(&key->asyncDev, in, inLen,
+                                &key->p.raw, &key->q.raw,
+                                &key->dP.raw, &key->dQ.raw,
+                                &key->u.raw,
+                                out, outLen);
+        #endif
+    #else /* WOLFSSL_ASYNC_CRYPT_TEST */
+        ret = wc_RsaFunctionSync(in, inLen, out, outLen, type, key, rng);
+    #endif
+        break;
+#endif
+
+    case RSA_PUBLIC_ENCRYPT:
+    case RSA_PUBLIC_DECRYPT:
+    #ifdef HAVE_CAVIUM
+        key->dataLen = key->n.raw.len;
+        ret = NitroxRsaExptMod(in, inLen,
+                               key->e.raw.buf, key->e.raw.len,
+                               key->n.raw.buf, key->n.raw.len,
+                               out, outLen, key);
+    #elif defined(HAVE_INTEL_QA)
+        ret = IntelQaRsaPublic(&key->asyncDev, in, inLen,
+                               &key->e.raw, &key->n.raw,
+                               out, outLen);
+    #else /* WOLFSSL_ASYNC_CRYPT_TEST */
+        ret = wc_RsaFunctionSync(in, inLen, out, outLen, type, key, rng);
+    #endif
+        break;
+
+    default:
+        ret = RSA_WRONG_TYPE_E;
+    }
+
+    return ret;
+}
+#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_RSA */
+
+#if defined(WC_RSA_DIRECT) || defined(WC_RSA_NO_PADDING)
+/* Function that does the RSA operation directly with no padding.
+ *
+ * in       buffer to do operation on
+ * inLen    length of input buffer
+ * out      buffer to hold results
+ * outSz    gets set to size of result buffer. Should be passed in as length
+ *          of out buffer. If the pointer "out" is null then outSz gets set to
+ *          the expected buffer size needed and LENGTH_ONLY_E gets returned.
+ * key      RSA key to use for encrypt/decrypt
+ * type     if using private or public key {RSA_PUBLIC_ENCRYPT,
+ *          RSA_PUBLIC_DECRYPT, RSA_PRIVATE_ENCRYPT, RSA_PRIVATE_DECRYPT}
+ * rng      wolfSSL RNG to use if needed
+ *
+ * returns size of result on success
+ */
+int wc_RsaDirect(byte* in, word32 inLen, byte* out, word32* outSz,
+        RsaKey* key, int type, WC_RNG* rng)
+{
+    int ret;
+
+    if (in == NULL || outSz == NULL || key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* sanity check on type of RSA operation */
+    switch (type) {
+        case RSA_PUBLIC_ENCRYPT:
+        case RSA_PUBLIC_DECRYPT:
+        case RSA_PRIVATE_ENCRYPT:
+        case RSA_PRIVATE_DECRYPT:
+            break;
+        default:
+            WOLFSSL_MSG("Bad RSA type");
+            return BAD_FUNC_ARG;
+    }
+
+    if ((ret = wc_RsaEncryptSize(key)) < 0) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (inLen != (word32)ret) {
+        WOLFSSL_MSG("Bad input length. Should be RSA key size");
+        return BAD_FUNC_ARG;
+    }
+
+    if (out == NULL) {
+        *outSz = inLen;
+        return LENGTH_ONLY_E;
+    }
+
+    switch (key->state) {
+        case RSA_STATE_NONE:
+        case RSA_STATE_ENCRYPT_PAD:
+        case RSA_STATE_ENCRYPT_EXPTMOD:
+        case RSA_STATE_DECRYPT_EXPTMOD:
+        case RSA_STATE_DECRYPT_UNPAD:
+            key->state = (type == RSA_PRIVATE_ENCRYPT ||
+                    type == RSA_PUBLIC_ENCRYPT) ? RSA_STATE_ENCRYPT_EXPTMOD:
+                                                  RSA_STATE_DECRYPT_EXPTMOD;
+
+            key->dataLen = *outSz;
+
+            ret = wc_RsaFunction(in, inLen, out, &key->dataLen, type, key, rng);
+            if (ret >= 0 || ret == WC_PENDING_E) {
+                key->state = (type == RSA_PRIVATE_ENCRYPT ||
+                    type == RSA_PUBLIC_ENCRYPT) ? RSA_STATE_ENCRYPT_RES:
+                                                  RSA_STATE_DECRYPT_RES;
+            }
+            if (ret < 0) {
+                break;
+            }
+
+            FALL_THROUGH;
+
+        case RSA_STATE_ENCRYPT_RES:
+        case RSA_STATE_DECRYPT_RES:
+            ret = key->dataLen;
+            break;
+
+        default:
+            ret = BAD_STATE_E;
+    }
+
+    /* if async pending then skip cleanup*/
+    if (ret == WC_PENDING_E
+    #ifdef WC_RSA_NONBLOCK
+        || ret == FP_WOULDBLOCK
+    #endif
+    ) {
+        return ret;
+    }
+
+    key->state = RSA_STATE_NONE;
+    wc_RsaCleanup(key);
+
+    return ret;
+}
+#endif /* WC_RSA_DIRECT || WC_RSA_NO_PADDING */
+
+#if defined(WOLFSSL_CRYPTOCELL)
+static int cc310_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out,
+                            word32 outLen, RsaKey* key)
+{
+    CRYSError_t ret = 0;
+    CRYS_RSAPrimeData_t primeData;
+    int modulusSize = wc_RsaEncryptSize(key);
+
+    /* The out buffer must be at least modulus size bytes long. */
+    if (outLen < modulusSize)
+        return BAD_FUNC_ARG;
+
+    ret = CRYS_RSA_PKCS1v15_Encrypt(&wc_rndState,
+                                    wc_rndGenVectFunc,
+                                    &key->ctx.pubKey,
+                                    &primeData,
+                                    (byte*)in,
+                                    inLen,
+                                    out);
+
+    if (ret != SA_SILIB_RET_OK){
+        WOLFSSL_MSG("CRYS_RSA_PKCS1v15_Encrypt failed");
+        return -1;
+    }
+
+    return modulusSize;
+}
+static int cc310_RsaPublicDecrypt(const byte* in, word32 inLen, byte* out,
+                            word32 outLen, RsaKey* key)
+{
+    CRYSError_t ret = 0;
+    CRYS_RSAPrimeData_t primeData;
+    uint16_t actualOutLen = outLen;
+
+    ret = CRYS_RSA_PKCS1v15_Decrypt(&key->ctx.privKey,
+                                    &primeData,
+                                    (byte*)in,
+                                    inLen,
+                                    out,
+                                    &actualOutLen);
+
+    if (ret != SA_SILIB_RET_OK){
+        WOLFSSL_MSG("CRYS_RSA_PKCS1v15_Decrypt failed");
+        return -1;
+    }
+    return actualOutLen;
+}
+
+int cc310_RsaSSL_Sign(const byte* in, word32 inLen, byte* out,
+                  word32 outLen, RsaKey* key, CRYS_RSA_HASH_OpMode_t mode)
+{
+    CRYSError_t ret = 0;
+    uint16_t actualOutLen = outLen*sizeof(byte);
+    CRYS_RSAPrivUserContext_t  contextPrivate;
+
+    ret =  CRYS_RSA_PKCS1v15_Sign(&wc_rndState,
+                wc_rndGenVectFunc,
+                &contextPrivate,
+                &key->ctx.privKey,
+                mode,
+                (byte*)in,
+                inLen,
+                out,
+                &actualOutLen);
+
+    if (ret != SA_SILIB_RET_OK){
+        WOLFSSL_MSG("CRYS_RSA_PKCS1v15_Sign failed");
+        return -1;
+    }
+    return actualOutLen;
+}
+
+int cc310_RsaSSL_Verify(const byte* in, word32 inLen, byte* sig,
+                               RsaKey* key, CRYS_RSA_HASH_OpMode_t mode)
+{
+    CRYSError_t ret = 0;
+    CRYS_RSAPubUserContext_t contextPub;
+
+    /* verify the signature in the sig pointer */
+    ret =  CRYS_RSA_PKCS1v15_Verify(&contextPub,
+                &key->ctx.pubKey,
+                mode,
+                (byte*)in,
+                inLen,
+                sig);
+
+    if (ret != SA_SILIB_RET_OK){
+        WOLFSSL_MSG("CRYS_RSA_PKCS1v15_Verify failed");
+        return -1;
+    }
+
+    return ret;
+}
+#endif /* WOLFSSL_CRYPTOCELL */
+
+int wc_RsaFunction(const byte* in, word32 inLen, byte* out,
+                          word32* outLen, int type, RsaKey* key, WC_RNG* rng)
+{
+    int ret = 0;
+
+    if (key == NULL || in == NULL || inLen == 0 || out == NULL ||
+            outLen == NULL || *outLen == 0 || type == RSA_TYPE_UNKNOWN) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef WOLF_CRYPTO_CB
+    if (key->devId != INVALID_DEVID) {
+        ret = wc_CryptoCb_Rsa(in, inLen, out, outLen, type, key, rng);
+        if (ret != CRYPTOCB_UNAVAILABLE)
+            return ret;
+        /* fall-through when unavailable */
+        ret = 0; /* reset error code and try using software */
+    }
+#endif
+
+#ifndef TEST_UNPAD_CONSTANT_TIME
+#ifndef NO_RSA_BOUNDS_CHECK
+    if (type == RSA_PRIVATE_DECRYPT &&
+        key->state == RSA_STATE_DECRYPT_EXPTMOD) {
+
+        /* Check that 1 < in < n-1. (Requirement of 800-56B.) */
+#ifdef WOLFSSL_SMALL_STACK
+        mp_int* c;
+#else
+        mp_int c[1];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+        c = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_RSA);
+        if (c == NULL)
+            ret = MEMORY_E;
+#endif
+
+        if (mp_init(c) != MP_OKAY)
+            ret = MEMORY_E;
+        if (ret == 0) {
+            if (mp_read_unsigned_bin(c, in, inLen) != 0)
+                ret = MP_READ_E;
+        }
+        if (ret == 0) {
+            /* check c > 1 */
+            if (mp_cmp_d(c, 1) != MP_GT)
+                ret = RSA_OUT_OF_RANGE_E;
+        }
+        if (ret == 0) {
+            /* add c+1 */
+            if (mp_add_d(c, 1, c) != MP_OKAY)
+                ret = MP_ADD_E;
+        }
+        if (ret == 0) {
+            /* check c+1 < n */
+            if (mp_cmp(c, &key->n) != MP_LT)
+                ret = RSA_OUT_OF_RANGE_E;
+        }
+        mp_clear(c);
+
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(c, key->heap, DYNAMIC_TYPE_RSA);
+#endif
+
+        if (ret != 0)
+            return ret;
+    }
+#endif /* NO_RSA_BOUNDS_CHECK */
+#endif
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA)
+    if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA &&
+                                                        key->n.raw.len > 0) {
+        ret = wc_RsaFunctionAsync(in, inLen, out, outLen, type, key, rng);
+    }
+    else
+#endif
+#ifdef WC_RSA_NONBLOCK
+    if (key->nb) {
+        ret = wc_RsaFunctionNonBlock(in, inLen, out, outLen, type, key);
+    }
+    else
+#endif
+    {
+        ret = wc_RsaFunctionSync(in, inLen, out, outLen, type, key, rng);
+    }
+
+    /* handle error */
+    if (ret < 0 && ret != WC_PENDING_E
+    #ifdef WC_RSA_NONBLOCK
+        && ret != FP_WOULDBLOCK
+    #endif
+    ) {
+        if (ret == MP_EXPTMOD_E) {
+            /* This can happen due to incorrectly set FP_MAX_BITS or missing XREALLOC */
+            WOLFSSL_MSG("RSA_FUNCTION MP_EXPTMOD_E: memory/config problem");
+        }
+
+        key->state = RSA_STATE_NONE;
+        wc_RsaCleanup(key);
+    }
+
+    return ret;
+}
+
+
+#ifndef WOLFSSL_RSA_VERIFY_ONLY
+/* Internal Wrappers */
+/* Gives the option of choosing padding type
+   in : input to be encrypted
+   inLen: length of input buffer
+   out: encrypted output
+   outLen: length of encrypted output buffer
+   key   : wolfSSL initialized RSA key struct
+   rng   : wolfSSL initialized random number struct
+   rsa_type  : type of RSA: RSA_PUBLIC_ENCRYPT, RSA_PUBLIC_DECRYPT,
+        RSA_PRIVATE_ENCRYPT or RSA_PRIVATE_DECRYPT
+   pad_value: RSA_BLOCK_TYPE_1 or RSA_BLOCK_TYPE_2
+   pad_type  : type of padding: WC_RSA_PKCSV15_PAD, WC_RSA_OAEP_PAD,
+        WC_RSA_NO_PAD or WC_RSA_PSS_PAD
+   hash  : type of hash algorithm to use found in wolfssl/wolfcrypt/hash.h
+   mgf   : type of mask generation function to use
+   label : optional label
+   labelSz : size of optional label buffer
+   saltLen : Length of salt used in PSS
+   rng : random number generator */
+static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out,
+                            word32 outLen, RsaKey* key, int rsa_type,
+                            byte pad_value, int pad_type,
+                            enum wc_HashType hash, int mgf,
+                            byte* label, word32 labelSz, int saltLen,
+                            WC_RNG* rng)
+{
+    int ret, sz;
+
+    if (in == NULL || inLen == 0 || out == NULL || key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    sz = wc_RsaEncryptSize(key);
+    if (sz > (int)outLen) {
+        return RSA_BUFFER_E;
+    }
+
+    if (sz < RSA_MIN_PAD_SZ) {
+        return WC_KEY_SIZE_E;
+    }
+
+    if (inLen > (word32)(sz - RSA_MIN_PAD_SZ)) {
+#ifdef WC_RSA_NO_PADDING
+        /* In the case that no padding is used the input length can and should
+         * be the same size as the RSA key. */
+        if (pad_type != WC_RSA_NO_PAD)
+#endif
+        return RSA_BUFFER_E;
+    }
+
+    switch (key->state) {
+    case RSA_STATE_NONE:
+    case RSA_STATE_ENCRYPT_PAD:
+    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) && \
+            defined(HAVE_CAVIUM)
+        if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA &&
+                                 pad_type != WC_RSA_PSS_PAD && key->n.raw.buf) {
+            /* Async operations that include padding */
+            if (rsa_type == RSA_PUBLIC_ENCRYPT &&
+                                                pad_value == RSA_BLOCK_TYPE_2) {
+                key->state = RSA_STATE_ENCRYPT_RES;
+                key->dataLen = key->n.raw.len;
+                return NitroxRsaPublicEncrypt(in, inLen, out, outLen, key);
+            }
+            else if (rsa_type == RSA_PRIVATE_ENCRYPT &&
+                                                pad_value == RSA_BLOCK_TYPE_1) {
+                key->state = RSA_STATE_ENCRYPT_RES;
+                key->dataLen = key->n.raw.len;
+                return NitroxRsaSSL_Sign(in, inLen, out, outLen, key);
+            }
+        }
+    #elif defined(WOLFSSL_CRYPTOCELL)
+        if (rsa_type == RSA_PUBLIC_ENCRYPT &&
+                                            pad_value == RSA_BLOCK_TYPE_2) {
+
+            return cc310_RsaPublicEncrypt(in, inLen, out, outLen, key);
+        }
+        else if (rsa_type == RSA_PRIVATE_ENCRYPT &&
+                                         pad_value == RSA_BLOCK_TYPE_1) {
+         return cc310_RsaSSL_Sign(in, inLen, out, outLen, key,
+                                  cc310_hashModeRSA(hash, 0));
+        }
+    #endif /* WOLFSSL_CRYPTOCELL */
+
+        key->state = RSA_STATE_ENCRYPT_PAD;
+        ret = wc_RsaPad_ex(in, inLen, out, sz, pad_value, rng, pad_type, hash,
+                           mgf, label, labelSz, saltLen, mp_count_bits(&key->n),
+                           key->heap);
+        if (ret < 0) {
+            break;
+        }
+
+        key->state = RSA_STATE_ENCRYPT_EXPTMOD;
+        FALL_THROUGH;
+
+    case RSA_STATE_ENCRYPT_EXPTMOD:
+
+        key->dataLen = outLen;
+        ret = wc_RsaFunction(out, sz, out, &key->dataLen, rsa_type, key, rng);
+
+        if (ret >= 0 || ret == WC_PENDING_E) {
+            key->state = RSA_STATE_ENCRYPT_RES;
+        }
+        if (ret < 0) {
+            break;
+        }
+
+        FALL_THROUGH;
+
+    case RSA_STATE_ENCRYPT_RES:
+        ret = key->dataLen;
+        break;
+
+    default:
+        ret = BAD_STATE_E;
+        break;
+    }
+
+    /* if async pending then return and skip done cleanup below */
+    if (ret == WC_PENDING_E
+    #ifdef WC_RSA_NONBLOCK
+        || ret == FP_WOULDBLOCK
+    #endif
+    ) {
+        return ret;
+    }
+
+    key->state = RSA_STATE_NONE;
+    wc_RsaCleanup(key);
+
+    return ret;
+}
+
+#endif
+
+/* Gives the option of choosing padding type
+   in : input to be decrypted
+   inLen: length of input buffer
+   out:  decrypted message
+   outLen: length of decrypted message in bytes
+   outPtr: optional inline output pointer (if provided doing inline)
+   key   : wolfSSL initialized RSA key struct
+   rsa_type  : type of RSA: RSA_PUBLIC_ENCRYPT, RSA_PUBLIC_DECRYPT,
+        RSA_PRIVATE_ENCRYPT or RSA_PRIVATE_DECRYPT
+   pad_value: RSA_BLOCK_TYPE_1 or RSA_BLOCK_TYPE_2
+   pad_type  : type of padding: WC_RSA_PKCSV15_PAD, WC_RSA_OAEP_PAD,
+        WC_RSA_NO_PAD, WC_RSA_PSS_PAD
+   hash  : type of hash algorithm to use found in wolfssl/wolfcrypt/hash.h
+   mgf   : type of mask generation function to use
+   label : optional label
+   labelSz : size of optional label buffer
+   saltLen : Length of salt used in PSS
+   rng : random number generator */
+static int RsaPrivateDecryptEx(byte* in, word32 inLen, byte* out,
+                            word32 outLen, byte** outPtr, RsaKey* key,
+                            int rsa_type, byte pad_value, int pad_type,
+                            enum wc_HashType hash, int mgf,
+                            byte* label, word32 labelSz, int saltLen,
+                            WC_RNG* rng)
+{
+    int ret = RSA_WRONG_TYPE_E;
+    byte* pad = NULL;
+
+    if (in == NULL || inLen == 0 || out == NULL || key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    switch (key->state) {
+    case RSA_STATE_NONE:
+        key->dataLen = inLen;
+
+    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) && \
+            defined(HAVE_CAVIUM)
+        /* Async operations that include padding */
+        if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA &&
+                                                   pad_type != WC_RSA_PSS_PAD) {
+#ifndef WOLFSSL_RSA_PUBLIC_ONLY
+            if (rsa_type == RSA_PRIVATE_DECRYPT &&
+                                                pad_value == RSA_BLOCK_TYPE_2) {
+                key->state = RSA_STATE_DECRYPT_RES;
+                key->data = NULL;
+                return NitroxRsaPrivateDecrypt(in, inLen, out, &key->dataLen,
+                                               key);
+#endif
+            }
+            else if (rsa_type == RSA_PUBLIC_DECRYPT &&
+                                                pad_value == RSA_BLOCK_TYPE_1) {
+                key->state = RSA_STATE_DECRYPT_RES;
+                key->data = NULL;
+                return NitroxRsaSSL_Verify(in, inLen, out, &key->dataLen, key);
+            }
+        }
+    #elif defined(WOLFSSL_CRYPTOCELL)
+        if (rsa_type == RSA_PRIVATE_DECRYPT &&
+                                            pad_value == RSA_BLOCK_TYPE_2) {
+            ret = cc310_RsaPublicDecrypt(in, inLen, out, outLen, key);
+            if (outPtr != NULL)
+                *outPtr = out; /* for inline */
+            return ret;
+        }
+        else if (rsa_type == RSA_PUBLIC_DECRYPT &&
+                                            pad_value == RSA_BLOCK_TYPE_1) {
+            return cc310_RsaSSL_Verify(in, inLen, out, key,
+                                       cc310_hashModeRSA(hash, 0));
+        }
+    #endif /* WOLFSSL_CRYPTOCELL */
+
+
+#if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_VERIFY_INLINE)
+        /* verify the tmp ptr is NULL, otherwise indicates bad state */
+        if (key->data != NULL) {
+            ret = BAD_STATE_E;
+            break;
+        }
+
+        /* if not doing this inline then allocate a buffer for it */
+        if (outPtr == NULL) {
+            key->data = (byte*)XMALLOC(inLen, key->heap,
+                                                      DYNAMIC_TYPE_WOLF_BIGINT);
+            key->dataIsAlloc = 1;
+            if (key->data == NULL) {
+                ret = MEMORY_E;
+                break;
+            }
+            XMEMCPY(key->data, in, inLen);
+        }
+        else {
+            key->data = out;
+        }
+#endif
+
+        key->state = RSA_STATE_DECRYPT_EXPTMOD;
+        FALL_THROUGH;
+
+    case RSA_STATE_DECRYPT_EXPTMOD:
+#if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_VERIFY_INLINE)
+        ret = wc_RsaFunction(key->data, inLen, key->data, &key->dataLen,
+                                                            rsa_type, key, rng);
+#else
+        ret = wc_RsaFunction(in, inLen, out, &key->dataLen, rsa_type, key, rng);
+#endif
+
+        if (ret >= 0 || ret == WC_PENDING_E) {
+            key->state = RSA_STATE_DECRYPT_UNPAD;
+        }
+        if (ret < 0) {
+            break;
+        }
+
+        FALL_THROUGH;
+
+    case RSA_STATE_DECRYPT_UNPAD:
+#if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_VERIFY_INLINE)
+        ret = wc_RsaUnPad_ex(key->data, key->dataLen, &pad, pad_value, pad_type,
+                             hash, mgf, label, labelSz, saltLen,
+                             mp_count_bits(&key->n), key->heap);
+#else
+        ret = wc_RsaUnPad_ex(out, key->dataLen, &pad, pad_value, pad_type, hash,
+                             mgf, label, labelSz, saltLen,
+                             mp_count_bits(&key->n), key->heap);
+#endif
+        if (rsa_type == RSA_PUBLIC_DECRYPT && ret > (int)outLen)
+            ret = RSA_BUFFER_E;
+        else if (ret >= 0 && pad != NULL) {
+#if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_VERIFY_INLINE)
+            signed char c;
+#endif
+
+            /* only copy output if not inline */
+            if (outPtr == NULL) {
+#if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_VERIFY_INLINE)
+                if (rsa_type == RSA_PRIVATE_DECRYPT) {
+                    word32 i, j;
+                    int start = (int)((size_t)pad - (size_t)key->data);
+
+                    for (i = 0, j = 0; j < key->dataLen; j++) {
+                        out[i] = key->data[j];
+                        c  = ctMaskGTE(j, start);
+                        c &= ctMaskLT(i, outLen);
+                        /* 0 - no add, -1 add */
+                        i += (word32)((byte)(-c));
+                    }
+                }
+                else
+#endif
+                {
+                    XMEMCPY(out, pad, ret);
+                }
+            }
+            else
+                *outPtr = pad;
+
+#if !defined(WOLFSSL_RSA_VERIFY_ONLY)
+            ret = ctMaskSelInt(ctMaskLTE(ret, outLen), ret, RSA_BUFFER_E);
+            ret = ctMaskSelInt(ctMaskNotEq(ret, 0), ret, RSA_BUFFER_E);
+#else
+            if (outLen < (word32)ret)
+                ret = RSA_BUFFER_E;
+#endif
+        }
+
+        key->state = RSA_STATE_DECRYPT_RES;
+        FALL_THROUGH;
+
+    case RSA_STATE_DECRYPT_RES:
+    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) && \
+            defined(HAVE_CAVIUM)
+        if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA &&
+                                                   pad_type != WC_RSA_PSS_PAD) {
+            if (ret > 0) {
+                /* convert result */
+                byte* dataLen = (byte*)&key->dataLen;
+                ret = (dataLen[0] << 8) | (dataLen[1]);
+
+                if (outPtr)
+                    *outPtr = in;
+            }
+        }
+    #endif
+        break;
+
+    default:
+        ret = BAD_STATE_E;
+        break;
+    }
+
+    /* if async pending then return and skip done cleanup below */
+    if (ret == WC_PENDING_E
+    #ifdef WC_RSA_NONBLOCK
+        || ret == FP_WOULDBLOCK
+    #endif
+    ) {
+        return ret;
+    }
+
+    key->state = RSA_STATE_NONE;
+    wc_RsaCleanup(key);
+
+    return ret;
+}
+
+
+#ifndef WOLFSSL_RSA_VERIFY_ONLY
+/* Public RSA Functions */
+int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen,
+                                                     RsaKey* key, WC_RNG* rng)
+{
+    return RsaPublicEncryptEx(in, inLen, out, outLen, key,
+        RSA_PUBLIC_ENCRYPT, RSA_BLOCK_TYPE_2, WC_RSA_PKCSV15_PAD,
+        WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng);
+}
+
+
+#if !defined(WC_NO_RSA_OAEP) || defined(WC_RSA_NO_PADDING)
+int wc_RsaPublicEncrypt_ex(const byte* in, word32 inLen, byte* out,
+                    word32 outLen, RsaKey* key, WC_RNG* rng, int type,
+                    enum wc_HashType hash, int mgf, byte* label,
+                    word32 labelSz)
+{
+    return RsaPublicEncryptEx(in, inLen, out, outLen, key, RSA_PUBLIC_ENCRYPT,
+        RSA_BLOCK_TYPE_2, type, hash, mgf, label, labelSz, 0, rng);
+}
+#endif /* WC_NO_RSA_OAEP */
+#endif
+
+
+#ifndef WOLFSSL_RSA_PUBLIC_ONLY
+int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, RsaKey* key)
+{
+    WC_RNG* rng;
+#ifdef WC_RSA_BLINDING
+    rng = key->rng;
+#else
+    rng = NULL;
+#endif
+    return RsaPrivateDecryptEx(in, inLen, in, inLen, out, key,
+        RSA_PRIVATE_DECRYPT, RSA_BLOCK_TYPE_2, WC_RSA_PKCSV15_PAD,
+        WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng);
+}
+
+
+#ifndef WC_NO_RSA_OAEP
+int wc_RsaPrivateDecryptInline_ex(byte* in, word32 inLen, byte** out,
+                                  RsaKey* key, int type, enum wc_HashType hash,
+                                  int mgf, byte* label, word32 labelSz)
+{
+    WC_RNG* rng;
+#ifdef WC_RSA_BLINDING
+    rng = key->rng;
+#else
+    rng = NULL;
+#endif
+    return RsaPrivateDecryptEx(in, inLen, in, inLen, out, key,
+        RSA_PRIVATE_DECRYPT, RSA_BLOCK_TYPE_2, type, hash,
+        mgf, label, labelSz, 0, rng);
+}
+#endif /* WC_NO_RSA_OAEP */
+
+
+int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out,
+                                                 word32 outLen, RsaKey* key)
+{
+    WC_RNG* rng;
+#ifdef WC_RSA_BLINDING
+    rng = key->rng;
+#else
+    rng = NULL;
+#endif
+    return RsaPrivateDecryptEx((byte*)in, inLen, out, outLen, NULL, key,
+        RSA_PRIVATE_DECRYPT, RSA_BLOCK_TYPE_2, WC_RSA_PKCSV15_PAD,
+        WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng);
+}
+
+#if !defined(WC_NO_RSA_OAEP) || defined(WC_RSA_NO_PADDING)
+int wc_RsaPrivateDecrypt_ex(const byte* in, word32 inLen, byte* out,
+                            word32 outLen, RsaKey* key, int type,
+                            enum wc_HashType hash, int mgf, byte* label,
+                            word32 labelSz)
+{
+    WC_RNG* rng;
+#ifdef WC_RSA_BLINDING
+    rng = key->rng;
+#else
+    rng = NULL;
+#endif
+    return RsaPrivateDecryptEx((byte*)in, inLen, out, outLen, NULL, key,
+        RSA_PRIVATE_DECRYPT, RSA_BLOCK_TYPE_2, type, hash, mgf, label,
+        labelSz, 0, rng);
+}
+#endif /* WC_NO_RSA_OAEP || WC_RSA_NO_PADDING */
+#endif /* WOLFSSL_RSA_PUBLIC_ONLY */
+
+#if !defined(WOLFSSL_CRYPTOCELL)
+int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key)
+{
+    WC_RNG* rng;
+#ifdef WC_RSA_BLINDING
+    rng = key->rng;
+#else
+    rng = NULL;
+#endif
+    return RsaPrivateDecryptEx(in, inLen, in, inLen, out, key,
+        RSA_PUBLIC_DECRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PKCSV15_PAD,
+        WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng);
+}
+#endif
+
+#ifndef WOLFSSL_RSA_VERIFY_ONLY
+int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen,
+                                                                 RsaKey* key)
+{
+    return wc_RsaSSL_Verify_ex(in, inLen, out, outLen, key , WC_RSA_PKCSV15_PAD);
+}
+
+int  wc_RsaSSL_Verify_ex(const byte* in, word32 inLen, byte* out, word32 outLen,
+                         RsaKey* key, int pad_type)
+{
+    WC_RNG* rng;
+
+    if (key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef WC_RSA_BLINDING
+    rng = key->rng;
+#else
+    rng = NULL;
+#endif
+
+    return RsaPrivateDecryptEx((byte*)in, inLen, out, outLen, NULL, key,
+        RSA_PUBLIC_DECRYPT, RSA_BLOCK_TYPE_1, pad_type,
+        WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng);
+}
+#endif
+
+#ifdef WC_RSA_PSS
+/* Verify the message signed with RSA-PSS.
+ * The input buffer is reused for the output buffer.
+ * Salt length is equal to hash length.
+ *
+ * in     Buffer holding encrypted data.
+ * inLen  Length of data in buffer.
+ * out    Pointer to address containing the PSS data.
+ * hash   Hash algorithm.
+ * mgf    Mask generation function.
+ * key    Public RSA key.
+ * returns the length of the PSS data on success and negative indicates failure.
+ */
+int wc_RsaPSS_VerifyInline(byte* in, word32 inLen, byte** out,
+                           enum wc_HashType hash, int mgf, RsaKey* key)
+{
+#ifndef WOLFSSL_PSS_SALT_LEN_DISCOVER
+    return wc_RsaPSS_VerifyInline_ex(in, inLen, out, hash, mgf,
+                                                 RSA_PSS_SALT_LEN_DEFAULT, key);
+#else
+    return wc_RsaPSS_VerifyInline_ex(in, inLen, out, hash, mgf,
+                                                RSA_PSS_SALT_LEN_DISCOVER, key);
+#endif
+}
+
+/* Verify the message signed with RSA-PSS.
+ * The input buffer is reused for the output buffer.
+ *
+ * in       Buffer holding encrypted data.
+ * inLen    Length of data in buffer.
+ * out      Pointer to address containing the PSS data.
+ * hash     Hash algorithm.
+ * mgf      Mask generation function.
+ * key      Public RSA key.
+ * saltLen  Length of salt used. RSA_PSS_SALT_LEN_DEFAULT (-1) indicates salt
+ *          length is the same as the hash length. RSA_PSS_SALT_LEN_DISCOVER
+ *          indicates salt length is determined from the data.
+ * returns the length of the PSS data on success and negative indicates failure.
+ */
+int wc_RsaPSS_VerifyInline_ex(byte* in, word32 inLen, byte** out,
+                              enum wc_HashType hash, int mgf, int saltLen,
+                              RsaKey* key)
+{
+    WC_RNG* rng;
+#ifdef WC_RSA_BLINDING
+    rng = key->rng;
+#else
+    rng = NULL;
+#endif
+    return RsaPrivateDecryptEx(in, inLen, in, inLen, out, key,
+        RSA_PUBLIC_DECRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PSS_PAD,
+        hash, mgf, NULL, 0, saltLen, rng);
+}
+
+/* Verify the message signed with RSA-PSS.
+ * Salt length is equal to hash length.
+ *
+ * in     Buffer holding encrypted data.
+ * inLen  Length of data in buffer.
+ * out    Pointer to address containing the PSS data.
+ * hash   Hash algorithm.
+ * mgf    Mask generation function.
+ * key    Public RSA key.
+ * returns the length of the PSS data on success and negative indicates failure.
+ */
+int wc_RsaPSS_Verify(byte* in, word32 inLen, byte* out, word32 outLen,
+                     enum wc_HashType hash, int mgf, RsaKey* key)
+{
+#ifndef WOLFSSL_PSS_SALT_LEN_DISCOVER
+    return wc_RsaPSS_Verify_ex(in, inLen, out, outLen, hash, mgf,
+                                                 RSA_PSS_SALT_LEN_DEFAULT, key);
+#else
+    return wc_RsaPSS_Verify_ex(in, inLen, out, outLen, hash, mgf,
+                                                RSA_PSS_SALT_LEN_DISCOVER, key);
+#endif
+}
+
+/* Verify the message signed with RSA-PSS.
+ *
+ * in       Buffer holding encrypted data.
+ * inLen    Length of data in buffer.
+ * out      Pointer to address containing the PSS data.
+ * hash     Hash algorithm.
+ * mgf      Mask generation function.
+ * key      Public RSA key.
+ * saltLen  Length of salt used. RSA_PSS_SALT_LEN_DEFAULT (-1) indicates salt
+ *          length is the same as the hash length. RSA_PSS_SALT_LEN_DISCOVER
+ *          indicates salt length is determined from the data.
+ * returns the length of the PSS data on success and negative indicates failure.
+ */
+int wc_RsaPSS_Verify_ex(byte* in, word32 inLen, byte* out, word32 outLen,
+                        enum wc_HashType hash, int mgf, int saltLen,
+                        RsaKey* key)
+{
+    WC_RNG* rng;
+#ifdef WC_RSA_BLINDING
+    rng = key->rng;
+#else
+    rng = NULL;
+#endif
+    return RsaPrivateDecryptEx(in, inLen, out, outLen, NULL, key,
+        RSA_PUBLIC_DECRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PSS_PAD,
+        hash, mgf, NULL, 0, saltLen, rng);
+}
+
+
+/* Checks the PSS data to ensure that the signature matches.
+ * Salt length is equal to hash length.
+ *
+ * in        Hash of the data that is being verified.
+ * inSz      Length of hash.
+ * sig       Buffer holding PSS data.
+ * sigSz     Size of PSS data.
+ * hashType  Hash algorithm.
+ * returns BAD_PADDING_E when the PSS data is invalid, BAD_FUNC_ARG when
+ * NULL is passed in to in or sig or inSz is not the same as the hash
+ * algorithm length and 0 on success.
+ */
+int wc_RsaPSS_CheckPadding(const byte* in, word32 inSz, byte* sig,
+                           word32 sigSz, enum wc_HashType hashType)
+{
+    return wc_RsaPSS_CheckPadding_ex(in, inSz, sig, sigSz, hashType, inSz, 0);
+}
+
+/* Checks the PSS data to ensure that the signature matches.
+ *
+ * in        Hash of the data that is being verified.
+ * inSz      Length of hash.
+ * sig       Buffer holding PSS data.
+ * sigSz     Size of PSS data.
+ * hashType  Hash algorithm.
+ * saltLen   Length of salt used. RSA_PSS_SALT_LEN_DEFAULT (-1) indicates salt
+ *           length is the same as the hash length. RSA_PSS_SALT_LEN_DISCOVER
+ *           indicates salt length is determined from the data.
+ * returns BAD_PADDING_E when the PSS data is invalid, BAD_FUNC_ARG when
+ * NULL is passed in to in or sig or inSz is not the same as the hash
+ * algorithm length and 0 on success.
+ */
+int wc_RsaPSS_CheckPadding_ex(const byte* in, word32 inSz, byte* sig,
+                              word32 sigSz, enum wc_HashType hashType,
+                              int saltLen, int bits)
+{
+    int ret = 0;
+#ifndef WOLFSSL_PSS_LONG_SALT
+    byte sigCheck[WC_MAX_DIGEST_SIZE*2 + RSA_PSS_PAD_SZ];
+#else
+    byte *sigCheck = NULL;
+#endif
+
+    (void)bits;
+
+    if (in == NULL || sig == NULL ||
+                               inSz != (word32)wc_HashGetDigestSize(hashType)) {
+        ret = BAD_FUNC_ARG;
+    }
+
+    if (ret == 0) {
+        if (saltLen == RSA_PSS_SALT_LEN_DEFAULT) {
+            saltLen = inSz;
+            #ifdef WOLFSSL_SHA512
+                /* See FIPS 186-4 section 5.5 item (e). */
+                if (bits == 1024 && inSz == WC_SHA512_DIGEST_SIZE) {
+                    saltLen = RSA_PSS_SALT_MAX_SZ;
+                }
+            #endif
+        }
+#ifndef WOLFSSL_PSS_LONG_SALT
+        else if ((word32)saltLen > inSz) {
+            ret = PSS_SALTLEN_E;
+        }
+#endif
+#ifndef WOLFSSL_PSS_SALT_LEN_DISCOVER
+        else if (saltLen < RSA_PSS_SALT_LEN_DEFAULT) {
+            ret = PSS_SALTLEN_E;
+        }
+#else
+        else if (saltLen == RSA_PSS_SALT_LEN_DISCOVER) {
+            saltLen = sigSz - inSz;
+            if (saltLen < 0) {
+                ret = PSS_SALTLEN_E;
+            }
+        }
+        else if (saltLen < RSA_PSS_SALT_LEN_DISCOVER) {
+            ret = PSS_SALTLEN_E;
+        }
+#endif
+    }
+
+    /* Sig = Salt | Exp Hash */
+    if (ret == 0) {
+        if (sigSz != inSz + saltLen) {
+            ret = PSS_SALTLEN_E;
+        }
+    }
+
+#ifdef WOLFSSL_PSS_LONG_SALT
+    if (ret == 0) {
+        sigCheck = (byte*)XMALLOC(RSA_PSS_PAD_SZ + inSz + saltLen, NULL,
+                                                       DYNAMIC_TYPE_RSA_BUFFER);
+        if (sigCheck == NULL) {
+            ret = MEMORY_E;
+        }
+    }
+#endif
+
+    /* Exp Hash = HASH(8 * 0x00 | Message Hash | Salt) */
+    if (ret == 0) {
+        XMEMSET(sigCheck, 0, RSA_PSS_PAD_SZ);
+        XMEMCPY(sigCheck + RSA_PSS_PAD_SZ, in, inSz);
+        XMEMCPY(sigCheck + RSA_PSS_PAD_SZ + inSz, sig, saltLen);
+        ret = wc_Hash(hashType, sigCheck, RSA_PSS_PAD_SZ + inSz + saltLen,
+                      sigCheck, inSz);
+    }
+    if (ret == 0) {
+        if (XMEMCMP(sigCheck, sig + saltLen, inSz) != 0) {
+            WOLFSSL_MSG("RsaPSS_CheckPadding: Padding Error");
+            ret = BAD_PADDING_E;
+        }
+    }
+
+#ifdef WOLFSSL_PSS_LONG_SALT
+    if (sigCheck != NULL) {
+        XFREE(sigCheck, NULL, DYNAMIC_TYPE_RSA_BUFFER);
+    }
+#endif
+    return ret;
+}
+
+
+/* Verify the message signed with RSA-PSS.
+ * The input buffer is reused for the output buffer.
+ * Salt length is equal to hash length.
+ *
+ * in     Buffer holding encrypted data.
+ * inLen  Length of data in buffer.
+ * out    Pointer to address containing the PSS data.
+ * digest Hash of the data that is being verified.
+ * digestLen Length of hash.
+ * hash   Hash algorithm.
+ * mgf    Mask generation function.
+ * key    Public RSA key.
+ * returns the length of the PSS data on success and negative indicates failure.
+ */
+int wc_RsaPSS_VerifyCheckInline(byte* in, word32 inLen, byte** out,
+                           const byte* digest, word32 digestLen,
+                           enum wc_HashType hash, int mgf, RsaKey* key)
+{
+    int ret = 0, verify, saltLen, hLen, bits = 0;
+
+    hLen = wc_HashGetDigestSize(hash);
+    if (hLen < 0)
+        return hLen;
+    if ((word32)hLen != digestLen)
+        return BAD_FUNC_ARG;
+
+    saltLen = hLen;
+    #ifdef WOLFSSL_SHA512
+        /* See FIPS 186-4 section 5.5 item (e). */
+        bits = mp_count_bits(&key->n);
+        if (bits == 1024 && hLen == WC_SHA512_DIGEST_SIZE)
+            saltLen = RSA_PSS_SALT_MAX_SZ;
+    #endif
+
+    verify = wc_RsaPSS_VerifyInline_ex(in, inLen, out, hash, mgf, saltLen, key);
+    if (verify > 0)
+        ret = wc_RsaPSS_CheckPadding_ex(digest, digestLen, *out, verify,
+                                        hash, saltLen, bits);
+    if (ret == 0)
+        ret = verify;
+
+    return ret;
+}
+
+
+/* Verify the message signed with RSA-PSS.
+ * Salt length is equal to hash length.
+ *
+ * in     Buffer holding encrypted data.
+ * inLen  Length of data in buffer.
+ * out    Pointer to address containing the PSS data.
+ * outLen Length of the output.
+ * digest Hash of the data that is being verified.
+ * digestLen Length of hash.
+ * hash   Hash algorithm.
+ * mgf    Mask generation function.
+ * key    Public RSA key.
+ * returns the length of the PSS data on success and negative indicates failure.
+ */
+int wc_RsaPSS_VerifyCheck(byte* in, word32 inLen, byte* out, word32 outLen,
+                          const byte* digest, word32 digestLen,
+                          enum wc_HashType hash, int mgf,
+                          RsaKey* key)
+{
+    int ret = 0, verify, saltLen, hLen, bits = 0;
+
+    hLen = wc_HashGetDigestSize(hash);
+    if (hLen < 0)
+        return hLen;
+    if ((word32)hLen != digestLen)
+        return BAD_FUNC_ARG;
+
+    saltLen = hLen;
+    #ifdef WOLFSSL_SHA512
+        /* See FIPS 186-4 section 5.5 item (e). */
+        bits = mp_count_bits(&key->n);
+        if (bits == 1024 && hLen == WC_SHA512_DIGEST_SIZE)
+            saltLen = RSA_PSS_SALT_MAX_SZ;
+    #endif
+
+    verify = wc_RsaPSS_Verify_ex(in, inLen, out, outLen, hash,
+                                 mgf, saltLen, key);
+    if (verify > 0)
+        ret = wc_RsaPSS_CheckPadding_ex(digest, digestLen, out, verify,
+                                        hash, saltLen, bits);
+    if (ret == 0)
+        ret = verify;
+
+    return ret;
+}
+
+#endif
+
+#if !defined(WOLFSSL_RSA_PUBLIC_ONLY) && !defined(WOLFSSL_RSA_VERIFY_ONLY)
+int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen,
+                                                   RsaKey* key, WC_RNG* rng)
+{
+    return RsaPublicEncryptEx(in, inLen, out, outLen, key,
+        RSA_PRIVATE_ENCRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PKCSV15_PAD,
+        WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng);
+}
+
+#ifdef WC_RSA_PSS
+/* Sign the hash of a message using RSA-PSS.
+ * Salt length is equal to hash length.
+ *
+ * in      Buffer holding hash of message.
+ * inLen   Length of data in buffer (hash length).
+ * out     Buffer to write encrypted signature into.
+ * outLen  Size of buffer to write to.
+ * hash    Hash algorithm.
+ * mgf     Mask generation function.
+ * key     Public RSA key.
+ * rng     Random number generator.
+ * returns the length of the encrypted signature on success, a negative value
+ * indicates failure.
+ */
+int wc_RsaPSS_Sign(const byte* in, word32 inLen, byte* out, word32 outLen,
+                       enum wc_HashType hash, int mgf, RsaKey* key, WC_RNG* rng)
+{
+    return wc_RsaPSS_Sign_ex(in, inLen, out, outLen, hash, mgf,
+                                            RSA_PSS_SALT_LEN_DEFAULT, key, rng);
+}
+
+/* Sign the hash of a message using RSA-PSS.
+ *
+ * in       Buffer holding hash of message.
+ * inLen    Length of data in buffer (hash length).
+ * out      Buffer to write encrypted signature into.
+ * outLen   Size of buffer to write to.
+ * hash     Hash algorithm.
+ * mgf      Mask generation function.
+ * saltLen  Length of salt used. RSA_PSS_SALT_LEN_DEFAULT (-1) indicates salt
+ *          length is the same as the hash length. RSA_PSS_SALT_LEN_DISCOVER
+ *          indicates salt length is determined from the data.
+ * key      Public RSA key.
+ * rng      Random number generator.
+ * returns the length of the encrypted signature on success, a negative value
+ * indicates failure.
+ */
+int wc_RsaPSS_Sign_ex(const byte* in, word32 inLen, byte* out, word32 outLen,
+                      enum wc_HashType hash, int mgf, int saltLen, RsaKey* key,
+                      WC_RNG* rng)
+{
+    return RsaPublicEncryptEx(in, inLen, out, outLen, key,
+        RSA_PRIVATE_ENCRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PSS_PAD,
+        hash, mgf, NULL, 0, saltLen, rng);
+}
+#endif
+#endif
+
+#if !defined(WOLFSSL_RSA_VERIFY_ONLY) || !defined(WOLFSSL_SP_MATH) || \
+                                                             defined(WC_RSA_PSS)
+int wc_RsaEncryptSize(RsaKey* key)
+{
+    int ret;
+
+    if (key == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    ret = mp_unsigned_bin_size(&key->n);
+
+#ifdef WOLF_CRYPTO_CB
+    if (ret == 0 && key->devId != INVALID_DEVID) {
+        ret = 2048/8; /* hardware handles, use 2048-bit as default */
+    }
+#endif
+
+    return ret;
+}
+#endif
+
+#ifndef WOLFSSL_RSA_VERIFY_ONLY
+/* flatten RsaKey structure into individual elements (e, n) */
+int wc_RsaFlattenPublicKey(RsaKey* key, byte* e, word32* eSz, byte* n,
+                                                                   word32* nSz)
+{
+    int sz, ret;
+
+    if (key == NULL || e == NULL || eSz == NULL || n == NULL || nSz == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    sz = mp_unsigned_bin_size(&key->e);
+    if ((word32)sz > *eSz)
+        return RSA_BUFFER_E;
+    ret = mp_to_unsigned_bin(&key->e, e);
+    if (ret != MP_OKAY)
+        return ret;
+    *eSz = (word32)sz;
+
+    sz = wc_RsaEncryptSize(key);
+    if ((word32)sz > *nSz)
+        return RSA_BUFFER_E;
+    ret = mp_to_unsigned_bin(&key->n, n);
+    if (ret != MP_OKAY)
+        return ret;
+    *nSz = (word32)sz;
+
+    return 0;
+}
+#endif
+
+#endif /* HAVE_FIPS */
+
+
+#ifndef WOLFSSL_RSA_VERIFY_ONLY
+static int RsaGetValue(mp_int* in, byte* out, word32* outSz)
+{
+    word32 sz;
+    int ret = 0;
+
+    /* Parameters ensured by calling function. */
+
+    sz = (word32)mp_unsigned_bin_size(in);
+    if (sz > *outSz)
+        ret = RSA_BUFFER_E;
+
+    if (ret == 0)
+        ret = mp_to_unsigned_bin(in, out);
+
+    if (ret == MP_OKAY)
+        *outSz = sz;
+
+    return ret;
+}
+
+
+int wc_RsaExportKey(RsaKey* key,
+                    byte* e, word32* eSz, byte* n, word32* nSz,
+                    byte* d, word32* dSz, byte* p, word32* pSz,
+                    byte* q, word32* qSz)
+{
+    int ret = BAD_FUNC_ARG;
+
+    if (key && e && eSz && n && nSz && d && dSz && p && pSz && q && qSz)
+        ret = 0;
+
+    if (ret == 0)
+        ret = RsaGetValue(&key->e, e, eSz);
+    if (ret == 0)
+        ret = RsaGetValue(&key->n, n, nSz);
+#ifndef WOLFSSL_RSA_PUBLIC_ONLY
+    if (ret == 0)
+        ret = RsaGetValue(&key->d, d, dSz);
+    if (ret == 0)
+        ret = RsaGetValue(&key->p, p, pSz);
+    if (ret == 0)
+        ret = RsaGetValue(&key->q, q, qSz);
+#else
+    /* no private parts to key */
+    if (d == NULL || p == NULL || q == NULL || dSz == NULL || pSz == NULL
+            || qSz == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+    else {
+        *dSz = 0;
+        *pSz = 0;
+        *qSz = 0;
+    }
+#endif /* WOLFSSL_RSA_PUBLIC_ONLY */
+
+    return ret;
+}
+#endif
+
+
+#ifdef WOLFSSL_KEY_GEN
+
+/* Check that |p-q| > 2^((size/2)-100) */
+static int wc_CompareDiffPQ(mp_int* p, mp_int* q, int size)
+{
+    mp_int c, d;
+    int ret;
+
+    if (p == NULL || q == NULL)
+        return BAD_FUNC_ARG;
+
+    ret = mp_init_multi(&c, &d, NULL, NULL, NULL, NULL);
+
+    /* c = 2^((size/2)-100) */
+    if (ret == 0)
+        ret = mp_2expt(&c, (size/2)-100);
+
+    /* d = |p-q| */
+    if (ret == 0)
+        ret = mp_sub(p, q, &d);
+
+    if (ret == 0)
+        ret = mp_abs(&d, &d);
+
+    /* compare */
+    if (ret == 0)
+        ret = mp_cmp(&d, &c);
+
+    if (ret == MP_GT)
+        ret = MP_OKAY;
+
+    mp_clear(&d);
+    mp_clear(&c);
+
+    return ret;
+}
+
+
+/* The lower_bound value is floor(2^(0.5) * 2^((nlen/2)-1)) where nlen is 4096.
+ * This number was calculated using a small test tool written with a common
+ * large number math library. Other values of nlen may be checked with a subset
+ * of lower_bound. */
+static const byte lower_bound[] = {
+    0xB5, 0x04, 0xF3, 0x33, 0xF9, 0xDE, 0x64, 0x84,
+    0x59, 0x7D, 0x89, 0xB3, 0x75, 0x4A, 0xBE, 0x9F,
+    0x1D, 0x6F, 0x60, 0xBA, 0x89, 0x3B, 0xA8, 0x4C,
+    0xED, 0x17, 0xAC, 0x85, 0x83, 0x33, 0x99, 0x15,
+/* 512 */
+    0x4A, 0xFC, 0x83, 0x04, 0x3A, 0xB8, 0xA2, 0xC3,
+    0xA8, 0xB1, 0xFE, 0x6F, 0xDC, 0x83, 0xDB, 0x39,
+    0x0F, 0x74, 0xA8, 0x5E, 0x43, 0x9C, 0x7B, 0x4A,
+    0x78, 0x04, 0x87, 0x36, 0x3D, 0xFA, 0x27, 0x68,
+/* 1024 */
+    0xD2, 0x20, 0x2E, 0x87, 0x42, 0xAF, 0x1F, 0x4E,
+    0x53, 0x05, 0x9C, 0x60, 0x11, 0xBC, 0x33, 0x7B,
+    0xCA, 0xB1, 0xBC, 0x91, 0x16, 0x88, 0x45, 0x8A,
+    0x46, 0x0A, 0xBC, 0x72, 0x2F, 0x7C, 0x4E, 0x33,
+    0xC6, 0xD5, 0xA8, 0xA3, 0x8B, 0xB7, 0xE9, 0xDC,
+    0xCB, 0x2A, 0x63, 0x43, 0x31, 0xF3, 0xC8, 0x4D,
+    0xF5, 0x2F, 0x12, 0x0F, 0x83, 0x6E, 0x58, 0x2E,
+    0xEA, 0xA4, 0xA0, 0x89, 0x90, 0x40, 0xCA, 0x4A,
+/* 2048 */
+    0x81, 0x39, 0x4A, 0xB6, 0xD8, 0xFD, 0x0E, 0xFD,
+    0xF4, 0xD3, 0xA0, 0x2C, 0xEB, 0xC9, 0x3E, 0x0C,
+    0x42, 0x64, 0xDA, 0xBC, 0xD5, 0x28, 0xB6, 0x51,
+    0xB8, 0xCF, 0x34, 0x1B, 0x6F, 0x82, 0x36, 0xC7,
+    0x01, 0x04, 0xDC, 0x01, 0xFE, 0x32, 0x35, 0x2F,
+    0x33, 0x2A, 0x5E, 0x9F, 0x7B, 0xDA, 0x1E, 0xBF,
+    0xF6, 0xA1, 0xBE, 0x3F, 0xCA, 0x22, 0x13, 0x07,
+    0xDE, 0xA0, 0x62, 0x41, 0xF7, 0xAA, 0x81, 0xC2,
+/* 3072 */
+    0xC1, 0xFC, 0xBD, 0xDE, 0xA2, 0xF7, 0xDC, 0x33,
+    0x18, 0x83, 0x8A, 0x2E, 0xAF, 0xF5, 0xF3, 0xB2,
+    0xD2, 0x4F, 0x4A, 0x76, 0x3F, 0xAC, 0xB8, 0x82,
+    0xFD, 0xFE, 0x17, 0x0F, 0xD3, 0xB1, 0xF7, 0x80,
+    0xF9, 0xAC, 0xCE, 0x41, 0x79, 0x7F, 0x28, 0x05,
+    0xC2, 0x46, 0x78, 0x5E, 0x92, 0x95, 0x70, 0x23,
+    0x5F, 0xCF, 0x8F, 0x7B, 0xCA, 0x3E, 0xA3, 0x3B,
+    0x4D, 0x7C, 0x60, 0xA5, 0xE6, 0x33, 0xE3, 0xE1
+/* 4096 */
+};
+
+
+/* returns 1 on key size ok and 0 if not ok */
+static WC_INLINE int RsaSizeCheck(int size)
+{
+    if (size < RSA_MIN_SIZE || size > RSA_MAX_SIZE) {
+        return 0;
+    }
+
+#ifdef HAVE_FIPS
+    /* Key size requirements for CAVP */
+    switch (size) {
+        case 1024:
+        case 2048:
+        case 3072:
+        case 4096:
+            return 1;
+    }
+
+    return 0;
+#else
+    return 1; /* allow unusual key sizes in non FIPS mode */
+#endif /* HAVE_FIPS */
+}
+
+
+static int _CheckProbablePrime(mp_int* p, mp_int* q, mp_int* e, int nlen,
+                                    int* isPrime, WC_RNG* rng)
+{
+    int ret;
+    mp_int tmp1, tmp2;
+    mp_int* prime;
+
+    if (p == NULL || e == NULL || isPrime == NULL)
+        return BAD_FUNC_ARG;
+
+    if (!RsaSizeCheck(nlen))
+        return BAD_FUNC_ARG;
+
+    *isPrime = MP_NO;
+
+    if (q != NULL) {
+        /* 5.4 - check that |p-q| <= (2^(1/2))(2^((nlen/2)-1)) */
+        ret = wc_CompareDiffPQ(p, q, nlen);
+        if (ret != MP_OKAY) goto notOkay;
+        prime = q;
+    }
+    else
+        prime = p;
+
+    ret = mp_init_multi(&tmp1, &tmp2, NULL, NULL, NULL, NULL);
+    if (ret != MP_OKAY) goto notOkay;
+
+    /* 4.4,5.5 - Check that prime >= (2^(1/2))(2^((nlen/2)-1))
+     *           This is a comparison against lowerBound */
+    ret = mp_read_unsigned_bin(&tmp1, lower_bound, nlen/16);
+    if (ret != MP_OKAY) goto notOkay;
+    ret = mp_cmp(prime, &tmp1);
+    if (ret == MP_LT) goto exit;
+
+    /* 4.5,5.6 - Check that GCD(p-1, e) == 1 */
+    ret = mp_sub_d(prime, 1, &tmp1);  /* tmp1 = prime-1 */
+    if (ret != MP_OKAY) goto notOkay;
+    ret = mp_gcd(&tmp1, e, &tmp2);  /* tmp2 = gcd(prime-1, e) */
+    if (ret != MP_OKAY) goto notOkay;
+    ret = mp_cmp_d(&tmp2, 1);
+    if (ret != MP_EQ) goto exit; /* e divides p-1 */
+
+    /* 4.5.1,5.6.1 - Check primality of p with 8 rounds of M-R.
+     * mp_prime_is_prime_ex() performs test divisions against the first 256
+     * prime numbers. After that it performs 8 rounds of M-R using random
+     * bases between 2 and n-2.
+     * mp_prime_is_prime() performs the same test divisions and then does
+     * M-R with the first 8 primes. Both functions set isPrime as a
+     * side-effect. */
+    if (rng != NULL)
+        ret = mp_prime_is_prime_ex(prime, 8, isPrime, rng);
+    else
+        ret = mp_prime_is_prime(prime, 8, isPrime);
+    if (ret != MP_OKAY) goto notOkay;
+
+exit:
+    ret = MP_OKAY;
+notOkay:
+    mp_clear(&tmp1);
+    mp_clear(&tmp2);
+    return ret;
+}
+
+
+int wc_CheckProbablePrime_ex(const byte* pRaw, word32 pRawSz,
+                          const byte* qRaw, word32 qRawSz,
+                          const byte* eRaw, word32 eRawSz,
+                          int nlen, int* isPrime, WC_RNG* rng)
+{
+    mp_int p, q, e;
+    mp_int* Q = NULL;
+    int ret;
+
+    if (pRaw == NULL || pRawSz == 0 ||
+        eRaw == NULL || eRawSz == 0 ||
+        isPrime == NULL) {
+
+        return BAD_FUNC_ARG;
+    }
+
+    if ((qRaw != NULL && qRawSz == 0) || (qRaw == NULL && qRawSz != 0))
+        return BAD_FUNC_ARG;
+
+    ret = mp_init_multi(&p, &q, &e, NULL, NULL, NULL);
+
+    if (ret == MP_OKAY)
+        ret = mp_read_unsigned_bin(&p, pRaw, pRawSz);
+
+    if (ret == MP_OKAY) {
+        if (qRaw != NULL) {
+            ret = mp_read_unsigned_bin(&q, qRaw, qRawSz);
+            if (ret == MP_OKAY)
+                Q = &q;
+        }
+    }
+
+    if (ret == MP_OKAY)
+        ret = mp_read_unsigned_bin(&e, eRaw, eRawSz);
+
+    if (ret == MP_OKAY)
+        ret = _CheckProbablePrime(&p, Q, &e, nlen, isPrime, rng);
+
+    ret = (ret == MP_OKAY) ? 0 : PRIME_GEN_E;
+
+    mp_clear(&p);
+    mp_clear(&q);
+    mp_clear(&e);
+
+    return ret;
+}
+
+
+int wc_CheckProbablePrime(const byte* pRaw, word32 pRawSz,
+                          const byte* qRaw, word32 qRawSz,
+                          const byte* eRaw, word32 eRawSz,
+                          int nlen, int* isPrime)
+{
+    return wc_CheckProbablePrime_ex(pRaw, pRawSz, qRaw, qRawSz,
+                          eRaw, eRawSz, nlen, isPrime, NULL);
+}
+
+#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS) && \
+        defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))
+/* Make an RSA key for size bits, with e specified, 65537 is a good e */
+int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng)
+{
+#ifndef WC_NO_RNG
+    mp_int p, q, tmp1, tmp2, tmp3;
+    int err, i, failCount, primeSz, isPrime = 0;
+    byte* buf = NULL;
+
+    if (key == NULL || rng == NULL)
+        return BAD_FUNC_ARG;
+
+    if (!RsaSizeCheck(size))
+        return BAD_FUNC_ARG;
+
+    if (e < 3 || (e & 1) == 0)
+        return BAD_FUNC_ARG;
+
+#if defined(WOLFSSL_CRYPTOCELL)
+
+    return cc310_RSA_GenerateKeyPair(key, size, e);
+
+#endif /*WOLFSSL_CRYPTOCELL*/
+
+#ifdef WOLF_CRYPTO_CB
+    if (key->devId != INVALID_DEVID) {
+        int ret = wc_CryptoCb_MakeRsaKey(key, size, e, rng);
+        if (ret != CRYPTOCB_UNAVAILABLE)
+            return ret;
+        /* fall-through when unavailable */
+    }
+#endif
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) && \
+    defined(WC_ASYNC_ENABLE_RSA_KEYGEN)
+    if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) {
+    #ifdef HAVE_CAVIUM
+        /* TODO: Not implemented */
+    #elif defined(HAVE_INTEL_QA)
+        return IntelQaRsaKeyGen(&key->asyncDev, key, size, e, rng);
+    #else
+        if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_RSA_MAKE)) {
+            WC_ASYNC_TEST* testDev = &key->asyncDev.test;
+            testDev->rsaMake.rng = rng;
+            testDev->rsaMake.key = key;
+            testDev->rsaMake.size = size;
+            testDev->rsaMake.e = e;
+            return WC_PENDING_E;
+        }
+    #endif
+    }
+#endif
+
+    err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL);
+
+    if (err == MP_OKAY)
+        err = mp_set_int(&tmp3, e);
+
+    /* The failCount value comes from NIST FIPS 186-4, section B.3.3,
+     * process steps 4.7 and 5.8. */
+    failCount = 5 * (size / 2);
+    primeSz = size / 16; /* size is the size of n in bits.
+                            primeSz is in bytes. */
+
+    /* allocate buffer to work with */
+    if (err == MP_OKAY) {
+        buf = (byte*)XMALLOC(primeSz, key->heap, DYNAMIC_TYPE_RSA);
+        if (buf == NULL)
+            err = MEMORY_E;
+    }
+
+    /* make p */
+    if (err == MP_OKAY) {
+        isPrime = 0;
+        i = 0;
+        do {
+#ifdef SHOW_GEN
+            printf(".");
+            fflush(stdout);
+#endif
+            /* generate value */
+            err = wc_RNG_GenerateBlock(rng, buf, primeSz);
+            if (err == 0) {
+                /* prime lower bound has the MSB set, set it in candidate */
+                buf[0] |= 0x80;
+                /* make candidate odd */
+                buf[primeSz-1] |= 0x01;
+                /* load value */
+                err = mp_read_unsigned_bin(&p, buf, primeSz);
+            }
+
+            if (err == MP_OKAY)
+                err = _CheckProbablePrime(&p, NULL, &tmp3, size, &isPrime, rng);
+
+#ifdef HAVE_FIPS
+            i++;
+#else
+            /* Keep the old retry behavior in non-FIPS build. */
+            (void)i;
+#endif
+        } while (err == MP_OKAY && !isPrime && i < failCount);
+    }
+
+    if (err == MP_OKAY && !isPrime)
+        err = PRIME_GEN_E;
+
+    /* make q */
+    if (err == MP_OKAY) {
+        isPrime = 0;
+        i = 0;
+        do {
+#ifdef SHOW_GEN
+            printf(".");
+            fflush(stdout);
+#endif
+            /* generate value */
+            err = wc_RNG_GenerateBlock(rng, buf, primeSz);
+            if (err == 0) {
+                /* prime lower bound has the MSB set, set it in candidate */
+                buf[0] |= 0x80;
+                /* make candidate odd */
+                buf[primeSz-1] |= 0x01;
+                /* load value */
+                err = mp_read_unsigned_bin(&q, buf, primeSz);
+            }
+
+            if (err == MP_OKAY)
+                err = _CheckProbablePrime(&p, &q, &tmp3, size, &isPrime, rng);
+
+#ifdef HAVE_FIPS
+            i++;
+#else
+            /* Keep the old retry behavior in non-FIPS build. */
+            (void)i;
+#endif
+        } while (err == MP_OKAY && !isPrime && i < failCount);
+    }
+
+    if (err == MP_OKAY && !isPrime)
+        err = PRIME_GEN_E;
+
+    if (buf) {
+        ForceZero(buf, primeSz);
+        XFREE(buf, key->heap, DYNAMIC_TYPE_RSA);
+    }
+
+    if (err == MP_OKAY && mp_cmp(&p, &q) < 0) {
+        err = mp_copy(&p, &tmp1);
+        if (err == MP_OKAY)
+            err = mp_copy(&q, &p);
+        if (err == MP_OKAY)
+            mp_copy(&tmp1, &q);
+    }
+
+    /* Setup RsaKey buffers */
+    if (err == MP_OKAY)
+        err = mp_init_multi(&key->n, &key->e, &key->d, &key->p, &key->q, NULL);
+    if (err == MP_OKAY)
+        err = mp_init_multi(&key->dP, &key->dQ, &key->u, NULL, NULL, NULL);
+
+    /* Software Key Calculation */
+    if (err == MP_OKAY)                /* tmp1 = p-1 */
+        err = mp_sub_d(&p, 1, &tmp1);
+    if (err == MP_OKAY)                /* tmp2 = q-1 */
+        err = mp_sub_d(&q, 1, &tmp2);
+#ifdef WC_RSA_BLINDING
+    if (err == MP_OKAY)                /* tmp3 = order of n */
+        err = mp_mul(&tmp1, &tmp2, &tmp3);
+#else
+    if (err == MP_OKAY)                /* tmp3 = lcm(p-1, q-1), last loop */
+        err = mp_lcm(&tmp1, &tmp2, &tmp3);
+#endif
+    /* make key */
+    if (err == MP_OKAY)                /* key->e = e */
+        err = mp_set_int(&key->e, (mp_digit)e);
+#ifdef WC_RSA_BLINDING
+    /* Blind the inverse operation with a value that is invertable */
+    if (err == MP_OKAY) {
+        do {
+            err = mp_rand(&key->p, get_digit_count(&tmp3), rng);
+            if (err == MP_OKAY)
+                err = mp_set_bit(&key->p, 0);
+            if (err == MP_OKAY)
+                err = mp_set_bit(&key->p, size - 1);
+            if (err == MP_OKAY)
+                err = mp_gcd(&key->p, &tmp3, &key->q);
+        }
+        while ((err == MP_OKAY) && !mp_isone(&key->q));
+    }
+    if (err == MP_OKAY)
+        err = mp_mul_d(&key->p, (mp_digit)e, &key->e);
+#endif
+    if (err == MP_OKAY)                /* key->d = 1/e mod lcm(p-1, q-1) */
+        err = mp_invmod(&key->e, &tmp3, &key->d);
+#ifdef WC_RSA_BLINDING
+    /* Take off blinding from d and reset e */
+    if (err == MP_OKAY)
+        err = mp_mulmod(&key->d, &key->p, &tmp3, &key->d);
+    if (err == MP_OKAY)
+        err = mp_set_int(&key->e, (mp_digit)e);
+#endif
+    if (err == MP_OKAY)                /* key->n = pq */
+        err = mp_mul(&p, &q, &key->n);
+    if (err == MP_OKAY)                /* key->dP = d mod(p-1) */
+        err = mp_mod(&key->d, &tmp1, &key->dP);
+    if (err == MP_OKAY)                /* key->dQ = d mod(q-1) */
+        err = mp_mod(&key->d, &tmp2, &key->dQ);
+#ifdef WOLFSSL_MP_INVMOD_CONSTANT_TIME
+    if (err == MP_OKAY)                /* key->u = 1/q mod p */
+        err = mp_invmod(&q, &p, &key->u);
+#else
+    if (err == MP_OKAY)
+        err = mp_sub_d(&p, 2, &tmp3);
+    if (err == MP_OKAY)                /* key->u = 1/q mod p = q^p-2 mod p */
+        err = mp_exptmod(&q, &tmp3 , &p, &key->u);
+#endif
+    if (err == MP_OKAY)
+        err = mp_copy(&p, &key->p);
+    if (err == MP_OKAY)
+        err = mp_copy(&q, &key->q);
+
+#ifdef HAVE_WOLF_BIGINT
+    /* make sure raw unsigned bin version is available */
+    if (err == MP_OKAY)
+         err = wc_mp_to_bigint(&key->n, &key->n.raw);
+    if (err == MP_OKAY)
+         err = wc_mp_to_bigint(&key->e, &key->e.raw);
+    if (err == MP_OKAY)
+         err = wc_mp_to_bigint(&key->d, &key->d.raw);
+    if (err == MP_OKAY)
+         err = wc_mp_to_bigint(&key->p, &key->p.raw);
+    if (err == MP_OKAY)
+         err = wc_mp_to_bigint(&key->q, &key->q.raw);
+    if (err == MP_OKAY)
+         err = wc_mp_to_bigint(&key->dP, &key->dP.raw);
+    if (err == MP_OKAY)
+         err = wc_mp_to_bigint(&key->dQ, &key->dQ.raw);
+    if (err == MP_OKAY)
+         err = wc_mp_to_bigint(&key->u, &key->u.raw);
+#endif
+
+    if (err == MP_OKAY)
+        key->type = RSA_PRIVATE;
+
+    mp_clear(&tmp1);
+    mp_clear(&tmp2);
+    mp_clear(&tmp3);
+    mp_clear(&p);
+    mp_clear(&q);
+
+#if defined(WOLFSSL_KEY_GEN) && !defined(WOLFSSL_NO_RSA_KEY_CHECK)
+    /* Perform the pair-wise consistency test on the new key. */
+    if (err == 0)
+        err = wc_CheckRsaKey(key);
+#endif
+
+    if (err != 0) {
+        wc_FreeRsaKey(key);
+        return err;
+    }
+
+#if defined(WOLFSSL_XILINX_CRYPT) || defined(WOLFSSL_CRYPTOCELL)
+    if (wc_InitRsaHw(key) != 0) {
+        return BAD_STATE_E;
+    }
+#endif
+    return 0;
+#else
+    return NOT_COMPILED_IN;
+#endif
+}
+#endif /* !FIPS || FIPS_VER >= 2 */
+#endif /* WOLFSSL_KEY_GEN */
+
+
+#ifdef WC_RSA_BLINDING
+int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng)
+{
+    if (key == NULL)
+        return BAD_FUNC_ARG;
+
+    key->rng = rng;
+
+    return 0;
+}
+#endif /* WC_RSA_BLINDING */
+
+#ifdef WC_RSA_NONBLOCK
+int wc_RsaSetNonBlock(RsaKey* key, RsaNb* nb)
+{
+    if (key == NULL)
+        return BAD_FUNC_ARG;
+
+    if (nb) {
+        XMEMSET(nb, 0, sizeof(RsaNb));
+    }
+
+    /* Allow nb == NULL to clear non-block mode */
+    key->nb = nb;
+
+    return 0;
+}
+#ifdef WC_RSA_NONBLOCK_TIME
+int wc_RsaSetNonBlockTime(RsaKey* key, word32 maxBlockUs, word32 cpuMHz)
+{
+    if (key == NULL || key->nb == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* calculate maximum number of instructions to block */
+    key->nb->exptmod.maxBlockInst = cpuMHz * maxBlockUs;
+
+    return 0;
+}
+#endif /* WC_RSA_NONBLOCK_TIME */
+#endif /* WC_RSA_NONBLOCK */
+
+#endif /* NO_RSA */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/sha.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/sha.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/sha.c	(revision 453)
@@ -0,0 +1,882 @@
+/* sha.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#if !defined(NO_SHA)
+
+#if defined(HAVE_FIPS) && \
+	defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
+
+    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
+    #define FIPS_NO_WRAPPERS
+
+    #ifdef USE_WINDOWS_API
+        #pragma code_seg(".fipsA$j")
+        #pragma const_seg(".fipsB$j")
+    #endif
+#endif
+
+#include <wolfssl/wolfcrypt/sha.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#include <wolfssl/wolfcrypt/hash.h>
+
+#ifdef WOLF_CRYPTO_CB
+    #include <wolfssl/wolfcrypt/cryptocb.h>
+#endif
+
+/* fips wrapper calls, user can call direct */
+#if defined(HAVE_FIPS) && \
+    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
+
+    int wc_InitSha(wc_Sha* sha)
+    {
+        if (sha == NULL) {
+            return BAD_FUNC_ARG;
+        }
+        return InitSha_fips(sha);
+    }
+    int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId)
+    {
+        (void)heap;
+        (void)devId;
+        if (sha == NULL) {
+            return BAD_FUNC_ARG;
+        }
+        return InitSha_fips(sha);
+    }
+
+    int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len)
+    {
+        if (sha == NULL || (data == NULL && len > 0)) {
+            return BAD_FUNC_ARG;
+        }
+        return ShaUpdate_fips(sha, data, len);
+    }
+
+    int wc_ShaFinal(wc_Sha* sha, byte* out)
+    {
+        if (sha == NULL || out == NULL) {
+            return BAD_FUNC_ARG;
+        }
+        return ShaFinal_fips(sha,out);
+    }
+    void wc_ShaFree(wc_Sha* sha)
+    {
+        (void)sha;
+        /* Not supported in FIPS */
+    }
+
+#else /* else build without fips, or for FIPS v2 */
+
+
+#if defined(WOLFSSL_TI_HASH)
+    /* #include <wolfcrypt/src/port/ti/ti-hash.c> included by wc_port.c */
+
+#else
+
+#include <wolfssl/wolfcrypt/logging.h>
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+
+/* Hardware Acceleration */
+#if defined(WOLFSSL_PIC32MZ_HASH)
+    #include <wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h>
+
+#elif defined(STM32_HASH)
+
+    /* Supports CubeMX HAL or Standard Peripheral Library */
+    int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId)
+    {
+        if (sha == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        (void)devId;
+        (void)heap;
+
+        wc_Stm32_Hash_Init(&sha->stmCtx);
+
+        return 0;
+    }
+
+    int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len)
+    {
+        int ret;
+
+        if (sha == NULL || (data == NULL && len > 0)) {
+            return BAD_FUNC_ARG;
+        }
+
+        ret = wolfSSL_CryptHwMutexLock();
+        if (ret == 0) {
+            ret = wc_Stm32_Hash_Update(&sha->stmCtx, HASH_AlgoSelection_SHA1,
+                data, len);
+            wolfSSL_CryptHwMutexUnLock();
+        }
+        return ret;
+    }
+
+    int wc_ShaFinal(wc_Sha* sha, byte* hash)
+    {
+        int ret;
+
+        if (sha == NULL || hash == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        ret = wolfSSL_CryptHwMutexLock();
+        if (ret == 0) {
+            ret = wc_Stm32_Hash_Final(&sha->stmCtx, HASH_AlgoSelection_SHA1,
+                hash, WC_SHA_DIGEST_SIZE);
+            wolfSSL_CryptHwMutexUnLock();
+        }
+
+        (void)wc_InitSha(sha);  /* reset state */
+
+        return ret;
+    }
+
+
+#elif defined(FREESCALE_LTC_SHA)
+
+    #include "fsl_ltc.h"
+    int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId)
+    {
+        if (sha == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        (void)devId;
+        (void)heap;
+
+        LTC_HASH_Init(LTC_BASE, &sha->ctx, kLTC_Sha1, NULL, 0);
+        return 0;
+    }
+
+    int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len)
+    {
+        LTC_HASH_Update(&sha->ctx, data, len);
+        return 0;
+    }
+
+    int wc_ShaFinal(wc_Sha* sha, byte* hash)
+    {
+        uint32_t hashlen = WC_SHA_DIGEST_SIZE;
+        LTC_HASH_Finish(&sha->ctx, hash, &hashlen);
+        return wc_InitSha(sha);  /* reset state */
+    }
+
+
+#elif defined(FREESCALE_MMCAU_SHA)
+
+    #ifdef FREESCALE_MMCAU_CLASSIC_SHA
+        #include "cau_api.h"
+    #else
+        #include "fsl_mmcau.h"
+    #endif
+
+    #define USE_SHA_SOFTWARE_IMPL /* Only for API's, actual transform is here */
+
+    #define XTRANSFORM(S,B)       Transform((S),(B))
+    #define XTRANSFORM_LEN(S,B,L) Transform_Len((S),(B),(L))
+
+    #ifndef WC_HASH_DATA_ALIGNMENT
+        /* these hardware API's require 4 byte (word32) alignment */
+        #define WC_HASH_DATA_ALIGNMENT 4
+    #endif
+
+    static int InitSha(wc_Sha* sha)
+    {
+        int ret = 0;
+        ret = wolfSSL_CryptHwMutexLock();
+        if (ret != 0) {
+            return ret;
+        }
+    #ifdef FREESCALE_MMCAU_CLASSIC_SHA
+        cau_sha1_initialize_output(sha->digest);
+    #else
+        MMCAU_SHA1_InitializeOutput((uint32_t*)sha->digest);
+    #endif
+        wolfSSL_CryptHwMutexUnLock();
+
+        sha->buffLen = 0;
+        sha->loLen   = 0;
+        sha->hiLen   = 0;
+
+        return ret;
+    }
+
+    static int Transform(wc_Sha* sha, const byte* data)
+    {
+        int ret = wolfSSL_CryptHwMutexLock();
+        if (ret == 0) {
+    #ifdef FREESCALE_MMCAU_CLASSIC_SHA
+            cau_sha1_hash_n((byte*)data, 1, sha->digest);
+    #else
+            MMCAU_SHA1_HashN((byte*)data, 1, (uint32_t*)sha->digest);
+    #endif
+            wolfSSL_CryptHwMutexUnLock();
+        }
+        return ret;
+    }
+
+    static int Transform_Len(wc_Sha* sha, const byte* data, word32 len)
+    {
+        int ret = wolfSSL_CryptHwMutexLock();
+        if (ret == 0) {
+        #if defined(WC_HASH_DATA_ALIGNMENT) && WC_HASH_DATA_ALIGNMENT > 0
+            if ((size_t)data % WC_HASH_DATA_ALIGNMENT) {
+                /* data pointer is NOT aligned,
+                 * so copy and perform one block at a time */
+                byte* local = (byte*)sha->buffer;
+                while (len >= WC_SHA_BLOCK_SIZE) {
+                    XMEMCPY(local, data, WC_SHA_BLOCK_SIZE);
+                #ifdef FREESCALE_MMCAU_CLASSIC_SHA
+                    cau_sha1_hash_n(local, 1, sha->digest);
+                #else
+                    MMCAU_SHA1_HashN(local, 1, sha->digest);
+                #endif
+                    data += WC_SHA_BLOCK_SIZE;
+                    len  -= WC_SHA_BLOCK_SIZE;
+                }
+            }
+            else
+        #endif
+            {
+    #ifdef FREESCALE_MMCAU_CLASSIC_SHA
+            cau_sha1_hash_n((byte*)data, len/WC_SHA_BLOCK_SIZE, sha->digest);
+    #else
+            MMCAU_SHA1_HashN((byte*)data, len/WC_SHA_BLOCK_SIZE,
+                (uint32_t*)sha->digest);
+    #endif
+            }
+            wolfSSL_CryptHwMutexUnLock();
+        }
+        return ret;
+    }
+
+#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
+    /* wolfcrypt/src/port/caam/caam_sha.c */
+
+#elif defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+     !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+
+    #include "wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h"
+
+    #define USE_SHA_SOFTWARE_IMPL
+
+    static int InitSha(wc_Sha* sha)
+    {
+        int ret = 0;
+
+        sha->digest[0] = 0x67452301L;
+        sha->digest[1] = 0xEFCDAB89L;
+        sha->digest[2] = 0x98BADCFEL;
+        sha->digest[3] = 0x10325476L;
+        sha->digest[4] = 0xC3D2E1F0L;
+
+        sha->buffLen = 0;
+        sha->loLen   = 0;
+        sha->hiLen   = 0;
+
+        /* always start firstblock = 1 when using hw engine */
+        sha->ctx.isfirstblock = 1;
+        sha->ctx.sha_type = SHA1;
+        if(sha->ctx.mode == ESP32_SHA_HW){
+            /* release hw engine */
+            esp_sha_hw_unlock();
+        }
+        /* always set mode as INIT
+        *  whether using HW or SW is determined at first call of update()
+        */
+        sha->ctx.mode = ESP32_SHA_INIT;
+
+        return ret;
+    }
+
+#elif defined(WOLFSSL_RENESAS_TSIP_CRYPT) && \
+    !defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH)
+
+    /* implemented in wolfcrypt/src/port/Renesas/renesas_tsip_sha.c */
+
+#else
+    /* Software implementation */
+    #define USE_SHA_SOFTWARE_IMPL
+
+    static int InitSha(wc_Sha* sha)
+    {
+        int ret = 0;
+
+        sha->digest[0] = 0x67452301L;
+        sha->digest[1] = 0xEFCDAB89L;
+        sha->digest[2] = 0x98BADCFEL;
+        sha->digest[3] = 0x10325476L;
+        sha->digest[4] = 0xC3D2E1F0L;
+
+        sha->buffLen = 0;
+        sha->loLen   = 0;
+        sha->hiLen   = 0;
+    #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+        sha->flags = 0;
+    #endif
+
+        return ret;
+    }
+#endif /* End Hardware Acceleration */
+
+/* Software implementation */
+#ifdef USE_SHA_SOFTWARE_IMPL
+
+static WC_INLINE void AddLength(wc_Sha* sha, word32 len)
+{
+    word32 tmp = sha->loLen;
+    if ((sha->loLen += len) < tmp)
+        sha->hiLen++;                       /* carry low to high */
+}
+
+/* Check if custom wc_Sha transform is used */
+#ifndef XTRANSFORM
+    #define XTRANSFORM(S,B)   Transform((S),(B))
+
+    #define blk0(i) (W[i] = *((word32*)&data[i*sizeof(word32)]))
+    #define blk1(i) (W[(i)&15] = \
+        rotlFixed(W[((i)+13)&15]^W[((i)+8)&15]^W[((i)+2)&15]^W[(i)&15],1))
+
+    #define f1(x,y,z) ((z)^((x) &((y)^(z))))
+    #define f2(x,y,z) ((x)^(y)^(z))
+    #define f3(x,y,z) (((x)&(y))|((z)&((x)|(y))))
+    #define f4(x,y,z) ((x)^(y)^(z))
+
+    #ifdef WOLFSSL_NUCLEUS_1_2
+        /* nucleus.h also defines R1-R4 */
+        #undef R1
+        #undef R2
+        #undef R3
+        #undef R4
+    #endif
+
+    /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+    #define R0(v,w,x,y,z,i) (z)+= f1((w),(x),(y)) + blk0((i)) + 0x5A827999+ \
+        rotlFixed((v),5); (w) = rotlFixed((w),30);
+    #define R1(v,w,x,y,z,i) (z)+= f1((w),(x),(y)) + blk1((i)) + 0x5A827999+ \
+        rotlFixed((v),5); (w) = rotlFixed((w),30);
+    #define R2(v,w,x,y,z,i) (z)+= f2((w),(x),(y)) + blk1((i)) + 0x6ED9EBA1+ \
+        rotlFixed((v),5); (w) = rotlFixed((w),30);
+    #define R3(v,w,x,y,z,i) (z)+= f3((w),(x),(y)) + blk1((i)) + 0x8F1BBCDC+ \
+        rotlFixed((v),5); (w) = rotlFixed((w),30);
+    #define R4(v,w,x,y,z,i) (z)+= f4((w),(x),(y)) + blk1((i)) + 0xCA62C1D6+ \
+        rotlFixed((v),5); (w) = rotlFixed((w),30);
+
+    static int Transform(wc_Sha* sha, const byte* data)
+    {
+        word32 W[WC_SHA_BLOCK_SIZE / sizeof(word32)];
+
+        /* Copy context->state[] to working vars */
+        word32 a = sha->digest[0];
+        word32 b = sha->digest[1];
+        word32 c = sha->digest[2];
+        word32 d = sha->digest[3];
+        word32 e = sha->digest[4];
+
+    #ifdef USE_SLOW_SHA
+        word32 t, i;
+
+        for (i = 0; i < 16; i++) {
+            R0(a, b, c, d, e, i);
+            t = e; e = d; d = c; c = b; b = a; a = t;
+        }
+
+        for (; i < 20; i++) {
+            R1(a, b, c, d, e, i);
+            t = e; e = d; d = c; c = b; b = a; a = t;
+        }
+
+        for (; i < 40; i++) {
+            R2(a, b, c, d, e, i);
+            t = e; e = d; d = c; c = b; b = a; a = t;
+        }
+
+        for (; i < 60; i++) {
+            R3(a, b, c, d, e, i);
+            t = e; e = d; d = c; c = b; b = a; a = t;
+        }
+
+        for (; i < 80; i++) {
+            R4(a, b, c, d, e, i);
+            t = e; e = d; d = c; c = b; b = a; a = t;
+        }
+    #else
+        /* nearly 1 K bigger in code size but 25% faster */
+        /* 4 rounds of 20 operations each. Loop unrolled. */
+        R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+        R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+        R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+        R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+
+        R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+
+        R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+        R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+        R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+        R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+        R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+
+        R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+        R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+        R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+        R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+        R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+
+        R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+        R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+        R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+        R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+        R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+    #endif
+
+        /* Add the working vars back into digest state[] */
+        sha->digest[0] += a;
+        sha->digest[1] += b;
+        sha->digest[2] += c;
+        sha->digest[3] += d;
+        sha->digest[4] += e;
+
+        (void)data; /* Not used */
+
+        return 0;
+    }
+#endif /* !USE_CUSTOM_SHA_TRANSFORM */
+
+
+int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId)
+{
+    int ret = 0;
+
+    if (sha == NULL)
+        return BAD_FUNC_ARG;
+
+    sha->heap = heap;
+#ifdef WOLF_CRYPTO_CB
+    sha->devId = devId;
+#endif
+
+#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+    sha->ctx.mode = ESP32_SHA_INIT;
+    sha->ctx.isfirstblock = 1;
+#endif
+    ret = InitSha(sha);
+    if (ret != 0)
+        return ret;
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA)
+    ret = wolfAsync_DevCtxInit(&sha->asyncDev, WOLFSSL_ASYNC_MARKER_SHA,
+                                                            sha->heap, devId);
+#else
+    (void)devId;
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    return ret;
+}
+
+/* do block size increments/updates */
+int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len)
+{
+    int ret = 0;
+    word32 blocksLen;
+    byte* local;
+
+    if (sha == NULL || (data == NULL && len > 0)) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef WOLF_CRYPTO_CB
+    if (sha->devId != INVALID_DEVID) {
+        ret = wc_CryptoCb_ShaHash(sha, data, len, NULL);
+        if (ret != CRYPTOCB_UNAVAILABLE)
+            return ret;
+        ret = 0; /* reset ret */
+        /* fall-through when unavailable */
+    }
+#endif
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA)
+    if (sha->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA) {
+    #if defined(HAVE_INTEL_QA)
+        return IntelQaSymSha(&sha->asyncDev, NULL, data, len);
+    #endif
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    /* check that internal buffLen is valid */
+    if (sha->buffLen >= WC_SHA_BLOCK_SIZE)
+        return BUFFER_E;
+
+    if (data == NULL && len == 0) {
+        /* valid, but do nothing */
+        return 0;
+    }
+
+    /* add length for final */
+    AddLength(sha, len);
+
+    local = (byte*)sha->buffer;
+
+    /* process any remainder from previous operation */
+    if (sha->buffLen > 0) {
+        blocksLen = min(len, WC_SHA_BLOCK_SIZE - sha->buffLen);
+        XMEMCPY(&local[sha->buffLen], data, blocksLen);
+
+        sha->buffLen += blocksLen;
+        data         += blocksLen;
+        len          -= blocksLen;
+
+        if (sha->buffLen == WC_SHA_BLOCK_SIZE) {
+        #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
+            ByteReverseWords(sha->buffer, sha->buffer, WC_SHA_BLOCK_SIZE);
+        #endif
+
+        #if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+            !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+            if (sha->ctx.mode == ESP32_SHA_INIT) {
+                esp_sha_try_hw_lock(&sha->ctx);
+            }
+            if (sha->ctx.mode == ESP32_SHA_SW) {
+                ret = XTRANSFORM(sha, (const byte*)local);
+            } else {
+                esp_sha_process(sha, (const byte*)local);
+            }
+        #else
+            ret = XTRANSFORM(sha, (const byte*)local);
+        #endif
+            if (ret != 0)
+                return ret;
+
+            sha->buffLen = 0;
+        }
+    }
+
+    /* process blocks */
+#ifdef XTRANSFORM_LEN
+    /* get number of blocks */
+    /* 64-1 = 0x3F (~ Inverted = 0xFFFFFFC0) */
+    /* len (masked by 0xFFFFFFC0) returns block aligned length */
+    blocksLen = len & ~(WC_SHA_BLOCK_SIZE-1);
+    if (blocksLen > 0) {
+        /* Byte reversal performed in function if required. */
+        XTRANSFORM_LEN(sha, data, blocksLen);
+        data += blocksLen;
+        len  -= blocksLen;
+    }
+#else
+    while (len >= WC_SHA_BLOCK_SIZE) {
+        word32* local32 = sha->buffer;
+        /* optimization to avoid memcpy if data pointer is properly aligned */
+        /* Little Endian requires byte swap, so can't use data directly */
+    #if defined(WC_HASH_DATA_ALIGNMENT) && !defined(LITTLE_ENDIAN_ORDER)
+        if (((size_t)data % WC_HASH_DATA_ALIGNMENT) == 0) {
+            local32 = (word32*)data;
+        }
+        else
+    #endif
+        {
+            XMEMCPY(local32, data, WC_SHA_BLOCK_SIZE);
+        }
+
+        data += WC_SHA_BLOCK_SIZE;
+        len  -= WC_SHA_BLOCK_SIZE;
+
+    #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
+        ByteReverseWords(local32, local32, WC_SHA_BLOCK_SIZE);
+    #endif
+
+    #if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+        !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+        if (sha->ctx.mode == ESP32_SHA_INIT){
+            esp_sha_try_hw_lock(&sha->ctx);
+        }
+        if (sha->ctx.mode == ESP32_SHA_SW){
+            ret = XTRANSFORM(sha, (const byte*)local32);
+        } else {
+            esp_sha_process(sha, (const byte*)local32);
+        }
+    #else
+        ret = XTRANSFORM(sha, (const byte*)local32);
+    #endif
+    }
+#endif /* XTRANSFORM_LEN */
+
+    /* save remainder */
+    if (len > 0) {
+        XMEMCPY(local, data, len);
+        sha->buffLen = len;
+    }
+
+    return ret;
+}
+
+int wc_ShaFinalRaw(wc_Sha* sha, byte* hash)
+{
+#ifdef LITTLE_ENDIAN_ORDER
+    word32 digest[WC_SHA_DIGEST_SIZE / sizeof(word32)];
+#endif
+
+    if (sha == NULL || hash == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef LITTLE_ENDIAN_ORDER
+    ByteReverseWords((word32*)digest, (word32*)sha->digest, WC_SHA_DIGEST_SIZE);
+    XMEMCPY(hash, digest, WC_SHA_DIGEST_SIZE);
+#else
+    XMEMCPY(hash, sha->digest, WC_SHA_DIGEST_SIZE);
+#endif
+
+    return 0;
+}
+
+int wc_ShaFinal(wc_Sha* sha, byte* hash)
+{
+    int ret;
+    byte* local;
+
+    if (sha == NULL || hash == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    local = (byte*)sha->buffer;
+
+#ifdef WOLF_CRYPTO_CB
+    if (sha->devId != INVALID_DEVID) {
+        ret = wc_CryptoCb_ShaHash(sha, NULL, 0, hash);
+        if (ret != CRYPTOCB_UNAVAILABLE)
+            return ret;
+        ret = 0; /* reset ret */
+        /* fall-through when unavailable */
+    }
+#endif
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA)
+    if (sha->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA) {
+    #if defined(HAVE_INTEL_QA)
+        return IntelQaSymSha(&sha->asyncDev, hash, NULL, WC_SHA_DIGEST_SIZE);
+    #endif
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    local[sha->buffLen++] = 0x80;  /* add 1 */
+
+    /* pad with zeros */
+    if (sha->buffLen > WC_SHA_PAD_SIZE) {
+        XMEMSET(&local[sha->buffLen], 0, WC_SHA_BLOCK_SIZE - sha->buffLen);
+        sha->buffLen += WC_SHA_BLOCK_SIZE - sha->buffLen;
+
+    #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
+        ByteReverseWords(sha->buffer, sha->buffer, WC_SHA_BLOCK_SIZE);
+    #endif
+
+    #if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+        !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+        if (sha->ctx.mode == ESP32_SHA_INIT) {
+            esp_sha_try_hw_lock(&sha->ctx);
+        }
+        if (sha->ctx.mode == ESP32_SHA_SW) {
+            ret = XTRANSFORM(sha, (const byte*)local);
+        } else {
+            ret = esp_sha_process(sha, (const byte*)local);
+        }
+    #else
+        ret = XTRANSFORM(sha, (const byte*)local);
+    #endif
+        if (ret != 0)
+            return ret;
+
+        sha->buffLen = 0;
+    }
+    XMEMSET(&local[sha->buffLen], 0, WC_SHA_PAD_SIZE - sha->buffLen);
+
+#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
+    ByteReverseWords(sha->buffer, sha->buffer, WC_SHA_BLOCK_SIZE);
+#endif
+
+    /* store lengths */
+    /* put lengths in bits */
+    sha->hiLen = (sha->loLen >> (8*sizeof(sha->loLen) - 3)) + (sha->hiLen << 3);
+    sha->loLen = sha->loLen << 3;
+
+    /* ! length ordering dependent on digest endian type ! */
+    XMEMCPY(&local[WC_SHA_PAD_SIZE], &sha->hiLen, sizeof(word32));
+    XMEMCPY(&local[WC_SHA_PAD_SIZE + sizeof(word32)], &sha->loLen, sizeof(word32));
+
+#if defined(FREESCALE_MMCAU_SHA)
+    /* Kinetis requires only these bytes reversed */
+    ByteReverseWords(&sha->buffer[WC_SHA_PAD_SIZE/sizeof(word32)],
+                     &sha->buffer[WC_SHA_PAD_SIZE/sizeof(word32)],
+                     2 * sizeof(word32));
+#endif
+
+#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+    if (sha->ctx.mode == ESP32_SHA_INIT) {
+        esp_sha_try_hw_lock(&sha->ctx);
+    }
+    if (sha->ctx.mode == ESP32_SHA_SW) {
+        ret = XTRANSFORM(sha, (const byte*)local);
+    } else {
+        ret = esp_sha_digest_process(sha, 1);
+    }
+#else
+    ret = XTRANSFORM(sha, (const byte*)local);
+#endif
+
+#ifdef LITTLE_ENDIAN_ORDER
+    ByteReverseWords(sha->digest, sha->digest, WC_SHA_DIGEST_SIZE);
+#endif
+
+    XMEMCPY(hash, sha->digest, WC_SHA_DIGEST_SIZE);
+
+    (void)InitSha(sha); /* reset state */
+
+    return ret;
+}
+
+#endif /* USE_SHA_SOFTWARE_IMPL */
+
+
+int wc_InitSha(wc_Sha* sha)
+{
+    return wc_InitSha_ex(sha, NULL, INVALID_DEVID);
+}
+
+void wc_ShaFree(wc_Sha* sha)
+{
+    if (sha == NULL)
+        return;
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA)
+    wolfAsync_DevCtxFree(&sha->asyncDev, WOLFSSL_ASYNC_MARKER_SHA);
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+#ifdef WOLFSSL_PIC32MZ_HASH
+    wc_ShaPic32Free(sha);
+#endif
+#if (defined(WOLFSSL_RENESAS_TSIP_CRYPT) && \
+    !defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH))
+    if (sha->msg != NULL) {
+        XFREE(sha->msg, sha->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        sha->msg = NULL;
+    }
+#endif
+}
+
+#endif /* !WOLFSSL_TI_HASH */
+#endif /* HAVE_FIPS */
+
+#ifndef WOLFSSL_TI_HASH
+#if !defined(WOLFSSL_RENESAS_TSIP_CRYPT) || \
+    defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH)
+int wc_ShaGetHash(wc_Sha* sha, byte* hash)
+{
+    int ret;
+    wc_Sha tmpSha;
+
+    if (sha == NULL || hash == NULL)
+        return BAD_FUNC_ARG;
+
+#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+    if(sha->ctx.mode == ESP32_SHA_INIT){
+        esp_sha_try_hw_lock(&sha->ctx);
+    }
+    if(sha->ctx.mode != ESP32_SHA_SW)
+        esp_sha_digest_process(sha, 0);
+#endif
+
+    ret = wc_ShaCopy(sha, &tmpSha);
+    if (ret == 0) {
+       ret = wc_ShaFinal(&tmpSha, hash);
+#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+        sha->ctx.mode = ESP32_SHA_SW;
+#endif
+
+
+    }
+    return ret;
+}
+
+int wc_ShaCopy(wc_Sha* src, wc_Sha* dst)
+{
+    int ret = 0;
+
+    if (src == NULL || dst == NULL)
+        return BAD_FUNC_ARG;
+
+    XMEMCPY(dst, src, sizeof(wc_Sha));
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev);
+#endif
+#ifdef WOLFSSL_PIC32MZ_HASH
+    ret = wc_Pic32HashCopy(&src->cache, &dst->cache);
+#endif
+#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+     dst->ctx.mode = src->ctx.mode;
+     dst->ctx.isfirstblock = src->ctx.isfirstblock;
+     dst->ctx.sha_type = src->ctx.sha_type;
+#endif
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+     dst->flags |= WC_HASH_FLAG_ISCOPY;
+#endif
+    return ret;
+}
+#endif /* defined(WOLFSSL_RENESAS_TSIP_CRYPT) ... */
+#endif /* !WOLFSSL_TI_HASH */
+
+
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+int wc_ShaSetFlags(wc_Sha* sha, word32 flags)
+{
+    if (sha) {
+        sha->flags = flags;
+    }
+    return 0;
+}
+int wc_ShaGetFlags(wc_Sha* sha, word32* flags)
+{
+    if (sha && flags) {
+        *flags = sha->flags;
+    }
+    return 0;
+}
+#endif
+
+#endif /* !NO_SHA */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/sha256.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/sha256.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/sha256.c	(revision 453)
@@ -0,0 +1,1644 @@
+/* sha256.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+/*
+ * SHA256 Build Options:
+ * USE_SLOW_SHA256:            Reduces code size by not partially unrolling
+                                (~2KB smaller and ~25% slower) (default OFF)
+ * WOLFSSL_SHA256_BY_SPEC:     Uses the Ch/Maj based on SHA256 specification
+                                (default ON)
+ * WOLFSSL_SHA256_ALT_CH_MAJ:  Alternate Ch/Maj that is easier for compilers to
+                                optimize and recognize as SHA256 (default OFF)
+ * SHA256_MANY_REGISTERS:      A SHA256 version that keeps all data in registers
+                                and partial unrolled (default OFF)
+ */
+
+/* Default SHA256 to use Ch/Maj based on specification */
+#if !defined(WOLFSSL_SHA256_BY_SPEC) && !defined(WOLFSSL_SHA256_ALT_CH_MAJ)
+    #define WOLFSSL_SHA256_BY_SPEC
+#endif
+
+
+#if !defined(NO_SHA256) && !defined(WOLFSSL_ARMASM)
+
+#if defined(HAVE_FIPS) && \
+	defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
+
+    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
+    #define FIPS_NO_WRAPPERS
+
+    #ifdef USE_WINDOWS_API
+        #pragma code_seg(".fipsA$d")
+        #pragma const_seg(".fipsB$d")
+    #endif
+#endif
+
+#include <wolfssl/wolfcrypt/sha256.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#include <wolfssl/wolfcrypt/cpuid.h>
+#include <wolfssl/wolfcrypt/hash.h>
+
+#ifdef WOLF_CRYPTO_CB
+    #include <wolfssl/wolfcrypt/cryptocb.h>
+#endif
+
+/* fips wrapper calls, user can call direct */
+#if defined(HAVE_FIPS) && \
+    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
+
+    int wc_InitSha256(wc_Sha256* sha)
+    {
+        if (sha == NULL) {
+            return BAD_FUNC_ARG;
+        }
+        return InitSha256_fips(sha);
+    }
+    int wc_InitSha256_ex(wc_Sha256* sha, void* heap, int devId)
+    {
+        (void)heap;
+        (void)devId;
+        if (sha == NULL) {
+            return BAD_FUNC_ARG;
+        }
+        return InitSha256_fips(sha);
+    }
+    int wc_Sha256Update(wc_Sha256* sha, const byte* data, word32 len)
+    {
+        if (sha == NULL ||  (data == NULL && len > 0)) {
+            return BAD_FUNC_ARG;
+        }
+
+        if (data == NULL && len == 0) {
+            /* valid, but do nothing */
+            return 0;
+        }
+
+        return Sha256Update_fips(sha, data, len);
+    }
+    int wc_Sha256Final(wc_Sha256* sha, byte* out)
+    {
+        if (sha == NULL || out == NULL) {
+            return BAD_FUNC_ARG;
+        }
+        return Sha256Final_fips(sha, out);
+    }
+    void wc_Sha256Free(wc_Sha256* sha)
+    {
+        (void)sha;
+        /* Not supported in FIPS */
+    }
+
+#else /* else build without fips, or for FIPS v2 */
+
+
+#if defined(WOLFSSL_TI_HASH)
+    /* #include <wolfcrypt/src/port/ti/ti-hash.c> included by wc_port.c */
+#elif defined(WOLFSSL_CRYPTOCELL)
+    /* wc_port.c includes wolfcrypt/src/port/arm/cryptoCellHash.c */
+#else
+
+#include <wolfssl/wolfcrypt/logging.h>
+
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+#ifdef WOLFSSL_DEVCRYPTO_HASH
+    #include <wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h>
+#endif
+
+
+
+#if defined(USE_INTEL_SPEEDUP)
+    #if defined(__GNUC__) && ((__GNUC__ < 4) || \
+                              (__GNUC__ == 4 && __GNUC_MINOR__ <= 8))
+        #undef  NO_AVX2_SUPPORT
+        #define NO_AVX2_SUPPORT
+    #endif
+    #if defined(__clang__) && ((__clang_major__ < 3) || \
+                               (__clang_major__ == 3 && __clang_minor__ <= 5))
+        #define NO_AVX2_SUPPORT
+    #elif defined(__clang__) && defined(NO_AVX2_SUPPORT)
+        #undef NO_AVX2_SUPPORT
+    #endif
+
+    #define HAVE_INTEL_AVX1
+    #ifndef NO_AVX2_SUPPORT
+        #define HAVE_INTEL_AVX2
+    #endif
+#endif /* USE_INTEL_SPEEDUP */
+
+#if defined(HAVE_INTEL_AVX2)
+    #define HAVE_INTEL_RORX
+#endif
+
+
+#if !defined(WOLFSSL_PIC32MZ_HASH) && !defined(STM32_HASH_SHA2) && \
+    (!defined(WOLFSSL_IMX6_CAAM) || defined(NO_IMX6_CAAM_HASH)) && \
+    !defined(WOLFSSL_AFALG_HASH) && !defined(WOLFSSL_DEVCRYPTO_HASH) && \
+    (!defined(WOLFSSL_ESP32WROOM32_CRYPT) || defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)) && \
+    (!defined(WOLFSSL_RENESAS_TSIP_CRYPT) || defined(NO_WOLFSSL_RENESAS_TSIP_HASH))
+
+static int InitSha256(wc_Sha256* sha256)
+{
+    int ret = 0;
+
+    if (sha256 == NULL)
+        return BAD_FUNC_ARG;
+
+    XMEMSET(sha256->digest, 0, sizeof(sha256->digest));
+    sha256->digest[0] = 0x6A09E667L;
+    sha256->digest[1] = 0xBB67AE85L;
+    sha256->digest[2] = 0x3C6EF372L;
+    sha256->digest[3] = 0xA54FF53AL;
+    sha256->digest[4] = 0x510E527FL;
+    sha256->digest[5] = 0x9B05688CL;
+    sha256->digest[6] = 0x1F83D9ABL;
+    sha256->digest[7] = 0x5BE0CD19L;
+
+    sha256->buffLen = 0;
+    sha256->loLen   = 0;
+    sha256->hiLen   = 0;
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+    sha256->flags = 0;
+#endif
+
+    return ret;
+}
+#endif
+
+
+/* Hardware Acceleration */
+#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
+
+    /* in case intel instructions aren't available, plus we need the K[] global */
+    #define NEED_SOFT_SHA256
+
+    /*****
+    Intel AVX1/AVX2 Macro Control Structure
+
+    #define HAVE_INTEL_AVX1
+    #define HAVE_INTEL_AVX2
+
+    #define HAVE_INTEL_RORX
+
+
+    int InitSha256(wc_Sha256* sha256) {
+         Save/Recover XMM, YMM
+         ...
+    }
+
+    #if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2)
+      Transform_Sha256(); Function prototype
+    #else
+      Transform_Sha256() {   }
+      int Sha256Final() {
+         Save/Recover XMM, YMM
+         ...
+      }
+    #endif
+
+    #if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2)
+        #if defined(HAVE_INTEL_RORX
+             #define RND with rorx instruction
+        #else
+            #define RND
+        #endif
+    #endif
+
+    #if defined(HAVE_INTEL_AVX1)
+
+       #define XMM Instructions/inline asm
+
+       int Transform_Sha256() {
+           Stitched Message Sched/Round
+        }
+
+    #elif defined(HAVE_INTEL_AVX2)
+
+      #define YMM Instructions/inline asm
+
+      int Transform_Sha256() {
+          More granular Stitched Message Sched/Round
+      }
+
+    #endif
+
+    */
+
+    /* Each platform needs to query info type 1 from cpuid to see if aesni is
+     * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts
+     */
+
+    /* #if defined(HAVE_INTEL_AVX1/2) at the tail of sha256 */
+    static int Transform_Sha256(wc_Sha256* sha256, const byte* data);
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+    #if defined(HAVE_INTEL_AVX1)
+        extern int Transform_Sha256_AVX1(wc_Sha256 *sha256, const byte* data);
+        extern int Transform_Sha256_AVX1_Len(wc_Sha256* sha256,
+                                             const byte* data, word32 len);
+    #endif
+    #if defined(HAVE_INTEL_AVX2)
+        extern int Transform_Sha256_AVX2(wc_Sha256 *sha256, const byte* data);
+        extern int Transform_Sha256_AVX2_Len(wc_Sha256* sha256,
+                                             const byte* data, word32 len);
+        #ifdef HAVE_INTEL_RORX
+        extern int Transform_Sha256_AVX1_RORX(wc_Sha256 *sha256, const byte* data);
+        extern int Transform_Sha256_AVX1_RORX_Len(wc_Sha256* sha256,
+                                                  const byte* data, word32 len);
+        extern int Transform_Sha256_AVX2_RORX(wc_Sha256 *sha256, const byte* data);
+        extern int Transform_Sha256_AVX2_RORX_Len(wc_Sha256* sha256,
+                                                  const byte* data, word32 len);
+        #endif /* HAVE_INTEL_RORX */
+    #endif /* HAVE_INTEL_AVX2 */
+
+#ifdef __cplusplus
+    }  /* extern "C" */
+#endif
+
+    static int (*Transform_Sha256_p)(wc_Sha256* sha256, const byte* data);
+                                                       /* = _Transform_Sha256 */
+    static int (*Transform_Sha256_Len_p)(wc_Sha256* sha256, const byte* data,
+                                         word32 len);
+                                                                    /* = NULL */
+    static int transform_check = 0;
+    static word32 intel_flags;
+
+    #define XTRANSFORM(S, D)         (*Transform_Sha256_p)((S),(D))
+    #define XTRANSFORM_LEN(S, D, L)  (*Transform_Sha256_Len_p)((S),(D),(L))
+
+    static void Sha256_SetTransform(void)
+    {
+
+        if (transform_check)
+            return;
+
+        intel_flags = cpuid_get_flags();
+
+    #ifdef HAVE_INTEL_AVX2
+        if (1 && IS_INTEL_AVX2(intel_flags)) {
+        #ifdef HAVE_INTEL_RORX
+            if (IS_INTEL_BMI2(intel_flags)) {
+                Transform_Sha256_p = Transform_Sha256_AVX2_RORX;
+                Transform_Sha256_Len_p = Transform_Sha256_AVX2_RORX_Len;
+            }
+            else
+        #endif
+            if (1)
+            {
+                Transform_Sha256_p = Transform_Sha256_AVX2;
+                Transform_Sha256_Len_p = Transform_Sha256_AVX2_Len;
+            }
+        #ifdef HAVE_INTEL_RORX
+            else {
+                Transform_Sha256_p = Transform_Sha256_AVX1_RORX;
+                Transform_Sha256_Len_p = Transform_Sha256_AVX1_RORX_Len;
+            }
+        #endif
+        }
+        else
+    #endif
+    #ifdef HAVE_INTEL_AVX1
+        if (IS_INTEL_AVX1(intel_flags)) {
+            Transform_Sha256_p = Transform_Sha256_AVX1;
+            Transform_Sha256_Len_p = Transform_Sha256_AVX1_Len;
+        }
+        else
+    #endif
+        {
+            Transform_Sha256_p = Transform_Sha256;
+            Transform_Sha256_Len_p = NULL;
+        }
+
+        transform_check = 1;
+    }
+
+    int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
+    {
+        int ret = 0;
+        if (sha256 == NULL)
+            return BAD_FUNC_ARG;
+
+        sha256->heap = heap;
+    #ifdef WOLF_CRYPTO_CB
+        sha256->devId = devId;
+    #endif
+
+        ret = InitSha256(sha256);
+        if (ret != 0)
+            return ret;
+
+        /* choose best Transform function under this runtime environment */
+        Sha256_SetTransform();
+
+    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256)
+        ret = wolfAsync_DevCtxInit(&sha256->asyncDev,
+                            WOLFSSL_ASYNC_MARKER_SHA256, sha256->heap, devId);
+    #else
+        (void)devId;
+    #endif /* WOLFSSL_ASYNC_CRYPT */
+
+        return ret;
+    }
+
+#elif defined(FREESCALE_LTC_SHA)
+    int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
+    {
+        (void)heap;
+        (void)devId;
+
+        LTC_HASH_Init(LTC_BASE, &sha256->ctx, kLTC_Sha256, NULL, 0);
+
+        return 0;
+    }
+
+#elif defined(FREESCALE_MMCAU_SHA)
+
+    #ifdef FREESCALE_MMCAU_CLASSIC_SHA
+        #include "cau_api.h"
+    #else
+        #include "fsl_mmcau.h"
+    #endif
+
+    #define XTRANSFORM(S, D)         Transform_Sha256((S),(D))
+    #define XTRANSFORM_LEN(S, D, L)  Transform_Sha256_Len((S),(D),(L))
+
+    #ifndef WC_HASH_DATA_ALIGNMENT
+        /* these hardware API's require 4 byte (word32) alignment */
+        #define WC_HASH_DATA_ALIGNMENT 4
+    #endif
+
+    int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
+    {
+        int ret = 0;
+
+        (void)heap;
+        (void)devId;
+
+        ret = wolfSSL_CryptHwMutexLock();
+        if (ret != 0) {
+            return ret;
+        }
+
+    #ifdef FREESCALE_MMCAU_CLASSIC_SHA
+        cau_sha256_initialize_output(sha256->digest);
+    #else
+        MMCAU_SHA256_InitializeOutput((uint32_t*)sha256->digest);
+    #endif
+        wolfSSL_CryptHwMutexUnLock();
+
+        sha256->buffLen = 0;
+        sha256->loLen   = 0;
+        sha256->hiLen   = 0;
+    #ifdef WOLFSSL_SMALL_STACK_CACHE
+        sha256->W = NULL;
+    #endif
+
+        return ret;
+    }
+
+    static int Transform_Sha256(wc_Sha256* sha256, const byte* data)
+    {
+        int ret = wolfSSL_CryptHwMutexLock();
+        if (ret == 0) {
+    #ifdef FREESCALE_MMCAU_CLASSIC_SHA
+            cau_sha256_hash_n((byte*)data, 1, sha256->digest);
+    #else
+            MMCAU_SHA256_HashN((byte*)data, 1, sha256->digest);
+    #endif
+            wolfSSL_CryptHwMutexUnLock();
+        }
+        return ret;
+    }
+
+    static int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
+        word32 len)
+    {
+        int ret = wolfSSL_CryptHwMutexLock();
+        if (ret == 0) {
+        #if defined(WC_HASH_DATA_ALIGNMENT) && WC_HASH_DATA_ALIGNMENT > 0
+            if ((size_t)data % WC_HASH_DATA_ALIGNMENT) {
+                /* data pointer is NOT aligned,
+                 * so copy and perform one block at a time */
+                byte* local = (byte*)sha256->buffer;
+                while (len >= WC_SHA256_BLOCK_SIZE) {
+                    XMEMCPY(local, data, WC_SHA256_BLOCK_SIZE);
+                #ifdef FREESCALE_MMCAU_CLASSIC_SHA
+                    cau_sha256_hash_n(local, 1, sha256->digest);
+                #else
+                    MMCAU_SHA256_HashN(local, 1, sha256->digest);
+                #endif
+                    data += WC_SHA256_BLOCK_SIZE;
+                    len  -= WC_SHA256_BLOCK_SIZE;
+                }
+            }
+            else
+        #endif
+            {
+    #ifdef FREESCALE_MMCAU_CLASSIC_SHA
+            cau_sha256_hash_n((byte*)data, len/WC_SHA256_BLOCK_SIZE,
+                sha256->digest);
+    #else
+            MMCAU_SHA256_HashN((byte*)data, len/WC_SHA256_BLOCK_SIZE,
+                sha256->digest);
+    #endif
+            }
+            wolfSSL_CryptHwMutexUnLock();
+        }
+        return ret;
+    }
+
+#elif defined(WOLFSSL_PIC32MZ_HASH)
+    #include <wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h>
+
+#elif defined(STM32_HASH_SHA2)
+
+    /* Supports CubeMX HAL or Standard Peripheral Library */
+
+    int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
+    {
+        if (sha256 == NULL)
+            return BAD_FUNC_ARG;
+
+        (void)devId;
+        (void)heap;
+
+        wc_Stm32_Hash_Init(&sha256->stmCtx);
+        return 0;
+    }
+
+    int wc_Sha256Update(wc_Sha256* sha256, const byte* data, word32 len)
+    {
+        int ret = 0;
+
+        if (sha256 == NULL || (data == NULL && len > 0)) {
+            return BAD_FUNC_ARG;
+        }
+
+        ret = wolfSSL_CryptHwMutexLock();
+        if (ret == 0) {
+            ret = wc_Stm32_Hash_Update(&sha256->stmCtx,
+                HASH_AlgoSelection_SHA256, data, len);
+            wolfSSL_CryptHwMutexUnLock();
+        }
+        return ret;
+    }
+
+    int wc_Sha256Final(wc_Sha256* sha256, byte* hash)
+    {
+        int ret = 0;
+
+        if (sha256 == NULL || hash == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        ret = wolfSSL_CryptHwMutexLock();
+        if (ret == 0) {
+            ret = wc_Stm32_Hash_Final(&sha256->stmCtx,
+                HASH_AlgoSelection_SHA256, hash, WC_SHA256_DIGEST_SIZE);
+            wolfSSL_CryptHwMutexUnLock();
+        }
+
+        (void)wc_InitSha256(sha256); /* reset state */
+
+        return ret;
+    }
+
+#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
+    /* functions defined in wolfcrypt/src/port/caam/caam_sha256.c */
+
+#elif defined(WOLFSSL_AFALG_HASH)
+    /* implemented in wolfcrypt/src/port/af_alg/afalg_hash.c */
+
+#elif defined(WOLFSSL_DEVCRYPTO_HASH)
+    /* implemented in wolfcrypt/src/port/devcrypto/devcrypt_hash.c */
+
+#elif defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_HASH)
+    #include "hal_data.h"
+
+    #ifndef WOLFSSL_SCE_SHA256_HANDLE
+        #define WOLFSSL_SCE_SHA256_HANDLE g_sce_hash_0
+    #endif
+
+    #define WC_SHA256_DIGEST_WORD_SIZE 16
+    #define XTRANSFORM(S, D) wc_Sha256SCE_XTRANSFORM((S), (D))
+    static int wc_Sha256SCE_XTRANSFORM(wc_Sha256* sha256, const byte* data)
+    {
+        if (WOLFSSL_SCE_GSCE_HANDLE.p_cfg->endian_flag ==
+                CRYPTO_WORD_ENDIAN_LITTLE)
+        {
+            ByteReverseWords((word32*)data, (word32*)data,
+                    WC_SHA256_BLOCK_SIZE);
+            ByteReverseWords(sha256->digest, sha256->digest,
+                    WC_SHA256_DIGEST_SIZE);
+        }
+
+        if (WOLFSSL_SCE_SHA256_HANDLE.p_api->hashUpdate(
+                    WOLFSSL_SCE_SHA256_HANDLE.p_ctrl, (word32*)data,
+                    WC_SHA256_DIGEST_WORD_SIZE, sha256->digest) != SSP_SUCCESS){
+            WOLFSSL_MSG("Unexpected hardware return value");
+            return WC_HW_E;
+        }
+
+        if (WOLFSSL_SCE_GSCE_HANDLE.p_cfg->endian_flag ==
+                CRYPTO_WORD_ENDIAN_LITTLE)
+        {
+            ByteReverseWords((word32*)data, (word32*)data,
+                    WC_SHA256_BLOCK_SIZE);
+            ByteReverseWords(sha256->digest, sha256->digest,
+                    WC_SHA256_DIGEST_SIZE);
+        }
+
+        return 0;
+    }
+
+
+    int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
+    {
+        int ret = 0;
+        if (sha256 == NULL)
+            return BAD_FUNC_ARG;
+
+        sha256->heap = heap;
+
+        ret = InitSha256(sha256);
+        if (ret != 0)
+            return ret;
+
+        (void)devId;
+
+        return ret;
+    }
+
+#elif defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+
+    #define NEED_SOFT_SHA256
+
+    static int InitSha256(wc_Sha256* sha256)
+    {
+        int ret = 0;
+
+        if (sha256 == NULL)
+            return BAD_FUNC_ARG;
+
+        XMEMSET(sha256->digest, 0, sizeof(sha256->digest));
+        sha256->digest[0] = 0x6A09E667L;
+        sha256->digest[1] = 0xBB67AE85L;
+        sha256->digest[2] = 0x3C6EF372L;
+        sha256->digest[3] = 0xA54FF53AL;
+        sha256->digest[4] = 0x510E527FL;
+        sha256->digest[5] = 0x9B05688CL;
+        sha256->digest[6] = 0x1F83D9ABL;
+        sha256->digest[7] = 0x5BE0CD19L;
+
+        sha256->buffLen = 0;
+        sha256->loLen   = 0;
+        sha256->hiLen   = 0;
+
+        /* always start firstblock = 1 when using hw engine */
+        sha256->ctx.isfirstblock = 1;
+        sha256->ctx.sha_type = SHA2_256;
+        if(sha256->ctx.mode == ESP32_SHA_HW) {
+            /* release hw */
+            esp_sha_hw_unlock();
+        }
+        /* always set mode as INIT
+        *  whether using HW or SW is determined at first call of update()
+        */
+        sha256->ctx.mode = ESP32_SHA_INIT;
+
+        return ret;
+    }
+    int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
+    {
+        int ret = 0;
+
+        if (sha256 == NULL)
+            return BAD_FUNC_ARG;
+
+        XMEMSET(sha256, 0, sizeof(wc_Sha256));
+        sha256->ctx.mode = ESP32_SHA_INIT;
+        sha256->ctx.isfirstblock = 1;
+        (void)devId;
+
+        ret = InitSha256(sha256);
+
+        return ret;
+    }
+
+#elif defined(WOLFSSL_RENESAS_TSIP_CRYPT) && \
+    !defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH)
+
+    /* implemented in wolfcrypt/src/port/Renesas/renesas_tsip_sha.c */
+
+#else
+    #define NEED_SOFT_SHA256
+
+    int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
+    {
+        int ret = 0;
+        if (sha256 == NULL)
+            return BAD_FUNC_ARG;
+
+        sha256->heap = heap;
+    #ifdef WOLF_CRYPTO_CB
+        sha256->devId = devId;
+        sha256->devCtx = NULL;
+    #endif
+
+        ret = InitSha256(sha256);
+        if (ret != 0)
+            return ret;
+
+    #ifdef WOLFSSL_SMALL_STACK_CACHE
+        sha256->W = NULL;
+    #endif
+
+    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256)
+        ret = wolfAsync_DevCtxInit(&sha256->asyncDev,
+                            WOLFSSL_ASYNC_MARKER_SHA256, sha256->heap, devId);
+    #else
+        (void)devId;
+    #endif /* WOLFSSL_ASYNC_CRYPT */
+
+        return ret;
+    }
+#endif /* End Hardware Acceleration */
+
+#ifdef NEED_SOFT_SHA256
+
+    static const ALIGN32 word32 K[64] = {
+        0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L, 0x3956C25BL,
+        0x59F111F1L, 0x923F82A4L, 0xAB1C5ED5L, 0xD807AA98L, 0x12835B01L,
+        0x243185BEL, 0x550C7DC3L, 0x72BE5D74L, 0x80DEB1FEL, 0x9BDC06A7L,
+        0xC19BF174L, 0xE49B69C1L, 0xEFBE4786L, 0x0FC19DC6L, 0x240CA1CCL,
+        0x2DE92C6FL, 0x4A7484AAL, 0x5CB0A9DCL, 0x76F988DAL, 0x983E5152L,
+        0xA831C66DL, 0xB00327C8L, 0xBF597FC7L, 0xC6E00BF3L, 0xD5A79147L,
+        0x06CA6351L, 0x14292967L, 0x27B70A85L, 0x2E1B2138L, 0x4D2C6DFCL,
+        0x53380D13L, 0x650A7354L, 0x766A0ABBL, 0x81C2C92EL, 0x92722C85L,
+        0xA2BFE8A1L, 0xA81A664BL, 0xC24B8B70L, 0xC76C51A3L, 0xD192E819L,
+        0xD6990624L, 0xF40E3585L, 0x106AA070L, 0x19A4C116L, 0x1E376C08L,
+        0x2748774CL, 0x34B0BCB5L, 0x391C0CB3L, 0x4ED8AA4AL, 0x5B9CCA4FL,
+        0x682E6FF3L, 0x748F82EEL, 0x78A5636FL, 0x84C87814L, 0x8CC70208L,
+        0x90BEFFFAL, 0xA4506CEBL, 0xBEF9A3F7L, 0xC67178F2L
+    };
+
+/* Both versions of Ch and Maj are logically the same, but with the second set
+    the compilers can recognize them better for optimization */
+#ifdef WOLFSSL_SHA256_BY_SPEC
+    /* SHA256 math based on specification */
+    #define Ch(x,y,z)       ((z) ^ ((x) & ((y) ^ (z))))
+    #define Maj(x,y,z)      ((((x) | (y)) & (z)) | ((x) & (y)))
+#else
+    /* SHA256 math reworked for easier compiler optimization */
+    #define Ch(x,y,z)       ((((y) ^ (z)) & (x)) ^ (z))
+    #define Maj(x,y,z)      ((((x) ^ (y)) & ((y) ^ (z))) ^ (y))
+#endif
+    #define R(x, n)         (((x) & 0xFFFFFFFFU) >> (n))
+
+    #define S(x, n)         rotrFixed(x, n)
+    #define Sigma0(x)       (S(x, 2)  ^ S(x, 13) ^ S(x, 22))
+    #define Sigma1(x)       (S(x, 6)  ^ S(x, 11) ^ S(x, 25))
+    #define Gamma0(x)       (S(x, 7)  ^ S(x, 18) ^ R(x, 3))
+    #define Gamma1(x)       (S(x, 17) ^ S(x, 19) ^ R(x, 10))
+
+    #define a(i) S[(0-i) & 7]
+    #define b(i) S[(1-i) & 7]
+    #define c(i) S[(2-i) & 7]
+    #define d(i) S[(3-i) & 7]
+    #define e(i) S[(4-i) & 7]
+    #define f(i) S[(5-i) & 7]
+    #define g(i) S[(6-i) & 7]
+    #define h(i) S[(7-i) & 7]
+
+    #ifndef XTRANSFORM
+         #define XTRANSFORM(S, D)         Transform_Sha256((S),(D))
+    #endif
+
+#ifndef SHA256_MANY_REGISTERS
+    #define RND(j) \
+         t0 = h(j) + Sigma1(e(j)) + Ch(e(j), f(j), g(j)) + K[i+j] + W[i+j]; \
+         t1 = Sigma0(a(j)) + Maj(a(j), b(j), c(j)); \
+         d(j) += t0; \
+         h(j)  = t0 + t1
+
+    static int Transform_Sha256(wc_Sha256* sha256, const byte* data)
+    {
+        word32 S[8], t0, t1;
+        int i;
+
+    #ifdef WOLFSSL_SMALL_STACK_CACHE
+        word32* W = sha256->W;
+        if (W == NULL) {
+            W = (word32*)XMALLOC(sizeof(word32) * WC_SHA256_BLOCK_SIZE, NULL,
+                                                           DYNAMIC_TYPE_DIGEST);
+            if (W == NULL)
+                return MEMORY_E;
+            sha256->W = W;
+        }
+    #elif defined(WOLFSSL_SMALL_STACK)
+        word32* W;
+        W = (word32*)XMALLOC(sizeof(word32) * WC_SHA256_BLOCK_SIZE, NULL,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+        if (W == NULL)
+            return MEMORY_E;
+    #else
+        word32 W[WC_SHA256_BLOCK_SIZE];
+    #endif
+
+        /* Copy context->state[] to working vars */
+        for (i = 0; i < 8; i++)
+            S[i] = sha256->digest[i];
+
+        for (i = 0; i < 16; i++)
+            W[i] = *((word32*)&data[i*sizeof(word32)]);
+
+        for (i = 16; i < WC_SHA256_BLOCK_SIZE; i++)
+            W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15]) + W[i-16];
+
+    #ifdef USE_SLOW_SHA256
+        /* not unrolled - ~2k smaller and ~25% slower */
+        for (i = 0; i < WC_SHA256_BLOCK_SIZE; i += 8) {
+            int j;
+            for (j = 0; j < 8; j++) { /* braces needed here for macros {} */
+                RND(j);
+            }
+        }
+    #else
+        /* partially loop unrolled */
+        for (i = 0; i < WC_SHA256_BLOCK_SIZE; i += 8) {
+            RND(0); RND(1); RND(2); RND(3);
+            RND(4); RND(5); RND(6); RND(7);
+        }
+    #endif /* USE_SLOW_SHA256 */
+
+        /* Add the working vars back into digest state[] */
+        for (i = 0; i < 8; i++) {
+            sha256->digest[i] += S[i];
+        }
+
+    #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
+        XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+        return 0;
+    }
+#else
+    /* SHA256 version that keeps all data in registers */
+    #define SCHED1(j) (W[j] = *((word32*)&data[j*sizeof(word32)]))
+    #define SCHED(j) (               \
+                   W[ j     & 15] += \
+            Gamma1(W[(j-2)  & 15])+  \
+                   W[(j-7)  & 15] +  \
+            Gamma0(W[(j-15) & 15])   \
+        )
+
+    #define RND1(j) \
+         t0 = h(j) + Sigma1(e(j)) + Ch(e(j), f(j), g(j)) + K[i+j] + SCHED1(j); \
+         t1 = Sigma0(a(j)) + Maj(a(j), b(j), c(j)); \
+         d(j) += t0; \
+         h(j)  = t0 + t1
+    #define RNDN(j) \
+         t0 = h(j) + Sigma1(e(j)) + Ch(e(j), f(j), g(j)) + K[i+j] + SCHED(j); \
+         t1 = Sigma0(a(j)) + Maj(a(j), b(j), c(j)); \
+         d(j) += t0; \
+         h(j)  = t0 + t1
+
+    static int Transform_Sha256(wc_Sha256* sha256, const byte* data)
+    {
+        word32 S[8], t0, t1;
+        int i;
+        word32 W[WC_SHA256_BLOCK_SIZE/sizeof(word32)];
+
+        /* Copy digest to working vars */
+        S[0] = sha256->digest[0];
+        S[1] = sha256->digest[1];
+        S[2] = sha256->digest[2];
+        S[3] = sha256->digest[3];
+        S[4] = sha256->digest[4];
+        S[5] = sha256->digest[5];
+        S[6] = sha256->digest[6];
+        S[7] = sha256->digest[7];
+
+        i = 0;
+        RND1( 0); RND1( 1); RND1( 2); RND1( 3);
+        RND1( 4); RND1( 5); RND1( 6); RND1( 7);
+        RND1( 8); RND1( 9); RND1(10); RND1(11);
+        RND1(12); RND1(13); RND1(14); RND1(15);
+        /* 64 operations, partially loop unrolled */
+        for (i = 16; i < 64; i += 16) {
+            RNDN( 0); RNDN( 1); RNDN( 2); RNDN( 3);
+            RNDN( 4); RNDN( 5); RNDN( 6); RNDN( 7);
+            RNDN( 8); RNDN( 9); RNDN(10); RNDN(11);
+            RNDN(12); RNDN(13); RNDN(14); RNDN(15);
+        }
+
+        /* Add the working vars back into digest */
+        sha256->digest[0] += S[0];
+        sha256->digest[1] += S[1];
+        sha256->digest[2] += S[2];
+        sha256->digest[3] += S[3];
+        sha256->digest[4] += S[4];
+        sha256->digest[5] += S[5];
+        sha256->digest[6] += S[6];
+        sha256->digest[7] += S[7];
+
+        return 0;
+    }
+#endif /* SHA256_MANY_REGISTERS */
+#endif
+/* End wc_ software implementation */
+
+
+#ifdef XTRANSFORM
+
+    static WC_INLINE void AddLength(wc_Sha256* sha256, word32 len)
+    {
+        word32 tmp = sha256->loLen;
+        if ((sha256->loLen += len) < tmp) {
+            sha256->hiLen++;                       /* carry low to high */
+        }
+    }
+
+    /* do block size increments/updates */
+    static WC_INLINE int Sha256Update(wc_Sha256* sha256, const byte* data, word32 len)
+    {
+        int ret = 0;
+        word32 blocksLen;
+        byte* local;
+
+        if (sha256 == NULL || (data == NULL && len > 0)) {
+            return BAD_FUNC_ARG;
+        }
+
+        if (data == NULL && len == 0) {
+            /* valid, but do nothing */
+            return 0;
+        }
+
+        /* check that internal buffLen is valid */
+        if (sha256->buffLen >= WC_SHA256_BLOCK_SIZE) {
+            return BUFFER_E;
+        }
+
+        /* add length for final */
+        AddLength(sha256, len);
+
+        local = (byte*)sha256->buffer;
+
+        /* process any remainder from previous operation */
+        if (sha256->buffLen > 0) {
+            blocksLen = min(len, WC_SHA256_BLOCK_SIZE - sha256->buffLen);
+            XMEMCPY(&local[sha256->buffLen], data, blocksLen);
+
+            sha256->buffLen += blocksLen;
+            data            += blocksLen;
+            len             -= blocksLen;
+
+            if (sha256->buffLen == WC_SHA256_BLOCK_SIZE) {
+            #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
+                #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
+                if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags))
+                #endif
+                {
+                    ByteReverseWords(sha256->buffer, sha256->buffer,
+                        WC_SHA256_BLOCK_SIZE);
+                }
+            #endif
+
+            #if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+                !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+                if (sha256->ctx.mode == ESP32_SHA_INIT){
+                    esp_sha_try_hw_lock(&sha256->ctx);
+                }
+                if (sha256->ctx.mode == ESP32_SHA_SW){
+                    ret = XTRANSFORM(sha256, (const byte*)local);
+                } else {
+                    esp_sha256_process(sha256, (const byte*)local);
+                }
+            #else
+                ret = XTRANSFORM(sha256, (const byte*)local);
+            #endif
+
+                if (ret == 0)
+                    sha256->buffLen = 0;
+                else
+                    len = 0; /* error */
+            }
+        }
+
+        /* process blocks */
+    #ifdef XTRANSFORM_LEN
+        #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
+        if (Transform_Sha256_Len_p != NULL)
+        #endif
+        {
+            /* get number of blocks */
+            /* 64-1 = 0x3F (~ Inverted = 0xFFFFFFC0) */
+            /* len (masked by 0xFFFFFFC0) returns block aligned length */
+            blocksLen = len & ~(WC_SHA256_BLOCK_SIZE-1);
+            if (blocksLen > 0) {
+                /* Byte reversal and alignment handled in function if required */
+                XTRANSFORM_LEN(sha256, data, blocksLen);
+                data += blocksLen;
+                len  -= blocksLen;
+            }
+        }
+        #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
+        else
+        #endif
+    #endif /* XTRANSFORM_LEN */
+    #if !defined(XTRANSFORM_LEN) || defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
+        {
+            while (len >= WC_SHA256_BLOCK_SIZE) {
+                word32* local32 = sha256->buffer;
+                /* optimization to avoid memcpy if data pointer is properly aligned */
+                /* Intel transform function requires use of sha256->buffer */
+                /* Little Endian requires byte swap, so can't use data directly */
+            #if defined(WC_HASH_DATA_ALIGNMENT) && !defined(LITTLE_ENDIAN_ORDER) && \
+                !defined(HAVE_INTEL_AVX1) && !defined(HAVE_INTEL_AVX2)
+                if (((size_t)data % WC_HASH_DATA_ALIGNMENT) == 0) {
+                    local32 = (word32*)data;
+                }
+                else
+            #endif
+                {
+                    XMEMCPY(local32, data, WC_SHA256_BLOCK_SIZE);
+                }
+
+                data += WC_SHA256_BLOCK_SIZE;
+                len  -= WC_SHA256_BLOCK_SIZE;
+
+            #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
+                #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
+                if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags))
+                #endif
+                {
+                    ByteReverseWords(local32, local32, WC_SHA256_BLOCK_SIZE);
+                }
+            #endif
+
+            #if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+                !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+                if (sha256->ctx.mode == ESP32_SHA_INIT){
+                    esp_sha_try_hw_lock(&sha256->ctx);
+                }
+                if (sha256->ctx.mode == ESP32_SHA_SW){
+                    ret = XTRANSFORM(sha256, (const byte*)local32);
+                } else {
+                    esp_sha256_process(sha256, (const byte*)local32);
+                }
+            #else
+                ret = XTRANSFORM(sha256, (const byte*)local32);
+            #endif
+
+                if (ret != 0)
+                    break;
+            }
+        }
+    #endif
+
+        /* save remainder */
+        if (len > 0) {
+            XMEMCPY(local, data, len);
+            sha256->buffLen = len;
+        }
+
+        return ret;
+    }
+
+    int wc_Sha256Update(wc_Sha256* sha256, const byte* data, word32 len)
+    {
+        if (sha256 == NULL || (data == NULL && len > 0)) {
+            return BAD_FUNC_ARG;
+        }
+
+        if (data == NULL && len == 0) {
+            /* valid, but do nothing */
+            return 0;
+        }
+
+    #ifdef WOLF_CRYPTO_CB
+        if (sha256->devId != INVALID_DEVID) {
+            int ret = wc_CryptoCb_Sha256Hash(sha256, data, len, NULL);
+            if (ret != CRYPTOCB_UNAVAILABLE)
+                return ret;
+            /* fall-through when unavailable */
+        }
+    #endif
+    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256)
+        if (sha256->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA256) {
+        #if defined(HAVE_INTEL_QA)
+            return IntelQaSymSha256(&sha256->asyncDev, NULL, data, len);
+        #endif
+        }
+    #endif /* WOLFSSL_ASYNC_CRYPT */
+
+        return Sha256Update(sha256, data, len);
+    }
+
+    static WC_INLINE int Sha256Final(wc_Sha256* sha256)
+    {
+
+        int ret;
+        byte* local;
+
+        if (sha256 == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        local = (byte*)sha256->buffer;
+        local[sha256->buffLen++] = 0x80; /* add 1 */
+
+        /* pad with zeros */
+        if (sha256->buffLen > WC_SHA256_PAD_SIZE) {
+            XMEMSET(&local[sha256->buffLen], 0,
+                WC_SHA256_BLOCK_SIZE - sha256->buffLen);
+            sha256->buffLen += WC_SHA256_BLOCK_SIZE - sha256->buffLen;
+
+        #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
+            #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
+            if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags))
+            #endif
+            {
+                ByteReverseWords(sha256->buffer, sha256->buffer,
+                                                      WC_SHA256_BLOCK_SIZE);
+            }
+        #endif
+
+        #if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+             !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+            if (sha256->ctx.mode == ESP32_SHA_INIT) {
+                esp_sha_try_hw_lock(&sha256->ctx);
+            }
+            if (sha256->ctx.mode == ESP32_SHA_SW) {
+                ret = XTRANSFORM(sha256, (const byte*)local);
+            } else {
+                ret = esp_sha256_process(sha256, (const byte*)local);
+            }
+        #else
+            ret = XTRANSFORM(sha256, (const byte*)local);
+        #endif
+            if (ret != 0)
+                return ret;
+
+            sha256->buffLen = 0;
+        }
+        XMEMSET(&local[sha256->buffLen], 0,
+            WC_SHA256_PAD_SIZE - sha256->buffLen);
+
+        /* put lengths in bits */
+        sha256->hiLen = (sha256->loLen >> (8 * sizeof(sha256->loLen) - 3)) +
+                                                         (sha256->hiLen << 3);
+        sha256->loLen = sha256->loLen << 3;
+
+        /* store lengths */
+    #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
+        #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
+        if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags))
+        #endif
+        {
+            ByteReverseWords(sha256->buffer, sha256->buffer,
+                WC_SHA256_BLOCK_SIZE);
+        }
+    #endif
+        /* ! length ordering dependent on digest endian type ! */
+        XMEMCPY(&local[WC_SHA256_PAD_SIZE], &sha256->hiLen, sizeof(word32));
+        XMEMCPY(&local[WC_SHA256_PAD_SIZE + sizeof(word32)], &sha256->loLen,
+                sizeof(word32));
+
+    #if defined(FREESCALE_MMCAU_SHA) || defined(HAVE_INTEL_AVX1) || \
+        defined(HAVE_INTEL_AVX2)
+        /* Kinetis requires only these bytes reversed */
+        #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
+        if (IS_INTEL_AVX1(intel_flags) || IS_INTEL_AVX2(intel_flags))
+        #endif
+        {
+            ByteReverseWords(
+                &sha256->buffer[WC_SHA256_PAD_SIZE / sizeof(word32)],
+                &sha256->buffer[WC_SHA256_PAD_SIZE / sizeof(word32)],
+                2 * sizeof(word32));
+        }
+    #endif
+
+    #if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+         !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+        if (sha256->ctx.mode == ESP32_SHA_INIT) {
+            esp_sha_try_hw_lock(&sha256->ctx);
+        }
+        if (sha256->ctx.mode == ESP32_SHA_SW) {
+            ret = XTRANSFORM(sha256, (const byte*)local);
+        } else {
+            ret = esp_sha256_digest_process(sha256, 1);
+        }
+    #else
+        ret = XTRANSFORM(sha256, (const byte*)local);
+    #endif
+
+        return ret;
+    }
+
+    int wc_Sha256FinalRaw(wc_Sha256* sha256, byte* hash)
+    {
+    #ifdef LITTLE_ENDIAN_ORDER
+        word32 digest[WC_SHA256_DIGEST_SIZE / sizeof(word32)];
+    #endif
+
+        if (sha256 == NULL || hash == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+    #ifdef LITTLE_ENDIAN_ORDER
+        ByteReverseWords((word32*)digest, (word32*)sha256->digest,
+                                                         WC_SHA256_DIGEST_SIZE);
+        XMEMCPY(hash, digest, WC_SHA256_DIGEST_SIZE);
+    #else
+        XMEMCPY(hash, sha256->digest, WC_SHA256_DIGEST_SIZE);
+    #endif
+
+        return 0;
+    }
+
+    int wc_Sha256Final(wc_Sha256* sha256, byte* hash)
+    {
+        int ret;
+
+        if (sha256 == NULL || hash == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+    #ifdef WOLF_CRYPTO_CB
+        if (sha256->devId != INVALID_DEVID) {
+            ret = wc_CryptoCb_Sha256Hash(sha256, NULL, 0, hash);
+            if (ret != CRYPTOCB_UNAVAILABLE)
+                return ret;
+            /* fall-through when unavailable */
+        }
+    #endif
+
+    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256)
+        if (sha256->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA256) {
+        #if defined(HAVE_INTEL_QA)
+            return IntelQaSymSha256(&sha256->asyncDev, hash, NULL,
+                                            WC_SHA256_DIGEST_SIZE);
+        #endif
+        }
+    #endif /* WOLFSSL_ASYNC_CRYPT */
+
+        ret = Sha256Final(sha256);
+        if (ret != 0)
+            return ret;
+
+    #if defined(LITTLE_ENDIAN_ORDER)
+        ByteReverseWords(sha256->digest, sha256->digest, WC_SHA256_DIGEST_SIZE);
+    #endif
+        XMEMCPY(hash, sha256->digest, WC_SHA256_DIGEST_SIZE);
+
+        return InitSha256(sha256);  /* reset state */
+    }
+
+#endif /* XTRANSFORM */
+
+#ifdef WOLFSSL_SHA224
+
+#ifdef STM32_HASH_SHA2
+
+    /* Supports CubeMX HAL or Standard Peripheral Library */
+
+    int wc_InitSha224_ex(wc_Sha224* sha224, void* heap, int devId)
+    {
+        if (sha224 == NULL)
+            return BAD_FUNC_ARG;
+
+        (void)devId;
+        (void)heap;
+
+        wc_Stm32_Hash_Init(&sha224->stmCtx);
+        return 0;
+    }
+
+    int wc_Sha224Update(wc_Sha224* sha224, const byte* data, word32 len)
+    {
+        int ret = 0;
+
+        if (sha224 == NULL || (data == NULL && len > 0)) {
+            return BAD_FUNC_ARG;
+        }
+
+        ret = wolfSSL_CryptHwMutexLock();
+        if (ret == 0) {
+            ret = wc_Stm32_Hash_Update(&sha224->stmCtx,
+                HASH_AlgoSelection_SHA224, data, len);
+            wolfSSL_CryptHwMutexUnLock();
+        }
+        return ret;
+    }
+
+    int wc_Sha224Final(wc_Sha224* sha224, byte* hash)
+    {
+        int ret = 0;
+
+        if (sha224 == NULL || hash == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        ret = wolfSSL_CryptHwMutexLock();
+        if (ret == 0) {
+            ret = wc_Stm32_Hash_Final(&sha224->stmCtx,
+                HASH_AlgoSelection_SHA224, hash, WC_SHA224_DIGEST_SIZE);
+            wolfSSL_CryptHwMutexUnLock();
+        }
+
+        (void)wc_InitSha224(sha224); /* reset state */
+
+        return ret;
+    }
+
+#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
+    /* functions defined in wolfcrypt/src/port/caam/caam_sha256.c */
+
+#elif defined(WOLFSSL_AFALG_HASH)
+    #error SHA224 currently not supported with AF_ALG enabled
+
+#elif defined(WOLFSSL_DEVCRYPTO_HASH)
+    /* implemented in wolfcrypt/src/port/devcrypto/devcrypt_hash.c */
+
+#else
+
+    #define NEED_SOFT_SHA224
+
+
+    static int InitSha224(wc_Sha224* sha224)
+    {
+        int ret = 0;
+
+        if (sha224 == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        sha224->digest[0] = 0xc1059ed8;
+        sha224->digest[1] = 0x367cd507;
+        sha224->digest[2] = 0x3070dd17;
+        sha224->digest[3] = 0xf70e5939;
+        sha224->digest[4] = 0xffc00b31;
+        sha224->digest[5] = 0x68581511;
+        sha224->digest[6] = 0x64f98fa7;
+        sha224->digest[7] = 0xbefa4fa4;
+
+        sha224->buffLen = 0;
+        sha224->loLen   = 0;
+        sha224->hiLen   = 0;
+
+    #if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2)
+        /* choose best Transform function under this runtime environment */
+        Sha256_SetTransform();
+    #endif
+    #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+        sha224->flags = 0;
+    #endif
+
+        return ret;
+    }
+
+#endif
+
+#ifdef NEED_SOFT_SHA224
+    int wc_InitSha224_ex(wc_Sha224* sha224, void* heap, int devId)
+    {
+        int ret = 0;
+
+        if (sha224 == NULL)
+            return BAD_FUNC_ARG;
+
+        sha224->heap = heap;
+
+        ret = InitSha224(sha224);
+        if (ret != 0)
+            return ret;
+
+    #ifdef WOLFSSL_SMALL_STACK_CACHE
+        sha224->W = NULL;
+    #endif
+
+    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224)
+        ret = wolfAsync_DevCtxInit(&sha224->asyncDev,
+                            WOLFSSL_ASYNC_MARKER_SHA224, sha224->heap, devId);
+    #else
+        (void)devId;
+    #endif /* WOLFSSL_ASYNC_CRYPT */
+
+        return ret;
+    }
+
+    int wc_Sha224Update(wc_Sha224* sha224, const byte* data, word32 len)
+    {
+        int ret;
+
+        if (sha224 == NULL || (data == NULL && len > 0)) {
+            return BAD_FUNC_ARG;
+        }
+
+    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224)
+        if (sha224->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA224) {
+        #if defined(HAVE_INTEL_QA)
+            return IntelQaSymSha224(&sha224->asyncDev, NULL, data, len);
+        #endif
+        }
+    #endif /* WOLFSSL_ASYNC_CRYPT */
+
+        ret = Sha256Update((wc_Sha256*)sha224, data, len);
+
+        return ret;
+    }
+
+    int wc_Sha224Final(wc_Sha224* sha224, byte* hash)
+    {
+        int ret;
+
+        if (sha224 == NULL || hash == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224)
+        if (sha224->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA224) {
+        #if defined(HAVE_INTEL_QA)
+            return IntelQaSymSha224(&sha224->asyncDev, hash, NULL,
+                                            WC_SHA224_DIGEST_SIZE);
+        #endif
+        }
+    #endif /* WOLFSSL_ASYNC_CRYPT */
+
+        ret = Sha256Final((wc_Sha256*)sha224);
+        if (ret != 0)
+            return ret;
+
+    #if defined(LITTLE_ENDIAN_ORDER)
+        ByteReverseWords(sha224->digest, sha224->digest, WC_SHA224_DIGEST_SIZE);
+    #endif
+        XMEMCPY(hash, sha224->digest, WC_SHA224_DIGEST_SIZE);
+
+        return InitSha224(sha224);  /* reset state */
+    }
+#endif /* end of SHA224 software implementation */
+
+    int wc_InitSha224(wc_Sha224* sha224)
+    {
+        return wc_InitSha224_ex(sha224, NULL, INVALID_DEVID);
+    }
+
+    void wc_Sha224Free(wc_Sha224* sha224)
+    {
+        if (sha224 == NULL)
+            return;
+
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+    if (sha224->W != NULL) {
+        XFREE(sha224->W, NULL, DYNAMIC_TYPE_DIGEST);
+        sha224->W = NULL;
+    }
+#endif
+
+    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224)
+        wolfAsync_DevCtxFree(&sha224->asyncDev, WOLFSSL_ASYNC_MARKER_SHA224);
+    #endif /* WOLFSSL_ASYNC_CRYPT */
+
+    #ifdef WOLFSSL_PIC32MZ_HASH
+        wc_Sha256Pic32Free(sha224);
+    #endif
+    }
+#endif /* WOLFSSL_SHA224 */
+
+
+int wc_InitSha256(wc_Sha256* sha256)
+{
+    return wc_InitSha256_ex(sha256, NULL, INVALID_DEVID);
+}
+
+void wc_Sha256Free(wc_Sha256* sha256)
+{
+    if (sha256 == NULL)
+        return;
+
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+    if (sha256->W != NULL) {
+        XFREE(sha256->W, NULL, DYNAMIC_TYPE_DIGEST);
+        sha256->W = NULL;
+    }
+#endif
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256)
+    wolfAsync_DevCtxFree(&sha256->asyncDev, WOLFSSL_ASYNC_MARKER_SHA256);
+#endif /* WOLFSSL_ASYNC_CRYPT */
+#ifdef WOLFSSL_PIC32MZ_HASH
+    wc_Sha256Pic32Free(sha256);
+#endif
+#if defined(WOLFSSL_AFALG_HASH)
+    if (sha256->alFd > 0) {
+        close(sha256->alFd);
+        sha256->alFd = -1; /* avoid possible double close on socket */
+    }
+    if (sha256->rdFd > 0) {
+        close(sha256->rdFd);
+        sha256->rdFd = -1; /* avoid possible double close on socket */
+    }
+#endif /* WOLFSSL_AFALG_HASH */
+#ifdef WOLFSSL_DEVCRYPTO_HASH
+    wc_DevCryptoFree(&sha256->ctx);
+#endif /* WOLFSSL_DEVCRYPTO */
+#if (defined(WOLFSSL_AFALG_HASH) && defined(WOLFSSL_AFALG_HASH_KEEP)) || \
+    (defined(WOLFSSL_DEVCRYPTO_HASH) && defined(WOLFSSL_DEVCRYPTO_HASH_KEEP)) || \
+    (defined(WOLFSSL_RENESAS_TSIP_CRYPT) && \
+    !defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH))
+    if (sha256->msg != NULL) {
+        XFREE(sha256->msg, sha256->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        sha256->msg = NULL;
+    }
+#endif
+}
+
+#endif /* !WOLFSSL_TI_HASH */
+#endif /* HAVE_FIPS */
+
+
+#ifndef WOLFSSL_TI_HASH
+#ifdef WOLFSSL_SHA224
+    int wc_Sha224GetHash(wc_Sha224* sha224, byte* hash)
+    {
+        int ret;
+        wc_Sha224 tmpSha224;
+
+        if (sha224 == NULL || hash == NULL)
+            return BAD_FUNC_ARG;
+
+        ret = wc_Sha224Copy(sha224, &tmpSha224);
+        if (ret == 0) {
+            ret = wc_Sha224Final(&tmpSha224, hash);
+            wc_Sha224Free(&tmpSha224);
+        }
+        return ret;
+    }
+    int wc_Sha224Copy(wc_Sha224* src, wc_Sha224* dst)
+    {
+        int ret = 0;
+
+        if (src == NULL || dst == NULL)
+            return BAD_FUNC_ARG;
+
+        XMEMCPY(dst, src, sizeof(wc_Sha224));
+    #ifdef WOLFSSL_SMALL_STACK_CACHE
+        dst->W = NULL;
+    #endif
+
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev);
+    #endif
+    #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+        dst->flags |= WC_HASH_FLAG_ISCOPY;
+    #endif
+
+        return ret;
+    }
+
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+    int wc_Sha224SetFlags(wc_Sha224* sha224, word32 flags)
+    {
+        if (sha224) {
+            sha224->flags = flags;
+        }
+        return 0;
+    }
+    int wc_Sha224GetFlags(wc_Sha224* sha224, word32* flags)
+    {
+        if (sha224 && flags) {
+            *flags = sha224->flags;
+        }
+        return 0;
+    }
+#endif
+
+#endif /* WOLFSSL_SHA224 */
+
+#ifdef WOLFSSL_AFALG_HASH
+    /* implemented in wolfcrypt/src/port/af_alg/afalg_hash.c */
+
+#elif defined(WOLFSSL_DEVCRYPTO_HASH)
+    /* implemented in wolfcrypt/src/port/devcrypto/devcrypt_hash.c */
+
+#elif defined(WOLFSSL_RENESAS_TSIP_CRYPT) && \
+    !defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH)
+
+    /* implemented in wolfcrypt/src/port/Renesas/renesas_tsip_sha.c */
+#else
+
+int wc_Sha256GetHash(wc_Sha256* sha256, byte* hash)
+{
+    int ret;
+    wc_Sha256 tmpSha256;
+
+    if (sha256 == NULL || hash == NULL)
+        return BAD_FUNC_ARG;
+
+#if  defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+    if(sha256->ctx.mode == ESP32_SHA_INIT){
+        esp_sha_try_hw_lock(&sha256->ctx);
+    }
+    if(sha256->ctx.mode == ESP32_SHA_HW)
+    {
+        esp_sha256_digest_process(sha256, 0);
+    }
+#endif
+    ret = wc_Sha256Copy(sha256, &tmpSha256);
+    if (ret == 0) {
+        ret = wc_Sha256Final(&tmpSha256, hash);
+#if  defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+        sha256->ctx.mode = ESP32_SHA_SW;
+#endif
+
+        wc_Sha256Free(&tmpSha256);
+    }
+    return ret;
+}
+int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst)
+{
+    int ret = 0;
+
+    if (src == NULL || dst == NULL)
+        return BAD_FUNC_ARG;
+
+    XMEMCPY(dst, src, sizeof(wc_Sha256));
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+    dst->W = NULL;
+#endif
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev);
+#endif
+#ifdef WOLFSSL_PIC32MZ_HASH
+    ret = wc_Pic32HashCopy(&src->cache, &dst->cache);
+#endif
+#if  defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+     dst->ctx.mode = src->ctx.mode;
+     dst->ctx.isfirstblock = src->ctx.isfirstblock;
+     dst->ctx.sha_type = src->ctx.sha_type;
+#endif
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+     dst->flags |= WC_HASH_FLAG_ISCOPY;
+#endif
+
+    return ret;
+}
+#endif
+
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+int wc_Sha256SetFlags(wc_Sha256* sha256, word32 flags)
+{
+    if (sha256) {
+        sha256->flags = flags;
+    }
+    return 0;
+}
+int wc_Sha256GetFlags(wc_Sha256* sha256, word32* flags)
+{
+    if (sha256 && flags) {
+        *flags = sha256->flags;
+    }
+    return 0;
+}
+#endif
+#endif /* !WOLFSSL_TI_HASH */
+
+#endif /* NO_SHA256 */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/sha512.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/sha512.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/sha512.c	(revision 453)
@@ -0,0 +1,1225 @@
+/* sha512.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#if (defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)) && !defined(WOLFSSL_ARMASM)
+
+#if defined(HAVE_FIPS) && \
+	defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
+
+    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
+    #define FIPS_NO_WRAPPERS
+
+    #ifdef USE_WINDOWS_API
+        #pragma code_seg(".fipsA$k")
+        #pragma const_seg(".fipsB$k")
+    #endif
+#endif
+
+#include <wolfssl/wolfcrypt/sha512.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#include <wolfssl/wolfcrypt/cpuid.h>
+#include <wolfssl/wolfcrypt/hash.h>
+
+/* deprecated USE_SLOW_SHA2 (replaced with USE_SLOW_SHA512) */
+#if defined(USE_SLOW_SHA2) && !defined(USE_SLOW_SHA512)
+    #define USE_SLOW_SHA512
+#endif
+
+/* fips wrapper calls, user can call direct */
+#if defined(HAVE_FIPS) && \
+    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
+
+    #ifdef WOLFSSL_SHA512
+
+        int wc_InitSha512(wc_Sha512* sha)
+        {
+            if (sha == NULL) {
+                return BAD_FUNC_ARG;
+            }
+
+            return InitSha512_fips(sha);
+        }
+        int wc_InitSha512_ex(wc_Sha512* sha, void* heap, int devId)
+        {
+            (void)heap;
+            (void)devId;
+            if (sha == NULL) {
+                return BAD_FUNC_ARG;
+            }
+            return InitSha512_fips(sha);
+        }
+        int wc_Sha512Update(wc_Sha512* sha, const byte* data, word32 len)
+        {
+            if (sha == NULL || (data == NULL && len > 0)) {
+                return BAD_FUNC_ARG;
+            }
+
+            return Sha512Update_fips(sha, data, len);
+        }
+        int wc_Sha512Final(wc_Sha512* sha, byte* out)
+        {
+            if (sha == NULL || out == NULL) {
+                return BAD_FUNC_ARG;
+            }
+
+            return Sha512Final_fips(sha, out);
+        }
+        void wc_Sha512Free(wc_Sha512* sha)
+        {
+            (void)sha;
+            /* Not supported in FIPS */
+        }
+    #endif
+
+    #if defined(WOLFSSL_SHA384) || defined(HAVE_AESGCM)
+        int wc_InitSha384(wc_Sha384* sha)
+        {
+            if (sha == NULL) {
+                return BAD_FUNC_ARG;
+            }
+            return InitSha384_fips(sha);
+        }
+        int wc_InitSha384_ex(wc_Sha384* sha, void* heap, int devId)
+        {
+            (void)heap;
+            (void)devId;
+            if (sha == NULL) {
+                return BAD_FUNC_ARG;
+            }
+            return InitSha384_fips(sha);
+        }
+        int wc_Sha384Update(wc_Sha384* sha, const byte* data, word32 len)
+        {
+            if (sha == NULL || (data == NULL && len > 0)) {
+                return BAD_FUNC_ARG;
+            }
+            return Sha384Update_fips(sha, data, len);
+        }
+        int wc_Sha384Final(wc_Sha384* sha, byte* out)
+        {
+            if (sha == NULL || out == NULL) {
+                return BAD_FUNC_ARG;
+            }
+            return Sha384Final_fips(sha, out);
+        }
+        void wc_Sha384Free(wc_Sha384* sha)
+        {
+            (void)sha;
+            /* Not supported in FIPS */
+        }
+    #endif /* WOLFSSL_SHA384 || HAVE_AESGCM */
+
+#else /* else build without fips, or for FIPS v2 */
+
+#include <wolfssl/wolfcrypt/logging.h>
+
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+
+#if defined(USE_INTEL_SPEEDUP)
+    #if defined(__GNUC__) && ((__GNUC__ < 4) || \
+                              (__GNUC__ == 4 && __GNUC_MINOR__ <= 8))
+        #undef  NO_AVX2_SUPPORT
+        #define NO_AVX2_SUPPORT
+    #endif
+    #if defined(__clang__) && ((__clang_major__ < 3) || \
+                               (__clang_major__ == 3 && __clang_minor__ <= 5))
+        #define NO_AVX2_SUPPORT
+    #elif defined(__clang__) && defined(NO_AVX2_SUPPORT)
+        #undef NO_AVX2_SUPPORT
+    #endif
+
+    #define HAVE_INTEL_AVX1
+    #ifndef NO_AVX2_SUPPORT
+        #define HAVE_INTEL_AVX2
+    #endif
+#endif
+
+#if defined(HAVE_INTEL_AVX1)
+    /* #define DEBUG_XMM  */
+#endif
+
+#if defined(HAVE_INTEL_AVX2)
+    #define HAVE_INTEL_RORX
+    /* #define DEBUG_YMM  */
+#endif
+
+#if defined(HAVE_BYTEREVERSE64) && \
+        !defined(HAVE_INTEL_AVX1) && !defined(HAVE_INTEL_AVX2)
+    #define ByteReverseWords64(out, in, size) ByteReverseWords64_1(out, size)
+    #define ByteReverseWords64_1(buf, size) \
+        { unsigned int i ;\
+            for(i=0; i< size/sizeof(word64); i++){\
+                __asm__ volatile("bswapq %0":"+r"(buf[i])::) ;\
+            }\
+        }
+#endif
+
+#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
+    /* functions defined in wolfcrypt/src/port/caam/caam_sha.c */
+
+#else
+
+#ifdef WOLFSSL_SHA512
+
+static int InitSha512(wc_Sha512* sha512)
+{
+    if (sha512 == NULL)
+        return BAD_FUNC_ARG;
+
+    sha512->digest[0] = W64LIT(0x6a09e667f3bcc908);
+    sha512->digest[1] = W64LIT(0xbb67ae8584caa73b);
+    sha512->digest[2] = W64LIT(0x3c6ef372fe94f82b);
+    sha512->digest[3] = W64LIT(0xa54ff53a5f1d36f1);
+    sha512->digest[4] = W64LIT(0x510e527fade682d1);
+    sha512->digest[5] = W64LIT(0x9b05688c2b3e6c1f);
+    sha512->digest[6] = W64LIT(0x1f83d9abfb41bd6b);
+    sha512->digest[7] = W64LIT(0x5be0cd19137e2179);
+
+    sha512->buffLen = 0;
+    sha512->loLen   = 0;
+    sha512->hiLen   = 0;
+
+#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+
+    sha512->ctx.sha_type = SHA2_512;
+     /* always start firstblock = 1 when using hw engine */
+    sha512->ctx.isfirstblock = 1;
+    if(sha512->ctx.mode == ESP32_SHA_HW) {
+        /* release hw */
+        esp_sha_hw_unlock();
+    }
+    /* always set mode as INIT
+    *  whether using HW or SW is determined at first call of update()
+    */
+    sha512->ctx.mode = ESP32_SHA_INIT;
+#endif
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+    sha512->flags = 0;
+#endif
+    return 0;
+}
+
+#endif /* WOLFSSL_SHA512 */
+
+/* Hardware Acceleration */
+#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
+
+#ifdef WOLFSSL_SHA512
+
+    /*****
+    Intel AVX1/AVX2 Macro Control Structure
+
+    #if defined(HAVE_INteL_SPEEDUP)
+        #define HAVE_INTEL_AVX1
+        #define HAVE_INTEL_AVX2
+    #endif
+
+    int InitSha512(wc_Sha512* sha512) {
+         Save/Recover XMM, YMM
+         ...
+
+         Check Intel AVX cpuid flags
+    }
+
+    #if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2)
+      Transform_Sha512_AVX1(); # Function prototype
+      Transform_Sha512_AVX2(); #
+    #endif
+
+      _Transform_Sha512() {     # Native Transform Function body
+
+      }
+
+      int Sha512Update() {
+         Save/Recover XMM, YMM
+         ...
+      }
+
+      int Sha512Final() {
+         Save/Recover XMM, YMM
+         ...
+      }
+
+
+    #if defined(HAVE_INTEL_AVX1)
+
+       XMM Instructions/INLINE asm Definitions
+
+    #endif
+
+    #if defined(HAVE_INTEL_AVX2)
+
+       YMM Instructions/INLINE asm Definitions
+
+    #endif
+
+    #if defnied(HAVE_INTEL_AVX1)
+
+      int Transform_Sha512_AVX1() {
+          Stitched Message Sched/Round
+      }
+
+    #endif
+
+    #if defnied(HAVE_INTEL_AVX2)
+
+      int Transform_Sha512_AVX2() {
+          Stitched Message Sched/Round
+      }
+    #endif
+
+    */
+
+
+    /* Each platform needs to query info type 1 from cpuid to see if aesni is
+     * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts
+     */
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+    #if defined(HAVE_INTEL_AVX1)
+        extern int Transform_Sha512_AVX1(wc_Sha512 *sha512);
+        extern int Transform_Sha512_AVX1_Len(wc_Sha512 *sha512, word32 len);
+    #endif
+    #if defined(HAVE_INTEL_AVX2)
+        extern int Transform_Sha512_AVX2(wc_Sha512 *sha512);
+        extern int Transform_Sha512_AVX2_Len(wc_Sha512 *sha512, word32 len);
+        #if defined(HAVE_INTEL_RORX)
+            extern int Transform_Sha512_AVX1_RORX(wc_Sha512 *sha512);
+            extern int Transform_Sha512_AVX1_RORX_Len(wc_Sha512 *sha512,
+                                                      word32 len);
+            extern int Transform_Sha512_AVX2_RORX(wc_Sha512 *sha512);
+            extern int Transform_Sha512_AVX2_RORX_Len(wc_Sha512 *sha512,
+                                                      word32 len);
+        #endif
+    #endif
+
+#ifdef __cplusplus
+    }  /* extern "C" */
+#endif
+
+    static int _Transform_Sha512(wc_Sha512 *sha512);
+    static int (*Transform_Sha512_p)(wc_Sha512* sha512) = _Transform_Sha512;
+    static int (*Transform_Sha512_Len_p)(wc_Sha512* sha512, word32 len) = NULL;
+    static int transform_check = 0;
+    static int intel_flags;
+    #define Transform_Sha512(sha512)     (*Transform_Sha512_p)(sha512)
+    #define Transform_Sha512_Len(sha512, len) \
+                                          (*Transform_Sha512_Len_p)(sha512, len)
+
+    static void Sha512_SetTransform()
+    {
+        if (transform_check)
+            return;
+
+        intel_flags = cpuid_get_flags();
+
+    #if defined(HAVE_INTEL_AVX2)
+        if (IS_INTEL_AVX2(intel_flags)) {
+        #ifdef HAVE_INTEL_RORX
+            if (IS_INTEL_BMI2(intel_flags)) {
+                Transform_Sha512_p = Transform_Sha512_AVX2_RORX;
+                Transform_Sha512_Len_p = Transform_Sha512_AVX2_RORX_Len;
+            }
+            else
+        #endif
+            if (1) {
+                Transform_Sha512_p = Transform_Sha512_AVX2;
+                Transform_Sha512_Len_p = Transform_Sha512_AVX2_Len;
+            }
+        #ifdef HAVE_INTEL_RORX
+            else {
+                Transform_Sha512_p = Transform_Sha512_AVX1_RORX;
+                Transform_Sha512_Len_p = Transform_Sha512_AVX1_RORX_Len;
+            }
+        #endif
+        }
+        else
+    #endif
+    #if defined(HAVE_INTEL_AVX1)
+        if (IS_INTEL_AVX1(intel_flags)) {
+            Transform_Sha512_p = Transform_Sha512_AVX1;
+            Transform_Sha512_Len_p = Transform_Sha512_AVX1_Len;
+        }
+        else
+    #endif
+            Transform_Sha512_p = _Transform_Sha512;
+
+        transform_check = 1;
+    }
+#endif /* WOLFSSL_SHA512 */
+
+#else
+    #define Transform_Sha512(sha512) _Transform_Sha512(sha512)
+
+#endif
+
+#ifdef WOLFSSL_SHA512
+
+int wc_InitSha512_ex(wc_Sha512* sha512, void* heap, int devId)
+{
+    int ret = 0;
+
+    if (sha512 == NULL)
+        return BAD_FUNC_ARG;
+
+    sha512->heap = heap;
+
+    ret = InitSha512(sha512);
+    if (ret != 0)
+        return ret;
+
+#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
+    Sha512_SetTransform();
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+    sha512->W = NULL;
+#endif
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512)
+    ret = wolfAsync_DevCtxInit(&sha512->asyncDev,
+                        WOLFSSL_ASYNC_MARKER_SHA512, sha512->heap, devId);
+#else
+    (void)devId;
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    return ret;
+}
+
+#endif /* WOLFSSL_SHA512 */
+
+
+static const word64 K512[80] = {
+    W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd),
+    W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc),
+    W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019),
+    W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118),
+    W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe),
+    W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2),
+    W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1),
+    W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694),
+    W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3),
+    W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65),
+    W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483),
+    W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5),
+    W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210),
+    W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4),
+    W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725),
+    W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70),
+    W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926),
+    W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df),
+    W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8),
+    W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b),
+    W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001),
+    W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30),
+    W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910),
+    W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8),
+    W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53),
+    W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8),
+    W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb),
+    W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3),
+    W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60),
+    W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec),
+    W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9),
+    W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b),
+    W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207),
+    W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178),
+    W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6),
+    W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b),
+    W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493),
+    W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c),
+    W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a),
+    W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817)
+};
+
+#define blk0(i) (W[i] = sha512->buffer[i])
+
+#define blk2(i) (\
+               W[ i     & 15] += \
+            s1(W[(i-2)  & 15])+ \
+               W[(i-7)  & 15] + \
+            s0(W[(i-15) & 15])  \
+        )
+
+#define Ch(x,y,z)  (z ^ (x & (y ^ z)))
+#define Maj(x,y,z) ((x & y) | (z & (x | y)))
+
+#define a(i) T[(0-i) & 7]
+#define b(i) T[(1-i) & 7]
+#define c(i) T[(2-i) & 7]
+#define d(i) T[(3-i) & 7]
+#define e(i) T[(4-i) & 7]
+#define f(i) T[(5-i) & 7]
+#define g(i) T[(6-i) & 7]
+#define h(i) T[(7-i) & 7]
+
+#define S0(x) (rotrFixed64(x,28) ^ rotrFixed64(x,34) ^ rotrFixed64(x,39))
+#define S1(x) (rotrFixed64(x,14) ^ rotrFixed64(x,18) ^ rotrFixed64(x,41))
+#define s0(x) (rotrFixed64(x,1)  ^ rotrFixed64(x,8)  ^ (x>>7))
+#define s1(x) (rotrFixed64(x,19) ^ rotrFixed64(x,61) ^ (x>>6))
+
+#define R(i) \
+    h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[i+j] + (j ? blk2(i) : blk0(i)); \
+    d(i) += h(i); \
+    h(i) += S0(a(i)) + Maj(a(i),b(i),c(i))
+
+static int _Transform_Sha512(wc_Sha512* sha512)
+{
+    const word64* K = K512;
+    word32 j;
+    word64 T[8];
+
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+    word64* W = sha512->W;
+    if (W == NULL) {
+        W = (word64*) XMALLOC(sizeof(word64) * 16, NULL,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+        if (W == NULL)
+            return MEMORY_E;
+        sha512->W = W;
+    }
+#elif defined(WOLFSSL_SMALL_STACK)
+    word64* W;
+    W = (word64*) XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (W == NULL)
+        return MEMORY_E;
+#else
+    word64 W[16];
+#endif
+
+    /* Copy digest to working vars */
+    XMEMCPY(T, sha512->digest, sizeof(T));
+
+#ifdef USE_SLOW_SHA512
+    /* over twice as small, but 50% slower */
+    /* 80 operations, not unrolled */
+    for (j = 0; j < 80; j += 16) {
+        int m;
+        for (m = 0; m < 16; m++) { /* braces needed here for macros {} */
+            R(m);
+        }
+    }
+#else
+    /* 80 operations, partially loop unrolled */
+    for (j = 0; j < 80; j += 16) {
+        R( 0); R( 1); R( 2); R( 3);
+        R( 4); R( 5); R( 6); R( 7);
+        R( 8); R( 9); R(10); R(11);
+        R(12); R(13); R(14); R(15);
+    }
+#endif /* USE_SLOW_SHA512 */
+
+    /* Add the working vars back into digest */
+    sha512->digest[0] += a(0);
+    sha512->digest[1] += b(0);
+    sha512->digest[2] += c(0);
+    sha512->digest[3] += d(0);
+    sha512->digest[4] += e(0);
+    sha512->digest[5] += f(0);
+    sha512->digest[6] += g(0);
+    sha512->digest[7] += h(0);
+
+    /* Wipe variables */
+    ForceZero(W, sizeof(word64) * 16);
+    ForceZero(T, sizeof(T));
+
+#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
+    XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return 0;
+}
+
+
+static WC_INLINE void AddLength(wc_Sha512* sha512, word32 len)
+{
+    word64 tmp = sha512->loLen;
+    if ( (sha512->loLen += len) < tmp)
+        sha512->hiLen++;                       /* carry low to high */
+}
+
+static WC_INLINE int Sha512Update(wc_Sha512* sha512, const byte* data, word32 len)
+{
+    int ret = 0;
+    /* do block size increments */
+    byte* local = (byte*)sha512->buffer;
+
+    /* check that internal buffLen is valid */
+    if (sha512->buffLen >= WC_SHA512_BLOCK_SIZE)
+        return BUFFER_E;
+
+    AddLength(sha512, len);
+
+    if (sha512->buffLen > 0) {
+        word32 add = min(len, WC_SHA512_BLOCK_SIZE - sha512->buffLen);
+        if (add > 0) {
+            XMEMCPY(&local[sha512->buffLen], data, add);
+
+            sha512->buffLen += add;
+            data            += add;
+            len             -= add;
+        }
+
+        if (sha512->buffLen == WC_SHA512_BLOCK_SIZE) {
+    #if defined(LITTLE_ENDIAN_ORDER)
+        #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
+            if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags))
+        #endif
+            {
+        #if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \
+             defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+                ByteReverseWords64(sha512->buffer, sha512->buffer,
+                                                         WC_SHA512_BLOCK_SIZE);
+        #endif
+            }
+    #endif
+    #if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \
+         defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+            ret = Transform_Sha512(sha512);
+    #else
+            if(sha512->ctx.mode == ESP32_SHA_INIT) {
+                esp_sha_try_hw_lock(&sha512->ctx);
+            }
+            ret = esp_sha512_process(sha512);
+            if(ret == 0 && sha512->ctx.mode == ESP32_SHA_SW){
+                ret = Transform_Sha512(sha512);
+            }
+    #endif
+            if (ret == 0)
+                sha512->buffLen = 0;
+            else
+                len = 0;
+        }
+    }
+
+#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
+    if (Transform_Sha512_Len_p != NULL) {
+        word32 blocksLen = len & ~(WC_SHA512_BLOCK_SIZE-1);
+
+        if (blocksLen > 0) {
+            sha512->data = data;
+            /* Byte reversal performed in function if required. */
+            Transform_Sha512_Len(sha512, blocksLen);
+            data += blocksLen;
+            len  -= blocksLen;
+        }
+    }
+    else
+#endif
+#if !defined(LITTLE_ENDIAN_ORDER) || defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
+    {
+        while (len >= WC_SHA512_BLOCK_SIZE) {
+            XMEMCPY(local, data, WC_SHA512_BLOCK_SIZE);
+
+            data += WC_SHA512_BLOCK_SIZE;
+            len  -= WC_SHA512_BLOCK_SIZE;
+
+        #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
+            if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags))
+            {
+                ByteReverseWords64(sha512->buffer, sha512->buffer,
+                                                          WC_SHA512_BLOCK_SIZE);
+            }
+        #endif
+            /* Byte reversal performed in function if required. */
+            ret = Transform_Sha512(sha512);
+            if (ret != 0)
+                break;
+        }
+    }
+#else
+    {
+        while (len >= WC_SHA512_BLOCK_SIZE) {
+            XMEMCPY(local, data, WC_SHA512_BLOCK_SIZE);
+
+            data += WC_SHA512_BLOCK_SIZE;
+            len  -= WC_SHA512_BLOCK_SIZE;
+    #if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \
+         defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+            ByteReverseWords64(sha512->buffer, sha512->buffer,
+                                                       WC_SHA512_BLOCK_SIZE);
+    #endif
+    #if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \
+         defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+            ret = Transform_Sha512(sha512);
+    #else
+            if(sha512->ctx.mode == ESP32_SHA_INIT) {
+                esp_sha_try_hw_lock(&sha512->ctx);
+            }
+            ret = esp_sha512_process(sha512);
+            if(ret == 0 && sha512->ctx.mode == ESP32_SHA_SW){
+                ret = Transform_Sha512(sha512);
+            }
+    #endif
+            if (ret != 0)
+                break;
+        }
+    }
+#endif
+
+    if (len > 0) {
+        XMEMCPY(local, data, len);
+        sha512->buffLen = len;
+    }
+
+    return ret;
+}
+
+#ifdef WOLFSSL_SHA512
+
+int wc_Sha512Update(wc_Sha512* sha512, const byte* data, word32 len)
+{
+    if (sha512 == NULL || (data == NULL && len > 0)) {
+        return BAD_FUNC_ARG;
+    }
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512)
+    if (sha512->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA512) {
+    #if defined(HAVE_INTEL_QA)
+        return IntelQaSymSha512(&sha512->asyncDev, NULL, data, len);
+    #endif
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    return Sha512Update(sha512, data, len);
+}
+
+#endif /* WOLFSSL_SHA512 */
+
+#endif /* WOLFSSL_IMX6_CAAM */
+
+static WC_INLINE int Sha512Final(wc_Sha512* sha512)
+{
+    byte* local = (byte*)sha512->buffer;
+    int ret;
+
+    if (sha512 == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    local[sha512->buffLen++] = 0x80;  /* add 1 */
+
+    /* pad with zeros */
+    if (sha512->buffLen > WC_SHA512_PAD_SIZE) {
+        XMEMSET(&local[sha512->buffLen], 0, WC_SHA512_BLOCK_SIZE - sha512->buffLen);
+        sha512->buffLen += WC_SHA512_BLOCK_SIZE - sha512->buffLen;
+#if defined(LITTLE_ENDIAN_ORDER)
+    #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
+        if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags))
+    #endif
+        {
+
+       #if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \
+            defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+            ByteReverseWords64(sha512->buffer,sha512->buffer,
+                                                         WC_SHA512_BLOCK_SIZE);
+       #endif
+        }
+#endif /* LITTLE_ENDIAN_ORDER */
+#if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \
+     defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+        ret = Transform_Sha512(sha512);
+#else
+       if(sha512->ctx.mode == ESP32_SHA_INIT) {
+            esp_sha_try_hw_lock(&sha512->ctx);
+       }
+        ret = esp_sha512_process(sha512);
+        if(ret == 0 && sha512->ctx.mode == ESP32_SHA_SW){
+            ret = Transform_Sha512(sha512);
+        }
+#endif
+        if (ret != 0)
+            return ret;
+
+        sha512->buffLen = 0;
+    }
+    XMEMSET(&local[sha512->buffLen], 0, WC_SHA512_PAD_SIZE - sha512->buffLen);
+
+    /* put lengths in bits */
+    sha512->hiLen = (sha512->loLen >> (8 * sizeof(sha512->loLen) - 3)) +
+                                                         (sha512->hiLen << 3);
+    sha512->loLen = sha512->loLen << 3;
+
+    /* store lengths */
+#if defined(LITTLE_ENDIAN_ORDER)
+    #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
+        if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags))
+    #endif
+    #if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \
+         defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+            ByteReverseWords64(sha512->buffer, sha512->buffer, WC_SHA512_PAD_SIZE);
+    #endif
+#endif
+    /* ! length ordering dependent on digest endian type ! */
+
+#if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \
+     defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+    sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2] = sha512->hiLen;
+    sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 1] = sha512->loLen;
+#endif
+
+#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
+    if (IS_INTEL_AVX1(intel_flags) || IS_INTEL_AVX2(intel_flags))
+        ByteReverseWords64(&(sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2]),
+                           &(sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2]),
+                           WC_SHA512_BLOCK_SIZE - WC_SHA512_PAD_SIZE);
+#endif
+#if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \
+    defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+    ret = Transform_Sha512(sha512);
+#else
+    if(sha512->ctx.mode == ESP32_SHA_INIT) {
+        esp_sha_try_hw_lock(&sha512->ctx);
+    }
+    ret = esp_sha512_digest_process(sha512, 1);
+    if(ret == 0 && sha512->ctx.mode == ESP32_SHA_SW) {
+        ret = Transform_Sha512(sha512);
+    }
+#endif
+    if (ret != 0)
+        return ret;
+
+    #ifdef LITTLE_ENDIAN_ORDER
+        ByteReverseWords64(sha512->digest, sha512->digest, WC_SHA512_DIGEST_SIZE);
+    #endif
+
+    return 0;
+}
+
+#ifdef WOLFSSL_SHA512
+
+int wc_Sha512FinalRaw(wc_Sha512* sha512, byte* hash)
+{
+#ifdef LITTLE_ENDIAN_ORDER
+    word64 digest[WC_SHA512_DIGEST_SIZE / sizeof(word64)];
+#endif
+
+    if (sha512 == NULL || hash == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef LITTLE_ENDIAN_ORDER
+    ByteReverseWords64((word64*)digest, (word64*)sha512->digest,
+                                                         WC_SHA512_DIGEST_SIZE);
+    XMEMCPY(hash, digest, WC_SHA512_DIGEST_SIZE);
+#else
+    XMEMCPY(hash, sha512->digest, WC_SHA512_DIGEST_SIZE);
+#endif
+
+    return 0;
+}
+
+int wc_Sha512Final(wc_Sha512* sha512, byte* hash)
+{
+    int ret;
+
+    if (sha512 == NULL || hash == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512)
+    if (sha512->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA512) {
+    #if defined(HAVE_INTEL_QA)
+        return IntelQaSymSha512(&sha512->asyncDev, hash, NULL,
+                                            WC_SHA512_DIGEST_SIZE);
+    #endif
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    ret = Sha512Final(sha512);
+    if (ret != 0)
+        return ret;
+
+    XMEMCPY(hash, sha512->digest, WC_SHA512_DIGEST_SIZE);
+
+    return InitSha512(sha512);  /* reset state */
+}
+
+int wc_InitSha512(wc_Sha512* sha512)
+{
+    return wc_InitSha512_ex(sha512, NULL, INVALID_DEVID);
+}
+
+void wc_Sha512Free(wc_Sha512* sha512)
+{
+    if (sha512 == NULL)
+        return;
+
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+    if (sha512->W != NULL) {
+        XFREE(sha512->W, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        sha512->W = NULL;
+    }
+#endif
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512)
+    wolfAsync_DevCtxFree(&sha512->asyncDev, WOLFSSL_ASYNC_MARKER_SHA512);
+#endif /* WOLFSSL_ASYNC_CRYPT */
+}
+
+#endif /* WOLFSSL_SHA512 */
+
+/* -------------------------------------------------------------------------- */
+/* SHA384 */
+/* -------------------------------------------------------------------------- */
+#ifdef WOLFSSL_SHA384
+
+#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
+    /* functions defined in wolfcrypt/src/port/caam/caam_sha.c */
+
+#else
+
+static int InitSha384(wc_Sha384* sha384)
+{
+    if (sha384 == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    sha384->digest[0] = W64LIT(0xcbbb9d5dc1059ed8);
+    sha384->digest[1] = W64LIT(0x629a292a367cd507);
+    sha384->digest[2] = W64LIT(0x9159015a3070dd17);
+    sha384->digest[3] = W64LIT(0x152fecd8f70e5939);
+    sha384->digest[4] = W64LIT(0x67332667ffc00b31);
+    sha384->digest[5] = W64LIT(0x8eb44a8768581511);
+    sha384->digest[6] = W64LIT(0xdb0c2e0d64f98fa7);
+    sha384->digest[7] = W64LIT(0x47b5481dbefa4fa4);
+
+    sha384->buffLen = 0;
+    sha384->loLen   = 0;
+    sha384->hiLen   = 0;
+
+#if  defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+    sha384->ctx.sha_type = SHA2_384;
+     /* always start firstblock = 1 when using hw engine */
+    sha384->ctx.isfirstblock = 1;
+    if(sha384->ctx.mode == ESP32_SHA_HW) {
+        /* release hw */
+        esp_sha_hw_unlock();
+    }
+    /* always set mode as INIT
+    *  whether using HW or SW is determined at first call of update()
+    */
+    sha384->ctx.mode = ESP32_SHA_INIT;
+
+#endif
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+    sha384->flags = 0;
+#endif
+
+    return 0;
+}
+
+int wc_Sha384Update(wc_Sha384* sha384, const byte* data, word32 len)
+{
+    if (sha384 == NULL || (data == NULL && len > 0)) {
+        return BAD_FUNC_ARG;
+    }
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384)
+    if (sha384->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA384) {
+    #if defined(HAVE_INTEL_QA)
+        return IntelQaSymSha384(&sha384->asyncDev, NULL, data, len);
+    #endif
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    return Sha512Update((wc_Sha512*)sha384, data, len);
+}
+
+
+int wc_Sha384FinalRaw(wc_Sha384* sha384, byte* hash)
+{
+#ifdef LITTLE_ENDIAN_ORDER
+    word64 digest[WC_SHA384_DIGEST_SIZE / sizeof(word64)];
+#endif
+
+    if (sha384 == NULL || hash == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef LITTLE_ENDIAN_ORDER
+    ByteReverseWords64((word64*)digest, (word64*)sha384->digest,
+                                                         WC_SHA384_DIGEST_SIZE);
+    XMEMCPY(hash, digest, WC_SHA384_DIGEST_SIZE);
+#else
+    XMEMCPY(hash, sha384->digest, WC_SHA384_DIGEST_SIZE);
+#endif
+
+    return 0;
+}
+
+int wc_Sha384Final(wc_Sha384* sha384, byte* hash)
+{
+    int ret;
+
+    if (sha384 == NULL || hash == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384)
+    if (sha384->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA384) {
+    #if defined(HAVE_INTEL_QA)
+        return IntelQaSymSha384(&sha384->asyncDev, hash, NULL,
+                                            WC_SHA384_DIGEST_SIZE);
+    #endif
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    ret = Sha512Final((wc_Sha512*)sha384);
+    if (ret != 0)
+        return ret;
+
+    XMEMCPY(hash, sha384->digest, WC_SHA384_DIGEST_SIZE);
+
+    return InitSha384(sha384);  /* reset state */
+}
+
+int wc_InitSha384_ex(wc_Sha384* sha384, void* heap, int devId)
+{
+    int ret;
+
+    if (sha384 == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    sha384->heap = heap;
+    ret = InitSha384(sha384);
+    if (ret != 0)
+        return ret;
+
+#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
+    Sha512_SetTransform();
+#endif
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+    sha384->W = NULL;
+#endif
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384)
+    ret = wolfAsync_DevCtxInit(&sha384->asyncDev, WOLFSSL_ASYNC_MARKER_SHA384,
+                                                           sha384->heap, devId);
+#else
+    (void)devId;
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    return ret;
+}
+
+#endif /* WOLFSSL_IMX6_CAAM */
+
+int wc_InitSha384(wc_Sha384* sha384)
+{
+    return wc_InitSha384_ex(sha384, NULL, INVALID_DEVID);
+}
+
+void wc_Sha384Free(wc_Sha384* sha384)
+{
+    if (sha384 == NULL)
+        return;
+
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+    if (sha384->W != NULL) {
+        XFREE(sha384->W, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        sha384->W = NULL;
+    }
+#endif
+
+#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384)
+    wolfAsync_DevCtxFree(&sha384->asyncDev, WOLFSSL_ASYNC_MARKER_SHA384);
+#endif /* WOLFSSL_ASYNC_CRYPT */
+}
+
+#endif /* WOLFSSL_SHA384 */
+
+#endif /* HAVE_FIPS */
+
+#ifdef WOLFSSL_SHA512
+
+int wc_Sha512GetHash(wc_Sha512* sha512, byte* hash)
+{
+    int ret;
+    wc_Sha512 tmpSha512;
+
+    if (sha512 == NULL || hash == NULL)
+        return BAD_FUNC_ARG;
+
+#if  defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+    if(sha512->ctx.mode == ESP32_SHA_INIT) {
+        esp_sha_try_hw_lock(&sha512->ctx);
+    }
+    if(sha512->ctx.mode != ESP32_SHA_SW)
+       esp_sha512_digest_process(sha512, 0);
+#endif
+
+    ret = wc_Sha512Copy(sha512, &tmpSha512);
+    if (ret == 0) {
+        ret = wc_Sha512Final(&tmpSha512, hash);
+#if  defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+        sha512->ctx.mode = ESP32_SHA_SW;;
+#endif
+        wc_Sha512Free(&tmpSha512);
+    }
+    return ret;
+}
+
+int wc_Sha512Copy(wc_Sha512* src, wc_Sha512* dst)
+{
+    int ret = 0;
+
+    if (src == NULL || dst == NULL)
+        return BAD_FUNC_ARG;
+
+    XMEMCPY(dst, src, sizeof(wc_Sha512));
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+    dst->W = NULL;
+#endif
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev);
+#endif
+#if  defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+    dst->ctx.mode = src->ctx.mode;
+    dst->ctx.isfirstblock = src->ctx.isfirstblock;
+    dst->ctx.sha_type = src->ctx.sha_type;
+#endif
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+     dst->flags |= WC_HASH_FLAG_ISCOPY;
+#endif
+
+    return ret;
+}
+
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+int wc_Sha512SetFlags(wc_Sha512* sha512, word32 flags)
+{
+    if (sha512) {
+        sha512->flags = flags;
+    }
+    return 0;
+}
+int wc_Sha512GetFlags(wc_Sha512* sha512, word32* flags)
+{
+    if (sha512 && flags) {
+        *flags = sha512->flags;
+    }
+    return 0;
+}
+#endif
+
+#endif /* WOLFSSL_SHA512 */
+
+#ifdef WOLFSSL_SHA384
+
+int wc_Sha384GetHash(wc_Sha384* sha384, byte* hash)
+{
+    int ret;
+    wc_Sha384 tmpSha384;
+
+    if (sha384 == NULL || hash == NULL)
+        return BAD_FUNC_ARG;
+#if  defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+    if(sha384->ctx.mode == ESP32_SHA_INIT) {
+        esp_sha_try_hw_lock(&sha384->ctx);
+    }
+    if(sha384->ctx.mode != ESP32_SHA_SW) {
+        esp_sha512_digest_process(sha384, 0);
+    }
+#endif
+    ret = wc_Sha384Copy(sha384, &tmpSha384);
+    if (ret == 0) {
+        ret = wc_Sha384Final(&tmpSha384, hash);
+#if  defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+        sha384->ctx.mode = ESP32_SHA_SW;
+#endif
+        wc_Sha384Free(&tmpSha384);
+    }
+    return ret;
+}
+int wc_Sha384Copy(wc_Sha384* src, wc_Sha384* dst)
+{
+    int ret = 0;
+
+    if (src == NULL || dst == NULL)
+        return BAD_FUNC_ARG;
+
+    XMEMCPY(dst, src, sizeof(wc_Sha384));
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+    dst->W = NULL;
+#endif
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev);
+#endif
+#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+   !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+    dst->ctx.mode = src->ctx.mode;
+    dst->ctx.isfirstblock = src->ctx.isfirstblock;
+    dst->ctx.sha_type = src->ctx.sha_type;
+#endif
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+     dst->flags |= WC_HASH_FLAG_ISCOPY;
+#endif
+
+    return ret;
+}
+
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+int wc_Sha384SetFlags(wc_Sha384* sha384, word32 flags)
+{
+    if (sha384) {
+        sha384->flags = flags;
+    }
+    return 0;
+}
+int wc_Sha384GetFlags(wc_Sha384* sha384, word32* flags)
+{
+    if (sha384 && flags) {
+        *flags = sha384->flags;
+    }
+    return 0;
+}
+#endif
+
+#endif /* WOLFSSL_SHA384 */
+
+#endif /* WOLFSSL_SHA512 || WOLFSSL_SHA384 */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/wc_encrypt.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/wc_encrypt.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/wc_encrypt.c	(revision 453)
@@ -0,0 +1,660 @@
+/* wc_encrypt.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+#include <wolfssl/wolfcrypt/aes.h>
+#include <wolfssl/wolfcrypt/des3.h>
+#include <wolfssl/wolfcrypt/hash.h>
+#include <wolfssl/wolfcrypt/arc4.h>
+#include <wolfssl/wolfcrypt/wc_encrypt.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#include <wolfssl/wolfcrypt/asn.h>
+#include <wolfssl/wolfcrypt/coding.h>
+#include <wolfssl/wolfcrypt/pwdbased.h>
+#include <wolfssl/wolfcrypt/logging.h>
+
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+#if !defined(NO_AES) && defined(HAVE_AES_CBC)
+#ifdef HAVE_AES_DECRYPT
+int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz,
+                                  const byte* key, word32 keySz, const byte* iv)
+{
+    int  ret = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    Aes* aes = NULL;
+#else
+    Aes  aes[1];
+#endif
+
+    if (out == NULL || in == NULL || key == NULL || iv == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    aes = (Aes*)XMALLOC(sizeof(Aes), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (aes == NULL)
+        return MEMORY_E;
+#endif
+
+    ret = wc_AesInit(aes, NULL, INVALID_DEVID);
+    if (ret == 0) {
+        ret = wc_AesSetKey(aes, key, keySz, iv, AES_DECRYPTION);
+        if (ret == 0)
+            ret = wc_AesCbcDecrypt(aes, out, in, inSz);
+
+        wc_AesFree(aes);
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(aes, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return ret;
+}
+#endif /* HAVE_AES_DECRYPT */
+
+int wc_AesCbcEncryptWithKey(byte* out, const byte* in, word32 inSz,
+                            const byte* key, word32 keySz, const byte* iv)
+{
+    int  ret = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    Aes* aes;
+#else
+    Aes  aes[1];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+    aes = (Aes*)XMALLOC(sizeof(Aes), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (aes == NULL)
+        return MEMORY_E;
+#endif
+
+    ret = wc_AesInit(aes, NULL, INVALID_DEVID);
+    if (ret == 0) {
+        ret = wc_AesSetKey(aes, key, keySz, iv, AES_ENCRYPTION);
+        if (ret == 0)
+            ret = wc_AesCbcEncrypt(aes, out, in, inSz);
+
+        wc_AesFree(aes);
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(aes, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return ret;
+}
+#endif /* !NO_AES && HAVE_AES_CBC */
+
+
+#if !defined(NO_DES3) && !defined(WOLFSSL_TI_CRYPT)
+int wc_Des_CbcEncryptWithKey(byte* out, const byte* in, word32 sz,
+                             const byte* key, const byte* iv)
+{
+    int ret  = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    Des* des;
+#else
+    Des  des[1];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+    des = (Des*)XMALLOC(sizeof(Des), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (des == NULL)
+        return MEMORY_E;
+#endif
+
+    ret = wc_Des_SetKey(des, key, iv, DES_ENCRYPTION);
+    if (ret == 0)
+        ret = wc_Des_CbcEncrypt(des, out, in, sz);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(des, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return ret;
+}
+
+int wc_Des_CbcDecryptWithKey(byte* out, const byte* in, word32 sz,
+                             const byte* key, const byte* iv)
+{
+    int ret  = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    Des* des;
+#else
+    Des  des[1];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+    des = (Des*)XMALLOC(sizeof(Des), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (des == NULL)
+        return MEMORY_E;
+#endif
+
+    ret = wc_Des_SetKey(des, key, iv, DES_DECRYPTION);
+    if (ret == 0)
+        ret = wc_Des_CbcDecrypt(des, out, in, sz);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(des, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return ret;
+}
+
+
+int wc_Des3_CbcEncryptWithKey(byte* out, const byte* in, word32 sz,
+                              const byte* key, const byte* iv)
+{
+    int ret    = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    Des3* des3;
+#else
+    Des3  des3[1];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+    des3 = (Des3*)XMALLOC(sizeof(Des3), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (des3 == NULL)
+        return MEMORY_E;
+#endif
+
+    ret = wc_Des3Init(des3, NULL, INVALID_DEVID);
+    if (ret == 0) {
+        ret = wc_Des3_SetKey(des3, key, iv, DES_ENCRYPTION);
+        if (ret == 0)
+            ret = wc_Des3_CbcEncrypt(des3, out, in, sz);
+        wc_Des3Free(des3);
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(des3, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return ret;
+}
+
+
+int wc_Des3_CbcDecryptWithKey(byte* out, const byte* in, word32 sz,
+                              const byte* key, const byte* iv)
+{
+    int ret    = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    Des3* des3;
+#else
+    Des3  des3[1];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+    des3 = (Des3*)XMALLOC(sizeof(Des3), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (des3 == NULL)
+        return MEMORY_E;
+#endif
+
+    ret = wc_Des3Init(des3, NULL, INVALID_DEVID);
+    if (ret == 0) {
+        ret = wc_Des3_SetKey(des3, key, iv, DES_DECRYPTION);
+        if (ret == 0)
+            ret = wc_Des3_CbcDecrypt(des3, out, in, sz);
+        wc_Des3Free(des3);
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(des3, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return ret;
+}
+
+#endif /* !NO_DES3 */
+
+
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+
+int wc_BufferKeyDecrypt(EncryptedInfo* info, byte* der, word32 derSz,
+    const byte* password, int passwordSz, int hashType)
+{
+    int ret = NOT_COMPILED_IN;
+#ifdef WOLFSSL_SMALL_STACK
+    byte* key      = NULL;
+#else
+    byte  key[WC_MAX_SYM_KEY_SIZE];
+#endif
+
+    (void)derSz;
+    (void)passwordSz;
+    (void)hashType;
+
+    if (der == NULL || password == NULL || info == NULL || info->keySz == 0) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* use file's salt for key derivation, hex decode first */
+    if (Base16_Decode(info->iv, info->ivSz, info->iv, &info->ivSz) != 0) {
+        return BUFFER_E;
+    }
+    if (info->ivSz < PKCS5_SALT_SZ)
+        return BUFFER_E;
+
+#ifdef WOLFSSL_SMALL_STACK
+    key = (byte*)XMALLOC(WC_MAX_SYM_KEY_SIZE, NULL, DYNAMIC_TYPE_SYMMETRIC_KEY);
+    if (key == NULL) {
+        return MEMORY_E;
+    }
+#endif
+
+    (void)XMEMSET(key, 0, WC_MAX_SYM_KEY_SIZE);
+
+#ifndef NO_PWDBASED
+    if ((ret = wc_PBKDF1(key, password, passwordSz, info->iv, PKCS5_SALT_SZ, 1,
+                                        info->keySz, hashType)) != 0) {
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(key, NULL, DYNAMIC_TYPE_SYMMETRIC_KEY);
+#endif
+        return ret;
+    }
+#endif
+
+#ifndef NO_DES3
+    if (info->cipherType == WC_CIPHER_DES)
+        ret = wc_Des_CbcDecryptWithKey(der, der, derSz, key, info->iv);
+    if (info->cipherType == WC_CIPHER_DES3)
+        ret = wc_Des3_CbcDecryptWithKey(der, der, derSz, key, info->iv);
+#endif /* NO_DES3 */
+#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(HAVE_AES_DECRYPT)
+    if (info->cipherType == WC_CIPHER_AES_CBC)
+        ret = wc_AesCbcDecryptWithKey(der, der, derSz, key, info->keySz,
+            info->iv);
+#endif /* !NO_AES && HAVE_AES_CBC && HAVE_AES_DECRYPT */
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(key, NULL, DYNAMIC_TYPE_SYMMETRIC_KEY);
+#endif
+
+    return ret;
+}
+
+int wc_BufferKeyEncrypt(EncryptedInfo* info, byte* der, word32 derSz,
+    const byte* password, int passwordSz, int hashType)
+{
+    int ret = NOT_COMPILED_IN;
+#ifdef WOLFSSL_SMALL_STACK
+    byte* key      = NULL;
+#else
+    byte  key[WC_MAX_SYM_KEY_SIZE];
+#endif
+
+    (void)derSz;
+    (void)passwordSz;
+    (void)hashType;
+
+    if (der == NULL || password == NULL || info == NULL || info->keySz == 0 ||
+            info->ivSz < PKCS5_SALT_SZ) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    key = (byte*)XMALLOC(WC_MAX_SYM_KEY_SIZE, NULL, DYNAMIC_TYPE_SYMMETRIC_KEY);
+    if (key == NULL) {
+        return MEMORY_E;
+    }
+#endif /* WOLFSSL_SMALL_STACK */
+
+    (void)XMEMSET(key, 0, WC_MAX_SYM_KEY_SIZE);
+
+#ifndef NO_PWDBASED
+    if ((ret = wc_PBKDF1(key, password, passwordSz, info->iv, PKCS5_SALT_SZ, 1,
+                                        info->keySz, hashType)) != 0) {
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(key, NULL, DYNAMIC_TYPE_SYMMETRIC_KEY);
+#endif
+        return ret;
+    }
+#endif
+
+#ifndef NO_DES3
+    if (info->cipherType == WC_CIPHER_DES)
+        ret = wc_Des_CbcEncryptWithKey(der, der, derSz, key, info->iv);
+    if (info->cipherType == WC_CIPHER_DES3)
+        ret = wc_Des3_CbcEncryptWithKey(der, der, derSz, key, info->iv);
+#endif /* NO_DES3 */
+#if !defined(NO_AES) && defined(HAVE_AES_CBC)
+    if (info->cipherType == WC_CIPHER_AES_CBC)
+        ret = wc_AesCbcEncryptWithKey(der, der, derSz, key, info->keySz,
+            info->iv);
+#endif /* !NO_AES && HAVE_AES_CBC */
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(key, NULL, DYNAMIC_TYPE_SYMMETRIC_KEY);
+#endif
+
+    return ret;
+}
+
+#endif /* WOLFSSL_ENCRYPTED_KEYS */
+
+
+#if !defined(NO_PWDBASED) && !defined(NO_ASN)
+
+#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12)
+/* Decrypt/Encrypt input in place from parameters based on id
+ *
+ * returns a negative value on fail case
+ */
+int wc_CryptKey(const char* password, int passwordSz, byte* salt,
+                      int saltSz, int iterations, int id, byte* input,
+                      int length, int version, byte* cbcIv, int enc, int shaOid)
+{
+    int typeH;
+    int derivedLen = 0;
+    int ret = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    byte* key;
+#else
+    byte key[MAX_KEY_SIZE];
+#endif
+
+    (void)input;
+    (void)length;
+    (void)enc;
+
+    WOLFSSL_ENTER("wc_CryptKey");
+
+    switch (id) {
+    #ifndef NO_DES3
+        #ifndef NO_MD5
+        case PBE_MD5_DES:
+            typeH = WC_MD5;
+            derivedLen = 16;           /* may need iv for v1.5 */
+            break;
+        #endif
+        #ifndef NO_SHA
+        case PBE_SHA1_DES:
+            typeH = WC_SHA;
+            derivedLen = 16;           /* may need iv for v1.5 */
+            break;
+
+        case PBE_SHA1_DES3:
+            switch(shaOid) {
+                case HMAC_SHA256_OID:
+                    typeH = WC_SHA256;
+                    derivedLen = 32;
+                    break;
+                default:
+                    typeH = WC_SHA;
+                    derivedLen = 32;           /* may need iv for v1.5 */
+                    break;
+            }
+        break;
+        #endif /* !NO_SHA */
+    #endif /* !NO_DES3 */
+    #if !defined(NO_SHA) && !defined(NO_RC4)
+        case PBE_SHA1_RC4_128:
+            typeH = WC_SHA;
+            derivedLen = 16;
+            break;
+    #endif
+    #if defined(WOLFSSL_AES_256)
+        case PBE_AES256_CBC:
+            switch(shaOid) {
+                case HMAC_SHA256_OID:
+                    typeH = WC_SHA256;
+                    derivedLen = 32;
+                    break;
+            #ifndef NO_SHA
+                default:
+                    typeH = WC_SHA;
+                    derivedLen = 32;
+                    break;
+            #endif
+            }
+            break;
+    #endif /* WOLFSSL_AES_256 && !NO_SHA */
+    #if defined(WOLFSSL_AES_128)
+        case PBE_AES128_CBC:
+            switch(shaOid) {
+                case HMAC_SHA256_OID:
+                    typeH = WC_SHA256;
+                    derivedLen = 16;
+                    break;
+            #ifndef NO_SHA
+                default:
+                    typeH = WC_SHA;
+                    derivedLen = 16;
+                    break;
+            #endif
+            }
+            break;
+    #endif /* WOLFSSL_AES_128 && !NO_SHA */
+        default:
+            WOLFSSL_MSG("Unknown/Unsupported encrypt/decrypt id");
+            (void)shaOid;
+            return ALGO_ID_E;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    key = (byte*)XMALLOC(MAX_KEY_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (key == NULL)
+        return MEMORY_E;
+#endif
+
+    if (version == PKCS5v2)
+        ret = wc_PBKDF2(key, (byte*)password, passwordSz,
+                        salt, saltSz, iterations, derivedLen, typeH);
+#ifndef NO_SHA
+    else if (version == PKCS5)
+        ret = wc_PBKDF1(key, (byte*)password, passwordSz,
+                        salt, saltSz, iterations, derivedLen, typeH);
+#endif
+#ifdef HAVE_PKCS12
+    else if (version == PKCS12v1) {
+        int  i, idx = 0;
+        byte unicodePasswd[MAX_UNICODE_SZ];
+
+        if ( (passwordSz * 2 + 2) > (int)sizeof(unicodePasswd)) {
+#ifdef WOLFSSL_SMALL_STACK
+            XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+            return UNICODE_SIZE_E;
+        }
+
+        for (i = 0; i < passwordSz; i++) {
+            unicodePasswd[idx++] = 0x00;
+            unicodePasswd[idx++] = (byte)password[i];
+        }
+        /* add trailing NULL */
+        unicodePasswd[idx++] = 0x00;
+        unicodePasswd[idx++] = 0x00;
+
+        ret =  wc_PKCS12_PBKDF(key, unicodePasswd, idx, salt, saltSz,
+                            iterations, derivedLen, typeH, 1);
+        if (id != PBE_SHA1_RC4_128)
+            ret += wc_PKCS12_PBKDF(cbcIv, unicodePasswd, idx, salt, saltSz,
+                                iterations, 8, typeH, 2);
+    }
+#endif /* HAVE_PKCS12 */
+    else {
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+        WOLFSSL_MSG("Unknown/Unsupported PKCS version");
+        return ALGO_ID_E;
+    }
+
+    if (ret != 0) {
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+        return ret;
+    }
+
+    switch (id) {
+#ifndef NO_DES3
+    #if !defined(NO_SHA) || !defined(NO_MD5)
+        case PBE_MD5_DES:
+        case PBE_SHA1_DES:
+        {
+            Des    des;
+            byte*  desIv = key + 8;
+
+            if (version == PKCS5v2 || version == PKCS12v1)
+                desIv = cbcIv;
+
+            if (enc) {
+                ret = wc_Des_SetKey(&des, key, desIv, DES_ENCRYPTION);
+            }
+            else {
+                ret = wc_Des_SetKey(&des, key, desIv, DES_DECRYPTION);
+            }
+            if (ret != 0) {
+#ifdef WOLFSSL_SMALL_STACK
+                XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+                return ret;
+            }
+
+            if (enc) {
+                wc_Des_CbcEncrypt(&des, input, input, length);
+            }
+            else {
+                wc_Des_CbcDecrypt(&des, input, input, length);
+            }
+            break;
+        }
+    #endif /* !NO_SHA || !NO_MD5 */
+
+    #ifndef NO_SHA
+        case PBE_SHA1_DES3:
+        {
+            Des3   des;
+            byte*  desIv = key + 24;
+
+            if (version == PKCS5v2 || version == PKCS12v1)
+                desIv = cbcIv;
+
+            ret = wc_Des3Init(&des, NULL, INVALID_DEVID);
+            if (ret != 0) {
+#ifdef WOLFSSL_SMALL_STACK
+                XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+                return ret;
+            }
+            if (enc) {
+                ret = wc_Des3_SetKey(&des, key, desIv, DES_ENCRYPTION);
+            }
+            else {
+                ret = wc_Des3_SetKey(&des, key, desIv, DES_DECRYPTION);
+            }
+            if (ret != 0) {
+#ifdef WOLFSSL_SMALL_STACK
+                XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+                return ret;
+            }
+            if (enc) {
+                ret = wc_Des3_CbcEncrypt(&des, input, input, length);
+            }
+            else {
+                ret = wc_Des3_CbcDecrypt(&des, input, input, length);
+            }
+            if (ret != 0) {
+#ifdef WOLFSSL_SMALL_STACK
+                XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+                return ret;
+            }
+            break;
+        }
+    #endif /* !NO_SHA */
+#endif
+#if !defined(NO_RC4) && !defined(NO_SHA)
+        case PBE_SHA1_RC4_128:
+        {
+            Arc4    dec;
+
+            wc_Arc4SetKey(&dec, key, derivedLen);
+            wc_Arc4Process(&dec, input, input, length);
+            break;
+        }
+#endif
+#if !defined(NO_AES) && defined(HAVE_AES_CBC)
+    #ifdef WOLFSSL_AES_256
+        case PBE_AES256_CBC:
+        case PBE_AES128_CBC:
+        {
+            Aes aes;
+            ret = wc_AesInit(&aes, NULL, INVALID_DEVID);
+            if (ret == 0) {
+                if (enc) {
+                    ret = wc_AesSetKey(&aes, key, derivedLen, cbcIv,
+                                                                AES_ENCRYPTION);
+                }
+                else {
+                    ret = wc_AesSetKey(&aes, key, derivedLen, cbcIv,
+                                                                AES_DECRYPTION);
+                }
+            }
+            if (ret == 0) {
+                if (enc)
+                    ret = wc_AesCbcEncrypt(&aes, input, input, length);
+                else
+                    ret = wc_AesCbcDecrypt(&aes, input, input, length);
+            }
+            if (ret != 0) {
+#ifdef WOLFSSL_SMALL_STACK
+                XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+                return ret;
+            }
+            ForceZero(&aes, sizeof(Aes));
+            break;
+        }
+    #endif /* WOLFSSL_AES_256 */
+#endif /* !NO_AES && HAVE_AES_CBC */
+
+        default:
+#ifdef WOLFSSL_SMALL_STACK
+            XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+            WOLFSSL_MSG("Unknown/Unsupported encrypt/decryption algorithm");
+            return ALGO_ID_E;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return ret;
+}
+
+#endif /* HAVE_PKCS8 || HAVE_PKCS12 */
+#endif /* !NO_PWDBASED */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/wc_port.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/wc_port.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/wc_port.c	(revision 453)
@@ -0,0 +1,2276 @@
+/* port.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+#include <wolfssl/wolfcrypt/types.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#include <wolfssl/wolfcrypt/logging.h>
+#include <wolfssl/wolfcrypt/wc_port.h>
+#ifdef HAVE_ECC
+    #include <wolfssl/wolfcrypt/ecc.h>
+#endif
+#ifdef WOLFSSL_ASYNC_CRYPT
+    #include <wolfssl/wolfcrypt/async.h>
+#endif
+
+/* IPP header files for library initialization */
+#ifdef HAVE_FAST_RSA
+    #include <ipp.h>
+    #include <ippcp.h>
+#endif
+
+#ifdef FREESCALE_LTC_TFM
+    #include <wolfssl/wolfcrypt/port/nxp/ksdk_port.h>
+#endif
+
+#if defined(WOLFSSL_ATMEL) || defined(WOLFSSL_ATECC508A)
+    #include <wolfssl/wolfcrypt/port/atmel/atmel.h>
+#endif
+#if defined(WOLFSSL_RENESAS_TSIP)
+    #include <wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h>
+#endif
+#if defined(WOLFSSL_STSAFEA100)
+    #include <wolfssl/wolfcrypt/port/st/stsafe.h>
+#endif
+
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+    #include <wolfssl/openssl/evp.h>
+#endif
+
+#if defined(USE_WOLFSSL_MEMORY) && defined(WOLFSSL_TRACK_MEMORY)
+    #include <wolfssl/wolfcrypt/memory.h>
+    #include <wolfssl/wolfcrypt/mem_track.h>
+#endif
+
+#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \
+    defined(WOLFSSL_IMX6_CAAM_BLOB)
+    #include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
+#endif
+
+#ifdef WOLF_CRYPTO_CB
+    #include <wolfssl/wolfcrypt/cryptocb.h>
+#endif
+
+#ifdef HAVE_INTEL_QA_SYNC
+    #include <wolfssl/wolfcrypt/port/intel/quickassist_sync.h>
+#endif
+
+#ifdef HAVE_CAVIUM_OCTEON_SYNC
+    #include <wolfssl/wolfcrypt/port/cavium/cavium_octeon_sync.h>
+#endif
+
+#ifdef WOLFSSL_SCE
+    #include "hal_data.h"
+#endif
+
+#if defined(WOLFSSL_DSP) && !defined(WOLFSSL_DSP_BUILD)
+    #include "rpcmem.h"
+#endif
+
+#ifdef _MSC_VER
+    /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */
+    #pragma warning(disable: 4996)
+#endif
+
+/* prevent multiple mutex initializations */
+static volatile int initRefCount = 0;
+
+/* Used to initialize state for wolfcrypt
+   return 0 on success
+ */
+int wolfCrypt_Init(void)
+{
+    int ret = 0;
+
+    if (initRefCount == 0) {
+        WOLFSSL_ENTER("wolfCrypt_Init");
+
+    #ifdef WOLFSSL_FORCE_MALLOC_FAIL_TEST
+        {
+            word32 rngMallocFail;
+            time_t seed = time(NULL);
+            srand((word32)seed);
+            rngMallocFail = rand() % 2000; /* max 2000 */
+            printf("\n--- RNG MALLOC FAIL AT %d---\n", rngMallocFail);
+            wolfSSL_SetMemFailCount(rngMallocFail);
+        }
+    #endif
+
+    #ifdef WOLF_CRYPTO_CB
+        wc_CryptoCb_Init();
+    #endif
+
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        ret = wolfAsync_HardwareStart();
+        if (ret != 0) {
+            WOLFSSL_MSG("Async hardware start failed");
+            /* don't return failure, allow operation to continue */
+        }
+    #endif
+
+    #if defined(WOLFSSL_RENESAS_TSIP_CRYPT)
+        ret = tsip_Open( );
+        if( ret != TSIP_SUCCESS ) {
+            WOLFSSL_MSG("RENESAS TSIP Open failed");
+            /* not return 1 since WOLFSSL_SUCCESS=1*/
+            ret = -1;/* FATAL ERROR */
+            return ret;
+        }
+    #endif
+
+    #if defined(WOLFSSL_TRACK_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY)
+        ret = InitMemoryTracker();
+        if (ret != 0) {
+            WOLFSSL_MSG("InitMemoryTracker failed");
+            return ret;
+        }
+    #endif
+
+    #if WOLFSSL_CRYPT_HW_MUTEX
+        /* If crypto hardware mutex protection is enabled, then initialize it */
+        ret = wolfSSL_CryptHwMutexInit();
+        if (ret != 0) {
+            WOLFSSL_MSG("Hw crypt mutex init failed");
+            return ret;
+        }
+    #endif
+
+    /* if defined have fast RSA then initialize Intel IPP */
+    #ifdef HAVE_FAST_RSA
+        WOLFSSL_MSG("Attempting to use optimized IPP Library");
+        if ((ret = ippInit()) != ippStsNoErr) {
+            /* possible to get a CPU feature support status on optimized IPP
+              library but still use default library and see competitive speeds */
+            WOLFSSL_MSG("Warning when trying to set up optimization");
+            WOLFSSL_MSG(ippGetStatusString(ret));
+            WOLFSSL_MSG("Using default fast IPP library");
+            ret = 0;
+            (void)ret; /* suppress not read warning */
+        }
+    #endif
+
+    #if defined(FREESCALE_LTC_TFM) || defined(FREESCALE_LTC_ECC)
+        ret = ksdk_port_init();
+        if (ret != 0) {
+            WOLFSSL_MSG("KSDK port init failed");
+            return ret;
+        }
+    #endif
+
+    #if defined(WOLFSSL_ATMEL) || defined(WOLFSSL_ATECC508A)
+        ret = atmel_init();
+        if (ret != 0) {
+            WOLFSSL_MSG("CryptoAuthLib init failed");
+            return ret;
+        }
+    #endif
+    #if defined(WOLFSSL_CRYPTOCELL)
+        /* enable and initialize the ARM CryptoCell 3xx runtime library */
+        ret = cc310_Init();
+        if (ret != 0) {
+            WOLFSSL_MSG("CRYPTOCELL init failed");
+            return ret;
+        }
+    #endif
+    #if defined(WOLFSSL_STSAFEA100)
+        stsafe_interface_init();
+    #endif
+
+    #ifdef WOLFSSL_ARMASM
+        WOLFSSL_MSG("Using ARM hardware acceleration");
+    #endif
+
+    #ifdef WOLFSSL_AFALG
+	WOLFSSL_MSG("Using AF_ALG for crypto acceleration");
+    #endif
+
+    #if !defined(WOLFCRYPT_ONLY) && defined(OPENSSL_EXTRA)
+        wolfSSL_EVP_init();
+    #endif
+
+    #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
+        if ((ret = wc_LoggingInit()) != 0) {
+            WOLFSSL_MSG("Error creating logging mutex");
+            return ret;
+        }
+    #endif
+
+#ifdef HAVE_ECC
+    #ifdef ECC_CACHE_CURVE
+        if ((ret = wc_ecc_curve_cache_init()) != 0) {
+            WOLFSSL_MSG("Error creating curve cache");
+            return ret;
+        }
+    #endif
+#endif
+
+#ifdef WOLFSSL_SCE
+        ret = (int)WOLFSSL_SCE_GSCE_HANDLE.p_api->open(
+                WOLFSSL_SCE_GSCE_HANDLE.p_ctrl, WOLFSSL_SCE_GSCE_HANDLE.p_cfg);
+        if (ret == SSP_ERR_CRYPTO_SCE_ALREADY_OPEN) {
+            WOLFSSL_MSG("SCE already open");
+            ret = 0;
+        }
+        if (ret != SSP_SUCCESS) {
+            WOLFSSL_MSG("Error opening SCE");
+            return -1; /* FATAL_ERROR */
+        }
+#endif
+
+#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \
+    defined(WOLFSSL_IMX6_CAAM_BLOB)
+        if ((ret = wc_caamInit()) != 0) {
+            return ret;
+        }
+#endif
+
+#if defined(WOLFSSL_DSP) && !defined(WOLFSSL_DSP_BUILD)
+	if ((ret = wolfSSL_InitHandle()) != 0) {
+            return ret;
+        }
+        rpcmem_init();
+#endif
+    }
+    initRefCount++;
+
+    return ret;
+}
+
+
+/* return success value is the same as wolfCrypt_Init */
+int wolfCrypt_Cleanup(void)
+{
+    int ret = 0;
+
+    initRefCount--;
+    if (initRefCount < 0)
+        initRefCount = 0;
+
+    if (initRefCount == 0) {
+        WOLFSSL_ENTER("wolfCrypt_Cleanup");
+
+#ifdef HAVE_ECC
+    #ifdef FP_ECC
+        wc_ecc_fp_free();
+    #endif
+    #ifdef ECC_CACHE_CURVE
+        wc_ecc_curve_cache_free();
+    #endif
+#endif /* HAVE_ECC */
+
+    #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
+        ret = wc_LoggingCleanup();
+    #endif
+
+    #if defined(WOLFSSL_TRACK_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY)
+        ShowMemoryTracker();
+    #endif
+
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        wolfAsync_HardwareStop();
+    #endif
+    #ifdef WOLFSSL_SCE
+        WOLFSSL_SCE_GSCE_HANDLE.p_api->close(WOLFSSL_SCE_GSCE_HANDLE.p_ctrl);
+    #endif
+    #if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \
+        defined(WOLFSSL_IMX6_CAAM_BLOB)
+        wc_caamFree();
+    #endif
+    #if defined(WOLFSSL_CRYPTOCELL)
+        cc310_Free();
+    #endif
+    #if defined(WOLFSSL_RENESAS_TSIP_CRYPT)
+        tsip_Close();
+    #endif
+    #if defined(WOLFSSL_DSP) && !defined(WOLFSSL_DSP_BUILD)
+        rpcmem_deinit();
+        wolfSSL_CleanupHandle();
+    #endif
+    }
+
+    return ret;
+}
+
+#if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) && \
+	!defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2)
+
+/* File Handling Helpers */
+/* returns 0 if file found, WC_READDIR_NOFILE if no files or negative error */
+int wc_ReadDirFirst(ReadDirCtx* ctx, const char* path, char** name)
+{
+    int ret = WC_READDIR_NOFILE; /* default to no files found */
+    int pathLen = 0;
+    int dnameLen = 0;
+
+    if (name)
+        *name = NULL;
+
+    if (ctx == NULL || path == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    XMEMSET(ctx->name, 0, MAX_FILENAME_SZ);
+    pathLen = (int)XSTRLEN(path);
+
+#ifdef USE_WINDOWS_API
+    if (pathLen > MAX_FILENAME_SZ - 3)
+        return BAD_PATH_ERROR;
+
+    XSTRNCPY(ctx->name, path, MAX_FILENAME_SZ - 3);
+    XSTRNCPY(ctx->name + pathLen, "\\*", MAX_FILENAME_SZ - pathLen);
+
+    ctx->hFind = FindFirstFileA(ctx->name, &ctx->FindFileData);
+    if (ctx->hFind == INVALID_HANDLE_VALUE) {
+        WOLFSSL_MSG("FindFirstFile for path verify locations failed");
+        return BAD_PATH_ERROR;
+    }
+
+    do {
+        if (!(ctx->FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+            dnameLen = (int)XSTRLEN(ctx->FindFileData.cFileName);
+
+            if (pathLen + dnameLen + 2 > MAX_FILENAME_SZ) {
+                return BAD_PATH_ERROR;
+            }
+            XSTRNCPY(ctx->name, path, pathLen + 1);
+            ctx->name[pathLen] = '\\';
+            XSTRNCPY(ctx->name + pathLen + 1,
+                     ctx->FindFileData.cFileName,
+                     MAX_FILENAME_SZ - pathLen - 1);
+            if (name)
+                *name = ctx->name;
+            return 0;
+        }
+    } while (FindNextFileA(ctx->hFind, &ctx->FindFileData));
+#elif defined(WOLFSSL_ZEPHYR)
+    if (fs_opendir(&ctx->dir, path) != 0) {
+        WOLFSSL_MSG("opendir path verify locations failed");
+        return BAD_PATH_ERROR;
+    }
+    ctx->dirp = &ctx->dir;
+
+    while ((fs_readdir(&ctx->dir, &ctx->entry)) != 0) {
+        dnameLen = (int)XSTRLEN(ctx->entry.name);
+
+        if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) {
+            ret = BAD_PATH_ERROR;
+            break;
+        }
+        XSTRNCPY(ctx->name, path, pathLen + 1);
+        ctx->name[pathLen] = '/';
+
+        /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because
+         * of earlier check it is known that dnameLen is less than
+         * MAX_FILENAME_SZ - (pathLen + 2)  so dnameLen +1 will fit */
+        XSTRNCPY(ctx->name + pathLen + 1, ctx->entry.name, dnameLen + 1);
+        if (fs_stat(ctx->name, &ctx->s) != 0) {
+            WOLFSSL_MSG("stat on name failed");
+            ret = BAD_PATH_ERROR;
+            break;
+        } else if (ctx->s.type == FS_DIR_ENTRY_FILE) {
+            if (name)
+                *name = ctx->name;
+            return 0;
+        }
+    }
+#elif defined(WOLFSSL_TELIT_M2MB)
+    ctx->dir = m2mb_fs_opendir((const CHAR*)path);
+    if (ctx->dir == NULL) {
+        WOLFSSL_MSG("opendir path verify locations failed");
+        return BAD_PATH_ERROR;
+    }
+
+    while ((ctx->entry = m2mb_fs_readdir(ctx->dir)) != NULL) {
+        dnameLen = (int)XSTRLEN(ctx->entry->d_name);
+
+        if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) {
+            ret = BAD_PATH_ERROR;
+            break;
+        }
+        XSTRNCPY(ctx->name, path, pathLen + 1);
+        ctx->name[pathLen] = '/';
+
+        /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because
+         * of earlier check it is known that dnameLen is less than
+         * MAX_FILENAME_SZ - (pathLen + 2)  so dnameLen +1 will fit */
+        XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, dnameLen + 1);
+
+        if (m2mb_fs_stat(ctx->name, &ctx->s) != 0) {
+            WOLFSSL_MSG("stat on name failed");
+            ret = BAD_PATH_ERROR;
+            break;
+        }
+        else if (ctx->s.st_mode & M2MB_S_IFREG) {
+            if (name)
+                *name = ctx->name;
+            return 0;
+        }
+    }
+#else
+    ctx->dir = opendir(path);
+    if (ctx->dir == NULL) {
+        WOLFSSL_MSG("opendir path verify locations failed");
+        return BAD_PATH_ERROR;
+    }
+
+    while ((ctx->entry = readdir(ctx->dir)) != NULL) {
+        dnameLen = (int)XSTRLEN(ctx->entry->d_name);
+
+        if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) {
+            ret = BAD_PATH_ERROR;
+            break;
+        }
+        XSTRNCPY(ctx->name, path, pathLen + 1);
+        ctx->name[pathLen] = '/';
+
+        /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because
+         * of earlier check it is known that dnameLen is less than
+         * MAX_FILENAME_SZ - (pathLen + 2)  so dnameLen +1 will fit */
+        XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, dnameLen + 1);
+        if (stat(ctx->name, &ctx->s) != 0) {
+            WOLFSSL_MSG("stat on name failed");
+            ret = BAD_PATH_ERROR;
+            break;
+        } else if (S_ISREG(ctx->s.st_mode)) {
+            if (name)
+                *name = ctx->name;
+            return 0;
+        }
+    }
+#endif
+    wc_ReadDirClose(ctx);
+
+    return ret;
+}
+
+/* returns 0 if file found, WC_READDIR_NOFILE if no more files */
+int wc_ReadDirNext(ReadDirCtx* ctx, const char* path, char** name)
+{
+    int ret = WC_READDIR_NOFILE; /* default to no file found */
+    int pathLen = 0;
+    int dnameLen = 0;
+
+    if (name)
+        *name = NULL;
+
+    if (ctx == NULL || path == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    XMEMSET(ctx->name, 0, MAX_FILENAME_SZ);
+    pathLen = (int)XSTRLEN(path);
+
+#ifdef USE_WINDOWS_API
+    while (FindNextFileA(ctx->hFind, &ctx->FindFileData)) {
+        if (!(ctx->FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+            dnameLen = (int)XSTRLEN(ctx->FindFileData.cFileName);
+
+            if (pathLen + dnameLen + 2 > MAX_FILENAME_SZ) {
+                return BAD_PATH_ERROR;
+            }
+            XSTRNCPY(ctx->name, path, pathLen + 1);
+            ctx->name[pathLen] = '\\';
+            XSTRNCPY(ctx->name + pathLen + 1,
+                     ctx->FindFileData.cFileName,
+                     MAX_FILENAME_SZ - pathLen - 1);
+            if (name)
+                *name = ctx->name;
+            return 0;
+        }
+    }
+#elif defined(WOLFSSL_ZEPHYR)
+    while ((fs_readdir(&ctx->dir, &ctx->entry)) != 0) {
+        dnameLen = (int)XSTRLEN(ctx->entry.name);
+
+        if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) {
+            ret = BAD_PATH_ERROR;
+            break;
+        }
+        XSTRNCPY(ctx->name, path, pathLen + 1);
+        ctx->name[pathLen] = '/';
+        /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because
+         * of earlier check it is known that dnameLen is less than
+         * MAX_FILENAME_SZ - (pathLen + 2) so that dnameLen +1 will fit */
+        XSTRNCPY(ctx->name + pathLen + 1, ctx->entry.name, dnameLen + 1);
+
+        if (fs_stat(ctx->name, &ctx->s) != 0) {
+            WOLFSSL_MSG("stat on name failed");
+            ret = BAD_PATH_ERROR;
+            break;
+        } else if (ctx->s.type == FS_DIR_ENTRY_FILE) {
+            if (name)
+                *name = ctx->name;
+            return 0;
+        }
+    }
+#elif defined(WOLFSSL_TELIT_M2MB)
+    while ((ctx->entry = m2mb_fs_readdir(ctx->dir)) != NULL) {
+        dnameLen = (int)XSTRLEN(ctx->entry->d_name);
+
+        if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) {
+            ret = BAD_PATH_ERROR;
+            break;
+        }
+        XSTRNCPY(ctx->name, path, pathLen + 1);
+        ctx->name[pathLen] = '/';
+
+        /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because
+         * of earlier check it is known that dnameLen is less than
+         * MAX_FILENAME_SZ - (pathLen + 2)  so dnameLen +1 will fit */
+        XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, dnameLen + 1);
+
+        if (m2mb_fs_stat(ctx->name, &ctx->s) != 0) {
+            WOLFSSL_MSG("stat on name failed");
+            ret = BAD_PATH_ERROR;
+            break;
+        }
+        else if (ctx->s.st_mode & M2MB_S_IFREG) {
+            if (name)
+                *name = ctx->name;
+            return 0;
+        }
+    }
+#else
+    while ((ctx->entry = readdir(ctx->dir)) != NULL) {
+        dnameLen = (int)XSTRLEN(ctx->entry->d_name);
+
+        if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) {
+            ret = BAD_PATH_ERROR;
+            break;
+        }
+        XSTRNCPY(ctx->name, path, pathLen + 1);
+        ctx->name[pathLen] = '/';
+        /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because
+         * of earlier check it is known that dnameLen is less than
+         * MAX_FILENAME_SZ - (pathLen + 2) so that dnameLen +1 will fit */
+        XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, dnameLen + 1);
+
+        if (stat(ctx->name, &ctx->s) != 0) {
+            WOLFSSL_MSG("stat on name failed");
+            ret = BAD_PATH_ERROR;
+            break;
+        } else if (S_ISREG(ctx->s.st_mode)) {
+            if (name)
+                *name = ctx->name;
+            return 0;
+        }
+    }
+#endif
+
+    wc_ReadDirClose(ctx);
+
+    return ret;
+}
+
+void wc_ReadDirClose(ReadDirCtx* ctx)
+{
+    if (ctx == NULL) {
+        return;
+    }
+
+#ifdef USE_WINDOWS_API
+    if (ctx->hFind != INVALID_HANDLE_VALUE) {
+        FindClose(ctx->hFind);
+        ctx->hFind = INVALID_HANDLE_VALUE;
+    }
+#elif defined(WOLFSSL_ZEPHYR)
+    if (ctx->dirp) {
+        fs_closedir(ctx->dirp);
+        ctx->dirp = NULL;
+    }
+#elif defined(WOLFSSL_TELIT_M2MB)
+    if (ctx->dir) {
+        m2mb_fs_closedir(ctx->dir);
+        ctx->dir = NULL;
+    }
+#else
+    if (ctx->dir) {
+        closedir(ctx->dir);
+        ctx->dir = NULL;
+    }
+#endif
+}
+
+#endif /* !NO_FILESYSTEM && !NO_WOLFSSL_DIR */
+
+#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_ZEPHYR)
+XFILE z_fs_open(const char* filename, const char* perm)
+{
+    XFILE file;
+
+    file = XMALLOC(sizeof(*file), NULL, DYNAMIC_TYPE_FILE);
+    if (file != NULL) {
+        if (fs_open(file, filename) != 0) {
+            XFREE(file, NULL, DYNAMIC_TYPE_FILE);
+            file = NULL;
+        }
+    }
+
+    return file;
+}
+
+int z_fs_close(XFILE file)
+{
+    int ret;
+
+    if (file == NULL)
+        return -1;
+    ret = (fs_close(file) == 0) ? 0 : -1;
+
+    XFREE(file, NULL, DYNAMIC_TYPE_FILE);
+
+    return ret;
+}
+
+#endif /* !NO_FILESYSTEM && !WOLFSSL_ZEPHYR */
+
+
+wolfSSL_Mutex* wc_InitAndAllocMutex(void)
+{
+    wolfSSL_Mutex* m = (wolfSSL_Mutex*) XMALLOC(sizeof(wolfSSL_Mutex), NULL,
+            DYNAMIC_TYPE_MUTEX);
+    if (m != NULL) {
+        if (wc_InitMutex(m) != 0) {
+            WOLFSSL_MSG("Init Mutex failed");
+            XFREE(m, NULL, DYNAMIC_TYPE_MUTEX);
+            m = NULL;
+        }
+    }
+    else {
+        WOLFSSL_MSG("Memory error with Mutex allocation");
+    }
+
+    return m;
+}
+
+#ifdef USE_WOLF_STRTOK
+/* String token (delim) search. If str is null use nextp. */
+char* wc_strtok(char *str, const char *delim, char **nextp)
+{
+    char* ret;
+    int i, j;
+
+    /* Use next if str is NULL */
+    if (str == NULL && nextp)
+        str = *nextp;
+
+    /* verify str input */
+    if (str == NULL || *str == '\0')
+        return NULL;
+
+    /* match on entire delim */
+    for (i = 0; str[i]; i++) {
+        for (j = 0; delim[j]; j++) {
+            if (delim[j] == str[i])
+                break;
+        }
+        if (!delim[j])
+            break;
+    }
+    str += i;
+    /* if end of string, not found so return NULL */
+    if (*str == '\0')
+        return NULL;
+
+    ret = str;
+
+    /* match on first delim */
+    for (i = 0; str[i]; i++) {
+        for (j = 0; delim[j]; j++) {
+            if (delim[j] == str[i])
+                break;
+        }
+        if (delim[j] == str[i])
+            break;
+    }
+    str += i;
+
+    /* null terminate found string */
+    if (*str)
+        *str++ = '\0';
+
+    /* return pointer to next */
+    if (nextp)
+        *nextp = str;
+
+    return ret;
+}
+#endif /* USE_WOLF_STRTOK */
+
+#ifdef USE_WOLF_STRSEP
+char* wc_strsep(char **stringp, const char *delim)
+{
+    char *s, *tok;
+    const char *spanp;
+
+    /* null check */
+    if (stringp == NULL || *stringp == NULL)
+        return NULL;
+
+    s = *stringp;
+    for (tok = s; *tok; ++tok) {
+        for (spanp = delim; *spanp; ++spanp) {
+            /* found delimiter */
+            if (*tok == *spanp) {
+                *tok = '\0'; /* replace delim with null term */
+                *stringp = tok + 1; /* return past delim */
+                return s;
+            }
+        }
+    }
+
+    *stringp = NULL;
+    return s;
+}
+#endif /* USE_WOLF_STRSEP */
+
+#if WOLFSSL_CRYPT_HW_MUTEX
+/* Mutex for protection of cryptography hardware */
+static wolfSSL_Mutex wcCryptHwMutex;
+static int wcCryptHwMutexInit = 0;
+
+int wolfSSL_CryptHwMutexInit(void) {
+    int ret = 0;
+    if(wcCryptHwMutexInit == 0) {
+        ret = wc_InitMutex(&wcCryptHwMutex);
+        if(ret == 0) {
+            wcCryptHwMutexInit = 1;
+        }
+    }
+    return ret;
+}
+
+int wolfSSL_CryptHwMutexLock(void) {
+    int ret = BAD_MUTEX_E;
+
+    /* Make sure HW Mutex has been initialized */
+    wolfSSL_CryptHwMutexInit();
+
+    if(wcCryptHwMutexInit) {
+        ret = wc_LockMutex(&wcCryptHwMutex);
+    }
+    return ret;
+}
+
+int wolfSSL_CryptHwMutexUnLock(void) {
+    int ret = BAD_MUTEX_E;
+
+    if(wcCryptHwMutexInit) {
+        ret = wc_UnLockMutex(&wcCryptHwMutex);
+    }
+    return ret;
+}
+#endif /* WOLFSSL_CRYPT_HW_MUTEX */
+
+
+/* ---------------------------------------------------------------------------*/
+/* Mutex Ports */
+/* ---------------------------------------------------------------------------*/
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+    static mutex_cb*     compat_mutex_cb = NULL;
+
+    /* Function that locks or unlocks a mutex based on the flag passed in.
+     *
+     * flag lock or unlock i.e. CRYPTO_LOCK
+     * type the type of lock to unlock or lock
+     * file name of the file calling
+     * line the line number from file calling
+     */
+    int wc_LockMutex_ex(int flag, int type, const char* file, int line)
+    {
+        if (compat_mutex_cb != NULL) {
+            compat_mutex_cb(flag, type, file, line);
+            return 0;
+        }
+        else {
+            WOLFSSL_MSG("Mutex call back function not set. Call wc_SetMutexCb");
+            return BAD_STATE_E;
+        }
+    }
+
+
+    /* Set the callback function to use for locking/unlocking mutex
+     *
+     * cb callback function to use
+     */
+    int wc_SetMutexCb(mutex_cb* cb)
+    {
+        compat_mutex_cb = cb;
+        return 0;
+    }
+#endif /* defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) */
+#ifdef SINGLE_THREADED
+
+    int wc_InitMutex(wolfSSL_Mutex* m)
+    {
+        (void)m;
+        return 0;
+    }
+
+    int wc_FreeMutex(wolfSSL_Mutex *m)
+    {
+        (void)m;
+        return 0;
+    }
+
+
+    int wc_LockMutex(wolfSSL_Mutex *m)
+    {
+        (void)m;
+        return 0;
+    }
+
+
+    int wc_UnLockMutex(wolfSSL_Mutex *m)
+    {
+        (void)m;
+        return 0;
+    }
+
+#elif defined(FREERTOS) || defined(FREERTOS_TCP) || \
+  defined(FREESCALE_FREE_RTOS)
+
+    int wc_InitMutex(wolfSSL_Mutex* m)
+    {
+        int iReturn;
+
+        *m = ( wolfSSL_Mutex ) xSemaphoreCreateMutex();
+        if( *m != NULL )
+            iReturn = 0;
+        else
+            iReturn = BAD_MUTEX_E;
+
+        return iReturn;
+    }
+
+    int wc_FreeMutex(wolfSSL_Mutex* m)
+    {
+        vSemaphoreDelete( *m );
+        return 0;
+    }
+
+    int wc_LockMutex(wolfSSL_Mutex* m)
+    {
+        /* Assume an infinite block, or should there be zero block? */
+        xSemaphoreTake( *m, portMAX_DELAY );
+        return 0;
+    }
+
+    int wc_UnLockMutex(wolfSSL_Mutex* m)
+    {
+        xSemaphoreGive( *m );
+        return 0;
+    }
+
+#elif defined(WOLFSSL_SAFERTOS)
+
+    int wc_InitMutex(wolfSSL_Mutex* m)
+    {
+        vSemaphoreCreateBinary(m->mutexBuffer, m->mutex);
+        if (m->mutex == NULL)
+            return BAD_MUTEX_E;
+
+        return 0;
+    }
+
+    int wc_FreeMutex(wolfSSL_Mutex* m)
+    {
+        (void)m;
+        return 0;
+    }
+
+    int wc_LockMutex(wolfSSL_Mutex* m)
+    {
+        /* Assume an infinite block */
+        xSemaphoreTake(m->mutex, portMAX_DELAY);
+        return 0;
+    }
+
+    int wc_UnLockMutex(wolfSSL_Mutex* m)
+    {
+        xSemaphoreGive(m->mutex);
+        return 0;
+    }
+
+#elif defined(USE_WINDOWS_API)
+
+    int wc_InitMutex(wolfSSL_Mutex* m)
+    {
+        InitializeCriticalSection(m);
+        return 0;
+    }
+
+
+    int wc_FreeMutex(wolfSSL_Mutex* m)
+    {
+        DeleteCriticalSection(m);
+        return 0;
+    }
+
+
+    int wc_LockMutex(wolfSSL_Mutex* m)
+    {
+        EnterCriticalSection(m);
+        return 0;
+    }
+
+
+    int wc_UnLockMutex(wolfSSL_Mutex* m)
+    {
+        LeaveCriticalSection(m);
+        return 0;
+    }
+
+#elif defined(WOLFSSL_PTHREADS)
+
+    int wc_InitMutex(wolfSSL_Mutex* m)
+    {
+        if (pthread_mutex_init(m, 0) == 0)
+            return 0;
+        else
+            return BAD_MUTEX_E;
+    }
+
+
+    int wc_FreeMutex(wolfSSL_Mutex* m)
+    {
+        if (pthread_mutex_destroy(m) == 0)
+            return 0;
+        else
+            return BAD_MUTEX_E;
+    }
+
+
+    int wc_LockMutex(wolfSSL_Mutex* m)
+    {
+        if (pthread_mutex_lock(m) == 0)
+            return 0;
+        else
+            return BAD_MUTEX_E;
+    }
+
+
+    int wc_UnLockMutex(wolfSSL_Mutex* m)
+    {
+        if (pthread_mutex_unlock(m) == 0)
+            return 0;
+        else
+            return BAD_MUTEX_E;
+    }
+
+#elif defined(WOLFSSL_VXWORKS)
+
+    int wc_InitMutex(wolfSSL_Mutex* m)
+    {
+        if (m) {
+            if ((*m = semMCreate(0)) != SEM_ID_NULL)
+                return 0;
+        }
+        return BAD_MUTEX_E;
+    }
+
+
+    int wc_FreeMutex(wolfSSL_Mutex* m)
+    {
+        if (m) {
+            if (semDelete(*m) == OK)
+                return 0;
+        }
+        return BAD_MUTEX_E;
+    }
+
+
+    int wc_LockMutex(wolfSSL_Mutex* m)
+    {
+        if (m) {
+            if (semTake(*m, WAIT_FOREVER) == OK)
+                return 0;
+        }
+        return BAD_MUTEX_E;
+    }
+
+
+    int wc_UnLockMutex(wolfSSL_Mutex* m)
+    {
+        if (m) {
+            if (semGive(*m) == OK)
+                return 0;
+        }
+        return BAD_MUTEX_E;
+    }
+
+#elif defined(THREADX)
+
+    int wc_InitMutex(wolfSSL_Mutex* m)
+    {
+        if (tx_mutex_create(m, "wolfSSL Mutex", TX_NO_INHERIT) == 0)
+            return 0;
+        else
+            return BAD_MUTEX_E;
+    }
+
+
+    int wc_FreeMutex(wolfSSL_Mutex* m)
+    {
+        if (tx_mutex_delete(m) == 0)
+            return 0;
+        else
+            return BAD_MUTEX_E;
+    }
+
+
+    int wc_LockMutex(wolfSSL_Mutex* m)
+    {
+        if (tx_mutex_get(m, TX_WAIT_FOREVER) == 0)
+            return 0;
+        else
+            return BAD_MUTEX_E;
+    }
+
+    int wc_UnLockMutex(wolfSSL_Mutex* m)
+    {
+        if (tx_mutex_put(m) == 0)
+            return 0;
+        else
+            return BAD_MUTEX_E;
+    }
+
+#elif defined(WOLFSSL_DEOS)
+
+    int wc_InitMutex(wolfSSL_Mutex* m)
+    {
+        mutexStatus mutStat;
+        /*
+        The empty string "" denotes an anonymous mutex, so objects do not cause name collisions.
+        `protectWolfSSLTemp` in an XML configuration element template describing a mutex.
+        */
+        if (m) {
+            mutStat = createMutex("", "protectWolfSSLTemp", m);
+            if (mutStat == mutexSuccess)
+                return 0;
+            else{
+                WOLFSSL_MSG("wc_InitMutex failed");
+                return mutStat;
+            }
+        }
+        return BAD_MUTEX_E;
+    }
+
+    int wc_FreeMutex(wolfSSL_Mutex* m)
+    {
+        mutexStatus mutStat;
+        if (m) {
+            mutStat = deleteMutex(*m);
+            if (mutStat == mutexSuccess)
+                return 0;
+            else{
+                WOLFSSL_MSG("wc_FreeMutex failed");
+                return mutStat;
+            }
+        }
+        return BAD_MUTEX_E;
+    }
+
+    int wc_LockMutex(wolfSSL_Mutex* m)
+    {
+        mutexStatus mutStat;
+        if (m) {
+            mutStat = lockMutex(*m);
+            if (mutStat == mutexSuccess)
+                return 0;
+            else{
+                WOLFSSL_MSG("wc_LockMutex failed");
+                return mutStat;
+            }
+        }
+        return BAD_MUTEX_E;
+    }
+
+    int wc_UnLockMutex(wolfSSL_Mutex* m)
+    {
+        mutexStatus mutStat;
+        if (m) {
+            mutStat = unlockMutex(*m);
+            if (mutStat== mutexSuccess)
+                return 0;
+            else{
+                WOLFSSL_MSG("wc_UnLockMutex failed");
+                return mutStat;
+            }
+        }
+        return BAD_MUTEX_E;
+    }
+
+#elif defined(MICRIUM)
+
+    int wc_InitMutex(wolfSSL_Mutex* m)
+    {
+        OS_ERR err;
+
+        OSMutexCreate(m, "wolfSSL Mutex", &err);
+
+        if (err == OS_ERR_NONE)
+            return 0;
+        else
+            return BAD_MUTEX_E;
+    }
+
+    int wc_FreeMutex(wolfSSL_Mutex* m)
+    {
+        #if (OS_CFG_MUTEX_DEL_EN == DEF_ENABLED)
+            OS_ERR err;
+
+            OSMutexDel(m, OS_OPT_DEL_ALWAYS, &err);
+
+            if (err == OS_ERR_NONE)
+                return 0;
+            else
+                return BAD_MUTEX_E;
+        #else
+            return 0;
+        #endif
+    }
+
+    int wc_LockMutex(wolfSSL_Mutex* m)
+    {
+        OS_ERR err;
+
+        OSMutexPend(m, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
+
+        if (err == OS_ERR_NONE)
+            return 0;
+        else
+            return BAD_MUTEX_E;
+    }
+
+    int wc_UnLockMutex(wolfSSL_Mutex* m)
+    {
+        OS_ERR err;
+
+        OSMutexPost(m, OS_OPT_POST_NONE, &err);
+
+        if (err == OS_ERR_NONE)
+            return 0;
+        else
+            return BAD_MUTEX_E;
+    }
+
+#elif defined(EBSNET)
+
+    int wc_InitMutex(wolfSSL_Mutex* m)
+    {
+        if (rtp_sig_mutex_alloc(m, "wolfSSL Mutex") == -1)
+            return BAD_MUTEX_E;
+        else
+            return 0;
+    }
+
+    int wc_FreeMutex(wolfSSL_Mutex* m)
+    {
+        rtp_sig_mutex_free(*m);
+        return 0;
+    }
+
+    int wc_LockMutex(wolfSSL_Mutex* m)
+    {
+        if (rtp_sig_mutex_claim_timed(*m, RTIP_INF) == 0)
+            return 0;
+        else
+            return BAD_MUTEX_E;
+    }
+
+    int wc_UnLockMutex(wolfSSL_Mutex* m)
+    {
+        rtp_sig_mutex_release(*m);
+        return 0;
+    }
+
+    int ebsnet_fseek(int a, long b, int c)
+    {
+        int retval;
+
+        retval = vf_lseek(a, b, c);
+        if (retval > 0)
+            retval = 0;
+        else
+            retval =  -1;
+
+        return(retval);
+    }
+
+#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
+
+    int wc_InitMutex(wolfSSL_Mutex* m)
+    {
+        if (_mutex_init(m, NULL) == MQX_EOK)
+            return 0;
+        else
+            return BAD_MUTEX_E;
+    }
+
+    int wc_FreeMutex(wolfSSL_Mutex* m)
+    {
+        if (_mutex_destroy(m) == MQX_EOK)
+            return 0;
+        else
+            return BAD_MUTEX_E;
+    }
+
+    int wc_LockMutex(wolfSSL_Mutex* m)
+    {
+        if (_mutex_lock(m) == MQX_EOK)
+            return 0;
+        else
+            return BAD_MUTEX_E;
+    }
+
+    int wc_UnLockMutex(wolfSSL_Mutex* m)
+    {
+        if (_mutex_unlock(m) == MQX_EOK)
+            return 0;
+        else
+            return BAD_MUTEX_E;
+    }
+
+#elif defined(WOLFSSL_TIRTOS)
+    #include <xdc/runtime/Error.h>
+
+    int wc_InitMutex(wolfSSL_Mutex* m)
+    {
+        Semaphore_Params params;
+        Error_Block eb;
+
+        Error_init(&eb);
+        Semaphore_Params_init(&params);
+        params.mode = Semaphore_Mode_BINARY;
+
+        *m = Semaphore_create(1, &params, &eb);
+        if (Error_check(&eb)) {
+            Error_raise(&eb, Error_E_generic, "Failed to Create the semaphore.",
+                NULL);
+            return BAD_MUTEX_E;
+        }
+        else
+            return 0;
+    }
+
+    int wc_FreeMutex(wolfSSL_Mutex* m)
+    {
+        Semaphore_delete(m);
+
+        return 0;
+    }
+
+    int wc_LockMutex(wolfSSL_Mutex* m)
+    {
+        Semaphore_pend(*m, BIOS_WAIT_FOREVER);
+
+        return 0;
+    }
+
+    int wc_UnLockMutex(wolfSSL_Mutex* m)
+    {
+        Semaphore_post(*m);
+
+        return 0;
+    }
+
+#elif defined(WOLFSSL_uITRON4)
+
+    int wc_InitMutex(wolfSSL_Mutex* m)
+    {
+        int iReturn;
+        m->sem.sematr  = TA_TFIFO;
+        m->sem.isemcnt = 1;
+        m->sem.maxsem  = 1;
+        m->sem.name    = NULL;
+
+        m->id = acre_sem(&m->sem);
+        if( m->id != E_OK )
+            iReturn = 0;
+        else
+            iReturn = BAD_MUTEX_E;
+
+        return iReturn;
+    }
+
+    int wc_FreeMutex(wolfSSL_Mutex* m)
+    {
+        del_sem( m->id );
+        return 0;
+    }
+
+    int wc_LockMutex(wolfSSL_Mutex* m)
+    {
+        wai_sem(m->id);
+        return 0;
+    }
+
+    int wc_UnLockMutex(wolfSSL_Mutex* m)
+    {
+        sig_sem(m->id);
+        return 0;
+    }
+
+    /****  uITRON malloc/free ***/
+    static ID ID_wolfssl_MPOOL = 0;
+    static T_CMPL wolfssl_MPOOL = {TA_TFIFO, 0, NULL, "wolfSSL_MPOOL"};
+
+    int uITRON4_minit(size_t poolsz) {
+        ER ercd;
+        wolfssl_MPOOL.mplsz = poolsz;
+        ercd = acre_mpl(&wolfssl_MPOOL);
+        if (ercd > 0) {
+            ID_wolfssl_MPOOL = ercd;
+            return 0;
+        } else {
+            return -1;
+        }
+    }
+
+    void *uITRON4_malloc(size_t sz) {
+        ER ercd;
+        void *p = NULL;
+        ercd = get_mpl(ID_wolfssl_MPOOL, sz, (VP)&p);
+        if (ercd == E_OK) {
+            return p;
+        } else {
+            return 0;
+        }
+    }
+
+    void *uITRON4_realloc(void *p, size_t sz) {
+      ER ercd;
+      void *newp;
+      if(p) {
+          ercd = get_mpl(ID_wolfssl_MPOOL, sz, (VP)&newp);
+          if (ercd == E_OK) {
+              XMEMCPY(newp, p, sz);
+              ercd = rel_mpl(ID_wolfssl_MPOOL, (VP)p);
+              if (ercd == E_OK) {
+                  return newp;
+              }
+          }
+      }
+      return 0;
+    }
+
+    void uITRON4_free(void *p) {
+        ER ercd;
+        ercd = rel_mpl(ID_wolfssl_MPOOL, (VP)p);
+        if (ercd == E_OK) {
+            return;
+        } else {
+            return;
+        }
+    }
+
+#elif defined(WOLFSSL_uTKERNEL2)
+
+    int wc_InitMutex(wolfSSL_Mutex* m)
+    {
+        int iReturn;
+        m->sem.sematr  = TA_TFIFO;
+        m->sem.isemcnt = 1;
+        m->sem.maxsem  = 1;
+
+        m->id = tk_cre_sem(&m->sem);
+        if( m->id != NULL )
+            iReturn = 0;
+        else
+            iReturn = BAD_MUTEX_E;
+
+        return iReturn;
+    }
+
+    int wc_FreeMutex(wolfSSL_Mutex* m)
+    {
+        tk_del_sem(m->id);
+        return 0;
+    }
+
+    int wc_LockMutex(wolfSSL_Mutex* m)
+    {
+        tk_wai_sem(m->id, 1, TMO_FEVR);
+        return 0;
+    }
+
+    int wc_UnLockMutex(wolfSSL_Mutex* m)
+    {
+        tk_sig_sem(m->id, 1);
+        return 0;
+    }
+
+    /****  uT-Kernel malloc/free ***/
+    static ID ID_wolfssl_MPOOL = 0;
+    static T_CMPL wolfssl_MPOOL = {
+        NULL,       /* Extended information */
+        TA_TFIFO,   /* Memory pool attribute */
+        0,          /* Size of whole memory pool (byte) */
+        "wolfSSL"   /* Object name (max 8-char) */
+    };
+
+    int uTKernel_init_mpool(unsigned int sz) {
+        ER ercd;
+        wolfssl_MPOOL.mplsz = sz;
+        ercd = tk_cre_mpl(&wolfssl_MPOOL);
+        if (ercd > 0) {
+            ID_wolfssl_MPOOL = ercd;
+            return 0;
+        } else {
+            return (int)ercd;
+        }
+    }
+
+    void *uTKernel_malloc(unsigned int sz) {
+        ER ercd;
+        void *p = NULL;
+        ercd = tk_get_mpl(ID_wolfssl_MPOOL, sz, (VP)&p, TMO_FEVR);
+        if (ercd == E_OK) {
+            return p;
+        } else {
+            return 0;
+        }
+    }
+
+    void *uTKernel_realloc(void *p, unsigned int sz) {
+      ER ercd;
+      void *newp;
+      if (p) {
+          ercd = tk_get_mpl(ID_wolfssl_MPOOL, sz, (VP)&newp, TMO_FEVR);
+          if (ercd == E_OK) {
+              XMEMCPY(newp, p, sz);
+              ercd = tk_rel_mpl(ID_wolfssl_MPOOL, (VP)p);
+              if (ercd == E_OK) {
+                  return newp;
+              }
+          }
+      }
+      return 0;
+    }
+
+    void uTKernel_free(void *p) {
+        ER ercd;
+        ercd = tk_rel_mpl(ID_wolfssl_MPOOL, (VP)p);
+        if (ercd == E_OK) {
+            return;
+        } else {
+            return;
+        }
+    }
+
+#elif defined (WOLFSSL_FROSTED)
+
+    int wc_InitMutex(wolfSSL_Mutex* m)
+    {
+        *m = mutex_init();
+        if (*m)
+            return 0;
+        else
+            return -1;
+    }
+
+    int wc_FreeMutex(wolfSSL_Mutex* m)
+    {
+        mutex_destroy(*m);
+        return(0);
+    }
+
+    int wc_LockMutex(wolfSSL_Mutex* m)
+    {
+        mutex_lock(*m);
+        return 0;
+    }
+
+    int wc_UnLockMutex(wolfSSL_Mutex* m)
+    {
+        mutex_unlock(*m);
+        return 0;
+    }
+
+#elif defined(WOLFSSL_CMSIS_RTOS)
+
+    #define CMSIS_NMUTEX 10
+    osMutexDef(wolfSSL_mt0);  osMutexDef(wolfSSL_mt1);  osMutexDef(wolfSSL_mt2);
+    osMutexDef(wolfSSL_mt3);  osMutexDef(wolfSSL_mt4);  osMutexDef(wolfSSL_mt5);
+    osMutexDef(wolfSSL_mt6);  osMutexDef(wolfSSL_mt7);  osMutexDef(wolfSSL_mt8);
+    osMutexDef(wolfSSL_mt9);
+
+    static const osMutexDef_t *CMSIS_mutex[] = { osMutex(wolfSSL_mt0),
+        osMutex(wolfSSL_mt1),    osMutex(wolfSSL_mt2),   osMutex(wolfSSL_mt3),
+        osMutex(wolfSSL_mt4),    osMutex(wolfSSL_mt5),   osMutex(wolfSSL_mt6),
+        osMutex(wolfSSL_mt7),    osMutex(wolfSSL_mt8),   osMutex(wolfSSL_mt9) };
+
+    static osMutexId CMSIS_mutexID[CMSIS_NMUTEX] = {0};
+
+    int wc_InitMutex(wolfSSL_Mutex* m)
+    {
+        int i;
+        for (i=0; i<CMSIS_NMUTEX; i++) {
+            if(CMSIS_mutexID[i] == 0) {
+                CMSIS_mutexID[i] = osMutexCreate(CMSIS_mutex[i]);
+                (*m) = CMSIS_mutexID[i];
+            return 0;
+            }
+        }
+        return -1;
+    }
+
+    int wc_FreeMutex(wolfSSL_Mutex* m)
+    {
+        int i;
+        osMutexDelete   (*m);
+        for (i=0; i<CMSIS_NMUTEX; i++) {
+            if(CMSIS_mutexID[i] == (*m)) {
+                CMSIS_mutexID[i] = 0;
+                return(0);
+            }
+        }
+        return(-1);
+    }
+
+    int wc_LockMutex(wolfSSL_Mutex* m)
+    {
+        osMutexWait(*m, osWaitForever);
+        return(0);
+    }
+
+    int wc_UnLockMutex(wolfSSL_Mutex* m)
+    {
+        osMutexRelease (*m);
+        return 0;
+    }
+
+#elif defined(WOLFSSL_CMSIS_RTOSv2)
+    int wc_InitMutex(wolfSSL_Mutex *m)
+    {
+        static const osMutexAttr_t attr = {
+            "wolfSSL_mutex", osMutexRecursive, NULL, 0};
+
+        if ((*m = osMutexNew(&attr)) != NULL)
+            return 0;
+        else
+            return BAD_MUTEX_E;
+    }
+
+    int wc_FreeMutex(wolfSSL_Mutex *m)
+    {
+        if (osMutexDelete(*m) == osOK)
+            return 0;
+        else
+            return BAD_MUTEX_E;
+    }
+
+
+    int wc_LockMutex(wolfSSL_Mutex *m)
+    {
+        if (osMutexAcquire(*m, osWaitForever) == osOK)
+            return 0;
+        else
+            return BAD_MUTEX_E;
+    }
+
+    int wc_UnLockMutex(wolfSSL_Mutex *m)
+    {
+        if (osMutexRelease(*m) == osOK)
+            return 0;
+        else
+            return BAD_MUTEX_E;
+    }
+
+#elif defined(WOLFSSL_MDK_ARM)
+
+    int wc_InitMutex(wolfSSL_Mutex* m)
+    {
+        os_mut_init (m);
+        return 0;
+    }
+
+    int wc_FreeMutex(wolfSSL_Mutex* m)
+    {
+        return(0);
+    }
+
+    int wc_LockMutex(wolfSSL_Mutex* m)
+    {
+        os_mut_wait (m, 0xffff);
+        return(0);
+    }
+
+    int wc_UnLockMutex(wolfSSL_Mutex* m)
+    {
+        os_mut_release (m);
+        return 0;
+    }
+
+#elif defined(INTIME_RTOS)
+
+    int wc_InitMutex(wolfSSL_Mutex* m)
+    {
+        int ret = 0;
+
+        if (m == NULL)
+            return BAD_FUNC_ARG;
+
+        *m = CreateRtSemaphore(
+            1,                      /* initial unit count */
+            1,                      /* maximum unit count */
+            PRIORITY_QUEUING        /* creation flags: FIFO_QUEUING or PRIORITY_QUEUING */
+        );
+        if (*m == BAD_RTHANDLE) {
+            ret = GetLastRtError();
+            if (ret != E_OK)
+                ret = BAD_MUTEX_E;
+        }
+        return ret;
+    }
+
+    int wc_FreeMutex(wolfSSL_Mutex* m)
+    {
+        int ret = 0;
+        BOOLEAN del;
+
+        if (m == NULL)
+            return BAD_FUNC_ARG;
+
+        del = DeleteRtSemaphore(
+            *m                      /* handle for RT semaphore */
+        );
+    	if (del != TRUE)
+    		ret = BAD_MUTEX_E;
+
+        return ret;
+    }
+
+    int wc_LockMutex(wolfSSL_Mutex* m)
+    {
+        int ret = 0;
+        DWORD lck;
+
+        if (m == NULL)
+            return BAD_FUNC_ARG;
+
+        lck = WaitForRtSemaphore(
+            *m,                     /* handle for RT semaphore */
+            1,                      /* number of units to wait for */
+            WAIT_FOREVER            /* number of milliseconds to wait for units */
+        );
+        if (lck == WAIT_FAILED) {
+            ret = GetLastRtError();
+            if (ret != E_OK)
+                ret = BAD_MUTEX_E;
+        }
+        return ret;
+    }
+
+    int wc_UnLockMutex(wolfSSL_Mutex* m)
+    {
+        int ret = 0;
+        BOOLEAN rel;
+
+        if (m == NULL)
+            return BAD_FUNC_ARG;
+
+        rel = ReleaseRtSemaphore(
+            *m,                     /* handle for RT semaphore */
+            1                       /* number of units to release to semaphore */
+        );
+    	if (rel != TRUE)
+    		ret = BAD_MUTEX_E;
+
+        return ret;
+    }
+
+#elif defined(WOLFSSL_NUCLEUS_1_2)
+
+    int wc_InitMutex(wolfSSL_Mutex* m)
+    {
+        /* Call the Nucleus function to create the semaphore */
+        if (NU_Create_Semaphore(m, "WOLFSSL_MTX", 1,
+                                NU_PRIORITY) == NU_SUCCESS) {
+            return 0;
+        }
+
+        return BAD_MUTEX_E;
+    }
+
+    int wc_FreeMutex(wolfSSL_Mutex* m)
+    {
+        if (NU_Delete_Semaphore(m) == NU_SUCCESS)
+            return 0;
+
+        return BAD_MUTEX_E;
+    }
+
+    int wc_LockMutex(wolfSSL_Mutex* m)
+    {
+        /* passing suspend task option */
+        if (NU_Obtain_Semaphore(m, NU_SUSPEND) == NU_SUCCESS)
+            return 0;
+
+        return BAD_MUTEX_E;
+    }
+
+    int wc_UnLockMutex(wolfSSL_Mutex* m)
+    {
+        if (NU_Release_Semaphore(m) == NU_SUCCESS)
+            return 0;
+
+        return BAD_MUTEX_E;
+    }
+
+#elif defined(WOLFSSL_ZEPHYR)
+
+    int wc_InitMutex(wolfSSL_Mutex* m)
+    {
+        k_mutex_init(m);
+
+        return 0;
+    }
+
+    int wc_FreeMutex(wolfSSL_Mutex* m)
+    {
+        return 0;
+    }
+
+    int wc_LockMutex(wolfSSL_Mutex* m)
+    {
+        int ret = 0;
+
+        if (k_mutex_lock(m, K_FOREVER) != 0)
+            ret = BAD_MUTEX_E;
+
+        return ret;
+    }
+
+    int wc_UnLockMutex(wolfSSL_Mutex* m)
+    {
+        k_mutex_unlock(m);
+
+        return 0;
+    }
+
+#elif defined(WOLFSSL_TELIT_M2MB)
+
+    int wc_InitMutex(wolfSSL_Mutex* m)
+    {
+        M2MB_OS_RESULT_E        osRes;
+        M2MB_OS_MTX_ATTR_HANDLE mtxAttrHandle;
+        UINT32                  inheritVal = 1;
+
+        osRes = m2mb_os_mtx_setAttrItem(&mtxAttrHandle,
+                                    CMDS_ARGS(
+                                      M2MB_OS_MTX_SEL_CMD_CREATE_ATTR, NULL,
+                                      M2MB_OS_MTX_SEL_CMD_NAME, "wolfMtx",
+                                      M2MB_OS_MTX_SEL_CMD_INHERIT, inheritVal
+                                    )
+                                );
+        if (osRes != M2MB_OS_SUCCESS) {
+            return BAD_MUTEX_E;
+        }
+
+        osRes = m2mb_os_mtx_init(m, &mtxAttrHandle);
+        if (osRes != M2MB_OS_SUCCESS) {
+            return BAD_MUTEX_E;
+        }
+
+        return 0;
+    }
+
+    int wc_FreeMutex(wolfSSL_Mutex* m)
+    {
+        M2MB_OS_RESULT_E osRes;
+
+        if (m == NULL)
+            return BAD_MUTEX_E;
+
+        osRes = m2mb_os_mtx_deinit(*m);
+        if (osRes != M2MB_OS_SUCCESS) {
+            return BAD_MUTEX_E;
+        }
+
+        return 0;
+    }
+
+    int wc_LockMutex(wolfSSL_Mutex* m)
+    {
+        M2MB_OS_RESULT_E osRes;
+
+        if (m == NULL)
+            return BAD_MUTEX_E;
+
+        osRes = m2mb_os_mtx_get(*m, M2MB_OS_WAIT_FOREVER);
+        if (osRes != M2MB_OS_SUCCESS) {
+            return BAD_MUTEX_E;
+        }
+
+        return 0;
+    }
+
+    int wc_UnLockMutex(wolfSSL_Mutex* m)
+    {
+        M2MB_OS_RESULT_E osRes;
+
+        if (m == NULL)
+            return BAD_MUTEX_E;
+
+        osRes = m2mb_os_mtx_put(*m);
+        if (osRes != M2MB_OS_SUCCESS) {
+            return BAD_MUTEX_E;
+        }
+
+        return 0;
+    }
+
+#else
+    #warning No mutex handling defined
+
+#endif
+
+#ifndef NO_ASN_TIME
+#if defined(_WIN32_WCE)
+time_t windows_time(time_t* timer)
+{
+    SYSTEMTIME     sysTime;
+    FILETIME       fTime;
+    ULARGE_INTEGER intTime;
+    time_t         localTime;
+
+    if (timer == NULL)
+        timer = &localTime;
+
+    GetSystemTime(&sysTime);
+    SystemTimeToFileTime(&sysTime, &fTime);
+
+    XMEMCPY(&intTime, &fTime, sizeof(FILETIME));
+    /* subtract EPOCH */
+    intTime.QuadPart -= 0x19db1ded53e8000;
+    /* to secs */
+    intTime.QuadPart /= 10000000;
+    *timer = (time_t)intTime.QuadPart;
+
+    return *timer;
+}
+#endif /*  _WIN32_WCE */
+
+#if defined(WOLFSSL_APACHE_MYNEWT)
+#include "os/os_time.h"
+
+time_t mynewt_time(time_t* timer)
+{
+    time_t now;
+    struct os_timeval tv;
+    os_gettimeofday(&tv, NULL);
+    now = (time_t)tv.tv_sec;
+    if(timer != NULL) {
+        *timer = now;
+    }
+    return now;
+}
+#endif /* WOLFSSL_APACHE_MYNEWT */
+
+#if defined(WOLFSSL_GMTIME)
+struct tm* gmtime(const time_t* timer)
+{
+    #define YEAR0          1900
+    #define EPOCH_YEAR     1970
+    #define SECS_DAY       (24L * 60L * 60L)
+    #define LEAPYEAR(year) (!((year) % 4) && (((year) % 100) || !((year) %400)))
+    #define YEARSIZE(year) (LEAPYEAR(year) ? 366 : 365)
+
+    static const int _ytab[2][12] =
+    {
+        {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
+        {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
+    };
+
+    static struct tm st_time;
+    struct tm* ret = &st_time;
+    time_t secs = *timer;
+    unsigned long dayclock, dayno;
+    int year = EPOCH_YEAR;
+
+    dayclock = (unsigned long)secs % SECS_DAY;
+    dayno    = (unsigned long)secs / SECS_DAY;
+
+    ret->tm_sec  = (int) dayclock % 60;
+    ret->tm_min  = (int)(dayclock % 3600) / 60;
+    ret->tm_hour = (int) dayclock / 3600;
+    ret->tm_wday = (int) (dayno + 4) % 7;        /* day 0 a Thursday */
+
+    while(dayno >= (unsigned long)YEARSIZE(year)) {
+        dayno -= YEARSIZE(year);
+        year++;
+    }
+
+    ret->tm_year = year - YEAR0;
+    ret->tm_yday = (int)dayno;
+    ret->tm_mon  = 0;
+
+    while(dayno >= (unsigned long)_ytab[LEAPYEAR(year)][ret->tm_mon]) {
+        dayno -= _ytab[LEAPYEAR(year)][ret->tm_mon];
+        ret->tm_mon++;
+    }
+
+    ret->tm_mday  = (int)++dayno;
+    ret->tm_isdst = 0;
+
+    return ret;
+}
+#endif /* WOLFSSL_GMTIME */
+
+
+#if defined(HAVE_RTP_SYS)
+#define YEAR0          1900
+
+struct tm* rtpsys_gmtime(const time_t* timer)       /* has a gmtime() but hangs */
+{
+    static struct tm st_time;
+    struct tm* ret = &st_time;
+
+    DC_RTC_CALENDAR cal;
+    dc_rtc_time_get(&cal, TRUE);
+
+    ret->tm_year  = cal.year - YEAR0;       /* gm starts at 1900 */
+    ret->tm_mon   = cal.month - 1;          /* gm starts at 0 */
+    ret->tm_mday  = cal.day;
+    ret->tm_hour  = cal.hour;
+    ret->tm_min   = cal.minute;
+    ret->tm_sec   = cal.second;
+
+    return ret;
+}
+
+#endif /* HAVE_RTP_SYS */
+
+
+#if defined(MICROCHIP_TCPIP_V5) || defined(MICROCHIP_TCPIP)
+
+/*
+ * time() is just a stub in Microchip libraries. We need our own
+ * implementation. Use SNTP client to get seconds since epoch.
+ */
+time_t pic32_time(time_t* timer)
+{
+#ifdef MICROCHIP_TCPIP_V5
+    DWORD sec = 0;
+#else
+    uint32_t sec = 0;
+#endif
+    time_t localTime;
+
+    if (timer == NULL)
+        timer = &localTime;
+
+#ifdef MICROCHIP_MPLAB_HARMONY
+    sec = TCPIP_SNTP_UTCSecondsGet();
+#else
+    sec = SNTPGetUTCSeconds();
+#endif
+    *timer = (time_t) sec;
+
+    return *timer;
+}
+
+#endif /* MICROCHIP_TCPIP || MICROCHIP_TCPIP_V5 */
+
+#if defined(WOLFSSL_DEOS)
+
+time_t deos_time(time_t* timer)
+{
+    const uint32_t systemTickTimeInHz = 1000000 / systemTickInMicroseconds();
+    uint32_t *systemTickPtr = systemTickPointer();
+
+    if (timer != NULL)
+        *timer = *systemTickPtr/systemTickTimeInHz;
+
+    #if defined(CURRENT_UNIX_TIMESTAMP)
+        /* CURRENT_UNIX_TIMESTAMP is seconds since Jan 01 1970. (UTC) */
+        return (time_t) *systemTickPtr/systemTickTimeInHz + CURRENT_UNIX_TIMESTAMP;
+    #else
+        return (time_t) *systemTickPtr/systemTickTimeInHz;
+    #endif
+}
+#endif /* WOLFSSL_DEOS */
+
+#if defined(MICRIUM)
+
+time_t micrium_time(time_t* timer)
+{
+    CLK_TS_SEC sec;
+
+    Clk_GetTS_Unix(&sec);
+
+    if (timer != NULL)
+        *timer = sec;
+
+    return (time_t) sec;
+}
+
+#endif /* MICRIUM */
+
+#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
+
+time_t mqx_time(time_t* timer)
+{
+    time_t localTime;
+    TIME_STRUCT time_s;
+
+    if (timer == NULL)
+        timer = &localTime;
+
+    _time_get(&time_s);
+    *timer = (time_t) time_s.SECONDS;
+
+    return *timer;
+}
+
+#endif /* FREESCALE_MQX || FREESCALE_KSDK_MQX */
+
+
+#if defined(WOLFSSL_TIRTOS) && defined(USER_TIME)
+
+time_t XTIME(time_t * timer)
+{
+    time_t sec = 0;
+
+    sec = (time_t) Seconds_get();
+
+    if (timer != NULL)
+        *timer = sec;
+
+    return sec;
+}
+
+#endif /* WOLFSSL_TIRTOS */
+
+#if defined(WOLFSSL_XILINX)
+#include "xrtcpsu.h"
+
+time_t XTIME(time_t * timer)
+{
+    time_t sec = 0;
+    XRtcPsu_Config* con;
+    XRtcPsu         rtc;
+
+    con = XRtcPsu_LookupConfig(XPAR_XRTCPSU_0_DEVICE_ID);
+    if (con != NULL) {
+        if (XRtcPsu_CfgInitialize(&rtc, con, con->BaseAddr) == XST_SUCCESS) {
+            sec = (time_t)XRtcPsu_GetCurrentTime(&rtc);
+        }
+        else {
+            WOLFSSL_MSG("Unable to initialize RTC");
+        }
+    }
+
+    if (timer != NULL)
+        *timer = sec;
+
+    return sec;
+}
+
+#endif /* WOLFSSL_XILINX */
+
+#if defined(WOLFSSL_ZEPHYR)
+
+time_t z_time(time_t * timer)
+{
+    struct timespec ts;
+
+    if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
+        if (timer != NULL)
+            *timer = ts.tv_sec;
+
+    return ts.tv_sec;
+}
+
+#endif /* WOLFSSL_ZEPHYR */
+
+
+#if defined(WOLFSSL_WICED)
+    #ifndef WOLFSSL_WICED_PSEUDO_UNIX_EPOCH_TIME
+        #error Please define WOLFSSL_WICED_PSEUDO_UNIX_EPOCH_TIME at build time.
+    #endif /* WOLFSSL_WICED_PSEUDO_UNIX_EPOCH_TIME */
+
+time_t wiced_pseudo_unix_epoch_time(time_t * timer)
+{
+    time_t epoch_time;
+    /* The time() function return uptime on WICED platform. */
+    epoch_time = time(NULL) + WOLFSSL_WICED_PSEUDO_UNIX_EPOCH_TIME;
+
+    if (timer != NULL) {
+        *timer = epoch_time;
+    }
+    return epoch_time;
+}
+#endif /* WOLFSSL_WICED */
+
+#ifdef WOLFSSL_TELIT_M2MB
+    time_t m2mb_xtime(time_t * timer)
+    {
+        time_t myTime = 0;
+        INT32 fd = m2mb_rtc_open("/dev/rtc0", 0);
+        if (fd != -1) {
+            M2MB_RTC_TIMEVAL_T timeval;
+
+            m2mb_rtc_ioctl(fd, M2MB_RTC_IOCTL_GET_TIMEVAL, &timeval);
+
+            myTime = timeval.sec;
+
+            m2mb_rtc_close(fd);
+        }
+        return myTime;
+    }
+    #ifdef WOLFSSL_TLS13
+    time_t m2mb_xtime_ms(time_t * timer)
+    {
+        time_t myTime = 0;
+        INT32 fd = m2mb_rtc_open("/dev/rtc0", 0);
+        if (fd != -1) {
+            M2MB_RTC_TIMEVAL_T timeval;
+
+            m2mb_rtc_ioctl(fd, M2MB_RTC_IOCTL_GET_TIMEVAL, &timeval);
+
+            myTime = timeval.sec + timeval.msec;
+
+            m2mb_rtc_close(fd);
+        }
+        return myTime;
+    }
+    #endif /* WOLFSSL_TLS13 */
+    #ifndef NO_CRYPT_BENCHMARK
+    double m2mb_xtime_bench(int reset)
+    {
+        double myTime = 0;
+        INT32 fd = m2mb_rtc_open("/dev/rtc0", 0);
+        if (fd != -1) {
+            M2MB_RTC_TIMEVAL_T timeval;
+
+            m2mb_rtc_ioctl(fd, M2MB_RTC_IOCTL_GET_TIMEVAL, &timeval);
+
+            myTime = (double)timeval.sec + ((double)timeval.msec / 1000);
+
+            m2mb_rtc_close(fd);
+        }
+        return myTime;
+    }
+    #endif /* !NO_CRYPT_BENCHMARK */
+#endif /* WOLFSSL_TELIT_M2MB */
+
+#endif /* !NO_ASN_TIME */
+
+#ifndef WOLFSSL_LEANPSK
+char* mystrnstr(const char* s1, const char* s2, unsigned int n)
+{
+    unsigned int s2_len = (unsigned int)XSTRLEN(s2);
+
+    if (s2_len == 0)
+        return (char*)s1;
+
+    while (n >= s2_len && s1[0]) {
+        if (s1[0] == s2[0])
+            if (XMEMCMP(s1, s2, s2_len) == 0)
+                return (char*)s1;
+        s1++;
+        n--;
+    }
+
+    return NULL;
+}
+#endif
+
+/* custom memory wrappers */
+#ifdef WOLFSSL_NUCLEUS_1_2
+
+    /* system memory pool */
+    extern NU_MEMORY_POOL System_Memory;
+
+    void* nucleus_malloc(unsigned long size, void* heap, int type)
+    {
+        STATUS status;
+        void*  stack_ptr;
+
+        status = NU_Allocate_Memory(&System_Memory, &stack_ptr, size,
+                                    NU_NO_SUSPEND);
+        if (status == NU_SUCCESS) {
+            return 0;
+        } else {
+            return stack_ptr;
+        }
+    }
+
+    void* nucleus_realloc(void* ptr, unsigned long size, void* heap, int type)
+    {
+        DM_HEADER* old_header;
+        word32     old_size, copy_size;
+        void*      new_mem;
+
+        /* if ptr is NULL, behave like malloc */
+        new_mem = nucleus_malloc(size, NULL, 0);
+        if (new_mem == 0 || ptr == 0) {
+            return new_mem;
+        }
+
+        /* calculate old memory block size */
+        /* mem pointers stored in block headers (ref dm_defs.h) */
+        old_header = (DM_HEADER*) ((byte*)ptr - DM_OVERHEAD);
+        old_size   = (byte*)old_header->dm_next_memory - (byte*)ptr;
+
+        /* copy old to new */
+        if (old_size < size) {
+            copy_size = old_size;
+        } else {
+            copy_size = size;
+        }
+        XMEMCPY(new_mem, ptr, copy_size);
+
+        /* free old */
+        nucleus_free(ptr, NULL, 0);
+
+        return new_mem;
+    }
+
+    void nucleus_free(void* ptr, void* heap, int type)
+    {
+        if (ptr != NULL)
+            NU_Deallocate_Memory(ptr);
+    }
+
+#endif /* WOLFSSL_NUCLEUS_1_2 */
+
+#if defined(WOLFSSL_TI_CRYPT) || defined(WOLFSSL_TI_HASH)
+    #include <wolfcrypt/src/port/ti/ti-ccm.c>  /* initialize and Mutex for TI Crypt Engine */
+    #include <wolfcrypt/src/port/ti/ti-hash.c> /* md5, sha1, sha224, sha256 */
+#endif
+
+#if defined(WOLFSSL_CRYPTOCELL)
+    #define WOLFSSL_CRYPTOCELL_C
+    #include <wolfcrypt/src/port/arm/cryptoCell.c> /* CC310, RTC and RNG */
+    #if !defined(NO_SHA256)
+        #define WOLFSSL_CRYPTOCELL_HASH_C
+        #include <wolfcrypt/src/port/arm/cryptoCellHash.c> /* sha256 */
+    #endif
+#endif
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/wolfmath.c
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/wolfmath.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfcrypt/src/wolfmath.c	(revision 453)
@@ -0,0 +1,381 @@
+/* wolfmath.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+/* common functions for either math library */
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+/* in case user set USE_FAST_MATH there */
+#include <wolfssl/wolfcrypt/settings.h>
+
+#include <wolfssl/wolfcrypt/integer.h>
+
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#include <wolfssl/wolfcrypt/logging.h>
+
+#if defined(USE_FAST_MATH) || !defined(NO_BIG_INT)
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    #include <wolfssl/wolfcrypt/async.h>
+#endif
+
+#ifdef NO_INLINE
+    #include <wolfssl/wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+
+#if !defined(WC_NO_CACHE_RESISTANT) && \
+    ((defined(HAVE_ECC) && defined(ECC_TIMING_RESISTANT)) || \
+     (defined(USE_FAST_MATH) && defined(TFM_TIMING_RESISTANT)))
+
+    /* all off / all on pointer addresses for constant calculations */
+    /* ecc.c uses same table */
+    const wolfssl_word wc_off_on_addr[2] =
+    {
+    #if defined(WC_64BIT_CPU)
+        W64LIT(0x0000000000000000),
+        W64LIT(0xffffffffffffffff)
+    #elif defined(WC_16BIT_CPU)
+        0x0000U,
+        0xffffU
+    #else
+        /* 32 bit */
+        0x00000000U,
+        0xffffffffU
+    #endif
+    };
+#endif
+
+
+#if !defined(WOLFSSL_SP_MATH)
+int get_digit_count(mp_int* a)
+{
+    if (a == NULL)
+        return 0;
+
+    return a->used;
+}
+#endif
+
+mp_digit get_digit(mp_int* a, int n)
+{
+    if (a == NULL)
+        return 0;
+
+    return (n >= a->used || n < 0) ? 0 : a->dp[n];
+}
+
+/* Conditionally copy a into b. Performed in constant time.
+ *
+ * a     MP integer to copy.
+ * copy  On 1, copy a into b. on 0 leave b unchanged.
+ * b     MP integer to copy into.
+ * returns BAD_FUNC_ARG when a or b is NULL, MEMORY_E when growing b fails and
+ *         MP_OKAY otherwise.
+ */
+int mp_cond_copy(mp_int* a, int copy, mp_int* b)
+{
+    int err = MP_OKAY;
+    int i;
+    mp_digit mask = (mp_digit)0 - copy;
+
+    if (a == NULL || b == NULL)
+        err = BAD_FUNC_ARG;
+
+    /* Ensure b has enough space to copy a into */
+    if (err == MP_OKAY)
+        err = mp_grow(b, a->used + 1);
+    if (err == MP_OKAY) {
+        /* When mask 0, b is unchanged2
+         * When mask all set, b ^ b ^ a = a
+         */
+        /* Conditionaly copy all digits and then number of used diigits.
+         * get_digit() returns 0 when index greater than available digit.
+         */
+        for (i = 0; i < a->used; i++) {
+            b->dp[i] ^= (get_digit(a, i) ^ get_digit(b, i)) & mask;
+        }
+        for (; i < b->used; i++) {
+            b->dp[i] ^= (get_digit(a, i) ^ get_digit(b, i)) & mask;
+        }
+        b->used ^= (a->used ^ b->used) & (int)mask;
+    }
+
+    return err;
+}
+
+#ifndef WC_NO_RNG
+int get_rand_digit(WC_RNG* rng, mp_digit* d)
+{
+    return wc_RNG_GenerateBlock(rng, (byte*)d, sizeof(mp_digit));
+}
+
+#ifdef WC_RSA_BLINDING
+int mp_rand(mp_int* a, int digits, WC_RNG* rng)
+{
+    int ret = 0;
+    int cnt = digits * sizeof(mp_digit);
+#if !defined(USE_FAST_MATH) && !defined(WOLFSSL_SP_MATH)
+    int i;
+#endif
+
+    if (rng == NULL) {
+        ret = MISSING_RNG_E;
+    }
+    else if (a == NULL) {
+        ret = BAD_FUNC_ARG;
+    }
+
+#if !defined(USE_FAST_MATH) && !defined(WOLFSSL_SP_MATH)
+    /* allocate space for digits */
+    if (ret == MP_OKAY) {
+        ret = mp_set_bit(a, digits * DIGIT_BIT - 1);
+    }
+#else
+#if defined(WOLFSSL_SP_MATH)
+    if ((ret == MP_OKAY) && (digits > SP_INT_DIGITS))
+#else
+    if ((ret == MP_OKAY) && (digits > FP_SIZE))
+#endif
+    {
+        ret = BAD_FUNC_ARG;
+    }
+    if (ret == MP_OKAY) {
+        a->used = digits;
+    }
+#endif
+    /* fill the data with random bytes */
+    if (ret == MP_OKAY) {
+        ret = wc_RNG_GenerateBlock(rng, (byte*)a->dp, cnt);
+    }
+    if (ret == MP_OKAY) {
+#if !defined(USE_FAST_MATH) && !defined(WOLFSSL_SP_MATH)
+        /* Mask down each digit to only bits used */
+        for (i = 0; i < a->used; i++) {
+            a->dp[i] &= MP_MASK;
+        }
+#endif
+        /* ensure top digit is not zero */
+        while ((ret == MP_OKAY) && (a->dp[a->used - 1] == 0)) {
+            ret = get_rand_digit(rng, &a->dp[a->used - 1]);
+#if !defined(USE_FAST_MATH) && !defined(WOLFSSL_SP_MATH)
+            a->dp[a->used - 1] &= MP_MASK;
+#endif
+        }
+    }
+
+    return ret;
+}
+#endif /* WC_RSA_BLINDING */
+#endif
+
+/* export an mp_int as unsigned char or hex string
+ * encType is WC_TYPE_UNSIGNED_BIN or WC_TYPE_HEX_STR
+ * return MP_OKAY on success */
+int wc_export_int(mp_int* mp, byte* buf, word32* len, word32 keySz,
+    int encType)
+{
+    int err;
+
+    if (mp == NULL)
+        return BAD_FUNC_ARG;
+
+    /* check buffer size */
+    if (*len < keySz) {
+        *len = keySz;
+        return BUFFER_E;
+    }
+
+    *len = keySz;
+    XMEMSET(buf, 0, *len);
+
+    if (encType == WC_TYPE_HEX_STR) {
+    #ifdef WC_MP_TO_RADIX
+        err = mp_tohex(mp, (char*)buf);
+    #else
+        err = NOT_COMPILED_IN;
+    #endif
+    }
+    else {
+        err = mp_to_unsigned_bin(mp, buf + (keySz - mp_unsigned_bin_size(mp)));
+    }
+
+    return err;
+}
+
+
+#ifdef HAVE_WOLF_BIGINT
+void wc_bigint_init(WC_BIGINT* a)
+{
+    if (a != NULL) {
+        a->buf = NULL;
+        a->len = 0;
+        a->heap = NULL;
+    }
+}
+
+int wc_bigint_alloc(WC_BIGINT* a, word32 sz)
+{
+    int err = MP_OKAY;
+
+    if (a == NULL)
+        return BAD_FUNC_ARG;
+
+    if (sz > 0) {
+        if (a->buf && sz > a->len) {
+            wc_bigint_free(a);
+        }
+        if (a->buf == NULL) {
+            a->buf = (byte*)XMALLOC(sz, a->heap, DYNAMIC_TYPE_WOLF_BIGINT);
+            if (a->buf == NULL) {
+                err = MP_MEM;
+            }
+        }
+        else {
+            XMEMSET(a->buf, 0, sz);
+        }
+    }
+    a->len = sz;
+
+    return err;
+}
+
+/* assumes input is big endian format */
+int wc_bigint_from_unsigned_bin(WC_BIGINT* a, const byte* in, word32 inlen)
+{
+    int err;
+
+    if (a == NULL || in == NULL || inlen == 0)
+        return BAD_FUNC_ARG;
+
+    err = wc_bigint_alloc(a, inlen);
+    if (err == 0) {
+        XMEMCPY(a->buf, in, inlen);
+    }
+
+    return err;
+}
+
+int wc_bigint_to_unsigned_bin(WC_BIGINT* a, byte* out, word32* outlen)
+{
+    word32 sz;
+
+    if (a == NULL || out == NULL || outlen == NULL || *outlen == 0)
+        return BAD_FUNC_ARG;
+
+    /* trim to fit into output buffer */
+    sz = a->len;
+    if (a->len > *outlen) {
+        WOLFSSL_MSG("wc_bigint_export: Truncating output");
+        sz = *outlen;
+    }
+
+    if (a->buf) {
+        XMEMCPY(out, a->buf, sz);
+    }
+
+    *outlen = sz;
+
+    return MP_OKAY;
+}
+
+void wc_bigint_zero(WC_BIGINT* a)
+{
+    if (a && a->buf) {
+        ForceZero(a->buf, a->len);
+    }
+}
+
+void wc_bigint_free(WC_BIGINT* a)
+{
+    if (a) {
+        if (a->buf) {
+          XFREE(a->buf, a->heap, DYNAMIC_TYPE_WOLF_BIGINT);
+        }
+        a->buf = NULL;
+        a->len = 0;
+    }
+}
+
+/* sz: make sure the buffer is at least that size and zero padded.
+ *     A `sz == 0` will use the size of `src`.
+ *     The calulcates sz is stored into dst->len in `wc_bigint_alloc`.
+ */
+int wc_mp_to_bigint_sz(mp_int* src, WC_BIGINT* dst, word32 sz)
+{
+    int err;
+    word32 x, y;
+
+    if (src == NULL || dst == NULL)
+        return BAD_FUNC_ARG;
+
+    /* get size of source */
+    x = mp_unsigned_bin_size(src);
+    if (sz < x)
+        sz = x;
+
+    /* make sure destination is allocated and large enough */
+    err = wc_bigint_alloc(dst, sz);
+    if (err == MP_OKAY) {
+
+        /* leading zero pad */
+        y = sz - x;
+        XMEMSET(dst->buf, 0, y);
+
+        /* export src as unsigned bin to destination buf */
+        err = mp_to_unsigned_bin(src, dst->buf + y);
+    }
+
+    return err;
+}
+
+int wc_mp_to_bigint(mp_int* src, WC_BIGINT* dst)
+{
+    if (src == NULL || dst == NULL)
+        return BAD_FUNC_ARG;
+
+    return wc_mp_to_bigint_sz(src, dst, 0);
+}
+
+int wc_bigint_to_mp(WC_BIGINT* src, mp_int* dst)
+{
+    int err;
+
+    if (src == NULL || dst == NULL)
+        return BAD_FUNC_ARG;
+
+    if (src->buf == NULL)
+        return BAD_FUNC_ARG;
+
+    err = mp_read_unsigned_bin(dst, src->buf, src->len);
+    wc_bigint_free(src);
+
+    return err;
+}
+#endif /* HAVE_WOLF_BIGINT */
+
+#endif /* USE_FAST_MATH || !NO_BIG_INT */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/callbacks.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/callbacks.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/callbacks.h	(revision 453)
@@ -0,0 +1,93 @@
+/* callbacks.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+#ifndef WOLFSSL_CALLBACKS_H
+#define WOLFSSL_CALLBACKS_H
+
+#include <wolfssl/wolfcrypt/wc_port.h>
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+
+enum { /* CALLBACK CONSTANTS */
+    MAX_PACKETNAME_SZ     =  24,
+    MAX_CIPHERNAME_SZ     =  24,
+    MAX_TIMEOUT_NAME_SZ   =  24,
+    MAX_PACKETS_HANDSHAKE =  14,       /* 12 for client auth plus 2 alerts */
+    MAX_VALUE_SZ          = 128,       /* all handshake packets but Cert should
+                                          fit here  */
+};
+
+struct WOLFSSL;
+
+typedef struct handShakeInfo_st {
+    struct WOLFSSL* ssl;
+    char   cipherName[MAX_CIPHERNAME_SZ + 1];    /* negotiated cipher */
+    char   packetNames[MAX_PACKETS_HANDSHAKE][MAX_PACKETNAME_SZ + 1];
+                                                 /* SSL packet names  */
+    int    numberPackets;                        /* actual # of packets */
+    int    negotiationError;                     /* cipher/parameter err */
+} HandShakeInfo;
+
+
+#if defined(HAVE_SYS_TIME_H) && !defined(NO_TIMEVAL)
+    typedef struct timeval WOLFSSL_TIMEVAL;
+#else /* HAVE_SYS_TIME_H */
+    /* Define the timeval explicitly. */
+    typedef struct {
+        long tv_sec;  /* Seconds. */
+        long tv_usec; /* Microseconds. */
+    } WOLFSSL_TIMEVAL;
+#endif /* HAVE_SYS_TIME_H */
+#if !defined(NO_OLD_TIMEVAL_NAME)
+    #define Timeval WOLFSSL_TIMEVAL
+#endif
+
+typedef struct packetInfo_st {
+    char           packetName[MAX_PACKETNAME_SZ + 1]; /* SSL packet name */
+    WOLFSSL_TIMEVAL timestamp;                       /* when it occurred    */
+    unsigned char  value[MAX_VALUE_SZ];             /* if fits, it's here */
+    unsigned char* bufferValue;                     /* otherwise here (non 0) */
+    int            valueSz;                         /* sz of value or buffer */
+} PacketInfo;
+
+
+typedef struct timeoutInfo_st {
+    char       timeoutName[MAX_TIMEOUT_NAME_SZ + 1]; /* timeout Name */
+    int        flags;                              /* for future use */
+    int        numberPackets;                      /* actual # of packets */
+    PacketInfo packets[MAX_PACKETS_HANDSHAKE];     /* list of all packets  */
+    WOLFSSL_TIMEVAL timeoutValue;                  /* timer that caused it */
+} TimeoutInfo;
+
+
+
+#ifdef __cplusplus
+    }  /* extern "C" */
+#endif
+
+
+#endif /* WOLFSSL_CALLBACKS_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/error-ssl.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/error-ssl.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/error-ssl.h	(revision 453)
@@ -0,0 +1,204 @@
+/* error-ssl.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+#ifndef WOLFSSL_ERROR_H
+#define WOLFSSL_ERROR_H
+
+#include <wolfssl/wolfcrypt/error-crypt.h>   /* pull in wolfCrypt errors */
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+enum wolfSSL_ErrorCodes {
+    INPUT_CASE_ERROR             = -301,   /* process input state error */
+    PREFIX_ERROR                 = -302,   /* bad index to key rounds  */
+    MEMORY_ERROR                 = -303,   /* out of memory            */
+    VERIFY_FINISHED_ERROR        = -304,   /* verify problem on finished */
+    VERIFY_MAC_ERROR             = -305,   /* verify mac problem       */
+    PARSE_ERROR                  = -306,   /* parse error on header    */
+    UNKNOWN_HANDSHAKE_TYPE       = -307,   /* weird handshake type     */
+    SOCKET_ERROR_E               = -308,   /* error state on socket    */
+    SOCKET_NODATA                = -309,   /* expected data, not there */
+    INCOMPLETE_DATA              = -310,   /* don't have enough data to
+                                              complete task            */
+    UNKNOWN_RECORD_TYPE          = -311,   /* unknown type in record hdr */
+    DECRYPT_ERROR                = -312,   /* error during decryption  */
+    FATAL_ERROR                  = -313,   /* recvd alert fatal error  */
+    ENCRYPT_ERROR                = -314,   /* error during encryption  */
+    FREAD_ERROR                  = -315,   /* fread problem            */
+    NO_PEER_KEY                  = -316,   /* need peer's key          */
+    NO_PRIVATE_KEY               = -317,   /* need the private key     */
+    RSA_PRIVATE_ERROR            = -318,   /* error during rsa priv op */
+    NO_DH_PARAMS                 = -319,   /* server missing DH params */
+    BUILD_MSG_ERROR              = -320,   /* build message failure    */
+
+    BAD_HELLO                    = -321,   /* client hello malformed   */
+    DOMAIN_NAME_MISMATCH         = -322,   /* peer subject name mismatch */
+    WANT_READ                    = -323,   /* want read, call again    */
+    NOT_READY_ERROR              = -324,   /* handshake layer not ready */
+    IPADDR_MISMATCH              = -325,   /* peer ip address mismatch */
+    VERSION_ERROR                = -326,   /* record layer version error */
+    WANT_WRITE                   = -327,   /* want write, call again   */
+    BUFFER_ERROR                 = -328,   /* malformed buffer input   */
+    VERIFY_CERT_ERROR            = -329,   /* verify cert error        */
+    VERIFY_SIGN_ERROR            = -330,   /* verify sign error        */
+    CLIENT_ID_ERROR              = -331,   /* psk client identity error  */
+    SERVER_HINT_ERROR            = -332,   /* psk server hint error  */
+    PSK_KEY_ERROR                = -333,   /* psk key error  */
+
+    GETTIME_ERROR                = -337,   /* gettimeofday failed ??? */
+    GETITIMER_ERROR              = -338,   /* getitimer failed ??? */
+    SIGACT_ERROR                 = -339,   /* sigaction failed ??? */
+    SETITIMER_ERROR              = -340,   /* setitimer failed ??? */
+    LENGTH_ERROR                 = -341,   /* record layer length error */
+    PEER_KEY_ERROR               = -342,   /* can't decode peer key */
+    ZERO_RETURN                  = -343,   /* peer sent close notify */
+    SIDE_ERROR                   = -344,   /* wrong client/server type */
+    NO_PEER_CERT                 = -345,   /* peer didn't send key */
+    NTRU_KEY_ERROR               = -346,   /* NTRU key error  */
+    NTRU_DRBG_ERROR              = -347,   /* NTRU drbg error  */
+    NTRU_ENCRYPT_ERROR           = -348,   /* NTRU encrypt error  */
+    NTRU_DECRYPT_ERROR           = -349,   /* NTRU decrypt error  */
+    ECC_CURVETYPE_ERROR          = -350,   /* Bad ECC Curve Type */
+    ECC_CURVE_ERROR              = -351,   /* Bad ECC Curve */
+    ECC_PEERKEY_ERROR            = -352,   /* Bad Peer ECC Key */
+    ECC_MAKEKEY_ERROR            = -353,   /* Bad Make ECC Key */
+    ECC_EXPORT_ERROR             = -354,   /* Bad ECC Export Key */
+    ECC_SHARED_ERROR             = -355,   /* Bad ECC Shared Secret */
+    NOT_CA_ERROR                 = -357,   /* Not a CA cert error */
+
+    BAD_CERT_MANAGER_ERROR       = -359,   /* Bad Cert Manager */
+    OCSP_CERT_REVOKED            = -360,   /* OCSP Certificate revoked */
+    CRL_CERT_REVOKED             = -361,   /* CRL Certificate revoked */
+    CRL_MISSING                  = -362,   /* CRL Not loaded */
+    MONITOR_SETUP_E              = -363,   /* CRL Monitor setup error */
+    THREAD_CREATE_E              = -364,   /* Thread Create Error */
+    OCSP_NEED_URL                = -365,   /* OCSP need an URL for lookup */
+    OCSP_CERT_UNKNOWN            = -366,   /* OCSP responder doesn't know */
+    OCSP_LOOKUP_FAIL             = -367,   /* OCSP lookup not successful */
+    MAX_CHAIN_ERROR              = -368,   /* max chain depth exceeded */
+    COOKIE_ERROR                 = -369,   /* dtls cookie error */
+    SEQUENCE_ERROR               = -370,   /* dtls sequence error */
+    SUITES_ERROR                 = -371,   /* suites pointer error */
+
+    OUT_OF_ORDER_E               = -373,   /* out of order message */
+    BAD_KEA_TYPE_E               = -374,   /* bad KEA type found */
+    SANITY_CIPHER_E              = -375,   /* sanity check on cipher error */
+    RECV_OVERFLOW_E              = -376,   /* RXCB returned more than read */
+    GEN_COOKIE_E                 = -377,   /* Generate Cookie Error */
+    NO_PEER_VERIFY               = -378,   /* Need peer cert verify Error */
+    FWRITE_ERROR                 = -379,   /* fwrite problem */
+    CACHE_MATCH_ERROR            = -380,   /* Cache hdr match error */
+    UNKNOWN_SNI_HOST_NAME_E      = -381,   /* Unrecognized host name Error */
+    UNKNOWN_MAX_FRAG_LEN_E       = -382,   /* Unrecognized max frag len Error */
+    KEYUSE_SIGNATURE_E           = -383,   /* KeyUse digSignature error */
+    KEYUSE_ENCIPHER_E            = -385,   /* KeyUse keyEncipher error */
+    EXTKEYUSE_AUTH_E             = -386,   /* ExtKeyUse server|client_auth */
+    SEND_OOB_READ_E              = -387,   /* Send Cb out of bounds read */
+    SECURE_RENEGOTIATION_E       = -388,   /* Invalid Renegotiation Info */
+    SESSION_TICKET_LEN_E         = -389,   /* Session Ticket too large */
+    SESSION_TICKET_EXPECT_E      = -390,   /* Session Ticket missing   */
+    SCR_DIFFERENT_CERT_E         = -391,   /* SCR Different cert error  */
+    SESSION_SECRET_CB_E          = -392,   /* Session secret Cb fcn failure */
+    NO_CHANGE_CIPHER_E           = -393,   /* Finished before change cipher */
+    SANITY_MSG_E                 = -394,   /* Sanity check on msg order error */
+    DUPLICATE_MSG_E              = -395,   /* Duplicate message error */
+    SNI_UNSUPPORTED              = -396,   /* SSL 3.0 does not support SNI */
+    SOCKET_PEER_CLOSED_E         = -397,   /* Underlying transport closed */
+    BAD_TICKET_KEY_CB_SZ         = -398,   /* Bad session ticket key cb size */
+    BAD_TICKET_MSG_SZ            = -399,   /* Bad session ticket msg size    */
+    BAD_TICKET_ENCRYPT           = -400,   /* Bad user ticket encrypt        */
+    DH_KEY_SIZE_E                = -401,   /* DH Key too small */
+    SNI_ABSENT_ERROR             = -402,   /* No SNI request. */
+    RSA_SIGN_FAULT               = -403,   /* RSA Sign fault */
+    HANDSHAKE_SIZE_ERROR         = -404,   /* Handshake message too large */
+    UNKNOWN_ALPN_PROTOCOL_NAME_E = -405,   /* Unrecognized protocol name Error*/
+    BAD_CERTIFICATE_STATUS_ERROR = -406,   /* Bad certificate status message */
+    OCSP_INVALID_STATUS          = -407,   /* Invalid OCSP Status */
+    OCSP_WANT_READ               = -408,   /* OCSP callback response WOLFSSL_CBIO_ERR_WANT_READ */
+    RSA_KEY_SIZE_E               = -409,   /* RSA key too small */
+    ECC_KEY_SIZE_E               = -410,   /* ECC key too small */
+    DTLS_EXPORT_VER_E            = -411,   /* export version error */
+    INPUT_SIZE_E                 = -412,   /* input size too big error */
+    CTX_INIT_MUTEX_E             = -413,   /* initialize ctx mutex error */
+    EXT_MASTER_SECRET_NEEDED_E   = -414,   /* need EMS enabled to resume */
+    DTLS_POOL_SZ_E               = -415,   /* exceeded DTLS pool size */
+    DECODE_E                     = -416,   /* decode handshake message error */
+    HTTP_TIMEOUT                 = -417,   /* HTTP timeout for OCSP or CRL req */
+    WRITE_DUP_READ_E             = -418,   /* Write dup write side can't read */
+    WRITE_DUP_WRITE_E            = -419,   /* Write dup read side can't write */
+    INVALID_CERT_CTX_E           = -420,   /* TLS cert ctx not matching */
+    BAD_KEY_SHARE_DATA           = -421,   /* Key Share data invalid */
+    MISSING_HANDSHAKE_DATA       = -422,   /* Handshake message missing data */
+    BAD_BINDER                   = -423,   /* Binder does not match */
+    EXT_NOT_ALLOWED              = -424,   /* Extension not allowed in msg */
+    INVALID_PARAMETER            = -425,   /* Security parameter invalid */
+    MCAST_HIGHWATER_CB_E         = -426,   /* Multicast highwater cb err */
+    ALERT_COUNT_E                = -427,   /* Alert Count exceeded err */
+    EXT_MISSING                  = -428,   /* Required extension not found */
+    UNSUPPORTED_EXTENSION        = -429,   /* TLSX not requested by client */
+    PRF_MISSING                  = -430,   /* PRF not compiled in */
+    DTLS_RETX_OVER_TX            = -431,   /* Retransmit DTLS flight over */
+    DH_PARAMS_NOT_FFDHE_E        = -432,   /* DH params from server not FFDHE */
+    TCA_INVALID_ID_TYPE          = -433,   /* TLSX TCA ID type invalid */
+    TCA_ABSENT_ERROR             = -434,   /* TLSX TCA ID no response */
+    TSIP_MAC_DIGSZ_E             = -435,   /* Invalid MAC size for TSIP */
+    CLIENT_CERT_CB_ERROR         = -436,   /* Client cert callback error */
+    SSL_SHUTDOWN_ALREADY_DONE_E  = -437,   /* Shutdown called redundantly */
+    TLS13_SECRET_CB_E            = -438,   /* TLS1.3 secret Cb fcn failure */
+
+    /* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */
+
+    /* begin negotiation parameter errors */
+    UNSUPPORTED_SUITE            = -500,   /* unsupported cipher suite */
+    MATCH_SUITE_ERROR            = -501,   /* can't match cipher suite */
+    COMPRESSION_ERROR            = -502,   /* compression mismatch */
+    KEY_SHARE_ERROR              = -503,   /* key share mismatch */
+    POST_HAND_AUTH_ERROR         = -504,   /* client won't do post-hand auth */
+    HRR_COOKIE_ERROR             = -505    /* HRR msg cookie mismatch */
+    /* end negotiation parameter errors only 10 for now */
+    /* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */
+
+    /* no error stings go down here, add above negotiation errors !!!! */
+};
+
+
+#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+    enum {
+        MIN_PARAM_ERR = UNSUPPORTED_SUITE,
+        MAX_PARAM_ERR = MIN_PARAM_ERR - 10
+    };
+#endif
+
+
+WOLFSSL_LOCAL
+void SetErrorString(int err, char* buff);
+
+
+#ifdef __cplusplus
+    }  /* extern "C" */
+#endif
+
+
+#endif /* wolfSSL_ERROR_H */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/internal.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/internal.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/internal.h	(revision 453)
@@ -0,0 +1,4613 @@
+/* internal.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+#ifndef WOLFSSL_INT_H
+#define WOLFSSL_INT_H
+
+
+#include <wolfssl/wolfcrypt/types.h>
+#include <wolfssl/ssl.h>
+#ifdef HAVE_CRL
+    #include <wolfssl/crl.h>
+#endif
+#include <wolfssl/wolfcrypt/random.h>
+#ifndef NO_DES3
+    #include <wolfssl/wolfcrypt/des3.h>
+#endif
+#ifndef NO_HC128
+    #include <wolfssl/wolfcrypt/hc128.h>
+#endif
+#ifndef NO_RABBIT
+    #include <wolfssl/wolfcrypt/rabbit.h>
+#endif
+#ifdef HAVE_CHACHA
+    #include <wolfssl/wolfcrypt/chacha.h>
+#endif
+#ifndef NO_ASN
+    #include <wolfssl/wolfcrypt/asn.h>
+    #include <wolfssl/wolfcrypt/pkcs12.h>
+#endif
+#ifndef NO_MD5
+    #include <wolfssl/wolfcrypt/md5.h>
+#endif
+#ifndef NO_SHA
+    #include <wolfssl/wolfcrypt/sha.h>
+#endif
+#ifndef NO_AES
+    #include <wolfssl/wolfcrypt/aes.h>
+#endif
+#ifdef HAVE_POLY1305
+    #include <wolfssl/wolfcrypt/poly1305.h>
+#endif
+#ifdef HAVE_CAMELLIA
+    #include <wolfssl/wolfcrypt/camellia.h>
+#endif
+#include <wolfssl/wolfcrypt/logging.h>
+#ifndef NO_HMAC
+    #include <wolfssl/wolfcrypt/hmac.h>
+#endif
+#ifndef NO_RC4
+    #include <wolfssl/wolfcrypt/arc4.h>
+#endif
+#ifndef NO_SHA256
+    #include <wolfssl/wolfcrypt/sha256.h>
+#endif
+#ifdef HAVE_OCSP
+    #include <wolfssl/ocsp.h>
+#endif
+#ifdef WOLFSSL_SHA384
+    #include <wolfssl/wolfcrypt/sha512.h>
+#endif
+#ifdef WOLFSSL_SHA512
+    #include <wolfssl/wolfcrypt/sha512.h>
+#endif
+#ifdef HAVE_AESGCM
+    #include <wolfssl/wolfcrypt/sha512.h>
+#endif
+#ifdef WOLFSSL_RIPEMD
+    #include <wolfssl/wolfcrypt/ripemd.h>
+#endif
+#ifdef HAVE_IDEA
+    #include <wolfssl/wolfcrypt/idea.h>
+#endif
+#ifndef NO_RSA
+    #include <wolfssl/wolfcrypt/rsa.h>
+#endif
+#ifdef HAVE_ECC
+    #include <wolfssl/wolfcrypt/ecc.h>
+#endif
+#ifndef NO_DH
+    #include <wolfssl/wolfcrypt/dh.h>
+#endif
+#ifdef HAVE_ED25519
+    #include <wolfssl/wolfcrypt/ed25519.h>
+#endif
+#ifdef HAVE_CURVE25519
+    #include <wolfssl/wolfcrypt/curve25519.h>
+#endif
+#ifdef HAVE_ED448
+    #include <wolfssl/wolfcrypt/ed448.h>
+#endif
+#ifdef HAVE_CURVE448
+    #include <wolfssl/wolfcrypt/curve448.h>
+#endif
+
+#include <wolfssl/wolfcrypt/wc_encrypt.h>
+#include <wolfssl/wolfcrypt/hash.h>
+
+#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+    #include <wolfssl/callbacks.h>
+#endif
+#ifdef WOLFSSL_CALLBACKS
+    #include <signal.h>
+#endif
+
+#ifdef USE_WINDOWS_API
+    #ifdef WOLFSSL_GAME_BUILD
+        #include "system/xtl.h"
+    #else
+        #if defined(_WIN32_WCE) || defined(WIN32_LEAN_AND_MEAN)
+            /* On WinCE winsock2.h must be included before windows.h */
+            #include <winsock2.h>
+        #endif
+        #include <windows.h>
+    #endif
+#elif defined(THREADX)
+    #ifndef SINGLE_THREADED
+        #include "tx_api.h"
+    #endif
+
+#elif defined(WOLFSSL_DEOS)
+    /* do nothing, just don't pick Unix */
+#elif defined(MICRIUM)
+    /* do nothing, just don't pick Unix */
+#elif defined(FREERTOS) || defined(FREERTOS_TCP) || defined(WOLFSSL_SAFERTOS)
+    /* do nothing */
+#elif defined(EBSNET)
+    /* do nothing */
+#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
+    /* do nothing */
+#elif defined(FREESCALE_FREE_RTOS)
+    #include "fsl_os_abstraction.h"
+#elif defined(WOLFSSL_uITRON4)
+        /* do nothing */
+#elif defined(WOLFSSL_uTKERNEL2)
+        /* do nothing */
+#elif defined(WOLFSSL_CMSIS_RTOS)
+    #include "cmsis_os.h"
+#elif defined(WOLFSSL_CMSIS_RTOSv2)
+    #include "cmsis_os2.h"
+#elif defined(WOLFSSL_MDK_ARM)
+    #if defined(WOLFSSL_MDK5)
+        #include "cmsis_os.h"
+    #else
+        #include <rtl.h>
+    #endif
+#elif defined(MBED)
+#elif defined(WOLFSSL_TIRTOS)
+    /* do nothing */
+#elif defined(INTIME_RTOS)
+    #include <rt.h>
+#elif defined(WOLFSSL_NUCLEUS_1_2)
+    /* do nothing */
+#elif defined(WOLFSSL_APACHE_MYNEWT)
+    #if !defined(WOLFSSL_LWIP)
+        void mynewt_ctx_clear(void *ctx);
+        void* mynewt_ctx_new();
+    #endif
+#elif defined(WOLFSSL_ZEPHYR)
+    #ifndef SINGLE_THREADED
+        #include <kernel.h>
+    #endif
+#elif defined(WOLFSSL_TELIT_M2MB)
+    /* do nothing */
+#else
+    #ifndef SINGLE_THREADED
+        #define WOLFSSL_PTHREADS
+        #include <pthread.h>
+    #endif
+    #if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM)
+        #include <unistd.h>      /* for close of BIO */
+    #endif
+#endif
+
+#ifndef CHAR_BIT
+    /* Needed for DTLS without big math */
+    #include <limits.h>
+#endif
+
+
+#ifdef HAVE_LIBZ
+    #include "zlib.h"
+#endif
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    #include <wolfssl/wolfcrypt/async.h>
+#endif
+
+#ifdef OPENSSL_EXTRA
+    #ifdef WOLFCRYPT_HAVE_SRP
+        #include <wolfssl/wolfcrypt/srp.h>
+    #endif
+#endif
+
+#ifdef _MSC_VER
+    /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */
+    #pragma warning(disable: 4996)
+#endif
+
+#ifdef NO_SHA
+    #define WC_SHA_DIGEST_SIZE 20
+#endif
+
+#ifdef NO_SHA256
+    #define WC_SHA256_DIGEST_SIZE 32
+#endif
+
+#ifdef NO_MD5
+    #define WC_MD5_DIGEST_SIZE 16
+#endif
+
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+/* Define or comment out the cipher suites you'd like to be compiled in
+   make sure to use at least one BUILD_SSL_xxx or BUILD_TLS_xxx is defined
+
+   When adding cipher suites, add name to cipher_names, idx to cipher_name_idx
+
+   Now that there is a maximum strength crypto build, the following BUILD_XXX
+   flags need to be divided into two groups selected by WOLFSSL_MAX_STRENGTH.
+   Those that do not use Perfect Forward Security and do not use AEAD ciphers
+   need to be switched off. Allowed suites use (EC)DHE, AES-GCM|CCM, or
+   CHACHA-POLY.
+*/
+
+/* Check that if WOLFSSL_MAX_STRENGTH is set that all the required options are
+ * not turned off. */
+#if defined(WOLFSSL_MAX_STRENGTH) && \
+    ((!defined(HAVE_ECC) && (defined(NO_DH) || defined(NO_RSA))) || \
+     (!defined(HAVE_AESGCM) && !defined(HAVE_AESCCM) && \
+      (!defined(HAVE_POLY1305) || !defined(HAVE_CHACHA))) || \
+     (defined(NO_SHA256) && !defined(WOLFSSL_SHA384)) || \
+     !defined(NO_OLD_TLS))
+
+    #error "You are trying to build max strength with requirements disabled."
+#endif
+
+/* Have QSH : Quantum-safe Handshake */
+#if defined(HAVE_QSH)
+    #define BUILD_TLS_QSH
+#endif
+
+#ifndef WOLFSSL_NO_TLS12
+
+#ifndef WOLFSSL_MAX_STRENGTH
+
+#ifdef WOLFSSL_AEAD_ONLY
+    /* AES CBC ciphers are not allowed in AEAD only mode */
+    #undef HAVE_AES_CBC
+#endif
+
+#ifndef WOLFSSL_AEAD_ONLY
+    #if !defined(NO_RSA) && !defined(NO_RC4)
+        #if defined(WOLFSSL_STATIC_RSA)
+            #if !defined(NO_SHA)
+                #define BUILD_SSL_RSA_WITH_RC4_128_SHA
+            #endif
+            #if !defined(NO_MD5)
+                #define BUILD_SSL_RSA_WITH_RC4_128_MD5
+            #endif
+        #endif
+        #if !defined(NO_TLS) && defined(HAVE_NTRU) && !defined(NO_SHA) \
+            && defined(WOLFSSL_STATIC_RSA)
+            #define BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
+        #endif
+    #endif
+
+    #if !defined(NO_RSA) && !defined(NO_DES3)
+        #if !defined(NO_SHA)
+            #if defined(WOLFSSL_STATIC_RSA)
+                #define BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
+            #endif
+            #if !defined(NO_TLS) && defined(HAVE_NTRU) \
+                && defined(WOLFSSL_STATIC_RSA)
+                    #define BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
+            #endif
+        #endif
+    #endif
+
+    #if !defined(NO_RSA) && defined(HAVE_IDEA)
+        #if !defined(NO_SHA) && defined(WOLFSSL_STATIC_RSA)
+            #define BUILD_SSL_RSA_WITH_IDEA_CBC_SHA
+        #endif
+    #endif
+#endif /* !WOLFSSL_AEAD_ONLY */
+
+    #if !defined(NO_RSA) && !defined(NO_AES) && !defined(NO_TLS)
+        #if !defined(NO_SHA) && defined(HAVE_AES_CBC)
+            #if defined(WOLFSSL_STATIC_RSA)
+                #ifdef WOLFSSL_AES_128
+                    #define BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
+                #endif
+                #ifdef WOLFSSL_AES_256
+                    #define BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
+                #endif
+            #endif
+            #if defined(HAVE_NTRU) && defined(WOLFSSL_STATIC_RSA)
+                #ifdef WOLFSSL_AES_128
+                    #define BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
+                #endif
+                #ifdef WOLFSSL_AES_256
+                    #define BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
+                #endif
+            #endif
+        #endif
+        #if defined(WOLFSSL_STATIC_RSA)
+            #if !defined (NO_SHA256) && defined(HAVE_AES_CBC)
+                #ifdef WOLFSSL_AES_128
+                    #define BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
+                #endif
+                #ifdef WOLFSSL_AES_256
+                    #define BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
+                #endif
+            #endif
+            #if defined (HAVE_AESGCM)
+                #ifdef WOLFSSL_AES_128
+                    #define BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
+                #endif
+                #if defined (WOLFSSL_SHA384) && defined(WOLFSSL_AES_256)
+                    #define BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384
+                #endif
+            #endif
+            #if defined (HAVE_AESCCM)
+                #ifdef WOLFSSL_AES_128
+                    #define BUILD_TLS_RSA_WITH_AES_128_CCM_8
+                #endif
+                #ifdef WOLFSSL_AES_256
+                    #define BUILD_TLS_RSA_WITH_AES_256_CCM_8
+                #endif
+            #endif
+        #endif
+    #endif
+
+    #if defined(HAVE_CAMELLIA) && !defined(NO_TLS) && !defined(NO_CAMELLIA_CBC)
+        #ifndef NO_RSA
+          #if defined(WOLFSSL_STATIC_RSA)
+            #if !defined(NO_SHA)
+                #define BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
+                #define BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
+            #endif
+            #ifndef NO_SHA256
+                #define BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
+                #define BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
+            #endif
+          #endif
+            #if !defined(NO_DH)
+              #if !defined(NO_SHA)
+                #define BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
+                #define BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
+              #endif
+                #ifndef NO_SHA256
+                    #define BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+                    #define BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
+                #endif
+            #endif
+        #endif
+    #endif
+
+#if defined(WOLFSSL_STATIC_PSK)
+    #if !defined(NO_PSK) && !defined(NO_AES) && !defined(NO_TLS)
+        #if !defined(NO_SHA)
+            #ifdef WOLFSSL_AES_128
+                #define BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
+            #endif
+            #ifdef WOLFSSL_AES_256
+                #define BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
+            #endif
+        #endif
+        #ifndef NO_SHA256
+            #ifdef WOLFSSL_AES_128
+                #ifdef HAVE_AES_CBC
+                    #define BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256
+                #endif
+                #ifdef HAVE_AESGCM
+                    #define BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256
+                #endif
+            #endif /* WOLFSSL_AES_128 */
+            #ifdef HAVE_AESCCM
+                #ifdef WOLFSSL_AES_128
+                    #define BUILD_TLS_PSK_WITH_AES_128_CCM_8
+                    #define BUILD_TLS_PSK_WITH_AES_128_CCM
+                #endif
+                #ifdef WOLFSSL_AES_256
+                    #define BUILD_TLS_PSK_WITH_AES_256_CCM_8
+                    #define BUILD_TLS_PSK_WITH_AES_256_CCM
+                #endif
+            #endif
+        #endif
+        #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256)
+            #ifdef HAVE_AES_CBC
+                #define BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384
+            #endif
+            #ifdef HAVE_AESGCM
+                #define BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384
+            #endif
+        #endif
+    #endif
+#endif
+
+    #if !defined(NO_TLS) && defined(HAVE_NULL_CIPHER)
+        #if !defined(NO_RSA)
+            #if defined(WOLFSSL_STATIC_RSA)
+                #ifndef NO_MD5
+                    #define BUILD_TLS_RSA_WITH_NULL_MD5
+                #endif
+                #if !defined(NO_SHA)
+                    #define BUILD_TLS_RSA_WITH_NULL_SHA
+                #endif
+                #ifndef NO_SHA256
+                    #define BUILD_TLS_RSA_WITH_NULL_SHA256
+                #endif
+            #endif
+        #endif
+        #if !defined(NO_PSK) && defined(WOLFSSL_STATIC_PSK)
+            #if !defined(NO_SHA)
+                #define BUILD_TLS_PSK_WITH_NULL_SHA
+            #endif
+            #ifndef NO_SHA256
+                #define BUILD_TLS_PSK_WITH_NULL_SHA256
+            #endif
+            #ifdef WOLFSSL_SHA384
+                #define BUILD_TLS_PSK_WITH_NULL_SHA384
+            #endif
+        #endif
+    #endif
+
+#if defined(WOLFSSL_STATIC_RSA)
+    #if !defined(NO_HC128) && !defined(NO_RSA) && !defined(NO_TLS)
+        #ifndef NO_MD5
+            #define BUILD_TLS_RSA_WITH_HC_128_MD5
+        #endif
+        #if !defined(NO_SHA)
+            #define BUILD_TLS_RSA_WITH_HC_128_SHA
+        #endif
+    #endif
+
+    #if !defined(NO_RABBIT) && !defined(NO_TLS) && !defined(NO_RSA)
+        #if !defined(NO_SHA)
+            #define BUILD_TLS_RSA_WITH_RABBIT_SHA
+        #endif
+    #endif
+#endif
+
+    #if !defined(NO_DH) && !defined(NO_AES) && !defined(NO_TLS) && \
+        !defined(NO_RSA)
+
+        #if !defined(NO_SHA)
+            #if defined(WOLFSSL_AES_128) && defined(HAVE_AES_CBC)
+                #define BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+            #endif
+            #if defined(WOLFSSL_AES_256) && defined(HAVE_AES_CBC)
+                #define BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+            #endif
+            #if !defined(NO_DES3)
+                #define BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+            #endif
+        #endif
+        #if !defined(NO_SHA256) && defined(HAVE_AES_CBC)
+            #ifdef WOLFSSL_AES_128
+                #define BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+            #endif
+            #ifdef WOLFSSL_AES_256
+                #define BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+            #endif
+        #endif
+    #endif
+
+    #if defined(HAVE_ANON) && !defined(NO_TLS) && !defined(NO_DH) && \
+        !defined(NO_AES) && !defined(NO_SHA) && defined(WOLFSSL_AES_128)
+        #ifdef HAVE_AES_CBC
+            #define BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA
+        #endif
+
+        #if defined(WOLFSSL_SHA384) && defined(HAVE_AESGCM)
+            #define BUILD_TLS_DH_anon_WITH_AES_256_GCM_SHA384
+        #endif
+    #endif
+
+    #if !defined(NO_DH) && !defined(NO_PSK) && !defined(NO_TLS)
+        #ifndef NO_SHA256
+            #if !defined(NO_AES) && defined(WOLFSSL_AES_128) && \
+                                                           defined(HAVE_AES_CBC)
+                #define BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
+            #endif
+            #ifdef HAVE_NULL_CIPHER
+                #define BUILD_TLS_DHE_PSK_WITH_NULL_SHA256
+            #endif
+        #endif
+        #ifdef WOLFSSL_SHA384
+            #if !defined(NO_AES) && defined(WOLFSSL_AES_256) && \
+                                                           defined(HAVE_AES_CBC)
+                #define BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
+            #endif
+            #ifdef HAVE_NULL_CIPHER
+                #define BUILD_TLS_DHE_PSK_WITH_NULL_SHA384
+            #endif
+        #endif
+    #endif
+
+    #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                     defined(HAVE_CURVE448)) && !defined(NO_TLS)
+        #if !defined(NO_AES)
+            #if !defined(NO_SHA) && defined(HAVE_AES_CBC)
+                #if !defined(NO_RSA)
+                    #ifdef WOLFSSL_AES_128
+                        #define BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+                    #endif
+                    #ifdef WOLFSSL_AES_256
+                        #define BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+                    #endif
+                    #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
+                        #ifdef WOLFSSL_AES_128
+                            #define BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
+                        #endif
+                        #ifdef WOLFSSL_AES_256
+                            #define BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+                        #endif
+                    #endif
+                #endif
+
+                #if defined(HAVE_ECC) || \
+                        (defined(HAVE_CURVE25519) && defined(HAVE_ED25519)) || \
+                        (defined(HAVE_CURVE448) && defined(HAVE_ED448))
+                    #ifdef WOLFSSL_AES_128
+                        #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+                    #endif
+                    #ifdef WOLFSSL_AES_256
+                        #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+                    #endif
+                #endif
+
+                #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
+                    #ifdef WOLFSSL_AES_128
+                        #define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+                    #endif
+                    #ifdef WOLFSSL_AES_256
+                        #define BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+                    #endif
+                #endif
+            #endif /* NO_SHA */
+            #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128) && \
+                                                           defined(HAVE_AES_CBC)
+                #if !defined(NO_RSA)
+                    #define BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+                    #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
+                        #define BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
+                    #endif
+                #endif
+                #if defined(HAVE_ECC) || \
+                        (defined(HAVE_CURVE25519) && defined(HAVE_ED25519)) || \
+                        (defined(HAVE_CURVE448) && defined(HAVE_ED448))
+                    #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
+                #endif
+                #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
+                    #define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
+                #endif
+            #endif
+
+            #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256) && \
+                                                           defined(HAVE_AES_CBC)
+                #if !defined(NO_RSA)
+                    #define BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
+                    #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
+                        #define BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
+                    #endif
+                #endif
+                #if defined(HAVE_ECC) || \
+                        (defined(HAVE_CURVE25519) && defined(HAVE_ED25519)) || \
+                        (defined(HAVE_CURVE448) && defined(HAVE_ED448))
+                    #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
+                #endif
+                #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
+                    #define BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
+                #endif
+            #endif
+
+            #if defined (HAVE_AESGCM)
+                #if !defined(NO_RSA)
+                    #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
+                        #ifdef WOLFSSL_AES_128
+                            #define BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+                        #endif
+                    #endif
+                    #if defined(WOLFSSL_SHA384)
+                        #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
+                            #ifdef WOLFSSL_AES_256
+                                #define BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
+                            #endif
+                        #endif
+                    #endif
+                #endif
+
+                #if defined(WOLFSSL_STATIC_DH) && defined(WOLFSSL_AES_128) && \
+                                                               defined(HAVE_ECC)
+                    #define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+                #endif
+
+                #if defined(WOLFSSL_SHA384)
+                    #if defined(WOLFSSL_STATIC_DH) && \
+                                   defined(WOLFSSL_AES_256) && defined(HAVE_ECC)
+                        #define BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
+                    #endif
+                #endif
+            #endif
+        #endif /* NO_AES */
+        #if !defined(NO_RC4)
+            #if !defined(NO_SHA)
+                #if !defined(NO_RSA)
+                    #ifndef WOLFSSL_AEAD_ONLY
+                        #define BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
+                    #endif
+                    #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
+                        #define BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA
+                    #endif
+                #endif
+
+                #if defined(HAVE_ECC) || \
+                        (defined(HAVE_CURVE25519) && defined(HAVE_ED25519)) || \
+                        (defined(HAVE_CURVE448) && defined(HAVE_ED448))
+                    #ifndef WOLFSSL_AEAD_ONLY
+                        #define BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+                    #endif
+                #endif
+                #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
+                    #define BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
+                #endif
+            #endif
+        #endif
+        #if !defined(NO_DES3)
+            #ifndef NO_SHA
+                #if !defined(NO_RSA)
+                    #define BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+                    #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
+                        #define BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+                    #endif
+                #endif
+
+                #if defined(HAVE_ECC) || \
+                        (defined(HAVE_CURVE25519) && defined(HAVE_ED25519)) || \
+                        (defined(HAVE_CURVE448) && defined(HAVE_ED448))
+                    #define BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+                #endif
+                #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
+                    #define BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+                #endif
+            #endif /* NO_SHA */
+        #endif
+        #if defined(HAVE_NULL_CIPHER)
+            #if !defined(NO_SHA)
+                #if defined(HAVE_ECC) || \
+                        (defined(HAVE_CURVE25519) && defined(HAVE_ED25519)) || \
+                        (defined(HAVE_CURVE448) && defined(HAVE_ED448))
+                    #define BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA
+                #endif
+            #endif
+            #if !defined(NO_PSK) && !defined(NO_SHA256)
+                #define BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256
+            #endif
+        #endif
+        #if !defined(NO_PSK) && !defined(NO_SHA256) && !defined(NO_AES) && \
+            defined(WOLFSSL_AES_128) && defined(HAVE_AES_CBC)
+            #define BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
+        #endif
+    #endif
+    #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && !defined(NO_SHA256)
+        #if !defined(NO_OLD_POLY1305)
+        #if defined(HAVE_ECC) || \
+                        (defined(HAVE_CURVE25519) && defined(HAVE_ED25519)) || \
+                        (defined(HAVE_CURVE448) && defined(HAVE_ED448))
+            #define BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+        #endif
+        #if !defined(NO_RSA) && defined(HAVE_ECC)
+            #define BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+        #endif
+        #if !defined(NO_DH) && !defined(NO_RSA)
+            #define BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+        #endif
+        #endif /* NO_OLD_POLY1305 */
+        #if !defined(NO_PSK)
+            #define BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256
+            #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+                                                             defined(HAVE_ED448)
+                #define BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256
+            #endif
+            #ifndef NO_DH
+                #define BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256
+            #endif
+        #endif /* !NO_PSK */
+    #endif
+
+#endif /* !WOLFSSL_MAX_STRENGTH */
+
+#if !defined(NO_DH) && !defined(NO_AES) && !defined(NO_TLS) && \
+    !defined(NO_RSA) && defined(HAVE_AESGCM)
+
+    #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128)
+        #define BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
+    #endif
+
+    #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256)
+        #define BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+    #endif
+#endif
+
+#if !defined(NO_DH) && !defined(NO_PSK) && !defined(NO_TLS)
+    #ifndef NO_SHA256
+        #if defined(HAVE_AESGCM) && defined(WOLFSSL_AES_128)
+            #define BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
+        #endif
+        #ifdef HAVE_AESCCM
+            #ifdef WOLFSSL_AES_128
+                #define BUILD_TLS_DHE_PSK_WITH_AES_128_CCM
+            #endif
+            #ifdef WOLFSSL_AES_256
+                #define BUILD_TLS_DHE_PSK_WITH_AES_256_CCM
+            #endif
+        #endif
+    #endif
+    #if defined(WOLFSSL_SHA384) && defined(HAVE_AESGCM) && \
+        defined(WOLFSSL_AES_256)
+        #define BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
+    #endif
+#endif
+
+#if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)) \
+                                         && !defined(NO_TLS) && !defined(NO_AES)
+    #ifdef HAVE_AESGCM
+        #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128)
+            #if defined(HAVE_ECC) || \
+                        (defined(HAVE_CURVE25519) && defined(HAVE_ED25519)) || \
+                        (defined(HAVE_CURVE448) && defined(HAVE_ED448))
+                #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+            #endif
+            #ifndef NO_RSA
+                #define BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+            #endif
+        #endif
+        #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256)
+            #if defined(HAVE_ECC) || \
+                        (defined(HAVE_CURVE25519) && defined(HAVE_ED25519)) || \
+                        (defined(HAVE_CURVE448) && defined(HAVE_ED448))
+                #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+            #endif
+            #ifndef NO_RSA
+                #define BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+            #endif
+        #endif
+    #endif
+    #if defined(HAVE_AESCCM) && !defined(NO_SHA256)
+        #if defined(HAVE_ECC) || \
+                        (defined(HAVE_CURVE25519) && defined(HAVE_ED25519)) || \
+                        (defined(HAVE_CURVE448) && defined(HAVE_ED448))
+            #ifdef WOLFSSL_AES_128
+                #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM
+                #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
+            #endif
+            #ifdef WOLFSSL_AES_256
+                #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8
+            #endif
+        #endif
+    #endif
+#endif
+
+#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && !defined(NO_SHA256)
+    #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
+        #if defined(HAVE_ECC) || \
+                        (defined(HAVE_CURVE25519) && defined(HAVE_ED25519)) || \
+                        (defined(HAVE_CURVE448) && defined(HAVE_ED448))
+            #define BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
+        #endif
+        #ifndef NO_RSA
+            #define BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+        #endif
+    #endif
+    #if !defined(NO_DH) && !defined(NO_RSA)
+        #define BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+    #endif
+#endif
+
+#endif
+
+#if defined(WOLFSSL_TLS13)
+    #ifdef HAVE_AESGCM
+        #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128)
+            #define BUILD_TLS_AES_128_GCM_SHA256
+        #endif
+        #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256)
+            #define BUILD_TLS_AES_256_GCM_SHA384
+        #endif
+    #endif
+
+    #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
+        #ifndef NO_SHA256
+            #define BUILD_TLS_CHACHA20_POLY1305_SHA256
+        #endif
+    #endif
+
+    #ifdef HAVE_AESCCM
+        #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128)
+            #define BUILD_TLS_AES_128_CCM_SHA256
+            #define BUILD_TLS_AES_128_CCM_8_SHA256
+        #endif
+    #endif
+    #ifdef HAVE_NULL_CIPHER
+        #ifndef NO_SHA256
+            #define BUILD_TLS_SHA256_SHA256
+        #endif
+        #ifdef WOLFSSL_SHA384
+            #define BUILD_TLS_SHA384_SHA384
+        #endif
+    #endif
+#endif
+
+#ifdef WOLFSSL_MULTICAST
+    #if defined(HAVE_NULL_CIPHER) && !defined(NO_SHA256)
+        #define BUILD_WDM_WITH_NULL_SHA256
+    #endif
+#endif
+
+#if defined(BUILD_SSL_RSA_WITH_RC4_128_SHA) || \
+    defined(BUILD_SSL_RSA_WITH_RC4_128_MD5)
+    #define BUILD_ARC4
+#endif
+
+#if defined(BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA)
+    #define BUILD_DES3
+#endif
+
+#if defined(BUILD_TLS_RSA_WITH_AES_128_CBC_SHA) || \
+    defined(BUILD_TLS_RSA_WITH_AES_256_CBC_SHA) || \
+    defined(BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) || \
+    defined(BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256)
+    #undef  BUILD_AES
+    #define BUILD_AES
+#endif
+
+#if defined(BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256) || \
+    defined(BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) || \
+    defined(BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) || \
+    defined(BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256) || \
+    defined(BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256) || \
+    defined(BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384) || \
+    defined(BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384) || \
+    defined(BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) || \
+    defined(BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384) || \
+    defined(BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384) || \
+    defined(BUILD_TLS_AES_128_GCM_SHA256) || \
+    defined(BUILD_TLS_AES_256_GCM_SHA384)
+    #define BUILD_AESGCM
+#else
+    /* No AES-GCM cipher suites available with build */
+    #define NO_AESGCM_AEAD
+#endif
+
+#if defined(BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256) || \
+    defined(BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256) || \
+    defined(BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256) || \
+    defined(BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256) || \
+    defined(BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256) || \
+    defined(BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256) || \
+    defined(BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256) || \
+    defined(BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256) || \
+    defined(BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256) || \
+    defined(BUILD_TLS_CHACHA20_POLY1305_SHA256)
+    /* Have an available ChaCha Poly cipher suite */
+#else
+    /* No ChaCha Poly cipher suites available with build */
+    #define NO_CHAPOL_AEAD
+#endif
+
+#if defined(BUILD_TLS_RSA_WITH_HC_128_SHA) || \
+    defined(BUILD_TLS_RSA_WITH_HC_128_MD5)
+    #define BUILD_HC128
+#endif
+
+#if defined(BUILD_TLS_RSA_WITH_RABBIT_SHA)
+    #define BUILD_RABBIT
+#endif
+
+#ifdef NO_DES3
+    #define DES_BLOCK_SIZE 8
+#else
+    #undef  BUILD_DES3
+    #define BUILD_DES3
+#endif
+
+#if defined(NO_AES) || defined(NO_AES_DECRYPT)
+    #define AES_BLOCK_SIZE 16
+    #undef  BUILD_AES
+#else
+    #undef  BUILD_AES
+    #define BUILD_AES
+#endif
+
+#ifndef NO_RC4
+    #undef  BUILD_ARC4
+    #define BUILD_ARC4
+#endif
+
+#ifdef HAVE_CHACHA
+    #define CHACHA20_BLOCK_SIZE 16
+#endif
+
+#if defined(WOLFSSL_MAX_STRENGTH) || \
+    (defined(HAVE_AESGCM) && !defined(NO_AESGCM_AEAD)) || \
+     defined(HAVE_AESCCM) || \
+    (defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && \
+     !defined(NO_CHAPOL_AEAD)) || \
+    (defined(WOLFSSL_TLS13) && defined(HAVE_NULL_CIPHER))
+
+    #define HAVE_AEAD
+#endif
+
+#if defined(WOLFSSL_MAX_STRENGTH) || \
+    defined(HAVE_ECC) || !defined(NO_DH)
+
+    #define HAVE_PFS
+#endif
+
+#if defined(BUILD_SSL_RSA_WITH_IDEA_CBC_SHA)
+    #define BUILD_IDEA
+#endif
+
+/* actual cipher values, 2nd byte */
+enum {
+    TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x16,
+    TLS_DHE_RSA_WITH_AES_256_CBC_SHA  = 0x39,
+    TLS_DHE_RSA_WITH_AES_128_CBC_SHA  = 0x33,
+    TLS_DH_anon_WITH_AES_128_CBC_SHA  = 0x34,
+    TLS_RSA_WITH_AES_256_CBC_SHA      = 0x35,
+    TLS_RSA_WITH_AES_128_CBC_SHA      = 0x2F,
+    TLS_RSA_WITH_NULL_MD5             = 0x01,
+    TLS_RSA_WITH_NULL_SHA             = 0x02,
+    TLS_PSK_WITH_AES_256_CBC_SHA      = 0x8d,
+    TLS_PSK_WITH_AES_128_CBC_SHA256   = 0xae,
+    TLS_PSK_WITH_AES_256_CBC_SHA384   = 0xaf,
+    TLS_PSK_WITH_AES_128_CBC_SHA      = 0x8c,
+    TLS_PSK_WITH_NULL_SHA256          = 0xb0,
+    TLS_PSK_WITH_NULL_SHA384          = 0xb1,
+    TLS_PSK_WITH_NULL_SHA             = 0x2c,
+    SSL_RSA_WITH_RC4_128_SHA          = 0x05,
+    SSL_RSA_WITH_RC4_128_MD5          = 0x04,
+    SSL_RSA_WITH_3DES_EDE_CBC_SHA     = 0x0A,
+    SSL_RSA_WITH_IDEA_CBC_SHA         = 0x07,
+
+    /* ECC suites, first byte is 0xC0 (ECC_BYTE) */
+    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA    = 0x14,
+    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA    = 0x13,
+    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA  = 0x0A,
+    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA  = 0x09,
+    TLS_ECDHE_RSA_WITH_RC4_128_SHA        = 0x11,
+    TLS_ECDHE_ECDSA_WITH_RC4_128_SHA      = 0x07,
+    TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA   = 0x12,
+    TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0x08,
+    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256   = 0x27,
+    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0x23,
+    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384   = 0x28,
+    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0x24,
+    TLS_ECDHE_ECDSA_WITH_NULL_SHA           = 0x06,
+    TLS_ECDHE_PSK_WITH_NULL_SHA256          = 0x3a,
+    TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256   = 0x37,
+
+    /* static ECDH, first byte is 0xC0 (ECC_BYTE) */
+    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA    = 0x0F,
+    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA    = 0x0E,
+    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA  = 0x05,
+    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA  = 0x04,
+    TLS_ECDH_RSA_WITH_RC4_128_SHA        = 0x0C,
+    TLS_ECDH_ECDSA_WITH_RC4_128_SHA      = 0x02,
+    TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA   = 0x0D,
+    TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 0x03,
+    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256   = 0x29,
+    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 = 0x25,
+    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384   = 0x2A,
+    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 = 0x26,
+
+    /* wolfSSL extension - eSTREAM */
+    TLS_RSA_WITH_HC_128_MD5       = 0xFB,
+    TLS_RSA_WITH_HC_128_SHA       = 0xFC,
+    TLS_RSA_WITH_RABBIT_SHA       = 0xFD,
+    WDM_WITH_NULL_SHA256          = 0xFE, /* wolfSSL DTLS Multicast */
+
+    /* wolfSSL extension - NTRU */
+    TLS_NTRU_RSA_WITH_RC4_128_SHA      = 0xe5,
+    TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA = 0xe6,
+    TLS_NTRU_RSA_WITH_AES_128_CBC_SHA  = 0xe7,  /* clashes w/official SHA-256 */
+    TLS_NTRU_RSA_WITH_AES_256_CBC_SHA  = 0xe8,
+
+    /* wolfSSL extension - NTRU , Quantum-safe Handshake
+       first byte is 0xD0 (QSH_BYTE) */
+    TLS_QSH      = 0x01,
+
+    /* SHA256 */
+    TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x6b,
+    TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x67,
+    TLS_RSA_WITH_AES_256_CBC_SHA256     = 0x3d,
+    TLS_RSA_WITH_AES_128_CBC_SHA256     = 0x3c,
+    TLS_RSA_WITH_NULL_SHA256            = 0x3b,
+    TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 = 0xb2,
+    TLS_DHE_PSK_WITH_NULL_SHA256        = 0xb4,
+
+    /* SHA384 */
+    TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 = 0xb3,
+    TLS_DHE_PSK_WITH_NULL_SHA384        = 0xb5,
+
+    /* AES-GCM */
+    TLS_RSA_WITH_AES_128_GCM_SHA256          = 0x9c,
+    TLS_RSA_WITH_AES_256_GCM_SHA384          = 0x9d,
+    TLS_DHE_RSA_WITH_AES_128_GCM_SHA256      = 0x9e,
+    TLS_DHE_RSA_WITH_AES_256_GCM_SHA384      = 0x9f,
+    TLS_DH_anon_WITH_AES_256_GCM_SHA384      = 0xa7,
+    TLS_PSK_WITH_AES_128_GCM_SHA256          = 0xa8,
+    TLS_PSK_WITH_AES_256_GCM_SHA384          = 0xa9,
+    TLS_DHE_PSK_WITH_AES_128_GCM_SHA256      = 0xaa,
+    TLS_DHE_PSK_WITH_AES_256_GCM_SHA384      = 0xab,
+
+    /* ECC AES-GCM, first byte is 0xC0 (ECC_BYTE) */
+    TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256  = 0x2b,
+    TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384  = 0x2c,
+    TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256   = 0x2d,
+    TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384   = 0x2e,
+    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256    = 0x2f,
+    TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384    = 0x30,
+    TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256     = 0x31,
+    TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384     = 0x32,
+
+    /* AES-CCM, first byte is 0xC0 but isn't ECC,
+     * also, in some of the other AES-CCM suites
+     * there will be second byte number conflicts
+     * with non-ECC AES-GCM */
+    TLS_RSA_WITH_AES_128_CCM_8         = 0xa0,
+    TLS_RSA_WITH_AES_256_CCM_8         = 0xa1,
+    TLS_ECDHE_ECDSA_WITH_AES_128_CCM   = 0xac,
+    TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 = 0xae,
+    TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 = 0xaf,
+    TLS_PSK_WITH_AES_128_CCM           = 0xa4,
+    TLS_PSK_WITH_AES_256_CCM           = 0xa5,
+    TLS_PSK_WITH_AES_128_CCM_8         = 0xa8,
+    TLS_PSK_WITH_AES_256_CCM_8         = 0xa9,
+    TLS_DHE_PSK_WITH_AES_128_CCM       = 0xa6,
+    TLS_DHE_PSK_WITH_AES_256_CCM       = 0xa7,
+
+    /* Camellia */
+    TLS_RSA_WITH_CAMELLIA_128_CBC_SHA        = 0x41,
+    TLS_RSA_WITH_CAMELLIA_256_CBC_SHA        = 0x84,
+    TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256     = 0xba,
+    TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256     = 0xc0,
+    TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA    = 0x45,
+    TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA    = 0x88,
+    TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xbe,
+    TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0xc4,
+
+    /* chacha20-poly1305 suites first byte is 0xCC (CHACHA_BYTE) */
+    TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256   = 0xa8,
+    TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xa9,
+    TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256     = 0xaa,
+    TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256   = 0xac,
+    TLS_PSK_WITH_CHACHA20_POLY1305_SHA256         = 0xab,
+    TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256     = 0xad,
+
+    /* chacha20-poly1305 earlier version of nonce and padding (CHACHA_BYTE) */
+    TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256   = 0x13,
+    TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 = 0x14,
+    TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256     = 0x15,
+
+    /* TLS v1.3 cipher suites */
+    TLS_AES_128_GCM_SHA256       = 0x01,
+    TLS_AES_256_GCM_SHA384       = 0x02,
+    TLS_CHACHA20_POLY1305_SHA256 = 0x03,
+    TLS_AES_128_CCM_SHA256       = 0x04,
+    TLS_AES_128_CCM_8_SHA256     = 0x05,
+
+    /* TLS v1.3 Integity only cipher suites - 0xC0 (ECC) first byte */
+    TLS_SHA256_SHA256            = 0xB4,
+    TLS_SHA384_SHA384            = 0xB5,
+
+    /* Fallback SCSV (Signaling Cipher Suite Value) */
+    TLS_FALLBACK_SCSV                        = 0x56,
+    /* Renegotiation Indication Extension Special Suite */
+    TLS_EMPTY_RENEGOTIATION_INFO_SCSV        = 0xff
+};
+
+
+#ifndef WOLFSSL_SESSION_TIMEOUT
+    #define WOLFSSL_SESSION_TIMEOUT 500
+    /* default session resumption cache timeout in seconds */
+#endif
+
+
+#ifndef WOLFSSL_DTLS_WINDOW_WORDS
+    #define WOLFSSL_DTLS_WINDOW_WORDS 2
+#endif /* WOLFSSL_DTLS_WINDOW_WORDS */
+#define DTLS_WORD_BITS (sizeof(word32) * CHAR_BIT)
+#define DTLS_SEQ_BITS  (WOLFSSL_DTLS_WINDOW_WORDS * DTLS_WORD_BITS)
+#define DTLS_SEQ_SZ    (sizeof(word32) * WOLFSSL_DTLS_WINDOW_WORDS)
+
+#ifndef WOLFSSL_MULTICAST
+    #define WOLFSSL_DTLS_PEERSEQ_SZ 1
+#else
+    #ifndef WOLFSSL_MULTICAST_PEERS
+        /* max allowed multicast group peers */
+        #define WOLFSSL_MULTICAST_PEERS 100
+    #endif
+    #define WOLFSSL_DTLS_PEERSEQ_SZ WOLFSSL_MULTICAST_PEERS
+#endif /* WOLFSSL_MULTICAST */
+
+#ifndef WOLFSSL_MAX_MTU
+    #define WOLFSSL_MAX_MTU 1500
+#endif /* WOLFSSL_MAX_MTU */
+
+
+/* set minimum DH key size allowed */
+#ifndef WOLFSSL_MIN_DHKEY_BITS
+    #ifdef WOLFSSL_MAX_STRENGTH
+        #define WOLFSSL_MIN_DHKEY_BITS 2048
+    #else
+        #define WOLFSSL_MIN_DHKEY_BITS 1024
+    #endif
+#endif
+#if (WOLFSSL_MIN_DHKEY_BITS % 8)
+    #error DH minimum bit size must be multiple of 8
+#endif
+#if (WOLFSSL_MIN_DHKEY_BITS > 16000)
+    #error DH minimum bit size must not be greater than 16000
+#endif
+#define MIN_DHKEY_SZ (WOLFSSL_MIN_DHKEY_BITS / 8)
+/* set maximum DH key size allowed */
+#ifndef WOLFSSL_MAX_DHKEY_BITS
+    #if (defined(USE_FAST_MATH) && defined(FP_MAX_BITS) && FP_MAX_BITS >= 16384)
+        #define WOLFSSL_MAX_DHKEY_BITS 8192
+    #else
+        #define WOLFSSL_MAX_DHKEY_BITS 4096
+    #endif
+#endif
+#if (WOLFSSL_MAX_DHKEY_BITS % 8)
+    #error DH maximum bit size must be multiple of 8
+#endif
+#if (WOLFSSL_MAX_DHKEY_BITS > 16000)
+    #error DH maximum bit size must not be greater than 16000
+#endif
+#define MAX_DHKEY_SZ (WOLFSSL_MAX_DHKEY_BITS / 8)
+
+#ifndef MAX_PSK_ID_LEN
+    /* max psk identity/hint supported */
+    #if defined(WOLFSSL_TLS13)
+        #define MAX_PSK_ID_LEN 256
+    #else
+        #define MAX_PSK_ID_LEN 128
+    #endif
+#endif
+
+#ifndef MAX_EARLY_DATA_SZ
+    /* maximum early data size */
+    #define MAX_EARLY_DATA_SZ  4096
+#endif
+
+enum Misc {
+    CIPHER_BYTE = 0x00,            /* Default ciphers */
+    ECC_BYTE    = 0xC0,            /* ECC first cipher suite byte */
+    QSH_BYTE    = 0xD0,            /* Quantum-safe Handshake cipher suite */
+    CHACHA_BYTE = 0xCC,            /* ChaCha first cipher suite */
+    TLS13_BYTE  = 0x13,            /* TLS v1.3 first byte of cipher suite */
+
+    SEND_CERT       = 1,
+    SEND_BLANK_CERT = 2,
+
+    DTLS_MAJOR      = 0xfe,     /* DTLS major version number */
+    DTLS_MINOR      = 0xff,     /* DTLS minor version number */
+    DTLSv1_2_MINOR  = 0xfd,     /* DTLS minor version number */
+    SSLv3_MAJOR     = 3,        /* SSLv3 and TLSv1+  major version number */
+    SSLv3_MINOR     = 0,        /* TLSv1   minor version number */
+    TLSv1_MINOR     = 1,        /* TLSv1   minor version number */
+    TLSv1_1_MINOR   = 2,        /* TLSv1_1 minor version number */
+    TLSv1_2_MINOR   = 3,        /* TLSv1_2 minor version number */
+    TLSv1_3_MINOR   = 4,        /* TLSv1_3 minor version number */
+    TLS_DRAFT_MAJOR = 0x7f,     /* Draft TLS major version number */
+#ifdef WOLFSSL_TLS13_DRAFT
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    TLS_DRAFT_MINOR = 0x12,     /* Minor version number of TLS draft */
+#elif defined(WOLFSSL_TLS13_DRAFT_22)
+    TLS_DRAFT_MINOR = 0x16,     /* Minor version number of TLS draft */
+#elif defined(WOLFSSL_TLS13_DRAFT_23)
+    TLS_DRAFT_MINOR = 0x17,     /* Minor version number of TLS draft */
+#elif defined(WOLFSSL_TLS13_DRAFT_26)
+    TLS_DRAFT_MINOR = 0x1a,     /* Minor version number of TLS draft */
+#else
+    TLS_DRAFT_MINOR = 0x1c,     /* Minor version number of TLS draft */
+#endif
+#endif
+    OLD_HELLO_ID    = 0x01,     /* SSLv2 Client Hello Indicator */
+    INVALID_BYTE    = 0xff,     /* Used to initialize cipher specs values */
+    NO_COMPRESSION  =  0,
+    ZLIB_COMPRESSION = 221,     /* wolfSSL zlib compression */
+    HELLO_EXT_SIG_ALGO = 13,    /* ID for the sig_algo hello extension */
+    HELLO_EXT_EXTMS = 0x0017,   /* ID for the extended master secret ext */
+    SECRET_LEN      = WOLFSSL_MAX_MASTER_KEY_LENGTH,
+                                /* pre RSA and all master */
+#if defined(WOLFSSL_MYSQL_COMPATIBLE) || \
+    (defined(USE_FAST_MATH) && defined(FP_MAX_BITS) && FP_MAX_BITS > 8192)
+#ifndef NO_PSK
+    ENCRYPT_LEN     = 1024 + MAX_PSK_ID_LEN + 2,   /* 8192 bit static buffer */
+#else
+    ENCRYPT_LEN     = 1024,     /* allow 8192 bit static buffer */
+#endif
+#else
+#ifndef NO_PSK
+    ENCRYPT_LEN     = 512 + MAX_PSK_ID_LEN + 2,    /* 4096 bit static buffer */
+#else
+    ENCRYPT_LEN     = 512,      /* allow 4096 bit static buffer */
+#endif
+#endif
+    SIZEOF_SENDER   =  4,       /* clnt or srvr           */
+    FINISHED_SZ     = 36,       /* WC_MD5_DIGEST_SIZE + WC_SHA_DIGEST_SIZE */
+    MAX_RECORD_SIZE = 16384,    /* 2^14, max size by standard */
+    MAX_PLAINTEXT_SZ   = (1 << 14),        /* Max plaintext sz   */
+    MAX_TLS_CIPHER_SZ  = (1 << 14) + 2048, /* Max TLS encrypted data sz */
+#ifdef WOLFSSL_TLS13
+    MAX_TLS13_PLAIN_SZ = (1 << 14) + 1,    /* Max unencrypted data sz */
+    MAX_TLS13_ENC_SZ   = (1 << 14) + 256,  /* Max encrypted data sz   */
+#endif
+    MAX_MSG_EXTRA   = 38 + WC_MAX_DIGEST_SIZE,
+                                /* max added to msg, mac + pad  from */
+                                /* RECORD_HEADER_SZ + BLOCK_SZ (pad) + Max
+                                   digest sz + BLOC_SZ (iv) + pad byte (1) */
+    MAX_COMP_EXTRA  = 1024,     /* max compression extra */
+    MAX_MTU         = WOLFSSL_MAX_MTU,     /* max expected MTU */
+    MAX_UDP_SIZE    = 8192 - 100, /* was MAX_MTU - 100 */
+    MAX_DH_SZ       = (MAX_DHKEY_SZ * 3) + 12, /* DH_P, DH_G and DH_Pub */
+                                /* 4096 p, pub, g + 2 byte size for each */
+    MAX_STR_VERSION = 8,        /* string rep of protocol version */
+
+    PAD_MD5        = 48,       /* pad length for finished */
+    PAD_SHA        = 40,       /* pad length for finished */
+    MAX_PAD_SIZE   = 256,      /* maximum length of padding */
+
+    LENGTH_SZ      =  2,       /* length field for HMAC, data only */
+    VERSION_SZ     =  2,       /* length of proctocol version */
+    SEQ_SZ         =  8,       /* 64 bit sequence number  */
+    ALERT_SIZE     =  2,       /* level + description     */
+    VERIFY_HEADER  =  2,       /* always use 2 bytes      */
+    EXTS_SZ        =  2,       /* always use 2 bytes      */
+    EXT_ID_SZ      =  2,       /* always use 2 bytes      */
+    MAX_DH_SIZE    = MAX_DHKEY_SZ+1,
+                               /* Max size plus possible leading 0 */
+    NAMED_DH_MASK  = 0x100,    /* Named group mask for DH parameters  */
+    MIN_FFHDE_GROUP = 0x100,   /* Named group minimum for FFDHE parameters  */
+    MAX_FFHDE_GROUP = 0x1FF,   /* Named group maximum for FFDHE parameters  */
+    SESSION_HINT_SZ = 4,       /* session timeout hint */
+    SESSION_ADD_SZ = 4,        /* session age add */
+    TICKET_NONCE_LEN_SZ = 1,   /* Ticket nonce length size */
+    DEF_TICKET_NONCE_SZ = 1,   /* Default ticket nonce size */
+    MAX_TICKET_NONCE_SZ = 8,   /* maximum ticket nonce size */
+    MAX_LIFETIME   = 604800,   /* maximum ticket lifetime */
+
+    RAN_LEN      = 32,         /* random length           */
+    SEED_LEN     = RAN_LEN * 2, /* tls prf seed length    */
+    ID_LEN       = 32,         /* session id length       */
+    COOKIE_SECRET_SZ = 14,     /* dtls cookie secret size */
+    MAX_COOKIE_LEN = 32,       /* max dtls cookie size    */
+    COOKIE_SZ    = 20,         /* use a 20 byte cookie    */
+    SUITE_LEN    =  2,         /* cipher suite sz length  */
+    ENUM_LEN     =  1,         /* always a byte           */
+    OPAQUE8_LEN  =  1,         /* 1 byte                  */
+    OPAQUE16_LEN =  2,         /* 2 bytes                 */
+    OPAQUE24_LEN =  3,         /* 3 bytes                 */
+    OPAQUE32_LEN =  4,         /* 4 bytes                 */
+    OPAQUE64_LEN =  8,         /* 8 bytes                 */
+    COMP_LEN     =  1,         /* compression length      */
+    CURVE_LEN    =  2,         /* ecc named curve length  */
+    KE_GROUP_LEN =  2,         /* key exchange group length */
+    SERVER_ID_LEN = 20,        /* server session id length  */
+
+    HANDSHAKE_HEADER_SZ   = 4,  /* type + length(3)        */
+    RECORD_HEADER_SZ      = 5,  /* type + version + len(2) */
+    CERT_HEADER_SZ        = 3,  /* always 3 bytes          */
+    REQ_HEADER_SZ         = 2,  /* cert request header sz  */
+    HINT_LEN_SZ           = 2,  /* length of hint size field */
+    TRUNCATED_HMAC_SZ     = 10, /* length of hmac w/ truncated hmac extension */
+    HELLO_EXT_SZ          = 4,  /* base length of a hello extension */
+    HELLO_EXT_TYPE_SZ     = 2,  /* length of a hello extension type */
+    HELLO_EXT_SZ_SZ       = 2,  /* length of a hello extension size */
+    HELLO_EXT_SIGALGO_SZ  = 2,  /* length of number of items in sigalgo list */
+
+    DTLS_HANDSHAKE_HEADER_SZ = 12, /* normal + seq(2) + offset(3) + length(3) */
+    DTLS_RECORD_HEADER_SZ    = 13, /* normal + epoch(2) + seq_num(6) */
+    DTLS_HANDSHAKE_EXTRA     = 8,  /* diff from normal */
+    DTLS_RECORD_EXTRA        = 8,  /* diff from normal */
+    DTLS_HANDSHAKE_SEQ_SZ    = 2,  /* handshake header sequence number */
+    DTLS_HANDSHAKE_FRAG_SZ   = 3,  /* fragment offset and length are 24 bit */
+    DTLS_POOL_SZ             = 255,/* allowed number of list items in TX pool */
+    DTLS_EXPORT_PRO          = 165,/* wolfSSL protocol for serialized session */
+    DTLS_EXPORT_STATE_PRO    = 166,/* wolfSSL protocol for serialized state */
+    DTLS_EXPORT_VERSION      = 4,  /* wolfSSL version for serialized session */
+    DTLS_EXPORT_OPT_SZ       = 60, /* amount of bytes used from Options */
+    DTLS_EXPORT_VERSION_3    = 3,  /* wolfSSL version before TLS 1.3 addition */
+    DTLS_EXPORT_OPT_SZ_3     = 59, /* amount of bytes used from Options */
+    DTLS_EXPORT_KEY_SZ       = 325 + (DTLS_SEQ_SZ * 2),
+                                   /* max amount of bytes used from Keys */
+    DTLS_EXPORT_MIN_KEY_SZ   = 85 + (DTLS_SEQ_SZ * 2),
+                                   /* min amount of bytes used from Keys */
+    DTLS_EXPORT_SPC_SZ       = 16, /* amount of bytes used from CipherSpecs */
+    DTLS_EXPORT_LEN          = 2,  /* 2 bytes for length and protocol */
+    DTLS_EXPORT_IP           = 46, /* max ip size IPv4 mapped IPv6 */
+    MAX_EXPORT_BUFFER        = 514, /* max size of buffer for exporting */
+    MAX_EXPORT_STATE_BUFFER  = (DTLS_EXPORT_MIN_KEY_SZ) + (3 * DTLS_EXPORT_LEN),
+                                    /* max size of buffer for exporting state */
+    FINISHED_LABEL_SZ   = 15,  /* TLS finished label size */
+    TLS_FINISHED_SZ     = 12,  /* TLS has a shorter size  */
+    EXT_MASTER_LABEL_SZ = 22,  /* TLS extended master secret label sz */
+    MASTER_LABEL_SZ     = 13,  /* TLS master secret label sz */
+    KEY_LABEL_SZ        = 13,  /* TLS key block expansion sz */
+    PROTOCOL_LABEL_SZ   = 9,   /* Length of the protocol label */
+    MAX_LABEL_SZ        = 34,  /* Maximum length of a label */
+    MAX_HKDF_LABEL_SZ   = OPAQUE16_LEN +
+                          OPAQUE8_LEN + PROTOCOL_LABEL_SZ + MAX_LABEL_SZ +
+                          OPAQUE8_LEN + WC_MAX_DIGEST_SIZE,
+    MAX_REQUEST_SZ      = 256, /* Maximum cert req len (no auth yet */
+    SESSION_FLUSH_COUNT = 256, /* Flush session cache unless user turns off */
+    TLS_MAX_PAD_SZ      = 255, /* Max padding in TLS */
+
+#if defined(HAVE_FIPS) && \
+    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
+    MAX_SYM_KEY_SIZE    = AES_256_KEY_SIZE,
+#else
+    MAX_SYM_KEY_SIZE    = WC_MAX_SYM_KEY_SIZE,
+#endif
+
+#ifdef HAVE_SELFTEST
+    #ifndef WOLFSSL_AES_KEY_SIZE_ENUM
+    #define WOLFSSL_AES_KEY_SIZE_ENUM
+    AES_IV_SIZE         = 16,
+    AES_128_KEY_SIZE    = 16,
+    AES_192_KEY_SIZE    = 24,
+    AES_256_KEY_SIZE    = 32,
+    #endif
+#endif
+
+    MAX_IV_SZ           = AES_BLOCK_SIZE,
+
+    AEAD_SEQ_OFFSET     = 4,   /* Auth Data: Sequence number */
+    AEAD_TYPE_OFFSET    = 8,   /* Auth Data: Type            */
+    AEAD_VMAJ_OFFSET    = 9,   /* Auth Data: Major Version   */
+    AEAD_VMIN_OFFSET    = 10,  /* Auth Data: Minor Version   */
+    AEAD_LEN_OFFSET     = 11,  /* Auth Data: Length          */
+    AEAD_AUTH_DATA_SZ   = 13,  /* Size of the data to authenticate */
+    AEAD_NONCE_SZ       = 12,
+    AESGCM_IMP_IV_SZ    = 4,   /* Size of GCM/CCM AEAD implicit IV */
+    AESGCM_EXP_IV_SZ    = 8,   /* Size of GCM/CCM AEAD explicit IV */
+    AESGCM_NONCE_SZ     = AESGCM_EXP_IV_SZ + AESGCM_IMP_IV_SZ,
+
+    CHACHA20_IMP_IV_SZ  = 12,  /* Size of ChaCha20 AEAD implicit IV */
+    CHACHA20_NONCE_SZ   = 12,  /* Size of ChacCha20 nonce           */
+    CHACHA20_OLD_OFFSET = 4,   /* Offset for seq # in old poly1305  */
+
+    /* For any new implicit/explicit IV size adjust AEAD_MAX_***_SZ */
+
+    AES_GCM_AUTH_SZ     = 16, /* AES-GCM Auth Tag length    */
+    AES_CCM_16_AUTH_SZ  = 16, /* AES-CCM-16 Auth Tag length */
+    AES_CCM_8_AUTH_SZ   = 8,  /* AES-CCM-8 Auth Tag Length  */
+    AESCCM_NONCE_SZ     = 12,
+
+    CAMELLIA_128_KEY_SIZE = 16, /* for 128 bit */
+    CAMELLIA_192_KEY_SIZE = 24, /* for 192 bit */
+    CAMELLIA_256_KEY_SIZE = 32, /* for 256 bit */
+    CAMELLIA_IV_SIZE      = 16, /* always block size */
+
+    CHACHA20_256_KEY_SIZE = 32,  /* for 256 bit             */
+    CHACHA20_128_KEY_SIZE = 16,  /* for 128 bit             */
+    CHACHA20_IV_SIZE      = 12,  /* 96 bits for iv          */
+
+    POLY1305_AUTH_SZ    = 16,  /* 128 bits                */
+
+    HMAC_NONCE_SZ       = 12,  /* Size of HMAC nonce */
+
+    HC_128_KEY_SIZE     = 16,  /* 128 bits                */
+    HC_128_IV_SIZE      = 16,  /* also 128 bits           */
+
+    RABBIT_KEY_SIZE     = 16,  /* 128 bits                */
+    RABBIT_IV_SIZE      =  8,  /* 64 bits for iv          */
+
+    EVP_SALT_SIZE       =  8,  /* evp salt size 64 bits   */
+
+#ifndef ECDHE_SIZE /* allow this to be overridden at compile-time */
+    ECDHE_SIZE          = 32,  /* ECHDE server size defaults to 256 bit */
+#endif
+    MAX_EXPORT_ECC_SZ   = 256, /* Export ANS X9.62 max future size */
+    MAX_CURVE_NAME_SZ   = 16,  /* Maximum size of curve name string */
+
+    NEW_SA_MAJOR        = 8,   /* Most significant byte used with new sig algos */
+    ED25519_SA_MAJOR    = 8,   /* Most significant byte for ED25519 */
+    ED25519_SA_MINOR    = 7,   /* Least significant byte for ED25519 */
+    ED448_SA_MAJOR      = 8,   /* Most significant byte for ED448 */
+    ED448_SA_MINOR      = 8,   /* Least significant byte for ED448 */
+
+    MIN_RSA_SHA512_PSS_BITS = 512 * 2 + 8 * 8, /* Min key size */
+    MIN_RSA_SHA384_PSS_BITS = 384 * 2 + 8 * 8, /* Min key size */
+
+#ifndef NO_RSA
+    MAX_CERT_VERIFY_SZ = 4096 / 8, /* max RSA - default 4096-bits */
+#elif defined(HAVE_ECC)
+    MAX_CERT_VERIFY_SZ = ECC_MAX_SIG_SIZE, /* max ECC  */
+#elif defined(HAVE_ED448)
+    MAX_CERT_VERIFY_SZ = ED448_SIG_SIZE,   /* max Ed448  */
+#elif defined(HAVE_ED25519)
+    MAX_CERT_VERIFY_SZ = ED25519_SIG_SIZE, /* max Ed25519  */
+#else
+    MAX_CERT_VERIFY_SZ = 1024, /* max default  */
+#endif
+    CLIENT_HELLO_FIRST =  35,  /* Protocol + RAN_LEN + sizeof(id_len) */
+    MAX_SUITE_NAME     =  48,  /* maximum length of cipher suite string */
+
+    DTLS_TIMEOUT_INIT       =  1, /* default timeout init for DTLS receive  */
+    DTLS_TIMEOUT_MAX        = 64, /* default max timeout for DTLS receive */
+    DTLS_TIMEOUT_MULTIPLIER =  2, /* default timeout multiplier for DTLS recv */
+
+    NULL_TERM_LEN      =   1,  /* length of null '\0' termination character */
+    MAX_PSK_KEY_LEN    =  64,  /* max psk key supported */
+    MIN_PSK_ID_LEN     =   6,  /* min length of identities */
+    MIN_PSK_BINDERS_LEN=  33,  /* min length of binders */
+    MAX_TICKET_AGE_SECS=  10,  /* maximum ticket age in seconds */
+
+#ifndef MAX_WOLFSSL_FILE_SIZE
+    MAX_WOLFSSL_FILE_SIZE = 1024ul * 1024ul * 4,  /* 4 mb file size alloc limit */
+#endif
+
+    MAX_X509_SIZE      = 2048, /* max static x509 buffer size */
+    CERT_MIN_SIZE      =  256, /* min PEM cert size with header/footer */
+
+    MAX_NTRU_PUB_KEY_SZ = 1027, /* NTRU max for now */
+    MAX_NTRU_ENCRYPT_SZ = 1027, /* NTRU max for now */
+    MAX_NTRU_BITS       =  256, /* max symmetric bit strength */
+    NO_SNIFF           =   0,  /* not sniffing */
+    SNIFF              =   1,  /* currently sniffing */
+
+    HASH_SIG_SIZE      =   2,  /* default SHA1 RSA */
+
+    NO_COPY            =   0,  /* should we copy static buffer for write */
+    COPY               =   1,  /* should we copy static buffer for write */
+
+    INVALID_PEER_ID    = 0xFFFF, /* Initialize value for peer ID. */
+
+    PREV_ORDER         = -1,   /* Sequence number is in previous epoch. */
+    PEER_ORDER         = 1,    /* Peer sequence number for verify. */
+    CUR_ORDER          = 0,    /* Current sequence number. */
+    WRITE_PROTO        = 1,    /* writing a protocol message */
+    READ_PROTO         = 0     /* reading a protocol message */
+};
+
+/* minimum Downgrade Minor version */
+#ifndef WOLFSSL_MIN_DOWNGRADE
+    #ifndef NO_OLD_TLS
+        #define WOLFSSL_MIN_DOWNGRADE TLSv1_MINOR
+    #else
+        #define WOLFSSL_MIN_DOWNGRADE TLSv1_2_MINOR
+    #endif
+#endif
+
+/* Set max implicit IV size for AEAD cipher suites */
+#define AEAD_MAX_IMP_SZ 12
+
+/* Set max explicit IV size for AEAD cipher suites */
+#define AEAD_MAX_EXP_SZ 8
+
+
+#ifndef WOLFSSL_MAX_SUITE_SZ
+    #define WOLFSSL_MAX_SUITE_SZ 300
+    /* 150 suites for now! */
+#endif
+
+/* number of items in the signature algo list */
+#ifndef WOLFSSL_MAX_SIGALGO
+    #define WOLFSSL_MAX_SIGALGO 32
+#endif
+
+
+/* set minimum ECC key size allowed */
+#ifndef WOLFSSL_MIN_ECC_BITS
+    #ifdef WOLFSSL_MAX_STRENGTH
+        #define WOLFSSL_MIN_ECC_BITS  256
+    #else
+        #define WOLFSSL_MIN_ECC_BITS 224
+    #endif
+#endif /* WOLFSSL_MIN_ECC_BITS */
+#if (WOLFSSL_MIN_ECC_BITS % 8)
+    /* Some ECC keys are not divisible by 8 such as prime239v1 or sect131r1.
+       In these cases round down to the nearest value divisible by 8. The
+       restriction of being divisible by 8 is in place to match wc_ecc_size
+       function from wolfSSL.
+     */
+    #error ECC minimum bit size must be a multiple of 8
+#endif
+#define MIN_ECCKEY_SZ (WOLFSSL_MIN_ECC_BITS / 8)
+
+/* set minimum RSA key size allowed */
+#ifndef WOLFSSL_MIN_RSA_BITS
+    #ifdef WOLFSSL_MAX_STRENGTH
+        #define WOLFSSL_MIN_RSA_BITS 2048
+    #else
+        #define WOLFSSL_MIN_RSA_BITS 1024
+    #endif
+#endif /* WOLFSSL_MIN_RSA_BITS */
+#if (WOLFSSL_MIN_RSA_BITS % 8)
+    /* This is to account for the example case of a min size of 2050 bits but
+       still allows 2049 bit key. So we need the measurement to be in bytes. */
+    #error RSA minimum bit size must be a multiple of 8
+#endif
+#define MIN_RSAKEY_SZ (WOLFSSL_MIN_RSA_BITS / 8)
+
+#ifdef SESSION_INDEX
+/* Shift values for making a session index */
+#define SESSIDX_ROW_SHIFT 4
+#define SESSIDX_IDX_MASK  0x0F
+#endif
+
+
+/* max cert chain peer depth */
+#ifndef MAX_CHAIN_DEPTH
+    #define MAX_CHAIN_DEPTH 9
+#endif
+
+/* max size of a certificate message payload */
+/* assumes MAX_CHAIN_DEPTH number of certificates at 2kb per certificate */
+#ifndef MAX_CERTIFICATE_SZ
+    #define MAX_CERTIFICATE_SZ \
+                CERT_HEADER_SZ + \
+                (MAX_X509_SIZE + CERT_HEADER_SZ) * MAX_CHAIN_DEPTH
+#endif
+
+/* max size of a handshake message, currently set to the certificate */
+#ifndef MAX_HANDSHAKE_SZ
+    #define MAX_HANDSHAKE_SZ MAX_CERTIFICATE_SZ
+#endif
+
+#ifndef SESSION_TICKET_LEN
+    #define SESSION_TICKET_LEN 256
+#endif
+
+#ifndef SESSION_TICKET_HINT_DEFAULT
+    #define SESSION_TICKET_HINT_DEFAULT 300
+#endif
+
+
+/* don't use extra 3/4k stack space unless need to */
+#ifdef HAVE_NTRU
+    #define MAX_ENCRYPT_SZ MAX_NTRU_ENCRYPT_SZ
+#else
+    #define MAX_ENCRYPT_SZ ENCRYPT_LEN
+#endif
+
+
+/* states */
+enum states {
+    NULL_STATE = 0,
+
+    SERVER_HELLOVERIFYREQUEST_COMPLETE,
+    SERVER_HELLO_RETRY_REQUEST_COMPLETE,
+    SERVER_HELLO_COMPLETE,
+    SERVER_ENCRYPTED_EXTENSIONS_COMPLETE,
+    SERVER_CERT_COMPLETE,
+    SERVER_KEYEXCHANGE_COMPLETE,
+    SERVER_HELLODONE_COMPLETE,
+	SERVER_CHANGECIPHERSPEC_COMPLETE,
+    SERVER_FINISHED_COMPLETE,
+
+    CLIENT_HELLO_RETRY,
+    CLIENT_HELLO_COMPLETE,
+    CLIENT_KEYEXCHANGE_COMPLETE,
+	CLIENT_CHANGECIPHERSPEC_COMPLETE,
+    CLIENT_FINISHED_COMPLETE,
+
+    HANDSHAKE_DONE
+};
+
+/* SSL Version */
+typedef struct ProtocolVersion {
+    byte major;
+    byte minor;
+} WOLFSSL_PACK ProtocolVersion;
+
+
+WOLFSSL_LOCAL ProtocolVersion MakeSSLv3(void);
+WOLFSSL_LOCAL ProtocolVersion MakeTLSv1(void);
+WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_1(void);
+WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_2(void);
+WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_3(void);
+
+#ifdef WOLFSSL_DTLS
+    WOLFSSL_LOCAL ProtocolVersion MakeDTLSv1(void);
+    WOLFSSL_LOCAL ProtocolVersion MakeDTLSv1_2(void);
+
+    #ifdef WOLFSSL_SESSION_EXPORT
+    WOLFSSL_LOCAL int wolfSSL_dtls_import_internal(WOLFSSL* ssl, byte* buf,
+                                                                     word32 sz);
+    WOLFSSL_LOCAL int wolfSSL_dtls_export_internal(WOLFSSL* ssl, byte* buf,
+                                                                     word32 sz);
+    WOLFSSL_LOCAL int wolfSSL_dtls_export_state_internal(WOLFSSL* ssl,
+                                                          byte* buf, word32 sz);
+    WOLFSSL_LOCAL int wolfSSL_dtls_import_state_internal(WOLFSSL* ssl,
+                                                          byte* buf, word32 sz);
+    WOLFSSL_LOCAL int wolfSSL_send_session(WOLFSSL* ssl);
+    #endif
+#endif
+
+
+/* wolfSSL method type */
+struct WOLFSSL_METHOD {
+    ProtocolVersion version;
+    byte            side;         /* connection side, server or client */
+    byte            downgrade;    /* whether to downgrade version, default no */
+};
+
+/* wolfSSL buffer type - internal uses "buffer" type */
+typedef WOLFSSL_BUFFER_INFO buffer;
+
+typedef struct Suites Suites;
+
+
+/* defaults to client */
+WOLFSSL_LOCAL void InitSSL_Method(WOLFSSL_METHOD*, ProtocolVersion);
+
+WOLFSSL_LOCAL int InitSSL_Suites(WOLFSSL* ssl);
+WOLFSSL_LOCAL int InitSSL_Side(WOLFSSL* ssl, word16 side);
+
+/* for sniffer */
+WOLFSSL_LOCAL int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                            word32 size, word32 totalSz, int sniff);
+WOLFSSL_LOCAL int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx);
+/* TLS v1.3 needs these */
+WOLFSSL_LOCAL int  HandleTlsResumption(WOLFSSL* ssl, int bogusID,
+                                       Suites* clSuites);
+#ifdef WOLFSSL_TLS13
+WOLFSSL_LOCAL int FindSuite(Suites* suites, byte first, byte second);
+#endif
+WOLFSSL_LOCAL int  DoClientHello(WOLFSSL* ssl, const byte* input, word32*,
+                                 word32);
+#ifdef WOLFSSL_TLS13
+WOLFSSL_LOCAL int DoTls13ClientHello(WOLFSSL* ssl, const byte* input,
+                                     word32* inOutIdx, word32 helloSz);
+#endif
+WOLFSSL_LOCAL int  DoServerHello(WOLFSSL* ssl, const byte* input, word32*,
+                                 word32);
+WOLFSSL_LOCAL int  CompleteServerHello(WOLFSSL *ssl);
+WOLFSSL_LOCAL int  CheckVersion(WOLFSSL *ssl, ProtocolVersion pv);
+WOLFSSL_LOCAL int  PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo,
+                                   word32 hashSigAlgoSz);
+WOLFSSL_LOCAL int  DecodePrivateKey(WOLFSSL *ssl, word16* length);
+#ifdef HAVE_PK_CALLBACKS
+WOLFSSL_LOCAL int GetPrivateKeySigSize(WOLFSSL* ssl);
+#ifndef NO_ASN
+    WOLFSSL_LOCAL int  InitSigPkCb(WOLFSSL* ssl, SignatureCtx* sigCtx);
+#endif
+#endif
+WOLFSSL_LOCAL void FreeKeyExchange(WOLFSSL* ssl);
+WOLFSSL_LOCAL void FreeSuites(WOLFSSL* ssl);
+WOLFSSL_LOCAL int  ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 size);
+WOLFSSL_LOCAL int  MatchDomainName(const char* pattern, int len, const char* str);
+#ifndef NO_CERTS
+WOLFSSL_LOCAL int  CheckAltNames(DecodedCert* dCert, char* domain);
+#ifdef OPENSSL_EXTRA
+WOLFSSL_LOCAL int  CheckIPAddr(DecodedCert* dCert, char* ipasc);
+#endif
+#endif
+WOLFSSL_LOCAL int  CreateTicket(WOLFSSL* ssl);
+WOLFSSL_LOCAL int  HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz);
+WOLFSSL_LOCAL int  HashOutput(WOLFSSL* ssl, const byte* output, int sz,
+                              int ivSz);
+WOLFSSL_LOCAL int  HashInput(WOLFSSL* ssl, const byte* input, int sz);
+#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+WOLFSSL_LOCAL int SNI_Callback(WOLFSSL* ssl);
+#endif
+#ifdef WOLFSSL_TLS13
+WOLFSSL_LOCAL int  DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input,
+                                word16 sz, const byte* aad, word16 aadSz);
+WOLFSSL_LOCAL int  DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input,
+                                           word32* inOutIdx, byte type,
+                                           word32 size, word32 totalSz);
+WOLFSSL_LOCAL int  DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input,
+                                       word32* inOutIdx, word32 totalSz);
+WOLFSSL_LOCAL int DoTls13ServerHello(WOLFSSL* ssl, const byte* input,
+                                     word32* inOutIdx, word32 helloSz,
+                                     byte* extMsgType);
+#endif
+int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int t,
+                    int pLen, int content);
+
+
+enum {
+    FORCED_FREE = 1,
+    NO_FORCED_FREE = 0
+};
+
+
+/* only use compression extra if using compression */
+#ifdef HAVE_LIBZ
+    #define COMP_EXTRA MAX_COMP_EXTRA
+#else
+    #define COMP_EXTRA 0
+#endif
+
+/* only the sniffer needs space in the buffer for extra MTU record(s) */
+#ifdef WOLFSSL_SNIFFER
+    #define MTU_EXTRA MAX_MTU * 3
+#else
+    #define MTU_EXTRA 0
+#endif
+
+
+/* embedded callbacks require large static buffers, make sure on */
+#ifdef WOLFSSL_CALLBACKS
+    #undef  LARGE_STATIC_BUFFERS
+    #define LARGE_STATIC_BUFFERS
+#endif
+
+
+/* give user option to use 16K static buffers */
+#if defined(LARGE_STATIC_BUFFERS)
+    #define RECORD_SIZE MAX_RECORD_SIZE
+#else
+    #ifdef WOLFSSL_DTLS
+        #define RECORD_SIZE MAX_MTU
+    #else
+        #define RECORD_SIZE 128
+    #endif
+#endif
+
+
+/* user option to turn off 16K output option */
+/* if using small static buffers (default) and SSL_write tries to write data
+   larger than the record we have, dynamically get it, unless user says only
+   write in static buffer chunks  */
+#ifndef STATIC_CHUNKS_ONLY
+    #define OUTPUT_RECORD_SIZE MAX_RECORD_SIZE
+#else
+    #define OUTPUT_RECORD_SIZE RECORD_SIZE
+#endif
+
+/* wolfSSL input buffer
+
+   RFC 2246:
+
+   length
+       The length (in bytes) of the following TLSPlaintext.fragment.
+       The length should not exceed 2^14.
+*/
+#if defined(LARGE_STATIC_BUFFERS)
+    #define STATIC_BUFFER_LEN RECORD_HEADER_SZ + RECORD_SIZE + COMP_EXTRA + \
+             MTU_EXTRA + MAX_MSG_EXTRA
+#else
+    /* don't fragment memory from the record header */
+    #define STATIC_BUFFER_LEN RECORD_HEADER_SZ
+#endif
+
+typedef struct {
+    ALIGN16 byte staticBuffer[STATIC_BUFFER_LEN];
+    byte*  buffer;       /* place holder for static or dynamic buffer */
+    word32 length;       /* total buffer length used */
+    word32 idx;          /* idx to part of length already consumed */
+    word32 bufferSize;   /* current buffer size */
+    byte   dynamicFlag;  /* dynamic memory currently in use */
+    byte   offset;       /* alignment offset attempt */
+} bufferStatic;
+
+/* Cipher Suites holder */
+struct Suites {
+    word16 suiteSz;                 /* suite length in bytes        */
+    word16 hashSigAlgoSz;           /* SigAlgo extension length in bytes */
+    byte   suites[WOLFSSL_MAX_SUITE_SZ];
+    byte   hashSigAlgo[WOLFSSL_MAX_SIGALGO]; /* sig/algo to offer */
+    byte   setSuites;               /* user set suites from default */
+    byte   hashAlgo;                /* selected hash algorithm */
+    byte   sigAlgo;                 /* selected sig algorithm */
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+    WOLF_STACK_OF(WOLFSSL_CIPHER)* stack; /* stack of available cipher suites */
+#endif
+};
+
+
+WOLFSSL_LOCAL void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig,
+                                         int haveRSAsig, int haveAnon,
+                                         int tls1_2, int keySz);
+WOLFSSL_LOCAL void InitSuites(Suites*, ProtocolVersion, int, word16, word16,
+                              word16, word16, word16, word16, word16, int);
+WOLFSSL_LOCAL int  MatchSuite(WOLFSSL* ssl, Suites* peerSuites);
+WOLFSSL_LOCAL int  SetCipherList(WOLFSSL_CTX*, Suites*, const char* list);
+
+#ifndef PSK_TYPES_DEFINED
+    typedef unsigned int (*wc_psk_client_callback)(WOLFSSL*, const char*, char*,
+                          unsigned int, unsigned char*, unsigned int);
+    typedef unsigned int (*wc_psk_server_callback)(WOLFSSL*, const char*,
+                          unsigned char*, unsigned int);
+#ifdef WOLFSSL_TLS13
+    typedef unsigned int (*wc_psk_client_tls13_callback)(WOLFSSL*, const char*,
+                          char*, unsigned int, unsigned char*, unsigned int,
+                          const char**);
+    typedef unsigned int (*wc_psk_server_tls13_callback)(WOLFSSL*, const char*,
+                          unsigned char*, unsigned int, const char**);
+#endif
+#endif /* PSK_TYPES_DEFINED */
+#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SESSION_EXPORT) && \
+   !defined(WOLFSSL_DTLS_EXPORT_TYPES)
+    typedef int (*wc_dtls_export)(WOLFSSL* ssl,
+                   unsigned char* exportBuffer, unsigned int sz, void* userCtx);
+#define WOLFSSL_DTLS_EXPORT_TYPES
+#endif /* WOLFSSL_DTLS_EXPORT_TYPES */
+
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+#define MAX_DESCRIPTION_SZ 255
+#endif
+/* wolfSSL Cipher type just points back to SSL */
+struct WOLFSSL_CIPHER {
+    byte cipherSuite0;
+    byte cipherSuite;
+    WOLFSSL* ssl;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+    char description[MAX_DESCRIPTION_SZ];
+    unsigned long offset;
+    unsigned int in_stack; /* TRUE if added to stack in wolfSSL_get_ciphers_compat */
+    int bits;
+#endif
+};
+
+
+#ifdef NO_ASN
+    /* no_asn won't have */
+    typedef struct CertStatus CertStatus;
+#endif
+
+#ifndef HAVE_OCSP
+    typedef struct WOLFSSL_OCSP WOLFSSL_OCSP;
+#endif
+
+/* wolfSSL OCSP controller */
+#ifdef HAVE_OCSP
+struct WOLFSSL_OCSP {
+    WOLFSSL_CERT_MANAGER* cm;            /* pointer back to cert manager */
+    OcspEntry*            ocspList;      /* OCSP response list */
+    wolfSSL_Mutex         ocspLock;      /* OCSP list lock */
+    int                   error;
+#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \
+    defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+    int(*statusCb)(WOLFSSL*, void*);
+#endif
+};
+#endif
+
+#ifndef MAX_DATE_SIZE
+#define MAX_DATE_SIZE 32
+#endif
+
+typedef struct CRL_Entry CRL_Entry;
+
+#ifdef NO_SHA
+    #define CRL_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
+#else
+    #define CRL_DIGEST_SIZE WC_SHA_DIGEST_SIZE
+#endif
+
+#ifdef NO_ASN
+    typedef struct RevokedCert RevokedCert;
+#endif
+
+/* Complete CRL */
+struct CRL_Entry {
+    CRL_Entry* next;                      /* next entry */
+    byte    issuerHash[CRL_DIGEST_SIZE];  /* issuer hash                 */
+    /* byte    crlHash[CRL_DIGEST_SIZE];      raw crl data hash           */
+    /* restore the hash here if needed for optimized comparisons */
+    byte    lastDate[MAX_DATE_SIZE]; /* last date updated  */
+    byte    nextDate[MAX_DATE_SIZE]; /* next update date   */
+    byte    lastDateFormat;          /* last date format */
+    byte    nextDateFormat;          /* next date format */
+    RevokedCert* certs;              /* revoked cert list  */
+    int          totalCerts;         /* number on list     */
+    int     verified;
+    byte*   toBeSigned;
+    word32  tbsSz;
+    byte*   signature;
+    word32  signatureSz;
+    word32  signatureOID;
+#if !defined(NO_SKID) && !defined(NO_ASN)
+    byte    extAuthKeyIdSet;
+    byte    extAuthKeyId[KEYID_SIZE];
+#endif
+};
+
+
+typedef struct CRL_Monitor CRL_Monitor;
+
+/* CRL directory monitor */
+struct CRL_Monitor {
+    char* path;      /* full dir path, if valid pointer we're using */
+    int   type;      /* PEM or ASN1 type */
+};
+
+
+#if defined(HAVE_CRL) && defined(NO_FILESYSTEM)
+    #undef HAVE_CRL_MONITOR
+#endif
+
+/* wolfSSL CRL controller */
+struct WOLFSSL_CRL {
+    WOLFSSL_CERT_MANAGER* cm;            /* pointer back to cert manager */
+    CRL_Entry*            crlList;       /* our CRL list */
+#ifdef HAVE_CRL_IO
+    CbCrlIO               crlIOCb;
+#endif
+    wolfSSL_Mutex         crlLock;       /* CRL list lock */
+    CRL_Monitor           monitors[2];   /* PEM and DER possible */
+#ifdef HAVE_CRL_MONITOR
+    pthread_cond_t        cond;          /* condition to signal setup */
+    pthread_t             tid;           /* monitoring thread */
+    int                   mfd;           /* monitor fd, -1 if no init yet */
+    int                   setup;         /* thread is setup predicate */
+#endif
+    void*                 heap;          /* heap hint for dynamic memory */
+};
+
+
+#ifdef NO_ASN
+    typedef struct Signer Signer;
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    typedef struct TrustedPeerCert TrustedPeerCert;
+#endif
+#endif
+
+
+#ifndef CA_TABLE_SIZE
+    #define CA_TABLE_SIZE 11
+#endif
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    #define TP_TABLE_SIZE 11
+#endif
+
+/* wolfSSL Certificate Manager */
+struct WOLFSSL_CERT_MANAGER {
+    Signer*         caTable[CA_TABLE_SIZE]; /* the CA signer table */
+    void*           heap;                /* heap helper */
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    TrustedPeerCert* tpTable[TP_TABLE_SIZE]; /* table of trusted peer certs */
+    wolfSSL_Mutex   tpLock;                  /* trusted peer list lock */
+#endif
+    WOLFSSL_CRL*    crl;                 /* CRL checker */
+    WOLFSSL_OCSP*   ocsp;                /* OCSP checker */
+#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+                               ||  defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
+    WOLFSSL_OCSP*   ocsp_stapling;       /* OCSP checker for OCSP stapling */
+#endif
+    char*           ocspOverrideURL;     /* use this responder */
+    void*           ocspIOCtx;           /* I/O callback CTX */
+#ifndef NO_WOLFSSL_CM_VERIFY
+    VerifyCallback  verifyCallback;      /* Verify callback */
+#endif
+    CallbackCACache caCacheCallback;     /* CA cache addition callback */
+    CbMissingCRL    cbMissingCRL;        /* notify through cb of missing crl */
+    CbOCSPIO        ocspIOCb;            /* I/O callback for OCSP lookup */
+    CbOCSPRespFree  ocspRespFreeCb;      /* Frees OCSP Response from IO Cb */
+    wolfSSL_Mutex   caLock;              /* CA list lock */
+    byte            crlEnabled;          /* is CRL on ? */
+    byte            crlCheckAll;         /* always leaf, but all ? */
+    byte            ocspEnabled;         /* is OCSP on ? */
+    byte            ocspCheckAll;        /* always leaf, but all ? */
+    byte            ocspSendNonce;       /* send the OCSP nonce ? */
+    byte            ocspUseOverrideURL;  /* ignore cert's responder, override */
+    byte            ocspStaplingEnabled; /* is OCSP Stapling on ? */
+
+#ifndef NO_RSA
+    short           minRsaKeySz;         /* minimum allowed RSA key size */
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
+    short           minEccKeySz;         /* minimum allowed ECC key size */
+#endif
+};
+
+WOLFSSL_LOCAL int CM_SaveCertCache(WOLFSSL_CERT_MANAGER*, const char*);
+WOLFSSL_LOCAL int CM_RestoreCertCache(WOLFSSL_CERT_MANAGER*, const char*);
+WOLFSSL_LOCAL int CM_MemSaveCertCache(WOLFSSL_CERT_MANAGER*, void*, int, int*);
+WOLFSSL_LOCAL int CM_MemRestoreCertCache(WOLFSSL_CERT_MANAGER*, const void*, int);
+WOLFSSL_LOCAL int CM_GetCertCacheMemSize(WOLFSSL_CERT_MANAGER*);
+WOLFSSL_LOCAL int CM_VerifyBuffer_ex(WOLFSSL_CERT_MANAGER* cm, const byte* buff,
+                                    long sz, int format, int err_val);
+
+
+#ifndef NO_CERTS
+#if !defined NOCERTS &&\
+    (!defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH))
+typedef struct ProcPeerCertArgs {
+    buffer*      certs;
+#ifdef WOLFSSL_TLS13
+    buffer*      exts; /* extensions */
+#endif
+    DecodedCert* dCert;
+    word32 idx;
+    word32 begin;
+    int    totalCerts; /* number of certs in certs buffer */
+    int    count;
+    int    certIdx;
+    int    lastErr;
+#ifdef WOLFSSL_TLS13
+    byte   ctxSz;
+#endif
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+    char   untrustedDepth;
+#endif
+    word16 fatal:1;
+    word16 verifyErr:1;
+    word16 dCertInit:1;
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    word16 haveTrustPeer:1; /* was cert verified by loaded trusted peer cert */
+#endif
+} ProcPeerCertArgs;
+WOLFSSL_LOCAL int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl,
+        int ret, ProcPeerCertArgs* args);
+#endif /* !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH) */
+#endif /* !defined NO_CERTS */
+
+/* wolfSSL Sock Addr */
+struct WOLFSSL_SOCKADDR {
+    unsigned int sz; /* sockaddr size */
+    void*        sa; /* pointer to the sockaddr_in or sockaddr_in6 */
+};
+
+typedef struct WOLFSSL_DTLS_CTX {
+    WOLFSSL_SOCKADDR peer;
+    int rfd;
+    int wfd;
+} WOLFSSL_DTLS_CTX;
+
+
+typedef struct WOLFSSL_DTLS_PEERSEQ {
+    word32 window[WOLFSSL_DTLS_WINDOW_WORDS];
+                        /* Sliding window for current epoch    */
+    word16 nextEpoch;   /* Expected epoch in next record       */
+    word16 nextSeq_hi;  /* Expected sequence in next record    */
+    word32 nextSeq_lo;
+
+    word32 prevWindow[WOLFSSL_DTLS_WINDOW_WORDS];
+                        /* Sliding window for old epoch        */
+    word32 prevSeq_lo;
+    word16 prevSeq_hi;  /* Next sequence in allowed old epoch  */
+
+#ifdef WOLFSSL_MULTICAST
+    word16 peerId;
+    word32 highwaterMark;
+#endif
+} WOLFSSL_DTLS_PEERSEQ;
+
+
+#define MAX_WRITE_IV_SZ 16 /* max size of client/server write_IV */
+
+/* keys and secrets
+ * keep as a constant size (no additional ifdefs) for session export */
+typedef struct Keys {
+#if !defined(WOLFSSL_AEAD_ONLY) || defined(WOLFSSL_TLS13)
+    byte client_write_MAC_secret[WC_MAX_DIGEST_SIZE];   /* max sizes */
+    byte server_write_MAC_secret[WC_MAX_DIGEST_SIZE];
+#endif
+    byte client_write_key[MAX_SYM_KEY_SIZE];         /* max sizes */
+    byte server_write_key[MAX_SYM_KEY_SIZE];
+    byte client_write_IV[MAX_WRITE_IV_SZ];               /* max sizes */
+    byte server_write_IV[MAX_WRITE_IV_SZ];
+#if defined(HAVE_AEAD) || defined(WOLFSSL_SESSION_EXPORT)
+    byte aead_exp_IV[AEAD_MAX_EXP_SZ];
+    byte aead_enc_imp_IV[AEAD_MAX_IMP_SZ];
+    byte aead_dec_imp_IV[AEAD_MAX_IMP_SZ];
+#endif
+
+    word32 peer_sequence_number_hi;
+    word32 peer_sequence_number_lo;
+    word32 sequence_number_hi;
+    word32 sequence_number_lo;
+
+#ifdef WOLFSSL_DTLS
+    word16 curEpoch;    /* Received epoch in current record    */
+    word16 curSeq_hi;   /* Received sequence in current record */
+    word32 curSeq_lo;
+#ifdef WOLFSSL_MULTICAST
+    byte   curPeerId;   /* Received peer group ID in current record */
+#endif
+    WOLFSSL_DTLS_PEERSEQ peerSeq[WOLFSSL_DTLS_PEERSEQ_SZ];
+
+    word16 dtls_peer_handshake_number;
+    word16 dtls_expected_peer_handshake_number;
+
+    word16 dtls_epoch;                          /* Current epoch    */
+    word16 dtls_sequence_number_hi;             /* Current epoch */
+    word32 dtls_sequence_number_lo;
+    word16 dtls_prev_sequence_number_hi;        /* Previous epoch */
+    word32 dtls_prev_sequence_number_lo;
+    word16 dtls_handshake_number;               /* Current tx handshake seq */
+#endif
+
+    word32 encryptSz;             /* last size of encrypted data   */
+    word32 padSz;                 /* how much to advance after decrypt part */
+    byte   encryptionOn;          /* true after change cipher spec */
+    byte   decryptedCur;          /* only decrypt current record once */
+#ifdef WOLFSSL_TLS13
+    byte   updateResponseReq:1;   /* KeyUpdate response from peer required. */
+    byte   keyUpdateRespond:1;    /* KeyUpdate is to be responded to. */
+#endif
+#ifdef WOLFSSL_RENESAS_TSIP_TLS
+    byte tsip_client_write_MAC_secret[TSIP_TLS_HMAC_KEY_INDEX_WORDSIZE];
+    byte tsip_server_write_MAC_secret[TSIP_TLS_HMAC_KEY_INDEX_WORDSIZE];
+#endif
+} Keys;
+
+
+
+/** TLS Extensions - RFC 6066 */
+#ifdef HAVE_TLS_EXTENSIONS
+
+typedef enum {
+    TLSX_SERVER_NAME                = 0x0000, /* a.k.a. SNI  */
+    TLSX_MAX_FRAGMENT_LENGTH        = 0x0001,
+    TLSX_TRUSTED_CA_KEYS            = 0x0003,
+    TLSX_TRUNCATED_HMAC             = 0x0004,
+    TLSX_STATUS_REQUEST             = 0x0005, /* a.k.a. OCSP stapling   */
+    TLSX_SUPPORTED_GROUPS           = 0x000a, /* a.k.a. Supported Curves */
+    TLSX_EC_POINT_FORMATS           = 0x000b,
+#if !defined(WOLFSSL_NO_SIGALG)
+    TLSX_SIGNATURE_ALGORITHMS       = 0x000d,
+#endif
+    TLSX_APPLICATION_LAYER_PROTOCOL = 0x0010, /* a.k.a. ALPN */
+    TLSX_STATUS_REQUEST_V2          = 0x0011, /* a.k.a. OCSP stapling v2 */
+#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+    TLSX_ENCRYPT_THEN_MAC           = 0x0016, /* RFC 7366 */
+#endif
+    TLSX_QUANTUM_SAFE_HYBRID        = 0x0018, /* a.k.a. QSH  */
+    TLSX_SESSION_TICKET             = 0x0023,
+#ifdef WOLFSSL_TLS13
+    #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+    TLSX_PRE_SHARED_KEY             = 0x0029,
+    #endif
+    #ifdef WOLFSSL_EARLY_DATA
+    TLSX_EARLY_DATA                 = 0x002a,
+    #endif
+    TLSX_SUPPORTED_VERSIONS         = 0x002b,
+    TLSX_COOKIE                     = 0x002c,
+    #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+    TLSX_PSK_KEY_EXCHANGE_MODES     = 0x002d,
+    #endif
+    #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
+    TLSX_POST_HANDSHAKE_AUTH        = 0x0031,
+    #endif
+    #if defined(WOLFSSL_TLS13_DRAFT_18) || defined(WOLFSSL_TLS13_DRAFT_22)
+    TLSX_KEY_SHARE                  = 0x0028,
+    #else
+    TLSX_SIGNATURE_ALGORITHMS_CERT  = 0x0032,
+    TLSX_KEY_SHARE                  = 0x0033,
+    #endif
+#endif
+    TLSX_RENEGOTIATION_INFO         = 0xff01
+} TLSX_Type;
+
+typedef struct TLSX {
+    TLSX_Type    type; /* Extension Type  */
+    void*        data; /* Extension Data  */
+    word32       val;  /* Extension Value */
+    byte         resp; /* IsResponse Flag */
+    struct TLSX* next; /* List Behavior   */
+} TLSX;
+
+WOLFSSL_LOCAL TLSX* TLSX_Find(TLSX* list, TLSX_Type type);
+WOLFSSL_LOCAL void  TLSX_Remove(TLSX** list, TLSX_Type type, void* heap);
+WOLFSSL_LOCAL void  TLSX_FreeAll(TLSX* list, void* heap);
+WOLFSSL_LOCAL int   TLSX_SupportExtensions(WOLFSSL* ssl);
+WOLFSSL_LOCAL int   TLSX_PopulateExtensions(WOLFSSL* ssl, byte isRequest);
+
+#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_CLIENT)
+WOLFSSL_LOCAL int   TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType,
+                                         word16* pLength);
+WOLFSSL_LOCAL int   TLSX_WriteRequest(WOLFSSL* ssl, byte* output,
+                                       byte msgType, word16* pOffset);
+#endif
+
+#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_SERVER)
+/* TLS 1.3 Certificate messages have extensions. */
+WOLFSSL_LOCAL int   TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType,
+                                          word16* pLength);
+WOLFSSL_LOCAL int   TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType,
+                                        word16* pOffset);
+#endif
+
+WOLFSSL_LOCAL int   TLSX_ParseVersion(WOLFSSL* ssl, byte* input, word16 length,
+                                      byte msgType, int* found);
+WOLFSSL_LOCAL int   TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length,
+                               byte msgType, Suites *suites);
+
+#elif defined(HAVE_SNI)                           \
+   || defined(HAVE_MAX_FRAGMENT)                  \
+   || defined(HAVE_TRUSTED_CA)                    \
+   || defined(HAVE_TRUNCATED_HMAC)                \
+   || defined(HAVE_CERTIFICATE_STATUS_REQUEST)    \
+   || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) \
+   || defined(HAVE_SUPPORTED_CURVES)              \
+   || defined(HAVE_ALPN)                          \
+   || defined(HAVE_QSH)                           \
+   || defined(HAVE_SESSION_TICKET)                \
+   || defined(HAVE_SECURE_RENEGOTIATION)          \
+   || defined(HAVE_SERVER_RENEGOTIATION_INFO)
+
+#error Using TLS extensions requires HAVE_TLS_EXTENSIONS to be defined.
+
+#endif /* HAVE_TLS_EXTENSIONS */
+
+/** Server Name Indication - RFC 6066 (session 3) */
+#ifdef HAVE_SNI
+
+typedef struct SNI {
+    byte                       type;    /* SNI Type         */
+    union { char* host_name; } data;    /* SNI Data         */
+    struct SNI*                next;    /* List Behavior    */
+    byte                       status;  /* Matching result  */
+#ifndef NO_WOLFSSL_SERVER
+    byte                       options; /* Behavior options */
+#endif
+} SNI;
+
+WOLFSSL_LOCAL int TLSX_UseSNI(TLSX** extensions, byte type, const void* data,
+                                                       word16 size, void* heap);
+WOLFSSL_LOCAL byte TLSX_SNI_Status(TLSX* extensions, byte type);
+WOLFSSL_LOCAL word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type,
+                                                                   void** data);
+
+#ifndef NO_WOLFSSL_SERVER
+WOLFSSL_LOCAL void   TLSX_SNI_SetOptions(TLSX* extensions, byte type,
+                                                                  byte options);
+WOLFSSL_LOCAL int    TLSX_SNI_GetFromBuffer(const byte* buffer, word32 bufferSz,
+                                         byte type, byte* sni, word32* inOutSz);
+#endif
+
+#endif /* HAVE_SNI */
+
+/* Trusted CA Key Indication - RFC 6066 (section 6) */
+#ifdef HAVE_TRUSTED_CA
+
+typedef struct TCA {
+    byte                       type;    /* TCA Type            */
+    byte*                      id;      /* TCA identifier      */
+    word16                     idSz;    /* TCA identifier size */
+    struct TCA*                next;    /* List Behavior       */
+} TCA;
+
+WOLFSSL_LOCAL int TLSX_UseTrustedCA(TLSX** extensions, byte type,
+                    const byte* id, word16 idSz, void* heap);
+
+#endif /* HAVE_TRUSTED_CA */
+
+/* Application-Layer Protocol Negotiation - RFC 7301 */
+#ifdef HAVE_ALPN
+typedef struct ALPN {
+    char*        protocol_name; /* ALPN protocol name */
+    struct ALPN* next;          /* List Behavior      */
+    byte         options;       /* Behavior options */
+    byte         negotiated;    /* ALPN protocol negotiated or not */
+} ALPN;
+
+WOLFSSL_LOCAL int TLSX_ALPN_GetRequest(TLSX* extensions,
+                                       void** data, word16 *dataSz);
+
+WOLFSSL_LOCAL int TLSX_UseALPN(TLSX** extensions, const void* data,
+                               word16 size, byte options, void* heap);
+
+WOLFSSL_LOCAL int TLSX_ALPN_SetOptions(TLSX** extensions, const byte option);
+
+#endif /* HAVE_ALPN */
+
+/** Maximum Fragment Length Negotiation - RFC 6066 (session 4) */
+#ifdef HAVE_MAX_FRAGMENT
+
+WOLFSSL_LOCAL int TLSX_UseMaxFragment(TLSX** extensions, byte mfl, void* heap);
+
+#endif /* HAVE_MAX_FRAGMENT */
+
+/** Truncated HMAC - RFC 6066 (session 7) */
+#ifdef HAVE_TRUNCATED_HMAC
+
+WOLFSSL_LOCAL int TLSX_UseTruncatedHMAC(TLSX** extensions, void* heap);
+
+#endif /* HAVE_TRUNCATED_HMAC */
+
+/** Certificate Status Request - RFC 6066 (session 8) */
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+
+typedef struct {
+    byte status_type;
+    byte options;
+    WOLFSSL* ssl;
+    union {
+        OcspRequest ocsp;
+    } request;
+#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)
+    buffer response;
+#endif
+} CertificateStatusRequest;
+
+WOLFSSL_LOCAL int   TLSX_UseCertificateStatusRequest(TLSX** extensions,
+           byte status_type, byte options, WOLFSSL* ssl, void* heap, int devId);
+#ifndef NO_CERTS
+WOLFSSL_LOCAL int   TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert,
+                                                                    void* heap);
+#endif
+WOLFSSL_LOCAL void* TLSX_CSR_GetRequest(TLSX* extensions);
+WOLFSSL_LOCAL int   TLSX_CSR_ForceRequest(WOLFSSL* ssl);
+
+#endif
+
+/** Certificate Status Request v2 - RFC 6961 */
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+
+typedef struct CSRIv2 {
+    byte status_type;
+    byte options;
+    word16 requests;
+    union {
+        OcspRequest ocsp[1 + MAX_CHAIN_DEPTH];
+    } request;
+    struct CSRIv2* next;
+} CertificateStatusRequestItemV2;
+
+WOLFSSL_LOCAL int   TLSX_UseCertificateStatusRequestV2(TLSX** extensions,
+                         byte status_type, byte options, void* heap, int devId);
+#ifndef NO_CERTS
+WOLFSSL_LOCAL int   TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert,
+                                                       byte isPeer, void* heap);
+#endif
+WOLFSSL_LOCAL void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type,
+                                                                    byte index);
+WOLFSSL_LOCAL int   TLSX_CSR2_ForceRequest(WOLFSSL* ssl);
+
+#endif
+
+/** Supported Elliptic Curves - RFC 4492 (session 4) */
+#ifdef HAVE_SUPPORTED_CURVES
+
+typedef struct SupportedCurve {
+    word16 name;                 /* Curve Names */
+    struct SupportedCurve* next; /* List Behavior */
+} SupportedCurve;
+
+typedef struct PointFormat {
+    byte format;                /* PointFormat */
+    struct PointFormat* next;   /* List Behavior */
+} PointFormat;
+
+WOLFSSL_LOCAL int TLSX_UseSupportedCurve(TLSX** extensions, word16 name,
+                                                                    void* heap);
+
+WOLFSSL_LOCAL int TLSX_UsePointFormat(TLSX** extensions, byte point,
+                                                                    void* heap);
+
+#ifndef NO_WOLFSSL_SERVER
+WOLFSSL_LOCAL int TLSX_ValidateSupportedCurves(WOLFSSL* ssl, byte first,
+                                                                   byte second);
+WOLFSSL_LOCAL int TLSX_SupportedCurve_CheckPriority(WOLFSSL* ssl);
+WOLFSSL_LOCAL int TLSX_SupportedFFDHE_Set(WOLFSSL* ssl);
+#endif
+WOLFSSL_LOCAL int TLSX_SupportedCurve_Preferred(WOLFSSL* ssl,
+                                                            int checkSupported);
+
+#endif /* HAVE_SUPPORTED_CURVES */
+
+/** Renegotiation Indication - RFC 5746 */
+#if defined(HAVE_SECURE_RENEGOTIATION) \
+ || defined(HAVE_SERVER_RENEGOTIATION_INFO)
+
+enum key_cache_state {
+    SCR_CACHE_NULL   = 0,       /* empty / begin state */
+    SCR_CACHE_NEEDED,           /* need to cache keys */
+    SCR_CACHE_COPY,             /* we have a cached copy */
+    SCR_CACHE_PARTIAL,          /* partial restore to real keys */
+    SCR_CACHE_COMPLETE          /* complete restore to real keys */
+};
+
+/* Additional Connection State according to rfc5746 section 3.1 */
+typedef struct SecureRenegotiation {
+   byte                 enabled;  /* secure_renegotiation flag in rfc */
+   byte                 verifySet;
+   byte                 startScr; /* server requested client to start scr */
+   enum key_cache_state cache_status;  /* track key cache state */
+   byte                 client_verify_data[TLS_FINISHED_SZ];  /* cached */
+   byte                 server_verify_data[TLS_FINISHED_SZ];  /* cached */
+   byte                 subject_hash_set; /* if peer cert hash is set */
+   byte                 subject_hash[KEYID_SIZE];  /* peer cert hash */
+   Keys                 tmp_keys;  /* can't overwrite real keys yet */
+} SecureRenegotiation;
+
+WOLFSSL_LOCAL int TLSX_UseSecureRenegotiation(TLSX** extensions, void* heap);
+
+#ifdef HAVE_SERVER_RENEGOTIATION_INFO
+WOLFSSL_LOCAL int TLSX_AddEmptyRenegotiationInfo(TLSX** extensions, void* heap);
+#endif
+
+#endif /* HAVE_SECURE_RENEGOTIATION */
+
+/** Session Ticket - RFC 5077 (session 3.2) */
+#ifdef HAVE_SESSION_TICKET
+
+typedef struct SessionTicket {
+    word32 lifetime;
+#ifdef WOLFSSL_TLS13
+    word64 seen;
+    word32 ageAdd;
+#endif
+    byte*  data;
+    word16 size;
+} SessionTicket;
+
+WOLFSSL_LOCAL int  TLSX_UseSessionTicket(TLSX** extensions,
+                                             SessionTicket* ticket, void* heap);
+WOLFSSL_LOCAL SessionTicket* TLSX_SessionTicket_Create(word32 lifetime,
+                                           byte* data, word16 size, void* heap);
+WOLFSSL_LOCAL void TLSX_SessionTicket_Free(SessionTicket* ticket, void* heap);
+
+#endif /* HAVE_SESSION_TICKET */
+
+/** Quantum-Safe-Hybrid - draft-whyte-qsh-tls12-00 */
+#ifdef HAVE_QSH
+
+typedef struct QSHScheme {
+    struct QSHScheme* next; /* List Behavior   */
+    byte*             PK;
+    word16            name; /* QSHScheme Names */
+    word16            PKLen;
+} QSHScheme;
+
+typedef struct QSHkey {
+    struct QSHKey* next;
+    word16 name;
+    buffer pub;
+    buffer pri;
+} QSHKey;
+
+typedef struct QSHSecret {
+    QSHScheme* list;
+    buffer* SerSi;
+    buffer* CliSi;
+} QSHSecret;
+
+/* used in key exchange during handshake */
+WOLFSSL_LOCAL int TLSX_QSHCipher_Parse(WOLFSSL* ssl, const byte* input,
+                                                  word16 length, byte isServer);
+WOLFSSL_LOCAL word16 TLSX_QSHPK_Write(QSHScheme* list, byte* output);
+WOLFSSL_LOCAL word16 TLSX_QSH_GetSize(QSHScheme* list, byte isRequest);
+
+/* used by api for setting a specific QSH scheme */
+WOLFSSL_LOCAL int TLSX_UseQSHScheme(TLSX** extensions, word16 name,
+                                         byte* pKey, word16 pKeySz, void* heap);
+
+/* used when parsing in QSHCipher structs */
+WOLFSSL_LOCAL int QSH_Decrypt(QSHKey* key, byte* in, word32 szIn,
+                                                      byte* out, word16* szOut);
+#ifndef NO_WOLFSSL_SERVER
+WOLFSSL_LOCAL int TLSX_ValidateQSHScheme(TLSX** extensions, word16 name);
+#endif
+
+#endif /* HAVE_QSH */
+
+#ifdef WOLFSSL_TLS13
+/* Cookie extension information - cookie data. */
+typedef struct Cookie {
+    word16 len;
+    byte   data;
+} Cookie;
+
+WOLFSSL_LOCAL int TLSX_Cookie_Use(WOLFSSL* ssl, byte* data, word16 len,
+                                  byte* mac, byte macSz, int resp);
+
+
+/* Key Share - TLS v1.3 Specification */
+
+/* The KeyShare extension information - entry in a linked list. */
+typedef struct KeyShareEntry {
+    word16                group;     /* NamedGroup               */
+    byte*                 ke;        /* Key exchange data        */
+    word32                keLen;     /* Key exchange data length */
+    void*                 key;       /* Private key              */
+    word32                keyLen;    /* Private key length       */
+    byte*                 pubKey;    /* Public key               */
+    word32                pubKeyLen; /* Public key length        */
+    struct KeyShareEntry* next;      /* List pointer             */
+} KeyShareEntry;
+
+WOLFSSL_LOCAL int TLSX_KeyShare_Use(WOLFSSL* ssl, word16 group, word16 len,
+                                    byte* data, KeyShareEntry **kse);
+WOLFSSL_LOCAL int TLSX_KeyShare_Empty(WOLFSSL* ssl);
+WOLFSSL_LOCAL int TLSX_KeyShare_Establish(WOLFSSL* ssl);
+WOLFSSL_LOCAL int TLSX_KeyShare_DeriveSecret(WOLFSSL* ssl);
+
+
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+#ifndef WOLFSSL_TLS13_DRAFT_18
+/* Ticket nonce - for deriving PSK.
+ * Length allowed to be: 1..255. Only support 4 bytes.
+ */
+typedef struct TicketNonce {
+    byte len;
+    byte data[MAX_TICKET_NONCE_SZ];
+} TicketNonce;
+#endif
+
+/* The PreSharedKey extension information - entry in a linked list. */
+typedef struct PreSharedKey {
+    word16               identityLen;             /* Length of identity */
+    byte*                identity;                /* PSK identity       */
+    word32               ticketAge;               /* Age of the ticket  */
+    byte                 cipherSuite0;            /* Cipher Suite       */
+    byte                 cipherSuite;             /* Cipher Suite       */
+    word32               binderLen;               /* Length of HMAC     */
+    byte                 binder[WC_MAX_DIGEST_SIZE]; /* HMAC of handshake */
+    byte                 hmac;                    /* HMAC algorithm     */
+    byte                 resumption:1;            /* Resumption PSK     */
+    byte                 chosen:1;                /* Server's choice    */
+    struct PreSharedKey* next;                    /* List pointer       */
+} PreSharedKey;
+
+WOLFSSL_LOCAL int TLSX_PreSharedKey_WriteBinders(PreSharedKey* list,
+                                                 byte* output, byte msgType,
+                                                 word16* pSz);
+WOLFSSL_LOCAL int TLSX_PreSharedKey_GetSizeBinders(PreSharedKey* list,
+                                                   byte msgType, word16* pSz);
+WOLFSSL_LOCAL int TLSX_PreSharedKey_Use(WOLFSSL* ssl, byte* identity,
+                                        word16 len, word32 age, byte hmac,
+                                        byte cipherSuite0, byte cipherSuite,
+                                        byte resumption,
+                                        PreSharedKey **preSharedKey);
+
+/* The possible Pre-Shared Key key exchange modes. */
+enum PskKeyExchangeMode {
+    PSK_KE,
+    PSK_DHE_KE
+};
+
+/* User can define this. */
+#ifndef WOLFSSL_DEF_PSK_CIPHER
+#define WOLFSSL_DEF_PSK_CIPHER    TLS_AES_128_GCM_SHA256
+#endif
+
+WOLFSSL_LOCAL int TLSX_PskKeModes_Use(WOLFSSL* ssl, byte modes);
+
+#ifdef WOLFSSL_EARLY_DATA
+WOLFSSL_LOCAL int TLSX_EarlyData_Use(WOLFSSL* ssl, word32 max);
+#endif
+#endif /* HAVE_SESSION_TICKET || !NO_PSK */
+
+
+/* The types of keys to derive for. */
+enum DeriveKeyType {
+    no_key,
+    early_data_key,
+    handshake_key,
+    traffic_key,
+    update_traffic_key
+};
+
+/* The key update request values for KeyUpdate message. */
+enum KeyUpdateRequest {
+    update_not_requested,
+    update_requested
+};
+#endif /* WOLFSSL_TLS13 */
+
+
+#ifdef OPENSSL_EXTRA
+enum SetCBIO {
+    WOLFSSL_CBIO_NONE = 0,
+    WOLFSSL_CBIO_RECV = 0x1,
+    WOLFSSL_CBIO_SEND = 0x2,
+};
+#endif
+
+/* wolfSSL context type */
+struct WOLFSSL_CTX {
+    WOLFSSL_METHOD* method;
+#ifdef SINGLE_THREADED
+    WC_RNG*         rng;          /* to be shared with WOLFSSL w/o locking */
+#endif
+    wolfSSL_Mutex   countMutex;   /* reference count mutex */
+    int         refCount;         /* reference count */
+    int         err;              /* error code in case of mutex not created */
+#ifndef NO_DH
+    buffer      serverDH_P;
+    buffer      serverDH_G;
+#endif
+#ifndef NO_CERTS
+    DerBuffer*  certificate;
+    DerBuffer*  certChain;
+                 /* chain after self, in DER, with leading size for each cert */
+    #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA)
+    WOLF_STACK_OF(WOLFSSL_X509_NAME)* ca_names;
+    #endif
+    #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \
+        defined(WOLFSSL_NGINX) || defined (WOLFSSL_HAPROXY)
+    WOLF_STACK_OF(WOLFSSL_X509)* x509Chain;
+    client_cert_cb CBClientCert;  /* client certificate callback */
+    #endif
+#ifdef WOLFSSL_TLS13
+    int         certChainCnt;
+#endif
+    DerBuffer*  privateKey;
+    byte        privateKeyType:7;
+    byte        privateKeyId:1;
+    int         privateKeySz;
+    int         privateKeyDevId;
+    WOLFSSL_CERT_MANAGER* cm;      /* our cert manager, ctx owns SSL will use */
+#endif
+#ifdef KEEP_OUR_CERT
+    WOLFSSL_X509*    ourCert;     /* keep alive a X509 struct of cert */
+    int              ownOurCert;  /* Dispose of certificate if we own */
+#endif
+    Suites*     suites;           /* make dynamic, user may not need/set */
+    void*       heap;             /* for user memory overrides */
+    byte        verifyDepth;
+    byte        verifyPeer:1;
+    byte        verifyNone:1;
+    byte        failNoCert:1;
+    byte        failNoCertxPSK:1; /* fail if no cert with the exception of PSK*/
+    byte        sessionCacheOff:1;
+    byte        sessionCacheFlushOff:1;
+#ifdef HAVE_EXT_CACHE
+    byte        internalCacheOff:1;
+#endif
+    byte        sendVerify:2;     /* for client side (can not be single bit) */
+    byte        haveRSA:1;        /* RSA available */
+    byte        haveECC:1;        /* ECC available */
+    byte        haveDH:1;         /* server DH parms set by user */
+    byte        haveNTRU:1;       /* server private NTRU  key loaded */
+    byte        haveECDSAsig:1;   /* server cert signed w/ ECDSA */
+    byte        haveStaticECC:1;  /* static server ECC private key */
+    byte        partialWrite:1;   /* only one msg per write call */
+    byte        quietShutdown:1;  /* don't send close notify */
+    byte        groupMessages:1;  /* group handshake messages before sending */
+    byte        minDowngrade;     /* minimum downgrade version */
+    byte        haveEMS:1;        /* have extended master secret extension */
+    byte        useClientOrder:1; /* Use client's cipher preference order */
+#ifdef WOLFSSL_TLS13
+    byte        noTicketTls13:1;  /* Server won't create new Ticket */
+    byte        noPskDheKe:1;     /* Don't use (EC)DHE with PSK */
+#endif
+    byte        mutualAuth:1;     /* Mutual authentication required */
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+    byte        postHandshakeAuth:1;  /* Post-handshake auth supported. */
+#endif
+#ifndef NO_DH
+    #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \
+        !defined(HAVE_SELFTEST)
+    byte        dhKeyTested:1;   /* Set when key has been tested. */
+    #endif
+#endif
+#ifdef HAVE_SECURE_RENEGOTIATION
+    byte        useSecureReneg:1; /* when set will set WOLFSSL objects generated to enable */
+#endif
+#ifdef HAVE_ENCRYPT_THEN_MAC
+    byte        disallowEncThenMac:1;  /* Don't do Encrypt-Then-MAC */
+#endif
+#ifdef WOLFSSL_STATIC_MEMORY
+    byte        onHeap:1; /* whether the ctx/method is put on heap hint */
+#endif
+#ifdef WOLFSSL_MULTICAST
+    byte        haveMcast;        /* multicast requested */
+    byte        mcastID;          /* multicast group ID */
+#endif
+#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS)
+    byte        dtlsSctp;         /* DTLS-over-SCTP mode */
+#endif
+#if (defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)) && \
+                                                           defined(WOLFSSL_DTLS)
+    word16      dtlsMtuSz;        /* DTLS MTU size */
+#endif
+#ifndef NO_DH
+    word16      minDhKeySz;       /* minimum DH key size */
+    word16      maxDhKeySz;       /* maximum DH key size */
+#endif
+#ifndef NO_RSA
+    short       minRsaKeySz;      /* minimum RSA key size */
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
+    short       minEccKeySz;      /* minimum ECC key size */
+#endif
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+    unsigned long     mask;             /* store SSL_OP_ flags */
+#endif
+#ifdef OPENSSL_EXTRA
+    byte              sessionCtx[ID_LEN]; /* app session context ID */
+    word32            disabledCurves;   /* curves disabled by user */
+    const unsigned char *alpn_cli_protos;/* ALPN client protocol list */
+    unsigned int         alpn_cli_protos_len;
+    byte              sessionCtxSz;
+    byte              cbioFlag;  /* WOLFSSL_CBIO_RECV/SEND: CBIORecv/Send is set */
+    CallbackInfoState* CBIS;      /* used to get info about SSL state */
+#endif
+    CallbackIORecv CBIORecv;
+    CallbackIOSend CBIOSend;
+#ifdef WOLFSSL_DTLS
+    CallbackGenCookie CBIOCookie;       /* gen cookie callback */
+#ifdef WOLFSSL_SESSION_EXPORT
+    wc_dtls_export  dtls_export;        /* export function for DTLS session */
+    CallbackGetPeer CBGetPeer;
+    CallbackSetPeer CBSetPeer;
+#endif
+#endif /* WOLFSSL_DTLS */
+    VerifyCallback  verifyCallback;     /* cert verification callback */
+#ifdef OPENSSL_ALL
+    CertVerifyCallback verifyCertCb;
+    void*              verifyCertCbArg;
+#endif /* OPENSSL_ALL */
+    word32          timeout;            /* session timeout */
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_ED448)
+    word32          ecdhCurveOID;       /* curve Ecc_Sum */
+#endif
+#ifdef HAVE_ECC
+    word16          eccTempKeySz;       /* in octets 20 - 66 */
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
+    word32          pkCurveOID;         /* curve Ecc_Sum */
+#endif
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+    byte        havePSK;                /* psk key set by user */
+    wc_psk_client_callback client_psk_cb;  /* client callback */
+    wc_psk_server_callback server_psk_cb;  /* server callback */
+#ifdef WOLFSSL_TLS13
+    wc_psk_client_tls13_callback client_psk_tls13_cb;  /* client callback */
+    wc_psk_server_tls13_callback server_psk_tls13_cb;  /* server callback */
+#endif
+    char        server_hint[MAX_PSK_ID_LEN + NULL_TERM_LEN];
+#endif /* HAVE_SESSION_TICKET || !NO_PSK */
+#ifdef WOLFSSL_TLS13
+    word16          group[WOLFSSL_MAX_GROUP_COUNT];
+    byte            numGroups;
+#endif
+#ifdef WOLFSSL_EARLY_DATA
+    word32          maxEarlyDataSz;
+#endif
+#ifdef HAVE_ANON
+    byte        haveAnon;               /* User wants to allow Anon suites */
+#endif /* HAVE_ANON */
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+    pem_password_cb* passwd_cb;
+    void*            passwd_userdata;
+#endif
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+    WOLFSSL_X509_STORE x509_store; /* points to ctx->cm */
+    WOLFSSL_X509_STORE* x509_store_pt; /* take ownership of external store */
+    byte            readAhead;
+    void*           userPRFArg; /* passed to prf callback */
+#endif
+#ifdef HAVE_EX_DATA
+    WOLFSSL_CRYPTO_EX_DATA ex_data;
+#endif
+#if defined(HAVE_ALPN) && (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY))
+    CallbackALPNSelect alpnSelect;
+    void*              alpnSelectArg;
+#endif
+#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || \
+                             defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) || \
+                             defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_OPENSSH) ))
+    CallbackSniRecv sniRecvCb;
+    void*           sniRecvCbArg;
+#endif
+#if defined(WOLFSSL_MULTICAST) && defined(WOLFSSL_DTLS)
+    CallbackMcastHighwater mcastHwCb; /* Sequence number highwater callback */
+    word32      mcastFirstSeq;    /* first trigger level */
+    word32      mcastSecondSeq;   /* second trigger level */
+    word32      mcastMaxSeq;      /* max level */
+#endif
+#ifdef HAVE_OCSP
+    WOLFSSL_OCSP      ocsp;
+#endif
+    int             devId;              /* async device id to use */
+#ifdef HAVE_TLS_EXTENSIONS
+    TLSX* extensions;                  /* RFC 6066 TLS Extensions data */
+    #ifndef NO_WOLFSSL_SERVER
+        #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+         || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+            OcspRequest* certOcspRequest;
+        #endif
+        #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+            OcspRequest* chainOcspRequest[MAX_CHAIN_DEPTH];
+        #endif
+    #endif
+    #if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER)
+        SessionTicketEncCb ticketEncCb;   /* enc/dec session ticket Cb */
+        void*              ticketEncCtx;  /* session encrypt context */
+        int                ticketHint;    /* ticket hint in seconds */
+    #endif
+    #ifdef HAVE_SUPPORTED_CURVES
+        byte userCurves;                  /* indicates user called wolfSSL_CTX_UseSupportedCurve */
+    #endif
+#endif
+#ifdef ATOMIC_USER
+    CallbackMacEncrypt    MacEncryptCb;    /* Atomic User Mac/Encrypt Cb */
+    CallbackDecryptVerify DecryptVerifyCb; /* Atomic User Decrypt/Verify Cb */
+    #ifdef HAVE_ENCRYPT_THEN_MAC
+        CallbackEncryptMac    EncryptMacCb;    /* Atomic User Mac/Enc Cb */
+        CallbackVerifyDecrypt VerifyDecryptCb; /* Atomic User Dec/Verify Cb */
+    #endif
+#endif
+#ifdef HAVE_PK_CALLBACKS
+    #ifdef HAVE_ECC
+        CallbackEccKeyGen EccKeyGenCb;  /* User EccKeyGen Callback Handler */
+        CallbackEccSign   EccSignCb;    /* User EccSign   Callback handler */
+        CallbackEccVerify EccVerifyCb;  /* User EccVerify Callback handler */
+        CallbackEccSharedSecret EccSharedSecretCb; /* User EccVerify Callback handler */
+        #ifdef HAVE_ED25519
+            /* User Ed25519Sign   Callback handler */
+            CallbackEd25519Sign   Ed25519SignCb;
+            /* User Ed25519Verify Callback handler */
+            CallbackEd25519Verify Ed25519VerifyCb;
+        #endif
+        #ifdef HAVE_CURVE25519
+            /* User X25519 KeyGen Callback Handler */
+            CallbackX25519KeyGen X25519KeyGenCb;
+            /* User X25519 SharedSecret Callback handler */
+            CallbackX25519SharedSecret X25519SharedSecretCb;
+        #endif
+        #ifdef HAVE_ED448
+            /* User Ed448Sign   Callback handler */
+            CallbackEd448Sign   Ed448SignCb;
+            /* User Ed448Verify Callback handler */
+            CallbackEd448Verify Ed448VerifyCb;
+        #endif
+        #ifdef HAVE_CURVE448
+            /* User X448 KeyGen Callback Handler */
+            CallbackX448KeyGen X448KeyGenCb;
+            /* User X448 SharedSecret Callback handler */
+            CallbackX448SharedSecret X448SharedSecretCb;
+        #endif
+    #endif /* HAVE_ECC */
+    #ifndef NO_DH
+        CallbackDhAgree DhAgreeCb;      /* User DH Agree Callback handler */
+    #endif
+    #ifndef NO_RSA
+        CallbackRsaSign   RsaSignCb;      /* User RsaSign Callback handler (priv key) */
+        CallbackRsaVerify RsaVerifyCb;    /* User RsaVerify Callback handler (pub key) */
+        CallbackRsaVerify RsaSignCheckCb; /* User VerifyRsaSign Callback handler (priv key) */
+        #ifdef WC_RSA_PSS
+            CallbackRsaPssSign   RsaPssSignCb;       /* User RsaSign (priv key) */
+            CallbackRsaPssVerify RsaPssVerifyCb;     /* User RsaVerify (pub key) */
+            CallbackRsaPssVerify RsaPssSignCheckCb; /* User VerifyRsaSign (priv key) */
+        #endif
+        CallbackRsaEnc    RsaEncCb;     /* User Rsa Public Encrypt  handler */
+        CallbackRsaDec    RsaDecCb;     /* User Rsa Private Decrypt handler */
+    #endif /* NO_RSA */
+#endif /* HAVE_PK_CALLBACKS */
+#ifdef HAVE_WOLF_EVENT
+        WOLF_EVENT_QUEUE event_queue;
+#endif /* HAVE_WOLF_EVENT */
+#ifdef HAVE_EXT_CACHE
+        WOLFSSL_SESSION*(*get_sess_cb)(WOLFSSL*, unsigned char*, int, int*);
+        int (*new_sess_cb)(WOLFSSL*, WOLFSSL_SESSION*);
+        void (*rem_sess_cb)(WOLFSSL_CTX*, WOLFSSL_SESSION*);
+#endif
+#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA256)
+        Srp*  srp;  /* TLS Secure Remote Password Protocol*/
+        byte* srp_password;
+#endif
+};
+
+WOLFSSL_LOCAL
+int InitSSL_Ctx(WOLFSSL_CTX*, WOLFSSL_METHOD*, void* heap);
+WOLFSSL_LOCAL
+void FreeSSL_Ctx(WOLFSSL_CTX*);
+WOLFSSL_LOCAL
+void SSL_CtxResourceFree(WOLFSSL_CTX*);
+
+WOLFSSL_LOCAL
+int DeriveTlsKeys(WOLFSSL* ssl);
+WOLFSSL_LOCAL
+int ProcessOldClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                          word32 inSz, word16 sz);
+
+#ifndef NO_CERTS
+    WOLFSSL_LOCAL
+    int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify);
+    WOLFSSL_LOCAL
+    int AlreadySigner(WOLFSSL_CERT_MANAGER* cm, byte* hash);
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    WOLFSSL_LOCAL
+    int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify);
+    WOLFSSL_LOCAL
+    int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, byte* hash);
+#endif
+#endif
+
+/* All cipher suite related info
+ * Keep as a constant size (no ifdefs) for session export */
+typedef struct CipherSpecs {
+    word16 key_size;
+    word16 iv_size;
+    word16 block_size;
+    word16 aead_mac_size;
+    byte bulk_cipher_algorithm;
+    byte cipher_type;               /* block, stream, or aead */
+    byte mac_algorithm;
+    byte kea;                       /* key exchange algo */
+    byte sig_algo;
+    byte hash_size;
+    byte pad_size;
+    byte static_ecdh;
+} CipherSpecs;
+
+
+void InitCipherSpecs(CipherSpecs* cs);
+
+
+/* Supported Key Exchange Protocols */
+enum KeyExchangeAlgorithm {
+    no_kea,
+    rsa_kea,
+    diffie_hellman_kea,
+    fortezza_kea,
+    psk_kea,
+    dhe_psk_kea,
+    ecdhe_psk_kea,
+    ntru_kea,
+    ecc_diffie_hellman_kea,
+    ecc_static_diffie_hellman_kea       /* for verify suite only */
+};
+
+
+/* Supported Authentication Schemes */
+enum SignatureAlgorithm {
+    anonymous_sa_algo = 0,
+    rsa_sa_algo       = 1,
+    dsa_sa_algo       = 2,
+    ecc_dsa_sa_algo   = 3,
+    rsa_pss_sa_algo   = 8,
+    ed25519_sa_algo   = 9,
+    rsa_pss_pss_algo  = 10,
+    ed448_sa_algo     = 11
+};
+
+#define PSS_RSAE_TO_PSS_PSS(macAlgo) \
+    (macAlgo + (pss_sha256 - sha256_mac))
+
+#define PSS_PSS_HASH_TO_MAC(macAlgo) \
+    (macAlgo - (pss_sha256 - sha256_mac))
+
+enum SigAlgRsaPss {
+    pss_sha256  = 0x09,
+    pss_sha384  = 0x0a,
+    pss_sha512  = 0x0b,
+};
+
+
+/* Supprted ECC Curve Types */
+enum EccCurves {
+    named_curve = 3
+};
+
+
+/* Valid client certificate request types from page 27 */
+enum ClientCertificateType {
+    rsa_sign            = 1,
+    dss_sign            = 2,
+    rsa_fixed_dh        = 3,
+    dss_fixed_dh        = 4,
+    rsa_ephemeral_dh    = 5,
+    dss_ephemeral_dh    = 6,
+    fortezza_kea_cert   = 20,
+    ecdsa_sign          = 64,
+    rsa_fixed_ecdh      = 65,
+    ecdsa_fixed_ecdh    = 66
+};
+
+
+#ifndef WOLFSSL_AEAD_ONLY
+enum CipherType { stream, block, aead };
+#else
+enum CipherType { aead };
+#endif
+
+
+#if defined(BUILD_AES) || defined(BUILD_AESGCM) || (defined(HAVE_CHACHA) && \
+                               defined(HAVE_POLY1305)) || defined(WOLFSSL_TLS13)
+    #define CIPHER_NONCE
+#endif
+
+
+/* cipher for now */
+typedef struct Ciphers {
+#ifdef BUILD_ARC4
+    Arc4*   arc4;
+#endif
+#ifdef BUILD_DES3
+    Des3*   des3;
+#endif
+#if defined(BUILD_AES) || defined(BUILD_AESGCM)
+    Aes*    aes;
+    #if (defined(BUILD_AESGCM) || defined(HAVE_AESCCM)) && \
+                                                      !defined(WOLFSSL_NO_TLS12)
+        byte* additional;
+    #endif
+#endif
+#ifdef CIPHER_NONCE
+    byte* nonce;
+#endif
+#ifdef HAVE_CAMELLIA
+    Camellia* cam;
+#endif
+#ifdef HAVE_CHACHA
+    ChaCha*   chacha;
+#endif
+#ifdef HAVE_HC128
+    HC128*  hc128;
+#endif
+#ifdef BUILD_RABBIT
+    Rabbit* rabbit;
+#endif
+#ifdef HAVE_IDEA
+    Idea* idea;
+#endif
+#if defined(WOLFSSL_TLS13) && defined(HAVE_NULL_CIPHER)
+    Hmac* hmac;
+#endif
+    byte    state;
+    byte    setup;       /* have we set it up flag for detection */
+} Ciphers;
+
+
+#ifdef HAVE_ONE_TIME_AUTH
+/* Ciphers for one time authentication such as poly1305 */
+typedef struct OneTimeAuth {
+#ifdef HAVE_POLY1305
+    Poly1305* poly1305;
+#endif
+    byte    setup;      /* flag for if a cipher has been set */
+
+} OneTimeAuth;
+#endif
+
+
+WOLFSSL_LOCAL void InitCiphers(WOLFSSL* ssl);
+WOLFSSL_LOCAL void FreeCiphers(WOLFSSL* ssl);
+
+
+/* hashes type */
+typedef struct Hashes {
+    #if !defined(NO_MD5) && !defined(NO_OLD_TLS)
+        byte md5[WC_MD5_DIGEST_SIZE];
+    #endif
+    #if !defined(NO_SHA)
+        byte sha[WC_SHA_DIGEST_SIZE];
+    #endif
+    #ifndef NO_SHA256
+        byte sha256[WC_SHA256_DIGEST_SIZE];
+    #endif
+    #ifdef WOLFSSL_SHA384
+        byte sha384[WC_SHA384_DIGEST_SIZE];
+    #endif
+    #ifdef WOLFSSL_SHA512
+        byte sha512[WC_SHA512_DIGEST_SIZE];
+    #endif
+} Hashes;
+
+WOLFSSL_LOCAL int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes);
+
+#ifdef WOLFSSL_TLS13
+typedef union Digest {
+#ifndef NO_WOLFSSL_SHA256
+    wc_Sha256 sha256;
+#endif
+#ifdef WOLFSSL_SHA384
+    wc_Sha384 sha384;
+#endif
+#ifdef WOLFSSL_SHA512
+    wc_Sha512 sha512;
+#endif
+} Digest;
+#endif
+
+/* Static x509 buffer */
+typedef struct x509_buffer {
+    int  length;                  /* actual size */
+    byte buffer[MAX_X509_SIZE];   /* max static cert size */
+} x509_buffer;
+
+
+/* wolfSSL X509_CHAIN, for no dynamic memory SESSION_CACHE */
+struct WOLFSSL_X509_CHAIN {
+    int         count;                    /* total number in chain */
+    x509_buffer certs[MAX_CHAIN_DEPTH];   /* only allow max depth 4 for now */
+};
+
+
+/* wolfSSL session type */
+struct WOLFSSL_SESSION {
+    word32             bornOn;                    /* create time in seconds   */
+    word32             timeout;                   /* timeout in seconds       */
+    byte               sessionID[ID_LEN];         /* id for protocol          */
+    byte               sessionIDSz;
+    byte               masterSecret[SECRET_LEN];  /* stored secret            */
+    word16             haveEMS;                   /* ext master secret flag   */
+#ifdef SESSION_CERTS
+#ifdef OPENSSL_EXTRA
+    WOLFSSL_X509*      peer;                      /* peer cert */
+#endif
+    WOLFSSL_X509_CHAIN chain;                     /* peer cert chain, static  */
+    #ifdef WOLFSSL_ALT_CERT_CHAINS
+    WOLFSSL_X509_CHAIN altChain;                  /* peer alt cert chain, static */
+    #endif
+#endif
+#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
+                               defined(HAVE_SESSION_TICKET))
+    ProtocolVersion    version;                   /* which version was used   */
+#endif
+#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \
+                        (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET))
+    byte               cipherSuite0;              /* first byte, normally 0   */
+    byte               cipherSuite;               /* 2nd byte, actual suite   */
+#endif
+#ifndef NO_CLIENT_CACHE
+    word16             idLen;                     /* serverID length          */
+    byte               serverID[SERVER_ID_LEN];   /* for easier client lookup */
+#endif
+#ifdef OPENSSL_EXTRA
+    byte               sessionCtxSz;              /* sessionCtx length        */
+    byte               sessionCtx[ID_LEN];        /* app specific context id  */
+#endif
+#ifdef WOLFSSL_TLS13
+    word16             namedGroup;
+#endif
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+    #ifdef WOLFSSL_TLS13
+    word32             ticketSeen;                /* Time ticket seen (ms) */
+    word32             ticketAdd;                 /* Added by client */
+        #ifndef WOLFSSL_TLS13_DRAFT_18
+    TicketNonce        ticketNonce;               /* Nonce used to derive PSK */
+        #endif
+    #endif
+    #ifdef WOLFSSL_EARLY_DATA
+    word32             maxEarlyDataSz;
+    #endif
+#endif
+#ifdef HAVE_SESSION_TICKET
+    byte*              ticket;
+    word16             ticketLen;
+    byte               staticTicket[SESSION_TICKET_LEN];
+    byte               isDynamic;
+#endif
+#ifdef HAVE_EXT_CACHE
+    byte               isAlloced;
+#endif
+#ifdef HAVE_EX_DATA
+    WOLFSSL_CRYPTO_EX_DATA ex_data;
+#endif
+};
+
+
+WOLFSSL_LOCAL
+WOLFSSL_SESSION* GetSession(WOLFSSL*, byte*, byte);
+WOLFSSL_LOCAL
+int          SetSession(WOLFSSL*, WOLFSSL_SESSION*);
+
+typedef int (*hmacfp) (WOLFSSL*, byte*, const byte*, word32, int, int, int);
+
+#ifndef NO_CLIENT_CACHE
+    WOLFSSL_SESSION* GetSessionClient(WOLFSSL*, const byte*, int);
+#endif
+
+/* client connect state for nonblocking restart */
+enum ConnectState {
+    CONNECT_BEGIN = 0,
+    CLIENT_HELLO_SENT,
+    HELLO_AGAIN,               /* HELLO_AGAIN s for DTLS case */
+    HELLO_AGAIN_REPLY,
+    FIRST_REPLY_DONE,
+    FIRST_REPLY_FIRST,
+    FIRST_REPLY_SECOND,
+    FIRST_REPLY_THIRD,
+    FIRST_REPLY_FOURTH,
+    FINISHED_DONE,
+    SECOND_REPLY_DONE
+};
+
+
+/* server accept state for nonblocking restart */
+enum AcceptState {
+    ACCEPT_BEGIN = 0,
+    ACCEPT_BEGIN_RENEG,
+    ACCEPT_CLIENT_HELLO_DONE,
+    ACCEPT_HELLO_RETRY_REQUEST_DONE,
+    ACCEPT_FIRST_REPLY_DONE,
+    SERVER_HELLO_SENT,
+    SERVER_EXTENSIONS_SENT,
+    CERT_SENT,
+    CERT_VERIFY_SENT,
+    CERT_STATUS_SENT,
+    KEY_EXCHANGE_SENT,
+    CERT_REQ_SENT,
+    SERVER_HELLO_DONE,
+    ACCEPT_SECOND_REPLY_DONE,
+    TICKET_SENT,
+    CHANGE_CIPHER_SENT,
+    ACCEPT_FINISHED_DONE,
+    ACCEPT_THIRD_REPLY_DONE
+};
+
+/* TLS 1.3 server accept state for nonblocking restart */
+enum AcceptStateTls13 {
+    TLS13_ACCEPT_BEGIN = 0,
+    TLS13_ACCEPT_BEGIN_RENEG,
+    TLS13_ACCEPT_CLIENT_HELLO_DONE,
+    TLS13_ACCEPT_HELLO_RETRY_REQUEST_DONE,
+    TLS13_ACCEPT_FIRST_REPLY_DONE,
+    TLS13_ACCEPT_SECOND_REPLY_DONE,
+    TLS13_SERVER_HELLO_SENT,
+    TLS13_ACCEPT_THIRD_REPLY_DONE,
+    TLS13_SERVER_EXTENSIONS_SENT,
+    TLS13_CERT_REQ_SENT,
+    TLS13_CERT_SENT,
+    TLS13_CERT_VERIFY_SENT,
+    TLS13_ACCEPT_FINISHED_SENT,
+    TLS13_PRE_TICKET_SENT,
+    TLS13_ACCEPT_FINISHED_DONE,
+    TLS13_TICKET_SENT
+};
+
+/* buffers for struct WOLFSSL */
+typedef struct Buffers {
+    bufferStatic    inputBuffer;
+    bufferStatic    outputBuffer;
+    buffer          domainName;            /* for client check */
+    buffer          clearOutputBuffer;
+    buffer          sig;                   /* signature data */
+    buffer          digest;                /* digest data */
+    int             prevSent;              /* previous plain text bytes sent
+                                              when got WANT_WRITE            */
+    int             plainSz;               /* plain text bytes in buffer to send
+                                              when got WANT_WRITE            */
+    byte            weOwnCert;             /* SSL own cert flag */
+    byte            weOwnCertChain;        /* SSL own cert chain flag */
+    byte            weOwnKey;              /* SSL own key  flag */
+    byte            weOwnDH;               /* SSL own dh (p,g)  flag */
+#ifndef NO_DH
+    buffer          serverDH_P;            /* WOLFSSL_CTX owns, unless we own */
+    buffer          serverDH_G;            /* WOLFSSL_CTX owns, unless we own */
+    buffer          serverDH_Pub;
+    buffer          serverDH_Priv;
+    DhKey*          serverDH_Key;
+#endif
+#ifndef NO_CERTS
+    DerBuffer*      certificate;           /* WOLFSSL_CTX owns, unless we own */
+    DerBuffer*      key;                   /* WOLFSSL_CTX owns, unless we own */
+    byte            keyType:7;             /* Type of key: RSA, ECC, Ed25519 */
+    byte            keyId:1;               /* Key data is an id not data */
+    int             keySz;                 /* Size of RSA key */
+    int             keyDevId;              /* Device Id for key */
+    DerBuffer*      certChain;             /* WOLFSSL_CTX owns, unless we own */
+                 /* chain after self, in DER, with leading size for each cert */
+#ifdef WOLFSSL_TLS13
+    int             certChainCnt;
+    DerBuffer*      certExts;
+#endif
+#endif
+#ifdef WOLFSSL_SEND_HRR_COOKIE
+    buffer          tls13CookieSecret;     /* HRR cookie secret */
+#endif
+#ifdef WOLFSSL_DTLS
+    WOLFSSL_DTLS_CTX dtlsCtx;              /* DTLS connection context */
+    #ifndef NO_WOLFSSL_SERVER
+        buffer       dtlsCookieSecret;     /* DTLS cookie secret */
+    #endif /* NO_WOLFSSL_SERVER */
+#endif
+#ifdef HAVE_PK_CALLBACKS
+    #ifdef HAVE_ECC
+        buffer peerEccDsaKey;              /* we own for Ecc Verify Callbacks */
+    #endif /* HAVE_ECC */
+    #ifdef HAVE_ED25519
+        buffer peerEd25519Key;             /* for Ed25519 Verify Callbacks */
+    #endif /* HAVE_ED25519 */
+    #ifdef HAVE_ED448
+        buffer peerEd448Key;             /* for Ed448 Verify Callbacks */
+    #endif /* HAVE_ED448 */
+    #ifndef NO_RSA
+        buffer peerRsaKey;                 /* we own for Rsa Verify Callbacks */
+    #endif /* NO_RSA */
+#endif /* HAVE_PK_CALLBACKS */
+} Buffers;
+
+/* sub-states for send/do key share (key exchange) */
+enum asyncState {
+    TLS_ASYNC_BEGIN = 0,
+    TLS_ASYNC_BUILD,
+    TLS_ASYNC_DO,
+    TLS_ASYNC_VERIFY,
+    TLS_ASYNC_FINALIZE,
+    TLS_ASYNC_END
+};
+
+/* sub-states for build message */
+enum buildMsgState {
+    BUILD_MSG_BEGIN = 0,
+    BUILD_MSG_SIZE,
+    BUILD_MSG_HASH,
+    BUILD_MSG_VERIFY_MAC,
+    BUILD_MSG_ENCRYPT,
+    BUILD_MSG_ENCRYPTED_VERIFY_MAC,
+};
+
+/* sub-states for cipher operations */
+enum cipherState {
+    CIPHER_STATE_BEGIN = 0,
+    CIPHER_STATE_DO,
+    CIPHER_STATE_END,
+};
+
+typedef struct Options {
+#ifndef NO_PSK
+    wc_psk_client_callback client_psk_cb;
+    wc_psk_server_callback server_psk_cb;
+#ifdef WOLFSSL_TLS13
+    wc_psk_client_tls13_callback client_psk_tls13_cb;  /* client callback */
+    wc_psk_server_tls13_callback server_psk_tls13_cb;  /* server callback */
+#endif
+#endif /* NO_PSK */
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+    unsigned long     mask; /* store SSL_OP_ flags */
+#endif
+
+    /* on/off or small bit flags, optimize layout */
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+    word16            havePSK:1;            /* psk key set by user */
+#endif /* HAVE_SESSION_TICKET || !NO_PSK */
+    word16            sendVerify:2;     /* false = 0, true = 1, sendBlank = 2 */
+    word16            sessionCacheOff:1;
+    word16            sessionCacheFlushOff:1;
+#ifdef HAVE_EXT_CACHE
+    word16            internalCacheOff:1;
+#endif
+    word16            side:2;             /* client, server or neither end */
+    word16            verifyPeer:1;
+    word16            verifyNone:1;
+    word16            failNoCert:1;
+    word16            failNoCertxPSK:1;   /* fail for no cert except with PSK */
+    word16            downgrade:1;        /* allow downgrade of versions */
+    word16            resuming:1;
+    word16            haveSessionId:1;    /* server may not send */
+    word16            tls:1;              /* using TLS ? */
+    word16            tls1_1:1;           /* using TLSv1.1+ ? */
+    word16            tls1_3:1;           /* using TLSv1.3+ ? */
+    word16            dtls:1;             /* using datagrams ? */
+    word16            connReset:1;        /* has the peer reset */
+    word16            isClosed:1;         /* if we consider conn closed */
+    word16            closeNotify:1;      /* we've received a close notify */
+    word16            sentNotify:1;       /* we've sent a close notify */
+    word16            usingCompression:1; /* are we using compression */
+    word16            haveRSA:1;          /* RSA available */
+    word16            haveECC:1;          /* ECC available */
+    word16            haveDH:1;           /* server DH parms set by user */
+    word16            haveNTRU:1;         /* server NTRU  private key loaded */
+    word16            haveQSH:1;          /* have QSH ability */
+    word16            haveECDSAsig:1;     /* server ECDSA signed cert */
+    word16            haveStaticECC:1;    /* static server ECC private key */
+    word16            havePeerCert:1;     /* do we have peer's cert */
+    word16            havePeerVerify:1;   /* and peer's cert verify */
+    word16            usingPSK_cipher:1;  /* are using psk as cipher */
+    word16            usingAnon_cipher:1; /* are we using an anon cipher */
+    word16            noPskDheKe:1;       /* Don't use (EC)DHE with PSK */
+    word16            sendAlertState:1;   /* nonblocking resume */
+    word16            partialWrite:1;     /* only one msg per write call */
+    word16            quietShutdown:1;    /* don't send close notify */
+    word16            certOnly:1;         /* stop once we get cert */
+    word16            groupMessages:1;    /* group handshake messages */
+    word16            saveArrays:1;       /* save array Memory for user get keys
+                                           or psk */
+    word16            weOwnRng:1;         /* will be true unless CTX owns */
+    word16            haveEMS:1;          /* using extended master secret */
+#ifdef HAVE_POLY1305
+    word16            oldPoly:1;        /* set when to use old rfc way of poly*/
+#endif
+#ifdef HAVE_ANON
+    word16            haveAnon:1;       /* User wants to allow Anon suites */
+#endif
+#ifdef HAVE_SESSION_TICKET
+    word16            createTicket:1;     /* Server to create new Ticket */
+    word16            useTicket:1;        /* Use Ticket not session cache */
+    word16            rejectTicket:1;     /* Callback rejected ticket */
+#ifdef WOLFSSL_TLS13
+    word16            noTicketTls13:1;    /* Server won't create new Ticket */
+#endif
+#endif
+#ifdef WOLFSSL_DTLS
+    word16            dtlsUseNonblock:1;  /* are we using nonblocking socket */
+    word16            dtlsHsRetain:1;     /* DTLS retaining HS data */
+    word16            haveMcast:1;        /* using multicast ? */
+#ifdef WOLFSSL_SCTP
+    word16            dtlsSctp:1;         /* DTLS-over-SCTP mode */
+#endif
+#endif
+#if defined(HAVE_TLS_EXTENSIONS) && defined(HAVE_SUPPORTED_CURVES)
+    word16            userCurves:1;       /* indicates user called wolfSSL_UseSupportedCurve */
+#endif
+    word16            keepResources:1;    /* Keep resources after handshake */
+    word16            useClientOrder:1;   /* Use client's cipher order */
+    word16            mutualAuth:1;       /* Mutual authentication is rquired */
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+    word16            postHandshakeAuth:1;/* Client send post_handshake_auth
+                                           * extension */
+#endif
+#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)
+    word16            sendCookie:1;       /* Server creates a Cookie in HRR */
+#endif
+#ifdef WOLFSSL_ALT_CERT_CHAINS
+    word16            usingAltCertChain:1;/* Alternate cert chain was used */
+#endif
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
+    word16            sentChangeCipher:1; /* Change Cipher Spec sent */
+#endif
+#if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
+               ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \
+                (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)))
+    word16            cacheMessages:1;    /* Cache messages for sign/verify */
+#endif
+#ifndef NO_DH
+    #if !defined(WOLFSSL_OLD_PRIME_CHECK) && \
+        !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
+        word16        dhDoKeyTest:1;      /* Need to do the DH Key prime test */
+        word16        dhKeyTested:1;      /* Set when key has been tested. */
+    #endif
+#endif
+#ifdef SINGLE_THREADED
+    word16            ownSuites:1;        /* if suites are malloced in ssl object */
+#endif
+#ifdef HAVE_ENCRYPT_THEN_MAC
+    word16            disallowEncThenMac:1;   /* Don't do Encrypt-Then-MAC */
+    word16            encThenMac:1;           /* Doing Encrypt-Then-MAC */
+    word16            startedETMRead:1;       /* Doing Encrypt-Then-MAC read */
+    word16            startedETMWrite:1;      /* Doing Encrypt-Then-MAC write */
+#endif
+
+    /* need full byte values for this section */
+    byte            processReply;           /* nonblocking resume */
+    byte            cipherSuite0;           /* first byte, normally 0 */
+    byte            cipherSuite;            /* second byte, actual suite */
+    byte            serverState;
+    byte            clientState;
+    byte            handShakeState;
+    byte            handShakeDone;      /* at least one handshake complete */
+    byte            minDowngrade;       /* minimum downgrade version */
+    byte            connectState;       /* nonblocking resume */
+    byte            acceptState;        /* nonblocking resume */
+    byte            asyncState;         /* sub-state for enum asyncState */
+    byte            buildMsgState;      /* sub-state for enum buildMsgState */
+    byte            alertCount;         /* detect warning dos attempt */
+#ifdef WOLFSSL_MULTICAST
+    word16          mcastID;            /* Multicast group ID */
+#endif
+#ifndef NO_DH
+    word16          minDhKeySz;         /* minimum DH key size */
+    word16          maxDhKeySz;         /* minimum DH key size */
+    word16          dhKeySz;            /* actual DH key size */
+#endif
+#ifndef NO_RSA
+    short           minRsaKeySz;      /* minimum RSA key size */
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
+    short           minEccKeySz;      /* minimum ECC key size */
+#endif
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+    byte            verifyDepth;      /* maximum verification depth */
+#endif
+#ifdef WOLFSSL_EARLY_DATA
+    word16          pskIdIndex;
+    word32          maxEarlyDataSz;
+#endif
+#ifdef WOLFSSL_TLS13
+    byte            oldMinor;          /* client preferred version < TLS 1.3 */
+#endif
+} Options;
+
+typedef struct Arrays {
+    byte*           pendingMsg;         /* defrag buffer */
+    byte*           preMasterSecret;
+    word32          preMasterSz;        /* differs for DH, actual size */
+    word32          pendingMsgSz;       /* defrag buffer size */
+    word32          pendingMsgOffset;   /* current offset into defrag buffer */
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+    word32          psk_keySz;          /* actual size */
+    char            client_identity[MAX_PSK_ID_LEN + NULL_TERM_LEN];
+    char            server_hint[MAX_PSK_ID_LEN + NULL_TERM_LEN];
+    byte            psk_key[MAX_PSK_KEY_LEN];
+#endif
+    byte            clientRandom[RAN_LEN];
+    byte            serverRandom[RAN_LEN];
+    byte            sessionID[ID_LEN];
+    byte            sessionIDSz;
+#ifdef WOLFSSL_TLS13
+    byte            secret[SECRET_LEN];
+#endif
+    byte            masterSecret[SECRET_LEN];
+#if defined(WOLFSSL_RENESAS_TSIP_TLS) && \
+   !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION)
+    byte            tsip_masterSecret[TSIP_TLS_MASTERSECRET_SIZE];
+#endif
+#ifdef WOLFSSL_DTLS
+    byte            cookie[MAX_COOKIE_LEN];
+    byte            cookieSz;
+#endif
+    byte            pendingMsgType;    /* defrag buffer message type */
+} Arrays;
+
+#ifndef ASN_NAME_MAX
+#define ASN_NAME_MAX 256
+#endif
+
+#ifndef MAX_DATE_SZ
+#define MAX_DATE_SZ 32
+#endif
+
+#define STACK_TYPE_X509               0
+#define STACK_TYPE_GEN_NAME           1
+#define STACK_TYPE_BIO                2
+#define STACK_TYPE_OBJ                3
+#define STACK_TYPE_STRING             4
+#define STACK_TYPE_CIPHER             5
+#define STACK_TYPE_ACCESS_DESCRIPTION 6
+#define STACK_TYPE_X509_EXT           7
+#define STACK_TYPE_NULL               8
+#define STACK_TYPE_X509_NAME          9
+#define STACK_TYPE_CONF_VALUE         10
+#define STACK_TYPE_X509_INFO          11
+
+struct WOLFSSL_STACK {
+    unsigned long num; /* number of nodes in stack
+                        * (safety measure for freeing and shortcut for count) */
+    #if defined(OPENSSL_ALL)
+    wolf_sk_compare_cb comp;
+    #endif
+
+    union {
+        WOLFSSL_X509*          x509;
+        WOLFSSL_X509_NAME*     name;
+        WOLFSSL_X509_INFO*     info;
+        WOLFSSL_BIO*           bio;
+        WOLFSSL_ASN1_OBJECT*   obj;
+        WOLFSSL_CIPHER         cipher;
+        WOLFSSL_ACCESS_DESCRIPTION* access;
+        WOLFSSL_X509_EXTENSION* ext;
+        WOLFSSL_CONF_VALUE*    conf;
+        void*                  generic;
+        char*                  string;
+        WOLFSSL_GENERAL_NAME*  gn;
+    } data;
+    void* heap; /* memory heap hint */
+    WOLFSSL_STACK* next;
+    byte type;     /* Identifies type of stack. */
+};
+
+struct WOLFSSL_X509_NAME {
+    char  *name;
+    int   dynamicName;
+    int   sz;
+    char  staticName[ASN_NAME_MAX];
+#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+    !defined(NO_ASN)
+    DecodedName fullName;
+    WOLFSSL_X509_NAME_ENTRY cnEntry;
+    WOLFSSL_X509_NAME_ENTRY extra[MAX_NAME_ENTRIES]; /* extra entries added */
+    WOLFSSL_X509*           x509;   /* x509 that struct belongs to */
+#endif /* OPENSSL_EXTRA */
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+    byte  raw[ASN_NAME_MAX];
+    int   rawLen;
+#endif
+};
+
+#ifndef EXTERNAL_SERIAL_SIZE
+    #define EXTERNAL_SERIAL_SIZE 32
+#endif
+
+#ifdef NO_ASN
+    typedef struct DNS_entry DNS_entry;
+#endif
+
+struct WOLFSSL_X509 {
+    int              version;
+    int              serialSz;
+#ifdef WOLFSSL_SEP
+    int              deviceTypeSz;
+    int              hwTypeSz;
+    byte             deviceType[EXTERNAL_SERIAL_SIZE];
+    byte             hwType[EXTERNAL_SERIAL_SIZE];
+    int              hwSerialNumSz;
+    byte             hwSerialNum[EXTERNAL_SERIAL_SIZE];
+#endif /* WOLFSSL_SEP */
+#if (defined(WOLFSSL_SEP) || defined(WOLFSSL_QT) || defined (OPENSSL_ALL)) && \
+    (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
+    byte             certPolicySet;
+    byte             certPolicyCrit;
+#endif /* (WOLFSSL_SEP || WOLFSSL_QT) && (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL) */
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+    WOLFSSL_STACK* ext_sk; /* Store X509_EXTENSIONS from wolfSSL_X509_get_ext */
+    WOLFSSL_STACK* ext_d2i;/* Store d2i extensions from wolfSSL_X509_get_ext_d2i */
+#endif /* WOLFSSL_QT || OPENSSL_ALL */
+#ifdef OPENSSL_EXTRA
+    WOLFSSL_ASN1_INTEGER* serialNumber; /* Stores SN from wolfSSL_X509_get_serialNumber */
+#endif
+    WOLFSSL_ASN1_TIME notBefore;
+    WOLFSSL_ASN1_TIME notAfter;
+    buffer           sig;
+    int              sigOID;
+    DNS_entry*       altNames;                       /* alt names list */
+    buffer           pubKey;
+    int              pubKeyOID;
+    DNS_entry*       altNamesNext;                   /* hint for retrieval */
+#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
+    word32       pkCurveOID;
+#endif /* HAVE_ECC */
+#ifndef NO_CERTS
+    DerBuffer*   derCert;                            /* may need  */
+#endif
+    void*            heap;                           /* heap hint */
+    byte             dynamicMemory;                  /* dynamic memory flag */
+    byte             isCa:1;
+#ifdef WOLFSSL_CERT_EXT
+    char             certPolicies[MAX_CERTPOL_NB][MAX_CERTPOL_SZ];
+    int              certPoliciesNb;
+#endif /* WOLFSSL_CERT_EXT */
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
+    wolfSSL_Mutex    refMutex;                       /* ref count mutex */
+    int              refCount;                       /* reference count */
+#endif
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+#ifdef HAVE_EX_DATA
+    WOLFSSL_CRYPTO_EX_DATA ex_data;
+#endif
+    byte*            authKeyId;
+    byte*            subjKeyId;
+    byte*            extKeyUsageSrc;
+    const byte*      CRLInfo;
+    byte*            authInfo;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+    byte*            authInfoCaIssuer;
+    int              authInfoCaIssuerSz;
+#endif
+    word32           pathLength;
+    word16           keyUsage;
+    int              CRLInfoSz;
+    int              authInfoSz;
+    word32           authKeyIdSz;
+    word32           subjKeyIdSz;
+    word32           extKeyUsageSz;
+    word32           extKeyUsageCount;
+
+    byte             CRLdistSet:1;
+    byte             CRLdistCrit:1;
+    byte             authInfoSet:1;
+    byte             authInfoCrit:1;
+    byte             keyUsageSet:1;
+    byte             keyUsageCrit:1;
+    byte             extKeyUsageCrit:1;
+    byte             subjKeyIdSet:1;
+
+    byte             subjKeyIdCrit:1;
+    byte             basicConstSet:1;
+    byte             basicConstCrit:1;
+    byte             basicConstPlSet:1;
+    byte             subjAltNameSet:1;
+    byte             subjAltNameCrit:1;
+    byte             authKeyIdSet:1;
+    byte             authKeyIdCrit:1;
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+    byte             serial[EXTERNAL_SERIAL_SIZE];
+    char             subjectCN[ASN_NAME_MAX];        /* common name short cut */
+#ifdef WOLFSSL_CERT_REQ
+    char             challengePw[CTC_NAME_SIZE]; /* for REQ certs */
+#endif
+    WOLFSSL_X509_NAME issuer;
+    WOLFSSL_X509_NAME subject;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_WPAS)
+    WOLFSSL_X509_ALGOR algor;
+    WOLFSSL_X509_PUBKEY key;
+#endif
+    byte issuerSet:1;
+};
+
+
+/* record layer header for PlainText, Compressed, and CipherText */
+typedef struct RecordLayerHeader {
+    byte            type;
+    byte            pvMajor;
+    byte            pvMinor;
+    byte            length[2];
+} RecordLayerHeader;
+
+
+/* record layer header for DTLS PlainText, Compressed, and CipherText */
+typedef struct DtlsRecordLayerHeader {
+    byte            type;
+    byte            pvMajor;
+    byte            pvMinor;
+    byte            sequence_number[8];   /* per record */
+    byte            length[2];
+} DtlsRecordLayerHeader;
+
+
+typedef struct DtlsFrag {
+    word32 begin;
+    word32 end;
+    struct DtlsFrag* next;
+} DtlsFrag;
+
+
+typedef struct DtlsMsg {
+    struct DtlsMsg* next;
+    byte*           buf;
+    byte*           msg;
+    DtlsFrag*       fragList;
+    word32          fragSz;    /* Length of fragments received */
+    word32          seq;       /* Handshake sequence number    */
+    word32          sz;        /* Length of whole message      */
+    byte            type;
+} DtlsMsg;
+
+
+#ifdef HAVE_NETX
+
+    /* NETX I/O Callback default */
+    typedef struct NetX_Ctx {
+        NX_TCP_SOCKET* nxSocket;    /* send/recv socket handle */
+        NX_PACKET*     nxPacket;    /* incoming packet handle for short reads */
+        ULONG          nxOffset;    /* offset already read from nxPacket */
+        ULONG          nxWait;      /* wait option flag */
+    } NetX_Ctx;
+
+#endif
+
+/* Handshake messages received from peer (plus change cipher */
+typedef struct MsgsReceived {
+    word16 got_hello_request:1;
+    word16 got_client_hello:2;
+    word16 got_server_hello:2;
+    word16 got_hello_verify_request:1;
+    word16 got_session_ticket:1;
+    word16 got_end_of_early_data:1;
+    word16 got_hello_retry_request:1;
+    word16 got_encrypted_extensions:1;
+    word16 got_certificate:1;
+    word16 got_certificate_status:1;
+    word16 got_server_key_exchange:1;
+    word16 got_certificate_request:1;
+    word16 got_server_hello_done:1;
+    word16 got_certificate_verify:1;
+    word16 got_client_key_exchange:1;
+    word16 got_finished:1;
+    word16 got_key_update:1;
+    word16 got_change_cipher:1;
+} MsgsReceived;
+
+
+/* Handshake hashes */
+typedef struct HS_Hashes {
+    Hashes          verifyHashes;
+    Hashes          certHashes;         /* for cert verify */
+#ifndef NO_SHA
+    wc_Sha          hashSha;            /* sha hash of handshake msgs */
+#endif
+#if !defined(NO_MD5) && !defined(NO_OLD_TLS)
+    wc_Md5          hashMd5;            /* md5 hash of handshake msgs */
+#endif
+#ifndef NO_SHA256
+    wc_Sha256       hashSha256;         /* sha256 hash of handshake msgs */
+#endif
+#ifdef WOLFSSL_SHA384
+    wc_Sha384       hashSha384;         /* sha384 hash of handshake msgs */
+#endif
+#ifdef WOLFSSL_SHA512
+    wc_Sha512       hashSha512;         /* sha512 hash of handshake msgs */
+#endif
+#if (defined(HAVE_ED25519) || defined(HAVE_ED448)) && \
+                                                !defined(WOLFSSL_NO_CLIENT_AUTH)
+    byte*           messages;           /* handshake messages */
+    int             length;             /* length of handshake messages' data */
+    int             prevLen;            /* length of messages but last */
+#endif
+} HS_Hashes;
+
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    #define MAX_ASYNC_ARGS 18
+    typedef void (*FreeArgsCb)(struct WOLFSSL* ssl, void* pArgs);
+
+    struct WOLFSSL_ASYNC {
+        WC_ASYNC_DEV* dev;
+        FreeArgsCb    freeArgs; /* function pointer to cleanup args */
+        word32        args[MAX_ASYNC_ARGS]; /* holder for current args */
+    };
+#endif
+
+#ifdef HAVE_WRITE_DUP
+
+    #define WRITE_DUP_SIDE 1
+    #define READ_DUP_SIDE 2
+
+    typedef struct WriteDup {
+        wolfSSL_Mutex   dupMutex;       /* reference count mutex */
+        int             dupCount;       /* reference count */
+        int             dupErr;         /* under dupMutex, pass to other side */
+    } WriteDup;
+
+    WOLFSSL_LOCAL void FreeWriteDup(WOLFSSL* ssl);
+    WOLFSSL_LOCAL int  NotifyWriteSide(WOLFSSL* ssl, int err);
+#endif /* HAVE_WRITE_DUP */
+
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+typedef struct CertReqCtx CertReqCtx;
+
+struct CertReqCtx {
+    CertReqCtx* next;
+    byte        len;
+    byte        ctx;
+};
+#endif
+
+#ifdef WOLFSSL_EARLY_DATA
+typedef enum EarlyDataState {
+    no_early_data,
+    early_data_ext,
+    expecting_early_data,
+    process_early_data,
+    done_early_data
+} EarlyDataState;
+#endif
+
+/* wolfSSL ssl type */
+struct WOLFSSL {
+    WOLFSSL_CTX*    ctx;
+    Suites*         suites;             /* only need during handshake */
+    Arrays*         arrays;
+#ifdef WOLFSSL_TLS13
+    byte            clientSecret[SECRET_LEN];
+    byte            serverSecret[SECRET_LEN];
+#endif
+    HS_Hashes*      hsHashes;
+    void*           IOCB_ReadCtx;
+    void*           IOCB_WriteCtx;
+    WC_RNG*         rng;
+    void*           verifyCbCtx;        /* cert verify callback user ctx*/
+    VerifyCallback  verifyCallback;     /* cert verification callback */
+    void*           heap;               /* for user overrides */
+#ifdef HAVE_WRITE_DUP
+    WriteDup*       dupWrite;           /* valid pointer indicates ON */
+             /* side that decrements dupCount to zero frees overall structure */
+    byte            dupSide;            /* write side or read side */
+#endif
+#ifdef OPENSSL_EXTRA
+    byte              cbioFlag;  /* WOLFSSL_CBIO_RECV/SEND: CBIORecv/Send is set */
+#endif
+    CallbackIORecv  CBIORecv;
+    CallbackIOSend  CBIOSend;
+#ifdef WOLFSSL_STATIC_MEMORY
+    WOLFSSL_HEAP_HINT heap_hint;
+#endif
+#ifndef NO_HANDSHAKE_DONE_CB
+    HandShakeDoneCb hsDoneCb;          /*  notify user handshake done */
+    void*           hsDoneCtx;         /*  user handshake cb context  */
+#endif
+#ifdef WOLFSSL_ASYNC_CRYPT
+    struct WOLFSSL_ASYNC async;
+#elif defined(WOLFSSL_NONBLOCK_OCSP)
+    void*           nonblockarg;        /* dynamic arg for handling non-block resume */
+#endif
+    void*           hsKey;              /* Handshake key (RsaKey or ecc_key) allocated from heap */
+    word32          hsType;             /* Type of Handshake key (hsKey) */
+    WOLFSSL_CIPHER  cipher;
+#ifndef WOLFSSL_AEAD_ONLY
+    hmacfp          hmac;
+#endif
+    Ciphers         encrypt;
+    Ciphers         decrypt;
+    Buffers         buffers;
+    WOLFSSL_SESSION session;
+#ifdef HAVE_EXT_CACHE
+    WOLFSSL_SESSION* extSession;
+#endif
+    WOLFSSL_ALERT_HISTORY alert_history;
+    int             error;
+    int             rfd;                /* read  file descriptor */
+    int             wfd;                /* write file descriptor */
+    int             rflags;             /* user read  flags */
+    int             wflags;             /* user write flags */
+    word32          timeout;            /* session timeout */
+    word32          fragOffset;         /* fragment offset */
+    word16          curSize;
+    byte            verifyDepth;
+    RecordLayerHeader curRL;
+    MsgsReceived    msgsReceived;       /* peer messages received */
+    ProtocolVersion version;            /* negotiated version */
+    ProtocolVersion chVersion;          /* client hello version */
+    CipherSpecs     specs;
+    Keys            keys;
+    Options         options;
+#ifdef OPENSSL_EXTRA
+    CallbackInfoState* CBIS;             /* used to get info about SSL state */
+    int              cbmode;             /* read or write on info callback */
+    int              cbtype;             /* event type in info callback */
+    WOLFSSL_BIO*     biord;              /* socket bio read  to free/close */
+    WOLFSSL_BIO*     biowr;              /* socket bio write to free/close */
+    byte             sessionCtx[ID_LEN]; /* app session context ID */
+    WOLFSSL_X509_VERIFY_PARAM* param;    /* verification parameters*/
+#endif
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+    unsigned long    peerVerifyRet;
+#endif
+#ifdef OPENSSL_EXTRA
+    byte             readAhead;
+    byte             sessionCtxSz;       /* size of sessionCtx stored */
+#ifdef HAVE_PK_CALLBACKS
+    void*            loggingCtx;         /* logging callback argument */
+#endif
+#endif /* OPENSSL_EXTRA */
+#ifndef NO_RSA
+    RsaKey*         peerRsaKey;
+#ifdef WOLFSSL_RENESAS_TSIP_TLS
+    byte            *peerTsipEncRsaKeyIndex;
+#endif
+    byte            peerRsaKeyPresent;
+#endif
+#ifdef HAVE_QSH
+    QSHKey*         QSH_Key;
+    QSHKey*         peerQSHKey;
+    QSHSecret*      QSH_secret;
+    byte            isQSH;             /* is the handshake a QSH? */
+    byte            sendQSHKeys;       /* flag for if the client should sen
+                                          public keys */
+    byte            peerQSHKeyPresent;
+    byte            minRequest;
+    byte            maxRequest;
+    byte            user_set_QSHSchemes;
+#endif
+#if defined(WOLFSSL_TLS13) || defined(HAVE_FFDHE)
+    word16          namedGroup;
+#endif
+#ifdef WOLFSSL_TLS13
+    word16          group[WOLFSSL_MAX_GROUP_COUNT];
+    byte            numGroups;
+#endif
+    word16          pssAlgo;
+#ifdef WOLFSSL_TLS13
+    #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22)
+    word16          certHashSigAlgoSz;  /* SigAlgoCert ext length in bytes */
+    byte            certHashSigAlgo[WOLFSSL_MAX_SIGALGO]; /* cert sig/algo to
+                                                           * offer */
+    #endif /* !WOLFSSL_TLS13_DRAFT_18 && !WOLFSSL_TLS13_DRAFT_22 */
+#endif
+#ifdef HAVE_NTRU
+    word16          peerNtruKeyLen;
+    byte            peerNtruKey[MAX_NTRU_PUB_KEY_SZ];
+    byte            peerNtruKeyPresent;
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
+    int             eccVerifyRes;
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
+    word32          ecdhCurveOID;            /* curve Ecc_Sum     */
+    ecc_key*        eccTempKey;              /* private ECDHE key */
+    byte            eccTempKeyPresent;       /* also holds type */
+    byte            peerEccKeyPresent;
+#endif
+#ifdef HAVE_ECC
+    ecc_key*        peerEccKey;              /* peer's  ECDHE key */
+    ecc_key*        peerEccDsaKey;           /* peer's  ECDSA key */
+    word16          eccTempKeySz;            /* in octets 20 - 66 */
+    byte            peerEccDsaKeyPresent;
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_CURVE448)
+    word32          pkCurveOID;              /* curve Ecc_Sum     */
+#endif
+#ifdef HAVE_ED25519
+    ed25519_key*    peerEd25519Key;
+    byte            peerEd25519KeyPresent;
+#endif
+#ifdef HAVE_CURVE25519
+    curve25519_key* peerX25519Key;
+    byte            peerX25519KeyPresent;
+#endif
+#ifdef HAVE_ED448
+    ed448_key*      peerEd448Key;
+    byte            peerEd448KeyPresent;
+#endif
+#ifdef HAVE_CURVE448
+    curve448_key*   peerX448Key;
+    byte            peerX448KeyPresent;
+#endif
+#ifdef HAVE_LIBZ
+    z_stream        c_stream;           /* compression   stream */
+    z_stream        d_stream;           /* decompression stream */
+    byte            didStreamInit;      /* for stream init and end */
+#endif
+#ifdef WOLFSSL_DTLS
+    int             dtls_timeout_init;  /* starting timeout value */
+    int             dtls_timeout_max;   /* maximum timeout value */
+    int             dtls_timeout;       /* current timeout value, changes */
+    word32          dtls_tx_msg_list_sz;
+    word32          dtls_rx_msg_list_sz;
+    DtlsMsg*        dtls_tx_msg_list;
+    DtlsMsg*        dtls_tx_msg;
+    DtlsMsg*        dtls_rx_msg_list;
+    void*           IOCB_CookieCtx;     /* gen cookie ctx */
+    word32          dtls_expected_rx;
+#ifdef WOLFSSL_SESSION_EXPORT
+    wc_dtls_export  dtls_export;        /* export function for session */
+#endif
+#if defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)
+    word16          dtlsMtuSz;
+#endif /* WOLFSSL_SCTP || WOLFSSL_DTLS_MTU */
+#ifdef WOLFSSL_MULTICAST
+    void*           mcastHwCbCtx;       /* Multicast highwater callback ctx */
+#endif /* WOLFSSL_MULTICAST */
+#ifdef WOLFSSL_DTLS_DROP_STATS
+    word32 macDropCount;
+    word32 replayDropCount;
+#endif /* WOLFSSL_DTLS_DROP_STATS */
+#endif /* WOLFSSL_DTLS */
+#ifdef WOLFSSL_CALLBACKS
+    TimeoutInfo     timeoutInfo;        /* info saved during handshake */
+    HandShakeInfo   handShakeInfo;      /* info saved during handshake */
+#endif
+#ifdef OPENSSL_EXTRA
+    SSL_Msg_Cb      protoMsgCb;         /* inspect protocol message callback */
+    void*           protoMsgCtx;        /* user set context with msg callback */
+#endif
+#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+    byte            hsInfoOn;           /* track handshake info        */
+    byte            toInfoOn;           /* track timeout   info        */
+#endif
+#ifdef HAVE_FUZZER
+    CallbackFuzzer  fuzzerCb;           /* for testing with using fuzzer */
+    void*           fuzzerCtx;          /* user defined pointer */
+#endif
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+    CertReqCtx*     certReqCtx;
+#endif
+#ifdef KEEP_PEER_CERT
+    WOLFSSL_X509     peerCert;           /* X509 peer cert */
+#endif
+#ifdef KEEP_OUR_CERT
+    WOLFSSL_X509*    ourCert;            /* keep alive a X509 struct of cert.
+                                            points to ctx if not owned (owned
+                                            flag found in buffers.weOwnCert) */
+#endif
+    byte             keepCert;           /* keep certificate after handshake */
+#if defined(HAVE_EX_DATA) || defined(FORTRESS)
+    WOLFSSL_CRYPTO_EX_DATA ex_data; /* external data, for Fortress */
+#endif
+    int              devId;             /* async device id to use */
+#ifdef HAVE_ONE_TIME_AUTH
+    OneTimeAuth     auth;
+#endif
+#ifdef HAVE_TLS_EXTENSIONS
+    TLSX* extensions;                  /* RFC 6066 TLS Extensions data */
+    #ifdef HAVE_MAX_FRAGMENT
+        word16 max_fragment;
+    #endif
+    #ifdef HAVE_TRUNCATED_HMAC
+        byte truncated_hmac;
+    #endif
+    #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+        byte status_request;
+    #endif
+    #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+        byte status_request_v2;
+    #endif
+    #if defined(HAVE_SECURE_RENEGOTIATION) \
+        || defined(HAVE_SERVER_RENEGOTIATION_INFO)
+        int                  secure_rene_count;    /* how many times */
+        SecureRenegotiation* secure_renegotiation; /* valid pointer indicates */
+    #endif                                         /* user turned on */
+    #ifdef HAVE_ALPN
+        char*   alpn_client_list;  /* keep the client's list */
+        #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)  || defined(WOLFSSL_HAPROXY)
+            CallbackALPNSelect alpnSelect;
+            void*              alpnSelectArg;
+        #endif
+    #endif                         /* of accepted protocols */
+    #if !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_SESSION_TICKET)
+        CallbackSessionTicket session_ticket_cb;
+        void*                 session_ticket_ctx;
+        byte                  expect_session_ticket;
+    #endif
+#endif /* HAVE_TLS_EXTENSIONS */
+#ifdef HAVE_OCSP
+        void*       ocspIOCtx;
+    #ifdef OPENSSL_EXTRA
+        byte*       ocspResp;
+        int         ocspRespSz;
+        #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+            char*   url;
+        #endif
+    #endif
+#endif
+#ifdef HAVE_NETX
+    NetX_Ctx        nxCtx;             /* NetX IO Context */
+#endif
+#if defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP)
+    void*           mnCtx;             /* mynewt mn_socket IO Context */
+#endif /* defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) */
+#ifdef WOLFSSL_GNRC
+    struct gnrc_wolfssl_ctx *gnrcCtx;  /* Riot-OS GNRC UDP/IP context */
+#endif
+#ifdef SESSION_INDEX
+    int sessionIndex;                  /* Session's location in the cache. */
+#endif
+#ifdef ATOMIC_USER
+    void*    MacEncryptCtx;    /* Atomic User Mac/Encrypt Callback Context */
+    void*    DecryptVerifyCtx; /* Atomic User Decrypt/Verify Callback Context */
+    #ifdef HAVE_ENCRYPT_THEN_MAC
+        void*    EncryptMacCtx;    /* Atomic User Encrypt/Mac Callback Ctx */
+        void*    VerifyDecryptCtx; /* Atomic User Verify/Decrypt Callback Ctx */
+    #endif
+#endif
+#ifdef HAVE_PK_CALLBACKS
+    #ifdef HAVE_ECC
+        void* EccKeyGenCtx;              /* EccKeyGen  Callback Context */
+        void* EccSignCtx;                /* Ecc Sign   Callback Context */
+        void* EccVerifyCtx;              /* Ecc Verify Callback Context */
+        void* EccSharedSecretCtx;        /* Ecc Pms    Callback Context */
+        #ifdef HAVE_ED25519
+            void* Ed25519SignCtx;        /* ED25519 Sign   Callback Context */
+            void* Ed25519VerifyCtx;      /* ED25519 Verify Callback Context */
+        #endif
+        #ifdef HAVE_CURVE25519
+            void* X25519KeyGenCtx;       /* X25519 KeyGen Callback Context */
+            void* X25519SharedSecretCtx; /* X25519 Pms    Callback Context */
+        #endif
+        #ifdef HAVE_ED448
+            void* Ed448SignCtx;          /* ED448 Sign   Callback Context */
+            void* Ed448VerifyCtx;        /* ED448 Verify Callback Context */
+        #endif
+        #ifdef HAVE_CURVE448
+            void* X448KeyGenCtx;         /* X448 KeyGen Callback Context */
+            void* X448SharedSecretCtx;   /* X448 Pms    Callback Context */
+        #endif
+    #endif /* HAVE_ECC */
+    #ifndef NO_DH
+        void* DhAgreeCtx; /* DH Pms Callback Context */
+    #endif /* !NO_DH */
+    #ifndef NO_RSA
+        void* RsaSignCtx;     /* Rsa Sign   Callback Context */
+        void* RsaVerifyCtx;   /* Rsa Verify Callback Context */
+        #ifdef WC_RSA_PSS
+            void* RsaPssSignCtx;     /* Rsa PSS Sign   Callback Context */
+            void* RsaPssVerifyCtx;   /* Rsa PSS Verify Callback Context */
+        #endif
+        void* RsaEncCtx;      /* Rsa Public  Encrypt   Callback Context */
+        void* RsaDecCtx;      /* Rsa Private Decrypt   Callback Context */
+    #endif /* NO_RSA */
+#endif /* HAVE_PK_CALLBACKS */
+#ifdef HAVE_SECRET_CALLBACK
+        SessionSecretCb sessionSecretCb;
+        void*           sessionSecretCtx;
+    #ifdef WOLFSSL_TLS13
+        Tls13SecretCb   tls13SecretCb;
+        void*           tls13SecretCtx;
+    #endif
+#endif /* HAVE_SECRET_CALLBACK */
+#ifdef WOLFSSL_JNI
+        void* jObjectRef;     /* reference to WolfSSLSession in JNI wrapper */
+#endif /* WOLFSSL_JNI */
+#ifdef WOLFSSL_EARLY_DATA
+    EarlyDataState earlyData;
+    word32 earlyDataSz;
+#endif
+#ifdef OPENSSL_ALL
+    long verifyCallbackResult;
+#endif
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+    WOLFSSL_STACK* supportedCiphers; /* Used in wolfSSL_get_ciphers_compat */
+    WOLFSSL_STACK* peerCertChain;    /* Used in wolfSSL_get_peer_cert_chain */
+#endif
+};
+
+
+WOLFSSL_LOCAL int  SSL_CTX_RefCount(WOLFSSL_CTX* ctx, int incr);
+WOLFSSL_LOCAL int  SetSSL_CTX(WOLFSSL*, WOLFSSL_CTX*, int);
+WOLFSSL_LOCAL int  InitSSL(WOLFSSL*, WOLFSSL_CTX*, int);
+WOLFSSL_LOCAL void FreeSSL(WOLFSSL*, void* heap);
+WOLFSSL_API   void SSL_ResourceFree(WOLFSSL*);   /* Micrium uses */
+
+
+#ifndef NO_CERTS
+
+    WOLFSSL_LOCAL int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
+                                    long sz, int format, int type, WOLFSSL* ssl,
+                                    long* used, int userChain, int verify);
+    WOLFSSL_LOCAL int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format,
+                                 int type, WOLFSSL* ssl, int userChain,
+                                WOLFSSL_CRL* crl, int verify);
+
+    #ifdef OPENSSL_EXTRA
+    WOLFSSL_LOCAL int CheckHostName(DecodedCert* dCert, char *domainName,
+                                    size_t domainNameLen);
+    #endif
+#endif
+
+
+#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+    WOLFSSL_LOCAL
+    void InitHandShakeInfo(HandShakeInfo*, WOLFSSL*);
+    WOLFSSL_LOCAL
+    void FinishHandShakeInfo(HandShakeInfo*);
+    WOLFSSL_LOCAL
+    void AddPacketName(WOLFSSL* ssl, const char* name);
+
+    WOLFSSL_LOCAL
+    void InitTimeoutInfo(TimeoutInfo*);
+    WOLFSSL_LOCAL
+    void FreeTimeoutInfo(TimeoutInfo*, void*);
+    WOLFSSL_LOCAL
+    void AddPacketInfo(WOLFSSL* ssl, const char* name, int type,
+                               const byte* data, int sz, int write, void* heap);
+    WOLFSSL_LOCAL
+    void AddLateName(const char*, TimeoutInfo*);
+    WOLFSSL_LOCAL
+    void AddLateRecordHeader(const RecordLayerHeader* rl, TimeoutInfo* info);
+#endif
+
+
+/* Record Layer Header identifier from page 12 */
+enum ContentType {
+    no_type            = 0,
+    change_cipher_spec = 20,
+    alert              = 21,
+    handshake          = 22,
+    application_data   = 23
+};
+
+
+/* handshake header, same for each message type, pgs 20/21 */
+typedef struct HandShakeHeader {
+    byte            type;
+    word24          length;
+} HandShakeHeader;
+
+
+/* DTLS handshake header, same for each message type */
+typedef struct DtlsHandShakeHeader {
+    byte            type;
+    word24          length;
+    byte            message_seq[2];    /* start at 0, retransmit gets same # */
+    word24          fragment_offset;   /* bytes in previous fragments */
+    word24          fragment_length;   /* length of this fragment */
+} DtlsHandShakeHeader;
+
+
+enum HandShakeType {
+    hello_request        =   0,
+    client_hello         =   1,
+    server_hello         =   2,
+    hello_verify_request =   3,    /* DTLS addition */
+    session_ticket       =   4,
+    end_of_early_data    =   5,
+    hello_retry_request  =   6,
+    encrypted_extensions =   8,
+    certificate          =  11,
+    server_key_exchange  =  12,
+    certificate_request  =  13,
+    server_hello_done    =  14,
+    certificate_verify   =  15,
+    client_key_exchange  =  16,
+    finished             =  20,
+    certificate_status   =  22,
+    key_update           =  24,
+    change_cipher_hs     =  55,    /* simulate unique handshake type for sanity
+                                      checks.  record layer change_cipher
+                                      conflicts with handshake finished */
+    message_hash         = 254,    /* synthetic message type for TLS v1.3 */
+    no_shake             = 255     /* used to initialize the DtlsMsg record */
+};
+
+enum ProvisionSide {
+    PROVISION_CLIENT = 1,
+    PROVISION_SERVER = 2,
+    PROVISION_CLIENT_SERVER = 3
+};
+
+
+static const byte client[SIZEOF_SENDER] = { 0x43, 0x4C, 0x4E, 0x54 };
+static const byte server[SIZEOF_SENDER] = { 0x53, 0x52, 0x56, 0x52 };
+
+static const byte tls_client[FINISHED_LABEL_SZ + 1] = "client finished";
+static const byte tls_server[FINISHED_LABEL_SZ + 1] = "server finished";
+
+#ifdef OPENSSL_EXTRA
+typedef struct {
+    int name_len;
+    const char *name;
+    int nid;
+} WOLF_EC_NIST_NAME;
+extern const WOLF_EC_NIST_NAME kNistCurves[];
+/* This is the longest and shortest curve name in the kNistCurves list */
+#define kNistCurves_MIN_NAME_LEN 5
+#define kNistCurves_MAX_NAME_LEN 7
+#endif
+
+/* internal functions */
+WOLFSSL_LOCAL int SendChangeCipher(WOLFSSL*);
+WOLFSSL_LOCAL int SendTicket(WOLFSSL*);
+WOLFSSL_LOCAL int DoClientTicket(WOLFSSL*, const byte*, word32);
+WOLFSSL_LOCAL int SendData(WOLFSSL*, const void*, int);
+#ifdef WOLFSSL_TLS13
+#ifdef WOLFSSL_TLS13_DRAFT_18
+WOLFSSL_LOCAL int SendTls13HelloRetryRequest(WOLFSSL*);
+#else
+WOLFSSL_LOCAL int SendTls13ServerHello(WOLFSSL*, byte);
+#endif
+#endif
+WOLFSSL_LOCAL int SendCertificate(WOLFSSL*);
+WOLFSSL_LOCAL int SendCertificateRequest(WOLFSSL*);
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+WOLFSSL_LOCAL int CreateOcspResponse(WOLFSSL*, OcspRequest**, buffer*);
+#endif
+#if defined(HAVE_SECURE_RENEGOTIATION) && \
+    defined(HAVE_SERVER_RENEGOTIATION_INFO)
+WOLFSSL_LOCAL int SendHelloRequest(WOLFSSL*);
+#endif
+WOLFSSL_LOCAL int SendCertificateStatus(WOLFSSL*);
+WOLFSSL_LOCAL int SendServerKeyExchange(WOLFSSL*);
+WOLFSSL_LOCAL int SendBuffered(WOLFSSL*);
+WOLFSSL_LOCAL int ReceiveData(WOLFSSL*, byte*, int, int);
+WOLFSSL_LOCAL int SendFinished(WOLFSSL*);
+WOLFSSL_LOCAL int SendAlert(WOLFSSL*, int, int);
+WOLFSSL_LOCAL int ProcessReply(WOLFSSL*);
+
+WOLFSSL_LOCAL int SetCipherSpecs(WOLFSSL*);
+WOLFSSL_LOCAL int MakeMasterSecret(WOLFSSL*);
+
+WOLFSSL_LOCAL int AddSession(WOLFSSL*);
+WOLFSSL_LOCAL int DeriveKeys(WOLFSSL* ssl);
+WOLFSSL_LOCAL int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side);
+
+WOLFSSL_LOCAL int IsTLS(const WOLFSSL* ssl);
+WOLFSSL_LOCAL int IsAtLeastTLSv1_2(const WOLFSSL* ssl);
+WOLFSSL_LOCAL int IsAtLeastTLSv1_3(const ProtocolVersion pv);
+
+WOLFSSL_LOCAL void FreeHandshakeResources(WOLFSSL* ssl);
+WOLFSSL_LOCAL void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree);
+WOLFSSL_LOCAL void ShrinkOutputBuffer(WOLFSSL* ssl);
+
+WOLFSSL_LOCAL int VerifyClientSuite(WOLFSSL* ssl);
+
+WOLFSSL_LOCAL int SetTicket(WOLFSSL*, const byte*, word32);
+WOLFSSL_LOCAL int wolfSSL_GetMaxRecordSize(WOLFSSL* ssl, int maxFragment);
+
+#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC)
+WOLFSSL_LOCAL int SetECKeyInternal(WOLFSSL_EC_KEY* eckey);
+WOLFSSL_LOCAL int SetECKeyExternal(WOLFSSL_EC_KEY* eckey);
+#endif
+
+WOLFSSL_LOCAL WC_RNG* WOLFSSL_RSA_GetRNG(WOLFSSL_RSA *rsa, WC_RNG **tmpRNG,
+                                         int *initTmpRng);
+
+#ifndef NO_CERTS
+    #ifndef NO_RSA
+        #ifdef WC_RSA_PSS
+            WOLFSSL_LOCAL int CheckRsaPssPadding(const byte* plain, word32 plainSz,
+                byte* out, word32 sigSz, enum wc_HashType hashType);
+            WOLFSSL_LOCAL int ConvertHashPss(int hashAlgo,
+                enum wc_HashType* hashType, int* mgf);
+        #endif
+        WOLFSSL_LOCAL int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig,
+            word32 sigSz, const byte* plain, word32 plainSz, int sigAlgo,
+            int hashAlgo, RsaKey* key, DerBuffer* keyBufInfo);
+        WOLFSSL_LOCAL int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz,
+            byte* out, word32* outSz, int sigAlgo, int hashAlgo, RsaKey* key,
+            DerBuffer* keyBufInfo);
+        WOLFSSL_LOCAL int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz,
+            byte** out, int sigAlgo, int hashAlgo, RsaKey* key,
+            buffer* keyBufInfo);
+        WOLFSSL_LOCAL int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out,
+            word32* outSz, RsaKey* key, DerBuffer* keyBufInfo);
+        WOLFSSL_LOCAL int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
+            word32* outSz, RsaKey* key, buffer* keyBufInfo);
+    #endif /* !NO_RSA */
+
+    #ifdef HAVE_ECC
+        WOLFSSL_LOCAL int EccSign(WOLFSSL* ssl, const byte* in, word32 inSz,
+            byte* out, word32* outSz, ecc_key* key, DerBuffer* keyBufInfo);
+        WOLFSSL_LOCAL int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz,
+            const byte* out, word32 outSz, ecc_key* key, buffer* keyBufInfo);
+        WOLFSSL_LOCAL int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key,
+            ecc_key* pub_key, byte* pubKeyDer, word32* pubKeySz, byte* out,
+            word32* outlen, int side);
+    #endif /* HAVE_ECC */
+    #ifdef HAVE_ED25519
+        WOLFSSL_LOCAL int Ed25519CheckPubKey(WOLFSSL* ssl);
+        WOLFSSL_LOCAL int Ed25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz,
+            byte* out, word32* outSz, ed25519_key* key, DerBuffer* keyBufInfo);
+        WOLFSSL_LOCAL int Ed25519Verify(WOLFSSL* ssl, const byte* in,
+            word32 inSz, const byte* msg, word32 msgSz, ed25519_key* key,
+            buffer* keyBufInfo);
+    #endif /* HAVE_ED25519 */
+    #ifdef HAVE_ED448
+        WOLFSSL_LOCAL int Ed448CheckPubKey(WOLFSSL* ssl);
+        WOLFSSL_LOCAL int Ed448Sign(WOLFSSL* ssl, const byte* in, word32 inSz,
+            byte* out, word32* outSz, ed448_key* key, DerBuffer* keyBufInfo);
+        WOLFSSL_LOCAL int Ed448Verify(WOLFSSL* ssl, const byte* in,
+            word32 inSz, const byte* msg, word32 msgSz, ed448_key* key,
+            buffer* keyBufInfo);
+    #endif /* HAVE_ED448 */
+
+
+    #ifdef WOLFSSL_TRUST_PEER_CERT
+
+        /* options for searching hash table for a matching trusted peer cert */
+        #define WC_MATCH_SKID 0
+        #define WC_MATCH_NAME 1
+
+        WOLFSSL_LOCAL TrustedPeerCert* GetTrustedPeer(void* vp, byte* hash,
+                                                                      int type);
+        WOLFSSL_LOCAL int MatchTrustedPeer(TrustedPeerCert* tp,
+                                                             DecodedCert* cert);
+    #endif
+
+    WOLFSSL_LOCAL Signer* GetCA(void* cm, byte* hash);
+    #ifndef NO_SKID
+        WOLFSSL_LOCAL Signer* GetCAByName(void* cm, byte* hash);
+    #endif
+#endif /* !NO_CERTS */
+WOLFSSL_LOCAL int  BuildTlsHandshakeHash(WOLFSSL* ssl, byte* hash,
+                                   word32* hashLen);
+WOLFSSL_LOCAL int  BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes,
+                                   const byte* sender);
+WOLFSSL_LOCAL void FreeArrays(WOLFSSL* ssl, int keep);
+WOLFSSL_LOCAL  int CheckAvailableSize(WOLFSSL *ssl, int size);
+WOLFSSL_LOCAL  int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength);
+
+#ifndef NO_TLS
+    WOLFSSL_LOCAL int  MakeTlsMasterSecret(WOLFSSL*);
+#ifndef WOLFSSL_AEAD_ONLY
+    WOLFSSL_LOCAL int  TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in,
+                                word32 sz, int padSz, int content, int verify);
+#endif
+#endif
+
+#ifndef NO_WOLFSSL_CLIENT
+    WOLFSSL_LOCAL int SendClientHello(WOLFSSL*);
+    #ifdef WOLFSSL_TLS13
+    WOLFSSL_LOCAL int SendTls13ClientHello(WOLFSSL*);
+    #endif
+    WOLFSSL_LOCAL int SendClientKeyExchange(WOLFSSL*);
+    WOLFSSL_LOCAL int SendCertificateVerify(WOLFSSL*);
+#endif /* NO_WOLFSSL_CLIENT */
+
+#ifndef NO_WOLFSSL_SERVER
+    WOLFSSL_LOCAL int SendServerHello(WOLFSSL*);
+    WOLFSSL_LOCAL int SendServerHelloDone(WOLFSSL*);
+#endif /* NO_WOLFSSL_SERVER */
+
+#ifdef WOLFSSL_DTLS
+    WOLFSSL_LOCAL DtlsMsg* DtlsMsgNew(word32, void*);
+    WOLFSSL_LOCAL void DtlsMsgDelete(DtlsMsg*, void*);
+    WOLFSSL_LOCAL void DtlsMsgListDelete(DtlsMsg*, void*);
+    WOLFSSL_LOCAL int  DtlsMsgSet(DtlsMsg*, word32, const byte*, byte,
+                                                       word32, word32, void*);
+    WOLFSSL_LOCAL DtlsMsg* DtlsMsgFind(DtlsMsg*, word32);
+    WOLFSSL_LOCAL void DtlsMsgStore(WOLFSSL*, word32, const byte*, word32,
+                                                byte, word32, word32, void*);
+    WOLFSSL_LOCAL DtlsMsg* DtlsMsgInsert(DtlsMsg*, DtlsMsg*);
+
+    WOLFSSL_LOCAL int  DtlsMsgPoolSave(WOLFSSL*, const byte*, word32);
+    WOLFSSL_LOCAL int  DtlsMsgPoolTimeout(WOLFSSL*);
+    WOLFSSL_LOCAL int  VerifyForDtlsMsgPoolSend(WOLFSSL*, byte, word32);
+    WOLFSSL_LOCAL void DtlsMsgPoolReset(WOLFSSL*);
+    WOLFSSL_LOCAL int  DtlsMsgPoolSend(WOLFSSL*, int);
+#endif /* WOLFSSL_DTLS */
+
+#ifndef NO_TLS
+
+
+#endif /* NO_TLS */
+
+#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK))
+    WOLFSSL_LOCAL word32 TimeNowInMilliseconds(void);
+#endif
+WOLFSSL_LOCAL word32  LowResTimer(void);
+
+#ifndef NO_CERTS
+    WOLFSSL_LOCAL void InitX509Name(WOLFSSL_X509_NAME*, int);
+    WOLFSSL_LOCAL void FreeX509Name(WOLFSSL_X509_NAME* name, void* heap);
+    WOLFSSL_LOCAL void InitX509(WOLFSSL_X509*, int, void* heap);
+    WOLFSSL_LOCAL void FreeX509(WOLFSSL_X509*);
+    WOLFSSL_LOCAL int  CopyDecodedToX509(WOLFSSL_X509*, DecodedCert*);
+#endif
+
+#ifndef MAX_CIPHER_NAME
+#define MAX_CIPHER_NAME 50
+#endif
+
+#ifdef WOLFSSL_NAMES_STATIC
+typedef char cipher_name[MAX_CIPHER_NAME];
+#else
+typedef const char* cipher_name;
+#endif
+
+typedef struct CipherSuiteInfo {
+    cipher_name name;
+#ifndef NO_ERROR_STRINGS
+    cipher_name name_iana;
+#endif
+    byte cipherSuite0;
+    byte cipherSuite;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+    byte minor;
+    byte major;
+#endif
+} CipherSuiteInfo;
+
+WOLFSSL_LOCAL const CipherSuiteInfo* GetCipherNames(void);
+WOLFSSL_LOCAL int GetCipherNamesSize(void);
+WOLFSSL_LOCAL const char* GetCipherNameInternal(const byte cipherSuite0, const byte cipherSuite);
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+/* used in wolfSSL_sk_CIPHER_description */
+#define MAX_SEGMENTS    5
+#define MAX_SEGMENT_SZ 20
+WOLFSSL_LOCAL int wolfSSL_sk_CIPHER_description(WOLFSSL_CIPHER*);
+WOLFSSL_LOCAL const char* GetCipherProtocol(const byte minor);
+WOLFSSL_LOCAL const char* GetCipherKeaStr(char n[][MAX_SEGMENT_SZ]);
+WOLFSSL_LOCAL const char* GetCipherAuthStr(char n[][MAX_SEGMENT_SZ]);
+WOLFSSL_LOCAL const char* GetCipherEncStr(char n[][MAX_SEGMENT_SZ]);
+WOLFSSL_LOCAL const char* GetCipherMacStr(char n[][MAX_SEGMENT_SZ]);
+WOLFSSL_LOCAL int SetCipherBits(const char* enc);
+#endif
+WOLFSSL_LOCAL const char* GetCipherNameIana(const byte cipherSuite0, const byte cipherSuite);
+WOLFSSL_LOCAL const char* wolfSSL_get_cipher_name_internal(WOLFSSL* ssl);
+WOLFSSL_LOCAL const char* wolfSSL_get_cipher_name_iana(WOLFSSL* ssl);
+WOLFSSL_LOCAL int GetCipherSuiteFromName(const char* name, byte* cipherSuite0,
+                                         byte* cipherSuite);
+
+enum encrypt_side {
+    ENCRYPT_SIDE_ONLY = 1,
+    DECRYPT_SIDE_ONLY,
+    ENCRYPT_AND_DECRYPT_SIDE
+};
+
+WOLFSSL_LOCAL int SetKeysSide(WOLFSSL*, enum encrypt_side);
+
+/* Set*Internal and Set*External functions */
+WOLFSSL_LOCAL int SetDsaInternal(WOLFSSL_DSA* dsa);
+WOLFSSL_LOCAL int SetDsaExternal(WOLFSSL_DSA* dsa);
+#ifndef HAVE_USER_RSA
+WOLFSSL_LOCAL int SetRsaExternal(WOLFSSL_RSA* rsa);
+WOLFSSL_LOCAL int SetRsaInternal(WOLFSSL_RSA* rsa);
+#endif
+WOLFSSL_LOCAL int SetDhInternal(WOLFSSL_DH* dh);
+WOLFSSL_LOCAL int SetDhExternal(WOLFSSL_DH *dh);
+
+#ifndef NO_DH
+    WOLFSSL_LOCAL int DhGenKeyPair(WOLFSSL* ssl, DhKey* dhKey,
+        byte* priv, word32* privSz,
+        byte* pub, word32* pubSz);
+    WOLFSSL_LOCAL int DhAgree(WOLFSSL* ssl, DhKey* dhKey,
+        const byte* priv, word32 privSz,
+        const byte* otherPub, word32 otherPubSz,
+        byte* agree, word32* agreeSz);
+#endif /* !NO_DH */
+
+#ifdef HAVE_ECC
+    WOLFSSL_LOCAL int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer);
+    WOLFSSL_LOCAL word16 GetCurveByOID(int oidSum);
+#endif
+
+WOLFSSL_LOCAL int InitHandshakeHashes(WOLFSSL* ssl);
+WOLFSSL_LOCAL void FreeHandshakeHashes(WOLFSSL* ssl);
+
+WOLFSSL_LOCAL int BuildMessage(WOLFSSL* ssl, byte* output, int outSz,
+                        const byte* input, int inSz, int type, int hashOutput,
+                        int sizeOnly, int asyncOkay);
+
+#ifdef WOLFSSL_TLS13
+int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
+               int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay);
+#endif
+
+WOLFSSL_LOCAL int AllocKey(WOLFSSL* ssl, int type, void** pKey);
+WOLFSSL_LOCAL void FreeKey(WOLFSSL* ssl, int type, void** pKey);
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    WOLFSSL_LOCAL int wolfSSL_AsyncInit(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev, word32 flags);
+    WOLFSSL_LOCAL int wolfSSL_AsyncPop(WOLFSSL* ssl, byte* state);
+    WOLFSSL_LOCAL int wolfSSL_AsyncPush(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev);
+#endif
+
+
+#ifdef __cplusplus
+    }  /* extern "C" */
+#endif
+
+#endif /* wolfSSL_INT_H */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/ocsp.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/ocsp.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/ocsp.h	(revision 453)
@@ -0,0 +1,133 @@
+/* ocsp.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+/* wolfSSL OCSP API */
+
+#ifndef WOLFSSL_OCSP_H
+#define WOLFSSL_OCSP_H
+
+#ifdef HAVE_OCSP
+
+#include <wolfssl/ssl.h>
+#include <wolfssl/wolfcrypt/asn.h>
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+typedef struct WOLFSSL_OCSP WOLFSSL_OCSP;
+
+#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || defined(WOLFSSL_NGINX) ||\
+    defined(WOLFSSL_HAPROXY)
+typedef struct OcspResponse WOLFSSL_OCSP_BASICRESP;
+
+typedef struct OcspRequest WOLFSSL_OCSP_CERTID;
+
+typedef struct OcspRequest WOLFSSL_OCSP_ONEREQ;
+
+typedef struct OcspRequest WOLFSSL_OCSP_REQUEST;
+#endif
+
+WOLFSSL_LOCAL int  InitOCSP(WOLFSSL_OCSP*, WOLFSSL_CERT_MANAGER*);
+WOLFSSL_LOCAL void FreeOCSP(WOLFSSL_OCSP*, int dynamic);
+
+WOLFSSL_LOCAL int  CheckCertOCSP(WOLFSSL_OCSP*, DecodedCert*,
+                                           WOLFSSL_BUFFER_INFO* responseBuffer);
+WOLFSSL_LOCAL int  CheckCertOCSP_ex(WOLFSSL_OCSP*, DecodedCert*,
+                             WOLFSSL_BUFFER_INFO* responseBuffer, WOLFSSL* ssl);
+WOLFSSL_LOCAL int  CheckOcspRequest(WOLFSSL_OCSP* ocsp,
+                 OcspRequest* ocspRequest, WOLFSSL_BUFFER_INFO* responseBuffer);
+WOLFSSL_LOCAL int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz,
+                                    WOLFSSL_BUFFER_INFO *responseBuffer, CertStatus *status,
+                                    OcspEntry *entry, OcspRequest *ocspRequest);
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
+    defined(WOLFSSL_APACHE_HTTPD)
+
+    WOLFSSL_API int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs,
+                                                  WOLFSSL_OCSP_CERTID *id, int *status, int *reason,
+                                                  WOLFSSL_ASN1_TIME **revtime, WOLFSSL_ASN1_TIME **thisupd,
+                                                  WOLFSSL_ASN1_TIME **nextupd);
+WOLFSSL_API const char *wolfSSL_OCSP_cert_status_str(long s);
+WOLFSSL_API int wolfSSL_OCSP_check_validity(WOLFSSL_ASN1_TIME* thisupd,
+    WOLFSSL_ASN1_TIME* nextupd, long sec, long maxsec);
+
+WOLFSSL_API void wolfSSL_OCSP_CERTID_free(WOLFSSL_OCSP_CERTID* certId);
+WOLFSSL_API WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id(
+    const WOLFSSL_EVP_MD *dgst, const WOLFSSL_X509 *subject,
+    const WOLFSSL_X509 *issuer);
+
+WOLFSSL_API void wolfSSL_OCSP_BASICRESP_free(WOLFSSL_OCSP_BASICRESP* basicResponse);
+WOLFSSL_API int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP *bs,
+    WOLF_STACK_OF(WOLFSSL_X509) *certs, WOLFSSL_X509_STORE *st, unsigned long flags);
+
+WOLFSSL_API void wolfSSL_OCSP_RESPONSE_free(OcspResponse* response);
+WOLFSSL_API OcspResponse* wolfSSL_d2i_OCSP_RESPONSE_bio(WOLFSSL_BIO* bio,
+    OcspResponse** response);
+WOLFSSL_API OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response,
+    const unsigned char** data, int len);
+WOLFSSL_API int wolfSSL_i2d_OCSP_RESPONSE(OcspResponse* response,
+    unsigned char** data);
+WOLFSSL_API int wolfSSL_OCSP_response_status(OcspResponse *response);
+WOLFSSL_API const char *wolfSSL_OCSP_response_status_str(long s);
+WOLFSSL_API WOLFSSL_OCSP_BASICRESP* wolfSSL_OCSP_response_get1_basic(
+    OcspResponse* response);
+
+WOLFSSL_API OcspRequest* wolfSSL_OCSP_REQUEST_new(void);
+WOLFSSL_API void wolfSSL_OCSP_REQUEST_free(OcspRequest* request);
+WOLFSSL_API int wolfSSL_i2d_OCSP_REQUEST(OcspRequest* request,
+    unsigned char** data);
+WOLFSSL_API WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req,
+    WOLFSSL_OCSP_CERTID *cid);
+WOLFSSL_API WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_CERTID_dup(WOLFSSL_OCSP_CERTID*);
+WOLFSSL_API int wolfSSL_i2d_OCSP_REQUEST_bio(WOLFSSL_BIO* out,
+    WOLFSSL_OCSP_REQUEST *req);
+
+#endif
+#ifdef OPENSSL_EXTRA
+WOLFSSL_API int wolfSSL_OCSP_REQUEST_add_ext(OcspRequest* req,
+        WOLFSSL_X509_EXTENSION* ext, int idx);
+WOLFSSL_API OcspResponse* wolfSSL_OCSP_response_create(int status,
+    WOLFSSL_OCSP_BASICRESP* bs);
+WOLFSSL_API const char* wolfSSL_OCSP_crl_reason_str(long s);
+
+WOLFSSL_API int wolfSSL_OCSP_id_get0_info(WOLFSSL_ASN1_STRING**,
+  WOLFSSL_ASN1_OBJECT**, WOLFSSL_ASN1_STRING**,
+  WOLFSSL_ASN1_INTEGER**, WOLFSSL_OCSP_CERTID*);
+
+WOLFSSL_API int wolfSSL_OCSP_request_add1_nonce(OcspRequest* req,
+        unsigned char* val, int sz);
+WOLFSSL_API int wolfSSL_OCSP_check_nonce(OcspRequest* req,
+        WOLFSSL_OCSP_BASICRESP* bs);
+#endif
+
+
+#ifdef __cplusplus
+    }  /* extern "C" */
+#endif
+
+
+#endif /* HAVE_OCSP */
+#endif /* WOLFSSL_OCSP_H */
+
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/aes.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/aes.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/aes.h	(revision 453)
@@ -0,0 +1,111 @@
+/* aes.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+/*  aes.h defines mini des openssl compatibility layer
+ *
+ */
+
+
+#ifndef WOLFSSL_AES_H_
+#define WOLFSSL_AES_H_
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifndef NO_AES
+#include <wolfssl/openssl/ssl.h> /* for size_t */
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+/* This structure wrapper is done because there is no aes_new function with
+ * OpenSSL compatibility layer. This makes code working with an AES structure
+ * to need the size of the structure. */
+typedef struct WOLFSSL_AES_KEY {
+    /* aligned and big enough for Aes from wolfssl/wolfcrypt/aes.h */
+    ALIGN16 void* holder[(376 + WC_ASYNC_DEV_SIZE)/ sizeof(void*)];
+    #ifdef GCM_TABLE
+    /* key-based fast multiplication table. */
+    ALIGN16 void* M0[4096 / sizeof(void*)];
+    #endif /* GCM_TABLE */
+    #if defined(WOLFSSL_DEVCRYPTO) && \
+        (defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC))
+    /* large enough for additional devcrypto information */
+    void* devKey[288 / sizeof(void*)];
+    #endif
+    #ifdef WOLFSSL_AFALG
+    void* afalg_holder[288 / sizeof(void*)];
+    #endif
+    #ifdef HAVE_PKCS11
+    void* pkcs11_holder[(AES_MAX_ID_LEN + sizeof(int)) / sizeof(void*)];
+    #endif
+    #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
+    void* async_holder[128 / sizeof(void*)];
+    #endif
+} WOLFSSL_AES_KEY;
+typedef WOLFSSL_AES_KEY AES_KEY;
+
+WOLFSSL_API int wolfSSL_AES_set_encrypt_key
+    (const unsigned char *, const int bits, AES_KEY *);
+WOLFSSL_API int wolfSSL_AES_set_decrypt_key
+    (const unsigned char *, const int bits, AES_KEY *);
+WOLFSSL_API void wolfSSL_AES_cbc_encrypt
+    (const unsigned char *in, unsigned char* out, size_t len,
+     AES_KEY *key, unsigned char* iv, const int enc);
+WOLFSSL_API void wolfSSL_AES_ecb_encrypt
+    (const unsigned char *in, unsigned char* out,
+     AES_KEY *key, const int enc);
+WOLFSSL_API void wolfSSL_AES_cfb128_encrypt
+    (const unsigned char *in, unsigned char* out, size_t len,
+     AES_KEY *key, unsigned char* iv, int* num, const int enc);
+
+#define AES_cbc_encrypt     wolfSSL_AES_cbc_encrypt
+#define AES_ecb_encrypt     wolfSSL_AES_ecb_encrypt
+#define AES_cfb128_encrypt  wolfSSL_AES_cfb128_encrypt
+#define AES_set_encrypt_key wolfSSL_AES_set_encrypt_key
+#define AES_set_decrypt_key wolfSSL_AES_set_decrypt_key
+
+#ifdef WOLFSSL_AES_DIRECT
+WOLFSSL_API void wolfSSL_AES_encrypt
+    (const unsigned char* input, unsigned char* output, AES_KEY *);
+WOLFSSL_API void wolfSSL_AES_decrypt
+    (const unsigned char* input, unsigned char* output, AES_KEY *);
+
+#define AES_encrypt         wolfSSL_AES_encrypt
+#define AES_decrypt         wolfSSL_AES_decrypt
+#endif /* HAVE_AES_DIRECT */
+
+#ifndef AES_ENCRYPT
+#define AES_ENCRYPT AES_ENCRYPTION
+#endif
+#ifndef AES_DECRYPT
+#define AES_DECRYPT AES_DECRYPTION
+#endif
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* NO_AES */
+
+#endif /* WOLFSSL_AES_H_ */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/asn1.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/asn1.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/asn1.h	(revision 453)
@@ -0,0 +1,152 @@
+/* asn1.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* asn1.h for openssl */
+
+#ifndef WOLFSSL_ASN1_H_
+#define WOLFSSL_ASN1_H_
+
+#include <wolfssl/openssl/ssl.h>
+
+#define ASN1_STRING_new      wolfSSL_ASN1_STRING_new
+#define ASN1_STRING_type_new wolfSSL_ASN1_STRING_type_new
+#define ASN1_STRING_type     wolfSSL_ASN1_STRING_type
+#define ASN1_STRING_set      wolfSSL_ASN1_STRING_set
+#define ASN1_STRING_free     wolfSSL_ASN1_STRING_free
+
+#define V_ASN1_INTEGER                   0x02
+#define V_ASN1_OCTET_STRING              0x04 /* tag for ASN1_OCTET_STRING */
+#define V_ASN1_NEG                       0x100
+#define V_ASN1_NEG_INTEGER               (2 | V_ASN1_NEG)
+#define V_ASN1_NEG_ENUMERATED            (10 | V_ASN1_NEG)
+
+/* Type for ASN1_print_ex */
+# define ASN1_STRFLGS_ESC_2253           1
+# define ASN1_STRFLGS_ESC_CTRL           2
+# define ASN1_STRFLGS_ESC_MSB            4
+# define ASN1_STRFLGS_ESC_QUOTE          8
+# define ASN1_STRFLGS_UTF8_CONVERT       0x10
+# define ASN1_STRFLGS_IGNORE_TYPE        0x20
+# define ASN1_STRFLGS_SHOW_TYPE          0x40
+# define ASN1_STRFLGS_DUMP_ALL           0x80
+# define ASN1_STRFLGS_DUMP_UNKNOWN       0x100
+# define ASN1_STRFLGS_DUMP_DER           0x200
+# define ASN1_STRFLGS_RFC2253            (ASN1_STRFLGS_ESC_2253 | \
+                                          ASN1_STRFLGS_ESC_CTRL | \
+                                          ASN1_STRFLGS_ESC_MSB | \
+                                          ASN1_STRFLGS_UTF8_CONVERT | \
+                                          ASN1_STRFLGS_DUMP_UNKNOWN | \
+                                          ASN1_STRFLGS_DUMP_DER)
+
+#define MBSTRING_UTF8                    0x1000
+#define MBSTRING_ASC                     0x1001
+#define MBSTRING_BMP                     0x1002
+#define MBSTRING_UNIV                    0x1004
+
+#define ASN1_UTCTIME_print              wolfSSL_ASN1_UTCTIME_print
+#define ASN1_TIME_check                 wolfSSL_ASN1_TIME_check
+#define ASN1_TIME_diff                  wolfSSL_ASN1_TIME_diff
+#define ASN1_TIME_set                   wolfSSL_ASN1_TIME_set
+
+#define V_ASN1_OBJECT                   6
+#define V_ASN1_UTCTIME                  23
+#define V_ASN1_GENERALIZEDTIME          24
+
+#define ASN1_STRING_FLAG_BITS_LEFT       0x008
+#define ASN1_STRING_FLAG_NDEF            0x010
+#define ASN1_STRING_FLAG_CONT            0x020
+#define ASN1_STRING_FLAG_MSTRING         0x040
+#define ASN1_STRING_FLAG_EMBED           0x080
+
+
+WOLFSSL_API WOLFSSL_ASN1_INTEGER *wolfSSL_BN_to_ASN1_INTEGER(
+    const WOLFSSL_BIGNUM*, WOLFSSL_ASN1_INTEGER*);
+
+WOLFSSL_API void wolfSSL_ASN1_TYPE_set(WOLFSSL_ASN1_TYPE *a, int type, void *value);
+
+#ifdef OPENSSL_ALL
+/* IMPLEMENT_ASN1_FUNCTIONS is strictly for external use only. Internally
+ * we don't use this. Some projects use OpenSSL to implement ASN1 types and
+ * this section is only to provide those projects with ASN1 functionality. */
+typedef struct {
+    size_t offset;              /* Offset of this field in structure */
+    byte type;                  /* The type of the member as defined in
+                                 * WOLFSSL_ASN1_TYPES */
+} WOLFSSL_ASN1_TEMPLATE;
+
+typedef struct {
+    byte type;                              /* One of the ASN_Tags types */
+    const WOLFSSL_ASN1_TEMPLATE *members;   /* If SEQUENCE or CHOICE this
+                                             * contains the contents */
+    size_t mcount;                          /* Number of members if SEQUENCE
+                                             * or CHOICE */
+    size_t size;                            /* Structure size */
+} WOLFSSL_ASN1_ITEM;
+
+typedef enum {
+    WOLFSSL_X509_ALGOR_ASN1 = 0,
+    WOLFSSL_ASN1_BIT_STRING_ASN1,
+} WOLFSSL_ASN1_TYPES;
+
+#define ASN1_SEQUENCE(type) \
+    static const type __##type##_dummy_struct;\
+    static const WOLFSSL_ASN1_TEMPLATE type##_member_data[]
+
+#define ASN1_SIMPLE(type, member, member_type) \
+    { (char*)&__##type##_dummy_struct.member - (char*)&__##type##_dummy_struct, \
+        WOLFSSL_##member_type##_ASN1 }
+
+#define ASN1_SEQUENCE_END(type) \
+    ; \
+    const WOLFSSL_ASN1_ITEM type##_template_data = { \
+            ASN_SEQUENCE, \
+            type##_member_data, \
+            sizeof(type##_member_data) / sizeof(WOLFSSL_ASN1_TEMPLATE), \
+            sizeof(type) \
+    };
+
+WOLFSSL_API void *wolfSSL_ASN1_item_new(const WOLFSSL_ASN1_ITEM *template);
+WOLFSSL_API void wolfSSL_ASN1_item_free(void *val, const WOLFSSL_ASN1_ITEM *template);
+WOLFSSL_API int wolfSSL_ASN1_item_i2d(const void *src, byte **dest,
+                                      const WOLFSSL_ASN1_ITEM *template);
+
+/* Need function declaration otherwise compiler complains */
+#define IMPLEMENT_ASN1_FUNCTIONS(type) \
+    type *type##_new(void); \
+    type *type##_new(void){ \
+        return (type*)wolfSSL_ASN1_item_new(&type##_template_data); \
+    } \
+    void type##_free(type *t); \
+    void type##_free(type *t){ \
+        wolfSSL_ASN1_item_free(t, &type##_template_data); \
+    } \
+    int i2d_##type(type *src, byte **dest); \
+    int i2d_##type(type *src, byte **dest) \
+    { \
+        return wolfSSL_ASN1_item_i2d(src, dest, &type##_template_data);\
+    }
+
+#endif /* OPENSSL_ALL */
+
+#define BN_to_ASN1_INTEGER          wolfSSL_BN_to_ASN1_INTEGER
+#define ASN1_TYPE_set               wolfSSL_ASN1_TYPE_set
+
+#endif /* WOLFSSL_ASN1_H_ */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/bio.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/bio.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/bio.h	(revision 453)
@@ -0,0 +1,164 @@
+/* bio.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* bio.h for openssl */
+
+
+#ifndef WOLFSSL_BIO_H_
+#define WOLFSSL_BIO_H_
+
+#include <wolfssl/openssl/ssl.h>
+
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+
+#define BIO_FLAG_BASE64_NO_NL WOLFSSL_BIO_FLAG_BASE64_NO_NL
+#define BIO_FLAG_READ         WOLFSSL_BIO_FLAG_READ
+#define BIO_FLAG_WRITE        WOLFSSL_BIO_FLAG_WRITE
+#define BIO_FLAG_IO_SPECIAL   WOLFSSL_BIO_FLAG_IO_SPECIAL
+#define BIO_FLAG_RETRY        WOLFSSL_BIO_FLAG_RETRY
+
+#define BIO_new_fp                      wolfSSL_BIO_new_fp
+#define BIO_new_file                    wolfSSL_BIO_new_file
+#define BIO_new_fp                      wolfSSL_BIO_new_fp
+#define BIO_ctrl                        wolfSSL_BIO_ctrl
+#define BIO_ctrl_pending                wolfSSL_BIO_ctrl_pending
+#define BIO_wpending                    wolfSSL_BIO_wpending
+#define BIO_get_mem_ptr                 wolfSSL_BIO_get_mem_ptr
+#define BIO_int_ctrl                    wolfSSL_BIO_int_ctrl
+#define BIO_reset                       wolfSSL_BIO_reset
+#define BIO_s_file                      wolfSSL_BIO_s_file
+#define BIO_s_bio                       wolfSSL_BIO_s_bio
+#define BIO_s_socket                    wolfSSL_BIO_s_socket
+#define BIO_set_fd                      wolfSSL_BIO_set_fd
+#define BIO_set_close                   wolfSSL_BIO_set_close
+#define BIO_ctrl_reset_read_request     wolfSSL_BIO_ctrl_reset_read_request
+#define BIO_set_write_buf_size          wolfSSL_BIO_set_write_buf_size
+#define BIO_make_bio_pair               wolfSSL_BIO_make_bio_pair
+
+#define BIO_set_fp                      wolfSSL_BIO_set_fp
+#define BIO_get_fp                      wolfSSL_BIO_get_fp
+#define BIO_seek                        wolfSSL_BIO_seek
+#define BIO_write_filename              wolfSSL_BIO_write_filename
+#define BIO_set_mem_eof_return          wolfSSL_BIO_set_mem_eof_return
+
+#define BIO_find_type wolfSSL_BIO_find_type
+#define BIO_next      wolfSSL_BIO_next
+#define BIO_gets      wolfSSL_BIO_gets
+#define BIO_puts      wolfSSL_BIO_puts
+
+#define BIO_should_retry                wolfSSL_BIO_should_retry
+
+#define BIO_TYPE_FILE WOLFSSL_BIO_FILE
+#define BIO_TYPE_BIO  WOLFSSL_BIO_BIO
+#define BIO_TYPE_MEM  WOLFSSL_BIO_MEMORY
+#define BIO_TYPE_BASE64 WOLFSSL_BIO_BASE64
+
+#define BIO_vprintf wolfSSL_BIO_vprintf
+#define BIO_printf  wolfSSL_BIO_printf
+#define BIO_dump    wolfSSL_BIO_dump
+
+/* BIO info callback */
+#define BIO_CB_FREE   WOLFSSL_BIO_CB_FREE
+#define BIO_CB_READ   WOLFSSL_BIO_CB_READ
+#define BIO_CB_WRITE  WOLFSSL_BIO_CB_WRITE
+#define BIO_CB_PUTS   WOLFSSL_BIO_CB_PUTS
+#define BIO_CB_GETS   WOLFSSL_BIO_CB_GETS
+#define BIO_CB_CTRL   WOLFSSL_BIO_CB_CTRL
+#define BIO_CB_RETURN WOLFSSL_BIO_CB_RETURN
+
+#define BIO_set_callback         wolfSSL_BIO_set_callback
+#define BIO_get_callback         wolfSSL_BIO_get_callback
+#define BIO_set_callback_arg     wolfSSL_BIO_set_callback_arg
+#define BIO_get_callback_arg     wolfSSL_BIO_get_callback_arg
+
+/* BIO for 1.1.0 or later */
+#define BIO_set_init               wolfSSL_BIO_set_init
+#define BIO_get_data               wolfSSL_BIO_get_data
+#define BIO_set_data               wolfSSL_BIO_set_data
+#define BIO_get_shutdown           wolfSSL_BIO_get_shutdown
+#define BIO_set_shutdown           wolfSSL_BIO_set_shutdown
+
+#define BIO_clear_flags            wolfSSL_BIO_clear_flags
+#define BIO_set_ex_data            wolfSSL_BIO_set_ex_data
+#define BIO_get_ex_data            wolfSSL_BIO_get_ex_data
+
+/* helper to set specific retry/read flags */
+#define BIO_set_retry_read(bio)\
+    wolfSSL_BIO_set_flags((bio), WOLFSSL_BIO_FLAG_RETRY | WOLFSSL_BIO_FLAG_READ)
+#define BIO_set_retry_write(bio)\
+    wolfSSL_BIO_set_flags((bio), WOLFSSL_BIO_FLAG_RETRY | WOLFSSL_BIO_FLAG_WRITE)
+
+#define BIO_clear_retry_flags      wolfSSL_BIO_clear_retry_flags
+
+#define BIO_meth_new               wolfSSL_BIO_meth_new
+#define BIO_meth_set_write         wolfSSL_BIO_meth_set_write
+#define BIO_meth_free              wolfSSL_BIO_meth_free
+#define BIO_meth_set_write         wolfSSL_BIO_meth_set_write
+#define BIO_meth_set_read          wolfSSL_BIO_meth_set_read
+#define BIO_meth_set_puts          wolfSSL_BIO_meth_set_puts
+#define BIO_meth_set_gets          wolfSSL_BIO_meth_set_gets
+#define BIO_meth_set_ctrl          wolfSSL_BIO_meth_set_ctrl
+#define BIO_meth_set_create        wolfSSL_BIO_meth_set_create
+#define BIO_meth_set_destroy       wolfSSL_BIO_meth_set_destroy
+
+
+/* BIO CTRL */
+#define BIO_CTRL_RESET             1
+#define BIO_CTRL_EOF               2
+#define BIO_CTRL_INFO              3
+#define BIO_CTRL_PUSH              6
+#define BIO_CTRL_POP               7
+#define BIO_CTRL_GET_CLOSE         8
+#define BIO_CTRL_SET_CLOSE         9
+#define BIO_CTRL_PENDING           10
+#define BIO_CTRL_FLUSH             11
+#define BIO_CTRL_DUP               12
+#define BIO_CTRL_WPENDING          13
+
+#define BIO_C_SET_FILE_PTR              106
+#define BIO_C_GET_FILE_PTR              107
+#define BIO_C_SET_FILENAME              108
+#define BIO_C_SET_BUF_MEM               114
+#define BIO_C_GET_BUF_MEM_PTR           115
+#define BIO_C_FILE_SEEK                 128
+#define BIO_C_SET_BUF_MEM_EOF_RETURN    130
+#define BIO_C_SET_WRITE_BUF_SIZE        136
+#define BIO_C_MAKE_BIO_PAIR             138
+
+#define BIO_CTRL_DGRAM_QUERY_MTU   40
+
+#define BIO_NOCLOSE                0x00
+#define BIO_CLOSE                  0x01
+
+#define BIO_FP_WRITE               0x04
+
+
+#ifdef __cplusplus
+    }  /* extern "C" */
+#endif
+
+
+#endif /* WOLFSSL_BIO_H_ */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/bn.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/bn.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/bn.h	(revision 453)
@@ -0,0 +1,226 @@
+/* bn.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* bn.h for openssl */
+
+/*!
+    \file wolfssl/openssl/bn.h
+    \brief bn.h for openssl
+*/
+
+
+#ifndef WOLFSSL_BN_H_
+#define WOLFSSL_BN_H_
+
+#include <wolfssl/wolfcrypt/settings.h>
+#include <wolfssl/wolfcrypt/integer.h>
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+typedef struct WOLFSSL_BIGNUM {
+    int neg;        /* openssh deference */
+    void *internal; /* our big num */
+#ifdef WOLFSSL_SP_MATH
+    sp_int fp;
+#elif defined(USE_FAST_MATH) && !defined(HAVE_WOLF_BIGINT)
+    fp_int fp;
+#endif
+} WOLFSSL_BIGNUM;
+
+
+#define BN_ULONG WOLFSSL_BN_ULONG
+#define WOLFSSL_BN_ULONG mp_digit
+
+typedef struct WOLFSSL_BN_CTX WOLFSSL_BN_CTX;
+typedef struct WOLFSSL_BN_GENCB WOLFSSL_BN_GENCB;
+
+WOLFSSL_API WOLFSSL_BN_CTX* wolfSSL_BN_CTX_new(void);
+WOLFSSL_API void           wolfSSL_BN_CTX_init(WOLFSSL_BN_CTX*);
+WOLFSSL_API void           wolfSSL_BN_CTX_free(WOLFSSL_BN_CTX*);
+
+WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_BN_new(void);
+#if defined(USE_FAST_MATH) && !defined(HAVE_WOLF_BIGINT)
+WOLFSSL_API void           wolfSSL_BN_init(WOLFSSL_BIGNUM *);
+#endif
+WOLFSSL_API void           wolfSSL_BN_free(WOLFSSL_BIGNUM*);
+WOLFSSL_API void           wolfSSL_BN_clear_free(WOLFSSL_BIGNUM*);
+WOLFSSL_API void           wolfSSL_BN_clear(WOLFSSL_BIGNUM*);
+
+
+WOLFSSL_API int wolfSSL_BN_sub(WOLFSSL_BIGNUM*, const WOLFSSL_BIGNUM*,
+                             const WOLFSSL_BIGNUM*);
+WOLFSSL_API int wolfSSL_BN_mod(WOLFSSL_BIGNUM*, const WOLFSSL_BIGNUM*,
+                             const WOLFSSL_BIGNUM*, const WOLFSSL_BN_CTX*);
+WOLFSSL_API int wolfSSL_BN_mod_exp(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a,
+        const WOLFSSL_BIGNUM *p, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx);
+WOLFSSL_API int wolfSSL_BN_mod_mul(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a,
+        const WOLFSSL_BIGNUM *b, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx);
+WOLFSSL_API const WOLFSSL_BIGNUM* wolfSSL_BN_value_one(void);
+
+
+WOLFSSL_API int wolfSSL_BN_num_bytes(const WOLFSSL_BIGNUM*);
+WOLFSSL_API int wolfSSL_BN_num_bits(const WOLFSSL_BIGNUM*);
+
+WOLFSSL_API int wolfSSL_BN_is_zero(const WOLFSSL_BIGNUM*);
+WOLFSSL_API int wolfSSL_BN_is_one(const WOLFSSL_BIGNUM*);
+WOLFSSL_API int wolfSSL_BN_is_odd(const WOLFSSL_BIGNUM*);
+WOLFSSL_API int wolfSSL_BN_is_negative(const WOLFSSL_BIGNUM*);
+WOLFSSL_API int wolfSSL_BN_is_word(const WOLFSSL_BIGNUM*, WOLFSSL_BN_ULONG);
+
+WOLFSSL_API int wolfSSL_BN_cmp(const WOLFSSL_BIGNUM*, const WOLFSSL_BIGNUM*);
+
+WOLFSSL_API int wolfSSL_BN_bn2bin(const WOLFSSL_BIGNUM*, unsigned char*);
+WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_BN_bin2bn(const unsigned char*, int len,
+                                WOLFSSL_BIGNUM* ret);
+
+WOLFSSL_API int wolfSSL_mask_bits(WOLFSSL_BIGNUM*, int n);
+
+WOLFSSL_API int wolfSSL_BN_pseudo_rand(WOLFSSL_BIGNUM*, int bits, int top,
+        int bottom);
+WOLFSSL_API int wolfSSL_BN_rand(WOLFSSL_BIGNUM*, int bits, int top, int bottom);
+WOLFSSL_API int wolfSSL_BN_is_bit_set(const WOLFSSL_BIGNUM*, int n);
+WOLFSSL_API int wolfSSL_BN_hex2bn(WOLFSSL_BIGNUM**, const char* str);
+
+WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_BN_dup(const WOLFSSL_BIGNUM*);
+WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_BN_copy(WOLFSSL_BIGNUM*,
+                                            const WOLFSSL_BIGNUM*);
+
+WOLFSSL_API int   wolfSSL_BN_dec2bn(WOLFSSL_BIGNUM**, const char* str);
+WOLFSSL_API char* wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM*);
+
+WOLFSSL_API int wolfSSL_BN_lshift(WOLFSSL_BIGNUM*, const WOLFSSL_BIGNUM*, int);
+WOLFSSL_API int wolfSSL_BN_add_word(WOLFSSL_BIGNUM*, WOLFSSL_BN_ULONG);
+WOLFSSL_API int wolfSSL_BN_set_bit(WOLFSSL_BIGNUM*, int);
+WOLFSSL_API int wolfSSL_BN_clear_bit(WOLFSSL_BIGNUM*, int);
+WOLFSSL_API int wolfSSL_BN_set_word(WOLFSSL_BIGNUM*, WOLFSSL_BN_ULONG);
+WOLFSSL_API unsigned long wolfSSL_BN_get_word(const WOLFSSL_BIGNUM*);
+
+WOLFSSL_API int wolfSSL_BN_add(WOLFSSL_BIGNUM*, WOLFSSL_BIGNUM*,
+                               WOLFSSL_BIGNUM*);
+WOLFSSL_API int wolfSSL_BN_mod_add(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a,
+                                   const WOLFSSL_BIGNUM *b, const WOLFSSL_BIGNUM *m,
+                                   WOLFSSL_BN_CTX *ctx);
+WOLFSSL_API char *wolfSSL_BN_bn2hex(const WOLFSSL_BIGNUM*);
+WOLFSSL_API int wolfSSL_BN_is_prime_ex(const WOLFSSL_BIGNUM*, int,
+                                       WOLFSSL_BN_CTX*, WOLFSSL_BN_GENCB*);
+WOLFSSL_API WOLFSSL_BN_ULONG wolfSSL_BN_mod_word(const WOLFSSL_BIGNUM*,
+                                                 WOLFSSL_BN_ULONG);
+#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)
+    WOLFSSL_API int wolfSSL_BN_print_fp(XFILE, const WOLFSSL_BIGNUM*);
+#endif
+WOLFSSL_API int wolfSSL_BN_rshift(WOLFSSL_BIGNUM*, const WOLFSSL_BIGNUM*, int);
+WOLFSSL_API WOLFSSL_BIGNUM *wolfSSL_BN_CTX_get(WOLFSSL_BN_CTX *ctx);
+WOLFSSL_API void wolfSSL_BN_CTX_start(WOLFSSL_BN_CTX *ctx);
+WOLFSSL_API WOLFSSL_BIGNUM *wolfSSL_BN_mod_inverse(WOLFSSL_BIGNUM*, WOLFSSL_BIGNUM*,
+                                        const WOLFSSL_BIGNUM*, WOLFSSL_BN_CTX *ctx);
+
+typedef WOLFSSL_BIGNUM BIGNUM;
+typedef WOLFSSL_BN_CTX BN_CTX;
+typedef WOLFSSL_BN_GENCB BN_GENCB;
+
+#define BN_CTX_new        wolfSSL_BN_CTX_new
+#define BN_CTX_init       wolfSSL_BN_CTX_init
+#define BN_CTX_free       wolfSSL_BN_CTX_free
+
+#define BN_new        wolfSSL_BN_new
+#define BN_init       wolfSSL_BN_init
+#define BN_free       wolfSSL_BN_free
+#define BN_clear_free wolfSSL_BN_clear_free
+#define BN_clear      wolfSSL_BN_clear
+
+#define BN_num_bytes wolfSSL_BN_num_bytes
+#define BN_num_bits  wolfSSL_BN_num_bits
+
+#define BN_is_zero  wolfSSL_BN_is_zero
+#define BN_is_one   wolfSSL_BN_is_one
+#define BN_is_odd   wolfSSL_BN_is_odd
+#define BN_is_negative wolfSSL_BN_is_negative
+#define BN_is_word  wolfSSL_BN_is_word
+
+#define BN_cmp    wolfSSL_BN_cmp
+
+#define BN_bn2bin  wolfSSL_BN_bn2bin
+#define BN_bin2bn  wolfSSL_BN_bin2bn
+
+#define BN_mod       wolfSSL_BN_mod
+#define BN_mod_exp   wolfSSL_BN_mod_exp
+#define BN_mod_mul   wolfSSL_BN_mod_mul
+#define BN_sub       wolfSSL_BN_sub
+#define BN_value_one wolfSSL_BN_value_one
+
+#define BN_mask_bits wolfSSL_mask_bits
+
+#define BN_pseudo_rand wolfSSL_BN_pseudo_rand
+#define BN_rand        wolfSSL_BN_rand
+#define BN_is_bit_set  wolfSSL_BN_is_bit_set
+#define BN_hex2bn      wolfSSL_BN_hex2bn
+
+#define BN_dup  wolfSSL_BN_dup
+#define BN_copy wolfSSL_BN_copy
+
+#define BN_get_word wolfSSL_BN_get_word
+#define BN_set_word wolfSSL_BN_set_word
+
+#define BN_dec2bn wolfSSL_BN_dec2bn
+#define BN_bn2dec wolfSSL_BN_bn2dec
+#define BN_bn2hex wolfSSL_BN_bn2hex
+
+#define BN_lshift wolfSSL_BN_lshift
+#define BN_add_word wolfSSL_BN_add_word
+#define BN_add wolfSSL_BN_add
+#define BN_mod_add wolfSSL_BN_mod_add
+#define BN_set_word wolfSSL_BN_set_word
+#define BN_set_bit wolfSSL_BN_set_bit
+#define BN_clear_bit wolfSSL_BN_clear_bit
+
+
+#define BN_is_prime_ex wolfSSL_BN_is_prime_ex
+#define BN_print_fp wolfSSL_BN_print_fp
+#define BN_rshift wolfSSL_BN_rshift
+#define BN_mod_word wolfSSL_BN_mod_word
+
+#define BN_CTX_get wolfSSL_BN_CTX_get
+#define BN_CTX_start wolfSSL_BN_CTX_start
+
+#define BN_mod_inverse wolfSSL_BN_mod_inverse
+
+#define BN_set_flags(x1, x2)
+
+#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L
+#define BN_get_rfc2409_prime_768   wolfSSL_DH_768_prime
+#define BN_get_rfc2409_prime_1024  wolfSSL_DH_1024_prime
+#define BN_get_rfc3526_prime_1536  wolfSSL_DH_1536_prime
+#define BN_get_rfc3526_prime_2048  wolfSSL_DH_2048_prime
+#define BN_get_rfc3526_prime_3072  wolfSSL_DH_3072_prime
+#define BN_get_rfc3526_prime_4096  wolfSSL_DH_4096_prime
+#define BN_get_rfc3526_prime_6144  wolfSSL_DH_6144_prime
+#define BN_get_rfc3526_prime_8192  wolfSSL_DH_8192_prime
+#endif
+
+
+#ifdef __cplusplus
+    }  /* extern "C" */
+#endif
+
+
+#endif /* WOLFSSL__H_ */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/buffer.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/buffer.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/buffer.h	(revision 453)
@@ -0,0 +1,47 @@
+/* buffer.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifndef WOLFSSL_BUFFER_H_
+#define WOLFSSL_BUFFER_H_
+
+#include <wolfssl/wolfcrypt/settings.h>
+#include <wolfssl/openssl/ssl.h>
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+
+WOLFSSL_API WOLFSSL_BUF_MEM* wolfSSL_BUF_MEM_new(void);
+WOLFSSL_API int wolfSSL_BUF_MEM_grow(WOLFSSL_BUF_MEM* buf, size_t len);
+WOLFSSL_API void wolfSSL_BUF_MEM_free(WOLFSSL_BUF_MEM* buf);
+
+
+#define BUF_MEM_new  wolfSSL_BUF_MEM_new
+#define BUF_MEM_grow wolfSSL_BUF_MEM_grow
+#define BUF_MEM_free wolfSSL_BUF_MEM_free
+
+#ifdef __cplusplus
+    }  /* extern "C" */
+#endif
+
+#endif /* WOLFSSL_BUFFER_H_ */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/conf.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/conf.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/conf.h	(revision 453)
@@ -0,0 +1,48 @@
+/* conf.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* conf.h for openSSL */
+
+#ifndef WOLFSSL_conf_H_
+#define WOLFSSL_conf_H_
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+struct WOLFSSL_CONF_VALUE {
+    char *section;
+    char *name;
+    char *value;
+};
+
+struct WOLFSSL_INIT_SETTINGS {
+    char* appname;
+};
+
+typedef struct WOLFSSL_CONF_VALUE CONF_VALUE;
+typedef struct WOLFSSL_INIT_SETTINGS OPENSSL_INIT_SETTINGS;
+
+#ifdef  __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* WOLFSSL_conf_H_ */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/crypto.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/crypto.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/crypto.h	(revision 453)
@@ -0,0 +1,91 @@
+/* crypto.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* crypto.h for openSSL */
+
+#ifndef WOLFSSL_CRYPTO_H_
+#define WOLFSSL_CRYPTO_H_
+
+#include <wolfssl/openssl/opensslv.h>
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifdef WOLFSSL_PREFIX
+#include "prefix_crypto.h"
+#endif
+
+
+WOLFSSL_API const char*   wolfSSLeay_version(int type);
+WOLFSSL_API unsigned long wolfSSLeay(void);
+WOLFSSL_API unsigned long wolfSSL_OpenSSL_version_num(void);
+
+#ifdef OPENSSL_EXTRA
+WOLFSSL_API void wolfSSL_OPENSSL_free(void*);
+WOLFSSL_API void *wolfSSL_OPENSSL_malloc(size_t a);
+#endif
+
+#define CRYPTO_THREADID void
+
+#define SSLeay_version wolfSSLeay_version
+#define SSLeay wolfSSLeay
+#define OpenSSL_version_num wolfSSL_OpenSSL_version_num
+
+#ifdef WOLFSSL_QT
+    #define SSLEAY_VERSION 0x10001000L
+#else
+    #define SSLEAY_VERSION 0x0090600fL
+#endif
+#define SSLEAY_VERSION_NUMBER SSLEAY_VERSION
+#define CRYPTO_lock wc_LockMutex_ex
+
+/* this function was used to set the default malloc, free, and realloc */
+#define CRYPTO_malloc_init() 0 /* CRYPTO_malloc_init is not needed */
+
+#define OPENSSL_free wolfSSL_OPENSSL_free
+#define OPENSSL_malloc wolfSSL_OPENSSL_malloc
+
+#ifdef WOLFSSL_QT
+    #define OPENSSL_INIT_ADD_ALL_CIPHERS    0x00000004L
+    #define OPENSSL_INIT_ADD_ALL_DIGESTS    0x00000008L
+    #define OPENSSL_INIT_LOAD_CONFIG        0x00000040L
+#endif
+
+#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \
+    defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA)
+#define CRYPTO_set_mem_ex_functions      wolfSSL_CRYPTO_set_mem_ex_functions
+#define FIPS_mode                        wolfSSL_FIPS_mode
+#define FIPS_mode_set                    wolfSSL_FIPS_mode_set
+typedef struct CRYPTO_EX_DATA            CRYPTO_EX_DATA;
+typedef void (CRYPTO_free_func)(void*parent, void*ptr, CRYPTO_EX_DATA *ad, int idx,
+        long argl, void* argp);
+#define CRYPTO_THREADID_set_callback wolfSSL_THREADID_set_callback
+#define CRYPTO_THREADID_set_numeric wolfSSL_THREADID_set_numeric
+
+#define CRYPTO_r_lock wc_LockMutex_ex
+#define CRYPTO_unlock wc_LockMutex_ex
+
+#define CRYPTO_THREAD_lock wc_LockMutex
+#define CRYPTO_THREAD_r_lock wc_LockMutex
+#define CRYPTO_THREAD_unlock wc_UnLockMutex
+
+#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
+
+#endif /* header */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/des.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/des.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/des.h	(revision 453)
@@ -0,0 +1,115 @@
+/* des.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+/*  des.h defines mini des openssl compatibility layer
+ *
+ */
+
+
+#ifndef WOLFSSL_DES_H_
+#define WOLFSSL_DES_H_
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifndef NO_DES3
+
+#ifdef WOLFSSL_PREFIX
+#include "prefix_des.h"
+#endif
+
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+typedef unsigned char WOLFSSL_DES_cblock[8];
+typedef /* const */ WOLFSSL_DES_cblock WOLFSSL_const_DES_cblock;
+typedef WOLFSSL_DES_cblock WOLFSSL_DES_key_schedule;
+typedef unsigned int WOLFSSL_DES_LONG;
+
+
+enum {
+    DES_ENCRYPT = 1,
+    DES_DECRYPT = 0
+};
+
+
+WOLFSSL_API int wolfSSL_DES_is_weak_key(WOLFSSL_const_DES_cblock* key);
+WOLFSSL_API WOLFSSL_DES_LONG wolfSSL_DES_cbc_cksum(const unsigned char* in,
+            WOLFSSL_DES_cblock* out, long length, WOLFSSL_DES_key_schedule* sc,
+            WOLFSSL_const_DES_cblock* iv);
+WOLFSSL_API int wolfSSL_DES_set_key(WOLFSSL_const_DES_cblock* myDes,
+                                               WOLFSSL_DES_key_schedule* key);
+WOLFSSL_API int wolfSSL_DES_set_key_checked(WOLFSSL_const_DES_cblock* myDes,
+                                               WOLFSSL_DES_key_schedule* key);
+WOLFSSL_API void wolfSSL_DES_set_key_unchecked(WOLFSSL_const_DES_cblock*,
+                                             WOLFSSL_DES_key_schedule*);
+WOLFSSL_API int  wolfSSL_DES_key_sched(WOLFSSL_const_DES_cblock* key,
+                                     WOLFSSL_DES_key_schedule* schedule);
+WOLFSSL_API void wolfSSL_DES_cbc_encrypt(const unsigned char* input,
+                     unsigned char* output, long length,
+                     WOLFSSL_DES_key_schedule* schedule, WOLFSSL_DES_cblock* ivec,
+                     int enc);
+WOLFSSL_API void wolfSSL_DES_ede3_cbc_encrypt(const unsigned char* input,
+                                      unsigned char* output, long sz,
+                                      WOLFSSL_DES_key_schedule* ks1,
+                                      WOLFSSL_DES_key_schedule* ks2,
+                                      WOLFSSL_DES_key_schedule* ks3,
+                                      WOLFSSL_DES_cblock* ivec, int enc);
+WOLFSSL_API void wolfSSL_DES_ncbc_encrypt(const unsigned char* input,
+                      unsigned char* output, long length,
+                      WOLFSSL_DES_key_schedule* schedule,
+                      WOLFSSL_DES_cblock* ivec, int enc);
+
+WOLFSSL_API void wolfSSL_DES_set_odd_parity(WOLFSSL_DES_cblock*);
+WOLFSSL_API void wolfSSL_DES_ecb_encrypt(WOLFSSL_DES_cblock*, WOLFSSL_DES_cblock*,
+                                       WOLFSSL_DES_key_schedule*, int);
+WOLFSSL_API int wolfSSL_DES_check_key_parity(WOLFSSL_DES_cblock*);
+
+
+typedef WOLFSSL_DES_cblock DES_cblock;
+typedef WOLFSSL_const_DES_cblock const_DES_cblock;
+typedef WOLFSSL_DES_key_schedule DES_key_schedule;
+typedef WOLFSSL_DES_LONG DES_LONG;
+
+#define DES_check_key(x) /* Define WOLFSSL_CHECK_DESKEY to check key */
+#define DES_is_weak_key       wolfSSL_DES_is_weak_key
+#define DES_set_key           wolfSSL_DES_set_key
+#define DES_set_key_checked   wolfSSL_DES_set_key_checked
+#define DES_set_key_unchecked wolfSSL_DES_set_key_unchecked
+#define DES_key_sched         wolfSSL_DES_key_sched
+#define DES_cbc_encrypt       wolfSSL_DES_cbc_encrypt
+#define DES_ncbc_encrypt      wolfSSL_DES_ncbc_encrypt
+#define DES_set_odd_parity    wolfSSL_DES_set_odd_parity
+#define DES_ecb_encrypt       wolfSSL_DES_ecb_encrypt
+#define DES_ede3_cbc_encrypt  wolfSSL_DES_ede3_cbc_encrypt
+#define DES_cbc_cksum         wolfSSL_DES_cbc_cksum
+#define DES_check_key_parity  wolfSSL_DES_check_key_parity
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* NO_DES3 */
+
+#endif /* WOLFSSL_DES_H_ */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/dh.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/dh.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/dh.h	(revision 453)
@@ -0,0 +1,115 @@
+/* dh.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* dh.h for openSSL */
+
+
+#ifndef WOLFSSL_DH_H_
+#define WOLFSSL_DH_H_
+
+#include <wolfssl/openssl/bn.h>
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+#ifndef WOLFSSL_DH_TYPE_DEFINED /* guard on redeclaration */
+typedef struct WOLFSSL_DH            WOLFSSL_DH;
+#define WOLFSSL_DH_TYPE_DEFINED
+#endif
+
+typedef WOLFSSL_DH                   DH;
+
+struct WOLFSSL_DH {
+    WOLFSSL_BIGNUM* p;
+    WOLFSSL_BIGNUM* g;
+    WOLFSSL_BIGNUM* q;
+    WOLFSSL_BIGNUM* pub_key;      /* openssh deference g^x */
+    WOLFSSL_BIGNUM* priv_key;     /* openssh deference x   */
+    void*          internal;     /* our DH */
+    char           inSet;        /* internal set from external ? */
+    char           exSet;        /* external set from internal ? */
+    /*added for lighttpd openssl compatibility, go back and add a getter in
+     * lighttpd src code.
+     */
+     int length;
+};
+
+WOLFSSL_API WOLFSSL_DH *wolfSSL_d2i_DHparams(WOLFSSL_DH **dh,
+                                         const unsigned char **pp, long length);
+WOLFSSL_API int wolfSSL_i2d_DHparams(const WOLFSSL_DH *dh, unsigned char **out);
+WOLFSSL_API WOLFSSL_DH* wolfSSL_DH_new(void);
+WOLFSSL_API void        wolfSSL_DH_free(WOLFSSL_DH*);
+
+WOLFSSL_API int wolfSSL_DH_check(const WOLFSSL_DH *dh, int *codes);
+WOLFSSL_API int wolfSSL_DH_size(WOLFSSL_DH*);
+WOLFSSL_API int wolfSSL_DH_generate_key(WOLFSSL_DH*);
+WOLFSSL_API int wolfSSL_DH_compute_key(unsigned char* key, WOLFSSL_BIGNUM* pub,
+                                     WOLFSSL_DH*);
+WOLFSSL_API int wolfSSL_DH_LoadDer(WOLFSSL_DH*, const unsigned char*, int sz);
+WOLFSSL_API int wolfSSL_DH_set0_pqg(WOLFSSL_DH*, WOLFSSL_BIGNUM*,
+    WOLFSSL_BIGNUM*, WOLFSSL_BIGNUM*);
+
+#define DH_new  wolfSSL_DH_new
+#define DH_free wolfSSL_DH_free
+
+#define d2i_DHparams    wolfSSL_d2i_DHparams
+#define i2d_DHparams    wolfSSL_i2d_DHparams
+#define DH_check        wolfSSL_DH_check
+
+#define DH_size         wolfSSL_DH_size
+#define DH_generate_key wolfSSL_DH_generate_key
+#define DH_compute_key  wolfSSL_DH_compute_key
+#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L
+#define DH_set0_pqg     wolfSSL_DH_set0_pqg
+#endif
+#define DH_bits(x)      (BN_num_bits(x->p))
+
+#define DH_GENERATOR_2                  2
+#define DH_CHECK_P_NOT_PRIME            0x01
+#define DH_CHECK_P_NOT_SAFE_PRIME       0x02
+#define DH_NOT_SUITABLE_GENERATOR       0x08
+
+/* Temporary values for wolfSSL_DH_Check*/
+#define DH_CHECK_INVALID_Q_VALUE        0x10
+#define DH_CHECK_Q_NOT_PRIME            0x11
+/* end temp */
+
+/* for pre 1.1.0 */
+#define get_rfc2409_prime_768      wolfSSL_DH_768_prime
+#define get_rfc2409_prime_1024     wolfSSL_DH_1024_prime
+#define get_rfc3526_prime_1536     wolfSSL_DH_1536_prime
+#define get_rfc3526_prime_2048     wolfSSL_DH_2048_prime
+#define get_rfc3526_prime_3072     wolfSSL_DH_3072_prime
+#define get_rfc3526_prime_4096     wolfSSL_DH_4096_prime
+#define get_rfc3526_prime_6144     wolfSSL_DH_6144_prime
+#define get_rfc3526_prime_8192     wolfSSL_DH_8192_prime
+
+#ifdef __cplusplus
+    }  /* extern "C" */
+#endif
+
+#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL)
+#define DH_generate_parameters    wolfSSL_DH_generate_parameters
+#define DH_generate_parameters_ex wolfSSL_DH_generate_parameters_ex
+#endif /* OPENSSL_ALL || HAVE_STUNNEL */
+
+#endif /* WOLFSSL_DH_H_ */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/dsa.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/dsa.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/dsa.h	(revision 453)
@@ -0,0 +1,113 @@
+/* dsa.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* dsa.h for openSSL */
+
+
+#ifndef WOLFSSL_DSA_H_
+#define WOLFSSL_DSA_H_
+
+#include <wolfssl/openssl/bn.h>
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+typedef struct WOLFSSL_DSA_SIG {
+    WOLFSSL_BIGNUM *r;
+    WOLFSSL_BIGNUM *s;
+} WOLFSSL_DSA_SIG;
+
+#ifndef WOLFSSL_DSA_TYPE_DEFINED /* guard on redeclaration */
+typedef struct WOLFSSL_DSA            WOLFSSL_DSA;
+#define WOLFSSL_DSA_TYPE_DEFINED
+#endif
+
+typedef WOLFSSL_DSA                   DSA;
+
+struct WOLFSSL_DSA {
+    WOLFSSL_BIGNUM* p;
+    WOLFSSL_BIGNUM* q;
+    WOLFSSL_BIGNUM* g;
+    WOLFSSL_BIGNUM* pub_key;      /* our y */
+    WOLFSSL_BIGNUM* priv_key;     /* our x */
+    void*          internal;     /* our Dsa Key */
+    char           inSet;        /* internal set from external ? */
+    char           exSet;        /* external set from internal ? */
+};
+
+
+WOLFSSL_API WOLFSSL_DSA* wolfSSL_DSA_new(void);
+WOLFSSL_API void wolfSSL_DSA_free(WOLFSSL_DSA*);
+
+WOLFSSL_API int wolfSSL_DSA_generate_key(WOLFSSL_DSA*);
+
+typedef void (*WOLFSSL_BN_CB)(int i, int j, void* exArg);
+WOLFSSL_API WOLFSSL_DSA* wolfSSL_DSA_generate_parameters(int bits,
+                   unsigned char* seed, int seedLen, int* counterRet,
+                   unsigned long* hRet, WOLFSSL_BN_CB cb, void* CBArg);
+WOLFSSL_API int wolfSSL_DSA_generate_parameters_ex(WOLFSSL_DSA*, int bits,
+                   unsigned char* seed, int seedLen, int* counterRet,
+                   unsigned long* hRet, void* cb);
+
+WOLFSSL_API int wolfSSL_DSA_LoadDer(WOLFSSL_DSA*, const unsigned char*, int sz);
+
+WOLFSSL_API int wolfSSL_DSA_LoadDer_ex(WOLFSSL_DSA*, const unsigned char*,
+                                       int sz, int opt);
+
+WOLFSSL_API int wolfSSL_DSA_do_sign(const unsigned char* d,
+                                    unsigned char* sigRet, WOLFSSL_DSA* dsa);
+
+WOLFSSL_API int wolfSSL_DSA_do_verify(const unsigned char* d,
+                                      unsigned char* sig,
+                                      WOLFSSL_DSA* dsa, int *dsacheck);
+
+WOLFSSL_API WOLFSSL_DSA_SIG* wolfSSL_DSA_SIG_new(void);
+WOLFSSL_API void wolfSSL_DSA_SIG_free(WOLFSSL_DSA_SIG *sig);
+WOLFSSL_API WOLFSSL_DSA_SIG* wolfSSL_DSA_do_sign_ex(const unsigned char* digest,
+                                                    int outLen, WOLFSSL_DSA* dsa);
+WOLFSSL_API int wolfSSL_DSA_do_verify_ex(const unsigned char* digest, int digest_len,
+                                         WOLFSSL_DSA_SIG* sig, WOLFSSL_DSA* dsa);
+
+#define WOLFSSL_DSA_LOAD_PRIVATE 1
+#define WOLFSSL_DSA_LOAD_PUBLIC  2
+
+#define DSA_new wolfSSL_DSA_new
+#define DSA_free wolfSSL_DSA_free
+
+#define DSA_LoadDer                wolfSSL_DSA_LoadDer
+#define DSA_generate_key           wolfSSL_DSA_generate_key
+#define DSA_generate_parameters    wolfSSL_DSA_generate_parameters
+#define DSA_generate_parameters_ex wolfSSL_DSA_generate_parameters_ex
+
+#define DSA_SIG_new                wolfSSL_DSA_SIG_new
+#define DSA_SIG_free               wolfSSL_DSA_SIG_free
+#define DSA_do_sign                wolfSSL_DSA_do_sign_ex
+#define DSA_do_verify              wolfSSL_DSA_do_verify_ex
+
+
+#define DSA_SIG                    WOLFSSL_DSA_SIG
+
+#ifdef __cplusplus
+    }  /* extern "C" */ 
+#endif
+
+#endif /* header */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ec.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ec.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ec.h	(revision 453)
@@ -0,0 +1,323 @@
+/* ec.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* ec.h for openssl */
+
+#ifndef WOLFSSL_EC_H_
+#define WOLFSSL_EC_H_
+
+#include <wolfssl/openssl/bn.h>
+#include <wolfssl/wolfcrypt/ecc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Map OpenSSL NID value */
+enum {
+    POINT_CONVERSION_COMPRESSED = 2,
+    POINT_CONVERSION_UNCOMPRESSED = 4,
+
+#ifdef HAVE_ECC
+    /* Use OpenSSL NIDs. NIDs can be mapped to ecc_curve_id enum values by
+        calling NIDToEccEnum() in ssl.c */
+    NID_X9_62_prime192v1 = 409,
+    NID_X9_62_prime192v2 = 410,
+    NID_X9_62_prime192v3 = 411,
+    NID_X9_62_prime239v1 = 412,
+    NID_X9_62_prime239v2 = 413,
+    NID_X9_62_prime239v3 = 414,
+    NID_X9_62_prime256v1 = 415,
+    NID_secp112r1 = 704,
+    NID_secp112r2 = 705,
+    NID_secp128r1 = 706,
+    NID_secp128r2 = 707,
+    NID_secp160r1 = 709,
+    NID_secp160r2 = 710,
+    NID_secp224r1 = 713,
+    NID_secp384r1 = 715,
+    NID_secp521r1 = 716,
+    NID_secp160k1 = 708,
+    NID_secp192k1 = 711,
+    NID_secp224k1 = 712,
+    NID_secp256k1 = 714,
+    NID_brainpoolP160r1 = 921,
+    NID_brainpoolP192r1 = 923,
+    NID_brainpoolP224r1 = 925,
+    NID_brainpoolP256r1 = 927,
+    NID_brainpoolP320r1 = 929,
+    NID_brainpoolP384r1 = 931,
+    NID_brainpoolP512r1 = 933,
+#endif
+
+    OPENSSL_EC_NAMED_CURVE  = 0x001
+};
+
+#ifndef WOLFSSL_EC_TYPE_DEFINED /* guard on redeclaration */
+typedef struct WOLFSSL_EC_KEY         WOLFSSL_EC_KEY;
+typedef struct WOLFSSL_EC_POINT       WOLFSSL_EC_POINT;
+typedef struct WOLFSSL_EC_GROUP       WOLFSSL_EC_GROUP;
+typedef struct WOLFSSL_EC_BUILTIN_CURVE WOLFSSL_EC_BUILTIN_CURVE;
+/* WOLFSSL_EC_METHOD is just an alias of WOLFSSL_EC_GROUP for now */
+typedef struct WOLFSSL_EC_GROUP       WOLFSSL_EC_METHOD;
+#define WOLFSSL_EC_TYPE_DEFINED
+#endif
+
+typedef WOLFSSL_EC_KEY                EC_KEY;
+typedef WOLFSSL_EC_GROUP              EC_GROUP;
+typedef WOLFSSL_EC_GROUP              EC_METHOD;
+typedef WOLFSSL_EC_POINT              EC_POINT;
+typedef WOLFSSL_EC_BUILTIN_CURVE      EC_builtin_curve;
+
+struct WOLFSSL_EC_POINT {
+    WOLFSSL_BIGNUM *X;
+    WOLFSSL_BIGNUM *Y;
+    WOLFSSL_BIGNUM *Z;
+
+    void*          internal;     /* our ECC point */
+    char           inSet;        /* internal set from external ? */
+    char           exSet;        /* external set from internal ? */
+};
+
+struct WOLFSSL_EC_GROUP {
+    int curve_idx; /* index of curve, used by WolfSSL as reference */
+    int curve_nid; /* NID of curve, used by OpenSSL/OpenSSH as reference */
+    int curve_oid; /* OID of curve, used by OpenSSL/OpenSSH as reference */
+};
+
+struct WOLFSSL_EC_KEY {
+    WOLFSSL_EC_GROUP *group;
+    WOLFSSL_EC_POINT *pub_key;
+    WOLFSSL_BIGNUM *priv_key;
+
+    void*          internal;     /* our ECC Key */
+    char           inSet;        /* internal set from external ? */
+    char           exSet;        /* external set from internal ? */
+    char           form;         /* Either POINT_CONVERSION_UNCOMPRESSED or
+                                  * POINT_CONVERSION_COMPRESSED */
+};
+
+struct WOLFSSL_EC_BUILTIN_CURVE {
+    int nid;
+    const char *comment;
+};
+
+#define WOLFSSL_EC_KEY_LOAD_PRIVATE 1
+#define WOLFSSL_EC_KEY_LOAD_PUBLIC  2
+
+WOLFSSL_API
+size_t wolfSSL_EC_get_builtin_curves(WOLFSSL_EC_BUILTIN_CURVE *r,size_t nitems);
+
+WOLFSSL_API
+WOLFSSL_EC_KEY *wolfSSL_EC_KEY_dup(const WOLFSSL_EC_KEY *src);
+
+WOLFSSL_API
+int wolfSSL_ECPoint_i2d(const WOLFSSL_EC_GROUP *curve,
+                        const WOLFSSL_EC_POINT *p,
+                        unsigned char *out, unsigned int *len);
+WOLFSSL_API
+int wolfSSL_ECPoint_d2i(unsigned char *in, unsigned int len,
+                        const WOLFSSL_EC_GROUP *curve, WOLFSSL_EC_POINT *p);
+WOLFSSL_API
+size_t wolfSSL_EC_POINT_point2oct(const WOLFSSL_EC_GROUP *group,
+                                  const WOLFSSL_EC_POINT *p,
+                                  char form,
+                                  byte *buf, size_t len, WOLFSSL_BN_CTX *ctx);
+WOLFSSL_API
+int wolfSSL_EC_POINT_oct2point(const WOLFSSL_EC_GROUP *group,
+                               WOLFSSL_EC_POINT *p, const unsigned char *buf,
+                               size_t len, WOLFSSL_BN_CTX *ctx);
+WOLFSSL_API
+int wolfSSL_i2o_ECPublicKey(const WOLFSSL_EC_KEY *in, unsigned char **out);
+WOLFSSL_API
+void wolfSSL_EC_KEY_set_conv_form(WOLFSSL_EC_KEY *eckey, char form);
+WOLFSSL_API
+WOLFSSL_BIGNUM *wolfSSL_EC_POINT_point2bn(const WOLFSSL_EC_GROUP *group,
+                                          const WOLFSSL_EC_POINT *p,
+                                          char form,
+                                          WOLFSSL_BIGNUM *in, WOLFSSL_BN_CTX *ctx);
+
+WOLFSSL_API
+int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key,
+                           const unsigned char* der, int derSz);
+WOLFSSL_API
+int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key,
+                              const unsigned char* der, int derSz, int opt);
+WOLFSSL_API
+void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key);
+WOLFSSL_API
+WOLFSSL_EC_POINT *wolfSSL_EC_KEY_get0_public_key(const WOLFSSL_EC_KEY *key);
+WOLFSSL_API
+const WOLFSSL_EC_GROUP *wolfSSL_EC_KEY_get0_group(const WOLFSSL_EC_KEY *key);
+WOLFSSL_API
+int wolfSSL_EC_KEY_set_private_key(WOLFSSL_EC_KEY *key,
+                                   const WOLFSSL_BIGNUM *priv_key);
+WOLFSSL_API
+WOLFSSL_BIGNUM *wolfSSL_EC_KEY_get0_private_key(const WOLFSSL_EC_KEY *key);
+WOLFSSL_API
+WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_by_curve_name(int nid);
+WOLFSSL_API const char* wolfSSL_EC_curve_nid2nist(int nid);
+WOLFSSL_API
+WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new(void);
+WOLFSSL_API
+int wolfSSL_EC_KEY_set_group(WOLFSSL_EC_KEY *key, WOLFSSL_EC_GROUP *group);
+WOLFSSL_API
+int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key);
+WOLFSSL_API
+void wolfSSL_EC_KEY_set_asn1_flag(WOLFSSL_EC_KEY *key, int asn1_flag);
+WOLFSSL_API
+int wolfSSL_EC_KEY_set_public_key(WOLFSSL_EC_KEY *key,
+                                  const WOLFSSL_EC_POINT *pub);
+WOLFSSL_API int wolfSSL_ECDSA_size(const WOLFSSL_EC_KEY *key);
+WOLFSSL_API int wolfSSL_ECDSA_sign(int type, const unsigned char *digest,
+                                   int digestSz, unsigned char *sig,
+                                   unsigned int *sigSz, WOLFSSL_EC_KEY *key);
+WOLFSSL_API
+void wolfSSL_EC_GROUP_set_asn1_flag(WOLFSSL_EC_GROUP *group, int flag);
+WOLFSSL_API
+WOLFSSL_EC_GROUP *wolfSSL_EC_GROUP_new_by_curve_name(int nid);
+WOLFSSL_API
+int wolfSSL_EC_GROUP_cmp(const WOLFSSL_EC_GROUP *a, const WOLFSSL_EC_GROUP *b,
+                         WOLFSSL_BN_CTX *ctx);
+WOLFSSL_API
+int wolfSSL_EC_GROUP_get_curve_name(const WOLFSSL_EC_GROUP *group);
+WOLFSSL_API
+int wolfSSL_EC_GROUP_get_degree(const WOLFSSL_EC_GROUP *group);
+WOLFSSL_API
+int wolfSSL_EC_GROUP_get_order(const WOLFSSL_EC_GROUP *group,
+                               WOLFSSL_BIGNUM *order, WOLFSSL_BN_CTX *ctx);
+WOLFSSL_API
+int wolfSSL_EC_GROUP_order_bits(const WOLFSSL_EC_GROUP *group);
+WOLFSSL_API
+void wolfSSL_EC_GROUP_free(WOLFSSL_EC_GROUP *group);
+WOLFSSL_API
+const WOLFSSL_EC_METHOD* wolfSSL_EC_GROUP_method_of(
+                                                const WOLFSSL_EC_GROUP *group);
+WOLFSSL_API
+int wolfSSL_EC_METHOD_get_field_type(const WOLFSSL_EC_METHOD *meth);
+WOLFSSL_API
+WOLFSSL_EC_POINT *wolfSSL_EC_POINT_new(const WOLFSSL_EC_GROUP *group);
+WOLFSSL_API
+int wolfSSL_EC_POINT_get_affine_coordinates_GFp(const WOLFSSL_EC_GROUP *group,
+                                                const WOLFSSL_EC_POINT *p,
+                                                WOLFSSL_BIGNUM *x,
+                                                WOLFSSL_BIGNUM *y,
+                                                WOLFSSL_BN_CTX *ctx);
+WOLFSSL_API
+int wolfSSL_EC_POINT_set_affine_coordinates_GFp(const WOLFSSL_EC_GROUP *group,
+                                                WOLFSSL_EC_POINT *point,
+                                                const WOLFSSL_BIGNUM *x,
+                                                const WOLFSSL_BIGNUM *y,
+                                                WOLFSSL_BN_CTX *ctx);
+WOLFSSL_API
+int wolfSSL_EC_POINT_mul(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r,
+                         const WOLFSSL_BIGNUM *n,
+                         const WOLFSSL_EC_POINT *q, const WOLFSSL_BIGNUM *m,
+                         WOLFSSL_BN_CTX *ctx);
+WOLFSSL_API
+void wolfSSL_EC_POINT_clear_free(WOLFSSL_EC_POINT *point);
+WOLFSSL_API
+int wolfSSL_EC_POINT_cmp(const WOLFSSL_EC_GROUP *group,
+                         const WOLFSSL_EC_POINT *a, const WOLFSSL_EC_POINT *b,
+                         WOLFSSL_BN_CTX *ctx);
+WOLFSSL_API int wolfSSL_EC_POINT_copy(WOLFSSL_EC_POINT *dest,
+                                      const WOLFSSL_EC_POINT *src);
+WOLFSSL_API
+void wolfSSL_EC_POINT_free(WOLFSSL_EC_POINT *point);
+WOLFSSL_API
+int wolfSSL_EC_POINT_is_at_infinity(const WOLFSSL_EC_GROUP *group,
+                                    const WOLFSSL_EC_POINT *a);
+
+#ifndef HAVE_SELFTEST
+WOLFSSL_API
+char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group,
+                                 const WOLFSSL_EC_POINT* point, int form,
+                                 WOLFSSL_BN_CTX* ctx);
+#endif
+
+#ifndef HAVE_ECC
+#define OPENSSL_NO_EC
+#endif
+
+#define EC_KEY_new                      wolfSSL_EC_KEY_new
+#define EC_KEY_free                     wolfSSL_EC_KEY_free
+#define EC_KEY_dup                      wolfSSL_EC_KEY_dup
+#define EC_KEY_get0_public_key          wolfSSL_EC_KEY_get0_public_key
+#define EC_KEY_get0_group               wolfSSL_EC_KEY_get0_group
+#define EC_KEY_set_private_key          wolfSSL_EC_KEY_set_private_key
+#define EC_KEY_get0_private_key         wolfSSL_EC_KEY_get0_private_key
+#define EC_KEY_new_by_curve_name        wolfSSL_EC_KEY_new_by_curve_name
+#define EC_KEY_set_group                wolfSSL_EC_KEY_set_group
+#define EC_KEY_generate_key             wolfSSL_EC_KEY_generate_key
+#define EC_KEY_set_asn1_flag            wolfSSL_EC_KEY_set_asn1_flag
+#define EC_KEY_set_public_key           wolfSSL_EC_KEY_set_public_key
+
+#define ECDSA_size                      wolfSSL_ECDSA_size
+#define ECDSA_sign                      wolfSSL_ECDSA_sign
+
+#define EC_GROUP_free                   wolfSSL_EC_GROUP_free
+#define EC_GROUP_set_asn1_flag          wolfSSL_EC_GROUP_set_asn1_flag
+#define EC_GROUP_new_by_curve_name      wolfSSL_EC_GROUP_new_by_curve_name
+#define EC_GROUP_cmp                    wolfSSL_EC_GROUP_cmp
+#define EC_GROUP_get_curve_name         wolfSSL_EC_GROUP_get_curve_name
+#define EC_GROUP_get_degree             wolfSSL_EC_GROUP_get_degree
+#define EC_GROUP_get_order              wolfSSL_EC_GROUP_get_order
+#define EC_GROUP_order_bits             wolfSSL_EC_GROUP_order_bits
+#define EC_GROUP_method_of              wolfSSL_EC_GROUP_method_of
+
+#define EC_METHOD_get_field_type        wolfSSL_EC_METHOD_get_field_type
+
+#define EC_POINT_new                    wolfSSL_EC_POINT_new
+#define EC_POINT_free                   wolfSSL_EC_POINT_free
+#define EC_POINT_get_affine_coordinates_GFp \
+                                     wolfSSL_EC_POINT_get_affine_coordinates_GFp
+#define EC_POINT_set_affine_coordinates_GFp \
+                                     wolfSSL_EC_POINT_set_affine_coordinates_GFp
+#define EC_POINT_mul                    wolfSSL_EC_POINT_mul
+#define EC_POINT_clear_free             wolfSSL_EC_POINT_clear_free
+#define EC_POINT_cmp                    wolfSSL_EC_POINT_cmp
+#define EC_POINT_copy                   wolfSSL_EC_POINT_copy
+#define EC_POINT_is_at_infinity         wolfSSL_EC_POINT_is_at_infinity
+
+#define EC_get_builtin_curves           wolfSSL_EC_get_builtin_curves
+
+#define ECPoint_i2d                     wolfSSL_ECPoint_i2d
+#define ECPoint_d2i                     wolfSSL_ECPoint_d2i
+#define EC_POINT_point2oct              wolfSSL_EC_POINT_point2oct
+#define EC_POINT_oct2point              wolfSSL_EC_POINT_oct2point
+#define EC_POINT_point2bn               wolfSSL_EC_POINT_point2bn
+#define i2o_ECPublicKey                 wolfSSL_i2o_ECPublicKey
+#define EC_KEY_set_conv_form            wolfSSL_EC_KEY_set_conv_form
+
+#ifndef HAVE_SELFTEST
+    #define EC_POINT_point2hex          wolfSSL_EC_POINT_point2hex
+#endif
+
+#define EC_POINT_dump                   wolfSSL_EC_POINT_dump
+#define EC_get_builtin_curves           wolfSSL_EC_get_builtin_curves
+
+#define EC_curve_nid2nist               wolfSSL_EC_curve_nid2nist
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif /* header */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ec25519.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ec25519.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ec25519.h	(revision 453)
@@ -0,0 +1,44 @@
+/* ec25519.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* ec25519.h */
+
+#ifndef WOLFSSL_EC25519_H_
+#define WOLFSSL_EC25519_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+WOLFSSL_API
+int wolfSSL_EC25519_generate_key(unsigned char *priv, unsigned int *privSz,
+                                 unsigned char *pub, unsigned int *pubSz);
+
+WOLFSSL_API
+int wolfSSL_EC25519_shared_key(unsigned char *shared, unsigned int *sharedSz,
+                               const unsigned char *priv, unsigned int privSz,
+                               const unsigned char *pub, unsigned int pubSz);
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif /* header */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ec448.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ec448.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ec448.h	(revision 453)
@@ -0,0 +1,44 @@
+/* ec448.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* ec448.h */
+
+#ifndef WOLFSSL_EC448_H_
+#define WOLFSSL_EC448_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+WOLFSSL_API
+int wolfSSL_EC448_generate_key(unsigned char *priv, unsigned int *privSz,
+                               unsigned char *pub, unsigned int *pubSz);
+
+WOLFSSL_API
+int wolfSSL_EC448_shared_key(unsigned char *shared, unsigned int *sharedSz,
+                             const unsigned char *priv, unsigned int privSz,
+                             const unsigned char *pub, unsigned int pubSz);
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif /* header */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ecdh.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ecdh.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ecdh.h	(revision 453)
@@ -0,0 +1,49 @@
+/* ecdh.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* ecdh.h for openssl */
+
+#ifndef WOLFSSL_ECDH_H_
+#define WOLFSSL_ECDH_H_
+
+#include <wolfssl/openssl/ssl.h>
+#include <wolfssl/openssl/bn.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+WOLFSSL_API int wolfSSL_ECDH_compute_key(void *out, size_t outlen,
+                                         const WOLFSSL_EC_POINT *pub_key,
+                                         WOLFSSL_EC_KEY *ecdh,
+                                         void *(*KDF) (const void *in,
+                                                       size_t inlen,
+                                                       void *out,
+                                                       size_t *outlen));
+
+#define ECDH_compute_key wolfSSL_ECDH_compute_key
+
+#ifdef __cplusplus
+}  /* extern C */
+#endif
+
+#endif /* header */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ecdsa.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ecdsa.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ecdsa.h	(revision 453)
@@ -0,0 +1,75 @@
+/* ecdsa.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* ecdsa.h for openssl */
+
+#ifndef WOLFSSL_ECDSA_H_
+#define WOLFSSL_ECDSA_H_
+
+#include <wolfssl/openssl/bn.h>
+#include <wolfssl/openssl/ec.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef WOLFSSL_ECDSA_TYPE_DEFINED /* guard on redeclaration */
+typedef struct WOLFSSL_ECDSA_SIG      WOLFSSL_ECDSA_SIG;
+#define WOLFSSL_ECDSA_TYPE_DEFINED
+#endif
+
+typedef WOLFSSL_ECDSA_SIG             ECDSA_SIG;
+
+struct WOLFSSL_ECDSA_SIG {
+    WOLFSSL_BIGNUM *r;
+    WOLFSSL_BIGNUM *s;
+};
+
+WOLFSSL_API void wolfSSL_ECDSA_SIG_free(WOLFSSL_ECDSA_SIG *sig);
+WOLFSSL_API WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_SIG_new(void);
+WOLFSSL_API WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_do_sign(const unsigned char *dgst,
+                                                     int dgst_len,
+                                                     WOLFSSL_EC_KEY *eckey);
+WOLFSSL_API int wolfSSL_ECDSA_do_verify(const unsigned char *dgst,
+                                        int dgst_len,
+                                        const WOLFSSL_ECDSA_SIG *sig,
+                                        WOLFSSL_EC_KEY *eckey);
+
+WOLFSSL_API WOLFSSL_ECDSA_SIG *wolfSSL_d2i_ECDSA_SIG(WOLFSSL_ECDSA_SIG **sig,
+                                                     const unsigned char **pp,
+                                                     long len);
+WOLFSSL_API int wolfSSL_i2d_ECDSA_SIG(const WOLFSSL_ECDSA_SIG *sig,
+                                      unsigned char **pp);
+
+#define ECDSA_SIG_free         wolfSSL_ECDSA_SIG_free
+#define ECDSA_SIG_new          wolfSSL_ECDSA_SIG_new
+#define ECDSA_do_sign          wolfSSL_ECDSA_do_sign
+#define ECDSA_do_verify        wolfSSL_ECDSA_do_verify
+#define d2i_ECDSA_SIG          wolfSSL_d2i_ECDSA_SIG
+#define i2d_ECDSA_SIG          wolfSSL_i2d_ECDSA_SIG
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif /* header */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ed25519.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ed25519.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ed25519.h	(revision 453)
@@ -0,0 +1,47 @@
+/* ed25519.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* ed25519.h */
+
+#ifndef WOLFSSL_ED25519_H_
+#define WOLFSSL_ED25519_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+WOLFSSL_API
+int wolfSSL_ED25519_generate_key(unsigned char *priv, unsigned int *privSz,
+                                 unsigned char *pub, unsigned int *pubSz);
+WOLFSSL_API
+int wolfSSL_ED25519_sign(const unsigned char *msg, unsigned int msgSz,
+                         const unsigned char *priv, unsigned int privSz,
+                         unsigned char *sig, unsigned int *sigSz);
+WOLFSSL_API
+int wolfSSL_ED25519_verify(const unsigned char *msg, unsigned int msgSz,
+                           const unsigned char *pub, unsigned int pubSz,
+                           const unsigned char *sig, unsigned int sigSz);
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif /* header */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ed448.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ed448.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ed448.h	(revision 453)
@@ -0,0 +1,47 @@
+/* ed448.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* ed448.h */
+
+#ifndef WOLFSSL_ED448_H_
+#define WOLFSSL_ED448_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+WOLFSSL_API
+int wolfSSL_ED448_generate_key(unsigned char *priv, unsigned int *privSz,
+                               unsigned char *pub, unsigned int *pubSz);
+WOLFSSL_API
+int wolfSSL_ED448_sign(const unsigned char *msg, unsigned int msgSz,
+                       const unsigned char *priv, unsigned int privSz,
+                       unsigned char *sig, unsigned int *sigSz);
+WOLFSSL_API
+int wolfSSL_ED448_verify(const unsigned char *msg, unsigned int msgSz,
+                         const unsigned char *pub, unsigned int pubSz,
+                         const unsigned char *sig, unsigned int sigSz);
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif /* header */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/err.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/err.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/err.h	(revision 453)
@@ -0,0 +1,55 @@
+/* err.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#ifndef WOLFSSL_OPENSSL_ERR_
+#define WOLFSSL_OPENSSL_ERR_
+
+#include <wolfssl/wolfcrypt/logging.h>
+
+/* err.h for openssl */
+#define ERR_load_crypto_strings          wolfSSL_ERR_load_crypto_strings
+#define ERR_load_CRYPTO_strings          wolfSSL_ERR_load_crypto_strings
+#define ERR_peek_last_error              wolfSSL_ERR_peek_last_error
+
+/* fatal error */
+#define ERR_R_MALLOC_FAILURE                    MEMORY_E
+#define ERR_R_PASSED_NULL_PARAMETER             BAD_FUNC_ARG
+#define ERR_R_DISABLED                          NOT_COMPILED_IN
+#define ERR_R_PASSED_INVALID_ARGUMENT           BAD_FUNC_ARG
+#define RSA_R_UNKNOWN_PADDING_TYPE              RSA_PAD_E
+#define EC_R_BUFFER_TOO_SMALL                   BUFFER_E
+
+/* SSL function codes */
+#define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT          1
+#define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE      2
+#define SSL_F_SSL_USE_PRIVATEKEY                3
+#define EC_F_EC_GFP_SIMPLE_POINT2OCT            4
+
+/* reasons */
+#define ERR_R_SYS_LIB                           1
+#define PKCS12_R_MAC_VERIFY_FAILURE             2
+
+#define RSAerr(f,r)  ERR_put_error(0,(f),(r),__FILE__,__LINE__)
+#define SSLerr(f,r)  ERR_put_error(0,(f),(r),__FILE__,__LINE__)
+#define ECerr(f,r)   ERR_put_error(0,(f),(r),__FILE__,__LINE__)
+
+#endif /* WOLFSSL_OPENSSL_ERR_ */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/evp.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/evp.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/evp.h	(revision 453)
@@ -0,0 +1,931 @@
+/* evp.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+/*!
+    \file wolfssl/openssl/evp.h
+    \brief evp.h defines mini evp openssl compatibility layer
+ */
+
+
+#ifndef WOLFSSL_EVP_H_
+#define WOLFSSL_EVP_H_
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifdef WOLFSSL_PREFIX
+#include "prefix_evp.h"
+#endif
+
+#ifndef NO_MD4
+    #include <wolfssl/openssl/md4.h>
+#endif
+#ifndef NO_MD5
+    #include <wolfssl/openssl/md5.h>
+#endif
+#include <wolfssl/openssl/sha.h>
+#include <wolfssl/openssl/sha3.h>
+#include <wolfssl/openssl/ripemd.h>
+#include <wolfssl/openssl/rsa.h>
+#include <wolfssl/openssl/dsa.h>
+#include <wolfssl/openssl/ec.h>
+#include <wolfssl/openssl/dh.h>
+
+#include <wolfssl/wolfcrypt/aes.h>
+#include <wolfssl/wolfcrypt/des3.h>
+#include <wolfssl/wolfcrypt/arc4.h>
+#include <wolfssl/wolfcrypt/hmac.h>
+#ifdef HAVE_IDEA
+    #include <wolfssl/wolfcrypt/idea.h>
+#endif
+#include <wolfssl/wolfcrypt/pwdbased.h>
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+
+typedef char WOLFSSL_EVP_CIPHER;
+#ifndef WOLFSSL_EVP_TYPE_DEFINED /* guard on redeclaration */
+typedef char   WOLFSSL_EVP_MD;
+typedef struct WOLFSSL_EVP_PKEY     WOLFSSL_EVP_PKEY;
+typedef struct WOLFSSL_EVP_MD_CTX   WOLFSSL_EVP_MD_CTX;
+#define WOLFSSL_EVP_TYPE_DEFINED
+#endif
+
+typedef WOLFSSL_EVP_PKEY       EVP_PKEY;
+typedef WOLFSSL_EVP_PKEY       PKCS8_PRIV_KEY_INFO;
+
+#ifndef NO_MD4
+    WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_md4(void);
+#endif
+#ifndef NO_MD5
+    WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_md5(void);
+#endif
+WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_mdc2(void);
+WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_sha1(void);
+WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_sha224(void);
+WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_sha256(void);
+WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_sha384(void);
+WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_sha512(void);
+WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_ripemd160(void);
+
+WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_sha3_224(void);
+WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_sha3_256(void);
+WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_sha3_384(void);
+WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_sha3_512(void);
+
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ecb(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ecb(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ecb(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cbc(void);
+#if !defined(NO_AES) && defined(HAVE_AES_CBC)
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cbc(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cbc(void);
+#endif
+#ifndef NO_AES
+#ifdef WOLFSSL_AES_CFB
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cfb1(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cfb1(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cfb1(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cfb8(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cfb8(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cfb8(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cfb128(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cfb128(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cfb128(void);
+#endif
+#ifdef WOLFSSL_AES_OFB
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ofb(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ofb(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ofb(void);
+#endif
+#ifdef WOLFSSL_AES_XTS
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_xts(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_xts(void);
+#endif
+#endif /* NO_AES */
+#if !defined(NO_AES) && defined(HAVE_AESGCM)
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_gcm(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_gcm(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_gcm(void);
+#endif
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ctr(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ctr(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ctr(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ecb(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ede3_ecb(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_cbc(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ede3_cbc(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_rc4(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_idea_cbc(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_enc_null(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_rc2_cbc(void);
+
+
+typedef union {
+    #ifndef NO_MD4
+        WOLFSSL_MD4_CTX    md4;
+    #endif
+    #ifndef NO_MD5
+        WOLFSSL_MD5_CTX    md5;
+    #endif
+    WOLFSSL_SHA_CTX    sha;
+    #ifdef WOLFSSL_SHA224
+        WOLFSSL_SHA224_CTX sha224;
+    #endif
+    WOLFSSL_SHA256_CTX sha256;
+    #ifdef WOLFSSL_SHA384
+        WOLFSSL_SHA384_CTX sha384;
+    #endif
+    #ifdef WOLFSSL_SHA512
+        WOLFSSL_SHA512_CTX sha512;
+    #endif
+    #ifdef WOLFSSL_RIPEMD
+        WOLFSSL_RIPEMD_CTX ripemd;
+    #endif
+    #ifndef WOLFSSL_NOSHA3_224
+        WOLFSSL_SHA3_224_CTX sha3_224;
+    #endif
+    #ifndef WOLFSSL_NOSHA3_256
+        WOLFSSL_SHA3_256_CTX sha3_256;
+    #endif
+        WOLFSSL_SHA3_384_CTX sha3_384;
+    #ifndef WOLFSSL_NOSHA3_512
+        WOLFSSL_SHA3_512_CTX sha3_512;
+    #endif
+} WOLFSSL_Hasher;
+
+typedef struct WOLFSSL_EVP_PKEY_CTX WOLFSSL_EVP_PKEY_CTX;
+typedef struct WOLFSSL_EVP_CIPHER_CTX WOLFSSL_EVP_CIPHER_CTX;
+
+struct WOLFSSL_EVP_MD_CTX {
+    union {
+        WOLFSSL_Hasher digest;
+    #ifndef NO_HMAC
+        Hmac hmac;
+    #endif
+    } hash;
+    int macType;
+    WOLFSSL_EVP_PKEY_CTX *pctx;
+};
+
+
+typedef union {
+#ifndef NO_AES
+    Aes  aes;
+#ifdef WOLFSSL_AES_XTS
+    XtsAes xts;
+#endif
+#endif
+#ifndef NO_DES3
+    Des  des;
+    Des3 des3;
+#endif
+    Arc4 arc4;
+#ifdef HAVE_IDEA
+    Idea idea;
+#endif
+#ifdef WOLFSSL_QT
+    int (*ctrl) (WOLFSSL_EVP_CIPHER_CTX *, int type, int arg, void *ptr);
+#endif
+} WOLFSSL_Cipher;
+
+
+enum {
+    AES_128_CBC_TYPE  = 1,
+    AES_192_CBC_TYPE  = 2,
+    AES_256_CBC_TYPE  = 3,
+    AES_128_CTR_TYPE  = 4,
+    AES_192_CTR_TYPE  = 5,
+    AES_256_CTR_TYPE  = 6,
+    AES_128_ECB_TYPE  = 7,
+    AES_192_ECB_TYPE  = 8,
+    AES_256_ECB_TYPE  = 9,
+    DES_CBC_TYPE      = 10,
+    DES_ECB_TYPE      = 11,
+    DES_EDE3_CBC_TYPE = 12,
+    DES_EDE3_ECB_TYPE = 13,
+    ARC4_TYPE         = 14,
+    NULL_CIPHER_TYPE  = 15,
+    EVP_PKEY_RSA      = 16,
+    EVP_PKEY_DSA      = 17,
+    EVP_PKEY_EC       = 18,
+#ifdef HAVE_IDEA
+    IDEA_CBC_TYPE     = 19,
+#endif
+    AES_128_GCM_TYPE  = 21,
+    AES_192_GCM_TYPE  = 22,
+    AES_256_GCM_TYPE  = 23,
+    NID_sha1          = 64,
+    NID_sha224        = 65,
+    NID_md2           = 77,
+    NID_md4           = 257,
+    NID_md5           =  4,
+    NID_hmac          = 855,
+    NID_dhKeyAgreement= 28,
+    EVP_PKEY_DH       = NID_dhKeyAgreement,
+    EVP_PKEY_HMAC     = NID_hmac,
+    AES_128_CFB1_TYPE = 24,
+    AES_192_CFB1_TYPE = 25,
+    AES_256_CFB1_TYPE = 26,
+    AES_128_CFB8_TYPE = 27,
+    AES_192_CFB8_TYPE = 28,
+    AES_256_CFB8_TYPE = 29,
+    AES_128_CFB128_TYPE = 30,
+    AES_192_CFB128_TYPE = 31,
+    AES_256_CFB128_TYPE = 32,
+    AES_128_OFB_TYPE = 33,
+    AES_192_OFB_TYPE = 34,
+    AES_256_OFB_TYPE = 35,
+    AES_128_XTS_TYPE = 36,
+    AES_256_XTS_TYPE = 37
+};
+
+enum {
+    NID_md5WithRSA    = 104,
+    NID_md5WithRSAEncryption = 8,
+    NID_dsaWithSHA1   = 113,
+    NID_dsaWithSHA1_2 = 70,
+    NID_sha1WithRSA   = 115,
+    NID_sha1WithRSAEncryption = 65,
+    NID_sha224WithRSAEncryption = 671,
+    NID_sha256WithRSAEncryption = 668,
+    NID_sha384WithRSAEncryption = 669,
+    NID_sha512WithRSAEncryption = 670,
+    NID_ecdsa_with_SHA1 = 416,
+    NID_ecdsa_with_SHA224 = 793,
+    NID_ecdsa_with_SHA256 = 794,
+    NID_ecdsa_with_SHA384 = 795,
+    NID_ecdsa_with_SHA512 = 796,
+    NID_dsa_with_SHA224 = 802,
+    NID_dsa_with_SHA256 = 803,
+    NID_sha3_224        = 1096,
+    NID_sha3_256        = 1097,
+    NID_sha3_384        = 1098,
+    NID_sha3_512        = 1099,
+};
+
+enum {
+    NID_aes_128_cbc = 419,
+    NID_aes_192_cbc = 423,
+    NID_aes_256_cbc = 427,
+    NID_aes_128_gcm = 895,
+    NID_aes_192_gcm = 898,
+    NID_aes_256_gcm = 901,
+    NID_aes_128_ctr = 904,
+    NID_aes_192_ctr = 905,
+    NID_aes_256_ctr = 906,
+    NID_aes_128_ecb = 418,
+    NID_aes_192_ecb = 422,
+    NID_aes_256_ecb = 426,
+    NID_des_cbc     =  31,
+    NID_des_ecb     =  29,
+    NID_des_ede3_cbc=  44,
+    NID_des_ede3_ecb=  33,
+    NID_idea_cbc    =  34,
+    NID_aes_128_cfb1= 650,
+    NID_aes_192_cfb1= 651,
+    NID_aes_256_cfb1= 652,
+    NID_aes_128_cfb8= 653,
+    NID_aes_192_cfb8= 654,
+    NID_aes_256_cfb8= 655,
+    NID_aes_128_cfb128 = 421,
+    NID_aes_192_cfb128 = 425,
+    NID_aes_256_cfb128 = 429,
+    NID_aes_128_ofb = 420,
+    NID_aes_192_ofb = 424,
+    NID_aes_256_ofb = 428,
+    NID_aes_128_xts = 913,
+    NID_aes_256_xts = 914
+};
+
+#define NID_X9_62_id_ecPublicKey EVP_PKEY_EC
+#define NID_dhKeyAgreement       EVP_PKEY_DH
+#define NID_rsaEncryption        EVP_PKEY_RSA
+#define NID_dsa                  EVP_PKEY_DSA
+
+#define WOLFSSL_EVP_BUF_SIZE 16
+struct WOLFSSL_EVP_CIPHER_CTX {
+    int            keyLen;         /* user may set for variable */
+    int            block_size;
+    unsigned long  flags;
+    unsigned char  enc;            /* if encrypt side, then true */
+    unsigned char  cipherType;
+#ifndef NO_AES
+    /* working iv pointer into cipher */
+    ALIGN16 unsigned char  iv[AES_BLOCK_SIZE];
+#elif !defined(NO_DES3)
+    /* working iv pointer into cipher */
+    ALIGN16 unsigned char  iv[DES_BLOCK_SIZE];
+#elif defined(HAVE_IDEA)
+    /* working iv pointer into cipher */
+    ALIGN16 unsigned char  iv[IDEA_BLOCK_SIZE];
+#endif
+    WOLFSSL_Cipher  cipher;
+    ALIGN16 byte buf[WOLFSSL_EVP_BUF_SIZE];
+    int  bufUsed;
+    ALIGN16 byte lastBlock[WOLFSSL_EVP_BUF_SIZE];
+    int  lastUsed;
+#if !defined(NO_AES) || !defined(NO_DES3) || defined(HAVE_IDEA) || \
+    defined(HAVE_AESGCM) || defined (WOLFSSL_AES_XTS)
+#define HAVE_WOLFSSL_EVP_CIPHER_CTX_IV
+    int    ivSz;
+    ALIGN16 unsigned char authTag[AES_BLOCK_SIZE];
+    int     authTagSz;
+#endif
+};
+
+struct WOLFSSL_EVP_PKEY_CTX {
+    WOLFSSL_EVP_PKEY *pkey;
+    WOLFSSL_EVP_PKEY *peerKey;
+    int op; /* operation */
+    int padding;
+    int nbits;
+};
+
+typedef int WOLFSSL_ENGINE  ;
+typedef WOLFSSL_ENGINE ENGINE;
+typedef WOLFSSL_EVP_PKEY_CTX EVP_PKEY_CTX;
+
+#define EVP_PKEY_OP_SIGN    (1 << 3)
+#define EVP_PKEY_OP_ENCRYPT (1 << 6)
+#define EVP_PKEY_OP_DECRYPT (1 << 7)
+#define EVP_PKEY_OP_DERIVE  (1 << 8)
+
+WOLFSSL_API void wolfSSL_EVP_init(void);
+WOLFSSL_API int  wolfSSL_EVP_MD_size(const WOLFSSL_EVP_MD* md);
+WOLFSSL_API int  wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md);
+WOLFSSL_API int  wolfSSL_EVP_MD_block_size(const WOLFSSL_EVP_MD *md);
+
+WOLFSSL_API WOLFSSL_EVP_MD_CTX *wolfSSL_EVP_MD_CTX_new (void);
+WOLFSSL_API void                wolfSSL_EVP_MD_CTX_free(WOLFSSL_EVP_MD_CTX* ctx);
+WOLFSSL_API void wolfSSL_EVP_MD_CTX_init(WOLFSSL_EVP_MD_CTX* ctx);
+WOLFSSL_API int  wolfSSL_EVP_MD_CTX_cleanup(WOLFSSL_EVP_MD_CTX* ctx);
+WOLFSSL_API int  wolfSSL_EVP_MD_CTX_copy(WOLFSSL_EVP_MD_CTX *out, const WOLFSSL_EVP_MD_CTX *in);
+WOLFSSL_API int  wolfSSL_EVP_MD_CTX_copy_ex(WOLFSSL_EVP_MD_CTX *out, const WOLFSSL_EVP_MD_CTX *in);
+WOLFSSL_API int  wolfSSL_EVP_MD_CTX_type(const WOLFSSL_EVP_MD_CTX *ctx);
+WOLFSSL_API int  wolfSSL_EVP_MD_CTX_size(const WOLFSSL_EVP_MD_CTX *ctx);
+WOLFSSL_API int  wolfSSL_EVP_MD_CTX_block_size(const WOLFSSL_EVP_MD_CTX *ctx);
+WOLFSSL_API const WOLFSSL_EVP_MD *wolfSSL_EVP_MD_CTX_md(const WOLFSSL_EVP_MD_CTX *ctx);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_get_cipherbyname(const char *name);
+WOLFSSL_API const WOLFSSL_EVP_MD     *wolfSSL_EVP_get_digestbyname(const char *name);
+WOLFSSL_API int wolfSSL_EVP_CIPHER_nid(const WOLFSSL_EVP_CIPHER *cipher);
+
+WOLFSSL_API int wolfSSL_EVP_DigestInit(WOLFSSL_EVP_MD_CTX* ctx,
+                                     const WOLFSSL_EVP_MD* type);
+WOLFSSL_API int wolfSSL_EVP_DigestInit_ex(WOLFSSL_EVP_MD_CTX* ctx,
+                                     const WOLFSSL_EVP_MD* type,
+                                     WOLFSSL_ENGINE *impl);
+WOLFSSL_API int wolfSSL_EVP_DigestUpdate(WOLFSSL_EVP_MD_CTX* ctx, const void* data,
+                                       size_t sz);
+WOLFSSL_API int wolfSSL_EVP_DigestFinal(WOLFSSL_EVP_MD_CTX* ctx, unsigned char* md,
+                                      unsigned int* s);
+WOLFSSL_API int wolfSSL_EVP_DigestFinal_ex(WOLFSSL_EVP_MD_CTX* ctx,
+                                            unsigned char* md, unsigned int* s);
+
+WOLFSSL_API int wolfSSL_EVP_DigestSignInit(WOLFSSL_EVP_MD_CTX *ctx,
+                                           WOLFSSL_EVP_PKEY_CTX **pctx,
+                                           const WOLFSSL_EVP_MD *type,
+                                           WOLFSSL_ENGINE *e,
+                                           WOLFSSL_EVP_PKEY *pkey);
+WOLFSSL_API int wolfSSL_EVP_DigestSignUpdate(WOLFSSL_EVP_MD_CTX *ctx,
+                                             const void *d, unsigned int cnt);
+WOLFSSL_API int wolfSSL_EVP_DigestSignFinal(WOLFSSL_EVP_MD_CTX *ctx,
+                                            unsigned char *sig, size_t *siglen);
+
+WOLFSSL_API int wolfSSL_EVP_DigestVerifyInit(WOLFSSL_EVP_MD_CTX *ctx,
+                                             WOLFSSL_EVP_PKEY_CTX **pctx,
+                                             const WOLFSSL_EVP_MD *type,
+                                             WOLFSSL_ENGINE *e,
+                                             WOLFSSL_EVP_PKEY *pkey);
+WOLFSSL_API int wolfSSL_EVP_DigestVerifyUpdate(WOLFSSL_EVP_MD_CTX *ctx,
+                                               const void *d, size_t cnt);
+WOLFSSL_API int wolfSSL_EVP_DigestVerifyFinal(WOLFSSL_EVP_MD_CTX *ctx,
+                                              const unsigned char *sig,
+                                              size_t siglen);
+WOLFSSL_API int wolfSSL_EVP_Digest(const unsigned char* in, int inSz, unsigned char* out,
+                              unsigned int* outSz, const WOLFSSL_EVP_MD* evp,
+                              WOLFSSL_ENGINE* eng);
+
+
+WOLFSSL_API int wolfSSL_EVP_BytesToKey(const WOLFSSL_EVP_CIPHER*,
+                              const WOLFSSL_EVP_MD*, const unsigned char*,
+                              const unsigned char*, int, int, unsigned char*,
+                              unsigned char*);
+
+WOLFSSL_API void wolfSSL_EVP_CIPHER_CTX_init(WOLFSSL_EVP_CIPHER_CTX* ctx);
+WOLFSSL_API int  wolfSSL_EVP_CIPHER_CTX_cleanup(WOLFSSL_EVP_CIPHER_CTX* ctx);
+WOLFSSL_API int  wolfSSL_EVP_CIPHER_CTX_ctrl(WOLFSSL_EVP_CIPHER_CTX *ctx, \
+                                             int type, int arg, void *ptr);
+WOLFSSL_API int  wolfSSL_EVP_CIPHER_CTX_iv_length(const WOLFSSL_EVP_CIPHER_CTX*);
+WOLFSSL_API int  wolfSSL_EVP_CIPHER_iv_length(const WOLFSSL_EVP_CIPHER*);
+WOLFSSL_API int wolfSSL_EVP_Cipher_key_length(const WOLFSSL_EVP_CIPHER* c);
+
+
+WOLFSSL_API int  wolfSSL_EVP_CipherInit(WOLFSSL_EVP_CIPHER_CTX* ctx,
+                                    const WOLFSSL_EVP_CIPHER* type,
+                                    const unsigned char* key,
+                                    const unsigned char* iv,
+                                    int enc);
+WOLFSSL_API int  wolfSSL_EVP_CipherInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx,
+                                    const WOLFSSL_EVP_CIPHER* type,
+                                    WOLFSSL_ENGINE *impl,
+                                    const unsigned char* key,
+                                    const unsigned char* iv,
+                                    int enc);
+WOLFSSL_API int  wolfSSL_EVP_EncryptInit(WOLFSSL_EVP_CIPHER_CTX* ctx,
+                                    const WOLFSSL_EVP_CIPHER* type,
+                                    const unsigned char* key,
+                                    const unsigned char* iv);
+WOLFSSL_API int  wolfSSL_EVP_EncryptInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx,
+                                    const WOLFSSL_EVP_CIPHER* type,
+                                    WOLFSSL_ENGINE *impl,
+                                    const unsigned char* key,
+                                    const unsigned char* iv);
+WOLFSSL_API int  wolfSSL_EVP_DecryptInit(WOLFSSL_EVP_CIPHER_CTX* ctx,
+                                    const WOLFSSL_EVP_CIPHER* type,
+                                    const unsigned char* key,
+                                    const unsigned char* iv);
+WOLFSSL_API int  wolfSSL_EVP_DecryptInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx,
+                                    const WOLFSSL_EVP_CIPHER* type,
+                                    WOLFSSL_ENGINE *impl,
+                                    const unsigned char* key,
+                                    const unsigned char* iv);
+WOLFSSL_API int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx,
+                                   unsigned char *out, int *outl,
+                                   const unsigned char *in, int inl);
+WOLFSSL_API int  wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx,
+                                   unsigned char *out, int *outl);
+WOLFSSL_API int  wolfSSL_EVP_CipherFinal_ex(WOLFSSL_EVP_CIPHER_CTX *ctx,
+                                   unsigned char *out, int *outl, int enc);
+WOLFSSL_API int  wolfSSL_EVP_EncryptFinal(WOLFSSL_EVP_CIPHER_CTX *ctx,
+                                   unsigned char *out, int *outl);
+WOLFSSL_API int  wolfSSL_EVP_EncryptFinal_ex(WOLFSSL_EVP_CIPHER_CTX *ctx,
+                                   unsigned char *out, int *outl);
+WOLFSSL_API int  wolfSSL_EVP_DecryptFinal(WOLFSSL_EVP_CIPHER_CTX *ctx,
+                                   unsigned char *out, int *outl);
+WOLFSSL_API int  wolfSSL_EVP_DecryptFinal_ex(WOLFSSL_EVP_CIPHER_CTX *ctx,
+                                   unsigned char *out, int *outl);
+WOLFSSL_API int  wolfSSL_EVP_DecryptFinal_legacy(WOLFSSL_EVP_CIPHER_CTX *ctx,
+                                   unsigned char *out, int *outl);
+
+WOLFSSL_API WOLFSSL_EVP_CIPHER_CTX *wolfSSL_EVP_CIPHER_CTX_new(void);
+WOLFSSL_API void wolfSSL_EVP_CIPHER_CTX_free(WOLFSSL_EVP_CIPHER_CTX *ctx);
+WOLFSSL_API int  wolfSSL_EVP_CIPHER_CTX_reset(WOLFSSL_EVP_CIPHER_CTX *ctx);
+WOLFSSL_API int  wolfSSL_EVP_CIPHER_CTX_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx);
+WOLFSSL_API int  wolfSSL_EVP_CIPHER_CTX_set_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx,
+                                                     int keylen);
+WOLFSSL_API int  wolfSSL_EVP_CIPHER_CTX_set_iv_length(WOLFSSL_EVP_CIPHER_CTX* ctx,
+                                                     int ivLen);
+WOLFSSL_API int  wolfSSL_EVP_CIPHER_CTX_set_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, byte* iv,
+                                                     int ivLen);
+WOLFSSL_API int  wolfSSL_EVP_Cipher(WOLFSSL_EVP_CIPHER_CTX* ctx,
+                          unsigned char* dst, unsigned char* src,
+                          unsigned int len);
+
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_get_cipherbynid(int);
+WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_get_digestbynid(int);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_CIPHER_CTX_cipher(const WOLFSSL_EVP_CIPHER_CTX *ctx);
+
+WOLFSSL_API int wolfSSL_EVP_PKEY_assign_RSA(WOLFSSL_EVP_PKEY* pkey,
+                                            WOLFSSL_RSA* key);
+WOLFSSL_API int wolfSSL_EVP_PKEY_assign_EC_KEY(WOLFSSL_EVP_PKEY* pkey,
+                                               WOLFSSL_EC_KEY* key);
+WOLFSSL_API int wolfSSL_EVP_PKEY_assign_DSA(EVP_PKEY* pkey, WOLFSSL_DSA* key);
+WOLFSSL_API int wolfSSL_EVP_PKEY_assign_DH(EVP_PKEY* pkey, WOLFSSL_DH* key);
+WOLFSSL_API WOLFSSL_RSA* wolfSSL_EVP_PKEY_get0_RSA(struct WOLFSSL_EVP_PKEY *pkey);
+WOLFSSL_API WOLFSSL_RSA* wolfSSL_EVP_PKEY_get1_RSA(WOLFSSL_EVP_PKEY*);
+WOLFSSL_API WOLFSSL_DSA* wolfSSL_EVP_PKEY_get1_DSA(WOLFSSL_EVP_PKEY*);
+WOLFSSL_API WOLFSSL_EC_KEY *wolfSSL_EVP_PKEY_get0_EC_KEY(WOLFSSL_EVP_PKEY *pkey);
+WOLFSSL_API WOLFSSL_EC_KEY *wolfSSL_EVP_PKEY_get1_EC_KEY(WOLFSSL_EVP_PKEY *key);
+WOLFSSL_API WOLFSSL_DH* wolfSSL_EVP_PKEY_get0_DH(WOLFSSL_EVP_PKEY* key);
+WOLFSSL_API WOLFSSL_DH* wolfSSL_EVP_PKEY_get1_DH(WOLFSSL_EVP_PKEY* key);
+WOLFSSL_API int wolfSSL_EVP_PKEY_set1_RSA(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_RSA *key);
+WOLFSSL_API int wolfSSL_EVP_PKEY_set1_DSA(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_DSA *key);
+WOLFSSL_API int wolfSSL_EVP_PKEY_set1_DH(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_DH *key);
+WOLFSSL_API int wolfSSL_EVP_PKEY_set1_EC_KEY(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_EC_KEY *key);
+WOLFSSL_API int wolfSSL_EVP_PKEY_assign(WOLFSSL_EVP_PKEY *pkey, int type, void *key);
+
+WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_mac_key(int type, ENGINE* e,
+                                          const unsigned char* key, int keylen);
+WOLFSSL_API const unsigned char* wolfSSL_EVP_PKEY_get0_hmac(const WOLFSSL_EVP_PKEY* pkey,
+        size_t* len);
+WOLFSSL_API int wolfSSL_EVP_PKEY_sign_init(WOLFSSL_EVP_PKEY_CTX *ctx);
+WOLFSSL_API int wolfSSL_EVP_PKEY_sign(WOLFSSL_EVP_PKEY_CTX *ctx,
+  unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen);
+WOLFSSL_API int wolfSSL_EVP_PKEY_keygen_init(WOLFSSL_EVP_PKEY_CTX *ctx);
+WOLFSSL_API int wolfSSL_EVP_PKEY_keygen(WOLFSSL_EVP_PKEY_CTX *ctx,
+  WOLFSSL_EVP_PKEY **ppkey);
+WOLFSSL_API int wolfSSL_EVP_PKEY_bits(const WOLFSSL_EVP_PKEY *pkey);
+WOLFSSL_API int wolfSSL_EVP_PKEY_CTX_free(WOLFSSL_EVP_PKEY_CTX *ctx);
+WOLFSSL_API WOLFSSL_EVP_PKEY_CTX *wolfSSL_EVP_PKEY_CTX_new(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_ENGINE *e);
+WOLFSSL_API int wolfSSL_EVP_PKEY_CTX_set_rsa_padding(WOLFSSL_EVP_PKEY_CTX *ctx, int padding);
+WOLFSSL_API WOLFSSL_EVP_PKEY_CTX *wolfSSL_EVP_PKEY_CTX_new_id(int id, WOLFSSL_ENGINE *e);
+WOLFSSL_API int wolfSSL_EVP_PKEY_CTX_set_rsa_keygen_bits(WOLFSSL_EVP_PKEY_CTX *ctx, int bits);
+
+WOLFSSL_API int wolfSSL_EVP_PKEY_derive_init(WOLFSSL_EVP_PKEY_CTX *ctx);
+WOLFSSL_API int wolfSSL_EVP_PKEY_derive_set_peer(WOLFSSL_EVP_PKEY_CTX *ctx, WOLFSSL_EVP_PKEY *peer);
+WOLFSSL_API int wolfSSL_EVP_PKEY_derive(WOLFSSL_EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen);
+
+WOLFSSL_API int wolfSSL_EVP_PKEY_decrypt(WOLFSSL_EVP_PKEY_CTX *ctx,
+                     unsigned char *out, size_t *outlen,
+                     const unsigned char *in, size_t inlen);
+WOLFSSL_API int wolfSSL_EVP_PKEY_decrypt_init(WOLFSSL_EVP_PKEY_CTX *ctx);
+WOLFSSL_API int wolfSSL_EVP_PKEY_encrypt(WOLFSSL_EVP_PKEY_CTX *ctx,
+                     unsigned char *out, size_t *outlen,
+                     const unsigned char *in, size_t inlen);
+WOLFSSL_API int wolfSSL_EVP_PKEY_encrypt_init(WOLFSSL_EVP_PKEY_CTX *ctx);
+WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_EVP_PKEY_new(void);
+WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_ex(void* heap);
+WOLFSSL_API void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY*);
+WOLFSSL_API int wolfSSL_EVP_PKEY_size(WOLFSSL_EVP_PKEY *pkey);
+WOLFSSL_API int wolfSSL_EVP_PKEY_missing_parameters(WOLFSSL_EVP_PKEY *pkey);
+WOLFSSL_API int wolfSSL_EVP_PKEY_cmp(const WOLFSSL_EVP_PKEY *a, const WOLFSSL_EVP_PKEY *b);
+WOLFSSL_API int wolfSSL_EVP_PKEY_type(int type);
+WOLFSSL_API int wolfSSL_EVP_PKEY_id(const EVP_PKEY *pkey);
+WOLFSSL_API int wolfSSL_EVP_PKEY_base_id(const EVP_PKEY *pkey);
+WOLFSSL_API int wolfSSL_EVP_SignFinal(WOLFSSL_EVP_MD_CTX *ctx, unsigned char *sigret,
+                  unsigned int *siglen, WOLFSSL_EVP_PKEY *pkey);
+WOLFSSL_API int wolfSSL_EVP_SignInit(WOLFSSL_EVP_MD_CTX *ctx, const WOLFSSL_EVP_MD *type);
+WOLFSSL_API int wolfSSL_EVP_SignInit_ex(WOLFSSL_EVP_MD_CTX* ctx,
+                                     const WOLFSSL_EVP_MD* type,
+                                     WOLFSSL_ENGINE *impl);
+WOLFSSL_API int wolfSSL_EVP_SignUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *data, size_t len);
+WOLFSSL_API int wolfSSL_EVP_VerifyFinal(WOLFSSL_EVP_MD_CTX *ctx,
+        unsigned char* sig, unsigned int sig_len, WOLFSSL_EVP_PKEY *pkey);
+WOLFSSL_API int wolfSSL_EVP_VerifyInit(WOLFSSL_EVP_MD_CTX *ctx, const WOLFSSL_EVP_MD *type);
+WOLFSSL_API int wolfSSL_EVP_VerifyUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *data, size_t len);
+
+
+/* these next ones don't need real OpenSSL type, for OpenSSH compat only */
+WOLFSSL_API void* wolfSSL_EVP_X_STATE(const WOLFSSL_EVP_CIPHER_CTX* ctx);
+WOLFSSL_API int   wolfSSL_EVP_X_STATE_LEN(const WOLFSSL_EVP_CIPHER_CTX* ctx);
+
+WOLFSSL_API void  wolfSSL_3des_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset,
+                                unsigned char* iv, int len);
+WOLFSSL_API void  wolfSSL_aes_ctr_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset,
+                                unsigned char* iv, int len);
+
+WOLFSSL_API int  wolfSSL_StoreExternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx);
+WOLFSSL_API int  wolfSSL_SetInternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx);
+
+WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_block_size(const WOLFSSL_EVP_CIPHER_CTX *ctx);
+WOLFSSL_API int wolfSSL_EVP_CIPHER_block_size(const WOLFSSL_EVP_CIPHER *cipher);
+WOLFSSL_API unsigned long WOLFSSL_EVP_CIPHER_mode(const WOLFSSL_EVP_CIPHER *cipher);
+WOLFSSL_API unsigned long WOLFSSL_CIPHER_mode(const WOLFSSL_EVP_CIPHER *cipher);
+WOLFSSL_API unsigned long wolfSSL_EVP_CIPHER_flags(const WOLFSSL_EVP_CIPHER *cipher);
+WOLFSSL_API void wolfSSL_EVP_CIPHER_CTX_set_flags(WOLFSSL_EVP_CIPHER_CTX *ctx, int flags);
+WOLFSSL_API void wolfSSL_EVP_CIPHER_CTX_clear_flags(WOLFSSL_EVP_CIPHER_CTX *ctx, int flags);
+WOLFSSL_API unsigned long wolfSSL_EVP_CIPHER_CTX_mode(const WOLFSSL_EVP_CIPHER_CTX *ctx);
+WOLFSSL_API int  wolfSSL_EVP_CIPHER_CTX_set_padding(WOLFSSL_EVP_CIPHER_CTX *c, int pad);
+WOLFSSL_API int  wolfSSL_EVP_add_digest(const WOLFSSL_EVP_MD *digest);
+WOLFSSL_API int  wolfSSL_EVP_add_cipher(const WOLFSSL_EVP_CIPHER *cipher);
+WOLFSSL_API void wolfSSL_EVP_cleanup(void);
+WOLFSSL_API int  wolfSSL_add_all_algorithms(void);
+WOLFSSL_API int  wolfSSL_OpenSSL_add_all_algorithms_conf(void);
+WOLFSSL_API int  wolfSSL_OpenSSL_add_all_algorithms_noconf(void);
+WOLFSSL_API int wolfSSL_EVP_read_pw_string(char*, int, const char*, int);
+
+WOLFSSL_API int wolfSSL_PKCS5_PBKDF2_HMAC_SHA1(const char * pass, int passlen,
+                                               const unsigned char * salt,
+                                               int saltlen, int iter,
+                                               int keylen, unsigned char *out);
+
+WOLFSSL_API int wolfSSL_PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
+                                           const unsigned char *salt,
+                                           int saltlen, int iter,
+                                           const WOLFSSL_EVP_MD *digest,
+                                           int keylen, unsigned char *out);
+
+WOLFSSL_LOCAL int wolfSSL_EVP_get_hashinfo(const WOLFSSL_EVP_MD* evp,
+                                           int* pHash, int* pHashSz);
+
+#define EVP_CIPH_STREAM_CIPHER WOLFSSL_EVP_CIPH_STREAM_CIPHER
+#define EVP_CIPH_ECB_MODE WOLFSSL_EVP_CIPH_ECB_MODE
+#define EVP_CIPH_CBC_MODE WOLFSSL_EVP_CIPH_CBC_MODE
+#define EVP_CIPH_CFB_MODE WOLFSSL_EVP_CIPH_CFB_MODE
+#define EVP_CIPH_OFB_MODE WOLFSSL_EVP_CIPH_OFB_MODE
+#define EVP_CIPH_CTR_MODE WOLFSSL_EVP_CIPH_CTR_MODE
+#define EVP_CIPH_GCM_MODE WOLFSSL_EVP_CIPH_GCM_MODE
+#define EVP_CIPH_CCM_MODE WOLFSSL_EVP_CIPH_CCM_MODE
+#define EVP_CIPH_XTS_MODE WOLFSSL_EVP_CIPH_XTS_MODE
+
+#define WOLFSSL_EVP_CIPH_MODE           0x0007
+#define WOLFSSL_EVP_CIPH_STREAM_CIPHER      0x0
+#define WOLFSSL_EVP_CIPH_ECB_MODE           0x1
+#define WOLFSSL_EVP_CIPH_CBC_MODE           0x2
+#define WOLFSSL_EVP_CIPH_CFB_MODE           0x3
+#define WOLFSSL_EVP_CIPH_OFB_MODE           0x4
+#define WOLFSSL_EVP_CIPH_CTR_MODE           0x5
+#define WOLFSSL_EVP_CIPH_GCM_MODE           0x6
+#define WOLFSSL_EVP_CIPH_CCM_MODE           0x7
+#define WOLFSSL_EVP_CIPH_XTS_MODE          0x10
+#define WOLFSSL_EVP_CIPH_NO_PADDING       0x100
+#define EVP_CIPH_VARIABLE_LENGTH          0x200
+#define WOLFSSL_EVP_CIPH_TYPE_INIT         0xff
+
+/* end OpenSSH compat */
+
+typedef WOLFSSL_EVP_MD         EVP_MD;
+typedef WOLFSSL_EVP_CIPHER     EVP_CIPHER;
+typedef WOLFSSL_EVP_MD_CTX     EVP_MD_CTX;
+typedef WOLFSSL_EVP_CIPHER_CTX EVP_CIPHER_CTX;
+
+#ifndef NO_MD4
+    #define EVP_md4       wolfSSL_EVP_md4
+#endif
+#ifndef NO_MD5
+    #define EVP_md5       wolfSSL_EVP_md5
+#endif
+#define EVP_sha1      wolfSSL_EVP_sha1
+#define EVP_mdc2      wolfSSL_EVP_mdc2
+#define EVP_dds1      wolfSSL_EVP_sha1
+#define EVP_sha224    wolfSSL_EVP_sha224
+#define EVP_sha256    wolfSSL_EVP_sha256
+#define EVP_sha384    wolfSSL_EVP_sha384
+#define EVP_sha512    wolfSSL_EVP_sha512
+#define EVP_ripemd160 wolfSSL_EVP_ripemd160
+
+#define EVP_sha3_224    wolfSSL_EVP_sha3_224
+#define EVP_sha3_256    wolfSSL_EVP_sha3_256
+#define EVP_sha3_384    wolfSSL_EVP_sha3_384
+#define EVP_sha3_512    wolfSSL_EVP_sha3_512
+
+#define EVP_aes_128_cbc    wolfSSL_EVP_aes_128_cbc
+#define EVP_aes_192_cbc    wolfSSL_EVP_aes_192_cbc
+#define EVP_aes_256_cbc    wolfSSL_EVP_aes_256_cbc
+#define EVP_aes_128_cfb1   wolfSSL_EVP_aes_128_cfb1
+#define EVP_aes_192_cfb1   wolfSSL_EVP_aes_192_cfb1
+#define EVP_aes_256_cfb1   wolfSSL_EVP_aes_256_cfb1
+#define EVP_aes_128_cfb8   wolfSSL_EVP_aes_128_cfb8
+#define EVP_aes_192_cfb8   wolfSSL_EVP_aes_192_cfb8
+#define EVP_aes_256_cfb8   wolfSSL_EVP_aes_256_cfb8
+#define EVP_aes_128_cfb128 wolfSSL_EVP_aes_128_cfb128
+#define EVP_aes_192_cfb128 wolfSSL_EVP_aes_192_cfb128
+#define EVP_aes_256_cfb128 wolfSSL_EVP_aes_256_cfb128
+#define EVP_aes_128_ofb    wolfSSL_EVP_aes_128_ofb
+#define EVP_aes_192_ofb    wolfSSL_EVP_aes_192_ofb
+#define EVP_aes_256_ofb    wolfSSL_EVP_aes_256_ofb
+#define EVP_aes_128_xts    wolfSSL_EVP_aes_128_xts
+#define EVP_aes_256_xts    wolfSSL_EVP_aes_256_xts
+#define EVP_aes_128_gcm    wolfSSL_EVP_aes_128_gcm
+#define EVP_aes_192_gcm    wolfSSL_EVP_aes_192_gcm
+#define EVP_aes_256_gcm    wolfSSL_EVP_aes_256_gcm
+#define EVP_aes_128_ecb    wolfSSL_EVP_aes_128_ecb
+#define EVP_aes_192_ecb    wolfSSL_EVP_aes_192_ecb
+#define EVP_aes_256_ecb    wolfSSL_EVP_aes_256_ecb
+#define EVP_aes_128_ctr    wolfSSL_EVP_aes_128_ctr
+#define EVP_aes_192_ctr    wolfSSL_EVP_aes_192_ctr
+#define EVP_aes_256_ctr    wolfSSL_EVP_aes_256_ctr
+#define EVP_des_cbc        wolfSSL_EVP_des_cbc
+#define EVP_des_ecb        wolfSSL_EVP_des_ecb
+#define EVP_des_ede3_cbc   wolfSSL_EVP_des_ede3_cbc
+#define EVP_des_ede3_ecb   wolfSSL_EVP_des_ede3_ecb
+#define EVP_rc4            wolfSSL_EVP_rc4
+#define EVP_idea_cbc       wolfSSL_EVP_idea_cbc
+#define EVP_enc_null       wolfSSL_EVP_enc_null
+
+#define EVP_MD_size             wolfSSL_EVP_MD_size
+#define EVP_MD_CTX_new          wolfSSL_EVP_MD_CTX_new
+#define EVP_MD_CTX_create       wolfSSL_EVP_MD_CTX_new
+#define EVP_MD_CTX_free         wolfSSL_EVP_MD_CTX_free
+#define EVP_MD_CTX_destroy      wolfSSL_EVP_MD_CTX_free
+#define EVP_MD_CTX_init         wolfSSL_EVP_MD_CTX_init
+#define EVP_MD_CTX_cleanup      wolfSSL_EVP_MD_CTX_cleanup
+#define EVP_MD_CTX_reset        wolfSSL_EVP_MD_CTX_cleanup
+#define EVP_MD_CTX_md           wolfSSL_EVP_MD_CTX_md
+#define EVP_MD_CTX_type         wolfSSL_EVP_MD_CTX_type
+#define EVP_MD_CTX_size         wolfSSL_EVP_MD_CTX_size
+#define EVP_MD_CTX_block_size   wolfSSL_EVP_MD_CTX_block_size
+#define EVP_MD_type             wolfSSL_EVP_MD_type
+#define EVP_MD_block_size       wolfSSL_EVP_MD_block_size
+
+#define EVP_Digest             wolfSSL_EVP_Digest
+#define EVP_DigestInit         wolfSSL_EVP_DigestInit
+#define EVP_DigestInit_ex      wolfSSL_EVP_DigestInit_ex
+#define EVP_DigestUpdate       wolfSSL_EVP_DigestUpdate
+#define EVP_DigestFinal        wolfSSL_EVP_DigestFinal
+#define EVP_DigestFinal_ex     wolfSSL_EVP_DigestFinal_ex
+#define EVP_DigestSignInit     wolfSSL_EVP_DigestSignInit
+#define EVP_DigestSignUpdate   wolfSSL_EVP_DigestSignUpdate
+#define EVP_DigestSignFinal    wolfSSL_EVP_DigestSignFinal
+#define EVP_DigestVerifyInit   wolfSSL_EVP_DigestVerifyInit
+#define EVP_DigestVerifyUpdate wolfSSL_EVP_DigestVerifyUpdate
+#define EVP_DigestVerifyFinal  wolfSSL_EVP_DigestVerifyFinal
+#define EVP_BytesToKey         wolfSSL_EVP_BytesToKey
+
+#define EVP_get_cipherbyname wolfSSL_EVP_get_cipherbyname
+#define EVP_get_digestbyname wolfSSL_EVP_get_digestbyname
+
+#define EVP_CIPHER_CTX_init           wolfSSL_EVP_CIPHER_CTX_init
+#define EVP_CIPHER_CTX_cleanup        wolfSSL_EVP_CIPHER_CTX_cleanup
+#define EVP_CIPHER_CTX_iv_length      wolfSSL_EVP_CIPHER_CTX_iv_length
+#define EVP_CIPHER_CTX_key_length     wolfSSL_EVP_CIPHER_CTX_key_length
+#define EVP_CIPHER_CTX_set_key_length wolfSSL_EVP_CIPHER_CTX_set_key_length
+#define EVP_CIPHER_CTX_mode           wolfSSL_EVP_CIPHER_CTX_mode
+#define EVP_CIPHER_CTX_cipher         wolfSSL_EVP_CIPHER_CTX_cipher
+
+#define EVP_CIPHER_iv_length          wolfSSL_EVP_CIPHER_iv_length
+#define EVP_CIPHER_key_length         wolfSSL_EVP_Cipher_key_length
+
+#define EVP_CipherInit                wolfSSL_EVP_CipherInit
+#define EVP_CipherInit_ex             wolfSSL_EVP_CipherInit_ex
+#define EVP_EncryptInit               wolfSSL_EVP_EncryptInit
+#define EVP_EncryptInit_ex            wolfSSL_EVP_EncryptInit_ex
+#define EVP_DecryptInit               wolfSSL_EVP_DecryptInit
+#define EVP_DecryptInit_ex            wolfSSL_EVP_DecryptInit_ex
+
+#define EVP_Cipher                    wolfSSL_EVP_Cipher
+#define EVP_CipherUpdate              wolfSSL_EVP_CipherUpdate
+#define EVP_EncryptUpdate             wolfSSL_EVP_CipherUpdate
+#define EVP_DecryptUpdate             wolfSSL_EVP_CipherUpdate
+#define EVP_CipherFinal               wolfSSL_EVP_CipherFinal
+#define EVP_CipherFinal_ex            wolfSSL_EVP_CipherFinal
+#define EVP_EncryptFinal              wolfSSL_EVP_CipherFinal
+#define EVP_EncryptFinal_ex           wolfSSL_EVP_CipherFinal
+#define EVP_DecryptFinal              wolfSSL_EVP_CipherFinal
+#define EVP_DecryptFinal_ex           wolfSSL_EVP_CipherFinal
+
+#define EVP_CIPHER_CTX_free           wolfSSL_EVP_CIPHER_CTX_free
+#define EVP_CIPHER_CTX_reset          wolfSSL_EVP_CIPHER_CTX_reset
+#define EVP_CIPHER_CTX_new            wolfSSL_EVP_CIPHER_CTX_new
+
+#define EVP_get_cipherbynid           wolfSSL_EVP_get_cipherbynid
+#define EVP_get_digestbynid           wolfSSL_EVP_get_digestbynid
+#define EVP_get_cipherbyname          wolfSSL_EVP_get_cipherbyname
+#define EVP_get_digestbyname          wolfSSL_EVP_get_digestbyname
+
+#define EVP_PKEY_assign                wolfSSL_EVP_PKEY_assign
+#define EVP_PKEY_assign_RSA            wolfSSL_EVP_PKEY_assign_RSA
+#define EVP_PKEY_assign_DSA            wolfSSL_EVP_PKEY_assign_DSA
+#define EVP_PKEY_assign_DH             wolfSSL_EVP_PKEY_assign_DH
+#define EVP_PKEY_assign_EC_KEY         wolfSSL_EVP_PKEY_assign_EC_KEY
+#define EVP_PKEY_get1_DSA              wolfSSL_EVP_PKEY_get1_DSA
+#define EVP_PKEY_set1_DSA              wolfSSL_EVP_PKEY_set1_DSA
+#define EVP_PKEY_get0_RSA              wolfSSL_EVP_PKEY_get0_RSA
+#define EVP_PKEY_get1_RSA              wolfSSL_EVP_PKEY_get1_RSA
+#define EVP_PKEY_set1_RSA              wolfSSL_EVP_PKEY_set1_RSA
+#define EVP_PKEY_set1_EC_KEY           wolfSSL_EVP_PKEY_set1_EC_KEY
+#define EVP_PKEY_get1_EC_KEY           wolfSSL_EVP_PKEY_get1_EC_KEY
+#define EVP_PKEY_set1_DH               wolfSSL_EVP_PKEY_set1_DH
+#define EVP_PKEY_get0_DH               wolfSSL_EVP_PKEY_get0_DH
+#define EVP_PKEY_get1_DH               wolfSSL_EVP_PKEY_get1_DH
+#define EVP_PKEY_get0_EC_KEY           wolfSSL_EVP_PKEY_get0_EC_KEY
+#define EVP_PKEY_get0_hmac             wolfSSL_EVP_PKEY_get0_hmac
+#define EVP_PKEY_new_mac_key           wolfSSL_EVP_PKEY_new_mac_key
+#define EVP_MD_CTX_copy                wolfSSL_EVP_MD_CTX_copy
+#define EVP_MD_CTX_copy_ex             wolfSSL_EVP_MD_CTX_copy_ex
+#define EVP_PKEY_sign_init             wolfSSL_EVP_PKEY_sign_init
+#define EVP_PKEY_sign                  wolfSSL_EVP_PKEY_sign
+#define EVP_PKEY_keygen                wolfSSL_EVP_PKEY_keygen
+#define EVP_PKEY_keygen_init           wolfSSL_EVP_PKEY_keygen_init
+#define EVP_PKEY_bits                  wolfSSL_EVP_PKEY_bits
+#define EVP_PKEY_CTX_free              wolfSSL_EVP_PKEY_CTX_free
+#define EVP_PKEY_CTX_new               wolfSSL_EVP_PKEY_CTX_new
+#define EVP_PKEY_CTX_set_rsa_padding   wolfSSL_EVP_PKEY_CTX_set_rsa_padding
+#define EVP_PKEY_CTX_new_id            wolfSSL_EVP_PKEY_CTX_new_id
+#define EVP_PKEY_CTX_set_rsa_keygen_bits wolfSSL_EVP_PKEY_CTX_set_rsa_keygen_bits
+#define EVP_PKEY_derive_init           wolfSSL_EVP_PKEY_derive_init
+#define EVP_PKEY_derive_set_peer       wolfSSL_EVP_PKEY_derive_set_peer
+#define EVP_PKEY_derive                wolfSSL_EVP_PKEY_derive
+#define EVP_PKEY_decrypt               wolfSSL_EVP_PKEY_decrypt
+#define EVP_PKEY_decrypt_init          wolfSSL_EVP_PKEY_decrypt_init
+#define EVP_PKEY_encrypt               wolfSSL_EVP_PKEY_encrypt
+#define EVP_PKEY_encrypt_init          wolfSSL_EVP_PKEY_encrypt_init
+#define EVP_PKEY_new                   wolfSSL_EVP_PKEY_new
+#define EVP_PKEY_free                  wolfSSL_EVP_PKEY_free
+#define EVP_PKEY_up_ref                wolfSSL_EVP_PKEY_up_ref
+#define EVP_PKEY_size                  wolfSSL_EVP_PKEY_size
+#define EVP_PKEY_missing_parameters    wolfSSL_EVP_PKEY_missing_parameters
+#define EVP_PKEY_cmp                   wolfSSL_EVP_PKEY_cmp
+#define EVP_PKEY_type                  wolfSSL_EVP_PKEY_type
+#define EVP_PKEY_base_id               wolfSSL_EVP_PKEY_base_id
+#define EVP_PKEY_id                    wolfSSL_EVP_PKEY_id
+#define EVP_SignFinal                  wolfSSL_EVP_SignFinal
+#define EVP_SignInit                   wolfSSL_EVP_SignInit
+#define EVP_SignInit_ex                wolfSSL_EVP_SignInit_ex
+#define EVP_SignUpdate                 wolfSSL_EVP_SignUpdate
+#define EVP_VerifyFinal                wolfSSL_EVP_VerifyFinal
+#define EVP_VerifyInit                 wolfSSL_EVP_VerifyInit
+#define EVP_VerifyUpdate               wolfSSL_EVP_VerifyUpdate
+
+#define EVP_CIPHER_CTX_ctrl        wolfSSL_EVP_CIPHER_CTX_ctrl
+#define EVP_CIPHER_CTX_block_size  wolfSSL_EVP_CIPHER_CTX_block_size
+#define EVP_CIPHER_block_size      wolfSSL_EVP_CIPHER_block_size
+#define EVP_CIPHER_flags           wolfSSL_EVP_CIPHER_flags
+#define EVP_CIPHER_CTX_set_flags   wolfSSL_EVP_CIPHER_CTX_set_flags
+#define EVP_CIPHER_CTX_clear_flags wolfSSL_EVP_CIPHER_CTX_clear_flags
+#define EVP_CIPHER_CTX_set_padding wolfSSL_EVP_CIPHER_CTX_set_padding
+#define EVP_CIPHER_CTX_flags       wolfSSL_EVP_CIPHER_CTX_flags
+#define EVP_CIPHER_CTX_set_iv      wolfSSL_EVP_CIPHER_CTX_set_iv
+#define EVP_add_digest             wolfSSL_EVP_add_digest
+#define EVP_add_cipher             wolfSSL_EVP_add_cipher
+#define EVP_cleanup                wolfSSL_EVP_cleanup
+#define EVP_read_pw_string         wolfSSL_EVP_read_pw_string
+#define EVP_rc2_cbc                wolfSSL_EVP_rc2_cbc
+
+#define OpenSSL_add_all_digests()  wolfSSL_EVP_init()
+#define OpenSSL_add_all_ciphers()  wolfSSL_EVP_init()
+#define OpenSSL_add_all_algorithms wolfSSL_add_all_algorithms
+#define OpenSSL_add_all_algorithms_noconf wolfSSL_OpenSSL_add_all_algorithms_noconf
+#define OpenSSL_add_all_algorithms_conf   wolfSSL_OpenSSL_add_all_algorithms_conf
+
+#define wolfSSL_OPENSSL_add_all_algorithms_noconf wolfSSL_OpenSSL_add_all_algorithms_noconf
+#define wolfSSL_OPENSSL_add_all_algorithms_conf   wolfSSL_OpenSSL_add_all_algorithms_conf
+
+/* provides older OpenSSL API compatibility  */
+#define OPENSSL_add_all_algorithms        OpenSSL_add_all_algorithms
+#define OPENSSL_add_all_algorithms_noconf OpenSSL_add_all_algorithms_noconf
+#define OPENSSL_add_all_algorithms_conf   OpenSSL_add_all_algorithms_conf
+
+#define NO_PADDING_BLOCK_SIZE      1
+
+#define PKCS5_PBKDF2_HMAC_SHA1     wolfSSL_PKCS5_PBKDF2_HMAC_SHA1
+#define PKCS5_PBKDF2_HMAC          wolfSSL_PKCS5_PBKDF2_HMAC
+
+/* OpenSSL compat. ctrl values */
+#define EVP_CTRL_INIT                  0x0
+#define EVP_CTRL_SET_KEY_LENGTH        0x1
+#define EVP_CTRL_SET_RC2_KEY_BITS      0x3  /* needed for qt compilation */
+
+#define EVP_CTRL_AEAD_SET_IVLEN        0x9
+#define EVP_CTRL_AEAD_GET_TAG          0x10
+#define EVP_CTRL_AEAD_SET_TAG          0x11
+#define EVP_CTRL_AEAD_SET_IV_FIXED     0x12
+#define EVP_CTRL_GCM_IV_GEN            0x13
+#define EVP_CTRL_GCM_SET_IVLEN         EVP_CTRL_AEAD_SET_IVLEN
+#define EVP_CTRL_GCM_GET_TAG           EVP_CTRL_AEAD_GET_TAG
+#define EVP_CTRL_GCM_SET_TAG           EVP_CTRL_AEAD_SET_TAG
+#define EVP_CTRL_GCM_SET_IV_FIXED      EVP_CTRL_AEAD_SET_IV_FIXED
+
+#define EVP_PKEY_print_private(arg1, arg2, arg3, arg4)
+
+#ifndef EVP_MAX_MD_SIZE
+    #define EVP_MAX_MD_SIZE   64     /* sha512 */
+#endif
+
+#ifndef EVP_MAX_KEY_LENGTH
+#define EVP_MAX_KEY_LENGTH    64
+#endif
+
+#ifndef EVP_MAX_IV_LENGTH
+#define EVP_MAX_IV_LENGTH     16
+#endif
+
+#ifndef EVP_MAX_BLOCK_LENGTH
+    #define EVP_MAX_BLOCK_LENGTH   32  /* 2 * blocklen(AES)? */
+    /* They define this as 32. Using the same value here. */
+#endif
+
+#ifndef EVP_MAX_IV_LENGTH
+    #define EVP_MAX_IV_LENGTH       16
+#endif
+
+
+#define EVP_R_BAD_DECRYPT               (-MIN_CODE_E + 100 + 1)
+#define EVP_R_BN_DECODE_ERROR           (-MIN_CODE_E + 100 + 2)
+#define EVP_R_DECODE_ERROR              (-MIN_CODE_E + 100 + 3)
+#define EVP_R_PRIVATE_KEY_DECODE_ERROR  (-MIN_CODE_E + 100 + 4)
+
+#define EVP_PKEY_NONE                   NID_undef
+#define EVP_PKEY_RSA                    6
+#define EVP_PKEY_RSA2                   19
+#define EVP_PKEY_DH                     28
+#define EVP_CIPHER_mode                 WOLFSSL_CIPHER_mode
+/* WOLFSSL_EVP_CIPHER is just the string name of the cipher */
+#define EVP_CIPHER_name(x)              x
+#define EVP_MD_CTX_reset                wolfSSL_EVP_MD_CTX_cleanup
+/* WOLFSSL_EVP_MD is just the string name of the digest */
+#define EVP_MD_name(x)                  x
+#define EVP_CIPHER_nid                  wolfSSL_EVP_CIPHER_nid
+
+
+WOLFSSL_API void printPKEY(WOLFSSL_EVP_PKEY *k);
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#include <wolfssl/openssl/objects.h>
+
+#endif /* WOLFSSL_EVP_H_ */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/hmac.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/hmac.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/hmac.h	(revision 453)
@@ -0,0 +1,100 @@
+/* hmac.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+/*  hmac.h defines mini hamc openssl compatibility layer
+ *
+ */
+
+
+#ifndef WOLFSSL_HMAC_H_
+#define WOLFSSL_HMAC_H_
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifdef WOLFSSL_PREFIX
+#include "prefix_hmac.h"
+#endif
+
+#include <wolfssl/openssl/evp.h>
+#include <wolfssl/openssl/opensslv.h>
+#include <wolfssl/wolfcrypt/hmac.h>
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+
+WOLFSSL_API unsigned char* wolfSSL_HMAC(const WOLFSSL_EVP_MD* evp_md,
+                               const void* key, int key_len,
+                               const unsigned char* d, int n, unsigned char* md,
+                               unsigned int* md_len);
+
+
+typedef struct WOLFSSL_HMAC_CTX {
+    Hmac hmac;
+    int  type;
+    word32  save_ipad[WC_HMAC_BLOCK_SIZE  / sizeof(word32)];  /* same block size all*/
+    word32  save_opad[WC_HMAC_BLOCK_SIZE  / sizeof(word32)];
+} WOLFSSL_HMAC_CTX;
+
+
+WOLFSSL_API WOLFSSL_HMAC_CTX* wolfSSL_HMAC_CTX_new(void);
+WOLFSSL_API int wolfSSL_HMAC_CTX_Init(WOLFSSL_HMAC_CTX* ctx);
+WOLFSSL_API int wolfSSL_HMAC_CTX_copy(WOLFSSL_HMAC_CTX* des,
+                                       WOLFSSL_HMAC_CTX* src);
+WOLFSSL_LOCAL int wolfSSL_HmacCopy(Hmac* des, Hmac* src);
+WOLFSSL_API int wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key,
+                                 int keylen, const EVP_MD* type);
+WOLFSSL_API int wolfSSL_HMAC_Init_ex(WOLFSSL_HMAC_CTX* ctx, const void* key,
+                             int keylen, const EVP_MD* type, WOLFSSL_ENGINE* e);
+WOLFSSL_API int wolfSSL_HMAC_Update(WOLFSSL_HMAC_CTX* ctx,
+                                   const unsigned char* data, int len);
+WOLFSSL_API int wolfSSL_HMAC_Final(WOLFSSL_HMAC_CTX* ctx, unsigned char* hash,
+                                  unsigned int* len);
+WOLFSSL_API int wolfSSL_HMAC_cleanup(WOLFSSL_HMAC_CTX* ctx);
+WOLFSSL_API void wolfSSL_HMAC_CTX_free(WOLFSSL_HMAC_CTX* ctx);
+WOLFSSL_API size_t wolfSSL_HMAC_size(const WOLFSSL_HMAC_CTX *ctx);
+
+typedef struct WOLFSSL_HMAC_CTX HMAC_CTX;
+
+#define HMAC(a,b,c,d,e,f,g) wolfSSL_HMAC((a),(b),(c),(d),(e),(f),(g))
+
+#define HMAC_CTX_new wolfSSL_HMAC_CTX_new
+#define HMAC_CTX_init wolfSSL_HMAC_CTX_Init
+#define HMAC_CTX_copy wolfSSL_HMAC_CTX_copy
+#define HMAC_CTX_free wolfSSL_HMAC_CTX_free
+#define HMAC_CTX_reset wolfSSL_HMAC_cleanup
+#define HMAC_Init_ex  wolfSSL_HMAC_Init_ex
+#define HMAC_Init     wolfSSL_HMAC_Init
+#define HMAC_Update   wolfSSL_HMAC_Update
+#define HMAC_Final    wolfSSL_HMAC_Final
+#define HMAC_cleanup  wolfSSL_HMAC_cleanup
+#define HMAC_size     wolfSSL_HMAC_size
+
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+
+#endif /* WOLFSSL_HMAC_H_ */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/md4.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/md4.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/md4.h	(revision 453)
@@ -0,0 +1,62 @@
+/* md4.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifndef WOLFSSL_MD4_H_
+#define WOLFSSL_MD4_H_
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifndef NO_MD4
+
+#ifdef WOLFSSL_PREFIX
+#include "prefix_md4.h"
+#endif
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+
+typedef struct WOLFSSL_MD4_CTX {
+    int buffer[32];      /* big enough to hold, check size in Init */
+} WOLFSSL_MD4_CTX;
+
+
+WOLFSSL_API void wolfSSL_MD4_Init(WOLFSSL_MD4_CTX*);
+WOLFSSL_API void wolfSSL_MD4_Update(WOLFSSL_MD4_CTX*, const void*, unsigned long);
+WOLFSSL_API void wolfSSL_MD4_Final(unsigned char*, WOLFSSL_MD4_CTX*);
+
+
+typedef WOLFSSL_MD4_CTX MD4_CTX;
+
+#define MD4_Init   wolfSSL_MD4_Init
+#define MD4_Update wolfSSL_MD4_Update
+#define MD4_Final  wolfSSL_MD4_Final
+
+#ifdef __cplusplus
+    }  /* extern "C" */
+#endif
+
+#endif /* NO_MD4 */
+
+#endif /* WOLFSSL_MD4_H_ */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/md5.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/md5.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/md5.h	(revision 453)
@@ -0,0 +1,81 @@
+/* md5.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* md5.h for openssl */
+
+
+#ifndef WOLFSSL_MD5_H_
+#define WOLFSSL_MD5_H_
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifndef NO_MD5
+
+#include <wolfssl/wolfcrypt/hash.h>
+
+#ifdef WOLFSSL_PREFIX
+#include "prefix_md5.h"
+#endif
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+
+typedef struct WOLFSSL_MD5_CTX {
+    /* big enough to hold wolfcrypt md5, but check on init */
+#ifdef STM32_HASH
+    void* holder[(112 + WC_ASYNC_DEV_SIZE + sizeof(STM32_HASH_Context)) / sizeof(void*)];
+#else
+    void* holder[(112 + WC_ASYNC_DEV_SIZE) / sizeof(void*)];
+#endif
+} WOLFSSL_MD5_CTX;
+
+WOLFSSL_API int wolfSSL_MD5_Init(WOLFSSL_MD5_CTX*);
+WOLFSSL_API int wolfSSL_MD5_Update(WOLFSSL_MD5_CTX*, const void*, unsigned long);
+WOLFSSL_API int wolfSSL_MD5_Final(unsigned char*, WOLFSSL_MD5_CTX*);
+
+
+typedef WOLFSSL_MD5_CTX MD5_CTX;
+
+#define MD5_Init wolfSSL_MD5_Init
+#define MD5_Update wolfSSL_MD5_Update
+#define MD5_Final wolfSSL_MD5_Final
+
+#ifdef OPENSSL_EXTRA_BSD
+    #define MD5Init wolfSSL_MD5_Init
+    #define MD5Update wolfSSL_MD5_Update
+    #define MD5Final wolfSSL_MD5_Final
+#endif
+
+#ifndef MD5
+#define MD5(d, n, md) wc_Md5Hash((d), (n), (md))
+#endif
+
+#define MD5_DIGEST_LENGTH MD5_DIGEST_SIZE
+
+#ifdef __cplusplus
+    }  /* extern "C" */
+#endif
+
+#endif /* NO_MD5 */
+
+#endif /* WOLFSSL_MD5_H_ */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/objects.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/objects.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/objects.h	(revision 453)
@@ -0,0 +1,63 @@
+/* objects.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifndef WOLFSSL_OBJECTS_H_
+#define WOLFSSL_OBJECTS_H_
+
+#include <wolfssl/wolfcrypt/settings.h>
+//#include <wolfssl/openssl/ssl.h>
+#ifndef OPENSSL_EXTRA_SSL_GUARD
+#define OPENSSL_EXTRA_SSL_GUARD
+#include <wolfssl/ssl.h>
+#endif /* OPENSSL_EXTRA_SSL_GUARD */
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+#define OBJ_nid2sn  wolfSSL_OBJ_nid2sn
+#define OBJ_obj2nid wolfSSL_OBJ_obj2nid
+#define OBJ_sn2nid  wolfSSL_OBJ_sn2nid
+#define OBJ_nid2ln  wolfSSL_OBJ_nid2ln
+#define OBJ_ln2nid  wolfSSL_OBJ_ln2nid
+#define OBJ_txt2nid wolfSSL_OBJ_txt2nid
+#define OBJ_txt2obj wolfSSL_OBJ_txt2obj
+#define OBJ_nid2obj wolfSSL_OBJ_nid2obj
+#define OBJ_obj2txt wolfSSL_OBJ_obj2txt
+#define OBJ_cleanup wolfSSL_OBJ_cleanup
+#define OBJ_cmp     wolfSSL_OBJ_cmp
+#define OBJ_create  wolfSSL_OBJ_create
+#define ASN1_OBJECT_free wolfSSL_ASN1_OBJECT_free
+
+/* not required for wolfSSL */
+#define OPENSSL_load_builtin_modules()
+
+
+#define NID_ad_OCSP                     178
+#define NID_ad_ca_issuers               179
+
+
+#ifdef __cplusplus
+    }  /* extern "C" */
+#endif
+
+#endif /* WOLFSSL_OBJECTS_H_ */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ocsp.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ocsp.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ocsp.h	(revision 453)
@@ -0,0 +1,82 @@
+/* ocsp.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* ocsp.h for libcurl */
+
+#ifndef WOLFSSL_OCSP_H_
+#define WOLFSSL_OCSP_H_
+
+#ifdef HAVE_OCSP
+#include <wolfssl/ocsp.h>
+
+#define OCSP_REQUEST              OcspRequest
+#define OCSP_RESPONSE             OcspResponse
+#define OCSP_BASICRESP            WOLFSSL_OCSP_BASICRESP
+#define OCSP_CERTID               WOLFSSL_OCSP_CERTID
+#define OCSP_ONEREQ               WOLFSSL_OCSP_ONEREQ
+
+#define OCSP_REVOKED_STATUS_NOSTATUS     -1
+
+
+#define OCSP_RESPONSE_STATUS_SUCCESSFUL  0
+#define OCSP_RESPONSE_STATUS_TRYLATER    3
+
+#define V_OCSP_CERTSTATUS_GOOD           0
+#define V_OCSP_CERTSTATUS_REVOKED        1
+#define V_OCSP_CERTSTATUS_UNKNOWN        2
+
+#define OCSP_resp_find_status     wolfSSL_OCSP_resp_find_status
+#define OCSP_cert_status_str      wolfSSL_OCSP_cert_status_str
+#define OCSP_check_validity       wolfSSL_OCSP_check_validity
+
+#define OCSP_CERTID_free          wolfSSL_OCSP_CERTID_free
+#define OCSP_cert_to_id           wolfSSL_OCSP_cert_to_id
+
+#define OCSP_BASICRESP_free       wolfSSL_OCSP_BASICRESP_free
+#define OCSP_basic_verify         wolfSSL_OCSP_basic_verify
+
+#define OCSP_RESPONSE_free        wolfSSL_OCSP_RESPONSE_free
+#define d2i_OCSP_RESPONSE_bio     wolfSSL_d2i_OCSP_RESPONSE_bio
+#define d2i_OCSP_RESPONSE         wolfSSL_d2i_OCSP_RESPONSE
+#define i2d_OCSP_RESPONSE         wolfSSL_i2d_OCSP_RESPONSE
+#define OCSP_response_status      wolfSSL_OCSP_response_status
+#define OCSP_response_status_str  wolfSSL_OCSP_response_status_str
+#define OCSP_response_get1_basic  wolfSSL_OCSP_response_get1_basic
+#define OCSP_response_create      wolfSSL_OCSP_response_create
+
+#define OCSP_REQUEST_new          wolfSSL_OCSP_REQUEST_new
+#define OCSP_REQUEST_free         wolfSSL_OCSP_REQUEST_free
+#define i2d_OCSP_REQUEST          wolfSSL_i2d_OCSP_REQUEST
+#define OCSP_request_add0_id      wolfSSL_OCSP_request_add0_id
+#define OCSP_request_add1_nonce   wolfSSL_OCSP_request_add1_nonce
+#define OCSP_check_nonce          wolfSSL_OCSP_check_nonce
+#define OCSP_id_get0_info         wolfSSL_OCSP_id_get0_info
+#define OCSP_crl_reason_str       wolfSSL_OCSP_crl_reason_str
+#define OCSP_REQUEST_add_ext      wolfSSL_OCSP_REQUEST_add_ext
+
+#define OCSP_CERTID_dup           wolfSSL_OCSP_CERTID_dup
+
+#define i2d_OCSP_REQUEST_bio      wolfSSL_i2d_OCSP_REQUEST_bio
+
+#endif /* HAVE_OCSP */
+
+#endif /* WOLFSSL_OCSP_H_ */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/opensslv.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/opensslv.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/opensslv.h	(revision 453)
@@ -0,0 +1,45 @@
+/* opensslv.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* opensslv.h compatibility */
+
+#ifndef WOLFSSL_OPENSSLV_H_
+#define WOLFSSL_OPENSSLV_H_
+
+
+/* api version compatibility */
+#if defined(WOLFSSL_APACHE_HTTPD)
+    /* For Apache httpd, Use 1.1.0 compatibility */
+     #define OPENSSL_VERSION_NUMBER 0x10100000L
+#elif defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(HAVE_LIGHTY) || \
+    defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
+    defined(WOLFSSL_OPENSSH) || defined(WOLFSSL_QT)
+     /* version number can be increased for Lighty after compatibility for ECDH
+        is added */
+     #define OPENSSL_VERSION_NUMBER 0x1000100fL
+#else
+     #define OPENSSL_VERSION_NUMBER 0x0090810fL
+#endif
+
+#define OPENSSL_VERSION_TEXT             LIBWOLFSSL_VERSION_STRING
+#define OPENSSL_VERSION                  0
+
+#endif /* header */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/pem.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/pem.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/pem.h	(revision 453)
@@ -0,0 +1,256 @@
+/* pem.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* pem.h for openssl */
+
+/*!
+    \file wolfssl/openssl/pem.h
+*/
+
+
+#ifndef WOLFSSL_PEM_H_
+#define WOLFSSL_PEM_H_
+
+#include <wolfssl/openssl/evp.h>
+#include <wolfssl/openssl/bio.h>
+#include <wolfssl/openssl/rsa.h>
+#include <wolfssl/openssl/dsa.h>
+#include <wolfssl/ssl.h>
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+/* RSA */
+WOLFSSL_API
+int wolfSSL_PEM_write_bio_RSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa,
+                                        const EVP_CIPHER* cipher,
+                                        unsigned char* passwd, int len,
+                                        pem_password_cb* cb, void* arg);
+WOLFSSL_API
+WOLFSSL_RSA* wolfSSL_PEM_read_bio_RSAPrivateKey(WOLFSSL_BIO* bio,
+                                                  WOLFSSL_RSA**,
+                                                  pem_password_cb* cb,
+                                                  void* arg);
+
+WOLFSSL_API
+int wolfSSL_PEM_write_bio_RSA_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa);
+
+WOLFSSL_API
+WOLFSSL_RSA *wolfSSL_PEM_read_bio_RSA_PUBKEY(WOLFSSL_BIO* bio,
+                                             WOLFSSL_RSA** rsa,
+                                             pem_password_cb* cb, void *u);
+
+WOLFSSL_API
+WOLFSSL_EC_GROUP* wolfSSL_PEM_read_bio_ECPKParameters(WOLFSSL_BIO* bio,
+                                                      WOLFSSL_EC_GROUP** group,
+                                                      pem_password_cb* cb,
+                                                      void* pass);
+WOLFSSL_API
+int wolfSSL_PEM_write_mem_RSAPrivateKey(RSA* rsa, const EVP_CIPHER* cipher,
+                                        unsigned char* passwd, int len,
+                                        unsigned char **pem, int *plen);
+#if !defined(NO_FILESYSTEM)
+WOLFSSL_API
+int wolfSSL_PEM_write_RSAPrivateKey(XFILE fp, WOLFSSL_RSA *rsa,
+                                    const EVP_CIPHER *enc,
+                                    unsigned char *kstr, int klen,
+                                    pem_password_cb *cb, void *u);
+WOLFSSL_API
+WOLFSSL_RSA *wolfSSL_PEM_read_RSAPublicKey(XFILE fp, WOLFSSL_RSA **x,
+                                           pem_password_cb *cb, void *u);
+WOLFSSL_API
+int wolfSSL_PEM_write_RSAPublicKey(XFILE fp, WOLFSSL_RSA *x);
+
+WOLFSSL_API
+int wolfSSL_PEM_write_RSA_PUBKEY(XFILE fp, WOLFSSL_RSA *x);
+#endif /* NO_FILESYSTEM */
+
+/* DSA */
+WOLFSSL_API
+int wolfSSL_PEM_write_bio_DSAPrivateKey(WOLFSSL_BIO* bio,
+                                        WOLFSSL_DSA* dsa,
+                                        const EVP_CIPHER* cipher,
+                                        unsigned char* passwd, int len,
+                                        pem_password_cb* cb, void* arg);
+
+WOLFSSL_API
+WOLFSSL_DSA* wolfSSL_PEM_read_bio_DSAPrivateKey(WOLFSSL_BIO* bio,
+                                                WOLFSSL_DSA** dsa,
+                                                pem_password_cb* cb,void *pass);
+
+WOLFSSL_API
+WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSA_PUBKEY(WOLFSSL_BIO* bio,WOLFSSL_DSA** dsa,
+                                               pem_password_cb* cb, void *pass);
+
+WOLFSSL_API
+int wolfSSL_PEM_write_bio_DSA_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_DSA* dsa);
+
+WOLFSSL_API
+int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa,
+                                        const EVP_CIPHER* cipher,
+                                        unsigned char* passwd, int len,
+                                        unsigned char **pem, int *plen);
+#if !defined(NO_FILESYSTEM)
+WOLFSSL_API
+int wolfSSL_PEM_write_DSAPrivateKey(XFILE fp, WOLFSSL_DSA *dsa,
+                                    const EVP_CIPHER *enc,
+                                    unsigned char *kstr, int klen,
+                                    pem_password_cb *cb, void *u);
+WOLFSSL_API
+int wolfSSL_PEM_write_DSA_PUBKEY(XFILE fp, WOLFSSL_DSA *x);
+#endif /* NO_FILESYSTEM */
+
+/* ECC */
+WOLFSSL_API
+int wolfSSL_PEM_write_bio_ECPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec,
+                                       const EVP_CIPHER* cipher,
+                                       unsigned char* passwd, int len,
+                                       pem_password_cb* cb, void* arg);
+WOLFSSL_API
+WOLFSSL_EC_KEY* wolfSSL_PEM_read_bio_ECPrivateKey(WOLFSSL_BIO* bio,
+                                                  WOLFSSL_EC_KEY** ec,
+                                                  pem_password_cb* cb,
+                                                  void *pass);
+WOLFSSL_API
+int wolfSSL_PEM_write_bio_EC_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec);
+
+WOLFSSL_API
+int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* key,
+                                       const EVP_CIPHER* cipher,
+                                       unsigned char* passwd, int len,
+                                       unsigned char **pem, int *plen);
+#if !defined(NO_FILESYSTEM)
+WOLFSSL_API
+int wolfSSL_PEM_write_ECPrivateKey(XFILE fp, WOLFSSL_EC_KEY *key,
+                                   const EVP_CIPHER *enc,
+                                   unsigned char *kstr, int klen,
+                                   pem_password_cb *cb, void *u);
+WOLFSSL_API
+int wolfSSL_PEM_write_EC_PUBKEY(XFILE fp, WOLFSSL_EC_KEY *key);
+
+WOLFSSL_API
+WOLFSSL_EC_KEY* wolfSSL_PEM_read_bio_EC_PUBKEY(WOLFSSL_BIO* bio,
+                                               WOLFSSL_EC_KEY** ec,
+                                               pem_password_cb* cb, void *pass);
+#endif /* NO_FILESYSTEM */
+
+/* EVP_KEY */
+WOLFSSL_API
+WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio,
+                                                  WOLFSSL_EVP_PKEY**,
+                                                  pem_password_cb* cb,
+                                                  void* arg);
+WOLFSSL_API
+WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_bio_PUBKEY(WOLFSSL_BIO* bio,
+                                              WOLFSSL_EVP_PKEY **key,
+                                              pem_password_cb *cb, void *pass);
+WOLFSSL_API
+int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key,
+                                        const WOLFSSL_EVP_CIPHER* cipher,
+                                        unsigned char* passwd, int len,
+                                        pem_password_cb* cb, void* arg);
+WOLFSSL_API
+int wolfSSL_PEM_write_bio_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key);
+
+
+WOLFSSL_API
+int wolfSSL_PEM_read_bio(WOLFSSL_BIO* bio, char **name, char **header,
+                         unsigned char **data, long *len);
+WOLFSSL_API
+int wolfSSL_PEM_write_bio(WOLFSSL_BIO *bio, const char *name,
+                          const char *header, const unsigned char *data,
+                          long len);
+#if !defined(NO_FILESYSTEM)
+WOLFSSL_API
+int wolfSSL_PEM_read(XFILE fp, char **name, char **header, unsigned char **data,
+                     long *len);
+WOLFSSL_API
+int wolfSSL_PEM_write(XFILE fp, const char *name, const char *header,
+                      const unsigned char *data, long len);
+#endif
+
+#if !defined(NO_FILESYSTEM)
+WOLFSSL_API
+WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PUBKEY(XFILE fp, EVP_PKEY **x,
+                                          pem_password_cb *cb, void *u);
+WOLFSSL_API
+WOLFSSL_X509 *wolfSSL_PEM_read_X509(XFILE fp, WOLFSSL_X509 **x,
+                                          pem_password_cb *cb, void *u);
+WOLFSSL_API
+WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PrivateKey(XFILE fp, WOLFSSL_EVP_PKEY **x,
+                                          pem_password_cb *cb, void *u);
+
+WOLFSSL_API
+int wolfSSL_PEM_write_X509(XFILE fp, WOLFSSL_X509 *x);
+WOLFSSL_API
+int wolfSSL_PEM_write_DHparams(XFILE fp, WOLFSSL_DH* dh);
+#endif /* NO_FILESYSTEM */
+
+#define PEM_read                        wolfSSL_PEM_read
+#define PEM_read_bio                    wolfSSL_PEM_read_bio
+#define PEM_write                       wolfSSL_PEM_write
+#define PEM_write_bio                   wolfSSL_PEM_write_bio
+
+#define PEM_read_X509                   wolfSSL_PEM_read_X509
+#define PEM_read_PrivateKey             wolfSSL_PEM_read_PrivateKey
+#define PEM_write_X509                  wolfSSL_PEM_write_X509
+#define PEM_write_bio_PrivateKey        wolfSSL_PEM_write_bio_PrivateKey
+#define PEM_write_bio_PKCS8PrivateKey   wolfSSL_PEM_write_bio_PKCS8PrivateKey
+
+/* DH */
+#define PEM_write_DHparams              wolfSSL_PEM_write_DHparams
+/* RSA */
+#define PEM_write_bio_RSAPrivateKey     wolfSSL_PEM_write_bio_RSAPrivateKey
+#define PEM_read_bio_RSAPrivateKey      wolfSSL_PEM_read_bio_RSAPrivateKey
+#define PEM_write_bio_RSA_PUBKEY        wolfSSL_PEM_write_bio_RSA_PUBKEY
+#define PEM_read_bio_RSA_PUBKEY         wolfSSL_PEM_read_bio_RSA_PUBKEY
+#define PEM_read_bio_ECPKParameters     wolfSSL_PEM_read_bio_ECPKParameters
+#define PEM_write_RSAPrivateKey         wolfSSL_PEM_write_RSAPrivateKey
+#define PEM_write_RSA_PUBKEY            wolfSSL_PEM_write_RSA_PUBKEY
+#define PEM_write_RSAPublicKey          wolfSSL_PEM_write_RSAPublicKey
+#define PEM_read_RSAPublicKey           wolfSSL_PEM_read_RSAPublicKey
+/* DSA */
+#define PEM_write_bio_DSAPrivateKey     wolfSSL_PEM_write_bio_DSAPrivateKey
+#define PEM_write_DSAPrivateKey         wolfSSL_PEM_write_DSAPrivateKey
+#define PEM_write_bio_DSA_PUBKEY        wolfSSL_PEM_write_bio_DSA_PUBKEY
+#define PEM_write_DSA_PUBKEY            wolfSSL_PEM_write_DSA_PUBKEY
+#define PEM_read_bio_DSAPrivateKey      wolfSSL_PEM_read_bio_DSAPrivateKey
+#define PEM_read_bio_DSA_PUBKEY         wolfSSL_PEM_read_bio_DSA_PUBKEY
+/* ECC */
+#define PEM_write_bio_ECPrivateKey      wolfSSL_PEM_write_bio_ECPrivateKey
+#define PEM_write_bio_EC_PUBKEY         wolfSSL_PEM_write_bio_EC_PUBKEY
+#define PEM_write_EC_PUBKEY             wolfSSL_PEM_write_EC_PUBKEY
+#define PEM_write_ECPrivateKey          wolfSSL_PEM_write_ECPrivateKey
+#define PEM_read_bio_ECPrivateKey       wolfSSL_PEM_read_bio_ECPrivateKey
+#define PEM_read_bio_EC_PUBKEY          wolfSSL_PEM_read_bio_EC_PUBKEY
+/* EVP_KEY */
+#define PEM_read_bio_PrivateKey         wolfSSL_PEM_read_bio_PrivateKey
+#define PEM_read_PUBKEY                 wolfSSL_PEM_read_PUBKEY
+#define PEM_read_bio_PUBKEY             wolfSSL_PEM_read_bio_PUBKEY
+#define PEM_write_bio_PUBKEY            wolfSSL_PEM_write_bio_PUBKEY
+
+#ifdef __cplusplus
+    }  /* extern "C" */ 
+#endif
+
+#endif /* WOLFSSL_PEM_H_ */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/rand.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/rand.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/rand.h	(revision 453)
@@ -0,0 +1,27 @@
+/* rand.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* rand.h for openSSL */
+
+#include <wolfssl/openssl/ssl.h>
+#include <wolfssl/wolfcrypt/random.h>
+
+#define RAND_set_rand_method     wolfSSL_RAND_set_rand_method
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/rc4.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/rc4.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/rc4.h	(revision 453)
@@ -0,0 +1,59 @@
+/* rc4.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+/*  rc4.h defines mini des openssl compatibility layer
+ *
+ */
+
+#ifndef WOLFSSL_RC4_COMPAT_H_
+#define WOLFSSL_RC4_COMPAT_H_
+
+#include <wolfssl/wolfcrypt/settings.h>
+#include <wolfssl/openssl/ssl.h> /* included for size_t */
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+/* applications including wolfssl/openssl/rc4.h are expecting to have access to
+ * the size of RC4_KEY structures. */
+typedef struct WOLFSSL_RC4_KEY {
+    /* big enough for Arc4 from wolfssl/wolfcrypt/arc4.h */
+    void* holder[(272 + WC_ASYNC_DEV_SIZE) / sizeof(void*)];
+} WOLFSSL_RC4_KEY;
+typedef WOLFSSL_RC4_KEY RC4_KEY;
+
+WOLFSSL_API void wolfSSL_RC4_set_key(WOLFSSL_RC4_KEY* key, int len,
+        const unsigned char* data);
+WOLFSSL_API void wolfSSL_RC4(WOLFSSL_RC4_KEY* key, size_t len,
+        const unsigned char* in, unsigned char* out);
+
+#define RC4         wolfSSL_RC4
+#define RC4_set_key wolfSSL_RC4_set_key
+
+#ifdef __cplusplus
+    }  /* extern "C" */
+#endif
+
+#endif /* WOLFSSL_RC4_COMPAT_H_ */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ripemd.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ripemd.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ripemd.h	(revision 453)
@@ -0,0 +1,58 @@
+/* ripemd.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* ripemd.h for openssl */
+
+
+#ifndef WOLFSSL_RIPEMD_H_
+#define WOLFSSL_RIPEMD_H_
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+
+typedef struct WOLFSSL_RIPEMD_CTX {
+    int holder[32];   /* big enough to hold wolfcrypt, but check on init */
+} WOLFSSL_RIPEMD_CTX;
+
+WOLFSSL_API void wolfSSL_RIPEMD_Init(WOLFSSL_RIPEMD_CTX*);
+WOLFSSL_API void wolfSSL_RIPEMD_Update(WOLFSSL_RIPEMD_CTX*, const void*,
+                                     unsigned long);
+WOLFSSL_API void wolfSSL_RIPEMD_Final(unsigned char*, WOLFSSL_RIPEMD_CTX*);
+
+
+typedef WOLFSSL_RIPEMD_CTX RIPEMD_CTX;
+
+#define RIPEMD_Init   wolfSSL_RIPEMD_Init
+#define RIPEMD_Update wolfSSL_RIPEMD_Update
+#define RIPEMD_Final  wolfSSL_RIPEMD_Final
+
+
+#ifdef __cplusplus
+    }  /* extern "C" */ 
+#endif
+
+
+#endif /* WOLFSSL_MD5_H_ */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/rsa.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/rsa.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/rsa.h	(revision 453)
@@ -0,0 +1,197 @@
+/* rsa.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* rsa.h for openSSL */
+
+
+#ifndef WOLFSSL_RSA_H_
+#define WOLFSSL_RSA_H_
+
+#include <wolfssl/openssl/bn.h>
+#include <wolfssl/openssl/err.h>
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+/* Padding types */
+#define RSA_PKCS1_PADDING      0
+#define RSA_PKCS1_OAEP_PADDING 1
+#define RSA_PKCS1_PSS_PADDING  2
+#define RSA_NO_PADDING         3
+
+/* Emulate OpenSSL flags */
+#define RSA_METHOD_FLAG_NO_CHECK        (1 << 1)
+#define RSA_FLAG_CACHE_PUBLIC           (1 << 2)
+#define RSA_FLAG_CACHE_PRIVATE          (1 << 3)
+#define RSA_FLAG_BLINDING               (1 << 4)
+#define RSA_FLAG_THREAD_SAFE            (1 << 5)
+#define RSA_FLAG_EXT_PKEY               (1 << 6)
+#define RSA_FLAG_NO_BLINDING            (1 << 7)
+#define RSA_FLAG_NO_CONSTTIME           (1 << 8)
+
+/* Salt length same as digest length */
+#define RSA_PSS_SALTLEN_DIGEST   -1
+/* Old max salt length */
+#define RSA_PSS_SALTLEN_MAX_SIGN -2
+/* Max salt length */
+#define RSA_PSS_SALTLEN_MAX      -3
+
+typedef struct WOLFSSL_RSA_METHOD {
+    int flags;
+    char *name;
+} WOLFSSL_RSA_METHOD;
+
+#ifndef WOLFSSL_RSA_TYPE_DEFINED /* guard on redeclaration */
+#define WOLFSSL_RSA_TYPE_DEFINED
+typedef struct WOLFSSL_RSA {
+#ifdef WC_RSA_BLINDING
+    WC_RNG* rng;              /* for PrivateDecrypt blinding */
+#endif
+    WOLFSSL_BIGNUM* n;
+    WOLFSSL_BIGNUM* e;
+    WOLFSSL_BIGNUM* d;
+    WOLFSSL_BIGNUM* p;
+    WOLFSSL_BIGNUM* q;
+    WOLFSSL_BIGNUM* dmp1;      /* dP */
+    WOLFSSL_BIGNUM* dmq1;      /* dQ */
+    WOLFSSL_BIGNUM* iqmp;      /* u */
+    void*          heap;
+    void*          internal;  /* our RSA */
+    char           inSet;     /* internal set from external ? */
+    char           exSet;     /* external set from internal ? */
+    char           ownRng;    /* flag for if the rng should be free'd */
+#if defined(OPENSSL_EXTRA)
+    WOLFSSL_RSA_METHOD* meth;
+#endif
+#if defined(HAVE_EX_DATA)
+    WOLFSSL_CRYPTO_EX_DATA ex_data;  /* external data */
+#endif
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
+    wolfSSL_Mutex    refMutex;                       /* ref count mutex */
+    int              refCount;                       /* reference count */
+#endif
+} WOLFSSL_RSA;
+#endif
+
+typedef WOLFSSL_RSA                   RSA;
+typedef WOLFSSL_RSA_METHOD            RSA_METHOD;
+
+WOLFSSL_API WOLFSSL_RSA* wolfSSL_RSA_new(void);
+WOLFSSL_API void        wolfSSL_RSA_free(WOLFSSL_RSA*);
+
+WOLFSSL_API int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA*, int bits, WOLFSSL_BIGNUM*,
+                                          void* cb);
+
+WOLFSSL_API int wolfSSL_RSA_blinding_on(WOLFSSL_RSA*, WOLFSSL_BN_CTX*);
+WOLFSSL_API int wolfSSL_RSA_public_encrypt(int len, const unsigned char* fr,
+	                               unsigned char* to, WOLFSSL_RSA*, int padding);
+WOLFSSL_API int wolfSSL_RSA_private_decrypt(int len, const unsigned char* fr,
+	                               unsigned char* to, WOLFSSL_RSA*, int padding);
+WOLFSSL_API int wolfSSL_RSA_private_encrypt(int len, unsigned char* in,
+                            unsigned char* out, WOLFSSL_RSA* rsa, int padding);
+
+WOLFSSL_API int wolfSSL_RSA_size(const WOLFSSL_RSA*);
+WOLFSSL_API int wolfSSL_RSA_sign(int type, const unsigned char* m,
+                               unsigned int mLen, unsigned char* sigRet,
+                               unsigned int* sigLen, WOLFSSL_RSA*);
+WOLFSSL_API int wolfSSL_RSA_sign_ex(int type, const unsigned char* m,
+                               unsigned int mLen, unsigned char* sigRet,
+                               unsigned int* sigLen, WOLFSSL_RSA*, int);
+WOLFSSL_API int wolfSSL_RSA_verify(int type, const unsigned char* m,
+                               unsigned int mLen, const unsigned char* sig,
+                               unsigned int sigLen, WOLFSSL_RSA*);
+WOLFSSL_API int wolfSSL_RSA_public_decrypt(int flen, const unsigned char* from,
+                                  unsigned char* to, WOLFSSL_RSA*, int padding);
+WOLFSSL_API int wolfSSL_RSA_GenAdd(WOLFSSL_RSA*);
+WOLFSSL_API int wolfSSL_RSA_LoadDer(WOLFSSL_RSA*, const unsigned char*, int sz);
+WOLFSSL_API int wolfSSL_RSA_LoadDer_ex(WOLFSSL_RSA*, const unsigned char*, int sz, int opt);
+
+WOLFSSL_API WOLFSSL_RSA_METHOD *wolfSSL_RSA_meth_new(const char *name, int flags);
+WOLFSSL_API void wolfSSL_RSA_meth_free(WOLFSSL_RSA_METHOD *meth);
+WOLFSSL_API int wolfSSL_RSA_meth_set(WOLFSSL_RSA_METHOD *rsa, void* p);
+WOLFSSL_API int wolfSSL_RSA_set_method(WOLFSSL_RSA *rsa, WOLFSSL_RSA_METHOD *meth);
+WOLFSSL_API const WOLFSSL_RSA_METHOD* wolfSSL_RSA_get_method(const WOLFSSL_RSA *rsa);
+WOLFSSL_API const WOLFSSL_RSA_METHOD* wolfSSL_RSA_get_default_method(void);
+
+WOLFSSL_API void wolfSSL_RSA_get0_key(const WOLFSSL_RSA *r, const WOLFSSL_BIGNUM **n,
+                                      const WOLFSSL_BIGNUM **e, const WOLFSSL_BIGNUM **d);
+WOLFSSL_API int wolfSSL_RSA_set0_key(WOLFSSL_RSA *r, WOLFSSL_BIGNUM *n, WOLFSSL_BIGNUM *e,
+                                     WOLFSSL_BIGNUM *d);
+WOLFSSL_API int wolfSSL_RSA_flags(const WOLFSSL_RSA *r);
+WOLFSSL_API void wolfSSL_RSA_set_flags(WOLFSSL_RSA *r, int flags);
+
+WOLFSSL_API WOLFSSL_RSA* wolfSSL_RSAPublicKey_dup(WOLFSSL_RSA *rsa);
+
+WOLFSSL_API void* wolfSSL_RSA_get_ex_data(const WOLFSSL_RSA *rsa, int idx);
+WOLFSSL_API int wolfSSL_RSA_set_ex_data(WOLFSSL_RSA *rsa, int idx, void *data);
+
+
+#define WOLFSSL_RSA_LOAD_PRIVATE 1
+#define WOLFSSL_RSA_LOAD_PUBLIC  2
+#define WOLFSSL_RSA_F4           0x10001L
+
+#define RSA_new  wolfSSL_RSA_new
+#define RSA_free wolfSSL_RSA_free
+
+#define RSA_generate_key_ex wolfSSL_RSA_generate_key_ex
+
+#define RSA_blinding_on     wolfSSL_RSA_blinding_on
+#define RSA_public_encrypt  wolfSSL_RSA_public_encrypt
+#define RSA_private_decrypt wolfSSL_RSA_private_decrypt
+#define RSA_private_encrypt wolfSSL_RSA_private_encrypt
+
+#define RSA_size           wolfSSL_RSA_size
+#define RSA_sign           wolfSSL_RSA_sign
+#define RSA_verify         wolfSSL_RSA_verify
+#define RSA_public_decrypt wolfSSL_RSA_public_decrypt
+
+#define RSA_meth_new            wolfSSL_RSA_meth_new
+#define RSA_meth_free           wolfSSL_RSA_meth_free
+#define RSA_meth_set_pub_enc    wolfSSL_RSA_meth_set
+#define RSA_meth_set_pub_dec    wolfSSL_RSA_meth_set
+#define RSA_meth_set_priv_enc   wolfSSL_RSA_meth_set
+#define RSA_meth_set_priv_dec   wolfSSL_RSA_meth_set
+#define RSA_meth_set_init       wolfSSL_RSA_meth_set
+#define RSA_meth_set_finish     wolfSSL_RSA_meth_set
+#define RSA_meth_set0_app_data  wolfSSL_RSA_meth_set
+#define RSA_get_default_method  wolfSSL_RSA_get_default_method
+#define RSA_get_method          wolfSSL_RSA_get_method
+#define RSA_set_method          wolfSSL_RSA_set_method
+#define RSA_get0_key            wolfSSL_RSA_get0_key
+#define RSA_set0_key            wolfSSL_RSA_set0_key
+#define RSA_flags               wolfSSL_RSA_flags
+#define RSA_set_flags           wolfSSL_RSA_set_flags
+
+#define RSAPublicKey_dup        wolfSSL_RSAPublicKey_dup
+#define RSA_get_ex_data        wolfSSL_RSA_get_ex_data
+#define RSA_set_ex_data        wolfSSL_RSA_set_ex_data
+
+#define RSA_get0_key       wolfSSL_RSA_get0_key
+
+#define RSA_F4             WOLFSSL_RSA_F4
+
+#ifdef __cplusplus
+    }  /* extern "C" */
+#endif
+
+#endif /* header */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/sha.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/sha.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/sha.h	(revision 453)
@@ -0,0 +1,203 @@
+/* sha.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* sha.h for openssl */
+
+
+#ifndef WOLFSSL_SHA_H_
+#define WOLFSSL_SHA_H_
+
+#include <wolfssl/wolfcrypt/settings.h>
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifdef WOLFSSL_PREFIX
+#include "prefix_sha.h"
+#endif
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+
+typedef struct WOLFSSL_SHA_CTX {
+    /* big enough to hold wolfcrypt Sha, but check on init */
+#if defined(STM32_HASH)
+    void* holder[(112 + WC_ASYNC_DEV_SIZE + sizeof(STM32_HASH_Context)) / sizeof(void*)];
+#else
+    void* holder[(112 + WC_ASYNC_DEV_SIZE) / sizeof(void*)];
+#endif
+    #ifdef WOLF_CRYPTO_CB
+    void* cryptocb_holder[(sizeof(int) + sizeof(void*) + 4) / sizeof(void*)];
+    #endif
+} WOLFSSL_SHA_CTX;
+
+WOLFSSL_API int wolfSSL_SHA_Init(WOLFSSL_SHA_CTX*);
+WOLFSSL_API int wolfSSL_SHA_Update(WOLFSSL_SHA_CTX*, const void*, unsigned long);
+WOLFSSL_API int wolfSSL_SHA_Final(unsigned char*, WOLFSSL_SHA_CTX*);
+
+/* SHA1 points to above, shouldn't use SHA0 ever */
+WOLFSSL_API int wolfSSL_SHA1_Init(WOLFSSL_SHA_CTX*);
+WOLFSSL_API int wolfSSL_SHA1_Update(WOLFSSL_SHA_CTX*, const void*, unsigned long);
+WOLFSSL_API int wolfSSL_SHA1_Final(unsigned char*, WOLFSSL_SHA_CTX*);
+
+enum {
+    SHA_DIGEST_LENGTH = 20
+};
+
+
+typedef WOLFSSL_SHA_CTX SHA_CTX;
+
+#define SHA_Init wolfSSL_SHA_Init
+#define SHA_Update wolfSSL_SHA_Update
+#define SHA_Final wolfSSL_SHA_Final
+
+#define SHA1_Init wolfSSL_SHA1_Init
+#define SHA1_Update wolfSSL_SHA1_Update
+#define SHA1_Final wolfSSL_SHA1_Final
+
+
+#ifdef WOLFSSL_SHA224
+
+/* Using ALIGN16 because when AES-NI is enabled digest and buffer in Sha256
+ * struct are 16 byte aligned. Any dereference to those elements after casting
+ * to Sha224, is expected to also be 16 byte aligned addresses.  */
+typedef struct WOLFSSL_SHA224_CTX {
+    /* big enough to hold wolfcrypt Sha224, but check on init */
+    ALIGN16 void* holder[(272 + WC_ASYNC_DEV_SIZE) / sizeof(void*)];
+} WOLFSSL_SHA224_CTX;
+
+WOLFSSL_API int wolfSSL_SHA224_Init(WOLFSSL_SHA224_CTX*);
+WOLFSSL_API int wolfSSL_SHA224_Update(WOLFSSL_SHA224_CTX*, const void*,
+	                                 unsigned long);
+WOLFSSL_API int wolfSSL_SHA224_Final(unsigned char*, WOLFSSL_SHA224_CTX*);
+
+enum {
+    SHA224_DIGEST_LENGTH = 28
+};
+
+
+typedef WOLFSSL_SHA224_CTX SHA224_CTX;
+
+#define SHA224_Init   wolfSSL_SHA224_Init
+#define SHA224_Update wolfSSL_SHA224_Update
+#define SHA224_Final  wolfSSL_SHA224_Final
+
+#endif /* WOLFSSL_SHA224 */
+
+
+/* Using ALIGN16 because when AES-NI is enabled digest and buffer in Sha256
+ * struct are 16 byte aligned. Any dereference to those elements after casting
+ * to Sha256, is expected to also be 16 byte aligned addresses.  */
+typedef struct WOLFSSL_SHA256_CTX {
+    /* big enough to hold wolfcrypt Sha256, but check on init */
+    ALIGN16 void* holder[(272 + WC_ASYNC_DEV_SIZE) / sizeof(void*)];
+} WOLFSSL_SHA256_CTX;
+
+WOLFSSL_API int wolfSSL_SHA256_Init(WOLFSSL_SHA256_CTX*);
+WOLFSSL_API int wolfSSL_SHA256_Update(WOLFSSL_SHA256_CTX*, const void*,
+	                                 unsigned long);
+WOLFSSL_API int wolfSSL_SHA256_Final(unsigned char*, WOLFSSL_SHA256_CTX*);
+
+enum {
+    SHA256_DIGEST_LENGTH = 32
+};
+
+
+typedef WOLFSSL_SHA256_CTX SHA256_CTX;
+
+#define SHA256_Init   wolfSSL_SHA256_Init
+#define SHA256_Update wolfSSL_SHA256_Update
+#define SHA256_Final  wolfSSL_SHA256_Final
+#if defined(NO_OLD_SHA_NAMES) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
+    /* SHA256 is only available in non-fips mode because of SHA256 enum in FIPS
+     * build. */
+    #define SHA256 wolfSSL_SHA256
+#endif
+
+
+#ifdef WOLFSSL_SHA384
+
+typedef struct WOLFSSL_SHA384_CTX {
+    /* big enough to hold wolfCrypt Sha384, but check on init */
+    void* holder[(256 + WC_ASYNC_DEV_SIZE) / sizeof(void*)];
+} WOLFSSL_SHA384_CTX;
+
+WOLFSSL_API int wolfSSL_SHA384_Init(WOLFSSL_SHA384_CTX*);
+WOLFSSL_API int wolfSSL_SHA384_Update(WOLFSSL_SHA384_CTX*, const void*,
+	                                 unsigned long);
+WOLFSSL_API int wolfSSL_SHA384_Final(unsigned char*, WOLFSSL_SHA384_CTX*);
+
+enum {
+    SHA384_DIGEST_LENGTH = 48
+};
+
+
+typedef WOLFSSL_SHA384_CTX SHA384_CTX;
+
+#define SHA384_Init   wolfSSL_SHA384_Init
+#define SHA384_Update wolfSSL_SHA384_Update
+#define SHA384_Final  wolfSSL_SHA384_Final
+#if defined(NO_OLD_SHA_NAMES) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
+    /* SHA384 is only available in non-fips mode because of SHA384 enum in FIPS
+     * build. */
+    #define SHA384 wolfSSL_SHA384
+#endif
+#endif /* WOLFSSL_SHA384 */
+
+#ifdef WOLFSSL_SHA512
+
+typedef struct WOLFSSL_SHA512_CTX {
+    /* big enough to hold wolfCrypt Sha384, but check on init */
+    void* holder[(288 + WC_ASYNC_DEV_SIZE) / sizeof(void*)];
+} WOLFSSL_SHA512_CTX;
+
+WOLFSSL_API int wolfSSL_SHA512_Init(WOLFSSL_SHA512_CTX*);
+WOLFSSL_API int wolfSSL_SHA512_Update(WOLFSSL_SHA512_CTX*, const void*,
+	                                 unsigned long);
+WOLFSSL_API int wolfSSL_SHA512_Final(unsigned char*, WOLFSSL_SHA512_CTX*);
+
+enum {
+    SHA512_DIGEST_LENGTH = 64
+};
+
+
+typedef WOLFSSL_SHA512_CTX SHA512_CTX;
+
+#define SHA512_Init   wolfSSL_SHA512_Init
+#define SHA512_Update wolfSSL_SHA512_Update
+#define SHA512_Final  wolfSSL_SHA512_Final
+#if defined(NO_OLD_SHA_NAMES) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
+    /* SHA512 is only available in non-fips mode because of SHA512 enum in FIPS
+     * build. */
+    #define SHA512 wolfSSL_SHA512
+#endif
+#endif /* WOLFSSL_SHA512 */
+
+
+
+
+#ifdef __cplusplus
+    }  /* extern "C" */
+#endif
+
+
+#endif /* WOLFSSL_SHA_H_ */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/sha3.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/sha3.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/sha3.h	(revision 453)
@@ -0,0 +1,150 @@
+/* sha3.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* sha3.h for openssl */
+
+
+#ifndef WOLFSSL_SHA3_H_
+#define WOLFSSL_SHA3_H_
+
+#include <wolfssl/wolfcrypt/settings.h>
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifdef WOLFSSL_PREFIX
+#include "prefix_sha.h"
+#endif
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+
+/* Using ALIGN16 because when AES-NI is enabled digest and buffer in Sha3
+ * struct are 16 byte aligned. Any dereference to those elements after casting
+ * to Sha3 is expected to also be 16 byte aligned addresses.  */
+struct WOLFSSL_SHA3_CTX {
+    /* big enough to hold wolfcrypt Sha3, but check on init */
+    ALIGN16 void* holder[(424 + WC_ASYNC_DEV_SIZE) / sizeof(void*)];
+};
+
+#ifndef WOLFSSL_NOSHA3_224
+typedef struct WOLFSSL_SHA3_CTX WOLFSSL_SHA3_224_CTX;
+
+WOLFSSL_API int wolfSSL_SHA3_224_Init(WOLFSSL_SHA3_224_CTX*);
+WOLFSSL_API int wolfSSL_SHA3_224_Update(WOLFSSL_SHA3_224_CTX*, const void*,
+                                     unsigned long);
+WOLFSSL_API int wolfSSL_SHA3_224_Final(unsigned char*, WOLFSSL_SHA3_224_CTX*);
+
+enum {
+    SHA3_224_DIGEST_LENGTH = 28
+};
+
+typedef WOLFSSL_SHA3_224_CTX SHA3_224_CTX;
+
+#define SHA3_224_Init   wolfSSL_SHA3_224_Init
+#define SHA3_224_Update wolfSSL_SHA3_224_Update
+#define SHA3_224_Final  wolfSSL_SHA3_224_Final
+#if defined(NO_OLD_WC_NAMES) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
+    #define SHA3_224 wolfSSL_SHA3_224
+#endif
+#endif /* WOLFSSL_NOSHA3_224 */
+
+
+#ifndef WOLFSSL_NOSHA3_256
+typedef struct WOLFSSL_SHA3_CTX WOLFSSL_SHA3_256_CTX;
+
+
+WOLFSSL_API int wolfSSL_SHA3_256_Init(WOLFSSL_SHA3_256_CTX*);
+WOLFSSL_API int wolfSSL_SHA3_256_Update(WOLFSSL_SHA3_256_CTX*, const void*,
+                                     unsigned long);
+WOLFSSL_API int wolfSSL_SHA3_256_Final(unsigned char*, WOLFSSL_SHA3_256_CTX*);
+
+enum {
+    SHA3_256_DIGEST_LENGTH = 32
+};
+
+
+typedef WOLFSSL_SHA3_256_CTX SHA3_256_CTX;
+
+#define SHA3_256_Init   wolfSSL_SHA3_256_Init
+#define SHA3_256_Update wolfSSL_SHA3_256_Update
+#define SHA3_256_Final  wolfSSL_SHA3_256_Final
+#if defined(NO_OLD_WC_NAMES) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
+    #define SHA3_256 wolfSSL_SHA3_256
+#endif
+#endif /* WOLFSSL_NOSHA3_256 */
+
+
+typedef struct WOLFSSL_SHA3_CTX WOLFSSL_SHA3_384_CTX;
+
+WOLFSSL_API int wolfSSL_SHA3_384_Init(WOLFSSL_SHA3_384_CTX*);
+WOLFSSL_API int wolfSSL_SHA3_384_Update(WOLFSSL_SHA3_384_CTX*, const void*,
+	                                 unsigned long);
+WOLFSSL_API int wolfSSL_SHA3_384_Final(unsigned char*, WOLFSSL_SHA3_384_CTX*);
+
+enum {
+    SHA3_384_DIGEST_LENGTH = 48
+};
+
+typedef WOLFSSL_SHA3_384_CTX SHA3_384_CTX;
+
+#define SHA3_384_Init   wolfSSL_SHA3_384_Init
+#define SHA3_384_Update wolfSSL_SHA3_384_Update
+#define SHA3_384_Final  wolfSSL_SHA3_384_Final
+#if defined(NO_OLD_WC_NAMES) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
+    #define SHA3_384 wolfSSL_SHA3_384
+#endif
+
+
+#ifndef WOLFSSL_NOSHA3_512
+
+typedef struct WOLFSSL_SHA3_CTX WOLFSSL_SHA3_512_CTX;
+
+WOLFSSL_API int wolfSSL_SHA3_512_Init(WOLFSSL_SHA3_512_CTX*);
+WOLFSSL_API int wolfSSL_SHA3_512_Update(WOLFSSL_SHA3_512_CTX*, const void*,
+	                                 unsigned long);
+WOLFSSL_API int wolfSSL_SHA3_512_Final(unsigned char*, WOLFSSL_SHA3_512_CTX*);
+
+enum {
+    SHA3_512_DIGEST_LENGTH = 64
+};
+
+
+typedef WOLFSSL_SHA3_512_CTX SHA3_512_CTX;
+
+#define SHA3_512_Init   wolfSSL_SHA3_512_Init
+#define SHA3_512_Update wolfSSL_SHA3_512_Update
+#define SHA3_512_Final  wolfSSL_SHA3_512_Final
+#if defined(NO_OLD_WC_NAMES) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
+    #define SHA3_512 wolfSSL_SHA3_512
+#endif
+#endif /* WOLFSSL_NOSHA3_512 */
+
+
+
+
+#ifdef __cplusplus
+    }  /* extern "C" */
+#endif
+
+
+#endif /* WOLFSSL_SHA3_H_ */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ssl.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ssl.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ssl.h	(revision 453)
@@ -0,0 +1,1245 @@
+/* ssl.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+/*  ssl.h defines wolfssl_openssl compatibility layer
+ *
+ */
+
+
+#ifndef WOLFSSL_OPENSSL_H_
+#define WOLFSSL_OPENSSL_H_
+
+/* wolfssl_openssl compatibility layer */
+#ifndef OPENSSL_EXTRA_SSL_GUARD
+#define OPENSSL_EXTRA_SSL_GUARD
+#include <wolfssl/ssl.h>
+#endif /* OPENSSL_EXTRA_SSL_GUARD */
+
+#include <wolfssl/openssl/tls1.h>
+#include <wolfssl/openssl/evp.h>
+#include <wolfssl/openssl/bio.h>
+#ifdef OPENSSL_EXTRA
+#include <wolfssl/openssl/crypto.h>
+#endif
+
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+#include <wolfssl/openssl/dh.h>
+#include <wolfssl/openssl/objects.h>
+#endif
+
+/* need MIN_CODE_E to determine wolfSSL error range */
+#include <wolfssl/wolfcrypt/error-crypt.h>
+
+/* all NID_* values are in asn.h */
+#include <wolfssl/wolfcrypt/asn.h>
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+#ifdef _WIN32
+    /* wincrypt.h clashes */
+    #undef X509_NAME
+#endif
+
+#ifdef WOLFSSL_UTASKER
+    /* tcpip.h clashes */
+    #undef ASN1_INTEGER
+#endif
+
+
+typedef WOLFSSL          SSL;
+typedef WOLFSSL_SESSION  SSL_SESSION;
+typedef WOLFSSL_METHOD   SSL_METHOD;
+typedef WOLFSSL_CTX      SSL_CTX;
+
+typedef WOLFSSL_X509       X509;
+typedef WOLFSSL_X509       X509_REQ;
+typedef WOLFSSL_X509_NAME  X509_NAME;
+typedef WOLFSSL_X509_INFO  X509_INFO;
+typedef WOLFSSL_X509_CHAIN X509_CHAIN;
+
+typedef WOLFSSL_STACK      EXTENDED_KEY_USAGE;
+
+
+/* redeclare guard */
+#define WOLFSSL_TYPES_DEFINED
+
+typedef WOLFSSL_BIO            BIO;
+typedef WOLFSSL_BIO_METHOD     BIO_METHOD;
+typedef WOLFSSL_CIPHER         SSL_CIPHER;
+typedef WOLFSSL_X509_LOOKUP    X509_LOOKUP;
+typedef WOLFSSL_X509_LOOKUP_METHOD X509_LOOKUP_METHOD;
+typedef WOLFSSL_X509_CRL       X509_CRL;
+typedef WOLFSSL_X509_EXTENSION X509_EXTENSION;
+typedef WOLFSSL_X509_PUBKEY    X509_PUBKEY;
+typedef WOLFSSL_X509_ALGOR     X509_ALGOR;
+typedef WOLFSSL_ASN1_TIME      ASN1_TIME;
+typedef WOLFSSL_ASN1_INTEGER   ASN1_INTEGER;
+typedef WOLFSSL_ASN1_OBJECT    ASN1_OBJECT;
+typedef WOLFSSL_ASN1_STRING    ASN1_STRING;
+typedef WOLFSSL_ASN1_TYPE      ASN1_TYPE;
+typedef WOLFSSL_ASN1_BIT_STRING ASN1_BIT_STRING;
+typedef WOLFSSL_dynlock_value  CRYPTO_dynlock_value;
+typedef WOLFSSL_BUF_MEM        BUF_MEM;
+typedef WOLFSSL_GENERAL_NAMES  GENERAL_NAMES;
+typedef WOLFSSL_GENERAL_NAME GENERAL_NAME;
+
+#define ASN1_UTCTIME         WOLFSSL_ASN1_TIME
+#define ASN1_GENERALIZEDTIME WOLFSSL_ASN1_TIME
+
+typedef WOLFSSL_COMP_METHOD    COMP_METHOD;
+typedef WOLFSSL_COMP           SSL_COMP;
+typedef WOLFSSL_X509_REVOKED   X509_REVOKED;
+typedef WOLFSSL_X509_OBJECT    X509_OBJECT;
+typedef WOLFSSL_X509_STORE     X509_STORE;
+typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX;
+typedef WOLFSSL_X509_VERIFY_PARAM X509_VERIFY_PARAM;
+
+#define EVP_CIPHER_INFO        EncryptedInfo
+
+#define STACK_OF(x) WOLFSSL_STACK
+#define OPENSSL_STACK WOLFSSL_STACK
+#define _STACK OPENSSL_STACK
+
+#define CONF_get1_default_config_file   wolfSSL_CONF_get1_default_config_file
+typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS;
+
+#ifdef WOLFSSL_QT
+    #if defined(NO_WOLFSSL_MEMORY)
+        #define CRYPTO_free(xp)         XFREE(xp, NULL, NULL);
+    #else
+        #define CRYPTO_free(xp) { if((xp)) wolfSSL_Free((xp));}
+    #endif
+#else
+  #define CRYPTO_free                     XFREE
+#endif
+
+#define CRYPTO_malloc                   XMALLOC
+#define CRYPTO_EX_new                   WOLFSSL_CRYPTO_EX_new
+#define CRYPTO_EX_dup                   WOLFSSL_CRYPTO_EX_dup
+#define CRYPTO_EX_free                  WOLFSSL_CRYPTO_EX_free
+#define CRYPTO_EX_DATA                  WOLFSSL_CRYPTO_EX_DATA
+
+/* depreciated */
+#define CRYPTO_thread_id                wolfSSL_thread_id
+#define CRYPTO_set_id_callback          wolfSSL_set_id_callback
+
+#define CRYPTO_LOCK             0x01
+#define CRYPTO_UNLOCK           0x02
+#define CRYPTO_READ             0x04
+#define CRYPTO_WRITE            0x08
+
+#define CRYPTO_set_locking_callback     wolfSSL_set_locking_callback
+#define CRYPTO_set_dynlock_create_callback  wolfSSL_set_dynlock_create_callback
+#define CRYPTO_set_dynlock_lock_callback wolfSSL_set_dynlock_lock_callback
+#define CRYPTO_set_dynlock_destroy_callback wolfSSL_set_dynlock_destroy_callback
+#define CRYPTO_num_locks                wolfSSL_num_locks
+#define CRYPTO_dynlock_value            WOLFSSL_dynlock_value
+
+#define CRYPTO_cleanup_all_ex_data      wolfSSL_cleanup_all_ex_data
+#define set_ex_data                     wolfSSL_CRYPTO_set_ex_data
+#define get_ex_data                     wolfSSL_CRYPTO_get_ex_data
+
+/* this function was used to set the default malloc, free, and realloc */
+#define CRYPTO_malloc_init() 0 /* CRYPTO_malloc_init is not needed */
+#define OPENSSL_malloc_init() 0 /* OPENSSL_malloc_init is not needed */
+
+#define SSL_get_client_random(ssl,out,outSz) \
+                                  wolfSSL_get_client_random((ssl),(out),(outSz))
+#define SSL_get_cipher_list(ctx,i)         wolfSSL_get_cipher_list_ex((ctx),(i))
+#define SSL_get_cipher_name(ctx)           wolfSSL_get_cipher((ctx))
+#define SSL_get_shared_ciphers(ctx,buf,len) \
+                                   wolfSSL_get_shared_ciphers((ctx),(buf),(len))
+
+/* at the moment only returns ok */
+#define SSL_get_verify_result           wolfSSL_get_verify_result
+#define SSL_get_verify_mode             wolfSSL_SSL_get_mode
+#define SSL_get_verify_depth            wolfSSL_get_verify_depth
+#define SSL_CTX_get_verify_mode         wolfSSL_CTX_get_verify_mode
+#define SSL_CTX_get_verify_depth        wolfSSL_CTX_get_verify_depth
+#define SSL_get_certificate             wolfSSL_get_certificate
+#define SSL_use_certificate             wolfSSL_use_certificate
+#define SSL_use_certificate_ASN1        wolfSSL_use_certificate_ASN1
+#define d2i_PKCS8_PRIV_KEY_INFO_bio     wolfSSL_d2i_PKCS8_PKEY_bio
+#define d2i_PKCS8PrivateKey_bio         wolfSSL_d2i_PKCS8PrivateKey_bio
+#define PKCS8_PRIV_KEY_INFO_free        wolfSSL_EVP_PKEY_free
+#define d2i_PKCS12_fp                   wolfSSL_d2i_PKCS12_fp
+
+#define d2i_PUBKEY                      wolfSSL_d2i_PUBKEY
+#define d2i_PUBKEY_bio                  wolfSSL_d2i_PUBKEY_bio
+#define d2i_PrivateKey                  wolfSSL_d2i_PrivateKey
+#define d2i_AutoPrivateKey              wolfSSL_d2i_AutoPrivateKey
+#define i2d_PrivateKey                  wolfSSL_i2d_PrivateKey
+#define SSL_use_PrivateKey              wolfSSL_use_PrivateKey
+#define SSL_use_PrivateKey_ASN1         wolfSSL_use_PrivateKey_ASN1
+#define SSL_use_RSAPrivateKey_ASN1      wolfSSL_use_RSAPrivateKey_ASN1
+#define SSL_get_privatekey              wolfSSL_get_privatekey
+#define SSL_CTX_use_PrivateKey_ASN1     wolfSSL_CTX_use_PrivateKey_ASN1
+
+#define SSLv23_method                   wolfSSLv23_method
+#define SSLv23_client_method            wolfSSLv23_client_method
+#define SSLv2_client_method             wolfSSLv2_client_method
+#define SSLv2_server_method             wolfSSLv2_server_method
+#define SSLv3_server_method             wolfSSLv3_server_method
+#define SSLv3_client_method             wolfSSLv3_client_method
+#define TLS_client_method               wolfTLS_client_method
+#define TLS_server_method               wolfTLS_server_method
+#define TLSv1_method                    wolfTLSv1_method
+#define TLSv1_server_method             wolfTLSv1_server_method
+#define TLSv1_client_method             wolfTLSv1_client_method
+#define TLSv1_1_method                  wolfTLSv1_1_method
+#define TLSv1_1_server_method           wolfTLSv1_1_server_method
+#define TLSv1_1_client_method           wolfTLSv1_1_client_method
+#define TLSv1_2_method                  wolfTLSv1_2_method
+#define TLSv1_2_server_method           wolfTLSv1_2_server_method
+#define TLSv1_2_client_method           wolfTLSv1_2_client_method
+#define TLSv1_3_method                  wolfTLSv1_3_method
+#define TLSv1_3_server_method           wolfTLSv1_3_server_method
+#define TLSv1_3_client_method           wolfTLSv1_3_client_method
+#define TLS_method                      wolfSSLv23_method
+
+#define X509_FILETYPE_ASN1 SSL_FILETYPE_ASN1
+
+#define X509_F_X509_CHECK_PRIVATE_KEY   128
+
+#ifdef WOLFSSL_DTLS
+    #define DTLSv1_client_method        wolfDTLSv1_client_method
+    #define DTLSv1_server_method        wolfDTLSv1_server_method
+    #define DTLSv1_2_client_method      wolfDTLSv1_2_client_method
+    #define DTLSv1_2_server_method      wolfDTLSv1_2_server_method
+    #define DTLS_method                 wolfDTLS_method
+#endif
+
+
+#ifndef NO_FILESYSTEM
+    #define SSL_CTX_use_certificate_file      wolfSSL_CTX_use_certificate_file
+    #define SSL_CTX_use_PrivateKey_file       wolfSSL_CTX_use_PrivateKey_file
+#ifdef WOLFSSL_APACHE_HTTPD
+    #define SSL_CTX_load_verify_locations(ctx,file,path) \
+        wolfSSL_CTX_load_verify_locations_ex(ctx,file,path,\
+                                                   WOLFSSL_LOAD_FLAG_IGNORE_ERR)
+#else
+    #define SSL_CTX_load_verify_locations     wolfSSL_CTX_load_verify_locations
+#endif
+    #define SSL_CTX_use_certificate_chain_file wolfSSL_CTX_use_certificate_chain_file
+    #define SSL_CTX_use_RSAPrivateKey_file    wolfSSL_CTX_use_RSAPrivateKey_file
+
+    #define SSL_use_certificate_file          wolfSSL_use_certificate_file
+    #define SSL_use_PrivateKey_file           wolfSSL_use_PrivateKey_file
+    #define SSL_use_certificate_chain_file    wolfSSL_use_certificate_chain_file
+    #define SSL_use_RSAPrivateKey_file        wolfSSL_use_RSAPrivateKey_file
+#endif
+
+#define SSL_CTX_new(method)             wolfSSL_CTX_new((WOLFSSL_METHOD*)(method))
+#ifdef OPENSSL_EXTRA
+#define SSL_CTX_up_ref                  wolfSSL_CTX_up_ref
+#endif
+#define SSL_new                         wolfSSL_new
+#define SSL_set_fd                      wolfSSL_set_fd
+#define SSL_get_fd                      wolfSSL_get_fd
+#define SSL_connect                     wolfSSL_connect
+#define SSL_clear                       wolfSSL_clear
+#define SSL_state                       wolfSSL_state
+
+#define SSL_write                       wolfSSL_write
+#define SSL_read                        wolfSSL_read
+#define SSL_peek                        wolfSSL_peek
+#define SSL_accept                      wolfSSL_accept
+#define SSL_CTX_free                    wolfSSL_CTX_free
+#define SSL_free                        wolfSSL_free
+#define SSL_shutdown                    wolfSSL_shutdown
+#define SSL_set_timeout                 wolfSSL_set_timeout
+
+#define SSL_CTX_set_quiet_shutdown      wolfSSL_CTX_set_quiet_shutdown
+#define SSL_set_quiet_shutdown          wolfSSL_set_quiet_shutdown
+#define SSL_get_error                   wolfSSL_get_error
+#define SSL_set_session                 wolfSSL_set_session
+#define SSL_get_session(x)              wolfSSL_get_session((WOLFSSL*) (x))
+#define SSL_SESSION_get0_peer           wolfSSL_SESSION_get0_peer
+#define SSL_flush_sessions              wolfSSL_flush_sessions
+/* assume unlimited temporarily */
+#define SSL_CTX_get_session_cache_mode(ctx) 0
+
+#define SSL_CTX_set_verify              wolfSSL_CTX_set_verify
+#define SSL_CTX_set_cert_verify_callback wolfSSL_CTX_set_cert_verify_callback
+#define SSL_set_verify                  wolfSSL_set_verify
+#define SSL_set_verify_result           wolfSSL_set_verify_result
+#define SSL_pending                     wolfSSL_pending
+#define SSL_load_error_strings          wolfSSL_load_error_strings
+#define SSL_library_init                wolfSSL_library_init
+#define OpenSSL_add_ssl_algorithms      wolfSSL_library_init
+#define SSL_CTX_set_session_cache_mode  wolfSSL_CTX_set_session_cache_mode
+#define SSL_CTX_set_cipher_list         wolfSSL_CTX_set_cipher_list
+#define SSL_CTX_set_ciphersuites        wolfSSL_CTX_set_cipher_list
+#define SSL_set_cipher_list             wolfSSL_set_cipher_list
+/* wolfSSL does not support security levels */
+#define SSL_CTX_set_security_level(...)
+/* wolfSSL does not support exporting keying material */
+#define SSL_export_keying_material(...) 0
+
+#define SSL_CTX_set1_groups_list        wolfSSL_CTX_set1_groups_list
+#define SSL_set1_groups_list            wolfSSL_set1_groups_list
+
+#define SSL_set_ex_data                 wolfSSL_set_ex_data
+#define SSL_get_shutdown                wolfSSL_get_shutdown
+#define SSL_set_rfd                     wolfSSL_set_rfd
+#define SSL_set_wfd                     wolfSSL_set_wfd
+#define SSL_set_shutdown                wolfSSL_set_shutdown
+#define SSL_set_session_id_context      wolfSSL_set_session_id_context
+#define SSL_set_connect_state           wolfSSL_set_connect_state
+#define SSL_set_accept_state            wolfSSL_set_accept_state
+#define SSL_session_reused              wolfSSL_session_reused
+#define SSL_SESSION_dup                 wolfSSL_SESSION_dup
+#define SSL_SESSION_free                wolfSSL_SESSION_free
+#define SSL_is_init_finished            wolfSSL_is_init_finished
+
+#define SSL_get_version                 wolfSSL_get_version
+#define SSL_get_current_cipher          wolfSSL_get_current_cipher
+
+/* use wolfSSL_get_cipher_name for its return format */
+#define SSL_get_cipher                  wolfSSL_get_cipher_name
+#define SSL_CIPHER_description          wolfSSL_CIPHER_description
+#define SSL_CIPHER_get_name             wolfSSL_CIPHER_get_name
+#define SSL_CIPHER_get_version          wolfSSL_CIPHER_get_version
+#define SSL_CIPHER_get_id               wolfSSL_CIPHER_get_id
+#define SSL_CIPHER_get_rfc_name         wolfSSL_CIPHER_get_name
+#define SSL_CIPHER_standard_name        wolfSSL_CIPHER_get_name
+#define SSL_get_cipher_by_value         wolfSSL_get_cipher_by_value
+
+#define SSL_get1_session                wolfSSL_get1_session
+
+#define SSL_get_keyblock_size           wolfSSL_get_keyblock_size
+#define SSL_get_keys                    wolfSSL_get_keys
+#define SSL_SESSION_get_master_key      wolfSSL_SESSION_get_master_key
+#define SSL_SESSION_get_master_key_length wolfSSL_SESSION_get_master_key_length
+
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+    #define SSL_MODE_RELEASE_BUFFERS    0x00000010U
+    #define ASN1_BOOLEAN                WOLFSSL_ASN1_BOOLEAN
+    #define X509_get_ext                wolfSSL_X509_get_ext
+    #define X509_cmp                    wolfSSL_X509_cmp
+    #define X509_EXTENSION_get_object   wolfSSL_X509_EXTENSION_get_object
+    #define X509_EXTENSION_get_critical wolfSSL_X509_EXTENSION_get_critical
+    #define X509_EXTENSION_get_data     wolfSSL_X509_EXTENSION_get_data
+    #define X509_EXTENSION_new          wolfSSL_X509_EXTENSION_new
+    #define X509_EXTENSION_free         wolfSSL_X509_EXTENSION_free
+    #define X509_gmtime_adj             wolfSSL_X509_gmtime_adj
+#endif
+
+#define DSA_dup_DH                      wolfSSL_DSA_dup_DH
+/* wolfSSL does not support DSA as the cert public key */
+#define EVP_PKEY_get0_DSA(...)          NULL
+#define DSA_bits(...)                   0
+
+#define i2d_X509_bio                    wolfSSL_i2d_X509_bio
+#define d2i_X509_bio                    wolfSSL_d2i_X509_bio
+#define d2i_X509_fp                     wolfSSL_d2i_X509_fp
+#define i2d_X509                        wolfSSL_i2d_X509
+#define d2i_X509                        wolfSSL_d2i_X509
+#define PEM_read_bio_X509               wolfSSL_PEM_read_bio_X509
+#define PEM_read_bio_X509_CRL           wolfSSL_PEM_read_bio_X509_CRL
+#define PEM_read_bio_X509_AUX           wolfSSL_PEM_read_bio_X509_AUX
+#define PEM_read_X509                   wolfSSL_PEM_read_X509
+#define PEM_X509_INFO_read_bio          wolfSSL_PEM_X509_INFO_read_bio
+#define PEM_write_bio_X509              wolfSSL_PEM_write_bio_X509
+#define PEM_write_bio_X509_AUX          wolfSSL_PEM_write_bio_X509_AUX
+#define PEM_X509_INFO_read_bio          wolfSSL_PEM_X509_INFO_read_bio
+#define i2d_PrivateKey                  wolfSSL_i2d_PrivateKey
+
+#define i2d_X509_REQ                    wolfSSL_i2d_X509_REQ
+#define X509_REQ_new                    wolfSSL_X509_REQ_new
+#define X509_REQ_free                   wolfSSL_X509_REQ_free
+#define X509_REQ_sign                   wolfSSL_X509_REQ_sign
+#define X509_REQ_add_extensions         wolfSSL_X509_REQ_add_extensions
+#define X509_REQ_set_subject_name       wolfSSL_X509_REQ_set_subject_name
+#define X509_REQ_set_pubkey             wolfSSL_X509_REQ_set_pubkey
+#define PEM_write_bio_X509_REQ          wolfSSL_PEM_write_bio_X509_REQ
+
+#define X509_new                        wolfSSL_X509_new
+#define X509_up_ref                     wolfSSL_X509_up_ref
+#define X509_free                       wolfSSL_X509_free
+#define X509_load_certificate_file      wolfSSL_X509_load_certificate_file
+#define X509_digest                     wolfSSL_X509_digest
+#define X509_get_ext_count              wolfSSL_X509_get_ext_count
+#define X509_get_ext_d2i                wolfSSL_X509_get_ext_d2i
+#define X509_get_ext                    wolfSSL_X509_get_ext
+#define X509_get_ext_by_NID             wolfSSL_X509_get_ext_by_NID
+#define X509_get_issuer_name            wolfSSL_X509_get_issuer_name
+#define X509_get_subject_name           wolfSSL_X509_get_subject_name
+#define X509_get_pubkey                 wolfSSL_X509_get_pubkey
+#define X509_get0_pubkey                wolfSSL_X509_get_pubkey
+#define X509_get_notBefore              wolfSSL_X509_get_notBefore
+#define X509_get_notAfter               wolfSSL_X509_get_notAfter
+#define X509_get_serialNumber           wolfSSL_X509_get_serialNumber
+#define X509_get0_pubkey_bitstr         wolfSSL_X509_get0_pubkey_bitstr
+#define X509_get_ex_new_index           wolfSSL_X509_get_ex_new_index
+#define X509_get_ex_data                wolfSSL_X509_get_ex_data
+#define X509_set_ex_data                wolfSSL_X509_set_ex_data
+#define X509_get1_ocsp                  wolfSSL_X509_get1_ocsp
+#ifndef WOLFSSL_HAPROXY
+#define X509_get_version                wolfSSL_X509_get_version
+#endif
+#define X509_get_signature_nid          wolfSSL_X509_get_signature_nid
+#define X509_set_subject_name           wolfSSL_X509_set_subject_name
+#define X509_set_issuer_name            wolfSSL_X509_set_issuer_name
+#define X509_set_pubkey                 wolfSSL_X509_set_pubkey
+#define X509_set_notAfter               wolfSSL_X509_set_notAfter
+#define X509_set_notBefore              wolfSSL_X509_set_notBefore
+#define X509_set_serialNumber           wolfSSL_X509_set_serialNumber
+#define X509_set_version                wolfSSL_X509_set_version
+#define X509_sign                       wolfSSL_X509_sign
+#define X509_print                      wolfSSL_X509_print
+#define X509_print_ex                   wolfSSL_X509_print_ex
+#define X509_verify_cert_error_string   wolfSSL_X509_verify_cert_error_string
+#define X509_verify_cert                wolfSSL_X509_verify_cert
+#define X509_check_private_key          wolfSSL_X509_check_private_key
+#define X509_check_ca                   wolfSSL_X509_check_ca
+#define X509_check_host                 wolfSSL_X509_check_host
+#define X509_email_free                 wolfSSL_X509_email_free
+#define X509_check_issued               wolfSSL_X509_check_issued
+#define X509_dup                        wolfSSL_X509_dup
+
+#define X509_EXTENSION_get_object       wolfSSL_X509_EXTENSION_get_object
+#define X509_EXTENSION_get_data         wolfSSL_X509_EXTENSION_get_data
+
+#define sk_X509_new                     wolfSSL_sk_X509_new
+#define sk_X509_new_null                wolfSSL_sk_X509_new
+#define sk_X509_num                     wolfSSL_sk_X509_num
+#define sk_X509_value                   wolfSSL_sk_X509_value
+#define sk_X509_shift                   wolfSSL_sk_X509_shift
+#define sk_X509_push                    wolfSSL_sk_X509_push
+#define sk_X509_pop                     wolfSSL_sk_X509_pop
+#define sk_X509_pop_free                wolfSSL_sk_X509_pop_free
+#define sk_X509_dup                     wolfSSL_sk_X509_dup
+#define sk_X509_free                    wolfSSL_sk_X509_free
+
+#define sk_X509_EXTENSION_num           wolfSSL_sk_X509_EXTENSION_num
+#define sk_X509_EXTENSION_value         wolfSSL_sk_X509_EXTENSION_value
+#define sk_X509_EXTENSION_new_null      wolfSSL_sk_X509_EXTENSION_new_null
+#define sk_X509_EXTENSION_pop_free      wolfSSL_sk_X509_EXTENSION_pop_free
+#define sk_X509_EXTENSION_push          wolfSSL_sk_X509_EXTENSION_push
+#define X509_EXTENSION_free             wolfSSL_X509_EXTENSION_free
+
+#define X509_INFO_new                   wolfSSL_X509_INFO_new
+#define X509_INFO_free                  wolfSSL_X509_INFO_free
+
+#define sk_X509_INFO_new_null           wolfSSL_sk_X509_INFO_new_null
+#define sk_X509_INFO_num                wolfSSL_sk_X509_INFO_num
+#define sk_X509_INFO_value              wolfSSL_sk_X509_INFO_value
+#define sk_X509_INFO_push               wolfSSL_sk_X509_INFO_push
+#define sk_X509_INFO_pop                wolfSSL_sk_X509_INFO_pop
+#define sk_X509_INFO_pop_free           wolfSSL_sk_X509_INFO_pop_free
+#define sk_X509_INFO_free               wolfSSL_sk_X509_INFO_free
+
+#define i2d_X509_NAME                   wolfSSL_i2d_X509_NAME
+#define X509_NAME_new                   wolfSSL_X509_NAME_new
+#define X509_NAME_free                  wolfSSL_X509_NAME_free
+#define X509_NAME_dup                   wolfSSL_X509_NAME_dup
+#define X509_NAME_get_text_by_NID       wolfSSL_X509_NAME_get_text_by_NID
+#define X509_NAME_get_index_by_OBJ      wolfSSL_X509_NAME_get_index_by_OBJ
+#define X509_NAME_cmp                   wolfSSL_X509_NAME_cmp
+#define X509_NAME_ENTRY_new             wolfSSL_X509_NAME_ENTRY_new
+#define X509_NAME_ENTRY_free            wolfSSL_X509_NAME_ENTRY_free
+#define X509_NAME_ENTRY_create_by_NID   wolfSSL_X509_NAME_ENTRY_create_by_NID
+#define X509_NAME_ENTRY_create_by_txt   wolfSSL_X509_NAME_ENTRY_create_by_txt
+#define X509_NAME_add_entry             wolfSSL_X509_NAME_add_entry
+#define X509_NAME_add_entry_by_txt      wolfSSL_X509_NAME_add_entry_by_txt
+#define X509_NAME_add_entry_by_NID      wolfSSL_X509_NAME_add_entry_by_NID
+#define X509_NAME_oneline               wolfSSL_X509_NAME_oneline
+#define X509_NAME_get_index_by_NID      wolfSSL_X509_NAME_get_index_by_NID
+#define X509_NAME_print_ex              wolfSSL_X509_NAME_print_ex
+#define X509_NAME_digest                wolfSSL_X509_NAME_digest
+#define X509_cmp_current_time           wolfSSL_X509_cmp_current_time
+#define X509_cmp_time                   wolfSSL_X509_cmp_time
+#define X509_time_adj                   wolfSSL_X509_time_adj
+#define X509_time_adj_ex                wolfSSL_X509_time_adj_ex
+
+#define sk_ACCESS_DESCRIPTION_num       wolfSSL_sk_ACCESS_DESCRIPTION_num
+#define sk_ACCESS_DESCRIPTION_value     wolfSSL_sk_ACCESS_DESCRIPTION_value
+
+#define sk_X509_NAME_new                wolfSSL_sk_X509_NAME_new
+#define sk_X509_NAME_push               wolfSSL_sk_X509_NAME_push
+#define sk_X509_NAME_find               wolfSSL_sk_X509_NAME_find
+#define sk_X509_NAME_set_cmp_func       wolfSSL_sk_X509_NAME_set_cmp_func
+#define sk_X509_NAME_num                wolfSSL_sk_X509_NAME_num
+#define sk_X509_NAME_value              wolfSSL_sk_X509_NAME_value
+#define sk_X509_NAME_pop                wolfSSL_sk_X509_NAME_pop
+#define sk_X509_NAME_pop_free           wolfSSL_sk_X509_NAME_pop_free
+#define sk_X509_NAME_free               wolfSSL_sk_X509_NAME_free
+
+typedef WOLFSSL_X509_NAME_ENTRY X509_NAME_ENTRY;
+
+#define X509_NAME_entry_count           wolfSSL_X509_NAME_entry_count
+#define X509_NAME_ENTRY_get_object      wolfSSL_X509_NAME_ENTRY_get_object
+#define X509_NAME_get_entry             wolfSSL_X509_NAME_get_entry
+#define X509_NAME_ENTRY_get_data        wolfSSL_X509_NAME_ENTRY_get_data
+#define X509_NAME_ENTRY_get_object      wolfSSL_X509_NAME_ENTRY_get_object
+
+#define X509_V_FLAG_CRL_CHECK     WOLFSSL_CRL_CHECK
+#define X509_V_FLAG_CRL_CHECK_ALL WOLFSSL_CRL_CHECKALL
+
+#define X509_V_FLAG_USE_CHECK_TIME WOLFSSL_USE_CHECK_TIME
+#define X509_V_FLAG_NO_CHECK_TIME  WOLFSSL_NO_CHECK_TIME
+#define X509_CHECK_FLAG_NO_WILDCARDS WOLFSSL_NO_WILDCARDS
+
+#define X509_STORE_CTX_get_current_cert wolfSSL_X509_STORE_CTX_get_current_cert
+#define X509_STORE_CTX_set_verify_cb    wolfSSL_X509_STORE_CTX_set_verify_cb
+#define X509_STORE_CTX_new              wolfSSL_X509_STORE_CTX_new
+#define X509_STORE_CTX_free             wolfSSL_X509_STORE_CTX_free
+#define X509_STORE_CTX_get_chain        wolfSSL_X509_STORE_CTX_get_chain
+#define X509_STORE_CTX_get1_chain       wolfSSL_X509_STORE_CTX_get1_chain
+#define X509_STORE_CTX_get_error        wolfSSL_X509_STORE_CTX_get_error
+#define X509_STORE_CTX_get_error_depth  wolfSSL_X509_STORE_CTX_get_error_depth
+#define X509_STORE_CTX_init             wolfSSL_X509_STORE_CTX_init
+#define X509_STORE_CTX_cleanup          wolfSSL_X509_STORE_CTX_cleanup
+#define X509_STORE_CTX_set_error        wolfSSL_X509_STORE_CTX_set_error
+#define X509_STORE_CTX_set_error_depth  wolfSSL_X509_STORE_CTX_set_error_depth
+#define X509_STORE_CTX_get_ex_data      wolfSSL_X509_STORE_CTX_get_ex_data
+#define X509_STORE_CTX_set_ex_data      wolfSSL_X509_STORE_CTX_set_ex_data
+#define X509_STORE_CTX_set_depth        wolfSSL_X509_STORE_CTX_set_depth
+#define X509_STORE_CTX_verify_cb        WOLFSSL_X509_STORE_CTX_verify_cb
+#define X509_STORE_CTX_get0_current_issuer \
+                                      wolfSSL_X509_STORE_CTX_get0_current_issuer
+#define X509_STORE_CTX_get0_store       wolfSSL_X509_STORE_CTX_get0_store
+#define X509_STORE_CTX_get0_cert        wolfSSL_X509_STORE_CTX_get0_cert
+
+#define X509_STORE_set_verify_cb(s, c) \
+wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_CTX_verify_cb)(c))
+#define X509_STORE_set_verify_cb_func(s, c) \
+wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_CTX_verify_cb)(c))
+
+
+#define X509_STORE_new                  wolfSSL_X509_STORE_new
+#define X509_STORE_free                 wolfSSL_X509_STORE_free
+#define X509_STORE_add_lookup           wolfSSL_X509_STORE_add_lookup
+#define X509_STORE_add_cert             wolfSSL_X509_STORE_add_cert
+#define X509_STORE_add_crl              wolfSSL_X509_STORE_add_crl
+#define X509_STORE_set_flags            wolfSSL_X509_STORE_set_flags
+#define X509_STORE_get1_certs           wolfSSL_X509_STORE_get1_certs
+#define X509_STORE_get_by_subject       wolfSSL_X509_STORE_get_by_subject
+#define X509_STORE_CTX_get1_issuer      wolfSSL_X509_STORE_CTX_get1_issuer
+#define X509_STORE_CTX_set_time         wolfSSL_X509_STORE_CTX_set_time
+#define X509_VERIFY_PARAM_set_hostflags wolfSSL_X509_VERIFY_PARAM_set_hostflags
+#define X509_VERIFY_PARAM_set1_host     wolfSSL_X509_VERIFY_PARAM_set1_host
+#define X509_VERIFY_PARAM_set1_ip_asc   wolfSSL_X509_VERIFY_PARAM_set1_ip_asc
+#define X509_STORE_load_locations       wolfSSL_X509_STORE_load_locations
+
+#define X509_LOOKUP_add_dir             wolfSSL_X509_LOOKUP_add_dir
+#define X509_LOOKUP_load_file           wolfSSL_X509_LOOKUP_load_file
+#define X509_LOOKUP_hash_dir            wolfSSL_X509_LOOKUP_hash_dir
+#define X509_LOOKUP_file                wolfSSL_X509_LOOKUP_file
+
+#define d2i_X509_CRL                    wolfSSL_d2i_X509_CRL
+#define d2i_X509_CRL_fp                 wolfSSL_d2i_X509_CRL_fp
+#define PEM_read_X509_CRL               wolfSSL_PEM_read_X509_CRL
+
+#define X509_CRL_free                   wolfSSL_X509_CRL_free
+#define X509_CRL_get_lastUpdate         wolfSSL_X509_CRL_get_lastUpdate
+#define X509_CRL_get_nextUpdate         wolfSSL_X509_CRL_get_nextUpdate
+#define X509_CRL_verify                 wolfSSL_X509_CRL_verify
+#define X509_CRL_get_REVOKED            wolfSSL_X509_CRL_get_REVOKED
+
+#define X509_get_X509_PUBKEY            wolfSSL_X509_get_X509_PUBKEY
+#define X509_get0_tbs_sigalg            wolfSSL_X509_get0_tbs_sigalg
+#define X509_PUBKEY_get0_param          wolfSSL_X509_PUBKEY_get0_param
+#define X509_PUBKEY_get                 wolfSSL_X509_PUBKEY_get
+#define X509_PUBKEY_set                 wolfSSL_X509_PUBKEY_set
+#define X509_ALGOR_get0                 wolfSSL_X509_ALGOR_get0
+#define X509_ALGOR_set0                 wolfSSL_X509_ALGOR_set0
+
+#define X509_ALGOR_new                  wolfSSL_X509_ALGOR_new
+#define X509_ALGOR_free                 wolfSSL_X509_ALGOR_free
+#define X509_PUBKEY_new                 wolfSSL_X509_PUBKEY_new
+#define X509_PUBKEY_free                wolfSSL_X509_PUBKEY_free
+
+#define sk_X509_REVOKED_num             wolfSSL_sk_X509_REVOKED_num
+#define sk_X509_REVOKED_value           wolfSSL_sk_X509_REVOKED_value
+
+#define X509_OBJECT_free_contents       wolfSSL_X509_OBJECT_free_contents
+#define X509_subject_name_hash          wolfSSL_X509_subject_name_hash
+
+#define X509_check_purpose(...)         0
+
+#define OCSP_parse_url                  wolfSSL_OCSP_parse_url
+
+#define MD4_Init                        wolfSSL_MD4_Init
+#define MD4_Update                      wolfSSL_MD4_Update
+#define MD4_Final                       wolfSSL_MD4_Final
+
+#define BIO_new                         wolfSSL_BIO_new
+#define BIO_free                        wolfSSL_BIO_free
+#define BIO_vfree                       wolfSSL_BIO_vfree
+#define BIO_free_all                    wolfSSL_BIO_free_all
+#define BIO_nread0                      wolfSSL_BIO_nread0
+#define BIO_nread                       wolfSSL_BIO_nread
+#define BIO_read                        wolfSSL_BIO_read
+#define BIO_nwrite0                     wolfSSL_BIO_nwrite0
+#define BIO_nwrite                      wolfSSL_BIO_nwrite
+#define BIO_write                       wolfSSL_BIO_write
+#define BIO_push                        wolfSSL_BIO_push
+#define BIO_pop                         wolfSSL_BIO_pop
+#define BIO_flush                       wolfSSL_BIO_flush
+#define BIO_pending                     wolfSSL_BIO_pending
+
+#define BIO_get_mem_data                wolfSSL_BIO_get_mem_data
+#define BIO_new_mem_buf                 wolfSSL_BIO_new_mem_buf
+
+#define BIO_f_buffer                    wolfSSL_BIO_f_buffer
+#define BIO_set_write_buffer_size       wolfSSL_BIO_set_write_buffer_size
+#define BIO_f_ssl                       wolfSSL_BIO_f_ssl
+#define BIO_new_socket                  wolfSSL_BIO_new_socket
+#define SSL_set_bio                     wolfSSL_set_bio
+#define BIO_set_ssl                     wolfSSL_BIO_set_ssl
+#define BIO_eof                         wolfSSL_BIO_eof
+#define BIO_set_ss                      wolfSSL_BIO_set_ss
+
+#define BIO_f_md                        wolfSSL_BIO_f_md
+#define BIO_get_md_ctx                  wolfSSL_BIO_get_md_ctx
+#define BIO_s_mem                       wolfSSL_BIO_s_mem
+#define BIO_f_base64                    wolfSSL_BIO_f_base64
+#define BIO_set_flags                   wolfSSL_BIO_set_flags
+#define BIO_set_nbio                    wolfSSL_BIO_set_nbio
+
+#define SSLeay_add_ssl_algorithms       wolfSSL_add_all_algorithms
+#define SSLeay_add_all_algorithms       wolfSSL_add_all_algorithms
+
+#define RAND_screen                     wolfSSL_RAND_screen
+#define RAND_file_name                  wolfSSL_RAND_file_name
+#define RAND_write_file                 wolfSSL_RAND_write_file
+#define RAND_load_file                  wolfSSL_RAND_load_file
+#define RAND_egd                        wolfSSL_RAND_egd
+#define RAND_seed                       wolfSSL_RAND_seed
+#define RAND_cleanup                    wolfSSL_RAND_Cleanup
+#define RAND_add                        wolfSSL_RAND_add
+#define RAND_poll                       wolfSSL_RAND_poll
+#define RAND_status                     wolfSSL_RAND_status
+#define RAND_bytes                      wolfSSL_RAND_bytes
+#define RAND_pseudo_bytes               wolfSSL_RAND_pseudo_bytes
+
+#define COMP_zlib                       wolfSSL_COMP_zlib
+#define COMP_rle                        wolfSSL_COMP_rle
+#define SSL_COMP_add_compression_method wolfSSL_COMP_add_compression_method
+
+#define SSL_get_ex_new_index            wolfSSL_get_ex_new_index
+#define RSA_get_ex_new_index            wolfSSL_get_ex_new_index
+
+#define ASN1_BIT_STRING_new             wolfSSL_ASN1_BIT_STRING_new
+#define ASN1_BIT_STRING_free            wolfSSL_ASN1_BIT_STRING_free
+#define ASN1_BIT_STRING_get_bit         wolfSSL_ASN1_BIT_STRING_get_bit
+#define ASN1_BIT_STRING_set_bit         wolfSSL_ASN1_BIT_STRING_set_bit
+
+#define sk_ASN1_OBJECT_free             wolfSSL_sk_ASN1_OBJECT_free
+
+#define ASN1_TIME_free                  wolfSSL_ASN1_TIME_free
+#define ASN1_TIME_adj                   wolfSSL_ASN1_TIME_adj
+#define ASN1_TIME_print                 wolfSSL_ASN1_TIME_print
+#define ASN1_TIME_to_generalizedtime    wolfSSL_ASN1_TIME_to_generalizedtime
+#define ASN1_GENERALIZEDTIME_print      wolfSSL_ASN1_GENERALIZEDTIME_print
+#define ASN1_GENERALIZEDTIME_free       wolfSSL_ASN1_GENERALIZEDTIME_free
+
+#define ASN1_tag2str                    wolfSSL_ASN1_tag2str
+
+#define i2a_ASN1_INTEGER                wolfSSL_i2a_ASN1_INTEGER
+#define i2c_ASN1_INTEGER                wolfSSL_i2c_ASN1_INTEGER
+#define ASN1_INTEGER_new                wolfSSL_ASN1_INTEGER_new
+#define ASN1_INTEGER_free               wolfSSL_ASN1_INTEGER_free
+#define ASN1_INTEGER_cmp                wolfSSL_ASN1_INTEGER_cmp
+#define ASN1_INTEGER_get                wolfSSL_ASN1_INTEGER_get
+#define ASN1_INTEGER_set                wolfSSL_ASN1_INTEGER_set
+#define ASN1_INTEGER_to_BN              wolfSSL_ASN1_INTEGER_to_BN
+
+#define i2a_ASN1_OBJECT                 wolfSSL_i2a_ASN1_OBJECT
+
+#define ASN1_STRING_data                wolfSSL_ASN1_STRING_data
+#define ASN1_STRING_get0_data           wolfSSL_ASN1_STRING_data
+#define ASN1_STRING_length              wolfSSL_ASN1_STRING_length
+#define ASN1_STRING_to_UTF8             wolfSSL_ASN1_STRING_to_UTF8
+#define ASN1_STRING_print_ex            wolfSSL_ASN1_STRING_print_ex
+#define ASN1_STRING_print(x, y)         wolfSSL_ASN1_STRING_print ((WOLFSSL_BIO*)(x), (WOLFSSL_ASN1_STRING*)(y))
+#define d2i_DISPLAYTEXT                 wolfSSL_d2i_DISPLAYTEXT
+
+#define ASN1_UTCTIME_pr                 wolfSSL_ASN1_UTCTIME_pr
+
+#define ASN1_IA5STRING                  WOLFSSL_ASN1_STRING
+
+#define ASN1_OCTET_STRING               WOLFSSL_ASN1_STRING
+#define ASN1_BOOLEAN                    WOLFSSL_ASN1_BOOLEAN
+
+#define SSL_load_client_CA_file         wolfSSL_load_client_CA_file
+
+#define SSL_CTX_get_client_CA_list      wolfSSL_CTX_get_client_CA_list
+#define SSL_CTX_set_client_CA_list      wolfSSL_CTX_set_client_CA_list
+#define SSL_CTX_set_client_cert_cb      wolfSSL_CTX_set_client_cert_cb
+#define SSL_CTX_set_cert_store          wolfSSL_CTX_set_cert_store
+#define SSL_CTX_get_cert_store(x)       wolfSSL_CTX_get_cert_store ((WOLFSSL_CTX*) (x))
+#define SSL_get_client_CA_list          wolfSSL_get_client_CA_list
+#define SSL_get_ex_data_X509_STORE_CTX_idx wolfSSL_get_ex_data_X509_STORE_CTX_idx
+#define SSL_get_ex_data                 wolfSSL_get_ex_data
+
+#define SSL_CTX_set_default_passwd_cb_userdata wolfSSL_CTX_set_default_passwd_cb_userdata
+#define SSL_CTX_set_default_passwd_cb   wolfSSL_CTX_set_default_passwd_cb
+
+#define SSL_CTX_set_timeout(ctx, to)    \
+                                 wolfSSL_CTX_set_timeout(ctx, (unsigned int) to)
+#define SSL_CTX_set_info_callback       wolfSSL_CTX_set_info_callback
+#define SSL_CTX_set_alpn_protos         wolfSSL_CTX_set_alpn_protos
+
+#define SSL_alert_type_string           wolfSSL_alert_type_string
+#define SSL_alert_desc_string           wolfSSL_alert_desc_string
+#define SSL_state_string                wolfSSL_state_string
+
+#define RSA_free                        wolfSSL_RSA_free
+#define RSA_generate_key                wolfSSL_RSA_generate_key
+#define SSL_CTX_set_tmp_rsa_callback    wolfSSL_CTX_set_tmp_rsa_callback
+#define RSA_print                       wolfSSL_RSA_print
+#define RSA_bits                        wolfSSL_RSA_size
+#define RSA_up_ref                      wolfSSL_RSA_up_ref
+#define RSA_padding_add_PKCS1_PSS       wolfSSL_RSA_padding_add_PKCS1_PSS
+#define RSA_verify_PKCS1_PSS            wolfSSL_RSA_verify_PKCS1_PSS
+
+#define PEM_def_callback                wolfSSL_PEM_def_callback
+
+#define SSL_CTX_sess_accept             wolfSSL_CTX_sess_accept
+#define SSL_CTX_sess_connect            wolfSSL_CTX_sess_connect
+#define SSL_CTX_sess_accept_good        wolfSSL_CTX_sess_accept_good
+#define SSL_CTX_sess_connect_good       wolfSSL_CTX_sess_connect_good
+#define SSL_CTX_sess_accept_renegotiate wolfSSL_CTX_sess_accept_renegotiate
+#define SSL_CTX_sess_connect_renegotiate wolfSSL_CTX_sess_connect_renegotiate
+#define SSL_CTX_sess_hits               wolfSSL_CTX_sess_hits
+#define SSL_CTX_sess_cb_hits            wolfSSL_CTX_sess_cb_hits
+#define SSL_CTX_sess_cache_full         wolfSSL_CTX_sess_cache_full
+#define SSL_CTX_sess_misses             wolfSSL_CTX_sess_misses
+#define SSL_CTX_sess_timeouts           wolfSSL_CTX_sess_timeouts
+#define SSL_CTX_sess_number             wolfSSL_CTX_sess_number
+#define SSL_CTX_sess_get_cache_size     wolfSSL_CTX_sess_get_cache_size
+
+
+#define SSL_DEFAULT_CIPHER_LIST WOLFSSL_DEFAULT_CIPHER_LIST
+
+#define SSL_CTX_set_psk_client_callback wolfSSL_CTX_set_psk_client_callback
+#define SSL_set_psk_client_callback     wolfSSL_set_psk_client_callback
+
+#define SSL_get_psk_identity_hint       wolfSSL_get_psk_identity_hint
+#define SSL_get_psk_identity            wolfSSL_get_psk_identity
+
+#define SSL_CTX_use_psk_identity_hint   wolfSSL_CTX_use_psk_identity_hint
+#define SSL_use_psk_identity_hint       wolfSSL_use_psk_identity_hint
+
+#define SSL_CTX_set_psk_server_callback wolfSSL_CTX_set_psk_server_callback
+#define SSL_set_psk_server_callback     wolfSSL_set_psk_server_callback
+
+/* system file ints for ERR_put_error */
+#define SYS_F_ACCEPT      WOLFSSL_SYS_ACCEPT
+#define SYS_F_BIND        WOLFSSL_SYS_BIND
+#define SYS_F_CONNECT     WOLFSSL_SYS_CONNECT
+#define SYS_F_FOPEN       WOLFSSL_SYS_FOPEN
+#define SYS_F_FREAD       WOLFSSL_SYS_FREAD
+#define SYS_F_GETADDRINFO WOLFSSL_SYS_GETADDRINFO
+#define SYS_F_GETSOCKOPT  WOLFSSL_SYS_GETSOCKOPT
+#define SYS_F_GETSOCKNAME WOLFSSL_SYS_GETSOCKNAME
+#define SYS_F_OPENDIR     WOLFSSL_SYS_OPENDIR
+#define SYS_F_SETSOCKOPT  WOLFSSL_SYS_SETSOCKOPT
+#define SYS_F_SOCKET      WOLFSSL_SYS_SOCKET
+#define SYS_F_GETHOSTBYNAME  WOLFSSL_SYS_GETHOSTBYNAME
+#define SYS_F_GETNAMEINFO    WOLFSSL_SYS_GETNAMEINFO
+#define SYS_F_GETSERVBYNAME  WOLFSSL_SYS_GETSERVBYNAME
+#define SYS_F_IOCTLSOCKET    WOLFSSL_SYS_IOCTLSOCKET
+#define SYS_F_LISTEN         WOLFSSL_SYS_LISTEN
+
+#define ERR_GET_LIB                     wolfSSL_ERR_GET_LIB
+#define ERR_GET_REASON                  wolfSSL_ERR_GET_REASON
+
+#define ERR_put_error                   wolfSSL_ERR_put_error
+#define ERR_peek_error                  wolfSSL_ERR_peek_error
+#define ERR_peek_errors_fp              wolfSSL_ERR_peek_errors_fp
+#define ERR_peek_error_line_data        wolfSSL_ERR_peek_error_line_data
+#define ERR_peek_last_error             wolfSSL_ERR_peek_last_error
+#define ERR_peek_last_error_line        wolfSSL_ERR_peek_last_error_line
+#define ERR_get_error_line              wolfSSL_ERR_get_error_line
+#define ERR_get_error_line_data         wolfSSL_ERR_get_error_line_data
+#define ERR_get_error                   wolfSSL_ERR_get_error
+#define ERR_print_errors_fp(file)       wolfSSL_ERR_dump_errors_fp((file))
+#define ERR_print_errors_cb             wolfSSL_ERR_print_errors_cb
+#define ERR_print_errors                wolfSSL_ERR_print_errors
+#define ERR_clear_error                 wolfSSL_ERR_clear_error
+#define ERR_free_strings                wolfSSL_ERR_free_strings
+#define ERR_remove_state                wolfSSL_ERR_remove_state
+#define ERR_remove_thread_state         wolfSSL_ERR_remove_thread_state
+#define ERR_error_string                wolfSSL_ERR_error_string
+#define ERR_error_string_n              wolfSSL_ERR_error_string_n
+#define ERR_reason_error_string         wolfSSL_ERR_reason_error_string
+#define ERR_load_BIO_strings            wolfSSL_ERR_load_BIO_strings
+
+#ifndef WOLFCRYPT_ONLY
+#define PEMerr(func, reason)            wolfSSL_ERR_put_error(ERR_LIB_PEM, \
+                                        (func), (reason), __FILE__, __LINE__)
+#else
+#define PEMerr(func, reason)            WOLFSSL_ERROR_LINE((reason), \
+                                        NULL, __LINE__, __FILE__, NULL)
+#endif
+
+#define SSLv23_server_method            wolfSSLv23_server_method
+#define SSL_CTX_set_options             wolfSSL_CTX_set_options
+#define SSL_CTX_get_options             wolfSSL_CTX_get_options
+#define SSL_CTX_clear_options           wolfSSL_CTX_clear_options
+
+#define SSL_CTX_check_private_key       wolfSSL_CTX_check_private_key
+#define SSL_check_private_key           wolfSSL_check_private_key
+
+#define SSL_CTX_set_mode                wolfSSL_CTX_set_mode
+#define SSL_CTX_get_mode                wolfSSL_CTX_get_mode
+#define SSL_CTX_set_default_read_ahead  wolfSSL_CTX_set_default_read_ahead
+
+#define SSL_CTX_sess_set_cache_size     wolfSSL_CTX_sess_set_cache_size
+#define SSL_CTX_set_default_verify_paths wolfSSL_CTX_set_default_verify_paths
+
+#define SSL_CTX_set_session_id_context  wolfSSL_CTX_set_session_id_context
+#define SSL_get_peer_certificate        wolfSSL_get_peer_certificate
+#define SSL_get_peer_cert_chain         wolfSSL_get_peer_cert_chain
+
+#define SSL_want                        wolfSSL_want
+#define SSL_want_read                   wolfSSL_want_read
+#define SSL_want_write                  wolfSSL_want_write
+
+#define BIO_prf                         wolfSSL_BIO_prf
+
+#define sk_num                          wolfSSL_sk_num
+#define sk_ASN1_OBJECT_num              wolfSSL_sk_num
+#define sk_value                        wolfSSL_sk_value
+#define sk_ASN1_OBJECT_value            wolfSSL_sk_value
+
+#define d2i_PKCS12_bio                  wolfSSL_d2i_PKCS12_bio
+#define d2i_PKCS12_fp                   wolfSSL_d2i_PKCS12_fp
+#define i2d_PKCS12_bio                  wolfSSL_i2d_PKCS12_bio
+
+#define d2i_RSAPublicKey                wolfSSL_d2i_RSAPublicKey
+#define d2i_RSAPrivateKey               wolfSSL_d2i_RSAPrivateKey
+#define i2d_RSAPrivateKey               wolfSSL_i2d_RSAPrivateKey
+#define i2d_RSAPublicKey                wolfSSL_i2d_RSAPublicKey
+
+#define SSL_CTX_get_ex_data             wolfSSL_CTX_get_ex_data
+#define SSL_CTX_set_ex_data             wolfSSL_CTX_set_ex_data
+#define SSL_CTX_sess_set_get_cb         wolfSSL_CTX_sess_set_get_cb
+#define SSL_CTX_sess_set_new_cb         wolfSSL_CTX_sess_set_new_cb
+#define SSL_CTX_sess_set_remove_cb      wolfSSL_CTX_sess_set_remove_cb
+
+#define i2d_SSL_SESSION                 wolfSSL_i2d_SSL_SESSION
+#define d2i_SSL_SESSION                 wolfSSL_d2i_SSL_SESSION
+#define SSL_SESSION_set_timeout         wolfSSL_SSL_SESSION_set_timeout
+#define SSL_SESSION_get_timeout         wolfSSL_SESSION_get_timeout
+#define SSL_SESSION_get_time            wolfSSL_SESSION_get_time
+
+#define SSL_CTX_get_ex_new_index        wolfSSL_CTX_get_ex_new_index
+#define PEM_read                        wolfSSL_PEM_read
+#define PEM_write                       wolfSSL_PEM_write
+#define PEM_get_EVP_CIPHER_INFO         wolfSSL_PEM_get_EVP_CIPHER_INFO
+#define PEM_do_header                   wolfSSL_PEM_do_header
+
+/*#if OPENSSL_API_COMPAT < 0x10100000L*/
+#define CONF_modules_free()
+#define ENGINE_cleanup()
+#define HMAC_CTX_cleanup                wolfSSL_HMAC_cleanup
+#define SSL_CTX_need_tmp_RSA(ctx)       0
+#define SSL_CTX_set_tmp_rsa(ctx,rsa)    1
+#define SSL_need_tmp_RSA(ssl)           0
+#define SSL_set_tmp_rsa(ssl,rsa)        1
+/*#endif*/
+
+#define CONF_modules_unload(a)
+#define CONF_get1_default_config_file wolfSSL_CONF_get1_default_config_file
+
+#define SSL_get_hit                     wolfSSL_session_reused
+
+/* yassl had set the default to be 500 */
+#define SSL_get_default_timeout(ctx)    500
+
+#define DTLSv1_get_timeout(ssl, timeleft)   wolfSSL_DTLSv1_get_timeout((ssl), (WOLFSSL_TIMEVAL*)(timeleft))
+#define DTLSv1_handle_timeout               wolfSSL_DTLSv1_handle_timeout
+#define DTLSv1_set_initial_timeout_duration wolfSSL_DTLSv1_set_initial_timeout_duration
+
+#ifndef NO_WOLFSSL_STUB
+#define SSL_CTX_set_current_time_cb(ssl, cb) ({ (void)ssl; (void)cb; })
+#endif
+
+#define SSL_CTX_use_certificate         wolfSSL_CTX_use_certificate
+#define SSL_CTX_add1_chain_cert         wolfSSL_CTX_add1_chain_cert
+#define SSL_CTX_use_PrivateKey          wolfSSL_CTX_use_PrivateKey
+#define BIO_read_filename               wolfSSL_BIO_read_filename
+#define SSL_CTX_set_verify_depth        wolfSSL_CTX_set_verify_depth
+#define SSL_set_verify_depth            wolfSSL_set_verify_depth
+#define SSL_get_app_data                wolfSSL_get_app_data
+#define SSL_set_app_data                wolfSSL_set_app_data
+#define SHA1                            wolfSSL_SHA1
+
+#define SSL_dup_CA_list                 wolfSSL_dup_CA_list
+
+#define sk_X509_NAME_find               wolfSSL_sk_X509_NAME_find
+
+enum {
+    GEN_DNS   = 0x02, /* ASN_DNS_TYPE */
+    GEN_EMAIL = 0x01, /* ASN_RFC822_TYPE */
+    GEN_URI   = 0x06, /* ASN_URI_TYPE */
+    GEN_IPADD = 0x07,
+    GEN_RID   = 0x08, /* Registered ID, not supported */
+};
+
+#define PEM_read_bio_DHparams           wolfSSL_PEM_read_bio_DHparams
+#define PEM_read_bio_DSAparams          wolfSSL_PEM_read_bio_DSAparams
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY)
+#define SSL_get_rbio                    wolfSSL_SSL_get_rbio
+#define SSL_get_wbio                    wolfSSL_SSL_get_wbio
+#define SSL_do_handshake                wolfSSL_SSL_do_handshake
+#define SSL_get_ciphers(x)              wolfSSL_get_ciphers_compat(x)
+#define SSL_SESSION_get_id              wolfSSL_SESSION_get_id
+#define SSL_get_cipher_bits(s,np)       \
+                          wolfSSL_CIPHER_get_bits(SSL_get_current_cipher(s),np)
+#define sk_SSL_CIPHER_num               wolfSSL_sk_SSL_CIPHER_num
+#define sk_SSL_COMP_zero                wolfSSL_sk_SSL_COMP_zero
+#define sk_SSL_CIPHER_value             wolfSSL_sk_SSL_CIPHER_value
+#endif /* OPENSSL_ALL || WOLFSSL_HAPROXY */
+#define sk_SSL_CIPHER_dup               wolfSSL_sk_SSL_CIPHER_dup
+#define sk_SSL_CIPHER_free              wolfSSL_sk_SSL_CIPHER_free
+#define sk_SSL_CIPHER_find              wolfSSL_sk_SSL_CIPHER_find
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || defined(WOLFSSL_HAPROXY) \
+    || defined(WOLFSSL_NGINX)
+#include <wolfssl/openssl/pem.h>
+
+#define SSL_CTRL_CHAIN       88
+#define GEN_IPADD            7
+#define ERR_LIB_SSL          20
+#define SSL_R_SHORT_READ     10
+#define ERR_R_PEM_LIB        9
+#define V_ASN1_IA5STRING     22
+#define V_ASN1_UTF8STRING    12
+#define SSL_CTRL_MODE        33
+
+#define SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS        83
+
+#define SSL_CTX_clear_chain_certs(ctx) SSL_CTX_set0_chain(ctx,NULL)
+#define d2i_RSAPrivateKey_bio           wolfSSL_d2i_RSAPrivateKey_bio
+#define SSL_CTX_use_RSAPrivateKey       wolfSSL_CTX_use_RSAPrivateKey
+#define d2i_PrivateKey_bio              wolfSSL_d2i_PrivateKey_bio
+#define BIO_new_bio_pair                wolfSSL_BIO_new_bio_pair
+#define SSL_get_verify_callback         wolfSSL_get_verify_callback
+
+#define SSL_set_mode(ssl,op)         wolfSSL_ctrl((ssl),SSL_CTRL_MODE,(op),NULL)
+
+#define SSL_CTX_use_certificate_ASN1    wolfSSL_CTX_use_certificate_ASN1
+#define SSL_CTX_set0_chain(ctx,sk) \
+                             wolfSSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN,0,(char *)(sk))
+#define SSL_CTX_get_app_data(ctx)       wolfSSL_CTX_get_ex_data(ctx,0)
+#define SSL_CTX_set_app_data(ctx,arg)   wolfSSL_CTX_set_ex_data(ctx,0, \
+                                                                  (char *)(arg))
+#endif /* OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY */
+
+#define SSL_CTX_set_tmp_dh              wolfSSL_CTX_set_tmp_dh
+
+#define TLSEXT_STATUSTYPE_ocsp  1
+
+#define SSL_set_options                 wolfSSL_set_options
+#define SSL_get_options                 wolfSSL_get_options
+#define SSL_clear_options               wolfSSL_clear_options
+#define SSL_set_tmp_dh                  wolfSSL_set_tmp_dh
+#define SSL_clear_num_renegotiations    wolfSSL_clear_num_renegotiations
+#define SSL_total_renegotiations        wolfSSL_total_renegotiations
+#define SSL_num_renegotiations          wolfSSL_num_renegotiations
+#define SSL_renegotiate                 wolfSSL_Rehandshake
+#define SSL_get_secure_renegotiation_support wolfSSL_SSL_get_secure_renegotiation_support
+#define SSL_set_tlsext_debug_arg        wolfSSL_set_tlsext_debug_arg
+#define SSL_set_tlsext_status_type      wolfSSL_set_tlsext_status_type
+#define SSL_set_tlsext_status_exts      wolfSSL_set_tlsext_status_exts
+#define SSL_get_tlsext_status_ids       wolfSSL_get_tlsext_status_ids
+#define SSL_set_tlsext_status_ids       wolfSSL_set_tlsext_status_ids
+#define SSL_get_tlsext_status_ocsp_res  wolfSSL_get_tlsext_status_ocsp_resp
+#define SSL_set_tlsext_status_ocsp_res  wolfSSL_set_tlsext_status_ocsp_resp
+#define SSL_set_tlsext_status_ocsp_resp  wolfSSL_set_tlsext_status_ocsp_resp
+#define SSL_get_tlsext_status_ocsp_resp  wolfSSL_get_tlsext_status_ocsp_resp
+
+#define SSL_CTX_add_extra_chain_cert    wolfSSL_CTX_add_extra_chain_cert
+#define SSL_CTX_get_read_ahead          wolfSSL_CTX_get_read_ahead
+#define SSL_CTX_set_read_ahead          wolfSSL_CTX_set_read_ahead
+#define SSL_CTX_set_tlsext_status_arg   wolfSSL_CTX_set_tlsext_status_arg
+#define SSL_CTX_set_tlsext_opaque_prf_input_callback_arg \
+                            wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg
+#define SSL_get_server_random           wolfSSL_get_server_random
+#define SSL_get_server_tmp_key          wolfSSL_get_server_tmp_key
+
+#define SSL_CTX_set_min_proto_version   wolfSSL_CTX_set_min_proto_version
+#define SSL_CTX_set_max_proto_version   wolfSSL_CTX_set_max_proto_version
+
+#define SSL_get_tlsext_status_exts      wolfSSL_get_tlsext_status_exts
+
+#define SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS         11
+#define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS         12
+#define SSL_CTRL_SET_TMP_DH                       3
+#define SSL_CTRL_SET_TMP_ECDH                     4
+#define SSL_CTRL_SET_TLSEXT_DEBUG_ARG             57
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE       65
+#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS       66
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS       67
+#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS        68
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS        69
+#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP  70
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP  71
+
+#define SSL_CTRL_EXTRA_CHAIN_CERT               14
+#define SSL_CTRL_OPTIONS                        32
+
+#define SSL_CTRL_SET_SESS_CACHE_SIZE            42
+#define SSL_CTRL_GET_READ_AHEAD                 40
+#define SSL_CTRL_SET_READ_AHEAD                 41
+
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB       63
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG   64
+
+#define SSL_CTRL_GET_EXTRA_CHAIN_CERTS          82
+#define SSL_CTRL_GET_SESSION_REUSED             0
+
+#define SSL_ctrl                        wolfSSL_ctrl
+#define SSL_CTX_ctrl                    wolfSSL_CTX_ctrl
+#define SSL_CTX_callback_ctrl           wolfSSL_CTX_callback_ctrl
+
+#define SSL3_RANDOM_SIZE                32 /* same as RAN_LEN in internal.h */
+
+#define SSL2_VERSION                     0x0002
+#define SSL3_VERSION                     0x0300
+#define TLS1_VERSION                     0x0301
+#define TLS1_1_VERSION                   0x0302
+#define TLS1_2_VERSION                   0x0303
+#define TLS1_3_VERSION                   0x0304
+#define DTLS1_VERSION                    0xFEFF
+#define DTLS1_2_VERSION                  0xFEFD
+
+#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(OPENSSL_EXTRA) \
+                                                         || defined(OPENSSL_ALL)
+#include <wolfssl/openssl/asn1.h>
+
+#define SSL23_ST_SR_CLNT_HELLO_A        (0x210|0x2000)
+#define SSL3_ST_SR_CLNT_HELLO_A         (0x110|0x2000)
+
+#define SSL3_AD_BAD_CERTIFICATE          bad_certificate
+#define SSL_AD_BAD_CERTIFICATE           SSL3_AD_BAD_CERTIFICATE
+
+#define ASN1_STRFLGS_ESC_MSB             4
+
+#define SSL_MAX_MASTER_KEY_LENGTH       WOLFSSL_MAX_MASTER_KEY_LENGTH
+
+#define SSL_alert_desc_string_long      wolfSSL_alert_desc_string_long
+#define SSL_alert_type_string_long      wolfSSL_alert_type_string_long
+#define SSL_CIPHER_get_bits             wolfSSL_CIPHER_get_bits
+#define sk_GENERAL_NAME_num             wolfSSL_sk_GENERAL_NAME_num
+#define SSL_CTX_get_options             wolfSSL_CTX_get_options
+
+#define SSL_CTX_flush_sessions          wolfSSL_flush_sessions
+#define SSL_CTX_add_session             wolfSSL_CTX_add_session
+#define SSL_version(x)                  wolfSSL_version ((WOLFSSL*) (x))
+#define SSL_get_state                   wolfSSL_get_state
+#define SSL_state_string_long           wolfSSL_state_string_long
+
+#define GENERAL_NAME_new                wolfSSL_GENERAL_NAME_new
+#define GENERAL_NAME_free               wolfSSL_GENERAL_NAME_free
+#define sk_GENERAL_NAME_push            wolfSSL_sk_GENERAL_NAME_push
+#define sk_GENERAL_NAME_value           wolfSSL_sk_GENERAL_NAME_value
+#define SSL_SESSION_get_ex_data         wolfSSL_SESSION_get_ex_data
+#define SSL_SESSION_set_ex_data         wolfSSL_SESSION_set_ex_data
+#define SSL_SESSION_get_ex_new_index    wolfSSL_SESSION_get_ex_new_index
+#define SSL_SESSION_get_id              wolfSSL_SESSION_get_id
+#define SSL_SESSION_print               wolfSSL_SESSION_print
+#define sk_GENERAL_NAME_pop_free        wolfSSL_sk_GENERAL_NAME_pop_free
+#define sk_GENERAL_NAME_free            wolfSSL_sk_GENERAL_NAME_free
+#define sk_ASN1_OBJECT_pop_free         wolfSSL_sk_ASN1_OBJECT_pop_free
+#define GENERAL_NAME_free               wolfSSL_GENERAL_NAME_free
+#define GENERAL_NAMES_free              wolfSSL_GENERAL_NAMES_free
+
+#define AUTHORITY_INFO_ACCESS_free      wolfSSL_AUTHORITY_INFO_ACCESS_free
+#define sk_ACCESS_DESCRIPTION_pop_free  wolfSSL_sk_ACCESS_DESCRIPTION_pop_free
+#define sk_ACCESS_DESCRIPTION_free      wolfSSL_sk_ACCESS_DESCRIPTION_free
+#define ACCESS_DESCRIPTION_free         wolfSSL_ACCESS_DESCRIPTION_free
+
+#define SSL3_AL_FATAL                   2
+#define SSL_TLSEXT_ERR_OK               0
+#define SSL_TLSEXT_ERR_ALERT_FATAL      alert_fatal
+#define SSL_TLSEXT_ERR_NOACK            alert_warning
+#define TLSEXT_NAMETYPE_host_name       WOLFSSL_SNI_HOST_NAME
+
+#define SSL_set_tlsext_host_name        wolfSSL_set_tlsext_host_name
+#define SSL_get_servername              wolfSSL_get_servername
+#define SSL_set_SSL_CTX                 wolfSSL_set_SSL_CTX
+#define SSL_CTX_get_verify_callback     wolfSSL_CTX_get_verify_callback
+#define SSL_CTX_set_tlsext_servername_callback wolfSSL_CTX_set_tlsext_servername_callback
+#define SSL_CTX_set_tlsext_servername_arg wolfSSL_CTX_set_servername_arg
+
+#define PSK_MAX_PSK_LEN                 256
+#define PSK_MAX_IDENTITY_LEN            128
+#define SSL_CTX_clear_options           wolfSSL_CTX_clear_options
+
+
+#endif /* HAVE_STUNNEL || WOLFSSL_NGINX */
+#define SSL_CTX_get_default_passwd_cb   wolfSSL_CTX_get_default_passwd_cb
+#define SSL_CTX_get_default_passwd_cb_userdata wolfSSL_CTX_get_default_passwd_cb_userdata
+
+#define SSL_CTX_set_msg_callback        wolfSSL_CTX_set_msg_callback
+#define SSL_set_msg_callback            wolfSSL_set_msg_callback
+#define SSL_CTX_set_msg_callback_arg    wolfSSL_CTX_set_msg_callback_arg
+#define SSL_set_msg_callback_arg        wolfSSL_set_msg_callback_arg
+
+#define SSL_CTX_clear_extra_chain_certs wolfSSL_CTX_clear_extra_chain_certs
+
+
+/* Nginx uses this to determine if reached end of certs in file.
+ * PEM_read_bio_X509 is called and the return error is lost.
+ * The error that needs to be detected is: SSL_NO_PEM_HEADER.
+ */
+#define ERR_GET_FUNC(l) (int)((((unsigned long)l) >> 12L) & 0xfffL)
+
+#define PEM_F_PEM_DEF_CALLBACK  100
+
+/* Avoid wolfSSL error code range */
+#define PEM_R_NO_START_LINE             (-MIN_CODE_E + 1)
+#define PEM_R_PROBLEMS_GETTING_PASSWORD (-MIN_CODE_E + 2)
+#define PEM_R_BAD_PASSWORD_READ         (-MIN_CODE_E + 3)
+#define PEM_R_BAD_DECRYPT               (-MIN_CODE_E + 4)
+
+#define ERR_LIB_PEM             9
+#define ERR_LIB_X509            10
+#define ERR_LIB_EVP             11
+#define ERR_LIB_ASN1            12
+
+#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
+    defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_ALL) || \
+    defined(HAVE_LIGHTY)
+
+#include <wolfssl/error-ssl.h>
+
+#define OPENSSL_STRING    WOLFSSL_STRING
+
+#define TLSEXT_TYPE_application_layer_protocol_negotiation    16
+
+#define OPENSSL_NPN_UNSUPPORTED 0
+#define OPENSSL_NPN_NEGOTIATED  1
+#define OPENSSL_NPN_NO_OVERLAP  2
+
+/* Nginx checks these to see if the error was a handshake error. */
+#define SSL_R_BAD_CHANGE_CIPHER_SPEC               LENGTH_ERROR
+#define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG            BUFFER_E
+#define SSL_R_DIGEST_CHECK_FAILED                  VERIFY_MAC_ERROR
+#define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST        SUITES_ERROR
+#define SSL_R_EXCESSIVE_MESSAGE_SIZE               BUFFER_ERROR
+#define SSL_R_LENGTH_MISMATCH                      LENGTH_ERROR
+#define SSL_R_NO_CIPHERS_SPECIFIED                 SUITES_ERROR
+#define SSL_R_NO_COMPRESSION_SPECIFIED             COMPRESSION_ERROR
+#define SSL_R_NO_SHARED_CIPHER                     MATCH_SUITE_ERROR
+#define SSL_R_RECORD_LENGTH_MISMATCH               HANDSHAKE_SIZE_ERROR
+#define SSL_R_UNEXPECTED_MESSAGE                   OUT_OF_ORDER_E
+#define SSL_R_UNEXPECTED_RECORD                    SANITY_MSG_E
+#define SSL_R_UNKNOWN_ALERT_TYPE                   BUFFER_ERROR
+#define SSL_R_UNKNOWN_PROTOCOL                     VERSION_ERROR
+#define SSL_R_WRONG_VERSION_NUMBER                 VERSION_ERROR
+#define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC  ENCRYPT_ERROR
+#define SSL_R_HTTPS_PROXY_REQUEST                  PARSE_ERROR
+#define SSL_R_HTTP_REQUEST                         PARSE_ERROR
+#define SSL_R_UNSUPPORTED_PROTOCOL                 VERSION_ERROR
+
+
+#ifdef HAVE_SESSION_TICKET
+#define SSL_OP_NO_TICKET                  SSL_OP_NO_TICKET
+#define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB 72
+#endif
+
+#define OPENSSL_config	                wolfSSL_OPENSSL_config
+#define OPENSSL_memdup                  wolfSSL_OPENSSL_memdup
+#define SSL_CTX_get_timeout             wolfSSL_SSL_CTX_get_timeout
+#define SSL_CTX_set_tmp_ecdh            wolfSSL_SSL_CTX_set_tmp_ecdh
+#define SSL_CTX_remove_session          wolfSSL_SSL_CTX_remove_session
+#define SSL_get_rbio                    wolfSSL_SSL_get_rbio
+#define SSL_get_wbio                    wolfSSL_SSL_get_wbio
+#define SSL_do_handshake                wolfSSL_SSL_do_handshake
+#define SSL_in_init                     wolfSSL_SSL_in_init
+#define SSL_in_connect_init             wolfSSL_SSL_in_connect_init
+#define SSL_get0_session                wolfSSL_SSL_get0_session
+#define SSL_CTX_set_tlsext_ticket_key_cb wolfSSL_CTX_set_tlsext_ticket_key_cb
+#define SSL_CTX_set_tlsext_status_cb    wolfSSL_CTX_set_tlsext_status_cb
+#define SSL_CTX_get_extra_chain_certs   wolfSSL_CTX_get_extra_chain_certs
+#define sk_OPENSSL_STRING_value         wolfSSL_sk_WOLFSSL_STRING_value
+#define SSL_get0_alpn_selected          wolfSSL_get0_alpn_selected
+#define SSL_select_next_proto           wolfSSL_select_next_proto
+#define SSL_CTX_set_alpn_select_cb      wolfSSL_CTX_set_alpn_select_cb
+#define SSL_CTX_set_next_protos_advertised_cb  wolfSSL_CTX_set_next_protos_advertised_cb
+#define SSL_CTX_set_next_proto_select_cb wolfSSL_CTX_set_next_proto_select_cb
+#define SSL_set_alpn_protos             wolfSSL_set_alpn_protos
+#define SSL_get0_next_proto_negotiated  wolfSSL_get0_next_proto_negotiated
+#define SSL_is_server                   wolfSSL_is_server
+
+#endif /* WOLFSSL_NGINX || WOLFSSL_HAPROXY || WOLFSSL_MYSQL_COMPATIBLE ||
+          OPENSSL_ALL || HAVE_LIGHTY */
+
+#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC)
+#define SSL_CTX_set1_curves_list        wolfSSL_CTX_set1_curves_list
+#define SSL_set1_curves_list            wolfSSL_set1_curves_list
+#endif
+
+#ifdef OPENSSL_EXTRA
+#define SSL_CTX_add_client_CA           wolfSSL_CTX_add_client_CA
+#define SSL_CTX_set_srp_password        wolfSSL_CTX_set_srp_password
+#define SSL_CTX_set_srp_username        wolfSSL_CTX_set_srp_username
+#define SSL_get_SSL_CTX                 wolfSSL_get_SSL_CTX
+#define SSL_get0_param                  wolfSSL_get0_param
+
+#define ERR_NUM_ERRORS                  16
+#define SN_pkcs9_emailAddress           "Email"
+#define LN_pkcs9_emailAddress           "emailAddress"
+#define NID_pkcs9_emailAddress          48
+#define OBJ_pkcs9_emailAddress          1L,2L,840L,113539L,1L,9L,1L
+
+#define SSL_get_rbio                    wolfSSL_SSL_get_rbio
+#define SSL_get_wbio                    wolfSSL_SSL_get_wbio
+#define SSL_do_handshake                wolfSSL_SSL_do_handshake
+#endif  /* OPENSSL_EXTRA */
+
+/* cipher suites for compatibility */
+#define TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA            (0xc013)
+#define TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA            (0xc014)
+#define TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256         (0xc02f)
+#define TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256   (0xcca8)
+#define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA          (0xc009)
+#define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA          (0xc00a)
+#define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256       (0xc02b)
+#define TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca9)
+
+#define X509_STORE_get0_objects         wolfSSL_X509_STORE_get0_objects
+#define sk_X509_OBJECT_num              wolfSSL_sk_X509_OBJECT_num
+#define sk_X509_OBJECT_value            wolfSSL_sk_X509_OBJECT_value
+#define sk_X509_OBJECT_delete           wolfSSL_sk_X509_OBJECT_delete
+#define X509_OBJECT_free                wolfSSL_X509_OBJECT_free
+#define X509_OBJECT_get_type(x)         0
+
+#define OpenSSL_version(x)              wolfSSL_lib_version()
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* wolfSSL_openssl_h__ */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/stack.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/stack.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/stack.h	(revision 453)
@@ -0,0 +1,59 @@
+/* stack.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* stack.h for openSSL */
+
+#ifndef WOLFSSL_STACK_H_
+#define WOLFSSL_STACK_H_
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+typedef void (*wolfSSL_sk_freefunc)(void *);
+
+WOLFSSL_API void wolfSSL_sk_GENERIC_pop_free(WOLFSSL_STACK* sk, wolfSSL_sk_freefunc);
+WOLFSSL_API void wolfSSL_sk_GENERIC_free(WOLFSSL_STACK *);
+WOLFSSL_API int wolfSSL_sk_GENERIC_push(WOLFSSL_STACK *sk, void *data);
+WOLFSSL_API void wolfSSL_sk_pop_free(WOLFSSL_STACK *st, void (*func) (void *));
+WOLFSSL_API void wolfSSL_sk_CONF_VALUE_free(WOLF_STACK_OF(WOLFSSL_CONF_VALUE)* sk);
+WOLFSSL_API WOLFSSL_STACK *wolfSSL_sk_new_null(void);
+
+WOLFSSL_API int wolfSSL_sk_CIPHER_push(WOLFSSL_STACK *st,WOLFSSL_CIPHER *cipher);
+WOLFSSL_API WOLFSSL_CIPHER* wolfSSL_sk_CIPHER_pop(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk);
+WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_new_cipher(void);
+
+#define OPENSSL_sk_free       wolfSSL_sk_free
+#define OPENSSL_sk_pop_free   wolfSSL_sk_pop_free
+#define OPENSSL_sk_new_null   wolfSSL_sk_new_null
+#define OPENSSL_sk_push       wolfSSL_sk_push
+
+/* provides older OpenSSL API compatibility  */
+#define sk_free         OPENSSL_sk_free
+#define sk_pop_free     OPENSSL_sk_pop_free
+#define sk_new_null     OPENSSL_sk_new_null
+#define sk_push         OPENSSL_sk_push
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/tls1.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/tls1.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/tls1.h	(revision 453)
@@ -0,0 +1,46 @@
+/* tls1.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifndef WOLFSSL_OPENSSL_TLS1_H_
+#define WOLFSSL_OPENSSL_TLS1_H_
+
+#ifndef TLS1_VERSION
+#define TLS1_VERSION                    0x0301
+#endif
+
+#ifndef TLS1_1_VERSION
+#define TLS1_1_VERSION                  0x0302
+#endif
+
+#ifndef TLS1_2_VERSION
+#define TLS1_2_VERSION                  0x0303
+#endif
+
+#ifndef TLS1_3_VERSION
+#define TLS1_3_VERSION                  0x0304
+#endif
+
+#ifndef TLS_MAX_VERSION
+#define TLS_MAX_VERSION                 TLS1_3_VERSION
+#endif
+
+#endif /* WOLFSSL_OPENSSL_TLS1_H_ */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ui.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ui.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/ui.h	(revision 453)
@@ -0,0 +1,2 @@
+/* ui.h for openssl */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/x509.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/x509.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/x509.h	(revision 453)
@@ -0,0 +1,26 @@
+/* x509.h for openssl */
+
+#include <wolfssl/openssl/ssl.h>
+#include <wolfssl/openssl/crypto.h>
+#include <wolfssl/openssl/dh.h>
+#include <wolfssl/openssl/ec.h>
+#include <wolfssl/openssl/ecdsa.h>
+
+/* wolfSSL_X509_print_ex flags */
+#define X509_FLAG_COMPAT        (0UL)
+#define X509_FLAG_NO_HEADER     (1UL << 0)
+#define X509_FLAG_NO_VERSION    (1UL << 1)
+#define X509_FLAG_NO_SERIAL     (1UL << 2)
+#define X509_FLAG_NO_SIGNAME    (1UL << 3)
+#define X509_FLAG_NO_ISSUER     (1UL << 4)
+#define X509_FLAG_NO_VALIDITY   (1UL << 5)
+#define X509_FLAG_NO_SUBJECT    (1UL << 6)
+#define X509_FLAG_NO_PUBKEY     (1UL << 7)
+#define X509_FLAG_NO_EXTENSIONS (1UL << 8)
+#define X509_FLAG_NO_SIGDUMP    (1UL << 9)
+#define X509_FLAG_NO_AUX        (1UL << 10)
+#define X509_FLAG_NO_ATTRIBUTES (1UL << 11)
+#define X509_FLAG_NO_IDS        (1UL << 12)
+
+#define XN_FLAG_FN_SN           0
+#define XN_FLAG_SEP_CPLUS_SPC   2
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/x509_vfy.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/x509_vfy.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/x509_vfy.h	(revision 453)
@@ -0,0 +1,45 @@
+/* x509_vfy.h
+ *
+ * Copyright (C) 2006-2017 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* x509_vfy.h for openSSL */
+
+#ifndef WOLFSSL_x509_vfy_H_
+#define WOLFSSL_x509_vfy_H_
+
+#include <wolfssl/openssl/x509v3.h>
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+    WOLFSSL_API int wolfSSL_X509_STORE_CTX_set_purpose(WOLFSSL_X509_STORE_CTX *ctx, int purpose);
+#endif
+
+#ifdef WOLFSSL_QT
+    #define X509_STORE_CTX_set_purpose  wolfSSL_X509_STORE_CTX_set_purpose
+#endif
+
+#ifdef  __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* WOLFSSL_x509_vfy_H_ */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/x509v3.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/x509v3.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/openssl/x509v3.h	(revision 453)
@@ -0,0 +1,116 @@
+/* x509v3.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* x509v3.h for openSSL */
+
+#ifndef WOLFSSL_x509v3_H
+#define WOLFSSL_x509v3_H
+
+#include <wolfssl/openssl/conf.h>
+#include <wolfssl/openssl/bio.h>
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+#define X509_PURPOSE_SSL_CLIENT       0
+#define X509_PURPOSE_SSL_SERVER       1
+
+#define NS_SSL_CLIENT                 0
+#define NS_SSL_SERVER                 1
+
+/* Forward reference */
+
+typedef void *(*X509V3_EXT_D2I)(void *, const unsigned char **, long);
+typedef STACK_OF(CONF_VALUE) *(*X509V3_EXT_I2V) (
+                                struct WOLFSSL_v3_ext_method *method,
+                                void *ext, STACK_OF(CONF_VALUE) *extlist);
+typedef char *(*X509V3_EXT_I2S)(struct WOLFSSL_v3_ext_method *method, void *ext);
+typedef int (*X509V3_EXT_I2R) (struct WOLFSSL_v3_ext_method *method,
+                               void *ext, BIO *out, int indent);
+typedef struct WOLFSSL_v3_ext_method X509V3_EXT_METHOD;
+
+struct WOLFSSL_v3_ext_method {
+    int ext_nid;
+    int ext_flags;
+    void *usr_data;
+    X509V3_EXT_D2I d2i;
+    X509V3_EXT_I2V i2v;
+    X509V3_EXT_I2S i2s;
+    X509V3_EXT_I2R i2r;
+};
+
+struct WOLFSSL_X509_EXTENSION {
+    WOLFSSL_ASN1_OBJECT *obj;
+    WOLFSSL_ASN1_BOOLEAN crit;
+    WOLFSSL_ASN1_STRING value;
+    WOLFSSL_v3_ext_method ext_method;
+    WOLFSSL_STACK* ext_sk; /* For extension specific data */
+};
+
+#define WOLFSSL_ASN1_BOOLEAN int
+#define GEN_OTHERNAME   0
+#define GEN_EMAIL       1
+#define GEN_DNS         2
+#define GEN_X400        3
+#define GEN_DIRNAME     4
+#define GEN_EDIPARTY    5
+#define GEN_URI         6
+#define GEN_IPADD       7
+#define GEN_RID         8
+
+#define GENERAL_NAME       WOLFSSL_GENERAL_NAME
+
+#define X509V3_CTX         WOLFSSL_X509V3_CTX
+
+typedef struct WOLFSSL_AUTHORITY_KEYID AUTHORITY_KEYID;
+typedef struct WOLFSSL_BASIC_CONSTRAINTS BASIC_CONSTRAINTS;
+typedef struct WOLFSSL_ACCESS_DESCRIPTION ACCESS_DESCRIPTION;
+typedef WOLF_STACK_OF(WOLFSSL_ACCESS_DESCRIPTION) WOLFSSL_AUTHORITY_INFO_ACCESS;
+
+WOLFSSL_API void wolfSSL_BASIC_CONSTRAINTS_free(WOLFSSL_BASIC_CONSTRAINTS *bc);
+WOLFSSL_API void wolfSSL_AUTHORITY_KEYID_free(WOLFSSL_AUTHORITY_KEYID *id);
+WOLFSSL_API const WOLFSSL_v3_ext_method* wolfSSL_X509V3_EXT_get(
+                                                    WOLFSSL_X509_EXTENSION* ex);
+WOLFSSL_API void* wolfSSL_X509V3_EXT_d2i(WOLFSSL_X509_EXTENSION* ex);
+WOLFSSL_API char* wolfSSL_i2s_ASN1_STRING(WOLFSSL_v3_ext_method *method,
+                                          const WOLFSSL_ASN1_STRING *s);
+WOLFSSL_API int wolfSSL_X509V3_EXT_print(WOLFSSL_BIO *out,
+        WOLFSSL_X509_EXTENSION *ext, unsigned long flag, int indent);
+
+#define BASIC_CONSTRAINTS_free    wolfSSL_BASIC_CONSTRAINTS_free
+#define AUTHORITY_KEYID_free      wolfSSL_AUTHORITY_KEYID_free
+#define SSL_CTX_get_cert_store(x) wolfSSL_CTX_get_cert_store ((WOLFSSL_CTX*) (x))
+#define ASN1_INTEGER              WOLFSSL_ASN1_INTEGER
+#define ASN1_OCTET_STRING         WOLFSSL_ASN1_STRING
+#define X509V3_EXT_get            wolfSSL_X509V3_EXT_get
+#define X509V3_EXT_d2i            wolfSSL_X509V3_EXT_d2i
+#define i2s_ASN1_OCTET_STRING     wolfSSL_i2s_ASN1_STRING
+#define X509V3_EXT_print          wolfSSL_X509V3_EXT_print
+#define X509V3_EXT_conf_nid wolfSSL_X509V3_EXT_conf_nid
+#define X509V3_set_ctx      wolfSSL_X509V3_set_ctx
+#define X509V3_set_ctx_nodb wolfSSL_X509V3_set_ctx_nodb
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/options.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/options.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/options.h	(revision 453)
@@ -0,0 +1,40 @@
+/* options.h.in
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+/* default blank options for autoconf */
+
+#ifndef WOLFSSL_OPTIONS_H
+#define WOLFSSL_OPTIONS_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* WOLFSSL_OPTIONS_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/ssl.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/ssl.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/ssl.h	(revision 453)
@@ -0,0 +1,3866 @@
+/* ssl.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+/*!
+    \file ../wolfssl/ssl.h
+    \brief Header file containing key wolfSSL API
+*/
+
+/* wolfSSL API */
+
+#ifndef WOLFSSL_SSL_H
+#define WOLFSSL_SSL_H
+
+
+/* for users not using preprocessor flags*/
+#include <wolfssl/wolfcrypt/settings.h>
+#include <wolfssl/version.h>
+#include <wolfssl/wolfcrypt/logging.h>
+#include <wolfssl/wolfcrypt/asn_public.h>
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifdef HAVE_WOLF_EVENT
+    #include <wolfssl/wolfcrypt/wolfevent.h>
+#endif
+
+/* used internally by wolfSSL while OpenSSL types aren't */
+#include <wolfssl/callbacks.h>
+
+#ifdef WOLFSSL_PREFIX
+    #include "prefix_ssl.h"
+#endif
+
+#ifdef LIBWOLFSSL_VERSION_STRING
+    #define WOLFSSL_VERSION LIBWOLFSSL_VERSION_STRING
+#endif
+
+#ifdef _WIN32
+    /* wincrypt.h clashes */
+    #undef OCSP_REQUEST
+    #undef OCSP_RESPONSE
+#endif
+
+#ifdef OPENSSL_COEXIST
+    /* mode to allow wolfSSL and OpenSSL to exist together */
+    #ifdef TEST_OPENSSL_COEXIST
+        /*
+        ./configure --enable-opensslcoexist \
+            CFLAGS="-I/usr/local/opt/openssl/include -DTEST_OPENSSL_COEXIST" \
+            LDFLAGS="-L/usr/local/opt/openssl/lib -lcrypto"
+        */
+        #include <openssl/ssl.h>
+        #include <openssl/rand.h>
+        #include <openssl/err.h>
+        #include <openssl/ec.h>
+        #include <openssl/hmac.h>
+        #include <openssl/bn.h>
+    #endif
+
+    /* make sure old names are disabled */
+    #ifndef NO_OLD_SSL_NAMES
+        #define NO_OLD_SSL_NAMES
+    #endif
+    #ifndef NO_OLD_WC_NAMES
+        #define NO_OLD_WC_NAMES
+    #endif
+
+#elif (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
+    #include <wolfssl/openssl/bn.h>
+    #include <wolfssl/openssl/hmac.h>
+
+    /* We need the old SSL names */
+    #ifdef NO_OLD_SSL_NAMES
+        #undef NO_OLD_SSL_NAMES
+    #endif
+    #ifdef NO_OLD_WC_NAMES
+        #undef NO_OLD_WC_NAMES
+    #endif
+#endif
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+#ifndef WOLFSSL_WOLFSSL_TYPE_DEFINED
+#define WOLFSSL_WOLFSSL_TYPE_DEFINED
+typedef struct WOLFSSL          WOLFSSL;
+#endif
+typedef struct WOLFSSL_SESSION  WOLFSSL_SESSION;
+typedef struct WOLFSSL_METHOD   WOLFSSL_METHOD;
+#ifndef WOLFSSL_WOLFSSL_CTX_TYPE_DEFINED
+#define WOLFSSL_WOLFSSL_CTX_TYPE_DEFINED
+typedef struct WOLFSSL_CTX      WOLFSSL_CTX;
+#endif
+
+typedef struct WOLFSSL_STACK      WOLFSSL_STACK;
+typedef struct WOLFSSL_X509       WOLFSSL_X509;
+typedef struct WOLFSSL_X509_NAME  WOLFSSL_X509_NAME;
+typedef struct WOLFSSL_X509_NAME_ENTRY  WOLFSSL_X509_NAME_ENTRY;
+typedef struct WOLFSSL_X509_PUBKEY WOLFSSL_X509_PUBKEY;
+typedef struct WOLFSSL_X509_ALGOR WOLFSSL_X509_ALGOR;
+typedef struct WOLFSSL_X509_CHAIN WOLFSSL_X509_CHAIN;
+typedef struct WC_PKCS12          WOLFSSL_X509_PKCS12;
+typedef struct WOLFSSL_X509_INFO  WOLFSSL_X509_INFO;
+
+typedef struct WOLFSSL_CERT_MANAGER WOLFSSL_CERT_MANAGER;
+typedef struct WOLFSSL_SOCKADDR     WOLFSSL_SOCKADDR;
+typedef struct WOLFSSL_CRL          WOLFSSL_CRL;
+typedef struct WOLFSSL_X509_STORE_CTX WOLFSSL_X509_STORE_CTX;
+
+typedef int (*WOLFSSL_X509_STORE_CTX_verify_cb)(int, WOLFSSL_X509_STORE_CTX *);
+
+/* redeclare guard */
+#define WOLFSSL_TYPES_DEFINED
+
+#include <wolfssl/wolfio.h>
+
+
+#ifndef WOLFSSL_RSA_TYPE_DEFINED /* guard on redeclaration */
+typedef struct WOLFSSL_RSA            WOLFSSL_RSA;
+#define WOLFSSL_RSA_TYPE_DEFINED
+#endif
+
+#ifndef WC_RNG_TYPE_DEFINED /* guard on redeclaration */
+    typedef struct WC_RNG WC_RNG;
+    #define WC_RNG_TYPE_DEFINED
+#endif
+
+#ifndef WOLFSSL_DSA_TYPE_DEFINED /* guard on redeclaration */
+typedef struct WOLFSSL_DSA            WOLFSSL_DSA;
+#define WOLFSSL_DSA_TYPE_DEFINED
+#endif
+
+#ifndef WOLFSSL_EC_TYPE_DEFINED /* guard on redeclaration */
+typedef struct WOLFSSL_EC_KEY         WOLFSSL_EC_KEY;
+typedef struct WOLFSSL_EC_POINT       WOLFSSL_EC_POINT;
+typedef struct WOLFSSL_EC_GROUP       WOLFSSL_EC_GROUP;
+typedef struct WOLFSSL_EC_BUILTIN_CURVE WOLFSSL_EC_BUILTIN_CURVE;
+/* WOLFSSL_EC_METHOD is just an alias of WOLFSSL_EC_GROUP for now */
+typedef struct WOLFSSL_EC_GROUP       WOLFSSL_EC_METHOD;
+#define WOLFSSL_EC_TYPE_DEFINED
+#endif
+
+#ifndef WOLFSSL_ECDSA_TYPE_DEFINED /* guard on redeclaration */
+typedef struct WOLFSSL_ECDSA_SIG      WOLFSSL_ECDSA_SIG;
+#define WOLFSSL_ECDSA_TYPE_DEFINED
+#endif
+
+typedef struct WOLFSSL_CIPHER         WOLFSSL_CIPHER;
+typedef struct WOLFSSL_X509_LOOKUP    WOLFSSL_X509_LOOKUP;
+typedef struct WOLFSSL_X509_LOOKUP_METHOD WOLFSSL_X509_LOOKUP_METHOD;
+typedef struct WOLFSSL_CRL            WOLFSSL_X509_CRL;
+typedef struct WOLFSSL_X509_STORE     WOLFSSL_X509_STORE;
+typedef struct WOLFSSL_X509_VERIFY_PARAM WOLFSSL_X509_VERIFY_PARAM;
+typedef struct WOLFSSL_BIO            WOLFSSL_BIO;
+typedef struct WOLFSSL_BIO_METHOD     WOLFSSL_BIO_METHOD;
+typedef struct WOLFSSL_X509_EXTENSION WOLFSSL_X509_EXTENSION;
+typedef struct WOLFSSL_CONF_VALUE     WOLFSSL_CONF_VALUE;
+typedef struct WOLFSSL_ASN1_OBJECT    WOLFSSL_ASN1_OBJECT;
+typedef struct WOLFSSL_ASN1_OTHERNAME WOLFSSL_ASN1_OTHERNAME;
+typedef struct WOLFSSL_X509V3_CTX     WOLFSSL_X509V3_CTX;
+typedef struct WOLFSSL_v3_ext_method  WOLFSSL_v3_ext_method;
+
+typedef struct WOLFSSL_ASN1_STRING      WOLFSSL_ASN1_STRING;
+typedef struct WOLFSSL_dynlock_value    WOLFSSL_dynlock_value;
+#ifndef WOLFSSL_DH_TYPE_DEFINED /* guard on redeclaration */
+typedef struct WOLFSSL_DH               WOLFSSL_DH;
+#define WOLFSSL_DH_TYPE_DEFINED /* guard on redeclaration */
+#endif
+typedef struct WOLFSSL_ASN1_BIT_STRING  WOLFSSL_ASN1_BIT_STRING;
+typedef struct WOLFSSL_ASN1_TYPE        WOLFSSL_ASN1_TYPE;
+
+typedef struct WOLFSSL_GENERAL_NAME WOLFSSL_GENERAL_NAME;
+typedef struct WOLFSSL_AUTHORITY_KEYID  WOLFSSL_AUTHORITY_KEYID;
+typedef struct WOLFSSL_BASIC_CONSTRAINTS WOLFSSL_BASIC_CONSTRAINTS;
+typedef struct WOLFSSL_ACCESS_DESCRIPTION WOLFSSL_ACCESS_DESCRIPTION;
+
+#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
+
+struct WOLFSSL_AUTHORITY_KEYID {
+    WOLFSSL_ASN1_STRING *keyid;
+    WOLFSSL_ASN1_OBJECT *issuer;
+    WOLFSSL_ASN1_INTEGER *serial;
+};
+
+struct WOLFSSL_BASIC_CONSTRAINTS {
+    int ca;
+    WOLFSSL_ASN1_INTEGER *pathlen;
+};
+
+#endif /* OPENSSL_ALL || OPENSSL_EXTRA*/
+
+#define WOLFSSL_ASN1_UTCTIME          WOLFSSL_ASN1_TIME
+#define WOLFSSL_ASN1_GENERALIZEDTIME  WOLFSSL_ASN1_TIME
+
+struct WOLFSSL_ASN1_STRING {
+    char strData[CTC_NAME_SIZE];
+    int length;
+    int type; /* type of string i.e. CTC_UTF8 */
+    char* data;
+    long flags;
+    unsigned int   isDynamic:1; /* flag for if data pointer dynamic (1 is yes 0 is no) */
+};
+
+#define WOLFSSL_MAX_SNAME 40
+
+
+#define WOLFSSL_ASN1_DYNAMIC 0x1
+#define WOLFSSL_ASN1_DYNAMIC_DATA 0x2
+
+struct WOLFSSL_ASN1_OTHERNAME {
+    WOLFSSL_ASN1_OBJECT* type_id;
+    WOLFSSL_ASN1_TYPE*   value;
+};
+
+struct WOLFSSL_GENERAL_NAME {
+    int type;
+    union {
+        char* ptr;
+        WOLFSSL_ASN1_OTHERNAME* otherName;
+        WOLFSSL_ASN1_STRING* rfc822Name;
+        WOLFSSL_ASN1_STRING* dNSName;
+        WOLFSSL_ASN1_TYPE* x400Address;
+        WOLFSSL_X509_NAME* directoryName;
+        WOLFSSL_ASN1_STRING* uniformResourceIdentifier;
+        WOLFSSL_ASN1_STRING* iPAddress;
+        WOLFSSL_ASN1_OBJECT* registeredID;
+
+        WOLFSSL_ASN1_STRING* ip;
+        WOLFSSL_X509_NAME* dirn;
+        WOLFSSL_ASN1_STRING* ia5;
+        WOLFSSL_ASN1_OBJECT* rid;
+        WOLFSSL_ASN1_TYPE* other;
+    } d; /* dereference */
+};
+
+struct WOLFSSL_ACCESS_DESCRIPTION {
+    WOLFSSL_ASN1_OBJECT*  method;
+    WOLFSSL_GENERAL_NAME* location;
+};
+
+struct WOLFSSL_X509V3_CTX {
+    WOLFSSL_X509* x509;
+};
+
+
+
+struct WOLFSSL_ASN1_OBJECT {
+    void*  heap;
+    const unsigned char* obj;
+    /* sName is short name i.e sha256 rather than oid (null terminated) */
+    char   sName[WOLFSSL_MAX_SNAME];
+    int    type; /* oid */
+    int    grp;  /* type of OID, i.e. oidCertPolicyType */
+    int    nid;
+    unsigned int  objSz;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) || defined(WOLFSSL_APACHE_HTTPD)
+    int ca;
+    WOLFSSL_ASN1_INTEGER *pathlen;
+#endif
+    unsigned char dynamic; /* if 1 then obj was dynamically created, 0 otherwise */
+
+#if defined(WOLFSSL_APACHE_HTTPD)
+    WOLFSSL_GENERAL_NAME* gn;
+#endif
+
+    struct d { /* derefrenced */
+        WOLFSSL_ASN1_STRING* dNSName;
+        WOLFSSL_ASN1_STRING  ia5_internal;
+        WOLFSSL_ASN1_STRING* ia5; /* points to ia5_internal */
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+        WOLFSSL_ASN1_STRING* uniformResourceIdentifier;
+        WOLFSSL_ASN1_STRING  iPAddress_internal;
+        WOLFSSL_ASN1_OTHERNAME* otherName; /* added for Apache httpd */
+#endif
+        WOLFSSL_ASN1_STRING* iPAddress; /* points to iPAddress_internal */
+    } d;
+};
+
+/* wrap ASN1 types */
+struct WOLFSSL_ASN1_TYPE {
+    int type;
+    union {
+        char *ptr;
+        WOLFSSL_ASN1_STRING*     asn1_string;
+        WOLFSSL_ASN1_OBJECT*     object;
+        WOLFSSL_ASN1_INTEGER*    integer;
+        WOLFSSL_ASN1_BIT_STRING* bit_string;
+        WOLFSSL_ASN1_STRING*     octet_string;
+        WOLFSSL_ASN1_STRING*     printablestring;
+        WOLFSSL_ASN1_STRING*     ia5string;
+        WOLFSSL_ASN1_UTCTIME*    utctime;
+        WOLFSSL_ASN1_GENERALIZEDTIME* generalizedtime;
+        WOLFSSL_ASN1_STRING*     utf8string;
+        WOLFSSL_ASN1_STRING*     set;
+        WOLFSSL_ASN1_STRING*     sequence;
+    } value;
+};
+
+struct WOLFSSL_EVP_PKEY {
+    void* heap;
+    int type;         /* openssh dereference */
+    int save_type;    /* openssh dereference */
+    int pkey_sz;
+    int references;  /*number of times free should be called for complete free*/
+    wolfSSL_Mutex    refMutex; /* ref count mutex */
+
+    union {
+        char* ptr; /* der format of key / or raw for NTRU */
+    } pkey;
+    #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
+    #ifndef NO_RSA
+        WOLFSSL_RSA* rsa;
+        byte      ownRsa; /* if struct owns RSA and should free it */
+    #endif
+    #ifndef NO_DSA
+        WOLFSSL_DSA* dsa;
+        byte      ownDsa; /* if struct owns DSA and should free it */
+    #endif
+    #ifdef HAVE_ECC
+        WOLFSSL_EC_KEY* ecc;
+        byte      ownEcc; /* if struct owns ECC and should free it */
+    #endif
+    #ifndef NO_DH
+        WOLFSSL_DH* dh;
+        byte      ownDh; /* if struct owns DH and should free it */
+    #endif
+    WC_RNG rng;
+    #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+    #ifdef HAVE_ECC
+        int pkey_curve;
+    #endif
+};
+typedef struct WOLFSSL_EVP_PKEY WOLFSSL_PKCS8_PRIV_KEY_INFO;
+#ifndef WOLFSSL_EVP_TYPE_DEFINED /* guard on redeclaration */
+typedef struct WOLFSSL_EVP_PKEY     WOLFSSL_EVP_PKEY;
+typedef struct WOLFSSL_EVP_MD_CTX   WOLFSSL_EVP_MD_CTX;
+typedef char   WOLFSSL_EVP_MD;
+#define WOLFSSL_EVP_TYPE_DEFINED
+#endif
+
+struct WOLFSSL_X509_PKEY {
+    WOLFSSL_EVP_PKEY* dec_pkey; /* dereferenced by Apache */
+    void* heap;
+};
+typedef struct WOLFSSL_X509_PKEY WOLFSSL_X509_PKEY;
+
+struct WOLFSSL_X509_INFO {
+    WOLFSSL_X509      *x509;
+    WOLFSSL_X509_CRL  *crl;
+    WOLFSSL_X509_PKEY  *x_pkey; /* dereferenced by Apache */
+    EncryptedInfo     enc_cipher;
+    int               enc_len;
+    char              *enc_data;
+    int               num;
+};
+
+#define WOLFSSL_EVP_PKEY_DEFAULT EVP_PKEY_RSA /* default key type */
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+    #define wolfSSL_SSL_MODE_RELEASE_BUFFERS    0x00000010U
+    #define wolfSSL_SSL_CTRL_SET_TMP_ECDH       4
+#endif
+
+struct WOLFSSL_X509_ALGOR {
+    WOLFSSL_ASN1_OBJECT* algorithm;
+    WOLFSSL_ASN1_TYPE* parameter;
+};
+
+struct WOLFSSL_X509_PUBKEY {
+    WOLFSSL_X509_ALGOR* algor;
+    WOLFSSL_EVP_PKEY* pkey;
+    int pubKeyOID;
+};
+
+
+enum BIO_TYPE {
+    WOLFSSL_BIO_BUFFER = 1,
+    WOLFSSL_BIO_SOCKET = 2,
+    WOLFSSL_BIO_SSL    = 3,
+    WOLFSSL_BIO_MEMORY = 4,
+    WOLFSSL_BIO_BIO    = 5,
+    WOLFSSL_BIO_FILE   = 6,
+    WOLFSSL_BIO_BASE64 = 7,
+    WOLFSSL_BIO_MD     = 8
+};
+
+enum BIO_FLAGS {
+    WOLFSSL_BIO_FLAG_BASE64_NO_NL = 0x01,
+    WOLFSSL_BIO_FLAG_READ         = 0x02,
+    WOLFSSL_BIO_FLAG_WRITE        = 0x04,
+    WOLFSSL_BIO_FLAG_IO_SPECIAL   = 0x08,
+    WOLFSSL_BIO_FLAG_RETRY        = 0x10
+};
+
+enum BIO_CB_OPS {
+    WOLFSSL_BIO_CB_FREE   = 0x01,
+    WOLFSSL_BIO_CB_READ   = 0x02,
+    WOLFSSL_BIO_CB_WRITE  = 0x03,
+    WOLFSSL_BIO_CB_PUTS   = 0x04,
+    WOLFSSL_BIO_CB_GETS   = 0x05,
+    WOLFSSL_BIO_CB_CTRL   = 0x06,
+    WOLFSSL_BIO_CB_RETURN = 0x80
+};
+
+typedef struct WOLFSSL_BUF_MEM {
+    char*  data;   /* dereferenced */
+    size_t length; /* current length */
+    size_t max;    /* maximum length */
+} WOLFSSL_BUF_MEM;
+
+/* custom method with user set callbacks */
+typedef int  (*wolfSSL_BIO_meth_write_cb)(WOLFSSL_BIO*, const char*, int);
+typedef int  (*wolfSSL_BIO_meth_read_cb)(WOLFSSL_BIO *, char *, int);
+typedef int  (*wolfSSL_BIO_meth_puts_cb)(WOLFSSL_BIO*, const char*);
+typedef int  (*wolfSSL_BIO_meth_gets_cb)(WOLFSSL_BIO*, char*, int);
+typedef long (*wolfSSL_BIO_meth_ctrl_get_cb)(WOLFSSL_BIO*, int, long, void*);
+typedef int  (*wolfSSL_BIO_meth_create_cb)(WOLFSSL_BIO*);
+typedef int  (*wolfSSL_BIO_meth_destroy_cb)(WOLFSSL_BIO*);
+
+typedef int wolfSSL_BIO_info_cb(WOLFSSL_BIO *, int, int);
+typedef long (*wolfssl_BIO_meth_ctrl_info_cb)(WOLFSSL_BIO*, int, wolfSSL_BIO_info_cb*);
+
+/* wolfSSL BIO_METHOD type */
+#ifndef MAX_BIO_METHOD_NAME
+#define MAX_BIO_METHOD_NAME 256
+#endif
+struct WOLFSSL_BIO_METHOD {
+    byte type;               /* method type */
+    char name[MAX_BIO_METHOD_NAME];
+    wolfSSL_BIO_meth_write_cb writeCb;
+    wolfSSL_BIO_meth_read_cb readCb;
+    wolfSSL_BIO_meth_puts_cb putsCb;
+    wolfSSL_BIO_meth_gets_cb getsCb;
+    wolfSSL_BIO_meth_ctrl_get_cb ctrlCb;
+    wolfSSL_BIO_meth_create_cb createCb;
+    wolfSSL_BIO_meth_destroy_cb freeCb;
+    wolfssl_BIO_meth_ctrl_info_cb ctrlInfoCb;
+};
+
+/* wolfSSL BIO type */
+typedef long (*wolf_bio_info_cb)(WOLFSSL_BIO *bio, int event, const char *parg,
+                                 int iarg, long larg, long return_value);
+
+struct WOLFSSL_BIO {
+    WOLFSSL_BUF_MEM* mem_buf;
+    WOLFSSL_BIO_METHOD* method;
+    WOLFSSL_BIO* prev;          /* previous in chain */
+    WOLFSSL_BIO* next;          /* next in chain */
+    WOLFSSL_BIO* pair;          /* BIO paired with */
+    void*        heap;          /* user heap hint */
+    void*        ptr;           /* WOLFSSL, file descriptor, MD, or mem buf */
+    void*        usrCtx;        /* user set pointer */
+    char*        infoArg;       /* BIO callback argument */
+    wolf_bio_info_cb infoCb;    /* BIO callback */
+    int          wrSz;          /* write buffer size (mem) */
+    int          wrIdx;         /* current index for write buffer */
+    int          rdIdx;         /* current read index */
+    int          readRq;        /* read request */
+    int          num;           /* socket num or length */
+    int          eof;           /* eof flag */
+    int          flags;
+    byte         type;          /* method type */
+    byte         init:1;        /* bio has been initialized */
+    byte         shutdown:1;    /* close flag */
+#ifdef HAVE_EX_DATA
+    WOLFSSL_CRYPTO_EX_DATA ex_data;
+#endif
+};
+
+typedef struct WOLFSSL_COMP_METHOD {
+    int type;            /* stunnel dereference */
+} WOLFSSL_COMP_METHOD;
+
+typedef struct WOLFSSL_COMP {
+    int id;
+    const char *name;
+    WOLFSSL_COMP_METHOD *method;
+} WOLFSSL_COMP;
+
+struct WOLFSSL_X509_LOOKUP_METHOD {
+    int type;
+};
+
+struct WOLFSSL_X509_LOOKUP {
+    WOLFSSL_X509_STORE *store;
+};
+
+struct WOLFSSL_X509_STORE {
+    int                   cache;          /* stunnel dereference */
+    WOLFSSL_CERT_MANAGER* cm;
+    WOLFSSL_X509_LOOKUP   lookup;
+#ifdef OPENSSL_EXTRA
+    int                   isDynamic;
+    WOLFSSL_X509_VERIFY_PARAM* param;    /* certificate validation parameter */
+#endif
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+    WOLFSSL_X509_STORE_CTX_verify_cb verify_cb;
+#endif
+#ifdef HAVE_EX_DATA
+    WOLFSSL_CRYPTO_EX_DATA ex_data;
+#endif
+#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL)
+    WOLFSSL_X509_CRL *crl;
+#endif
+};
+
+#ifdef OPENSSL_EXTRA
+#define WOLFSSL_USE_CHECK_TIME 0x2
+#define WOLFSSL_NO_CHECK_TIME  0x200000
+#define WOLFSSL_NO_WILDCARDS   0x4
+#define WOLFSSL_HOST_NAME_MAX  256
+#define WOLFSSL_MAX_IPSTR 46 /* max ip size IPv4 mapped IPv6 */
+struct WOLFSSL_X509_VERIFY_PARAM {
+    time_t         check_time;
+    unsigned long  flags;
+    char           hostName[WOLFSSL_HOST_NAME_MAX];
+    unsigned int  hostFlags;
+    char ipasc[WOLFSSL_MAX_IPSTR];
+};
+#endif
+
+typedef struct WOLFSSL_ALERT {
+    int code;
+    int level;
+} WOLFSSL_ALERT;
+
+typedef struct WOLFSSL_ALERT_HISTORY {
+    WOLFSSL_ALERT last_rx;
+    WOLFSSL_ALERT last_tx;
+} WOLFSSL_ALERT_HISTORY;
+
+typedef struct WOLFSSL_X509_REVOKED {
+    WOLFSSL_ASN1_INTEGER* serialNumber;          /* stunnel dereference */
+} WOLFSSL_X509_REVOKED;
+
+
+typedef struct WOLFSSL_X509_OBJECT {
+    union {
+        char* ptr;
+        WOLFSSL_X509 *x509;
+        WOLFSSL_X509_CRL* crl;           /* stunnel dereference */
+    } data;
+} WOLFSSL_X509_OBJECT;
+
+#define WOLFSSL_ASN1_BOOLEAN                int
+
+typedef struct WOLFSSL_BUFFER_INFO {
+    unsigned char* buffer;
+    unsigned int length;
+} WOLFSSL_BUFFER_INFO;
+
+struct WOLFSSL_X509_STORE_CTX {
+    WOLFSSL_X509_STORE* store;    /* Store full of a CA cert chain */
+    WOLFSSL_X509* current_cert;   /* current X509 (OPENSSL_EXTRA) */
+#ifdef WOLFSSL_ASIO
+    WOLFSSL_X509* current_issuer; /* asio dereference */
+#endif
+    WOLFSSL_X509_CHAIN* sesChain; /* pointer to WOLFSSL_SESSION peer chain */
+    WOLFSSL_STACK* chain;
+#ifdef OPENSSL_EXTRA
+    WOLFSSL_X509_VERIFY_PARAM* param; /* certificate validation parameter */
+#endif
+    char* domain;                /* subject CN domain name */
+#if defined(HAVE_EX_DATA) || defined(FORTRESS)
+    WOLFSSL_CRYPTO_EX_DATA ex_data;  /* external data */
+#endif
+#if defined(WOLFSSL_APACHE_HTTPD) || defined(OPENSSL_EXTRA)
+    int depth;                   /* used in X509_STORE_CTX_*_depth */
+#endif
+    void* userCtx;               /* user ctx */
+    int   error;                 /* current error */
+    int   error_depth;           /* index of cert depth for this error */
+    int   discardSessionCerts;   /* so verify callback can flag for discard */
+    int   totalCerts;            /* number of peer cert buffers */
+    WOLFSSL_BUFFER_INFO* certs;  /* peer certs */
+    WOLFSSL_X509_STORE_CTX_verify_cb verify_cb; /* verify callback */
+};
+
+typedef char* WOLFSSL_STRING;
+
+/* Valid Alert types from page 16/17
+ * Add alert string to the function wolfSSL_alert_type_string_long in src/ssl.c
+ */
+enum AlertDescription {
+    close_notify                    =   0,
+    unexpected_message              =  10,
+    bad_record_mac                  =  20,
+    record_overflow                 =  22,
+    decompression_failure           =  30,
+    handshake_failure               =  40,
+    no_certificate                  =  41,
+    bad_certificate                 =  42,
+    unsupported_certificate         =  43,
+    certificate_revoked             =  44,
+    certificate_expired             =  45,
+    certificate_unknown             =  46,
+    illegal_parameter               =  47,
+    unknown_ca                      =  48,
+    decode_error                    =  50,
+    decrypt_error                   =  51,
+    #ifdef WOLFSSL_MYSQL_COMPATIBLE
+    /* catch name conflict for enum protocol with MYSQL build */
+    wc_protocol_version             =  70,
+    #else
+    protocol_version                =  70,
+    #endif
+    inappropriate_fallback          =  86,
+    no_renegotiation                = 100,
+    missing_extension               = 109,
+    unsupported_extension           = 110, /**< RFC 5246, section 7.2.2 */
+    unrecognized_name               = 112, /**< RFC 6066, section 3 */
+    bad_certificate_status_response = 113, /**< RFC 6066, section 8 */
+    unknown_psk_identity            = 115, /**< RFC 4279, section 2 */
+    certificate_required            = 116, /**< RFC 8446, section 8.2 */
+    no_application_protocol         = 120
+};
+
+
+enum AlertLevel {
+    alert_warning = 1,
+    alert_fatal   = 2
+};
+
+/* Maximum master key length (SECRET_LEN) */
+#define WOLFSSL_MAX_MASTER_KEY_LENGTH 48
+/* Maximum number of groups that can be set */
+#define WOLFSSL_MAX_GROUP_COUNT       10
+
+#if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13)
+enum Tls13Secret {
+    CLIENT_EARLY_TRAFFIC_SECRET,
+    CLIENT_HANDSHAKE_TRAFFIC_SECRET,
+    SERVER_HANDSHAKE_TRAFFIC_SECRET,
+    CLIENT_TRAFFIC_SECRET,
+    SERVER_TRAFFIC_SECRET,
+    EARLY_EXPORTER_SECRET,
+    EXPORTER_SECRET
+};
+#endif
+
+
+typedef WOLFSSL_METHOD* (*wolfSSL_method_func)(void* heap);
+
+/* CTX Method EX Constructor Functions */
+WOLFSSL_API WOLFSSL_METHOD *wolfTLS_client_method_ex(void* heap);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLS_server_method_ex(void* heap);
+WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_method_ex(void* heap);
+WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_server_method_ex(void* heap);
+WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_client_method_ex(void* heap);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_method_ex(void* heap);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_server_method_ex(void* heap);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_client_method_ex(void* heap);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_method_ex(void* heap);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_server_method_ex(void* heap);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_client_method_ex(void* heap);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_method_ex(void* heap);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_server_method_ex(void* heap);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_client_method_ex(void* heap);
+#ifdef WOLFSSL_TLS13
+    WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_method_ex(void* heap);
+    WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_server_method_ex(void* heap);
+    WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_client_method_ex(void* heap);
+#endif
+
+WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_method_ex(void* heap);
+WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_server_method_ex(void* heap);
+WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_client_method_ex(void* heap);
+
+#ifdef WOLFSSL_DTLS
+    WOLFSSL_API WOLFSSL_METHOD *wolfDTLS_method_ex(void* heap);
+    WOLFSSL_API WOLFSSL_METHOD *wolfDTLS_client_method_ex(void* heap);
+    WOLFSSL_API WOLFSSL_METHOD *wolfDTLS_server_method_ex(void* heap);
+    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_method_ex(void* heap);
+    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_client_method_ex(void* heap);
+    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_server_method_ex(void* heap);
+    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_method_ex(void* heap);
+    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_client_method_ex(void* heap);
+    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_server_method_ex(void* heap);
+#endif
+
+/* CTX Method Constructor Functions */
+WOLFSSL_API WOLFSSL_METHOD *wolfTLS_client_method(void);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLS_server_method(void);
+WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_method(void);
+WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_method(void);
+WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_server_method(void);
+WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_client_method(void);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_method(void);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_server_method(void);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_client_method(void);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_method(void);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_server_method(void);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_client_method(void);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_method(void);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_server_method(void);
+WOLFSSL_ABI WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_client_method(void);
+#ifdef WOLFSSL_TLS13
+    WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_method(void);
+    WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_server_method(void);
+    WOLFSSL_ABI WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_client_method(void);
+#endif
+
+#ifdef WOLFSSL_DTLS
+    WOLFSSL_API WOLFSSL_METHOD *wolfDTLS_method(void);
+    WOLFSSL_API WOLFSSL_METHOD *wolfDTLS_server_method(void);
+    WOLFSSL_API WOLFSSL_METHOD *wolfDTLS_client_method(void);
+    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_method(void);
+    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_client_method(void);
+    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_server_method(void);
+    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_method(void);
+    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_client_method(void);
+    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_server_method(void);
+#endif
+
+#ifdef HAVE_POLY1305
+    WOLFSSL_API int wolfSSL_use_old_poly(WOLFSSL*, int);
+#endif
+
+#ifdef WOLFSSL_SESSION_EXPORT
+#ifdef WOLFSSL_DTLS
+
+#ifndef WOLFSSL_DTLS_EXPORT_TYPES
+typedef int (*wc_dtls_export)(WOLFSSL* ssl,
+                   unsigned char* exportBuffer, unsigned int sz, void* userCtx);
+#define WOLFSSL_DTLS_EXPORT_TYPES
+#endif /* WOLFSSL_DTLS_EXPORT_TYPES */
+
+WOLFSSL_API int wolfSSL_dtls_import(WOLFSSL* ssl, unsigned char* buf,
+                                                               unsigned int sz);
+WOLFSSL_API int wolfSSL_CTX_dtls_set_export(WOLFSSL_CTX* ctx,
+                                                           wc_dtls_export func);
+WOLFSSL_API int wolfSSL_dtls_set_export(WOLFSSL* ssl, wc_dtls_export func);
+WOLFSSL_API int wolfSSL_dtls_export(WOLFSSL* ssl, unsigned char* buf,
+                                                              unsigned int* sz);
+WOLFSSL_API int wolfSSL_dtls_export_state_only(WOLFSSL* ssl, unsigned char* buf,
+                                                              unsigned int* sz);
+#endif /* WOLFSSL_DTLS */
+#endif /* WOLFSSL_SESSION_EXPORT */
+
+#ifdef WOLFSSL_STATIC_MEMORY
+#ifndef WOLFSSL_MEM_GUARD
+#define WOLFSSL_MEM_GUARD
+    typedef struct WOLFSSL_MEM_STATS      WOLFSSL_MEM_STATS;
+    typedef struct WOLFSSL_MEM_CONN_STATS WOLFSSL_MEM_CONN_STATS;
+#endif
+WOLFSSL_API int wolfSSL_CTX_load_static_memory(WOLFSSL_CTX** ctx,
+                                            wolfSSL_method_func method,
+                                            unsigned char* buf, unsigned int sz,
+                                            int flag, int max);
+WOLFSSL_API int wolfSSL_CTX_is_static_memory(WOLFSSL_CTX* ctx,
+                                                 WOLFSSL_MEM_STATS* mem_stats);
+WOLFSSL_API int wolfSSL_is_static_memory(WOLFSSL* ssl,
+                                            WOLFSSL_MEM_CONN_STATS* mem_stats);
+#endif
+
+#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
+
+WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX*,
+                                                              const char*, int);
+WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX*,
+                                                              const char*, int);
+
+#endif
+
+#ifndef NO_CERTS
+#define WOLFSSL_LOAD_FLAG_NONE          0x00000000
+#define WOLFSSL_LOAD_FLAG_IGNORE_ERR    0x00000001
+#define WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY 0x00000002
+#define WOLFSSL_LOAD_FLAG_PEM_CA_ONLY   0x00000004
+
+#ifndef WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS
+#define WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS WOLFSSL_LOAD_FLAG_NONE
+#endif
+#endif /* !NO_CERTS */
+
+#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
+
+WOLFSSL_API int wolfSSL_CTX_load_verify_locations_ex(WOLFSSL_CTX*, const char*,
+                                                const char*, unsigned int);
+WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX*,
+                                                      const char*, const char*);
+#ifdef WOLFSSL_TRUST_PEER_CERT
+WOLFSSL_API int wolfSSL_CTX_trust_peer_cert(WOLFSSL_CTX*, const char*, int);
+#endif
+WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_file(
+                                                     WOLFSSL_CTX*, const char*);
+WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_file_format(WOLFSSL_CTX *,
+                                                  const char *file, int format);
+WOLFSSL_API int wolfSSL_CTX_use_RSAPrivateKey_file(WOLFSSL_CTX*, const char*, int);
+
+WOLFSSL_API long wolfSSL_get_verify_depth(WOLFSSL* ssl);
+WOLFSSL_API long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx);
+WOLFSSL_API void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx,int depth);
+WOLFSSL_ABI WOLFSSL_API int wolfSSL_use_certificate_file(WOLFSSL*, const char*,
+                                                                           int);
+WOLFSSL_ABI WOLFSSL_API int wolfSSL_use_PrivateKey_file(WOLFSSL*, const char*,
+                                                                           int);
+WOLFSSL_ABI WOLFSSL_API int wolfSSL_use_certificate_chain_file(WOLFSSL*,
+                                                                   const char*);
+WOLFSSL_API int wolfSSL_use_certificate_chain_file_format(WOLFSSL*,
+                                                  const char *file, int format);
+WOLFSSL_API int wolfSSL_use_RSAPrivateKey_file(WOLFSSL*, const char*, int);
+
+#ifdef WOLFSSL_DER_LOAD
+    WOLFSSL_API int wolfSSL_CTX_der_load_verify_locations(WOLFSSL_CTX*,
+                                                    const char*, int);
+#endif
+
+#ifdef HAVE_NTRU
+    WOLFSSL_API int wolfSSL_CTX_use_NTRUPrivateKey_file(WOLFSSL_CTX*, const char*);
+    /* load NTRU private key blob */
+#endif
+
+#endif /* !NO_FILESYSTEM && !NO_CERTS */
+
+WOLFSSL_API WOLFSSL_CTX* wolfSSL_CTX_new_ex(WOLFSSL_METHOD* method, void* heap);
+WOLFSSL_ABI WOLFSSL_API WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD*);
+#ifdef OPENSSL_EXTRA
+WOLFSSL_API int wolfSSL_CTX_up_ref(WOLFSSL_CTX*);
+#endif
+WOLFSSL_ABI WOLFSSL_API WOLFSSL* wolfSSL_new(WOLFSSL_CTX*);
+WOLFSSL_API WOLFSSL_CTX* wolfSSL_get_SSL_CTX(WOLFSSL* ssl);
+WOLFSSL_API WOLFSSL_X509_VERIFY_PARAM* wolfSSL_get0_param(WOLFSSL* ssl);
+WOLFSSL_API int  wolfSSL_is_server(WOLFSSL*);
+WOLFSSL_API WOLFSSL* wolfSSL_write_dup(WOLFSSL*);
+WOLFSSL_ABI WOLFSSL_API int  wolfSSL_set_fd (WOLFSSL*, int);
+WOLFSSL_API int  wolfSSL_set_write_fd (WOLFSSL*, int);
+WOLFSSL_API int  wolfSSL_set_read_fd (WOLFSSL*, int);
+WOLFSSL_API char* wolfSSL_get_cipher_list(int priority);
+WOLFSSL_API char* wolfSSL_get_cipher_list_ex(WOLFSSL* ssl, int priority);
+WOLFSSL_API int  wolfSSL_get_ciphers(char*, int);
+WOLFSSL_API int wolfSSL_get_ciphers_iana(char*, int);
+WOLFSSL_API const char* wolfSSL_get_cipher_name(WOLFSSL* ssl);
+WOLFSSL_API const char* wolfSSL_get_cipher_name_from_suite(const unsigned char,
+    const unsigned char);
+WOLFSSL_API const char* wolfSSL_get_cipher_name_iana_from_suite(
+    const unsigned char, const unsigned char);
+WOLFSSL_API const char* wolfSSL_get_shared_ciphers(WOLFSSL* ssl, char* buf,
+    int len);
+WOLFSSL_API const char* wolfSSL_get_curve_name(WOLFSSL* ssl);
+WOLFSSL_API int  wolfSSL_get_fd(const WOLFSSL*);
+/* please see note at top of README if you get an error from connect */
+WOLFSSL_ABI WOLFSSL_API int  wolfSSL_connect(WOLFSSL*);
+WOLFSSL_ABI WOLFSSL_API int  wolfSSL_write(WOLFSSL*, const void*, int);
+WOLFSSL_ABI WOLFSSL_API int  wolfSSL_read(WOLFSSL*, void*, int);
+WOLFSSL_API int  wolfSSL_peek(WOLFSSL*, void*, int);
+WOLFSSL_API int  wolfSSL_accept(WOLFSSL*);
+WOLFSSL_API int  wolfSSL_CTX_mutual_auth(WOLFSSL_CTX* ctx, int req);
+WOLFSSL_API int  wolfSSL_mutual_auth(WOLFSSL* ssl, int req);
+#ifdef WOLFSSL_TLS13
+WOLFSSL_API int  wolfSSL_send_hrr_cookie(WOLFSSL* ssl,
+    const unsigned char* secret, unsigned int secretSz);
+WOLFSSL_API int  wolfSSL_CTX_no_ticket_TLSv13(WOLFSSL_CTX* ctx);
+WOLFSSL_API int  wolfSSL_no_ticket_TLSv13(WOLFSSL* ssl);
+WOLFSSL_API int  wolfSSL_CTX_no_dhe_psk(WOLFSSL_CTX* ctx);
+WOLFSSL_API int  wolfSSL_no_dhe_psk(WOLFSSL* ssl);
+WOLFSSL_API int  wolfSSL_update_keys(WOLFSSL* ssl);
+WOLFSSL_API int  wolfSSL_CTX_allow_post_handshake_auth(WOLFSSL_CTX* ctx);
+WOLFSSL_API int  wolfSSL_allow_post_handshake_auth(WOLFSSL* ssl);
+WOLFSSL_API int  wolfSSL_request_certificate(WOLFSSL* ssl);
+
+WOLFSSL_API int  wolfSSL_CTX_set1_groups_list(WOLFSSL_CTX *ctx, char *list);
+WOLFSSL_API int  wolfSSL_set1_groups_list(WOLFSSL *ssl, char *list);
+
+WOLFSSL_API int  wolfSSL_preferred_group(WOLFSSL* ssl);
+WOLFSSL_API int  wolfSSL_CTX_set_groups(WOLFSSL_CTX* ctx, int* groups,
+                                        int count);
+WOLFSSL_API int  wolfSSL_set_groups(WOLFSSL* ssl, int* groups, int count);
+
+WOLFSSL_API int  wolfSSL_connect_TLSv13(WOLFSSL*);
+WOLFSSL_API int  wolfSSL_accept_TLSv13(WOLFSSL*);
+
+#ifdef WOLFSSL_EARLY_DATA
+WOLFSSL_API int  wolfSSL_CTX_set_max_early_data(WOLFSSL_CTX* ctx,
+                                                unsigned int sz);
+WOLFSSL_API int  wolfSSL_set_max_early_data(WOLFSSL* ssl, unsigned int sz);
+WOLFSSL_API int  wolfSSL_write_early_data(WOLFSSL*, const void*, int, int*);
+WOLFSSL_API int  wolfSSL_read_early_data(WOLFSSL*, void*, int, int*);
+#endif
+#endif
+WOLFSSL_ABI WOLFSSL_API void wolfSSL_CTX_free(WOLFSSL_CTX*);
+WOLFSSL_ABI WOLFSSL_API void wolfSSL_free(WOLFSSL*);
+WOLFSSL_ABI WOLFSSL_API int  wolfSSL_shutdown(WOLFSSL*);
+WOLFSSL_API int  wolfSSL_send(WOLFSSL*, const void*, int sz, int flags);
+WOLFSSL_API int  wolfSSL_recv(WOLFSSL*, void*, int sz, int flags);
+
+WOLFSSL_API void wolfSSL_CTX_set_quiet_shutdown(WOLFSSL_CTX*, int);
+WOLFSSL_API void wolfSSL_set_quiet_shutdown(WOLFSSL*, int);
+
+WOLFSSL_ABI WOLFSSL_API int  wolfSSL_get_error(WOLFSSL*, int);
+WOLFSSL_API int  wolfSSL_get_alert_history(WOLFSSL*, WOLFSSL_ALERT_HISTORY *);
+
+WOLFSSL_ABI WOLFSSL_API int  wolfSSL_set_session(WOLFSSL*, WOLFSSL_SESSION*);
+WOLFSSL_API long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION*, long);
+WOLFSSL_ABI WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL*);
+WOLFSSL_ABI WOLFSSL_API void wolfSSL_flush_sessions(WOLFSSL_CTX*, long);
+WOLFSSL_API int  wolfSSL_SetServerID(WOLFSSL*, const unsigned char*, int, int);
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || defined(WOLFSSL_HAPROXY) \
+    || defined(WOLFSSL_NGINX)
+WOLFSSL_API int  wolfSSL_BIO_new_bio_pair(WOLFSSL_BIO**, size_t,
+                     WOLFSSL_BIO**, size_t);
+
+WOLFSSL_API int wolfSSL_RSA_padding_add_PKCS1_PSS(WOLFSSL_RSA *rsa, unsigned char *EM,
+                                                  const unsigned char *mHash,
+                                                  const WOLFSSL_EVP_MD *Hash, int saltLen);
+WOLFSSL_API int wolfSSL_RSA_verify_PKCS1_PSS(WOLFSSL_RSA *rsa, const unsigned char *mHash,
+                                          const WOLFSSL_EVP_MD *hashAlg,
+                                          const unsigned char *EM, int saltLen);
+WOLFSSL_API WOLFSSL_RSA* wolfSSL_d2i_RSAPrivateKey_bio(WOLFSSL_BIO*, WOLFSSL_RSA**);
+WOLFSSL_API int wolfSSL_CTX_use_certificate_ASN1(WOLFSSL_CTX*,
+                                           int, const unsigned char*);
+WOLFSSL_API int wolfSSL_CTX_use_RSAPrivateKey(WOLFSSL_CTX*, WOLFSSL_RSA*);
+WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_bio(WOLFSSL_BIO*, WOLFSSL_EVP_PKEY**);
+#endif /* OPENSSL_ALL || WOLFSSL_ASIO */
+
+#ifdef SESSION_INDEX
+WOLFSSL_API int wolfSSL_GetSessionIndex(WOLFSSL* ssl);
+WOLFSSL_API int wolfSSL_GetSessionAtIndex(int index, WOLFSSL_SESSION* session);
+#endif /* SESSION_INDEX */
+
+#if defined(SESSION_CERTS)
+WOLFSSL_API
+    WOLFSSL_X509_CHAIN* wolfSSL_SESSION_get_peer_chain(WOLFSSL_SESSION* session);
+WOLFSSL_API WOLFSSL_X509* wolfSSL_SESSION_get0_peer(WOLFSSL_SESSION* session);
+#endif /* SESSION_INDEX && SESSION_CERTS */
+
+typedef int (*VerifyCallback)(int, WOLFSSL_X509_STORE_CTX*);
+typedef void (CallbackInfoState)(const WOLFSSL*, int, int);
+
+#if defined(HAVE_EX_DATA) || defined(FORTRESS)
+typedef int  (WOLFSSL_CRYPTO_EX_new)(void* p, void* ptr,
+        WOLFSSL_CRYPTO_EX_DATA* a, int idx, long argValue, void* arg);
+typedef int  (WOLFSSL_CRYPTO_EX_dup)(WOLFSSL_CRYPTO_EX_DATA* out,
+        WOLFSSL_CRYPTO_EX_DATA* in, void* inPtr, int idx, long argV, void* arg);
+typedef void (WOLFSSL_CRYPTO_EX_free)(void* p, void* ptr,
+        WOLFSSL_CRYPTO_EX_DATA* a, int idx, long argValue, void* arg);
+
+WOLFSSL_API int  wolfSSL_get_ex_new_index(long argValue, void* arg,
+        WOLFSSL_CRYPTO_EX_new* a, WOLFSSL_CRYPTO_EX_dup* b,
+        WOLFSSL_CRYPTO_EX_free* c);
+#endif
+
+WOLFSSL_API void wolfSSL_CTX_set_verify(WOLFSSL_CTX*, int,
+                                      VerifyCallback verify_callback);
+
+#ifdef OPENSSL_ALL
+typedef int (*CertVerifyCallback)(WOLFSSL_X509_STORE_CTX* store, void* arg);
+WOLFSSL_API void wolfSSL_CTX_set_cert_verify_callback(WOLFSSL_CTX* ctx,
+    CertVerifyCallback cb, void* arg);
+#endif
+
+WOLFSSL_API void wolfSSL_set_verify(WOLFSSL*, int, VerifyCallback verify_callback);
+WOLFSSL_API void wolfSSL_set_verify_result(WOLFSSL*, long);
+WOLFSSL_API void wolfSSL_SetCertCbCtx(WOLFSSL*, void*);
+
+WOLFSSL_ABI WOLFSSL_API int  wolfSSL_pending(WOLFSSL*);
+
+WOLFSSL_API void wolfSSL_load_error_strings(void);
+WOLFSSL_API int  wolfSSL_library_init(void);
+WOLFSSL_ABI WOLFSSL_API long wolfSSL_CTX_set_session_cache_mode(WOLFSSL_CTX*,
+                                                                          long);
+
+#ifdef HAVE_SECRET_CALLBACK
+typedef int (*SessionSecretCb)(WOLFSSL* ssl, void* secret, int* secretSz,
+                               void* ctx);
+WOLFSSL_API int  wolfSSL_set_session_secret_cb(WOLFSSL*, SessionSecretCb,
+                                               void*);
+#ifdef WOLFSSL_TLS13
+typedef int (*Tls13SecretCb)(WOLFSSL* ssl, int id, const unsigned char* secret,
+                             int secretSz, void* ctx);
+WOLFSSL_API int  wolfSSL_set_tls13_secret_cb(WOLFSSL*, Tls13SecretCb, void*);
+#endif
+#endif /* HAVE_SECRET_CALLBACK */
+
+/* session cache persistence */
+WOLFSSL_API int  wolfSSL_save_session_cache(const char*);
+WOLFSSL_API int  wolfSSL_restore_session_cache(const char*);
+WOLFSSL_API int  wolfSSL_memsave_session_cache(void*, int);
+WOLFSSL_API int  wolfSSL_memrestore_session_cache(const void*, int);
+WOLFSSL_API int  wolfSSL_get_session_cache_memsize(void);
+
+/* certificate cache persistence, uses ctx since certs are per ctx */
+WOLFSSL_API int  wolfSSL_CTX_save_cert_cache(WOLFSSL_CTX*, const char*);
+WOLFSSL_API int  wolfSSL_CTX_restore_cert_cache(WOLFSSL_CTX*, const char*);
+WOLFSSL_API int  wolfSSL_CTX_memsave_cert_cache(WOLFSSL_CTX*, void*, int, int*);
+WOLFSSL_API int  wolfSSL_CTX_memrestore_cert_cache(WOLFSSL_CTX*, const void*, int);
+WOLFSSL_API int  wolfSSL_CTX_get_cert_cache_memsize(WOLFSSL_CTX*);
+
+/* only supports full name from cipher_name[] delimited by : */
+WOLFSSL_API int  wolfSSL_CTX_set_cipher_list(WOLFSSL_CTX*, const char*);
+WOLFSSL_API int  wolfSSL_set_cipher_list(WOLFSSL*, const char*);
+
+/* Nonblocking DTLS helper functions */
+WOLFSSL_API void wolfSSL_dtls_set_using_nonblock(WOLFSSL*, int);
+WOLFSSL_API int  wolfSSL_dtls_get_using_nonblock(WOLFSSL*);
+#define wolfSSL_set_using_nonblock wolfSSL_dtls_set_using_nonblock
+#define wolfSSL_get_using_nonblock wolfSSL_dtls_get_using_nonblock
+    /* The old names are deprecated. */
+WOLFSSL_API int  wolfSSL_dtls_get_current_timeout(WOLFSSL* ssl);
+WOLFSSL_API int  wolfSSL_DTLSv1_get_timeout(WOLFSSL* ssl,
+        WOLFSSL_TIMEVAL* timeleft);
+WOLFSSL_API void wolfSSL_DTLSv1_set_initial_timeout_duration(WOLFSSL* ssl,
+    word32 duration_ms);
+WOLFSSL_API int  wolfSSL_DTLSv1_handle_timeout(WOLFSSL* ssl);
+
+WOLFSSL_API int  wolfSSL_dtls_set_timeout_init(WOLFSSL* ssl, int);
+WOLFSSL_API int  wolfSSL_dtls_set_timeout_max(WOLFSSL* ssl, int);
+WOLFSSL_API int  wolfSSL_dtls_got_timeout(WOLFSSL* ssl);
+WOLFSSL_API int  wolfSSL_dtls_retransmit(WOLFSSL*);
+WOLFSSL_API int  wolfSSL_dtls(WOLFSSL* ssl);
+
+WOLFSSL_API int  wolfSSL_dtls_set_peer(WOLFSSL*, void*, unsigned int);
+WOLFSSL_API int  wolfSSL_dtls_get_peer(WOLFSSL*, void*, unsigned int*);
+
+WOLFSSL_API int  wolfSSL_CTX_dtls_set_sctp(WOLFSSL_CTX*);
+WOLFSSL_API int  wolfSSL_dtls_set_sctp(WOLFSSL*);
+WOLFSSL_API int  wolfSSL_CTX_dtls_set_mtu(WOLFSSL_CTX*, unsigned short);
+WOLFSSL_API int  wolfSSL_dtls_set_mtu(WOLFSSL*, unsigned short);
+
+WOLFSSL_API int  wolfSSL_dtls_get_drop_stats(WOLFSSL*,
+                                             unsigned int*, unsigned int*);
+WOLFSSL_API int  wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX*, unsigned short);
+WOLFSSL_API int  wolfSSL_set_secret(WOLFSSL*, unsigned short,
+                     const unsigned char*, unsigned int,
+                     const unsigned char*, const unsigned char*,
+                     const unsigned char*);
+WOLFSSL_API int  wolfSSL_mcast_read(WOLFSSL*, unsigned short*, void*, int);
+WOLFSSL_API int  wolfSSL_mcast_peer_add(WOLFSSL*, unsigned short, int);
+WOLFSSL_API int  wolfSSL_mcast_peer_known(WOLFSSL*, unsigned short);
+WOLFSSL_API int  wolfSSL_mcast_get_max_peers(void);
+typedef int (*CallbackMcastHighwater)(unsigned short peerId,
+                                      unsigned int maxSeq,
+                                      unsigned int curSeq, void* ctx);
+WOLFSSL_API int  wolfSSL_CTX_mcast_set_highwater_cb(WOLFSSL_CTX*,
+                                                    unsigned int,
+                                                    unsigned int,
+                                                    unsigned int,
+                                                    CallbackMcastHighwater);
+WOLFSSL_API int  wolfSSL_mcast_set_highwater_ctx(WOLFSSL*, void*);
+
+WOLFSSL_API int   wolfSSL_ERR_GET_LIB(unsigned long err);
+WOLFSSL_API int   wolfSSL_ERR_GET_REASON(unsigned long err);
+WOLFSSL_API char* wolfSSL_ERR_error_string(unsigned long,char*);
+WOLFSSL_API void  wolfSSL_ERR_error_string_n(unsigned long e, char* buf,
+                                           unsigned long sz);
+WOLFSSL_API const char* wolfSSL_ERR_reason_error_string(unsigned long);
+
+/* extras */
+
+
+/* for now LHASH is not implemented */
+typedef int WOLFSSL_LHASH;
+#ifndef WOLF_LHASH_OF
+    #define WOLF_LHASH_OF(x) WOLFSSL_LHASH
+#endif
+
+#ifndef WOLF_STACK_OF
+    #define WOLF_STACK_OF(x) WOLFSSL_STACK
+#endif
+#ifndef DECLARE_STACK_OF
+    #define DECLARE_STACK_OF(x) WOLF_STACK_OF(x);
+#endif
+
+WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_new_node(void* heap);
+WOLFSSL_API void wolfSSL_sk_free(WOLFSSL_STACK* sk);
+WOLFSSL_API void wolfSSL_sk_free_node(WOLFSSL_STACK* in);
+WOLFSSL_API int wolfSSL_sk_push_node(WOLFSSL_STACK** stack, WOLFSSL_STACK* in);
+WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_get_node(WOLFSSL_STACK* sk, int idx);
+WOLFSSL_API int wolfSSL_sk_push(WOLFSSL_STACK *st, const void *data);
+
+#if defined(HAVE_OCSP)
+#include "wolfssl/ocsp.h"
+#include "wolfssl/wolfcrypt/asn.h"
+#endif
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+WOLFSSL_API int wolfSSL_sk_ACCESS_DESCRIPTION_push(
+                                       WOLF_STACK_OF(ACCESS_DESCRIPTION)* sk,
+                                       WOLFSSL_ACCESS_DESCRIPTION* access);
+#endif /* defined(OPENSSL_ALL) || defined(WOLFSSL_QT) */
+
+typedef WOLF_STACK_OF(WOLFSSL_GENERAL_NAME) WOLFSSL_GENERAL_NAMES;
+
+WOLFSSL_API int wolfSSL_sk_X509_push(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk,
+                                                            WOLFSSL_X509* x509);
+WOLFSSL_API WOLFSSL_X509* wolfSSL_sk_X509_pop(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk);
+WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_X509_dup(WOLFSSL_STACK* sk);
+WOLFSSL_API void wolfSSL_sk_X509_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk);
+WOLFSSL_API WOLFSSL_GENERAL_NAME* wolfSSL_GENERAL_NAME_new(void);
+WOLFSSL_API void wolfSSL_GENERAL_NAME_free(WOLFSSL_GENERAL_NAME* gn);
+WOLFSSL_API int wolfSSL_sk_GENERAL_NAME_push(WOLF_STACK_OF(WOLFSSL_GENERAL_NAME)* sk,
+                                                      WOLFSSL_GENERAL_NAME* gn);
+WOLFSSL_API WOLFSSL_GENERAL_NAME* wolfSSL_sk_GENERAL_NAME_value(
+        WOLFSSL_STACK* sk, int i);
+WOLFSSL_API int wolfSSL_sk_GENERAL_NAME_num(WOLFSSL_STACK* sk);
+WOLFSSL_API void wolfSSL_sk_GENERAL_NAME_pop_free(WOLFSSL_STACK* sk,
+                                       void (*f) (WOLFSSL_GENERAL_NAME*));
+WOLFSSL_API void wolfSSL_sk_GENERAL_NAME_free(WOLFSSL_STACK* sk);
+WOLFSSL_API void wolfSSL_GENERAL_NAMES_free(WOLFSSL_GENERAL_NAMES* name);
+WOLFSSL_API int wolfSSL_sk_ACCESS_DESCRIPTION_num(WOLFSSL_STACK* sk);
+WOLFSSL_API void wolfSSL_AUTHORITY_INFO_ACCESS_free(
+        WOLF_STACK_OF(WOLFSSL_ACCESS_DESCRIPTION)* sk);
+WOLFSSL_API WOLFSSL_ACCESS_DESCRIPTION* wolfSSL_sk_ACCESS_DESCRIPTION_value(
+        WOLFSSL_STACK* sk, int idx);
+WOLFSSL_API void wolfSSL_sk_ACCESS_DESCRIPTION_free(WOLFSSL_STACK* sk);
+WOLFSSL_API void wolfSSL_sk_ACCESS_DESCRIPTION_pop_free(WOLFSSL_STACK* sk,
+        void (*f) (WOLFSSL_ACCESS_DESCRIPTION*));
+WOLFSSL_API void wolfSSL_ACCESS_DESCRIPTION_free(WOLFSSL_ACCESS_DESCRIPTION* access);
+WOLFSSL_API void wolfSSL_sk_X509_EXTENSION_pop_free(
+        WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk,
+        void (*f) (WOLFSSL_X509_EXTENSION*));
+WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* wolfSSL_sk_X509_EXTENSION_new_null(void);
+WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_ASN1_OBJECT_new(void);
+WOLFSSL_API void wolfSSL_ASN1_OBJECT_free(WOLFSSL_ASN1_OBJECT* obj);
+WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_new_asn1_obj(void);
+WOLFSSL_API int wolfSSL_sk_ASN1_OBJECT_push(WOLF_STACK_OF(WOLFSSL_ASN1_OBJEXT)* sk,
+                                                      WOLFSSL_ASN1_OBJECT* obj);
+WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_sk_ASN1_OBJECT_pop(
+                                            WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk);
+WOLFSSL_API void wolfSSL_sk_ASN1_OBJECT_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk);
+WOLFSSL_API void wolfSSL_sk_ASN1_OBJECT_pop_free(
+                WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk,
+                void (*f)(WOLFSSL_ASN1_OBJECT*));
+WOLFSSL_API int wolfSSL_ASN1_STRING_to_UTF8(unsigned char **out, WOLFSSL_ASN1_STRING *in);
+WOLFSSL_API int wolfSSL_sk_X509_EXTENSION_num(WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk);
+WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_sk_X509_EXTENSION_value(
+                            WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk, int idx);
+WOLFSSL_API int  wolfSSL_set_ex_data(WOLFSSL*, int, void*);
+WOLFSSL_API int  wolfSSL_get_shutdown(const WOLFSSL*);
+WOLFSSL_API int  wolfSSL_set_rfd(WOLFSSL*, int);
+WOLFSSL_API int  wolfSSL_set_wfd(WOLFSSL*, int);
+WOLFSSL_API void wolfSSL_set_shutdown(WOLFSSL*, int);
+WOLFSSL_API int  wolfSSL_set_session_id_context(WOLFSSL*, const unsigned char*,
+                                           unsigned int);
+WOLFSSL_API void wolfSSL_set_connect_state(WOLFSSL*);
+WOLFSSL_API void wolfSSL_set_accept_state(WOLFSSL*);
+WOLFSSL_API int  wolfSSL_session_reused(WOLFSSL*);
+WOLFSSL_API WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session);
+WOLFSSL_API void wolfSSL_SESSION_free(WOLFSSL_SESSION* session);
+WOLFSSL_API int  wolfSSL_is_init_finished(WOLFSSL*);
+
+WOLFSSL_API const char*  wolfSSL_get_version(WOLFSSL*);
+WOLFSSL_API int  wolfSSL_get_current_cipher_suite(WOLFSSL* ssl);
+WOLFSSL_API WOLFSSL_CIPHER*  wolfSSL_get_current_cipher(WOLFSSL*);
+WOLFSSL_API char* wolfSSL_CIPHER_description(const WOLFSSL_CIPHER*, char*, int);
+WOLFSSL_API const char*  wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher);
+WOLFSSL_API const char*  wolfSSL_CIPHER_get_version(const WOLFSSL_CIPHER* cipher);
+WOLFSSL_API word32       wolfSSL_CIPHER_get_id(const WOLFSSL_CIPHER* cipher);
+WOLFSSL_API const WOLFSSL_CIPHER* wolfSSL_get_cipher_by_value(word16 value);
+WOLFSSL_API const char*  wolfSSL_SESSION_CIPHER_get_name(WOLFSSL_SESSION* session);
+WOLFSSL_API const char*  wolfSSL_get_cipher(WOLFSSL*);
+WOLFSSL_API void wolfSSL_sk_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk);
+WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl);
+                           /* what's ref count */
+
+WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_new(void);
+#if defined(OPENSSL_EXTRA_X509_SMALL) || defined(OPENSSL_ALL)
+WOLFSSL_API int wolfSSL_RSA_up_ref(WOLFSSL_RSA* rsa);
+WOLFSSL_API int wolfSSL_X509_up_ref(WOLFSSL_X509* x509);
+WOLFSSL_API int wolfSSL_EVP_PKEY_up_ref(WOLFSSL_EVP_PKEY* pkey);
+#endif
+
+WOLFSSL_API int wolfSSL_OCSP_parse_url(char* url, char** host, char** port,
+                                     char** path, int* ssl);
+
+WOLFSSL_API WOLFSSL_METHOD* wolfSSLv23_client_method(void);
+WOLFSSL_API WOLFSSL_METHOD* wolfSSLv2_client_method(void);
+WOLFSSL_API WOLFSSL_METHOD* wolfSSLv2_server_method(void);
+
+WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new(WOLFSSL_BIO_METHOD*);
+WOLFSSL_API int  wolfSSL_BIO_free(WOLFSSL_BIO*);
+WOLFSSL_API void wolfSSL_BIO_vfree(WOLFSSL_BIO*);
+WOLFSSL_API int  wolfSSL_BIO_free_all(WOLFSSL_BIO*);
+WOLFSSL_API int wolfSSL_BIO_gets(WOLFSSL_BIO* bio, char* buf, int sz);
+WOLFSSL_API int wolfSSL_BIO_puts(WOLFSSL_BIO* bio, const char* buf);
+WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_next(WOLFSSL_BIO* bio);
+WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_find_type(WOLFSSL_BIO* bio, int type);
+WOLFSSL_API int  wolfSSL_BIO_read(WOLFSSL_BIO*, void*, int);
+WOLFSSL_API int  wolfSSL_BIO_write(WOLFSSL_BIO*, const void*, int);
+WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_push(WOLFSSL_BIO*, WOLFSSL_BIO* append);
+WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_pop(WOLFSSL_BIO*);
+WOLFSSL_API int  wolfSSL_BIO_flush(WOLFSSL_BIO*);
+WOLFSSL_API int  wolfSSL_BIO_pending(WOLFSSL_BIO*);
+WOLFSSL_API void wolfSSL_BIO_set_callback(WOLFSSL_BIO *bio,
+                                          wolf_bio_info_cb callback_func);
+WOLFSSL_API wolf_bio_info_cb wolfSSL_BIO_get_callback(WOLFSSL_BIO *bio);
+WOLFSSL_API void  wolfSSL_BIO_set_callback_arg(WOLFSSL_BIO *bio, char *arg);
+WOLFSSL_API char* wolfSSL_BIO_get_callback_arg(const WOLFSSL_BIO *bio);
+
+WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_md(void);
+WOLFSSL_API int wolfSSL_BIO_get_md_ctx(WOLFSSL_BIO *bio,
+                                                WOLFSSL_EVP_MD_CTX **mdcp);
+
+WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_buffer(void);
+WOLFSSL_API long wolfSSL_BIO_set_write_buffer_size(WOLFSSL_BIO*, long size);
+WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_ssl(void);
+WOLFSSL_API WOLFSSL_BIO*        wolfSSL_BIO_new_socket(int sfd, int flag);
+WOLFSSL_API int         wolfSSL_BIO_eof(WOLFSSL_BIO*);
+
+WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_mem(void);
+WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_base64(void);
+WOLFSSL_API void wolfSSL_BIO_set_flags(WOLFSSL_BIO*, int);
+WOLFSSL_API void wolfSSL_BIO_clear_flags(WOLFSSL_BIO *bio, int flags);
+WOLFSSL_API int wolfSSL_BIO_set_ex_data(WOLFSSL_BIO *bio, int idx, void *data);
+WOLFSSL_API void *wolfSSL_BIO_get_ex_data(WOLFSSL_BIO *bio, int idx);
+WOLFSSL_API long wolfSSL_BIO_set_nbio(WOLFSSL_BIO*, long);
+
+WOLFSSL_API int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio,void* p);
+
+WOLFSSL_API void wolfSSL_BIO_set_init(WOLFSSL_BIO*, int);
+WOLFSSL_API void wolfSSL_BIO_set_data(WOLFSSL_BIO*, void*);
+WOLFSSL_API void* wolfSSL_BIO_get_data(WOLFSSL_BIO*);
+WOLFSSL_API void wolfSSL_BIO_set_shutdown(WOLFSSL_BIO*, int);
+WOLFSSL_API int wolfSSL_BIO_get_shutdown(WOLFSSL_BIO*);
+WOLFSSL_API void wolfSSL_BIO_clear_retry_flags(WOLFSSL_BIO*);
+WOLFSSL_API int wolfSSL_BIO_should_retry(WOLFSSL_BIO *bio);
+
+WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_meth_new(int, const char*);
+WOLFSSL_API void wolfSSL_BIO_meth_free(WOLFSSL_BIO_METHOD*);
+WOLFSSL_API int wolfSSL_BIO_meth_set_write(WOLFSSL_BIO_METHOD*, wolfSSL_BIO_meth_write_cb);
+WOLFSSL_API int wolfSSL_BIO_meth_set_read(WOLFSSL_BIO_METHOD*, wolfSSL_BIO_meth_read_cb);
+WOLFSSL_API int wolfSSL_BIO_meth_set_puts(WOLFSSL_BIO_METHOD*, wolfSSL_BIO_meth_puts_cb);
+WOLFSSL_API int wolfSSL_BIO_meth_set_gets(WOLFSSL_BIO_METHOD*, wolfSSL_BIO_meth_gets_cb);
+WOLFSSL_API int wolfSSL_BIO_meth_set_ctrl(WOLFSSL_BIO_METHOD*, wolfSSL_BIO_meth_ctrl_get_cb);
+WOLFSSL_API int wolfSSL_BIO_meth_set_create(WOLFSSL_BIO_METHOD*, wolfSSL_BIO_meth_create_cb);
+WOLFSSL_API int wolfSSL_BIO_meth_set_destroy(WOLFSSL_BIO_METHOD*, wolfSSL_BIO_meth_destroy_cb);
+WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new_mem_buf(const void* buf, int len);
+
+WOLFSSL_API long wolfSSL_BIO_set_ssl(WOLFSSL_BIO*, WOLFSSL*, int flag);
+#ifndef NO_FILESYSTEM
+WOLFSSL_API long wolfSSL_BIO_set_fd(WOLFSSL_BIO* b, int fd, int flag);
+#endif
+WOLFSSL_API int wolfSSL_BIO_set_close(WOLFSSL_BIO *b, long flag);
+WOLFSSL_API void wolfSSL_set_bio(WOLFSSL*, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr);
+
+#ifndef NO_FILESYSTEM
+WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_file(void);
+#endif
+
+WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_bio(void);
+WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_socket(void);
+
+WOLFSSL_API long wolfSSL_BIO_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, void *parg);
+WOLFSSL_API long wolfSSL_BIO_int_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, int iarg);
+
+WOLFSSL_API int  wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *b, long size);
+WOLFSSL_API int  wolfSSL_BIO_make_bio_pair(WOLFSSL_BIO *b1, WOLFSSL_BIO *b2);
+WOLFSSL_API int  wolfSSL_BIO_ctrl_reset_read_request(WOLFSSL_BIO *b);
+WOLFSSL_API int  wolfSSL_BIO_nread0(WOLFSSL_BIO *bio, char **buf);
+WOLFSSL_API int  wolfSSL_BIO_nread(WOLFSSL_BIO *bio, char **buf, int num);
+WOLFSSL_API int  wolfSSL_BIO_nwrite(WOLFSSL_BIO *bio, char **buf, int num);
+WOLFSSL_API int  wolfSSL_BIO_reset(WOLFSSL_BIO *bio);
+
+WOLFSSL_API int  wolfSSL_BIO_seek(WOLFSSL_BIO *bio, int ofs);
+WOLFSSL_API int  wolfSSL_BIO_write_filename(WOLFSSL_BIO *bio, char *name);
+WOLFSSL_API long wolfSSL_BIO_set_mem_eof_return(WOLFSSL_BIO *bio, int v);
+WOLFSSL_API long wolfSSL_BIO_get_mem_ptr(WOLFSSL_BIO *bio, WOLFSSL_BUF_MEM **m);
+WOLFSSL_API int wolfSSL_BIO_get_len(WOLFSSL_BIO *bio);
+
+WOLFSSL_API void        wolfSSL_RAND_screen(void);
+WOLFSSL_API const char* wolfSSL_RAND_file_name(char*, unsigned long);
+WOLFSSL_API int         wolfSSL_RAND_write_file(const char*);
+WOLFSSL_API int         wolfSSL_RAND_load_file(const char*, long);
+WOLFSSL_API int         wolfSSL_RAND_egd(const char*);
+WOLFSSL_API int         wolfSSL_RAND_seed(const void*, int);
+WOLFSSL_API void        wolfSSL_RAND_Cleanup(void);
+WOLFSSL_API void        wolfSSL_RAND_add(const void*, int, double);
+WOLFSSL_API int         wolfSSL_RAND_poll(void);
+
+WOLFSSL_API WOLFSSL_COMP_METHOD* wolfSSL_COMP_zlib(void);
+WOLFSSL_API WOLFSSL_COMP_METHOD* wolfSSL_COMP_rle(void);
+WOLFSSL_API int wolfSSL_COMP_add_compression_method(int, void*);
+
+WOLFSSL_API unsigned long wolfSSL_thread_id(void);
+WOLFSSL_API void wolfSSL_set_id_callback(unsigned long (*f)(void));
+WOLFSSL_API void wolfSSL_set_locking_callback(void (*f)(int, int, const char*,
+                                                      int));
+WOLFSSL_API void wolfSSL_set_dynlock_create_callback(WOLFSSL_dynlock_value* (*f)
+                                                   (const char*, int));
+WOLFSSL_API void wolfSSL_set_dynlock_lock_callback(void (*f)(int,
+                                      WOLFSSL_dynlock_value*, const char*, int));
+WOLFSSL_API void wolfSSL_set_dynlock_destroy_callback(void (*f)
+                                     (WOLFSSL_dynlock_value*, const char*, int));
+WOLFSSL_API int  wolfSSL_num_locks(void);
+
+WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get_current_cert(
+                                                        WOLFSSL_X509_STORE_CTX*);
+WOLFSSL_API int   wolfSSL_X509_STORE_CTX_get_error(WOLFSSL_X509_STORE_CTX*);
+WOLFSSL_API int   wolfSSL_X509_STORE_CTX_get_error_depth(WOLFSSL_X509_STORE_CTX*);
+
+WOLFSSL_API void  wolfSSL_X509_STORE_CTX_set_verify_cb(WOLFSSL_X509_STORE_CTX *ctx,
+                                  WOLFSSL_X509_STORE_CTX_verify_cb verify_cb);
+WOLFSSL_API void wolfSSL_X509_STORE_set_verify_cb(WOLFSSL_X509_STORE *st,
+                                 WOLFSSL_X509_STORE_CTX_verify_cb verify_cb);
+WOLFSSL_API int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* n,
+                                                           unsigned char** out);
+#ifndef NO_RSA
+WOLFSSL_API int wolfSSL_RSA_print(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa, int offset);
+#endif
+WOLFSSL_API int wolfSSL_X509_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509* x509,
+    unsigned long nmflags, unsigned long cflag);
+WOLFSSL_API int wolfSSL_X509_print(WOLFSSL_BIO* bio, WOLFSSL_X509* x509);
+WOLFSSL_ABI WOLFSSL_API char* wolfSSL_X509_NAME_oneline(WOLFSSL_X509_NAME*,
+                                                                    char*, int);
+#if defined(OPENSSL_EXTRA) && defined(XSNPRINTF)
+WOLFSSL_API char* wolfSSL_X509_get_name_oneline(WOLFSSL_X509_NAME*, char*, int);
+#endif
+WOLFSSL_ABI WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_X509_get_issuer_name(
+                                                                 WOLFSSL_X509*);
+WOLFSSL_ABI WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_X509_get_subject_name(
+                                                                 WOLFSSL_X509*);
+WOLFSSL_API int  wolfSSL_X509_ext_isSet_by_NID(WOLFSSL_X509*, int);
+WOLFSSL_API int  wolfSSL_X509_ext_get_critical_by_NID(WOLFSSL_X509*, int);
+WOLFSSL_API int  wolfSSL_X509_get_isCA(WOLFSSL_X509*);
+WOLFSSL_API int  wolfSSL_X509_get_isSet_pathLength(WOLFSSL_X509*);
+WOLFSSL_API unsigned int wolfSSL_X509_get_pathLength(WOLFSSL_X509*);
+WOLFSSL_API unsigned int wolfSSL_X509_get_keyUsage(WOLFSSL_X509*);
+WOLFSSL_API unsigned char* wolfSSL_X509_get_authorityKeyID(
+                                            WOLFSSL_X509*, unsigned char*, int*);
+WOLFSSL_API unsigned char* wolfSSL_X509_get_subjectKeyID(
+                                            WOLFSSL_X509*, unsigned char*, int*);
+
+WOLFSSL_API int wolfSSL_X509_verify(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey);
+WOLFSSL_API int wolfSSL_X509_set_subject_name(WOLFSSL_X509*,
+                                              WOLFSSL_X509_NAME*);
+WOLFSSL_API int wolfSSL_X509_set_issuer_name(WOLFSSL_X509*,
+                                              WOLFSSL_X509_NAME*);
+WOLFSSL_API int wolfSSL_X509_set_pubkey(WOLFSSL_X509*, WOLFSSL_EVP_PKEY*);
+WOLFSSL_API int wolfSSL_X509_set_notAfter(WOLFSSL_X509* x509,
+        const WOLFSSL_ASN1_TIME* t);
+WOLFSSL_API int wolfSSL_X509_set_notBefore(WOLFSSL_X509* x509,
+        const WOLFSSL_ASN1_TIME* t);
+WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_X509_get_notBefore(const WOLFSSL_X509* x509);
+WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_X509_get_notAfter(const WOLFSSL_X509* x509);
+WOLFSSL_API int wolfSSL_X509_set_serialNumber(WOLFSSL_X509* x509,
+        WOLFSSL_ASN1_INTEGER* s);
+WOLFSSL_API int wolfSSL_X509_set_version(WOLFSSL_X509* x509, long v);
+WOLFSSL_API int wolfSSL_X509_sign(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey,
+        const WOLFSSL_EVP_MD* md);
+
+
+WOLFSSL_API int wolfSSL_X509_NAME_entry_count(WOLFSSL_X509_NAME*);
+WOLFSSL_API int wolfSSL_X509_NAME_get_text_by_NID(
+                                            WOLFSSL_X509_NAME*, int, char*, int);
+WOLFSSL_API int wolfSSL_X509_NAME_get_index_by_NID(
+                                           WOLFSSL_X509_NAME*, int, int);
+WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_X509_NAME_ENTRY_get_data(WOLFSSL_X509_NAME_ENTRY*);
+
+WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_new(void);
+WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_type_new(int type);
+WOLFSSL_API int wolfSSL_ASN1_STRING_type(const WOLFSSL_ASN1_STRING* asn1);
+WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_d2i_DISPLAYTEXT(WOLFSSL_ASN1_STRING **asn, const unsigned char **in, long len);
+WOLFSSL_API void wolfSSL_ASN1_STRING_free(WOLFSSL_ASN1_STRING* asn1);
+WOLFSSL_API int wolfSSL_ASN1_STRING_set(WOLFSSL_ASN1_STRING* asn1,
+                                                  const void* data, int dataSz);
+WOLFSSL_API unsigned char* wolfSSL_ASN1_STRING_data(WOLFSSL_ASN1_STRING*);
+WOLFSSL_API int wolfSSL_ASN1_STRING_length(WOLFSSL_ASN1_STRING*);
+WOLFSSL_API int         wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX*);
+WOLFSSL_API const char* wolfSSL_X509_verify_cert_error_string(long);
+WOLFSSL_API int wolfSSL_X509_get_signature_type(WOLFSSL_X509*);
+WOLFSSL_API int wolfSSL_X509_get_signature(WOLFSSL_X509*, unsigned char*, int*);
+WOLFSSL_API int wolfSSL_X509_get_pubkey_buffer(WOLFSSL_X509*, unsigned char*,
+        int*);
+WOLFSSL_API int wolfSSL_X509_get_pubkey_type(WOLFSSL_X509* x509);
+
+WOLFSSL_API int wolfSSL_X509_LOOKUP_add_dir(WOLFSSL_X509_LOOKUP*,const char*,long);
+WOLFSSL_API int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP*, const char*,
+                                            long);
+WOLFSSL_API WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_hash_dir(void);
+WOLFSSL_API WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_file(void);
+
+WOLFSSL_API WOLFSSL_X509_LOOKUP* wolfSSL_X509_STORE_add_lookup(WOLFSSL_X509_STORE*,
+                                                    WOLFSSL_X509_LOOKUP_METHOD*);
+WOLFSSL_API WOLFSSL_X509_STORE*  wolfSSL_X509_STORE_new(void);
+WOLFSSL_API void         wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE*);
+WOLFSSL_API int          wolfSSL_X509_STORE_add_cert(
+                                              WOLFSSL_X509_STORE*, WOLFSSL_X509*);
+WOLFSSL_API WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get_chain(
+                                                   WOLFSSL_X509_STORE_CTX* ctx);
+WOLFSSL_API WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get1_chain(
+                                                   WOLFSSL_X509_STORE_CTX* ctx);
+WOLFSSL_API int wolfSSL_X509_STORE_set_flags(WOLFSSL_X509_STORE* store,
+                                                            unsigned long flag);
+WOLFSSL_API int          wolfSSL_X509_STORE_set_default_paths(WOLFSSL_X509_STORE*);
+WOLFSSL_API int          wolfSSL_X509_STORE_get_by_subject(WOLFSSL_X509_STORE_CTX*,
+                                   int, WOLFSSL_X509_NAME*, WOLFSSL_X509_OBJECT*);
+WOLFSSL_API WOLFSSL_X509_STORE_CTX* wolfSSL_X509_STORE_CTX_new(void);
+WOLFSSL_API int  wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX*,
+                      WOLFSSL_X509_STORE*, WOLFSSL_X509*, WOLF_STACK_OF(WOLFSSL_X509)*);
+WOLFSSL_API void wolfSSL_X509_STORE_CTX_free(WOLFSSL_X509_STORE_CTX*);
+WOLFSSL_API void wolfSSL_X509_STORE_CTX_cleanup(WOLFSSL_X509_STORE_CTX*);
+
+WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_lastUpdate(WOLFSSL_X509_CRL*);
+WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_nextUpdate(WOLFSSL_X509_CRL*);
+WOLFSSL_ASN1_TIME* wolfSSL_X509_gmtime_adj(WOLFSSL_ASN1_TIME *s, long adj);
+
+WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_X509_get_pubkey(WOLFSSL_X509*);
+WOLFSSL_API int       wolfSSL_X509_CRL_verify(WOLFSSL_X509_CRL*, WOLFSSL_EVP_PKEY*);
+WOLFSSL_API void      wolfSSL_X509_OBJECT_free_contents(WOLFSSL_X509_OBJECT*);
+WOLFSSL_API WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY_bio(
+        WOLFSSL_BIO* bio, WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey);
+WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio,
+                                         WOLFSSL_EVP_PKEY** out);
+WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY(WOLFSSL_EVP_PKEY** key,
+        const unsigned char** in, long inSz);
+WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type,
+        WOLFSSL_EVP_PKEY** out, const unsigned char **in, long inSz);
+WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_EVP(WOLFSSL_EVP_PKEY** key,
+        unsigned char** in, long inSz);
+WOLFSSL_API int wolfSSL_i2d_PrivateKey(WOLFSSL_EVP_PKEY* key,
+        unsigned char** der);
+WOLFSSL_API int       wolfSSL_X509_cmp_current_time(const WOLFSSL_ASN1_TIME*);
+#ifdef OPENSSL_EXTRA
+WOLFSSL_API int wolfSSL_X509_cmp_time(const WOLFSSL_ASN1_TIME* asnTime,
+        time_t *cmpTime);
+WOLFSSL_API WOLFSSL_ASN1_TIME *wolfSSL_X509_time_adj_ex(WOLFSSL_ASN1_TIME *asnTime,
+    int offset_day, long offset_sec, time_t *in_tm);
+WOLFSSL_API WOLFSSL_ASN1_TIME *wolfSSL_X509_time_adj(WOLFSSL_ASN1_TIME *asnTime,
+    long offset_sec, time_t *in_tm);
+WOLFSSL_API int       wolfSSL_sk_X509_REVOKED_num(WOLFSSL_X509_REVOKED*);
+WOLFSSL_API void      wolfSSL_X509_STORE_CTX_set_time(WOLFSSL_X509_STORE_CTX*,
+                                                      unsigned long flags,
+                                                      time_t t);
+WOLFSSL_API void wolfSSL_X509_VERIFY_PARAM_set_hostflags(
+                WOLFSSL_X509_VERIFY_PARAM* param, unsigned int flags);
+WOLFSSL_API int wolfSSL_X509_VERIFY_PARAM_set1_host(WOLFSSL_X509_VERIFY_PARAM* pParam,
+                                                    const char* name,
+                                                    unsigned int nameSz);
+WOLFSSL_API int wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(
+        WOLFSSL_X509_VERIFY_PARAM *param, const char *ipasc);
+#endif
+WOLFSSL_API WOLFSSL_X509_REVOKED* wolfSSL_X509_CRL_get_REVOKED(WOLFSSL_X509_CRL*);
+WOLFSSL_API WOLFSSL_X509_REVOKED* wolfSSL_sk_X509_REVOKED_value(
+                                                      WOLFSSL_X509_REVOKED*,int);
+WOLFSSL_API WOLFSSL_ASN1_INTEGER* wolfSSL_X509_get_serialNumber(WOLFSSL_X509*);
+WOLFSSL_API void wolfSSL_ASN1_INTEGER_free(WOLFSSL_ASN1_INTEGER*);
+WOLFSSL_API WOLFSSL_ASN1_INTEGER* wolfSSL_ASN1_INTEGER_new(void);
+WOLFSSL_API WOLFSSL_ASN1_INTEGER* wolfSSL_ASN1_INTEGER_dup(
+                                              const WOLFSSL_ASN1_INTEGER* src);
+WOLFSSL_API int wolfSSL_ASN1_INTEGER_set(WOLFSSL_ASN1_INTEGER *a, long v);
+
+WOLFSSL_API int wolfSSL_ASN1_TIME_print(WOLFSSL_BIO*, const WOLFSSL_ASN1_TIME*);
+
+WOLFSSL_API char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* t,
+                                                            char* buf, int len);
+WOLFSSL_API int  wolfSSL_ASN1_INTEGER_cmp(const WOLFSSL_ASN1_INTEGER*,
+                                       const WOLFSSL_ASN1_INTEGER*);
+WOLFSSL_API long wolfSSL_ASN1_INTEGER_get(const WOLFSSL_ASN1_INTEGER*);
+
+#ifdef OPENSSL_EXTRA
+WOLFSSL_API WOLFSSL_BIGNUM *wolfSSL_ASN1_INTEGER_to_BN(const WOLFSSL_ASN1_INTEGER *ai,
+                                       WOLFSSL_BIGNUM *bn);
+WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_adj(WOLFSSL_ASN1_TIME*, time_t,
+                                                     int, long);
+WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_new(void);
+WOLFSSL_API void wolfSSL_ASN1_TIME_free(WOLFSSL_ASN1_TIME* t);
+#endif
+
+WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char*);
+WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_CTX_get_client_CA_list(
+        const WOLFSSL_CTX *s);
+/* deprecated function name */
+#define wolfSSL_SSL_CTX_get_client_CA_list wolfSSL_CTX_get_client_CA_list
+
+WOLFSSL_API void  wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX*,
+                                               WOLF_STACK_OF(WOLFSSL_X509_NAME)*);
+WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get_client_CA_list(
+            const WOLFSSL* ssl);
+
+typedef int (*client_cert_cb)(WOLFSSL *ssl, WOLFSSL_X509 **x509,
+                              WOLFSSL_EVP_PKEY **pkey);
+WOLFSSL_API void wolfSSL_CTX_set_client_cert_cb(WOLFSSL_CTX *ctx, client_cert_cb);
+
+WOLFSSL_API void* wolfSSL_X509_STORE_CTX_get_ex_data(
+        WOLFSSL_X509_STORE_CTX* ctx, int idx);
+WOLFSSL_API int  wolfSSL_X509_STORE_CTX_set_ex_data(WOLFSSL_X509_STORE_CTX* ctx,
+        int idx, void *data);
+WOLFSSL_API void wolfSSL_X509_STORE_CTX_set_depth(WOLFSSL_X509_STORE_CTX* ctx,
+        int depth);
+WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get0_current_issuer(
+        WOLFSSL_X509_STORE_CTX* ctx);
+WOLFSSL_API WOLFSSL_X509_STORE* wolfSSL_X509_STORE_CTX_get0_store(
+        WOLFSSL_X509_STORE_CTX* ctx);
+WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get0_cert(
+        WOLFSSL_X509_STORE_CTX*);
+WOLFSSL_API int  wolfSSL_get_ex_data_X509_STORE_CTX_idx(void);
+WOLFSSL_API void wolfSSL_X509_STORE_CTX_set_error(
+                                           WOLFSSL_X509_STORE_CTX* ctx, int er);
+void wolfSSL_X509_STORE_CTX_set_error_depth(WOLFSSL_X509_STORE_CTX* ctx,
+                                                                     int depth);
+WOLFSSL_API void* wolfSSL_get_ex_data(const WOLFSSL*, int);
+
+WOLFSSL_API void wolfSSL_CTX_set_default_passwd_cb_userdata(WOLFSSL_CTX*,
+                                                          void* userdata);
+WOLFSSL_API void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX*,
+                                                   pem_password_cb*);
+WOLFSSL_API pem_password_cb* wolfSSL_CTX_get_default_passwd_cb(WOLFSSL_CTX *ctx);
+WOLFSSL_API void *wolfSSL_CTX_get_default_passwd_cb_userdata(WOLFSSL_CTX *ctx);
+
+WOLFSSL_API void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX*,
+                          void (*)(const WOLFSSL* ssl, int type, int val));
+
+WOLFSSL_API unsigned long wolfSSL_ERR_peek_error(void);
+WOLFSSL_API int           wolfSSL_GET_REASON(int);
+
+WOLFSSL_API const char* wolfSSL_alert_type_string_long(int);
+WOLFSSL_API const char* wolfSSL_alert_desc_string_long(int);
+WOLFSSL_API const char* wolfSSL_state_string_long(const WOLFSSL*);
+
+WOLFSSL_API WOLFSSL_RSA* wolfSSL_RSA_generate_key(int, unsigned long,
+                                               void(*)(int, int, void*), void*);
+WOLFSSL_API WOLFSSL_RSA *wolfSSL_d2i_RSAPublicKey(WOLFSSL_RSA **r,
+                                            const unsigned char **pp, long len);
+WOLFSSL_API WOLFSSL_RSA *wolfSSL_d2i_RSAPrivateKey(WOLFSSL_RSA**,
+                                            const unsigned char**, long);
+WOLFSSL_API int wolfSSL_i2d_RSAPublicKey(WOLFSSL_RSA *r, const unsigned char **pp);
+WOLFSSL_API int wolfSSL_i2d_RSAPrivateKey(WOLFSSL_RSA *r, unsigned char **pp);
+WOLFSSL_API void wolfSSL_CTX_set_tmp_rsa_callback(WOLFSSL_CTX *,
+                                           WOLFSSL_RSA *(*)(WOLFSSL *, int, int));
+
+WOLFSSL_API int wolfSSL_PEM_def_callback(char*, int num, int w, void* key);
+
+WOLFSSL_API long wolfSSL_CTX_sess_accept(WOLFSSL_CTX*);
+WOLFSSL_API long wolfSSL_CTX_sess_connect(WOLFSSL_CTX*);
+WOLFSSL_API long wolfSSL_CTX_sess_accept_good(WOLFSSL_CTX*);
+WOLFSSL_API long wolfSSL_CTX_sess_connect_good(WOLFSSL_CTX*);
+WOLFSSL_API long wolfSSL_CTX_sess_accept_renegotiate(WOLFSSL_CTX*);
+WOLFSSL_API long wolfSSL_CTX_sess_connect_renegotiate(WOLFSSL_CTX*);
+WOLFSSL_API long wolfSSL_CTX_sess_hits(WOLFSSL_CTX*);
+WOLFSSL_API long wolfSSL_CTX_sess_cb_hits(WOLFSSL_CTX*);
+WOLFSSL_API long wolfSSL_CTX_sess_cache_full(WOLFSSL_CTX*);
+WOLFSSL_API long wolfSSL_CTX_sess_misses(WOLFSSL_CTX*);
+WOLFSSL_API long wolfSSL_CTX_sess_timeouts(WOLFSSL_CTX*);
+WOLFSSL_API long wolfSSL_CTX_sess_number(WOLFSSL_CTX*);
+
+WOLFSSL_API long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX*, WOLFSSL_X509*);
+WOLFSSL_API long wolfSSL_CTX_sess_set_cache_size(WOLFSSL_CTX*, long);
+WOLFSSL_API long wolfSSL_CTX_sess_get_cache_size(WOLFSSL_CTX*);
+
+WOLFSSL_API long wolfSSL_CTX_get_session_cache_mode(WOLFSSL_CTX*);
+WOLFSSL_API int  wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX*);
+WOLFSSL_API int  wolfSSL_CTX_set_read_ahead(WOLFSSL_CTX*, int v);
+WOLFSSL_API long wolfSSL_CTX_set_tlsext_status_arg(WOLFSSL_CTX*, void* arg);
+WOLFSSL_API long wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg(
+        WOLFSSL_CTX*, void* arg);
+WOLFSSL_API int  wolfSSL_CTX_add_client_CA(WOLFSSL_CTX*, WOLFSSL_X509*);
+WOLFSSL_API int  wolfSSL_CTX_set_srp_password(WOLFSSL_CTX*, char*);
+WOLFSSL_API int  wolfSSL_CTX_set_srp_username(WOLFSSL_CTX*, char*);
+
+WOLFSSL_API long wolfSSL_set_options(WOLFSSL *s, long op);
+WOLFSSL_API long wolfSSL_get_options(const WOLFSSL *s);
+WOLFSSL_API long wolfSSL_clear_options(WOLFSSL *s,  long op);
+WOLFSSL_API long wolfSSL_clear_num_renegotiations(WOLFSSL *s);
+WOLFSSL_API long wolfSSL_total_renegotiations(WOLFSSL *s);
+WOLFSSL_API long wolfSSL_num_renegotiations(WOLFSSL* s);
+WOLFSSL_API long wolfSSL_set_tmp_dh(WOLFSSL *s, WOLFSSL_DH *dh);
+WOLFSSL_API long wolfSSL_set_tlsext_debug_arg(WOLFSSL *s, void *arg);
+WOLFSSL_API long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type);
+WOLFSSL_API long wolfSSL_set_tlsext_status_exts(WOLFSSL *s, void *arg);
+WOLFSSL_API long wolfSSL_get_tlsext_status_ids(WOLFSSL *s, void *arg);
+WOLFSSL_API long wolfSSL_set_tlsext_status_ids(WOLFSSL *s, void *arg);
+WOLFSSL_API long wolfSSL_get_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char **resp);
+WOLFSSL_API long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char *resp, int len);
+
+WOLFSSL_API void wolfSSL_CONF_modules_unload(int all);
+WOLFSSL_API char* wolfSSL_CONF_get1_default_config_file(void);
+WOLFSSL_API long wolfSSL_get_tlsext_status_exts(WOLFSSL *s, void *arg);
+WOLFSSL_API long wolfSSL_get_verify_result(const WOLFSSL *ssl);
+
+#define WOLFSSL_DEFAULT_CIPHER_LIST ""   /* default all */
+
+/* These are bit-masks */
+enum {
+    WOLFSSL_OCSP_URL_OVERRIDE = 1,
+    WOLFSSL_OCSP_NO_NONCE     = 2,
+    WOLFSSL_OCSP_CHECKALL     = 4,
+
+    WOLFSSL_CRL_CHECKALL = 1,
+    WOLFSSL_CRL_CHECK    = 2,
+};
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \
+    defined(HAVE_WEBSERVER)
+/* Separated out from other enums because of size */
+enum {
+    SSL_OP_MICROSOFT_SESS_ID_BUG                  = 0x00000001,
+    SSL_OP_NETSCAPE_CHALLENGE_BUG                 = 0x00000002,
+    SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG       = 0x00000004,
+    SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG            = 0x00000008,
+    SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER             = 0x00000010,
+    SSL_OP_MSIE_SSLV2_RSA_PADDING                 = 0x00000020,
+    SSL_OP_SSLEAY_080_CLIENT_DH_BUG               = 0x00000040,
+    SSL_OP_TLS_D5_BUG                             = 0x00000080,
+    SSL_OP_TLS_BLOCK_PADDING_BUG                  = 0x00000100,
+    SSL_OP_TLS_ROLLBACK_BUG                       = 0x00000200,
+    SSL_OP_EPHEMERAL_RSA                          = 0x00000800,
+    WOLFSSL_OP_NO_SSLv3                           = 0x00001000,
+    WOLFSSL_OP_NO_TLSv1                           = 0x00002000,
+    SSL_OP_PKCS1_CHECK_1                          = 0x00004000,
+    SSL_OP_PKCS1_CHECK_2                          = 0x00008000,
+    SSL_OP_NETSCAPE_CA_DN_BUG                     = 0x00010000,
+    SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG        = 0x00020000,
+    SSL_OP_SINGLE_DH_USE                          = 0x00040000,
+    SSL_OP_NO_TICKET                              = 0x00080000,
+    SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS            = 0x00100000,
+    SSL_OP_NO_QUERY_MTU                           = 0x00200000,
+    SSL_OP_COOKIE_EXCHANGE                        = 0x00400000,
+    SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION = 0x00800000,
+    SSL_OP_SINGLE_ECDH_USE                        = 0x01000000,
+    SSL_OP_CIPHER_SERVER_PREFERENCE               = 0x02000000,
+    WOLFSSL_OP_NO_TLSv1_1                         = 0x04000000,
+    WOLFSSL_OP_NO_TLSv1_2                         = 0x08000000,
+    SSL_OP_NO_COMPRESSION                         = 0x10000000,
+    WOLFSSL_OP_NO_TLSv1_3                         = 0x20000000,
+    WOLFSSL_OP_NO_SSLv2                           = 0x40000000,
+    SSL_OP_ALL   =
+                    (SSL_OP_MICROSOFT_SESS_ID_BUG
+                  | SSL_OP_NETSCAPE_CHALLENGE_BUG
+                  | SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
+                  | SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
+                  | SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
+                  | SSL_OP_MSIE_SSLV2_RSA_PADDING
+                  | SSL_OP_SSLEAY_080_CLIENT_DH_BUG
+                  | SSL_OP_TLS_D5_BUG
+                  | SSL_OP_TLS_BLOCK_PADDING_BUG
+                  | SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
+                  | SSL_OP_TLS_ROLLBACK_BUG),
+};
+
+/* for compatibility these must be macros */
+#define SSL_OP_NO_SSLv2   WOLFSSL_OP_NO_SSLv2
+#define SSL_OP_NO_SSLv3   WOLFSSL_OP_NO_SSLv3
+#define SSL_OP_NO_TLSv1   WOLFSSL_OP_NO_TLSv1
+#define SSL_OP_NO_TLSv1_1 WOLFSSL_OP_NO_TLSv1_1
+#define SSL_OP_NO_TLSv1_2 WOLFSSL_OP_NO_TLSv1_2
+#if !(!defined(WOLFSSL_TLS13) && defined(WOLFSSL_APACHE_HTTPD)) /* apache uses this to determine if TLS 1.3 is enabled */
+#define SSL_OP_NO_TLSv1_3 WOLFSSL_OP_NO_TLSv1_3
+#endif
+
+#define SSL_OP_NO_SSL_MASK (SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | \
+    SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2 | SSL_OP_NO_TLSv1_3)
+
+#define SSL_NOTHING 1
+#define SSL_WRITING 2
+#define SSL_READING 3
+
+enum {
+#ifdef HAVE_OCSP
+    /* OCSP Flags */
+    OCSP_NOCERTS     = 1,
+    OCSP_NOINTERN    = 2,
+    OCSP_NOSIGS      = 4,
+    OCSP_NOCHAIN     = 8,
+    OCSP_NOVERIFY    = 16,
+    OCSP_NOEXPLICIT  = 32,
+    OCSP_NOCASIGN    = 64,
+    OCSP_NODELEGATED = 128,
+    OCSP_NOCHECKS    = 256,
+    OCSP_TRUSTOTHER  = 512,
+    OCSP_RESPID_KEY  = 1024,
+    OCSP_NOTIME      = 2048,
+
+    /* OCSP Types */
+    OCSP_CERTID   = 2,
+    OCSP_REQUEST  = 4,
+    OCSP_RESPONSE = 8,
+    OCSP_BASICRESP = 16,
+#endif
+
+    ASN1_GENERALIZEDTIME = 4,
+    SSL_MAX_SSL_SESSION_ID_LENGTH = 32,
+
+    SSL_ST_CONNECT = 0x1000,
+    SSL_ST_ACCEPT  = 0x2000,
+    SSL_ST_MASK    = 0x0FFF,
+
+    SSL_CB_LOOP = 0x01,
+    SSL_CB_EXIT = 0x02,
+    SSL_CB_READ = 0x04,
+    SSL_CB_WRITE = 0x08,
+    SSL_CB_HANDSHAKE_START = 0x10,
+    SSL_CB_HANDSHAKE_DONE = 0x20,
+    SSL_CB_ALERT = 0x4000,
+    SSL_CB_READ_ALERT = (SSL_CB_ALERT | SSL_CB_READ),
+    SSL_CB_WRITE_ALERT = (SSL_CB_ALERT | SSL_CB_WRITE),
+    SSL_CB_ACCEPT_LOOP = (SSL_ST_ACCEPT | SSL_CB_LOOP),
+    SSL_CB_ACCEPT_EXIT = (SSL_ST_ACCEPT | SSL_CB_EXIT),
+    SSL_CB_CONNECT_LOOP = (SSL_ST_CONNECT | SSL_CB_LOOP),
+    SSL_CB_CONNECT_EXIT = (SSL_ST_CONNECT | SSL_CB_EXIT),
+    SSL_CB_MODE_READ = 1,
+    SSL_CB_MODE_WRITE = 2,
+
+    SSL_MODE_ENABLE_PARTIAL_WRITE = 2,
+    SSL_MODE_AUTO_RETRY = 3, /* wolfSSL default is to block with blocking io
+                              * and auto retry */
+    SSL_MODE_RELEASE_BUFFERS = -1, /* For libwebsockets build. No current use. */
+
+    BIO_FLAGS_BASE64_NO_NL = 1,
+    BIO_CLOSE   = 1,
+    BIO_NOCLOSE = 0,
+
+    X509_FILETYPE_PEM = 8,
+    X509_LU_X509      = 9,
+    X509_LU_CRL       = 12,
+
+    X509_V_OK                                    = 0,
+    X509_V_ERR_CRL_SIGNATURE_FAILURE             = 13,
+    X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD    = 14,
+    X509_V_ERR_CRL_HAS_EXPIRED                   = 15,
+    X509_V_ERR_CERT_REVOKED                      = 16,
+    X509_V_ERR_CERT_CHAIN_TOO_LONG               = 17,
+    X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT         = 18,
+    X509_V_ERR_CERT_NOT_YET_VALID                = 19,
+    X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD    = 20,
+    X509_V_ERR_CERT_HAS_EXPIRED                  = 21,
+    X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD     = 22,
+    X509_V_ERR_CERT_REJECTED                     = 23,
+    /* Required for Nginx  */
+    X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT       = 24,
+    X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN         = 25,
+    X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY = 26,
+    X509_V_ERR_CERT_UNTRUSTED                    = 27,
+    X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE   = 28,
+    X509_V_ERR_SUBJECT_ISSUER_MISMATCH           = 29,
+    /* additional X509_V_ERR_* enums not used in wolfSSL */
+    X509_V_ERR_UNABLE_TO_GET_CRL,
+    X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE,
+    X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE,
+    X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY,
+    X509_V_ERR_CERT_SIGNATURE_FAILURE,
+    X509_V_ERR_CRL_NOT_YET_VALID,
+    X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD,
+    X509_V_ERR_OUT_OF_MEM,
+    X509_V_ERR_INVALID_CA,
+    X509_V_ERR_PATH_LENGTH_EXCEEDED,
+    X509_V_ERR_INVALID_PURPOSE,
+    X509_V_ERR_AKID_SKID_MISMATCH,
+    X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH,
+    X509_V_ERR_KEYUSAGE_NO_CERTSIGN,
+    X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER,
+    X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION,
+    X509_V_ERR_KEYUSAGE_NO_CRL_SIGN,
+    X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION,
+    X509_V_ERR_INVALID_NON_CA,
+    X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED,
+    X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE,
+    X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED,
+    X509_V_ERR_INVALID_EXTENSION,
+    X509_V_ERR_INVALID_POLICY_EXTENSION,
+    X509_V_ERR_NO_EXPLICIT_POLICY,
+    X509_V_ERR_UNNESTED_RESOURCE,
+    X509_V_ERR_APPLICATION_VERIFICATION,
+
+    X509_R_CERT_ALREADY_IN_HASH_TABLE,
+
+    XN_FLAG_SPC_EQ  = (1 << 23),
+    XN_FLAG_SEP_CPLUS_SPC = (2 << 16),
+    XN_FLAG_ONELINE = 0,
+    XN_FLAG_RFC2253 = 1,
+    XN_FLAG_DN_REV = (1 << 20),
+
+    CRYPTO_LOCK = 1,
+    CRYPTO_NUM_LOCKS = 10,
+
+    ASN1_STRFLGS_ESC_MSB = 4
+};
+#endif
+
+/* extras end */
+
+#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)
+/* wolfSSL extension, provide last error from SSL_get_error
+   since not using thread storage error queue */
+#include <stdio.h>
+WOLFSSL_API void  wolfSSL_ERR_print_errors_fp(XFILE, int err);
+#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
+WOLFSSL_API void wolfSSL_ERR_dump_errors_fp(XFILE fp);
+WOLFSSL_API void wolfSSL_ERR_print_errors_cb(int (*cb)(const char *str,
+                                                size_t len, void *u), void *u);
+#endif
+#endif
+WOLFSSL_API void wolfSSL_ERR_print_errors(WOLFSSL_BIO *bio);
+
+
+#ifndef NO_OLD_SSL_NAMES
+    #define SSL_ERROR_NONE WOLFSSL_ERROR_NONE
+    #define SSL_FAILURE WOLFSSL_FAILURE
+    #define SSL_SUCCESS WOLFSSL_SUCCESS
+    #define SSL_SHUTDOWN_NOT_DONE WOLFSSL_SHUTDOWN_NOT_DONE
+
+    #define SSL_ALPN_NOT_FOUND WOLFSSL_ALPN_NOT_FOUND
+    #define SSL_BAD_CERTTYPE WOLFSSL_BAD_CERTTYPE
+    #define SSL_BAD_STAT WOLFSSL_BAD_STAT
+    #define SSL_BAD_PATH WOLFSSL_BAD_PATH
+    #define SSL_BAD_FILETYPE WOLFSSL_BAD_FILETYPE
+    #define SSL_BAD_FILE WOLFSSL_BAD_FILE
+    #define SSL_NOT_IMPLEMENTED WOLFSSL_NOT_IMPLEMENTED
+    #define SSL_UNKNOWN WOLFSSL_UNKNOWN
+    #define SSL_FATAL_ERROR WOLFSSL_FATAL_ERROR
+
+    #define SSL_FILETYPE_ASN1 WOLFSSL_FILETYPE_ASN1
+    #define SSL_FILETYPE_PEM WOLFSSL_FILETYPE_PEM
+    #define SSL_FILETYPE_DEFAULT WOLFSSL_FILETYPE_DEFAULT
+    #define SSL_FILETYPE_RAW WOLFSSL_FILETYPE_RAW
+
+    #define SSL_VERIFY_NONE WOLFSSL_VERIFY_NONE
+    #define SSL_VERIFY_PEER WOLFSSL_VERIFY_PEER
+    #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT
+    #define SSL_VERIFY_CLIENT_ONCE WOLFSSL_VERIFY_CLIENT_ONCE
+    #define SSL_VERIFY_FAIL_EXCEPT_PSK WOLFSSL_VERIFY_FAIL_EXCEPT_PSK
+
+    #define SSL_SESS_CACHE_OFF WOLFSSL_SESS_CACHE_OFF
+    #define SSL_SESS_CACHE_CLIENT WOLFSSL_SESS_CACHE_CLIENT
+    #define SSL_SESS_CACHE_SERVER WOLFSSL_SESS_CACHE_SERVER
+    #define SSL_SESS_CACHE_BOTH WOLFSSL_SESS_CACHE_BOTH
+    #define SSL_SESS_CACHE_NO_AUTO_CLEAR WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR
+    #define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP
+    #define SSL_SESS_CACHE_NO_INTERNAL_STORE WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE
+    #define SSL_SESS_CACHE_NO_INTERNAL WOLFSSL_SESS_CACHE_NO_INTERNAL
+
+    #define SSL_ERROR_WANT_READ WOLFSSL_ERROR_WANT_READ
+    #define SSL_ERROR_WANT_WRITE WOLFSSL_ERROR_WANT_WRITE
+    #define SSL_ERROR_WANT_CONNECT WOLFSSL_ERROR_WANT_CONNECT
+    #define SSL_ERROR_WANT_ACCEPT WOLFSSL_ERROR_WANT_ACCEPT
+    #define SSL_ERROR_SYSCALL WOLFSSL_ERROR_SYSCALL
+    #define SSL_ERROR_WANT_X509_LOOKUP WOLFSSL_ERROR_WANT_X509_LOOKUP
+    #define SSL_ERROR_ZERO_RETURN WOLFSSL_ERROR_ZERO_RETURN
+    #define SSL_ERROR_SSL WOLFSSL_ERROR_SSL
+
+    #define SSL_SENT_SHUTDOWN WOLFSSL_SENT_SHUTDOWN
+    #define SSL_RECEIVED_SHUTDOWN WOLFSSL_RECEIVED_SHUTDOWN
+    #define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER
+
+    #define SSL_R_SSL_HANDSHAKE_FAILURE WOLFSSL_R_SSL_HANDSHAKE_FAILURE
+    #define SSL_R_TLSV1_ALERT_UNKNOWN_CA WOLFSSL_R_TLSV1_ALERT_UNKNOWN_CA
+    #define SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN WOLFSSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN
+    #define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE WOLFSSL_R_SSLV3_ALERT_BAD_CERTIFICATE
+
+    #define PEM_BUFSIZE WOLF_PEM_BUFSIZE
+#endif
+
+enum { /* ssl Constants */
+    WOLFSSL_ERROR_NONE      =  0,   /* for most functions */
+    WOLFSSL_FAILURE         =  0,   /* for some functions */
+    WOLFSSL_SUCCESS         =  1,
+    WOLFSSL_SHUTDOWN_NOT_DONE =  2,  /* call wolfSSL_shutdown again to complete */
+
+    WOLFSSL_ALPN_NOT_FOUND  = -9,
+    WOLFSSL_BAD_CERTTYPE    = -8,
+    WOLFSSL_BAD_STAT        = -7,
+    WOLFSSL_BAD_PATH        = -6,
+    WOLFSSL_BAD_FILETYPE    = -5,
+    WOLFSSL_BAD_FILE        = -4,
+    WOLFSSL_NOT_IMPLEMENTED = -3,
+    WOLFSSL_UNKNOWN         = -2,
+    WOLFSSL_FATAL_ERROR     = -1,
+
+    WOLFSSL_FILETYPE_ASN1    = 2,
+    WOLFSSL_FILETYPE_PEM     = 1,
+    WOLFSSL_FILETYPE_DEFAULT = 2, /* ASN1 */
+    WOLFSSL_FILETYPE_RAW     = 3, /* NTRU raw key blob */
+
+    WOLFSSL_VERIFY_NONE                 = 0,
+    WOLFSSL_VERIFY_PEER                 = 1,
+    WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT = 2,
+    WOLFSSL_VERIFY_CLIENT_ONCE          = 4,
+    WOLFSSL_VERIFY_FAIL_EXCEPT_PSK      = 8,
+
+    WOLFSSL_SESS_CACHE_OFF                = 0x0000,
+    WOLFSSL_SESS_CACHE_CLIENT             = 0x0001,
+    WOLFSSL_SESS_CACHE_SERVER             = 0x0002,
+    WOLFSSL_SESS_CACHE_BOTH               = 0x0003,
+    WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR      = 0x0008,
+    WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP = 0x0100,
+    WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE  = 0x0200,
+    WOLFSSL_SESS_CACHE_NO_INTERNAL        = 0x0300,
+
+    WOLFSSL_ERROR_WANT_READ        =  2,
+    WOLFSSL_ERROR_WANT_WRITE       =  3,
+    WOLFSSL_ERROR_WANT_CONNECT     =  7,
+    WOLFSSL_ERROR_WANT_ACCEPT      =  8,
+    WOLFSSL_ERROR_SYSCALL          =  5,
+    WOLFSSL_ERROR_WANT_X509_LOOKUP = 83,
+    WOLFSSL_ERROR_ZERO_RETURN      =  6,
+    WOLFSSL_ERROR_SSL              = 85,
+
+    WOLFSSL_SENT_SHUTDOWN     = 1,
+    WOLFSSL_RECEIVED_SHUTDOWN = 2,
+    WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER = 4,
+
+    WOLFSSL_R_SSL_HANDSHAKE_FAILURE           = 101,
+    WOLFSSL_R_TLSV1_ALERT_UNKNOWN_CA          = 102,
+    WOLFSSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN = 103,
+    WOLFSSL_R_SSLV3_ALERT_BAD_CERTIFICATE     = 104,
+
+    WOLF_PEM_BUFSIZE = 1024
+};
+
+#ifndef NO_PSK
+    typedef unsigned int (*wc_psk_client_callback)(WOLFSSL*, const char*, char*,
+                                    unsigned int, unsigned char*, unsigned int);
+    WOLFSSL_API void wolfSSL_CTX_set_psk_client_callback(WOLFSSL_CTX*,
+                                                    wc_psk_client_callback);
+    WOLFSSL_API void wolfSSL_set_psk_client_callback(WOLFSSL*,
+                                                    wc_psk_client_callback);
+#ifdef WOLFSSL_TLS13
+    typedef unsigned int (*wc_psk_client_tls13_callback)(WOLFSSL*, const char*,
+               char*, unsigned int, unsigned char*, unsigned int, const char**);
+    WOLFSSL_API void wolfSSL_CTX_set_psk_client_tls13_callback(WOLFSSL_CTX*,
+                                                  wc_psk_client_tls13_callback);
+    WOLFSSL_API void wolfSSL_set_psk_client_tls13_callback(WOLFSSL*,
+                                                  wc_psk_client_tls13_callback);
+#endif
+
+    WOLFSSL_API const char* wolfSSL_get_psk_identity_hint(const WOLFSSL*);
+    WOLFSSL_API const char* wolfSSL_get_psk_identity(const WOLFSSL*);
+
+    WOLFSSL_API int wolfSSL_CTX_use_psk_identity_hint(WOLFSSL_CTX*, const char*);
+    WOLFSSL_API int wolfSSL_use_psk_identity_hint(WOLFSSL*, const char*);
+
+    typedef unsigned int (*wc_psk_server_callback)(WOLFSSL*, const char*,
+                          unsigned char*, unsigned int);
+    WOLFSSL_API void wolfSSL_CTX_set_psk_server_callback(WOLFSSL_CTX*,
+                                                    wc_psk_server_callback);
+    WOLFSSL_API void wolfSSL_set_psk_server_callback(WOLFSSL*,
+                                                    wc_psk_server_callback);
+#ifdef WOLFSSL_TLS13
+    typedef unsigned int (*wc_psk_server_tls13_callback)(WOLFSSL*, const char*,
+                          unsigned char*, unsigned int, const char**);
+    WOLFSSL_API void wolfSSL_CTX_set_psk_server_tls13_callback(WOLFSSL_CTX*,
+                                                  wc_psk_server_tls13_callback);
+    WOLFSSL_API void wolfSSL_set_psk_server_tls13_callback(WOLFSSL*,
+                                                  wc_psk_server_tls13_callback);
+#endif
+
+    #define PSK_TYPES_DEFINED
+#endif /* NO_PSK */
+
+
+#ifdef HAVE_ANON
+    WOLFSSL_API int wolfSSL_CTX_allow_anon_cipher(WOLFSSL_CTX*);
+#endif /* HAVE_ANON */
+
+
+/* extra begins */
+#ifdef OPENSSL_EXTRA
+enum {  /* ERR Constants */
+    ERR_TXT_STRING = 1
+};
+
+/* bio misc */
+enum {
+    WOLFSSL_BIO_ERROR = -1,
+    WOLFSSL_BIO_UNSET = -2,
+    WOLFSSL_BIO_SIZE  = 17000 /* default BIO write size if not set */
+};
+#endif
+
+WOLFSSL_API void wolfSSL_ERR_put_error(int lib, int fun, int err,
+                                       const char* file, int line);
+WOLFSSL_API unsigned long wolfSSL_ERR_get_error_line(const char**, int*);
+WOLFSSL_API unsigned long wolfSSL_ERR_get_error_line_data(const char**, int*,
+                                                 const char**, int *);
+
+WOLFSSL_API unsigned long wolfSSL_ERR_get_error(void);
+WOLFSSL_API void          wolfSSL_ERR_clear_error(void);
+
+
+WOLFSSL_API int  wolfSSL_RAND_status(void);
+WOLFSSL_API int  wolfSSL_RAND_pseudo_bytes(unsigned char* buf, int num);
+WOLFSSL_API int  wolfSSL_RAND_bytes(unsigned char* buf, int num);
+WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_server_method(void);
+WOLFSSL_API long wolfSSL_CTX_set_options(WOLFSSL_CTX*, long);
+WOLFSSL_API long wolfSSL_CTX_get_options(WOLFSSL_CTX* ctx);
+WOLFSSL_API long wolfSSL_CTX_clear_options(WOLFSSL_CTX*, long);
+
+#ifndef NO_CERTS
+  WOLFSSL_API int  wolfSSL_CTX_check_private_key(const WOLFSSL_CTX*);
+#endif /* !NO_CERTS */
+
+WOLFSSL_API void wolfSSL_ERR_free_strings(void);
+WOLFSSL_API void wolfSSL_ERR_remove_state(unsigned long);
+WOLFSSL_API int  wolfSSL_clear(WOLFSSL* ssl);
+WOLFSSL_API int  wolfSSL_state(WOLFSSL* ssl);
+
+WOLFSSL_API void wolfSSL_cleanup_all_ex_data(void);
+WOLFSSL_API long wolfSSL_CTX_set_mode(WOLFSSL_CTX* ctx, long mode);
+WOLFSSL_API long wolfSSL_CTX_get_mode(WOLFSSL_CTX* ctx);
+WOLFSSL_API void wolfSSL_CTX_set_default_read_ahead(WOLFSSL_CTX* ctx, int m);
+WOLFSSL_API long wolfSSL_SSL_get_mode(WOLFSSL* ssl);
+
+
+WOLFSSL_API int  wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX*);
+WOLFSSL_API int  wolfSSL_CTX_set_session_id_context(WOLFSSL_CTX*,
+                                            const unsigned char*, unsigned int);
+WOLFSSL_ABI WOLFSSL_API WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL*);
+WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL*);
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl);
+#endif
+
+#ifdef OPENSSL_EXTRA
+WOLFSSL_API int wolfSSL_want(WOLFSSL*);
+#endif
+WOLFSSL_API int wolfSSL_want_read(WOLFSSL*);
+WOLFSSL_API int wolfSSL_want_write(WOLFSSL*);
+
+#if !defined(NO_FILESYSTEM) && defined (OPENSSL_EXTRA)
+#include <stdarg.h> /* var_arg */
+WOLFSSL_API int wolfSSL_BIO_vprintf(WOLFSSL_BIO* bio, const char* format,
+                                                            va_list args);
+#endif
+WOLFSSL_API int wolfSSL_BIO_printf(WOLFSSL_BIO*, const char*, ...);
+WOLFSSL_API int wolfSSL_BIO_dump(WOLFSSL_BIO *bio, const char*, int);
+WOLFSSL_API int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO*,
+                                         const WOLFSSL_ASN1_UTCTIME*);
+WOLFSSL_API int wolfSSL_ASN1_GENERALIZEDTIME_print(WOLFSSL_BIO*,
+                                         const WOLFSSL_ASN1_GENERALIZEDTIME*);
+WOLFSSL_API void wolfSSL_ASN1_GENERALIZEDTIME_free(WOLFSSL_ASN1_GENERALIZEDTIME*);
+WOLFSSL_API int wolfSSL_ASN1_TIME_check(const WOLFSSL_ASN1_TIME*);
+WOLFSSL_API int wolfSSL_ASN1_TIME_diff(int *pday, int *psec,
+                   const WOLFSSL_ASN1_TIME *from, const WOLFSSL_ASN1_TIME *to);
+#ifdef OPENSSL_EXTRA
+WOLFSSL_API WOLFSSL_ASN1_TIME *wolfSSL_ASN1_TIME_set(WOLFSSL_ASN1_TIME *s, time_t t);
+#endif
+
+WOLFSSL_API int wolfSSL_sk_num(WOLFSSL_STACK* sk);
+WOLFSSL_API void* wolfSSL_sk_value(WOLFSSL_STACK* sk, int i);
+
+#if defined(HAVE_EX_DATA) || defined(FORTRESS)
+WOLFSSL_API void* wolfSSL_CRYPTO_get_ex_data(const WOLFSSL_CRYPTO_EX_DATA* ex_data,
+                                            int idx);
+WOLFSSL_API int wolfSSL_CRYPTO_set_ex_data(WOLFSSL_CRYPTO_EX_DATA* ex_data, int idx,
+                                            void *data);
+#endif
+
+/* stunnel 4.28 needs */
+WOLFSSL_API void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX*, int);
+WOLFSSL_API int   wolfSSL_CTX_set_ex_data(WOLFSSL_CTX*, int, void*);
+WOLFSSL_API void  wolfSSL_CTX_sess_set_get_cb(WOLFSSL_CTX*,
+                       WOLFSSL_SESSION*(*f)(WOLFSSL*, unsigned char*, int, int*));
+WOLFSSL_API void  wolfSSL_CTX_sess_set_new_cb(WOLFSSL_CTX*,
+                                            int (*f)(WOLFSSL*, WOLFSSL_SESSION*));
+WOLFSSL_API void  wolfSSL_CTX_sess_set_remove_cb(WOLFSSL_CTX*,
+                                       void (*f)(WOLFSSL_CTX*, WOLFSSL_SESSION*));
+
+WOLFSSL_API int          wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION*,unsigned char**);
+WOLFSSL_API WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION**,
+                                                   const unsigned char**, long);
+
+WOLFSSL_API long wolfSSL_SESSION_get_timeout(const WOLFSSL_SESSION*);
+WOLFSSL_API long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION*);
+WOLFSSL_API int  wolfSSL_CTX_get_ex_new_index(long, void*, void*, void*, void*);
+
+
+/* extra ends */
+
+
+/* wolfSSL extensions */
+
+/* call before SSL_connect, if verifying will add name check to
+   date check and signature check */
+WOLFSSL_ABI WOLFSSL_API int wolfSSL_check_domain_name(WOLFSSL*, const char*);
+
+/* need to call once to load library (session cache) */
+WOLFSSL_ABI WOLFSSL_API int wolfSSL_Init(void);
+/* call when done to cleanup/free session cache mutex / resources  */
+WOLFSSL_ABI WOLFSSL_API int wolfSSL_Cleanup(void);
+
+/* which library version do we have */
+WOLFSSL_API const char* wolfSSL_lib_version(void);
+/* which library version do we have in hex */
+WOLFSSL_API word32 wolfSSL_lib_version_hex(void);
+
+/* do accept or connect depedning on side */
+WOLFSSL_API int wolfSSL_negotiate(WOLFSSL* ssl);
+/* turn on wolfSSL data compression */
+WOLFSSL_API int wolfSSL_set_compression(WOLFSSL* ssl);
+
+WOLFSSL_ABI WOLFSSL_API int wolfSSL_set_timeout(WOLFSSL*, unsigned int);
+WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_set_timeout(WOLFSSL_CTX*, unsigned int);
+WOLFSSL_API void wolfSSL_CTX_set_current_time_cb(WOLFSSL_CTX* ctx,
+    void (*cb)(const WOLFSSL* ssl, WOLFSSL_TIMEVAL* out_clock));
+
+/* get wolfSSL peer X509_CHAIN */
+WOLFSSL_API WOLFSSL_X509_CHAIN* wolfSSL_get_peer_chain(WOLFSSL* ssl);
+#ifdef WOLFSSL_ALT_CERT_CHAINS
+WOLFSSL_API int wolfSSL_is_peer_alt_cert_chain(const WOLFSSL* ssl);
+/* get wolfSSL alternate peer X509_CHAIN */
+WOLFSSL_API WOLFSSL_X509_CHAIN* wolfSSL_get_peer_alt_chain(WOLFSSL* ssl);
+#endif
+/* peer chain count */
+WOLFSSL_API int  wolfSSL_get_chain_count(WOLFSSL_X509_CHAIN* chain);
+/* index cert length */
+WOLFSSL_API int  wolfSSL_get_chain_length(WOLFSSL_X509_CHAIN*, int idx);
+/* index cert */
+WOLFSSL_API unsigned char* wolfSSL_get_chain_cert(WOLFSSL_X509_CHAIN*, int idx);
+/* index cert in X509 */
+WOLFSSL_API WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN*, int idx);
+/* free X509 */
+#define wolfSSL_FreeX509(x509) wolfSSL_X509_free((x509))
+WOLFSSL_ABI WOLFSSL_API void wolfSSL_X509_free(WOLFSSL_X509*);
+/* get index cert in PEM */
+WOLFSSL_API int  wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN*, int idx,
+                                unsigned char* buf, int inLen, int* outLen);
+WOLFSSL_ABI WOLFSSL_API const unsigned char* wolfSSL_get_sessionID(
+                                                      const WOLFSSL_SESSION* s);
+WOLFSSL_API int  wolfSSL_X509_get_serial_number(WOLFSSL_X509*,unsigned char*,int*);
+WOLFSSL_API char*  wolfSSL_X509_get_subjectCN(WOLFSSL_X509*);
+WOLFSSL_API const unsigned char* wolfSSL_X509_get_der(WOLFSSL_X509*, int*);
+WOLFSSL_API const unsigned char* wolfSSL_X509_get_tbs(WOLFSSL_X509*, int*);
+WOLFSSL_ABI WOLFSSL_API const byte* wolfSSL_X509_notBefore(WOLFSSL_X509*);
+WOLFSSL_ABI WOLFSSL_API const byte* wolfSSL_X509_notAfter(WOLFSSL_X509*);
+WOLFSSL_API int wolfSSL_X509_version(WOLFSSL_X509*);
+
+WOLFSSL_API int wolfSSL_cmp_peer_cert_to_file(WOLFSSL*, const char*);
+
+WOLFSSL_ABI WOLFSSL_API char* wolfSSL_X509_get_next_altname(WOLFSSL_X509*);
+WOLFSSL_API int wolfSSL_X509_add_altname(WOLFSSL_X509*, const char*, int);
+
+WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509(WOLFSSL_X509** x509,
+        const unsigned char** in, int len);
+WOLFSSL_API WOLFSSL_X509*
+    wolfSSL_X509_d2i(WOLFSSL_X509** x509, const unsigned char* in, int len);
+WOLFSSL_API int wolfSSL_i2d_X509(WOLFSSL_X509* x509, unsigned char** out);
+WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL(WOLFSSL_X509_CRL **crl,
+                                                   const unsigned char *in, int len);
+#ifndef NO_FILESYSTEM
+WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL_fp(XFILE file, WOLFSSL_X509_CRL **crl);
+#endif
+WOLFSSL_API void wolfSSL_X509_CRL_free(WOLFSSL_X509_CRL *crl);
+
+#ifndef NO_FILESYSTEM
+    #ifndef NO_STDIO_FILESYSTEM
+    WOLFSSL_API WOLFSSL_X509*
+        wolfSSL_X509_d2i_fp(WOLFSSL_X509** x509, XFILE file);
+    #endif
+WOLFSSL_ABI WOLFSSL_API WOLFSSL_X509*
+    wolfSSL_X509_load_certificate_file(const char* fname, int format);
+#endif
+WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_load_certificate_buffer(
+    const unsigned char* buf, int sz, int format);
+
+#ifdef WOLFSSL_SEP
+    WOLFSSL_API unsigned char*
+           wolfSSL_X509_get_device_type(WOLFSSL_X509*, unsigned char*, int*);
+    WOLFSSL_API unsigned char*
+           wolfSSL_X509_get_hw_type(WOLFSSL_X509*, unsigned char*, int*);
+    WOLFSSL_API unsigned char*
+           wolfSSL_X509_get_hw_serial_number(WOLFSSL_X509*, unsigned char*, int*);
+#endif
+
+/* connect enough to get peer cert */
+WOLFSSL_API int  wolfSSL_connect_cert(WOLFSSL* ssl);
+
+
+
+/* PKCS12 compatibility */
+typedef struct WC_PKCS12 WC_PKCS12;
+WOLFSSL_API WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio,
+                                       WC_PKCS12** pkcs12);
+WOLFSSL_API int wolfSSL_i2d_PKCS12_bio(WOLFSSL_BIO *bio, WC_PKCS12 *pkcs12);
+#ifndef NO_FILESYSTEM
+WOLFSSL_API WOLFSSL_X509_PKCS12* wolfSSL_d2i_PKCS12_fp(XFILE fp,
+                                       WOLFSSL_X509_PKCS12** pkcs12);
+#endif
+WOLFSSL_API int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw,
+     WOLFSSL_EVP_PKEY** pkey, WOLFSSL_X509** cert,
+     WOLF_STACK_OF(WOLFSSL_X509)** ca);
+WOLFSSL_API WC_PKCS12* wolfSSL_PKCS12_create(char* pass, char* name,
+        WOLFSSL_EVP_PKEY* pkey, WOLFSSL_X509* cert,
+        WOLF_STACK_OF(WOLFSSL_X509)* ca,
+        int keyNID, int certNID, int itt, int macItt, int keytype);
+WOLFSSL_API void wolfSSL_PKCS12_PBE_add(void);
+
+
+
+#ifndef NO_DH
+/* server Diffie-Hellman parameters */
+WOLFSSL_API int  wolfSSL_SetTmpDH(WOLFSSL*, const unsigned char* p, int pSz,
+                                const unsigned char* g, int gSz);
+WOLFSSL_API int  wolfSSL_SetTmpDH_buffer(WOLFSSL*, const unsigned char* b, long sz,
+                                       int format);
+WOLFSSL_API int wolfSSL_SetEnableDhKeyTest(WOLFSSL*, int);
+#ifndef NO_FILESYSTEM
+    WOLFSSL_API int  wolfSSL_SetTmpDH_file(WOLFSSL*, const char* f, int format);
+#endif
+
+/* server ctx Diffie-Hellman parameters */
+WOLFSSL_API int  wolfSSL_CTX_SetTmpDH(WOLFSSL_CTX*, const unsigned char* p,
+                                    int pSz, const unsigned char* g, int gSz);
+WOLFSSL_API int  wolfSSL_CTX_SetTmpDH_buffer(WOLFSSL_CTX*, const unsigned char* b,
+                                           long sz, int format);
+
+#ifndef NO_FILESYSTEM
+    WOLFSSL_API int  wolfSSL_CTX_SetTmpDH_file(WOLFSSL_CTX*, const char* f,
+                                             int format);
+#endif
+
+WOLFSSL_API int wolfSSL_CTX_SetMinDhKey_Sz(WOLFSSL_CTX*, word16);
+WOLFSSL_API int wolfSSL_SetMinDhKey_Sz(WOLFSSL*, word16);
+WOLFSSL_API int wolfSSL_CTX_SetMaxDhKey_Sz(WOLFSSL_CTX*, word16);
+WOLFSSL_API int wolfSSL_SetMaxDhKey_Sz(WOLFSSL*, word16);
+WOLFSSL_API int wolfSSL_GetDhKey_Sz(WOLFSSL*);
+#endif /* NO_DH */
+
+#ifndef NO_RSA
+WOLFSSL_API int wolfSSL_CTX_SetMinRsaKey_Sz(WOLFSSL_CTX*, short);
+WOLFSSL_API int wolfSSL_SetMinRsaKey_Sz(WOLFSSL*, short);
+#endif /* NO_RSA */
+
+#ifdef HAVE_ECC
+WOLFSSL_API int wolfSSL_CTX_SetMinEccKey_Sz(WOLFSSL_CTX*, short);
+WOLFSSL_API int wolfSSL_SetMinEccKey_Sz(WOLFSSL*, short);
+#endif /* NO_RSA */
+
+WOLFSSL_API int  wolfSSL_SetTmpEC_DHE_Sz(WOLFSSL*, word16);
+WOLFSSL_API int  wolfSSL_CTX_SetTmpEC_DHE_Sz(WOLFSSL_CTX*, word16);
+
+/* keyblock size in bytes or -1 */
+/* need to call wolfSSL_KeepArrays before handshake to save keys */
+WOLFSSL_API int wolfSSL_get_keyblock_size(WOLFSSL*);
+WOLFSSL_API int wolfSSL_get_keys(WOLFSSL*,unsigned char** ms, unsigned int* msLen,
+                                       unsigned char** sr, unsigned int* srLen,
+                                       unsigned char** cr, unsigned int* crLen);
+
+/* Computes EAP-TLS and EAP-TTLS keying material from the master_secret. */
+WOLFSSL_API int wolfSSL_make_eap_keys(WOLFSSL*, void* key, unsigned int len,
+                                                             const char* label);
+
+
+#ifndef _WIN32
+    #ifndef NO_WRITEV
+        #ifdef __PPU
+            #include <sys/types.h>
+            #include <sys/socket.h>
+        #elif !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_IAR_ARM) && \
+              !defined(WOLFSSL_PICOTCP) && !defined(WOLFSSL_ROWLEY_ARM) && \
+              !defined(WOLFSSL_EMBOS) && !defined(WOLFSSL_FROSTED) && \
+              !defined(WOLFSSL_CHIBIOS) && !defined(WOLFSSL_CONTIKI) && \
+              !defined(WOLFSSL_ZEPHYR)
+            #include <sys/uio.h>
+        #endif
+        /* allow writev style writing */
+        WOLFSSL_API int wolfSSL_writev(WOLFSSL* ssl, const struct iovec* iov,
+                                     int iovcnt);
+    #endif
+#endif
+
+
+#ifndef NO_CERTS
+    /* SSL_CTX versions */
+    WOLFSSL_API int wolfSSL_CTX_UnloadCAs(WOLFSSL_CTX*);
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    WOLFSSL_API int wolfSSL_CTX_Unload_trust_peers(WOLFSSL_CTX*);
+    WOLFSSL_API int wolfSSL_CTX_trust_peer_buffer(WOLFSSL_CTX*,
+                                               const unsigned char*, long, int);
+#endif
+    WOLFSSL_API int wolfSSL_CTX_load_verify_buffer_ex(WOLFSSL_CTX*,
+                                               const unsigned char*, long, int,
+                                               int, word32);
+    WOLFSSL_API int wolfSSL_CTX_load_verify_buffer(WOLFSSL_CTX*,
+                                               const unsigned char*, long, int);
+    WOLFSSL_API int wolfSSL_CTX_load_verify_chain_buffer_format(WOLFSSL_CTX*,
+                                               const unsigned char*, long, int);
+    WOLFSSL_API int wolfSSL_CTX_use_certificate_buffer(WOLFSSL_CTX*,
+                                               const unsigned char*, long, int);
+    WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_buffer(WOLFSSL_CTX*,
+                                               const unsigned char*, long, int);
+    WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_id(WOLFSSL_CTX*,
+                                         const unsigned char*, long, int, long);
+    WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_buffer_format(WOLFSSL_CTX*,
+                                               const unsigned char*, long, int);
+    WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_buffer(WOLFSSL_CTX*,
+                                                    const unsigned char*, long);
+
+    /* SSL versions */
+    WOLFSSL_API int wolfSSL_use_certificate_buffer(WOLFSSL*, const unsigned char*,
+                                               long, int);
+    WOLFSSL_API int wolfSSL_use_certificate_ASN1(WOLFSSL* ssl,
+                                           const unsigned char* der, int derSz);
+    WOLFSSL_API int wolfSSL_use_PrivateKey_buffer(WOLFSSL*, const unsigned char*,
+                                               long, int);
+    WOLFSSL_API int wolfSSL_use_PrivateKey_id(WOLFSSL*, const unsigned char*,
+                                                               long, int, long);
+    WOLFSSL_API int wolfSSL_use_certificate_chain_buffer_format(WOLFSSL*,
+                                               const unsigned char*, long, int);
+    WOLFSSL_API int wolfSSL_use_certificate_chain_buffer(WOLFSSL*,
+                                               const unsigned char*, long);
+    WOLFSSL_API int wolfSSL_UnloadCertsKeys(WOLFSSL*);
+
+    #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+        defined(KEEP_OUR_CERT)
+        WOLFSSL_API WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl);
+    #endif
+#endif
+
+WOLFSSL_API int wolfSSL_CTX_set_group_messages(WOLFSSL_CTX*);
+WOLFSSL_API int wolfSSL_set_group_messages(WOLFSSL*);
+
+
+#ifdef HAVE_FUZZER
+enum fuzzer_type {
+    FUZZ_HMAC      = 0,
+    FUZZ_ENCRYPT   = 1,
+    FUZZ_SIGNATURE = 2,
+    FUZZ_HASH      = 3,
+    FUZZ_HEAD      = 4
+};
+
+typedef int (*CallbackFuzzer)(WOLFSSL* ssl, const unsigned char* buf, int sz,
+        int type, void* fuzzCtx);
+
+WOLFSSL_API void wolfSSL_SetFuzzerCb(WOLFSSL* ssl, CallbackFuzzer cbf, void* fCtx);
+#endif
+
+
+WOLFSSL_API int   wolfSSL_DTLS_SetCookieSecret(WOLFSSL*, const byte*, word32);
+
+
+/* I/O Callback default errors */
+enum IOerrors {
+    WOLFSSL_CBIO_ERR_GENERAL    = -1,     /* general unexpected err */
+    WOLFSSL_CBIO_ERR_WANT_READ  = -2,     /* need to call read  again */
+    WOLFSSL_CBIO_ERR_WANT_WRITE = -2,     /* need to call write again */
+    WOLFSSL_CBIO_ERR_CONN_RST   = -3,     /* connection reset */
+    WOLFSSL_CBIO_ERR_ISR        = -4,     /* interrupt */
+    WOLFSSL_CBIO_ERR_CONN_CLOSE = -5,     /* connection closed or epipe */
+    WOLFSSL_CBIO_ERR_TIMEOUT    = -6      /* socket timeout */
+};
+
+
+/* CA cache callbacks */
+enum {
+    WOLFSSL_SSLV3    = 0,
+    WOLFSSL_TLSV1    = 1,
+    WOLFSSL_TLSV1_1  = 2,
+    WOLFSSL_TLSV1_2  = 3,
+    WOLFSSL_TLSV1_3  = 4,
+    WOLFSSL_USER_CA  = 1,          /* user added as trusted */
+    WOLFSSL_CHAIN_CA = 2           /* added to cache from trusted chain */
+};
+
+WOLFSSL_ABI WOLFSSL_API WC_RNG* wolfSSL_GetRNG(WOLFSSL*);
+
+WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_SetMinVersion(WOLFSSL_CTX*, int);
+WOLFSSL_API int wolfSSL_SetMinVersion(WOLFSSL*, int);
+WOLFSSL_API int wolfSSL_GetObjectSize(void);  /* object size based on build */
+WOLFSSL_API int wolfSSL_CTX_GetObjectSize(void);
+WOLFSSL_API int wolfSSL_METHOD_GetObjectSize(void);
+WOLFSSL_API int wolfSSL_GetOutputSize(WOLFSSL*, int);
+WOLFSSL_API int wolfSSL_GetMaxOutputSize(WOLFSSL*);
+WOLFSSL_API int wolfSSL_GetVersion(WOLFSSL* ssl);
+WOLFSSL_API int wolfSSL_SetVersion(WOLFSSL* ssl, int version);
+
+/* moved to asn.c, old names kept for backwards compatibility */
+#define wolfSSL_KeyPemToDer    wc_KeyPemToDer
+#define wolfSSL_CertPemToDer   wc_CertPemToDer
+#define wolfSSL_PemPubKeyToDer wc_PemPubKeyToDer
+#define wolfSSL_PubKeyPemToDer wc_PubKeyPemToDer
+#define wolfSSL_PemCertToDer   wc_PemCertToDer
+
+
+typedef void (*CallbackCACache)(unsigned char* der, int sz, int type);
+typedef void (*CbMissingCRL)(const char* url);
+typedef int  (*CbOCSPIO)(void*, const char*, int,
+                                         unsigned char*, int, unsigned char**);
+typedef void (*CbOCSPRespFree)(void*,unsigned char*);
+
+#ifdef HAVE_CRL_IO
+typedef int  (*CbCrlIO)(WOLFSSL_CRL* crl, const char* url, int urlSz);
+#endif
+
+/* User Atomic Record Layer CallBacks */
+typedef int (*CallbackMacEncrypt)(WOLFSSL* ssl, unsigned char* macOut,
+       const unsigned char* macIn, unsigned int macInSz, int macContent,
+       int macVerify, unsigned char* encOut, const unsigned char* encIn,
+       unsigned int encSz, void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetMacEncryptCb(WOLFSSL_CTX*, CallbackMacEncrypt);
+WOLFSSL_API void  wolfSSL_SetMacEncryptCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetMacEncryptCtx(WOLFSSL* ssl);
+
+typedef int (*CallbackDecryptVerify)(WOLFSSL* ssl,
+       unsigned char* decOut, const unsigned char* decIn,
+       unsigned int decSz, int content, int verify, unsigned int* padSz,
+       void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetDecryptVerifyCb(WOLFSSL_CTX*,
+                                                 CallbackDecryptVerify);
+WOLFSSL_API void  wolfSSL_SetDecryptVerifyCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetDecryptVerifyCtx(WOLFSSL* ssl);
+
+typedef int (*CallbackEncryptMac)(WOLFSSL* ssl, unsigned char* macOut,
+       int content, int macVerify, unsigned char* encOut,
+       const unsigned char* encIn, unsigned int encSz, void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetEncryptMacCb(WOLFSSL_CTX*, CallbackEncryptMac);
+WOLFSSL_API void  wolfSSL_SetEncryptMacCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetEncryptMacCtx(WOLFSSL* ssl);
+
+typedef int (*CallbackVerifyDecrypt)(WOLFSSL* ssl,
+       unsigned char* decOut, const unsigned char* decIn,
+       unsigned int decSz, int content, int verify, unsigned int* padSz,
+       void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetVerifyDecryptCb(WOLFSSL_CTX*,
+                                                 CallbackVerifyDecrypt);
+WOLFSSL_API void  wolfSSL_SetVerifyDecryptCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetVerifyDecryptCtx(WOLFSSL* ssl);
+
+WOLFSSL_API const unsigned char* wolfSSL_GetMacSecret(WOLFSSL*, int);
+WOLFSSL_API const unsigned char* wolfSSL_GetClientWriteKey(WOLFSSL*);
+WOLFSSL_API const unsigned char* wolfSSL_GetClientWriteIV(WOLFSSL*);
+WOLFSSL_API const unsigned char* wolfSSL_GetServerWriteKey(WOLFSSL*);
+WOLFSSL_API const unsigned char* wolfSSL_GetServerWriteIV(WOLFSSL*);
+WOLFSSL_API int                  wolfSSL_GetKeySize(WOLFSSL*);
+WOLFSSL_API int                  wolfSSL_GetIVSize(WOLFSSL*);
+WOLFSSL_API int                  wolfSSL_GetSide(WOLFSSL*);
+WOLFSSL_API int                  wolfSSL_IsTLSv1_1(WOLFSSL*);
+WOLFSSL_API int                  wolfSSL_GetBulkCipher(WOLFSSL*);
+WOLFSSL_API int                  wolfSSL_GetCipherBlockSize(WOLFSSL*);
+WOLFSSL_API int                  wolfSSL_GetAeadMacSize(WOLFSSL*);
+WOLFSSL_API int                  wolfSSL_GetHmacSize(WOLFSSL*);
+WOLFSSL_API int                  wolfSSL_GetHmacType(WOLFSSL*);
+WOLFSSL_API int                  wolfSSL_GetCipherType(WOLFSSL*);
+WOLFSSL_API int                  wolfSSL_SetTlsHmacInner(WOLFSSL*, unsigned char*,
+                                                       word32, int, int);
+
+/* Atomic User Needs */
+enum {
+    WOLFSSL_SERVER_END = 0,
+    WOLFSSL_CLIENT_END = 1,
+    WOLFSSL_NEITHER_END = 3,
+    WOLFSSL_BLOCK_TYPE = 2,
+    WOLFSSL_STREAM_TYPE = 3,
+    WOLFSSL_AEAD_TYPE = 4,
+    WOLFSSL_TLS_HMAC_INNER_SZ = 13      /* SEQ_SZ + ENUM + VERSION_SZ + LEN_SZ */
+};
+
+/* for GetBulkCipher and internal use */
+enum BulkCipherAlgorithm {
+    wolfssl_cipher_null,
+    wolfssl_rc4,
+    wolfssl_rc2,
+    wolfssl_des,
+    wolfssl_triple_des,             /* leading 3 (3des) not valid identifier */
+    wolfssl_des40,
+#ifdef HAVE_IDEA
+    wolfssl_idea,
+#endif
+    wolfssl_aes,
+    wolfssl_aes_gcm,
+    wolfssl_aes_ccm,
+    wolfssl_chacha,
+    wolfssl_camellia,
+    wolfssl_hc128,                  /* wolfSSL extensions */
+    wolfssl_rabbit
+};
+
+
+/* for KDF TLS 1.2 mac types */
+enum KDF_MacAlgorithm {
+    wolfssl_sha256 = 4,     /* needs to match hash.h wc_MACAlgorithm */
+    wolfssl_sha384,
+    wolfssl_sha512
+};
+
+
+/* Public Key Callback support */
+#ifdef HAVE_PK_CALLBACKS
+#ifdef HAVE_ECC
+
+struct ecc_key;
+
+typedef int (*CallbackEccKeyGen)(WOLFSSL* ssl, struct ecc_key* key,
+    unsigned int keySz, int ecc_curve, void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetEccKeyGenCb(WOLFSSL_CTX*, CallbackEccKeyGen);
+WOLFSSL_API void  wolfSSL_SetEccKeyGenCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetEccKeyGenCtx(WOLFSSL* ssl);
+
+typedef int (*CallbackEccSign)(WOLFSSL* ssl,
+       const unsigned char* in, unsigned int inSz,
+       unsigned char* out, word32* outSz,
+       const unsigned char* keyDer, unsigned int keySz,
+       void* ctx);
+WOLFSSL_ABI WOLFSSL_API void  wolfSSL_CTX_SetEccSignCb(WOLFSSL_CTX*,
+                                                               CallbackEccSign);
+WOLFSSL_API void  wolfSSL_SetEccSignCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetEccSignCtx(WOLFSSL* ssl);
+
+typedef int (*CallbackEccVerify)(WOLFSSL* ssl,
+       const unsigned char* sig, unsigned int sigSz,
+       const unsigned char* hash, unsigned int hashSz,
+       const unsigned char* keyDer, unsigned int keySz,
+       int* result, void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetEccVerifyCb(WOLFSSL_CTX*, CallbackEccVerify);
+WOLFSSL_API void  wolfSSL_SetEccVerifyCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetEccVerifyCtx(WOLFSSL* ssl);
+
+typedef int (*CallbackEccSharedSecret)(WOLFSSL* ssl, struct ecc_key* otherKey,
+        unsigned char* pubKeyDer, word32* pubKeySz,
+        unsigned char* out, word32* outlen,
+        int side, void* ctx); /* side is WOLFSSL_CLIENT_END or WOLFSSL_SERVER_END */
+WOLFSSL_API void  wolfSSL_CTX_SetEccSharedSecretCb(WOLFSSL_CTX*, CallbackEccSharedSecret);
+WOLFSSL_API void  wolfSSL_SetEccSharedSecretCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetEccSharedSecretCtx(WOLFSSL* ssl);
+#endif
+
+#ifndef NO_DH
+/* Public DH Key Callback support */
+struct DhKey;
+typedef int (*CallbackDhAgree)(WOLFSSL* ssl, struct DhKey* key,
+        const unsigned char* priv, unsigned int privSz,
+        const unsigned char* otherPubKeyDer, unsigned int otherPubKeySz,
+        unsigned char* out, unsigned int* outlen,
+        void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetDhAgreeCb(WOLFSSL_CTX*, CallbackDhAgree);
+WOLFSSL_API void  wolfSSL_SetDhAgreeCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetDhAgreeCtx(WOLFSSL* ssl);
+#endif /* !NO_DH */
+
+#ifdef HAVE_ED25519
+struct ed25519_key;
+typedef int (*CallbackEd25519Sign)(WOLFSSL* ssl,
+       const unsigned char* in, unsigned int inSz,
+       unsigned char* out, unsigned int* outSz,
+       const unsigned char* keyDer, unsigned int keySz,
+       void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetEd25519SignCb(WOLFSSL_CTX*,
+                                               CallbackEd25519Sign);
+WOLFSSL_API void  wolfSSL_SetEd25519SignCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetEd25519SignCtx(WOLFSSL* ssl);
+
+typedef int (*CallbackEd25519Verify)(WOLFSSL* ssl,
+       const unsigned char* sig, unsigned int sigSz,
+       const unsigned char* msg, unsigned int msgSz,
+       const unsigned char* keyDer, unsigned int keySz,
+       int* result, void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetEd25519VerifyCb(WOLFSSL_CTX*,
+                                                 CallbackEd25519Verify);
+WOLFSSL_API void  wolfSSL_SetEd25519VerifyCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetEd25519VerifyCtx(WOLFSSL* ssl);
+#endif
+
+#ifdef HAVE_CURVE25519
+struct curve25519_key;
+
+typedef int (*CallbackX25519KeyGen)(WOLFSSL* ssl, struct curve25519_key* key,
+    unsigned int keySz, void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetX25519KeyGenCb(WOLFSSL_CTX*, CallbackX25519KeyGen);
+WOLFSSL_API void  wolfSSL_SetX25519KeyGenCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetX25519KeyGenCtx(WOLFSSL* ssl);
+
+typedef int (*CallbackX25519SharedSecret)(WOLFSSL* ssl,
+        struct curve25519_key* otherKey,
+        unsigned char* pubKeyDer, unsigned int* pubKeySz,
+        unsigned char* out, unsigned int* outlen,
+        int side, void* ctx);
+        /* side is WOLFSSL_CLIENT_END or WOLFSSL_SERVER_END */
+WOLFSSL_API void  wolfSSL_CTX_SetX25519SharedSecretCb(WOLFSSL_CTX*,
+        CallbackX25519SharedSecret);
+WOLFSSL_API void  wolfSSL_SetX25519SharedSecretCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetX25519SharedSecretCtx(WOLFSSL* ssl);
+#endif
+
+#ifdef HAVE_ED448
+struct ed448_key;
+typedef int (*CallbackEd448Sign)(WOLFSSL* ssl,
+       const unsigned char* in, unsigned int inSz,
+       unsigned char* out, unsigned int* outSz,
+       const unsigned char* keyDer, unsigned int keySz,
+       void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetEd448SignCb(WOLFSSL_CTX*,
+                                               CallbackEd448Sign);
+WOLFSSL_API void  wolfSSL_SetEd448SignCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetEd448SignCtx(WOLFSSL* ssl);
+
+typedef int (*CallbackEd448Verify)(WOLFSSL* ssl,
+       const unsigned char* sig, unsigned int sigSz,
+       const unsigned char* msg, unsigned int msgSz,
+       const unsigned char* keyDer, unsigned int keySz,
+       int* result, void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetEd448VerifyCb(WOLFSSL_CTX*,
+                                                 CallbackEd448Verify);
+WOLFSSL_API void  wolfSSL_SetEd448VerifyCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetEd448VerifyCtx(WOLFSSL* ssl);
+#endif
+
+#ifdef HAVE_CURVE448
+struct curve448_key;
+
+typedef int (*CallbackX448KeyGen)(WOLFSSL* ssl, struct curve448_key* key,
+    unsigned int keySz, void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetX448KeyGenCb(WOLFSSL_CTX*, CallbackX448KeyGen);
+WOLFSSL_API void  wolfSSL_SetX448KeyGenCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetX448KeyGenCtx(WOLFSSL* ssl);
+
+typedef int (*CallbackX448SharedSecret)(WOLFSSL* ssl,
+        struct curve448_key* otherKey,
+        unsigned char* pubKeyDer, unsigned int* pubKeySz,
+        unsigned char* out, unsigned int* outlen,
+        int side, void* ctx);
+        /* side is WOLFSSL_CLIENT_END or WOLFSSL_SERVER_END */
+WOLFSSL_API void  wolfSSL_CTX_SetX448SharedSecretCb(WOLFSSL_CTX*,
+        CallbackX448SharedSecret);
+WOLFSSL_API void  wolfSSL_SetX448SharedSecretCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetX448SharedSecretCtx(WOLFSSL* ssl);
+#endif
+
+#ifndef NO_RSA
+typedef int (*CallbackRsaSign)(WOLFSSL* ssl,
+       const unsigned char* in, unsigned int inSz,
+       unsigned char* out, unsigned int* outSz,
+       const unsigned char* keyDer, unsigned int keySz,
+       void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetRsaSignCb(WOLFSSL_CTX*, CallbackRsaSign);
+WOLFSSL_API void  wolfSSL_SetRsaSignCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetRsaSignCtx(WOLFSSL* ssl);
+
+typedef int (*CallbackRsaVerify)(WOLFSSL* ssl,
+       unsigned char* sig, unsigned int sigSz,
+       unsigned char** out,
+       const unsigned char* keyDer, unsigned int keySz,
+       void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetRsaVerifyCb(WOLFSSL_CTX*, CallbackRsaVerify);
+WOLFSSL_API void  wolfSSL_CTX_SetRsaSignCheckCb(WOLFSSL_CTX*, CallbackRsaVerify);
+WOLFSSL_API void  wolfSSL_SetRsaVerifyCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetRsaVerifyCtx(WOLFSSL* ssl);
+
+#ifdef WC_RSA_PSS
+typedef int (*CallbackRsaPssSign)(WOLFSSL* ssl,
+       const unsigned char* in, unsigned int inSz,
+       unsigned char* out, unsigned int* outSz,
+       int hash, int mgf,
+       const unsigned char* keyDer, unsigned int keySz,
+       void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetRsaPssSignCb(WOLFSSL_CTX*, CallbackRsaPssSign);
+WOLFSSL_API void  wolfSSL_SetRsaPssSignCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetRsaPssSignCtx(WOLFSSL* ssl);
+
+typedef int (*CallbackRsaPssVerify)(WOLFSSL* ssl,
+       unsigned char* sig, unsigned int sigSz,
+       unsigned char** out,
+       int hash, int mgf,
+       const unsigned char* keyDer, unsigned int keySz,
+       void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetRsaPssVerifyCb(WOLFSSL_CTX*,
+                                                CallbackRsaPssVerify);
+WOLFSSL_API void  wolfSSL_CTX_SetRsaPssSignCheckCb(WOLFSSL_CTX*,
+                                                    CallbackRsaPssVerify);
+WOLFSSL_API void  wolfSSL_SetRsaPssVerifyCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetRsaPssVerifyCtx(WOLFSSL* ssl);
+#endif
+
+/* RSA Public Encrypt cb */
+typedef int (*CallbackRsaEnc)(WOLFSSL* ssl,
+       const unsigned char* in, unsigned int inSz,
+       unsigned char* out, unsigned int* outSz,
+       const unsigned char* keyDer, unsigned int keySz,
+       void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetRsaEncCb(WOLFSSL_CTX*, CallbackRsaEnc);
+WOLFSSL_API void  wolfSSL_SetRsaEncCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetRsaEncCtx(WOLFSSL* ssl);
+
+/* RSA Private Decrypt cb */
+typedef int (*CallbackRsaDec)(WOLFSSL* ssl,
+       unsigned char* in, unsigned int inSz,
+       unsigned char** out,
+       const unsigned char* keyDer, unsigned int keySz,
+       void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetRsaDecCb(WOLFSSL_CTX*, CallbackRsaDec);
+WOLFSSL_API void  wolfSSL_SetRsaDecCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl);
+#endif
+#endif /* HAVE_PK_CALLBACKS */
+
+#ifndef NO_CERTS
+    WOLFSSL_API void wolfSSL_CTX_SetCACb(WOLFSSL_CTX*, CallbackCACache);
+
+    WOLFSSL_API WOLFSSL_CERT_MANAGER* wolfSSL_CTX_GetCertManager(WOLFSSL_CTX*);
+
+    WOLFSSL_API WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew_ex(void* heap);
+    WOLFSSL_API WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew(void);
+    WOLFSSL_API void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER*);
+
+    WOLFSSL_API int wolfSSL_CertManagerLoadCA(WOLFSSL_CERT_MANAGER*, const char* f,
+                                                                 const char* d);
+    WOLFSSL_API int wolfSSL_CertManagerLoadCABuffer(WOLFSSL_CERT_MANAGER*,
+                                  const unsigned char* in, long sz, int format);
+    WOLFSSL_API int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm);
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    WOLFSSL_API int wolfSSL_CertManagerUnload_trust_peers(WOLFSSL_CERT_MANAGER* cm);
+#endif
+    WOLFSSL_API int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER*, const char* f,
+                                                                    int format);
+    WOLFSSL_API int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm,
+                                const unsigned char* buff, long sz, int format);
+    WOLFSSL_API int wolfSSL_CertManagerCheckCRL(WOLFSSL_CERT_MANAGER*,
+                                                        unsigned char*, int sz);
+    WOLFSSL_API int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER*,
+                                                                   int options);
+    WOLFSSL_API int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER*);
+    WOLFSSL_API void wolfSSL_CertManagerSetVerify(WOLFSSL_CERT_MANAGER* cm,
+            VerifyCallback vc);
+    WOLFSSL_API int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER*,
+                                                         const char*, int, int);
+    WOLFSSL_API int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER*,
+                                            const unsigned char*, long sz, int);
+    WOLFSSL_API int wolfSSL_CertManagerSetCRL_Cb(WOLFSSL_CERT_MANAGER*,
+                                                                  CbMissingCRL);
+    WOLFSSL_API int wolfSSL_CertManagerFreeCRL(WOLFSSL_CERT_MANAGER *);
+#ifdef HAVE_CRL_IO
+    WOLFSSL_API int wolfSSL_CertManagerSetCRL_IOCb(WOLFSSL_CERT_MANAGER*,
+                                                                       CbCrlIO);
+#endif
+#if defined(HAVE_OCSP)
+    WOLFSSL_API int wolfSSL_CertManagerCheckOCSPResponse(WOLFSSL_CERT_MANAGER *,
+        byte *response, int responseSz, WOLFSSL_BUFFER_INFO *responseBuffer,
+        CertStatus *status, OcspEntry *entry, OcspRequest *ocspRequest);
+#endif
+    WOLFSSL_API int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER*,
+                                                        unsigned char*, int sz);
+    WOLFSSL_API int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER*,
+                                                                   int options);
+    WOLFSSL_API int wolfSSL_CertManagerDisableOCSP(WOLFSSL_CERT_MANAGER*);
+    WOLFSSL_API int wolfSSL_CertManagerSetOCSPOverrideURL(WOLFSSL_CERT_MANAGER*,
+                                                                   const char*);
+    WOLFSSL_API int wolfSSL_CertManagerSetOCSP_Cb(WOLFSSL_CERT_MANAGER*,
+                                               CbOCSPIO, CbOCSPRespFree, void*);
+
+    WOLFSSL_API int wolfSSL_CertManagerEnableOCSPStapling(
+                                                      WOLFSSL_CERT_MANAGER* cm);
+    WOLFSSL_API int wolfSSL_CertManagerDisableOCSPStapling(
+                                                      WOLFSSL_CERT_MANAGER* cm);
+#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_SIGNER_DER_CERT) && !defined(NO_FILESYSTEM)
+WOLFSSL_API WOLFSSL_STACK* wolfSSL_CertManagerGetCerts(WOLFSSL_CERT_MANAGER* cm);
+#endif
+    WOLFSSL_API int wolfSSL_EnableCRL(WOLFSSL* ssl, int options);
+    WOLFSSL_API int wolfSSL_DisableCRL(WOLFSSL* ssl);
+    WOLFSSL_API int wolfSSL_LoadCRL(WOLFSSL*, const char*, int, int);
+    WOLFSSL_API int wolfSSL_LoadCRLBuffer(WOLFSSL*,
+                                          const unsigned char*, long sz, int);
+    WOLFSSL_API int wolfSSL_SetCRL_Cb(WOLFSSL*, CbMissingCRL);
+#ifdef HAVE_CRL_IO
+    WOLFSSL_API int wolfSSL_SetCRL_IOCb(WOLFSSL* ssl, CbCrlIO cb);
+#endif
+    WOLFSSL_API int wolfSSL_EnableOCSP(WOLFSSL*, int options);
+    WOLFSSL_API int wolfSSL_DisableOCSP(WOLFSSL*);
+    WOLFSSL_API int wolfSSL_SetOCSP_OverrideURL(WOLFSSL*, const char*);
+    WOLFSSL_API int wolfSSL_SetOCSP_Cb(WOLFSSL*, CbOCSPIO, CbOCSPRespFree, void*);
+    WOLFSSL_API int wolfSSL_EnableOCSPStapling(WOLFSSL*);
+    WOLFSSL_API int wolfSSL_DisableOCSPStapling(WOLFSSL*);
+
+    WOLFSSL_API int wolfSSL_CTX_EnableCRL(WOLFSSL_CTX* ctx, int options);
+    WOLFSSL_API int wolfSSL_CTX_DisableCRL(WOLFSSL_CTX* ctx);
+    WOLFSSL_API int wolfSSL_CTX_LoadCRL(WOLFSSL_CTX*, const char*, int, int);
+    WOLFSSL_API int wolfSSL_CTX_LoadCRLBuffer(WOLFSSL_CTX*,
+                                            const unsigned char*, long sz, int);
+    WOLFSSL_API int wolfSSL_CTX_SetCRL_Cb(WOLFSSL_CTX*, CbMissingCRL);
+#ifdef HAVE_CRL_IO
+    WOLFSSL_API int wolfSSL_CTX_SetCRL_IOCb(WOLFSSL_CTX*, CbCrlIO);
+#endif
+
+    WOLFSSL_API int wolfSSL_CTX_EnableOCSP(WOLFSSL_CTX*, int options);
+    WOLFSSL_API int wolfSSL_CTX_DisableOCSP(WOLFSSL_CTX*);
+    WOLFSSL_API int wolfSSL_CTX_SetOCSP_OverrideURL(WOLFSSL_CTX*, const char*);
+    WOLFSSL_API int wolfSSL_CTX_SetOCSP_Cb(WOLFSSL_CTX*,
+                                               CbOCSPIO, CbOCSPRespFree, void*);
+    WOLFSSL_API int wolfSSL_CTX_EnableOCSPStapling(WOLFSSL_CTX*);
+    WOLFSSL_API int wolfSSL_CTX_DisableOCSPStapling(WOLFSSL_CTX*);
+#endif /* !NO_CERTS */
+
+
+#ifdef SINGLE_THREADED
+    WOLFSSL_API int wolfSSL_CTX_new_rng(WOLFSSL_CTX*);
+#endif
+
+/* end of handshake frees temporary arrays, if user needs for get_keys or
+   psk hints, call KeepArrays before handshake and then FreeArrays when done
+   if don't want to wait for object free */
+WOLFSSL_API void wolfSSL_KeepArrays(WOLFSSL*);
+WOLFSSL_API void wolfSSL_FreeArrays(WOLFSSL*);
+
+WOLFSSL_API int wolfSSL_KeepHandshakeResources(WOLFSSL* ssl);
+WOLFSSL_API int wolfSSL_FreeHandshakeResources(WOLFSSL* ssl);
+
+WOLFSSL_API int wolfSSL_CTX_UseClientSuites(WOLFSSL_CTX* ctx);
+WOLFSSL_API int wolfSSL_UseClientSuites(WOLFSSL* ssl);
+
+/* async additions */
+#define wolfSSL_UseAsync wolfSSL_SetDevId
+#define wolfSSL_CTX_UseAsync wolfSSL_CTX_SetDevId
+WOLFSSL_ABI WOLFSSL_API int wolfSSL_SetDevId(WOLFSSL*, int devId);
+WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_SetDevId(WOLFSSL_CTX*, int devId);
+
+/* helpers to get device id and heap */
+WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_GetDevId(WOLFSSL_CTX*, WOLFSSL*);
+WOLFSSL_API void* wolfSSL_CTX_GetHeap(WOLFSSL_CTX* ctx, WOLFSSL* ssl);
+
+/* TLS Extensions */
+
+/* Server Name Indication */
+#ifdef HAVE_SNI
+
+/* SNI types */
+enum {
+    WOLFSSL_SNI_HOST_NAME = 0
+};
+
+WOLFSSL_ABI WOLFSSL_API int wolfSSL_UseSNI(WOLFSSL*, unsigned char,
+                                                   const void*, unsigned short);
+WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_UseSNI(WOLFSSL_CTX*, unsigned char,
+                                                   const void*, unsigned short);
+
+#ifndef NO_WOLFSSL_SERVER
+
+/* SNI options */
+enum {
+    /* Do not abort the handshake if the requested SNI didn't match. */
+    WOLFSSL_SNI_CONTINUE_ON_MISMATCH = 0x01,
+
+    /* Behave as if the requested SNI matched in a case of mismatch.  */
+    /* In this case, the status will be set to WOLFSSL_SNI_FAKE_MATCH. */
+    WOLFSSL_SNI_ANSWER_ON_MISMATCH   = 0x02,
+
+    /* Abort the handshake if the client didn't send a SNI request. */
+    WOLFSSL_SNI_ABORT_ON_ABSENCE     = 0x04,
+};
+
+WOLFSSL_API void wolfSSL_SNI_SetOptions(WOLFSSL* ssl, unsigned char type,
+                                                         unsigned char options);
+WOLFSSL_API void wolfSSL_CTX_SNI_SetOptions(WOLFSSL_CTX* ctx,
+                                     unsigned char type, unsigned char options);
+WOLFSSL_API int wolfSSL_SNI_GetFromBuffer(
+                 const unsigned char* clientHello, unsigned int helloSz,
+                 unsigned char type, unsigned char* sni, unsigned int* inOutSz);
+
+#endif /* NO_WOLFSSL_SERVER */
+
+/* SNI status */
+enum {
+    WOLFSSL_SNI_NO_MATCH   = 0,
+    WOLFSSL_SNI_FAKE_MATCH = 1, /**< @see WOLFSSL_SNI_ANSWER_ON_MISMATCH */
+    WOLFSSL_SNI_REAL_MATCH = 2,
+    WOLFSSL_SNI_FORCE_KEEP = 3  /** Used with -DWOLFSSL_ALWAYS_KEEP_SNI */
+};
+
+WOLFSSL_API unsigned char wolfSSL_SNI_Status(WOLFSSL* ssl, unsigned char type);
+
+WOLFSSL_API unsigned short wolfSSL_SNI_GetRequest(WOLFSSL *ssl,
+                                               unsigned char type, void** data);
+
+#endif /* HAVE_SNI */
+
+/* Trusted CA Key Indication - RFC 6066 (Section 6) */
+#ifdef HAVE_TRUSTED_CA
+
+/* TCA Identifier Type */
+enum {
+    WOLFSSL_TRUSTED_CA_PRE_AGREED = 0,
+    WOLFSSL_TRUSTED_CA_KEY_SHA1 = 1,
+    WOLFSSL_TRUSTED_CA_X509_NAME = 2,
+    WOLFSSL_TRUSTED_CA_CERT_SHA1 = 3
+};
+
+WOLFSSL_API int wolfSSL_UseTrustedCA(WOLFSSL* ssl, unsigned char type,
+            const unsigned char* certId, unsigned int certIdSz);
+#endif /* HAVE_TRUSTED_CA */
+
+/* Application-Layer Protocol Negotiation */
+#ifdef HAVE_ALPN
+
+/* ALPN status code */
+enum {
+    WOLFSSL_ALPN_NO_MATCH = 0,
+    WOLFSSL_ALPN_MATCH    = 1,
+    WOLFSSL_ALPN_CONTINUE_ON_MISMATCH = 2,
+    WOLFSSL_ALPN_FAILED_ON_MISMATCH = 4,
+};
+
+enum {
+    WOLFSSL_MAX_ALPN_PROTO_NAME_LEN = 255,
+    WOLFSSL_MAX_ALPN_NUMBER = 257
+};
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+typedef int (*CallbackALPNSelect)(WOLFSSL* ssl, const unsigned char** out,
+    unsigned char* outLen, const unsigned char* in, unsigned int inLen,
+    void *arg);
+#endif
+
+WOLFSSL_ABI WOLFSSL_API int wolfSSL_UseALPN(WOLFSSL* ssl,
+                                char *protocol_name_list,
+                                unsigned int protocol_name_listSz,
+                                unsigned char options);
+
+WOLFSSL_API int wolfSSL_ALPN_GetProtocol(WOLFSSL* ssl, char **protocol_name,
+                                         unsigned short *size);
+
+WOLFSSL_API int wolfSSL_ALPN_GetPeerProtocol(WOLFSSL* ssl, char **list,
+                                             unsigned short *listSz);
+WOLFSSL_API int wolfSSL_ALPN_FreePeerProtocol(WOLFSSL* ssl, char **list);
+#endif /* HAVE_ALPN */
+
+/* Maximum Fragment Length */
+#ifdef HAVE_MAX_FRAGMENT
+
+/* Fragment lengths */
+enum {
+    WOLFSSL_MFL_2_9  = 1, /*  512 bytes */
+    WOLFSSL_MFL_2_10 = 2, /* 1024 bytes */
+    WOLFSSL_MFL_2_11 = 3, /* 2048 bytes */
+    WOLFSSL_MFL_2_12 = 4, /* 4096 bytes */
+    WOLFSSL_MFL_2_13 = 5, /* 8192 bytes *//* wolfSSL ONLY!!! */
+    WOLFSSL_MFL_2_8  = 6, /*  256 bytes *//* wolfSSL ONLY!!! */
+    WOLFSSL_MFL_MIN  = WOLFSSL_MFL_2_9,
+    WOLFSSL_MFL_MAX  = WOLFSSL_MFL_2_8,
+};
+
+#ifndef NO_WOLFSSL_CLIENT
+
+WOLFSSL_API int wolfSSL_UseMaxFragment(WOLFSSL* ssl, unsigned char mfl);
+WOLFSSL_API int wolfSSL_CTX_UseMaxFragment(WOLFSSL_CTX* ctx, unsigned char mfl);
+
+#endif
+#endif /* HAVE_MAX_FRAGMENT */
+
+/* Truncated HMAC */
+#ifdef HAVE_TRUNCATED_HMAC
+#ifndef NO_WOLFSSL_CLIENT
+
+WOLFSSL_API int wolfSSL_UseTruncatedHMAC(WOLFSSL* ssl);
+WOLFSSL_API int wolfSSL_CTX_UseTruncatedHMAC(WOLFSSL_CTX* ctx);
+
+#endif
+#endif
+
+/* Certificate Status Request */
+/* Certificate Status Type */
+enum {
+    WOLFSSL_CSR_OCSP = 1
+};
+
+/* Certificate Status Options (flags) */
+enum {
+    WOLFSSL_CSR_OCSP_USE_NONCE = 0x01
+};
+
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+#ifndef NO_WOLFSSL_CLIENT
+
+WOLFSSL_API int wolfSSL_UseOCSPStapling(WOLFSSL* ssl,
+                              unsigned char status_type, unsigned char options);
+
+WOLFSSL_API int wolfSSL_CTX_UseOCSPStapling(WOLFSSL_CTX* ctx,
+                              unsigned char status_type, unsigned char options);
+
+#endif
+#endif
+
+/* Certificate Status Request v2 */
+/* Certificate Status Type */
+enum {
+    WOLFSSL_CSR2_OCSP = 1,
+    WOLFSSL_CSR2_OCSP_MULTI = 2
+};
+
+/* Certificate Status v2 Options (flags) */
+enum {
+    WOLFSSL_CSR2_OCSP_USE_NONCE = 0x01
+};
+
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+#ifndef NO_WOLFSSL_CLIENT
+
+WOLFSSL_API int wolfSSL_UseOCSPStaplingV2(WOLFSSL* ssl,
+                              unsigned char status_type, unsigned char options);
+
+WOLFSSL_API int wolfSSL_CTX_UseOCSPStaplingV2(WOLFSSL_CTX* ctx,
+                              unsigned char status_type, unsigned char options);
+
+#endif
+#endif
+
+/* Named Groups */
+enum {
+#if 0 /* Not Supported */
+    WOLFSSL_ECC_SECT163K1 = 1,
+    WOLFSSL_ECC_SECT163R1 = 2,
+    WOLFSSL_ECC_SECT163R2 = 3,
+    WOLFSSL_ECC_SECT193R1 = 4,
+    WOLFSSL_ECC_SECT193R2 = 5,
+    WOLFSSL_ECC_SECT233K1 = 6,
+    WOLFSSL_ECC_SECT233R1 = 7,
+    WOLFSSL_ECC_SECT239K1 = 8,
+    WOLFSSL_ECC_SECT283K1 = 9,
+    WOLFSSL_ECC_SECT283R1 = 10,
+    WOLFSSL_ECC_SECT409K1 = 11,
+    WOLFSSL_ECC_SECT409R1 = 12,
+    WOLFSSL_ECC_SECT571K1 = 13,
+    WOLFSSL_ECC_SECT571R1 = 14,
+#endif
+    WOLFSSL_ECC_SECP160K1 = 15,
+    WOLFSSL_ECC_SECP160R1 = 16,
+    WOLFSSL_ECC_SECP160R2 = 17,
+    WOLFSSL_ECC_SECP192K1 = 18,
+    WOLFSSL_ECC_SECP192R1 = 19,
+    WOLFSSL_ECC_SECP224K1 = 20,
+    WOLFSSL_ECC_SECP224R1 = 21,
+    WOLFSSL_ECC_SECP256K1 = 22,
+    WOLFSSL_ECC_SECP256R1 = 23,
+    WOLFSSL_ECC_SECP384R1 = 24,
+    WOLFSSL_ECC_SECP521R1 = 25,
+    WOLFSSL_ECC_BRAINPOOLP256R1 = 26,
+    WOLFSSL_ECC_BRAINPOOLP384R1 = 27,
+    WOLFSSL_ECC_BRAINPOOLP512R1 = 28,
+    WOLFSSL_ECC_X25519    = 29,
+    WOLFSSL_ECC_X448      = 30,
+
+    WOLFSSL_FFDHE_2048    = 256,
+    WOLFSSL_FFDHE_3072    = 257,
+    WOLFSSL_FFDHE_4096    = 258,
+    WOLFSSL_FFDHE_6144    = 259,
+    WOLFSSL_FFDHE_8192    = 260,
+};
+
+enum {
+    WOLFSSL_EC_PF_UNCOMPRESSED = 0,
+#if 0 /* Not Supported */
+    WOLFSSL_EC_PF_X962_COMP_PRIME = 1,
+    WOLFSSL_EC_PF_X962_COMP_CHAR2 = 2,
+#endif
+};
+
+#ifdef HAVE_SUPPORTED_CURVES
+#ifndef NO_WOLFSSL_CLIENT
+
+WOLFSSL_API int wolfSSL_UseSupportedCurve(WOLFSSL* ssl, word16 name);
+WOLFSSL_API int wolfSSL_CTX_UseSupportedCurve(WOLFSSL_CTX* ctx,
+                                                           word16 name);
+
+#endif
+#endif
+
+#ifdef WOLFSSL_TLS13
+WOLFSSL_API int wolfSSL_UseKeyShare(WOLFSSL* ssl, word16 group);
+WOLFSSL_API int wolfSSL_NoKeyShares(WOLFSSL* ssl);
+#endif
+
+
+/* Secure Renegotiation */
+#ifdef HAVE_SECURE_RENEGOTIATION
+
+WOLFSSL_API int wolfSSL_UseSecureRenegotiation(WOLFSSL* ssl);
+WOLFSSL_API int wolfSSL_CTX_UseSecureRenegotiation(WOLFSSL_CTX* ctx);
+WOLFSSL_API int wolfSSL_StartSecureRenegotiation(WOLFSSL* ssl, int resume);
+WOLFSSL_API int wolfSSL_Rehandshake(WOLFSSL* ssl);
+WOLFSSL_API int wolfSSL_SecureResume(WOLFSSL* ssl);
+WOLFSSL_API long wolfSSL_SSL_get_secure_renegotiation_support(WOLFSSL* ssl);
+
+#endif
+
+/* Session Ticket */
+#ifdef HAVE_SESSION_TICKET
+
+#ifndef NO_WOLFSSL_CLIENT
+WOLFSSL_API int wolfSSL_UseSessionTicket(WOLFSSL* ssl);
+WOLFSSL_API int wolfSSL_CTX_UseSessionTicket(WOLFSSL_CTX* ctx);
+WOLFSSL_API int wolfSSL_get_SessionTicket(WOLFSSL*, unsigned char*, word32*);
+WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL*, const unsigned char*, word32);
+typedef int (*CallbackSessionTicket)(WOLFSSL*, const unsigned char*, int, void*);
+WOLFSSL_API int wolfSSL_set_SessionTicket_cb(WOLFSSL*,
+                                                  CallbackSessionTicket, void*);
+#endif /* NO_WOLFSSL_CLIENT */
+
+
+#define WOLFSSL_TICKET_NAME_SZ 16
+#define WOLFSSL_TICKET_IV_SZ   16
+#define WOLFSSL_TICKET_MAC_SZ  32
+
+enum TicketEncRet {
+    WOLFSSL_TICKET_RET_FATAL  = -1,  /* fatal error, don't use ticket */
+    WOLFSSL_TICKET_RET_OK     =  0,  /* ok, use ticket */
+    WOLFSSL_TICKET_RET_REJECT,       /* don't use ticket, but not fatal */
+    WOLFSSL_TICKET_RET_CREATE        /* existing ticket ok and create new one */
+};
+
+#ifndef NO_WOLFSSL_SERVER
+
+typedef int (*SessionTicketEncCb)(WOLFSSL*,
+                                 unsigned char key_name[WOLFSSL_TICKET_NAME_SZ],
+                                 unsigned char iv[WOLFSSL_TICKET_IV_SZ],
+                                 unsigned char mac[WOLFSSL_TICKET_MAC_SZ],
+                                 int enc, unsigned char*, int, int*, void*);
+WOLFSSL_API int wolfSSL_CTX_set_TicketEncCb(WOLFSSL_CTX* ctx,
+                                            SessionTicketEncCb);
+WOLFSSL_API int wolfSSL_CTX_set_TicketHint(WOLFSSL_CTX* ctx, int);
+WOLFSSL_API int wolfSSL_CTX_set_TicketEncCtx(WOLFSSL_CTX* ctx, void*);
+
+#endif /* NO_WOLFSSL_SERVER */
+
+#endif /* HAVE_SESSION_TICKET */
+
+#ifdef HAVE_QSH
+/* Quantum-safe Crypto Schemes */
+enum {
+    WOLFSSL_NTRU_EESS439 = 0x0101, /* max plaintext length of 65  */
+    WOLFSSL_NTRU_EESS593 = 0x0102, /* max plaintext length of 86  */
+    WOLFSSL_NTRU_EESS743 = 0x0103, /* max plaintext length of 106 */
+    WOLFSSL_LWE_XXX  = 0x0201,     /* Learning With Error encryption scheme */
+    WOLFSSL_HFE_XXX  = 0x0301,     /* Hidden Field Equation scheme */
+    WOLFSSL_NULL_QSH = 0xFFFF      /* QSHScheme is not used */
+};
+
+
+/* test if the connection is using a QSH secure connection return 1 if so */
+WOLFSSL_API int wolfSSL_isQSH(WOLFSSL* ssl);
+WOLFSSL_API int wolfSSL_UseSupportedQSH(WOLFSSL* ssl, unsigned short name);
+#ifndef NO_WOLFSSL_CLIENT
+    /* user control over sending client public key in hello
+       when flag = 1 will send keys if flag is 0 or function is not called
+       then will not send keys in the hello extension */
+    WOLFSSL_API int wolfSSL_UseClientQSHKeys(WOLFSSL* ssl, unsigned char flag);
+#endif
+
+#endif /* QSH */
+
+/* TLS Extended Master Secret Extension */
+WOLFSSL_API int wolfSSL_DisableExtendedMasterSecret(WOLFSSL* ssl);
+WOLFSSL_API int wolfSSL_CTX_DisableExtendedMasterSecret(WOLFSSL_CTX* ctx);
+
+
+#define WOLFSSL_CRL_MONITOR   0x01   /* monitor this dir flag */
+#define WOLFSSL_CRL_START_MON 0x02   /* start monitoring flag */
+
+
+/* notify user the handshake is done */
+typedef int (*HandShakeDoneCb)(WOLFSSL*, void*);
+WOLFSSL_API int wolfSSL_SetHsDoneCb(WOLFSSL*, HandShakeDoneCb, void*);
+
+
+WOLFSSL_API int wolfSSL_PrintSessionStats(void);
+WOLFSSL_API int wolfSSL_get_session_stats(unsigned int* active,
+                                          unsigned int* total,
+                                          unsigned int* peak,
+                                          unsigned int* maxSessions);
+/* External facing KDF */
+WOLFSSL_API
+int wolfSSL_MakeTlsMasterSecret(unsigned char* ms, word32 msLen,
+                               const unsigned char* pms, word32 pmsLen,
+                               const unsigned char* cr, const unsigned char* sr,
+                               int tls1_2, int hash_type);
+
+WOLFSSL_API
+int wolfSSL_MakeTlsExtendedMasterSecret(unsigned char* ms, word32 msLen,
+                              const unsigned char* pms, word32 pmsLen,
+                              const unsigned char* sHash, word32 sHashLen,
+                              int tls1_2, int hash_type);
+
+WOLFSSL_API
+int wolfSSL_DeriveTlsKeys(unsigned char* key_data, word32 keyLen,
+                               const unsigned char* ms, word32 msLen,
+                               const unsigned char* sr, const unsigned char* cr,
+                               int tls1_2, int hash_type);
+
+#ifdef WOLFSSL_CALLBACKS
+
+typedef int (*HandShakeCallBack)(HandShakeInfo*);
+typedef int (*TimeoutCallBack)(TimeoutInfo*);
+
+/* wolfSSL connect extension allowing HandShakeCallBack and/or TimeoutCallBack
+   for diagnostics */
+WOLFSSL_API int wolfSSL_connect_ex(WOLFSSL*, HandShakeCallBack, TimeoutCallBack,
+                                 WOLFSSL_TIMEVAL);
+WOLFSSL_API int wolfSSL_accept_ex(WOLFSSL*, HandShakeCallBack, TimeoutCallBack,
+                                WOLFSSL_TIMEVAL);
+
+#endif /* WOLFSSL_CALLBACKS */
+
+
+#ifdef WOLFSSL_HAVE_WOLFSCEP
+    WOLFSSL_API void wolfSSL_wolfSCEP(void);
+#endif /* WOLFSSL_HAVE_WOLFSCEP */
+
+#ifdef WOLFSSL_HAVE_CERT_SERVICE
+    WOLFSSL_API void wolfSSL_cert_service(void);
+#endif
+
+#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+/* Smaller subset of X509 compatibility functions. Avoid increasing the size of
+ * this subset and its memory usage */
+
+#include <wolfssl/openssl/asn1.h>
+struct WOLFSSL_X509_NAME_ENTRY {
+    WOLFSSL_ASN1_OBJECT  object;  /* static object just for keeping grp, type */
+    WOLFSSL_ASN1_STRING  data;
+    WOLFSSL_ASN1_STRING* value;  /* points to data, for lighttpd port */
+    int nid; /* i.e. ASN_COMMON_NAME */
+    int set;
+    int size;
+};
+
+WOLFSSL_API int wolfSSL_X509_NAME_get_index_by_OBJ(WOLFSSL_X509_NAME *name,
+                                                   const WOLFSSL_ASN1_OBJECT *obj,
+                                                   int idx);
+
+#endif /* OPENSSL_ALL || OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
+
+enum {
+    WOLFSSL_SYS_ACCEPT = 0,
+    WOLFSSL_SYS_BIND,
+    WOLFSSL_SYS_CONNECT,
+    WOLFSSL_SYS_FOPEN,
+    WOLFSSL_SYS_FREAD,
+    WOLFSSL_SYS_GETADDRINFO,
+    WOLFSSL_SYS_GETSOCKOPT,
+    WOLFSSL_SYS_GETSOCKNAME,
+    WOLFSSL_SYS_GETHOSTBYNAME,
+    WOLFSSL_SYS_GETNAMEINFO,
+    WOLFSSL_SYS_GETSERVBYNAME,
+    WOLFSSL_SYS_IOCTLSOCKET,
+    WOLFSSL_SYS_LISTEN,
+    WOLFSSL_SYS_OPENDIR,
+    WOLFSSL_SYS_SETSOCKOPT,
+    WOLFSSL_SYS_SOCKET
+};
+
+/* Object functions */
+WOLFSSL_API const char* wolfSSL_OBJ_nid2sn(int n);
+WOLFSSL_API int wolfSSL_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o);
+WOLFSSL_API int wolfSSL_OBJ_get_type(const WOLFSSL_ASN1_OBJECT *o);
+WOLFSSL_API int wolfSSL_OBJ_sn2nid(const char *sn);
+
+WOLFSSL_API const char* wolfSSL_OBJ_nid2ln(int n);
+WOLFSSL_API int wolfSSL_OBJ_ln2nid(const char *ln);
+WOLFSSL_API int wolfSSL_OBJ_cmp(const WOLFSSL_ASN1_OBJECT* a,
+            const WOLFSSL_ASN1_OBJECT* b);
+WOLFSSL_API int wolfSSL_OBJ_txt2nid(const char *sn);
+WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_txt2obj(const char* s, int no_name);
+
+WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_nid2obj(int n);
+WOLFSSL_LOCAL WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_nid2obj_ex(int n, WOLFSSL_ASN1_OBJECT *arg_obj);
+WOLFSSL_API int wolfSSL_OBJ_obj2txt(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a, int no_name);
+
+WOLFSSL_API void wolfSSL_OBJ_cleanup(void);
+WOLFSSL_API int wolfSSL_OBJ_create(const char *oid, const char *sn, const char *ln);
+#ifdef HAVE_ECC
+WOLFSSL_LOCAL int NIDToEccEnum(int n);
+#endif
+/* end of object functions */
+
+WOLFSSL_API unsigned long wolfSSL_ERR_peek_last_error_line(const char **file, int *line);
+WOLFSSL_API long wolfSSL_ctrl(WOLFSSL* ssl, int cmd, long opt, void* pt);
+WOLFSSL_API long wolfSSL_CTX_ctrl(WOLFSSL_CTX* ctx, int cmd, long opt,void* pt);
+WOLFSSL_API long wolfSSL_CTX_callback_ctrl(WOLFSSL_CTX* ctx, int cmd, void (*fp)(void));
+WOLFSSL_API long wolfSSL_CTX_clear_extra_chain_certs(WOLFSSL_CTX* ctx);
+
+#ifndef NO_CERTS
+WOLFSSL_API WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_create_by_NID(
+            WOLFSSL_X509_NAME_ENTRY** out, int nid, int type,
+            const unsigned char* data, int dataSz);
+WOLFSSL_API WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_create_by_txt(
+            WOLFSSL_X509_NAME_ENTRY **neIn, const char *txt, int format,
+            const unsigned char *data, int dataSz);
+WOLFSSL_API int wolfSSL_X509_NAME_add_entry(WOLFSSL_X509_NAME* name,
+                              WOLFSSL_X509_NAME_ENTRY* entry, int idx, int set);
+WOLFSSL_API int wolfSSL_X509_NAME_add_entry_by_txt(WOLFSSL_X509_NAME *name,
+    const char *field, int type, const unsigned char *bytes, int len, int loc,
+    int set);
+WOLFSSL_API int wolfSSL_X509_NAME_add_entry_by_NID(WOLFSSL_X509_NAME *name, int nid,
+                                           int type, const unsigned char *bytes,
+                                           int len, int loc, int set);
+WOLFSSL_API int wolfSSL_X509_NAME_cmp(const WOLFSSL_X509_NAME* x,
+            const WOLFSSL_X509_NAME* y);
+WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_X509_NAME_new(void);
+WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509*);
+WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_X509_NAME_dup(WOLFSSL_X509_NAME*);
+WOLFSSL_API int wolfSSL_check_private_key(const WOLFSSL* ssl);
+WOLFSSL_API void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509,
+                                                     int nid, int* c, int* idx);
+WOLFSSL_API int wolfSSL_X509_get_ext_count(const WOLFSSL_X509* passedCert);
+WOLFSSL_API int wolfSSL_X509_get_ext_by_NID(const WOLFSSL_X509 *x, int nid, int lastpos);
+WOLFSSL_API int wolfSSL_X509_add_ext(WOLFSSL_X509 *x, WOLFSSL_X509_EXTENSION *ex, int loc);
+WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_X509V3_EXT_conf_nid(
+        WOLF_LHASH_OF(CONF_VALUE)* conf, WOLFSSL_X509V3_CTX* ctx, int nid,
+        char* value);
+WOLFSSL_API void wolfSSL_X509V3_set_ctx(WOLFSSL_X509V3_CTX* ctx,
+        WOLFSSL_X509* issuer, WOLFSSL_X509* subject, WOLFSSL_X509* req,
+        WOLFSSL_X509_CRL* crl, int flag);
+WOLFSSL_API void wolfSSL_X509V3_set_ctx_nodb(WOLFSSL_X509V3_CTX* ctx);
+WOLFSSL_API int wolfSSL_X509_digest(const WOLFSSL_X509* x509,
+        const WOLFSSL_EVP_MD* digest, unsigned char* buf, unsigned int* len);
+WOLFSSL_API int wolfSSL_use_certificate(WOLFSSL* ssl, WOLFSSL_X509* x509);
+WOLFSSL_API int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey);
+WOLFSSL_API int wolfSSL_use_PrivateKey_ASN1(int pri, WOLFSSL* ssl,
+                                            const unsigned char* der, long derSz);
+WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_get_privatekey(const WOLFSSL *ssl);
+#ifndef NO_RSA
+WOLFSSL_API int wolfSSL_use_RSAPrivateKey_ASN1(WOLFSSL* ssl, unsigned char* der,
+                                                                long derSz);
+#endif
+WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_ASN1(int pri, WOLFSSL_CTX* ctx,
+                                            unsigned char* der, long derSz);
+
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+WOLFSSL_API int wolfSSL_X509_cmp(const WOLFSSL_X509* a, const WOLFSSL_X509* b);
+WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_X509_get_ext(const WOLFSSL_X509* x, int loc);
+WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x, int loc);
+WOLFSSL_API int wolfSSL_X509_EXTENSION_get_critical(const WOLFSSL_X509_EXTENSION* ex);
+WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_X509_EXTENSION_new(void);
+WOLFSSL_API int wolfSSL_sk_X509_EXTENSION_push(WOLFSSL_STACK* sk,
+                                       WOLFSSL_X509_EXTENSION* ext);
+WOLFSSL_API void wolfSSL_sk_X509_EXTENSION_free(WOLFSSL_STACK* sk);
+WOLFSSL_API void wolfSSL_X509_EXTENSION_free(WOLFSSL_X509_EXTENSION* ext_to_free);
+WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_new_x509_ext(void);
+#endif
+
+WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_X509_EXTENSION_get_object(WOLFSSL_X509_EXTENSION* ext);
+WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_X509_EXTENSION_get_data(WOLFSSL_X509_EXTENSION* ext);
+#endif /* NO_CERTS */
+
+WOLFSSL_API WOLFSSL_DH *wolfSSL_DSA_dup_DH(const WOLFSSL_DSA *r);
+
+WOLFSSL_API int wolfSSL_SESSION_get_master_key(const WOLFSSL_SESSION* ses,
+        unsigned char* out, int outSz);
+WOLFSSL_API int wolfSSL_SESSION_get_master_key_length(const WOLFSSL_SESSION* ses);
+
+WOLFSSL_API void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx,
+                                                       WOLFSSL_X509_STORE* str);
+WOLFSSL_API int wolfSSL_i2d_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509* x509);
+#if !defined(NO_FILESYSTEM)
+WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509_fp(XFILE fp,
+                                               WOLFSSL_X509** x509);
+WOLFSSL_API WOLFSSL_STACK* wolfSSL_X509_STORE_GetCerts(WOLFSSL_X509_STORE_CTX* s);
+#endif
+WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509_bio(WOLFSSL_BIO* bio,
+                                               WOLFSSL_X509** x509);
+WOLFSSL_API WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(WOLFSSL_CTX* ctx);
+
+WOLFSSL_API size_t wolfSSL_BIO_wpending(const WOLFSSL_BIO *bio);
+WOLFSSL_API size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *b);
+
+WOLFSSL_API size_t wolfSSL_get_server_random(const WOLFSSL *ssl,
+                                             unsigned char *out, size_t outlen);
+WOLFSSL_API int wolfSSL_get_server_tmp_key(const WOLFSSL*, WOLFSSL_EVP_PKEY**);
+
+WOLFSSL_API int wolfSSL_CTX_set_min_proto_version(WOLFSSL_CTX*, int);
+WOLFSSL_API int wolfSSL_CTX_set_max_proto_version(WOLFSSL_CTX*, int);
+
+WOLFSSL_API size_t wolfSSL_get_client_random(const WOLFSSL* ssl,
+                                              unsigned char* out, size_t outSz);
+WOLFSSL_API int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey);
+WOLFSSL_API WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u);
+WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_PEM_read_bio_X509_CRL(WOLFSSL_BIO *bp,
+        WOLFSSL_X509_CRL **x, pem_password_cb *cb, void *u);
+WOLFSSL_API WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509_AUX
+        (WOLFSSL_BIO *bp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u);
+WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_INFO)* wolfSSL_PEM_X509_INFO_read_bio(
+        WOLFSSL_BIO* bio, WOLF_STACK_OF(WOLFSSL_X509_INFO)* sk,
+        pem_password_cb* cb, void* u);
+#ifndef NO_FILESYSTEM
+WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_PEM_read_X509_CRL(XFILE fp,
+        WOLFSSL_X509_CRL **x, pem_password_cb *cb, void *u);
+#endif
+WOLFSSL_API int wolfSSL_PEM_get_EVP_CIPHER_INFO(char* header,
+                                                EncryptedInfo* cipher);
+WOLFSSL_API int wolfSSL_PEM_do_header(EncryptedInfo* cipher,
+                                      unsigned char* data, long* len,
+                                      pem_password_cb* callback, void* ctx);
+
+/*lighttp compatibility */
+
+struct WOLFSSL_ASN1_BIT_STRING {
+    int length;
+    int type;
+    byte* data;
+    long flags;
+};
+
+
+#if    defined(OPENSSL_EXTRA) \
+    || defined(OPENSSL_ALL) \
+    || defined(HAVE_LIGHTY) \
+    || defined(WOLFSSL_MYSQL_COMPATIBLE) \
+    || defined(HAVE_STUNNEL) \
+    || defined(WOLFSSL_NGINX) \
+    || defined(WOLFSSL_HAPROXY)
+WOLFSSL_API void wolfSSL_X509_NAME_ENTRY_free(WOLFSSL_X509_NAME_ENTRY* ne);
+WOLFSSL_API WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_new(void);
+WOLFSSL_API void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME* name);
+WOLFSSL_API char wolfSSL_CTX_use_certificate(WOLFSSL_CTX*, WOLFSSL_X509*);
+WOLFSSL_API int wolfSSL_CTX_add1_chain_cert(WOLFSSL_CTX*, WOLFSSL_X509*);
+WOLFSSL_API int wolfSSL_BIO_read_filename(WOLFSSL_BIO *b, const char *name);
+/* These are to be merged shortly */
+WOLFSSL_API void wolfSSL_set_verify_depth(WOLFSSL *ssl,int depth);
+WOLFSSL_API void* wolfSSL_get_app_data( const WOLFSSL *ssl);
+WOLFSSL_API int wolfSSL_set_app_data(WOLFSSL *ssl, void *arg);
+WOLFSSL_API WOLFSSL_ASN1_OBJECT * wolfSSL_X509_NAME_ENTRY_get_object(WOLFSSL_X509_NAME_ENTRY *ne);
+WOLFSSL_API WOLFSSL_X509_NAME_ENTRY *wolfSSL_X509_NAME_get_entry(WOLFSSL_X509_NAME *name, int loc);
+WOLFSSL_API unsigned char *wolfSSL_SHA1(const unsigned char *d, size_t n, unsigned char *md);
+WOLFSSL_API unsigned char *wolfSSL_SHA256(const unsigned char *d, size_t n, unsigned char *md);
+WOLFSSL_API unsigned char *wolfSSL_SHA384(const unsigned char *d, size_t n, unsigned char *md);
+WOLFSSL_API unsigned char *wolfSSL_SHA512(const unsigned char *d, size_t n, unsigned char *md);
+WOLFSSL_API int wolfSSL_X509_check_private_key(WOLFSSL_X509*, WOLFSSL_EVP_PKEY*);
+WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list( WOLF_STACK_OF(WOLFSSL_X509_NAME) *sk );
+WOLFSSL_API int wolfSSL_X509_check_ca(WOLFSSL_X509 *x509);
+
+#ifndef NO_FILESYSTEM
+WOLFSSL_API long wolfSSL_BIO_set_fp(WOLFSSL_BIO *bio, XFILE fp, int c);
+WOLFSSL_API long wolfSSL_BIO_get_fp(WOLFSSL_BIO *bio, XFILE* fp);
+WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new_fp(XFILE fp, int c);
+#endif
+
+#endif /* OPENSSL_EXTRA || OPENSSL_ALL || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
+
+#endif /* OPENSSL_EXTRA || OPENSSL_ALL */
+
+
+#if defined(OPENSSL_ALL) \
+    || defined(HAVE_STUNNEL) \
+    || defined(HAVE_LIGHTY) \
+    || defined(WOLFSSL_MYSQL_COMPATIBLE) \
+    || defined(WOLFSSL_HAPROXY) \
+    || defined(OPENSSL_EXTRA)
+
+WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new_file(const char *filename, const char *mode);
+WOLFSSL_API long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX*, WOLFSSL_DH*);
+WOLFSSL_API WOLFSSL_DH *wolfSSL_PEM_read_bio_DHparams(WOLFSSL_BIO *bp,
+    WOLFSSL_DH **x, pem_password_cb *cb, void *u);
+WOLFSSL_API WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSAparams(WOLFSSL_BIO *bp,
+    WOLFSSL_DSA **x, pem_password_cb *cb, void *u);
+WOLFSSL_API int wolfSSL_PEM_write_bio_X509_REQ(WOLFSSL_BIO *bp,WOLFSSL_X509 *x);
+WOLFSSL_API int wolfSSL_PEM_write_bio_X509_AUX(WOLFSSL_BIO *bp,WOLFSSL_X509 *x);
+WOLFSSL_API int wolfSSL_PEM_write_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 *x);
+#endif /* HAVE_STUNNEL || HAVE_LIGHTY */
+
+#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && defined(WOLFSSL_CERT_GEN) && \
+                                                       defined(WOLFSSL_CERT_REQ)
+WOLFSSL_API int wolfSSL_i2d_X509_REQ(WOLFSSL_X509* req, unsigned char** out);
+WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_REQ_new(void);
+WOLFSSL_API void wolfSSL_X509_REQ_free(WOLFSSL_X509* req);
+WOLFSSL_API int wolfSSL_X509_REQ_sign(WOLFSSL_X509 *req, WOLFSSL_EVP_PKEY *pkey,
+                                      const WOLFSSL_EVP_MD *md);
+WOLFSSL_API int wolfSSL_X509_REQ_add_extensions(WOLFSSL_X509* req,
+        WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* ext);
+WOLFSSL_API int wolfSSL_X509_REQ_set_subject_name(WOLFSSL_X509 *req,
+                                                  WOLFSSL_X509_NAME *name);
+WOLFSSL_API int wolfSSL_X509_REQ_set_pubkey(WOLFSSL_X509 *req,
+                                            WOLFSSL_EVP_PKEY *pkey);
+#endif
+
+
+#if defined(OPENSSL_ALL) \
+    || defined(HAVE_STUNNEL) \
+    || defined(WOLFSSL_NGINX) \
+    || defined(WOLFSSL_HAPROXY) \
+    || defined(OPENSSL_EXTRA) \
+    || defined(HAVE_LIGHTY)
+
+#include <wolfssl/openssl/crypto.h>
+
+/* SNI received callback type */
+typedef int (*CallbackSniRecv)(WOLFSSL *ssl, int *ret, void* exArg);
+
+WOLFSSL_API int wolfSSL_CRYPTO_set_mem_ex_functions(void *(*m) (size_t, const char *, int),
+    void *(*r) (void *, size_t, const char *, int), void (*f) (void *));
+
+WOLFSSL_API void wolfSSL_CRYPTO_cleanup_all_ex_data(void);
+
+WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_DH_768_prime(WOLFSSL_BIGNUM* bn);
+WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_DH_1024_prime(WOLFSSL_BIGNUM* bn);
+WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_DH_1536_prime(WOLFSSL_BIGNUM* bn);
+WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_DH_2048_prime(WOLFSSL_BIGNUM* bn);
+WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_DH_3072_prime(WOLFSSL_BIGNUM* bn);
+WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_DH_4096_prime(WOLFSSL_BIGNUM* bn);
+WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_DH_6144_prime(WOLFSSL_BIGNUM* bn);
+WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_DH_8192_prime(WOLFSSL_BIGNUM* bn);
+
+WOLFSSL_API WOLFSSL_DH *wolfSSL_DH_generate_parameters(int prime_len, int generator,
+    void (*callback) (int, int, void *), void *cb_arg);
+
+WOLFSSL_API int wolfSSL_DH_generate_parameters_ex(WOLFSSL_DH*, int, int,
+                           void (*callback) (int, int, void *));
+
+WOLFSSL_API void wolfSSL_ERR_load_crypto_strings(void);
+
+WOLFSSL_API unsigned long wolfSSL_ERR_peek_last_error(void);
+
+WOLFSSL_API int wolfSSL_FIPS_mode(void);
+
+WOLFSSL_API int wolfSSL_FIPS_mode_set(int r);
+
+WOLFSSL_API int wolfSSL_RAND_set_rand_method(const void *meth);
+
+WOLFSSL_API int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits);
+
+WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_X509_new(void);
+WOLFSSL_API int wolfSSL_sk_X509_num(const WOLF_STACK_OF(WOLFSSL_X509) *s);
+
+WOLFSSL_API WOLFSSL_X509_INFO *wolfSSL_X509_INFO_new(void);
+WOLFSSL_API void wolfSSL_X509_INFO_free(WOLFSSL_X509_INFO* info);
+
+WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_X509_INFO_new_null(void);
+WOLFSSL_API int wolfSSL_sk_X509_INFO_num(const WOLF_STACK_OF(WOLFSSL_X509_INFO)*);
+WOLFSSL_API WOLFSSL_X509_INFO* wolfSSL_sk_X509_INFO_value(
+    const WOLF_STACK_OF(WOLFSSL_X509_INFO)*, int);
+WOLFSSL_API int wolfSSL_sk_X509_INFO_push(WOLF_STACK_OF(WOLFSSL_X509_INFO)*,
+    WOLFSSL_X509_INFO*);
+WOLFSSL_API WOLFSSL_X509_INFO* wolfSSL_sk_X509_INFO_pop(WOLF_STACK_OF(WOLFSSL_X509_INFO)*);
+WOLFSSL_API void wolfSSL_sk_X509_INFO_pop_free(WOLF_STACK_OF(WOLFSSL_X509_INFO)*,
+    void (*f) (WOLFSSL_X509_INFO*));
+WOLFSSL_API void wolfSSL_sk_X509_INFO_free(WOLF_STACK_OF(WOLFSSL_X509_INFO)*);
+
+typedef int (*wolf_sk_compare_cb)(const void* const *a,
+                                  const void* const *b);
+WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_sk_X509_NAME_new(
+    wolf_sk_compare_cb);
+WOLFSSL_API int wolfSSL_sk_X509_NAME_push(WOLF_STACK_OF(WOLFSSL_X509_NAME)*,
+    WOLFSSL_X509_NAME*);
+WOLFSSL_API int wolfSSL_sk_X509_NAME_find(const WOLF_STACK_OF(WOLFSSL_X509_NAME)*,
+    WOLFSSL_X509_NAME*);
+WOLFSSL_API int wolfSSL_sk_X509_NAME_set_cmp_func(
+    WOLF_STACK_OF(WOLFSSL_X509_NAME)*, wolf_sk_compare_cb);
+WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_sk_X509_NAME_value(const WOLF_STACK_OF(WOLFSSL_X509_NAME)*, int);
+WOLFSSL_API int wolfSSL_sk_X509_NAME_num(const WOLF_STACK_OF(WOLFSSL_X509_NAME)*);
+WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_sk_X509_NAME_pop(WOLF_STACK_OF(WOLFSSL_X509_NAME)*);
+WOLFSSL_API void wolfSSL_sk_X509_NAME_pop_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)*,
+    void (*f) (WOLFSSL_X509_NAME*));
+WOLFSSL_API void wolfSSL_sk_X509_NAME_free(WOLF_STACK_OF(WOLFSSL_X509_NAME) *);
+
+WOLFSSL_API int wolfSSL_sk_X509_OBJECT_num(const WOLF_STACK_OF(WOLFSSL_X509_OBJECT) *s);
+
+WOLFSSL_API int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO*,WOLFSSL_X509_NAME*,int,
+        unsigned long);
+
+WOLFSSL_API WOLFSSL_ASN1_BIT_STRING* wolfSSL_ASN1_BIT_STRING_new(void);
+WOLFSSL_API void wolfSSL_ASN1_BIT_STRING_free(WOLFSSL_ASN1_BIT_STRING*);
+WOLFSSL_API WOLFSSL_ASN1_BIT_STRING* wolfSSL_X509_get0_pubkey_bitstr(
+                            const WOLFSSL_X509*);
+WOLFSSL_API int wolfSSL_ASN1_BIT_STRING_get_bit(
+                            const WOLFSSL_ASN1_BIT_STRING*, int);
+WOLFSSL_API int wolfSSL_ASN1_BIT_STRING_set_bit(
+                            WOLFSSL_ASN1_BIT_STRING*, int, int);
+
+WOLFSSL_API int        wolfSSL_CTX_add_session(WOLFSSL_CTX*, WOLFSSL_SESSION*);
+
+WOLFSSL_API int  wolfSSL_version(WOLFSSL*);
+
+WOLFSSL_API int wolfSSL_get_state(const WOLFSSL*);
+
+WOLFSSL_API WOLFSSL_X509* wolfSSL_sk_X509_value(WOLF_STACK_OF(WOLFSSL_X509)*, int);
+
+WOLFSSL_API WOLFSSL_X509* wolfSSL_sk_X509_shift(WOLF_STACK_OF(WOLFSSL_X509)*);
+
+WOLFSSL_API void* wolfSSL_sk_X509_OBJECT_value(WOLF_STACK_OF(WOLFSSL_X509_OBJECT)*, int);
+
+WOLFSSL_API void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION*, int);
+
+WOLFSSL_API int   wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION*, int, void*);
+
+WOLFSSL_API int wolfSSL_SESSION_get_ex_new_index(long,void*,void*,void*,
+        CRYPTO_free_func*);
+
+WOLFSSL_API int wolfSSL_X509_NAME_get_sz(WOLFSSL_X509_NAME*);
+
+
+WOLFSSL_API const unsigned char* wolfSSL_SESSION_get_id(WOLFSSL_SESSION*,
+        unsigned int*);
+
+WOLFSSL_API int wolfSSL_SESSION_print(WOLFSSL_BIO*, const WOLFSSL_SESSION*);
+
+WOLFSSL_API int wolfSSL_set_tlsext_host_name(WOLFSSL *, const char *);
+
+WOLFSSL_API const char* wolfSSL_get_servername(WOLFSSL *, unsigned char);
+
+WOLFSSL_API WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL*,WOLFSSL_CTX*);
+
+WOLFSSL_API VerifyCallback wolfSSL_CTX_get_verify_callback(WOLFSSL_CTX*);
+
+WOLFSSL_API VerifyCallback wolfSSL_get_verify_callback(WOLFSSL*);
+
+WOLFSSL_API void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX *,
+        CallbackSniRecv);
+WOLFSSL_API int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX *,
+        CallbackSniRecv);
+
+WOLFSSL_API int  wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX *, void*);
+
+WOLFSSL_API void wolfSSL_ERR_remove_thread_state(void*);
+
+/* support for deprecated old name */
+#define WOLFSSL_ERR_remove_thread_state wolfSSL_ERR_remove_thread_state
+
+#ifndef NO_FILESYSTEM
+WOLFSSL_API void wolfSSL_print_all_errors_fp(XFILE fp);
+#endif
+
+WOLFSSL_API void wolfSSL_THREADID_set_callback(void (*threadid_func)(void*));
+
+WOLFSSL_API void wolfSSL_THREADID_set_numeric(void* id, unsigned long val);
+
+WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs(
+                               WOLFSSL_X509_STORE_CTX*, WOLFSSL_X509_NAME*);
+WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_OBJECT)*
+        wolfSSL_X509_STORE_get0_objects(WOLFSSL_X509_STORE *);
+WOLFSSL_API WOLFSSL_X509_OBJECT*
+        wolfSSL_sk_X509_OBJECT_delete(WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* sk, int i);
+WOLFSSL_API void wolfSSL_X509_OBJECT_free(WOLFSSL_X509_OBJECT *a);
+
+WOLFSSL_API void wolfSSL_sk_X509_pop_free(WOLF_STACK_OF(WOLFSSL_X509)* sk, void (*f) (WOLFSSL_X509*));
+#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || HAVE_LIGHTY */
+
+#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC)
+WOLFSSL_API int wolfSSL_CTX_set1_curves_list(WOLFSSL_CTX* ctx, const char* names);
+WOLFSSL_API int wolfSSL_set1_curves_list(WOLFSSL* ssl, const char* names);
+#endif /* OPENSSL_EXTRA && HAVE_ECC */
+
+#if defined(OPENSSL_ALL) || \
+    defined(HAVE_STUNNEL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \
+    defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+
+WOLFSSL_API int wolfSSL_CTX_get_verify_mode(WOLFSSL_CTX* ctx);
+
+#endif
+
+#ifdef WOLFSSL_JNI
+WOLFSSL_API int wolfSSL_set_jobject(WOLFSSL* ssl, void* objPtr);
+WOLFSSL_API void* wolfSSL_get_jobject(WOLFSSL* ssl);
+#endif /* WOLFSSL_JNI */
+
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+WOLFSSL_API int wolfSSL_AsyncPoll(WOLFSSL* ssl, WOLF_EVENT_FLAG flags);
+WOLFSSL_API int wolfSSL_CTX_AsyncPoll(WOLFSSL_CTX* ctx, WOLF_EVENT** events, int maxEvents,
+    WOLF_EVENT_FLAG flags, int* eventCount);
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+#ifdef OPENSSL_EXTRA
+typedef void (*SSL_Msg_Cb)(int write_p, int version, int content_type,
+    const void *buf, size_t len, WOLFSSL *ssl, void *arg);
+
+WOLFSSL_API int wolfSSL_CTX_set_msg_callback(WOLFSSL_CTX *ctx, SSL_Msg_Cb cb);
+WOLFSSL_API int wolfSSL_set_msg_callback(WOLFSSL *ssl, SSL_Msg_Cb cb);
+WOLFSSL_API int wolfSSL_CTX_set_msg_callback_arg(WOLFSSL_CTX *ctx, void* arg);
+WOLFSSL_API int wolfSSL_set_msg_callback_arg(WOLFSSL *ssl, void* arg);
+WOLFSSL_API unsigned long wolfSSL_ERR_peek_error_line_data(const char **file,
+    int *line, const char **data, int *flags);
+WOLFSSL_API int wolfSSL_CTX_set_alpn_protos(WOLFSSL_CTX *ctx,
+    const unsigned char *protos, unsigned int protos_len);
+WOLFSSL_API int wolfSSL_set_alpn_protos(WOLFSSL* ssl,
+        const unsigned char* protos, unsigned int protos_len);
+WOLFSSL_API void *wolfSSL_OPENSSL_memdup(const void *data,
+    size_t siz, const char* file, int line);
+WOLFSSL_API void wolfSSL_ERR_load_BIO_strings(void);
+#endif
+
+#if defined(OPENSSL_ALL) \
+    || defined(WOLFSSL_NGINX) \
+    || defined(WOLFSSL_HAPROXY) \
+    || defined(OPENSSL_EXTRA)
+WOLFSSL_API void wolfSSL_OPENSSL_config(char *config_name);
+#endif
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+/* Not an OpenSSL API. */
+WOLFSSL_LOCAL int wolfSSL_get_ocsp_response(WOLFSSL* ssl, byte** response);
+/* Not an OpenSSL API. */
+WOLFSSL_LOCAL char* wolfSSL_get_ocsp_url(WOLFSSL* ssl);
+/* Not an OpenSSL API. */
+WOLFSSL_API int wolfSSL_set_ocsp_url(WOLFSSL* ssl, char* url);
+#endif
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \
+    || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY)
+WOLFSSL_API WOLF_STACK_OF(WOLFSSL_CIPHER) *wolfSSL_get_ciphers_compat(const WOLFSSL *ssl);
+WOLFSSL_API int wolfSSL_X509_get_ex_new_index(int idx, void *arg, void *a,
+    void *b, void *c);
+WOLFSSL_API void *wolfSSL_X509_get_ex_data(WOLFSSL_X509 *x509, int idx);
+WOLFSSL_API int wolfSSL_X509_set_ex_data(WOLFSSL_X509 *x509, int idx,
+    void *data);
+WOLFSSL_API int wolfSSL_X509_NAME_digest(const WOLFSSL_X509_NAME *data,
+    const WOLFSSL_EVP_MD *type, unsigned char *md, unsigned int *len);
+
+WOLFSSL_API long wolfSSL_SSL_CTX_get_timeout(const WOLFSSL_CTX *ctx);
+WOLFSSL_API long wolfSSL_get_timeout(WOLFSSL* ssl);
+WOLFSSL_API int wolfSSL_SSL_CTX_set_tmp_ecdh(WOLFSSL_CTX *ctx,
+    WOLFSSL_EC_KEY *ecdh);
+WOLFSSL_API int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *,
+    WOLFSSL_SESSION *c);
+
+WOLFSSL_API WOLFSSL_BIO *wolfSSL_SSL_get_rbio(const WOLFSSL *s);
+WOLFSSL_API WOLFSSL_BIO *wolfSSL_SSL_get_wbio(const WOLFSSL *s);
+WOLFSSL_API int wolfSSL_SSL_do_handshake(WOLFSSL *s);
+WOLFSSL_API int wolfSSL_SSL_in_init(WOLFSSL*);
+WOLFSSL_API int wolfSSL_SSL_in_connect_init(WOLFSSL*);
+
+#ifndef NO_SESSION_CACHE
+    WOLFSSL_API WOLFSSL_SESSION *wolfSSL_SSL_get0_session(const WOLFSSL *s);
+#endif
+WOLFSSL_API int wolfSSL_X509_check_host(WOLFSSL_X509 *x, const char *chk,
+    size_t chklen, unsigned int flags, char **peername);
+
+WOLFSSL_API int wolfSSL_i2a_ASN1_INTEGER(WOLFSSL_BIO *bp,
+    const WOLFSSL_ASN1_INTEGER *a);
+
+#ifdef HAVE_SESSION_TICKET
+WOLFSSL_API int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *, int (*)(
+    WOLFSSL *ssl, unsigned char *name, unsigned char *iv,
+    WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc));
+#endif
+
+#if defined(HAVE_OCSP) || defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) || \
+    defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+WOLFSSL_API int wolfSSL_CTX_get_extra_chain_certs(WOLFSSL_CTX* ctx,
+    WOLF_STACK_OF(X509)** chain);
+WOLFSSL_API int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx,
+    int(*)(WOLFSSL*, void*));
+
+WOLFSSL_API int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer,
+    WOLFSSL_X509_STORE_CTX *ctx, WOLFSSL_X509 *x);
+
+WOLFSSL_API void wolfSSL_X509_email_free(WOLF_STACK_OF(WOLFSSL_STRING) *sk);
+WOLFSSL_API WOLF_STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ocsp(WOLFSSL_X509 *x);
+
+WOLFSSL_API int wolfSSL_X509_check_issued(WOLFSSL_X509 *issuer,
+    WOLFSSL_X509 *subject);
+
+WOLFSSL_API char* wolfSSL_sk_WOLFSSL_STRING_value(
+    WOLF_STACK_OF(WOLFSSL_STRING)* strings, int idx);
+#endif /* HAVE_OCSP */
+
+WOLFSSL_API int PEM_write_bio_WOLFSSL_X509(WOLFSSL_BIO *bio,
+    WOLFSSL_X509 *cert);
+
+#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY ||
+    OPENSSL_EXTRA || HAVE_LIGHTY*/
+
+WOLFSSL_API void wolfSSL_get0_alpn_selected(const WOLFSSL *ssl,
+        const unsigned char **data, unsigned int *len);
+WOLFSSL_API int wolfSSL_select_next_proto(unsigned char **out,
+        unsigned char *outlen,
+        const unsigned char *in, unsigned int inlen,
+        const unsigned char *client,
+        unsigned int client_len);
+WOLFSSL_API void wolfSSL_CTX_set_alpn_select_cb(WOLFSSL_CTX *ctx,
+        int (*cb) (WOLFSSL *ssl,
+            const unsigned char **out,
+            unsigned char *outlen,
+            const unsigned char *in,
+            unsigned int inlen,
+            void *arg), void *arg);
+WOLFSSL_API void wolfSSL_CTX_set_next_protos_advertised_cb(WOLFSSL_CTX *s,
+        int (*cb) (WOLFSSL *ssl,
+            const unsigned char **out,
+            unsigned int *outlen,
+            void *arg), void *arg);
+WOLFSSL_API void wolfSSL_CTX_set_next_proto_select_cb(WOLFSSL_CTX *s,
+        int (*cb) (WOLFSSL *ssl,
+            unsigned char **out,
+            unsigned char *outlen,
+            const unsigned char *in,
+            unsigned int inlen,
+            void *arg), void *arg);
+WOLFSSL_API void wolfSSL_get0_next_proto_negotiated(const WOLFSSL *s, const unsigned char **data,
+        unsigned *len);
+
+
+#ifdef OPENSSL_EXTRA
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+WOLFSSL_API const unsigned char *SSL_SESSION_get0_id_context(
+        const WOLFSSL_SESSION *sess, unsigned int *sid_ctx_length);
+WOLFSSL_API size_t SSL_get_finished(const WOLFSSL *s, void *buf, size_t count);
+WOLFSSL_API size_t SSL_get_peer_finished(const WOLFSSL *s, void *buf, size_t count);
+#endif
+
+WOLFSSL_API int SSL_SESSION_set1_id(WOLFSSL_SESSION *s, const unsigned char *sid, unsigned int sid_len);
+WOLFSSL_API int SSL_SESSION_set1_id_context(WOLFSSL_SESSION *s, const unsigned char *sid_ctx, unsigned int sid_ctx_len);
+WOLFSSL_API WOLFSSL_X509_ALGOR* wolfSSL_X509_ALGOR_new(void);
+WOLFSSL_API void wolfSSL_X509_ALGOR_free(WOLFSSL_X509_ALGOR *alg);
+WOLFSSL_API const WOLFSSL_X509_ALGOR* wolfSSL_X509_get0_tbs_sigalg(const WOLFSSL_X509 *x);
+WOLFSSL_API void wolfSSL_X509_ALGOR_get0(const WOLFSSL_ASN1_OBJECT **paobj, int *pptype, const void **ppval, const WOLFSSL_X509_ALGOR *algor);
+WOLFSSL_API int wolfSSL_X509_ALGOR_set0(WOLFSSL_X509_ALGOR *algor, WOLFSSL_ASN1_OBJECT *aobj, int ptype, void *pval);
+WOLFSSL_API WOLFSSL_ASN1_TYPE* wolfSSL_ASN1_TYPE_new(void);
+WOLFSSL_API void wolfSSL_ASN1_TYPE_free(WOLFSSL_ASN1_TYPE* at);
+WOLFSSL_API WOLFSSL_X509_PUBKEY *wolfSSL_X509_PUBKEY_new(void);
+WOLFSSL_API void wolfSSL_X509_PUBKEY_free(WOLFSSL_X509_PUBKEY *x);
+WOLFSSL_API WOLFSSL_X509_PUBKEY *wolfSSL_X509_get_X509_PUBKEY(const WOLFSSL_X509* x509);
+WOLFSSL_API int wolfSSL_X509_PUBKEY_get0_param(WOLFSSL_ASN1_OBJECT **ppkalg, const unsigned char **pk, int *ppklen, WOLFSSL_X509_ALGOR **pa, WOLFSSL_X509_PUBKEY *pub);
+WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_X509_PUBKEY_get(WOLFSSL_X509_PUBKEY* key);
+WOLFSSL_API int wolfSSL_X509_PUBKEY_set(WOLFSSL_X509_PUBKEY **x, WOLFSSL_EVP_PKEY *key);
+WOLFSSL_API int i2t_ASN1_OBJECT(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a);
+WOLFSSL_API int wolfSSL_i2a_ASN1_OBJECT(WOLFSSL_BIO *bp, WOLFSSL_ASN1_OBJECT *a);
+WOLFSSL_API void SSL_CTX_set_tmp_dh_callback(WOLFSSL_CTX *ctx, WOLFSSL_DH *(*dh) (WOLFSSL *ssl, int is_export, int keylength));
+WOLFSSL_API WOLF_STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void);
+WOLFSSL_API int wolfSSL_X509_STORE_load_locations(WOLFSSL_X509_STORE *str, const char *file, const char *dir);
+WOLFSSL_API int wolfSSL_X509_STORE_add_crl(WOLFSSL_X509_STORE *ctx, WOLFSSL_X509_CRL *x);
+WOLFSSL_API int wolfSSL_sk_SSL_CIPHER_num(const WOLF_STACK_OF(WOLFSSL_CIPHER)* p);
+WOLFSSL_API int wolfSSL_sk_SSL_CIPHER_find(
+        WOLF_STACK_OF(WOLFSSL_CIPHER)* sk, const WOLFSSL_CIPHER* toFind);
+WOLFSSL_API WOLF_STACK_OF(WOLFSSL_CIPHER)* wolfSSL_sk_SSL_CIPHER_dup(
+        WOLF_STACK_OF(WOLFSSL_CIPHER)* in);
+WOLFSSL_API void wolfSSL_sk_SSL_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk);
+WOLFSSL_API int wolfSSL_sk_SSL_COMP_zero(WOLFSSL_STACK* st);
+WOLFSSL_API int wolfSSL_sk_SSL_COMP_num(WOLF_STACK_OF(WOLFSSL_COMP)* sk);
+WOLFSSL_API WOLFSSL_CIPHER* wolfSSL_sk_SSL_CIPHER_value(void *ciphers, int idx);
+WOLFSSL_API void ERR_load_SSL_strings(void);
+WOLFSSL_API void wolfSSL_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *p);
+
+WOLFSSL_API const char *wolfSSL_ASN1_tag2str(int tag);
+WOLFSSL_API int wolfSSL_ASN1_STRING_print_ex(WOLFSSL_BIO *out, WOLFSSL_ASN1_STRING *str, unsigned long flags);
+WOLFSSL_API int wolfSSL_ASN1_STRING_print(WOLFSSL_BIO *out, WOLFSSL_ASN1_STRING *str);
+WOLFSSL_API int wolfSSL_ASN1_TIME_get_length(WOLFSSL_ASN1_TIME *t);
+WOLFSSL_API unsigned char* wolfSSL_ASN1_TIME_get_data(WOLFSSL_ASN1_TIME *t);
+WOLFSSL_API WOLFSSL_ASN1_TIME *wolfSSL_ASN1_TIME_to_generalizedtime(WOLFSSL_ASN1_TIME *t,
+                                                                WOLFSSL_ASN1_TIME **out);
+WOLFSSL_API int wolfSSL_i2c_ASN1_INTEGER(WOLFSSL_ASN1_INTEGER *a, unsigned char **pp);
+WOLFSSL_API int wolfSSL_X509_CA_num(WOLFSSL_X509_STORE *store);
+WOLFSSL_API long wolfSSL_X509_get_version(const WOLFSSL_X509 *x);
+WOLFSSL_API int wolfSSL_X509_get_signature_nid(const WOLFSSL_X509* x);
+
+WOLFSSL_API int wolfSSL_PEM_write_bio_PKCS8PrivateKey(WOLFSSL_BIO* bio,
+    WOLFSSL_EVP_PKEY* pkey, const WOLFSSL_EVP_CIPHER* enc, char* passwd,
+    int passwdSz, pem_password_cb* cb, void* ctx);
+WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PKCS8PrivateKey_bio(WOLFSSL_BIO* bio,
+    WOLFSSL_EVP_PKEY** pkey, pem_password_cb* cb, void* u);
+WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_AutoPrivateKey(
+    WOLFSSL_EVP_PKEY** pkey, const unsigned char** data, long length);
+WOLFSSL_API unsigned long  wolfSSL_X509_subject_name_hash(const WOLFSSL_X509* x509);
+
+
+#endif /* OPENSSL_EXTRA */
+
+#ifdef HAVE_PK_CALLBACKS
+WOLFSSL_API int wolfSSL_IsPrivatePkSet(WOLFSSL* ssl);
+WOLFSSL_API int wolfSSL_CTX_IsPrivatePkSet(WOLFSSL_CTX* ctx);
+#endif
+
+#ifdef HAVE_ENCRYPT_THEN_MAC
+WOLFSSL_API int wolfSSL_CTX_AllowEncryptThenMac(WOLFSSL_CTX *, int);
+WOLFSSL_API int wolfSSL_AllowEncryptThenMac(WOLFSSL *s, int);
+#endif
+
+#ifdef __cplusplus
+    }  /* extern "C" */
+#endif
+
+
+#endif /* WOLFSSL_SSL_H */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/test.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/test.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/test.h	(revision 453)
@@ -0,0 +1,3683 @@
+/* test.h */
+
+#ifndef wolfSSL_TEST_H
+#define wolfSSL_TEST_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <ctype.h>
+#include <wolfssl/wolfcrypt/types.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#include <wolfssl/wolfcrypt/random.h>
+#include <wolfssl/wolfcrypt/mem_track.h>
+#if defined(SHOW_CERTS) && \
+    (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
+    #include <wolfssl/wolfcrypt/asn.h> /* for domain component NID value */
+#endif
+
+#ifdef ATOMIC_USER
+    #include <wolfssl/wolfcrypt/aes.h>
+    #include <wolfssl/wolfcrypt/arc4.h>
+    #include <wolfssl/wolfcrypt/hmac.h>
+#endif
+#ifdef HAVE_PK_CALLBACKS
+    #include <wolfssl/wolfcrypt/asn.h>
+    #ifndef NO_RSA
+        #include <wolfssl/wolfcrypt/rsa.h>
+    #endif
+    #ifdef HAVE_ECC
+        #include <wolfssl/wolfcrypt/ecc.h>
+    #endif /* HAVE_ECC */
+    #ifndef NO_DH
+        #include <wolfssl/wolfcrypt/dh.h>
+    #endif /* !NO_DH */
+    #ifdef HAVE_ED25519
+        #include <wolfssl/wolfcrypt/ed25519.h>
+    #endif /* HAVE_ED25519 */
+    #ifdef HAVE_CURVE25519
+        #include <wolfssl/wolfcrypt/curve25519.h>
+    #endif /* HAVE_ECC */
+    #ifdef HAVE_ED448
+        #include <wolfssl/wolfcrypt/ed448.h>
+    #endif /* HAVE_ED448 */
+    #ifdef HAVE_CURVE448
+        #include <wolfssl/wolfcrypt/curve448.h>
+    #endif /* HAVE_ECC */
+#endif /*HAVE_PK_CALLBACKS */
+
+#ifdef USE_WINDOWS_API
+    #include <winsock2.h>
+    #include <process.h>
+    #ifdef TEST_IPV6            /* don't require newer SDK for IPV4 */
+        #include <ws2tcpip.h>
+        #include <wspiapi.h>
+    #endif
+    #define SOCKET_T SOCKET
+    #define SNPRINTF _snprintf
+#elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET)
+    #include <string.h>
+    #include "rl_net.h"
+    #define SOCKET_T int
+    typedef int socklen_t ;
+    #define inet_addr wolfSSL_inet_addr
+    static unsigned long wolfSSL_inet_addr(const char *cp)
+    {
+        unsigned int a[4] ; unsigned long ret ;
+        sscanf(cp, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]) ;
+        ret = ((a[3]<<24) + (a[2]<<16) + (a[1]<<8) + a[0]) ;
+        return(ret) ;
+    }
+    #if defined(HAVE_KEIL_RTX)
+        #define sleep(t) os_dly_wait(t/1000+1);
+    #elif defined(WOLFSSL_CMSIS_RTOS) || defined(WOLFSSL_CMSIS_RTOSv2)
+        #define sleep(t) osDelay(t/1000+1);
+    #endif
+#elif defined(WOLFSSL_TIRTOS)
+    #include <string.h>
+    #include <netdb.h>
+    #include <sys/types.h>
+    #include <arpa/inet.h>
+    #include <sys/socket.h>
+    #include <ti/sysbios/knl/Task.h>
+    struct hostent {
+        char *h_name; /* official name of host */
+        char **h_aliases; /* alias list */
+        int h_addrtype; /* host address type */
+        int h_length; /* length of address */
+        char **h_addr_list; /* list of addresses from name server */
+    };
+    #define SOCKET_T int
+#elif defined(WOLFSSL_VXWORKS)
+    #include <hostLib.h>
+    #include <sockLib.h>
+    #include <arpa/inet.h>
+    #include <string.h>
+    #include <selectLib.h>
+    #include <sys/types.h>
+    #include <netinet/in.h>
+    #include <fcntl.h>
+    #include <sys/time.h>
+    #include <netdb.h>
+    #include <pthread.h>
+    #define SOCKET_T int
+#elif defined(WOLFSSL_ZEPHYR)
+    #include <string.h>
+    #include <sys/types.h>
+    #include <net/socket.h>
+    #define SOCKET_T int
+    #define SOL_SOCKET 1
+    #define SO_REUSEADDR 201
+    #define WOLFSSL_USE_GETADDRINFO
+
+    static unsigned long inet_addr(const char *cp)
+    {
+        unsigned int a[4]; unsigned long ret;
+        int i, j;
+        for (i=0, j=0; i<4; i++) {
+            a[i] = 0;
+            while (cp[j] != '.' && cp[j] != '\0') {
+                a[i] *= 10;
+                a[i] += cp[j] - '0';
+                j++;
+            }
+        }
+        ret = ((a[3]<<24) + (a[2]<<16) + (a[1]<<8) + a[0]) ;
+        return(ret) ;
+    }
+#else
+    #include <string.h>
+    #include <sys/types.h>
+#ifndef WOLFSSL_LEANPSK
+    #include <unistd.h>
+    #include <netdb.h>
+    #include <netinet/in.h>
+    #include <netinet/tcp.h>
+    #include <arpa/inet.h>
+    #include <sys/ioctl.h>
+    #include <sys/time.h>
+    #include <sys/socket.h>
+    #include <pthread.h>
+    #include <fcntl.h>
+    #ifdef TEST_IPV6
+        #include <netdb.h>
+    #endif
+#endif
+    #define SOCKET_T int
+    #ifndef SO_NOSIGPIPE
+        #include <signal.h>  /* ignore SIGPIPE */
+    #endif
+    #define SNPRINTF snprintf
+#endif /* USE_WINDOWS_API */
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    #include <wolfssl/wolfcrypt/async.h>
+#endif
+#ifdef HAVE_CAVIUM
+    #include <wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h>
+#endif
+#ifdef _MSC_VER
+    /* disable conversion warning */
+    /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */
+    #pragma warning(disable:4244 4996)
+#endif
+
+#ifndef WOLFSSL_CIPHER_LIST_MAX_SIZE
+    #define WOLFSSL_CIPHER_LIST_MAX_SIZE 4096
+#endif
+/* Buffer for benchmark tests */
+#ifndef TEST_BUFFER_SIZE
+    #define TEST_BUFFER_SIZE 16384
+#endif
+
+#ifndef WOLFSSL_HAVE_MIN
+    #define WOLFSSL_HAVE_MIN
+    static WC_INLINE word32 min(word32 a, word32 b)
+    {
+        return a > b ? b : a;
+    }
+#endif /* WOLFSSL_HAVE_MIN */
+
+/* Socket Handling */
+#ifndef WOLFSSL_SOCKET_INVALID
+#ifdef USE_WINDOWS_API
+    #define WOLFSSL_SOCKET_INVALID  ((SOCKET_T)INVALID_SOCKET)
+#elif defined(WOLFSSL_TIRTOS)
+    #define WOLFSSL_SOCKET_INVALID  ((SOCKET_T)-1)
+#else
+    #define WOLFSSL_SOCKET_INVALID  (SOCKET_T)(0)
+#endif
+#endif /* WOLFSSL_SOCKET_INVALID */
+
+#ifndef WOLFSSL_SOCKET_IS_INVALID
+#if defined(USE_WINDOWS_API) || defined(WOLFSSL_TIRTOS)
+    #define WOLFSSL_SOCKET_IS_INVALID(s)  ((SOCKET_T)(s) == WOLFSSL_SOCKET_INVALID)
+#else
+    #define WOLFSSL_SOCKET_IS_INVALID(s)  ((SOCKET_T)(s) < WOLFSSL_SOCKET_INVALID)
+#endif
+#endif /* WOLFSSL_SOCKET_IS_INVALID */
+
+#if defined(__MACH__) || defined(USE_WINDOWS_API)
+    #ifndef _SOCKLEN_T
+        typedef int socklen_t;
+    #endif
+#endif
+
+
+/* HPUX doesn't use socklent_t for third parameter to accept, unless
+   _XOPEN_SOURCE_EXTENDED is defined */
+#if !defined(__hpux__) && !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_IAR_ARM)\
+ && !defined(WOLFSSL_ROWLEY_ARM)  && !defined(WOLFSSL_KEIL_TCP_NET)
+    typedef socklen_t* ACCEPT_THIRD_T;
+#else
+    #if defined _XOPEN_SOURCE_EXTENDED
+        typedef socklen_t* ACCEPT_THIRD_T;
+    #else
+        typedef int*       ACCEPT_THIRD_T;
+    #endif
+#endif
+
+
+
+#ifdef SINGLE_THREADED
+    typedef unsigned int  THREAD_RETURN;
+    typedef void*         THREAD_TYPE;
+    #define WOLFSSL_THREAD
+#else
+    #if defined(_POSIX_THREADS) && !defined(__MINGW32__)
+        typedef void*         THREAD_RETURN;
+        typedef pthread_t     THREAD_TYPE;
+        #define WOLFSSL_THREAD
+        #define INFINITE -1
+        #define WAIT_OBJECT_0 0L
+    #elif defined(WOLFSSL_MDK_ARM)|| defined(WOLFSSL_KEIL_TCP_NET)
+        typedef unsigned int  THREAD_RETURN;
+        typedef int           THREAD_TYPE;
+        #define WOLFSSL_THREAD
+    #elif defined(WOLFSSL_TIRTOS)
+        typedef void          THREAD_RETURN;
+        typedef Task_Handle   THREAD_TYPE;
+        #define WOLFSSL_THREAD
+    #elif defined(WOLFSSL_ZEPHYR)
+        typedef void            THREAD_RETURN;
+        typedef struct k_thread THREAD_TYPE;
+        #define WOLFSSL_THREAD
+    #else
+        typedef unsigned int  THREAD_RETURN;
+        typedef intptr_t      THREAD_TYPE;
+        #define WOLFSSL_THREAD __stdcall
+    #endif
+#endif
+
+
+#ifdef TEST_IPV6
+    typedef struct sockaddr_in6 SOCKADDR_IN_T;
+    #define AF_INET_V    AF_INET6
+#else
+    typedef struct sockaddr_in  SOCKADDR_IN_T;
+    #define AF_INET_V    AF_INET
+#endif
+
+
+#ifndef WOLFSSL_NO_TLS12
+#define SERVER_DEFAULT_VERSION 3
+#else
+#define SERVER_DEFAULT_VERSION 4
+#endif
+#define SERVER_DTLS_DEFAULT_VERSION (-2)
+#define SERVER_INVALID_VERSION (-99)
+#define SERVER_DOWNGRADE_VERSION (-98)
+#ifndef WOLFSSL_NO_TLS12
+#define CLIENT_DEFAULT_VERSION 3
+#else
+#define CLIENT_DEFAULT_VERSION 4
+#endif
+#define CLIENT_DTLS_DEFAULT_VERSION (-2)
+#define CLIENT_INVALID_VERSION (-99)
+#define CLIENT_DOWNGRADE_VERSION (-98)
+#define EITHER_DOWNGRADE_VERSION (-97)
+#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_MAX_STRENGTH)
+    #define DEFAULT_MIN_DHKEY_BITS 2048
+    #define DEFAULT_MAX_DHKEY_BITS 3072
+#else
+    #define DEFAULT_MIN_DHKEY_BITS 1024
+    #define DEFAULT_MAX_DHKEY_BITS 2048
+#endif
+#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_MAX_STRENGTH)
+    #define DEFAULT_MIN_RSAKEY_BITS 2048
+#else
+    #define DEFAULT_MIN_RSAKEY_BITS 1024
+#endif
+#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_MAX_STRENGTH)
+    #define DEFAULT_MIN_ECCKEY_BITS 256
+#else
+    #define DEFAULT_MIN_ECCKEY_BITS 224
+#endif
+
+/* all certs relative to wolfSSL home directory now */
+#if defined(WOLFSSL_NO_CURRDIR) || defined(WOLFSSL_MDK_SHELL)
+#define caCertFile        "certs/ca-cert.pem"
+#define eccCertFile       "certs/server-ecc.pem"
+#define eccKeyFile        "certs/ecc-key.pem"
+#define eccRsaCertFile    "certs/server-ecc-rsa.pem"
+#define svrCertFile       "certs/server-cert.pem"
+#define svrKeyFile        "certs/server-key.pem"
+#define cliCertFile       "certs/client-cert.pem"
+#define cliCertDerFile    "certs/client-cert.der"
+#define cliCertFileExt    "certs/client-cert-ext.pem"
+#define cliCertDerFileExt "certs/client-cert-ext.der"
+#define cliKeyFile        "certs/client-key.pem"
+#define ntruCertFile      "certs/ntru-cert.pem"
+#define ntruKeyFile       "certs/ntru-key.raw"
+#define dhParamFile       "certs/dh2048.pem"
+#define cliEccKeyFile     "certs/ecc-client-key.pem"
+#define cliEccCertFile    "certs/client-ecc-cert.pem"
+#define caEccCertFile     "certs/ca-ecc-cert.pem"
+#define crlPemDir         "certs/crl"
+#define edCertFile        "certs/ed25519/server-ed25519-cert.pem"
+#define edKeyFile         "certs/ed25519/server-ed25519-priv.pem"
+#define cliEdCertFile     "certs/ed25519/client-ed25519.pem"
+#define cliEdKeyFile      "certs/ed25519/client-ed25519-priv.pem"
+#define caEdCertFile      "certs/ed25519/ca-ed25519.pem"
+#define ed448CertFile     "certs/ed448/server-ed448-cert.pem"
+#define ed448KeyFile      "certs/ed448/server-ed448-priv.pem"
+#define cliEd448CertFile  "certs/ed448/client-ed448.pem"
+#define cliEd448KeyFile   "certs/ed448/client-ed448-priv.pem"
+#define caEd448CertFile   "certs/ed448/ca-ed448.pem"
+#ifdef HAVE_WNR
+    /* Whitewood netRandom default config file */
+    #define wnrConfig     "wnr-example.conf"
+#endif
+#else
+#define caCertFile        "./certs/ca-cert.pem"
+#define eccCertFile       "./certs/server-ecc.pem"
+#define eccKeyFile        "./certs/ecc-key.pem"
+#define eccRsaCertFile    "./certs/server-ecc-rsa.pem"
+#define svrCertFile       "./certs/server-cert.pem"
+#define svrKeyFile        "./certs/server-key.pem"
+#define cliCertFile       "./certs/client-cert.pem"
+#define cliCertDerFile    "./certs/client-cert.der"
+#define cliCertFileExt    "./certs/client-cert-ext.pem"
+#define cliCertDerFileExt "./certs/client-cert-ext.der"
+#define cliKeyFile        "./certs/client-key.pem"
+#define ntruCertFile      "./certs/ntru-cert.pem"
+#define ntruKeyFile       "./certs/ntru-key.raw"
+#define dhParamFile       "./certs/dh2048.pem"
+#define cliEccKeyFile     "./certs/ecc-client-key.pem"
+#define cliEccCertFile    "./certs/client-ecc-cert.pem"
+#define caEccCertFile     "./certs/ca-ecc-cert.pem"
+#define crlPemDir         "./certs/crl"
+#define edCertFile        "./certs/ed25519/server-ed25519-cert.pem"
+#define edKeyFile         "./certs/ed25519/server-ed25519-priv.pem"
+#define cliEdCertFile     "./certs/ed25519/client-ed25519.pem"
+#define cliEdKeyFile      "./certs/ed25519/client-ed25519-priv.pem"
+#define caEdCertFile      "./certs/ed25519/ca-ed25519.pem"
+#define ed448CertFile     "./certs/ed448/server-ed448-cert.pem"
+#define ed448KeyFile      "./certs/ed448/server-ed448-priv.pem"
+#define cliEd448CertFile  "./certs/ed448/client-ed448.pem"
+#define cliEd448KeyFile   "./certs/ed448/client-ed448-priv.pem"
+#define caEd448CertFile   "./certs/ed448/ca-ed448.pem"
+#ifdef HAVE_WNR
+    /* Whitewood netRandom default config file */
+    #define wnrConfig     "./wnr-example.conf"
+#endif
+#endif
+
+typedef struct tcp_ready {
+    word16 ready;              /* predicate */
+    word16 port;
+    char*  srfName;     /* server ready file name */
+#if defined(_POSIX_THREADS) && !defined(__MINGW32__)
+    pthread_mutex_t mutex;
+    pthread_cond_t  cond;
+#endif
+} tcp_ready;
+
+
+static WC_INLINE void InitTcpReady(tcp_ready* ready)
+{
+    ready->ready = 0;
+    ready->port = 0;
+    ready->srfName = NULL;
+#ifdef SINGLE_THREADED
+#elif defined(_POSIX_THREADS) && !defined(__MINGW32__)
+    pthread_mutex_init(&ready->mutex, 0);
+    pthread_cond_init(&ready->cond, 0);
+#endif
+}
+
+
+static WC_INLINE void FreeTcpReady(tcp_ready* ready)
+{
+#ifdef SINGLE_THREADED
+    (void)ready;
+#elif defined(_POSIX_THREADS) && !defined(__MINGW32__)
+    pthread_mutex_destroy(&ready->mutex);
+    pthread_cond_destroy(&ready->cond);
+#else
+    (void)ready;
+#endif
+}
+
+typedef WOLFSSL_METHOD* (*method_provider)(void);
+typedef void (*ctx_callback)(WOLFSSL_CTX* ctx);
+typedef void (*ssl_callback)(WOLFSSL* ssl);
+
+typedef struct callback_functions {
+    method_provider method;
+    ctx_callback ctx_ready;
+    ssl_callback ssl_ready;
+    ssl_callback on_result;
+    WOLFSSL_CTX* ctx;
+} callback_functions;
+
+typedef struct func_args {
+    int    argc;
+    char** argv;
+    int    return_code;
+    tcp_ready* signal;
+    callback_functions *callbacks;
+} func_args;
+
+
+
+
+void wait_tcp_ready(func_args*);
+
+#ifdef WOLFSSL_ZEPHYR
+typedef void THREAD_FUNC(void*, void*, void*);
+#else
+typedef THREAD_RETURN WOLFSSL_THREAD THREAD_FUNC(void*);
+#endif
+
+void start_thread(THREAD_FUNC, func_args*, THREAD_TYPE*);
+void join_thread(THREAD_TYPE);
+
+/* wolfSSL */
+#ifndef TEST_IPV6
+    static const char* const wolfSSLIP   = "127.0.0.1";
+#else
+    static const char* const wolfSSLIP   = "::1";
+#endif
+static const word16      wolfSSLPort = 11111;
+
+
+
+#ifndef MY_EX_USAGE
+#define MY_EX_USAGE 2
+#endif
+
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE 1
+#endif
+
+#if defined(WOLFSSL_FORCE_MALLOC_FAIL_TEST) || defined(WOLFSSL_ZEPHYR)
+    #ifndef EXIT_SUCCESS
+        #define EXIT_SUCCESS   0
+    #endif
+    #define XEXIT(rc)   return rc
+    #define XEXIT_T(rc) return (THREAD_RETURN)rc
+#else
+    #define XEXIT(rc)   exit((int)(rc))
+    #define XEXIT_T(rc) exit((int)(rc))
+#endif
+
+
+static WC_INLINE
+#if defined(WOLFSSL_FORCE_MALLOC_FAIL_TEST) || defined(WOLFSSL_ZEPHYR)
+THREAD_RETURN
+#else
+WC_NORETURN void
+#endif
+err_sys(const char* msg)
+{
+    printf("wolfSSL error: %s\n", msg);
+
+#if !defined(__GNUC__)
+    /* scan-build (which pretends to be gnuc) can get confused and think the
+     * msg pointer can be null even when hardcoded and then it won't exit,
+     * making null pointer checks above the err_sys() call useless.
+     * We could just always exit() but some compilers will complain about no
+     * possible return, with gcc we know the attribute to handle that with
+     * WC_NORETURN. */
+    if (msg)
+#endif
+    {
+        XEXIT_T(EXIT_FAILURE);
+    }
+}
+
+
+extern int   myoptind;
+extern char* myoptarg;
+
+static WC_INLINE int mygetopt(int argc, char** argv, const char* optstring)
+{
+    static char* next = NULL;
+
+    char  c;
+    char* cp;
+
+    /* Added sanity check becuase scan-build complains argv[myoptind] access 
+     * results in a null pointer dereference. */
+    if (argv == NULL)  {
+        myoptarg = NULL;
+        return -1;
+    }
+
+    if (myoptind == 0)
+        next = NULL;   /* we're starting new/over */
+
+    if (next == NULL || *next == '\0') {
+        if (myoptind == 0)
+            myoptind++;
+
+        if (myoptind >= argc || argv[myoptind] == NULL ||
+                argv[myoptind][0] != '-' || argv[myoptind][1] == '\0') {
+            myoptarg = NULL;
+            if (myoptind < argc)
+                myoptarg = argv[myoptind];
+
+            return -1;
+        }
+
+        if (strcmp(argv[myoptind], "--") == 0) {
+            myoptind++;
+            myoptarg = NULL;
+
+            if (myoptind < argc)
+                myoptarg = argv[myoptind];
+
+            return -1;
+        }
+
+        next = argv[myoptind];
+        next++;                  /* skip - */
+        myoptind++;
+    }
+
+    c  = *next++;
+    /* The C++ strchr can return a different value */
+    cp = (char*)strchr(optstring, c);
+
+    if (cp == NULL || c == ':')
+        return '?';
+
+    cp++;
+
+    if (*cp == ':') {
+        if (*next != '\0') {
+            myoptarg = next;
+            next     = NULL;
+        }
+        else if (myoptind < argc) {
+            myoptarg = argv[myoptind];
+            myoptind++;
+        }
+        else
+            return '?';
+    }
+
+    return c;
+}
+
+
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+
+static WC_INLINE int PasswordCallBack(char* passwd, int sz, int rw, void* userdata)
+{
+    (void)rw;
+    (void)userdata;
+    if (userdata != NULL) {
+        strncpy(passwd, (char*)userdata, sz);
+        return (int)XSTRLEN((char*)userdata);
+    }
+    else {
+        strncpy(passwd, "yassl123", sz);
+        return 8;
+    }
+}
+
+#endif
+
+static const char* client_showpeer_msg[][8] = {
+    /* English */
+    {
+        "SSL version is",
+        "SSL cipher suite is",
+        "SSL curve name is",
+        "SSL DH size is",
+        "SSL reused session",
+        "Alternate cert chain used",
+        "peer's cert info:",
+        NULL
+    },
+#ifndef NO_MULTIBYTE_PRINT
+    /* Japanese */
+    {
+        "SSL バージョンは",
+        "SSL 暗号スイートは",
+        "SSL 曲線名は",
+        "SSL DH サイズは",
+        "SSL 再利用セッション",
+        "代替証明チェーンを使用",
+        "相手方証明書情報",
+        NULL
+    },
+#endif
+};
+
+#if defined(KEEP_PEER_CERT) || defined(KEEP_OUR_CERT) || defined(SESSION_CERTS)
+static const char* client_showx509_msg[][5] = {
+    /* English */
+    {
+        "issuer",
+        "subject",
+        "altname",
+        "serial number",
+        NULL
+    },
+#ifndef NO_MULTIBYTE_PRINT
+    /* Japanese */
+    {
+        "発行者",
+        "サブジェクト",
+        "代替名",
+        "シリアル番号",
+        NULL
+    },
+#endif
+};
+
+/* lng_index is to specify the language for displaying message.              */
+/* 0:English, 1:Japanese                                                     */
+static WC_INLINE void ShowX509Ex(WOLFSSL_X509* x509, const char* hdr,
+                                                                 int lng_index)
+{
+    char* altName;
+    char* issuer;
+    char* subject;
+    byte  serial[32];
+    int   ret;
+    int   sz = sizeof(serial);
+    const char** words = client_showx509_msg[lng_index];
+
+    if (x509 == NULL) {
+        printf("%s No Cert\n", hdr);
+        return;
+    }
+
+    issuer  = wolfSSL_X509_NAME_oneline(
+                                      wolfSSL_X509_get_issuer_name(x509), 0, 0);
+    subject = wolfSSL_X509_NAME_oneline(
+                                     wolfSSL_X509_get_subject_name(x509), 0, 0);
+
+    printf("%s\n %s : %s\n %s: %s\n", hdr, words[0], issuer, words[1], subject);
+
+    while ( (altName = wolfSSL_X509_get_next_altname(x509)) != NULL)
+        printf(" %s = %s\n", words[2], altName);
+
+    ret = wolfSSL_X509_get_serial_number(x509, serial, &sz);
+    if (ret == WOLFSSL_SUCCESS) {
+        int  i;
+        int  strLen;
+        char serialMsg[80];
+
+        /* testsuite has multiple threads writing to stdout, get output
+           message ready to write once */
+        strLen = sprintf(serialMsg, " %s", words[3]);
+        for (i = 0; i < sz; i++)
+            sprintf(serialMsg + strLen + (i*3), ":%02x ", serial[i]);
+        printf("%s\n", serialMsg);
+    }
+
+    XFREE(subject, 0, DYNAMIC_TYPE_OPENSSL);
+    XFREE(issuer,  0, DYNAMIC_TYPE_OPENSSL);
+
+#if defined(SHOW_CERTS) && defined(OPENSSL_EXTRA)
+    {
+        WOLFSSL_BIO* bio;
+        char buf[256]; /* should be size of ASN_NAME_MAX */
+        int  textSz;
+
+        /* print out domain component if certificate has it */
+        textSz = wolfSSL_X509_NAME_get_text_by_NID(
+                wolfSSL_X509_get_subject_name(x509), NID_domainComponent,
+                buf, sizeof(buf));
+        if (textSz > 0) {
+            printf("Domain Component = %s\n", buf);
+        }
+
+        bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file());
+        if (bio != NULL) {
+            wolfSSL_BIO_set_fp(bio, stdout, BIO_NOCLOSE);
+            wolfSSL_X509_print(bio, x509);
+            wolfSSL_BIO_free(bio);
+        }
+    }
+#endif /* SHOW_CERTS && OPENSSL_EXTRA */
+}
+/* original ShowX509 to maintain compatibility */
+static WC_INLINE void ShowX509(WOLFSSL_X509* x509, const char* hdr)
+{
+    ShowX509Ex(x509, hdr, 0);
+}
+
+#endif /* KEEP_PEER_CERT || KEEP_OUR_CERT || SESSION_CERTS */
+
+#if defined(SHOW_CERTS) && defined(SESSION_CERTS) && \
+    (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
+static WC_INLINE void ShowX509Chain(WOLFSSL_X509_CHAIN* chain, int count,
+    const char* hdr)
+{
+    int i;
+    int length;
+    unsigned char buffer[3072];
+    WOLFSSL_X509* chainX509;
+
+    for (i = 0; i < count; i++) {
+        wolfSSL_get_chain_cert_pem(chain, i, buffer, sizeof(buffer), &length);
+        buffer[length] = 0;
+        printf("\n%s: %d has length %d data = \n%s\n", hdr, i, length, buffer);
+
+        chainX509 = wolfSSL_get_chain_X509(chain, i);
+        if (chainX509)
+            ShowX509(chainX509, hdr);
+        else
+            printf("get_chain_X509 failed\n");
+        wolfSSL_FreeX509(chainX509);
+    }
+}
+#endif /* SHOW_CERTS && SESSION_CERTS */
+
+/* lng_index is to specify the language for displaying message.              */
+/* 0:English, 1:Japanese                                                     */
+static WC_INLINE void showPeerEx(WOLFSSL* ssl, int lng_index)
+{
+    WOLFSSL_CIPHER* cipher;
+    const char** words = client_showpeer_msg[lng_index];
+
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) || \
+                                                                 !defined(NO_DH)
+    const char *name;
+#endif
+#ifndef NO_DH
+    int bits;
+#endif
+#ifdef KEEP_PEER_CERT
+    WOLFSSL_X509* peer = wolfSSL_get_peer_certificate(ssl);
+    if (peer)
+        ShowX509Ex(peer, words[6], lng_index);
+    else
+        printf("peer has no cert!\n");
+    wolfSSL_FreeX509(peer);
+#endif
+#if defined(SHOW_CERTS) && defined(KEEP_OUR_CERT) && \
+    (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
+    ShowX509(wolfSSL_get_certificate(ssl), "our cert info:");
+    printf("Peer verify result = %lu\n", wolfSSL_get_verify_result(ssl));
+#endif /* SHOW_CERTS && KEEP_OUR_CERT */
+    printf("%s %s\n", words[0], wolfSSL_get_version(ssl));
+
+    cipher = wolfSSL_get_current_cipher(ssl);
+#ifdef HAVE_QSH
+    printf("%s %s%s\n", words[1], (wolfSSL_isQSH(ssl))? "QSH:": "",
+            wolfSSL_CIPHER_get_name(cipher));
+#else
+    printf("%s %s\n", words[1], wolfSSL_CIPHER_get_name(cipher));
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) || \
+                                                                 !defined(NO_DH)
+    if ((name = wolfSSL_get_curve_name(ssl)) != NULL)
+        printf("%s %s\n", words[2], name);
+#endif
+#ifndef NO_DH
+    else if ((bits = wolfSSL_GetDhKey_Sz(ssl)) > 0)
+        printf("%s %d bits\n", words[3], bits);
+#endif
+    if (wolfSSL_session_reused(ssl))
+        printf("%s\n", words[4]);
+#ifdef WOLFSSL_ALT_CERT_CHAINS
+    if (wolfSSL_is_peer_alt_cert_chain(ssl))
+        printf("%s\n", words[5]);
+#endif
+
+#if defined(SHOW_CERTS) && defined(SESSION_CERTS) && \
+    (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
+    {
+        WOLFSSL_X509_CHAIN* chain;
+
+        chain = wolfSSL_get_peer_chain(ssl);
+        ShowX509Chain(chain, wolfSSL_get_chain_count(chain), "session cert");
+
+    #ifdef WOLFSSL_ALT_CERT_CHAINS
+        if (wolfSSL_is_peer_alt_cert_chain(ssl)) {
+            chain = wolfSSL_get_peer_alt_chain(ssl);
+            ShowX509Chain(chain, wolfSSL_get_chain_count(chain), "alt cert");
+        }
+    #endif
+    }
+#endif /* SHOW_CERTS && SESSION_CERTS */
+  (void)ssl;
+}
+/* original showPeer to maintain compatibility */
+static WC_INLINE void showPeer(WOLFSSL* ssl)
+{
+    showPeerEx(ssl, 0);
+}
+
+static WC_INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer,
+                              word16 port, int udp, int sctp)
+{
+    int useLookup = 0;
+    (void)useLookup;
+    (void)udp;
+    (void)sctp;
+
+    if (addr == NULL)
+        err_sys("invalid argument to build_addr, addr is NULL");
+
+    XMEMSET(addr, 0, sizeof(SOCKADDR_IN_T));
+
+#ifndef TEST_IPV6
+    /* peer could be in human readable form */
+    if ( ((size_t)peer != INADDR_ANY) && isalpha((int)peer[0])) {
+    #ifndef WOLFSSL_USE_GETADDRINFO
+        #if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET)
+            int err;
+            struct hostent* entry = gethostbyname(peer, &err);
+        #elif defined(WOLFSSL_TIRTOS)
+            struct hostent* entry = DNSGetHostByName(peer);
+        #elif defined(WOLFSSL_VXWORKS)
+            struct hostent* entry = (struct hostent*)hostGetByName((char*)peer);
+        #else
+            struct hostent* entry = gethostbyname(peer);
+        #endif
+
+        if (entry) {
+            XMEMCPY(&addr->sin_addr.s_addr, entry->h_addr_list[0],
+                   entry->h_length);
+            useLookup = 1;
+        }
+    #else
+        struct zsock_addrinfo hints, *addrInfo;
+        char portStr[6];
+        XSNPRINTF(portStr, sizeof(portStr), "%d", port);
+        memset(&hints, 0, sizeof(hints));
+        hints.ai_family = AF_UNSPEC;
+        hints.ai_socktype = udp ? SOCK_DGRAM : SOCK_STREAM;
+        hints.ai_protocol = udp ? IPPROTO_UDP : IPPROTO_TCP;
+        if (getaddrinfo((char*)peer, portStr, &hints, &addrInfo) == 0) {
+            XMEMCPY(addr, addrInfo->ai_addr, sizeof(*addr));
+            useLookup = 1;
+        }
+    #endif
+        else
+            err_sys("no entry for host");
+    }
+#endif
+
+
+#ifndef TEST_IPV6
+    #if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET)
+        addr->sin_family = PF_INET;
+    #else
+        addr->sin_family = AF_INET_V;
+    #endif
+    addr->sin_port = XHTONS(port);
+    if ((size_t)peer == INADDR_ANY)
+        addr->sin_addr.s_addr = INADDR_ANY;
+    else {
+        if (!useLookup)
+            addr->sin_addr.s_addr = inet_addr(peer);
+    }
+#else
+    addr->sin6_family = AF_INET_V;
+    addr->sin6_port = XHTONS(port);
+    if ((size_t)peer == INADDR_ANY) {
+        addr->sin6_addr = in6addr_any;
+    }
+    else {
+        #if defined(HAVE_GETADDRINFO) || defined(WOLF_C99)
+            struct addrinfo  hints;
+            struct addrinfo* answer = NULL;
+            int    ret;
+            char   strPort[80];
+
+            XMEMSET(&hints, 0, sizeof(hints));
+
+            hints.ai_family   = AF_INET_V;
+            if (udp) {
+                hints.ai_socktype = SOCK_DGRAM;
+                hints.ai_protocol = IPPROTO_UDP;
+            }
+        #ifdef WOLFSSL_SCTP
+            else if (sctp) {
+                hints.ai_socktype = SOCK_STREAM;
+                hints.ai_protocol = IPPROTO_SCTP;
+            }
+        #endif
+            else {
+                hints.ai_socktype = SOCK_STREAM;
+                hints.ai_protocol = IPPROTO_TCP;
+            }
+
+            SNPRINTF(strPort, sizeof(strPort), "%d", port);
+            strPort[79] = '\0';
+
+            ret = getaddrinfo(peer, strPort, &hints, &answer);
+            if (ret < 0 || answer == NULL)
+                err_sys("getaddrinfo failed");
+
+            XMEMCPY(addr, answer->ai_addr, answer->ai_addrlen);
+            freeaddrinfo(answer);
+        #else
+            printf("no ipv6 getaddrinfo, loopback only tests/examples\n");
+            addr->sin6_addr = in6addr_loopback;
+        #endif
+    }
+#endif
+}
+
+
+static WC_INLINE void tcp_socket(SOCKET_T* sockfd, int udp, int sctp)
+{
+    (void)sctp;
+
+    if (udp)
+        *sockfd = socket(AF_INET_V, SOCK_DGRAM, IPPROTO_UDP);
+#ifdef WOLFSSL_SCTP
+    else if (sctp)
+        *sockfd = socket(AF_INET_V, SOCK_STREAM, IPPROTO_SCTP);
+#endif
+    else
+        *sockfd = socket(AF_INET_V, SOCK_STREAM, IPPROTO_TCP);
+
+    if(WOLFSSL_SOCKET_IS_INVALID(*sockfd)) {
+        err_sys("socket failed\n");
+    }
+
+#ifndef USE_WINDOWS_API
+#ifdef SO_NOSIGPIPE
+    {
+        int       on = 1;
+        socklen_t len = sizeof(on);
+        int       res = setsockopt(*sockfd, SOL_SOCKET, SO_NOSIGPIPE, &on, len);
+        if (res < 0)
+            err_sys("setsockopt SO_NOSIGPIPE failed\n");
+    }
+#elif defined(WOLFSSL_MDK_ARM) || defined (WOLFSSL_TIRTOS) ||\
+                        defined(WOLFSSL_KEIL_TCP_NET) || defined(WOLFSSL_ZEPHYR)
+    /* nothing to define */
+#else  /* no S_NOSIGPIPE */
+    signal(SIGPIPE, SIG_IGN);
+#endif /* S_NOSIGPIPE */
+
+#if defined(TCP_NODELAY)
+    if (!udp && !sctp)
+    {
+        int       on = 1;
+        socklen_t len = sizeof(on);
+        int       res = setsockopt(*sockfd, IPPROTO_TCP, TCP_NODELAY, &on, len);
+        if (res < 0)
+            err_sys("setsockopt TCP_NODELAY failed\n");
+    }
+#endif
+#endif  /* USE_WINDOWS_API */
+}
+
+static WC_INLINE void tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port,
+                               int udp, int sctp, WOLFSSL* ssl)
+{
+    SOCKADDR_IN_T addr;
+    build_addr(&addr, ip, port, udp, sctp);
+    if (udp) {
+        wolfSSL_dtls_set_peer(ssl, &addr, sizeof(addr));
+    }
+    tcp_socket(sockfd, udp, sctp);
+
+    if (!udp) {
+        if (connect(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0)
+            err_sys("tcp connect failed");
+    }
+}
+
+
+static WC_INLINE void udp_connect(SOCKET_T* sockfd, void* addr, int addrSz)
+{
+    if (connect(*sockfd, (const struct sockaddr*)addr, addrSz) != 0)
+        err_sys("tcp connect failed");
+}
+
+
+enum {
+    TEST_SELECT_FAIL,
+    TEST_TIMEOUT,
+    TEST_RECV_READY,
+    TEST_SEND_READY,
+    TEST_ERROR_READY
+};
+
+
+#if !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_KEIL_TCP_NET) && \
+                                 !defined(WOLFSSL_TIRTOS)
+static WC_INLINE int tcp_select_ex(SOCKET_T socketfd, int to_sec, int rx)
+{
+    fd_set fds, errfds;
+    fd_set* recvfds = NULL;
+    fd_set* sendfds = NULL;
+    SOCKET_T nfds = socketfd + 1;
+#if !defined(__INTEGRITY)
+    struct timeval timeout = {(to_sec > 0) ? to_sec : 0, 0};
+#else
+    struct timeval timeout;
+#endif
+    int result;
+
+    FD_ZERO(&fds);
+    FD_SET(socketfd, &fds);
+    FD_ZERO(&errfds);
+    FD_SET(socketfd, &errfds);
+
+    if (rx)
+        recvfds = &fds;
+    else
+        sendfds = &fds;
+
+#if defined(__INTEGRITY)
+    timeout.tv_sec = (long long)(to_sec > 0) ? to_sec : 0, 0;
+#endif
+    result = select(nfds, recvfds, sendfds, &errfds, &timeout);
+
+    if (result == 0)
+        return TEST_TIMEOUT;
+    else if (result > 0) {
+        if (FD_ISSET(socketfd, &fds)) {
+            if (rx)
+                return TEST_RECV_READY;
+            else
+                return TEST_SEND_READY;
+        }
+        else if(FD_ISSET(socketfd, &errfds))
+            return TEST_ERROR_READY;
+    }
+
+    return TEST_SELECT_FAIL;
+}
+
+static WC_INLINE int tcp_select(SOCKET_T socketfd, int to_sec)
+{
+    return tcp_select_ex(socketfd, to_sec, 1);
+}
+
+static WC_INLINE int tcp_select_tx(SOCKET_T socketfd, int to_sec)
+{
+    return tcp_select_ex(socketfd, to_sec, 0);
+}
+
+#elif defined(WOLFSSL_TIRTOS) || defined(WOLFSSL_KEIL_TCP_NET)
+static WC_INLINE int tcp_select(SOCKET_T socketfd, int to_sec)
+{
+    return TEST_RECV_READY;
+}
+static WC_INLINE int tcp_select_tx(SOCKET_T socketfd, int to_sec)
+{
+    return TEST_SEND_READY;
+}
+#endif /* !WOLFSSL_MDK_ARM */
+
+
+static WC_INLINE void tcp_listen(SOCKET_T* sockfd, word16* port, int useAnyAddr,
+                              int udp, int sctp)
+{
+    SOCKADDR_IN_T addr;
+
+    /* don't use INADDR_ANY by default, firewall may block, make user switch
+       on */
+    build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSSLIP), *port, udp, sctp);
+    tcp_socket(sockfd, udp, sctp);
+
+#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_ARM)\
+                   && !defined(WOLFSSL_KEIL_TCP_NET) && !defined(WOLFSSL_ZEPHYR)
+    {
+        int       res, on  = 1;
+        socklen_t len = sizeof(on);
+        res = setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, &on, len);
+        if (res < 0)
+            err_sys("setsockopt SO_REUSEADDR failed\n");
+    }
+#endif
+
+    if (bind(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0)
+        err_sys("tcp bind failed");
+    if (!udp) {
+        #ifdef WOLFSSL_KEIL_TCP_NET
+            #define SOCK_LISTEN_MAX_QUEUE 1
+        #else
+            #define SOCK_LISTEN_MAX_QUEUE 5
+        #endif
+        if (listen(*sockfd, SOCK_LISTEN_MAX_QUEUE) != 0)
+                err_sys("tcp listen failed");
+    }
+    #if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_TIRTOS) \
+                                                     && !defined(WOLFSSL_ZEPHYR)
+        if (*port == 0) {
+            socklen_t len = sizeof(addr);
+            if (getsockname(*sockfd, (struct sockaddr*)&addr, &len) == 0) {
+                #ifndef TEST_IPV6
+                    *port = XNTOHS(addr.sin_port);
+                #else
+                    *port = XNTOHS(addr.sin6_port);
+                #endif
+            }
+        }
+    #endif
+}
+
+
+#if 0
+static WC_INLINE int udp_read_connect(SOCKET_T sockfd)
+{
+    SOCKADDR_IN_T cliaddr;
+    byte          b[1500];
+    int           n;
+    socklen_t     len = sizeof(cliaddr);
+
+    n = (int)recvfrom(sockfd, (char*)b, sizeof(b), MSG_PEEK,
+                      (struct sockaddr*)&cliaddr, &len);
+    if (n > 0) {
+        if (connect(sockfd, (const struct sockaddr*)&cliaddr,
+                    sizeof(cliaddr)) != 0)
+            err_sys("udp connect failed");
+    }
+    else
+        err_sys("recvfrom failed");
+
+    return sockfd;
+}
+#endif
+
+static WC_INLINE void udp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd,
+                              int useAnyAddr, word16 port, func_args* args)
+{
+    SOCKADDR_IN_T addr;
+
+    (void)args;
+    build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSSLIP), port, 1, 0);
+    tcp_socket(sockfd, 1, 0);
+
+
+#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_ARM) \
+                   && !defined(WOLFSSL_KEIL_TCP_NET) && !defined(WOLFSSL_ZEPHYR)
+    {
+        int       res, on  = 1;
+        socklen_t len = sizeof(on);
+        res = setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, &on, len);
+        if (res < 0)
+            err_sys("setsockopt SO_REUSEADDR failed\n");
+    }
+#endif
+
+    if (bind(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0)
+        err_sys("tcp bind failed");
+
+    #if (defined(NO_MAIN_DRIVER) && !defined(USE_WINDOWS_API)) && !defined(WOLFSSL_TIRTOS)
+        if (port == 0) {
+            socklen_t len = sizeof(addr);
+            if (getsockname(*sockfd, (struct sockaddr*)&addr, &len) == 0) {
+                #ifndef TEST_IPV6
+                    port = XNTOHS(addr.sin_port);
+                #else
+                    port = XNTOHS(addr.sin6_port);
+                #endif
+            }
+        }
+    #endif
+
+#if defined(_POSIX_THREADS) && defined(NO_MAIN_DRIVER) && !defined(__MINGW32__)
+    /* signal ready to accept data */
+    {
+    tcp_ready* ready = args->signal;
+    pthread_mutex_lock(&ready->mutex);
+    ready->ready = 1;
+    ready->port = port;
+    pthread_cond_signal(&ready->cond);
+    pthread_mutex_unlock(&ready->mutex);
+    }
+#elif defined (WOLFSSL_TIRTOS)
+    /* Need mutex? */
+    tcp_ready* ready = args->signal;
+    ready->ready = 1;
+    ready->port = port;
+#else
+    (void)port;
+#endif
+
+    *clientfd = *sockfd;
+}
+
+static WC_INLINE void tcp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd,
+                              func_args* args, word16 port, int useAnyAddr,
+                              int udp, int sctp, int ready_file, int do_listen)
+{
+    SOCKADDR_IN_T client;
+    socklen_t client_len = sizeof(client);
+    tcp_ready* ready = NULL;
+
+    (void) ready; /* Account for case when "ready" is not used */
+
+    if (udp) {
+        udp_accept(sockfd, clientfd, useAnyAddr, port, args);
+        return;
+    }
+
+    if(do_listen) {
+        tcp_listen(sockfd, &port, useAnyAddr, udp, sctp);
+
+    #if defined(_POSIX_THREADS) && defined(NO_MAIN_DRIVER) && !defined(__MINGW32__)
+        /* signal ready to tcp_accept */
+        if (args)
+            ready = args->signal;
+        if (ready) {
+            pthread_mutex_lock(&ready->mutex);
+            ready->ready = 1;
+            ready->port = port;
+            pthread_cond_signal(&ready->cond);
+            pthread_mutex_unlock(&ready->mutex);
+        }
+    #elif defined (WOLFSSL_TIRTOS)
+        /* Need mutex? */
+        if (args)
+            ready = args->signal;
+        if (ready) {
+            ready->ready = 1;
+            ready->port = port;
+        }
+    #endif
+
+        if (ready_file) {
+        #if !defined(NO_FILESYSTEM) || defined(FORCE_BUFFER_TEST)
+            XFILE srf = NULL;
+            if (args)
+                ready = args->signal;
+
+            if (ready) {
+                srf = XFOPEN(ready->srfName, "w");
+
+                if (srf) {
+                    /* let's write port sever is listening on to ready file
+                       external monitor can then do ephemeral ports by passing
+                       -p 0 to server on supported platforms with -R ready_file
+                       client can then wait for existence of ready_file and see
+                       which port the server is listening on. */
+                    fprintf(srf, "%d\n", (int)port);
+                    fclose(srf);
+                }
+            }
+        #endif
+        }
+    }
+
+    *clientfd = accept(*sockfd, (struct sockaddr*)&client,
+                      (ACCEPT_THIRD_T)&client_len);
+    if(WOLFSSL_SOCKET_IS_INVALID(*clientfd)) {
+        err_sys("tcp accept failed");
+    }
+}
+
+
+static WC_INLINE void tcp_set_nonblocking(SOCKET_T* sockfd)
+{
+    #ifdef USE_WINDOWS_API
+        unsigned long blocking = 1;
+        int ret = ioctlsocket(*sockfd, FIONBIO, &blocking);
+        if (ret == SOCKET_ERROR)
+            err_sys("ioctlsocket failed");
+    #elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) \
+        || defined (WOLFSSL_TIRTOS)|| defined(WOLFSSL_VXWORKS) \
+        || defined(WOLFSSL_ZEPHYR)
+         /* non blocking not supported, for now */
+    #else
+        int flags = fcntl(*sockfd, F_GETFL, 0);
+        if (flags < 0)
+            err_sys("fcntl get failed");
+        flags = fcntl(*sockfd, F_SETFL, flags | O_NONBLOCK);
+        if (flags < 0)
+            err_sys("fcntl set failed");
+    #endif
+}
+
+
+#ifndef NO_PSK
+
+/* identity is OpenSSL testing default for openssl s_client, keep same */
+static const char* kIdentityStr = "Client_identity";
+
+static WC_INLINE unsigned int my_psk_client_cb(WOLFSSL* ssl, const char* hint,
+        char* identity, unsigned int id_max_len, unsigned char* key,
+        unsigned int key_max_len)
+{
+    (void)ssl;
+    (void)hint;
+    (void)key_max_len;
+
+    /* see internal.h MAX_PSK_ID_LEN for PSK identity limit */
+    strncpy(identity, kIdentityStr, id_max_len);
+
+    if (wolfSSL_GetVersion(ssl) < WOLFSSL_TLSV1_3) {
+        /* test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using
+           unsigned binary */
+        key[0] = 0x1a;
+        key[1] = 0x2b;
+        key[2] = 0x3c;
+        key[3] = 0x4d;
+
+        return 4;   /* length of key in octets or 0 for error */
+    }
+    else {
+        int i;
+        int b = 0x01;
+
+        for (i = 0; i < 32; i++, b += 0x22) {
+            if (b >= 0x100)
+                b = 0x01;
+            key[i] = b;
+        }
+
+        return 32;   /* length of key in octets or 0 for error */
+    }
+}
+
+
+static WC_INLINE unsigned int my_psk_server_cb(WOLFSSL* ssl, const char* identity,
+        unsigned char* key, unsigned int key_max_len)
+{
+    (void)ssl;
+    (void)key_max_len;
+
+    /* see internal.h MAX_PSK_ID_LEN for PSK identity limit */
+    if (strncmp(identity, kIdentityStr, strlen(kIdentityStr)) != 0)
+        return 0;
+
+    if (wolfSSL_GetVersion(ssl) < WOLFSSL_TLSV1_3) {
+        /* test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using
+           unsigned binary */
+        key[0] = 0x1a;
+        key[1] = 0x2b;
+        key[2] = 0x3c;
+        key[3] = 0x4d;
+
+        return 4;   /* length of key in octets or 0 for error */
+    }
+    else {
+        int i;
+        int b = 0x01;
+
+        for (i = 0; i < 32; i++, b += 0x22) {
+            if (b >= 0x100)
+                b = 0x01;
+            key[i] = b;
+        }
+
+        return 32;   /* length of key in octets or 0 for error */
+    }
+}
+
+
+static WC_INLINE unsigned int my_psk_client_tls13_cb(WOLFSSL* ssl,
+        const char* hint, char* identity, unsigned int id_max_len,
+        unsigned char* key, unsigned int key_max_len, const char** ciphersuite)
+{
+    int i;
+    int b = 0x01;
+
+    (void)ssl;
+    (void)hint;
+    (void)key_max_len;
+
+    /* see internal.h MAX_PSK_ID_LEN for PSK identity limit */
+    strncpy(identity, kIdentityStr, id_max_len);
+
+    for (i = 0; i < 32; i++, b += 0x22) {
+        if (b >= 0x100)
+            b = 0x01;
+        key[i] = b;
+    }
+
+    *ciphersuite = "TLS13-AES128-GCM-SHA256";
+
+    return 32;   /* length of key in octets or 0 for error */
+}
+
+
+static WC_INLINE unsigned int my_psk_server_tls13_cb(WOLFSSL* ssl,
+        const char* identity, unsigned char* key, unsigned int key_max_len,
+        const char** ciphersuite)
+{
+    int i;
+    int b = 0x01;
+
+    (void)ssl;
+    (void)key_max_len;
+
+    /* see internal.h MAX_PSK_ID_LEN for PSK identity limit */
+    if (strncmp(identity, kIdentityStr, strlen(kIdentityStr)) != 0)
+        return 0;
+
+    for (i = 0; i < 32; i++, b += 0x22) {
+        if (b >= 0x100)
+            b = 0x01;
+        key[i] = b;
+    }
+
+    *ciphersuite = "TLS13-AES128-GCM-SHA256";
+
+    return 32;   /* length of key in octets or 0 for error */
+}
+
+#endif /* NO_PSK */
+
+
+#if defined(WOLFSSL_USER_CURRTIME)
+    extern   double current_time(int reset);
+
+#elif defined(USE_WINDOWS_API)
+
+    #define WIN32_LEAN_AND_MEAN
+    #include <windows.h>
+
+    static WC_INLINE double current_time(int reset)
+    {
+        static int init = 0;
+        static LARGE_INTEGER freq;
+
+        LARGE_INTEGER count;
+
+        if (!init) {
+            QueryPerformanceFrequency(&freq);
+            init = 1;
+        }
+
+        QueryPerformanceCounter(&count);
+
+        (void)reset;
+        return (double)count.QuadPart / freq.QuadPart;
+    }
+
+#elif defined(WOLFSSL_TIRTOS)
+    extern double current_time();
+#elif defined(WOLFSSL_ZEPHYR)
+    extern double current_time();
+#else
+
+#if !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_KEIL_TCP_NET) && !defined(WOLFSSL_CHIBIOS)
+    #include <sys/time.h>
+
+    static WC_INLINE double current_time(int reset)
+    {
+        struct timeval tv;
+        gettimeofday(&tv, 0);
+        (void)reset;
+
+        return (double)tv.tv_sec + (double)tv.tv_usec / 1000000;
+    }
+#else
+    extern double current_time(int reset);
+#endif
+#endif /* USE_WINDOWS_API */
+
+
+#if defined(HAVE_OCSP) && defined(WOLFSSL_NONBLOCK_OCSP)
+static WC_INLINE int OCSPIOCb(void* ioCtx, const char* url, int urlSz,
+    unsigned char* request, int requestSz, unsigned char** response)
+{
+#ifdef TEST_NONBLOCK_CERTS
+    static int ioCbCnt = 0;
+#endif
+
+    (void)ioCtx;
+    (void)url;
+    (void)urlSz;
+    (void)request;
+    (void)requestSz;
+    (void)response;
+
+#ifdef TEST_NONBLOCK_CERTS
+    if (ioCbCnt) {
+        ioCbCnt = 0;
+        return EmbedOcspLookup(ioCtx, url, urlSz, request, requestSz, response);
+    }
+    else {
+        ioCbCnt = 1;
+        return WOLFSSL_CBIO_ERR_WANT_READ;
+    }
+#else
+    return EmbedOcspLookup(ioCtx, url, urlSz, request, requestSz, response);
+#endif
+}
+
+static WC_INLINE void OCSPRespFreeCb(void* ioCtx, unsigned char* response)
+{
+    (void)ioCtx;
+    (void)response;
+}
+#endif
+
+#if !defined(NO_CERTS)
+    #if !defined(NO_FILESYSTEM) || \
+        (defined(NO_FILESYSTEM) && defined(FORCE_BUFFER_TEST))
+
+    /* reads file size, allocates buffer, reads into buffer, returns buffer */
+    static WC_INLINE int load_file(const char* fname, byte** buf, size_t* bufLen)
+    {
+        int ret;
+        long int fileSz;
+        XFILE file;
+
+        if (fname == NULL || buf == NULL || bufLen == NULL)
+            return BAD_FUNC_ARG;
+
+        /* set defaults */
+        *buf = NULL;
+        *bufLen = 0;
+
+        /* open file (read-only binary) */
+        file = XFOPEN(fname, "rb");
+        if (!file) {
+            printf("Error loading %s\n", fname);
+            return BAD_PATH_ERROR;
+        }
+
+        fseek(file, 0, SEEK_END);
+        fileSz = (int)ftell(file);
+        rewind(file);
+        if (fileSz  > 0) {
+            *bufLen = (size_t)fileSz;
+            *buf = (byte*)malloc(*bufLen);
+            if (*buf == NULL) {
+                ret = MEMORY_E;
+                printf("Error allocating %lu bytes\n", (unsigned long)*bufLen);
+            }
+            else {
+                size_t readLen = fread(*buf, *bufLen, 1, file);
+
+                /* check response code */
+                ret = (readLen > 0) ? 0 : -1;
+            }
+        }
+        else {
+            ret = BUFFER_E;
+        }
+        fclose(file);
+
+        return ret;
+    }
+
+    enum {
+        WOLFSSL_CA   = 1,
+        WOLFSSL_CERT = 2,
+        WOLFSSL_KEY  = 3,
+        WOLFSSL_CERT_CHAIN = 4,
+    };
+
+    static WC_INLINE void load_buffer(WOLFSSL_CTX* ctx, const char* fname, int type)
+    {
+        int format = WOLFSSL_FILETYPE_PEM;
+        byte* buff = NULL;
+        size_t sz = 0;
+
+        if (load_file(fname, &buff, &sz) != 0) {
+            err_sys("can't open file for buffer load "
+                    "Please run from wolfSSL home directory if not");
+        }
+
+        /* determine format */
+        if (strstr(fname, ".der"))
+            format = WOLFSSL_FILETYPE_ASN1;
+
+        if (type == WOLFSSL_CA) {
+            if (wolfSSL_CTX_load_verify_buffer(ctx, buff, (long)sz, format)
+                                              != WOLFSSL_SUCCESS)
+                err_sys("can't load buffer ca file");
+        }
+        else if (type == WOLFSSL_CERT) {
+            if (wolfSSL_CTX_use_certificate_buffer(ctx, buff, (long)sz,
+                        format) != WOLFSSL_SUCCESS)
+                err_sys("can't load buffer cert file");
+        }
+        else if (type == WOLFSSL_KEY) {
+            if (wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, (long)sz,
+                        format) != WOLFSSL_SUCCESS)
+                err_sys("can't load buffer key file");
+        }
+        else if (type == WOLFSSL_CERT_CHAIN) {
+            if (wolfSSL_CTX_use_certificate_chain_buffer_format(ctx, buff,
+                    (long)sz, format) != WOLFSSL_SUCCESS)
+                err_sys("can't load cert chain buffer");
+        }
+
+        if (buff)
+            free(buff);
+    }
+
+    static WC_INLINE void load_ssl_buffer(WOLFSSL* ssl, const char* fname, int type)
+    {
+        int format = WOLFSSL_FILETYPE_PEM;
+        byte* buff = NULL;
+        size_t sz = 0;
+
+        if (load_file(fname, &buff, &sz) != 0) {
+            err_sys("can't open file for buffer load "
+                    "Please run from wolfSSL home directory if not");
+        }
+
+        /* determine format */
+        if (strstr(fname, ".der"))
+            format = WOLFSSL_FILETYPE_ASN1;
+
+        if (type == WOLFSSL_CA) {
+            /* verify certs (CA's) use the shared ctx->cm (WOLFSSL_CERT_MANAGER) */
+            WOLFSSL_CTX* ctx = wolfSSL_get_SSL_CTX(ssl);
+            if (wolfSSL_CTX_load_verify_buffer(ctx, buff, (long)sz, format)
+                                              != WOLFSSL_SUCCESS)
+                err_sys("can't load buffer ca file");
+        }
+        else if (type == WOLFSSL_CERT) {
+            if (wolfSSL_use_certificate_buffer(ssl, buff, (long)sz,
+                        format) != WOLFSSL_SUCCESS)
+                err_sys("can't load buffer cert file");
+        }
+        else if (type == WOLFSSL_KEY) {
+            if (wolfSSL_use_PrivateKey_buffer(ssl, buff, (long)sz,
+                        format) != WOLFSSL_SUCCESS)
+                err_sys("can't load buffer key file");
+        }
+        else if (type == WOLFSSL_CERT_CHAIN) {
+            if (wolfSSL_use_certificate_chain_buffer_format(ssl, buff,
+                    (long)sz, format) != WOLFSSL_SUCCESS)
+                err_sys("can't load cert chain buffer");
+        }
+
+        if (buff)
+            free(buff);
+    }
+
+    #ifdef TEST_PK_PRIVKEY
+    static WC_INLINE int load_key_file(const char* fname, byte** derBuf, word32* derLen)
+    {
+        int ret;
+        byte* buf = NULL;
+        size_t bufLen;
+
+        ret = load_file(fname, &buf, &bufLen);
+        if (ret != 0)
+            return ret;
+
+        *derBuf = (byte*)malloc(bufLen);
+        if (*derBuf == NULL) {
+            free(buf);
+            return MEMORY_E;
+        }
+
+        ret = wc_KeyPemToDer(buf, (word32)bufLen, *derBuf, (word32)bufLen, NULL);
+        if (ret < 0) {
+            free(buf);
+            free(*derBuf);
+            return ret;
+        }
+        *derLen = ret;
+        free(buf);
+
+        return 0;
+    }
+    #endif /* TEST_PK_PRIVKEY */
+
+    #endif /* !NO_FILESYSTEM || (NO_FILESYSTEM && FORCE_BUFFER_TEST) */
+#endif /* !NO_CERTS */
+
+static int myVerifyFail = 0;
+
+/* The verify callback is called for every certificate only when
+ * --enable-opensslextra is defined because it sets WOLFSSL_ALWAYS_VERIFY_CB and
+ * WOLFSSL_VERIFY_CB_ALL_CERTS.
+ * Normal cases of the verify callback only occur on certificate failures when the
+ * wolfSSL_set_verify(ssl, SSL_VERIFY_PEER, myVerifyCb); is called
+*/
+
+static WC_INLINE int myVerify(int preverify, WOLFSSL_X509_STORE_CTX* store)
+{
+    char buffer[WOLFSSL_MAX_ERROR_SZ];
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+    WOLFSSL_X509* peer;
+#if defined(SHOW_CERTS) && !defined(NO_FILESYSTEM)
+    WOLFSSL_BIO* bio = NULL;
+    WOLFSSL_STACK* sk = NULL;
+    X509* x509 = NULL;
+    int i = 0;
+#endif
+#endif
+    (void)preverify;
+
+    /* Verify Callback Arguments:
+     * preverify:           1=Verify Okay, 0=Failure
+     * store->error:        Failure error code (0 indicates no failure)
+     * store->current_cert: Current WOLFSSL_X509 object (only with OPENSSL_EXTRA)
+     * store->error_depth:  Current Index
+     * store->domain:       Subject CN as string (null term)
+     * store->totalCerts:   Number of certs presented by peer
+     * store->certs[i]:     A `WOLFSSL_BUFFER_INFO` with plain DER for each cert
+     * store->store:        WOLFSSL_X509_STORE with CA cert chain
+     * store->store->cm:    WOLFSSL_CERT_MANAGER
+     * store->ex_data:      The WOLFSSL object pointer
+     * store->discardSessionCerts: When set to non-zero value session certs
+        will be discarded (only with SESSION_CERTS)
+     */
+
+    printf("In verification callback, error = %d, %s\n", store->error,
+                                 wolfSSL_ERR_error_string(store->error, buffer));
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+    peer = store->current_cert;
+    if (peer) {
+        char* issuer  = wolfSSL_X509_NAME_oneline(
+                                       wolfSSL_X509_get_issuer_name(peer), 0, 0);
+        char* subject = wolfSSL_X509_NAME_oneline(
+                                      wolfSSL_X509_get_subject_name(peer), 0, 0);
+        printf("\tPeer's cert info:\n issuer : %s\n subject: %s\n", issuer,
+                                                                  subject);
+        XFREE(subject, 0, DYNAMIC_TYPE_OPENSSL);
+        XFREE(issuer,  0, DYNAMIC_TYPE_OPENSSL);
+#if defined(SHOW_CERTS) && !defined(NO_FILESYSTEM)
+/* avoid printing duplicate certs */
+        if (store->depth == 1) {
+            /* retrieve x509 certs and display them on stdout */
+            sk = wolfSSL_X509_STORE_GetCerts(store);
+
+            for (i = 0; i < wolfSSL_sk_X509_num(sk); i++) {
+                x509 = wolfSSL_sk_X509_value(sk, i);
+                bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file());
+                if (bio != NULL) {
+                    wolfSSL_BIO_set_fp(bio, stdout, BIO_NOCLOSE);
+                    wolfSSL_X509_print(bio, x509);
+                    wolfSSL_BIO_free(bio);
+                }
+            }
+            wolfSSL_sk_X509_free(sk);
+        }
+#endif
+    }
+    else
+        printf("\tPeer has no cert!\n");
+#else
+    printf("\tPeer certs: %d\n", store->totalCerts);
+    #ifdef SHOW_CERTS
+    {   int i;
+        for (i=0; i<store->totalCerts; i++) {
+            WOLFSSL_BUFFER_INFO* cert = &store->certs[i];
+            printf("\t\tCert %d: Ptr %p, Len %u\n", i, cert->buffer, cert->length);
+        }
+    }
+    #endif /* SHOW_CERTS */
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+
+    printf("\tSubject's domain name at %d is %s\n", store->error_depth, store->domain);
+
+    /* Testing forced fail case by return zero */
+    if (myVerifyFail) {
+        return 0; /* test failure case */
+    }
+
+    /* If error indicate we are overriding it for testing purposes */
+    if (store->error != 0) {
+        printf("\tAllowing failed certificate check, testing only "
+            "(shouldn't do this in production)\n");
+    }
+
+    /* A non-zero return code indicates failure override */
+    return 1;
+}
+
+
+static WC_INLINE int myDateCb(int preverify, WOLFSSL_X509_STORE_CTX* store)
+{
+    char buffer[WOLFSSL_MAX_ERROR_SZ];
+    (void)preverify;
+
+    printf("In verification callback, error = %d, %s\n", store->error,
+                                 wolfSSL_ERR_error_string(store->error, buffer));
+    printf("Subject's domain name is %s\n", store->domain);
+
+    if (store->error == ASN_BEFORE_DATE_E || store->error == ASN_AFTER_DATE_E) {
+        printf("Overriding cert date error as example for bad clock testing\n");
+        return 1;
+    }
+    printf("Cert error is not date error, not overriding\n");
+
+    return 0;
+}
+
+
+#ifdef HAVE_EXT_CACHE
+
+static WC_INLINE WOLFSSL_SESSION* mySessGetCb(WOLFSSL* ssl, unsigned char* id,
+    int id_len, int* copy)
+{
+    (void)ssl;
+    (void)id;
+    (void)id_len;
+    (void)copy;
+
+    /* using internal cache, this is for testing only */
+    return NULL;
+}
+
+static WC_INLINE int mySessNewCb(WOLFSSL* ssl, WOLFSSL_SESSION* session)
+{
+    (void)ssl;
+    (void)session;
+
+    /* using internal cache, this is for testing only */
+    return 0;
+}
+
+static WC_INLINE void mySessRemCb(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session)
+{
+    (void)ctx;
+    (void)session;
+
+    /* using internal cache, this is for testing only */
+}
+
+#endif /* HAVE_EXT_CACHE */
+
+
+#ifdef HAVE_CRL
+
+static WC_INLINE void CRL_CallBack(const char* url)
+{
+    printf("CRL callback url = %s\n", url);
+}
+
+#endif
+
+#ifndef NO_DH
+static WC_INLINE void SetDH(WOLFSSL* ssl)
+{
+    /* dh1024 p */
+    static const unsigned char p[] =
+    {
+        0xE6, 0x96, 0x9D, 0x3D, 0x49, 0x5B, 0xE3, 0x2C, 0x7C, 0xF1, 0x80, 0xC3,
+        0xBD, 0xD4, 0x79, 0x8E, 0x91, 0xB7, 0x81, 0x82, 0x51, 0xBB, 0x05, 0x5E,
+        0x2A, 0x20, 0x64, 0x90, 0x4A, 0x79, 0xA7, 0x70, 0xFA, 0x15, 0xA2, 0x59,
+        0xCB, 0xD5, 0x23, 0xA6, 0xA6, 0xEF, 0x09, 0xC4, 0x30, 0x48, 0xD5, 0xA2,
+        0x2F, 0x97, 0x1F, 0x3C, 0x20, 0x12, 0x9B, 0x48, 0x00, 0x0E, 0x6E, 0xDD,
+        0x06, 0x1C, 0xBC, 0x05, 0x3E, 0x37, 0x1D, 0x79, 0x4E, 0x53, 0x27, 0xDF,
+        0x61, 0x1E, 0xBB, 0xBE, 0x1B, 0xAC, 0x9B, 0x5C, 0x60, 0x44, 0xCF, 0x02,
+        0x3D, 0x76, 0xE0, 0x5E, 0xEA, 0x9B, 0xAD, 0x99, 0x1B, 0x13, 0xA6, 0x3C,
+        0x97, 0x4E, 0x9E, 0xF1, 0x83, 0x9E, 0xB5, 0xDB, 0x12, 0x51, 0x36, 0xF7,
+        0x26, 0x2E, 0x56, 0xA8, 0x87, 0x15, 0x38, 0xDF, 0xD8, 0x23, 0xC6, 0x50,
+        0x50, 0x85, 0xE2, 0x1F, 0x0D, 0xD5, 0xC8, 0x6B,
+    };
+
+    /* dh1024 g */
+    static const unsigned char g[] =
+    {
+      0x02,
+    };
+
+    wolfSSL_SetTmpDH(ssl, p, sizeof(p), g, sizeof(g));
+}
+
+static WC_INLINE void SetDHCtx(WOLFSSL_CTX* ctx)
+{
+    /* dh1024 p */
+    static const unsigned char p[] =
+    {
+        0xE6, 0x96, 0x9D, 0x3D, 0x49, 0x5B, 0xE3, 0x2C, 0x7C, 0xF1, 0x80, 0xC3,
+        0xBD, 0xD4, 0x79, 0x8E, 0x91, 0xB7, 0x81, 0x82, 0x51, 0xBB, 0x05, 0x5E,
+        0x2A, 0x20, 0x64, 0x90, 0x4A, 0x79, 0xA7, 0x70, 0xFA, 0x15, 0xA2, 0x59,
+        0xCB, 0xD5, 0x23, 0xA6, 0xA6, 0xEF, 0x09, 0xC4, 0x30, 0x48, 0xD5, 0xA2,
+        0x2F, 0x97, 0x1F, 0x3C, 0x20, 0x12, 0x9B, 0x48, 0x00, 0x0E, 0x6E, 0xDD,
+        0x06, 0x1C, 0xBC, 0x05, 0x3E, 0x37, 0x1D, 0x79, 0x4E, 0x53, 0x27, 0xDF,
+        0x61, 0x1E, 0xBB, 0xBE, 0x1B, 0xAC, 0x9B, 0x5C, 0x60, 0x44, 0xCF, 0x02,
+        0x3D, 0x76, 0xE0, 0x5E, 0xEA, 0x9B, 0xAD, 0x99, 0x1B, 0x13, 0xA6, 0x3C,
+        0x97, 0x4E, 0x9E, 0xF1, 0x83, 0x9E, 0xB5, 0xDB, 0x12, 0x51, 0x36, 0xF7,
+        0x26, 0x2E, 0x56, 0xA8, 0x87, 0x15, 0x38, 0xDF, 0xD8, 0x23, 0xC6, 0x50,
+        0x50, 0x85, 0xE2, 0x1F, 0x0D, 0xD5, 0xC8, 0x6B,
+    };
+
+    /* dh1024 g */
+    static const unsigned char g[] =
+    {
+      0x02,
+    };
+
+    wolfSSL_CTX_SetTmpDH(ctx, p, sizeof(p), g, sizeof(g));
+}
+#endif /* NO_DH */
+
+#ifndef NO_CERTS
+
+static WC_INLINE void CaCb(unsigned char* der, int sz, int type)
+{
+    (void)der;
+    printf("Got CA cache add callback, derSz = %d, type = %d\n", sz, type);
+}
+
+#endif /* !NO_CERTS */
+
+
+/* Wolf Root Directory Helper */
+/* KEIL-RL File System does not support relative directory */
+#if !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_KEIL_FS) && !defined(WOLFSSL_TIRTOS)
+    /* Maximum depth to search for WolfSSL root */
+    #define MAX_WOLF_ROOT_DEPTH 5
+
+    static WC_INLINE int ChangeToWolfRoot(void)
+    {
+        #if !defined(NO_FILESYSTEM) || defined(FORCE_BUFFER_TEST)
+            int depth, res;
+            XFILE file;
+            for(depth = 0; depth <= MAX_WOLF_ROOT_DEPTH; depth++) {
+                file = XFOPEN(ntruKeyFile, "rb");
+                if (file != NULL) {
+                    fclose(file);
+                    return depth;
+                }
+            #ifdef USE_WINDOWS_API
+                res = SetCurrentDirectoryA("..\\");
+            #else
+                res = chdir("../");
+            #endif
+                if (res < 0) {
+                    printf("chdir to ../ failed!\n");
+                    break;
+                }
+            }
+
+            err_sys("wolf root not found");
+            return -1;
+        #else
+            return 0;
+        #endif
+    }
+#endif /* !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_KEIL_FS) && !defined(WOLFSSL_TIRTOS) */
+
+#ifdef HAVE_STACK_SIZE
+
+typedef THREAD_RETURN WOLFSSL_THREAD (*thread_func)(void* args);
+#define STACK_CHECK_VAL 0x01
+
+static WC_INLINE int StackSizeCheck(func_args* args, thread_func tf)
+{
+    int            ret, i, used;
+    void*          status;
+    unsigned char* myStack = NULL;
+    int            stackSize = 1024*152;
+    pthread_attr_t myAttr;
+    pthread_t      threadId;
+
+#ifdef PTHREAD_STACK_MIN
+    if (stackSize < PTHREAD_STACK_MIN)
+        stackSize = PTHREAD_STACK_MIN;
+#endif
+
+    ret = posix_memalign((void**)&myStack, sysconf(_SC_PAGESIZE), stackSize);
+    if (ret != 0 || myStack == NULL)
+        err_sys("posix_memalign failed\n");
+
+    XMEMSET(myStack, STACK_CHECK_VAL, stackSize);
+
+    ret = pthread_attr_init(&myAttr);
+    if (ret != 0)
+        err_sys("attr_init failed");
+
+    ret = pthread_attr_setstack(&myAttr, myStack, stackSize);
+    if (ret != 0)
+        err_sys("attr_setstackaddr failed");
+
+    ret = pthread_create(&threadId, &myAttr, tf, args);
+    if (ret != 0) {
+        perror("pthread_create failed");
+        exit(EXIT_FAILURE);
+    }
+
+    ret = pthread_join(threadId, &status);
+    if (ret != 0)
+        err_sys("pthread_join failed");
+
+    for (i = 0; i < stackSize; i++) {
+        if (myStack[i] != STACK_CHECK_VAL) {
+            break;
+        }
+    }
+
+    free(myStack);
+
+    used = stackSize - i;
+    printf("stack used = %d\n", used);
+
+    return (int)((size_t)status);
+}
+
+
+#endif /* HAVE_STACK_SIZE */
+
+
+#ifdef STACK_TRAP
+
+/* good settings
+   --enable-debug --disable-shared C_EXTRA_FLAGS="-DUSER_TIME -DTFM_TIMING_RESISTANT -DPOSITIVE_EXP_ONLY -DSTACK_TRAP"
+
+*/
+
+#ifdef HAVE_STACK_SIZE
+    /* client only for now, setrlimit will fail if pthread_create() called */
+    /* STACK_SIZE does pthread_create() on client */
+    #error "can't use STACK_TRAP with STACK_SIZE, setrlimit will fail"
+#endif /* HAVE_STACK_SIZE */
+
+static WC_INLINE void StackTrap(void)
+{
+    struct rlimit  rl;
+    if (getrlimit(RLIMIT_STACK, &rl) != 0)
+        err_sys("getrlimit failed");
+    printf("rlim_cur = %llu\n", rl.rlim_cur);
+    rl.rlim_cur = 1024*21;  /* adjust trap size here */
+    if (setrlimit(RLIMIT_STACK, &rl) != 0) {
+        perror("setrlimit");
+        err_sys("setrlimit failed");
+    }
+}
+
+#else /* STACK_TRAP */
+
+static WC_INLINE void StackTrap(void)
+{
+}
+
+#endif /* STACK_TRAP */
+
+
+#if defined(ATOMIC_USER) && !defined(WOLFSSL_AEAD_ONLY)
+
+/* Atomic Encrypt Context example */
+typedef struct AtomicEncCtx {
+    int  keySetup;           /* have we done key setup yet */
+    Aes  aes;                /* for aes example */
+} AtomicEncCtx;
+
+
+/* Atomic Decrypt Context example */
+typedef struct AtomicDecCtx {
+    int  keySetup;           /* have we done key setup yet */
+    Aes  aes;                /* for aes example */
+} AtomicDecCtx;
+
+
+static WC_INLINE int myMacEncryptCb(WOLFSSL* ssl, unsigned char* macOut,
+       const unsigned char* macIn, unsigned int macInSz, int macContent,
+       int macVerify, unsigned char* encOut, const unsigned char* encIn,
+       unsigned int encSz, void* ctx)
+{
+    int  ret;
+    Hmac hmac;
+    byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ];
+    AtomicEncCtx* encCtx = (AtomicEncCtx*)ctx;
+    const char* tlsStr = "TLS";
+
+    /* example supports (d)tls aes */
+    if (wolfSSL_GetBulkCipher(ssl) != wolfssl_aes) {
+        printf("myMacEncryptCb not using AES\n");
+        return -1;
+    }
+
+    if (strstr(wolfSSL_get_version(ssl), tlsStr) == NULL) {
+        printf("myMacEncryptCb not using (D)TLS\n");
+        return -1;
+    }
+
+    /* hmac, not needed if aead mode */
+    wolfSSL_SetTlsHmacInner(ssl, myInner, macInSz, macContent, macVerify);
+
+    ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID);
+    if (ret != 0)
+        return ret;
+    ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl),
+               wolfSSL_GetMacSecret(ssl, macVerify), wolfSSL_GetHmacSize(ssl));
+    if (ret != 0)
+        return ret;
+    ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner));
+    if (ret != 0)
+        return ret;
+    ret = wc_HmacUpdate(&hmac, macIn, macInSz);
+    if (ret != 0)
+        return ret;
+    ret = wc_HmacFinal(&hmac, macOut);
+    if (ret != 0)
+        return ret;
+
+
+    /* encrypt setup on first time */
+    if (encCtx->keySetup == 0) {
+        int   keyLen = wolfSSL_GetKeySize(ssl);
+        const byte* key;
+        const byte* iv;
+
+        if (wolfSSL_GetSide(ssl) == WOLFSSL_CLIENT_END) {
+            key = wolfSSL_GetClientWriteKey(ssl);
+            iv  = wolfSSL_GetClientWriteIV(ssl);
+        }
+        else {
+            key = wolfSSL_GetServerWriteKey(ssl);
+            iv  = wolfSSL_GetServerWriteIV(ssl);
+        }
+
+        ret = wc_AesSetKey(&encCtx->aes, key, keyLen, iv, AES_ENCRYPTION);
+        if (ret != 0) {
+            printf("AesSetKey failed in myMacEncryptCb\n");
+            return ret;
+        }
+        encCtx->keySetup = 1;
+    }
+
+    /* encrypt */
+    return wc_AesCbcEncrypt(&encCtx->aes, encOut, encIn, encSz);
+}
+
+
+static WC_INLINE int myDecryptVerifyCb(WOLFSSL* ssl,
+       unsigned char* decOut, const unsigned char* decIn,
+       unsigned int decSz, int macContent, int macVerify,
+       unsigned int* padSz, void* ctx)
+{
+    AtomicDecCtx* decCtx = (AtomicDecCtx*)ctx;
+    int ret      = 0;
+    int macInSz  = 0;
+    int ivExtra  = 0;
+    int digestSz = wolfSSL_GetHmacSize(ssl);
+    unsigned int pad     = 0;
+    unsigned int padByte = 0;
+    Hmac hmac;
+    byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ];
+    byte verify[WC_MAX_DIGEST_SIZE];
+    const char* tlsStr = "TLS";
+
+    /* example supports (d)tls aes */
+    if (wolfSSL_GetBulkCipher(ssl) != wolfssl_aes) {
+        printf("myMacEncryptCb not using AES\n");
+        return -1;
+    }
+
+    if (strstr(wolfSSL_get_version(ssl), tlsStr) == NULL) {
+        printf("myMacEncryptCb not using (D)TLS\n");
+        return -1;
+    }
+
+    /*decrypt */
+    if (decCtx->keySetup == 0) {
+        int   keyLen = wolfSSL_GetKeySize(ssl);
+        const byte* key;
+        const byte* iv;
+
+        /* decrypt is from other side (peer) */
+        if (wolfSSL_GetSide(ssl) == WOLFSSL_SERVER_END) {
+            key = wolfSSL_GetClientWriteKey(ssl);
+            iv  = wolfSSL_GetClientWriteIV(ssl);
+        }
+        else {
+            key = wolfSSL_GetServerWriteKey(ssl);
+            iv  = wolfSSL_GetServerWriteIV(ssl);
+        }
+
+        ret = wc_AesSetKey(&decCtx->aes, key, keyLen, iv, AES_DECRYPTION);
+        if (ret != 0) {
+            printf("AesSetKey failed in myDecryptVerifyCb\n");
+            return ret;
+        }
+        decCtx->keySetup = 1;
+    }
+
+    /* decrypt */
+    ret = wc_AesCbcDecrypt(&decCtx->aes, decOut, decIn, decSz);
+    if (ret != 0)
+        return ret;
+
+    if (wolfSSL_GetCipherType(ssl) == WOLFSSL_AEAD_TYPE) {
+        *padSz = wolfSSL_GetAeadMacSize(ssl);
+        return 0; /* hmac, not needed if aead mode */
+    }
+
+    if (wolfSSL_GetCipherType(ssl) == WOLFSSL_BLOCK_TYPE) {
+        pad     = *(decOut + decSz - 1);
+        padByte = 1;
+        if (wolfSSL_IsTLSv1_1(ssl))
+            ivExtra = wolfSSL_GetCipherBlockSize(ssl);
+    }
+
+    *padSz  = wolfSSL_GetHmacSize(ssl) + pad + padByte;
+    macInSz = decSz - ivExtra - digestSz - pad - padByte;
+
+    wolfSSL_SetTlsHmacInner(ssl, myInner, macInSz, macContent, macVerify);
+
+    ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID);
+    if (ret != 0)
+        return ret;
+    ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl),
+               wolfSSL_GetMacSecret(ssl, macVerify), digestSz);
+    if (ret != 0)
+        return ret;
+    ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner));
+    if (ret != 0)
+        return ret;
+    ret = wc_HmacUpdate(&hmac, decOut + ivExtra, macInSz);
+    if (ret != 0)
+        return ret;
+    ret = wc_HmacFinal(&hmac, verify);
+    if (ret != 0)
+        return ret;
+
+    if (XMEMCMP(verify, decOut + decSz - digestSz - pad - padByte,
+               digestSz) != 0) {
+        printf("myDecryptVerify verify failed\n");
+        return -1;
+    }
+
+    return ret;
+}
+
+#if defined(HAVE_ENCRYPT_THEN_MAC)
+
+static WC_INLINE int myEncryptMacCb(WOLFSSL* ssl, unsigned char* macOut,
+       int content, int macVerify, unsigned char* encOut,
+       const unsigned char* encIn, unsigned int encSz, void* ctx)
+{
+    int  ret;
+    Hmac hmac;
+    AtomicEncCtx* encCtx = (AtomicEncCtx*)ctx;
+    byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ];
+    const char* tlsStr = "TLS";
+
+    /* example supports (d)tls aes */
+    if (wolfSSL_GetBulkCipher(ssl) != wolfssl_aes) {
+        printf("myMacEncryptCb not using AES\n");
+        return -1;
+    }
+
+    if (strstr(wolfSSL_get_version(ssl), tlsStr) == NULL) {
+        printf("myMacEncryptCb not using (D)TLS\n");
+        return -1;
+    }
+
+    /* encrypt setup on first time */
+    if (encCtx->keySetup == 0) {
+        int   keyLen = wolfSSL_GetKeySize(ssl);
+        const byte* key;
+        const byte* iv;
+
+        if (wolfSSL_GetSide(ssl) == WOLFSSL_CLIENT_END) {
+            key = wolfSSL_GetClientWriteKey(ssl);
+            iv  = wolfSSL_GetClientWriteIV(ssl);
+        }
+        else {
+            key = wolfSSL_GetServerWriteKey(ssl);
+            iv  = wolfSSL_GetServerWriteIV(ssl);
+        }
+
+        ret = wc_AesSetKey(&encCtx->aes, key, keyLen, iv, AES_ENCRYPTION);
+        if (ret != 0) {
+            printf("AesSetKey failed in myMacEncryptCb\n");
+            return ret;
+        }
+        encCtx->keySetup = 1;
+    }
+
+    /* encrypt */
+    ret = wc_AesCbcEncrypt(&encCtx->aes, encOut, encIn, encSz);
+    if (ret != 0)
+        return ret;
+
+    /* Reconstruct record header. */
+    wolfSSL_SetTlsHmacInner(ssl, myInner, encSz, content, macVerify);
+
+    ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID);
+    if (ret != 0)
+        return ret;
+    ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl),
+               wolfSSL_GetMacSecret(ssl, macVerify), wolfSSL_GetHmacSize(ssl));
+    if (ret != 0)
+        return ret;
+    ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner));
+    if (ret != 0)
+        return ret;
+    ret = wc_HmacUpdate(&hmac, encOut, encSz);
+    if (ret != 0)
+        return ret;
+    return wc_HmacFinal(&hmac, macOut);
+}
+
+
+static WC_INLINE int myVerifyDecryptCb(WOLFSSL* ssl,
+       unsigned char* decOut, const unsigned char* decIn,
+       unsigned int decSz, int content, int macVerify,
+       unsigned int* padSz, void* ctx)
+{
+    AtomicDecCtx* decCtx = (AtomicDecCtx*)ctx;
+    int ret      = 0;
+    int digestSz = wolfSSL_GetHmacSize(ssl);
+    Hmac hmac;
+    byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ];
+    byte verify[WC_MAX_DIGEST_SIZE];
+    const char* tlsStr = "TLS";
+
+    /* example supports (d)tls aes */
+    if (wolfSSL_GetBulkCipher(ssl) != wolfssl_aes) {
+        printf("myMacEncryptCb not using AES\n");
+        return -1;
+    }
+
+    if (strstr(wolfSSL_get_version(ssl), tlsStr) == NULL) {
+        printf("myMacEncryptCb not using (D)TLS\n");
+        return -1;
+    }
+
+    /* Reconstruct record header. */
+    wolfSSL_SetTlsHmacInner(ssl, myInner, decSz, content, macVerify);
+
+    ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID);
+    if (ret != 0)
+        return ret;
+    ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl),
+               wolfSSL_GetMacSecret(ssl, macVerify), digestSz);
+    if (ret != 0)
+        return ret;
+    ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner));
+    if (ret != 0)
+        return ret;
+    ret = wc_HmacUpdate(&hmac, decIn, decSz);
+    if (ret != 0)
+        return ret;
+    ret = wc_HmacFinal(&hmac, verify);
+    if (ret != 0)
+        return ret;
+
+    if (XMEMCMP(verify, decOut + decSz, digestSz) != 0) {
+        printf("myDecryptVerify verify failed\n");
+        return -1;
+    }
+
+    /* decrypt */
+    if (decCtx->keySetup == 0) {
+        int   keyLen = wolfSSL_GetKeySize(ssl);
+        const byte* key;
+        const byte* iv;
+
+        /* decrypt is from other side (peer) */
+        if (wolfSSL_GetSide(ssl) == WOLFSSL_SERVER_END) {
+            key = wolfSSL_GetClientWriteKey(ssl);
+            iv  = wolfSSL_GetClientWriteIV(ssl);
+        }
+        else {
+            key = wolfSSL_GetServerWriteKey(ssl);
+            iv  = wolfSSL_GetServerWriteIV(ssl);
+        }
+
+        ret = wc_AesSetKey(&decCtx->aes, key, keyLen, iv, AES_DECRYPTION);
+        if (ret != 0) {
+            printf("AesSetKey failed in myDecryptVerifyCb\n");
+            return ret;
+        }
+        decCtx->keySetup = 1;
+    }
+
+    /* decrypt */
+    ret = wc_AesCbcDecrypt(&decCtx->aes, decOut, decIn, decSz);
+    if (ret != 0)
+        return ret;
+
+    *padSz  = *(decOut + decSz - 1) + 1;
+
+    return 0;
+}
+
+#endif
+
+
+static WC_INLINE void SetupAtomicUser(WOLFSSL_CTX* ctx, WOLFSSL* ssl)
+{
+    AtomicEncCtx* encCtx;
+    AtomicDecCtx* decCtx;
+
+    encCtx = (AtomicEncCtx*)malloc(sizeof(AtomicEncCtx));
+    if (encCtx == NULL)
+        err_sys("AtomicEncCtx malloc failed");
+    XMEMSET(encCtx, 0, sizeof(AtomicEncCtx));
+
+    decCtx = (AtomicDecCtx*)malloc(sizeof(AtomicDecCtx));
+    if (decCtx == NULL) {
+        free(encCtx);
+        err_sys("AtomicDecCtx malloc failed");
+    }
+    XMEMSET(decCtx, 0, sizeof(AtomicDecCtx));
+
+    wolfSSL_CTX_SetMacEncryptCb(ctx, myMacEncryptCb);
+    wolfSSL_SetMacEncryptCtx(ssl, encCtx);
+
+    wolfSSL_CTX_SetDecryptVerifyCb(ctx, myDecryptVerifyCb);
+    wolfSSL_SetDecryptVerifyCtx(ssl, decCtx);
+
+#if defined(HAVE_ENCRYPT_THEN_MAC)
+    wolfSSL_CTX_SetEncryptMacCb(ctx, myEncryptMacCb);
+    wolfSSL_SetEncryptMacCtx(ssl, encCtx);
+
+    wolfSSL_CTX_SetVerifyDecryptCb(ctx, myVerifyDecryptCb);
+    wolfSSL_SetVerifyDecryptCtx(ssl, decCtx);
+#endif
+}
+
+
+static WC_INLINE void FreeAtomicUser(WOLFSSL* ssl)
+{
+    AtomicEncCtx* encCtx = (AtomicEncCtx*)wolfSSL_GetMacEncryptCtx(ssl);
+    AtomicDecCtx* decCtx = (AtomicDecCtx*)wolfSSL_GetDecryptVerifyCtx(ssl);
+
+    /* Encrypt-Then-MAC callbacks use same contexts. */
+
+    free(decCtx);
+    free(encCtx);
+}
+
+#endif /* ATOMIC_USER */
+
+#ifdef WOLFSSL_STATIC_MEMORY
+static WC_INLINE int wolfSSL_PrintStats(WOLFSSL_MEM_STATS* stats)
+{
+    word16 i;
+
+    if (stats == NULL) {
+        return 0;
+    }
+
+    /* print to stderr so is on the same pipe as WOLFSSL_DEBUG */
+    fprintf(stderr, "Total mallocs   = %d\n", stats->totalAlloc);
+    fprintf(stderr, "Total frees     = %d\n", stats->totalFr);
+    fprintf(stderr, "Current mallocs = %d\n", stats->curAlloc);
+    fprintf(stderr, "Available IO    = %d\n", stats->avaIO);
+    fprintf(stderr, "Max con. handshakes  = %d\n", stats->maxHa);
+    fprintf(stderr, "Max con. IO          = %d\n", stats->maxIO);
+    fprintf(stderr, "State of memory blocks: size   : available \n");
+    for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
+       fprintf(stderr, "                      : %d\t : %d\n", stats->blockSz[i],
+                                                            stats->avaBlock[i]);
+    }
+
+    return 1;
+}
+#endif /* WOLFSSL_STATIC_MEMORY */
+
+#ifdef HAVE_PK_CALLBACKS
+
+typedef struct PkCbInfo {
+    const char* ourKey;
+#ifdef TEST_PK_PRIVKEY
+    union {
+    #ifdef HAVE_ECC
+        ecc_key ecc;
+    #endif
+    #ifdef HAVE_CURVE25519
+        curve25519_key curve;
+    #endif
+    #ifdef HAVE_CURVE448
+        curve448_key curve;
+    #endif
+    } keyGen;
+#endif
+} PkCbInfo;
+
+#if defined(DEBUG_PK_CB) || defined(TEST_PK_PRIVKEY)
+    #define WOLFSSL_PKMSG(_f_, ...) printf(_f_, ##__VA_ARGS__)
+#else
+    #define WOLFSSL_PKMSG(_f_, ...)
+#endif
+
+#ifdef HAVE_ECC
+
+static WC_INLINE int myEccKeyGen(WOLFSSL* ssl, ecc_key* key, word32 keySz,
+    int ecc_curve, void* ctx)
+{
+    int       ret;
+    WC_RNG    rng;
+    PkCbInfo* cbInfo = (PkCbInfo*)ctx;
+    ecc_key*  new_key;
+#ifdef TEST_PK_PRIVKEY
+    byte qx[MAX_ECC_BYTES], qy[MAX_ECC_BYTES];
+    word32 qxLen = sizeof(qx), qyLen = sizeof(qy);
+
+    new_key = &cbInfo->keyGen.ecc;
+#else
+    new_key = key;
+#endif
+
+    (void)ssl;
+    (void)cbInfo;
+
+    WOLFSSL_PKMSG("PK ECC KeyGen: keySz %d, Curve ID %d\n", keySz, ecc_curve);
+
+    ret = wc_InitRng(&rng);
+    if (ret != 0)
+        return ret;
+
+    ret = wc_ecc_init(new_key);
+    if (ret == 0) {
+        /* create new key */
+        ret = wc_ecc_make_key_ex(&rng, keySz, new_key, ecc_curve);
+
+    #ifdef TEST_PK_PRIVKEY
+        if (ret == 0) {
+            /* extract public portion from new key into `key` arg */
+            ret = wc_ecc_export_public_raw(new_key, qx, &qxLen, qy, &qyLen);
+            if (ret == 0) {
+                /* load public portion only into key */
+                ret = wc_ecc_import_unsigned(key, qx, qy, NULL, ecc_curve);
+            }
+            (void)qxLen;
+            (void)qyLen;
+        }
+    #endif
+    }
+
+    WOLFSSL_PKMSG("PK ECC KeyGen: ret %d\n", ret);
+
+    wc_FreeRng(&rng);
+
+    return ret;
+}
+
+static WC_INLINE int myEccSign(WOLFSSL* ssl, const byte* in, word32 inSz,
+        byte* out, word32* outSz, const byte* key, word32 keySz, void* ctx)
+{
+    int       ret;
+    WC_RNG    rng;
+    word32    idx = 0;
+    ecc_key   myKey;
+    byte*     keyBuf = (byte*)key;
+    PkCbInfo* cbInfo = (PkCbInfo*)ctx;
+
+    (void)ssl;
+    (void)cbInfo;
+
+    WOLFSSL_PKMSG("PK ECC Sign: inSz %d, keySz %d\n", inSz, keySz);
+
+#ifdef TEST_PK_PRIVKEY
+    ret = load_key_file(cbInfo->ourKey, &keyBuf, &keySz);
+    if (ret != 0)
+        return ret;
+#endif
+
+    ret = wc_InitRng(&rng);
+    if (ret != 0)
+        return ret;
+
+    ret = wc_ecc_init(&myKey);
+    if (ret == 0) {
+        ret = wc_EccPrivateKeyDecode(keyBuf, &idx, &myKey, keySz);
+        if (ret == 0) {
+            WOLFSSL_PKMSG("PK ECC Sign: Curve ID %d\n", myKey.dp->id);
+            ret = wc_ecc_sign_hash(in, inSz, out, outSz, &rng, &myKey);
+        }
+        wc_ecc_free(&myKey);
+    }
+    wc_FreeRng(&rng);
+
+#ifdef TEST_PK_PRIVKEY
+    free(keyBuf);
+#endif
+
+    WOLFSSL_PKMSG("PK ECC Sign: ret %d outSz %d\n", ret, *outSz);
+
+    return ret;
+}
+
+
+static WC_INLINE int myEccVerify(WOLFSSL* ssl, const byte* sig, word32 sigSz,
+        const byte* hash, word32 hashSz, const byte* key, word32 keySz,
+        int* result, void* ctx)
+{
+    int       ret;
+    word32    idx = 0;
+    ecc_key   myKey;
+    PkCbInfo* cbInfo = (PkCbInfo*)ctx;
+
+    (void)ssl;
+    (void)cbInfo;
+
+    WOLFSSL_PKMSG("PK ECC Verify: sigSz %d, hashSz %d, keySz %d\n", sigSz, hashSz, keySz);
+
+    ret = wc_ecc_init(&myKey);
+    if (ret == 0) {
+        ret = wc_EccPublicKeyDecode(key, &idx, &myKey, keySz);
+        if (ret == 0)
+            ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, result, &myKey);
+        wc_ecc_free(&myKey);
+    }
+
+    WOLFSSL_PKMSG("PK ECC Verify: ret %d, result %d\n", ret, *result);
+
+    return ret;
+}
+
+static WC_INLINE int myEccSharedSecret(WOLFSSL* ssl, ecc_key* otherKey,
+        unsigned char* pubKeyDer, unsigned int* pubKeySz,
+        unsigned char* out, unsigned int* outlen,
+        int side, void* ctx)
+{
+    int       ret;
+    ecc_key*  privKey = NULL;
+    ecc_key*  pubKey = NULL;
+    ecc_key   tmpKey;
+    PkCbInfo* cbInfo = (PkCbInfo*)ctx;
+
+    (void)ssl;
+    (void)cbInfo;
+
+    WOLFSSL_PKMSG("PK ECC PMS: Side %s, Peer Curve %d\n",
+        side == WOLFSSL_CLIENT_END ? "client" : "server", otherKey->dp->id);
+
+    ret = wc_ecc_init(&tmpKey);
+    if (ret != 0) {
+        return ret;
+    }
+
+    /* for client: create and export public key */
+    if (side == WOLFSSL_CLIENT_END) {
+        WC_RNG rng;
+
+        privKey = &tmpKey;
+        pubKey = otherKey;
+
+        ret = wc_InitRng(&rng);
+        if (ret == 0) {
+            ret = wc_ecc_make_key_ex(&rng, 0, privKey, otherKey->dp->id);
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (ret == WC_PENDING_E) {
+                ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_NONE);
+            }
+        #endif
+            if (ret == 0)
+                ret = wc_ecc_export_x963(privKey, pubKeyDer, pubKeySz);
+            wc_FreeRng(&rng);
+        }
+    }
+
+    /* for server: import public key */
+    else if (side == WOLFSSL_SERVER_END) {
+    #ifdef TEST_PK_PRIVKEY
+        privKey = &cbInfo->keyGen.ecc;
+    #else
+        privKey = otherKey;
+    #endif
+        pubKey = &tmpKey;
+
+        ret = wc_ecc_import_x963_ex(pubKeyDer, *pubKeySz, pubKey,
+            otherKey->dp->id);
+    }
+    else {
+        ret = BAD_FUNC_ARG;
+    }
+
+    /* generate shared secret and return it */
+    if (ret == 0) {
+        ret = wc_ecc_shared_secret(privKey, pubKey, out, outlen);
+
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        if (ret == WC_PENDING_E) {
+            ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+        }
+    #endif
+    }
+
+#ifdef TEST_PK_PRIVKEY
+    if (side == WOLFSSL_SERVER_END) {
+        wc_ecc_free(&cbInfo->keyGen.ecc);
+    }
+#endif
+
+    wc_ecc_free(&tmpKey);
+
+    WOLFSSL_PKMSG("PK ECC PMS: ret %d, PubKeySz %d, OutLen %d\n", ret, *pubKeySz, *outlen);
+
+    return ret;
+}
+
+#ifdef HAVE_ED25519
+static WC_INLINE int myEd25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz,
+        byte* out, word32* outSz, const byte* key, word32 keySz, void* ctx)
+{
+    int         ret;
+    word32      idx = 0;
+    ed25519_key myKey;
+    byte*       keyBuf = (byte*)key;
+    PkCbInfo*   cbInfo = (PkCbInfo*)ctx;
+
+    (void)ssl;
+    (void)cbInfo;
+
+    WOLFSSL_PKMSG("PK 25519 Sign: inSz %d, keySz %d\n", inSz, keySz);
+
+#ifdef TEST_PK_PRIVKEY
+    ret = load_key_file(cbInfo->ourKey, &keyBuf, &keySz);
+    if (ret != 0)
+        return ret;
+#endif
+
+    ret = wc_ed25519_init(&myKey);
+    if (ret == 0) {
+        ret = wc_Ed25519PrivateKeyDecode(keyBuf, &idx, &myKey, keySz);
+        if (ret == 0)
+            ret = wc_ed25519_sign_msg(in, inSz, out, outSz, &myKey);
+        wc_ed25519_free(&myKey);
+    }
+
+#ifdef TEST_PK_PRIVKEY
+    free(keyBuf);
+#endif
+
+    WOLFSSL_PKMSG("PK 25519 Sign: ret %d, outSz %d\n", ret, *outSz);
+
+    return ret;
+}
+
+
+static WC_INLINE int myEd25519Verify(WOLFSSL* ssl, const byte* sig, word32 sigSz,
+        const byte* msg, word32 msgSz, const byte* key, word32 keySz,
+        int* result, void* ctx)
+{
+    int         ret;
+    ed25519_key myKey;
+    PkCbInfo* cbInfo = (PkCbInfo*)ctx;
+
+    (void)ssl;
+    (void)cbInfo;
+
+    WOLFSSL_PKMSG("PK 25519 Verify: sigSz %d, msgSz %d, keySz %d\n", sigSz, msgSz, keySz);
+
+    ret = wc_ed25519_init(&myKey);
+    if (ret == 0) {
+        ret = wc_ed25519_import_public(key, keySz, &myKey);
+        if (ret == 0) {
+            ret = wc_ed25519_verify_msg(sig, sigSz, msg, msgSz, result, &myKey);
+        }
+        wc_ed25519_free(&myKey);
+    }
+
+    WOLFSSL_PKMSG("PK 25519 Verify: ret %d, result %d\n", ret, *result);
+
+    return ret;
+}
+#endif /* HAVE_ED25519 */
+
+#ifdef HAVE_CURVE25519
+static WC_INLINE int myX25519KeyGen(WOLFSSL* ssl, curve25519_key* key,
+    unsigned int keySz, void* ctx)
+{
+    int       ret;
+    WC_RNG    rng;
+    PkCbInfo* cbInfo = (PkCbInfo*)ctx;
+
+    (void)ssl;
+    (void)cbInfo;
+
+    WOLFSSL_PKMSG("PK 25519 KeyGen: keySz %d\n", keySz);
+
+    ret = wc_InitRng(&rng);
+    if (ret != 0)
+        return ret;
+
+    ret = wc_curve25519_make_key(&rng, keySz, key);
+
+    wc_FreeRng(&rng);
+
+    WOLFSSL_PKMSG("PK 25519 KeyGen: ret %d\n", ret);
+
+    return ret;
+}
+
+static WC_INLINE int myX25519SharedSecret(WOLFSSL* ssl, curve25519_key* otherKey,
+        unsigned char* pubKeyDer, unsigned int* pubKeySz,
+        unsigned char* out, unsigned int* outlen,
+        int side, void* ctx)
+{
+    int      ret;
+    curve25519_key* privKey = NULL;
+    curve25519_key* pubKey = NULL;
+    curve25519_key  tmpKey;
+    PkCbInfo* cbInfo = (PkCbInfo*)ctx;
+
+    (void)ssl;
+    (void)cbInfo;
+
+    WOLFSSL_PKMSG("PK 25519 PMS: side %s\n",
+        side == WOLFSSL_CLIENT_END ? "client" : "server");
+
+    ret = wc_curve25519_init(&tmpKey);
+    if (ret != 0) {
+        return ret;
+    }
+
+    /* for client: create and export public key */
+    if (side == WOLFSSL_CLIENT_END) {
+        WC_RNG rng;
+
+        privKey = &tmpKey;
+        pubKey = otherKey;
+
+        ret = wc_InitRng(&rng);
+        if (ret == 0) {
+            ret = wc_curve25519_make_key(&rng, CURVE25519_KEYSIZE, privKey);
+            if (ret == 0) {
+                ret = wc_curve25519_export_public_ex(privKey, pubKeyDer,
+                    pubKeySz, EC25519_LITTLE_ENDIAN);
+            }
+            wc_FreeRng(&rng);
+        }
+    }
+
+    /* for server: import public key */
+    else if (side == WOLFSSL_SERVER_END) {
+        privKey = otherKey;
+        pubKey = &tmpKey;
+
+        ret = wc_curve25519_import_public_ex(pubKeyDer, *pubKeySz, pubKey,
+            EC25519_LITTLE_ENDIAN);
+    }
+    else {
+        ret = BAD_FUNC_ARG;
+    }
+
+    /* generate shared secret and return it */
+    if (ret == 0) {
+        ret = wc_curve25519_shared_secret_ex(privKey, pubKey, out, outlen,
+            EC25519_LITTLE_ENDIAN);
+    }
+
+    wc_curve25519_free(&tmpKey);
+
+    WOLFSSL_PKMSG("PK 25519 PMS: ret %d, pubKeySz %d, outLen %d\n",
+        ret, *pubKeySz, *outlen);
+
+    return ret;
+}
+#endif /* HAVE_CURVE25519 */
+
+#ifdef HAVE_ED448
+static WC_INLINE int myEd448Sign(WOLFSSL* ssl, const byte* in, word32 inSz,
+        byte* out, word32* outSz, const byte* key, word32 keySz, void* ctx)
+{
+    int         ret;
+    word32      idx = 0;
+    ed448_key   myKey;
+    byte*       keyBuf = (byte*)key;
+    PkCbInfo*   cbInfo = (PkCbInfo*)ctx;
+
+    (void)ssl;
+    (void)cbInfo;
+
+    WOLFSSL_PKMSG("PK 448 Sign: inSz %d, keySz %d\n", inSz, keySz);
+
+#ifdef TEST_PK_PRIVKEY
+    ret = load_key_file(cbInfo->ourKey, &keyBuf, &keySz);
+    if (ret != 0)
+        return ret;
+#endif
+
+    ret = wc_ed448_init(&myKey);
+    if (ret == 0) {
+        ret = wc_Ed448PrivateKeyDecode(keyBuf, &idx, &myKey, keySz);
+        if (ret == 0)
+            ret = wc_ed448_sign_msg(in, inSz, out, outSz, &myKey);
+        wc_ed448_free(&myKey);
+    }
+
+#ifdef TEST_PK_PRIVKEY
+    free(keyBuf);
+#endif
+
+    WOLFSSL_PKMSG("PK 448 Sign: ret %d, outSz %d\n", ret, *outSz);
+
+    return ret;
+}
+
+
+static WC_INLINE int myEd448Verify(WOLFSSL* ssl, const byte* sig, word32 sigSz,
+        const byte* msg, word32 msgSz, const byte* key, word32 keySz,
+        int* result, void* ctx)
+{
+    int         ret;
+    ed448_key   myKey;
+    PkCbInfo*   cbInfo = (PkCbInfo*)ctx;
+
+    (void)ssl;
+    (void)cbInfo;
+
+    WOLFSSL_PKMSG("PK 448 Verify: sigSz %d, msgSz %d, keySz %d\n", sigSz, msgSz,
+                  keySz);
+
+    ret = wc_ed448_init(&myKey);
+    if (ret == 0) {
+        ret = wc_ed448_import_public(key, keySz, &myKey);
+        if (ret == 0) {
+            ret = wc_ed448_verify_msg(sig, sigSz, msg, msgSz, result, &myKey);
+        }
+        wc_ed448_free(&myKey);
+    }
+
+    WOLFSSL_PKMSG("PK 448 Verify: ret %d, result %d\n", ret, *result);
+
+    return ret;
+}
+#endif /* HAVE_ED448 */
+
+#ifdef HAVE_CURVE448
+static WC_INLINE int myX448KeyGen(WOLFSSL* ssl, curve448_key* key,
+    unsigned int keySz, void* ctx)
+{
+    int       ret;
+    WC_RNG    rng;
+    PkCbInfo* cbInfo = (PkCbInfo*)ctx;
+
+    (void)ssl;
+    (void)cbInfo;
+
+    WOLFSSL_PKMSG("PK 448 KeyGen: keySz %d\n", keySz);
+
+    ret = wc_InitRng(&rng);
+    if (ret != 0)
+        return ret;
+
+    ret = wc_curve448_make_key(&rng, keySz, key);
+
+    wc_FreeRng(&rng);
+
+    WOLFSSL_PKMSG("PK 448 KeyGen: ret %d\n", ret);
+
+    return ret;
+}
+
+static WC_INLINE int myX448SharedSecret(WOLFSSL* ssl, curve448_key* otherKey,
+        unsigned char* pubKeyDer, unsigned int* pubKeySz,
+        unsigned char* out, unsigned int* outlen,
+        int side, void* ctx)
+{
+    int           ret;
+    curve448_key* privKey = NULL;
+    curve448_key* pubKey = NULL;
+    curve448_key  tmpKey;
+    PkCbInfo*     cbInfo = (PkCbInfo*)ctx;
+
+    (void)ssl;
+    (void)cbInfo;
+
+    WOLFSSL_PKMSG("PK 448 PMS: side %s\n",
+        side == WOLFSSL_CLIENT_END ? "client" : "server");
+
+    ret = wc_curve448_init(&tmpKey);
+    if (ret != 0) {
+        return ret;
+    }
+
+    /* for client: create and export public key */
+    if (side == WOLFSSL_CLIENT_END) {
+        WC_RNG rng;
+
+        privKey = &tmpKey;
+        pubKey = otherKey;
+
+        ret = wc_InitRng(&rng);
+        if (ret == 0) {
+            ret = wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, privKey);
+            if (ret == 0) {
+                ret = wc_curve448_export_public_ex(privKey, pubKeyDer,
+                    pubKeySz, EC448_LITTLE_ENDIAN);
+            }
+            wc_FreeRng(&rng);
+        }
+    }
+
+    /* for server: import public key */
+    else if (side == WOLFSSL_SERVER_END) {
+        privKey = otherKey;
+        pubKey = &tmpKey;
+
+        ret = wc_curve448_import_public_ex(pubKeyDer, *pubKeySz, pubKey,
+            EC448_LITTLE_ENDIAN);
+    }
+    else {
+        ret = BAD_FUNC_ARG;
+    }
+
+    /* generate shared secret and return it */
+    if (ret == 0) {
+        ret = wc_curve448_shared_secret_ex(privKey, pubKey, out, outlen,
+            EC448_LITTLE_ENDIAN);
+    }
+
+    wc_curve448_free(&tmpKey);
+
+    WOLFSSL_PKMSG("PK 448 PMS: ret %d, pubKeySz %d, outLen %d\n",
+        ret, *pubKeySz, *outlen);
+
+    return ret;
+}
+#endif /* HAVE_CURVE448 */
+
+#endif /* HAVE_ECC */
+
+#ifndef NO_DH
+static WC_INLINE int myDhCallback(WOLFSSL* ssl, struct DhKey* key,
+        const unsigned char* priv, unsigned int privSz,
+        const unsigned char* pubKeyDer, unsigned int pubKeySz,
+        unsigned char* out, unsigned int* outlen,
+        void* ctx)
+{
+    int ret;
+    PkCbInfo* cbInfo = (PkCbInfo*)ctx;
+
+    (void)ssl;
+    (void)cbInfo;
+
+    /* return 0 on success */
+    ret = wc_DhAgree(key, out, outlen, priv, privSz, pubKeyDer, pubKeySz);
+
+    WOLFSSL_PKMSG("PK ED Agree: ret %d, privSz %d, pubKeySz %d, outlen %d\n",
+        ret, privSz, pubKeySz, *outlen);
+
+    return ret;
+};
+
+#endif /* !NO_DH */
+
+#ifndef NO_RSA
+
+static WC_INLINE int myRsaSign(WOLFSSL* ssl, const byte* in, word32 inSz,
+        byte* out, word32* outSz, const byte* key, word32 keySz, void* ctx)
+{
+    WC_RNG  rng;
+    int     ret;
+    word32  idx = 0;
+    RsaKey  myKey;
+    byte*   keyBuf = (byte*)key;
+    PkCbInfo* cbInfo = (PkCbInfo*)ctx;
+
+    (void)ssl;
+    (void)cbInfo;
+
+    WOLFSSL_PKMSG("PK RSA Sign: inSz %d, keySz %d\n", inSz, keySz);
+
+#ifdef TEST_PK_PRIVKEY
+    ret = load_key_file(cbInfo->ourKey, &keyBuf, &keySz);
+    if (ret != 0)
+        return ret;
+#endif
+
+    ret = wc_InitRng(&rng);
+    if (ret != 0)
+        return ret;
+
+    ret = wc_InitRsaKey(&myKey, NULL);
+    if (ret == 0) {
+        ret = wc_RsaPrivateKeyDecode(keyBuf, &idx, &myKey, keySz);
+        if (ret == 0)
+            ret = wc_RsaSSL_Sign(in, inSz, out, *outSz, &myKey, &rng);
+        if (ret > 0) {  /* save and convert to 0 success */
+            *outSz = ret;
+            ret = 0;
+        }
+        wc_FreeRsaKey(&myKey);
+    }
+    wc_FreeRng(&rng);
+
+#ifdef TEST_PK_PRIVKEY
+    free(keyBuf);
+#endif
+
+    WOLFSSL_PKMSG("PK RSA Sign: ret %d, outSz %d\n", ret, *outSz);
+
+    return ret;
+}
+
+
+static WC_INLINE int myRsaVerify(WOLFSSL* ssl, byte* sig, word32 sigSz,
+        byte** out, const byte* key, word32 keySz, void* ctx)
+{
+    int     ret;
+    word32  idx = 0;
+    RsaKey  myKey;
+    PkCbInfo* cbInfo = (PkCbInfo*)ctx;
+
+    (void)ssl;
+    (void)cbInfo;
+
+    WOLFSSL_PKMSG("PK RSA Verify: sigSz %d, keySz %d\n", sigSz, keySz);
+
+    ret = wc_InitRsaKey(&myKey, NULL);
+    if (ret == 0) {
+        ret = wc_RsaPublicKeyDecode(key, &idx, &myKey, keySz);
+        if (ret == 0)
+            ret = wc_RsaSSL_VerifyInline(sig, sigSz, out, &myKey);
+        wc_FreeRsaKey(&myKey);
+    }
+
+    WOLFSSL_PKMSG("PK RSA Verify: ret %d\n", ret);
+
+    return ret;
+}
+
+static WC_INLINE int myRsaSignCheck(WOLFSSL* ssl, byte* sig, word32 sigSz,
+        byte** out, const byte* key, word32 keySz, void* ctx)
+{
+    int     ret;
+    word32  idx = 0;
+    RsaKey  myKey;
+    byte*   keyBuf = (byte*)key;
+    PkCbInfo* cbInfo = (PkCbInfo*)ctx;
+
+    (void)ssl;
+    (void)cbInfo;
+
+    WOLFSSL_PKMSG("PK RSA SignCheck: sigSz %d, keySz %d\n", sigSz, keySz);
+
+#ifdef TEST_PK_PRIVKEY
+    ret = load_key_file(cbInfo->ourKey, &keyBuf, &keySz);
+    if (ret != 0)
+        return ret;
+#endif
+
+    ret = wc_InitRsaKey(&myKey, NULL);
+    if (ret == 0) {
+        ret = wc_RsaPrivateKeyDecode(keyBuf, &idx, &myKey, keySz);
+        if (ret == 0)
+            ret = wc_RsaSSL_VerifyInline(sig, sigSz, out, &myKey);
+        wc_FreeRsaKey(&myKey);
+    }
+#ifdef TEST_PK_PRIVKEY
+    free(keyBuf);
+#endif
+
+    WOLFSSL_PKMSG("PK RSA SignCheck: ret %d\n", ret);
+
+    return ret;
+}
+
+#ifdef WC_RSA_PSS
+static WC_INLINE int myRsaPssSign(WOLFSSL* ssl, const byte* in, word32 inSz,
+        byte* out, word32* outSz, int hash, int mgf, const byte* key,
+        word32 keySz, void* ctx)
+{
+    enum wc_HashType hashType = WC_HASH_TYPE_NONE;
+    WC_RNG           rng;
+    int              ret;
+    word32           idx = 0;
+    RsaKey           myKey;
+    byte*            keyBuf = (byte*)key;
+    PkCbInfo* cbInfo = (PkCbInfo*)ctx;
+
+    (void)ssl;
+    (void)cbInfo;
+
+    WOLFSSL_PKMSG("PK RSA PSS Sign: inSz %d, hash %d, mgf %d, keySz %d\n",
+        inSz, hash, mgf, keySz);
+
+#ifdef TEST_PK_PRIVKEY
+    ret = load_key_file(cbInfo->ourKey, &keyBuf, &keySz);
+    if (ret != 0)
+        return ret;
+#endif
+
+    switch (hash) {
+#ifndef NO_SHA256
+        case SHA256h:
+            hashType = WC_HASH_TYPE_SHA256;
+            break;
+#endif
+#ifdef WOLFSSL_SHA384
+        case SHA384h:
+            hashType = WC_HASH_TYPE_SHA384;
+            break;
+#endif
+#ifdef WOLFSSL_SHA512
+        case SHA512h:
+            hashType = WC_HASH_TYPE_SHA512;
+            break;
+#endif
+    }
+
+    ret = wc_InitRng(&rng);
+    if (ret != 0)
+        return ret;
+
+    ret = wc_InitRsaKey(&myKey, NULL);
+    if (ret == 0) {
+        ret = wc_RsaPrivateKeyDecode(keyBuf, &idx, &myKey, keySz);
+        if (ret == 0) {
+            ret = wc_RsaPSS_Sign(in, inSz, out, *outSz, hashType, mgf, &myKey,
+                                 &rng);
+        }
+        if (ret > 0) {  /* save and convert to 0 success */
+            *outSz = ret;
+            ret = 0;
+        }
+        wc_FreeRsaKey(&myKey);
+    }
+    wc_FreeRng(&rng);
+
+#ifdef TEST_PK_PRIVKEY
+    free(keyBuf);
+#endif
+
+    WOLFSSL_PKMSG("PK RSA PSS Sign: ret %d, outSz %d\n", ret, *outSz);
+
+    return ret;
+}
+
+
+static WC_INLINE int myRsaPssVerify(WOLFSSL* ssl, byte* sig, word32 sigSz,
+        byte** out, int hash, int mgf, const byte* key, word32 keySz, void* ctx)
+{
+    int       ret;
+    word32    idx = 0;
+    RsaKey    myKey;
+    PkCbInfo* cbInfo = (PkCbInfo*)ctx;
+    enum wc_HashType hashType = WC_HASH_TYPE_NONE;
+
+    (void)ssl;
+    (void)cbInfo;
+
+    WOLFSSL_PKMSG("PK RSA PSS Verify: sigSz %d, hash %d, mgf %d, keySz %d\n",
+        sigSz, hash, mgf, keySz);
+
+    switch (hash) {
+#ifndef NO_SHA256
+        case SHA256h:
+            hashType = WC_HASH_TYPE_SHA256;
+            break;
+#endif
+#ifdef WOLFSSL_SHA384
+        case SHA384h:
+            hashType = WC_HASH_TYPE_SHA384;
+            break;
+#endif
+#ifdef WOLFSSL_SHA512
+        case SHA512h:
+            hashType = WC_HASH_TYPE_SHA512;
+            break;
+#endif
+    }
+
+    ret = wc_InitRsaKey(&myKey, NULL);
+    if (ret == 0) {
+        ret = wc_RsaPublicKeyDecode(key, &idx, &myKey, keySz);
+        if (ret == 0) {
+            ret = wc_RsaPSS_VerifyInline(sig, sigSz, out, hashType, mgf,
+                                         &myKey);
+            }
+        wc_FreeRsaKey(&myKey);
+    }
+
+    WOLFSSL_PKMSG("PK RSA PSS Verify: ret %d\n", ret);
+
+    return ret;
+}
+
+static WC_INLINE int myRsaPssSignCheck(WOLFSSL* ssl, byte* sig, word32 sigSz,
+        byte** out, int hash, int mgf, const byte* key, word32 keySz, void* ctx)
+{
+    int       ret;
+    word32    idx = 0;
+    RsaKey    myKey;
+    byte*     keyBuf = (byte*)key;
+    PkCbInfo* cbInfo = (PkCbInfo*)ctx;
+    enum wc_HashType hashType = WC_HASH_TYPE_NONE;
+
+    (void)ssl;
+    (void)cbInfo;
+
+    WOLFSSL_PKMSG("PK RSA PSS SignCheck: sigSz %d, hash %d, mgf %d, keySz %d\n",
+        sigSz, hash, mgf, keySz);
+
+#ifdef TEST_PK_PRIVKEY
+    ret = load_key_file(cbInfo->ourKey, &keyBuf, &keySz);
+    if (ret != 0)
+        return ret;
+#endif
+
+    switch (hash) {
+#ifndef NO_SHA256
+        case SHA256h:
+            hashType = WC_HASH_TYPE_SHA256;
+            break;
+#endif
+#ifdef WOLFSSL_SHA384
+        case SHA384h:
+            hashType = WC_HASH_TYPE_SHA384;
+            break;
+#endif
+#ifdef WOLFSSL_SHA512
+        case SHA512h:
+            hashType = WC_HASH_TYPE_SHA512;
+            break;
+#endif
+    }
+
+    ret = wc_InitRsaKey(&myKey, NULL);
+    if (ret == 0) {
+        ret = wc_RsaPrivateKeyDecode(keyBuf, &idx, &myKey, keySz);
+        if (ret == 0) {
+            ret = wc_RsaPSS_VerifyInline(sig, sigSz, out, hashType, mgf,
+                                         &myKey);
+            }
+        wc_FreeRsaKey(&myKey);
+    }
+
+#ifdef TEST_PK_PRIVKEY
+    free(keyBuf);
+#endif
+
+    WOLFSSL_PKMSG("PK RSA PSS SignCheck: ret %d\n", ret);
+
+    return ret;
+}
+#endif
+
+
+static WC_INLINE int myRsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz,
+                           byte* out, word32* outSz, const byte* key,
+                           word32 keySz, void* ctx)
+{
+    int       ret;
+    word32    idx = 0;
+    RsaKey    myKey;
+    WC_RNG    rng;
+    PkCbInfo* cbInfo = (PkCbInfo*)ctx;
+
+    (void)ssl;
+    (void)cbInfo;
+
+    WOLFSSL_PKMSG("PK RSA Enc: inSz %d, keySz %d\n", inSz, keySz);
+
+    ret = wc_InitRng(&rng);
+    if (ret != 0)
+        return ret;
+
+    ret = wc_InitRsaKey(&myKey, NULL);
+    if (ret == 0) {
+        ret = wc_RsaPublicKeyDecode(key, &idx, &myKey, keySz);
+        if (ret == 0) {
+            ret = wc_RsaPublicEncrypt(in, inSz, out, *outSz, &myKey, &rng);
+            if (ret > 0) {
+                *outSz = ret;
+                ret = 0;  /* reset to success */
+            }
+        }
+        wc_FreeRsaKey(&myKey);
+    }
+    wc_FreeRng(&rng);
+
+    WOLFSSL_PKMSG("PK RSA Enc: ret %d, outSz %d\n", ret, *outSz);
+
+    return ret;
+}
+
+static WC_INLINE int myRsaDec(WOLFSSL* ssl, byte* in, word32 inSz,
+                           byte** out,
+                           const byte* key, word32 keySz, void* ctx)
+{
+    int       ret;
+    word32    idx = 0;
+    RsaKey    myKey;
+    byte*     keyBuf = (byte*)key;
+    PkCbInfo* cbInfo = (PkCbInfo*)ctx;
+
+    (void)ssl;
+    (void)cbInfo;
+
+    WOLFSSL_PKMSG("PK RSA Dec: inSz %d, keySz %d\n", inSz, keySz);
+
+#ifdef TEST_PK_PRIVKEY
+    ret = load_key_file(cbInfo->ourKey, &keyBuf, &keySz);
+    if (ret != 0)
+        return ret;
+#endif
+
+    ret = wc_InitRsaKey(&myKey, NULL);
+    if (ret == 0) {
+        ret = wc_RsaPrivateKeyDecode(keyBuf, &idx, &myKey, keySz);
+        if (ret == 0) {
+            #ifdef WC_RSA_BLINDING
+                ret = wc_RsaSetRNG(&myKey, wolfSSL_GetRNG(ssl));
+                if (ret != 0) {
+                    wc_FreeRsaKey(&myKey);
+                    return ret;
+                }
+            #endif
+            ret = wc_RsaPrivateDecryptInline(in, inSz, out, &myKey);
+        }
+        wc_FreeRsaKey(&myKey);
+    }
+
+#ifdef TEST_PK_PRIVKEY
+    free(keyBuf);
+#endif
+
+    WOLFSSL_PKMSG("PK RSA Dec: ret %d\n", ret);
+
+    return ret;
+}
+
+#endif /* NO_RSA */
+
+static WC_INLINE void SetupPkCallbacks(WOLFSSL_CTX* ctx)
+{
+    (void)ctx;
+
+    #ifdef HAVE_ECC
+        wolfSSL_CTX_SetEccKeyGenCb(ctx, myEccKeyGen);
+        wolfSSL_CTX_SetEccSignCb(ctx, myEccSign);
+        wolfSSL_CTX_SetEccVerifyCb(ctx, myEccVerify);
+        wolfSSL_CTX_SetEccSharedSecretCb(ctx, myEccSharedSecret);
+    #endif /* HAVE_ECC */
+    #ifndef NO_DH
+        wolfSSL_CTX_SetDhAgreeCb(ctx, myDhCallback);
+    #endif
+    #ifdef HAVE_ED25519
+        wolfSSL_CTX_SetEd25519SignCb(ctx, myEd25519Sign);
+        wolfSSL_CTX_SetEd25519VerifyCb(ctx, myEd25519Verify);
+    #endif
+    #ifdef HAVE_CURVE25519
+        wolfSSL_CTX_SetX25519KeyGenCb(ctx, myX25519KeyGen);
+        wolfSSL_CTX_SetX25519SharedSecretCb(ctx, myX25519SharedSecret);
+    #endif
+    #ifdef HAVE_ED448
+        wolfSSL_CTX_SetEd448SignCb(ctx, myEd448Sign);
+        wolfSSL_CTX_SetEd448VerifyCb(ctx, myEd448Verify);
+    #endif
+    #ifdef HAVE_CURVE448
+        wolfSSL_CTX_SetX448KeyGenCb(ctx, myX448KeyGen);
+        wolfSSL_CTX_SetX448SharedSecretCb(ctx, myX448SharedSecret);
+    #endif
+    #ifndef NO_RSA
+        wolfSSL_CTX_SetRsaSignCb(ctx, myRsaSign);
+        wolfSSL_CTX_SetRsaVerifyCb(ctx, myRsaVerify);
+        wolfSSL_CTX_SetRsaSignCheckCb(ctx, myRsaSignCheck);
+        #ifdef WC_RSA_PSS
+            wolfSSL_CTX_SetRsaPssSignCb(ctx, myRsaPssSign);
+            wolfSSL_CTX_SetRsaPssVerifyCb(ctx, myRsaPssVerify);
+            wolfSSL_CTX_SetRsaPssSignCheckCb(ctx, myRsaPssSignCheck);
+        #endif
+        wolfSSL_CTX_SetRsaEncCb(ctx, myRsaEnc);
+        wolfSSL_CTX_SetRsaDecCb(ctx, myRsaDec);
+    #endif /* NO_RSA */
+}
+
+static WC_INLINE void SetupPkCallbackContexts(WOLFSSL* ssl, void* myCtx)
+{
+    #ifdef HAVE_ECC
+        wolfSSL_SetEccKeyGenCtx(ssl, myCtx);
+        wolfSSL_SetEccSignCtx(ssl, myCtx);
+        wolfSSL_SetEccVerifyCtx(ssl, myCtx);
+        wolfSSL_SetEccSharedSecretCtx(ssl, myCtx);
+    #endif /* HAVE_ECC */
+    #ifndef NO_DH
+        wolfSSL_SetDhAgreeCtx(ssl, myCtx);
+    #endif
+    #ifdef HAVE_ED25519
+        wolfSSL_SetEd25519SignCtx(ssl, myCtx);
+        wolfSSL_SetEd25519VerifyCtx(ssl, myCtx);
+    #endif
+    #ifdef HAVE_CURVE25519
+        wolfSSL_SetX25519KeyGenCtx(ssl, myCtx);
+        wolfSSL_SetX25519SharedSecretCtx(ssl, myCtx);
+    #endif
+    #ifdef HAVE_ED448
+        wolfSSL_SetEd448SignCtx(ssl, myCtx);
+        wolfSSL_SetEd448VerifyCtx(ssl, myCtx);
+    #endif
+    #ifdef HAVE_CURVE448
+        wolfSSL_SetX448KeyGenCtx(ssl, myCtx);
+        wolfSSL_SetX448SharedSecretCtx(ssl, myCtx);
+    #endif
+    #ifndef NO_RSA
+        wolfSSL_SetRsaSignCtx(ssl, myCtx);
+        wolfSSL_SetRsaVerifyCtx(ssl, myCtx);
+        #ifdef WC_RSA_PSS
+            wolfSSL_SetRsaPssSignCtx(ssl, myCtx);
+            wolfSSL_SetRsaPssVerifyCtx(ssl, myCtx);
+        #endif
+        wolfSSL_SetRsaEncCtx(ssl, myCtx);
+        wolfSSL_SetRsaDecCtx(ssl, myCtx);
+    #endif /* NO_RSA */
+}
+
+#endif /* HAVE_PK_CALLBACKS */
+
+
+
+
+#if defined(__hpux__) || defined(__MINGW32__) || defined (WOLFSSL_TIRTOS) \
+                      || defined(_MSC_VER)
+
+/* HP/UX doesn't have strsep, needed by test/suites.c */
+static WC_INLINE char* strsep(char **stringp, const char *delim)
+{
+    char* start;
+    char* end;
+
+    start = *stringp;
+    if (start == NULL)
+        return NULL;
+
+    if ((end = strpbrk(start, delim))) {
+        *end++ = '\0';
+        *stringp = end;
+    } else {
+        *stringp = NULL;
+    }
+
+    return start;
+}
+
+#endif /* __hpux__ and others */
+
+/* Create unique filename, len is length of tempfn name, assuming
+   len does not include null terminating character,
+   num is number of characters in tempfn name to randomize */
+static WC_INLINE const char* mymktemp(char *tempfn, int len, int num)
+{
+    int x, size;
+    static const char alphanum[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                                   "abcdefghijklmnopqrstuvwxyz";
+    WC_RNG rng;
+    byte   out;
+
+    if (tempfn == NULL || len < 1 || num < 1 || len <= num) {
+        printf("Bad input\n");
+        return NULL;
+    }
+
+    size = len - 1;
+
+    if (wc_InitRng(&rng) != 0) {
+        printf("InitRng failed\n");
+        return NULL;
+    }
+
+    for (x = size; x > size - num; x--) {
+        if (wc_RNG_GenerateBlock(&rng,(byte*)&out, sizeof(out)) != 0) {
+            printf("RNG_GenerateBlock failed\n");
+            return NULL;
+        }
+        tempfn[x] = alphanum[out % (sizeof(alphanum) - 1)];
+    }
+    tempfn[len] = '\0';
+
+    wc_FreeRng(&rng);
+    (void)rng; /* for WC_NO_RNG case */
+
+    return tempfn;
+}
+
+
+
+#if defined(HAVE_SESSION_TICKET) && defined(HAVE_CHACHA) && \
+                                    defined(HAVE_POLY1305)
+
+    #include <wolfssl/wolfcrypt/chacha20_poly1305.h>
+
+    typedef struct key_ctx {
+        byte name[WOLFSSL_TICKET_NAME_SZ];        /* name for this context */
+        byte key[CHACHA20_POLY1305_AEAD_KEYSIZE]; /* cipher key */
+    } key_ctx;
+
+    static THREAD_LS_T key_ctx myKey_ctx;
+    static THREAD_LS_T WC_RNG myKey_rng;
+
+    static WC_INLINE int TicketInit(void)
+    {
+        int ret = wc_InitRng(&myKey_rng);
+        if (ret != 0) return ret;
+
+        ret = wc_RNG_GenerateBlock(&myKey_rng, myKey_ctx.key, sizeof(myKey_ctx.key));
+        if (ret != 0) return ret;
+
+        ret = wc_RNG_GenerateBlock(&myKey_rng, myKey_ctx.name,sizeof(myKey_ctx.name));
+        if (ret != 0) return ret;
+
+        return 0;
+    }
+
+    static WC_INLINE void TicketCleanup(void)
+    {
+        wc_FreeRng(&myKey_rng);
+    }
+
+    static WC_INLINE int myTicketEncCb(WOLFSSL* ssl,
+                             byte key_name[WOLFSSL_TICKET_NAME_SZ],
+                             byte iv[WOLFSSL_TICKET_IV_SZ],
+                             byte mac[WOLFSSL_TICKET_MAC_SZ],
+                             int enc, byte* ticket, int inLen, int* outLen,
+                             void* userCtx)
+    {
+        (void)ssl;
+        (void)userCtx;
+
+        int ret;
+        word16 sLen = XHTONS(inLen);
+        byte aad[WOLFSSL_TICKET_NAME_SZ + WOLFSSL_TICKET_IV_SZ + 2];
+        int  aadSz = WOLFSSL_TICKET_NAME_SZ + WOLFSSL_TICKET_IV_SZ + 2;
+        byte* tmp = aad;
+
+        if (enc) {
+            XMEMCPY(key_name, myKey_ctx.name, WOLFSSL_TICKET_NAME_SZ);
+
+            ret = wc_RNG_GenerateBlock(&myKey_rng, iv, WOLFSSL_TICKET_IV_SZ);
+            if (ret != 0) return WOLFSSL_TICKET_RET_REJECT;
+
+            /* build aad from key name, iv, and length */
+            XMEMCPY(tmp, key_name, WOLFSSL_TICKET_NAME_SZ);
+            tmp += WOLFSSL_TICKET_NAME_SZ;
+            XMEMCPY(tmp, iv, WOLFSSL_TICKET_IV_SZ);
+            tmp += WOLFSSL_TICKET_IV_SZ;
+            XMEMCPY(tmp, &sLen, 2);
+
+            ret = wc_ChaCha20Poly1305_Encrypt(myKey_ctx.key, iv,
+                                              aad, aadSz,
+                                              ticket, inLen,
+                                              ticket,
+                                              mac);
+            if (ret != 0) return WOLFSSL_TICKET_RET_REJECT;
+            *outLen = inLen;  /* no padding in this mode */
+        } else {
+            /* decrypt */
+
+            /* see if we know this key */
+            if (XMEMCMP(key_name, myKey_ctx.name, WOLFSSL_TICKET_NAME_SZ) != 0){
+                printf("client presented unknown ticket key name ");
+                return WOLFSSL_TICKET_RET_FATAL;
+            }
+
+            /* build aad from key name, iv, and length */
+            XMEMCPY(tmp, key_name, WOLFSSL_TICKET_NAME_SZ);
+            tmp += WOLFSSL_TICKET_NAME_SZ;
+            XMEMCPY(tmp, iv, WOLFSSL_TICKET_IV_SZ);
+            tmp += WOLFSSL_TICKET_IV_SZ;
+            XMEMCPY(tmp, &sLen, 2);
+
+            ret = wc_ChaCha20Poly1305_Decrypt(myKey_ctx.key, iv,
+                                              aad, aadSz,
+                                              ticket, inLen,
+                                              mac,
+                                              ticket);
+            if (ret != 0) return WOLFSSL_TICKET_RET_REJECT;
+            *outLen = inLen;  /* no padding in this mode */
+        }
+
+        return WOLFSSL_TICKET_RET_OK;
+    }
+
+#endif  /* HAVE_SESSION_TICKET && CHACHA20 && POLY1305 */
+
+static WC_INLINE word16 GetRandomPort(void)
+{
+    word16 port = 0;
+
+    /* Generate random port for testing */
+    WC_RNG rng;
+    if (wc_InitRng(&rng) == 0) {
+        if (wc_RNG_GenerateBlock(&rng, (byte*)&port, sizeof(port)) == 0) {
+            port |= 0xC000; /* Make sure its in the 49152 - 65535 range */
+        }
+        wc_FreeRng(&rng);
+    }
+    (void)rng; /* for WC_NO_RNG case */
+    return port;
+}
+
+#endif /* wolfSSL_TEST_H */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/version.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/version.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/version.h	(revision 453)
@@ -0,0 +1,40 @@
+/* wolfssl_version.h.in
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifndef WOLFSSL_VERSION_H
+#define WOLFSSL_VERSION_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LIBWOLFSSL_VERSION_STRING "4.4.0"
+#define LIBWOLFSSL_VERSION_HEX 0x04004000
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* WOLFSSL_VERSION_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/aes.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/aes.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/aes.h	(revision 453)
@@ -0,0 +1,437 @@
+/* aes.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/aes.h
+*/
+
+
+#ifndef WOLF_CRYPT_AES_H
+#define WOLF_CRYPT_AES_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifndef NO_AES
+
+#if defined(HAVE_FIPS) && \
+    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
+    #include <wolfssl/wolfcrypt/fips.h>
+#endif /* HAVE_FIPS_VERSION >= 2 */
+
+/* included for fips @wc_fips */
+#if defined(HAVE_FIPS) && \
+    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
+#include <cyassl/ctaocrypt/aes.h>
+#if defined(CYASSL_AES_COUNTER) && !defined(WOLFSSL_AES_COUNTER)
+    #define WOLFSSL_AES_COUNTER
+#endif
+#if !defined(WOLFSSL_AES_DIRECT) && defined(CYASSL_AES_DIRECT)
+    #define WOLFSSL_AES_DIRECT
+#endif
+#endif
+
+#ifndef WC_NO_RNG
+    #include <wolfssl/wolfcrypt/random.h>
+#endif
+#ifdef STM32_CRYPTO
+    #include <wolfssl/wolfcrypt/port/st/stm32.h>
+#endif
+
+#ifdef WOLFSSL_AESNI
+
+#include <wmmintrin.h>
+#include <emmintrin.h>
+#include <smmintrin.h>
+
+#endif /* WOLFSSL_AESNI */
+
+
+#ifdef WOLFSSL_XILINX_CRYPT
+#include "xsecure_aes.h"
+#endif
+
+#if defined(WOLFSSL_AFALG) || defined(WOLFSSL_AFALG_XILINX_AES)
+/* included for struct msghdr */
+#include <wolfssl/wolfcrypt/port/af_alg/wc_afalg.h>
+#endif
+
+#if defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC)
+#include <wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h>
+#endif
+
+#if defined(HAVE_AESGCM) && !defined(WC_NO_RNG)
+    #include <wolfssl/wolfcrypt/random.h>
+#endif
+
+#if defined(WOLFSSL_CRYPTOCELL)
+    #include <wolfssl/wolfcrypt/port/arm/cryptoCell.h>
+#endif
+
+#if defined(WOLFSSL_RENESAS_TSIP_TLS) && \
+    defined(WOLFSSL_RENESAS_TSIP_TLS_AES_CRYPT)
+    #include <wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h>
+#endif
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+#ifndef WOLFSSL_AES_KEY_SIZE_ENUM
+#define WOLFSSL_AES_KEY_SIZE_ENUM
+/* these are required for FIPS and non-FIPS */
+enum {
+    AES_128_KEY_SIZE    = 16,  /* for 128 bit             */
+    AES_192_KEY_SIZE    = 24,  /* for 192 bit             */
+    AES_256_KEY_SIZE    = 32,  /* for 256 bit             */
+
+    AES_IV_SIZE         = 16,  /* always block size       */
+};
+#endif
+
+/* avoid redefinition of structs */
+#if !defined(HAVE_FIPS) || \
+    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    #include <wolfssl/wolfcrypt/async.h>
+#endif
+
+enum {
+    AES_ENC_TYPE   = WC_CIPHER_AES,   /* cipher unique type */
+    AES_ENCRYPTION = 0,
+    AES_DECRYPTION = 1,
+
+    AES_BLOCK_SIZE      = 16,
+
+    KEYWRAP_BLOCK_SIZE  = 8,
+
+    GCM_NONCE_MAX_SZ = 16, /* wolfCrypt's maximum nonce size allowed. */
+    GCM_NONCE_MID_SZ = 12, /* The usual default nonce size for AES-GCM. */
+    GCM_NONCE_MIN_SZ = 8,  /* wolfCrypt's minimum nonce size allowed. */
+    CCM_NONCE_MIN_SZ = 7,
+    CCM_NONCE_MAX_SZ = 13,
+    CTR_SZ   = 4,
+    AES_IV_FIXED_SZ = 4,
+#ifdef WOLFSSL_AES_CFB
+    AES_CFB_MODE = 1,
+#endif
+#ifdef WOLFSSL_AES_OFB
+    AES_OFB_MODE = 2,
+#endif
+#ifdef WOLFSSL_AES_XTS
+    AES_XTS_MODE = 3,
+#endif
+
+#ifdef HAVE_PKCS11
+    AES_MAX_ID_LEN   = 32,
+#endif
+};
+
+
+struct Aes {
+    /* AESNI needs key first, rounds 2nd, not sure why yet */
+    ALIGN16 word32 key[60];
+    word32  rounds;
+    int     keylen;
+
+    ALIGN16 word32 reg[AES_BLOCK_SIZE / sizeof(word32)];      /* for CBC mode */
+    ALIGN16 word32 tmp[AES_BLOCK_SIZE / sizeof(word32)];      /* same         */
+
+#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM)
+    word32 invokeCtr[2];
+    word32 nonceSz;
+#endif
+#ifdef HAVE_AESGCM
+    ALIGN16 byte H[AES_BLOCK_SIZE];
+#ifdef OPENSSL_EXTRA
+    word32 aadH[4]; /* additional authenticated data GHASH */
+    word32 aadLen;  /* additional authenticated data len */
+#endif
+
+#ifdef GCM_TABLE
+    /* key-based fast multiplication table. */
+    ALIGN16 byte M0[256][AES_BLOCK_SIZE];
+#endif /* GCM_TABLE */
+#ifdef HAVE_CAVIUM_OCTEON_SYNC
+    word32 y0;
+#endif
+#endif /* HAVE_AESGCM */
+#ifdef WOLFSSL_AESNI
+    byte use_aesni;
+#endif /* WOLFSSL_AESNI */
+#ifdef WOLF_CRYPTO_CB
+    int    devId;
+    void*  devCtx;
+#endif
+#ifdef HAVE_PKCS11
+    byte id[AES_MAX_ID_LEN];
+    int  idLen;
+#endif
+#ifdef WOLFSSL_ASYNC_CRYPT
+    WC_ASYNC_DEV asyncDev;
+#endif /* WOLFSSL_ASYNC_CRYPT */
+#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) || \
+    defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS)
+    word32  left;            /* unused bytes left from last call */
+#endif
+#ifdef WOLFSSL_XILINX_CRYPT
+    XSecure_Aes xilAes;
+    XCsuDma     dma;
+    word32      key_init[8];
+    word32      kup;
+#endif
+#if defined(WOLFSSL_AFALG) || defined(WOLFSSL_AFALG_XILINX_AES)
+    int alFd; /* server socket to bind to */
+    int rdFd; /* socket to read from */
+    struct msghdr msg;
+    int dir;  /* flag for encrpyt or decrypt */
+#ifdef WOLFSSL_AFALG_XILINX_AES
+    word32 msgBuf[CMSG_SPACE(4) + CMSG_SPACE(sizeof(struct af_alg_iv) +
+                  GCM_NONCE_MID_SZ)];
+#endif
+#endif
+#if defined(WOLF_CRYPTO_CB) || (defined(WOLFSSL_DEVCRYPTO) && \
+    (defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC))) || \
+    (defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES))
+    word32 devKey[AES_MAX_KEY_SIZE/WOLFSSL_BIT_SIZE/sizeof(word32)]; /* raw key */
+#ifdef HAVE_CAVIUM_OCTEON_SYNC
+    int    keySet;
+#endif
+#endif
+#if defined(WOLFSSL_DEVCRYPTO) && \
+    (defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC))
+    WC_CRYPTODEV ctx;
+#endif
+#if defined(WOLFSSL_CRYPTOCELL)
+    aes_context_t ctx;
+#endif
+#if defined(WOLFSSL_RENESAS_TSIP_TLS) && \
+    defined(WOLFSSL_RENESAS_TSIP_TLS_AES_CRYPT)
+    TSIP_AES_CTX ctx;
+#endif
+    void*  heap; /* memory hint to use */
+};
+
+#ifndef WC_AES_TYPE_DEFINED
+    typedef struct Aes Aes;
+    #define WC_AES_TYPE_DEFINED
+#endif
+
+#ifdef WOLFSSL_AES_XTS
+typedef struct XtsAes {
+    Aes aes;
+    Aes tweak;
+} XtsAes;
+#endif
+
+#ifdef HAVE_AESGCM
+typedef struct Gmac {
+    Aes aes;
+} Gmac;
+#endif /* HAVE_AESGCM */
+#endif /* HAVE_FIPS */
+
+
+/* Authenticate cipher function prototypes */
+typedef int (*wc_AesAuthEncryptFunc)(Aes* aes, byte* out,
+                                   const byte* in, word32 sz,
+                                   const byte* iv, word32 ivSz,
+                                   byte* authTag, word32 authTagSz,
+                                   const byte* authIn, word32 authInSz);
+typedef int (*wc_AesAuthDecryptFunc)(Aes* aes, byte* out,
+                                   const byte* in, word32 sz,
+                                   const byte* iv, word32 ivSz,
+                                   const byte* authTag, word32 authTagSz,
+                                   const byte* authIn, word32 authInSz);
+
+/* AES-CBC */
+WOLFSSL_API int  wc_AesSetKey(Aes* aes, const byte* key, word32 len,
+                              const byte* iv, int dir);
+WOLFSSL_API int  wc_AesSetIV(Aes* aes, const byte* iv);
+
+#ifdef HAVE_AES_CBC
+WOLFSSL_API int  wc_AesCbcEncrypt(Aes* aes, byte* out,
+                                  const byte* in, word32 sz);
+WOLFSSL_API int  wc_AesCbcDecrypt(Aes* aes, byte* out,
+                                  const byte* in, word32 sz);
+#endif
+
+#ifdef WOLFSSL_AES_CFB
+WOLFSSL_API int wc_AesCfbEncrypt(Aes* aes, byte* out,
+                                    const byte* in, word32 sz);
+WOLFSSL_API int wc_AesCfb1Encrypt(Aes* aes, byte* out,
+                                    const byte* in, word32 sz);
+WOLFSSL_API int wc_AesCfb8Encrypt(Aes* aes, byte* out,
+                                    const byte* in, word32 sz);
+#ifdef HAVE_AES_DECRYPT
+WOLFSSL_API int wc_AesCfbDecrypt(Aes* aes, byte* out,
+                                    const byte* in, word32 sz);
+WOLFSSL_API int wc_AesCfb1Decrypt(Aes* aes, byte* out,
+                                    const byte* in, word32 sz);
+WOLFSSL_API int wc_AesCfb8Decrypt(Aes* aes, byte* out,
+                                    const byte* in, word32 sz);
+#endif /* HAVE_AES_DECRYPT */
+#endif /* WOLFSSL_AES_CFB */
+
+#ifdef WOLFSSL_AES_OFB
+WOLFSSL_API int wc_AesOfbEncrypt(Aes* aes, byte* out,
+                                    const byte* in, word32 sz);
+#ifdef HAVE_AES_DECRYPT
+WOLFSSL_API int wc_AesOfbDecrypt(Aes* aes, byte* out,
+                                    const byte* in, word32 sz);
+#endif /* HAVE_AES_DECRYPT */
+#endif /* WOLFSSL_AES_OFB */
+
+#ifdef HAVE_AES_ECB
+WOLFSSL_API int wc_AesEcbEncrypt(Aes* aes, byte* out,
+                                  const byte* in, word32 sz);
+WOLFSSL_API int wc_AesEcbDecrypt(Aes* aes, byte* out,
+                                  const byte* in, word32 sz);
+#endif
+
+/* AES-CTR */
+#ifdef WOLFSSL_AES_COUNTER
+ WOLFSSL_API int wc_AesCtrEncrypt(Aes* aes, byte* out,
+                                   const byte* in, word32 sz);
+#endif
+/* AES-DIRECT */
+#if defined(WOLFSSL_AES_DIRECT)
+ WOLFSSL_API void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in);
+ WOLFSSL_API void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in);
+ WOLFSSL_API int  wc_AesSetKeyDirect(Aes* aes, const byte* key, word32 len,
+                                const byte* iv, int dir);
+#endif
+
+#ifdef HAVE_AESGCM
+#ifdef WOLFSSL_XILINX_CRYPT
+ WOLFSSL_API int  wc_AesGcmSetKey_ex(Aes* aes, const byte* key, word32 len,
+         word32 kup);
+#elif defined(WOLFSSL_AFALG_XILINX_AES)
+ WOLFSSL_LOCAL int  wc_AesGcmSetKey_ex(Aes* aes, const byte* key, word32 len,
+         word32 kup);
+#endif
+ WOLFSSL_API int  wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len);
+ WOLFSSL_API int  wc_AesGcmEncrypt(Aes* aes, byte* out,
+                                   const byte* in, word32 sz,
+                                   const byte* iv, word32 ivSz,
+                                   byte* authTag, word32 authTagSz,
+                                   const byte* authIn, word32 authInSz);
+ WOLFSSL_API int  wc_AesGcmDecrypt(Aes* aes, byte* out,
+                                   const byte* in, word32 sz,
+                                   const byte* iv, word32 ivSz,
+                                   const byte* authTag, word32 authTagSz,
+                                   const byte* authIn, word32 authInSz);
+
+#ifndef WC_NO_RNG
+ WOLFSSL_API int  wc_AesGcmSetExtIV(Aes* aes, const byte* iv, word32 ivSz);
+ WOLFSSL_API int  wc_AesGcmSetIV(Aes* aes, word32 ivSz,
+                                   const byte* ivFixed, word32 ivFixedSz,
+                                   WC_RNG* rng);
+ WOLFSSL_API int  wc_AesGcmEncrypt_ex(Aes* aes, byte* out,
+                                   const byte* in, word32 sz,
+                                   byte* ivOut, word32 ivOutSz,
+                                   byte* authTag, word32 authTagSz,
+                                   const byte* authIn, word32 authInSz);
+#endif /* WC_NO_RNG */
+
+ WOLFSSL_API int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len);
+ WOLFSSL_API int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz,
+                               const byte* authIn, word32 authInSz,
+                               byte* authTag, word32 authTagSz);
+#ifndef WC_NO_RNG
+ WOLFSSL_API int wc_Gmac(const byte* key, word32 keySz, byte* iv, word32 ivSz,
+                               const byte* authIn, word32 authInSz,
+                               byte* authTag, word32 authTagSz, WC_RNG* rng);
+ WOLFSSL_API int wc_GmacVerify(const byte* key, word32 keySz,
+                               const byte* iv, word32 ivSz,
+                               const byte* authIn, word32 authInSz,
+                               const byte* authTag, word32 authTagSz);
+#endif /* WC_NO_RNG */
+ WOLFSSL_LOCAL void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
+                               word32 cSz, byte* s, word32 sSz);
+#endif /* HAVE_AESGCM */
+#ifdef HAVE_AESCCM
+ WOLFSSL_API int  wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz);
+ WOLFSSL_API int  wc_AesCcmEncrypt(Aes* aes, byte* out,
+                                   const byte* in, word32 inSz,
+                                   const byte* nonce, word32 nonceSz,
+                                   byte* authTag, word32 authTagSz,
+                                   const byte* authIn, word32 authInSz);
+ WOLFSSL_API int  wc_AesCcmDecrypt(Aes* aes, byte* out,
+                                   const byte* in, word32 inSz,
+                                   const byte* nonce, word32 nonceSz,
+                                   const byte* authTag, word32 authTagSz,
+                                   const byte* authIn, word32 authInSz);
+ WOLFSSL_API int  wc_AesCcmSetNonce(Aes* aes,
+                                   const byte* nonce, word32 nonceSz);
+ WOLFSSL_API int  wc_AesCcmEncrypt_ex(Aes* aes, byte* out,
+                                   const byte* in, word32 sz,
+                                   byte* ivOut, word32 ivOutSz,
+                                   byte* authTag, word32 authTagSz,
+                                   const byte* authIn, word32 authInSz);
+#endif /* HAVE_AESCCM */
+#ifdef HAVE_AES_KEYWRAP
+ WOLFSSL_API int  wc_AesKeyWrap(const byte* key, word32 keySz,
+                                const byte* in, word32 inSz,
+                                byte* out, word32 outSz,
+                                const byte* iv);
+ WOLFSSL_API int  wc_AesKeyUnWrap(const byte* key, word32 keySz,
+                                const byte* in, word32 inSz,
+                                byte* out, word32 outSz,
+                                const byte* iv);
+#endif /* HAVE_AES_KEYWRAP */
+
+#ifdef WOLFSSL_AES_XTS
+
+WOLFSSL_API int wc_AesXtsSetKey(XtsAes* aes, const byte* key,
+         word32 len, int dir, void* heap, int devId);
+
+WOLFSSL_API int wc_AesXtsEncryptSector(XtsAes* aes, byte* out,
+         const byte* in, word32 sz, word64 sector);
+
+WOLFSSL_API int wc_AesXtsDecryptSector(XtsAes* aes, byte* out,
+         const byte* in, word32 sz, word64 sector);
+
+WOLFSSL_API int wc_AesXtsEncrypt(XtsAes* aes, byte* out,
+         const byte* in, word32 sz, const byte* i, word32 iSz);
+
+WOLFSSL_API int wc_AesXtsDecrypt(XtsAes* aes, byte* out,
+        const byte* in, word32 sz, const byte* i, word32 iSz);
+
+WOLFSSL_API int wc_AesXtsFree(XtsAes* aes);
+#endif
+
+WOLFSSL_API int wc_AesGetKeySize(Aes* aes, word32* keySize);
+
+WOLFSSL_API int  wc_AesInit(Aes* aes, void* heap, int devId);
+#ifdef HAVE_PKCS11
+WOLFSSL_API int  wc_AesInit_Id(Aes* aes, unsigned char* id, int len, void* heap,
+        int devId);
+#endif
+WOLFSSL_API void wc_AesFree(Aes* aes);
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+
+#endif /* NO_AES */
+#endif /* WOLF_CRYPT_AES_H */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/arc4.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/arc4.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/arc4.h	(revision 453)
@@ -0,0 +1,68 @@
+/* arc4.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/arc4.h
+*/
+
+#ifndef WOLF_CRYPT_ARC4_H
+#define WOLF_CRYPT_ARC4_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    #include <wolfssl/wolfcrypt/async.h>
+#endif
+
+enum {
+	ARC4_ENC_TYPE   = 4,    /* cipher unique type */
+    ARC4_STATE_SIZE = 256,
+    RC4_KEY_SIZE    = 16,   /* always 128bit           */
+};
+
+/* ARC4 encryption and decryption */
+typedef struct Arc4 {
+    byte x;
+    byte y;
+    byte state[ARC4_STATE_SIZE];
+#ifdef WOLFSSL_ASYNC_CRYPT
+    WC_ASYNC_DEV asyncDev;
+#endif
+    void* heap;
+} Arc4;
+
+WOLFSSL_API int wc_Arc4Process(Arc4*, byte*, const byte*, word32);
+WOLFSSL_API int wc_Arc4SetKey(Arc4*, const byte*, word32);
+
+WOLFSSL_API int  wc_Arc4Init(Arc4*, void*, int);
+WOLFSSL_API void wc_Arc4Free(Arc4*);
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+
+#endif /* WOLF_CRYPT_ARC4_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/asn.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/asn.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/asn.h	(revision 453)
@@ -0,0 +1,1470 @@
+/* asn.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/asn.h
+*/
+
+#ifndef WOLF_CRYPT_ASN_H
+#define WOLF_CRYPT_ASN_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifndef NO_ASN
+
+
+#if !defined(NO_ASN_TIME) && defined(NO_TIME_H)
+    #define NO_ASN_TIME /* backwards compatibility with NO_TIME_H */
+#endif
+
+#include <wolfssl/wolfcrypt/integer.h>
+
+/* fips declare of RsaPrivateKeyDecode @wc_fips */
+#if defined(HAVE_FIPS) && !defined(NO_RSA) && \
+	(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
+    #include <cyassl/ctaocrypt/rsa.h>
+#endif
+
+#ifndef NO_DH
+    #include <wolfssl/wolfcrypt/dh.h>
+#endif
+#ifndef NO_DSA
+    #include <wolfssl/wolfcrypt/dsa.h>
+#endif
+#ifndef NO_SHA
+    #include <wolfssl/wolfcrypt/sha.h>
+#endif
+#ifndef NO_MD5
+    #include <wolfssl/wolfcrypt/md5.h>
+#endif
+#include <wolfssl/wolfcrypt/sha256.h>
+#include <wolfssl/wolfcrypt/asn_public.h>   /* public interface */
+
+#if defined(NO_SHA) && defined(NO_SHA256)
+    #define WC_SHA256_DIGEST_SIZE 32
+#endif
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+#ifndef EXTERNAL_SERIAL_SIZE
+    #define EXTERNAL_SERIAL_SIZE 32
+#endif
+
+enum {
+    ISSUER  = 0,
+    SUBJECT = 1,
+
+    BEFORE  = 0,
+    AFTER   = 1
+};
+
+/* ASN Tags   */
+enum ASN_Tags {
+    ASN_EOC               = 0x00,
+    ASN_BOOLEAN           = 0x01,
+    ASN_INTEGER           = 0x02,
+    ASN_BIT_STRING        = 0x03,
+    ASN_OCTET_STRING      = 0x04,
+    ASN_TAG_NULL          = 0x05,
+    ASN_OBJECT_ID         = 0x06,
+    ASN_ENUMERATED        = 0x0a,
+    ASN_UTF8STRING        = 0x0c,
+    ASN_SEQUENCE          = 0x10,
+    ASN_SET               = 0x11,
+    ASN_PRINTABLE_STRING  = 0x13,
+    ASN_UTC_TIME          = 0x17,
+    ASN_OTHER_TYPE        = 0x00,
+    ASN_RFC822_TYPE       = 0x01,
+    ASN_DNS_TYPE          = 0x02,
+    ASN_DIR_TYPE          = 0x04,
+    ASN_URI_TYPE          = 0x06, /* the value 6 is from GeneralName OID */
+    ASN_IP_TYPE           = 0x07, /* the value 7 is from GeneralName OID */
+    ASN_GENERALIZED_TIME  = 0x18,
+    CRL_EXTENSIONS        = 0xa0,
+    ASN_EXTENSIONS        = 0xa3,
+    ASN_LONG_LENGTH       = 0x80,
+    ASN_INDEF_LENGTH      = 0x80,
+
+    /* ASN_Flags - Bitmask */
+    ASN_CONSTRUCTED       = 0x20,
+    ASN_APPLICATION       = 0x40,
+    ASN_CONTEXT_SPECIFIC  = 0x80,
+};
+
+#define ASN_UTC_TIME_SIZE 14
+#define ASN_GENERALIZED_TIME_SIZE 16
+#define ASN_GENERALIZED_TIME_MAX 68
+
+enum DN_Tags {
+    ASN_DN_NULL       = 0x00,
+    ASN_COMMON_NAME   = 0x03,   /* CN */
+    ASN_SUR_NAME      = 0x04,   /* SN */
+    ASN_SERIAL_NUMBER = 0x05,   /* serialNumber */
+    ASN_COUNTRY_NAME  = 0x06,   /* C  */
+    ASN_LOCALITY_NAME = 0x07,   /* L  */
+    ASN_STATE_NAME    = 0x08,   /* ST */
+    ASN_ORG_NAME      = 0x0a,   /* O  */
+    ASN_ORGUNIT_NAME  = 0x0b,   /* OU */
+    ASN_BUS_CAT       = 0x0f,   /* businessCategory */
+    ASN_EMAIL_NAME    = 0x98,   /* not oid number there is 97 in 2.5.4.0-97 */
+
+    /* pilot attribute types
+     * OID values of 0.9.2342.19200300.100.1.* */
+    ASN_USER_ID          = 0x01, /* UID */
+    ASN_DOMAIN_COMPONENT = 0x19  /* DC */
+};
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+typedef struct WOLFSSL_ObjectInfo {
+    int nid;
+    int id;
+    word32 type;
+    const char* sName;
+    const char* lName;
+} WOLFSSL_ObjectInfo;
+extern const size_t wolfssl_object_info_sz;
+extern const WOLFSSL_ObjectInfo wolfssl_object_info[];
+#endif /* defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) */
+
+/* DN Tag Strings */
+#define WOLFSSL_COMMON_NAME      "/CN="
+#define WOLFSSL_LN_COMMON_NAME   "/commonName="
+#define WOLFSSL_SUR_NAME         "/SN="
+#define WOLFSSL_SERIAL_NUMBER    "/serialNumber="
+#define WOLFSSL_COUNTRY_NAME     "/C="
+#define WOLFSSL_LN_COUNTRY_NAME  "/countryName="
+#define WOLFSSL_LOCALITY_NAME    "/L="
+#define WOLFSSL_LN_LOCALITY_NAME "/localityName="
+#define WOLFSSL_STATE_NAME       "/ST="
+#define WOLFSSL_LN_STATE_NAME    "/stateOrProvinceName="
+#define WOLFSSL_ORG_NAME         "/O="
+#define WOLFSSL_LN_ORG_NAME      "/organizationName="
+#define WOLFSSL_ORGUNIT_NAME     "/OU="
+#define WOLFSSL_LN_ORGUNIT_NAME  "/organizationalUnitName="
+#define WOLFSSL_DOMAIN_COMPONENT "/DC="
+#define WOLFSSL_LN_DOMAIN_COMPONENT "/domainComponent="
+#define WOLFSSL_BUS_CAT          "/businessCategory="
+#define WOLFSSL_JOI_C            "/jurisdictionC="
+#define WOLFSSL_JOI_ST           "/jurisdictionST="
+#define WOLFSSL_EMAIL_ADDR       "/emailAddress="
+
+#define WOLFSSL_USER_ID          "/UID="
+#define WOLFSSL_DOMAIN_COMPONENT "/DC="
+
+#if defined(WOLFSSL_APACHE_HTTPD)
+    /* otherName strings */
+    #define WOLFSSL_SN_MS_UPN       "msUPN"
+    #define WOLFSSL_LN_MS_UPN       "Microsoft User Principal Name"
+    #define WOLFSSL_MS_UPN_SUM 265
+    #define WOLFSSL_SN_DNS_SRV      "id-on-dnsSRV"
+    #define WOLFSSL_LN_DNS_SRV      "SRVName"
+    /* TLS features extension strings */
+    #define WOLFSSL_SN_TLS_FEATURE  "tlsfeature"
+    #define WOLFSSL_LN_TLS_FEATURE  "TLS Feature"
+    #define WOLFSSL_TLS_FEATURE_SUM 92
+#endif
+
+/* NIDs */
+enum
+{
+    NID_undef = 0,
+    NID_netscape_cert_type = NID_undef,
+    NID_des = 66,
+    NID_des3 = 67,
+    NID_sha256 = 672,
+    NID_sha384 = 673,
+    NID_sha512 = 674,
+    NID_hw_name_oid = 73,
+    NID_id_pkix_OCSP_basic = 74,
+    NID_any_policy = 75,
+    NID_anyExtendedKeyUsage = 76,
+    NID_givenName = 99,
+    NID_initials = 101,
+    NID_title = 106,
+    NID_description = 107,
+    NID_basic_constraints = 133,
+    NID_key_usage = 129,     /* 2.5.29.15 */
+    NID_ext_key_usage = 151, /* 2.5.29.37 */
+    NID_subject_key_identifier = 128,
+    NID_authority_key_identifier = 149,
+    NID_private_key_usage_period = 130, /* 2.5.29.16 */
+    NID_subject_alt_name = 131,
+    NID_issuer_alt_name = 132,
+    NID_info_access = 69,
+    NID_sinfo_access = 79,      /* id-pe 11 */
+    NID_name_constraints = 144, /* 2.5.29.30 */
+    NID_crl_distribution_points = 145, /* 2.5.29.31 */
+    NID_certificate_policies = 146,
+    NID_policy_mappings = 147,
+    NID_policy_constraints = 150,
+    NID_inhibit_any_policy = 168,      /* 2.5.29.54 */
+    NID_tlsfeature = 1020,             /* id-pe 24 */
+    NID_commonName = 0x03,             /* matches ASN_COMMON_NAME in asn.h */
+
+
+    NID_surname = 0x04,                /* SN */
+    NID_serialNumber = 0x05,           /* serialNumber */
+    NID_countryName = 0x06,            /* C  */
+    NID_localityName = 0x07,           /* L  */
+    NID_stateOrProvinceName = 0x08,    /* ST */
+    NID_organizationName = 0x0a,       /* O  */
+    NID_organizationalUnitName = 0x0b, /* OU */
+    NID_jurisdictionCountryName = 0xc,
+    NID_jurisdictionStateOrProvinceName = 0xd,
+    NID_businessCategory = ASN_BUS_CAT,
+    NID_domainComponent = ASN_DOMAIN_COMPONENT,
+    NID_emailAddress = 0x30,           /* emailAddress */
+    NID_id_on_dnsSRV = 82,             /* 1.3.6.1.5.5.7.8.7 */
+    NID_ms_upn = 265,                  /* 1.3.6.1.4.1.311.20.2.3 */
+
+    NID_X9_62_prime_field = 406        /* 1.2.840.10045.1.1 */
+};
+
+enum ECC_TYPES
+{
+    ECC_PREFIX_0 = 160,
+    ECC_PREFIX_1 = 161
+};
+
+#ifdef WOLFSSL_CERT_PIV
+    enum PIV_Tags {
+        ASN_PIV_CERT          = 0x0A,
+        ASN_PIV_NONCE         = 0x0B,
+        ASN_PIV_SIGNED_NONCE  = 0x0C,
+
+        ASN_PIV_TAG_CERT      = 0x70,
+        ASN_PIV_TAG_CERT_INFO = 0x71,
+        ASN_PIV_TAG_MSCUID    = 0x72,
+        ASN_PIV_TAG_ERR_DET   = 0xFE,
+
+        /* certificate info masks */
+        ASN_PIV_CERT_INFO_COMPRESSED = 0x03,
+        ASN_PIV_CERT_INFO_ISX509     = 0x04,
+    };
+#endif /* WOLFSSL_CERT_PIV */
+
+
+#define ASN_JOI_PREFIX_SZ       10
+#define ASN_JOI_PREFIX          "\x2b\x06\x01\x04\x01\x82\x37\x3c\x02\x01"
+#define ASN_JOI_C               0x3
+#define ASN_JOI_ST              0x2
+
+#ifndef WC_ASN_NAME_MAX
+    #ifdef OPENSSL_EXTRA
+        #define WC_ASN_NAME_MAX 300
+    #else
+        #define WC_ASN_NAME_MAX 256
+    #endif
+#endif
+#define ASN_NAME_MAX WC_ASN_NAME_MAX
+
+enum Misc_ASN {
+    MAX_SALT_SIZE       =  64,     /* MAX PKCS Salt length */
+    MAX_IV_SIZE         =  64,     /* MAX PKCS Iv length */
+    ASN_BOOL_SIZE       =   2,     /* including type */
+    ASN_ECC_HEADER_SZ   =   2,     /* String type + 1 byte len */
+    ASN_ECC_CONTEXT_SZ  =   2,     /* Content specific type + 1 byte len */
+#ifdef NO_SHA
+    KEYID_SIZE          = WC_SHA256_DIGEST_SIZE,
+#else
+    KEYID_SIZE          = WC_SHA_DIGEST_SIZE,
+#endif
+    RSA_INTS            =   8,     /* RSA ints in private key */
+    DSA_INTS            =   5,     /* DSA ints in private key */
+    MIN_DATE_SIZE       =  13,
+    MAX_DATE_SIZE       =  32,
+    ASN_GEN_TIME_SZ     =  15,     /* 7 numbers * 2 + Zulu tag */
+#ifndef NO_RSA
+    MAX_ENCODED_SIG_SZ  = 512,
+#elif defined(HAVE_ECC)
+    MAX_ENCODED_SIG_SZ  = 140,
+#elif defined(HAVE_CURVE448)
+    MAX_ENCODED_SIG_SZ  = 114,
+#else
+    MAX_ENCODED_SIG_SZ  =  64,
+#endif
+    MAX_SIG_SZ          = 256,
+    MAX_ALGO_SZ         =  20,
+    MAX_SHORT_SZ        =   6,     /* asn int + byte len + 4 byte length */
+    MAX_SEQ_SZ          =   5,     /* enum(seq | con) + length(4) */
+    MAX_SET_SZ          =   5,     /* enum(set | con) + length(4) */
+    MAX_OCTET_STR_SZ    =   5,     /* enum(set | con) + length(4) */
+    MAX_EXP_SZ          =   5,     /* enum(contextspec|con|exp) + length(4) */
+    MAX_PRSTR_SZ        =   5,     /* enum(prstr) + length(4) */
+    MAX_VERSION_SZ      =   5,     /* enum + id + version(byte) + (header(2))*/
+    MAX_ENCODED_DIG_ASN_SZ= 9,     /* enum(bit or octet) + length(4) */
+    MAX_ENCODED_DIG_SZ  =  64 + MAX_ENCODED_DIG_ASN_SZ, /* asn header + sha512 */
+    MAX_RSA_INT_SZ      = 517,     /* RSA raw sz 4096 for bits + tag + len(4) */
+    MAX_DSA_INT_SZ      = 261,     /* DSA raw sz 2048 for bits + tag + len(4) */
+    MAX_NTRU_KEY_SZ     = 610,     /* NTRU 112 bit public key */
+    MAX_NTRU_ENC_SZ     = 628,     /* NTRU 112 bit DER public encoding */
+    MAX_LENGTH_SZ       =   4,     /* Max length size for DER encoding */
+    MAX_RSA_E_SZ        =  16,     /* Max RSA public e size */
+    MAX_CA_SZ           =  32,     /* Max encoded CA basic constraint length */
+    MAX_SN_SZ           =  35,     /* Max encoded serial number (INT) length */
+    MAX_DER_DIGEST_SZ     = MAX_ENCODED_DIG_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ,
+                            /* Maximum DER digest size */
+    MAX_DER_DIGEST_ASN_SZ = MAX_ENCODED_DIG_ASN_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ,
+                            /* Maximum DER digest ASN header size */
+#ifdef WOLFSSL_CERT_GEN
+    #ifdef WOLFSSL_CERT_REQ
+                          /* Max encoded cert req attributes length */
+        MAX_ATTRIB_SZ   = MAX_SEQ_SZ * 3 + (11 + MAX_SEQ_SZ) * 2 +
+                          MAX_PRSTR_SZ + CTC_NAME_SIZE, /* 11 is the OID size */
+    #endif
+    #if defined(WOLFSSL_ALT_NAMES) || defined(WOLFSSL_CERT_EXT)
+        MAX_EXTENSIONS_SZ   = 1 + MAX_LENGTH_SZ + CTC_MAX_ALT_SIZE,
+    #else
+        MAX_EXTENSIONS_SZ   = 1 + MAX_LENGTH_SZ + MAX_CA_SZ,
+    #endif
+                                   /* Max total extensions, id + len + others */
+#endif
+#if defined(WOLFSSL_CERT_EXT) || defined(OPENSSL_EXTRA) || defined(HAVE_PKCS7)
+    MAX_OID_SZ          = 32,      /* Max DER length of OID*/
+    MAX_OID_STRING_SZ   = 64,      /* Max string length representation of OID*/
+#endif
+#ifdef WOLFSSL_CERT_EXT
+    MAX_KID_SZ          = 45,      /* Max encoded KID length (SHA-256 case) */
+    MAX_KEYUSAGE_SZ     = 18,      /* Max encoded Key Usage length */
+    MAX_EXTKEYUSAGE_SZ  = 12 + (6 * (8 + 2)) +
+                          CTC_MAX_EKU_OID_SZ, /* Max encoded ExtKeyUsage
+                          (SEQ/LEN + OBJID + OCTSTR/LEN + SEQ +
+                          (6 * (SEQ + OID))) */
+    MAX_CERTPOL_NB      = CTC_MAX_CERTPOL_NB,/* Max number of Cert Policy */
+    MAX_CERTPOL_SZ      = CTC_MAX_CERTPOL_SZ,
+#endif
+    MAX_AIA_SZ          = 2,       /* Max Authority Info Access extension size*/
+    MAX_NAME_ENTRIES    = 5,       /* extra entries added to x509 name struct */
+    OCSP_NONCE_EXT_SZ   = 35,      /* OCSP Nonce Extension size */
+    MAX_OCSP_EXT_SZ     = 58,      /* Max OCSP Extension length */
+    MAX_OCSP_NONCE_SZ   = 16,      /* OCSP Nonce size           */
+    EIGHTK_BUF          = 8192,    /* Tmp buffer size           */
+    MAX_PUBLIC_KEY_SZ   = MAX_NTRU_ENC_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ * 2,
+                                   /* use bigger NTRU size */
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+    HEADER_ENCRYPTED_KEY_SIZE = 88,/* Extra header size for encrypted key */
+#else
+    HEADER_ENCRYPTED_KEY_SIZE = 0,
+#endif
+    TRAILING_ZERO       = 1,       /* Used for size of zero pad */
+    ASN_TAG_SZ          = 1,       /* single byte ASN.1 tag */
+    MIN_VERSION_SZ      = 3,       /* Min bytes needed for GetMyVersion */
+#if defined(OPENSSL_ALL)  || defined(WOLFSSL_MYSQL_COMPATIBLE) || \
+    defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
+    defined(OPENSSL_EXTRA) || defined(HAVE_PKCS7)
+    MAX_TIME_STRING_SZ  = 25,      /* Max length of formatted time string */
+#endif
+
+    PKCS5_SALT_SZ       = 8,
+
+    PEM_LINE_LEN       = 80,       /* PEM line max + fudge */
+};
+
+
+enum Oid_Types {
+    oidHashType         = 0,
+    oidSigType          = 1,
+    oidKeyType          = 2,
+    oidCurveType        = 3,
+    oidBlkType          = 4,
+    oidOcspType         = 5,
+    oidCertExtType      = 6,
+    oidCertAuthInfoType = 7,
+    oidCertPolicyType   = 8,
+    oidCertAltNameType  = 9,
+    oidCertKeyUseType   = 10,
+    oidKdfType          = 11,
+    oidKeyWrapType      = 12,
+    oidCmsKeyAgreeType  = 13,
+    oidPBEType          = 14,
+    oidHmacType         = 15,
+    oidCompressType     = 16,
+    oidCertNameType     = 17,
+    oidTlsExtType       = 18,
+    oidCrlExtType       = 19,
+    oidIgnoreType
+};
+
+
+enum Hash_Sum  {
+    MD2h      = 646,
+    MD5h      = 649,
+    SHAh      =  88,
+    SHA224h   = 417,
+    SHA256h   = 414,
+    SHA384h   = 415,
+    SHA512h   = 416,
+    SHA3_224h = 420,
+    SHA3_256h = 421,
+    SHA3_384h = 422,
+    SHA3_512h = 423
+};
+
+
+#if !defined(NO_DES3) || !defined(NO_AES)
+enum Block_Sum {
+#ifdef WOLFSSL_AES_128
+    AES128CBCb = 414,
+    AES128GCMb = 418,
+    AES128CCMb = 419,
+#endif
+#ifdef WOLFSSL_AES_192
+    AES192CBCb = 434,
+    AES192GCMb = 438,
+    AES192CCMb = 439,
+#endif
+#ifdef WOLFSSL_AES_256
+    AES256CBCb = 454,
+    AES256GCMb = 458,
+    AES256CCMb = 459,
+#endif
+#ifndef NO_DES3
+    DESb       = 69,
+    DES3b      = 652
+#endif
+};
+#endif /* !NO_DES3 || !NO_AES */
+
+
+enum Key_Sum {
+    DSAk     = 515,
+    RSAk     = 645,
+    NTRUk    = 274,
+    ECDSAk   = 518,
+    ED25519k = 256,
+    ED448k   = 257,
+    DHk      = 647, /* dhKeyAgreement OID: 1.2.840.113549.1.3.1 */
+};
+
+#if !defined(NO_AES) || defined(HAVE_PKCS7)
+enum KeyWrap_Sum {
+#ifdef WOLFSSL_AES_128
+    AES128_WRAP  = 417,
+#endif
+#ifdef WOLFSSL_AES_192
+    AES192_WRAP  = 437,
+#endif
+#ifdef WOLFSSL_AES_256
+    AES256_WRAP  = 457,
+#endif
+#ifdef HAVE_PKCS7
+    PWRI_KEK_WRAP = 680  /*id-alg-PWRI-KEK, 1.2.840.113549.1.9.16.3.9 */
+#endif
+};
+#endif /* !NO_AES || PKCS7 */
+
+enum Key_Agree {
+    dhSinglePass_stdDH_sha1kdf_scheme   = 464,
+    dhSinglePass_stdDH_sha224kdf_scheme = 188,
+    dhSinglePass_stdDH_sha256kdf_scheme = 189,
+    dhSinglePass_stdDH_sha384kdf_scheme = 190,
+    dhSinglePass_stdDH_sha512kdf_scheme = 191,
+};
+
+
+
+enum KDF_Sum {
+    PBKDF2_OID = 660
+};
+
+
+enum HMAC_Sum {
+    HMAC_SHA224_OID   = 652,
+    HMAC_SHA256_OID   = 653,
+    HMAC_SHA384_OID   = 654,
+    HMAC_SHA512_OID   = 655,
+    HMAC_SHA3_224_OID = 426,
+    HMAC_SHA3_256_OID = 427,
+    HMAC_SHA3_384_OID = 428,
+    HMAC_SHA3_512_OID = 429
+};
+
+
+enum Extensions_Sum {
+    BASIC_CA_OID    = 133,
+    ALT_NAMES_OID   = 131,
+    CRL_DIST_OID    = 145,
+    AUTH_INFO_OID   = 69, /* id-pe 1 */
+    AUTH_KEY_OID    = 149,
+    SUBJ_KEY_OID    = 128,
+    CERT_POLICY_OID = 146,
+    KEY_USAGE_OID   = 129,  /* 2.5.29.15 */
+    INHIBIT_ANY_OID = 168,  /* 2.5.29.54 */
+    EXT_KEY_USAGE_OID         = 151, /* 2.5.29.37 */
+    NAME_CONS_OID             = 144, /* 2.5.29.30 */
+    PRIV_KEY_USAGE_PERIOD_OID = 130, /* 2.5.29.16 */
+    SUBJECT_INFO_ACCESS       = 79,  /* id-pe 11 */
+    POLICY_MAP_OID            = 147,
+    POLICY_CONST_OID          = 150,
+    ISSUE_ALT_NAMES_OID       = 132,
+    TLS_FEATURE_OID           = 92,  /* id-pe 24 */
+    NETSCAPE_CT_OID           = 753  /* 2.16.840.1.113730.1.1 */
+};
+
+enum CertificatePolicy_Sum {
+    CP_ANY_OID      = 146  /* id-ce 32 0 */
+};
+
+enum SepHardwareName_Sum {
+    HW_NAME_OID     = 79   /* 1.3.6.1.5.5.7.8.4 from RFC 4108*/
+};
+
+enum AuthInfo_Sum {
+    AIA_OCSP_OID      = 116, /* 1.3.6.1.5.5.7.48.1 */
+    AIA_CA_ISSUER_OID = 117  /* 1.3.6.1.5.5.7.48.2 */
+};
+
+enum ExtKeyUsage_Sum { /* From RFC 5280 */
+    EKU_ANY_OID         = 151, /* 2.5.29.37.0, anyExtendedKeyUsage         */
+    EKU_SERVER_AUTH_OID = 71,  /* 1.3.6.1.5.5.7.3.1, id-kp-serverAuth      */
+    EKU_CLIENT_AUTH_OID = 72,  /* 1.3.6.1.5.5.7.3.2, id-kp-clientAuth      */
+    EKU_CODESIGNING_OID = 73,  /* 1.3.6.1.5.5.7.3.3, id-kp-codeSigning     */
+    EKU_EMAILPROTECT_OID = 74, /* 1.3.6.1.5.5.7.3.4, id-kp-emailProtection */
+    EKU_TIMESTAMP_OID   = 78,  /* 1.3.6.1.5.5.7.3.8, id-kp-timeStamping    */
+    EKU_OCSP_SIGN_OID   = 79   /* 1.3.6.1.5.5.7.3.9, id-kp-OCSPSigning     */
+};
+
+#ifdef HAVE_LIBZ
+enum CompressAlg_Sum {
+    ZLIBc = 679  /* 1.2.840.113549.1.9.16.3.8, id-alg-zlibCompress */
+};
+#endif
+
+enum VerifyType {
+    NO_VERIFY   = 0,
+    VERIFY      = 1,
+    VERIFY_CRL  = 2,
+    VERIFY_OCSP = 3,
+    VERIFY_NAME = 4,
+    VERIFY_SKIP_DATE = 5,
+};
+
+#ifdef WOLFSSL_CERT_EXT
+enum KeyIdType {
+    SKID_TYPE = 0,
+    AKID_TYPE = 1
+};
+#endif
+
+/* Key usage extension bits (based on RFC 5280) */
+#define KEYUSE_DIGITAL_SIG    0x0080
+#define KEYUSE_CONTENT_COMMIT 0x0040
+#define KEYUSE_KEY_ENCIPHER   0x0020
+#define KEYUSE_DATA_ENCIPHER  0x0010
+#define KEYUSE_KEY_AGREE      0x0008
+#define KEYUSE_KEY_CERT_SIGN  0x0004
+#define KEYUSE_CRL_SIGN       0x0002
+#define KEYUSE_ENCIPHER_ONLY  0x0001
+#define KEYUSE_DECIPHER_ONLY  0x8000
+
+/* Extended Key Usage bits (internal mapping only) */
+#define EXTKEYUSE_USER        0x80
+#define EXTKEYUSE_OCSP_SIGN   0x40
+#define EXTKEYUSE_TIMESTAMP   0x20
+#define EXTKEYUSE_EMAILPROT   0x10
+#define EXTKEYUSE_CODESIGN    0x08
+#define EXTKEYUSE_CLIENT_AUTH 0x04
+#define EXTKEYUSE_SERVER_AUTH 0x02
+#define EXTKEYUSE_ANY         0x01
+
+typedef struct DNS_entry   DNS_entry;
+
+struct DNS_entry {
+    DNS_entry* next;   /* next on DNS list */
+    int        type;   /* i.e. ASN_DNS_TYPE */
+    int        len;    /* actual DNS len */
+    char*      name;   /* actual DNS name */
+};
+
+
+typedef struct Base_entry  Base_entry;
+
+struct Base_entry {
+    Base_entry* next;   /* next on name base list */
+    char*       name;   /* actual name base */
+    int         nameSz; /* name length */
+    byte        type;   /* Name base type (DNS or RFC822) */
+};
+
+#define DOMAIN_COMPONENT_MAX 10
+#define DN_NAMES_MAX 9
+
+struct DecodedName {
+    char*   fullName;
+    int     fullNameLen;
+    int     entryCount;
+    int     cnIdx;
+    int     cnLen;
+    int     cnNid;
+    int     snIdx;
+    int     snLen;
+    int     snNid;
+    int     cIdx;
+    int     cLen;
+    int     cNid;
+    int     lIdx;
+    int     lLen;
+    int     lNid;
+    int     stIdx;
+    int     stLen;
+    int     stNid;
+    int     oIdx;
+    int     oLen;
+    int     oNid;
+    int     ouIdx;
+    int     ouLen;
+#ifdef WOLFSSL_CERT_EXT
+    int     bcIdx;
+    int     bcLen;
+    int     jcIdx;
+    int     jcLen;
+    int     jsIdx;
+    int     jsLen;
+#endif
+    int     ouNid;
+    int     emailIdx;
+    int     emailLen;
+    int     emailNid;
+    int     uidIdx;
+    int     uidLen;
+    int     uidNid;
+    int     serialIdx;
+    int     serialLen;
+    int     serialNid;
+    int     dcIdx[DOMAIN_COMPONENT_MAX];
+    int     dcLen[DOMAIN_COMPONENT_MAX];
+    int     dcNum;
+    int     dcMode;
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+    /* hold the location / order with which each of the DN tags was found
+     *
+     * example of ASN_DOMAIN_COMPONENT at index 0 if first found and so on.
+     */
+    int     loc[DOMAIN_COMPONENT_MAX + DN_NAMES_MAX];
+    int     locSz;
+#endif
+};
+
+enum SignatureState {
+    SIG_STATE_BEGIN,
+    SIG_STATE_HASH,
+    SIG_STATE_KEY,
+    SIG_STATE_DO,
+    SIG_STATE_CHECK,
+};
+
+
+#ifdef HAVE_PK_CALLBACKS
+#ifdef HAVE_ECC
+    typedef int (*wc_CallbackEccVerify)(
+           const unsigned char* sig, unsigned int sigSz,
+           const unsigned char* hash, unsigned int hashSz,
+           const unsigned char* keyDer, unsigned int keySz,
+           int* result, void* ctx);
+#endif
+#ifndef NO_RSA
+    typedef int (*wc_CallbackRsaVerify)(
+           unsigned char* sig, unsigned int sigSz,
+           unsigned char** out,
+           const unsigned char* keyDer, unsigned int keySz,
+           void* ctx);
+#endif
+#endif /* HAVE_PK_CALLBACKS */
+
+struct SignatureCtx {
+    void* heap;
+    byte* digest;
+#ifndef NO_RSA
+    byte* out;
+    byte* plain;
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
+    int verify;
+#endif
+    union {
+    #ifndef NO_RSA
+        struct RsaKey*      rsa;
+    #endif
+    #ifdef HAVE_ECC
+        struct ecc_key*     ecc;
+    #endif
+    #ifdef HAVE_ED25519
+        struct ed25519_key* ed25519;
+    #endif
+    #ifdef HAVE_ED448
+        struct ed448_key* ed448;
+    #endif
+        void* ptr;
+    } key;
+    int devId;
+    int state;
+    int typeH;
+    int digestSz;
+    word32 keyOID;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    WC_ASYNC_DEV* asyncDev;
+    void* asyncCtx;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+#ifdef HAVE_ECC
+    wc_CallbackEccVerify pkCbEcc;
+    void* pkCtxEcc;
+#endif
+#ifndef NO_RSA
+    wc_CallbackRsaVerify pkCbRsa;
+    void* pkCtxRsa;
+#endif
+#endif /* HAVE_PK_CALLBACKS */
+#ifndef NO_RSA
+#ifdef WOLFSSL_RENESAS_TSIP_TLS
+    byte verifyByTSIP;
+    word32 certBegin;
+    word32 pubkey_n_start;
+    word32 pubkey_n_len;
+    word32 pubkey_e_start;
+    word32 pubkey_e_len;
+#endif
+#endif
+};
+
+enum CertSignState {
+    CERTSIGN_STATE_BEGIN,
+    CERTSIGN_STATE_DIGEST,
+    CERTSIGN_STATE_ENCODE,
+    CERTSIGN_STATE_DO,
+};
+
+struct CertSignCtx {
+    byte* sig;
+    byte* digest;
+    #ifndef NO_RSA
+        byte* encSig;
+        int encSigSz;
+    #endif
+    int state; /* enum CertSignState */
+};
+
+#ifndef WOLFSSL_MAX_PATH_LEN
+    /* RFC 5280 Section 6.1.2. "Initialization" - item (k) defines
+     *     (k)  max_path_length:  this integer is initialized to "n", is
+     *     decremented for each non-self-issued certificate in the path,
+     *     and may be reduced to the value in the path length constraint
+     *     field within the basic constraints extension of a CA
+     *     certificate.
+     *
+     * wolfSSL has arbitrarily selected the value 127 for "n" in the above
+     * description. Users can modify the maximum path length by setting
+     * WOLFSSL_MAX_PATH_LEN to a preferred value at build time
+     */
+    #define WOLFSSL_MAX_PATH_LEN 127
+#endif
+
+typedef struct DecodedCert DecodedCert;
+typedef struct DecodedName DecodedName;
+typedef struct Signer      Signer;
+#ifdef WOLFSSL_TRUST_PEER_CERT
+typedef struct TrustedPeerCert TrustedPeerCert;
+#endif /* WOLFSSL_TRUST_PEER_CERT */
+typedef struct SignatureCtx SignatureCtx;
+typedef struct CertSignCtx  CertSignCtx;
+
+
+struct DecodedCert {
+    const byte* publicKey;
+    word32  pubKeySize;
+    int     pubKeyStored;
+    word32  certBegin;               /* offset to start of cert          */
+    word32  sigIndex;                /* offset to start of signature     */
+    word32  sigLength;               /* length of signature              */
+    word32  signatureOID;            /* sum of algorithm object id       */
+    word32  keyOID;                  /* sum of key algo  object id       */
+    int     version;                 /* cert version, 1 or 3             */
+    DNS_entry* altNames;             /* alt names list of dns entries    */
+#ifndef IGNORE_NAME_CONSTRAINTS
+    DNS_entry* altEmailNames;        /* alt names list of RFC822 entries */
+    Base_entry* permittedNames;      /* Permitted name bases             */
+    Base_entry* excludedNames;       /* Excluded name bases              */
+#endif /* IGNORE_NAME_CONSTRAINTS */
+    byte    subjectHash[KEYID_SIZE]; /* hash of all Names                */
+    byte    issuerHash[KEYID_SIZE];  /* hash of all Names                */
+#ifdef HAVE_OCSP
+    byte    subjectKeyHash[KEYID_SIZE]; /* hash of the public Key         */
+    byte    issuerKeyHash[KEYID_SIZE]; /* hash of the public Key         */
+#endif /* HAVE_OCSP */
+    const byte* signature;           /* not owned, points into raw cert  */
+    char*   subjectCN;               /* CommonName                       */
+    int     subjectCNLen;            /* CommonName Length                */
+    char    subjectCNEnc;            /* CommonName Encoding              */
+    char    issuer[ASN_NAME_MAX];    /* full name including common name  */
+    char    subject[ASN_NAME_MAX];   /* full name including common name  */
+    int     verify;                  /* Default to yes, but could be off */
+    const byte* source;              /* byte buffer holder cert, NOT owner */
+    word32  srcIdx;                  /* current offset into buffer       */
+    word32  maxIdx;                  /* max offset based on init size    */
+    void*   heap;                    /* for user memory overrides        */
+    byte    serial[EXTERNAL_SERIAL_SIZE];  /* raw serial number          */
+    int     serialSz;                /* raw serial bytes stored */
+    const byte* extensions;          /* not owned, points into raw cert  */
+    int     extensionsSz;            /* length of cert extensions */
+    word32  extensionsIdx;           /* if want to go back and parse later */
+    const byte* extAuthInfo;         /* Authority Information Access URI */
+    int     extAuthInfoSz;           /* length of the URI                */
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+    const byte* extAuthInfoCaIssuer; /* Authority Info Access caIssuer URI */
+    int     extAuthInfoCaIssuerSz;   /* length of the caIssuer URI         */
+#endif
+    const byte* extCrlInfo;          /* CRL Distribution Points          */
+    int     extCrlInfoSz;            /* length of the URI                */
+    byte    extSubjKeyId[KEYID_SIZE]; /* Subject Key ID                  */
+    byte    extAuthKeyId[KEYID_SIZE]; /* Authority Key ID                */
+    byte    pathLength;              /* CA basic constraint path length  */
+    byte    maxPathLen;              /* max_path_len see RFC 5280 section
+                                      * 6.1.2 "Initialization" - (k) for
+                                      * description of max_path_len */
+    word16  extKeyUsage;             /* Key usage bitfield               */
+    byte    extExtKeyUsage;          /* Extended Key usage bitfield      */
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+    const byte* extExtKeyUsageSrc;
+    word32  extExtKeyUsageSz;
+    word32  extExtKeyUsageCount;
+    const byte* extAuthKeyIdSrc;
+    word32  extAuthKeyIdSz;
+    const byte* extSubjKeyIdSrc;
+    word32  extSubjKeyIdSz;
+#endif
+
+#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
+    word32  pkCurveOID;           /* Public Key's curve OID */
+#endif /* HAVE_ECC */
+    const byte* beforeDate;
+    int     beforeDateLen;
+    const byte* afterDate;
+    int     afterDateLen;
+#if defined(HAVE_PKCS7) || defined(WOLFSSL_CERT_EXT)
+    const byte* issuerRaw;           /* pointer to issuer inside source */
+    int     issuerRawLen;
+#endif
+#if !defined(IGNORE_NAME_CONSTRAINTS) || defined(WOLFSSL_CERT_EXT)
+    const byte* subjectRaw;          /* pointer to subject inside source */
+    int     subjectRawLen;
+#endif
+#if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_EXT)
+    /* easy access to subject info for other sign */
+    char*   subjectSN;
+    int     subjectSNLen;
+    char    subjectSNEnc;
+    char*   subjectC;
+    int     subjectCLen;
+    char    subjectCEnc;
+    char*   subjectL;
+    int     subjectLLen;
+    char    subjectLEnc;
+    char*   subjectST;
+    int     subjectSTLen;
+    char    subjectSTEnc;
+    char*   subjectO;
+    int     subjectOLen;
+    char    subjectOEnc;
+    char*   subjectOU;
+    int     subjectOULen;
+    char    subjectOUEnc;
+    char*   subjectSND;
+    int     subjectSNDLen;
+    char    subjectSNDEnc;
+#ifdef WOLFSSL_CERT_EXT
+    char*   subjectBC;
+    int     subjectBCLen;
+    char    subjectBCEnc;
+    char*   subjectJC;
+    int     subjectJCLen;
+    char    subjectJCEnc;
+    char*   subjectJS;
+    int     subjectJSLen;
+    char    subjectJSEnc;
+#endif
+    char*   subjectEmail;
+    int     subjectEmailLen;
+#endif /* WOLFSSL_CERT_GEN */
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+    DecodedName issuerName;
+    DecodedName subjectName;
+#endif /* OPENSSL_EXTRA */
+#ifdef WOLFSSL_SEP
+    int     deviceTypeSz;
+    byte*   deviceType;
+    int     hwTypeSz;
+    byte*   hwType;
+    int     hwSerialNumSz;
+    byte*   hwSerialNum;
+#endif /* WOLFSSL_SEP */
+#ifdef WOLFSSL_CERT_EXT
+    char    extCertPolicies[MAX_CERTPOL_NB][MAX_CERTPOL_SZ];
+    int     extCertPoliciesNb;
+#endif /* defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_EXT) */
+
+    Signer* ca;
+#ifndef NO_CERTS
+    SignatureCtx sigCtx;
+#endif
+#ifdef WOLFSSL_RENESAS_TSIP
+    byte*  tsip_encRsaKeyIdx;
+#endif
+
+    int badDate;
+    int criticalExt;
+
+    /* Option Bits */
+    byte subjectCNStored : 1;      /* have we saved a copy we own */
+    byte extSubjKeyIdSet : 1;      /* Set when the SKID was read from cert */
+    byte extAuthKeyIdSet : 1;      /* Set when the AKID was read from cert */
+#ifndef IGNORE_NAME_CONSTRAINTS
+    byte extNameConstraintSet : 1;
+#endif
+    byte isCA : 1;                 /* CA basic constraint true */
+    byte pathLengthSet : 1;        /* CA basic const path length set */
+    byte weOwnAltNames : 1;        /* altNames haven't been given to copy */
+    byte extKeyUsageSet : 1;
+    byte extExtKeyUsageSet : 1;    /* Extended Key Usage set */
+    byte extCRLdistSet : 1;
+    byte extAuthInfoSet : 1;
+    byte extBasicConstSet : 1;
+    byte extSubjAltNameSet : 1;
+    byte inhibitAnyOidSet : 1;
+    byte selfSigned : 1;           /* Indicates subject and issuer are same */
+#if defined(WOLFSSL_SEP) || defined(WOLFSSL_QT)
+    byte extCertPolicySet : 1;
+#endif
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+    byte extCRLdistCrit : 1;
+    byte extAuthInfoCrit : 1;
+    byte extBasicConstCrit : 1;
+    byte extSubjAltNameCrit : 1;
+    byte extAuthKeyIdCrit : 1;
+    #ifndef IGNORE_NAME_CONSTRAINTS
+        byte extNameConstraintCrit : 1;
+    #endif
+    byte extSubjKeyIdCrit : 1;
+    byte extKeyUsageCrit : 1;
+    byte extExtKeyUsageCrit : 1;
+#endif /* OPENSSL_EXTRA */
+#if defined(WOLFSSL_SEP) || defined(WOLFSSL_QT)
+    byte extCertPolicyCrit : 1;
+#endif
+
+};
+
+
+#ifdef NO_SHA
+    #define SIGNER_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
+#else
+    #define SIGNER_DIGEST_SIZE WC_SHA_DIGEST_SIZE
+#endif
+
+/* CA Signers */
+/* if change layout change PERSIST_CERT_CACHE functions too */
+struct Signer {
+    word32  pubKeySize;
+    word32  keyOID;                  /* key type */
+    word16  keyUsage;
+    byte    maxPathLen;
+    byte    pathLength;
+    byte    pathLengthSet : 1;
+    byte    selfSigned : 1;
+    const byte* publicKey;
+    int     nameLen;
+    char*   name;                    /* common name */
+#ifndef IGNORE_NAME_CONSTRAINTS
+        Base_entry* permittedNames;
+        Base_entry* excludedNames;
+#endif /* IGNORE_NAME_CONSTRAINTS */
+    byte    subjectNameHash[SIGNER_DIGEST_SIZE];
+                                     /* sha hash of names in certificate */
+    #ifndef NO_SKID
+        byte    subjectKeyIdHash[SIGNER_DIGEST_SIZE];
+                                     /* sha hash of names in certificate */
+    #endif
+    #ifdef HAVE_OCSP
+        byte subjectKeyHash[KEYID_SIZE];
+    #endif
+#ifdef WOLFSSL_SIGNER_DER_CERT
+    DerBuffer* derCert;
+#endif
+#ifdef WOLFSSL_RENESAS_TSIP_TLS
+    word32 cm_idx;
+#endif
+    Signer* next;
+};
+
+
+#ifdef WOLFSSL_TRUST_PEER_CERT
+/* used for having trusted peer certs rather then CA */
+struct TrustedPeerCert {
+    int     nameLen;
+    char*   name;                    /* common name */
+    #ifndef IGNORE_NAME_CONSTRAINTS
+        Base_entry* permittedNames;
+        Base_entry* excludedNames;
+    #endif /* IGNORE_NAME_CONSTRAINTS */
+    byte    subjectNameHash[SIGNER_DIGEST_SIZE];
+                                     /* sha hash of names in certificate */
+    #ifndef NO_SKID
+        byte    subjectKeyIdHash[SIGNER_DIGEST_SIZE];
+                                     /* sha hash of names in certificate */
+    #endif
+    word32 sigLen;
+    byte*  sig;
+    struct TrustedPeerCert* next;
+};
+#endif /* WOLFSSL_TRUST_PEER_CERT */
+
+
+/* for testing or custom openssl wrappers */
+#if defined(WOLFSSL_TEST_CERT) || defined(OPENSSL_EXTRA) || \
+    defined(OPENSSL_EXTRA_X509_SMALL)
+    #define WOLFSSL_ASN_API WOLFSSL_API
+#else
+    #define WOLFSSL_ASN_API WOLFSSL_LOCAL
+#endif
+
+WOLFSSL_LOCAL int CalcHashId(const byte* data, word32 len, byte* hash);
+
+WOLFSSL_ASN_API int wc_BerToDer(const byte* ber, word32 berSz, byte* der,
+                                word32* derSz);
+
+WOLFSSL_ASN_API void FreeAltNames(DNS_entry*, void*);
+#ifndef IGNORE_NAME_CONSTRAINTS
+    WOLFSSL_ASN_API void FreeNameSubtrees(Base_entry*, void*);
+#endif /* IGNORE_NAME_CONSTRAINTS */
+WOLFSSL_ASN_API void InitDecodedCert(DecodedCert*, const byte*, word32, void*);
+WOLFSSL_ASN_API void FreeDecodedCert(DecodedCert*);
+WOLFSSL_ASN_API int  ParseCert(DecodedCert*, int type, int verify, void* cm);
+
+WOLFSSL_LOCAL int DecodePolicyOID(char *o, word32 oSz,
+                                  const byte *in, word32 inSz);
+WOLFSSL_LOCAL int EncodePolicyOID(byte *out, word32 *outSz,
+                                  const char *in, void* heap);
+WOLFSSL_API int CheckCertSignature(const byte*,word32,void*,void* cm);
+WOLFSSL_LOCAL int CheckCertSignaturePubKey(const byte* cert, word32 certSz,
+        void* heap, const byte* pubKey, word32 pubKeySz, int pubKeyOID);
+WOLFSSL_LOCAL int ParseCertRelative(DecodedCert*,int type,int verify,void* cm);
+WOLFSSL_LOCAL int DecodeToKey(DecodedCert*, int verify);
+WOLFSSL_LOCAL int wc_GetPubX509(DecodedCert* cert, int verify, int* badDate);
+
+WOLFSSL_LOCAL const byte* OidFromId(word32 id, word32 type, word32* oidSz);
+WOLFSSL_LOCAL Signer* MakeSigner(void*);
+WOLFSSL_LOCAL void    FreeSigner(Signer*, void*);
+WOLFSSL_LOCAL void    FreeSignerTable(Signer**, int, void*);
+#ifdef WOLFSSL_TRUST_PEER_CERT
+WOLFSSL_LOCAL void    FreeTrustedPeer(TrustedPeerCert*, void*);
+WOLFSSL_LOCAL void    FreeTrustedPeerTable(TrustedPeerCert**, int, void*);
+#endif /* WOLFSSL_TRUST_PEER_CERT */
+
+WOLFSSL_ASN_API int ToTraditional(byte* buffer, word32 length);
+WOLFSSL_ASN_API int ToTraditional_ex(byte* buffer, word32 length,
+                                     word32* algId);
+WOLFSSL_LOCAL int ToTraditionalInline(const byte* input, word32* inOutIdx,
+                                      word32 length);
+WOLFSSL_LOCAL int ToTraditionalInline_ex(const byte* input, word32* inOutIdx,
+                                         word32 length, word32* algId);
+WOLFSSL_LOCAL int ToTraditionalEnc(byte* buffer, word32 length,const char*,int,
+                                   word32* algId);
+WOLFSSL_ASN_API int UnTraditionalEnc(byte* key, word32 keySz, byte* out,
+        word32* outSz, const char* password, int passwordSz, int vPKCS,
+        int vAlgo, byte* salt, word32 saltSz, int itt, WC_RNG* rng, void* heap);
+WOLFSSL_ASN_API int TraditionalEnc(byte* key, word32 keySz, byte* out,
+        word32* outSz, const char* password, int passwordSz, int vPKCS,
+        int vAlgo, int encAlgId, byte* salt, word32 saltSz, int itt,
+        WC_RNG* rng, void* heap);
+WOLFSSL_LOCAL int DecryptContent(byte* input, word32 sz,const char* psw,int pswSz);
+WOLFSSL_LOCAL int EncryptContent(byte* input, word32 sz, byte* out, word32* outSz,
+        const char* password,int passwordSz, int vPKCS, int vAlgo,
+        byte* salt, word32 saltSz, int itt, WC_RNG* rng, void* heap);
+WOLFSSL_LOCAL int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID,
+        word32* oidSz, int* algoID, void* heap);
+
+typedef struct tm wolfssl_tm;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_EXTRA) || \
+    defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+WOLFSSL_LOCAL int GetTimeString(byte* date, int format, char* buf, int len);
+#endif
+#if !defined(NO_ASN_TIME) && defined(HAVE_PKCS7)
+WOLFSSL_LOCAL int GetAsnTimeString(void* currTime, byte* buf, word32 len);
+#endif
+WOLFSSL_LOCAL int ExtractDate(const unsigned char* date, unsigned char format,
+                                                 wolfssl_tm* certTime, int* idx);
+WOLFSSL_LOCAL int DateGreaterThan(const struct tm* a, const struct tm* b);
+WOLFSSL_LOCAL int ValidateDate(const byte* date, byte format, int dateType);
+WOLFSSL_LOCAL int wc_OBJ_sn2nid(const char *sn);
+
+/* ASN.1 helper functions */
+#ifdef WOLFSSL_CERT_GEN
+WOLFSSL_ASN_API int SetName(byte* output, word32 outputSz, CertName* name);
+#endif
+WOLFSSL_LOCAL int GetShortInt(const byte* input, word32* inOutIdx, int* number,
+                              word32 maxIdx);
+WOLFSSL_LOCAL int SetShortInt(byte* input, word32* inOutIdx, word32 number,
+                              word32 maxIdx);
+
+WOLFSSL_LOCAL const char* GetSigName(int oid);
+WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len,
+                           word32 maxIdx);
+WOLFSSL_LOCAL int GetLength_ex(const byte* input, word32* inOutIdx, int* len,
+                           word32 maxIdx, int check);
+WOLFSSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len,
+                             word32 maxIdx);
+WOLFSSL_LOCAL int GetSequence_ex(const byte* input, word32* inOutIdx, int* len,
+                           word32 maxIdx, int check);
+WOLFSSL_LOCAL int GetOctetString(const byte* input, word32* inOutIdx, int* len,
+                         word32 maxIdx);
+WOLFSSL_LOCAL int GetSet(const byte* input, word32* inOutIdx, int* len,
+                        word32 maxIdx);
+WOLFSSL_LOCAL int GetSet_ex(const byte* input, word32* inOutIdx, int* len,
+                        word32 maxIdx, int check);
+WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx,
+                              int* version, word32 maxIdx);
+WOLFSSL_LOCAL int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx,
+                        word32 maxIdx);
+#ifdef HAVE_OID_ENCODING
+    WOLFSSL_LOCAL int EncodeObjectId(const word16* in, word32 inSz,
+        byte* out, word32* outSz);
+#endif
+#ifdef HAVE_OID_DECODING
+    WOLFSSL_LOCAL int DecodeObjectId(const byte* in, word32 inSz,
+        word16* out, word32* outSz);
+#endif
+WOLFSSL_LOCAL int GetASNObjectId(const byte* input, word32* inOutIdx, int* len,
+                                 word32 maxIdx);
+WOLFSSL_LOCAL int SetObjectId(int len, byte* output);
+WOLFSSL_LOCAL int GetObjectId(const byte* input, word32* inOutIdx, word32* oid,
+                              word32 oidType, word32 maxIdx);
+WOLFSSL_LOCAL int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid,
+                           word32 oidType, word32 maxIdx);
+WOLFSSL_LOCAL int GetASNTag(const byte* input, word32* idx, byte* tag,
+                            word32 inputSz);
+WOLFSSL_LOCAL word32 SetLength(word32 length, byte* output);
+WOLFSSL_LOCAL word32 SetSequence(word32 len, byte* output);
+WOLFSSL_LOCAL word32 SetOctetString(word32 len, byte* output);
+#if (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) && !defined(NO_DH) \
+    || defined(WOLFSSL_OPENSSH)
+WOLFSSL_LOCAL int wc_DhParamsToDer(DhKey* key, byte* out, word32* outSz);
+WOLFSSL_LOCAL int wc_DhPubKeyToDer(DhKey* key, byte* out, word32* outSz);
+WOLFSSL_LOCAL int wc_DhPrivKeyToDer(DhKey* key, byte* out, word32* outSz);
+#endif
+WOLFSSL_LOCAL word32 SetBitString(word32 len, byte unusedBits, byte* output);
+WOLFSSL_LOCAL word32 SetImplicit(byte tag,byte number,word32 len,byte* output);
+WOLFSSL_LOCAL word32 SetExplicit(byte number, word32 len, byte* output);
+WOLFSSL_LOCAL word32 SetSet(word32 len, byte* output);
+WOLFSSL_LOCAL word32 SetAlgoID(int algoOID,byte* output,int type,int curveSz);
+WOLFSSL_LOCAL int SetMyVersion(word32 version, byte* output, int header);
+WOLFSSL_LOCAL int SetSerialNumber(const byte* sn, word32 snSz, byte* output,
+    word32 outputSz, int maxSnSz);
+WOLFSSL_LOCAL int GetSerialNumber(const byte* input, word32* inOutIdx,
+    byte* serial, int* serialSz, word32 maxIdx);
+WOLFSSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash,
+                             int maxIdx);
+WOLFSSL_LOCAL int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der);
+WOLFSSL_LOCAL int StoreDHparams(byte* out, word32* outLen, mp_int* p, mp_int* g);
+WOLFSSL_LOCAL int FlattenAltNames( byte*, word32, const DNS_entry*);
+
+#ifdef HAVE_ECC
+    /* ASN sig helpers */
+    WOLFSSL_LOCAL int StoreECC_DSA_Sig(byte* out, word32* outLen, mp_int* r,
+                                      mp_int* s);
+    WOLFSSL_LOCAL int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen,
+                                       mp_int* r, mp_int* s);
+#endif
+#if defined HAVE_ECC && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
+WOLFSSL_API int EccEnumToNID(int n);
+#endif
+
+WOLFSSL_LOCAL void InitSignatureCtx(SignatureCtx* sigCtx, void* heap, int devId);
+WOLFSSL_LOCAL void FreeSignatureCtx(SignatureCtx* sigCtx);
+
+#ifndef NO_CERTS
+
+WOLFSSL_LOCAL int wc_EncryptedInfoParse(EncryptedInfo* info, char** pBuffer,
+                                        size_t bufSz);
+
+WOLFSSL_LOCAL int PemToDer(const unsigned char* buff, long sz, int type,
+                          DerBuffer** pDer, void* heap, EncryptedInfo* info,
+                          int* eccKey);
+WOLFSSL_LOCAL int AllocDer(DerBuffer** der, word32 length, int type, void* heap);
+WOLFSSL_LOCAL void FreeDer(DerBuffer** der);
+
+#endif /* !NO_CERTS */
+
+#ifdef WOLFSSL_CERT_GEN
+
+enum cert_enums {
+#ifdef WOLFSSL_CERT_EXT
+    NAME_ENTRIES    =  10,
+#else
+    NAME_ENTRIES    =  9,
+#endif
+    JOINT_LEN       =  2,
+    EMAIL_JOINT_LEN =  9,
+    PILOT_JOINT_LEN =  10,
+    RSA_KEY         = 10,
+    NTRU_KEY        = 11,
+    ECC_KEY         = 12,
+    ED25519_KEY     = 13,
+    ED448_KEY       = 14
+};
+
+#endif /* WOLFSSL_CERT_GEN */
+
+
+
+/* for pointer use */
+typedef struct CertStatus CertStatus;
+
+#ifdef HAVE_OCSP
+
+enum Ocsp_Response_Status {
+    OCSP_SUCCESSFUL        = 0, /* Response has valid confirmations */
+    OCSP_MALFORMED_REQUEST = 1, /* Illegal confirmation request */
+    OCSP_INTERNAL_ERROR    = 2, /* Internal error in issuer */
+    OCSP_TRY_LATER         = 3, /* Try again later */
+    OCSP_SIG_REQUIRED      = 5, /* Must sign the request (4 is skipped) */
+    OCSP_UNAUTHROIZED      = 6  /* Request unauthorized */
+};
+
+
+enum Ocsp_Cert_Status {
+    CERT_GOOD    = 0,
+    CERT_REVOKED = 1,
+    CERT_UNKNOWN = 2
+};
+
+
+enum Ocsp_Sums {
+    OCSP_BASIC_OID = 117,
+    OCSP_NONCE_OID = 118
+};
+
+#ifdef OPENSSL_EXTRA
+enum Ocsp_Verify_Error {
+    OCSP_VERIFY_ERROR_NONE = 0,
+    OCSP_BAD_ISSUER = 1
+};
+#endif
+
+
+typedef struct OcspRequest  OcspRequest;
+typedef struct OcspResponse OcspResponse;
+
+
+struct CertStatus {
+    CertStatus* next;
+
+    byte serial[EXTERNAL_SERIAL_SIZE];
+    int serialSz;
+
+    int status;
+
+    byte thisDate[MAX_DATE_SIZE];
+    byte nextDate[MAX_DATE_SIZE];
+    byte thisDateFormat;
+    byte nextDateFormat;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+    WOLFSSL_ASN1_TIME thisDateParsed;
+    WOLFSSL_ASN1_TIME nextDateParsed;
+    byte* thisDateAsn;
+    byte* nextDateAsn;
+#endif
+
+    byte*  rawOcspResponse;
+    word32 rawOcspResponseSz;
+};
+
+
+struct OcspResponse {
+    int     responseStatus;  /* return code from Responder */
+
+    byte*   response;        /* Pointer to beginning of OCSP Response */
+    word32  responseSz;      /* length of the OCSP Response */
+
+    byte    producedDate[MAX_DATE_SIZE];
+                             /* Date at which this response was signed */
+    byte    producedDateFormat; /* format of the producedDate */
+    byte*   issuerHash;
+    byte*   issuerKeyHash;
+
+    byte*   cert;
+    word32  certSz;
+
+    byte*   sig;             /* Pointer to sig in source */
+    word32  sigSz;           /* Length in octets for the sig */
+    word32  sigOID;          /* OID for hash used for sig */
+
+    CertStatus* status;      /* certificate status to fill out */
+
+    byte*   nonce;           /* pointer to nonce inside ASN.1 response */
+    int     nonceSz;         /* length of the nonce string */
+
+    byte*   source;          /* pointer to source buffer, not owned */
+    word32  maxIdx;          /* max offset based on init size */
+
+#ifdef OPENSSL_EXTRA
+    int     verifyError;
+#endif
+};
+
+
+struct OcspRequest {
+    byte   issuerHash[KEYID_SIZE];
+    byte   issuerKeyHash[KEYID_SIZE];
+    byte*  serial;   /* copy of the serial number in source cert */
+    int    serialSz;
+#ifdef OPENSSL_EXTRA
+    WOLFSSL_ASN1_INTEGER* serialInt;
+#endif
+    byte*  url;      /* copy of the extAuthInfo in source cert */
+    int    urlSz;
+
+    byte   nonce[MAX_OCSP_NONCE_SZ];
+    int    nonceSz;
+    void*  heap;
+    void*  ssl;
+};
+
+typedef struct OcspEntry OcspEntry;
+
+#ifdef NO_SHA
+#define OCSP_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
+#else
+#define OCSP_DIGEST_SIZE WC_SHA_DIGEST_SIZE
+#endif
+
+struct OcspEntry
+{
+    OcspEntry *next;                      /* next entry             */
+    byte issuerHash[OCSP_DIGEST_SIZE];    /* issuer hash            */
+    byte issuerKeyHash[OCSP_DIGEST_SIZE]; /* issuer public key hash */
+    CertStatus *status;                   /* OCSP response list     */
+    int totalStatus;                      /* number on list         */
+};
+
+WOLFSSL_LOCAL void InitOcspResponse(OcspResponse*, CertStatus*, byte*, word32);
+WOLFSSL_LOCAL int  OcspResponseDecode(OcspResponse*, void*, void* heap, int);
+
+WOLFSSL_LOCAL int    InitOcspRequest(OcspRequest*, DecodedCert*, byte, void*);
+WOLFSSL_LOCAL void   FreeOcspRequest(OcspRequest*);
+WOLFSSL_LOCAL int    EncodeOcspRequest(OcspRequest*, byte*, word32);
+WOLFSSL_LOCAL word32 EncodeOcspRequestExtensions(OcspRequest*, byte*, word32);
+
+
+WOLFSSL_LOCAL int  CompareOcspReqResp(OcspRequest*, OcspResponse*);
+
+
+#endif /* HAVE_OCSP */
+
+
+/* for pointer use */
+typedef struct RevokedCert RevokedCert;
+
+#ifdef HAVE_CRL
+
+struct RevokedCert {
+    byte         serialNumber[EXTERNAL_SERIAL_SIZE];
+    int          serialSz;
+    RevokedCert* next;
+};
+
+typedef struct DecodedCRL DecodedCRL;
+
+struct DecodedCRL {
+    word32  certBegin;               /* offset to start of cert          */
+    word32  sigIndex;                /* offset to start of signature     */
+    word32  sigLength;               /* length of signature              */
+    word32  signatureOID;            /* sum of algorithm object id       */
+    byte*   signature;               /* pointer into raw source, not owned */
+    byte    issuerHash[SIGNER_DIGEST_SIZE]; /* issuer name hash          */
+    byte    crlHash[SIGNER_DIGEST_SIZE]; /* raw crl data hash            */
+    byte    lastDate[MAX_DATE_SIZE]; /* last date updated  */
+    byte    nextDate[MAX_DATE_SIZE]; /* next update date   */
+    byte    lastDateFormat;          /* format of last date */
+    byte    nextDateFormat;          /* format of next date */
+    RevokedCert* certs;              /* revoked cert list  */
+    int          totalCerts;         /* number on list     */
+    void*   heap;
+#ifndef NO_SKID
+    byte    extAuthKeyIdSet;
+    byte    extAuthKeyId[SIGNER_DIGEST_SIZE]; /* Authority Key ID        */
+#endif
+};
+
+WOLFSSL_LOCAL void InitDecodedCRL(DecodedCRL*, void* heap);
+WOLFSSL_LOCAL int VerifyCRL_Signature(SignatureCtx* sigCtx,
+                                      const byte* toBeSigned, word32 tbsSz,
+                                      const byte* signature, word32 sigSz,
+                                      word32 signatureOID, Signer *ca,
+                                      void* heap);
+WOLFSSL_LOCAL int  ParseCRL(DecodedCRL*, const byte* buff, word32 sz, void* cm);
+WOLFSSL_LOCAL void FreeDecodedCRL(DecodedCRL*);
+
+
+#endif /* HAVE_CRL */
+
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* !NO_ASN */
+
+
+#if !defined(NO_ASN) || !defined(NO_PWDBASED)
+
+#ifndef MAX_KEY_SIZE
+    #define MAX_KEY_SIZE    64  /* MAX PKCS Key length */
+#endif
+#ifndef MAX_UNICODE_SZ
+    #define MAX_UNICODE_SZ  256
+#endif
+
+enum PBESTypes {
+    PBE_MD5_DES      = 0,
+    PBE_SHA1_RC4_128 = 1,
+    PBE_SHA1_DES     = 2,
+    PBE_SHA1_DES3    = 3,
+    PBE_AES256_CBC   = 4,
+    PBE_AES128_CBC   = 5,
+
+    PBE_SHA1_RC4_128_SUM = 657,
+    PBE_SHA1_DES3_SUM    = 659,
+    PBES2            = 13       /* algo ID */
+};
+
+enum PKCSTypes {
+    PKCS5v2             =   6,     /* PKCS #5 v2.0 */
+    PKCS12v1            =  12,     /* PKCS #12 */
+    PKCS5               =   5,     /* PKCS oid tag */
+    PKCS8v0             =   0,     /* default PKCS#8 version */
+};
+
+#endif /* !NO_ASN || !NO_PWDBASED */
+
+#endif /* WOLF_CRYPT_ASN_H */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/asn_public.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/asn_public.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/asn_public.h	(revision 453)
@@ -0,0 +1,610 @@
+/* asn_public.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/asn_public.h
+*/
+
+#ifndef WOLF_CRYPT_ASN_PUBLIC_H
+#define WOLF_CRYPT_ASN_PUBLIC_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+/* guard on redeclaration */
+#ifndef WC_ECCKEY_TYPE_DEFINED
+    typedef struct ecc_key ecc_key;
+    #define WC_ECCKEY_TYPE_DEFINED
+#endif
+#ifndef WC_ED25519KEY_TYPE_DEFINED
+    typedef struct ed25519_key ed25519_key;
+    #define WC_ED25519KEY_TYPE_DEFINED
+#endif
+#ifndef WC_ED448KEY_TYPE_DEFINED
+    typedef struct ed448_key ed448_key;
+    #define WC_ED448KEY_TYPE_DEFINED
+#endif
+#ifndef WC_RSAKEY_TYPE_DEFINED
+    typedef struct RsaKey RsaKey;
+    #define WC_RSAKEY_TYPE_DEFINED
+#endif
+#ifndef WC_RNG_TYPE_DEFINED
+    typedef struct WC_RNG WC_RNG;
+    #define WC_RNG_TYPE_DEFINED
+#endif
+
+enum Ecc_Sum {
+    ECC_SECP112R1_OID = 182,
+    ECC_SECP112R2_OID = 183,
+    ECC_SECP128R1_OID = 204,
+    ECC_SECP128R2_OID = 205,
+    ECC_SECP160R1_OID = 184,
+    ECC_SECP160R2_OID = 206,
+    ECC_SECP160K1_OID = 185,
+    ECC_BRAINPOOLP160R1_OID = 98,
+    ECC_SECP192R1_OID = 520,
+    ECC_PRIME192V2_OID = 521,
+    ECC_PRIME192V3_OID = 522,
+    ECC_SECP192K1_OID = 207,
+    ECC_BRAINPOOLP192R1_OID = 100,
+    ECC_SECP224R1_OID = 209,
+    ECC_SECP224K1_OID = 208,
+    ECC_BRAINPOOLP224R1_OID = 102,
+    ECC_PRIME239V1_OID = 523,
+    ECC_PRIME239V2_OID = 524,
+    ECC_PRIME239V3_OID = 525,
+    ECC_SECP256R1_OID = 526,
+    ECC_SECP256K1_OID = 186,
+    ECC_BRAINPOOLP256R1_OID = 104,
+    ECC_X25519_OID = 365,
+    ECC_ED25519_OID = 256,
+    ECC_BRAINPOOLP320R1_OID = 106,
+    ECC_X448_OID = 362,
+    ECC_ED448_OID = 257,
+    ECC_SECP384R1_OID = 210,
+    ECC_BRAINPOOLP384R1_OID = 108,
+    ECC_BRAINPOOLP512R1_OID = 110,
+    ECC_SECP521R1_OID = 211,
+};
+
+
+/* Certificate file Type */
+enum CertType {
+    CERT_TYPE       = 0,
+    PRIVATEKEY_TYPE,
+    DH_PARAM_TYPE,
+    DSA_PARAM_TYPE,
+    CRL_TYPE,
+    CA_TYPE,
+    ECC_PRIVATEKEY_TYPE,
+    DSA_PRIVATEKEY_TYPE,
+    CERTREQ_TYPE,
+    DSA_TYPE,
+    ECC_TYPE,
+    RSA_TYPE,
+    PUBLICKEY_TYPE,
+    RSA_PUBLICKEY_TYPE,
+    ECC_PUBLICKEY_TYPE,
+    TRUSTED_PEER_TYPE,
+    EDDSA_PRIVATEKEY_TYPE,
+    ED25519_TYPE,
+    ED448_TYPE,
+    PKCS12_TYPE,
+    PKCS8_PRIVATEKEY_TYPE,
+    PKCS8_ENC_PRIVATEKEY_TYPE,
+    DETECT_CERT_TYPE,
+    DH_PRIVATEKEY_TYPE,
+};
+
+
+/* Signature type, by OID sum */
+enum Ctc_SigType {
+    CTC_SHAwDSA      = 517,
+    CTC_MD2wRSA      = 646,
+    CTC_MD5wRSA      = 648,
+    CTC_SHAwRSA      = 649,
+    CTC_SHAwECDSA    = 520,
+    CTC_SHA224wRSA   = 658,
+    CTC_SHA224wECDSA = 523,
+    CTC_SHA256wRSA   = 655,
+    CTC_SHA256wECDSA = 524,
+    CTC_SHA384wRSA   = 656,
+    CTC_SHA384wECDSA = 525,
+    CTC_SHA512wRSA   = 657,
+    CTC_SHA512wECDSA = 526,
+    CTC_ED25519      = 256,
+    CTC_ED448        = 257
+};
+
+enum Ctc_Encoding {
+    CTC_UTF8       = 0x0c, /* utf8      */
+    CTC_PRINTABLE  = 0x13  /* printable */
+};
+
+#ifndef WC_CTC_NAME_SIZE
+    #define WC_CTC_NAME_SIZE 64
+#endif
+#ifndef WC_CTC_MAX_ALT_SIZE
+    #define WC_CTC_MAX_ALT_SIZE 16384
+#endif
+
+enum Ctc_Misc {
+    CTC_COUNTRY_SIZE  =     2,
+    CTC_NAME_SIZE     = WC_CTC_NAME_SIZE,
+    CTC_DATE_SIZE     =    32,
+    CTC_MAX_ALT_SIZE  = WC_CTC_MAX_ALT_SIZE, /* may be huge, default: 16384 */
+    CTC_SERIAL_SIZE   =    20,
+    CTC_GEN_SERIAL_SZ =    16,
+#ifdef WOLFSSL_CERT_EXT
+    /* AKID could contains: hash + (Option) AuthCertIssuer,AuthCertSerialNum
+     * We support only hash */
+    CTC_MAX_SKID_SIZE = 32, /* SHA256_DIGEST_SIZE */
+    CTC_MAX_AKID_SIZE = 32, /* SHA256_DIGEST_SIZE */
+    CTC_MAX_CERTPOL_SZ = 64,
+    CTC_MAX_CERTPOL_NB = 2 /* Max number of Certificate Policy */
+#endif /* WOLFSSL_CERT_EXT */
+};
+
+/* DER buffer */
+typedef struct DerBuffer {
+    byte*  buffer;
+    void*  heap;
+    word32 length;
+    int    type;    /* enum CertType */
+    int    dynType; /* DYNAMIC_TYPE_* */
+} DerBuffer;
+
+typedef struct WOLFSSL_ASN1_TIME {
+    unsigned char data[CTC_DATE_SIZE]; /* date bytes */
+    int length;
+    int type;
+} WOLFSSL_ASN1_TIME;
+
+enum {
+    IV_SZ   = 32,                   /* max iv sz */
+    NAME_SZ = 80,                   /* max one line */
+
+    PEM_PASS_READ  = 0,
+    PEM_PASS_WRITE = 1,
+};
+
+
+typedef int (pem_password_cb)(char* passwd, int sz, int rw, void* userdata);
+
+typedef struct EncryptedInfo {
+    pem_password_cb* passwd_cb;
+    void*            passwd_userdata;
+
+    long     consumed;         /* tracks PEM bytes consumed */
+
+    int      cipherType;
+    word32   keySz;
+    word32   ivSz;             /* salt or encrypted IV size */
+
+    char     name[NAME_SZ];    /* cipher name, such as "DES-CBC" */
+    byte     iv[IV_SZ];        /* salt or encrypted IV */
+
+    word16   set:1;            /* if encryption set */
+} EncryptedInfo;
+
+
+#define WOLFSSL_ASN1_INTEGER_MAX 20
+typedef struct WOLFSSL_ASN1_INTEGER {
+    /* size can be increased set at 20 for tag, length then to hold at least 16
+     * byte type */
+    unsigned char  intData[WOLFSSL_ASN1_INTEGER_MAX];
+    /* ASN_INTEGER | LENGTH | hex of number */
+    unsigned char  negative;   /* negative number flag */
+
+    unsigned char* data;
+    unsigned int   dataMax;   /* max size of data buffer */
+    unsigned int   isDynamic:1; /* flag for if data pointer dynamic (1 is yes 0 is no) */
+
+    int length;
+    int type;
+} WOLFSSL_ASN1_INTEGER;
+
+
+#if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_EXT)
+#ifdef WOLFSSL_EKU_OID
+    #ifndef CTC_MAX_EKU_NB
+        #define CTC_MAX_EKU_NB 1
+    #endif
+    #ifndef CTC_MAX_EKU_OID_SZ
+        #define CTC_MAX_EKU_OID_SZ 30
+    #endif
+#else
+    #undef CTC_MAX_EKU_OID_SZ
+    #define CTC_MAX_EKU_OID_SZ 0
+#endif
+#endif /* WOLFSSL_CERT_GEN || WOLFSSL_CERT_EXT */
+
+#ifdef WOLFSSL_CERT_GEN
+
+#ifdef WOLFSSL_MULTI_ATTRIB
+#ifndef CTC_MAX_ATTRIB
+    #define CTC_MAX_ATTRIB 4
+#endif
+
+/* ASN Encoded Name field */
+typedef struct NameAttrib {
+    int  sz;                     /* actual string value length */
+    int  id;                     /* id of name */
+    int  type;                   /* enc of name */
+    char value[CTC_NAME_SIZE];   /* name */
+} NameAttrib;
+#endif /* WOLFSSL_MULTI_ATTRIB */
+
+
+typedef struct CertName {
+    char country[CTC_NAME_SIZE];
+    char countryEnc;
+    char state[CTC_NAME_SIZE];
+    char stateEnc;
+    char locality[CTC_NAME_SIZE];
+    char localityEnc;
+    char sur[CTC_NAME_SIZE];
+    char surEnc;
+    char org[CTC_NAME_SIZE];
+    char orgEnc;
+    char unit[CTC_NAME_SIZE];
+    char unitEnc;
+    char commonName[CTC_NAME_SIZE];
+    char commonNameEnc;
+    char serialDev[CTC_NAME_SIZE];
+    char serialDevEnc;
+#ifdef WOLFSSL_CERT_EXT
+    char busCat[CTC_NAME_SIZE];
+    char busCatEnc;
+    char joiC[CTC_NAME_SIZE];
+    char joiCEnc;
+    char joiSt[CTC_NAME_SIZE];
+    char joiStEnc;
+#endif
+    char email[CTC_NAME_SIZE];  /* !!!! email has to be last !!!! */
+#ifdef WOLFSSL_MULTI_ATTRIB
+    NameAttrib name[CTC_MAX_ATTRIB];
+#endif
+} CertName;
+
+
+/* for user to fill for certificate generation */
+typedef struct Cert {
+    int      version;                   /* x509 version  */
+    byte     serial[CTC_SERIAL_SIZE];   /* serial number */
+    int      serialSz;                  /* serial size */
+    int      sigType;                   /* signature algo type */
+    CertName issuer;                    /* issuer info */
+    int      daysValid;                 /* validity days */
+    int      selfSigned;                /* self signed flag */
+    CertName subject;                   /* subject info */
+    int      isCA;                      /* is this going to be a CA */
+    /* internal use only */
+    int      bodySz;                    /* pre sign total size */
+    int      keyType;                   /* public key type of subject */
+#ifdef WOLFSSL_ALT_NAMES
+    byte     altNames[CTC_MAX_ALT_SIZE]; /* altNames copy */
+    int      altNamesSz;                 /* altNames size in bytes */
+    byte     beforeDate[CTC_DATE_SIZE];  /* before date copy */
+    int      beforeDateSz;               /* size of copy */
+    byte     afterDate[CTC_DATE_SIZE];   /* after date copy */
+    int      afterDateSz;                /* size of copy */
+#endif
+#ifdef WOLFSSL_CERT_EXT
+    byte    skid[CTC_MAX_SKID_SIZE];     /* Subject Key Identifier */
+    int     skidSz;                      /* SKID size in bytes */
+    byte    akid[CTC_MAX_AKID_SIZE];     /* Authority Key Identifier */
+    int     akidSz;                      /* AKID size in bytes */
+    word16  keyUsage;                    /* Key Usage */
+    byte    extKeyUsage;                 /* Extended Key Usage */
+#ifdef WOLFSSL_EKU_OID
+    /* Extended Key Usage OIDs */
+    byte    extKeyUsageOID[CTC_MAX_EKU_NB][CTC_MAX_EKU_OID_SZ];
+    byte    extKeyUsageOIDSz[CTC_MAX_EKU_NB];
+#endif
+    char    certPolicies[CTC_MAX_CERTPOL_NB][CTC_MAX_CERTPOL_SZ];
+    word16  certPoliciesNb;              /* Number of Cert Policy */
+    byte     issRaw[sizeof(CertName)];   /* raw issuer info */
+    byte     sbjRaw[sizeof(CertName)];   /* raw subject info */
+#endif
+#ifdef WOLFSSL_CERT_REQ
+    char     challengePw[CTC_NAME_SIZE];
+    int      challengePwPrintableString; /* encode as PrintableString */
+#endif
+    void*   decodedCert;    /* internal DecodedCert allocated from heap */
+    byte*   der;            /* Pointer to buffer of current DecodedCert cache */
+    void*   heap;           /* heap hint */
+} Cert;
+
+
+/* Initialize and Set Certificate defaults:
+   version    = 3 (0x2)
+   serial     = 0 (Will be randomly generated)
+   sigType    = SHA_WITH_RSA
+   issuer     = blank
+   daysValid  = 500
+   selfSigned = 1 (true) use subject as issuer
+   subject    = blank
+   isCA       = 0 (false)
+   keyType    = RSA_KEY (default)
+*/
+WOLFSSL_API int wc_InitCert(Cert*);
+WOLFSSL_API int wc_MakeCert_ex(Cert* cert, byte* derBuffer, word32 derSz,
+                                int keyType, void* key, WC_RNG* rng);
+WOLFSSL_API int wc_MakeCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*,
+                             ecc_key*, WC_RNG*);
+#ifdef WOLFSSL_CERT_REQ
+    WOLFSSL_API int wc_MakeCertReq_ex(Cert*, byte* derBuffer, word32 derSz,
+                                       int, void*);
+    WOLFSSL_API int wc_MakeCertReq(Cert*, byte* derBuffer, word32 derSz,
+                                    RsaKey*, ecc_key*);
+#endif
+WOLFSSL_API int wc_SignCert_ex(int requestSz, int sType, byte* buffer,
+                                word32 buffSz, int keyType, void* key,
+                                WC_RNG* rng);
+WOLFSSL_API int wc_SignCert(int requestSz, int sigType, byte* derBuffer,
+                             word32 derSz, RsaKey*, ecc_key*, WC_RNG*);
+WOLFSSL_API int wc_MakeSelfCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*,
+                             WC_RNG*);
+WOLFSSL_API int wc_SetIssuer(Cert*, const char*);
+WOLFSSL_API int wc_SetSubject(Cert*, const char*);
+#ifdef WOLFSSL_ALT_NAMES
+    WOLFSSL_API int wc_SetAltNames(Cert*, const char*);
+#endif
+
+#ifdef WOLFSSL_CERT_GEN_CACHE
+WOLFSSL_API void wc_SetCert_Free(Cert* cert);
+#endif
+
+WOLFSSL_API int wc_SetIssuerBuffer(Cert*, const byte*, int);
+WOLFSSL_API int wc_SetSubjectBuffer(Cert*, const byte*, int);
+WOLFSSL_API int wc_SetAltNamesBuffer(Cert*, const byte*, int);
+WOLFSSL_API int wc_SetDatesBuffer(Cert*, const byte*, int);
+
+#ifndef NO_ASN_TIME
+WOLFSSL_API int wc_GetCertDates(Cert* cert, struct tm* before,
+    struct tm* after);
+#endif
+
+#ifdef WOLFSSL_CERT_EXT
+WOLFSSL_API int wc_SetAuthKeyIdFromPublicKey_ex(Cert *cert, int keyType,
+                                                void* key);
+WOLFSSL_API int wc_SetAuthKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey,
+                                             ecc_key *eckey);
+WOLFSSL_API int wc_SetAuthKeyIdFromCert(Cert *cert, const byte *der, int derSz);
+WOLFSSL_API int wc_SetAuthKeyId(Cert *cert, const char* file);
+WOLFSSL_API int wc_SetSubjectKeyIdFromPublicKey_ex(Cert *cert, int keyType,
+                                                   void* key);
+WOLFSSL_API int wc_SetSubjectKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey,
+                                                ecc_key *eckey);
+WOLFSSL_API int wc_SetSubjectKeyId(Cert *cert, const char* file);
+WOLFSSL_API int wc_GetSubjectRaw(byte **subjectRaw, Cert *cert);
+WOLFSSL_API int wc_SetSubjectRaw(Cert* cert, const byte* der, int derSz);
+WOLFSSL_API int wc_SetIssuerRaw(Cert* cert, const byte* der, int derSz);
+
+#ifdef HAVE_NTRU
+WOLFSSL_API int wc_SetSubjectKeyIdFromNtruPublicKey(Cert *cert, byte *ntruKey,
+                                                    word16 ntruKeySz);
+#endif
+
+/* Set the KeyUsage.
+ * Value is a string separated tokens with ','. Accepted tokens are :
+ * digitalSignature,nonRepudiation,contentCommitment,keyCertSign,cRLSign,
+ * dataEncipherment,keyAgreement,keyEncipherment,encipherOnly and decipherOnly.
+ *
+ * nonRepudiation and contentCommitment are for the same usage.
+ */
+WOLFSSL_API int wc_SetKeyUsage(Cert *cert, const char *value);
+
+/* Set ExtendedKeyUsage
+ * Value is a string separated tokens with ','. Accepted tokens are :
+ * any,serverAuth,clientAuth,codeSigning,emailProtection,timeStamping,OCSPSigning
+ */
+WOLFSSL_API int wc_SetExtKeyUsage(Cert *cert, const char *value);
+
+
+#ifdef WOLFSSL_EKU_OID
+/* Set ExtendedKeyUsage with unique OID
+ * oid is expected to be in byte representation
+ */
+WOLFSSL_API int wc_SetExtKeyUsageOID(Cert *cert, const char *oid, word32 sz,
+                                     byte idx, void* heap);
+#endif /* WOLFSSL_EKU_OID */
+#endif /* WOLFSSL_CERT_EXT */
+
+    #ifdef HAVE_NTRU
+        WOLFSSL_API int wc_MakeNtruCert(Cert*, byte* derBuffer, word32 derSz,
+                                     const byte* ntruKey, word16 keySz,
+                                     WC_RNG*);
+    #endif
+
+#endif /* WOLFSSL_CERT_GEN */
+
+WOLFSSL_API int wc_GetDateInfo(const byte* certDate, int certDateSz,
+    const byte** date, byte* format, int* length);
+#ifndef NO_ASN_TIME
+WOLFSSL_API int wc_GetDateAsCalendarTime(const byte* date, int length,
+    byte format, struct tm* time);
+#endif
+
+#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
+
+    WOLFSSL_API int wc_PemGetHeaderFooter(int type, const char** header,
+        const char** footer);
+
+#endif
+
+WOLFSSL_API  int wc_AllocDer(DerBuffer** pDer, word32 length, int type, void* heap);
+WOLFSSL_API void wc_FreeDer(DerBuffer** pDer);
+
+#ifdef WOLFSSL_PEM_TO_DER
+    WOLFSSL_API int wc_PemToDer(const unsigned char* buff, long longSz, int type,
+              DerBuffer** pDer, void* heap, EncryptedInfo* info, int* eccKey);
+
+    WOLFSSL_API int wc_KeyPemToDer(const unsigned char*, int,
+                                   unsigned char*, int, const char*);
+    WOLFSSL_API int wc_CertPemToDer(const unsigned char*, int,
+                                    unsigned char*, int, int);
+#endif /* WOLFSSL_PEM_TO_DER */
+
+#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER)
+    #ifndef NO_FILESYSTEM
+        WOLFSSL_API int wc_PemPubKeyToDer(const char* fileName,
+                                          unsigned char* derBuf, int derSz);
+    #endif
+
+    WOLFSSL_API int wc_PubKeyPemToDer(const unsigned char*, int,
+                                      unsigned char*, int);
+#endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER */
+
+#ifdef WOLFSSL_CERT_GEN
+    #ifndef NO_FILESYSTEM
+        WOLFSSL_API int wc_PemCertToDer(const char* fileName,
+                                        unsigned char* derBuf, int derSz);
+    #endif
+#endif /* WOLFSSL_CERT_GEN */
+
+#ifdef WOLFSSL_DER_TO_PEM
+    WOLFSSL_API int wc_DerToPem(const byte* der, word32 derSz, byte* output,
+                                word32 outputSz, int type);
+    WOLFSSL_API int wc_DerToPemEx(const byte* der, word32 derSz, byte* output,
+                                word32 outputSz, byte *cipherIno, int type);
+#endif
+
+#ifndef NO_RSA
+    #if !defined(HAVE_USER_RSA)
+    WOLFSSL_API int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx,
+        word32 inSz, const byte** n, word32* nSz, const byte** e, word32* eSz);
+    #endif
+    WOLFSSL_API int wc_RsaPublicKeyDerSize(RsaKey* key, int with_header);
+#endif
+
+#ifdef HAVE_ECC
+    /* private key helpers */
+    WOLFSSL_API int wc_EccPrivateKeyDecode(const byte*, word32*,
+                                           ecc_key*, word32);
+    WOLFSSL_API int wc_EccKeyToDer(ecc_key*, byte* output, word32 inLen);
+    WOLFSSL_API int wc_EccPrivateKeyToDer(ecc_key* key, byte* output,
+                                          word32 inLen);
+    WOLFSSL_API int wc_EccPrivateKeyToPKCS8(ecc_key* key, byte* output,
+                                            word32* outLen);
+
+    /* public key helper */
+    WOLFSSL_API int wc_EccPublicKeyDecode(const byte*, word32*,
+                                              ecc_key*, word32);
+    WOLFSSL_API int wc_EccPublicKeyToDer(ecc_key*, byte* output,
+                                         word32 inLen, int with_AlgCurve);
+    WOLFSSL_API int wc_EccPublicKeyDerSize(ecc_key*, int with_AlgCurve);
+#endif
+
+#ifdef HAVE_ED25519
+    /* private key helpers */
+    WOLFSSL_API int wc_Ed25519PrivateKeyDecode(const byte*, word32*,
+                                               ed25519_key*, word32);
+    WOLFSSL_API int wc_Ed25519KeyToDer(ed25519_key* key, byte* output,
+                                       word32 inLen);
+    WOLFSSL_API int wc_Ed25519PrivateKeyToDer(ed25519_key* key, byte* output,
+                                              word32 inLen);
+
+    /* public key helper */
+    WOLFSSL_API int wc_Ed25519PublicKeyDecode(const byte*, word32*,
+                                              ed25519_key*, word32);
+    #if (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN))
+        WOLFSSL_API int wc_Ed25519PublicKeyToDer(ed25519_key*, byte* output,
+                                               word32 inLen, int with_AlgCurve);
+    #endif
+#endif
+
+#ifdef HAVE_ED448
+    /* private key helpers */
+    WOLFSSL_API int wc_Ed448PrivateKeyDecode(const byte*, word32*,
+                                             ed448_key*, word32);
+    WOLFSSL_API int wc_Ed448KeyToDer(ed448_key* key, byte* output,
+                                     word32 inLen);
+    WOLFSSL_API int wc_Ed448PrivateKeyToDer(ed448_key* key, byte* output,
+                                            word32 inLen);
+
+    /* public key helper */
+    WOLFSSL_API int wc_Ed448PublicKeyDecode(const byte*, word32*,
+                                            ed448_key*, word32);
+    #if (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN))
+        WOLFSSL_API int wc_Ed448PublicKeyToDer(ed448_key*, byte* output,
+                                               word32 inLen, int with_AlgCurve);
+    #endif
+#endif
+
+/* DER encode signature */
+WOLFSSL_API word32 wc_EncodeSignature(byte* out, const byte* digest,
+                                      word32 digSz, int hashOID);
+WOLFSSL_API int wc_GetCTC_HashOID(int type);
+
+WOLFSSL_API int wc_GetPkcs8TraditionalOffset(byte* input,
+                                             word32* inOutIdx, word32 sz);
+WOLFSSL_API int wc_CreatePKCS8Key(byte* out, word32* outSz,
+       byte* key, word32 keySz, int algoID, const byte* curveOID, word32 oidSz);
+
+#ifndef NO_ASN_TIME
+/* Time */
+/* Returns seconds (Epoch/UTC)
+ * timePtr: is "time_t", which is typically "long"
+ * Example:
+    long lTime;
+    rc = wc_GetTime(&lTime, (word32)sizeof(lTime));
+*/
+WOLFSSL_API int wc_GetTime(void* timePtr, word32 timeSize);
+#endif
+
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+    WOLFSSL_API int wc_EncryptedInfoGet(EncryptedInfo* info,
+        const char* cipherInfo);
+#endif
+
+
+#ifdef WOLFSSL_CERT_PIV
+
+typedef struct _wc_CertPIV {
+    const byte*  cert;
+    word32       certSz;
+    const byte*  certErrDet;
+    word32       certErrDetSz;
+    const byte*  nonce;         /* Identiv Only */
+    word32       nonceSz;       /* Identiv Only */
+    const byte*  signedNonce;   /* Identiv Only */
+    word32       signedNonceSz; /* Identiv Only */
+
+    /* flags */
+    word16       compression:2;
+    word16       isX509:1;
+    word16       isIdentiv:1;
+} wc_CertPIV;
+
+WOLFSSL_API int wc_ParseCertPIV(wc_CertPIV* cert, const byte* buf, word32 totalSz);
+#endif /* WOLFSSL_CERT_PIV */
+
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* WOLF_CRYPT_ASN_PUBLIC_H */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/chacha.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/chacha.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/chacha.h	(revision 453)
@@ -0,0 +1,83 @@
+/* chacha.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/chacha.h
+*/
+
+
+#ifndef WOLF_CRYPT_CHACHA_H
+#define WOLF_CRYPT_CHACHA_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifdef HAVE_CHACHA
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+/* Size of the IV */
+#define CHACHA_IV_WORDS    3
+#define CHACHA_IV_BYTES    (CHACHA_IV_WORDS * sizeof(word32))
+
+/* Size of ChaCha chunks */
+#define CHACHA_CHUNK_WORDS 16
+#define CHACHA_CHUNK_BYTES (CHACHA_CHUNK_WORDS * sizeof(word32))
+
+#ifdef WOLFSSL_X86_64_BUILD
+#if defined(USE_INTEL_SPEEDUP) && !defined(NO_CHACHA_ASM)
+    #define USE_INTEL_CHACHA_SPEEDUP
+    #define HAVE_INTEL_AVX1
+#endif
+#endif
+
+enum {
+	CHACHA_ENC_TYPE = WC_CIPHER_CHACHA,    /* cipher unique type */
+    CHACHA_MAX_KEY_SZ = 32,
+};
+
+typedef struct ChaCha {
+    word32 X[CHACHA_CHUNK_WORDS];           /* state of cipher */
+    word32 left;                            /* number of bytes leftover */
+#ifdef HAVE_INTEL_AVX1
+    /* vpshufd reads 16 bytes but we only use bottom 4. */
+    byte extra[12];
+#endif
+} ChaCha;
+
+/**
+  * IV(nonce) changes with each record
+  * counter is for what value the block counter should start ... usually 0
+  */
+WOLFSSL_API int wc_Chacha_SetIV(ChaCha* ctx, const byte* inIv, word32 counter);
+
+WOLFSSL_API int wc_Chacha_Process(ChaCha* ctx, byte* cipher, const byte* plain,
+                              word32 msglen);
+WOLFSSL_API int wc_Chacha_SetKey(ChaCha* ctx, const byte* key, word32 keySz);
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* HAVE_CHACHA */
+#endif /* WOLF_CRYPT_CHACHA_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/coding.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/coding.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/coding.h	(revision 453)
@@ -0,0 +1,88 @@
+/* coding.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/coding.h
+*/
+
+#ifndef WOLF_CRYPT_CODING_H
+#define WOLF_CRYPT_CODING_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+
+WOLFSSL_API int Base64_Decode(const byte* in, word32 inLen, byte* out,
+                               word32* outLen);
+
+#if defined(OPENSSL_EXTRA) || defined(SESSION_CERTS) || defined(WOLFSSL_KEY_GEN) \
+   || defined(WOLFSSL_CERT_GEN) || defined(HAVE_WEBSERVER) || !defined(NO_DSA)
+    #ifndef WOLFSSL_BASE64_ENCODE
+        #define WOLFSSL_BASE64_ENCODE
+    #endif
+#endif
+
+
+#ifdef WOLFSSL_BASE64_ENCODE
+    enum Escaped {
+        WC_STD_ENC = 0,       /* normal \n line ending encoding */
+        WC_ESC_NL_ENC,        /* use escape sequence encoding   */
+        WC_NO_NL_ENC          /* no encoding at all             */
+    }; /* Encoding types */
+
+    /* encode isn't */
+    WOLFSSL_API
+    int Base64_Encode(const byte* in, word32 inLen, byte* out,
+                                  word32* outLen);
+    WOLFSSL_API
+    int Base64_EncodeEsc(const byte* in, word32 inLen, byte* out,
+                                  word32* outLen);
+    WOLFSSL_API
+    int Base64_Encode_NoNl(const byte* in, word32 inLen, byte* out,
+                                  word32* outLen);
+#endif
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \
+    defined(HAVE_WEBSERVER) || defined(HAVE_FIPS) || \
+    defined(HAVE_ECC_CDH) || defined(HAVE_SELFTEST) || \
+    defined(WOLFSSL_ENCRYPTED_KEYS)
+    #ifndef WOLFSSL_BASE16
+        #define WOLFSSL_BASE16
+    #endif
+#endif
+
+#ifdef WOLFSSL_BASE16
+    WOLFSSL_API
+    int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen);
+    WOLFSSL_API
+    int Base16_Encode(const byte* in, word32 inLen, byte* out, word32* outLen);
+#endif
+
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* WOLF_CRYPT_CODING_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/cpuid.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/cpuid.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/cpuid.h	(revision 453)
@@ -0,0 +1,62 @@
+/* cpuid.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+#ifndef WOLF_CRYPT_CPUID_H
+#define WOLF_CRYPT_CPUID_H
+
+
+#include <wolfssl/wolfcrypt/types.h>
+
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+#if defined(WOLFSSL_X86_64_BUILD) || defined(USE_INTEL_SPEEDUP) || \
+    defined(WOLFSSL_AESNI)
+    #define CPUID_AVX1   0x0001
+    #define CPUID_AVX2   0x0002
+    #define CPUID_RDRAND 0x0004
+    #define CPUID_RDSEED 0x0008
+    #define CPUID_BMI2   0x0010   /* MULX, RORX */
+    #define CPUID_AESNI  0x0020
+    #define CPUID_ADX    0x0040   /* ADCX, ADOX */
+
+    #define IS_INTEL_AVX1(f)    ((f) & CPUID_AVX1)
+    #define IS_INTEL_AVX2(f)    ((f) & CPUID_AVX2)
+    #define IS_INTEL_RDRAND(f)  ((f) & CPUID_RDRAND)
+    #define IS_INTEL_RDSEED(f)  ((f) & CPUID_RDSEED)
+    #define IS_INTEL_BMI2(f)    ((f) & CPUID_BMI2)
+    #define IS_INTEL_AESNI(f)   ((f) & CPUID_AESNI)
+    #define IS_INTEL_ADX(f)     ((f) & CPUID_ADX)
+
+    void cpuid_set_flags(void);
+    word32 cpuid_get_flags(void);
+#endif
+
+#ifdef __cplusplus
+    }   /* extern "C" */
+#endif
+
+
+#endif /* WOLF_CRYPT_CPUID_H */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/curve25519.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/curve25519.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/curve25519.h	(revision 453)
@@ -0,0 +1,165 @@
+/* curve25519.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/curve25519.h
+*/
+
+
+#ifndef WOLF_CRYPT_CURVE25519_H
+#define WOLF_CRYPT_CURVE25519_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifdef HAVE_CURVE25519
+
+#include <wolfssl/wolfcrypt/fe_operations.h>
+#include <wolfssl/wolfcrypt/random.h>
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    #include <wolfssl/wolfcrypt/async.h>
+#endif
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+#define CURVE25519_KEYSIZE 32
+
+#ifdef WOLFSSL_NAMES_STATIC
+typedef char curve25519_str[12];
+#else
+typedef const char* curve25519_str;
+#endif
+
+/* curve25519 set type */
+typedef struct {
+    int size;             /* The size of the curve in octets */
+    curve25519_str name; /* name of this curve */
+} curve25519_set_type;
+
+
+/* ECC point, the internal structure is Little endian
+ * the mathematical functions used the endianness */
+typedef struct {
+    byte point[CURVE25519_KEYSIZE];
+    #ifdef FREESCALE_LTC_ECC
+        byte pointY[CURVE25519_KEYSIZE];
+    #endif
+} ECPoint;
+
+/* A CURVE25519 Key */
+typedef struct curve25519_key {
+    int idx;            /* Index into the ecc_sets[] for the parameters of
+                           this curve if -1, this key is using user supplied
+                           curve in dp */
+    const curve25519_set_type* dp;   /* domain parameters, either points to
+                                   curves (idx >= 0) or user supplied */
+    ECPoint   p;        /* public key  */
+    ECPoint   k;        /* private key */
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    WC_ASYNC_DEV asyncDev;
+#endif
+} curve25519_key;
+
+enum {
+    EC25519_LITTLE_ENDIAN=0,
+    EC25519_BIG_ENDIAN=1
+};
+
+WOLFSSL_API
+int wc_curve25519_make_key(WC_RNG* rng, int keysize, curve25519_key* key);
+
+WOLFSSL_API
+int wc_curve25519_shared_secret(curve25519_key* private_key,
+                                curve25519_key* public_key,
+                                byte* out, word32* outlen);
+
+WOLFSSL_API
+int wc_curve25519_shared_secret_ex(curve25519_key* private_key,
+                                   curve25519_key* public_key,
+                                   byte* out, word32* outlen, int endian);
+
+WOLFSSL_API
+int wc_curve25519_init(curve25519_key* key);
+
+WOLFSSL_API
+void wc_curve25519_free(curve25519_key* key);
+
+
+/* raw key helpers */
+WOLFSSL_API
+int wc_curve25519_import_private(const byte* priv, word32 privSz,
+                                 curve25519_key* key);
+WOLFSSL_API
+int wc_curve25519_import_private_ex(const byte* priv, word32 privSz,
+                                    curve25519_key* key, int endian);
+
+WOLFSSL_API
+int wc_curve25519_import_private_raw(const byte* priv, word32 privSz,
+                            const byte* pub, word32 pubSz, curve25519_key* key);
+WOLFSSL_API
+int wc_curve25519_import_private_raw_ex(const byte* priv, word32 privSz,
+                                        const byte* pub, word32 pubSz,
+                                        curve25519_key* key, int endian);
+WOLFSSL_API
+int wc_curve25519_export_private_raw(curve25519_key* key, byte* out,
+                                     word32* outLen);
+WOLFSSL_API
+int wc_curve25519_export_private_raw_ex(curve25519_key* key, byte* out,
+                                        word32* outLen, int endian);
+
+WOLFSSL_API
+int wc_curve25519_import_public(const byte* in, word32 inLen,
+                                curve25519_key* key);
+WOLFSSL_API
+int wc_curve25519_import_public_ex(const byte* in, word32 inLen,
+                                   curve25519_key* key, int endian);
+WOLFSSL_API
+int wc_curve25519_check_public(const byte* pub, word32 pubSz, int endian);
+
+WOLFSSL_API
+int wc_curve25519_export_public(curve25519_key* key, byte* out, word32* outLen);
+WOLFSSL_API
+int wc_curve25519_export_public_ex(curve25519_key* key, byte* out,
+                                   word32* outLen, int endian);
+
+WOLFSSL_API
+int wc_curve25519_export_key_raw(curve25519_key* key,
+                                 byte* priv, word32 *privSz,
+                                 byte* pub, word32 *pubSz);
+WOLFSSL_API
+int wc_curve25519_export_key_raw_ex(curve25519_key* key,
+                                    byte* priv, word32 *privSz,
+                                    byte* pub, word32 *pubSz,
+                                    int endian);
+/* size helper */
+WOLFSSL_API
+int wc_curve25519_size(curve25519_key* key);
+
+#ifdef __cplusplus
+    }    /* extern "C" */
+#endif
+
+#endif /* HAVE_CURVE25519 */
+#endif /* WOLF_CRYPT_CURVE25519_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/curve448.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/curve448.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/curve448.h	(revision 453)
@@ -0,0 +1,139 @@
+/* curve448.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* Implemented to: RFC 7748 */
+
+
+#ifndef WOLF_CRYPT_CURVE448_H
+#define WOLF_CRYPT_CURVE448_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifdef HAVE_CURVE448
+
+#include <wolfssl/wolfcrypt/fe_448.h>
+#include <wolfssl/wolfcrypt/random.h>
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    #include <wolfssl/wolfcrypt/async.h>
+#endif
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+#define CURVE448_KEY_SIZE        56
+#define CURVE448_PUB_KEY_SIZE    56
+
+
+/* A CURVE448 Key */
+typedef struct curve448_key {
+    byte p[CURVE448_PUB_KEY_SIZE];  /* public key  */
+    byte k[CURVE448_KEY_SIZE];      /* private key */
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    WC_ASYNC_DEV asyncDev;
+#endif
+} curve448_key;
+
+enum {
+    EC448_LITTLE_ENDIAN = 0,
+    EC448_BIG_ENDIAN    = 1
+};
+
+WOLFSSL_API
+int wc_curve448_make_key(WC_RNG* rng, int keysize, curve448_key* key);
+
+WOLFSSL_API
+int wc_curve448_shared_secret(curve448_key* private_key,
+                              curve448_key* public_key,
+                              byte* out, word32* outlen);
+
+WOLFSSL_API
+int wc_curve448_shared_secret_ex(curve448_key* private_key,
+                                 curve448_key* public_key,
+                                 byte* out, word32* outlen, int endian);
+
+WOLFSSL_API
+int wc_curve448_init(curve448_key* key);
+
+WOLFSSL_API
+void wc_curve448_free(curve448_key* key);
+
+
+/* raw key helpers */
+WOLFSSL_API
+int wc_curve448_import_private(const byte* priv, word32 privSz,
+                               curve448_key* key);
+WOLFSSL_API
+int wc_curve448_import_private_ex(const byte* priv, word32 privSz,
+                                  curve448_key* key, int endian);
+
+WOLFSSL_API
+int wc_curve448_import_private_raw(const byte* priv, word32 privSz,
+                                   const byte* pub, word32 pubSz,
+                                   curve448_key* key);
+WOLFSSL_API
+int wc_curve448_import_private_raw_ex(const byte* priv, word32 privSz,
+                                      const byte* pub, word32 pubSz,
+                                      curve448_key* key, int endian);
+WOLFSSL_API
+int wc_curve448_export_private_raw(curve448_key* key, byte* out,
+                                   word32* outLen);
+WOLFSSL_API
+int wc_curve448_export_private_raw_ex(curve448_key* key, byte* out,
+                                      word32* outLen, int endian);
+
+WOLFSSL_API
+int wc_curve448_import_public(const byte* in, word32 inLen,
+                              curve448_key* key);
+WOLFSSL_API
+int wc_curve448_import_public_ex(const byte* in, word32 inLen,
+                                 curve448_key* key, int endian);
+WOLFSSL_API
+int wc_curve448_check_public(const byte* pub, word32 pubSz, int endian);
+
+WOLFSSL_API
+int wc_curve448_export_public(curve448_key* key, byte* out, word32* outLen);
+WOLFSSL_API
+int wc_curve448_export_public_ex(curve448_key* key, byte* out,
+                                 word32* outLen, int endian);
+
+WOLFSSL_API
+int wc_curve448_export_key_raw(curve448_key* key,
+                               byte* priv, word32 *privSz,
+                               byte* pub, word32 *pubSz);
+WOLFSSL_API
+int wc_curve448_export_key_raw_ex(curve448_key* key,
+                                  byte* priv, word32 *privSz,
+                                  byte* pub, word32 *pubSz,
+                                  int endian);
+/* size helper */
+WOLFSSL_API
+int wc_curve448_size(curve448_key* key);
+
+#ifdef __cplusplus
+    }    /* extern "C" */
+#endif
+
+#endif /* HAVE_CURVE448 */
+#endif /* WOLF_CRYPT_CURVE448_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/des3.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/des3.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/des3.h	(revision 453)
@@ -0,0 +1,158 @@
+/* des3.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/des3.h
+*/
+
+#ifndef WOLF_CRYPT_DES3_H
+#define WOLF_CRYPT_DES3_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifndef NO_DES3
+
+#if defined(HAVE_FIPS) && \
+    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
+    #include <wolfssl/wolfcrypt/fips.h>
+#endif /* HAVE_FIPS_VERSION >= 2 */
+
+#if defined(HAVE_FIPS) && \
+	(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
+/* included for fips @wc_fips */
+#include <cyassl/ctaocrypt/des3.h>
+#endif
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+/* these are required for FIPS and non-FIPS */
+enum {
+    DES_KEY_SIZE        =  8,  /* des                     */
+    DES3_KEY_SIZE       = 24,  /* 3 des ede               */
+    DES_IV_SIZE         =  8,  /* should be the same as DES_BLOCK_SIZE */
+};
+
+
+/* avoid redefinition of structs */
+#if !defined(HAVE_FIPS) || \
+    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    #include <wolfssl/wolfcrypt/async.h>
+#endif
+
+enum {
+    DES_ENC_TYPE    = WC_CIPHER_DES,     /* cipher unique type */
+    DES3_ENC_TYPE   = WC_CIPHER_DES3,    /* cipher unique type */
+
+    DES_BLOCK_SIZE  = 8,
+    DES_KS_SIZE     = 32,    /* internal DES key buffer size */
+
+    DES_ENCRYPTION  = 0,
+    DES_DECRYPTION  = 1
+};
+
+#define DES_IVLEN 8
+#define DES_KEYLEN 8
+#define DES3_IVLEN 8
+#define DES3_KEYLEN 24
+
+
+#if defined(STM32_CRYPTO)
+enum {
+    DES_CBC = 0,
+    DES_ECB = 1
+};
+#endif
+
+
+/* DES encryption and decryption */
+typedef struct Des {
+    word32 reg[DES_BLOCK_SIZE / sizeof(word32)];      /* for CBC mode */
+    word32 tmp[DES_BLOCK_SIZE / sizeof(word32)];      /* same         */
+    word32 key[DES_KS_SIZE];
+} Des;
+
+
+/* DES3 encryption and decryption */
+struct Des3 {
+    word32 key[3][DES_KS_SIZE];
+    word32 reg[DES_BLOCK_SIZE / sizeof(word32)];      /* for CBC mode */
+    word32 tmp[DES_BLOCK_SIZE / sizeof(word32)];      /* same         */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    WC_ASYNC_DEV asyncDev;
+#endif
+#if defined(WOLF_CRYPTO_CB) || \
+    (defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES))
+    word32 devKey[DES3_KEYLEN/sizeof(word32)]; /* raw key */
+#endif
+#ifdef WOLF_CRYPTO_CB
+    int    devId;
+    void*  devCtx;
+#endif
+    void* heap;
+};
+
+#ifndef WC_DES3_TYPE_DEFINED
+    typedef struct Des3 Des3;
+    #define WC_DES3_TYPE_DEFINED
+#endif
+#endif /* HAVE_FIPS */
+
+
+WOLFSSL_API int  wc_Des_SetKey(Des* des, const byte* key,
+                               const byte* iv, int dir);
+WOLFSSL_API void wc_Des_SetIV(Des* des, const byte* iv);
+WOLFSSL_API int  wc_Des_CbcEncrypt(Des* des, byte* out,
+                                   const byte* in, word32 sz);
+WOLFSSL_API int  wc_Des_CbcDecrypt(Des* des, byte* out,
+                                   const byte* in, word32 sz);
+WOLFSSL_API int  wc_Des_EcbEncrypt(Des* des, byte* out,
+                                   const byte* in, word32 sz);
+WOLFSSL_API int wc_Des3_EcbEncrypt(Des3* des, byte* out,
+                                   const byte* in, word32 sz);
+
+/* ECB decrypt same process as encrypt but with decrypt key */
+#define wc_Des_EcbDecrypt  wc_Des_EcbEncrypt
+#define wc_Des3_EcbDecrypt wc_Des3_EcbEncrypt
+
+WOLFSSL_API int  wc_Des3_SetKey(Des3* des, const byte* key,
+                                const byte* iv,int dir);
+WOLFSSL_API int  wc_Des3_SetIV(Des3* des, const byte* iv);
+WOLFSSL_API int  wc_Des3_CbcEncrypt(Des3* des, byte* out,
+                                    const byte* in,word32 sz);
+WOLFSSL_API int  wc_Des3_CbcDecrypt(Des3* des, byte* out,
+                                    const byte* in,word32 sz);
+
+/* These are only required when using either:
+  static memory (WOLFSSL_STATIC_MEMORY) or asynchronous (WOLFSSL_ASYNC_CRYPT) */
+WOLFSSL_API int  wc_Des3Init(Des3*, void*, int);
+WOLFSSL_API void wc_Des3Free(Des3*);
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* NO_DES3 */
+#endif /* WOLF_CRYPT_DES3_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/dh.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/dh.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/dh.h	(revision 453)
@@ -0,0 +1,139 @@
+/* dh.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/dh.h
+*/
+
+#ifndef WOLF_CRYPT_DH_H
+#define WOLF_CRYPT_DH_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifndef NO_DH
+
+#if defined(HAVE_FIPS) && \
+    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
+    #include <wolfssl/wolfcrypt/fips.h>
+#endif /* HAVE_FIPS_VERSION >= 2 */
+
+#include <wolfssl/wolfcrypt/integer.h>
+#include <wolfssl/wolfcrypt/random.h>
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    #include <wolfssl/wolfcrypt/async.h>
+#endif
+typedef struct DhParams {
+    #ifdef HAVE_FFDHE_Q
+    const byte* q;
+    word32      q_len;
+    #endif /* HAVE_FFDHE_Q */
+    const byte* p;
+    word32      p_len;
+    const byte* g;
+    word32      g_len;
+} DhParams;
+
+/* Diffie-Hellman Key */
+struct DhKey {
+    mp_int p, g, q;                         /* group parameters  */
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH)
+    mp_int pub;
+    mp_int priv;
+#endif
+    void* heap;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    WC_ASYNC_DEV asyncDev;
+#endif
+};
+
+#ifndef WC_DH_TYPE_DEFINED
+    typedef struct DhKey DhKey;
+    #define WC_DH_TYPE_DEFINED
+#endif
+
+#ifdef HAVE_FFDHE_2048
+WOLFSSL_API const DhParams* wc_Dh_ffdhe2048_Get(void);
+#endif
+#ifdef HAVE_FFDHE_3072
+WOLFSSL_API const DhParams* wc_Dh_ffdhe3072_Get(void);
+#endif
+#ifdef HAVE_FFDHE_4096
+WOLFSSL_API const DhParams* wc_Dh_ffdhe4096_Get(void);
+#endif
+#ifdef HAVE_FFDHE_6144
+WOLFSSL_API const DhParams* wc_Dh_ffdhe6144_Get(void);
+#endif
+#ifdef HAVE_FFDHE_8192
+WOLFSSL_API const DhParams* wc_Dh_ffdhe8192_Get(void);
+#endif
+
+WOLFSSL_API int wc_InitDhKey(DhKey* key);
+WOLFSSL_API int wc_InitDhKey_ex(DhKey* key, void* heap, int devId);
+WOLFSSL_API int wc_FreeDhKey(DhKey* key);
+
+WOLFSSL_API int wc_DhGenerateKeyPair(DhKey* key, WC_RNG* rng, byte* priv,
+                                 word32* privSz, byte* pub, word32* pubSz);
+WOLFSSL_API int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz,
+                       const byte* priv, word32 privSz, const byte* otherPub,
+                       word32 pubSz);
+
+WOLFSSL_API int wc_DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key,
+                           word32);
+WOLFSSL_API int wc_DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g,
+                        word32 gSz);
+WOLFSSL_API int wc_DhSetKey_ex(DhKey* key, const byte* p, word32 pSz,
+                        const byte* g, word32 gSz, const byte* q, word32 qSz);
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+WOLFSSL_LOCAL int wc_DhSetFullKeys(DhKey* key,const byte* priv_key,word32 privSz,
+                                   const byte* pub_key, word32 pubSz);
+#endif
+WOLFSSL_API int wc_DhSetCheckKey(DhKey* key, const byte* p, word32 pSz,
+                        const byte* g, word32 gSz, const byte* q, word32 qSz,
+                        int trusted, WC_RNG* rng);
+WOLFSSL_API int wc_DhParamsLoad(const byte* input, word32 inSz, byte* p,
+                            word32* pInOutSz, byte* g, word32* gInOutSz);
+WOLFSSL_API int wc_DhCheckPubKey(DhKey* key, const byte* pub, word32 pubSz);
+WOLFSSL_API int wc_DhCheckPubKey_ex(DhKey* key, const byte* pub, word32 pubSz,
+                            const byte* prime, word32 primeSz);
+WOLFSSL_API int wc_DhCheckPubValue(const byte* prime, word32 primeSz,
+                                   const byte* pub, word32 pubSz);
+WOLFSSL_API int wc_DhCheckPrivKey(DhKey* key, const byte* priv, word32 pubSz);
+WOLFSSL_API int wc_DhCheckPrivKey_ex(DhKey* key, const byte* priv, word32 pubSz,
+                            const byte* prime, word32 primeSz);
+WOLFSSL_API int wc_DhCheckKeyPair(DhKey* key, const byte* pub, word32 pubSz,
+                        const byte* priv, word32 privSz);
+WOLFSSL_API int wc_DhGenerateParams(WC_RNG *rng, int modSz, DhKey *dh);
+WOLFSSL_API int wc_DhExportParamsRaw(DhKey* dh, byte* p, word32* pSz,
+                       byte* q, word32* qSz, byte* g, word32* gSz);
+
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* NO_DH */
+#endif /* WOLF_CRYPT_DH_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/dsa.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/dsa.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/dsa.h	(revision 453)
@@ -0,0 +1,105 @@
+/* dsa.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/dsa.h
+*/
+
+#ifndef WOLF_CRYPT_DSA_H
+#define WOLF_CRYPT_DSA_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifndef NO_DSA
+
+#include <wolfssl/wolfcrypt/integer.h>
+#include <wolfssl/wolfcrypt/random.h>
+
+/* for DSA reverse compatibility */
+#define InitDsaKey wc_InitDsaKey
+#define FreeDsaKey wc_FreeDsaKey
+#define DsaSign wc_DsaSign
+#define DsaVerify wc_DsaVerify
+#define DsaPublicKeyDecode wc_DsaPublicKeyDecode
+#define DsaPrivateKeyDecode wc_DsaPrivateKeyDecode
+#define DsaKeyToDer wc_DsaKeyToDer
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+
+enum {
+    DSA_PUBLIC   = 0,
+    DSA_PRIVATE  = 1
+};
+
+enum {
+    DSA_HALF_SIZE = 20,   /* r and s size  */
+    DSA_SIG_SIZE  = 40    /* signature size */
+};
+
+/* DSA */
+typedef struct DsaKey {
+    mp_int p, q, g, y, x;
+    int   type;                               /* public or private */
+    void* heap;                               /* memory hint */
+} DsaKey;
+
+WOLFSSL_API int wc_InitDsaKey(DsaKey* key);
+WOLFSSL_API int wc_InitDsaKey_h(DsaKey* key, void* h);
+WOLFSSL_API void wc_FreeDsaKey(DsaKey* key);
+WOLFSSL_API int wc_DsaSign(const byte* digest, byte* out,
+                           DsaKey* key, WC_RNG* rng);
+WOLFSSL_API int wc_DsaVerify(const byte* digest, const byte* sig,
+                             DsaKey* key, int* answer);
+WOLFSSL_API int wc_DsaPublicKeyDecode(const byte* input, word32* inOutIdx,
+                                      DsaKey*, word32);
+WOLFSSL_API int wc_DsaPrivateKeyDecode(const byte* input, word32* inOutIdx,
+                                       DsaKey*, word32);
+WOLFSSL_API int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen);
+WOLFSSL_API int wc_SetDsaPublicKey(byte* output, DsaKey* key,
+                                   int outLen, int with_header);
+WOLFSSL_API int wc_DsaKeyToPublicDer(DsaKey* key, byte* output, word32 inLen);
+
+#ifdef WOLFSSL_KEY_GEN
+WOLFSSL_API int wc_MakeDsaKey(WC_RNG *rng, DsaKey *dsa);
+WOLFSSL_API int wc_MakeDsaParameters(WC_RNG *rng, int modulus_size, DsaKey *dsa);
+#endif
+
+/* raw export functions */
+WOLFSSL_API int wc_DsaImportParamsRaw(DsaKey* dsa, const char* p,
+                                      const char* q, const char* g);
+WOLFSSL_API int wc_DsaImportParamsRawCheck(DsaKey* dsa, const char* p,
+                                      const char* q, const char* g,
+                                      int trusted, WC_RNG* rng);
+WOLFSSL_API int wc_DsaExportParamsRaw(DsaKey* dsa, byte* p, word32* pSz,
+                                      byte* q, word32* qSz, byte* g,
+                                      word32* gSz);
+WOLFSSL_API int wc_DsaExportKeyRaw(DsaKey* dsa, byte* x, word32* xSz, byte* y,
+                                   word32* ySz);
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* NO_DSA */
+#endif /* WOLF_CRYPT_DSA_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/ecc.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/ecc.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/ecc.h	(revision 453)
@@ -0,0 +1,762 @@
+/* ecc.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/ecc.h
+*/
+
+
+#ifndef WOLF_CRYPT_ECC_H
+#define WOLF_CRYPT_ECC_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifdef HAVE_ECC
+
+#if defined(HAVE_FIPS) && \
+    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
+    #include <wolfssl/wolfcrypt/fips.h>
+#endif /* HAVE_FIPS_VERSION >= 2 */
+
+#include <wolfssl/wolfcrypt/integer.h>
+#include <wolfssl/wolfcrypt/random.h>
+
+#ifdef HAVE_X963_KDF
+    #include <wolfssl/wolfcrypt/hash.h>
+#endif
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    #include <wolfssl/wolfcrypt/async.h>
+    #ifdef WOLFSSL_CERT_GEN
+        #include <wolfssl/wolfcrypt/asn.h>
+    #endif
+#endif
+
+#ifdef WOLFSSL_ATECC508A
+    #include <wolfssl/wolfcrypt/port/atmel/atmel.h>
+#endif /* WOLFSSL_ATECC508A */
+
+#if defined(WOLFSSL_CRYPTOCELL)
+    #include <wolfssl/wolfcrypt/port/arm/cryptoCell.h>
+#endif
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+
+/* Enable curve B parameter if needed */
+#if defined(HAVE_COMP_KEY) || defined(ECC_CACHE_CURVE)
+    #ifndef USE_ECC_B_PARAM /* Allow someone to force enable */
+        #define USE_ECC_B_PARAM
+    #endif
+#endif
+
+
+/* Use this as the key->idx if a custom ecc_set is used for key->dp */
+#define ECC_CUSTOM_IDX    (-1)
+
+
+/* Determine max ECC bits based on enabled curves */
+#if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
+    #define MAX_ECC_BITS    521
+#elif defined(HAVE_ECC512)
+    #define MAX_ECC_BITS    512
+#elif defined(HAVE_ECC384)
+    #define MAX_ECC_BITS    384
+#elif defined(HAVE_ECC320)
+    #define MAX_ECC_BITS    320
+#elif !defined(NO_ECC256)
+    #define MAX_ECC_BITS    256
+#elif defined(HAVE_ECC239)
+    #define MAX_ECC_BITS    239
+#elif defined(HAVE_ECC224)
+    #define MAX_ECC_BITS    224
+#elif defined(HAVE_ECC192)
+    #define MAX_ECC_BITS    192
+#elif defined(HAVE_ECC160)
+    #define MAX_ECC_BITS    160
+#elif defined(HAVE_ECC128)
+    #define MAX_ECC_BITS    128
+#elif defined(HAVE_ECC112)
+    #define MAX_ECC_BITS    112
+#endif
+
+/* calculate max ECC bytes */
+#if ((MAX_ECC_BITS * 2) % 8) == 0
+    #define MAX_ECC_BYTES     (MAX_ECC_BITS / 8)
+#else
+    /* add byte if not aligned */
+    #define MAX_ECC_BYTES     ((MAX_ECC_BITS / 8) + 1)
+#endif
+
+#ifndef ECC_MAX_PAD_SZ
+    /* ECC maximum padding size (when MSB is set extra byte required for R and S) */
+    #define ECC_MAX_PAD_SZ 2
+#endif
+
+enum {
+    ECC_PUBLICKEY       = 1,
+    ECC_PRIVATEKEY      = 2,
+    ECC_PRIVATEKEY_ONLY = 3,
+    ECC_MAXNAME     = 16,   /* MAX CURVE NAME LENGTH */
+    SIG_HEADER_SZ   =  7,   /* ECC signature header size (30 81 87 02 42 [R] 02 42 [S]) */
+    ECC_BUFSIZE     = 256,  /* for exported keys temp buffer */
+    ECC_MINSIZE     = 20,   /* MIN Private Key size */
+    ECC_MAXSIZE     = 66,   /* MAX Private Key size */
+    ECC_MAXSIZE_GEN = 74,   /* MAX Buffer size required when generating ECC keys*/
+    ECC_MAX_OID_LEN = 16,
+    ECC_MAX_SIG_SIZE= ((MAX_ECC_BYTES * 2) + ECC_MAX_PAD_SZ + SIG_HEADER_SZ),
+
+    /* max crypto hardware size */
+#ifdef WOLFSSL_ATECC508A
+    ECC_MAX_CRYPTO_HW_SIZE = ATECC_KEY_SIZE, /* from port/atmel/atmel.h */
+    ECC_MAX_CRYPTO_HW_PUBKEY_SIZE = (ATECC_KEY_SIZE*2),
+#elif defined(PLUTON_CRYPTO_ECC)
+    ECC_MAX_CRYPTO_HW_SIZE = 32,
+#elif defined(WOLFSSL_CRYPTOCELL)
+    #ifndef CRYPTOCELL_KEY_SIZE
+        CRYPTOCELL_KEY_SIZE = ECC_MAXSIZE,
+    #endif
+    ECC_MAX_CRYPTO_HW_SIZE = CRYPTOCELL_KEY_SIZE,
+#endif
+
+    /* point compression type */
+    ECC_POINT_COMP_EVEN = 0x02,
+    ECC_POINT_COMP_ODD = 0x03,
+    ECC_POINT_UNCOMP = 0x04,
+
+    /* Shamir's dual add constants */
+    SHAMIR_PRECOMP_SZ = 16,
+
+#ifdef HAVE_PKCS11
+    ECC_MAX_ID_LEN    = 32,
+#endif
+};
+
+/* Curve Types */
+typedef enum ecc_curve_id {
+    ECC_CURVE_INVALID = -1,
+    ECC_CURVE_DEF = 0, /* NIST or SECP */
+
+    /* NIST Prime Curves */
+    ECC_SECP192R1,
+    ECC_PRIME192V2,
+    ECC_PRIME192V3,
+    ECC_PRIME239V1,
+    ECC_PRIME239V2,
+    ECC_PRIME239V3,
+    ECC_SECP256R1,
+
+    /* SECP Curves */
+    ECC_SECP112R1,
+    ECC_SECP112R2,
+    ECC_SECP128R1,
+    ECC_SECP128R2,
+    ECC_SECP160R1,
+    ECC_SECP160R2,
+    ECC_SECP224R1,
+    ECC_SECP384R1,
+    ECC_SECP521R1,
+
+    /* Koblitz */
+    ECC_SECP160K1,
+    ECC_SECP192K1,
+    ECC_SECP224K1,
+    ECC_SECP256K1,
+
+    /* Brainpool Curves */
+    ECC_BRAINPOOLP160R1,
+    ECC_BRAINPOOLP192R1,
+    ECC_BRAINPOOLP224R1,
+    ECC_BRAINPOOLP256R1,
+    ECC_BRAINPOOLP320R1,
+    ECC_BRAINPOOLP384R1,
+    ECC_BRAINPOOLP512R1,
+
+    /* Twisted Edwards Curves */
+#ifdef HAVE_CURVE25519
+    ECC_X25519,
+#endif
+#ifdef HAVE_CURVE448
+    ECC_X448,
+#endif
+
+#ifdef WOLFSSL_CUSTOM_CURVES
+    ECC_CURVE_CUSTOM,
+#endif
+} ecc_curve_id;
+
+#ifdef HAVE_OID_ENCODING
+typedef word16 ecc_oid_t;
+#else
+typedef byte   ecc_oid_t;
+    /* OID encoded with ASN scheme:
+        first element = (oid[0] * 40) + oid[1]
+        if any element > 127 then MSB 0x80 indicates additional byte */
+#endif
+
+
+#if !defined(WOLFSSL_ECC_CURVE_STATIC) && defined(USE_WINDOWS_API)
+    /* MSC does something different with the pointers to the arrays than GCC,
+     * and it causes the FIPS checksum to fail. In the case of windows builds,
+     * store everything as arrays instead of pointers to strings. */
+
+    #define WOLFSSL_ECC_CURVE_STATIC
+#endif
+
+/* ECC set type defined a GF(p) curve */
+#ifndef WOLFSSL_ECC_CURVE_STATIC
+typedef struct ecc_set_type {
+    int size;             /* The size of the curve in octets */
+    int id;               /* id of this curve */
+    const char* name;     /* name of this curve */
+    const char* prime;    /* prime that defines the field, curve is in (hex) */
+    const char* Af;       /* fields A param (hex) */
+    const char* Bf;       /* fields B param (hex) */
+    const char* order;    /* order of the curve (hex) */
+    const char* Gx;       /* x coordinate of the base point on curve (hex) */
+    const char* Gy;       /* y coordinate of the base point on curve (hex) */
+    const ecc_oid_t* oid;
+    word32      oidSz;
+    word32      oidSum;    /* sum of encoded OID bytes */
+    int         cofactor;
+} ecc_set_type;
+#else
+#define MAX_ECC_NAME 16
+#define MAX_ECC_STRING ((MAX_ECC_BYTES * 2) + 1)
+    /* The values are stored as text strings. */
+
+typedef struct ecc_set_type {
+    int size;             /* The size of the curve in octets */
+    int id;               /* id of this curve */
+    const char name[MAX_ECC_NAME];     /* name of this curve */
+    const char prime[MAX_ECC_STRING];    /* prime that defines the field, curve is in (hex) */
+    const char Af[MAX_ECC_STRING];       /* fields A param (hex) */
+    const char Bf[MAX_ECC_STRING];       /* fields B param (hex) */
+    const char order[MAX_ECC_STRING];    /* order of the curve (hex) */
+    const char Gx[MAX_ECC_STRING];       /* x coordinate of the base point on curve (hex) */
+    const char Gy[MAX_ECC_STRING];       /* y coordinate of the base point on curve (hex) */
+    const ecc_oid_t oid[10];
+    word32      oidSz;
+    word32      oidSum;    /* sum of encoded OID bytes */
+    int         cofactor;
+} ecc_set_type;
+#endif
+
+
+#ifdef ALT_ECC_SIZE
+
+/* Note on ALT_ECC_SIZE:
+ * The fast math code uses an array of a fixed size to store the big integers.
+ * By default, the array is big enough for RSA keys. There is a size,
+ * FP_MAX_BITS which can be used to make the array smaller when one wants ECC
+ * but not RSA. Some people want fast math sized for both RSA and ECC, where
+ * ECC won't use as much as RSA. The flag ALT_ECC_SIZE switches in an alternate
+ * ecc_point structure that uses an alternate fp_int that has a shorter array
+ * of fp_digits.
+ *
+ * Now, without ALT_ECC_SIZE, the ecc_point has three single item arrays of
+ * mp_ints for the components of the point. With ALT_ECC_SIZE, the components
+ * of the point are pointers that are set to each of a three item array of
+ * alt_fp_ints. While an mp_int will have 4096 bits of digit inside the
+ * structure, the alt_fp_int will only have 528 bits. A size value was added
+ * in the ALT case, as well, and is set by mp_init() and alt_fp_init(). The
+ * functions fp_zero() and fp_copy() use the size parameter. An int needs to
+ * be initialized before using it instead of just fp_zeroing it, the init will
+ * call zero. FP_MAX_BITS_ECC defaults to 528, but can be set to change the
+ * number of bits used in the alternate FP_INT.
+ *
+ * Do not enable ALT_ECC_SIZE and disable fast math in the configuration.
+ */
+
+#ifndef USE_FAST_MATH
+    #error USE_FAST_MATH must be defined to use ALT_ECC_SIZE
+#endif
+
+/* determine max bits required for ECC math */
+#ifndef FP_MAX_BITS_ECC
+    /* check alignment */
+    #if ((MAX_ECC_BITS * 2) % DIGIT_BIT) == 0
+        /* max bits is double */
+        #define FP_MAX_BITS_ECC     (MAX_ECC_BITS * 2)
+    #else
+        /* max bits is doubled, plus one digit of fudge */
+        #define FP_MAX_BITS_ECC     ((MAX_ECC_BITS * 2) + DIGIT_BIT)
+    #endif
+#else
+    /* verify alignment */
+    #if FP_MAX_BITS_ECC % CHAR_BIT
+       #error FP_MAX_BITS_ECC must be a multiple of CHAR_BIT
+    #endif
+#endif
+
+/* determine buffer size */
+#define FP_SIZE_ECC    (FP_MAX_BITS_ECC/DIGIT_BIT)
+
+
+/* This needs to match the size of the fp_int struct, except the
+ * fp_digit array will be shorter. */
+typedef struct alt_fp_int {
+    int used, sign, size;
+    mp_digit dp[FP_SIZE_ECC];
+} alt_fp_int;
+#endif /* ALT_ECC_SIZE */
+
+#ifndef WC_ECCKEY_TYPE_DEFINED
+    typedef struct ecc_key ecc_key;
+    #define WC_ECCKEY_TYPE_DEFINED
+#endif
+
+
+/* A point on an ECC curve, stored in Jacobian format such that (x,y,z) =>
+   (x/z^2, y/z^3, 1) when interpreted as affine */
+typedef struct {
+#ifndef ALT_ECC_SIZE
+    mp_int x[1];        /* The x coordinate */
+    mp_int y[1];        /* The y coordinate */
+    mp_int z[1];        /* The z coordinate */
+#else
+    mp_int* x;        /* The x coordinate */
+    mp_int* y;        /* The y coordinate */
+    mp_int* z;        /* The z coordinate */
+    alt_fp_int xyz[3];
+#endif
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+    ecc_key* key;
+#endif
+} ecc_point;
+
+/* ECC Flags */
+enum {
+    WC_ECC_FLAG_NONE = 0x00,
+#ifdef HAVE_ECC_CDH
+    WC_ECC_FLAG_COFACTOR = 0x01,
+#endif
+};
+
+/* An ECC Key */
+struct ecc_key {
+    int type;           /* Public or Private */
+    int idx;            /* Index into the ecc_sets[] for the parameters of
+                           this curve if -1, this key is using user supplied
+                           curve in dp */
+    int    state;
+    word32 flags;
+    const ecc_set_type* dp;     /* domain parameters, either points to NIST
+                                   curves (idx >= 0) or user supplied */
+#ifdef WOLFSSL_CUSTOM_CURVES
+    int deallocSet;
+#endif
+    void* heap;         /* heap hint */
+    ecc_point pubkey;   /* public key */
+    mp_int    k;        /* private key */
+#ifdef WOLFSSL_ATECC508A
+    int  slot;        /* Key Slot Number (-1 unknown) */
+    byte pubkey_raw[ECC_MAX_CRYPTO_HW_PUBKEY_SIZE];
+#endif
+#if defined(PLUTON_CRYPTO_ECC) || defined(WOLF_CRYPTO_CB)
+    int devId;
+#endif
+#ifdef WOLFSSL_ASYNC_CRYPT
+    mp_int* r;          /* sign/verify temps */
+    mp_int* s;
+    WC_ASYNC_DEV asyncDev;
+    #ifdef HAVE_CAVIUM_V
+        mp_int* e;      /* Sign, Verify and Shared Secret */
+        mp_int* signK;
+    #endif
+    #ifdef WOLFSSL_CERT_GEN
+        CertSignCtx certSignCtx; /* context info for cert sign (MakeSignature) */
+    #endif
+#endif /* WOLFSSL_ASYNC_CRYPT */
+#ifdef HAVE_PKCS11
+    byte id[ECC_MAX_ID_LEN];
+    int  idLen;
+#endif
+#if defined(WOLFSSL_CRYPTOCELL)
+    ecc_context_t ctx;
+#endif
+
+#ifdef WOLFSSL_ECDSA_SET_K
+    mp_int *sign_k;
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+    mp_int* t1;
+    mp_int* t2;
+#ifdef ALT_ECC_SIZE
+    mp_int* x;
+    mp_int* y;
+    mp_int* z;
+#endif
+#endif
+
+#ifdef WOLFSSL_DSP
+    remote_handle64 handle;
+#endif
+};
+
+
+WOLFSSL_ABI WOLFSSL_API ecc_key* wc_ecc_key_new(void*);
+WOLFSSL_ABI WOLFSSL_API void wc_ecc_key_free(ecc_key*);
+
+
+/* ECC predefined curve sets  */
+extern const ecc_set_type ecc_sets[];
+extern const size_t ecc_sets_count;
+
+WOLFSSL_API
+const char* wc_ecc_get_name(int curve_id);
+
+#ifndef WOLFSSL_ATECC508A
+
+#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL
+    #define ECC_API    WOLFSSL_API
+#else
+    #define ECC_API    WOLFSSL_LOCAL
+#endif
+
+ECC_API int ecc_mul2add(ecc_point* A, mp_int* kA,
+                ecc_point* B, mp_int* kB,
+                ecc_point* C, mp_int* a, mp_int* modulus, void* heap);
+
+ECC_API int ecc_map(ecc_point*, mp_int*, mp_digit);
+ECC_API int ecc_map_ex(ecc_point*, mp_int*, mp_digit, int ct);
+ECC_API int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R,
+                                     mp_int* a, mp_int* modulus, mp_digit mp);
+ECC_API int ecc_projective_dbl_point(ecc_point* P, ecc_point* R, mp_int* a,
+                                     mp_int* modulus, mp_digit mp);
+
+#endif
+
+WOLFSSL_API
+int wc_ecc_make_key(WC_RNG* rng, int keysize, ecc_key* key);
+WOLFSSL_ABI WOLFSSL_API
+int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id);
+WOLFSSL_API
+int wc_ecc_make_pub(ecc_key* key, ecc_point* pubOut);
+WOLFSSL_API
+int wc_ecc_check_key(ecc_key* key);
+WOLFSSL_API
+int wc_ecc_is_point(ecc_point* ecp, mp_int* a, mp_int* b, mp_int* prime);
+WOLFSSL_API
+int wc_ecc_get_generator(ecc_point* ecp, int curve_idx);
+
+#ifdef HAVE_ECC_DHE
+WOLFSSL_API
+int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out,
+                      word32* outlen);
+WOLFSSL_LOCAL
+int wc_ecc_shared_secret_gen(ecc_key* private_key, ecc_point* point,
+                             byte* out, word32 *outlen);
+WOLFSSL_API
+int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point,
+                             byte* out, word32 *outlen);
+
+#if defined(WOLFSSL_ATECC508A) || defined(PLUTON_CRYPTO_ECC) || defined(WOLFSSL_CRYPTOCELL)
+#define wc_ecc_shared_secret_ssh wc_ecc_shared_secret
+#else
+#define wc_ecc_shared_secret_ssh wc_ecc_shared_secret_ex /* For backwards compat */
+#endif
+
+#endif /* HAVE_ECC_DHE */
+
+#ifdef HAVE_ECC_SIGN
+WOLFSSL_ABI WOLFSSL_API
+int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen,
+                     WC_RNG* rng, ecc_key* key);
+WOLFSSL_API
+int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng,
+                        ecc_key* key, mp_int *r, mp_int *s);
+#ifdef WOLFSSL_ECDSA_SET_K
+WOLFSSL_API
+int wc_ecc_sign_set_k(const byte* k, word32 klen, ecc_key* key);
+#endif
+#endif /* HAVE_ECC_SIGN */
+
+#ifdef HAVE_ECC_VERIFY
+WOLFSSL_API
+int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash,
+                    word32 hashlen, int* stat, ecc_key* key);
+WOLFSSL_API
+int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash,
+                          word32 hashlen, int* stat, ecc_key* key);
+#endif /* HAVE_ECC_VERIFY */
+
+WOLFSSL_API
+int wc_ecc_init(ecc_key* key);
+WOLFSSL_ABI WOLFSSL_API
+int wc_ecc_init_ex(ecc_key* key, void* heap, int devId);
+#ifdef HAVE_PKCS11
+WOLFSSL_API
+int wc_ecc_init_id(ecc_key* key, unsigned char* id, int len, void* heap,
+                   int devId);
+#endif
+#ifdef WOLFSSL_CUSTOM_CURVES
+WOLFSSL_LOCAL
+void wc_ecc_free_curve(const ecc_set_type* curve, void* heap);
+#endif
+WOLFSSL_ABI WOLFSSL_API
+int wc_ecc_free(ecc_key* key);
+WOLFSSL_API
+int wc_ecc_set_flags(ecc_key* key, word32 flags);
+WOLFSSL_API
+void wc_ecc_fp_free(void);
+
+WOLFSSL_API
+int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id);
+
+WOLFSSL_API
+int wc_ecc_is_valid_idx(int n);
+WOLFSSL_API
+int wc_ecc_get_curve_idx(int curve_id);
+WOLFSSL_API
+int wc_ecc_get_curve_id(int curve_idx);
+#define wc_ecc_get_curve_name_from_id wc_ecc_get_name
+WOLFSSL_API
+int wc_ecc_get_curve_size_from_id(int curve_id);
+
+WOLFSSL_API
+int wc_ecc_get_curve_idx_from_name(const char* curveName);
+WOLFSSL_API
+int wc_ecc_get_curve_size_from_name(const char* curveName);
+WOLFSSL_API
+int wc_ecc_get_curve_id_from_name(const char* curveName);
+WOLFSSL_API
+int wc_ecc_get_curve_id_from_params(int fieldSize,
+        const byte* prime, word32 primeSz, const byte* Af, word32 AfSz,
+        const byte* Bf, word32 BfSz, const byte* order, word32 orderSz,
+        const byte* Gx, word32 GxSz, const byte* Gy, word32 GySz, int cofactor);
+WOLFSSL_API
+int wc_ecc_get_curve_id_from_dp_params(const ecc_set_type* dp);
+
+WOLFSSL_API
+int wc_ecc_get_curve_id_from_oid(const byte* oid, word32 len);
+
+WOLFSSL_API const ecc_set_type* wc_ecc_get_curve_params(int curve_idx);
+
+WOLFSSL_API
+ecc_point* wc_ecc_new_point(void);
+WOLFSSL_API
+ecc_point* wc_ecc_new_point_h(void* h);
+WOLFSSL_API
+void wc_ecc_del_point(ecc_point* p);
+WOLFSSL_API
+void wc_ecc_del_point_h(ecc_point* p, void* h);
+WOLFSSL_API
+int wc_ecc_copy_point(ecc_point* p, ecc_point *r);
+WOLFSSL_API
+int wc_ecc_cmp_point(ecc_point* a, ecc_point *b);
+WOLFSSL_API
+int wc_ecc_point_is_at_infinity(ecc_point *p);
+
+#ifndef WOLFSSL_ATECC508A
+WOLFSSL_API
+int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R,
+                  mp_int* a, mp_int* modulus, int map);
+WOLFSSL_LOCAL
+int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R,
+                  mp_int* a, mp_int* modulus, int map, void* heap);
+#endif /* !WOLFSSL_ATECC508A */
+
+
+#ifdef HAVE_ECC_KEY_EXPORT
+/* ASN key helpers */
+WOLFSSL_API
+int wc_ecc_export_x963(ecc_key*, byte* out, word32* outLen);
+WOLFSSL_API
+int wc_ecc_export_x963_ex(ecc_key*, byte* out, word32* outLen, int compressed);
+    /* extended functionality with compressed option */
+#endif /* HAVE_ECC_KEY_EXPORT */
+
+#ifdef HAVE_ECC_KEY_IMPORT
+WOLFSSL_ABI WOLFSSL_API
+int wc_ecc_import_x963(const byte* in, word32 inLen, ecc_key* key);
+WOLFSSL_API
+int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key,
+                          int curve_id);
+WOLFSSL_API
+int wc_ecc_import_private_key(const byte* priv, word32 privSz, const byte* pub,
+                           word32 pubSz, ecc_key* key);
+WOLFSSL_API
+int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz,
+                const byte* pub, word32 pubSz, ecc_key* key, int curve_id);
+WOLFSSL_API
+int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen);
+WOLFSSL_API
+int wc_ecc_rs_raw_to_sig(const byte* r, word32 rSz, const byte* s, word32 sSz,
+    byte* out, word32* outlen);
+WOLFSSL_API
+int wc_ecc_sig_to_rs(const byte* sig, word32 sigLen, byte* r, word32* rLen,
+                   byte* s, word32* sLen);
+WOLFSSL_API
+int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy,
+                   const char* d, const char* curveName);
+WOLFSSL_API
+int wc_ecc_import_raw_ex(ecc_key* key, const char* qx, const char* qy,
+                   const char* d, int curve_id);
+WOLFSSL_API
+int wc_ecc_import_unsigned(ecc_key* key, byte* qx, byte* qy,
+                   byte* d, int curve_id);
+#endif /* HAVE_ECC_KEY_IMPORT */
+
+#ifdef HAVE_ECC_KEY_EXPORT
+WOLFSSL_API
+int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen,
+                     byte* qy, word32* qyLen, byte* d, word32* dLen,
+                     int encType);
+WOLFSSL_API
+int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen);
+WOLFSSL_API
+int wc_ecc_export_public_raw(ecc_key* key, byte* qx, word32* qxLen,
+                             byte* qy, word32* qyLen);
+WOLFSSL_API
+int wc_ecc_export_private_raw(ecc_key* key, byte* qx, word32* qxLen,
+                              byte* qy, word32* qyLen, byte* d, word32* dLen);
+#endif /* HAVE_ECC_KEY_EXPORT */
+
+#ifdef HAVE_ECC_KEY_EXPORT
+WOLFSSL_API
+int wc_ecc_export_point_der_ex(const int curve_idx, ecc_point* point, byte* out,
+                               word32* outLen, int compressed);
+WOLFSSL_API
+int wc_ecc_export_point_der(const int curve_idx, ecc_point* point,
+                            byte* out, word32* outLen);
+WOLFSSL_LOCAL
+int wc_ecc_export_point_der_compressed(const int curve_idx, ecc_point* point,
+                                       byte* out, word32* outLen);
+#endif /* HAVE_ECC_KEY_EXPORT */
+
+
+#ifdef HAVE_ECC_KEY_IMPORT
+WOLFSSL_API
+int wc_ecc_import_point_der_ex(byte* in, word32 inLen, const int curve_idx,
+                               ecc_point* point, int shortKeySize);
+WOLFSSL_API
+int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx,
+                            ecc_point* point);
+#endif /* HAVE_ECC_KEY_IMPORT */
+
+/* size helper */
+WOLFSSL_API
+int wc_ecc_size(ecc_key* key);
+WOLFSSL_API
+int wc_ecc_sig_size_calc(int sz);
+WOLFSSL_API
+int wc_ecc_sig_size(ecc_key* key);
+
+WOLFSSL_API
+int wc_ecc_get_oid(word32 oidSum, const byte** oid, word32* oidSz);
+
+#ifdef WOLFSSL_CUSTOM_CURVES
+    WOLFSSL_API
+    int wc_ecc_set_custom_curve(ecc_key* key, const ecc_set_type* dp);
+#endif
+
+#ifdef HAVE_ECC_ENCRYPT
+/* ecc encrypt */
+
+enum ecEncAlgo {
+    ecAES_128_CBC = 1,  /* default */
+    ecAES_256_CBC = 2
+};
+
+enum ecKdfAlgo {
+    ecHKDF_SHA256 = 1,  /* default */
+    ecHKDF_SHA1   = 2
+};
+
+enum ecMacAlgo {
+    ecHMAC_SHA256 = 1,  /* default */
+    ecHMAC_SHA1   = 2
+};
+
+enum {
+    KEY_SIZE_128     = 16,
+    KEY_SIZE_256     = 32,
+    IV_SIZE_64       =  8,
+    IV_SIZE_128      = 16,
+    EXCHANGE_SALT_SZ = 16,
+    EXCHANGE_INFO_SZ = 23
+};
+
+enum ecFlags {
+    REQ_RESP_CLIENT = 1,
+    REQ_RESP_SERVER = 2
+};
+
+
+typedef struct ecEncCtx ecEncCtx;
+
+WOLFSSL_API
+ecEncCtx* wc_ecc_ctx_new(int flags, WC_RNG* rng);
+WOLFSSL_API
+ecEncCtx* wc_ecc_ctx_new_ex(int flags, WC_RNG* rng, void* heap);
+WOLFSSL_API
+void wc_ecc_ctx_free(ecEncCtx*);
+WOLFSSL_API
+int wc_ecc_ctx_reset(ecEncCtx*, WC_RNG*);  /* reset for use again w/o alloc/free */
+
+WOLFSSL_API
+const byte* wc_ecc_ctx_get_own_salt(ecEncCtx*);
+WOLFSSL_API
+int wc_ecc_ctx_set_peer_salt(ecEncCtx*, const byte* salt);
+WOLFSSL_API
+int wc_ecc_ctx_set_info(ecEncCtx*, const byte* info, int sz);
+
+WOLFSSL_API
+int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
+                word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx);
+WOLFSSL_API
+int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
+                word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx);
+
+#endif /* HAVE_ECC_ENCRYPT */
+
+#ifdef HAVE_X963_KDF
+WOLFSSL_API int wc_X963_KDF(enum wc_HashType type, const byte* secret,
+                word32 secretSz, const byte* sinfo, word32 sinfoSz,
+                byte* out, word32 outSz);
+#endif
+
+#ifdef ECC_CACHE_CURVE
+WOLFSSL_API int wc_ecc_curve_cache_init(void);
+WOLFSSL_API void wc_ecc_curve_cache_free(void);
+#endif
+
+WOLFSSL_API
+int wc_ecc_gen_k(WC_RNG* rng, int size, mp_int* k, mp_int* order);
+
+#ifdef WOLFSSL_DSP
+WOLFSSL_API
+int wc_ecc_set_handle(ecc_key* key, remote_handle64 handle);
+WOLFSSL_LOCAL
+int sp_dsp_ecc_verify_256(remote_handle64 handle, const byte* hash, word32 hashLen, mp_int* pX,
+    mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap);
+#endif
+
+#ifdef __cplusplus
+    }    /* extern "C" */
+#endif
+
+#endif /* HAVE_ECC */
+#endif /* WOLF_CRYPT_ECC_H */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/ed25519.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/ed25519.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/ed25519.h	(revision 453)
@@ -0,0 +1,169 @@
+/* ed25519.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/ed25519.h
+*/
+
+
+#ifndef WOLF_CRYPT_ED25519_H
+#define WOLF_CRYPT_ED25519_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifdef HAVE_ED25519
+
+#include <wolfssl/wolfcrypt/fe_operations.h>
+#include <wolfssl/wolfcrypt/ge_operations.h>
+#include <wolfssl/wolfcrypt/random.h>
+#include <wolfssl/wolfcrypt/sha512.h>
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    #include <wolfssl/wolfcrypt/async.h>
+#endif
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+
+/* info about EdDSA curve specifically ed25519, defined as an elliptic curve
+   over GF(p) */
+/*
+    32,                key size
+    "ED25519",         curve name
+    "2^255-19",        prime number
+    "SHA512",          hash function
+    "-121665/121666",  value of d
+*/
+
+#define ED25519_KEY_SIZE     32 /* private key only */
+#define ED25519_SIG_SIZE     64
+
+#define ED25519_PUB_KEY_SIZE 32 /* compressed */
+/* both private and public key */
+#define ED25519_PRV_KEY_SIZE (ED25519_PUB_KEY_SIZE+ED25519_KEY_SIZE)
+
+
+enum {
+    Ed25519    = -1,
+    Ed25519ctx = 0,
+    Ed25519ph  = 1,
+};
+
+#ifndef WC_ED25519KEY_TYPE_DEFINED
+    typedef struct ed25519_key ed25519_key;
+    #define WC_ED25519KEY_TYPE_DEFINED
+#endif
+
+/* An ED25519 Key */
+struct ed25519_key {
+    byte    p[ED25519_PUB_KEY_SIZE]; /* compressed public key */
+    byte    k[ED25519_PRV_KEY_SIZE]; /* private key : 32 secret -- 32 public */
+#ifdef FREESCALE_LTC_ECC
+    /* uncompressed point coordinates */
+    byte pointX[ED25519_KEY_SIZE]; /* recovered X coordinate */
+    byte pointY[ED25519_KEY_SIZE]; /* Y coordinate is the public key with The most significant bit of the final octet always zero. */
+#endif
+    word16 pubKeySet:1;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    WC_ASYNC_DEV asyncDev;
+#endif
+};
+
+
+WOLFSSL_API
+int wc_ed25519_make_public(ed25519_key* key, unsigned char* pubKey,
+                           word32 pubKeySz);
+WOLFSSL_API
+int wc_ed25519_make_key(WC_RNG* rng, int keysize, ed25519_key* key);
+WOLFSSL_API
+int wc_ed25519_sign_msg(const byte* in, word32 inLen, byte* out,
+                        word32 *outLen, ed25519_key* key);
+WOLFSSL_API
+int wc_ed25519ctx_sign_msg(const byte* in, word32 inLen, byte* out,
+                           word32 *outLen, ed25519_key* key,
+                           const byte* context, byte contextLen);
+WOLFSSL_API
+int wc_ed25519ph_sign_hash(const byte* hash, word32 hashLen, byte* out,
+                           word32 *outLen, ed25519_key* key,
+                           const byte* context, byte contextLen);
+WOLFSSL_API
+int wc_ed25519ph_sign_msg(const byte* in, word32 inLen, byte* out,
+                          word32 *outLen, ed25519_key* key, const byte* context,
+                          byte contextLen);
+WOLFSSL_API
+int wc_ed25519_verify_msg(const byte* sig, word32 sigLen, const byte* msg,
+                          word32 msgLen, int* stat, ed25519_key* key);
+WOLFSSL_API
+int wc_ed25519ctx_verify_msg(const byte* sig, word32 sigLen, const byte* msg,
+                             word32 msgLen, int* stat, ed25519_key* key,
+                             const byte* context, byte contextLen);
+WOLFSSL_API
+int wc_ed25519ph_verify_hash(const byte* sig, word32 sigLen, const byte* hash,
+                             word32 hashLen, int* stat, ed25519_key* key,
+                             const byte* context, byte contextLen);
+WOLFSSL_API
+int wc_ed25519ph_verify_msg(const byte* sig, word32 sigLen, const byte* msg,
+                            word32 msgLen, int* stat, ed25519_key* key,
+                            const byte* context, byte contextLen);
+WOLFSSL_API
+int wc_ed25519_init(ed25519_key* key);
+WOLFSSL_API
+void wc_ed25519_free(ed25519_key* key);
+WOLFSSL_API
+int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key);
+WOLFSSL_API
+int wc_ed25519_import_private_only(const byte* priv, word32 privSz,
+                                                              ed25519_key* key);
+WOLFSSL_API
+int wc_ed25519_import_private_key(const byte* priv, word32 privSz,
+                               const byte* pub, word32 pubSz, ed25519_key* key);
+WOLFSSL_API
+int wc_ed25519_export_public(ed25519_key*, byte* out, word32* outLen);
+WOLFSSL_API
+int wc_ed25519_export_private_only(ed25519_key* key, byte* out, word32* outLen);
+WOLFSSL_API
+int wc_ed25519_export_private(ed25519_key* key, byte* out, word32* outLen);
+WOLFSSL_API
+int wc_ed25519_export_key(ed25519_key* key,
+                          byte* priv, word32 *privSz,
+                          byte* pub, word32 *pubSz);
+
+WOLFSSL_API
+int wc_ed25519_check_key(ed25519_key* key);
+
+/* size helper */
+WOLFSSL_API
+int wc_ed25519_size(ed25519_key* key);
+WOLFSSL_API
+int wc_ed25519_priv_size(ed25519_key* key);
+WOLFSSL_API
+int wc_ed25519_pub_size(ed25519_key* key);
+WOLFSSL_API
+int wc_ed25519_sig_size(ed25519_key* key);
+
+#ifdef __cplusplus
+    }    /* extern "C" */
+#endif
+
+#endif /* HAVE_ED25519 */
+#endif /* WOLF_CRYPT_ED25519_H */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/error-crypt.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/error-crypt.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/error-crypt.h	(revision 453)
@@ -0,0 +1,255 @@
+/* error-crypt.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/error-crypt.h
+*/
+
+#ifndef WOLF_CRYPT_ERROR_H
+#define WOLF_CRYPT_ERROR_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#if defined(HAVE_FIPS) && \
+    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
+	#include <cyassl/ctaocrypt/error-crypt.h>
+#endif /* HAVE_FIPS V1 */
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+
+/* error codes, add string for new errors !!! */
+enum {
+    MAX_CODE_E         = -100,  /* errors -101 - -299 */
+    OPEN_RAN_E         = -101,  /* opening random device error */
+    READ_RAN_E         = -102,  /* reading random device error */
+    WINCRYPT_E         = -103,  /* windows crypt init error */
+    CRYPTGEN_E         = -104,  /* windows crypt generation error */
+    RAN_BLOCK_E        = -105,  /* reading random device would block */
+    BAD_MUTEX_E        = -106,  /* Bad mutex operation */
+    WC_TIMEOUT_E       = -107,  /* timeout error */
+    WC_PENDING_E       = -108,  /* wolfCrypt operation pending (would block) */
+    WC_NOT_PENDING_E   = -109,  /* wolfCrypt operation not pending */
+
+    MP_INIT_E          = -110,  /* mp_init error state */
+    MP_READ_E          = -111,  /* mp_read error state */
+    MP_EXPTMOD_E       = -112,  /* mp_exptmod error state */
+    MP_TO_E            = -113,  /* mp_to_xxx error state, can't convert */
+    MP_SUB_E           = -114,  /* mp_sub error state, can't subtract */
+    MP_ADD_E           = -115,  /* mp_add error state, can't add */
+    MP_MUL_E           = -116,  /* mp_mul error state, can't multiply */
+    MP_MULMOD_E        = -117,  /* mp_mulmod error state, can't multiply mod */
+    MP_MOD_E           = -118,  /* mp_mod error state, can't mod */
+    MP_INVMOD_E        = -119,  /* mp_invmod error state, can't inv mod */
+    MP_CMP_E           = -120,  /* mp_cmp error state */
+    MP_ZERO_E          = -121,  /* got a mp zero result, not expected */
+
+    MEMORY_E           = -125,  /* out of memory error */
+    VAR_STATE_CHANGE_E = -126,  /* var state modified by different thread */
+
+    RSA_WRONG_TYPE_E   = -130,  /* RSA wrong block type for RSA function */
+    RSA_BUFFER_E       = -131,  /* RSA buffer error, output too small or
+                                   input too large */
+    BUFFER_E           = -132,  /* output buffer too small or input too large */
+    ALGO_ID_E          = -133,  /* setting algo id error */
+    PUBLIC_KEY_E       = -134,  /* setting public key error */
+    DATE_E             = -135,  /* setting date validity error */
+    SUBJECT_E          = -136,  /* setting subject name error */
+    ISSUER_E           = -137,  /* setting issuer  name error */
+    CA_TRUE_E          = -138,  /* setting CA basic constraint true error */
+    EXTENSIONS_E       = -139,  /* setting extensions error */
+
+    ASN_PARSE_E        = -140,  /* ASN parsing error, invalid input */
+    ASN_VERSION_E      = -141,  /* ASN version error, invalid number */
+    ASN_GETINT_E       = -142,  /* ASN get big int error, invalid data */
+    ASN_RSA_KEY_E      = -143,  /* ASN key init error, invalid input */
+    ASN_OBJECT_ID_E    = -144,  /* ASN object id error, invalid id */
+    ASN_TAG_NULL_E     = -145,  /* ASN tag error, not null */
+    ASN_EXPECT_0_E     = -146,  /* ASN expect error, not zero */
+    ASN_BITSTR_E       = -147,  /* ASN bit string error, wrong id */
+    ASN_UNKNOWN_OID_E  = -148,  /* ASN oid error, unknown sum id */
+    ASN_DATE_SZ_E      = -149,  /* ASN date error, bad size */
+    ASN_BEFORE_DATE_E  = -150,  /* ASN date error, current date before */
+    ASN_AFTER_DATE_E   = -151,  /* ASN date error, current date after */
+    ASN_SIG_OID_E      = -152,  /* ASN signature error, mismatched oid */
+    ASN_TIME_E         = -153,  /* ASN time error, unknown time type */
+    ASN_INPUT_E        = -154,  /* ASN input error, not enough data */
+    ASN_SIG_CONFIRM_E  = -155,  /* ASN sig error, confirm failure */
+    ASN_SIG_HASH_E     = -156,  /* ASN sig error, unsupported hash type */
+    ASN_SIG_KEY_E      = -157,  /* ASN sig error, unsupported key type */
+    ASN_DH_KEY_E       = -158,  /* ASN key init error, invalid input */
+    ASN_NTRU_KEY_E     = -159,  /* ASN ntru key decode error, invalid input */
+    ASN_CRIT_EXT_E     = -160,  /* ASN unsupported critical extension */
+    ASN_ALT_NAME_E     = -161,  /* ASN alternate name error */
+    ASN_NO_PEM_HEADER  = -162,  /* ASN no PEM header found */
+
+    ECC_BAD_ARG_E      = -170,  /* ECC input argument of wrong type */
+    ASN_ECC_KEY_E      = -171,  /* ASN ECC bad input */
+    ECC_CURVE_OID_E    = -172,  /* Unsupported ECC OID curve type */
+    BAD_FUNC_ARG       = -173,  /* Bad function argument provided */
+    NOT_COMPILED_IN    = -174,  /* Feature not compiled in */
+    UNICODE_SIZE_E     = -175,  /* Unicode password too big */
+    NO_PASSWORD        = -176,  /* no password provided by user */
+    ALT_NAME_E         = -177,  /* alt name size problem, too big */
+    BAD_OCSP_RESPONDER = -178,  /* missing key usage extensions */
+
+    AES_GCM_AUTH_E     = -180,  /* AES-GCM Authentication check failure */
+    AES_CCM_AUTH_E     = -181,  /* AES-CCM Authentication check failure */
+
+    ASYNC_INIT_E       = -182,  /* Async Init type error */
+
+    COMPRESS_INIT_E    = -183,  /* Compress init error */
+    COMPRESS_E         = -184,  /* Compress error */
+    DECOMPRESS_INIT_E  = -185,  /* DeCompress init error */
+    DECOMPRESS_E       = -186,  /* DeCompress error */
+
+    BAD_ALIGN_E         = -187,  /* Bad alignment for operation, no alloc */
+    ASN_NO_SIGNER_E     = -188,  /* ASN no signer to confirm failure */
+    ASN_CRL_CONFIRM_E   = -189,  /* ASN CRL signature confirm failure */
+    ASN_CRL_NO_SIGNER_E = -190,  /* ASN CRL no signer to confirm failure */
+    ASN_OCSP_CONFIRM_E  = -191,  /* ASN OCSP signature confirm failure */
+
+    BAD_STATE_E         = -192,  /* Bad state operation */
+    BAD_PADDING_E       = -193,  /* Bad padding, msg not correct length  */
+
+    REQ_ATTRIBUTE_E     = -194,  /* setting cert request attributes error */
+
+    PKCS7_OID_E         = -195,  /* PKCS#7, mismatched OID error */
+    PKCS7_RECIP_E       = -196,  /* PKCS#7, recipient error */
+    FIPS_NOT_ALLOWED_E  = -197,  /* FIPS not allowed error */
+    ASN_NAME_INVALID_E  = -198,  /* ASN name constraint error */
+
+    RNG_FAILURE_E       = -199,  /* RNG Failed, Reinitialize */
+    HMAC_MIN_KEYLEN_E   = -200,  /* FIPS Mode HMAC Minimum Key Length error */
+    RSA_PAD_E           = -201,  /* RSA Padding Error */
+    LENGTH_ONLY_E       = -202,  /* Returning output length only */
+
+    IN_CORE_FIPS_E      = -203,  /* In Core Integrity check failure */
+    AES_KAT_FIPS_E      = -204,  /* AES KAT failure */
+    DES3_KAT_FIPS_E     = -205,  /* DES3 KAT failure */
+    HMAC_KAT_FIPS_E     = -206,  /* HMAC KAT failure */
+    RSA_KAT_FIPS_E      = -207,  /* RSA KAT failure */
+    DRBG_KAT_FIPS_E     = -208,  /* HASH DRBG KAT failure */
+    DRBG_CONT_FIPS_E    = -209,  /* HASH DRBG Continuous test failure */
+    AESGCM_KAT_FIPS_E   = -210,  /* AESGCM KAT failure */
+    THREAD_STORE_KEY_E  = -211,  /* Thread local storage key create failure */
+    THREAD_STORE_SET_E  = -212,  /* Thread local storage key set failure */
+
+    MAC_CMP_FAILED_E    = -213,  /* MAC comparison failed */
+    IS_POINT_E          = -214,  /* ECC is point on curve failed */
+    ECC_INF_E           = -215,  /* ECC point infinity error */
+    ECC_PRIV_KEY_E      = -216,  /* ECC private key not valid error */
+    ECC_OUT_OF_RANGE_E  = -217,  /* ECC key component out of range */
+
+    SRP_CALL_ORDER_E    = -218,  /* SRP function called in the wrong order. */
+    SRP_VERIFY_E        = -219,  /* SRP proof verification failed. */
+    SRP_BAD_KEY_E       = -220,  /* SRP bad ephemeral values. */
+
+    ASN_NO_SKID         = -221,  /* ASN no Subject Key Identifier found */
+    ASN_NO_AKID         = -222,  /* ASN no Authority Key Identifier found */
+    ASN_NO_KEYUSAGE     = -223,  /* ASN no Key Usage found */
+    SKID_E              = -224,  /* setting Subject Key Identifier error */
+    AKID_E              = -225,  /* setting Authority Key Identifier error */
+    KEYUSAGE_E          = -226,  /* Bad Key Usage value */
+    CERTPOLICIES_E      = -227,  /* setting Certificate Policies error */
+
+    WC_INIT_E           = -228,  /* wolfcrypt failed to initialize */
+    SIG_VERIFY_E        = -229,  /* wolfcrypt signature verify error */
+    BAD_COND_E          = -230,  /* Bad condition variable operation */
+    SIG_TYPE_E          = -231,  /* Signature Type not enabled/available */
+    HASH_TYPE_E         = -232,  /* Hash Type not enabled/available */
+
+    WC_KEY_SIZE_E       = -234,  /* Key size error, either too small or large */
+    ASN_COUNTRY_SIZE_E  = -235,  /* ASN Cert Gen, invalid country code size */
+    MISSING_RNG_E       = -236,  /* RNG required but not provided */
+    ASN_PATHLEN_SIZE_E  = -237,  /* ASN CA path length too large error */
+    ASN_PATHLEN_INV_E   = -238,  /* ASN CA path length inversion error */
+
+    BAD_KEYWRAP_ALG_E   = -239,
+    BAD_KEYWRAP_IV_E    = -240,  /* Decrypted AES key wrap IV incorrect */
+    WC_CLEANUP_E        = -241,  /* wolfcrypt cleanup failed */
+    ECC_CDH_KAT_FIPS_E  = -242,  /* ECC CDH Known Answer Test failure */
+    DH_CHECK_PUB_E      = -243,  /* DH Check Pub Key error */
+    BAD_PATH_ERROR      = -244,  /* Bad path for opendir */
+
+    ASYNC_OP_E          = -245,  /* Async operation error */
+
+    ECC_PRIVATEONLY_E   = -246,  /* Invalid use of private only ECC key*/
+    EXTKEYUSAGE_E       = -247,  /* Bad Extended Key Usage value */
+    WC_HW_E             = -248,  /* Error with hardware crypto use */
+    WC_HW_WAIT_E        = -249,  /* Hardware waiting on resource */
+
+    PSS_SALTLEN_E       = -250,  /* PSS length of salt is too long for hash */
+    PRIME_GEN_E         = -251,  /* Failure finding a prime. */
+    BER_INDEF_E         = -252,  /* Cannot decode indefinite length BER. */
+    RSA_OUT_OF_RANGE_E  = -253,  /* Ciphertext to decrypt out of range. */
+    RSAPSS_PAT_FIPS_E   = -254,  /* RSA-PSS PAT failure */
+    ECDSA_PAT_FIPS_E    = -255,  /* ECDSA PAT failure */
+    DH_KAT_FIPS_E       = -256,  /* DH KAT failure */
+    AESCCM_KAT_FIPS_E   = -257,  /* AESCCM KAT failure */
+    SHA3_KAT_FIPS_E     = -258,  /* SHA-3 KAT failure */
+    ECDHE_KAT_FIPS_E    = -259,  /* ECDHE KAT failure */
+    AES_GCM_OVERFLOW_E  = -260,  /* AES-GCM invocation counter overflow. */
+    AES_CCM_OVERFLOW_E  = -261,  /* AES-CCM invocation counter overflow. */
+    RSA_KEY_PAIR_E      = -262,  /* RSA Key Pair-Wise Consistency check fail. */
+    DH_CHECK_PRIV_E     = -263,  /* DH Check Priv Key error */
+
+    WC_AFALG_SOCK_E     = -264,  /* AF_ALG socket error */
+    WC_DEVCRYPTO_E      = -265,  /* /dev/crypto error */
+
+    ZLIB_INIT_ERROR     = -266,   /* zlib init error  */
+    ZLIB_COMPRESS_ERROR = -267,   /* zlib compression error  */
+    ZLIB_DECOMPRESS_ERROR = -268,  /* zlib decompression error  */
+
+    PKCS7_NO_SIGNER_E   = -269,  /* No signer in PKCS#7 signed data msg */
+    WC_PKCS7_WANT_READ_E= -270,  /* PKCS7 operations wants more input */
+
+    CRYPTOCB_UNAVAILABLE= -271,  /* Crypto callback unavailable */
+    PKCS7_SIGNEEDS_CHECK= -272,  /* signature needs verified by caller */
+    PSS_SALTLEN_RECOVER_E=-273,  /* PSS slat length not recoverable */
+
+    ASN_SELF_SIGNED_E   = -274, /* ASN self-signed certificate error */
+
+    WC_LAST_E           = -274,  /* Update this to indicate last error */
+    MIN_CODE_E          = -300   /* errors -101 - -299 */
+
+    /* add new companion error id strings for any new error codes
+       wolfcrypt/src/error.c !!! */
+};
+
+
+#ifdef NO_ERROR_STRINGS
+    #define wc_GetErrorString(error) "no support for error strings built in"
+    #define wc_ErrorString(err, buf) \
+        (void)err; XSTRNCPY((buf), wc_GetErrorString((err)), \
+        WOLFSSL_MAX_ERROR_SZ);
+
+#else
+WOLFSSL_API void wc_ErrorString(int err, char* buff);
+WOLFSSL_API const char* wc_GetErrorString(int error);
+#endif
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+#endif /* WOLF_CRYPT_ERROR_H */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/hash.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/hash.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/hash.h	(revision 453)
@@ -0,0 +1,247 @@
+/* hash.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/hash.h
+*/
+
+#ifndef WOLF_CRYPT_HASH_H
+#define WOLF_CRYPT_HASH_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifndef NO_MD5
+    #include <wolfssl/wolfcrypt/md5.h>
+#endif
+#ifndef NO_SHA
+    #include <wolfssl/wolfcrypt/sha.h>
+#endif
+#if defined(WOLFSSL_SHA224) || !defined(NO_SHA256)
+    #include <wolfssl/wolfcrypt/sha256.h>
+#endif
+#if defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512)
+    #include <wolfssl/wolfcrypt/sha512.h>
+#endif
+#ifdef HAVE_BLAKE2
+    #include <wolfssl/wolfcrypt/blake2.h>
+#endif
+#ifdef WOLFSSL_SHA3
+    #include <wolfssl/wolfcrypt/sha3.h>
+#endif
+#ifndef NO_MD4
+    #include <wolfssl/wolfcrypt/md4.h>
+#endif
+#ifdef WOLFSSL_MD2
+    #include <wolfssl/wolfcrypt/md2.h>
+#endif
+#if defined(HAVE_BLAKE2) || defined(HAVE_BLAKE2S)
+    #include <wolfssl/wolfcrypt/blake2.h>
+#endif
+
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+#if !defined(HAVE_FIPS) && !defined(NO_OLD_WC_NAMES)
+    #define MAX_DIGEST_SIZE WC_MAX_DIGEST_SIZE
+#endif
+
+
+/* Supported Message Authentication Codes from page 43 */
+enum wc_MACAlgorithm {
+    no_mac,
+    md5_mac,
+    sha_mac,
+    sha224_mac,
+    sha256_mac,     /* needs to match external KDF_MacAlgorithm */
+    sha384_mac,
+    sha512_mac,
+    rmd_mac,
+    blake2b_mac
+};
+
+enum wc_HashFlags {
+    WC_HASH_FLAG_NONE =     0x00000000,
+    WC_HASH_FLAG_WILLCOPY = 0x00000001, /* flag to indicate hash will be copied */
+    WC_HASH_FLAG_ISCOPY =   0x00000002, /* hash is copy */
+#ifdef WOLFSSL_SHA3
+    WC_HASH_SHA3_KECCAK256 =0x00010000, /* Older KECCAK256 */
+#endif
+};
+
+
+typedef union {
+    #ifndef NO_MD5
+        wc_Md5 md5;
+    #endif
+    #ifndef NO_SHA
+        wc_Sha sha;
+    #endif
+    #ifdef WOLFSSL_SHA224
+        wc_Sha224 sha224;
+    #endif
+    #ifndef NO_SHA256
+        wc_Sha256 sha256;
+    #endif
+    #ifdef WOLFSSL_SHA384
+        wc_Sha384 sha384;
+    #endif
+    #ifdef WOLFSSL_SHA512
+        wc_Sha512 sha512;
+    #endif
+    #ifdef WOLFSSL_SHA3
+        wc_Sha3 sha3;
+    #endif
+} wc_HashAlg;
+
+/* Find largest possible digest size
+   Note if this gets up to the size of 80 or over check smallstack build */
+#if defined(WOLFSSL_SHA3)
+    #define WC_MAX_DIGEST_SIZE WC_SHA3_512_DIGEST_SIZE
+    #define WC_MAX_BLOCK_SIZE  WC_SHA3_224_BLOCK_SIZE /* 224 is the largest block size */
+#elif defined(WOLFSSL_SHA512)
+    #define WC_MAX_DIGEST_SIZE WC_SHA512_DIGEST_SIZE
+    #define WC_MAX_BLOCK_SIZE  WC_SHA512_BLOCK_SIZE
+#elif defined(HAVE_BLAKE2)
+    #define WC_MAX_DIGEST_SIZE BLAKE2B_OUTBYTES
+    #define WC_MAX_BLOCK_SIZE  BLAKE2B_BLOCKBYTES
+#elif defined(WOLFSSL_SHA384)
+    #define WC_MAX_DIGEST_SIZE WC_SHA384_DIGEST_SIZE
+    #define WC_MAX_BLOCK_SIZE  WC_SHA384_BLOCK_SIZE
+#elif !defined(NO_SHA256)
+    #define WC_MAX_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
+    #define WC_MAX_BLOCK_SIZE  WC_SHA256_BLOCK_SIZE
+#elif defined(WOLFSSL_SHA224)
+    #define WC_MAX_DIGEST_SIZE WC_SHA224_DIGEST_SIZE
+    #define WC_MAX_BLOCK_SIZE  WC_SHA224_BLOCK_SIZE
+#elif !defined(NO_SHA)
+    #define WC_MAX_DIGEST_SIZE WC_SHA_DIGEST_SIZE
+    #define WC_MAX_BLOCK_SIZE  WC_SHA_BLOCK_SIZE
+#elif !defined(NO_MD5)
+    #define WC_MAX_DIGEST_SIZE WC_MD5_DIGEST_SIZE
+    #define WC_MAX_BLOCK_SIZE  WC_MD5_BLOCK_SIZE
+#else
+    #define WC_MAX_DIGEST_SIZE 64 /* default to max size of 64 */
+    #define WC_MAX_BLOCK_SIZE  128
+#endif
+
+#if !defined(NO_ASN) || !defined(NO_DH) || defined(HAVE_ECC)
+WOLFSSL_API int wc_HashGetOID(enum wc_HashType hash_type);
+WOLFSSL_API enum wc_HashType wc_OidGetHash(int oid);
+#endif
+
+WOLFSSL_API enum wc_HashType wc_HashTypeConvert(int hashType);
+
+WOLFSSL_API int wc_HashGetDigestSize(enum wc_HashType hash_type);
+WOLFSSL_API int wc_HashGetBlockSize(enum wc_HashType hash_type);
+WOLFSSL_API int wc_Hash(enum wc_HashType hash_type,
+    const byte* data, word32 data_len,
+    byte* hash, word32 hash_len);
+
+/* generic hash operation wrappers */
+WOLFSSL_API int wc_HashInit_ex(wc_HashAlg* hash, enum wc_HashType type,
+    void* heap, int devId);
+WOLFSSL_API int wc_HashInit(wc_HashAlg* hash, enum wc_HashType type);
+WOLFSSL_API int wc_HashUpdate(wc_HashAlg* hash, enum wc_HashType type,
+    const byte* data, word32 dataSz);
+WOLFSSL_API int wc_HashFinal(wc_HashAlg* hash, enum wc_HashType type,
+    byte* out);
+WOLFSSL_API int wc_HashFree(wc_HashAlg* hash, enum wc_HashType type);
+
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+    WOLFSSL_API int wc_HashSetFlags(wc_HashAlg* hash, enum wc_HashType type,
+        word32 flags);
+    WOLFSSL_API int wc_HashGetFlags(wc_HashAlg* hash, enum wc_HashType type,
+        word32* flags);
+#endif
+
+#ifndef NO_MD5
+#include <wolfssl/wolfcrypt/md5.h>
+WOLFSSL_API int wc_Md5Hash(const byte* data, word32 len, byte* hash);
+#endif
+
+#ifndef NO_SHA
+#include <wolfssl/wolfcrypt/sha.h>
+WOLFSSL_API int wc_ShaHash(const byte*, word32, byte*);
+#endif
+
+#ifdef WOLFSSL_SHA224
+#include <wolfssl/wolfcrypt/sha256.h>
+WOLFSSL_API int wc_Sha224Hash(const byte*, word32, byte*);
+#endif /* defined(WOLFSSL_SHA224) */
+
+#ifndef NO_SHA256
+#include <wolfssl/wolfcrypt/sha256.h>
+WOLFSSL_API int wc_Sha256Hash(const byte*, word32, byte*);
+#endif
+
+#ifdef WOLFSSL_SHA384
+#include <wolfssl/wolfcrypt/sha512.h>
+WOLFSSL_API int wc_Sha384Hash(const byte*, word32, byte*);
+#endif /* defined(WOLFSSL_SHA384) */
+
+#ifdef WOLFSSL_SHA512
+#include <wolfssl/wolfcrypt/sha512.h>
+WOLFSSL_API int wc_Sha512Hash(const byte*, word32, byte*);
+#endif /* WOLFSSL_SHA512 */
+
+#ifdef WOLFSSL_SHA3
+#include <wolfssl/wolfcrypt/sha3.h>
+WOLFSSL_API int wc_Sha3_224Hash(const byte*, word32, byte*);
+WOLFSSL_API int wc_Sha3_256Hash(const byte*, word32, byte*);
+WOLFSSL_API int wc_Sha3_384Hash(const byte*, word32, byte*);
+WOLFSSL_API int wc_Sha3_512Hash(const byte*, word32, byte*);
+#ifdef WOLFSSL_SHAKE256
+WOLFSSL_API int wc_Shake256Hash(const byte*, word32, byte*, word32);
+#endif
+#endif /* WOLFSSL_SHA3 */
+
+enum max_prf {
+#ifdef HAVE_FFDHE_8192
+    MAX_PRF_HALF        = 516, /* Maximum half secret len */
+#elif defined(HAVE_FFDHE_6144)
+    MAX_PRF_HALF        = 388, /* Maximum half secret len */
+#else
+    MAX_PRF_HALF        = 260, /* Maximum half secret len */
+#endif
+    MAX_PRF_LABSEED     = 128, /* Maximum label + seed len */
+    MAX_PRF_DIG         = 224  /* Maximum digest len      */
+};
+
+#ifdef WOLFSSL_HAVE_PRF
+WOLFSSL_API int wc_PRF(byte* result, word32 resLen, const byte* secret,
+                    word32 secLen, const byte* seed, word32 seedLen, int hash,
+                    void* heap, int devId);
+WOLFSSL_API int wc_PRF_TLSv1(byte* digest, word32 digLen, const byte* secret,
+                    word32 secLen, const byte* label, word32 labLen,
+                    const byte* seed, word32 seedLen, void* heap, int devId);
+WOLFSSL_API int wc_PRF_TLS(byte* digest, word32 digLen, const byte* secret,
+                    word32 secLen, const byte* label, word32 labLen,
+                    const byte* seed, word32 seedLen, int useAtLeastSha256,
+                    int hash_type, void* heap, int devId);
+#endif /* WOLFSSL_HAVE_PRF */
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* WOLF_CRYPT_HASH_H */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/hc128.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/hc128.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/hc128.h	(revision 453)
@@ -0,0 +1,67 @@
+/* hc128.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/hc128.h
+*/
+
+
+#ifndef WOLF_CRYPT_HC128_H
+#define WOLF_CRYPT_HC128_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifndef NO_HC128
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+enum {
+	HC128_ENC_TYPE =  WC_CIPHER_HC128,     /* cipher unique type */
+};
+
+/* HC-128 stream cipher */
+typedef struct HC128 {
+    word32 T[1024];             /* P[i] = T[i];  Q[i] = T[1024 + i ]; */
+    word32 X[16];
+    word32 Y[16];
+    word32 counter1024;         /* counter1024 = i mod 1024 at the ith step */
+    word32 key[8];
+    word32 iv[8];
+#ifdef XSTREAM_ALIGN
+    void*  heap;  /* heap hint, currently XMALLOC only used with aligning */
+#endif
+} HC128;
+
+
+WOLFSSL_API int wc_Hc128_Process(HC128*, byte*, const byte*, word32);
+WOLFSSL_API int wc_Hc128_SetKey(HC128*, const byte* key, const byte* iv);
+
+WOLFSSL_LOCAL int wc_Hc128_SetHeap(HC128* ctx, void* heap);
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* HAVE_HC128 */
+#endif /* WOLF_CRYPT_HC128_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/hmac.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/hmac.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/hmac.h	(revision 453)
@@ -0,0 +1,207 @@
+/* hmac.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/hmac.h
+*/
+
+#ifndef NO_HMAC
+
+#ifndef WOLF_CRYPT_HMAC_H
+#define WOLF_CRYPT_HMAC_H
+
+#include <wolfssl/wolfcrypt/hash.h>
+
+#if defined(HAVE_FIPS) && \
+	(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
+/* for fips @wc_fips */
+    #include <cyassl/ctaocrypt/hmac.h>
+    #define WC_HMAC_BLOCK_SIZE HMAC_BLOCK_SIZE
+#endif
+
+
+#if defined(HAVE_FIPS) && \
+	defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
+	#include <wolfssl/wolfcrypt/fips.h>
+#endif
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+/* avoid redefinition of structs */
+#if !defined(HAVE_FIPS) || \
+    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    #include <wolfssl/wolfcrypt/async.h>
+#endif
+
+#ifndef NO_OLD_WC_NAMES
+    #define HMAC_BLOCK_SIZE WC_HMAC_BLOCK_SIZE
+#endif
+
+#define WC_HMAC_INNER_HASH_KEYED_SW     1
+#define WC_HMAC_INNER_HASH_KEYED_DEV    2
+
+enum {
+    HMAC_FIPS_MIN_KEY = 14,   /* 112 bit key length minimum */
+
+    IPAD    = 0x36,
+    OPAD    = 0x5C,
+
+/* If any hash is not enabled, add the ID here. */
+#ifdef NO_MD5
+    WC_MD5     = WC_HASH_TYPE_MD5,
+#endif
+#ifdef NO_SHA
+    WC_SHA     = WC_HASH_TYPE_SHA,
+#endif
+#ifdef NO_SHA256
+    WC_SHA256  = WC_HASH_TYPE_SHA256,
+#endif
+#ifndef WOLFSSL_SHA512
+    WC_SHA512  = WC_HASH_TYPE_SHA512,
+#endif
+#ifndef WOLFSSL_SHA384
+    WC_SHA384  = WC_HASH_TYPE_SHA384,
+#endif
+#ifndef WOLFSSL_SHA224
+    WC_SHA224  = WC_HASH_TYPE_SHA224,
+#endif
+#ifndef WOLFSSL_SHA3
+    WC_SHA3_224 = WC_HASH_TYPE_SHA3_224,
+    WC_SHA3_256 = WC_HASH_TYPE_SHA3_256,
+    WC_SHA3_384 = WC_HASH_TYPE_SHA3_384,
+    WC_SHA3_512 = WC_HASH_TYPE_SHA3_512,
+#endif
+#ifdef HAVE_PKCS11
+    HMAC_MAX_ID_LEN = 32,
+#endif
+};
+
+/* Select the largest available hash for the buffer size. */
+#define WC_HMAC_BLOCK_SIZE WC_MAX_BLOCK_SIZE
+
+#if !defined(WOLFSSL_SHA3) && !defined(WOLFSSL_SHA512) && \
+    !defined(WOLFSSL_SHA384) && defined(NO_SHA256) && \
+    defined(WOLFSSL_SHA224) && defined(NO_SHA) && defined(NO_MD5)
+    #error "You have to have some kind of hash if you want to use HMAC."
+#endif
+
+
+/* hash union */
+typedef union {
+#ifndef NO_MD5
+    wc_Md5 md5;
+#endif
+#ifndef NO_SHA
+    wc_Sha sha;
+#endif
+#ifdef WOLFSSL_SHA224
+    wc_Sha224 sha224;
+#endif
+#ifndef NO_SHA256
+    wc_Sha256 sha256;
+#endif
+#ifdef WOLFSSL_SHA384
+    wc_Sha384 sha384;
+#endif
+#ifdef WOLFSSL_SHA512
+    wc_Sha512 sha512;
+#endif
+#ifdef WOLFSSL_SHA3
+    wc_Sha3 sha3;
+#endif
+} Hash;
+
+/* Hmac digest */
+struct Hmac {
+    Hash    hash;
+    word32  ipad[WC_HMAC_BLOCK_SIZE  / sizeof(word32)];  /* same block size all*/
+    word32  opad[WC_HMAC_BLOCK_SIZE  / sizeof(word32)];
+    word32  innerHash[WC_MAX_DIGEST_SIZE / sizeof(word32)];
+    void*   heap;                 /* heap hint */
+    byte    macType;              /* md5 sha or sha256 */
+    byte    innerHashKeyed;       /* keyed flag */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    WC_ASYNC_DEV asyncDev;
+#endif /* WOLFSSL_ASYNC_CRYPT */
+#ifdef WOLF_CRYPTO_CB
+    int     devId;
+    void*   devCtx;
+    const byte* keyRaw;
+#endif
+#ifdef HAVE_PKCS11
+    byte    id[HMAC_MAX_ID_LEN];
+    int     idLen;
+#endif
+#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
+    word16  keyLen;          /* hmac key length (key in ipad) */
+#endif
+};
+
+#ifndef WC_HMAC_TYPE_DEFINED
+    typedef struct Hmac Hmac;
+    #define WC_HMAC_TYPE_DEFINED
+#endif
+
+
+#endif /* HAVE_FIPS */
+
+/* does init */
+WOLFSSL_API int wc_HmacSetKey(Hmac*, int type, const byte* key, word32 keySz);
+WOLFSSL_API int wc_HmacUpdate(Hmac*, const byte*, word32);
+WOLFSSL_API int wc_HmacFinal(Hmac*, byte*);
+WOLFSSL_API int wc_HmacSizeByType(int type);
+
+WOLFSSL_API int wc_HmacInit(Hmac* hmac, void* heap, int devId);
+WOLFSSL_API int wc_HmacInit_Id(Hmac* hmac, byte* id, int len, void* heap,
+                               int devId);
+WOLFSSL_API void wc_HmacFree(Hmac*);
+
+WOLFSSL_API int wolfSSL_GetHmacMaxSize(void);
+
+WOLFSSL_LOCAL int _InitHmac(Hmac* hmac, int type, void* heap);
+
+#ifdef HAVE_HKDF
+
+WOLFSSL_API int wc_HKDF_Extract(int type, const byte* salt, word32 saltSz,
+                                const byte* inKey, word32 inKeySz, byte* out);
+WOLFSSL_API int wc_HKDF_Expand(int type, const byte* inKey, word32 inKeySz,
+                               const byte* info, word32 infoSz,
+                               byte* out,        word32 outSz);
+
+WOLFSSL_API int wc_HKDF(int type, const byte* inKey, word32 inKeySz,
+                    const byte* salt, word32 saltSz,
+                    const byte* info, word32 infoSz,
+                    byte* out, word32 outSz);
+
+#endif /* HAVE_HKDF */
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* WOLF_CRYPT_HMAC_H */
+
+#endif /* NO_HMAC */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/idea.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/idea.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/idea.h	(revision 453)
@@ -0,0 +1,70 @@
+/* idea.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/idea.h
+*/
+
+#ifndef WOLF_CRYPT_IDEA_H
+#define WOLF_CRYPT_IDEA_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifdef HAVE_IDEA
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+enum {
+    IDEA_MODULO     = 0x10001,             /* 2^16+1 */
+    IDEA_2EXP16     = 0x10000,             /* 2^16 */
+    IDEA_MASK       = 0xFFFF,              /* 16 bits set to one */
+    IDEA_ROUNDS     = 8,                   /* number of rounds for IDEA */
+    IDEA_SK_NUM     = (6*IDEA_ROUNDS + 4), /* number of subkeys */
+    IDEA_KEY_SIZE   = 16,                  /* size of key in bytes */
+    IDEA_BLOCK_SIZE = 8,                   /* size of IDEA blocks in bytes */
+    IDEA_IV_SIZE    = 8,                   /* size of IDEA IV in bytes */
+    IDEA_ENCRYPTION = 0,
+    IDEA_DECRYPTION = 1
+};
+
+/* IDEA encryption and decryption */
+typedef struct Idea {
+    word32  reg[IDEA_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */
+    word32  tmp[IDEA_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */
+    word16  skey[IDEA_SK_NUM]; /* 832 bits expanded key */
+} Idea;
+
+WOLFSSL_API int wc_IdeaSetKey(Idea *idea, const byte* key, word16 keySz,
+                              const byte *iv, int dir);
+WOLFSSL_API int wc_IdeaSetIV(Idea *idea, const byte* iv);
+WOLFSSL_API int wc_IdeaCipher(Idea *idea, byte* out, const byte* in);
+WOLFSSL_API int wc_IdeaCbcEncrypt(Idea *idea, byte* out,
+                                  const byte* in, word32 len);
+WOLFSSL_API int wc_IdeaCbcDecrypt(Idea *idea, byte* out,
+                                  const byte* in, word32 len);
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* HAVE_IDEA */
+#endif /* WOLF_CRYPT_IDEA_H */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/integer.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/integer.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/integer.h	(revision 453)
@@ -0,0 +1,409 @@
+/* integer.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+/*
+ * Based on public domain LibTomMath 0.38 by Tom St Denis, tomstdenis@iahu.ca,
+ * http://math.libtomcrypt.com
+ */
+
+
+#ifndef WOLF_CRYPT_INTEGER_H
+#define WOLF_CRYPT_INTEGER_H
+
+/* may optionally use fast math instead, not yet supported on all platforms and
+   may not be faster on all
+*/
+#include <wolfssl/wolfcrypt/types.h>       /* will set MP_xxBIT if not default */
+#ifdef WOLFSSL_SP_MATH
+    #include <wolfssl/wolfcrypt/sp_int.h>
+#elif defined(USE_FAST_MATH)
+    #include <wolfssl/wolfcrypt/tfm.h>
+#else
+
+#include <wolfssl/wolfcrypt/random.h>
+
+#ifndef CHAR_BIT
+    #include <limits.h>
+#endif
+
+#include <wolfssl/wolfcrypt/mpi_class.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+
+/* C++ compilers don't like assigning void * to mp_digit * */
+#define  OPT_CAST(x)  (x *)
+
+#elif defined(_SH3)
+
+/* SuperH SH3 compiler doesn't like assigning voi* to mp_digit* */
+#define  OPT_CAST(x)  (x *)
+
+#else
+
+/* C on the other hand doesn't care */
+#define  OPT_CAST(x)
+
+#endif /* __cplusplus */
+
+
+/* detect 64-bit mode if possible */
+#if defined(__x86_64__) && !(defined (_MSC_VER) && defined(__clang__))
+   #if !(defined(MP_64BIT) && defined(MP_16BIT) && defined(MP_8BIT))
+      #define MP_64BIT
+   #endif
+#endif
+/* if intel compiler doesn't provide 128 bit type don't turn on 64bit */
+#if defined(MP_64BIT) && defined(__INTEL_COMPILER) && !defined(HAVE___UINT128_T)
+    #undef MP_64BIT
+#endif
+
+
+/* allow user to define on mp_digit, mp_word, DIGIT_BIT types */
+#ifndef WOLFSSL_BIGINT_TYPES
+
+/* some default configurations.
+ *
+ * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits
+ * A "mp_word" must be able to hold 2*DIGIT_BIT + 1 bits
+ *
+ * At the very least a mp_digit must be able to hold 7 bits
+ * [any size beyond that is ok provided it doesn't overflow the data type]
+ */
+#ifdef MP_8BIT
+   /* 8-bit */
+   typedef unsigned char      mp_digit;
+   typedef unsigned short     mp_word;
+   /* don't define DIGIT_BIT, so its calculated below */
+#elif defined(MP_16BIT)
+   /* 16-bit */
+   typedef unsigned int       mp_digit;
+   typedef unsigned long      mp_word;
+   /* don't define DIGIT_BIT, so its calculated below */
+#elif defined(NO_64BIT)
+   /* 32-bit forced to 16-bit */
+   typedef unsigned short     mp_digit;
+   typedef unsigned int       mp_word;
+   #define DIGIT_BIT          12
+#elif defined(MP_64BIT)
+   /* 64-bit */
+   /* for GCC only on supported platforms */
+   typedef unsigned long long mp_digit;  /* 64 bit type, 128 uses mode(TI) */
+   typedef unsigned long      mp_word __attribute__ ((mode(TI)));
+   #define DIGIT_BIT          60
+#else
+   /* 32-bit default case */
+
+   #if defined(_MSC_VER) || defined(__BORLANDC__)
+      typedef unsigned __int64   ulong64;
+   #else
+      typedef unsigned long long ulong64;
+   #endif
+
+   typedef unsigned int       mp_digit;  /* long could be 64 now, changed TAO */
+   typedef ulong64            mp_word;
+
+   #ifdef MP_31BIT
+      /* this is an extension that uses 31-bit digits */
+      #define DIGIT_BIT          31
+   #else
+      /* default case is 28-bit digits, defines MP_28BIT as a handy test macro */
+      #define DIGIT_BIT          28
+      #define MP_28BIT
+   #endif
+#endif
+
+#endif /* WOLFSSL_BIGINT_TYPES */
+
+/* otherwise the bits per digit is calculated automatically from the size of
+   a mp_digit */
+#ifndef DIGIT_BIT
+   #define DIGIT_BIT ((int)((CHAR_BIT * sizeof(mp_digit) - 1)))
+      /* bits per digit */
+#endif
+
+#define MP_DIGIT_BIT     DIGIT_BIT
+#define MP_MASK          ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
+#define MP_DIGIT_MAX     MP_MASK
+
+/* equalities */
+#define MP_LT        -1   /* less than */
+#define MP_EQ         0   /* equal to */
+#define MP_GT         1   /* greater than */
+
+#define MP_ZPOS       0   /* positive integer */
+#define MP_NEG        1   /* negative */
+
+#define MP_OKAY       0   /* ok result */
+#define MP_MEM        -2  /* out of mem */
+#define MP_VAL        -3  /* invalid input */
+#define MP_NOT_INF	  -4  /* point not at infinity */
+#define MP_RANGE      MP_NOT_INF
+
+#define MP_YES        1   /* yes response */
+#define MP_NO         0   /* no response */
+
+/* Primality generation flags */
+#define LTM_PRIME_BBS      0x0001 /* BBS style prime */
+#define LTM_PRIME_SAFE     0x0002 /* Safe prime (p-1)/2 == prime */
+#define LTM_PRIME_2MSB_ON  0x0008 /* force 2nd MSB to 1 */
+
+typedef int           mp_err;
+
+/* define this to use lower memory usage routines (exptmods mostly) */
+#define MP_LOW_MEM
+
+/* default precision */
+#ifndef MP_PREC
+   #ifndef MP_LOW_MEM
+      #define MP_PREC                 32     /* default digits of precision */
+   #else
+      #define MP_PREC                 1      /* default digits of precision */
+   #endif
+#endif
+
+/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD -
+   BITS_PER_DIGIT*2) */
+#define MP_WARRAY  ((mp_word)1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1))
+
+#ifdef HAVE_WOLF_BIGINT
+    /* raw big integer */
+    typedef struct WC_BIGINT {
+        byte*   buf;
+        word32  len;
+        void*   heap;
+    } WC_BIGINT;
+    #define WOLF_BIGINT_DEFINED
+#endif
+
+/* the mp_int structure */
+typedef struct mp_int {
+    int used, alloc, sign;
+    mp_digit *dp;
+
+#ifdef HAVE_WOLF_BIGINT
+    struct WC_BIGINT raw; /* unsigned binary (big endian) */
+#endif
+} mp_int;
+
+/* wolf big int and common functions */
+#include <wolfssl/wolfcrypt/wolfmath.h>
+
+
+/* callback for mp_prime_random, should fill dst with random bytes and return
+   how many read [up to len] */
+typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);
+
+
+#define USED(m)    ((m)->used)
+#define DIGIT(m,k) ((m)->dp[(k)])
+#define SIGN(m)    ((m)->sign)
+
+
+/* ---> Basic Manipulations <--- */
+#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
+#define mp_isone(a) \
+    (((((a)->used == 1)) && ((a)->dp[0] == 1u)) ? MP_YES : MP_NO)
+#define mp_iseven(a) \
+    (((a)->used > 0 && (((a)->dp[0] & 1u) == 0u)) ? MP_YES : MP_NO)
+#define mp_isodd(a) \
+    (((a)->used > 0 && (((a)->dp[0] & 1u) == 1u)) ? MP_YES : MP_NO)
+#define mp_isneg(a)  (((a)->sign != MP_ZPOS) ? MP_YES : MP_NO)
+#define mp_isword(a, w) \
+    ((((a)->used == 1) && ((a)->dp[0] == w)) || ((w == 0) && ((a)->used == 0)) \
+                                                               ? MP_YES : MP_NO)
+
+/* number of primes */
+#ifdef MP_8BIT
+   #define PRIME_SIZE      31
+#else
+   #define PRIME_SIZE      256
+#endif
+
+#ifndef MAX_INVMOD_SZ
+    #if defined(WOLFSSL_MYSQL_COMPATIBLE)
+        #define MAX_INVMOD_SZ 8192
+    #else
+        #define MAX_INVMOD_SZ 4096
+    #endif
+#endif
+
+#define mp_prime_random(a, t, size, bbs, cb, dat) \
+   mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat)
+
+#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len))
+#define mp_raw_size(mp)           mp_signed_bin_size(mp)
+#define mp_toraw(mp, str)         mp_to_signed_bin((mp), (str))
+#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len))
+#define mp_mag_size(mp)           mp_unsigned_bin_size(mp)
+#define mp_tomag(mp, str)         mp_to_unsigned_bin((mp), (str))
+
+#define MP_RADIX_BIN  2
+#define MP_RADIX_OCT  8
+#define MP_RADIX_DEC  10
+#define MP_RADIX_HEX  16
+#define MP_RADIX_MAX  64
+
+#define mp_tobinary(M, S)  mp_toradix((M), (S), MP_RADIX_BIN)
+#define mp_tooctal(M, S)   mp_toradix((M), (S), MP_RADIX_OCT)
+#define mp_todecimal(M, S) mp_toradix((M), (S), MP_RADIX_DEC)
+#define mp_tohex(M, S)     mp_toradix((M), (S), MP_RADIX_HEX)
+
+#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1)
+
+#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \
+    defined(WOLFSSL_DEBUG_MATH) || defined(DEBUG_WOLFSSL)
+extern const char *mp_s_rmap;
+#endif
+
+/* 6 functions needed by Rsa */
+MP_API int  mp_init (mp_int * a);
+MP_API void mp_clear (mp_int * a);
+MP_API void mp_free (mp_int * a);
+MP_API void mp_forcezero(mp_int * a);
+MP_API int  mp_unsigned_bin_size(mp_int * a);
+MP_API int  mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c);
+MP_API int  mp_to_unsigned_bin_at_pos(int x, mp_int *t, unsigned char *b);
+MP_API int  mp_to_unsigned_bin (mp_int * a, unsigned char *b);
+MP_API int  mp_to_unsigned_bin_len(mp_int * a, unsigned char *b, int c);
+MP_API int  mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y);
+MP_API int  mp_exptmod_ex (mp_int * G, mp_int * X, int digits, mp_int * P,
+                           mp_int * Y);
+/* end functions needed by Rsa */
+
+/* functions added to support above needed, removed TOOM and KARATSUBA */
+MP_API int  mp_count_bits (mp_int * a);
+MP_API int  mp_leading_bit (mp_int * a);
+MP_API int  mp_init_copy (mp_int * a, mp_int * b);
+MP_API int  mp_copy (mp_int * a, mp_int * b);
+MP_API int  mp_grow (mp_int * a, int size);
+MP_API int  mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d);
+MP_API void mp_zero (mp_int * a);
+MP_API void mp_clamp (mp_int * a);
+MP_API void mp_exch (mp_int * a, mp_int * b);
+MP_API void mp_rshd (mp_int * a, int b);
+MP_API void mp_rshb (mp_int * a, int b);
+MP_API int  mp_mod_2d (mp_int * a, int b, mp_int * c);
+MP_API int  mp_mul_2d (mp_int * a, int b, mp_int * c);
+MP_API int  mp_lshd (mp_int * a, int b);
+MP_API int  mp_abs (mp_int * a, mp_int * b);
+MP_API int  mp_invmod (mp_int * a, mp_int * b, mp_int * c);
+int  fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c);
+MP_API int  mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c);
+MP_API int  mp_cmp_mag (mp_int * a, mp_int * b);
+MP_API int  mp_cmp (mp_int * a, mp_int * b);
+MP_API int  mp_cmp_d(mp_int * a, mp_digit b);
+MP_API int  mp_set (mp_int * a, mp_digit b);
+MP_API int  mp_is_bit_set (mp_int * a, mp_digit b);
+MP_API int  mp_mod (mp_int * a, mp_int * b, mp_int * c);
+MP_API int  mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d);
+MP_API int  mp_div_2(mp_int * a, mp_int * b);
+MP_API int  mp_add (mp_int * a, mp_int * b, mp_int * c);
+int  s_mp_add (mp_int * a, mp_int * b, mp_int * c);
+int  s_mp_sub (mp_int * a, mp_int * b, mp_int * c);
+MP_API int  mp_sub (mp_int * a, mp_int * b, mp_int * c);
+MP_API int  mp_reduce_is_2k_l(mp_int *a);
+MP_API int  mp_reduce_is_2k(mp_int *a);
+MP_API int  mp_dr_is_modulus(mp_int *a);
+MP_API int  mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y,
+                             int);
+MP_API int  mp_exptmod_base_2 (mp_int * X, mp_int * P, mp_int * Y);
+#define mp_exptmod_nct(G,X,P,Y)    mp_exptmod_fast(G,X,P,Y,0)
+MP_API int  mp_montgomery_setup (mp_int * n, mp_digit * rho);
+int  fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho);
+MP_API int  mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho);
+MP_API void mp_dr_setup(mp_int *a, mp_digit *d);
+MP_API int  mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k);
+MP_API int  mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d);
+int  fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs);
+int  s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs);
+MP_API int  mp_reduce_2k_setup_l(mp_int *a, mp_int *d);
+MP_API int  mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d);
+MP_API int  mp_reduce (mp_int * x, mp_int * m, mp_int * mu);
+MP_API int  mp_reduce_setup (mp_int * a, mp_int * b);
+int  s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode);
+MP_API int  mp_montgomery_calc_normalization (mp_int * a, mp_int * b);
+int  s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs);
+int  s_mp_sqr (mp_int * a, mp_int * b);
+int  fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs);
+int  fast_s_mp_sqr (mp_int * a, mp_int * b);
+MP_API int  mp_init_size (mp_int * a, int size);
+MP_API int  mp_div_3 (mp_int * a, mp_int *c, mp_digit * d);
+MP_API int  mp_mul_2(mp_int * a, mp_int * b);
+MP_API int  mp_mul (mp_int * a, mp_int * b, mp_int * c);
+MP_API int  mp_sqr (mp_int * a, mp_int * b);
+MP_API int  mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d);
+MP_API int  mp_submod (mp_int* a, mp_int* b, mp_int* c, mp_int* d);
+MP_API int  mp_addmod (mp_int* a, mp_int* b, mp_int* c, mp_int* d);
+MP_API int  mp_mul_d (mp_int * a, mp_digit b, mp_int * c);
+MP_API int  mp_2expt (mp_int * a, int b);
+MP_API int  mp_set_bit (mp_int * a, int b);
+MP_API int  mp_reduce_2k_setup(mp_int *a, mp_digit *d);
+MP_API int  mp_add_d (mp_int* a, mp_digit b, mp_int* c);
+MP_API int  mp_set_int (mp_int * a, unsigned long b);
+MP_API int  mp_sub_d (mp_int * a, mp_digit b, mp_int * c);
+/* end support added functions */
+
+/* added */
+MP_API int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e,
+                         mp_int* f);
+MP_API int mp_toradix (mp_int *a, char *str, int radix);
+MP_API int mp_radix_size (mp_int * a, int radix, int *size);
+
+#ifdef WOLFSSL_DEBUG_MATH
+    MP_API void mp_dump(const char* desc, mp_int* a, byte verbose);
+#else
+    #define mp_dump(desc, a, verbose)
+#endif
+
+#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) || !defined(NO_RSA) || \
+    !defined(NO_DSA) || !defined(NO_DH)
+    MP_API int mp_sqrmod(mp_int* a, mp_int* b, mp_int* c);
+#endif
+#if !defined(NO_DSA) || defined(HAVE_ECC)
+    MP_API int mp_read_radix(mp_int* a, const char* str, int radix);
+#endif
+
+#if defined(WOLFSSL_KEY_GEN) || !defined(NO_RSA) || !defined(NO_DSA) || !defined(NO_DH)
+    MP_API int mp_prime_is_prime (mp_int * a, int t, int *result);
+    MP_API int mp_prime_is_prime_ex (mp_int * a, int t, int *result, WC_RNG*);
+#endif /* WOLFSSL_KEY_GEN NO_RSA NO_DSA NO_DH */
+#ifdef WOLFSSL_KEY_GEN
+    MP_API int mp_gcd (mp_int * a, mp_int * b, mp_int * c);
+    MP_API int mp_lcm (mp_int * a, mp_int * b, mp_int * c);
+    MP_API int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap);
+#endif
+
+MP_API int mp_cnt_lsb(mp_int *a);
+MP_API int mp_mod_d(mp_int* a, mp_digit b, mp_digit* c);
+
+
+#ifdef __cplusplus
+   }
+#endif
+
+
+#endif /* USE_FAST_MATH */
+
+#endif  /* WOLF_CRYPT_INTEGER_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/logging.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/logging.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/logging.h	(revision 453)
@@ -0,0 +1,194 @@
+/* logging.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/logging.h
+*/
+
+
+/* submitted by eof */
+
+
+#ifndef WOLFSSL_LOGGING_H
+#define WOLFSSL_LOGGING_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+
+enum wc_LogLevels {
+    ERROR_LOG = 0,
+    INFO_LOG,
+    ENTER_LOG,
+    LEAVE_LOG,
+    OTHER_LOG
+};
+
+#ifdef WOLFSSL_FUNC_TIME
+/* WARNING: This code is only to be used for debugging performance.
+ *          The code is not thread-safe.
+ *          Do not use WOLFSSL_FUNC_TIME in production code.
+ */
+enum wc_FuncNum {
+    WC_FUNC_HELLO_REQUEST_SEND = 0,
+    WC_FUNC_HELLO_REQUEST_DO,
+    WC_FUNC_CLIENT_HELLO_SEND,
+    WC_FUNC_CLIENT_HELLO_DO,
+    WC_FUNC_SERVER_HELLO_SEND,
+    WC_FUNC_SERVER_HELLO_DO,
+    WC_FUNC_ENCRYPTED_EXTENSIONS_SEND,
+    WC_FUNC_ENCRYPTED_EXTENSIONS_DO,
+    WC_FUNC_CERTIFICATE_REQUEST_SEND,
+    WC_FUNC_CERTIFICATE_REQUEST_DO,
+    WC_FUNC_CERTIFICATE_SEND,
+    WC_FUNC_CERTIFICATE_DO,
+    WC_FUNC_CERTIFICATE_VERIFY_SEND,
+    WC_FUNC_CERTIFICATE_VERIFY_DO,
+    WC_FUNC_FINISHED_SEND,
+    WC_FUNC_FINISHED_DO,
+    WC_FUNC_KEY_UPDATE_SEND,
+    WC_FUNC_KEY_UPDATE_DO,
+    WC_FUNC_EARLY_DATA_SEND,
+    WC_FUNC_EARLY_DATA_DO,
+    WC_FUNC_NEW_SESSION_TICKET_SEND,
+    WC_FUNC_NEW_SESSION_TICKET_DO,
+    WC_FUNC_SERVER_HELLO_DONE_SEND,
+    WC_FUNC_SERVER_HELLO_DONE_DO,
+    WC_FUNC_TICKET_SEND,
+    WC_FUNC_TICKET_DO,
+    WC_FUNC_CLIENT_KEY_EXCHANGE_SEND,
+    WC_FUNC_CLIENT_KEY_EXCHANGE_DO,
+    WC_FUNC_CERTIFICATE_STATUS_SEND,
+    WC_FUNC_CERTIFICATE_STATUS_DO,
+    WC_FUNC_SERVER_KEY_EXCHANGE_SEND,
+    WC_FUNC_SERVER_KEY_EXCHANGE_DO,
+    WC_FUNC_END_OF_EARLY_DATA_SEND,
+    WC_FUNC_END_OF_EARLY_DATA_DO,
+    WC_FUNC_COUNT
+};
+#endif
+
+typedef void (*wolfSSL_Logging_cb)(const int logLevel,
+                                   const char *const logMessage);
+
+WOLFSSL_API int wolfSSL_SetLoggingCb(wolfSSL_Logging_cb log_function);
+WOLFSSL_API wolfSSL_Logging_cb wolfSSL_GetLoggingCb(void);
+
+/* turn logging on, only if compiled in */
+WOLFSSL_API int  wolfSSL_Debugging_ON(void);
+/* turn logging off */
+WOLFSSL_API void wolfSSL_Debugging_OFF(void);
+
+
+#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
+    WOLFSSL_LOCAL int wc_LoggingInit(void);
+    WOLFSSL_LOCAL int wc_LoggingCleanup(void);
+    WOLFSSL_LOCAL int wc_AddErrorNode(int error, int line, char* buf,
+            char* file);
+    WOLFSSL_LOCAL int wc_PeekErrorNode(int index, const char **file,
+            const char **reason, int *line);
+    WOLFSSL_LOCAL void wc_RemoveErrorNode(int index);
+    WOLFSSL_LOCAL void wc_ClearErrorNodes(void);
+    WOLFSSL_LOCAL int wc_PullErrorNode(const char **file, const char **reason,
+                            int *line);
+    WOLFSSL_API   int wc_SetLoggingHeap(void* h);
+    WOLFSSL_API   int wc_ERR_remove_state(void);
+    #if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)
+        WOLFSSL_API void wc_ERR_print_errors_fp(XFILE fp);
+        WOLFSSL_API void wc_ERR_print_errors_cb(int (*cb)(const char *str,
+                                                size_t len, void *u), void *u);
+    #endif
+#endif /* OPENSSL_EXTRA || DEBUG_WOLFSSL_VERBOSE */
+
+#ifdef WOLFSSL_FUNC_TIME
+    /* WARNING: This code is only to be used for debugging performance.
+     *          The code is not thread-safe.
+     *          Do not use WOLFSSL_FUNC_TIME in production code.
+     */
+    WOLFSSL_API void WOLFSSL_START(int funcNum);
+    WOLFSSL_API void WOLFSSL_END(int funcNum);
+    WOLFSSL_API void WOLFSSL_TIME(int count);
+#else
+    #define WOLFSSL_START(n)
+    #define WOLFSSL_END(n)
+    #define WOLFSSL_TIME(n)
+#endif
+
+#if defined(DEBUG_WOLFSSL) && !defined(WOLFSSL_DEBUG_ERRORS_ONLY)
+    #if defined(_WIN32)
+        #if defined(INTIME_RTOS)
+            #define __func__ NULL
+        #else
+            #define __func__ __FUNCTION__
+        #endif
+    #endif
+
+    /* a is prepended to m and b is appended, creating a log msg a + m + b */
+    #define WOLFSSL_LOG_CAT(a, m, b) #a " " m " "  #b
+
+    WOLFSSL_API void WOLFSSL_ENTER(const char* msg);
+    WOLFSSL_API void WOLFSSL_LEAVE(const char* msg, int ret);
+    #define WOLFSSL_STUB(m) \
+        WOLFSSL_MSG(WOLFSSL_LOG_CAT(wolfSSL Stub, m, not implemented))
+    WOLFSSL_API int WOLFSSL_IS_DEBUG_ON(void);
+
+    WOLFSSL_API void WOLFSSL_MSG(const char* msg);
+    WOLFSSL_API void WOLFSSL_BUFFER(const byte* buffer, word32 length);
+
+#else
+
+    #define WOLFSSL_ENTER(m)
+    #define WOLFSSL_LEAVE(m, r)
+    #define WOLFSSL_STUB(m)
+    #define WOLFSSL_IS_DEBUG_ON() 0
+
+    #define WOLFSSL_MSG(m)
+    #define WOLFSSL_BUFFER(b, l)
+
+#endif /* DEBUG_WOLFSSL && !WOLFSSL_DEBUG_ERRORS_ONLY */
+
+#if defined(DEBUG_WOLFSSL) || defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) ||\
+    defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA)
+
+    #if (!defined(NO_ERROR_QUEUE) && defined(OPENSSL_EXTRA) && !defined(_WIN32))\
+        || defined(DEBUG_WOLFSSL_VERBOSE)
+        WOLFSSL_API void WOLFSSL_ERROR_LINE(int err, const char* func, unsigned int line,
+            const char* file, void* ctx);
+        #define WOLFSSL_ERROR(x) \
+            WOLFSSL_ERROR_LINE((x), __func__, __LINE__, __FILE__, NULL)
+    #else
+        WOLFSSL_API void WOLFSSL_ERROR(int err);
+    #endif
+    WOLFSSL_API void WOLFSSL_ERROR_MSG(const char* msg);
+
+#else
+    #define WOLFSSL_ERROR(e)
+    #define WOLFSSL_ERROR_MSG(m)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* WOLFSSL_LOGGING_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/md2.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/md2.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/md2.h	(revision 453)
@@ -0,0 +1,69 @@
+/* md2.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/md2.h
+*/
+
+
+#ifndef WOLF_CRYPT_MD2_H
+#define WOLF_CRYPT_MD2_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifdef WOLFSSL_MD2
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+/* in bytes */
+enum {
+    MD2             =  WC_HASH_TYPE_MD2,
+    MD2_BLOCK_SIZE  = 16,
+    MD2_DIGEST_SIZE = 16,
+    MD2_PAD_SIZE    = 16,
+    MD2_X_SIZE      = 48
+};
+
+
+/* Md2 digest */
+typedef struct Md2 {
+    word32  count;   /* bytes % PAD_SIZE  */
+    byte    X[MD2_X_SIZE];
+    byte    C[MD2_BLOCK_SIZE];
+    byte    buffer[MD2_BLOCK_SIZE];
+} Md2;
+
+
+WOLFSSL_API void wc_InitMd2(Md2*);
+WOLFSSL_API void wc_Md2Update(Md2*, const byte*, word32);
+WOLFSSL_API void wc_Md2Final(Md2*, byte*);
+WOLFSSL_API int  wc_Md2Hash(const byte*, word32, byte*);
+
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* WOLFSSL_MD2 */
+#endif /* WOLF_CRYPT_MD2_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/md4.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/md4.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/md4.h	(revision 453)
@@ -0,0 +1,67 @@
+/* md4.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/md4.h
+*/
+
+#ifndef WOLF_CRYPT_MD4_H
+#define WOLF_CRYPT_MD4_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifndef NO_MD4
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+/* in bytes */
+enum {
+    MD4             =  WC_HASH_TYPE_MD4,
+    MD4_BLOCK_SIZE  = 64,
+    MD4_DIGEST_SIZE = 16,
+    MD4_PAD_SIZE    = 56
+};
+
+
+/* MD4 digest */
+typedef struct Md4 {
+    word32  buffLen;   /* in bytes          */
+    word32  loLen;     /* length in bytes   */
+    word32  hiLen;     /* length in bytes   */
+    word32  digest[MD4_DIGEST_SIZE / sizeof(word32)];
+    word32  buffer[MD4_BLOCK_SIZE  / sizeof(word32)];
+} Md4;
+
+
+WOLFSSL_API void wc_InitMd4(Md4*);
+WOLFSSL_API void wc_Md4Update(Md4*, const byte*, word32);
+WOLFSSL_API void wc_Md4Final(Md4*, byte*);
+
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* NO_MD4 */
+#endif /* WOLF_CRYPT_MD4_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/md5.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/md5.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/md5.h	(revision 453)
@@ -0,0 +1,130 @@
+/* md5.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/md5.h
+*/
+
+
+#ifndef WOLF_CRYPT_MD5_H
+#define WOLF_CRYPT_MD5_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifndef NO_MD5
+
+#ifdef HAVE_FIPS
+    #define wc_InitMd5   InitMd5
+    #define wc_Md5Update Md5Update
+    #define wc_Md5Final  Md5Final
+    #define wc_Md5Hash   Md5Hash
+#endif
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+#ifndef NO_OLD_WC_NAMES
+    #define Md5             wc_Md5
+    #define MD5             WC_MD5
+    #define MD5_BLOCK_SIZE  WC_MD5_BLOCK_SIZE
+    #define MD5_DIGEST_SIZE WC_MD5_DIGEST_SIZE
+    #define WC_MD5_PAD_SIZE WC_MD5_PAD_SIZE
+#endif
+
+/* in bytes */
+enum {
+    WC_MD5             =  WC_HASH_TYPE_MD5,
+    WC_MD5_BLOCK_SIZE  = 64,
+    WC_MD5_DIGEST_SIZE = 16,
+    WC_MD5_PAD_SIZE    = 56
+};
+
+
+#ifdef WOLFSSL_MICROCHIP_PIC32MZ
+    #include <wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h>
+#endif
+#ifdef STM32_HASH
+    #include <wolfssl/wolfcrypt/port/st/stm32.h>
+#endif
+#ifdef WOLFSSL_ASYNC_CRYPT
+    #include <wolfssl/wolfcrypt/async.h>
+#endif
+
+#ifdef WOLFSSL_TI_HASH
+    #include "wolfssl/wolfcrypt/port/ti/ti-hash.h"
+#elif defined(WOLFSSL_IMX6_CAAM)
+    #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h"
+#else
+
+/* MD5 digest */
+typedef struct wc_Md5 {
+#ifdef STM32_HASH
+    STM32_HASH_Context stmCtx;
+#else
+    word32  buffLen;   /* in bytes          */
+    word32  loLen;     /* length in bytes   */
+    word32  hiLen;     /* length in bytes   */
+    word32  buffer[WC_MD5_BLOCK_SIZE  / sizeof(word32)];
+#ifdef WOLFSSL_PIC32MZ_HASH
+    word32  digest[PIC32_DIGEST_SIZE / sizeof(word32)];
+#else
+    word32  digest[WC_MD5_DIGEST_SIZE / sizeof(word32)];
+#endif
+    void*   heap;
+#ifdef WOLFSSL_PIC32MZ_HASH
+    hashUpdCache cache; /* cache for updates */
+#endif
+#endif /* STM32_HASH */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    WC_ASYNC_DEV asyncDev;
+#endif /* WOLFSSL_ASYNC_CRYPT */
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+    word32 flags; /* enum wc_HashFlags in hash.h */
+#endif
+} wc_Md5;
+
+#endif /* WOLFSSL_TI_HASH */
+
+WOLFSSL_API int wc_InitMd5(wc_Md5*);
+WOLFSSL_API int wc_InitMd5_ex(wc_Md5*, void*, int);
+WOLFSSL_API int wc_Md5Update(wc_Md5*, const byte*, word32);
+WOLFSSL_API int wc_Md5Final(wc_Md5*, byte*);
+WOLFSSL_API void wc_Md5Free(wc_Md5*);
+
+WOLFSSL_API int  wc_Md5GetHash(wc_Md5*, byte*);
+WOLFSSL_API int  wc_Md5Copy(wc_Md5*, wc_Md5*);
+
+#ifdef WOLFSSL_PIC32MZ_HASH
+WOLFSSL_API void wc_Md5SizeSet(wc_Md5* md5, word32 len);
+#endif
+
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+    WOLFSSL_API int wc_Md5SetFlags(wc_Md5* md5, word32 flags);
+    WOLFSSL_API int wc_Md5GetFlags(wc_Md5* md5, word32* flags);
+#endif
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* NO_MD5 */
+#endif /* WOLF_CRYPT_MD5_H */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/memory.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/memory.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/memory.h	(revision 453)
@@ -0,0 +1,233 @@
+/* memory.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+/* submitted by eof */
+
+/*!
+    \file wolfssl/wolfcrypt/memory.h
+*/
+
+#ifndef WOLFSSL_MEMORY_H
+#define WOLFSSL_MEMORY_H
+
+#ifndef STRING_USER
+#include <stdlib.h>
+#endif
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+#ifdef WOLFSSL_FORCE_MALLOC_FAIL_TEST
+    WOLFSSL_API void wolfSSL_SetMemFailCount(int memFailCount);
+#endif
+
+#ifdef WOLFSSL_STATIC_MEMORY
+    #ifdef WOLFSSL_DEBUG_MEMORY
+        typedef void *(*wolfSSL_Malloc_cb)(size_t size, void* heap, int type, const char* func, unsigned int line);
+        typedef void (*wolfSSL_Free_cb)(void *ptr, void* heap, int type, const char* func, unsigned int line);
+        typedef void *(*wolfSSL_Realloc_cb)(void *ptr, size_t size, void* heap, int type, const char* func, unsigned int line);
+        WOLFSSL_API void* wolfSSL_Malloc(size_t size, void* heap, int type, const char* func, unsigned int line);
+        WOLFSSL_API void  wolfSSL_Free(void *ptr, void* heap, int type, const char* func, unsigned int line);
+        WOLFSSL_API void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type, const char* func, unsigned int line);
+    #else
+        typedef void *(*wolfSSL_Malloc_cb)(size_t size, void* heap, int type);
+        typedef void (*wolfSSL_Free_cb)(void *ptr, void* heap, int type);
+        typedef void *(*wolfSSL_Realloc_cb)(void *ptr, size_t size, void* heap, int type);
+        WOLFSSL_API void* wolfSSL_Malloc(size_t size, void* heap, int type);
+        WOLFSSL_API void  wolfSSL_Free(void *ptr, void* heap, int type);
+        WOLFSSL_API void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type);
+    #endif /* WOLFSSL_DEBUG_MEMORY */
+#else
+    #ifdef WOLFSSL_DEBUG_MEMORY
+        typedef void *(*wolfSSL_Malloc_cb)(size_t size, const char* func, unsigned int line);
+        typedef void (*wolfSSL_Free_cb)(void *ptr, const char* func, unsigned int line);
+        typedef void *(*wolfSSL_Realloc_cb)(void *ptr, size_t size, const char* func, unsigned int line);
+
+        /* Public in case user app wants to use XMALLOC/XFREE */
+        WOLFSSL_API void* wolfSSL_Malloc(size_t size, const char* func, unsigned int line);
+        WOLFSSL_API void  wolfSSL_Free(void *ptr, const char* func, unsigned int line);
+        WOLFSSL_API void* wolfSSL_Realloc(void *ptr, size_t size, const char* func, unsigned int line);
+    #else
+        typedef void *(*wolfSSL_Malloc_cb)(size_t size);
+        typedef void (*wolfSSL_Free_cb)(void *ptr);
+        typedef void *(*wolfSSL_Realloc_cb)(void *ptr, size_t size);
+        /* Public in case user app wants to use XMALLOC/XFREE */
+        WOLFSSL_API void* wolfSSL_Malloc(size_t size);
+        WOLFSSL_API void  wolfSSL_Free(void *ptr);
+        WOLFSSL_API void* wolfSSL_Realloc(void *ptr, size_t size);
+    #endif /* WOLFSSL_DEBUG_MEMORY */
+#endif /* WOLFSSL_STATIC_MEMORY */
+
+/* Public get/set functions */
+WOLFSSL_API int wolfSSL_SetAllocators(wolfSSL_Malloc_cb,
+                                      wolfSSL_Free_cb,
+                                      wolfSSL_Realloc_cb);
+WOLFSSL_API int wolfSSL_GetAllocators(wolfSSL_Malloc_cb*,
+                                      wolfSSL_Free_cb*,
+                                      wolfSSL_Realloc_cb*);
+
+#ifdef WOLFSSL_STATIC_MEMORY
+    #define WOLFSSL_STATIC_TIMEOUT 1
+    #ifndef WOLFSSL_STATIC_ALIGN
+        #define WOLFSSL_STATIC_ALIGN 16
+    #endif
+    #ifndef WOLFMEM_MAX_BUCKETS
+        #define WOLFMEM_MAX_BUCKETS  9
+    #endif
+    #define WOLFMEM_DEF_BUCKETS  9     /* number of default memory blocks */
+    #ifndef WOLFMEM_IO_SZ
+        #define WOLFMEM_IO_SZ        16992 /* 16 byte aligned */
+    #endif
+    #ifndef WOLFMEM_BUCKETS
+        #ifndef SESSION_CERTS
+            /* default size of chunks of memory to separate into */
+            #ifndef LARGEST_MEM_BUCKET
+                #define LARGEST_MEM_BUCKET 16128
+            #endif
+            #define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3456,4544,\
+                                    LARGEST_MEM_BUCKET
+        #elif defined (OPENSSL_EXTRA)
+            /* extra storage in structs for multiple attributes and order */
+            #ifndef LARGEST_MEM_BUCKET
+                #define LARGEST_MEM_BUCKET 25600
+            #endif
+            #define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3360,4480,\
+                                    LARGEST_MEM_BUCKET
+        #elif defined (WOLFSSL_CERT_EXT)
+            /* certificate extensions requires 24k for the SSL struct */
+            #ifndef LARGEST_MEM_BUCKET
+                #define LARGEST_MEM_BUCKET 24576
+            #endif
+            #define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3456,4544,\
+                                    LARGEST_MEM_BUCKET
+        #else
+            /* increase 23k for object member of WOLFSSL_X509_NAME_ENTRY */
+            #ifndef LARGEST_MEM_BUCKET
+                #define LARGEST_MEM_BUCKET 23440
+            #endif
+            #define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3456,4544,\
+                                    LARGEST_MEM_BUCKET
+        #endif
+    #endif
+    #ifndef WOLFMEM_DIST
+        #ifndef WOLFSSL_STATIC_MEMORY_SMALL
+            #define WOLFMEM_DIST    49,10,6,14,5,6,9,1,1
+        #else
+            /* Low resource and not RSA */
+            #define WOLFMEM_DIST    29, 7,6, 9,4,4,0,0,0
+        #endif
+    #endif
+
+    /* flags for loading static memory (one hot bit) */
+    #define WOLFMEM_GENERAL       0x01
+    #define WOLFMEM_IO_POOL       0x02
+    #define WOLFMEM_IO_POOL_FIXED 0x04
+    #define WOLFMEM_TRACK_STATS   0x08
+
+    #ifndef WOLFSSL_MEM_GUARD
+    #define WOLFSSL_MEM_GUARD
+        typedef struct WOLFSSL_MEM_STATS      WOLFSSL_MEM_STATS;
+        typedef struct WOLFSSL_MEM_CONN_STATS WOLFSSL_MEM_CONN_STATS;
+    #endif
+
+    struct WOLFSSL_MEM_CONN_STATS {
+        word32 peakMem;   /* peak memory usage    */
+        word32 curMem;    /* current memory usage */
+        word32 peakAlloc; /* peak memory allocations */
+        word32 curAlloc;  /* current memory allocations */
+        word32 totalAlloc;/* total memory allocations for lifetime */
+        word32 totalFr;   /* total frees for lifetime */
+    };
+
+    struct WOLFSSL_MEM_STATS {
+        word32 curAlloc;  /* current memory allocations */
+        word32 totalAlloc;/* total memory allocations for lifetime */
+        word32 totalFr;   /* total frees for lifetime */
+        word32 totalUse;  /* total amount of memory used in blocks */
+        word32 avaIO;     /* available IO specific pools */
+        word32 maxHa;     /* max number of concurrent handshakes allowed */
+        word32 maxIO;     /* max number of concurrent IO connections allowed */
+        word32 blockSz[WOLFMEM_MAX_BUCKETS]; /* block sizes in stacks */
+        word32 avaBlock[WOLFMEM_MAX_BUCKETS];/* ava block sizes */
+        word32 usedBlock[WOLFMEM_MAX_BUCKETS];
+        int    flag; /* flag used */
+    };
+
+    typedef struct wc_Memory wc_Memory; /* internal structure for mem bucket */
+    typedef struct WOLFSSL_HEAP {
+        wc_Memory* ava[WOLFMEM_MAX_BUCKETS];
+        wc_Memory* io;                  /* list of buffers to use for IO */
+        word32     maxHa;               /* max concurrent handshakes */
+        word32     curHa;
+        word32     maxIO;               /* max concurrent IO connections */
+        word32     curIO;
+        word32     sizeList[WOLFMEM_MAX_BUCKETS];/* memory sizes in ava list */
+        word32     distList[WOLFMEM_MAX_BUCKETS];/* general distribution */
+        word32     inUse; /* amount of memory currently in use */
+        word32     ioUse;
+        word32     alloc; /* total number of allocs */
+        word32     frAlc; /* total number of frees  */
+        int        flag;
+        wolfSSL_Mutex memory_mutex;
+    } WOLFSSL_HEAP;
+
+    /* structure passed into XMALLOC as heap hint
+     * having this abstraction allows tracking statistics of individual ssl's
+     */
+    typedef struct WOLFSSL_HEAP_HINT {
+        WOLFSSL_HEAP*           memory;
+        WOLFSSL_MEM_CONN_STATS* stats;  /* hold individual connection stats */
+        wc_Memory*  outBuf; /* set if using fixed io buffers */
+        wc_Memory*  inBuf;
+        byte        haFlag; /* flag used for checking handshake count */
+    } WOLFSSL_HEAP_HINT;
+
+    WOLFSSL_API int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint,
+            unsigned char* buf, unsigned int sz, int flag, int max);
+
+    WOLFSSL_LOCAL int wolfSSL_init_memory_heap(WOLFSSL_HEAP* heap);
+    WOLFSSL_LOCAL int wolfSSL_load_static_memory(byte* buffer, word32 sz,
+                                                  int flag, WOLFSSL_HEAP* heap);
+    WOLFSSL_LOCAL int wolfSSL_GetMemStats(WOLFSSL_HEAP* heap,
+                                                      WOLFSSL_MEM_STATS* stats);
+    WOLFSSL_LOCAL int SetFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io);
+    WOLFSSL_LOCAL int FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io);
+
+    WOLFSSL_API int wolfSSL_StaticBufferSz(byte* buffer, word32 sz, int flag);
+    WOLFSSL_API int wolfSSL_MemoryPaddingSz(void);
+#endif /* WOLFSSL_STATIC_MEMORY */
+
+#ifdef WOLFSSL_STACK_LOG
+    WOLFSSL_API void __attribute__((no_instrument_function))
+            __cyg_profile_func_enter(void *func,  void *caller);
+    WOLFSSL_API void __attribute__((no_instrument_function))
+            __cyg_profile_func_exit(void *func, void *caller);
+#endif /* WOLFSSL_STACK_LOG */
+
+#ifdef __cplusplus
+    }  /* extern "C" */
+#endif
+
+#endif /* WOLFSSL_MEMORY_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/misc.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/misc.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/misc.h	(revision 453)
@@ -0,0 +1,118 @@
+/* misc.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+#ifndef WOLF_CRYPT_MISC_H
+#define WOLF_CRYPT_MISC_H
+
+
+#include <wolfssl/wolfcrypt/types.h>
+
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+
+#ifdef NO_INLINE
+WOLFSSL_LOCAL
+word32 rotlFixed(word32, word32);
+WOLFSSL_LOCAL
+word32 rotrFixed(word32, word32);
+
+WOLFSSL_LOCAL
+word32 ByteReverseWord32(word32);
+WOLFSSL_LOCAL
+void   ByteReverseWords(word32*, const word32*, word32);
+
+WOLFSSL_LOCAL
+void XorWords(wolfssl_word*, const wolfssl_word*, word32);
+WOLFSSL_LOCAL
+void xorbuf(void*, const void*, word32);
+
+WOLFSSL_LOCAL
+void ForceZero(const void*, word32);
+
+WOLFSSL_LOCAL
+int ConstantCompare(const byte*, const byte*, int);
+
+#ifdef WORD64_AVAILABLE
+WOLFSSL_LOCAL
+word64 rotlFixed64(word64, word64);
+WOLFSSL_LOCAL
+word64 rotrFixed64(word64, word64);
+
+WOLFSSL_LOCAL
+word64 ByteReverseWord64(word64);
+WOLFSSL_LOCAL
+void   ByteReverseWords64(word64*, const word64*, word32);
+#endif /* WORD64_AVAILABLE */
+
+#ifndef WOLFSSL_HAVE_MIN
+    #if defined(HAVE_FIPS) && !defined(min) /* so ifdef check passes */
+        #define min min
+    #endif
+    WOLFSSL_LOCAL word32 min(word32 a, word32 b);
+#endif
+
+#ifndef WOLFSSL_HAVE_MAX
+    #if defined(HAVE_FIPS) && !defined(max) /* so ifdef check passes */
+        #define max max
+    #endif
+    WOLFSSL_LOCAL word32 max(word32 a, word32 b);
+#endif /* WOLFSSL_HAVE_MAX */
+
+
+void c32to24(word32 in, word24 out);
+void c16toa(word16 u16, byte* c);
+void c32toa(word32 u32, byte* c);
+void c24to32(const word24 u24, word32* u32);
+void ato16(const byte* c, word16* u16);
+void ato24(const byte* c, word32* u24);
+void ato32(const byte* c, word32* u32);
+word32 btoi(byte b);
+
+
+WOLFSSL_LOCAL byte ctMaskGT(int a, int b);
+WOLFSSL_LOCAL byte ctMaskGTE(int a, int b);
+WOLFSSL_LOCAL int  ctMaskIntGTE(int a, int b);
+WOLFSSL_LOCAL byte ctMaskLT(int a, int b);
+WOLFSSL_LOCAL byte ctMaskLTE(int a, int b);
+WOLFSSL_LOCAL byte ctMaskEq(int a, int b);
+WOLFSSL_LOCAL word16 ctMask16GT(int a, int b);
+WOLFSSL_LOCAL word16 ctMask16LT(int a, int b);
+WOLFSSL_LOCAL word16 ctMask16Eq(int a, int b);
+WOLFSSL_LOCAL byte ctMaskNotEq(int a, int b);
+WOLFSSL_LOCAL byte ctMaskSel(byte m, byte a, byte b);
+WOLFSSL_LOCAL int  ctMaskSelInt(byte m, int a, int b);
+WOLFSSL_LOCAL byte ctSetLTE(int a, int b);
+
+#endif /* NO_INLINE */
+
+
+#ifdef __cplusplus
+    }   /* extern "C" */
+#endif
+
+
+#endif /* WOLF_CRYPT_MISC_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/mpi_class.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/mpi_class.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/mpi_class.h	(revision 453)
@@ -0,0 +1,1021 @@
+/* mpi_class.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+#if !(defined(LTM1) && defined(LTM2) && defined(LTM3))
+#if defined(LTM2)
+#define LTM3
+#endif
+#if defined(LTM1)
+#define LTM2
+#endif
+#define LTM1
+
+#if defined(LTM_ALL)
+#define BN_ERROR_C
+#define BN_FAST_MP_INVMOD_C
+#define BN_FAST_MP_MONTGOMERY_REDUCE_C
+#define BN_FAST_S_MP_MUL_DIGS_C
+#define BN_FAST_S_MP_MUL_HIGH_DIGS_C
+#define BN_FAST_S_MP_SQR_C
+#define BN_MP_2EXPT_C
+#define BN_MP_ABS_C
+#define BN_MP_ADD_C
+#define BN_MP_ADD_D_C
+#define BN_MP_ADDMOD_C
+#define BN_MP_AND_C
+#define BN_MP_CLAMP_C
+#define BN_MP_CLEAR_C
+#define BN_MP_CLEAR_MULTI_C
+#define BN_MP_CMP_C
+#define BN_MP_CMP_D_C
+#define BN_MP_CMP_MAG_C
+#define BN_MP_CNT_LSB_C
+#define BN_MP_COPY_C
+#define BN_MP_COUNT_BITS_C
+#define BN_MP_DIV_C
+#define BN_MP_DIV_2_C
+#define BN_MP_DIV_2D_C
+#define BN_MP_DIV_3_C
+#define BN_MP_DIV_D_C
+#define BN_MP_DR_IS_MODULUS_C
+#define BN_MP_DR_REDUCE_C
+#define BN_MP_DR_SETUP_C
+#define BN_MP_EXCH_C
+#define BN_MP_EXPT_D_C
+#define BN_MP_EXPTMOD_BASE_2
+#define BN_MP_EXPTMOD_C
+#define BN_MP_EXPTMOD_FAST_C
+#define BN_MP_EXTEUCLID_C
+#define BN_MP_FREAD_C
+#define BN_MP_FWRITE_C
+#define BN_MP_GCD_C
+#define BN_MP_GET_INT_C
+#define BN_MP_GROW_C
+#define BN_MP_INIT_C
+#define BN_MP_INIT_COPY_C
+#define BN_MP_INIT_MULTI_C
+#define BN_MP_INIT_SET_C
+#define BN_MP_INIT_SET_INT_C
+#define BN_MP_INIT_SIZE_C
+#define BN_MP_INVMOD_C
+#define BN_MP_INVMOD_SLOW_C
+#define BN_MP_IS_SQUARE_C
+#define BN_MP_JACOBI_C
+#define BN_MP_KARATSUBA_MUL_C
+#define BN_MP_KARATSUBA_SQR_C
+#define BN_MP_LCM_C
+#define BN_MP_LSHD_C
+#define BN_MP_MOD_C
+#define BN_MP_MOD_2D_C
+#define BN_MP_MOD_D_C
+#define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+#define BN_MP_MONTGOMERY_REDUCE_C
+#define BN_MP_MONTGOMERY_SETUP_C
+#define BN_MP_MUL_C
+#define BN_MP_MUL_2_C
+#define BN_MP_MUL_2D_C
+#define BN_MP_MUL_D_C
+#define BN_MP_MULMOD_C
+#define BN_MP_N_ROOT_C
+#define BN_MP_NEG_C
+#define BN_MP_OR_C
+#define BN_MP_PRIME_FERMAT_C
+#define BN_MP_PRIME_IS_DIVISIBLE_C
+#define BN_MP_PRIME_IS_PRIME_C
+#define BN_MP_PRIME_MILLER_RABIN_C
+#define BN_MP_PRIME_NEXT_PRIME_C
+#define BN_MP_PRIME_RABIN_MILLER_TRIALS_C
+#define BN_MP_PRIME_RANDOM_EX_C
+#define BN_MP_RADIX_SIZE_C
+#define BN_MP_RADIX_SMAP_C
+#define BN_MP_RAND_C
+#define BN_MP_READ_RADIX_C
+#define BN_MP_READ_SIGNED_BIN_C
+#define BN_MP_READ_UNSIGNED_BIN_C
+#define BN_MP_REDUCE_C
+#define BN_MP_REDUCE_2K_C
+#define BN_MP_REDUCE_2K_L_C
+#define BN_MP_REDUCE_2K_SETUP_C
+#define BN_MP_REDUCE_2K_SETUP_L_C
+#define BN_MP_REDUCE_IS_2K_C
+#define BN_MP_REDUCE_IS_2K_L_C
+#define BN_MP_REDUCE_SETUP_C
+#define BN_MP_RSHD_C
+#define BN_MP_SET_C
+#define BN_MP_SET_INT_C
+#define BN_MP_SHRINK_C
+#define BN_MP_SIGNED_BIN_SIZE_C
+#define BN_MP_SQR_C
+#define BN_MP_SQRMOD_C
+#define BN_MP_SQRT_C
+#define BN_MP_SUB_C
+#define BN_MP_SUB_D_C
+#define BN_MP_SUBMOD_C
+#define BN_MP_TO_SIGNED_BIN_C
+#define BN_MP_TO_SIGNED_BIN_N_C
+#define BN_MP_TO_UNSIGNED_BIN_C
+#define BN_MP_TO_UNSIGNED_BIN_N_C
+#define BN_MP_TOOM_MUL_C
+#define BN_MP_TOOM_SQR_C
+#define BN_MP_TORADIX_C
+#define BN_MP_TORADIX_N_C
+#define BN_MP_UNSIGNED_BIN_SIZE_C
+#define BN_MP_XOR_C
+#define BN_MP_ZERO_C
+#define BN_PRIME_TAB_C
+#define BN_REVERSE_C
+#define BN_S_MP_ADD_C
+#define BN_S_MP_EXPTMOD_C
+#define BN_S_MP_MUL_DIGS_C
+#define BN_S_MP_MUL_HIGH_DIGS_C
+#define BN_S_MP_SQR_C
+#define BN_S_MP_SUB_C
+#define BNCORE_C
+#endif
+
+#if defined(BN_ERROR_C)
+   #define BN_MP_ERROR_TO_STRING_C
+#endif
+
+#if defined(BN_FAST_MP_INVMOD_C)
+   #define BN_MP_ISEVEN_C
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_COPY_C
+   #define BN_MP_MOD_C
+   #define BN_MP_SET_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_ISODD_C
+   #define BN_MP_SUB_C
+   #define BN_MP_CMP_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_CMP_D_C
+   #define BN_MP_ADD_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_FAST_MP_MONTGOMERY_REDUCE_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_FAST_S_MP_MUL_DIGS_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_FAST_S_MP_SQR_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_2EXPT_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_GROW_C
+#endif
+
+#if defined(BN_MP_ABS_C)
+   #define BN_MP_COPY_C
+#endif
+
+#if defined(BN_MP_ADD_C)
+   #define BN_S_MP_ADD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_ADD_D_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_ADDMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_ADD_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_AND_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_CLAMP_C)
+#endif
+
+#if defined(BN_MP_CLEAR_C)
+#endif
+
+#if defined(BN_MP_CLEAR_MULTI_C)
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_CMP_C)
+   #define BN_MP_CMP_MAG_C
+#endif
+
+#if defined(BN_MP_CMP_D_C)
+#endif
+
+#if defined(BN_MP_CMP_MAG_C)
+#endif
+
+#if defined(BN_MP_CNT_LSB_C)
+   #define BN_MP_ISZERO_C
+#endif
+
+#if defined(BN_MP_COPY_C)
+   #define BN_MP_GROW_C
+#endif
+
+#if defined(BN_MP_COUNT_BITS_C)
+#endif
+
+#if defined(BN_MP_DIV_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_COPY_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_SET_C
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_ABS_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_CMP_C
+   #define BN_MP_SUB_C
+   #define BN_MP_ADD_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_MULTI_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_INIT_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_DIV_2_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_DIV_2D_C)
+   #define BN_MP_COPY_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_INIT_C
+   #define BN_MP_MOD_2D_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_MP_DIV_3_C)
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_DIV_D_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_COPY_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_DIV_3_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_DR_IS_MODULUS_C)
+#endif
+
+#if defined(BN_MP_DR_REDUCE_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_DR_SETUP_C)
+#endif
+
+#if defined(BN_MP_EXCH_C)
+#endif
+
+#if defined(BN_MP_EXPT_D_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_SET_C
+   #define BN_MP_SQR_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MUL_C
+#endif
+
+#if defined(BN_MP_EXPTMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_INVMOD_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_ABS_C
+   #define BN_MP_CLEAR_MULTI_C
+   #define BN_MP_REDUCE_IS_2K_L_C
+   #define BN_S_MP_EXPTMOD_C
+   #define BN_MP_DR_IS_MODULUS_C
+   #define BN_MP_REDUCE_IS_2K_C
+   #define BN_MP_ISODD_C
+   #define BN_MP_EXPTMOD_FAST_C
+   #define BN_MP_EXPTMOD_BASE_2
+#endif
+
+#if defined(BN_MP_EXPTMOD_FAST_C)
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_INIT_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MONTGOMERY_SETUP_C
+   #define BN_FAST_MP_MONTGOMERY_REDUCE_C
+   #define BN_MP_MONTGOMERY_REDUCE_C
+   #define BN_MP_DR_SETUP_C
+   #define BN_MP_DR_REDUCE_C
+   #define BN_MP_REDUCE_2K_SETUP_C
+   #define BN_MP_REDUCE_2K_C
+   #define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+   #define BN_MP_MULMOD_C
+   #define BN_MP_SET_C
+   #define BN_MP_MOD_C
+   #define BN_MP_COPY_C
+   #define BN_MP_SQR_C
+   #define BN_MP_MUL_C
+   #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_MP_EXTEUCLID_C)
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_SET_C
+   #define BN_MP_COPY_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_DIV_C
+   #define BN_MP_MUL_C
+   #define BN_MP_SUB_C
+   #define BN_MP_NEG_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_FREAD_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_S_RMAP_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_CMP_D_C
+#endif
+
+#if defined(BN_MP_FWRITE_C)
+   #define BN_MP_RADIX_SIZE_C
+   #define BN_MP_TORADIX_C
+#endif
+
+#if defined(BN_MP_GCD_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_ABS_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CNT_LSB_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_EXCH_C
+   #define BN_S_MP_SUB_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_GET_INT_C)
+#endif
+
+#if defined(BN_MP_GROW_C)
+#endif
+
+#if defined(BN_MP_INIT_C)
+#endif
+
+#if defined(BN_MP_INIT_COPY_C)
+   #define BN_MP_COPY_C
+#endif
+
+#if defined(BN_MP_INIT_MULTI_C)
+   #define BN_MP_ERR_C
+   #define BN_MP_INIT_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_INIT_SET_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SET_C
+#endif
+
+#if defined(BN_MP_INIT_SET_INT_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SET_INT_C
+#endif
+
+#if defined(BN_MP_INIT_SIZE_C)
+   #define BN_MP_INIT_C
+#endif
+
+#if defined(BN_MP_INVMOD_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_ISODD_C
+   #define BN_FAST_MP_INVMOD_C
+   #define BN_MP_INVMOD_SLOW_C
+#endif
+
+#if defined(BN_MP_INVMOD_SLOW_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_MOD_C
+   #define BN_MP_COPY_C
+   #define BN_MP_ISEVEN_C
+   #define BN_MP_SET_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_ISODD_C
+   #define BN_MP_ADD_C
+   #define BN_MP_SUB_C
+   #define BN_MP_CMP_C
+   #define BN_MP_CMP_D_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_IS_SQUARE_C)
+   #define BN_MP_MOD_D_C
+   #define BN_MP_INIT_SET_INT_C
+   #define BN_MP_MOD_C
+   #define BN_MP_GET_INT_C
+   #define BN_MP_SQRT_C
+   #define BN_MP_SQR_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_JACOBI_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CNT_LSB_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_MOD_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_KARATSUBA_MUL_C)
+   #define BN_MP_MUL_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_SUB_C
+   #define BN_MP_ADD_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_KARATSUBA_SQR_C)
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_SQR_C
+   #define BN_MP_SUB_C
+   #define BN_S_MP_ADD_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_ADD_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_LCM_C)
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_GCD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_DIV_C
+   #define BN_MP_MUL_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_LSHD_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_RSHD_C
+#endif
+
+#if defined(BN_MP_MOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_DIV_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_ADD_C
+   #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_MP_MOD_2D_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_COPY_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_MOD_D_C)
+   #define BN_MP_DIV_D_C
+#endif
+
+#if defined(BN_MP_MONTGOMERY_CALC_NORMALIZATION_C)
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_2EXPT_C
+   #define BN_MP_SET_C
+   #define BN_MP_MUL_2_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_MONTGOMERY_REDUCE_C)
+   #define BN_FAST_MP_MONTGOMERY_REDUCE_C
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_MONTGOMERY_SETUP_C)
+#endif
+
+#if defined(BN_MP_MUL_C)
+   #define BN_MP_TOOM_MUL_C
+   #define BN_MP_KARATSUBA_MUL_C
+   #define BN_FAST_S_MP_MUL_DIGS_C
+   #define BN_S_MP_MUL_C
+   #define BN_S_MP_MUL_DIGS_C
+#endif
+
+#if defined(BN_MP_MUL_2_C)
+   #define BN_MP_GROW_C
+#endif
+
+#if defined(BN_MP_MUL_2D_C)
+   #define BN_MP_COPY_C
+   #define BN_MP_GROW_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_MUL_D_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_MULMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_MUL_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_N_ROOT_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SET_C
+   #define BN_MP_COPY_C
+   #define BN_MP_EXPT_D_C
+   #define BN_MP_MUL_C
+   #define BN_MP_SUB_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_DIV_C
+   #define BN_MP_CMP_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_NEG_C)
+   #define BN_MP_COPY_C
+   #define BN_MP_ISZERO_C
+#endif
+
+#if defined(BN_MP_OR_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_FERMAT_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_INIT_C
+   #define BN_MP_EXPTMOD_C
+   #define BN_MP_CMP_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_IS_DIVISIBLE_C)
+   #define BN_MP_MOD_D_C
+#endif
+
+#if defined(BN_MP_PRIME_IS_PRIME_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_PRIME_IS_DIVISIBLE_C
+   #define BN_MP_INIT_C
+   #define BN_MP_SET_C
+   #define BN_MP_PRIME_MILLER_RABIN_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_MILLER_RABIN_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_CNT_LSB_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_EXPTMOD_C
+   #define BN_MP_CMP_C
+   #define BN_MP_SQRMOD_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_NEXT_PRIME_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_SET_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_ISEVEN_C
+   #define BN_MP_MOD_D_C
+   #define BN_MP_INIT_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_PRIME_MILLER_RABIN_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_RABIN_MILLER_TRIALS_C)
+#endif
+
+#if defined(BN_MP_PRIME_RANDOM_EX_C)
+   #define BN_MP_READ_UNSIGNED_BIN_C
+   #define BN_MP_PRIME_IS_PRIME_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_MUL_2_C
+   #define BN_MP_ADD_D_C
+#endif
+
+#if defined(BN_MP_RADIX_SIZE_C)
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_DIV_D_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_RADIX_SMAP_C)
+   #define BN_MP_S_RMAP_C
+#endif
+
+#if defined(BN_MP_RAND_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_LSHD_C
+#endif
+
+#if defined(BN_MP_READ_RADIX_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_S_RMAP_C
+   #define BN_MP_RADIX_SMAP_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_ISZERO_C
+#endif
+
+#if defined(BN_MP_READ_SIGNED_BIN_C)
+   #define BN_MP_READ_UNSIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_READ_UNSIGNED_BIN_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_REDUCE_C)
+   #define BN_MP_REDUCE_SETUP_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_MUL_C
+   #define BN_S_MP_MUL_HIGH_DIGS_C
+   #define BN_FAST_S_MP_MUL_HIGH_DIGS_C
+   #define BN_MP_MOD_2D_C
+   #define BN_S_MP_MUL_DIGS_C
+   #define BN_MP_SUB_C
+   #define BN_MP_CMP_D_C
+   #define BN_MP_SET_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_ADD_C
+   #define BN_MP_CMP_C
+   #define BN_S_MP_SUB_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_MUL_D_C
+   #define BN_S_MP_ADD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_L_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_MUL_C
+   #define BN_S_MP_ADD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_SETUP_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_2EXPT_C
+   #define BN_MP_CLEAR_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_SETUP_L_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_2EXPT_C
+   #define BN_MP_COUNT_BITS_C
+   #define BN_S_MP_SUB_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_IS_2K_C)
+   #define BN_MP_REDUCE_2K_C
+   #define BN_MP_COUNT_BITS_C
+#endif
+
+#if defined(BN_MP_REDUCE_IS_2K_L_C)
+#endif
+
+#if defined(BN_MP_REDUCE_SETUP_C)
+   #define BN_MP_2EXPT_C
+   #define BN_MP_DIV_C
+#endif
+
+#if defined(BN_MP_RSHD_C)
+   #define BN_MP_ZERO_C
+#endif
+
+#if defined(BN_MP_SET_C)
+   #define BN_MP_ZERO_C
+#endif
+
+#if defined(BN_MP_SET_INT_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_SHRINK_C)
+#endif
+
+#if defined(BN_MP_SIGNED_BIN_SIZE_C)
+   #define BN_MP_UNSIGNED_BIN_SIZE_C
+#endif
+
+#if defined(BN_MP_SQR_C)
+   #define BN_MP_TOOM_SQR_C
+   #define BN_MP_KARATSUBA_SQR_C
+   #define BN_FAST_S_MP_SQR_C
+   #define BN_S_MP_SQR_C
+#endif
+
+#if defined(BN_MP_SQRMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SQR_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_SQRT_C)
+   #define BN_MP_N_ROOT_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_DIV_C
+   #define BN_MP_ADD_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_SUB_C)
+   #define BN_S_MP_ADD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_SUB_D_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_SUBMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SUB_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_TO_SIGNED_BIN_C)
+   #define BN_MP_TO_UNSIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_TO_SIGNED_BIN_N_C)
+   #define BN_MP_SIGNED_BIN_SIZE_C
+   #define BN_MP_TO_SIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_TO_UNSIGNED_BIN_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_TO_UNSIGNED_BIN_N_C)
+   #define BN_MP_UNSIGNED_BIN_SIZE_C
+   #define BN_MP_TO_UNSIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_TOOM_MUL_C)
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_MOD_2D_C
+   #define BN_MP_COPY_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_MUL_C
+   #define BN_MP_MUL_2_C
+   #define BN_MP_ADD_C
+   #define BN_MP_SUB_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_DIV_3_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_TOOM_SQR_C)
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_MOD_2D_C
+   #define BN_MP_COPY_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_SQR_C
+   #define BN_MP_MUL_2_C
+   #define BN_MP_ADD_C
+   #define BN_MP_SUB_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_DIV_3_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_TORADIX_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_DIV_D_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_S_RMAP_C
+#endif
+
+#if defined(BN_MP_TORADIX_N_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_DIV_D_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_S_RMAP_C
+#endif
+
+#if defined(BN_MP_UNSIGNED_BIN_SIZE_C)
+   #define BN_MP_COUNT_BITS_C
+#endif
+
+#if defined(BN_MP_XOR_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_ZERO_C)
+#endif
+
+#if defined(BN_PRIME_TAB_C)
+#endif
+
+#if defined(BN_REVERSE_C)
+#endif
+
+#if defined(BN_S_MP_ADD_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_S_MP_EXPTMOD_C)
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_INIT_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_REDUCE_SETUP_C
+   #define BN_MP_REDUCE_C
+   #define BN_MP_REDUCE_2K_SETUP_L_C
+   #define BN_MP_REDUCE_2K_L_C
+   #define BN_MP_MOD_C
+   #define BN_MP_COPY_C
+   #define BN_MP_SQR_C
+   #define BN_MP_MUL_C
+   #define BN_MP_SET_C
+   #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_S_MP_MUL_DIGS_C)
+   #define BN_FAST_S_MP_MUL_DIGS_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_S_MP_MUL_HIGH_DIGS_C)
+   #define BN_FAST_S_MP_MUL_HIGH_DIGS_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_S_MP_SQR_C)
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_S_MP_SUB_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BNCORE_C)
+#endif
+
+#ifdef LTM3
+#define LTM_LAST
+#endif
+#include "mpi_superclass.h"
+#include "mpi_class.h"
+#else
+#define LTM_LAST
+#endif
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/mpi_superclass.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/mpi_superclass.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/mpi_superclass.h	(revision 453)
@@ -0,0 +1,96 @@
+/* mpi_superclass.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+/* super class file for PK algos */
+
+/* default ... include all MPI */
+#define LTM_ALL
+
+/* RSA only (does not support DH/DSA/ECC) */
+/* #define SC_RSA_1 */
+
+/* For reference.... On an Athlon64 optimizing for speed...
+
+   LTM's mpi.o with all functions [striped] is 142KiB in size.
+
+*/
+
+/* Works for RSA only, mpi.o is 68KiB */
+#ifdef SC_RSA_1
+   #define BN_MP_SHRINK_C
+   #define BN_MP_LCM_C
+   #define BN_MP_PRIME_RANDOM_EX_C
+   #define BN_MP_INVMOD_C
+   #define BN_MP_GCD_C
+   #define BN_MP_MOD_C
+   #define BN_MP_MULMOD_C
+   #define BN_MP_ADDMOD_C
+   #define BN_MP_EXPTMOD_C
+   #define BN_MP_SET_INT_C
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_CLEAR_MULTI_C
+   #define BN_MP_UNSIGNED_BIN_SIZE_C
+   #define BN_MP_TO_UNSIGNED_BIN_C
+   #define BN_MP_MOD_D_C
+   #define BN_MP_PRIME_RABIN_MILLER_TRIALS_C
+   #define BN_REVERSE_C
+   #define BN_PRIME_TAB_C
+
+   /* other modifiers */
+   #define BN_MP_DIV_SMALL                    /* Slower division, not critical */
+
+   /* here we are on the last pass so we turn things off.  The functions classes are still there
+    * but we remove them specifically from the build.  This also invokes tweaks in functions
+    * like removing support for even moduli, etc...
+    */
+#ifdef LTM_LAST
+   #undef  BN_MP_TOOM_MUL_C
+   #undef  BN_MP_TOOM_SQR_C
+   #undef  BN_MP_KARATSUBA_MUL_C
+   #undef  BN_MP_KARATSUBA_SQR_C
+   #undef  BN_MP_REDUCE_C
+   #undef  BN_MP_REDUCE_SETUP_C
+   #undef  BN_MP_DR_IS_MODULUS_C
+   #undef  BN_MP_DR_SETUP_C
+   #undef  BN_MP_DR_REDUCE_C
+   #undef  BN_MP_REDUCE_IS_2K_C
+   #undef  BN_MP_REDUCE_2K_SETUP_C
+   #undef  BN_MP_REDUCE_2K_C
+   #undef  BN_S_MP_EXPTMOD_C
+   #undef  BN_MP_DIV_3_C
+   #undef  BN_S_MP_MUL_HIGH_DIGS_C
+   #undef  BN_FAST_S_MP_MUL_HIGH_DIGS_C
+   #undef  BN_FAST_MP_INVMOD_C
+
+   /* To safely undefine these you have to make sure your RSA key won't exceed the Comba threshold
+    * which is roughly 255 digits [7140 bits for 32-bit machines, 15300 bits for 64-bit machines]
+    * which means roughly speaking you can handle up to 2536-bit RSA keys with these defined without
+    * trouble.
+    */
+   #undef  BN_S_MP_MUL_DIGS_C
+   #undef  BN_S_MP_SQR_C
+   #undef  BN_MP_MONTGOMERY_REDUCE_C
+#endif
+
+#endif
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/pkcs12.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/pkcs12.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/pkcs12.h	(revision 453)
@@ -0,0 +1,72 @@
+/* pkcs12.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifndef WOLF_CRYPT_PKCS12_H
+#define WOLF_CRYPT_PKCS12_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+#ifndef WOLFSSL_TYPES_DEFINED /* do not redeclare from ssl.h */
+    typedef struct WC_PKCS12 WC_PKCS12;
+#endif
+
+typedef struct WC_DerCertList { /* dereferenced in ssl.c */
+    byte* buffer;
+    word32 bufferSz;
+    struct WC_DerCertList* next;
+} WC_DerCertList;
+
+/* default values for creating PKCS12 */
+enum {
+    WC_PKCS12_ITT_DEFAULT = 2048,
+    WC_PKCS12_VERSION_DEFAULT = 3,
+    WC_PKCS12_MAC_DEFAULT = 1,
+};
+
+WOLFSSL_API WC_PKCS12* wc_PKCS12_new(void);
+WOLFSSL_API void wc_PKCS12_free(WC_PKCS12* pkcs12);
+WOLFSSL_API int wc_d2i_PKCS12(const byte* der, word32 derSz, WC_PKCS12* pkcs12);
+WOLFSSL_API int wc_i2d_PKCS12(WC_PKCS12* pkcs12, byte** der, int* derSz);
+WOLFSSL_API int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw,
+        byte** pkey, word32* pkeySz, byte** cert, word32* certSz,
+        WC_DerCertList** ca);
+WOLFSSL_API WC_PKCS12* wc_PKCS12_create(char* pass, word32 passSz,
+        char* name, byte* key, word32 keySz, byte* cert, word32 certSz,
+        WC_DerCertList* ca, int nidKey, int nidCert, int iter, int macIter,
+        int keyType, void* heap);
+
+
+WOLFSSL_LOCAL int wc_PKCS12_SetHeap(WC_PKCS12* pkcs12, void* heap);
+WOLFSSL_LOCAL void* wc_PKCS12_GetHeap(WC_PKCS12* pkcs12);
+
+WOLFSSL_LOCAL void wc_FreeCertList(WC_DerCertList* list, void* heap);
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* WOLF_CRYPT_PKCS12_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/pwdbased.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/pwdbased.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/pwdbased.h	(revision 453)
@@ -0,0 +1,77 @@
+/* pwdbased.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/pwdbased.h
+*/
+
+#ifndef WOLF_CRYPT_PWDBASED_H
+#define WOLF_CRYPT_PWDBASED_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifndef NO_PWDBASED
+
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+/*
+ * hashType renamed to typeH to avoid shadowing global declaration here:
+ * wolfssl/wolfcrypt/asn.h line 173 in enum Oid_Types
+ */
+WOLFSSL_API int wc_PBKDF1_ex(byte* key, int keyLen, byte* iv, int ivLen,
+                      const byte* passwd, int passwdLen, 
+                      const byte* salt, int saltLen, int iterations, 
+                      int hashType, void* heap);
+WOLFSSL_API int wc_PBKDF1(byte* output, const byte* passwd, int pLen,
+                      const byte* salt, int sLen, int iterations, int kLen,
+                      int typeH);
+WOLFSSL_API int wc_PBKDF2_ex(byte* output, const byte* passwd, int pLen,
+                    const byte* salt, int sLen, int iterations, int kLen,
+                    int typeH, void* heap, int devId);
+WOLFSSL_API int wc_PBKDF2(byte* output, const byte* passwd, int pLen,
+                      const byte* salt, int sLen, int iterations, int kLen,
+                      int typeH);
+WOLFSSL_API int wc_PKCS12_PBKDF(byte* output, const byte* passwd, int pLen,
+                            const byte* salt, int sLen, int iterations,
+                            int kLen, int typeH, int purpose);
+WOLFSSL_API int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd,int passLen,
+                       const byte* salt, int saltLen, int iterations, int kLen,
+                       int hashType, int id, void* heap);
+
+#ifdef HAVE_SCRYPT
+WOLFSSL_API int wc_scrypt(byte* output, const byte* passwd, int passLen,
+                          const byte* salt, int saltLen, int cost,
+                          int blockSize, int parallel, int dkLen);
+WOLFSSL_API int wc_scrypt_ex(byte* output, const byte* passwd, int passLen,
+                             const byte* salt, int saltLen, word32 iterations,
+                             int blockSize, int parallel, int dkLen);
+#endif
+
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* NO_PWDBASED */
+#endif /* WOLF_CRYPT_PWDBASED_H */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/rabbit.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/rabbit.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/rabbit.h	(revision 453)
@@ -0,0 +1,73 @@
+/* rabbit.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/rabbit.h
+*/
+
+
+#ifndef WOLF_CRYPT_RABBIT_H
+#define WOLF_CRYPT_RABBIT_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifndef NO_RABBIT
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+
+enum {
+	RABBIT_ENC_TYPE  = 5     /* cipher unique type */
+};
+
+
+/* Rabbit Context */
+typedef struct RabbitCtx {
+    word32 x[8];
+    word32 c[8];
+    word32 carry;
+} RabbitCtx;
+
+
+/* Rabbit stream cipher */
+typedef struct Rabbit {
+    RabbitCtx masterCtx;
+    RabbitCtx workCtx;
+#ifdef XSTREAM_ALIGN
+    void*  heap;  /* heap hint, currently XMALLOC only used with aligning */
+#endif
+} Rabbit;
+
+
+WOLFSSL_API int wc_RabbitProcess(Rabbit*, byte*, const byte*, word32);
+WOLFSSL_API int wc_RabbitSetKey(Rabbit*, const byte* key, const byte* iv);
+
+WOLFSSL_LOCAL int wc_Rabbit_SetHeap(Rabbit* ctx, void* heap);
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* NO_RABBIT */
+#endif /* WOLF_CRYPT_RABBIT_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/random.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/random.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/random.h	(revision 453)
@@ -0,0 +1,250 @@
+/* random.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/random.h
+*/
+
+
+
+#ifndef WOLF_CRYPT_RANDOM_H
+#define WOLF_CRYPT_RANDOM_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#if defined(HAVE_FIPS) && \
+    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
+    #include <wolfssl/wolfcrypt/fips.h>
+#endif /* HAVE_FIPS_VERSION >= 2 */
+
+/* included for fips @wc_fips */
+#if defined(HAVE_FIPS) && \
+        (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
+#include <cyassl/ctaocrypt/random.h>
+#endif
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+ /* Maximum generate block length */
+#ifndef RNG_MAX_BLOCK_LEN
+    #ifdef HAVE_INTEL_QA
+        #define RNG_MAX_BLOCK_LEN (0xFFFFl)
+    #else
+        #define RNG_MAX_BLOCK_LEN (0x10000l)
+    #endif
+#endif
+
+/* Size of the BRBG seed */
+#ifndef DRBG_SEED_LEN
+    #define DRBG_SEED_LEN (440/8)
+#endif
+
+
+#if !defined(CUSTOM_RAND_TYPE)
+    /* To maintain compatibility the default is byte */
+    #define CUSTOM_RAND_TYPE    byte
+#endif
+
+/* make sure Hash DRBG is enabled, unless WC_NO_HASHDRBG is defined
+    or CUSTOM_RAND_GENERATE_BLOCK is defined */
+#if !defined(WC_NO_HASHDRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK)
+    #undef  HAVE_HASHDRBG
+    #define HAVE_HASHDRBG
+    #ifndef WC_RESEED_INTERVAL
+        #define WC_RESEED_INTERVAL (1000000)
+    #endif
+#endif
+
+
+/* avoid redefinition of structs */
+#if !defined(HAVE_FIPS) || \
+    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))
+
+/* RNG supports the following sources (in order):
+ * 1. CUSTOM_RAND_GENERATE_BLOCK: Defines name of function as RNG source and
+ *     bypasses the options below.
+ * 2. HAVE_INTEL_RDRAND: Uses the Intel RDRAND if supported by CPU.
+ * 3. HAVE_HASHDRBG (requires SHA256 enabled): Uses SHA256 based P-RNG
+ *     seeded via wc_GenerateSeed. This is the default source.
+ */
+
+ /* Seed source can be overridden by defining one of these:
+      CUSTOM_RAND_GENERATE_SEED
+      CUSTOM_RAND_GENERATE_SEED_OS
+      CUSTOM_RAND_GENERATE */
+
+
+#if defined(CUSTOM_RAND_GENERATE_BLOCK)
+    /* To use define the following:
+     * #define CUSTOM_RAND_GENERATE_BLOCK myRngFunc
+     * extern int myRngFunc(byte* output, word32 sz);
+     */
+#elif defined(HAVE_HASHDRBG)
+    #ifdef NO_SHA256
+        #error "Hash DRBG requires SHA-256."
+    #endif /* NO_SHA256 */
+    #include <wolfssl/wolfcrypt/sha256.h>
+#elif defined(HAVE_WNR)
+     /* allow whitewood as direct RNG source using wc_GenerateSeed directly */
+#elif defined(HAVE_INTEL_RDRAND)
+    /* Intel RDRAND or RDSEED */
+#elif !defined(WC_NO_RNG)
+    #error No RNG source defined!
+#endif
+
+#ifdef HAVE_WNR
+    #include <wnr.h>
+#endif
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    #include <wolfssl/wolfcrypt/async.h>
+#endif
+
+
+#if defined(USE_WINDOWS_API)
+    #if defined(_WIN64)
+        typedef unsigned __int64 ProviderHandle;
+        /* type HCRYPTPROV, avoid #include <windows.h> */
+    #else
+        typedef unsigned long ProviderHandle;
+    #endif
+#endif
+
+
+/* OS specific seeder */
+typedef struct OS_Seed {
+    #if defined(USE_WINDOWS_API)
+        ProviderHandle handle;
+    #else
+        int fd;
+    #endif
+    #if defined(WOLF_CRYPTO_CB)
+        int devId;
+    #endif
+} OS_Seed;
+
+
+#ifndef WC_RNG_TYPE_DEFINED /* guard on redeclaration */
+    typedef struct WC_RNG WC_RNG;
+    #define WC_RNG_TYPE_DEFINED
+#endif
+
+/* RNG context */
+struct WC_RNG {
+    OS_Seed seed;
+    void* heap;
+#ifdef HAVE_HASHDRBG
+    /* Hash-based Deterministic Random Bit Generator */
+    struct DRBG* drbg;
+#if defined(WOLFSSL_NO_MALLOC) && !defined(WOLFSSL_STATIC_MEMORY)
+    #define DRBG_STRUCT_SZ ((sizeof(word32)*3) + (DRBG_SEED_LEN*2))
+    #ifdef WOLFSSL_SMALL_STACK_CACHE
+        #define DRBG_STRUCT_SZ_SHA256 (sizeof(wc_Sha256))
+    #else
+        #define DRBG_STRUCT_SZ_SHA256 0
+    #endif
+    #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
+        #define DRBG_STRUCT_SZ_ASYNC (sizeof(void*) + sizeof(int))
+    #else
+        #define DRBG_STRUCT_SZ_ASYNC 0
+    #endif
+    byte drbg_data[DRBG_STRUCT_SZ + DRBG_STRUCT_SZ_SHA256 + DRBG_STRUCT_SZ_ASYNC];
+#endif
+    byte status;
+#endif
+#ifdef WOLFSSL_ASYNC_CRYPT
+    WC_ASYNC_DEV asyncDev;
+#endif
+#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
+    int devId;
+#endif
+};
+
+#endif /* NO FIPS or have FIPS v2*/
+
+/* NO_OLD_RNGNAME removes RNG struct name to prevent possible type conflicts,
+ * can't be used with CTaoCrypt FIPS */
+#if !defined(NO_OLD_RNGNAME) && !defined(HAVE_FIPS)
+    #define RNG WC_RNG
+#endif
+
+
+WOLFSSL_LOCAL
+int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz);
+
+
+#ifdef HAVE_WNR
+    /* Whitewood netRandom client library */
+    WOLFSSL_API int  wc_InitNetRandom(const char*, wnr_hmac_key, int);
+    WOLFSSL_API int  wc_FreeNetRandom(void);
+#endif /* HAVE_WNR */
+
+
+WOLFSSL_ABI WOLFSSL_API WC_RNG* wc_rng_new(byte*, word32, void*);
+WOLFSSL_ABI WOLFSSL_API void wc_rng_free(WC_RNG*);
+
+
+#ifndef WC_NO_RNG
+WOLFSSL_API int  wc_InitRng(WC_RNG*);
+WOLFSSL_API int  wc_InitRng_ex(WC_RNG* rng, void* heap, int devId);
+WOLFSSL_API int  wc_InitRngNonce(WC_RNG* rng, byte* nonce, word32 nonceSz);
+WOLFSSL_API int  wc_InitRngNonce_ex(WC_RNG* rng, byte* nonce, word32 nonceSz,
+                                    void* heap, int devId);
+WOLFSSL_ABI WOLFSSL_API int wc_RNG_GenerateBlock(WC_RNG*, byte*, word32 sz);
+WOLFSSL_API int  wc_RNG_GenerateByte(WC_RNG*, byte*);
+WOLFSSL_API int  wc_FreeRng(WC_RNG*);
+#else
+#include <wolfssl/wolfcrypt/error-crypt.h>
+#define wc_InitRng(rng) NOT_COMPILED_IN
+#define wc_InitRng_ex(rng, h, d) NOT_COMPILED_IN
+#define wc_InitRngNonce(rng, n, s) NOT_COMPILED_IN
+#define wc_InitRngNonce_ex(rng, n, s, h, d) NOT_COMPILED_IN
+#define wc_RNG_GenerateBlock(rng, b, s) NOT_COMPILED_IN
+#define wc_RNG_GenerateByte(rng, b) NOT_COMPILED_IN
+#define wc_FreeRng(rng) (void)NOT_COMPILED_IN
+#endif
+
+
+
+#ifdef HAVE_HASHDRBG
+    WOLFSSL_LOCAL int wc_RNG_DRBG_Reseed(WC_RNG* rng, const byte* entropy,
+                                        word32 entropySz);
+    WOLFSSL_API int wc_RNG_TestSeed(const byte* seed, word32 seedSz);
+    WOLFSSL_API int wc_RNG_HealthTest(int reseed,
+                                        const byte* entropyA, word32 entropyASz,
+                                        const byte* entropyB, word32 entropyBSz,
+                                        byte* output, word32 outputSz);
+    WOLFSSL_API int wc_RNG_HealthTest_ex(int reseed,
+                                        const byte* nonce, word32 nonceSz,
+                                        const byte* entropyA, word32 entropyASz,
+                                        const byte* entropyB, word32 entropyBSz,
+                                        byte* output, word32 outputSz,
+                                        void* heap, int devId);
+#endif /* HAVE_HASHDRBG */
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* WOLF_CRYPT_RANDOM_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/ripemd.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/ripemd.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/ripemd.h	(revision 453)
@@ -0,0 +1,67 @@
+/* ripemd.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/ripemd.h
+*/
+
+#ifndef WOLF_CRYPT_RIPEMD_H
+#define WOLF_CRYPT_RIPEMD_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifdef WOLFSSL_RIPEMD
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+
+/* in bytes */
+enum {
+    RIPEMD             =  3,    /* hash type unique */
+    RIPEMD_BLOCK_SIZE  = 64,
+    RIPEMD_DIGEST_SIZE = 20,
+    RIPEMD_PAD_SIZE    = 56
+};
+
+
+/* RipeMd 160 digest */
+typedef struct RipeMd {
+    word32  buffLen;   /* in bytes          */
+    word32  loLen;     /* length in bytes   */
+    word32  hiLen;     /* length in bytes   */
+    word32  digest[RIPEMD_DIGEST_SIZE / sizeof(word32)];
+    word32  buffer[RIPEMD_BLOCK_SIZE  / sizeof(word32)];
+} RipeMd;
+
+
+WOLFSSL_API int wc_InitRipeMd(RipeMd*);
+WOLFSSL_API int wc_RipeMdUpdate(RipeMd*, const byte*, word32);
+WOLFSSL_API int wc_RipeMdFinal(RipeMd*, byte*);
+
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* WOLFSSL_RIPEMD */
+#endif /* WOLF_CRYPT_RIPEMD_H */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/rsa.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/rsa.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/rsa.h	(revision 453)
@@ -0,0 +1,371 @@
+/* rsa.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/rsa.h
+*/
+
+
+#ifndef WOLF_CRYPT_RSA_H
+#define WOLF_CRYPT_RSA_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifndef NO_RSA
+
+
+/* RSA default exponent */
+#ifndef WC_RSA_EXPONENT
+    #define WC_RSA_EXPONENT 65537L
+#endif
+
+#if defined(WC_RSA_NONBLOCK)
+    /* enable support for fast math based non-blocking exptmod */
+    /* this splits the RSA function into many smaller operations */
+    #ifndef USE_FAST_MATH
+        #error RSA non-blocking mode only supported using fast math
+    #endif
+    #ifndef TFM_TIMING_RESISTANT
+      #error RSA non-blocking mode only supported with timing resistance enabled
+    #endif
+
+    /* RSA bounds check is not supported with RSA non-blocking mode */
+    #undef  NO_RSA_BOUNDS_CHECK
+    #define NO_RSA_BOUNDS_CHECK
+#endif
+
+/* allow for user to plug in own crypto */
+#if !defined(HAVE_FIPS) && (defined(HAVE_USER_RSA) || defined(HAVE_FAST_RSA))
+    #include "user_rsa.h"
+#else
+
+#if defined(HAVE_FIPS) && \
+	(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
+/* for fips @wc_fips */
+#include <cyassl/ctaocrypt/rsa.h>
+#if defined(CYASSL_KEY_GEN) && !defined(WOLFSSL_KEY_GEN)
+    #define WOLFSSL_KEY_GEN
+#endif
+#else
+    #include <wolfssl/wolfcrypt/integer.h>
+    #include <wolfssl/wolfcrypt/random.h>
+#endif /* HAVE_FIPS && HAVE_FIPS_VERION 1 */
+#if defined(HAVE_FIPS) && \
+	defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
+#include <wolfssl/wolfcrypt/fips.h>
+#endif
+
+/* header file needed for OAEP padding */
+#include <wolfssl/wolfcrypt/hash.h>
+
+#ifdef WOLFSSL_XILINX_CRYPT
+#include "xsecure_rsa.h"
+#endif
+
+#if defined(WOLFSSL_CRYPTOCELL)
+    #include <wolfssl/wolfcrypt/port/arm/cryptoCell.h>
+#endif
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+enum {
+    RSA_MIN_SIZE = 512,
+    RSA_MAX_SIZE = 4096,
+};
+
+/* avoid redefinition of structs */
+#if !defined(HAVE_FIPS) || \
+    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    #include <wolfssl/wolfcrypt/async.h>
+    #ifdef WOLFSSL_CERT_GEN
+        #include <wolfssl/wolfcrypt/asn.h>
+    #endif
+#endif
+
+enum {
+    RSA_PUBLIC   = 0,
+    RSA_PRIVATE  = 1,
+
+    RSA_TYPE_UNKNOWN    = -1,
+    RSA_PUBLIC_ENCRYPT  = 0,
+    RSA_PUBLIC_DECRYPT  = 1,
+    RSA_PRIVATE_ENCRYPT = 2,
+    RSA_PRIVATE_DECRYPT = 3,
+
+    RSA_BLOCK_TYPE_1 = 1,
+    RSA_BLOCK_TYPE_2 = 2,
+
+    RSA_MIN_PAD_SZ   = 11,     /* separator + 0 + pad value + 8 pads */
+
+    RSA_PSS_PAD_SZ = 8,
+    RSA_PSS_SALT_MAX_SZ = 62,
+
+#ifdef OPENSSL_EXTRA
+    RSA_PKCS1_PADDING_SIZE = 11,
+    RSA_PKCS1_OAEP_PADDING_SIZE = 42, /* (2 * hashlen(SHA-1)) + 2 */
+#endif
+#ifdef WC_RSA_PSS
+    RSA_PSS_PAD_TERM = 0xBC,
+#endif
+
+    RSA_PSS_SALT_LEN_DEFAULT  = -1,
+#ifdef WOLFSSL_PSS_SALT_LEN_DISCOVER
+    RSA_PSS_SALT_LEN_DISCOVER = -2,
+#endif
+
+#ifdef HAVE_PKCS11
+    RSA_MAX_ID_LEN      = 32,
+#endif
+};
+
+#ifdef WC_RSA_NONBLOCK
+typedef struct RsaNb {
+    exptModNb_t exptmod; /* non-block expt_mod */
+    mp_int tmp;
+} RsaNb;
+#endif
+
+/* RSA */
+struct RsaKey {
+    mp_int n, e;
+#ifndef WOLFSSL_RSA_PUBLIC_ONLY
+    mp_int d, p, q;
+#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM)
+    mp_int dP, dQ, u;
+#endif
+#endif
+    void* heap;                               /* for user memory overrides */
+    byte* data;                               /* temp buffer for async RSA */
+    int   type;                               /* public or private */
+    int   state;
+    word32 dataLen;
+#ifdef WC_RSA_BLINDING
+    WC_RNG* rng;                              /* for PrivateDecrypt blinding */
+#endif
+#ifdef WOLF_CRYPTO_CB
+    int   devId;
+#endif
+#ifdef WOLFSSL_ASYNC_CRYPT
+    WC_ASYNC_DEV asyncDev;
+    #ifdef WOLFSSL_CERT_GEN
+        CertSignCtx certSignCtx; /* context info for cert sign (MakeSignature) */
+    #endif
+#endif /* WOLFSSL_ASYNC_CRYPT */
+#ifdef WOLFSSL_XILINX_CRYPT
+    word32 pubExp; /* to keep values in scope they are here in struct */
+    byte*  mod;
+    XSecure_Rsa xRsa;
+#endif
+#ifdef HAVE_PKCS11
+    byte id[RSA_MAX_ID_LEN];
+    int  idLen;
+#endif
+#if defined(WOLFSSL_ASYNC_CRYPT) || !defined(WOLFSSL_RSA_VERIFY_INLINE)
+    byte   dataIsAlloc;
+#endif
+#ifdef WC_RSA_NONBLOCK
+    RsaNb* nb;
+#endif
+#ifdef WOLFSSL_AFALG_XILINX_RSA
+    int alFd;
+    int rdFd;
+#endif
+#if defined(WOLFSSL_CRYPTOCELL)
+    rsa_context_t ctx;
+#endif
+};
+
+#ifndef WC_RSAKEY_TYPE_DEFINED
+    typedef struct RsaKey RsaKey;
+    #define WC_RSAKEY_TYPE_DEFINED
+#endif
+
+#endif /*HAVE_FIPS */
+
+WOLFSSL_API int  wc_InitRsaKey(RsaKey* key, void* heap);
+WOLFSSL_API int  wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId);
+WOLFSSL_API int  wc_FreeRsaKey(RsaKey* key);
+#ifdef HAVE_PKCS11
+WOLFSSL_API int wc_InitRsaKey_Id(RsaKey* key, unsigned char* id, int len,
+                                 void* heap, int devId);
+#endif
+WOLFSSL_API int  wc_CheckRsaKey(RsaKey* key);
+#ifdef WOLFSSL_XILINX_CRYPT
+WOLFSSL_LOCAL int wc_InitRsaHw(RsaKey* key);
+#endif /* WOLFSSL_XILINX_CRYPT */
+
+WOLFSSL_API int  wc_RsaFunction(const byte* in, word32 inLen, byte* out,
+                           word32* outLen, int type, RsaKey* key, WC_RNG* rng);
+
+WOLFSSL_API int  wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out,
+                                 word32 outLen, RsaKey* key, WC_RNG* rng);
+WOLFSSL_API int  wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out,
+                                        RsaKey* key);
+WOLFSSL_API int  wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out,
+                                  word32 outLen, RsaKey* key);
+WOLFSSL_API int  wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out,
+                            word32 outLen, RsaKey* key, WC_RNG* rng);
+WOLFSSL_API int  wc_RsaPSS_Sign(const byte* in, word32 inLen, byte* out,
+                                word32 outLen, enum wc_HashType hash, int mgf,
+                                RsaKey* key, WC_RNG* rng);
+WOLFSSL_API int  wc_RsaPSS_Sign_ex(const byte* in, word32 inLen, byte* out,
+                                   word32 outLen, enum wc_HashType hash,
+                                   int mgf, int saltLen, RsaKey* key,
+                                   WC_RNG* rng);
+WOLFSSL_API int  wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out,
+                                    RsaKey* key);
+WOLFSSL_API int  wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out,
+                              word32 outLen, RsaKey* key);
+WOLFSSL_API int  wc_RsaSSL_Verify_ex(const byte* in, word32 inLen, byte* out,
+                              word32 outLen, RsaKey* key, int pad_type);
+WOLFSSL_API int  wc_RsaPSS_VerifyInline(byte* in, word32 inLen, byte** out,
+                                        enum wc_HashType hash, int mgf,
+                                        RsaKey* key);
+WOLFSSL_API int  wc_RsaPSS_VerifyInline_ex(byte* in, word32 inLen, byte** out,
+                                           enum wc_HashType hash, int mgf,
+                                           int saltLen, RsaKey* key);
+WOLFSSL_API int  wc_RsaPSS_Verify(byte* in, word32 inLen, byte* out,
+                                  word32 outLen, enum wc_HashType hash, int mgf,
+                                  RsaKey* key);
+WOLFSSL_API int  wc_RsaPSS_Verify_ex(byte* in, word32 inLen, byte* out,
+                                     word32 outLen, enum wc_HashType hash,
+                                     int mgf, int saltLen, RsaKey* key);
+WOLFSSL_API int  wc_RsaPSS_CheckPadding(const byte* in, word32 inLen, byte* sig,
+                                        word32 sigSz,
+                                        enum wc_HashType hashType);
+WOLFSSL_API int  wc_RsaPSS_CheckPadding_ex(const byte* in, word32 inLen,
+                                           byte* sig, word32 sigSz,
+                                           enum wc_HashType hashType,
+                                           int saltLen, int bits);
+WOLFSSL_API int  wc_RsaPSS_VerifyCheckInline(byte* in, word32 inLen, byte** out,
+                               const byte* digest, word32 digentLen,
+                               enum wc_HashType hash, int mgf,
+                               RsaKey* key);
+WOLFSSL_API int  wc_RsaPSS_VerifyCheck(byte* in, word32 inLen,
+                               byte* out, word32 outLen,
+                               const byte* digest, word32 digestLen,
+                               enum wc_HashType hash, int mgf,
+                               RsaKey* key);
+
+WOLFSSL_API int  wc_RsaEncryptSize(RsaKey* key);
+
+#if !defined(HAVE_FIPS) || \
+	(defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))
+/* to avoid asn duplicate symbols @wc_fips */
+WOLFSSL_API int  wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx,
+                                                               RsaKey*, word32);
+WOLFSSL_API int  wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx,
+                                                               RsaKey*, word32);
+WOLFSSL_API int  wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz,
+                                        const byte* e, word32 eSz, RsaKey* key);
+WOLFSSL_API int wc_RsaKeyToDer(RsaKey*, byte* output, word32 inLen);
+
+
+#ifdef WC_RSA_BLINDING
+    WOLFSSL_API int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng);
+#endif
+#ifdef WC_RSA_NONBLOCK
+    WOLFSSL_API int wc_RsaSetNonBlock(RsaKey* key, RsaNb* nb);
+    #ifdef WC_RSA_NONBLOCK_TIME
+    WOLFSSL_API int wc_RsaSetNonBlockTime(RsaKey* key, word32 maxBlockUs,
+                                          word32 cpuMHz);
+    #endif
+#endif
+
+/*
+   choice of padding added after fips, so not available when using fips RSA
+ */
+
+/* Mask Generation Function Identifiers */
+#define WC_MGF1NONE   0
+#define WC_MGF1SHA1   26
+#define WC_MGF1SHA224 4
+#define WC_MGF1SHA256 1
+#define WC_MGF1SHA384 2
+#define WC_MGF1SHA512 3
+
+/* Padding types */
+#define WC_RSA_PKCSV15_PAD 0
+#define WC_RSA_OAEP_PAD    1
+#define WC_RSA_PSS_PAD     2
+#define WC_RSA_NO_PAD      3
+
+WOLFSSL_API int  wc_RsaPublicEncrypt_ex(const byte* in, word32 inLen, byte* out,
+                   word32 outLen, RsaKey* key, WC_RNG* rng, int type,
+                   enum wc_HashType hash, int mgf, byte* label, word32 lableSz);
+WOLFSSL_API int  wc_RsaPrivateDecrypt_ex(const byte* in, word32 inLen,
+                   byte* out, word32 outLen, RsaKey* key, int type,
+                   enum wc_HashType hash, int mgf, byte* label, word32 lableSz);
+WOLFSSL_API int  wc_RsaPrivateDecryptInline_ex(byte* in, word32 inLen,
+                      byte** out, RsaKey* key, int type, enum wc_HashType hash,
+                      int mgf, byte* label, word32 lableSz);
+#if defined(WC_RSA_DIRECT) || defined(WC_RSA_NO_PADDING)
+WOLFSSL_API int wc_RsaDirect(byte* in, word32 inLen, byte* out, word32* outSz,
+                   RsaKey* key, int type, WC_RNG* rng);
+#endif
+
+#endif /* HAVE_FIPS */
+
+WOLFSSL_API int  wc_RsaFlattenPublicKey(RsaKey*, byte*, word32*, byte*,
+                                                                       word32*);
+WOLFSSL_API int wc_RsaExportKey(RsaKey* key,
+                                byte* e, word32* eSz,
+                                byte* n, word32* nSz,
+                                byte* d, word32* dSz,
+                                byte* p, word32* pSz,
+                                byte* q, word32* qSz);
+
+WOLFSSL_API int wc_RsaKeyToPublicDer(RsaKey*, byte* output, word32 inLen);
+
+#ifdef WOLFSSL_KEY_GEN
+    WOLFSSL_API int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng);
+    WOLFSSL_API int wc_CheckProbablePrime_ex(const byte* p, word32 pSz,
+                                          const byte* q, word32 qSz,
+                                          const byte* e, word32 eSz,
+                                          int nlen, int* isPrime, WC_RNG* rng);
+    WOLFSSL_API int wc_CheckProbablePrime(const byte* p, word32 pSz,
+                                          const byte* q, word32 qSz,
+                                          const byte* e, word32 eSz,
+                                          int nlen, int* isPrime);
+#endif
+
+WOLFSSL_LOCAL int wc_RsaPad_ex(const byte* input, word32 inputLen, byte* pkcsBlock,
+        word32 pkcsBlockLen, byte padValue, WC_RNG* rng, int padType,
+        enum wc_HashType hType, int mgf, byte* optLabel, word32 labelLen,
+        int saltLen, int bits, void* heap);
+WOLFSSL_LOCAL int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** out,
+                                   byte padValue, int padType, enum wc_HashType hType,
+                                   int mgf, byte* optLabel, word32 labelLen, int saltLen,
+                                   int bits, void* heap);
+
+#endif /* HAVE_USER_RSA */
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* NO_RSA */
+#endif /* WOLF_CRYPT_RSA_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/settings.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/settings.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/settings.h	(revision 453)
@@ -0,0 +1,2195 @@
+/* settings.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+/* Place OS specific preprocessor flags, defines, includes here, will be
+   included into every file because types.h includes it */
+
+
+#ifndef WOLF_CRYPT_SETTINGS_H
+#define WOLF_CRYPT_SETTINGS_H
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+/* This flag allows wolfSSL to include options.h instead of having client
+ * projects do it themselves. This should *NEVER* be defined when building
+ * wolfSSL as it can cause hard to debug problems. */
+#ifdef EXTERNAL_OPTS_OPENVPN
+#include <wolfssl/options.h>
+#endif
+
+/* Uncomment next line if using IPHONE */
+/* #define IPHONE */
+
+/* Uncomment next line if using ThreadX */
+/* #define THREADX */
+
+/* Uncomment next line if using Micrium uC/OS-III */
+/* #define MICRIUM */
+
+/* Uncomment next line if using Deos RTOS*/
+/* #define WOLFSSL_DEOS*/
+
+/* Uncomment next line if using Mbed */
+/* #define MBED */
+
+/* Uncomment next line if using Microchip PIC32 ethernet starter kit */
+/* #define MICROCHIP_PIC32 */
+
+/* Uncomment next line if using Microchip TCP/IP stack, version 5 */
+/* #define MICROCHIP_TCPIP_V5 */
+
+/* Uncomment next line if using Microchip TCP/IP stack, version 6 or later */
+/* #define MICROCHIP_TCPIP */
+
+/* Uncomment next line if using PIC32MZ Crypto Engine */
+/* #define WOLFSSL_MICROCHIP_PIC32MZ */
+
+/* Uncomment next line if using FreeRTOS */
+/* #define FREERTOS */
+
+/* Uncomment next line if using FreeRTOS+ TCP */
+/* #define FREERTOS_TCP */
+
+/* Uncomment next line if using FreeRTOS Windows Simulator */
+/* #define FREERTOS_WINSIM */
+
+/* Uncomment next line if using RTIP */
+/* #define EBSNET */
+
+/* Uncomment next line if using lwip */
+/* #define WOLFSSL_LWIP */
+
+/* Uncomment next line if building wolfSSL for a game console */
+/* #define WOLFSSL_GAME_BUILD */
+
+/* Uncomment next line if building wolfSSL for LSR */
+/* #define WOLFSSL_LSR */
+
+/* Uncomment next line if building for Freescale Classic MQX version 5.0 */
+/* #define FREESCALE_MQX_5_0 */
+
+/* Uncomment next line if building for Freescale Classic MQX version 4.0 */
+/* #define FREESCALE_MQX_4_0 */
+
+/* Uncomment next line if building for Freescale Classic MQX/RTCS/MFS */
+/* #define FREESCALE_MQX */
+
+/* Uncomment next line if building for Freescale KSDK MQX/RTCS/MFS */
+/* #define FREESCALE_KSDK_MQX */
+
+/* Uncomment next line if building for Freescale KSDK Bare Metal */
+/* #define FREESCALE_KSDK_BM */
+
+/* Uncomment next line if building for Freescale KSDK FreeRTOS, */
+/* (old name FREESCALE_FREE_RTOS) */
+/* #define FREESCALE_KSDK_FREERTOS */
+
+/* Uncomment next line if using STM32F2 */
+/* #define WOLFSSL_STM32F2 */
+
+/* Uncomment next line if using STM32F4 */
+/* #define WOLFSSL_STM32F4 */
+
+/* Uncomment next line if using STM32FL */
+/* #define WOLFSSL_STM32FL */
+
+/* Uncomment next line if using STM32F7 */
+/* #define WOLFSSL_STM32F7 */
+
+/* Uncomment next line if using QL SEP settings */
+/* #define WOLFSSL_QL */
+
+/* Uncomment next line if building for EROAD */
+/* #define WOLFSSL_EROAD */
+
+/* Uncomment next line if building for IAR EWARM */
+/* #define WOLFSSL_IAR_ARM */
+
+/* Uncomment next line if building for Rowley CrossWorks ARM */
+/* #define WOLFSSL_ROWLEY_ARM */
+
+/* Uncomment next line if using TI-RTOS settings */
+/* #define WOLFSSL_TIRTOS */
+
+/* Uncomment next line if building with PicoTCP */
+/* #define WOLFSSL_PICOTCP */
+
+/* Uncomment next line if building for PicoTCP demo bundle */
+/* #define WOLFSSL_PICOTCP_DEMO */
+
+/* Uncomment next line if building for uITRON4  */
+/* #define WOLFSSL_uITRON4 */
+
+/* Uncomment next line if building for uT-Kernel */
+/* #define WOLFSSL_uTKERNEL2 */
+
+/* Uncomment next line if using Max Strength build */
+/* #define WOLFSSL_MAX_STRENGTH */
+
+/* Uncomment next line if building for VxWorks */
+/* #define WOLFSSL_VXWORKS */
+
+/* Uncomment next line if building for Nordic nRF5x platform */
+/* #define WOLFSSL_NRF5x */
+
+/* Uncomment next line to enable deprecated less secure static DH suites */
+/* #define WOLFSSL_STATIC_DH */
+
+/* Uncomment next line to enable deprecated less secure static RSA suites */
+/* #define WOLFSSL_STATIC_RSA */
+
+/* Uncomment next line if building for ARDUINO */
+/* Uncomment both lines if building for ARDUINO on INTEL_GALILEO */
+/* #define WOLFSSL_ARDUINO */
+/* #define INTEL_GALILEO */
+
+/* Uncomment next line to enable asynchronous crypto WC_PENDING_E */
+/* #define WOLFSSL_ASYNC_CRYPT */
+
+/* Uncomment next line if building for uTasker */
+/* #define WOLFSSL_UTASKER */
+
+/* Uncomment next line if building for embOS */
+/* #define WOLFSSL_EMBOS */
+
+/* Uncomment next line if building for RIOT-OS */
+/* #define WOLFSSL_RIOT_OS */
+
+/* Uncomment next line if building for using XILINX hardened crypto */
+/* #define WOLFSSL_XILINX_CRYPT */
+
+/* Uncomment next line if building for using XILINX */
+/* #define WOLFSSL_XILINX */
+
+/* Uncomment next line if building for WICED Studio. */
+/* #define WOLFSSL_WICED  */
+
+/* Uncomment next line if building for Nucleus 1.2 */
+/* #define WOLFSSL_NUCLEUS_1_2 */
+
+/* Uncomment next line if building for using Apache mynewt */
+/* #define WOLFSSL_APACHE_MYNEWT */
+
+/* Uncomment next line if building for using ESP-IDF */
+/* #define WOLFSSL_ESPIDF */
+
+/* Uncomment next line if using Espressif ESP32-WROOM-32 */
+/* #define WOLFSSL_ESPWROOM32 */
+
+/* Uncomment next line if using Espressif ESP32-WROOM-32SE */
+/* #define WOLFSSL_ESPWROOM32SE */
+
+/* Uncomment next line if using ARM CRYPTOCELL*/
+/* #define WOLFSSL_CRYPTOCELL */
+
+/* Uncomment next line if using RENESAS TSIP */
+/* #define WOLFSSL_RENESAS_TSIP */
+
+/* Uncomment next line if using RENESAS RX64N */
+/* #define WOLFSSL_RENESAS_RX65N */
+
+#include <wolfssl/wolfcrypt/visibility.h>
+
+#ifdef WOLFSSL_USER_SETTINGS
+    #include "user_settings.h"
+#endif
+
+
+/* make sure old RNG name is used with CTaoCrypt FIPS */
+#ifdef HAVE_FIPS
+    #if !defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)
+        #define WC_RNG RNG
+    #else
+        #ifndef WOLFSSL_STM32L4
+            #define RNG WC_RNG
+        #endif
+    #endif
+    /* blinding adds API not available yet in FIPS mode */
+    #undef WC_RSA_BLINDING
+#endif
+
+
+#if defined(_WIN32) && !defined(_M_X64) && \
+    defined(HAVE_AESGCM) && defined(WOLFSSL_AESNI)
+
+/* The _M_X64 macro is what's used in the headers for MSC to tell if it
+ * has the 64-bit versions of the 128-bit integers available. If one is
+ * building on 32-bit Windows with AES-NI, turn off the AES-GCMloop
+ * unrolling. */
+
+    #define AES_GCM_AESNI_NO_UNROLL
+#endif
+
+#ifdef IPHONE
+    #define SIZEOF_LONG_LONG 8
+#endif
+
+#ifdef THREADX
+    #define SIZEOF_LONG_LONG 8
+#endif
+
+#ifdef HAVE_NETX
+    #ifdef NEED_THREADX_TYPES
+        #include <types.h>
+    #endif
+    #include <nx_api.h>
+#endif
+
+#if defined(WOLFSSL_ESPIDF)
+    #define FREERTOS
+    #define WOLFSSL_LWIP
+    #define NO_WRITEV
+    #define SIZEOF_LONG_LONG 8
+    #define NO_WOLFSSL_DIR
+    #define WOLFSSL_NO_CURRDIR
+
+    #define TFM_TIMING_RESISTANT
+    #define ECC_TIMING_RESISTANT
+    #define WC_RSA_BLINDING
+
+#if defined(WOLFSSL_ESPWROOM32) || defined(WOLFSSL_ESPWROOM32SE)
+   #ifndef NO_ESP32WROOM32_CRYPT
+        #define WOLFSSL_ESP32WROOM32_CRYPT
+        #if defined(ESP32_USE_RSA_PRIMITIVE) && \
+            !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI)
+            #define WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI
+            #define USE_FAST_MATH
+            #define WOLFSSL_SMALL_STACK
+        #endif
+   #endif
+#endif
+#endif /* WOLFSSL_ESPIDF */
+
+#if defined(WOLFSSL_RENESAS_TSIP)
+    #define TSIP_TLS_HMAC_KEY_INDEX_WORDSIZE 64
+    #define TSIP_TLS_MASTERSECRET_SIZE       80   /* 20 words */
+    #define TSIP_TLS_ENCPUBKEY_SZ_BY_CERTVRFY 560 /* in byte  */
+    #if !defined(NO_RENESAS_TSIP_CRYPT) && defined(WOLFSSL_RENESAS_RX65N)
+        #define WOLFSSL_RENESAS_TSIP_CRYPT
+        #define WOLFSSL_RENESAS_TSIP_TLS
+        #define WOLFSSL_RENESAS_TSIP_TLS_AES_CRYPT
+    #endif
+#endif
+
+#if defined(WOLFSSL_RENESAS_RA6M3G)
+    /* settings in user_settings.h */
+#endif
+
+#if defined(HAVE_LWIP_NATIVE) /* using LwIP native TCP socket */
+    #define WOLFSSL_LWIP
+    #define NO_WRITEV
+    #define SINGLE_THREADED
+    #define WOLFSSL_USER_IO
+    #define NO_FILESYSTEM
+#endif
+
+#if defined(WOLFSSL_CONTIKI)
+    #include <contiki.h>
+    #define WOLFSSL_UIP
+    #define NO_WOLFSSL_MEMORY
+    #define NO_WRITEV
+    #define SINGLE_THREADED
+    #define WOLFSSL_USER_IO
+    #define NO_FILESYSTEM
+    #define CUSTOM_RAND_TYPE uint16_t
+    #define CUSTOM_RAND_GENERATE random_rand
+    static inline word32 LowResTimer(void)
+    {
+        return clock_seconds();
+    }
+#endif
+
+#if defined(WOLFSSL_IAR_ARM) || defined(WOLFSSL_ROWLEY_ARM)
+    #define NO_MAIN_DRIVER
+    #define SINGLE_THREADED
+    #if !defined(USE_CERT_BUFFERS_2048) && !defined(USE_CERT_BUFFERS_4096)
+        #define USE_CERT_BUFFERS_1024
+    #endif
+    #define BENCH_EMBEDDED
+    #define NO_FILESYSTEM
+    #define NO_WRITEV
+    #define WOLFSSL_USER_IO
+    #define BENCH_EMBEDDED
+#endif
+
+#ifdef MICROCHIP_PIC32
+    /* #define WOLFSSL_MICROCHIP_PIC32MZ */
+    #define SIZEOF_LONG_LONG 8
+    #define SINGLE_THREADED
+    #define WOLFSSL_USER_IO
+    #define NO_WRITEV
+    #define NO_DEV_RANDOM
+    #define NO_FILESYSTEM
+    #define USE_FAST_MATH
+    #define TFM_TIMING_RESISTANT
+    #define WOLFSSL_HAVE_MIN
+    #define WOLFSSL_HAVE_MAX
+    #define NO_BIG_INT
+#endif
+
+#ifdef WOLFSSL_MICROCHIP_PIC32MZ
+    #ifndef NO_PIC32MZ_CRYPT
+        #define WOLFSSL_PIC32MZ_CRYPT
+    #endif
+    #ifndef NO_PIC32MZ_RNG
+        #define WOLFSSL_PIC32MZ_RNG
+    #endif
+    #ifndef NO_PIC32MZ_HASH
+        #define WOLFSSL_PIC32MZ_HASH
+    #endif
+#endif
+
+#ifdef MICROCHIP_TCPIP_V5
+    /* include timer functions */
+    #include "TCPIP Stack/TCPIP.h"
+#endif
+
+#ifdef MICROCHIP_TCPIP
+    /* include timer, NTP functions */
+    #ifdef MICROCHIP_MPLAB_HARMONY
+        #include "tcpip/tcpip.h"
+    #else
+        #include "system/system_services.h"
+        #include "tcpip/sntp.h"
+    #endif
+#endif
+
+#ifdef MBED
+    #define WOLFSSL_USER_IO
+    #define NO_FILESYSTEM
+    #define NO_CERTS
+    #if !defined(USE_CERT_BUFFERS_2048) && !defined(USE_CERT_BUFFERS_4096)
+        #define USE_CERT_BUFFERS_1024
+    #endif
+    #define NO_WRITEV
+    #define NO_DEV_RANDOM
+    #define NO_SHA512
+    #define NO_DH
+    /* Allows use of DH with fixed points if uncommented and NO_DH is removed */
+    /* WOLFSSL_DH_CONST */
+    #define NO_DSA
+    #define NO_HC128
+    #define HAVE_ECC
+    #define NO_SESSION_CACHE
+    #define WOLFSSL_CMSIS_RTOS
+#endif
+
+
+#ifdef WOLFSSL_EROAD
+    #define FREESCALE_MQX
+    #define FREESCALE_MMCAU
+    #define SINGLE_THREADED
+    #define NO_STDIO_FILESYSTEM
+    #define WOLFSSL_LEANPSK
+    #define HAVE_NULL_CIPHER
+    #define NO_OLD_TLS
+    #define NO_ASN
+    #define NO_BIG_INT
+    #define NO_RSA
+    #define NO_DSA
+    #define NO_DH
+    /* Allows use of DH with fixed points if uncommented and NO_DH is removed */
+    /* WOLFSSL_DH_CONST */
+    #define NO_CERTS
+    #define NO_PWDBASED
+    #define NO_DES3
+    #define NO_MD4
+    #define NO_RC4
+    #define NO_MD5
+    #define NO_SESSION_CACHE
+    #define NO_MAIN_DRIVER
+#endif
+
+#ifdef WOLFSSL_PICOTCP
+    #ifndef errno
+        #define errno pico_err
+    #endif
+    #include "pico_defines.h"
+    #include "pico_stack.h"
+    #include "pico_constants.h"
+    #include "pico_protocol.h"
+    #define CUSTOM_RAND_GENERATE pico_rand
+#endif
+
+#ifdef WOLFSSL_PICOTCP_DEMO
+    #define WOLFSSL_STM32
+    #define USE_FAST_MATH
+    #define TFM_TIMING_RESISTANT
+    #define XMALLOC(s, h, type)  PICO_ZALLOC((s))
+    #define XFREE(p, h, type)    PICO_FREE((p))
+    #define SINGLE_THREADED
+    #define NO_WRITEV
+    #define WOLFSSL_USER_IO
+    #define NO_DEV_RANDOM
+    #define NO_FILESYSTEM
+#endif
+
+#ifdef FREERTOS_WINSIM
+    #define FREERTOS
+    #define USE_WINDOWS_API
+#endif
+
+
+#ifdef WOLFSSL_VXWORKS
+    /* VxWorks simulator incorrectly detects building for i386 */
+    #ifdef VXWORKS_SIM
+        #define TFM_NO_ASM
+    #endif
+    /* For VxWorks pthreads wrappers for mutexes uncomment the next line. */
+    /* #define WOLFSSL_PTHREADS */
+    #define WOLFSSL_HAVE_MIN
+    #define WOLFSSL_HAVE_MAX
+    #define USE_FAST_MATH
+    #define TFM_TIMING_RESISTANT
+    #define NO_MAIN_DRIVER
+    #define NO_DEV_RANDOM
+    #define NO_WRITEV
+    #define HAVE_STRINGS_H
+#endif
+
+
+#ifdef WOLFSSL_ARDUINO
+    #define NO_WRITEV
+    #define NO_WOLFSSL_DIR
+    #define SINGLE_THREADED
+    #define NO_DEV_RANDOM
+    #ifndef INTEL_GALILEO /* Galileo has time.h compatibility */
+        #define TIME_OVERRIDES
+        #ifndef XTIME
+            #error "Must define XTIME externally see porting guide"
+            #error "https://www.wolfssl.com/docs/porting-guide/"
+        #endif
+        #ifndef XGMTIME
+            #error "Must define XGMTIME externally see porting guide"
+            #error "https://www.wolfssl.com/docs/porting-guide/"
+        #endif
+    #endif
+    #define WOLFSSL_USER_IO
+    #define HAVE_ECC
+    #define NO_DH
+    #define NO_SESSION_CACHE
+#endif
+
+
+#ifdef WOLFSSL_UTASKER
+    /* uTasker configuration - used for fnRandom() */
+    #include "config.h"
+
+    #define SINGLE_THREADED
+    #define NO_WOLFSSL_DIR
+    #define WOLFSSL_HAVE_MIN
+    #define NO_WRITEV
+
+    #define HAVE_ECC
+    #define ALT_ECC_SIZE
+    #define USE_FAST_MATH
+    #define TFM_TIMING_RESISTANT
+    #define ECC_TIMING_RESISTANT
+
+    /* used in wolfCrypt test */
+    #define NO_MAIN_DRIVER
+    #define USE_CERT_BUFFERS_2048
+
+    /* uTasker port uses RAW sockets, use I/O callbacks
+     * See wolfSSL uTasker example for sample callbacks */
+    #define WOLFSSL_USER_IO
+
+    /* uTasker filesystem not ported  */
+    #define NO_FILESYSTEM
+
+    /* uTasker RNG is abstracted, calls HW RNG when available */
+    #define CUSTOM_RAND_GENERATE    fnRandom
+    #define CUSTOM_RAND_TYPE        unsigned short
+
+    /* user needs to define XTIME to function that provides
+     * seconds since Unix epoch */
+    #ifndef XTIME
+        #error XTIME must be defined in wolfSSL settings.h
+        /* #define XTIME fnSecondsSinceEpoch */
+    #endif
+
+    /* use uTasker std library replacements where available */
+    #define STRING_USER
+    #define XMEMCPY(d,s,l)         uMemcpy((d),(s),(l))
+    #define XMEMSET(b,c,l)         uMemset((b),(c),(l))
+    #define XMEMCMP(s1,s2,n)       uMemcmp((s1),(s2),(n))
+    #define XMEMMOVE(d,s,l)        memmove((d),(s),(l))
+
+    #define XSTRLEN(s1)            uStrlen((s1))
+    #define XSTRNCPY(s1,s2,n)      strncpy((s1),(s2),(n))
+    #define XSTRSTR(s1,s2)         strstr((s1),(s2))
+    #define XSTRNSTR(s1,s2,n)      mystrnstr((s1),(s2),(n))
+    #define XSTRNCMP(s1,s2,n)      strncmp((s1),(s2),(n))
+    #define XSTRNCAT(s1,s2,n)      strncat((s1),(s2),(n))
+    #define XSTRNCASECMP(s1,s2,n)  _strnicmp((s1),(s2),(n))
+    #if defined(WOLFSSL_CERT_EXT) || defined(OPENSSL_EXTRA) \
+            || defined(HAVE_ALPN)
+        #define XSTRTOK            strtok_r
+    #endif
+#endif
+
+#ifdef WOLFSSL_EMBOS
+    #define NO_FILESYSTEM           /* Not ported at this time */
+    #define USE_CERT_BUFFERS_2048   /* use when NO_FILESYSTEM */
+    #define NO_MAIN_DRIVER
+    #define NO_RC4
+    #define SINGLE_THREADED         /* Not ported at this time */
+#endif
+
+#ifdef WOLFSSL_RIOT_OS
+    #define NO_WRITEV
+    #define TFM_NO_ASM
+    #define NO_FILESYSTEM
+    #define USE_CERT_BUFFERS_2048
+    #if defined(WOLFSSL_GNRC) && !defined(WOLFSSL_DTLS)
+        #define WOLFSSL_DTLS
+    #endif
+#endif
+
+#ifdef WOLFSSL_CHIBIOS
+    /* ChibiOS definitions. This file is distributed with chibiOS. */
+    #include "wolfssl_chibios.h"
+#endif
+
+#ifdef WOLFSSL_PB
+    /* PB is using older 1.2 version of Nucleus */
+    #undef WOLFSSL_NUCLEUS
+    #define WOLFSSL_NUCLEUS_1_2
+#endif
+
+#ifdef WOLFSSL_NUCLEUS_1_2
+    #define NO_WRITEV
+    #define NO_WOLFSSL_DIR
+
+    #if !defined(NO_ASN_TIME) && !defined(USER_TIME)
+        #error User must define XTIME, see manual
+    #endif
+
+    #if !defined(XMALLOC_OVERRIDE) && !defined(XMALLOC_USER)
+        extern void* nucleus_malloc(unsigned long size, void* heap, int type);
+        extern void* nucleus_realloc(void* ptr, unsigned long size, void* heap,
+                                     int type);
+        extern void  nucleus_free(void* ptr, void* heap, int type);
+
+        #define XMALLOC(s, h, type)  nucleus_malloc((s), (h), (type))
+        #define XREALLOC(p, n, h, t) nucleus_realloc((p), (n), (h), (t))
+        #define XFREE(p, h, type)    nucleus_free((p), (h), (type))
+    #endif
+#endif
+
+#ifdef WOLFSSL_NRF5x
+        #define SIZEOF_LONG 4
+        #define SIZEOF_LONG_LONG 8
+        #define NO_ASN_TIME
+        #define NO_DEV_RANDOM
+        #define NO_FILESYSTEM
+        #define NO_MAIN_DRIVER
+        #define NO_WRITEV
+        #define SINGLE_THREADED
+        #define USE_FAST_MATH
+        #define TFM_TIMING_RESISTANT
+        #define USE_WOLFSSL_MEMORY
+        #define WOLFSSL_NRF51
+        #define WOLFSSL_USER_IO
+        #define NO_SESSION_CACHE
+#endif
+
+/* Micrium will use Visual Studio for compilation but not the Win32 API */
+#if defined(_WIN32) && !defined(MICRIUM) && !defined(FREERTOS) && \
+    !defined(FREERTOS_TCP) && !defined(EBSNET) && !defined(WOLFSSL_EROAD) && \
+    !defined(WOLFSSL_UTASKER) && !defined(INTIME_RTOS)
+    #define USE_WINDOWS_API
+#endif
+
+#if defined(WOLFSSL_uITRON4)
+
+#define XMALLOC_USER
+#include <stddef.h>
+#define ITRON_POOL_SIZE 1024*20
+extern int uITRON4_minit(size_t poolsz) ;
+extern void *uITRON4_malloc(size_t sz) ;
+extern void *uITRON4_realloc(void *p, size_t sz) ;
+extern void uITRON4_free(void *p) ;
+
+#define XMALLOC(sz, heap, type)     uITRON4_malloc(sz)
+#define XREALLOC(p, sz, heap, type) uITRON4_realloc(p, sz)
+#define XFREE(p, heap, type)        uITRON4_free(p)
+#endif
+
+#if defined(WOLFSSL_uTKERNEL2)
+  #ifndef NO_TKERNEL_MEM_POOL
+    #define XMALLOC_OVERRIDE
+    int   uTKernel_init_mpool(unsigned int sz); /* initializing malloc pool */
+    void* uTKernel_malloc(unsigned int sz);
+    void* uTKernel_realloc(void *p, unsigned int sz);
+    void  uTKernel_free(void *p);
+    #define XMALLOC(s, h, type)  uTKernel_malloc((s))
+    #define XREALLOC(p, n, h, t) uTKernel_realloc((p), (n))
+    #define XFREE(p, h, type)    uTKernel_free((p))
+  #endif
+
+  #ifndef NO_STDIO_FGETS_REMAP
+    #include <stdio.h>
+    #include "tm/tmonitor.h"
+
+    /* static char* gets(char *buff); */
+    static char* fgets(char *buff, int sz, XFILE fp) {
+        char * p = buff;
+        *p = '\0';
+        while (1) {
+            *p = tm_getchar(-1);
+            tm_putchar(*p);
+            if (*p == '\r') {
+                tm_putchar('\n');
+                *p = '\0';
+                break;
+            }
+            p++;
+        }
+        return buff;
+    }
+  #endif /* !NO_STDIO_FGETS_REMAP */
+#endif
+
+
+#if defined(WOLFSSL_LEANPSK) && !defined(XMALLOC_USER) && \
+        !defined(NO_WOLFSSL_MEMORY)
+    #include <stdlib.h>
+    #define XMALLOC(s, h, type)  malloc((s))
+    #define XFREE(p, h, type)    free((p))
+    #define XREALLOC(p, n, h, t) realloc((p), (n))
+#endif
+
+#if defined(XMALLOC_USER) && defined(SSN_BUILDING_LIBYASSL)
+    #undef  XMALLOC
+    #define XMALLOC     yaXMALLOC
+    #undef  XFREE
+    #define XFREE       yaXFREE
+    #undef  XREALLOC
+    #define XREALLOC    yaXREALLOC
+#endif
+
+
+#ifdef FREERTOS
+    #include "FreeRTOS.h"
+
+    #if !defined(XMALLOC_USER) && !defined(NO_WOLFSSL_MEMORY) && \
+        !defined(WOLFSSL_STATIC_MEMORY)
+        #define XMALLOC(s, h, type)  pvPortMalloc((s))
+        #define XFREE(p, h, type)    vPortFree((p))
+    #endif
+    /* FreeRTOS pvPortRealloc() implementation can be found here:
+        https://github.com/wolfSSL/wolfssl-freertos/pull/3/files */
+    #if !defined(USE_FAST_MATH) || defined(HAVE_ED25519) || defined(HAVE_ED448)
+        #if defined(WOLFSSL_ESPIDF)
+            /*In IDF, realloc(p, n) is equivalent to 
+            heap_caps_realloc(p, s, MALLOC_CAP_8BIT) */
+            #define XREALLOC(p, n, h, t) realloc((p), (n))
+        #else
+            #define XREALLOC(p, n, h, t) pvPortRealloc((p), (n))
+        #endif
+    #endif
+    #ifndef NO_WRITEV
+        #define NO_WRITEV
+    #endif
+    #ifndef HAVE_SHA512
+        #ifndef NO_SHA512
+            #define NO_SHA512
+        #endif
+    #endif
+    #ifndef HAVE_DH
+        #ifndef NO_DH
+            #define NO_DH
+        #endif
+    #endif
+    #ifndef NO_DSA
+        #define NO_DSA
+    #endif
+    #ifndef NO_HC128
+        #define NO_HC128
+    #endif
+
+    #ifndef SINGLE_THREADED
+        #include "semphr.h"
+    #endif
+#endif
+
+#ifdef FREERTOS_TCP
+    #if !defined(NO_WOLFSSL_MEMORY) && !defined(XMALLOC_USER) && \
+        !defined(WOLFSSL_STATIC_MEMORY)
+        #define XMALLOC(s, h, type)  pvPortMalloc((s))
+        #define XFREE(p, h, type)    vPortFree((p))
+    #endif
+
+    #define WOLFSSL_GENSEED_FORTEST
+
+    #define NO_WOLFSSL_DIR
+    #define NO_WRITEV
+    #define USE_FAST_MATH
+    #define TFM_TIMING_RESISTANT
+    #define NO_MAIN_DRIVER
+#endif
+
+#ifdef WOLFSSL_TIRTOS
+    #define SIZEOF_LONG_LONG 8
+    #define NO_WRITEV
+    #define NO_WOLFSSL_DIR
+    #define USE_FAST_MATH
+    #define TFM_TIMING_RESISTANT
+    #define ECC_TIMING_RESISTANT
+    #define WC_RSA_BLINDING
+    #define NO_DEV_RANDOM
+    #define NO_FILESYSTEM
+    #define USE_CERT_BUFFERS_2048
+    #define NO_ERROR_STRINGS
+    /* Uncomment this setting if your toolchain does not offer time.h header */
+    /* #define USER_TIME */
+    #define HAVE_ECC
+    #define HAVE_ALPN
+    #define USE_WOLF_STRTOK /* use with HAVE_ALPN */
+    #define HAVE_TLS_EXTENSIONS
+    #define HAVE_AESGCM
+    #ifdef WOLFSSL_TI_CRYPT
+        #define NO_GCM_ENCRYPT_EXTRA
+        #define NO_PUBLIC_GCM_SET_IV
+        #define NO_PUBLIC_CCM_SET_NONCE
+    #endif
+    #define HAVE_SUPPORTED_CURVES
+    #define ALT_ECC_SIZE
+
+    #ifdef __IAR_SYSTEMS_ICC__
+        #pragma diag_suppress=Pa089
+    #elif !defined(__GNUC__)
+        /* Suppress the sslpro warning */
+        #pragma diag_suppress=11
+    #endif
+
+    #include <ti/sysbios/hal/Seconds.h>
+#endif
+
+#ifdef EBSNET
+    #include "rtip.h"
+
+    /* #define DEBUG_WOLFSSL */
+    #define NO_WOLFSSL_DIR  /* tbd */
+
+    #if (POLLOS)
+        #define SINGLE_THREADED
+    #endif
+
+    #if (RTPLATFORM)
+        #if (!RTP_LITTLE_ENDIAN)
+            #define BIG_ENDIAN_ORDER
+        #endif
+    #else
+        #if (!KS_LITTLE_ENDIAN)
+            #define BIG_ENDIAN_ORDER
+        #endif
+    #endif
+
+    #if (WINMSP3)
+        #undef SIZEOF_LONG
+        #define SIZEOF_LONG_LONG 8
+    #else
+        #error settings.h - please implement SIZEOF_LONG and SIZEOF_LONG_LONG
+    #endif
+
+    #define XMALLOC(s, h, type) ((void *)rtp_malloc((s), SSL_PRO_MALLOC))
+    #define XFREE(p, h, type) (rtp_free(p))
+    #define XREALLOC(p, n, h, t) (rtp_realloc((p), (n)))
+
+    #if (WINMSP3)
+        #define XSTRNCASECMP(s1,s2,n)  _strnicmp((s1),(s2),(n))
+    #else
+        #sslpro: settings.h - please implement XSTRNCASECMP - needed for HAVE_ECC
+    #endif
+
+    #define WOLFSSL_HAVE_MAX
+    #define WOLFSSL_HAVE_MIN
+
+    #define USE_FAST_MATH
+    #define TFM_TIMING_RESISTANT
+    #define WC_RSA_BLINDING
+    #define ECC_TIMING_RESISTANT
+
+    #define HAVE_ECC
+
+#endif /* EBSNET */
+
+#ifdef WOLFSSL_GAME_BUILD
+    #define SIZEOF_LONG_LONG 8
+    #if defined(__PPU) || defined(__XENON)
+        #define BIG_ENDIAN_ORDER
+    #endif
+#endif
+
+#ifdef WOLFSSL_LSR
+    #define HAVE_WEBSERVER
+    #define SIZEOF_LONG_LONG 8
+    #define WOLFSSL_LOW_MEMORY
+    #define NO_WRITEV
+    #define NO_SHA512
+    #define NO_DH
+    /* Allows use of DH with fixed points if uncommented and NO_DH is removed */
+    /* WOLFSSL_DH_CONST */
+    #define NO_DSA
+    #define NO_HC128
+    #define NO_DEV_RANDOM
+    #define NO_WOLFSSL_DIR
+    #define NO_RABBIT
+    #ifndef NO_FILESYSTEM
+        #define LSR_FS
+        #include "inc/hw_types.h"
+        #include "fs.h"
+    #endif
+    #define WOLFSSL_LWIP
+    #include <errno.h>  /* for tcp errno */
+    #define WOLFSSL_SAFERTOS
+    #if defined(__IAR_SYSTEMS_ICC__)
+        /* enum uses enum */
+        #pragma diag_suppress=Pa089
+    #endif
+#endif
+
+#ifdef WOLFSSL_SAFERTOS
+    #ifndef SINGLE_THREADED
+        #include "SafeRTOS/semphr.h"
+    #endif
+    #ifndef WOLFSSL_NO_MALLOC
+        #include "SafeRTOS/heap.h"
+    #endif
+    #if !defined(XMALLOC_USER) && !defined(NO_WOLFSSL_MEMORY) && \
+        !defined(WOLFSSL_STATIC_MEMORY)
+        #define XMALLOC(s, h, type)  pvPortMalloc((s))
+        #define XFREE(p, h, type)    vPortFree((p))
+    #endif
+    /* FreeRTOS pvPortRealloc() implementation can be found here:
+        https://github.com/wolfSSL/wolfssl-freertos/pull/3/files */
+    #if !defined(USE_FAST_MATH) || defined(HAVE_ED25519) || defined(HAVE_ED448)
+        #define XREALLOC(p, n, h, t) pvPortRealloc((p), (n))
+    #endif
+#endif
+
+#ifdef WOLFSSL_LOW_MEMORY
+    #undef  RSA_LOW_MEM
+    #define RSA_LOW_MEM
+    #undef  WOLFSSL_SMALL_STACK
+    #define WOLFSSL_SMALL_STACK
+    #undef  TFM_TIMING_RESISTANT
+    #define TFM_TIMING_RESISTANT
+#endif
+
+#ifdef FREESCALE_MQX_5_0
+    /* use normal Freescale MQX port, but with minor changes for 5.0 */
+    #define FREESCALE_MQX
+#endif
+
+#ifdef FREESCALE_MQX_4_0
+    /* use normal Freescale MQX port, but with minor changes for 4.0 */
+    #define FREESCALE_MQX
+#endif
+
+#ifdef FREESCALE_MQX
+    #define FREESCALE_COMMON
+    #include "mqx.h"
+    #ifndef NO_FILESYSTEM
+        #include "mfs.h"
+        #if (defined(MQX_USE_IO_OLD) && MQX_USE_IO_OLD) || \
+            defined(FREESCALE_MQX_5_0)
+            #include "fio.h"
+            #define NO_STDIO_FILESYSTEM
+        #else
+            #include "nio.h"
+        #endif
+    #endif
+    #ifndef SINGLE_THREADED
+        #include "mutex.h"
+    #endif
+
+    #if !defined(XMALLOC_OVERRIDE) && !defined(XMALLOC_USER)
+        #define XMALLOC_OVERRIDE
+        #define XMALLOC(s, h, t)    (void *)_mem_alloc_system((s))
+        #define XFREE(p, h, t)      {void* xp = (p); if ((xp)) _mem_free((xp));}
+        /* Note: MQX has no realloc, using fastmath above */
+    #endif
+#endif
+
+#ifdef FREESCALE_KSDK_MQX
+    #define FREESCALE_COMMON
+    #include <mqx.h>
+    #ifndef NO_FILESYSTEM
+        #if (defined(MQX_USE_IO_OLD) && MQX_USE_IO_OLD) || \
+            defined(FREESCALE_MQX_5_0)
+            #include <fio.h>
+        #else
+            #include <stdio.h>
+            #include <nio.h>
+        #endif
+    #endif
+    #ifndef SINGLE_THREADED
+        #include <mutex.h>
+    #endif
+
+    #define XMALLOC(s, h, t)    (void *)_mem_alloc_system((s))
+    #define XFREE(p, h, t)      {void* xp = (p); if ((xp)) _mem_free((xp));}
+    #define XREALLOC(p, n, h, t) _mem_realloc((p), (n)) /* since MQX 4.1.2 */
+
+    #define MQX_FILE_PTR FILE *
+    #define IO_SEEK_SET  SEEK_SET
+    #define IO_SEEK_END  SEEK_END
+#endif /* FREESCALE_KSDK_MQX */
+
+#if defined(FREESCALE_FREE_RTOS) || defined(FREESCALE_KSDK_FREERTOS)
+    #define NO_FILESYSTEM
+    #define WOLFSSL_CRYPT_HW_MUTEX 1
+
+    #if !defined(XMALLOC_USER) && !defined(NO_WOLFSSL_MEMORY)
+        #define XMALLOC(s, h, type)  pvPortMalloc((s))
+        #define XFREE(p, h, type)    vPortFree((p))
+    #endif
+
+    //#define USER_TICKS
+    /* Allows use of DH with fixed points if uncommented and NO_DH is removed */
+    /* WOLFSSL_DH_CONST */
+    #define WOLFSSL_LWIP
+    #define FREERTOS_TCP
+
+    #define FREESCALE_FREE_RTOS
+    #define FREERTOS_SOCKET_ERROR ( -1 )
+    #define FREERTOS_EWOULDBLOCK ( -2 )
+    #define FREERTOS_EINVAL ( -4 )
+    #define FREERTOS_EADDRNOTAVAIL ( -5 )
+    #define FREERTOS_EADDRINUSE ( -6 )
+    #define FREERTOS_ENOBUFS ( -7 )
+    #define FREERTOS_ENOPROTOOPT ( -8 )
+#endif /* FREESCALE_FREE_RTOS || FREESCALE_KSDK_FREERTOS */
+
+#ifdef FREESCALE_KSDK_BM
+    #define FREESCALE_COMMON
+    #define WOLFSSL_USER_IO
+    #define SINGLE_THREADED
+    #define NO_FILESYSTEM
+    #ifndef TIME_OVERRIDES
+        #define USER_TICKS
+    #endif
+#endif /* FREESCALE_KSDK_BM */
+
+#ifdef FREESCALE_COMMON
+    #define SIZEOF_LONG_LONG 8
+
+    /* disable features */
+    #undef  NO_WRITEV
+    #define NO_WRITEV
+    #undef  NO_DEV_RANDOM
+    #define NO_DEV_RANDOM
+    #undef  NO_RABBIT
+    #define NO_RABBIT
+    #undef  NO_WOLFSSL_DIR
+    #define NO_WOLFSSL_DIR
+    #undef  NO_RC4
+    #define NO_RC4
+
+    /* enable features */
+    #undef  USE_FAST_MATH
+    #define USE_FAST_MATH
+
+    #define USE_CERT_BUFFERS_2048
+    #define BENCH_EMBEDDED
+
+    #define TFM_TIMING_RESISTANT
+    #define ECC_TIMING_RESISTANT
+
+    #undef  HAVE_ECC
+    #define HAVE_ECC
+    #ifndef NO_AES
+        #undef  HAVE_AESCCM
+        #define HAVE_AESCCM
+        #undef  HAVE_AESGCM
+        #define HAVE_AESGCM
+        #undef  WOLFSSL_AES_COUNTER
+        #define WOLFSSL_AES_COUNTER
+        #undef  WOLFSSL_AES_DIRECT
+        #define WOLFSSL_AES_DIRECT
+    #endif
+
+    #ifdef FREESCALE_KSDK_1_3
+        #include "fsl_device_registers.h"
+    #elif !defined(FREESCALE_MQX)
+        /* Classic MQX does not have fsl_common.h */
+        #include "fsl_common.h"
+    #endif
+
+    /* random seed */
+    #define NO_OLD_RNGNAME
+    #if defined(FSL_FEATURE_SOC_TRNG_COUNT) && (FSL_FEATURE_SOC_TRNG_COUNT > 0)
+        #define FREESCALE_KSDK_2_0_TRNG
+    #elif defined(FSL_FEATURE_SOC_RNG_COUNT) && (FSL_FEATURE_SOC_RNG_COUNT > 0)
+        #ifdef FREESCALE_KSDK_1_3
+            #include "fsl_rnga_driver.h"
+            #define FREESCALE_RNGA
+            #define RNGA_INSTANCE (0)
+        #else
+            #define FREESCALE_KSDK_2_0_RNGA
+        #endif
+    #elif !defined(FREESCALE_KSDK_BM) && !defined(FREESCALE_FREE_RTOS) && !defined(FREESCALE_KSDK_FREERTOS)
+        #define FREESCALE_RNGA
+        #define RNGA_INSTANCE (0)
+        /* defaulting to K70 RNGA, user should change if different */
+        /* #define FREESCALE_K53_RNGB */
+        #define FREESCALE_K70_RNGA
+    #endif
+
+    /* HW crypto */
+    /* automatic enable based on Kinetis feature */
+    /* if case manual selection is required, for example for benchmarking purposes,
+     * just define FREESCALE_USE_MMCAU or FREESCALE_USE_LTC or none of these two macros (for software only)
+     * both can be enabled simultaneously as LTC has priority over MMCAU in source code.
+     */
+    /* #define FSL_HW_CRYPTO_MANUAL_SELECTION */
+    #ifndef FSL_HW_CRYPTO_MANUAL_SELECTION
+        #if defined(FSL_FEATURE_SOC_MMCAU_COUNT) && FSL_FEATURE_SOC_MMCAU_COUNT
+            #define FREESCALE_USE_MMCAU
+        #endif
+
+        #if defined(FSL_FEATURE_SOC_LTC_COUNT) && FSL_FEATURE_SOC_LTC_COUNT
+            #define FREESCALE_USE_LTC
+        #endif
+    #else
+        /* #define FREESCALE_USE_MMCAU */
+        /* #define FREESCALE_USE_LTC */
+    #endif
+#endif /* FREESCALE_COMMON */
+
+/* Classic pre-KSDK mmCAU library */
+#ifdef FREESCALE_USE_MMCAU_CLASSIC
+    #define FREESCALE_USE_MMCAU
+    #define FREESCALE_MMCAU_CLASSIC
+    #define FREESCALE_MMCAU_CLASSIC_SHA
+#endif
+
+/* KSDK mmCAU library */
+#ifdef FREESCALE_USE_MMCAU
+    /* AES and DES */
+    #define FREESCALE_MMCAU
+    /* MD5, SHA-1 and SHA-256 */
+    #define FREESCALE_MMCAU_SHA
+#endif /* FREESCALE_USE_MMCAU */
+
+#ifdef FREESCALE_USE_LTC
+    #if defined(FSL_FEATURE_SOC_LTC_COUNT) && FSL_FEATURE_SOC_LTC_COUNT
+        #define FREESCALE_LTC
+        #define LTC_BASE LTC0
+
+        #if defined(FSL_FEATURE_LTC_HAS_DES) && FSL_FEATURE_LTC_HAS_DES
+            #define FREESCALE_LTC_DES
+        #endif
+
+        #if defined(FSL_FEATURE_LTC_HAS_GCM) && FSL_FEATURE_LTC_HAS_GCM
+            #define FREESCALE_LTC_AES_GCM
+        #endif
+
+        #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
+            #define FREESCALE_LTC_SHA
+        #endif
+
+        #if defined(FSL_FEATURE_LTC_HAS_PKHA) && FSL_FEATURE_LTC_HAS_PKHA
+            #define FREESCALE_LTC_ECC
+            #define FREESCALE_LTC_TFM
+
+            /* the LTC PKHA hardware limit is 2048 bits (256 bytes) for integer arithmetic.
+               the LTC_MAX_INT_BYTES defines the size of local variables that hold big integers. */
+            #ifndef LTC_MAX_INT_BYTES
+                #define LTC_MAX_INT_BYTES (256)
+            #endif
+
+            /* This FREESCALE_LTC_TFM_RSA_4096_ENABLE macro can be defined.
+             * In such a case both software and hardware algorithm
+             * for TFM is linked in. The decision for which algorithm is used is determined at runtime
+             * from size of inputs. If inputs and result can fit into LTC (see LTC_MAX_INT_BYTES)
+             * then we call hardware algorithm, otherwise we call software algorithm.
+             *
+             * Chinese reminder theorem is used to break RSA 4096 exponentiations (both public and private key)
+             * into several computations with 2048-bit modulus and exponents.
+             */
+            /* #define FREESCALE_LTC_TFM_RSA_4096_ENABLE */
+
+            /* ECC-384, ECC-256, ECC-224 and ECC-192 have been enabled with LTC PKHA acceleration */
+            #ifdef HAVE_ECC
+                #undef  ECC_TIMING_RESISTANT
+                #define ECC_TIMING_RESISTANT
+
+                /* the LTC PKHA hardware limit is 512 bits (64 bytes) for ECC.
+                   the LTC_MAX_ECC_BITS defines the size of local variables that hold ECC parameters
+                   and point coordinates */
+                #ifndef LTC_MAX_ECC_BITS
+                    #define LTC_MAX_ECC_BITS (384)
+                #endif
+
+                /* Enable curves up to 384 bits */
+                #if !defined(ECC_USER_CURVES) && !defined(HAVE_ALL_CURVES)
+                    #define ECC_USER_CURVES
+                    #define HAVE_ECC192
+                    #define HAVE_ECC224
+                    #undef  NO_ECC256
+                    #define HAVE_ECC384
+                #endif
+            #endif
+        #endif
+    #endif
+#endif /* FREESCALE_USE_LTC */
+
+#ifdef FREESCALE_LTC_TFM_RSA_4096_ENABLE
+    #undef  USE_CERT_BUFFERS_4096
+    #define USE_CERT_BUFFERS_4096
+    #undef  FP_MAX_BITS
+    #define FP_MAX_BITS (8192)
+
+    #undef  NO_DH
+    #define NO_DH
+    #undef  NO_DSA
+    #define NO_DSA
+#endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */
+
+/* if LTC has AES engine but doesn't have GCM, use software with LTC AES ECB mode */
+#if defined(FREESCALE_USE_LTC) && !defined(FREESCALE_LTC_AES_GCM)
+    #define GCM_TABLE
+#endif
+
+#if defined(WOLFSSL_STM32F2) || defined(WOLFSSL_STM32F4) || \
+    defined(WOLFSSL_STM32F7) || defined(WOLFSSL_STM32F1) || \
+    defined(WOLFSSL_STM32L4)
+
+    #define SIZEOF_LONG_LONG 8
+    #ifndef CHAR_BIT
+      #define CHAR_BIT 8
+    #endif
+    #define NO_DEV_RANDOM
+    #define NO_WOLFSSL_DIR
+    #undef  NO_RABBIT
+    #define NO_RABBIT
+    #ifndef NO_STM32_RNG
+        #undef  STM32_RNG
+        #define STM32_RNG
+        #ifdef WOLFSSL_STM32F427_RNG
+            #include "stm32f427xx.h"
+        #endif
+    #endif
+    #ifndef NO_STM32_CRYPTO
+        #undef  STM32_CRYPTO
+        #define STM32_CRYPTO
+
+        #ifdef WOLFSSL_STM32L4
+            #define NO_AES_192 /* hardware does not support 192-bit */
+        #endif
+    #endif
+    #ifndef NO_STM32_HASH
+        #undef  STM32_HASH
+        #define STM32_HASH
+    #endif
+    #if !defined(__GNUC__) && !defined(__ICCARM__)
+        #define KEIL_INTRINSICS
+    #endif
+    #define NO_OLD_RNGNAME
+    #ifdef WOLFSSL_STM32_CUBEMX
+        #if defined(WOLFSSL_STM32F2)
+            #include "stm32f2xx_hal.h"
+        #elif defined(WOLFSSL_STM32L4)
+            #include "stm32l4xx_hal.h"
+        #elif defined(WOLFSSL_STM32F4)
+            #include "stm32f4xx_hal.h"
+        #elif defined(WOLFSSL_STM32F7)
+            #include "stm32f7xx_hal.h"
+        #elif defined(WOLFSSL_STM32F1)
+            #include "stm32f1xx_hal.h"
+        #endif
+        #if defined(WOLFSSL_CUBEMX_USE_LL) && defined(WOLFSSL_STM32L4)
+            #include "stm32l4xx_ll_rng.h"
+        #endif
+
+        #ifndef STM32_HAL_TIMEOUT
+            #define STM32_HAL_TIMEOUT   0xFF
+        #endif
+    #else
+        #if defined(WOLFSSL_STM32F2)
+            #include "stm32f2xx.h"
+            #ifdef STM32_CRYPTO
+                #include "stm32f2xx_cryp.h"
+            #endif
+            #ifdef STM32_HASH
+                #include "stm32f2xx_hash.h"
+            #endif
+        #elif defined(WOLFSSL_STM32F4)
+            #include "stm32f4xx.h"
+            #ifdef STM32_CRYPTO
+                #include "stm32f4xx_cryp.h"
+            #endif
+            #ifdef STM32_HASH
+                #include "stm32f4xx_hash.h"
+            #endif
+        #elif defined(WOLFSSL_STM32L4)
+            #include "stm32l4xx.h"
+            #ifdef STM32_CRYPTO
+                #include "stm32l4xx_cryp.h"
+            #endif
+            #ifdef STM32_HASH
+                #include "stm32l4xx_hash.h"
+            #endif
+        #elif defined(WOLFSSL_STM32F7)
+            #include "stm32f7xx.h"
+        #elif defined(WOLFSSL_STM32F1)
+            #include "stm32f1xx.h"
+        #endif
+    #endif /* WOLFSSL_STM32_CUBEMX */
+#endif /* WOLFSSL_STM32F2 || WOLFSSL_STM32F4 || WOLFSSL_STM32L4 || WOLFSSL_STM32F7 */
+#ifdef WOLFSSL_DEOS
+    #include <deos.h>
+    #include <timeout.h>
+    #include <socketapi.h>
+    #include <lwip-socket.h>
+    #include <mem.h>
+    #include <string.h>
+    #include <stdlib.h> /* for rand_r: pseudo-random number generator */
+    #include <stdio.h>  /* for snprintf */
+
+    /* use external memory XMALLOC, XFREE and XREALLOC functions */
+    #define XMALLOC_USER
+
+    /* disable fall-back case, malloc, realloc and free are unavailable */
+    #define WOLFSSL_NO_MALLOC
+
+    /* file system has not been ported since it is a separate product. */
+
+    #define NO_FILESYSTEM
+
+    #ifdef NO_FILESYSTEM
+        #define NO_WOLFSSL_DIR
+        #define NO_WRITEV
+    #endif
+
+    #define USE_FAST_MATH
+    #define TFM_TIMING_RESISTANT
+    #define ECC_TIMING_RESISTANT
+    #define WC_RSA_BLINDING
+
+    #define HAVE_ECC
+    #define ALT_ECC_SIZE
+    #define TFM_ECC192
+    #define TFM_ECC224
+    #define TFM_ECC256
+    #define TFM_ECC384
+    #define TFM_ECC521
+
+    #define HAVE_TLS_EXTENSIONS
+    #define HAVE_SUPPORTED_CURVES
+    #define HAVE_EXTENDED_MASTER
+
+    #if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+        #define BIG_ENDIAN_ORDER
+    #else
+        #undef  BIG_ENDIAN_ORDER
+        #define LITTLE_ENDIAN_ORDER
+    #endif
+#endif /* WOLFSSL_DEOS*/
+
+#ifdef MICRIUM
+    #include <stdlib.h>
+    #include <os.h>
+    #include <net_cfg.h>
+    #include <net_sock.h>
+    #include <net_err.h>
+    #include <lib_mem.h>
+    #include <lib_math.h>
+
+    #define USE_FAST_MATH
+    #define TFM_TIMING_RESISTANT
+    #define ECC_TIMING_RESISTANT
+    #define WC_RSA_BLINDING
+    #define HAVE_HASHDRBG
+
+    #define HAVE_ECC
+    #define ALT_ECC_SIZE
+    #define TFM_ECC192
+    #define TFM_ECC224
+    #define TFM_ECC256
+    #define TFM_ECC384
+    #define TFM_ECC521
+
+    #define NO_RC4
+    #define HAVE_TLS_EXTENSIONS
+    #define HAVE_SUPPORTED_CURVES
+    #define HAVE_EXTENDED_MASTER
+
+    #define NO_WOLFSSL_DIR
+    #define NO_WRITEV
+
+    #ifndef CUSTOM_RAND_GENERATE
+        #define CUSTOM_RAND_TYPE     RAND_NBR
+        #define CUSTOM_RAND_GENERATE Math_Rand
+    #endif
+    #define STRING_USER
+    #define XSTRLEN(pstr) ((CPU_SIZE_T)Str_Len((CPU_CHAR *)(pstr)))
+    #define XSTRNCPY(pstr_dest, pstr_src, len_max) \
+                    ((CPU_CHAR *)Str_Copy_N((CPU_CHAR *)(pstr_dest), \
+                     (CPU_CHAR *)(pstr_src), (CPU_SIZE_T)(len_max)))
+    #define XSTRNCMP(pstr_1, pstr_2, len_max) \
+                    ((CPU_INT16S)Str_Cmp_N((CPU_CHAR *)(pstr_1), \
+                     (CPU_CHAR *)(pstr_2), (CPU_SIZE_T)(len_max)))
+    #define XSTRNCASECMP(pstr_1, pstr_2, len_max) \
+                    ((CPU_INT16S)Str_CmpIgnoreCase_N((CPU_CHAR *)(pstr_1), \
+                     (CPU_CHAR *)(pstr_2), (CPU_SIZE_T)(len_max)))
+    #define XSTRSTR(pstr, pstr_srch) \
+                    ((CPU_CHAR *)Str_Str((CPU_CHAR *)(pstr), \
+                     (CPU_CHAR *)(pstr_srch)))
+    #define XSTRNSTR(pstr, pstr_srch, len_max) \
+                    ((CPU_CHAR *)Str_Str_N((CPU_CHAR *)(pstr), \
+                     (CPU_CHAR *)(pstr_srch),(CPU_SIZE_T)(len_max)))
+    #define XSTRNCAT(pstr_dest, pstr_cat, len_max) \
+                    ((CPU_CHAR *)Str_Cat_N((CPU_CHAR *)(pstr_dest), \
+                     (const CPU_CHAR *)(pstr_cat),(CPU_SIZE_T)(len_max)))
+    #define XMEMSET(pmem, data_val, size) \
+                    ((void)Mem_Set((void *)(pmem), \
+                    (CPU_INT08U) (data_val), \
+                    (CPU_SIZE_T)(size)))
+    #define XMEMCPY(pdest, psrc, size) ((void)Mem_Copy((void *)(pdest), \
+                     (void *)(psrc), (CPU_SIZE_T)(size)))
+    #define XMEMCMP(pmem_1, pmem_2, size) \
+                   (((CPU_BOOLEAN)Mem_Cmp((void *)(pmem_1), \
+                                          (void *)(pmem_2), \
+                     (CPU_SIZE_T)(size))) ? DEF_NO : DEF_YES)
+    #define XMEMMOVE XMEMCPY
+
+    #if (OS_CFG_MUTEX_EN == DEF_DISABLED)
+        #define SINGLE_THREADED
+    #endif
+
+    #if (CPU_CFG_ENDIAN_TYPE == CPU_ENDIAN_TYPE_BIG)
+        #define BIG_ENDIAN_ORDER
+    #else
+        #undef  BIG_ENDIAN_ORDER
+        #define LITTLE_ENDIAN_ORDER
+    #endif
+#endif /* MICRIUM */
+
+#ifdef WOLFSSL_MCF5441X
+    #define BIG_ENDIAN_ORDER
+    #ifndef SIZEOF_LONG
+        #define SIZEOF_LONG 4
+    #endif
+    #ifndef SIZEOF_LONG_LONG
+        #define SIZEOF_LONG_LONG 8
+    #endif
+#endif
+
+#ifdef WOLFSSL_QL
+    #ifndef WOLFSSL_SEP
+        #define WOLFSSL_SEP
+    #endif
+    #ifndef OPENSSL_EXTRA
+        #define OPENSSL_EXTRA
+    #endif
+    #ifndef SESSION_CERTS
+        #define SESSION_CERTS
+    #endif
+    #ifndef HAVE_AESCCM
+        #define HAVE_AESCCM
+    #endif
+    #ifndef ATOMIC_USER
+        #define ATOMIC_USER
+    #endif
+    #ifndef WOLFSSL_DER_LOAD
+        #define WOLFSSL_DER_LOAD
+    #endif
+    #ifndef KEEP_PEER_CERT
+        #define KEEP_PEER_CERT
+    #endif
+    #ifndef HAVE_ECC
+        #define HAVE_ECC
+    #endif
+    #ifndef SESSION_INDEX
+        #define SESSION_INDEX
+    #endif
+#endif /* WOLFSSL_QL */
+
+
+#if defined(WOLFSSL_XILINX)
+    #define NO_WOLFSSL_DIR
+    #define NO_DEV_RANDOM
+    #define HAVE_AESGCM
+#endif
+
+#if defined(WOLFSSL_XILINX_CRYPT) || defined(WOLFSSL_AFALG_XILINX)
+    #if defined(WOLFSSL_ARMASM)
+        #error can not use both ARMv8 instructions and XILINX hardened crypto
+    #endif
+    #if defined(WOLFSSL_SHA3)
+        /* only SHA3-384 is supported */
+        #undef WOLFSSL_NOSHA3_224
+        #undef WOLFSSL_NOSHA3_256
+        #undef WOLFSSL_NOSHA3_512
+        #define WOLFSSL_NOSHA3_224
+        #define WOLFSSL_NOSHA3_256
+        #define WOLFSSL_NOSHA3_512
+    #endif
+    #ifdef WOLFSSL_AFALG_XILINX_AES
+        #undef  WOLFSSL_AES_DIRECT
+        #define WOLFSSL_AES_DIRECT
+    #endif
+#endif /*(WOLFSSL_XILINX_CRYPT)*/
+
+#if defined(WOLFSSL_APACHE_MYNEWT)
+    #include "os/os_malloc.h"
+    #if !defined(WOLFSSL_LWIP)
+        #include <mn_socket/mn_socket.h>
+    #endif
+
+    #if !defined(SIZEOF_LONG)
+        #define SIZEOF_LONG 4
+    #endif
+    #if !defined(SIZEOF_LONG_LONG)
+        #define SIZEOF_LONG_LONG 8
+    #endif
+    #if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+        #define BIG_ENDIAN_ORDER
+    #else
+        #undef  BIG_ENDIAN_ORDER
+        #define LITTLE_ENDIAN_ORDER
+    #endif
+    #define NO_WRITEV
+    #define WOLFSSL_USER_IO
+    #define SINGLE_THREADED
+    #define NO_DEV_RANDOM
+    #define NO_DH
+    #define NO_WOLFSSL_DIR
+    #define NO_ERROR_STRINGS
+    #define HAVE_ECC
+    #define NO_SESSION_CACHE
+    #define NO_ERROR_STRINGS
+    #define XMALLOC_USER
+    #define XMALLOC(sz, heap, type)     os_malloc(sz)
+    #define XREALLOC(p, sz, heap, type) os_realloc(p, sz)
+    #define XFREE(p, heap, type)        os_free(p)
+
+#endif /*(WOLFSSL_APACHE_MYNEWT)*/
+
+#ifdef WOLFSSL_ZEPHYR
+    #include <zephyr.h>
+    #include <misc/printk.h>
+    #include <misc/util.h>
+    #include <stdlib.h>
+
+    #define WOLFSSL_DH_CONST
+    #define WOLFSSL_HAVE_MIN
+    #define WOLFSSL_HAVE_MAX
+    #define NO_WRITEV
+
+    #define USE_FLAT_BENCHMARK_H
+    #define USE_FLAT_TEST_H
+    #define EXIT_FAILURE 1
+    #define MAIN_NO_ARGS
+
+    void *z_realloc(void *ptr, size_t size);
+    #define realloc   z_realloc
+
+    #define CONFIG_NET_SOCKETS_POSIX_NAMES
+#endif
+
+#ifdef WOLFSSL_IMX6
+    #ifndef SIZEOF_LONG_LONG
+        #define SIZEOF_LONG_LONG 8
+    #endif
+#endif
+
+/* if defined turn on all CAAM support */
+#ifdef WOLFSSL_IMX6_CAAM
+    #undef  WOLFSSL_IMX6_CAAM_RNG
+    #define WOLFSSL_IMX6_CAAM_RNG
+
+    #undef  WOLFSSL_IMX6_CAAM_BLOB
+    #define WOLFSSL_IMX6_CAAM_BLOB
+
+#if defined(HAVE_AESGCM) || defined(WOLFSSL_AES_XTS)
+    /* large performance gain with HAVE_AES_ECB defined */
+    #undef HAVE_AES_ECB
+    #define HAVE_AES_ECB
+#endif
+#endif
+
+#if !defined(XMALLOC_USER) && !defined(MICRIUM_MALLOC) && \
+    !defined(WOLFSSL_LEANPSK) && !defined(NO_WOLFSSL_MEMORY) && \
+    !defined(XMALLOC_OVERRIDE)
+    #define USE_WOLFSSL_MEMORY
+#endif
+
+
+#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS)
+    #undef  KEEP_PEER_CERT
+    #define KEEP_PEER_CERT
+#endif
+
+
+/* stream ciphers except arc4 need 32bit alignment, intel ok without */
+#ifndef XSTREAM_ALIGN
+    #if defined(__x86_64__) || defined(__ia64__) || defined(__i386__)
+        #define NO_XSTREAM_ALIGN
+    #else
+        #define XSTREAM_ALIGN
+    #endif
+#endif
+
+/* write dup cannot be used with secure renegotiation because write dup
+ * make write side write only and read side read only */
+#if defined(HAVE_WRITE_DUP) && defined(HAVE_SECURE_RENEGOTIATION)
+    #error "WRITE DUP and SECURE RENEGOTIATION cannot both be on"
+#endif
+
+#ifdef WOLFSSL_SGX
+    #ifdef _MSC_VER
+        #define NO_RC4
+        #ifndef HAVE_FIPS
+            #define WOLFCRYPT_ONLY
+            #define NO_DES3
+            #define NO_SHA
+            #define NO_MD5
+        #else
+            #define TFM_TIMING_RESISTANT
+            #define NO_WOLFSSL_DIR
+            #define NO_WRITEV
+            #define NO_MAIN_DRIVER
+            #define WOLFSSL_LOG_PRINTF
+            #define WOLFSSL_DH_CONST
+        #endif
+    #else
+        #define HAVE_ECC
+        #define NO_WRITEV
+        #define NO_MAIN_DRIVER
+        #define USER_TICKS
+        #define WOLFSSL_LOG_PRINTF
+        #define WOLFSSL_DH_CONST
+    #endif /* _MSC_VER */
+    #if !defined(HAVE_FIPS) && !defined(NO_RSA)
+        #define WC_RSA_BLINDING
+    #endif
+
+    #define NO_FILESYSTEM
+    #define ECC_TIMING_RESISTANT
+    #define TFM_TIMING_RESISTANT
+    #define SINGLE_THREADED
+    #define NO_ASN_TIME /* can not use headers such as windows.h */
+    #define HAVE_AESGCM
+    #define USE_CERT_BUFFERS_2048
+    #define USE_FAST_MATH
+#endif /* WOLFSSL_SGX */
+
+/* FreeScale MMCAU hardware crypto has 4 byte alignment.
+   However, KSDK fsl_mmcau.h gives API with no alignment
+   requirements (4 byte alignment is managed internally by fsl_mmcau.c) */
+#ifdef FREESCALE_MMCAU
+    #ifdef FREESCALE_MMCAU_CLASSIC
+        #define WOLFSSL_MMCAU_ALIGNMENT 4
+    #else
+        #define WOLFSSL_MMCAU_ALIGNMENT 0
+    #endif
+#endif
+
+/* if using hardware crypto and have alignment requirements, specify the
+   requirement here.  The record header of SSL/TLS will prevent easy alignment.
+   This hint tries to help as much as possible.  */
+#ifndef WOLFSSL_GENERAL_ALIGNMENT
+    #ifdef WOLFSSL_AESNI
+        #define WOLFSSL_GENERAL_ALIGNMENT 16
+    #elif defined(XSTREAM_ALIGN)
+        #define WOLFSSL_GENERAL_ALIGNMENT  4
+    #elif defined(FREESCALE_MMCAU) || defined(FREESCALE_MMCAU_CLASSIC)
+        #define WOLFSSL_GENERAL_ALIGNMENT  WOLFSSL_MMCAU_ALIGNMENT
+    #else
+        #define WOLFSSL_GENERAL_ALIGNMENT  0
+    #endif
+#endif
+
+#if defined(WOLFSSL_GENERAL_ALIGNMENT) && (WOLFSSL_GENERAL_ALIGNMENT > 0)
+    #if defined(_MSC_VER)
+        #define XGEN_ALIGN __declspec(align(WOLFSSL_GENERAL_ALIGNMENT))
+    #elif defined(__GNUC__)
+        #define XGEN_ALIGN __attribute__((aligned(WOLFSSL_GENERAL_ALIGNMENT)))
+    #else
+        #define XGEN_ALIGN
+    #endif
+#else
+    #define XGEN_ALIGN
+#endif
+
+
+#ifdef __INTEL_COMPILER
+    #pragma warning(disable:2259) /* explicit casts to smaller sizes, disable */
+#endif
+
+/* user can specify what curves they want with ECC_USER_CURVES otherwise
+ * all curves are on by default for now */
+#ifndef ECC_USER_CURVES
+    #if !defined(WOLFSSL_SP_MATH) && !defined(HAVE_ALL_CURVES)
+        #define HAVE_ALL_CURVES
+    #endif
+#endif
+
+/* ECC Configs */
+#ifdef HAVE_ECC
+    /* By default enable Sign, Verify, DHE, Key Import and Key Export unless explicitly disabled */
+    #ifndef NO_ECC_SIGN
+        #undef HAVE_ECC_SIGN
+        #define HAVE_ECC_SIGN
+    #endif
+    #ifndef NO_ECC_VERIFY
+        #undef HAVE_ECC_VERIFY
+        #define HAVE_ECC_VERIFY
+    #endif
+    #ifndef NO_ECC_CHECK_KEY
+        #undef HAVE_ECC_CHECK_KEY
+        #define HAVE_ECC_CHECK_KEY
+    #endif
+    #ifndef NO_ECC_DHE
+        #undef HAVE_ECC_DHE
+        #define HAVE_ECC_DHE
+    #endif
+    #ifndef NO_ECC_KEY_IMPORT
+        #undef HAVE_ECC_KEY_IMPORT
+        #define HAVE_ECC_KEY_IMPORT
+    #endif
+    #ifndef NO_ECC_KEY_EXPORT
+        #undef HAVE_ECC_KEY_EXPORT
+        #define HAVE_ECC_KEY_EXPORT
+    #endif
+#endif /* HAVE_ECC */
+
+/* Curve25519 Configs */
+#ifdef HAVE_CURVE25519
+    /* By default enable shared secret, key export and import */
+    #ifndef NO_CURVE25519_SHARED_SECRET
+        #undef HAVE_CURVE25519_SHARED_SECRET
+        #define HAVE_CURVE25519_SHARED_SECRET
+    #endif
+    #ifndef NO_CURVE25519_KEY_EXPORT
+        #undef HAVE_CURVE25519_KEY_EXPORT
+        #define HAVE_CURVE25519_KEY_EXPORT
+    #endif
+    #ifndef NO_CURVE25519_KEY_IMPORT
+        #undef HAVE_CURVE25519_KEY_IMPORT
+        #define HAVE_CURVE25519_KEY_IMPORT
+    #endif
+#endif /* HAVE_CURVE25519 */
+
+/* Ed25519 Configs */
+#ifdef HAVE_ED25519
+    /* By default enable sign, verify, key export and import */
+    #ifndef NO_ED25519_SIGN
+        #undef HAVE_ED25519_SIGN
+        #define HAVE_ED25519_SIGN
+    #endif
+    #ifndef NO_ED25519_VERIFY
+        #undef HAVE_ED25519_VERIFY
+        #define HAVE_ED25519_VERIFY
+    #endif
+    #ifndef NO_ED25519_KEY_EXPORT
+        #undef HAVE_ED25519_KEY_EXPORT
+        #define HAVE_ED25519_KEY_EXPORT
+    #endif
+    #ifndef NO_ED25519_KEY_IMPORT
+        #undef HAVE_ED25519_KEY_IMPORT
+        #define HAVE_ED25519_KEY_IMPORT
+    #endif
+#endif /* HAVE_ED25519 */
+
+/* Curve448 Configs */
+#ifdef HAVE_CURVE448
+    /* By default enable shared secret, key export and import */
+    #ifndef NO_CURVE448_SHARED_SECRET
+        #undef HAVE_CURVE448_SHARED_SECRET
+        #define HAVE_CURVE448_SHARED_SECRET
+    #endif
+    #ifndef NO_CURVE448_KEY_EXPORT
+        #undef HAVE_CURVE448_KEY_EXPORT
+        #define HAVE_CURVE448_KEY_EXPORT
+    #endif
+    #ifndef NO_CURVE448_KEY_IMPORT
+        #undef HAVE_CURVE448_KEY_IMPORT
+        #define HAVE_CURVE448_KEY_IMPORT
+    #endif
+#endif /* HAVE_CURVE448 */
+
+/* Ed448 Configs */
+#ifdef HAVE_ED448
+    /* By default enable sign, verify, key export and import */
+    #ifndef NO_ED448_SIGN
+        #undef HAVE_ED448_SIGN
+        #define HAVE_ED448_SIGN
+    #endif
+    #ifndef NO_ED448_VERIFY
+        #undef HAVE_ED448_VERIFY
+        #define HAVE_ED448_VERIFY
+    #endif
+    #ifndef NO_ED448_KEY_EXPORT
+        #undef HAVE_ED448_KEY_EXPORT
+        #define HAVE_ED448_KEY_EXPORT
+    #endif
+    #ifndef NO_ED448_KEY_IMPORT
+        #undef HAVE_ED448_KEY_IMPORT
+        #define HAVE_ED448_KEY_IMPORT
+    #endif
+#endif /* HAVE_ED448 */
+
+/* AES Config */
+#ifndef NO_AES
+    /* By default enable all AES key sizes, decryption and CBC */
+    #ifndef AES_MAX_KEY_SIZE
+        #undef  AES_MAX_KEY_SIZE
+        #define AES_MAX_KEY_SIZE    256
+    #endif
+
+    #ifndef NO_AES_128
+        #undef  WOLFSSL_AES_128
+        #define WOLFSSL_AES_128
+    #endif
+    #if !defined(NO_AES_192) && AES_MAX_KEY_SIZE >= 192
+        #undef  WOLFSSL_AES_192
+        #define WOLFSSL_AES_192
+    #endif
+    #if !defined(NO_AES_256) && AES_MAX_KEY_SIZE >= 256
+        #undef  WOLFSSL_AES_256
+        #define WOLFSSL_AES_256
+    #endif
+    #if !defined(WOLFSSL_AES_128) && defined(HAVE_ECC_ENCRYPT)
+        #warning HAVE_ECC_ENCRYPT uses AES 128 bit keys
+     #endif
+
+    #ifndef NO_AES_DECRYPT
+        #undef  HAVE_AES_DECRYPT
+        #define HAVE_AES_DECRYPT
+    #endif
+    #ifndef NO_AES_CBC
+        #undef  HAVE_AES_CBC
+        #define HAVE_AES_CBC
+    #endif
+    #ifdef WOLFSSL_AES_XTS
+        /* AES-XTS makes calls to AES direct functions */
+        #ifndef WOLFSSL_AES_DIRECT
+        #define WOLFSSL_AES_DIRECT
+        #endif
+    #endif
+    #ifdef WOLFSSL_AES_CFB
+        /* AES-CFB makes calls to AES direct functions */
+        #ifndef WOLFSSL_AES_DIRECT
+        #define WOLFSSL_AES_DIRECT
+        #endif
+    #endif
+#endif
+
+#if (defined(WOLFSSL_TLS13) && defined(WOLFSSL_NO_TLS12)) || \
+    (!defined(HAVE_AES_CBC) && defined(NO_DES3) && defined(NO_RC4) && \
+     !defined(HAVE_CAMELLIA) && !defined(HAVE_IDEA) && \
+     !defined(HAVE_NULL_CIPHER) && !defined(HAVE_HC128))
+    #define WOLFSSL_AEAD_ONLY
+#endif
+
+#if !defined(NO_DH) && !defined(HAVE_FFDHE)
+    #if defined(HAVE_FFDHE_2048) || defined(HAVE_FFDHE_3072) || \
+            defined(HAVE_FFDHE_4096) || defined(HAVE_FFDHE_6144) || \
+            defined(HAVE_FFDHE_8192)
+        #define HAVE_FFDHE
+    #endif
+#endif
+#if defined(HAVE_FFDHE_8192)
+    #define MIN_FFDHE_FP_MAX_BITS 16384
+#elif defined(HAVE_FFDHE_6144)
+    #define MIN_FFDHE_FP_MAX_BITS 12288
+#elif defined(HAVE_FFDHE_4096)
+    #define MIN_FFDHE_FP_MAX_BITS 8192
+#elif defined(HAVE_FFDHE_3072)
+    #define MIN_FFDHE_FP_MAX_BITS 6144
+#elif defined(HAVE_FFDHE_2048)
+    #define MIN_FFDHE_FP_MAX_BITS 4096
+#else
+    #define MIN_FFDHE_FP_MAX_BITS 0
+#endif
+#if defined(HAVE_FFDHE) && defined(FP_MAX_BITS)
+    #if MIN_FFDHE_FP_MAX_BITS > FP_MAX_BITS
+        #error "FFDHE parameters are too large for FP_MAX_BIT as set"
+    #endif
+#endif
+
+/* if desktop type system and fastmath increase default max bits */
+#ifdef WOLFSSL_X86_64_BUILD
+    #if defined(USE_FAST_MATH) && !defined(FP_MAX_BITS)
+        #if MIN_FFDHE_FP_MAX_BITS <= 8192
+            #define FP_MAX_BITS 8192
+        #else
+            #define FP_MAX_BITS MIN_FFDHE_FP_MAX_BITS
+        #endif
+    #endif
+#endif
+
+/* If using the max strength build, ensure OLD TLS is disabled. */
+#ifdef WOLFSSL_MAX_STRENGTH
+    #undef NO_OLD_TLS
+    #define NO_OLD_TLS
+#endif
+
+
+/* Default AES minimum auth tag sz, allow user to override */
+#ifndef WOLFSSL_MIN_AUTH_TAG_SZ
+    #define WOLFSSL_MIN_AUTH_TAG_SZ 12
+#endif
+
+
+/* sniffer requires:
+ * static RSA cipher suites
+ * session stats and peak stats
+ */
+#ifdef WOLFSSL_SNIFFER
+    #ifndef WOLFSSL_STATIC_RSA
+        #define WOLFSSL_STATIC_RSA
+    #endif
+    #ifndef WOLFSSL_STATIC_DH
+        #define WOLFSSL_STATIC_DH
+    #endif
+    /* Allow option to be disabled. */
+    #ifndef WOLFSSL_NO_SESSION_STATS
+        #ifndef WOLFSSL_SESSION_STATS
+            #define WOLFSSL_SESSION_STATS
+        #endif
+        #ifndef WOLFSSL_PEAK_SESSIONS
+            #define WOLFSSL_PEAK_SESSIONS
+        #endif
+    #endif
+#endif
+
+/* Decode Public Key extras on by default, user can turn off with
+ * WOLFSSL_NO_DECODE_EXTRA */
+#ifndef WOLFSSL_NO_DECODE_EXTRA
+    #ifndef RSA_DECODE_EXTRA
+        #define RSA_DECODE_EXTRA
+    #endif
+    #ifndef ECC_DECODE_EXTRA
+        #define ECC_DECODE_EXTRA
+    #endif
+#endif
+
+/* C Sharp wrapper defines */
+#ifdef HAVE_CSHARP
+    #ifndef WOLFSSL_DTLS
+        #define WOLFSSL_DTLS
+    #endif
+    #undef NO_PSK
+    #undef NO_SHA256
+    #undef NO_DH
+#endif
+
+/* Asynchronous Crypto */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* Make sure wolf events are enabled */
+    #undef HAVE_WOLF_EVENT
+    #define HAVE_WOLF_EVENT
+
+    #ifdef WOLFSSL_ASYNC_CRYPT_TEST
+        #define WC_ASYNC_DEV_SIZE 168
+    #else
+        #define WC_ASYNC_DEV_SIZE 336
+    #endif
+
+    #if !defined(HAVE_CAVIUM) && !defined(HAVE_INTEL_QA) && \
+        !defined(WOLFSSL_ASYNC_CRYPT_TEST)
+        #error No async hardware defined with WOLFSSL_ASYNC_CRYPT!
+    #endif
+
+    /* Enable ECC_CACHE_CURVE for ASYNC */
+    #if !defined(ECC_CACHE_CURVE)
+        #define ECC_CACHE_CURVE
+    #endif
+#endif /* WOLFSSL_ASYNC_CRYPT */
+#ifndef WC_ASYNC_DEV_SIZE
+    #define WC_ASYNC_DEV_SIZE 0
+#endif
+
+/* leantls checks */
+#ifdef WOLFSSL_LEANTLS
+    #ifndef HAVE_ECC
+        #error leantls build needs ECC
+    #endif
+#endif /* WOLFSSL_LEANTLS*/
+
+/* restriction with static memory */
+#ifdef WOLFSSL_STATIC_MEMORY
+    #if defined(HAVE_IO_POOL) || defined(XMALLOC_USER) || defined(NO_WOLFSSL_MEMORY)
+         #error static memory cannot be used with HAVE_IO_POOL, XMALLOC_USER or NO_WOLFSSL_MEMORY
+    #endif
+    #if !defined(USE_FAST_MATH) && !defined(NO_BIG_INT)
+        #error static memory requires fast math please define USE_FAST_MATH
+    #endif
+    #ifdef WOLFSSL_SMALL_STACK
+        #error static memory does not support small stack please undefine
+    #endif
+#endif /* WOLFSSL_STATIC_MEMORY */
+
+#ifdef HAVE_AES_KEYWRAP
+    #ifndef WOLFSSL_AES_DIRECT
+        #error AES key wrap requires AES direct please define WOLFSSL_AES_DIRECT
+    #endif
+#endif
+
+#ifdef HAVE_PKCS7
+    #if defined(NO_AES) && defined(NO_DES3)
+        #error PKCS7 needs either AES or 3DES enabled, please enable one
+    #endif
+    #ifndef HAVE_AES_KEYWRAP
+        #error PKCS7 requires AES key wrap please define HAVE_AES_KEYWRAP
+    #endif
+    #if defined(HAVE_ECC) && !defined(HAVE_X963_KDF)
+        #error PKCS7 requires X963 KDF please define HAVE_X963_KDF
+    #endif
+#endif
+
+#ifndef NO_PKCS12
+    #undef  HAVE_PKCS12
+    #define HAVE_PKCS12
+#endif
+
+#ifndef NO_PKCS8
+    #undef  HAVE_PKCS8
+    #define HAVE_PKCS8
+#endif
+
+#if !defined(NO_PBKDF1) || defined(WOLFSSL_ENCRYPTED_KEYS) || defined(HAVE_PKCS8) || defined(HAVE_PKCS12)
+    #undef  HAVE_PBKDF1
+    #define HAVE_PBKDF1
+#endif
+
+#if !defined(NO_PBKDF2) || defined(HAVE_PKCS7) || defined(HAVE_SCRYPT)
+    #undef  HAVE_PBKDF2
+    #define HAVE_PBKDF2
+#endif
+
+
+#if !defined(WOLFCRYPT_ONLY) && !defined(NO_OLD_TLS) && \
+        (defined(NO_SHA) || defined(NO_MD5))
+    #error old TLS requires MD5 and SHA
+#endif
+
+/* for backwards compatibility */
+#if defined(TEST_IPV6) && !defined(WOLFSSL_IPV6)
+    #define WOLFSSL_IPV6
+#endif
+
+
+/* Place any other flags or defines here */
+
+#if defined(WOLFSSL_MYSQL_COMPATIBLE) && defined(_WIN32) \
+                                      && defined(HAVE_GMTIME_R)
+    #undef HAVE_GMTIME_R /* don't trust macro with windows */
+#endif /* WOLFSSL_MYSQL_COMPATIBLE */
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+    #define SSL_OP_NO_COMPRESSION    SSL_OP_NO_COMPRESSION
+    #define OPENSSL_NO_ENGINE
+    #define X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT
+    #ifndef OPENSSL_EXTRA
+        #define OPENSSL_EXTRA
+    #endif
+    #ifndef HAVE_SESSION_TICKET
+        #define HAVE_SESSION_TICKET
+    #endif
+    #ifndef HAVE_OCSP
+        #define HAVE_OCSP
+    #endif
+    #ifndef KEEP_OUR_CERT
+        #define KEEP_OUR_CERT
+    #endif
+    #ifndef HAVE_SNI
+        #define HAVE_SNI
+    #endif
+#endif
+
+#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+    #define SSL_CTRL_SET_TLSEXT_HOSTNAME 55
+#endif
+
+
+/* both CURVE and ED small math should be enabled */
+#ifdef CURVED25519_SMALL
+        #define CURVE25519_SMALL
+        #define ED25519_SMALL
+#endif
+
+/* both CURVE and ED small math should be enabled */
+#ifdef CURVED448_SMALL
+        #define CURVE448_SMALL
+        #define ED448_SMALL
+#endif
+
+
+#ifndef WOLFSSL_ALERT_COUNT_MAX
+    #define WOLFSSL_ALERT_COUNT_MAX 5
+#endif
+
+/* warning for not using harden build options (default with ./configure) */
+#ifndef WC_NO_HARDEN
+    #if (defined(USE_FAST_MATH) && !defined(TFM_TIMING_RESISTANT)) || \
+        (defined(HAVE_ECC) && !defined(ECC_TIMING_RESISTANT)) || \
+        (!defined(NO_RSA) && !defined(WC_RSA_BLINDING) && !defined(HAVE_FIPS) && \
+            !defined(WC_NO_RNG))
+
+        #ifndef _MSC_VER
+            #warning "For timing resistance / side-channel attack prevention consider using harden options"
+        #else
+            #pragma message("Warning: For timing resistance / side-channel attack prevention consider using harden options")
+        #endif
+    #endif
+#endif
+
+#if defined(NO_OLD_WC_NAMES) || defined(OPENSSL_EXTRA)
+    /* added to have compatibility with SHA256() */
+    #if !defined(NO_OLD_SHA_NAMES) && !defined(HAVE_FIPS)
+        #define NO_OLD_SHA_NAMES
+    #endif
+#endif
+
+/* switch for compatibility layer functionality. Has subparts i.e. BIO/X509
+ * When opensslextra is enabled all subparts should be turned on. */
+#ifdef OPENSSL_EXTRA
+    #undef  OPENSSL_EXTRA_X509_SMALL
+    #define OPENSSL_EXTRA_X509_SMALL
+#endif /* OPENSSL_EXTRA */
+
+/* support for converting DER to PEM */
+#if (defined(WOLFSSL_KEY_GEN) && !defined(WOLFSSL_NO_DER_TO_PEM)) || \
+    defined(WOLFSSL_CERT_GEN) || defined(OPENSSL_EXTRA)
+    #undef  WOLFSSL_DER_TO_PEM
+    #define WOLFSSL_DER_TO_PEM
+#endif
+
+/* keep backwards compatibility enabling encrypted private key */
+#ifndef WOLFSSL_ENCRYPTED_KEYS
+    #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \
+        defined(HAVE_WEBSERVER)
+        #define WOLFSSL_ENCRYPTED_KEYS
+    #endif
+#endif
+
+/* support for disabling PEM to DER */
+#if !defined(WOLFSSL_NO_PEM)
+    #undef  WOLFSSL_PEM_TO_DER
+    #define WOLFSSL_PEM_TO_DER
+#endif
+
+/* Parts of the openssl compatibility layer require peer certs */
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+    #undef  KEEP_PEER_CERT
+    #define KEEP_PEER_CERT
+#endif
+
+/* RAW hash function APIs are not implemented with ARMv8 hardware acceleration*/
+#ifdef WOLFSSL_ARMASM
+    #undef  WOLFSSL_NO_HASH_RAW
+    #define WOLFSSL_NO_HASH_RAW
+#endif
+
+#if !defined(WOLFSSL_SHA384) && !defined(WOLFSSL_SHA512) && defined(NO_AES) && \
+                                                          !defined(WOLFSSL_SHA3)
+    #undef  WOLFSSL_NO_WORD64_OPS
+    #define WOLFSSL_NO_WORD64_OPS
+#endif
+
+#if !defined(WOLFCRYPT_ONLY) && !defined(WOLFSSL_NO_TLS12)
+    #undef  WOLFSSL_HAVE_PRF
+    #define WOLFSSL_HAVE_PRF
+#endif
+
+#if defined(NO_AES) && defined(NO_DES3) && !defined(HAVE_CAMELLIA) && \
+       !defined(WOLFSSL_HAVE_PRF) && defined(NO_PWDBASED) && !defined(HAVE_IDEA)
+    #undef  WOLFSSL_NO_XOR_OPS
+    #define WOLFSSL_NO_XOR_OPS
+#endif
+
+#if defined(NO_ASN) && defined(WOLFCRYPT_ONLY)
+    #undef  WOLFSSL_NO_INT_ENCODE
+    #define WOLFSSL_NO_INT_ENCODE
+    #undef  WOLFSSL_NO_INT_DECODE
+    #define WOLFSSL_NO_INT_DECODE
+#endif
+
+#if defined(WOLFCRYPT_ONLY) && defined(WOLFSSL_RSA_VERIFY_ONLY) && \
+    defined(WC_NO_RSA_OAEP)
+    #undef  WOLFSSL_NO_CT_OPS
+    #define WOLFSSL_NO_CT_OPS
+#endif
+
+#if defined(WOLFCRYPT_ONLY) && defined(NO_AES) && !defined(HAVE_CURVE25519) && \
+        !defined(HAVE_CURVE448) && defined(WC_NO_RNG) && defined(WC_NO_RSA_OAEP)
+    #undef  WOLFSSL_NO_CONST_CMP
+    #define WOLFSSL_NO_CONST_CMP
+#endif
+
+#if defined(WOLFCRYPT_ONLY) && defined(NO_AES) && !defined(WOLFSSL_SHA384) && \
+    !defined(WOLFSSL_SHA512) && defined(WC_NO_RNG) && \
+                    defined(WOLFSSL_SP_MATH) && defined(WOLFSSL_RSA_PUBLIC_ONLY)
+    #undef  WOLFSSL_NO_FORCE_ZERO
+    #define WOLFSSL_NO_FORCE_ZERO
+#endif
+
+/* Detect old cryptodev name */
+#if defined(WOLF_CRYPTO_DEV) && !defined(WOLF_CRYPTO_CB)
+    #define WOLF_CRYPTO_CB
+#endif
+
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_NO_SIGALG)
+    #error TLS 1.3 requires the Signature Algorithms extension to be enabled
+#endif
+
+#ifndef NO_WOLFSSL_BASE64_DECODE
+    #define WOLFSSL_BASE64_DECODE
+#endif
+
+#if defined(HAVE_EX_DATA) || defined(FORTRESS)
+    #define MAX_EX_DATA 5  /* allow for five items of ex_data */
+#endif
+
+#ifdef NO_WOLFSSL_SMALL_STACK
+    #undef WOLFSSL_SMALL_STACK
+#endif
+
+/* The client session cache requires time for timeout */
+#if defined(NO_ASN_TIME) && !defined(NO_SESSION_CACHE)
+    #define NO_SESSION_CACHE
+#endif
+
+/* Use static ECC structs for Position Independant Code (PIC) */
+#if defined(__IAR_SYSTEMS_ICC__) && defined(__ROPI__)
+    #define WOLFSSL_ECC_CURVE_STATIC
+    #define WOLFSSL_NAMES_STATIC
+    #define WOLFSSL_NO_CONSTCHARCONST
+#endif
+
+
+#ifdef __cplusplus
+    }   /* extern "C" */
+#endif
+
+#endif
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/sha.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/sha.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/sha.h	(revision 453)
@@ -0,0 +1,178 @@
+/* sha.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/sha.h
+*/
+
+
+#ifndef WOLF_CRYPT_SHA_H
+#define WOLF_CRYPT_SHA_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifndef NO_SHA
+
+#if defined(HAVE_FIPS) && \
+    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
+    #include <wolfssl/wolfcrypt/fips.h>
+#endif /* HAVE_FIPS_VERSION >= 2 */
+
+#if defined(HAVE_FIPS) && \
+	(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
+#define wc_Sha             Sha
+#define WC_SHA             SHA
+#define WC_SHA_BLOCK_SIZE  SHA_BLOCK_SIZE
+#define WC_SHA_DIGEST_SIZE SHA_DIGEST_SIZE
+#define WC_SHA_PAD_SIZE    SHA_PAD_SIZE
+
+/* for fips @wc_fips */
+#include <cyassl/ctaocrypt/sha.h>
+#endif
+
+#ifdef FREESCALE_LTC_SHA
+    #include "fsl_ltc.h"
+#endif
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+/* avoid redefinition of structs */
+#if !defined(HAVE_FIPS) || \
+    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))
+
+#ifdef WOLFSSL_MICROCHIP_PIC32MZ
+    #include <wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h>
+#endif
+#ifdef STM32_HASH
+    #include <wolfssl/wolfcrypt/port/st/stm32.h>
+#endif
+#ifdef WOLFSSL_ASYNC_CRYPT
+    #include <wolfssl/wolfcrypt/async.h>
+#endif
+#ifdef WOLFSSL_ESP32WROOM32_CRYPT
+    #include <wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h>
+#endif
+
+#if !defined(NO_OLD_SHA_NAMES)
+    #define SHA             WC_SHA
+#endif
+
+#ifndef NO_OLD_WC_NAMES
+    #define Sha             wc_Sha
+    #define SHA_BLOCK_SIZE  WC_SHA_BLOCK_SIZE
+    #define SHA_DIGEST_SIZE WC_SHA_DIGEST_SIZE
+    #define SHA_PAD_SIZE    WC_SHA_PAD_SIZE
+#endif
+
+/* in bytes */
+enum {
+    WC_SHA              =  WC_HASH_TYPE_SHA,
+    WC_SHA_BLOCK_SIZE   = 64,
+    WC_SHA_DIGEST_SIZE  = 20,
+    WC_SHA_PAD_SIZE     = 56
+};
+
+
+#if defined(WOLFSSL_TI_HASH)
+    #include "wolfssl/wolfcrypt/port/ti/ti-hash.h"
+
+#elif defined(WOLFSSL_IMX6_CAAM)
+    #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h"
+#elif defined(WOLFSSL_RENESAS_TSIP_CRYPT) && \
+   !defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH)
+    #include "wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h"
+#else
+
+/* Sha digest */
+struct wc_Sha {
+#ifdef FREESCALE_LTC_SHA
+        ltc_hash_ctx_t ctx;
+#elif defined(STM32_HASH)
+        STM32_HASH_Context stmCtx;
+#else
+        word32  buffLen;   /* in bytes          */
+        word32  loLen;     /* length in bytes   */
+        word32  hiLen;     /* length in bytes   */
+        word32  buffer[WC_SHA_BLOCK_SIZE  / sizeof(word32)];
+    #ifdef WOLFSSL_PIC32MZ_HASH
+        word32  digest[PIC32_DIGEST_SIZE / sizeof(word32)];
+    #else
+        word32  digest[WC_SHA_DIGEST_SIZE / sizeof(word32)];
+    #endif
+        void*   heap;
+    #ifdef WOLFSSL_PIC32MZ_HASH
+        hashUpdCache cache; /* cache for updates */
+    #endif
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        WC_ASYNC_DEV asyncDev;
+    #endif /* WOLFSSL_ASYNC_CRYPT */
+    #ifdef WOLF_CRYPTO_CB
+        int    devId;
+        void*  devCtx; /* generic crypto callback context */
+    #endif
+#endif
+#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+   !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+    WC_ESP32SHA ctx;
+#endif
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+    word32 flags; /* enum wc_HashFlags in hash.h */
+#endif
+};
+
+#ifndef WC_SHA_TYPE_DEFINED
+    typedef struct wc_Sha wc_Sha;
+    #define WC_SHA_TYPE_DEFINED
+#endif
+
+#endif /* WOLFSSL_TI_HASH */
+
+
+#endif /* HAVE_FIPS */
+
+WOLFSSL_API int wc_InitSha(wc_Sha*);
+WOLFSSL_API int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId);
+WOLFSSL_API int wc_ShaUpdate(wc_Sha*, const byte*, word32);
+WOLFSSL_API int wc_ShaFinalRaw(wc_Sha*, byte*);
+WOLFSSL_API int wc_ShaFinal(wc_Sha*, byte*);
+WOLFSSL_API void wc_ShaFree(wc_Sha*);
+
+WOLFSSL_API int wc_ShaGetHash(wc_Sha*, byte*);
+WOLFSSL_API int wc_ShaCopy(wc_Sha*, wc_Sha*);
+
+#ifdef WOLFSSL_PIC32MZ_HASH
+WOLFSSL_API void wc_ShaSizeSet(wc_Sha* sha, word32 len);
+#endif
+
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+    WOLFSSL_API int wc_ShaSetFlags(wc_Sha* sha, word32 flags);
+    WOLFSSL_API int wc_ShaGetFlags(wc_Sha* sha, word32* flags);
+#endif
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* NO_SHA */
+#endif /* WOLF_CRYPT_SHA_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/sha256.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/sha256.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/sha256.h	(revision 453)
@@ -0,0 +1,255 @@
+/* sha256.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/sha256.h
+*/
+
+
+
+#ifndef WOLF_CRYPT_SHA256_H
+#define WOLF_CRYPT_SHA256_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#ifndef NO_SHA256
+
+#if defined(HAVE_FIPS) && \
+    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
+    #include <wolfssl/wolfcrypt/fips.h>
+#endif /* HAVE_FIPS_VERSION >= 2 */
+
+#if defined(HAVE_FIPS) && \
+	(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
+    #define wc_Sha256             Sha256
+    #define WC_SHA256             SHA256
+    #define WC_SHA256_BLOCK_SIZE  SHA256_BLOCK_SIZE
+    #define WC_SHA256_DIGEST_SIZE SHA256_DIGEST_SIZE
+    #define WC_SHA256_PAD_SIZE    SHA256_PAD_SIZE
+
+    #ifdef WOLFSSL_SHA224
+        #define wc_Sha224             Sha224
+        #define WC_SHA224             SHA224
+        #define WC_SHA224_BLOCK_SIZE  SHA224_BLOCK_SIZE
+        #define WC_SHA224_DIGEST_SIZE SHA224_DIGEST_SIZE
+        #define WC_SHA224_PAD_SIZE    SHA224_PAD_SIZE
+    #endif
+
+    /* for fips @wc_fips */
+    #include <cyassl/ctaocrypt/sha256.h>
+#endif
+
+#ifdef FREESCALE_LTC_SHA
+    #include "fsl_ltc.h"
+#endif
+
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+/* avoid redefinition of structs */
+#if !defined(HAVE_FIPS) || \
+    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))
+
+#ifdef WOLFSSL_MICROCHIP_PIC32MZ
+    #include <wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h>
+#endif
+#ifdef STM32_HASH
+    #include <wolfssl/wolfcrypt/port/st/stm32.h>
+#endif
+#ifdef WOLFSSL_ASYNC_CRYPT
+    #include <wolfssl/wolfcrypt/async.h>
+#endif
+#if defined(WOLFSSL_DEVCRYPTO) && defined(WOLFSSL_DEVCRYPTO_HASH)
+    #include <wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h>
+#endif
+#if defined(WOLFSSL_ESP32WROOM32_CRYPT)
+    #include "wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h"
+#endif
+#if defined(WOLFSSL_CRYPTOCELL)
+    #include <wolfssl/wolfcrypt/port/arm/cryptoCell.h>
+#endif
+
+#if defined(_MSC_VER)
+    #define SHA256_NOINLINE __declspec(noinline)
+#elif defined(__IAR_SYSTEMS_ICC__) || defined(__GNUC__)
+    #define SHA256_NOINLINE __attribute__((noinline))
+#else
+    #define SHA256_NOINLINE
+#endif
+
+#if !defined(NO_OLD_SHA_NAMES)
+    #define SHA256             WC_SHA256
+#endif
+
+#ifndef NO_OLD_WC_NAMES
+    #define Sha256             wc_Sha256
+    #define SHA256_BLOCK_SIZE  WC_SHA256_BLOCK_SIZE
+    #define SHA256_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
+    #define SHA256_PAD_SIZE    WC_SHA256_PAD_SIZE
+#endif
+
+/* in bytes */
+enum {
+    WC_SHA256              =  WC_HASH_TYPE_SHA256,
+    WC_SHA256_BLOCK_SIZE   = 64,
+    WC_SHA256_DIGEST_SIZE  = 32,
+    WC_SHA256_PAD_SIZE     = 56
+};
+
+
+#ifdef WOLFSSL_TI_HASH
+    #include "wolfssl/wolfcrypt/port/ti/ti-hash.h"
+#elif defined(WOLFSSL_IMX6_CAAM)
+    #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h"
+#elif defined(WOLFSSL_AFALG_HASH)
+    #include "wolfssl/wolfcrypt/port/af_alg/afalg_hash.h"
+#elif defined(WOLFSSL_RENESAS_TSIP_CRYPT) && \
+   !defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH)
+    #include "wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h"
+#else
+
+/* wc_Sha256 digest */
+struct wc_Sha256 {
+#ifdef FREESCALE_LTC_SHA
+    ltc_hash_ctx_t ctx;
+#elif defined(STM32_HASH_SHA2)
+    STM32_HASH_Context stmCtx;
+#else
+    /* alignment on digest and buffer speeds up ARMv8 crypto operations */
+    ALIGN16 word32  digest[WC_SHA256_DIGEST_SIZE / sizeof(word32)];
+    ALIGN16 word32  buffer[WC_SHA256_BLOCK_SIZE  / sizeof(word32)];
+    word32  buffLen;   /* in bytes          */
+    word32  loLen;     /* length in bytes   */
+    word32  hiLen;     /* length in bytes   */
+    void*   heap;
+#ifdef WOLFSSL_PIC32MZ_HASH
+    hashUpdCache cache; /* cache for updates */
+#endif
+#ifdef WOLFSSL_ASYNC_CRYPT
+    WC_ASYNC_DEV asyncDev;
+#endif /* WOLFSSL_ASYNC_CRYPT */
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+    word32* W;
+#endif
+#ifdef WOLFSSL_DEVCRYPTO_HASH
+    WC_CRYPTODEV ctx;
+    byte*  msg;
+    word32 used;
+    word32 len;
+#endif
+#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+   !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+    WC_ESP32SHA ctx;
+#endif
+#ifdef WOLFSSL_CRYPTOCELL
+    CRYS_HASHUserContext_t ctx;
+#endif
+#ifdef WOLF_CRYPTO_CB
+    int    devId;
+    void*  devCtx; /* generic crypto callback context */
+#endif
+#endif
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+    word32 flags; /* enum wc_HashFlags in hash.h */
+#endif
+};
+
+#ifndef WC_SHA256_TYPE_DEFINED
+    typedef struct wc_Sha256 wc_Sha256;
+    #define WC_SHA256_TYPE_DEFINED
+#endif
+
+#endif
+
+#endif /* HAVE_FIPS */
+
+WOLFSSL_API int wc_InitSha256(wc_Sha256*);
+WOLFSSL_API int wc_InitSha256_ex(wc_Sha256*, void*, int);
+WOLFSSL_API int wc_Sha256Update(wc_Sha256*, const byte*, word32);
+WOLFSSL_API int wc_Sha256FinalRaw(wc_Sha256*, byte*);
+WOLFSSL_API int wc_Sha256Final(wc_Sha256*, byte*);
+WOLFSSL_API void wc_Sha256Free(wc_Sha256*);
+
+WOLFSSL_API int wc_Sha256GetHash(wc_Sha256*, byte*);
+WOLFSSL_API int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst);
+
+#ifdef WOLFSSL_PIC32MZ_HASH
+WOLFSSL_API void wc_Sha256SizeSet(wc_Sha256*, word32);
+#endif
+
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+    WOLFSSL_API int wc_Sha256SetFlags(wc_Sha256* sha256, word32 flags);
+    WOLFSSL_API int wc_Sha256GetFlags(wc_Sha256* sha256, word32* flags);
+#endif
+
+#ifdef WOLFSSL_SHA224
+/* avoid redefinition of structs */
+#if !defined(HAVE_FIPS) || \
+    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))
+
+#ifndef NO_OLD_WC_NAMES
+    #define Sha224             wc_Sha224
+    #define SHA224             WC_SHA224
+    #define SHA224_BLOCK_SIZE  WC_SHA224_BLOCK_SIZE
+    #define SHA224_DIGEST_SIZE WC_SHA224_DIGEST_SIZE
+    #define SHA224_PAD_SIZE    WC_SHA224_PAD_SIZE
+#endif
+
+/* in bytes */
+enum {
+    WC_SHA224              =   WC_HASH_TYPE_SHA224,
+    WC_SHA224_BLOCK_SIZE   =   WC_SHA256_BLOCK_SIZE,
+    WC_SHA224_DIGEST_SIZE  =   28,
+    WC_SHA224_PAD_SIZE     =   WC_SHA256_PAD_SIZE
+};
+
+
+#ifndef WC_SHA224_TYPE_DEFINED
+    typedef struct wc_Sha256 wc_Sha224;
+    #define WC_SHA224_TYPE_DEFINED
+#endif
+#endif /* HAVE_FIPS */
+
+WOLFSSL_API int wc_InitSha224(wc_Sha224*);
+WOLFSSL_API int wc_InitSha224_ex(wc_Sha224*, void*, int);
+WOLFSSL_API int wc_Sha224Update(wc_Sha224*, const byte*, word32);
+WOLFSSL_API int wc_Sha224Final(wc_Sha224*, byte*);
+WOLFSSL_API void wc_Sha224Free(wc_Sha224*);
+
+WOLFSSL_API int wc_Sha224GetHash(wc_Sha224*, byte*);
+WOLFSSL_API int wc_Sha224Copy(wc_Sha224* src, wc_Sha224* dst);
+
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+    WOLFSSL_API int wc_Sha224SetFlags(wc_Sha224* sha224, word32 flags);
+    WOLFSSL_API int wc_Sha224GetFlags(wc_Sha224* sha224, word32* flags);
+#endif
+
+#endif /* WOLFSSL_SHA224 */
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* NO_SHA256 */
+#endif /* WOLF_CRYPT_SHA256_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/sha512.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/sha512.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/sha512.h	(revision 453)
@@ -0,0 +1,228 @@
+/* sha512.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/sha512.h
+*/
+
+
+#ifndef WOLF_CRYPT_SHA512_H
+#define WOLF_CRYPT_SHA512_H
+
+#include <wolfssl/wolfcrypt/types.h>
+
+#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
+
+#if defined(HAVE_FIPS) && \
+    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
+    #include <wolfssl/wolfcrypt/fips.h>
+#endif /* HAVE_FIPS_VERSION >= 2 */
+
+#if defined(HAVE_FIPS) && \
+	(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
+    #ifdef WOLFSSL_SHA512
+        #define wc_Sha512             Sha512
+        #define WC_SHA512             SHA512
+        #define WC_SHA512_BLOCK_SIZE  SHA512_BLOCK_SIZE
+        #define WC_SHA512_DIGEST_SIZE SHA512_DIGEST_SIZE
+        #define WC_SHA512_PAD_SIZE    SHA512_PAD_SIZE
+    #endif /* WOLFSSL_SHA512 */
+    #ifdef WOLFSSL_SHA384
+        #define wc_Sha384             Sha384
+        #define WC_SHA384             SHA384
+        #define WC_SHA384_BLOCK_SIZE  SHA384_BLOCK_SIZE
+        #define WC_SHA384_DIGEST_SIZE SHA384_DIGEST_SIZE
+        #define WC_SHA384_PAD_SIZE    SHA384_PAD_SIZE
+    #endif /* WOLFSSL_SHA384 */
+
+    #define CYASSL_SHA512
+    #if defined(WOLFSSL_SHA384)
+        #define CYASSL_SHA384
+    #endif
+	/* for fips @wc_fips */
+    #include <cyassl/ctaocrypt/sha512.h>
+#endif
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+/* avoid redefinition of structs */
+#if !defined(HAVE_FIPS) || \
+    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    #include <wolfssl/wolfcrypt/async.h>
+#endif
+#ifdef WOLFSSL_ESP32WROOM32_CRYPT
+    #include <wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h>
+#endif
+#if defined(_MSC_VER)
+    #define SHA512_NOINLINE __declspec(noinline)
+#elif defined(__IAR_SYSTEMS_ICC__) || defined(__GNUC__)
+    #define SHA512_NOINLINE __attribute__((noinline))
+#else
+    #define SHA512_NOINLINE
+#endif
+
+#ifdef WOLFSSL_SHA512
+
+#if !defined(NO_OLD_SHA_NAMES)
+    #define SHA512             WC_SHA512
+#endif
+
+#if !defined(NO_OLD_WC_NAMES)
+    #define Sha512             wc_Sha512
+    #define SHA512_BLOCK_SIZE  WC_SHA512_BLOCK_SIZE
+    #define SHA512_DIGEST_SIZE WC_SHA512_DIGEST_SIZE
+    #define SHA512_PAD_SIZE    WC_SHA512_PAD_SIZE
+#endif
+
+#endif /* WOLFSSL_SHA512 */
+
+/* in bytes */
+enum {
+#ifdef WOLFSSL_SHA512
+    WC_SHA512              =   WC_HASH_TYPE_SHA512,
+#endif
+    WC_SHA512_BLOCK_SIZE   = 128,
+    WC_SHA512_DIGEST_SIZE  =  64,
+    WC_SHA512_PAD_SIZE     = 112
+};
+
+
+#ifdef WOLFSSL_IMX6_CAAM
+    #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h"
+#else
+/* wc_Sha512 digest */
+struct wc_Sha512 {
+    word64  digest[WC_SHA512_DIGEST_SIZE / sizeof(word64)];
+    word64  buffer[WC_SHA512_BLOCK_SIZE  / sizeof(word64)];
+    word32  buffLen;   /* in bytes          */
+    word64  loLen;     /* length in bytes   */
+    word64  hiLen;     /* length in bytes   */
+    void*   heap;
+#ifdef USE_INTEL_SPEEDUP
+    const byte* data;
+#endif
+#ifdef WOLFSSL_ASYNC_CRYPT
+    WC_ASYNC_DEV asyncDev;
+#endif /* WOLFSSL_ASYNC_CRYPT */
+#ifdef WOLFSSL_SMALL_STACK_CACHE
+    word64* W;
+#endif
+#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+   !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+    WC_ESP32SHA ctx;
+#endif
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+    word32 flags; /* enum wc_HashFlags in hash.h */
+#endif
+};
+
+#ifndef WC_SHA512_TYPE_DEFINED
+    typedef struct wc_Sha512 wc_Sha512;
+    #define WC_SHA512_TYPE_DEFINED
+#endif
+#endif
+
+#endif /* HAVE_FIPS */
+
+#ifdef WOLFSSL_ARMASM
+WOLFSSL_LOCAL void Transform_Sha512_Len(wc_Sha512* sha512, const byte* data,
+                                        word32 len);
+#endif
+
+#ifdef WOLFSSL_SHA512
+
+WOLFSSL_API int wc_InitSha512(wc_Sha512*);
+WOLFSSL_API int wc_InitSha512_ex(wc_Sha512*, void*, int);
+WOLFSSL_API int wc_Sha512Update(wc_Sha512*, const byte*, word32);
+WOLFSSL_API int wc_Sha512FinalRaw(wc_Sha512*, byte*);
+WOLFSSL_API int wc_Sha512Final(wc_Sha512*, byte*);
+WOLFSSL_API void wc_Sha512Free(wc_Sha512*);
+
+WOLFSSL_API int wc_Sha512GetHash(wc_Sha512*, byte*);
+WOLFSSL_API int wc_Sha512Copy(wc_Sha512* src, wc_Sha512* dst);
+
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+    WOLFSSL_API int wc_Sha512SetFlags(wc_Sha512* sha512, word32 flags);
+    WOLFSSL_API int wc_Sha512GetFlags(wc_Sha512* sha512, word32* flags);
+#endif
+
+#endif /* WOLFSSL_SHA512 */
+
+#if defined(WOLFSSL_SHA384)
+
+/* avoid redefinition of structs */
+#if !defined(HAVE_FIPS) || \
+    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))
+
+#if !defined(NO_OLD_SHA_NAMES)
+    #define SHA384             WC_SHA384
+#endif
+
+#if !defined(NO_OLD_WC_NAMES)
+    #define Sha384             wc_Sha384
+    #define SHA384_BLOCK_SIZE  WC_SHA384_BLOCK_SIZE
+    #define SHA384_DIGEST_SIZE WC_SHA384_DIGEST_SIZE
+    #define SHA384_PAD_SIZE    WC_SHA384_PAD_SIZE
+#endif
+
+/* in bytes */
+enum {
+    WC_SHA384              =   WC_HASH_TYPE_SHA384,
+    WC_SHA384_BLOCK_SIZE   =   WC_SHA512_BLOCK_SIZE,
+    WC_SHA384_DIGEST_SIZE  =   48,
+    WC_SHA384_PAD_SIZE     =   WC_SHA512_PAD_SIZE
+};
+
+
+#ifndef WC_SHA384_TYPE_DEFINED
+    typedef struct wc_Sha512 wc_Sha384;
+    #define WC_SHA384_TYPE_DEFINED
+#endif
+#endif /* HAVE_FIPS */
+
+WOLFSSL_API int wc_InitSha384(wc_Sha384*);
+WOLFSSL_API int wc_InitSha384_ex(wc_Sha384*, void*, int);
+WOLFSSL_API int wc_Sha384Update(wc_Sha384*, const byte*, word32);
+WOLFSSL_API int wc_Sha384FinalRaw(wc_Sha384*, byte*);
+WOLFSSL_API int wc_Sha384Final(wc_Sha384*, byte*);
+WOLFSSL_API void wc_Sha384Free(wc_Sha384*);
+
+WOLFSSL_API int wc_Sha384GetHash(wc_Sha384*, byte*);
+WOLFSSL_API int wc_Sha384Copy(wc_Sha384* src, wc_Sha384* dst);
+
+#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
+    WOLFSSL_API int wc_Sha384SetFlags(wc_Sha384* sha384, word32 flags);
+    WOLFSSL_API int wc_Sha384GetFlags(wc_Sha384* sha384, word32* flags);
+#endif
+
+#endif /* WOLFSSL_SHA384 */
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* WOLFSSL_SHA512 || WOLFSSL_SHA384 */
+#endif /* WOLF_CRYPT_SHA512_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/types.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/types.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/types.h	(revision 453)
@@ -0,0 +1,950 @@
+/* types.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/types.h
+*/
+
+#ifndef WOLF_CRYPT_TYPES_H
+#define WOLF_CRYPT_TYPES_H
+
+    #include <wolfssl/wolfcrypt/settings.h>
+    #include <wolfssl/wolfcrypt/wc_port.h>
+
+    #ifdef __cplusplus
+        extern "C" {
+    #endif
+
+
+    #define WOLFSSL_ABI
+            /* Tag for all the APIs that are a part of the fixed ABI. */
+
+    /*
+     * This struct is used multiple time by other structs and
+     * needs to be defined somwhere that all structs can import
+     * (with minimal depencencies).
+     */
+    #if defined(HAVE_EX_DATA) || defined(FORTRESS)
+    typedef struct WOLFSSL_CRYPTO_EX_DATA {
+        void* ex_data[MAX_EX_DATA];
+    } WOLFSSL_CRYPTO_EX_DATA;
+    #endif
+
+    #if defined(WORDS_BIGENDIAN)
+        #define BIG_ENDIAN_ORDER
+    #endif
+
+    #ifndef BIG_ENDIAN_ORDER
+        #define LITTLE_ENDIAN_ORDER
+    #endif
+
+    #ifndef WOLFSSL_TYPES
+        #ifndef byte
+            typedef unsigned char  byte;
+        #endif
+        #ifdef WC_16BIT_CPU
+            typedef unsigned int   word16;
+            typedef unsigned long  word32;
+        #else
+            typedef unsigned short word16;
+            typedef unsigned int   word32;
+        #endif
+        typedef byte           word24[3];
+    #endif
+
+
+    /* constant pointer to a constant char */
+    #ifdef WOLFSSL_NO_CONSTCHARCONST
+        typedef const char*       wcchar;
+    #else
+        typedef const char* const wcchar;
+    #endif
+
+
+    /* try to set SIZEOF_LONG or SIZEOF_LONG_LONG if user didn't */
+    #if defined(_MSC_VER) || defined(HAVE_LIMITS_H)
+        #if !defined(SIZEOF_LONG_LONG) && !defined(SIZEOF_LONG)
+            #include <limits.h>
+            #if defined(ULONG_MAX) && (ULONG_MAX == 0xffffffffUL)
+                #define SIZEOF_LONG 4
+            #endif
+            #if defined(ULLONG_MAX) && (ULLONG_MAX == 0xffffffffffffffffULL)
+                #define SIZEOF_LONG_LONG 8
+            #endif
+        #endif
+    #elif !defined(__BCPLUSPLUS__) && !defined(__EMSCRIPTEN__)
+        #if !defined(SIZEOF_LONG_LONG) && !defined(SIZEOF_LONG)
+            #if (defined(__alpha__) || defined(__ia64__) || \
+                defined(_ARCH_PPC64) || defined(__mips64) || \
+                defined(__x86_64__)  || defined(__s390x__ ) || \
+                ((defined(sun) || defined(__sun)) && \
+                 (defined(LP64) || defined(_LP64))))
+                /* long should be 64bit */
+                #define SIZEOF_LONG 8
+            #elif defined(__i386__) || defined(__CORTEX_M3__)
+                /* long long should be 64bit */
+                #define SIZEOF_LONG_LONG 8
+            #endif
+         #endif
+    #endif
+
+    #if defined(_MSC_VER) || defined(__BCPLUSPLUS__)
+        #define WORD64_AVAILABLE
+        #define W64LIT(x) x##ui64
+        typedef unsigned __int64 word64;
+    #elif defined(__EMSCRIPTEN__)
+        #define WORD64_AVAILABLE
+        #define W64LIT(x) x##ull
+        typedef unsigned long long word64;
+    #elif defined(SIZEOF_LONG) && SIZEOF_LONG == 8
+        #define WORD64_AVAILABLE
+        #define W64LIT(x) x##LL
+        typedef unsigned long word64;
+    #elif defined(SIZEOF_LONG_LONG) && SIZEOF_LONG_LONG == 8
+        #define WORD64_AVAILABLE
+        #define W64LIT(x) x##LL
+        typedef unsigned long long word64;
+    #elif defined(__SIZEOF_LONG_LONG__) && __SIZEOF_LONG_LONG__ == 8
+        #define WORD64_AVAILABLE
+        #define W64LIT(x) x##LL
+        typedef unsigned long long word64;
+    #endif
+
+#if !defined(NO_64BIT) && defined(WORD64_AVAILABLE) && !defined(WC_16BIT_CPU)
+    /* These platforms have 64-bit CPU registers.  */
+    #if (defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) || \
+         defined(__mips64)  || defined(__x86_64__) || defined(_M_X64)) || \
+         defined(__aarch64__) || defined(__sparc64__) || defined(__s390x__ ) || \
+        (defined(__riscv_xlen) && (__riscv_xlen == 64))
+        typedef word64 wolfssl_word;
+        #define WC_64BIT_CPU
+    #elif (defined(sun) || defined(__sun)) && \
+          (defined(LP64) || defined(_LP64))
+        /* LP64 with GNU GCC compiler is reserved for when long int is 64 bits
+         * and int uses 32 bits. When using Solaris Studio sparc and __sparc are
+         * available for 32 bit detection but __sparc64__ could be missed. This
+         * uses LP64 for checking 64 bit CPU arch. */
+        typedef word64 wolfssl_word;
+        #define WC_64BIT_CPU
+    #else
+        typedef word32 wolfssl_word;
+        #ifdef WORD64_AVAILABLE
+            #define WOLFCRYPT_SLOW_WORD64
+        #endif
+    #endif
+
+#elif defined(WC_16BIT_CPU)
+        #undef WORD64_AVAILABLE
+        typedef word16 wolfssl_word;
+        #define MP_16BIT  /* for mp_int, mp_word needs to be twice as big as
+                             mp_digit, no 64 bit type so make mp_digit 16 bit */
+
+#else
+        #undef WORD64_AVAILABLE
+        typedef word32 wolfssl_word;
+        #define MP_16BIT  /* for mp_int, mp_word needs to be twice as big as
+                             mp_digit, no 64 bit type so make mp_digit 16 bit */
+#endif
+
+    enum {
+        WOLFSSL_WORD_SIZE  = sizeof(wolfssl_word),
+        WOLFSSL_BIT_SIZE   = 8,
+        WOLFSSL_WORD_BITS  = WOLFSSL_WORD_SIZE * WOLFSSL_BIT_SIZE
+    };
+
+    #define WOLFSSL_MAX_16BIT 0xffffU
+
+    /* use inlining if compiler allows */
+    #ifndef WC_INLINE
+    #ifndef NO_INLINE
+        #ifdef _MSC_VER
+            #define WC_INLINE __inline
+        #elif defined(__GNUC__)
+               #ifdef WOLFSSL_VXWORKS
+                   #define WC_INLINE __inline__
+               #else
+                   #define WC_INLINE inline
+               #endif
+        #elif defined(__IAR_SYSTEMS_ICC__)
+            #define WC_INLINE inline
+        #elif defined(THREADX)
+            #define WC_INLINE _Inline
+        #elif defined(__ghc__)
+            #ifndef __cplusplus
+                #define WC_INLINE __inline
+            #else
+                #define WC_INLINE inline
+            #endif
+        #else
+            #define WC_INLINE
+        #endif
+    #else
+        #define WC_INLINE
+    #endif
+    #endif
+
+    #if defined(HAVE_FIPS) || defined(HAVE_SELFTEST)
+        #define INLINE WC_INLINE
+    #endif
+
+
+    /* set up rotate style */
+    #if (defined(_MSC_VER) || defined(__BCPLUSPLUS__)) && \
+        !defined(WOLFSSL_SGX) && !defined(INTIME_RTOS)
+        #define INTEL_INTRINSICS
+        #define FAST_ROTATE
+    #elif defined(__MWERKS__) && TARGET_CPU_PPC
+        #define PPC_INTRINSICS
+        #define FAST_ROTATE
+    #elif defined(__GNUC__)  && (defined(__i386__) || defined(__x86_64__))
+        /* GCC does peephole optimizations which should result in using rotate
+           instructions  */
+        #define FAST_ROTATE
+    #endif
+
+
+    /* set up thread local storage if available */
+    #ifdef HAVE_THREAD_LS
+        #if defined(_MSC_VER)
+            #define THREAD_LS_T __declspec(thread)
+        /* Thread local storage only in FreeRTOS v8.2.1 and higher */
+        #elif defined(FREERTOS) || defined(FREERTOS_TCP) || \
+                                                         defined(WOLFSSL_ZEPHYR)
+            #define THREAD_LS_T
+        #else
+            #define THREAD_LS_T __thread
+        #endif
+    #else
+        #define THREAD_LS_T
+    #endif
+
+    /* GCC 7 has new switch() fall-through detection */
+    /* default to FALL_THROUGH stub */
+    #ifndef FALL_THROUGH
+    #define FALL_THROUGH
+
+    #if defined(__GNUC__)
+        #if ((__GNUC__ > 7) || ((__GNUC__ == 7) && (__GNUC_MINOR__ >= 1)))
+            #undef  FALL_THROUGH
+            #define FALL_THROUGH __attribute__ ((fallthrough));
+        #endif
+    #endif
+    #endif /* FALL_THROUGH */
+
+    /* Micrium will use Visual Studio for compilation but not the Win32 API */
+    #if defined(_WIN32) && !defined(MICRIUM) && !defined(FREERTOS) && \
+        !defined(FREERTOS_TCP) && !defined(EBSNET) && \
+        !defined(WOLFSSL_UTASKER) && !defined(INTIME_RTOS)
+        #define USE_WINDOWS_API
+    #endif
+
+    #define XSTR_SIZEOF(x) (sizeof(x) - 1) /* -1 to not count the null char */
+
+    /* idea to add global alloc override by Moises Guimaraes  */
+    /* default to libc stuff */
+    /* XREALLOC is used once in normal math lib, not in fast math lib */
+    /* XFREE on some embedded systems doesn't like free(0) so test  */
+    #if defined(HAVE_IO_POOL)
+        WOLFSSL_API void* XMALLOC(size_t n, void* heap, int type);
+        WOLFSSL_API void* XREALLOC(void *p, size_t n, void* heap, int type);
+        WOLFSSL_API void XFREE(void *p, void* heap, int type);
+    #elif (defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_INTEL_QA)) || \
+          defined(HAVE_INTEL_QA_SYNC)
+        #ifndef HAVE_INTEL_QA_SYNC
+            #include <wolfssl/wolfcrypt/port/intel/quickassist_mem.h>
+            #undef USE_WOLFSSL_MEMORY
+            #ifdef WOLFSSL_DEBUG_MEMORY
+                #define XMALLOC(s, h, t)     IntelQaMalloc((s), (h), (t), __func__, __LINE__)
+                #define XFREE(p, h, t)       IntelQaFree((p), (h), (t), __func__, __LINE__)
+                #define XREALLOC(p, n, h, t) IntelQaRealloc((p), (n), (h), (t), __func__, __LINE__)
+            #else
+                #define XMALLOC(s, h, t)     IntelQaMalloc((s), (h), (t))
+                #define XFREE(p, h, t)       IntelQaFree((p), (h), (t))
+                #define XREALLOC(p, n, h, t) IntelQaRealloc((p), (n), (h), (t))
+            #endif /* WOLFSSL_DEBUG_MEMORY */
+        #else
+            #include <wolfssl/wolfcrypt/port/intel/quickassist_sync.h>
+            #undef USE_WOLFSSL_MEMORY
+            #ifdef WOLFSSL_DEBUG_MEMORY
+                #define XMALLOC(s, h, t)     wc_CryptoCb_IntelQaMalloc((s), (h), (t), __func__, __LINE__)
+                #define XFREE(p, h, t)       wc_CryptoCb_IntelQaFree((p), (h), (t), __func__, __LINE__)
+                #define XREALLOC(p, n, h, t) wc_CryptoCb_IntelQaRealloc((p), (n), (h), (t), __func__, __LINE__)
+            #else
+                #define XMALLOC(s, h, t)     wc_CryptoCb_IntelQaMalloc((s), (h), (t))
+                #define XFREE(p, h, t)       wc_CryptoCb_IntelQaFree((p), (h), (t))
+                #define XREALLOC(p, n, h, t) wc_CryptoCb_IntelQaRealloc((p), (n), (h), (t))
+            #endif /* WOLFSSL_DEBUG_MEMORY */
+        #endif
+    #elif defined(XMALLOC_USER)
+        /* prototypes for user heap override functions */
+        #include <stddef.h>  /* for size_t */
+        extern void *XMALLOC(size_t n, void* heap, int type);
+        extern void *XREALLOC(void *p, size_t n, void* heap, int type);
+        extern void XFREE(void *p, void* heap, int type);
+    #elif defined(WOLFSSL_MEMORY_LOG)
+        #define XMALLOC(n, h, t)        xmalloc(n, h, t, __func__, __FILE__, __LINE__)
+        #define XREALLOC(p, n, h, t)    xrealloc(p, n, h, t, __func__,  __FILE__, __LINE__)
+        #define XFREE(p, h, t)          xfree(p, h, t, __func__, __FILE__, __LINE__)
+
+        /* prototypes for user heap override functions */
+        #include <stddef.h>  /* for size_t */
+        #include <stdlib.h>
+        WOLFSSL_API void *xmalloc(size_t n, void* heap, int type,
+                const char* func, const char* file, unsigned int line);
+        WOLFSSL_API void *xrealloc(void *p, size_t n, void* heap, int type,
+                const char* func, const char* file, unsigned int line);
+        WOLFSSL_API void xfree(void *p, void* heap, int type, const char* func,
+                const char* file, unsigned int line);
+    #elif defined(XMALLOC_OVERRIDE)
+        /* override the XMALLOC, XFREE and XREALLOC macros */
+    #elif defined(WOLFSSL_TELIT_M2MB)
+        /* Telit M2MB SDK requires use m2mb_os API's, not std malloc/free */
+        /* Use of malloc/free will cause CPU reboot */
+        #define XMALLOC(s, h, t)     ((void)h, (void)t, m2mb_os_malloc((s)))
+        #define XFREE(p, h, t)       {void* xp = (p); if((xp)) m2mb_os_free((xp));}
+        #define XREALLOC(p, n, h, t) m2mb_os_realloc((p), (n))
+
+    #elif defined(NO_WOLFSSL_MEMORY)
+        #ifdef WOLFSSL_NO_MALLOC
+            /* this platform does not support heap use */
+            #ifdef WOLFSSL_MALLOC_CHECK
+                #include <stdio.h>
+                static inline void* malloc_check(size_t sz) {
+                    printf("wolfSSL_malloc failed");
+                    return NULL;
+                };
+                #define XMALLOC(s, h, t)     malloc_check((s))
+                #define XFREE(p, h, t)
+                #define XREALLOC(p, n, h, t) (NULL)
+            #else
+                #define XMALLOC(s, h, t)     (NULL)
+                #define XFREE(p, h, t)
+                #define XREALLOC(p, n, h, t) (NULL)
+            #endif
+        #else
+        /* just use plain C stdlib stuff if desired */
+        #include <stdlib.h>
+        #define XMALLOC(s, h, t)     malloc((s))
+        #define XFREE(p, h, t)       {void* xp = (p); if((xp)) free((xp));}
+        #define XREALLOC(p, n, h, t) realloc((p), (n))
+        #endif
+    #elif !defined(MICRIUM_MALLOC) && !defined(EBSNET) \
+            && !defined(WOLFSSL_SAFERTOS) && !defined(FREESCALE_MQX) \
+            && !defined(FREESCALE_KSDK_MQX) && !defined(FREESCALE_FREE_RTOS) \
+            && !defined(WOLFSSL_LEANPSK) && !defined(WOLFSSL_uITRON4)
+        /* default C runtime, can install different routines at runtime via cbs */
+        #include <wolfssl/wolfcrypt/memory.h>
+        #ifdef WOLFSSL_STATIC_MEMORY
+            #ifdef WOLFSSL_DEBUG_MEMORY
+                #define XMALLOC(s, h, t)     wolfSSL_Malloc((s), (h), (t), __func__, __LINE__)
+                #define XFREE(p, h, t)       {void* xp = (p); if((xp)) wolfSSL_Free((xp), (h), (t), __func__, __LINE__);}
+                #define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n), (h), (t), __func__, __LINE__)
+            #else
+                #define XMALLOC(s, h, t)     wolfSSL_Malloc((s), (h), (t))
+                #define XFREE(p, h, t)       {void* xp = (p); if((xp)) wolfSSL_Free((xp), (h), (t));}
+                #define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n), (h), (t))
+            #endif /* WOLFSSL_DEBUG_MEMORY */
+        #elif !defined(FREERTOS) && !defined(FREERTOS_TCP)
+            #ifdef WOLFSSL_DEBUG_MEMORY
+                #define XMALLOC(s, h, t)     ((void)h, (void)t, wolfSSL_Malloc((s), __func__, __LINE__))
+                #define XFREE(p, h, t)       {void* xp = (p); if((xp)) wolfSSL_Free((xp), __func__, __LINE__);}
+                #define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n), __func__, __LINE__)
+            #else
+                #define XMALLOC(s, h, t)     ((void)h, (void)t, wolfSSL_Malloc((s)))
+                #define XFREE(p, h, t)       {void* xp = (p); if((xp)) wolfSSL_Free((xp));}
+                #define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n))
+            #endif /* WOLFSSL_DEBUG_MEMORY */
+        #endif /* WOLFSSL_STATIC_MEMORY */
+    #endif
+
+    /* declare/free variable handling for async */
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        #define DECLARE_VAR(VAR_NAME, VAR_TYPE, VAR_SIZE, HEAP) \
+            VAR_TYPE* VAR_NAME = (VAR_TYPE*)XMALLOC(sizeof(VAR_TYPE) * VAR_SIZE, (HEAP), DYNAMIC_TYPE_WOLF_BIGINT);
+        #define DECLARE_VAR_INIT(VAR_NAME, VAR_TYPE, VAR_SIZE, INIT_VALUE, HEAP) \
+            VAR_TYPE* VAR_NAME = ({ \
+                VAR_TYPE* ptr = (VAR_TYPE*)XMALLOC(sizeof(VAR_TYPE) * VAR_SIZE, (HEAP), DYNAMIC_TYPE_WOLF_BIGINT); \
+                if (ptr && INIT_VALUE) { \
+                    XMEMCPY(ptr, INIT_VALUE, sizeof(VAR_TYPE) * VAR_SIZE); \
+                } \
+                ptr; \
+            })
+        #define DECLARE_ARRAY(VAR_NAME, VAR_TYPE, VAR_ITEMS, VAR_SIZE, HEAP) \
+            VAR_TYPE* VAR_NAME[VAR_ITEMS]; \
+            int idx##VAR_NAME; \
+            for (idx##VAR_NAME=0; idx##VAR_NAME<VAR_ITEMS; idx##VAR_NAME++) { \
+                VAR_NAME[idx##VAR_NAME] = (VAR_TYPE*)XMALLOC(VAR_SIZE, (HEAP), DYNAMIC_TYPE_WOLF_BIGINT); \
+            }
+        #define FREE_VAR(VAR_NAME, HEAP) \
+            XFREE(VAR_NAME, (HEAP), DYNAMIC_TYPE_WOLF_BIGINT);
+        #define FREE_ARRAY(VAR_NAME, VAR_ITEMS, HEAP) \
+            for (idx##VAR_NAME=0; idx##VAR_NAME<VAR_ITEMS; idx##VAR_NAME++) { \
+                XFREE(VAR_NAME[idx##VAR_NAME], (HEAP), DYNAMIC_TYPE_WOLF_BIGINT); \
+            }
+
+        #define DECLARE_ARRAY_DYNAMIC_DEC(VAR_NAME, VAR_TYPE, VAR_ITEMS, VAR_SIZE, HEAP) \
+            DECLARE_ARRAY(VAR_NAME, VAR_TYPE, VAR_ITEMS, VAR_SIZE, HEAP)
+        #define DECLARE_ARRAY_DYNAMIC_EXE(VAR_NAME, VAR_TYPE, VAR_ITEMS, VAR_SIZE, HEAP)
+        #define FREE_ARRAY_DYNAMIC(VAR_NAME, VAR_ITEMS, HEAP) \
+            FREE_ARRAY(VAR_NAME, VAR_ITEMS, HEAP)
+    #else
+        #define DECLARE_VAR(VAR_NAME, VAR_TYPE, VAR_SIZE, HEAP) \
+            VAR_TYPE VAR_NAME[VAR_SIZE]
+        #define DECLARE_VAR_INIT(VAR_NAME, VAR_TYPE, VAR_SIZE, INIT_VALUE, HEAP) \
+            VAR_TYPE* VAR_NAME = (VAR_TYPE*)INIT_VALUE
+        #define DECLARE_ARRAY(VAR_NAME, VAR_TYPE, VAR_ITEMS, VAR_SIZE, HEAP) \
+            VAR_TYPE VAR_NAME[VAR_ITEMS][VAR_SIZE]
+        #define FREE_VAR(VAR_NAME, HEAP) /* nothing to free, its stack */
+        #define FREE_ARRAY(VAR_NAME, VAR_ITEMS, HEAP)  /* nothing to free, its stack */
+
+        #define DECLARE_ARRAY_DYNAMIC_DEC(VAR_NAME, VAR_TYPE, VAR_ITEMS, VAR_SIZE, HEAP) \
+            VAR_TYPE* VAR_NAME[VAR_ITEMS]; \
+            int idx##VAR_NAME;
+        #define DECLARE_ARRAY_DYNAMIC_EXE(VAR_NAME, VAR_TYPE, VAR_ITEMS, VAR_SIZE, HEAP) \
+            for (idx##VAR_NAME=0; idx##VAR_NAME<VAR_ITEMS; idx##VAR_NAME++) { \
+                VAR_NAME[idx##VAR_NAME] = (VAR_TYPE*)XMALLOC(VAR_SIZE, (HEAP), DYNAMIC_TYPE_TMP_BUFFER); \
+            }
+        #define FREE_ARRAY_DYNAMIC(VAR_NAME, VAR_ITEMS, HEAP) \
+            for (idx##VAR_NAME=0; idx##VAR_NAME<VAR_ITEMS; idx##VAR_NAME++) { \
+                XFREE(VAR_NAME[idx##VAR_NAME], (HEAP), DYNAMIC_TYPE_TMP_BUFFER); \
+            }
+    #endif
+
+    #if !defined(USE_WOLF_STRTOK) && \
+            ((defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)) || \
+             defined(WOLFSSL_TIRTOS) || defined(WOLF_C99))
+        #define USE_WOLF_STRTOK
+    #endif
+    #if !defined(USE_WOLF_STRSEP) && (defined(WOLF_C99))
+        #define USE_WOLF_STRSEP
+    #endif
+
+    #ifndef STRING_USER
+        #include <string.h>
+        #define XMEMCPY(d,s,l)    memcpy((d),(s),(l))
+        #define XMEMSET(b,c,l)    memset((b),(c),(l))
+        #define XMEMCMP(s1,s2,n)  memcmp((s1),(s2),(n))
+        #define XMEMMOVE(d,s,l)   memmove((d),(s),(l))
+
+        #define XSTRLEN(s1)       strlen((s1))
+        #define XSTRNCPY(s1,s2,n) strncpy((s1),(s2),(n))
+        /* strstr, strncmp, and strncat only used by wolfSSL proper,
+         * not required for wolfCrypt only */
+        #define XSTRSTR(s1,s2)    strstr((s1),(s2))
+        #define XSTRNSTR(s1,s2,n) mystrnstr((s1),(s2),(n))
+        #define XSTRNCMP(s1,s2,n) strncmp((s1),(s2),(n))
+        #define XSTRNCAT(s1,s2,n) strncat((s1),(s2),(n))
+
+        #ifdef USE_WOLF_STRSEP
+            #define XSTRSEP(s1,d) wc_strsep((s1),(d))
+        #else
+            #define XSTRSEP(s1,d) strsep((s1),(d))
+        #endif
+
+        #ifndef XSTRNCASECMP
+        #if defined(MICROCHIP_PIC32) || defined(WOLFSSL_TIRTOS) || \
+                defined(WOLFSSL_ZEPHYR)
+            /* XC32 does not support strncasecmp, so use case sensitive one */
+            #define XSTRNCASECMP(s1,s2,n) strncmp((s1),(s2),(n))
+        #elif defined(USE_WINDOWS_API) || defined(FREERTOS_TCP_WINSIM)
+            #define XSTRNCASECMP(s1,s2,n) _strnicmp((s1),(s2),(n))
+        #else
+            #if defined(HAVE_STRINGS_H) && defined(WOLF_C99) && \
+                !defined(WOLFSSL_SGX)
+                #include <strings.h>
+            #endif
+            #if defined(WOLFSSL_DEOS)
+                #define XSTRNCASECMP(s1,s2,n) strnicmp((s1),(s2),(n))
+            #else
+                #define XSTRNCASECMP(s1,s2,n) strncasecmp((s1),(s2),(n))
+            #endif
+        #endif
+        #endif /* !XSTRNCASECMP */
+
+        /* snprintf is used in asn.c for GetTimeString, PKCS7 test, and when
+           debugging is turned on */
+        #ifndef USE_WINDOWS_API
+            #ifndef XSNPRINTF
+            #if defined(NO_FILESYSTEM) && (defined(OPENSSL_EXTRA) || \
+                   defined(HAVE_PKCS7)) && !defined(NO_STDIO_FILESYSTEM)
+                /* case where stdio is not included else where but is needed
+                   for snprintf */
+                #include <stdio.h>
+            #endif
+            #define XSNPRINTF snprintf
+            #endif
+        #else
+            #if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__)
+                #if defined(_MSC_VER) && (_MSC_VER >= 1900)
+                    /* Beginning with the UCRT in Visual Studio 2015 and
+                       Windows 10, snprintf is no longer identical to
+                       _snprintf. The snprintf function behavior is now
+                       C99 standard compliant. */
+                    #include <stdio.h>
+                    #define XSNPRINTF snprintf
+                #else
+                    /* 4996 warning to use MS extensions e.g., _sprintf_s
+                       instead of _snprintf */
+                    #if !defined(__MINGW32__)
+                    #pragma warning(disable: 4996)
+                    #endif
+                    static WC_INLINE
+                    int xsnprintf(char *buffer, size_t bufsize,
+                            const char *format, ...) {
+                        va_list ap;
+                        int ret;
+
+                        if ((int)bufsize <= 0) return -1;
+                        va_start(ap, format);
+                        ret = vsnprintf(buffer, bufsize, format, ap);
+                        if (ret >= (int)bufsize)
+                            ret = -1;
+                        va_end(ap);
+                        return ret;
+                    }
+                    #define XSNPRINTF xsnprintf
+                #endif /* (_MSC_VER >= 1900) */
+            #else
+                #define XSNPRINTF snprintf
+            #endif /* _MSC_VER */
+        #endif /* USE_WINDOWS_API */
+
+        #if defined(WOLFSSL_CERT_EXT) || defined(OPENSSL_EXTRA) \
+                    || defined(HAVE_ALPN)
+            /* use only Thread Safe version of strtok */
+            #if defined(USE_WOLF_STRTOK)
+                #define XSTRTOK(s1,d,ptr) wc_strtok((s1),(d),(ptr))
+            #elif defined(USE_WINDOWS_API) || defined(INTIME_RTOS)
+                #define XSTRTOK(s1,d,ptr) strtok_s((s1),(d),(ptr))
+            #else
+                #define XSTRTOK(s1,d,ptr) strtok_r((s1),(d),(ptr))
+            #endif
+        #endif
+
+        #if defined(WOLFSSL_CERT_EXT) || defined(HAVE_OCSP) || \
+            defined(HAVE_CRL_IO) || defined(HAVE_HTTP_CLIENT) || \
+            !defined(NO_CRYPT_BENCHMARK)
+
+            #ifndef XATOI /* if custom XATOI is not already defined */
+                #include <stdlib.h>
+                #define XATOI(s)          atoi((s))
+            #endif
+        #endif
+    #endif
+
+    #ifdef USE_WOLF_STRTOK
+        WOLFSSL_API char* wc_strtok(char *str, const char *delim, char **nextp);
+    #endif
+    #ifdef USE_WOLF_STRSEP
+        WOLFSSL_API char* wc_strsep(char **stringp, const char *delim);
+    #endif
+
+    #if !defined(NO_FILESYSTEM) && defined(OPENSSL_EXTRA) && \
+        !defined(NO_STDIO_FILESYSTEM)
+        #ifndef XGETENV
+            #include <stdlib.h>
+            #define XGETENV getenv
+        #endif
+    #endif /* OPENSSL_EXTRA */
+
+    #ifndef CTYPE_USER
+        #include <ctype.h>
+        #if defined(HAVE_ECC) || defined(HAVE_OCSP) || \
+            defined(WOLFSSL_KEY_GEN) || !defined(NO_DSA)
+            #define XTOUPPER(c)     toupper((c))
+            #define XISALPHA(c)     isalpha((c))
+        #endif
+        /* needed by wolfSSL_check_domain_name() */
+        #define XTOLOWER(c)      tolower((c))
+    #endif
+
+
+    /* memory allocation types for user hints */
+    enum {
+        DYNAMIC_TYPE_CA           = 1,
+        DYNAMIC_TYPE_CERT         = 2,
+        DYNAMIC_TYPE_KEY          = 3,
+        DYNAMIC_TYPE_FILE         = 4,
+        DYNAMIC_TYPE_SUBJECT_CN   = 5,
+        DYNAMIC_TYPE_PUBLIC_KEY   = 6,
+        DYNAMIC_TYPE_SIGNER       = 7,
+        DYNAMIC_TYPE_NONE         = 8,
+        DYNAMIC_TYPE_BIGINT       = 9,
+        DYNAMIC_TYPE_RSA          = 10,
+        DYNAMIC_TYPE_METHOD       = 11,
+        DYNAMIC_TYPE_OUT_BUFFER   = 12,
+        DYNAMIC_TYPE_IN_BUFFER    = 13,
+        DYNAMIC_TYPE_INFO         = 14,
+        DYNAMIC_TYPE_DH           = 15,
+        DYNAMIC_TYPE_DOMAIN       = 16,
+        DYNAMIC_TYPE_SSL          = 17,
+        DYNAMIC_TYPE_CTX          = 18,
+        DYNAMIC_TYPE_WRITEV       = 19,
+        DYNAMIC_TYPE_OPENSSL      = 20,
+        DYNAMIC_TYPE_DSA          = 21,
+        DYNAMIC_TYPE_CRL          = 22,
+        DYNAMIC_TYPE_REVOKED      = 23,
+        DYNAMIC_TYPE_CRL_ENTRY    = 24,
+        DYNAMIC_TYPE_CERT_MANAGER = 25,
+        DYNAMIC_TYPE_CRL_MONITOR  = 26,
+        DYNAMIC_TYPE_OCSP_STATUS  = 27,
+        DYNAMIC_TYPE_OCSP_ENTRY   = 28,
+        DYNAMIC_TYPE_ALTNAME      = 29,
+        DYNAMIC_TYPE_SUITES       = 30,
+        DYNAMIC_TYPE_CIPHER       = 31,
+        DYNAMIC_TYPE_RNG          = 32,
+        DYNAMIC_TYPE_ARRAYS       = 33,
+        DYNAMIC_TYPE_DTLS_POOL    = 34,
+        DYNAMIC_TYPE_SOCKADDR     = 35,
+        DYNAMIC_TYPE_LIBZ         = 36,
+        DYNAMIC_TYPE_ECC          = 37,
+        DYNAMIC_TYPE_TMP_BUFFER   = 38,
+        DYNAMIC_TYPE_DTLS_MSG     = 39,
+        DYNAMIC_TYPE_X509         = 40,
+        DYNAMIC_TYPE_TLSX         = 41,
+        DYNAMIC_TYPE_OCSP         = 42,
+        DYNAMIC_TYPE_SIGNATURE    = 43,
+        DYNAMIC_TYPE_HASHES       = 44,
+        DYNAMIC_TYPE_SRP          = 45,
+        DYNAMIC_TYPE_COOKIE_PWD   = 46,
+        DYNAMIC_TYPE_USER_CRYPTO  = 47,
+        DYNAMIC_TYPE_OCSP_REQUEST = 48,
+        DYNAMIC_TYPE_X509_EXT     = 49,
+        DYNAMIC_TYPE_X509_STORE   = 50,
+        DYNAMIC_TYPE_X509_CTX     = 51,
+        DYNAMIC_TYPE_URL          = 52,
+        DYNAMIC_TYPE_DTLS_FRAG    = 53,
+        DYNAMIC_TYPE_DTLS_BUFFER  = 54,
+        DYNAMIC_TYPE_SESSION_TICK = 55,
+        DYNAMIC_TYPE_PKCS         = 56,
+        DYNAMIC_TYPE_MUTEX        = 57,
+        DYNAMIC_TYPE_PKCS7        = 58,
+        DYNAMIC_TYPE_AES_BUFFER   = 59,
+        DYNAMIC_TYPE_WOLF_BIGINT  = 60,
+        DYNAMIC_TYPE_ASN1         = 61,
+        DYNAMIC_TYPE_LOG          = 62,
+        DYNAMIC_TYPE_WRITEDUP     = 63,
+        DYNAMIC_TYPE_PRIVATE_KEY  = 64,
+        DYNAMIC_TYPE_HMAC         = 65,
+        DYNAMIC_TYPE_ASYNC        = 66,
+        DYNAMIC_TYPE_ASYNC_NUMA   = 67,
+        DYNAMIC_TYPE_ASYNC_NUMA64 = 68,
+        DYNAMIC_TYPE_CURVE25519   = 69,
+        DYNAMIC_TYPE_ED25519      = 70,
+        DYNAMIC_TYPE_SECRET       = 71,
+        DYNAMIC_TYPE_DIGEST       = 72,
+        DYNAMIC_TYPE_RSA_BUFFER   = 73,
+        DYNAMIC_TYPE_DCERT        = 74,
+        DYNAMIC_TYPE_STRING       = 75,
+        DYNAMIC_TYPE_PEM          = 76,
+        DYNAMIC_TYPE_DER          = 77,
+        DYNAMIC_TYPE_CERT_EXT     = 78,
+        DYNAMIC_TYPE_ALPN         = 79,
+        DYNAMIC_TYPE_ENCRYPTEDINFO= 80,
+        DYNAMIC_TYPE_DIRCTX       = 81,
+        DYNAMIC_TYPE_HASHCTX      = 82,
+        DYNAMIC_TYPE_SEED         = 83,
+        DYNAMIC_TYPE_SYMMETRIC_KEY= 84,
+        DYNAMIC_TYPE_ECC_BUFFER   = 85,
+        DYNAMIC_TYPE_QSH          = 86,
+        DYNAMIC_TYPE_SALT         = 87,
+        DYNAMIC_TYPE_HASH_TMP     = 88,
+        DYNAMIC_TYPE_BLOB         = 89,
+        DYNAMIC_TYPE_NAME_ENTRY   = 90,
+        DYNAMIC_TYPE_CURVE448     = 91,
+        DYNAMIC_TYPE_ED448        = 92,
+        DYNAMIC_TYPE_SNIFFER_SERVER     = 1000,
+        DYNAMIC_TYPE_SNIFFER_SESSION    = 1001,
+        DYNAMIC_TYPE_SNIFFER_PB         = 1002,
+        DYNAMIC_TYPE_SNIFFER_PB_BUFFER  = 1003,
+        DYNAMIC_TYPE_SNIFFER_TICKET_ID  = 1004,
+        DYNAMIC_TYPE_SNIFFER_NAMED_KEY  = 1005,
+    };
+
+    /* max error buffer string size */
+    #ifndef WOLFSSL_MAX_ERROR_SZ
+        #define WOLFSSL_MAX_ERROR_SZ 80
+    #endif
+
+    /* stack protection */
+    enum {
+        MIN_STACK_BUFFER = 8
+    };
+
+
+    /* Algorithm Types */
+    enum wc_AlgoType {
+        WC_ALGO_TYPE_NONE = 0,
+        WC_ALGO_TYPE_HASH = 1,
+        WC_ALGO_TYPE_CIPHER = 2,
+        WC_ALGO_TYPE_PK = 3,
+        WC_ALGO_TYPE_RNG = 4,
+        WC_ALGO_TYPE_SEED = 5,
+        WC_ALGO_TYPE_HMAC = 6,
+
+        WC_ALGO_TYPE_MAX = WC_ALGO_TYPE_HMAC
+    };
+
+    /* hash types */
+    enum wc_HashType {
+    #if defined(HAVE_SELFTEST) || defined(HAVE_FIPS)
+        /* In selftest build, WC_* types are not mapped to WC_HASH_TYPE types.
+         * Values here are based on old selftest hmac.h enum, with additions.
+         * These values are fixed for backwards FIPS compatibility */
+        WC_HASH_TYPE_NONE = 15,
+        WC_HASH_TYPE_MD2 = 16,
+        WC_HASH_TYPE_MD4 = 17,
+        WC_HASH_TYPE_MD5 = 0,
+        WC_HASH_TYPE_SHA = 1, /* SHA-1 (not old SHA-0) */
+        WC_HASH_TYPE_SHA224 = 8,
+        WC_HASH_TYPE_SHA256 = 2,
+        WC_HASH_TYPE_SHA384 = 5,
+        WC_HASH_TYPE_SHA512 = 4,
+        WC_HASH_TYPE_MD5_SHA = 18,
+        WC_HASH_TYPE_SHA3_224 = 10,
+        WC_HASH_TYPE_SHA3_256 = 11,
+        WC_HASH_TYPE_SHA3_384 = 12,
+        WC_HASH_TYPE_SHA3_512 = 13,
+        WC_HASH_TYPE_BLAKE2B = 14,
+        WC_HASH_TYPE_BLAKE2S = 19,
+
+        WC_HASH_TYPE_MAX = WC_HASH_TYPE_BLAKE2S
+    #else
+        WC_HASH_TYPE_NONE = 0,
+        WC_HASH_TYPE_MD2 = 1,
+        WC_HASH_TYPE_MD4 = 2,
+        WC_HASH_TYPE_MD5 = 3,
+        WC_HASH_TYPE_SHA = 4, /* SHA-1 (not old SHA-0) */
+        WC_HASH_TYPE_SHA224 = 5,
+        WC_HASH_TYPE_SHA256 = 6,
+        WC_HASH_TYPE_SHA384 = 7,
+        WC_HASH_TYPE_SHA512 = 8,
+        WC_HASH_TYPE_MD5_SHA = 9,
+        WC_HASH_TYPE_SHA3_224 = 10,
+        WC_HASH_TYPE_SHA3_256 = 11,
+        WC_HASH_TYPE_SHA3_384 = 12,
+        WC_HASH_TYPE_SHA3_512 = 13,
+        WC_HASH_TYPE_BLAKE2B = 14,
+        WC_HASH_TYPE_BLAKE2S = 15,
+
+        WC_HASH_TYPE_MAX = WC_HASH_TYPE_BLAKE2S
+    #endif /* HAVE_SELFTEST */
+    };
+
+    /* cipher types */
+    enum wc_CipherType {
+        WC_CIPHER_NONE = 0,
+        WC_CIPHER_AES = 1,
+        WC_CIPHER_AES_CBC = 2,
+        WC_CIPHER_AES_GCM = 3,
+        WC_CIPHER_AES_CTR = 4,
+        WC_CIPHER_AES_XTS = 5,
+        WC_CIPHER_AES_CFB = 6,
+        WC_CIPHER_DES3 = 7,
+        WC_CIPHER_DES = 8,
+        WC_CIPHER_CHACHA = 9,
+        WC_CIPHER_HC128 = 10,
+        WC_CIPHER_IDEA = 11,
+
+        WC_CIPHER_MAX = WC_CIPHER_HC128
+    };
+
+    /* PK=public key (asymmetric) based algorithms */
+    enum wc_PkType {
+        WC_PK_TYPE_NONE = 0,
+        WC_PK_TYPE_RSA = 1,
+        WC_PK_TYPE_DH = 2,
+        WC_PK_TYPE_ECDH = 3,
+        WC_PK_TYPE_ECDSA_SIGN = 4,
+        WC_PK_TYPE_ECDSA_VERIFY = 5,
+        WC_PK_TYPE_ED25519 = 6,
+        WC_PK_TYPE_CURVE25519 = 7,
+        WC_PK_TYPE_RSA_KEYGEN = 8,
+        WC_PK_TYPE_EC_KEYGEN = 9,
+
+        WC_PK_TYPE_MAX = WC_PK_TYPE_EC_KEYGEN
+    };
+
+
+    /* settings detection for compile vs runtime math incompatibilities */
+    enum {
+    #if !defined(USE_FAST_MATH) && !defined(SIZEOF_LONG) && !defined(SIZEOF_LONG_LONG)
+        CTC_SETTINGS = 0x0
+    #elif !defined(USE_FAST_MATH) && defined(SIZEOF_LONG) && (SIZEOF_LONG == 8)
+        CTC_SETTINGS = 0x1
+    #elif !defined(USE_FAST_MATH) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 8)
+        CTC_SETTINGS = 0x2
+    #elif !defined(USE_FAST_MATH) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 4)
+        CTC_SETTINGS = 0x4
+    #elif defined(USE_FAST_MATH) && !defined(SIZEOF_LONG) && !defined(SIZEOF_LONG_LONG)
+        CTC_SETTINGS = 0x8
+    #elif defined(USE_FAST_MATH) && defined(SIZEOF_LONG) && (SIZEOF_LONG == 8)
+        CTC_SETTINGS = 0x10
+    #elif defined(USE_FAST_MATH) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 8)
+        CTC_SETTINGS = 0x20
+    #elif defined(USE_FAST_MATH) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 4)
+        CTC_SETTINGS = 0x40
+    #else
+        #error "bad math long / long long settings"
+    #endif
+    };
+
+
+    WOLFSSL_API word32 CheckRunTimeSettings(void);
+
+    /* If user uses RSA, DH, DSA, or ECC math lib directly then fast math and long
+       types need to match at compile time and run time, CheckCtcSettings will
+       return 1 if a match otherwise 0 */
+    #define CheckCtcSettings() (CTC_SETTINGS == CheckRunTimeSettings())
+
+    /* invalid device id */
+    #define INVALID_DEVID    -2
+
+
+    /* AESNI requires alignment and ARMASM gains some performance from it
+     * Xilinx RSA operations require alignment */
+    #if defined(WOLFSSL_AESNI) || defined(WOLFSSL_ARMASM) || \
+        defined(USE_INTEL_SPEEDUP) || defined(WOLFSSL_AFALG_XILINX)
+        #if !defined(ALIGN16)
+            #if defined(__IAR_SYSTEMS_ICC__) || defined(__GNUC__)
+                #define ALIGN16 __attribute__ ( (aligned (16)))
+            #elif defined(_MSC_VER)
+                /* disable align warning, we want alignment ! */
+                #pragma warning(disable: 4324)
+                #define ALIGN16 __declspec (align (16))
+            #else
+                #define ALIGN16
+            #endif
+        #endif /* !ALIGN16 */
+
+        #if !defined (ALIGN32)
+            #if defined(__IAR_SYSTEMS_ICC__) || defined(__GNUC__)
+                #define ALIGN32 __attribute__ ( (aligned (32)))
+            #elif defined(_MSC_VER)
+                /* disable align warning, we want alignment ! */
+                #pragma warning(disable: 4324)
+                #define ALIGN32 __declspec (align (32))
+            #else
+                #define ALIGN32
+            #endif
+        #endif /* !ALIGN32 */
+
+        #if !defined(ALIGN64)
+            #if defined(__IAR_SYSTEMS_ICC__) || defined(__GNUC__)
+                #define ALIGN64 __attribute__ ( (aligned (64)))
+            #elif defined(_MSC_VER)
+                /* disable align warning, we want alignment ! */
+                #pragma warning(disable: 4324)
+                #define ALIGN64 __declspec (align (64))
+            #else
+                #define ALIGN64
+            #endif
+        #endif /* !ALIGN64 */
+
+        #if defined(__IAR_SYSTEMS_ICC__) || defined(__GNUC__)
+            #define ALIGN128 __attribute__ ( (aligned (128)))
+        #elif defined(_MSC_VER)
+            /* disable align warning, we want alignment ! */
+            #pragma warning(disable: 4324)
+            #define ALIGN128 __declspec (align (128))
+        #else
+            #define ALIGN128
+        #endif
+
+        #if defined(__IAR_SYSTEMS_ICC__) || defined(__GNUC__)
+            #define ALIGN256 __attribute__ ( (aligned (256)))
+        #elif defined(_MSC_VER)
+            /* disable align warning, we want alignment ! */
+            #pragma warning(disable: 4324)
+            #define ALIGN256 __declspec (align (256))
+        #else
+            #define ALIGN256
+        #endif
+
+    #else
+        #ifndef ALIGN16
+            #define ALIGN16
+        #endif
+        #ifndef ALIGN32
+            #define ALIGN32
+        #endif
+        #ifndef ALIGN64
+            #define ALIGN64
+        #endif
+        #ifndef ALIGN128
+            #define ALIGN128
+        #endif
+        #ifndef ALIGN256
+            #define ALIGN256
+        #endif
+    #endif /* WOLFSSL_AESNI || WOLFSSL_ARMASM */
+
+
+    #ifndef TRUE
+        #define TRUE  1
+    #endif
+    #ifndef FALSE
+        #define FALSE 0
+    #endif
+
+
+    #if defined(HAVE_STACK_SIZE)
+        #define EXIT_TEST(ret) return (void*)((size_t)(ret))
+    #else
+        #define EXIT_TEST(ret) return ret
+    #endif
+
+
+    #if (defined(__IAR_SYSTEMS_ICC__) && (__IAR_SYSTEMS_ICC__ > 8)) || \
+         defined(__GNUC__)
+        #define WOLFSSL_PACK __attribute__ ((packed))
+    #else
+        #define WOLFSSL_PACK
+    #endif
+
+    #ifndef __GNUC_PREREQ
+        #if defined(__GNUC__) && defined(__GNUC_MINOR__)
+            #define __GNUC_PREREQ(maj, min) \
+                ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+        #else
+            #define __GNUC_PREREQ(maj, min) (0) /* not GNUC */
+        #endif
+    #endif
+
+    #if defined(__IAR_SYSTEMS_ICC__) || defined(__GNUC__)
+        #define WC_NORETURN __attribute__((noreturn))
+    #else
+        #define WC_NORETURN
+    #endif
+
+    #if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \
+        defined(WOLFSSL_DEBUG_MATH) || defined(DEBUG_WOLFSSL) || \
+        defined(WOLFSSL_PUBLIC_MP) || defined(OPENSSL_EXTRA) || \
+            (defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT))
+        #undef  WC_MP_TO_RADIX
+        #define WC_MP_TO_RADIX
+    #endif
+
+    #ifdef __cplusplus
+        }   /* extern "C" */
+    #endif
+
+#endif /* WOLF_CRYPT_TYPES_H */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/visibility.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/visibility.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/visibility.h	(revision 453)
@@ -0,0 +1,79 @@
+/* visibility.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+/* Visibility control macros */
+
+#ifndef WOLF_CRYPT_VISIBILITY_H
+#define WOLF_CRYPT_VISIBILITY_H
+
+
+/* for compatibility and so that fips is using same name of macro @wc_fips */
+/* The following visibility wrappers are for old FIPS. New FIPS should use
+ * the same as a non-FIPS build. */
+#if defined(HAVE_FIPS) && \
+    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
+    #include <cyassl/ctaocrypt/visibility.h>
+    #define WOLFSSL_API   CYASSL_API
+	#define WOLFSSL_LOCAL CYASSL_LOCAL
+#else
+
+/* WOLFSSL_API is used for the public API symbols.
+        It either imports or exports (or does nothing for static builds)
+
+   WOLFSSL_LOCAL is used for non-API symbols (private).
+*/
+
+#if defined(BUILDING_WOLFSSL)
+    #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__)
+        #if defined(WOLFSSL_DLL)
+            #define WOLFSSL_API __declspec(dllexport)
+        #else
+            #define WOLFSSL_API
+        #endif
+        #define WOLFSSL_LOCAL
+    #elif defined(HAVE_VISIBILITY) && HAVE_VISIBILITY
+        #define WOLFSSL_API   __attribute__ ((visibility("default")))
+        #define WOLFSSL_LOCAL __attribute__ ((visibility("hidden")))
+    #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
+        #define WOLFSSL_API   __global
+        #define WOLFSSL_LOCAL __hidden
+    #else
+        #define WOLFSSL_API
+        #define WOLFSSL_LOCAL
+    #endif /* HAVE_VISIBILITY */
+#else /* BUILDING_WOLFSSL */
+    #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__)
+        #if defined(WOLFSSL_DLL)
+            #define WOLFSSL_API __declspec(dllimport)
+        #else
+            #define WOLFSSL_API
+        #endif
+        #define WOLFSSL_LOCAL
+    #else
+        #define WOLFSSL_API
+        #define WOLFSSL_LOCAL
+    #endif
+#endif /* BUILDING_WOLFSSL */
+
+#endif /* HAVE_FIPS */
+#endif /* WOLF_CRYPT_VISIBILITY_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/wc_encrypt.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/wc_encrypt.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/wc_encrypt.h	(revision 453)
@@ -0,0 +1,101 @@
+/* wc_encrypt.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/wc_encrypt.h
+*/
+
+
+#ifndef WOLF_CRYPT_ENCRYPT_H
+#define WOLF_CRYPT_ENCRYPT_H
+
+#include <wolfssl/wolfcrypt/types.h>
+#include <wolfssl/wolfcrypt/aes.h>
+#include <wolfssl/wolfcrypt/chacha.h>
+#include <wolfssl/wolfcrypt/des3.h>
+#include <wolfssl/wolfcrypt/arc4.h>
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+/* determine max cipher key size */
+#ifndef NO_AES
+    #define WC_MAX_SYM_KEY_SIZE     (AES_MAX_KEY_SIZE/8)
+#elif defined(HAVE_CHACHA)
+    #define WC_MAX_SYM_KEY_SIZE     CHACHA_MAX_KEY_SZ
+#elif !defined(NO_DES3)
+    #define WC_MAX_SYM_KEY_SIZE     DES3_KEY_SIZE
+#elif !defined(NO_RC4)
+    #define WC_MAX_SYM_KEY_SIZE     RC4_KEY_SIZE
+#else
+    #define WC_MAX_SYM_KEY_SIZE     32
+#endif
+
+
+#if !defined(NO_AES) && defined(HAVE_AES_CBC)
+WOLFSSL_API int wc_AesCbcEncryptWithKey(byte* out, const byte* in, word32 inSz,
+                                        const byte* key, word32 keySz,
+                                        const byte* iv);
+WOLFSSL_API int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz,
+                                        const byte* key, word32 keySz,
+                                        const byte* iv);
+#endif /* !NO_AES */
+
+
+#ifndef NO_DES3
+WOLFSSL_API int wc_Des_CbcDecryptWithKey(byte* out,
+                                         const byte* in, word32 sz,
+                                         const byte* key, const byte* iv);
+WOLFSSL_API int wc_Des_CbcEncryptWithKey(byte* out,
+                                         const byte* in, word32 sz,
+                                         const byte* key, const byte* iv);
+WOLFSSL_API int wc_Des3_CbcEncryptWithKey(byte* out,
+                                          const byte* in, word32 sz,
+                                          const byte* key, const byte* iv);
+WOLFSSL_API int wc_Des3_CbcDecryptWithKey(byte* out,
+                                          const byte* in, word32 sz,
+                                          const byte* key, const byte* iv);
+#endif /* !NO_DES3 */
+
+
+
+
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+    struct EncryptedInfo;
+    WOLFSSL_API int wc_BufferKeyDecrypt(struct EncryptedInfo* info, byte* der, word32 derSz,
+        const byte* password, int passwordSz, int hashType);
+    WOLFSSL_API int wc_BufferKeyEncrypt(struct EncryptedInfo* info, byte* der, word32 derSz,
+        const byte* password, int passwordSz, int hashType);
+#endif /* WOLFSSL_ENCRYPTED_KEYS */
+
+#ifndef NO_PWDBASED
+    WOLFSSL_LOCAL int wc_CryptKey(const char* password, int passwordSz, 
+        byte* salt, int saltSz, int iterations, int id, byte* input, int length,
+        int version, byte* cbcIv, int enc, int shaOid);
+#endif
+
+#ifdef __cplusplus
+    }  /* extern "C" */
+#endif
+
+#endif /* WOLF_CRYPT_ENCRYPT_H */
+
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/wc_port.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/wc_port.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/wc_port.h	(revision 453)
@@ -0,0 +1,780 @@
+/* wc_port.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfcrypt/wc_port.h
+*/
+
+#ifndef WOLF_CRYPT_PORT_H
+#define WOLF_CRYPT_PORT_H
+
+#include <wolfssl/wolfcrypt/settings.h>
+#include <wolfssl/wolfcrypt/visibility.h>
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+/* Detect if compiler supports C99. "NO_WOLF_C99" can be defined in
+ * user_settings.h to disable checking for C99 support. */
+#if !defined(WOLF_C99) && defined(__STDC_VERSION__) && \
+    !defined(WOLFSSL_ARDUINO) && !defined(NO_WOLF_C99)
+    #if __STDC_VERSION__ >= 199901L
+        #define WOLF_C99
+    #endif
+#endif
+
+
+/* GENERIC INCLUDE SECTION */
+#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
+    #include <mqx.h>
+    #if (defined(MQX_USE_IO_OLD) && MQX_USE_IO_OLD) || \
+        defined(FREESCALE_MQX_5_0)
+        #include <fio.h>
+    #else
+        #include <nio.h>
+    #endif
+#endif
+
+
+/* THREADING/MUTEX SECTION */
+#ifdef USE_WINDOWS_API
+    #ifdef WOLFSSL_GAME_BUILD
+        #include "system/xtl.h"
+    #else
+        #ifndef WIN32_LEAN_AND_MEAN
+            #define WIN32_LEAN_AND_MEAN
+        #endif
+        #ifndef WOLFSSL_SGX
+            #if defined(_WIN32_WCE) || defined(WIN32_LEAN_AND_MEAN)
+                /* On WinCE winsock2.h must be included before windows.h */
+                #include <winsock2.h>
+            #endif
+            #include <windows.h>
+        #endif /* WOLFSSL_SGX */
+    #endif
+#elif defined(THREADX)
+    #ifndef SINGLE_THREADED
+        #ifdef NEED_THREADX_TYPES
+            #include <types.h>
+        #endif
+        #include <tx_api.h>
+    #endif
+#elif defined(WOLFSSL_DEOS)
+    #include "mutexapi.h"
+#elif defined(MICRIUM)
+    /* do nothing, just don't pick Unix */
+#elif defined(FREERTOS) || defined(FREERTOS_TCP) || defined(WOLFSSL_SAFERTOS)
+    /* do nothing */
+#elif defined(EBSNET)
+    /* do nothing */
+#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
+    /* do nothing */
+#elif defined(FREESCALE_FREE_RTOS)
+    #include "fsl_os_abstraction.h"
+#elif defined(WOLFSSL_VXWORKS)
+    #include <semLib.h>
+#elif defined(WOLFSSL_uITRON4)
+    #include "stddef.h"
+    #include "kernel.h"
+#elif  defined(WOLFSSL_uTKERNEL2)
+    #include "tk/tkernel.h"
+#elif defined(WOLFSSL_CMSIS_RTOS)
+    #include "cmsis_os.h"
+#elif defined(WOLFSSL_CMSIS_RTOSv2)
+    #include "cmsis_os2.h"
+#elif defined(WOLFSSL_MDK_ARM)
+    #if defined(WOLFSSL_MDK5)
+        #include "cmsis_os.h"
+    #else
+        #include <rtl.h>
+    #endif
+#elif defined(WOLFSSL_CMSIS_RTOS)
+    #include "cmsis_os.h"
+#elif defined(WOLFSSL_TIRTOS)
+    #include <ti/sysbios/BIOS.h>
+    #include <ti/sysbios/knl/Semaphore.h>
+#elif defined(WOLFSSL_FROSTED)
+    #include <semaphore.h>
+#elif defined(INTIME_RTOS)
+    #include <rt.h>
+    #include <io.h>
+#elif defined(WOLFSSL_NUCLEUS_1_2)
+    /* NU_DEBUG needed struct access in nucleus_realloc */
+    #define NU_DEBUG
+    #include "plus/nucleus.h"
+    #include "nucleus.h"
+#elif defined(WOLFSSL_APACHE_MYNEWT)
+    /* do nothing */
+#elif defined(WOLFSSL_ZEPHYR)
+    #ifndef SINGLE_THREADED
+        #include <kernel.h>
+    #endif
+#elif defined(WOLFSSL_TELIT_M2MB)
+
+    /* Telit SDK uses C++ compile option (--cpp), which causes link issue
+        to API's if wrapped in extern "C" */
+    #ifdef __cplusplus
+        }  /* extern "C" */
+    #endif
+
+    #include "m2mb_types.h"
+    #include "m2mb_os_types.h"
+    #include "m2mb_os_api.h"
+    #include "m2mb_os.h"
+    #include "m2mb_os_mtx.h"
+    #ifndef NO_ASN_TIME
+    #include "m2mb_rtc.h"
+    #endif
+    #ifndef NO_FILESYSTEM
+    #include "m2mb_fs_posix.h"
+    #endif
+
+    #undef kB /* eliminate conflict in asn.h */
+
+    #ifdef __cplusplus
+        extern "C" {
+    #endif
+
+#else
+    #ifndef SINGLE_THREADED
+        #define WOLFSSL_PTHREADS
+        #include <pthread.h>
+    #endif
+    #if (defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS)) && \
+        !defined(NO_FILESYSTEM)
+        #include <unistd.h>      /* for close of BIO */
+    #endif
+#endif
+
+/* For FIPS keep the function names the same */
+#ifdef HAVE_FIPS
+#define wc_InitMutex   InitMutex
+#define wc_FreeMutex   FreeMutex
+#define wc_LockMutex   LockMutex
+#define wc_UnLockMutex UnLockMutex
+#endif /* HAVE_FIPS */
+
+#ifdef SINGLE_THREADED
+    typedef int wolfSSL_Mutex;
+#else /* MULTI_THREADED */
+    /* FREERTOS comes first to enable use of FreeRTOS Windows simulator only */
+    #if defined(FREERTOS)
+        typedef xSemaphoreHandle wolfSSL_Mutex;
+    #elif defined(FREERTOS_TCP)
+        #include "FreeRTOS.h"
+        #include "semphr.h"
+		typedef SemaphoreHandle_t  wolfSSL_Mutex;
+    #elif defined(WOLFSSL_SAFERTOS)
+        typedef struct wolfSSL_Mutex {
+            signed char mutexBuffer[portQUEUE_OVERHEAD_BYTES];
+            xSemaphoreHandle mutex;
+        } wolfSSL_Mutex;
+    #elif defined(USE_WINDOWS_API)
+        typedef CRITICAL_SECTION wolfSSL_Mutex;
+    #elif defined(WOLFSSL_PTHREADS)
+        typedef pthread_mutex_t wolfSSL_Mutex;
+    #elif defined(THREADX)
+        typedef TX_MUTEX wolfSSL_Mutex;
+    #elif defined(WOLFSSL_DEOS)
+        typedef mutex_handle_t wolfSSL_Mutex;
+    #elif defined(MICRIUM)
+        typedef OS_MUTEX wolfSSL_Mutex;
+    #elif defined(EBSNET)
+        typedef RTP_MUTEX wolfSSL_Mutex;
+    #elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
+        typedef MUTEX_STRUCT wolfSSL_Mutex;
+    #elif defined(FREESCALE_FREE_RTOS)
+        typedef mutex_t wolfSSL_Mutex;
+    #elif defined(WOLFSSL_VXWORKS)
+        typedef SEM_ID wolfSSL_Mutex;
+    #elif defined(WOLFSSL_uITRON4)
+        typedef struct wolfSSL_Mutex {
+            T_CSEM sem ;
+            ID     id ;
+        } wolfSSL_Mutex;
+    #elif defined(WOLFSSL_uTKERNEL2)
+        typedef struct wolfSSL_Mutex {
+            T_CSEM sem ;
+            ID     id ;
+        } wolfSSL_Mutex;
+    #elif defined(WOLFSSL_MDK_ARM)
+        #if defined(WOLFSSL_CMSIS_RTOS)
+            typedef osMutexId wolfSSL_Mutex;
+        #else
+            typedef OS_MUT wolfSSL_Mutex;
+        #endif
+    #elif defined(WOLFSSL_CMSIS_RTOS)
+        typedef osMutexId wolfSSL_Mutex;
+    #elif defined(WOLFSSL_CMSIS_RTOSv2)
+        typedef osMutexId_t wolfSSL_Mutex;
+    #elif defined(WOLFSSL_TIRTOS)
+        typedef ti_sysbios_knl_Semaphore_Handle wolfSSL_Mutex;
+    #elif defined(WOLFSSL_FROSTED)
+        typedef mutex_t * wolfSSL_Mutex;
+    #elif defined(INTIME_RTOS)
+        typedef RTHANDLE wolfSSL_Mutex;
+    #elif defined(WOLFSSL_NUCLEUS_1_2)
+        typedef NU_SEMAPHORE wolfSSL_Mutex;
+    #elif defined(WOLFSSL_ZEPHYR)
+        typedef struct k_mutex wolfSSL_Mutex;
+    #elif defined(WOLFSSL_TELIT_M2MB)
+        typedef M2MB_OS_MTX_HANDLE wolfSSL_Mutex;
+    #else
+        #error Need a mutex type in multithreaded mode
+    #endif /* USE_WINDOWS_API */
+#endif /* SINGLE_THREADED */
+
+/* Enable crypt HW mutex for Freescale MMCAU, PIC32MZ or STM32 */
+#if defined(FREESCALE_MMCAU) || defined(WOLFSSL_MICROCHIP_PIC32MZ) || \
+    defined(STM32_CRYPTO)
+    #ifndef WOLFSSL_CRYPT_HW_MUTEX
+        #define WOLFSSL_CRYPT_HW_MUTEX  1
+    #endif
+#endif /* FREESCALE_MMCAU */
+
+#ifndef WOLFSSL_CRYPT_HW_MUTEX
+    #define WOLFSSL_CRYPT_HW_MUTEX  0
+#endif
+
+#if WOLFSSL_CRYPT_HW_MUTEX
+    /* wolfSSL_CryptHwMutexInit is called on first wolfSSL_CryptHwMutexLock,
+       however it's recommended to call this directly on Hw init to avoid possible
+       race condition where two calls to wolfSSL_CryptHwMutexLock are made at
+       the same time. */
+    int wolfSSL_CryptHwMutexInit(void);
+    int wolfSSL_CryptHwMutexLock(void);
+    int wolfSSL_CryptHwMutexUnLock(void);
+#else
+    /* Define stubs, since HW mutex is disabled */
+    #define wolfSSL_CryptHwMutexInit()      0 /* Success */
+    #define wolfSSL_CryptHwMutexLock()      0 /* Success */
+    #define wolfSSL_CryptHwMutexUnLock()    (void)0 /* Success */
+#endif /* WOLFSSL_CRYPT_HW_MUTEX */
+
+/* Mutex functions */
+WOLFSSL_API int wc_InitMutex(wolfSSL_Mutex*);
+WOLFSSL_API wolfSSL_Mutex* wc_InitAndAllocMutex(void);
+WOLFSSL_API int wc_FreeMutex(wolfSSL_Mutex*);
+WOLFSSL_API int wc_LockMutex(wolfSSL_Mutex*);
+WOLFSSL_API int wc_UnLockMutex(wolfSSL_Mutex*);
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+/* dynamically set which mutex to use. unlock / lock is controlled by flag */
+typedef void (mutex_cb)(int flag, int type, const char* file, int line);
+
+WOLFSSL_API int wc_LockMutex_ex(int flag, int type, const char* file, int line);
+WOLFSSL_API int wc_SetMutexCb(mutex_cb* cb);
+#endif
+
+/* main crypto initialization function */
+WOLFSSL_API int wolfCrypt_Init(void);
+WOLFSSL_API int wolfCrypt_Cleanup(void);
+
+
+/* FILESYSTEM SECTION */
+/* filesystem abstraction layer, used by ssl.c */
+#ifndef NO_FILESYSTEM
+
+#if defined(EBSNET)
+    #include "vfapi.h"
+    #include "vfile.h"
+
+    int ebsnet_fseek(int a, long b, int c); /* Not prototyped in vfile.h per
+                                             * EBSnet feedback */
+
+    #define XFILE                    int
+    #define XFOPEN(NAME, MODE)       vf_open((const char *)NAME, VO_RDONLY, 0);
+    #define XFSEEK                   ebsnet_fseek
+    #define XFTELL                   vf_tell
+    #define XREWIND                  vf_rewind
+    #define XFREAD(BUF, SZ, AMT, FD) vf_read(FD, BUF, SZ*AMT)
+    #define XFWRITE(BUF, SZ, AMT, FD) vf_write(FD, BUF, SZ*AMT)
+    #define XFCLOSE                  vf_close
+    #define XSEEK_END                VSEEK_END
+    #define XBADFILE                 -1
+    #define XFGETS(b,s,f)            -2 /* Not ported yet */
+#elif defined(LSR_FS)
+    #include <fs.h>
+    #define XFILE                   struct fs_file*
+    #define XFOPEN(NAME, MODE)      fs_open((char*)NAME);
+    #define XFSEEK(F, O, W)         (void)F
+    #define XFTELL(F)               (F)->len
+    #define XREWIND(F)              (void)F
+    #define XFREAD(BUF, SZ, AMT, F) fs_read(F, (char*)BUF, SZ*AMT)
+    #define XFWRITE(BUF, SZ, AMT, F) fs_write(F, (char*)BUF, SZ*AMT)
+    #define XFCLOSE                 fs_close
+    #define XSEEK_END               0
+    #define XBADFILE                NULL
+    #define XFGETS(b,s,f)            -2 /* Not ported yet */
+#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
+    #define XFILE                   MQX_FILE_PTR
+    #define XFOPEN                  fopen
+    #define XFSEEK                  fseek
+    #define XFTELL                  ftell
+    #define XREWIND(F)              fseek(F, 0, IO_SEEK_SET)
+    #define XFREAD                  fread
+    #define XFWRITE                 fwrite
+    #define XFCLOSE                 fclose
+    #define XSEEK_END               IO_SEEK_END
+    #define XBADFILE                NULL
+    #define XFGETS                  fgets
+#elif defined(WOLFSSL_DEOS)
+    #define NO_FILESYSTEM
+    #warning "TODO - DDC-I Certifiable Fast File System for Deos is not integrated"
+    //#define XFILE      bfd *
+
+#elif defined(MICRIUM)
+    #include <fs_api.h>
+    #define XFILE      FS_FILE*
+    #define XFOPEN     fs_fopen
+    #define XFSEEK     fs_fseek
+    #define XFTELL     fs_ftell
+    #define XREWIND    fs_rewind
+    #define XFREAD     fs_fread
+    #define XFWRITE    fs_fwrite
+    #define XFCLOSE    fs_fclose
+    #define XSEEK_END  FS_SEEK_END
+    #define XBADFILE   NULL
+    #define XFGETS(b,s,f) -2 /* Not ported yet */
+#elif defined(WOLFSSL_NUCLEUS_1_2)
+    #include "fal/inc/fal.h"
+    #define XFILE      FILE*
+    #define XFOPEN     fopen
+    #define XFSEEK     fseek
+    #define XFTELL     ftell
+    #define XREWIND    rewind
+    #define XFREAD     fread
+    #define XFWRITE    fwrite
+    #define XFCLOSE    fclose
+    #define XSEEK_END  PSEEK_END
+    #define XBADFILE   NULL
+#elif defined(WOLFSSL_APACHE_MYNEWT)
+    #include <fs/fs.h>
+    #define XFILE  struct fs_file*
+
+    #define XFOPEN     mynewt_fopen
+    #define XFSEEK     mynewt_fseek
+    #define XFTELL     mynewt_ftell
+    #define XREWIND    mynewt_rewind
+    #define XFREAD     mynewt_fread
+    #define XFWRITE    mynewt_fwrite
+    #define XFCLOSE    mynewt_fclose
+    #define XSEEK_END  2
+    #define XBADFILE   NULL
+    #define XFGETS(b,s,f) -2 /* Not ported yet */
+#elif defined(WOLFSSL_ZEPHYR)
+    #include <fs.h>
+
+    #define XFILE      struct fs_file_t*
+    #define STAT       struct fs_dirent
+
+    XFILE z_fs_open(const char* filename, const char* perm);
+    int z_fs_close(XFILE file);
+
+    #define XFOPEN              z_fs_open
+    #define XFCLOSE             z_fs_close
+    #define XFSEEK              fs_seek
+    #define XFTELL              fs_tell
+    #define XFREWIND            fs_rewind
+    #define XREWIND(F)          fs_seek(F, 0, FS_SEEK_SET)
+    #define XFREAD(P,S,N,F)     fs_read(F, P, S*N)
+    #define XFWRITE(P,S,N,F)    fs_write(F, P, S*N)
+    #define XSEEK_END           FS_SEEK_END
+    #define XBADFILE            NULL
+    #define XFGETS(b,s,f)       -2 /* Not ported yet */
+
+#elif defined(WOLFSSL_TELIT_M2MB)
+    #define XFILE                    INT32
+    #define XFOPEN(NAME, MODE)       m2mb_fs_open((NAME), 0, (MODE))
+    #define XFSEEK(F, O, W)          m2mb_fs_lseek((F), (O), (W))
+    #define XFTELL(F)                m2mb_fs_lseek((F), 0, M2MB_SEEK_END)
+    #define XREWIND(F)               (void)F
+    #define XFREAD(BUF, SZ, AMT, F)  m2mb_fs_read((F), (BUF), (SZ)*(AMT))
+    #define XFWRITE(BUF, SZ, AMT, F) m2mb_fs_write((F), (BUF), (SZ)*(AMT))
+    #define XFCLOSE                  m2mb_fs_close
+    #define XSEEK_END                M2MB_SEEK_END
+    #define XBADFILE                 -1
+    #define XFGETS(b,s,f)            -2 /* Not ported yet */
+
+#elif defined(WOLFSSL_USER_FILESYSTEM)
+    /* To be defined in user_settings.h */
+#else
+    /* stdio, default case */
+    #include <stdio.h>
+    #define XFILE      FILE*
+    #if defined(WOLFSSL_MDK_ARM)
+        extern FILE * wolfSSL_fopen(const char *name, const char *mode) ;
+        #define XFOPEN     wolfSSL_fopen
+    #else
+        #define XFOPEN     fopen
+    #endif
+    #define XFSEEK     fseek
+    #define XFTELL     ftell
+    #define XREWIND    rewind
+    #define XFREAD     fread
+    #define XFWRITE    fwrite
+    #define XFCLOSE    fclose
+    #define XSEEK_END  SEEK_END
+    #define XBADFILE   NULL
+    #define XFGETS     fgets
+
+    #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR)\
+        && !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2)
+        #include <dirent.h>
+        #include <unistd.h>
+        #include <sys/stat.h>
+    #endif
+#endif
+
+    #ifndef MAX_FILENAME_SZ
+        #define MAX_FILENAME_SZ  256 /* max file name length */
+    #endif
+    #ifndef MAX_PATH
+        #define MAX_PATH 256
+    #endif
+
+#if !defined(NO_WOLFSSL_DIR) && !defined(WOLFSSL_NUCLEUS) && \
+    !defined(WOLFSSL_NUCLEUS_1_2)
+    typedef struct ReadDirCtx {
+    #ifdef USE_WINDOWS_API
+        WIN32_FIND_DATAA FindFileData;
+        HANDLE hFind;
+    #elif defined(WOLFSSL_ZEPHYR)
+        struct fs_dirent entry;
+        struct fs_dir_t  dir;
+        struct fs_dirent s;
+        struct fs_dir_t* dirp;
+
+    #elif defined(WOLFSSL_TELIT_M2MB)
+        M2MB_DIR_T* dir;
+        struct M2MB_DIRENT* entry;
+        struct M2MB_STAT s;
+    #else
+        struct dirent* entry;
+        DIR*   dir;
+        struct stat s;
+    #endif
+        char name[MAX_FILENAME_SZ];
+    } ReadDirCtx;
+
+    #define WC_READDIR_NOFILE -1
+
+    WOLFSSL_API int wc_ReadDirFirst(ReadDirCtx* ctx, const char* path, char** name);
+    WOLFSSL_API int wc_ReadDirNext(ReadDirCtx* ctx, const char* path, char** name);
+    WOLFSSL_API void wc_ReadDirClose(ReadDirCtx* ctx);
+#endif /* !NO_WOLFSSL_DIR */
+
+#endif /* !NO_FILESYSTEM */
+
+
+/* MIN/MAX MACRO SECTION */
+/* Windows API defines its own min() macro. */
+#if defined(USE_WINDOWS_API)
+    #if defined(min) || defined(WOLFSSL_MYSQL_COMPATIBLE)
+        #define WOLFSSL_HAVE_MIN
+    #endif /* min */
+    #if defined(max) || defined(WOLFSSL_MYSQL_COMPATIBLE)
+        #define WOLFSSL_HAVE_MAX
+    #endif /* max */
+#endif /* USE_WINDOWS_API */
+
+
+/* TIME SECTION */
+/* Time functions */
+#ifndef NO_ASN_TIME
+#if defined(USER_TIME)
+    /* Use our gmtime and time_t/struct tm types.
+       Only needs seconds since EPOCH using XTIME function.
+       time_t XTIME(time_t * timer) {}
+    */
+    #define WOLFSSL_GMTIME
+    #ifndef HAVE_TM_TYPE
+        #define USE_WOLF_TM
+    #endif
+    #ifndef HAVE_TIME_T_TYPE
+        #define USE_WOLF_TIME_T
+    #endif
+
+#elif defined(TIME_OVERRIDES)
+    /* Override XTIME() and XGMTIME() functionality.
+       Requires user to provide these functions:
+        time_t XTIME(time_t * timer) {}
+        struct tm* XGMTIME(const time_t* timer, struct tm* tmp) {}
+    */
+    #ifndef HAVE_TIME_T_TYPE
+        #define USE_WOLF_TIME_T
+    #endif
+    #ifndef HAVE_TM_TYPE
+        #define USE_WOLF_TM
+    #endif
+    #define NEED_TMP_TIME
+
+#elif defined(WOLFSSL_XILINX)
+    #define USER_TIME
+    #include <time.h>
+
+#elif defined(HAVE_RTP_SYS)
+    #include "os.h"           /* dc_rtc_api needs    */
+    #include "dc_rtc_api.h"   /* to get current time */
+
+    /* uses parital <time.h> structures */
+    #define XTIME(tl)       (0)
+    #define XGMTIME(c, t)   rtpsys_gmtime((c))
+
+#elif defined(WOLFSSL_DEOS)
+    #define XTIME(t1)       deos_time((t1))
+    #define WOLFSSL_GMTIME
+    #define USE_WOLF_TM
+    #define USE_WOLF_TIME_T
+
+#elif defined(MICRIUM)
+    #include <clk.h>
+    #include <time.h>
+    #define XTIME(t1)       micrium_time((t1))
+    #define WOLFSSL_GMTIME
+
+#elif defined(MICROCHIP_TCPIP_V5) || defined(MICROCHIP_TCPIP)
+    #include <time.h>
+    #define XTIME(t1)       pic32_time((t1))
+    #define XGMTIME(c, t)   gmtime((c))
+
+#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
+    #ifdef FREESCALE_MQX_4_0
+        #include <time.h>
+        extern time_t mqx_time(time_t* timer);
+    #else
+        #define HAVE_GMTIME_R
+    #endif
+    #define XTIME(t1)       mqx_time((t1))
+
+#elif defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS) || defined(FREESCALE_KSDK_FREERTOS)
+    #include <time.h>
+    #ifndef XTIME
+        /*extern time_t ksdk_time(time_t* timer);*/
+        #define XTIME(t1)   ksdk_time((t1))
+    #endif
+    #define XGMTIME(c, t)   gmtime((c))
+
+#elif defined(WOLFSSL_ATMEL) && defined(WOLFSSL_ATMEL_TIME)
+    #define XTIME(t1)       atmel_get_curr_time_and_date((t1))
+    #define WOLFSSL_GMTIME
+    #define USE_WOLF_TM
+    #define USE_WOLF_TIME_T
+
+#elif defined(WOLFSSL_WICED)
+    #include <time.h>
+    time_t wiced_pseudo_unix_epoch_time(time_t * timer);
+    #define XTIME(t1)       wiced_pseudo_unix_epoch_time((t1))
+    #define HAVE_GMTIME_R
+
+#elif defined(IDIRECT_DEV_TIME)
+    /*Gets the timestamp from cloak software owned by VT iDirect
+    in place of time() from <time.h> */
+    #include <time.h>
+    #define XTIME(t1)       idirect_time((t1))
+    #define XGMTIME(c, t)   gmtime((c))
+
+#elif defined(_WIN32_WCE)
+    #include <windows.h>
+    #define XTIME(t1)       windows_time((t1))
+    #define WOLFSSL_GMTIME
+
+#elif defined(WOLFSSL_APACHE_MYNEWT)
+    #include "os/os_time.h"
+    #define XTIME(t1)       mynewt_time((t1))
+    #define WOLFSSL_GMTIME
+    #define USE_WOLF_TM
+    #define USE_WOLF_TIME_T
+
+#elif defined(WOLFSSL_ZEPHYR)
+    #ifndef _POSIX_C_SOURCE
+        #include <posix/time.h>
+    #else
+        #include <sys/time.h>
+    #endif
+
+    typedef signed int time_t;
+
+    time_t z_time(time_t *timer);
+
+    #define XTIME(tl)       z_time((tl))
+    #define XGMTIME(c, t)   gmtime((c))
+    #define WOLFSSL_GMTIME
+
+    #define USE_WOLF_TM
+
+#elif defined(WOLFSSL_TELIT_M2MB)
+    typedef long time_t;
+    extern time_t m2mb_xtime(time_t * timer);
+    #define XTIME(tl)       m2mb_xtime((tl))
+    #ifdef WOLFSSL_TLS13
+        extern time_t m2mb_xtime_ms(time_t * timer);
+        #define XTIME_MS(tl)    m2mb_xtime_ms((tl))
+    #endif
+    #ifndef NO_CRYPT_BENCHMARK
+        extern double m2mb_xtime_bench(int reset);
+        #define WOLFSSL_CURRTIME_REMAP m2mb_xtime_bench
+    #endif
+    #define XGMTIME(c, t)   gmtime((c))
+    #define WOLFSSL_GMTIME
+    #define USE_WOLF_TM
+
+#else
+    /* default */
+    /* uses complete <time.h> facility */
+    #include <time.h>
+    #if defined(HAVE_SYS_TIME_H)
+        #include <sys/time.h>
+    #endif
+
+    /* PowerPC time_t is int */
+    #ifdef __PPC__
+        #define TIME_T_NOT_64BIT
+    #endif
+#endif
+
+#ifdef SIZEOF_TIME_T
+    /* check if size of time_t from autoconf is less than 8 bytes (64bits) */
+    #if SIZEOF_TIME_T < 8
+        #undef  TIME_T_NOT_64BIT
+        #define TIME_T_NOT_64BIT
+    #endif
+#endif
+#ifdef TIME_T_NOT_LONG
+    /* one old reference to TIME_T_NOT_LONG in GCC-ARM example README
+     * this keeps support for the old macro name */
+    #undef  TIME_T_NOT_64BIT
+    #define TIME_T_NOT_64BIT
+#endif
+
+/* Map default time functions */
+#if !defined(XTIME) && !defined(TIME_OVERRIDES) && !defined(USER_TIME)
+    #ifdef TEST_BEFORE_DATE
+    #define XTIME(tl)       (946681200UL) /* Jan 1, 2000 */
+    #else
+    #define XTIME(tl)       time((tl))
+    #endif
+#endif
+#if !defined(XGMTIME) && !defined(TIME_OVERRIDES)
+    #if defined(WOLFSSL_GMTIME) || !defined(HAVE_GMTIME_R) || defined(WOLF_C99)
+        #define XGMTIME(c, t)   gmtime((c))
+    #else
+        #define XGMTIME(c, t)   gmtime_r((c), (t))
+        #define NEED_TMP_TIME
+    #endif
+#endif
+#if !defined(XVALIDATE_DATE) && !defined(HAVE_VALIDATE_DATE)
+    #define USE_WOLF_VALIDDATE
+    #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
+#endif
+
+/* wolf struct tm and time_t */
+#if defined(USE_WOLF_TM)
+    struct tm {
+        int  tm_sec;     /* seconds after the minute [0-60] */
+        int  tm_min;     /* minutes after the hour [0-59] */
+        int  tm_hour;    /* hours since midnight [0-23] */
+        int  tm_mday;    /* day of the month [1-31] */
+        int  tm_mon;     /* months since January [0-11] */
+        int  tm_year;    /* years since 1900 */
+        int  tm_wday;    /* days since Sunday [0-6] */
+        int  tm_yday;    /* days since January 1 [0-365] */
+        int  tm_isdst;   /* Daylight Savings Time flag */
+        long tm_gmtoff;  /* offset from CUT in seconds */
+        char *tm_zone;   /* timezone abbreviation */
+    };
+#endif /* USE_WOLF_TM */
+#if defined(USE_WOLF_TIME_T)
+    typedef long time_t;
+#endif
+#if defined(USE_WOLF_SUSECONDS_T)
+    typedef long suseconds_t;
+#endif
+#if defined(USE_WOLF_TIMEVAL_T)
+    struct timeval
+    {
+        time_t tv_sec;
+        suseconds_t tv_usec;
+    };
+#endif
+
+    /* forward declarations */
+#if defined(USER_TIME)
+    struct tm* gmtime(const time_t* timer);
+    extern time_t XTIME(time_t * timer);
+
+    #ifdef STACK_TRAP
+        /* for stack trap tracking, don't call os gmtime on OS X/linux,
+           uses a lot of stack spce */
+        extern time_t time(time_t * timer);
+        #define XTIME(tl)  time((tl))
+    #endif /* STACK_TRAP */
+
+#elif defined(TIME_OVERRIDES)
+    extern time_t XTIME(time_t * timer);
+    extern struct tm* XGMTIME(const time_t* timer, struct tm* tmp);
+#elif defined(WOLFSSL_GMTIME)
+    struct tm* gmtime(const time_t* timer);
+#endif
+#endif /* NO_ASN_TIME */
+
+
+#ifndef WOLFSSL_LEANPSK
+    char* mystrnstr(const char* s1, const char* s2, unsigned int n);
+#endif
+
+#ifndef FILE_BUFFER_SIZE
+    #define FILE_BUFFER_SIZE 1024     /* default static file buffer size for input,
+                                    will use dynamic buffer if not big enough */
+#endif
+
+#ifdef HAVE_CAVIUM_OCTEON_SYNC
+    /* By default, the OCTEON's global variables are all thread local. This
+     * tag allows them to be shared between threads. */
+    #include "cvmx-platform.h"
+    #define WOLFSSL_GLOBAL CVMX_SHARED
+#else
+    #define WOLFSSL_GLOBAL
+#endif
+
+#ifdef WOLFSSL_DSP
+    #include "wolfssl_dsp.h"
+
+    /* callbacks for setting handle */
+    typedef int (*wolfSSL_DSP_Handle_cb)(remote_handle64 *handle, int finished,
+                                         void *ctx);
+    WOLFSSL_API int wolfSSL_GetHandleCbSet();
+    WOLFSSL_API int wolfSSL_SetHandleCb(wolfSSL_DSP_Handle_cb in);
+    WOLFSSL_LOCAL int wolfSSL_InitHandle();
+    WOLFSSL_LOCAL void wolfSSL_CleanupHandle();
+#endif
+
+#ifdef WOLFSSL_SCE
+    #ifndef WOLFSSL_SCE_GSCE_HANDLE
+        #define WOLFSSL_SCE_GSCE_HANDLE g_sce
+    #endif
+#endif
+
+#ifdef __cplusplus
+    }  /* extern "C" */
+#endif
+
+#endif /* WOLF_CRYPT_PORT_H */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/wolfmath.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/wolfmath.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfcrypt/wolfmath.h	(revision 453)
@@ -0,0 +1,97 @@
+/* wolfmath.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#ifndef __WOLFMATH_H__
+#define __WOLFMATH_H__
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+#ifdef WOLFSSL_PUBLIC_MP
+    #define MP_API   WOLFSSL_API
+#else
+    #define MP_API   WOLFSSL_LOCAL
+#endif
+
+#ifndef MIN
+   #define MIN(x,y) ((x)<(y)?(x):(y))
+#endif
+
+#ifndef MAX
+   #define MAX(x,y) ((x)>(y)?(x):(y))
+#endif
+
+/* timing resistance array */
+#if !defined(WC_NO_CACHE_RESISTANT) && \
+    ((defined(HAVE_ECC) && defined(ECC_TIMING_RESISTANT)) || \
+     (defined(USE_FAST_MATH) && defined(TFM_TIMING_RESISTANT)))
+
+    extern const wolfssl_word wc_off_on_addr[2];
+#endif
+
+
+/* common math functions */
+MP_API int get_digit_count(mp_int* a);
+MP_API mp_digit get_digit(mp_int* a, int n);
+MP_API int get_rand_digit(WC_RNG* rng, mp_digit* d);
+
+WOLFSSL_API int mp_cond_copy(mp_int* a, int copy, mp_int* b);
+WOLFSSL_API int mp_rand(mp_int* a, int digits, WC_RNG* rng);
+
+enum {
+    /* format type */
+    WC_TYPE_HEX_STR = 1,
+    WC_TYPE_UNSIGNED_BIN = 2,
+};
+
+WOLFSSL_API int wc_export_int(mp_int* mp, byte* buf, word32* len,
+    word32 keySz, int encType);
+
+#ifdef HAVE_WOLF_BIGINT
+    #if !defined(WOLF_BIGINT_DEFINED)
+        /* raw big integer */
+        typedef struct WC_BIGINT {
+            byte*   buf;
+            word32  len;
+            void*   heap;
+        } WC_BIGINT;
+        #define WOLF_BIGINT_DEFINED
+    #endif
+
+    WOLFSSL_LOCAL void wc_bigint_init(WC_BIGINT* a);
+    WOLFSSL_LOCAL int wc_bigint_alloc(WC_BIGINT* a, word32 sz);
+    WOLFSSL_LOCAL int wc_bigint_from_unsigned_bin(WC_BIGINT* a, const byte* in, word32 inlen);
+    WOLFSSL_LOCAL int wc_bigint_to_unsigned_bin(WC_BIGINT* a, byte* out, word32* outlen);
+    WOLFSSL_LOCAL void wc_bigint_zero(WC_BIGINT* a);
+    WOLFSSL_LOCAL void wc_bigint_free(WC_BIGINT* a);
+
+    WOLFSSL_LOCAL int wc_mp_to_bigint(mp_int* src, WC_BIGINT* dst);
+    WOLFSSL_LOCAL int wc_mp_to_bigint_sz(mp_int* src, WC_BIGINT* dst, word32 sz);
+    WOLFSSL_LOCAL int wc_bigint_to_mp(WC_BIGINT* src, mp_int* dst);
+#endif /* HAVE_WOLF_BIGINT */
+
+
+#ifdef __cplusplus
+    } /* extern "C" */
+#endif
+
+#endif /* __WOLFMATH_H__ */
Index: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfio.h
===================================================================
--- azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfio.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/wolfssl-4.4.0/wolfssl/wolfio.h	(revision 453)
@@ -0,0 +1,600 @@
+/* io.h
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/*!
+    \file wolfssl/wolfio.h
+*/
+
+#ifndef WOLFSSL_IO_H
+#define WOLFSSL_IO_H
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+/* Micrium uses NetSock I/O callbacks in wolfio.c */
+#if !defined(WOLFSSL_USER_IO)
+    /* OCSP and CRL_IO require HTTP client */
+    #if defined(HAVE_OCSP) || defined(HAVE_CRL_IO)
+        #ifndef HAVE_HTTP_CLIENT
+            #define HAVE_HTTP_CLIENT
+        #endif
+    #endif
+#endif
+
+#if !defined(WOLFSSL_USER_IO)
+    /* Micrium uses NetSock I/O callbacks in wolfio.c */
+    #if !defined(USE_WOLFSSL_IO) && !defined(MICRIUM) && \
+        !defined(WOLFSSL_CONTIKI) && !defined(WOLFSSL_NO_SOCK)
+        #define USE_WOLFSSL_IO
+    #endif
+#endif
+
+
+#if defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT)
+
+#ifdef HAVE_LIBZ
+    #include "zlib.h"
+#endif
+
+#ifndef USE_WINDOWS_API
+    #if defined(WOLFSSL_LWIP) && !defined(WOLFSSL_APACHE_MYNEWT)
+        /* lwIP needs to be configured to use sockets API in this mode */
+        /* LWIP_SOCKET 1 in lwip/opt.h or in build */
+        #include "lwip/sockets.h"
+        #ifndef LWIP_PROVIDE_ERRNO
+            #include <errno.h>
+            #define LWIP_PROVIDE_ERRNO 1
+        #endif
+    #elif defined(FREESCALE_MQX)
+        #include <posix.h>
+        #include <rtcs.h>
+    #elif defined(FREESCALE_KSDK_MQX)
+        #include <rtcs.h>
+    #elif (defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET))
+        #include "rl_net.h"
+        #include "errno.h"
+    #elif defined(WOLFSSL_CMSIS_RTOS)
+        #include "cmsis_os.h"
+    #elif defined(WOLFSSL_CMSIS_RTOSv2)
+        #include "cmsis_os2.h"
+    #elif defined(WOLFSSL_TIRTOS)
+        #include <sys/socket.h>
+    #elif defined(FREERTOS_TCP)
+        #include "FreeRTOS_Sockets.h"
+    #elif defined(WOLFSSL_IAR_ARM)
+        /* nothing */
+    #elif defined(HAVE_NETX_BSD)
+        #ifdef NETX_DUO
+            #include "nxd_bsd.h"
+        #else
+            #include "nx_bsd.h"
+        #endif
+    #elif defined(WOLFSSL_VXWORKS)
+        #include <sockLib.h>
+        #include <errno.h>
+    #elif defined(WOLFSSL_NUCLEUS_1_2)
+        #include <externs.h>
+        #include <errno.h>
+    #elif defined(WOLFSSL_ATMEL)
+        #include "socket/include/socket.h"
+    #elif defined(INTIME_RTOS)
+        #undef MIN
+        #undef MAX
+        #include <rt.h>
+        #include <sys/types.h>
+        #include <sys/socket.h>
+        #include <netdb.h>
+        #include <netinet/in.h>
+        #include <io.h>
+        /* <sys/socket.h> defines these, to avoid conflict, do undef */
+        #undef SOCKADDR
+        #undef SOCKADDR_IN
+    #elif defined(WOLFSSL_PRCONNECT_PRO)
+        #include <prconnect_pro/prconnect_pro.h>
+        #include <sys/types.h>
+        #include <errno.h>
+        #include <unistd.h>
+        #include <fcntl.h>
+        #include <netdb.h>
+        #include <sys/ioctl.h>
+    #elif defined(WOLFSSL_SGX)
+        #include <errno.h>
+    #elif defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP)
+        #include <mn_socket/mn_socket.h>
+    #elif defined(WOLFSSL_DEOS)
+        #include <socketapi.h>
+        #include <lwip-socket.h>
+        #include <errno.h>
+    #elif defined(WOLFSSL_ZEPHYR)
+        #include <net/socket.h>
+    #elif defined(HAVE_NETX)
+        #include "nx_api.h"
+        #include "errno.h"
+    #elif !defined(WOLFSSL_NO_SOCK)
+        #include <sys/types.h>
+        #include <errno.h>
+        #ifndef EBSNET
+            #include <unistd.h>
+        #endif
+        #include <fcntl.h>
+        #define XFCNTL(fd, flag, block) fcntl((fd), (flag), (block))
+
+        #if defined(HAVE_RTP_SYS)
+            #include <socket.h>
+        #elif defined(EBSNET)
+            #include "rtipapi.h"  /* errno */
+            #include "socket.h"
+        #elif !defined(DEVKITPRO) && !defined(WOLFSSL_PICOTCP) \
+                && !defined(WOLFSSL_CONTIKI) && !defined(WOLFSSL_WICED) \
+                && !defined(WOLFSSL_GNRC) && !defined(WOLFSSL_RIOT_OS)
+            #include <sys/socket.h>
+            #include <arpa/inet.h>
+            #include <netinet/in.h>
+            #include <netdb.h>
+            #ifdef __PPU
+                #include <netex/errno.h>
+            #else
+                #include <sys/ioctl.h>
+            #endif
+        #endif
+    #endif
+
+    #if defined(WOLFSSL_RENESAS_RA6M3G) /* Uses FREERTOS_TCP */
+        #include <errno.h>
+    #endif
+
+#endif /* USE_WINDOWS_API */
+
+#ifdef __sun
+    #include <sys/filio.h>
+#endif
+
+#ifdef USE_WINDOWS_API
+    /* no epipe yet */
+    #ifndef WSAEPIPE
+        #define WSAEPIPE       -12345
+    #endif
+    #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK
+    #define SOCKET_EAGAIN      WSAETIMEDOUT
+    #define SOCKET_ECONNRESET  WSAECONNRESET
+    #define SOCKET_EINTR       WSAEINTR
+    #define SOCKET_EPIPE       WSAEPIPE
+    #define SOCKET_ECONNREFUSED WSAENOTCONN
+    #define SOCKET_ECONNABORTED WSAECONNABORTED
+#elif defined(__PPU)
+    #define SOCKET_EWOULDBLOCK SYS_NET_EWOULDBLOCK
+    #define SOCKET_EAGAIN      SYS_NET_EAGAIN
+    #define SOCKET_ECONNRESET  SYS_NET_ECONNRESET
+    #define SOCKET_EINTR       SYS_NET_EINTR
+    #define SOCKET_EPIPE       SYS_NET_EPIPE
+    #define SOCKET_ECONNREFUSED SYS_NET_ECONNREFUSED
+    #define SOCKET_ECONNABORTED SYS_NET_ECONNABORTED
+#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
+    #if MQX_USE_IO_OLD
+        /* RTCS old I/O doesn't have an EWOULDBLOCK */
+        #define SOCKET_EWOULDBLOCK  EAGAIN
+        #define SOCKET_EAGAIN       EAGAIN
+        #define SOCKET_ECONNRESET   RTCSERR_TCP_CONN_RESET
+        #define SOCKET_EINTR        EINTR
+        #define SOCKET_EPIPE        EPIPE
+        #define SOCKET_ECONNREFUSED RTCSERR_TCP_CONN_REFUSED
+        #define SOCKET_ECONNABORTED RTCSERR_TCP_CONN_ABORTED
+    #else
+        #define SOCKET_EWOULDBLOCK  NIO_EWOULDBLOCK
+        #define SOCKET_EAGAIN       NIO_EAGAIN
+        #define SOCKET_ECONNRESET   NIO_ECONNRESET
+        #define SOCKET_EINTR        NIO_EINTR
+        #define SOCKET_EPIPE        NIO_EPIPE
+        #define SOCKET_ECONNREFUSED NIO_ECONNREFUSED
+        #define SOCKET_ECONNABORTED NIO_ECONNABORTED
+    #endif
+#elif defined(WOLFSSL_MDK_ARM)|| defined(WOLFSSL_KEIL_TCP_NET)
+        #define SOCKET_EWOULDBLOCK BSD_ERROR_WOULDBLOCK
+        #define SOCKET_EAGAIN      BSD_ERROR_LOCKED
+        #define SOCKET_ECONNRESET  BSD_ERROR_CLOSED
+        #define SOCKET_EINTR       BSD_ERROR
+        #define SOCKET_EPIPE       BSD_ERROR
+        #define SOCKET_ECONNREFUSED BSD_ERROR
+        #define SOCKET_ECONNABORTED BSD_ERROR
+#elif defined(WOLFSSL_PICOTCP)
+    #define SOCKET_EWOULDBLOCK  PICO_ERR_EAGAIN
+    #define SOCKET_EAGAIN       PICO_ERR_EAGAIN
+    #define SOCKET_ECONNRESET   PICO_ERR_ECONNRESET
+    #define SOCKET_EINTR        PICO_ERR_EINTR
+    #define SOCKET_EPIPE        PICO_ERR_EIO
+    #define SOCKET_ECONNREFUSED PICO_ERR_ECONNREFUSED
+    #define SOCKET_ECONNABORTED PICO_ERR_ESHUTDOWN
+#elif defined(FREERTOS_TCP)
+    #define SOCKET_EWOULDBLOCK FREERTOS_EWOULDBLOCK
+    #define SOCKET_EAGAIN       FREERTOS_EWOULDBLOCK
+    #define SOCKET_ECONNRESET   FREERTOS_SOCKET_ERROR
+    #define SOCKET_EINTR        FREERTOS_SOCKET_ERROR
+    #define SOCKET_EPIPE        FREERTOS_SOCKET_ERROR
+    #define SOCKET_ECONNREFUSED FREERTOS_SOCKET_ERROR
+    #define SOCKET_ECONNABORTED FREERTOS_SOCKET_ERROR
+#elif defined(WOLFSSL_NUCLEUS_1_2)
+    #define SOCKET_EWOULDBLOCK  NU_WOULD_BLOCK
+    #define SOCKET_EAGAIN       NU_WOULD_BLOCK
+    #define SOCKET_ECONNRESET   NU_NOT_CONNECTED
+    #define SOCKET_EINTR        NU_NOT_CONNECTED
+    #define SOCKET_EPIPE        NU_NOT_CONNECTED
+    #define SOCKET_ECONNREFUSED NU_CONNECTION_REFUSED
+    #define SOCKET_ECONNABORTED NU_NOT_CONNECTED
+#elif defined(WOLFSSL_DEOS)
+     #define SOCKET_EWOULDBLOCK EAGAIN
+     #define SOCKET_EAGAIN      EAGAIN
+     #define SOCKET_ECONNRESET  EINTR
+     #define SOCKET_EINTR       EINTR
+     #define SOCKET_EPIPE       EPIPE
+     #define SOCKET_ECONNREFUSED SOCKET_ERROR
+     #define SOCKET_ECONNABORTED SOCKET_ERROR
+#elif defined(HAVE_NETX)
+    #define SOCKET_EWOULDBLOCK NX_NOT_CONNECTED
+    #define SOCKET_EAGAIN      NX_NOT_CONNECTED
+    #define SOCKET_ECONNRESET  NX_NOT_CONNECTED
+    #define SOCKET_EINTR       NX_NOT_CONNECTED
+    #define SOCKET_EPIPE       NX_NOT_CONNECTED
+    #define SOCKET_ECONNREFUSED NX_NOT_CONNECTED
+    #define SOCKET_ECONNABORTED NX_NOT_CONNECTED
+#else
+    #define SOCKET_EWOULDBLOCK EWOULDBLOCK
+    #define SOCKET_EAGAIN      EAGAIN
+    #define SOCKET_ECONNRESET  ECONNRESET
+    #define SOCKET_EINTR       EINTR
+    #define SOCKET_EPIPE       EPIPE
+    #define SOCKET_ECONNREFUSED ECONNREFUSED
+    #define SOCKET_ECONNABORTED ECONNABORTED
+#endif /* USE_WINDOWS_API */
+
+#ifdef DEVKITPRO
+    /* from network.h */
+    int net_send(int, const void*, int, unsigned int);
+    int net_recv(int, void*, int, unsigned int);
+    #define SEND_FUNCTION net_send
+    #define RECV_FUNCTION net_recv
+#elif defined(WOLFSSL_LWIP) && !defined(WOLFSSL_APACHE_MYNEWT)
+    #define SEND_FUNCTION lwip_send
+    #define RECV_FUNCTION lwip_recv
+#elif defined(WOLFSSL_PICOTCP)
+    #define SEND_FUNCTION pico_send
+    #define RECV_FUNCTION pico_recv
+#elif defined(FREERTOS_TCP)
+    #define RECV_FUNCTION(a,b,c,d)  FreeRTOS_recv((Socket_t)(a),(void*)(b), (size_t)(c), (BaseType_t)(d))
+    #define SEND_FUNCTION(a,b,c,d)  FreeRTOS_send((Socket_t)(a),(void*)(b), (size_t)(c), (BaseType_t)(d))
+#elif defined(WOLFSSL_VXWORKS)
+    #define SEND_FUNCTION send
+    #define RECV_FUNCTION recv
+#elif defined(WOLFSSL_NUCLEUS_1_2)
+    #define SEND_FUNCTION NU_Send
+    #define RECV_FUNCTION NU_Recv
+#elif defined(WOLFSSL_ZEPHYR)
+    #ifndef WOLFSSL_MAX_SEND_SZ
+        #define WOLFSSL_MAX_SEND_SZ       256
+    #endif
+
+    #define SEND_FUNCTION send
+    #define RECV_FUNCTION recv
+#else
+    #define SEND_FUNCTION send
+    #define RECV_FUNCTION recv
+    #if !defined(HAVE_SOCKADDR) && !defined(WOLFSSL_NO_SOCK)
+        #define HAVE_SOCKADDR
+    #endif
+#endif
+
+#ifdef USE_WINDOWS_API
+    typedef unsigned int SOCKET_T;
+#else
+    typedef int SOCKET_T;
+#endif
+
+#ifndef WOLFSSL_NO_SOCK
+    #ifndef XSOCKLENT
+        #ifdef USE_WINDOWS_API
+            #define XSOCKLENT int
+        #else
+            #define XSOCKLENT socklen_t
+        #endif
+    #endif
+
+    /* Socket Addr Support */
+    #ifdef HAVE_SOCKADDR
+        typedef struct sockaddr         SOCKADDR;
+        typedef struct sockaddr_storage SOCKADDR_S;
+        typedef struct sockaddr_in      SOCKADDR_IN;
+        #ifdef WOLFSSL_IPV6
+            typedef struct sockaddr_in6 SOCKADDR_IN6;
+        #endif
+        typedef struct hostent          HOSTENT;
+    #endif /* HAVE_SOCKADDR */
+
+    /* use gethostbyname for c99 */
+    #if defined(HAVE_GETADDRINFO) && !defined(WOLF_C99)
+        typedef struct addrinfo         ADDRINFO;
+    #endif
+#endif /* WOLFSSL_NO_SOCK */
+
+
+/* IO API's */
+#ifdef HAVE_IO_TIMEOUT
+    WOLFSSL_API  int wolfIO_SetBlockingMode(SOCKET_T sockfd, int non_blocking);
+    WOLFSSL_API void wolfIO_SetTimeout(int to_sec);
+    WOLFSSL_API  int wolfIO_Select(SOCKET_T sockfd, int to_sec);
+#endif
+WOLFSSL_API  int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip,
+    unsigned short port, int to_sec);
+WOLFSSL_API  int wolfIO_Send(SOCKET_T sd, char *buf, int sz, int wrFlags);
+WOLFSSL_API  int wolfIO_Recv(SOCKET_T sd, char *buf, int sz, int rdFlags);
+
+#endif /* USE_WOLFSSL_IO || HAVE_HTTP_CLIENT */
+
+#ifndef WOLFSSL_NO_SOCK
+#ifdef USE_WINDOWS_API
+    #ifndef CloseSocket
+        #define CloseSocket(s) closesocket(s)
+    #endif
+    #define StartTCP() { WSADATA wsd; WSAStartup(0x0002, &wsd); }
+#elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET)
+    #ifndef CloseSocket
+        extern int closesocket(int);
+        #define CloseSocket(s) closesocket(s)
+    #endif
+    #define StartTCP()
+#else
+    #ifndef CloseSocket
+        #define CloseSocket(s) close(s)
+    #endif
+    #define StartTCP()
+    #ifdef FREERTOS_TCP_WINSIM
+        extern int close(int);
+    #endif
+#endif
+#endif /* WOLFSSL_NO_SOCK */
+
+
+WOLFSSL_API int BioSend(WOLFSSL* ssl, char *buf, int sz, void *ctx);
+WOLFSSL_API int BioReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx);
+#if defined(USE_WOLFSSL_IO)
+    /* default IO callbacks */
+    WOLFSSL_API int EmbedReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx);
+    WOLFSSL_API int EmbedSend(WOLFSSL* ssl, char* buf, int sz, void* ctx);
+
+    #ifdef WOLFSSL_DTLS
+        WOLFSSL_API int EmbedReceiveFrom(WOLFSSL* ssl, char* buf, int sz, void*);
+        WOLFSSL_API int EmbedSendTo(WOLFSSL* ssl, char* buf, int sz, void* ctx);
+        WOLFSSL_API int EmbedGenerateCookie(WOLFSSL* ssl, unsigned char* buf,
+                                           int sz, void*);
+        #ifdef WOLFSSL_MULTICAST
+            WOLFSSL_API int EmbedReceiveFromMcast(WOLFSSL* ssl,
+                                                  char* buf, int sz, void*);
+        #endif /* WOLFSSL_MULTICAST */
+        #ifdef WOLFSSL_SESSION_EXPORT
+            WOLFSSL_API int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz,
+                                                unsigned short* port, int* fam);
+            WOLFSSL_API int EmbedSetPeer(WOLFSSL* ssl, char* ip, int ipSz,
+                                                  unsigned short port, int fam);
+        #endif /* WOLFSSL_SESSION_EXPORT */
+    #endif /* WOLFSSL_DTLS */
+#endif /* USE_WOLFSSL_IO */
+
+#ifdef HAVE_OCSP
+    WOLFSSL_API int wolfIO_HttpBuildRequestOcsp(const char* domainName,
+        const char* path, int ocspReqSz, unsigned char* buf, int bufSize);
+    WOLFSSL_API int wolfIO_HttpProcessResponseOcsp(int sfd,
+        unsigned char** respBuf, unsigned char* httpBuf, int httpBufSz,
+        void* heap);
+
+    WOLFSSL_API int EmbedOcspLookup(void*, const char*, int, unsigned char*,
+                                   int, unsigned char**);
+    WOLFSSL_API void EmbedOcspRespFree(void*, unsigned char*);
+#endif
+
+#ifdef HAVE_CRL_IO
+    WOLFSSL_API int wolfIO_HttpBuildRequestCrl(const char* url, int urlSz,
+        const char* domainName, unsigned char* buf, int bufSize);
+    WOLFSSL_API int wolfIO_HttpProcessResponseCrl(WOLFSSL_CRL* crl, int sfd,
+        unsigned char* httpBuf, int httpBufSz);
+
+    WOLFSSL_API int EmbedCrlLookup(WOLFSSL_CRL* crl, const char* url,
+        int urlSz);
+#endif
+
+
+#if defined(HAVE_HTTP_CLIENT)
+    WOLFSSL_API  int wolfIO_DecodeUrl(const char* url, int urlSz, char* outName,
+        char* outPath, unsigned short* outPort);
+
+    WOLFSSL_API  int wolfIO_HttpBuildRequest(const char* reqType,
+        const char* domainName, const char* path, int pathLen, int reqSz,
+        const char* contentType, unsigned char* buf, int bufSize);
+    WOLFSSL_LOCAL int wolfIO_HttpBuildRequest_ex(const char* reqType,
+        const char* domainName, const char* path, int pathLen, int reqSz,
+        const char* contentType, const char *exHdrs, unsigned char* buf, int bufSize);
+    WOLFSSL_API  int wolfIO_HttpProcessResponse(int sfd, const char** appStrList,
+        unsigned char** respBuf, unsigned char* httpBuf, int httpBufSz,
+        int dynType, void* heap);
+#endif /* HAVE_HTTP_CLIENT */
+
+
+/* I/O callbacks */
+typedef int (*CallbackIORecv)(WOLFSSL *ssl, char *buf, int sz, void *ctx);
+typedef int (*CallbackIOSend)(WOLFSSL *ssl, char *buf, int sz, void *ctx);
+WOLFSSL_API void wolfSSL_CTX_SetIORecv(WOLFSSL_CTX*, CallbackIORecv);
+WOLFSSL_API void wolfSSL_CTX_SetIOSend(WOLFSSL_CTX*, CallbackIOSend);
+WOLFSSL_API void wolfSSL_SSLSetIORecv(WOLFSSL*, CallbackIORecv);
+WOLFSSL_API void wolfSSL_SSLSetIOSend(WOLFSSL*, CallbackIOSend);
+/* deprecated old name */
+#define wolfSSL_SetIORecv wolfSSL_CTX_SetIORecv
+#define wolfSSL_SetIOSend wolfSSL_CTX_SetIOSend
+
+WOLFSSL_API void wolfSSL_SetIOReadCtx( WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *ctx);
+
+WOLFSSL_API void* wolfSSL_GetIOReadCtx( WOLFSSL* ssl);
+WOLFSSL_API void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl);
+
+WOLFSSL_API void wolfSSL_SetIOReadFlags( WOLFSSL* ssl, int flags);
+WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags);
+
+
+#ifdef HAVE_NETX
+    WOLFSSL_LOCAL int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx);
+    WOLFSSL_LOCAL int NetX_Send(WOLFSSL *ssl, char *buf, int sz, void *ctx);
+
+    WOLFSSL_API void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxsocket,
+                                      ULONG waitoption);
+#endif /* HAVE_NETX */
+
+#ifdef MICRIUM
+    WOLFSSL_LOCAL int MicriumSend(WOLFSSL* ssl, char* buf, int sz, void* ctx);
+    WOLFSSL_LOCAL int MicriumReceive(WOLFSSL* ssl, char* buf, int sz,
+                                     void* ctx);
+    WOLFSSL_LOCAL int MicriumReceiveFrom(WOLFSSL* ssl, char* buf, int sz,
+                                         void* ctx);
+    WOLFSSL_LOCAL int MicriumSendTo(WOLFSSL* ssl, char* buf, int sz, void* ctx);
+#endif /* MICRIUM */
+
+#if defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP)
+    WOLFSSL_LOCAL int Mynewt_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx);
+    WOLFSSL_LOCAL int Mynewt_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx);
+    WOLFSSL_API void wolfSSL_SetIO_Mynewt(WOLFSSL* ssl, struct mn_socket* mnSocket,
+                                          struct mn_sockaddr_in* mnSockAddrIn);
+#endif /* defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) */
+
+#ifdef WOLFSSL_UIP
+
+    struct uip_wolfssl_ctx {
+        union socket_connector {
+            struct tcp_socket tcp;
+            struct udp_socket udp;
+        } conn;
+        WOLFSSL_CTX *ctx;
+        WOLFSSL *ssl;
+        uint8_t *input_databuf;
+        uint8_t *output_databuf;
+        uint8_t *ssl_rx_databuf;
+        int ssl_rb_len;
+        int ssl_rb_off;
+        struct process *process;
+        tcp_socket_data_callback_t input_callback;
+        tcp_socket_event_callback_t event_callback;
+        int closing;
+        uip_ipaddr_t peer_addr;
+        uint16_t peer_port;
+    };
+
+    typedef struct uip_wolfssl_ctx uip_wolfssl_ctx;
+
+    WOLFSSL_LOCAL int uIPSend(WOLFSSL* ssl, char* buf, int sz, void* ctx);
+    WOLFSSL_LOCAL int uIPReceive(WOLFSSL* ssl, char* buf, int sz,
+                                     void* ctx);
+    WOLFSSL_LOCAL int uIPReceiveFrom(WOLFSSL* ssl, char* buf, int sz,
+                                         void* ctx);
+    WOLFSSL_LOCAL int uIPSendTo(WOLFSSL* ssl, char* buf, int sz, void* ctx);
+
+#endif
+
+#ifdef WOLFSSL_GNRC
+    #include <sock_types.h>
+    #include <net/gnrc.h>
+    #include <net/af.h>
+    #include <net/sock.h>
+    #include <net/gnrc/tcp.h>
+    #include <net/gnrc/udp.h>
+
+    struct gnrc_wolfssl_ctx {
+        union socket_connector {
+        #ifdef MODULE_SOCK_TCP
+            sock_tcp_t tcp;
+        #endif
+            sock_udp_t udp;
+        } conn;
+        WOLFSSL_CTX *ctx;
+        WOLFSSL *ssl;
+
+        int closing;
+        struct _sock_tl_ep peer_addr;
+    };
+
+    typedef struct gnrc_wolfssl_ctx sock_tls_t;
+
+    WOLFSSL_LOCAL int GNRC_ReceiveFrom(WOLFSSL* ssl, char* buf, int sz,
+                                     void* ctx);
+    WOLFSSL_LOCAL int GNRC_SendTo(WOLFSSL* ssl, char* buf, int sz, void* ctx);
+
+#endif
+
+
+#ifdef WOLFSSL_DTLS
+    typedef int (*CallbackGenCookie)(WOLFSSL* ssl, unsigned char* buf, int sz,
+                                     void* ctx);
+    WOLFSSL_API void  wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX*, CallbackGenCookie);
+    WOLFSSL_API void  wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx);
+    WOLFSSL_API void* wolfSSL_GetCookieCtx(WOLFSSL* ssl);
+
+    #ifdef WOLFSSL_SESSION_EXPORT
+        typedef int (*CallbackGetPeer)(WOLFSSL* ssl, char* ip, int* ipSz,
+                                            unsigned short* port, int* fam);
+        typedef int (*CallbackSetPeer)(WOLFSSL* ssl, char* ip, int ipSz,
+                                              unsigned short port, int fam);
+
+        WOLFSSL_API void wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX*, CallbackGetPeer);
+        WOLFSSL_API void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX*, CallbackSetPeer);
+    #endif /* WOLFSSL_SESSION_EXPORT */
+#endif
+
+
+
+#ifndef XINET_NTOP
+    #define XINET_NTOP(a,b,c,d) inet_ntop((a),(b),(c),(d))
+    #ifdef USE_WINDOWS_API /* Windows-friendly definition */
+        #undef  XINET_NTOP
+        #define XINET_NTOP(a,b,c,d) InetNtop((a),(b),(c),(d))
+    #endif
+#endif
+#ifndef XINET_PTON
+    #define XINET_PTON(a,b,c)   inet_pton((a),(b),(c))
+    #ifdef USE_WINDOWS_API /* Windows-friendly definition */
+        #undef  XINET_PTON
+        #define XINET_PTON(a,b,c)   InetPton((a),(b),(c))
+    #endif
+#endif
+#ifndef XHTONS
+    #define XHTONS(a) htons((a))
+#endif
+#ifndef XNTOHS
+    #define XNTOHS(a) ntohs((a))
+#endif
+
+#ifndef WOLFSSL_IP4
+    #define WOLFSSL_IP4 AF_INET
+#endif
+#ifndef WOLFSSL_IP6
+    #define WOLFSSL_IP6 AF_INET6
+#endif
+
+
+#ifdef __cplusplus
+    }  /* extern "C" */
+#endif
+
+#endif /* WOLFSSL_IO_H */
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/.vscode/c_cpp_properties.json
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/.vscode/c_cpp_properties.json	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/.vscode/c_cpp_properties.json	(revision 453)
@@ -0,0 +1,15 @@
+{
+    "configurations": [
+        {
+            "name": "Sipeed Maix bit",
+            "includePath": [
+            ],
+            "windowsSdkVersion": "10.0.17763.0",
+            "compilerPath": "C:\\xpack-riscv-none-embed-gcc-8.3.0-1.2\\bin\\riscv-none-embed-gcc.exe",
+            "cStandard": "c11",
+            "cppStandard": "c++17",
+            "intelliSenseMode": "gcc-x64"
+        }
+    ],
+    "version": 4
+}
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/.vscode/settings.json
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/.vscode/settings.json	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/.vscode/settings.json	(revision 453)
@@ -0,0 +1,17 @@
+// Place your settings in this file to overwrite default and user settings.
+{
+    "terminal.integrated.setLocaleVariables": true,
+    "terminal.integrated.shell.windows": "C:\\msys64\\usr\\bin\\bash.exe",
+    "terminal.integrated.shellArgs.windows": [
+        "--login",
+        "-i"
+    ],
+    "terminal.integrated.env.windows": {
+        "PATH": "C:\\xpack-riscv-none-embed-gcc-8.3.0-1.2\\bin",
+        "CHERE_INVOKING": "1",
+        "MSYS2_PATH_TYPE": "inherit",
+        "MSYSTEM": "MINGW64"
+    },
+    "C_Cpp.intelliSenseEngine": "Tag Parser",
+    "C_Cpp.default.intelliSenseMode": "gcc-x64"
+}
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/.vscode/tasks.json
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/.vscode/tasks.json	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/.vscode/tasks.json	(revision 453)
@@ -0,0 +1,57 @@
+{
+    // See https://go.microsoft.com/fwlink/?LinkId=733558
+    // for the documentation about the tasks.json format
+    "version": "2.0.0",
+    "name": "make",
+    "type": "shell",
+    "problemMatcher": {
+        "owner": "cpp",
+        "fileLocation": [
+            "relative",
+            "${workspaceFolder}/Debug"
+        ],
+        "pattern": {
+            "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error|fatal error):\\s+(.*)$",
+            "file": 1,
+            "line": 2,
+            "column": 3,
+            "severity": 4,
+            "message": 5
+        }
+    },
+    "tasks": [
+        {
+            "label": "build zlib",
+            "args": [
+                "-j",
+                "all"
+            ],
+            "linux": {
+                "command": "make"
+            },
+            "osx": {
+                "command": "make"
+            },
+            "windows": {
+                "command": "make.exe"
+            },
+            "group": "build"
+        },
+        {
+            "label": "clean zlib",
+            "args": [
+                "clean"
+            ],
+            "linux": {
+                "command": "make"
+            },
+            "osx": {
+                "command": "make"
+            },
+            "windows": {
+                "command": "make.exe"
+            },
+            "group": "build"
+        }
+    ]
+}
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/FAQ
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/FAQ	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/FAQ	(revision 453)
@@ -0,0 +1,368 @@
+
+                Frequently Asked Questions about zlib
+
+
+If your question is not there, please check the zlib home page
+http://zlib.net/ which may have more recent information.
+The lastest zlib FAQ is at http://zlib.net/zlib_faq.html
+
+
+ 1. Is zlib Y2K-compliant?
+
+    Yes. zlib doesn't handle dates.
+
+ 2. Where can I get a Windows DLL version?
+
+    The zlib sources can be compiled without change to produce a DLL.  See the
+    file win32/DLL_FAQ.txt in the zlib distribution.  Pointers to the
+    precompiled DLL are found in the zlib web site at http://zlib.net/ .
+
+ 3. Where can I get a Visual Basic interface to zlib?
+
+    See
+        * http://marknelson.us/1997/01/01/zlib-engine/
+        * win32/DLL_FAQ.txt in the zlib distribution
+
+ 4. compress() returns Z_BUF_ERROR.
+
+    Make sure that before the call of compress(), the length of the compressed
+    buffer is equal to the available size of the compressed buffer and not
+    zero.  For Visual Basic, check that this parameter is passed by reference
+    ("as any"), not by value ("as long").
+
+ 5. deflate() or inflate() returns Z_BUF_ERROR.
+
+    Before making the call, make sure that avail_in and avail_out are not zero.
+    When setting the parameter flush equal to Z_FINISH, also make sure that
+    avail_out is big enough to allow processing all pending input.  Note that a
+    Z_BUF_ERROR is not fatal--another call to deflate() or inflate() can be
+    made with more input or output space.  A Z_BUF_ERROR may in fact be
+    unavoidable depending on how the functions are used, since it is not
+    possible to tell whether or not there is more output pending when
+    strm.avail_out returns with zero.  See http://zlib.net/zlib_how.html for a
+    heavily annotated example.
+
+ 6. Where's the zlib documentation (man pages, etc.)?
+
+    It's in zlib.h .  Examples of zlib usage are in the files test/example.c
+    and test/minigzip.c, with more in examples/ .
+
+ 7. Why don't you use GNU autoconf or libtool or ...?
+
+    Because we would like to keep zlib as a very small and simple package.
+    zlib is rather portable and doesn't need much configuration.
+
+ 8. I found a bug in zlib.
+
+    Most of the time, such problems are due to an incorrect usage of zlib.
+    Please try to reproduce the problem with a small program and send the
+    corresponding source to us at zlib@gzip.org .  Do not send multi-megabyte
+    data files without prior agreement.
+
+ 9. Why do I get "undefined reference to gzputc"?
+
+    If "make test" produces something like
+
+       example.o(.text+0x154): undefined reference to `gzputc'
+
+    check that you don't have old files libz.* in /usr/lib, /usr/local/lib or
+    /usr/X11R6/lib. Remove any old versions, then do "make install".
+
+10. I need a Delphi interface to zlib.
+
+    See the contrib/delphi directory in the zlib distribution.
+
+11. Can zlib handle .zip archives?
+
+    Not by itself, no.  See the directory contrib/minizip in the zlib
+    distribution.
+
+12. Can zlib handle .Z files?
+
+    No, sorry.  You have to spawn an uncompress or gunzip subprocess, or adapt
+    the code of uncompress on your own.
+
+13. How can I make a Unix shared library?
+
+    By default a shared (and a static) library is built for Unix.  So:
+
+    make distclean
+    ./configure
+    make
+
+14. How do I install a shared zlib library on Unix?
+
+    After the above, then:
+
+    make install
+
+    However, many flavors of Unix come with a shared zlib already installed.
+    Before going to the trouble of compiling a shared version of zlib and
+    trying to install it, you may want to check if it's already there!  If you
+    can #include <zlib.h>, it's there.  The -lz option will probably link to
+    it.  You can check the version at the top of zlib.h or with the
+    ZLIB_VERSION symbol defined in zlib.h .
+
+15. I have a question about OttoPDF.
+
+    We are not the authors of OttoPDF. The real author is on the OttoPDF web
+    site: Joel Hainley, jhainley@myndkryme.com.
+
+16. Can zlib decode Flate data in an Adobe PDF file?
+
+    Yes. See http://www.pdflib.com/ . To modify PDF forms, see
+    http://sourceforge.net/projects/acroformtool/ .
+
+17. Why am I getting this "register_frame_info not found" error on Solaris?
+
+    After installing zlib 1.1.4 on Solaris 2.6, running applications using zlib
+    generates an error such as:
+
+        ld.so.1: rpm: fatal: relocation error: file /usr/local/lib/libz.so:
+        symbol __register_frame_info: referenced symbol not found
+
+    The symbol __register_frame_info is not part of zlib, it is generated by
+    the C compiler (cc or gcc).  You must recompile applications using zlib
+    which have this problem.  This problem is specific to Solaris.  See
+    http://www.sunfreeware.com for Solaris versions of zlib and applications
+    using zlib.
+
+18. Why does gzip give an error on a file I make with compress/deflate?
+
+    The compress and deflate functions produce data in the zlib format, which
+    is different and incompatible with the gzip format.  The gz* functions in
+    zlib on the other hand use the gzip format.  Both the zlib and gzip formats
+    use the same compressed data format internally, but have different headers
+    and trailers around the compressed data.
+
+19. Ok, so why are there two different formats?
+
+    The gzip format was designed to retain the directory information about a
+    single file, such as the name and last modification date.  The zlib format
+    on the other hand was designed for in-memory and communication channel
+    applications, and has a much more compact header and trailer and uses a
+    faster integrity check than gzip.
+
+20. Well that's nice, but how do I make a gzip file in memory?
+
+    You can request that deflate write the gzip format instead of the zlib
+    format using deflateInit2().  You can also request that inflate decode the
+    gzip format using inflateInit2().  Read zlib.h for more details.
+
+21. Is zlib thread-safe?
+
+    Yes.  However any library routines that zlib uses and any application-
+    provided memory allocation routines must also be thread-safe.  zlib's gz*
+    functions use stdio library routines, and most of zlib's functions use the
+    library memory allocation routines by default.  zlib's *Init* functions
+    allow for the application to provide custom memory allocation routines.
+
+    Of course, you should only operate on any given zlib or gzip stream from a
+    single thread at a time.
+
+22. Can I use zlib in my commercial application?
+
+    Yes.  Please read the license in zlib.h.
+
+23. Is zlib under the GNU license?
+
+    No.  Please read the license in zlib.h.
+
+24. The license says that altered source versions must be "plainly marked". So
+    what exactly do I need to do to meet that requirement?
+
+    You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h.  In
+    particular, the final version number needs to be changed to "f", and an
+    identification string should be appended to ZLIB_VERSION.  Version numbers
+    x.x.x.f are reserved for modifications to zlib by others than the zlib
+    maintainers.  For example, if the version of the base zlib you are altering
+    is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and
+    ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3".  You can also
+    update the version strings in deflate.c and inftrees.c.
+
+    For altered source distributions, you should also note the origin and
+    nature of the changes in zlib.h, as well as in ChangeLog and README, along
+    with the dates of the alterations.  The origin should include at least your
+    name (or your company's name), and an email address to contact for help or
+    issues with the library.
+
+    Note that distributing a compiled zlib library along with zlib.h and
+    zconf.h is also a source distribution, and so you should change
+    ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes
+    in zlib.h as you would for a full source distribution.
+
+25. Will zlib work on a big-endian or little-endian architecture, and can I
+    exchange compressed data between them?
+
+    Yes and yes.
+
+26. Will zlib work on a 64-bit machine?
+
+    Yes.  It has been tested on 64-bit machines, and has no dependence on any
+    data types being limited to 32-bits in length.  If you have any
+    difficulties, please provide a complete problem report to zlib@gzip.org
+
+27. Will zlib decompress data from the PKWare Data Compression Library?
+
+    No.  The PKWare DCL uses a completely different compressed data format than
+    does PKZIP and zlib.  However, you can look in zlib's contrib/blast
+    directory for a possible solution to your problem.
+
+28. Can I access data randomly in a compressed stream?
+
+    No, not without some preparation.  If when compressing you periodically use
+    Z_FULL_FLUSH, carefully write all the pending data at those points, and
+    keep an index of those locations, then you can start decompression at those
+    points.  You have to be careful to not use Z_FULL_FLUSH too often, since it
+    can significantly degrade compression.  Alternatively, you can scan a
+    deflate stream once to generate an index, and then use that index for
+    random access.  See examples/zran.c .
+
+29. Does zlib work on MVS, OS/390, CICS, etc.?
+
+    It has in the past, but we have not heard of any recent evidence.  There
+    were working ports of zlib 1.1.4 to MVS, but those links no longer work.
+    If you know of recent, successful applications of zlib on these operating
+    systems, please let us know.  Thanks.
+
+30. Is there some simpler, easier to read version of inflate I can look at to
+    understand the deflate format?
+
+    First off, you should read RFC 1951.  Second, yes.  Look in zlib's
+    contrib/puff directory.
+
+31. Does zlib infringe on any patents?
+
+    As far as we know, no.  In fact, that was originally the whole point behind
+    zlib.  Look here for some more information:
+
+    http://www.gzip.org/#faq11
+
+32. Can zlib work with greater than 4 GB of data?
+
+    Yes.  inflate() and deflate() will process any amount of data correctly.
+    Each call of inflate() or deflate() is limited to input and output chunks
+    of the maximum value that can be stored in the compiler's "unsigned int"
+    type, but there is no limit to the number of chunks.  Note however that the
+    strm.total_in and strm_total_out counters may be limited to 4 GB.  These
+    counters are provided as a convenience and are not used internally by
+    inflate() or deflate().  The application can easily set up its own counters
+    updated after each call of inflate() or deflate() to count beyond 4 GB.
+    compress() and uncompress() may be limited to 4 GB, since they operate in a
+    single call.  gzseek() and gztell() may be limited to 4 GB depending on how
+    zlib is compiled.  See the zlibCompileFlags() function in zlib.h.
+
+    The word "may" appears several times above since there is a 4 GB limit only
+    if the compiler's "long" type is 32 bits.  If the compiler's "long" type is
+    64 bits, then the limit is 16 exabytes.
+
+33. Does zlib have any security vulnerabilities?
+
+    The only one that we are aware of is potentially in gzprintf().  If zlib is
+    compiled to use sprintf() or vsprintf(), then there is no protection
+    against a buffer overflow of an 8K string space (or other value as set by
+    gzbuffer()), other than the caller of gzprintf() assuring that the output
+    will not exceed 8K.  On the other hand, if zlib is compiled to use
+    snprintf() or vsnprintf(), which should normally be the case, then there is
+    no vulnerability.  The ./configure script will display warnings if an
+    insecure variation of sprintf() will be used by gzprintf().  Also the
+    zlibCompileFlags() function will return information on what variant of
+    sprintf() is used by gzprintf().
+
+    If you don't have snprintf() or vsnprintf() and would like one, you can
+    find a portable implementation here:
+
+        http://www.ijs.si/software/snprintf/
+
+    Note that you should be using the most recent version of zlib.  Versions
+    1.1.3 and before were subject to a double-free vulnerability, and versions
+    1.2.1 and 1.2.2 were subject to an access exception when decompressing
+    invalid compressed data.
+
+34. Is there a Java version of zlib?
+
+    Probably what you want is to use zlib in Java. zlib is already included
+    as part of the Java SDK in the java.util.zip package. If you really want
+    a version of zlib written in the Java language, look on the zlib home
+    page for links: http://zlib.net/ .
+
+35. I get this or that compiler or source-code scanner warning when I crank it
+    up to maximally-pedantic. Can't you guys write proper code?
+
+    Many years ago, we gave up attempting to avoid warnings on every compiler
+    in the universe.  It just got to be a waste of time, and some compilers
+    were downright silly as well as contradicted each other.  So now, we simply
+    make sure that the code always works.
+
+36. Valgrind (or some similar memory access checker) says that deflate is
+    performing a conditional jump that depends on an uninitialized value.
+    Isn't that a bug?
+
+    No.  That is intentional for performance reasons, and the output of deflate
+    is not affected.  This only started showing up recently since zlib 1.2.x
+    uses malloc() by default for allocations, whereas earlier versions used
+    calloc(), which zeros out the allocated memory.  Even though the code was
+    correct, versions 1.2.4 and later was changed to not stimulate these
+    checkers.
+
+37. Will zlib read the (insert any ancient or arcane format here) compressed
+    data format?
+
+    Probably not. Look in the comp.compression FAQ for pointers to various
+    formats and associated software.
+
+38. How can I encrypt/decrypt zip files with zlib?
+
+    zlib doesn't support encryption.  The original PKZIP encryption is very
+    weak and can be broken with freely available programs.  To get strong
+    encryption, use GnuPG, http://www.gnupg.org/ , which already includes zlib
+    compression.  For PKZIP compatible "encryption", look at
+    http://www.info-zip.org/
+
+39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings?
+
+    "gzip" is the gzip format, and "deflate" is the zlib format.  They should
+    probably have called the second one "zlib" instead to avoid confusion with
+    the raw deflate compressed data format.  While the HTTP 1.1 RFC 2616
+    correctly points to the zlib specification in RFC 1950 for the "deflate"
+    transfer encoding, there have been reports of servers and browsers that
+    incorrectly produce or expect raw deflate data per the deflate
+    specification in RFC 1951, most notably Microsoft.  So even though the
+    "deflate" transfer encoding using the zlib format would be the more
+    efficient approach (and in fact exactly what the zlib format was designed
+    for), using the "gzip" transfer encoding is probably more reliable due to
+    an unfortunate choice of name on the part of the HTTP 1.1 authors.
+
+    Bottom line: use the gzip format for HTTP 1.1 encoding.
+
+40. Does zlib support the new "Deflate64" format introduced by PKWare?
+
+    No.  PKWare has apparently decided to keep that format proprietary, since
+    they have not documented it as they have previous compression formats.  In
+    any case, the compression improvements are so modest compared to other more
+    modern approaches, that it's not worth the effort to implement.
+
+41. I'm having a problem with the zip functions in zlib, can you help?
+
+    There are no zip functions in zlib.  You are probably using minizip by
+    Giles Vollant, which is found in the contrib directory of zlib.  It is not
+    part of zlib.  In fact none of the stuff in contrib is part of zlib.  The
+    files in there are not supported by the zlib authors.  You need to contact
+    the authors of the respective contribution for help.
+
+42. The match.asm code in contrib is under the GNU General Public License.
+    Since it's part of zlib, doesn't that mean that all of zlib falls under the
+    GNU GPL?
+
+    No.  The files in contrib are not part of zlib.  They were contributed by
+    other authors and are provided as a convenience to the user within the zlib
+    distribution.  Each item in contrib has its own license.
+
+43. Is zlib subject to export controls?  What is its ECCN?
+
+    zlib is not subject to export controls, and so is classified as EAR99.
+
+44. Can you please sign these lengthy legal documents and fax them back to us
+    so that we can use your software in our product?
+
+    No. Go away. Shoo.
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/INDEX
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/INDEX	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/INDEX	(revision 453)
@@ -0,0 +1,68 @@
+CMakeLists.txt  cmake build file
+ChangeLog       history of changes
+FAQ             Frequently Asked Questions about zlib
+INDEX           this file
+Makefile        dummy Makefile that tells you to ./configure
+Makefile.in     template for Unix Makefile
+README          guess what
+configure       configure script for Unix
+make_vms.com    makefile for VMS
+test/example.c  zlib usages examples for build testing
+test/minigzip.c minimal gzip-like functionality for build testing
+test/infcover.c inf*.c code coverage for build coverage testing
+treebuild.xml   XML description of source file dependencies
+zconf.h.cmakein zconf.h template for cmake
+zconf.h.in      zconf.h template for configure
+zlib.3          Man page for zlib
+zlib.3.pdf      Man page in PDF format
+zlib.map        Linux symbol information
+zlib.pc.in      Template for pkg-config descriptor
+zlib.pc.cmakein zlib.pc template for cmake
+zlib2ansi       perl script to convert source files for C++ compilation
+
+amiga/          makefiles for Amiga SAS C
+as400/          makefiles for AS/400
+doc/            documentation for formats and algorithms
+msdos/          makefiles for MSDOS
+nintendods/     makefile for Nintendo DS
+old/            makefiles for various architectures and zlib documentation
+                files that have not yet been updated for zlib 1.2.x
+qnx/            makefiles for QNX
+watcom/         makefiles for OpenWatcom
+win32/          makefiles for Windows
+
+                zlib public header files (required for library use):
+zconf.h
+zlib.h
+
+                private source files used to build the zlib library:
+adler32.c
+compress.c
+crc32.c
+crc32.h
+deflate.c
+deflate.h
+gzclose.c
+gzguts.h
+gzlib.c
+gzread.c
+gzwrite.c
+infback.c
+inffast.c
+inffast.h
+inffixed.h
+inflate.c
+inflate.h
+inftrees.c
+inftrees.h
+trees.c
+trees.h
+uncompr.c
+zutil.c
+zutil.h
+
+                source files for sample programs
+See examples/README.examples
+
+                unsupported contributions by third parties
+See contrib/README.contrib
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/Makefile
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/Makefile	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/Makefile	(revision 453)
@@ -0,0 +1,185 @@
+# This file was automagically generated by mbed.org. For more information, 
+# see http://mbed.org/handbook/Exporting-to-GCC-ARM-Embedded
+
+###############################################################################
+# Boiler-plate
+
+# cross-platform directory manipulation
+ifeq ($(shell echo $$OS),$$OS)
+    MAKEDIR = if not exist "$(1)" mkdir "$(1)"
+    RM = rmdir /S /Q "$(1)"
+else
+    MAKEDIR = '$(SHELL)' -c "mkdir -p \"$(1)\""
+    RM = '$(SHELL)' -c "rm -rf \"$(1)\""
+endif
+
+OBJDIR := Debug
+# Move to the build directory
+ifeq (,$(filter $(OBJDIR),$(notdir $(CURDIR))))
+.SUFFIXES:
+mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
+MAKETARGET = '$(MAKE)' --no-print-directory -C $(OBJDIR) -f '$(mkfile_path)' \
+		'SRCDIR=$(CURDIR)' $(MAKECMDGOALS)
+.PHONY: $(OBJDIR) clean
+all:
+	+@$(call MAKEDIR,$(OBJDIR))
+	+@$(MAKETARGET)
+$(OBJDIR): all
+Makefile : ;
+% :: $(OBJDIR) ; :
+clean :
+	$(call RM,$(OBJDIR))
+
+else
+
+# trick rules into thinking we are in the root, when we are in the bulid dir
+VPATH = ../../zlib-1.2.11
+
+# Boiler-plate
+###############################################################################
+# Project settings
+
+PROJECT := zlib
+
+
+# Project settings
+###############################################################################
+# Objects and Paths
+
+OBJECTS += src/adler32.o
+OBJECTS += src/compress.o
+OBJECTS += src/crc32.o
+OBJECTS += src/deflate.o
+#OBJECTS += src/gzclose.o
+#OBJECTS += src/gzlib.o
+#OBJECTS += src/gzread.o
+#OBJECTS += src/gzwrite.o
+OBJECTS += src/infback.o
+OBJECTS += src/inffast.o
+OBJECTS += src/inflate.o
+OBJECTS += src/inftrees.o
+OBJECTS += src/trees.o
+OBJECTS += src/uncompr.o
+OBJECTS += src/zutil.o
+
+INCLUDE_PATHS += -I../../asp_baseplatform
+INCLUDE_PATHS += -I../../asp_baseplatform/include
+INCLUDE_PATHS += -I../../asp_baseplatform/arch
+INCLUDE_PATHS += -I../../asp_baseplatform/arch/riscv_gcc
+INCLUDE_PATHS += -I../../asp_baseplatform/target/k210_gcc
+INCLUDE_PATHS += -I../../asp_baseplatform/OBJ/K210_GCC/DEMO
+INCLUDE_PATHS += -I../../asp_baseplatform/monitor
+INCLUDE_PATHS += -I../../asp_baseplatform/files
+
+# Objects and Paths
+###############################################################################
+# Tools and Flags
+
+AS      = riscv-none-embed-gcc
+CC      = riscv-none-embed-gcc
+CPP     = riscv-none-embed-g++
+AR      = riscv-none-embed-ar
+RANLIB  = riscv-none-embed-ranlib
+
+
+C_FLAGS += -std=gnu11
+C_FLAGS += -march=rv64imafdc
+C_FLAGS += -mabi=lp64d
+C_FLAGS += -mcmodel=medany
+C_FLAGS += -O2
+C_FLAGS += -fmessage-length=0
+C_FLAGS += -fsigned-char
+C_FLAGS += -ffunction-sections
+C_FLAGS += -fdata-sections
+C_FLAGS += -Wall
+C_FLAGS += -Wextra
+C_FLAGS += -Wno-unused-parameter
+C_FLAGS += -Wno-missing-field-initializers
+C_FLAGS += -Wnull-dereference
+
+C_FLAGS += -g3
+C_FLAGS += -Wstack-usage=256
+
+CXX_FLAGS += -std=gnu++11
+CXX_FLAGS += -std=gnu11
+CXX_FLAGS += -march=rv64imafdc
+CXX_FLAGS += -mabi=lp64d
+CXX_FLAGS += -mcmodel=medany
+CXX_FLAGS += -O2
+CXX_FLAGS += -fmessage-length=0
+CXX_FLAGS += -fsigned-char
+CXX_FLAGS += -ffunction-sections
+CXX_FLAGS += -fdata-sections
+CXX_FLAGS += -Wall
+CXX_FLAGS += -Wextra
+CXX_FLAGS += -Wno-unused-parameter
+CXX_FLAGS += -Wno-missing-field-initializers
+CXX_FLAGS += -Wnull-dereference
+
+CXX_FLAGS += -g3
+CXX_FLAGS += -Wstack-usage=256
+
+ASM_FLAGS += -x
+ASM_FLAGS += assembler-with-cpp
+ASM_FLAGS += -march=rv64imafdc
+ASM_FLAGS += -mabi=lp64d
+ASM_FLAGS += -mcmodel=medany
+ASM_FLAGS += -O2
+ASM_FLAGS += -fmessage-length=0
+ASM_FLAGS += -fsigned-char
+ASM_FLAGS += -ffunction-sections
+ASM_FLAGS += -fdata-sections
+ASM_FLAGS += -Wall
+ASM_FLAGS += -Wextra
+ASM_FLAGS += -Wno-unused-parameter
+ASM_FLAGS += -Wno-missing-field-initializers
+ASM_FLAGS += -Wnull-dereference
+ASM_FLAGS += -g3
+ASM_FLAGS += -Wstack-usage=256
+
+
+# Tools and Flags
+###############################################################################
+# Rules
+
+.PHONY: all lst size
+
+
+all: lib$(PROJECT).a
+
+
+.s.o:
+	+@$(call MAKEDIR,$(dir $@))
+	+@echo "Assemble: $(notdir $<)"
+	@$(AS) -c $(ASM_FLAGS) -o $@ $<
+
+.S.o:
+	+@$(call MAKEDIR,$(dir $@))
+	+@echo "Assemble: $(notdir $<)"
+	@$(AS) -c $(ASM_FLAGS) -o $@ $<
+
+.c.o:
+	+@$(call MAKEDIR,$(dir $@))
+	+@echo "Compile: $(notdir $<)"
+	@$(CC) $(C_FLAGS) $(INCLUDE_PATHS) -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -c -o "$@" "$<"
+
+.cpp.o:
+	+@$(call MAKEDIR,$(dir $@))
+	+@echo "Compile: $(notdir $<)"
+	@$(CPP) $(CXX_FLAGS) $(INCLUDE_PATHS) -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -c -o "$@" "$<"
+
+lib$(PROJECT).a: $(OBJECTS)
+	rm -f lib$(PROJECT).a
+	$(AR) -rcs lib$(PROJECT).a $(OBJECTS)
+	$(RANLIB) lib$(PROJECT).a
+
+# Rules
+###############################################################################
+# Dependencies
+
+DEPS = $(OBJECTS:.o=.d) $(SYS_OBJECTS:.o=.d)
+-include $(DEPS)
+endif
+
+# Dependencies
+###############################################################################
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/README
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/README	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/README	(revision 453)
@@ -0,0 +1,115 @@
+ZLIB DATA COMPRESSION LIBRARY
+
+zlib 1.2.11 is a general purpose data compression library.  All the code is
+thread safe.  The data format used by the zlib library is described by RFCs
+(Request for Comments) 1950 to 1952 in the files
+http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and
+rfc1952 (gzip format).
+
+All functions of the compression library are documented in the file zlib.h
+(volunteer to write man pages welcome, contact zlib@gzip.org).  A usage example
+of the library is given in the file test/example.c which also tests that
+the library is working correctly.  Another example is given in the file
+test/minigzip.c.  The compression library itself is composed of all source
+files in the root directory.
+
+To compile all files and run the test program, follow the instructions given at
+the top of Makefile.in.  In short "./configure; make test", and if that goes
+well, "make install" should work for most flavors of Unix.  For Windows, use
+one of the special makefiles in win32/ or contrib/vstudio/ .  For VMS, use
+make_vms.com.
+
+Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant
+<info@winimage.com> for the Windows DLL version.  The zlib home page is
+http://zlib.net/ .  Before reporting a problem, please check this site to
+verify that you have the latest version of zlib; otherwise get the latest
+version and check whether the problem still exists or not.
+
+PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help.
+
+Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan.  1997
+issue of Dr.  Dobb's Journal; a copy of the article is available at
+http://marknelson.us/1997/01/01/zlib-engine/ .
+
+The changes made in version 1.2.11 are documented in the file ChangeLog.
+
+Unsupported third party contributions are provided in directory contrib/ .
+
+zlib is available in Java using the java.util.zip package, documented at
+http://java.sun.com/developer/technicalArticles/Programming/compression/ .
+
+A Perl interface to zlib written by Paul Marquess <pmqs@cpan.org> is available
+at CPAN (Comprehensive Perl Archive Network) sites, including
+http://search.cpan.org/~pmqs/IO-Compress-Zlib/ .
+
+A Python interface to zlib written by A.M. Kuchling <amk@amk.ca> is
+available in Python 1.5 and later versions, see
+http://docs.python.org/library/zlib.html .
+
+zlib is built into tcl: http://wiki.tcl.tk/4610 .
+
+An experimental package to read and write files in .zip format, written on top
+of zlib by Gilles Vollant <info@winimage.com>, is available in the
+contrib/minizip directory of zlib.
+
+
+Notes for some targets:
+
+- For Windows DLL versions, please see win32/DLL_FAQ.txt
+
+- For 64-bit Irix, deflate.c must be compiled without any optimization. With
+  -O, one libpng test fails. The test works in 32 bit mode (with the -n32
+  compiler flag). The compiler bug has been reported to SGI.
+
+- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works
+  when compiled with cc.
+
+- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is
+  necessary to get gzprintf working correctly. This is done by configure.
+
+- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with
+  other compilers. Use "make test" to check your compiler.
+
+- gzdopen is not supported on RISCOS or BEOS.
+
+- For PalmOs, see http://palmzlib.sourceforge.net/
+
+
+Acknowledgments:
+
+  The deflate format used by zlib was defined by Phil Katz.  The deflate and
+  zlib specifications were written by L.  Peter Deutsch.  Thanks to all the
+  people who reported problems and suggested various improvements in zlib; they
+  are too numerous to cite here.
+
+Copyright notice:
+
+ (C) 1995-2017 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  jloup@gzip.org          madler@alumni.caltech.edu
+
+If you use the zlib library in a product, we would appreciate *not* receiving
+lengthy legal documents to sign.  The sources are provided for free but without
+warranty of any kind.  The library has been entirely written by Jean-loup
+Gailly and Mark Adler; it does not include third-party code.
+
+If you redistribute modified sources, we would appreciate that you include in
+the file ChangeLog history information documenting your changes.  Please read
+the FAQ for more information on the distribution of modified source versions.
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/src/adler32.c
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/src/adler32.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/src/adler32.c	(revision 453)
@@ -0,0 +1,186 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-2011, 2016 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include "zutil.h"
+
+local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
+
+#define BASE 65521U     /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i)  {adler += (buf)[i]; sum2 += adler;}
+#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf)   DO8(buf,0); DO8(buf,8);
+
+/* use NO_DIVIDE if your processor does not do division in hardware --
+   try it both ways to see which is faster */
+#ifdef NO_DIVIDE
+/* note that this assumes BASE is 65521, where 65536 % 65521 == 15
+   (thank you to John Reiser for pointing this out) */
+#  define CHOP(a) \
+    do { \
+        unsigned long tmp = a >> 16; \
+        a &= 0xffffUL; \
+        a += (tmp << 4) - tmp; \
+    } while (0)
+#  define MOD28(a) \
+    do { \
+        CHOP(a); \
+        if (a >= BASE) a -= BASE; \
+    } while (0)
+#  define MOD(a) \
+    do { \
+        CHOP(a); \
+        MOD28(a); \
+    } while (0)
+#  define MOD63(a) \
+    do { /* this assumes a is not negative */ \
+        z_off64_t tmp = a >> 32; \
+        a &= 0xffffffffL; \
+        a += (tmp << 8) - (tmp << 5) + tmp; \
+        tmp = a >> 16; \
+        a &= 0xffffL; \
+        a += (tmp << 4) - tmp; \
+        tmp = a >> 16; \
+        a &= 0xffffL; \
+        a += (tmp << 4) - tmp; \
+        if (a >= BASE) a -= BASE; \
+    } while (0)
+#else
+#  define MOD(a) a %= BASE
+#  define MOD28(a) a %= BASE
+#  define MOD63(a) a %= BASE
+#endif
+
+/* ========================================================================= */
+uLong ZEXPORT adler32_z(adler, buf, len)
+    uLong adler;
+    const Bytef *buf;
+    z_size_t len;
+{
+    unsigned long sum2;
+    unsigned n;
+
+    /* split Adler-32 into component sums */
+    sum2 = (adler >> 16) & 0xffff;
+    adler &= 0xffff;
+
+    /* in case user likes doing a byte at a time, keep it fast */
+    if (len == 1) {
+        adler += buf[0];
+        if (adler >= BASE)
+            adler -= BASE;
+        sum2 += adler;
+        if (sum2 >= BASE)
+            sum2 -= BASE;
+        return adler | (sum2 << 16);
+    }
+
+    /* initial Adler-32 value (deferred check for len == 1 speed) */
+    if (buf == Z_NULL)
+        return 1L;
+
+    /* in case short lengths are provided, keep it somewhat fast */
+    if (len < 16) {
+        while (len--) {
+            adler += *buf++;
+            sum2 += adler;
+        }
+        if (adler >= BASE)
+            adler -= BASE;
+        MOD28(sum2);            /* only added so many BASE's */
+        return adler | (sum2 << 16);
+    }
+
+    /* do length NMAX blocks -- requires just one modulo operation */
+    while (len >= NMAX) {
+        len -= NMAX;
+        n = NMAX / 16;          /* NMAX is divisible by 16 */
+        do {
+            DO16(buf);          /* 16 sums unrolled */
+            buf += 16;
+        } while (--n);
+        MOD(adler);
+        MOD(sum2);
+    }
+
+    /* do remaining bytes (less than NMAX, still just one modulo) */
+    if (len) {                  /* avoid modulos if none remaining */
+        while (len >= 16) {
+            len -= 16;
+            DO16(buf);
+            buf += 16;
+        }
+        while (len--) {
+            adler += *buf++;
+            sum2 += adler;
+        }
+        MOD(adler);
+        MOD(sum2);
+    }
+
+    /* return recombined sums */
+    return adler | (sum2 << 16);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT adler32(adler, buf, len)
+    uLong adler;
+    const Bytef *buf;
+    uInt len;
+{
+    return adler32_z(adler, buf, len);
+}
+
+/* ========================================================================= */
+local uLong adler32_combine_(adler1, adler2, len2)
+    uLong adler1;
+    uLong adler2;
+    z_off64_t len2;
+{
+    unsigned long sum1;
+    unsigned long sum2;
+    unsigned rem;
+
+    /* for negative len, return invalid adler32 as a clue for debugging */
+    if (len2 < 0)
+        return 0xffffffffUL;
+
+    /* the derivation of this formula is left as an exercise for the reader */
+    MOD63(len2);                /* assumes len2 >= 0 */
+    rem = (unsigned)len2;
+    sum1 = adler1 & 0xffff;
+    sum2 = rem * sum1;
+    MOD(sum2);
+    sum1 += (adler2 & 0xffff) + BASE - 1;
+    sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
+    if (sum1 >= BASE) sum1 -= BASE;
+    if (sum1 >= BASE) sum1 -= BASE;
+    if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1);
+    if (sum2 >= BASE) sum2 -= BASE;
+    return sum1 | (sum2 << 16);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT adler32_combine(adler1, adler2, len2)
+    uLong adler1;
+    uLong adler2;
+    z_off_t len2;
+{
+    return adler32_combine_(adler1, adler2, len2);
+}
+
+uLong ZEXPORT adler32_combine64(adler1, adler2, len2)
+    uLong adler1;
+    uLong adler2;
+    z_off64_t len2;
+{
+    return adler32_combine_(adler1, adler2, len2);
+}
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/src/compress.c
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/src/compress.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/src/compress.c	(revision 453)
@@ -0,0 +1,86 @@
+/* compress.c -- compress a memory buffer
+ * Copyright (C) 1995-2005, 2014, 2016 Jean-loup Gailly, Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+/* ===========================================================================
+     Compresses the source buffer into the destination buffer. The level
+   parameter has the same meaning as in deflateInit.  sourceLen is the byte
+   length of the source buffer. Upon entry, destLen is the total size of the
+   destination buffer, which must be at least 0.1% larger than sourceLen plus
+   12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+   Z_STREAM_ERROR if the level parameter is invalid.
+*/
+int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
+    Bytef *dest;
+    uLongf *destLen;
+    const Bytef *source;
+    uLong sourceLen;
+    int level;
+{
+    z_stream stream;
+    int err;
+    const uInt max = (uInt)-1;
+    uLong left;
+
+    left = *destLen;
+    *destLen = 0;
+
+    stream.zalloc = (alloc_func)0;
+    stream.zfree = (free_func)0;
+    stream.opaque = (voidpf)0;
+
+    err = deflateInit(&stream, level);
+    if (err != Z_OK) return err;
+
+    stream.next_out = dest;
+    stream.avail_out = 0;
+    stream.next_in = (z_const Bytef *)source;
+    stream.avail_in = 0;
+
+    do {
+        if (stream.avail_out == 0) {
+            stream.avail_out = left > (uLong)max ? max : (uInt)left;
+            left -= stream.avail_out;
+        }
+        if (stream.avail_in == 0) {
+            stream.avail_in = sourceLen > (uLong)max ? max : (uInt)sourceLen;
+            sourceLen -= stream.avail_in;
+        }
+        err = deflate(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH);
+    } while (err == Z_OK);
+
+    *destLen = stream.total_out;
+    deflateEnd(&stream);
+    return err == Z_STREAM_END ? Z_OK : err;
+}
+
+/* ===========================================================================
+ */
+int ZEXPORT compress (dest, destLen, source, sourceLen)
+    Bytef *dest;
+    uLongf *destLen;
+    const Bytef *source;
+    uLong sourceLen;
+{
+    return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
+}
+
+/* ===========================================================================
+     If the default memLevel or windowBits for deflateInit() is changed, then
+   this function needs to be updated.
+ */
+uLong ZEXPORT compressBound (sourceLen)
+    uLong sourceLen;
+{
+    return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
+           (sourceLen >> 25) + 13;
+}
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/src/crc32.c
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/src/crc32.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/src/crc32.c	(revision 453)
@@ -0,0 +1,442 @@
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
+ * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
+ * tables for updating the shift register in one step with three exclusive-ors
+ * instead of four steps with four exclusive-ors.  This results in about a
+ * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
+ */
+
+/* @(#) $Id$ */
+
+/*
+  Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
+  protection on the static variables used to control the first-use generation
+  of the crc tables.  Therefore, if you #define DYNAMIC_CRC_TABLE, you should
+  first call get_crc_table() to initialize the tables before allowing more than
+  one thread to use crc32().
+
+  DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h.
+ */
+
+#ifdef MAKECRCH
+#  include <stdio.h>
+#  ifndef DYNAMIC_CRC_TABLE
+#    define DYNAMIC_CRC_TABLE
+#  endif /* !DYNAMIC_CRC_TABLE */
+#endif /* MAKECRCH */
+
+#include "zutil.h"      /* for STDC and FAR definitions */
+
+/* Definitions for doing the crc four data bytes at a time. */
+#if !defined(NOBYFOUR) && defined(Z_U4)
+#  define BYFOUR
+#endif
+#ifdef BYFOUR
+   local unsigned long crc32_little OF((unsigned long,
+                        const unsigned char FAR *, z_size_t));
+   local unsigned long crc32_big OF((unsigned long,
+                        const unsigned char FAR *, z_size_t));
+#  define TBLS 8
+#else
+#  define TBLS 1
+#endif /* BYFOUR */
+
+/* Local functions for crc concatenation */
+local unsigned long gf2_matrix_times OF((unsigned long *mat,
+                                         unsigned long vec));
+local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
+local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2));
+
+
+#ifdef DYNAMIC_CRC_TABLE
+
+local volatile int crc_table_empty = 1;
+local z_crc_t FAR crc_table[TBLS][256];
+local void make_crc_table OF((void));
+#ifdef MAKECRCH
+   local void write_table OF((FILE *, const z_crc_t FAR *));
+#endif /* MAKECRCH */
+/*
+  Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
+  x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
+
+  Polynomials over GF(2) are represented in binary, one bit per coefficient,
+  with the lowest powers in the most significant bit.  Then adding polynomials
+  is just exclusive-or, and multiplying a polynomial by x is a right shift by
+  one.  If we call the above polynomial p, and represent a byte as the
+  polynomial q, also with the lowest power in the most significant bit (so the
+  byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
+  where a mod b means the remainder after dividing a by b.
+
+  This calculation is done using the shift-register method of multiplying and
+  taking the remainder.  The register is initialized to zero, and for each
+  incoming bit, x^32 is added mod p to the register if the bit is a one (where
+  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
+  x (which is shifting right by one and adding x^32 mod p if the bit shifted
+  out is a one).  We start with the highest power (least significant bit) of
+  q and repeat for all eight bits of q.
+
+  The first table is simply the CRC of all possible eight bit values.  This is
+  all the information needed to generate CRCs on data a byte at a time for all
+  combinations of CRC register values and incoming bytes.  The remaining tables
+  allow for word-at-a-time CRC calculation for both big-endian and little-
+  endian machines, where a word is four bytes.
+*/
+local void make_crc_table()
+{
+    z_crc_t c;
+    int n, k;
+    z_crc_t poly;                       /* polynomial exclusive-or pattern */
+    /* terms of polynomial defining this crc (except x^32): */
+    static volatile int first = 1;      /* flag to limit concurrent making */
+    static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+
+    /* See if another task is already doing this (not thread-safe, but better
+       than nothing -- significantly reduces duration of vulnerability in
+       case the advice about DYNAMIC_CRC_TABLE is ignored) */
+    if (first) {
+        first = 0;
+
+        /* make exclusive-or pattern from polynomial (0xedb88320UL) */
+        poly = 0;
+        for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++)
+            poly |= (z_crc_t)1 << (31 - p[n]);
+
+        /* generate a crc for every 8-bit value */
+        for (n = 0; n < 256; n++) {
+            c = (z_crc_t)n;
+            for (k = 0; k < 8; k++)
+                c = c & 1 ? poly ^ (c >> 1) : c >> 1;
+            crc_table[0][n] = c;
+        }
+
+#ifdef BYFOUR
+        /* generate crc for each value followed by one, two, and three zeros,
+           and then the byte reversal of those as well as the first table */
+        for (n = 0; n < 256; n++) {
+            c = crc_table[0][n];
+            crc_table[4][n] = ZSWAP32(c);
+            for (k = 1; k < 4; k++) {
+                c = crc_table[0][c & 0xff] ^ (c >> 8);
+                crc_table[k][n] = c;
+                crc_table[k + 4][n] = ZSWAP32(c);
+            }
+        }
+#endif /* BYFOUR */
+
+        crc_table_empty = 0;
+    }
+    else {      /* not first */
+        /* wait for the other guy to finish (not efficient, but rare) */
+        while (crc_table_empty)
+            ;
+    }
+
+#ifdef MAKECRCH
+    /* write out CRC tables to crc32.h */
+    {
+        FILE *out;
+
+        out = fopen("crc32.h", "w");
+        if (out == NULL) return;
+        fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
+        fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
+        fprintf(out, "local const z_crc_t FAR ");
+        fprintf(out, "crc_table[TBLS][256] =\n{\n  {\n");
+        write_table(out, crc_table[0]);
+#  ifdef BYFOUR
+        fprintf(out, "#ifdef BYFOUR\n");
+        for (k = 1; k < 8; k++) {
+            fprintf(out, "  },\n  {\n");
+            write_table(out, crc_table[k]);
+        }
+        fprintf(out, "#endif\n");
+#  endif /* BYFOUR */
+        fprintf(out, "  }\n};\n");
+        fclose(out);
+    }
+#endif /* MAKECRCH */
+}
+
+#ifdef MAKECRCH
+local void write_table(out, table)
+    FILE *out;
+    const z_crc_t FAR *table;
+{
+    int n;
+
+    for (n = 0; n < 256; n++)
+        fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : "    ",
+                (unsigned long)(table[n]),
+                n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
+}
+#endif /* MAKECRCH */
+
+#else /* !DYNAMIC_CRC_TABLE */
+/* ========================================================================
+ * Tables of CRC-32s of all single-byte values, made by make_crc_table().
+ */
+#include "crc32.h"
+#endif /* DYNAMIC_CRC_TABLE */
+
+/* =========================================================================
+ * This function can be used by asm versions of crc32()
+ */
+const z_crc_t FAR * ZEXPORT get_crc_table()
+{
+#ifdef DYNAMIC_CRC_TABLE
+    if (crc_table_empty)
+        make_crc_table();
+#endif /* DYNAMIC_CRC_TABLE */
+    return (const z_crc_t FAR *)crc_table;
+}
+
+/* ========================================================================= */
+#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
+#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
+
+/* ========================================================================= */
+unsigned long ZEXPORT crc32_z(crc, buf, len)
+    unsigned long crc;
+    const unsigned char FAR *buf;
+    z_size_t len;
+{
+    if (buf == Z_NULL) return 0UL;
+
+#ifdef DYNAMIC_CRC_TABLE
+    if (crc_table_empty)
+        make_crc_table();
+#endif /* DYNAMIC_CRC_TABLE */
+
+#ifdef BYFOUR
+    if (sizeof(void *) == sizeof(ptrdiff_t)) {
+        z_crc_t endian;
+
+        endian = 1;
+        if (*((unsigned char *)(&endian)))
+            return crc32_little(crc, buf, len);
+        else
+            return crc32_big(crc, buf, len);
+    }
+#endif /* BYFOUR */
+    crc = crc ^ 0xffffffffUL;
+    while (len >= 8) {
+        DO8;
+        len -= 8;
+    }
+    if (len) do {
+        DO1;
+    } while (--len);
+    return crc ^ 0xffffffffUL;
+}
+
+/* ========================================================================= */
+unsigned long ZEXPORT crc32(crc, buf, len)
+    unsigned long crc;
+    const unsigned char FAR *buf;
+    uInt len;
+{
+    return crc32_z(crc, buf, len);
+}
+
+#ifdef BYFOUR
+
+/*
+   This BYFOUR code accesses the passed unsigned char * buffer with a 32-bit
+   integer pointer type. This violates the strict aliasing rule, where a
+   compiler can assume, for optimization purposes, that two pointers to
+   fundamentally different types won't ever point to the same memory. This can
+   manifest as a problem only if one of the pointers is written to. This code
+   only reads from those pointers. So long as this code remains isolated in
+   this compilation unit, there won't be a problem. For this reason, this code
+   should not be copied and pasted into a compilation unit in which other code
+   writes to the buffer that is passed to these routines.
+ */
+
+/* ========================================================================= */
+#define DOLIT4 c ^= *buf4++; \
+        c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
+            crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
+#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
+
+/* ========================================================================= */
+local unsigned long crc32_little(crc, buf, len)
+    unsigned long crc;
+    const unsigned char FAR *buf;
+    z_size_t len;
+{
+    register z_crc_t c;
+    register const z_crc_t FAR *buf4;
+
+    c = (z_crc_t)crc;
+    c = ~c;
+    while (len && ((ptrdiff_t)buf & 3)) {
+        c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
+        len--;
+    }
+
+    buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
+    while (len >= 32) {
+        DOLIT32;
+        len -= 32;
+    }
+    while (len >= 4) {
+        DOLIT4;
+        len -= 4;
+    }
+    buf = (const unsigned char FAR *)buf4;
+
+    if (len) do {
+        c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
+    } while (--len);
+    c = ~c;
+    return (unsigned long)c;
+}
+
+/* ========================================================================= */
+#define DOBIG4 c ^= *buf4++; \
+        c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
+            crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
+#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
+
+/* ========================================================================= */
+local unsigned long crc32_big(crc, buf, len)
+    unsigned long crc;
+    const unsigned char FAR *buf;
+    z_size_t len;
+{
+    register z_crc_t c;
+    register const z_crc_t FAR *buf4;
+
+    c = ZSWAP32((z_crc_t)crc);
+    c = ~c;
+    while (len && ((ptrdiff_t)buf & 3)) {
+        c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
+        len--;
+    }
+
+    buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
+    while (len >= 32) {
+        DOBIG32;
+        len -= 32;
+    }
+    while (len >= 4) {
+        DOBIG4;
+        len -= 4;
+    }
+    buf = (const unsigned char FAR *)buf4;
+
+    if (len) do {
+        c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
+    } while (--len);
+    c = ~c;
+    return (unsigned long)(ZSWAP32(c));
+}
+
+#endif /* BYFOUR */
+
+#define GF2_DIM 32      /* dimension of GF(2) vectors (length of CRC) */
+
+/* ========================================================================= */
+local unsigned long gf2_matrix_times(mat, vec)
+    unsigned long *mat;
+    unsigned long vec;
+{
+    unsigned long sum;
+
+    sum = 0;
+    while (vec) {
+        if (vec & 1)
+            sum ^= *mat;
+        vec >>= 1;
+        mat++;
+    }
+    return sum;
+}
+
+/* ========================================================================= */
+local void gf2_matrix_square(square, mat)
+    unsigned long *square;
+    unsigned long *mat;
+{
+    int n;
+
+    for (n = 0; n < GF2_DIM; n++)
+        square[n] = gf2_matrix_times(mat, mat[n]);
+}
+
+/* ========================================================================= */
+local uLong crc32_combine_(crc1, crc2, len2)
+    uLong crc1;
+    uLong crc2;
+    z_off64_t len2;
+{
+    int n;
+    unsigned long row;
+    unsigned long even[GF2_DIM];    /* even-power-of-two zeros operator */
+    unsigned long odd[GF2_DIM];     /* odd-power-of-two zeros operator */
+
+    /* degenerate case (also disallow negative lengths) */
+    if (len2 <= 0)
+        return crc1;
+
+    /* put operator for one zero bit in odd */
+    odd[0] = 0xedb88320UL;          /* CRC-32 polynomial */
+    row = 1;
+    for (n = 1; n < GF2_DIM; n++) {
+        odd[n] = row;
+        row <<= 1;
+    }
+
+    /* put operator for two zero bits in even */
+    gf2_matrix_square(even, odd);
+
+    /* put operator for four zero bits in odd */
+    gf2_matrix_square(odd, even);
+
+    /* apply len2 zeros to crc1 (first square will put the operator for one
+       zero byte, eight zero bits, in even) */
+    do {
+        /* apply zeros operator for this bit of len2 */
+        gf2_matrix_square(even, odd);
+        if (len2 & 1)
+            crc1 = gf2_matrix_times(even, crc1);
+        len2 >>= 1;
+
+        /* if no more bits set, then done */
+        if (len2 == 0)
+            break;
+
+        /* another iteration of the loop with odd and even swapped */
+        gf2_matrix_square(odd, even);
+        if (len2 & 1)
+            crc1 = gf2_matrix_times(odd, crc1);
+        len2 >>= 1;
+
+        /* if no more bits set, then done */
+    } while (len2 != 0);
+
+    /* return combined crc */
+    crc1 ^= crc2;
+    return crc1;
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine(crc1, crc2, len2)
+    uLong crc1;
+    uLong crc2;
+    z_off_t len2;
+{
+    return crc32_combine_(crc1, crc2, len2);
+}
+
+uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
+    uLong crc1;
+    uLong crc2;
+    z_off64_t len2;
+{
+    return crc32_combine_(crc1, crc2, len2);
+}
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/src/crc32.h
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/src/crc32.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/src/crc32.h	(revision 453)
@@ -0,0 +1,441 @@
+/* crc32.h -- tables for rapid CRC calculation
+ * Generated automatically by crc32.c
+ */
+
+local const z_crc_t FAR crc_table[TBLS][256] =
+{
+  {
+    0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
+    0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
+    0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
+    0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
+    0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
+    0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
+    0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
+    0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
+    0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
+    0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
+    0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
+    0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
+    0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
+    0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
+    0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
+    0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
+    0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
+    0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
+    0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
+    0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
+    0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
+    0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
+    0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
+    0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
+    0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
+    0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
+    0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
+    0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
+    0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
+    0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
+    0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
+    0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
+    0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
+    0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
+    0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
+    0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
+    0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
+    0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
+    0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
+    0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
+    0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
+    0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
+    0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
+    0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
+    0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
+    0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
+    0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
+    0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
+    0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
+    0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
+    0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
+    0x2d02ef8dUL
+#ifdef BYFOUR
+  },
+  {
+    0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
+    0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
+    0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
+    0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
+    0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
+    0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
+    0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
+    0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
+    0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
+    0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
+    0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
+    0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
+    0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
+    0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
+    0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
+    0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
+    0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
+    0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
+    0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
+    0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
+    0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
+    0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
+    0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
+    0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
+    0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
+    0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
+    0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
+    0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
+    0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
+    0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
+    0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
+    0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
+    0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
+    0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
+    0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
+    0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
+    0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
+    0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
+    0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
+    0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
+    0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
+    0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
+    0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
+    0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
+    0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
+    0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
+    0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
+    0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
+    0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
+    0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
+    0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
+    0x9324fd72UL
+  },
+  {
+    0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
+    0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
+    0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
+    0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
+    0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
+    0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
+    0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
+    0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
+    0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
+    0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
+    0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
+    0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
+    0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
+    0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
+    0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
+    0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
+    0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
+    0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
+    0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
+    0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
+    0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
+    0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
+    0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
+    0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
+    0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
+    0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
+    0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
+    0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
+    0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
+    0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
+    0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
+    0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
+    0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
+    0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
+    0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
+    0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
+    0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
+    0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
+    0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
+    0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
+    0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
+    0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
+    0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
+    0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
+    0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
+    0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
+    0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
+    0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
+    0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
+    0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
+    0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
+    0xbe9834edUL
+  },
+  {
+    0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
+    0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
+    0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
+    0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
+    0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
+    0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
+    0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
+    0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
+    0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
+    0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
+    0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
+    0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
+    0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
+    0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
+    0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
+    0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
+    0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
+    0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
+    0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
+    0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
+    0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
+    0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
+    0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
+    0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
+    0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
+    0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
+    0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
+    0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
+    0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
+    0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
+    0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
+    0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
+    0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
+    0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
+    0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
+    0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
+    0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
+    0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
+    0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
+    0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
+    0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
+    0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
+    0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
+    0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
+    0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
+    0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
+    0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
+    0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
+    0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
+    0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
+    0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
+    0xde0506f1UL
+  },
+  {
+    0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
+    0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
+    0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
+    0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
+    0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
+    0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
+    0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
+    0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
+    0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
+    0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
+    0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
+    0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
+    0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
+    0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
+    0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
+    0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
+    0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
+    0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
+    0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
+    0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
+    0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
+    0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
+    0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
+    0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
+    0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
+    0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
+    0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
+    0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
+    0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
+    0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
+    0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
+    0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
+    0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
+    0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
+    0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
+    0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
+    0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
+    0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
+    0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
+    0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
+    0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
+    0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
+    0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
+    0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
+    0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
+    0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
+    0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
+    0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
+    0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
+    0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
+    0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
+    0x8def022dUL
+  },
+  {
+    0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
+    0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
+    0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
+    0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
+    0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
+    0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
+    0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
+    0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
+    0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
+    0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
+    0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
+    0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
+    0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
+    0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
+    0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
+    0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
+    0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
+    0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
+    0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
+    0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
+    0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
+    0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
+    0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
+    0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
+    0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
+    0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
+    0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
+    0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
+    0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
+    0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
+    0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
+    0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
+    0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
+    0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
+    0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
+    0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
+    0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
+    0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
+    0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
+    0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
+    0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
+    0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
+    0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
+    0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
+    0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
+    0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
+    0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
+    0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
+    0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
+    0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
+    0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
+    0x72fd2493UL
+  },
+  {
+    0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
+    0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
+    0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
+    0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
+    0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
+    0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
+    0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
+    0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
+    0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
+    0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
+    0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
+    0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
+    0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
+    0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
+    0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
+    0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
+    0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
+    0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
+    0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
+    0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
+    0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
+    0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
+    0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
+    0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
+    0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
+    0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
+    0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
+    0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
+    0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
+    0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
+    0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
+    0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
+    0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
+    0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
+    0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
+    0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
+    0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
+    0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
+    0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
+    0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
+    0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
+    0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
+    0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
+    0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
+    0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
+    0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
+    0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
+    0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
+    0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
+    0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
+    0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
+    0xed3498beUL
+  },
+  {
+    0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
+    0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
+    0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
+    0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
+    0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
+    0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
+    0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
+    0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
+    0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
+    0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
+    0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
+    0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
+    0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
+    0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
+    0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
+    0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
+    0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
+    0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
+    0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
+    0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
+    0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
+    0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
+    0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
+    0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
+    0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
+    0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
+    0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
+    0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
+    0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
+    0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
+    0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
+    0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
+    0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
+    0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
+    0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
+    0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
+    0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
+    0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
+    0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
+    0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
+    0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
+    0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
+    0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
+    0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
+    0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
+    0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
+    0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
+    0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
+    0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
+    0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
+    0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
+    0xf10605deUL
+#endif
+  }
+};
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/src/deflate.c
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/src/deflate.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/src/deflate.c	(revision 453)
@@ -0,0 +1,2163 @@
+/* deflate.c -- compress data using the deflation algorithm
+ * Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ *  ALGORITHM
+ *
+ *      The "deflation" process depends on being able to identify portions
+ *      of the input text which are identical to earlier input (within a
+ *      sliding window trailing behind the input currently being processed).
+ *
+ *      The most straightforward technique turns out to be the fastest for
+ *      most input files: try all possible matches and select the longest.
+ *      The key feature of this algorithm is that insertions into the string
+ *      dictionary are very simple and thus fast, and deletions are avoided
+ *      completely. Insertions are performed at each input character, whereas
+ *      string matches are performed only when the previous match ends. So it
+ *      is preferable to spend more time in matches to allow very fast string
+ *      insertions and avoid deletions. The matching algorithm for small
+ *      strings is inspired from that of Rabin & Karp. A brute force approach
+ *      is used to find longer strings when a small match has been found.
+ *      A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
+ *      (by Leonid Broukhis).
+ *         A previous version of this file used a more sophisticated algorithm
+ *      (by Fiala and Greene) which is guaranteed to run in linear amortized
+ *      time, but has a larger average cost, uses more memory and is patented.
+ *      However the F&G algorithm may be faster for some highly redundant
+ *      files if the parameter max_chain_length (described below) is too large.
+ *
+ *  ACKNOWLEDGEMENTS
+ *
+ *      The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
+ *      I found it in 'freeze' written by Leonid Broukhis.
+ *      Thanks to many people for bug reports and testing.
+ *
+ *  REFERENCES
+ *
+ *      Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
+ *      Available in http://tools.ietf.org/html/rfc1951
+ *
+ *      A description of the Rabin and Karp algorithm is given in the book
+ *         "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
+ *
+ *      Fiala,E.R., and Greene,D.H.
+ *         Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
+ *
+ */
+
+/* @(#) $Id$ */
+
+#include "deflate.h"
+
+const char deflate_copyright[] =
+   " deflate 1.2.11 Copyright 1995-2017 Jean-loup Gailly and Mark Adler ";
+/*
+  If you use the zlib library in a product, an acknowledgment is welcome
+  in the documentation of your product. If for some reason you cannot
+  include such an acknowledgment, I would appreciate that you keep this
+  copyright string in the executable of your product.
+ */
+
+/* ===========================================================================
+ *  Function prototypes.
+ */
+typedef enum {
+    need_more,      /* block not completed, need more input or more output */
+    block_done,     /* block flush performed */
+    finish_started, /* finish started, need only more output at next deflate */
+    finish_done     /* finish done, accept no more input or output */
+} block_state;
+
+typedef block_state (*compress_func) OF((deflate_state *s, int flush));
+/* Compression function. Returns the block state after the call. */
+
+local int deflateStateCheck      OF((z_streamp strm));
+local void slide_hash     OF((deflate_state *s));
+local void fill_window    OF((deflate_state *s));
+local block_state deflate_stored OF((deflate_state *s, int flush));
+local block_state deflate_fast   OF((deflate_state *s, int flush));
+#ifndef FASTEST
+local block_state deflate_slow   OF((deflate_state *s, int flush));
+#endif
+local block_state deflate_rle    OF((deflate_state *s, int flush));
+local block_state deflate_huff   OF((deflate_state *s, int flush));
+local void lm_init        OF((deflate_state *s));
+local void putShortMSB    OF((deflate_state *s, uInt b));
+local void flush_pending  OF((z_streamp strm));
+local unsigned read_buf   OF((z_streamp strm, Bytef *buf, unsigned size));
+#ifdef ASMV
+#  pragma message("Assembler code may have bugs -- use at your own risk")
+      void match_init OF((void)); /* asm code initialization */
+      uInt longest_match  OF((deflate_state *s, IPos cur_match));
+#else
+local uInt longest_match  OF((deflate_state *s, IPos cur_match));
+#endif
+
+#ifdef ZLIB_DEBUG
+local  void check_match OF((deflate_state *s, IPos start, IPos match,
+                            int length));
+#endif
+
+/* ===========================================================================
+ * Local data
+ */
+
+#define NIL 0
+/* Tail of hash chains */
+
+#ifndef TOO_FAR
+#  define TOO_FAR 4096
+#endif
+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+typedef struct config_s {
+   ush good_length; /* reduce lazy search above this match length */
+   ush max_lazy;    /* do not perform lazy search above this match length */
+   ush nice_length; /* quit search above this match length */
+   ush max_chain;
+   compress_func func;
+} config;
+
+#ifdef FASTEST
+local const config configuration_table[2] = {
+/*      good lazy nice chain */
+/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */
+/* 1 */ {4,    4,  8,    4, deflate_fast}}; /* max speed, no lazy matches */
+#else
+local const config configuration_table[10] = {
+/*      good lazy nice chain */
+/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */
+/* 1 */ {4,    4,  8,    4, deflate_fast}, /* max speed, no lazy matches */
+/* 2 */ {4,    5, 16,    8, deflate_fast},
+/* 3 */ {4,    6, 32,   32, deflate_fast},
+
+/* 4 */ {4,    4, 16,   16, deflate_slow},  /* lazy matches */
+/* 5 */ {8,   16, 32,   32, deflate_slow},
+/* 6 */ {8,   16, 128, 128, deflate_slow},
+/* 7 */ {8,   32, 128, 256, deflate_slow},
+/* 8 */ {32, 128, 258, 1024, deflate_slow},
+/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */
+#endif
+
+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
+ * meaning.
+ */
+
+/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */
+#define RANK(f) (((f) * 2) - ((f) > 4 ? 9 : 0))
+
+/* ===========================================================================
+ * Update a hash value with the given input byte
+ * IN  assertion: all calls to UPDATE_HASH are made with consecutive input
+ *    characters, so that a running hash key can be computed from the previous
+ *    key instead of complete recalculation each time.
+ */
+#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
+
+
+/* ===========================================================================
+ * Insert string str in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * If this file is compiled with -DFASTEST, the compression level is forced
+ * to 1, and no hash chains are maintained.
+ * IN  assertion: all calls to INSERT_STRING are made with consecutive input
+ *    characters and the first MIN_MATCH bytes of str are valid (except for
+ *    the last MIN_MATCH-1 bytes of the input file).
+ */
+#ifdef FASTEST
+#define INSERT_STRING(s, str, match_head) \
+   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+    match_head = s->head[s->ins_h], \
+    s->head[s->ins_h] = (Pos)(str))
+#else
+#define INSERT_STRING(s, str, match_head) \
+   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+    match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \
+    s->head[s->ins_h] = (Pos)(str))
+#endif
+
+/* ===========================================================================
+ * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
+ * prev[] will be initialized on the fly.
+ */
+#define CLEAR_HASH(s) \
+    s->head[s->hash_size-1] = NIL; \
+    zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
+
+/* ===========================================================================
+ * Slide the hash table when sliding the window down (could be avoided with 32
+ * bit values at the expense of memory usage). We slide even when level == 0 to
+ * keep the hash table consistent if we switch back to level > 0 later.
+ */
+local void slide_hash(s)
+    deflate_state *s;
+{
+    unsigned n, m;
+    Posf *p;
+    uInt wsize = s->w_size;
+
+    n = s->hash_size;
+    p = &s->head[n];
+    do {
+        m = *--p;
+        *p = (Pos)(m >= wsize ? m - wsize : NIL);
+    } while (--n);
+    n = wsize;
+#ifndef FASTEST
+    p = &s->prev[n];
+    do {
+        m = *--p;
+        *p = (Pos)(m >= wsize ? m - wsize : NIL);
+        /* If n is not on any hash chain, prev[n] is garbage but
+         * its value will never be used.
+         */
+    } while (--n);
+#endif
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateInit_(strm, level, version, stream_size)
+    z_streamp strm;
+    int level;
+    const char *version;
+    int stream_size;
+{
+    return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
+                         Z_DEFAULT_STRATEGY, version, stream_size);
+    /* To do: ignore strm->next_in if we use it as window */
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
+                  version, stream_size)
+    z_streamp strm;
+    int  level;
+    int  method;
+    int  windowBits;
+    int  memLevel;
+    int  strategy;
+    const char *version;
+    int stream_size;
+{
+    deflate_state *s;
+    int wrap = 1;
+    static const char my_version[] = ZLIB_VERSION;
+
+    ushf *overlay;
+    /* We overlay pending_buf and d_buf+l_buf. This works since the average
+     * output size for (length,distance) codes is <= 24 bits.
+     */
+
+    if (version == Z_NULL || version[0] != my_version[0] ||
+        stream_size != sizeof(z_stream)) {
+        return Z_VERSION_ERROR;
+    }
+    if (strm == Z_NULL) return Z_STREAM_ERROR;
+
+    strm->msg = Z_NULL;
+    if (strm->zalloc == (alloc_func)0) {
+#ifdef Z_SOLO
+        return Z_STREAM_ERROR;
+#else
+        strm->zalloc = zcalloc;
+        strm->opaque = (voidpf)0;
+#endif
+    }
+    if (strm->zfree == (free_func)0)
+#ifdef Z_SOLO
+        return Z_STREAM_ERROR;
+#else
+        strm->zfree = zcfree;
+#endif
+
+#ifdef FASTEST
+    if (level != 0) level = 1;
+#else
+    if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+
+    if (windowBits < 0) { /* suppress zlib wrapper */
+        wrap = 0;
+        windowBits = -windowBits;
+    }
+#ifdef GZIP
+    else if (windowBits > 15) {
+        wrap = 2;       /* write gzip wrapper instead */
+        windowBits -= 16;
+    }
+#endif
+    if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
+        windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
+        strategy < 0 || strategy > Z_FIXED || (windowBits == 8 && wrap != 1)) {
+        return Z_STREAM_ERROR;
+    }
+    if (windowBits == 8) windowBits = 9;  /* until 256-byte window bug fixed */
+    s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
+    if (s == Z_NULL) return Z_MEM_ERROR;
+    strm->state = (struct internal_state FAR *)s;
+    s->strm = strm;
+    s->status = INIT_STATE;     /* to pass state test in deflateReset() */
+
+    s->wrap = wrap;
+    s->gzhead = Z_NULL;
+    s->w_bits = (uInt)windowBits;
+    s->w_size = 1 << s->w_bits;
+    s->w_mask = s->w_size - 1;
+
+    s->hash_bits = (uInt)memLevel + 7;
+    s->hash_size = 1 << s->hash_bits;
+    s->hash_mask = s->hash_size - 1;
+    s->hash_shift =  ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
+
+    s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
+    s->prev   = (Posf *)  ZALLOC(strm, s->w_size, sizeof(Pos));
+    s->head   = (Posf *)  ZALLOC(strm, s->hash_size, sizeof(Pos));
+
+    s->high_water = 0;      /* nothing written to s->window yet */
+
+    s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
+
+    overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
+    s->pending_buf = (uchf *) overlay;
+    s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
+
+    if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
+        s->pending_buf == Z_NULL) {
+        s->status = FINISH_STATE;
+        strm->msg = ERR_MSG(Z_MEM_ERROR);
+        deflateEnd (strm);
+        return Z_MEM_ERROR;
+    }
+    s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
+    s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
+
+    s->level = level;
+    s->strategy = strategy;
+    s->method = (Byte)method;
+
+    return deflateReset(strm);
+}
+
+/* =========================================================================
+ * Check for a valid deflate stream state. Return 0 if ok, 1 if not.
+ */
+local int deflateStateCheck (strm)
+    z_streamp strm;
+{
+    deflate_state *s;
+    if (strm == Z_NULL ||
+        strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)
+        return 1;
+    s = strm->state;
+    if (s == Z_NULL || s->strm != strm || (s->status != INIT_STATE &&
+#ifdef GZIP
+                                           s->status != GZIP_STATE &&
+#endif
+                                           s->status != EXTRA_STATE &&
+                                           s->status != NAME_STATE &&
+                                           s->status != COMMENT_STATE &&
+                                           s->status != HCRC_STATE &&
+                                           s->status != BUSY_STATE &&
+                                           s->status != FINISH_STATE))
+        return 1;
+    return 0;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
+    z_streamp strm;
+    const Bytef *dictionary;
+    uInt  dictLength;
+{
+    deflate_state *s;
+    uInt str, n;
+    int wrap;
+    unsigned avail;
+    z_const unsigned char *next;
+
+    if (deflateStateCheck(strm) || dictionary == Z_NULL)
+        return Z_STREAM_ERROR;
+    s = strm->state;
+    wrap = s->wrap;
+    if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead)
+        return Z_STREAM_ERROR;
+
+    /* when using zlib wrappers, compute Adler-32 for provided dictionary */
+    if (wrap == 1)
+        strm->adler = adler32(strm->adler, dictionary, dictLength);
+    s->wrap = 0;                    /* avoid computing Adler-32 in read_buf */
+
+    /* if dictionary would fill window, just replace the history */
+    if (dictLength >= s->w_size) {
+        if (wrap == 0) {            /* already empty otherwise */
+            CLEAR_HASH(s);
+            s->strstart = 0;
+            s->block_start = 0L;
+            s->insert = 0;
+        }
+        dictionary += dictLength - s->w_size;  /* use the tail */
+        dictLength = s->w_size;
+    }
+
+    /* insert dictionary into window and hash */
+    avail = strm->avail_in;
+    next = strm->next_in;
+    strm->avail_in = dictLength;
+    strm->next_in = (z_const Bytef *)dictionary;
+    fill_window(s);
+    while (s->lookahead >= MIN_MATCH) {
+        str = s->strstart;
+        n = s->lookahead - (MIN_MATCH-1);
+        do {
+            UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);
+#ifndef FASTEST
+            s->prev[str & s->w_mask] = s->head[s->ins_h];
+#endif
+            s->head[s->ins_h] = (Pos)str;
+            str++;
+        } while (--n);
+        s->strstart = str;
+        s->lookahead = MIN_MATCH-1;
+        fill_window(s);
+    }
+    s->strstart += s->lookahead;
+    s->block_start = (long)s->strstart;
+    s->insert = s->lookahead;
+    s->lookahead = 0;
+    s->match_length = s->prev_length = MIN_MATCH-1;
+    s->match_available = 0;
+    strm->next_in = next;
+    strm->avail_in = avail;
+    s->wrap = wrap;
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateGetDictionary (strm, dictionary, dictLength)
+    z_streamp strm;
+    Bytef *dictionary;
+    uInt  *dictLength;
+{
+    deflate_state *s;
+    uInt len;
+
+    if (deflateStateCheck(strm))
+        return Z_STREAM_ERROR;
+    s = strm->state;
+    len = s->strstart + s->lookahead;
+    if (len > s->w_size)
+        len = s->w_size;
+    if (dictionary != Z_NULL && len)
+        zmemcpy(dictionary, s->window + s->strstart + s->lookahead - len, len);
+    if (dictLength != Z_NULL)
+        *dictLength = len;
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateResetKeep (strm)
+    z_streamp strm;
+{
+    deflate_state *s;
+
+    if (deflateStateCheck(strm)) {
+        return Z_STREAM_ERROR;
+    }
+
+    strm->total_in = strm->total_out = 0;
+    strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
+    strm->data_type = Z_UNKNOWN;
+
+    s = (deflate_state *)strm->state;
+    s->pending = 0;
+    s->pending_out = s->pending_buf;
+
+    if (s->wrap < 0) {
+        s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */
+    }
+    s->status =
+#ifdef GZIP
+        s->wrap == 2 ? GZIP_STATE :
+#endif
+        s->wrap ? INIT_STATE : BUSY_STATE;
+    strm->adler =
+#ifdef GZIP
+        s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
+#endif
+        adler32(0L, Z_NULL, 0);
+    s->last_flush = Z_NO_FLUSH;
+
+    _tr_init(s);
+
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateReset (strm)
+    z_streamp strm;
+{
+    int ret;
+
+    ret = deflateResetKeep(strm);
+    if (ret == Z_OK)
+        lm_init(strm->state);
+    return ret;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetHeader (strm, head)
+    z_streamp strm;
+    gz_headerp head;
+{
+    if (deflateStateCheck(strm) || strm->state->wrap != 2)
+        return Z_STREAM_ERROR;
+    strm->state->gzhead = head;
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflatePending (strm, pending, bits)
+    unsigned *pending;
+    int *bits;
+    z_streamp strm;
+{
+    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
+    if (pending != Z_NULL)
+        *pending = strm->state->pending;
+    if (bits != Z_NULL)
+        *bits = strm->state->bi_valid;
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflatePrime (strm, bits, value)
+    z_streamp strm;
+    int bits;
+    int value;
+{
+    deflate_state *s;
+    int put;
+
+    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
+    s = strm->state;
+    if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3))
+        return Z_BUF_ERROR;
+    do {
+        put = Buf_size - s->bi_valid;
+        if (put > bits)
+            put = bits;
+        s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid);
+        s->bi_valid += put;
+        _tr_flush_bits(s);
+        value >>= put;
+        bits -= put;
+    } while (bits);
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateParams(strm, level, strategy)
+    z_streamp strm;
+    int level;
+    int strategy;
+{
+    deflate_state *s;
+    compress_func func;
+
+    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
+    s = strm->state;
+
+#ifdef FASTEST
+    if (level != 0) level = 1;
+#else
+    if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+    if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
+        return Z_STREAM_ERROR;
+    }
+    func = configuration_table[s->level].func;
+
+    if ((strategy != s->strategy || func != configuration_table[level].func) &&
+        s->high_water) {
+        /* Flush the last buffer: */
+        int err = deflate(strm, Z_BLOCK);
+        if (err == Z_STREAM_ERROR)
+            return err;
+        if (strm->avail_out == 0)
+            return Z_BUF_ERROR;
+    }
+    if (s->level != level) {
+        if (s->level == 0 && s->matches != 0) {
+            if (s->matches == 1)
+                slide_hash(s);
+            else
+                CLEAR_HASH(s);
+            s->matches = 0;
+        }
+        s->level = level;
+        s->max_lazy_match   = configuration_table[level].max_lazy;
+        s->good_match       = configuration_table[level].good_length;
+        s->nice_match       = configuration_table[level].nice_length;
+        s->max_chain_length = configuration_table[level].max_chain;
+    }
+    s->strategy = strategy;
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain)
+    z_streamp strm;
+    int good_length;
+    int max_lazy;
+    int nice_length;
+    int max_chain;
+{
+    deflate_state *s;
+
+    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
+    s = strm->state;
+    s->good_match = (uInt)good_length;
+    s->max_lazy_match = (uInt)max_lazy;
+    s->nice_match = nice_length;
+    s->max_chain_length = (uInt)max_chain;
+    return Z_OK;
+}
+
+/* =========================================================================
+ * For the default windowBits of 15 and memLevel of 8, this function returns
+ * a close to exact, as well as small, upper bound on the compressed size.
+ * They are coded as constants here for a reason--if the #define's are
+ * changed, then this function needs to be changed as well.  The return
+ * value for 15 and 8 only works for those exact settings.
+ *
+ * For any setting other than those defaults for windowBits and memLevel,
+ * the value returned is a conservative worst case for the maximum expansion
+ * resulting from using fixed blocks instead of stored blocks, which deflate
+ * can emit on compressed data for some combinations of the parameters.
+ *
+ * This function could be more sophisticated to provide closer upper bounds for
+ * every combination of windowBits and memLevel.  But even the conservative
+ * upper bound of about 14% expansion does not seem onerous for output buffer
+ * allocation.
+ */
+uLong ZEXPORT deflateBound(strm, sourceLen)
+    z_streamp strm;
+    uLong sourceLen;
+{
+    deflate_state *s;
+    uLong complen, wraplen;
+
+    /* conservative upper bound for compressed data */
+    complen = sourceLen +
+              ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5;
+
+    /* if can't get parameters, return conservative bound plus zlib wrapper */
+    if (deflateStateCheck(strm))
+        return complen + 6;
+
+    /* compute wrapper length */
+    s = strm->state;
+    switch (s->wrap) {
+    case 0:                                 /* raw deflate */
+        wraplen = 0;
+        break;
+    case 1:                                 /* zlib wrapper */
+        wraplen = 6 + (s->strstart ? 4 : 0);
+        break;
+#ifdef GZIP
+    case 2:                                 /* gzip wrapper */
+        wraplen = 18;
+        if (s->gzhead != Z_NULL) {          /* user-supplied gzip header */
+            Bytef *str;
+            if (s->gzhead->extra != Z_NULL)
+                wraplen += 2 + s->gzhead->extra_len;
+            str = s->gzhead->name;
+            if (str != Z_NULL)
+                do {
+                    wraplen++;
+                } while (*str++);
+            str = s->gzhead->comment;
+            if (str != Z_NULL)
+                do {
+                    wraplen++;
+                } while (*str++);
+            if (s->gzhead->hcrc)
+                wraplen += 2;
+        }
+        break;
+#endif
+    default:                                /* for compiler happiness */
+        wraplen = 6;
+    }
+
+    /* if not default parameters, return conservative bound */
+    if (s->w_bits != 15 || s->hash_bits != 8 + 7)
+        return complen + wraplen;
+
+    /* default settings: return tight bound for that case */
+    return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
+           (sourceLen >> 25) + 13 - 6 + wraplen;
+}
+
+/* =========================================================================
+ * Put a short in the pending buffer. The 16-bit value is put in MSB order.
+ * IN assertion: the stream state is correct and there is enough room in
+ * pending_buf.
+ */
+local void putShortMSB (s, b)
+    deflate_state *s;
+    uInt b;
+{
+    put_byte(s, (Byte)(b >> 8));
+    put_byte(s, (Byte)(b & 0xff));
+}
+
+/* =========================================================================
+ * Flush as much pending output as possible. All deflate() output, except for
+ * some deflate_stored() output, goes through this function so some
+ * applications may wish to modify it to avoid allocating a large
+ * strm->next_out buffer and copying into it. (See also read_buf()).
+ */
+local void flush_pending(strm)
+    z_streamp strm;
+{
+    unsigned len;
+    deflate_state *s = strm->state;
+
+    _tr_flush_bits(s);
+    len = s->pending;
+    if (len > strm->avail_out) len = strm->avail_out;
+    if (len == 0) return;
+
+    zmemcpy(strm->next_out, s->pending_out, len);
+    strm->next_out  += len;
+    s->pending_out  += len;
+    strm->total_out += len;
+    strm->avail_out -= len;
+    s->pending      -= len;
+    if (s->pending == 0) {
+        s->pending_out = s->pending_buf;
+    }
+}
+
+/* ===========================================================================
+ * Update the header CRC with the bytes s->pending_buf[beg..s->pending - 1].
+ */
+#define HCRC_UPDATE(beg) \
+    do { \
+        if (s->gzhead->hcrc && s->pending > (beg)) \
+            strm->adler = crc32(strm->adler, s->pending_buf + (beg), \
+                                s->pending - (beg)); \
+    } while (0)
+
+/* ========================================================================= */
+int ZEXPORT deflate (strm, flush)
+    z_streamp strm;
+    int flush;
+{
+    int old_flush; /* value of flush param for previous deflate call */
+    deflate_state *s;
+
+    if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) {
+        return Z_STREAM_ERROR;
+    }
+    s = strm->state;
+
+    if (strm->next_out == Z_NULL ||
+        (strm->avail_in != 0 && strm->next_in == Z_NULL) ||
+        (s->status == FINISH_STATE && flush != Z_FINISH)) {
+        ERR_RETURN(strm, Z_STREAM_ERROR);
+    }
+    if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
+
+    old_flush = s->last_flush;
+    s->last_flush = flush;
+
+    /* Flush as much pending output as possible */
+    if (s->pending != 0) {
+        flush_pending(strm);
+        if (strm->avail_out == 0) {
+            /* Since avail_out is 0, deflate will be called again with
+             * more output space, but possibly with both pending and
+             * avail_in equal to zero. There won't be anything to do,
+             * but this is not an error situation so make sure we
+             * return OK instead of BUF_ERROR at next call of deflate:
+             */
+            s->last_flush = -1;
+            return Z_OK;
+        }
+
+    /* Make sure there is something to do and avoid duplicate consecutive
+     * flushes. For repeated and useless calls with Z_FINISH, we keep
+     * returning Z_STREAM_END instead of Z_BUF_ERROR.
+     */
+    } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) &&
+               flush != Z_FINISH) {
+        ERR_RETURN(strm, Z_BUF_ERROR);
+    }
+
+    /* User must not provide more input after the first FINISH: */
+    if (s->status == FINISH_STATE && strm->avail_in != 0) {
+        ERR_RETURN(strm, Z_BUF_ERROR);
+    }
+
+    /* Write the header */
+    if (s->status == INIT_STATE) {
+        /* zlib header */
+        uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
+        uInt level_flags;
+
+        if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2)
+            level_flags = 0;
+        else if (s->level < 6)
+            level_flags = 1;
+        else if (s->level == 6)
+            level_flags = 2;
+        else
+            level_flags = 3;
+        header |= (level_flags << 6);
+        if (s->strstart != 0) header |= PRESET_DICT;
+        header += 31 - (header % 31);
+
+        putShortMSB(s, header);
+
+        /* Save the adler32 of the preset dictionary: */
+        if (s->strstart != 0) {
+            putShortMSB(s, (uInt)(strm->adler >> 16));
+            putShortMSB(s, (uInt)(strm->adler & 0xffff));
+        }
+        strm->adler = adler32(0L, Z_NULL, 0);
+        s->status = BUSY_STATE;
+
+        /* Compression must start with an empty pending buffer */
+        flush_pending(strm);
+        if (s->pending != 0) {
+            s->last_flush = -1;
+            return Z_OK;
+        }
+    }
+#ifdef GZIP
+    if (s->status == GZIP_STATE) {
+        /* gzip header */
+        strm->adler = crc32(0L, Z_NULL, 0);
+        put_byte(s, 31);
+        put_byte(s, 139);
+        put_byte(s, 8);
+        if (s->gzhead == Z_NULL) {
+            put_byte(s, 0);
+            put_byte(s, 0);
+            put_byte(s, 0);
+            put_byte(s, 0);
+            put_byte(s, 0);
+            put_byte(s, s->level == 9 ? 2 :
+                     (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+                      4 : 0));
+            put_byte(s, OS_CODE);
+            s->status = BUSY_STATE;
+
+            /* Compression must start with an empty pending buffer */
+            flush_pending(strm);
+            if (s->pending != 0) {
+                s->last_flush = -1;
+                return Z_OK;
+            }
+        }
+        else {
+            put_byte(s, (s->gzhead->text ? 1 : 0) +
+                     (s->gzhead->hcrc ? 2 : 0) +
+                     (s->gzhead->extra == Z_NULL ? 0 : 4) +
+                     (s->gzhead->name == Z_NULL ? 0 : 8) +
+                     (s->gzhead->comment == Z_NULL ? 0 : 16)
+                     );
+            put_byte(s, (Byte)(s->gzhead->time & 0xff));
+            put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff));
+            put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff));
+            put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff));
+            put_byte(s, s->level == 9 ? 2 :
+                     (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+                      4 : 0));
+            put_byte(s, s->gzhead->os & 0xff);
+            if (s->gzhead->extra != Z_NULL) {
+                put_byte(s, s->gzhead->extra_len & 0xff);
+                put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);
+            }
+            if (s->gzhead->hcrc)
+                strm->adler = crc32(strm->adler, s->pending_buf,
+                                    s->pending);
+            s->gzindex = 0;
+            s->status = EXTRA_STATE;
+        }
+    }
+    if (s->status == EXTRA_STATE) {
+        if (s->gzhead->extra != Z_NULL) {
+            ulg beg = s->pending;   /* start of bytes to update crc */
+            uInt left = (s->gzhead->extra_len & 0xffff) - s->gzindex;
+            while (s->pending + left > s->pending_buf_size) {
+                uInt copy = s->pending_buf_size - s->pending;
+                zmemcpy(s->pending_buf + s->pending,
+                        s->gzhead->extra + s->gzindex, copy);
+                s->pending = s->pending_buf_size;
+                HCRC_UPDATE(beg);
+                s->gzindex += copy;
+                flush_pending(strm);
+                if (s->pending != 0) {
+                    s->last_flush = -1;
+                    return Z_OK;
+                }
+                beg = 0;
+                left -= copy;
+            }
+            zmemcpy(s->pending_buf + s->pending,
+                    s->gzhead->extra + s->gzindex, left);
+            s->pending += left;
+            HCRC_UPDATE(beg);
+            s->gzindex = 0;
+        }
+        s->status = NAME_STATE;
+    }
+    if (s->status == NAME_STATE) {
+        if (s->gzhead->name != Z_NULL) {
+            ulg beg = s->pending;   /* start of bytes to update crc */
+            int val;
+            do {
+                if (s->pending == s->pending_buf_size) {
+                    HCRC_UPDATE(beg);
+                    flush_pending(strm);
+                    if (s->pending != 0) {
+                        s->last_flush = -1;
+                        return Z_OK;
+                    }
+                    beg = 0;
+                }
+                val = s->gzhead->name[s->gzindex++];
+                put_byte(s, val);
+            } while (val != 0);
+            HCRC_UPDATE(beg);
+            s->gzindex = 0;
+        }
+        s->status = COMMENT_STATE;
+    }
+    if (s->status == COMMENT_STATE) {
+        if (s->gzhead->comment != Z_NULL) {
+            ulg beg = s->pending;   /* start of bytes to update crc */
+            int val;
+            do {
+                if (s->pending == s->pending_buf_size) {
+                    HCRC_UPDATE(beg);
+                    flush_pending(strm);
+                    if (s->pending != 0) {
+                        s->last_flush = -1;
+                        return Z_OK;
+                    }
+                    beg = 0;
+                }
+                val = s->gzhead->comment[s->gzindex++];
+                put_byte(s, val);
+            } while (val != 0);
+            HCRC_UPDATE(beg);
+        }
+        s->status = HCRC_STATE;
+    }
+    if (s->status == HCRC_STATE) {
+        if (s->gzhead->hcrc) {
+            if (s->pending + 2 > s->pending_buf_size) {
+                flush_pending(strm);
+                if (s->pending != 0) {
+                    s->last_flush = -1;
+                    return Z_OK;
+                }
+            }
+            put_byte(s, (Byte)(strm->adler & 0xff));
+            put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+            strm->adler = crc32(0L, Z_NULL, 0);
+        }
+        s->status = BUSY_STATE;
+
+        /* Compression must start with an empty pending buffer */
+        flush_pending(strm);
+        if (s->pending != 0) {
+            s->last_flush = -1;
+            return Z_OK;
+        }
+    }
+#endif
+
+    /* Start a new block or continue the current one.
+     */
+    if (strm->avail_in != 0 || s->lookahead != 0 ||
+        (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
+        block_state bstate;
+
+        bstate = s->level == 0 ? deflate_stored(s, flush) :
+                 s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) :
+                 s->strategy == Z_RLE ? deflate_rle(s, flush) :
+                 (*(configuration_table[s->level].func))(s, flush);
+
+        if (bstate == finish_started || bstate == finish_done) {
+            s->status = FINISH_STATE;
+        }
+        if (bstate == need_more || bstate == finish_started) {
+            if (strm->avail_out == 0) {
+                s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
+            }
+            return Z_OK;
+            /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
+             * of deflate should use the same flush parameter to make sure
+             * that the flush is complete. So we don't have to output an
+             * empty block here, this will be done at next call. This also
+             * ensures that for a very small output buffer, we emit at most
+             * one empty block.
+             */
+        }
+        if (bstate == block_done) {
+            if (flush == Z_PARTIAL_FLUSH) {
+                _tr_align(s);
+            } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */
+                _tr_stored_block(s, (char*)0, 0L, 0);
+                /* For a full flush, this empty block will be recognized
+                 * as a special marker by inflate_sync().
+                 */
+                if (flush == Z_FULL_FLUSH) {
+                    CLEAR_HASH(s);             /* forget history */
+                    if (s->lookahead == 0) {
+                        s->strstart = 0;
+                        s->block_start = 0L;
+                        s->insert = 0;
+                    }
+                }
+            }
+            flush_pending(strm);
+            if (strm->avail_out == 0) {
+              s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
+              return Z_OK;
+            }
+        }
+    }
+
+    if (flush != Z_FINISH) return Z_OK;
+    if (s->wrap <= 0) return Z_STREAM_END;
+
+    /* Write the trailer */
+#ifdef GZIP
+    if (s->wrap == 2) {
+        put_byte(s, (Byte)(strm->adler & 0xff));
+        put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+        put_byte(s, (Byte)((strm->adler >> 16) & 0xff));
+        put_byte(s, (Byte)((strm->adler >> 24) & 0xff));
+        put_byte(s, (Byte)(strm->total_in & 0xff));
+        put_byte(s, (Byte)((strm->total_in >> 8) & 0xff));
+        put_byte(s, (Byte)((strm->total_in >> 16) & 0xff));
+        put_byte(s, (Byte)((strm->total_in >> 24) & 0xff));
+    }
+    else
+#endif
+    {
+        putShortMSB(s, (uInt)(strm->adler >> 16));
+        putShortMSB(s, (uInt)(strm->adler & 0xffff));
+    }
+    flush_pending(strm);
+    /* If avail_out is zero, the application will call deflate again
+     * to flush the rest.
+     */
+    if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */
+    return s->pending != 0 ? Z_OK : Z_STREAM_END;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateEnd (strm)
+    z_streamp strm;
+{
+    int status;
+
+    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
+
+    status = strm->state->status;
+
+    /* Deallocate in reverse order of allocations: */
+    TRY_FREE(strm, strm->state->pending_buf);
+    TRY_FREE(strm, strm->state->head);
+    TRY_FREE(strm, strm->state->prev);
+    TRY_FREE(strm, strm->state->window);
+
+    ZFREE(strm, strm->state);
+    strm->state = Z_NULL;
+
+    return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
+}
+
+/* =========================================================================
+ * Copy the source state to the destination state.
+ * To simplify the source, this is not supported for 16-bit MSDOS (which
+ * doesn't have enough memory anyway to duplicate compression states).
+ */
+int ZEXPORT deflateCopy (dest, source)
+    z_streamp dest;
+    z_streamp source;
+{
+#ifdef MAXSEG_64K
+    return Z_STREAM_ERROR;
+#else
+    deflate_state *ds;
+    deflate_state *ss;
+    ushf *overlay;
+
+
+    if (deflateStateCheck(source) || dest == Z_NULL) {
+        return Z_STREAM_ERROR;
+    }
+
+    ss = source->state;
+
+    zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
+
+    ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
+    if (ds == Z_NULL) return Z_MEM_ERROR;
+    dest->state = (struct internal_state FAR *) ds;
+    zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state));
+    ds->strm = dest;
+
+    ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
+    ds->prev   = (Posf *)  ZALLOC(dest, ds->w_size, sizeof(Pos));
+    ds->head   = (Posf *)  ZALLOC(dest, ds->hash_size, sizeof(Pos));
+    overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
+    ds->pending_buf = (uchf *) overlay;
+
+    if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
+        ds->pending_buf == Z_NULL) {
+        deflateEnd (dest);
+        return Z_MEM_ERROR;
+    }
+    /* following zmemcpy do not work for 16-bit MSDOS */
+    zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
+    zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos));
+    zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos));
+    zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
+
+    ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
+    ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
+    ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
+
+    ds->l_desc.dyn_tree = ds->dyn_ltree;
+    ds->d_desc.dyn_tree = ds->dyn_dtree;
+    ds->bl_desc.dyn_tree = ds->bl_tree;
+
+    return Z_OK;
+#endif /* MAXSEG_64K */
+}
+
+/* ===========================================================================
+ * Read a new buffer from the current input stream, update the adler32
+ * and total number of bytes read.  All deflate() input goes through
+ * this function so some applications may wish to modify it to avoid
+ * allocating a large strm->next_in buffer and copying from it.
+ * (See also flush_pending()).
+ */
+local unsigned read_buf(strm, buf, size)
+    z_streamp strm;
+    Bytef *buf;
+    unsigned size;
+{
+    unsigned len = strm->avail_in;
+
+    if (len > size) len = size;
+    if (len == 0) return 0;
+
+    strm->avail_in  -= len;
+
+    zmemcpy(buf, strm->next_in, len);
+    if (strm->state->wrap == 1) {
+        strm->adler = adler32(strm->adler, buf, len);
+    }
+#ifdef GZIP
+    else if (strm->state->wrap == 2) {
+        strm->adler = crc32(strm->adler, buf, len);
+    }
+#endif
+    strm->next_in  += len;
+    strm->total_in += len;
+
+    return len;
+}
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new zlib stream
+ */
+local void lm_init (s)
+    deflate_state *s;
+{
+    s->window_size = (ulg)2L*s->w_size;
+
+    CLEAR_HASH(s);
+
+    /* Set the default configuration parameters:
+     */
+    s->max_lazy_match   = configuration_table[s->level].max_lazy;
+    s->good_match       = configuration_table[s->level].good_length;
+    s->nice_match       = configuration_table[s->level].nice_length;
+    s->max_chain_length = configuration_table[s->level].max_chain;
+
+    s->strstart = 0;
+    s->block_start = 0L;
+    s->lookahead = 0;
+    s->insert = 0;
+    s->match_length = s->prev_length = MIN_MATCH-1;
+    s->match_available = 0;
+    s->ins_h = 0;
+#ifndef FASTEST
+#ifdef ASMV
+    match_init(); /* initialize the asm code */
+#endif
+#endif
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ * OUT assertion: the match length is not greater than s->lookahead.
+ */
+#ifndef ASMV
+/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
+ * match.S. The code will be functionally equivalent.
+ */
+local uInt longest_match(s, cur_match)
+    deflate_state *s;
+    IPos cur_match;                             /* current match */
+{
+    unsigned chain_length = s->max_chain_length;/* max hash chain length */
+    register Bytef *scan = s->window + s->strstart; /* current string */
+    register Bytef *match;                      /* matched string */
+    register int len;                           /* length of current match */
+    int best_len = (int)s->prev_length;         /* best match length so far */
+    int nice_match = s->nice_match;             /* stop if match long enough */
+    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
+        s->strstart - (IPos)MAX_DIST(s) : NIL;
+    /* Stop when cur_match becomes <= limit. To simplify the code,
+     * we prevent matches with the string of window index 0.
+     */
+    Posf *prev = s->prev;
+    uInt wmask = s->w_mask;
+
+#ifdef UNALIGNED_OK
+    /* Compare two bytes at a time. Note: this is not always beneficial.
+     * Try with and without -DUNALIGNED_OK to check.
+     */
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
+    register ush scan_start = *(ushf*)scan;
+    register ush scan_end   = *(ushf*)(scan+best_len-1);
+#else
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+    register Byte scan_end1  = scan[best_len-1];
+    register Byte scan_end   = scan[best_len];
+#endif
+
+    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+     * It is easy to get rid of this optimization if necessary.
+     */
+    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+    /* Do not waste too much time if we already have a good match: */
+    if (s->prev_length >= s->good_match) {
+        chain_length >>= 2;
+    }
+    /* Do not look for matches beyond the end of the input. This is necessary
+     * to make deflate deterministic.
+     */
+    if ((uInt)nice_match > s->lookahead) nice_match = (int)s->lookahead;
+
+    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+    do {
+        Assert(cur_match < s->strstart, "no future");
+        match = s->window + cur_match;
+
+        /* Skip to next match if the match length cannot increase
+         * or if the match length is less than 2.  Note that the checks below
+         * for insufficient lookahead only occur occasionally for performance
+         * reasons.  Therefore uninitialized memory will be accessed, and
+         * conditional jumps will be made that depend on those values.
+         * However the length of the match is limited to the lookahead, so
+         * the output of deflate is not affected by the uninitialized values.
+         */
+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
+        /* This code assumes sizeof(unsigned short) == 2. Do not use
+         * UNALIGNED_OK if your compiler uses a different size.
+         */
+        if (*(ushf*)(match+best_len-1) != scan_end ||
+            *(ushf*)match != scan_start) continue;
+
+        /* It is not necessary to compare scan[2] and match[2] since they are
+         * always equal when the other bytes match, given that the hash keys
+         * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
+         * strstart+3, +5, ... up to strstart+257. We check for insufficient
+         * lookahead only every 4th comparison; the 128th check will be made
+         * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
+         * necessary to put more guard bytes at the end of the window, or
+         * to check more often for insufficient lookahead.
+         */
+        Assert(scan[2] == match[2], "scan[2]?");
+        scan++, match++;
+        do {
+        } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 scan < strend);
+        /* The funny "do {}" generates better code on most compilers */
+
+        /* Here, scan <= window+strstart+257 */
+        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+        if (*scan == *match) scan++;
+
+        len = (MAX_MATCH - 1) - (int)(strend-scan);
+        scan = strend - (MAX_MATCH-1);
+
+#else /* UNALIGNED_OK */
+
+        if (match[best_len]   != scan_end  ||
+            match[best_len-1] != scan_end1 ||
+            *match            != *scan     ||
+            *++match          != scan[1])      continue;
+
+        /* The check at best_len-1 can be removed because it will be made
+         * again later. (This heuristic is not always a win.)
+         * It is not necessary to compare scan[2] and match[2] since they
+         * are always equal when the other bytes match, given that
+         * the hash keys are equal and that HASH_BITS >= 8.
+         */
+        scan += 2, match++;
+        Assert(*scan == *match, "match[2]?");
+
+        /* We check for insufficient lookahead only every 8th comparison;
+         * the 256th check will be made at strstart+258.
+         */
+        do {
+        } while (*++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 scan < strend);
+
+        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+        len = MAX_MATCH - (int)(strend - scan);
+        scan = strend - MAX_MATCH;
+
+#endif /* UNALIGNED_OK */
+
+        if (len > best_len) {
+            s->match_start = cur_match;
+            best_len = len;
+            if (len >= nice_match) break;
+#ifdef UNALIGNED_OK
+            scan_end = *(ushf*)(scan+best_len-1);
+#else
+            scan_end1  = scan[best_len-1];
+            scan_end   = scan[best_len];
+#endif
+        }
+    } while ((cur_match = prev[cur_match & wmask]) > limit
+             && --chain_length != 0);
+
+    if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
+    return s->lookahead;
+}
+#endif /* ASMV */
+
+#else /* FASTEST */
+
+/* ---------------------------------------------------------------------------
+ * Optimized version for FASTEST only
+ */
+local uInt longest_match(s, cur_match)
+    deflate_state *s;
+    IPos cur_match;                             /* current match */
+{
+    register Bytef *scan = s->window + s->strstart; /* current string */
+    register Bytef *match;                       /* matched string */
+    register int len;                           /* length of current match */
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+
+    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+     * It is easy to get rid of this optimization if necessary.
+     */
+    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+    Assert(cur_match < s->strstart, "no future");
+
+    match = s->window + cur_match;
+
+    /* Return failure if the match length is less than 2:
+     */
+    if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;
+
+    /* The check at best_len-1 can be removed because it will be made
+     * again later. (This heuristic is not always a win.)
+     * It is not necessary to compare scan[2] and match[2] since they
+     * are always equal when the other bytes match, given that
+     * the hash keys are equal and that HASH_BITS >= 8.
+     */
+    scan += 2, match += 2;
+    Assert(*scan == *match, "match[2]?");
+
+    /* We check for insufficient lookahead only every 8th comparison;
+     * the 256th check will be made at strstart+258.
+     */
+    do {
+    } while (*++scan == *++match && *++scan == *++match &&
+             *++scan == *++match && *++scan == *++match &&
+             *++scan == *++match && *++scan == *++match &&
+             *++scan == *++match && *++scan == *++match &&
+             scan < strend);
+
+    Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+    len = MAX_MATCH - (int)(strend - scan);
+
+    if (len < MIN_MATCH) return MIN_MATCH - 1;
+
+    s->match_start = cur_match;
+    return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead;
+}
+
+#endif /* FASTEST */
+
+#ifdef ZLIB_DEBUG
+
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
+/* ===========================================================================
+ * Check that the match at match_start is indeed a match.
+ */
+local void check_match(s, start, match, length)
+    deflate_state *s;
+    IPos start, match;
+    int length;
+{
+    /* check that the match is indeed a match */
+    if (zmemcmp(s->window + match,
+                s->window + start, length) != EQUAL) {
+        fprintf(stderr, " start %u, match %u, length %d\n",
+                start, match, length);
+        do {
+            fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
+        } while (--length != 0);
+        z_error("invalid match");
+    }
+    if (z_verbose > 1) {
+        fprintf(stderr,"\\[%d,%d]", start-match, length);
+        do { putc(s->window[start++], stderr); } while (--length != 0);
+    }
+}
+#else
+#  define check_match(s, start, match, length)
+#endif /* ZLIB_DEBUG */
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead.
+ *
+ * IN assertion: lookahead < MIN_LOOKAHEAD
+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ *    At least one byte has been read, or avail_in == 0; reads are
+ *    performed for at least two bytes (required for the zip translate_eol
+ *    option -- not supported here).
+ */
+local void fill_window(s)
+    deflate_state *s;
+{
+    unsigned n;
+    unsigned more;    /* Amount of free space at the end of the window. */
+    uInt wsize = s->w_size;
+
+    Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead");
+
+    do {
+        more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
+
+        /* Deal with !@#$% 64K limit: */
+        if (sizeof(int) <= 2) {
+            if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
+                more = wsize;
+
+            } else if (more == (unsigned)(-1)) {
+                /* Very unlikely, but possible on 16 bit machine if
+                 * strstart == 0 && lookahead == 1 (input done a byte at time)
+                 */
+                more--;
+            }
+        }
+
+        /* If the window is almost full and there is insufficient lookahead,
+         * move the upper half to the lower one to make room in the upper half.
+         */
+        if (s->strstart >= wsize+MAX_DIST(s)) {
+
+            zmemcpy(s->window, s->window+wsize, (unsigned)wsize - more);
+            s->match_start -= wsize;
+            s->strstart    -= wsize; /* we now have strstart >= MAX_DIST */
+            s->block_start -= (long) wsize;
+            slide_hash(s);
+            more += wsize;
+        }
+        if (s->strm->avail_in == 0) break;
+
+        /* If there was no sliding:
+         *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+         *    more == window_size - lookahead - strstart
+         * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+         * => more >= window_size - 2*WSIZE + 2
+         * In the BIG_MEM or MMAP case (not yet supported),
+         *   window_size == input_size + MIN_LOOKAHEAD  &&
+         *   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+         * Otherwise, window_size == 2*WSIZE so more >= 2.
+         * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+         */
+        Assert(more >= 2, "more < 2");
+
+        n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
+        s->lookahead += n;
+
+        /* Initialize the hash value now that we have some input: */
+        if (s->lookahead + s->insert >= MIN_MATCH) {
+            uInt str = s->strstart - s->insert;
+            s->ins_h = s->window[str];
+            UPDATE_HASH(s, s->ins_h, s->window[str + 1]);
+#if MIN_MATCH != 3
+            Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+            while (s->insert) {
+                UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);
+#ifndef FASTEST
+                s->prev[str & s->w_mask] = s->head[s->ins_h];
+#endif
+                s->head[s->ins_h] = (Pos)str;
+                str++;
+                s->insert--;
+                if (s->lookahead + s->insert < MIN_MATCH)
+                    break;
+            }
+        }
+        /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+         * but this is not important since only literal bytes will be emitted.
+         */
+
+    } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
+
+    /* If the WIN_INIT bytes after the end of the current data have never been
+     * written, then zero those bytes in order to avoid memory check reports of
+     * the use of uninitialized (or uninitialised as Julian writes) bytes by
+     * the longest match routines.  Update the high water mark for the next
+     * time through here.  WIN_INIT is set to MAX_MATCH since the longest match
+     * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
+     */
+    if (s->high_water < s->window_size) {
+        ulg curr = s->strstart + (ulg)(s->lookahead);
+        ulg init;
+
+        if (s->high_water < curr) {
+            /* Previous high water mark below current data -- zero WIN_INIT
+             * bytes or up to end of window, whichever is less.
+             */
+            init = s->window_size - curr;
+            if (init > WIN_INIT)
+                init = WIN_INIT;
+            zmemzero(s->window + curr, (unsigned)init);
+            s->high_water = curr + init;
+        }
+        else if (s->high_water < (ulg)curr + WIN_INIT) {
+            /* High water mark at or above current data, but below current data
+             * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
+             * to end of window, whichever is less.
+             */
+            init = (ulg)curr + WIN_INIT - s->high_water;
+            if (init > s->window_size - s->high_water)
+                init = s->window_size - s->high_water;
+            zmemzero(s->window + s->high_water, (unsigned)init);
+            s->high_water += init;
+        }
+    }
+
+    Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
+           "not enough room for search");
+}
+
+/* ===========================================================================
+ * Flush the current block, with given end-of-file flag.
+ * IN assertion: strstart is set to the end of the current match.
+ */
+#define FLUSH_BLOCK_ONLY(s, last) { \
+   _tr_flush_block(s, (s->block_start >= 0L ? \
+                   (charf *)&s->window[(unsigned)s->block_start] : \
+                   (charf *)Z_NULL), \
+                (ulg)((long)s->strstart - s->block_start), \
+                (last)); \
+   s->block_start = s->strstart; \
+   flush_pending(s->strm); \
+   Tracev((stderr,"[FLUSH]")); \
+}
+
+/* Same but force premature exit if necessary. */
+#define FLUSH_BLOCK(s, last) { \
+   FLUSH_BLOCK_ONLY(s, last); \
+   if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \
+}
+
+/* Maximum stored block length in deflate format (not including header). */
+#define MAX_STORED 65535
+
+/* Minimum of a and b. */
+#define MIN(a, b) ((a) > (b) ? (b) : (a))
+
+/* ===========================================================================
+ * Copy without compression as much as possible from the input stream, return
+ * the current block state.
+ *
+ * In case deflateParams() is used to later switch to a non-zero compression
+ * level, s->matches (otherwise unused when storing) keeps track of the number
+ * of hash table slides to perform. If s->matches is 1, then one hash table
+ * slide will be done when switching. If s->matches is 2, the maximum value
+ * allowed here, then the hash table will be cleared, since two or more slides
+ * is the same as a clear.
+ *
+ * deflate_stored() is written to minimize the number of times an input byte is
+ * copied. It is most efficient with large input and output buffers, which
+ * maximizes the opportunites to have a single copy from next_in to next_out.
+ */
+local block_state deflate_stored(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    /* Smallest worthy block size when not flushing or finishing. By default
+     * this is 32K. This can be as small as 507 bytes for memLevel == 1. For
+     * large input and output buffers, the stored block size will be larger.
+     */
+    unsigned min_block = MIN(s->pending_buf_size - 5, s->w_size);
+
+    /* Copy as many min_block or larger stored blocks directly to next_out as
+     * possible. If flushing, copy the remaining available input to next_out as
+     * stored blocks, if there is enough space.
+     */
+    unsigned len, left, have, last = 0;
+    unsigned used = s->strm->avail_in;
+    do {
+        /* Set len to the maximum size block that we can copy directly with the
+         * available input data and output space. Set left to how much of that
+         * would be copied from what's left in the window.
+         */
+        len = MAX_STORED;       /* maximum deflate stored block length */
+        have = (s->bi_valid + 42) >> 3;         /* number of header bytes */
+        if (s->strm->avail_out < have)          /* need room for header */
+            break;
+            /* maximum stored block length that will fit in avail_out: */
+        have = s->strm->avail_out - have;
+        left = s->strstart - s->block_start;    /* bytes left in window */
+        if (len > (ulg)left + s->strm->avail_in)
+            len = left + s->strm->avail_in;     /* limit len to the input */
+        if (len > have)
+            len = have;                         /* limit len to the output */
+
+        /* If the stored block would be less than min_block in length, or if
+         * unable to copy all of the available input when flushing, then try
+         * copying to the window and the pending buffer instead. Also don't
+         * write an empty block when flushing -- deflate() does that.
+         */
+        if (len < min_block && ((len == 0 && flush != Z_FINISH) ||
+                                flush == Z_NO_FLUSH ||
+                                len != left + s->strm->avail_in))
+            break;
+
+        /* Make a dummy stored block in pending to get the header bytes,
+         * including any pending bits. This also updates the debugging counts.
+         */
+        last = flush == Z_FINISH && len == left + s->strm->avail_in ? 1 : 0;
+        _tr_stored_block(s, (char *)0, 0L, last);
+
+        /* Replace the lengths in the dummy stored block with len. */
+        s->pending_buf[s->pending - 4] = len;
+        s->pending_buf[s->pending - 3] = len >> 8;
+        s->pending_buf[s->pending - 2] = ~len;
+        s->pending_buf[s->pending - 1] = ~len >> 8;
+
+        /* Write the stored block header bytes. */
+        flush_pending(s->strm);
+
+#ifdef ZLIB_DEBUG
+        /* Update debugging counts for the data about to be copied. */
+        s->compressed_len += len << 3;
+        s->bits_sent += len << 3;
+#endif
+
+        /* Copy uncompressed bytes from the window to next_out. */
+        if (left) {
+            if (left > len)
+                left = len;
+            zmemcpy(s->strm->next_out, s->window + s->block_start, left);
+            s->strm->next_out += left;
+            s->strm->avail_out -= left;
+            s->strm->total_out += left;
+            s->block_start += left;
+            len -= left;
+        }
+
+        /* Copy uncompressed bytes directly from next_in to next_out, updating
+         * the check value.
+         */
+        if (len) {
+            read_buf(s->strm, s->strm->next_out, len);
+            s->strm->next_out += len;
+            s->strm->avail_out -= len;
+            s->strm->total_out += len;
+        }
+    } while (last == 0);
+
+    /* Update the sliding window with the last s->w_size bytes of the copied
+     * data, or append all of the copied data to the existing window if less
+     * than s->w_size bytes were copied. Also update the number of bytes to
+     * insert in the hash tables, in the event that deflateParams() switches to
+     * a non-zero compression level.
+     */
+    used -= s->strm->avail_in;      /* number of input bytes directly copied */
+    if (used) {
+        /* If any input was used, then no unused input remains in the window,
+         * therefore s->block_start == s->strstart.
+         */
+        if (used >= s->w_size) {    /* supplant the previous history */
+            s->matches = 2;         /* clear hash */
+            zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size);
+            s->strstart = s->w_size;
+        }
+        else {
+            if (s->window_size - s->strstart <= used) {
+                /* Slide the window down. */
+                s->strstart -= s->w_size;
+                zmemcpy(s->window, s->window + s->w_size, s->strstart);
+                if (s->matches < 2)
+                    s->matches++;   /* add a pending slide_hash() */
+            }
+            zmemcpy(s->window + s->strstart, s->strm->next_in - used, used);
+            s->strstart += used;
+        }
+        s->block_start = s->strstart;
+        s->insert += MIN(used, s->w_size - s->insert);
+    }
+    if (s->high_water < s->strstart)
+        s->high_water = s->strstart;
+
+    /* If the last block was written to next_out, then done. */
+    if (last)
+        return finish_done;
+
+    /* If flushing and all input has been consumed, then done. */
+    if (flush != Z_NO_FLUSH && flush != Z_FINISH &&
+        s->strm->avail_in == 0 && (long)s->strstart == s->block_start)
+        return block_done;
+
+    /* Fill the window with any remaining input. */
+    have = s->window_size - s->strstart - 1;
+    if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) {
+        /* Slide the window down. */
+        s->block_start -= s->w_size;
+        s->strstart -= s->w_size;
+        zmemcpy(s->window, s->window + s->w_size, s->strstart);
+        if (s->matches < 2)
+            s->matches++;           /* add a pending slide_hash() */
+        have += s->w_size;          /* more space now */
+    }
+    if (have > s->strm->avail_in)
+        have = s->strm->avail_in;
+    if (have) {
+        read_buf(s->strm, s->window + s->strstart, have);
+        s->strstart += have;
+    }
+    if (s->high_water < s->strstart)
+        s->high_water = s->strstart;
+
+    /* There was not enough avail_out to write a complete worthy or flushed
+     * stored block to next_out. Write a stored block to pending instead, if we
+     * have enough input for a worthy block, or if flushing and there is enough
+     * room for the remaining input as a stored block in the pending buffer.
+     */
+    have = (s->bi_valid + 42) >> 3;         /* number of header bytes */
+        /* maximum stored block length that will fit in pending: */
+    have = MIN(s->pending_buf_size - have, MAX_STORED);
+    min_block = MIN(have, s->w_size);
+    left = s->strstart - s->block_start;
+    if (left >= min_block ||
+        ((left || flush == Z_FINISH) && flush != Z_NO_FLUSH &&
+         s->strm->avail_in == 0 && left <= have)) {
+        len = MIN(left, have);
+        last = flush == Z_FINISH && s->strm->avail_in == 0 &&
+               len == left ? 1 : 0;
+        _tr_stored_block(s, (charf *)s->window + s->block_start, len, last);
+        s->block_start += len;
+        flush_pending(s->strm);
+    }
+
+    /* We've done all we can with the available input and output. */
+    return last ? finish_started : need_more;
+}
+
+/* ===========================================================================
+ * Compress as much as possible from the input stream, return the current
+ * block state.
+ * This function does not perform lazy evaluation of matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+local block_state deflate_fast(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    IPos hash_head;       /* head of the hash chain */
+    int bflush;           /* set if current block must be flushed */
+
+    for (;;) {
+        /* Make sure that we always have enough lookahead, except
+         * at the end of the input file. We need MAX_MATCH bytes
+         * for the next match, plus MIN_MATCH bytes to insert the
+         * string following the next match.
+         */
+        if (s->lookahead < MIN_LOOKAHEAD) {
+            fill_window(s);
+            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+                return need_more;
+            }
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+
+        /* Insert the string window[strstart .. strstart+2] in the
+         * dictionary, and set hash_head to the head of the hash chain:
+         */
+        hash_head = NIL;
+        if (s->lookahead >= MIN_MATCH) {
+            INSERT_STRING(s, s->strstart, hash_head);
+        }
+
+        /* Find the longest match, discarding those <= prev_length.
+         * At this point we have always match_length < MIN_MATCH
+         */
+        if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
+            /* To simplify the code, we prevent matches with the string
+             * of window index 0 (in particular we have to avoid a match
+             * of the string with itself at the start of the input file).
+             */
+            s->match_length = longest_match (s, hash_head);
+            /* longest_match() sets match_start */
+        }
+        if (s->match_length >= MIN_MATCH) {
+            check_match(s, s->strstart, s->match_start, s->match_length);
+
+            _tr_tally_dist(s, s->strstart - s->match_start,
+                           s->match_length - MIN_MATCH, bflush);
+
+            s->lookahead -= s->match_length;
+
+            /* Insert new strings in the hash table only if the match length
+             * is not too large. This saves time but degrades compression.
+             */
+#ifndef FASTEST
+            if (s->match_length <= s->max_insert_length &&
+                s->lookahead >= MIN_MATCH) {
+                s->match_length--; /* string at strstart already in table */
+                do {
+                    s->strstart++;
+                    INSERT_STRING(s, s->strstart, hash_head);
+                    /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+                     * always MIN_MATCH bytes ahead.
+                     */
+                } while (--s->match_length != 0);
+                s->strstart++;
+            } else
+#endif
+            {
+                s->strstart += s->match_length;
+                s->match_length = 0;
+                s->ins_h = s->window[s->strstart];
+                UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+                Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+                /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+                 * matter since it will be recomputed at next deflate call.
+                 */
+            }
+        } else {
+            /* No match, output a literal byte */
+            Tracevv((stderr,"%c", s->window[s->strstart]));
+            _tr_tally_lit (s, s->window[s->strstart], bflush);
+            s->lookahead--;
+            s->strstart++;
+        }
+        if (bflush) FLUSH_BLOCK(s, 0);
+    }
+    s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
+    if (flush == Z_FINISH) {
+        FLUSH_BLOCK(s, 1);
+        return finish_done;
+    }
+    if (s->last_lit)
+        FLUSH_BLOCK(s, 0);
+    return block_done;
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+local block_state deflate_slow(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    IPos hash_head;          /* head of hash chain */
+    int bflush;              /* set if current block must be flushed */
+
+    /* Process the input block. */
+    for (;;) {
+        /* Make sure that we always have enough lookahead, except
+         * at the end of the input file. We need MAX_MATCH bytes
+         * for the next match, plus MIN_MATCH bytes to insert the
+         * string following the next match.
+         */
+        if (s->lookahead < MIN_LOOKAHEAD) {
+            fill_window(s);
+            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+                return need_more;
+            }
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+
+        /* Insert the string window[strstart .. strstart+2] in the
+         * dictionary, and set hash_head to the head of the hash chain:
+         */
+        hash_head = NIL;
+        if (s->lookahead >= MIN_MATCH) {
+            INSERT_STRING(s, s->strstart, hash_head);
+        }
+
+        /* Find the longest match, discarding those <= prev_length.
+         */
+        s->prev_length = s->match_length, s->prev_match = s->match_start;
+        s->match_length = MIN_MATCH-1;
+
+        if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
+            s->strstart - hash_head <= MAX_DIST(s)) {
+            /* To simplify the code, we prevent matches with the string
+             * of window index 0 (in particular we have to avoid a match
+             * of the string with itself at the start of the input file).
+             */
+            s->match_length = longest_match (s, hash_head);
+            /* longest_match() sets match_start */
+
+            if (s->match_length <= 5 && (s->strategy == Z_FILTERED
+#if TOO_FAR <= 32767
+                || (s->match_length == MIN_MATCH &&
+                    s->strstart - s->match_start > TOO_FAR)
+#endif
+                )) {
+
+                /* If prev_match is also MIN_MATCH, match_start is garbage
+                 * but we will ignore the current match anyway.
+                 */
+                s->match_length = MIN_MATCH-1;
+            }
+        }
+        /* If there was a match at the previous step and the current
+         * match is not better, output the previous match:
+         */
+        if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
+            uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
+            /* Do not insert strings in hash table beyond this. */
+
+            check_match(s, s->strstart-1, s->prev_match, s->prev_length);
+
+            _tr_tally_dist(s, s->strstart -1 - s->prev_match,
+                           s->prev_length - MIN_MATCH, bflush);
+
+            /* Insert in hash table all strings up to the end of the match.
+             * strstart-1 and strstart are already inserted. If there is not
+             * enough lookahead, the last two strings are not inserted in
+             * the hash table.
+             */
+            s->lookahead -= s->prev_length-1;
+            s->prev_length -= 2;
+            do {
+                if (++s->strstart <= max_insert) {
+                    INSERT_STRING(s, s->strstart, hash_head);
+                }
+            } while (--s->prev_length != 0);
+            s->match_available = 0;
+            s->match_length = MIN_MATCH-1;
+            s->strstart++;
+
+            if (bflush) FLUSH_BLOCK(s, 0);
+
+        } else if (s->match_available) {
+            /* If there was no match at the previous position, output a
+             * single literal. If there was a match but the current match
+             * is longer, truncate the previous match to a single literal.
+             */
+            Tracevv((stderr,"%c", s->window[s->strstart-1]));
+            _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+            if (bflush) {
+                FLUSH_BLOCK_ONLY(s, 0);
+            }
+            s->strstart++;
+            s->lookahead--;
+            if (s->strm->avail_out == 0) return need_more;
+        } else {
+            /* There is no previous match to compare with, wait for
+             * the next step to decide.
+             */
+            s->match_available = 1;
+            s->strstart++;
+            s->lookahead--;
+        }
+    }
+    Assert (flush != Z_NO_FLUSH, "no flush?");
+    if (s->match_available) {
+        Tracevv((stderr,"%c", s->window[s->strstart-1]));
+        _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+        s->match_available = 0;
+    }
+    s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
+    if (flush == Z_FINISH) {
+        FLUSH_BLOCK(s, 1);
+        return finish_done;
+    }
+    if (s->last_lit)
+        FLUSH_BLOCK(s, 0);
+    return block_done;
+}
+#endif /* FASTEST */
+
+/* ===========================================================================
+ * For Z_RLE, simply look for runs of bytes, generate matches only of distance
+ * one.  Do not maintain a hash table.  (It will be regenerated if this run of
+ * deflate switches away from Z_RLE.)
+ */
+local block_state deflate_rle(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    int bflush;             /* set if current block must be flushed */
+    uInt prev;              /* byte at distance one to match */
+    Bytef *scan, *strend;   /* scan goes up to strend for length of run */
+
+    for (;;) {
+        /* Make sure that we always have enough lookahead, except
+         * at the end of the input file. We need MAX_MATCH bytes
+         * for the longest run, plus one for the unrolled loop.
+         */
+        if (s->lookahead <= MAX_MATCH) {
+            fill_window(s);
+            if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) {
+                return need_more;
+            }
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+
+        /* See how many times the previous byte repeats */
+        s->match_length = 0;
+        if (s->lookahead >= MIN_MATCH && s->strstart > 0) {
+            scan = s->window + s->strstart - 1;
+            prev = *scan;
+            if (prev == *++scan && prev == *++scan && prev == *++scan) {
+                strend = s->window + s->strstart + MAX_MATCH;
+                do {
+                } while (prev == *++scan && prev == *++scan &&
+                         prev == *++scan && prev == *++scan &&
+                         prev == *++scan && prev == *++scan &&
+                         prev == *++scan && prev == *++scan &&
+                         scan < strend);
+                s->match_length = MAX_MATCH - (uInt)(strend - scan);
+                if (s->match_length > s->lookahead)
+                    s->match_length = s->lookahead;
+            }
+            Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan");
+        }
+
+        /* Emit match if have run of MIN_MATCH or longer, else emit literal */
+        if (s->match_length >= MIN_MATCH) {
+            check_match(s, s->strstart, s->strstart - 1, s->match_length);
+
+            _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush);
+
+            s->lookahead -= s->match_length;
+            s->strstart += s->match_length;
+            s->match_length = 0;
+        } else {
+            /* No match, output a literal byte */
+            Tracevv((stderr,"%c", s->window[s->strstart]));
+            _tr_tally_lit (s, s->window[s->strstart], bflush);
+            s->lookahead--;
+            s->strstart++;
+        }
+        if (bflush) FLUSH_BLOCK(s, 0);
+    }
+    s->insert = 0;
+    if (flush == Z_FINISH) {
+        FLUSH_BLOCK(s, 1);
+        return finish_done;
+    }
+    if (s->last_lit)
+        FLUSH_BLOCK(s, 0);
+    return block_done;
+}
+
+/* ===========================================================================
+ * For Z_HUFFMAN_ONLY, do not look for matches.  Do not maintain a hash table.
+ * (It will be regenerated if this run of deflate switches away from Huffman.)
+ */
+local block_state deflate_huff(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    int bflush;             /* set if current block must be flushed */
+
+    for (;;) {
+        /* Make sure that we have a literal to write. */
+        if (s->lookahead == 0) {
+            fill_window(s);
+            if (s->lookahead == 0) {
+                if (flush == Z_NO_FLUSH)
+                    return need_more;
+                break;      /* flush the current block */
+            }
+        }
+
+        /* Output a literal byte */
+        s->match_length = 0;
+        Tracevv((stderr,"%c", s->window[s->strstart]));
+        _tr_tally_lit (s, s->window[s->strstart], bflush);
+        s->lookahead--;
+        s->strstart++;
+        if (bflush) FLUSH_BLOCK(s, 0);
+    }
+    s->insert = 0;
+    if (flush == Z_FINISH) {
+        FLUSH_BLOCK(s, 1);
+        return finish_done;
+    }
+    if (s->last_lit)
+        FLUSH_BLOCK(s, 0);
+    return block_done;
+}
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/src/deflate.h
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/src/deflate.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/src/deflate.h	(revision 453)
@@ -0,0 +1,349 @@
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995-2016 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef DEFLATE_H
+#define DEFLATE_H
+
+#include "zutil.h"
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+   trailer creation by deflate().  NO_GZIP would be used to avoid linking in
+   the crc code when it is not needed.  For shared libraries, gzip encoding
+   should be left enabled. */
+#ifndef NO_GZIP
+#  define GZIP
+#endif
+
+/* ===========================================================================
+ * Internal compression state.
+ */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS  256
+/* number of literal bytes 0..255 */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES   30
+/* number of distance codes */
+
+#define BL_CODES  19
+/* number of codes used to transfer the bit lengths */
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define Buf_size 16
+/* size of bit buffer in bi_buf */
+
+#define INIT_STATE    42    /* zlib header -> BUSY_STATE */
+#ifdef GZIP
+#  define GZIP_STATE  57    /* gzip header -> BUSY_STATE | EXTRA_STATE */
+#endif
+#define EXTRA_STATE   69    /* gzip extra block -> NAME_STATE */
+#define NAME_STATE    73    /* gzip file name -> COMMENT_STATE */
+#define COMMENT_STATE 91    /* gzip comment -> HCRC_STATE */
+#define HCRC_STATE   103    /* gzip header CRC -> BUSY_STATE */
+#define BUSY_STATE   113    /* deflate -> FINISH_STATE */
+#define FINISH_STATE 666    /* stream complete */
+/* Stream status */
+
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data_s {
+    union {
+        ush  freq;       /* frequency count */
+        ush  code;       /* bit string */
+    } fc;
+    union {
+        ush  dad;        /* father node in Huffman tree */
+        ush  len;        /* length of bit string */
+    } dl;
+} FAR ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad  dl.dad
+#define Len  dl.len
+
+typedef struct static_tree_desc_s  static_tree_desc;
+
+typedef struct tree_desc_s {
+    ct_data *dyn_tree;           /* the dynamic tree */
+    int     max_code;            /* largest code with non zero frequency */
+    const static_tree_desc *stat_desc;  /* the corresponding static tree */
+} FAR tree_desc;
+
+typedef ush Pos;
+typedef Pos FAR Posf;
+typedef unsigned IPos;
+
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+typedef struct internal_state {
+    z_streamp strm;      /* pointer back to this zlib stream */
+    int   status;        /* as the name implies */
+    Bytef *pending_buf;  /* output still pending */
+    ulg   pending_buf_size; /* size of pending_buf */
+    Bytef *pending_out;  /* next pending byte to output to the stream */
+    ulg   pending;       /* nb of bytes in the pending buffer */
+    int   wrap;          /* bit 0 true for zlib, bit 1 true for gzip */
+    gz_headerp  gzhead;  /* gzip header information to write */
+    ulg   gzindex;       /* where in extra, name, or comment */
+    Byte  method;        /* can only be DEFLATED */
+    int   last_flush;    /* value of flush param for previous deflate call */
+
+                /* used by deflate.c: */
+
+    uInt  w_size;        /* LZ77 window size (32K by default) */
+    uInt  w_bits;        /* log2(w_size)  (8..16) */
+    uInt  w_mask;        /* w_size - 1 */
+
+    Bytef *window;
+    /* Sliding window. Input bytes are read into the second half of the window,
+     * and move to the first half later to keep a dictionary of at least wSize
+     * bytes. With this organization, matches are limited to a distance of
+     * wSize-MAX_MATCH bytes, but this ensures that IO is always
+     * performed with a length multiple of the block size. Also, it limits
+     * the window size to 64K, which is quite useful on MSDOS.
+     * To do: use the user input buffer as sliding window.
+     */
+
+    ulg window_size;
+    /* Actual size of window: 2*wSize, except when the user input buffer
+     * is directly used as sliding window.
+     */
+
+    Posf *prev;
+    /* Link to older string with same hash index. To limit the size of this
+     * array to 64K, this link is maintained only for the last 32K strings.
+     * An index in this array is thus a window index modulo 32K.
+     */
+
+    Posf *head; /* Heads of the hash chains or NIL. */
+
+    uInt  ins_h;          /* hash index of string to be inserted */
+    uInt  hash_size;      /* number of elements in hash table */
+    uInt  hash_bits;      /* log2(hash_size) */
+    uInt  hash_mask;      /* hash_size-1 */
+
+    uInt  hash_shift;
+    /* Number of bits by which ins_h must be shifted at each input
+     * step. It must be such that after MIN_MATCH steps, the oldest
+     * byte no longer takes part in the hash key, that is:
+     *   hash_shift * MIN_MATCH >= hash_bits
+     */
+
+    long block_start;
+    /* Window position at the beginning of the current output block. Gets
+     * negative when the window is moved backwards.
+     */
+
+    uInt match_length;           /* length of best match */
+    IPos prev_match;             /* previous match */
+    int match_available;         /* set if previous match exists */
+    uInt strstart;               /* start of string to insert */
+    uInt match_start;            /* start of matching string */
+    uInt lookahead;              /* number of valid bytes ahead in window */
+
+    uInt prev_length;
+    /* Length of the best match at previous step. Matches not greater than this
+     * are discarded. This is used in the lazy match evaluation.
+     */
+
+    uInt max_chain_length;
+    /* To speed up deflation, hash chains are never searched beyond this
+     * length.  A higher limit improves compression ratio but degrades the
+     * speed.
+     */
+
+    uInt max_lazy_match;
+    /* Attempt to find a better match only when the current match is strictly
+     * smaller than this value. This mechanism is used only for compression
+     * levels >= 4.
+     */
+#   define max_insert_length  max_lazy_match
+    /* Insert new strings in the hash table only if the match length is not
+     * greater than this length. This saves time but degrades compression.
+     * max_insert_length is used only for compression levels <= 3.
+     */
+
+    int level;    /* compression level (1..9) */
+    int strategy; /* favor or force Huffman coding*/
+
+    uInt good_match;
+    /* Use a faster search when the previous match is longer than this */
+
+    int nice_match; /* Stop searching when current match exceeds this */
+
+                /* used by trees.c: */
+    /* Didn't use ct_data typedef below to suppress compiler warning */
+    struct ct_data_s dyn_ltree[HEAP_SIZE];   /* literal and length tree */
+    struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+    struct ct_data_s bl_tree[2*BL_CODES+1];  /* Huffman tree for bit lengths */
+
+    struct tree_desc_s l_desc;               /* desc. for literal tree */
+    struct tree_desc_s d_desc;               /* desc. for distance tree */
+    struct tree_desc_s bl_desc;              /* desc. for bit length tree */
+
+    ush bl_count[MAX_BITS+1];
+    /* number of codes at each bit length for an optimal tree */
+
+    int heap[2*L_CODES+1];      /* heap used to build the Huffman trees */
+    int heap_len;               /* number of elements in the heap */
+    int heap_max;               /* element of largest frequency */
+    /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+     * The same heap array is used to build all trees.
+     */
+
+    uch depth[2*L_CODES+1];
+    /* Depth of each subtree used as tie breaker for trees of equal frequency
+     */
+
+    uchf *l_buf;          /* buffer for literals or lengths */
+
+    uInt  lit_bufsize;
+    /* Size of match buffer for literals/lengths.  There are 4 reasons for
+     * limiting lit_bufsize to 64K:
+     *   - frequencies can be kept in 16 bit counters
+     *   - if compression is not successful for the first block, all input
+     *     data is still in the window so we can still emit a stored block even
+     *     when input comes from standard input.  (This can also be done for
+     *     all blocks if lit_bufsize is not greater than 32K.)
+     *   - if compression is not successful for a file smaller than 64K, we can
+     *     even emit a stored file instead of a stored block (saving 5 bytes).
+     *     This is applicable only for zip (not gzip or zlib).
+     *   - creating new Huffman trees less frequently may not provide fast
+     *     adaptation to changes in the input data statistics. (Take for
+     *     example a binary file with poorly compressible code followed by
+     *     a highly compressible string table.) Smaller buffer sizes give
+     *     fast adaptation but have of course the overhead of transmitting
+     *     trees more frequently.
+     *   - I can't count above 4
+     */
+
+    uInt last_lit;      /* running index in l_buf */
+
+    ushf *d_buf;
+    /* Buffer for distances. To simplify the code, d_buf and l_buf have
+     * the same number of elements. To use different lengths, an extra flag
+     * array would be necessary.
+     */
+
+    ulg opt_len;        /* bit length of current block with optimal trees */
+    ulg static_len;     /* bit length of current block with static trees */
+    uInt matches;       /* number of string matches in current block */
+    uInt insert;        /* bytes at end of window left to insert */
+
+#ifdef ZLIB_DEBUG
+    ulg compressed_len; /* total bit length of compressed file mod 2^32 */
+    ulg bits_sent;      /* bit length of compressed data sent mod 2^32 */
+#endif
+
+    ush bi_buf;
+    /* Output buffer. bits are inserted starting at the bottom (least
+     * significant bits).
+     */
+    int bi_valid;
+    /* Number of valid bits in bi_buf.  All bits above the last valid bit
+     * are always zero.
+     */
+
+    ulg high_water;
+    /* High water mark offset in window for initialized bytes -- bytes above
+     * this are set to zero in order to avoid memory check warnings when
+     * longest match routines access bytes past the input.  This is then
+     * updated to the new high water mark.
+     */
+
+} FAR deflate_state;
+
+/* Output a byte on the stream.
+ * IN assertion: there is enough room in pending_buf.
+ */
+#define put_byte(s, c) {s->pending_buf[s->pending++] = (Bytef)(c);}
+
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST(s)  ((s)->w_size-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+#define WIN_INIT MAX_MATCH
+/* Number of bytes after end of data in window to initialize in order to avoid
+   memory checker errors from longest match routines */
+
+        /* in trees.c */
+void ZLIB_INTERNAL _tr_init OF((deflate_state *s));
+int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
+void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf,
+                        ulg stored_len, int last));
+void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s));
+void ZLIB_INTERNAL _tr_align OF((deflate_state *s));
+void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
+                        ulg stored_len, int last));
+
+#define d_code(dist) \
+   ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. _dist_code[256] and _dist_code[257] are never
+ * used.
+ */
+
+#ifndef ZLIB_DEBUG
+/* Inline versions of _tr_tally for speed: */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+  extern uch ZLIB_INTERNAL _length_code[];
+  extern uch ZLIB_INTERNAL _dist_code[];
+#else
+  extern const uch ZLIB_INTERNAL _length_code[];
+  extern const uch ZLIB_INTERNAL _dist_code[];
+#endif
+
+# define _tr_tally_lit(s, c, flush) \
+  { uch cc = (c); \
+    s->d_buf[s->last_lit] = 0; \
+    s->l_buf[s->last_lit++] = cc; \
+    s->dyn_ltree[cc].Freq++; \
+    flush = (s->last_lit == s->lit_bufsize-1); \
+   }
+# define _tr_tally_dist(s, distance, length, flush) \
+  { uch len = (uch)(length); \
+    ush dist = (ush)(distance); \
+    s->d_buf[s->last_lit] = dist; \
+    s->l_buf[s->last_lit++] = len; \
+    dist--; \
+    s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
+    s->dyn_dtree[d_code(dist)].Freq++; \
+    flush = (s->last_lit == s->lit_bufsize-1); \
+  }
+#else
+# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
+# define _tr_tally_dist(s, distance, length, flush) \
+              flush = _tr_tally(s, distance, length)
+#endif
+
+#endif /* DEFLATE_H */
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/src/gzclose.c
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/src/gzclose.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/src/gzclose.c	(revision 453)
@@ -0,0 +1,25 @@
+/* gzclose.c -- zlib gzclose() function
+ * Copyright (C) 2004, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "gzguts.h"
+
+/* gzclose() is in a separate file so that it is linked in only if it is used.
+   That way the other gzclose functions can be used instead to avoid linking in
+   unneeded compression or decompression routines. */
+int ZEXPORT gzclose(file)
+    gzFile file;
+{
+#ifndef NO_GZCOMPRESS
+    gz_statep state;
+
+    if (file == NULL)
+        return Z_STREAM_ERROR;
+    state = (gz_statep)file;
+
+    return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file);
+#else
+    return gzclose_r(file);
+#endif
+}
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/src/gzguts.h
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/src/gzguts.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/src/gzguts.h	(revision 453)
@@ -0,0 +1,218 @@
+/* gzguts.h -- zlib internal header definitions for gz* operations
+ * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#ifdef _LARGEFILE64_SOURCE
+#  ifndef _LARGEFILE_SOURCE
+#    define _LARGEFILE_SOURCE 1
+#  endif
+#  ifdef _FILE_OFFSET_BITS
+#    undef _FILE_OFFSET_BITS
+#  endif
+#endif
+
+#ifdef HAVE_HIDDEN
+#  define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
+#else
+#  define ZLIB_INTERNAL
+#endif
+
+#include <stdio.h>
+#include "zlib.h"
+#ifdef STDC
+#  include <string.h>
+#  include <stdlib.h>
+#  include <limits.h>
+#endif
+
+#ifndef _POSIX_SOURCE
+#  define _POSIX_SOURCE
+#endif
+#include <fcntl.h>
+
+#ifdef _WIN32
+#  include <stddef.h>
+#endif
+
+#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32)
+#  include <io.h>
+#endif
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+#  define WIDECHAR
+#endif
+
+#ifdef WINAPI_FAMILY
+#  define open _open
+#  define read _read
+#  define write _write
+#  define close _close
+#endif
+
+#ifdef NO_DEFLATE       /* for compatibility with old definition */
+#  define NO_GZCOMPRESS
+#endif
+
+#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
+#  ifndef HAVE_VSNPRINTF
+#    define HAVE_VSNPRINTF
+#  endif
+#endif
+
+#if defined(__CYGWIN__)
+#  ifndef HAVE_VSNPRINTF
+#    define HAVE_VSNPRINTF
+#  endif
+#endif
+
+#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410)
+#  ifndef HAVE_VSNPRINTF
+#    define HAVE_VSNPRINTF
+#  endif
+#endif
+
+#ifndef HAVE_VSNPRINTF
+#  ifdef MSDOS
+/* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
+   but for now we just assume it doesn't. */
+#    define NO_vsnprintf
+#  endif
+#  ifdef __TURBOC__
+#    define NO_vsnprintf
+#  endif
+#  ifdef WIN32
+/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
+#    if !defined(vsnprintf) && !defined(NO_vsnprintf)
+#      if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
+#         define vsnprintf _vsnprintf
+#      endif
+#    endif
+#  endif
+#  ifdef __SASC
+#    define NO_vsnprintf
+#  endif
+#  ifdef VMS
+#    define NO_vsnprintf
+#  endif
+#  ifdef __OS400__
+#    define NO_vsnprintf
+#  endif
+#  ifdef __MVS__
+#    define NO_vsnprintf
+#  endif
+#endif
+
+/* unlike snprintf (which is required in C99), _snprintf does not guarantee
+   null termination of the result -- however this is only used in gzlib.c where
+   the result is assured to fit in the space provided */
+#if defined(_MSC_VER) && _MSC_VER < 1900
+#  define snprintf _snprintf
+#endif
+
+#ifndef local
+#  define local static
+#endif
+/* since "static" is used to mean two completely different things in C, we
+   define "local" for the non-static meaning of "static", for readability
+   (compile with -Dlocal if your debugger can't find static symbols) */
+
+/* gz* functions always use library allocation functions */
+#ifndef STDC
+  extern voidp  malloc OF((uInt size));
+  extern void   free   OF((voidpf ptr));
+#endif
+
+/* get errno and strerror definition */
+#if defined UNDER_CE
+#  include <windows.h>
+#  define zstrerror() gz_strwinerror((DWORD)GetLastError())
+#else
+#  ifndef NO_STRERROR
+#    include <errno.h>
+#    define zstrerror() strerror(errno)
+#  else
+#    define zstrerror() "stdio error (consult errno)"
+#  endif
+#endif
+
+/* provide prototypes for these when building zlib without LFS */
+#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
+    ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+    ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
+    ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
+    ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
+#endif
+
+/* default memLevel */
+#if MAX_MEM_LEVEL >= 8
+#  define DEF_MEM_LEVEL 8
+#else
+#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
+#endif
+
+/* default i/o buffer size -- double this for output when reading (this and
+   twice this must be able to fit in an unsigned type) */
+#define GZBUFSIZE 8192
+
+/* gzip modes, also provide a little integrity check on the passed structure */
+#define GZ_NONE 0
+#define GZ_READ 7247
+#define GZ_WRITE 31153
+#define GZ_APPEND 1     /* mode set to GZ_WRITE after the file is opened */
+
+/* values for gz_state how */
+#define LOOK 0      /* look for a gzip header */
+#define COPY 1      /* copy input directly */
+#define GZIP 2      /* decompress a gzip stream */
+
+/* internal gzip file state data structure */
+typedef struct {
+        /* exposed contents for gzgetc() macro */
+    struct gzFile_s x;      /* "x" for exposed */
+                            /* x.have: number of bytes available at x.next */
+                            /* x.next: next output data to deliver or write */
+                            /* x.pos: current position in uncompressed data */
+        /* used for both reading and writing */
+    int mode;               /* see gzip modes above */
+    int fd;                 /* file descriptor */
+    char *path;             /* path or fd for error messages */
+    unsigned size;          /* buffer size, zero if not allocated yet */
+    unsigned want;          /* requested buffer size, default is GZBUFSIZE */
+    unsigned char *in;      /* input buffer (double-sized when writing) */
+    unsigned char *out;     /* output buffer (double-sized when reading) */
+    int direct;             /* 0 if processing gzip, 1 if transparent */
+        /* just for reading */
+    int how;                /* 0: get header, 1: copy, 2: decompress */
+    z_off64_t start;        /* where the gzip data started, for rewinding */
+    int eof;                /* true if end of input file reached */
+    int past;               /* true if read requested past end */
+        /* just for writing */
+    int level;              /* compression level */
+    int strategy;           /* compression strategy */
+        /* seek request */
+    z_off64_t skip;         /* amount to skip (already rewound if backwards) */
+    int seek;               /* true if seek request pending */
+        /* error information */
+    int err;                /* error code */
+    char *msg;              /* error message */
+        /* zlib inflate or deflate stream */
+    z_stream strm;          /* stream structure in-place (not a pointer) */
+} gz_state;
+typedef gz_state FAR *gz_statep;
+
+/* shared functions */
+void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *));
+#if defined UNDER_CE
+char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error));
+#endif
+
+/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
+   value -- needed when comparing unsigned to z_off64_t, which is signed
+   (possible z_off64_t types off_t, off64_t, and long are all signed) */
+#ifdef INT_MAX
+#  define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)
+#else
+unsigned ZLIB_INTERNAL gz_intmax OF((void));
+#  define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
+#endif
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/src/gzlib.c
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/src/gzlib.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/src/gzlib.c	(revision 453)
@@ -0,0 +1,637 @@
+/* gzlib.c -- zlib functions common to reading and writing gzip files
+ * Copyright (C) 2004-2017 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "gzguts.h"
+
+#if defined(_WIN32) && !defined(__BORLANDC__) && !defined(__MINGW32__)
+#  define LSEEK _lseeki64
+#else
+#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
+#  define LSEEK lseek64
+#else
+#  define LSEEK lseek
+#endif
+#endif
+
+/* Local functions */
+local void gz_reset OF((gz_statep));
+local gzFile gz_open OF((const void *, int, const char *));
+
+#if defined UNDER_CE
+
+/* Map the Windows error number in ERROR to a locale-dependent error message
+   string and return a pointer to it.  Typically, the values for ERROR come
+   from GetLastError.
+
+   The string pointed to shall not be modified by the application, but may be
+   overwritten by a subsequent call to gz_strwinerror
+
+   The gz_strwinerror function does not change the current setting of
+   GetLastError. */
+char ZLIB_INTERNAL *gz_strwinerror (error)
+     DWORD error;
+{
+    static char buf[1024];
+
+    wchar_t *msgbuf;
+    DWORD lasterr = GetLastError();
+    DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
+        | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+        NULL,
+        error,
+        0, /* Default language */
+        (LPVOID)&msgbuf,
+        0,
+        NULL);
+    if (chars != 0) {
+        /* If there is an \r\n appended, zap it.  */
+        if (chars >= 2
+            && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
+            chars -= 2;
+            msgbuf[chars] = 0;
+        }
+
+        if (chars > sizeof (buf) - 1) {
+            chars = sizeof (buf) - 1;
+            msgbuf[chars] = 0;
+        }
+
+        wcstombs(buf, msgbuf, chars + 1);
+        LocalFree(msgbuf);
+    }
+    else {
+        sprintf(buf, "unknown win32 error (%ld)", error);
+    }
+
+    SetLastError(lasterr);
+    return buf;
+}
+
+#endif /* UNDER_CE */
+
+/* Reset gzip file state */
+local void gz_reset(state)
+    gz_statep state;
+{
+    state->x.have = 0;              /* no output data available */
+    if (state->mode == GZ_READ) {   /* for reading ... */
+        state->eof = 0;             /* not at end of file */
+        state->past = 0;            /* have not read past end yet */
+        state->how = LOOK;          /* look for gzip header */
+    }
+    state->seek = 0;                /* no seek request pending */
+    gz_error(state, Z_OK, NULL);    /* clear error */
+    state->x.pos = 0;               /* no uncompressed data yet */
+    state->strm.avail_in = 0;       /* no input data yet */
+}
+
+/* Open a gzip file either by name or file descriptor. */
+local gzFile gz_open(path, fd, mode)
+    const void *path;
+    int fd;
+    const char *mode;
+{
+    gz_statep state;
+    z_size_t len;
+    int oflag;
+#ifdef O_CLOEXEC
+    int cloexec = 0;
+#endif
+#ifdef O_EXCL
+    int exclusive = 0;
+#endif
+
+    /* check input */
+    if (path == NULL)
+        return NULL;
+
+    /* allocate gzFile structure to return */
+    state = (gz_statep)malloc(sizeof(gz_state));
+    if (state == NULL)
+        return NULL;
+    state->size = 0;            /* no buffers allocated yet */
+    state->want = GZBUFSIZE;    /* requested buffer size */
+    state->msg = NULL;          /* no error message yet */
+
+    /* interpret mode */
+    state->mode = GZ_NONE;
+    state->level = Z_DEFAULT_COMPRESSION;
+    state->strategy = Z_DEFAULT_STRATEGY;
+    state->direct = 0;
+    while (*mode) {
+        if (*mode >= '0' && *mode <= '9')
+            state->level = *mode - '0';
+        else
+            switch (*mode) {
+            case 'r':
+                state->mode = GZ_READ;
+                break;
+#ifndef NO_GZCOMPRESS
+            case 'w':
+                state->mode = GZ_WRITE;
+                break;
+            case 'a':
+                state->mode = GZ_APPEND;
+                break;
+#endif
+            case '+':       /* can't read and write at the same time */
+                free(state);
+                return NULL;
+            case 'b':       /* ignore -- will request binary anyway */
+                break;
+#ifdef O_CLOEXEC
+            case 'e':
+                cloexec = 1;
+                break;
+#endif
+#ifdef O_EXCL
+            case 'x':
+                exclusive = 1;
+                break;
+#endif
+            case 'f':
+                state->strategy = Z_FILTERED;
+                break;
+            case 'h':
+                state->strategy = Z_HUFFMAN_ONLY;
+                break;
+            case 'R':
+                state->strategy = Z_RLE;
+                break;
+            case 'F':
+                state->strategy = Z_FIXED;
+                break;
+            case 'T':
+                state->direct = 1;
+                break;
+            default:        /* could consider as an error, but just ignore */
+                ;
+            }
+        mode++;
+    }
+
+    /* must provide an "r", "w", or "a" */
+    if (state->mode == GZ_NONE) {
+        free(state);
+        return NULL;
+    }
+
+    /* can't force transparent read */
+    if (state->mode == GZ_READ) {
+        if (state->direct) {
+            free(state);
+            return NULL;
+        }
+        state->direct = 1;      /* for empty file */
+    }
+
+    /* save the path name for error messages */
+#ifdef WIDECHAR
+    if (fd == -2) {
+        len = wcstombs(NULL, path, 0);
+        if (len == (z_size_t)-1)
+            len = 0;
+    }
+    else
+#endif
+        len = strlen((const char *)path);
+    state->path = (char *)malloc(len + 1);
+    if (state->path == NULL) {
+        free(state);
+        return NULL;
+    }
+#ifdef WIDECHAR
+    if (fd == -2)
+        if (len)
+            wcstombs(state->path, path, len + 1);
+        else
+            *(state->path) = 0;
+    else
+#endif
+#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
+        (void)snprintf(state->path, len + 1, "%s", (const char *)path);
+#else
+        strcpy(state->path, path);
+#endif
+
+    /* compute the flags for open() */
+    oflag =
+#ifdef O_LARGEFILE
+        O_LARGEFILE |
+#endif
+#ifdef O_BINARY
+        O_BINARY |
+#endif
+#ifdef O_CLOEXEC
+        (cloexec ? O_CLOEXEC : 0) |
+#endif
+        (state->mode == GZ_READ ?
+         O_RDONLY :
+         (O_WRONLY | O_CREAT |
+#ifdef O_EXCL
+          (exclusive ? O_EXCL : 0) |
+#endif
+          (state->mode == GZ_WRITE ?
+           O_TRUNC :
+           O_APPEND)));
+
+    /* open the file with the appropriate flags (or just use fd) */
+    state->fd = fd > -1 ? fd : (
+#ifdef WIDECHAR
+        fd == -2 ? _wopen(path, oflag, 0666) :
+#endif
+        open((const char *)path, oflag, 0666));
+    if (state->fd == -1) {
+        free(state->path);
+        free(state);
+        return NULL;
+    }
+    if (state->mode == GZ_APPEND) {
+        LSEEK(state->fd, 0, SEEK_END);  /* so gzoffset() is correct */
+        state->mode = GZ_WRITE;         /* simplify later checks */
+    }
+
+    /* save the current position for rewinding (only if reading) */
+    if (state->mode == GZ_READ) {
+        state->start = LSEEK(state->fd, 0, SEEK_CUR);
+        if (state->start == -1) state->start = 0;
+    }
+
+    /* initialize stream */
+    gz_reset(state);
+
+    /* return stream */
+    return (gzFile)state;
+}
+
+/* -- see zlib.h -- */
+gzFile ZEXPORT gzopen(path, mode)
+    const char *path;
+    const char *mode;
+{
+    return gz_open(path, -1, mode);
+}
+
+/* -- see zlib.h -- */
+gzFile ZEXPORT gzopen64(path, mode)
+    const char *path;
+    const char *mode;
+{
+    return gz_open(path, -1, mode);
+}
+
+/* -- see zlib.h -- */
+gzFile ZEXPORT gzdopen(fd, mode)
+    int fd;
+    const char *mode;
+{
+    char *path;         /* identifier for error messages */
+    gzFile gz;
+
+    if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
+        return NULL;
+#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
+    (void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd);
+#else
+    sprintf(path, "<fd:%d>", fd);   /* for debugging */
+#endif
+    gz = gz_open(path, fd, mode);
+    free(path);
+    return gz;
+}
+
+/* -- see zlib.h -- */
+#ifdef WIDECHAR
+gzFile ZEXPORT gzopen_w(path, mode)
+    const wchar_t *path;
+    const char *mode;
+{
+    return gz_open(path, -2, mode);
+}
+#endif
+
+/* -- see zlib.h -- */
+int ZEXPORT gzbuffer(file, size)
+    gzFile file;
+    unsigned size;
+{
+    gz_statep state;
+
+    /* get internal structure and check integrity */
+    if (file == NULL)
+        return -1;
+    state = (gz_statep)file;
+    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+        return -1;
+
+    /* make sure we haven't already allocated memory */
+    if (state->size != 0)
+        return -1;
+
+    /* check and set requested size */
+    if ((size << 1) < size)
+        return -1;              /* need to be able to double it */
+    if (size < 2)
+        size = 2;               /* need two bytes to check magic header */
+    state->want = size;
+    return 0;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzrewind(file)
+    gzFile file;
+{
+    gz_statep state;
+
+    /* get internal structure */
+    if (file == NULL)
+        return -1;
+    state = (gz_statep)file;
+
+    /* check that we're reading and that there's no error */
+    if (state->mode != GZ_READ ||
+            (state->err != Z_OK && state->err != Z_BUF_ERROR))
+        return -1;
+
+    /* back up and start over */
+    if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
+        return -1;
+    gz_reset(state);
+    return 0;
+}
+
+/* -- see zlib.h -- */
+z_off64_t ZEXPORT gzseek64(file, offset, whence)
+    gzFile file;
+    z_off64_t offset;
+    int whence;
+{
+    unsigned n;
+    z_off64_t ret;
+    gz_statep state;
+
+    /* get internal structure and check integrity */
+    if (file == NULL)
+        return -1;
+    state = (gz_statep)file;
+    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+        return -1;
+
+    /* check that there's no error */
+    if (state->err != Z_OK && state->err != Z_BUF_ERROR)
+        return -1;
+
+    /* can only seek from start or relative to current position */
+    if (whence != SEEK_SET && whence != SEEK_CUR)
+        return -1;
+
+    /* normalize offset to a SEEK_CUR specification */
+    if (whence == SEEK_SET)
+        offset -= state->x.pos;
+    else if (state->seek)
+        offset += state->skip;
+    state->seek = 0;
+
+    /* if within raw area while reading, just go there */
+    if (state->mode == GZ_READ && state->how == COPY &&
+            state->x.pos + offset >= 0) {
+        ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
+        if (ret == -1)
+            return -1;
+        state->x.have = 0;
+        state->eof = 0;
+        state->past = 0;
+        state->seek = 0;
+        gz_error(state, Z_OK, NULL);
+        state->strm.avail_in = 0;
+        state->x.pos += offset;
+        return state->x.pos;
+    }
+
+    /* calculate skip amount, rewinding if needed for back seek when reading */
+    if (offset < 0) {
+        if (state->mode != GZ_READ)         /* writing -- can't go backwards */
+            return -1;
+        offset += state->x.pos;
+        if (offset < 0)                     /* before start of file! */
+            return -1;
+        if (gzrewind(file) == -1)           /* rewind, then skip to offset */
+            return -1;
+    }
+
+    /* if reading, skip what's in output buffer (one less gzgetc() check) */
+    if (state->mode == GZ_READ) {
+        n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
+            (unsigned)offset : state->x.have;
+        state->x.have -= n;
+        state->x.next += n;
+        state->x.pos += n;
+        offset -= n;
+    }
+
+    /* request skip (if not zero) */
+    if (offset) {
+        state->seek = 1;
+        state->skip = offset;
+    }
+    return state->x.pos + offset;
+}
+
+/* -- see zlib.h -- */
+z_off_t ZEXPORT gzseek(file, offset, whence)
+    gzFile file;
+    z_off_t offset;
+    int whence;
+{
+    z_off64_t ret;
+
+    ret = gzseek64(file, (z_off64_t)offset, whence);
+    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
+}
+
+/* -- see zlib.h -- */
+z_off64_t ZEXPORT gztell64(file)
+    gzFile file;
+{
+    gz_statep state;
+
+    /* get internal structure and check integrity */
+    if (file == NULL)
+        return -1;
+    state = (gz_statep)file;
+    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+        return -1;
+
+    /* return position */
+    return state->x.pos + (state->seek ? state->skip : 0);
+}
+
+/* -- see zlib.h -- */
+z_off_t ZEXPORT gztell(file)
+    gzFile file;
+{
+    z_off64_t ret;
+
+    ret = gztell64(file);
+    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
+}
+
+/* -- see zlib.h -- */
+z_off64_t ZEXPORT gzoffset64(file)
+    gzFile file;
+{
+    z_off64_t offset;
+    gz_statep state;
+
+    /* get internal structure and check integrity */
+    if (file == NULL)
+        return -1;
+    state = (gz_statep)file;
+    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+        return -1;
+
+    /* compute and return effective offset in file */
+    offset = LSEEK(state->fd, 0, SEEK_CUR);
+    if (offset == -1)
+        return -1;
+    if (state->mode == GZ_READ)             /* reading */
+        offset -= state->strm.avail_in;     /* don't count buffered input */
+    return offset;
+}
+
+/* -- see zlib.h -- */
+z_off_t ZEXPORT gzoffset(file)
+    gzFile file;
+{
+    z_off64_t ret;
+
+    ret = gzoffset64(file);
+    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzeof(file)
+    gzFile file;
+{
+    gz_statep state;
+
+    /* get internal structure and check integrity */
+    if (file == NULL)
+        return 0;
+    state = (gz_statep)file;
+    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+        return 0;
+
+    /* return end-of-file state */
+    return state->mode == GZ_READ ? state->past : 0;
+}
+
+/* -- see zlib.h -- */
+const char * ZEXPORT gzerror(file, errnum)
+    gzFile file;
+    int *errnum;
+{
+    gz_statep state;
+
+    /* get internal structure and check integrity */
+    if (file == NULL)
+        return NULL;
+    state = (gz_statep)file;
+    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+        return NULL;
+
+    /* return error information */
+    if (errnum != NULL)
+        *errnum = state->err;
+    return state->err == Z_MEM_ERROR ? "out of memory" :
+                                       (state->msg == NULL ? "" : state->msg);
+}
+
+/* -- see zlib.h -- */
+void ZEXPORT gzclearerr(file)
+    gzFile file;
+{
+    gz_statep state;
+
+    /* get internal structure and check integrity */
+    if (file == NULL)
+        return;
+    state = (gz_statep)file;
+    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+        return;
+
+    /* clear error and end-of-file */
+    if (state->mode == GZ_READ) {
+        state->eof = 0;
+        state->past = 0;
+    }
+    gz_error(state, Z_OK, NULL);
+}
+
+/* Create an error message in allocated memory and set state->err and
+   state->msg accordingly.  Free any previous error message already there.  Do
+   not try to free or allocate space if the error is Z_MEM_ERROR (out of
+   memory).  Simply save the error message as a static string.  If there is an
+   allocation failure constructing the error message, then convert the error to
+   out of memory. */
+void ZLIB_INTERNAL gz_error(state, err, msg)
+    gz_statep state;
+    int err;
+    const char *msg;
+{
+    /* free previously allocated message and clear */
+    if (state->msg != NULL) {
+        if (state->err != Z_MEM_ERROR)
+            free(state->msg);
+        state->msg = NULL;
+    }
+
+    /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
+    if (err != Z_OK && err != Z_BUF_ERROR)
+        state->x.have = 0;
+
+    /* set error code, and if no message, then done */
+    state->err = err;
+    if (msg == NULL)
+        return;
+
+    /* for an out of memory error, return literal string when requested */
+    if (err == Z_MEM_ERROR)
+        return;
+
+    /* construct error message with path */
+    if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
+            NULL) {
+        state->err = Z_MEM_ERROR;
+        return;
+    }
+#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
+    (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
+                   "%s%s%s", state->path, ": ", msg);
+#else
+    strcpy(state->msg, state->path);
+    strcat(state->msg, ": ");
+    strcat(state->msg, msg);
+#endif
+}
+
+#ifndef INT_MAX
+/* portably return maximum value for an int (when limits.h presumed not
+   available) -- we need to do this to cover cases where 2's complement not
+   used, since C standard permits 1's complement and sign-bit representations,
+   otherwise we could just use ((unsigned)-1) >> 1 */
+unsigned ZLIB_INTERNAL gz_intmax()
+{
+    unsigned p, q;
+
+    p = 1;
+    do {
+        q = p;
+        p <<= 1;
+        p++;
+    } while (p > q);
+    return q >> 1;
+}
+#endif
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/src/gzread.c
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/src/gzread.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/src/gzread.c	(revision 453)
@@ -0,0 +1,654 @@
+/* gzread.c -- zlib functions for reading gzip files
+ * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "gzguts.h"
+
+/* Local functions */
+local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *));
+local int gz_avail OF((gz_statep));
+local int gz_look OF((gz_statep));
+local int gz_decomp OF((gz_statep));
+local int gz_fetch OF((gz_statep));
+local int gz_skip OF((gz_statep, z_off64_t));
+local z_size_t gz_read OF((gz_statep, voidp, z_size_t));
+
+/* Use read() to load a buffer -- return -1 on error, otherwise 0.  Read from
+   state->fd, and update state->eof, state->err, and state->msg as appropriate.
+   This function needs to loop on read(), since read() is not guaranteed to
+   read the number of bytes requested, depending on the type of descriptor. */
+local int gz_load(state, buf, len, have)
+    gz_statep state;
+    unsigned char *buf;
+    unsigned len;
+    unsigned *have;
+{
+    int ret;
+    unsigned get, max = ((unsigned)-1 >> 2) + 1;
+
+    *have = 0;
+    do {
+        get = len - *have;
+        if (get > max)
+            get = max;
+        ret = read(state->fd, buf + *have, get);
+        if (ret <= 0)
+            break;
+        *have += (unsigned)ret;
+    } while (*have < len);
+    if (ret < 0) {
+        gz_error(state, Z_ERRNO, zstrerror());
+        return -1;
+    }
+    if (ret == 0)
+        state->eof = 1;
+    return 0;
+}
+
+/* Load up input buffer and set eof flag if last data loaded -- return -1 on
+   error, 0 otherwise.  Note that the eof flag is set when the end of the input
+   file is reached, even though there may be unused data in the buffer.  Once
+   that data has been used, no more attempts will be made to read the file.
+   If strm->avail_in != 0, then the current data is moved to the beginning of
+   the input buffer, and then the remainder of the buffer is loaded with the
+   available data from the input file. */
+local int gz_avail(state)
+    gz_statep state;
+{
+    unsigned got;
+    z_streamp strm = &(state->strm);
+
+    if (state->err != Z_OK && state->err != Z_BUF_ERROR)
+        return -1;
+    if (state->eof == 0) {
+        if (strm->avail_in) {       /* copy what's there to the start */
+            unsigned char *p = state->in;
+            unsigned const char *q = strm->next_in;
+            unsigned n = strm->avail_in;
+            do {
+                *p++ = *q++;
+            } while (--n);
+        }
+        if (gz_load(state, state->in + strm->avail_in,
+                    state->size - strm->avail_in, &got) == -1)
+            return -1;
+        strm->avail_in += got;
+        strm->next_in = state->in;
+    }
+    return 0;
+}
+
+/* Look for gzip header, set up for inflate or copy.  state->x.have must be 0.
+   If this is the first time in, allocate required memory.  state->how will be
+   left unchanged if there is no more input data available, will be set to COPY
+   if there is no gzip header and direct copying will be performed, or it will
+   be set to GZIP for decompression.  If direct copying, then leftover input
+   data from the input buffer will be copied to the output buffer.  In that
+   case, all further file reads will be directly to either the output buffer or
+   a user buffer.  If decompressing, the inflate state will be initialized.
+   gz_look() will return 0 on success or -1 on failure. */
+local int gz_look(state)
+    gz_statep state;
+{
+    z_streamp strm = &(state->strm);
+
+    /* allocate read buffers and inflate memory */
+    if (state->size == 0) {
+        /* allocate buffers */
+        state->in = (unsigned char *)malloc(state->want);
+        state->out = (unsigned char *)malloc(state->want << 1);
+        if (state->in == NULL || state->out == NULL) {
+            free(state->out);
+            free(state->in);
+            gz_error(state, Z_MEM_ERROR, "out of memory");
+            return -1;
+        }
+        state->size = state->want;
+
+        /* allocate inflate memory */
+        state->strm.zalloc = Z_NULL;
+        state->strm.zfree = Z_NULL;
+        state->strm.opaque = Z_NULL;
+        state->strm.avail_in = 0;
+        state->strm.next_in = Z_NULL;
+        if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) {    /* gunzip */
+            free(state->out);
+            free(state->in);
+            state->size = 0;
+            gz_error(state, Z_MEM_ERROR, "out of memory");
+            return -1;
+        }
+    }
+
+    /* get at least the magic bytes in the input buffer */
+    if (strm->avail_in < 2) {
+        if (gz_avail(state) == -1)
+            return -1;
+        if (strm->avail_in == 0)
+            return 0;
+    }
+
+    /* look for gzip magic bytes -- if there, do gzip decoding (note: there is
+       a logical dilemma here when considering the case of a partially written
+       gzip file, to wit, if a single 31 byte is written, then we cannot tell
+       whether this is a single-byte file, or just a partially written gzip
+       file -- for here we assume that if a gzip file is being written, then
+       the header will be written in a single operation, so that reading a
+       single byte is sufficient indication that it is not a gzip file) */
+    if (strm->avail_in > 1 &&
+            strm->next_in[0] == 31 && strm->next_in[1] == 139) {
+        inflateReset(strm);
+        state->how = GZIP;
+        state->direct = 0;
+        return 0;
+    }
+
+    /* no gzip header -- if we were decoding gzip before, then this is trailing
+       garbage.  Ignore the trailing garbage and finish. */
+    if (state->direct == 0) {
+        strm->avail_in = 0;
+        state->eof = 1;
+        state->x.have = 0;
+        return 0;
+    }
+
+    /* doing raw i/o, copy any leftover input to output -- this assumes that
+       the output buffer is larger than the input buffer, which also assures
+       space for gzungetc() */
+    state->x.next = state->out;
+    if (strm->avail_in) {
+        memcpy(state->x.next, strm->next_in, strm->avail_in);
+        state->x.have = strm->avail_in;
+        strm->avail_in = 0;
+    }
+    state->how = COPY;
+    state->direct = 1;
+    return 0;
+}
+
+/* Decompress from input to the provided next_out and avail_out in the state.
+   On return, state->x.have and state->x.next point to the just decompressed
+   data.  If the gzip stream completes, state->how is reset to LOOK to look for
+   the next gzip stream or raw data, once state->x.have is depleted.  Returns 0
+   on success, -1 on failure. */
+local int gz_decomp(state)
+    gz_statep state;
+{
+    int ret = Z_OK;
+    unsigned had;
+    z_streamp strm = &(state->strm);
+
+    /* fill output buffer up to end of deflate stream */
+    had = strm->avail_out;
+    do {
+        /* get more input for inflate() */
+        if (strm->avail_in == 0 && gz_avail(state) == -1)
+            return -1;
+        if (strm->avail_in == 0) {
+            gz_error(state, Z_BUF_ERROR, "unexpected end of file");
+            break;
+        }
+
+        /* decompress and handle errors */
+        ret = inflate(strm, Z_NO_FLUSH);
+        if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
+            gz_error(state, Z_STREAM_ERROR,
+                     "internal error: inflate stream corrupt");
+            return -1;
+        }
+        if (ret == Z_MEM_ERROR) {
+            gz_error(state, Z_MEM_ERROR, "out of memory");
+            return -1;
+        }
+        if (ret == Z_DATA_ERROR) {              /* deflate stream invalid */
+            gz_error(state, Z_DATA_ERROR,
+                     strm->msg == NULL ? "compressed data error" : strm->msg);
+            return -1;
+        }
+    } while (strm->avail_out && ret != Z_STREAM_END);
+
+    /* update available output */
+    state->x.have = had - strm->avail_out;
+    state->x.next = strm->next_out - state->x.have;
+
+    /* if the gzip stream completed successfully, look for another */
+    if (ret == Z_STREAM_END)
+        state->how = LOOK;
+
+    /* good decompression */
+    return 0;
+}
+
+/* Fetch data and put it in the output buffer.  Assumes state->x.have is 0.
+   Data is either copied from the input file or decompressed from the input
+   file depending on state->how.  If state->how is LOOK, then a gzip header is
+   looked for to determine whether to copy or decompress.  Returns -1 on error,
+   otherwise 0.  gz_fetch() will leave state->how as COPY or GZIP unless the
+   end of the input file has been reached and all data has been processed.  */
+local int gz_fetch(state)
+    gz_statep state;
+{
+    z_streamp strm = &(state->strm);
+
+    do {
+        switch(state->how) {
+        case LOOK:      /* -> LOOK, COPY (only if never GZIP), or GZIP */
+            if (gz_look(state) == -1)
+                return -1;
+            if (state->how == LOOK)
+                return 0;
+            break;
+        case COPY:      /* -> COPY */
+            if (gz_load(state, state->out, state->size << 1, &(state->x.have))
+                    == -1)
+                return -1;
+            state->x.next = state->out;
+            return 0;
+        case GZIP:      /* -> GZIP or LOOK (if end of gzip stream) */
+            strm->avail_out = state->size << 1;
+            strm->next_out = state->out;
+            if (gz_decomp(state) == -1)
+                return -1;
+        }
+    } while (state->x.have == 0 && (!state->eof || strm->avail_in));
+    return 0;
+}
+
+/* Skip len uncompressed bytes of output.  Return -1 on error, 0 on success. */
+local int gz_skip(state, len)
+    gz_statep state;
+    z_off64_t len;
+{
+    unsigned n;
+
+    /* skip over len bytes or reach end-of-file, whichever comes first */
+    while (len)
+        /* skip over whatever is in output buffer */
+        if (state->x.have) {
+            n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ?
+                (unsigned)len : state->x.have;
+            state->x.have -= n;
+            state->x.next += n;
+            state->x.pos += n;
+            len -= n;
+        }
+
+        /* output buffer empty -- return if we're at the end of the input */
+        else if (state->eof && state->strm.avail_in == 0)
+            break;
+
+        /* need more data to skip -- load up output buffer */
+        else {
+            /* get more output, looking for header if required */
+            if (gz_fetch(state) == -1)
+                return -1;
+        }
+    return 0;
+}
+
+/* Read len bytes into buf from file, or less than len up to the end of the
+   input.  Return the number of bytes read.  If zero is returned, either the
+   end of file was reached, or there was an error.  state->err must be
+   consulted in that case to determine which. */
+local z_size_t gz_read(state, buf, len)
+    gz_statep state;
+    voidp buf;
+    z_size_t len;
+{
+    z_size_t got;
+    unsigned n;
+
+    /* if len is zero, avoid unnecessary operations */
+    if (len == 0)
+        return 0;
+
+    /* process a skip request */
+    if (state->seek) {
+        state->seek = 0;
+        if (gz_skip(state, state->skip) == -1)
+            return 0;
+    }
+
+    /* get len bytes to buf, or less than len if at the end */
+    got = 0;
+    do {
+        /* set n to the maximum amount of len that fits in an unsigned int */
+        n = -1;
+        if (n > len)
+            n = len;
+
+        /* first just try copying data from the output buffer */
+        if (state->x.have) {
+            if (state->x.have < n)
+                n = state->x.have;
+            memcpy(buf, state->x.next, n);
+            state->x.next += n;
+            state->x.have -= n;
+        }
+
+        /* output buffer empty -- return if we're at the end of the input */
+        else if (state->eof && state->strm.avail_in == 0) {
+            state->past = 1;        /* tried to read past end */
+            break;
+        }
+
+        /* need output data -- for small len or new stream load up our output
+           buffer */
+        else if (state->how == LOOK || n < (state->size << 1)) {
+            /* get more output, looking for header if required */
+            if (gz_fetch(state) == -1)
+                return 0;
+            continue;       /* no progress yet -- go back to copy above */
+            /* the copy above assures that we will leave with space in the
+               output buffer, allowing at least one gzungetc() to succeed */
+        }
+
+        /* large len -- read directly into user buffer */
+        else if (state->how == COPY) {      /* read directly */
+            if (gz_load(state, (unsigned char *)buf, n, &n) == -1)
+                return 0;
+        }
+
+        /* large len -- decompress directly into user buffer */
+        else {  /* state->how == GZIP */
+            state->strm.avail_out = n;
+            state->strm.next_out = (unsigned char *)buf;
+            if (gz_decomp(state) == -1)
+                return 0;
+            n = state->x.have;
+            state->x.have = 0;
+        }
+
+        /* update progress */
+        len -= n;
+        buf = (char *)buf + n;
+        got += n;
+        state->x.pos += n;
+    } while (len);
+
+    /* return number of bytes read into user buffer */
+    return got;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzread(file, buf, len)
+    gzFile file;
+    voidp buf;
+    unsigned len;
+{
+    gz_statep state;
+
+    /* get internal structure */
+    if (file == NULL)
+        return -1;
+    state = (gz_statep)file;
+
+    /* check that we're reading and that there's no (serious) error */
+    if (state->mode != GZ_READ ||
+            (state->err != Z_OK && state->err != Z_BUF_ERROR))
+        return -1;
+
+    /* since an int is returned, make sure len fits in one, otherwise return
+       with an error (this avoids a flaw in the interface) */
+    if ((int)len < 0) {
+        gz_error(state, Z_STREAM_ERROR, "request does not fit in an int");
+        return -1;
+    }
+
+    /* read len or fewer bytes to buf */
+    len = gz_read(state, buf, len);
+
+    /* check for an error */
+    if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR)
+        return -1;
+
+    /* return the number of bytes read (this is assured to fit in an int) */
+    return (int)len;
+}
+
+/* -- see zlib.h -- */
+z_size_t ZEXPORT gzfread(buf, size, nitems, file)
+    voidp buf;
+    z_size_t size;
+    z_size_t nitems;
+    gzFile file;
+{
+    z_size_t len;
+    gz_statep state;
+
+    /* get internal structure */
+    if (file == NULL)
+        return 0;
+    state = (gz_statep)file;
+
+    /* check that we're reading and that there's no (serious) error */
+    if (state->mode != GZ_READ ||
+            (state->err != Z_OK && state->err != Z_BUF_ERROR))
+        return 0;
+
+    /* compute bytes to read -- error on overflow */
+    len = nitems * size;
+    if (size && len / size != nitems) {
+        gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
+        return 0;
+    }
+
+    /* read len or fewer bytes to buf, return the number of full items read */
+    return len ? gz_read(state, buf, len) / size : 0;
+}
+
+/* -- see zlib.h -- */
+#ifdef Z_PREFIX_SET
+#  undef z_gzgetc
+#else
+#  undef gzgetc
+#endif
+int ZEXPORT gzgetc(file)
+    gzFile file;
+{
+    int ret;
+    unsigned char buf[1];
+    gz_statep state;
+
+    /* get internal structure */
+    if (file == NULL)
+        return -1;
+    state = (gz_statep)file;
+
+    /* check that we're reading and that there's no (serious) error */
+    if (state->mode != GZ_READ ||
+        (state->err != Z_OK && state->err != Z_BUF_ERROR))
+        return -1;
+
+    /* try output buffer (no need to check for skip request) */
+    if (state->x.have) {
+        state->x.have--;
+        state->x.pos++;
+        return *(state->x.next)++;
+    }
+
+    /* nothing there -- try gz_read() */
+    ret = gz_read(state, buf, 1);
+    return ret < 1 ? -1 : buf[0];
+}
+
+int ZEXPORT gzgetc_(file)
+gzFile file;
+{
+    return gzgetc(file);
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzungetc(c, file)
+    int c;
+    gzFile file;
+{
+    gz_statep state;
+
+    /* get internal structure */
+    if (file == NULL)
+        return -1;
+    state = (gz_statep)file;
+
+    /* check that we're reading and that there's no (serious) error */
+    if (state->mode != GZ_READ ||
+        (state->err != Z_OK && state->err != Z_BUF_ERROR))
+        return -1;
+
+    /* process a skip request */
+    if (state->seek) {
+        state->seek = 0;
+        if (gz_skip(state, state->skip) == -1)
+            return -1;
+    }
+
+    /* can't push EOF */
+    if (c < 0)
+        return -1;
+
+    /* if output buffer empty, put byte at end (allows more pushing) */
+    if (state->x.have == 0) {
+        state->x.have = 1;
+        state->x.next = state->out + (state->size << 1) - 1;
+        state->x.next[0] = (unsigned char)c;
+        state->x.pos--;
+        state->past = 0;
+        return c;
+    }
+
+    /* if no room, give up (must have already done a gzungetc()) */
+    if (state->x.have == (state->size << 1)) {
+        gz_error(state, Z_DATA_ERROR, "out of room to push characters");
+        return -1;
+    }
+
+    /* slide output data if needed and insert byte before existing data */
+    if (state->x.next == state->out) {
+        unsigned char *src = state->out + state->x.have;
+        unsigned char *dest = state->out + (state->size << 1);
+        while (src > state->out)
+            *--dest = *--src;
+        state->x.next = dest;
+    }
+    state->x.have++;
+    state->x.next--;
+    state->x.next[0] = (unsigned char)c;
+    state->x.pos--;
+    state->past = 0;
+    return c;
+}
+
+/* -- see zlib.h -- */
+char * ZEXPORT gzgets(file, buf, len)
+    gzFile file;
+    char *buf;
+    int len;
+{
+    unsigned left, n;
+    char *str;
+    unsigned char *eol;
+    gz_statep state;
+
+    /* check parameters and get internal structure */
+    if (file == NULL || buf == NULL || len < 1)
+        return NULL;
+    state = (gz_statep)file;
+
+    /* check that we're reading and that there's no (serious) error */
+    if (state->mode != GZ_READ ||
+        (state->err != Z_OK && state->err != Z_BUF_ERROR))
+        return NULL;
+
+    /* process a skip request */
+    if (state->seek) {
+        state->seek = 0;
+        if (gz_skip(state, state->skip) == -1)
+            return NULL;
+    }
+
+    /* copy output bytes up to new line or len - 1, whichever comes first --
+       append a terminating zero to the string (we don't check for a zero in
+       the contents, let the user worry about that) */
+    str = buf;
+    left = (unsigned)len - 1;
+    if (left) do {
+        /* assure that something is in the output buffer */
+        if (state->x.have == 0 && gz_fetch(state) == -1)
+            return NULL;                /* error */
+        if (state->x.have == 0) {       /* end of file */
+            state->past = 1;            /* read past end */
+            break;                      /* return what we have */
+        }
+
+        /* look for end-of-line in current output buffer */
+        n = state->x.have > left ? left : state->x.have;
+        eol = (unsigned char *)memchr(state->x.next, '\n', n);
+        if (eol != NULL)
+            n = (unsigned)(eol - state->x.next) + 1;
+
+        /* copy through end-of-line, or remainder if not found */
+        memcpy(buf, state->x.next, n);
+        state->x.have -= n;
+        state->x.next += n;
+        state->x.pos += n;
+        left -= n;
+        buf += n;
+    } while (left && eol == NULL);
+
+    /* return terminated string, or if nothing, end of file */
+    if (buf == str)
+        return NULL;
+    buf[0] = 0;
+    return str;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzdirect(file)
+    gzFile file;
+{
+    gz_statep state;
+
+    /* get internal structure */
+    if (file == NULL)
+        return 0;
+    state = (gz_statep)file;
+
+    /* if the state is not known, but we can find out, then do so (this is
+       mainly for right after a gzopen() or gzdopen()) */
+    if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
+        (void)gz_look(state);
+
+    /* return 1 if transparent, 0 if processing a gzip stream */
+    return state->direct;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzclose_r(file)
+    gzFile file;
+{
+    int ret, err;
+    gz_statep state;
+
+    /* get internal structure */
+    if (file == NULL)
+        return Z_STREAM_ERROR;
+    state = (gz_statep)file;
+
+    /* check that we're reading */
+    if (state->mode != GZ_READ)
+        return Z_STREAM_ERROR;
+
+    /* free memory and close file */
+    if (state->size) {
+        inflateEnd(&(state->strm));
+        free(state->out);
+        free(state->in);
+    }
+    err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;
+    gz_error(state, Z_OK, NULL);
+    free(state->path);
+    ret = close(state->fd);
+    free(state);
+    return ret ? Z_ERRNO : err;
+}
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/src/gzwrite.c
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/src/gzwrite.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/src/gzwrite.c	(revision 453)
@@ -0,0 +1,665 @@
+/* gzwrite.c -- zlib functions for writing gzip files
+ * Copyright (C) 2004-2017 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "gzguts.h"
+
+/* Local functions */
+local int gz_init OF((gz_statep));
+local int gz_comp OF((gz_statep, int));
+local int gz_zero OF((gz_statep, z_off64_t));
+local z_size_t gz_write OF((gz_statep, voidpc, z_size_t));
+
+/* Initialize state for writing a gzip file.  Mark initialization by setting
+   state->size to non-zero.  Return -1 on a memory allocation failure, or 0 on
+   success. */
+local int gz_init(state)
+    gz_statep state;
+{
+    int ret;
+    z_streamp strm = &(state->strm);
+
+    /* allocate input buffer (double size for gzprintf) */
+    state->in = (unsigned char *)malloc(state->want << 1);
+    if (state->in == NULL) {
+        gz_error(state, Z_MEM_ERROR, "out of memory");
+        return -1;
+    }
+
+    /* only need output buffer and deflate state if compressing */
+    if (!state->direct) {
+        /* allocate output buffer */
+        state->out = (unsigned char *)malloc(state->want);
+        if (state->out == NULL) {
+            free(state->in);
+            gz_error(state, Z_MEM_ERROR, "out of memory");
+            return -1;
+        }
+
+        /* allocate deflate memory, set up for gzip compression */
+        strm->zalloc = Z_NULL;
+        strm->zfree = Z_NULL;
+        strm->opaque = Z_NULL;
+        ret = deflateInit2(strm, state->level, Z_DEFLATED,
+                           MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
+        if (ret != Z_OK) {
+            free(state->out);
+            free(state->in);
+            gz_error(state, Z_MEM_ERROR, "out of memory");
+            return -1;
+        }
+        strm->next_in = NULL;
+    }
+
+    /* mark state as initialized */
+    state->size = state->want;
+
+    /* initialize write buffer if compressing */
+    if (!state->direct) {
+        strm->avail_out = state->size;
+        strm->next_out = state->out;
+        state->x.next = strm->next_out;
+    }
+    return 0;
+}
+
+/* Compress whatever is at avail_in and next_in and write to the output file.
+   Return -1 if there is an error writing to the output file or if gz_init()
+   fails to allocate memory, otherwise 0.  flush is assumed to be a valid
+   deflate() flush value.  If flush is Z_FINISH, then the deflate() state is
+   reset to start a new gzip stream.  If gz->direct is true, then simply write
+   to the output file without compressing, and ignore flush. */
+local int gz_comp(state, flush)
+    gz_statep state;
+    int flush;
+{
+    int ret, writ;
+    unsigned have, put, max = ((unsigned)-1 >> 2) + 1;
+    z_streamp strm = &(state->strm);
+
+    /* allocate memory if this is the first time through */
+    if (state->size == 0 && gz_init(state) == -1)
+        return -1;
+
+    /* write directly if requested */
+    if (state->direct) {
+        while (strm->avail_in) {
+            put = strm->avail_in > max ? max : strm->avail_in;
+            writ = write(state->fd, strm->next_in, put);
+            if (writ < 0) {
+                gz_error(state, Z_ERRNO, zstrerror());
+                return -1;
+            }
+            strm->avail_in -= (unsigned)writ;
+            strm->next_in += writ;
+        }
+        return 0;
+    }
+
+    /* run deflate() on provided input until it produces no more output */
+    ret = Z_OK;
+    do {
+        /* write out current buffer contents if full, or if flushing, but if
+           doing Z_FINISH then don't write until we get to Z_STREAM_END */
+        if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
+            (flush != Z_FINISH || ret == Z_STREAM_END))) {
+            while (strm->next_out > state->x.next) {
+                put = strm->next_out - state->x.next > (int)max ? max :
+                      (unsigned)(strm->next_out - state->x.next);
+                writ = write(state->fd, state->x.next, put);
+                if (writ < 0) {
+                    gz_error(state, Z_ERRNO, zstrerror());
+                    return -1;
+                }
+                state->x.next += writ;
+            }
+            if (strm->avail_out == 0) {
+                strm->avail_out = state->size;
+                strm->next_out = state->out;
+                state->x.next = state->out;
+            }
+        }
+
+        /* compress */
+        have = strm->avail_out;
+        ret = deflate(strm, flush);
+        if (ret == Z_STREAM_ERROR) {
+            gz_error(state, Z_STREAM_ERROR,
+                      "internal error: deflate stream corrupt");
+            return -1;
+        }
+        have -= strm->avail_out;
+    } while (have);
+
+    /* if that completed a deflate stream, allow another to start */
+    if (flush == Z_FINISH)
+        deflateReset(strm);
+
+    /* all done, no errors */
+    return 0;
+}
+
+/* Compress len zeros to output.  Return -1 on a write error or memory
+   allocation failure by gz_comp(), or 0 on success. */
+local int gz_zero(state, len)
+    gz_statep state;
+    z_off64_t len;
+{
+    int first;
+    unsigned n;
+    z_streamp strm = &(state->strm);
+
+    /* consume whatever's left in the input buffer */
+    if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
+        return -1;
+
+    /* compress len zeros (len guaranteed > 0) */
+    first = 1;
+    while (len) {
+        n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
+            (unsigned)len : state->size;
+        if (first) {
+            memset(state->in, 0, n);
+            first = 0;
+        }
+        strm->avail_in = n;
+        strm->next_in = state->in;
+        state->x.pos += n;
+        if (gz_comp(state, Z_NO_FLUSH) == -1)
+            return -1;
+        len -= n;
+    }
+    return 0;
+}
+
+/* Write len bytes from buf to file.  Return the number of bytes written.  If
+   the returned value is less than len, then there was an error. */
+local z_size_t gz_write(state, buf, len)
+    gz_statep state;
+    voidpc buf;
+    z_size_t len;
+{
+    z_size_t put = len;
+
+    /* if len is zero, avoid unnecessary operations */
+    if (len == 0)
+        return 0;
+
+    /* allocate memory if this is the first time through */
+    if (state->size == 0 && gz_init(state) == -1)
+        return 0;
+
+    /* check for seek request */
+    if (state->seek) {
+        state->seek = 0;
+        if (gz_zero(state, state->skip) == -1)
+            return 0;
+    }
+
+    /* for small len, copy to input buffer, otherwise compress directly */
+    if (len < state->size) {
+        /* copy to input buffer, compress when full */
+        do {
+            unsigned have, copy;
+
+            if (state->strm.avail_in == 0)
+                state->strm.next_in = state->in;
+            have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
+                              state->in);
+            copy = state->size - have;
+            if (copy > len)
+                copy = len;
+            memcpy(state->in + have, buf, copy);
+            state->strm.avail_in += copy;
+            state->x.pos += copy;
+            buf = (const char *)buf + copy;
+            len -= copy;
+            if (len && gz_comp(state, Z_NO_FLUSH) == -1)
+                return 0;
+        } while (len);
+    }
+    else {
+        /* consume whatever's left in the input buffer */
+        if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
+            return 0;
+
+        /* directly compress user buffer to file */
+        state->strm.next_in = (z_const Bytef *)buf;
+        do {
+            unsigned n = (unsigned)-1;
+            if (n > len)
+                n = len;
+            state->strm.avail_in = n;
+            state->x.pos += n;
+            if (gz_comp(state, Z_NO_FLUSH) == -1)
+                return 0;
+            len -= n;
+        } while (len);
+    }
+
+    /* input was all buffered or compressed */
+    return put;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzwrite(file, buf, len)
+    gzFile file;
+    voidpc buf;
+    unsigned len;
+{
+    gz_statep state;
+
+    /* get internal structure */
+    if (file == NULL)
+        return 0;
+    state = (gz_statep)file;
+
+    /* check that we're writing and that there's no error */
+    if (state->mode != GZ_WRITE || state->err != Z_OK)
+        return 0;
+
+    /* since an int is returned, make sure len fits in one, otherwise return
+       with an error (this avoids a flaw in the interface) */
+    if ((int)len < 0) {
+        gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
+        return 0;
+    }
+
+    /* write len bytes from buf (the return value will fit in an int) */
+    return (int)gz_write(state, buf, len);
+}
+
+/* -- see zlib.h -- */
+z_size_t ZEXPORT gzfwrite(buf, size, nitems, file)
+    voidpc buf;
+    z_size_t size;
+    z_size_t nitems;
+    gzFile file;
+{
+    z_size_t len;
+    gz_statep state;
+
+    /* get internal structure */
+    if (file == NULL)
+        return 0;
+    state = (gz_statep)file;
+
+    /* check that we're writing and that there's no error */
+    if (state->mode != GZ_WRITE || state->err != Z_OK)
+        return 0;
+
+    /* compute bytes to read -- error on overflow */
+    len = nitems * size;
+    if (size && len / size != nitems) {
+        gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
+        return 0;
+    }
+
+    /* write len bytes to buf, return the number of full items written */
+    return len ? gz_write(state, buf, len) / size : 0;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzputc(file, c)
+    gzFile file;
+    int c;
+{
+    unsigned have;
+    unsigned char buf[1];
+    gz_statep state;
+    z_streamp strm;
+
+    /* get internal structure */
+    if (file == NULL)
+        return -1;
+    state = (gz_statep)file;
+    strm = &(state->strm);
+
+    /* check that we're writing and that there's no error */
+    if (state->mode != GZ_WRITE || state->err != Z_OK)
+        return -1;
+
+    /* check for seek request */
+    if (state->seek) {
+        state->seek = 0;
+        if (gz_zero(state, state->skip) == -1)
+            return -1;
+    }
+
+    /* try writing to input buffer for speed (state->size == 0 if buffer not
+       initialized) */
+    if (state->size) {
+        if (strm->avail_in == 0)
+            strm->next_in = state->in;
+        have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
+        if (have < state->size) {
+            state->in[have] = (unsigned char)c;
+            strm->avail_in++;
+            state->x.pos++;
+            return c & 0xff;
+        }
+    }
+
+    /* no room in buffer or not initialized, use gz_write() */
+    buf[0] = (unsigned char)c;
+    if (gz_write(state, buf, 1) != 1)
+        return -1;
+    return c & 0xff;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzputs(file, str)
+    gzFile file;
+    const char *str;
+{
+    int ret;
+    z_size_t len;
+    gz_statep state;
+
+    /* get internal structure */
+    if (file == NULL)
+        return -1;
+    state = (gz_statep)file;
+
+    /* check that we're writing and that there's no error */
+    if (state->mode != GZ_WRITE || state->err != Z_OK)
+        return -1;
+
+    /* write string */
+    len = strlen(str);
+    ret = gz_write(state, str, len);
+    return ret == 0 && len != 0 ? -1 : ret;
+}
+
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#include <stdarg.h>
+
+/* -- see zlib.h -- */
+int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
+{
+    int len;
+    unsigned left;
+    char *next;
+    gz_statep state;
+    z_streamp strm;
+
+    /* get internal structure */
+    if (file == NULL)
+        return Z_STREAM_ERROR;
+    state = (gz_statep)file;
+    strm = &(state->strm);
+
+    /* check that we're writing and that there's no error */
+    if (state->mode != GZ_WRITE || state->err != Z_OK)
+        return Z_STREAM_ERROR;
+
+    /* make sure we have some buffer space */
+    if (state->size == 0 && gz_init(state) == -1)
+        return state->err;
+
+    /* check for seek request */
+    if (state->seek) {
+        state->seek = 0;
+        if (gz_zero(state, state->skip) == -1)
+            return state->err;
+    }
+
+    /* do the printf() into the input buffer, put length in len -- the input
+       buffer is double-sized just for this function, so there is guaranteed to
+       be state->size bytes available after the current contents */
+    if (strm->avail_in == 0)
+        strm->next_in = state->in;
+    next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
+    next[state->size - 1] = 0;
+#ifdef NO_vsnprintf
+#  ifdef HAS_vsprintf_void
+    (void)vsprintf(next, format, va);
+    for (len = 0; len < state->size; len++)
+        if (next[len] == 0) break;
+#  else
+    len = vsprintf(next, format, va);
+#  endif
+#else
+#  ifdef HAS_vsnprintf_void
+    (void)vsnprintf(next, state->size, format, va);
+    len = strlen(next);
+#  else
+    len = vsnprintf(next, state->size, format, va);
+#  endif
+#endif
+
+    /* check that printf() results fit in buffer */
+    if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
+        return 0;
+
+    /* update buffer and position, compress first half if past that */
+    strm->avail_in += (unsigned)len;
+    state->x.pos += len;
+    if (strm->avail_in >= state->size) {
+        left = strm->avail_in - state->size;
+        strm->avail_in = state->size;
+        if (gz_comp(state, Z_NO_FLUSH) == -1)
+            return state->err;
+        memcpy(state->in, state->in + state->size, left);
+        strm->next_in = state->in;
+        strm->avail_in = left;
+    }
+    return len;
+}
+
+int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
+{
+    va_list va;
+    int ret;
+
+    va_start(va, format);
+    ret = gzvprintf(file, format, va);
+    va_end(va);
+    return ret;
+}
+
+#else /* !STDC && !Z_HAVE_STDARG_H */
+
+/* -- see zlib.h -- */
+int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
+                       a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
+    gzFile file;
+    const char *format;
+    int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
+        a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
+{
+    unsigned len, left;
+    char *next;
+    gz_statep state;
+    z_streamp strm;
+
+    /* get internal structure */
+    if (file == NULL)
+        return Z_STREAM_ERROR;
+    state = (gz_statep)file;
+    strm = &(state->strm);
+
+    /* check that can really pass pointer in ints */
+    if (sizeof(int) != sizeof(void *))
+        return Z_STREAM_ERROR;
+
+    /* check that we're writing and that there's no error */
+    if (state->mode != GZ_WRITE || state->err != Z_OK)
+        return Z_STREAM_ERROR;
+
+    /* make sure we have some buffer space */
+    if (state->size == 0 && gz_init(state) == -1)
+        return state->error;
+
+    /* check for seek request */
+    if (state->seek) {
+        state->seek = 0;
+        if (gz_zero(state, state->skip) == -1)
+            return state->error;
+    }
+
+    /* do the printf() into the input buffer, put length in len -- the input
+       buffer is double-sized just for this function, so there is guaranteed to
+       be state->size bytes available after the current contents */
+    if (strm->avail_in == 0)
+        strm->next_in = state->in;
+    next = (char *)(strm->next_in + strm->avail_in);
+    next[state->size - 1] = 0;
+#ifdef NO_snprintf
+#  ifdef HAS_sprintf_void
+    sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
+            a13, a14, a15, a16, a17, a18, a19, a20);
+    for (len = 0; len < size; len++)
+        if (next[len] == 0)
+            break;
+#  else
+    len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
+                  a12, a13, a14, a15, a16, a17, a18, a19, a20);
+#  endif
+#else
+#  ifdef HAS_snprintf_void
+    snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+             a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+    len = strlen(next);
+#  else
+    len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
+                   a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+#  endif
+#endif
+
+    /* check that printf() results fit in buffer */
+    if (len == 0 || len >= state->size || next[state->size - 1] != 0)
+        return 0;
+
+    /* update buffer and position, compress first half if past that */
+    strm->avail_in += len;
+    state->x.pos += len;
+    if (strm->avail_in >= state->size) {
+        left = strm->avail_in - state->size;
+        strm->avail_in = state->size;
+        if (gz_comp(state, Z_NO_FLUSH) == -1)
+            return state->err;
+        memcpy(state->in, state->in + state->size, left);
+        strm->next_in = state->in;
+        strm->avail_in = left;
+    }
+    return (int)len;
+}
+
+#endif
+
+/* -- see zlib.h -- */
+int ZEXPORT gzflush(file, flush)
+    gzFile file;
+    int flush;
+{
+    gz_statep state;
+
+    /* get internal structure */
+    if (file == NULL)
+        return Z_STREAM_ERROR;
+    state = (gz_statep)file;
+
+    /* check that we're writing and that there's no error */
+    if (state->mode != GZ_WRITE || state->err != Z_OK)
+        return Z_STREAM_ERROR;
+
+    /* check flush parameter */
+    if (flush < 0 || flush > Z_FINISH)
+        return Z_STREAM_ERROR;
+
+    /* check for seek request */
+    if (state->seek) {
+        state->seek = 0;
+        if (gz_zero(state, state->skip) == -1)
+            return state->err;
+    }
+
+    /* compress remaining data with requested flush */
+    (void)gz_comp(state, flush);
+    return state->err;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzsetparams(file, level, strategy)
+    gzFile file;
+    int level;
+    int strategy;
+{
+    gz_statep state;
+    z_streamp strm;
+
+    /* get internal structure */
+    if (file == NULL)
+        return Z_STREAM_ERROR;
+    state = (gz_statep)file;
+    strm = &(state->strm);
+
+    /* check that we're writing and that there's no error */
+    if (state->mode != GZ_WRITE || state->err != Z_OK)
+        return Z_STREAM_ERROR;
+
+    /* if no change is requested, then do nothing */
+    if (level == state->level && strategy == state->strategy)
+        return Z_OK;
+
+    /* check for seek request */
+    if (state->seek) {
+        state->seek = 0;
+        if (gz_zero(state, state->skip) == -1)
+            return state->err;
+    }
+
+    /* change compression parameters for subsequent input */
+    if (state->size) {
+        /* flush previous input with previous parameters before changing */
+        if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
+            return state->err;
+        deflateParams(strm, level, strategy);
+    }
+    state->level = level;
+    state->strategy = strategy;
+    return Z_OK;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzclose_w(file)
+    gzFile file;
+{
+    int ret = Z_OK;
+    gz_statep state;
+
+    /* get internal structure */
+    if (file == NULL)
+        return Z_STREAM_ERROR;
+    state = (gz_statep)file;
+
+    /* check that we're writing */
+    if (state->mode != GZ_WRITE)
+        return Z_STREAM_ERROR;
+
+    /* check for seek request */
+    if (state->seek) {
+        state->seek = 0;
+        if (gz_zero(state, state->skip) == -1)
+            ret = state->err;
+    }
+
+    /* flush, free memory, and close file */
+    if (gz_comp(state, Z_FINISH) == -1)
+        ret = state->err;
+    if (state->size) {
+        if (!state->direct) {
+            (void)deflateEnd(&(state->strm));
+            free(state->out);
+        }
+        free(state->in);
+    }
+    gz_error(state, Z_OK, NULL);
+    free(state->path);
+    if (close(state->fd) == -1)
+        ret = Z_ERRNO;
+    free(state);
+    return ret;
+}
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/src/infback.c
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/src/infback.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/src/infback.c	(revision 453)
@@ -0,0 +1,640 @@
+/* infback.c -- inflate using a call-back interface
+ * Copyright (C) 1995-2016 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+   This code is largely copied from inflate.c.  Normally either infback.o or
+   inflate.o would be linked into an application--not both.  The interface
+   with inffast.c is retained so that optimized assembler-coded versions of
+   inflate_fast() can be used with either inflate.c or infback.c.
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+/* function prototypes */
+local void fixedtables OF((struct inflate_state FAR *state));
+
+/*
+   strm provides memory allocation functions in zalloc and zfree, or
+   Z_NULL to use the library memory allocation functions.
+
+   windowBits is in the range 8..15, and window is a user-supplied
+   window and output buffer that is 2**windowBits bytes.
+ */
+int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
+z_streamp strm;
+int windowBits;
+unsigned char FAR *window;
+const char *version;
+int stream_size;
+{
+    struct inflate_state FAR *state;
+
+    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+        stream_size != (int)(sizeof(z_stream)))
+        return Z_VERSION_ERROR;
+    if (strm == Z_NULL || window == Z_NULL ||
+        windowBits < 8 || windowBits > 15)
+        return Z_STREAM_ERROR;
+    strm->msg = Z_NULL;                 /* in case we return an error */
+    if (strm->zalloc == (alloc_func)0) {
+#ifdef Z_SOLO
+        return Z_STREAM_ERROR;
+#else
+        strm->zalloc = zcalloc;
+        strm->opaque = (voidpf)0;
+#endif
+    }
+    if (strm->zfree == (free_func)0)
+#ifdef Z_SOLO
+        return Z_STREAM_ERROR;
+#else
+    strm->zfree = zcfree;
+#endif
+    state = (struct inflate_state FAR *)ZALLOC(strm, 1,
+                                               sizeof(struct inflate_state));
+    if (state == Z_NULL) return Z_MEM_ERROR;
+    Tracev((stderr, "inflate: allocated\n"));
+    strm->state = (struct internal_state FAR *)state;
+    state->dmax = 32768U;
+    state->wbits = (uInt)windowBits;
+    state->wsize = 1U << windowBits;
+    state->window = window;
+    state->wnext = 0;
+    state->whave = 0;
+    return Z_OK;
+}
+
+/*
+   Return state with length and distance decoding tables and index sizes set to
+   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
+   If BUILDFIXED is defined, then instead this routine builds the tables the
+   first time it's called, and returns those tables the first time and
+   thereafter.  This reduces the size of the code by about 2K bytes, in
+   exchange for a little execution time.  However, BUILDFIXED should not be
+   used for threaded applications, since the rewriting of the tables and virgin
+   may not be thread-safe.
+ */
+local void fixedtables(state)
+struct inflate_state FAR *state;
+{
+#ifdef BUILDFIXED
+    static int virgin = 1;
+    static code *lenfix, *distfix;
+    static code fixed[544];
+
+    /* build fixed huffman tables if first call (may not be thread safe) */
+    if (virgin) {
+        unsigned sym, bits;
+        static code *next;
+
+        /* literal/length table */
+        sym = 0;
+        while (sym < 144) state->lens[sym++] = 8;
+        while (sym < 256) state->lens[sym++] = 9;
+        while (sym < 280) state->lens[sym++] = 7;
+        while (sym < 288) state->lens[sym++] = 8;
+        next = fixed;
+        lenfix = next;
+        bits = 9;
+        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+        /* distance table */
+        sym = 0;
+        while (sym < 32) state->lens[sym++] = 5;
+        distfix = next;
+        bits = 5;
+        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+        /* do this just once */
+        virgin = 0;
+    }
+#else /* !BUILDFIXED */
+#   include "inffixed.h"
+#endif /* BUILDFIXED */
+    state->lencode = lenfix;
+    state->lenbits = 9;
+    state->distcode = distfix;
+    state->distbits = 5;
+}
+
+/* Macros for inflateBack(): */
+
+/* Load returned state from inflate_fast() */
+#define LOAD() \
+    do { \
+        put = strm->next_out; \
+        left = strm->avail_out; \
+        next = strm->next_in; \
+        have = strm->avail_in; \
+        hold = state->hold; \
+        bits = state->bits; \
+    } while (0)
+
+/* Set state from registers for inflate_fast() */
+#define RESTORE() \
+    do { \
+        strm->next_out = put; \
+        strm->avail_out = left; \
+        strm->next_in = next; \
+        strm->avail_in = have; \
+        state->hold = hold; \
+        state->bits = bits; \
+    } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+    do { \
+        hold = 0; \
+        bits = 0; \
+    } while (0)
+
+/* Assure that some input is available.  If input is requested, but denied,
+   then return a Z_BUF_ERROR from inflateBack(). */
+#define PULL() \
+    do { \
+        if (have == 0) { \
+            have = in(in_desc, &next); \
+            if (have == 0) { \
+                next = Z_NULL; \
+                ret = Z_BUF_ERROR; \
+                goto inf_leave; \
+            } \
+        } \
+    } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflateBack()
+   with an error if there is no input available. */
+#define PULLBYTE() \
+    do { \
+        PULL(); \
+        have--; \
+        hold += (unsigned long)(*next++) << bits; \
+        bits += 8; \
+    } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator.  If there is
+   not enough available input to do that, then return from inflateBack() with
+   an error. */
+#define NEEDBITS(n) \
+    do { \
+        while (bits < (unsigned)(n)) \
+            PULLBYTE(); \
+    } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+    ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+    do { \
+        hold >>= (n); \
+        bits -= (unsigned)(n); \
+    } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+    do { \
+        hold >>= bits & 7; \
+        bits -= bits & 7; \
+    } while (0)
+
+/* Assure that some output space is available, by writing out the window
+   if it's full.  If the write fails, return from inflateBack() with a
+   Z_BUF_ERROR. */
+#define ROOM() \
+    do { \
+        if (left == 0) { \
+            put = state->window; \
+            left = state->wsize; \
+            state->whave = left; \
+            if (out(out_desc, put, left)) { \
+                ret = Z_BUF_ERROR; \
+                goto inf_leave; \
+            } \
+        } \
+    } while (0)
+
+/*
+   strm provides the memory allocation functions and window buffer on input,
+   and provides information on the unused input on return.  For Z_DATA_ERROR
+   returns, strm will also provide an error message.
+
+   in() and out() are the call-back input and output functions.  When
+   inflateBack() needs more input, it calls in().  When inflateBack() has
+   filled the window with output, or when it completes with data in the
+   window, it calls out() to write out the data.  The application must not
+   change the provided input until in() is called again or inflateBack()
+   returns.  The application must not change the window/output buffer until
+   inflateBack() returns.
+
+   in() and out() are called with a descriptor parameter provided in the
+   inflateBack() call.  This parameter can be a structure that provides the
+   information required to do the read or write, as well as accumulated
+   information on the input and output such as totals and check values.
+
+   in() should return zero on failure.  out() should return non-zero on
+   failure.  If either in() or out() fails, than inflateBack() returns a
+   Z_BUF_ERROR.  strm->next_in can be checked for Z_NULL to see whether it
+   was in() or out() that caused in the error.  Otherwise,  inflateBack()
+   returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
+   error, or Z_MEM_ERROR if it could not allocate memory for the state.
+   inflateBack() can also return Z_STREAM_ERROR if the input parameters
+   are not correct, i.e. strm is Z_NULL or the state was not initialized.
+ */
+int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
+z_streamp strm;
+in_func in;
+void FAR *in_desc;
+out_func out;
+void FAR *out_desc;
+{
+    struct inflate_state FAR *state;
+    z_const unsigned char FAR *next;    /* next input */
+    unsigned char FAR *put;     /* next output */
+    unsigned have, left;        /* available input and output */
+    unsigned long hold;         /* bit buffer */
+    unsigned bits;              /* bits in bit buffer */
+    unsigned copy;              /* number of stored or match bytes to copy */
+    unsigned char FAR *from;    /* where to copy match bytes from */
+    code here;                  /* current decoding table entry */
+    code last;                  /* parent table entry */
+    unsigned len;               /* length to copy for repeats, bits to drop */
+    int ret;                    /* return code */
+    static const unsigned short order[19] = /* permutation of code lengths */
+        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+    /* Check that the strm exists and that the state was initialized */
+    if (strm == Z_NULL || strm->state == Z_NULL)
+        return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* Reset the state */
+    strm->msg = Z_NULL;
+    state->mode = TYPE;
+    state->last = 0;
+    state->whave = 0;
+    next = strm->next_in;
+    have = next != Z_NULL ? strm->avail_in : 0;
+    hold = 0;
+    bits = 0;
+    put = state->window;
+    left = state->wsize;
+
+    /* Inflate until end of block marked as last */
+    for (;;)
+        switch (state->mode) {
+        case TYPE:
+            /* determine and dispatch block type */
+            if (state->last) {
+                BYTEBITS();
+                state->mode = DONE;
+                break;
+            }
+            NEEDBITS(3);
+            state->last = BITS(1);
+            DROPBITS(1);
+            switch (BITS(2)) {
+            case 0:                             /* stored block */
+                Tracev((stderr, "inflate:     stored block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = STORED;
+                break;
+            case 1:                             /* fixed block */
+                fixedtables(state);
+                Tracev((stderr, "inflate:     fixed codes block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = LEN;              /* decode codes */
+                break;
+            case 2:                             /* dynamic block */
+                Tracev((stderr, "inflate:     dynamic codes block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = TABLE;
+                break;
+            case 3:
+                strm->msg = (char *)"invalid block type";
+                state->mode = BAD;
+            }
+            DROPBITS(2);
+            break;
+
+        case STORED:
+            /* get and verify stored block length */
+            BYTEBITS();                         /* go to byte boundary */
+            NEEDBITS(32);
+            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+                strm->msg = (char *)"invalid stored block lengths";
+                state->mode = BAD;
+                break;
+            }
+            state->length = (unsigned)hold & 0xffff;
+            Tracev((stderr, "inflate:       stored length %u\n",
+                    state->length));
+            INITBITS();
+
+            /* copy stored block from input to output */
+            while (state->length != 0) {
+                copy = state->length;
+                PULL();
+                ROOM();
+                if (copy > have) copy = have;
+                if (copy > left) copy = left;
+                zmemcpy(put, next, copy);
+                have -= copy;
+                next += copy;
+                left -= copy;
+                put += copy;
+                state->length -= copy;
+            }
+            Tracev((stderr, "inflate:       stored end\n"));
+            state->mode = TYPE;
+            break;
+
+        case TABLE:
+            /* get dynamic table entries descriptor */
+            NEEDBITS(14);
+            state->nlen = BITS(5) + 257;
+            DROPBITS(5);
+            state->ndist = BITS(5) + 1;
+            DROPBITS(5);
+            state->ncode = BITS(4) + 4;
+            DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+            if (state->nlen > 286 || state->ndist > 30) {
+                strm->msg = (char *)"too many length or distance symbols";
+                state->mode = BAD;
+                break;
+            }
+#endif
+            Tracev((stderr, "inflate:       table sizes ok\n"));
+
+            /* get code length code lengths (not a typo) */
+            state->have = 0;
+            while (state->have < state->ncode) {
+                NEEDBITS(3);
+                state->lens[order[state->have++]] = (unsigned short)BITS(3);
+                DROPBITS(3);
+            }
+            while (state->have < 19)
+                state->lens[order[state->have++]] = 0;
+            state->next = state->codes;
+            state->lencode = (code const FAR *)(state->next);
+            state->lenbits = 7;
+            ret = inflate_table(CODES, state->lens, 19, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid code lengths set";
+                state->mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       code lengths ok\n"));
+
+            /* get length and distance code code lengths */
+            state->have = 0;
+            while (state->have < state->nlen + state->ndist) {
+                for (;;) {
+                    here = state->lencode[BITS(state->lenbits)];
+                    if ((unsigned)(here.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                if (here.val < 16) {
+                    DROPBITS(here.bits);
+                    state->lens[state->have++] = here.val;
+                }
+                else {
+                    if (here.val == 16) {
+                        NEEDBITS(here.bits + 2);
+                        DROPBITS(here.bits);
+                        if (state->have == 0) {
+                            strm->msg = (char *)"invalid bit length repeat";
+                            state->mode = BAD;
+                            break;
+                        }
+                        len = (unsigned)(state->lens[state->have - 1]);
+                        copy = 3 + BITS(2);
+                        DROPBITS(2);
+                    }
+                    else if (here.val == 17) {
+                        NEEDBITS(here.bits + 3);
+                        DROPBITS(here.bits);
+                        len = 0;
+                        copy = 3 + BITS(3);
+                        DROPBITS(3);
+                    }
+                    else {
+                        NEEDBITS(here.bits + 7);
+                        DROPBITS(here.bits);
+                        len = 0;
+                        copy = 11 + BITS(7);
+                        DROPBITS(7);
+                    }
+                    if (state->have + copy > state->nlen + state->ndist) {
+                        strm->msg = (char *)"invalid bit length repeat";
+                        state->mode = BAD;
+                        break;
+                    }
+                    while (copy--)
+                        state->lens[state->have++] = (unsigned short)len;
+                }
+            }
+
+            /* handle error breaks in while */
+            if (state->mode == BAD) break;
+
+            /* check for end-of-block code (better have one) */
+            if (state->lens[256] == 0) {
+                strm->msg = (char *)"invalid code -- missing end-of-block";
+                state->mode = BAD;
+                break;
+            }
+
+            /* build code tables -- note: do not change the lenbits or distbits
+               values here (9 and 6) without reading the comments in inftrees.h
+               concerning the ENOUGH constants, which depend on those values */
+            state->next = state->codes;
+            state->lencode = (code const FAR *)(state->next);
+            state->lenbits = 9;
+            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid literal/lengths set";
+                state->mode = BAD;
+                break;
+            }
+            state->distcode = (code const FAR *)(state->next);
+            state->distbits = 6;
+            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+                            &(state->next), &(state->distbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid distances set";
+                state->mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       codes ok\n"));
+            state->mode = LEN;
+
+        case LEN:
+            /* use inflate_fast() if we have enough input and output */
+            if (have >= 6 && left >= 258) {
+                RESTORE();
+                if (state->whave < state->wsize)
+                    state->whave = state->wsize - left;
+                inflate_fast(strm, state->wsize);
+                LOAD();
+                break;
+            }
+
+            /* get a literal, length, or end-of-block code */
+            for (;;) {
+                here = state->lencode[BITS(state->lenbits)];
+                if ((unsigned)(here.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if (here.op && (here.op & 0xf0) == 0) {
+                last = here;
+                for (;;) {
+                    here = state->lencode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + here.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+            }
+            DROPBITS(here.bits);
+            state->length = (unsigned)here.val;
+
+            /* process literal */
+            if (here.op == 0) {
+                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+                        "inflate:         literal '%c'\n" :
+                        "inflate:         literal 0x%02x\n", here.val));
+                ROOM();
+                *put++ = (unsigned char)(state->length);
+                left--;
+                state->mode = LEN;
+                break;
+            }
+
+            /* process end of block */
+            if (here.op & 32) {
+                Tracevv((stderr, "inflate:         end of block\n"));
+                state->mode = TYPE;
+                break;
+            }
+
+            /* invalid code */
+            if (here.op & 64) {
+                strm->msg = (char *)"invalid literal/length code";
+                state->mode = BAD;
+                break;
+            }
+
+            /* length code -- get extra bits, if any */
+            state->extra = (unsigned)(here.op) & 15;
+            if (state->extra != 0) {
+                NEEDBITS(state->extra);
+                state->length += BITS(state->extra);
+                DROPBITS(state->extra);
+            }
+            Tracevv((stderr, "inflate:         length %u\n", state->length));
+
+            /* get distance code */
+            for (;;) {
+                here = state->distcode[BITS(state->distbits)];
+                if ((unsigned)(here.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if ((here.op & 0xf0) == 0) {
+                last = here;
+                for (;;) {
+                    here = state->distcode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + here.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+            }
+            DROPBITS(here.bits);
+            if (here.op & 64) {
+                strm->msg = (char *)"invalid distance code";
+                state->mode = BAD;
+                break;
+            }
+            state->offset = (unsigned)here.val;
+
+            /* get distance extra bits, if any */
+            state->extra = (unsigned)(here.op) & 15;
+            if (state->extra != 0) {
+                NEEDBITS(state->extra);
+                state->offset += BITS(state->extra);
+                DROPBITS(state->extra);
+            }
+            if (state->offset > state->wsize - (state->whave < state->wsize ?
+                                                left : 0)) {
+                strm->msg = (char *)"invalid distance too far back";
+                state->mode = BAD;
+                break;
+            }
+            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
+
+            /* copy match from window to output */
+            do {
+                ROOM();
+                copy = state->wsize - state->offset;
+                if (copy < left) {
+                    from = put + copy;
+                    copy = left - copy;
+                }
+                else {
+                    from = put - state->offset;
+                    copy = left;
+                }
+                if (copy > state->length) copy = state->length;
+                state->length -= copy;
+                left -= copy;
+                do {
+                    *put++ = *from++;
+                } while (--copy);
+            } while (state->length != 0);
+            break;
+
+        case DONE:
+            /* inflate stream terminated properly -- write leftover output */
+            ret = Z_STREAM_END;
+            if (left < state->wsize) {
+                if (out(out_desc, state->window, state->wsize - left))
+                    ret = Z_BUF_ERROR;
+            }
+            goto inf_leave;
+
+        case BAD:
+            ret = Z_DATA_ERROR;
+            goto inf_leave;
+
+        default:                /* can't happen, but makes compilers happy */
+            ret = Z_STREAM_ERROR;
+            goto inf_leave;
+        }
+
+    /* Return unused input */
+  inf_leave:
+    strm->next_in = next;
+    strm->avail_in = have;
+    return ret;
+}
+
+int ZEXPORT inflateBackEnd(strm)
+z_streamp strm;
+{
+    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
+        return Z_STREAM_ERROR;
+    ZFREE(strm, strm->state);
+    strm->state = Z_NULL;
+    Tracev((stderr, "inflate: end\n"));
+    return Z_OK;
+}
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/src/inffast.c
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/src/inffast.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/src/inffast.c	(revision 453)
@@ -0,0 +1,323 @@
+/* inffast.c -- fast decoding
+ * Copyright (C) 1995-2017 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifdef ASMINF
+#  pragma message("Assembler code may have bugs -- use at your own risk")
+#else
+
+/*
+   Decode literal, length, and distance codes and write out the resulting
+   literal and match bytes until either not enough input or output is
+   available, an end-of-block is encountered, or a data error is encountered.
+   When large enough input and output buffers are supplied to inflate(), for
+   example, a 16K input buffer and a 64K output buffer, more than 95% of the
+   inflate execution time is spent in this routine.
+
+   Entry assumptions:
+
+        state->mode == LEN
+        strm->avail_in >= 6
+        strm->avail_out >= 258
+        start >= strm->avail_out
+        state->bits < 8
+
+   On return, state->mode is one of:
+
+        LEN -- ran out of enough output space or enough available input
+        TYPE -- reached end of block code, inflate() to interpret next block
+        BAD -- error in block data
+
+   Notes:
+
+    - The maximum input bits used by a length/distance pair is 15 bits for the
+      length code, 5 bits for the length extra, 15 bits for the distance code,
+      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
+      Therefore if strm->avail_in >= 6, then there is enough input to avoid
+      checking for available input while decoding.
+
+    - The maximum bytes that a single length/distance pair can output is 258
+      bytes, which is the maximum length that can be coded.  inflate_fast()
+      requires strm->avail_out >= 258 for each loop to avoid checking for
+      output space.
+ */
+void ZLIB_INTERNAL inflate_fast(strm, start)
+z_streamp strm;
+unsigned start;         /* inflate()'s starting value for strm->avail_out */
+{
+    struct inflate_state FAR *state;
+    z_const unsigned char FAR *in;      /* local strm->next_in */
+    z_const unsigned char FAR *last;    /* have enough input while in < last */
+    unsigned char FAR *out;     /* local strm->next_out */
+    unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */
+    unsigned char FAR *end;     /* while out < end, enough space available */
+#ifdef INFLATE_STRICT
+    unsigned dmax;              /* maximum distance from zlib header */
+#endif
+    unsigned wsize;             /* window size or zero if not using window */
+    unsigned whave;             /* valid bytes in the window */
+    unsigned wnext;             /* window write index */
+    unsigned char FAR *window;  /* allocated sliding window, if wsize != 0 */
+    unsigned long hold;         /* local strm->hold */
+    unsigned bits;              /* local strm->bits */
+    code const FAR *lcode;      /* local strm->lencode */
+    code const FAR *dcode;      /* local strm->distcode */
+    unsigned lmask;             /* mask for first level of length codes */
+    unsigned dmask;             /* mask for first level of distance codes */
+    code here;                  /* retrieved table entry */
+    unsigned op;                /* code bits, operation, extra bits, or */
+                                /*  window position, window bytes to copy */
+    unsigned len;               /* match length, unused bytes */
+    unsigned dist;              /* match distance */
+    unsigned char FAR *from;    /* where to copy match from */
+
+    /* copy state to local variables */
+    state = (struct inflate_state FAR *)strm->state;
+    in = strm->next_in;
+    last = in + (strm->avail_in - 5);
+    out = strm->next_out;
+    beg = out - (start - strm->avail_out);
+    end = out + (strm->avail_out - 257);
+#ifdef INFLATE_STRICT
+    dmax = state->dmax;
+#endif
+    wsize = state->wsize;
+    whave = state->whave;
+    wnext = state->wnext;
+    window = state->window;
+    hold = state->hold;
+    bits = state->bits;
+    lcode = state->lencode;
+    dcode = state->distcode;
+    lmask = (1U << state->lenbits) - 1;
+    dmask = (1U << state->distbits) - 1;
+
+    /* decode literals and length/distances until end-of-block or not enough
+       input data or output space */
+    do {
+        if (bits < 15) {
+            hold += (unsigned long)(*in++) << bits;
+            bits += 8;
+            hold += (unsigned long)(*in++) << bits;
+            bits += 8;
+        }
+        here = lcode[hold & lmask];
+      dolen:
+        op = (unsigned)(here.bits);
+        hold >>= op;
+        bits -= op;
+        op = (unsigned)(here.op);
+        if (op == 0) {                          /* literal */
+            Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+                    "inflate:         literal '%c'\n" :
+                    "inflate:         literal 0x%02x\n", here.val));
+            *out++ = (unsigned char)(here.val);
+        }
+        else if (op & 16) {                     /* length base */
+            len = (unsigned)(here.val);
+            op &= 15;                           /* number of extra bits */
+            if (op) {
+                if (bits < op) {
+                    hold += (unsigned long)(*in++) << bits;
+                    bits += 8;
+                }
+                len += (unsigned)hold & ((1U << op) - 1);
+                hold >>= op;
+                bits -= op;
+            }
+            Tracevv((stderr, "inflate:         length %u\n", len));
+            if (bits < 15) {
+                hold += (unsigned long)(*in++) << bits;
+                bits += 8;
+                hold += (unsigned long)(*in++) << bits;
+                bits += 8;
+            }
+            here = dcode[hold & dmask];
+          dodist:
+            op = (unsigned)(here.bits);
+            hold >>= op;
+            bits -= op;
+            op = (unsigned)(here.op);
+            if (op & 16) {                      /* distance base */
+                dist = (unsigned)(here.val);
+                op &= 15;                       /* number of extra bits */
+                if (bits < op) {
+                    hold += (unsigned long)(*in++) << bits;
+                    bits += 8;
+                    if (bits < op) {
+                        hold += (unsigned long)(*in++) << bits;
+                        bits += 8;
+                    }
+                }
+                dist += (unsigned)hold & ((1U << op) - 1);
+#ifdef INFLATE_STRICT
+                if (dist > dmax) {
+                    strm->msg = (char *)"invalid distance too far back";
+                    state->mode = BAD;
+                    break;
+                }
+#endif
+                hold >>= op;
+                bits -= op;
+                Tracevv((stderr, "inflate:         distance %u\n", dist));
+                op = (unsigned)(out - beg);     /* max distance in output */
+                if (dist > op) {                /* see if copy from window */
+                    op = dist - op;             /* distance back in window */
+                    if (op > whave) {
+                        if (state->sane) {
+                            strm->msg =
+                                (char *)"invalid distance too far back";
+                            state->mode = BAD;
+                            break;
+                        }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+                        if (len <= op - whave) {
+                            do {
+                                *out++ = 0;
+                            } while (--len);
+                            continue;
+                        }
+                        len -= op - whave;
+                        do {
+                            *out++ = 0;
+                        } while (--op > whave);
+                        if (op == 0) {
+                            from = out - dist;
+                            do {
+                                *out++ = *from++;
+                            } while (--len);
+                            continue;
+                        }
+#endif
+                    }
+                    from = window;
+                    if (wnext == 0) {           /* very common case */
+                        from += wsize - op;
+                        if (op < len) {         /* some from window */
+                            len -= op;
+                            do {
+                                *out++ = *from++;
+                            } while (--op);
+                            from = out - dist;  /* rest from output */
+                        }
+                    }
+                    else if (wnext < op) {      /* wrap around window */
+                        from += wsize + wnext - op;
+                        op -= wnext;
+                        if (op < len) {         /* some from end of window */
+                            len -= op;
+                            do {
+                                *out++ = *from++;
+                            } while (--op);
+                            from = window;
+                            if (wnext < len) {  /* some from start of window */
+                                op = wnext;
+                                len -= op;
+                                do {
+                                    *out++ = *from++;
+                                } while (--op);
+                                from = out - dist;      /* rest from output */
+                            }
+                        }
+                    }
+                    else {                      /* contiguous in window */
+                        from += wnext - op;
+                        if (op < len) {         /* some from window */
+                            len -= op;
+                            do {
+                                *out++ = *from++;
+                            } while (--op);
+                            from = out - dist;  /* rest from output */
+                        }
+                    }
+                    while (len > 2) {
+                        *out++ = *from++;
+                        *out++ = *from++;
+                        *out++ = *from++;
+                        len -= 3;
+                    }
+                    if (len) {
+                        *out++ = *from++;
+                        if (len > 1)
+                            *out++ = *from++;
+                    }
+                }
+                else {
+                    from = out - dist;          /* copy direct from output */
+                    do {                        /* minimum length is three */
+                        *out++ = *from++;
+                        *out++ = *from++;
+                        *out++ = *from++;
+                        len -= 3;
+                    } while (len > 2);
+                    if (len) {
+                        *out++ = *from++;
+                        if (len > 1)
+                            *out++ = *from++;
+                    }
+                }
+            }
+            else if ((op & 64) == 0) {          /* 2nd level distance code */
+                here = dcode[here.val + (hold & ((1U << op) - 1))];
+                goto dodist;
+            }
+            else {
+                strm->msg = (char *)"invalid distance code";
+                state->mode = BAD;
+                break;
+            }
+        }
+        else if ((op & 64) == 0) {              /* 2nd level length code */
+            here = lcode[here.val + (hold & ((1U << op) - 1))];
+            goto dolen;
+        }
+        else if (op & 32) {                     /* end-of-block */
+            Tracevv((stderr, "inflate:         end of block\n"));
+            state->mode = TYPE;
+            break;
+        }
+        else {
+            strm->msg = (char *)"invalid literal/length code";
+            state->mode = BAD;
+            break;
+        }
+    } while (in < last && out < end);
+
+    /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+    len = bits >> 3;
+    in -= len;
+    bits -= len << 3;
+    hold &= (1U << bits) - 1;
+
+    /* update state and return */
+    strm->next_in = in;
+    strm->next_out = out;
+    strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
+    strm->avail_out = (unsigned)(out < end ?
+                                 257 + (end - out) : 257 - (out - end));
+    state->hold = hold;
+    state->bits = bits;
+    return;
+}
+
+/*
+   inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
+   - Using bit fields for code structure
+   - Different op definition to avoid & for extra bits (do & for table bits)
+   - Three separate decoding do-loops for direct, window, and wnext == 0
+   - Special case for distance > 1 copies to do overlapped load and store copy
+   - Explicit branch predictions (based on measured branch probabilities)
+   - Deferring match copy and interspersed it with decoding subsequent codes
+   - Swapping literal/length else
+   - Swapping window/direct else
+   - Larger unrolled copy loops (three is about right)
+   - Moving len -= 3 statement into middle of loop
+ */
+
+#endif /* !ASMINF */
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/src/inffast.h
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/src/inffast.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/src/inffast.h	(revision 453)
@@ -0,0 +1,11 @@
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995-2003, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start));
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/src/inffixed.h
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/src/inffixed.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/src/inffixed.h	(revision 453)
@@ -0,0 +1,94 @@
+    /* inffixed.h -- table for decoding fixed codes
+     * Generated automatically by makefixed().
+     */
+
+    /* WARNING: this file should *not* be used by applications.
+       It is part of the implementation of this library and is
+       subject to change. Applications should only use zlib.h.
+     */
+
+    static const code lenfix[512] = {
+        {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
+        {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
+        {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
+        {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
+        {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
+        {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
+        {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
+        {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
+        {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
+        {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
+        {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
+        {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
+        {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
+        {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
+        {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
+        {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
+        {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
+        {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
+        {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
+        {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
+        {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
+        {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
+        {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
+        {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
+        {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
+        {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
+        {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
+        {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
+        {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
+        {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
+        {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
+        {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
+        {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
+        {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
+        {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
+        {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
+        {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
+        {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
+        {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
+        {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
+        {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
+        {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
+        {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
+        {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
+        {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
+        {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
+        {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
+        {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
+        {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
+        {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
+        {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
+        {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
+        {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
+        {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
+        {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
+        {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
+        {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
+        {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
+        {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
+        {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
+        {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
+        {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
+        {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
+        {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
+        {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
+        {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
+        {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
+        {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
+        {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
+        {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
+        {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
+        {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
+        {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
+        {0,9,255}
+    };
+
+    static const code distfix[32] = {
+        {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
+        {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
+        {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
+        {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
+        {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
+        {22,5,193},{64,5,0}
+    };
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/src/inflate.c
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/src/inflate.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/src/inflate.c	(revision 453)
@@ -0,0 +1,1561 @@
+/* inflate.c -- zlib decompression
+ * Copyright (C) 1995-2016 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * Change history:
+ *
+ * 1.2.beta0    24 Nov 2002
+ * - First version -- complete rewrite of inflate to simplify code, avoid
+ *   creation of window when not needed, minimize use of window when it is
+ *   needed, make inffast.c even faster, implement gzip decoding, and to
+ *   improve code readability and style over the previous zlib inflate code
+ *
+ * 1.2.beta1    25 Nov 2002
+ * - Use pointers for available input and output checking in inffast.c
+ * - Remove input and output counters in inffast.c
+ * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
+ * - Remove unnecessary second byte pull from length extra in inffast.c
+ * - Unroll direct copy to three copies per loop in inffast.c
+ *
+ * 1.2.beta2    4 Dec 2002
+ * - Change external routine names to reduce potential conflicts
+ * - Correct filename to inffixed.h for fixed tables in inflate.c
+ * - Make hbuf[] unsigned char to match parameter type in inflate.c
+ * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
+ *   to avoid negation problem on Alphas (64 bit) in inflate.c
+ *
+ * 1.2.beta3    22 Dec 2002
+ * - Add comments on state->bits assertion in inffast.c
+ * - Add comments on op field in inftrees.h
+ * - Fix bug in reuse of allocated window after inflateReset()
+ * - Remove bit fields--back to byte structure for speed
+ * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
+ * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
+ * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
+ * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
+ * - Use local copies of stream next and avail values, as well as local bit
+ *   buffer and bit count in inflate()--for speed when inflate_fast() not used
+ *
+ * 1.2.beta4    1 Jan 2003
+ * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
+ * - Move a comment on output buffer sizes from inffast.c to inflate.c
+ * - Add comments in inffast.c to introduce the inflate_fast() routine
+ * - Rearrange window copies in inflate_fast() for speed and simplification
+ * - Unroll last copy for window match in inflate_fast()
+ * - Use local copies of window variables in inflate_fast() for speed
+ * - Pull out common wnext == 0 case for speed in inflate_fast()
+ * - Make op and len in inflate_fast() unsigned for consistency
+ * - Add FAR to lcode and dcode declarations in inflate_fast()
+ * - Simplified bad distance check in inflate_fast()
+ * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
+ *   source file infback.c to provide a call-back interface to inflate for
+ *   programs like gzip and unzip -- uses window as output buffer to avoid
+ *   window copying
+ *
+ * 1.2.beta5    1 Jan 2003
+ * - Improved inflateBack() interface to allow the caller to provide initial
+ *   input in strm.
+ * - Fixed stored blocks bug in inflateBack()
+ *
+ * 1.2.beta6    4 Jan 2003
+ * - Added comments in inffast.c on effectiveness of POSTINC
+ * - Typecasting all around to reduce compiler warnings
+ * - Changed loops from while (1) or do {} while (1) to for (;;), again to
+ *   make compilers happy
+ * - Changed type of window in inflateBackInit() to unsigned char *
+ *
+ * 1.2.beta7    27 Jan 2003
+ * - Changed many types to unsigned or unsigned short to avoid warnings
+ * - Added inflateCopy() function
+ *
+ * 1.2.0        9 Mar 2003
+ * - Changed inflateBack() interface to provide separate opaque descriptors
+ *   for the in() and out() functions
+ * - Changed inflateBack() argument and in_func typedef to swap the length
+ *   and buffer address return values for the input function
+ * - Check next_in and next_out for Z_NULL on entry to inflate()
+ *
+ * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifdef MAKEFIXED
+#  ifndef BUILDFIXED
+#    define BUILDFIXED
+#  endif
+#endif
+
+/* function prototypes */
+local int inflateStateCheck OF((z_streamp strm));
+local void fixedtables OF((struct inflate_state FAR *state));
+local int updatewindow OF((z_streamp strm, const unsigned char FAR *end,
+                           unsigned copy));
+#ifdef BUILDFIXED
+   void makefixed OF((void));
+#endif
+local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf,
+                              unsigned len));
+
+local int inflateStateCheck(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+    if (strm == Z_NULL ||
+        strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)
+        return 1;
+    state = (struct inflate_state FAR *)strm->state;
+    if (state == Z_NULL || state->strm != strm ||
+        state->mode < HEAD || state->mode > SYNC)
+        return 1;
+    return 0;
+}
+
+int ZEXPORT inflateResetKeep(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    strm->total_in = strm->total_out = state->total = 0;
+    strm->msg = Z_NULL;
+    if (state->wrap)        /* to support ill-conceived Java test suite */
+        strm->adler = state->wrap & 1;
+    state->mode = HEAD;
+    state->last = 0;
+    state->havedict = 0;
+    state->dmax = 32768U;
+    state->head = Z_NULL;
+    state->hold = 0;
+    state->bits = 0;
+    state->lencode = state->distcode = state->next = state->codes;
+    state->sane = 1;
+    state->back = -1;
+    Tracev((stderr, "inflate: reset\n"));
+    return Z_OK;
+}
+
+int ZEXPORT inflateReset(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    state->wsize = 0;
+    state->whave = 0;
+    state->wnext = 0;
+    return inflateResetKeep(strm);
+}
+
+int ZEXPORT inflateReset2(strm, windowBits)
+z_streamp strm;
+int windowBits;
+{
+    int wrap;
+    struct inflate_state FAR *state;
+
+    /* get the state */
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* extract wrap request from windowBits parameter */
+    if (windowBits < 0) {
+        wrap = 0;
+        windowBits = -windowBits;
+    }
+    else {
+        wrap = (windowBits >> 4) + 5;
+#ifdef GUNZIP
+        if (windowBits < 48)
+            windowBits &= 15;
+#endif
+    }
+
+    /* set number of window bits, free window if different */
+    if (windowBits && (windowBits < 8 || windowBits > 15))
+        return Z_STREAM_ERROR;
+    if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) {
+        ZFREE(strm, state->window);
+        state->window = Z_NULL;
+    }
+
+    /* update state and reset the rest of it */
+    state->wrap = wrap;
+    state->wbits = (unsigned)windowBits;
+    return inflateReset(strm);
+}
+
+int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
+z_streamp strm;
+int windowBits;
+const char *version;
+int stream_size;
+{
+    int ret;
+    struct inflate_state FAR *state;
+
+    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+        stream_size != (int)(sizeof(z_stream)))
+        return Z_VERSION_ERROR;
+    if (strm == Z_NULL) return Z_STREAM_ERROR;
+    strm->msg = Z_NULL;                 /* in case we return an error */
+    if (strm->zalloc == (alloc_func)0) {
+#ifdef Z_SOLO
+        return Z_STREAM_ERROR;
+#else
+        strm->zalloc = zcalloc;
+        strm->opaque = (voidpf)0;
+#endif
+    }
+    if (strm->zfree == (free_func)0)
+#ifdef Z_SOLO
+        return Z_STREAM_ERROR;
+#else
+        strm->zfree = zcfree;
+#endif
+    state = (struct inflate_state FAR *)
+            ZALLOC(strm, 1, sizeof(struct inflate_state));
+    if (state == Z_NULL) return Z_MEM_ERROR;
+    Tracev((stderr, "inflate: allocated\n"));
+    strm->state = (struct internal_state FAR *)state;
+    state->strm = strm;
+    state->window = Z_NULL;
+    state->mode = HEAD;     /* to pass state test in inflateReset2() */
+    ret = inflateReset2(strm, windowBits);
+    if (ret != Z_OK) {
+        ZFREE(strm, state);
+        strm->state = Z_NULL;
+    }
+    return ret;
+}
+
+int ZEXPORT inflateInit_(strm, version, stream_size)
+z_streamp strm;
+const char *version;
+int stream_size;
+{
+    return inflateInit2_(strm, DEF_WBITS, version, stream_size);
+}
+
+int ZEXPORT inflatePrime(strm, bits, value)
+z_streamp strm;
+int bits;
+int value;
+{
+    struct inflate_state FAR *state;
+
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (bits < 0) {
+        state->hold = 0;
+        state->bits = 0;
+        return Z_OK;
+    }
+    if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR;
+    value &= (1L << bits) - 1;
+    state->hold += (unsigned)value << state->bits;
+    state->bits += (uInt)bits;
+    return Z_OK;
+}
+
+/*
+   Return state with length and distance decoding tables and index sizes set to
+   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
+   If BUILDFIXED is defined, then instead this routine builds the tables the
+   first time it's called, and returns those tables the first time and
+   thereafter.  This reduces the size of the code by about 2K bytes, in
+   exchange for a little execution time.  However, BUILDFIXED should not be
+   used for threaded applications, since the rewriting of the tables and virgin
+   may not be thread-safe.
+ */
+local void fixedtables(state)
+struct inflate_state FAR *state;
+{
+#ifdef BUILDFIXED
+    static int virgin = 1;
+    static code *lenfix, *distfix;
+    static code fixed[544];
+
+    /* build fixed huffman tables if first call (may not be thread safe) */
+    if (virgin) {
+        unsigned sym, bits;
+        static code *next;
+
+        /* literal/length table */
+        sym = 0;
+        while (sym < 144) state->lens[sym++] = 8;
+        while (sym < 256) state->lens[sym++] = 9;
+        while (sym < 280) state->lens[sym++] = 7;
+        while (sym < 288) state->lens[sym++] = 8;
+        next = fixed;
+        lenfix = next;
+        bits = 9;
+        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+        /* distance table */
+        sym = 0;
+        while (sym < 32) state->lens[sym++] = 5;
+        distfix = next;
+        bits = 5;
+        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+        /* do this just once */
+        virgin = 0;
+    }
+#else /* !BUILDFIXED */
+#   include "inffixed.h"
+#endif /* BUILDFIXED */
+    state->lencode = lenfix;
+    state->lenbits = 9;
+    state->distcode = distfix;
+    state->distbits = 5;
+}
+
+#ifdef MAKEFIXED
+#include <stdio.h>
+
+/*
+   Write out the inffixed.h that is #include'd above.  Defining MAKEFIXED also
+   defines BUILDFIXED, so the tables are built on the fly.  makefixed() writes
+   those tables to stdout, which would be piped to inffixed.h.  A small program
+   can simply call makefixed to do this:
+
+    void makefixed(void);
+
+    int main(void)
+    {
+        makefixed();
+        return 0;
+    }
+
+   Then that can be linked with zlib built with MAKEFIXED defined and run:
+
+    a.out > inffixed.h
+ */
+void makefixed()
+{
+    unsigned low, size;
+    struct inflate_state state;
+
+    fixedtables(&state);
+    puts("    /* inffixed.h -- table for decoding fixed codes");
+    puts("     * Generated automatically by makefixed().");
+    puts("     */");
+    puts("");
+    puts("    /* WARNING: this file should *not* be used by applications.");
+    puts("       It is part of the implementation of this library and is");
+    puts("       subject to change. Applications should only use zlib.h.");
+    puts("     */");
+    puts("");
+    size = 1U << 9;
+    printf("    static const code lenfix[%u] = {", size);
+    low = 0;
+    for (;;) {
+        if ((low % 7) == 0) printf("\n        ");
+        printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op,
+               state.lencode[low].bits, state.lencode[low].val);
+        if (++low == size) break;
+        putchar(',');
+    }
+    puts("\n    };");
+    size = 1U << 5;
+    printf("\n    static const code distfix[%u] = {", size);
+    low = 0;
+    for (;;) {
+        if ((low % 6) == 0) printf("\n        ");
+        printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
+               state.distcode[low].val);
+        if (++low == size) break;
+        putchar(',');
+    }
+    puts("\n    };");
+}
+#endif /* MAKEFIXED */
+
+/*
+   Update the window with the last wsize (normally 32K) bytes written before
+   returning.  If window does not exist yet, create it.  This is only called
+   when a window is already in use, or when output has been written during this
+   inflate call, but the end of the deflate stream has not been reached yet.
+   It is also called to create a window for dictionary data when a dictionary
+   is loaded.
+
+   Providing output buffers larger than 32K to inflate() should provide a speed
+   advantage, since only the last 32K of output is copied to the sliding window
+   upon return from inflate(), and since all distances after the first 32K of
+   output will fall in the output data, making match copies simpler and faster.
+   The advantage may be dependent on the size of the processor's data caches.
+ */
+local int updatewindow(strm, end, copy)
+z_streamp strm;
+const Bytef *end;
+unsigned copy;
+{
+    struct inflate_state FAR *state;
+    unsigned dist;
+
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* if it hasn't been done already, allocate space for the window */
+    if (state->window == Z_NULL) {
+        state->window = (unsigned char FAR *)
+                        ZALLOC(strm, 1U << state->wbits,
+                               sizeof(unsigned char));
+        if (state->window == Z_NULL) return 1;
+    }
+
+    /* if window not in use yet, initialize */
+    if (state->wsize == 0) {
+        state->wsize = 1U << state->wbits;
+        state->wnext = 0;
+        state->whave = 0;
+    }
+
+    /* copy state->wsize or less output bytes into the circular window */
+    if (copy >= state->wsize) {
+        zmemcpy(state->window, end - state->wsize, state->wsize);
+        state->wnext = 0;
+        state->whave = state->wsize;
+    }
+    else {
+        dist = state->wsize - state->wnext;
+        if (dist > copy) dist = copy;
+        zmemcpy(state->window + state->wnext, end - copy, dist);
+        copy -= dist;
+        if (copy) {
+            zmemcpy(state->window, end - copy, copy);
+            state->wnext = copy;
+            state->whave = state->wsize;
+        }
+        else {
+            state->wnext += dist;
+            if (state->wnext == state->wsize) state->wnext = 0;
+            if (state->whave < state->wsize) state->whave += dist;
+        }
+    }
+    return 0;
+}
+
+/* Macros for inflate(): */
+
+/* check function to use adler32() for zlib or crc32() for gzip */
+#ifdef GUNZIP
+#  define UPDATE(check, buf, len) \
+    (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
+#else
+#  define UPDATE(check, buf, len) adler32(check, buf, len)
+#endif
+
+/* check macros for header crc */
+#ifdef GUNZIP
+#  define CRC2(check, word) \
+    do { \
+        hbuf[0] = (unsigned char)(word); \
+        hbuf[1] = (unsigned char)((word) >> 8); \
+        check = crc32(check, hbuf, 2); \
+    } while (0)
+
+#  define CRC4(check, word) \
+    do { \
+        hbuf[0] = (unsigned char)(word); \
+        hbuf[1] = (unsigned char)((word) >> 8); \
+        hbuf[2] = (unsigned char)((word) >> 16); \
+        hbuf[3] = (unsigned char)((word) >> 24); \
+        check = crc32(check, hbuf, 4); \
+    } while (0)
+#endif
+
+/* Load registers with state in inflate() for speed */
+#define LOAD() \
+    do { \
+        put = strm->next_out; \
+        left = strm->avail_out; \
+        next = strm->next_in; \
+        have = strm->avail_in; \
+        hold = state->hold; \
+        bits = state->bits; \
+    } while (0)
+
+/* Restore state from registers in inflate() */
+#define RESTORE() \
+    do { \
+        strm->next_out = put; \
+        strm->avail_out = left; \
+        strm->next_in = next; \
+        strm->avail_in = have; \
+        state->hold = hold; \
+        state->bits = bits; \
+    } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+    do { \
+        hold = 0; \
+        bits = 0; \
+    } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflate()
+   if there is no input available. */
+#define PULLBYTE() \
+    do { \
+        if (have == 0) goto inf_leave; \
+        have--; \
+        hold += (unsigned long)(*next++) << bits; \
+        bits += 8; \
+    } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator.  If there is
+   not enough available input to do that, then return from inflate(). */
+#define NEEDBITS(n) \
+    do { \
+        while (bits < (unsigned)(n)) \
+            PULLBYTE(); \
+    } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+    ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+    do { \
+        hold >>= (n); \
+        bits -= (unsigned)(n); \
+    } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+    do { \
+        hold >>= bits & 7; \
+        bits -= bits & 7; \
+    } while (0)
+
+/*
+   inflate() uses a state machine to process as much input data and generate as
+   much output data as possible before returning.  The state machine is
+   structured roughly as follows:
+
+    for (;;) switch (state) {
+    ...
+    case STATEn:
+        if (not enough input data or output space to make progress)
+            return;
+        ... make progress ...
+        state = STATEm;
+        break;
+    ...
+    }
+
+   so when inflate() is called again, the same case is attempted again, and
+   if the appropriate resources are provided, the machine proceeds to the
+   next state.  The NEEDBITS() macro is usually the way the state evaluates
+   whether it can proceed or should return.  NEEDBITS() does the return if
+   the requested bits are not available.  The typical use of the BITS macros
+   is:
+
+        NEEDBITS(n);
+        ... do something with BITS(n) ...
+        DROPBITS(n);
+
+   where NEEDBITS(n) either returns from inflate() if there isn't enough
+   input left to load n bits into the accumulator, or it continues.  BITS(n)
+   gives the low n bits in the accumulator.  When done, DROPBITS(n) drops
+   the low n bits off the accumulator.  INITBITS() clears the accumulator
+   and sets the number of available bits to zero.  BYTEBITS() discards just
+   enough bits to put the accumulator on a byte boundary.  After BYTEBITS()
+   and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
+
+   NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
+   if there is no input available.  The decoding of variable length codes uses
+   PULLBYTE() directly in order to pull just enough bytes to decode the next
+   code, and no more.
+
+   Some states loop until they get enough input, making sure that enough
+   state information is maintained to continue the loop where it left off
+   if NEEDBITS() returns in the loop.  For example, want, need, and keep
+   would all have to actually be part of the saved state in case NEEDBITS()
+   returns:
+
+    case STATEw:
+        while (want < need) {
+            NEEDBITS(n);
+            keep[want++] = BITS(n);
+            DROPBITS(n);
+        }
+        state = STATEx;
+    case STATEx:
+
+   As shown above, if the next state is also the next case, then the break
+   is omitted.
+
+   A state may also return if there is not enough output space available to
+   complete that state.  Those states are copying stored data, writing a
+   literal byte, and copying a matching string.
+
+   When returning, a "goto inf_leave" is used to update the total counters,
+   update the check value, and determine whether any progress has been made
+   during that inflate() call in order to return the proper return code.
+   Progress is defined as a change in either strm->avail_in or strm->avail_out.
+   When there is a window, goto inf_leave will update the window with the last
+   output written.  If a goto inf_leave occurs in the middle of decompression
+   and there is no window currently, goto inf_leave will create one and copy
+   output to the window for the next call of inflate().
+
+   In this implementation, the flush parameter of inflate() only affects the
+   return code (per zlib.h).  inflate() always writes as much as possible to
+   strm->next_out, given the space available and the provided input--the effect
+   documented in zlib.h of Z_SYNC_FLUSH.  Furthermore, inflate() always defers
+   the allocation of and copying into a sliding window until necessary, which
+   provides the effect documented in zlib.h for Z_FINISH when the entire input
+   stream available.  So the only thing the flush parameter actually does is:
+   when flush is set to Z_FINISH, inflate() cannot return Z_OK.  Instead it
+   will return Z_BUF_ERROR if it has not reached the end of the stream.
+ */
+
+int ZEXPORT inflate(strm, flush)
+z_streamp strm;
+int flush;
+{
+    struct inflate_state FAR *state;
+    z_const unsigned char FAR *next;    /* next input */
+    unsigned char FAR *put;     /* next output */
+    unsigned have, left;        /* available input and output */
+    unsigned long hold;         /* bit buffer */
+    unsigned bits;              /* bits in bit buffer */
+    unsigned in, out;           /* save starting available input and output */
+    unsigned copy;              /* number of stored or match bytes to copy */
+    unsigned char FAR *from;    /* where to copy match bytes from */
+    code here;                  /* current decoding table entry */
+    code last;                  /* parent table entry */
+    unsigned len;               /* length to copy for repeats, bits to drop */
+    int ret;                    /* return code */
+#ifdef GUNZIP
+    unsigned char hbuf[4];      /* buffer for gzip header crc calculation */
+#endif
+    static const unsigned short order[19] = /* permutation of code lengths */
+        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+    if (inflateStateCheck(strm) || strm->next_out == Z_NULL ||
+        (strm->next_in == Z_NULL && strm->avail_in != 0))
+        return Z_STREAM_ERROR;
+
+    state = (struct inflate_state FAR *)strm->state;
+    if (state->mode == TYPE) state->mode = TYPEDO;      /* skip check */
+    LOAD();
+    in = have;
+    out = left;
+    ret = Z_OK;
+    for (;;)
+        switch (state->mode) {
+        case HEAD:
+            if (state->wrap == 0) {
+                state->mode = TYPEDO;
+                break;
+            }
+            NEEDBITS(16);
+#ifdef GUNZIP
+            if ((state->wrap & 2) && hold == 0x8b1f) {  /* gzip header */
+                if (state->wbits == 0)
+                    state->wbits = 15;
+                state->check = crc32(0L, Z_NULL, 0);
+                CRC2(state->check, hold);
+                INITBITS();
+                state->mode = FLAGS;
+                break;
+            }
+            state->flags = 0;           /* expect zlib header */
+            if (state->head != Z_NULL)
+                state->head->done = -1;
+            if (!(state->wrap & 1) ||   /* check if zlib header allowed */
+#else
+            if (
+#endif
+                ((BITS(8) << 8) + (hold >> 8)) % 31) {
+                strm->msg = (char *)"incorrect header check";
+                state->mode = BAD;
+                break;
+            }
+            if (BITS(4) != Z_DEFLATED) {
+                strm->msg = (char *)"unknown compression method";
+                state->mode = BAD;
+                break;
+            }
+            DROPBITS(4);
+            len = BITS(4) + 8;
+            if (state->wbits == 0)
+                state->wbits = len;
+            if (len > 15 || len > state->wbits) {
+                strm->msg = (char *)"invalid window size";
+                state->mode = BAD;
+                break;
+            }
+            state->dmax = 1U << len;
+            Tracev((stderr, "inflate:   zlib header ok\n"));
+            strm->adler = state->check = adler32(0L, Z_NULL, 0);
+            state->mode = hold & 0x200 ? DICTID : TYPE;
+            INITBITS();
+            break;
+#ifdef GUNZIP
+        case FLAGS:
+            NEEDBITS(16);
+            state->flags = (int)(hold);
+            if ((state->flags & 0xff) != Z_DEFLATED) {
+                strm->msg = (char *)"unknown compression method";
+                state->mode = BAD;
+                break;
+            }
+            if (state->flags & 0xe000) {
+                strm->msg = (char *)"unknown header flags set";
+                state->mode = BAD;
+                break;
+            }
+            if (state->head != Z_NULL)
+                state->head->text = (int)((hold >> 8) & 1);
+            if ((state->flags & 0x0200) && (state->wrap & 4))
+                CRC2(state->check, hold);
+            INITBITS();
+            state->mode = TIME;
+        case TIME:
+            NEEDBITS(32);
+            if (state->head != Z_NULL)
+                state->head->time = hold;
+            if ((state->flags & 0x0200) && (state->wrap & 4))
+                CRC4(state->check, hold);
+            INITBITS();
+            state->mode = OS;
+        case OS:
+            NEEDBITS(16);
+            if (state->head != Z_NULL) {
+                state->head->xflags = (int)(hold & 0xff);
+                state->head->os = (int)(hold >> 8);
+            }
+            if ((state->flags & 0x0200) && (state->wrap & 4))
+                CRC2(state->check, hold);
+            INITBITS();
+            state->mode = EXLEN;
+        case EXLEN:
+            if (state->flags & 0x0400) {
+                NEEDBITS(16);
+                state->length = (unsigned)(hold);
+                if (state->head != Z_NULL)
+                    state->head->extra_len = (unsigned)hold;
+                if ((state->flags & 0x0200) && (state->wrap & 4))
+                    CRC2(state->check, hold);
+                INITBITS();
+            }
+            else if (state->head != Z_NULL)
+                state->head->extra = Z_NULL;
+            state->mode = EXTRA;
+        case EXTRA:
+            if (state->flags & 0x0400) {
+                copy = state->length;
+                if (copy > have) copy = have;
+                if (copy) {
+                    if (state->head != Z_NULL &&
+                        state->head->extra != Z_NULL) {
+                        len = state->head->extra_len - state->length;
+                        zmemcpy(state->head->extra + len, next,
+                                len + copy > state->head->extra_max ?
+                                state->head->extra_max - len : copy);
+                    }
+                    if ((state->flags & 0x0200) && (state->wrap & 4))
+                        state->check = crc32(state->check, next, copy);
+                    have -= copy;
+                    next += copy;
+                    state->length -= copy;
+                }
+                if (state->length) goto inf_leave;
+            }
+            state->length = 0;
+            state->mode = NAME;
+        case NAME:
+            if (state->flags & 0x0800) {
+                if (have == 0) goto inf_leave;
+                copy = 0;
+                do {
+                    len = (unsigned)(next[copy++]);
+                    if (state->head != Z_NULL &&
+                            state->head->name != Z_NULL &&
+                            state->length < state->head->name_max)
+                        state->head->name[state->length++] = (Bytef)len;
+                } while (len && copy < have);
+                if ((state->flags & 0x0200) && (state->wrap & 4))
+                    state->check = crc32(state->check, next, copy);
+                have -= copy;
+                next += copy;
+                if (len) goto inf_leave;
+            }
+            else if (state->head != Z_NULL)
+                state->head->name = Z_NULL;
+            state->length = 0;
+            state->mode = COMMENT;
+        case COMMENT:
+            if (state->flags & 0x1000) {
+                if (have == 0) goto inf_leave;
+                copy = 0;
+                do {
+                    len = (unsigned)(next[copy++]);
+                    if (state->head != Z_NULL &&
+                            state->head->comment != Z_NULL &&
+                            state->length < state->head->comm_max)
+                        state->head->comment[state->length++] = (Bytef)len;
+                } while (len && copy < have);
+                if ((state->flags & 0x0200) && (state->wrap & 4))
+                    state->check = crc32(state->check, next, copy);
+                have -= copy;
+                next += copy;
+                if (len) goto inf_leave;
+            }
+            else if (state->head != Z_NULL)
+                state->head->comment = Z_NULL;
+            state->mode = HCRC;
+        case HCRC:
+            if (state->flags & 0x0200) {
+                NEEDBITS(16);
+                if ((state->wrap & 4) && hold != (state->check & 0xffff)) {
+                    strm->msg = (char *)"header crc mismatch";
+                    state->mode = BAD;
+                    break;
+                }
+                INITBITS();
+            }
+            if (state->head != Z_NULL) {
+                state->head->hcrc = (int)((state->flags >> 9) & 1);
+                state->head->done = 1;
+            }
+            strm->adler = state->check = crc32(0L, Z_NULL, 0);
+            state->mode = TYPE;
+            break;
+#endif
+        case DICTID:
+            NEEDBITS(32);
+            strm->adler = state->check = ZSWAP32(hold);
+            INITBITS();
+            state->mode = DICT;
+        case DICT:
+            if (state->havedict == 0) {
+                RESTORE();
+                return Z_NEED_DICT;
+            }
+            strm->adler = state->check = adler32(0L, Z_NULL, 0);
+            state->mode = TYPE;
+        case TYPE:
+            if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
+        case TYPEDO:
+            if (state->last) {
+                BYTEBITS();
+                state->mode = CHECK;
+                break;
+            }
+            NEEDBITS(3);
+            state->last = BITS(1);
+            DROPBITS(1);
+            switch (BITS(2)) {
+            case 0:                             /* stored block */
+                Tracev((stderr, "inflate:     stored block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = STORED;
+                break;
+            case 1:                             /* fixed block */
+                fixedtables(state);
+                Tracev((stderr, "inflate:     fixed codes block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = LEN_;             /* decode codes */
+                if (flush == Z_TREES) {
+                    DROPBITS(2);
+                    goto inf_leave;
+                }
+                break;
+            case 2:                             /* dynamic block */
+                Tracev((stderr, "inflate:     dynamic codes block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = TABLE;
+                break;
+            case 3:
+                strm->msg = (char *)"invalid block type";
+                state->mode = BAD;
+            }
+            DROPBITS(2);
+            break;
+        case STORED:
+            BYTEBITS();                         /* go to byte boundary */
+            NEEDBITS(32);
+            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+                strm->msg = (char *)"invalid stored block lengths";
+                state->mode = BAD;
+                break;
+            }
+            state->length = (unsigned)hold & 0xffff;
+            Tracev((stderr, "inflate:       stored length %u\n",
+                    state->length));
+            INITBITS();
+            state->mode = COPY_;
+            if (flush == Z_TREES) goto inf_leave;
+        case COPY_:
+            state->mode = COPY;
+        case COPY:
+            copy = state->length;
+            if (copy) {
+                if (copy > have) copy = have;
+                if (copy > left) copy = left;
+                if (copy == 0) goto inf_leave;
+                zmemcpy(put, next, copy);
+                have -= copy;
+                next += copy;
+                left -= copy;
+                put += copy;
+                state->length -= copy;
+                break;
+            }
+            Tracev((stderr, "inflate:       stored end\n"));
+            state->mode = TYPE;
+            break;
+        case TABLE:
+            NEEDBITS(14);
+            state->nlen = BITS(5) + 257;
+            DROPBITS(5);
+            state->ndist = BITS(5) + 1;
+            DROPBITS(5);
+            state->ncode = BITS(4) + 4;
+            DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+            if (state->nlen > 286 || state->ndist > 30) {
+                strm->msg = (char *)"too many length or distance symbols";
+                state->mode = BAD;
+                break;
+            }
+#endif
+            Tracev((stderr, "inflate:       table sizes ok\n"));
+            state->have = 0;
+            state->mode = LENLENS;
+        case LENLENS:
+            while (state->have < state->ncode) {
+                NEEDBITS(3);
+                state->lens[order[state->have++]] = (unsigned short)BITS(3);
+                DROPBITS(3);
+            }
+            while (state->have < 19)
+                state->lens[order[state->have++]] = 0;
+            state->next = state->codes;
+            state->lencode = (const code FAR *)(state->next);
+            state->lenbits = 7;
+            ret = inflate_table(CODES, state->lens, 19, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid code lengths set";
+                state->mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       code lengths ok\n"));
+            state->have = 0;
+            state->mode = CODELENS;
+        case CODELENS:
+            while (state->have < state->nlen + state->ndist) {
+                for (;;) {
+                    here = state->lencode[BITS(state->lenbits)];
+                    if ((unsigned)(here.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                if (here.val < 16) {
+                    DROPBITS(here.bits);
+                    state->lens[state->have++] = here.val;
+                }
+                else {
+                    if (here.val == 16) {
+                        NEEDBITS(here.bits + 2);
+                        DROPBITS(here.bits);
+                        if (state->have == 0) {
+                            strm->msg = (char *)"invalid bit length repeat";
+                            state->mode = BAD;
+                            break;
+                        }
+                        len = state->lens[state->have - 1];
+                        copy = 3 + BITS(2);
+                        DROPBITS(2);
+                    }
+                    else if (here.val == 17) {
+                        NEEDBITS(here.bits + 3);
+                        DROPBITS(here.bits);
+                        len = 0;
+                        copy = 3 + BITS(3);
+                        DROPBITS(3);
+                    }
+                    else {
+                        NEEDBITS(here.bits + 7);
+                        DROPBITS(here.bits);
+                        len = 0;
+                        copy = 11 + BITS(7);
+                        DROPBITS(7);
+                    }
+                    if (state->have + copy > state->nlen + state->ndist) {
+                        strm->msg = (char *)"invalid bit length repeat";
+                        state->mode = BAD;
+                        break;
+                    }
+                    while (copy--)
+                        state->lens[state->have++] = (unsigned short)len;
+                }
+            }
+
+            /* handle error breaks in while */
+            if (state->mode == BAD) break;
+
+            /* check for end-of-block code (better have one) */
+            if (state->lens[256] == 0) {
+                strm->msg = (char *)"invalid code -- missing end-of-block";
+                state->mode = BAD;
+                break;
+            }
+
+            /* build code tables -- note: do not change the lenbits or distbits
+               values here (9 and 6) without reading the comments in inftrees.h
+               concerning the ENOUGH constants, which depend on those values */
+            state->next = state->codes;
+            state->lencode = (const code FAR *)(state->next);
+            state->lenbits = 9;
+            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid literal/lengths set";
+                state->mode = BAD;
+                break;
+            }
+            state->distcode = (const code FAR *)(state->next);
+            state->distbits = 6;
+            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+                            &(state->next), &(state->distbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid distances set";
+                state->mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       codes ok\n"));
+            state->mode = LEN_;
+            if (flush == Z_TREES) goto inf_leave;
+        case LEN_:
+            state->mode = LEN;
+        case LEN:
+            if (have >= 6 && left >= 258) {
+                RESTORE();
+                inflate_fast(strm, out);
+                LOAD();
+                if (state->mode == TYPE)
+                    state->back = -1;
+                break;
+            }
+            state->back = 0;
+            for (;;) {
+                here = state->lencode[BITS(state->lenbits)];
+                if ((unsigned)(here.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if (here.op && (here.op & 0xf0) == 0) {
+                last = here;
+                for (;;) {
+                    here = state->lencode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + here.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+                state->back += last.bits;
+            }
+            DROPBITS(here.bits);
+            state->back += here.bits;
+            state->length = (unsigned)here.val;
+            if ((int)(here.op) == 0) {
+                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+                        "inflate:         literal '%c'\n" :
+                        "inflate:         literal 0x%02x\n", here.val));
+                state->mode = LIT;
+                break;
+            }
+            if (here.op & 32) {
+                Tracevv((stderr, "inflate:         end of block\n"));
+                state->back = -1;
+                state->mode = TYPE;
+                break;
+            }
+            if (here.op & 64) {
+                strm->msg = (char *)"invalid literal/length code";
+                state->mode = BAD;
+                break;
+            }
+            state->extra = (unsigned)(here.op) & 15;
+            state->mode = LENEXT;
+        case LENEXT:
+            if (state->extra) {
+                NEEDBITS(state->extra);
+                state->length += BITS(state->extra);
+                DROPBITS(state->extra);
+                state->back += state->extra;
+            }
+            Tracevv((stderr, "inflate:         length %u\n", state->length));
+            state->was = state->length;
+            state->mode = DIST;
+        case DIST:
+            for (;;) {
+                here = state->distcode[BITS(state->distbits)];
+                if ((unsigned)(here.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if ((here.op & 0xf0) == 0) {
+                last = here;
+                for (;;) {
+                    here = state->distcode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + here.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+                state->back += last.bits;
+            }
+            DROPBITS(here.bits);
+            state->back += here.bits;
+            if (here.op & 64) {
+                strm->msg = (char *)"invalid distance code";
+                state->mode = BAD;
+                break;
+            }
+            state->offset = (unsigned)here.val;
+            state->extra = (unsigned)(here.op) & 15;
+            state->mode = DISTEXT;
+        case DISTEXT:
+            if (state->extra) {
+                NEEDBITS(state->extra);
+                state->offset += BITS(state->extra);
+                DROPBITS(state->extra);
+                state->back += state->extra;
+            }
+#ifdef INFLATE_STRICT
+            if (state->offset > state->dmax) {
+                strm->msg = (char *)"invalid distance too far back";
+                state->mode = BAD;
+                break;
+            }
+#endif
+            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
+            state->mode = MATCH;
+        case MATCH:
+            if (left == 0) goto inf_leave;
+            copy = out - left;
+            if (state->offset > copy) {         /* copy from window */
+                copy = state->offset - copy;
+                if (copy > state->whave) {
+                    if (state->sane) {
+                        strm->msg = (char *)"invalid distance too far back";
+                        state->mode = BAD;
+                        break;
+                    }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+                    Trace((stderr, "inflate.c too far\n"));
+                    copy -= state->whave;
+                    if (copy > state->length) copy = state->length;
+                    if (copy > left) copy = left;
+                    left -= copy;
+                    state->length -= copy;
+                    do {
+                        *put++ = 0;
+                    } while (--copy);
+                    if (state->length == 0) state->mode = LEN;
+                    break;
+#endif
+                }
+                if (copy > state->wnext) {
+                    copy -= state->wnext;
+                    from = state->window + (state->wsize - copy);
+                }
+                else
+                    from = state->window + (state->wnext - copy);
+                if (copy > state->length) copy = state->length;
+            }
+            else {                              /* copy from output */
+                from = put - state->offset;
+                copy = state->length;
+            }
+            if (copy > left) copy = left;
+            left -= copy;
+            state->length -= copy;
+            do {
+                *put++ = *from++;
+            } while (--copy);
+            if (state->length == 0) state->mode = LEN;
+            break;
+        case LIT:
+            if (left == 0) goto inf_leave;
+            *put++ = (unsigned char)(state->length);
+            left--;
+            state->mode = LEN;
+            break;
+        case CHECK:
+            if (state->wrap) {
+                NEEDBITS(32);
+                out -= left;
+                strm->total_out += out;
+                state->total += out;
+                if ((state->wrap & 4) && out)
+                    strm->adler = state->check =
+                        UPDATE(state->check, put - out, out);
+                out = left;
+                if ((state->wrap & 4) && (
+#ifdef GUNZIP
+                     state->flags ? hold :
+#endif
+                     ZSWAP32(hold)) != state->check) {
+                    strm->msg = (char *)"incorrect data check";
+                    state->mode = BAD;
+                    break;
+                }
+                INITBITS();
+                Tracev((stderr, "inflate:   check matches trailer\n"));
+            }
+#ifdef GUNZIP
+            state->mode = LENGTH;
+        case LENGTH:
+            if (state->wrap && state->flags) {
+                NEEDBITS(32);
+                if (hold != (state->total & 0xffffffffUL)) {
+                    strm->msg = (char *)"incorrect length check";
+                    state->mode = BAD;
+                    break;
+                }
+                INITBITS();
+                Tracev((stderr, "inflate:   length matches trailer\n"));
+            }
+#endif
+            state->mode = DONE;
+        case DONE:
+            ret = Z_STREAM_END;
+            goto inf_leave;
+        case BAD:
+            ret = Z_DATA_ERROR;
+            goto inf_leave;
+        case MEM:
+            return Z_MEM_ERROR;
+        case SYNC:
+        default:
+            return Z_STREAM_ERROR;
+        }
+
+    /*
+       Return from inflate(), updating the total counts and the check value.
+       If there was no progress during the inflate() call, return a buffer
+       error.  Call updatewindow() to create and/or update the window state.
+       Note: a memory error from inflate() is non-recoverable.
+     */
+  inf_leave:
+    RESTORE();
+    if (state->wsize || (out != strm->avail_out && state->mode < BAD &&
+            (state->mode < CHECK || flush != Z_FINISH)))
+        if (updatewindow(strm, strm->next_out, out - strm->avail_out)) {
+            state->mode = MEM;
+            return Z_MEM_ERROR;
+        }
+    in -= strm->avail_in;
+    out -= strm->avail_out;
+    strm->total_in += in;
+    strm->total_out += out;
+    state->total += out;
+    if ((state->wrap & 4) && out)
+        strm->adler = state->check =
+            UPDATE(state->check, strm->next_out - out, out);
+    strm->data_type = (int)state->bits + (state->last ? 64 : 0) +
+                      (state->mode == TYPE ? 128 : 0) +
+                      (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
+    if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
+        ret = Z_BUF_ERROR;
+    return ret;
+}
+
+int ZEXPORT inflateEnd(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+    if (inflateStateCheck(strm))
+        return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (state->window != Z_NULL) ZFREE(strm, state->window);
+    ZFREE(strm, strm->state);
+    strm->state = Z_NULL;
+    Tracev((stderr, "inflate: end\n"));
+    return Z_OK;
+}
+
+int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength)
+z_streamp strm;
+Bytef *dictionary;
+uInt *dictLength;
+{
+    struct inflate_state FAR *state;
+
+    /* check state */
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* copy dictionary */
+    if (state->whave && dictionary != Z_NULL) {
+        zmemcpy(dictionary, state->window + state->wnext,
+                state->whave - state->wnext);
+        zmemcpy(dictionary + state->whave - state->wnext,
+                state->window, state->wnext);
+    }
+    if (dictLength != Z_NULL)
+        *dictLength = state->whave;
+    return Z_OK;
+}
+
+int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
+z_streamp strm;
+const Bytef *dictionary;
+uInt dictLength;
+{
+    struct inflate_state FAR *state;
+    unsigned long dictid;
+    int ret;
+
+    /* check state */
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (state->wrap != 0 && state->mode != DICT)
+        return Z_STREAM_ERROR;
+
+    /* check for correct dictionary identifier */
+    if (state->mode == DICT) {
+        dictid = adler32(0L, Z_NULL, 0);
+        dictid = adler32(dictid, dictionary, dictLength);
+        if (dictid != state->check)
+            return Z_DATA_ERROR;
+    }
+
+    /* copy dictionary to window using updatewindow(), which will amend the
+       existing dictionary if appropriate */
+    ret = updatewindow(strm, dictionary + dictLength, dictLength);
+    if (ret) {
+        state->mode = MEM;
+        return Z_MEM_ERROR;
+    }
+    state->havedict = 1;
+    Tracev((stderr, "inflate:   dictionary set\n"));
+    return Z_OK;
+}
+
+int ZEXPORT inflateGetHeader(strm, head)
+z_streamp strm;
+gz_headerp head;
+{
+    struct inflate_state FAR *state;
+
+    /* check state */
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
+
+    /* save header structure */
+    state->head = head;
+    head->done = 0;
+    return Z_OK;
+}
+
+/*
+   Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff.  Return when found
+   or when out of input.  When called, *have is the number of pattern bytes
+   found in order so far, in 0..3.  On return *have is updated to the new
+   state.  If on return *have equals four, then the pattern was found and the
+   return value is how many bytes were read including the last byte of the
+   pattern.  If *have is less than four, then the pattern has not been found
+   yet and the return value is len.  In the latter case, syncsearch() can be
+   called again with more data and the *have state.  *have is initialized to
+   zero for the first call.
+ */
+local unsigned syncsearch(have, buf, len)
+unsigned FAR *have;
+const unsigned char FAR *buf;
+unsigned len;
+{
+    unsigned got;
+    unsigned next;
+
+    got = *have;
+    next = 0;
+    while (next < len && got < 4) {
+        if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
+            got++;
+        else if (buf[next])
+            got = 0;
+        else
+            got = 4 - got;
+        next++;
+    }
+    *have = got;
+    return next;
+}
+
+int ZEXPORT inflateSync(strm)
+z_streamp strm;
+{
+    unsigned len;               /* number of bytes to look at or looked at */
+    unsigned long in, out;      /* temporary to save total_in and total_out */
+    unsigned char buf[4];       /* to restore bit buffer to byte string */
+    struct inflate_state FAR *state;
+
+    /* check parameters */
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
+
+    /* if first time, start search in bit buffer */
+    if (state->mode != SYNC) {
+        state->mode = SYNC;
+        state->hold <<= state->bits & 7;
+        state->bits -= state->bits & 7;
+        len = 0;
+        while (state->bits >= 8) {
+            buf[len++] = (unsigned char)(state->hold);
+            state->hold >>= 8;
+            state->bits -= 8;
+        }
+        state->have = 0;
+        syncsearch(&(state->have), buf, len);
+    }
+
+    /* search available input */
+    len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
+    strm->avail_in -= len;
+    strm->next_in += len;
+    strm->total_in += len;
+
+    /* return no joy or set up to restart inflate() on a new block */
+    if (state->have != 4) return Z_DATA_ERROR;
+    in = strm->total_in;  out = strm->total_out;
+    inflateReset(strm);
+    strm->total_in = in;  strm->total_out = out;
+    state->mode = TYPE;
+    return Z_OK;
+}
+
+/*
+   Returns true if inflate is currently at the end of a block generated by
+   Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+   implementation to provide an additional safety check. PPP uses
+   Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
+   block. When decompressing, PPP checks that at the end of input packet,
+   inflate is waiting for these length bytes.
+ */
+int ZEXPORT inflateSyncPoint(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    return state->mode == STORED && state->bits == 0;
+}
+
+int ZEXPORT inflateCopy(dest, source)
+z_streamp dest;
+z_streamp source;
+{
+    struct inflate_state FAR *state;
+    struct inflate_state FAR *copy;
+    unsigned char FAR *window;
+    unsigned wsize;
+
+    /* check input */
+    if (inflateStateCheck(source) || dest == Z_NULL)
+        return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)source->state;
+
+    /* allocate space */
+    copy = (struct inflate_state FAR *)
+           ZALLOC(source, 1, sizeof(struct inflate_state));
+    if (copy == Z_NULL) return Z_MEM_ERROR;
+    window = Z_NULL;
+    if (state->window != Z_NULL) {
+        window = (unsigned char FAR *)
+                 ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
+        if (window == Z_NULL) {
+            ZFREE(source, copy);
+            return Z_MEM_ERROR;
+        }
+    }
+
+    /* copy state */
+    zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
+    zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));
+    copy->strm = dest;
+    if (state->lencode >= state->codes &&
+        state->lencode <= state->codes + ENOUGH - 1) {
+        copy->lencode = copy->codes + (state->lencode - state->codes);
+        copy->distcode = copy->codes + (state->distcode - state->codes);
+    }
+    copy->next = copy->codes + (state->next - state->codes);
+    if (window != Z_NULL) {
+        wsize = 1U << state->wbits;
+        zmemcpy(window, state->window, wsize);
+    }
+    copy->window = window;
+    dest->state = (struct internal_state FAR *)copy;
+    return Z_OK;
+}
+
+int ZEXPORT inflateUndermine(strm, subvert)
+z_streamp strm;
+int subvert;
+{
+    struct inflate_state FAR *state;
+
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+    state->sane = !subvert;
+    return Z_OK;
+#else
+    (void)subvert;
+    state->sane = 1;
+    return Z_DATA_ERROR;
+#endif
+}
+
+int ZEXPORT inflateValidate(strm, check)
+z_streamp strm;
+int check;
+{
+    struct inflate_state FAR *state;
+
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (check)
+        state->wrap |= 4;
+    else
+        state->wrap &= ~4;
+    return Z_OK;
+}
+
+long ZEXPORT inflateMark(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+
+    if (inflateStateCheck(strm))
+        return -(1L << 16);
+    state = (struct inflate_state FAR *)strm->state;
+    return (long)(((unsigned long)((long)state->back)) << 16) +
+        (state->mode == COPY ? state->length :
+            (state->mode == MATCH ? state->was - state->length : 0));
+}
+
+unsigned long ZEXPORT inflateCodesUsed(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+    if (inflateStateCheck(strm)) return (unsigned long)-1;
+    state = (struct inflate_state FAR *)strm->state;
+    return (unsigned long)(state->next - state->codes);
+}
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/src/inflate.h
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/src/inflate.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/src/inflate.h	(revision 453)
@@ -0,0 +1,125 @@
+/* inflate.h -- internal inflate state definition
+ * Copyright (C) 1995-2016 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+   trailer decoding by inflate().  NO_GZIP would be used to avoid linking in
+   the crc code when it is not needed.  For shared libraries, gzip decoding
+   should be left enabled. */
+#ifndef NO_GZIP
+#  define GUNZIP
+#endif
+
+/* Possible inflate modes between inflate() calls */
+typedef enum {
+    HEAD = 16180,   /* i: waiting for magic header */
+    FLAGS,      /* i: waiting for method and flags (gzip) */
+    TIME,       /* i: waiting for modification time (gzip) */
+    OS,         /* i: waiting for extra flags and operating system (gzip) */
+    EXLEN,      /* i: waiting for extra length (gzip) */
+    EXTRA,      /* i: waiting for extra bytes (gzip) */
+    NAME,       /* i: waiting for end of file name (gzip) */
+    COMMENT,    /* i: waiting for end of comment (gzip) */
+    HCRC,       /* i: waiting for header crc (gzip) */
+    DICTID,     /* i: waiting for dictionary check value */
+    DICT,       /* waiting for inflateSetDictionary() call */
+        TYPE,       /* i: waiting for type bits, including last-flag bit */
+        TYPEDO,     /* i: same, but skip check to exit inflate on new block */
+        STORED,     /* i: waiting for stored size (length and complement) */
+        COPY_,      /* i/o: same as COPY below, but only first time in */
+        COPY,       /* i/o: waiting for input or output to copy stored block */
+        TABLE,      /* i: waiting for dynamic block table lengths */
+        LENLENS,    /* i: waiting for code length code lengths */
+        CODELENS,   /* i: waiting for length/lit and distance code lengths */
+            LEN_,       /* i: same as LEN below, but only first time in */
+            LEN,        /* i: waiting for length/lit/eob code */
+            LENEXT,     /* i: waiting for length extra bits */
+            DIST,       /* i: waiting for distance code */
+            DISTEXT,    /* i: waiting for distance extra bits */
+            MATCH,      /* o: waiting for output space to copy string */
+            LIT,        /* o: waiting for output space to write literal */
+    CHECK,      /* i: waiting for 32-bit check value */
+    LENGTH,     /* i: waiting for 32-bit length (gzip) */
+    DONE,       /* finished check, done -- remain here until reset */
+    BAD,        /* got a data error -- remain here until reset */
+    MEM,        /* got an inflate() memory error -- remain here until reset */
+    SYNC        /* looking for synchronization bytes to restart inflate() */
+} inflate_mode;
+
+/*
+    State transitions between above modes -
+
+    (most modes can go to BAD or MEM on error -- not shown for clarity)
+
+    Process header:
+        HEAD -> (gzip) or (zlib) or (raw)
+        (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT ->
+                  HCRC -> TYPE
+        (zlib) -> DICTID or TYPE
+        DICTID -> DICT -> TYPE
+        (raw) -> TYPEDO
+    Read deflate blocks:
+            TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK
+            STORED -> COPY_ -> COPY -> TYPE
+            TABLE -> LENLENS -> CODELENS -> LEN_
+            LEN_ -> LEN
+    Read deflate codes in fixed or dynamic block:
+                LEN -> LENEXT or LIT or TYPE
+                LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
+                LIT -> LEN
+    Process trailer:
+        CHECK -> LENGTH -> DONE
+ */
+
+/* State maintained between inflate() calls -- approximately 7K bytes, not
+   including the allocated sliding window, which is up to 32K bytes. */
+struct inflate_state {
+    z_streamp strm;             /* pointer back to this zlib stream */
+    inflate_mode mode;          /* current inflate mode */
+    int last;                   /* true if processing last block */
+    int wrap;                   /* bit 0 true for zlib, bit 1 true for gzip,
+                                   bit 2 true to validate check value */
+    int havedict;               /* true if dictionary provided */
+    int flags;                  /* gzip header method and flags (0 if zlib) */
+    unsigned dmax;              /* zlib header max distance (INFLATE_STRICT) */
+    unsigned long check;        /* protected copy of check value */
+    unsigned long total;        /* protected copy of output count */
+    gz_headerp head;            /* where to save gzip header information */
+        /* sliding window */
+    unsigned wbits;             /* log base 2 of requested window size */
+    unsigned wsize;             /* window size or zero if not using window */
+    unsigned whave;             /* valid bytes in the window */
+    unsigned wnext;             /* window write index */
+    unsigned char FAR *window;  /* allocated sliding window, if needed */
+        /* bit accumulator */
+    unsigned long hold;         /* input bit accumulator */
+    unsigned bits;              /* number of bits in "in" */
+        /* for string and stored block copying */
+    unsigned length;            /* literal or length of data to copy */
+    unsigned offset;            /* distance back to copy string from */
+        /* for table and code decoding */
+    unsigned extra;             /* extra bits needed */
+        /* fixed and dynamic code tables */
+    code const FAR *lencode;    /* starting table for length/literal codes */
+    code const FAR *distcode;   /* starting table for distance codes */
+    unsigned lenbits;           /* index bits for lencode */
+    unsigned distbits;          /* index bits for distcode */
+        /* dynamic table building */
+    unsigned ncode;             /* number of code length code lengths */
+    unsigned nlen;              /* number of length code lengths */
+    unsigned ndist;             /* number of distance code lengths */
+    unsigned have;              /* number of code lengths in lens[] */
+    code FAR *next;             /* next available space in codes[] */
+    unsigned short lens[320];   /* temporary storage for code lengths */
+    unsigned short work[288];   /* work area for code table building */
+    code codes[ENOUGH];         /* space for code tables */
+    int sane;                   /* if false, allow invalid distance too far */
+    int back;                   /* bits back of last unprocessed length/lit */
+    unsigned was;               /* initial length of match */
+};
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/src/inftrees.c
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/src/inftrees.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/src/inftrees.c	(revision 453)
@@ -0,0 +1,304 @@
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-2017 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+
+#define MAXBITS 15
+
+const char inflate_copyright[] =
+   " inflate 1.2.11 Copyright 1995-2017 Mark Adler ";
+/*
+  If you use the zlib library in a product, an acknowledgment is welcome
+  in the documentation of your product. If for some reason you cannot
+  include such an acknowledgment, I would appreciate that you keep this
+  copyright string in the executable of your product.
+ */
+
+/*
+   Build a set of tables to decode the provided canonical Huffman code.
+   The code lengths are lens[0..codes-1].  The result starts at *table,
+   whose indices are 0..2^bits-1.  work is a writable array of at least
+   lens shorts, which is used as a work area.  type is the type of code
+   to be generated, CODES, LENS, or DISTS.  On return, zero is success,
+   -1 is an invalid code, and +1 means that ENOUGH isn't enough.  table
+   on return points to the next available entry's address.  bits is the
+   requested root table index bits, and on return it is the actual root
+   table index bits.  It will differ if the request is greater than the
+   longest code or if it is less than the shortest code.
+ */
+int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work)
+codetype type;
+unsigned short FAR *lens;
+unsigned codes;
+code FAR * FAR *table;
+unsigned FAR *bits;
+unsigned short FAR *work;
+{
+    unsigned len;               /* a code's length in bits */
+    unsigned sym;               /* index of code symbols */
+    unsigned min, max;          /* minimum and maximum code lengths */
+    unsigned root;              /* number of index bits for root table */
+    unsigned curr;              /* number of index bits for current table */
+    unsigned drop;              /* code bits to drop for sub-table */
+    int left;                   /* number of prefix codes available */
+    unsigned used;              /* code entries in table used */
+    unsigned huff;              /* Huffman code */
+    unsigned incr;              /* for incrementing code, index */
+    unsigned fill;              /* index for replicating entries */
+    unsigned low;               /* low bits for current root entry */
+    unsigned mask;              /* mask for low root bits */
+    code here;                  /* table entry for duplication */
+    code FAR *next;             /* next available space in table */
+    const unsigned short FAR *base;     /* base value table to use */
+    const unsigned short FAR *extra;    /* extra bits table to use */
+    unsigned match;             /* use base and extra for symbol >= match */
+    unsigned short count[MAXBITS+1];    /* number of codes of each length */
+    unsigned short offs[MAXBITS+1];     /* offsets in table for each length */
+    static const unsigned short lbase[31] = { /* Length codes 257..285 base */
+        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+    static const unsigned short lext[31] = { /* Length codes 257..285 extra */
+        16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
+        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 77, 202};
+    static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
+        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+        8193, 12289, 16385, 24577, 0, 0};
+    static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
+        16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
+        23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
+        28, 28, 29, 29, 64, 64};
+
+    /*
+       Process a set of code lengths to create a canonical Huffman code.  The
+       code lengths are lens[0..codes-1].  Each length corresponds to the
+       symbols 0..codes-1.  The Huffman code is generated by first sorting the
+       symbols by length from short to long, and retaining the symbol order
+       for codes with equal lengths.  Then the code starts with all zero bits
+       for the first code of the shortest length, and the codes are integer
+       increments for the same length, and zeros are appended as the length
+       increases.  For the deflate format, these bits are stored backwards
+       from their more natural integer increment ordering, and so when the
+       decoding tables are built in the large loop below, the integer codes
+       are incremented backwards.
+
+       This routine assumes, but does not check, that all of the entries in
+       lens[] are in the range 0..MAXBITS.  The caller must assure this.
+       1..MAXBITS is interpreted as that code length.  zero means that that
+       symbol does not occur in this code.
+
+       The codes are sorted by computing a count of codes for each length,
+       creating from that a table of starting indices for each length in the
+       sorted table, and then entering the symbols in order in the sorted
+       table.  The sorted table is work[], with that space being provided by
+       the caller.
+
+       The length counts are used for other purposes as well, i.e. finding
+       the minimum and maximum length codes, determining if there are any
+       codes at all, checking for a valid set of lengths, and looking ahead
+       at length counts to determine sub-table sizes when building the
+       decoding tables.
+     */
+
+    /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
+    for (len = 0; len <= MAXBITS; len++)
+        count[len] = 0;
+    for (sym = 0; sym < codes; sym++)
+        count[lens[sym]]++;
+
+    /* bound code lengths, force root to be within code lengths */
+    root = *bits;
+    for (max = MAXBITS; max >= 1; max--)
+        if (count[max] != 0) break;
+    if (root > max) root = max;
+    if (max == 0) {                     /* no symbols to code at all */
+        here.op = (unsigned char)64;    /* invalid code marker */
+        here.bits = (unsigned char)1;
+        here.val = (unsigned short)0;
+        *(*table)++ = here;             /* make a table to force an error */
+        *(*table)++ = here;
+        *bits = 1;
+        return 0;     /* no symbols, but wait for decoding to report error */
+    }
+    for (min = 1; min < max; min++)
+        if (count[min] != 0) break;
+    if (root < min) root = min;
+
+    /* check for an over-subscribed or incomplete set of lengths */
+    left = 1;
+    for (len = 1; len <= MAXBITS; len++) {
+        left <<= 1;
+        left -= count[len];
+        if (left < 0) return -1;        /* over-subscribed */
+    }
+    if (left > 0 && (type == CODES || max != 1))
+        return -1;                      /* incomplete set */
+
+    /* generate offsets into symbol table for each length for sorting */
+    offs[1] = 0;
+    for (len = 1; len < MAXBITS; len++)
+        offs[len + 1] = offs[len] + count[len];
+
+    /* sort symbols by length, by symbol order within each length */
+    for (sym = 0; sym < codes; sym++)
+        if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
+
+    /*
+       Create and fill in decoding tables.  In this loop, the table being
+       filled is at next and has curr index bits.  The code being used is huff
+       with length len.  That code is converted to an index by dropping drop
+       bits off of the bottom.  For codes where len is less than drop + curr,
+       those top drop + curr - len bits are incremented through all values to
+       fill the table with replicated entries.
+
+       root is the number of index bits for the root table.  When len exceeds
+       root, sub-tables are created pointed to by the root entry with an index
+       of the low root bits of huff.  This is saved in low to check for when a
+       new sub-table should be started.  drop is zero when the root table is
+       being filled, and drop is root when sub-tables are being filled.
+
+       When a new sub-table is needed, it is necessary to look ahead in the
+       code lengths to determine what size sub-table is needed.  The length
+       counts are used for this, and so count[] is decremented as codes are
+       entered in the tables.
+
+       used keeps track of how many table entries have been allocated from the
+       provided *table space.  It is checked for LENS and DIST tables against
+       the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
+       the initial root table size constants.  See the comments in inftrees.h
+       for more information.
+
+       sym increments through all symbols, and the loop terminates when
+       all codes of length max, i.e. all codes, have been processed.  This
+       routine permits incomplete codes, so another loop after this one fills
+       in the rest of the decoding tables with invalid code markers.
+     */
+
+    /* set up for code type */
+    switch (type) {
+    case CODES:
+        base = extra = work;    /* dummy value--not used */
+        match = 20;
+        break;
+    case LENS:
+        base = lbase;
+        extra = lext;
+        match = 257;
+        break;
+    default:    /* DISTS */
+        base = dbase;
+        extra = dext;
+        match = 0;
+    }
+
+    /* initialize state for loop */
+    huff = 0;                   /* starting code */
+    sym = 0;                    /* starting code symbol */
+    len = min;                  /* starting code length */
+    next = *table;              /* current table to fill in */
+    curr = root;                /* current table index bits */
+    drop = 0;                   /* current bits to drop from code for index */
+    low = (unsigned)(-1);       /* trigger new sub-table when len > root */
+    used = 1U << root;          /* use root table entries */
+    mask = used - 1;            /* mask for comparing low */
+
+    /* check available table space */
+    if ((type == LENS && used > ENOUGH_LENS) ||
+        (type == DISTS && used > ENOUGH_DISTS))
+        return 1;
+
+    /* process all codes and make table entries */
+    for (;;) {
+        /* create table entry */
+        here.bits = (unsigned char)(len - drop);
+        if (work[sym] + 1U < match) {
+            here.op = (unsigned char)0;
+            here.val = work[sym];
+        }
+        else if (work[sym] >= match) {
+            here.op = (unsigned char)(extra[work[sym] - match]);
+            here.val = base[work[sym] - match];
+        }
+        else {
+            here.op = (unsigned char)(32 + 64);         /* end of block */
+            here.val = 0;
+        }
+
+        /* replicate for those indices with low len bits equal to huff */
+        incr = 1U << (len - drop);
+        fill = 1U << curr;
+        min = fill;                 /* save offset to next table */
+        do {
+            fill -= incr;
+            next[(huff >> drop) + fill] = here;
+        } while (fill != 0);
+
+        /* backwards increment the len-bit code huff */
+        incr = 1U << (len - 1);
+        while (huff & incr)
+            incr >>= 1;
+        if (incr != 0) {
+            huff &= incr - 1;
+            huff += incr;
+        }
+        else
+            huff = 0;
+
+        /* go to next symbol, update count, len */
+        sym++;
+        if (--(count[len]) == 0) {
+            if (len == max) break;
+            len = lens[work[sym]];
+        }
+
+        /* create new sub-table if needed */
+        if (len > root && (huff & mask) != low) {
+            /* if first time, transition to sub-tables */
+            if (drop == 0)
+                drop = root;
+
+            /* increment past last table */
+            next += min;            /* here min is 1 << curr */
+
+            /* determine length of next table */
+            curr = len - drop;
+            left = (int)(1 << curr);
+            while (curr + drop < max) {
+                left -= count[curr + drop];
+                if (left <= 0) break;
+                curr++;
+                left <<= 1;
+            }
+
+            /* check for enough space */
+            used += 1U << curr;
+            if ((type == LENS && used > ENOUGH_LENS) ||
+                (type == DISTS && used > ENOUGH_DISTS))
+                return 1;
+
+            /* point entry in root table to sub-table */
+            low = huff & mask;
+            (*table)[low].op = (unsigned char)curr;
+            (*table)[low].bits = (unsigned char)root;
+            (*table)[low].val = (unsigned short)(next - *table);
+        }
+    }
+
+    /* fill in remaining table entry if code is incomplete (guaranteed to have
+       at most one remaining entry, since if the code is incomplete, the
+       maximum code length that was allowed to get this far is one bit) */
+    if (huff != 0) {
+        here.op = (unsigned char)64;            /* invalid code marker */
+        here.bits = (unsigned char)(len - drop);
+        here.val = (unsigned short)0;
+        next[huff] = here;
+    }
+
+    /* set return parameters */
+    *table += used;
+    *bits = root;
+    return 0;
+}
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/src/inftrees.h
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/src/inftrees.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/src/inftrees.h	(revision 453)
@@ -0,0 +1,62 @@
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-2005, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* Structure for decoding tables.  Each entry provides either the
+   information needed to do the operation requested by the code that
+   indexed that table entry, or it provides a pointer to another
+   table that indexes more bits of the code.  op indicates whether
+   the entry is a pointer to another table, a literal, a length or
+   distance, an end-of-block, or an invalid code.  For a table
+   pointer, the low four bits of op is the number of index bits of
+   that table.  For a length or distance, the low four bits of op
+   is the number of extra bits to get after the code.  bits is
+   the number of bits in this code or part of the code to drop off
+   of the bit buffer.  val is the actual byte to output in the case
+   of a literal, the base length or distance, or the offset from
+   the current table to the next table.  Each entry is four bytes. */
+typedef struct {
+    unsigned char op;           /* operation, extra bits, table bits */
+    unsigned char bits;         /* bits in this part of the code */
+    unsigned short val;         /* offset in table or code value */
+} code;
+
+/* op values as set by inflate_table():
+    00000000 - literal
+    0000tttt - table link, tttt != 0 is the number of table index bits
+    0001eeee - length or distance, eeee is the number of extra bits
+    01100000 - end of block
+    01000000 - invalid code
+ */
+
+/* Maximum size of the dynamic table.  The maximum number of code structures is
+   1444, which is the sum of 852 for literal/length codes and 592 for distance
+   codes.  These values were found by exhaustive searches using the program
+   examples/enough.c found in the zlib distribtution.  The arguments to that
+   program are the number of symbols, the initial root table size, and the
+   maximum bit length of a code.  "enough 286 9 15" for literal/length codes
+   returns returns 852, and "enough 30 6 15" for distance codes returns 592.
+   The initial root table size (9 or 6) is found in the fifth argument of the
+   inflate_table() calls in inflate.c and infback.c.  If the root table size is
+   changed, then these maximum sizes would be need to be recalculated and
+   updated. */
+#define ENOUGH_LENS 852
+#define ENOUGH_DISTS 592
+#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)
+
+/* Type of code to build for inflate_table() */
+typedef enum {
+    CODES,
+    LENS,
+    DISTS
+} codetype;
+
+int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens,
+                             unsigned codes, code FAR * FAR *table,
+                             unsigned FAR *bits, unsigned short FAR *work));
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/src/trees.c
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/src/trees.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/src/trees.c	(revision 453)
@@ -0,0 +1,1203 @@
+/* trees.c -- output deflated data using Huffman coding
+ * Copyright (C) 1995-2017 Jean-loup Gailly
+ * detect_data_type() function provided freely by Cosmin Truta, 2006
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ *  ALGORITHM
+ *
+ *      The "deflation" process uses several Huffman trees. The more
+ *      common source values are represented by shorter bit sequences.
+ *
+ *      Each code tree is stored in a compressed form which is itself
+ * a Huffman encoding of the lengths of all the code strings (in
+ * ascending order by source values).  The actual code strings are
+ * reconstructed from the lengths in the inflate process, as described
+ * in the deflate specification.
+ *
+ *  REFERENCES
+ *
+ *      Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
+ *      Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
+ *
+ *      Storer, James A.
+ *          Data Compression:  Methods and Theory, pp. 49-50.
+ *          Computer Science Press, 1988.  ISBN 0-7167-8156-5.
+ *
+ *      Sedgewick, R.
+ *          Algorithms, p290.
+ *          Addison-Wesley, 1983. ISBN 0-201-06672-6.
+ */
+
+/* @(#) $Id$ */
+
+/* #define GEN_TREES_H */
+
+#include "deflate.h"
+
+#ifdef ZLIB_DEBUG
+#  include <ctype.h>
+#endif
+
+/* ===========================================================================
+ * Constants
+ */
+
+#define MAX_BL_BITS 7
+/* Bit length codes must not exceed MAX_BL_BITS bits */
+
+#define END_BLOCK 256
+/* end of block literal code */
+
+#define REP_3_6      16
+/* repeat previous bit length 3-6 times (2 bits of repeat count) */
+
+#define REPZ_3_10    17
+/* repeat a zero length 3-10 times  (3 bits of repeat count) */
+
+#define REPZ_11_138  18
+/* repeat a zero length 11-138 times  (7 bits of repeat count) */
+
+local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
+   = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
+
+local const int extra_dbits[D_CODES] /* extra bits for each distance code */
+   = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+
+local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */
+   = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
+
+local const uch bl_order[BL_CODES]
+   = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+/* The lengths of the bit length codes are sent in order of decreasing
+ * probability, to avoid transmitting the lengths for unused bit length codes.
+ */
+
+/* ===========================================================================
+ * Local data. These are initialized only once.
+ */
+
+#define DIST_CODE_LEN  512 /* see definition of array dist_code below */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+/* non ANSI compilers may not accept trees.h */
+
+local ct_data static_ltree[L_CODES+2];
+/* The static literal tree. Since the bit lengths are imposed, there is no
+ * need for the L_CODES extra codes used during heap construction. However
+ * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
+ * below).
+ */
+
+local ct_data static_dtree[D_CODES];
+/* The static distance tree. (Actually a trivial tree since all codes use
+ * 5 bits.)
+ */
+
+uch _dist_code[DIST_CODE_LEN];
+/* Distance codes. The first 256 values correspond to the distances
+ * 3 .. 258, the last 256 values correspond to the top 8 bits of
+ * the 15 bit distances.
+ */
+
+uch _length_code[MAX_MATCH-MIN_MATCH+1];
+/* length code for each normalized match length (0 == MIN_MATCH) */
+
+local int base_length[LENGTH_CODES];
+/* First normalized length for each code (0 = MIN_MATCH) */
+
+local int base_dist[D_CODES];
+/* First normalized distance for each code (0 = distance of 1) */
+
+#else
+#  include "trees.h"
+#endif /* GEN_TREES_H */
+
+struct static_tree_desc_s {
+    const ct_data *static_tree;  /* static tree or NULL */
+    const intf *extra_bits;      /* extra bits for each code or NULL */
+    int     extra_base;          /* base index for extra_bits */
+    int     elems;               /* max number of elements in the tree */
+    int     max_length;          /* max bit length for the codes */
+};
+
+local const static_tree_desc  static_l_desc =
+{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
+
+local const static_tree_desc  static_d_desc =
+{static_dtree, extra_dbits, 0,          D_CODES, MAX_BITS};
+
+local const static_tree_desc  static_bl_desc =
+{(const ct_data *)0, extra_blbits, 0,   BL_CODES, MAX_BL_BITS};
+
+/* ===========================================================================
+ * Local (static) routines in this file.
+ */
+
+local void tr_static_init OF((void));
+local void init_block     OF((deflate_state *s));
+local void pqdownheap     OF((deflate_state *s, ct_data *tree, int k));
+local void gen_bitlen     OF((deflate_state *s, tree_desc *desc));
+local void gen_codes      OF((ct_data *tree, int max_code, ushf *bl_count));
+local void build_tree     OF((deflate_state *s, tree_desc *desc));
+local void scan_tree      OF((deflate_state *s, ct_data *tree, int max_code));
+local void send_tree      OF((deflate_state *s, ct_data *tree, int max_code));
+local int  build_bl_tree  OF((deflate_state *s));
+local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
+                              int blcodes));
+local void compress_block OF((deflate_state *s, const ct_data *ltree,
+                              const ct_data *dtree));
+local int  detect_data_type OF((deflate_state *s));
+local unsigned bi_reverse OF((unsigned value, int length));
+local void bi_windup      OF((deflate_state *s));
+local void bi_flush       OF((deflate_state *s));
+
+#ifdef GEN_TREES_H
+local void gen_trees_header OF((void));
+#endif
+
+#ifndef ZLIB_DEBUG
+#  define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
+   /* Send a code of the given tree. c and tree must not have side effects */
+
+#else /* !ZLIB_DEBUG */
+#  define send_code(s, c, tree) \
+     { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
+       send_bits(s, tree[c].Code, tree[c].Len); }
+#endif
+
+/* ===========================================================================
+ * Output a short LSB first on the stream.
+ * IN assertion: there is enough room in pendingBuf.
+ */
+#define put_short(s, w) { \
+    put_byte(s, (uch)((w) & 0xff)); \
+    put_byte(s, (uch)((ush)(w) >> 8)); \
+}
+
+/* ===========================================================================
+ * Send a value on a given number of bits.
+ * IN assertion: length <= 16 and value fits in length bits.
+ */
+#ifdef ZLIB_DEBUG
+local void send_bits      OF((deflate_state *s, int value, int length));
+
+local void send_bits(s, value, length)
+    deflate_state *s;
+    int value;  /* value to send */
+    int length; /* number of bits */
+{
+    Tracevv((stderr," l %2d v %4x ", length, value));
+    Assert(length > 0 && length <= 15, "invalid length");
+    s->bits_sent += (ulg)length;
+
+    /* If not enough room in bi_buf, use (valid) bits from bi_buf and
+     * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
+     * unused bits in value.
+     */
+    if (s->bi_valid > (int)Buf_size - length) {
+        s->bi_buf |= (ush)value << s->bi_valid;
+        put_short(s, s->bi_buf);
+        s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
+        s->bi_valid += length - Buf_size;
+    } else {
+        s->bi_buf |= (ush)value << s->bi_valid;
+        s->bi_valid += length;
+    }
+}
+#else /* !ZLIB_DEBUG */
+
+#define send_bits(s, value, length) \
+{ int len = length;\
+  if (s->bi_valid > (int)Buf_size - len) {\
+    int val = (int)value;\
+    s->bi_buf |= (ush)val << s->bi_valid;\
+    put_short(s, s->bi_buf);\
+    s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
+    s->bi_valid += len - Buf_size;\
+  } else {\
+    s->bi_buf |= (ush)(value) << s->bi_valid;\
+    s->bi_valid += len;\
+  }\
+}
+#endif /* ZLIB_DEBUG */
+
+
+/* the arguments must not have side effects */
+
+/* ===========================================================================
+ * Initialize the various 'constant' tables.
+ */
+local void tr_static_init()
+{
+#if defined(GEN_TREES_H) || !defined(STDC)
+    static int static_init_done = 0;
+    int n;        /* iterates over tree elements */
+    int bits;     /* bit counter */
+    int length;   /* length value */
+    int code;     /* code value */
+    int dist;     /* distance index */
+    ush bl_count[MAX_BITS+1];
+    /* number of codes at each bit length for an optimal tree */
+
+    if (static_init_done) return;
+
+    /* For some embedded targets, global variables are not initialized: */
+#ifdef NO_INIT_GLOBAL_POINTERS
+    static_l_desc.static_tree = static_ltree;
+    static_l_desc.extra_bits = extra_lbits;
+    static_d_desc.static_tree = static_dtree;
+    static_d_desc.extra_bits = extra_dbits;
+    static_bl_desc.extra_bits = extra_blbits;
+#endif
+
+    /* Initialize the mapping length (0..255) -> length code (0..28) */
+    length = 0;
+    for (code = 0; code < LENGTH_CODES-1; code++) {
+        base_length[code] = length;
+        for (n = 0; n < (1<<extra_lbits[code]); n++) {
+            _length_code[length++] = (uch)code;
+        }
+    }
+    Assert (length == 256, "tr_static_init: length != 256");
+    /* Note that the length 255 (match length 258) can be represented
+     * in two different ways: code 284 + 5 bits or code 285, so we
+     * overwrite length_code[255] to use the best encoding:
+     */
+    _length_code[length-1] = (uch)code;
+
+    /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+    dist = 0;
+    for (code = 0 ; code < 16; code++) {
+        base_dist[code] = dist;
+        for (n = 0; n < (1<<extra_dbits[code]); n++) {
+            _dist_code[dist++] = (uch)code;
+        }
+    }
+    Assert (dist == 256, "tr_static_init: dist != 256");
+    dist >>= 7; /* from now on, all distances are divided by 128 */
+    for ( ; code < D_CODES; code++) {
+        base_dist[code] = dist << 7;
+        for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
+            _dist_code[256 + dist++] = (uch)code;
+        }
+    }
+    Assert (dist == 256, "tr_static_init: 256+dist != 512");
+
+    /* Construct the codes of the static literal tree */
+    for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
+    n = 0;
+    while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
+    while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
+    while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
+    while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
+    /* Codes 286 and 287 do not exist, but we must include them in the
+     * tree construction to get a canonical Huffman tree (longest code
+     * all ones)
+     */
+    gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
+
+    /* The static distance tree is trivial: */
+    for (n = 0; n < D_CODES; n++) {
+        static_dtree[n].Len = 5;
+        static_dtree[n].Code = bi_reverse((unsigned)n, 5);
+    }
+    static_init_done = 1;
+
+#  ifdef GEN_TREES_H
+    gen_trees_header();
+#  endif
+#endif /* defined(GEN_TREES_H) || !defined(STDC) */
+}
+
+/* ===========================================================================
+ * Genererate the file trees.h describing the static trees.
+ */
+#ifdef GEN_TREES_H
+#  ifndef ZLIB_DEBUG
+#    include <stdio.h>
+#  endif
+
+#  define SEPARATOR(i, last, width) \
+      ((i) == (last)? "\n};\n\n" :    \
+       ((i) % (width) == (width)-1 ? ",\n" : ", "))
+
+void gen_trees_header()
+{
+    FILE *header = fopen("trees.h", "w");
+    int i;
+
+    Assert (header != NULL, "Can't open trees.h");
+    fprintf(header,
+            "/* header created automatically with -DGEN_TREES_H */\n\n");
+
+    fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n");
+    for (i = 0; i < L_CODES+2; i++) {
+        fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code,
+                static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5));
+    }
+
+    fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n");
+    for (i = 0; i < D_CODES; i++) {
+        fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code,
+                static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));
+    }
+
+    fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n");
+    for (i = 0; i < DIST_CODE_LEN; i++) {
+        fprintf(header, "%2u%s", _dist_code[i],
+                SEPARATOR(i, DIST_CODE_LEN-1, 20));
+    }
+
+    fprintf(header,
+        "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n");
+    for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {
+        fprintf(header, "%2u%s", _length_code[i],
+                SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));
+    }
+
+    fprintf(header, "local const int base_length[LENGTH_CODES] = {\n");
+    for (i = 0; i < LENGTH_CODES; i++) {
+        fprintf(header, "%1u%s", base_length[i],
+                SEPARATOR(i, LENGTH_CODES-1, 20));
+    }
+
+    fprintf(header, "local const int base_dist[D_CODES] = {\n");
+    for (i = 0; i < D_CODES; i++) {
+        fprintf(header, "%5u%s", base_dist[i],
+                SEPARATOR(i, D_CODES-1, 10));
+    }
+
+    fclose(header);
+}
+#endif /* GEN_TREES_H */
+
+/* ===========================================================================
+ * Initialize the tree data structures for a new zlib stream.
+ */
+void ZLIB_INTERNAL _tr_init(s)
+    deflate_state *s;
+{
+    tr_static_init();
+
+    s->l_desc.dyn_tree = s->dyn_ltree;
+    s->l_desc.stat_desc = &static_l_desc;
+
+    s->d_desc.dyn_tree = s->dyn_dtree;
+    s->d_desc.stat_desc = &static_d_desc;
+
+    s->bl_desc.dyn_tree = s->bl_tree;
+    s->bl_desc.stat_desc = &static_bl_desc;
+
+    s->bi_buf = 0;
+    s->bi_valid = 0;
+#ifdef ZLIB_DEBUG
+    s->compressed_len = 0L;
+    s->bits_sent = 0L;
+#endif
+
+    /* Initialize the first block of the first file: */
+    init_block(s);
+}
+
+/* ===========================================================================
+ * Initialize a new block.
+ */
+local void init_block(s)
+    deflate_state *s;
+{
+    int n; /* iterates over tree elements */
+
+    /* Initialize the trees. */
+    for (n = 0; n < L_CODES;  n++) s->dyn_ltree[n].Freq = 0;
+    for (n = 0; n < D_CODES;  n++) s->dyn_dtree[n].Freq = 0;
+    for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
+
+    s->dyn_ltree[END_BLOCK].Freq = 1;
+    s->opt_len = s->static_len = 0L;
+    s->last_lit = s->matches = 0;
+}
+
+#define SMALLEST 1
+/* Index within the heap array of least frequent node in the Huffman tree */
+
+
+/* ===========================================================================
+ * Remove the smallest element from the heap and recreate the heap with
+ * one less element. Updates heap and heap_len.
+ */
+#define pqremove(s, tree, top) \
+{\
+    top = s->heap[SMALLEST]; \
+    s->heap[SMALLEST] = s->heap[s->heap_len--]; \
+    pqdownheap(s, tree, SMALLEST); \
+}
+
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+#define smaller(tree, n, m, depth) \
+   (tree[n].Freq < tree[m].Freq || \
+   (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
+
+/* ===========================================================================
+ * Restore the heap property by moving down the tree starting at node k,
+ * exchanging a node with the smallest of its two sons if necessary, stopping
+ * when the heap property is re-established (each father smaller than its
+ * two sons).
+ */
+local void pqdownheap(s, tree, k)
+    deflate_state *s;
+    ct_data *tree;  /* the tree to restore */
+    int k;               /* node to move down */
+{
+    int v = s->heap[k];
+    int j = k << 1;  /* left son of k */
+    while (j <= s->heap_len) {
+        /* Set j to the smallest of the two sons: */
+        if (j < s->heap_len &&
+            smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {
+            j++;
+        }
+        /* Exit if v is smaller than both sons */
+        if (smaller(tree, v, s->heap[j], s->depth)) break;
+
+        /* Exchange v with the smallest son */
+        s->heap[k] = s->heap[j];  k = j;
+
+        /* And continue down the tree, setting j to the left son of k */
+        j <<= 1;
+    }
+    s->heap[k] = v;
+}
+
+/* ===========================================================================
+ * Compute the optimal bit lengths for a tree and update the total bit length
+ * for the current block.
+ * IN assertion: the fields freq and dad are set, heap[heap_max] and
+ *    above are the tree nodes sorted by increasing frequency.
+ * OUT assertions: the field len is set to the optimal bit length, the
+ *     array bl_count contains the frequencies for each bit length.
+ *     The length opt_len is updated; static_len is also updated if stree is
+ *     not null.
+ */
+local void gen_bitlen(s, desc)
+    deflate_state *s;
+    tree_desc *desc;    /* the tree descriptor */
+{
+    ct_data *tree        = desc->dyn_tree;
+    int max_code         = desc->max_code;
+    const ct_data *stree = desc->stat_desc->static_tree;
+    const intf *extra    = desc->stat_desc->extra_bits;
+    int base             = desc->stat_desc->extra_base;
+    int max_length       = desc->stat_desc->max_length;
+    int h;              /* heap index */
+    int n, m;           /* iterate over the tree elements */
+    int bits;           /* bit length */
+    int xbits;          /* extra bits */
+    ush f;              /* frequency */
+    int overflow = 0;   /* number of elements with bit length too large */
+
+    for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
+
+    /* In a first pass, compute the optimal bit lengths (which may
+     * overflow in the case of the bit length tree).
+     */
+    tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
+
+    for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
+        n = s->heap[h];
+        bits = tree[tree[n].Dad].Len + 1;
+        if (bits > max_length) bits = max_length, overflow++;
+        tree[n].Len = (ush)bits;
+        /* We overwrite tree[n].Dad which is no longer needed */
+
+        if (n > max_code) continue; /* not a leaf node */
+
+        s->bl_count[bits]++;
+        xbits = 0;
+        if (n >= base) xbits = extra[n-base];
+        f = tree[n].Freq;
+        s->opt_len += (ulg)f * (unsigned)(bits + xbits);
+        if (stree) s->static_len += (ulg)f * (unsigned)(stree[n].Len + xbits);
+    }
+    if (overflow == 0) return;
+
+    Tracev((stderr,"\nbit length overflow\n"));
+    /* This happens for example on obj2 and pic of the Calgary corpus */
+
+    /* Find the first bit length which could increase: */
+    do {
+        bits = max_length-1;
+        while (s->bl_count[bits] == 0) bits--;
+        s->bl_count[bits]--;      /* move one leaf down the tree */
+        s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
+        s->bl_count[max_length]--;
+        /* The brother of the overflow item also moves one step up,
+         * but this does not affect bl_count[max_length]
+         */
+        overflow -= 2;
+    } while (overflow > 0);
+
+    /* Now recompute all bit lengths, scanning in increasing frequency.
+     * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
+     * lengths instead of fixing only the wrong ones. This idea is taken
+     * from 'ar' written by Haruhiko Okumura.)
+     */
+    for (bits = max_length; bits != 0; bits--) {
+        n = s->bl_count[bits];
+        while (n != 0) {
+            m = s->heap[--h];
+            if (m > max_code) continue;
+            if ((unsigned) tree[m].Len != (unsigned) bits) {
+                Tracev((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
+                s->opt_len += ((ulg)bits - tree[m].Len) * tree[m].Freq;
+                tree[m].Len = (ush)bits;
+            }
+            n--;
+        }
+    }
+}
+
+/* ===========================================================================
+ * Generate the codes for a given tree and bit counts (which need not be
+ * optimal).
+ * IN assertion: the array bl_count contains the bit length statistics for
+ * the given tree and the field len is set for all tree elements.
+ * OUT assertion: the field code is set for all tree elements of non
+ *     zero code length.
+ */
+local void gen_codes (tree, max_code, bl_count)
+    ct_data *tree;             /* the tree to decorate */
+    int max_code;              /* largest code with non zero frequency */
+    ushf *bl_count;            /* number of codes at each bit length */
+{
+    ush next_code[MAX_BITS+1]; /* next code value for each bit length */
+    unsigned code = 0;         /* running code value */
+    int bits;                  /* bit index */
+    int n;                     /* code index */
+
+    /* The distribution counts are first used to generate the code values
+     * without bit reversal.
+     */
+    for (bits = 1; bits <= MAX_BITS; bits++) {
+        code = (code + bl_count[bits-1]) << 1;
+        next_code[bits] = (ush)code;
+    }
+    /* Check that the bit counts in bl_count are consistent. The last code
+     * must be all ones.
+     */
+    Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
+            "inconsistent bit counts");
+    Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+    for (n = 0;  n <= max_code; n++) {
+        int len = tree[n].Len;
+        if (len == 0) continue;
+        /* Now reverse the bits */
+        tree[n].Code = (ush)bi_reverse(next_code[len]++, len);
+
+        Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
+             n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
+    }
+}
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ *     and corresponding code. The length opt_len is updated; static_len is
+ *     also updated if stree is not null. The field max_code is set.
+ */
+local void build_tree(s, desc)
+    deflate_state *s;
+    tree_desc *desc; /* the tree descriptor */
+{
+    ct_data *tree         = desc->dyn_tree;
+    const ct_data *stree  = desc->stat_desc->static_tree;
+    int elems             = desc->stat_desc->elems;
+    int n, m;          /* iterate over heap elements */
+    int max_code = -1; /* largest code with non zero frequency */
+    int node;          /* new node being created */
+
+    /* Construct the initial heap, with least frequent element in
+     * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+     * heap[0] is not used.
+     */
+    s->heap_len = 0, s->heap_max = HEAP_SIZE;
+
+    for (n = 0; n < elems; n++) {
+        if (tree[n].Freq != 0) {
+            s->heap[++(s->heap_len)] = max_code = n;
+            s->depth[n] = 0;
+        } else {
+            tree[n].Len = 0;
+        }
+    }
+
+    /* The pkzip format requires that at least one distance code exists,
+     * and that at least one bit should be sent even if there is only one
+     * possible code. So to avoid special checks later on we force at least
+     * two codes of non zero frequency.
+     */
+    while (s->heap_len < 2) {
+        node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
+        tree[node].Freq = 1;
+        s->depth[node] = 0;
+        s->opt_len--; if (stree) s->static_len -= stree[node].Len;
+        /* node is 0 or 1 so it does not have extra bits */
+    }
+    desc->max_code = max_code;
+
+    /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+     * establish sub-heaps of increasing lengths:
+     */
+    for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
+
+    /* Construct the Huffman tree by repeatedly combining the least two
+     * frequent nodes.
+     */
+    node = elems;              /* next internal node of the tree */
+    do {
+        pqremove(s, tree, n);  /* n = node of least frequency */
+        m = s->heap[SMALLEST]; /* m = node of next least frequency */
+
+        s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
+        s->heap[--(s->heap_max)] = m;
+
+        /* Create a new node father of n and m */
+        tree[node].Freq = tree[n].Freq + tree[m].Freq;
+        s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ?
+                                s->depth[n] : s->depth[m]) + 1);
+        tree[n].Dad = tree[m].Dad = (ush)node;
+#ifdef DUMP_BL_TREE
+        if (tree == s->bl_tree) {
+            fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
+                    node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
+        }
+#endif
+        /* and insert the new node in the heap */
+        s->heap[SMALLEST] = node++;
+        pqdownheap(s, tree, SMALLEST);
+
+    } while (s->heap_len >= 2);
+
+    s->heap[--(s->heap_max)] = s->heap[SMALLEST];
+
+    /* At this point, the fields freq and dad are set. We can now
+     * generate the bit lengths.
+     */
+    gen_bitlen(s, (tree_desc *)desc);
+
+    /* The field len is now set, we can generate the bit codes */
+    gen_codes ((ct_data *)tree, max_code, s->bl_count);
+}
+
+/* ===========================================================================
+ * Scan a literal or distance tree to determine the frequencies of the codes
+ * in the bit length tree.
+ */
+local void scan_tree (s, tree, max_code)
+    deflate_state *s;
+    ct_data *tree;   /* the tree to be scanned */
+    int max_code;    /* and its largest code of non zero frequency */
+{
+    int n;                     /* iterates over all tree elements */
+    int prevlen = -1;          /* last emitted length */
+    int curlen;                /* length of current code */
+    int nextlen = tree[0].Len; /* length of next code */
+    int count = 0;             /* repeat count of the current code */
+    int max_count = 7;         /* max repeat count */
+    int min_count = 4;         /* min repeat count */
+
+    if (nextlen == 0) max_count = 138, min_count = 3;
+    tree[max_code+1].Len = (ush)0xffff; /* guard */
+
+    for (n = 0; n <= max_code; n++) {
+        curlen = nextlen; nextlen = tree[n+1].Len;
+        if (++count < max_count && curlen == nextlen) {
+            continue;
+        } else if (count < min_count) {
+            s->bl_tree[curlen].Freq += count;
+        } else if (curlen != 0) {
+            if (curlen != prevlen) s->bl_tree[curlen].Freq++;
+            s->bl_tree[REP_3_6].Freq++;
+        } else if (count <= 10) {
+            s->bl_tree[REPZ_3_10].Freq++;
+        } else {
+            s->bl_tree[REPZ_11_138].Freq++;
+        }
+        count = 0; prevlen = curlen;
+        if (nextlen == 0) {
+            max_count = 138, min_count = 3;
+        } else if (curlen == nextlen) {
+            max_count = 6, min_count = 3;
+        } else {
+            max_count = 7, min_count = 4;
+        }
+    }
+}
+
+/* ===========================================================================
+ * Send a literal or distance tree in compressed form, using the codes in
+ * bl_tree.
+ */
+local void send_tree (s, tree, max_code)
+    deflate_state *s;
+    ct_data *tree; /* the tree to be scanned */
+    int max_code;       /* and its largest code of non zero frequency */
+{
+    int n;                     /* iterates over all tree elements */
+    int prevlen = -1;          /* last emitted length */
+    int curlen;                /* length of current code */
+    int nextlen = tree[0].Len; /* length of next code */
+    int count = 0;             /* repeat count of the current code */
+    int max_count = 7;         /* max repeat count */
+    int min_count = 4;         /* min repeat count */
+
+    /* tree[max_code+1].Len = -1; */  /* guard already set */
+    if (nextlen == 0) max_count = 138, min_count = 3;
+
+    for (n = 0; n <= max_code; n++) {
+        curlen = nextlen; nextlen = tree[n+1].Len;
+        if (++count < max_count && curlen == nextlen) {
+            continue;
+        } else if (count < min_count) {
+            do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
+
+        } else if (curlen != 0) {
+            if (curlen != prevlen) {
+                send_code(s, curlen, s->bl_tree); count--;
+            }
+            Assert(count >= 3 && count <= 6, " 3_6?");
+            send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);
+
+        } else if (count <= 10) {
+            send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);
+
+        } else {
+            send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);
+        }
+        count = 0; prevlen = curlen;
+        if (nextlen == 0) {
+            max_count = 138, min_count = 3;
+        } else if (curlen == nextlen) {
+            max_count = 6, min_count = 3;
+        } else {
+            max_count = 7, min_count = 4;
+        }
+    }
+}
+
+/* ===========================================================================
+ * Construct the Huffman tree for the bit lengths and return the index in
+ * bl_order of the last bit length code to send.
+ */
+local int build_bl_tree(s)
+    deflate_state *s;
+{
+    int max_blindex;  /* index of last bit length code of non zero freq */
+
+    /* Determine the bit length frequencies for literal and distance trees */
+    scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
+    scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
+
+    /* Build the bit length tree: */
+    build_tree(s, (tree_desc *)(&(s->bl_desc)));
+    /* opt_len now includes the length of the tree representations, except
+     * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+     */
+
+    /* Determine the number of bit length codes to send. The pkzip format
+     * requires that at least 4 bit length codes be sent. (appnote.txt says
+     * 3 but the actual value used is 4.)
+     */
+    for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
+        if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
+    }
+    /* Update opt_len to include the bit length tree and counts */
+    s->opt_len += 3*((ulg)max_blindex+1) + 5+5+4;
+    Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
+            s->opt_len, s->static_len));
+
+    return max_blindex;
+}
+
+/* ===========================================================================
+ * Send the header for a block using dynamic Huffman trees: the counts, the
+ * lengths of the bit length codes, the literal tree and the distance tree.
+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ */
+local void send_all_trees(s, lcodes, dcodes, blcodes)
+    deflate_state *s;
+    int lcodes, dcodes, blcodes; /* number of codes for each tree */
+{
+    int rank;                    /* index in bl_order */
+
+    Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
+    Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
+            "too many codes");
+    Tracev((stderr, "\nbl counts: "));
+    send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
+    send_bits(s, dcodes-1,   5);
+    send_bits(s, blcodes-4,  4); /* not -3 as stated in appnote.txt */
+    for (rank = 0; rank < blcodes; rank++) {
+        Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+        send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
+    }
+    Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
+
+    send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
+    Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
+
+    send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
+    Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
+}
+
+/* ===========================================================================
+ * Send a stored block
+ */
+void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last)
+    deflate_state *s;
+    charf *buf;       /* input block */
+    ulg stored_len;   /* length of input block */
+    int last;         /* one if this is the last block for a file */
+{
+    send_bits(s, (STORED_BLOCK<<1)+last, 3);    /* send block type */
+    bi_windup(s);        /* align on byte boundary */
+    put_short(s, (ush)stored_len);
+    put_short(s, (ush)~stored_len);
+    zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len);
+    s->pending += stored_len;
+#ifdef ZLIB_DEBUG
+    s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
+    s->compressed_len += (stored_len + 4) << 3;
+    s->bits_sent += 2*16;
+    s->bits_sent += stored_len<<3;
+#endif
+}
+
+/* ===========================================================================
+ * Flush the bits in the bit buffer to pending output (leaves at most 7 bits)
+ */
+void ZLIB_INTERNAL _tr_flush_bits(s)
+    deflate_state *s;
+{
+    bi_flush(s);
+}
+
+/* ===========================================================================
+ * Send one empty static block to give enough lookahead for inflate.
+ * This takes 10 bits, of which 7 may remain in the bit buffer.
+ */
+void ZLIB_INTERNAL _tr_align(s)
+    deflate_state *s;
+{
+    send_bits(s, STATIC_TREES<<1, 3);
+    send_code(s, END_BLOCK, static_ltree);
+#ifdef ZLIB_DEBUG
+    s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
+#endif
+    bi_flush(s);
+}
+
+/* ===========================================================================
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and write out the encoded block.
+ */
+void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
+    deflate_state *s;
+    charf *buf;       /* input block, or NULL if too old */
+    ulg stored_len;   /* length of input block */
+    int last;         /* one if this is the last block for a file */
+{
+    ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
+    int max_blindex = 0;  /* index of last bit length code of non zero freq */
+
+    /* Build the Huffman trees unless a stored block is forced */
+    if (s->level > 0) {
+
+        /* Check if the file is binary or text */
+        if (s->strm->data_type == Z_UNKNOWN)
+            s->strm->data_type = detect_data_type(s);
+
+        /* Construct the literal and distance trees */
+        build_tree(s, (tree_desc *)(&(s->l_desc)));
+        Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
+                s->static_len));
+
+        build_tree(s, (tree_desc *)(&(s->d_desc)));
+        Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
+                s->static_len));
+        /* At this point, opt_len and static_len are the total bit lengths of
+         * the compressed block data, excluding the tree representations.
+         */
+
+        /* Build the bit length tree for the above two trees, and get the index
+         * in bl_order of the last bit length code to send.
+         */
+        max_blindex = build_bl_tree(s);
+
+        /* Determine the best encoding. Compute the block lengths in bytes. */
+        opt_lenb = (s->opt_len+3+7)>>3;
+        static_lenb = (s->static_len+3+7)>>3;
+
+        Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
+                opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
+                s->last_lit));
+
+        if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+
+    } else {
+        Assert(buf != (char*)0, "lost buf");
+        opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
+    }
+
+#ifdef FORCE_STORED
+    if (buf != (char*)0) { /* force stored block */
+#else
+    if (stored_len+4 <= opt_lenb && buf != (char*)0) {
+                       /* 4: two words for the lengths */
+#endif
+        /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+         * Otherwise we can't have processed more than WSIZE input bytes since
+         * the last block flush, because compression would have been
+         * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+         * transform a block into a stored block.
+         */
+        _tr_stored_block(s, buf, stored_len, last);
+
+#ifdef FORCE_STATIC
+    } else if (static_lenb >= 0) { /* force static trees */
+#else
+    } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
+#endif
+        send_bits(s, (STATIC_TREES<<1)+last, 3);
+        compress_block(s, (const ct_data *)static_ltree,
+                       (const ct_data *)static_dtree);
+#ifdef ZLIB_DEBUG
+        s->compressed_len += 3 + s->static_len;
+#endif
+    } else {
+        send_bits(s, (DYN_TREES<<1)+last, 3);
+        send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
+                       max_blindex+1);
+        compress_block(s, (const ct_data *)s->dyn_ltree,
+                       (const ct_data *)s->dyn_dtree);
+#ifdef ZLIB_DEBUG
+        s->compressed_len += 3 + s->opt_len;
+#endif
+    }
+    Assert (s->compressed_len == s->bits_sent, "bad compressed size");
+    /* The above check is made mod 2^32, for files larger than 512 MB
+     * and uLong implemented on 32 bits.
+     */
+    init_block(s);
+
+    if (last) {
+        bi_windup(s);
+#ifdef ZLIB_DEBUG
+        s->compressed_len += 7;  /* align on byte boundary */
+#endif
+    }
+    Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
+           s->compressed_len-7*last));
+}
+
+/* ===========================================================================
+ * Save the match info and tally the frequency counts. Return true if
+ * the current block must be flushed.
+ */
+int ZLIB_INTERNAL _tr_tally (s, dist, lc)
+    deflate_state *s;
+    unsigned dist;  /* distance of matched string */
+    unsigned lc;    /* match length-MIN_MATCH or unmatched char (if dist==0) */
+{
+    s->d_buf[s->last_lit] = (ush)dist;
+    s->l_buf[s->last_lit++] = (uch)lc;
+    if (dist == 0) {
+        /* lc is the unmatched char */
+        s->dyn_ltree[lc].Freq++;
+    } else {
+        s->matches++;
+        /* Here, lc is the match length - MIN_MATCH */
+        dist--;             /* dist = match distance - 1 */
+        Assert((ush)dist < (ush)MAX_DIST(s) &&
+               (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
+               (ush)d_code(dist) < (ush)D_CODES,  "_tr_tally: bad match");
+
+        s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
+        s->dyn_dtree[d_code(dist)].Freq++;
+    }
+
+#ifdef TRUNCATE_BLOCK
+    /* Try to guess if it is profitable to stop the current block here */
+    if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
+        /* Compute an upper bound for the compressed length */
+        ulg out_length = (ulg)s->last_lit*8L;
+        ulg in_length = (ulg)((long)s->strstart - s->block_start);
+        int dcode;
+        for (dcode = 0; dcode < D_CODES; dcode++) {
+            out_length += (ulg)s->dyn_dtree[dcode].Freq *
+                (5L+extra_dbits[dcode]);
+        }
+        out_length >>= 3;
+        Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
+               s->last_lit, in_length, out_length,
+               100L - out_length*100L/in_length));
+        if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
+    }
+#endif
+    return (s->last_lit == s->lit_bufsize-1);
+    /* We avoid equality with lit_bufsize because of wraparound at 64K
+     * on 16 bit machines and because stored blocks are restricted to
+     * 64K-1 bytes.
+     */
+}
+
+/* ===========================================================================
+ * Send the block data compressed using the given Huffman trees
+ */
+local void compress_block(s, ltree, dtree)
+    deflate_state *s;
+    const ct_data *ltree; /* literal tree */
+    const ct_data *dtree; /* distance tree */
+{
+    unsigned dist;      /* distance of matched string */
+    int lc;             /* match length or unmatched char (if dist == 0) */
+    unsigned lx = 0;    /* running index in l_buf */
+    unsigned code;      /* the code to send */
+    int extra;          /* number of extra bits to send */
+
+    if (s->last_lit != 0) do {
+        dist = s->d_buf[lx];
+        lc = s->l_buf[lx++];
+        if (dist == 0) {
+            send_code(s, lc, ltree); /* send a literal byte */
+            Tracecv(isgraph(lc), (stderr," '%c' ", lc));
+        } else {
+            /* Here, lc is the match length - MIN_MATCH */
+            code = _length_code[lc];
+            send_code(s, code+LITERALS+1, ltree); /* send the length code */
+            extra = extra_lbits[code];
+            if (extra != 0) {
+                lc -= base_length[code];
+                send_bits(s, lc, extra);       /* send the extra length bits */
+            }
+            dist--; /* dist is now the match distance - 1 */
+            code = d_code(dist);
+            Assert (code < D_CODES, "bad d_code");
+
+            send_code(s, code, dtree);       /* send the distance code */
+            extra = extra_dbits[code];
+            if (extra != 0) {
+                dist -= (unsigned)base_dist[code];
+                send_bits(s, dist, extra);   /* send the extra distance bits */
+            }
+        } /* literal or match pair ? */
+
+        /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
+        Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
+               "pendingBuf overflow");
+
+    } while (lx < s->last_lit);
+
+    send_code(s, END_BLOCK, ltree);
+}
+
+/* ===========================================================================
+ * Check if the data type is TEXT or BINARY, using the following algorithm:
+ * - TEXT if the two conditions below are satisfied:
+ *    a) There are no non-portable control characters belonging to the
+ *       "black list" (0..6, 14..25, 28..31).
+ *    b) There is at least one printable character belonging to the
+ *       "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
+ * - BINARY otherwise.
+ * - The following partially-portable control characters form a
+ *   "gray list" that is ignored in this detection algorithm:
+ *   (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
+ * IN assertion: the fields Freq of dyn_ltree are set.
+ */
+local int detect_data_type(s)
+    deflate_state *s;
+{
+    /* black_mask is the bit mask of black-listed bytes
+     * set bits 0..6, 14..25, and 28..31
+     * 0xf3ffc07f = binary 11110011111111111100000001111111
+     */
+    unsigned long black_mask = 0xf3ffc07fUL;
+    int n;
+
+    /* Check for non-textual ("black-listed") bytes. */
+    for (n = 0; n <= 31; n++, black_mask >>= 1)
+        if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0))
+            return Z_BINARY;
+
+    /* Check for textual ("white-listed") bytes. */
+    if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0
+            || s->dyn_ltree[13].Freq != 0)
+        return Z_TEXT;
+    for (n = 32; n < LITERALS; n++)
+        if (s->dyn_ltree[n].Freq != 0)
+            return Z_TEXT;
+
+    /* There are no "black-listed" or "white-listed" bytes:
+     * this stream either is empty or has tolerated ("gray-listed") bytes only.
+     */
+    return Z_BINARY;
+}
+
+/* ===========================================================================
+ * Reverse the first len bits of a code, using straightforward code (a faster
+ * method would use a table)
+ * IN assertion: 1 <= len <= 15
+ */
+local unsigned bi_reverse(code, len)
+    unsigned code; /* the value to invert */
+    int len;       /* its bit length */
+{
+    register unsigned res = 0;
+    do {
+        res |= code & 1;
+        code >>= 1, res <<= 1;
+    } while (--len > 0);
+    return res >> 1;
+}
+
+/* ===========================================================================
+ * Flush the bit buffer, keeping at most 7 bits in it.
+ */
+local void bi_flush(s)
+    deflate_state *s;
+{
+    if (s->bi_valid == 16) {
+        put_short(s, s->bi_buf);
+        s->bi_buf = 0;
+        s->bi_valid = 0;
+    } else if (s->bi_valid >= 8) {
+        put_byte(s, (Byte)s->bi_buf);
+        s->bi_buf >>= 8;
+        s->bi_valid -= 8;
+    }
+}
+
+/* ===========================================================================
+ * Flush the bit buffer and align the output on a byte boundary
+ */
+local void bi_windup(s)
+    deflate_state *s;
+{
+    if (s->bi_valid > 8) {
+        put_short(s, s->bi_buf);
+    } else if (s->bi_valid > 0) {
+        put_byte(s, (Byte)s->bi_buf);
+    }
+    s->bi_buf = 0;
+    s->bi_valid = 0;
+#ifdef ZLIB_DEBUG
+    s->bits_sent = (s->bits_sent+7) & ~7;
+#endif
+}
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/src/trees.h
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/src/trees.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/src/trees.h	(revision 453)
@@ -0,0 +1,128 @@
+/* header created automatically with -DGEN_TREES_H */
+
+local const ct_data static_ltree[L_CODES+2] = {
+{{ 12},{  8}}, {{140},{  8}}, {{ 76},{  8}}, {{204},{  8}}, {{ 44},{  8}},
+{{172},{  8}}, {{108},{  8}}, {{236},{  8}}, {{ 28},{  8}}, {{156},{  8}},
+{{ 92},{  8}}, {{220},{  8}}, {{ 60},{  8}}, {{188},{  8}}, {{124},{  8}},
+{{252},{  8}}, {{  2},{  8}}, {{130},{  8}}, {{ 66},{  8}}, {{194},{  8}},
+{{ 34},{  8}}, {{162},{  8}}, {{ 98},{  8}}, {{226},{  8}}, {{ 18},{  8}},
+{{146},{  8}}, {{ 82},{  8}}, {{210},{  8}}, {{ 50},{  8}}, {{178},{  8}},
+{{114},{  8}}, {{242},{  8}}, {{ 10},{  8}}, {{138},{  8}}, {{ 74},{  8}},
+{{202},{  8}}, {{ 42},{  8}}, {{170},{  8}}, {{106},{  8}}, {{234},{  8}},
+{{ 26},{  8}}, {{154},{  8}}, {{ 90},{  8}}, {{218},{  8}}, {{ 58},{  8}},
+{{186},{  8}}, {{122},{  8}}, {{250},{  8}}, {{  6},{  8}}, {{134},{  8}},
+{{ 70},{  8}}, {{198},{  8}}, {{ 38},{  8}}, {{166},{  8}}, {{102},{  8}},
+{{230},{  8}}, {{ 22},{  8}}, {{150},{  8}}, {{ 86},{  8}}, {{214},{  8}},
+{{ 54},{  8}}, {{182},{  8}}, {{118},{  8}}, {{246},{  8}}, {{ 14},{  8}},
+{{142},{  8}}, {{ 78},{  8}}, {{206},{  8}}, {{ 46},{  8}}, {{174},{  8}},
+{{110},{  8}}, {{238},{  8}}, {{ 30},{  8}}, {{158},{  8}}, {{ 94},{  8}},
+{{222},{  8}}, {{ 62},{  8}}, {{190},{  8}}, {{126},{  8}}, {{254},{  8}},
+{{  1},{  8}}, {{129},{  8}}, {{ 65},{  8}}, {{193},{  8}}, {{ 33},{  8}},
+{{161},{  8}}, {{ 97},{  8}}, {{225},{  8}}, {{ 17},{  8}}, {{145},{  8}},
+{{ 81},{  8}}, {{209},{  8}}, {{ 49},{  8}}, {{177},{  8}}, {{113},{  8}},
+{{241},{  8}}, {{  9},{  8}}, {{137},{  8}}, {{ 73},{  8}}, {{201},{  8}},
+{{ 41},{  8}}, {{169},{  8}}, {{105},{  8}}, {{233},{  8}}, {{ 25},{  8}},
+{{153},{  8}}, {{ 89},{  8}}, {{217},{  8}}, {{ 57},{  8}}, {{185},{  8}},
+{{121},{  8}}, {{249},{  8}}, {{  5},{  8}}, {{133},{  8}}, {{ 69},{  8}},
+{{197},{  8}}, {{ 37},{  8}}, {{165},{  8}}, {{101},{  8}}, {{229},{  8}},
+{{ 21},{  8}}, {{149},{  8}}, {{ 85},{  8}}, {{213},{  8}}, {{ 53},{  8}},
+{{181},{  8}}, {{117},{  8}}, {{245},{  8}}, {{ 13},{  8}}, {{141},{  8}},
+{{ 77},{  8}}, {{205},{  8}}, {{ 45},{  8}}, {{173},{  8}}, {{109},{  8}},
+{{237},{  8}}, {{ 29},{  8}}, {{157},{  8}}, {{ 93},{  8}}, {{221},{  8}},
+{{ 61},{  8}}, {{189},{  8}}, {{125},{  8}}, {{253},{  8}}, {{ 19},{  9}},
+{{275},{  9}}, {{147},{  9}}, {{403},{  9}}, {{ 83},{  9}}, {{339},{  9}},
+{{211},{  9}}, {{467},{  9}}, {{ 51},{  9}}, {{307},{  9}}, {{179},{  9}},
+{{435},{  9}}, {{115},{  9}}, {{371},{  9}}, {{243},{  9}}, {{499},{  9}},
+{{ 11},{  9}}, {{267},{  9}}, {{139},{  9}}, {{395},{  9}}, {{ 75},{  9}},
+{{331},{  9}}, {{203},{  9}}, {{459},{  9}}, {{ 43},{  9}}, {{299},{  9}},
+{{171},{  9}}, {{427},{  9}}, {{107},{  9}}, {{363},{  9}}, {{235},{  9}},
+{{491},{  9}}, {{ 27},{  9}}, {{283},{  9}}, {{155},{  9}}, {{411},{  9}},
+{{ 91},{  9}}, {{347},{  9}}, {{219},{  9}}, {{475},{  9}}, {{ 59},{  9}},
+{{315},{  9}}, {{187},{  9}}, {{443},{  9}}, {{123},{  9}}, {{379},{  9}},
+{{251},{  9}}, {{507},{  9}}, {{  7},{  9}}, {{263},{  9}}, {{135},{  9}},
+{{391},{  9}}, {{ 71},{  9}}, {{327},{  9}}, {{199},{  9}}, {{455},{  9}},
+{{ 39},{  9}}, {{295},{  9}}, {{167},{  9}}, {{423},{  9}}, {{103},{  9}},
+{{359},{  9}}, {{231},{  9}}, {{487},{  9}}, {{ 23},{  9}}, {{279},{  9}},
+{{151},{  9}}, {{407},{  9}}, {{ 87},{  9}}, {{343},{  9}}, {{215},{  9}},
+{{471},{  9}}, {{ 55},{  9}}, {{311},{  9}}, {{183},{  9}}, {{439},{  9}},
+{{119},{  9}}, {{375},{  9}}, {{247},{  9}}, {{503},{  9}}, {{ 15},{  9}},
+{{271},{  9}}, {{143},{  9}}, {{399},{  9}}, {{ 79},{  9}}, {{335},{  9}},
+{{207},{  9}}, {{463},{  9}}, {{ 47},{  9}}, {{303},{  9}}, {{175},{  9}},
+{{431},{  9}}, {{111},{  9}}, {{367},{  9}}, {{239},{  9}}, {{495},{  9}},
+{{ 31},{  9}}, {{287},{  9}}, {{159},{  9}}, {{415},{  9}}, {{ 95},{  9}},
+{{351},{  9}}, {{223},{  9}}, {{479},{  9}}, {{ 63},{  9}}, {{319},{  9}},
+{{191},{  9}}, {{447},{  9}}, {{127},{  9}}, {{383},{  9}}, {{255},{  9}},
+{{511},{  9}}, {{  0},{  7}}, {{ 64},{  7}}, {{ 32},{  7}}, {{ 96},{  7}},
+{{ 16},{  7}}, {{ 80},{  7}}, {{ 48},{  7}}, {{112},{  7}}, {{  8},{  7}},
+{{ 72},{  7}}, {{ 40},{  7}}, {{104},{  7}}, {{ 24},{  7}}, {{ 88},{  7}},
+{{ 56},{  7}}, {{120},{  7}}, {{  4},{  7}}, {{ 68},{  7}}, {{ 36},{  7}},
+{{100},{  7}}, {{ 20},{  7}}, {{ 84},{  7}}, {{ 52},{  7}}, {{116},{  7}},
+{{  3},{  8}}, {{131},{  8}}, {{ 67},{  8}}, {{195},{  8}}, {{ 35},{  8}},
+{{163},{  8}}, {{ 99},{  8}}, {{227},{  8}}
+};
+
+local const ct_data static_dtree[D_CODES] = {
+{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
+{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
+{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
+{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
+{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
+{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
+};
+
+const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {
+ 0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  8,
+ 8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10,
+10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  0,  0, 16, 17,
+18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+};
+
+const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {
+ 0,  1,  2,  3,  4,  5,  6,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 12, 12,
+13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+};
+
+local const int base_length[LENGTH_CODES] = {
+0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+64, 80, 96, 112, 128, 160, 192, 224, 0
+};
+
+local const int base_dist[D_CODES] = {
+    0,     1,     2,     3,     4,     6,     8,    12,    16,    24,
+   32,    48,    64,    96,   128,   192,   256,   384,   512,   768,
+ 1024,  1536,  2048,  3072,  4096,  6144,  8192, 12288, 16384, 24576
+};
+
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/src/uncompr.c
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/src/uncompr.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/src/uncompr.c	(revision 453)
@@ -0,0 +1,93 @@
+/* uncompr.c -- decompress a memory buffer
+ * Copyright (C) 1995-2003, 2010, 2014, 2016 Jean-loup Gailly, Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+/* ===========================================================================
+     Decompresses the source buffer into the destination buffer.  *sourceLen is
+   the byte length of the source buffer. Upon entry, *destLen is the total size
+   of the destination buffer, which must be large enough to hold the entire
+   uncompressed data. (The size of the uncompressed data must have been saved
+   previously by the compressor and transmitted to the decompressor by some
+   mechanism outside the scope of this compression library.) Upon exit,
+   *destLen is the size of the decompressed data and *sourceLen is the number
+   of source bytes consumed. Upon return, source + *sourceLen points to the
+   first unused input byte.
+
+     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_BUF_ERROR if there was not enough room in the output buffer, or
+   Z_DATA_ERROR if the input data was corrupted, including if the input data is
+   an incomplete zlib stream.
+*/
+int ZEXPORT uncompress2 (dest, destLen, source, sourceLen)
+    Bytef *dest;
+    uLongf *destLen;
+    const Bytef *source;
+    uLong *sourceLen;
+{
+    z_stream stream;
+    int err;
+    const uInt max = (uInt)-1;
+    uLong len, left;
+    Byte buf[1];    /* for detection of incomplete stream when *destLen == 0 */
+
+    len = *sourceLen;
+    if (*destLen) {
+        left = *destLen;
+        *destLen = 0;
+    }
+    else {
+        left = 1;
+        dest = buf;
+    }
+
+    stream.next_in = (z_const Bytef *)source;
+    stream.avail_in = 0;
+    stream.zalloc = (alloc_func)0;
+    stream.zfree = (free_func)0;
+    stream.opaque = (voidpf)0;
+
+    err = inflateInit(&stream);
+    if (err != Z_OK) return err;
+
+    stream.next_out = dest;
+    stream.avail_out = 0;
+
+    do {
+        if (stream.avail_out == 0) {
+            stream.avail_out = left > (uLong)max ? max : (uInt)left;
+            left -= stream.avail_out;
+        }
+        if (stream.avail_in == 0) {
+            stream.avail_in = len > (uLong)max ? max : (uInt)len;
+            len -= stream.avail_in;
+        }
+        err = inflate(&stream, Z_NO_FLUSH);
+    } while (err == Z_OK);
+
+    *sourceLen -= len + stream.avail_in;
+    if (dest != buf)
+        *destLen = stream.total_out;
+    else if (stream.total_out && err == Z_BUF_ERROR)
+        left = 1;
+
+    inflateEnd(&stream);
+    return err == Z_STREAM_END ? Z_OK :
+           err == Z_NEED_DICT ? Z_DATA_ERROR  :
+           err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR :
+           err;
+}
+
+int ZEXPORT uncompress (dest, destLen, source, sourceLen)
+    Bytef *dest;
+    uLongf *destLen;
+    const Bytef *source;
+    uLong sourceLen;
+{
+    return uncompress2(dest, destLen, source, &sourceLen);
+}
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/src/zconf.h
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/src/zconf.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/src/zconf.h	(revision 453)
@@ -0,0 +1,536 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+#define Z_SOLO
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ * Even better than compiling with -DZ_PREFIX would be to use configure to set
+ * this permanently in zconf.h using "./configure --zprefix".
+ */
+#ifdef Z_PREFIX     /* may be set to #if 1 by ./configure */
+#  define Z_PREFIX_SET
+
+/* all linked symbols and init macros */
+#  define _dist_code            z__dist_code
+#  define _length_code          z__length_code
+#  define _tr_align             z__tr_align
+#  define _tr_flush_bits        z__tr_flush_bits
+#  define _tr_flush_block       z__tr_flush_block
+#  define _tr_init              z__tr_init
+#  define _tr_stored_block      z__tr_stored_block
+#  define _tr_tally             z__tr_tally
+#  define adler32               z_adler32
+#  define adler32_combine       z_adler32_combine
+#  define adler32_combine64     z_adler32_combine64
+#  define adler32_z             z_adler32_z
+#  ifndef Z_SOLO
+#    define compress              z_compress
+#    define compress2             z_compress2
+#    define compressBound         z_compressBound
+#  endif
+#  define crc32                 z_crc32
+#  define crc32_combine         z_crc32_combine
+#  define crc32_combine64       z_crc32_combine64
+#  define crc32_z               z_crc32_z
+#  define deflate               z_deflate
+#  define deflateBound          z_deflateBound
+#  define deflateCopy           z_deflateCopy
+#  define deflateEnd            z_deflateEnd
+#  define deflateGetDictionary  z_deflateGetDictionary
+#  define deflateInit           z_deflateInit
+#  define deflateInit2          z_deflateInit2
+#  define deflateInit2_         z_deflateInit2_
+#  define deflateInit_          z_deflateInit_
+#  define deflateParams         z_deflateParams
+#  define deflatePending        z_deflatePending
+#  define deflatePrime          z_deflatePrime
+#  define deflateReset          z_deflateReset
+#  define deflateResetKeep      z_deflateResetKeep
+#  define deflateSetDictionary  z_deflateSetDictionary
+#  define deflateSetHeader      z_deflateSetHeader
+#  define deflateTune           z_deflateTune
+#  define deflate_copyright     z_deflate_copyright
+#  define get_crc_table         z_get_crc_table
+#  ifndef Z_SOLO
+#    define gz_error              z_gz_error
+#    define gz_intmax             z_gz_intmax
+#    define gz_strwinerror        z_gz_strwinerror
+#    define gzbuffer              z_gzbuffer
+#    define gzclearerr            z_gzclearerr
+#    define gzclose               z_gzclose
+#    define gzclose_r             z_gzclose_r
+#    define gzclose_w             z_gzclose_w
+#    define gzdirect              z_gzdirect
+#    define gzdopen               z_gzdopen
+#    define gzeof                 z_gzeof
+#    define gzerror               z_gzerror
+#    define gzflush               z_gzflush
+#    define gzfread               z_gzfread
+#    define gzfwrite              z_gzfwrite
+#    define gzgetc                z_gzgetc
+#    define gzgetc_               z_gzgetc_
+#    define gzgets                z_gzgets
+#    define gzoffset              z_gzoffset
+#    define gzoffset64            z_gzoffset64
+#    define gzopen                z_gzopen
+#    define gzopen64              z_gzopen64
+#    ifdef _WIN32
+#      define gzopen_w              z_gzopen_w
+#    endif
+#    define gzprintf              z_gzprintf
+#    define gzputc                z_gzputc
+#    define gzputs                z_gzputs
+#    define gzread                z_gzread
+#    define gzrewind              z_gzrewind
+#    define gzseek                z_gzseek
+#    define gzseek64              z_gzseek64
+#    define gzsetparams           z_gzsetparams
+#    define gztell                z_gztell
+#    define gztell64              z_gztell64
+#    define gzungetc              z_gzungetc
+#    define gzvprintf             z_gzvprintf
+#    define gzwrite               z_gzwrite
+#  endif
+#  define inflate               z_inflate
+#  define inflateBack           z_inflateBack
+#  define inflateBackEnd        z_inflateBackEnd
+#  define inflateBackInit       z_inflateBackInit
+#  define inflateBackInit_      z_inflateBackInit_
+#  define inflateCodesUsed      z_inflateCodesUsed
+#  define inflateCopy           z_inflateCopy
+#  define inflateEnd            z_inflateEnd
+#  define inflateGetDictionary  z_inflateGetDictionary
+#  define inflateGetHeader      z_inflateGetHeader
+#  define inflateInit           z_inflateInit
+#  define inflateInit2          z_inflateInit2
+#  define inflateInit2_         z_inflateInit2_
+#  define inflateInit_          z_inflateInit_
+#  define inflateMark           z_inflateMark
+#  define inflatePrime          z_inflatePrime
+#  define inflateReset          z_inflateReset
+#  define inflateReset2         z_inflateReset2
+#  define inflateResetKeep      z_inflateResetKeep
+#  define inflateSetDictionary  z_inflateSetDictionary
+#  define inflateSync           z_inflateSync
+#  define inflateSyncPoint      z_inflateSyncPoint
+#  define inflateUndermine      z_inflateUndermine
+#  define inflateValidate       z_inflateValidate
+#  define inflate_copyright     z_inflate_copyright
+#  define inflate_fast          z_inflate_fast
+#  define inflate_table         z_inflate_table
+#  ifndef Z_SOLO
+#    define uncompress            z_uncompress
+#    define uncompress2           z_uncompress2
+#  endif
+#  define zError                z_zError
+#  ifndef Z_SOLO
+#    define zcalloc               z_zcalloc
+#    define zcfree                z_zcfree
+#  endif
+#  define zlibCompileFlags      z_zlibCompileFlags
+#  define zlibVersion           z_zlibVersion
+
+/* all zlib typedefs in zlib.h and zconf.h */
+#  define Byte                  z_Byte
+#  define Bytef                 z_Bytef
+#  define alloc_func            z_alloc_func
+#  define charf                 z_charf
+#  define free_func             z_free_func
+#  ifndef Z_SOLO
+#    define gzFile                z_gzFile
+#  endif
+#  define gz_header             z_gz_header
+#  define gz_headerp            z_gz_headerp
+#  define in_func               z_in_func
+#  define intf                  z_intf
+#  define out_func              z_out_func
+#  define uInt                  z_uInt
+#  define uIntf                 z_uIntf
+#  define uLong                 z_uLong
+#  define uLongf                z_uLongf
+#  define voidp                 z_voidp
+#  define voidpc                z_voidpc
+#  define voidpf                z_voidpf
+
+/* all zlib structs in zlib.h and zconf.h */
+#  define gz_header_s           z_gz_header_s
+#  define internal_state        z_internal_state
+
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+#  define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+#  define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+#  define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+#  ifndef WIN32
+#    define WIN32
+#  endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+#  if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+#    ifndef SYS16BIT
+#      define SYS16BIT
+#    endif
+#  endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+#  define MAXSEG_64K
+#endif
+#ifdef MSDOS
+#  define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+#  ifndef STDC
+#    define STDC
+#  endif
+#  if __STDC_VERSION__ >= 199901L
+#    ifndef STDC99
+#      define STDC99
+#    endif
+#  endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+#  define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC)    /* iSeries (formerly AS/400). */
+#  define STDC
+#endif
+
+#ifndef STDC
+#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+#    define const       /* note: need a more gentle solution here */
+#  endif
+#endif
+
+#if defined(ZLIB_CONST) && !defined(z_const)
+#  define z_const const
+#else
+#  define z_const
+#endif
+
+#ifdef Z_SOLO
+   typedef unsigned long z_size_t;
+#else
+#  define z_longlong long long
+#  if defined(NO_SIZE_T)
+     typedef unsigned NO_SIZE_T z_size_t;
+#  elif defined(STDC)
+#    include <stddef.h>
+     typedef size_t z_size_t;
+#  else
+     typedef unsigned long z_size_t;
+#  endif
+#  undef z_longlong
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+#  ifdef MAXSEG_64K
+#    define MAX_MEM_LEVEL 8
+#  else
+#    define MAX_MEM_LEVEL 9
+#  endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+#  define MAX_WBITS   15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+            (1 << (windowBits+2)) +  (1 << (memLevel+9))
+ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+   The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus about 7 kilobytes
+ for small objects.
+*/
+
+                        /* Type declarations */
+
+#ifndef OF /* function prototypes */
+#  ifdef STDC
+#    define OF(args)  args
+#  else
+#    define OF(args)  ()
+#  endif
+#endif
+
+#ifndef Z_ARG /* function prototypes for stdarg */
+#  if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#    define Z_ARG(args)  args
+#  else
+#    define Z_ARG(args)  ()
+#  endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+#  if defined(M_I86SM) || defined(M_I86MM)
+     /* MSC small or medium model */
+#    define SMALL_MEDIUM
+#    ifdef _MSC_VER
+#      define FAR _far
+#    else
+#      define FAR far
+#    endif
+#  endif
+#  if (defined(__SMALL__) || defined(__MEDIUM__))
+     /* Turbo C small or medium model */
+#    define SMALL_MEDIUM
+#    ifdef __BORLANDC__
+#      define FAR _far
+#    else
+#      define FAR far
+#    endif
+#  endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+   /* If building or using zlib as a DLL, define ZLIB_DLL.
+    * This is not mandatory, but it offers a little performance increase.
+    */
+#  ifdef ZLIB_DLL
+#    if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+#      ifdef ZLIB_INTERNAL
+#        define ZEXTERN extern __declspec(dllexport)
+#      else
+#        define ZEXTERN extern __declspec(dllimport)
+#      endif
+#    endif
+#  endif  /* ZLIB_DLL */
+   /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+    * define ZLIB_WINAPI.
+    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+    */
+#  ifdef ZLIB_WINAPI
+#    ifdef FAR
+#      undef FAR
+#    endif
+#    include <windows.h>
+     /* No need for _export, use ZLIB.DEF instead. */
+     /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+#    define ZEXPORT WINAPI
+#    ifdef WIN32
+#      define ZEXPORTVA WINAPIV
+#    else
+#      define ZEXPORTVA FAR CDECL
+#    endif
+#  endif
+#endif
+
+#if defined (__BEOS__)
+#  ifdef ZLIB_DLL
+#    ifdef ZLIB_INTERNAL
+#      define ZEXPORT   __declspec(dllexport)
+#      define ZEXPORTVA __declspec(dllexport)
+#    else
+#      define ZEXPORT   __declspec(dllimport)
+#      define ZEXPORTVA __declspec(dllimport)
+#    endif
+#  endif
+#endif
+
+#ifndef ZEXTERN
+#  define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+#  define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+#  define ZEXPORTVA
+#endif
+
+#ifndef FAR
+#  define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char  Byte;  /* 8 bits */
+#endif
+typedef unsigned int   uInt;  /* 16 bits or more */
+typedef unsigned long  uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+#  define Bytef Byte FAR
+#else
+   typedef Byte  FAR Bytef;
+#endif
+typedef char  FAR charf;
+typedef int   FAR intf;
+typedef uInt  FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+   typedef void const *voidpc;
+   typedef void FAR   *voidpf;
+   typedef void       *voidp;
+#else
+   typedef Byte const *voidpc;
+   typedef Byte FAR   *voidpf;
+   typedef Byte       *voidp;
+#endif
+
+#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
+#  include <limits.h>
+#  if (UINT_MAX == 0xffffffffUL)
+#    define Z_U4 unsigned
+#  elif (ULONG_MAX == 0xffffffffUL)
+#    define Z_U4 unsigned long
+#  elif (USHRT_MAX == 0xffffffffUL)
+#    define Z_U4 unsigned short
+#  endif
+#endif
+
+#ifdef Z_U4
+   typedef Z_U4 z_crc_t;
+#else
+   typedef unsigned long z_crc_t;
+#endif
+
+#ifdef HAVE_UNISTD_H    /* may be set to #if 1 by ./configure */
+#  define Z_HAVE_UNISTD_H
+#endif
+
+#ifdef HAVE_STDARG_H    /* may be set to #if 1 by ./configure */
+#  define Z_HAVE_STDARG_H
+#endif
+
+#ifdef STDC
+#  ifndef Z_SOLO
+#    include <sys/types.h>      /* for off_t */
+#  endif
+#endif
+
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#  ifndef Z_SOLO
+#    include <stdarg.h>         /* for va_list */
+#  endif
+#endif
+
+#ifdef _WIN32
+#  ifndef Z_SOLO
+#    include <stddef.h>         /* for wchar_t */
+#  endif
+#endif
+
+/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
+ * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
+ * though the former does not conform to the LFS document), but considering
+ * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
+ * equivalently requesting no 64-bit operations
+ */
+#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
+#  undef _LARGEFILE64_SOURCE
+#endif
+
+#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)
+#  define Z_HAVE_UNISTD_H
+#endif
+#ifndef Z_SOLO
+#  if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
+#    include <unistd.h>         /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
+#    ifdef VMS
+#      include <unixio.h>       /* for off_t */
+#    endif
+#    ifndef z_off_t
+#      define z_off_t off_t
+#    endif
+#  endif
+#endif
+
+#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
+#  define Z_LFS64
+#endif
+
+#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
+#  define Z_LARGE64
+#endif
+
+#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
+#  define Z_WANT64
+#endif
+
+#if !defined(SEEK_SET) && !defined(Z_SOLO)
+#  define SEEK_SET        0       /* Seek from beginning of file.  */
+#  define SEEK_CUR        1       /* Seek from current position.  */
+#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
+#endif
+
+#ifndef z_off_t
+#  define z_off_t long
+#endif
+
+#if !defined(_WIN32) && defined(Z_LARGE64)
+#  define z_off64_t off64_t
+#else
+#  if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
+#    define z_off64_t __int64
+#  else
+#    define z_off64_t z_off_t
+#  endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+  #pragma map(deflateInit_,"DEIN")
+  #pragma map(deflateInit2_,"DEIN2")
+  #pragma map(deflateEnd,"DEEND")
+  #pragma map(deflateBound,"DEBND")
+  #pragma map(inflateInit_,"ININ")
+  #pragma map(inflateInit2_,"ININ2")
+  #pragma map(inflateEnd,"INEND")
+  #pragma map(inflateSync,"INSY")
+  #pragma map(inflateSetDictionary,"INSEDI")
+  #pragma map(compressBound,"CMBND")
+  #pragma map(inflate_table,"INTABL")
+  #pragma map(inflate_fast,"INFA")
+  #pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/src/zlib.h
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/src/zlib.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/src/zlib.h	(revision 453)
@@ -0,0 +1,1912 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+  version 1.2.11, January 15th, 2017
+
+  Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  jloup@gzip.org          madler@alumni.caltech.edu
+
+
+  The data format used by the zlib library is described by RFCs (Request for
+  Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
+  (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).
+*/
+
+#ifndef ZLIB_H
+#define ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.2.11"
+#define ZLIB_VERNUM 0x12b0
+#define ZLIB_VER_MAJOR 1
+#define ZLIB_VER_MINOR 2
+#define ZLIB_VER_REVISION 11
+#define ZLIB_VER_SUBREVISION 0
+
+/*
+    The 'zlib' compression library provides in-memory compression and
+  decompression functions, including integrity checks of the uncompressed data.
+  This version of the library supports only one compression method (deflation)
+  but other algorithms will be added later and will have the same stream
+  interface.
+
+    Compression can be done in a single step if the buffers are large enough,
+  or can be done by repeated calls of the compression function.  In the latter
+  case, the application must provide more input and/or consume the output
+  (providing more output space) before each call.
+
+    The compressed data format used by default by the in-memory functions is
+  the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+  around a deflate stream, which is itself documented in RFC 1951.
+
+    The library also supports reading and writing files in gzip (.gz) format
+  with an interface similar to that of stdio using the functions that start
+  with "gz".  The gzip format is different from the zlib format.  gzip is a
+  gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+    This library can optionally read and write gzip and raw deflate streams in
+  memory as well.
+
+    The zlib format was designed to be compact and fast for use in memory
+  and on communications channels.  The gzip format was designed for single-
+  file compression on file systems, has a larger header than zlib to maintain
+  directory information, and uses a different, slower check method than zlib.
+
+    The library does not install any signal handler.  The decoder checks
+  the consistency of the compressed data, so the library should never crash
+  even in the case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void   (*free_func)  OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+    z_const Bytef *next_in;     /* next input byte */
+    uInt     avail_in;  /* number of bytes available at next_in */
+    uLong    total_in;  /* total number of input bytes read so far */
+
+    Bytef    *next_out; /* next output byte will go here */
+    uInt     avail_out; /* remaining free space at next_out */
+    uLong    total_out; /* total number of bytes output so far */
+
+    z_const char *msg;  /* last error message, NULL if no error */
+    struct internal_state FAR *state; /* not visible by applications */
+
+    alloc_func zalloc;  /* used to allocate the internal state */
+    free_func  zfree;   /* used to free the internal state */
+    voidpf     opaque;  /* private data object passed to zalloc and zfree */
+
+    int     data_type;  /* best guess about the data type: binary or text
+                           for deflate, or the decoding state for inflate */
+    uLong   adler;      /* Adler-32 or CRC-32 value of the uncompressed data */
+    uLong   reserved;   /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+     gzip header information passed to and from zlib routines.  See RFC 1952
+  for more details on the meanings of these fields.
+*/
+typedef struct gz_header_s {
+    int     text;       /* true if compressed data believed to be text */
+    uLong   time;       /* modification time */
+    int     xflags;     /* extra flags (not used when writing a gzip file) */
+    int     os;         /* operating system */
+    Bytef   *extra;     /* pointer to extra field or Z_NULL if none */
+    uInt    extra_len;  /* extra field length (valid if extra != Z_NULL) */
+    uInt    extra_max;  /* space at extra (only when reading header) */
+    Bytef   *name;      /* pointer to zero-terminated file name or Z_NULL */
+    uInt    name_max;   /* space at name (only when reading header) */
+    Bytef   *comment;   /* pointer to zero-terminated comment or Z_NULL */
+    uInt    comm_max;   /* space at comment (only when reading header) */
+    int     hcrc;       /* true if there was or will be a header crc */
+    int     done;       /* true when done reading gzip header (not used
+                           when writing a gzip file) */
+} gz_header;
+
+typedef gz_header FAR *gz_headerp;
+
+/*
+     The application must update next_in and avail_in when avail_in has dropped
+   to zero.  It must update next_out and avail_out when avail_out has dropped
+   to zero.  The application must initialize zalloc, zfree and opaque before
+   calling the init function.  All other fields are set by the compression
+   library and must not be updated by the application.
+
+     The opaque value provided by the application will be passed as the first
+   parameter for calls of zalloc and zfree.  This can be useful for custom
+   memory management.  The compression library attaches no meaning to the
+   opaque value.
+
+     zalloc must return Z_NULL if there is not enough memory for the object.
+   If zlib is used in a multi-threaded application, zalloc and zfree must be
+   thread safe.  In that case, zlib is thread-safe.  When zalloc and zfree are
+   Z_NULL on entry to the initialization function, they are set to internal
+   routines that use the standard library functions malloc() and free().
+
+     On 16-bit systems, the functions zalloc and zfree must be able to allocate
+   exactly 65536 bytes, but will not be required to allocate more than this if
+   the symbol MAXSEG_64K is defined (see zconf.h).  WARNING: On MSDOS, pointers
+   returned by zalloc for objects of exactly 65536 bytes *must* have their
+   offset normalized to zero.  The default allocation function provided by this
+   library ensures this (see zutil.c).  To reduce memory requirements and avoid
+   any allocation of 64K objects, at the expense of compression ratio, compile
+   the library with -DMAX_WBITS=14 (see zconf.h).
+
+     The fields total_in and total_out can be used for statistics or progress
+   reports.  After compression, total_in holds the total size of the
+   uncompressed data and may be saved for use by the decompressor (particularly
+   if the decompressor wants to decompress everything in a single step).
+*/
+
+                        /* constants */
+
+#define Z_NO_FLUSH      0
+#define Z_PARTIAL_FLUSH 1
+#define Z_SYNC_FLUSH    2
+#define Z_FULL_FLUSH    3
+#define Z_FINISH        4
+#define Z_BLOCK         5
+#define Z_TREES         6
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK            0
+#define Z_STREAM_END    1
+#define Z_NEED_DICT     2
+#define Z_ERRNO        (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR   (-3)
+#define Z_MEM_ERROR    (-4)
+#define Z_BUF_ERROR    (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative values
+ * are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION         0
+#define Z_BEST_SPEED             1
+#define Z_BEST_COMPRESSION       9
+#define Z_DEFAULT_COMPRESSION  (-1)
+/* compression levels */
+
+#define Z_FILTERED            1
+#define Z_HUFFMAN_ONLY        2
+#define Z_RLE                 3
+#define Z_FIXED               4
+#define Z_DEFAULT_STRATEGY    0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY   0
+#define Z_TEXT     1
+#define Z_ASCII    Z_TEXT   /* for compatibility with 1.2.2 and earlier */
+#define Z_UNKNOWN  2
+/* Possible values of the data_type field for deflate() */
+
+#define Z_DEFLATED   8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+
+                        /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+   If the first character differs, the library code actually used is not
+   compatible with the zlib.h header file used by the application.  This check
+   is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+     Initializes the internal stream state for compression.  The fields
+   zalloc, zfree and opaque must be initialized before by the caller.  If
+   zalloc and zfree are set to Z_NULL, deflateInit updates them to use default
+   allocation functions.
+
+     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+   1 gives best speed, 9 gives best compression, 0 gives no compression at all
+   (the input data is simply copied a block at a time).  Z_DEFAULT_COMPRESSION
+   requests a default compromise between speed and compression (currently
+   equivalent to level 6).
+
+     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if level is not a valid compression level, or
+   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+   with the version assumed by the caller (ZLIB_VERSION).  msg is set to null
+   if there is no error message.  deflateInit does not perform any compression:
+   this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+    deflate compresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full.  It may introduce
+  some output latency (reading input without producing any output) except when
+  forced to flush.
+
+    The detailed semantics are as follows.  deflate performs one or both of the
+  following actions:
+
+  - Compress more input starting at next_in and update next_in and avail_in
+    accordingly.  If not all input can be processed (because there is not
+    enough room in the output buffer), next_in and avail_in are updated and
+    processing will resume at this point for the next call of deflate().
+
+  - Generate more output starting at next_out and update next_out and avail_out
+    accordingly.  This action is forced if the parameter flush is non zero.
+    Forcing flush frequently degrades the compression ratio, so this parameter
+    should be set only when necessary.  Some output may be provided even if
+    flush is zero.
+
+    Before the call of deflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming more
+  output, and updating avail_in or avail_out accordingly; avail_out should
+  never be zero before the call.  The application can consume the compressed
+  output when it wants, for example when the output buffer is full (avail_out
+  == 0), or after each call of deflate().  If deflate returns Z_OK and with
+  zero avail_out, it must be called again after making room in the output
+  buffer because there might be more output pending. See deflatePending(),
+  which can be used if desired to determine whether or not there is more ouput
+  in that case.
+
+    Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
+  decide how much data to accumulate before producing output, in order to
+  maximize compression.
+
+    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+  flushed to the output buffer and the output is aligned on a byte boundary, so
+  that the decompressor can get all input data available so far.  (In
+  particular avail_in is zero after the call if enough output space has been
+  provided before the call.) Flushing may degrade compression for some
+  compression algorithms and so it should be used only when necessary.  This
+  completes the current deflate block and follows it with an empty stored block
+  that is three bits plus filler bits to the next byte, followed by four bytes
+  (00 00 ff ff).
+
+    If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the
+  output buffer, but the output is not aligned to a byte boundary.  All of the
+  input data so far will be available to the decompressor, as for Z_SYNC_FLUSH.
+  This completes the current deflate block and follows it with an empty fixed
+  codes block that is 10 bits long.  This assures that enough bytes are output
+  in order for the decompressor to finish the block before the empty fixed
+  codes block.
+
+    If flush is set to Z_BLOCK, a deflate block is completed and emitted, as
+  for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to
+  seven bits of the current block are held to be written as the next byte after
+  the next deflate block is completed.  In this case, the decompressor may not
+  be provided enough bits at this point in order to complete decompression of
+  the data provided so far to the compressor.  It may need to wait for the next
+  block to be emitted.  This is for advanced applications that need to control
+  the emission of deflate blocks.
+
+    If flush is set to Z_FULL_FLUSH, all output is flushed as with
+  Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+  restart from this point if previous compressed data has been damaged or if
+  random access is desired.  Using Z_FULL_FLUSH too often can seriously degrade
+  compression.
+
+    If deflate returns with avail_out == 0, this function must be called again
+  with the same value of the flush parameter and more output space (updated
+  avail_out), until the flush is complete (deflate returns with non-zero
+  avail_out).  In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+  avail_out is greater than six to avoid repeated flush markers due to
+  avail_out == 0 on return.
+
+    If the parameter flush is set to Z_FINISH, pending input is processed,
+  pending output is flushed and deflate returns with Z_STREAM_END if there was
+  enough output space.  If deflate returns with Z_OK or Z_BUF_ERROR, this
+  function must be called again with Z_FINISH and more output space (updated
+  avail_out) but no more input data, until it returns with Z_STREAM_END or an
+  error.  After deflate has returned Z_STREAM_END, the only possible operations
+  on the stream are deflateReset or deflateEnd.
+
+    Z_FINISH can be used in the first deflate call after deflateInit if all the
+  compression is to be done in a single step.  In order to complete in one
+  call, avail_out must be at least the value returned by deflateBound (see
+  below).  Then deflate is guaranteed to return Z_STREAM_END.  If not enough
+  output space is provided, deflate will not return Z_STREAM_END, and it must
+  be called again as described above.
+
+    deflate() sets strm->adler to the Adler-32 checksum of all input read
+  so far (that is, total_in bytes).  If a gzip stream is being generated, then
+  strm->adler will be the CRC-32 checksum of the input read so far.  (See
+  deflateInit2 below.)
+
+    deflate() may update strm->data_type if it can make a good guess about
+  the input data type (Z_BINARY or Z_TEXT).  If in doubt, the data is
+  considered binary.  This field is only for information purposes and does not
+  affect the compression algorithm in any manner.
+
+    deflate() returns Z_OK if some progress has been made (more input
+  processed or more output produced), Z_STREAM_END if all input has been
+  consumed and all output has been produced (only when flush is set to
+  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+  if next_in or next_out was Z_NULL or the state was inadvertently written over
+  by the application), or Z_BUF_ERROR if no progress is possible (for example
+  avail_in or avail_out was zero).  Note that Z_BUF_ERROR is not fatal, and
+  deflate() can be called again with more input and more output space to
+  continue compressing.
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any pending
+   output.
+
+     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+   stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+   prematurely (some input or output was discarded).  In the error case, msg
+   may be set but then points to a static string (which must not be
+   deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+     Initializes the internal stream state for decompression.  The fields
+   next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+   the caller.  In the current version of inflate, the provided input is not
+   read or consumed.  The allocation of a sliding window will be deferred to
+   the first call of inflate (if the decompression does not complete on the
+   first call).  If zalloc and zfree are set to Z_NULL, inflateInit updates
+   them to use default allocation functions.
+
+     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+   version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+   invalid, such as a null pointer to the structure.  msg is set to null if
+   there is no error message.  inflateInit does not perform any decompression.
+   Actual decompression will be done by inflate().  So next_in, and avail_in,
+   next_out, and avail_out are unused and unchanged.  The current
+   implementation of inflateInit() does not process any header information --
+   that is deferred until inflate() is called.
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+    inflate decompresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full.  It may introduce
+  some output latency (reading input without producing any output) except when
+  forced to flush.
+
+  The detailed semantics are as follows.  inflate performs one or both of the
+  following actions:
+
+  - Decompress more input starting at next_in and update next_in and avail_in
+    accordingly.  If not all input can be processed (because there is not
+    enough room in the output buffer), then next_in and avail_in are updated
+    accordingly, and processing will resume at this point for the next call of
+    inflate().
+
+  - Generate more output starting at next_out and update next_out and avail_out
+    accordingly.  inflate() provides as much output as possible, until there is
+    no more input data or no more space in the output buffer (see below about
+    the flush parameter).
+
+    Before the call of inflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming more
+  output, and updating the next_* and avail_* values accordingly.  If the
+  caller of inflate() does not provide both available input and available
+  output space, it is possible that there will be no progress made.  The
+  application can consume the uncompressed output when it wants, for example
+  when the output buffer is full (avail_out == 0), or after each call of
+  inflate().  If inflate returns Z_OK and with zero avail_out, it must be
+  called again after making room in the output buffer because there might be
+  more output pending.
+
+    The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH,
+  Z_BLOCK, or Z_TREES.  Z_SYNC_FLUSH requests that inflate() flush as much
+  output as possible to the output buffer.  Z_BLOCK requests that inflate()
+  stop if and when it gets to the next deflate block boundary.  When decoding
+  the zlib or gzip format, this will cause inflate() to return immediately
+  after the header and before the first block.  When doing a raw inflate,
+  inflate() will go ahead and process the first block, and will return when it
+  gets to the end of that block, or when it runs out of data.
+
+    The Z_BLOCK option assists in appending to or combining deflate streams.
+  To assist in this, on return inflate() always sets strm->data_type to the
+  number of unused bits in the last byte taken from strm->next_in, plus 64 if
+  inflate() is currently decoding the last block in the deflate stream, plus
+  128 if inflate() returned immediately after decoding an end-of-block code or
+  decoding the complete header up to just before the first byte of the deflate
+  stream.  The end-of-block will not be indicated until all of the uncompressed
+  data from that block has been written to strm->next_out.  The number of
+  unused bits may in general be greater than seven, except when bit 7 of
+  data_type is set, in which case the number of unused bits will be less than
+  eight.  data_type is set as noted here every time inflate() returns for all
+  flush options, and so can be used to determine the amount of currently
+  consumed input in bits.
+
+    The Z_TREES option behaves as Z_BLOCK does, but it also returns when the
+  end of each deflate block header is reached, before any actual data in that
+  block is decoded.  This allows the caller to determine the length of the
+  deflate block header for later use in random access within a deflate block.
+  256 is added to the value of strm->data_type when inflate() returns
+  immediately after reaching the end of the deflate block header.
+
+    inflate() should normally be called until it returns Z_STREAM_END or an
+  error.  However if all decompression is to be performed in a single step (a
+  single call of inflate), the parameter flush should be set to Z_FINISH.  In
+  this case all pending input is processed and all pending output is flushed;
+  avail_out must be large enough to hold all of the uncompressed data for the
+  operation to complete.  (The size of the uncompressed data may have been
+  saved by the compressor for this purpose.)  The use of Z_FINISH is not
+  required to perform an inflation in one step.  However it may be used to
+  inform inflate that a faster approach can be used for the single inflate()
+  call.  Z_FINISH also informs inflate to not maintain a sliding window if the
+  stream completes, which reduces inflate's memory footprint.  If the stream
+  does not complete, either because not all of the stream is provided or not
+  enough output space is provided, then a sliding window will be allocated and
+  inflate() can be called again to continue the operation as if Z_NO_FLUSH had
+  been used.
+
+     In this implementation, inflate() always flushes as much output as
+  possible to the output buffer, and always uses the faster approach on the
+  first call.  So the effects of the flush parameter in this implementation are
+  on the return value of inflate() as noted below, when inflate() returns early
+  when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of
+  memory for a sliding window when Z_FINISH is used.
+
+     If a preset dictionary is needed after this call (see inflateSetDictionary
+  below), inflate sets strm->adler to the Adler-32 checksum of the dictionary
+  chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+  strm->adler to the Adler-32 checksum of all output produced so far (that is,
+  total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+  below.  At the end of the stream, inflate() checks that its computed Adler-32
+  checksum is equal to that saved by the compressor and returns Z_STREAM_END
+  only if the checksum is correct.
+
+    inflate() can decompress and check either zlib-wrapped or gzip-wrapped
+  deflate data.  The header type is detected automatically, if requested when
+  initializing with inflateInit2().  Any information contained in the gzip
+  header is not retained unless inflateGetHeader() is used.  When processing
+  gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output
+  produced so far.  The CRC-32 is checked against the gzip trailer, as is the
+  uncompressed length, modulo 2^32.
+
+    inflate() returns Z_OK if some progress has been made (more input processed
+  or more output produced), Z_STREAM_END if the end of the compressed data has
+  been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+  corrupted (input stream not conforming to the zlib format or incorrect check
+  value, in which case strm->msg points to a string with a more specific
+  error), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+  next_in or next_out was Z_NULL, or the state was inadvertently written over
+  by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR
+  if no progress was possible or if there was not enough room in the output
+  buffer when Z_FINISH is used.  Note that Z_BUF_ERROR is not fatal, and
+  inflate() can be called again with more input and more output space to
+  continue decompressing.  If Z_DATA_ERROR is returned, the application may
+  then call inflateSync() to look for a good compression block if a partial
+  recovery of the data is to be attempted.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any pending
+   output.
+
+     inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state
+   was inconsistent.
+*/
+
+
+                        /* Advanced functions */
+
+/*
+    The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+                                     int  level,
+                                     int  method,
+                                     int  windowBits,
+                                     int  memLevel,
+                                     int  strategy));
+
+     This is another version of deflateInit with more compression options.  The
+   fields next_in, zalloc, zfree and opaque must be initialized before by the
+   caller.
+
+     The method parameter is the compression method.  It must be Z_DEFLATED in
+   this version of the library.
+
+     The windowBits parameter is the base two logarithm of the window size
+   (the size of the history buffer).  It should be in the range 8..15 for this
+   version of the library.  Larger values of this parameter result in better
+   compression at the expense of memory usage.  The default value is 15 if
+   deflateInit is used instead.
+
+     For the current implementation of deflate(), a windowBits value of 8 (a
+   window size of 256 bytes) is not supported.  As a result, a request for 8
+   will result in 9 (a 512-byte window).  In that case, providing 8 to
+   inflateInit2() will result in an error when the zlib header with 9 is
+   checked against the initialization of inflate().  The remedy is to not use 8
+   with deflateInit2() with this initialization, or at least in that case use 9
+   with inflateInit2().
+
+     windowBits can also be -8..-15 for raw deflate.  In this case, -windowBits
+   determines the window size.  deflate() will then generate raw deflate data
+   with no zlib header or trailer, and will not compute a check value.
+
+     windowBits can also be greater than 15 for optional gzip encoding.  Add
+   16 to windowBits to write a simple gzip header and trailer around the
+   compressed data instead of a zlib wrapper.  The gzip header will have no
+   file name, no extra data, no comment, no modification time (set to zero), no
+   header crc, and the operating system will be set to the appropriate value,
+   if the operating system was determined at compile time.  If a gzip stream is
+   being written, strm->adler is a CRC-32 instead of an Adler-32.
+
+     For raw deflate or gzip encoding, a request for a 256-byte window is
+   rejected as invalid, since only the zlib header provides a means of
+   transmitting the window size to the decompressor.
+
+     The memLevel parameter specifies how much memory should be allocated
+   for the internal compression state.  memLevel=1 uses minimum memory but is
+   slow and reduces compression ratio; memLevel=9 uses maximum memory for
+   optimal speed.  The default value is 8.  See zconf.h for total memory usage
+   as a function of windowBits and memLevel.
+
+     The strategy parameter is used to tune the compression algorithm.  Use the
+   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+   filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
+   string match), or Z_RLE to limit match distances to one (run-length
+   encoding).  Filtered data consists mostly of small values with a somewhat
+   random distribution.  In this case, the compression algorithm is tuned to
+   compress them better.  The effect of Z_FILTERED is to force more Huffman
+   coding and less string matching; it is somewhat intermediate between
+   Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY.  Z_RLE is designed to be almost as
+   fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data.  The
+   strategy parameter only affects the compression ratio but not the
+   correctness of the compressed output even if it is not set appropriately.
+   Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler
+   decoder for special applications.
+
+     deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid
+   method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is
+   incompatible with the version assumed by the caller (ZLIB_VERSION).  msg is
+   set to null if there is no error message.  deflateInit2 does not perform any
+   compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the compression dictionary from the given byte sequence
+   without producing any compressed output.  When using the zlib format, this
+   function must be called immediately after deflateInit, deflateInit2 or
+   deflateReset, and before any call of deflate.  When doing raw deflate, this
+   function must be called either before any call of deflate, or immediately
+   after the completion of a deflate block, i.e. after all input has been
+   consumed and all output has been delivered when using any of the flush
+   options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH.  The
+   compressor and decompressor must use exactly the same dictionary (see
+   inflateSetDictionary).
+
+     The dictionary should consist of strings (byte sequences) that are likely
+   to be encountered later in the data to be compressed, with the most commonly
+   used strings preferably put towards the end of the dictionary.  Using a
+   dictionary is most useful when the data to be compressed is short and can be
+   predicted with good accuracy; the data can then be compressed better than
+   with the default empty dictionary.
+
+     Depending on the size of the compression data structures selected by
+   deflateInit or deflateInit2, a part of the dictionary may in effect be
+   discarded, for example if the dictionary is larger than the window size
+   provided in deflateInit or deflateInit2.  Thus the strings most likely to be
+   useful should be put at the end of the dictionary, not at the front.  In
+   addition, the current implementation of deflate will use at most the window
+   size minus 262 bytes of the provided dictionary.
+
+     Upon return of this function, strm->adler is set to the Adler-32 value
+   of the dictionary; the decompressor may later use this value to determine
+   which dictionary has been used by the compressor.  (The Adler-32 value
+   applies to the whole dictionary even if only a subset of the dictionary is
+   actually used by the compressor.) If a raw deflate was requested, then the
+   Adler-32 value is not computed and strm->adler is not set.
+
+     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is
+   inconsistent (for example if deflate has already been called for this stream
+   or if not at a block boundary for raw deflate).  deflateSetDictionary does
+   not perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm,
+                                             Bytef *dictionary,
+                                             uInt  *dictLength));
+/*
+     Returns the sliding dictionary being maintained by deflate.  dictLength is
+   set to the number of bytes in the dictionary, and that many bytes are copied
+   to dictionary.  dictionary must have enough space, where 32768 bytes is
+   always enough.  If deflateGetDictionary() is called with dictionary equal to
+   Z_NULL, then only the dictionary length is returned, and nothing is copied.
+   Similary, if dictLength is Z_NULL, then it is not set.
+
+     deflateGetDictionary() may return a length less than the window size, even
+   when more than the window size in input has been provided. It may return up
+   to 258 bytes less in that case, due to how zlib's implementation of deflate
+   manages the sliding window and lookahead for matches, where matches can be
+   up to 258 bytes long. If the application needs the last window-size bytes of
+   input, then that would need to be saved by the application outside of zlib.
+
+     deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
+   stream state is inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+                                    z_streamp source));
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when several compression strategies will be
+   tried, for example when there are several ways of pre-processing the input
+   data with a filter.  The streams that will be discarded should then be freed
+   by calling deflateEnd.  Note that deflateCopy duplicates the internal
+   compression state which can be quite large, so this strategy is slow and can
+   consume lots of memory.
+
+     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being Z_NULL).  msg is left unchanged in both source and
+   destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to deflateEnd followed by deflateInit, but
+   does not free and reallocate the internal compression state.  The stream
+   will leave the compression level and any other attributes that may have been
+   set unchanged.
+
+     deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+                                      int level,
+                                      int strategy));
+/*
+     Dynamically update the compression level and compression strategy.  The
+   interpretation of level and strategy is as in deflateInit2().  This can be
+   used to switch between compression and straight copy of the input data, or
+   to switch to a different kind of input data requiring a different strategy.
+   If the compression approach (which is a function of the level) or the
+   strategy is changed, and if any input has been consumed in a previous
+   deflate() call, then the input available so far is compressed with the old
+   level and strategy using deflate(strm, Z_BLOCK).  There are three approaches
+   for the compression levels 0, 1..3, and 4..9 respectively.  The new level
+   and strategy will take effect at the next call of deflate().
+
+     If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does
+   not have enough output space to complete, then the parameter change will not
+   take effect.  In this case, deflateParams() can be called again with the
+   same parameters and more output space to try again.
+
+     In order to assure a change in the parameters on the first try, the
+   deflate stream should be flushed using deflate() with Z_BLOCK or other flush
+   request until strm.avail_out is not zero, before calling deflateParams().
+   Then no more input data should be provided before the deflateParams() call.
+   If this is done, the old level and strategy will be applied to the data
+   compressed before deflateParams(), and the new level and strategy will be
+   applied to the the data compressed after deflateParams().
+
+     deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream
+   state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if
+   there was not enough output space to complete the compression of the
+   available input data before a change in the strategy or approach.  Note that
+   in the case of a Z_BUF_ERROR, the parameters are not changed.  A return
+   value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be
+   retried with more output space.
+*/
+
+ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
+                                    int good_length,
+                                    int max_lazy,
+                                    int nice_length,
+                                    int max_chain));
+/*
+     Fine tune deflate's internal compression parameters.  This should only be
+   used by someone who understands the algorithm used by zlib's deflate for
+   searching for the best matching string, and even then only by the most
+   fanatic optimizer trying to squeeze out the last compressed bit for their
+   specific input data.  Read the deflate.c source code for the meaning of the
+   max_lazy, good_length, nice_length, and max_chain parameters.
+
+     deflateTune() can be called after deflateInit() or deflateInit2(), and
+   returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
+ */
+
+ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
+                                       uLong sourceLen));
+/*
+     deflateBound() returns an upper bound on the compressed size after
+   deflation of sourceLen bytes.  It must be called after deflateInit() or
+   deflateInit2(), and after deflateSetHeader(), if used.  This would be used
+   to allocate an output buffer for deflation in a single pass, and so would be
+   called before deflate().  If that first deflate() call is provided the
+   sourceLen input bytes, an output buffer allocated to the size returned by
+   deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed
+   to return Z_STREAM_END.  Note that it is possible for the compressed size to
+   be larger than the value returned by deflateBound() if flush options other
+   than Z_FINISH or Z_NO_FLUSH are used.
+*/
+
+ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm,
+                                       unsigned *pending,
+                                       int *bits));
+/*
+     deflatePending() returns the number of bytes and bits of output that have
+   been generated, but not yet provided in the available output.  The bytes not
+   provided would be due to the available output space having being consumed.
+   The number of bits of output not provided are between 0 and 7, where they
+   await more bits to join them in order to fill out a full byte.  If pending
+   or bits are Z_NULL, then those values are not set.
+
+     deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+ */
+
+ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
+                                     int bits,
+                                     int value));
+/*
+     deflatePrime() inserts bits in the deflate output stream.  The intent
+   is that this function is used to start off the deflate output with the bits
+   leftover from a previous deflate stream when appending to it.  As such, this
+   function can only be used for raw deflate, and must be used before the first
+   deflate() call after a deflateInit2() or deflateReset().  bits must be less
+   than or equal to 16, and that many of the least significant bits of value
+   will be inserted in the output.
+
+     deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough
+   room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the
+   source stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
+                                         gz_headerp head));
+/*
+     deflateSetHeader() provides gzip header information for when a gzip
+   stream is requested by deflateInit2().  deflateSetHeader() may be called
+   after deflateInit2() or deflateReset() and before the first call of
+   deflate().  The text, time, os, extra field, name, and comment information
+   in the provided gz_header structure are written to the gzip header (xflag is
+   ignored -- the extra flags are set according to the compression level).  The
+   caller must assure that, if not Z_NULL, name and comment are terminated with
+   a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
+   available there.  If hcrc is true, a gzip header crc is included.  Note that
+   the current versions of the command-line version of gzip (up through version
+   1.3.x) do not support header crc's, and will report that it is a "multi-part
+   gzip file" and give up.
+
+     If deflateSetHeader is not used, the default gzip header has text false,
+   the time set to zero, and os set to 255, with no extra, name, or comment
+   fields.  The gzip header is returned to the default state by deflateReset().
+
+     deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+                                     int  windowBits));
+
+     This is another version of inflateInit with an extra parameter.  The
+   fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+   before by the caller.
+
+     The windowBits parameter is the base two logarithm of the maximum window
+   size (the size of the history buffer).  It should be in the range 8..15 for
+   this version of the library.  The default value is 15 if inflateInit is used
+   instead.  windowBits must be greater than or equal to the windowBits value
+   provided to deflateInit2() while compressing, or it must be equal to 15 if
+   deflateInit2() was not used.  If a compressed stream with a larger window
+   size is given as input, inflate() will return with the error code
+   Z_DATA_ERROR instead of trying to allocate a larger window.
+
+     windowBits can also be zero to request that inflate use the window size in
+   the zlib header of the compressed stream.
+
+     windowBits can also be -8..-15 for raw inflate.  In this case, -windowBits
+   determines the window size.  inflate() will then process raw deflate data,
+   not looking for a zlib or gzip header, not generating a check value, and not
+   looking for any check values for comparison at the end of the stream.  This
+   is for use with other formats that use the deflate compressed data format
+   such as zip.  Those formats provide their own check values.  If a custom
+   format is developed using the raw deflate format for compressed data, it is
+   recommended that a check value such as an Adler-32 or a CRC-32 be applied to
+   the uncompressed data as is done in the zlib, gzip, and zip formats.  For
+   most applications, the zlib format should be used as is.  Note that comments
+   above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+     windowBits can also be greater than 15 for optional gzip decoding.  Add
+   32 to windowBits to enable zlib and gzip decoding with automatic header
+   detection, or add 16 to decode only the gzip format (the zlib format will
+   return a Z_DATA_ERROR).  If a gzip stream is being decoded, strm->adler is a
+   CRC-32 instead of an Adler-32.  Unlike the gunzip utility and gzread() (see
+   below), inflate() will not automatically decode concatenated gzip streams.
+   inflate() will return Z_STREAM_END at the end of the gzip stream.  The state
+   would need to be reset to continue decoding a subsequent gzip stream.
+
+     inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+   version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+   invalid, such as a null pointer to the structure.  msg is set to null if
+   there is no error message.  inflateInit2 does not perform any decompression
+   apart from possibly reading the zlib header if present: actual decompression
+   will be done by inflate().  (So next_in and avail_in may be modified, but
+   next_out and avail_out are unused and unchanged.) The current implementation
+   of inflateInit2() does not process any header information -- that is
+   deferred until inflate() is called.
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the decompression dictionary from the given uncompressed byte
+   sequence.  This function must be called immediately after a call of inflate,
+   if that call returned Z_NEED_DICT.  The dictionary chosen by the compressor
+   can be determined from the Adler-32 value returned by that call of inflate.
+   The compressor and decompressor must use exactly the same dictionary (see
+   deflateSetDictionary).  For raw inflate, this function can be called at any
+   time to set the dictionary.  If the provided dictionary is smaller than the
+   window and there is already data in the window, then the provided dictionary
+   will amend what's there.  The application must insure that the dictionary
+   that was used for compression is provided.
+
+     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is
+   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+   expected one (incorrect Adler-32 value).  inflateSetDictionary does not
+   perform any decompression: this will be done by subsequent calls of
+   inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm,
+                                             Bytef *dictionary,
+                                             uInt  *dictLength));
+/*
+     Returns the sliding dictionary being maintained by inflate.  dictLength is
+   set to the number of bytes in the dictionary, and that many bytes are copied
+   to dictionary.  dictionary must have enough space, where 32768 bytes is
+   always enough.  If inflateGetDictionary() is called with dictionary equal to
+   Z_NULL, then only the dictionary length is returned, and nothing is copied.
+   Similary, if dictLength is Z_NULL, then it is not set.
+
+     inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
+   stream state is inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/*
+     Skips invalid compressed data until a possible full flush point (see above
+   for the description of deflate with Z_FULL_FLUSH) can be found, or until all
+   available input is skipped.  No output is provided.
+
+     inflateSync searches for a 00 00 FF FF pattern in the compressed data.
+   All full flush points have this pattern, but not all occurrences of this
+   pattern are full flush points.
+
+     inflateSync returns Z_OK if a possible full flush point has been found,
+   Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
+   has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
+   In the success case, the application may save the current current value of
+   total_in which indicates where valid compressed data was found.  In the
+   error case, the application may repeatedly call inflateSync, providing more
+   input each time, until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
+                                    z_streamp source));
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when randomly accessing a large stream.  The
+   first pass through the stream can periodically record the inflate state,
+   allowing restarting inflate at those points when randomly accessing the
+   stream.
+
+     inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being Z_NULL).  msg is left unchanged in both source and
+   destination.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to inflateEnd followed by inflateInit,
+   but does not free and reallocate the internal decompression state.  The
+   stream will keep attributes that may have been set by inflateInit2.
+
+     inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm,
+                                      int windowBits));
+/*
+     This function is the same as inflateReset, but it also permits changing
+   the wrap and window size requests.  The windowBits parameter is interpreted
+   the same as it is for inflateInit2.  If the window size is changed, then the
+   memory allocated for the window is freed, and the window will be reallocated
+   by inflate() if needed.
+
+     inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being Z_NULL), or if
+   the windowBits parameter is invalid.
+*/
+
+ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
+                                     int bits,
+                                     int value));
+/*
+     This function inserts bits in the inflate input stream.  The intent is
+   that this function is used to start inflating at a bit position in the
+   middle of a byte.  The provided bits will be used before any bytes are used
+   from next_in.  This function should only be used with raw inflate, and
+   should be used before the first inflate() call after inflateInit2() or
+   inflateReset().  bits must be less than or equal to 16, and that many of the
+   least significant bits of value will be inserted in the input.
+
+     If bits is negative, then the input stream bit buffer is emptied.  Then
+   inflatePrime() can be called again to put bits in the buffer.  This is used
+   to clear out bits leftover after feeding inflate a block description prior
+   to feeding inflate codes.
+
+     inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm));
+/*
+     This function returns two values, one in the lower 16 bits of the return
+   value, and the other in the remaining upper bits, obtained by shifting the
+   return value down 16 bits.  If the upper value is -1 and the lower value is
+   zero, then inflate() is currently decoding information outside of a block.
+   If the upper value is -1 and the lower value is non-zero, then inflate is in
+   the middle of a stored block, with the lower value equaling the number of
+   bytes from the input remaining to copy.  If the upper value is not -1, then
+   it is the number of bits back from the current bit position in the input of
+   the code (literal or length/distance pair) currently being processed.  In
+   that case the lower value is the number of bytes already emitted for that
+   code.
+
+     A code is being processed if inflate is waiting for more input to complete
+   decoding of the code, or if it has completed decoding but is waiting for
+   more output space to write the literal or match data.
+
+     inflateMark() is used to mark locations in the input data for random
+   access, which may be at bit positions, and to note those cases where the
+   output of a code may span boundaries of random access blocks.  The current
+   location in the input stream can be determined from avail_in and data_type
+   as noted in the description for the Z_BLOCK flush parameter for inflate.
+
+     inflateMark returns the value noted above, or -65536 if the provided
+   source stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
+                                         gz_headerp head));
+/*
+     inflateGetHeader() requests that gzip header information be stored in the
+   provided gz_header structure.  inflateGetHeader() may be called after
+   inflateInit2() or inflateReset(), and before the first call of inflate().
+   As inflate() processes the gzip stream, head->done is zero until the header
+   is completed, at which time head->done is set to one.  If a zlib stream is
+   being decoded, then head->done is set to -1 to indicate that there will be
+   no gzip header information forthcoming.  Note that Z_BLOCK or Z_TREES can be
+   used to force inflate() to return immediately after header processing is
+   complete and before any actual data is decompressed.
+
+     The text, time, xflags, and os fields are filled in with the gzip header
+   contents.  hcrc is set to true if there is a header CRC.  (The header CRC
+   was valid if done is set to one.) If extra is not Z_NULL, then extra_max
+   contains the maximum number of bytes to write to extra.  Once done is true,
+   extra_len contains the actual extra field length, and extra contains the
+   extra field, or that field truncated if extra_max is less than extra_len.
+   If name is not Z_NULL, then up to name_max characters are written there,
+   terminated with a zero unless the length is greater than name_max.  If
+   comment is not Z_NULL, then up to comm_max characters are written there,
+   terminated with a zero unless the length is greater than comm_max.  When any
+   of extra, name, or comment are not Z_NULL and the respective field is not
+   present in the header, then that field is set to Z_NULL to signal its
+   absence.  This allows the use of deflateSetHeader() with the returned
+   structure to duplicate the header.  However if those fields are set to
+   allocated memory, then the application will need to save those pointers
+   elsewhere so that they can be eventually freed.
+
+     If inflateGetHeader is not used, then the header information is simply
+   discarded.  The header is always checked for validity, including the header
+   CRC if present.  inflateReset() will reset the process to discard the header
+   information.  The application would need to call inflateGetHeader() again to
+   retrieve the header from the next gzip stream.
+
+     inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
+                                        unsigned char FAR *window));
+
+     Initialize the internal stream state for decompression using inflateBack()
+   calls.  The fields zalloc, zfree and opaque in strm must be initialized
+   before the call.  If zalloc and zfree are Z_NULL, then the default library-
+   derived memory allocation routines are used.  windowBits is the base two
+   logarithm of the window size, in the range 8..15.  window is a caller
+   supplied buffer of that size.  Except for special applications where it is
+   assured that deflate was used with small window sizes, windowBits must be 15
+   and a 32K byte window must be supplied to be able to decompress general
+   deflate streams.
+
+     See inflateBack() for the usage of these routines.
+
+     inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
+   the parameters are invalid, Z_MEM_ERROR if the internal state could not be
+   allocated, or Z_VERSION_ERROR if the version of the library does not match
+   the version of the header file.
+*/
+
+typedef unsigned (*in_func) OF((void FAR *,
+                                z_const unsigned char FAR * FAR *));
+typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
+
+ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
+                                    in_func in, void FAR *in_desc,
+                                    out_func out, void FAR *out_desc));
+/*
+     inflateBack() does a raw inflate with a single call using a call-back
+   interface for input and output.  This is potentially more efficient than
+   inflate() for file i/o applications, in that it avoids copying between the
+   output and the sliding window by simply making the window itself the output
+   buffer.  inflate() can be faster on modern CPUs when used with large
+   buffers.  inflateBack() trusts the application to not change the output
+   buffer passed by the output function, at least until inflateBack() returns.
+
+     inflateBackInit() must be called first to allocate the internal state
+   and to initialize the state with the user-provided window buffer.
+   inflateBack() may then be used multiple times to inflate a complete, raw
+   deflate stream with each call.  inflateBackEnd() is then called to free the
+   allocated state.
+
+     A raw deflate stream is one with no zlib or gzip header or trailer.
+   This routine would normally be used in a utility that reads zip or gzip
+   files and writes out uncompressed files.  The utility would decode the
+   header and process the trailer on its own, hence this routine expects only
+   the raw deflate stream to decompress.  This is different from the default
+   behavior of inflate(), which expects a zlib header and trailer around the
+   deflate stream.
+
+     inflateBack() uses two subroutines supplied by the caller that are then
+   called by inflateBack() for input and output.  inflateBack() calls those
+   routines until it reads a complete deflate stream and writes out all of the
+   uncompressed data, or until it encounters an error.  The function's
+   parameters and return types are defined above in the in_func and out_func
+   typedefs.  inflateBack() will call in(in_desc, &buf) which should return the
+   number of bytes of provided input, and a pointer to that input in buf.  If
+   there is no input available, in() must return zero -- buf is ignored in that
+   case -- and inflateBack() will return a buffer error.  inflateBack() will
+   call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1].
+   out() should return zero on success, or non-zero on failure.  If out()
+   returns non-zero, inflateBack() will return with an error.  Neither in() nor
+   out() are permitted to change the contents of the window provided to
+   inflateBackInit(), which is also the buffer that out() uses to write from.
+   The length written by out() will be at most the window size.  Any non-zero
+   amount of input may be provided by in().
+
+     For convenience, inflateBack() can be provided input on the first call by
+   setting strm->next_in and strm->avail_in.  If that input is exhausted, then
+   in() will be called.  Therefore strm->next_in must be initialized before
+   calling inflateBack().  If strm->next_in is Z_NULL, then in() will be called
+   immediately for input.  If strm->next_in is not Z_NULL, then strm->avail_in
+   must also be initialized, and then if strm->avail_in is not zero, input will
+   initially be taken from strm->next_in[0 ..  strm->avail_in - 1].
+
+     The in_desc and out_desc parameters of inflateBack() is passed as the
+   first parameter of in() and out() respectively when they are called.  These
+   descriptors can be optionally used to pass any information that the caller-
+   supplied in() and out() functions need to do their job.
+
+     On return, inflateBack() will set strm->next_in and strm->avail_in to
+   pass back any unused input that was provided by the last in() call.  The
+   return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
+   if in() or out() returned an error, Z_DATA_ERROR if there was a format error
+   in the deflate stream (in which case strm->msg is set to indicate the nature
+   of the error), or Z_STREAM_ERROR if the stream was not properly initialized.
+   In the case of Z_BUF_ERROR, an input or output error can be distinguished
+   using strm->next_in which will be Z_NULL only if in() returned an error.  If
+   strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning
+   non-zero.  (in() will always be called before out(), so strm->next_in is
+   assured to be defined if out() returns non-zero.)  Note that inflateBack()
+   cannot return Z_OK.
+*/
+
+ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
+/*
+     All memory allocated by inflateBackInit() is freed.
+
+     inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
+   state was inconsistent.
+*/
+
+ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
+/* Return flags indicating compile-time options.
+
+    Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
+     1.0: size of uInt
+     3.2: size of uLong
+     5.4: size of voidpf (pointer)
+     7.6: size of z_off_t
+
+    Compiler, assembler, and debug options:
+     8: ZLIB_DEBUG
+     9: ASMV or ASMINF -- use ASM code
+     10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
+     11: 0 (reserved)
+
+    One-time table building (smaller code, but not thread-safe if true):
+     12: BUILDFIXED -- build static block decoding tables when needed
+     13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
+     14,15: 0 (reserved)
+
+    Library content (indicates missing functionality):
+     16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
+                          deflate code when not needed)
+     17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
+                    and decode gzip streams (to avoid linking crc code)
+     18-19: 0 (reserved)
+
+    Operation variations (changes in library functionality):
+     20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
+     21: FASTEST -- deflate algorithm with only one, lowest compression level
+     22,23: 0 (reserved)
+
+    The sprintf variant used by gzprintf (zero is best):
+     24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
+     25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
+     26: 0 = returns value, 1 = void -- 1 means inferred string length returned
+
+    Remainder:
+     27-31: 0 (reserved)
+ */
+
+#ifndef Z_SOLO
+
+                        /* utility functions */
+
+/*
+     The following utility functions are implemented on top of the basic
+   stream-oriented functions.  To simplify the interface, some default options
+   are assumed (compression level and memory usage, standard memory allocation
+   functions).  The source code of these utility functions can be modified if
+   you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,
+                                 const Bytef *source, uLong sourceLen));
+/*
+     Compresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer.  Upon entry, destLen is the total size
+   of the destination buffer, which must be at least the value returned by
+   compressBound(sourceLen).  Upon exit, destLen is the actual size of the
+   compressed data.  compress() is equivalent to compress2() with a level
+   parameter of Z_DEFAULT_COMPRESSION.
+
+     compress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,
+                                  const Bytef *source, uLong sourceLen,
+                                  int level));
+/*
+     Compresses the source buffer into the destination buffer.  The level
+   parameter has the same meaning as in deflateInit.  sourceLen is the byte
+   length of the source buffer.  Upon entry, destLen is the total size of the
+   destination buffer, which must be at least the value returned by
+   compressBound(sourceLen).  Upon exit, destLen is the actual size of the
+   compressed data.
+
+     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+   Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
+/*
+     compressBound() returns an upper bound on the compressed size after
+   compress() or compress2() on sourceLen bytes.  It would be used before a
+   compress() or compress2() call to allocate the destination buffer.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,
+                                   const Bytef *source, uLong sourceLen));
+/*
+     Decompresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer.  Upon entry, destLen is the total size
+   of the destination buffer, which must be large enough to hold the entire
+   uncompressed data.  (The size of the uncompressed data must have been saved
+   previously by the compressor and transmitted to the decompressor by some
+   mechanism outside the scope of this compression library.) Upon exit, destLen
+   is the actual size of the uncompressed data.
+
+     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.  In
+   the case where there is not enough room, uncompress() will fill the output
+   buffer with the uncompressed data up to that point.
+*/
+
+ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest,   uLongf *destLen,
+                                    const Bytef *source, uLong *sourceLen));
+/*
+     Same as uncompress, except that sourceLen is a pointer, where the
+   length of the source is *sourceLen.  On return, *sourceLen is the number of
+   source bytes consumed.
+*/
+
+                        /* gzip file access functions */
+
+/*
+     This library supports reading and writing files in gzip (.gz) format with
+   an interface similar to that of stdio, using the functions that start with
+   "gz".  The gzip format is different from the zlib format.  gzip is a gzip
+   wrapper, documented in RFC 1952, wrapped around a deflate stream.
+*/
+
+typedef struct gzFile_s *gzFile;    /* semi-opaque gzip file descriptor */
+
+/*
+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
+
+     Opens a gzip (.gz) file for reading or writing.  The mode parameter is as
+   in fopen ("rb" or "wb") but can also include a compression level ("wb9") or
+   a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only
+   compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F'
+   for fixed code compression as in "wb9F".  (See the description of
+   deflateInit2 for more information about the strategy parameter.)  'T' will
+   request transparent writing or appending with no compression and not using
+   the gzip format.
+
+     "a" can be used instead of "w" to request that the gzip stream that will
+   be written be appended to the file.  "+" will result in an error, since
+   reading and writing to the same gzip file is not supported.  The addition of
+   "x" when writing will create the file exclusively, which fails if the file
+   already exists.  On systems that support it, the addition of "e" when
+   reading or writing will set the flag to close the file on an execve() call.
+
+     These functions, as well as gzip, will read and decode a sequence of gzip
+   streams in a file.  The append function of gzopen() can be used to create
+   such a file.  (Also see gzflush() for another way to do this.)  When
+   appending, gzopen does not test whether the file begins with a gzip stream,
+   nor does it look for the end of the gzip streams to begin appending.  gzopen
+   will simply append a gzip stream to the existing file.
+
+     gzopen can be used to read a file which is not in gzip format; in this
+   case gzread will directly read from the file without decompression.  When
+   reading, this will be detected automatically by looking for the magic two-
+   byte gzip header.
+
+     gzopen returns NULL if the file could not be opened, if there was
+   insufficient memory to allocate the gzFile state, or if an invalid mode was
+   specified (an 'r', 'w', or 'a' was not provided, or '+' was provided).
+   errno can be checked to determine if the reason gzopen failed was that the
+   file could not be opened.
+*/
+
+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
+/*
+     gzdopen associates a gzFile with the file descriptor fd.  File descriptors
+   are obtained from calls like open, dup, creat, pipe or fileno (if the file
+   has been previously opened with fopen).  The mode parameter is as in gzopen.
+
+     The next call of gzclose on the returned gzFile will also close the file
+   descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
+   fd.  If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,
+   mode);.  The duplicated descriptor should be saved to avoid a leak, since
+   gzdopen does not close fd if it fails.  If you are using fileno() to get the
+   file descriptor from a FILE *, then you will have to use dup() to avoid
+   double-close()ing the file descriptor.  Both gzclose() and fclose() will
+   close the associated file descriptor, so they need to have different file
+   descriptors.
+
+     gzdopen returns NULL if there was insufficient memory to allocate the
+   gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not
+   provided, or '+' was provided), or if fd is -1.  The file descriptor is not
+   used until the next gz* read, write, seek, or close operation, so gzdopen
+   will not detect if fd is invalid (unless fd is -1).
+*/
+
+ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
+/*
+     Set the internal buffer size used by this library's functions.  The
+   default buffer size is 8192 bytes.  This function must be called after
+   gzopen() or gzdopen(), and before any other calls that read or write the
+   file.  The buffer memory allocation is always deferred to the first read or
+   write.  Three times that size in buffer space is allocated.  A larger buffer
+   size of, for example, 64K or 128K bytes will noticeably increase the speed
+   of decompression (reading).
+
+     The new buffer size also affects the maximum length for gzprintf().
+
+     gzbuffer() returns 0 on success, or -1 on failure, such as being called
+   too late.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+     Dynamically update the compression level or strategy.  See the description
+   of deflateInit2 for the meaning of these parameters.  Previously provided
+   data is flushed before the parameter change.
+
+     gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not
+   opened for writing, Z_ERRNO if there is an error writing the flushed data,
+   or Z_MEM_ERROR if there is a memory allocation error.
+*/
+
+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
+/*
+     Reads the given number of uncompressed bytes from the compressed file.  If
+   the input file is not in gzip format, gzread copies the given number of
+   bytes into the buffer directly from the file.
+
+     After reaching the end of a gzip stream in the input, gzread will continue
+   to read, looking for another gzip stream.  Any number of gzip streams may be
+   concatenated in the input file, and will all be decompressed by gzread().
+   If something other than a gzip stream is encountered after a gzip stream,
+   that remaining trailing garbage is ignored (and no error is returned).
+
+     gzread can be used to read a gzip file that is being concurrently written.
+   Upon reaching the end of the input, gzread will return with the available
+   data.  If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then
+   gzclearerr can be used to clear the end of file indicator in order to permit
+   gzread to be tried again.  Z_OK indicates that a gzip stream was completed
+   on the last gzread.  Z_BUF_ERROR indicates that the input file ended in the
+   middle of a gzip stream.  Note that gzread does not return -1 in the event
+   of an incomplete gzip stream.  This error is deferred until gzclose(), which
+   will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip
+   stream.  Alternatively, gzerror can be used before gzclose to detect this
+   case.
+
+     gzread returns the number of uncompressed bytes actually read, less than
+   len for end of file, or -1 for error.  If len is too large to fit in an int,
+   then nothing is read, -1 is returned, and the error state is set to
+   Z_STREAM_ERROR.
+*/
+
+ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems,
+                                     gzFile file));
+/*
+     Read up to nitems items of size size from file to buf, otherwise operating
+   as gzread() does.  This duplicates the interface of stdio's fread(), with
+   size_t request and return types.  If the library defines size_t, then
+   z_size_t is identical to size_t.  If not, then z_size_t is an unsigned
+   integer type that can contain a pointer.
+
+     gzfread() returns the number of full items read of size size, or zero if
+   the end of the file was reached and a full item could not be read, or if
+   there was an error.  gzerror() must be consulted if zero is returned in
+   order to determine if there was an error.  If the multiplication of size and
+   nitems overflows, i.e. the product does not fit in a z_size_t, then nothing
+   is read, zero is returned, and the error state is set to Z_STREAM_ERROR.
+
+     In the event that the end of file is reached and only a partial item is
+   available at the end, i.e. the remaining uncompressed data length is not a
+   multiple of size, then the final partial item is nevetheless read into buf
+   and the end-of-file flag is set.  The length of the partial item read is not
+   provided, but could be inferred from the result of gztell().  This behavior
+   is the same as the behavior of fread() implementations in common libraries,
+   but it prevents the direct use of gzfread() to read a concurrently written
+   file, reseting and retrying on end-of-file, when size is not 1.
+*/
+
+ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
+                                voidpc buf, unsigned len));
+/*
+     Writes the given number of uncompressed bytes into the compressed file.
+   gzwrite returns the number of uncompressed bytes written or 0 in case of
+   error.
+*/
+
+ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size,
+                                      z_size_t nitems, gzFile file));
+/*
+     gzfwrite() writes nitems items of size size from buf to file, duplicating
+   the interface of stdio's fwrite(), with size_t request and return types.  If
+   the library defines size_t, then z_size_t is identical to size_t.  If not,
+   then z_size_t is an unsigned integer type that can contain a pointer.
+
+     gzfwrite() returns the number of full items written of size size, or zero
+   if there was an error.  If the multiplication of size and nitems overflows,
+   i.e. the product does not fit in a z_size_t, then nothing is written, zero
+   is returned, and the error state is set to Z_STREAM_ERROR.
+*/
+
+ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));
+/*
+     Converts, formats, and writes the arguments to the compressed file under
+   control of the format string, as in fprintf.  gzprintf returns the number of
+   uncompressed bytes actually written, or a negative zlib error code in case
+   of error.  The number of uncompressed bytes written is limited to 8191, or
+   one less than the buffer size given to gzbuffer().  The caller should assure
+   that this limit is not exceeded.  If it is exceeded, then gzprintf() will
+   return an error (0) with nothing written.  In this case, there may also be a
+   buffer overflow with unpredictable consequences, which is possible only if
+   zlib was compiled with the insecure functions sprintf() or vsprintf()
+   because the secure snprintf() or vsnprintf() functions were not available.
+   This can be determined using zlibCompileFlags().
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+     Writes the given null-terminated string to the compressed file, excluding
+   the terminating null character.
+
+     gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+     Reads bytes from the compressed file until len-1 characters are read, or a
+   newline character is read and transferred to buf, or an end-of-file
+   condition is encountered.  If any characters are read or if len == 1, the
+   string is terminated with a null character.  If no characters are read due
+   to an end-of-file or len < 1, then the buffer is left untouched.
+
+     gzgets returns buf which is a null-terminated string, or it returns NULL
+   for end-of-file or in case of error.  If there was an error, the contents at
+   buf are indeterminate.
+*/
+
+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
+/*
+     Writes c, converted to an unsigned char, into the compressed file.  gzputc
+   returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
+/*
+     Reads one byte from the compressed file.  gzgetc returns this byte or -1
+   in case of end of file or error.  This is implemented as a macro for speed.
+   As such, it does not do all of the checking the other functions do.  I.e.
+   it does not check to see if file is NULL, nor whether the structure file
+   points to has been clobbered or not.
+*/
+
+ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
+/*
+     Push one character back onto the stream to be read as the first character
+   on the next read.  At least one character of push-back is allowed.
+   gzungetc() returns the character pushed, or -1 on failure.  gzungetc() will
+   fail if c is -1, and may fail if a character has been pushed but not read
+   yet.  If gzungetc is used immediately after gzopen or gzdopen, at least the
+   output buffer size of pushed characters is allowed.  (See gzbuffer above.)
+   The pushed character will be discarded if the stream is repositioned with
+   gzseek() or gzrewind().
+*/
+
+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
+/*
+     Flushes all pending output into the compressed file.  The parameter flush
+   is as in the deflate() function.  The return value is the zlib error number
+   (see function gzerror below).  gzflush is only permitted when writing.
+
+     If the flush parameter is Z_FINISH, the remaining data is written and the
+   gzip stream is completed in the output.  If gzwrite() is called again, a new
+   gzip stream will be started in the output.  gzread() is able to read such
+   concatenated gzip streams.
+
+     gzflush should be called only when strictly necessary because it will
+   degrade compression if called too often.
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
+                                   z_off_t offset, int whence));
+
+     Sets the starting position for the next gzread or gzwrite on the given
+   compressed file.  The offset represents a number of bytes in the
+   uncompressed data stream.  The whence parameter is defined as in lseek(2);
+   the value SEEK_END is not supported.
+
+     If the file is opened for reading, this function is emulated but can be
+   extremely slow.  If the file is opened for writing, only forward seeks are
+   supported; gzseek then compresses a sequence of zeroes up to the new
+   starting position.
+
+     gzseek returns the resulting offset location as measured in bytes from
+   the beginning of the uncompressed stream, or -1 in case of error, in
+   particular if the file is opened for writing and the new starting position
+   would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT    gzrewind OF((gzFile file));
+/*
+     Rewinds the given file. This function is supported only for reading.
+
+     gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));
+
+     Returns the starting position for the next gzread or gzwrite on the given
+   compressed file.  This position represents a number of bytes in the
+   uncompressed data stream, and is zero when starting, even if appending or
+   reading a gzip stream from the middle of a file using gzdopen().
+
+     gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));
+
+     Returns the current offset in the file being read or written.  This offset
+   includes the count of bytes that precede the gzip stream, for example when
+   appending or when using gzdopen() for reading.  When reading, the offset
+   does not include as yet unused buffered input.  This information can be used
+   for a progress indicator.  On error, gzoffset() returns -1.
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+     Returns true (1) if the end-of-file indicator has been set while reading,
+   false (0) otherwise.  Note that the end-of-file indicator is set only if the
+   read tried to go past the end of the input, but came up short.  Therefore,
+   just like feof(), gzeof() may return false even if there is no more data to
+   read, in the event that the last read request was for the exact number of
+   bytes remaining in the input file.  This will happen if the input file size
+   is an exact multiple of the buffer size.
+
+     If gzeof() returns true, then the read functions will return no more data,
+   unless the end-of-file indicator is reset by gzclearerr() and the input file
+   has grown since the previous end of file was detected.
+*/
+
+ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
+/*
+     Returns true (1) if file is being copied directly while reading, or false
+   (0) if file is a gzip stream being decompressed.
+
+     If the input file is empty, gzdirect() will return true, since the input
+   does not contain a gzip stream.
+
+     If gzdirect() is used immediately after gzopen() or gzdopen() it will
+   cause buffers to be allocated to allow reading the file to determine if it
+   is a gzip file.  Therefore if gzbuffer() is used, it should be called before
+   gzdirect().
+
+     When writing, gzdirect() returns true (1) if transparent writing was
+   requested ("wT" for the gzopen() mode), or false (0) otherwise.  (Note:
+   gzdirect() is not needed when writing.  Transparent writing must be
+   explicitly requested, so the application already knows the answer.  When
+   linking statically, using gzdirect() will include all of the zlib code for
+   gzip file reading and decompression, which may not be desired.)
+*/
+
+ZEXTERN int ZEXPORT    gzclose OF((gzFile file));
+/*
+     Flushes all pending output if necessary, closes the compressed file and
+   deallocates the (de)compression state.  Note that once file is closed, you
+   cannot call gzerror with file, since its structures have been deallocated.
+   gzclose must not be called more than once on the same file, just as free
+   must not be called more than once on the same allocation.
+
+     gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a
+   file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the
+   last read ended in the middle of a gzip stream, or Z_OK on success.
+*/
+
+ZEXTERN int ZEXPORT gzclose_r OF((gzFile file));
+ZEXTERN int ZEXPORT gzclose_w OF((gzFile file));
+/*
+     Same as gzclose(), but gzclose_r() is only for use when reading, and
+   gzclose_w() is only for use when writing or appending.  The advantage to
+   using these instead of gzclose() is that they avoid linking in zlib
+   compression or decompression code that is not used when only reading or only
+   writing respectively.  If gzclose() is used, then both compression and
+   decompression code will be included the application when linking to a static
+   zlib library.
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+     Returns the error message for the last error which occurred on the given
+   compressed file.  errnum is set to zlib error number.  If an error occurred
+   in the file system and not in the compression library, errnum is set to
+   Z_ERRNO and the application may consult errno to get the exact error code.
+
+     The application must not modify the returned string.  Future calls to
+   this function may invalidate the previously returned string.  If file is
+   closed, then the string previously returned by gzerror will no longer be
+   available.
+
+     gzerror() should be used to distinguish errors from end-of-file for those
+   functions above that do not distinguish those cases in their return values.
+*/
+
+ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
+/*
+     Clears the error and end-of-file flags for file.  This is analogous to the
+   clearerr() function in stdio.  This is useful for continuing to read a gzip
+   file that is being written concurrently.
+*/
+
+#endif /* !Z_SOLO */
+
+                        /* checksum functions */
+
+/*
+     These functions are not related to compression but are exported
+   anyway because they might be useful in applications using the compression
+   library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+/*
+     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+   return the updated checksum.  If buf is Z_NULL, this function returns the
+   required initial value for the checksum.
+
+     An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed
+   much faster.
+
+   Usage example:
+
+     uLong adler = adler32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       adler = adler32(adler, buffer, length);
+     }
+     if (adler != original_adler) error();
+*/
+
+ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf,
+                                    z_size_t len));
+/*
+     Same as adler32(), but with a size_t length.
+*/
+
+/*
+ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
+                                          z_off_t len2));
+
+     Combine two Adler-32 checksums into one.  For two sequences of bytes, seq1
+   and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
+   each, adler1 and adler2.  adler32_combine() returns the Adler-32 checksum of
+   seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.  Note
+   that the z_off_t type (like off_t) is a signed integer.  If len2 is
+   negative, the result has no meaning or utility.
+*/
+
+ZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));
+/*
+     Update a running CRC-32 with the bytes buf[0..len-1] and return the
+   updated CRC-32.  If buf is Z_NULL, this function returns the required
+   initial value for the crc.  Pre- and post-conditioning (one's complement) is
+   performed within this function so it shouldn't be done by the application.
+
+   Usage example:
+
+     uLong crc = crc32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       crc = crc32(crc, buffer, length);
+     }
+     if (crc != original_crc) error();
+*/
+
+ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf,
+                                  z_size_t len));
+/*
+     Same as crc32(), but with a size_t length.
+*/
+
+/*
+ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
+
+     Combine two CRC-32 check values into one.  For two sequences of bytes,
+   seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
+   calculated for each, crc1 and crc2.  crc32_combine() returns the CRC-32
+   check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
+   len2.
+*/
+
+
+                        /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int  level, int  method,
+                                      int windowBits, int memLevel,
+                                      int strategy, const char *version,
+                                      int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,
+                                      const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
+                                         unsigned char FAR *window,
+                                         const char *version,
+                                         int stream_size));
+#ifdef Z_PREFIX_SET
+#  define z_deflateInit(strm, level) \
+          deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
+#  define z_inflateInit(strm) \
+          inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
+#  define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+          deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+                        (strategy), ZLIB_VERSION, (int)sizeof(z_stream))
+#  define z_inflateInit2(strm, windowBits) \
+          inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
+                        (int)sizeof(z_stream))
+#  define z_inflateBackInit(strm, windowBits, window) \
+          inflateBackInit_((strm), (windowBits), (window), \
+                           ZLIB_VERSION, (int)sizeof(z_stream))
+#else
+#  define deflateInit(strm, level) \
+          deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
+#  define inflateInit(strm) \
+          inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
+#  define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+          deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+                        (strategy), ZLIB_VERSION, (int)sizeof(z_stream))
+#  define inflateInit2(strm, windowBits) \
+          inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
+                        (int)sizeof(z_stream))
+#  define inflateBackInit(strm, windowBits, window) \
+          inflateBackInit_((strm), (windowBits), (window), \
+                           ZLIB_VERSION, (int)sizeof(z_stream))
+#endif
+
+#ifndef Z_SOLO
+
+/* gzgetc() macro and its supporting function and exposed data structure.  Note
+ * that the real internal state is much larger than the exposed structure.
+ * This abbreviated structure exposes just enough for the gzgetc() macro.  The
+ * user should not mess with these exposed elements, since their names or
+ * behavior could change in the future, perhaps even capriciously.  They can
+ * only be used by the gzgetc() macro.  You have been warned.
+ */
+struct gzFile_s {
+    unsigned have;
+    unsigned char *next;
+    z_off64_t pos;
+};
+ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file));  /* backward compatibility */
+#ifdef Z_PREFIX_SET
+#  undef z_gzgetc
+#  define z_gzgetc(g) \
+          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g))
+#else
+#  define gzgetc(g) \
+          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g))
+#endif
+
+/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or
+ * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if
+ * both are true, the application gets the *64 functions, and the regular
+ * functions are changed to 64 bits) -- in case these are set on systems
+ * without large file support, _LFS64_LARGEFILE must also be true
+ */
+#ifdef Z_LARGE64
+   ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+   ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
+   ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
+   ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
+   ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));
+   ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
+#endif
+
+#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)
+#  ifdef Z_PREFIX_SET
+#    define z_gzopen z_gzopen64
+#    define z_gzseek z_gzseek64
+#    define z_gztell z_gztell64
+#    define z_gzoffset z_gzoffset64
+#    define z_adler32_combine z_adler32_combine64
+#    define z_crc32_combine z_crc32_combine64
+#  else
+#    define gzopen gzopen64
+#    define gzseek gzseek64
+#    define gztell gztell64
+#    define gzoffset gzoffset64
+#    define adler32_combine adler32_combine64
+#    define crc32_combine crc32_combine64
+#  endif
+#  ifndef Z_LARGE64
+     ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+     ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));
+     ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));
+     ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));
+     ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
+     ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
+#  endif
+#else
+   ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));
+   ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int));
+   ZEXTERN z_off_t ZEXPORT gztell OF((gzFile));
+   ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));
+   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
+   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+#endif
+
+#else /* Z_SOLO */
+
+   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
+   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+
+#endif /* !Z_SOLO */
+
+/* undocumented functions */
+ZEXTERN const char   * ZEXPORT zError           OF((int));
+ZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp));
+ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table    OF((void));
+ZEXTERN int            ZEXPORT inflateUndermine OF((z_streamp, int));
+ZEXTERN int            ZEXPORT inflateValidate OF((z_streamp, int));
+ZEXTERN unsigned long  ZEXPORT inflateCodesUsed OF ((z_streamp));
+ZEXTERN int            ZEXPORT inflateResetKeep OF((z_streamp));
+ZEXTERN int            ZEXPORT deflateResetKeep OF((z_streamp));
+#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO)
+ZEXTERN gzFile         ZEXPORT gzopen_w OF((const wchar_t *path,
+                                            const char *mode));
+#endif
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#  ifndef Z_SOLO
+ZEXTERN int            ZEXPORTVA gzvprintf Z_ARG((gzFile file,
+                                                  const char *format,
+                                                  va_list va));
+#  endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZLIB_H */
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/src/zutil.c
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/src/zutil.c	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/src/zutil.c	(revision 453)
@@ -0,0 +1,325 @@
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995-2017 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include "zutil.h"
+#ifndef Z_SOLO
+#  include "gzguts.h"
+#endif
+
+z_const char * const z_errmsg[10] = {
+    (z_const char *)"need dictionary",     /* Z_NEED_DICT       2  */
+    (z_const char *)"stream end",          /* Z_STREAM_END      1  */
+    (z_const char *)"",                    /* Z_OK              0  */
+    (z_const char *)"file error",          /* Z_ERRNO         (-1) */
+    (z_const char *)"stream error",        /* Z_STREAM_ERROR  (-2) */
+    (z_const char *)"data error",          /* Z_DATA_ERROR    (-3) */
+    (z_const char *)"insufficient memory", /* Z_MEM_ERROR     (-4) */
+    (z_const char *)"buffer error",        /* Z_BUF_ERROR     (-5) */
+    (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */
+    (z_const char *)""
+};
+
+
+const char * ZEXPORT zlibVersion()
+{
+    return ZLIB_VERSION;
+}
+
+uLong ZEXPORT zlibCompileFlags()
+{
+    uLong flags;
+
+    flags = 0;
+    switch ((int)(sizeof(uInt))) {
+    case 2:     break;
+    case 4:     flags += 1;     break;
+    case 8:     flags += 2;     break;
+    default:    flags += 3;
+    }
+    switch ((int)(sizeof(uLong))) {
+    case 2:     break;
+    case 4:     flags += 1 << 2;        break;
+    case 8:     flags += 2 << 2;        break;
+    default:    flags += 3 << 2;
+    }
+    switch ((int)(sizeof(voidpf))) {
+    case 2:     break;
+    case 4:     flags += 1 << 4;        break;
+    case 8:     flags += 2 << 4;        break;
+    default:    flags += 3 << 4;
+    }
+    switch ((int)(sizeof(z_off_t))) {
+    case 2:     break;
+    case 4:     flags += 1 << 6;        break;
+    case 8:     flags += 2 << 6;        break;
+    default:    flags += 3 << 6;
+    }
+#ifdef ZLIB_DEBUG
+    flags += 1 << 8;
+#endif
+#if defined(ASMV) || defined(ASMINF)
+    flags += 1 << 9;
+#endif
+#ifdef ZLIB_WINAPI
+    flags += 1 << 10;
+#endif
+#ifdef BUILDFIXED
+    flags += 1 << 12;
+#endif
+#ifdef DYNAMIC_CRC_TABLE
+    flags += 1 << 13;
+#endif
+#ifdef NO_GZCOMPRESS
+    flags += 1L << 16;
+#endif
+#ifdef NO_GZIP
+    flags += 1L << 17;
+#endif
+#ifdef PKZIP_BUG_WORKAROUND
+    flags += 1L << 20;
+#endif
+#ifdef FASTEST
+    flags += 1L << 21;
+#endif
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#  ifdef NO_vsnprintf
+    flags += 1L << 25;
+#    ifdef HAS_vsprintf_void
+    flags += 1L << 26;
+#    endif
+#  else
+#    ifdef HAS_vsnprintf_void
+    flags += 1L << 26;
+#    endif
+#  endif
+#else
+    flags += 1L << 24;
+#  ifdef NO_snprintf
+    flags += 1L << 25;
+#    ifdef HAS_sprintf_void
+    flags += 1L << 26;
+#    endif
+#  else
+#    ifdef HAS_snprintf_void
+    flags += 1L << 26;
+#    endif
+#  endif
+#endif
+    return flags;
+}
+
+#ifdef ZLIB_DEBUG
+#include <stdlib.h>
+#  ifndef verbose
+#    define verbose 0
+#  endif
+int ZLIB_INTERNAL z_verbose = verbose;
+
+void ZLIB_INTERNAL z_error (m)
+    char *m;
+{
+    fprintf(stderr, "%s\n", m);
+    exit(1);
+}
+#endif
+
+/* exported to allow conversion of error code to string for compress() and
+ * uncompress()
+ */
+const char * ZEXPORT zError(err)
+    int err;
+{
+    return ERR_MSG(err);
+}
+
+#if defined(_WIN32_WCE)
+    /* The Microsoft C Run-Time Library for Windows CE doesn't have
+     * errno.  We define it as a global variable to simplify porting.
+     * Its value is always 0 and should not be used.
+     */
+    int errno = 0;
+#endif
+
+#ifndef HAVE_MEMCPY
+
+void ZLIB_INTERNAL zmemcpy(dest, source, len)
+    Bytef* dest;
+    const Bytef* source;
+    uInt  len;
+{
+    if (len == 0) return;
+    do {
+        *dest++ = *source++; /* ??? to be unrolled */
+    } while (--len != 0);
+}
+
+int ZLIB_INTERNAL zmemcmp(s1, s2, len)
+    const Bytef* s1;
+    const Bytef* s2;
+    uInt  len;
+{
+    uInt j;
+
+    for (j = 0; j < len; j++) {
+        if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
+    }
+    return 0;
+}
+
+void ZLIB_INTERNAL zmemzero(dest, len)
+    Bytef* dest;
+    uInt  len;
+{
+    if (len == 0) return;
+    do {
+        *dest++ = 0;  /* ??? to be unrolled */
+    } while (--len != 0);
+}
+#endif
+
+#ifndef Z_SOLO
+
+#ifdef SYS16BIT
+
+#ifdef __TURBOC__
+/* Turbo C in 16-bit mode */
+
+#  define MY_ZCALLOC
+
+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
+ * and farmalloc(64K) returns a pointer with an offset of 8, so we
+ * must fix the pointer. Warning: the pointer must be put back to its
+ * original form in order to free it, use zcfree().
+ */
+
+#define MAX_PTR 10
+/* 10*64K = 640K */
+
+local int next_ptr = 0;
+
+typedef struct ptr_table_s {
+    voidpf org_ptr;
+    voidpf new_ptr;
+} ptr_table;
+
+local ptr_table table[MAX_PTR];
+/* This table is used to remember the original form of pointers
+ * to large buffers (64K). Such pointers are normalized with a zero offset.
+ * Since MSDOS is not a preemptive multitasking OS, this table is not
+ * protected from concurrent access. This hack doesn't work anyway on
+ * a protected system like OS/2. Use Microsoft C instead.
+ */
+
+voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+    voidpf buf;
+    ulg bsize = (ulg)items*size;
+
+    (void)opaque;
+
+    /* If we allocate less than 65520 bytes, we assume that farmalloc
+     * will return a usable pointer which doesn't have to be normalized.
+     */
+    if (bsize < 65520L) {
+        buf = farmalloc(bsize);
+        if (*(ush*)&buf != 0) return buf;
+    } else {
+        buf = farmalloc(bsize + 16L);
+    }
+    if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
+    table[next_ptr].org_ptr = buf;
+
+    /* Normalize the pointer to seg:0 */
+    *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
+    *(ush*)&buf = 0;
+    table[next_ptr++].new_ptr = buf;
+    return buf;
+}
+
+void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
+{
+    int n;
+
+    (void)opaque;
+
+    if (*(ush*)&ptr != 0) { /* object < 64K */
+        farfree(ptr);
+        return;
+    }
+    /* Find the original pointer */
+    for (n = 0; n < next_ptr; n++) {
+        if (ptr != table[n].new_ptr) continue;
+
+        farfree(table[n].org_ptr);
+        while (++n < next_ptr) {
+            table[n-1] = table[n];
+        }
+        next_ptr--;
+        return;
+    }
+    Assert(0, "zcfree: ptr not found");
+}
+
+#endif /* __TURBOC__ */
+
+
+#ifdef M_I86
+/* Microsoft C in 16-bit mode */
+
+#  define MY_ZCALLOC
+
+#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
+#  define _halloc  halloc
+#  define _hfree   hfree
+#endif
+
+voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size)
+{
+    (void)opaque;
+    return _halloc((long)items, size);
+}
+
+void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
+{
+    (void)opaque;
+    _hfree(ptr);
+}
+
+#endif /* M_I86 */
+
+#endif /* SYS16BIT */
+
+
+#ifndef MY_ZCALLOC /* Any system without a special alloc function */
+
+#ifndef STDC
+extern voidp  malloc OF((uInt size));
+extern voidp  calloc OF((uInt items, uInt size));
+extern void   free   OF((voidpf ptr));
+#endif
+
+voidpf ZLIB_INTERNAL zcalloc (opaque, items, size)
+    voidpf opaque;
+    unsigned items;
+    unsigned size;
+{
+    (void)opaque;
+    return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
+                              (voidpf)calloc(items, size);
+}
+
+void ZLIB_INTERNAL zcfree (opaque, ptr)
+    voidpf opaque;
+    voidpf ptr;
+{
+    (void)opaque;
+    free(ptr);
+}
+
+#endif /* MY_ZCALLOC */
+
+#endif /* !Z_SOLO */
Index: azure_iot_hub_riscv/trunk/zlib-1.2.11/src/zutil.h
===================================================================
--- azure_iot_hub_riscv/trunk/zlib-1.2.11/src/zutil.h	(revision 453)
+++ azure_iot_hub_riscv/trunk/zlib-1.2.11/src/zutil.h	(revision 453)
@@ -0,0 +1,271 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZUTIL_H
+#define ZUTIL_H
+
+#ifdef HAVE_HIDDEN
+#  define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
+#else
+#  define ZLIB_INTERNAL
+#endif
+
+#include "zlib.h"
+
+#if defined(STDC) && !defined(Z_SOLO)
+#  if !(defined(_WIN32_WCE) && defined(_MSC_VER))
+#    include <stddef.h>
+#  endif
+#  include <string.h>
+#  include <stdlib.h>
+#endif
+
+#ifdef Z_SOLO
+   typedef long ptrdiff_t;  /* guess -- will be caught if guess is wrong */
+#endif
+
+#ifndef local
+#  define local static
+#endif
+/* since "static" is used to mean two completely different things in C, we
+   define "local" for the non-static meaning of "static", for readability
+   (compile with -Dlocal if your debugger can't find static symbols) */
+
+typedef unsigned char  uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long  ulg;
+
+extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
+/* (size given to avoid silly warnings with Visual C++) */
+
+#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
+
+#define ERR_RETURN(strm,err) \
+  return (strm->msg = ERR_MSG(err), (err))
+/* To be used only when the state is known to be valid */
+
+        /* common constants */
+
+#ifndef DEF_WBITS
+#  define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+#  define DEF_MEM_LEVEL 8
+#else
+#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES    2
+/* The three kinds of block type */
+
+#define MIN_MATCH  3
+#define MAX_MATCH  258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+        /* target dependencies */
+
+#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
+#  define OS_CODE  0x00
+#  ifndef Z_SOLO
+#    if defined(__TURBOC__) || defined(__BORLANDC__)
+#      if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
+         /* Allow compilation with ANSI keywords only enabled */
+         void _Cdecl farfree( void *block );
+         void *_Cdecl farmalloc( unsigned long nbytes );
+#      else
+#        include <alloc.h>
+#      endif
+#    else /* MSC or DJGPP */
+#      include <malloc.h>
+#    endif
+#  endif
+#endif
+
+#ifdef AMIGA
+#  define OS_CODE  1
+#endif
+
+#if defined(VAXC) || defined(VMS)
+#  define OS_CODE  2
+#  define F_OPEN(name, mode) \
+     fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
+#endif
+
+#ifdef __370__
+#  if __TARGET_LIB__ < 0x20000000
+#    define OS_CODE 4
+#  elif __TARGET_LIB__ < 0x40000000
+#    define OS_CODE 11
+#  else
+#    define OS_CODE 8
+#  endif
+#endif
+
+#if defined(ATARI) || defined(atarist)
+#  define OS_CODE  5
+#endif
+
+#ifdef OS2
+#  define OS_CODE  6
+#  if defined(M_I86) && !defined(Z_SOLO)
+#    include <malloc.h>
+#  endif
+#endif
+
+#if defined(MACOS) || defined(TARGET_OS_MAC)
+#  define OS_CODE  7
+#  ifndef Z_SOLO
+#    if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+#      include <unix.h> /* for fdopen */
+#    else
+#      ifndef fdopen
+#        define fdopen(fd,mode) NULL /* No fdopen() */
+#      endif
+#    endif
+#  endif
+#endif
+
+#ifdef __acorn
+#  define OS_CODE 13
+#endif
+
+#if defined(WIN32) && !defined(__CYGWIN__)
+#  define OS_CODE  10
+#endif
+
+#ifdef _BEOS_
+#  define OS_CODE  16
+#endif
+
+#ifdef __TOS_OS400__
+#  define OS_CODE 18
+#endif
+
+#ifdef __APPLE__
+#  define OS_CODE 19
+#endif
+
+#if defined(_BEOS_) || defined(RISCOS)
+#  define fdopen(fd,mode) NULL /* No fdopen() */
+#endif
+
+#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX
+#  if defined(_WIN32_WCE)
+#    define fdopen(fd,mode) NULL /* No fdopen() */
+#    ifndef _PTRDIFF_T_DEFINED
+       typedef int ptrdiff_t;
+#      define _PTRDIFF_T_DEFINED
+#    endif
+#  else
+#    define fdopen(fd,type)  _fdopen(fd,type)
+#  endif
+#endif
+
+#if defined(__BORLANDC__) && !defined(MSDOS)
+  #pragma warn -8004
+  #pragma warn -8008
+  #pragma warn -8066
+#endif
+
+/* provide prototypes for these when building zlib without LFS */
+#if !defined(_WIN32) && \
+    (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0)
+    ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
+    ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
+#endif
+
+        /* common defaults */
+
+#ifndef OS_CODE
+#  define OS_CODE  3     /* assume Unix */
+#endif
+
+#ifndef F_OPEN
+#  define F_OPEN(name, mode) fopen((name), (mode))
+#endif
+
+         /* functions */
+
+#if defined(pyr) || defined(Z_SOLO)
+#  define NO_MEMCPY
+#endif
+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
+ /* Use our own functions for small and medium model with MSC <= 5.0.
+  * You may have to use the same strategy for Borland C (untested).
+  * The __SC__ check is for Symantec.
+  */
+#  define NO_MEMCPY
+#endif
+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
+#  define HAVE_MEMCPY
+#endif
+#ifdef HAVE_MEMCPY
+#  ifdef SMALL_MEDIUM /* MSDOS small or medium model */
+#    define zmemcpy _fmemcpy
+#    define zmemcmp _fmemcmp
+#    define zmemzero(dest, len) _fmemset(dest, 0, len)
+#  else
+#    define zmemcpy memcpy
+#    define zmemcmp memcmp
+#    define zmemzero(dest, len) memset(dest, 0, len)
+#  endif
+#else
+   void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
+   int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
+   void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len));
+#endif
+
+/* Diagnostic functions */
+#ifdef ZLIB_DEBUG
+#  include <stdio.h>
+   extern int ZLIB_INTERNAL z_verbose;
+   extern void ZLIB_INTERNAL z_error OF((char *m));
+#  define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+#  define Trace(x) {if (z_verbose>=0) fprintf x ;}
+#  define Tracev(x) {if (z_verbose>0) fprintf x ;}
+#  define Tracevv(x) {if (z_verbose>1) fprintf x ;}
+#  define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
+#  define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
+#else
+#  define Assert(cond,msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c,x)
+#  define Tracecv(c,x)
+#endif
+
+#ifndef Z_SOLO
+   voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items,
+                                    unsigned size));
+   void ZLIB_INTERNAL zcfree  OF((voidpf opaque, voidpf ptr));
+#endif
+
+#define ZALLOC(strm, items, size) \
+           (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr)  (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+
+/* Reverse the bytes in a 32-bit value */
+#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
+                    (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
+
+#endif /* ZUTIL_H */
